Repository: smarr/RoarVM Branch: master Commit: 2f93789b6ecd Files: 1706 Total size: 39.0 MB Directory structure: gitextract_g7mokxl_/ ├── .gitignore ├── .gitmodules ├── INSTALL.rst ├── README ├── README.rst ├── image.st/ │ ├── RVM-multicore-support.mvc.st │ ├── RVM-multicore-support.pharo.st │ ├── RVM-multicore-support.squeak.st │ └── Sly3.mvc.st └── vm/ ├── RoarVM.xcodeproj/ │ └── project.pbxproj ├── run/ │ ├── reliability-test │ ├── tile-runner │ ├── tile-rvm │ └── tile-rvm-db ├── src/ │ ├── externals/ │ │ ├── externals.cpp │ │ └── externals.h │ ├── from_squeak/ │ │ ├── Cross/ │ │ │ ├── plugins/ │ │ │ │ ├── AsynchFilePlugin/ │ │ │ │ │ └── AsynchFilePlugin.h │ │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ │ ├── B3DAcceleratorPlugin.h │ │ │ │ │ ├── sqOpenGLRenderer.c │ │ │ │ │ └── sqOpenGLRenderer.h │ │ │ │ ├── BochsIA32Plugin/ │ │ │ │ │ ├── BochsIA32Plugin.h │ │ │ │ │ └── sqBochsIA32Plugin.cpp │ │ │ │ ├── CroquetPlugin/ │ │ │ │ │ ├── CroquetPlugin.h │ │ │ │ │ ├── CroquetPlugin.st │ │ │ │ │ ├── md5.h │ │ │ │ │ └── tribox.c │ │ │ │ ├── DropPlugin/ │ │ │ │ │ └── DropPlugin.h │ │ │ │ ├── ExampleSurfacePlugin/ │ │ │ │ │ ├── ExampleSurfacePlugin.h │ │ │ │ │ ├── SurfacePlugin-Examples.st │ │ │ │ │ └── sqMemorySurface.c │ │ │ │ ├── FileCopyPlugin/ │ │ │ │ │ └── FileCopyPlugin.h │ │ │ │ ├── FilePlugin/ │ │ │ │ │ ├── FilePlugin.c │ │ │ │ │ ├── FilePlugin.h │ │ │ │ │ └── sqFilePluginBasicPrims.c │ │ │ │ ├── FloatMathPlugin/ │ │ │ │ │ ├── FloatMathPlugin.h │ │ │ │ │ ├── FloatMathPlugin.st │ │ │ │ │ ├── FloatMathPluginTests.st │ │ │ │ │ ├── acos.c │ │ │ │ │ ├── acosh.c │ │ │ │ │ ├── asin.c │ │ │ │ │ ├── asinh.c │ │ │ │ │ ├── atan.c │ │ │ │ │ ├── atan2.c │ │ │ │ │ ├── atanh.c │ │ │ │ │ ├── copysign.c │ │ │ │ │ ├── cos.c │ │ │ │ │ ├── cosh.c │ │ │ │ │ ├── exp.c │ │ │ │ │ ├── expm1.c │ │ │ │ │ ├── fdlibm/ │ │ │ │ │ │ ├── MD5 │ │ │ │ │ │ ├── changes │ │ │ │ │ │ ├── configure │ │ │ │ │ │ ├── configure.in │ │ │ │ │ │ ├── e_acos.c │ │ │ │ │ │ ├── e_acosh.c │ │ │ │ │ │ ├── e_asin.c │ │ │ │ │ │ ├── e_atan2.c │ │ │ │ │ │ ├── e_atanh.c │ │ │ │ │ │ ├── e_cosh.c │ │ │ │ │ │ ├── e_exp.c │ │ │ │ │ │ ├── e_fmod.c │ │ │ │ │ │ ├── e_gamma.c │ │ │ │ │ │ ├── e_gamma_r.c │ │ │ │ │ │ ├── e_hypot.c │ │ │ │ │ │ ├── e_j0.c │ │ │ │ │ │ ├── e_j1.c │ │ │ │ │ │ ├── e_jn.c │ │ │ │ │ │ ├── e_lgamma.c │ │ │ │ │ │ ├── e_lgamma_r.c │ │ │ │ │ │ ├── e_log.c │ │ │ │ │ │ ├── e_log10.c │ │ │ │ │ │ ├── e_pow.c │ │ │ │ │ │ ├── e_rem_pio2.c │ │ │ │ │ │ ├── e_remainder.c │ │ │ │ │ │ ├── e_scalb.c │ │ │ │ │ │ ├── e_sinh.c │ │ │ │ │ │ ├── e_sqrt.c │ │ │ │ │ │ ├── fdlibm.h │ │ │ │ │ │ ├── index │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ ├── k_cos.c │ │ │ │ │ │ ├── k_rem_pio2.c │ │ │ │ │ │ ├── k_sin.c │ │ │ │ │ │ ├── k_standard.c │ │ │ │ │ │ ├── k_tan.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ ├── makefile.in │ │ │ │ │ │ ├── readme │ │ │ │ │ │ ├── s_asinh.c │ │ │ │ │ │ ├── s_atan.c │ │ │ │ │ │ ├── s_cbrt.c │ │ │ │ │ │ ├── s_ceil.c │ │ │ │ │ │ ├── s_copysign.c │ │ │ │ │ │ ├── s_cos.c │ │ │ │ │ │ ├── s_erf.c │ │ │ │ │ │ ├── s_expm1.c │ │ │ │ │ │ ├── s_fabs.c │ │ │ │ │ │ ├── s_finite.c │ │ │ │ │ │ ├── s_floor.c │ │ │ │ │ │ ├── s_frexp.c │ │ │ │ │ │ ├── s_ilogb.c │ │ │ │ │ │ ├── s_isnan.c │ │ │ │ │ │ ├── s_ldexp.c │ │ │ │ │ │ ├── s_lib_version.c │ │ │ │ │ │ ├── s_log1p.c │ │ │ │ │ │ ├── s_logb.c │ │ │ │ │ │ ├── s_matherr.c │ │ │ │ │ │ ├── s_modf.c │ │ │ │ │ │ ├── s_nextafter.c │ │ │ │ │ │ ├── s_rint.c │ │ │ │ │ │ ├── s_scalbn.c │ │ │ │ │ │ ├── s_signgam.c │ │ │ │ │ │ ├── s_significand.c │ │ │ │ │ │ ├── s_sin.c │ │ │ │ │ │ ├── s_tan.c │ │ │ │ │ │ ├── s_tanh.c │ │ │ │ │ │ ├── w_acos.c │ │ │ │ │ │ ├── w_acosh.c │ │ │ │ │ │ ├── w_asin.c │ │ │ │ │ │ ├── w_atan2.c │ │ │ │ │ │ ├── w_atanh.c │ │ │ │ │ │ ├── w_cosh.c │ │ │ │ │ │ ├── w_exp.c │ │ │ │ │ │ ├── w_fmod.c │ │ │ │ │ │ ├── w_gamma.c │ │ │ │ │ │ ├── w_gamma_r.c │ │ │ │ │ │ ├── w_hypot.c │ │ │ │ │ │ ├── w_j0.c │ │ │ │ │ │ ├── w_j1.c │ │ │ │ │ │ ├── w_jn.c │ │ │ │ │ │ ├── w_lgamma.c │ │ │ │ │ │ ├── w_lgamma_r.c │ │ │ │ │ │ ├── w_log.c │ │ │ │ │ │ ├── w_log10.c │ │ │ │ │ │ ├── w_pow.c │ │ │ │ │ │ ├── w_remainder.c │ │ │ │ │ │ ├── w_scalb.c │ │ │ │ │ │ ├── w_sinh.c │ │ │ │ │ │ └── w_sqrt.c │ │ │ │ │ ├── finite.c │ │ │ │ │ ├── fmod.c │ │ │ │ │ ├── hypot.c │ │ │ │ │ ├── ieee754names.h │ │ │ │ │ ├── isnan.c │ │ │ │ │ ├── k_cos.c │ │ │ │ │ ├── k_rem_pio2.c │ │ │ │ │ ├── k_sin.c │ │ │ │ │ ├── k_tan.c │ │ │ │ │ ├── ldexp.c │ │ │ │ │ ├── log.c │ │ │ │ │ ├── log10.c │ │ │ │ │ ├── log1p.c │ │ │ │ │ ├── modf.c │ │ │ │ │ ├── pow.c │ │ │ │ │ ├── rem_pio2.c │ │ │ │ │ ├── rint.c │ │ │ │ │ ├── scalb.c │ │ │ │ │ ├── scalbn.c │ │ │ │ │ ├── sin.c │ │ │ │ │ ├── sinh.c │ │ │ │ │ ├── sqrt.c │ │ │ │ │ ├── tan.c │ │ │ │ │ └── tanh.c │ │ │ │ ├── GStreamerPlugin/ │ │ │ │ │ ├── squeakAudioVideoPipeLineSignalInterface.c │ │ │ │ │ └── squeakAudioVideoPipeLineSignalInterface.h │ │ │ │ ├── HostWindowPlugin/ │ │ │ │ │ └── HostWindowPlugin.h │ │ │ │ ├── IA32ABI/ │ │ │ │ │ ├── dabusiness.h │ │ │ │ │ ├── ia32abi.h │ │ │ │ │ └── ia32abicc.c │ │ │ │ ├── InternetConfigPlugin/ │ │ │ │ │ └── InternetConfigPlugin.h │ │ │ │ ├── JPEGReadWriter2Plugin/ │ │ │ │ │ ├── Error.c │ │ │ │ │ ├── JPEGReadWriter2Plugin.h │ │ │ │ │ ├── ReadMe.txt │ │ │ │ │ ├── jcapimin.c │ │ │ │ │ ├── jcapistd.c │ │ │ │ │ ├── jccoefct.c │ │ │ │ │ ├── jccolor.c │ │ │ │ │ ├── jcdctmgr.c │ │ │ │ │ ├── jchuff.c │ │ │ │ │ ├── jchuff.h │ │ │ │ │ ├── jcinit.c │ │ │ │ │ ├── jcmainct.c │ │ │ │ │ ├── jcmarker.c │ │ │ │ │ ├── jcmaster.c │ │ │ │ │ ├── jcomapi.c │ │ │ │ │ ├── jconfig.h │ │ │ │ │ ├── jcparam.c │ │ │ │ │ ├── jcphuff.c │ │ │ │ │ ├── jcprepct.c │ │ │ │ │ ├── jcsample.c │ │ │ │ │ ├── jctrans.c │ │ │ │ │ ├── jdapimin.c │ │ │ │ │ ├── jdapistd.c │ │ │ │ │ ├── jdatadst.c │ │ │ │ │ ├── jdatasrc.c │ │ │ │ │ ├── jdcoefct.c │ │ │ │ │ ├── jdcolor.c │ │ │ │ │ ├── jdct.h │ │ │ │ │ ├── jddctmgr.c │ │ │ │ │ ├── jdhuff.c │ │ │ │ │ ├── jdhuff.h │ │ │ │ │ ├── jdinput.c │ │ │ │ │ ├── jdmainct.c │ │ │ │ │ ├── jdmarker.c │ │ │ │ │ ├── jdmaster.c │ │ │ │ │ ├── jdmerge.c │ │ │ │ │ ├── jdphuff.c │ │ │ │ │ ├── jdpostct.c │ │ │ │ │ ├── jdsample.c │ │ │ │ │ ├── jdtrans.c │ │ │ │ │ ├── jerror.c │ │ │ │ │ ├── jerror.h │ │ │ │ │ ├── jfdctflt.c │ │ │ │ │ ├── jfdctfst.c │ │ │ │ │ ├── jfdctint.c │ │ │ │ │ ├── jidctflt.c │ │ │ │ │ ├── jidctfst.c │ │ │ │ │ ├── jidctint.c │ │ │ │ │ ├── jidctred.c │ │ │ │ │ ├── jinclude.h │ │ │ │ │ ├── jmemdatadst.c │ │ │ │ │ ├── jmemdatasrc.c │ │ │ │ │ ├── jmemmgr.c │ │ │ │ │ ├── jmemnobs.c │ │ │ │ │ ├── jmemsys.h │ │ │ │ │ ├── jmorecfg.h │ │ │ │ │ ├── jpegint.h │ │ │ │ │ ├── jpeglib.h │ │ │ │ │ ├── jquant1.c │ │ │ │ │ ├── jquant2.c │ │ │ │ │ ├── jutils.c │ │ │ │ │ └── jversion.h │ │ │ │ ├── JoystickTabletPlugin/ │ │ │ │ │ └── JoystickTabletPlugin.h │ │ │ │ ├── LocalePlugin/ │ │ │ │ │ └── LocalePlugin.h │ │ │ │ ├── MIDIPlugin/ │ │ │ │ │ └── MIDIPlugin.h │ │ │ │ ├── Mpeg3Plugin/ │ │ │ │ │ ├── COPYING │ │ │ │ │ ├── JMMMpegBuffer.1.cs │ │ │ │ │ ├── JMMMpegBufferTest.1.cs │ │ │ │ │ ├── JMMMpegPluginBuffer.1.cs │ │ │ │ │ ├── JMMMpegPluginaddBufferOffsetting.1.cs │ │ │ │ │ ├── JMMMpegaddBufferOffsetting.1.cs │ │ │ │ │ ├── Mpeg3Plugin.h │ │ │ │ │ ├── README │ │ │ │ │ ├── docs/ │ │ │ │ │ │ └── index.html │ │ │ │ │ ├── examplesSqueak.txt │ │ │ │ │ └── libmpeg/ │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── audio/ │ │ │ │ │ │ ├── ac3.h │ │ │ │ │ │ ├── dct.c │ │ │ │ │ │ ├── header.c │ │ │ │ │ │ ├── huffman.h │ │ │ │ │ │ ├── layer1.c │ │ │ │ │ │ ├── layer2.c │ │ │ │ │ │ ├── layer3.c │ │ │ │ │ │ ├── mpeg3audio.c │ │ │ │ │ │ ├── mpeg3audio.h │ │ │ │ │ │ ├── pcm.c │ │ │ │ │ │ ├── synthesizers.c │ │ │ │ │ │ ├── tables.c │ │ │ │ │ │ └── tables.h │ │ │ │ │ ├── bitstream.c │ │ │ │ │ ├── bitstream.h │ │ │ │ │ ├── changesForSqueak.c │ │ │ │ │ ├── changesForSqueak.h │ │ │ │ │ ├── configure │ │ │ │ │ ├── dump.c │ │ │ │ │ ├── dump2.c │ │ │ │ │ ├── global_config │ │ │ │ │ ├── ioctl.h │ │ │ │ │ ├── libmpeg3.c │ │ │ │ │ ├── libmpeg3.h │ │ │ │ │ ├── make_package │ │ │ │ │ ├── mpeg3atrack.c │ │ │ │ │ ├── mpeg3atrack.h │ │ │ │ │ ├── mpeg3cat.c │ │ │ │ │ ├── mpeg3css.h │ │ │ │ │ ├── mpeg3demux.c │ │ │ │ │ ├── mpeg3demux.h │ │ │ │ │ ├── mpeg3io.c │ │ │ │ │ ├── mpeg3io.h │ │ │ │ │ ├── mpeg3private.h │ │ │ │ │ ├── mpeg3private.inc │ │ │ │ │ ├── mpeg3protos.h │ │ │ │ │ ├── mpeg3title.c │ │ │ │ │ ├── mpeg3title.h │ │ │ │ │ ├── mpeg3toc.c │ │ │ │ │ ├── mpeg3vtrack.c │ │ │ │ │ ├── mpeg3vtrack.h │ │ │ │ │ ├── test.c │ │ │ │ │ ├── testaudio.c │ │ │ │ │ ├── timecode.h │ │ │ │ │ ├── udump.c │ │ │ │ │ └── video/ │ │ │ │ │ ├── getpicture.c │ │ │ │ │ ├── headers.c │ │ │ │ │ ├── idct.c │ │ │ │ │ ├── idct.h │ │ │ │ │ ├── layerdata.h │ │ │ │ │ ├── macroblocks.c │ │ │ │ │ ├── mmxidct.S │ │ │ │ │ ├── mmxidct_gasp.s │ │ │ │ │ ├── mmxidct_orig.S │ │ │ │ │ ├── mmxtest.c │ │ │ │ │ ├── motion.c │ │ │ │ │ ├── mpeg3video.c │ │ │ │ │ ├── mpeg3video.h │ │ │ │ │ ├── mpeg3videoprotos.h │ │ │ │ │ ├── output.c │ │ │ │ │ ├── reconmmx.s │ │ │ │ │ ├── reconstruct.c │ │ │ │ │ ├── seek.c │ │ │ │ │ ├── slice.c │ │ │ │ │ ├── slice.h │ │ │ │ │ ├── vlc.c │ │ │ │ │ ├── vlc.h │ │ │ │ │ └── worksheet.c │ │ │ │ ├── PrintJobPlugin/ │ │ │ │ │ └── PrintJobPlugin.h │ │ │ │ ├── PseudoTTYPlugin/ │ │ │ │ │ └── PseudoTTYPlugin.h │ │ │ │ ├── QuicktimePlugin/ │ │ │ │ │ └── QuicktimePlugin.h │ │ │ │ ├── RePlugin/ │ │ │ │ │ ├── RePlugin3-Fixes.1.cs │ │ │ │ │ ├── RePlugin3-Fixes2.1.cs │ │ │ │ │ ├── RePlugin3.3.1.cs │ │ │ │ │ ├── chartables.c │ │ │ │ │ ├── config.h │ │ │ │ │ ├── get.c │ │ │ │ │ ├── internal.h │ │ │ │ │ ├── oldInternal.h │ │ │ │ │ ├── pcre.c │ │ │ │ │ ├── pcre.h │ │ │ │ │ ├── rePlugin.h │ │ │ │ │ └── study.c │ │ │ │ ├── SecurityPlugin/ │ │ │ │ │ └── SecurityPlugin.h │ │ │ │ ├── SerialPlugin/ │ │ │ │ │ └── SerialPlugin.h │ │ │ │ ├── SocketPlugin/ │ │ │ │ │ └── SocketPlugin.h │ │ │ │ ├── SoundCodecPrims/ │ │ │ │ │ ├── SoundCodecPrims.h │ │ │ │ │ └── sqSoundCodecPluginBasicPrims.c │ │ │ │ ├── SoundGenerationPlugin/ │ │ │ │ │ ├── SoundGenerationPlugin.h │ │ │ │ │ └── sqOldSoundPrims.c │ │ │ │ ├── SoundPlugin/ │ │ │ │ │ └── SoundPlugin.h │ │ │ │ ├── Squeak3D/ │ │ │ │ │ ├── b3d.h │ │ │ │ │ ├── b3dAlloc.c │ │ │ │ │ ├── b3dAlloc.h │ │ │ │ │ ├── b3dDraw.c │ │ │ │ │ ├── b3dInit.c │ │ │ │ │ ├── b3dMain.c │ │ │ │ │ ├── b3dRemap.c │ │ │ │ │ └── b3dTypes.h │ │ │ │ ├── SqueakFFIPrims/ │ │ │ │ │ ├── sqFFI.h │ │ │ │ │ ├── sqFFIPlugin.c │ │ │ │ │ ├── sqFFITestFuncs.c │ │ │ │ │ └── sqManualSurface.c │ │ │ │ ├── SqueakSSL/ │ │ │ │ │ └── SqueakSSL.h │ │ │ │ ├── SurfacePlugin/ │ │ │ │ │ ├── SurfacePlugin.c │ │ │ │ │ └── SurfacePlugin.h │ │ │ │ └── UUIDPlugin/ │ │ │ │ └── UUIDPlugin.h │ │ │ └── vm/ │ │ │ ├── dispdbg.h │ │ │ ├── sq.h │ │ │ ├── sqAssert.h │ │ │ ├── sqAtomicOps.h │ │ │ ├── sqCogStackAlignment.h │ │ │ ├── sqExternalSemaphores.c │ │ │ ├── sqHeapMap.c │ │ │ ├── sqMemoryAccess.h │ │ │ ├── sqMemoryFence.h │ │ │ ├── sqNamedPrims.c │ │ │ ├── sqTicker.c │ │ │ ├── sqVirtualMachine.c │ │ │ └── sqVirtualMachine.h │ │ ├── LICENSE │ │ ├── Mac OS/ │ │ │ ├── plugins/ │ │ │ │ ├── AsynchFilePlugin/ │ │ │ │ │ └── sqMacAsyncFilePrims.c │ │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ │ ├── sqMacOpenGL.c │ │ │ │ │ ├── sqMacOpenGL.h │ │ │ │ │ └── sqMacOpenGLInfo.c │ │ │ │ ├── ClipboardExtended/ │ │ │ │ │ ├── ClipboardExtendedPlugin.c │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── JMMExtendedClipBoardPlugin.1.cs │ │ │ │ │ ├── Sophie-Clipboard.st │ │ │ │ │ ├── SophieSUnitClipboard.st │ │ │ │ │ ├── sqMacExtendedClipboard.c │ │ │ │ │ └── sqMacExtendedClipboard.h │ │ │ │ ├── CroquetPlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── sqMacCroquet.c │ │ │ │ │ └── sqMacCroquet.h │ │ │ │ ├── CurlPlugin/ │ │ │ │ │ └── Info-CURLPlugin.plist │ │ │ │ ├── DropPlugin/ │ │ │ │ │ └── sqMacDragDrop.c │ │ │ │ ├── ExuperyPlugin/ │ │ │ │ │ └── sqOSXExuperyPlugin.c │ │ │ │ ├── FileCopyPlugin/ │ │ │ │ │ ├── FileCopy.xml │ │ │ │ │ ├── MoreFiles 1.5/ │ │ │ │ │ │ ├── C Headers/ │ │ │ │ │ │ │ ├── DirectoryCopy.h │ │ │ │ │ │ │ ├── FSpCompat.h │ │ │ │ │ │ │ ├── FileCopy.h │ │ │ │ │ │ │ ├── FullPath.h │ │ │ │ │ │ │ ├── IterateDirectory.h │ │ │ │ │ │ │ ├── MoreDesktopMgr.h │ │ │ │ │ │ │ ├── MoreFiles.h │ │ │ │ │ │ │ ├── MoreFilesExtras.h │ │ │ │ │ │ │ ├── Optimization.h │ │ │ │ │ │ │ ├── OptimizationEnd.h │ │ │ │ │ │ │ └── Search.h │ │ │ │ │ │ ├── MoreFilesReadMe │ │ │ │ │ │ ├── PascalInterfaces/ │ │ │ │ │ │ │ ├── DirectoryCopy.p │ │ │ │ │ │ │ ├── FSpCompat.p │ │ │ │ │ │ │ ├── FileCopy.p │ │ │ │ │ │ │ ├── FullPath.p │ │ │ │ │ │ │ ├── IterateDirectory.p │ │ │ │ │ │ │ ├── MoreDesktopMgr.p │ │ │ │ │ │ │ ├── MoreFiles.p │ │ │ │ │ │ │ ├── MoreFilesExtras.p │ │ │ │ │ │ │ └── Search.p │ │ │ │ │ │ └── Sources/ │ │ │ │ │ │ ├── DirectoryCopy.c │ │ │ │ │ │ ├── FSpCompat.c │ │ │ │ │ │ ├── FileCopy.c │ │ │ │ │ │ ├── FullPath.c │ │ │ │ │ │ ├── IterateDirectory.c │ │ │ │ │ │ ├── MoreDesktopMgr.c │ │ │ │ │ │ ├── MoreFiles.c │ │ │ │ │ │ ├── MoreFilesExtras.c │ │ │ │ │ │ └── Search.c │ │ │ │ │ ├── sqMacFileCopy.c │ │ │ │ │ └── sqMacFileCopy.h │ │ │ │ ├── FilePlugin/ │ │ │ │ │ ├── sqMacDirectory.c │ │ │ │ │ ├── sqMacUnixFileInterface.c │ │ │ │ │ └── sqMacUnixFileInterface.h │ │ │ │ ├── FloatMathPlugin/ │ │ │ │ │ └── Info.plist │ │ │ │ ├── HostWindowPlugin/ │ │ │ │ │ ├── sqMacHostWindow.c │ │ │ │ │ └── sqMacHostWindow.h │ │ │ │ ├── IA32ABI/ │ │ │ │ │ └── Info.plist │ │ │ │ ├── InternetConfigPlugin/ │ │ │ │ │ ├── InternetConfiguration.xml │ │ │ │ │ └── sqMacInternetConfiguration.c │ │ │ │ ├── JPEGReadWriter2Plugin/ │ │ │ │ │ └── JConfig.h │ │ │ │ ├── JoystickTabletPlugin/ │ │ │ │ │ ├── HID_Error_Handler.c │ │ │ │ │ ├── HID_Error_Handler.h │ │ │ │ │ ├── HID_Name_Lookup.c │ │ │ │ │ ├── HID_Name_Lookup.h │ │ │ │ │ ├── HID_Queue_Utilities.c │ │ │ │ │ ├── HID_Queue_Utilities.h │ │ │ │ │ ├── HID_Utilities.c │ │ │ │ │ ├── HID_Utilities.h │ │ │ │ │ ├── HID_Utilities_External.h │ │ │ │ │ ├── HID_Utilities_Internal.h │ │ │ │ │ ├── libHIDUtilities.a │ │ │ │ │ └── sqMacJoystickAndTablet.c │ │ │ │ ├── KedamaPlugin/ │ │ │ │ │ ├── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── Info-KedamaPlugin__Upgraded_.plist │ │ │ │ │ └── KedamaPlugin.st │ │ │ │ ├── KedamaPlugin2/ │ │ │ │ │ ├── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── Info-KedamaPlugin__Upgraded_.plist │ │ │ │ │ └── KedamaPlugin2.st │ │ │ │ ├── LocalePlugin/ │ │ │ │ │ ├── Info-SqueakLocalePlugin__Upgraded_.plist │ │ │ │ │ ├── LocalePlugin.proj.xml │ │ │ │ │ ├── SqueakLocale.pbproj/ │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── resources/ │ │ │ │ │ │ └── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── sqMacLocaleCarbon.c │ │ │ │ │ ├── sqMacLocaleCarbon.h │ │ │ │ │ ├── sqMacLocaleOS9.c │ │ │ │ │ └── sqMacLocaleOS9.h │ │ │ │ ├── MIDIPlugin/ │ │ │ │ │ └── sqMacMIDI.c │ │ │ │ ├── MacMenubarPlugin/ │ │ │ │ │ └── MacMenubarPlugin.h │ │ │ │ ├── Mpeg3Plugin/ │ │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ │ ├── changesetsForInMemoryBuffer/ │ │ │ │ │ │ ├── JMMMpegBuffer.1.cs │ │ │ │ │ │ ├── JMMMpegBufferTest.1.cs │ │ │ │ │ │ └── JMMMpegPluginBuffer.1.cs │ │ │ │ │ ├── mpeg3Plugin-Info.plist │ │ │ │ │ ├── mpeglibAudioVideo.xml │ │ │ │ │ ├── myMacHeadersCarbon.pch │ │ │ │ │ ├── resources/ │ │ │ │ │ │ ├── App.rsrc │ │ │ │ │ │ └── CarbonApp.rsrc │ │ │ │ │ ├── resources.sit │ │ │ │ │ ├── sqMacFileBits.c │ │ │ │ │ └── sqMacFileBits.h │ │ │ │ ├── OpenALPlugin/ │ │ │ │ │ └── Info.plist │ │ │ │ ├── PrintJobPlugin/ │ │ │ │ │ ├── Info-PrintJobPlugin__Upgraded_.plist │ │ │ │ │ ├── PrintJobPlugin.pbproj.sit │ │ │ │ │ ├── PrintJobPlugin.project.xml │ │ │ │ │ ├── RealPrinting-JMM.7.cs │ │ │ │ │ ├── resources.sit │ │ │ │ │ ├── sqMacPrinting.c │ │ │ │ │ └── sqMacPrinting.h │ │ │ │ ├── QuicktimePlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── JMMMacQuicktimePlugin.3.cs │ │ │ │ │ ├── PkgInfo │ │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ │ ├── SqueakQuicktime.xcodeproj/ │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── resources/ │ │ │ │ │ │ └── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── sqMacQuicktimeInteface.c │ │ │ │ │ └── sqMacQuicktimeInteface.h │ │ │ │ ├── SecurityPlugin/ │ │ │ │ │ └── sqMacSecurity.c │ │ │ │ ├── SerialExtendedPlugin/ │ │ │ │ │ ├── Info-SerialExtendedUnixPlugin__Upgraded_.plist │ │ │ │ │ ├── SerialExtendedMacOS9.xml.sit │ │ │ │ │ ├── SerialExtendedPlugin.pbproj.sit │ │ │ │ │ ├── serialExtendedUnixPlugin.h │ │ │ │ │ └── sqMacSerialExtended.c │ │ │ │ ├── SerialPlugin/ │ │ │ │ │ └── sqMacSerialPort.c │ │ │ │ ├── ServicesPlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── JMMMacServices.5.cs │ │ │ │ │ ├── JMMServicesPlugin.2.cs │ │ │ │ │ ├── MacServicesReadMe.rtf │ │ │ │ │ ├── SqueakServices.pbproj/ │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── resources/ │ │ │ │ │ │ └── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── sqMacServices.c │ │ │ │ │ └── sqMacServices.h │ │ │ │ ├── SocketPlugin/ │ │ │ │ │ ├── 68K/ │ │ │ │ │ │ ├── AddressXlation.h │ │ │ │ │ │ ├── MacTCP.h │ │ │ │ │ │ ├── dnr.c │ │ │ │ │ │ └── sqMacNetworkNOMACTCP.c │ │ │ │ │ └── sqMacNetwork.c │ │ │ │ ├── SoundPlugin/ │ │ │ │ │ ├── sqMacSound.c │ │ │ │ │ ├── sqMacUnixInterfaceSound.c │ │ │ │ │ ├── sqMacUnixInterfaceSound.h │ │ │ │ │ ├── sqUnixSoundDebug.h │ │ │ │ │ └── sqUnixSoundMacOSXJMM.c │ │ │ │ ├── SparklePlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── interp.h │ │ │ │ │ ├── sqMacMainObjCSparkle.h │ │ │ │ │ └── sqMacMainObjCSparkle.m │ │ │ │ ├── SpellingPlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── JMMMacSpelling.3.cs │ │ │ │ │ ├── JMMMacSpelling.4.cs │ │ │ │ │ ├── JMMMacSpellingPlugin.1.cs │ │ │ │ │ ├── SpellCheck/ │ │ │ │ │ │ ├── English.lproj/ │ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ │ ├── Info-SpellCheck__Upgraded_.plist │ │ │ │ │ │ ├── SpellCheck.m │ │ │ │ │ │ └── SpellCheck.pbproj/ │ │ │ │ │ │ ├── apple.pbxuser │ │ │ │ │ │ ├── deric.pbxuser │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── SqueakSpelling.pbproj/ │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── build/ │ │ │ │ │ │ ├── .gdb_history │ │ │ │ │ │ └── PkgInfo │ │ │ │ │ ├── resources/ │ │ │ │ │ │ └── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── sqMacSpellingPlugin.c │ │ │ │ │ └── sqMacSpellingPlugin.h │ │ │ │ ├── SqueakFFIPrims/ │ │ │ │ │ ├── Info-SqueakFFIPlugin__Upgraded_.plist │ │ │ │ │ ├── SqueakFFIPrims.proj.xml │ │ │ │ │ ├── ppc-darwin-Carbon-UI.c │ │ │ │ │ ├── ppc-darwin-asm-MacIntel.S │ │ │ │ │ ├── ppc-global.h │ │ │ │ │ ├── resources/ │ │ │ │ │ │ └── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── sqMacFFI.s │ │ │ │ │ ├── sqMacFFIPPC.c │ │ │ │ │ ├── sqMacIntel-Win32.c │ │ │ │ │ ├── x86-sysv-MacIntel.c │ │ │ │ │ └── x86-sysv-asm-MacIntel.S │ │ │ │ ├── SqueakObjectiveCPlugin/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── squeakProxy.h │ │ │ │ │ ├── squeakProxy.m │ │ │ │ │ ├── squeakSUnitTester.h │ │ │ │ │ └── squeakSUnitTester.m │ │ │ │ ├── TestOSAPlugin/ │ │ │ │ │ ├── Info-TestOSAPlugin__Upgraded_.plist │ │ │ │ │ ├── JMMFixOSAPluginForOSX.1.cs │ │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ │ └── TestOSAPlugin.proj.xml │ │ │ │ ├── UUIDPlugin/ │ │ │ │ │ └── sqMacUUID.c │ │ │ │ └── UnixOSProcessPlugin/ │ │ │ │ ├── Info.plist │ │ │ │ ├── PkgInfo │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ └── UnixOSProcessPlugin.c │ │ │ └── vm/ │ │ │ ├── Developer/ │ │ │ │ ├── Info-NPSophie__Upgraded_.plist │ │ │ │ ├── Info-NPSqueak__Upgraded_.plist │ │ │ │ ├── Info-Squeak_VM_Debug__Upgraded_.plist │ │ │ │ ├── Info-Squeak_VM_OPT__Upgraded_.plist │ │ │ │ ├── MacVMCorrectFileTypes.st │ │ │ │ ├── MyPlugin v2.proj.xml │ │ │ │ ├── MyPlugin68K v2.proj.xml │ │ │ │ ├── NPSqueakStub.c │ │ │ │ ├── NPSqueakStub.sit │ │ │ │ ├── Squeak VM Universal-Info.plist │ │ │ │ ├── SqueakPro5.xml │ │ │ │ ├── SqueakQL/ │ │ │ │ │ ├── English.lproj/ │ │ │ │ │ │ └── InfoPlist.strings │ │ │ │ │ ├── GeneratePreviewForURL.c │ │ │ │ │ ├── GenerateThumbnailForURL.c │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── SqueakQL.xcodeproj/ │ │ │ │ │ │ ├── bert.mode1v3 │ │ │ │ │ │ ├── bert.pbxuser │ │ │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ └── main.c │ │ │ │ ├── interp.h │ │ │ │ ├── myMacHeaders.c │ │ │ │ ├── myMacHeaders.pch │ │ │ │ ├── myMacHeadersCarbon.pch │ │ │ │ ├── resources.sit │ │ │ │ ├── sqGnu.h │ │ │ │ └── sqMacMinimal.c │ │ │ ├── Documentation/ │ │ │ │ ├── 3.2.2 Release Notes.rtf │ │ │ │ ├── 3.2.3 Release Notes.rtf │ │ │ │ ├── 3.2.4 Release Notes.rtf │ │ │ │ ├── 3.2.5 Release Notes.rtf │ │ │ │ ├── 3.2.6 Release Notes.rtf │ │ │ │ ├── 3.2.7 Release Notes.rtf │ │ │ │ ├── 3.2.8 Release Notes.rtf │ │ │ │ ├── 3.4.0 Release Notes.rtf │ │ │ │ ├── 3.5.0 Release Notes.rtf │ │ │ │ ├── 3.5.1 Release Notes.rtf │ │ │ │ ├── 3.5.2 Release Notes.rtf │ │ │ │ ├── 3.6.0 Release Notes.rtf │ │ │ │ ├── 3.6.1 Release Notes.rtf │ │ │ │ ├── 3.7.1 Release Notes.rtf │ │ │ │ ├── 3.7.2 Release Notes.rtf │ │ │ │ ├── 3.7.3 Release Notes.rtf │ │ │ │ ├── 3.7.4 Release Notes.rtf │ │ │ │ ├── 3.7.5 Release Notes.rtf │ │ │ │ ├── 3.8.x Release Notes.rtf │ │ │ │ ├── 4.x.x Release Notes.rtf │ │ │ │ ├── 5.x.x Release Notes.rtf │ │ │ │ ├── readme │ │ │ │ └── readme.txt │ │ │ ├── Info-NPSqueak__Upgraded_.plist │ │ │ ├── NSCursorWrappers.h │ │ │ ├── NSCursorWrappers.m │ │ │ ├── PluginSDK 4.01a/ │ │ │ │ ├── Common/ │ │ │ │ │ ├── npmac.cpp │ │ │ │ │ └── npwin.cpp │ │ │ │ └── Include/ │ │ │ │ ├── jni.h │ │ │ │ ├── jni_md.h │ │ │ │ ├── jri.h │ │ │ │ ├── jri_md.h │ │ │ │ ├── jritypes.h │ │ │ │ ├── npapi.h │ │ │ │ └── npupp.h │ │ │ ├── config.h │ │ │ ├── malloc.h │ │ │ ├── npsqueak/ │ │ │ │ ├── English.lproj/ │ │ │ │ │ ├── InfoPlist.strings │ │ │ │ │ └── Localized.r │ │ │ │ ├── SqueakBrowser-Info.plist │ │ │ │ ├── SqueakBrowser.rsrc │ │ │ │ ├── SqueakBrowser_Prefix.pch │ │ │ │ ├── main.c │ │ │ │ ├── npsqueak.c │ │ │ │ └── npunix.c │ │ │ ├── nsPoolManagement.h │ │ │ ├── nsPoolManagement.m │ │ │ ├── osExports.c │ │ │ ├── specialChangeSets/ │ │ │ │ ├── ArraysToGlobalStruct-JMM.1.cs │ │ │ │ ├── Gnuifier.6.cs │ │ │ │ ├── Gnuifier.st │ │ │ │ ├── Old/ │ │ │ │ │ ├── ArraysToGlobalStruct-JMM.1.cs │ │ │ │ │ ├── FasterCopyLoop-JMM.4.cs │ │ │ │ │ ├── FasterCopyLoopPart2-JMM.2.cs │ │ │ │ │ ├── FasterLookupMethod-JMM.1.cs │ │ │ │ │ ├── Interpreter-readImageFromFile-jmm-dtl.2.cs │ │ │ │ │ ├── JMM-fixBiasToGrow.1.cs │ │ │ │ │ ├── MakePrimPointXInternal-JMM.1.cs │ │ │ │ │ ├── SlightlyFasterActivate-JMM.3.cs │ │ │ │ │ ├── VMM38-64bit-imageUpdates.1.cs │ │ │ │ │ ├── VMM38-gc-instrument-image.1.cs │ │ │ │ │ ├── VmUpdates-dtl/ │ │ │ │ │ │ ├── JMM-VmUpdates32bitclean.2.cs │ │ │ │ │ │ ├── VMMaker-wbk.40.8.cs │ │ │ │ │ │ ├── VmUpdates-1001-dtl.1.cs │ │ │ │ │ │ ├── VmUpdates-1002-dtl.1.cs │ │ │ │ │ │ ├── VmUpdates-1003-dtl.1.cs │ │ │ │ │ │ ├── VmUpdates-1004-dtl.1.cs │ │ │ │ │ │ ├── VmUpdates-1005-dtl.1.cs │ │ │ │ │ │ └── VmUpdates-1006-dtl.1.cs │ │ │ │ │ └── bigCursor-bf.1.cs │ │ │ │ ├── VMM38-64bit-imageUpdates.1.cs │ │ │ │ └── VMM38-gc-instrument-image.1.cs │ │ │ ├── sqConfig.h │ │ │ ├── sqMacEncoding.c │ │ │ ├── sqMacEncoding.h │ │ │ ├── sqMacExternalPrims.c │ │ │ ├── sqMacExternalPrims.h │ │ │ ├── sqMacFileLogic.c │ │ │ ├── sqMacFileLogic.h │ │ │ ├── sqMacImageIO.c │ │ │ ├── sqMacImageIO.h │ │ │ ├── sqMacMain.c │ │ │ ├── sqMacMain.h │ │ │ ├── sqMacMemory.c │ │ │ ├── sqMacMemory.h │ │ │ ├── sqMacNSPlugin.c │ │ │ ├── sqMacNSPluginUILogic.c │ │ │ ├── sqMacNSPluginUILogic2.c │ │ │ ├── sqMacNSPluginUILogic2.h │ │ │ ├── sqMacTime.c │ │ │ ├── sqMacTime.h │ │ │ ├── sqMacUIAppleEvents.c │ │ │ ├── sqMacUIAppleEvents.h │ │ │ ├── sqMacUIClipBoard.c │ │ │ ├── sqMacUIClipBoard.h │ │ │ ├── sqMacUIConstants.h │ │ │ ├── sqMacUIEvents.c │ │ │ ├── sqMacUIEvents.h │ │ │ ├── sqMacUIEventsUniversal.c │ │ │ ├── sqMacUIMenuBar.c │ │ │ ├── sqMacUIMenuBar.h │ │ │ ├── sqMacUIMenuBarUniversal.c │ │ │ ├── sqMacUnixCommandLineInterface.c │ │ │ ├── sqMacUnixCommandLineInterface.h │ │ │ ├── sqMacUnixExternalPrims.c │ │ │ ├── sqMacWindow.c │ │ │ ├── sqMacWindow.h │ │ │ ├── sqMacWindowUniversal.c │ │ │ ├── sqNamedPrims.h │ │ │ ├── sqPlatformSpecific.h │ │ │ └── version.c │ │ ├── README.rst │ │ ├── iOS/ │ │ │ ├── plugins/ │ │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ │ ├── sqMacOpenGL.c │ │ │ │ │ ├── sqMacOpenGL.h │ │ │ │ │ ├── sqMacOpenGLInfo.c │ │ │ │ │ └── sqMacUIConstants.h │ │ │ │ ├── ClipboardExtended/ │ │ │ │ │ ├── sqMacExtendedClipboard.h │ │ │ │ │ └── sqMacExtendedClipboard.m │ │ │ │ ├── CroquetPlugin/ │ │ │ │ │ ├── sqMacCroquet.c │ │ │ │ │ └── sqMacCroquet.h │ │ │ │ ├── FT2Plugin/ │ │ │ │ │ ├── FT2Plugin.xcodeproj/ │ │ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ │ │ ├── MAC.pbxuser │ │ │ │ │ │ ├── bert.mode1 │ │ │ │ │ │ ├── bert.pbxuser │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── Info-FT2Plugin.plist │ │ │ │ │ ├── PkgInfo │ │ │ │ │ ├── freetype2/ │ │ │ │ │ │ └── freetype/ │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ ├── ftconfig.h │ │ │ │ │ │ │ ├── ftheader.h │ │ │ │ │ │ │ ├── ftmodule.h │ │ │ │ │ │ │ ├── ftoption.h │ │ │ │ │ │ │ └── ftstdlib.h │ │ │ │ │ │ ├── freetype.h │ │ │ │ │ │ ├── ftadvanc.h │ │ │ │ │ │ ├── ftbbox.h │ │ │ │ │ │ ├── ftbdf.h │ │ │ │ │ │ ├── ftbitmap.h │ │ │ │ │ │ ├── ftcache.h │ │ │ │ │ │ ├── ftchapters.h │ │ │ │ │ │ ├── ftcid.h │ │ │ │ │ │ ├── fterrdef.h │ │ │ │ │ │ ├── fterrors.h │ │ │ │ │ │ ├── ftgasp.h │ │ │ │ │ │ ├── ftglyph.h │ │ │ │ │ │ ├── ftgxval.h │ │ │ │ │ │ ├── ftgzip.h │ │ │ │ │ │ ├── ftimage.h │ │ │ │ │ │ ├── ftincrem.h │ │ │ │ │ │ ├── ftlcdfil.h │ │ │ │ │ │ ├── ftlist.h │ │ │ │ │ │ ├── ftlzw.h │ │ │ │ │ │ ├── ftmac.h │ │ │ │ │ │ ├── ftmm.h │ │ │ │ │ │ ├── ftmodapi.h │ │ │ │ │ │ ├── ftmoderr.h │ │ │ │ │ │ ├── ftotval.h │ │ │ │ │ │ ├── ftoutln.h │ │ │ │ │ │ ├── ftpfr.h │ │ │ │ │ │ ├── ftrender.h │ │ │ │ │ │ ├── ftsizes.h │ │ │ │ │ │ ├── ftsnames.h │ │ │ │ │ │ ├── ftstroke.h │ │ │ │ │ │ ├── ftsynth.h │ │ │ │ │ │ ├── ftsystem.h │ │ │ │ │ │ ├── fttrigon.h │ │ │ │ │ │ ├── fttypes.h │ │ │ │ │ │ ├── ftwinfnt.h │ │ │ │ │ │ ├── ftxf86.h │ │ │ │ │ │ ├── t1tables.h │ │ │ │ │ │ ├── ttnameid.h │ │ │ │ │ │ ├── tttables.h │ │ │ │ │ │ ├── tttags.h │ │ │ │ │ │ └── ttunpat.h │ │ │ │ │ └── macFileNameBits.c │ │ │ │ ├── JoystickTabletPlugin/ │ │ │ │ │ ├── HID_Error_Handler.c │ │ │ │ │ ├── HID_Error_Handler.h │ │ │ │ │ ├── HID_Name_Lookup.c │ │ │ │ │ ├── HID_Name_Lookup.h │ │ │ │ │ ├── HID_Queue_Utilities.c │ │ │ │ │ ├── HID_Queue_Utilities.h │ │ │ │ │ ├── HID_Utilities.c │ │ │ │ │ ├── HID_Utilities.h │ │ │ │ │ ├── HID_Utilities_External.h │ │ │ │ │ ├── HID_Utilities_Internal.h │ │ │ │ │ └── sqMacJoystickAndTablet.c │ │ │ │ ├── LocalePlugin/ │ │ │ │ │ ├── sqMacLocaleCarbon.c │ │ │ │ │ └── sqMacLocaleCarbon.h │ │ │ │ ├── MIDIPlugin/ │ │ │ │ │ └── sqMacMIDI.c │ │ │ │ ├── MacMenubarPlugin/ │ │ │ │ │ ├── MacMenuOS9ToOSX.h │ │ │ │ │ ├── MacMenuOS9ToOSX.m │ │ │ │ │ └── MacMenubarPlugin.h │ │ │ │ ├── Mpeg3Plugin/ │ │ │ │ │ ├── changesetsForInMemoryBuffer/ │ │ │ │ │ │ ├── JMMMpegBuffer.1.cs │ │ │ │ │ │ ├── JMMMpegBufferTest.1.cs │ │ │ │ │ │ └── JMMMpegPluginBuffer.1.cs │ │ │ │ │ ├── sqMacFileBits.c │ │ │ │ │ └── sqMacFileBits.h │ │ │ │ ├── SecurityPlugin/ │ │ │ │ │ └── sqMacSecurity.c │ │ │ │ ├── SerialPlugin/ │ │ │ │ │ └── sqMacSerialPort.c │ │ │ │ ├── SoundPlugin/ │ │ │ │ │ ├── sqSqueakSoundCoreAudio.h │ │ │ │ │ ├── sqSqueakSoundCoreAudio.m │ │ │ │ │ ├── sqSqueakSoundCoreAudioAPI.h │ │ │ │ │ └── sqSqueakSoundCoreAudioAPI.m │ │ │ │ ├── SqueakFFIPrims/ │ │ │ │ │ ├── dummyFFI.c │ │ │ │ │ └── dummyFFI.h │ │ │ │ ├── SqueakLocale/ │ │ │ │ │ ├── Info-SqueakLocalePlugin__Upgraded_.plist │ │ │ │ │ ├── SqueakLocale.xcodeproj/ │ │ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ │ │ ├── MAC.pbxuser │ │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── sqMacLocaleCocoa.h │ │ │ │ │ └── sqMacLocaleCocoa.m │ │ │ │ ├── SqueakObjectiveC/ │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── PDColoredProgressView.h │ │ │ │ │ ├── PDColoredProgressView.m │ │ │ │ │ ├── drawing.m │ │ │ │ │ ├── squeakProxy.h │ │ │ │ │ ├── squeakProxy.m │ │ │ │ │ ├── squeakSUnitTester.h │ │ │ │ │ └── squeakSUnitTester.m │ │ │ │ └── UnixOSProcessPlugin/ │ │ │ │ ├── Info.plist │ │ │ │ ├── PkgInfo │ │ │ │ ├── UnixOSProcessPlugin.xcodeproj/ │ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ │ ├── MAC.pbxuser │ │ │ │ │ ├── bert.mode1 │ │ │ │ │ ├── bert.pbxuser │ │ │ │ │ ├── johnmci.mode1 │ │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ │ ├── johnmci.pbxuser │ │ │ │ │ └── project.pbxproj │ │ │ │ └── UnixOSProcessPluginOLD.xcodeproj/ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ ├── MAC.pbxuser │ │ │ │ ├── johnmci.mode1 │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ ├── johnmci.pbxuser │ │ │ │ └── project.pbxproj │ │ │ └── vm/ │ │ │ ├── 5.x.x Release Notes.rtf │ │ │ ├── Common/ │ │ │ │ ├── Classes/ │ │ │ │ │ ├── Queue.h │ │ │ │ │ ├── Queue.m │ │ │ │ │ ├── sqMacV2Time.c │ │ │ │ │ ├── sqMacV2Time.h │ │ │ │ │ ├── sqSqueakAppDelegate.h │ │ │ │ │ ├── sqSqueakAppDelegate.m │ │ │ │ │ ├── sqSqueakAttributesAPI.h │ │ │ │ │ ├── sqSqueakAttributesAPI.m │ │ │ │ │ ├── sqSqueakCursorAPI.h │ │ │ │ │ ├── sqSqueakCursorAPI.m │ │ │ │ │ ├── sqSqueakEventsAPI.h │ │ │ │ │ ├── sqSqueakEventsAPI.m │ │ │ │ │ ├── sqSqueakFileDirectoryAPI.h │ │ │ │ │ ├── sqSqueakFileDirectoryAPI.m │ │ │ │ │ ├── sqSqueakFileDirectoryInterface.h │ │ │ │ │ ├── sqSqueakFileDirectoryInterface.m │ │ │ │ │ ├── sqSqueakInfoPlistInterface.h │ │ │ │ │ ├── sqSqueakInfoPlistInterface.m │ │ │ │ │ ├── sqSqueakMainApp.h │ │ │ │ │ ├── sqSqueakMainApp.m │ │ │ │ │ ├── sqSqueakMainApplication+attributes.h │ │ │ │ │ ├── sqSqueakMainApplication+attributes.m │ │ │ │ │ ├── sqSqueakMainApplication+cursor.h │ │ │ │ │ ├── sqSqueakMainApplication+cursor.m │ │ │ │ │ ├── sqSqueakMainApplication+events.h │ │ │ │ │ ├── sqSqueakMainApplication+events.m │ │ │ │ │ ├── sqSqueakMainApplication+imageReadWrite.h │ │ │ │ │ ├── sqSqueakMainApplication+imageReadWrite.m │ │ │ │ │ ├── sqSqueakMainApplication+screen.h │ │ │ │ │ ├── sqSqueakMainApplication+screen.m │ │ │ │ │ ├── sqSqueakMainApplication+sound.h │ │ │ │ │ ├── sqSqueakMainApplication+sound.m │ │ │ │ │ ├── sqSqueakMainApplication+vmAndImagePath.h │ │ │ │ │ ├── sqSqueakMainApplication+vmAndImagePath.m │ │ │ │ │ ├── sqSqueakMainApplication.h │ │ │ │ │ ├── sqSqueakMainApplication.m │ │ │ │ │ ├── sqSqueakScreenAPI.h │ │ │ │ │ ├── sqSqueakScreenAPI.m │ │ │ │ │ ├── sqSqueakScreenAndWindow.h │ │ │ │ │ ├── sqSqueakScreenAndWindow.m │ │ │ │ │ ├── sqSqueakSoundAPI.h │ │ │ │ │ ├── sqSqueakSoundAPI.m │ │ │ │ │ ├── sqSqueakVmAndImagePathAPI.h │ │ │ │ │ └── sqSqueakVmAndImagePathAPI.m │ │ │ │ ├── English.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── aio.c │ │ │ │ └── main.m │ │ │ ├── Default.psd │ │ │ ├── English.lproj/ │ │ │ │ └── MainMenu.xib │ │ │ ├── Entitlements.plist │ │ │ ├── Info-iPhone.plist │ │ │ ├── MainWindow.xib │ │ │ ├── OSX/ │ │ │ │ ├── BitMapConversionLogicFromX11.c │ │ │ │ ├── BitMapConversionLogicFromX11.h │ │ │ │ ├── Credits.rtf │ │ │ │ ├── English.lproj/ │ │ │ │ │ ├── InfoPlist.strings │ │ │ │ │ └── MainMenu.xib │ │ │ │ ├── RoarVM.icns │ │ │ │ ├── SqViewBitmapConversion.h │ │ │ │ ├── SqViewBitmapConversion.m │ │ │ │ ├── SqViewClut.h │ │ │ │ ├── SqViewClut.m │ │ │ │ ├── Squeak.icns │ │ │ │ ├── SqueakChanges.icns │ │ │ │ ├── SqueakGeneric.icns │ │ │ │ ├── SqueakImage.icns │ │ │ │ ├── SqueakOSXAppDelegate.h │ │ │ │ ├── SqueakOSXAppDelegate.m │ │ │ │ ├── SqueakOSXApplication.h │ │ │ │ ├── SqueakOSXApplication.m │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ ├── SqueakProject.icns │ │ │ │ ├── SqueakScript.icns │ │ │ │ ├── SqueakSources.icns │ │ │ │ ├── dtraceOperationsPerSecond.d │ │ │ │ ├── dtracedrawrecttiming.d │ │ │ │ ├── keyBoardStrokeDetails.h │ │ │ │ ├── keyBoardStrokeDetails.m │ │ │ │ ├── macintoshosxextra.c │ │ │ │ ├── macintoshosxextra.h │ │ │ │ ├── plugins/ │ │ │ │ │ ├── HostWindowPlugin/ │ │ │ │ │ │ ├── sqMacHostWindow.h │ │ │ │ │ │ └── sqMacHostWindow.m │ │ │ │ │ └── SoundPlugin/ │ │ │ │ │ ├── sqSqueakOSXSoundCoreAudio.h │ │ │ │ │ └── sqSqueakOSXSoundCoreAudio.m │ │ │ │ ├── sqMacUnixExternalPrims.m │ │ │ │ ├── sqMacV2Browser.h │ │ │ │ ├── sqMacV2Browser.m │ │ │ │ ├── sqMacV2Window.h │ │ │ │ ├── sqMacV2Window.m │ │ │ │ ├── sqSqueakMainApplication+screen.h │ │ │ │ ├── sqSqueakMainApplication+screen.m │ │ │ │ ├── sqSqueakOSXApplication+attributes.h │ │ │ │ ├── sqSqueakOSXApplication+attributes.m │ │ │ │ ├── sqSqueakOSXApplication+clipboard.h │ │ │ │ ├── sqSqueakOSXApplication+clipboard.m │ │ │ │ ├── sqSqueakOSXApplication+cursor.h │ │ │ │ ├── sqSqueakOSXApplication+cursor.m │ │ │ │ ├── sqSqueakOSXApplication+events.h │ │ │ │ ├── sqSqueakOSXApplication+events.m │ │ │ │ ├── sqSqueakOSXApplication+imageReadWrite.h │ │ │ │ ├── sqSqueakOSXApplication+imageReadWrite.m │ │ │ │ ├── sqSqueakOSXApplication.h │ │ │ │ ├── sqSqueakOSXApplication.m │ │ │ │ ├── sqSqueakOSXClipboardAPI.h │ │ │ │ ├── sqSqueakOSXClipboardAPI.m │ │ │ │ ├── sqSqueakOSXDropAPI.h │ │ │ │ ├── sqSqueakOSXDropAPI.m │ │ │ │ ├── sqSqueakOSXFileDirectoryInterface.h │ │ │ │ ├── sqSqueakOSXFileDirectoryInterface.m │ │ │ │ ├── sqSqueakOSXInfoPlistInterface.h │ │ │ │ ├── sqSqueakOSXInfoPlistInterface.m │ │ │ │ ├── sqSqueakOSXNSView.h │ │ │ │ ├── sqSqueakOSXNSView.m │ │ │ │ ├── sqSqueakOSXScreenAndWindow.h │ │ │ │ └── sqSqueakOSXScreenAndWindow.m │ │ │ ├── Resources-iPad/ │ │ │ │ └── MainWindow-iPad.xib │ │ │ ├── RoarVMOnIPad.xcodeproj/ │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ ├── johnmci.pbxuser │ │ │ │ └── project.pbxproj │ │ │ ├── RoarVMSwipeEvent.h │ │ │ ├── RoarVMSwipeEvent.m │ │ │ ├── Settings.bundle/ │ │ │ │ ├── Root.plist │ │ │ │ └── en.lproj/ │ │ │ │ └── Root.strings │ │ │ ├── SqueakNoOGLIPhone_Prefix.pch │ │ │ ├── SqueakPureObjc-Info 64x64.plist │ │ │ ├── SqueakPureObjc-Info.plist │ │ │ ├── SqueakPureObjc-InfoCOG.plist │ │ │ ├── SqueakPureObjc.xcodeproj/ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ └── MAC.pbxuser │ │ │ ├── SqueakPureObjcCogVM.xcodeproj/ │ │ │ │ ├── MAC.mode1v3 │ │ │ │ ├── MAC.mode1v3~esteban_master │ │ │ │ ├── MAC.pbxuser │ │ │ │ ├── johnmci.mode1v3 │ │ │ │ ├── johnmci.pbxuser │ │ │ │ └── project.pbxproj │ │ │ ├── SqueakPureObjc_Prefix.pch │ │ │ ├── artwork/ │ │ │ │ └── MacSqueakIcons/ │ │ │ │ ├── Changes.psd │ │ │ │ ├── Document Icon Template.psd │ │ │ │ ├── Gear.psd │ │ │ │ ├── Plugin.psd │ │ │ │ ├── Script.psd │ │ │ │ ├── Scroll.psd │ │ │ │ └── SqueakAqua.psd │ │ │ ├── iPhone/ │ │ │ │ ├── Classes/ │ │ │ │ │ ├── RoarVMAbstractEvent.h │ │ │ │ │ ├── RoarVMAbstractEvent.m │ │ │ │ │ ├── RoarVMMouseEvent.h │ │ │ │ │ ├── RoarVMMouseEvent.m │ │ │ │ │ ├── RoarVMMouseUpEvent.h │ │ │ │ │ ├── RoarVMMouseUpEvent.m │ │ │ │ │ ├── SqueakNoOGLIPhoneAppDelegate.h │ │ │ │ │ ├── SqueakNoOGLIPhoneAppDelegate.m │ │ │ │ │ ├── SqueakUIController.h │ │ │ │ │ ├── SqueakUIController.m │ │ │ │ │ ├── SqueakUIView.h │ │ │ │ │ ├── SqueakUIView.m │ │ │ │ │ ├── SqueakUIViewCALayer.h │ │ │ │ │ ├── SqueakUIViewCALayer.m │ │ │ │ │ ├── SqueakUIViewOpenGL.h │ │ │ │ │ ├── SqueakUIViewOpenGL.m │ │ │ │ │ ├── SqueakUIViewOpenGLAlternate.m │ │ │ │ │ ├── UIGestureRecognizer+RoarVMEvents.h │ │ │ │ │ ├── UIGestureRecognizer+RoarVMEvents.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+Network.h │ │ │ │ │ ├── sqSqueakIPhoneApplication+Network.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+attributes.h │ │ │ │ │ ├── sqSqueakIPhoneApplication+attributes.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+clipboard.h │ │ │ │ │ ├── sqSqueakIPhoneApplication+clipboard.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+events.h │ │ │ │ │ ├── sqSqueakIPhoneApplication+events.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+imageReadWrite.h │ │ │ │ │ ├── sqSqueakIPhoneApplication+imageReadWrite.m │ │ │ │ │ ├── sqSqueakIPhoneApplication+sound.h │ │ │ │ │ ├── sqSqueakIPhoneApplication.h │ │ │ │ │ ├── sqSqueakIPhoneApplication.m │ │ │ │ │ ├── sqSqueakIPhoneClipboardAPI.h │ │ │ │ │ ├── sqSqueakIPhoneClipboardAPI.m │ │ │ │ │ ├── sqSqueakIPhoneFileDirectoryInterface.h │ │ │ │ │ ├── sqSqueakIPhoneFileDirectoryInterface.m │ │ │ │ │ ├── sqSqueakIPhoneInfoPlistInterface.h │ │ │ │ │ ├── sqSqueakIPhoneInfoPlistInterface.m │ │ │ │ │ ├── sqSqueakiPhoneApplication+sound.m │ │ │ │ │ ├── sqiPhoneScreenAndWindow.h │ │ │ │ │ └── sqiPhoneScreenAndWindow.m │ │ │ │ ├── Info-iPhone.plist │ │ │ │ ├── SqueakV3-minimum-MVC.sources │ │ │ │ ├── config.h │ │ │ │ ├── iPhone.changes │ │ │ │ ├── iPhone.image │ │ │ │ ├── macintoshextra.c │ │ │ │ ├── macintoshextra.h │ │ │ │ ├── osExports.c │ │ │ │ ├── plugins/ │ │ │ │ │ ├── ClipboardExtended/ │ │ │ │ │ │ ├── sqMacExtendedClipboard.h │ │ │ │ │ │ └── sqMacExtendedClipboard.m │ │ │ │ │ ├── HostWindowPlugin/ │ │ │ │ │ │ ├── sqMacHostWindow.c │ │ │ │ │ │ └── sqMacHostWindow.h │ │ │ │ │ └── SqueakFFIPrims/ │ │ │ │ │ ├── dummyFFI.c │ │ │ │ │ └── dummyFFI.h │ │ │ │ ├── sqConfig.h │ │ │ │ ├── sqDummyaio.c │ │ │ │ ├── sqDummyaio.h │ │ │ │ ├── sqMacV2Memory.c │ │ │ │ ├── sqMacV2Memory.h │ │ │ │ └── sqPlatformSpecific.h │ │ │ ├── sqGnu.h │ │ │ └── src/ │ │ │ ├── plugins/ │ │ │ │ └── LocalePlugin/ │ │ │ │ └── LocalePlugin.c │ │ │ ├── plugins.int │ │ │ └── vm/ │ │ │ ├── interp.c │ │ │ ├── interp.h │ │ │ └── sqNamedPrims.h │ │ ├── intplugins/ │ │ │ ├── ADPCMCodecPlugin/ │ │ │ │ └── ADPCMCodecPlugin.c │ │ │ ├── AsynchFilePlugin/ │ │ │ │ └── AsynchFilePlugin.c │ │ │ ├── B2DPlugin/ │ │ │ │ └── B2DPlugin.c │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ └── B3DAcceleratorPlugin.c │ │ │ ├── BMPReadWriterPlugin/ │ │ │ │ └── BMPReadWriterPlugin.c │ │ │ ├── BitBltPlugin/ │ │ │ │ └── BitBltPlugin.c │ │ │ ├── CroquetPlugin/ │ │ │ │ └── CroquetPlugin.c │ │ │ ├── DSAPrims/ │ │ │ │ └── DSAPrims.c │ │ │ ├── DropPlugin/ │ │ │ │ └── DropPlugin.c │ │ │ ├── FFTPlugin/ │ │ │ │ └── FFTPlugin.c │ │ │ ├── FT2Plugin/ │ │ │ │ └── FT2Plugin.c │ │ │ ├── FileCopyPlugin/ │ │ │ │ └── FileCopyPlugin.c │ │ │ ├── FilePlugin/ │ │ │ │ └── FilePlugin.c │ │ │ ├── FloatArrayPlugin/ │ │ │ │ └── FloatArrayPlugin.c │ │ │ ├── FloatMathPlugin/ │ │ │ │ └── FloatMathPlugin.c │ │ │ ├── GeniePlugin/ │ │ │ │ └── GeniePlugin.c │ │ │ ├── HostWindowPlugin/ │ │ │ │ └── HostWindowPlugin.c │ │ │ ├── IA32ABI/ │ │ │ │ └── IA32ABI.c │ │ │ ├── JPEGReadWriter2Plugin/ │ │ │ │ └── JPEGReadWriter2Plugin.c │ │ │ ├── JPEGReaderPlugin/ │ │ │ │ └── JPEGReaderPlugin.c │ │ │ ├── JoystickTabletPlugin/ │ │ │ │ └── JoystickTabletPlugin.c │ │ │ ├── Klatt/ │ │ │ │ └── Klatt.c │ │ │ ├── LargeIntegers/ │ │ │ │ └── LargeIntegers.c │ │ │ ├── LocalePlugin/ │ │ │ │ └── LocalePlugin.c │ │ │ ├── MIDIPlugin/ │ │ │ │ └── MIDIPlugin.c │ │ │ ├── Matrix2x3Plugin/ │ │ │ │ └── Matrix2x3Plugin.c │ │ │ ├── MiscPrimitivePlugin/ │ │ │ │ └── MiscPrimitivePlugin.c │ │ │ ├── Mpeg3Plugin/ │ │ │ │ └── Mpeg3Plugin.c │ │ │ ├── ObjectiveCPlugin/ │ │ │ │ └── ObjectiveCPlugin.c │ │ │ ├── RePlugin/ │ │ │ │ └── RePlugin.c │ │ │ ├── SecurityPlugin/ │ │ │ │ └── SecurityPlugin.c │ │ │ ├── SerialPlugin/ │ │ │ │ └── SerialPlugin.c │ │ │ ├── SlangTestSupportPlugin/ │ │ │ │ └── SlangTestSupportPlugin.c │ │ │ ├── SocketPlugin/ │ │ │ │ └── SocketPlugin.c │ │ │ ├── SoundCodecPrims/ │ │ │ │ └── SoundCodecPrims.c │ │ │ ├── SoundGenerationPlugin/ │ │ │ │ └── SoundGenerationPlugin.c │ │ │ ├── SoundPlugin/ │ │ │ │ └── SoundPlugin.c │ │ │ ├── Squeak3D/ │ │ │ │ └── Squeak3D.c │ │ │ ├── SqueakFFIPrims/ │ │ │ │ └── SqueakFFIPrims.c │ │ │ ├── StarSqueakPlugin/ │ │ │ │ └── StarSqueakPlugin.c │ │ │ ├── UUIDPlugin/ │ │ │ │ └── UUIDPlugin.c │ │ │ ├── UnixOSProcessPlugin/ │ │ │ │ └── UnixOSProcessPlugin.c │ │ │ └── ZipPlugin/ │ │ │ └── ZipPlugin.c │ │ └── unix/ │ │ ├── CMakeLists.txt │ │ ├── ChangeLog │ │ ├── Makefile │ │ ├── README │ │ ├── README.CMake │ │ ├── README.SVN │ │ ├── cmake/ │ │ │ ├── Fixes.cmake │ │ │ ├── PluginExternal.cmake │ │ │ ├── PluginInternal.cmake │ │ │ ├── Plugins.cmake │ │ │ ├── Utils.cmake │ │ │ ├── config.guess │ │ │ ├── config.in │ │ │ ├── config.sub │ │ │ ├── configure │ │ │ ├── disabledPlugins.c │ │ │ ├── gnuify │ │ │ ├── gnuify.awk │ │ │ ├── squeak.in │ │ │ ├── squeak.sh.in │ │ │ ├── testDoubleWordAlignment.c │ │ │ ├── testDoubleWordOrder.c │ │ │ ├── testLanginfoCodeset.c │ │ │ └── verstamp │ │ ├── config/ │ │ │ ├── Makefile │ │ │ ├── Makefile.cpp-plg.in │ │ │ ├── Makefile.in │ │ │ ├── Makefile.install │ │ │ ├── Makefile.plg.in │ │ │ ├── README │ │ │ ├── Squeak.spec.in │ │ │ ├── acinclude.m4 │ │ │ ├── aclocal.m4 │ │ │ ├── bin.squeak.sh.in │ │ │ ├── build │ │ │ ├── config.guess │ │ │ ├── config.h.in │ │ │ ├── config.sub │ │ │ ├── configure │ │ │ ├── configure.ac │ │ │ ├── gnuify │ │ │ ├── inisqueak.in │ │ │ ├── install-sh │ │ │ ├── ltcf-c.sh │ │ │ ├── ltconfig │ │ │ ├── ltmain.sh │ │ │ ├── make.cfg.in │ │ │ ├── make.ext.in │ │ │ ├── make.int.in │ │ │ ├── make.prg.in │ │ │ ├── mkacinc │ │ │ ├── mkconfig.in │ │ │ ├── mkinstalldirs │ │ │ ├── mkman │ │ │ ├── mkmf │ │ │ ├── mktargets │ │ │ ├── relpath │ │ │ ├── squeak.sh.in │ │ │ ├── uninstall │ │ │ ├── version │ │ │ ├── version.stamp │ │ │ ├── verstamp │ │ │ └── vmm.config │ │ ├── doc/ │ │ │ ├── 3.10-1.RELEASE_NOTES │ │ │ ├── 3.10-2.RELEASE_NOTES │ │ │ ├── 3.10-3.RELEASE_NOTES │ │ │ ├── 3.2-1.RELEASE_NOTES │ │ │ ├── 3.2-2.RELEASE_NOTES │ │ │ ├── 3.2-3.RELEASE_NOTES │ │ │ ├── 3.2-4.RELEASE_NOTES │ │ │ ├── 3.2-5.RELEASE_NOTES │ │ │ ├── 3.2-6.RELEASE_NOTES │ │ │ ├── 3.5-1devel.RELEASE_NOTES │ │ │ ├── 3.6-3.RELEASE_NOTES │ │ │ ├── 3.7-7.RELEASE_NOTES │ │ │ ├── 3.7b-2.RELEASE_NOTES │ │ │ ├── 3.7b-3.RELEASE_NOTES │ │ │ ├── 3.7b-4.RELEASE_NOTES │ │ │ ├── 3.7b-5.RELEASE_NOTES │ │ │ ├── 3.9-4.RELEASE_NOTES │ │ │ ├── 3.9-7.RELEASE_NOTES │ │ │ ├── COPYING │ │ │ ├── COPYRIGHT │ │ │ ├── HowToBuildFromSource.html/ │ │ │ │ ├── HowToBuildFromSource-node1.html │ │ │ │ ├── HowToBuildFromSource-node2.html │ │ │ │ ├── HowToBuildFromSource-node3.html │ │ │ │ ├── HowToBuildFromSource-node4.html │ │ │ │ ├── HowToBuildFromSource-node5.html │ │ │ │ ├── HowToBuildFromSource-node6.html │ │ │ │ ├── HowToBuildFromSource-node7.html │ │ │ │ ├── HowToBuildFromSource.css │ │ │ │ ├── HowToBuildFromSource.html │ │ │ │ └── index.html │ │ │ ├── HowToBuildFromSource.ps │ │ │ ├── HowToBuildFromSource.txt │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README.Contributing │ │ │ ├── README.Keyboard │ │ │ ├── README.Sound │ │ │ ├── RELEASE_NOTES_3.11.3.2135 │ │ │ ├── RELEASE_NOTES_4.0.3.2196 │ │ │ ├── RELEASE_NOTES_4.0.3.2202 │ │ │ └── squeak.1 │ │ ├── misc/ │ │ │ ├── 00_README │ │ │ ├── AioPluginV1-1.sar │ │ │ ├── GLXUnix-ikp.2.cs │ │ │ ├── OSProcessPluginV3-3.sar │ │ │ ├── System-Tracing.2.cs │ │ │ ├── VMM38b4-64bit-image1-ikp.1.cs │ │ │ ├── VMM38b4-64bit-image2-ikp.1.cs │ │ │ ├── VMM38b4-64bit-vm1-ikp.1.cs │ │ │ ├── VMM38b4-64bit-vm2-ikp.2.cs │ │ │ ├── VMMaker-tpr.14.mcz │ │ │ ├── XDisplayControlPluginV1-0.sar │ │ │ └── threadValidate/ │ │ │ ├── Makefile │ │ │ ├── config.h │ │ │ ├── sqTicker.c │ │ │ ├── sqUnixHeartbeat.c │ │ │ └── threadValidate.c │ │ ├── npsqueak/ │ │ │ ├── Makefile │ │ │ ├── README.npsqueak │ │ │ ├── include/ │ │ │ │ ├── jri.h │ │ │ │ ├── jri_md.h │ │ │ │ ├── jritypes.h │ │ │ │ ├── npapi.h │ │ │ │ └── npupp.h │ │ │ ├── npsqueak.c │ │ │ ├── npsqueakregister.in │ │ │ ├── npsqueakrun.in │ │ │ ├── npunix.c │ │ │ └── test/ │ │ │ ├── plugintest.html │ │ │ └── plugintest.sts │ │ ├── plugins/ │ │ │ ├── AioPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── build.cmake │ │ │ │ └── config.cmake │ │ │ ├── AsynchFilePlugin/ │ │ │ │ ├── sqUnixAsynchFile.c │ │ │ │ └── sqUnixAsynchFile.h │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── NOTES │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ ├── sqUnixOpenGL.c │ │ │ │ ├── sqUnixOpenGL.h │ │ │ │ └── zzz/ │ │ │ │ ├── sqUnixOpenGL.OSX │ │ │ │ └── sqUnixOpenGL.X11 │ │ │ ├── CameraPlugin/ │ │ │ │ └── sqCamera.c │ │ │ ├── ClipboardExtendedPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ └── sqUnixExtendedClipboard.c │ │ │ ├── DBusPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ └── config.cmake │ │ │ ├── DropPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ └── sqUnixDragDrop.c │ │ │ ├── FT2Plugin/ │ │ │ │ ├── FT2PluginHeaderFix-ikp.1.cs │ │ │ │ └── config.cmake │ │ │ ├── FileCopyPlugin/ │ │ │ │ ├── build.cmake │ │ │ │ └── sqUnixFileCopyPlugin.c │ │ │ ├── FilePlugin/ │ │ │ │ ├── config.cmake │ │ │ │ └── sqUnixFile.c │ │ │ ├── FloatMathPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ └── config.cmake │ │ │ ├── GStreamerPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ └── config.cmake │ │ │ ├── HostWindowPlugin/ │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ └── sqUnixHostWindowPlugin.c │ │ │ ├── ImmX11Plugin/ │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ └── config.cmake │ │ │ ├── JPEGReadWriter2Plugin/ │ │ │ │ └── Makefile.inc │ │ │ ├── JoystickTabletPlugin/ │ │ │ │ └── sqUnixJoystickTablet.c │ │ │ ├── LocalePlugin/ │ │ │ │ ├── sqUnixLocale.c │ │ │ │ └── sqUnixLocale.h │ │ │ ├── MIDIPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ ├── sqUnixMIDI.c │ │ │ │ ├── sqUnixMIDIALSA.inc │ │ │ │ └── sqUnixMIDINone.inc │ │ │ ├── Mpeg3Plugin/ │ │ │ │ ├── Makefile.in │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── config.cmake │ │ │ │ └── mkmf.subdirs │ │ │ ├── OggPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ └── config.cmake │ │ │ ├── PrintJobPlugin/ │ │ │ │ ├── sqPrinting.c │ │ │ │ └── sqPrinting.h │ │ │ ├── PseudoTTYPlugin/ │ │ │ │ ├── PseudoTTY.st │ │ │ │ ├── PseudoTTYPlugin.st │ │ │ │ ├── README │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ ├── openpty.h │ │ │ │ └── sqUnixPseudoTTYPlugin.c │ │ │ ├── RomePlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ └── config.cmake │ │ │ ├── SecurityPlugin/ │ │ │ │ └── sqUnixSecurity.c │ │ │ ├── SerialPlugin/ │ │ │ │ └── sqUnixSerial.c │ │ │ ├── SocketPlugin/ │ │ │ │ ├── config.cmake │ │ │ │ └── sqUnixSocket.c │ │ │ ├── SoundPlugin/ │ │ │ │ ├── sqUnixSound.c │ │ │ │ └── zzz/ │ │ │ │ ├── Buffer.h │ │ │ │ ├── DoubleBuffer.h │ │ │ │ ├── Fifo.h │ │ │ │ └── ring.h │ │ │ ├── SqueakFFIPrims/ │ │ │ │ ├── 00README │ │ │ │ ├── Makefile │ │ │ │ ├── Makefile.in │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── any-libffi-asm.S │ │ │ │ ├── any-libffi.c │ │ │ │ ├── build.cmake │ │ │ │ ├── config.cmake │ │ │ │ ├── ffi-config │ │ │ │ ├── ffi-test-main.c │ │ │ │ ├── ffi-test-sq.h │ │ │ │ ├── ffi-test.c │ │ │ │ ├── ffi-test.h │ │ │ │ ├── ppc-darwin-asm.S │ │ │ │ ├── ppc-darwin.c │ │ │ │ ├── ppc-global.h │ │ │ │ ├── ppc-sysv-asm.S │ │ │ │ ├── ppc-sysv.c │ │ │ │ ├── x86-sysv-asm.S │ │ │ │ └── x86-sysv.c │ │ │ ├── UUIDPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── config.cmake │ │ │ │ └── sqUnixUUID.c │ │ │ ├── UnixOSProcessPlugin/ │ │ │ │ ├── Makefile.inc │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── build.cmake │ │ │ │ └── config.cmake │ │ │ ├── VideoForLinuxPlugin/ │ │ │ │ ├── Video4Squeak-dgd.8.cs │ │ │ │ ├── VideoForLinuxPlugin.c │ │ │ │ ├── VideoForLinuxPlugin.h │ │ │ │ ├── acinclude.m4 │ │ │ │ ├── ccvt.h │ │ │ │ ├── ccvt_c2.c │ │ │ │ ├── ccvt_misc.c │ │ │ │ ├── ccvt_types.h │ │ │ │ ├── palettes.c │ │ │ │ ├── palettes.h │ │ │ │ ├── videolib.c │ │ │ │ └── videolib.h │ │ │ └── XDisplayControlPlugin/ │ │ │ ├── Makefile.inc │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ └── config.cmake │ │ ├── src/ │ │ │ ├── plugins/ │ │ │ │ ├── AioPlugin/ │ │ │ │ │ └── AioPlugin.c │ │ │ │ ├── B3DAcceleratorPlugin/ │ │ │ │ │ └── B3DAcceleratorPlugin.c │ │ │ │ ├── ClipboardExtendedPlugin/ │ │ │ │ │ └── ClipboardExtendedPlugin.c │ │ │ │ ├── DBusPlugin/ │ │ │ │ │ └── DBusPlugin.c │ │ │ │ ├── FileCopyPlugin/ │ │ │ │ │ └── FileCopyPlugin.c │ │ │ │ ├── GStreamerPlugin/ │ │ │ │ │ └── GStreamerPlugin.c │ │ │ │ ├── HostWindowPlugin/ │ │ │ │ │ └── HostWindowPlugin.c │ │ │ │ ├── KedamaPlugin/ │ │ │ │ │ └── KedamaPlugin.c │ │ │ │ ├── KedamaPlugin2/ │ │ │ │ │ └── KedamaPlugin2.c │ │ │ │ ├── Mpeg3Plugin/ │ │ │ │ │ └── Mpeg3Plugin.c │ │ │ │ ├── RomePlugin/ │ │ │ │ │ └── RomePlugin.c │ │ │ │ ├── Squeak3D/ │ │ │ │ │ └── Squeak3D.c │ │ │ │ ├── SqueakFFIPrims/ │ │ │ │ │ └── SqueakFFIPrims.c │ │ │ │ ├── UUIDPlugin/ │ │ │ │ │ └── UUIDPlugin.c │ │ │ │ ├── UnixOSProcessPlugin/ │ │ │ │ │ └── UnixOSProcessPlugin.c │ │ │ │ └── XDisplayControlPlugin/ │ │ │ │ └── XDisplayControlPlugin.c │ │ │ ├── plugins.ext │ │ │ ├── plugins.int │ │ │ └── vm/ │ │ │ ├── interp.c │ │ │ ├── interp.h │ │ │ └── sqNamedPrims.h │ │ ├── vm/ │ │ │ ├── Makefile.in │ │ │ ├── SqDisplay.h │ │ │ ├── SqModule.h │ │ │ ├── SqSound.h │ │ │ ├── acinclude.m4 │ │ │ ├── aio.c │ │ │ ├── build.cmake │ │ │ ├── config.cmake │ │ │ ├── debug.c │ │ │ ├── debug.h │ │ │ ├── dlfcn-dyld.c │ │ │ ├── feedback.h │ │ │ ├── glibc.h │ │ │ ├── interp.h │ │ │ ├── mac-alias.c │ │ │ ├── osExports.c │ │ │ ├── sqConfig.h │ │ │ ├── sqGnu.h │ │ │ ├── sqNamedPrims.h │ │ │ ├── sqPlatformSpecific.h │ │ │ ├── sqUnixCharConv.c │ │ │ ├── sqUnixCharConv.h │ │ │ ├── sqUnixEvent.c │ │ │ ├── sqUnixExternalPrims.c │ │ │ ├── sqUnixGL.h │ │ │ ├── sqUnixGlobals.h │ │ │ ├── sqUnixHeartbeat.c │ │ │ ├── sqUnixMain.c │ │ │ ├── sqUnixMain.h │ │ │ ├── sqUnixMemory.c │ │ │ ├── sqUnixThreads.c │ │ │ ├── sqUnixVMProfile.c │ │ │ ├── sqUnixWindow.h │ │ │ ├── sqaio.h │ │ │ └── sunos.h │ │ ├── vm-display-Quartz/ │ │ │ ├── CPS.h │ │ │ ├── Info.plist.in │ │ │ ├── Makefile.in │ │ │ ├── Makefile.inc │ │ │ ├── PkgInfo │ │ │ ├── Resources/ │ │ │ │ ├── GLXUnix-ikp.2.cs │ │ │ │ ├── SqueakChanges.icns │ │ │ │ ├── SqueakHelp/ │ │ │ │ │ └── SqueakHelp.html │ │ │ │ ├── SqueakImage.icns │ │ │ │ ├── SqueakPlugin.icns │ │ │ │ ├── SqueakProject.icns │ │ │ │ ├── SqueakSources.icns │ │ │ │ └── SqueakVM.icns │ │ │ ├── Squeak.h │ │ │ ├── Squeak.m │ │ │ ├── SqueakView.h │ │ │ ├── SqueakView.m │ │ │ ├── SqueakWindow.h │ │ │ ├── SqueakWindow.m │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ ├── config.cmake │ │ │ ├── mkinfo │ │ │ ├── sqUnixQuartz.m │ │ │ ├── sqUnixQuartzGL.h │ │ │ └── zzz/ │ │ │ ├── Squeak.h │ │ │ ├── Squeak.m │ │ │ ├── SqueakView.h │ │ │ ├── SqueakView.m │ │ │ ├── SqueakWindow.h │ │ │ ├── SqueakWindow.m │ │ │ └── sqUnixQuartz.m │ │ ├── vm-display-X11/ │ │ │ ├── Makefile.in │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ ├── config.cmake │ │ │ ├── sqUnixMozilla.c │ │ │ ├── sqUnixOpenGL.X11 │ │ │ ├── sqUnixX11.c │ │ │ └── sqUnixXdnd.c │ │ ├── vm-display-custom/ │ │ │ ├── Makefile.in │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ └── sqUnixCustomWindow.c │ │ ├── vm-display-fbdev/ │ │ │ ├── 00_README.fbdev │ │ │ ├── Makefile.in │ │ │ ├── TODO │ │ │ ├── acinclude.m4 │ │ │ ├── config.cmake │ │ │ ├── sqUnixFBDev.c │ │ │ ├── sqUnixFBDevFramebuffer.c │ │ │ ├── sqUnixFBDevKeyboard.c │ │ │ ├── sqUnixFBDevKeymap.c │ │ │ ├── sqUnixFBDevMouse.c │ │ │ ├── sqUnixFBDevMouseADB.c │ │ │ ├── sqUnixFBDevMousePS2.c │ │ │ └── sqUnixFBDevUtil.c │ │ ├── vm-display-null/ │ │ │ ├── Makefile.inc │ │ │ ├── build.cmake │ │ │ └── sqUnixDisplayNull.c │ │ ├── vm-sound-ALSA/ │ │ │ ├── Makefile.inc │ │ │ ├── acinclude.m4 │ │ │ ├── config.cmake │ │ │ └── sqUnixSoundALSA.c │ │ ├── vm-sound-MacOSX/ │ │ │ ├── Makefile.inc │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ ├── config.cmake │ │ │ ├── sqUnixSoundDebug.h │ │ │ └── sqUnixSoundMacOSX.c │ │ ├── vm-sound-NAS/ │ │ │ ├── Makefile.inc │ │ │ ├── acinclude.m4 │ │ │ ├── config.cmake │ │ │ └── sqUnixSoundNAS.c │ │ ├── vm-sound-OSS/ │ │ │ ├── Makefile.inc │ │ │ ├── acinclude.m4 │ │ │ ├── config.cmake │ │ │ └── sqUnixSoundOSS.c │ │ ├── vm-sound-Sun/ │ │ │ ├── acinclude.m4 │ │ │ ├── config.cmake │ │ │ └── sqUnixSoundSun.c │ │ ├── vm-sound-custom/ │ │ │ ├── acinclude.m4 │ │ │ └── sqUnixCustomSound.c │ │ ├── vm-sound-null/ │ │ │ ├── acinclude.m4 │ │ │ ├── build.cmake │ │ │ └── sqUnixSoundNull.c │ │ └── vm-sound-pulse/ │ │ ├── config.cmake │ │ └── sqUnixSoundPulseAudio.c │ ├── heap/ │ │ ├── abstract_mark_sweep_collector.cpp │ │ ├── abstract_mark_sweep_collector.h │ │ ├── abstract_object_heap.cpp │ │ ├── abstract_object_heap.h │ │ ├── abstract_object_heap.inline.h │ │ ├── abstract_object_table.h │ │ ├── gc_oop_stack.h │ │ ├── indirect_oop_mark_sweep_collector.h │ │ ├── mark_sweep_collector.h │ │ ├── memory_system.cpp │ │ ├── memory_system.h │ │ ├── memory_system.inline.h │ │ ├── multicore_object_heap.cpp │ │ ├── multicore_object_heap.h │ │ ├── multicore_object_heap.inline.h │ │ ├── multicore_object_table.cpp │ │ ├── multicore_object_table.h │ │ ├── multicore_object_table.inline.h │ │ └── oop_closure.h │ ├── image_readers/ │ │ ├── squeak_image_reader.cpp │ │ └── squeak_image_reader.h │ ├── interpreter/ │ │ ├── abstract_primitive_table.h │ │ ├── at_cache.cpp │ │ ├── at_cache.h │ │ ├── external_primitive_table.h │ │ ├── interpreter_bytecodes.cpp │ │ ├── interpreter_bytecodes.h │ │ ├── interpreter_primitives.cpp │ │ ├── interpreter_primitives.h │ │ ├── method_cache.cpp │ │ ├── method_cache.h │ │ ├── obsolete_indexed_primitive_table.cpp │ │ ├── obsolete_indexed_primitive_table.h │ │ ├── obsolete_named_primitive_table.cpp │ │ ├── obsolete_named_primitive_table.h │ │ ├── primitive_table.cpp │ │ ├── primitive_table.h │ │ ├── squeak_interpreter.cpp │ │ └── squeak_interpreter.h │ ├── linux_bash_profile │ ├── linux_bashrc │ ├── makefiles/ │ │ ├── Makefile.common │ │ ├── Makefile.debug │ │ ├── Makefile.opt │ │ └── configure │ ├── message_buffers/ │ │ ├── buffered_channel.cpp │ │ ├── buffered_channel.h │ │ ├── buffered_channel_debug.h │ │ ├── synced_queue.cpp │ │ └── synced_queue.h │ ├── messages/ │ │ ├── abstract_message.cpp │ │ ├── abstract_message.h │ │ ├── deferred_request.cpp │ │ ├── deferred_request.h │ │ ├── interactions.cpp │ │ ├── interactions.h │ │ ├── interpreter_subset_for_control_transfer.cpp │ │ ├── interpreter_subset_for_control_transfer.h │ │ ├── message_classes.cpp │ │ ├── message_classes.h │ │ ├── message_or_ack_request.cpp │ │ ├── message_or_ack_request.h │ │ ├── message_statics.cpp │ │ ├── message_statics.h │ │ ├── message_stats.cpp │ │ ├── message_stats.h │ │ ├── message_templates.h │ │ ├── receive_marker.cpp │ │ └── receive_marker.h │ ├── multichip/ │ │ ├── abstract_zero_copy_command_queue_endpoint.cpp │ │ ├── abstract_zero_copy_command_queue_endpoint.h │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.cpp │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.h │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_receiver.cpp │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_receiver.h │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_sender.cpp │ │ ├── chip_to_chip_direct_to_hypervisor_zero_copy_sender.h │ │ ├── chip_to_chip_zero_copy_command_queue_endpoint.cpp │ │ ├── chip_to_chip_zero_copy_command_queue_endpoint.h │ │ ├── chip_to_chip_zero_copy_command_receiver.cpp │ │ ├── chip_to_chip_zero_copy_command_receiver.h │ │ ├── chip_to_chip_zero_copy_command_sender.cpp │ │ ├── chip_to_chip_zero_copy_command_sender.h │ │ ├── host_pci_info.cpp │ │ ├── host_pci_info.h │ │ ├── tilera_chip_to_chip_message_queue.cpp │ │ └── tilera_chip_to_chip_message_queue.h │ ├── objects/ │ │ ├── chunk.h │ │ ├── chunk.inline.h │ │ ├── header_type.cpp │ │ ├── header_type.h │ │ ├── object.cpp │ │ ├── object.h │ │ ├── object.inline.h │ │ ├── object_indices.h │ │ ├── object_p.h │ │ ├── preheader.h │ │ ├── process_field_locator.cpp │ │ ├── process_field_locator.h │ │ ├── roots.cpp │ │ ├── roots.h │ │ ├── special_indices.h │ │ └── word_containing_object_type.h │ ├── oops/ │ │ ├── abstract_oop.h │ │ ├── oop.cpp │ │ ├── oop.h │ │ ├── oop.inline.h │ │ └── tags.h │ ├── platform/ │ │ ├── abstract_cpu_coordinate.h │ │ ├── abstract_memory_semantics.h │ │ ├── abstract_message_queue.h │ │ ├── abstract_os_interface.cpp │ │ ├── abstract_os_interface.h │ │ ├── cacheline_aligned.h │ │ ├── cpu_coordinate.h │ │ ├── dummy_cpu_coordinate.cpp │ │ ├── dummy_cpu_coordinate.h │ │ ├── ilib_message_queue.cpp │ │ ├── ilib_message_queue.h │ │ ├── ilib_os_interface.cpp │ │ ├── ilib_os_interface.h │ │ ├── logical_core.cpp │ │ ├── logical_core.h │ │ ├── memory_semantics.h │ │ ├── message_queue.h │ │ ├── os_interface.h │ │ ├── osx_os_interface.cpp │ │ ├── osx_os_interface.h │ │ ├── posix_os_interface.cpp │ │ ├── posix_os_interface.h │ │ ├── process_memory_semantics.cpp │ │ ├── process_memory_semantics.h │ │ ├── shared_memory_message_queue.cpp │ │ ├── shared_memory_message_queue.h │ │ ├── shared_memory_message_queue_per_sender.cpp │ │ ├── shared_memory_message_queue_per_sender.h │ │ ├── thread_memory_semantics.cpp │ │ ├── thread_memory_semantics.h │ │ ├── tile_cpu_coordinate.cpp │ │ ├── tile_cpu_coordinate.h │ │ ├── tmc_os_interface.cpp │ │ └── tmc_os_interface.h │ ├── primitives/ │ │ ├── RVMPlugin.cpp │ │ └── RVMPlugin.h │ ├── runtime/ │ │ ├── abstract_mutex.cpp │ │ ├── abstract_mutex.h │ │ ├── abstract_tracer.cpp │ │ ├── abstract_tracer.h │ │ ├── bytemap.cpp │ │ ├── bytemap.h │ │ ├── core_tracer.cpp │ │ ├── core_tracer.h │ │ ├── debug_helper.cpp │ │ ├── debug_helper.h │ │ ├── debug_store_checks.h │ │ ├── error_handling.cpp │ │ ├── error_handling.h │ │ ├── execution_tracer.cpp │ │ ├── execution_tracer.h │ │ ├── gc_debugging_tracer.cpp │ │ ├── gc_debugging_tracer.h │ │ ├── headers.h │ │ ├── main.cpp │ │ ├── measurements.cpp │ │ ├── measurements.h │ │ ├── my_rank.cpp │ │ ├── my_rank.h │ │ ├── oop_tracer.cpp │ │ ├── oop_tracer.h │ │ ├── performance_counters.cpp │ │ ├── performance_counters.h │ │ ├── printer.cpp │ │ ├── printer.h │ │ ├── profiling_tracer.cpp │ │ ├── profiling_tracer.h │ │ ├── rank_set.cpp │ │ ├── rank_set.h │ │ ├── runtime_tester.h │ │ ├── rvm_bitmap.cpp │ │ ├── rvm_bitmap.h │ │ ├── rvm_config.cpp │ │ ├── rvm_config.h │ │ ├── rvm_squeak_config.h │ │ ├── safepoint.cpp │ │ ├── safepoint.h │ │ ├── safepoint_ability.cpp │ │ ├── safepoint_ability.h │ │ ├── safepoint_request_queue.cpp │ │ ├── safepoint_request_queue.h │ │ ├── scheduler_mutex.cpp │ │ ├── scheduler_mutex.h │ │ ├── semaphore_mutex.cpp │ │ ├── semaphore_mutex.h │ │ ├── squeak_adapters.cpp │ │ ├── squeak_adapters.h │ │ ├── timeout_deferral.cpp │ │ ├── timeout_deferral.h │ │ ├── timeout_timer.cpp │ │ ├── timeout_timer.h │ │ ├── tracked_ptr.h │ │ ├── tracked_ptr_registry.h │ │ ├── utils.cpp │ │ └── utils.h │ ├── tests/ │ │ ├── buffered_channel.cpp │ │ ├── cacheline_alignment.cpp │ │ ├── external_primitive_table.cpp │ │ ├── main.cpp │ │ ├── os_interface.cpp │ │ ├── starter.cpp │ │ ├── starter.h │ │ ├── synced_queue.cpp │ │ ├── synced_queue_threaded.cpp │ │ ├── test_os_interface.h │ │ └── tracked_ptr.cpp │ └── types/ │ └── types.h └── tests/ ├── __init__.py └── test_startup.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # OS X .DS_Store # Xcode xcuserdata vm/RoarVM.xcodeproj/*.pbxuser vm/RoarVM.xcodeproj/*.perspectivev3 *xcworkspace # Build dir vm/build/*.o vm/build/*.opt vm/build/Makefile vm/build/config.last vm/build/compiler_check vm/build/rvm vm/build/Debug/ vm/build/Release/ vm/build/RoarVM.build/ vm/build/libgtest.a vm/build/rvm-test vm/src/tests/*.o # Unit tests vm/_trial_temp/ *.pyc ================================================ FILE: .gitmodules ================================================ [submodule "vm/googletest"] path = vm/googletest url = git://github.com/smarr/googletest.git ================================================ FILE: INSTALL.rst ================================================ Installation and Usage Instructions for the RoarVM ================================================== This file briefly describes how to compile and use the RoarVM. Installation ------------ Requirements: - gcc, g++ (also tested with icc v11 on Linux) - Ubuntu: libx11-dev, libxext-dev - Mac OS X: Xcode Developer Tools Compilation: In the standard case, calling ./configure ; make in the build directory should be sufficient to compile the rvm executable:: $ cd build $ ./configure $ make Compilation for Debugging:: $ cd build $ ./configure --debug $ make Known Issues: The standard compiler on modern Linux systems is currently not fully supported. Some of its optimizations lead to crashes in the RoarVM. Configure supports a workaround which reduces the optimization level for affected files. Until the bug in the RoarVM is fixed, please use:: $ ./configure --opt-workaround Usage ----- The RoarVM executable supports the following command-line interface:: ./rvm [options] [app-params] [options] optional command-line parameters as detailed below a relative path to a Smalltalk image [app-params] parameters given the application executed by the RoarVM Command-line Parameters:: -headless initializes the RoarVM with a dummy display to avoid opening an X11 session, useful for command-line applications or benchmarks -num_core N starts the RoarVM with N interpreter instances, each running on a dedicated processor core -geom N,M starts the RoarVM with N*M interpreter instances, each running on a dedicated processor core. REMARK: this option is meant for TILE64 processors, where the interpreter instances are distributed on the 2D mesh of cores in an N*M layout -min_heap_MB N sets the lower limit for the overall heap size Filing in RoarVM Changes '''''''''''''''''''''''' To use your current image on top of the RoarVM, a few changes need to be applied to the image. 1. Chose the suitable support file from /image.st/ 2. Open you image (depending on the image, you need to use the SqueakVM) 3. Open a file list in your image 4. Pick the chosen support file and install it or file it in 5. Acknowledge the change to the Process class by pressing proceed in the warning dialog window 6. Save and quit the image 7. Run RoarVM with a num_core setting > 1 Remark: The support for Squeak and Pharo has its limitations. Be aware that those Smalltalks have not been developed with hardware parallelism in mind. It is very likely that you will run into problems that are caused by the assumption that only a single Smalltalk Process is active at a time, and that the scheduler has certain properties like switching between processes only at known places. ================================================ FILE: README ================================================ This branch is used to prepare the code for integration into the RoarVM. The RoarVM uses a slightly different directory structure and supports only a subset of the standard platforms of the SqueakVMs. See https://github.com/smarr/RoarVM/blob/master/README.rst for details. ================================================ FILE: README.rst ================================================ RoarVM - The Manycore SqueakVM ============================== .. image:: https://github.com/smarr/RoarVM/raw/1591bb4e1c282f418231da77cf6d09ec31e2abe8/misc/RoarVM-logo-full.jpg :align: left RoarVM, formerly known as the Renaissance Virtual Machine (RVM) is developed as part of a IBM Research project to investigate programming paradigms and languages for manycore systems of the future. Specifically, this VM is meant to support manycore systems with more than 1000 cores in the future. The RVM was open sourced by IBM Research under the `Eclipse Public License`_. Please see the `open source announcement`_ for further information. Today, the RoarVM supports the parallel execution of Smalltalk programs on x86 compatible multicore systems and Tilera TILE64-based manycore systems. It is tested with standard Squeak 4.1 closure-enabled images, and with a stripped down version of a MVC-based Squeak 3.9 image. The RoarVM provides parallel execution of Smalltalk processes and thus, the programming model is a typical shared-memory model similar to Java with its threads and classical Pthreads for C/C++. .. _Eclipse Public License: http://www.eclipse.org/legal/epl-v10.html .. _open source announcement: http://soft.vub.ac.be/~smarr/rvm-open-source-release/ Install and Use --------------- Please see the INSTALL.rst file. Features -------- The RoarVM is compatible with Squeak and its forks. However, the Smalltalk images needs a number of changes to enable it to utilize more than one core and to interact with the VM correctly. - compatible with Squeak 4.1 and Pharo 1.2 - the RoarVM has full closure support - Smalltalk processes are executed in parallel - tested with 8 cores, 16 hyperthreads on Intel systems - tested with 56 cores on Tilera TILE64/TILEPro64 processors - tested with Linux and Mac OS X 10.6 Purpose ------- The source code of the RoarVM has been released as open source to enable the Smalltalk community to evaluate the ideas and possibly integrate them into their existing systems. The RoarVM provides the necessary functionality to experiment with Smalltalk systems on multi- and manycore machines, which we would like to encourage. However, we also welcome all contributions to the RoarVM itself. Either to bring it up to the speed of the existing VMs or to extend it for further experiments. Known Issues ------------ The RoarVM is a research project and is not as optimized for performance as the standard Squeak VM. Thus, its sequential performance is slower. This is due to the fact that the RoarVM misses optimizations like using the GCC label as value extension to speed up the interpreter. - single core performance is slower than the Squeak VM * Squeak 4.2.4beta1U, MVC image, OS X 554,844,390 bytecodes/sec; 12,213,718 sends/sec * RoarVM, MVC image, OS X, 1 core 66,286,897 bytecodes/sec; 2,910,474 sends/sec * RoarVM, MVC image, OS X, 8 cores 470,588,235 bytecodes/sec; 19,825,677 sends/sec - idle process does not yield when the RoarVM is run on more than one core - the event processing is not adapted fully yet, thus, the idle process is busy-waiting for performance reasons - will drain your battery, on mobile devices - Garbage collector is as simple as possible - it is neither concurrent nor parallel - performance can be problematic - Graphical subsystem based on X11 - in contrast to todays Squeak VM, especially the OS X version, the RoarVM uses solely X11 and does not integrate as well into the OS as Squeak does - Stability should be ok, however, crashes can happen occasionally Technical Overview ------------------ The implementation details of the RoarVM are currently documented in: [1] Hosting an Object Heap on Manycore Hardware: An Exploration, by David Ungar, and Sam S. Adams, in Proceedings of the 5th Symposium on Dynamic Languages, ACM (2009), p. 99-110. http://portal.acm.org/citation.cfm?id=1640134.1640149 As well as an VEE submission which is currently under review. Furthermore, the design is based on the following earlier work: [2] Multiprocessor Smalltalk: A Case Study of a Multiprocessor-Based Programming Environment by Joseph Pallas, and David Ungar, in Proceedings of the ACM SIGPLAN 1988 Conference on Programming Language Design and Implementation, ACM (1988), p. 268-277. http://portal.acm.org/citation.cfm?id=54017 The RoarVM resembles the Squeak VM which is written in Smalltalk/Slang, however, it is rewritten in C++ to facilitate the development on manycore architectures. The C source code of for instance plugins to the Squeak VM has been reused directly. This code is located in /src/from squeak/. The support for x86 compatible multicore systems is currently based on POSIX threads. Thus, the RoarVM can be started with a number of threads which are executed on distinct processor cores. On Tilera TILE64-based systems, the iLib library is used and for each processor core a separate processes is started which executes an interpreter instance each. For both architectures, the VM provides the illusion of a single object heap, spanning all of the cores, to the Smalltalk user. Smalltalk processes are scheduled by a single scheduler on the available processor cores, and thus, the processes can execute in parallel. For synchronization, the standard Smalltalk mechanisms are available. Semaphores as well as mutexes work as in classical systems. Currently, the RoarVM uses a single central scheduler which is based on the design of Pallas[2]. Its data structures are accessible from the image and only require minimal modifications to the image, since the do not change the general model of execution. A distinct feature of the RoarVM is its use of an object table. It was introduced to reduce the necessary complexity to enable object migration between heaps on manycore architectures. TODO: add some remarks on the heap structure License ------- Copyright (c) 2008 - 2010 IBM Corporation and others. All rights reserved. This RoarVM and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at: http://www.eclipse.org/legal/epl-v10.html All parts directly taken over from the original Squeak source code are licensed under their original licenses. Credits ------- Since the RoarVM is based on the work which has been done for Squeak, we would like to acknowledge the Squeak community as a whole for its valuable work. The RoarVM was designed and implemented as 'Renaissance VM' by David Ungar and Sam Adams at IBM Research. It was ported to x86 compatible multicore systems by Stefan Marr at the Software Languages Lab, Vrije Universiteit Brussel. Special thanks go to Max OrHai for designing our logo. ================================================ FILE: image.st/RVM-multicore-support.mvc.st ================================================ '****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************'! DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine destFormSema' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'! Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name hostCore coreMask' classVariableNames: 'SemaForSuspensions' poolDictionaries: '' category: 'Kernel-Processes'! Object subclass: #RVMPrimitives instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Support'! Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess EmergencyProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'! FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1 interlock' classVariableNames: 'Registry' poolDictionaries: '' category: 'System-Files'! View subclass: #StandardSystemView instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes displayInterlock' classVariableNames: 'CacheBits LabelStyle' poolDictionaries: '' category: 'ST80-Support'! Object subclass: #Mutex instanceVariableNames: 'semaphore owner' classVariableNames: '' poolDictionaries: '' category: 'RVM-Support'! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 11/25/2008 00:23'! activePriority "Answer the priority level of the currently running Process." ^self thisProcess priority! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 9/16/2010 14:53'! preemptedProcess "Return the process that the currently active process just preempted." | list listWithoutMe | self thisProcess priority to: 1 by: -1 do:[:priority| list := quiescentProcessLists at: priority. "RVM keeps running processes on the lists -- dmu 9/16/10" listWithoutMe := list reject: [:p | p == Processor thisProcess]. listWithoutMe isEmpty ifFalse:[^listWithoutMe last]. ]. ^nil "Processor preemptedProcess"! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'dmu 11/25/2008 00:23'! terminateActive "Terminate the process that is currently running." self thisProcess terminate! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:39'! areRunningProcessesInSchedulerLists "Our RVM follows Pallas' MS system and keeps runnable processes in the scheduler lists even when running." ^RVMPrimitives isRVM! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 11/25/2008 00:26'! isActive: aProcess ^ aProcess suspendedContext == nil! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:32'! thisProcess ^ RVMPrimitives thisProcess! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 3/22/2010 13:03'! yieldIfFewerCoresThan: n RVMPrimitives coreCount < n ifTrue: [self yield]! ! !Project class methodsFor: 'utilities' stamp: 'dmu 11/25/2008 00:24'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor thisProcess suspend]! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/8/2010 23:41'! breakpoint self primitiveFailed! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:02'! printExecutionTrace ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printOnConsole: aString "Prints a string onto the console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:00'! printStack "Prints Smalltalk stack to console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printVMStatistics ! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:04'! sampleRVM "Grab some data from the VM and return it" "RVMPrimitives sampleRVM" ^ nil! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'sm 10/27/2010 22:09'! getMainRank "Get a sample from the VM and read out the main rank" | sample | sample := self sampleRVM. ^ ((sample at: 6) at: 2) at: 6! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:40'! sampleSpecificData: flags "Grab some data from the VM and return it" "Bit offsets for flags; bit 0 is 1, bit 1 is 2, bit 2 is 4, etc. allCores, // 0 runMask, messageNames, cpuCoreStats, allCoreStats, fence, millisecs, // 6 cycles, messageStats, memorySystemStats, interpreterStats, objectTableStats, interactionStats, coreCoords, // 14 sendTallies, receiveTallies, bufferedMessageStats, receiveCycles, // memory system gcStats, // 19 heapStats, // interpreter bytecodes, // 20 yieldCount, cycleCounts, interruptChecks, movedMutatedObjectStats, mutexStats, interpreterLoopStats // 26" ^ nil! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:58'! moveAllToReadMostlyHeaps "Move all objects into read-mostly heaps" self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:55'! shuffleToHeapsFrom: firstHeap to: lastHeap "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:56'! shuffleToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:30'! for: anObject setRankTo: rank self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:31'! for: anObject setRankTo: rank isReadWrite: isRW self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:17'! getCoreOf: anObject "RVMPrimitives getCoreOf: 2@3" ^ -1! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:47'! getMutabilityOf: anObject "Return true if argument is in a read/write heap, false if in read-mostly heap" ^ true! ! !RVMPrimitives class methodsFor: 'enumerating a heap' stamp: 'dmu 6/8/2010 23:10'! allObjectsInHeap: rank isReadWrite: trueForReadWriteFalseForReadMostly "return array of all objects in either read/write or read-mostly heap specified by rank and trueForReadWriteFalseForReadMostly" "RVMPrimitives allObjectsInHeap: 0 isReadWrite: true" ^ nil! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:18'! getCoreIAmRunningOn "RVMPrimitives getCoreIAmRunningOn" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:44'! getRunMask "Return an integer with ones corresponding to cores RVM is allowed to use: 1 means core 0, 3 means cores 0 and 1, etc." "RVMPrimitives getRunMask printStringBase: 16" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:07'! getRunningProcessesByCore "Returns array of running processes, indexed by core (+1)" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:46'! setRunMask: anInteger "Sets run mask to argument and returns old run mask. Only cores set in run mask will be used to run Smalltalk processes." "RVMPrimitives setRunMask: 1" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:04'! thisProcess "Return the process that is running; RVM does not use ActiveProcess for this state, since many may be running" ^ Processor activeProcess! ! !RVMPrimitives class methodsFor: 'cores' stamp: 'dmu 6/8/2010 23:11'! coreCount "RVMPrimitives coreCount" ^ 1! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:25'! getCoreTrace "RVMPrimitives getCoreTrace" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:26'! getMutatedReplicatedObjectsTrace ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:22'! startCoreTrace: size "RVMPrimitives startCoreTrace: 1000" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:27'! startMutatedReplicatedObjectsTrace: size ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/8/2010 23:19'! getEmergencySemaphore "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives getEmergencySemaphore" ! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/9/2010 00:06'! setEmergencySemaphore: aSema "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives setEmergencySemaphore: Semaphore new" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! getExtraPreheaderWordOf: anObject "Returns the extra preheader word of the argument." "RVMPrimitives getExtraPreheaderWordOf: 3@4" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! setExtraPreheaderWordOf: anObject to: newContents "Sets the extra preheader word of the first argument." "|n| n := 3@4. RVMPrimitives setExtraPreheaderWordOf: n to: 17. RVMPrimitives getExtraPreheaderWordOf: n" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/9/2010 00:05'! setExtraWordSelector: aSelector "returns the old one" ^self primitiveFailed! ! !RVMPrimitives class methodsFor: 'testing' stamp: 'dmu 6/14/2010 15:36'! isRVM "RVMPrimitives isRVM" ^ (self getCoreOf: nil) ~= -1! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 6/14/2010 16:14'! valueAt: blockPriority "Evaluate the receiver (block), with another priority as the actual one and restore it afterwards. The caller should be careful with using higher priorities." | activeProcess result outsidePriority | activeProcess := Processor thisProcess. outsidePriority := activeProcess priority. activeProcess priority: blockPriority. result := self ensure: [activeProcess priority: outsidePriority]. "Yield after restoring lower priority to give the preempted processes a chance to run." blockPriority > outsidePriority ifTrue: [Processor yield]. ^ result! ! !BlockContext methodsFor: 'private' stamp: 'dmu 11/25/2008 00:18'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !CPUWatcher methodsFor: 'process operations' stamp: 'dmu 11/25/2008 00:18'! debugProcess: aProcess | uiPriority oldPriority | uiPriority := Processor thisProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority := ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! inActiveControllerProcess "Answer whether the active scheduling process is the actual active process in the system." ^activeControllerProcess == Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! resetActiveController "When saving a morphic project whose parent is mvc, we need to set this up first" activeController := nil. activeControllerProcess := Processor thisProcess. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! scheduleActiveNoTerminate: aController "Make aController be the active controller. Presumably the process that requested the new active controller wants to keep control to do more activites before the new controller can take control. Therefore, do not terminate the currently active process." self schedulePassive: aController. self scheduled: aController from: Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! searchForActiveController "Find a scheduled controller that wants control and give control to it. If none wants control, then see if the System Menu has been requested." | aController | activeController := nil. activeControllerProcess := Processor thisProcess. self activeController: self nextActiveController. Processor terminateActive! ! !Cursor methodsFor: 'displaying' stamp: 'dmu 6/14/2010 16:15'! showWhile: aBlock "While evaluating the argument, aBlock, make the receiver be the cursor shape." "ar 2/2/2006: Only allow this if active process is ui process" | oldcursor | Processor thisProcess == Project uiProcess ifFalse:[^aBlock value]. oldcursor := Sensor currentCursor. self show. ^aBlock ensure: [oldcursor show] ! ! !Paragraph methodsFor: 'RVM' stamp: 'dmu 6/15/2010 11:36'! destFormSema: s destFormSema := s! ! !Paragraph methodsFor: 'private' stamp: 'ssa 4/7/2009 12:39'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | destFormSema isNil ifTrue:[self destFormSema: Semaphore forMutualExclusion]. destFormSema critical: [ saveDestinationForm _ destinationForm. self destinationForm: aDisplayMedium. self displayLines: lineInterval. destinationForm _ saveDestinationForm ]! ! !Process methodsFor: 'accessing' stamp: 'ssa 2/17/2009 22:34'! isActiveProcess ^ Processor areRunningProcessesInSchedulerLists ifTrue: [ suspendedContext isNil and:[myList notNil]] ifFalse: [self == Processor activeProcess]! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/14/2010 16:16'! run "Suspend current process and execute self instead" | proc | proc := Processor thisProcess. [ proc suspend. self resume. ] forkAt: Processor highestPriority! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:44'! suspend "Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes." self isActiveProcess ifTrue: [ self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ myList ifNotNil: [ myList remove: self ifAbsent: []. myList := nil]. ] ! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:45'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock | self == Processor thisProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ unwindBlock := ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ self suspend. myList ifNotNil: [ myList remove: self ifAbsent: []. myList := nil]. suspendedContext ifNotNil: [ ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" self suspend. ^ suspendedContext := suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:01'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | self suspend. ctxt := suspendedContext. suspendedContext := nil. "disable this process while running its stack in active process below" pair := ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext := pair first. error := pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:06'! install: aContext "Replace the suspendedContext with aContext." (Processor isActive: self) ifTrue: [^self error: 'An active process cannot install contexts']. suspendedContext := aContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:07'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:08'! popTo: aContext value: aValue "Replace the suspendedContext with aContext, releasing all contexts between the currently suspendedContext and it." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ self]. "aContext is on top" self return: callee value: aValue! ! !Process class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 15:11'! semaForSuspensions SemaForSuspensions isNil ifTrue:[SemaForSuspensions := Semaphore forMutualExclusion]. ^SemaForSuspensions! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. Transcript cr; show: 'launching debugger'. Debugger openOn: self context: context label: title contents: nil fullView: bool. ! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debugWithTitle: title "Open debugger on self" | context | context := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. self debug: context title: title full: true. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:31'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self == Processor thisProcess ifFalse: [^self]. self suspend. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'dmu 6/14/2010 16:11'! signalException: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" | oldList | "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. "Suspend myself first to ensure that I won't run away in the midst of the following modifications." myList ifNotNil:[oldList := self suspend]. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class lookupSelector: #pvtSignal:list:) arguments: (Array with: anException with: oldList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" oldList ifNotNil: [self resume]. ! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask ^ coreMask! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask: m coreMask := m! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:41'! hostCore ^ hostCore! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:31'! isRunning Processor thisProcess == self ifTrue: [^ true]. self isActiveProcess ifTrue: [^ true]. myList ifNil: [^ false]. ^ myList class ~~ Semaphore! ! !Process methodsFor: 'RVM' stamp: 'ssa 3/2/2010 18:23'! nilMyListUnlessRVM Processor areRunningProcessesInSchedulerLists ifFalse: [ "primitiveSuspend will use myList to remove from list and will nil it out" myList := nil. ]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'dmu 6/14/2010 16:17'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight := stackList at: stackListIndex]. selectedProcess == Processor thisProcess ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext := selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'ssa 6/11/2010 14:35'! nameAndRulesFor: aProcess "Answer a nickname and two flags: allow-stop, and allow-debug" ^ [aProcess caseOf: { [ProcessorScheduler emergencyProcess] -> [{'emergency evaluator ShftCtrl-A'. false. true}]. [] -> [{'no process'. false. false}]. [Smalltalk lowSpaceWatcherProcess] -> [{'the low space watcher'. false. false}]. [WeakArray runningFinalizationProcess] -> [{'the WeakArray finalization process'. false. false}]. [Processor thisProcess] -> [{'the UI process'. false. true}]. [Processor backgroundProcess] -> [{'the idle process'. false. false}]. [Sensor interruptWatcherProcess] -> [{'the user interrupt watcher'. false. false}]. [Sensor eventTicklerProcess] -> [{'the event tickler'. false. false}]. [Project uiProcess] -> [{'the inactive Morphic UI process'. false. false}]. [Smalltalk at: #SoundPlayer ifPresent: [:sp | sp playerProcess]] -> [{'the Sound Player'. false. false}]. [ScheduledControllers ifNotNil: [ScheduledControllers activeControllerProcess]] -> [{'the inactive MVC controller process'. false. true}]. [Smalltalk at: #CPUWatcher ifPresent: [:cw | cw currentWatcherProcess]] -> [{'the CPUWatcher'. false. false}]} otherwise: [(aProcess priority = Processor timingPriority and: [aProcess suspendedContext receiver == Delay]) ifTrue: [{'the timer interrupt watcher'. false. false}] ifFalse: [{aProcess suspendedContext asString. true. true}]]] ifError: [:err :rcvr | {aProcess suspendedContext asString. true. true}]! ! !Paragraph reorganize! ('accessing' backgroundColor clippingRectangle clippingRectangle: compositionRectangle compositionRectangle: destinationForm fillColor fillColor: height indentationOfLineIndex:ifBlank: mask numberOfLines replaceFrom:to:with:displaying: rule rule: stringAtLineNumber: text:) ('alignment' centered justified leftFlush rightFlush toggleAlignment) ('character location' characterBlockAtPoint: characterBlockForIndex: defaultCharacterBlock) ('composition' composeAll wrappingBox:clippingBox:) ('converting' asForm asString asText) ('display box access' boundingBox computeBoundingBox) ('displaying' displayOn: displayOn:at: displayOn:at:clippingBox:rule:fillColor: displayOn:transformation:clippingBox:align:with:rule:fillColor:) ('indicating' flash outline) ('scrolling' scrollBy: scrollBy:withSelectionFrom:to: scrollDelta scrollUncheckedBy:withSelectionFrom:to:) ('selecting' caretFormForDepth: clickAt:for:controller: extendSelectionAt:endBlock: extendSelectionMark:pointBlock: hiliteRect: mouseMovedFrom:pivotBlock:showingCaret: mouseSelect mouseSelect: reverseFrom:to: selectionRectsFrom:to:) ('utilities' clearVisibleRectangle deepCopy destinationForm: fit lines: visibleRectangle) ('RVM' destFormSema:) ('private' bottomAtLineIndex: compositionRectangle:text:style:offset: compositionRectangleDelta displayLines: displayLines:affectedRectangle: displayOn:lines: leftMarginForCompositionForLine: leftMarginForDisplayForLine:alignment: lineAt:put: lineIndexOfCharacterIndex: lineIndexOfTop: lines moveBy: rightMarginForComposition rightMarginForDisplay setWithText:style: setWithText:style:compositionRectangle:clippingRectangle: setWithText:style:compositionRectangle:clippingRectangle:foreColor:backColor: topAtLineIndex: topAtLineIndex:using:and: trimLinesTo: updateCompositionHeight withClippingRectangle:do:) ! !BitBlt methodsFor: 'accessing' stamp: 'dmu 4/4/2009 00:24'! copyBitsOnMain "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 4/4/2009 00:20'! copyBitsLocally "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/3/2009 23:01'! drawLoopLocallyX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | | self primitiveFailed! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:36'! globalDrawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | dx _ xDelta sign. dy _ yDelta sign. px _ yDelta abs. py _ xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P _ py // 2. 1 to: py do: [:i | destX _ destX + dx. (P _ P - px) < 0 ifTrue: [destY _ destY + dy. P _ P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P _ px // 2. 1 to: px do: [:i | destY _ destY + dy. (P _ P - py) < 0 ifTrue: [destX _ destX + dx. P _ P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:52'! localDrawLoopX: xDelta Y: yDelta "Primitive" ^self primitiveFailed! ! !ControlManager methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:14'! activeControllerNoTerminate: aController andProcess: aProcess "Set aController to be the currently active controller and aProcess to be the process that handles controller scheduling activities in the system. This message differs from activeController:andProcess: in that it does not send controlTerminate to the currently active controller." self inActiveControllerProcess ifTrue: [aController~~nil ifTrue: [(scheduledControllers includes: aController) ifTrue: [self promote: aController] ifFalse: [self error: 'Old controller not scheduled']]. activeController _ aController. activeController == nil ifFalse: [activeController controlInitialize]. activeControllerProcess _ aProcess. activeControllerProcess resume] ifFalse: ['New active controller process must be set from old one, resetting...' print. self reset. ] ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/2/2010 14:12'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | suspendingList newActiveController | (suspendingList _ activeControllerProcess suspendingList) == nil ifTrue: [activeControllerProcess == Processor thisProcess ifTrue: [activeControllerProcess suspend]] ifFalse: [suspendingList remove: activeControllerProcess ifAbsent:[]. activeControllerProcess offList]. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController _ (Debugger openInterrupt: labelString onProcess: activeControllerProcess) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/25/2010 16:17'! reset "ssa - reset the window controller process" | newProcess | newProcess := [ScheduledControllers resetActiveController. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process" "Processor terminateActive"! ! !Controller methodsFor: 'basic control sequence' stamp: 'dmu 3/22/2010 14:25'! interActivityPause "if we are looping quickly, insert a short delay. Thus if we are just doing UI stuff, we won't take up much CPU" | currentTime wait | [RVMPrimitives isRVM ifTrue: [Processor yield. ^ self].]. MinActivityLapse ifNotNil: [ lastActivityTime ifNotNil: [ currentTime _ Time millisecondClockValue. wait _ lastActivityTime + MinActivityLapse - currentTime. wait > 0 ifTrue: [ wait <= MinActivityLapse "big waits happen after a snapshot" ifTrue: [DisplayScreen checkForNewScreenSize. "(Delay forMilliseconds: wait) wait "]. ]. ]. ]. lastActivityTime _ Time millisecondClockValue.! ! !EventSensor methodsFor: 'accessing' stamp: 'ssa 12/17/2009 12:30'! nextEvent "Return the next event from the receiver." eventQueue == nil ifTrue:[^self nextEventSynthesized] ifFalse:[^self nextEventFromQueue] ! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 6/21/2004 10:42'! startUp "Run the I/O process" self initialize. self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/17/2009 14:18'! flushNonKbdEvents eventQueue ifNil: [^ self]. [^self]value. "don't flush so we don't lose events" eventQueue flushAllSuchThat: [:buf | (self isKbdEvent: buf) not] ! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:42'! nextEventFromQueue "Return the next event from the receiver." eventQueue isEmpty ifTrue:[self fetchMoreEvents]. eventQueue isEmpty ifTrue:[^nil] ifFalse:[^eventQueue next]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/17/2004 07:09'! nextEventSynthesized "Return a synthesized event. This method is called if an event driven client wants to receive events but the primary user interface is not event-driven (e.g., the receiver does not have an event queue but only updates its state). This can, for instance, happen if a Morphic World is run in an MVC window. To simplify the clients work this method will always return all available keyboard events first, and then (repeatedly) the mouse events. Since mouse events come last, the client can assume that after one mouse event has been received there are no more to come. Note that it is impossible for EventSensor to determine if a mouse event has been issued before so the client must be aware of the possible problem of getting repeatedly the same mouse events. See HandMorph>>processEvents for an example on how to deal with this." | kbd array buttons pos modifiers mapped | "First check for keyboard" array _ Array new: 8. kbd _ self primKbdNext. kbd ifNotNil: ["simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^ array]. "Then check for mouse" pos _ self primMousePt. buttons _ mouseButtons. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ array ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMouseButtons self fetchMoreEvents. self flushNonKbdEvents. ^ mouseButtons ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMousePt self fetchMoreEvents. self flushNonKbdEvents. ^ mousePosition ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 12:46'! processEvent: evt "Process a single event. This method is run at high priority." | type | type := evt at: 1. "Tackle mouse events first" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1). self queueEvent: evt. self processMouseEvent: evt . ^self]. "Store the event in the queue if there's any" type = EventTypeKeyboard ifTrue: [ "Check if the event is a user interrupt" ((evt at: 4) = 0 and: [((evt at: 3) bitOr: (((evt at: 5) bitAnd: 8) bitShift: 8)) = interruptKey]) ifTrue: ["interrupt key is meta - not reported as event" ^ interruptSemaphore signal]. "Else swap ctrl/alt keys if neeeded.wi" KeyDecodeTable at: {evt at: 3. evt at: 5} ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]. self queueEvent: evt. self processKeyboardEvent: evt . ^self ]. "Handle all events other than Keyborad or Mouse." self queueEvent: evt. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/16/2009 13:12'! processKeyboardEvent: evt "process a keyboard event, updating InputSensor state" | charCode pressCode | "Never update keyboardBuffer if we have an eventQueue active" mouseButtons _ (mouseButtons bitAnd: 7) bitOr: ((evt at: 5) bitShift: 3). eventQueue ifNotNil:[^self]. charCode _ evt at: 3. charCode = nil ifTrue:[^self]. "extra characters not handled in MVC" pressCode _ evt at: 4. pressCode = EventKeyChar ifFalse:[^self]. "key down/up not handled in MVC" "mix in modifiers" charCode _ charCode bitOr: ((evt at: 5) bitShift: 8). keyboardBuffer nextPut: charCode .! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:38'! forkOn: aCore "Create and schedule a Process running the code in the receiver." ^ self newProcess resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:09'! forkOn: aCore with: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:08'! forkOn: aCore with: anObject at: aPriority "Create and schedule a Process running the code in the receiver." | proc | proc _ self newProcessWith: anObject. proc priority: aPriority. ^proc resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:34'! forkWith: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:33'! newProcessWith: anObject "Answer a Process running the code in the receiver. The process is not scheduled." "Simulation guard" ^Process forContext: [self value: anObject. Processor terminateActive] priority: Processor activePriority! ! !Delay class methodsFor: 'snapshotting' stamp: 'dmu 5/25/2010 11:02'! startUp "Restart active delay, if any, when resuming a snapshot." self restoreResumptionTimes. ActiveDelay == nil ifFalse: [ActiveDelay activate]. AccessProtect _ Semaphore forMutualExclusion ! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! hostCore: anObject "Set the value of hostCore" hostCore _ anObject! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList "Answer the value of myList" myList isNil ifTrue:[self myList: nil]. ^ myList! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList: anObject "Set the value of myList" myList _ anObject! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/2/2010 17:02'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." "Debugging code below causes terminated running processes to seem not terminated. -- dmu 3/2/10" "(myList isNil and: [RVMPrimitives isRVM]) ifTrue:[self halt]." self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:44'! resume "Allow the process that the receiver represents to continue. Put the receiver in line to become the activeProcess. Check for a nil suspendedContext, which indicates a previously terminated Process that would cause a vm crash if the resume attempt were permitted" suspendedContext ifNil: [^ self primitiveFailed]. ^ self primitiveResume! ! !Process methodsFor: 'changing process state' stamp: 'dmu 4/7/2009 02:41'! resumeOn: aCore self useOnlyCore: aCore. self resume! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." self suspend. suspendedContext == aContext ifTrue: [ ^ suspendedContext _ aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:03'! step self suspend. ^ suspendedContext _ suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! stepToCallee "Step until top context changes" | ctxt | self suspend. ctxt _ suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext _ suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! stepToSendOrReturn self suspend. ^ suspendedContext _ suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:57'! avoidCore: anIndex "Force this process to avoid this core (0-55)" self coreMask: (self coreMask bitClear: (1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:49'! avoidCores: aCollectionOfIndicies "Force this process to avoid these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitClear:mask)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:59'! useAdditionalCore: anIndex "Force this process to only urn on this core (0-55)" self coreMask: (self coreMask bitOr:(1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:50'! useAdditionalCores: aCollectionOfIndicies "Allow this process to run on these additional cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitOr:mask)! ! !Process methodsFor: 'core assignment' stamp: 'dmu 5/5/2009 01:32'! useOnlyCore: anIndex "Force this process to only run on this core (0-55)" self coreMask: (1 bitShift: anIndex)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:02'! useOnlyCores: aCollectionOfIndicies "Force this process to only run on these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: mask! ! !Process methodsFor: 'core assignment' stamp: 'dmu 1/25/2010 11:06'! useOnlyMainCore RVMPrimitives isRVM ifTrue: [self useOnlyCore: (RVMPrimitives getMainRank)]! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:30'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. self suspend. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! !Process class methodsFor: 'instance creation' stamp: 'dmu 3/24/2010 15:46'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess _ self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. [newProcess coreMask:(1 bitShift: 27)]. ^newProcess! ! !Process class methodsFor: 'instance creation' stamp: 'ssa 2/26/2009 02:45'! forContext: aContext priority: anInteger coreMask: anIntegerMask "Answer an instance of me that has suspended aContext at priority anInteger using this coreMask." | newProcess | newProcess _ self forContext: aContext priority: anInteger. newProcess coreMask:anIntegerMask. ^newProcess! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:37'! removeAllPossible "Terminate and remove all processes that you can. This should leave the standard set only" self terminatableProcesses print do:[:proc| proc terminate]! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:31'! terminatableProcesses "Answer all current processes that may be user terminated like in the ProcessBrowser" "self terminatableProcesses" | processList | Smalltalk garbageCollectMost. "lose defunct processes" processList _ Process allSubInstances reject: [:each | each isTerminated]. processList _ processList sortBy: [:a :b | a priority >= b priority]. processList _ WeakArray withAll: processList. ^processList select:[:proc| (ProcessBrowser nameAndRulesFor: proc) at: 2]! ! !Project methodsFor: 'menu messages' stamp: 'dmu 11/25/2008 00:23'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject _ self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World _ world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World _ nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess _ Processor thisProcess. ! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock interlock ifNil: [self interlock: Semaphore forMutualExclusion]. ^ interlock! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock: aSemaphore interlock _ aSemaphore! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetInterlock self interlock signal. self interlock: nil! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:09'! safelyDo: aBlock ^ self interlock critical: aBlock! ! !StandardFileStream class methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetAllInterlocks "self resetAllInterlocks" self allSubInstancesDo: [:sfs| sfs resetInterlock]! ! !RemoteString methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:19'! text "Answer the receiver's string asText if remote files are enabled." | theFile theText | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile _ SourceFiles at: sourceFileNumber. theFile safelyDo: [ theFile position: filePositionHi. theText _ theFile nextChunkText]. ^theText! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:25'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | "Simulation guard" topView _ self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor thisProcess suspend. ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:26'! snapshot: save andQuit: quit embedded: embeddedFlag "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. The latter part of this method runs when resuming a previously saved image. The resume logic checks for a document file to process when starting up." | resuming msg sourceLink | Object flushDependents. Object flushEvents. save & (SourceFiles at: 2) notNil ifTrue: [msg _ (quit ifTrue: ['----QUIT----'] ifFalse: ['----SNAPSHOT----']) , Date dateAndTimeNow printString, ' ', (FileDirectory default localNameFor: self imageName). sourceLink _ ' priorSource: ' , LastQuitLogPosition printString. self assureStartupStampLogged. (SourceFiles at: 2) safelyDo: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position. self logChange: msg , sourceLink. ]. Transcript cr; show: msg]. self processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [self clearExternalObjects]. self processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !UnhandledError methodsFor: 'priv handling' stamp: 'dmu 11/25/2008 00:25'! devDefaultAction Processor thisProcess debug: exception signalerContext title: exception description! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: false. self displayLabelText. ]! ! Cursor initialize! Controller initialize! !BitBlt methodsFor: 'copying' stamp: 'ssa 4/7/2009 13:44'! OLDcopyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 5/10/2009 08:43'! copyBits RVMPrimitives isRVM ifFalse:[^self OLDcopyBits]. destForm == Display ifTrue: [self copyBitsOnMain] ifFalse: [self copyBitsLocally]! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards _ (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 _ startPoint. point2 _ stopPoint] ifFalse: [point1 _ stopPoint. point2 _ startPoint]. sourceForm == nil ifTrue: [destX _ point1 x. destY _ point1 y] ifFalse: [width _ sourceForm width. height _ sourceForm height. offset _ sourceForm offset. destX _ (point1 x + offset x) rounded. destY _ (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. (destForm == Display or:[RVMPrimitives isRVM not]) ifTrue: [ self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded] ifFalse: [self drawLoopLocallyX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded]. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." ^(destForm == Display or:[RVMPrimitives isRVM not]) ifTrue:[self globalDrawLoopX:xDelta Y: yDelta ] ifFalse:[self localDrawLoopX:xDelta Y: yDelta ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:17'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr | (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance classCommented: self. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr _ self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr _ oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file _ SourceFiles at: 2) ifNotNil: [ file safelyDo: [ file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header _ String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance classCommented: self. ! ! !CompiledMethod methodsFor: 'source code management' stamp: 'dmu 9/7/2010 14:23'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString st80str | (SourceFiles == nil or: [(file _ SourceFiles at: fileIndex) == nil]) ifTrue: [^ self become: (self copyWithTempNames: methodNode tempNames)]. SmalltalkImage current assureStartupStampLogged. file safelyDo: [ file setToEnd. preambleBlock value: file. "Write the preamble" (methodNode isKindOf: DialectMethodNode) ifTrue: ["This source was parsed from an alternate syntax. We must convert to ST80 before logging it." st80str _ (DialectStream dialect: #ST80 contents: [:strm | methodNode printOn: strm]) asString. remoteString _ RemoteString newString: st80str onFileNumber: fileIndex toFile: file] ifFalse: [remoteString _ RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file]. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex ]! ! !RemoteString methodsFor: 'private' stamp: 'dmu 9/7/2010 14:23'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile _ SourceFiles at: fileNumber. theFile safelyDo: [ theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile] ]! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'dmu 9/7/2010 14:26'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes _ SourceFiles at: 2. changes safelyDo: [ changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aStringOrText isText ifTrue: [aString _ aStringOrText string] ifFalse: [aString _ aStringOrText]. (aString isMemberOf: String) ifFalse: [self error: 'can''t log this change']. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile _ SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile _ SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp _ nil. self forceChangesToDisk. ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:22'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble _ self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble _ '']. method _ self methodDict at: selector. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos _ method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: (self decompilerClass new decompile: selector in: self method: method) decompileString] ifFalse: [sourceFile _ SourceFiles at: method fileIndex. sourceFile safelyDo: [ sourceFile position: oldPos. preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile]. "Copy the method chunk" newPos _ outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "[" "The following chunk may have ]style[" "]" sourceFile peek == "[" $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos _ outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'dmu 9/7/2010 14:12'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" StandardFileStream resetAllInterlocks. SourceFiles _ self new initialize! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 9/17/2010 11:02'! userBackgroundPriority ^ UserBackgroundPriority! ! !Process methodsFor: 'RVM' stamp: 'dmu 9/17/2010 11:59'! suspendedContextWaitingIfNecessary "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." [self suspendedContext isNil] whileTrue. ^ self suspendedContext! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'dmu 9/17/2010 12:00'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector _ evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig _ evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context _ guineaPig suspendedContextWaitingIfNecessary. debugger _ Debugger new process: guineaPig controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: context isolationHead: nil. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:37'! displayInterlock displayInterlock ifNil: [self displayInterlock: Mutex new]. ^ displayInterlock! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:24'! displayInterlock: aSemaphore displayInterlock _ aSemaphore! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:31'! displayEmphasized "Display with label highlighted to indicate that it is active." self critical: [ self displayDeEmphasized; emphasize. isLabelComplemented _ true ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:30'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self critical: [ (bitsValid and: [controller ~~ ScheduledControllers activeController]) ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [Display deferUpdates: true. super display. Display deferUpdates: false; forceToScreen: self windowBox. CacheBits ifTrue: [self cacheBitsAsIs]] ] ! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:37'! critical: aBlock ^self displayInterlock critical: aBlock! ! !Mutex commentStamp: ''! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !Mutex methodsFor: 'initialize' stamp: 'das 11/3/2005 22:53'! initialize semaphore := Semaphore forMutualExclusion.! ! !Mutex methodsFor: 'mutual exclusion' stamp: 'dmu 6/14/2010 16:16'! critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess | activeProcess := Processor thisProcess. activeProcess == owner ifTrue:[^aBlock value]. ^semaphore critical:[ owner := activeProcess. aBlock ensure:[owner := nil]].! ! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: true. self displayLabelBoxes. self displayLabelText. ]! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:47'! resetDisplayInterlock self displayInterlock: nil! ! !ControlManager methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:48'! restore "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." scheduledControllers first view uncacheBits. "assure refresh" self unschedule: screenController; scheduleOnBottom: screenController. screenController view window: Display boundingBox; displayDeEmphasized. self scheduledWindowControllers reverseDo: [:aController | aController view resetDisplayInterlock; displayDeEmphasized]. ! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'dmu 9/17/2010 16:39'! handleUserInterrupt Preferences cmdDotEnabled ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] forkAt: Processor thisProcess priority + 1]]! ! ================================================ FILE: image.st/RVM-multicore-support.pharo.st ================================================ '****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************'! DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine destFormSema' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'! Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name env hostCore coreMask' classVariableNames: 'SemaForSuspensions' poolDictionaries: '' category: 'Kernel-Processes'! Object subclass: #RVMPrimitives instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Support'! Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess EmergencyProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'! FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1 interlock' classVariableNames: 'Registry' poolDictionaries: '' category: 'Files-Kernel'! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 11/25/2008 00:23'! activePriority "Answer the priority level of the currently running Process." ^self thisProcess priority! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 9/16/2010 14:53'! preemptedProcess "Return the process that the currently active process just preempted." | list listWithoutMe | self thisProcess priority to: 1 by: -1 do:[:priority| list := quiescentProcessLists at: priority. "RVM keeps running processes on the lists -- dmu 9/16/10" listWithoutMe := list reject: [:p | p == Processor thisProcess]. listWithoutMe isEmpty ifFalse:[^listWithoutMe last]. ]. ^nil "Processor preemptedProcess"! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'dmu 11/25/2008 00:23'! terminateActive "Terminate the process that is currently running." self thisProcess terminate! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:39'! areRunningProcessesInSchedulerLists "Our RVM follows Pallas' MS system and keeps runnable processes in the scheduler lists even when running." ^RVMPrimitives isRVM! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 11/25/2008 00:26'! isActive: aProcess ^ aProcess suspendedContext == nil! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:32'! thisProcess ^ RVMPrimitives thisProcess! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 3/22/2010 13:03'! yieldIfFewerCoresThan: n RVMPrimitives coreCount < n ifTrue: [self yield]! ! !Project class methodsFor: 'utilities' stamp: 'dmu 11/25/2008 00:24'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor thisProcess suspend]! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/8/2010 23:41'! breakpoint self primitiveFailed! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:02'! printExecutionTrace ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printOnConsole: aString "Prints a string onto the console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:00'! printStack "Prints Smalltalk stack to console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printVMStatistics ! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:04'! sampleRVM "Grab some data from the VM and return it" "RVMPrimitives sampleRVM" ^ nil! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'sm 10/27/2010 22:09'! getMainRank "Get a sample from the VM and read out the main rank" | sample | sample := self sampleRVM. ^ ((sample at: 6) at: 2) at: 6! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:40'! sampleSpecificData: flags "Grab some data from the VM and return it" "Bit offsets for flags; bit 0 is 1, bit 1 is 2, bit 2 is 4, etc. allCores, // 0 runMask, messageNames, cpuCoreStats, allCoreStats, fence, millisecs, // 6 cycles, messageStats, memorySystemStats, interpreterStats, objectTableStats, interactionStats, coreCoords, // 14 sendTallies, receiveTallies, bufferedMessageStats, receiveCycles, // memory system gcStats, // 19 heapStats, // interpreter bytecodes, // 20 yieldCount, cycleCounts, interruptChecks, movedMutatedObjectStats, mutexStats, interpreterLoopStats // 26" ^ nil! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:58'! moveAllToReadMostlyHeaps "Move all objects into read-mostly heaps" self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:55'! shuffleToHeapsFrom: firstHeap to: lastHeap "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:56'! shuffleToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:30'! for: anObject setRankTo: rank self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:31'! for: anObject setRankTo: rank isReadWrite: isRW self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:17'! getCoreOf: anObject "RVMPrimitives getCoreOf: 2@3" ^ -1! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:47'! getMutabilityOf: anObject "Return true if argument is in a read/write heap, false if in read-mostly heap" ^ true! ! !RVMPrimitives class methodsFor: 'enumerating a heap' stamp: 'dmu 6/8/2010 23:10'! allObjectsInHeap: rank isReadWrite: trueForReadWriteFalseForReadMostly "return array of all objects in either read/write or read-mostly heap specified by rank and trueForReadWriteFalseForReadMostly" "RVMPrimitives allObjectsInHeap: 0 isReadWrite: true" ^ nil! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:18'! getCoreIAmRunningOn "RVMPrimitives getCoreIAmRunningOn" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:44'! getRunMask "Return an integer with ones corresponding to cores RVM is allowed to use: 1 means core 0, 3 means cores 0 and 1, etc." "RVMPrimitives getRunMask printStringBase: 16" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:07'! getRunningProcessesByCore "Returns array of running processes, indexed by core (+1)" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:46'! setRunMask: anInteger "Sets run mask to argument and returns old run mask. Only cores set in run mask will be used to run Smalltalk processes." "RVMPrimitives setRunMask: 1" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:04'! thisProcess "Return the process that is running; RVM does not use ActiveProcess for this state, since many may be running" ^ Processor activeProcess! ! !RVMPrimitives class methodsFor: 'cores' stamp: 'dmu 6/8/2010 23:11'! coreCount "RVMPrimitives coreCount" ^ 1! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:25'! getCoreTrace "RVMPrimitives getCoreTrace" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:26'! getMutatedReplicatedObjectsTrace ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:22'! startCoreTrace: size "RVMPrimitives startCoreTrace: 1000" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:27'! startMutatedReplicatedObjectsTrace: size ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/8/2010 23:19'! getEmergencySemaphore "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives getEmergencySemaphore" ! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/9/2010 00:06'! setEmergencySemaphore: aSema "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives setEmergencySemaphore: Semaphore new" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! getExtraPreheaderWordOf: anObject "Returns the extra preheader word of the argument." "RVMPrimitives getExtraPreheaderWordOf: 3@4" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! setExtraPreheaderWordOf: anObject to: newContents "Sets the extra preheader word of the first argument." "|n| n := 3@4. RVMPrimitives setExtraPreheaderWordOf: n to: 17. RVMPrimitives getExtraPreheaderWordOf: n" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/9/2010 00:05'! setExtraWordSelector: aSelector "returns the old one" ^self primitiveFailed! ! !RVMPrimitives class methodsFor: 'testing' stamp: 'dmu 6/14/2010 15:36'! isRVM "RVMPrimitives isRVM" ^ (self getCoreOf: nil) ~= -1! ! !BlockClosure methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:13'! valueAt: blockPriority "Evaluate the receiver (block), with another priority as the actual one and restore it afterwards. The caller should be careful with using higher priorities." | activeProcess result outsidePriority | activeProcess := Processor thisProcess. outsidePriority := activeProcess priority. activeProcess priority: blockPriority. result := self ensure: [activeProcess priority: outsidePriority]. "Yield after restoring lower priority to give the preempted processes a chance to run." blockPriority > outsidePriority ifTrue: [Processor yield]. ^ result! ! !BlockClosure methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:13'! valueWithin: aDuration onTimeout: timeoutBlock "Evaluate the receiver. If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead" | theProcess delay watchdog | aDuration <= Duration zero ifTrue: [^ timeoutBlock value ]. "the block will be executed in the current process" theProcess := Processor thisProcess. delay := aDuration asDelay. "make a watchdog process" watchdog := [ delay wait. "wait for timeout or completion" theProcess ifNotNil:[ theProcess signalException: TimedOut ] ] newProcess. "Watchdog needs to run at high priority to do its job (but not at timing priority)" watchdog priority: Processor timingPriority-1. "catch the timeout signal" ^ [ watchdog resume. "start up the watchdog" self ensure:[ "evaluate the receiver" theProcess := nil. "it has completed, so ..." delay delaySemaphore signal. "arrange for the watchdog to exit" ]] on: TimedOut do: [ :e | timeoutBlock value ]. ! ! !BlockClosure methodsFor: 'private' stamp: 'dmu 6/14/2010 16:13'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !BlockContext methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:14'! valueWithin: aDuration onTimeout: timeoutBlock "Evaluate the receiver. If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead" | theProcess delay watchdog | aDuration <= Duration zero ifTrue: [^ timeoutBlock value ]. "the block will be executed in the current process" theProcess := Processor thisProcess. delay := aDuration asDelay. "make a watchdog process" watchdog := [ delay wait. "wait for timeout or completion" theProcess ifNotNil:[ theProcess signalException: TimedOut ] ] newProcess. "Watchdog needs to run at high priority to do its job (but not at timing priority)" watchdog priority: Processor timingPriority-1. "catch the timeout signal" ^ [ watchdog resume. "start up the watchdog" self ensure:[ "evaluate the receiver" theProcess := nil. "it has completed, so ..." delay delaySemaphore signal. "arrange for the watchdog to exit" ]] on: TimedOut do: [ :e | timeoutBlock value ]. ! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 6/14/2010 16:14'! valueAt: blockPriority "Evaluate the receiver (block), with another priority as the actual one and restore it afterwards. The caller should be careful with using higher priorities." | activeProcess result outsidePriority | activeProcess := Processor thisProcess. outsidePriority := activeProcess priority. activeProcess priority: blockPriority. result := self ensure: [activeProcess priority: outsidePriority]. "Yield after restoring lower priority to give the preempted processes a chance to run." blockPriority > outsidePriority ifTrue: [Processor yield]. ^ result! ! !BlockContext methodsFor: 'private' stamp: 'dmu 11/25/2008 00:18'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !CPUWatcher methodsFor: 'process operations' stamp: 'dmu 11/25/2008 00:18'! debugProcess: aProcess | uiPriority oldPriority | uiPriority := Processor thisProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority := ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !Cursor methodsFor: 'displaying' stamp: 'dmu 6/14/2010 16:15'! showWhile: aBlock "While evaluating the argument, aBlock, make the receiver be the cursor shape." "ar 2/2/2006: Only allow this if active process is ui process" | oldcursor | Processor thisProcess == Project uiProcess ifFalse:[^aBlock value]. oldcursor := Sensor currentCursor. self show. ^aBlock ensure: [oldcursor show] ! ! !Debugger class methodsFor: 'class initialization' stamp: 'dmu 6/14/2010 16:15'! openContext: aContext label: aString contents: contentsStringOrNil "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." "Simulation guard" ErrorRecursion not & self logDebuggerStackToFile ifTrue: [Smalltalk logError: aString inContext: aContext to: 'PharoDebug.log']. ErrorRecursion ifTrue:[ ErrorRecursion := false. self primitiveError: aString]. ErrorRecursion := true. self informExistingDebugger: aContext label: aString. (Debugger context: aContext) openNotifierContents: contentsStringOrNil label: aString. ErrorRecursion := false. Processor thisProcess suspend. ! ! !Debugger class methodsFor: 'instance creation' stamp: 'dmu 6/14/2010 16:15'! context: aContext "Answer an instance of me for debugging the active process starting with the given context." ^ self new process: Processor thisProcess controller: nil context: aContext! ! !DelayWaitTimeout methodsFor: 'private' stamp: 'dmu 6/14/2010 16:15'! setDelay: anInteger forSemaphore: aSemaphore super setDelay: anInteger forSemaphore: aSemaphore. process := Processor thisProcess. expired := false.! ! !HTTPLoader methodsFor: 'private' stamp: 'dmu 6/14/2010 16:15'! startDownload | newDownloadProcess | downloads size >= self maxNrOfConnections ifTrue: [^self]. requests size <= 0 ifTrue: [^self]. newDownloadProcess := [ [ self nextRequest startRetrieval ] on: FTPConnectionException do: [ :ex | Cursor normal show. self removeProcess: Processor thisProcess. self startDownload ]. self removeProcess: Processor thisProcess. self startDownload ] newProcess. downloads add: newDownloadProcess. newDownloadProcess resume! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 6/14/2010 16:16'! spyEvery: millisecs on: aBlock "Create a spy and spy on the given block at the specified rate." "Spy only on the active process (in which aBlock is run)" | myDelay time0 observedProcess | aBlock isBlock ifFalse: [ self error: 'spy needs a block here' ]. self class: aBlock receiver class method: aBlock method. "set up the probe" observedProcess := Processor thisProcess. myDelay := Delay forMilliseconds: millisecs. time0 := Time millisecondClockValue. gcStats := Smalltalk getVMParameters. Timer ifNotNil: [ self error: 'it seems a tally is already running' ]. Timer := [ [ true ] whileTrue: [ | startTime | startTime := Time millisecondClockValue. myDelay wait. self tally: Processor preemptedProcess suspendedContext in: (observedProcess == Processor preemptedProcess ifTrue: [observedProcess] ifFalse: [nil]) "tally can be > 1 if ran a long primitive" by: (Time millisecondClockValue - startTime) // millisecs]. nil] newProcess. Timer priority: Processor timingPriority-1. "activate the probe and evaluate the block" Timer resume. ^ aBlock ensure: [ "cancel the probe and return the value" "Could have already been terminated. See #terminateTimerProcess" Timer ifNotNil: [ Timer terminate. Timer := nil ]. "Collect gc statistics" Smalltalk getVMParameters keysAndValuesDo: [ :idx :gcVal | gcVal ifNotNil: [ gcStats at: idx put: (gcVal - (gcStats at: idx))]]. time := Time millisecondClockValue - time0]! ! !Monitor methodsFor: 'private' stamp: 'dmu 6/14/2010 16:16'! enter self isOwnerProcess ifTrue: [ nestingLevel := nestingLevel + 1. ] ifFalse: [ mutex wait. ownerProcess := Processor thisProcess. nestingLevel := 1. ].! ! !Monitor methodsFor: 'private' stamp: 'dmu 6/14/2010 16:16'! isOwnerProcess ^ Processor thisProcess == ownerProcess! ! !Paragraph methodsFor: 'RVM' stamp: 'dmu 6/15/2010 11:36'! destFormSema: s destFormSema := s! ! !Paragraph methodsFor: 'private' stamp: 'dmu 4/1/2009 19:38'! compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint compositionRectangle := compositionRect copy. text := aText. textStyle := aTextStyle. rule := DefaultRule. mask := nil. "was DefaultMask " marginTabsLevel := 0. destFormSema := Semaphore forMutualExclusion. destinationForm := Display. offset := aPoint. ^self composeAll! ! !Paragraph methodsFor: 'private' stamp: 'ssa 4/7/2009 12:39'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | destFormSema isNil ifTrue:[self destFormSema: Semaphore forMutualExclusion]. destFormSema critical: [ saveDestinationForm := destinationForm. self destinationForm: aDisplayMedium. self displayLines: lineInterval. destinationForm := saveDestinationForm ]! ! !Process methodsFor: 'accessing' stamp: 'ssa 2/17/2009 22:34'! isActiveProcess ^ Processor areRunningProcessesInSchedulerLists ifTrue: [ suspendedContext isNil and:[myList notNil]] ifFalse: [self == Processor activeProcess]! ! !Process methodsFor: 'accessing' stamp: 'dmu 6/18/2010 17:35'! isTerminated self isActiveProcess ifTrue: [^ false]. ^suspendedContext isNil or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. If so, and the pc is greater than the startpc, the bock has alrteady sent and returned from value and there is nothing more to do." suspendedContext isBottomContext and: [suspendedContext pc isNil or: [suspendedContext pc > suspendedContext startpc]]]! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/14/2010 16:16'! run "Suspend current process and execute self instead" | proc | proc := Processor thisProcess. [ proc suspend. self resume. ] forkAt: Processor highestPriority! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/18/2010 00:18'! suspend "Primitive. Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes. The return value of this method is the list the receiver was previously on (if any)." | oldList | "This is fallback code for VMs which only support the old primitiveSuspend which would not accept processes that are waiting to be run." RVMPrimitives isRVM ifTrue: [self error: 'suspend should never fail']. myList ifNil:[^nil]. "this allows us to use suspend multiple times" oldList := myList. myList := nil. oldList remove: self ifAbsent:[]. ^oldList! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/17/2010 23:57'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock oldList | self == Processor thisProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ (ctxt tempAt: 2) ifNil: [ ctxt tempAt: 2 put: nil. unwindBlock := ctxt tempAt: 1. thisContext terminateTo: ctxt. unwindBlock value ]]. thisContext terminateTo: nil. self suspend ] ifFalse: [ "Always suspend the process first so it doesn't accidentally get woken up" oldList := self suspend. suspendedContext ifNotNil:[ "Figure out if we are terminating the process while waiting in Semaphore>>critical: In this case, pop the suspendedContext so that we leave the ensure: block inside Semaphore>>critical: without signaling the semaphore." (oldList class == Semaphore and:[ suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[ suspendedContext := suspendedContext home.]. "If we are terminating a process halfways through an unwind, try to complete that unwind block first." (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [ :outer | (suspendedContext findContextSuchThat: [ :c | c closure == (outer tempAt: 1)]) ifNotNil: [ :inner | "This is an unwind block currently under evaluation" suspendedContext runUntilErrorOrReturnFrom: inner ]]. ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']] ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" self suspend. ^ suspendedContext := suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:01'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | self suspend. ctxt := suspendedContext. suspendedContext := nil. "disable this process while running its stack in active process below" pair := ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext := pair first. error := pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:06'! install: aContext "Replace the suspendedContext with aContext." (Processor isActive: self) ifTrue: [^self error: 'An active process cannot install contexts']. suspendedContext := aContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:07'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:08'! popTo: aContext value: aValue "Replace the suspendedContext with aContext, releasing all contexts between the currently suspendedContext and it." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ self]. "aContext is on top" self return: callee value: aValue! ! !Process class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 15:11'! semaForSuspensions SemaForSuspensions isNil ifTrue:[SemaForSuspensions := Semaphore forMutualExclusion]. ^SemaForSuspensions! ! !Process methodsFor: 'debugging' stamp: 'dmu 6/14/2010 16:09'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. UIManager default onDebug: self context: context title: title full: bool ! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debugWithTitle: title "Open debugger on self" | context | context := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. self debug: context title: title full: true. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:31'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self == Processor thisProcess ifFalse: [^self]. self suspend. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'dmu 6/14/2010 16:11'! signalException: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" | oldList | "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. "Suspend myself first to ensure that I won't run away in the midst of the following modifications." myList ifNotNil:[oldList := self suspend]. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class lookupSelector: #pvtSignal:list:) arguments: (Array with: anException with: oldList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" oldList ifNotNil: [self resume]. ! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask ^ coreMask! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask: m coreMask := m! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:41'! hostCore ^ hostCore! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:31'! isRunning Processor thisProcess == self ifTrue: [^ true]. self isActiveProcess ifTrue: [^ true]. myList ifNil: [^ false]. ^ myList class ~~ Semaphore! ! !Process methodsFor: 'RVM' stamp: 'ssa 3/2/2010 18:23'! nilMyListUnlessRVM Processor areRunningProcessesInSchedulerLists ifFalse: [ "primitiveSuspend will use myList to remove from list and will nil it out" myList := nil. ]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'dmu 6/14/2010 16:17'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight := stackList at: stackListIndex]. selectedProcess == Processor thisProcess ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext := selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ! !ProcessBrowser class methodsFor: 'class initialization' stamp: 'dmu 6/14/2010 16:17'! registerWellKnownProcesses "Associate each well-known process with a nickname and two flags: allow-stop, and allow-debug. Additional processes may be added to this list as required" WellKnownProcesses := OrderedCollection new. self registerWellKnownProcess: [] label: 'no process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Smalltalk lowSpaceWatcherProcess] label: 'the low space watcher' allowStop: false allowDebug: false. self registerWellKnownProcess: [WeakArray runningFinalizationProcess] label: 'the WeakArray finalization process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Processor thisProcess] label: 'the UI process' allowStop: false allowDebug: true. self registerWellKnownProcess: [Processor backgroundProcess] label: 'the idle process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Sensor interruptWatcherProcess] label: 'the user interrupt watcher' allowStop: false allowDebug: false. self registerWellKnownProcess: [Sensor eventTicklerProcess] label: 'the event tickler' allowStop: false allowDebug: false. self registerWellKnownProcess: [Project uiProcess] label: 'the inactive Morphic UI process' allowStop: false allowDebug: false. self registerWellKnownProcess: [ Smalltalk globals at: #SoundPlayer ifPresent: [ :sp | sp playerProcess ] ] label: 'the Sound Player' allowStop: false allowDebug: false. self registerWellKnownProcess: [ Smalltalk globals at: #CPUWatcher ifPresent: [ :cw | cw currentWatcherProcess ] ] label: 'the CPUWatcher' allowStop: false allowDebug: false ! ! !StandardToolSet class methodsFor: 'debugging' stamp: 'dmu 6/14/2010 16:17'! debugError: anError "Handle an otherwise unhandled error" ^Processor thisProcess debug: anError signalerContext title: anError description! ! !TestCase methodsFor: 'extensions' stamp: 'dmu 6/14/2010 16:18'! should: aBlock notTakeMoreThan: aDuration "Evaluate aBlock in a forked process and if it takes more than anInteger milliseconds to run we terminate the process and report a test failure. It'' important to use the active process for the test failure so that the failure reporting works correctly in the context of the exception handlers." | succeeded evaluationProcess result delay testProcess | succeeded := false. delay := Delay forDuration: aDuration. testProcess := Processor thisProcess. "Create a new process to evaluate aBlock" evaluationProcess := [ [result := aBlock value. succeeded := true.] on: Exception do: [succeeded := false] . delay unschedule. testProcess resume ] newProcess name: 'Process to evaluate should: notTakeMoreThanMilliseconds:'. evaluationProcess resume. "Wait the milliseconds they asked me to" delay wait. "After this point either aBlock was evaluated if succeeded is not still nil" succeeded ifNil: [ evaluationProcess terminate. self assert: false description: ('Block evaluation took more than the expected <1p>' expandMacrosWith: aDuration)]. "If tests in block failed, rerun block in this context, so it's handled correctly" succeeded ifFalse: [^aBlock value]. ^result! ! !SemaphoreTest methodsFor: 'private' stamp: 'dmu 6/14/2010 16:17'! criticalError Processor thisProcess terminate! ! !TestFailure methodsFor: 'camp smalltalk' stamp: 'dmu 6/14/2010 16:18'! defaultAction Processor thisProcess debug: self signalerContext title: self description! ! !Utilities class methodsFor: 'fetching updates' stamp: 'dmu 6/14/2010 16:19'! retrieveUrls: urls ontoQueue: queue withWaitSema: waitSema "download the given list of URLs. The queue will be loaded alternately with url's and with the retrieved contents. If a download fails, the contents will be #failed. If all goes well, a special pair with an empty URL and the contents #finished will be put on the queue. waitSema is waited on every time before a new document is downloaded; this keeps the downloader from getting too far ahead of the main process" "kill the existing downloader if there is one" | updateCounter | UpdateDownloader ifNotNil: [UpdateDownloader terminate]. updateCounter := 0. "fork a new downloading process" UpdateDownloader := [ 'Downloading updates' displayProgressAt: Sensor cursorPoint from: 0 to: urls size during: [:bar | urls do: [:url | | front canPeek doc | waitSema wait. queue nextPut: url. doc := HTTPClient httpGet: url. doc isString ifTrue: [queue nextPut: #failed. UpdateDownloader := nil. Processor thisProcess terminate] ifFalse: [canPeek := 120 min: doc size. front := doc next: canPeek. doc skip: -1 * canPeek. (front beginsWith: ' "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 4/4/2009 00:20'! copyBitsLocally "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/3/2009 23:01'! drawLoopLocallyX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | | self primitiveFailed! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:36'! globalDrawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | dx := xDelta sign. dy := yDelta sign. px := yDelta abs. py := xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P := py // 2. 1 to: py do: [:i | destX := destX + dx. (P := P - px) < 0 ifTrue: [destY := destY + dy. P := P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P := px // 2. 1 to: px do: [:i | destY := destY + dy. (P := P - py) < 0 ifTrue: [destX := destX + dx. P := P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:52'! localDrawLoopX: xDelta Y: yDelta "Primitive" ^self primitiveFailed! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:38'! forkOn: aCore "Create and schedule a Process running the code in the receiver." ^ self newProcess resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:09'! forkOn: aCore with: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:08'! forkOn: aCore with: anObject at: aPriority "Create and schedule a Process running the code in the receiver." | proc | proc := self newProcessWith: anObject. proc priority: aPriority. ^proc resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:34'! forkWith: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:33'! newProcessWith: anObject "Answer a Process running the code in the receiver. The process is not scheduled." "Simulation guard" ^Process forContext: [self value: anObject. Processor terminateActive] priority: Processor activePriority! ! !Delay class methodsFor: 'snapshotting' stamp: 'dmu 5/25/2010 11:02'! startUp "Restart active delay, if any, when resuming a snapshot." DelaySuspended ifFalse:[^self error: 'Trying to activate Delay twice']. DelaySuspended := false. self restoreResumptionTimes. AccessProtect := Semaphore forMutualExclusion ! ! !Delay methodsFor: 'private' stamp: 'StefanMarr 11/9/2010 23:38' prior: 47886371! schedule "Schedule this delay" | delayDelivered | delayDelivered := false. beingWaitedOn ifTrue: [^self error: 'This Delay has already been scheduled.']. resumptionTime := Time millisecondClockValue + delayDuration. [AccessProtect critical: [ ScheduledDelay ifNil: [ ScheduledDelay := self. TimingSemaphore signal. delayDelivered := true. ] ]. delayDelivered ] whileFalse.! ! !Delay methodsFor: 'private' stamp: 'StefanMarr 11/9/2010 23:39' prior: 47885691! unschedule | delayDelivered | delayDelivered := false. [AccessProtect critical: [ ScheduledDelay ifNil: [ FinishedDelay := self. TimingSemaphore signal. delayDelivered := true. ] ]. delayDelivered ] whileFalse.! ! !Delay class methodsFor: 'timer process' stamp: 'StefanMarr 11/9/2010 17:44' prior: 19672467! handleTimerEvent "Handle a timer event; which can be either: - a schedule request (ScheduledDelay notNil) - an unschedule request (FinishedDelay notNil) - a timer signal (not explicitly specified) We check for timer expiry every time we get a signal." | nowTick nextTick | "Wait until there is work to do." TimingSemaphore wait. "Process any schedule requests" ScheduledDelay ifNotNil:[ "Schedule the given delay" self scheduleDelay: ScheduledDelay. ScheduledDelay := nil. ]. "Process any unschedule requests" FinishedDelay ifNotNil:[ self unscheduleDelay: FinishedDelay. FinishedDelay := nil. ]. "Check for clock wrap-around." nowTick := Time millisecondClockValue. nowTick < ActiveDelayStartTime ifTrue: [ "clock wrapped" self saveResumptionTimes. self restoreResumptionTimes. ]. ActiveDelayStartTime := nowTick. "Signal any expired delays" [ActiveDelay notNil and:[nowTick >= ActiveDelay resumptionTime]] whileTrue:[ ActiveDelay signalWaitingProcess. SuspendedDelays isEmpty ifTrue: [ActiveDelay := nil] ifFalse:[ActiveDelay := SuspendedDelays removeFirst]. ]. "And signal when the next request is due. We sleep at most 1sec here as a soft busy-loop so that we don't accidentally miss signals." nextTick := nowTick + 1000. ActiveDelay ifNotNil:[nextTick := nextTick min: ActiveDelay resumptionTime]. nextTick := nextTick min: SmallInteger maxVal. "Since we have processed all outstanding requests, reset the timing semaphore so that only new work will wake us up again. Do this RIGHT BEFORE setting the next wakeup call from the VM because it is only signaled once so we mustn't miss it." "No!!!! If running multicore, TimingSemaphore may have already been signalled!!!! Do not reset signals, because then we will miss it -- dmu 9/26/10" RVMPrimitives coreCount > 1 ifFalse: [TimingSemaphore initSignals]. "Do not wait till the next Delay if Semaphore already signaled. -- dmu 9/26/10" TimingSemaphore isSignaled ifFalse: [ Delay primSignal: TimingSemaphore atMilliseconds: nextTick. ]. "This last test is necessary for the obscure case that the msecs clock rolls over after nowTick has been computed (unlikely but not impossible). In this case we'd wait for MillisecondClockMask msecs (roughly six days) or until another delay gets scheduled (which may not be any time soon). In any case, since handling the condition is easy, let's just deal with it" Time millisecondClockValue < nowTick ifTrue:[TimingSemaphore signal]. "retry" ! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! hostCore: anObject "Set the value of hostCore" hostCore := anObject! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList "Answer the value of myList" myList isNil ifTrue:[self myList: nil]. ^ myList! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList: anObject "Set the value of myList" myList := anObject! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/2/2010 17:02'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." "Debugging code below causes terminated running processes to seem not terminated. -- dmu 3/2/10" "(myList isNil and: [RVMPrimitives isRVM]) ifTrue:[self halt]." self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'dmu 4/7/2009 02:41'! resumeOn: aCore self useOnlyCore: aCore. self resume! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." self suspend. suspendedContext == aContext ifTrue: [ ^ suspendedContext := aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:03'! step self suspend. ^ suspendedContext := suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! stepToCallee "Step until top context changes" | ctxt | self suspend. ctxt := suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext := suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! stepToSendOrReturn self suspend. ^ suspendedContext := suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:57'! avoidCore: anIndex "Force this process to avoid this core (0-55)" self coreMask: (self coreMask bitClear: (1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:49'! avoidCores: aCollectionOfIndicies "Force this process to avoid these cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitClear:mask)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:59'! useAdditionalCore: anIndex "Force this process to only urn on this core (0-55)" self coreMask: (self coreMask bitOr:(1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:50'! useAdditionalCores: aCollectionOfIndicies "Allow this process to run on these additional cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitOr:mask)! ! !Process methodsFor: 'core assignment' stamp: 'dmu 5/5/2009 01:32'! useOnlyCore: anIndex "Force this process to only run on this core (0-55)" self coreMask: (1 bitShift: anIndex)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:02'! useOnlyCores: aCollectionOfIndicies "Force this process to only run on these cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: mask! ! !Process methodsFor: 'core assignment' stamp: 'dmu 1/25/2010 11:06'! useOnlyMainCore RVMPrimitives isRVM ifTrue: [self useOnlyCore: (RVMPrimitives getMainRank)]! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:30'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. self suspend. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! !Process class methodsFor: 'instance creation' stamp: 'dmu 3/24/2010 15:46'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess := self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. [newProcess coreMask:(1 bitShift: 27)]. ^newProcess! ! !Process class methodsFor: 'instance creation' stamp: 'ssa 2/26/2009 02:45'! forContext: aContext priority: anInteger coreMask: anIntegerMask "Answer an instance of me that has suspended aContext at priority anInteger using this coreMask." | newProcess | newProcess := self forContext: aContext priority: anInteger. newProcess coreMask:anIntegerMask. ^newProcess! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:37'! removeAllPossible "Terminate and remove all processes that you can. This should leave the standard set only" self terminatableProcesses print do:[:proc| proc terminate]! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:31'! terminatableProcesses "Answer all current processes that may be user terminated like in the ProcessBrowser" "self terminatableProcesses" | processList | Smalltalk garbageCollectMost. "lose defunct processes" processList := Process allSubInstances reject: [:each | each isTerminated]. processList := processList sortBy: [:a :b | a priority >= b priority]. processList := WeakArray withAll: processList. ^processList select:[:proc| (ProcessBrowser nameAndRulesFor: proc) at: 2]! ! !Project methodsFor: 'menu messages' stamp: 'dmu 11/25/2008 00:23'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject := self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World := world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World := nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess := Processor thisProcess. ! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock interlock ifNil: [self interlock: Semaphore forMutualExclusion]. ^ interlock! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock: aSemaphore interlock := aSemaphore! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetInterlock self interlock signal. self interlock: nil! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:09'! safelyDo: aBlock ^ self interlock critical: aBlock! ! !StandardFileStream class methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetAllInterlocks "self resetAllInterlocks" self allSubInstancesDo: [:sfs| sfs resetInterlock]! ! !RemoteString methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:19'! text "Answer the receiver's string asText if remote files are enabled. Use a read only copy to avoid syntax errors when accessed via multiple processes." | theFile | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile := (SourceFiles at: sourceFileNumber) readOnlyCopy. ^[theFile safelyDo: [ theFile position: filePositionHi. theFile position > theFile size ifTrue: [ self error: 'RemoteString past end of file' ]. theFile nextChunkText string ]] ensure: [theFile close]! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:25'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." "Simulation guard" self buildMorphicViewOn: aSyntaxError. Project spawnNewProcessIfThisIsUI: Processor activeProcess. ^ Processor thisProcess suspend! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:26'! snapshot: save andQuit: quit embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil: [ msg := String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [ quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ] ]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ (SourceFiles at: 2) safelyDo: [ LastQuitLogPosition := (SourceFiles at: 2) setToEnd; position ]]. self logChange: msg. Transcript cr; show: msg ]. self processShutDownList: quit. Cursor write show. save ifTrue: [ resuming := embeddedFlag ifTrue: [ self snapshotEmbeddedPrimitive ] ifFalse: [ self snapshotPrimitive ]. "<-- PC frozen here on image file" resuming == false ifTrue: [ "Time to reclaim segment files is immediately after a save" Smalltalk globals at: #ImageSegment ifPresent: [ :theClass | theClass reclaimObsoleteSegmentFiles ] ] "guard against failure" ] ifFalse: [ resuming := false ]. quit & (resuming == false) ifTrue: [ self quitPrimitive ]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [ Smalltalk clearExternalObjects ]. self processStartUpList: resuming == true. resuming == true ifTrue: [ self recordStartupStamp ]. UIManager default onSnapshot. "Now it's time to raise an error" resuming == nil ifTrue: [ self error: 'Failed to write image file (disk full?)' ]. ^ resuming! ! Cursor initialize! Controller initialize! !BitBlt methodsFor: 'copying' stamp: 'ssa 4/7/2009 13:44'! OLDcopyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 5/10/2009 08:43'! copyBits RVMPrimitives isRVM ifFalse:[^self OLDcopyBits]. destForm == Display ifTrue: [self copyBitsOnMain] ifFalse: [self copyBitsLocally]! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards := (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 := startPoint. point2 := stopPoint] ifFalse: [point1 := stopPoint. point2 := startPoint]. sourceForm == nil ifTrue: [destX := point1 x. destY := point1 y] ifFalse: [width := sourceForm width. height := sourceForm height. offset := sourceForm offset. destX := (point1 x + offset x) rounded. destY := (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. (destForm == Display or:[RVMPrimitives isRVM not]) ifTrue: [ self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded] ifFalse: [self drawLoopLocallyX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded]. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." ^(destForm == Display or:[RVMPrimitives isRVM not]) ifTrue:[self globalDrawLoopX:xDelta Y: yDelta ] ifFalse:[self localDrawLoopX:xDelta Y: yDelta ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:17'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr oldComment oldStamp | oldComment := self organization classComment. oldStamp := self organization commentStamp. (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance class: self oldComment: oldComment newComment: aString string oldStamp: oldStamp newStamp: aStamp. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr := self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr isNil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr := oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file := SourceFiles at: 2) ifNotNil: [file safelyDo: [file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header := String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance class: self oldComment: oldComment newComment: aString oldStamp: oldStamp newStamp: aStamp ! ! !CompiledMethod methodsFor: 'source code management' stamp: 'dmu 9/7/2010 14:23'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString | (SourceFiles == nil or: [(file := SourceFiles at: fileIndex) == nil]) ifTrue: [^self become: (self copyWithTempsFromMethodNode: methodNode)]. SmalltalkImage current assureStartupStampLogged. file safelyDo: [ file setToEnd. preambleBlock value: file. "Write the preamble" remoteString := RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex]. ! ! !RemoteString methodsFor: 'private' stamp: 'dmu 9/7/2010 14:23'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile := SourceFiles at: fileNumber. theFile safelyDo: [ theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile] ]! ! !SmalltalkImage methodsFor: 'sources, change log' stamp: 'dmu 9/7/2010 14:26'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes := SourceFiles at: 2. changes safelyDo: [ changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aString := aStringOrText asString. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile := SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile := SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp := nil. self forceChangesToDisk. ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:22'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble := self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble := '']. method := self methodDict at: selector ifAbsent: [outStream nextPutAll: selector; cr. outStream tab; nextPutAll: '** ERROR!! THIS SCRIPT IS MISSING ** ' translated; cr; cr. outStream nextPutAll: ' '. ^ outStream]. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos := method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: method decompileString] ifFalse: [sourceFile := SourceFiles at: method fileIndex. sourceFile safelyDo: [ preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile at: oldPos] ifFalse: [sourceFile position: oldPos]. "Copy the method chunk" newPos := outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "The following chunk may have ]style[" sourceFile peek == $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos := outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'dmu 9/7/2010 14:12'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" StandardFileStream resetAllInterlocks. SourceFiles := self new initialize! ! !Process methodsFor: 'RVM' stamp: 'dmu 9/17/2010 11:59'! suspendedContextWaitingIfNecessary "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." [self suspendedContext isNil] whileTrue. ^ self suspendedContext! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'dmu 9/17/2010 12:00'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector := evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig := evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context := guineaPig suspendedContextWaitingIfNecessary. debugger := ToolSet debug: guineaPig controller: nil context: context. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! !Mutex methodsFor: 'mutual exclusion' stamp: 'dmu 6/14/2010 16:16'! critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess | activeProcess := Processor thisProcess. activeProcess == owner ifTrue:[^aBlock value]. ^semaphore critical:[ owner := activeProcess. aBlock ensure:[owner := nil]].! ! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !UserInterruptHandler methodsFor: 'private' stamp: 'dmu 9/17/2010 16:39'! handleUserInterrupt "This will be called from the event-fetcher process. Assume no system-vital processes have a lower priority than this, and are thus ok to interrupt" UserInterruptHandler cmdDotEnabled ifTrue: [ [|toInterrupt| toInterrupt := Processor preemptedProcess. "Only interrupt processes which are potentially blocking the UI" toInterrupt priority < Project uiProcess priority ifTrue: [toInterrupt := Project uiProcess]. "Fork at lower priority to avoid interrupting system-critical processes" toInterrupt debugWithTitle: 'User Interrupt'] forkAt: Processor thisProcess priority -1]! ! !TAssertable methodsFor: 'asserting' stamp: 'StefanMarr 10/30/2010 13:38'! should: aBlock notTakeMoreThan: aDuration "Evaluate aBlock in a forked process and if it takes more than anInteger milliseconds to run we terminate the process and report a test failure. It'' important to use the active process for the test failure so that the failure reporting works correctly in the context of the exception handlers." | evaluated evaluationProcess result delay testProcess | evaluated := false. delay := Delay forDuration: aDuration. testProcess := Processor thisProcess. "Create a new process to evaluate aBlock" evaluationProcess := [ result := aBlock value. evaluated := true. delay unschedule. testProcess resume ] forkNamed: 'Process to evaluate should: notTakeMoreThanMilliseconds:'. "Wait the milliseconds they asked me to" delay wait. "After this point either aBlock was evaluated or not..." evaluated ifFalse: [ evaluationProcess terminate. self assert: false description: ('Block evaluation took more than the expected <1p>' expandMacrosWith: aDuration)]. ^result! ! !ProcessTest methodsFor: 'running' stamp: 'StefanMarr 10/30/2010 13:38'! tearDown Processor thisProcess environmentRemoveKey: #processTests ifAbsent: []! ! !ProcessTest methodsFor: 'testing' stamp: 'StefanMarr 10/30/2010 13:39'! testEnvironmentAt Processor thisProcess environmentAt: #processTests put: 42. self assert: (Processor thisProcess environmentAt: #processTests) = 42. self should: [Processor thisProcess environmentAt: #foobar] raise: Error! ! !ProcessTest methodsFor: 'testing' stamp: 'StefanMarr 10/30/2010 13:38'! testEnvironmentAtPut self assert: (Processor thisProcess environmentAt: #processTests put: 42) = 42.! ! !ProcessTest methodsFor: 'testing' stamp: 'StefanMarr 10/30/2010 13:38'! testEnvironmentRemoveKey Processor thisProcess environmentAt: #processTests put: 42. Processor thisProcess environmentRemoveKey: #processTests. self assert: (Processor thisProcess environmentAt: #processTests ifAbsent: []) isNil. self should: [Processor thisProcess environmentAt: #processTests] raise: Error! ! !UpdateStreamer methodsFor: 'private actions' stamp: 'StefanMarr 10/30/2010 13:39'! silentRetrieveUrls: urls ontoQueue: queue withWaitSema: waitSema "download the given list of URLs. The queue will be loaded alternately with url's and with the retrieved contents. If a download fails, the contents will be #failed. If all goes well, a special pair with an empty URL and the contents #finished will be put on the queue. waitSema is waited on every time before a new document is downloaded; this keeps the downloader from getting too far ahead of the main process" "kill the existing downloader if there is one" self zapUpdateDownloader. "fork a new downloading process" UpdateDownloader := [ urls do: [:url | | canPeek front doc | waitSema wait. queue nextPut: url. doc := HTTPClient httpGet: url. doc isString ifTrue: [queue nextPut: #failed. UpdateDownloader := nil. Processor thisProcess terminate] ifFalse: [canPeek := 120 min: doc size. front := doc next: canPeek. doc skip: -1 * canPeek. (front beginsWith: ' array at: 1 put: EventTypeNone. "If there is no event, the primitive will fail, client code expects the indication via the array" ^nil! ! ================================================ FILE: image.st/RVM-multicore-support.squeak.st ================================================ '****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************'! DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine destFormSema' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'! PluggableTextMorph subclass: #PluggableTextMorphPlus instanceVariableNames: 'getColorSelector acceptAction unstyledAcceptText styler textInterlock' classVariableNames: '' poolDictionaries: '' category: 'ToolBuilder-Morphic'! Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name island env hostCore coreMask' classVariableNames: 'SemaForSuspensions' poolDictionaries: '' category: 'Kernel-Processes'! Object subclass: #RVMPrimitives instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Support'! Object subclass: #SHTextStyler instanceVariableNames: 'sem backgroundProcess text monitor view stylingEnabled textInterlock' classVariableNames: '' poolDictionaries: '' category: 'ShoutCore-Styling'! Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess EmergencyProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'! FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1 interlock' classVariableNames: 'Registry' poolDictionaries: '' category: 'System-Files'! View subclass: #StandardSystemView instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes displayInterlock' classVariableNames: 'CacheBits LabelStyle' poolDictionaries: '' category: 'ST80-Support'! Object subclass: #Mutex instanceVariableNames: 'semaphore owner' classVariableNames: '' poolDictionaries: '' category: 'RVM-Support'! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 11/25/2008 00:23'! activePriority "Answer the priority level of the currently running Process." ^self thisProcess priority! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 9/16/2010 14:53'! preemptedProcess "Return the process that the currently active process just preempted." | list listWithoutMe | self thisProcess priority to: 1 by: -1 do:[:priority| list := quiescentProcessLists at: priority. "RVM keeps running processes on the lists -- dmu 9/16/10" listWithoutMe := list reject: [:p | p == Processor thisProcess]. listWithoutMe isEmpty ifFalse:[^listWithoutMe last]. ]. ^nil "Processor preemptedProcess"! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'dmu 11/25/2008 00:23'! terminateActive "Terminate the process that is currently running." self thisProcess terminate! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:39'! areRunningProcessesInSchedulerLists "Our RVM follows Pallas' MS system and keeps runnable processes in the scheduler lists even when running." ^RVMPrimitives isRVM! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 11/25/2008 00:26'! isActive: aProcess ^ aProcess suspendedContext == nil! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:32'! thisProcess ^ RVMPrimitives thisProcess! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 3/22/2010 13:03'! yieldIfFewerCoresThan: n RVMPrimitives coreCount < n ifTrue: [self yield]! ! !Project class methodsFor: 'utilities' stamp: 'dmu 11/25/2008 00:24'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor thisProcess suspend]! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/8/2010 23:41'! breakpoint self primitiveFailed! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:02'! printExecutionTrace ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printOnConsole: aString "Prints a string onto the console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:00'! printStack "Prints Smalltalk stack to console" ! ! !RVMPrimitives class methodsFor: 'debugging VM' stamp: 'dmu 6/9/2010 00:01'! printVMStatistics ! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:04'! sampleRVM "Grab some data from the VM and return it" "RVMPrimitives sampleRVM" ^ nil! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'sm 10/27/2010 22:09'! getMainRank "Get a sample from the VM and read out the main rank" | sample | sample := self sampleRVM. ^ ((sample at: 6) at: 2) at: 6! ! !RVMPrimitives class methodsFor: 'VM statistics' stamp: 'dmu 6/8/2010 23:40'! sampleSpecificData: flags "Grab some data from the VM and return it" "Bit offsets for flags; bit 0 is 1, bit 1 is 2, bit 2 is 4, etc. allCores, // 0 runMask, messageNames, cpuCoreStats, allCoreStats, fence, millisecs, // 6 cycles, messageStats, memorySystemStats, interpreterStats, objectTableStats, interactionStats, coreCoords, // 14 sendTallies, receiveTallies, bufferedMessageStats, receiveCycles, // memory system gcStats, // 19 heapStats, // interpreter bytecodes, // 20 yieldCount, cycleCounts, interruptChecks, movedMutatedObjectStats, mutexStats, interpreterLoopStats // 26" ^ nil! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:58'! moveAllToReadMostlyHeaps "Move all objects into read-mostly heaps" self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:55'! shuffleToHeapsFrom: firstHeap to: lastHeap "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:56'! shuffleToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Deal out all objects in the system into heaps from firstHeap through lastHeap in round-robin fashion so that adjacent objects wind up in different heaps" "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'rearranging objects' stamp: 'dmu 6/8/2010 23:57'! spreadToHeapsFrom: firstHeap to: lastHeap movingReadWriteObjectsToReadMostlyHeap: rwToRM movingReadMostlyObjectsToReadWriteHeap: rmToRw "Spread out all objects in the system into heaps from firstHeap through lastHeap so that each heap ends up about equally full." "If rwToRM, move objects in read/write heaps to read-mostly heaps." "If rmToRW, move objects in read-mostly heaps to read/write heaps." ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:30'! for: anObject setRankTo: rank self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:31'! for: anObject setRankTo: rank isReadWrite: isRW self primitiveFailed! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:17'! getCoreOf: anObject "RVMPrimitives getCoreOf: 2@3" ^ -1! ! !RVMPrimitives class methodsFor: 'situating an object' stamp: 'dmu 6/8/2010 23:47'! getMutabilityOf: anObject "Return true if argument is in a read/write heap, false if in read-mostly heap" ^ true! ! !RVMPrimitives class methodsFor: 'enumerating a heap' stamp: 'dmu 6/8/2010 23:10'! allObjectsInHeap: rank isReadWrite: trueForReadWriteFalseForReadMostly "return array of all objects in either read/write or read-mostly heap specified by rank and trueForReadWriteFalseForReadMostly" "RVMPrimitives allObjectsInHeap: 0 isReadWrite: true" ^ nil! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:18'! getCoreIAmRunningOn "RVMPrimitives getCoreIAmRunningOn" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:44'! getRunMask "Return an integer with ones corresponding to cores RVM is allowed to use: 1 means core 0, 3 means cores 0 and 1, etc." "RVMPrimitives getRunMask printStringBase: 16" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:07'! getRunningProcessesByCore "Returns array of running processes, indexed by core (+1)" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/8/2010 23:46'! setRunMask: anInteger "Sets run mask to argument and returns old run mask. Only cores set in run mask will be used to run Smalltalk processes." "RVMPrimitives setRunMask: 1" ^ -1! ! !RVMPrimitives class methodsFor: 'processes' stamp: 'dmu 6/9/2010 00:04'! thisProcess "Return the process that is running; RVM does not use ActiveProcess for this state, since many may be running" ^ Processor activeProcess! ! !RVMPrimitives class methodsFor: 'cores' stamp: 'dmu 6/8/2010 23:11'! coreCount "RVMPrimitives coreCount" ^ 1! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:25'! getCoreTrace "RVMPrimitives getCoreTrace" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:26'! getMutatedReplicatedObjectsTrace ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:22'! startCoreTrace: size "RVMPrimitives startCoreTrace: 1000" ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'tracing' stamp: 'dmu 6/8/2010 23:27'! startMutatedReplicatedObjectsTrace: size ^ self primitiveFailed! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/8/2010 23:19'! getEmergencySemaphore "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives getEmergencySemaphore" ! ! !RVMPrimitives class methodsFor: 'emergency evaluating' stamp: 'dmu 6/9/2010 00:06'! setEmergencySemaphore: aSema "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "RVMPrimitives setEmergencySemaphore: Semaphore new" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! getExtraPreheaderWordOf: anObject "Returns the extra preheader word of the argument." "RVMPrimitives getExtraPreheaderWordOf: 3@4" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/14/2010 15:27'! setExtraPreheaderWordOf: anObject to: newContents "Sets the extra preheader word of the first argument." "|n| n := 3@4. RVMPrimitives setExtraPreheaderWordOf: n to: 17. RVMPrimitives getExtraPreheaderWordOf: n" ! ! !RVMPrimitives class methodsFor: 'using extra word' stamp: 'dmu 6/9/2010 00:05'! setExtraWordSelector: aSelector "returns the old one" ^self primitiveFailed! ! !RVMPrimitives class methodsFor: 'testing' stamp: 'dmu 6/14/2010 15:36'! isRVM "RVMPrimitives isRVM" ^ (self getCoreOf: nil) ~= -1! ! !BlockClosure methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:13'! valueAt: blockPriority "Evaluate the receiver (block), with another priority as the actual one and restore it afterwards. The caller should be careful with using higher priorities." | activeProcess result outsidePriority | activeProcess := Processor thisProcess. outsidePriority := activeProcess priority. activeProcess priority: blockPriority. result := self ensure: [activeProcess priority: outsidePriority]. "Yield after restoring lower priority to give the preempted processes a chance to run." blockPriority > outsidePriority ifTrue: [Processor yield]. ^ result! ! !BlockClosure methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:13'! valueWithin: aDuration onTimeout: timeoutBlock "Evaluate the receiver. If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead" | theProcess delay watchdog | aDuration <= Duration zero ifTrue: [^ timeoutBlock value ]. "the block will be executed in the current process" theProcess := Processor thisProcess. delay := aDuration asDelay. "make a watchdog process" watchdog := [ delay wait. "wait for timeout or completion" theProcess ifNotNil:[ theProcess signalException: TimedOut ] ] newProcess. "Watchdog needs to run at high priority to do its job (but not at timing priority)" watchdog priority: Processor timingPriority-1. "catch the timeout signal" ^ [ watchdog resume. "start up the watchdog" self ensure:[ "evaluate the receiver" theProcess := nil. "it has completed, so ..." delay delaySemaphore signal. "arrange for the watchdog to exit" ]] on: TimedOut do: [ :e | timeoutBlock value ]. ! ! !BlockClosure methodsFor: 'private' stamp: 'dmu 6/14/2010 16:13'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !BlockContext methodsFor: 'evaluating' stamp: 'dmu 6/14/2010 16:14'! valueWithin: aDuration onTimeout: timeoutBlock "Evaluate the receiver. If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead" | theProcess delay watchdog | aDuration <= Duration zero ifTrue: [^ timeoutBlock value ]. "the block will be executed in the current process" theProcess := Processor thisProcess. delay := aDuration asDelay. "make a watchdog process" watchdog := [ delay wait. "wait for timeout or completion" theProcess ifNotNil:[ theProcess signalException: TimedOut ] ] newProcess. "Watchdog needs to run at high priority to do its job (but not at timing priority)" watchdog priority: Processor timingPriority-1. "catch the timeout signal" ^ [ watchdog resume. "start up the watchdog" self ensure:[ "evaluate the receiver" theProcess := nil. "it has completed, so ..." delay delaySemaphore signal. "arrange for the watchdog to exit" ]] on: TimedOut do: [ :e | timeoutBlock value ]. ! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 6/14/2010 16:14'! valueAt: blockPriority "Evaluate the receiver (block), with another priority as the actual one and restore it afterwards. The caller should be careful with using higher priorities." | activeProcess result outsidePriority | activeProcess := Processor thisProcess. outsidePriority := activeProcess priority. activeProcess priority: blockPriority. result := self ensure: [activeProcess priority: outsidePriority]. "Yield after restoring lower priority to give the preempted processes a chance to run." blockPriority > outsidePriority ifTrue: [Processor yield]. ^ result! ! !BlockContext methodsFor: 'private' stamp: 'dmu 11/25/2008 00:18'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !CPUWatcher methodsFor: 'process operations' stamp: 'dmu 11/25/2008 00:18'! debugProcess: aProcess | uiPriority oldPriority | uiPriority := Processor thisProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority := ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !ComplexProgressIndicator methodsFor: 'as yet unclassified' stamp: 'dmu 6/14/2010 16:14'! withProgressDo: aBlock | safetyFactor totals trialRect delta targetOwner | Smalltalk isMorphic ifFalse: [^aBlock value]. formerProject := Project current. formerWorld := World. formerProcess := Processor thisProcess. targetMorph ifNil: [targetMorph := ProgressTargetRequestNotification signal]. targetMorph ifNil: [ trialRect := Rectangle center: Sensor cursorPoint extent: 80@80. delta := trialRect amountToTranslateWithin: formerWorld bounds. trialRect := trialRect translateBy: delta. translucentMorph := TranslucentProgessMorph new opaqueBackgroundColor: Color white; bounds: trialRect; openInWorld: formerWorld. ] ifNotNil: [ targetOwner := targetMorph owner. translucentMorph := TranslucentProgessMorph new setProperty: #morphicLayerNumber toValue: targetMorph morphicLayerNumber - 0.1; bounds: targetMorph boundsInWorld; openInWorld: targetMorph world. ]. stageCompleted := 0. safetyFactor := 1.1. "better to guess high than low" translucentMorph setProperty: #progressStageNumber toValue: 1. translucentMorph hide. targetOwner ifNotNil: [targetOwner hide]. totals := self loadingHistoryDataForKey: 'total'. newRatio := 1.0. estimate := totals size < 2 ifTrue: [ 15000 "be a pessimist" ] ifFalse: [ (totals sum - totals max) / (totals size - 1 max: 1) * safetyFactor. ]. start := Time millisecondClockValue. self forkProgressWatcher. [ aBlock on: ProgressInitiationException do: [ :ex | ex sendNotificationsTo: [ :min :max :curr | "ignore this as it is inaccurate" ]. ]. ] on: ProgressNotification do: [ :note | | stageCompletedString | translucentMorph show. targetOwner ifNotNil: [targetOwner show]. note extraParam ifNotNil:[self addProgressDecoration: note extraParam]. stageCompletedString := (note messageText findTokens: ' ') first. stageCompleted := (stageCompletedString copyUpTo: $:) asNumber. cumulativeStageTime := Time millisecondClockValue - start max: 1. prevData := self loadingHistoryDataForKey: stageCompletedString. prevData isEmpty ifFalse: [ newRatio := (cumulativeStageTime / (prevData average max: 1)) asFloat. ]. self loadingHistoryAt: stageCompletedString add: cumulativeStageTime. translucentMorph setProperty: #progressStageNumber toValue: stageCompleted + 1. note resume. ]. stageCompleted := 999. "we may or may not get here" ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! inActiveControllerProcess "Answer whether the active scheduling process is the actual active process in the system." ^activeControllerProcess == Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! resetActiveController "When saving a morphic project whose parent is mvc, we need to set this up first" activeController := nil. activeControllerProcess := Processor thisProcess. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! scheduleActiveNoTerminate: aController "Make aController be the active controller. Presumably the process that requested the new active controller wants to keep control to do more activites before the new controller can take control. Therefore, do not terminate the currently active process." self schedulePassive: aController. self scheduled: aController from: Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! searchForActiveController "Find a scheduled controller that wants control and give control to it. If none wants control, then see if the System Menu has been requested." | aController | activeController := nil. activeControllerProcess := Processor thisProcess. self activeController: self nextActiveController. Processor terminateActive! ! !Cursor methodsFor: 'displaying' stamp: 'dmu 6/14/2010 16:15'! showWhile: aBlock "While evaluating the argument, aBlock, make the receiver be the cursor shape." "ar 2/2/2006: Only allow this if active process is ui process" | oldcursor | Processor thisProcess == Project uiProcess ifFalse:[^aBlock value]. oldcursor := Sensor currentCursor. self show. ^aBlock ensure: [oldcursor show] ! ! !Debugger class methodsFor: 'class initialization' stamp: 'dmu 6/14/2010 16:15'! openContext: aContext label: aString contents: contentsStringOrNil "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." "Simulation guard" ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue: [Smalltalk logError: aString inContext: aContext to: 'SqueakDebug.log']. ErrorRecursion ifTrue: [ErrorRecursion := false. self primitiveError: aString]. ErrorRecursion := true. self informExistingDebugger: aContext label: aString. (Debugger context: aContext) openNotifierContents: contentsStringOrNil label: aString. ErrorRecursion := false. Processor thisProcess suspend. ! ! !Debugger class methodsFor: 'instance creation' stamp: 'dmu 6/14/2010 16:15'! context: aContext "Answer an instance of me for debugging the active process starting with the given context." ^ self new process: Processor thisProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: aContext! ! !DelayWaitTimeout methodsFor: 'private' stamp: 'dmu 6/14/2010 16:15'! setDelay: anInteger forSemaphore: aSemaphore super setDelay: anInteger forSemaphore: aSemaphore. process := Processor thisProcess. expired := false.! ! !HTTPLoader methodsFor: 'private' stamp: 'dmu 6/14/2010 16:15'! startDownload | newDownloadProcess | downloads size >= self maxNrOfConnections ifTrue: [^self]. requests size <= 0 ifTrue: [^self]. newDownloadProcess := [ [ self nextRequest startRetrieval ] on: FTPConnectionException do: [ :ex | Cursor normal show. self removeProcess: Processor thisProcess. self startDownload ]. self removeProcess: Processor thisProcess. self startDownload ] newProcess. downloads add: newDownloadProcess. newDownloadProcess resume! ! !MVCToolBuilder class methodsFor: 'accessing' stamp: 'dmu 6/14/2010 16:16'! isActiveBuilder "Answer whether I am the currently active builder" "This is really a way of answering whether 'Smalltalk isMVC'" ScheduledControllers ifNil:[^false]. ^ScheduledControllers activeControllerProcess == Processor thisProcess! ! !MVCUIManager class methodsFor: 'accessing' stamp: 'dmu 6/14/2010 16:16'! isActiveManager "Answer whether I should act as the active ui manager" "This is really a way of answering whether 'Smalltalk isMVC'" ScheduledControllers ifNil:[^false]. ^ScheduledControllers activeControllerProcess == Processor thisProcess! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 6/14/2010 16:16'! spyEvery: millisecs on: aBlock "Create a spy and spy on the given block at the specified rate." "Spy only on the active process (in which aBlock is run)" | myDelay time0 observedProcess | aBlock isBlock ifFalse: [ self error: 'spy needs a block here' ]. self class: aBlock receiver class method: aBlock method. "set up the probe" observedProcess := Processor thisProcess. myDelay := Delay forMilliseconds: millisecs. time0 := Time millisecondClockValue. gcStats := SmalltalkImage current getVMParameters. Timer ifNotNil: [ self error: 'it seems a tally is already running' ]. Timer := [ [ true ] whileTrue: [ | startTime | startTime := Time millisecondClockValue. myDelay wait. self tally: Processor preemptedProcess suspendedContext in: (observedProcess == Processor preemptedProcess ifTrue: [observedProcess] ifFalse: [nil]) "tally can be > 1 if ran a long primitive" by: (Time millisecondClockValue - startTime) // millisecs]. nil] newProcess. Timer priority: Processor timingPriority-1. "activate the probe and evaluate the block" Timer resume. ^ aBlock ensure: [ "cancel the probe and return the value" "Could have already been terminated. See #terminateTimerProcess" Timer ifNotNil: [ Timer terminate. Timer := nil ]. "Collect gc statistics" SmalltalkImage current getVMParameters keysAndValuesDo: [ :idx :gcVal | gcStats at: idx put: (gcVal - (gcStats at: idx))]. time := Time millisecondClockValue - time0]! ! !Monitor methodsFor: 'private' stamp: 'dmu 6/14/2010 16:16'! enter self isOwnerProcess ifTrue: [ nestingLevel := nestingLevel + 1. ] ifFalse: [ mutex wait. ownerProcess := Processor thisProcess. nestingLevel := 1. ].! ! !Monitor methodsFor: 'private' stamp: 'dmu 6/14/2010 16:16'! isOwnerProcess ^ Processor thisProcess == ownerProcess! ! !Paragraph methodsFor: 'RVM' stamp: 'dmu 6/15/2010 11:36'! destFormSema: s destFormSema := s! ! !Paragraph methodsFor: 'private' stamp: 'dmu 4/1/2009 19:38'! compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint compositionRectangle := compositionRect copy. text := aText. textStyle := aTextStyle. rule := DefaultRule. mask := nil. "was DefaultMask " marginTabsLevel := 0. destFormSema := Semaphore forMutualExclusion. destinationForm := Display. offset := aPoint. ^self composeAll! ! !Paragraph methodsFor: 'private' stamp: 'ssa 4/7/2009 12:39'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | destFormSema isNil ifTrue:[self destFormSema: Semaphore forMutualExclusion]. destFormSema critical: [ saveDestinationForm := destinationForm. self destinationForm: aDisplayMedium. self displayLines: lineInterval. destinationForm := saveDestinationForm ]! ! !PluggableTextMorphPlus methodsFor: 'styling' stamp: 'dmu 6/21/2010 15:35'! hasUnacceptedEdits: aBoolean "re-implemented to re-style the text iff aBoolean is true" self textInterlock critical: [ super hasUnacceptedEdits: aBoolean]. (aBoolean and: [self okToStyle]) ifTrue: [ styler styleInBackgroundProcess: textMorph contents]! ! !PluggableTextMorphPlus methodsFor: 'styling' stamp: 'dmu 6/21/2010 15:33'! setText: aText self okToStyle ifFalse:[^super setText: aText]. self textInterlock critical: [ super setText: (styler format: aText asText). ]. aText size < 4096 ifTrue:[styler style: textMorph contents] ifFalse:[styler styleInBackgroundProcess: textMorph contents]! ! !PluggableTextMorphPlus methodsFor: 'RVM' stamp: 'dmu 6/21/2010 11:33'! textInterlock textInterlock isNil ifTrue: [textInterlock := Monitor new]. ^textInterlock! ! !Process methodsFor: 'accessing' stamp: 'ssa 2/17/2009 22:34'! isActiveProcess ^ Processor areRunningProcessesInSchedulerLists ifTrue: [ suspendedContext isNil and:[myList notNil]] ifFalse: [self == Processor activeProcess]! ! !Process methodsFor: 'accessing' stamp: 'dmu 6/18/2010 17:35'! isTerminated self isActiveProcess ifTrue: [^ false]. ^suspendedContext isNil or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. If so, and the pc is greater than the startpc, the bock has alrteady sent and returned from value and there is nothing more to do." suspendedContext isBottomContext and: [suspendedContext pc isNil or: [suspendedContext pc > suspendedContext startpc]]]! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/14/2010 16:16'! run "Suspend current process and execute self instead" | proc | proc := Processor thisProcess. [ proc suspend. self resume. ] forkAt: Processor highestPriority! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/18/2010 00:18'! suspend "Primitive. Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes. The return value of this method is the list the receiver was previously on (if any)." | oldList | "This is fallback code for VMs which only support the old primitiveSuspend which would not accept processes that are waiting to be run." RVMPrimitives isRVM ifTrue: [self error: 'suspend should never fail']. myList ifNil:[^nil]. "this allows us to use suspend multiple times" oldList := myList. myList := nil. oldList remove: self ifAbsent:[]. ^oldList! ! !Process methodsFor: 'changing process state' stamp: 'dmu 6/17/2010 23:57'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock oldList | self == Processor thisProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ (ctxt tempAt: 2) ifNil:[ ctxt tempAt: 2 put: nil. unwindBlock := ctxt tempAt: 1. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self suspend. ] ifFalse:[ "Always suspend the process first so it doesn't accidentally get woken up" oldList := self suspend. suspendedContext ifNotNil:[ "Figure out if we are terminating the process while waiting in Semaphore>>critical: In this case, pop the suspendedContext so that we leave the ensure: block inside Semaphore>>critical: without signaling the semaphore." (oldList class == Semaphore and:[ suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[ suspendedContext := suspendedContext home. ]. "If we are terminating a process halfways through an unwind, try to complete that unwind block first." (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil:[:outer| (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil:[:inner| "This is an unwind block currently under evaluation" suspendedContext runUntilErrorOrReturnFrom: inner. ]. ]. ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" self suspend. ^ suspendedContext := suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:01'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | self suspend. ctxt := suspendedContext. suspendedContext := nil. "disable this process while running its stack in active process below" pair := ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext := pair first. error := pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:06'! install: aContext "Replace the suspendedContext with aContext." (Processor isActive: self) ifTrue: [^self error: 'An active process cannot install contexts']. suspendedContext := aContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:07'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 6/14/2010 16:08'! popTo: aContext value: aValue "Replace the suspendedContext with aContext, releasing all contexts between the currently suspendedContext and it." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ self]. "aContext is on top" self return: callee value: aValue! ! !Process class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 15:11'! semaForSuspensions SemaForSuspensions isNil ifTrue:[SemaForSuspensions := Semaphore forMutualExclusion]. ^SemaForSuspensions! ! !Process methodsFor: 'debugging' stamp: 'dmu 6/14/2010 16:09'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. ToolSet debug: self context: context label: title contents: nil fullView: bool. ! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debugWithTitle: title "Open debugger on self" | context | context := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. self debug: context title: title full: true. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:31'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self == Processor thisProcess ifFalse: [^self]. self suspend. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'dmu 6/14/2010 16:11'! signalException: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" | oldList | "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. "Suspend myself first to ensure that I won't run away in the midst of the following modifications." myList ifNotNil:[oldList := self suspend]. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class lookupSelector: #pvtSignal:list:) arguments: (Array with: anException with: oldList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" oldList ifNotNil: [self resume]. ! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask ^ coreMask! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask: m coreMask := m! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:41'! hostCore ^ hostCore! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:31'! isRunning Processor thisProcess == self ifTrue: [^ true]. self isActiveProcess ifTrue: [^ true]. myList ifNil: [^ false]. ^ myList class ~~ Semaphore! ! !Process methodsFor: 'RVM' stamp: 'ssa 3/2/2010 18:23'! nilMyListUnlessRVM Processor areRunningProcessesInSchedulerLists ifFalse: [ "primitiveSuspend will use myList to remove from list and will nil it out" myList := nil. ]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'dmu 6/14/2010 16:17'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight := stackList at: stackListIndex]. selectedProcess == Processor thisProcess ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext := selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ! !ProcessBrowser class methodsFor: 'class initialization' stamp: 'dmu 6/14/2010 16:17'! registerWellKnownProcesses "Associate each well-known process with a nickname and two flags: allow-stop, and allow-debug. Additional processes may be added to this list as required" WellKnownProcesses := OrderedCollection new. self registerWellKnownProcess: [] label: 'no process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Smalltalk lowSpaceWatcherProcess] label: 'the low space watcher' allowStop: false allowDebug: false. self registerWellKnownProcess: [WeakArray runningFinalizationProcess] label: 'the WeakArray finalization process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Processor thisProcess] label: 'the UI process' allowStop: false allowDebug: true. self registerWellKnownProcess: [Processor backgroundProcess] label: 'the idle process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Sensor interruptWatcherProcess] label: 'the user interrupt watcher' allowStop: false allowDebug: false. self registerWellKnownProcess: [Sensor eventTicklerProcess] label: 'the event tickler' allowStop: false allowDebug: false. self registerWellKnownProcess: [Project uiProcess] label: 'the inactive Morphic UI process' allowStop: false allowDebug: false. self registerWellKnownProcess: [Smalltalk at: #SoundPlayer ifPresent: [:sp | sp playerProcess]] label: 'the Sound Player' allowStop: false allowDebug: false. self registerWellKnownProcess: [ScheduledControllers ifNotNil: [ScheduledControllers activeControllerProcess]] label: 'the inactive MVC controller process' allowStop: false allowDebug: true. self registerWellKnownProcess: [Smalltalk at: #CPUWatcher ifPresent: [:cw | cw currentWatcherProcess]] label: 'the CPUWatcher' allowStop: false allowDebug: false ! ! !SHTextStyler methodsFor: 'styling' stamp: 'sm 9/29/2010 18:27'! initialize stylingEnabled := true. "If on RVM deactivate it for the moment. There is a racecondition we do not handle yet." RVMPrimitives isRVM ifTrue: [ stylingEnabled := false ] ! ! !SHTextStyler methodsFor: 'styling' stamp: 'dmu 6/21/2010 15:34'! styleInBackgroundProcess: aText self terminateBackgroundStylingProcess. stylingEnabled ifTrue:[ text := aText copy. self monitor critical: [ sem := Semaphore new. [sem notNil ifTrue: [ sem wait. view ifNotNil: [ self textInterlock critical: [view stylerStyledInBackground: text]]] ] forkAt: Processor activePriority. backgroundProcess := [ | s | self privateStyle: text. s := sem. "terminateBackgroundStylingProcess nils sem" s ifNotNil: [s signal]] forkAt: Processor userBackgroundPriority] ] ! ! !SHTextStyler methodsFor: 'RVM' stamp: 'dmu 6/21/2010 11:34'! textInterlock view isNil ifTrue: [^ Monitor new]. ^view textInterlock! ! !SoundPlayer class methodsFor: 'player process' stamp: 'dmu 6/14/2010 16:17'! stopPlayerProcess "Stop the sound player process." "SoundPlayer stopPlayerProcess" (PlayerProcess == nil or:[PlayerProcess == Processor thisProcess]) ifFalse:[PlayerProcess terminate]. PlayerProcess := nil. self primSoundStop. ActiveSounds := OrderedCollection new. Buffer := nil. PlayerSemaphore := Semaphore forMutualExclusion. ReadyForBuffer ifNotNil: [Smalltalk unregisterExternalObject: ReadyForBuffer]. ReadyForBuffer := nil. ! ! !StandardToolSet class methodsFor: 'debugging' stamp: 'dmu 6/14/2010 16:17'! debugError: anError "Handle an otherwise unhandled error" ^Processor thisProcess debug: anError signalerContext title: anError description! ! !SyntaxError class methodsFor: '*Morphic-Support' stamp: 'dmu 6/14/2010 16:19'! morphicOpen: aSyntaxError "Answer a view whose model is an instance of me." self buildMorphicViewOn: aSyntaxError. Project spawnNewProcessIfThisIsUI: Processor thisProcess. ^ Processor thisProcess suspend! ! !SyntaxError class methodsFor: '*ST80-Support' stamp: 'dmu 6/14/2010 16:18'! mvcOpen: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | topView := self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor thisProcess suspend ! ! !TestCase methodsFor: 'extensions' stamp: 'dmu 6/14/2010 16:18'! should: aBlock notTakeMoreThan: aDuration "Evaluate aBlock in a forked process and if it takes more than anInteger milliseconds to run we terminate the process and report a test failure. It'' important to use the active process for the test failure so that the failure reporting works correctly in the context of the exception handlers." | evaluated evaluationProcess result delay testProcess | evaluated := false. delay := Delay forDuration: aDuration. testProcess := Processor thisProcess. "Create a new process to evaluate aBlock" evaluationProcess := [ result := aBlock value. evaluated := true. delay unschedule. testProcess resume ] forkNamed: 'Process to evaluate should: notTakeMoreThanMilliseconds:'. "Wait the milliseconds they asked me to" delay wait. "After this point either aBlock was evaluated or not..." evaluated ifFalse: [ evaluationProcess terminate. self assert: false description: ('Block evaluation took more than the expected <1p>' expandMacrosWith: aDuration)]. ^result! ! !SemaphoreTest methodsFor: 'private' stamp: 'dmu 6/14/2010 16:17'! criticalError Processor thisProcess terminate! ! !TestFailure methodsFor: 'camp smalltalk' stamp: 'dmu 6/14/2010 16:18'! defaultAction Processor thisProcess debug: self signalerContext title: self description! ! !Utilities class methodsFor: 'fetching updates' stamp: 'dmu 6/14/2010 16:19'! retrieveUrls: urls ontoQueue: queue withWaitSema: waitSema "download the given list of URLs. The queue will be loaded alternately with url's and with the retrieved contents. If a download fails, the contents will be #failed. If all goes well, a special pair with an empty URL and the contents #finished will be put on the queue. waitSema is waited on every time before a new document is downloaded; this keeps the downloader from getting too far ahead of the main process" "kill the existing downloader if there is one" | updateCounter | UpdateDownloader ifNotNil: [UpdateDownloader terminate]. updateCounter := 0. "fork a new downloading process" UpdateDownloader := [ 'Downloading updates' displayProgressAt: Sensor cursorPoint from: 0 to: urls size during: [:bar | urls do: [:url | | front canPeek doc | waitSema wait. queue nextPut: url. doc := HTTPClient httpGet: url. doc isString ifTrue: [queue nextPut: #failed. UpdateDownloader := nil. Processor thisProcess terminate] ifFalse: [canPeek := 120 min: doc size. front := doc next: canPeek. doc skip: -1 * canPeek. (front beginsWith: ' "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 4/4/2009 00:20'! copyBitsLocally "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/3/2009 23:01'! drawLoopLocallyX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | | self primitiveFailed! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:36'! globalDrawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | dx := xDelta sign. dy := yDelta sign. px := yDelta abs. py := xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P := py // 2. 1 to: py do: [:i | destX := destX + dx. (P := P - px) < 0 ifTrue: [destY := destY + dy. P := P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P := px // 2. 1 to: px do: [:i | destY := destY + dy. (P := P - py) < 0 ifTrue: [destX := destX + dx. P := P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:52'! localDrawLoopX: xDelta Y: yDelta "Primitive" ^self primitiveFailed! ! !ControlManager methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:14'! activeControllerNoTerminate: aController andProcess: aProcess "Set aController to be the currently active controller and aProcess to be the process that handles controller scheduling activities in the system. This message differs from activeController:andProcess: in that it does not send controlTerminate to the currently active controller." self inActiveControllerProcess ifTrue: [aController~~nil ifTrue: [(scheduledControllers includes: aController) ifTrue: [self promote: aController] ifFalse: [self error: 'Old controller not scheduled']]. activeController := aController. activeController == nil ifFalse: [activeController controlInitialize]. activeControllerProcess := aProcess. activeControllerProcess resume] ifFalse: ['New active controller process must be set from old one, resetting...' print. self reset. ] ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/2/2010 14:12'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | suspendingList newActiveController | (suspendingList := activeControllerProcess suspendingList) == nil ifTrue: [activeControllerProcess == Processor thisProcess ifTrue: [activeControllerProcess suspend]] ifFalse: [suspendingList remove: activeControllerProcess ifAbsent:[]. activeControllerProcess offList]. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController := (Debugger openInterrupt: labelString onProcess: activeControllerProcess) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/25/2010 16:17'! reset "ssa - reset the window controller process" | newProcess | newProcess := [ScheduledControllers resetActiveController. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process" "Processor terminateActive"! ! !Controller methodsFor: 'basic control sequence' stamp: 'dmu 3/22/2010 14:25'! interActivityPause "if we are looping quickly, insert a short delay. Thus if we are just doing UI stuff, we won't take up much CPU" | currentTime wait | [RVMPrimitives isRVM ifTrue: [Processor yield. ^ self].]. MinActivityLapse ifNotNil: [ lastActivityTime ifNotNil: [ currentTime := Time millisecondClockValue. wait := lastActivityTime + MinActivityLapse - currentTime. wait > 0 ifTrue: [ wait <= MinActivityLapse "big waits happen after a snapshot" ifTrue: [DisplayScreen checkForNewScreenSize. "(Delay forMilliseconds: wait) wait "]. ]. ]. ]. lastActivityTime := Time millisecondClockValue.! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/17/2009 14:18'! flushNonKbdEvents eventQueue ifNil: [^ self]. [^self]value. "don't flush so we don't lose events" eventQueue flushAllSuchThat: [:buf | (self isKbdEvent: buf) not] ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMouseButtons self fetchMoreEvents. self flushNonKbdEvents. ^ mouseButtons ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMousePt self fetchMoreEvents. self flushNonKbdEvents. ^ mousePosition ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 12:46'! processEvent: evt "Process a single event. This method is run at high priority." | type | type := evt at: 1. "Tackle mouse events first" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1). self queueEvent: evt. self processMouseEvent: evt . ^self]. "Store the event in the queue if there's any" type = EventTypeKeyboard ifTrue: [ "Check if the event is a user interrupt" ((evt at: 4) = 0 and: [((evt at: 3) bitOr: (((evt at: 5) bitAnd: 8) bitShift: 8)) = interruptKey]) ifTrue: ["interrupt key is meta - not reported as event" ^ interruptSemaphore signal]. "Else swap ctrl/alt keys if neeeded.wi" KeyDecodeTable at: {evt at: 3. evt at: 5} ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]. self queueEvent: evt. self processKeyboardEvent: evt . ^self ]. "Handle all events other than Keyborad or Mouse." self queueEvent: evt. ! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:38'! forkOn: aCore "Create and schedule a Process running the code in the receiver." ^ self newProcess resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:09'! forkOn: aCore with: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:08'! forkOn: aCore with: anObject at: aPriority "Create and schedule a Process running the code in the receiver." | proc | proc := self newProcessWith: anObject. proc priority: aPriority. ^proc resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:34'! forkWith: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:33'! newProcessWith: anObject "Answer a Process running the code in the receiver. The process is not scheduled." "Simulation guard" ^Process forContext: [self value: anObject. Processor terminateActive] priority: Processor activePriority! ! !Delay class methodsFor: 'snapshotting' stamp: 'dmu 5/25/2010 11:02'! startUp "Restart active delay, if any, when resuming a snapshot." DelaySuspended ifFalse:[^self error: 'Trying to activate Delay twice']. DelaySuspended := false. self restoreResumptionTimes. ActiveDelay == nil ifFalse: [ActiveDelay activate]. AccessProtect := Semaphore forMutualExclusion ! ! !Delay methodsFor: 'private' stamp: 'sm 11/9/2010 23:38'! schedule "Schedule this delay" | delayDelivered | delayDelivered := false. beingWaitedOn ifTrue: [^self error: 'This Delay has already been scheduled.']. resumptionTime := Time millisecondClockValue + delayDuration. [AccessProtect critical: [ ScheduledDelay ifNil: [ ScheduledDelay := self. TimingSemaphore signal. delayDelivered := true. ] ]. delayDelivered ] whileFalse.! ! !Delay methodsFor: 'private' stamp: 'sm 11/9/2010 23:39'! unschedule | delayDelivered | delayDelivered := false. [AccessProtect critical: [ ScheduledDelay ifNil: [ FinishedDelay := self. TimingSemaphore signal. delayDelivered := true. ] ]. delayDelivered ] whileFalse.! ! !Delay class methodsFor: 'timer process' stamp: 'sm 11/9/2010 17:44'! handleTimerEvent "Handle a timer event; which can be either: - a schedule request (ScheduledDelay notNil) - an unschedule request (FinishedDelay notNil) - a timer signal (not explicitly specified) We check for timer expiry every time we get a signal." | nowTick nextTick | "Wait until there is work to do." TimingSemaphore wait. "Process any schedule requests" ScheduledDelay ifNotNil:[ "Schedule the given delay" self scheduleDelay: ScheduledDelay. ScheduledDelay := nil. ]. "Process any unschedule requests" FinishedDelay ifNotNil:[ self unscheduleDelay: FinishedDelay. FinishedDelay := nil. ]. "Check for clock wrap-around." nowTick := Time millisecondClockValue. nowTick < ActiveDelayStartTime ifTrue: [ "clock wrapped" self saveResumptionTimes. self restoreResumptionTimes. ]. ActiveDelayStartTime := nowTick. "Signal any expired delays" [ActiveDelay notNil and:[nowTick >= ActiveDelay resumptionTime]] whileTrue:[ ActiveDelay signalWaitingProcess. SuspendedDelays isEmpty ifTrue: [ActiveDelay := nil] ifFalse:[ActiveDelay := SuspendedDelays removeFirst]. ]. "And signal when the next request is due. We sleep at most 1sec here as a soft busy-loop so that we don't accidentally miss signals." nextTick := nowTick + 1000. ActiveDelay ifNotNil:[nextTick := nextTick min: ActiveDelay resumptionTime]. nextTick := nextTick min: SmallInteger maxVal. "Since we have processed all outstanding requests, reset the timing semaphore so that only new work will wake us up again. Do this RIGHT BEFORE setting the next wakeup call from the VM because it is only signaled once so we mustn't miss it." "No!!!! If running multicore, TimingSemaphore may have already been signalled!!!! Do not reset signals, because then we will miss it -- dmu 9/26/10" RVMPrimitives coreCount > 1 ifFalse: [TimingSemaphore initSignals]. "Do not wait till the next Delay if Semaphore already signaled. -- dmu 9/26/10" TimingSemaphore isSignaled ifFalse: [ Delay primSignal: TimingSemaphore atMilliseconds: nextTick. ]. "This last test is necessary for the obscure case that the msecs clock rolls over after nowTick has been computed (unlikely but not impossible). In this case we'd wait for MillisecondClockMask msecs (roughly six days) or until another delay gets scheduled (which may not be any time soon). In any case, since handling the condition is easy, let's just deal with it" Time millisecondClockValue < nowTick ifTrue:[TimingSemaphore signal]. "retry" ! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! hostCore: anObject "Set the value of hostCore" hostCore := anObject! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList "Answer the value of myList" myList isNil ifTrue:[self myList: nil]. ^ myList! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList: anObject "Set the value of myList" myList := anObject! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/2/2010 17:02'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." "Debugging code below causes terminated running processes to seem not terminated. -- dmu 3/2/10" "(myList isNil and: [RVMPrimitives isRVM]) ifTrue:[self halt]." self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'dmu 4/7/2009 02:41'! resumeOn: aCore self useOnlyCore: aCore. self resume! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." self suspend. suspendedContext == aContext ifTrue: [ ^ suspendedContext := aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:03'! step self suspend. ^ suspendedContext := suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! stepToCallee "Step until top context changes" | ctxt | self suspend. ctxt := suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext := suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! stepToSendOrReturn self suspend. ^ suspendedContext := suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:57'! avoidCore: anIndex "Force this process to avoid this core (0-55)" self coreMask: (self coreMask bitClear: (1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:49'! avoidCores: aCollectionOfIndicies "Force this process to avoid these cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitClear:mask)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:59'! useAdditionalCore: anIndex "Force this process to only urn on this core (0-55)" self coreMask: (self coreMask bitOr:(1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:50'! useAdditionalCores: aCollectionOfIndicies "Allow this process to run on these additional cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitOr:mask)! ! !Process methodsFor: 'core assignment' stamp: 'dmu 5/5/2009 01:32'! useOnlyCore: anIndex "Force this process to only run on this core (0-55)" self coreMask: (1 bitShift: anIndex)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:02'! useOnlyCores: aCollectionOfIndicies "Force this process to only run on these cores (0-55)" | mask | mask := 0. aCollectionOfIndicies do:[:index| mask := mask bitOr: (1 bitShift: index)]. self coreMask: mask! ! !Process methodsFor: 'core assignment' stamp: 'dmu 1/25/2010 11:06'! useOnlyMainCore RVMPrimitives isRVM ifTrue: [self useOnlyCore: (RVMPrimitives getMainRank)]! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:30'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. self suspend. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! !Process class methodsFor: 'instance creation' stamp: 'dmu 3/24/2010 15:46'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess := self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. [newProcess coreMask:(1 bitShift: 27)]. ^newProcess! ! !Process class methodsFor: 'instance creation' stamp: 'ssa 2/26/2009 02:45'! forContext: aContext priority: anInteger coreMask: anIntegerMask "Answer an instance of me that has suspended aContext at priority anInteger using this coreMask." | newProcess | newProcess := self forContext: aContext priority: anInteger. newProcess coreMask:anIntegerMask. ^newProcess! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:37'! removeAllPossible "Terminate and remove all processes that you can. This should leave the standard set only" self terminatableProcesses print do:[:proc| proc terminate]! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:31'! terminatableProcesses "Answer all current processes that may be user terminated like in the ProcessBrowser" "self terminatableProcesses" | processList | Smalltalk garbageCollectMost. "lose defunct processes" processList := Process allSubInstances reject: [:each | each isTerminated]. processList := processList sortBy: [:a :b | a priority >= b priority]. processList := WeakArray withAll: processList. ^processList select:[:proc| (ProcessBrowser nameAndRulesFor: proc) at: 2]! ! !Project methodsFor: 'menu messages' stamp: 'dmu 11/25/2008 00:23'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject := self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World := world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World := nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess := Processor thisProcess. ! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock interlock ifNil: [self interlock: Semaphore forMutualExclusion]. ^ interlock! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:07'! interlock: aSemaphore interlock := aSemaphore! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetInterlock self interlock signal. self interlock: nil! ! !StandardFileStream methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:09'! safelyDo: aBlock ^ self interlock critical: aBlock! ! !StandardFileStream class methodsFor: 'RVM' stamp: 'dmu 9/7/2010 14:14'! resetAllInterlocks "self resetAllInterlocks" self allSubInstancesDo: [:sfs| sfs resetInterlock]! ! !RemoteString methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:19'! text "Answer the receiver's string asText if remote files are enabled." | theFile theText | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile := SourceFiles at: sourceFileNumber. theFile safelyDo: [ theFile position: filePositionHi. theText := theFile nextChunkText]. ^theText! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:25'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | "Simulation guard" topView := self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor thisProcess suspend. ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:26'! snapshot: save andQuit: quit embedded: embeddedFlag "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. The latter part of this method runs when resuming a previously saved image. The resume logic checks for a document file to process when starting up." | resuming msg sourceLink | Object flushDependents. Object flushEvents. save & (SourceFiles at: 2) notNil ifTrue: [msg := (quit ifTrue: ['----QUIT----'] ifFalse: ['----SNAPSHOT----']) , Date dateAndTimeNow printString, ' ', (FileDirectory default localNameFor: self imageName). sourceLink := ' priorSource: ' , LastQuitLogPosition printString. self assureStartupStampLogged. (SourceFiles at: 2) safelyDo: [ LastQuitLogPosition := (SourceFiles at: 2) setToEnd; position. self logChange: msg , sourceLink. ]. Transcript cr; show: msg]. self processShutDownList: quit. Cursor write show. save ifTrue: [resuming := embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming := false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [self clearExternalObjects]. self processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !UnhandledError methodsFor: 'priv handling' stamp: 'dmu 11/25/2008 00:25'! devDefaultAction Processor thisProcess debug: exception signalerContext title: exception description! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: false. self displayLabelText. ]! ! Cursor initialize! Controller initialize! !BitBlt methodsFor: 'copying' stamp: 'ssa 4/7/2009 13:44'! OLDcopyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap := colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX := destX asInteger. destY := destY asInteger. width := width asInteger. height := height asInteger. sourceX := sourceX asInteger. sourceY := sourceY asInteger. clipX := clipX asInteger. clipY := clipY asInteger. clipWidth := clipWidth asInteger. clipHeight := clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 5/10/2009 08:43'! copyBits RVMPrimitives isRVM ifFalse:[^self OLDcopyBits]. destForm == Display ifTrue: [self copyBitsOnMain] ifFalse: [self copyBitsLocally]! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards := (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 := startPoint. point2 := stopPoint] ifFalse: [point1 := stopPoint. point2 := startPoint]. sourceForm == nil ifTrue: [destX := point1 x. destY := point1 y] ifFalse: [width := sourceForm width. height := sourceForm height. offset := sourceForm offset. destX := (point1 x + offset x) rounded. destY := (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. (destForm == Display or:[RVMPrimitives isRVM not]) ifTrue: [ self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded] ifFalse: [self drawLoopLocallyX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded]. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." ^(destForm == Display or:[RVMPrimitives isRVM not]) ifTrue:[self globalDrawLoopX:xDelta Y: yDelta ] ifFalse:[self localDrawLoopX:xDelta Y: yDelta ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:17'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr | (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance classCommented: self. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr := self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr := oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file := SourceFiles at: 2) ifNotNil: [ file safelyDo: [ file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header := String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance classCommented: self. ! ! !CompiledMethod methodsFor: 'source code management' stamp: 'dmu 9/7/2010 14:23'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString | (SourceFiles == nil or: [(file := SourceFiles at: fileIndex) == nil]) ifTrue: [^self become: (self copyWithTempsFromMethodNode: methodNode)]. SmalltalkImage current assureStartupStampLogged. file safelyDo: [ file setToEnd. preambleBlock value: file. "Write the preamble" remoteString := RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex]. ! ! !RemoteString methodsFor: 'private' stamp: 'dmu 9/7/2010 14:23'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile := SourceFiles at: fileNumber. theFile safelyDo: [ theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile] ]! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'dmu 9/7/2010 14:26'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes := SourceFiles at: 2. changes safelyDo: [ changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aString := aStringOrText asString. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile := SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile := SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp := nil. self forceChangesToDisk. ]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:22'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble := self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble := '']. method := self methodDict at: selector ifAbsent: [outStream nextPutAll: selector; cr. outStream tab; nextPutAll: '** ERROR!! THIS SCRIPT IS MISSING ** ' translated; cr; cr. outStream nextPutAll: ' '. ^ outStream]. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos := method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: method decompileString] ifFalse: [sourceFile := SourceFiles at: method fileIndex. sourceFile safelyDo: [ preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile at: oldPos] ifFalse: [sourceFile position: oldPos]. "Copy the method chunk" newPos := outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "The following chunk may have ]style[" sourceFile peek == $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos := outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'dmu 9/7/2010 14:12'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" StandardFileStream resetAllInterlocks. SourceFiles := self new initialize! ! !Process methodsFor: 'RVM' stamp: 'dmu 9/17/2010 11:59'! suspendedContextWaitingIfNecessary "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." [self suspendedContext isNil] whileTrue. ^ self suspendedContext! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'dmu 9/17/2010 12:00'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector := evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig := evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context := guineaPig suspendedContextWaitingIfNecessary. debugger := Debugger new process: guineaPig controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: context isolationHead: nil. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:37'! displayInterlock displayInterlock ifNil: [self displayInterlock: Mutex new]. ^ displayInterlock! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:24'! displayInterlock: aSemaphore displayInterlock := aSemaphore! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:31'! displayEmphasized "Display with label highlighted to indicate that it is active." self critical: [ self displayDeEmphasized; emphasize. isLabelComplemented := true ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:30'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self critical: [ (bitsValid and: [controller ~~ ScheduledControllers activeController]) ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [Display deferUpdates: true. super display. Display deferUpdates: false; forceToScreen: self windowBox. CacheBits ifTrue: [self cacheBitsAsIs]] ] ! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:37'! critical: aBlock ^self displayInterlock critical: aBlock! ! !Mutex methodsFor: 'mutual exclusion' stamp: 'dmu 6/14/2010 16:16'! critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess | activeProcess := Processor thisProcess. activeProcess == owner ifTrue:[^aBlock value]. ^semaphore critical:[ owner := activeProcess. aBlock ensure:[owner := nil]].! ! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: true. self displayLabelBoxes. self displayLabelText. ]! ! !StandardSystemView methodsFor: 'RVM' stamp: 'dmu 9/17/2010 12:47'! resetDisplayInterlock self displayInterlock: nil! ! !ControlManager methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:48'! restore "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." scheduledControllers first view uncacheBits. "assure refresh" self unschedule: screenController; scheduleOnBottom: screenController. screenController view window: Display boundingBox; displayDeEmphasized. self scheduledWindowControllers reverseDo: [:aController | aController view resetDisplayInterlock; displayDeEmphasized]. ! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'dmu 9/17/2010 16:39'! handleUserInterrupt Preferences cmdDotEnabled ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] forkAt: Processor thisProcess priority + 1]]! ! ================================================ FILE: image.st/Sly3.mvc.st ================================================ '****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************'! Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name hostCore coreMask lyDebuggingBlock parent children creatorEnsemble ' classVariableNames: 'SemaForSupensions' poolDictionaries: '' category: 'Kernel-Processes'! Object subclass: #Sly3 instanceVariableNames: '' classVariableNames: 'KeepFlying SerializeForDebugging' poolDictionaries: '' category: 'Sly3'! Sly3 class instanceVariableNames: ''! Object subclass: #Sly3AbstractModifier instanceVariableNames: 'previous next' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3AbstractModifier subclass: #Sly3Adverb instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Adverb subclass: #Sly3OperandDistributor instanceVariableNames: 'resultantMembers countsUpToMe' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModCollectionly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3AbstractIndirectOperandDistributor instanceVariableNames: 'parameter' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3AbstractIndirectOperandDistributor subclass: #Sly3ModRandomly instanceVariableNames: '' classVariableNames: 'RandomNumberSource' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModWholly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModRoundly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModSingly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModDuplicatively instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Adverb subclass: #Sly3ModSerially instanceVariableNames: 'cachedMod cachedEns' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3OperandDistributor subclass: #Sly3ModSelectively instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3ModWholly subclass: #Sly3ModPlainly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Object subclass: #Sly3Boids instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! Sly3Boids subclass: #Sly3aBoids instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! Sly3AbstractModifier subclass: #Sly3Gerund instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Object subclass: #ArchiveReader instanceVariableNames: 'stream classMap objectMap startPosition classVersions position' classVariableNames: '' poolDictionaries: '' category: 'RVM-Archiving'! Object subclass: #ArchiveWriter instanceVariableNames: 'stream classMap objectMap position' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'RVM-Archiving'! Object subclass: #BinaryChoice instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Compatibility'! Object subclass: #Collection instanceVariableNames: '' classVariableNames: 'MutexForPicking RandomForPicking Tasks' poolDictionaries: '' category: 'Collections-Abstract'! Object subclass: #Controller instanceVariableNames: 'model view sensor lastActivityTime lastProcessRunningMe killCounter' classVariableNames: 'MinActivityLapse' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! ArchiveReader subclass: #CopyReader instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Archiving'! ArchiveWriter subclass: #CopyWriter instanceVariableNames: 'copySet' classVariableNames: '' poolDictionaries: '' category: 'RVM-Archiving'! Form subclass: #Cursor instanceVariableNames: '' classVariableNames: 'ActionCursor BlankCursor BottomLeftCursor BottomRightCursor CornerCursor CrossHairCursor CurrentCursor DownCursor LeftArrowCursor MarkerCursor MenuCursor MoveCursor NormalCursor OriginCursor ReadCursor ResizeLeftCursor ResizeTopCursor ResizeTopLeftCursor ResizeTopRightCursor RightArrowCursor SquareCursor TopLeftCursor TopRightCursor UpCursor WaitCursor WebLinkCursor WriteCursor XeqCursor' poolDictionaries: '' category: 'Graphics-Display Objects'! Form subclass: #DisplayScreen instanceVariableNames: 'clippingBox extraRegions' classVariableNames: 'Blank5 DeferringUpdates DisplayChangeSignature Dot1 Dot5 ScreenSave' poolDictionaries: '' category: 'Graphics-Display Objects'! ArchiveReader subclass: #RVMSampleReader instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'RVM-Archiving'! ArchiveWriter subclass: #RVMSampleWriter instanceVariableNames: 'rawData' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'RVM-Archiving'! Sly3AbstractIndirectOperandDistributor subclass: #Sly3ModValuely instanceVariableNames: '' classVariableNames: 'RandomNumberSource' poolDictionaries: '' category: 'Sly3-Modifiers'! Object subclass: #Sly3EnsembleMirror instanceVariableNames: 'theEnsemble members' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! Object subclass: #Sly3MessageEnvelope instanceVariableNames: 'receiver message deactivateEnsembleBehaviorFlags' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! Object subclass: #Sly3Boid instanceVariableNames: 'position velocity neighbors flock lastDrawnPosition lastLastDrawnPosition' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! Sly3Boid subclass: #Sly3aBoid instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! !ChangeList methodsFor: 'scanning' stamp: 'ssa 1/5/2010 15:55'! scanRecords: someRecords changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. someRecords do:[:each| each type = #doIt ifTrue:[self addItem: each text: 'do it: ' , (each string contractTo: 50)]. each type = #preamble ifTrue:[self addItem: each text: 'preamble: ' , (each string contractTo: 50)]. each type = #classComment ifTrue:[self addItem: each text: 'class comment for ', each methodClassName]. each type = #method ifTrue:[self addItem: each text: 'method: ',each methodClassName,(each isMetaClassChange ifTrue: [' class '] ifFalse: [' ']),each methodSelector,' ', each stamp]]. listSelections _ Array new: list size withAll: false! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 12:19'! changeListMenu: aMenu "Fill aMenu up so that it comprises the primary changelist-browser menu" aMenu addList: #( ('fileIn selections' fileInSelections 'import the selected items into the image') ('fileOut selections... ' fileOutSelections 'create a new file containing the selected items') - ('compare to current' compareToCurrentVersion 'open a separate window which shows the text differences between the on-file version and the in-image version.' ) ('toggle diffing (D)' toggleDiffing 'start or stop showing diffs in the code pane.') - ('select conflicts with any changeset' selectAllConflicts 'select methods in the file which also occur in any change-set in the system') ('select conflicts with current changeset' selectConflicts 'select methods in the file which also occur in the current change-set') ('select conflicts with...' selectConflictsWith 'allows you to designate a file or change-set against which to check for code conflicts.') - ('select changes matching...' selectChangesMatching 'select changes in the file that match a user-supplied pattern') ('spawn changes matching...' spawnChangesMatching 'spawn changes in the file that match a user-supplied pattern into a new change list view') ('select changes such that...' selectSuchThat 'select changes in the file that evaluate to true to a user-supplied code fragment') ('spawn changes such that...' spawnSuchThat 'spawn changes in the file that evaluate to true to a user-supplied code fragment') - ('select unchanged methods' selectUnchangedMethods 'select methods in the file whose in-image versions are the same as their in-file counterparts' ) ('select new methods' selectNewMethods 'select methods in the file that do not current occur in the image') ('select methods for this class' selectMethodsForThisClass 'select all methods in the file that belong to the currently-selected class') - ('select all (a)' selectAll 'select all the items in the list') ('deselect all' deselectAll 'deselect all the items in the list') ('invert selections' invertSelections 'select every item that is not currently selected, and deselect every item that *is* currently selected') ('spawn selections' spawnSelections 'spawn all selected changes into a new change list view') - ('browse current versions of selections' browseCurrentVersionsOfSelections 'open a message-list browser showing the current (in-image) counterparts of the selected methods') ('destroy current methods of selections' destroyCurrentCodeOfSelections 'remove (*destroy*) the in-image counterparts of all selected methods') - ('remove doIts' removeDoIts 'remove all items that are doIts rather than methods') ('remove older versions' removeOlderMethodVersions 'remove all but the most recent versions of methods in the list') ('remove up-to-date versions' removeExistingMethodVersions 'remove all items whose code is the same as the counterpart in-image code') ('remove selected items' removeSelections 'remove the selected items from the change-list') ('remove unselected items' removeNonSelections 'remove all the items not currently selected from the change-list')). ^ aMenu ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:16'! selectChangesMatching "query the user for a pattern then select all changes matching that pattern" | pattern | pattern _ FillInTheBlank request: 'Enter a pattern to match to select changes: # = single character wildcard * = many character wildcard'. '' . pattern isEmpty ifTrue: [^ self ]. self selectSuchThat: [:aChangeRecord | aChangeRecord match: pattern]! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 15:07'! selectSuchThat "query the user for a selection criterio. By Lex Spoon. NB: the UI for invoking this from a changelist browser is currently commented out; to reenfranchise it, you'll need to mild editing to ChangeList method #changeListMenu:" | code block | code _ FillInTheBlank request: 'selection criteria for a change named aChangeRecord? For instance, aChangeRecord category = ''System-Network'' aChangeRecord type = "one of #(#method #doIt #classComment #preamble )" aChangeRecord text = ''whole change text'' aChangeRecord string includesSubString: ''change text substring'' aChangeRecord string includesSubString: ''change text substring'' ''*fooba#'' match: aChangeRecord string ''*fooba#'' match: aChangeRecord methodSelectorSafe ''*fooba#'' match: aChangeRecord methodSelectorSafe ' initialAnswer: 'aChangeRecord match:''*anything#anyChar'''. code isEmpty ifTrue: [^ self ]. block _ Compiler evaluate: '[:aChangeRecord | ', code, ']'. self selectSuchThat: block! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:46'! spawnChangesMatching "query the user for a pattern then select all changes matching that pattern" | pattern | pattern _ FillInTheBlank request: 'Enter a pattern to match to select changes: # = single character wildcard * = many character wildcard'. '' . pattern isEmpty ifTrue: [^ self ]. self spawnSuchThat: [:aChangeRecord | aChangeRecord match: pattern] titled:'Changes matching ',pattern! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:55'! spawnSelections "spawn a new changelist view for the selections" self class browseRecords: self selectedChanges titled:'Selected Changes'! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 15:07'! spawnSuchThat "query the user for a selection criterion block and then spawn" | code block | code _ FillInTheBlank request: 'selection criteria for a change named aChangeRecord? For instance, aChangeRecord category = ''System-Network'' aChangeRecord type = "one of #(#method #doIt #classComment #preamble )" aChangeRecord text = ''whole change text'' aChangeRecord string includesSubString: ''change text substring'' ''*foo*ba#'' match: aChangeRecord string ''*foo*ba#'' match: aChangeRecord methodSelectorSafe ''*foo*ba#'' match: aChangeRecord methodSelectorSafe ' initialAnswer: 'aChangeRecord match:''*anything#anyChar'''. code isEmpty ifTrue: [^ self ]. block _ Compiler evaluate: '[:aChangeRecord | ', code, ']'. self spawnSuchThat: block titled: 'Changes such that ''',code,'''' ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:58'! spawnSuchThat: aBlock titled: aString "spawn changes passing aBlock" | changes | changes _ changeList select: [ :change | aBlock value: change ]. self class browseRecords: changes titled: aString! ! !ChangeList methodsFor: 'viewing access' stamp: 'ssa 1/1/1970 00:15'! togglePrimaryListIndex: newListIndex listIndex = newListIndex ifTrue: [listSelections at: listIndex put: false. listIndex := 0] ifFalse: [newListIndex ~= 0 ifTrue: [listSelections at: newListIndex put: true. listIndex := newListIndex]]. self changed: #listIndex. self contentsChanged! ! !ChangeList methodsFor: 'accessing' stamp: 'ssa 1/5/2010 13:56'! changeList: aCollection changeList _ aCollection! ! !ChangeList methodsFor: 'accessing' stamp: 'ssa 1/5/2010 14:56'! selectedChanges | sels | sels _ OrderedCollection new. listSelections with: changeList do: [:selected :item | selected ifTrue: [sels add: item]]. ^sels! ! !ChangeList class methodsFor: 'public access' stamp: 'ssa 1/5/2010 14:45'! browseRecords: someChangeRecords "Opens a changeList on a collection of change records" self browseRecords: someChangeRecords titled: 'Some changes'! ! !ChangeList class methodsFor: 'public access' stamp: 'ssa 1/5/2010 14:45'! browseRecords: someChangeRecords titled: aString "Opens a changeList on a collection of change records" | changeList | changeList _ self new scanRecords: someChangeRecords. self open: changeList name: aString multiSelect: true! ! !ChangeList class methodsFor: 'instance creation' stamp: 'ssa 8/21/2009 15:32'! open: aChangeList name: aString multiSelect: multiSelect "Create a standard system view for the messageSet, whose label is aString. The listView may be either single or multiple selection type" | topView listHeight annoHeight optButtonHeight codeHeight aListView underPane annotationPane buttonsView aBrowserCodeView | listHeight _ 70. annoHeight _ 10. optButtonHeight _ aChangeList optionalButtonHeight. codeHeight _ 110. topView _ (StandardSystemView new) model: aChangeList; label: aString; minimumSize: 200 @ 120; borderWidth: 1. aListView _ (multiSelect ifTrue: [PluggableListViewOfMany on: aChangeList list: #list primarySelection: #listIndex changePrimarySelection: #togglePrimaryListIndex: listSelection: #listSelectionAt: changeListSelection: #listSelectionAt:put: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])] ifFalse: [PluggableListView on: aChangeList list: #list selected: #listIndex changeSelected: #toggleListIndex: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])]). aListView window: (0 @ 0 extent: 200 @ listHeight). topView addSubView: aListView . underPane _ aListView. aChangeList wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: aChangeList text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0 @ 0 extent: 200 @ 10). topView addSubView: annotationPane below: underPane. underPane _ annotationPane . codeHeight _ codeHeight - annoHeight]. aChangeList wantsOptionalButtons ifTrue: [buttonsView _ aChangeList optionalButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. codeHeight _ codeHeight - optButtonHeight]. aBrowserCodeView _ PluggableTextView on: aChangeList text: #contents accept: #contents: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. aBrowserCodeView scrollingView controller: ReadOnlyTextController new. aBrowserCodeView window: (0 @ 0 extent: 200 @ codeHeight). topView addSubView: aBrowserCodeView below: underPane. topView controller open.! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/17/2002 11:37'! changeSetListKey: aChar from: view "Respond to a Command key. I am a model with a listView that has a list of changeSets." aChar == $b ifTrue: [^ self browseChangeSet]. aChar == $B ifTrue: [^ self openChangeSetBrowser]. aChar == $c ifTrue: [^ self copyAllToOther]. aChar == $D ifTrue: [^ self toggleDiffing]. aChar == $f ifTrue: [^ self findCngSet]. aChar == $m ifTrue: [^ self newCurrent]. aChar == $n ifTrue: [^ self newSet]. aChar == $o ifTrue: [^ self fileOut]. aChar == $p ifTrue: [^ self addPreamble]. aChar == $r ifTrue: [^ self rename]. aChar == $s ifTrue: [^ self chooseChangeSetCategory]. aChar == $x ifTrue: [^ self remove]. aChar == $- ifTrue: [^ self subtractOtherSide]. ^ self messageListKey: aChar from: view! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/29/2003 08:09'! changeSetMenu: aMenu shifted: isShifted "Set up aMenu to hold commands for the change-set-list pane. This could be for a single or double changeSorter" isShifted ifTrue: [^ self shiftedChangeSetMenu: aMenu]. Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu title: 'Change Set: ' , myChangeSet name]. aMenu add: 'make changes go to me (m)' action: #newCurrent. aMenu addLine. aMenu add: 'new change set... (n)' action: #newSet. aMenu add: 'find...(f)' action: #findCngSet. aMenu add: 'show category... (s)' action: #chooseChangeSetCategory. aMenu balloonTextForLastItem: 'Lets you choose which change sets should be listed in this change sorter'. aMenu add: 'select change set...' action: #chooseCngSet. aMenu addLine. aMenu add: 'rename change set (r)' action: #rename. aMenu add: 'file out (o)' action: #fileOut. " aMenu add: 'mail to list' action: #mailOut. " aMenu add: 'browse methods (b)' action: #browseChangeSet. aMenu add: 'browse change set (B)' action: #openChangeSetBrowser. aMenu addLine. parent ifNotNil: [aMenu add: 'copy all to other side (c)' action: #copyAllToOther. aMenu add: 'submerge into other side' action: #submergeIntoOtherSide. aMenu add: 'subtract other side (-)' action: #subtractOtherSide. aMenu addLine]. myChangeSet hasPreamble ifTrue: [aMenu add: 'edit preamble (p)' action: #addPreamble. aMenu add: 'remove preamble' action: #removePreamble] ifFalse: [aMenu add: 'add preamble (p)' action: #addPreamble]. myChangeSet hasPostscript ifTrue: [aMenu add: 'edit postscript...' action: #editPostscript. aMenu add: 'remove postscript' action: #removePostscript] ifFalse: [aMenu add: 'add postscript...' action: #editPostscript]. aMenu addLine. aMenu add: 'category functions...' action: #offerCategorySubmenu. aMenu balloonTextForLastItem: 'Various commands relating to change-set-categories'. aMenu addLine. aMenu add: 'destroy change set (x)' action: #remove. aMenu addLine. aMenu add: 'more...' action: #offerShiftedChangeSetMenu. ^ aMenu! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:28'! classListKey: aChar from: view "Respond to a Command key in the class-list pane." aChar == $x ifTrue: [^ self removeClass]. aChar == $d ifTrue: [^ self forgetClass]. aChar == $m ifTrue: [^ self moveClassToOther]. ^ self messageListKey: aChar from: view "picks up b,h,p"! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:24'! classListMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the class list" aMenu title: 'class list'. (parent notNil and: [shifted not]) ifTrue: [aMenu addList: #( "These two only apply to dual change sorters" ('copy class chgs to other side' copyClassToOther) ('move class chgs to other side (m)' moveClassToOther) ('copy chgs to other side from classes matching...' copyClassesToOtherMatching) ('move chgs to other side from classes matching...' moveClassesToOtherMatching) )]. aMenu addList: (shifted ifFalse: [#( - ('delete class from change set (d)' forgetClass) ('remove class from system (x)' removeClass) - ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' spawnHierarchy) ('browse protocol (p)' browseFullProtocol) - ('printOut' printOutClass) ('fileOut' fileOutClass) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' browseClassVarRefs) ('class vars' browseClassVariables) ('class refs (N)' browseClassRefs) - ('more...' offerShiftedClassListMenu))] ifTrue: [#( - ('unsent methods' browseUnusedMethods) ('unreferenced inst vars' showUnreferencedInstVars) ('unreferenced class vars' showUnreferencedClassVars) - ('sample instance' makeSampleInstance) ('inspect instances' inspectInstances) ('inspect subinstances' inspectSubInstances) - ('more...' offerUnshiftedClassListMenu ))]). ^ aMenu! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:13'! copyClassesToOtherMatching "Adsk the user for a pattern. Copy matching changes from this changeset in the other changeSet" | otherSorter otherChangeSet pattern classNamesToCopy | self checkThatSidesDiffer: [^ self halt]. self okToChange ifFalse: [^ self halt]. otherSorter _ parent other: self. otherChangeSet _ otherSorter changeSet. pattern _ FillInTheBlank request: 'Enter a pattern to match to the class to copy changes: # = single character wildcard * = many character wildcard'. ''. pattern isEmpty ifTrue: [^ self ]. classNamesToCopy _ OrderedCollection new. self changeSet changedClassNames do: [:nm | (pattern match: nm) ifTrue:[classNamesToCopy add: nm]]. classNamesToCopy do:[:clsnm| otherChangeSet absorbClass: clsnm from: myChangeSet]. otherSorter showChangeSet: otherChangeSet.! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:22'! moveClassesToOtherMatching "Adsk the user for a pattern. Move matching changes from this changeset in the other changeSet" | otherSorter otherChangeSet pattern classNamesToCopy | self checkThatSidesDiffer: [^ self halt]. self okToChange ifFalse: [^ self halt]. otherSorter _ parent other: self. otherChangeSet _ otherSorter changeSet. pattern _ FillInTheBlank request: 'Enter a pattern to match to the class to copy changes: # = single character wildcard * = many character wildcard'. ''. pattern isEmpty ifTrue: [^ self ]. classNamesToCopy _ OrderedCollection new. self changeSet changedClassNames do: [:nm | (pattern match: nm) ifTrue:[classNamesToCopy add: nm]]. classNamesToCopy do:[:clsnm| otherChangeSet absorbClass: clsnm from: myChangeSet. myChangeSet removeClassChanges: clsnm]. currentClassName _ nil. currentSelector _ nil. self showChangeSet: myChangeSet. otherSorter showChangeSet: otherChangeSet.! ! Object subclass: #Benchmark instanceVariableNames: 'dummy verboseTranscript reporting reportStream fromList' classVariableNames: 'Outputs StandardTests' poolDictionaries: '' category: 'RVM-Testing'! !Benchmark commentStamp: 'ssa 8/19/2008 22:14'! Benchmark testStandardToFile: (FileStream fileNamed: 'test1.timing'). Benchmark testStandardToFile: (FileStream fileNamed: 'test2.timing'). Benchmark new compareOldTimes: 'test1.timing' toNewTimes: 'test2.timing' outputTo: 'compare1-2.timing'. Benchmark new displayOutputNamed: 'compare1-2.timing' --------------original comment follows------------------------------- Class Benchmark contains facilities for timing the performance of your system and reporting the results. There are built-in methods for timing certain activities that occur frequently in using Smalltalk-80. There are also facilities for timing the execution of most byte codes. It is intended that comparison of timing information between implementations and over time will allow implementors to discover where their systems could stand improvement and to gauge the value of intended performance enhancements. The main interface to these facilities is through sending the messsage Benchmark new test: aBlock labeled: aLabel repeated: howManyTimes. This will cause howManyTimes executions of aBlock and report the results, using aLabel for ease of identification. The results can be reported in several different ways. The default is to print a fairly verbose report in the Transcript. But the reporting mode can be altered by sending the Benchmark which is going to perform a given test the message setOutputParameters. This gives you the option of directing the report to a file or an internal stream and also of shortening the feedback in the Transcript. The system automatically invites you to respecify the output parameters (e.g. naming a new output report file) whenever you test more than one thing at a time, using the message testList: (as in testStandardTests below). Try an example. To time your system's performance of simple addition, say Benchmark new test3plus4 or to time pushing an instance variable onto the stack, say Benchmark new testLoadInstVar. If you had wished to print the results on a file or internal stream, you could have said Benchmark new setOutputParameters testLoadInstVar. If you look at the code for these methods (e.g. testLoadInstVar), you will notice that it does a few things that you didn't want to time, such as sending the message ==, or popping things off the stack. This is to make the compiler happy or to keep the stack from overflowing. So you may want to subtract this stuff out. (Use systems of equations. Be clever!!) The message category "macro operations" contains methods for timing more involved activities such as compiling, decompiling, editing text, formatting text, etc. There is a message to class Benchmark which will invoke all the built-in benchmarks sequentially. Say Benchmark testStandardTests. There are also facilities for examining or automatically comparing the output files or streams generated by testing a bunch of benchmarks sequentially. See the "output" category. Be sure to read the comment to the streamsRatherThanFiles code. Have fun and share your results with a friend. ! MouseMenuController subclass: #RVMAspectLabelController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! Object subclass: #RVMBarrier instanceVariableNames: 'interlock waitSema signalsNeededToPass' classVariableNames: '' poolDictionaries: '' category: 'RVM-Misc'! MouseMenuController subclass: #RVMButtonController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMCanvasController instanceVariableNames: '' classVariableNames: 'Marker' poolDictionaries: '' category: 'RVM-UI-TraceBased'! MouseMenuController subclass: #RVMCheckBoxController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMColorButtonController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMColorScaleController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! MouseMenuController subclass: #RVMCoreIndexController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMGridLocationController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMGroupLocatorController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! MouseMenuController subclass: #RVMKiviatController instanceVariableNames: 'scalerAdjusters' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Kiviat'! MouseMenuController subclass: #RVMMultiAspectKiviatController instanceVariableNames: 'scalerAdjusters' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Kiviat'! MouseMenuController subclass: #RVMMultiAspectStripChartController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Leftovers'! RVMGroupLocatorController subclass: #RVMMultiGroupLocatorController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! Object subclass: #RVMObject instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMAllCPUCoreStats instanceVariableNames: 'coreStats rawData' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMCPUCoreStats instanceVariableNames: 'rawData millisecondsSinceLastQuery cyclesSinceLastQuery sendTallies receiveTally memorySystemStats squeakInterpreterStats messageNames myX myY myRank objectTableStats' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMCircularCollection instanceVariableNames: 'array begin end numberOfElements size nextIndex' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMObject subclass: #RVMColoredDataScaler instanceVariableNames: 'scaler color' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMObject subclass: #RVMCoreMessageTally instanceVariableNames: 'talliesInOrderCache allocateOrRecycleContextMessage allocateOrRecycleContextJustTestingMessage recycleContextIfPossibleMessage flushInterpreterCachesMessage flushMethodCacheMessage flushByMethodMessage flushSelectiveMessage addObjectFromSnapshotMessage updateWholeInterpreterMessage updateEnoughInterpreterToTransferControlMessage updateEnoughInterpreterToTransferControlJustTestingMessage updateEnoughInterpreterToTransferControlJustTestingResponse zapUnusedPortionOfHeapMessage zapUnusedPortionOfHeapResponse verifyInterpreterAndHeapMessage doAllRootsThereMessage doAllRootsThereResponse doAllRootsHereMessage hereIsARootResponse newValueForOopMessage noMoreRootsResponse scanCompactOrMakeFreeObjectsMessage scanCompactOrMakeFreeObjectsResponse returnContextMessage runPrimitiveMessage runPrimitiveJustTestingMessage runPrimitiveResponse loadFunctionFromPluginMessage loadFunctionFromPluginResponse broadcastInterpreterDoublewordMessage broadcastInterpreterWordMessage broadcastInterpreterBoolMessage sampleOneCoreMessage sampleOneCoreResponse initiateBarrierMessage respondToBarrierMessage aboutToWriteReadMostlyMemoryMessage aboutToWriteReadMostlyMemoryResponse wroteReadMostlyMemoryMessage flushFreeContextsMessage enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse rawData' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMDataScaler instanceVariableNames: 'aspect min max range observedMin observedMax lastObserved automaticScaling outOfRangeDetected pinAtZero minLocked maxLocked' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMObject subclass: #RVMExperiment instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Experiments'! RVMObject subclass: #RVMGroupStats instanceVariableNames: 'mainX mainY mainRank groupSize remaining width height' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMHeapStats instanceVariableNames: 'readWrite bytesUsed bytesLeft allocationsSinceLastQuery compactionsSinceLastQuery' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMHeapStats subclass: #RVMGlobalHeapStats instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Leftovers'! RVMHeapStats subclass: #RVMLocalHeapStats instanceVariableNames: 'objectsFetchedSinceLastQuery overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery failedFetchRequestsSinceLastQuery objectsFlushedSinceLastQuery' classVariableNames: '' poolDictionaries: '' category: 'RVM-Leftovers'! RVMObject subclass: #RVMMemorySystemStats instanceVariableNames: 'gcCount gcMilliseconds gcCycles readWriteHeapStats readMostlyHeapStats' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMMonitor instanceVariableNames: '' classVariableNames: 'DelayTiming LastSample Listeners RecordingFile RecordingMode SampleLimit Samples SamplingProcess ShowHeartbeat ShowTestAspects TurboSampling' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMMulticoreSample instanceVariableNames: 'rawData messageNames cpuCoreStats groupStats runMask fence processInstanceCount' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! !RVMMulticoreSample commentStamp: 'ssa 8/19/2008 11:52'! two ways to capture a sample: RVMMulticoreSample captureSlow - uses a flexible but slower approach to handle data pairs " captureFast - fast, order dependent version (6x faster) " capture - calls captureFast "performance test" results := OrderedCollection new. 100 timesRepeat:[results add: (Time millisecondsToRun:[1000 timesRepeat:[RVMMulticoreSample captureFast]])/1000.0]. results average captureFast = 0.13813 captureSlow = 0.80164 MessageTally spyOn:[1000 timesRepeat:[RVMMulticoreSample captureFast]] shows a 6x improvement over captureSlow! RVMObject subclass: #RVMObjectCoordinate instanceVariableNames: 'object mutability activity coreIndex coreCoordinate' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! RVMObject subclass: #RVMObjectTableStats instanceVariableNames: 'entryCount allocatedEntryCount entriesFreedSinceLastQuery allocationsSinceLastQuery' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! PluggableTextView subclass: #RVMPluggableTextView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! Object subclass: #RVMProcessSwarm instanceVariableNames: 'processes' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'! !RVMProcessSwarm commentStamp: 'ssa 4/7/2009 13:37'! RVMProcessSwarm newRunning: [1000 timesRepeat:[10 factorial]]. 56 timesRepeat:[1000 timesRepeat:[10 factorial]] (Time millisecondsToRun:[1000 timesRepeat:[10 factorial]])/1000.0 ====> 1.5ms per 10 factorial (Time millisecondsToRun:[1000 timesRepeat:[10 factorial]]) ====> 1587ms per job (Time millisecondsToRun:[10 timesRepeat:[56 timesRepeat:[1000 timesRepeat:[10 factorial]]]])/10.0 87902.1 85059.2 91263 proc _ [RVMTester print: ((Time millisecondsToRun:[10 timesRepeat:[56 timesRepeat:[1000 timesRepeat:[10 factorial]]]])/10.0) printString] copy fixTemps newProcess. proc coreMask: (1 bitShift: 4). proc resume. Process allInstances collect:[:proc| proc coreMask] Process instanceCount Process allInstances do:[:proc| proc coreMask:(1 bitShift:27)] [:x | x _ 10. [x] value] value: 2 Array locate. coord _ Array asObjectCoordinate. delay _ Delay forMilliseconds: 500. 0 to: 55 do:[:coreIndex|delay wait. coord moveToCore: coreIndex] Benchmark new testCompiler Process allInstancesDo:[:each| each coreMask: nil]. RVMTester runOnlyOn: 8. RVMTester runOnAll count _ 0. [[true] whileTrue:[0 to: 55 do: [:i | Processor thisProcess coreMask: (1 bitShift: i). Processor yield. 10 factorial. RVMTester print: '[',count printString,'] finished on core ',Processor thisProcess hostCore printString]. count _ count +1]]fork Process allInstances collect:[:e| e coreMask] RVMTester moveAllToReadMostlyHeaps "RVMProcessSwarm newRunning: [3000 factorial] onCores:(1 to: 10)" "RVMProcessSwarm newRunning: [RVMTester print: Processor thisProcess hostCore factorial printString] onCores:#(1 3 5 7)" "RVMProcessSwarm newRunning: [3000 factorial. RVMTester print: Processor thisProcess hostCore printString,' done'] onCores:(1 to: 10),(40 to:50) "! RVMObject subclass: #RVMSample instanceVariableNames: 'rawData millisecondsSinceLastSample cyclesSinceLastSample globalHeapStats localHeapStats objectTableStats squeakInterpreterStats' classVariableNames: '' poolDictionaries: '' category: 'RVM-Leftovers'! RVMObject subclass: #RVMSampleFlags instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! RVMObject subclass: #RVMSqueakInterpreterStats instanceVariableNames: 'bytecodesExecuted yieldCount millisecondsRunning millisecondsWaiting cyclesRunning cyclesWaiting contextChangeCount interruptCheckCount unforcedInterruptCheckCount' classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'! ColorSystemView subclass: #RVMStandardSystemView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMCanvasController subclass: #RVMStripChartController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! MouseMenuController subclass: #RVMStripChartScaleController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMObject subclass: #RVMStripChartTrace instanceVariableNames: 'rawData scaledData scaler color pen muted' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMStripChartTrace subclass: #RVMAspectTrace instanceVariableNames: 'aspect' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMAspectTrace subclass: #RVMCoreAspectTrace instanceVariableNames: 'coreIndex' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! Object subclass: #RVMTest instanceVariableNames: 'name environment testBlock setUpBlock tearDownBlock assertionBlock lastResult runLog assertions' classVariableNames: 'DebugOnFail' poolDictionaries: '' category: 'RVM-Testing'! !RVMTest commentStamp: 'ssa 7/7/2010 14:09'! See "examples" in my class! Object subclass: #RVMTestResult instanceVariableNames: 'test result assertion' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'! Object subclass: #RVMTestSuite instanceVariableNames: 'tests' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'! RVMObject subclass: #RVMTester instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'! RVMTestSuite subclass: #Sly3SyntaxTests instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! !RVMTester commentStamp: 'ssa 7/7/2010 14:09'! This was the original pargking lot for various VM testing methods! MouseMenuController subclass: #RVMTileGridController instanceVariableNames: 'process' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMTileGridController subclass: #RVMTileStripChartController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! MouseMenuController subclass: #RVMTraceUIHolderController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! MouseMenuController subclass: #RVMValueController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! MouseMenuController subclass: #RVMValueEditorController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! View subclass: #RVMView instanceVariableNames: 'okToDisplay' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMButtonView instanceVariableNames: 'label action style' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMCanvasView instanceVariableNames: 'canvas dirty offset extent' classVariableNames: 'Marker' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMView subclass: #RVMCheckBoxView instanceVariableNames: 'label checked checkStateAction checkAction uncheckAction labelForm checkedBoxForm uncheckedBoxForm' classVariableNames: 'TestState' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMCheckBoxView subclass: #RVMCheckBoxOnlyView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMColorButtonView instanceVariableNames: 'color colorGetter colorSetter' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMCanvasView subclass: #RVMColorScaleView instanceVariableNames: 'scalerSource colorsSource aspectSource orientation aspectLabel adjustScaleBox usesScaler' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMView subclass: #RVMColoredDataScalerView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMExpressionEditorView instanceVariableNames: 'sourceString' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMGridLocationView instanceVariableNames: 'pointGetter extentGetter pointSetter canvas' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMGroupLocatorView instanceVariableNames: 'objectsSource boxes color countsPerCore backgroundCanvas canvas' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! RVMView subclass: #RVMKiviatView instanceVariableNames: 'spokePens aspect spokeColor webColor scaler canvas backgroundCanvas webPen rescaleCounter lastAverage lastTotal drawingBackground firstDisplay rescaleCounterDefault adjustScaleBox blinker' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Kiviat'! !RVMKiviatView commentStamp: ''! I'm a kiviat chart for displaying core aspect data! RVMView subclass: #RVMLabelView instanceVariableNames: 'label' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMLabelView subclass: #RVMAspectLabelView instanceVariableNames: 'getAspectsSelector getAspectSelector setAspectSelector lastAspect' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMLabelView subclass: #RVMCoreIndexView instanceVariableNames: 'getCoreIndex setCoreIndex getAvailableIndicies' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMMinMaxView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMView subclass: #RVMMultiAspectKiviatView instanceVariableNames: 'spokePens aspects spokeColor webColor scalers canvas backgroundCanvas webPen rescaleCounter drawingBackground firstDisplay rescaleCounterDefault adjustScaleBox coreIndicies colors indexIcons blinker' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Kiviat'! !RVMMultiAspectKiviatView commentStamp: ''! I'm a kiviat chart for displaying core aspect data! RVMView subclass: #RVMMultiAspectStripChartView instanceVariableNames: 'aspects chart dotSize data sampleSource coreIndex scalers' classVariableNames: '' poolDictionaries: '' category: 'RVM-Leftovers'! RVMGroupLocatorView subclass: #RVMMultiGroupLocatorView instanceVariableNames: 'sources counts colors' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! RVMKiviatView subclass: #RVMMultiKiviatView instanceVariableNames: 'aspects colors scalers lastTotals lastAverages commonScale pinMinAtZero' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Kiviat'! RVMView subclass: #RVMObjectCoordinateView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Locators'! RVMCheckBoxView subclass: #RVMRadioButtonView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMCanvasView subclass: #RVMStripChartScaleView instanceVariableNames: 'stripChart currentTrace uiHolder adjustScaleBox' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMCanvasView subclass: #RVMStripChartView instanceVariableNames: 'traces rescaleCounter' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMView subclass: #RVMTileGridView instanceVariableNames: 'canvas scale tiles colors maxValue minValue numberOfColors sample data aspect showProcessState' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMTileGridView subclass: #RVMTileGridScalerView instanceVariableNames: 'scaler rescaleCounter' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMTileGridView subclass: #RVMTileStripChartView instanceVariableNames: 'previousData boxSize box boxes count chart' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMTileStripChartView subclass: #RVMScanningStripChartView instanceVariableNames: 'scanner scannerLocation' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMScanningStripChartView subclass: #RVMAbsScanningStripChartView instanceVariableNames: 'scaler' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMTileStripChartView subclass: #RVMTileStripChartScalerView instanceVariableNames: 'scaler rescaleCounter' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TileBased'! RVMView subclass: #RVMTraceUIHolderView instanceVariableNames: 'stripChart' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-TraceBased'! RVMView subclass: #RVMValueView instanceVariableNames: 'label valueGetter valueSetter' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! RVMValueView subclass: #RVMValueEditorView instanceVariableNames: 'box operation lockBox valueBox operationBox oneBox tenBox hundredBox zeroBox prefixBox lockGetter lockSetter canvas lastValue lastOp lastLocked' classVariableNames: '' poolDictionaries: '' category: 'RVM-UI-Generic'! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadInstVar dummy _ 1. self test: [dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. nil] labeled: 'load an instance variable, 20 times' repeated: 10000 "Benchmark new testLoadInstVar"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadLiteralIndirect self test: [Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. nil] labeled: 'load literal indirect (overflow refct), 20 times' repeated: 10000 "Benchmark new testLoadLiteralIndirect"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadLiteralNRef self test: [3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. nil] labeled: 'load nonRefcounted literal, 20 times' repeated: 10000 "Benchmark new testLoadLiteralNRef"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadQuickConstant self test: [1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. nil] labeled: 'load 1, 40 times; send ==, 20 times' repeated: 10000 "Benchmark new testLoadQuickConstant"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadTempNRef | temp | temp _ 1. self test: [temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. nil] labeled: 'load 1 as a temp, 20 times' repeated: 10000 "Benchmark new testLoadTempNRef"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testLoadTempRef | temp | temp _ 0@0. self test: [temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. nil] labeled: 'load 0@0, 20 times' repeated: 10000 "Benchmark new testLoadTempRef"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testPopStoreInstVar self test: [dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. nil] labeled: 'store into an instance variable, 20 times' repeated: 10000 "Benchmark new testPopStoreInstVar"! ! !Benchmark methodsFor: 'load and popStore' stamp: ''! testPopStoreTemp | temp | self test: [temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. nil] labeled: 'store into a temp, 20 times' repeated: 10000 "Benchmark new testPopStoreTemp"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! test16bitArith | twentyK | twentyK _ 20000. self test: [twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. nil] labeled: 'add 20000 + 20000, 10 times' repeated: 1000 "Benchmark new test16bitArith"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! test3div4 self test: [3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. nil] labeled: 'divide 3 by 4, 10 times' repeated: 1000 "Benchmark new test3div4"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! test3lessThan4 self test: [3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. nil] labeled: 'test 3 < 4, 10 times' repeated: 10000 "Benchmark new test3lessThan4"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! test3plus4 self test: [3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. nil] labeled: 'add 3 + 4, 10 times' repeated: 10000 "Benchmark new test3plus4"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! test3times4 self test: [3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. nil] labeled: 'multiply 3 * 4, 10 times' repeated: 10000 "Benchmark new test3times4"! ! !Benchmark methodsFor: 'arithmetic' stamp: ''! testLargeIntArith | eightyK | eightyK _ 80000. self test: [eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. nil] labeled: 'add 80000 + 80000, 10 times' repeated: 100 "Benchmark new testLargeIntArith"! ! !Benchmark methodsFor: 'control' stamp: ''! testActivationReturn self test: [self recur: 14] labeled: 'activate and return, 32K times' repeated: 1 "Benchmark new testActivationReturn"! ! !Benchmark methodsFor: 'control' stamp: ''! testShortBranch self test: [false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. nil] labeled: 'short branch on false, 10 times' repeated: 10000 "Benchmark new testShortBranch"! ! !Benchmark methodsFor: 'control' stamp: ''! testWhileLoop | temp | self test: [temp _ 10000. [temp > 0] whileTrue: [temp _ temp - 1]. nil] labeled: 'simple whileLoop, 10000 times through' repeated: 10 "Benchmark new testWhileLoop"! ! !Benchmark methodsFor: 'arrays and strings' stamp: ''! testArrayAt | array index | array _ #(1 2 3 4 5 6). index _ 4. self test: [array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. nil] labeled: 'send #at: 20 times (to an array)' repeated: 1000 "Benchmark new testArrayAt"! ! !Benchmark methodsFor: 'arrays and strings' stamp: ''! testArrayAtPut | array index element | array _ #(1 2 3 4 5 6). index _ 4. element _ 17. self test: [array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. nil] labeled: 'send #at:put: 20 times (to an array)' repeated: 1000 "Benchmark new testArrayAtPut"! ! !Benchmark methodsFor: 'arrays and strings' stamp: ''! testSize | string | string _ 'abcde'. self test: [string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. nil] labeled: 'send #size 20 times (to a string)' repeated: 1000 "Benchmark new testSize"! ! !Benchmark methodsFor: 'arrays and strings' stamp: ''! testStringAt | string index | string _ 'abcdefg'. index _ 4. self test: [string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. nil] labeled: 'send #at: 20 times (to a string)' repeated: 1000 "Benchmark new testStringAt"! ! !Benchmark methodsFor: 'arrays and strings' stamp: ''! testStringAtPut | string index char | string _ 'abcdefg'. index _ 4. char _ $q. self test: [string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. nil] labeled: 'send #at:put: 20 times (to a string)' repeated: 1000 "Benchmark new testStringAtPut"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testBlockCopy | tC | tC _ thisContext. self test: [tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. nil] labeled: 'execute blockCopy: 0, 20 times' repeated: 1000 "Benchmark new testBlockCopy"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testClass | pt | pt _ 0@0. self test: [pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. nil] labeled: 'send #class 20 times (to a point)' repeated: 1000 "Benchmark new testClass"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testCreation self test: [Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. nil] labeled: 'create 20 uninitialized points' repeated: 1000 "Benchmark new testCreation"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testEQ | temp | temp _ 1. self test: [temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp. nil] labeled: 'send ==, 20 times' repeated: 10000 "Benchmark new testEQ"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testLoadThisContext self test: [thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. nil] labeled: 'load thisContext, 20 times' repeated: 10000 "Benchmark new testLoadThisContext"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testPointCreation self test: [3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. nil] labeled: 'create 3@4, 10 times' repeated: 1000 "Benchmark new testPointCreation"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testPointX | pt | pt _ 0@0. self test: [pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. nil] labeled: 'execute aPoint x, 10 times' repeated: 10000 "Benchmark new testPointX"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testStreamNext | strm | strm _ ReadStream on: 'abcdefghijklmnopqrstuvwxyz'. self test: [strm position: 0. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. nil] labeled: 'execute ReadStream next, 20 times' repeated: 1000 "Benchmark new testStreamNext"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testStreamNextPut | strm ch | strm _ ReadWriteStream on: 'abcdefghijklmnopqrstuvwxyz'. ch _ $q. self test: [strm position: 0. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. nil] labeled: 'execute ReadWriteStream nextPut:, 20 times' repeated: 1000 "Benchmark new testStreamNextPut"! ! !Benchmark methodsFor: 'primitive byte codes' stamp: ''! testValue | block | block _ [3+4]. self test: [block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. nil] labeled: 'evaluate the block: (3+4), 20 times' repeated: 1000 "Benchmark new testValue"! ! !Benchmark methodsFor: 'primitive methods' stamp: ''! testAsFloat self test: [1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. nil] labeled: 'convert 1 to floating point, 20 times' repeated: 100 "Benchmark new testAsFloat"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:08'! testBasicAt | coll index | coll _ Array new: 16. index _ 5. self test: [coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. nil] labeled: 'send #basicAt: 20 times (to an array)' repeated: 1000 "Benchmark new testBasicAt"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:09'! testBasicAtPut | coll index element | coll _ Array new: 16. index _ 5. element _ 17. self test: [coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. nil] labeled: 'send #basicAtPut: 20 times (to a set)' repeated: 1000 "Benchmark new testBasicAtPut"! ! !Benchmark methodsFor: 'primitive methods' stamp: ''! testBitBLT | bLTer | bLTer _ self sampleBitBLT. self test: [bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. nil] labeled: 'call bitBLT 10 times' repeated: 10 "Benchmark new testBitBLT"! ! !Benchmark methodsFor: 'primitive methods' stamp: ''! testFloatingPointAddition | a b | a _ 3.1. b _ 4.1. self test: [a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. nil] labeled: 'add 3.1 plus 4.1, 20 times' repeated: 100 "Benchmark new testFloatingPointAddition"! ! !Benchmark methodsFor: 'primitive methods' stamp: ''! testPerform self test: [3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. nil] labeled: '3 perform: #+ with: 4, 20 times' repeated: 1000 "Benchmark new testPerform"! ! !Benchmark methodsFor: 'primitive methods' stamp: ''! testStringReplace | source sink size | source _ self longishString copy. sink _ source copy. size _ sink size. self test: [sink replaceFrom: 1 to: size with: source startingAt: 1. nil] labeled: 'replace characters in a string' repeated: 100 "Benchmark new testStringReplace"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:51'! testTextScanning | clipRect para range scanner stops | "clipRect _ Display boundingBox. para _ Paragraph withText: 'Hi there, folks' asText. range _ 1 to: para numberOfLines. scanner _ DisplayScanner new. scanner displayLines: range in: para clippedBy: clipRect. stops _ scanner instVarAt: 17." self test: ["scanner destX: 0. scanner scanCharactersFrom: 1 to: 16 in: 'Hi there, folks!!' rightX: 400 stopConditions: stops displaying: true"] labeled: 'DISABLED scan characters (primitive text display)' repeated: 100 "Benchmark new testTextScanning"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:54'! testAllCallsOn self test: [SystemNavigation default allCallsOn: #printStringBase:] labeled: 'find all calls on #printStringBase:' repeated: 3 "Benchmark new testAllCallsOn"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:51'! testAllImplementors self test: [SystemNavigation default allImplementorsOf: #next] labeled: 'find all implementors of #next' repeated: 10 "Benchmark new testAllImplementors"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testClassOrganizer | class | class _ Benchmark. self test: [class organization changeFromString: class organization printString] labeled: 'read and write class organization' repeated: 1 "Benchmark new testClassOrganizer"! ! !Benchmark methodsFor: 'macro operations' stamp: 'dmu 1/1/2009 04:42'! testCompiler self test: [Benchmark compileBenchmark: 'dummy: aBlock repeated: nTimes | i emptyBlock emptyTime blockTime | nTimes > 1000 ifTrue: [^self time: aBlock repeatedK: nTimes // 1000]. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [emptyBlock value]]. blockTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [aBlock value]]. ^blockTime - emptyTime' notifying: nil ] labeled: 'compile dummy method' repeated: 5. Benchmark removeSelector: #dummy:repeated: "Benchmark new testCompiler"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testDecompiler | class | class _ InputSensor. self test: [class selectors do: [:sel | (Decompiler new decompile: sel in: class method: (class compiledMethodAt: sel)) decompileString]] labeled: 'decompile class InputSensor' repeated: 1 "Benchmark new testDecompiler"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:57'! testMandala self test: [Pen new mandala: 30 diameter: 400] labeled: 'testing Mandala' repeated: 2 "Benchmark new testMandala"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testPrintDefinition | class | class _ Compiler. self test: [class definition] labeled: 'print a class definition' repeated: 20 "Benchmark new testPrintDefinition"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testPrintHierarchy | class | class _ InstructionStream. self test: [class printHierarchy] labeled: 'print a class hierarchy' repeated: 10 "Benchmark new testPrintHierarchy"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testTextDisplay | para | para _ Paragraph withText: self textForDisplay. para displayAt: 200@200. self test: [para displayAt: 200@200] labeled: 'display text' repeated: 10 "Benchmark new testTextDisplay"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testTextEditing | aStringHolderView editor selectPoint | aStringHolderView _ self favoriteStringHolderView. editor _ aStringHolderView controller. selectPoint _ 0. self test: [editor selectAt: (selectPoint _ selectPoint + 5). editor replaceSelectionWith: 'Now!! ' asText] labeled: 'text replacement and redisplay' repeated: 20. aStringHolderView release "Benchmark new testTextEditing"! ! !Benchmark methodsFor: 'macro operations' stamp: ''! testTextFormatting | aString aView contents | aString _ self stringForDisplay. aView _ StringHolderView container: StringHolder new. aView window: Display boundingBox viewport: (100@100 extent: 200@200). self test: [aView editString: (aString asText makeSelectorBoldIn: Benchmark) asParagraph] labeled: 'format a bunch of text' repeated: 5. aView release "Benchmark new testTextFormatting"! ! !Benchmark methodsFor: 'testing' stamp: ''! test: aBlock labeled: label repeated: nTimes "This is the main message to a Benchmark. aBlock is repeated nTimes, and the results are reported." | time | time _ self time: aBlock repeated: nTimes. self report: label timedAt: time repeated: nTimes! ! !Benchmark methodsFor: 'testing' stamp: 'ssa 8/19/2008 21:56'! testList: selectorList "This message allows you to test a series of benchmarks and record all the results on a file or stream." fromList _ true. self setOutputParameters. selectorList do: [:selector | self perform: selector]. reporting ifTrue: [self closeOutput: reportStream]. fromList _ false. "Benchmark new testList: #(testLoadInstVar testLoadLiteralIndirect testLoadLiteralNRef testLoadQuickConstant testLoadTempNRef)"! ! !Benchmark methodsFor: 'testing' stamp: 'ssa 8/19/2008 21:56'! testList: selectorList toFile: aFileStream "This message allows you to test a series of benchmarks and record all the results on a file or stream." fromList _ true. self fileOutputParameters: aFileStream. selectorList do: [:selector | self perform: selector. verboseTranscript ifTrue: []]. reporting ifTrue: [self closeOutput: reportStream]. fromList _ false. "Benchmark new testList: #(testLoadInstVar testLoadLiteralIndirect testLoadLiteralNRef testLoadQuickConstant testLoadTempNRef) toFile: (FileStream fileNamed: 'Smalltalk.timing')"! ! !Benchmark methodsFor: 'testing' stamp: ''! time: aBlock repeated10K: tenKTimes | i emptyBlock emptyTime blockTime | tenKTimes > 10000 ifTrue: [^self error: 'one hundred million repetitions is my limit']. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [1 to: tenKTimes do: [:j | i _ 0. [(i _ i + 1) <= 10000] whileTrue: [emptyBlock value]]]. blockTime _ Time millisecondsToRun: [1 to: tenKTimes do: [:j | i _ 0. [(i _ i + 1) <= 10000] whileTrue: [aBlock value]]]. ^blockTime - emptyTime! ! !Benchmark methodsFor: 'testing' stamp: ''! time: aBlock repeated: nTimes "Answer how many milliseconds it takes to repeat aBlock nTimes, corrected for the time to repeat an empty block." | i emptyBlock emptyTime blockTime iBox | nTimes > 10000 ifTrue: [^self time: aBlock repeated10K: nTimes // 10000]. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [emptyBlock value]]. blockTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [aBlock value]]. ^blockTime - emptyTime! ! !Benchmark methodsFor: 'output' stamp: ''! clearOutputs "This allows you to get rid of your old accumulated output streams." Outputs _ nil "Benchmark new clearOutputs"! ! !Benchmark methodsFor: 'output' stamp: ''! closeOutput: aStream self streamsRatherThanFiles ifTrue: [aStream reset] ifFalse: [aStream close]! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:12'! compareOldTimes: oldName toNewTimes: newName outputTo: outName "Compare two sets of benchmark ouput reports." | oldDict newDict labels compareStream oldTime newTime | oldDict _ Dictionary new. newDict _ Dictionary new. labels _ OrderedCollection new. self readOutput: (self outputNamed: oldName) intoDict: oldDict andCollection: nil. self readOutput: (self outputNamed: newName) intoDict: newDict andCollection: labels. compareStream _ self makeOutputNamed: outName. labels do: [:label | (oldDict includesKey: label) ifTrue: [compareStream nextPutAll: label; cr; tab; nextPutAll: 'old time: ', (oldTime _ oldDict at: label) printString; tab; nextPutAll: 'new time: ', (newTime _ newDict at: label) printString; tab. oldTime = 0 ifTrue:[compareStream nextPutAll:'percent change: ERROR oldTime=0';cr;cr] ifFalse:[compareStream nextPutAll: 'percent change: ', (newTime - oldTime * 100.0 / oldTime) printString; cr; cr]]]. self closeOutput: compareStream "Benchmark new compareOldTimes: 'test1.timing' toNewTimes: 'test2.timing' outputTo: 'compare1-2.timing'" "Benchmark new displayOutputNamed: 'compare1-2.timing'"! ! !Benchmark methodsFor: 'output' stamp: ''! displayOutputNamed: name "Create a window on the display to view the contents of the named output. Does not allow editing of the output file or stream." | output contents | output _ self outputNamed: name. contents _ self streamsRatherThanFiles ifTrue: [output contents] ifFalse: [output contentsOfEntireFile]. StringHolderView open: (StringHolder new contents: contents) label: name! ! !Benchmark methodsFor: 'output' stamp: ''! makeOutputNamed: name "Create a new output file or stream of the given name." self streamsRatherThanFiles ifTrue: [Outputs == nil ifTrue: [Outputs _ Dictionary new]. Outputs at: name put: (ReadWriteStream on: (String new: 1000))]. ^self outputNamed: name! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:06'! outputNamed: name "Answer with the output file or stream of the given name." self streamsRatherThanFiles ifTrue: [^Outputs at: name] ifFalse: [^FileStream fileNamed: name]! ! !Benchmark methodsFor: 'output' stamp: ''! readOutput: aStream intoDict: aDict andCollection: aColl "Parse the output file or stream, aStream, putting labels and times in aDict. If aColl is non-nil (but rather an ordered collection), also add the labels to it in order." | leftBracket rightBracket tab space label value | leftBracket _ $[. rightBracket _ $]. tab _ $ . space _ $ . aStream upTo: leftBracket. [aStream atEnd] whileFalse: [label _ aStream upTo: rightBracket. aColl notNil ifTrue: [aColl add: label]. aStream next: 2; upTo: tab. value _ Number readFrom: (ReadStream on: (aStream upTo: space)). aDict at: label put: value. aStream upTo: leftBracket]. self closeOutput: aStream! ! !Benchmark methodsFor: 'output' stamp: ''! report: label timedAt: time repeated: numberOfTimes "Do all the reporting, both in the Transcript and on the output file or stream." | reportString | reportString _ self reportStringFor: label timedAt: time repeated: numberOfTimes. verboseTranscript ifTrue: [Transcript show: reportString] ifFalse: [Transcript show: ' [', label, ']']. reporting ifTrue: [reportStream nextPutAll: reportString. fromList ifFalse: [self closeOutput: reportStream]]! ! !Benchmark methodsFor: 'output' stamp: ''! reportStringFor: label timedAt: time repeated: numberOfTimes "Generate the parsible string to represent the measurement of a benchmark." | nTimes unitTime seconds aStream| aStream _ WriteStream on: (String new: 200). nTimes _ numberOfTimes <= 1000 ifTrue: [numberOfTimes] ifFalse: [numberOfTimes // 1000 * 1000]. seconds _ time asFloat / 1000. aStream cr; nextPutAll: 'Testing: [' , label , ']'; cr. aStream tab; print: nTimes; nextPutAll: ' repetition(s) in'; cr; tab; print: seconds; nextPutAll: ' seconds'; cr. nTimes ~= 1 ifTrue: [unitTime _ (time * 1000) asFloat / nTimes. aStream tab; print: unitTime; nextPutAll: ' microseconds per repetition'; cr]. ^aStream contents! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:05'! streamsRatherThanFiles "Should the named outputs be (internal Smalltalk-80) streams rather than disk files? They should if there is no file system. Feel free to change this method if you have a file system but want streams anyway." ^false! ! !Benchmark methodsFor: 'instance initialization' stamp: ''! defaultOutputParameters reporting _ false. verboseTranscript _ true. fromList _ false! ! !Benchmark methodsFor: 'instance initialization' stamp: ''! fileOutputParameters: aFileStream reporting _ true. reportStream _ aFileStream. verboseTranscript _ false! ! !Benchmark methodsFor: 'instance initialization' stamp: 'ssa 8/19/2008 22:24'! setOutputParameters | answer | BinaryChoice message: 'Would you like the transcript to just show labels, rather than full reports?' displayAt: Sensor mousePoint centered: true ifTrue: [verboseTranscript _ false] ifFalse: [verboseTranscript _ true]. BinaryChoice message: 'Should the full reports to be output (saved on a file or stream)?' displayAt: Sensor mousePoint centered: true ifTrue: [reporting _ true] ifFalse: [reporting _ false]. reporting ifTrue: [answer := FillInTheBlank request: 'Please supply desired output name' initialAnswer: '.timing' centerAt: Sensor mousePoint. answer isEmpty ifFalse:[reportStream _ self makeOutputNamed: answer] ifTrue:[reporting := false]]! ! !Benchmark methodsFor: 'private' stamp: ''! favoriteStringHolderView | aStringHolderView message | message _ self longishString. aStringHolderView _ StringHolderView container: (StringHolder new contents: message). aStringHolderView window: (0@0 extent: 300@200). aStringHolderView translateBy: 100@250. aStringHolderView display. ^aStringHolderView! ! !Benchmark methodsFor: 'private' stamp: ''! longishString ^ 'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.'! ! !Benchmark methodsFor: 'private' stamp: ''! recur: exp "Invokes a recursion involving ((2 raisedTo: exp+1) - 1) activations and returns." exp = 0 ifTrue: [^self]. self recur: exp - 1. ^self recur: exp - 1! ! !Benchmark methodsFor: 'private' stamp: 'ssa 8/19/2008 21:11'! sampleBitBLT ^BitBlt destForm: Display sourceForm: nil halftoneForm: Color black combinationRule: Form reverse destOrigin: 0@0 sourceOrigin: 0@0 extent: 400@400 clipRect: Display boundingBox! ! !Benchmark methodsFor: 'private' stamp: ''! stringForDisplay ^'testTextDisplay | clipRect para range scanner | clipRect _ Display boundingBox. para _ Paragraph withText: self textForDisplay. range _ 1 to: para numberOfLines. scanner _ DisplayScanner new. self test: [scanner displayLines: range in: para clippedBy: clipRect] labeled: ''displaying text'' repeated: 10 "Benchmark new testTextDisplay"'! ! !Benchmark methodsFor: 'private' stamp: ''! textForDisplay ^self stringForDisplay asText! ! !Benchmark class methodsFor: 'standard tests' stamp: 'ssa 8/19/2008 21:36'! setStandardTests "These are all the built-in benchmarks. Feel free to change if you add more or think some of these are useless. To just execute a few, use testList: directly." StandardTests _ #(testLoadInstVar testLoadTempNRef testLoadTempRef testLoadQuickConstant testLoadLiteralNRef testLoadLiteralIndirect testPopStoreInstVar testPopStoreTemp test3plus4 test3lessThan4 test3times4 test3div4 test16bitArith testLargeIntArith testActivationReturn testShortBranch testWhileLoop testArrayAt testArrayAtPut testStringAt testStringAtPut testSize testPointCreation testStreamNext testStreamNextPut testEQ testClass testBlockCopy testValue testCreation testPointX testLoadThisContext testBasicAt testBasicAtPut testPerform testStringReplace testAsFloat testFloatingPointAddition testBitBLT testTextScanning testClassOrganizer testPrintDefinition testPrintHierarchy testAllCallsOn testAllImplementors testCompiler testDecompiler testTextDisplay testTextFormatting testTextEditing )! ! !Benchmark class methodsFor: 'standard tests' stamp: ''! testStandardTests "This message allows you to test the default series of benchmarks and record all the results according to how you answer the interactive prompts." self setStandardTests. self new testList: StandardTests "Benchmark testStandardTests"! ! !Benchmark class methodsFor: 'standard tests' stamp: ''! testStandardToFile: aFileStream "This message allows you to test the default series of benchmarks and record all the results on the specified file or stream." self setStandardTests. self new testList: StandardTests toFile: aFileStream "Benchmark testStandardToFile: (FileStream fileNamed: 'Smalltalk.timing')"! ! !Benchmark class methodsFor: 'instance creation' stamp: ''! new ^super new defaultOutputParameters "Benchmark new inspect"! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:40'! compileBenchmark: text classified: cat notifying: requestor | stamp | stamp _ self acceptsLoggingOfCompilation ifTrue: [Utilities changeStamp] ifFalse: [nil]. ^ self compileBenchmark: text classified: cat withStamp: stamp notifying: requestor ! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:39'! compileBenchmark: text classified: cat withStamp: changeStamp notifying: requestor ^ self compile: text classified: cat withStamp: changeStamp notifying: requestor logSource: false! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:41'! compileBenchmark: code notifying: requestor "Refer to the comment in Behavior|compile:notifying:." ^self compileBenchmark: code classified: ClassOrganizer default notifying: requestor! ! !Collection methodsFor: '*Sly' stamp: 'dmu 9/17/2010 11:04'! parallelCollect: aBlock "#(1 2 3 4 5) asOrderedCollection parallelCollect:[:e| e * 2]" | results task barrier result interlock | "true ifTrue: [^ self collect: aBlock.]." "for debugging" self ifEmpty: [^ self]. (Sly3 serializeForDebugging or: [self size = 1]) ifTrue: [^ self collect: aBlock]. results _ self species new. barrier _ RVMBarrier new signalsNeededToPass: self size. interlock _ Semaphore forMutualExclusion. self do:[:each| task _ [ result _ ([aBlock copy fixTemps value: each] ifCurtailed: [barrier signal. "Tasks do:[:eachTask| eachTask terminate]. Tasks _ OrderedCollection new." "self error: 'Yipes!! An ensemble is NLRing back.'." ] ). interlock critical: [results add: result]. barrier signal] asSlyMemberProcess. task resume]. barrier wait. ^results! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:25'! aspectFromUser | menu answer | menu := CustomMenu new. self view aspects do: [:aspect | menu add: aspect action: aspect]. answer := menu startUp: self view aspect withCaption: 'Select the aspect to monitor' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. self view aspect: answer. self view displayView. self view topView newFrame! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:55'! controlActivity Cursor menu show. super controlActivity! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:55'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 16:19'! yellowButtonActivity self aspectFromUser. ! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:49'! initialize interlock _ Semaphore new. interlock signal. waitSema _ Semaphore new. signalsNeededToPass _ 0! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 19:14'! signal interlock critical: [ signalsNeededToPass _ signalsNeededToPass - 1. signalsNeededToPass < 0 ifTrue: [self error: 'oops']. signalsNeededToPass = 0 ifTrue: [waitSema signal] ]! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 14:23'! signalsNeededToPass: n signalsNeededToPass _ n! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:32'! wait waitSema wait! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:24'! waitSema ^ waitSema! ! !RVMButtonController methodsFor: 'basic control sequence' stamp: 'ssa 1/1/1970 01:12'! redButtonActivity | aborted lastAborted | self view displayPressed. lastAborted _ false. aborted _ true. [Sensor redButtonPressed] whileTrue:[ aborted _ (self view insetDisplayBox containsPoint: Sensor cursorPoint) not. aborted & lastAborted not ifTrue:[self view displayView. lastAborted _ true]. aborted not & lastAborted ifTrue:[self view displayPressed. lastAborted _ false]]. self view displayView. aborted ifFalse:[self view performAction]! ! !RVMButtonController methodsFor: 'controlling' stamp: 'ssa 10/3/2008 20:53'! controlInitialize self view style ~~ #raisedGray ifTrue:[Cursor action show]. super controlInitialize! ! !RVMButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:04'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMCanvasController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:16'! redButtonActivity "Move the offset of the view, effectively scrolling the canvas." | startPoint delta oldOffset | Cursor crossHair show. startPoint _ Sensor cursorPoint. oldOffset _ self view offset. [Sensor redButtonPressed] whileTrue:[delta _ Sensor cursorPoint - startPoint. self view offset: oldOffset + delta. self view displayView]. Cursor normal show ! ! !RVMCanvasController methodsFor: 'controlling' stamp: 'ssa 10/8/2008 19:05'! yellowButtonActivity ! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 11/15/2008 11:04'! clearView Display fill: self view insetDisplayBox fillColor: Color white! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 11/15/2008 11:04'! redButtonActivity | aborted lastAborted | self view displayPressed. lastAborted _ false. aborted _ true. [Sensor redButtonPressed] whileTrue:[ aborted _ (self view insetDisplayBox containsPoint: Sensor cursorPoint) not. aborted & lastAborted not ifTrue:[self clearView. self view displayView. lastAborted _ true]. aborted not & lastAborted ifTrue:[self clearView. self view displayPressed. lastAborted _ false]]. self clearView. self view displayView. aborted ifFalse:[self view performAction]! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 10/19/2008 00:09'! yellowButtonActivity ! ! !RVMCheckBoxController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:20'! controlActivity "Cursor action show." super controlActivity! ! !RVMCheckBoxController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:05'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:50'! colorFromUser "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette." | d startPt save tr oldColor c here s | d _ Display depth. ((Color colorChart == nil) or: [Color colorChart depth ~= Display depth]) ifTrue: [Color colorChart:(Color oldColorPaletteForDepth: d extent: (2 * 144)@80)]. startPt _ Sensor cursorPoint. save _ Form fromDisplay: (startPt extent: Color colorChart extent). Color colorChart displayAt: startPt. tr _ Color colorChart extent - (50@19) corner: Color colorChart extent. tr _ tr translateBy: startPt. oldColor _ nil. [Sensor anyButtonPressed] whileTrue: [ c _ Display colorAt: (here _ Sensor cursorPoint). (tr containsPoint: here) ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c] ifTrue: [ c _ Color transparent. Display fill: (0@61+startPt extent: 20@19) fillColor: Color white]. c = oldColor ifFalse: [ Display fillWhite: (20@61 + startPt extent: 135@19). c isTransparent ifTrue: [s _ 'transparent'] ifFalse: [s _ c shortPrintString. s _ s copyFrom: 7 to: s size - 1]. s displayAt: 20@61 + startPt. oldColor _ c]]. save displayAt: startPt. Sensor waitNoButton. ^ c ! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:56'! controlActivity Cursor menu show. super controlActivity! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:56'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 16:06'! yellowButtonActivity view color: self colorFromUser. view display! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 20:13'! redButtonActivity self view usesScaler ifTrue:[ (self view adjustScaleBox containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]]! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 5/12/2010 10:19'! spawnScaleAdjuster | scaler maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height | scaler _ self view scaler. maxView _ RVMValueEditorView on: scaler valueGetter: [scaler max] valueSetter:[:v|scaler setMax:v. self view model redrawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: scaler valueGetter: [scaler min] valueSetter:[:v|scaler setMin:v. self view model redrawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[scaler resetScaling. self view model redrawOnCanvas; displayView]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[scaler setRangeToObserved. self view model redrawOnCanvas; displayView]. autoScaleCheckBox _ RVMCheckBoxView on: scaler label: 'Automatic Scaling' checkState: [scaler automaticScaling] whenChecked: [scaler automatic. self view model redrawOnCanvas; displayView] whenUnchecked: [scaler manual. self view model redrawOnCanvas; displayView] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: self view aspect. height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. topView controller open! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 5/4/2010 15:41'! yellowButtonActivity self spawnScaleAdjuster! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:14'! controlActivity Cursor menu show. super controlActivity! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:14'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 11/17/2008 17:10'! yellowButtonActivity | currentIndex maxIndex newIndex | currentIndex _ self view coreIndex. maxIndex _ self view availableIndicies. [newIndex _ FillInTheBlank request:'Enter a new core index between 0 and ',(maxIndex - 1)printString,':' initialAnswer: currentIndex printString. (newIndex isEmpty or:[(newIndex asNumber between: 0 and: maxIndex - 1) not])] whileTrue. newIndex asNumber = currentIndex ifTrue:[^self]. self view coreIndex: newIndex asNumber. self view displayView ! ! !RVMGridLocationController methodsFor: 'controlling' stamp: 'ssa 11/16/2008 02:19'! redButtonActivity | point grid box coord cellSize | point _ Sensor cursorPoint. grid _ RVMMonitor extent. box _ self view insetDisplayBox. cellSize _ box extent // grid + 1. coord _ (point - box origin //(cellSize))+1. self view point: coord. view displayView. ! ! !RVMGridLocationController methodsFor: 'controlling' stamp: 'ssa 11/15/2008 16:11'! yellowButtonActivity ! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 11:36'! changeObjectsSourceSourceTo: aString Cursor wait showWhile:[ self view objectsSourceSource: aString. self view changed:#objectsSourceSource]! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 09:45'! redButtonActivity self view hear:nil! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 11:33'! yellowButtonActivity | menu action choices | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:[self view inspect]. menu addLine. choices _ {'Object withAllSubclasses'. 'View withAllSubclasses'. 'Number allSubclasses'. #line. 'String allInstances'. 'Array allInstances'. 'Collection allSubInstances' }. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action:choice]]. action := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. (action isKindOf: BlockContext) ifTrue:[^action value]. action notNil ifTrue:[self changeObjectsSourceSourceTo: action]! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:42'! addCoreAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to monitor' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view addAspect: selectedAspect]]. self view drawOnCanvas. self view displayView ! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 10:26'! changeRescaleCounter | result | self view dontDisplayWhile:[ result _ FillInTheBlank request:'How many samples between rescaling?' initialAnswer: self view rescaleCounterDefault printString. result isNil ifFalse:[result _ result asNumber max:0. self view rescaleCounterDefault:result]]. self view displayView! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:52'! inspectView self view inspect! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 11/11/2008 17:37'! redButtonActivity ((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:55'! removeAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view aspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select aspect to remove:' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view removeAspect: selectedAspect]. ]. self view drawOnCanvas. self view displayView ! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:06'! rescale self view resetScaling. self view displayView! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 09:06'! yellowButtonActivity | menu answer onlyOne maxed | onlyOne _ self view aspectCount = 1. maxed _ self view aspectCount = 4. self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:#inspectView. menu add:'Rescale' action:#rescale. menu add:'Change Rescale Counter' action:#changeRescaleCounter. onlyOne ifTrue:[menu add: 'Change aspect' action: #changeAspect. menu addLine]. maxed ifFalse:[ menu add: 'Add core aspect' action: #addCoreAspect]. onlyOne ifFalse:[menu addLine. menu add: 'Remove aspect' action: #removeAspect.]. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMKiviatController methodsFor: 'menu messages' stamp: 'ssa 10/7/2008 19:38'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'Core aspects' action: #core. menu add: 'Test aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. self view aspect = newAspect ifTrue:[^self]. self view aspect: newAspect]. self view resetScaling. self view drawOnCanvas. self view displayView! ! !RVMKiviatController methodsFor: 'menu messages' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height scalerIndex result | (self view scalers size = 1 or:[self view commonScale])ifFalse:[result _ (PopUpMenu labelArray:self view aspects) startUpWithCaption:'Adjust the scale of which aspect?'. result = 0 ifTrue:[^self]. scalerIndex _ result]ifTrue:[scalerIndex _ 1]. maxView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) max] valueSetter:[:v|(view scalerAt: scalerIndex) setMax:v. view drawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) min] valueSetter:[:v|(view scalerAt: scalerIndex) setMin:v. view drawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[(view scalerAt: scalerIndex) resetScaling. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[(view scalerAt: scalerIndex) setRangeToObserved. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: (view scalerAt: scalerIndex) label: 'Automatic Scaling' checkState: [(view scalerAt: scalerIndex) automaticScaling] whenChecked: [(view scalerAt: scalerIndex) automatic. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [(view scalerAt: scalerIndex) manual. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: (view aspects at: scalerIndex). height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. self scalerAdjusters add: topView. topView controller open! ! !RVMKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:32'! scalerAdjusters "Answer the value of scalerAdjusters" scalerAdjusters isNil ifTrue:[self scalerAdjusters: OrderedCollection new]. ^ scalerAdjusters! ! !RVMKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:31'! scalerAdjusters: anObject "Set the value of scalerAdjusters" scalerAdjusters _ anObject! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:42'! addCoreAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to monitor' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view addAspect: selectedAspect]]. self view drawOnCanvas. self view displayView ! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 10:26'! changeRescaleCounter | result | self view dontDisplayWhile:[ result _ FillInTheBlank request:'How many samples between rescaling?' initialAnswer: self view rescaleCounterDefault printString. result isNil ifFalse:[result _ result asNumber max:0. self view rescaleCounterDefault:result]]. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:52'! inspectView self view inspect! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 11/27/2008 14:00'! redButtonActivity "((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]"! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:55'! removeAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view aspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select aspect to remove:' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view removeAspect: selectedAspect]. ]. self view drawOnCanvas. self view displayView ! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:06'! rescale self view resetScaling. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 11/12/2008 12:48'! yellowButtonActivity | menu answer | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:#inspectView. menu add:'Rescale' action:#rescale. menu add:'Change Rescale Counter' action:#changeRescaleCounter. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMMultiAspectKiviatController methodsFor: 'menu messages' stamp: 'ssa 10/7/2008 19:38'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'Core aspects' action: #core. menu add: 'Test aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. self view aspect = newAspect ifTrue:[^self]. self view aspect: newAspect]. self view resetScaling. self view drawOnCanvas. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'menu messages' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height scalerIndex result | (self view scalers size = 1 or:[self view commonScale])ifFalse:[result _ (PopUpMenu labelArray:self view aspects) startUpWithCaption:'Adjust the scale of which aspect?'. result = 0 ifTrue:[^self]. scalerIndex _ result]ifTrue:[scalerIndex _ 1]. maxView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) max] valueSetter:[:v|(view scalerAt: scalerIndex) setMax:v. view drawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) min] valueSetter:[:v|(view scalerAt: scalerIndex) setMin:v. view drawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[(view scalerAt: scalerIndex) resetScaling. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[(view scalerAt: scalerIndex) setRangeToObserved. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: (view scalerAt: scalerIndex) label: 'Automatic Scaling' checkState: [(view scalerAt: scalerIndex) automaticScaling] whenChecked: [(view scalerAt: scalerIndex) automatic. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [(view scalerAt: scalerIndex) manual. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: (view aspects at: scalerIndex). height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. self scalerAdjusters add: topView. topView controller open! ! !RVMMultiAspectKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:32'! scalerAdjusters "Answer the value of scalerAdjusters" scalerAdjusters isNil ifTrue:[self scalerAdjusters: OrderedCollection new]. ^ scalerAdjusters! ! !RVMMultiAspectKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:31'! scalerAdjusters: anObject "Set the value of scalerAdjusters" scalerAdjusters _ anObject! ! !RVMMultiAspectStripChartController methodsFor: 'menu messages' stamp: 'ssa 9/14/2008 21:49'! eraseStrip self view eraseStrip! ! !RVMMultiAspectStripChartController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 17:44'! redButtonActivity self view displayView! ! !RVMMultiAspectStripChartController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 15:15'! yellowButtonActivity | menu answer | self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := CustomMenu new. menu add: 'erase strip' action: #eraseStrip:. answer := menu startUp: nil withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer]]]! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:44'! changeSourceForGroupNumber: anIndex | menu action choices | menu := CustomMenu new. choices _ {'Object withAllSubclasses'. 'View withAllSubclasses'. 'Number allSubclasses'. #line. 'String allInstances'. 'Array allInstances'. 'Collection allSubInstances' }. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action:choice]]. action := menu startUp: nil withCaption: 'Select an expression to use for group #',(anIndex printString) at: Sensor cursorPoint. action notNil ifTrue:[self changeSourceSourcefromGroupNumber: anIndex to: action]! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:47'! changeSourceSourcefromGroupNumber: anIndex to: aString Cursor wait showWhile:[ self view sourceSourceForGroupNumber: anIndex put: aString. self view changed:#updateDisplay]! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:53'! yellowButtonActivity | menu action choices index | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:[self view inspect]. menu addLine. choices _ view sources collect:[:each| 'Change #',(index _ view sources indexOf: each) printString, ': ',(view sourceSourceForGroupNumber:index)]. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action: (choices indexOf: choice)]]. action := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. (action isKindOf: BlockContext) ifTrue:[^action value]. action notNil ifTrue:[self changeSourceForGroupNumber: action]! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! coreStats "Answer the value of coreStats" coreStats isNil ifTrue:[self coreStats: OrderedCollection new]. ^coreStats! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! coreStats: anObject "Set the value of coreStats" coreStats := anObject! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:34'! initializeFastFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFastFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:05'! initializeFastestFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFastestFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/13/2008 17:25'! initializeFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! allocationsSinceLastReadMostlys ^self coreStats collect:[:each| each allocationsSinceLastReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadWrites ^self coreStats collect:[:each| each allocationsSinceLastReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:52'! allocationsSinceLasts ^self coreStats collect:[:each| each allocationsSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:19'! bytecodeCounts "RVMMulticoreSample capture bytecodeCounts" "Answer the collection of bytecode counts during this sample" ^self coreStats collect:[:each| each bytecodesExecuted]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:37'! bytecodesPerMillisecond "RVMMulticoreSample capture bytecodesPerMillisecond" "Answer the collection of ratios of bytecodes executed per millisecond during this sample" ^self coreStats collect:[:each| each bytecodesPerMillisecond]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:24'! bytecodesPerSecond "RVMMulticoreSample capture bytecodesPerSecond" "Answer the collection of ratios of bytecodes executed per second during this sample" ^self coreStats collect:[:each| each bytecodesPerSecond]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! bytesLeftReadMostlys ^self coreStats collect:[:each| each bytesLeftReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadWrites ^self coreStats collect:[:each| each bytesLeftReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLefts ^self coreStats collect:[:each| each bytesLeft]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:38'! bytesUsedReadMostlys ^self coreStats collect:[:each| each bytesUsedReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:48'! bytesUsedReadWrites ^self coreStats collect:[:each| each bytesUsedReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 1/1/1970 00:07'! bytesUseds ^self coreStats collect:[:each| each bytesUsed]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! compactionsSinceLastReadMostlys ^self coreStats collect:[:each| each compactionsSinceLastReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLastReadWrites ^self coreStats collect:[:each| each compactionsSinceLastReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLasts ^self coreStats collect:[:each| each compactionsSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:07'! contextChangeCounts "RVMMulticoreSample capture contextChangeCounts" "Answer the collection of contextChanges during this sample" ^self coreStats collect:[:each| each contextChangeCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:52'! cyclesRunWaitRatios "RVMMulticoreSample capture cyclesRunWaitRatios" "Answer the collection of ratios during this sample" ^self coreStats collect:[:each| each cyclesRunWaitRatio]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:48'! cyclesRunnings "RVMMulticoreSample capture cyclesRunnings" "Answer the collection of cyclesRunning counts during this sample" ^self coreStats collect:[:each| each cyclesRunning]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:41'! cyclesSinceLasts "RVMMulticoreSample capture cyclesSinceLasts" "Answer the collection of cyclesSinceLasts counts during this sample" ^self coreStats collect:[:each| each cyclesSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:48'! cyclesWaitings "RVMMulticoreSample capture cyclesWaitings" "Answer the collection of cyclesWaiting counts during this sample" ^self coreStats collect:[:each| each cyclesWaiting]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! interruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each interruptCheckCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! millisecondsRunnings "RVMMulticoreSample capture millisecondsRunnings" "Answer the collection of millisecondsRunning counts during this sample" ^self coreStats collect:[:each| each millisecondsRunning]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:37'! millisecondsWaitings "RVMMulticoreSample capture millisecondsWaitings" "Answer the collection of millisecondsWaiting counts during this sample" ^self coreStats collect:[:each| each millisecondsWaiting]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:43'! msRunWaitRatios "RVMMulticoreSample capture msRunWaitRatios" "Answer the collection of ratios during this sample" ^self coreStats collect:[:each| each msRunWaitRatio]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:29'! msSinceLasts "RVMMulticoreSample capture msSinceLasts" "Answer the collection of msSinceLasts counts during this sample" ^self coreStats collect:[:each| each msSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:03'! receiveTallySum | tallies sum s | tallies := self coreStats collect: [:each | each receiveTally]. sum := Array new: (tallies at: 1) rawData size. 1 to: sum size do: [:i | s := 0. 1 to: tallies size do: [:j | s := s + ((tallies at: j) rawData at: i)]. sum at: i put: s]. ^ sum! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:53'! sendTallySums "Answer an array with the sum of all my send tallies in order from all my coreStats" | sums stats | sums _ self coreStats first sendTallySums. 2 to: self coreStats size do:[:index| stats _ self coreStats at: index. sums _ sums + stats sendTallySums]. ^sums! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:27'! sendTallySumsDictionary "Answer a dictionary with the sums of all my send tallies from all my coreStats associated with their name" | dict keys values | dict _ Dictionary new. keys _ RVMCoreMessageTally tallyOrder. values _ self sendTallySums. keys with: values do:[:key :value| dict at: key put: value]. ^dict! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/26/2009 09:55'! sendTallySumsSorted "Answer a sorted collection with the sums of all my send tallies from all my coreStats associated with their name" ^self sendTallySumsDictionary associations asSortedCollection:[:a :b| a value > b value]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 17:06'! sendTallySumsSortedReport "Answer a string to be used as a report of the sorted send tally sums" | report | report _ 'Sorted Send Tallies for all cores',String crlf,'--------------------------',String crlf. self sendTallySumsSorted do:[:assoc| report _ report, assoc value printString,' ',assoc key,String crlf]. ^report! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:07'! unforcedInterruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each unforcedInterruptCheckCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:17'! yieldCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each yieldCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:16'! yieldFrequencies "RVMMulticoreSample capture yieldFrequencies" ^self coreStats collect:[:each| each yieldFrequency]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:37'! yieldsPerSecond "RVMMulticoreSample capture yieldsPerSecond" "Answer the collection of ratios of yields per second during this sample" ^self coreStats collect:[:each| each yieldsPerSecond]! ! !RVMAllCPUCoreStats methodsFor: 'DNU hacks' stamp: 'ssa 3/27/2009 17:26'! doesNotUnderstand: aMessage "Hack DNU to install measurement mesages for tally aspects" | code tallyAspect | (aMessage selector first: 5) = 'sumOf' ifTrue:[ tallyAspect _ aMessage selector last: aMessage selector - 5. tallyAspect at: 1 put: tallyAspect first asLowercase. (RVMMulticoreSample coreTallyAspects includes: tallyAspect) ifFalse:[^super doesNotUnderstand: aMessage]. code _ aMessage selector,' "Answer the sum for this tally aspect from all cores" ^self sendTallySumsDictionary at: #',tallyAspect. self class compile: code classified: 'tallying' notifying: nil. ^self perform: aMessage selector]. ^super doesNotUnderstand: aMessage! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:33'! newFastFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFastFrom: data forMessageNames: messageNames. ^stats! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:05'! newFastestFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFastestFrom: data forMessageNames: messageNames. ^stats! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/13/2008 17:26'! newFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFrom: data forMessageNames: messageNames. ^stats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! cyclesSinceLastQuery "Answer the value of cyclesSinceLastQuery" cyclesSinceLastQuery isNil ifTrue:[self cyclesSinceLastQuery: 0]. ^cyclesSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! cyclesSinceLastQuery: anObject "Set the value of cyclesSinceLastQuery" cyclesSinceLastQuery := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:22'! memorySystemStats "Answer the value of memorySystemStats" memorySystemStats isNil ifTrue:[self memorySystemStats: RVMMemorySystemStats new]. ^memorySystemStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! memorySystemStats: anObject "Set the value of memorySystemStats" memorySystemStats := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! messageNames "Answer the value of messageNames" messageNames isNil ifTrue:[self messageNames: nil]. ^messageNames! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! messageNames: anObject "Set the value of messageNames" messageNames := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:08'! millisecondsSinceLastQuery "Answer the value of millisecondsSinceLastQuery" millisecondsSinceLastQuery isNil ifTrue:[self millisecondsSinceLastQuery: 0]. ^millisecondsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! millisecondsSinceLastQuery: anObject "Set the value of millisecondsSinceLastQuery" millisecondsSinceLastQuery := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myRank "Answer the value of myRank" myRank isNil ifTrue:[self myRank: nil]. ^myRank! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myRank: anObject "Set the value of myRank" myRank := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myX "Answer the value of myX" myX isNil ifTrue:[self myX: nil]. ^myX! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myX: anObject "Set the value of myX" myX := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myY "Answer the value of myY" myY isNil ifTrue:[self myY: nil]. ^myY! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myY: anObject "Set the value of myY" myY := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:54'! objectTableStats "Answer the value of objectTableStats" objectTableStats isNil ifTrue:[self objectTableStats: RVMObjectTableStats new]. ^objectTableStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:54'! objectTableStats: anObject "Set the value of objectTableStats" objectTableStats := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:12'! receiveTally "Answer the value of receiveTally" receiveTally isNil ifTrue:[self receiveTally: nil]. ^receiveTally! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:12'! receiveTally: anObject "Set the value of receiveTally" receiveTally := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:20'! sendTallies "Answer the value of sendTallies" sendTallies isNil ifTrue:[self sendTallies: OrderedCollection new]. ^sendTallies! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! sendTallies: anObject "Set the value of sendTallies" sendTallies := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:11'! squeakInterpreterStats "Answer the value of squeakInterpreterStats" squeakInterpreterStats isNil ifTrue:[self squeakInterpreterStats: RVMSqueakInterpreterStats new]. ^squeakInterpreterStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! squeakInterpreterStats: anObject "Set the value of squeakInterpreterStats" squeakInterpreterStats := anObject! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:22'! initializeCoreStatsFrom: data | valueMap objectMap target | valueMap := { 'x' -> #myX:. 'y' -> #myY:. 'rank' -> #myRank:. }. objectMap := { 'sendTalliesByCore' -> #initializeSendTalliesFrom:. 'receiveTallies' -> #initializeReceiveTalliesFrom:. }. target := self. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'dmu 1/1/1970 01:09'! initializeFastCoreStatsFrom: data self myX: (data at: 2). self myY: (data at: 4). self myRank: (data at: 6). self initializeFastSendTalliesFrom: (data at: 8). self initializeFastReceiveTalliesFrom: (data at: 10). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:47'! initializeFastFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | self rawData: data. target := self. target millisecondsSinceLastQuery: (data at: 2). target cyclesSinceLastQuery: (data at: 4). target initializeFastCoreStatsFrom: (data at: 6). target initializeFastMemorySystemStatsFrom: (data at: 8). target initializeFastSqueakInterpreterStatsFrom: (data at: 10). target initializeFastObjectTableStatsFrom: (data at: 12). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:06'! initializeFastMemorySystemStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats. target gcCount: (data at: 2). target gcMilliseconds: (data at: 4). target gcCycles: (data at: 6). self initializeFastReadWriteHeapStatsFrom: (data at: 8). self initializeFastReadMostlyHeapStatsFrom: (data at: 10). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:53'! initializeFastObjectTableStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self objectTableStats. target allocatedEntryCount: (data at: 2). target entryCount: (data at: 4). target allocationsSinceLastQuery: (data at: 6). target entriesFreedSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeFastReadMostlyHeapStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats readMostlyHeapStats. target bytesUsed: (data at: 2). target bytesLeft: (data at: 4). target allocationsSinceLastQuery: (data at: 4). target compactionsSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeFastReadWriteHeapStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats readWriteHeapStats. target bytesUsed: (data at: 2). target bytesLeft: (data at: 4). target allocationsSinceLastQuery: (data at: 4). target compactionsSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:21'! initializeFastReceiveTalliesFrom: data "data looks like #(395 0 0 1041 1 520 0 0 0 121 0 1 0 1 0 1 28741 10 1 0) number of elements based on number of messages tallied" self receiveTally: (RVMCoreMessageTally fastForData: data)! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 3/25/2009 14:19'! initializeFastSendTalliesFrom: data "data USED TO looks like #('send_tallies' #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 'send_tallies' #(4 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 11 0 0 0) ... as many as we have cores being used) number of elements based on number of messages tallied" "NOW DATA LOOKS LIKE #(0 0 0 4290 0 0 0 0 0 4840 0 0 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 322 0 0)" "OLD CODE 2 to: data size by: 2 do:[:index| self sendTallies add: (RVMCoreMessageTally fastForData: (data at: index))]" "NEW CODE" self sendTallies add: (RVMCoreMessageTally fastForData: data )! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 9/9/2008 22:40'! initializeFastSqueakInterpreterStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self squeakInterpreterStats. target bytecodesExecuted: (data at: 2). target yieldCount: (data at: 4). " target millisecondsRunning: (data at: 6). target millisecondsWaiting: (data at: 8)." target cyclesRunning: (data at: 6). target cyclesWaiting: (data at: 8). target contextChangeCount: (data at: 10). target interruptCheckCount: (data at: 12). target unforcedInterruptCheckCount: (data at: 14) ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:07'! initializeFastestCoreStatsFrom: data "skip the tallies for speed" self myX: (data at: 2). self myY: (data at: 4). self myRank: (data at: 6). " self initializeFastSendTalliesFrom: (data at: 8). self initializeFastReceiveTalliesFrom: (data at: 10)." ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:48'! initializeFastestFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | self rawData: data. target := self. target millisecondsSinceLastQuery: (data at: 2). target cyclesSinceLastQuery: (data at: 4). target initializeFastestCoreStatsFrom: (data at: 6). target initializeFastMemorySystemStatsFrom: (data at: 8). target initializeFastSqueakInterpreterStatsFrom: (data at: 10). target initializeFastObjectTableStatsFrom: (data at: 12). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:48'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap target | self rawData: data. valueMap := { 'millisecs' -> #millisecondsSinceLastQuery:. 'cycles' -> #cyclesSinceLastQuery:. }. objectMap := { 'coreStats' -> #initializeCoreStatsFrom:. 'memorySystemStats' -> #initializeMemorySystemStatsFrom:. 'interpreterStats' -> #initializeSqueakInterpreterStatsFrom:. 'objectTableStats' -> #initializeFastObjectTableStatsFrom:. }. target := self. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:04'! initializeMemorySystemStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | self rawData: data. valueMap := { 'gcCount' -> #gcCount:. 'gcMilliseconds' -> #gcMilliseconds:. 'gcCycles' -> #gcCycles:. 'readWriteHeapStats' -> #initializeReadWriteHeapStatsFrom:. 'readMostlyHeapStats' -> #initializeReadMostlyHeapStatsFrom:. }. target := self memorySystemStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:50'! initializeObjectTableStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap target | valueMap := { 'allocatedEntryCount[rank]' -> #allocatedEntryCount:. 'entryCount[rank]' -> #entryCount:. 'allocationsSinceLastQuery[rank]' -> #allocationsSinceLastQuery:. 'entriesFreedSinceLastQuery[rank]' -> #entriesFreedSinceLastQuery:. }. objectMap := {}. target := self objectTableStats. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeReadMostlyHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocationsSinceLastQuery' -> #allocationsSinceLastQuery:. 'compactionsSinceLastQuery' -> #compactionsSinceLastQuery:. }. target := self memorySystemStats readMostlyHeapStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeReadWriteHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocationsSinceLastQuery' -> #allocationsSinceLastQuery:. 'compactionsSinceLastQuery' -> #compactionsSinceLastQuery:. }. target := self memorySystemStats readWriteHeapStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/13/2008 18:21'! initializeReceiveTalliesFrom: data "data looks like #(395 0 0 1041 1 520 0 0 0 121 0 1 0 1 0 1 28741 10 1 0) number of elements based on number of messages tallied" self receiveTally: (RVMCoreMessageTally forMessageNames: self messageNames andData: data)! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:31'! initializeSendTalliesFrom: data "data looks like #('send_tallies' #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 'send_tallies' #(4 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 11 0 0 0) ... as many as we have cores being used) number of elements based on number of messages tallied" | tally | data do:[:each| each = 'sendTallies' ifFalse:[ tally := RVMCoreMessageTally forMessageNames: self messageNames andData: each. self sendTallies add: tally]]! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 9/9/2008 22:24'! initializeSqueakInterpreterStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | self rawData: data. valueMap := { 'bytecodesExecuted' -> #bytecodesExecuted:. 'yieldCount' -> #yieldCount:. 'contextChangeCount' -> #contextChangeCount:. "'millisecondsRunning' -> #millisecondsRunning:." "'millisecondsWaiting' -> #millisecondsWaiting:." 'cyclesRunning' -> #cyclesRunning:. 'cyclesWaiting' -> #cyclesWaiting:. 'contextChangeCount' -> #contextChangeCount:. 'interruptCheckCount' -> #interruptCheckCount:. 'unforcedInterruptCheckCount' -> #unforcedInterruptCheckCount:. }. target := self squeakInterpreterStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'dmu 8/15/2008 21:03'! processMap: map into: targetObject forData: data | index datum | map do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[ assoc key = 'receiveTallies' ifFalse:[self error:'Can''t find ',assoc key,' in sample data']]. datum := data at: index + 1. targetObject perform: assoc value with: datum]. ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:52'! allocationsSinceLast ^self allocationsSinceLastReadWrite + self allocationsSinceLastReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! allocationsSinceLastReadMostly ^self memorySystemStats readMostlyHeapStats allocationsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! allocationsSinceLastReadWrite ^self memorySystemStats readWriteHeapStats allocationsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:18'! bytecodesExecuted "Answer the count of bytecodes executed during this sample" ^self squeakInterpreterStats bytecodesExecuted! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:18'! bytecodesPerMillisecond "Answer the ratio of bytecodes executed per ms during this sample" ^(self squeakInterpreterStats bytecodesExectued / (1 max: self millisecondsSinceLastQuery) asFloat ) rounded! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:18'! bytecodesPerSecond "Answer the ratio of bytecodes executed per second during this sample" self millisecondsSinceLastQuery = 0 ifTrue:[^0]. ^(self squeakInterpreterStats bytecodesExecuted / (1 max: self millisecondsSinceLastQuery) asFloat * 1000) rounded! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeft ^self bytesLeftReadWrite + self bytesLeftReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeftReadMostly ^self memorySystemStats readMostlyHeapStats bytesLeft ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeftReadWrite ^self memorySystemStats readWriteHeapStats bytesLeft ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:45'! bytesUsed ^self bytesUsedReadWrite + self bytesUsedReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:44'! bytesUsedReadMostly ^self memorySystemStats readMostlyHeapStats bytesUsed ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 1/1/1970 00:54'! bytesUsedReadWrite ^self memorySystemStats readWriteHeapStats bytesUsed ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLast ^self compactionsSinceLastReadWrite + self compactionsSinceLastReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:57'! compactionsSinceLastReadMostly ^self memorySystemStats readMostlyHeapStats compactionsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! compactionsSinceLastReadWrite ^self memorySystemStats readWriteHeapStats compactionsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! contextChangeCount "Answer the count of yields during this sample" ^self squeakInterpreterStats contextChangeCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:53'! cyclesRunWaitRatio "Answer the ratio between my cyclesRunning and cyclesWaiting" ^self squeakInterpreterStats cyclesRunWaitRatio! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:46'! cyclesRunning "Answer the count of cycles spent running during this sample" ^self squeakInterpreterStats cyclesRunning! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:41'! cyclesSinceLast "Answer the count of cycles since last sample" ^self cyclesSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:46'! cyclesWaiting "Answer the count of cycles spect waiting during this sample" ^self squeakInterpreterStats cyclesWaiting! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! interruptCheckCount "Answer the count of yields during this sample" ^self squeakInterpreterStats interruptCheckCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:34'! millisecondsRunning "Answer the count of ms spent running during this sample" ^self squeakInterpreterStats millisecondsRunning! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:53'! millisecondsWaiting "Answer the count of ms spect waiting during this sample" ^self squeakInterpreterStats millisecondsWaiting! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:43'! msRunWaitRatio "Answer the ratio between my msRunning and msWaiting" ^self squeakInterpreterStats msRunWaitRatio! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:27'! msSinceLast "Answer the count of ms since last sample" ^self millisecondsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:55'! sendTallySums "Answer an array with the sum of all my send tallies in order" | sums tally | self sendTallies isEmpty ifTrue:[^#()]. sums _ self sendTallies first talliesInOrder. 2 to: self sendTallies size do:[:index| tally _ self sendTallies at: index. sums _ sums + tally talliesInOrder]. ^sums! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! unforcedInterruptCheckCount "Answer the count of yields during this sample" ^self squeakInterpreterStats unforcedInterruptCheckCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:16'! yieldCount "Answer the count of yields during this sample" ^self squeakInterpreterStats yieldCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:17'! yieldFrequency ^self squeakInterpreterStats yieldFrequency! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:19'! yieldsPerSecond "Answer the ratio of yields per second during this sample" ^(self squeakInterpreterStats yieldCount / (1 max: self millisecondsSinceLastQuery) asFloat * 1000) rounded! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 10:57'! newFastFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFastFrom: data. ^stats! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:05'! newFastestFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFastestFrom: data. ^stats! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/13/2008 17:49'! newFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFrom: data. ^stats! ! !RVMCircularCollection methodsFor: 'add/remove elements' stamp: 'ssa 1/1/1970 00:03'! add: anObject "Add this object to my collection, increment the lastIndex, adjust if there is a rollover." self begin = 0 ifTrue:[ "I have no elements, add the first one" self begin:1. self end: 1] ifFalse:[ "I have elements, add one more and adjust if needed" self numberOfElements = self size ifTrue:["need to rollover the first element" self begin = self size "adjust begin and end" ifTrue:[self begin: 1. self end: self size] ifFalse:[self end: self begin. self begin: self begin + 1]] ifFalse:["no rollover needed" self end: (self end + 1 min: self size)]]. self array at: self end put: anObject. self incrementElements ! ! !RVMCircularCollection methodsFor: 'add/remove elements' stamp: 'ssa 1/1/1970 00:41'! removeAll self begin: 0. self end: 0. self array:nil. self numberOfElements:0! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:53'! array "Answer the value of array" array isNil ifTrue:[self array: (Array new: self size)]. ^ array! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:38'! array: anObject "Set the value of array" array _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! begin "Answer the value of begin" begin isNil ifTrue:[self begin: 0]. ^ begin! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! begin: anObject "Set the value of begin" begin _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:04'! decrementElements self numberOfElements: ((self numberOfElements - 1) max: 0)! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! end "Answer the value of end" end isNil ifTrue:[self end: 0]. ^ end! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! end: anObject "Set the value of end" end _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:12'! incrementElements self numberOfElements: ((self numberOfElements + 1) min: self size)! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! numberOfElements "Answer the value of numberOfElements" numberOfElements isNil ifTrue:[self numberOfElements: 0]. ^ numberOfElements! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! numberOfElements: anObject "Set the value of numberOfElements" numberOfElements _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 10/18/2008 21:37'! realIndexFor: index "Answer the loop adjusted index value" | realIndex | index > self size ifTrue:[realIndex _ index \\ self size] ifFalse:[realIndex _ index]. realIndex _ realIndex - 1 + self begin. realIndex > self size ifTrue:[realIndex _ realIndex - self size]. ^realIndex ! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:52'! size "Answer the value of size" size isNil ifTrue:[self size: 10]. ^ size! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:04'! size: aNumber "Set the value of size" | contents oldSize | size = aNumber ifTrue:[^self]. self isEmpty ifTrue:[size _ aNumber. self array:nil; numberOfElements:0] ifFalse:[contents _ self asOrderedCollection. oldSize _ contents size. size _ aNumber. self begin:0;end:0;numberOfElements:0. self array: (Array new: size). 1 to: (size min: oldSize) do:[:index| self add: (contents at: index)]]. ! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:14'! at: index ^self array at: (self realIndexFor: index)! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:15'! at: index put: anObject self array at: (self realIndexFor: index) put: anObject! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 22:00'! atRandom ^self at: self numberOfElements atRandom! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:27'! first ^self at:1! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:28'! last ^self at:self numberOfElements! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 21:29'! nextIndex "Answer the value of nextIndex" nextIndex isNil ifTrue:[self nextIndex: 1]. ^ nextIndex! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 21:40'! nextIndex: anInteger "Set the value of nextIndex" anInteger > self size ifTrue:[^nextIndex _ 1]. nextIndex _ anInteger! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 1/1/1970 00:40'! asArray ^self asOrderedCollection asArray! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 10/28/2008 19:41'! asCircularCollection ^self! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 1/1/1970 00:20'! asOrderedCollection | oc | oc _ OrderedCollection new. self do:[:each| oc add: each]. ^oc! ! !RVMCircularCollection methodsFor: 'enumerating' stamp: 'ssa 1/1/1970 00:18'! collect: aBlock "Iterate over my elements in order and answer the results" | results | results _ self class new: self size. self do:[:each| results add: (aBlock value: each)]. ^results! ! !RVMCircularCollection methodsFor: 'enumerating' stamp: 'ssa 1/1/1970 00:13'! do: aBlock "Iterate over my elements in order" 1 to: self numberOfElements do:[:index| aBlock value:(self at: index)]! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 5/28/2010 16:55'! atEnd "Acting like an infinite stream" ^false! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:55'! isEmpty ^self numberOfElements = 0! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:55'! isFull ^self numberOfElements = self size! ! !RVMCircularCollection methodsFor: 'printing' stamp: 'ssa 10/3/2008 21:17'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' size:',self size printString,' numberOfElements:',self numberOfElements printString! ! !RVMCircularCollection methodsFor: 'stream emulation' stamp: 'ssa 10/18/2008 21:31'! next "Answer the next element in line, then advance the nextIndex" | item | self isEmpty ifTrue:[self error:'Empty Collection']. item _ self at: self nextIndex. self nextIndex: self nextIndex + 1. ^item! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:19'! new: anInteger | collection | collection _ self new. collection size: anInteger. ^collection! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:42'! new: anInteger withAll: aCollection | collection | collection _ self new: anInteger. aCollection do:[:each| collection add: each]. ^collection! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:42'! withAll: aCollection ^self new: aCollection size withAll: aCollection! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:36'! testAdd "RVMCircularCollection testAdd" | cc bag | cc _ self new: 10. 5 timesRepeat:[cc add: 1]. bag _ cc asOrderedCollection asBag. bag size = 5 & ((bag occurrencesOf: 1) = 5 ) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:39'! testCollect "RVMCircularCollection testCollect" | cc results | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. results _ cc collect:[:each| each]. results asArray = #(16 17 18 19 20) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:38'! testDo "RVMCircularCollection testDo" | cc total | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. total _ 0. cc do:[:each| total _ total + each]. total = #(20 19 18 17 16) sum ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:54'! testResize "RVMCircularCollection testResize" | cc | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. cc size: 2. cc asArray = #(16 17) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:35'! testRollover "RVMCircularCollection testRollover" | cc | cc _ self new: 10. 1 to: 20 do:[:each| cc add: each]. cc asOrderedCollection asArray = #(11 12 13 14 15 16 17 18 19 20) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMColoredDataScaler methodsFor: 'privatizing' stamp: 'ssa 9/17/2008 13:01'! privatize "Install a copy of my current scaler so changes to it won't effect others." self scaler: self scaler deepCopy! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 12:56'! aspect ^self scaler aspect! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:22'! aspect: aSymbol "Swap in a new default scaler for this aspect if different from my current aspect." | defaultScaler | aSymbol == self aspect ifTrue:[^self]. "no need to change" defaultScaler _ RVMMonitor scalerFor: aSymbol. self scaler: defaultScaler "use the shared scaler until user asks for private copy". ! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:22'! color "Answer the value of color" color isNil ifTrue:[self color: Color blue]. ^ color! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:22'! color: anObject "Set the value of color" color _ anObject! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:23'! lastObserved ^self scaler lastObserved! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! max ^self scaler max! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! max: aValue ^self scaler max: aValue! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! min ^self scaler min! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! min: aValue ^self scaler min: aValue! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:24'! scale: someData ^self scaler scale: someData! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:35'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: RVMDataScaler exampleInstance]. ^ scaler! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:35'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMColoredDataScaler methodsFor: 'user interface' stamp: 'ssa 9/17/2008 13:05'! open RVMColoredDataScalerView openOn: self. ! ! !RVMColoredDataScaler methodsFor: 'delegation' stamp: 'ssa 9/17/2008 13:03'! doesNotUnderstand: aMessage "See if my scaler understands it." Transcript cr;show:'delegating: ',aMessage printString. ^self scaler perform: aMessage selector withArguments: aMessage arguments! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:35'! aspect: aSymbol ^self aspect: aSymbol color: Color random! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/14/2008 20:58'! aspect: aSymbol color: aColor | scaler | scaler _ self new. scaler scaler: (RVMMonitor scalerFor: aSymbol). scaler color: aColor. ^scaler! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 22:37'! aspect: aSymbol min: minValue max: maxValue color: aColor | scaler | scaler _ self aspect: aSymbol min: minValue max: maxValue. scaler color: aColor. ^scaler! ! !RVMColoredDataScaler class methodsFor: 'examples' stamp: 'ssa 9/17/2008 14:03'! exampleInstance | cs | cs _ self new. cs scaler:RVMDataScaler exampleInstance. cs color: Color blue. ^cs! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryMessage "Answer the tally for this message." ^aboutToWriteReadMostlyMemoryMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryMessage: aValue "Answer the tally for this message." aboutToWriteReadMostlyMemoryMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryResponse "Answer the tally for this message." ^aboutToWriteReadMostlyMemoryResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryResponse: aValue "Answer the tally for this message." aboutToWriteReadMostlyMemoryResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! addObjectFromSnapshotMessage "Answer the tally for this message." ^addObjectFromSnapshotMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! addObjectFromSnapshotMessage: aValue "Answer the tally for this message." addObjectFromSnapshotMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextJustTestingMessage "Answer the tally for this message." ^allocateOrRecycleContextJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextJustTestingMessage: aValue "Answer the tally for this message." allocateOrRecycleContextJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextMessage "Answer the tally for this message." ^allocateOrRecycleContextMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextMessage: aValue "Answer the tally for this message." allocateOrRecycleContextMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterBoolMessage "Answer the tally for this message." ^broadcastInterpreterBoolMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterBoolMessage: aValue "Answer the tally for this message." broadcastInterpreterBoolMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterDoublewordMessage "Answer the tally for this message." ^broadcastInterpreterDoublewordMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterDoublewordMessage: aValue "Answer the tally for this message." broadcastInterpreterDoublewordMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterWordMessage "Answer the tally for this message." ^broadcastInterpreterWordMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterWordMessage: aValue "Answer the tally for this message." broadcastInterpreterWordMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! determineTalliesInOrder "Answer an array of tallies in the order they appear in the sample" ^self tallyOrder collect:[:label| self perform: label]! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsHereMessage "Answer the tally for this message." ^doAllRootsHereMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsHereMessage: aValue "Answer the tally for this message." doAllRootsHereMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereMessage "Answer the tally for this message." ^doAllRootsThereMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereMessage: aValue "Answer the tally for this message." doAllRootsThereMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereResponse "Answer the tally for this message." ^doAllRootsThereResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereResponse: aValue "Answer the tally for this message." doAllRootsThereResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage "Answer the tally for this message." ^enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage: aValue "Answer the tally for this message." enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse "Answer the tally for this message." ^enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse: aValue "Answer the tally for this message." enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage "Answer the tally for this message." ^enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage: aValue "Answer the tally for this message." enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse "Answer the tally for this message." ^enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse: aValue "Answer the tally for this message." enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage "Answer the tally for this message." ^enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage: aValue "Answer the tally for this message." enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse "Answer the tally for this message." ^enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse: aValue "Answer the tally for this message." enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushByMethodMessage "Answer the tally for this message." ^flushByMethodMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushByMethodMessage: aValue "Answer the tally for this message." flushByMethodMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! flushFreeContextsMessage "Answer the tally for this message." ^flushFreeContextsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! flushFreeContextsMessage: aValue "Answer the tally for this message." flushFreeContextsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushInterpreterCachesMessage "Answer the tally for this message." ^flushInterpreterCachesMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushInterpreterCachesMessage: aValue "Answer the tally for this message." flushInterpreterCachesMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushMethodCacheMessage "Answer the tally for this message." ^flushMethodCacheMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushMethodCacheMessage: aValue "Answer the tally for this message." flushMethodCacheMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushSelectiveMessage "Answer the tally for this message." ^flushSelectiveMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushSelectiveMessage: aValue "Answer the tally for this message." flushSelectiveMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! hereIsARootResponse "Answer the tally for this message." ^hereIsARootResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! hereIsARootResponse: aValue "Answer the tally for this message." hereIsARootResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! initiateBarrierMessage "Answer the tally for this message." ^initiateBarrierMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! initiateBarrierMessage: aValue "Answer the tally for this message." initiateBarrierMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginMessage "Answer the tally for this message." ^loadFunctionFromPluginMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginMessage: aValue "Answer the tally for this message." loadFunctionFromPluginMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginResponse "Answer the tally for this message." ^loadFunctionFromPluginResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginResponse: aValue "Answer the tally for this message." loadFunctionFromPluginResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! newValueForOopMessage "Answer the tally for this message." ^newValueForOopMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! newValueForOopMessage: aValue "Answer the tally for this message." newValueForOopMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! noMoreRootsResponse "Answer the tally for this message." ^noMoreRootsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! noMoreRootsResponse: aValue "Answer the tally for this message." noMoreRootsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! rawData "Answer the tally for this message." ^rawData! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! rawData: aValue "Answer the tally for this message." rawData _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! recycleContextIfPossibleMessage "Answer the tally for this message." ^recycleContextIfPossibleMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! recycleContextIfPossibleMessage: aValue "Answer the tally for this message." recycleContextIfPossibleMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! respondToBarrierMessage "Answer the tally for this message." ^respondToBarrierMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! respondToBarrierMessage: aValue "Answer the tally for this message." respondToBarrierMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! returnContextMessage "Answer the tally for this message." ^returnContextMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! returnContextMessage: aValue "Answer the tally for this message." returnContextMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveJustTestingMessage "Answer the tally for this message." ^runPrimitiveJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveJustTestingMessage: aValue "Answer the tally for this message." runPrimitiveJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveMessage "Answer the tally for this message." ^runPrimitiveMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveMessage: aValue "Answer the tally for this message." runPrimitiveMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveResponse "Answer the tally for this message." ^runPrimitiveResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveResponse: aValue "Answer the tally for this message." runPrimitiveResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreMessage "Answer the tally for this message." ^sampleOneCoreMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreMessage: aValue "Answer the tally for this message." sampleOneCoreMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreResponse "Answer the tally for this message." ^sampleOneCoreResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreResponse: aValue "Answer the tally for this message." sampleOneCoreResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsMessage "Answer the tally for this message." ^scanCompactOrMakeFreeObjectsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsMessage: aValue "Answer the tally for this message." scanCompactOrMakeFreeObjectsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsResponse "Answer the tally for this message." ^scanCompactOrMakeFreeObjectsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsResponse: aValue "Answer the tally for this message." scanCompactOrMakeFreeObjectsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! talliesInOrder "Answer an array of tallies in the order they appear in the sample" ^self talliesInOrderCache! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! talliesInOrderCache "Answer the value of talliesInOrderCache" talliesInOrderCache isNil ifTrue:[self talliesInOrderCache: self determineTalliesInOrder]. ^ talliesInOrderCache! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:04'! talliesInOrderCache: anObject "Set the value of talliesInOrderCache" talliesInOrderCache _ anObject! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:16'! tallyOrder "Answer an array of tally names in the order they appear in the sample" "RVMMulticoreSample primitiveCapture at: 8" ^self class tallyOrder! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingMessage "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingMessage: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingResponse "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlJustTestingResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingResponse: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlJustTestingResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlMessage "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlMessage: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateWholeInterpreterMessage "Answer the tally for this message." ^updateWholeInterpreterMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateWholeInterpreterMessage: aValue "Answer the tally for this message." updateWholeInterpreterMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! verifyInterpreterAndHeapMessage "Answer the tally for this message." ^verifyInterpreterAndHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! verifyInterpreterAndHeapMessage: aValue "Answer the tally for this message." verifyInterpreterAndHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! wroteReadMostlyMemoryMessage "Answer the tally for this message." ^wroteReadMostlyMemoryMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! wroteReadMostlyMemoryMessage: aValue "Answer the tally for this message." wroteReadMostlyMemoryMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapMessage "Answer the tally for this message." ^zapUnusedPortionOfHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapMessage: aValue "Answer the tally for this message." zapUnusedPortionOfHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapResponse "Answer the tally for this message." ^zapUnusedPortionOfHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapResponse: aValue "Answer the tally for this message." zapUnusedPortionOfHeapResponse _ aValue! ! !RVMCoreMessageTally class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:00'! fastForData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. tally allocateOrRecycleContextMessage: (data at: 1). tally allocateOrRecycleContextJustTestingMessage: (data at: 2). tally recycleContextIfPossibleMessage: (data at: 3). tally flushInterpreterCachesMessage: (data at: 4). tally flushMethodCacheMessage: (data at: 5). tally flushByMethodMessage: (data at: 6). tally flushSelectiveMessage: (data at: 7). tally addObjectFromSnapshotMessage: (data at: 8). tally updateWholeInterpreterMessage: (data at: 9). tally updateEnoughInterpreterToTransferControlMessage: (data at: 10). tally updateEnoughInterpreterToTransferControlJustTestingMessage: (data at: 11). tally updateEnoughInterpreterToTransferControlJustTestingResponse: (data at: 12). tally zapUnusedPortionOfHeapMessage: (data at: 13). tally zapUnusedPortionOfHeapResponse: (data at: 14). tally verifyInterpreterAndHeapMessage: (data at: 15). tally doAllRootsThereMessage: (data at: 16). tally doAllRootsThereResponse: (data at: 17). tally doAllRootsHereMessage: (data at: 18). tally hereIsARootResponse: (data at: 19). tally newValueForOopMessage: (data at: 20). tally noMoreRootsResponse: (data at: 21). tally scanCompactOrMakeFreeObjectsMessage: (data at: 22). tally scanCompactOrMakeFreeObjectsResponse: (data at: 23). tally returnContextMessage: (data at: 24). tally runPrimitiveMessage: (data at: 25). tally runPrimitiveJustTestingMessage: (data at: 26). tally runPrimitiveResponse: (data at: 27). tally loadFunctionFromPluginMessage: (data at: 28). tally loadFunctionFromPluginResponse: (data at: 29). tally broadcastInterpreterDoublewordMessage: (data at: 30). tally broadcastInterpreterWordMessage: (data at: 31). tally broadcastInterpreterBoolMessage: (data at: 32). tally sampleOneCoreMessage: (data at: 33). tally sampleOneCoreResponse: (data at: 34). tally initiateBarrierMessage: (data at: 35). tally respondToBarrierMessage: (data at: 36). tally aboutToWriteReadMostlyMemoryMessage: (data at: 37). tally aboutToWriteReadMostlyMemoryResponse: (data at: 38). tally wroteReadMostlyMemoryMessage: (data at: 39). tally flushFreeContextsMessage: (data at: 40). tally enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage: (data at: 41). tally enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse: (data at: 42). tally enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage: (data at: 43). tally enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse: (data at: 44). tally enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage: (data at: 45). tally enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse: (data at: 46). ^tally! ! !RVMCoreMessageTally class methodsFor: 'instance creation' stamp: 'dmu 1/1/1970 00:02'! forMessageNames: aCollectionOfMessageNames andData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. 1 to: data size do:[:index| tally perform:((aCollectionOfMessageNames at: index),':') asSymbol with:(data at: index)]. ^tally! ! !RVMCoreMessageTally class methodsFor: 'code generation' stamp: 'ssa 3/26/2009 10:14'! adaptToNewTallyMessages "RVMCoreMessageTally adaptToNewTallyMessages" "Change this class to work with the new messages" "BE SURE TO UPDATE tallyOrder MESSAGE IF THE TALLY ORDER CHANGES" | messageNames code index | messageNames _ (RVMMulticoreSample primitiveCapture at: 8) asOrderedCollection. messageNames add: 'rawData'. RVMObject subclass: #RVMCoreMessageTally instanceVariableNames: messageNames asArray classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'. code _ 'fastForData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. '. index _ 0. messageNames remove: 'rawData'. messageNames do:[:messageName| index _ index + 1. code _ code, 'tally ',messageName,': (data at: ',index printString,'). ']. code _ code,'^tally'. RVMCoreMessageTally class compile: code classified:'instance creation' notifying:nil. RVMCoreMessageTally removeCategory: 'accessing'. messageNames do:[:selector| code _ selector,' "Answer the tally for this message." ^',selector. RVMCoreMessageTally compile: code classified:'accessing' notifying:nil. code _ selector,': aValue "Answer the tally for this message." ',selector,' _ aValue'. RVMCoreMessageTally compile: code classified:'accessing' notifying:nil]. ! ! !RVMCoreMessageTally class methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:15'! tallyOrder "Answer an array of tally names in the order they appear in the sample" "RVMMulticoreSample primitiveCapture at: 8" ^#(#allocateOrRecycleContextMessage #allocateOrRecycleContextJustTestingMessage #recycleContextIfPossibleMessage #flushInterpreterCachesMessage #flushMethodCacheMessage #flushByMethodMessage #flushSelectiveMessage #addObjectFromSnapshotMessage #updateWholeInterpreterMessage #updateEnoughInterpreterToTransferControlMessage #updateEnoughInterpreterToTransferControlJustTestingMessage #updateEnoughInterpreterToTransferControlJustTestingResponse #zapUnusedPortionOfHeapMessage #zapUnusedPortionOfHeapResponse #verifyInterpreterAndHeapMessage #doAllRootsThereMessage #doAllRootsThereResponse #doAllRootsHereMessage #hereIsARootResponse #newValueForOopMessage #noMoreRootsResponse #scanCompactOrMakeFreeObjectsMessage #scanCompactOrMakeFreeObjectsResponse #returnContextMessage #runPrimitiveMessage #runPrimitiveJustTestingMessage #runPrimitiveResponse #loadFunctionFromPluginMessage #loadFunctionFromPluginResponse #broadcastInterpreterDoublewordMessage #broadcastInterpreterWordMessage #broadcastInterpreterBoolMessage #sampleOneCoreMessage #sampleOneCoreResponse #initiateBarrierMessage #respondToBarrierMessage #aboutToWriteReadMostlyMemoryMessage #aboutToWriteReadMostlyMemoryResponse #wroteReadMostlyMemoryMessage #flushFreeContextsMessage #enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage #enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse #enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage #enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse #enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage #enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse) ! ! !RVMDataScaler methodsFor: 'private' stamp: 'ssa 11/4/2008 15:50'! setMax: aValue "No side effects" max _ aValue. self range:nil! ! !RVMDataScaler methodsFor: 'private' stamp: 'ssa 11/4/2008 15:50'! setMin: aValue "No side effects" min _ aValue. self range:nil! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 11/4/2008 15:08'! adjustMax "Adjust my max based on my observedMax" | newMax | self maxLocked ifTrue:[^self]. newMax _ self max max: self observedMax. self max = newMax ifTrue:[^self]. self outOfRangeDetected: true. self max: newMax! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 11/4/2008 15:09'! adjustMin "Adjust my min based on my observedMin" | newMin | self minLocked ifTrue:[^self]. newMin _ self min min: self observedMin. self min = newMin ifTrue:[^self]. self outOfRangeDetected: true. self min: newMin! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:40'! automatic "Set to automatic scaling mode. This mode expands the min/max over time to adapt to the data being observed. Send the message #resetScaling to flush historical min/max and rescale." self automaticScaling: true. self resetScaling! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:40'! manual "Turn off automatic scaling mode. Stops adapting min/max" self automaticScaling: false. ! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/6/2008 16:28'! resetObservations "Reset my memory of min/max observations and my min/max as well once the first data value is observed." self observedMin:nil. self observedMax: nil.! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:15'! resetOutOfRangeDetector "Reset my out of range detector" self outOfRangeDetected: false.! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/6/2008 16:29'! resetScaling "Reset my memory of min/max observations and my min/max as well once the first data value is observed." min _ nil. max _ nil. observedMin _ nil. observedMax _ nil. range _ nil! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/7/2008 17:35'! scale: someData "Answer a number between 0-100 representing the percentage location of this data between my min and max" self lastObserved: someData. self observedMin:(self observedMin min: someData). self observedMax:(self observedMax max: someData). someData <= self min ifTrue:[^0]. someData >= self max ifTrue:[^100]. ^someData - self min * 100.0 / self range ! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 01:10'! setRangeToObserved "Set my min and max to what I have observed in my data scaling" min _ self observedMin. max _ self observedMax. self range: nil ! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:57'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #notDefinedYet]. ^ aspect! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:56'! aspect: anObject "Set the value of aspect" aspect _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:39'! automaticScaling "Answer the value of automaticScaling" automaticScaling isNil ifTrue:[self automaticScaling: false]. ^ automaticScaling! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:39'! automaticScaling: anObject "Set the value of automaticScaling" automaticScaling _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:33'! lastObserved "Answer the value of lastObserved" lastObserved isNil ifTrue:[self lastObserved: 0]. ^ lastObserved! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:33'! lastObserved: anObject "Set the value of lastObserved" lastObserved _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:08'! max "Answer the value of max" max isNil ifTrue:[^1]. ^ max! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/19/2008 10:53'! max: aNumber "Set the value of max" max _ min isNil ifTrue:[aNumber] ifFalse:[aNumber max: self min]. self range:nil! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! maxLocked "Answer the value of maxLocked" maxLocked isNil ifTrue:[self maxLocked: false]. ^ maxLocked! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! maxLocked: anObject "Set the value of maxLocked" maxLocked _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:22'! min "Answer the value of min" self pinAtZero ifTrue:[^0]. min isNil ifTrue:[self min: 100000000]. ^ min! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/19/2008 10:53'! min: aNumber "Set the value of min" min _ max isNil ifTrue:[aNumber] ifFalse:[aNumber min: self max]. self range:nil! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! minLocked "Answer the value of minLocked" minLocked isNil ifTrue:[self minLocked: false]. ^ minLocked! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! minLocked: anObject "Set the value of minLocked" minLocked _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:45'! observedMax "Answer the value of observedMax" observedMax isNil ifTrue:[self observedMax: -10000000000]. ^ observedMax! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:43'! observedMax: aNumber "Set the value of observedMax" observedMax _ aNumber. self automaticScaling ifTrue:[self adjustMax]! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:45'! observedMin "Answer the value of observedMin" observedMin isNil ifTrue:[self observedMin: 10000000000]. ^ observedMin! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:44'! observedMin: aNumber "Set the value of observedMin" observedMin _ aNumber. self automaticScaling ifTrue:[self adjustMin]! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:14'! outOfRangeDetected "Answer the value of outOfRangeDetected" outOfRangeDetected isNil ifTrue:[self outOfRangeDetected: false]. ^ outOfRangeDetected! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/2/2008 19:12'! outOfRangeDetected: anObject "Set the value of outOfRangeDetected" outOfRangeDetected _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:22'! pinAtZero "Answer the value of pinAtZero" pinAtZero isNil ifTrue:[self pinAtZero: false]. ^ pinAtZero! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:21'! pinAtZero: anObject "Set the value of pinAtZero" pinAtZero _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:50'! pinMinAtZero self pinAtZero: true! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:52'! range "Answer the value of range" range isNil ifTrue:[self range: (self max - self min)]. ^ range! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:52'! range: anObject "Set the value of range" range _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:50'! unpinMinAtZero self pinAtZero: false! ! !RVMDataScaler methodsFor: 'data generation' stamp: 'ssa 9/13/2008 19:33'! atRandom "Answer a random data value in my range." ^ self range atRandom + self min! ! !RVMDataScaler methodsFor: 'autocoding' stamp: 'ssa 9/13/2008 20:13'! harden "Compile a method into RVMMonitor that will reproduce a scaler like me." RVMMonitor autocodeScalerMethodForScaler: self! ! !RVMDataScaler methodsFor: 'user interface' stamp: 'ssa 9/13/2008 22:38'! open | cs | cs _ RVMColoredDataScaler new. cs scaler: self. cs color: Color random. cs open! ! !RVMDataScaler methodsFor: 'printing' stamp: 'ssa 10/6/2008 16:19'! printOn: aStream super printOn: aStream. aStream nextPutAll: 'min:',self min printString,' max:',self max printString! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 17:59'! example1 "RVMDataScaler example1" | scaler | scaler _ self min: 5 max: 15. 1 to: 20 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:00'! example2 "RVMDataScaler example2" | scaler | scaler _ self min: 0.5 max: 1.5. 0.1 to: 2.0 by: 0.1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:02'! example3 "RVMDataScaler example3" | scaler | scaler _ self min: -5 max: -1. -7 to: 0 by: 1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:02'! example4 "RVMDataScaler example4" | scaler | scaler _ self min: -5 max: 5. -7 to: 7 by: 1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:48'! exampleInstance "RVMDataScaler exampleInstance" ^self aspect: #bytesUseds min: 0 max: 100000! ! !RVMDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 19:57'! aspect: aSymbol min: minValue max: maxValue "Answer a new data scaler with this range." | scaler | scaler _ self new. scaler aspect: aSymbol. scaler min: minValue. scaler max: maxValue. ^scaler! ! !RVMDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 19:58'! min: minValue max: maxValue "Answer a new data scaler with this range." ^self aspect: nil min: minValue max: maxValue! ! !RVMExperiment class methodsFor: 'as yet unclassified' stamp: 'dmu 1/1/1970 00:04'! do: aBlock | ms s | RVMMulticoreSample capture. ms := Time millisecondsToRun: aBlock. s := RVMMulticoreSample capture. Transcript cr; show: 'ms: '; show: ms; show: ' yields: '; show: s yieldCounts sum; show: ' bytecodes: '; show: s bytecodeCounts sum; show: ' total/unforced interruptCheckCounts: '; show: s interruptCheckCounts sum; show: '/'; show: s unforcedInterruptCheckCounts sum; cr; show: 'receive tallies: ', s receiveTallySum printString! ! !RVMExperiment class methodsFor: 'as yet unclassified' stamp: 'dmu 1/1/1970 00:14'! testCompiler self do: [Benchmark new testCompiler]! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! coreIndices "Answer a collection of points that give my core indicies as row@column" | points | points _ OrderedCollection new. 1 to: self height do:[:h| 1 to: self width do:[:w| h*w-1 + w > self groupSize ifTrue:[^points "handle odd last row case"]. points add: w@h]]. ^points! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'ssa 11/13/2008 09:41'! extent "Answer the dimensions of my tile grid" ^self width @ self height! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! groupSize ^ groupSize! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! groupSize: x groupSize _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! height ^ height! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! height: x height _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainRank ^ mainRank! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainRank: x mainRank _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainX ^ mainX! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainX: x mainX _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainY ^ mainY! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainY: y mainY _ y! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! remaining ^ remaining! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! remaining: r remaining _ r! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:00'! width ^ width! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! width: x width _ x! ! !RVMGroupStats methodsFor: 'initialize-release' stamp: 'ssa 8/19/2008 10:56'! initializeFastFrom: data self mainX:(data at: 2). self mainY: (data at: 4). self mainRank: (data at: 6). self width: (data at: 8). self height: (data at: 10). self groupSize: (data at: 12). self remaining: (data at: 14). ! ! !RVMGroupStats methodsFor: 'initialize-release' stamp: 'dmu 8/15/2008 22:07'! initializeFrom: data 1 to: data size by: 2 do: [:i| self perform: ((data at: i), ':') asSymbol with: (data at: i + 1) ]! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:06'! allocationsSinceLastQuery "Answer the number of object allocations since the last query" allocationsSinceLastQuery isNil ifTrue:[^0]. ^allocationsSinceLastQuery! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:07'! allocationsSinceLastQuery: count "Set the number of object allocations since the last query" allocationsSinceLastQuery := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:04'! bytesLeft "Answer the number of bytes left in this heap" bytesLeft isNil ifTrue:[^0]. ^bytesLeft! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:05'! bytesLeft: count "Set the number of bytes left in this heap" bytesLeft := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 10/4/2008 08:38'! bytesUsed "Answer the number of bytes used in this heap" bytesUsed isNil ifTrue:[^0]. ^bytesUsed ! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:04'! bytesUsed: count "Set the number of bytes used in this heap" bytesUsed := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:06'! compactionsSinceLastQuery "Answer the number of object compactions since the last query" compactionsSinceLastQuery isNil ifTrue:[^0]. ^compactionsSinceLastQuery! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:07'! compactionsSinceLastQuery: count "Set the number of object compactions since the last query" compactionsSinceLastQuery := count! ! !RVMHeapStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:27'! readWrite "Answer the value of readWrite" readWrite isNil ifTrue:[self readWrite: true]. ^ readWrite! ! !RVMHeapStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:27'! readWrite: anObject "Set the value of readWrite" readWrite _ anObject! ! !RVMGlobalHeapStats methodsFor: 'testing' stamp: 'ssa 7/21/2008 10:09'! isGlobal ^true! ! !RVMGlobalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:09'! scope "Answer my scope" ^'Global'! ! !RVMHeapStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:27'! newReadMostly ^self new readWrite: false ! ! !RVMHeapStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:28'! newReadWrite ^self new readWrite: true! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:31'! failedFetchRequestsSinceLastQuery "Answer how many fetch requests failed since the last query" failedFetchRequestsSinceLastQuery isNil ifTrue:[^0]. ^failedFetchRequestsSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:29'! failedFetchRequestsSinceLastQuery: count "Set how many fetch requests failed since the last query" failedFetchRequestsSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 11:09'! objectsFetchedSinceLastQuery "Answer how many objects were fetched into this local heap since the last query" objectsFetchedSinceLastQuery isNil ifTrue:[^0]. ^objectsFetchedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 11:09'! objectsFetchedSinceLastQuery: count "Set how many objects were fetched into this local heap since the last query" objectsFetchedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:32'! objectsFlushedSinceLastQuery "Answer how many objects were flushed since the last query" objectsFlushedSinceLastQuery isNil ifTrue:[^0]. ^objectsFlushedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:32'! objectsFlushedSinceLastQuery: count "Set how many objects were flushed since the last query" objectsFlushedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:26'! overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery "Answer how many 'cramden' requests were denied since the last query" overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery isNil ifTrue:[^0]. ^overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:27'! overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery: count "Set how many 'cramden' requests were denied since the last query" overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:11'! scope "Answer my scope" ^'Local'! ! !RVMLocalHeapStats methodsFor: 'testing' stamp: 'ssa 7/21/2008 10:11'! isLocal ^true! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCount "Answer the value of gcCount" gcCount isNil ifTrue:[self gcCount: nil]. ^gcCount! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCount: anObject "Set the value of gcCount" gcCount := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCycles "Answer the value of gcCycles" gcCycles isNil ifTrue:[self gcCycles: nil]. ^gcCycles! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCycles: anObject "Set the value of gcCycles" gcCycles := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcMilliseconds "Answer the value of gcMilliseconds" gcMilliseconds isNil ifTrue:[self gcMilliseconds: nil]. ^gcMilliseconds! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcMilliseconds: anObject "Set the value of gcMilliseconds" gcMilliseconds := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:52'! readMostlyHeapStats "Answer the value of readMostlyHeapStats" readMostlyHeapStats isNil ifTrue:[self readMostlyHeapStats: RVMHeapStats newReadMostly]. ^ readMostlyHeapStats! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readMostlyHeapStats: anObject "Set the value of readMostlyHeapStats" readMostlyHeapStats _ anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readWriteHeapStats "Answer the value of readWriteHeapStats" readWriteHeapStats isNil ifTrue:[self readWriteHeapStats: RVMHeapStats newReadWrite]. ^ readWriteHeapStats! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readWriteHeapStats: anObject "Set the value of readWriteHeapStats" readWriteHeapStats _ anObject! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:27'! closeRecordingFile "Close the recording file" self recordingFile flush;close. self recordingFile: nil! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:41'! isRecording ^self recordingMode ~= #off! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 15:32'! loadChunkedSamplesFromRecordingFile "Load the samples with the data on a file supplied by the user" | fs data chunk readChunkTime compileChunkTime | fs _ StandardFileMenu oldFileStreamWithPattern:'*.recording'. fs isNil ifTrue:[^self inform:'No file to load']. Cursor read showWhile:[ data _ OrderedCollection new. [fs atEnd] whileFalse:[Transcript cr;show:'reading data chunk #',(data size + 1) printString. readChunkTime _ Time millisecondsToRun:[chunk _ fs nextChunk]. Transcript cr;show:(readChunkTime //1000 )printString,' secs to read chunk'. compileChunkTime _ Time millisecondsToRun:[data add: (Compiler evaluate: chunk)]. Transcript cr;show: (compileChunkTime //1000) printString,' secs to compile chunk'. ]. fs close. self recordingMode = #file ifTrue:[self recordingMode: #loop]. self recordingMode = #loop ifTrue:[data _ data asCircularCollection]. self samples: data asCircularCollection]. self changed:#recordingMode ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 19:45'! loadSamplesFromRecordingFile "Load the samples with the data on a file supplied by the user" | fs data readChunkTime | fs _ StandardFileMenu oldFileStreamWithPattern:'*.recording'. fs isNil ifTrue:[^self inform:'No file to load']. Cursor read showWhile:[ data _ OrderedCollection new. [fs atEnd] whileFalse:[Transcript cr;show:'reading data chunk #',(data size + 1) printString. readChunkTime _ Time millisecondsToRun:[data add: (RVMSampleReader dearchiveRawDataFrom: fs)]. Transcript cr;show:(readChunkTime /1000.0)printString,' seconds to read'. ]. fs close. self recordingMode = #file ifTrue:[self recordingMode: #loop]. self recordingMode = #loop ifTrue:[data _ data asCircularCollection. self sampleLimit: data size]. self samples: data asCircularCollection]. self changed:#recordingMode ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:41'! openRecordingFile "Open the recording file" self recordingFile ensureOpen! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:37'! recordAllToFile: aCollection "Record each of these elements to the recording file in chunk format" aCollection do:[:each| self recordToFile: each]! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 15:33'! recordChunkToFile: anObject "Record the object on the recording file in chunk format" anObject printOn: self recordingFile. self recordingFile nextPut:$!!;cr;cr! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:45'! recordSample: someData "Record this sample data based on the recording mode" self recordingMode = #off ifTrue:[^self]. self recordingMode = #file ifTrue:[^self recordToFile: someData]. self samples add: someData! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 19:27'! recordToFile: anObject "Record the object on the recording file in archiver format" RVMSampleWriter archiveRawData: anObject on:self recordingFile ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:24'! recordingFile "Answer an appropriately named file for recording samples, open and ready." RecordingFile isNil ifTrue:[self recordingFile: self recordingFileFromUser]. ^RecordingFile! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:28'! recordingFile: aFile "Set an appropriately named file for recording samples, open and ready." RecordingFile isNil ifFalse:[RecordingFile close]. RecordingFile _ aFile! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:31'! recordingFileFromUser "Answer an appropriately named file for recording samples, open and ready." ^FileStream newFileNamed:'rvm-samples.recording'! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 23:19'! recordingMode "Recording modes are #off, #loop, #file, and #long" RecordingMode isNil ifTrue:[RecordingMode _ #loop]. ^RecordingMode! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:52'! recordingMode: nextMode "Recording modes are #off, #loop, #file, and #long" | lastMode | lastMode _ RecordingMode. lastMode = nextMode ifTrue:[^self]. self switchFrom: lastMode to: nextMode. RecordingMode _ nextMode. self changed:#recordingMode! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:21'! switchFrom: lastMode to: nextMode. "Switch recording modes. Recording modes are #off, #loop, #file, and #long" nextMode = #off ifTrue:[ lastMode = #loop ifTrue:["do nothing, leave collection in place"]. lastMode = #long ifTrue:["do nothing, leave collection in place"]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #loop ifTrue:[ lastMode = #off ifTrue:[self samples: (RVMCircularCollection new:self sampleLimit)]. lastMode = #long ifTrue:[self samples: (RVMCircularCollection withAll: self samples)]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #long ifTrue:[ lastMode = #off ifTrue:[self samples: OrderedCollection new]. lastMode = #loop ifTrue:[self samples: self samples asOrderedCollection]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #file ifTrue:[self openRecordingFile; recordAllToFile: self samples]. ! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 1/1/1970 00:18'! coreCount ^self lastSample groupStats groupSize! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 11/27/2008 14:45'! extent ^self lastSample extent! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 11/17/2008 13:22'! mainRank ^self lastSample groupStats mainRank ! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/17/2008 17:11'! coreIndexFromUser "RVMMonitor coreIndexFromUser" "Answer a valid coreINdex from the user for my current configuration" | maxIndex newIndex | maxIndex _ self coreCount. [newIndex _ FillInTheBlank request:'Enter a core index between 0 and ',(maxIndex - 1) printString,':' initialAnswer: '1'. (newIndex isEmpty or:[(newIndex asNumber between: 0 and: maxIndex - 1) not])] whileTrue. ^newIndex asNumber! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'dmu 9/17/2010 15:33'! dashboard "RVMMonitor dashboard " | topView samplingCheck turboCheck gcButton benchButton subViewCount sampleButton clearSamplesButton forgetButton shuffle56Button shuffle4Button multistripButton systemAspectsButton coreAspectsButton inspectSampleButton testAspectCheck spiderButton bytesUsedsSpiderButton delayTimingCheck recordingOptionsButton allToReadMostlyButton printAllHeapsButton printExecutionTraceButton printStackButton gridButton stripButton scanButton outlierButton locateClassesButton locatorButton locators4Button heartbeat spread56Button runningProcessesButton | topView := RVMStandardSystemView new . topView borderWidth:1. samplingCheck _ RVMCheckBoxView on: self label: 'Sampling' checkState: [self sampling] whenChecked: [self startSampling] whenUnchecked: [self stopSampling] monitor: true. turboCheck _ RVMCheckBoxView on: self label: 'Turbo' checkState: [self turboSampling] whenChecked: [self turboOn] whenUnchecked: [self turboOff] monitor: true. testAspectCheck _ RVMCheckBoxView on: self label: 'Test Aspects' checkState: [self showTestAspects] whenChecked: [self showTestAspects:true] whenUnchecked: [self showTestAspects:false] monitor: true. delayTimingCheck _ RVMCheckBoxView on: self label: 'Short Delay' checkState: [self delayTiming = #short] whenChecked: [self useShortDelay] whenUnchecked: [self useNormalDelay] monitor: true. heartbeat _ RVMCheckBoxView on: self label: 'Heartbeat' checkState: [self showHeartbeat] whenChecked: [self startHeartbeat] whenUnchecked: [self stopHeartbeat] monitor: true. sampleButton _ RVMButtonView label:'Take Sample' action:[RVMMonitor getSample; informListeners]. inspectSampleButton _ RVMButtonView label:'Inspect Sample' action:[RVMMonitor lastSample inspect]. clearSamplesButton _ RVMButtonView label:'Clear Samples' action:[RVMMonitor clearSamples]. recordingOptionsButton _ RVMButtonView label:'Recording Options' action:[RVMMonitor recordingControls]. forgetButton _ RVMButtonView label:'Forget Listeners' action:[RVMMonitor forgetListeners]. gcButton _ RVMButtonView label:'GC' action:[Transcript cr show:'GC: ',Smalltalk garbageCollect printString]. spread56Button _ RVMButtonView label:'Spread 56' action:[RVMTester spreadFrom: 0 to: 55 moveRWtoRM: true moveRMtoRW: false]. shuffle56Button _ RVMButtonView label:'Shuffle:56' action:[RVMTester shuffle:56]. shuffle4Button _ RVMButtonView label:'Shuffle:4' action:[RVMTester shuffle:4]. allToReadMostlyButton _ RVMButtonView label:'All->readMostly' action:[RVMTester moveAllToReadMostlyHeaps]. printAllHeapsButton _ RVMButtonView label:'Print BytesUsed' action:[RVMTester printAllHeapsBytesUsed]. printExecutionTraceButton _ RVMButtonView label:'Print Trace' action:[RVMTester printExecutionTrace]. printStackButton _ RVMButtonView label:'Print Stack' action:[RVMTester printStack]. gridButton _ self relAbsButtonLabeled:'Tile Grid...' relAction:[RVMTileGridView example] absAction:[RVMTileGridScalerView example]. stripButton _ self relAbsButtonLabeled:'Tile Strip...' relAction:[RVMTileStripChartView example] absAction:[RVMTileStripChartScalerView example]. scanButton _ self relAbsButtonLabeled:'Tile Scan...' relAction:[RVMScanningStripChartView example] absAction:[RVMAbsScanningStripChartView example]. multistripButton _ RVMButtonView label:'Multi Strip' action:[RVMCoreAspectTrace exampleView1]. systemAspectsButton _ RVMButtonView label:'System Aspects' action:[RVMAspectTrace monitorAllSystemAspects]. coreAspectsButton _ RVMButtonView label:'Core Aspects' action:[RVMCoreAspectTrace monitorAllCoreAspectsForCoreFromUser]. runningProcessesButton _ RVMButtonView label:'Running Processes' action:[RVMAspectTrace exampleView8]. spiderButton _ RVMButtonView label:'Kiviat' action:[RVMMultiKiviatView exampleBytecodesAndProcessesRunning]. bytesUsedsSpiderButton _ RVMButtonView label:'heap size Kiviat' action:[RVMMultiKiviatView exampleBytesUsedTrioCommonPinned]. outlierButton _ RVMButtonView label:'Outlier...' action:[RVMMonitor outlierFromUser]. locateClassesButton _ RVMButtonView label:'Class Locator' action:[RVMGroupLocatorView openOn: Smalltalk objectsSource:#allClasses labeled:'All Classes']. locatorButton _ RVMButtonView label:'Group Locator' action:[RVMGroupLocatorView openWithSourceEditorOn: nil objectsSource:[Array allInstances]]. locators4Button _ RVMButtonView label:'4 Group Locator' action:[RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Collection withAllSubclasses]. [Object withAllSubclasses]. [View allSubInstances]} colors: nil]. benchButton _ RVMButtonView label:'testCompiler' action:[Cursor wait showWhile:[RVMExperiment testCompiler]]. topView addSubView: samplingCheck. topView addSubView: turboCheck below: samplingCheck. topView addSubView: testAspectCheck below: turboCheck. topView addSubView: delayTimingCheck below: testAspectCheck. topView addSubView: heartbeat below: delayTimingCheck. topView addSubView: sampleButton below: heartbeat. topView addSubView: inspectSampleButton below: sampleButton. topView addSubView: clearSamplesButton below: inspectSampleButton. topView addSubView: recordingOptionsButton below: clearSamplesButton. topView addSubView: forgetButton below: recordingOptionsButton. topView addSubView: gcButton below: forgetButton. topView addSubView: spread56Button below: gcButton. topView addSubView: shuffle56Button below: spread56Button. topView addSubView: shuffle4Button below: shuffle56Button. topView addSubView: allToReadMostlyButton below: shuffle4Button. topView addSubView: printAllHeapsButton below: allToReadMostlyButton. topView addSubView: printExecutionTraceButton below: printAllHeapsButton. topView addSubView: printStackButton below: printExecutionTraceButton. topView addSubView: gridButton below: printStackButton. topView addSubView: stripButton below: gridButton. topView addSubView: scanButton below: stripButton. topView addSubView: multistripButton below: scanButton. topView addSubView: systemAspectsButton below: multistripButton. topView addSubView: coreAspectsButton below: systemAspectsButton. topView addSubView: runningProcessesButton below: coreAspectsButton. topView addSubView: spiderButton below: runningProcessesButton. topView addSubView: bytesUsedsSpiderButton below: spiderButton. topView addSubView: outlierButton below: bytesUsedsSpiderButton. topView addSubView: locateClassesButton below: outlierButton. topView addSubView: locatorButton below: locateClassesButton. topView addSubView: locators4Button below: locatorButton. topView addSubView: benchButton below: locators4Button. topView label: 'RVM'. RVMMonitor forgetAll: topView allSubViews. RVMMonitor forget: topView. subViewCount _ topView subViews size. topView minimumSize: 120@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/13/2008 02:10'! outlierFromUser | menu result selectors labels aspects sel cores | selectors _ #(coreAspectSubset coreAspectSubsetAllocationCompaction coreAspectSubsetBytecodes coreAspectSubsetBytes coreAspectSubsetRunWait coreAspectSubsetYields allCoreAspects). labels _ #('selected aspects' 'allocation/compaction' 'bytecodes' 'bytes' 'run/wait' 'yields' 'all for a single core'). menu _ PopUpMenu labelArray: labels. result _ menu startUpWithCaption:'Which set of aspects for the Outlier?'. result = 0 ifTrue: [^self]. aspects _ RVMMultiAspectKiviatView perform: (sel _ selectors at: result). cores _ sel = #allCoreAspects ifTrue:[Array with: self coreIndexFromUser]ifFalse:[(1 to: RVMMonitor coreCount) asOrderedCollection]. RVMMultiAspectKiviatView openOnAspects: aspects forCores: cores titled:'Outliers: ',(labels at: result)! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 5/12/2010 10:16'! recordingControls "RVMMonitor recordingControls " | topView offRadio loopRadio subViewCount longRadio fileRadio loadButton radios | topView := RVMStandardSystemView new . radios _ RVMView new. topView borderWidth:1. RVMRadioButtonView testState:#(true false false false false). offRadio _ RVMRadioButtonView on: self label: 'stop recording' checkState: [RVMMonitor recordingMode = #off] whenChecked: [RVMMonitor recordingMode: #off] whenUnchecked: [] monitor: true. loopRadio _ RVMRadioButtonView on: self label: 'record last ',RVMMonitor sampleLimit printString,' samples' checkState: [RVMMonitor recordingMode = #loop] whenChecked: [RVMMonitor recordingMode: #loop] whenUnchecked: [] monitor: true. longRadio _ RVMRadioButtonView on: self label: 'record all samples' checkState: [RVMMonitor recordingMode = #long] whenChecked: [RVMMonitor recordingMode: #long] whenUnchecked: [] monitor: true. fileRadio _ RVMRadioButtonView on: self label: 'record all samples to a file' checkState: [RVMMonitor recordingMode = #file] whenChecked: [RVMMonitor recordingMode: #file] whenUnchecked: [] monitor: true. loadButton _ RVMButtonView label:'Load samples from file' action:[RVMMonitor loadSamplesFromRecordingFile]. radios addSubView: offRadio. radios addSubView: loopRadio below: offRadio. radios addSubView: longRadio below: loopRadio. radios addSubView: fileRadio below: longRadio. topView addSubView: radios. topView addSubView: loadButton below: radios. RVMMonitor forgetAll: topView allSubViews. RVMMonitor forget: topView. topView label: 'Recording Options'. subViewCount _ radios subViews size + topView subViews size - 1. topView minimumSize: 200@(subViewCount*28). topView maximumSize: 200@topView minimumSize y. topView controller open! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/15/2008 23:30'! relAbsButtonLabeled: aTitle relAction: relAction absAction: absAction | menu result | ^RVMButtonView label: aTitle action: [menu _ PopUpMenu labelArray:#('Relative Scaling' 'Absolute Scaling'). result _ menu startUpWithCaption:'Which color scaling to use?'. result = 1 ifTrue: [relAction copy value]. result = 2 ifTrue: [absAction copy value]] copy! ! !RVMMonitor class methodsFor: 'test aspects' stamp: 'ssa 10/3/2008 15:06'! showTestAspects ShowTestAspects isNil ifTrue:[ShowTestAspects _ false]. ^ShowTestAspects! ! !RVMMonitor class methodsFor: 'test aspects' stamp: 'ssa 10/3/2008 15:06'! showTestAspects: aBoolean ShowTestAspects _ aBoolean! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:12'! clearSamples "Clear my collection of samples" Samples := nil. LastSample := nil.! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:19'! delaySamplingDuring: aBlock self sampling ifTrue:[self stopSampling. aBlock value. self startSampling] ifFalse:[aBlock value]! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:25'! delayTiming DelayTiming isNil ifTrue:[DelayTiming _ #normal]. ^DelayTiming! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:25'! delayTiming: aSymbol "#normal or #short" DelayTiming _ aSymbol! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'dmu 4/10/2009 22:48'! getSample "Get the next sample" LastSample := self turboSampling ifTrue:[RVMMulticoreSample captureFastest]ifFalse:[RVMMulticoreSample next]. RVMTester isRVM & self isRecording ifTrue:[ self recordSample: LastSample rawData]. ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 11/15/2008 23:42'! lastSample "Answer the last recorded sample" LastSample isNil ifTrue:[self getSample]. ^LastSample ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:23'! normalDelayTiming ^self delayTiming = #normal! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/21/2008 11:56'! sampleLimit SampleLimit isNil ifTrue:[SampleLimit := 2]. ^SampleLimit! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 8/22/2008 09:42'! sampleLimit: anInteger SampleLimit := anInteger. self clearSamples! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/18/2008 22:14'! samples "Answer my collection of samples" Samples isNil ifTrue:[self samples:(RVMCircularCollection new:self sampleLimit)]. ^Samples! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/18/2008 22:14'! samples: aCollection "Set my collection of samples" Samples _ aCollection! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:19'! sampling "Am I current sampling?" ^SamplingProcess notNil! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 7/16/2010 16:54'! startSampling "RVMMonitor startSampling" "Start the sampling process" | delay timeToRun delayTime lastTime| lastTime _ Time now asSeconds. SamplingProcess notNil ifTrue:[self stopSampling]. SamplingProcess := [[ Sensor leftShiftDown & Sensor controlKeyPressed] whileFalse: [ "RVMTester print: (Time now asSeconds - lastTime) printString,' seconds since last sample'." timeToRun _ Time millisecondsToRun: [self getSample]. lastTime _ Time now asSeconds. "RVMTester print:'sampling took ',(timeToRun/1000.0) printString,' seconds'." delayTime _ self normalDelayTiming ifTrue:[10*timeToRun]ifFalse:[100 min: 10*timeToRun]. delay := Delay forMilliseconds: delayTime. self informListeners. RVMMulticoreSample flush. "clear sample buffers from monitor activity" delay wait]] newProcess. SamplingProcess name: 'RVMMonitor sampling process'. SamplingProcess resume ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 9/4/2008 15:00'! stopSampling "RVMMonitor stopSampling" "Stop the sampling process" SamplingProcess isNil ifFalse:[SamplingProcess terminate]. SamplingProcess := nil! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboOff "Turn off turboSampling" TurboSampling := false! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboOn "Turn on turboSampling" TurboSampling := true! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboSampling "Answer my turboSampling flag" TurboSampling isNil ifTrue:[TurboSampling := true]. ^TurboSampling! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:22'! useNormalDelay self delaySamplingDuring:[self delayTiming: #normal]. ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:22'! useShortDelay self delaySamplingDuring:[self delayTiming: #short].! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 1/1/1970 00:07'! forget: someone self listeners remove: someone ifAbsent:[]! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 10/28/2008 19:54'! forgetAll: someListeners someListeners do:[:each| self forget: each]! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 1/1/1970 00:07'! forgetListeners Listeners := nil! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 8/25/2008 05:02'! inform: someone self listeners add: someone! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 2/18/2009 17:42'! informListeners self listeners do:[:each| each hear: self] " | sema | sema _ Semaphore new. self listeners do:[:each| [each hear: self. sema signal] copy fixTemps fork]. self listeners do: [:each| sema wait]" ! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 8/25/2008 04:59'! listeners "Answer the list of listeners to me" Listeners isNil ifTrue:[Listeners := OrderedCollection new]. ^Listeners! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:03'! autocodeScalerMethodFor: aSelector "Autocode and install a default scaler method for the aspect found in this selector." "Note this also adds a class variable of the form SCALERaspect" | aspect code var | aspect _ aSelector allButLast:'Scaler' size. var _ 'SCALER',aspect. self addClassVarName: var. code _ aSelector,' "Answer the default scaler for ',aspect,'." ',var,' isNil ifTrue:[',var,' _ RVMDataScaler aspect: #',aspect,' min: 0 max: 100]. ^',var. self class compile: code classified:'scalers' notifying:nil! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:03'! autocodeScalerMethodForScaler: aDataScaler "Autocode and install a default scaler method for the aspect found in this selector." "Note this also adds a class variable of the form SCALERaspect" | aspect code var | aspect _ aDataScaler aspect. var _ 'SCALER',aspect. (self classVarNames includes: var) ifFalse:[self addClassVarName: var]. code _ aspect,'Scaler "Answer the default scaler for ',aspect,'." ',var,' isNil ifTrue:[',var,' _ RVMDataScaler aspect:#',aspect,' min: ',aDataScaler min printString,' max: ',aDataScaler max printString,']. ^',var. self class compile: code classified:'scalers' notifying:nil! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:49'! doesNotUnderstand: aMessage "autocode a method for aMessage if its one I recognize." (aMessage selector isUnary & (aMessage selector endsWith: 'Scaler')) ifTrue:[self halt:'this should not be used anymore'. self autocodeScalerMethodFor: aMessage selector. ^self perform: aMessage selector]. ^super doesNotUnderstand: aMessage! ! !RVMMonitor class methodsFor: 'data generation' stamp: 'ssa 9/13/2008 19:40'! dataFor: anAspect "Answer a generated data value for this aspect, based on the range of its scaler" ^(self scalerFor:anAspect) atRandom! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:44'! coloredScalerFor: aspect "Answer an appropriate colored scaler for this aspect." ^RVMColoredDataScaler aspect: aspect! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:44'! coloredScalersFor: aspects "Answer an appropriate colored scalers for this aspect." ^aspects collect:[:each| self coloredScalerFor: each]! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:02'! scalerFor: aspect "Answer an appropriate scalers for this aspect." [^RVMDataScaler new automatic]value. ^self perform: (aspect,'Scaler') asSymbol! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 9/13/2008 19:39'! scalersFor: aspects "Answer a collection of appropriate scalers for these aspects." ^aspects collect:[:aspect| self scalerFor: aspect]! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:02'! showHeartbeat ShowHeartbeat isNil ifTrue:[ShowHeartbeat _ false]. ^ShowHeartbeat! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:03'! showHeartbeat: aBoolean ShowHeartbeat _ aBoolean! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/3/2009 12:18'! startHeartbeat "RVMMonitor startHeartbeat" "RVMMonitor stopHeartbeat" | rect delay | self showHeartbeat: true. rect _ 0@0 extent: 4@4. delay _ Delay forSeconds: 1. [[self showHeartbeat] whileTrue:[Display reverse: rect. delay wait]] forkAt: Processor highestPriority. Processor yield ! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:09'! stopHeartbeat "RVMMonitor startHeartbeat" "RVMMonitor stopHeartbeat" self showHeartbeat: false.! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 9/14/2008 20:50'! aspects "Answer a list of message selectors that will return arrays of numbers for my monitor" ^self class aspects! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:06'! coreIndices ^self groupStats coreIndices! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:33'! cpuCoreStats "Answer the value of cpuCoreStats" ^cpuCoreStats! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! cpuCoreStats: anObject "Set the value of cpuCoreStats" cpuCoreStats := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/13/2008 09:42'! extent "Answer the dimensions of my tile grid" ^self groupStats extent! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:03'! fence "Answer the value of fence" fence isNil ifTrue:[self fence: nil]. ^ fence! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:03'! fence: anObject "Set the value of fence" fence _ anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 8/15/2008 22:13'! groupStats ^ groupStats! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 8/15/2008 22:14'! groupStats: x groupStats _ x! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:33'! messageNames "Answer the value of messageNames" ^messageNames! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! messageNames: anObject "Set the value of messageNames" messageNames := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! numberOfCores ^self groupStats isNil ifTrue:[56]ifFalse:[self groupStats groupSize]! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 10/18/2008 18:03'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:04'! runMask ^ runMask! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:05'! runMask: x runMask := x! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:20'! totalYields ^ self cpuCoreStats yieldCounts sum! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/13/2008 17:32'! initializeAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/19/2008 10:50'! initializeFastAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFastFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 7/16/2010 16:45'! initializeFastFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." self rawData: data. self runMask: (data at: 2). self messageNames: (data at: 4). self initializeFastGroupStatsFrom: (data at: 6). self initializeFastAllCPUCoreStatsFrom: (data at: 8). self fence: (data at: 10). self processInstanceCount: Process instanceCount ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 3/25/2009 14:11'! initializeFastGroupStatsFrom: data self groupStats: (RVMGroupStats new initializeFastFrom: data last)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:04'! initializeFastestAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFastestFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'dmu 5/21/2010 23:05'! initializeFastestFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." self rawData: data. self runMask: (data at: 2). self messageNames: (data at: 4). self initializeFastestGroupStatsFrom: ((data at: 6 ) at: 2). self initializeFastestAllCPUCoreStatsFrom: (data at: 8). self fence: (data at: 10). ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 3/25/2009 19:17'! initializeFastestGroupStatsFrom: data self groupStats: (RVMGroupStats new initializeFastFrom: data )! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 7/16/2010 16:46'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap | self rawData: data. valueMap := { }. objectMap := { 'runMask' -> #runMask:. 'messageNames' -> #messageNames:. 'allCPUCoreStats' -> #initializeAllCPUCoreStatsFrom:. 'groupStats' -> #initializeGroupStatsFrom:. 'fence' -> #fence:. }. self processMap: valueMap into: self forData: data. self processMap: objectMap into: self forData: data. self processInstanceCount: Process instanceCount ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'dmu 8/15/2008 22:11'! initializeGroupStatsFrom: data groupStats _ RVMGroupStats new initializeFrom: data! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/13/2008 15:47'! processMap: map into: targetObject forData: data | index datum | map do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. targetObject perform: assoc value with: datum]. ! ! !RVMMulticoreSample methodsFor: 'printing' stamp: 'ssa 8/15/2008 16:28'! printOn: aStream aStream nextPutAll: 'anRVMMulticoreStats('; cr;tab;nextPutAll: ' bytecodesPerCycle=';nextPutAll: self bytecodesPerCycle printString; cr;tab;nextPutAll: ' bytecodesPerCyclesAverage=';nextPutAll: self bytecodesPerCyclesAverage printString; cr;tab;nextPutAll: ' bytecodesPerMillisecond=';nextPutAll: self bytecodesPerMillisecond printString; cr;tab;nextPutAll: ' bytecodesPerMillisecondsAverage=';nextPutAll: self bytecodesPerMillisecondsAverage printString; cr;tab;nextPutAll: ' bytecodeCountsAvg=';nextPutAll: self bytecodeCountsAverage printString; cr;tab;nextPutAll: ' bytecodePerSecondAvg=';nextPutAll: self bytecodesPerSecondAverage printString; cr;tab;nextPutAll: ' cyclesRunningsAvg=';nextPutAll: self cyclesRunningsAverage printString; cr;tab;nextPutAll: ' cyclesWaitingsAvg=';nextPutAll: self cyclesWaitingsAverage printString; cr;tab;nextPutAll: ' cyclesRunWaitRatiosAvg=';nextPutAll: self cyclesRunWaitRatiosAverage printString; cr;tab;nextPutAll: ' msRunningsAvg=';nextPutAll: self msRunningsAverage printString; cr;tab;nextPutAll: ' msWaitingsAvg=';nextPutAll: self msWaitingsAverage printString; cr;tab;nextPutAll: ' msRunWaitRatiosAvg=';nextPutAll: self msRunWaitRatiosAverage printString; cr;tab;nextPutAll: ' yieldCountsAvg=';nextPutAll: self yieldCountsAverage printString; cr;tab;nextPutAll: ' yieldsPerSecondAvg=';nextPutAll: self yieldsPerSecondAverage printString; cr;tab;nextPutAll: ')';cr ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:58'! allocationsReadMostlys "RVMMulticoreSample capture allocationsReadMostlys" "Answer the collection of allocationsSinceLastReadMostlys" ^self cpuCoreStats allocationsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:58'! allocationsReadWrites "RVMMulticoreSample capture allocationsReadWrites" "Answer the collection of allocationsSinceLastReadWrites" ^self cpuCoreStats allocationsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadMostlys "RVMMulticoreSample capture allocationsSinceLastReadMostlys" "Answer the collection of allocationsSinceLastReadMostlys" ^self cpuCoreStats allocationsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadWrites "RVMMulticoreSample capture allocationsSinceLastReadWrites" "Answer the collection of allocationsSinceLastReadWrites" ^self cpuCoreStats allocationsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:00'! allocationsTotal "RVMMulticoreSample capture allocationsTotal" "Answer the collection of allocationsSinceLast" ^self cpuCoreStats allocationsSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:40'! bytecodeCounts "RVMMulticoreSample capture bytecodeCounts" "Answer the collection of bytecode counts during this sample" ^self cpuCoreStats bytecodeCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! bytecodeCountsAverage "RVMMulticoreSample capture bytecodeCountsAverage" "Answer the average of bytecode counts during this sample" ^self cpuCoreStats bytecodeCounts average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:19'! bytecodesPerCycle "RVMMulticoreSample capture bytecodesPerCycle" | avg | avg := self cyclesSinceLastsAverage. ^avg = 0 ifTrue:[0] ifFalse:[self bytecodeCounts sum / (1 max: self cyclesSinceLastsAverage) asFloat]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:05'! bytecodesPerCycles "RVMMulticoreSample capture bytecodesPerCycles" ^self bytecodeCounts with: self cyclesRunnings collect:[:bc :ms| ms = 0 ifTrue:[0] ifFalse:[bc/ms asFloat]]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:06'! bytecodesPerCyclesAverage "RVMMulticoreSample capture bytecodesPerCyclesAverage" ^self bytecodesPerCycles average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! bytecodesPerKCs ^ self bytecodesPerCycles collect: [:x| x * 1000]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:09'! bytecodesPerMCs ^ self bytecodesPerCycles collect: [:x| x * 1000000]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:20'! bytecodesPerMillisecond "RVMMulticoreSample capture bytecodesPerMillisecond" ^self bytecodeCounts sum / (1 max: self msSinceLastsAverage) asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:20'! bytecodesPerMilliseconds "RVMMulticoreSample capture bytecodesPerMilliseconds" ^self bytecodeCounts with: self msSinceLasts collect:[:bc :ms| bc/(1 max: ms) asFloat]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:35'! bytecodesPerMillisecondsAverage "RVMMulticoreSample capture bytecodesPerMillisecondsAverage" ^self bytecodesPerMilliseconds average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:25'! bytecodesPerSecond "RVMMulticoreSample capture bytecodesPerSecond" "Answer the collection of ratios of bytecodes executed per second during this sample" ^self cpuCoreStats bytecodesPerSecond! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! bytecodesPerSecondAverage "RVMMulticoreSample capture bytecodesPerSecondAverage" "Answer the average of ratios of bytecodes executed per second during this sample" ^self cpuCoreStats bytecodesPerSecond average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadMostlys "RVMMulticoreSample capture bytesLeftReadMostlys" "Answer the collection of bytesLeftReadMostlys" ^self cpuCoreStats bytesLeftReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadWrites "RVMMulticoreSample capture bytesLeftReadWrites" "Answer the collection of bytesLeftReadWrites" ^self cpuCoreStats bytesLeftReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLefts "RVMMulticoreSample capture bytesLefts" "Answer the collection of bytesLeft" ^self cpuCoreStats bytesLefts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:48'! bytesUsedReadMostlys "RVMMulticoreSample capture bytesUsedReadMostlys" "Answer the collection of bytesUsedReadMostlys" ^self cpuCoreStats bytesUsedReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:47'! bytesUsedReadWrites "RVMMulticoreSample capture bytesUsedReadWrites" "Answer the collection of bytesUsedReadWrites" ^self cpuCoreStats bytesUsedReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:24'! bytesUseds "RVMMulticoreSample capture bytesUseds" "Answer the collection of bytesUsed" ^self cpuCoreStats bytesUseds! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:59'! compactionsReadMostlys "RVMMulticoreSample capture compactionsSinceLastReadMostlys" "Answer the collection of compactionsSinceLastReadMostlys" ^self cpuCoreStats compactionsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:59'! compactionsReadWrites "RVMMulticoreSample capture compactionsReadWrites" "Answer the collection of compactionsSinceLastReadWrites" ^self cpuCoreStats compactionsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:00'! compactionsTotal "RVMMulticoreSample capture compactionsTotal" "Answer the collection of compactionsSinceLast" ^self cpuCoreStats compactionsSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! contextChangeCounts "RVMMulticoreSample capture contextChangeCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats contextChangeCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 4/1/2009 22:32'! coreProcessUtilization ^RVMTester coreProcessUtilization asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:52'! cyclesRunWaitRatios "RVMMulticoreSample capture cyclesRunWaitRatios" "Answer the collection of ratios during this sample" ^self cpuCoreStats cyclesRunWaitRatios! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesRunWaitRatiosAverage "RVMMulticoreSample capture cyclesRunWaitRatiosAverage" "Answer the average of ratios during this sample" ^self cpuCoreStats cyclesRunWaitRatios average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:49'! cyclesRunnings "RVMMulticoreSample capture cyclesRunnings" "Answer the collection of cyclesRunning counts during this sample" ^self cpuCoreStats cyclesRunnings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesRunningsAverage "RVMMulticoreSample capture cyclesRunningsAverage" "Answer the average of cyclesRunning counts during this sample" ^self cpuCoreStats cyclesRunnings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:30'! cyclesSinceLasts "RVMMulticoreSample capture cyclesSinceLasts" "Answer the cyclesSinceLasts during this sample" ^self cpuCoreStats cyclesSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:08'! cyclesSinceLastsAverage "RVMMulticoreSample capture cyclesSinceLastsAverage" "Answer the average cyclesSinceLasts during this sample" ^self cpuCoreStats cyclesSinceLasts average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:49'! cyclesWaitings "RVMMulticoreSample capture cyclesWaitings" "Answer the collection of cyclesWaiting counts during this sample" ^self cpuCoreStats cyclesWaitings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesWaitingsAverage "RVMMulticoreSample capture cyclesWaitingsAverage" "Answer the average of cyclesWaiting counts during this sample" ^self cpuCoreStats cyclesWaitings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! interruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats interruptCheckCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 8/17/2008 11:01'! millisecondsRunnings "RVMMulticoreSample capture millisecondsRunnings" "Answer the collection of msRunning counts during this sample" ^self cpuCoreStats millisecondsRunnings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:41'! millisecondsWaitings "RVMMulticoreSample capture millisecondsWaitings" "Answer the collection of millisecondsWaitings counts during this sample" ^self cpuCoreStats millisecondsWaitings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:44'! msRunWaitRatios "RVMMulticoreSample capture msRunWaitRatios" "Answer the collection of ratios during this sample" ^self cpuCoreStats msRunWaitRatios! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:15'! msRunWaitRatiosAverage "RVMMulticoreSample capture msRunWaitRatiosAverage" "Answer the average of ratios during this sample" ^self cpuCoreStats msRunWaitRatios average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:29'! msRunningsAverage "RVMMulticoreSample capture msRunningsAverage" "Answer the average of millisecondsRunning counts during this sample" ^self cpuCoreStats millisecondsRunnings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:30'! msSinceLasts "RVMMulticoreSample capture msSinceLasts" "Answer the collection of msSinceLasts during this sample" ^self cpuCoreStats msSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:30'! msSinceLastsAverage "RVMMulticoreSample capture msSinceLastsAverage" "Answer the average msSinceLasts during this sample" ^self cpuCoreStats msSinceLasts average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:43'! msWaitingsAverage "RVMMulticoreSample capture msWaitingsAverage" "Answer the average of msWaiting counts during this sample" ^self cpuCoreStats millisecondsWaitings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 4/1/2009 22:36'! numberOfRunningProcesses ^RVMTester numberOfRunningProcesses ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 4/10/2009 22:48'! processCountsPerCore | bag counts | bag _ (Process allInstances asOrderedCollection collect:[:obj| RVMTester isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMTester getCoreHolding:obj]]) asBag. counts _ Array new: RVMMonitor coreCount. 1 to: RVMMonitor coreCount do:[:coreIndex| counts at: coreIndex put: (bag occurrencesOf: coreIndex)]. ^counts ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:20'! receiveTallySum ^ self cpuCoreStats receiveTallySum! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 4/2/2009 02:12'! runningProcessCountsPerCore ^RVMTester runningProcessByCore collect:[:obj| obj isNil ifTrue:[0] ifFalse:[1]]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 3/27/2009 17:04'! sendTallySumsSortedReport "Answer a string report of the sorted send tallies across all cores" ^self cpuCoreStats sendTallySumsSortedReport! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! unforcedInterruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats unforcedInterruptCheckCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:17'! yieldCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats yieldCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:18'! yieldCountsAverage "RVMMulticoreSample capture yieldCountsAverage" "Answer the average of yields during this sample" ^self cpuCoreStats yieldCounts average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:16'! yieldFrequencies "RVMMulticoreSample capture yieldFrequencies" ^self cpuCoreStats yieldFrequencies! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:36'! yieldsPerSecond "RVMMulticoreSample capture yieldsPerSecond" "Answer the collection of ratios of yields per second during this sample" ^self cpuCoreStats yieldsPerSecond! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:15'! yieldsPerSecondAverage "RVMMulticoreSample capture yieldsPerSecondAverage" "Answer the average of ratios of yields per second during this sample" ^self cpuCoreStats yieldsPerSecond average asFloat! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random1 "RVMMulticoreSample new random1" "generated data for testing visualization" ^1 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random10 "RVMMulticoreSample new random10" "generated data for testing visualization" ^10 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random100 "RVMMulticoreSample new random100" "generated data for testing visualization" ^100 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:00'! random1000 "RVMMulticoreSample new random1000" "generated data for testing visualization" ^1000 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0001To1 "RVMMulticoreSample new test0001To1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0001. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1 "RVMMulticoreSample new test0to1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to10 "RVMMulticoreSample new test0to10" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 10.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:32'! test0to100 "RVMMulticoreSample new test0to100" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 100.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^(testData copyFrom: 1 to: self numberOfCores) ! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:27'! test0to1B "RVMMulticoreSample new test0to1B" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000000000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1K "RVMMulticoreSample new test0to1K" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1M "RVMMulticoreSample new test0to1M" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! testNeg1To1 "RVMMulticoreSample new testNeg1To1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ -1.0. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:07'! testRandom1 "RVMMulticoreSample new testRandom1" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 1 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom10 "RVMMulticoreSample new testRandom10" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 10 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom100 "RVMMulticoreSample new testRandom100" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 100 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom1000 "RVMMulticoreSample new testRandom1000" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 1000 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandom100s "RVMMulticoreSample new testRandom100s" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 100. max _ 999. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandom1Ks "RVMMulticoreSample new testRandom1Ks" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000. max _ 1999. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:04'! testRandomBs "RVMMulticoreSample new testRandomBs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000000000. max _ 999000000000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandomKs "RVMMulticoreSample new testRandomKs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000. max _ 999000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:04'! testRandomMs "RVMMulticoreSample new testRandomMs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000000. max _ 999000000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'co vs inco' stamp: 'dmu 10/5/2008 02:14'! coinBytes " RVMTester moveAllToReadMostlyHeaps. RVMTester printCoInBytesUsed. Smalltalk garbageCollect. RVMTester printCoInBytesUsed. RVMMulticoreSample capture coinBytes" ^self cpuCoreStats coreStats collect: [:stat | (stat memorySystemStats readWriteHeapStats bytesUsed @ stat memorySystemStats readMostlyHeapStats bytesUsed)]! ! !RVMMulticoreSample methodsFor: 'co vs inco' stamp: 'dmu 10/5/2008 00:26'! coinBytesTotal "Smalltalk garbageCollect. RVMMulticoreSample capture coinBytes" | s | s := 0 @ 0. self cpuCoreStats coreStats do: [:stat | s := s + (stat memorySystemStats readWriteHeapStats bytesUsed @ stat memorySystemStats readMostlyHeapStats bytesUsed)]. ^ s! ! !RVMMulticoreSample methodsFor: 'archiving' stamp: 'ssa 10/26/2008 21:12'! archiveOn: aStream | rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: RVMMonitor lastSample on: rw. aStream storeObject: self; storeClass: self class; store: rw reset. ! ! !RVMMulticoreSample methodsFor: 'copying' stamp: 'ssa 10/26/2008 21:08'! deepCopy "Use the RVMSampleWriter/Reader" | rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: self on: rw. RVMSampleReader dearchiveSampleFrom: rw reset ! ! !RVMMulticoreSample class methodsFor: 'examples' stamp: 'ssa 8/13/2008 15:13'! example "RVMMulticoreSample example" self capture explore! ! !RVMMulticoreSample class methodsFor: 'examples' stamp: 'ssa 9/9/2008 19:50'! examplePrimitive "RVMMulticoreSample examplePrimitive" self primitiveCapture inspect! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:07'! archiveVersion ^2! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:10'! dearchive: versionNumber from: aStream versionNumber = self archiveVersion ifTrue:[^self dearchiveFrom: aStream]. self error:'Can''t handle this archive version'! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 10/26/2008 22:07'! dearchiveFrom: aStream | rwStream sample | rwStream _ aStream next. sample _ RVMSampleReader dearchiveSampleFrom: rwStream reset. aStream storeObject: sample. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:48'! capture "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample capture" ^self captureFast! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:34'! captureFast "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureFast" | data sample | data := self primitiveCapture. sample := self new. sample initializeFastFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:03'! captureFastest "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureFastest" | data sample | data := self primitiveCapture. sample := self new. sample initializeFastestFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:48'! captureSlow "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureSlow" | data sample | data := self primitiveCapture. sample := self new. sample initializeFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:26'! newFrom: rawData "Answer a new instance of me holding these values" "RVMMulticoreSample newFrom: self primitiveCapture" | sample | sample := self new. sample initializeFastFrom: rawData. ^sample! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'ssa 10/18/2008 21:42'! primitiveCapture "Grab some data from the VM and return it" [^RVMMonitor samples next]value. self primitiveFailed! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'dmu 4/10/2009 17:39'! primitiveCapture: flags "Grab some data from the VM and return it" self primitiveFailed! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'dmu 4/10/2009 17:39'! primitiveCaptureOneCore "self primitiveCaptureOneCore" ^ self primitiveCapture: RVMSampleFlags everything - RVMSampleFlags allCores! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'ssa 11/12/2008 12:23'! primitiveFlush "Clear out the sample buffer in the vm by grabbing a sample" ! ! !RVMMulticoreSample class methodsFor: 'sample access' stamp: 'ssa 11/12/2008 12:23'! flush self primitiveFlush! ! !RVMMulticoreSample class methodsFor: 'sample access' stamp: 'ssa 1/1/1970 00:32'! next ^self capture! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 22:54'! aspectFromUserUnder: aSymbol "Answer a selected aspect categorized under #system, #core, #testSystem, #testCore." | menu | menu := CustomMenu new. (self aspectsUnder: aSymbol) do: [:aspect | menu add: aspect action: aspect]. ^menu startUp:nil withCaption: 'Select the aspect to monitor'. ! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:10'! aspects "Answer a list of message selectors that will return arrays of numbers for my monitor" ^(RVMMulticoreSample allMethodsInCategory: #measuring), (RVMMonitor showTestAspects ifTrue:[self testAspects]ifFalse:[#()])! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 22:51'! aspectsUnder: aSymbol "Answer the aspects categorized under #system, #core, #testSystem, #testCore." aSymbol == #system ifTrue:[^self systemAspects]. aSymbol == #core ifTrue:[^self coreAspects]. aSymbol == #testSystem ifTrue:[^self testSystemAspects]. aSymbol == #testCore ifTrue:[^self testCoreAspects]. ^self aspects! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'dmu 4/2/2009 02:09'! coreAspects "Answer a list of message selectors that will return collections of core numbers for my monitor" ^#(#allocationsReadWrites #allocationsReadMostlys #allocationsTotal #bytecodeCounts #bytecodesPerCycles #bytecodesPerKCs #bytecodesPerMCs #bytecodesPerMilliseconds #bytecodesPerSecond #bytesLeftReadWrites #bytesLeftReadMostlys #bytesLefts #bytesUsedReadWrites #bytesUsedReadMostlys #bytesUseds #compactionsReadWrites #compactionsReadMostlys #compactionsTotal #contextChangeCounts #cyclesRunWaitRatios #cyclesRunnings #cyclesSinceLasts #cyclesWaitings #interruptCheckCounts #millisecondsRunnings #millisecondsWaitings #msRunWaitRatios #msSinceLasts #unforcedInterruptCheckCounts #yieldCounts #yieldFrequencies #yieldsPerSecond #processCountsPerCore #runningProcessCountsPerCore)! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 3/26/2009 10:18'! coreTallyAspects "Answer a list of message selectors that will return tallies from core message tallies" ^RVMCoreMessageTally tallyOrder! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 7/16/2010 15:21'! systemAspects "Answer a list of message selectors that will return single system numbers for my monitor" ^#(#numberOfRunningProcesses #processCount #coreProcessUtilization #bytecodeCountsAverage #bytecodesPerCycle #bytecodesPerCyclesAverage #bytecodesPerMillisecond #bytecodesPerMillisecondsAverage #bytecodesPerSecondAverage #cyclesRunWaitRatiosAverage #cyclesRunningsAverage #cyclesSinceLastsAverage #cyclesWaitingsAverage #msRunWaitRatiosAverage #msRunningsAverage #msSinceLastsAverage #msWaitingsAverage #yieldCountsAverage #yieldsPerSecondAverage )! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^self testCoreAspects, self testSystemAspects! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testCoreAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^RVMMulticoreSample allMethodsInCategory: 'test measuring - core' asSymbol! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testSystemAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^RVMMulticoreSample allMethodsInCategory: 'test measuring - system' asSymbol! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/6/2008 18:46'! updateSystemAndCoreAspectMethods "RVMMulticoreSample updateSystemAndCoreAspectMethods" "Determine the lists of single value system aspects and multivalue core aspects and update the access methods for them" | all singles groups code sample | all _ RVMMulticoreSample allMethodsInCategory: #measuring. singles _ OrderedCollection new. groups _ OrderedCollection new. sample _ RVMMulticoreSample capture. all do:[:msg| ((sample perform: msg) isKindOf:Number)ifTrue:[singles add: msg]ifFalse:[groups add: msg]]. groups remove:#receiveTallySum ifAbsent:[]. code _ 'coreAspects "Answer a list of message selectors that will return collections of core numbers for my monitor" ^', groups asArray storeString. self class compile: code classified:'aspect access' notifying:nil. code _ 'systemAspects "Answer a list of message selectors that will return single system numbers for my monitor" ^', singles asArray storeString. self class compile: code classified:'aspect access' notifying:nil. ! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/16/2008 01:06'! activity "Answer the value of activity, whether or not you want the baton passed on a message send" ^RVMTester getPassTheBatonOf: self object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/16/2008 02:11'! coreCoordinate "Answer the value of coreCoordinate" ^(self coreIndex + 1 asPointWithinRectangleWithExtent: RVMMonitor extent) ! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/16/2008 02:08'! coreIndex "Answer the value of coreIndex" ^(RVMTester getCoreHolding: self object)! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/16/2008 01:06'! mutability "Answer the value of mutability, whether you are readWrite (true) or readMostly (false)" ^RVMTester getReadWriteOf: self object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:29'! object "Answer the value of object" object isNil ifTrue:[self object: nil]. ^ object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:29'! object: anObject "Set the value of object" object _ anObject! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'dmu 5/25/2010 10:43'! makeActive RVMTester isRVM ifTrue:[ RVMTester setCoordinatesOf: self object toCore: self coreIndex readWrite: self mutability]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'dmu 5/25/2010 10:43'! makePassive RVMTester isRVM ifTrue:[ RVMTester setCoordinatesOf: self object toCore: self coreIndex readWrite: self mutability ]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'dmu 5/25/2010 10:43'! makeReadMostly RVMTester isRVM ifTrue:[ RVMTester setCoordinatesOf: self object toCore: self coreIndex readWrite: false ]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'dmu 5/25/2010 10:43'! makeReadWrite RVMTester isRVM ifTrue:[ RVMTester setCoordinatesOf: self object toCore: self coreIndex readWrite: true]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ssa 11/16/2008 02:23'! moveToCoordinate: aPoint self moveToCore: (aPoint y -1 * RVMMonitor extent x + aPoint x) -1 . self changed:#coreCoordinate! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'dmu 5/25/2010 10:43'! moveToCore: anIndex RVMTester isRVM ifTrue:[ RVMTester setCoordinatesOf: self object toCore: (anIndex max:0) readWrite: self mutability ]. self changed! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isActive ^self activity = true! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isPassive ^self activity = false! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isReadMostly ^self mutability = false! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:25'! isReadWrite ^self mutability = true! ! !RVMObjectCoordinate class methodsFor: 'instance creation' stamp: 'ssa 11/16/2008 01:27'! for: anObject "Answer the coordinate for this object" | coord | coord _ self new. coord object: anObject. ^coord! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:20'! allocatedEntryCount "Answer the number of allocated entries in this object table" allocatedEntryCount isNil ifTrue:[^0]. ^allocatedEntryCount! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:20'! allocatedEntryCount: count "Set the number of allocated entries in this object table" allocatedEntryCount := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:43'! allocationsSinceLastQuery "Answer the allocations made since the last query" allocationsSinceLastQuery isNil ifTrue:[^0]. ^allocationsSinceLastQuery! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:44'! allocationsSinceLastQuery: count "Set the allocations made since the last query" allocationsSinceLastQuery := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:45'! entriesFreedSinceLastQuery "Answer the allocations freed since the last query" entriesFreedSinceLastQuery isNil ifTrue:[^0]. ^entriesFreedSinceLastQuery! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:46'! entriesFreedSinceLastQuery: count "Set the allocations freed since the last query" entriesFreedSinceLastQuery := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:19'! entryCount "Answer the number of entries in this object table" entryCount isNil ifTrue:[^0]. ^entryCount! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:19'! entryCount: count "Set the number of entries in this object table" entryCount := count! ! !RVMPluggableTextView methodsFor: 'model access' stamp: 'ssa 11/27/2008 13:06'! getText "Answer the list to be displayed." | txt | getTextSelector == nil ifTrue: [^ Text new]. txt _ getTextSelector isSymbol ifTrue:[model perform: getTextSelector]ifFalse:[getTextSelector value]. txt == nil ifTrue: [^ Text new]. self hasUnacceptedEdits: false. "clean now" ^ txt! ! !RVMPluggableTextView methodsFor: 'model access' stamp: 'ssa 11/27/2008 13:08'! setText: textToAccept from: ctlr "Inform the model of text to be accepted, and return true if OK. Any errors should be reported to the controller, ctlr." setTextSelector == nil ifTrue: [^ true]. setTextSelector isSymbol ifTrue: [^ model perform: setTextSelector with: textToAccept] ifFalse: [^ setTextSelector value: textToAccept]! ! !RVMPluggableTextView methodsFor: 'updating' stamp: 'ssa 11/27/2008 13:47'! update: aSymbol "Refer to the comment in View|update:. Do nothing if the given symbol does not match any action. " aSymbol == #updateDisplay ifTrue: [^ self updateDisplayContents]. ^super update: aSymbol! ! !RVMProcessSwarm methodsFor: 'creation' stamp: 'dmu 2/22/2009 07:14'! initialize: aBlock | p | processes _ OrderedCollection new. 0 to: 55 do: [:i | p _ aBlock copy fixTemps newProcess. p coreMask: (1 bitShift: i). p resume. ].! ! !RVMProcessSwarm methodsFor: 'creation' stamp: 'ssa 2/26/2009 04:36'! initialize: aBlock onCores: aCollectionOfIndicies | p | aCollectionOfIndicies size timesRepeat:[ p _ aBlock copy fixTemps newProcess. p useOnlyCores: aCollectionOfIndicies. p resume. ].! ! !RVMProcessSwarm class methodsFor: 'instance creation' stamp: 'dmu 2/23/2009 08:51'! newRunning: aBlock "RVMProcessSwarm newRunning: [3000 factorial]" "RVMProcessSwarm newRunning: [RVMTester print: Processor thisProcess hostCore factorial printString]" super new initialize: aBlock! ! !RVMProcessSwarm class methodsFor: 'instance creation' stamp: 'ssa 2/26/2009 04:36'! newRunning: aBlock onCores: aCollectionOfIndicies "RVMProcessSwarm newRunning: [3000 factorial] onCores:(1 to: 10)" "RVMProcessSwarm newRunning: [RVMTester print: Processor thisProcess hostCore factorial printString] onCores:#(1 3 5 7)" "RVMProcessSwarm newRunning: [3000 factorial. RVMTester print: Processor thisProcess hostCore printString,' done'] onCores:(1 to: 10),(40 to:50) " super new initialize: aBlock onCores: aCollectionOfIndicies! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:38'! cyclesSinceLastSample "Answer the number of processor cycles since the last sample was taken" cyclesSinceLastSample isNil ifTrue:[^0]. ^cyclesSinceLastSample! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 10:05'! cyclesSinceLastSample: count "Set the number of processor cycles since the last sample was taken" cyclesSinceLastSample := count! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! globalHeapStats "Answer the global heap stats for this sample" globalHeapStats isNil ifTrue:[self globalHeapStats: RVMGlobalHeapStats new]. ^globalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:40'! globalHeapStats: anRVMGlobalHeapStats "Set the global heap stats for this sample" globalHeapStats := anRVMGlobalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! localHeapStats "Answer the local heap stats for this sample" localHeapStats isNil ifTrue:[self localHeapStats: RVMLocalHeapStats new]. ^localHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 10:13'! localHeapStats: anRVMLocalHeapStats "Set the local heap stats for this sample" localHeapStats := anRVMLocalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:38'! millisecondsSinceLastSample "Answer the time since the last sample was taken" millisecondsSinceLastSample isNil ifTrue:[^0]. ^millisecondsSinceLastSample! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:37'! millisecondsSinceLastSample: milliseconds "Set the time since the last sample was taken" millisecondsSinceLastSample := milliseconds! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! objectTableStats "Answer the object stats for this sample" objectTableStats isNil ifTrue:[self objectTableStats: RVMObjectTableStats new]. ^objectTableStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:45'! objectTableStats: anRVMObjectTableStats "Set the object stats for this sample" objectTableStats := anRVMObjectTableStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:25'! rawData "Answer the raw data for this sample" ^rawData! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:25'! rawData: anArray "Set the raw data for this sample" rawData := anArray! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:30'! squeakInterpreterStats "Answer the squeak interpreter stats for this sample" squeakInterpreterStats isNil ifTrue:[self squeakInterpreterStats: RVMSqueakInterpreterStats new]. ^squeakInterpreterStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:22'! squeakInterpreterStats: anRVMSqueakInterpreterStats "Set the squeak interpreter stats for this sample" squeakInterpreterStats := anRVMSqueakInterpreterStats! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:31'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self rawData: data. valueMap := { 'millisecs' -> #millisecondsSinceLastSample:. 'cycles' -> #cyclesSinceLastSample:. }. objectMap := { 'The_Global_Object_Heap.get_stats()' -> #initializeGlobalHeapStatsFrom:. 'The_Local_Object_Heap.get_stats()' -> #initializeLocalHeapStatsFrom:. 'The_Object_Table.get_stats()' -> #initializeObjectTableStatsFrom:. 'The_Squeak_Interpreter.get_stats()' -> #initializeSqueakInterpreterStatsFrom:. }. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:11'! initializeGlobalHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self initializeHeapStatsFrom: data into: self globalHeapStats. valueMap := {}. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self globalHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self globalHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:11'! initializeHeapStatsFrom: data into: aHeapStats "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocations_since_last_query' -> #allocationsSinceLastQuery:. 'compactions_since_last_query' -> #compactionsSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. aHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. aHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:12'! initializeLocalHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self initializeHeapStatsFrom: data into: self localHeapStats. valueMap := { 'objects_fetched_into_local_heap_since_last_query' -> #objectsFetchedSinceLastQuery:. 'overly_large_fetch_or_allocation_requests_denied_since_last_query' -> #overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery:. 'fetch_requests_that_failed_since_last_query' -> #failedFetchRequestsSinceLastQuery:. 'objects_flushed_since_last_query' -> #objectsFlushedSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self localHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self localHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:16'! initializeObjectTableStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'how_many_entries_are_currently_allocated' -> #allocatedEntryCount:. 'how_many_entries_exist' -> #entryCount:. 'how_many_allocations_have_occured_since_last_query' -> #allocationsMadeSinceLastQuery:. 'how_many_have_been_freed_since_last_query' -> #allocationsFreedSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self objectTableStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self objectTableStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:19'! initializeSqueakInterpreterStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'bcCount - bytecodes' -> #bytecodeCount:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self squeakInterpreterStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self squeakInterpreterStats perform: assoc value with: datum]. ! ! !RVMSample class methodsFor: 'primitive access' stamp: 'ssa 7/21/2008 10:38'! primitiveCapture "Grab some data from the VM and return it" self primitiveFailed! ! !RVMSample class methodsFor: 'instance creation' stamp: 'ssa 7/21/2008 11:23'! capture "Capture a sample from the vm and answer a new instance of me holding those values" | data sample | data := self primitiveCapture. sample := self new. sample initializeFrom: data. ^sample! ! !RVMSample class methodsFor: 'example' stamp: 'ssa 7/21/2008 11:24'! example "RVMSample example" self capture explore! ! !RVMSample class methodsFor: 'example' stamp: 'ssa 8/13/2008 15:05'! examplePrimitive "RVMSample examplePrimitive" self primitiveCapture explore! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! allCoreStats ^ 1 bitShift: 4! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! allCores ^ 1 bitShift: 0! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! bufferedMessageStats ^ 1 bitShift: 17! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! bytecodes ^ 1 bitShift: 21! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! coreCoords ^ 1 bitShift: 14! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! cpuCoreStats ^ 1 bitShift: 3! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! cycleCounts ^ 1 bitShift: 23! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! cycles ^ 1 bitShift: 8! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! dontPassTheBatonDefault ^ 1 bitShift: 5! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:30'! everything ^ SmallInteger maxVal! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:31'! fence ^ 1 bitShift: 6! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:31'! gcStats ^ 1 bitShift: 19! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! heapStats ^ 1 bitShift: 20! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interactionStats ^ 1 bitShift: 13! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interpreterLoopStats ^ 1 bitShift: 27! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interpreterStats ^ 1 bitShift: 11! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interruptChecks ^ 1 bitShift: 24! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! memorySystemStats ^ 1 bitShift: 10! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! messageNames ^ 1 bitShift: 2! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! messageStats ^ 1 bitShift: 9! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! millisecs ^ 1 bitShift: 7! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! movedMutatedObjectStats ^ 1 bitShift: 25! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! mutexStats ^ 1 bitShift: 26 ! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! objectTableStats ^ 1 bitShift: 12! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! receiveCycles ^ 1 bitShift: 18! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! receiveTallies ^ 1 bitShift: 16! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! runMask ^ 1 bitShift: 1! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:35'! sendTallies ^ 1 bitShift: 15! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:35'! yieldCount ^ 1 bitShift: 22! ! !RVMSqueakInterpreterStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:21'! cyclesRunWaitRatio "Answer the ratio between my cyclesRunning and cyclesWaiting" ^self cyclesWaiting = 0 ifTrue:[0] ifFalse:[self cyclesRunning / (1 max: self cyclesWaiting) asFloat]! ! !RVMSqueakInterpreterStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:21'! msRunWaitRatio "Answer the ratio between my millisecondsRunning and millisecondsWaiting" ^self millisecondsWaiting = 0 ifTrue:[0] ifFalse:[self millisecondsRunning / (1 max: self millisecondsWaiting) asFloat]! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:27'! bytecodesExecuted "Answer the number of bytecodes processed since last query" bytecodesExecuted isNil ifTrue:[^0]. ^bytecodesExecuted! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:27'! bytecodesExecuted: count "Set the number of bytecodes processed since last query" bytecodesExecuted := count! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! contextChangeCount "Answer the value of contextChangeCount" contextChangeCount isNil ifTrue:[self contextChangeCount: 0]. ^contextChangeCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:10'! contextChangeCount: anObject "Set the value of contextChangeCount" contextChangeCount := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! cyclesRunning "Answer the value of cyclesRunning" cyclesRunning isNil ifTrue:[self cyclesRunning: 0]. ^cyclesRunning! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! cyclesRunning: anObject "Set the value of cyclesRunning" cyclesRunning := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! cyclesWaiting "Answer the value of cyclesWaiting" cyclesWaiting isNil ifTrue:[self cyclesWaiting: 0]. ^cyclesWaiting! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! cyclesWaiting: anObject "Set the value of cyclesWaiting" cyclesWaiting := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! interruptCheckCount ^ interruptCheckCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! interruptCheckCount: x interruptCheckCount := x! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! millisecondsRunning "Answer the value of millisecondsRunning" millisecondsRunning isNil ifTrue:[self millisecondsRunning: 0]. ^millisecondsRunning! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:24'! millisecondsRunning: anObject "Set the value of msRunning" millisecondsRunning := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:01'! millisecondsWaiting "Answer the value of msWaiting" millisecondsWaiting isNil ifTrue:[self millisecondsWaiting: 0]. ^millisecondsWaiting! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:25'! millisecondsWaiting: anObject "Set the value of msWaiting" millisecondsWaiting := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:04'! unforcedInterruptCheckCount ^ unforcedInterruptCheckCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! unforcedInterruptCheckCount: x unforcedInterruptCheckCount := x! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! yieldCount "Answer the value of yieldCount" yieldCount isNil ifTrue:[self yieldCount: 0]. ^yieldCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! yieldCount: anObject "Set the value of yieldCount" yieldCount := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 9/17/2010 15:21'! yieldFrequency "Answer the value of yieldCount/contextChangeCount" ^self contextChangeCount = 0 ifTrue: [0] ifFalse: [(self yieldCount / (1 max: self contextChangeCount)) asFloat]! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 8/20/2008 19:15'! displayLabelText "The label goes in the center of the window" | labelRect | labelText foregroundColor: Color black backgroundColor: self labelColor. labelRect := self labelTextRegion. Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor. labelText displayOn: Display at: labelRect topLeft clippingBox: labelRect rule: labelText rule fillColor: labelText fillColor. labelText destinationForm: nil! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:02'! displayView self okToDisplay: true. super displayView! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! dontDisplayWhile: aBlock "Switch my okToDisplay flag off during this block" self okToDisplay: false. aBlock value. self okToDisplay: true. self displayView! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! erase self okToDisplay: false. ^super erase! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! okToDisplay: aBoolean self subViews do:[:v| v isRVMView ifTrue:[v okToDisplay: aBoolean]]. ! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:24'! constrainFrame: aRectangle "Constrain aRectangle, to the minimum and maximum size for this window" | adjustmentForLabel bWidth | bWidth _ labelFrame borderWidth. (bWidth isKindOf: Rectangle) ifTrue:[bWidth _ bWidth origin x]. adjustmentForLabel := 0 @ (labelFrame height - bWidth). ^ aRectangle origin extent: ((aRectangle extent max: minimumSize + adjustmentForLabel) min: maximumSize + adjustmentForLabel).! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:51'! initialExtent ^self minimumSize! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:25'! newFrame self subViews do:[:v| v isRVMView ifTrue:[v newFrame]]! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:15'! newFrame: frameChangeBlock super newFrame: frameChangeBlock. self subViews do:[:v| v isRVMView ifTrue:[v newFrame]]! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:14'! resizeInitially "Determine the rectangular area for the receiver, adjusted to the minimum and maximum sizes." self resizeTo: self initialFrame. self subViews do:[:v| v isRVMView ifTrue:[v firstFrame]] ! ! !RVMStandardSystemView methodsFor: 'accessing' stamp: 'ssa 10/4/2008 08:29'! subViews: aCollection. subViews _ aCollection! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:56'! eraseStrip self view traces do:[:trace| trace removeAllData]. self view canvas:nil. self view displayView! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 01:00'! inspectScaler self view traces first scaler inspect! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 12:59'! muteAll self view traces do:[:trace| trace mute]. self view topView allSubViews do:[:v|( v isKindOf: RVMCheckBoxOnlyView) ifTrue:[v update:#checked]]! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/20/2008 09:02'! spawnUnmuted | unmutes | unmutes _ self view traces select:[:trace| trace muted not]. self view okToDisplay: true. RVMStripChartView openOnTraces: unmutes deepCopy titled: 'Selected traces'! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 12:59'! unmuteAll self view traces do:[:trace| trace unmute]. self view topView allSubViews do:[:v|( v isKindOf: RVMCheckBoxOnlyView) ifTrue:[v update:#checked]]! ! !RVMStripChartController methodsFor: 'controlling' stamp: 'ssa 10/20/2008 08:21'! yellowButtonActivity | menu answer | self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := CustomMenu new. "menu add: 'inspect scaler' action: #inspectScaler." menu add: 'mute all' action: #muteAll. menu add: 'unmute all' action: #unmuteAll. menu add: 'spawn unmuted' action: #spawnUnmuted. menu addLine. menu add: 'erase strip' action: #eraseStrip. answer := menu startUp: #eraseStrip withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer]]]! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:33'! addCoreTrace | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to trace' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view stripChart addCoreTraceForAspect: selectedAspect coreIndex: RVMMonitor coreIndexFromUser]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:36'! addSystemTrace | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample systemAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a system aspect to trace' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view stripChart addSystemTraceForAspect: selectedAspect]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 10/3/2008 23:12'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'System aspects' action: #system. menu add: 'Core aspects' action: #core. menu add: 'Test System Aspects' action: #testSystem. menu add: 'Test Core Aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. newAspect = self view stripChart traces first aspect ifTrue:[^self]. self view stripChart removeAllTraces. (#(testCore core) includes: answer) ifTrue:[self view stripChart addCoreTraceForAspect: newAspect coreIndex: RVMMonitor coreIndexFromUser] ifFalse:[self view stripChart addSystemTraceForAspect: newAspect]. self view currentTrace: self view stripChart traces first]. self view hear: nil. self view stripChart newFrame.! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:31'! changeScaleAspect | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Show scale for this aspect:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view currentTrace: selectedTrace]]. self view hear: nil! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 11/11/2008 22:06'! redButtonActivity ((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:08'! removeOtherTraces | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Remove all traces except:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view stripChart removeTraces: (self view stripChart traces copyWithout: selectedTrace). self view currentTrace: selectedTrace]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:07'! removeTrace | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Select trace to remove:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view stripChart removeTrace: selectedTrace. self view currentTrace = selectedTrace ifTrue:[self view currentTrace: nil]]. ]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:05'! scalerForThisAspect self view okToDisplay:true. RVMColoredDataScalerView openOnAspect: self view currentTrace aspect! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height | maxView _ RVMValueEditorView on: view currentTrace scaler valueGetter: [view currentTrace scaler max] valueSetter:[:v|view currentTrace scaler setMax:v. view drawCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: view currentTrace scaler valueGetter: [view currentTrace scaler min] valueSetter:[:v|view currentTrace scaler setMin:v. view drawCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[view currentTrace scaler resetScaling. view drawCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[view currentTrace scaler setRangeToObserved. view drawCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: view currentTrace scaler label: 'Automatic Scaling' checkState: [view currentTrace scaler automaticScaling] whenChecked: [view currentTrace scaler automatic. view drawCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [view currentTrace scaler manual. view drawCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: view currentAspect. height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. topView controller open! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 10/4/2008 08:19'! yellowButtonActivity | menu answer onlyOneTrace | onlyOneTrace _ self view stripChart traces size = 1. self view topView dontDisplayWhile:[ menu := CustomMenu new. onlyOneTrace ifTrue:[menu add: 'Change aspect' action: #changeAspect. menu addLine]. onlyOneTrace ifFalse:[menu add: 'Show other scale' action: #changeScaleAspect. menu addLine]. menu add: 'Add system aspect trace' action: #addSystemTrace. menu add: 'Add core aspect trace' action: #addCoreTrace. onlyOneTrace ifFalse:[menu addLine. menu add: 'Remove trace' action: #removeTrace. menu add: 'Remove other traces' action: #removeOtherTraces]. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMStripChartScaleController methodsFor: 'view resizing' stamp: 'ssa 1/1/1970 00:38'! adjustViewSizes self view topView unlock. self view topView display! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 10/10/2008 19:23'! color "Answer the value of color" color isNil ifTrue:[self color: Color black]. ^ color! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! color: anObject "Set the value of color" color _ anObject. color notNil ifTrue:[self pen color: color]! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! max "Answer my scaler max." ^self scaler max! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! max: aValue "Set my scaler max." self scaler max: aValue! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! min "Answer my scaler min." ^self scaler min! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! min: aValue "Set my scaler min." self scaler min: aValue! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:24'! muted "Answer the value of muted" muted isNil ifTrue:[self muted: false]. ^ muted! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:24'! muted: anObject "Set the value of muted" muted _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 10/10/2008 19:22'! pen "Answer the value of pen" | bic | pen isNil ifTrue:[bic _ Pen new. bic defaultNib:1. bic combinationRule: Form over. self pen: bic]. ^ pen! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:01'! pen: anObject "Set the value of pen" pen _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: (RVMCircularCollection new:10)]. ^ rawData! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! rawData: anObject "Set the value of rawData" rawData _ anObject. scaledData _ rawData collect:[:datum| self scaler scale: datum].! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:09'! scaledData "Answer the value of scaledData" scaledData isNil ifTrue:[self scaledData: self initialScaledData]. ^ scaledData! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scaledData: anObject "Set the value of scaledData" scaledData _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: nil]. ^ scaler! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:04'! scaler: anObject "Set the value of scaler" scaler _ anObject. scaler notNil ifTrue:[self removeAllData]! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:53'! add: aValue "Add this value to the end of my data" self rawData add: aValue. self scaledData add: (self scaler scale: aValue)! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 01:25'! addData "do nothing, only works in subclasses"! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:25'! initialScaledData "Generate the scaled data by scaling the rawData" ^self rawData collect:[:datum| self scaler scale: datum]! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:41'! removeAllData self rawData removeAll. self scaledData removeAll! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 01:13'! resizeTo: anInteger (self rawData isKindOf: RVMCircularCollection) ifTrue:[ self rawData size: anInteger. self scaledData size: anInteger]! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:12'! drawLastOn: aColorForm "Draw the last line segment on this canvas using this pen." | yScale xSpacing x | self muted ifTrue:[^self]. self pen destForm: aColorForm. self scaledData numberOfElements = 1 ifTrue:[^self drawOn: aColorForm]. yScale _ aColorForm height / 100. xSpacing _ 2. x _ self scaledData numberOfElements - 1* xSpacing. self pen place: x@ (aColorForm height -((self scaledData at: self scaledData numberOfElements - 1) * yScale)). self pen goto: x+ xSpacing @ (aColorForm height -((self scaledData at: self scaledData numberOfElements) * yScale)). ! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:25'! drawOn: aColorForm | yScale xSpacing x first | self muted ifTrue:[^self]. self pen destForm: aColorForm. yScale _ aColorForm height / 100. xSpacing _ 2. x _ 0. first _ true. self scaledData do:[:datum| first ifTrue:[self pen place: x@ (aColorForm height -(datum * yScale)). first _ false]. self pen goto: x@ (aColorForm height -(datum * yScale)). x _ x + xSpacing. x < 0 ifTrue:[^self]]! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:28'! mute self muted: true.! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:11'! redrawOn: aColorForm self scaledData: nil. self drawOn: aColorForm! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:28'! unmute self muted: false.! ! !RVMStripChartTrace methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:04'! isEmpty ^self rawData isEmpty! ! !RVMStripChartTrace methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:04'! isFull ^self rawData isFull! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:21'! colorButton "Answer a color button connect to my color" ^RVMColorButtonView on: self colorGetter:#color colorSetter:#color:! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:23'! minmaxButton "Answer a minmax button connect to my scaler's minmax" ^RVMMinMaxView on: self getMin: #min setMin: #min: getMax: #max setMax: #max:! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 5/12/2010 10:13'! muteButton "Answer a color button connect to my color" | v | v _ RVMCheckBoxOnlyView on: self label: '' checkState: [self muted not] whenChecked: [self unmute] whenUnchecked: [self mute]. RVMMonitor inform: v. ^v! ! !RVMStripChartTrace methodsFor: 'scaling' stamp: 'ssa 10/6/2008 16:29'! rescale "Reset my scaler and recompute my scaledData" self scaler resetScaling. self scaledData:nil.! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:44'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #bytesUseds]. ^ aspect! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:03'! aspect: anObject "Set the value of aspect" aspect _ anObject. aspect notNil ifTrue:[self scaler: (RVMMonitor scalerFor:aspect)]! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:17'! aspectLabel ^self aspect! ! !RVMAspectTrace methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:26'! addData "Assume a single valued data source" self add:(RVMMonitor lastSample perform: self aspect)! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:29'! allView ^self aspectColorMuteView! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:32'! aspectButton "Answer an aspect button connect to my aspect" ^RVMAspectLabelView on: self getAllAspectsWith: [RVMMulticoreSample systemAspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:46'! aspectColorMuteView "Answer a view showing my color and aspect" | view | view _ RVMView new. view model: self. view addSubView: self muteButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self colorButton in: ((1/10)@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((2/10)@0 extent: (8/10) @ 1) borderWidth:1. ^view! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:37'! aspectColorView "Answer a view showing my color and aspect" | view | view _ RVMView new. view addSubView: self colorButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((1/10)@0 extent: (9/10) @ 1) borderWidth:1. ^view! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:21'! aspectLabel ^'#',self coreIndex printString,' ',self aspect! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:27'! coreIndex "Answer the value of coreIndex" coreIndex isNil ifTrue:[self coreIndex: 1]. ^ coreIndex! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:27'! coreIndex: anObject "Set the value of coreIndex" coreIndex _ anObject! ! !RVMCoreAspectTrace methodsFor: 'updating' stamp: 'ssa 11/17/2008 17:09'! addData "Assume a multi valued data source" self add:((RVMMonitor lastSample perform: self aspect) at: self coreIndex + 1)! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:46'! allView "Answer a view showing my color and aspect" | view | view _ RVMView new. view model: self. view addSubView: self muteButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self coreIndexButton in: (1/10@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self colorButton in: (2/10@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((3/10)@0 extent: (7/10) @ 1) borderWidth:1. ^view! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:20'! aspectButton "Answer an aspect button connect to my aspect" ^RVMAspectLabelView on: self getAllAspectsWith: [RVMMulticoreSample coreAspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:.! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:34'! coreIndexButton "Answer an aspect button connect to my aspect" ^RVMCoreIndexView on: self getCoreIndex:#coreIndex setCoreIndex: #coreIndex: getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]! ! !RVMStripChartTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:50'! data: someData min: minValue max: maxValue color: aColor "Answer a new strip chart trace with this data and parameters. Note that the type of collection used for someData will also be used for scaled data. Use OrderedCollection for variable sized data, CircularCollection for fixed size." | trace | trace _ self new. trace scaler: (RVMDataScaler min: minValue max: maxValue); rawData: someData; color: aColor. ^trace! ! !RVMStripChartTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:29'! size: anInteger min: minValue max: maxValue color: aColor "Answer a new strip chart trace with this size buffer and parameters" | trace | trace _ self new. trace scaler: (RVMDataScaler min: minValue max: maxValue); rawData: (RVMCircularCollection new: anInteger); color: aColor. ^trace! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 10/18/2008 23:18'! exampleCircularInstance "RVMStripChartTrace exampleCircularInstance" ^ self data: #(1 2 3 4 5 6 7 8 9) asCircularCollection min: 0 max: 10 color: Color blue! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:55'! exampleInstance "RVMStripChartTrace exampleInstance" ^ self data: #(1 2 3 4 5 6 5 4 3 2 1) min: 0 max: 10 color: Color blue! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:14'! randomInstance "RVMStripChartTrace randomInstance" | data | data _ OrderedCollection new. 100 timesRepeat:[data add: 10 atRandom]. ^ self data: data min: 0 max: 10 color: Color random! ! !RVMAspectTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:35'! aspect: aSymbol size: anInteger color: aColor | trace | trace _ self new. trace scaler: RVMDataScaler new automatic; rawData: (RVMCircularCollection new: anInteger); color: aColor; aspect: aSymbol. ^trace! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:51'! exampleInstance "RVMAspectTrace exampleInstance" ^self aspect: #bytecodeCountsAverage size: 100 color: Color blue! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:46'! exampleView1 "RVMAspectTrace exampleView1" RVMStripChartView openOnTrace: self exampleInstance! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:31'! exampleView2 "RVMAspectTrace exampleView2" self exampleInstance aspectColorView demo! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:35'! exampleView3 "RVMAspectTrace exampleView3" self exampleInstance aspectButton demo! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:25'! exampleView4 "RVMAspectTrace exampleView4" | traces | traces _ OrderedCollection new. RVMMulticoreSample systemAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:18'! monitorAllSystemAspects "RVMAspectTrace monitorAllSystemAspects" | traces colors | colors _ (Color wheel: RVMMulticoreSample systemAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. RVMMulticoreSample systemAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'All system aspects'! ! !RVMAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 00:07'! monitorAspects: someAspects "RVMAspectTrace monitorAspects: #(bytecodeCountsAverage bytecodesPerSecondAverage yieldCountsAverage)" | traces colors | colors _ (Color wheel: someAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. someAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'Selected system aspects'! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:14'! monitorAllCoreAspectsForCore: anInteger "RVMCoreAspectTrace monitorAllCoreAspectsForCore: 1" | traces colors | colors _ (Color wheel: RVMMulticoreSample coreAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. RVMMulticoreSample coreAspects do:[:aspect| traces add:(self coreIndex: anInteger aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'All core aspects for core #',anInteger printString! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 00:21'! monitorAllCoreAspectsForCoreFromUser "RVMCoreAspectTrace monitorAllCoreAspectsForCoreFromUser" self monitorAllCoreAspectsForCore: RVMMonitor coreIndexFromUser! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:21'! monitorAspects: someAspects forCore: anInteger "RVMCoreAspectTrace monitorAspects: #(bytecodeCounts bytesUseds) forCore: 1" | traces colors | colors _ (Color wheel: someAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. someAspects do:[:aspect| traces add:(self coreIndex: anInteger aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'Selected aspects for core #',anInteger printString! ! !RVMCoreAspectTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:32'! coreIndex: anIndex aspect: aSymbol size: anInteger color: aColor | trace | trace _ self aspect: aSymbol size: anInteger color: aColor. trace coreIndex: anIndex. ^trace! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:44'! exampleInstance "RVMCoreAspectTrace exampleInstance" ^self coreIndex: 1 aspect: #bytesUseds size: 100 color: Color blue! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:16'! exampleView1 "RVMCoreAspectTrace exampleView1" RVMStripChartView openOnTrace: self exampleInstance! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:24'! exampleView2 "RVMCoreAspectTrace exampleView2" | traces | traces _ OrderedCollection new. traces add:(self coreIndex: 1 aspect: #bytecodeCounts size: 200 color: Color blue). traces add:(self coreIndex: 1 aspect: #bytesUseds size: 200 color: Color red). traces add:(self coreIndex: 1 aspect: #yieldCounts size: 200 color: Color green). RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:07'! exampleView3 "RVMCoreAspectTrace exampleView3" | traces | traces _ OrderedCollection new. 1 to: 4 do:[:core| traces add:(self coreIndex: core aspect: #bytecodeCounts size: 100 color: Color random). traces add:(self coreIndex: core aspect: #bytesUseds size: 100 color: Color random). traces add:(self coreIndex: core aspect: #yieldCounts size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:38'! exampleView4 "RVMCoreAspectTrace exampleView4" self exampleInstance aspectColorView demo! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:36'! exampleView5 "RVMCoreAspectTrace exampleView5" self exampleInstance allView demo! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:06'! exampleView6 "RVMCoreAspectTrace exampleView6" | traces | traces _ OrderedCollection new. 1 to: 10 do:[:core| traces add:(self coreIndex: core aspect: #bytecodeCounts size: 100 color: Color random). traces add:(self coreIndex: core aspect: #bytesUseds size: 100 color: Color random). traces add:(self coreIndex: core aspect: #yieldCounts size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:09'! exampleView7 "RVMCoreAspectTrace exampleView7" | traces | traces _ OrderedCollection new. RVMMulticoreSample coreAspects do:[:aspect| traces add:(self coreIndex: 1 aspect: aspect size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMTest methodsFor: 'logging' stamp: 'dmu 11/11/2009 18:06'! log: aString Transcript cr;show:'log: [',self name,'] ',aString. Transcript cr; cr. self runLog add: {Time dateAndTimeNow. aString}! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:19'! assertionBlock "Answer the value of assertionBlock" assertionBlock isNil ifTrue:[self assertionBlock: [:test :outcome| false]]. ^ assertionBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:46'! assertionBlock: anObject "Set the value of assertionBlock" assertionBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:47'! assertions "Answer the value of assertions" assertions isNil ifTrue:[self assertions: OrderedCollection new]. ^ assertions! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:47'! assertions: anObject "Set the value of assertions" assertions _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! environment "Answer the value of environment" environment isNil ifTrue:[self environment: nil]. ^ environment! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! environment: anObject "Set the value of environment" environment _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! lastResult "Answer the value of lastResult" lastResult isNil ifTrue:[self lastResult: nil]. ^ lastResult! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! lastResult: anObject "Set the value of lastResult" lastResult _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:05'! name "Answer the value of name" name isNil ifTrue:[self name: 'unnamed']. ^ name! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:05'! name: anObject "Set the value of name" name _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:39'! result ^self lastResult! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:31'! runLog "Answer the value of runLog" runLog isNil ifTrue:[self runLog: OrderedCollection new]. ^ runLog! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:31'! runLog: anObject "Set the value of runLog" runLog _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 08:58'! setUpBlock "Answer the value of setUpBlock" setUpBlock isNil ifTrue:[self setUpBlock: [:test| ]]. ^ setUpBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! setUpBlock: anObject "Set the value of setUpBlock" setUpBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 08:58'! tearDownBlock "Answer the value of tearDownBlock" tearDownBlock isNil ifTrue:[self tearDownBlock: [:test :env|]]. ^ tearDownBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! tearDownBlock: anObject "Set the value of tearDownBlock" tearDownBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:19'! testBlock "Answer the value of testBlock" testBlock isNil ifTrue:[self testBlock: [:test :env| self log:'testing']]. ^ testBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:22'! testBlock: anObject "Set the value of testBlock" testBlock _ anObject! ! !RVMTest methodsFor: 'testing process' stamp: 'ssa 3/5/2010 17:37'! run self environment: (self setUpBlock value: self). self lastResult: self runTest. self tearDownBlock value: self value: self environment. ^self lastResult ! ! !RVMTest methodsFor: 'testing process' stamp: 'dmu 9/3/2010 11:49'! runTest | outcome result decision | outcome _ self testBlock value: self value: self environment. result _ RVMTestResult test: self result: outcome asserting: ((self assertionBlock value: self value: outcome) and:[self allAssertionsPassed]). self log: result gradeString. (result failed and:[self name ~= 'testFailure'])ifTrue:[decision _ self confirm:'Test [', self name,'] failed, continue?'. decision ifFalse:[self halt:'Test [', self name,'] failed, aborting other tests']]. ^result! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:00'! fullPrintOn: aStream aStream nextPutAll: 'Testing: ',self name. aStream cr; nextPutAll: 'result: '. self result printOn:aStream. aStream cr; nextPutAll: 'setUp: '. self setUpBlock printOn:aStream. aStream cr; nextPutAll: 'test: '. self testBlock printOn:aStream. aStream cr; nextPutAll: 'tearDown: '. self tearDownBlock printOn:aStream. aStream cr; nextPutAll: 'asserting: '. self assertionBlock printOn:aStream. aStream cr; nextPutAll: 'runLog: '. self runLog printOn:aStream. ! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:05'! gradeString ^self lastResult isNil ifTrue:['untested']ifFalse:[self lastResult gradeString]! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 06:59'! printOn: aStream aStream nextPutAll: self shortPrintString,'(',self gradeString,')'! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 06:04'! shortPrintString ^'Testing: ',self name! ! !RVMTest methodsFor: 'assertions' stamp: 'ssa 8/27/2009 06:51'! allAssertionsPassed self assertions detect:[:each| each = false] ifNone:[^true]. ^false! ! !RVMTest methodsFor: 'assertions' stamp: 'ssa 9/15/2009 16:34'! assert: aTrueResult self assert: aTrueResult ifFail: [self log: 'assertion failed']! ! !RVMTest methodsFor: 'assertions' stamp: 'dmu 12/16/2009 16:06'! assert: aTrueResult ifFail: failBlock (aTrueResult = true) | (aTrueResult = false) ifFalse:[self lyError:'assertion expressions result result in Booleans']. self assertions add: aTrueResult. aTrueResult ifFalse:[self class debugOnFail ifTrue:[self halt:self printString,' assertion failed']ifFalse:failBlock]. ! ! !RVMTest class methodsFor: 'settings' stamp: 'ssa 9/15/2009 16:28'! debugOnFail "If true, then a failing assertion or failBlock execution will open a Debugger" DebugOnFail isNil ifTrue:[DebugOnFail _ false]. ^DebugOnFail! ! !RVMTest class methodsFor: 'settings' stamp: 'ssa 9/15/2009 16:29'! debugOnFail: aBoolean "If true, then a failing assertion or failBlock execution will open a Debugger" DebugOnFail _ aBoolean! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runSetUp: setUpBlock test: testBlock asserting: assertionBlock | test | test _ self setUp: setUpBlock test: testBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:51'! runSetUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock | test | test _ self setUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runTest: testBlock asserting: assertionBlock | test | test _ self test: testBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runTest: testBlock tearDown: tearDownBlock asserting: assertionBlock | test | test _ self test: testBlock tearDown: tearDownBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'examples' stamp: 'ssa 7/7/2010 14:02'! fullExample "self fullExample run" "Use this example as a template for your tests in subclasses of LyTestSuite in the 'tests' message category" | theTest | theTest _ RVMTest setUp: [:test| test log:'setting up for test:',test name. "setUpBlocks return the test environment" #( 1 2 3 4 5 )] test:[:test :env| test log:'test:',test name,' starting...'. "testBlocks perform the test in the setup environment. The test object is available for assertions and logging" test assert: (env at: 2)=2. test assert:(env select:[:e| e odd]) = #(1 3 5) ifFail:[test log:'odd selections failed']. test log:'test:',test name,' complete'. "the last expression result is the outcome of the test" env size = 5] tearDown:[:test :env| test log:'tearing down test:',test name. "tearDownBlocks do any necessary cleanup that would not otherwise be garbage collected" test log:'tear down complete'] asserting:[:test :outcome| "assertionBlocks must result in True or False, and represent the pass/fail judgement of the test outcome" "if you use assert: or assert:ifFail: in these blocks their ANDed result will be ANDed to the result of this block for the final assertion" outcome = true "or use an expression that results in True or False"]. theTest name: 'fullExample'. ^theTest! ! !RVMTest class methodsFor: 'examples' stamp: 'ssa 7/7/2010 14:03'! simpleFullExample "self simpleFullExample run" | theTest | theTest _ RVMTest setUp: [:test| ] test:[:test :env| 123] tearDown:[:test :env| ] asserting:[:test :outcome| outcome = 123]. theTest name: 'simpleFullExample'. ^theTest! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:49'! setUp: setUpBlock test: testBlock asserting: assertionBlock ^self new setUpBlock: setUpBlock; testBlock: testBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:48'! setUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock ^self new setUpBlock: setUpBlock; testBlock: testBlock; tearDownBlock: tearDownBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:50'! test: testBlock asserting: assertionBlock ^self new testBlock: testBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:50'! test: testBlock tearDown: tearDownBlock asserting: assertionBlock ^self new testBlock: testBlock; tearDownBlock: tearDownBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'user interfacing' stamp: 'ssa 5/12/2010 10:19'! debugOnFailSwitch "self debugOnFailSwitch" | topView | topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: 130@30. topView maximumSize: 200@200. topView addSubView: (RVMCheckBoxView on: self label: 'LyTest debugOnFail' checkState: [self debugOnFail] whenChecked: [self debugOnFail: true] whenUnchecked: [self debugOnFail: false] monitor: true). topView controller open! ! !RVMTest class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! fullExampleTest "self fullExampleTest" | theTest | theTest _ RVMTest setUp: [:test| test log:'setting up for test:',test name. "setUpBlocks return the test environment" #( 1 2 3 4 5 )] test:[:test :env| test log:'test:',test name,' starting...'. "testBlocks perform the test in the setup environment. The test object is available for assertions and logging" test assert: (env at: 2)=2. test assert:(env select:[:e| e odd]) = #(1 3 5) ifFail:[test log:'odd selections failed']. test log:'test:',test name,' complete'. "the last expression result is the outcome of the test" env size = 5] tearDown:[:test :env| test log:'tearing down test:',test name. "tearDownBlocks do any necessary cleanup that would not otherwise be garbage collected" test log:'tear down complete'] asserting:[:test :outcome| "assertionBlocks must result in True or False, and represent the pass/fail judgement of the test outcome" test allAssertionsPassed . " use this when using assert: or assert:ifFail:" outcome = true "or use an expression that results in True or False"]. theTest name: 'fullExampleTest'. ^theTest! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:03'! assertion "Answer the value of assertion" assertion isNil ifTrue:[self assertion: nil]. ^ assertion! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:27'! assertion: anObject "Set the value of assertion" assertion _ anObject! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! result "Answer the value of result" result isNil ifTrue:[self result: nil]. ^ result! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! result: anObject "Set the value of result" result _ anObject! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! test "Answer the value of test" test isNil ifTrue:[self test: nil]. ^ test! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! test: anObject "Set the value of test" test _ anObject! ! !RVMTestResult methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:01'! gradeString ^self passed ifTrue:['passed']ifFalse:['failed']! ! !RVMTestResult methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:01'! printOn: aStream aStream nextPutAll: self gradeString, ' ',self test shortPrintString! ! !RVMTestResult methodsFor: 'testing' stamp: 'ssa 8/27/2009 06:02'! failed ^self assertion not! ! !RVMTestResult methodsFor: 'testing' stamp: 'ssa 8/27/2009 06:02'! passed ^self assertion! ! !RVMTestResult class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:26'! test: aRVMTest result: anOutcome asserting: anAssertion ^self new test: aRVMTest; result: anOutcome; assertion: anAssertion; yourself! ! !RVMTestSuite methodsFor: 'acessing' stamp: 'ssa 8/27/2009 07:07'! results ^self tests collect:[:test| test result]! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/30/2009 03:50'! failureCount ^(self tests select:[:test| test result failed])size! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/30/2009 03:50'! failures ^(self tests select:[:test| test result failed])! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/27/2009 09:06'! reportResults | passers failures | passers _ OrderedCollection new. failures _ OrderedCollection new. self tests do:[:test| test result passed ifTrue:[passers add: test name asSymbol]ifFalse:[failures add: test name asSymbol]]. Transcript cr;show:'-------------------';cr; show: 'Results for TestSuite:'; show: 'Summary: ',passers size printString,' passed, ',failures size printString,' failed';cr. failures isEmpty ifFalse:[Transcript show:'Failed tests: ',failures asArray printString;cr; show:'"1 systemNavigation browseAllImplementorsOfList:', failures asArray printString,' title: ''Failed Tests'' "'] ! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'dmu 9/24/2010 00:17'! run Transcript cr;show:'Starting run.....................'. self tests do:[:test| test printConsole. test run]. Transcript cr;show:'......................Ending run'. self reportResults! ! !RVMTestSuite methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:31'! tests "Answer the value of tests" tests isNil ifTrue:[self tests: OrderedCollection new]. ^ tests! ! !RVMTestSuite methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:31'! tests: anObject "Set the value of tests" tests _ anObject! ! !RVMTestSuite class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:35'! tests: someTests ^self new tests: someTests! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:31'! run "self run" "just run the tests in my own 'testing' message category" ^self tests run! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:45'! runAll "self runAll" "just run all tests in the 'testing' message category of myself and my subclasses" ^self testsWithSubTests run! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:45'! runSubs "self runSubs" "just run all tests in the 'testing' message category of my subclasses" ^self subTests run! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 09:37'! subTests "Answer a test suite built by scanning methods in my subclasses 'tests' categories" | testSelectors tests | tests _ OrderedCollection new. self allSubclassesDo:[:cls| testSelectors _ cls class organization listAtCategoryNamed: 'tests'. tests addAll:(testSelectors collect:[:selector| cls perform: selector])]. ^self tests: tests! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 06:57'! tests "self tests" "Answer a test suite built by scanning methods in my 'tests' category" | testSelectors | testSelectors _ self class organization listAtCategoryNamed: 'tests'. ^self tests: (testSelectors collect:[:selector| self perform: selector])! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 08:29'! testsWithSubTests "Answer a test suite built by scanning methods in my own and my subclasses 'tests' categories" | testSelectors tests | tests _ OrderedCollection new. self withAllSubclassesDo:[:cls| testSelectors _ cls class organization listAtCategoryNamed: 'tests'. tests addAll:(testSelectors collect:[:selector| cls perform: selector])]. ^self tests: tests! ! !RVMTestSuite class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! testFailure "self testFailure run" "A test that will always fail to ensure the system is functioning at a minimum" | theTest | theTest _ RVMTest test:[:test :env| ] asserting:[:test :outcome| false]. theTest name: 'testFailure'. ^theTest! ! !RVMTestSuite class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! testRVMTest ^RVMTest fullExampleTest! ! !RVMTestSuite class methodsFor: 'user interface' stamp: 'ssa 8/31/2009 10:50'! runAllButton "self runAllButton" | topView | topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: 130@30. topView maximumSize: 200@200. topView addSubView: (RVMButtonView label:'Run All Tests' action:[self runAll]). topView label: 'Tester'. topView controller open! ! !RVMTester class methodsFor: 'testing' stamp: 'ssa 9/24/2008 12:40'! changingSuperclassTest "RVMTester changingSuperclassTest" "Create a class, then change its superclass and verify" Transcript cr;show:'Starting changing superclass test......'. #(Foo Bar Baz)do:[:n| Smalltalk removeClassNamed: n]. Object subclass: #Foo instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. Object subclass: #Bar instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. (Smalltalk classNamed:#Foo) subclass: #Baz instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. Transcript cr;show:'Foo, Bar and Baz test classes created, Baz is subclass of Foo, ready to try to change superclass to Bar'. (Smalltalk classNamed:#Bar) subclass: #Baz instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. (Smalltalk classNamed:#Baz) superclass == (Smalltalk classNamed:#Bar) ifTrue:[Transcript cr;show:'Successful....test passed'] ifFalse:[Transcript cr;show:'Nope....test failed']. Transcript cr;show:'Cleaning up....'. #(Foo Bar Baz)do:[:n| Smalltalk removeClassNamed: n]. Transcript cr;show:'...End of changing superclass test'. ! ! !RVMTester class methodsFor: 'testing' stamp: 'dmu 4/1/2009 04:28'! delayTest "RVMTester delayTest" | rect delay | rect _ 0@0 extent: 40@40. delay _ Delay forSeconds: 1. [Sensor leftShiftDown not] whileTrue:[Display reverse: rect. delay wait] ! ! !RVMTester class methodsFor: 'testing' stamp: 'ssa 7/24/2008 15:28'! methodDeletionTest "RVMTester methodDeletionTest" "Create a test class and add 32 methods to it, then try to add 33" | testClassName testClass | testClassName := #RVMTESTforMethodDeletion. (Smalltalk includesKey: testClassName) ifTrue:[(Smalltalk at: testClassName) removeFromSystem]. Object subclass: testClassName instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. testClass := Smalltalk at: testClassName. Transcript cr;cr;show:'Test class created: ',testClassName. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 5 methods'. 1 to: 5 do:[:count| testClass compile: 'testMethod',count printString]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Removing 5 methods'. 1 to: 5 do:[:count| testClass removeSelector: ('testMethod',count printString) asSymbol]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. testClass selectors notEmpty ifTrue:[Transcript cr;show:'Test Failed']ifFalse:[Transcript cr;show:'test passed']. Transcript cr;show:'Removing test class: ',testClassName. testClass removeFromSystem. Transcript cr;show:'test class removed.... test over'. ! ! !RVMTester class methodsFor: 'testing' stamp: 'ssa 7/24/2008 15:23'! methodDictionaryGrowthTest "RVMTester methodDictionaryGrowthTest" "Create a test class and add 32 methods to it, then try to add 33" | testClassName testClass | testClassName := #RVMTESTforMethodDictionaryGrowth. (Smalltalk includesKey: testClassName) ifTrue:[(Smalltalk at: testClassName) removeFromSystem]. Object subclass: testClassName instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. testClass := Smalltalk at: testClassName. Transcript cr;cr;show:'Test class created: ',testClassName. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 32 methods'. 1 to: 32 do:[:count| testClass compile: 'testMethod',count printString]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 33rd method'. testClass compile: 'testMethod33'. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Removing test class: ',testClassName. testClass removeFromSystem. Transcript cr;show:'test class removed.... test over'. ! ! !RVMTester class methodsFor: 'testing' stamp: 'dmu 1/1/2009 04:13'! runParallelCompilerBenchmarks: n "RVMTester runParallelCompilerBenchmarks: 4" n timesRepeat: [[Benchmark new testCompiler. Transcript show: 'done'; cr] copy fixTemps fork]! ! !RVMTester class methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:21'! segmentationFaultTest "RVMTester segmentationFaultTest" "Executing this code produces a segmenation fault" | all singles groups file | Transcript cr;show:'test starting... segmentation fault test... writing to segfaultLog.txt'. file _ FileStream newFileNamed:'segfaultLog.txt'. all _ #(bytecodeCounts bytecodeCountsAverage bytecodesPerCycle bytecodesPerCycles bytecodesPerCyclesAverage bytecodesPerKCs bytecodesPerMCs bytecodesPerMillisecond bytecodesPerMilliseconds bytecodesPerMillisecondsAverage bytecodesPerSecond bytecodesPerSecondAverage bytesUseds contextChangeCounts cyclesRunWaitRatios cyclesRunWaitRatiosAverage cyclesRunnings cyclesRunningsAverage cyclesSinceLasts cyclesSinceLastsAverage cyclesWaitings cyclesWaitingsAverage interruptCheckCounts millisecondsRunnings millisecondsWaitings msRunWaitRatios msRunWaitRatiosAverage msRunningsAverage msSinceLasts msSinceLastsAverage msWaitingsAverage receiveTallySum unforcedInterruptCheckCounts yieldCounts yieldCountsAverage yieldFrequencies yieldsPerSecond yieldsPerSecondAverage). singles _ OrderedCollection new. groups _ OrderedCollection new. all do:[:msg| file nextPutAll:'Attempting ',msg,' '. file flush. ((RVMMonitor lastSample perform: msg) isKindOf:Number)ifTrue:[singles add: msg]ifFalse:[groups add: msg]]. file close. Transcript cr;show:'test passed.... test over'. ! ! !RVMTester class methodsFor: 'testing' stamp: 'dmu 5/4/2009 23:51'! testAtRandom "self testAtRandom" | r n t | r _ Random new. n _ 0. 100000 timesRepeat: [ t _ 396 atRandom: r. n _ n + 1. t isInteger ifFalse: [self error: 'not int']. t < 0 ifTrue: [self error: 'neg' ]. t > 400 ifTrue: [self error: 'too big']. ]! ! !RVMTester class methodsFor: 'testing' stamp: 'dmu 5/5/2009 00:24'! testNextInt "self testAtRandom" | r n t | r _ Random new. n _ 0. 100000 timesRepeat: [ t _ r nextInt: 396. n _ n + 1. t isInteger ifFalse: [self error: 'not int']. t < 0 ifTrue: [self error: 'neg' ]. t > 400 ifTrue: [self error: 'too big']. ]! ! !RVMTester class methodsFor: 'printing' stamp: 'dmu 5/25/2010 10:39'! printPrefixFor: anObject "RVMTester printPrefixFor: Array " "Answer a string to use as a prefix in Inspectors and Debuggers when printing an object" | index readWrite | (anObject isKindOf: SmallInteger) ifTrue:[^'']. (anObject isKindOf: Boolean) ifTrue:[^'']. (anObject isNil) ifTrue:[^'']. index_(RVMTester getCoreHolding: anObject) printString. readWrite_(RVMTester getReadWriteOf: anObject)ifTrue:['rw']ifFalse:['rm']. ^'<',readWrite,index,'> '! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/6/2008 13:10'! allObjectsInHeap: rank isReadWrite: isC "RVMTester allObjectsInHeap: 34 isReadWrite: true" self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 3/22/2010 12:40'! coreCount "RVMTester coreCount" ^ 1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/1/2009 22:17'! coreProcessUtilization "RVMTester coreProcessUtilization" "How many processes are running on my cores versus how many core??" ^self numberOfRunningProcesses / RVMMonitor coreCount! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 11/22/2008 23:43'! enableMultithreading: aBool "RVMTester enableMultithreading: true" self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:01'! extraRemoteContextAllocations: n ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:01'! extraYields: n ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/7/2009 02:53'! getCore "RVMTester getCore" ^ -1! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/16/2008 02:22'! getCoreHolding: anObject ^(self primitivGetCoreHolding: anObject)! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/7/2009 04:49'! getCoreIAmRunningOn "RVMTester getCoreIAmRunningOn" ^ -1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:05'! getCoreTrace ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 6/2/2010 23:13'! getEmergencySemaphore "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "self getEmergencySemaphore signal" ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:03'! getMutatedReplicatedObjectsTrace ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 1/1/1970 00:11'! getPassTheBatonOf: anObject ^ true! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/6/2008 13:11'! getReadWriteOf: anObject ^ true! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/18/2009 18:34'! isRVM "RVMTester isRVM" "Am I actually running on the Tilera64?" ^(self getCoreHolding: nil) ~= -1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/3/2009 03:40'! move: anObject toCore: anInt self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/3/2009 03:40'! move: anObject toCore: anInteger readWritely: readWriteBoolean passTheBaton: batonBoolean self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/6/2008 13:12'! moveAllToReadMostlyHeaps "RVMTester moveAllToReadMostlyHeaps" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:56'! numberOfRunningProcesses ^self runningProcesses size! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/16/2008 02:07'! primitivGetCoreHolding: anObject ^ -1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/1/2009 22:00'! primitiveRunningProcessByCore "Answers an array of numberOfCores size with a nil or Process instance for each core. If a Process instance then that process was running on that core when invoked" "RVMTester primitiveRunningProcessByCore" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 12/7/2008 20:44'! print: aString "RVMTester print: 'hello'" "omit module just as in thisProcess method to hit obsolete_named-primitive_table and be local"! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 11/6/2008 13:13'! printAllHeapsBytesUsed "RVMTester printAllHeapsBytesUsed" ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 10/27/2008 21:07'! printExecutionTrace "RVMTester printExecutionTrace" " [ [ [ RVMTester printExecutionTrace ] value ] value ] value" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 10/27/2008 15:27'! printStack "RVMTester printStack" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:02'! runMask: aMask ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 2/11/2009 06:03'! runOnAll "RVMTester runOnAll" self runOnlyOn: -1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:03'! runOnOne: aBool self runMask: ( aBool ifTrue: [1] ifFalse: [0] )! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 2/11/2009 06:02'! runOnlyOn: anInt "RVMTester runOnlyOn: 0" self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:47'! runningProcessByCore "Answers an array of numberOfCores size with a nil or Process instance for each core. If a Process instance then that process was running on that core when invoked" ^self primitiveRunningProcessByCore! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:48'! runningProcesses "Answers an array of Process instances that were running when invoked" ^self runningProcessByCore select:[:each| each notNil]! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 5/25/2010 10:42'! setCoordinatesOf: anObject toCore: anInt readWrite: aBool "RVMTester setCoordinatesOf: 3@4 toCore: 17 readWrite: false " self primitiveFailed ! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 1/1/1970 00:25'! setCoordinatesOf: anObject toCore: anInt readWrite: aBool passTheBaton: anotherBool "RVMTester setCoordinatesOf: 3@4 toCore: 17 readWrite: false passTheBaton: false" self primitiveFailed ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:00'! setCoreTraceSize: n ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 6/2/2010 23:10'! setEmergencySemaphore: aSemaOrNil "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" ! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:06'! setMutatedReplicatedObjectsTraceSize: n ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:40'! shuffle: numCores ^ self shuffleFrom: 0 to: numCores - 1! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:39'! shuffleFrom: first to: last ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 11/1/2008 06:12'! shuffleFrom: first to: last moveRWtoRM: bool1 moveRMtoRW: bool2 "RVMTester shuffleFrom: 1 to: 17 moveRWtoRM: false moveRMtoRW: true" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 2/11/2009 06:04'! soleRunningCore "RVMTester soleRunningCore" self primitiveFailed! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 4/2/2009 00:34'! spreadFrom: first to: last moveRWtoRM: bool1 moveRMtoRW: bool2 "RVMTester spreadFrom: 1 to: 17 moveRWtoRM: true moveRMtoRW: false" ^ self primitiveFailed! ! !RVMTester class methodsFor: 'as yet unclassified' stamp: 'dmu 1/1/1970 00:50'! randomWalk "RVMTester randomWalk" [ [Sensor leftShiftDown not] whileTrue: [ Delay forMilliseconds: 250. RVMTester move: false toCore: ( 0 max: (55 min: ( self getCoreHolding: false) + 3 atRandom - 2)) ]. Transcript show: 'killed'; cr ] fork. ! ! !RVMTester class methodsFor: 'teleportation' stamp: 'ssa 11/4/2008 23:39'! isMulticoreCoordinate: stringOrSymbol "Answer true if my unary selector matched the special multicore object coordinate format. {rm,rw}{Pass,Hold}{coreIndex, 0-55}" | readWrite baton coreIndex aSymbol | aSymbol _ stringOrSymbol asSymbol. aSymbol isUnary ifFalse:[^false]. aSymbol size >= 7 ifFalse:[^false]. readWrite _ aSymbol first: 2. (#('rw' 'rm') includes: readWrite) ifFalse:[^false]. baton _ aSymbol copyFrom: 3 to: 6. (#('Pass' 'Hold') includes: baton) ifFalse:[^false]. coreIndex _ aSymbol allButFirst:6. (coreIndex isAllDigits and:[(coreIndex _ coreIndex asNumber) between: 0 and: 55]) ifFalse:[^false]. ^true ! ! !RVMTester class methodsFor: 'teleportation' stamp: 'ssa 11/16/2008 01:00'! teleport: anObject to: aSymbol "move this object to this multicore object coordinate. aSymbol := {in,co}{Pass,Hold}{coreIndex, 1-56}" | readWrite baton coreIndex old new | (self isMulticoreCoordinate: aSymbol) ifFalse:[self error:'Teleport aborted; bad coordinates = ',aSymbol]. readWrite _ (aSymbol first: 2) = 'rw'. baton _ (aSymbol copyFrom: 3 to: 6) = 'Pass'. coreIndex _ (aSymbol allButFirst:6) asNumber - 1 max: 0. old _ self printPrefixFor: anObject. self move: anObject toCore: coreIndex readWritely: readWrite passTheBaton: baton. Sensor leftShiftDown ifTrue:[new _ self printPrefixFor: anObject. Transcript cr;show:'Zzzoingggg!! ',anObject printString,' vanished from ',old. Transcript cr;show:'Ggggniozzz!! ',anObject printString,' appeared at ',new]. ! ! !RVMTester class methodsFor: 'demos' stamp: 'ssa 10/10/2008 19:27'! colorTrail "RVMTester colorTrail" | rect boxes centers count colors pen x y coreIndex | rect _ Rectangle fromUser. boxes _ rect subDivideBy: 8@8. centers _ boxes collect:[:box| box center]. count _ 500. colors _ Color hotColdShades:count. pen _ Pen new. pen defaultNib:6. pen combinationRule: Form paint. pen place: (centers at:32). x _ y _ 4. pen down. 1 to:count do:[:index|pen color: (colors at: index). x _ (x + (3 atRandom - 2))min:8 max:1. y _ (y + (3 atRandom - 2))min:8 max:1. coreIndex _ y - 1 * 8 + x. pen goto: (centers at:(coreIndex))]! ! !RVMTester class methodsFor: 'demos' stamp: 'ssa 10/6/2008 11:20'! displayImageOnReadMostlyStripChart "RVMTester displayImageOnReadMostlyStripChart" "Works on readMostlyHeap tile strip chart" | f text images height width pixelOn | f _ Form fromDisplay:(0@0 extent: 200@200).. text _ 'IBM' asDisplayText asParagraph asForm magnifyBy:2. "logo _ GIFReadWriter formFromFileNamed: 'ibm-logo-bw.gif'. logo replaceColor: Color white with: Color transparent. face _ GIFReadWriter formFromFileNamed: 'sam-photo-bw.gif'. face replaceColor: Color white with: Color transparent." images _ OrderedCollection new. "images add: logo. images add: face." images add: text. images do:[:image| height _ image boundingBox height. width _ image boundingBox width. 0 to: width -1 do:[:x| 0 to: height - 1 do:[:y| pixelOn _ (image colorAt: x@y) isTransparent. RVMTester move: f copy toCore: y + 3 readWritely: pixelOn passTheBaton: true. ]. RVMTester move: f toCore: 1 readWritely: true passTheBaton: true.. RVMMonitor getSample;informListeners. Smalltalk garbageCollect. ]] ! ! !RVMTester class methodsFor: 'demos' stamp: 'ssa 11/4/2008 23:39'! spockToursTheRenaissance "RVMTester spockToursTheRenaissance" 'Spock' rwPass24 rmHold2 rmPass40 rwHold0 rwPass55 ! ! !RVMTester class methodsFor: 'filing out ' stamp: 'ssa 10/8/2008 16:49'! fileOutAllRVMCategories "RVMTester fileOutAllRVMCategories" | cats classNames classes orderedClasses fileStream | cats := SystemOrganization categoriesMatching: 'RVM-*'. classNames := OrderedCollection new. cats do: [:cat | classNames addAll: (SystemOrganization listAtCategoryNamed: cat)]. classes := classNames collect: [:n | Smalltalk at: n]. orderedClasses := ChangeSet superclassOrder: classes. fileStream := FileStream fileNamed: 'all-RVM-categories ' , Time now print24 , ' ' , (Date today printFormat: #(2 1 3 $- 1 2 2 )) , '.st'. orderedClasses do: [:cls | cls fileOutOn: fileStream]. fileStream close! ! !RVMTester class methodsFor: 'testing for RVM' stamp: 'dmu 4/10/2009 22:44'! positiveIfOnRVM "RVMTester positiveIfOnRVM" ^ -1! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:22'! browseAspectsForCore: coreIndex self view okToDisplay:true. RVMCoreAspectTrace monitorAllCoreAspectsForCore: coreIndex! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:29'! browseThisAspectForAllCores: coreIndex self view okToDisplay:true. RVMTileStripChartView openOnAspect: self view aspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:24'! browseThisAspectForCore: coreIndex self view okToDisplay:true. RVMCoreAspectTrace monitorAspects: (Array with: self view aspect) forCore: coreIndex! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 10/4/2008 08:36'! changeAspect: coreIndex | menu answer | menu := CustomMenu new. self view sample aspects do: [:aspect | menu add: aspect action: aspect]. answer := menu startUp: self view aspect withCaption: 'Select the aspect to monitor'. self view topView okToDisplay:true. answer isNil ifTrue:[^self]. self view aspect: answer. self view topView allSubViews do:[:each| each hear: nil]. self view displayView! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:12'! doMessageTallyOfDisplayView self view topView okToDisplay:true. MessageTally spyOn:[100 timesRepeat:[view displayView]] ! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:12'! inspectDataValues: coreIndex self view topView okToDisplay:true. self view data inspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 02:00'! inspectView:coreIndex self view okToDisplay:true. self view inspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:02'! scalerForThisAspect: coreIndex self view okToDisplay:true. RVMColoredDataScalerView openOnAspect: self view aspect! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 13:10'! coreIndexAt: aPoint | box | 1 to: self view tiles size do:[:index| box _ self view tiles at: index. ( box containsPoint: aPoint) ifTrue:[^index]]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:55'! redButtonActivity | delay | ["Color showColors: self view colors. " ^self ]value. Cursor move show. Sensor waitNoButton. Cursor normal show. self process isNil ifTrue: [ self view showProcessOn. self process: [[((self view displayBox containsPoint: Sensor cursorPoint) & Sensor redButtonPressed) or:[Sensor leftShiftDown & Sensor controlKeyPressed]] whileFalse: [ delay := Delay forMilliseconds: 1 * (Time millisecondsToRun: [self view displayView]). delay wait]]. self process fork] ifFalse: [self stopDisplayProcess]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'dmu 1/1/1970 00:08'! stopDisplayProcess self process terminate. self view showProcessOff. self view displayView. self process: nil! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:11'! yellowButtonActivity | menu answer coreIndex | coreIndex _ self coreIndexAt: Sensor cursorPoint. self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := self yellowButtonMenu. answer := menu startUp: nil withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer with: coreIndex]]]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 01:59'! yellowButtonMenu | menu coreIndex | coreIndex _ self coreIndexAt: Sensor cursorPoint. menu := CustomMenu new. menu add: 'change aspect' action: #changeAspect:. menu add: ' stripchart all aspects for core #',coreIndex printString action: #browseAspectsForCore:. menu add: 'stripchart this aspect for core #',coreIndex printString action: #browseThisAspectForCore:. menu add: 'stripchart this aspect for all cores' action: #browseThisAspectForAllCores:. menu add: 'adjust scale for this aspect' action: #scalerForThisAspect:. menu add: 'current data values' action: #inspectDataValues:. menu add: 'inspect view' action: #inspectView:. ^menu ! ! !RVMTileGridController methodsFor: 'accessing' stamp: 'ssa 8/15/2008 20:14'! process "Answer the value of process" process isNil ifTrue:[self process: nil]. ^process! ! !RVMTileGridController methodsFor: 'accessing' stamp: 'ssa 8/15/2008 20:14'! process: anObject "Set the value of process" process := anObject! ! !RVMTileGridController methodsFor: 'initialize-release' stamp: 'ssa 8/15/2008 20:21'! release self process notNil ifTrue:[self process terminate]. super release! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 15:14'! eraseStrip: coreIndex self view eraseStrip! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 01:40'! redraw: coreIndex self view okToDisplay: true. self view redrawOnCanvas. self view displayView! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/3/2008 21:43'! rescale: coreIndex self view okToDisplay: true. self view rescale. self view displayView! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/3/2008 21:27'! yellowButtonMenu | menu | menu _ super yellowButtonMenu. menu add: 'erase strip' action: #eraseStrip:. menu add: 'redraw' action: #redraw:. menu add: 'rescale' action: #rescale:. ^menu! ! !RVMTileStripChartController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 16:20'! coreIndexAt: aPoint | p | p _ aPoint y - self view insetDisplayBox origin y // self view boxSize. ^p max:1! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:51'! adjustCursor "Show the appropriate arrow cursor" (Sensor cursorPoint x - self view insetDisplayBox center x )> 0 ifTrue:[Cursor up show] ifFalse:[Cursor down show]. ! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:50'! controlActivity "Show the appropriate arrow cursor, then default to other controlActivity" self adjustCursor. super controlActivity! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:34'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:49'! redButtonActivity | point center delta sign delay | center _ self view insetDisplayBox center. delay _ Delay forMilliseconds: 100. [Sensor redButtonPressed] whileTrue: [self adjustCursor. point := Sensor cursorPoint. delta _ (point x - center x). sign _ delta < 0 ifTrue:[-1]ifFalse:[1]. delta _ delta abs max:1. delta >10 ifFalse:[delta _ 1]. self view changeValueBy: (delta * sign). delay wait]! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:15'! yellowButtonActivity | result | self view dontDisplayWhile:[ result _ FillInTheBlank request: 'Enter the new value' initialAnswer: self view value printString. result notNil ifTrue:[self view value: (Compiler evaluate: result). self view displayView] ]! ! !RVMValueEditorController methodsFor: 'controller access' stamp: 'ssa 10/29/2008 21:32'! defaultControllerClass ^RVMValueEditorController! ! !RVMValueEditorController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 20:47'! redButtonActivity | p wait delay | delay _ Delay forMilliseconds: 100. wait _ [Sensor leftShiftDown ifFalse:[Sensor waitNoButton] ifTrue:[delay wait]]. p _ Sensor cursorPoint - self view insetDisplayBox origin. (self view lockBox containsPoint: p) ifTrue:[self view locked: self view locked not. self view displayView. ^Sensor waitNoButton.]. (self view oneBox containsPoint: p) ifTrue:[self view performOperationWith: 1. ^wait value]. (self view tenBox containsPoint: p) ifTrue:[self view performOperationWith: 10. ^wait value]. (self view hundredBox containsPoint: p) ifTrue:[self view performOperationWith: 100. ^wait value]. (self view zeroBox containsPoint: p) ifTrue:[^self view resetValueToZero]. self view operations with: self view operationBoxes do:[:op :bx| (bx containsPoint: p) ifTrue:[self view operation: op. ^self view displayView]]! ! !RVMValueEditorController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 19:35'! yellowButtonActivity | result | self view topView dontDisplayWhile:[ result _ FillInTheBlank request: 'Enter the new value' initialAnswer: self view value printString. result notNil ifTrue:[self view value: (Compiler evaluate: result). self view displayView] ]! ! !RVMView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:16'! dontDisplayWhile: aBlock "Switch my okToDisplay flag off during this block" self okToDisplay: false. aBlock value. self okToDisplay: true. self displayView! ! !RVMView methodsFor: 'updating' stamp: 'ssa 10/7/2008 21:55'! firstFrame "A signal from my topView that I have been reframed. Default is to do nothing but propagate the signal. Subclasses will override to react appropriately" self subViews do:[:each| each firstFrame]! ! !RVMView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:12'! newFrame "A signal from my topView that I have been reframed. Default is to do nothing but propagate the signal. Subclasses will override to react appropriately" self subViews do:[:each| each newFrame]! ! !RVMView methodsFor: 'updating' stamp: 'ssa 10/21/2008 11:31'! uncache (self topView isKindOf: StandardSystemView) ifTrue:[self topView uncacheBits]! ! !RVMView methodsFor: 'initialize-release' stamp: 'ssa 10/3/2008 23:24'! initialize super initialize. self backgroundColor: Color white. RVMMonitor inform: self! ! !RVMView methodsFor: 'initialize-release' stamp: 'ssa 1/1/1970 00:07'! release RVMMonitor forget: self. super release. ! ! !RVMView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:34'! hear: aSpeaker "Some object I am listening to is speaking" ! ! !RVMView methodsFor: 'demonstrating' stamp: 'ssa 11/15/2008 15:43'! demo "Add me to a system view and open me on the desktop" self demoSized: self minimumSize! ! !RVMView methodsFor: 'demonstrating' stamp: 'ssa 11/15/2008 15:42'! demoSized: anExtent "Add me to a system view and open me on the desktop" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: anExtent. topView addSubView: self . topView label: self class name,' demo'. topView controller open! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:24'! controller: aController super controller: aController. aController isNil ifTrue:[self okToDisplay: false]! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 15:44'! minimumSize ^100@100! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:15'! okToDisplay "Answer the value of okToDisplay" okToDisplay isNil ifTrue:[self okToDisplay: false]. ^ okToDisplay ! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! okToDisplay: aBoolean "Set the value of okToDisplay" okToDisplay _ aBoolean. self subViews do:[:v| v okToDisplay: aBoolean]! ! !RVMView methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:19'! isRVMView ^true! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:19'! displayAction "Let the controller indicate action available" self displayLabel. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 16:03'! displayLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: Color white. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 03:09'! displayLabelDark | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: self baseColorDark. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form erase fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:22'! displayOutline self displayLabel. Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: Color black.! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 03:02'! displayPressed self displayLabelDark. Display border: (self insetDisplayBox insetBy: 0@0) width:2 fillColor: self baseColor. Display border: (self insetDisplayBox insetBy: 2@2) width:2 fillColor: self baseColor darker. Display border: (self insetDisplayBox insetBy: 4@4) width:2 fillColor: self baseColor darker darker. Display border: (self insetDisplayBox insetBy: 6@6) width:2 fillColor: self baseColor darker darker darker. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 17:07'! displayRaisedGray self displayRaisedWhiteLabel. self displayRaisedLabel. Display border: (self insetDisplayBox insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (self insetDisplayBox insetBy: 0@0) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (self insetDisplayBox insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (self insetDisplayBox insetBy: 1@1) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker. Display border: (self insetDisplayBox insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter lighter. Display border: (self insetDisplayBox insetBy: 2@2) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker. Display border: (self insetDisplayBox insetBy: 3@3) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (self insetDisplayBox insetBy: 3@3) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor . ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 2/22/2010 15:34'! displayRaisedLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. "Display fill: self insetDisplayBox fillColor: self baseColor." labelForm displayOn: Display at: labelRect center - labelForm boundingBox center - (0@3)clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 2/22/2010 15:37'! displayRaisedWhiteLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: self baseColor lighter lighter backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: self baseColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center - (0@3)+(1@1)clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:15'! displayView self style == #raisedGray ifTrue:[self displayRaisedGray]. self style == #outline ifTrue:[self displayOutline]. self style == #action ifTrue:[self displayAction]. ! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! action "Answer the value of action, a block to execute when the button is released" action isNil ifTrue:[self action: [self inform:'no action defined yet']]. ^ action! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! action: anObject "Set the value of action" action _ anObject! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 02:47'! baseColor ^Color gray lighter lighter lighter! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:02'! baseColorDark ^Color gray ! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:42'! label "Answer the value of label" label isNil ifTrue:[self label: 'not labeled yet']. ^ label! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! label: anObject "Set the value of label" label _ anObject! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:14'! style "Answer the value of style. how I should display myself. Current options are #raisedGray, #outline, #action" style isNil ifTrue:[self style: #raisedGray]. ^ style! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:13'! style: anObject "Set the value of style" style _ anObject! ! !RVMButtonView methodsFor: 'actions' stamp: 'ssa 1/1/1970 00:10'! performAction self action copy value! ! !RVMButtonView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:25'! defaultControllerClass ^RVMButtonController! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:27'! example "RVMButtonView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'Flash' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 02:59'! exampleGC "RVMButtonView exampleGC" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'GC' action:[Smalltalk garbageCollect print]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:43'! exampleLong "RVMButtonView exampleLong" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'Flash the display by reversing twice' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 01:43'! exampleTall "RVMButtonView exampleTall" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:' Flash the display by reversing twice' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! label: aString action: aBlock | v | v _ self new. v label: aString. v action: aBlock. ^v ! ! !RVMButtonView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:21'! label: aString style: aSymbol action: aBlock | v | v _ self new. v label: aString. v style: aSymbol. v action: aBlock. ^v ! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:10'! drawCanvas "This is the main drawing method. Subclasses will override to do their own drawing" self marker destForm: self canvas. self drawCross! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:10'! drawCross | box | box _ self canvas boundingBox. self drawLineFrom: box topLeft to: box bottomRight color: Color blue. self drawLineFrom: box topRight to: box bottomLeft color: Color red. ! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:22'! drawLineFrom: beginPoint to: endPoint color: aColor "Draw a line on the canvas in canvas coordinates" Marker color: aColor; place: beginPoint; goto: endPoint! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:33'! eraseCanvas self canvas fillWhite! ! !RVMCanvasView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:29'! defaultControllerClass ^RVMCanvasController! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:23'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self extent - (0@2) depth: Display depth). self drawCanvas]. ^ canvas! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:25'! defaultOffset ^0@0! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! dirty "Answer the value of dirty" dirty isNil ifTrue:[self dirty: true]. ^ dirty! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! dirty: anObject "Set the value of dirty" dirty _ anObject! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:32'! extent "Answer the value of extent" extent isNil ifTrue:[self extent: self insetDisplayBox extent]. ^ extent! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:40'! extent: aPoint "Set the value of extent" extent _ aPoint ! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! marker ^self class marker! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:25'! offset "Answer the value of offset" offset isNil ifTrue:[self offset: self defaultOffset]. ^ offset! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:31'! offset: aPoint "Set the value of offset" offset _ aPoint min: 0@0 max: self insetDisplayBox extent - self canvas extent! ! !RVMCanvasView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin + self offset clippingBox: self insetDisplayBox. ! ! !RVMCanvasView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:30'! newFrame "My frame has changed. Default is to do nothing special"! ! !RVMCanvasView class methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:20'! marker "Answer the default form to draw with, a 1 pixel black dot." Marker isNil ifTrue:[Marker _ Pen new. Marker defaultNib:1]. ^Marker! ! !RVMCanvasView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:13'! example "RVMCanvasView example" | topView | topView _ StandardSystemView new. topView label:'CanvasView test'. topView minimumSize: 200@200. topView borderWidth:2. topView addSubView: self new. topView controller open! ! !RVMCanvasView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:17'! example2 "RVMCanvasView example2" | topView view | topView _ RVMStandardSystemView new. topView label:'CanvasView test'. topView minimumSize: 200@50. topView borderWidth:2. view _ self new. view extent: 500@50. topView addSubView: view. topView controller open! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 10/19/2008 00:43'! hear: aSpeaker "Some object I am listening to is speaking" self checked:nil. self displayView! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:44'! performAction "I've been clicked, switch state and act" self checked ifTrue:[self performUncheckAction]ifFalse:[self performCheckAction]. self checked: nil. self displayView! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:46'! performCheckAction self checkAction isSymbol ifTrue:[self model perform: self checkAction] ifFalse:[self checkAction value]! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:46'! performUncheckAction self uncheckAction isSymbol ifTrue:[self model perform: self uncheckAction] ifFalse:[self uncheckAction value]! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 10/19/2008 00:56'! update: aSelector super update: aSelector. self checked: nil. self displayView! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 2/22/2010 15:39'! baseColor ^Color gray lighter lighter lighter! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:16'! checkAction "Answer the value of checkAction" checkAction isNil ifTrue:[self checkAction: [self inform:'box just checked']]. ^ checkAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! checkAction: anObject "Set the value of checkAction" checkAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:12'! checkBoxForm "Answer the value of checkBoxForm" ^self checkState ifTrue:[self checkedBoxForm]ifFalse:[self uncheckedBoxForm]! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:43'! checkState "Answer the value of checked the state of my checkbox" ^self checkStateAction isSymbol ifTrue:[self model perform: self checkStateAction] ifFalse:[self checkStateAction value]! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:19'! checkStateAction "Answer the value of checkStateAction" checkStateAction isNil ifTrue:[self checkStateAction: [false]]. ^ checkStateAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:18'! checkStateAction: anObject "Set the value of checkStateAction" checkStateAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:42'! checked "Answer the value of checked the state of my checkbox" checked isNil ifTrue:[self checked: self checkState]. ^ checked! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! checked: anObject "Set the value of checked" checked _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! checkedBoxForm "Answer the value of checkedBoxForm" checkedBoxForm isNil ifTrue:[self checkedBoxForm: self buildCheckedBoxForm]. ^ checkedBoxForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! checkedBoxForm: anObject "Set the value of checkedBoxForm" checkedBoxForm _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:17'! label "Answer the value of label" label isNil ifTrue:[self label: 'no label yet']. ^ label! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! label: anObject "Set the value of label" label _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:03'! labelForm "Answer the value of labelForm" labelForm isNil ifTrue:[self labelForm: self buildLabelForm]. ^ labelForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:03'! labelForm: anObject "Set the value of labelForm" labelForm _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:17'! uncheckAction "Answer the value of uncheckAction" uncheckAction isNil ifTrue:[self uncheckAction: [self inform:'box just UNchecked']]. ^ uncheckAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! uncheckAction: anObject "Set the value of uncheckAction" uncheckAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:10'! uncheckedBoxForm "Answer the value of uncheckedBoxForm" uncheckedBoxForm isNil ifTrue:[self uncheckedBoxForm: self buildUncheckedBoxForm]. ^ uncheckedBoxForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! uncheckedBoxForm: anObject "Set the value of uncheckedBoxForm" uncheckedBoxForm _ anObject! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:40'! buildCheckedBoxForm "Answer the check(ed) box " | box marker | box _ Form extent: 15@15 depth: Display depth . box fillColor: self baseColor lighter lighter. box border: box boundingBox width:1 fillColor: Color black. marker _ Form extent:2@2. marker fillColor: Color black. box drawLine: marker from: box boundingBox origin to: box boundingBox corner clippingBox: box boundingBox rule: Form over fillColor: nil. box drawLine: marker from: box boundingBox topRight - (2@0) to: box boundingBox bottomLeft - (2@0) clippingBox: box boundingBox rule: Form over fillColor: nil. ^box! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:01'! buildLabelForm "Answer the label form" | labelText | labelText := (' ',self label ) asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. ^labelText "asParagraph asForm" ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:40'! buildUncheckedBoxForm "Answer the uncheck(ed) box" | box | box _ Form extent: 15@15 depth: Display depth . box fillColor:self baseColor lighter lighter. box border: box boundingBox width:1 fillColor: Color black. ^box! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:34'! buildUnderLabelForm "Answer the under label form" | labelText | labelText := (' ',self label ) asDisplayText . labelText foregroundColor: self baseColor lighter lighter backgroundColor: Color transparent. ^labelText "asParagraph asForm" ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:39'! displayContents | box theLabelForm theCheckBoxForm underLabelForm | theCheckBoxForm _ self checkBoxForm. theLabelForm _ self buildLabelForm. underLabelForm _ self buildUnderLabelForm. box _ 0@0 extent: theCheckBoxForm width + theLabelForm width @ (theCheckBoxForm height max: theLabelForm height). box _ box align: box leftCenter with: self insetDisplayBox leftCenter + (4@1). Display fill: self insetDisplayBox fillColor: self baseColor. theCheckBoxForm displayOn: Display at: box origin clippingBox: self insetDisplayBox rule: Form over fillColor:nil. underLabelForm displayOn: Display at: box origin + (theCheckBoxForm width@-2)+(1@1) clippingBox: self insetDisplayBox rule: Form over fillColor:nil. theLabelForm displayOn: Display at: box origin + (theCheckBoxForm width@-2) clippingBox: self insetDisplayBox rule: Form over fillColor:nil. ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 04:10'! displayPressed self displayContents. Display border:( self insetDisplayBox insetBy: 2@2) width: 2 fillColor: Color gray! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 11/15/2008 15:49'! displayView self okToDisplay ifFalse:[^self]. self uncache. self displayContents! ! !RVMCheckBoxView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 03:21'! defaultControllerClass ^RVMCheckBoxController! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 5/4/2010 15:36'! checkBoxForm "Answer the check(ed) box based on the current state " ^self checkBoxFormX! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 5/4/2010 15:36'! checkBoxFormNotCircle "Answer the check(ed) box based on the current state " ^self checked ifTrue:[self clearCircle]ifFalse:[self notSign]! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:05'! checkBoxFormOnOff "Answer the check(ed) box based on the current state " | msg msgText | msg _ self checked ifTrue:[ 'O N'] ifFalse:['O F F']. msgText _ msg asDisplayText. ^msgText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: msgText boundingBox extent). ! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:56'! checkBoxFormX "Answer the check(ed) box based on the current state " | box marker | box _ Form extent: self insetDisplayBox width asPoint depth: Display depth. "box border: box boundingBox width:2 fillColor: Color gray." self checked ifFalse:[^box]. "box fill: (box boundingBox insetBy: 2) fillColor: Color gray lighter lighter." marker _ Form extent:2@2 depth: Display depth. marker fillColor: Color gray. box drawLine: marker from: box boundingBox origin to: box boundingBox corner clippingBox: box boundingBox rule: Form over fillColor: nil. box drawLine: marker from: box boundingBox topRight - (2@0) to: box boundingBox bottomLeft - (2@0) clippingBox: box boundingBox rule: Form over fillColor: nil. ^box! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! checkedCircle ^Form extent: 10@10 depth: 1 fromArray: #( 1056964608 1635778560 3250585600 2185232384 2185232384 2487222272 2285895680 3368026112 1635778560 1056964608) offset: 0@0! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! clearCircle ^ Form extent: 10 @ 10 depth: 1 fromArray: #(1056964608 1635778560 3233808384 2151677952 2151677952 2151677952 2151677952 3233808384 1635778560 1056964608 ) offset: 0 @0! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 11/11/2008 22:42'! displayContents | checkBoxForm box | self okToDisplay ifFalse:[^self]. checkBoxForm _ self checkBoxForm. checkBoxForm _ checkBoxForm scaledToSize:(self insetDisplayBox extent min: checkBoxForm boundingBox extent). box _ checkBoxForm boundingBox. box _ box align: box center with: self insetDisplayBox center. Display fill: self insetDisplayBox fillColor: Color white. checkBoxForm displayOn: Display at: box origin ! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! notSign ^Form extent: 10@10 depth: 1 fromArray: #( 1056964608 1635778560 3250585600 2202009600 2252341248 2353004544 2554331136 4039114752 1635778560 1056964608) offset: 0@0! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 11/13/2008 10:05'! example "RVMCheckBoxView example" "Note we are using this class as a test model for this method. See examplePoint for a more normal usage" | topView | topView := RVMStandardSystemView new. self testState: true. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@200. topView addSubView: (self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]). topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 05:23'! examplePoint "RVMCheckBoxView examplePoint" | topView model | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@200. model _ 0@0. topView addSubView: (self on: model label: 'test' checkState: [model x = 1] whenChecked: [model x: 1] whenUnchecked: [model x:0]). topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 05:24'! exampleTwin "RVMCheckBoxView exampleTwin" "Note we are using this class as a test model for this method. See examplePoint for a more normal usage" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@50. topView maximumSize: 200@200. topView addSubView: (v _ self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]). topView addSubView: (self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]) below: v. topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:22'! on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock ^self on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock monitor: false! ! !RVMCheckBoxView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:21'! on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock monitor: updateFromRVMMonitor | v | v _ self new. v model: aModel. v label: aString. v checkStateAction: getterBlock. v checkAction: checkedBlock. v uncheckAction: uncheckedBlock. updateFromRVMMonitor ifTrue:[RVMMonitor inform: v]. ^v! ! !RVMCheckBoxView class methodsFor: 'testing' stamp: 'ssa 1/1/1970 04:22'! testState TestState isNil ifTrue:[TestState _ true]. ^TestState! ! !RVMCheckBoxView class methodsFor: 'testing' stamp: 'ssa 1/1/1970 04:25'! testState: aValue TestState _ aValue. self changed:#testState! ! !RVMColorButtonView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 15:58'! defaultControllerClass ^RVMColorButtonController! ! !RVMColorButtonView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView self uncache. Display fill: self insetDisplayBox fillColor: self color. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self color negated."! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:29'! color "Answer the value of color" color isNil ifTrue:[color_(self colorSetter isSymbol ifTrue:[model perform: self colorGetter] ifFalse:[self colorGetter value])]. ^ color! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:05'! color: anObject "Set the value of color" color _ anObject. self colorSetter isSymbol ifTrue:[model perform: self colorSetter with: anObject] ifFalse:[self colorSetter value: anObject]! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:21'! colorGetter "Answer the value of colorGetter" colorGetter isNil ifTrue:[self colorGetter: #color]. ^ colorGetter! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:20'! colorGetter: anObject "Set the value of colorGetter" colorGetter _ anObject! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:21'! colorSetter "Answer the value of colorSetter" colorSetter isNil ifTrue:[self colorSetter: #color:]. ^ colorSetter! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:20'! colorSetter: anObject "Set the value of colorSetter" colorSetter _ anObject! ! !RVMColorButtonView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 22:03'! example "RVMColorButtonView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@50. topView maximumSize: 100@100. topView addSubView: self exampleInstance. topView label: 'ColorButton'. topView controller open! ! !RVMColorButtonView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:58'! exampleInstance ^self on: nil colorGetter:[Color random] colorSetter:[:color| color print]! ! !RVMColorButtonView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:57'! on: aModel colorGetter: getterSelector colorSetter: setterSelector | view | view _ self new. view model: aModel. view colorGetter: getterSelector. view colorSetter: setterSelector. ^view! ! !RVMColorScaleView methodsFor: 'controller access' stamp: 'ssa 11/4/2008 14:28'! defaultControllerClass ^RVMColorScaleController! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 14:26'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 14:25'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:42'! aspect ^self aspectSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/9/2008 11:42'! aspectLabel "Answer the value of aspectLabel" aspectLabel isNil ifTrue:[self aspectLabel: (Form extent: 1@1)]. ^ aspectLabel! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 19:13'! aspectLabel: anObject "Set the value of aspectLabel" aspectLabel _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:42'! aspectSource "Answer the value of aspectSource" aspectSource isNil ifTrue:[self aspectSource: [#bytesUseds]]. ^ aspectSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:41'! aspectSource: anObject "Set the value of aspectSource" aspectSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:26'! colors ^self colorsSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:25'! colorsSource "Answer the value of colorsSource" colorsSource isNil ifTrue:[self colorsSource: [Color hotColdShades: 25]]. ^ colorsSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:25'! colorsSource: anObject "Set the value of colorsSource" colorsSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! horizontal self orientation:#horizontal! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:27'! orientation "Answer the value of orientation" orientation isNil ifTrue:[self orientation: #vertical]. ^ orientation! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:30'! orientation: anObject "Set the value of orientation" orientation _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:20'! scaler ^self scalerSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:19'! scalerSource "Answer the value of scalerSource" scalerSource isNil ifTrue:[self scalerSource: [RVMDataScaler exampleInstance]]. ^ scalerSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:19'! scalerSource: anObject "Set the value of scalerSource" scalerSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:11'! usesScaler "Answer the value of usesScaler" usesScaler isNil ifTrue:[self usesScaler: false]. ^ usesScaler! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:11'! usesScaler: anObject "Set the value of usesScaler" usesScaler _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! vertical self orientation:#vertical! ! !RVMColorScaleView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:55'! hear: something self drawFastCanvas. self displayView! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 13:44'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 14:14'! adjustScaleIconHorizontal ^((ColorForm extent: 31@16 depth: 8 fromArray: #( 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967040 4280755235 606282787 606282787 606282787 606282787 606282787 606282787 606600960 4280615169 16843009 16843009 16843009 16843009 16843009 16843009 19201792 4279173377 320014867 269488906 319427073 303237651 318837002 320014864 17760000 4280615169 4294967295 387186687 4294909697 251658239 4278852095 4294967050 19201792 4280615184 4294967295 4294967295 4294909713 251658239 4294967295 4294967050 19136256 4280615169 4294967295 4294967295 4294967295 4294967295 4294967295 4294967050 19201792 4280753933 4294967295 4294967295 4294967295 4294967295 4294967295 4294967072 522649344 4294967295 4294967295 4294967295 603979775 4294905615 4294967295 4294967295 4294967040 4294967295 4294967295 4280556050 251658239 4294911764 371261439 4294967295 4294967040 4294967295 4294967077 419496203 4294967295 4294967054 16847630 4294967295 4294967040 4294967295 4294909706 16843024 286331153 286331153 16843024 420478975 4294967040 4294967295 4294905368 268501267 202116108 202116120 16843028 505806847 4294967040 4294967295 4294967295 253100305 654311423 4294967043 17440767 4294967295 4294967040 4294967295 4294967295 4294910490 536870911 4294905623 505872383 4294967295 4294967040 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967040) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.0 0.0 0.0) #(1.0 1.0 1.0) #(0.5 0.5 0.5) #(1.0 0.0 0.0) #(0.0 1.0 0.0) #(0.0 0.0 1.0) #(0.0 1.0 1.0) #(1.0 1.0 0.0) #(1.0 0.0 1.0) #(0.125 0.125 0.125) #(0.25 0.25 0.25) #(0.375 0.375 0.375) #(0.625 0.625 0.625) #(0.75 0.75 0.75) #(0.875 0.875 0.875) #(0.031 0.031 0.031) #(0.063 0.063 0.063) #(0.094 0.094 0.094) #(0.156 0.156 0.156) #(0.188 0.188 0.188) #(0.219 0.219 0.219) #(0.282 0.282 0.282) #(0.313 0.313 0.313) #(0.344 0.344 0.344) #(0.407 0.407 0.407) #(0.438 0.438 0.438) #(0.469 0.469 0.469) #(0.531 0.531 0.531) #(0.562 0.562 0.562) #(0.593 0.593 0.593) #(0.656 0.656 0.656) #(0.687 0.687 0.687) #(0.718 0.718 0.718) #(0.781 0.781 0.781) #(0.812 0.812 0.812) #(0.844 0.844 0.844) #(0.906 0.906 0.906) #(0.937 0.937 0.937) #(0.969 0.969 0.969) #(0.0 0.0 0.0) #(0.0 0.199 0.0) #(0.0 0.4 0.0) #(0.0 0.599 0.0) #(0.0 0.8 0.0) #(0.0 1.0 0.0) #(0.0 0.0 0.199) #(0.0 0.199 0.199) #(0.0 0.4 0.199) #(0.0 0.599 0.199) #(0.0 0.8 0.199) #(0.0 1.0 0.199) #(0.0 0.0 0.4) #(0.0 0.199 0.4) #(0.0 0.4 0.4) #(0.0 0.599 0.4) #(0.0 0.8 0.4) #(0.0 1.0 0.4) #(0.0 0.0 0.599) #(0.0 0.199 0.599) #(0.0 0.4 0.599) #(0.0 0.599 0.599) #(0.0 0.8 0.599) #(0.0 1.0 0.599) #(0.0 0.0 0.8) #(0.0 0.199 0.8) #(0.0 0.4 0.8) #(0.0 0.599 0.8) #(0.0 0.8 0.8) #(0.0 1.0 0.8) #(0.0 0.0 1.0) #(0.0 0.199 1.0) #(0.0 0.4 1.0) #(0.0 0.599 1.0) #(0.0 0.8 1.0) #(0.0 1.0 1.0) #(0.199 0.0 0.0) #(0.199 0.199 0.0) #(0.199 0.4 0.0) #(0.199 0.599 0.0) #(0.199 0.8 0.0) #(0.199 1.0 0.0) #(0.199 0.0 0.199) #(0.199 0.199 0.199) #(0.199 0.4 0.199) #(0.199 0.599 0.199) #(0.199 0.8 0.199) #(0.199 1.0 0.199) #(0.199 0.0 0.4) #(0.199 0.199 0.4) #(0.199 0.4 0.4) #(0.199 0.599 0.4) #(0.199 0.8 0.4) #(0.199 1.0 0.4) #(0.199 0.0 0.599) #(0.199 0.199 0.599) #(0.199 0.4 0.599) #(0.199 0.599 0.599) #(0.199 0.8 0.599) #(0.199 1.0 0.599) #(0.199 0.0 0.8) #(0.199 0.199 0.8) #(0.199 0.4 0.8) #(0.199 0.599 0.8) #(0.199 0.8 0.8) #(0.199 1.0 0.8) #(0.199 0.0 1.0) #(0.199 0.199 1.0) #(0.199 0.4 1.0) #(0.199 0.599 1.0) #(0.199 0.8 1.0) #(0.199 1.0 1.0) #(0.4 0.0 0.0) #(0.4 0.199 0.0) #(0.4 0.4 0.0) #(0.4 0.599 0.0) #(0.4 0.8 0.0) #(0.4 1.0 0.0) #(0.4 0.0 0.199) #(0.4 0.199 0.199) #(0.4 0.4 0.199) #(0.4 0.599 0.199) #(0.4 0.8 0.199) #(0.4 1.0 0.199) #(0.4 0.0 0.4) #(0.4 0.199 0.4) #(0.4 0.4 0.4) #(0.4 0.599 0.4) #(0.4 0.8 0.4) #(0.4 1.0 0.4) #(0.4 0.0 0.599) #(0.4 0.199 0.599) #(0.4 0.4 0.599) #(0.4 0.599 0.599) #(0.4 0.8 0.599) #(0.4 1.0 0.599) #(0.4 0.0 0.8) #(0.4 0.199 0.8) #(0.4 0.4 0.8) #(0.4 0.599 0.8) #(0.4 0.8 0.8) #(0.4 1.0 0.8) #(0.4 0.0 1.0) #(0.4 0.199 1.0) #(0.4 0.4 1.0) #(0.4 0.599 1.0) #(0.4 0.8 1.0) #(0.4 1.0 1.0) #(0.599 0.0 0.0) #(0.599 0.199 0.0) #(0.599 0.4 0.0) #(0.599 0.599 0.0) #(0.599 0.8 0.0) #(0.599 1.0 0.0) #(0.599 0.0 0.199) #(0.599 0.199 0.199) #(0.599 0.4 0.199) #(0.599 0.599 0.199) #(0.599 0.8 0.199) #(0.599 1.0 0.199) #(0.599 0.0 0.4) #(0.599 0.199 0.4) #(0.599 0.4 0.4) #(0.599 0.599 0.4) #(0.599 0.8 0.4) #(0.599 1.0 0.4) #(0.599 0.0 0.599) #(0.599 0.199 0.599) #(0.599 0.4 0.599) #(0.599 0.599 0.599) #(0.599 0.8 0.599) #(0.599 1.0 0.599) #(0.599 0.0 0.8) #(0.599 0.199 0.8) #(0.599 0.4 0.8) #(0.599 0.599 0.8) #(0.599 0.8 0.8) #(0.599 1.0 0.8) #(0.599 0.0 1.0) #(0.599 0.199 1.0) #(0.599 0.4 1.0) #(0.599 0.599 1.0) #(0.599 0.8 1.0) #(0.599 1.0 1.0) #(0.8 0.0 0.0) #(0.8 0.199 0.0) #(0.8 0.4 0.0) #(0.8 0.599 0.0) #(0.8 0.8 0.0) #(0.8 1.0 0.0) #(0.8 0.0 0.199) #(0.8 0.199 0.199) #(0.8 0.4 0.199) #(0.8 0.599 0.199) #(0.8 0.8 0.199) #(0.8 1.0 0.199) #(0.8 0.0 0.4) #(0.8 0.199 0.4) #(0.8 0.4 0.4) #(0.8 0.599 0.4) #(0.8 0.8 0.4) #(0.8 1.0 0.4) #(0.8 0.0 0.599) #(0.8 0.199 0.599) #(0.8 0.4 0.599) #(0.8 0.599 0.599) #(0.8 0.8 0.599) #(0.8 1.0 0.599) #(0.8 0.0 0.8) #(0.8 0.199 0.8) #(0.8 0.4 0.8) #(0.8 0.599 0.8) #(0.8 0.8 0.8) #(0.8 1.0 0.8) #(0.8 0.0 1.0) #(0.8 0.199 1.0) #(0.8 0.4 1.0) #(0.8 0.599 1.0) #(0.8 0.8 1.0) #(0.8 1.0 1.0) #(1.0 0.0 0.0) #(1.0 0.199 0.0) #(1.0 0.4 0.0) #(1.0 0.599 0.0) #(1.0 0.8 0.0) #(1.0 1.0 0.0) #(1.0 0.0 0.199) #(1.0 0.199 0.199) #(1.0 0.4 0.199) #(1.0 0.599 0.199) #(1.0 0.8 0.199) #(1.0 1.0 0.199) #(1.0 0.0 0.4) #(1.0 0.199 0.4) #(1.0 0.4 0.4) #(1.0 0.599 0.4) #(1.0 0.8 0.4) #(1.0 1.0 0.4) #(1.0 0.0 0.599) #(1.0 0.199 0.599) #(1.0 0.4 0.599) #(1.0 0.599 0.599) #(1.0 0.8 0.599) #(1.0 1.0 0.599) #(1.0 0.0 0.8) #(1.0 0.199 0.8) #(1.0 0.4 0.8) #(1.0 0.599 0.8) #(1.0 0.8 0.8) #(1.0 1.0 0.8) #(1.0 0.0 1.0) #(1.0 0.199 1.0) #(1.0 0.4 1.0) #(1.0 0.599 1.0) #(1.0 0.8 1.0) #(1.0 1.0 1.0) ))! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:04'! drawCanvas self canvas fillWhite. self orientation = #vertical ifTrue:[self drawVertical] ifFalse:[self drawHorizontal]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 01:14'! drawColorBarHorizontalIn: aRectangle | w r | w _ aRectangle width / self colors size. r _ aRectangle origin extent: w@aRectangle height. self colors do: [:c | self canvas fill: r rounded fillColor: c. r _ r translateBy: w@0]. ! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:07'! drawColorBarVerticalIn: aRectangle | h r | h _ aRectangle height / self colors size. r _ aRectangle origin extent: aRectangle width@h. self colors do: [:c | self canvas fill: r rounded fillColor: c. r _ r translateBy: 0@h]. ! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:51'! drawFastCanvas self orientation = #vertical ifTrue:[self drawFastVertical] ifFalse:[self drawFastHorizontal]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawFastHorizontal "Display in horizontal style, text labels only for speed" | maxLabel minLabel midLabel box ticLength margin bigBox leftX midX adjustIcon loc | self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:self aspect asDisplayText. maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin+ (0@11) corner: bigBox corner. ticLength _ 4. margin _ 2. leftX _ box topLeft x + 2. midX _ box center x. self aspectLabel align: self aspectLabel boundingBox bottomCenter with: box bottomCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight + (-2@ticLength+margin). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox topCenter with: box topCenter + (0@ticLength+margin). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox topLeft with: box topLeft +(0@ticLength+margin). minLabel displayOn: self canvas. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIconHorizontal. adjustIcon displayOn: self canvas at: (loc _ ((leftX+midX//2)@(bigBox center y + 4)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawFastVertical "Display in vertical style, only the text labels for speed" | maxLabel minLabel midLabel box ticLength margin bigBox eraser1 eraser2 eraser3 eraser topY midY adjustIcon loc | eraser _ ' '. eraser1 _ eraser asDisplayText. eraser2 _ eraser asDisplayText. eraser3 _ eraser asDisplayText. eraser1 foregroundColor: Color white backgroundColor: Color white. eraser2 foregroundColor: Color white backgroundColor: Color white. eraser3 foregroundColor: Color white backgroundColor: Color white. self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:(self aspect asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0). maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin + (self aspectLabel width@0) extent: 40@bigBox height. ticLength _ 4. margin _ 2. topY _ box topRight y + 2 . midY _ box center y. self aspectLabel align: self aspectLabel boundingBox leftCenter with: bigBox leftCenter. self aspectLabel displayOn: self canvas. eraser1 align: eraser1 boundingBox topRight with: box topRight - (ticLength+margin+1@0). eraser1 displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. eraser2 align: eraser2 boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). eraser2 displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. eraser3 align: eraser3 boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). eraser3 displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIcon. adjustIcon displayOn: self canvas at: (loc _ (bigBox topCenter x @ (topY+midY//2)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawHorizontal "Display in horizontal style" | maxLabel minLabel midLabel box ticLength margin topY leftX rightX bigBox midX adjustIcon loc | self aspectLabel asParagraph asForm fillWhite displayOn: self canvas. self aspectLabel:self aspect asDisplayText. maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin+ (0@11) corner: bigBox corner. self drawColorBarHorizontalIn: (bigBox origin + (0@1) extent: bigBox width@10). ticLength _ 4. margin _ 2. self aspectLabel align: self aspectLabel boundingBox bottomCenter with: box bottomCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight + (-2@ticLength+margin). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox topCenter with: box topCenter + (0@ticLength+margin). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox topLeft with: box topLeft +(0@ticLength+margin). minLabel displayOn: self canvas. leftX _ box topLeft x + 2. midX _ box center x. rightX _ box topRight x - 2. topY _ box topRight y + margin. self canvas fill: (leftX@topY corner: rightX @(topY+1)) fillColor: Color black. self canvas fill: (leftX@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX+leftX//2@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX+rightX//2@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (rightX@topY extent: 1@ticLength) fillColor: Color black. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIconHorizontal. adjustIcon displayOn: self canvas at: (loc _ ((leftX+midX//2)@(bigBox center y + 4)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawVertical "Display in vertical style" | maxLabel minLabel midLabel box ticLength margin topY midY bottomY leftX rightX bigBox adjustIcon loc | self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:(self aspect asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0). maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin + (aspectLabel width@0) extent: 40@bigBox height. self drawColorBarVerticalIn: (box topRight extent: 10@bigBox height). ticLength _ 4. margin _ 2. self aspectLabel align: self aspectLabel boundingBox leftCenter with: bigBox leftCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. topY _ box topRight y + 2 . midY _ box center y. bottomY _ box bottomRight y - 3. leftX _ box topRight x - ticLength - margin. rightX _ box corner x - margin. self canvas fill: (rightX - 1@topY corner: rightX@bottomY) fillColor: Color black. self canvas fill: (leftX@topY extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@(topY+midY//2) extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@midY extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@(midY+bottomY//2) extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@bottomY extent: ticLength@1) fillColor: Color black. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIcon. adjustIcon displayOn: self canvas at: (loc _( bigBox topCenter x @ (topY+midY//2)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'framing' stamp: 'ssa 1/1/1970 01:30'! newFrame self canvas: nil. self extent: self insetDisplayBox extent. self drawCanvas. self displayView! ! !RVMColorScaleView class methodsFor: 'instance creation' stamp: 'ssa 11/4/2008 20:16'! aspectSource: aspectBlock scalerSource: aBlock colorsSource: colorBlock orientation: aSymbol forView: aView adjustScaler: aBoolean "Answer a new view. Use these blocks to access the scaler and colors it will need to display. Orientation is #vertical or #horizontal" | v | v _ self new. v aspectSource: aspectBlock. v scalerSource: aBlock. v colorsSource: colorBlock. v orientation: aSymbol. v model: aView. v usesScaler: aBoolean. ^v! ! !RVMColorScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:02'! exampleHorizontal "RVMColorScaleView exampleHorizontal" self new horizontal demo! ! !RVMColorScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:03'! exampleVertical "RVMColorScaleView exampleVertical" self new vertical demo! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:30'! aspectView "Answer a subview on my aspect, the symbol name for the aspect of the data sample I am scaling" ^RVMAspectLabelView on: self model getAllAspectsWith: [RVMMulticoreSample aspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:.! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 1/1/1970 01:02'! autoscaleHardenView "Answer a subview showing the autoscale/harden/privatize buttons" | view autoscaleButton hardenButton privatizeButton | view _ RVMView new. autoscaleButton _ RVMButtonView label:'A' style:#action action:[self model scaler setRangeToObserved]. hardenButton _ RVMButtonView label:'H' style:#action action:[self model scaler harden]. privatizeButton _ RVMButtonView label:'P' style:#action action:[self model privatize]. view addSubView: autoscaleButton. view addSubView: hardenButton below: autoscaleButton. view addSubView: privatizeButton below: hardenButton. ^view! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:59'! colorButton "Answer a subview that shows the color to use to display my data" ^RVMColorButtonView on: self model colorGetter:#color colorSetter: #color:! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 1/1/1970 01:16'! initializeSubViews "Add the subviews required to provide a UI for my model, a ColoredDataScaler." self addSubView: self aspectView in: (0@0 extent: 5/10 @ (1/2)) borderWidth:0. self addSubView: self valueView in: (0@(1/2 )extent: 5/10 @ (1/2)) borderWidth:0. self addSubView: self autoscaleHardenView in: (5/10@0 extent: 1/10@1) borderWidth:0. self addSubView: self minMaxView in: (6/10@0 extent: 4/10@1) borderWidth:1. ! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 14:00'! minMaxView "Answer a subview showing the min/max settings for the data sample I am scaling" ^RVMMinMaxView on: self model getMin: #min setMin: #min: getMax: #max setMax: #max:! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:56'! valueView "Answer a subview that will show the last observed value" ^RVMValueView on: self model valueGetterOnly:#lastObserved! ! !RVMColoredDataScalerView methodsFor: 'model access' stamp: 'ssa 9/17/2008 13:09'! model: aColoredDataScaler "Set my model and initialize my subviews" super model: aColoredDataScaler. self initializeSubViews! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:07'! on: aColoredDataScaler "Answer a new view on this scaler" | view | view _ self new. view model: aColoredDataScaler. ^view! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:37'! onAspect: aSymbol ^self on: (RVMColoredDataScaler aspect: aSymbol)! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:17'! openOn: aColoredDataScaler "RVMColoredDataScalerView openOn: RVMColoredDataScaler exampleInstance" "Open a new view on this scaler" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 200@40. topView maximumSize: 300@80. topView addSubView: (self on: aColoredDataScaler). topView label: 'Aspect Data Scaler'. topView controller open! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:35'! openOnAspect: aSymbol "RVMColoredDataScalerView openOnAspect:#bytesUsed" self openOn: (RVMColoredDataScaler aspect: aSymbol)! ! !RVMGridLocationView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 01:29'! displayView | gridExtent point boxes box dot | self canvas extent > self insetDisplayBox extent ifTrue:[self canvas:nil; canvas]. self okToDisplay ifFalse:[^self]. point _ self point. self uncache. self canvas displayOn: Display at:self insetDisplayBox origin. gridExtent _ self gridExtent. dot _ Form extent:1@1. dot fillBlack. boxes _ self insetDisplayBox subDivideBy: gridExtent. 1 to: gridExtent x do:[:x| 1 to: gridExtent y do:[:y| point = (x@y) ifTrue:[box _ boxes at: y-1*gridExtent x+x. Display fill: (box origin - (0@1) extent:box extent)rounded fillColor: Color black]. (point = (0@0)) & ((x@y)=(1@1)) ifTrue:[box _ boxes at: y-1*gridExtent x+x.. Display fill: box rounded fillColor: Color red]. (point > (gridExtent)) & ((x@y)=(gridExtent)) ifTrue:[box _ boxes at: y-1*gridExtent x+x.. Display fill: box rounded fillColor: Color red]. ]]! ! !RVMGridLocationView methodsFor: 'displaying' stamp: 'ssa 11/15/2008 23:46'! drawGridOnCanvas | gridExtent boxes dot leftX rightX boxHeight boxWidth lineY lineX topY bottomY | self canvas fillWhite. gridExtent _ self gridExtent. dot _ Form extent:1@1. dot fillBlack. leftX _ self canvas boundingBox origin x. rightX _ self canvas boundingBox corner x. topY _ self canvas boundingBox origin y. bottomY _ self canvas boundingBox corner y. boxes _ self canvas boundingBox subDivideBy: gridExtent. boxHeight _ boxes first height. boxWidth _ boxes first width . lineY _ topY + boxHeight -2. lineX _ leftX + boxWidth . 1 to: gridExtent x do:[:x| x > (gridExtent x - 2) ifFalse:[ self canvas drawLine: dot from: (leftX@lineY) to: rightX@lineY clippingBox: self canvas boundingBox rule: Form paint fillColor: Color black. lineY _ lineY + boxHeight]. 1 to: gridExtent y do:[:y| y > (gridExtent y - 1) ifFalse:[ self canvas drawLine: dot from: lineX@topY to: lineX@bottomY clippingBox: self canvas boundingBox rule: Form paint fillColor: Color black. lineX _ lineX + boxWidth]. ]]! ! !RVMGridLocationView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:56'! hear: something self displayView! ! !RVMGridLocationView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:32'! newFrame self canvas: nil. self canvas! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 18:03'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (Form extent: self insetDisplayBox extent). self drawGridOnCanvas]. ^ canvas! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 18:02'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:31'! extentGetter "Answer the value of extentGetter" extentGetter isNil ifTrue:[self extentGetter: [8@7]]. ^ extentGetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! extentGetter: anObject "Set the value of extentGetter" extentGetter _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 13:05'! gridExtent ^self extentGetter isSymbol ifTrue:[self model perform: self extentGetter] ifFalse:[self extentGetter value]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:37'! point ^self pointGetter isSymbol ifTrue:[self model perform: self pointGetter] ifFalse:[self pointGetter value]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 02:20'! point: aPoint self pointSetter isSymbol ifTrue:[self model perform: self pointSetter with: aPoint] ifFalse:[self pointSetter value: aPoint]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:31'! pointGetter "Answer the value of pointGetter" pointGetter isNil ifTrue:[self pointGetter: [self extent atRandom]]. ^ pointGetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! pointGetter: anObject "Set the value of pointGetter" pointGetter _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:32'! pointSetter "Answer the value of pointSetter" pointSetter isNil ifTrue:[self pointSetter: ["do nothing by default"]]. ^ pointSetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! pointSetter: anObject "Set the value of pointSetter" pointSetter _ anObject! ! !RVMGridLocationView methodsFor: 'controller access' stamp: 'ssa 11/15/2008 16:10'! defaultControllerClass ^RVMGridLocationController! ! !RVMGridLocationView class methodsFor: 'instance creation' stamp: 'ssa 11/13/2008 12:47'! on: aModel pointGetter: pointGetterBlockOrSelector pointSetter: pointSetterBlockOrSelector extentGetter: extentGetterBlockOrSelector | v | v _ self new. v model: aModel. v pointGetter: pointGetterBlockOrSelector. v pointSetter: pointSetterBlockOrSelector. v extentGetter: extentGetterBlockOrSelector. ^v ! ! !RVMGroupLocatorView methodsFor: 'framing' stamp: 'ssa 11/27/2008 09:33'! newFrame self boxes: nil. self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 14:42'! drawBackgroundCanvas | alt count lighter rowWidth | rowWidth _ RVMMonitor extent x . alt _ false. count _ 0. lighter _ Color black lighter lighter. self boxes do:[:r| self backgroundCanvas fill: r fillColor: (alt ifTrue:[Color black]ifFalse:[lighter]). "self backgroundCanvas border: r width: 1 fillColor: Color gray." alt _ alt not. count _ count + 1. rowWidth odd ifFalse:[count = rowWidth ifTrue:[alt _ alt not. count _ 0]]]. ! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 3/31/2009 18:06'! drawLocations | dot coreExtent amt index rect pt dotSize realRect label | coreExtent _ RVMMonitor extent. dotSize _(self boxes first width // ((self countsPerCore size // self boxes size)max:1))min:self boxes first width //2 max:1. dot _ Form dotOfSize: dotSize color: self color. 0 to: coreExtent x - 1 do:[:x| 0 to: coreExtent y - 1 do:[:y| amt _ self countsPerCore occurrencesOf: (index _ y*coreExtent x+x). rect _ (realRect _ self boxes at: index + 1) insetBy: dot offset abs. label _ amt printString asDisplayText . label foregroundColor: Color red backgroundColor: Color transparent. label displayOn: self canvas at: realRect origin - (0@3) clippingBox: realRect rule: Form paint fillColor: Color red. "amt timesRepeat:[pt _ rect asRandomPoint. dot displayOn: self canvas at: pt clippingBox: realRect rule: Form paint fillColor:nil]"]. ]! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 09:19'! drawOnCanvas self backgroundCanvas displayOn: self canvas at: 0@0. self drawLocations! ! !RVMGroupLocatorView methodsFor: 'displaying' stamp: 'ssa 11/27/2008 09:24'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self drawOnCanvas. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. ! ! !RVMGroupLocatorView methodsFor: 'listening' stamp: 'ssa 11/27/2008 09:31'! hear: something "Update my display" self countsPerCore: nil. self drawOnCanvas. self displayView! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:35'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[self backgroundCanvas: (Form extent: self insetDisplayBox extent depth: Display depth). self drawBackgroundCanvas]. ^ backgroundCanvas! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:30'! boxes "Answer the value of boxes" boxes isNil ifTrue:[self boxes: ((self insetDisplayBox subDivideRoundedBy: RVMMonitor extent) collect:[:r| r translateBy: self insetDisplayBox origin negated])]. ^ boxes! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! boxes: anObject "Set the value of boxes" boxes _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:35'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (Form extent: self insetDisplayBox extent depth: Display depth)]. ^ canvas! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:27'! changeColorTo: aColor "Set the value of color" self color: aColor. self hear:nil! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:15'! color "Answer the value of color" color isNil ifTrue:[self color: Color red]. ^ color! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:15'! color: anObject "Set the value of color" color _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'dmu 5/10/2009 04:38'! countsPerCore "Answer the value of countsPerCore" countsPerCore isNil ifTrue:[self countsPerCore: (self objects asOrderedCollection collect:[:obj| RVMTester isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMTester getCoreHolding:obj]]) asBag]. ^ countsPerCore! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:14'! countsPerCore: aBag "Set the value of countsPerCore, a Bag of coreIndicies with occurenceCounts showing how many of my objects reside in each core" countsPerCore _ aBag! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:16'! objects "Answer my colection of objects to locate." ^self objectsSource isSymbol ifTrue:[self model perform: self objectsSource] ifFalse:[self objectsSource value]! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:16'! objectsSource "Answer the value of objectsSource, a Block that returns a collection of objects to locate. Can also be a SYmbol, a message selector to send to my model" objectsSource isNil ifTrue:[self objectsSource: [String allInstances]]. ^ objectsSource! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:17'! objectsSource: aBlockOrSymbol "Set the value of objectsSource" objectsSource _ aBlockOrSymbol! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 10:34'! objectsSourceSource | code | self objectsSource isSymbol ifTrue:[^self objectsSource printString]. code _ self objectsSource decompile printString. (code beginsWith:'{[') &(code endsWith:']}') ifTrue:[code _ code copyFrom: 3 to: code size - 2]. ^code! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 11:34'! objectsSourceSource: aText | value aString | aString _ aText asString. ( aString withBlanksTrimmed beginsWith:'#') ifTrue:[value _ Compiler new evaluate: aString in: nil to: nil notifying: nil ifFail: [^ false]. self model perform: value. "test to make sure it works before installing"] ifFalse:[value _ Compiler new evaluate: '[',aString,']' in: nil to: nil notifying: nil ifFail: [^ false]]. self objectsSource:value. self hear:nil. ^true "tell the editor its OK"! ! !RVMGroupLocatorView methodsFor: 'controller access' stamp: 'ssa 11/27/2008 09:57'! defaultControllerClass ^RVMGroupLocatorController! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 09:57'! on: aModel objectsSource: aBlockOrSelector "(RVMGroupLocatorView on: Smalltalk objectsSource:#values) demo" "(RVMGroupLocatorView on: nil objectsSource:[String allInstances]) demo" | v | v _ self new. v model: aModel. v objectsSource: aBlockOrSelector. ^v! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 14:10'! openOn: aModel objectsSource: aBlockOrSelector labeled: aString "RVMGroupLocatorView openOn: Smalltalk objectsSource:#allClasses labeled:'All Classes'" "RVMGroupLocatorView openOn: nil objectsSource:[Array allInstances] labeled: 'All Arrays'" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 150@150. topView maximumSize: 800@800. v := self on: aModel objectsSource: aBlockOrSelector. v borderWidth:1. topView addSubView: v viewport:(0@0 extent: 150@150). topView label: aString. topView controller open! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 13:36'! openWithSourceEditorOn: aModel objectsSource: aBlockOrSelector "RVMGroupLocatorView openWithSourceEditorOn: Smalltalk objectsSource:#values" "RVMGroupLocatorView openWithSourceEditorOn: nil objectsSource:[Array allInstances]" | topView v ptv cbv | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 150@170. topView maximumSize: 400@425. v := self on: aModel objectsSource: aBlockOrSelector. v borderWidth:1. ptv _ PluggableTextView on: v text:#objectsSourceSource accept:#objectsSourceSource:. ptv borderWidth:1. cbv _ RVMColorButtonView on: v colorGetter:#color colorSetter:#changeColorTo:. cbv borderWidth:1. topView addSubView: v viewport:(0@0 extent: 150@150). topView addSubView: cbv viewport:(0@150 extent:20@20). topView addSubView: ptv viewport:(20@150 extent:130@20). topView label: 'Group Locator'. topView controller open! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #test0to100]. ^ aspect! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:23'! aspect: anObject "Set the value of aspect" aspect _ anObject. self lastAverage: nil. self lastTotal: nil. self topView == self ifFalse:[self topView relabel: anObject asString]! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:22'! aspectCount ^1! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[ self backgroundCanvas:(ColorForm extent: self canvasExtent depth:8). self spokePens do:[:pen| pen destForm: backgroundCanvas]. self drawBackgroundCanvas.]. ^ backgroundCanvas! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:53'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject ! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:08'! blinker "Answer the value of blinker" blinker isNil ifTrue:[self blinker: true]. self blinker: blinker not. ^ blinker! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:08'! blinker: anObject "Set the value of blinker" blinker _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self canvasExtent depth:8)]. ^ canvas! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:11'! canvas: anObject "Set the value of canvas" canvas _ anObject. self webPen destForm: anObject. self spokePens:nil! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:00'! canvasExtent "Answer the extent of my canvas" ^self insetDisplayBox extent ! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:38'! center ^self canvas center! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:08'! centerMargin "the distance from center to the start of a spoke" ^20! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:13'! diameter "Answer the smallest square diameter for this view's box" ^self canvas height < self canvas width ifTrue:[self canvas height- (self labelRowCount * 10)] ifFalse:[self canvas width - 20]! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground "Answer the value of drawingBackground" drawingBackground isNil ifTrue:[self drawingBackground: false]. ^ drawingBackground! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground: anObject "Set the value of drawingBackground" drawingBackground _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:52'! firstDisplay "Answer the value of firstDisplay" firstDisplay isNil ifTrue:[self firstDisplay: false]. ^ firstDisplay! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 15:13'! firstDisplay: anObject "Set the value of firstDisplay" firstDisplay _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 01:18'! labelRowCount "How many rows of labels will I have?" ^2! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastAverage "Answer the value of lastAverage" lastAverage isNil ifTrue:[self lastAverage: 0]. ^ lastAverage! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastAverage: anObject "Set the value of lastAverage" lastAverage _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastTotal "Answer the value of lastTotal" lastTotal isNil ifTrue:[self lastTotal: 0]. ^ lastTotal! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastTotal: anObject "Set the value of lastTotal" lastTotal _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! majorTicLength ^8! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:35'! majorTicSpacing ^self spokeLength / (self numberOfMajorTics - 1) asFloat! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicLength ^4! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicSpacing ^self majorTicSpacing /( self numberOfMinorTics + 1)! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:38'! numberOfMajorTics ^3! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! numberOfMinorTics ^1! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 13:56'! radius "Answer the smallest radius for this view's box" ^self diameter // 2! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: self rescaleCounterDefault]. ^ rescaleCounter! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 15:02'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault "Answer the value of rescaleCounterDefault" rescaleCounterDefault isNil ifTrue:[self rescaleCounterDefault: 10]. ^ rescaleCounterDefault! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault: anObject "Set the value of rescaleCounterDefault" rescaleCounterDefault _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: RVMDataScaler new automatic]. ^ scaler! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 22:07'! spokeColor "Answer the value of spokeColor" spokeColor isNil ifTrue:[self spokeColor: Color gray lighter lighter]. ^ spokeColor! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! spokeColor: anObject "Set the value of spokeColor" spokeColor _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:30'! spokeLength ^self radius - self centerMargin - 5! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! spokePens "Answer the value of spokePens" spokePens isNil ifTrue:[self spokePens: self initializeSpokePens]. ^ spokePens! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! spokePens: anObject "Set the value of spokePens" spokePens _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor "Answer the value of webColor" webColor isNil ifTrue:[self webColor: Color blue]. ^ webColor! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor: anObject "Set the value of webColor" webColor _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:06'! webPen "Answer the value of webPen" webPen isNil ifTrue:[self webPen: Pen new. webPen color: self webColor. webPen defaultNib:2. webPen combinationRule: Form over. webPen destForm: self canvas]. ^ webPen! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:29'! webPen: anObject "Set the value of webPen" webPen _ anObject! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:19'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:34'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. origin _ self backgroundCanvas boundingBox leftCenter - adjustIcon boundingBox leftCenter + (4@0). adjustIcon displayOn: self backgroundCanvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:18'! drawBackgroundCanvas self drawingBackground: true. self backgroundCanvas fillWhite. self drawSpokes. self drawAdjustScaleIcon. self drawingBackground: false ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:07'! drawCounterOnCanvas | counterLabel | self scaler automaticScaling ifFalse:[^self]. counterLabel _ ('rescale in: ',self rescaleCounter printString ) asDisplayText. counterLabel displayOn: self canvas at: self canvas boundingBox bottomRight -(counterLabel width@90). ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:29'! drawLabelsOnCanvas | minLabel maxLabel aspectLabel avgLabel totalLabel start | aspectLabel _ self aspect asString asDisplayText. aspectLabel foregroundColor: self webColor backgroundColor: Color transparent. aspectLabel displayOn: self canvas at: (2@-4). minLabel _ ('min: ',self scaler min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',self scaler max printShowingMax3Digits) asDisplayText. minLabel foregroundColor: self webColor backgroundColor: Color transparent. maxLabel foregroundColor: self webColor backgroundColor: Color transparent. minLabel displayOn: self canvas at: 0@((aspectLabel height //2)-2)clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: 0@(start _ maxLabel height) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. avgLabel _ ('avg: ',self lastAverage printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',self lastTotal printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: self webColor backgroundColor: Color transparent. totalLabel foregroundColor: self webColor backgroundColor: Color transparent. totalLabel displayOn: self canvas at: 0@(start _start +(totalLabel height - 6)) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: 0@( start + (maxLabel height - 6)) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMajorTicUsing: pen pen turn:90; go: self majorTicLength/2;turn:180;down;go:self majorTicLength;up; turn:180; go: self majorTicLength/2;turn:-90! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMinorTicUsing: pen pen turn:90; go: self minorTicLength/2;turn:180;down;go:self minorTicLength;up; turn:180; go: self minorTicLength/2;turn:-90! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/8/2008 19:16'! drawOnCanvas self drawingBackground ifTrue:[^self]. self backgroundCanvas displayOn: self canvas at: 0@0. self drawCounterOnCanvas. self drawWeb. self drawLabelsOnCanvas. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/17/2008 13:25'! drawSpokes | pen label labelOffsets labelOffset mainIndex oldColor | mainIndex _ RVMMonitor mainRank + 1. 1 to: self spokePens size do:[:index| pen _ self spokePens at: index. oldColor _ pen color. index = mainIndex ifTrue:[pen color: Color red]. pen destForm: self backgroundCanvas. pen place: self center. pen up; go: self centerMargin. pen down;go: self spokeLength;up. label _ (index - 1) printString asDisplayText asParagraph asForm. self diameter < 300 ifTrue:[label _ label scaledToSize: 11@11]. labelOffsets _ {0@label height negated. 0@0. label width negated@0. label extent negated}. labelOffset _ labelOffsets at: ((index - 1// (self spokePens size / 4) + 1) min:4). label displayOn: self backgroundCanvas at: pen location + labelOffset clippingBox: self backgroundCanvas boundingBox rule: Form paint fillColor: nil. self drawTicsUsing: pen. pen color: oldColor] ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 11:54'! drawTicsUsing: pen pen up;place: self center;go:self centerMargin. self drawMajorTicUsing: pen. self numberOfMajorTics - 1 timesRepeat:[ self numberOfMinorTics timesRepeat:[ pen go: self minorTicSpacing. self drawMinorTicUsing: pen]. pen go: self minorTicSpacing. self drawMajorTicUsing: pen]. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 14:18'! drawWeb self drawingBackground ifTrue:[^self]. self placeSpokePens. self webPen color: self webColor. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:39'! placeSpokePens | data tot | data _ RVMMonitor lastSample perform: self aspect. tot _ 0. self spokePens size = data size ifFalse: [self resetAfterCoreCountChange]. data with: self spokePens do:[:datum :pen| tot _ tot + datum. pen up;place: self center;go:self centerMargin. pen go:(self spokeLength /100.0*(self scaler scale: datum))]. self lastTotal: tot. self lastAverage: tot / data size! ! !RVMKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 15:20'! firstFrame ! ! !RVMKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 19:20'! newFrame self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMKiviatView methodsFor: 'scaling' stamp: 'ssa 10/8/2008 18:52'! resetScaling self scaler resetScaling. ! ! !RVMKiviatView methodsFor: 'initialize-release' stamp: 'ssa 10/6/2008 16:42'! initializeSpokePens | pens numberOfSpokes spacing center pen | pens _ OrderedCollection new. numberOfSpokes _ RVMMonitor coreCount. spacing _ 360 / numberOfSpokes asFloat. center _ self insetDisplayBox center. numberOfSpokes timesRepeat:[ pen _ Pen new. pen defaultNib:1. pen combinationRule: Form over. pen color: self spokeColor. pen place: center. pen north. pen turn: pens size * spacing. pens add: pen]. ^pens! ! !RVMKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 21:41'! release "self controller scalerAdjusters do:[:each| each topView controller closeAndUnscheduleNoTerminate]. self controller scalerAdjusters: nil." super release! ! !RVMKiviatView methodsFor: 'displaying' stamp: 'ssa 11/12/2008 13:16'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self firstDisplay ifFalse:[self firstDisplay:true. self drawOnCanvas]. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. self blinker ifTrue:[(Form dotOfSize:5) displayOn: Display at: self insetDisplayBox center] ! ! !RVMKiviatView methodsFor: 'controller access' stamp: 'ssa 10/6/2008 13:35'! defaultControllerClass ^RVMKiviatController! ! !RVMKiviatView methodsFor: 'listening' stamp: 'dmu 2/6/2009 22:35'! hear: something "Update my traces and redisplay" self firstDisplay ifFalse:[^self]. self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self resetScaling.]. self drawingBackground ifTrue:[^self]. self drawOnCanvas. self displayView! ! !RVMKiviatView class methodsFor: 'examples' stamp: 'ssa 10/6/2008 16:00'! example "RVMKiviatView example" self openOnAspect: #bytesUseds! ! !RVMKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 13:58'! openOnAspect: aSymbol "RVMKiviatView example" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@250. topView maximumSize: 600@500. v := self new. v borderWidth:1. v aspect: aSymbol. topView addSubView: v. topView label: v aspect. topView controller open! ! !RVMLabelView methodsFor: 'displaying' stamp: 'ssa 9/14/2008 20:45'! displayView | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: self backgroundColor backgroundColor: self foregroundColor. labelForm := labelText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: labelText boundingBox extent). labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self foregroundColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: labelText foregroundColor. ! ! !RVMLabelView methodsFor: 'accessing' stamp: 'ssa 8/26/2008 22:55'! label "Answer the value of label" label isNil ifTrue:[^'no label yet']. ^label! ! !RVMLabelView methodsFor: 'accessing' stamp: 'ssa 8/26/2008 22:54'! label: anObject "Set the value of label" label := anObject! ! !RVMAspectLabelView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView | labelRect labelText labelForm | self uncache. labelText := self label asDisplayText. labelText foregroundColor: self foregroundColor backgroundColor: self backgroundColor. labelForm := labelText asParagraph asForm. labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self backgroundColor. labelForm displayOn: Display at: labelRect leftCenter - labelForm boundingBox leftCenter + (2@0) clippingBox: labelRect rule: Form paint fillColor: nil. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated." ! ! !RVMAspectLabelView methodsFor: 'updating' stamp: 'ssa 9/17/2008 14:17'! update: aSymbol aSymbol = self getAspectSelector ifTrue:[self displayView ]. super update: aSymbol! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:51'! aspect ^self getAspectSelector isSymbol ifTrue:[self model perform: self getAspectSelector] ifFalse:["assume a block" self getAspectSelector value]! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:14'! aspect: aSymbol self setAspectSelector isSymbol ifTrue:[self model perform: self setAspectSelector with: aSymbol] ifFalse:["assume a block" self setAspectSelector value: aSymbol]. ! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:15'! aspects ^self getAspectsSelector isSymbol ifTrue:[self model perform: self getAspectsSelector] ifFalse:["assume a block" self getAspectsSelector value]! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:06'! backgroundColor ^Color white! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:36'! foregroundColor ^Color black! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! getAspectSelector "Answer the value of getAspectSelector" getAspectSelector isNil ifTrue:[self getAspectSelector: #aspect]. ^ getAspectSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! getAspectSelector: anObject "Set the value of getAspectSelector" getAspectSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! getAspectsSelector "Answer the value of getAspectsSelector" getAspectsSelector isNil ifTrue:[self getAspectsSelector: #aspects]. ^ getAspectsSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! getAspectsSelector: anObject "Set the value of getAspectsSelector" getAspectsSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:18'! label ^self aspect! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:25'! lastAspect "Answer the value of lastAspect" lastAspect isNil ifTrue:[self lastAspect: #foo]. ^ lastAspect! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:25'! lastAspect: anObject "Set the value of lastAspect" lastAspect _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! setAspectSelector "Answer the value of setAspectSelector" setAspectSelector isNil ifTrue:[self setAspectSelector: #aspect:]. ^ setAspectSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! setAspectSelector: anObject "Set the value of setAspectSelector" setAspectSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 16:16'! defaultControllerClass ^RVMAspectLabelController! ! !RVMCoreIndexView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:36'! displayView | labelRect labelText labelForm | self okToDisplay ifFalse:[^self]. self uncache. labelText := self label asDisplayText. labelText foregroundColor: self foregroundColor backgroundColor: self backgroundColor. labelForm := labelText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: labelText boundingBox extent). labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self backgroundColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: nil. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated." ! ! !RVMCoreIndexView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:14'! defaultControllerClass ^RVMCoreIndexController! ! !RVMCoreIndexView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:24'! hear: something self displayView! ! !RVMCoreIndexView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:12'! update: aSymbol aSymbol = self getCoreIndex ifTrue:[self displayView ]. super update: aSymbol! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:18'! availableIndicies "Answer the number of indices available" ^self getAvailableIndicies isSymbol ifTrue:[self model perform: self getAvailableIndicies] ifFalse:["assume a block" self getAvailableIndicies value]! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! coreIndex ^self getCoreIndex isSymbol ifTrue:[self model perform: self getCoreIndex] ifFalse:["assume a block" self getCoreIndex value]! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! coreIndex: aValue self setCoreIndex isSymbol ifTrue:[self model perform: self setCoreIndex with: aValue] ifFalse:["assume a block" self setCoreIndex value: aValue]. ! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:18'! getAvailableIndicies "Answer the value of getAvailableIndicies" getAvailableIndicies isNil ifTrue:[self getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]]. ^ getAvailableIndicies! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:17'! getAvailableIndicies: anObject "Set the value of getAvailableIndicies" getAvailableIndicies _ anObject! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! getCoreIndex "Answer the value of getCoreIndex" getCoreIndex isNil ifTrue:[self getCoreIndex: #coreIndex]. ^ getCoreIndex! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! getCoreIndex: anObject "Set the value of getCoreIndex" getCoreIndex _ anObject! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:31'! label ^self coreIndex printString! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! setCoreIndex "Answer the value of setCoreIndex" setCoreIndex isNil ifTrue:[self setCoreIndex: #coreIndex:]. ^ setCoreIndex! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! setCoreIndex: anObject "Set the value of setCoreIndex" setCoreIndex _ anObject! ! !RVMLabelView class methodsFor: 'instance creation' stamp: 'ssa 8/26/2008 23:02'! label: aString | view | view := self new. view label: aString. ^view! ! !RVMAspectLabelView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:27'! on: anObject "Answer a label view that will send #aspect to this object to find its label" | view | view := self new. view model: anObject. ^view! ! !RVMAspectLabelView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 14:04'! on: anObject getAllAspectsWith: getAspectsSelector getCurrentAspectWith: getAspectSelector setNewAspectWith: setAspectSelector "Answer an aspect view that can probe and change the aspect of its aspectee. Note 'selector' arguments can be symbols or blocks" | view | view := self new. view model: anObject. view getAspectsSelector: getAspectsSelector. view getAspectSelector: getAspectSelector. view setAspectSelector: setAspectSelector. ^view! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:31'! example "RVMAspectLabelView example" | topView view | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. view _ self on: view getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view model: view. topView addSubView: view. topView label: 'Aspect Button'. topView controller open! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:31'! exampleMany "RVMAspectLabelView exampleMany" | topView view1 view2 view3 | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@75. topView maximumSize: 200@100. view1 _ self on: view1 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view1 on: view1. view2 _ self on: view2 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view2 on: view2. view3 _ self on: view3 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view3 on: view3. topView addSubView: view1. topView addSubView: view2 below: view1. topView addSubView: view3 below: view2. topView label: 'Aspect Button'. topView controller open! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:32'! exampleWithColorButton "RVMAspectLabelView exampleWithColorButton" | topView view colorButton | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. view _ self on: view getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view model: view. colorButton _ RVMColorButtonView new. topView addSubView: view in: (0@0 extent: 5/6 @ 1) borderWidth:0. topView addSubView: colorButton in: (5/6@0 extent: 1/6@1) borderWidth:0. topView label: 'Aspect Button'. topView controller open! ! !RVMCoreIndexView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:30'! example "RVMCoreIndexView example" self exampleInstance demo! ! !RVMCoreIndexView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:30'! exampleInstance "RVMCoreIndexView exampleInstance" ^self on: RVMCoreAspectTrace exampleInstance getCoreIndex:#coreIndex setCoreIndex: #coreIndex: getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]! ! !RVMCoreIndexView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:28'! on: aModel getCoreIndex: getter setCoreIndex: setter getAvailableIndicies: maxIndexGetter | view | view _ self new. view model: aModel; getCoreIndex: getter; setCoreIndex: setter; getAvailableIndicies: maxIndexGetter. ^view! ! !RVMMinMaxView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 20:54'! example "RVMMinMaxView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@50. topView maximumSize: 200@100. topView addSubView: self exampleInstance. topView label: 'MinMax'. topView controller open! ! !RVMMinMaxView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:56'! exampleInstance | scaler | scaler _ RVMDataScaler exampleInstance. ^self on: scaler getMin: [scaler min] setMin:[:v| scaler min: v] getMax: [scaler max] setMax: [:v| scaler max: v]. ! ! !RVMMinMaxView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:53'! on: aModel getMin: getMin setMin: setMin getMax: getMax setMax: setMax | view v | view _ self new. view addSubView: (v _ RVMValueView on: aModel valueGetter: getMin valueSetter: setMin label:'m'). view addSubView: (RVMValueView on: aModel valueGetter: getMax valueSetter: setMax label:'M') above: v. ^view! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:14'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: RVMMulticoreSample systemAspects]. ^ aspects! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:12'! aspects: anObject "Set the value of aspects" aspects _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[ self backgroundCanvas:(ColorForm extent: self canvasExtent depth:8). self spokePens do:[:pen| pen destForm: backgroundCanvas]. self drawBackgroundCanvas.]. ^ backgroundCanvas! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:53'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject ! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:17'! blinker "Answer the value of blinker" blinker isNil ifTrue:[self blinker: true]. self blinker: blinker not. ^ blinker! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:18'! blinker: anObject "Set the value of blinker" blinker _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self canvasExtent depth:8)]. ^ canvas! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:11'! canvas: anObject "Set the value of canvas" canvas _ anObject. self webPen destForm: anObject. self spokePens:nil! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:00'! canvasExtent "Answer the extent of my canvas" ^self insetDisplayBox extent ! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:38'! center ^self canvas center! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:08'! centerMargin "the distance from center to the start of a spoke" ^20! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:36'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: ((Color wheel: self coreIndicies size) "collect:[:each| each darker darker]") ]. ^ colors! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 09:38'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:34'! coreIndicies "Answer the value of coreIndicies" coreIndicies isNil ifTrue:[self coreIndicies: (1 to: RVMMonitor coreCount) asOrderedCollection]. ^ coreIndicies! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 09:50'! coreIndicies: anObject "Set the value of coreIndicies" coreIndicies _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:13'! diameter "Answer the smallest square diameter for this view's box" ^self canvas height < self canvas width ifTrue:[self canvas height- (self labelRowCount * 10)] ifFalse:[self canvas width - 20]! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground "Answer the value of drawingBackground" drawingBackground isNil ifTrue:[self drawingBackground: false]. ^ drawingBackground! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground: anObject "Set the value of drawingBackground" drawingBackground _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:52'! firstDisplay "Answer the value of firstDisplay" firstDisplay isNil ifTrue:[self firstDisplay: false]. ^ firstDisplay! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 15:13'! firstDisplay: anObject "Set the value of firstDisplay" firstDisplay _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:56'! indexIcons "Answer the value of indexIcons" indexIcons isNil ifTrue:[self indexIcons: self buildIndexIcons]. ^ indexIcons! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:56'! indexIcons: anObject "Set the value of indexIcons" indexIcons _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 01:18'! labelRowCount "How many rows of labels will I have?" ^2! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! majorTicLength ^8! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:35'! majorTicSpacing ^self spokeLength / (self numberOfMajorTics - 1) asFloat! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicLength ^4! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicSpacing ^self majorTicSpacing /( self numberOfMinorTics + 1)! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:38'! numberOfMajorTics ^3! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! numberOfMinorTics ^1! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 13:56'! radius "Answer the smallest radius for this view's box" ^self diameter // 2! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: self rescaleCounterDefault]. ^ rescaleCounter! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 15:02'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault "Answer the value of rescaleCounterDefault" rescaleCounterDefault isNil ifTrue:[self rescaleCounterDefault: 10]. ^ rescaleCounterDefault! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault: anObject "Set the value of rescaleCounterDefault" rescaleCounterDefault _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:15'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: (self aspects collect:[:each| RVMDataScaler new automatic])]. ^ scalers! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:12'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 22:07'! spokeColor "Answer the value of spokeColor" spokeColor isNil ifTrue:[self spokeColor: Color gray lighter lighter]. ^ spokeColor! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! spokeColor: anObject "Set the value of spokeColor" spokeColor _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:30'! spokeLength ^self radius - self centerMargin - 5! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! spokePens "Answer the value of spokePens" spokePens isNil ifTrue:[self spokePens: self initializeSpokePens]. ^ spokePens! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! spokePens: anObject "Set the value of spokePens" spokePens _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor "Answer the value of webColor" webColor isNil ifTrue:[self webColor: Color blue]. ^ webColor! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor: anObject "Set the value of webColor" webColor _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:06'! webPen "Answer the value of webPen" webPen isNil ifTrue:[self webPen: Pen new. webPen color: self webColor. webPen defaultNib:2. webPen combinationRule: Form over. webPen destForm: self canvas]. ^ webPen! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:29'! webPen: anObject "Set the value of webPen" webPen _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:19'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:21'! buildIndexIcons | icon label | ^self coreIndicies collect:[:index| label _ index printString asDisplayText . label foregroundColor: Color black backgroundColor: Color transparent. icon _ self iconCircle. label align: label boundingBox center with: icon boundingBox center. label displayOn: icon at: 0@-2. icon offset: icon boundingBox center negated. icon]! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:34'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. origin _ self backgroundCanvas boundingBox leftCenter - adjustIcon boundingBox leftCenter + (4@0). adjustIcon displayOn: self backgroundCanvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:59'! drawBackgroundCanvas self drawingBackground: true. self backgroundCanvas fillWhite. self drawSpokes. "self drawAdjustScaleIcon." "self drawLabelsOnBackground." self drawingBackground: false. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:18'! drawCounterOnCanvas | counterLabel | counterLabel _ ('rescale in: ',self rescaleCounter printString ) asDisplayText. counterLabel displayOn: self canvas at: self canvas boundingBox bottomRight -(counterLabel width@90). ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 10:27'! drawLabelsOnBackground | labels count origin coreNameText | labels _ self coreIndicies isEmpty ifTrue:[Array with:'System Aspects']ifFalse:[self coreIndicies collect:[:each| 'Core #',each printString]]. count _ 1. origin _ 2@-4. labels do:[:coreName| coreNameText _ coreName asDisplayText. coreNameText foregroundColor: (self colors at: count) backgroundColor: Color transparent. coreNameText displayOn: self backgroundCanvas at: origin. origin _ origin + (0@coreNameText height). count = (labels size //2) ifTrue:[origin _ self canvas boundingBox topRight - (coreNameText width @0)]. count _ count + 1] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMajorTicUsing: pen pen turn:90; go: self majorTicLength/2;turn:180;down;go:self majorTicLength;up; turn:180; go: self majorTicLength/2;turn:-90! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMinorTicUsing: pen pen turn:90; go: self minorTicLength/2;turn:180;down;go:self minorTicLength;up; turn:180; go: self minorTicLength/2;turn:-90! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:43'! drawOnCanvas self drawingBackground ifTrue:[^self]. self backgroundCanvas displayOn: self canvas at: 0@0. "self drawCounterOnCanvas." self drawWeb. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:24'! drawSpokes | pen label labelOffsets labelOffset | 1 to: self spokePens size do:[:index| pen _ self spokePens at: index. pen destForm: self backgroundCanvas. pen place: self center. pen up; go: self centerMargin. pen down;go: self spokeLength;up. label _ (self aspects at: index) asString asDisplayText asParagraph asForm. "self diameter < 300 ifTrue:[label _ label scaledToSize: 11@11]." labelOffsets _ {0@label height negated. 0@0. label width negated@0. label extent negated}. labelOffset _ labelOffsets at: ((index - 1// (self spokePens size / 4) + 1) min:4). label displayOn: self backgroundCanvas at: pen location + labelOffset clippingBox: self backgroundCanvas boundingBox rule: Form paint fillColor: nil. self drawTicsUsing: pen] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 11:54'! drawTicsUsing: pen pen up;place: self center;go:self centerMargin. self drawMajorTicUsing: pen. self numberOfMajorTics - 1 timesRepeat:[ self numberOfMinorTics timesRepeat:[ pen go: self minorTicSpacing. self drawMinorTicUsing: pen]. pen go: self minorTicSpacing. self drawMajorTicUsing: pen]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 13:06'! drawWeb self coreIndicies isEmpty ifTrue:[^self drawWebSystem]. self coreIndicies do:[:index| self placeSpokePensForCore: index. self webPen color: (self colors at: (self coreIndicies indexOf: index)). self webPen combinationRule: Form paint. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up]. self coreIndicies "shuffled" do:[:index| self placeIconsForCore: index] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 10:07'! drawWebSystem self drawingBackground ifTrue:[^self]. self placeSpokePens. self webPen color: self webColor. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:12'! iconCircle | icon aForm aCircle | icon _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 1@1. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: icon. ^icon! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:46'! placeIconsForCore: anIndex | data scaledDatum offset aspectIndex | data _ anIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: anIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. offset _ self aspects size > 0 ifTrue:[0]ifFalse:[((anIndex) - 1)*8/5]. aspectIndex _ 1. data with: self spokePens do:[:datum :pen| pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalers at: aspectIndex) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset. aspectIndex _ aspectIndex + 1. (self indexIcons at: (self coreIndicies indexOf: anIndex)) displayOn: self canvas at: pen location]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 02:26'! placeSpokePens | data index | data _ self coreIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: self coreIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. index _ 0. data with: self spokePens do:[:datum :pen| index _ index + 1. pen up;place: self center;go:self centerMargin. pen go:(self spokeLength /100.0*((self scalers at: index) scale: datum))]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:45'! placeSpokePensForCore: anIndex | data scaledDatum offset aspectIndex | data _ anIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: anIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. offset _ self aspects size > 0 ifTrue:[0]ifFalse:[((anIndex) - 1)*8/5]. aspectIndex _ 1. data with: self spokePens do:[:datum :pen| pen color: (self colors at: (self coreIndicies indexOf: anIndex)). pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalers at: aspectIndex) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset. aspectIndex _ aspectIndex + 1]. ! ! !RVMMultiAspectKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 15:20'! firstFrame ! ! !RVMMultiAspectKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 19:20'! newFrame self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMMultiAspectKiviatView methodsFor: 'scaling' stamp: 'ssa 11/11/2008 23:06'! resetScaling self scalers do:[:each| each resetScaling]. ! ! !RVMMultiAspectKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 23:05'! initializeSpokePens | pens numberOfSpokes spacing center pen | pens _ OrderedCollection new. numberOfSpokes _ self aspects size. spacing _ 360 / numberOfSpokes asFloat. center _ self insetDisplayBox center. numberOfSpokes timesRepeat:[ pen _ Pen new. pen defaultNib:1. pen combinationRule: Form over. pen color: self spokeColor. pen place: center. pen north. pen turn: pens size * spacing. pens add: pen]. ^pens! ! !RVMMultiAspectKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 21:41'! release "self controller scalerAdjusters do:[:each| each topView controller closeAndUnscheduleNoTerminate]. self controller scalerAdjusters: nil." super release! ! !RVMMultiAspectKiviatView methodsFor: 'displaying' stamp: 'ssa 11/12/2008 13:18'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self firstDisplay ifFalse:[self firstDisplay:true. self drawOnCanvas]. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. self blinker ifTrue:[(Form dotOfSize:5) displayOn: Display at: self insetDisplayBox center] ! ! !RVMMultiAspectKiviatView methodsFor: 'controller access' stamp: 'ssa 10/6/2008 13:35'! defaultControllerClass ^RVMMultiAspectKiviatController! ! !RVMMultiAspectKiviatView methodsFor: 'listening' stamp: 'dmu 2/6/2009 22:35'! hear: something "Update my traces and redisplay" self firstDisplay ifFalse: [^self]. self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self resetScaling.]. self drawingBackground ifTrue:[^self]. self drawOnCanvas. self displayView! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/13/2008 02:02'! allCoreAspects ^RVMMulticoreSample coreAspects! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:53'! coreAspectSubset "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubset forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers'" ^#( bytecodesPerSecond bytesUseds contextChangeCounts interruptCheckCounts unforcedInterruptCheckCounts yieldsPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetAllocationCompaction "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetAllocationCompaction forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Allocation/Compaction'" ^#(allocationsReadWrites allocationsReadMostlys allocationsTotal compactionsReadWrites compactionsReadMostlys compactionsTotal )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetBytecodes "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetBytecodes forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Bytecodes'" ^#( bytecodeCounts bytecodesPerCycles bytecodesPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetBytes "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetBytes forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Bytes'" ^#(bytesLeftReadWrites bytesLeftReadMostlys bytesLefts bytesUsedReadWrites bytesUsedReadMostlys bytesUseds )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:55'! coreAspectSubsetRunWait "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetRunWait forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: RunWait'" ^#(millisecondsRunnings millisecondsWaitings msRunWaitRatios msSinceLasts )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:55'! coreAspectSubsetYields "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetYields forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Yields'" ^#(unforcedInterruptCheckCounts yieldCounts yieldFrequencies yieldsPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/11/2008 23:18'! example "RVMMultiAspectKiviatView example" self openOnAspects: RVMMulticoreSample systemAspects! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:26'! example10Cores "RVMMultiAspectKiviatView example10Cores" self openOnAspects: RVMMulticoreSample coreAspects forCores: #(1 2 3 4 5 6 7 8 9 10)! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:50'! example10CoresSubset1 "RVMMultiAspectKiviatView example10CoresSubset1" self openOnAspects: self coreAspectSubset forCores: #(1 2 3 4 5 6 7 8 9 10)! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:34'! example20Cores "RVMMultiAspectKiviatView example20Cores" self openOnAspects: RVMMulticoreSample coreAspects forCores: (1 to: 20) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 11:53'! exampleAllCores "RVMMultiAspectKiviatView exampleAllCores" self openOnAspects: RVMMulticoreSample coreAspects forCores:(1 to: RVMMonitor coreCount) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 11:53'! exampleAllCoresSubset1 "RVMMultiAspectKiviatView exampleAllCoresSubset1" self openOnAspects: self coreAspectSubset forCores:(1 to: RVMMonitor coreCount) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 02:24'! exampleCore5 "RVMMultiAspectKiviatView exampleCore5" self openOnAspects: RVMMulticoreSample coreAspects forCore: 5! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:45'! exampleSubset1 "RVMMultiAspectKiviatView exampleSubset1" self openOnAspects: self coreAspectSubset! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/11/2008 23:17'! openOnAspect: aSymbol "RVMMultiAspectKiviatView example" self openOnAspects: (Array with: aSymbol)! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 11:44'! openOnAspects: someSymbols "RVMMultiAspectKiviatView example" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 600@250. topView maximumSize: 1000@800. v := self new. v borderWidth:1. v aspects: someSymbols. topView addSubView: v. topView label: 'MultiAspectKiviat'. topView controller open! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 10:15'! openOnAspects: someSymbols forCore: anIndex "RVMMultiAspectKiviatView exampleCore5" self openOnAspects: someSymbols forCores: (Array with: anIndex)! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 12:52'! openOnAspects: someSymbols forCores: indexArray "RVMMultiAspectKiviatView exampleAllCores" self openOnAspects: someSymbols forCores: indexArray titled: 'MultiAspectKiviat'! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 12:59'! openOnAspects: someSymbols forCores: indexArray titled: aString "RVMMultiAspectKiviatView exampleAllCores" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@150"(9*indexArray size max:250)". topView maximumSize: 1000@800. v := self new. v coreIndicies: indexArray. v borderWidth:1. v aspects: someSymbols. topView addSubView: v. topView label: aString. topView controller open! ! !RVMMultiAspectStripChartView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 17:43'! defaultControllerClass ^RVMMultiAspectStripChartController! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:12'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: OrderedCollection new]. ^ aspects! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:41'! aspects: anObject "Set the value of aspects" aspects _ anObject.. self scalers:nil. self data: nil. ! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:12'! chart "Answer the value of chart" chart isNil ifTrue:[self chart: (Form fromDisplay: self insetDisplayBox) fillWhite]. ^ chart! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:11'! chart: anObject "Set the value of chart" chart _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/14/2008 20:55'! colors "Answer the value of colors" ^self scalers collect:[:each| each color]! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:36'! coreIndex "Answer the value of coreIndex" coreIndex isNil ifTrue:[self coreIndex: 1]. ^ coreIndex! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:36'! coreIndex: anObject "Set the value of coreIndex" coreIndex _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:25'! data "Answer the value of data" data isNil ifTrue:[self data: (Array new: self aspects size)]. ^ data! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:11'! data: anObject "Set the value of data" data _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:18'! dotSize "Answer the value of dotSize" dotSize isNil ifTrue:[self dotSize: 2]. ^ dotSize! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:14'! dotSize: anObject "Set the value of dotSize" dotSize _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:49'! getData | sample | sample _ self sampleSource value. 1 to: self aspects size do:[:index| self data at: index put: ((self scalers at: index) scale:((sample perform: (self aspects at: index)) at: self coreIndex))]! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:29'! sampleSource "Answer the value of sampleSource" sampleSource isNil ifTrue:[self sampleSource: [RVMMonitor lastSample]]. ^ sampleSource! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:27'! sampleSource: anObject "Set the value of sampleSource" sampleSource _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: (RVMMonitor coloredScalersFor: self aspects)]. ^ scalers! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 18:04'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:33'! hear: something self displayView! ! !RVMMultiAspectStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | bottomLeft points sortedPoints box | self okToDisplay ifFalse:[^self]. self uncache. self getData. self chart displayOn: Display at: self insetDisplayBox origin + (self dotSize @ 0) clippingBox: self insetDisplayBox. bottomLeft := self insetDisplayBox bottomLeft. points := OrderedCollection new. 1 to: self aspects size do: [:index | points add: index @ (self data at: index)]. sortedPoints := points asSortedCollection: [:a :b | a y > b y]. sortedPoints do: [:each | box := bottomLeft - (0 @ (each y * self dotSize)) corner: bottomLeft + (self dotSize @ 0). Display fill: box fillColor: (self colors at: each x)]. self chart:(Form fromDisplay: self insetDisplayBox).! ! !RVMMultiAspectStripChartView methodsFor: 'displaying' stamp: 'ssa 9/14/2008 21:50'! eraseStrip Display fill: self insetDisplayBox fillColor: Color white. self chart: nil;chart! ! !RVMMultiAspectStripChartView methodsFor: 'auxiliary views' stamp: 'ssa 1/1/1970 00:29'! combinedScalerView "Answer a view holding all my appropriate scaler views" | v last current | v _ RVMView new. last _ nil. self scalers do:[:scaler| v addSubView: (current _ RVMColoredDataScalerView on: scaler) below: last. current borderWidth:1. last _ current]. ^v! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:29'! example "RVMMultiAspectStripChartView example" | topView chart scalers aspectCount | topView := RVMStandardSystemView new. topView borderWidth:1. chart _ self exampleInstance. aspectCount _ chart aspects size. topView minimumSize: 200@(aspectCount*40). topView maximumSize: 800@(2*aspectCount*40). scalers _ chart combinedScalerView. topView addSubView: scalers in:(0@0 extent: 1/3 @ 1)borderWidth:1. topView addSubView: chart in:(1/3@0 extent: 2/3 @ 1)borderWidth:1. topView label: 'Multi Aspect Strip'. topView controller open! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:28'! exampleInstance | view | view _ self new. view aspects: #( bytecodeCounts bytesUseds yieldCounts ). ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 9/14/2008 20:30'! exampleMany "RVMMultiAspectStripChartView exampleMany" | topView view manyCount lastView | topView := RVMStandardSystemView new. topView borderWidth:1. manyCount _ 4. topView minimumSize: 100@(25*manyCount). topView maximumSize: 200@(50*manyCount). lastView _ nil. manyCount timesRepeat:[ view _ self exampleInstance. topView addSubView: view below: lastView. lastView _ view]. topView label: 'Aspect/Color'. topView controller open! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:10'! coreIndex: index "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: #(bytesUsed bytecodeCounts yieldCounts). view sampleSource: [RVMMonitor lastSample]. ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:08'! coreIndex: index aspects: aspects "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: aspects. view sampleSource: [RVMMonitor lastSample]. ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:08'! coreIndex: index aspects: aspects sampleSource: aBlock "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: aspects. view sampleSource: aBlock. ^view! ! !RVMMultiGroupLocatorView methodsFor: 'listening' stamp: 'ssa 11/27/2008 13:24'! hear: something "Update my display" self counts: nil. self drawOnCanvas. self displayView! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:55'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: (Color hotColdShades: (self sources size max:5))]. ^ colors! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:37'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:33'! counts "Answer the value of counts" counts isNil ifTrue:[self counts: (Array new:self sources size). 1 to: self sources size do:[:index| self countsPerCoreForGroupNumber: index]]. ^ counts! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:31'! counts: anObject "Set the value of counts" counts _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'dmu 4/18/2009 18:35'! countsPerCoreForGroupNumber: anIndex "Answer the value of countsPerCore" (self counts at: anIndex) isNil ifTrue:[self counts at: anIndex put: ((self objectsForGroupNumber: anIndex) asOrderedCollection collect:[:obj| RVMTester isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMTester getCoreHolding:obj]]) asBag]. ^ self counts at: anIndex! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:33'! objectsForGroupNumber: anIndex "Answer my colection of objects to locate." | source | source _ self sources at: anIndex. ^source isSymbol ifTrue:[self model perform: source] ifFalse:[source value]! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:19'! sourceSourceForGroupNumber: anIndex | code source | source _ self sources at: anIndex. source isSymbol ifTrue:[^source printString]. code _ source decompile printString. (code beginsWith:'{[') &(code endsWith:']}') ifTrue:[code _ code copyFrom: 3 to: code size - 2]. ^code! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:22'! sourceSourceForGroupNumber: anIndex put: aText | value aString | aString _ aText asString. ( aString withBlanksTrimmed beginsWith:'#') ifTrue:[value _ Compiler new evaluate: aString in: nil to: nil notifying: nil ifFail: [^ false]. self model perform: value. "test to make sure it works before installing"] ifFalse:[value _ Compiler new evaluate: '[',aString,']' in: nil to: nil notifying: nil ifFail: [^ false]]. self sources at: anIndex put: value. self hear:nil. ^true "tell the editor its OK"! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:42'! sources "Answer the value of sources" sources isNil ifTrue:[self sources: {[String allInstances]. [View withAllSubclasses]. [Number withAllSubclasses]}]. ^ sources! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:31'! sources: anObject "Set the value of sources" sources _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 13:34'! drawLocations | indicies | indicies _ (self counts asSortedCollection:[:a :b| a size < b size]) collect:[:each| self counts indexOf: each]. indicies do:[:anIndex| self drawLocationsForGroupNumber: anIndex]! ! !RVMMultiGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 12:40'! drawLocationsForGroupNumber: anIndex | dot coreExtent amt index rect pt dotSize realRect | coreExtent _ RVMMonitor extent. dotSize _(self boxes first width // (((self countsPerCoreForGroupNumber:anIndex) size // self boxes size)max:1))min:self boxes first width //2 max:1. dot _ Form dotOfSize: dotSize color: (self colors at: anIndex). 0 to: coreExtent x - 1 do:[:x| 0 to: coreExtent y - 1 do:[:y| amt _ (self countsPerCoreForGroupNumber:anIndex) occurrencesOf: (index _ y*8+x). rect _ (realRect _ self boxes at: index + 1) insetBy: dot offset abs. amt timesRepeat:[pt _ rect asRandomPoint. dot displayOn: self canvas at: pt clippingBox: realRect rule: Form paint fillColor:nil]]. ]! ! !RVMMultiGroupLocatorView methodsFor: 'controller access' stamp: 'ssa 11/27/2008 13:40'! defaultControllerClass ^RVMMultiGroupLocatorController! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 12:58'! on: aModel sources: someBlocksOrSelectors ^self on: aModel sources: someBlocksOrSelectors colors: nil! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 12:55'! on: aModel sources: someBlocksOrSelectors colors: someColors "(RVMMultiGroupLocatorView on: Smalltalk sources: {#keys. #values. #classNames} colors: nil) demo" "(RVMultiGroupLocatorView on: nil sources: {[String allInstances]. [Array allInstances]} colors: {Color yellow. Color green}) demo" "(RVMMultiGroupLocatorView on: nil sources: {[String allInstances]. [Array allInstances]. [Object withAllSubclasses]. [Float allInstances]} colors: nil) demo" | v | v _ self new. v model: aModel. v sources: someBlocksOrSelectors. v colors: someColors. ^v! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 14:04'! openOn: aModel sources: someBlocksOrSelectors colors: someColors "RVMMultiGroupLocatorView openOn: Smalltalk sources: {#keys. #values. #classNames} colors: nil" "RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Array allInstances]} colors: {Color yellow. Color green}" "RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Array allInstances]. [Object withAllSubclasses]. [Float allInstances]} colors: nil" | topView v ptv cbv h | topView := RVMStandardSystemView new. topView borderWidth:1. v := self on: aModel sources: someBlocksOrSelectors colors: someColors. v borderWidth:1. topView minimumSize: 150@(150 + (v sources size * 20)). topView maximumSize: 800@900. topView addSubView: v viewport:(0@0 extent: 150@150). h _ 0. 1 to: v sources size do:[:groupIndex| ptv _ RVMPluggableTextView on: v text:[v sourceSourceForGroupNumber: groupIndex] fixTemps accept:[:arg| v sourceSourceForGroupNumber: groupIndex put: arg] fixTemps. ptv borderWidth:1. cbv _ RVMColorButtonView on: v colorGetter:[v colors at: groupIndex] fixTemps colorSetter:[:arg|v colors at: groupIndex put: arg. v displayView] fixTemps. cbv borderWidth:1. topView addSubView: cbv viewport:(0@(h+150) extent:20@20). topView addSubView: ptv viewport:(20@(h+150) extent:130@20). h _ h + 20]. topView label: 'Group Locator'. topView controller open! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:35'! addAspect: aSymbol | s | self aspects add: aSymbol. self scalers add:(s _ RVMDataScaler new automatic). self pinMinAtZero ifTrue:[s pinMinAtZero]. self lastTotals add: 0. self lastAverages add:0 ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:02'! aspect "Get the value of aspect" ^self aspects at:1! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:44'! aspect: anObject "Set the value of aspect" self aspects at:1 put: anObject. self lastAverages at: 1 put: 0. self lastTotals at: 1 put:0. self topView == self ifFalse:[self topView relabel: anObject asString]. self resetScaling. self drawOnCanvas! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:22'! aspectCount ^self aspects size! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:02'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: #(bytesUseds bytesUsedReadWrites bytesUsedReadMostlys) asOrderedCollection]. ^ aspects ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:33'! aspects: anObject "Set the value of aspects" aspects _ anObject. aspects notNil ifTrue:[aspects _ aspects asOrderedCollection. aspects size > 4 ifTrue:[aspects _ aspects copyFrom: 1 to: 4]]. self lastAverages: nil. self lastTotals: nil! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:57'! colorForAspect: aSymbol ^self colors at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/21/2008 11:33'! colors "Answer the value of colors " colors isNil ifTrue:[self colors: {Color blue. Color red. Color green darker darker. Color orange darker }]. ^ colors! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:56'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! commonScale "Answer the value of commonScale" commonScale isNil ifTrue:[self commonScale: false]. ^ commonScale! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:13'! commonScale: anObject "Set the value of commonScale" commonScale _ anObject.! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 20:02'! lastAverageForAspect: aSymbol ^self lastAverages at: (self aspects indexOf: aSymbol ifAbsent:[1])! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:19'! lastAverageForAspect: aSymbol put: aValue ^self lastAverages at: (self aspects indexOf: aSymbol) put: aValue! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:41'! lastAverages "Answer the value of lastAverages" lastAverages isNil ifTrue:[self lastAverages: (Array new: self aspects size withAll: 0)asOrderedCollection]. ^ lastAverages! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:14'! lastAverages: anObject "Set the value of lastAverages" lastAverages _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:15'! lastTotalForAspect: aSymbol ^self lastTotals at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:19'! lastTotalForAspect: aSymbol put: aValue ^self lastTotals at: (self aspects indexOf: aSymbol) put: aValue! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:41'! lastTotals "Answer the value of lastTotals" lastTotals isNil ifTrue:[self lastTotals: (Array new: self aspects size withAll: 0) asOrderedCollection]. ^ lastTotals! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:14'! lastTotals: anObject "Set the value of lastTotals" lastTotals _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! pinMinAtZero "Answer the value of pinMinAtZero" pinMinAtZero isNil ifTrue:[self pinMinAtZero: false]. ^ pinMinAtZero! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! pinMinAtZero: anObject "Set the value of pinMinAtZero" pinMinAtZero _ anObject. self scalers do:[:each| each pinMinAtZero]! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:15'! removeAspect: aSymbol | index | index _ self aspects indexOf: aSymbol. self aspects remove: aSymbol. self commonScale ifFalse:[self scalers remove:(self scalers at: index)]. self lastTotals remove:(self lastTotals at: index). self lastAverages remove:(self lastAverages at: index) ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:04'! scaler "Get the default scaler" ^self scalers at:1! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 21:27'! scalerAt: anIndex "Get the default scaler" self commonScale ifTrue:[^self scalers first]. ^self scalers at: anIndex! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:13'! scalerForAspect: aSymbol self commonScale ifTrue:[^self scalers first]. ^self scalers at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:59'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: OrderedCollection new. self aspects do:[:a| scalers add: RVMDataScaler new automatic]]. ^ scalers! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:56'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:39'! drawBottomLeftLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height -3. aspectLabel displayOn: self canvas at: box bottomLeft - (0 @aspectLabel height). minLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y -( height*2) )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height*3)+3)) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height *4)+6)) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height *5)+9)) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:36'! drawBottomRightLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height -3. aspectLabel displayOn: self canvas at: box bottomRight - (aspectLabel extent). minLabel displayOn: self canvas at: ((box bottomRight x - minLabel width)@(box bottomRight y -( height*2) )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box bottomRight x - maxLabel width)@(box bottomRight y - (height*3)+3)) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box bottomRight x - totalLabel width)@(box bottomRight y - (height *4)+6)) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box bottomRight x - avgLabel width)@(box bottomRight y - (height *5)+9)) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 14:56'! drawLabelsOnCanvas | quads | quads _ #(drawTopLeftLabelsOnCanvasForAspect: drawTopRightLabelsOnCanvasForAspect: drawBottomRightLabelsOnCanvasForAspect: drawBottomLeftLabelsOnCanvasForAspect:). 1 to: self aspects size do:[:index| self perform: (quads at: index) with: (self aspects at: index)]! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:13'! drawTopLeftLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height - 6. aspectLabel displayOn: self canvas at: (0@-4). minLabel displayOn: self canvas at: ((0)@(box topLeft y + height )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((0)@(box topLeft y + (height*2))) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((0)@(box topLeft y + (height *3))) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((0)@(box topLeft y + (height *4))) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:10'! drawTopRightLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height - 6. aspectLabel displayOn: self canvas at: box topRight - (aspectLabel width @4). minLabel displayOn: self canvas at: ((box topRight x - minLabel width)@(box topRight y + height )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box topRight x - maxLabel width)@(box topRight y + (height*2))) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box topRight x - totalLabel width)@(box topRight y + (height *3))) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box topRight x - avgLabel width)@(box topRight y + (height *4))) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 16:04'! drawWeb self aspects do:[:aSymbol| self placeSpokePensForAspect: aSymbol. self webPen color: (self colorForAspect: aSymbol). self webPen combinationRule: Form paint. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up] ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:37'! placeSpokePensForAspect: aSymbol | data scaledDatum tot offset | data _ RVMMonitor lastSample perform: aSymbol. offset _ ((self aspects indexOf: aSymbol) - 1)*4/5. tot _ 0. self spokePens size = data size ifFalse: [self resetAfterCoreCountChange]. data with: self spokePens do:[:datum :pen| tot _ tot + datum. pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalerForAspect: aSymbol) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset]. self lastTotalForAspect: aSymbol put: tot. self lastAverageForAspect: aSymbol put: tot / data size! ! !RVMMultiKiviatView methodsFor: 'scaling' stamp: 'ssa 10/7/2008 19:48'! resetScaling | data tot | self scalers do:[:s| s resetScaling]. self aspects do:[:aSymbol| data _ RVMMonitor lastSample perform: aSymbol. tot _ 0. data do:[:datum | tot _ tot + datum. (self scalerForAspect: aSymbol) scale: datum]. self lastTotalForAspect: aSymbol put: tot. self lastAverageForAspect: aSymbol put: tot / data size]! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 15:38'! example "RVMMultiKiviatView example" self openOnAspects: #(bytesUsedReadMostlys bytesUsedReadWrites bytesUseds bytecodeCounts)! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 4/3/2009 17:51'! exampleBytecodesAndProcessesRunning "RVMMultiKiviatView exampleBytecodesAndProcessesRunning" self openOnAspects: #(bytecodeCounts runningProcessCountsPerCore ) pinAllScalesAtZero: false useCommonScale: false! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 16:01'! exampleBytesUsedTrioCommonPinned "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" self openOnAspects: #(bytesUsedReadWrites bytesUsedReadMostlys bytesUseds ) pinAllScalesAtZero: true useCommonScale: true! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 16:01'! exampleBytesUsedTrioPinned "RVMMultiKiviatView exampleBytesUsedTrioPinned" self openOnAspects: #(bytesUsedReadWrites bytesUsedReadMostlys bytesUseds ) pinAllScalesAtZero: true! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 18:29'! exampleSingle "RVMMultiKiviatView exampleSingle" self openOnAspects: #(bytecodeCounts) pinAllScalesAtZero: false useCommonScale: false titled: 'bytecodeCounts' ! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 15:54'! openOnAspects: someAspects "RVMMultiKiviatView example" self openOnAspects: someAspects pinAllScalesAtZero: false! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 16:12'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean "RVMMultiKiviatView exampleBytesUsedTrioPinned" self openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: false! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 16:09'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" | | self openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale titled: 'Multiaspect Kiviat'! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 19:24'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale titled: aString "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" | topView v label | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@250. topView maximumSize: 600@500. v := self new. v borderWidth:1. v aspects: someAspects. v commonScale: commonScale. v pinMinAtZero: aBoolean. topView addSubView: v. label _ aString,(aBoolean ifTrue:[' (pinned)']ifFalse:['']),(commonScale ifTrue:[' (uniscale)']ifFalse:['']). topView label: label. topView controller open! ! !RVMObjectCoordinateView methodsFor: 'listening' stamp: 'ssa 11/15/2008 23:43'! hear: something self displayView! ! !RVMObjectCoordinateView methodsFor: 'listening' stamp: 'ssa 11/15/2008 23:44'! update self displayView! ! !RVMObjectCoordinateView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:15'! on: anRVMObjectCoordinate "RVMObjectCoordinateView openOn: nil asObjectCoordinate " | mutabilityView readWriteButton readMostlyButton activityView passButton holdButton coreIndexView coordView tileCoordView | mutabilityView _ RVMView new. readWriteButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'readWrite' checkState: #isReadWrite whenChecked: #makeReadWrite whenUnchecked: [] monitor: true. readMostlyButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'readMostly' checkState: #isReadMostly whenChecked: #makeReadMostly whenUnchecked: [] monitor: true. mutabilityView addSubView: readWriteButton in:(0@0 extent: 1@0.5) borderWidth:0. mutabilityView addSubView: readMostlyButton in:(0@0.5 extent: 1@0.5) borderWidth:0. activityView _ RVMView new.. passButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'pass baton' checkState: #isActive whenChecked: #makeActive whenUnchecked: [] monitor: true. holdButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'keep baton' checkState: #isPassive whenChecked: #makePassive whenUnchecked: [] monitor: true. activityView addSubView: passButton in:(0@0 extent: 1@0.5) borderWidth:0. activityView addSubView: holdButton in:(0@0.5 extent: 1@0.5) borderWidth:0. tileCoordView _ RVMGridLocationView on: anRVMObjectCoordinate pointGetter: #coreCoordinate pointSetter: #moveToCoordinate: extentGetter: [RVMMonitor extent]. coreIndexView _ RVMCoreIndexView on: anRVMObjectCoordinate getCoreIndex:#coreIndex setCoreIndex: #moveToCore: getAvailableIndicies: [RVMMonitor coreCount]. coordView _ self new. coordView addSubView: mutabilityView in:(0@0 extent: 1/3@1) borderWidth:1. coordView addSubView: activityView in:((1/3)@0 extent: 1/3@1) borderWidth:1. coordView addSubView: tileCoordView in:((2/3)@0 extent: 1/6@1) borderWidth:1. coordView addSubView: coreIndexView in:((5/6)@0 extent: 1/6@1) borderWidth:1. ^coordView ! ! !RVMObjectCoordinateView class methodsFor: 'instance creation' stamp: 'ssa 11/15/2008 15:52'! openOn: anRVMObjectCoordinate "RVMObjectCoordinateView openOn: nil asObjectCoordinate" "Add me to a system view and open me on the desktop" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@50. topView addSubView: (self on: anRVMObjectCoordinate) . topView label: 'Locating: ',anRVMObjectCoordinate object printString. topView controller open! ! !RVMRadioButtonView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:19'! buildCheckedBoxForm "Answer the check(ed) circle " | box aForm aCircle dot | box _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 2@2. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: box. dot _ Form dotOfSize: 10. dot displayOn: box at: box boundingBox center clippingBox: box boundingBox rule: Form paint fillColor:nil. ^box! ! !RVMRadioButtonView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:19'! buildUncheckedBoxForm "Answer the uncheck(ed) circle " | box aForm aCircle | box _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 2@2. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: box. ^box! ! !RVMRadioButtonView methodsFor: 'action' stamp: 'ssa 11/16/2008 01:26'! performAction "I've been clicked, switch state and act" | others | self checked: true. self performCheckAction. others _ self superView subViewsSatisfying: [:each| each ~~ self and:[each class == self class]]. others do:[:each| each checked: false. each performUncheckAction. each displayView]. self displayView ! ! !RVMRadioButtonView class methodsFor: 'examples' stamp: 'ssa 10/18/2008 23:34'! example "RVMRadioButtonView example" super example! ! !RVMRadioButtonView class methodsFor: 'examples' stamp: 'ssa 5/12/2010 10:15'! exampleRecording "RVMRadioButtonView exampleRecording" | topView offRadio loopRadio subViewCount longRadio fileRadio | topView := RVMStandardSystemView new . topView borderWidth:1. RVMRadioButtonView testState:#(true false false false false). offRadio _ RVMRadioButtonView on: self label: 'off' checkState: [RVMMonitor recordingMode = #off] whenChecked: [RVMMonitor recordingMode: #off] whenUnchecked: [] monitor: true. loopRadio _ RVMRadioButtonView on: self label: 'record last ',RVMMonitor sampleLimit printString,' samples' checkState: [RVMMonitor recordingMode = #loop] whenChecked: [RVMMonitor recordingMode: #loop] whenUnchecked: [] monitor: true. longRadio _ RVMRadioButtonView on: self label: 'record all samples' checkState: [RVMMonitor recordingMode = #long] whenChecked: [RVMMonitor recordingMode: #long] whenUnchecked: [] monitor: true. fileRadio _ RVMRadioButtonView on: self label: 'record all samples to a file' checkState: [RVMMonitor recordingMode = #file] whenChecked: [RVMMonitor recordingMode: #file] whenUnchecked: [] monitor: true. topView addSubView: offRadio. topView addSubView: loopRadio below: offRadio. topView addSubView: longRadio below: loopRadio. topView addSubView: fileRadio below: longRadio. topView label: 'Recording Options'. subViewCount _ topView subViews size. topView minimumSize: 100@(subViewCount*28). topView maximumSize: 200@topView minimumSize y. topView controller open! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 22:02'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 22:02'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! currentAspect "Answer the value of currentAspect" ^self currentTrace aspect! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:17'! currentAspectLabel "Answer a good label for this aspect" ^self currentTrace aspectLabel! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:12'! currentColor "Answer the value of currentColor" ^self currentTrace color! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:12'! currentTrace "Answer the value of currentTrace" currentTrace isNil ifTrue:[self currentTrace: self stripChart traces first]. ^ currentTrace! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! currentTrace: anObject "Set the value of currentTrace" currentTrace _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:10'! stripChart "Answer the value of stripChart" stripChart isNil ifTrue:[self stripChart: (RVMStripChartView trace:RVMCoreAspectTrace exampleInstance)]. ^ stripChart! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! stripChart: anObject "Set the value of stripChart" stripChart _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! uiHolder "Answer the value of uiHolder" uiHolder isNil ifTrue:[self uiHolder: nil]. ^ uiHolder! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! uiHolder: anObject "Set the value of uiHolder" uiHolder _ anObject! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 21:59'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 22:05'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. adjustIcon _ adjustIcon scaledToSize: adjustIcon extent * 0.75. origin _ self canvas boundingBox center - adjustIcon boundingBox extent - (0@6). adjustIcon displayOn: self canvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 22:03'! drawCanvas | scaler maxLabel minLabel midLabel box ticLength ticOffset topY midY bottomY leftX rightX margin aspectLabel | self eraseCanvas. scaler _ self currentTrace scaler. aspectLabel _ self currentAspectLabel asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0. maxLabel _ scaler max printShowingMax3Digits asDisplayText. minLabel _ scaler min printShowingMax3Digits asDisplayText. midLabel _ (scaler range / 2 + scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: self currentColor backgroundColor: Color transparent. midLabel foregroundColor: self currentColor backgroundColor: Color transparent. minLabel foregroundColor: self currentColor backgroundColor: Color transparent. box _ self canvas boundingBox. ticLength _ 4. ticOffset _ maxLabel height // 2. margin _ 2. aspectLabel align: aspectLabel boundingBox leftCenter with: box leftCenter. aspectLabel displayOn: self canvas at: 0@0 clippingBox: box. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. topY _ box topRight y . midY _ box center y. bottomY _ box bottomRight y - 2. leftX _ box topRight x - ticLength - margin. rightX _ box corner x - margin. self canvas fill: (rightX - 1@topY corner: rightX@bottomY) fillColor: self currentColor. self canvas fill: (leftX@topY extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@(topY+midY//2) extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@midY extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@(midY+bottomY//2) extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@bottomY extent: ticLength@1) fillColor: self currentColor. self drawAdjustScaleIcon! ! !RVMStripChartScaleView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:24'! newFrame self canvas: nil. self extent: self insetDisplayBox extent. self drawCanvas. self displayView! ! !RVMStripChartScaleView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:04'! defaultControllerClass ^RVMStripChartScaleController! ! !RVMStripChartScaleView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:05'! hear: something "Update my traces and redisplay" self drawCanvas. self displayView! ! !RVMStripChartScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:22'! example "RVMStripChartScaleView example" self new demo! ! !RVMStripChartScaleView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:58'! stripChart: aStripChart uiHolder: aUIHolder | view | view _ self new. view stripChart: aStripChart. view uiHolder: aUIHolder. ^view! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/2/2008 19:21'! drawCanvas self eraseCanvas. self traces do:[:trace| trace drawOn: self canvas]! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/3/2008 23:13'! drawFastOnCanvas | box | self traces isEmpty ifTrue:[^self canvas fillWhite]. self traces first isFull ifTrue:[self canvas displayOn: self canvas at: -2@0]. box _ self canvas boundingBox. self canvas fillWhite: (box topRight - (2@0) extent: 2@ box height). self traces do:[:trace| trace drawLastOn: self canvas ]! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/2/2008 19:21'! redrawCanvas self eraseCanvas. self traces do:[:trace| trace redrawOn: self canvas]! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:26'! defaultOffset ^self canvas width negated@ 0! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 16:09'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 15]. ^ rescaleCounter ! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 15:21'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! traces "Answer the value of traces" traces isNil ifTrue:[self traces: OrderedCollection new]. ^ traces! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! traces: anObject "Set the value of traces" traces _ anObject! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/8/2008 18:34'! firstFrame "First time framed, set my canvas to match my view" self canvas: nil. self extent: self insetDisplayBox extent - (0@2). self traces do:[:trace| trace resizeTo: self extent x //2]. self drawCanvas. ! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/3/2008 23:23'! newFrame "My frame has changed. Reset my canvas to my new size and redraw" self canvas: nil. self extent: self insetDisplayBox extent - (0@2). self traces do:[:trace| trace resizeTo: self extent x //2]. self drawCanvas. self displayView! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/4/2008 08:28'! rebuildAll | view subGroups width scaleView scaleWidth topView extraRows | topView _ self topView. (topView allSubViews copyWithout: self) do:[:v| v release]. topView subViews: (OrderedCollection with: self). topView borderWidth:1. width _ 400. view _ self . scaleWidth _ 60. subGroups _ RVMTraceUIHolderView forStripChart: view. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. extraRows _ self traces size = 1 ifTrue:[0]ifFalse:[subGroups subViews size]. topView minimumSize: width@(100+(extraRows * 20)). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). extraRows > 0 ifTrue:[topView addSubView: subGroups viewport: (0@100 extent: width@(extraRows* 20))]. topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. subGroups borderWidth:0. topView reframeTo:(topView displayBox origin - (0@(topView labelHeight -2) ) extent: topView minimumSize + (0@topView labelHeight)). ScheduledControllers restore: topView windowBox. ! ! !RVMStripChartView methodsFor: 'listening' stamp: 'ssa 11/11/2008 22:38'! hear: something "Update my traces and redisplay" | outOfRangeTraces | self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self traces do:[:trace| trace scaler automaticScaling ifTrue:[trace rescale]]]. self traces do:[:trace| trace addData]. outOfRangeTraces _ self traces select:[:trace| trace scaler outOfRangeDetected] . outOfRangeTraces isEmpty ifTrue:[self drawFastOnCanvas. ^self displayView]. self redrawCanvas. outOfRangeTraces do:[:trace| trace scaler resetOutOfRangeDetector]. self displayView! ! !RVMStripChartView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:38'! defaultControllerClass ^RVMStripChartController! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/4/2008 08:18'! addCoreTraceForAspect: aSymbol coreIndex: anInteger | traceSize existingColors traceColor newTrace | traceSize _ self extent x //2. existingColors _ self traces collect:[:trace| trace color]. [traceColor _ Color random darker. self traces isEmpty or:[ (existingColors collect:[:color| color diff: traceColor]) asSortedCollection last < 0.7]] whileFalse. newTrace _ RVMCoreAspectTrace coreIndex: anInteger aspect: aSymbol size: traceSize color: traceColor. self traces add: newTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/3/2008 23:08'! addSystemTraceForAspect: aSymbol | traceSize existingColors traceColor newTrace | traceSize _ self extent x //2. existingColors _ self traces collect:[:trace| trace color]. [traceColor _ Color random darker. self traces isEmpty or:[(existingColors collect:[:color| color diff: traceColor]) asSortedCollection last < 0.7]] whileFalse. newTrace _ RVMAspectTrace aspect: aSymbol size: traceSize color: traceColor. self traces add: newTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/3/2008 22:59'! removeAllTraces self traces removeAll: self traces copy. ! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 1/1/1970 00:51'! removeTrace: aTrace self traces remove: aTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 1/1/1970 00:51'! removeTraces: someTraces self traces removeAll: someTraces. self newFrame! ! !RVMStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin + self offset - (0@2 ) clippingBox: self insetDisplayBox. ! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! openOnTrace: aTrace "RVMStripChartView openOnTrace: RVMAspectTrace exampleInstance" self openOnTrace: aTrace titled:'Multi-aspect Stripchart' ! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! openOnTrace: aTrace titled: aString | topView view subGroups width scaleView scaleWidth | topView _ RVMStandardSystemView new. topView label: aString. topView borderWidth:1. width _ 400. view _ self traces: (OrderedCollection with: aTrace). scaleWidth _ 60. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. topView minimumSize: width@100. topView addSubView: view viewport: (scaleWidth@0 extent: width-scaleWidth@100). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. topView controller open! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:16'! openOnTraces: someTraces "RVMCoreAspectTrace exampleView3" self openOnTraces: someTraces titled: 'Multi-aspect Stripchart'! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 10/8/2008 19:09'! openOnTraces: someTraces titled: aString | topView view subGroups width scaleView scaleWidth | someTraces size = 1 ifTrue:[self openOnTrace: someTraces first titled: aString]. topView _ RVMStandardSystemView new. topView label: aString. topView borderWidth:1. someTraces size > 2 ifTrue:[width _ 400]ifFalse:[width _ someTraces size + 1 * 150 ]. view _ self traces: someTraces. scaleWidth _ 60. subGroups _ RVMTraceUIHolderView forStripChart: view. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. topView minimumSize: width@(100+(subGroups subViews size + 1 * 20)). topView addSubView: view viewport: (scaleWidth@0 extent: width-scaleWidth@100). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). topView addSubView: subGroups viewport: (0@100 extent: width@(subGroups subViews size* 20)). topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. subGroups borderWidth:0. topView controller open! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:10'! trace: aTrace ^self traces:(OrderedCollection with: aTrace)! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:09'! traces: someTraces | view | view _ self new. view traces: someTraces. ^view! ! !RVMStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:09'! example "RVMStripChartView example" self openOnTrace: RVMCoreAspectTrace exampleInstance! ! !RVMTileGridView methodsFor: 'autoscaling' stamp: 'ssa 10/1/2008 09:09'! autoscale "Adjust my scale so that it fits the data." self minValue: self data min. self maxValue: self data max. self scale:nil! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:34'! hear: someObject self sample: nil. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 10/3/2008 19:33'! newFrame self canvas: nil. self displayView! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 8/19/2008 18:25'! unlock super unlock. self tiles:nil ! ! !RVMTileGridView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:30'! defaultControllerClass ^RVMTileGridController! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:34'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #bytecodesPerSecond]. ^aspect! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! aspect: anObject "Set the value of aspect" aspect := anObject. self topView == self ifFalse:[self topView relabel: self typeLabel,anObject]! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 14:27'! aspects ^self sample aspects! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:46'! canvas canvas isNil ifTrue:[self canvas: (Form fromDisplay: self insetDisplayBox) fillWhite]. ^canvas ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 9/24/2008 17:45'! canvas: aForm canvas _ aForm! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: self makeColors]. ^colors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! colors: anObject "Set the value of colors" colors := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 09:12'! data "Answer the value of data" data isNil ifTrue:[ (self sample respondsTo: self aspect) ifFalse: [^ Array new: 0]. self data: (self sample perform: self aspect)]. ^data! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:29'! data: anObject "Set the value of data" data := anObject. data ifNotNil:[(data isKindOf: Collection) ifFalse:[data _ Array with: data]]. data notNil ifTrue:[self autoscale]! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 12:44'! gridExtent "Answer the width and height of the grid of tiles that is appropriate for the layout of cores we have" | total | total _ self data size. total = 1 ifTrue:[^1@1]. total < 4 ifTrue:[^1@ total]. total = 4 ifTrue:[^2@ 2]. total < 16 ifTrue:[^4@ (total/4+0.5)rounded]. "otherwise assume a Tilera 8x8 grid" ^self sample groupStats width @ self sample groupStats height! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! makeColors ^(Color hotColdShades: self numberOfColors) reversed! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:22'! maxValue "Answer the value of maxValue" maxValue isNil ifTrue:[self maxValue: 5000]. ^maxValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! maxValue: anObject "Set the value of maxValue" maxValue := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:22'! minValue "Answer the value of minValue" minValue isNil ifTrue:[self minValue: 0]. ^minValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! minValue: anObject "Set the value of minValue" minValue := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:26'! numberOfColors "Answer the value of numberOfColors" numberOfColors isNil ifTrue:[self numberOfColors: 100]. ^numberOfColors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 19:50'! numberOfColors: anObject "Set the value of numberOfColors" numberOfColors := anObject rounded. self colors:nil. self changed:#numberOfColors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:25'! sample "Answer the value of sample" sample isNil ifTrue:[self sample: RVMMonitor lastSample]. ^sample! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:49'! sample: anObject "Set the value of sample" sample := anObject.. self data:nil. ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 10:04'! scale "Answer the value of scale" scale isNil ifTrue:[self scale: self maxValue / self numberOfColors asFloat]. ^scale ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:50'! scale: anObject "Set the value of scale" scale := anObject. scale = 0 ifTrue: [scale := 0.01]. self changed:#scale. ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 09:06'! scaler "Answer a scaler for me as needed" ^RVMDataScaler aspect: self aspect min: self minValue max: self maxValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/19/2008 18:09'! showProcessState "Answer the value of showProcessState" showProcessState isNil ifTrue:[self showProcessState: false]. ^showProcessState! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/19/2008 18:08'! showProcessState: anObject "Set the value of showProcessState" showProcessState := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:13'! tiles "Answer the value of tiles" tiles isNil ifTrue:[self tiles: (self insetDisplayBox subDivideRoundedBy: (self data size > 1 ifTrue:[self sample groupStats width @ self sample groupStats height]ifFalse:[1@1]))]. ^tiles! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 11:56'! tiles: anObject "Set the value of tiles" tiles := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:58'! typeLabel ^'Rel: '! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 15:47'! displayView | color colorIndex | self okToDisplay ifFalse:[^self]. self uncache. self sample: nil. self canvas fillColor: self tileBorderColor. 1 to: self tiles size do:[:index| color := index > self data size ifFalse:[ colorIndex _ (((self data at: index) / self scale)min: self numberOfColors max: 1) rounded. self colors at: colorIndex] ifTrue:[Color black]. self canvas fill: (((self tiles at: index) translateBy: self insetDisplayBox origin negated)insetBy:1@1) fillColor: color . self tiles size = 1 ifTrue:[(self data first printString asDisplayText alignedTo:#center)displayOn: self canvas at: self canvas boundingBox center]. ]. self canvas displayAt: self insetDisplayBox origin ! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:41'! redrawOnCanvas "do nothing"! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:42'! tileBorderColor ^Color darkGray! ! !RVMTileGridScalerView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | color | self okToDisplay ifFalse: [^ self]. self uncache. self sample: nil. self scaler resetObservations. self canvas fillColor: self tileBorderColor. 1 to: self tiles size do: [:index | color := index > self data size ifTrue: [Color black] ifFalse: [self colors at: ((self scaler scale: (self data at: index))min: 100 max:1)]. self canvas fill: (((self tiles at: index) translateBy: self insetDisplayBox origin negated) insetBy: 1 @ 1) fillColor: color. self tiles size = 1 ifTrue: [(self data first printString asDisplayText alignedTo: #center) displayOn: self canvas at: self canvas boundingBox center]]. self canvas displayAt: self insetDisplayBox origin! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:07'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:02'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 30]. ^ rescaleCounter! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:03'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject ! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:46'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^ scaler! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:45'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! typeLabel ^'Abs: '! ! !RVMTileGridScalerView methodsFor: 'listening' stamp: 'ssa 11/4/2008 15:37'! hear: someObject "self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self scaler resetScaling]. " self sample: nil. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileGridView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:17'! example "RVMTileGridView example" | topView v scaleWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. topView minimumSize: 200+scaleWidth@200. topView maximumSize: 460@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: 200@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: false) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileGridView class methodsFor: 'instance creation' stamp: 'ssa 8/15/2008 16:36'! aspect: aMessageSelector numberOfColors: numColors minValue: minValue maxValue: maxValue "Answer a new view with these params" | view | view := self new. view aspect: aMessageSelector; numberOfColors: numColors; minValue: minValue; maxValue: maxValue. ^view! ! !RVMTileGridView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:19'! adjustScaler ^false! ! !RVMTileGridScalerView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:15'! example "RVMTileGridScalerView example" | topView v scaleWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. topView minimumSize: 200+scaleWidth@200. topView maximumSize: 460@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: 200@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: true) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin clippingBox: self insetDisplayBox.! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 20:47'! drawOnCanvas | color colorIndex | [#draw print]. self canvas displayOn: self canvas at: self boxSize negated @ 0. 1 to: self count do: [:index | colorIndex := ((self data at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated) fillColor: color]! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:38'! eraseStrip self previousData:nil. self canvas fillWhite. self displayView! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 20:27'! redrawOnCanvas | color colorIndex x | #redraw print. self canvas fillWhite. x _ 0. self previousData do:[:oldData| 1 to: self count do: [:index | colorIndex := ((oldData at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated - (x@0)) fillColor: color]. x _ x + self boxSize]! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:37'! aspect: anObject "Set the value of aspect" super aspect: anObject. self eraseStrip! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 08:48'! box "Answer the value of box" box isNil ifTrue:[self box: (self insetDisplayBox topRight - (self boxSize @ 0) extent: self boxSize @ self insetDisplayBox height)]. ^box! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:02'! box: anObject "Set the value of box" box := anObject. self boxes:nil. self boxSize: nil! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:24'! boxSize "Answer the value of boxSize" boxSize isNil ifTrue:[self boxSize: ((self insetDisplayBox height // self count max:1)min:4)]. ^boxSize! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! boxSize: anObject "Set the value of boxSize" boxSize := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 4/20/2010 10:23'! boxes "Answer the value of boxes" boxes isNil ifTrue:[self boxes: (self box subDivideRoundedBy: 1@ self count)]. ^boxes! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! boxes: anObject "Set the value of boxes" boxes := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/9/2008 11:42'! chart "Answer the value of chart" chart isNil ifTrue:[self chart: (Form fromDisplay: self insetDisplayBox)]. ^chart! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:33'! chart: anObject "Set the value of chart" chart := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:32'! count "Answer the value of count" count isNil ifTrue:[self count: self data size]. ^count! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! count: anObject "Set the value of count" count := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:36'! data: someData super data: someData. someData notNil ifTrue:[self previousData add: someData]! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! previousData "Answer the value of previousData" previousData isNil ifTrue:[self previousData: (RVMCircularCollection new: self visibleSampleCount)]. ^previousData! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:28'! previousData: anObject "Set the value of previousData" previousData := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:41'! scale: aValue "Set the value of scale" super scale: aValue. "aValue isNil ifFalse:[self redrawOnCanvas]"! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 17:22'! unlock super unlock. self box:nil ! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! visibleSampleCount "How many samples (columns of boxes) can I currently display?" ^self chart boundingBox width // self boxSize! ! !RVMTileStripChartView methodsFor: 'updating' stamp: 'ssa 10/3/2008 20:34'! hear: someObject self sample: nil. self drawOnCanvas. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileStripChartView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:10'! newFrame super newFrame. self canvas:nil. self box: nil! ! !RVMTileStripChartView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:30'! defaultControllerClass ^RVMTileStripChartController! ! !RVMTileStripChartView methodsFor: 'scaling' stamp: 'ssa 10/3/2008 22:26'! rescale "do nothing"! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 15:21'! drawOnCanvas | color colorIndex | 1 to: self count do: [:index | colorIndex := ((self data at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0. ! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:37'! eraseStrip self resetScannerLocation. super eraseStrip.! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:02'! nextScannerLocation "Answer the next location for the scanner" self scannerLocation: self scannerLocation + self boxSize. ^self scannerLocation! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:41'! redrawOnCanvas | color colorIndex | self canvas fillWhite. self resetScannerLocation. self previousData do:[:oldData| 1 to: self count do: [:index | colorIndex := ((oldData at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0]! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 15:20'! box "Answer the value of box" box isNil ifTrue:[self box: (0@0 extent: self boxSize @ self scanner boundingBox height)]. ^box! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:37'! resetScannerLocation scannerLocation _ nil! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:27'! scanner "Answer the value of scanner" scanner isNil ifTrue:[self scanner: (ColorForm extent: self boxSize * 3 @self canvas height depth:8)]. ^ scanner! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:31'! scanner: anObject "Set the value of scanner" scanner _ anObject. scanner fillWhite. scanner border: scanner boundingBox width:1 fillColor:Color black. '< < < < < < < < < < < < < < < <' asParagraph asForm displayOn: scanner at: scanner boundingBox topCenter - (1@0). scanner border: scanner boundingBox width:1 ! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 15:24'! scannerLocation "Answer the value of scannerLocation" scannerLocation isNil ifTrue:[self scannerLocation: self boxSize negated]. ^ scannerLocation! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:15'! scannerLocation: anInteger "Set the value of scannerLocation" anInteger > self canvas boundingBox width ifTrue:[scannerLocation _ self boxSize negated] ifFalse:[scannerLocation _ anInteger]! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:49'! typeLabel ^'RelScan: '! ! !RVMAbsScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:29'! drawOnCanvas | color | 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(self data at: index)) min: self numberOfColors max:1). self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0. ! ! !RVMAbsScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:41'! redrawOnCanvas | color | self canvas fillWhite. self resetScannerLocation. self previousData do:[:oldData| 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(oldData at: index)) min: self numberOfColors max:1). self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0]! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:23'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:26'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^scaler! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:23'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:49'! typeLabel ^'AbsScan: '! ! !RVMAbsScanningStripChartView methodsFor: 'scaling' stamp: 'ssa 10/28/2008 20:47'! rescale "Reset the scaler and pass the previous data thorugh it to find the min/max. Then redraw" self scaler resetScaling. self previousData do:[:dats| dats do:[:d| scaler scale: d]]. self scaler resetOutOfRangeDetector. self topView newFrame. self redrawOnCanvas! ! !RVMTileStripChartScalerView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 21:02'! drawOnCanvas | color | self canvas displayOn: self canvas at: self boxSize negated @0. 1 to: self count do:[:index| color := self colors at: ((self scaler scale:(self data at: index)) min: self numberOfColors max:1). self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated )fillColor: color]. ! ! !RVMTileStripChartScalerView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:51'! redrawOnCanvas | color x | [#redrawScaler print]. self canvas fillWhite. x _ 0. self previousData asOrderedCollection reversed do:[:oldData| 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(oldData at: index)) min: self numberOfColors max:1). self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated - (x@0)) fillColor: color]. x _ x + self boxSize]! ! !RVMTileStripChartScalerView methodsFor: 'scaling' stamp: 'ssa 10/6/2008 16:30'! rescale "Reset the scaler and pass the previous data thorugh it to find the min/max. Then redraw" [#rescaling print]. self scaler resetScaling. self previousData do:[:dats| dats do:[:d| scaler scale: d]]. self scaler resetOutOfRangeDetector. self redrawOnCanvas! ! !RVMTileStripChartScalerView methodsFor: 'listening' stamp: 'ssa 11/4/2008 19:50'! hear: someObject self sample: nil. "self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self rescale]. self scaler outOfRangeDetected ifTrue:[[('out of range = ',self scaler lastObserved printString) print]. self rescale]." self drawOnCanvas. self topView isCollapsed ifFalse:[self displayView]. ! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:06'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:51'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 1]. ^ rescaleCounter! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 22:09'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject ! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:04'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^ scaler! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:03'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:16'! typeLabel ^'Abs: '! ! !RVMTileStripChartView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:18'! example "RVMTileStripChartView example" | topView v scaleWidth stripWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. stripWidth _ 200. topView minimumSize: stripWidth+scaleWidth@200. topView maximumSize: 1000@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: stripWidth@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: self adjustScaler) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:16'! example1 "RVMTileStripChartView example1" self openOnAspect: #bytesUseds! ! !RVMTileStripChartView class methodsFor: 'scheduling' stamp: 'ssa 1/1/1970 00:16'! openOnAspect: aSymbol "Open a new monitor on this aspect" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 200@200. topView maximumSize: 600@400. topView insideColor: Color white. v := self new. v aspect: aSymbol. topView addSubView: v. topView label: v typeLabel,aSymbol. topView controller open! ! !RVMAbsScanningStripChartView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:19'! adjustScaler ^true! ! !RVMTileStripChartScalerView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:20'! adjustScaler ^true! ! !RVMTraceUIHolderView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! stripChart "Answer the value of stripChart" ^ stripChart! ! !RVMTraceUIHolderView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! stripChart: anObject "Set the value of stripChart" stripChart _ anObject! ! !RVMTraceUIHolderView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:39'! defaultControllerClass ^RVMTraceUIHolderController! ! !RVMTraceUIHolderView methodsFor: 'subView inserting' stamp: 'ssa 1/1/1970 00:19'! myControls "Add the button to use to modify the number of traces my stripchart uses" | addTraceButton removeTraceButton holder | addTraceButton _ RVMButtonView label:'+' action:[self addTrace]. removeTraceButton _ RVMButtonView label:'-' action:[self removeTrace]. holder _ RVMView new. holder addSubView: addTraceButton. holder addSubView: removeTraceButton toRightOf: addTraceButton. ^holder! ! !RVMTraceUIHolderView methodsFor: 'subView inserting' stamp: 'ssa 1/1/1970 00:15'! rebuildSubViews | allSubs lastGroup holder last | allSubs _ self stripChart traces collect:[:trace| trace allView]. lastGroup _ nil. allSubs groupsOfNoMoreThan: 3 atATimeDo:[:group| holder _ RVMView new. last _ nil. group do:[:v| holder addSubView: v toRightOf: last. last _ v]. self addSubView:holder below: lastGroup. lastGroup _ holder]. ! ! !RVMTraceUIHolderView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:55'! forStripChart: aViewWithTraces | v | v _ self new. v stripChart: aViewWithTraces. v rebuildSubViews. ^v! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 11:00'! changeValueBy: delta self value: self value + delta. self displayView.! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 20:57'! label "Answer the value of label" label isNil ifTrue:[self label: '']. ^ label! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 20:57'! label: anObject "Set the value of label" label _ anObject! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! value "Answer the value of value" | temp | temp _ self valueGetter isSymbol ifTrue:[self model perform: self valueGetter] ifFalse:[self valueGetter value]. ^temp isFraction ifTrue:[temp asFloat] ifFalse:[temp]! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:28'! value: anObject "Set the value of value" self valueSetter isSymbol ifTrue:[model perform: self valueSetter with: anObject] ifFalse:[self valueSetter value: anObject]! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:37'! valueGetter "Answer the value of valueGetter" valueGetter isNil ifTrue:[self valueGetter: [100 atRandom]]. ^ valueGetter! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:36'! valueGetter: anObject "Set the value of valueGetter" valueGetter _ anObject! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:38'! valueSetter "Answer the value of valueSetter" valueSetter isNil ifTrue:[self valueSetter: [:v| v print]]. ^ valueSetter! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:36'! valueSetter: anObject "Set the value of valueSetter" valueSetter _ anObject! ! !RVMValueView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | label1 labelForm | self okToDisplay ifFalse:[^self]. self uncache. label1 _ ' ',self label,' ',self value printString. labelForm _ label1 asDisplayText. Display fill: self insetDisplayBox fillColor: Color white. labelForm displayOn: Display at: self insetDisplayBox leftCenter - labelForm boundingBox leftCenter clippingBox: self insetDisplayBox. "(self controller isKindOf: NoController) ifFalse:[ Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated.]" ! ! !RVMValueView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 20:35'! defaultControllerClass ^RVMValueController! ! !RVMValueView methodsFor: 'listening' stamp: 'ssa 11/4/2008 19:37'! hear: something self displayView! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:27'! closedPadlock ^((ColorForm extent: 14@16 depth: 8 fromArray: #( 0 2511181205 2912223232 0 197 2097152000 7456089 0 51549 9817545 2908582317 0 7456000 2915368960 2915893445 1895825408 9276765 3445161984 13473173 2365587456 9276813 3439329280 13473173 2365587456 7712141 3036678400 12167597 1962934272 1701414249 2171169129 1770357121 2237988864 2634354961 286331153 286331153 228392960 2702252313 421075225 286857497 834732032 3625525537 555819297 555819321 1103167488 4011402533 623191333 623984969 905641984 4012455225 892942657 1094797621 1374617600 3693688117 892679497 893995345 1241186304 4012193065 1094795573 1363752273 1375404032 3504924904 3253266652 3705461980 3704619008) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.0 0.0 0.0) ))! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:03'! displayView self box. self okToDisplay ifFalse:[^self]. self uncache. ((self lastValue = self value and:[self lastOp = self operation])and:[self lastLocked = self locked])ifFalse:[ self drawOnCanvas]. self canvas displayAt: self insetDisplayBox origin ! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:03'! drawOnCanvas | lock lt vt ot nt val | self box. self canvas fillWhite. lock _ self lockForm. self lastLocked: self locked. lock displayOn: self canvas at: self lockBox center - lock boundingBox center clippingBox: self lockBox. self lockBox displayOn: self canvas withBorderWidths:#(0 0 0 1). (lt _ (' ',label) asDisplayText) displayOn: self canvas at: self prefixBox leftCenter - (0@lt boundingBox leftCenter y) clippingBox: self prefixBox. self prefixBox displayOn: self canvas withBorderWidths:#(1 0 0 1). val _ self value. (vt _ val printShowingMax3Digits asDisplayText) displayOn: self canvas at: self valueBox leftCenter - vt boundingBox leftCenter clippingBox: self valueBox. self lastValue: val. self valueBox displayOn: self canvas withBorderWidths:#(0 0 0 1). self operationBoxes with: self operations do:[:bx :op| (ot _ op asString asDisplayText) displayOn: self canvas at: bx center - ot boundingBox center-(0@((#(/ + -) includes: op) ifTrue:[2]ifFalse:[1])) clippingBox: bx. bx displayOn: self canvas withBorderWidths:#(1 0 0 1). op = self operation ifTrue:[self lastOp: op. self canvas reverse: (bx insetBy:1)]. ]. self numberBoxes with: #(1 10 100 0) do:[:bx :num| (nt _ num printString asDisplayText) displayOn: self canvas at: bx center - nt boundingBox center clippingBox: bx. bx displayOn: self canvas withBorderWidths:#(1 0 0 1)]. ! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 21:25'! lockForm ^self locked ifTrue:[self closedPadlock] ifFalse:[self openPadlock]! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:27'! openPadlock ^((ColorForm extent: 20@16 depth: 8 fromArray: #( 146 2861732522 2449473536 0 0 5614218 0 1841452288 0 0 12741888 3334915730 5882368 0 0 1839879626 2852126914 2852170349 0 0 2324859594 0 3396178570 0 0 2324859594 0 3396176522 0 0 1908838070 0 2995956337 0 0 0 24962 2122220133 1701143938 2122220129 0 39429 151850253 218959117 218958234 0 40461 353178901 353178901 353709502 0 54805 488447261 488447261 490028478 0 60957 556605729 556605733 1027944954 0 60961 824522037 825310525 1160859118 0 60965 825569585 1027423557 1162692090 0 60961 824524093 893732165 1162694126 0 52966 3873888954 3873888998 3873102542) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.0 0.0 0.0) ))! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:20'! box box isNil ifTrue:[self box: self canvas boundingBox]. box extent = self insetDisplayBox extent ifFalse:[self box: self canvas boundingBox]. ^box! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 10:43'! box: anObject "Set the value of box" box _ anObject. lockBox _ prefixBox _ valueBox _ operationBox _ oneBox _ tenBox _ hundredBox _ zeroBox _ nil.! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:08'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent:198@26 depth: Display depth) fillWhite]. ^ canvas! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:12'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! hundredBox "Answer the value of hundredBox" hundredBox isNil ifTrue:[self hundredBox: (self zeroBox topLeft - (self hundredLabel boundingBox width@0) extent: ( self hundredLabel boundingBox width @ self box height))]. ^ hundredBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! hundredBox: anObject "Set the value of hundredBox" hundredBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:50'! hundredLabel ^' 100 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:02'! lastLocked "Answer the value of lastLocked" lastLocked isNil ifTrue:[self lastLocked: nil]. ^ lastLocked! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:02'! lastLocked: anObject "Set the value of lastLocked" lastLocked _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:57'! lastOp "Answer the value of lastOp" lastOp isNil ifTrue:[self lastOp: #none]. ^ lastOp! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:56'! lastOp: anObject "Set the value of lastOp" lastOp _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:52'! lastValue "Answer the value of lastValue" lastValue isNil ifTrue:[self lastValue: 0.0000000000000001]. ^ lastValue! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:51'! lastValue: anObject "Set the value of lastValue" lastValue _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:43'! lockBox "Answer the value of lockBox" lockBox isNil ifTrue:[self lockBox: (self box origin extent: (24@self box height))]. ^ lockBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! lockBox: anObject "Set the value of lockBox" lockBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockGetter "Answer the value of lockGetter" lockGetter isNil ifTrue:[self lockGetter: nil]. ^ lockGetter! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockGetter: anObject "Set the value of lockGetter" lockGetter _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockSetter "Answer the value of lockSetter" lockSetter isNil ifTrue:[self lockSetter: nil]. ^ lockSetter! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockSetter: anObject "Set the value of lockSetter" lockSetter _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 21:37'! locked | temp | temp _ self lockGetter isSymbol ifTrue:[self model perform: self lockGetter] ifFalse:[self lockGetter value]. ^temp! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:31'! locked: aBoolean "Set the value of locked" self lockSetter isSymbol ifTrue:[model perform: self lockSetter with: aBoolean] ifFalse:[self lockSetter value: aBoolean]! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 07:49'! numberBoxes "Answer the number boxes" ^{self oneBox. self tenBox. self hundredBox. self zeroBox}! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:52'! numbersBox "Answer the rectangle encompassing all number boxes" ^((self zeroBox merge: self hundredBox)merge: self tenBox)merge:self oneBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! oneBox "Answer the value of oneBox" oneBox isNil ifTrue:[self oneBox: (self tenBox topLeft - (self oneLabel boundingBox width@0) extent: ( self oneLabel boundingBox width @ self box height))]. ^ oneBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! oneBox: anObject "Set the value of oneBox" oneBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! oneLabel ^' 1 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:42'! opBox "Answer the value of opBox, the rectangle sized for a single operation button" ^0@0 extent: (self box height //2) asPoint! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:39'! operation "Answer the value of operation, #+, #-, #*, or #/" operation isNil ifTrue:[self operation: #+]. ^ operation! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! operation: anObject "Set the value of operation" operation _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:41'! operationBox "Answer the value of operationBox" operationBox isNil ifTrue:[self operationBox: ((self numbersBox topLeft - (self opBox width * 2 @0)extent:self opBox extent * 2))]. ^ operationBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! operationBox: anObject "Set the value of operationBox" operationBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:45'! operationBoxes "Answer the boxes for + * - / boxes in + | * ----- - | / order" ^self operationBox subDivideBy: 2@2! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:47'! operations ^#(+ * - /)! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:37'! postLabelBox "Answer the rectangle encompassing all boxes to the left of the label" ^self operationBox merge: self numbersBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:35'! preLabelBox "Answer the rectangle encompassing all boxes to the right of the label" ^self lockBox merge: self prefixBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:53'! prefixBox "Answer the value of prefixBox" prefixBox isNil ifTrue:[self prefixBox: (self lockBox topRight extent: (self label asDisplayText boundingBox width @ self box height))]. ^ prefixBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:32'! prefixBox: anObject "Set the value of prefixBox" prefixBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! tenBox "Answer the value of tenBox" tenBox isNil ifTrue:[self tenBox: (self hundredBox topLeft - (self tenLabel boundingBox width@0) extent: ( self tenLabel boundingBox width @ self box height))]. ^ tenBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! tenBox: anObject "Set the value of tenBox" tenBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:50'! tenLabel ^' 10 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:34'! valueBox "Answer the value of valueBox" valueBox isNil ifTrue:[self valueBox: (self preLabelBox topRight corner: self postLabelBox bottomLeft)]. ^ valueBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! valueBox: anObject "Set the value of valueBox" valueBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! zeroBox "Answer the value of zeroBox" zeroBox isNil ifTrue:[self zeroBox: (self box topRight - (self zeroLabel boundingBox width@0) extent: ( self zeroLabel boundingBox width @ self box height))]. ^ zeroBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! zeroBox: anObject "Set the value of zeroBox" zeroBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! zeroLabel ^' 0 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'controller access' stamp: 'ssa 10/29/2008 21:35'! defaultControllerClass ^RVMValueEditorController! ! !RVMValueEditorView methodsFor: 'editing' stamp: 'ssa 10/29/2008 21:45'! performOperationWith: aNumber self value: (self value perform: self operation with: aNumber). self displayView! ! !RVMValueEditorView methodsFor: 'editing' stamp: 'ssa 10/29/2008 21:46'! resetValueToZero self value: 0. self displayView! ! !RVMValueView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:52'! on: aModel valueGetter: getterSymbolOrBlock valueSetter: setterSymbolOrBlock label: aString | view | view _ self new. view model: aModel. view valueGetter: getterSymbolOrBlock. view valueSetter: setterSymbolOrBlock. view label: aString. ^view! ! !RVMValueView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 14:29'! on: aModel valueGetterOnly: getterSymbolOrBlock | view | view _ self new. view model: aModel. view controller: NoController new. view valueGetter: getterSymbolOrBlock. view valueSetter: [:v| ]. view label: ''. ^view! ! !RVMValueView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 20:31'! example "RVMValueView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. topView addSubView: self exampleInstance. topView label: 'Value Editor'. topView controller open! ! !RVMValueView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 07:51'! exampleInstance | view | view _ self on: nil valueGetter: [100 atRandom] valueSetter:[:v|v print] label:'min: '. ^view! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:06'! example "RVMValueEditorView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize:200@26. topView maximumSize: 200@26. topView addSubView: self exampleInstanceMin. topView label: 'Value Editor'. topView controller open! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 20:38'! exampleInstanceMax | view scaler | scaler _ RVMMonitor scalerFor: #bytesUseds. view _ self on: scaler valueGetter: [scaler max] valueSetter:[:v|scaler max:v] label:'max: '. view lockGetter:#maxLocked; lockSetter:#maxLocked:. ^view! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:06'! exampleInstanceMin | view scaler | scaler _ RVMMonitor scalerFor: #bytesUseds. view _ self on: scaler valueGetter: [scaler min] valueSetter:[:v|scaler min:v] label:'min: '. view lockGetter:#minLocked; lockSetter:#minLocked:. ^view! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:33'! exampleMinMax "RVMValueEditorView exampleMinMax" | topView v x | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize:200@54. topView maximumSize: 200@54. topView addSubView: (v_self exampleInstanceMin). topView addSubView: (x _ self exampleInstanceMax) below: v. topView label: 'Value Editor'. topView controller open! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/18/2008 23:18'! asCircularCollection "Answer a circular version of myself" ^RVMCircularCollection withAll: self! ! !ArrayedCollection methodsFor: '*Sly' stamp: 'dmu 9/17/2010 11:04'! parallelCollect: aBlock "#(1 2 3 4 5) parallelCollect:[:e| e * 2]" | results task barrier interlock result | "true ifTrue: [^ self collect: aBlock.]." "for debugging" self ifEmpty: [^ self]. (Sly3 serializeForDebugging or: [self size = 1]) ifTrue: [^ self collect: aBlock]. results _ self species new: self size. barrier _ RVMBarrier new signalsNeededToPass: self size. interlock _ Semaphore forMutualExclusion. 1 to: self size do: [:i| task _ [ result _ [aBlock copy fixTemps value: (self at: i)] ifCurtailed: [barrier signal]. interlock critical: [results at: i put: result]. barrier signal ] asSlyMemberProcess. task resume ]. barrier wait. ^results! ! !ImageReadWriter commentStamp: ''! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. I am an abstract class to provide for encoding and/or decoding an image on a stream. Instance Variables: stream stream for image storages Class Variables: ImageNotStoredSignal image not stored error signal MagicNumberErrorSignal magic number error signal Subclasses must implement the following messages: accessing nextImage nextPutImage: testing canUnderstand (added tao 10/26/97)! ImageReadWriter subclass: #BMPReadWriter instanceVariableNames: 'bfType bfSize bfOffBits biSize biWidth biHeight biPlanes biBitCount biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Files'! !GIFReadWriter commentStamp: ''! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. Used with permission. Modified for use in Squeak.! GIFReadWriter subclass: #AnimatedGIFReadWriter instanceVariableNames: 'forms delays comments' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Files'! !EventSensor commentStamp: 'nk 4/13/2004 11:18'! EventSensor is a replacement for InputSensor based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design. For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events. On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM. Instance variables: mouseButtons - mouse button state as replacement for primMouseButtons mousePosition - mouse position as replacement for primMousePt keyboardBuffer - keyboard input buffer interruptKey - currently defined interrupt key interruptSemaphore - the semaphore signaled when the interruptKey is detected eventQueue - an optional event queue for event driven applications inputSemaphore - the semaphore signaled by the VM if asynchronous event notification is supported lastEventPoll - the last millisecondClockValue at which we called fetchMoreEvents hasInputSemaphore - true if my inputSemaphore has actually been signaled at least once. Class variables: EventPollPeriod - the number of milliseconds to wait between polling for more events in the userInterruptHandler. EventTicklerProcess - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds). Event format: The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported. Currently, the following events are defined: Null event ============= The Null event is returned when the ST side asks for more events but no more events are available. Structure: [1] - event type 0 [2-8] - unused Mouse event structure ========================== Mouse events are generated when mouse input is detected. Structure: [1] - event type 1 [2] - time stamp [3] - mouse x position [4] - mouse y position [5] - button state; bitfield with the following entries: 1 - yellow (e.g., right) button 2 - blue (e.g., middle) button 4 - red (e.g., left) button [all other bits are currently undefined] [6] - modifier keys; bitfield with the following entries: 1 - shift key 2 - ctrl key 4 - (Mac specific) option key 8 - Cmd/Alt key [all other bits are currently undefined] [7] - reserved. [8] - reserved. Keyboard events ==================== Keyboard events are generated when keyboard input is detected. [1] - event type 2 [2] - time stamp [3] - character code For now the character code is in Mac Roman encoding. [4] - press state; integer with the following meaning 0 - character 1 - key press (down) 2 - key release (up) [5] - modifier keys (same as in mouse events) [6] - reserved. [7] - reserved. [8] - reserved. ! Object subclass: #JPEGColorComponent instanceVariableNames: 'currentX currentY hSampleFactor vSampleFactor mcuBlocks widthInBlocks heightInBlocks dctSize mcuWidth mcuHeight priorDCValue id qTableIndex dcTableIndex acTableIndex' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Files'! !JPEGColorComponent commentStamp: ''! I represent a single component of color in JPEG YCbCr color space. I can accept a list of blocks in my component from the current MCU, then stream the samples from this block for use in color conversion. I also store the running DC sample value for my component, used by the Huffman decoder. The following layout is fixed for the JPEG primitives to work: currentX currentY hSampleFactor vSampleFactor mcuBlocks > widthInBlocks heightInBlocks dctSize mcuWidth mcuHeight priorDCValue ! Object subclass: #JPEGHuffmanTable instanceVariableNames: 'bits values mincode maxcode valptr lookaheadBits lookaheadSymbol' classVariableNames: 'BitBufferSize Lookahead' poolDictionaries: '' category: 'Graphics-Files'! !JPEGHuffmanTable commentStamp: ''! I represent the table of values used to decode Huffman entropy-encoded bitstreams. From the JFIF file header entropy values, I build a derived table of codes and values for faster decoding.! ImageReadWriter subclass: #JPEGReadWriter instanceVariableNames: 'width height components currentComponents qTable hACTable hDCTable restartInterval restartsToGo mcuWidth mcuHeight mcusPerRow mcuRowsInScan mcuMembership mcuSampleBuffer mcuImageBuffer majorVersion minorVersion dataPrecision densityUnit xDensity yDensity ss se ah al sosSeen residuals ditherMask' classVariableNames: 'ConstBits DCTK1 DCTK2 DCTK3 DCTK4 DCTSize DCTSize2 DitherMasks FIXn0n298631336 FIXn0n34414 FIXn0n390180644 FIXn0n541196100 FIXn0n71414 FIXn0n765366865 FIXn0n899976223 FIXn1n175875602 FIXn1n40200 FIXn1n501321110 FIXn1n77200 FIXn1n847759065 FIXn1n961570560 FIXn2n053119869 FIXn2n562915447 FIXn3n072711026 FloatSampleOffset HuffmanTableSize JFIFMarkerParser JPEGNaturalOrder MaxSample Pass1Bits Pass1Div Pass2Div QTableScaleFactor QuantizationTableSize SampleOffset' poolDictionaries: '' category: 'Graphics-Files'! !JPEGReadWriter commentStamp: ''! I am a subclass of ImageReadWriter that understands JFIF file streams, and can decode JPEG images. This code is based upon the Independent Joint Photographic Experts Group (IJPEG) software, originally written in C by Tom Lane, Philip Gladstone, Luis Ortiz, Jim Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. ! ImageReadWriter subclass: #JPEGReadWriter2 instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Files'! !JPEGReadWriter2 commentStamp: ''! I provide fast JPEG compression and decompression. I require the VM pluginJPEGReadWriter2Plugin, which is typically stored in same directory as the Squeak virtual machine. JPEGReadWriter2Plugin is based on LIBJPEG library. This sentence applies to the plugin: "This software is based in part on the work of the Independent JPEG Group". The LIBJPEG license allows it to be used free for any purpose so long as its origin and copyright are acknowledged. You can read more about LIBJPEG and get the complete source code at www.ijg.org. ! Object subclass: #ListItemWrapper instanceVariableNames: 'item model' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !ListItemWrapper commentStamp: ''! Contributed by Bob Arning as part of the ObjectExplorer package. ! Object subclass: #LyGraphicsLibrary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! MouseMenuController subclass: #MSWScrollBarController instanceVariableNames: 'unitScrollDelay' classVariableNames: '' poolDictionaries: '' category: 'Interface-MSWLook'! ListItemWrapper subclass: #ObjectExplorerWrapper instanceVariableNames: 'itemName parent isOpen' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !ObjectExplorerWrapper commentStamp: ''! Contributed by Bob Arning as part of the ObjectExplorer package. ! ObjectExplorerWrapper subclass: #ClassHierarchyExplorerWrapper instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! ColorForm subclass: #OpaqueForm instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !OpaqueForm commentStamp: ''! OpaqueForms include a shape as well as a figure form. The shape indicates what part of the background should get occluded in displaying, so that patterns other than black in the figure form will still appear opaque. Instance Variables: figure
the actual image shape the mask for displaying! Object subclass: #PluggableOutline instanceVariableNames: 'subject list selection openItems levels' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! PluggableOutline subclass: #AbstractHierarchicalList instanceVariableNames: 'currentSelection myBrowser' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !AbstractHierarchicalList commentStamp: ''! Contributed by Bob Arning as part of the ObjectExplorer package. ! AbstractHierarchicalList subclass: #ObjectExplorer instanceVariableNames: 'rootObject inspector monitorList monitorProcess rootLabel' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !ObjectExplorer commentStamp: ''! ObjectExplorer provides a hierarchical alternative to #inspect. Simply evaluate an expression like: World explore and enjoy.! ObjectExplorer subclass: #ClassHierarchyExplorer instanceVariableNames: 'centralClass' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! ObjectExplorer subclass: #PointerExplorer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !PointerExplorer commentStamp: 'avi 8/21/2004 20:01'! A variant on the ObjectExlorer that works "backwards": like the ObjectExplorer, it shows a tree of objects, but expanding a node won't show the objects which that node references, but rather the objects that reference that node. Its main use is to track down memory leaks: if you want to know why a particular object is still alive, open a PointerExplorer on it and drill down until you find the root object that's referencing it. For example, find all the references to the symbol #zot with: PointerExplorer new openExplorerFor: #zot For the "name" of the object, the PointerExplorer shows each object's identityHash, to allow the user to identify when two similar objects are identical and notice cycles.! ObjectExplorerWrapper subclass: #PointerExplorerWrapper instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !PointerExplorerWrapper commentStamp: 'avi 8/21/2004 19:58'! A subclass of ObjectExplorerWrapper for use with PointerExplorer. #contents is overridden to work backwards: it returns wrappers for the objects pointing to item rather than for the objects that item points to.! Object subclass: #PopUpMenu instanceVariableNames: 'labelString font lineArray frame form marker selection' classVariableNames: 'CacheMenuForms LastStartupTime MenuStyle' poolDictionaries: '' category: 'Tools-Menus'! ReadStream subclass: #JPEGReadStream instanceVariableNames: 'bitBuffer bitsInBuffer' classVariableNames: 'MaxBits' poolDictionaries: '' category: 'Graphics-Files'! !JPEGReadStream commentStamp: ''! Encapsulates huffman encoded access to JPEG data. The following layout is fixed for the JPEG primitives to work: collection position readLimit bitBuffer bitsInBuffer ! Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess EmergencyProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'! RVMObject subclass: #RVMSBinarySampleWriter instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'RVM-Archiving'! !RVMSBinarySampleWriter commentStamp: 'ssa 10/26/2008 23:51'! A test to see if a completely flattened binary stream write method would be faster than the archiver. Not so!! this takes 4-6 seconds and generates a 600K file for a 56 core sample Archiver takes 0.7 sec and generates a 40K file! Object subclass: #RemoteString instanceVariableNames: 'sourceFileNumber filePositionHi' classVariableNames: 'CurrentTextAttStructure CurrentTextAttVersion TextAttributeStructureVersions' poolDictionaries: '' category: 'System-Files'! PluggableListController subclass: #LyPluggableOutlineController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! Array variableSubclass: #ArrayWithNilDetector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! OrderedCollection subclass: #OrderedCollectionWithNilDetector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! MouseMenuController subclass: #StandardSystemController instanceVariableNames: 'status preventClosing' classVariableNames: 'HBorderCursor ScheduledBlueButtonMenu ScheduledBlueButtonMessages VBorderCursor' poolDictionaries: '' category: 'ST80-Support'! StandardSystemController subclass: #MSWSystemController instanceVariableNames: 'lastSystemActivity' classVariableNames: '' poolDictionaries: '' category: 'Interface-MSWLook'! CodeHolder subclass: #Browser instanceVariableNames: 'systemOrganizer classOrganizer metaClassOrganizer systemCategoryListIndex classListIndex messageCategoryListIndex messageListIndex editSelection metaClassIndicated lastClassSelected' classVariableNames: 'RecentClasses' poolDictionaries: '' category: 'Tools-Browser'! HierarchyBrowser subclass: #HierarchyOutlineBrowser instanceVariableNames: 'subject list selection openItems levels currentSelection myBrowser' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! !HierarchyOutlineBrowser commentStamp: ''! Contributed by Bob Arning as part of the ObjectExplorer package. ! TextDoIt subclass: #TextBlockDoIt instanceVariableNames: 'actionBlock' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! WriteStream subclass: #TranscriptStream instanceVariableNames: '' classVariableNames: 'AccessSema ShowInConsole' poolDictionaries: '' category: 'Collections-Streams'! View subclass: #MSWScrollBarView instanceVariableNames: 'scrollBarWidth scrollBarBox upButtonBox downButtonBox elevatorShaft elevatorCache upButtonCache downButtonCache' classVariableNames: 'WhereToLocateScrollBars' poolDictionaries: '' category: 'Interface-MSWLook'! PluggableListView subclass: #PluggableListViewByObject instanceVariableNames: 'objects scrollCache' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! PluggableListViewByObject subclass: #LyPluggableOutlineView instanceVariableNames: 'getChildrenSelector twistyTargets' classVariableNames: '' poolDictionaries: '' category: 'Ly-Tools'! LyPluggableOutlineView subclass: #ExplorerListView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Ly-Explorer'! StandardSystemView subclass: #MSWSystemView instanceVariableNames: 'growFrame' classVariableNames: 'CloseBoxForm GrowBoxForm ShrinkBoxForm SystemBoxForm' poolDictionaries: '' category: 'Interface-MSWLook'! View subclass: #StringHolderView instanceVariableNames: 'displayContents hasUnacceptedEdits askBeforeDiscardingEdits textStyle' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !Object methodsFor: '*Javascript' stamp: 'aw 8/29/2007 14:27'! ~== anObject ^ (self == anObject) not! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/18/2010 15:47'! primitiveGetExtraPreheaderWord: anObject "ignores receiver, queries argument" self primitiveFailed! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/18/2010 14:52'! primitiveSetExtraPreheaderWord: w "sets word IN w to SELF" self primitiveFailed! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/16/2010 19:11'! primitiveSetExtraWordSelector: aSelector self primitiveFailed! ! !Object methodsFor: 'RVM-ensembles' stamp: 'ssa 4/21/2009 20:29'! forMeRun: aBlock ^ aBlock value! ! !Object methodsFor: 'RVM-ensembles' stamp: 'dmu 5/14/2010 10:29'! printConsole RVMTester isRVM ifTrue: [RVMTester print: self printString] ifFalse: [Transcript showInConsole ifFalse: [Transcript show: self printString; cr]]! ! !Object methodsFor: 'converting' stamp: ''! asDisplayObject "kwa -- 7 July 1989, answer some DisplayObject which represents the receiver. The default is DisplayString. Subclasses may wish to override. kwa -- 5 December 1989, changed from DisplayText to DisplayString for efficiency." "ssa - 27 February 1990, at kwa's suggestion, changed asDisplayString back to asDisplayText to work around a bug in glyph scanning" "KSC Extension" ^self asDisplayText! ! !Object methodsFor: 'converting' stamp: ''! asDisplayText "Convert the receiver into a DisplayText." "KSC Extension." ^self asText asDisplayText! ! !Object methodsFor: 'converting' stamp: 'ssa 11/13/2008 10:34'! asObjectCoordinate "Answer an RVMObjectCoordinate with my manycore coordinate details" ^RVMObjectCoordinate for: self! ! !Object methodsFor: 'converting' stamp: ''! asText "kwa -- 7 July 1989, answer some Text which represents the receiver. The default is to use asString asText. This is so any object can can be treated as a Text (whether it is or not). Subclasses may wish to override (but shouldn't have to) to take advantage of emphasis et al." "KSC Extension" ^self asString asText! ! !Object methodsFor: 'converting' stamp: 'ssa 12/16/2009 13:22'! printDirectlyToDisplay "For debugging: write the receiver's printString directly to the display at (0, 100); senders of this are detected by the check-for-slips mechanism." self asString displayAt: 0@0 "StringMorph someInstance printDirectlyToDisplay"! ! !Object methodsFor: 'debugging' stamp: 'ssa 1/21/2010 12:08'! display "Display my printString on the screen to avoid the transcript" self printString asParagraph display! ! !Object methodsFor: 'debugging' stamp: 'ssa 2/26/2009 01:59'! locate "Open a object coordinate view on my location in the manycore world" "Array locate" RVMObjectCoordinateView openOn: self asObjectCoordinate! ! !Object methodsFor: 'debugging' stamp: 'ssa 8/8/2008 17:25'! print Transcript cr;show: self printString! ! !Object methodsFor: '*Sly3' stamp: 'dmu 9/3/2010 17:00'! doesNotUnderstand: aMessage "Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector)." "Testing: (3 activeProcess)" | newSelector rps | rps _ {Sly3Adverb reflectiveAdverb stringWithUppercaseSuffix. Sly3ModWholly stringWithUppercaseSuffix}. rps do: [:rp | (aMessage selector beginsWith: rp) ifTrue: [ newSelector _ aMessage selector copyFrom: rp size + 1 to: aMessage selector size. newSelector size = 0 ifTrue: [^ self]. ^ self perform: newSelector asSymbol withArguments: aMessage arguments ] ]. (RVMTester isMulticoreCoordinate: aMessage selector) ifTrue:[RVMTester teleport: self to: aMessage selector. ^self]. (Preferences autoAccessors and: [self tryToDefineVariableAccess: aMessage]) ifTrue: [^ aMessage sentTo: self]. ^ MessageNotUnderstood new message: aMessage; receiver: self; signal! ! !Object methodsFor: 'inspecting' stamp: 'ssa 1/6/2010 20:19'! inspect "Create and schedule an Inspector in which the user can examine the receiver's variables." self inspectorClass openOn: self withEvalPane: true! ! !Object methodsFor: 'macpal' stamp: 'ssa 9/8/2009 10:22'! allInstanceVariableValues "Answer a collection whose elements are the values of those instance variables of the receiver" | c | c _ OrderedCollection new. 1 to: self class instSize do: [:i | c add: (self instVarAt: i)]. ^ c! ! !Object methodsFor: 'macpal' stamp: 'ssa 9/8/2009 10:51'! allInstanceVariableValuesPlusIndexed "Answer a collection whose elements are the values of those instance variables of the receiver. Also include the indexed variables if any" | c | c _ OrderedCollection new. 1 to: self class instSize do: [:i | c add: (self instVarAt: i)]. self class isVariable ifFalse:[^c]. 1 to: self size do:[:index| c add: (self basicAt: index)]. ^ c! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/11/2009 16:40'! explore ObjectExplorer new openExplorerFor: self! ! !Object methodsFor: 'outlining' stamp: 'ssa 3/9/2010 16:17'! hasContents ^false! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/10/2009 16:00'! outlineString ^self printString! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:36'! subobjects "Answer an appropriate collection of my sub objects for an outliner view" ^self class allInstVarNames with: self allInstanceVariableValues collect:[:key :value| key -> value]! ! !Object methodsFor: 'printing' stamp: ''! archiveOn: aStream "This is the generic archiver for objects. If an object does anything special, this method will need to be subclassed along with the complementary method - dearchiveFrom:" aStream storeObject: self; storeClass: self class. self class isVariable ifTrue: [aStream store: self basicSize. 1 to: self basicSize do: [:i | aStream nextPut: (self basicAt: i)].]. 1 to: self class instSize do: [:i | aStream nextPut: (self instVarAt: i)].! ! !Object methodsFor: 'printing' stamp: 'ssa 10/25/2008 20:45'! archiveVersion "Subclasses should override when they implement a different archive version" ^1! ! !Object methodsFor: 'printing' stamp: ''! basicArchiveOn: aStream "This is the generic archiver for objects. This can be used if you want to bypass superclass or other reasons for overriding archiveOn:" aStream storeObject: self; storeClass: self class. self class isVariable ifTrue: [aStream store: self basicSize. 1 to: self basicSize do: [:i | aStream nextPut: (self basicAt: i)].]. 1 to: self class instSize do: [:i | aStream nextPut: (self instVarAt: i)].! ! !Object methodsFor: 'printing' stamp: ''! dearchiveFrom: aStream "This is the generic de-archiver for objects. If an object does anything special, this method will need to be subclassed along with the complementary method - archiveOn:" self class isVariable ifTrue: [1 to: self basicSize do: [:i | self basicAt: i put: aStream next]]. 1 to: self class instSize do: [:j | self instVarAt: j put: aStream next]! ! !Object methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:21'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables." self class allInstVarNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab; nextPutAll: (RVMTester printPrefixFor: (self instVarAt: index)); print:(self instVarAt: index); cr]! ! !Object methodsFor: 'printing' stamp: 'ssa 9/4/2009 22:29'! printStringUpTo: limit "Answer a String whose characters are a description of the receiver. If you want to print without a character limit, use fullPrintString." | limitedString | limitedString _ String streamContents: [:s | self printOn: s] limitedTo: limit. limitedString size < limit ifTrue: [^ limitedString]. ^ limitedString, '...'! ! !Object methodsFor: 'testing' stamp: 'ssa 9/8/2009 10:48'! hasInstanceVariables ^self allInstanceVariableValuesPlusIndexed size > 0! ! !Object methodsFor: 'testing' stamp: 'ssa 5/12/2010 19:26'! isArray "Return true if the receiver is an Array" ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 5/27/2010 10:40'! isBoolean "Return true if the receiver is true or false. Note: Do not override in any class except Boolean." ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 8/11/2009 12:37'! isCharacter ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 8/31/2009 14:14'! isObject ^true! ! !Object methodsFor: 'updating' stamp: 'ssa 5/12/2010 10:29'! changed: anAspect with: anObject from: aSource "Receiver changed. The change is denoted by the argument anAspect. Usually the argument is a Symbol that is part of the dependent's change protocol. Inform all of the dependents. Also pass anObject for additional information." self dependents do: [:aDependent | aDependent update: anAspect with: anObject from: aSource]! ! !Object methodsFor: 'updating' stamp: 'ssa 5/12/2010 10:29'! update: anAspect with: anObject from: aSource "Receive a change notice from an object of whom the receiver is a dependent. The default behavior is to call update:, which by default does nothing; a subclass might want to change itself in some way." ^ self update: anAspect with: anObject! ! !Object methodsFor: 'user interface' stamp: 'ssa 6/17/2010 16:15'! asExplorerString ^ self printString! ! !Object methodsFor: 'user interface' stamp: 'ssa 11/30/2009 17:49'! defaultBackgroundColor "Answer the color to be used as the base window color for a window whose model is an object of the receiver's class" (Smalltalk includesKey: #WINDOWCOLORSELECTOR) ifFalse:[Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| Preferences windowColorFor: obj class name]]. ^((Smalltalk at: #WINDOWCOLORSELECTOR) value: self) ! ! !ArchiveReader methodsFor: 'reading' stamp: ''! close stream close! ! !ArchiveReader methodsFor: 'reading' stamp: ''! next | anInteger | startPosition _ position. anInteger _ self read: Integer. ^anInteger = 0 ifTrue: [objectMap at: (self read: Integer)] ifFalse: [(classMap at: anInteger) dearchive: (classVersions at: anInteger) from: self]! ! !ArchiveReader methodsFor: 'reading' stamp: ''! read: aClass "Ask aClass to read one of its objects from stream. aClass is typically Integer, Float, Symbol, etc. Assume the object was put on the stream using ArchiveWriter>store:" | anObject | anObject _ aClass readFrom: stream. stream skipSeparators. position _ position + 1. ^anObject! ! !ArchiveReader methodsFor: 'testing' stamp: ''! isCopier "For compatibility with CopyReader (in case an object cares what type of Reader its using)." ^false! ! !ArchiveReader methodsFor: 'private' stamp: 'ssa 10/25/2008 21:29'! dearchive: version from: aStream "This is used before a class is read in for the first time... version is ignored here. This method has this name only to avoid another case statement (see #next). A better name for this method would be #dearchiveClassFrom:" | aClass anInteger | classMap add: (aClass _ Smalltalk at: (aStream read: Symbol)). classVersions add: (anInteger _ aStream read: Integer). ^aClass dearchive: anInteger from: aStream! ! !ArchiveReader methodsFor: 'private' stamp: ''! setStream: aStream stream _ aStream. objectMap _ IdentityDictionary new: 400. classMap _ OrderedCollection new: 30. classMap add: self. classVersions _ OrderedCollection with: 0. position _ 0! ! !ArchiveReader methodsFor: 'private' stamp: ''! storeObject: anObject objectMap at: startPosition put: anObject! ! !ArchiveWriter methodsFor: 'writing' stamp: ''! canCopy: anObject "For archiving, I write out everything" ^true! ! !ArchiveWriter methodsFor: 'writing' stamp: ''! close stream close! ! !ArchiveWriter methodsFor: 'writing' stamp: ''! nextPut: anObject | anInteger | anInteger _ objectMap at: anObject ifAbsent: [^anObject archiveOn: self]. self store: 0; store: anInteger! ! !ArchiveWriter methodsFor: 'writing' stamp: ''! store: anObject "Put anObject on the Stream, converting it to an ascii String. anObject will typically be a Symbol, Number, etc. This takes advantage of the storeOn:/readFrom: facility already in Smalltalk which works well for Basic Classes." "kwa -- 12 October 1989, replaced #space with: nextPut: Space (a TextConstant) for efficiency." stream store: anObject; nextPut: Space. position _ position + 1! ! !ArchiveWriter methodsFor: 'private' stamp: 'ssa 10/26/2008 20:44'! setStream: aWriteStream stream _ aWriteStream. classMap _ IdentityDictionary new: 30. classMap at: self put: 1. objectMap _ IdentityDictionary new: 400. position _ 0! ! !ArchiveWriter methodsFor: 'private' stamp: ''! storeClass: aClass self store: (classMap at: aClass ifAbsent: [self store: 1; store: aClass name; store: aClass archiveVersion. ^classMap at: aClass put: classMap size + 1])! ! !ArchiveWriter methodsFor: 'private' stamp: ''! storeObject: anObject objectMap at: anObject put: "stream" position! ! !ArchiveWriter methodsFor: 'testing' stamp: ''! isCopier "For compatibility with CopyWriter (in case an object cares what type of Writer its using)." ^false! ! !Association methodsFor: 'outlining' stamp: 'ssa 9/10/2009 16:01'! outlineString ^self key asString,' ',self value printString! ! !Behavior methodsFor: 'accessing' stamp: 'ssa 9/2/2009 17:59'! setInstanceFormat: sizeAndFlags "Set the format for the receiver (a Class)." format _ sizeAndFlags! ! !Behavior methodsFor: 'printing' stamp: 'ssa 10/25/2008 20:48'! archiveVersion "This is the daefault version number for an archived instance of any class. Version 1 was back when each class was responsible for its own archiving. Version 2 uses the default archiving behavior in object (see Object>archiveOn: and Object class>dearchive:from:)." ^1! ! !Behavior methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:22'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables. But, not useful for a class with a method dictionary." aStream nextPutAll: (RVMTester printPrefixFor: self). aStream nextPutAll: '<>'; cr.! ! !Behavior methodsFor: 'compiling' stamp: 'ssa 9/3/2008 12:19'! compile: code notifying: requestor trailer: trailingBytes "Compile the argument, code, as source code in the context of the receiver and insEtall the result in the receiver's method dictionary. The second argument, requestor, is to be notified if an error occurs. The argument code is either a string or an object that converts to a string or a PositionableStream. This method also saves the source code." | methodAndNode | methodAndNode := self basicCompile: code "a Text" notifying: requestor trailer: trailingBytes ifFail: [^nil]. methodAndNode method putSource: code fromParseNode: methodAndNode node inFile: 2 withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr]. self addSelector: methodAndNode selector withMethod: methodAndNode method notifying: requestor. ^ methodAndNode selector! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'ssa 10/8/2008 15:47'! allSubclasses "Answer a Set of the receiver's and the receiver's descendent's subclasses. " | scan scanTop | scan _ OrderedCollection withAll: self subclasses. scanTop _ 1. [scanTop > scan size] whileFalse: [scan addAll: (scan at: scanTop) subclasses. scanTop _ scanTop + 1]. ^ scan "asSet"! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'ssa 10/8/2008 16:02'! withAllSubclasses "Answer a Set of the receiver, the receiver's descendent's, and the receiver's descendent's subclasses." | subs | subs _ self allSubclasses. subs addFirst: self. ^subs! ! !Behavior methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:46'! subobjects ^self subclasses! ! !BitBlt methodsFor: 'accessing' stamp: 'dmu 4/4/2009 00:24'! copyBitsOnMain "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 4/4/2009 00:20'! copyBitsLocally "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/3/2009 23:01'! drawLoopLocallyX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | | self primitiveFailed! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:36'! globalDrawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | dx _ xDelta sign. dy _ yDelta sign. px _ yDelta abs. py _ xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P _ py // 2. 1 to: py do: [:i | destX _ destX + dx. (P _ P - px) < 0 ifTrue: [destY _ destY + dy. P _ P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P _ px // 2. 1 to: px do: [:i | destY _ destY + dy. (P _ P - py) < 0 ifTrue: [destX _ destX + dx. P _ P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:52'! localDrawLoopX: xDelta Y: yDelta "Primitive" ^self primitiveFailed! ! !BlockNode methodsFor: 'accessing' stamp: 'dmu 1/21/2010 15:22'! returnSelfIfNoOther self returns ifFalse: [statements last == NodeSelf ifFalse: [ (statements isKindOf: Array) ifTrue: [statements _ statements asOrderedCollection]. statements add: NodeSelf ]. self returnLast]! ! !Boolean methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfFalse ! ! !Boolean methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfTrue ! ! !Boolean methodsFor: 'testing' stamp: 'ssa 5/27/2010 10:41'! isBoolean "Return true if the receiver is true or false. Note: Do not override in any class except Boolean." ^true! ! !Boolean methodsFor: 'testing' stamp: 'ssa 6/1/2010 16:46'! mustBeBoolean ^false! ! !Boolean methodsFor: 'testing' stamp: 'ssa 6/1/2010 16:47'! mustBeBooleanIn: aContext ^true! ! !ChangeRecord methodsFor: 'testing' stamp: 'ssa 1/5/2010 14:12'! match: aPatternString "Answer true is any of my text matches aPatternString" (aPatternString match: self string) ifTrue:[^true]. (aPatternString match: self methodClassNameSafe) ifTrue:[^true]. ^false! ! !ChangeRecord methodsFor: 'access' stamp: 'ssa 1/5/2010 14:04'! methodClassNameSafe ^class isNil ifTrue:['']ifFalse:[class]! ! !ChangeRecord methodsFor: 'access' stamp: 'ssa 1/5/2010 14:03'! methodSelectorSafe "Answer a string in any case" type == #method ifFalse: [^ '']. ^ Parser new parseSelector: self string! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! changeRecords "Answer the value of changeRecords" changeRecords isNil ifTrue:[self changeRecords: nil]. ^ changeRecords! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! changeRecords: anObject "Set the value of changeRecords" changeRecords _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! isolatedProject: anObject "Set the value of isolatedProject" isolatedProject _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! isolationSet "Answer the value of isolationSet" isolationSet isNil ifTrue:[self isolationSet: nil]. ^ isolationSet! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! postscript "Answer the value of postscript" postscript isNil ifTrue:[self postscript: nil]. ^ postscript! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! postscript: anObject "Set the value of postscript" postscript _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! preamble "Answer the value of preamble" preamble isNil ifTrue:[self preamble: nil]. ^ preamble! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! preamble: anObject "Set the value of preamble" preamble _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! revertable "Answer the value of revertable" revertable isNil ifTrue:[self revertable: nil]. ^ revertable! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! revertable: anObject "Set the value of revertable" revertable _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! structures: anObject "Set the value of structures" structures _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! superclasses: anObject "Set the value of superclasses" superclasses _ anObject! ! !Character methodsFor: 'testing' stamp: 'ssa 8/11/2009 12:37'! isCharacter ^true! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:29'! at: index index > 1 ifTrue:[^super at: index]. ^self! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:25'! doesNotUnderstand: aMessage "Hack DNU to make chars act like strings" ^self asString perform: aMessage selector withArguments: aMessage arguments! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:28'! size ^1! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ssa 8/19/2008 21:22'! scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops displaying: foo ^ self scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: 0! ! !CharacterScanner methodsFor: 'accessing' stamp: 'ssa 8/19/2008 21:15'! destX: x destX := x! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'ssa 10/8/2008 19:00'! allMethodsInCategory: aName "Answer a list of all the method categories of the receiver and all its superclasses " | aColl | aColl _ OrderedCollection new. self withAllSuperclasses do: [:aClass | aColl addAll: (aName = ClassOrganizer allCategory ifTrue: [aClass organization allMethodSelectors] ifFalse: [aClass organization listAtCategoryNamed: aName])]. ^ aColl asSet asSortedArray! ! !Collection methodsFor: 'accessing' stamp: 'ssa 3/12/2010 17:57'! atRandom "Answer a random element of the receiver. 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." ^ self atRandom: self class randomForPicking "Examples: #('one' 'or' 'the' 'other') atRandom (1 to: 10) atRandom 'Just pick one of these letters at random' atRandom #(3 7 4 9 21) asSet atRandom (just to show it also works for Sets) "! ! !Collection methodsFor: 'converting' stamp: ''! asString: aBlock withDelimiter: aDelimiter "kwa -- 30 November 1988, Answer a string with each of the objects in the receiver (converted to strings by aBlock) separated by aDelimiter." "KSC Extension" | aStream | self isEmpty ifTrue: [^'']. aStream _ WriteStream on: (String new: 64). self do: [:each | aStream nextPutAll: (aBlock value: each). aStream nextPutAll: aDelimiter]. aStream skip: aDelimiter size negated. ^aStream contents "#(13 2 3) asString: [:each | (each * 2) printString] withDelimiter: ', '"! ! !Collection methodsFor: 'converting' stamp: ''! asStringWithDelimiter: aDelimiter "kwa -- 13 May 1988, Answer a string of from the objects in the receiver separated by aDelimiter." "KSC Extension" | aStream | self isEmpty ifTrue: [^'']. aStream _ WriteStream on: (String new: 64). self do: [:each | (each isKindOf: String) ifTrue: [aStream nextPutAll: each asString] ifFalse: [each printOn: aStream]. aStream nextPutAll: aDelimiter]. aStream skip: aDelimiter size negated. ^aStream contents "#(a b 2 3) asStringWithDelimiter: ', '"! ! !Collection methodsFor: 'converting' stamp: ''! asText: aBlock withDelimiter: aDelimiter "kwa -- 30 November 1988, Answer a text with each of the objects in the receiver (converted to texts by aBlock) separated by aDelimiter." "KSC Extension" | aDelimiterText first text | self isEmpty ifTrue: [^'' asText]. aDelimiterText _ aDelimiter asText. first _ true. self do: [:each | first ifTrue: [text _ (aBlock value: each) asText. first _ false] ifFalse: [text _ text, aDelimiterText, (aBlock value: each) asText]]. ^text "(#(13 2 3) asText: [:each | (each * 2) printString asText allBold] withDelimiter: ', ') asDisplayText displayAt: Sensor cursorPoint"! ! !Collection methodsFor: 'enumerating' stamp: ''! collect: aBlock if: aQualifyingBlock "kwa -- 1 February 1989, Evaluate aQualifyingBlock with each of the values of the receiver as the argument. If the result is true, collect the resulting values of aBlock (using the same value as the argument) into a collection that is like the receiver. Answer the new collection." "KSC Extension" | newCollection | newCollection _ self species new. self do: [:each | (aQualifyingBlock value: each) ifTrue: [newCollection add: (aBlock value: each)]]. ^newCollection! ! !Collection methodsFor: 'removing' stamp: 'ssa 9/9/2009 12:16'! removeAll: aCollection ifAbsent:aBlock "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification. ArrayedCollections cannot respond to this message." aCollection do: [:each | self remove: each ifAbsent: aBlock]. ^ aCollection! ! !Collection methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:47'! subobjects ^self! ! !CharacterSet methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:50'! addAll: aCollection aCollection do:[:char| self add: char]! ! !CharacterSet methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:52'! removeAll: aCollection aCollection do:[:char| self remove: char]! ! !ControlManager methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:14'! activeControllerNoTerminate: aController andProcess: aProcess "Set aController to be the currently active controller and aProcess to be the the process that handles controller scheduling activities in the system. This message differs from activeController:andProcess: in that it does not send controlTerminate to the currently active controller." self inActiveControllerProcess ifTrue: [aController~~nil ifTrue: [(scheduledControllers includes: aController) ifTrue: [self promote: aController] ifFalse: [self error: 'Old controller not scheduled']]. activeController _ aController. activeController == nil ifFalse: [activeController controlInitialize]. activeControllerProcess _ aProcess. activeControllerProcess resume] ifFalse: ['New active controller process must be set from old one, resetting...' print. self reset. ] ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! inActiveControllerProcess "Answer whether the active scheduling process is the actual active process in the system." ^activeControllerProcess == Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/2/2010 14:12'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | suspendingList newActiveController | (suspendingList _ activeControllerProcess suspendingList) == nil ifTrue: [activeControllerProcess == Processor thisProcess ifTrue: [activeControllerProcess suspend]] ifFalse: [suspendingList remove: activeControllerProcess ifAbsent:[]. activeControllerProcess offList]. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController _ (Debugger openInterrupt: labelString onProcess: activeControllerProcess) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/25/2010 16:17'! reset "ssa - reset the window controller process" | newProcess | newProcess := [ScheduledControllers resetActiveController. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process" "Processor terminateActive"! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! resetActiveController "When saving a morphic project whose parent is mvc, we need to set this up first" activeController := nil. activeControllerProcess := Processor thisProcess. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! scheduleActiveNoTerminate: aController "Make aController be the active controller. Presumably the process that requested the new active controller wants to keep control to do more activites before the new controller can take control. Therefore, do not terminate the currently active process." self schedulePassive: aController. self scheduled: aController from: Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! searchForActiveController "Find a scheduled controller that wants control and give control to it. If none wants control, then see if the System Menu has been requested." | aController | activeController := nil. activeControllerProcess := Processor thisProcess. self activeController: self nextActiveController. Processor terminateActive! ! !ControlManager methodsFor: 'displaying' stamp: 'ssa 8/26/2008 08:55'! restore: aRectangle below: index without: aView "Restore all windows visible in aRectangle, but without aView" | view | view := (scheduledControllers at: index) view. view == aView ifTrue: [index >= scheduledControllers size ifTrue: [^ self]. ^ self restore: aRectangle below: index+1 without: aView]. view isNil ifTrue:[^self]. view displayOn: ((BitBlt current toForm: Display) clipRect: aRectangle). index >= scheduledControllers size ifTrue: [^ self]. (aRectangle areasOutside: view windowBox) do: [:rect | self restore: rect below: index + 1 without: aView]! ! !Controller methodsFor: 'basic control sequence' stamp: 'ssa 5/11/2010 16:45'! controlLoop "Sent by Controller|startUp as part of the standard control sequence. Controller|controlLoop sends the message Controller|isControlActive to test for loop termination. As long as true is returned, the loop continues. When false is returned, the loop ends. Each time through the loop, the message Controller|controlActivity is sent." [self isControlActive] whileTrue: ["self killExtraUIProcesses." self interActivityPause. self controlActivity. Processor yield]. self lastProcessRunningMe: nil! ! !Controller methodsFor: 'basic control sequence' stamp: 'dmu 3/22/2010 14:25'! interActivityPause "if we are looping quickly, insert a short delay. Thus if we are just doing UI stuff, we won't take up much CPU" | currentTime wait | [RVMTester isRVM ifTrue: [Processor yield. ^ self].]. MinActivityLapse ifNotNil: [ lastActivityTime ifNotNil: [ currentTime := Time millisecondClockValue. wait := lastActivityTime + MinActivityLapse - currentTime. wait > 0 ifTrue: [ wait <= MinActivityLapse "big waits happen after a snapshot" ifTrue: [DisplayScreen checkForNewScreenSize. "(Delay forMilliseconds: wait) wait "]. ]. ]. ]. lastActivityTime := Time millisecondClockValue.! ! !Controller methodsFor: '*Ly' stamp: 'dmu 3/29/2010 00:21'! killExtraUIProcesses | p lp | p _ Processor thisProcess. lp _ self lastProcessRunningMe. p == lp ifTrue: [self killCounter: 0. ^ self]. lp isRunning ifTrue: [ self killCounter < 5 ifTrue: [ self killCounter: self killCounter + 1. ^ self. ]. self killCounter: 0. Transcript cr;show:'Controller>>killExtraUIProcesses working, killing process hash=',p identityHash printString. p terminate ] "1 foo" "2 timesRepeat:[[self halt]fork]"! ! !Controller methodsFor: 'accessing' stamp: 'dmu 3/26/2010 14:59'! killCounter "Answer the value of killCounter" killCounter isNil ifTrue:[self killCounter: 0]. ^ killCounter! ! !Controller methodsFor: 'accessing' stamp: 'dmu 3/26/2010 14:59'! killCounter: anObject "Set the value of killCounter" killCounter _ anObject! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:18'! lastActivityTime "Answer the value of lastActivityTime" lastActivityTime isNil ifTrue:[self lastActivityTime: nil]. ^ lastActivityTime! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:18'! lastActivityTime: anObject "Set the value of lastActivityTime" lastActivityTime _ anObject! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:28'! lastProcessRunningMe "Answer the value of lastProcessRunningMe" lastProcessRunningMe isNil ifTrue:[self lastProcessRunningMe: Processor thisProcess]. ^ lastProcessRunningMe! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:18'! lastProcessRunningMe: anObject "Set the value of lastProcessRunningMe" lastProcessRunningMe _ anObject! ! !CopyReader methodsFor: 'reading' stamp: ''! read: aClass "Ignore aClass and grab the object directly from the stream. aClass is typically Integer, Float, Symbol, etc. Assume the object was put on the stream using CopyWriter>store: (look there for more info)." | anObject | anObject _ stream next. position _ position + 1. ^anObject! ! !CopyReader methodsFor: 'testing' stamp: ''! isCopier ^true! ! !CopyWriter methodsFor: 'testing' stamp: ''! isCopier ^true! ! !CopyWriter methodsFor: 'writing' stamp: ''! canCopy: anObject "Answer true only if anObject is in the copySet (or if there is no copySet). This can be used by objects which are connected to objects which are not to be copied." ^copySet == nil ifTrue:[true] ifFalse:[copySet includes: anObject]! ! !CopyWriter methodsFor: 'writing' stamp: ''! copySet: aCollection "Set the set of objects that should be copied." copySet _ aCollection! ! !CopyWriter methodsFor: 'writing' stamp: ''! store: anObject "Put anObject directly on the Stream... don't convert it to an ascii String since it's not going to a file. anObject will typically be a Symbol, Number, etc." stream nextPut: anObject. position _ position + 1! ! !Delay methodsFor: 'as yet unclassified' stamp: 'dmu 5/10/2009 02:54'! spinWait | t | t _ Time millisecondClockValue + delayDuration. [t < Time millisecondClockValue] whileTrue: [Processor yield]! ! !DisplayObject methodsFor: 'displaying-generic' stamp: 'ssa 9/4/2009 10:47'! displayOn: aDisplayMedium at: aDisplayPoint "Display the receiver located at aDisplayPoint with default settings for rule and halftone." self displayOn: aDisplayMedium at: aDisplayPoint clippingBox: aDisplayMedium boundingBox rule: Form paint fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic' stamp: 'ssa 12/17/2009 16:54'! followCursor "Just show the Form following the mouse. 6/21/96 tk" Cursor blank showWhile: [self follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]. Sensor waitNoButton ! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:50'! border: aRectangle width: borderWidth fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: Form over fillColor: aHalfTone clippingBox: clipRect! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:50'! border: aRectangle width: borderWidth rule: combinationRule fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: combinationRule fillColor: aHalfTone clippingBox: clipRect! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:42'! border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of each edge of the border is determined by the four coordinates of insets. Uses aHalfTone and combinationRule for drawing the border." (aRectangle areasOutside: (aRectangle insetBy: insets)) do: [:edgeStrip | self fill: edgeStrip rule: combinationRule fillColor: aHalfTone clippingBox: clipRect]! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 12/18/2009 06:38'! outlined self border: self boundingBox width: 1! ! !DisplayText methodsFor: 'accessing' stamp: 'ssa 8/27/2009 11:17'! numberOfLines "Answer the number of lines of text in the receiver." ^self text lineCount! ! !DisplayText methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:34'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text is identical to that of the receiver." | para | para _ Paragraph withText: text style: aTextStyle. para foregroundColor: foreColor backgroundColor: backColor. backColor isTransparent ifTrue: [para rule: Form paint]. ^ para! ! !DisplayText methodsFor: 'testing' stamp: 'ssa 1/20/2010 11:00'! isEmpty ^self text isEmpty! ! !False methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:53'! haltIfFalse self halt ! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:23'! bottomCenter ^self width//2@self height ! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! bottomLeft ^0@self height! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! bottomRight ^self extent! ! !Form methodsFor: 'accessing' stamp: 'ssa 8/25/2009 13:22'! displayBox ^Rectangle origin: self offset extent: width @ height! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:22'! leftCenter ^0@(self height//2)! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:22'! rightCenter ^self width @ (self height//2)! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:23'! topCenter ^self width//2@0 ! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! topLeft ^0@0! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! topRight ^self width@0! ! !Form methodsFor: 'converting' stamp: 'ssa 8/28/2009 16:18'! asOpaqueForm ^OpaqueForm figure: self shape: self! ! !Form methodsFor: 'converting' stamp: 'ssa 8/28/2009 11:32'! wrapAround: aPoint "Answer a new form which contains the image of the receiver, but translated by deltaPoint, with wrap-around. Used for realigning halftone masks. Assumes the receiver is 32x32 with zero offset." "[Sensor anyButtonPressed] whileFalse: [((Cursor normal wrapAround: Sensor cursorPoint) magnifyBy: 8) displayAt: 100@100]" | newForm delta | newForm _ Form extent: (width@height) depth: 1.. delta _ (aPoint x\\32)@(aPoint y\\32). delta = (0@0) ifTrue: [^self]. self displayOn: newForm at: delta-(32@32) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta-(32@0) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta-(0@32) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta clippingBox: newForm boundingBox rule: Form paint fillColor: nil. ^newForm! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 09:59'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm aDisplayMedium copyBits: self boundingBox from: self at: aDisplayPoint + self offset clippingBox: clipRectangle rule: rule fillColor: aForm map: (self colormapIfNeededFor: aDisplayMedium). ! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 15:45'! displayTranslucentOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle ((aDisplayMedium isKindOf:Form) ifTrue:[aDisplayMedium]ifFalse:[aDisplayMedium displayMedium]) paintBits: self at: aDisplayPoint + self offset clippingBox: clipRectangle translucent: 0.3! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 15:32'! paintBits: sourceForm at: destOrigin clippingBox: aRect translucent: factor "Make up a BitBlt table and copy the bits with the given colorMap." (BitBlt current destForm: self sourceForm: sourceForm halftoneForm: nil combinationRule: 31 destOrigin: destOrigin sourceOrigin: 0@0 extent: sourceForm extent clipRect: aRect) copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255) " | f f2 f3 | f _ Form fromUser. f replaceColor: (Color r: 0.8 g: 1.0 b: 0.599) withColor: Color transparent. f2 _ Form fromDisplay: (0@0 extent: f extent). f3 _ f2 deepCopy. 0.0 to: 1.0 by: 1.0/32 do: [:t | f3 _ f2 deepCopy. f3 paintBits: f at: 0@0 translucent: t. f3 displayAt: 0@0. (Delay forMilliseconds: 100) wait]. "! ! !Form methodsFor: 'filling' stamp: 'ssa 11/30/2009 13:30'! fill: aRectangle rule: anInteger fillColor: aForm clippingBox: clipRect "Replace a rectangular area of the receiver with the pattern described by aForm according to the rule anInteger." "Display fill: (300@300 extent: 300@100) rule: Form paint fillColor: Color red. Display fill: (300@300 extent: 300@100) rule: Form paint fillColor: Color green clippingBox: (300@300 extent: 150@100)" | bb | bb _ BitBlt current toForm: self. bb clipRect: clipRect. bb copy: aRectangle from: 0@0 in: nil fillColor: aForm rule: anInteger! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 12/17/2009 16:16'! erase self eraseInside: self boundingBox! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 12/17/2009 16:26'! eraseInside: aRect "Erase a transparent rectangular 'hole' in me" " | form| form _ Form extent:100@100 depth: Display depth. form fillColor: Color blue. form eraseInside: (20@20 extent:60@60). form followCursor" | eraser | eraser _ Form extent: self extent depth:1. eraser fill: aRect fillColor: Color black. self eraseShape: eraser! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 4/10/2009 23:42'! nextLifeGeneration "Compute next generation by computing neighbor counts. These are tallied in nbr1, nbr2, nbr4." | all delta nbr1 nbr2 nbr4 carry2 carry4 | all _ 0@0 extent: self extent. nbr1 _ Form extent: self extent. nbr2 _ Form extent: self extent. nbr4 _ Form extent: self extent. carry2 _ Form extent: self extent. carry4 _ Form extent: self extent. nbr1 fillWhite. nbr2 fillWhite. nbr4 fillWhite. 1 to: 8 do: "Three-bit add for each shift of self" [:i | delta _ (i+4\\9//3 - 1)@(i+4\\3 - 1). "8 neighbor deltas" carry2 copy: all from: nbr1 to: 0@0 rule: Form over. carry2 copy: all from: self to: delta rule: Form and. "carry 2" nbr1 copy: all from: self to: delta rule: Form reverse. "sum 1" "(reverse is xor)" carry4 copy: all from: nbr2 to: 0@0 rule: Form over. carry4 copy: all from: carry2 to: 0@0 rule: Form and. "carry 4" nbr2 copy: all from: carry2 to: 0@0 rule: Form reverse. "sum 2" nbr4 copy: all from: carry4 to: 0@0 rule: Form reverse]. "sum 4" "Next gen = ((2s AND self) OR (2s AND 1s)) AND (NOT 4s)" self copy: all from: nbr2 to: 0@0 rule: Form and. nbr1 copy: all from: nbr2 to: 0@0 rule: Form and. self copy: all from: nbr1 to: 0@0 rule: Form under. self copy: all from: nbr4 to: 0@0 rule: Form erase. self borderWidth: 1 fillColor: Color white. "trim edges"! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 4/10/2009 23:39'! nextLifeGenerationBlueBook "|f| f_Form fromUser. 100 timesRepeat:[f nextLifeGeneration display]" | nbr1 nbr2 nbr4 carry2 carry4 all delta | nbr1 := Form extent: self extent. nbr2 := Form extent: self extent. nbr4 := Form extent: self extent. carry2 := Form extent: self extent. carry4 := Form extent: self extent. all := self boundingBox. 1 to: 8 do: [:i | "delta is the offset of the eight neighboring cells" delta := (#(-1 0 1 1 1 0 1 -1 ) at: i) @ (#(1 -1 -1 0 1 1 1 0 ) at: i). carry2 copy: all from: 0 @ 0 in: nbr1 rule: 3. carry2 copy: all from: delta in: self rule: 1. "AND for carry into 2" nbr1 copy: all from: delta in: self rule: 6. "XOR for sum 1" carry4 copy: all from: 0 @ 0 in: nbr2 rule: 3. carry4 copy: all from: 0 @ 0 in: carry2 rule: 1. "AND for carry into 4" nbr2 copy: all from: 0 @ 0 in: carry2 rule: 6. "XOR for sum 2" nbr4 copy: all from: 0 @ 0 in: carry4 rule: 6]. "XOR for sum 4 (ignore carry into 8)" self copy: all from: 0 @ 0 in: nbr2 rule: 1. nbr1 copy: all from: 0 @ 0 in: nbr2 rule: 1. self copy: all from: 0 @ 0 in: nbr1 rule: 7. self copy: all from: 0 @ 0 in: nbr4 rule: 4 "compute next generation"! ! !Form methodsFor: 'scaling, rotation' stamp: 'ssa 8/31/2009 13:43'! rotateBy: deg smoothing: cellSize "Rotate the receiver by the indicated number of degrees." "rot is the destination form, big enough for any angle." | side rot warp r1 pts p center dim | side _ 1 + ((width*width) + (height*height)) asFloat sqrt asInteger. (#(0 90 180 270 360) includes: deg abs) ifTrue:[dim _ self extent]ifFalse:[dim _ side@side]. rot _ Form extent: dim depth: self depth. center _ rot extent // 2. "Now compute the sin and cos constants for the rotation angle." warp _ (WarpBlt current toForm: rot) sourceForm: self; colorMap: (self colormapIfNeededFor: rot); cellSize: cellSize; "installs a new colormap if cellSize > 1" combinationRule: Form over. r1 _ rot boundingBox align: center with: self boundingBox center. pts _ r1 innerCorners collect: [:pt | p _ pt - r1 center. (r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @ (r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))]. warp copyQuad: pts toRect: rot boundingBox. ^ rot " | a f | f _ Form fromDisplay: (0@0 extent: 200@200). a _ 0. [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: (a _ a+5) smoothing: 2) display]. f display "! ! !Form methodsFor: 'scaling, rotation' stamp: 'ssa 11/30/2009 12:57'! scaledToSize: newExtent | scale | newExtent = self extent ifTrue: [^self]. scale _ (newExtent x / self width) @ (newExtent y / self height). ^self magnify: self boundingBox by: scale smoothing: 2. ! ! !Form methodsFor: 'printing' stamp: ''! archiveOn: anArchiver "Always use #storeOn: and #readFrom:" " anArchiver isCopier ifFalse: [^super archiveOn: anArchiver]." anArchiver storeObject: self; storeClass: self class; store: self.! ! !ColorForm methodsFor: 'private' stamp: 'ssa 11/26/2009 22:44'! setExtent: extent depth: bitsPerPixel "Create a virtual bit map with the given extent and bitsPerPixel." | bpp | bpp _ bitsPerPixel. bpp > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits, proceed for 8 bits'. bpp _ 8]. super setExtent: extent depth: bpp. ! ! !DisplayScreen methodsFor: 'displaying' stamp: 'dmu 1/25/2010 11:25'! drawDot5At: point1 "Display drawDot5At: 100@100" Dot5 ifNil: [Dot5 _ Form dotOfSize:5]. Dot5 displayAt: point1! ! !DisplayScreen methodsFor: 'displaying' stamp: 'dmu 3/23/2010 00:02'! drawLineFrom: point1 to: point2 color: aColor "Display drawLineFrom: Point fromUser to: Point fromUser color: Color fromUser" "Display drawLineFrom: 0@0 to: 200@200 color: Color black" "Display drawLineFrom: 0@0 to: 200@200 color: Color white" Dot1 ifNil: [Dot1 _ Form dotOfSize:1]. self drawLine: Dot1 from: point1 to: point2 clippingBox: self boundingBox rule: Form paint fillColor: aColor ! ! !DisplayScreen methodsFor: 'displaying' stamp: 'dmu 1/25/2010 11:27'! eraseDot5At: point1 "Display eraseDot5At: 100@100" Blank5 ifNil: [Blank5 _ (Form dotOfSize:5) fillWhite]. Blank5 displayAt: point1! ! !DisplayScreen methodsFor: 'displaying' stamp: 'dmu 3/23/2010 00:03'! eraseLineFrom: point1 to: point2 color: aColor "Display eraseLineFrom: Point fromUser to: Point fromUser color: Color fromUser" "Display eraseLineFrom: 0@0 to: 200@200 color: Color black" "Display eraseLineFrom: 0@0 to: 200@200 color: Color white" Dot1 ifNil: [Dot1 _ Form dotOfSize:1]. self drawLine: Dot1 from: point1 to: point2 clippingBox: self boundingBox rule: Form erase fillColor: aColor ! ! !DisplayScreen methodsFor: 'displaying' stamp: 'ssa 8/23/2009 15:06'! outline: rectBlock do: effectBlock while: durationBlock width: borderWidth halftone: halftone "Display an evolving rectangle dynamically. rectBlock supplies a rectangle, durationBlock supplies true, then false to terminate. effectBlock is executed at each iteration." | oldRect edges rect | oldRect _ rectBlock value rounded. edges _ oldRect areasOutside: (oldRect insetBy: borderWidth). edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. [durationBlock value] whileTrue: [rect _ rectBlock value rounded. rect = oldRect ifFalse: [edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. effectBlock value. edges _ rect areasOutside: (rect insetBy: borderWidth). edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. oldRect _ rect]]. edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. ^ oldRect! ! !DisplayScreen methodsFor: 'displaying' stamp: 'ssa 8/23/2009 15:05'! outline: rectBlock while: durationBlock width: borderWidth halftone: halftone "Display an evolving rectangle dynamically. rectBlock supplies a rectangle, durationBlock supplies true, then false to terminate." ^self outline: rectBlock do: [] while: durationBlock width: borderWidth halftone: halftone! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 10:14'! boundingBox clippingBox == nil ifTrue: [self clippingBox: super boundingBox]. ^ clippingBox copy! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 09:59'! clippingTo: aRect do: aBlock "Display clippingTo: Rectangle fromUser do: [ScheduledControllers restore: Display fullBoundingBox]" | saveClip | saveClip _ clippingBox. self clippingBox: aRect. aBlock value. self clippingBox: saveClip! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 09:59'! fullScreen "Display fullScreen" ScreenSave notNil ifTrue: [Display _ ScreenSave]. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'private' stamp: 'ssa 8/24/2009 10:00'! copyFrom: aForm "Take on all state of aForm, with complete sharing" super copyFrom: aForm. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'private' stamp: 'ssa 8/24/2009 10:00'! setExtent: aPoint depth: bitsPerPixel "DisplayScreen startUp" "This method is critical. If the setExtent fails, there will be no proper display on which to show the error condition..." "ar 5/1/1999: ... and that is exactly why we check for the available display depths first." "RAA 27 Nov 99 - if depth and extent are the same and acceptable, why go through this. also - record when we change so worlds can tell if it is time to repaint" (depth == bitsPerPixel and: [aPoint = self extent and: [self supportsDisplayDepth: bitsPerPixel]]) ifFalse: [ bits _ nil. "Free up old bitmap in case space is low" DisplayChangeSignature _ (DisplayChangeSignature ifNil: [0]) + 1. (self supportsDisplayDepth: bitsPerPixel) ifTrue:[super setExtent: aPoint depth: bitsPerPixel] ifFalse:["Search for a suitable depth" super setExtent: aPoint depth: self findAnyDisplayDepth]. ]. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'accessing' stamp: 'ssa 8/24/2009 10:10'! clippingBox: aRect clippingBox _ aRect ! ! !ImageReadWriter methodsFor: 'accessing' stamp: ''! nextImage "Dencoding an image on stream and answer the image." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'accessing' stamp: ''! nextPutImage: anImage "Encoding anImage on stream." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! atEnd ^stream atEnd! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'sd 1/30/2004 15:18'! close stream close! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! contents ^stream contents! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! cr ^stream nextPut: Character cr asInteger! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! lf "PPM and PBM are used LF as CR." ^stream nextPut: Character lf asInteger! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! next ^stream next! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! next: size ^stream next: size! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextLong "Read a 32-bit quantity from the input stream." ^(stream next bitShift: 24) + (stream next bitShift: 16) + (stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextLongPut: a32BitW "Write out a 32-bit integer as 32 bits." stream nextPut: ((a32BitW bitShift: -24) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -16) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a32BitW bitAnd: 16rFF). ^a32BitW! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextPut: aByte ^stream nextPut: aByte! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextPutAll: aByteArray ^stream nextPutAll: aByteArray! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextWord "Read a 16-bit quantity from the input stream." ^(stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! nextWordPut: a16BitW "Write out a 16-bit integer as 16 bits." stream nextPut: ((a16BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a16BitW bitAnd: 16rFF). ^a16BitW! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'tao 10/23/97 18:00'! peekFor: aValue ^stream peekFor: aValue! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! position ^stream position! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! position: anInteger ^stream position: anInteger! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! size ^stream size! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! skip: anInteger ^stream skip: anInteger! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! space ^stream nextPut: Character space asInteger! ! !ImageReadWriter methodsFor: 'stream access' stamp: ''! tab ^stream nextPut: Character tab asInteger! ! !ImageReadWriter methodsFor: 'private' stamp: ''! changePadOfBits: bits width: width height: height depth: depth from: oldPad to: newPad "Change padding size of bits." | srcRowByteSize dstRowByteSize newBits srcRowBase rowEndOffset | (#(8 16 32) includes: oldPad) ifFalse: [^self error: 'Invalid pad: ', oldPad printString]. (#(8 16 32) includes: newPad) ifFalse: [^self error: 'Invalid pad: ', newPad printString]. srcRowByteSize _ width * depth + oldPad - 1 // oldPad * (oldPad / 8). srcRowByteSize * height = bits size ifFalse: [^self error: 'Incorrect bitmap array size.']. dstRowByteSize _ width * depth + newPad - 1 // newPad * (newPad / 8). newBits _ ByteArray new: dstRowByteSize * height. srcRowBase _ 1. rowEndOffset _ dstRowByteSize - 1. 1 to: newBits size by: dstRowByteSize do: [:dstRowBase | newBits replaceFrom: dstRowBase to: dstRowBase + rowEndOffset with: bits startingAt: srcRowBase. srcRowBase _ srcRowBase + srcRowByteSize]. ^newBits! ! !ImageReadWriter methodsFor: 'private' stamp: ''! hasMagicNumber: aByteArray | position | position _ stream position. ((stream size - position) >= aByteArray size and: [(stream next: aByteArray size) = aByteArray]) ifTrue: [^true]. stream position: position. ^false! ! !ImageReadWriter methodsFor: 'private' stamp: 'sd 1/30/2004 15:18'! on: aStream (stream _ aStream) reset. stream binary. "Note that 'reset' makes a file be text. Must do this after."! ! !ImageReadWriter methodsFor: 'private' stamp: ''! unpackBits: bits depthTo8From: depth with: width height: height pad: pad "Unpack bits of depth 1, 2, or 4 image to it of depth 8 image." | bitMask pixelInByte bitsWidth upBitsWidth stopWidth trailingSize upBits bitIndex upBitIndex val | (#(1 2 4) includes: depth) ifFalse: [^self error: 'depth must be 1, 2, or 4']. (#(8 16 32) includes: pad) ifFalse: [^self error: 'pad must be 8, 16, or 32']. bitMask _ (1 bitShift: depth) - 1. pixelInByte _ 8 / depth. bitsWidth _ width * depth + pad - 1 // pad * (pad / 8). upBitsWidth _ width * 8 + pad - 1 // pad * (pad / 8). stopWidth _ width * depth + 7 // 8. trailingSize _ width - (stopWidth - 1 * pixelInByte). upBits _ ByteArray new: upBitsWidth * height. 1 to: height do: [:i | bitIndex _ i - 1 * bitsWidth. upBitIndex _ i - 1 * upBitsWidth. 1 to: stopWidth - 1 do: [:j | val _ bits at: (bitIndex _ bitIndex + 1). upBitIndex _ upBitIndex + pixelInByte. 1 to: pixelInByte do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. val _ (bits at: (bitIndex _ bitIndex + 1)) bitShift: depth negated * (pixelInByte - trailingSize). upBitIndex _ upBitIndex + trailingSize. 1 to: trailingSize do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. ^ upBits ! ! !ImageReadWriter methodsFor: 'testing' stamp: 'tao 10/27/97 09:26'! understandsImageFormat "Test to see if the image stream format is understood by this decoder. This should be implemented in each subclass of ImageReadWriter so that a proper decoder can be selected without ImageReadWriter having to know about all possible image file types." ^ false! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 6/16/2002 15:36'! nextImage | colors | stream binary. self readHeader. biBitCount = 24 ifTrue:[^self read24BmpFile]. "read the color map" colors := self readColorMap. ^self readIndexedBmpFile: colors! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:48'! read24BmpFile "Read 24-bit pixel data from the given a BMP stream." | form formBits pixelLine bitsIndex bitBlt | form _ Form extent: biWidth@biHeight depth: 32. pixelLine := ByteArray new: (((24 * biWidth) + 31) // 32) * 4. bitsIndex := form height - 1 * biWidth + 1. formBits := form bits. 1 to: biHeight do: [:i | pixelLine := stream nextInto: pixelLine. self read24BmpLine: pixelLine into: formBits startingAt: bitsIndex width: biWidth. bitsIndex := bitsIndex - biWidth. ]. bitBlt := BitBlt toForm: form. bitBlt combinationRule: 7 "bitOr:with:". bitBlt halftoneForm: (Bitmap with: 16rFF000000). bitBlt copyBits. ^ form ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:47'! read24BmpLine: pixelLine into: formBits startingAt: formBitsIndex width: width | pixIndex rgb bitsIndex | pixIndex _ 0. "pre-increment" bitsIndex := formBitsIndex-1. "pre-increment" 1 to: width do: [:j | rgb := (pixelLine at: (pixIndex := pixIndex+1)) + ((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 8) + ((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 16). formBits at: (bitsIndex := bitsIndex+1) put: rgb. ]. ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/24/2005 20:57'! readColorMap "Read colorCount BMP color map entries from the given binary stream. Answer an array of Colors." | colorCount colors maxLevel b g r ccStream | colorCount _ (bfOffBits - 54) // 4. "Note: some programs (e.g. Photoshop 4.0) apparently do not set colorCount; assume that any data between the end of the header and the start of the pixel data is the color map" biBitCount >= 16 ifTrue:[^nil]. colorCount = 0 ifTrue: [ "this BMP file does not have a color map" "default monochrome color map" biBitCount = 1 ifTrue: [^ Array with: Color white with: Color black]. "default gray-scale color map" maxLevel _ (2 raisedTo: biBitCount) - 1. ^ (0 to: maxLevel) collect: [:level | Color gray: (level asFloat / maxLevel)]]. ccStream := ReadStream on: (stream next: colorCount*4). colors _ Array new: colorCount. 1 to: colorCount do: [:i | b _ ccStream next. g _ ccStream next. r _ ccStream next. ccStream next. "skip reserved" colors at: i put: (Color r: r g: g b: b range: 255)]. ^ colors ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 6/16/2002 15:20'! readHeader | reserved | bfType _ stream nextLittleEndianNumber: 2. bfSize _ stream nextLittleEndianNumber: 4. reserved _ stream nextLittleEndianNumber: 4. bfOffBits _ stream nextLittleEndianNumber: 4. biSize _ stream nextLittleEndianNumber: 4. biWidth _ stream nextLittleEndianNumber: 4. biHeight _ stream nextLittleEndianNumber: 4. biPlanes _ stream nextLittleEndianNumber: 2. biBitCount _ stream nextLittleEndianNumber: 2. biCompression _ stream nextLittleEndianNumber: 4. biSizeImage _ stream nextLittleEndianNumber: 4. biXPelsPerMeter _ stream nextLittleEndianNumber: 4. biYPelsPerMeter _ stream nextLittleEndianNumber: 4. biClrUsed _ stream nextLittleEndianNumber: 4. biClrImportant _ stream nextLittleEndianNumber: 4. ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:45'! readIndexedBmpFile: colors "Read uncompressed pixel data of depth d from the given BMP stream, where d is 1, 4, 8, or 16" | form bytesPerRow pixelData pixelLine startIndex map bitBlt mask | colors ifNil:[form _ Form extent: biWidth@biHeight depth: biBitCount] ifNotNil:[form _ ColorForm extent: biWidth@biHeight depth: biBitCount. form colors: colors]. bytesPerRow _ (((biBitCount* biWidth) + 31) // 32) * 4. pixelData _ ByteArray new: bytesPerRow * biHeight. biHeight to: 1 by: -1 do: [:y | pixelLine _ stream next: bytesPerRow. startIndex _ ((y - 1) * bytesPerRow) + 1. pixelData replaceFrom: startIndex to: startIndex + bytesPerRow - 1 with: pixelLine startingAt: 1]. form bits copyFromByteArray: pixelData. biBitCount = 16 ifTrue:[ map := ColorMap shifts: #(8 -8 0 0) masks: #(16rFF 16rFF00 0 0). mask := 16r80008000. ]. biBitCount = 32 ifTrue:[ map := ColorMap shifts: #(24 8 -8 -24) masks: #(16rFF 16rFF00 16rFF0000 16rFF000000). mask := 16rFF000000. ]. map ifNotNil:[ bitBlt := BitBlt toForm: form. bitBlt sourceForm: form. bitBlt colorMap: map. bitBlt combinationRule: Form over. bitBlt copyBits. ]. mask ifNotNil:[ bitBlt := BitBlt toForm: form. bitBlt combinationRule: 7 "bitOr:with:". bitBlt halftoneForm: (Bitmap with: mask). bitBlt copyBits. ]. ^ form ! ! !BMPReadWriter methodsFor: 'testing' stamp: 'ar 6/16/2002 15:27'! understandsImageFormat stream size < 54 ifTrue:[^false]. "min size = BITMAPFILEHEADER+BITMAPINFOHEADER" self readHeader. bfType = 19778 "BM" ifFalse:[^false]. biSize = 40 ifFalse:[^false]. biPlanes = 1 ifFalse:[^false]. bfSize <= stream size ifFalse:[^false]. biCompression = 0 ifFalse:[^false]. ^true! ! !BMPReadWriter methodsFor: 'writing' stamp: 'yo 2/18/2004 17:57'! nextPutImage: aForm | bhSize rowBytes rgb data colorValues depth image ppw scanLineLen | depth := aForm depth. [#(1 4 8 32) includes: depth] whileFalse:[depth := depth + 1 asLargerPowerOfTwo]. image := aForm asFormOfDepth: depth. image unhibernate. bhSize _ 14. "# bytes in file header" biSize _ 40. "info header size in bytes" biWidth := image width. biHeight := image height. biClrUsed _ depth = 32 ifTrue: [0] ifFalse:[1 << depth]. "No. color table entries" bfOffBits _ biSize + bhSize + (4*biClrUsed). rowBytes _ ((depth min: 24) * biWidth + 31 // 32) * 4. biSizeImage _ biHeight * rowBytes. "Write the file header" stream position: 0. stream nextLittleEndianNumber: 2 put: 19778. "bfType = BM" stream nextLittleEndianNumber: 4 put: bfOffBits + biSizeImage. "Entire file size in bytes" stream nextLittleEndianNumber: 4 put: 0. "bfReserved" stream nextLittleEndianNumber: 4 put: bfOffBits. "Offset of bitmap data from start of hdr (and file)" "Write the bitmap info header" stream position: bhSize. stream nextLittleEndianNumber: 4 put: biSize. "info header size in bytes" stream nextLittleEndianNumber: 4 put: image width. "biWidth" stream nextLittleEndianNumber: 4 put: image height. "biHeight" stream nextLittleEndianNumber: 2 put: 1. "biPlanes" stream nextLittleEndianNumber: 2 put: (depth min: 24). "biBitCount" stream nextLittleEndianNumber: 4 put: 0. "biCompression" stream nextLittleEndianNumber: 4 put: biSizeImage. "size of image section in bytes" stream nextLittleEndianNumber: 4 put: 2800. "biXPelsPerMeter" stream nextLittleEndianNumber: 4 put: 2800. "biYPelsPerMeter" stream nextLittleEndianNumber: 4 put: biClrUsed. stream nextLittleEndianNumber: 4 put: 0. "biClrImportant" biClrUsed > 0 ifTrue: [ "write color map; this works for ColorForms, too" colorValues _ image colormapIfNeededForDepth: 32. 1 to: biClrUsed do: [:i | rgb _ colorValues at: i. 0 to: 24 by: 8 do: [:j | stream nextPut: (rgb >> j bitAnd: 16rFF)]]]. depth < 32 ifTrue: [ "depth = 1, 4 or 8." data _ image bits asByteArray. ppw _ 32 // depth. scanLineLen _ biWidth + ppw - 1 // ppw * 4. "# of bytes in line" 1 to: biHeight do: [:i | stream next: scanLineLen putAll: data startingAt: (biHeight-i)*scanLineLen+1. ]. ] ifFalse: [ 1 to: biHeight do:[:i | data _ (image copy: (0@(biHeight-i) extent: biWidth@1)) bits. 1 to: data size do: [:j | stream nextLittleEndianNumber: 3 put: (data at: j)]. 1 to: (data size*3)+3//4*4-(data size*3) do: [:j | stream nextPut: 0 "pad to 32-bits"] ]. ]. stream position = (bfOffBits + biSizeImage) ifFalse: [self error:'Write failure']. stream close.! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:43'! delay: aNumberOrNil "Set delay for next image in hundredth (1/100) of seconds" delay := aNumberOrNil! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:39'! loopCount: aNumber "Set looping. This must be done before any image is written!!" loopCount := aNumber! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'sd 1/30/2004 15:18'! nextImage "Read in the next GIF image from the stream. Read it all into memory first for speed." | f thisImageColorTable | stream class == ReadWriteStream ifFalse: [ stream binary. self on: (ReadWriteStream with: (stream contentsOfEntireFile))]. localColorTable _ nil. self readHeader. f _ self readBody. self close. f == nil ifTrue: [^ self error: 'corrupt GIF file']. thisImageColorTable _ localColorTable ifNil: [colorPalette]. transparentIndex ifNotNil: [ transparentIndex + 1 > thisImageColorTable size ifTrue: [ thisImageColorTable _ thisImageColorTable forceTo: transparentIndex + 1 paddingWith: Color white ]. thisImageColorTable at: transparentIndex + 1 put: Color transparent ]. f colors: thisImageColorTable. ^ f ! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'ar 10/24/2005 22:52'! nextPutImage: aForm | reduced tempForm | aForm unhibernate. aForm depth > 8 ifTrue:[ reduced := aForm colorReduced. "minimize depth" reduced depth > 8 ifTrue: [ "Not enough color space; do it the hard way." reduced := reduced asFormOfDepth: 8]. ] ifFalse:[reduced := aForm]. reduced depth < 8 ifTrue: [ "writeBitData: expects depth of 8" tempForm := reduced class extent: reduced extent depth: 8. (reduced isColorForm) ifTrue:[ tempForm copyBits: reduced boundingBox from: reduced at: 0@0 clippingBox: reduced boundingBox rule: Form over fillColor: nil map: nil. tempForm colors: reduced colors. ] ifFalse: [reduced displayOn: tempForm]. reduced := tempForm. ]. (reduced isColorForm) ifTrue:[ (reduced colorsUsed includes: Color transparent) ifTrue: [ transparentIndex := (reduced colors indexOf: Color transparent) - 1. ] ] ifFalse: [transparentIndex := nil]. width := reduced width. height := reduced height. bitsPerPixel := reduced depth. colorPalette := reduced colormapIfNeededForDepth: 32. interlace := false. self writeHeader. self writeBitData: reduced bits. ! ! !GIFReadWriter methodsFor: 'accessing' stamp: '6/18/97 13:18 '! setStream: aStream "Feed it in from an existing source" stream _ aStream! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'di 9/15/1998 09:53'! understandsImageFormat ^('abc' collect: [:x | stream next asCharacter]) = 'GIF'! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: ''! flushCode self flushBits! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'tk 9/14/97 16:25'! readPixelFrom: bits "Since bits is a Bitmap with 32 bit values, watch out for the padding at the end of each row. But, GIF format already wants padding to 32 bit boundary!! OK as is. tk 9/14/97" | pixel | ypos >= height ifTrue: [^nil]. pixel _ bits byteAt: (ypos * rowByteSize + xpos + 1). self updatePixelPosition. ^pixel! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:21'! writeBitData: bits "using modified Lempel-Ziv Welch algorithm." | maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel index disp nomatch | pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ width * 8 + 31 // 32 * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ WriteStream on: (ByteArray new: 256). maxBits _ 12. maxMaxCode _ 1 bitShift: maxBits. tSize _ 5003. prefixTable _ Array new: tSize. suffixTable _ Array new: tSize. initCodeSize _ bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. self nextPut: initCodeSize. self setParameters: initCodeSize. tShift _ 0. fCode _ tSize. [fCode < 65536] whileTrue: [tShift _ tShift + 1. fCode _ fCode * 2]. tShift _ 8 - tShift. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self writeCodeAndCheckCodeSize: clearCode. ent _ self readPixelFrom: bits. [(pixel _ self readPixelFrom: bits) == nil] whileFalse: [ fCode _ (pixel bitShift: maxBits) + ent. index _ ((pixel bitShift: tShift) bitXor: ent) + 1. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index] ifFalse: [nomatch _ true. (suffixTable at: index) >= 0 ifTrue: [disp _ tSize - index + 1. index = 1 ifTrue: [disp _ 1]. "probe" [(index _ index - disp) < 1 ifTrue: [index _ index + tSize]. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index. nomatch _ false. "continue whileFalse:"]. nomatch and: [(suffixTable at: index) > 0]] whileTrue: ["probe"]]. "nomatch" nomatch ifTrue: [self writeCodeAndCheckCodeSize: ent. ent _ pixel. freeCode < maxMaxCode ifTrue: [prefixTable at: index put: freeCode. suffixTable at: index put: fCode. freeCode _ freeCode + 1] ifFalse: [self writeCodeAndCheckCodeSize: clearCode. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self setParameters: initCodeSize]]]]. prefixTable _ suffixTable _ nil. self writeCodeAndCheckCodeSize: ent. self writeCodeAndCheckCodeSize: eoiCode. self flushCode. self nextPut: 0. "zero-length packet" ! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: ''! writeCode: aCode self nextBitsPut: aCode! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: ''! writeCodeAndCheckCodeSize: aCode self writeCode: aCode. self checkCodeSize! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:38'! writeHeader | byte | stream position = 0 ifTrue: [ "For first image only" self nextPutAll: 'GIF89a' asByteArray. self writeWord: width. "Screen Width" self writeWord: height. "Screen Height" byte _ 16r80. "has color map" byte _ byte bitOr: ((bitsPerPixel - 1) bitShift: 5). "color resolution" byte _ byte bitOr: bitsPerPixel - 1. "bits per pixel" self nextPut: byte. self nextPut: 0. "background color." self nextPut: 0. "reserved" colorPalette do: [:pixelValue | self nextPut: ((pixelValue bitShift: -16) bitAnd: 255); nextPut: ((pixelValue bitShift: -8) bitAnd: 255); nextPut: (pixelValue bitAnd: 255)]. loopCount notNil ifTrue: [ "Write a Netscape loop chunk" self nextPut: Extension. self nextPutAll: #(255 11 78 69 84 83 67 65 80 69 50 46 48 3 1) asByteArray. self writeWord: loopCount. self nextPut: 0]]. delay notNil | transparentIndex notNil ifTrue: [ self nextPut: Extension; nextPutAll: #(16rF9 4) asByteArray; nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [9]); writeWord: (delay isNil ifTrue: [0] ifFalse: [delay]); nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [transparentIndex]); nextPut: 0]. self nextPut: ImageSeparator. self writeWord: 0. "Image Left" self writeWord: 0. "Image Top" self writeWord: width. "Image Width" self writeWord: height. "Image Height" byte _ interlace ifTrue: [16r40] ifFalse: [0]. self nextPut: byte. ! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: ''! writeWord: aWord self nextPut: (aWord bitAnd: 255). self nextPut: ((aWord bitShift: -8) bitAnd: 255). ^aWord! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'mir 11/19/2003 12:19'! readBitData "using modified Lempel-Ziv Welch algorithm." | outCodes outCount bitMask initCodeSize code curCode oldCode inCode finChar i bytes f c packedBits hasLocalColor localColorSize maxOutCodes | maxOutCodes _ 4096. offset := self readWord@self readWord. "Image Left@Image Top" width _ self readWord. height _ self readWord. "--- Local Color Table Flag 1 Bit Interlace Flag 1 Bit Sort Flag 1 Bit Reserved 2 Bits Size of Local Color Table 3 Bits ----" packedBits _ self next. interlace _ (packedBits bitAnd: 16r40) ~= 0. hasLocalColor _ (packedBits bitAnd: 16r80) ~= 0. localColorSize _ 1 bitShift: ((packedBits bitAnd: 16r7) + 1). hasLocalColor ifTrue: [localColorTable _ self readColorTable: localColorSize]. pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ ((width + 3) // 4) * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ ReadStream on: ByteArray new. outCodes _ ByteArray new: maxOutCodes + 1. outCount _ 0. bitMask _ (1 bitShift: bitsPerPixel) - 1. prefixTable _ Array new: 4096. suffixTable _ Array new: 4096. initCodeSize _ self next. self setParameters: initCodeSize. bitsPerPixel > 8 ifTrue: [^self error: 'never heard of a GIF that deep']. bytes _ ByteArray new: rowByteSize * height. [(code _ self readCode) = eoiCode] whileFalse: [code = clearCode ifTrue: [self setParameters: initCodeSize. curCode _ oldCode _ code _ self readCode. finChar _ curCode bitAnd: bitMask. "Horrible hack to avoid running off the end of the bitmap. Seems to cure problem reading some gifs!!? tk 6/24/97 20:16" xpos = 0 ifTrue: [ ypos < height ifTrue: [ bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]] ifFalse: [bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]. self updatePixelPosition] ifFalse: [curCode _ inCode _ code. curCode >= freeCode ifTrue: [curCode _ oldCode. outCodes at: (outCount _ outCount + 1) put: finChar]. [curCode > bitMask] whileTrue: [outCount > maxOutCodes ifTrue: [^self error: 'corrupt GIF file (OutCount)']. outCodes at: (outCount _ outCount + 1) put: (suffixTable at: curCode + 1). curCode _ prefixTable at: curCode + 1]. finChar _ curCode bitAnd: bitMask. outCodes at: (outCount _ outCount + 1) put: finChar. i _ outCount. [i > 0] whileTrue: ["self writePixel: (outCodes at: i) to: bits" bytes at: (ypos * rowByteSize) + xpos + 1 put: (outCodes at: i). self updatePixelPosition. i _ i - 1]. outCount _ 0. prefixTable at: freeCode + 1 put: oldCode. suffixTable at: freeCode + 1 put: finChar. oldCode _ inCode. freeCode _ freeCode + 1. self checkCodeSize]]. prefixTable _ suffixTable _ nil. f _ ColorForm extent: width@height depth: 8. f bits copyFromByteArray: bytes. "Squeak can handle depths 1, 2, 4, and 8" bitsPerPixel > 4 ifTrue: [^ f]. "reduce depth to save space" c _ ColorForm extent: width@height depth: (bitsPerPixel = 3 ifTrue: [4] ifFalse: [bitsPerPixel]). f displayOn: c. ^ c ! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'KLC 1/25/2004 14:04'! readBody "Read the GIF blocks. Modified to return a form. " | form extype block blocksize packedFields delay1 | form _ nil. [stream atEnd] whileFalse: [ block _ self next. block = Terminator ifTrue: [^ form]. block = ImageSeparator ifTrue: [ form isNil ifTrue: [form _ self readBitData] ifFalse: [self skipBitData]. ] ifFalse: [ block = Extension ifFalse: [^ form "^ self error: 'Unknown block type'"]. "Extension block" extype _ self next. "extension type" extype = 16rF9 ifTrue: [ "graphics control" self next = 4 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. "==== Reserved 3 Bits Disposal Method 3 Bits User Input Flag 1 Bit Transparent Color Flag 1 Bit ===" packedFields _ self next. delay1 := self next. "delay time 1" delay := (self next*256 + delay1) *10. "delay time 2" transparentIndex _ self next. (packedFields bitAnd: 1) = 0 ifTrue: [transparentIndex _ nil]. self next = 0 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. ] ifFalse: [ "Skip blocks" [(blocksize _ self next) > 0] whileTrue: [ "Read the block and ignore it and eat the block terminator" self next: blocksize]]]]! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: ''! readCode ^self nextBits! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:48'! readColorTable: numberOfEntries | array r g b | array _ Array new: numberOfEntries. 1 to: array size do: [ :i | r _ self next. g _ self next. b _ self next. array at: i put: (Color r: r g: g b: b range: 255) ]. ^array! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:49'! readHeader | is89 byte hasColorMap | (self hasMagicNumber: 'GIF87a' asByteArray) ifTrue: [is89 _ false] ifFalse: [(self hasMagicNumber: 'GIF89a' asByteArray) ifTrue: [is89 _ true] ifFalse: [^ self error: 'This does not appear to be a GIF file']]. self readWord. "skip Screen Width" self readWord. "skip Screen Height" byte _ self next. hasColorMap _ (byte bitAnd: 16r80) ~= 0. bitsPerPixel _ (byte bitAnd: 7) + 1. byte _ self next. "skip background color." self next ~= 0 ifTrue: [is89 ifFalse: [^self error: 'corrupt GIF file (screen descriptor)']]. hasColorMap ifTrue: [colorPalette _ self readColorTable: (1 bitShift: bitsPerPixel)] ifFalse: ["Transcript cr; show: 'GIF file does not have a color map.'." colorPalette _ nil "Palette monochromeDefault"].! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: ''! readWord ^self next + (self next bitShift: 8)! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: ''! skipBitData | misc blocksize | self readWord. "skip Image Left" self readWord. "skip Image Top" self readWord. "width" self readWord. "height" misc _ self next. (misc bitAnd: 16r80) = 0 ifFalse: [ "skip colormap" 1 to: (1 bitShift: (misc bitAnd: 7) + 1) do: [:i | self next; next; next]]. self next. "minimum code size" [(blocksize _ self next) > 0] whileTrue: [self next: blocksize]! ! !GIFReadWriter methodsFor: 'private-bits access' stamp: ''! flushBits remainBitCount = 0 ifFalse: [self nextBytePut: bufByte. remainBitCount _ 0]. self flushBuffer! ! !GIFReadWriter methodsFor: 'private-bits access' stamp: ''! nextBits | integer readBitCount shiftCount byte | integer _ 0. remainBitCount = 0 ifTrue: [readBitCount _ 8. shiftCount _ 0] ifFalse: [readBitCount _ remainBitCount. shiftCount _ remainBitCount - 8]. [readBitCount < codeSize] whileTrue: [byte _ self nextByte. byte == nil ifTrue: [^eoiCode]. integer _ integer + (byte bitShift: shiftCount). shiftCount _ shiftCount + 8. readBitCount _ readBitCount + 8]. (remainBitCount _ readBitCount - codeSize) = 0 ifTrue: [byte _ self nextByte] ifFalse: [byte _ self peekByte]. byte == nil ifTrue: [^eoiCode]. ^(integer + (byte bitShift: shiftCount)) bitAnd: maxCode! ! !GIFReadWriter methodsFor: 'private-bits access' stamp: ''! nextBitsPut: anInteger | integer writeBitCount shiftCount | shiftCount _ 0. remainBitCount = 0 ifTrue: [writeBitCount _ 8. integer _ anInteger] ifFalse: [writeBitCount _ remainBitCount. integer _ bufByte + (anInteger bitShift: 8 - remainBitCount)]. [writeBitCount < codeSize] whileTrue: [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255). shiftCount _ shiftCount - 8. writeBitCount _ writeBitCount + 8]. (remainBitCount _ writeBitCount - codeSize) = 0 ifTrue: [self nextBytePut: (integer bitShift: shiftCount)] ifFalse: [bufByte _ integer bitShift: shiftCount]. ^anInteger! ! !GIFReadWriter methodsFor: 'private-packing' stamp: ''! fillBuffer | packSize | packSize _ self next. bufStream _ ReadStream on: (self next: packSize)! ! !GIFReadWriter methodsFor: 'private-packing' stamp: ''! flushBuffer bufStream isEmpty ifTrue: [^self]. self nextPut: bufStream size. self nextPutAll: bufStream contents. bufStream _ WriteStream on: (ByteArray new: 256)! ! !GIFReadWriter methodsFor: 'private-packing' stamp: ''! nextByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream next! ! !GIFReadWriter methodsFor: 'private-packing' stamp: ''! nextBytePut: aByte bufStream nextPut: aByte. bufStream size >= 254 ifTrue: [self flushBuffer]! ! !GIFReadWriter methodsFor: 'private-packing' stamp: ''! peekByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream peek! ! !GIFReadWriter methodsFor: 'private' stamp: ''! checkCodeSize (freeCode > maxCode and: [codeSize < 12]) ifTrue: [codeSize _ codeSize + 1. maxCode _ (1 bitShift: codeSize) - 1]! ! !GIFReadWriter methodsFor: 'private' stamp: ''! setParameters: initCodeSize clearCode _ 1 bitShift: initCodeSize. eoiCode _ clearCode + 1. freeCode _ clearCode + 2. codeSize _ initCodeSize + 1. maxCode _ (1 bitShift: codeSize) - 1! ! !GIFReadWriter methodsFor: 'private' stamp: ''! updatePixelPosition (xpos _ xpos + 1) >= width ifFalse: [^self]. xpos _ 0. interlace ifFalse: [ypos _ ypos + 1. ^self]. pass = 0 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 4]. ^self]. pass = 1 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 2]. ^self]. pass = 2 ifTrue: [(ypos _ ypos + 4) >= height ifTrue: [pass _ pass + 1. ypos _ 1]. ^self]. pass = 3 ifTrue: [ypos _ ypos + 2. ^self]. ^self error: 'can''t happen'! ! !GIFReadWriter methodsFor: 'stream access' stamp: 'bf 5/29/2003 01:23'! close "Write terminator" self nextPut: Terminator. ^super close! ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'bf 2/25/2005 11:11'! allImages | body colorTable | stream class == ReadWriteStream ifFalse: [ stream binary. self on: (ReadWriteStream with: (stream contentsOfEntireFile))]. localColorTable _ nil. forms _ OrderedCollection new. delays _ OrderedCollection new. comments _ OrderedCollection new. self readHeader. [(body _ self readBody) == nil] whileFalse: [colorTable _ localColorTable ifNil: [colorPalette]. transparentIndex ifNotNil: [transparentIndex + 1 > colorTable size ifTrue: [colorTable _ colorTable forceTo: transparentIndex + 1 paddingWith: Color white]. colorTable at: transparentIndex + 1 put: Color transparent]. body colors: colorTable. forms add: body. delays add: delay]. ^ forms! ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'mir 11/19/2003 14:16'! delays ^ delays! ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'mir 11/19/2003 14:16'! forms ^ forms! ! !AnimatedGIFReadWriter methodsFor: 'private' stamp: 'mir 11/19/2003 12:25'! comment: aString comments add: aString! ! !AnimatedGIFReadWriter methodsFor: 'private-decoding' stamp: 'mir 11/19/2003 12:21'! readBitData | form | form := super readBitData. form offset: offset. ^form! ! !InfiniteForm methodsFor: 'accessing' stamp: 'ssa 8/28/2009 11:40'! depth ^patternForm depth! ! !InfiniteForm methodsFor: 'as yet unclassified' stamp: 'ssa 8/28/2009 11:39'! hasNonStandardPalette ^patternForm hasNonStandardPalette! ! !InputSensor methodsFor: 'mouse' stamp: 'ssa 10/27/2008 20:37'! waitClick "Wait for the user to press any mouse button and release it, then answer with the current location of the cursor." | pt | pt _ self waitButton. self waitNoButton. ^pt! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 7/23/2000 14:37'! eventQueue "Return the current event queue" ^eventQueue! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 4/12/2004 19:36'! eventTicklerProcess "Answer my event tickler process, if any" ^EventTicklerProcess! ! !EventSensor methodsFor: 'accessing' stamp: 'ssa 12/17/2009 13:19'! flushAllButDandDEvents | newQueue oldQueue | newQueue _ SharedQueue new. self eventQueue ifNil: [eventQueue := newQueue. ^self]. oldQueue _ self eventQueue. [oldQueue size > 0] whileTrue: [| item type | item _ oldQueue next. type _ item at: 1. type = EventTypeDragDropFiles ifTrue: [ newQueue nextPut: item]]. eventQueue := newQueue. ! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/7/2001 17:13'! flushEvents eventQueue ifNotNil:[eventQueue flush].! ! !EventSensor methodsFor: 'accessing' stamp: 'ssa 12/17/2009 12:30'! nextEvent "Return the next event from the receiver." eventQueue == nil ifTrue:[^self nextEventSynthesized] ifFalse:[^self nextEventFromQueue] ! ! !EventSensor methodsFor: 'accessing' stamp: 'JMM 11/7/2005 14:38'! peekButtons self wait2ms. self fetchMoreEvents. ^mouseButtons! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/6/2004 14:51'! peekEvent "Look ahead at the next event." eventQueue ifNil:[^nil]. self fetchMoreEvents. ^eventQueue peek! ! !EventSensor methodsFor: 'accessing' stamp: 'tpr 1/5/2005 17:34'! peekKeyboardEvent "Return the next keyboard char event from the receiver or nil if none available" ^eventQueue nextOrNilSuchThat: [:buf | buf first = EventTypeKeyboard and: [(buf fourth) = EventKeyChar]]! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/8/2001 21:45'! peekMousePt ^mousePosition! ! !EventSensor methodsFor: 'accessing' stamp: 'JMM 11/7/2005 14:38'! peekPosition self wait2ms. self fetchMoreEvents. ^mousePosition! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 19:21'! initialize "Initialize the receiver" mouseButtons := 0. mousePosition := 0 @ 0. keyboardBuffer := SharedQueue new. self setInterruptKey: (interruptKey ifNil: [$. asciiValue bitOr: 16r0800 ]). "cmd-." interruptSemaphore := (Smalltalk specialObjectsArray at: 31) ifNil: [Semaphore new]. self flushAllButDandDEvents. inputSemaphore := Semaphore new. hasInputSemaphore := false.! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 20:13'! shutDown super shutDown. EventTicklerProcess ifNotNil: [ EventTicklerProcess terminate. EventTicklerProcess _ nil. ]. inputSemaphore ifNotNil:[Smalltalk unregisterExternalObject: inputSemaphore]. ! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 6/21/2004 10:42'! startUp "Run the I/O process" self initialize. self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! ! !EventSensor methodsFor: 'mouse' stamp: 'ar 5/18/2003 18:27'! createMouseEvent "create and return a new mouse event from the current mouse position; this is useful for restarting normal event queue processing after manual polling" | buttons modifiers pos mapped eventBuffer | eventBuffer _ Array new: 8. buttons _ self primMouseButtons. pos _ self primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. eventBuffer at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ eventBuffer! ! !EventSensor methodsFor: 'private' stamp: 'nk 4/12/2004 20:16'! eventTickler "Poll infrequently to make sure that the UI process is not been stuck. If it has been stuck, then spin the event loop so that I can detect the interrupt key." | delay | delay := Delay forMilliseconds: self class eventPollPeriod. self lastEventPoll. "ensure not nil." [| delta | [ delay wait. delta := Time millisecondClockValue - lastEventPoll. (delta < 0 or: [delta > self class eventPollPeriod]) ifTrue: ["force check on rollover" self fetchMoreEvents]] on: Error do: [:ex | ]. true ] whileTrue.! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/17/2009 14:18'! flushNonKbdEvents eventQueue ifNil: [^ self]. [^self]value. "don't flush so we don't lose events" eventQueue flushAllSuchThat: [:buf | (self isKbdEvent: buf) not] ! ! !EventSensor methodsFor: 'private' stamp: 'nk 6/21/2004 10:40'! installEventTickler "Initialize the interrupt watcher process. Terminate the old process if any." "Sensor installEventTickler" EventTicklerProcess ifNotNil: [EventTicklerProcess terminate]. EventTicklerProcess _ [self eventTickler] forkAt: Processor lowIOPriority. ! ! !EventSensor methodsFor: 'private' stamp: 'di 10/1/2001 20:51'! isKbdEvent: buf ^ (buf at: 1) = EventTypeKeyboard and: [(buf at: 4) = EventKeyChar]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/18/2004 13:21'! lastEventPoll "Answer the last clock value at which fetchMoreEvents was called." ^lastEventPoll ifNil: [ lastEventPoll _ Time millisecondClockValue ]! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:42'! nextEventFromQueue "Return the next event from the receiver." eventQueue isEmpty ifTrue:[self fetchMoreEvents]. eventQueue isEmpty ifTrue:[^nil] ifFalse:[^eventQueue next]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/17/2004 07:09'! nextEventSynthesized "Return a synthesized event. This method is called if an event driven client wants to receive events but the primary user interface is not event-driven (e.g., the receiver does not have an event queue but only updates its state). This can, for instance, happen if a Morphic World is run in an MVC window. To simplify the clients work this method will always return all available keyboard events first, and then (repeatedly) the mouse events. Since mouse events come last, the client can assume that after one mouse event has been received there are no more to come. Note that it is impossible for EventSensor to determine if a mouse event has been issued before so the client must be aware of the possible problem of getting repeatedly the same mouse events. See HandMorph>>processEvents for an example on how to deal with this." | kbd array buttons pos modifiers mapped | "First check for keyboard" array _ Array new: 8. kbd _ self primKbdNext. kbd ifNotNil: ["simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^ array]. "Then check for mouse" pos _ self primMousePt. buttons _ mouseButtons. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ array ! ! !EventSensor methodsFor: 'private' stamp: 'ar 7/23/2000 00:34'! primInterruptSemaphore: aSemaphore "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." interruptSemaphore _ aSemaphore. "backward compatibility: use the old primitive which is obsolete now" super primInterruptSemaphore: aSemaphore! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primKbdNext "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | evtBuf | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse:[^ keyboardBuffer next]. eventQueue ifNotNil: [evtBuf _ eventQueue nextOrNilSuchThat: [:buf | self isKbdEvent: buf]. self flushNonKbdEvents]. ^ evtBuf ifNotNil: [evtBuf at: 3] ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primKbdPeek "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | char | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse: [^ keyboardBuffer peek]. char _ nil. eventQueue ifNotNil: [eventQueue nextOrNilSuchThat: "NOTE: must not return out of this block, so loop to end" [:buf | (self isKbdEvent: buf) ifTrue: [char ifNil: [char _ buf at: 3]]. false "NOTE: block value must be false so Queue won't advance"]]. ^ char ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMouseButtons self fetchMoreEvents. self flushNonKbdEvents. ^ mouseButtons! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMousePt self fetchMoreEvents. self flushNonKbdEvents. ^ mousePosition ! ! !EventSensor methodsFor: 'private' stamp: 'ls 10/23/2000 14:14'! primSetInterruptKey: anInteger "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 ." interruptKey _ anInteger. "backward compatibility: use the old primitive which is obsolete now" super primSetInterruptKey: anInteger! ! !EventSensor methodsFor: 'private' stamp: 'JMM 11/7/2005 14:37'! wait2ms (Delay forMilliseconds: 2) wait.! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 13:21'! fetchMoreEvents "Fetch more events from the VM" | eventBuffer type | "Reset input semaphore so clients can wait for the next events after this one." inputSemaphore isSignaled ifTrue: [ hasInputSemaphore _ true. inputSemaphore initSignals ]. "Remember the last time that I checked for events." lastEventPoll := Time millisecondClockValue. eventBuffer := Array new: 8. [self primGetNextEvent: eventBuffer. type := eventBuffer at: 1. type = EventTypeNone] whileFalse: [self processEvent: eventBuffer ]. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:12'! mapButtons: buttons modifiers: modifiers "Map the buttons to yellow or blue based on the given modifiers. If only the red button is pressed, then map Ctrl-RedButton -> BlueButton. Cmd-RedButton -> YellowButton. " (buttons = RedButtonBit) ifFalse:[^buttons]. (modifiers allMask: CtrlKeyBit) ifTrue:[^BlueButtonBit]. (modifiers allMask: CommandKeyBit) ifTrue:[^YellowButtonBit]. ^buttons! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 13:30'! primGetNextEvent: array "Store the next OS event available into the provided array. Essential. If the VM is not event driven the ST code will fall back to the old-style mechanism and use the state based primitives instead." | kbd buttons modifiers pos mapped | "Simulate the events" array at: 1 put: EventTypeNone. "assume no more events" "First check for keyboard" kbd _ super primKbdNext. kbd = nil ifFalse:[ "simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^self]. "Then check for mouse" buttons _ super primMouseButtons. pos _ super primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. (pos = mousePosition and:[(mapped bitOr: (modifiers bitShift: 3)) = mouseButtons]) ifTrue:[^self]. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:16'! primSetInputSemaphore: semaIndex "Set the input semaphore the VM should use for asynchronously signaling the availability of events. Primitive. Optional." ^nil! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 12:46'! processEvent: evt "Process a single event. This method is run at high priority." | type | type := evt at: 1. "Tackle mouse events first" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1). self queueEvent: evt. self processMouseEvent: evt . ^self]. "Store the event in the queue if there's any" type = EventTypeKeyboard ifTrue: [ "Check if the event is a user interrupt" ((evt at: 4) = 0 and: [((evt at: 3) bitOr: (((evt at: 5) bitAnd: 8) bitShift: 8)) = interruptKey]) ifTrue: ["interrupt key is meta - not reported as event" ^ interruptSemaphore signal]. "Else swap ctrl/alt keys if neeeded.wi" KeyDecodeTable at: {evt at: 3. evt at: 5} ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]. self queueEvent: evt. self processKeyboardEvent: evt . ^self ]. "Handle all events other than Keyborad or Mouse." self queueEvent: evt. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/16/2009 13:12'! processKeyboardEvent: evt "process a keyboard event, updating InputSensor state" | charCode pressCode | "Never update keyboardBuffer if we have an eventQueue active" mouseButtons _ (mouseButtons bitAnd: 7) bitOr: ((evt at: 5) bitShift: 3). eventQueue ifNotNil:[^self]. charCode _ evt at: 3. charCode = nil ifTrue:[^self]. "extra characters not handled in MVC" pressCode _ evt at: 4. pressCode = EventKeyChar ifFalse:[^self]. "key down/up not handled in MVC" "mix in modifiers" charCode _ charCode bitOr: ((evt at: 5) bitShift: 8). keyboardBuffer nextPut: charCode .! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 8/16/2000 22:07'! processMouseEvent: evt "process a mouse event, updating InputSensor state" | modifiers buttons mapped | mousePosition _ (evt at: 3) @ (evt at: 4). buttons _ evt at: 5. modifiers _ evt at: 6. mapped _ self mapButtons: buttons modifiers: modifiers. mouseButtons _ mapped bitOr: (modifiers bitShift: 3).! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 14:17'! queueEvent: evt "Queue the given event in the event queue (if any). Note that the event buffer must be copied since it will be reused later on." eventQueue ifNil:[^self]. eventQueue nextPut: evt clone.! ! !InstructionStream methodsFor: 'scanning' stamp: 'ssa 5/11/2010 16:14'! skipBackBeforeJump "Assuming that the receiver is positioned jast after a jump, skip back one or two bytes, depending on the size of the previous jump instruction." | strm short | strm _ InstructionStream on: self method. (strm scanFor: [:byte | ((short _ byte between: 152 and: 159) or: [byte between: 168 and: 175]) and: [strm pc = (short ifTrue: [pc-1] ifFalse: [pc-2])]]) ifFalse: [self error: 'Where''s the jump??'. self jump: 0]. self jump: (short ifTrue: [-1] ifFalse: [-2]). ! ! !ContextPart methodsFor: 'debugger access' stamp: 'ssa 1/1/1970 00:36'! tempsAndValues "Return a string of the temporary variabls and their current values" | aStream | aStream _ WriteStream on: (String new: 100). self tempNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab. aStream nextPutAll:(RVMTester printPrefixFor:(self tempAt: index)). (self tempAt: index) printOn: aStream. aStream cr]. ^aStream contents! ! !ContextPart methodsFor: 'system simulation' stamp: 'ssa 9/7/2009 14:34'! runSimulated: aBlock contextAtEachStep: block2 "Simulate the execution of the argument, aBlock, until it ends. aBlock MUST NOT contain an '^'. Evaluate block2 with the current context prior to each instruction executed. Answer the simulated value of aBlock." | current | (aBlock isBlock and: [aBlock hasMethodReturn]) ifTrue: [self error: 'simulation of blocks with ^ can run loose']. current _ aBlock asContext. current privSender: self. [current == self] whileFalse: [block2 value: current. current _ current step]. ^ self pop! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'ssa 1/21/2010 16:20'! unwindTo: aContext | ctx unwindBlock | ctx := self. [(ctx _ ctx findNextUnwindContextUpTo: aContext) isNil] whileFalse: [ unwindBlock := ctx tempAt: 1. unwindBlock == nil ifFalse: [ ctx tempAt: 1 put: nil. unwindBlock value] ]. ! ! !BlockContext methodsFor: 'evaluating' stamp: 'dmu 8/17/2009 21:52'! value: arg1 value: arg2 value: arg3 value: arg4 value: arg5 "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than three arguments or if the block is already being executed. Optional. See Object documentation whatIsAPrimitive." ^self valueWithArguments: (Array with: arg1 with: arg2 with: arg3 with: arg4 with: arg5)! ! !BlockContext methodsFor: 'controlling' stamp: 'ssa 8/24/2009 16:18'! loopExit [self value: [^ self]] repeat! ! !BlockContext methodsFor: 'controlling' stamp: 'ssa 8/24/2009 16:43'! untilFalse: aBlock [self value. aBlock value ifFalse: [^ self]] repeat ! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:38'! forkOn: aCore "Create and schedule a Process running the code in the receiver." ^ self newProcess resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:09'! forkOn: aCore with: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'ssa 4/8/2009 20:08'! forkOn: aCore with: anObject at: aPriority "Create and schedule a Process running the code in the receiver." | proc | proc _ self newProcessWith: anObject. proc priority: aPriority. ^proc resumeOn: aCore! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:34'! forkWith: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:33'! newProcessWith: anObject "Answer a Process running the code in the receiver. The process is not scheduled." "Simulation guard" ^Process forContext: [self value: anObject. Processor terminateActive] priority: Processor activePriority! ! !BlockContext methodsFor: 'printing' stamp: 'ssa 11/27/2009 16:55'! asString | str | str _ (((self decompile ifNil: ['--source missing--']) printString replaceAll: Character cr with: Character space) replaceAll: Character tab with: Character space). ^str copyFrom: 2 to: str size - 1! ! !BlockContext methodsFor: 'printing' stamp: 'ssa 8/27/2009 06:12'! printOn: aStream | blockString truncatedBlockString | aStream nextPutAll:(RVMTester printPrefixFor: self). home == nil ifTrue: [^aStream nextPutAll: 'a BlockContext with home=nil']. aStream nextPutAll: '[] in '. super printOn: aStream. aStream nextPutAll: ' '. blockString _ ((self decompile ifNil: ['--source missing--']) printString replaceAll: Character cr with: Character space) replaceAll: Character tab with: Character space. truncatedBlockString _ blockString truncateWithElipsisTo: 800. truncatedBlockString size < blockString size ifTrue: [truncatedBlockString _ truncatedBlockString, ']}']. aStream nextPutAll: truncatedBlockString. ! ! !BlockContext methodsFor: 'private' stamp: 'dmu 11/25/2008 00:18'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess := Processor thisProcess. oldPriority := activeProcess priority. activeProcess priority: Processor highestPriority. result := self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !BlockContext methodsFor: 'converting' stamp: 'ssa 9/7/2009 14:36'! asContext ^self! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:21'! acTableIndex ^acTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:20'! acTableIndex: anInteger acTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:21'! dcTableIndex ^dcTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:20'! dcTableIndex: anInteger dcTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! heightInBlocks ^heightInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:10'! heightInBlocks: anInteger heightInBlocks _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:09'! id ^id! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:09'! id: anObject id _ anObject! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'ar 3/4/2001 01:19'! mcuWidth: mw mcuHeight: mh dctSize: ds mcuWidth _ mw. mcuHeight _ mh. dctSize _ ds. hSampleFactor _ mcuWidth // widthInBlocks. vSampleFactor _ mcuHeight // heightInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:15'! priorDCValue: aNumber priorDCValue _ aNumber! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:43'! qTableIndex ^qTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! qTableIndex: anInteger qTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:18'! totalMcuBlocks ^ heightInBlocks * widthInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:16'! updateDCValue: aNumber priorDCValue _ priorDCValue + aNumber. ^priorDCValue! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! widthInBlocks ^widthInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:10'! widthInBlocks: anInteger widthInBlocks _ anInteger! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'tao 10/23/97 12:24'! initializeSampleStreamBlocks: aCollection mcuBlocks _ aCollection. self resetSampleStream! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'ar 3/4/2001 22:16'! nextSample | dx dy blockIndex sampleIndex sample | dx _ currentX // hSampleFactor. dy _ currentY // vSampleFactor. blockIndex _ dy // dctSize * widthInBlocks + (dx // dctSize) + 1. sampleIndex _ dy \\ dctSize * dctSize + (dx \\ dctSize) + 1. sample _ (mcuBlocks at: blockIndex) at: sampleIndex. currentX _ currentX + 1. currentX < (mcuWidth * dctSize) ifFalse: [currentX _ 0. currentY _ currentY + 1]. ^ sample! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'tao 10/23/97 12:24'! resetSampleStream currentX _ 0. currentY _ 0! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/20/97 14:27'! bits: anObject bits _ anObject! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:31'! lookaheadBits ^lookaheadBits! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:38'! lookaheadSymbol ^lookaheadSymbol! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:59'! maxcode ^maxcode! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/20/97 14:27'! values: anObject values _ anObject! ! !JPEGHuffmanTable methodsFor: 'computation' stamp: 'tao 10/24/97 12:28'! makeDerivedTables | huffSize huffCode code si index lookbits | mincode _ Array new: 16. maxcode _ Array new: 17. valptr _ Array new: 17. huffSize _ OrderedCollection new. 1 to: 16 do: [:l | 1 to: (bits at: l) do: [:i | huffSize add: l]]. huffSize add: 0. code _ 0. huffCode _ Array new: huffSize size. si _ huffSize at: 1. index _ 1. [(huffSize at: index) ~= 0] whileTrue: [[(huffSize at: index) = si] whileTrue: [huffCode at: index put: code. index _ index + 1. code _ code + 1]. code _ code << 1. si _ si + 1]. index _ 1. 1 to: 16 do: [:l | (bits at: l) ~= 0 ifTrue: [valptr at: l put: index. mincode at: l put: (huffCode at: index). index _ index + (bits at: l). maxcode at: l put: (huffCode at: index-1)] ifFalse: [maxcode at: l put: -1]]. maxcode at: 17 put: 16rFFFFF. lookaheadBits _ (Array new: 1 << Lookahead) atAllPut: 0. lookaheadSymbol _ Array new: 1 << Lookahead. index _ 1. 1 to: Lookahead do: [:l | 1 to: (bits at: l) do: [:i | lookbits _ (huffCode at: index) << (Lookahead - l) + 1. (1 << (Lookahead - l) to: 1 by: -1) do: [:ctr | lookaheadBits at: lookbits put: l. lookaheadSymbol at: lookbits put: (values at: index). lookbits _ lookbits + 1]. index _ index + 1]]! ! !JPEGHuffmanTable methodsFor: 'computation' stamp: 'tao 10/21/97 22:44'! valueForCode: code length: length ^ values at: ((valptr at: length) + code - (mincode at: length))! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 13:46'! hACTable hACTable ifNil: [hACTable _ Array new: HuffmanTableSize]. ^ hACTable! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 13:46'! hDCTable hDCTable ifNil: [hDCTable _ Array new: HuffmanTableSize]. ^ hDCTable! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 08:46'! qTable qTable ifNil: [qTable _ Array new: QuantizationTableSize]. ^ qTable! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:18'! colorConvertFloatYCbCrMCU | ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits | ySampleStream _ currentComponents at: 1. cbSampleStream _ currentComponents at: 2. crSampleStream _ currentComponents at: 3. ySampleStream resetSampleStream. cbSampleStream resetSampleStream. crSampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ ySampleStream nextSample. cb _ cbSampleStream nextSample - FloatSampleOffset. cr _ crSampleStream nextSample - FloatSampleOffset. red _ self sampleFloatRangeLimit: (y + (1.40200 * cr)). green _ self sampleFloatRangeLimit: (y - (0.34414 * cb) - (0.71414 * cr)). blue _ self sampleFloatRangeLimit: (y + (1.77200 * cb)). bits at: i put: 16rFF000000 + (red << 16) + (green << 8) + blue]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:17'! colorConvertGrayscaleMCU | ySampleStream y bits | ySampleStream _ currentComponents at: 1. ySampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ (ySampleStream nextSample) + (residuals at: 2). y > MaxSample ifTrue: [y _ MaxSample]. residuals at: 2 put: (y bitAnd: ditherMask). y _ y bitAnd: MaxSample - ditherMask. y < 1 ifTrue: [y _ 1]. bits at: i put: 16rFF000000 + (y<<16) + (y<<8) + y]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:18'! colorConvertIntYCbCrMCU | ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits | ySampleStream _ currentComponents at: 1. cbSampleStream _ currentComponents at: 2. crSampleStream _ currentComponents at: 3. ySampleStream resetSampleStream. cbSampleStream resetSampleStream. crSampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ ySampleStream nextSample. cb _ cbSampleStream nextSample - SampleOffset. cr _ crSampleStream nextSample - SampleOffset. red _ y + ((FIXn1n40200 * cr) // 65536) + (residuals at: 1). red > MaxSample ifTrue: [red _ MaxSample] ifFalse: [red < 0 ifTrue: [red _ 0]]. residuals at: 1 put: (red bitAnd: ditherMask). red _ red bitAnd: MaxSample - ditherMask. red < 1 ifTrue: [red _ 1]. green _ y - ((FIXn0n34414 * cb) // 65536) - ((FIXn0n71414 * cr) // 65536) + (residuals at: 2). green > MaxSample ifTrue: [green _ MaxSample] ifFalse: [green < 0 ifTrue: [green _ 0]]. residuals at: 2 put: (green bitAnd: ditherMask). green _ green bitAnd: MaxSample - ditherMask. green < 1 ifTrue: [green _ 1]. blue _ y + ((FIXn1n77200 * cb) // 65536) + (residuals at: 3). blue > MaxSample ifTrue: [blue _ MaxSample] ifFalse: [blue < 0 ifTrue: [blue _ 0]]. residuals at: 3 put: (blue bitAnd: ditherMask). blue _ blue bitAnd: MaxSample - ditherMask. blue < 1 ifTrue: [blue _ 1]. bits at: i put: 16rFF000000 + (red bitShift: 16) + (green bitShift: 8) + blue]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/7/2001 01:02'! colorConvertMCU ^ currentComponents size = 3 ifTrue: [self useFloatingPoint ifTrue: [self colorConvertFloatYCbCrMCU] ifFalse: [self primColorConvertYCbCrMCU: currentComponents bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.]] ifFalse: [self primColorConvertGrayscaleMCU]! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:19'! primColorConvertGrayscaleMCU self primColorConvertGrayscaleMCU: (currentComponents at: 1) bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/15/2001 18:11'! primColorConvertGrayscaleMCU: componentArray bits: bits residuals: residualArray ditherMask: mask "JPEGReaderPlugin doPrimitive: #primitiveColorConvertGrayscaleMCU." ^self colorConvertGrayscaleMCU! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 21:36'! primColorConvertIntYCbCrMCU self primColorConvertYCbCrMCU: currentComponents bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 21:36'! primColorConvertYCbCrMCU: componentArray bits: bits residuals: residualArray ditherMask: mask ^self colorConvertIntYCbCrMCU! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'tao 10/26/97 15:43'! sampleFloatRangeLimit: aNumber ^ (aNumber rounded max: 0) min: MaxSample! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'di 9/15/1998 14:30'! sampleRangeLimit: aNumber aNumber < 0 ifTrue: [^ 0]. aNumber > MaxSample ifTrue: [^ MaxSample]. ^ aNumber! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 15:16'! dctFloatRangeLimit: value ^ (value / 8.0) + FloatSampleOffset.! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 16:34'! idctBlockFloat: anArray component: aColorComponent | t0 t1 t2 t3 t4 t5 t6 t7 t10 t11 t12 t13 z5 z10 z11 z12 z13 qt ws | qt _ self qTable at: (aColorComponent qTableIndex). ws _ Array new: DCTSize2. "Pass 1: process columns from input, store into work array" 1 to: DCTSize do: [:i | t0 _ (anArray at: i) * (qt at: i). t1 _ (anArray at: (DCTSize*2 + i)) * (qt at: (DCTSize*2 + i)). t2 _ (anArray at: (DCTSize*4 + i)) * (qt at: (DCTSize*4 + i)). t3 _ (anArray at: (DCTSize*6 + i)) * (qt at: (DCTSize*6 + i)). t10 _ t0 + t2. t11 _ t0 - t2. t13 _ t1 + t3. t12 _ (t1 - t3) * DCTK1 - t13. t0 _ t10 + t13. t3 _ t10 - t13. t1 _ t11 + t12. t2 _ t11 - t12. t4 _ (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)). t5 _ (anArray at: (DCTSize*3 + i)) * (qt at: (DCTSize*3 + i)). t6 _ (anArray at: (DCTSize*5 + i)) * (qt at: (DCTSize*5 + i)). t7 _ (anArray at: (DCTSize*7 + i)) * (qt at: (DCTSize*7 + i)). z13 _ t6 + t5. z10 _ t6 - t5. z11 _ t4 + t7. z12 _ t4 - t7. t7 _ z11 + z13. t11 _ (z11 - z13) * DCTK1. z5 _ (z10 + z12) * DCTK2. t10 _ DCTK3 * z12 - z5. t12 _ DCTK4 * z10 + z5. t6 _ t12 - t7. t5 _ t11 - t6. t4 _ t10 + t5. ws at: i put: t0 + t7. ws at: (DCTSize*7 + i) put: t0 - t7. ws at: (DCTSize + i) put: t1 + t6. ws at: (DCTSize*6 + i) put: t1 - t6. ws at: (DCTSize*2 + i) put: t2 + t5. ws at: (DCTSize*5 + i) put: t2 - t5. ws at: (DCTSize*4 + i) put: t3 + t4. ws at: (DCTSize*3 + i) put: t3 - t4]. "Pass 2: process rows from the workspace" (0 to: DCTSize2-DCTSize by: DCTSize) do: [:i | t10 _ (ws at: (i+1)) + (ws at: (i+5)). t11 _ (ws at: (i+1)) - (ws at: (i+5)). t13 _ (ws at: (i+3)) + (ws at: (i+7)). t12 _ ((ws at: (i+3)) - (ws at: (i+7))) * DCTK1 - t13. t0 _ t10 + t13. t3 _ t10 - t13. t1 _ t11 + t12. t2 _ t11 - t12. z13 _ (ws at: (i+6)) + (ws at: (i+4)). z10 _ (ws at: (i+6)) - (ws at: (i+4)). z11 _ (ws at: (i+2)) + (ws at: (i+8)). z12 _ (ws at: (i+2)) - (ws at: (i+8)). t7 _ z11 + z13. t11 _ (z11 - z13) * DCTK1. z5 _ (z10 + z12) * DCTK2. t10 _ DCTK3 * z12 - z5. t12 _ DCTK4 * z10 + z5. t6 _ t12 - t7. t5 _ t11 - t6. t4 _ t10 + t5. "final output stage: scale down by a factor of 8 and range-limit" anArray at: (i+1) put: (self dctFloatRangeLimit: (t0 + t7)). anArray at: (i+8) put: (self dctFloatRangeLimit: (t0 - t7)). anArray at: (i+2) put: (self dctFloatRangeLimit: (t1 + t6)). anArray at: (i+7) put: (self dctFloatRangeLimit: (t1 - t6)). anArray at: (i+3) put: (self dctFloatRangeLimit: (t2 + t5)). anArray at: (i+6) put: (self dctFloatRangeLimit: (t2 - t5)). anArray at: (i+5) put: (self dctFloatRangeLimit: (t3 + t4)). anArray at: (i+4) put: (self dctFloatRangeLimit: (t3 - t4))] ! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:35'! idctBlockInt: anArray component: aColorComponent ^self idctBlockInt: anArray qt: (self qTable at: aColorComponent qTableIndex)! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:34'! idctBlockInt: anArray qt: qt | ws anACTerm dcval z1 z2 z3 z4 z5 t0 t1 t2 t3 t10 t11 t12 t13 shift | ws _ Array new: DCTSize2. "Pass 1: process columns from anArray, store into work array" shift _ 1 bitShift: ConstBits - Pass1Bits. 1 to: DCTSize do: [:i | anACTerm _ nil. 1 to: DCTSize-1 do:[:row| anACTerm ifNil:[ (anArray at: row * DCTSize + i) = 0 ifFalse:[anACTerm _ row]]]. anACTerm == nil ifTrue: [dcval _ (anArray at: i) * (qt at: 1) bitShift: Pass1Bits. 0 to: DCTSize-1 do: [:j | ws at: (j * DCTSize + i) put: dcval]] ifFalse: [z2 _ (anArray at: (DCTSize * 2 + i)) * (qt at: (DCTSize * 2 + i)). z3 _ (anArray at: (DCTSize * 6 + i)) * (qt at: (DCTSize * 6 + i)). z1 _ (z2 + z3) * FIXn0n541196100. t2 _ z1 + (z3 * FIXn1n847759065 negated). t3 _ z1 + (z2 * FIXn0n765366865). z2 _ (anArray at: i) * (qt at: i). z3 _ (anArray at: (DCTSize * 4 + i)) * (qt at: (DCTSize * 4 + i)). t0 _ (z2 + z3) bitShift: ConstBits. t1 _ (z2 - z3) bitShift: ConstBits. t10 _ t0 + t3. t13 _ t0 - t3. t11 _ t1 + t2. t12 _ t1 - t2. t0 _ (anArray at: (DCTSize * 7 + i)) * (qt at: (DCTSize * 7 + i)). t1 _ (anArray at: (DCTSize * 5 + i)) * (qt at: (DCTSize * 5 + i)). t2 _ (anArray at: (DCTSize * 3 + i)) * (qt at: (DCTSize * 3 + i)). t3 _ (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)). z1 _ t0 + t3. z2 _ t1 + t2. z3 _ t0 + t2. z4 _ t1 + t3. z5 _ (z3 + z4) * FIXn1n175875602. t0 _ t0 * FIXn0n298631336. t1 _ t1 * FIXn2n053119869. t2 _ t2 * FIXn3n072711026. t3 _ t3 * FIXn1n501321110. z1 _ z1 * FIXn0n899976223 negated. z2 _ z2 * FIXn2n562915447 negated. z3 _ z3 * FIXn1n961570560 negated. z4 _ z4 * FIXn0n390180644 negated. z3 _ z3 + z5. z4 _ z4 + z5. t0 _ t0 + z1 + z3. t1 _ t1 +z2 +z4. t2 _ t2 + z2 + z3. t3 _ t3 + z1 + z4. ws at: i put: (t10 + t3) >> (ConstBits - Pass1Bits). ws at: (DCTSize * 7 + i) put: (t10 - t3) // shift. ws at: (DCTSize * 1 + i) put: (t11 + t2) // shift. ws at: (DCTSize * 6 + i) put: (t11 - t2) // shift. ws at: (DCTSize * 2 + i) put: (t12 + t1) // shift. ws at: (DCTSize * 5 + i) put: (t12 - t1) // shift. ws at: (DCTSize * 3 + i) put: (t13 + t0) // shift. ws at: (DCTSize * 4 + i) put: (t13 - t0) // shift]]. "Pass 2: process rows from work array, store back into anArray" shift _ 1 bitShift: ConstBits + Pass1Bits + 3. 0 to: DCTSize2-DCTSize by: DCTSize do: [:i | z2 _ ws at: i + 3. z3 _ ws at: i + 7. z1 _ (z2 + z3) * FIXn0n541196100. t2 _ z1 + (z3 * FIXn1n847759065 negated). t3 _ z1 + (z2 * FIXn0n765366865). t0 _ (ws at: (i + 1)) + (ws at: (i + 5)) bitShift: ConstBits. t1 _ (ws at: (i + 1)) - (ws at: (i + 5)) bitShift: ConstBits. t10 _ t0 + t3. t13 _ t0 - t3. t11 _ t1 + t2. t12 _ t1 -t2. t0 _ ws at: (i + 8). t1 _ ws at: (i + 6). t2 _ ws at: (i + 4). t3 _ ws at: (i + 2). z1 _ t0 + t3. z2 _ t1 + t2. z3 _ t0 + t2. z4 _ t1 + t3. z5 _ (z3 + z4) * FIXn1n175875602. t0 _ t0 * FIXn0n298631336. t1 _ t1 * FIXn2n053119869. t2 _ t2 * FIXn3n072711026. t3 _ t3 * FIXn1n501321110. z1 _ z1 * FIXn0n899976223 negated. z2 _ z2 * FIXn2n562915447 negated. z3 _ z3 * FIXn1n961570560 negated. z4 _ z4 * FIXn0n390180644 negated. z3 _ z3 + z5. z4 _ z4 + z5. t0 _ t0 + z1 + z3. t1 _ t1 + z2 + z4. t2 _ t2 + z2 + z3. t3 _ t3 + z1 + z4. anArray at: (i + 1) put: (self sampleRangeLimit: (t10 + t3) // shift + SampleOffset). anArray at: (i + 8) put: (self sampleRangeLimit: (t10 - t3) // shift + SampleOffset). anArray at: (i + 2) put: (self sampleRangeLimit: (t11 + t2) // shift + SampleOffset). anArray at: (i + 7) put: (self sampleRangeLimit: (t11 - t2) // shift + SampleOffset). anArray at: (i + 3) put: (self sampleRangeLimit: (t12 + t1) // shift + SampleOffset). anArray at: (i + 6) put: (self sampleRangeLimit: (t12 - t1) // shift + SampleOffset). anArray at: (i + 4) put: (self sampleRangeLimit: (t13 + t0) // shift + SampleOffset). anArray at: (i + 5) put: (self sampleRangeLimit: (t13 - t0) // shift + SampleOffset)]. ! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/7/2001 00:58'! idctMCU | comp fp ci | fp _ self useFloatingPoint. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. fp ifTrue:[ self idctBlockFloat: (mcuSampleBuffer at: i) component: comp. ] ifFalse:[ self primIdctInt: (mcuSampleBuffer at: i) qt: (qTable at: comp qTableIndex)]].! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:37'! primIdctBlockInt: anArray component: aColorComponent ^self primIdctInt: anArray qt: (self qTable at: aColorComponent qTableIndex)! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:35'! primIdctInt: anArray qt: qt ^self idctBlockInt: anArray qt: qt! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 16:16'! scaleQuantizationTable: table | index | index _ 1. 1 to: DCTSize do: [:row | 1 to: DCTSize do: [:col | table at: index put: ((table at: index) * (QTableScaleFactor at: row) * (QTableScaleFactor at: col)) rounded. index _ index + 1]]. ^ table ! ! !JPEGReadWriter methodsFor: 'error handling' stamp: 'tao 10/19/97 12:25'! notSupported: aString self error: aString , ' is not currently supported'! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 20:55'! decodeBlockInto: anArray component: aColorComponent dcTable: huffmanDC acTable: huffmanAC | byte i zeroCount | byte _ stream decodeValueFrom: huffmanDC. byte ~= 0 ifTrue: [byte _ self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte]. byte _ aColorComponent updateDCValue: byte. anArray atAllPut: 0. anArray at: 1 put: byte. i _ 2. [i <= DCTSize2] whileTrue: [byte _ stream decodeValueFrom: huffmanAC. zeroCount _ byte >> 4. byte _ byte bitAnd: 16r0F. byte ~= 0 ifTrue: [i _ i + zeroCount. byte _ self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte. anArray at: (JPEGNaturalOrder at: i) put: byte] ifFalse: [zeroCount = 15 ifTrue: [i _ i + zeroCount] ifFalse: [^ self]]. i _ i + 1] ! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/7/2001 01:00'! decodeMCU | comp ci | (restartInterval ~= 0 and: [restartsToGo = 0]) ifTrue: [self processRestart]. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. self primDecodeBlockInto: (mcuSampleBuffer at: i) component: comp dcTable: (hDCTable at: comp dcTableIndex) acTable: (hACTable at: comp acTableIndex) stream: stream. ]. restartsToGo _ restartsToGo - 1.! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 17:27'! getBits: requestedBits ^stream getBits: requestedBits! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 21:32'! primDecodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable stream: jpegStream ^self decodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 17:40'! processRestart stream resetBitBuffer. self parseNextMarker. currentComponents do: [:c | c priorDCValue: 0]. restartsToGo _ restartInterval.! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 01:17'! scaleAndSignExtend: aNumber inFieldWidth: w aNumber < (1 bitShift: (w - 1)) ifTrue: [^aNumber - (1 bitShift: w) + 1] ifFalse: [^aNumber]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/4/2001 18:38'! initialSOSSetup mcuWidth _ (components detectMax: [:c | c widthInBlocks]) widthInBlocks. mcuHeight _ (components detectMax: [:c | c heightInBlocks]) heightInBlocks. components do:[:c | c mcuWidth: mcuWidth mcuHeight: mcuHeight dctSize: DCTSize]. stream resetBitBuffer.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'mir 6/13/2001 13:06'! okToIgnoreMarker: aMarker ^ (((16rE0 to: 16rEF) includes: aMarker) "unhandled APPn markers" or: [aMarker = 16rDC or: [aMarker = 16rFE]]) "DNL or COM markers" or: [aMarker = 16r99] "Whatever that is"! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/6/2001 22:28'! parseAPPn | length buffer thumbnailLength markerStart | markerStart _ self position. length _ self nextWord. buffer _ self next: 4. (buffer asString = 'JFIF') ifFalse: [ "Skip APPs that we're not interested in" stream next: length-6. ^self]. self next. majorVersion _ self next. minorVersion _ self next. densityUnit _ self next. xDensity _ self nextWord. yDensity _ self nextWord. thumbnailLength _ self next * self next * 3. length _ length - (self position - markerStart). length = thumbnailLength ifFalse: [self error: 'APP0 thumbnail length is incorrect.']. self next: length! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/20/97 13:36'! parseDecoderRestartInterval | length | length _ self nextWord. length = 4 ifFalse: [self error: 'DRI length incorrect']. restartInterval _ self nextWord.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'mir 6/12/2001 11:28'! parseFirstMarker | marker | self next = 16rFF ifFalse: [self error: 'JFIF marker expected']. marker _ self next. marker = 16rD9 ifTrue: [^self "halt: 'EOI encountered.'"]. marker = 16rD8 ifFalse: [self error: 'SOI marker expected']. self parseStartOfInput. ! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/4/2001 18:36'! parseHuffmanTable | length markerStart index bits count huffVal isACTable hTable | markerStart _ self position. length _ self nextWord. [self position - markerStart >= length] whileFalse: [index _ self next. isACTable _ (index bitAnd: 16r10) ~= 0. index _ (index bitAnd: 16r0F) + 1. index > HuffmanTableSize ifTrue: [self error: 'image has more than ', HuffmanTableSize printString, ' quantization tables']. bits _ self next: 16. count _ bits sum. (count > 256 or: [(count > (length - (self position - markerStart)))]) ifTrue: [self error: 'Huffman Table count is incorrect']. huffVal _ self next: count. hTable _ stream buildLookupTable: huffVal counts: bits. isACTable ifTrue: [self hACTable at: index put: hTable] ifFalse: [self hDCTable at: index put: hTable]].! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/24/97 17:32'! parseNOP "don't need to do anything, here"! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'BG 3/16/2005 08:24'! parseNextMarker "Parse the next marker of the stream" | byte discardedBytes | discardedBytes _ 0. [(byte _ self next) = 16rFF] whileFalse: [discardedBytes _ discardedBytes + 1]. [[(byte _ self next) = 16rFF] whileTrue. byte = 16r00] whileTrue: [discardedBytes _ discardedBytes + 2]. discardedBytes > 0 ifTrue: [self "notifyWithLabel: 'warning: extraneous data discarded'"]. self perform: (JFIFMarkerParser at: byte ifAbsent: [(self okToIgnoreMarker: byte) ifTrue: [#skipMarker] ifFalse: [self error: 'marker ', byte printStringHex , ' cannot be handled']])! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/3/2001 22:19'! parseQuantizationTable | length markerStart n prec value table | markerStart _ self position. length _ self nextWord. [self position - markerStart >= length] whileFalse: [value _ self next. n _ (value bitAnd: 16r0F) + 1. prec _ (value >> 4) > 0. n > QuantizationTableSize ifTrue: [self error: 'image has more than ', QuantizationTableSize printString, ' quantization tables']. table _ IntegerArray new: DCTSize2. 1 to: DCTSize2 do: [:i | value _ (prec ifTrue: [self nextWord] ifFalse: [self next]). table at: (JPEGNaturalOrder at: i) put: value]. self useFloatingPoint ifTrue: [self scaleQuantizationTable: table]. self qTable at: n put: table]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/24/97 17:07'! parseStartOfFile | length markerStart value n | markerStart _ self position. length _ self nextWord. dataPrecision _ self next. dataPrecision = 8 ifFalse: [self error: 'cannot handle ', dataPrecision printString, '-bit components']. height _ self nextWord. width _ self nextWord. n _ self next. (height = 0) | (width = 0) | (n = 0) ifTrue: [self error: 'empty image']. (length - (self position - markerStart)) ~= (n * 3) ifTrue: [self error: 'component length is incorrect']. components _ Array new: n. 1 to: components size do: [:i | components at: i put: (JPEGColorComponent new id: self next; "heightInBlocks: (((value _ self next) >> 4) bitAnd: 16r0F); widthInBlocks: (value bitAnd: 16r0F);" widthInBlocks: (((value _ self next) >> 4) bitAnd: 16r0F); heightInBlocks: (value bitAnd: 16r0F); qTableIndex: self next + 1)]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/22/97 17:38'! parseStartOfInput restartInterval _ 0. densityUnit _ 0. xDensity _ 1. yDensity _ 1 ! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/26/97 21:53'! parseStartOfScan | length n id value dcNum acNum comp | length _ self nextWord. n _ self next. (length ~= (n*2 + 6)) | (n < 1) ifTrue: [self error: 'SOS length is incorrect']. currentComponents _ Array new: n. 1 to: n do: [:i | id _ self next. value _ self next. dcNum _ (value >> 4) bitAnd: 16r0F. acNum _ value bitAnd: 16r0F. comp _ components detect: [:c | c id = id]. comp dcTableIndex: dcNum+1; acTableIndex: acNum+1. currentComponents at: i put: comp]. ss _ self next. se _ self next. value _ self next. ah _ (value >> 4) bitAnd: 16r0F. al _ value bitAnd: 16r0F. self initialSOSSetup. self perScanSetup. sosSeen _ true! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/7/2001 01:01'! perScanSetup mcusPerRow _ (width / (mcuWidth * DCTSize)) ceiling. mcuRowsInScan _ (height / (mcuHeight * DCTSize)) ceiling. (currentComponents size = 3 or: [currentComponents size = 1]) ifFalse: [self error: 'JPEG color space not recognized']. mcuMembership _ OrderedCollection new. currentComponents withIndexDo: [:c :i | c priorDCValue: 0. mcuMembership addAll: ((1 to: c totalMcuBlocks) collect: [:b | i])]. mcuMembership _ mcuMembership asArray. mcuSampleBuffer _ (1 to: mcuMembership size) collect: [:i | IntegerArray new: DCTSize2]. currentComponents withIndexDo: [:c :i | c initializeSampleStreamBlocks: ((1 to: mcuMembership size) select: [:j | i = (mcuMembership at: j)] thenCollect: [:j | mcuSampleBuffer at: j])]. mcuImageBuffer _ Form extent: (mcuWidth @ mcuHeight) * DCTSize depth: 32. restartsToGo _ restartInterval.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/22/97 16:27'! skipMarker | length markerStart | markerStart _ self position. length _ self nextWord. self next: length - (self position - markerStart) ! ! !JPEGReadWriter methodsFor: 'preferences' stamp: 'tao 10/26/97 22:09'! useFloatingPoint ^ false! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/7/2001 00:18'! decompressionTest "Test decompression; don't generate actual image" | xStep yStep x y | MessageTally spyOn:[ ditherMask _ DitherMasks at: 32. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. x _ x + xStep]. y _ y + yStep]. ].! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'tao 9/18/1998 08:53'! nextImage ^ self nextImageDitheredToDepth: Display depth ! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 10/28/2001 16:25'! nextImageDitheredToDepth: depth | form xStep yStep x y bb | ditherMask _ DitherMasks at: depth ifAbsent: [self error: 'can only dither to display depths']. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. form _ Form extent: (width @ height) depth: depth. bb _ BitBlt current toForm: form. bb sourceForm: mcuImageBuffer. bb colorMap: (mcuImageBuffer colormapIfNeededFor: form). bb sourceRect: mcuImageBuffer boundingBox. bb combinationRule: Form over. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. bb destX: x; destY: y; copyBits. x _ x + xStep]. y _ y + yStep]. ^ form! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/4/2001 17:26'! setStream: aStream "Feed it in from an existing source" stream _ JPEGReadStream on: aStream upToEnd.! ! !JPEGReadWriter methodsFor: 'testing' stamp: 'ar 3/4/2001 00:50'! understandsImageFormat "Answer true if the image stream format is understood by this decoder." self next = 16rFF ifFalse: [^ false]. self next = 16rD8 ifFalse: [^ false]. ^ true ! ! !JPEGReadWriter methodsFor: 'private' stamp: 'ar 3/4/2001 17:34'! on: aStream super on: aStream. stream _ JPEGReadStream on: stream upToEnd.! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:34'! primImageHeight: aJPEGCompressStruct self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primImageWidth: aJPEGCompressStruct self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGCompressStructSize self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGDecompressStructSize self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGErrorMgr2StructSize self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'ar 11/27/2001 00:39'! primJPEGPluginIsPresent ^false! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGReadHeader: aJPEGDecompressStruct fromByteArray: source errorMgr: aJPEGErrorMgr2Struct self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jmv 12/7/2001 13:45'! primJPEGReadImage: aJPEGDecompressStruct fromByteArray: source onForm: form doDithering: ditherFlag errorMgr: aJPEGErrorMgr2Struct self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGWriteImage: aJPEGCompressStruct onByteArray: destination form: form quality: quality progressiveJPEG: progressiveFlag errorMgr: aJPEGErrorMgr2Struct self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'JMM 1/11/2005 14:56'! compress: aForm quality: quality "Encode the given Form and answer the compressed ByteArray. Quality goes from 0 (low) to 100 (high), where -1 means default." | sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount | aForm unhibernate. "odd width images of depth 16 give problems; avoid them." sourceForm _ (aForm depth = 32) | (aForm width even & (aForm depth = 16)) ifTrue: [aForm] ifFalse: [aForm asFormOfDepth: 32]. jpegCompressStruct _ ByteArray new: self primJPEGCompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. buffer _ ByteArray new: sourceForm width * sourceForm height + 1024. byteCount _ self primJPEGWriteImage: jpegCompressStruct onByteArray: buffer form: sourceForm quality: quality progressiveJPEG: false errorMgr: jpegErrorMgr2Struct. byteCount = 0 ifTrue: [self error: 'buffer too small for compressed data']. ^ buffer copyFrom: 1 to: byteCount ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:01'! imageExtent: aByteArray "Answer the extent of the compressed image encoded in the given ByteArray." | jpegDecompressStruct jpegErrorMgr2Struct w h | jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ^ w @ h ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:23'! nextImage "Decode and answer a Form from my stream." ^ self nextImageSuggestedDepth: Display depth ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'sd 1/30/2004 15:19'! nextImageSuggestedDepth: depth "Decode and answer a Form of the given depth from my stream. Close the stream if it is a file stream. Possible depths are 16-bit and 32-bit." | bytes width height form jpegDecompressStruct jpegErrorMgr2Struct depthToUse | bytes _ stream upToEnd. stream close. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: bytes errorMgr: jpegErrorMgr2Struct. width _ self primImageWidth: jpegDecompressStruct. height _ self primImageHeight: jpegDecompressStruct. "Odd width images of depth 16 gave problems. Avoid them (or check carefully!!)" depthToUse _ ((depth = 32) | width odd) ifTrue: [32] ifFalse: [16]. form _ Form extent: width@height depth: depthToUse. (width = 0 or: [height = 0]) ifTrue: [^ form]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: bytes onForm: form doDithering: true errorMgr: jpegErrorMgr2Struct. ^ form ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:21'! nextPutImage: aForm "Encode the given Form on my stream with default quality." ^ self nextPutImage: aForm quality: -1 progressiveJPEG: false ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'JMM 1/11/2005 14:45'! nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag "Encode the given Form on my stream with the given settings. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG." | sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount | aForm unhibernate. "odd width images of depth 16 give problems; avoid them." sourceForm _ (aForm depth = 32) | (aForm width even & (aForm depth = 16)) ifTrue: [aForm] ifFalse: [aForm asFormOfDepth: 32]. jpegCompressStruct _ ByteArray new: self primJPEGCompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. buffer _ ByteArray new: sourceForm width * sourceForm height + 1024. byteCount _ self primJPEGWriteImage: jpegCompressStruct onByteArray: buffer form: sourceForm quality: quality progressiveJPEG: progressiveFlag errorMgr: jpegErrorMgr2Struct. byteCount = 0 ifTrue: [self error: 'buffer too small for compressed data']. stream next: byteCount putAll: buffer startingAt: 1. self close. ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jmv 12/7/2001 13:49'! uncompress: aByteArray into: aForm "Uncompress an image from the given ByteArray into the given Form. Fails if the given Form has the wrong dimensions or depth. If aForm has depth 16, do ordered dithering." | jpegDecompressStruct jpegErrorMgr2Struct w h | aForm unhibernate. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ((aForm width = w) & (aForm height = h)) ifFalse: [ ^ self error: 'form dimensions do not match']. "odd width images of depth 16 give problems; avoid them" w odd ifTrue: [ aForm depth = 32 ifFalse: [^ self error: 'must use depth 32 with odd width']] ifFalse: [ ((aForm depth = 16) | (aForm depth = 32)) ifFalse: [^ self error: 'must use depth 16 or 32']]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: aByteArray onForm: aForm doDithering: true errorMgr: jpegErrorMgr2Struct. ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jmv 12/7/2001 13:48'! uncompress: aByteArray into: aForm doDithering: ditherFlag "Uncompress an image from the given ByteArray into the given Form. Fails if the given Form has the wrong dimensions or depth. If aForm has depth 16 and ditherFlag = true, do ordered dithering." | jpegDecompressStruct jpegErrorMgr2Struct w h | aForm unhibernate. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ((aForm width = w) & (aForm height = h)) ifFalse: [ ^ self error: 'form dimensions do not match']. "odd width images of depth 16 give problems; avoid them" w odd ifTrue: [ aForm depth = 32 ifFalse: [^ self error: 'must use depth 32 with odd width']] ifFalse: [ ((aForm depth = 16) | (aForm depth = 32)) ifFalse: [^ self error: 'must use depth 16 or 32']]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: aByteArray onForm: aForm doDithering: ditherFlag errorMgr: jpegErrorMgr2Struct. ! ! !JPEGReadWriter2 methodsFor: 'testing' stamp: 'ar 11/27/2001 00:40'! isPluginPresent ^self primJPEGPluginIsPresent! ! !JPEGReadWriter2 methodsFor: 'testing' stamp: 'ar 11/27/2001 00:39'! understandsImageFormat "Answer true if the image stream format is understood by this decoder." self isPluginPresent ifFalse:[^false]. "cannot read it otherwise" self next = 16rFF ifFalse: [^ false]. self next = 16rD8 ifFalse: [^ false]. ^ true ! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 12:15'! hasEquivalentIn: aCollection aCollection detect: [ :each | each withoutListWrapper = item withoutListWrapper ] ifNone: [^false]. ^true! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 4/4/1999 17:58'! sendSettingMessageTo: aModel aModel perform: (self settingSelector ifNil: [^self]) with: self withoutListWrapper ! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 21:31'! settingSelector ^nil! ! !ListItemWrapper methodsFor: 'converting' stamp: 'RAA 3/30/1999 18:17'! asString ^item asString! ! !ListItemWrapper methodsFor: 'converting' stamp: 'RAA 3/31/1999 12:13'! withoutListWrapper ^item withoutListWrapper! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/31/1999 16:32'! contents ^Array new! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 4/1/1999 20:09'! hasContents ^self contents isEmpty not! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 8/3/1999 09:40'! highlightingColor ^Color red! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:22'! icon "Answer a form to be used as icon" ^ nil! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! item "Answer the value of item" item isNil ifTrue:[self item: nil]. ^ item! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! item: anObject "Set the value of item" item _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! model "Answer the value of model" model isNil ifTrue:[self model: nil]. ^ model! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! model: anObject "Set the value of model" model _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 4/2/1999 15:14'! preferredColor ^nil! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/30/1999 18:27'! setItem: anObject item _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/31/1999 16:44'! setItem: anObject model: aModel item _ anObject. model _ aModel.! ! !MSWScrollBarController methodsFor: 'delays' stamp: 'ssa 1/15/98 13:51'! defaultUnitScrollDelay "Answer the delay to use when unit scrolling, i.e., pressing the up or down button." ^Delay forMilliseconds: 50! ! !MSWScrollBarController methodsFor: 'delays' stamp: 'ssa 1/15/98 13:52'! wait self defaultUnitScrollDelay wait! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 8/22/2009 15:13'! elevatorBox "Compute this each time since the view content my change." | box originY extentY | box _ self view elevatorShaft. extentY _ self viewToScroll percentVisibleContent * box height. originY _ (self viewToScroll percentPreceedingContent * box height) min: box height - extentY. ^(box origin x asInteger @ (box origin y + originY) asInteger max: box origin) extent: ((box extent x asInteger @ extentY asInteger) min: box extent max: 10@box width)! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 12/5/97 16:00'! scroller ^self viewToScroll controller! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 1/15/98 13:50'! unitScrollDelay "<^hOf Delay>" "ssa 1/15/98 13:50 - Answer the instance variable, unitScrollDelay" unitScrollDelay isNil ifTrue:[self unitScrollDelay: self defaultUnitScrollDelay]. ^unitScrollDelay! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 1/15/98 13:50'! unitScrollDelay: aDelay "" "ssa 1/15/98 13:50 - Set unitScrollDelay to be aDelay." unitScrollDelay _ aDelay! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:40'! viewToScroll ^self view subViews first! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:07'! pageDown "Scroll down by one page length." self scroller scrollView: self pageHeight negated. self view updateElevator! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:00'! pageHeight "Answer the height of a page for the scrolling view." ^self viewToScroll displayBox height! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 8/27/2009 07:11'! pageUp "Scroll up by one page length." self scroller scrollView: self pageHeight. self view updateElevator! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'stp 2/18/98 13:50'! reallyScrollAbsolute | height center offset | center _ self view elevatorBox center y. offset _ (center - Sensor cursorPoint y). height _ self view elevatorShaft height. (self viewToScroll percentPreceedingContent ~= 0.0 or: [self viewToScroll percentVisibleContent < 1.0]) ifTrue:[self scroller scrollView: ((offset / height) * (self scroller view totalContentHeight * self scroller view unitContentHeight)) asInteger. self view updateElevator]! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'stp 2/18/98 13:53'! scrollAbsolute | lastY thisY | [Sensor redButtonPressed] whileTrue: [thisY := Sensor cursorPoint y. lastY isNil ifTrue: [lastY := thisY. self reallyScrollAbsolute] ifFalse: [lastY = thisY ifFalse: [lastY := thisY. self reallyScrollAbsolute]]]! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 1/15/98 13:54'! unitDown "Scroll down by one content unit." self view displayDownButtonPressed. [Sensor redButtonPressed] whileTrue:[ self scroller scrollView: self unitHeight negated. self view updateElevator. self wait]. self view displayDownButton. ! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:00'! unitHeight "Answer the height of a content unit for the scrolling view." ^self viewToScroll unitContentHeight! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 1/15/98 13:54'! unitUp "Scroll up by one content unit." self view displayUpButtonPressed. [Sensor redButtonPressed] whileTrue:[ self scroller scrollView: self unitHeight. self view updateElevator. self wait]. self view displayUpButton. ! ! !MSWScrollBarController methodsFor: 'control activity' stamp: 'ssa 1/8/98 16:28'! controlActivity "Refer to the comment in Controller|controlActivity." (Sensor redButtonPressed and:[self view scrollBarBox containsPoint: Sensor cursorPoint]) ifTrue: [^self redButtonActivity]. super controlActivity ! ! !MSWScrollBarController methodsFor: 'control activity' stamp: 'ssa 8/27/2009 04:44'! redButtonActivity | point | " self scroller view visibleContentHeight >= (self scroller view totalContentHeight + 2) ifTrue:[^self]." point _ Sensor cursorPoint. (self view upButtonBox containsPoint: point) ifTrue:[^self unitUp]. (self view downButtonBox containsPoint: point) ifTrue:[^self unitDown]. (self view elevatorBox containsPoint: point) ifTrue:[^self scrollAbsolute]. self view elevatorBox center y > point y ifTrue:[self wait. self pageUp] ifFalse:[self wait. self pageDown]. ! ! !MSWScrollBarController methodsFor: 'delegation' stamp: 'ssa 8/21/2009 12:55'! doesNotUnderstand: aMessage "Here it comes, the dreaded doesNotUnderstand: HACK ssa 1/23/98 14:55" ^self viewToScroll controller perform: aMessage selector withArguments: aMessage arguments! ! !Message methodsFor: 'private' stamp: 'ssa 5/27/2010 11:13'! arguments: anArray args _ anArray! ! !Message methodsFor: 'private' stamp: 'ssa 7/16/2010 19:03'! selector: aSymbol selector _ aSymbol. ! ! !Message methodsFor: 'sending' stamp: 'ssa 5/28/2010 17:06'! sentTo: receiver "answer the result of sending this message to receiver" lookupClass == nil ifTrue: [^ receiver perform: selector withArguments: args asArray] ifFalse: [^ receiver perform: selector withArguments: args asArray inSuperclass: lookupClass]! ! !MessageTally methodsFor: 'comparing' stamp: ''! < aMessageTally "Refer to the comment in Magnitude|<." ^tally > aMessageTally tally! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:05'! = aMessageTally self species == aMessageTally species ifFalse: [^ false]. ^ aMessageTally method == method! ! !MessageTally methodsFor: 'comparing' stamp: ''! > aMessageTally "Refer to the comment in Magnitude|>." ^tally < aMessageTally tally! ! !MessageTally methodsFor: 'comparing' stamp: ''! hash "Hash is reimplemented because = is implemented." ^method asOop! ! !MessageTally methodsFor: 'comparing' stamp: ''! isPrimitives "Detect pseudo node used to carry tally of local hits" ^ receivers == nil! ! !MessageTally methodsFor: 'comparing' stamp: ''! sonsOver: threshold | hereTally last sons | (receivers == nil or: [receivers size = 0]) ifTrue: [^#()]. hereTally _ tally. sons _ receivers select: "subtract subNode tallies for primitive hits here" [:son | hereTally _ hereTally - son tally. son tally > threshold]. hereTally > threshold ifTrue: [last _ MessageTally new class: class method: method. ^sons copyWith: (last primitives: hereTally)]. ^sons! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:04'! species ^MessageTally! ! !MessageTally methodsFor: 'initialize-release' stamp: ''! close (Timer isMemberOf: Process) ifTrue: [Timer terminate]. Timer _ ObservedProcess _ nil. class _ method _ tally _ receivers _ nil! ! !MessageTally methodsFor: 'initialize-release' stamp: 'nk 3/8/2004 12:29'! initialize maxClassNameSize _ self class defaultMaxClassNameSize. maxClassPlusSelectorSize _ self class defaultMaxClassPlusSelectorSize. maxTabs _ self class defaultMaxTabs.! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 9/17/2010 12:02'! spyEvery: millisecs on: aBlock "Create a spy and spy on the given block at the specified rate." | myDelay startTime time0 | (aBlock isMemberOf: BlockContext) ifFalse: [self error: 'spy needs a block here']. self class: aBlock receiver class method: aBlock method. "set up the probe" ObservedProcess := Processor thisProcess. myDelay := Delay forMilliseconds: millisecs. time0 := Time millisecondClockValue. gcStats := SmalltalkImage current getVMParameters. Timer := [[true] whileTrue: [startTime := Time millisecondClockValue. myDelay wait. ObservedProcess suspend. self tally: ObservedProcess suspendedContextWaitingIfNecessary "tally can be > 1 if ran a long primitive" by: (Time millisecondClockValue - startTime) // millisecs. ObservedProcess resume]. nil] newProcess. Timer priority: Processor userInterruptPriority. "activate the probe and evaluate the block" Timer resume. ^ aBlock ensure: ["Collect gc statistics" SmalltalkImage current getVMParameters keysAndValuesDo: [:idx :gcVal| gcStats at: idx put: (gcVal - (gcStats at: idx))]. "cancel the probe and return the value" Timer notNil ifTrue:[Timer terminate]. time := Time millisecondClockValue - time0]! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 9/17/2010 12:03'! spyEvery: millisecs onProcess: aProcess forMilliseconds: msecDuration "Create a spy and spy on the given process at the specified rate." | myDelay time0 endTime sem | (aProcess isKindOf: Process) ifFalse: [self error: 'spy needs a Process here']. self class: aProcess suspendedContextWaitingIfNecessary receiver class method: aProcess suspendedContext method. "set up the probe" ObservedProcess _ aProcess. myDelay _ Delay forMilliseconds: millisecs. time0 _ Time millisecondClockValue. endTime _ time0 + msecDuration. sem _ Semaphore new. gcStats _ SmalltalkImage current getVMParameters. Timer _ [[| startTime | startTime _ Time millisecondClockValue. myDelay wait. ObservedProcess suspend. self tally: ObservedProcess suspendedContextWaitingIfNecessary by: Time millisecondClockValue - startTime // millisecs. startTime < endTime. ObservedProcess resume] whileTrue. sem signal] forkAt: (ObservedProcess priority + 1 min: Processor highestPriority). "activate the probe and wait for it to finish" sem wait. "Collect gc statistics" SmalltalkImage current getVMParameters keysAndValuesDo: [:idx :gcVal| gcStats at: idx put: (gcVal - gcStats at: idx)]. time _ Time millisecondClockValue - time0! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/15/2000 21:49'! fullPrintOn: aStream tallyExact: isExact orThreshold: perCent | threshold | isExact ifFalse: [threshold _ (perCent asFloat / 100 * tally) rounded]. aStream nextPutAll: '**Tree**'; cr. self treePrintOn: aStream tabs: OrderedCollection new thisTab: '' total: tally totalTime: time tallyExact: isExact orThreshold: threshold. aStream nextPut: Character newPage; cr. aStream nextPutAll: '**Leaves**'; cr. self leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/22/2000 02:28'! leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold | dict | dict _ IdentityDictionary new: 100. self leavesInto: dict fromSender: nil. isExact ifTrue: [dict asSortedCollection do: [:node | node printOn: aStream total: tally totalTime: nil tallyExact: isExact. node printSenderCountsOn: aStream]] ifFalse: [(dict asOrderedCollection select: [:node | node tally > threshold]) asSortedCollection do: [:node | node printOn: aStream total: tally totalTime: time tallyExact: isExact]]! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:14'! printOn: aStream | aSelector className aClass | (class isNil or: [method isNil]) ifTrue: [^super printOn: aStream]. aSelector := class selectorAtMethod: method setClass: [:c | aClass := c]. className := aClass name contractTo: self maxClassNameSize. aStream nextPutAll: className; nextPutAll: ' >> '; nextPutAll: (aSelector contractTo: self maxClassPlusSelectorSize - className size)! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:15'! printOn: aStream total: total totalTime: totalTime tallyExact: isExact | aSelector className myTally aClass percentage | isExact ifTrue: [myTally := tally. receivers == nil ifFalse: [receivers do: [:r | myTally := myTally - r tally]]. aStream print: myTally; space] ifFalse: [percentage := tally asFloat / total * 100.0 roundTo: 0.1. aStream print: percentage; nextPutAll: '% {'; print: (percentage * totalTime / 100) rounded; nextPutAll: 'ms} ']. receivers == nil ifTrue: [aStream nextPutAll: 'primitives'; cr] ifFalse: [aSelector := class selectorAtMethod: method setClass: [:c | aClass := c]. className := aClass name contractTo: self maxClassNameSize. aStream nextPutAll: class name; nextPutAll: (aClass = class ifTrue: ['>>'] ifFalse: ['(' , aClass name , ')>>']); nextPutAll: (aSelector contractTo: self maxClassPlusSelectorSize - className size); cr]! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/22/2000 02:28'! printSenderCountsOn: aStream | mergedSenders mergedNode | mergedSenders _ IdentityDictionary new. senders do: [:node | mergedNode _ mergedSenders at: node method ifAbsent: [nil]. mergedNode == nil ifTrue: [mergedSenders at: node method put: node] ifFalse: [mergedNode bump: node tally]]. mergedSenders asSortedCollection do: [:node | 10 to: node tally printString size by: -1 do: [:i | aStream space]. node printOn: aStream total: tally totalTime: nil tallyExact: true]! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:23'! treePrintOn: aStream tabs: tabs thisTab: myTab total: total totalTime: totalTime tallyExact: isExact orThreshold: threshold | sons sonTab | tabs do: [:tab | aStream nextPutAll: tab]. tabs size > 0 ifTrue: [self printOn: aStream total: total totalTime: totalTime tallyExact: isExact]. sons := isExact ifTrue: [receivers] ifFalse: [self sonsOver: threshold]. sons isEmpty ifFalse: [tabs addLast: myTab. sons := sons asSortedCollection. (1 to: sons size) do: [:i | sonTab := i < sons size ifTrue: [' |'] ifFalse: [' ']. (sons at: i) treePrintOn: aStream tabs: (tabs size < self maxTabs ifTrue: [tabs] ifFalse: [(tabs select: [:x | x = '[']) copyWith: '[']) thisTab: sonTab total: total totalTime: totalTime tallyExact: isExact orThreshold: threshold]. tabs removeLast]! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassNameSize ^maxClassNameSize! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxClassNameSize: aNumber maxClassNameSize := aNumber! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassPlusSelectorSize ^maxClassPlusSelectorSize! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxClassPlusSelectorSize: aNumber maxClassPlusSelectorSize := aNumber! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxTabs ^maxTabs! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxTabs: aNumber maxTabs := aNumber! ! !MessageTally methodsFor: 'reporting' stamp: ''! report: strm "Print a report, with cutoff percentage of each element of the tree (leaves, roots, tree)=2, on the stream, strm." self report: strm cutoff: 2! ! !MessageTally methodsFor: 'reporting' stamp: 'spfa 6/1/2004 19:23'! report: strm cutoff: threshold tally = 0 ifTrue: [strm nextPutAll: ' - no tallies obtained'] ifFalse: [strm nextPutAll: ' - '; print: tally; nextPutAll: ' tallies, ', time printString, ' msec.'; cr; cr. self fullPrintOn: strm tallyExact: false orThreshold: threshold]. time isZero ifFalse: [self reportGCStatsOn: strm].! ! !MessageTally methodsFor: 'reporting' stamp: 'ar 7/18/2001 22:12'! reportGCStatsOn: str | oldSpaceEnd youngSpaceEnd memoryEnd fullGCs fullGCTime incrGCs incrGCTime tenureCount upTime rootOverflows | upTime _ time. oldSpaceEnd _ gcStats at: 1. youngSpaceEnd _ gcStats at: 2. memoryEnd _ gcStats at: 3. fullGCs _ gcStats at: 7. fullGCTime _ gcStats at: 8. incrGCs _ gcStats at: 9. incrGCTime _ gcStats at: 10. tenureCount _ gcStats at: 11. rootOverflows _ gcStats at: 22. str cr. str nextPutAll: '**Memory**'; cr. str nextPutAll: ' old '; nextPutAll: oldSpaceEnd asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' young '; nextPutAll: (youngSpaceEnd - oldSpaceEnd) asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' used '; nextPutAll: youngSpaceEnd asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' free '; nextPutAll: (memoryEnd - youngSpaceEnd) asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str cr. str nextPutAll: '**GCs**'; cr. str nextPutAll: ' full '; print: fullGCs; nextPutAll: ' totalling '; nextPutAll: fullGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((fullGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime)'. fullGCs = 0 ifFalse: [str nextPutAll: ', avg '; print: ((fullGCTime / fullGCs) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' incr '; print: incrGCs; nextPutAll: ' totalling '; nextPutAll: incrGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((incrGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime)'. incrGCs = 0 ifFalse: [str nextPutAll:', avg '; print: ((incrGCTime / incrGCs) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' tenures '; nextPutAll: tenureCount asStringWithCommas. tenureCount = 0 ifFalse: [str nextPutAll: ' (avg '; print: (incrGCs / tenureCount) asInteger; nextPutAll: ' GCs/tenure)']. str cr. str nextPutAll: ' root table '; nextPutAll: rootOverflows asStringWithCommas; nextPutAll:' overflows'. str cr. ! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 12:06'! tally "Answer the receiver's number of tally." ^tally! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 11:47'! time "Answer the receiver's run time." ^time! ! !MessageTally methodsFor: 'private' stamp: ''! class: aClass method: aMethod class _ aClass. method _ aMethod. tally _ 0. receivers _ Array new: 0! ! !MessageTally methodsFor: 'private' stamp: ''! copyWithTally: hitCount ^ (MessageTally new class: class method: method) bump: hitCount! ! !MessageTally methodsFor: 'private' stamp: ''! method ^method! ! !MessageTally methodsFor: 'private' stamp: ''! primitives: anInteger tally _ anInteger. receivers _ nil! ! !MessageTally methodsFor: 'collecting leaves' stamp: ''! bump: hitCount tally _ tally + hitCount! ! !MessageTally methodsFor: 'collecting leaves' stamp: ''! bump: hitCount fromSender: senderTally "Add this hitCount to the total, and include a reference to the sender responsible for the increment" self bump: hitCount. senders == nil ifTrue: [senders _ OrderedCollection new]. senderTally == nil ifFalse: [senders add: (senderTally copyWithTally: hitCount)]! ! !MessageTally methodsFor: 'collecting leaves' stamp: ''! into: leafDict fromSender: senderTally | leafNode | leafNode _ leafDict at: method ifAbsent: [leafDict at: method put: (MessageTally new class: class method: method)]. leafNode bump: tally fromSender: senderTally! ! !MessageTally methodsFor: 'collecting leaves' stamp: ''! leavesInto: leafDict fromSender: senderTally | rcvrs | rcvrs _ self sonsOver: 0. rcvrs size = 0 ifTrue: [self into: leafDict fromSender: senderTally] ifFalse: [rcvrs do: [:node | node isPrimitives ifTrue: [node leavesInto: leafDict fromSender: senderTally] ifFalse: [node leavesInto: leafDict fromSender: self]]]! ! !MessageTally methodsFor: 'tallying' stamp: ''! bumpBy: count tally _ tally + count! ! !MessageTally methodsFor: 'tallying' stamp: ''! tally: context by: count "Explicitly tally the specified context and its stack." | root | context method == method ifTrue: [^self bumpBy: count]. (root _ context home sender) == nil ifTrue: [^ (self bumpBy: count) tallyPath: context by: count]. ^ (self tally: root by: count) tallyPath: context by: count! ! !MessageTally methodsFor: 'tallying' stamp: ''! tallyPath: context by: count | aMethod path | aMethod _ context method. receivers do: [:aMessageTally | aMessageTally method == aMethod ifTrue: [path _ aMessageTally]]. path == nil ifTrue: [path _ MessageTally new class: context receiver class method: aMethod. receivers _ receivers copyWith: path]. ^ path bumpBy: count! ! !MethodContext methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:14'! printOn: aStream | h | aStream nextPutAll:(RVMTester printPrefixFor: self). self isExecutingBlock ifFalse: [^ super printOn: aStream]. h _ self blockHome. h ifNil: [^ aStream nextPutAll: '[]']. aStream nextPutAll: '[] from '. h printOn: aStream! ! !MethodContext methodsFor: 'converting' stamp: 'ssa 9/7/2009 14:36'! asContext ^self! ! !Model methodsFor: 'printing' stamp: ''! archiveOn: aStream "To be consistent with Object, don't file out the dependents (subclasses may wish to override or put back the dependencies back in some other manner -- see Figure>dearchiveFrom:)." | oldDependents | oldDependents _ dependents. dependents _ nil. super archiveOn: aStream. dependents _ oldDependents.! ! !CPUWatcher methodsFor: 'process operations' stamp: 'dmu 11/25/2008 00:18'! debugProcess: aProcess | uiPriority oldPriority | uiPriority := Processor thisProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority := ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !Number methodsFor: 'arithmetic' stamp: 'ssa 11/27/2009 16:14'! inverted ^1/self! ! !Number methodsFor: 'mathematical functions' stamp: 'ssa 8/27/2009 14:58'! pi ^Float pi * self! ! !Number methodsFor: 'truncation and round off' stamp: 'ssa 8/30/2009 04:04'! atRandom ^self asFloat * (Collection atRandom: self class randomForPicking copy)! ! !Number methodsFor: 'converting' stamp: 'ssa 11/15/2008 08:57'! asPointWithinRectangleWithExtent: extent "Answer a point showing what coordinate I would have if wrapped into a rectangle of this extent. Clip out of bounds answer to 0@0 if undershot or extent if overShot. Only really useful for integers" | x y newX newY | x _ extent x. y _ extent y. self > (x*y) ifTrue:[^extent]. self < 1 ifTrue:[^0@0]. newX _ self \\ x = 0 ifTrue:[x]ifFalse:[self \\ x]. newY _ self - 1 // x + 1. ^newX@newY "{0 asPointWithinRectangleWithExtent:2@2. 1 asPointWithinRectangleWithExtent:2@2. 2 asPointWithinRectangleWithExtent:2@2. 3 asPointWithinRectangleWithExtent:2@2. 4 asPointWithinRectangleWithExtent:2@2. 5 asPointWithinRectangleWithExtent:2@2.} #(0@0 1@1 2@1 1@2 2@2 2@2)" "{0 asPointWithinRectangleWithExtent:3@3. 1 asPointWithinRectangleWithExtent:3@3. 2 asPointWithinRectangleWithExtent:3@3. 3 asPointWithinRectangleWithExtent:3@3. 4 asPointWithinRectangleWithExtent:3@3. 5 asPointWithinRectangleWithExtent:3@3. 6 asPointWithinRectangleWithExtent:3@3. 7 asPointWithinRectangleWithExtent:3@3. 8 asPointWithinRectangleWithExtent:3@3. 9 asPointWithinRectangleWithExtent:3@3. 10 asPointWithinRectangleWithExtent:3@3.} #(0@0 1@1 2@1 3@1 1@2 2@2 3@2 1@3 2@3 3@3 3@3)"! ! !Number methodsFor: 'converting' stamp: ''! theta: angle "Answer a new Point whose r value is the receiver and whose theta value is the argument." "KSC Extension" ^(angle cos * self) @ (angle sin * self)! ! !Number methodsFor: 'intervals' stamp: 'ssa 9/7/2009 21:42'! zeno "100 zeno" "-100 zeno" "Answer a collection of numbers representing Zeno's paradox steps between myself and zero" | steps distanceRemaining | steps _ OrderedCollection new. distanceRemaining _ self abs. [distanceRemaining > 1] whileTrue:[steps add: distanceRemaining * self sign. distanceRemaining _ distanceRemaining / 2.0]. ^steps asArray! ! !Number methodsFor: 'printing' stamp: ''! archiveOn: aStream aStream storeClass: self class; store: self! ! !Number methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:39'! floatPrecisionForDecimalPlaces: places "Answer the floatPrecision that corresponds to the given number of decimal places" ^ #(1 0.1 0.01 0.001 0.0001 0.00001 0.000001 0.0000001 0.00000001 0.000000001) at: (places + 1) " (0 to: 6) collect: [:i | Number floatPrecisionForDecimalPlaces: i] "! ! !Number methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:48'! printShowingDecimalPlaces: placesDesired "Print the receiver showing precisely the given number of places desired . If the placesDesired provided is positive, a decimal point and that many digits after the decimal point will always be shown. If the placesDesired is zero, a whole number will be shown, without a decimal point. This method could probably be greatly optimized -- improvements welcomed." | aString | placesDesired <= 0 ifTrue: [^ self rounded printString]. aString _ ((self asFloat roundTo: (self floatPrecisionForDecimalPlaces: placesDesired)) asString), ((String new: placesDesired) atAllPut: $0). ^ aString copyFrom: 1 to: ((aString indexOf: $.) + placesDesired) " 0.23 printShowingDecimalPlaces: 2 23.5698 printShowingDecimalPlaces: 2 -234.567 printShowingDecimalPlaces: 5 23.4567 printShowingDecimalPlaces: 0 "! ! !Number methodsFor: 'printing' stamp: 'ssa 10/7/2008 18:20'! printShowingMax3Digits "Print the receiver showing precisely the 3 digits, using K M B T for thousand, million, etc." "|num| num _ 0.00001234567890. 20 timesRepeat:[num printShowingMax3Digits print. num _ num *10]." | s abs value | value _ self isFraction ifTrue:[self asFloat]ifFalse:[self]. s _ value printString select:[:char| '0123456789' includes: char]. s size <=3 ifTrue:[^value printString]. abs _ value abs asFloat. abs < 0.01 ifTrue:[^((value * 1000) printShowingDecimalPlaces: 2),'m']. abs < 0.1 ifTrue:[^((value * 1000) printShowingDecimalPlaces: 1),'m']. abs < 10 ifTrue:[^value printShowingDecimalPlaces: 2]. abs < 100 ifTrue:[^value printShowingDecimalPlaces: 1]. abs < 1000 ifTrue:[^value asInteger printString]. abs < 10000 ifTrue:[^((value /1000) printShowingDecimalPlaces: 2),'K']. abs < 100000 ifTrue:[^((value /1000) printShowingDecimalPlaces: 1),'K']. abs < 1000000 ifTrue:[^((value /1000) asInteger printString),'K']. abs < 10000000 ifTrue:[^((value /1000000) printShowingDecimalPlaces: 2),'M']. abs < 100000000 ifTrue:[^((value /1000000) printShowingDecimalPlaces: 1),'M']. abs < 1000000000 ifTrue:[^(value /1000000) asInteger printString,'M']. abs < 10000000000 ifTrue:[^((value /1000000000) printShowingDecimalPlaces: 2),'B']. abs < 100000000000 ifTrue:[^((value /1000000000) printShowingDecimalPlaces: 1),'B']. abs < 1000000000000 ifTrue:[^((value /1000000000) asInteger printString),'B']. abs < 10000000000000 ifTrue:[^((value /1000000000000) printShowingDecimalPlaces: 2),'T']. abs < 100000000000000 ifTrue:[^((value /1000000000000) printShowingDecimalPlaces: 1),'T']. abs < 1000000000000000 ifTrue:[^((value /1000000000000) asInteger printString),'T']. abs < 10000000000000000 ifTrue:[^((value /1000000000000000) printShowingDecimalPlaces: 2),'Q']. abs < 100000000000000000 ifTrue:[^((value /1000000000000000) printShowingDecimalPlaces: 1),'Q']. abs < 1000000000000000000 ifTrue:[^((value /1000000000000000) asInteger printString),'Q']. ^'too big' ! ! !Float methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:24'! absPrintOn: aStream base: base digitCount: digitCount "Print me in the given base, using digitCount significant figures." "Float pi absPrintOn: Transcript base: 10 digitCount: 4. Transcript cr;flush" | fuzz x exp q fBase scale logScale xi | self isInf ifTrue: [^ aStream nextPutAll: 'Inf']. fBase _ base asFloat. "x is myself normalized to [1.0, fBase), exp is my exponent" exp _ self < 1.0 ifTrue: [self reciprocalFloorLog: fBase] ifFalse: [self floorLog: fBase]. scale _ 1.0. logScale _ 0. [(x _ fBase raisedTo: (exp + logScale)) = 0] whileTrue: [scale _ scale * fBase. logScale _ logScale + 1]. x _ self * scale / x. fuzz _ fBase raisedTo: 1 - digitCount. "round the last digit to be printed" x _ 0.5 * fuzz + x. x >= fBase ifTrue: ["check if rounding has unnormalized x" x _ x / fBase. exp _ exp + 1]. (exp < 6 and: [exp > -4]) ifTrue: ["decimal notation" q _ 0. exp < 0 ifTrue: [1 to: 1 - exp do: [:i | aStream nextPut: ('0.0000' at: i)]]] ifFalse: ["scientific notation" q _ exp. exp _ 0]. [x >= fuzz] whileTrue: ["use fuzz to track significance" xi _ x asInteger. aStream nextPut: (Character digitValue: xi). x _ x - xi asFloat * fBase. fuzz _ fuzz * fBase. exp _ exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. [exp >= -1] whileTrue: [aStream nextPut: $0. exp _ exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. q ~= 0 ifTrue: [aStream nextPut: $e. q printOn: aStream]! ! !Integer methodsFor: 'truncation and round off' stamp: 'ssa 11/27/2009 16:44'! atRandom "Answer a random integer from 1 to self. This implementation uses a shared generator. Heavy users should their own implementation or use Interval>atRandom: directly." self = 0 ifTrue: [ ^0 ]. self < 0 ifTrue: [ ^self negated atRandom negated ]. ^self atRandom: Collection randomForPicking ! ! !Integer methodsFor: 'printing' stamp: 'ar 7/18/2001 22:09'! asStringWithCommasSigned "123456789 asStringWithCommasSigned" "-123456789 asStringWithCommasSigned" | digits | digits _ self abs printString. ^ String streamContents: [:strm | self sign = -1 ifTrue: [strm nextPut: $-] ifFalse:[strm nextPut: $+]. 1 to: digits size do: [:i | strm nextPut: (digits at: i). (i < digits size and: [(i - digits size) \\ 3 = 0]) ifTrue: [strm nextPut: $,]]]! ! !Integer methodsFor: 'printing' stamp: 'ssa 8/26/2009 12:23'! printeth "1 printeth '1st'" "2 printeth '2nd'" "3 printeth '3rd'" "4 printeth '4th'" "5 printeth '5th'" "1234 printeth '1234th'" "121 printeth '121st'" | str suffix | str _ self printString. suffix _ (#('st' 'nd' 'rd' 'th')at: ((str last asNumber max:1) min:4)). ^str,suffix! ! !Integer methodsFor: 'benchmarks' stamp: 'dmu 1/1/1970 00:40'! tinyRVMBenchmarks "Report the results of running the two tiny Squeak benchmarks. ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results" "0 tinyBenchmarks" "On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec" "On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec" | t1 t2 r n1 n2 s1 s2 totalYields | n1 _ 1. s1 _ RVMMulticoreSample capture. [t1 _ Time millisecondsToRun: [n1 benchmark]. t1 < 1000] whileTrue:[n1 _ n1 * 2]. "Note: #benchmark's runtime is about O(n)" n2 _ 28. [t2 _ Time millisecondsToRun: [r _ n2 benchFib]. t2 < 1000] whileTrue:[n2 _ n2 + 1]. "Note: #benchFib's runtime is about O(k^n), where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...." s2 _ RVMMulticoreSample capture. totalYields _ s2 totalYields. ^ ((n1 * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', ((r * 1000) // t2) printString, ' sends/sec; ', totalYields printString, ' total yields; ', (t1 + t2) printString, ' total ms'! ! !Integer methodsFor: 'explorer' stamp: 'laza 3/17/2005 13:37'! explorerContents ^{ 'hexadecimal' -> 16. 'octal' -> 8. 'binary' -> 2 } collect: [:each | ObjectExplorerWrapper with: each key translated name: (self printStringBase: each value) model: self]! ! !LargePositiveInteger methodsFor: 'printing' stamp: 'ssa 9/11/2009 16:52'! printOn: aStream "hack to fix strange LPI bug" ^(self - 1 + 1)printOn: aStream base: 10! ! !Object class methodsFor: 'instance creation' stamp: ''! dearchive: versionNumber from: aStream "Override this method when implementing new archive versions for a class." ^versionNumber == self archiveVersion ifTrue: [self dearchiveFrom: aStream] ifFalse: [self error: 'Can''t dearchive this version.']! ! !Object class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream | anObject | self isVariable ifTrue:[anObject _ self basicNew: (aStream read: Integer)] ifFalse:[anObject _ self dearchiveNewFrom: aStream]. aStream storeObject: anObject. anObject dearchiveFrom: aStream. ^anObject! ! !Object class methodsFor: 'instance creation' stamp: ''! dearchiveNewFrom: aStream ^self basicNew! ! !ArchiveReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 08:08'! dearchive: aString "ArchiveReader dearchive: 'archive.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream next. aStream close. ^anObject! ! !ArchiveReader class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 20:52'! fastStreamOn: aFilename "Answer a stream which is appropriate for getting the data from aFilename as fast as possible. The default version ignores lineEndConventions. This is tightly coupled with ArchiveWriter>fastStreamOn:" ^(FileStream oldFileNamed: aFilename) openReadOnly; yourself! ! !ArchiveReader class methodsFor: 'instance creation' stamp: ''! on: aStream ^self new setStream: aStream! ! !ArchiveWriter class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 21:17'! archive: anObject to: aString "ArchiveWriter archive: Array new to: 'archive.test'" "ArchiveWriter archive: 1 to: 'archive.test'" "ArchiveWriter archive: #(1 2 3) to: 'archive.test'" "ArchiveWriter archive: (Array with: #aSymbol with: 'aSymbol') to: 'archive.test'" | stream | stream _ self fastStreamOn: aString. (self on: stream) nextPut: anObject; close.! ! !ArchiveWriter class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 20:34'! fastStreamOn: aFilename "Answer a stream which is appropriate for getting the data to aFilename as fast as possible. The default version ignores lineEndConventions. This is tightly coupled with ArchiveReader>fastStreamOn:" ^FileStream newFileNamed: aFilename! ! !ArchiveWriter class methodsFor: 'instance creation' stamp: ''! on: aWriteStream ^self new setStream: aWriteStream! ! !BinaryChoice class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 21:47'! message: aString displayAt: aPoint centered: aBoolean ifTrue: trueBlock ifFalse: falseBlock "Mimic the old BinaryChoice protocol. Canceling the menu by clicking outside executes false block" | answer | answer := PopUpMenu withCaption: aString chooseFrom: #( 'Yes' 'No'). answer = 1 ifTrue: trueBlock ifFalse: falseBlock! ! !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:08'! alphaBlendDemo "To run this demo, use... Display restoreAfter: [BitBlt alphaBlendDemo] Displays 10 alphas, then lets you paint. Option-Click to stop painting." "This code exhibits alpha blending in any display depth by performing the blend in an off-screen buffer with 32-bit pixels, and then copying the result back onto the screen with an appropriate color map. - tk 3/10/97" "This version uses a sliding buffer for painting that keeps pixels in 32 bits as long as they are in the buffer, so as not to lose info by converting down to display resolution and back up to 32 bits at each operation. - di 3/15/97" | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect | "compute color maps if needed" Display depth <= 8 ifTrue: [ mapDto32 _ Color cachedColormapFrom: Display depth to: 32. map32toD _ Color cachedColormapFrom: 32 to: Display depth]. "display 10 different alphas, across top of screen" buff _ Form extent: 500@50 depth: 32. dispToBuff _ BitBlt toForm: buff. dispToBuff colorMap: mapDto32. dispToBuff copyFrom: (50@10 extent: 500@50) in: Display to: 0@0. 1 to: 10 do: [:i | dispToBuff fill: (50*(i-1)@0 extent: 50@50) fillColor: (Color red alpha: i/10) rule: Form blend]. buffToDisplay _ BitBlt toForm: Display. buffToDisplay colorMap: map32toD. buffToDisplay copyFrom: buff boundingBox in: buff to: 50@10. "Create a brush with radially varying alpha" brush _ Form extent: 30@30 depth: 32. 1 to: 5 do: [:i | brush fillShape: (Form dotOfSize: brush width*(6-i)//5) fillColor: (Color red alpha: 0.02 * i - 0.01) at: brush extent // 2]. "Now paint with the brush using alpha blending." buffSize _ 100. buff _ Form extent: brush extent + buffSize depth: 32. "Travelling 32-bit buffer" dispToBuff _ BitBlt toForm: buff. "This is from Display to buff" dispToBuff colorMap: mapDto32. brushToBuff _ BitBlt toForm: buff. "This is from brush to buff" brushToBuff sourceForm: brush; sourceOrigin: 0@0. brushToBuff combinationRule: Form blend. buffToBuff _ BitBlt toForm: buff. "This is for slewing the buffer" [Sensor yellowButtonPressed] whileFalse: [prevP _ nil. buffRect _ Sensor cursorPoint - (buffSize // 2) extent: buff extent. dispToBuff copyFrom: buffRect in: Display to: 0@0. [Sensor redButtonPressed] whileTrue: ["Here is the painting loop" p _ Sensor cursorPoint - (brush extent // 2). (prevP == nil or: [prevP ~= p]) ifTrue: [prevP == nil ifTrue: [prevP _ p]. (p dist: prevP) > buffSize ifTrue: ["Stroke too long to fit in buffer -- clip to buffer, and next time through will do more of it" theta _ (p-prevP) theta. p _ ((theta cos@theta sin) * buffSize asFloat + prevP) truncated]. brushRect _ p extent: brush extent. (buffRect containsRect: brushRect) ifFalse: ["Brush is out of buffer region. Scroll the buffer, and fill vacated regions from the display" delta _ brushRect amountToTranslateWithin: buffRect. buffToBuff copyFrom: buff boundingBox in: buff to: delta. newBuffRect _ buffRect translateBy: delta negated. (newBuffRect areasOutside: buffRect) do: [:r | dispToBuff copyFrom: r in: Display to: r origin - newBuffRect origin]. buffRect _ newBuffRect]. "Interpolate from prevP to p..." brushToBuff drawFrom: prevP - buffRect origin to: p - buffRect origin withFirstPoint: false. "Update (only) the altered pixels of the destination" updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent. buffToDisplay copy: updateRect from: updateRect origin - buffRect origin in: buff. prevP _ p]]]! ! !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:09'! antiAliasDemo "To run this demo, use... Display restoreAfter: [BitBlt antiAliasDemo] Goes immediately into on-screen paint mode. Option-Click to stop painting." "This code exhibits alpha blending in any display depth by performing the blend in an off-screen buffer with 32-bit pixels, and then copying the result back onto the screen with an appropriate color map. - tk 3/10/97" "This version uses a sliding buffer for painting that keeps pixels in 32 bits as long as they are in the buffer, so as not to lose info by converting down to display resolution and back up to 32 bits at each operation. - di 3/15/97" "This version also uses WarpBlt to paint into twice as large a buffer, and then use smoothing when reducing back down to the display. In fact this same routine will now work for 3x3 soothing as well. Remove the statements 'buff displayAt: 0@0' to hide the buffer. - di 3/19/97" | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect scale p0 | "compute color maps if needed" Display depth <= 8 ifTrue: [ mapDto32 _ Color cachedColormapFrom: Display depth to: 32. map32toD _ Color cachedColormapFrom: 32 to: Display depth]. "Create a brush with radially varying alpha" brush _ Form extent: 3@3 depth: 32. brush fill: brush boundingBox fillColor: (Color red alpha: 0.05). brush fill: (1@1 extent: 1@1) fillColor: (Color red alpha: 0.2). scale _ 2. "Actual drawing happens at this magnification" "Scale brush up for painting in magnified buffer" brush _ brush magnify: brush boundingBox by: scale. "Now paint with the brush using alpha blending." buffSize _ 100. buff _ Form extent: (brush extent + buffSize) * scale depth: 32. "Travelling 32-bit buffer" dispToBuff _ (WarpBlt toForm: buff) "From Display to buff - magnify by 2" sourceForm: Display; colorMap: mapDto32; combinationRule: Form over. brushToBuff _ (BitBlt toForm: buff) "From brush to buff" sourceForm: brush; sourceOrigin: 0@0; combinationRule: Form blend. buffToDisplay _ (WarpBlt toForm: Display) "From buff to Display - shrink by 2" sourceForm: buff; colorMap: map32toD; cellSize: scale; "...and use smoothing" combinationRule: Form over. buffToBuff _ BitBlt toForm: buff. "This is for slewing the buffer" [Sensor yellowButtonPressed] whileFalse: [prevP _ nil. buffRect _ Sensor cursorPoint - (buff extent // scale // 2) extent: buff extent // scale. p0 _ (buff extent // 2) - (buffRect extent // 2). dispToBuff copyQuad: buffRect innerCorners toRect: buff boundingBox. buff displayAt: 0@0. "** remove to hide sliding buffer **" [Sensor redButtonPressed] whileTrue: ["Here is the painting loop" p _ Sensor cursorPoint - buffRect origin + p0. "p, prevP are rel to buff origin" (prevP == nil or: [prevP ~= p]) ifTrue: [prevP == nil ifTrue: [prevP _ p]. (p dist: prevP) > (buffSize-1) ifTrue: ["Stroke too long to fit in buffer -- clip to buffer, and next time through will do more of it" theta _ (p-prevP) theta. p _ ((theta cos@theta sin) * (buffSize-2) asFloat + prevP) truncated]. brushRect _ p extent: brush extent. ((buff boundingBox insetBy: scale) containsRect: brushRect) ifFalse: ["Brush is out of buffer region. Scroll the buffer, and fill vacated regions from the display" delta _ (brushRect amountToTranslateWithin: (buff boundingBox insetBy: scale)) // scale. buffToBuff copyFrom: buff boundingBox in: buff to: delta*scale. newBuffRect _ buffRect translateBy: delta negated. p _ p translateBy: delta*scale. prevP _ prevP translateBy: delta*scale. (newBuffRect areasOutside: buffRect) do: [:r | dispToBuff copyQuad: r innerCorners toRect: (r origin - newBuffRect origin*scale extent: r extent*scale)]. buffRect _ newBuffRect]. "Interpolate from prevP to p..." brushToBuff drawFrom: prevP to: p withFirstPoint: false. buff displayAt: 0@0. "** remove to hide sliding buffer **" "Update (only) the altered pixels of the destination" updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent. updateRect _ updateRect origin // scale * scale corner: updateRect corner + scale // scale * scale. buffToDisplay copyQuad: updateRect innerCorners toRect: (updateRect origin // scale + buffRect origin extent: updateRect extent // scale). prevP _ p]]]! ! !BitBlt class methodsFor: 'examples' stamp: 'ssa 10/27/2008 16:38'! exampleColorMap "BitBlt exampleColorMap" "This example shows what one can do with the fixed part of a color map. The color map, as setup below, rotates the bits of a pixel all the way around. Thus you'll get a (sometime strange looking ;-) animation of colors which will end up exactly the way it looked at the beginning. The example is given to make you understand that the masks and shifts can be used for a lot more than simply color converting pixels. In this example, for instance, we use only two of the four independent shifters." | cc bb | cc _ ColorMap masks: { 1 << (Display depth-1). "mask out high bit of color component" 1 << (Display depth-1) - 1. "mask all other bits" 0. 0} shifts: { 1 - Display depth. "shift right to bottom most position" 1. "shift all other pixels one bit left" 0. 0}. bb _ BitBlt toForm: Display. bb sourceForm: Display; combinationRule: 3; colorMap: cc. 1 to: Display depth do:[:i| bb copyBits. Display forceDisplayUpdate. Sensor waitButton;waitNoButton ]. ! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 4/24/2001 23:49'! benchDiffsFrom: before to: afterwards "Given two outputs of BitBlt>>benchmark show the relative improvements." | old new log oldLine newLine oldVal newVal improvement | log _ WriteStream on: String new. old _ ReadStream on: before. new _ ReadStream on: afterwards. [old atEnd or:[new atEnd]] whileFalse:[ oldLine _ old upTo: Character cr. newLine _ new upTo: Character cr. (oldLine includes: Character tab) ifTrue:[ oldLine _ ReadStream on: oldLine. newLine _ ReadStream on: newLine. Transcript cr; show: (oldLine upTo: Character tab); tab. log cr; nextPutAll: (newLine upTo: Character tab); tab. [oldLine skipSeparators. newLine skipSeparators. oldLine atEnd] whileFalse:[ oldVal _ Integer readFrom: oldLine. newVal _ Integer readFrom: newLine. improvement _ oldVal asFloat / newVal asFloat roundTo: 0.01. Transcript show: improvement printString; tab; tab. log print: improvement; tab; tab]. ] ifFalse:[ Transcript cr; show: oldLine. log cr; nextPutAll: oldLine. ]. ]. ^log contents! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 5/14/2001 23:31'! benchmark2 "BitBlt benchmark" "Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else. Attention: *this*may*take*a*while*" | bb source dest destRect log t | log _ WriteStream on: String new. destRect _ 0@0 extent: 600@600. "Form paint/Form over - the most common rules" #( 25 3 ) do:[:rule| Transcript cr; show:'---- Combination rule: ', rule printString,' ----'. log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'. #(1 2 4 8 16 32) do:[:destDepth| dest _ nil. dest _ Form extent: destRect extent depth: destDepth. Transcript cr. log cr. #(1 2 4 8 16 32) do:[:sourceDepth| Transcript cr; show: sourceDepth printString, ' => ', destDepth printString. log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString. source _ nil. bb _ nil. source _ Form extent: destRect extent depth: sourceDepth. (source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black. bb _ WarpBlt toForm: dest. bb sourceForm: source. bb sourceRect: source boundingBox. bb destRect: dest boundingBox. bb colorMap: (source colormapIfNeededFor: dest). bb combinationRule: rule. "Measure speed of copyBits" t _ Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. bb sourceForm: source destRect: source boundingBox. "Measure speed of 1x1 warpBits" bb cellSize: 1. t _ Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 2x2 warpBits" bb cellSize: 2. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 3x3 warpBits" bb cellSize: 3. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. ]. ]. ]. ^log contents! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 4/26/2001 21:04'! benchmark3 "BitBlt benchmark" "Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else. Attention: *this*may*take*a*while*" | bb source dest destRect log t | log _ WriteStream on: String new. destRect _ 0@0 extent: 600@600. "Form paint/Form over - the most common rules" #( 25 3 ) do:[:rule| Transcript cr; show:'---- Combination rule: ', rule printString,' ----'. log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'. #(1 2 4 8 16 32) do:[:destDepth| dest _ nil. dest _ Form extent: destRect extent depth: destDepth. Transcript cr. log cr. #(1 2 4 8 16 32) do:[:sourceDepth| Transcript cr; show: sourceDepth printString, ' => ', destDepth printString. log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString. source _ nil. bb _ nil. source _ Form extent: destRect extent depth: sourceDepth. (source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black. bb _ WarpBlt toForm: dest. bb sourceForm: source. bb sourceRect: source boundingBox. bb destRect: dest boundingBox. bb colorMap: (source colormapIfNeededFor: dest). bb combinationRule: rule. "Measure speed of copyBits" t _ Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. bb sourceForm: source destRect: source boundingBox. "Measure speed of 1x1 warpBits" bb cellSize: 1. t _ Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 2x2 warpBits" bb cellSize: 2. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 3x3 warpBits" bb cellSize: 3. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. ]. ]. ]. ^log contents! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowDown ^ self value: 31! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowLeft ^ self value: 28! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowRight ^ self value: 29! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowUp ^ self value: 30! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! backspace "Answer the Character representing a backspace." ^self value: 8! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! cr "Answer the Character representing a carriage return." ^self value: 13! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! delete ^ self value: 127! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! end ^ self value: 4! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! enter "Answer the Character representing enter." ^self value: 3! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ls 9/2/1999 08:06'! escape "Answer the ASCII ESC character" ^self value: 27! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'sma 3/15/2000 22:33'! euro "The Euro currency sign, that E with two dashes. The key code is a wild guess" ^ Character value: 219! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! home ^ self value: 1! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! insert ^ self value: 5! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ls 9/8/1998 22:15'! lf "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! linefeed "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'wiz 4/9/2006 20:30'! nbsp "non-breakable space. Latin1 encoding common usage." ^ Character value: 160! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! newPage "Answer the Character representing a form feed." ^self value: 12! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! pageDown ^ self value: 12! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! pageUp ^ self value: 11! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! space "Answer the Character representing a space." ^self value: 32! ! !Character class methodsFor: 'accessing untypeable characters' stamp: ''! tab "Answer the Character representing a tab." ^self value: 9! ! !Color class methodsFor: 'other' stamp: 'ssa 9/13/2008 16:04'! colorChart ^ColorChart! ! !Color class methodsFor: 'other' stamp: 'ssa 9/13/2008 16:04'! colorChart: aChart ColorChart _ aChart! ! !Color class methodsFor: 'color from user' stamp: 'ssa 9/13/2008 15:52'! fromUser "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette." "Note: Since the color chart is cached, you may need to do 'ColorChart _ nil' after changing the oldColorPaletteForDepth:extent: method." "Color fromUser" | d startPt save tr oldColor c here s | d _ Display depth. ((ColorChart == nil) or: [ColorChart depth ~= Display depth]) ifTrue: [ColorChart _ self oldColorPaletteForDepth: d extent: (2 * 144)@80]. startPt _ Sensor cursorPoint "y < Display center y ifTrue: [startPt _ 0@(Display boundingBox bottom - ColorChart height)] ifFalse: [startPt _ 0@0]". save _ Form fromDisplay: (startPt extent: ColorChart extent). ColorChart displayAt: startPt. tr _ ColorChart extent - (50@19) corner: ColorChart extent. tr _ tr translateBy: startPt. oldColor _ nil. [Sensor anyButtonPressed] whileFalse: [ c _ Display colorAt: (here _ Sensor cursorPoint). (tr containsPoint: here) ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c] ifTrue: [ c _ Color transparent. Display fill: (0@61+startPt extent: 20@19) fillColor: Color white]. c = oldColor ifFalse: [ Display fillWhite: (20@61 + startPt extent: 135@19). c isTransparent ifTrue: [s _ 'transparent'] ifFalse: [s _ c shortPrintString. s _ s copyFrom: 7 to: s size - 1]. s displayAt: 20@61 + startPt. oldColor _ c]]. save displayAt: startPt. Sensor waitNoButton. ^ c ! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/27/2000 20:08'! mappingToARGB: srcBitMasks "Return a ColorMap mapping from srcBitMasks into canonical ARGB space" ^self mappingFrom: srcBitMasks to: #(16rFF0000 16rFF00 16rFF 16rFF000000)! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/4/2001 15:59'! masks: maskArray shifts: shiftArray ^self shifts: shiftArray masks: maskArray colors: nil.! ! !Controller class methodsFor: 'initialization' stamp: 'ssa 8/15/2008 09:40'! initialize "Controller initialize" self MinActivityLapse: 50.! ! !CopyWriter class methodsFor: 'instance creation' stamp: ''! copy: anObject | aStream | aStream _ ReadWriteStream on: (Array new: 100). (self on: aStream) nextPut: anObject. aStream reset. ^(CopyReader on: aStream) next! ! !Delay class methodsFor: 'snapshotting' stamp: 'dmu 5/25/2010 11:02'! startUp "Restart active delay, if any, when resuming a snapshot." self restoreResumptionTimes. ActiveDelay == nil ifFalse: [ActiveDelay activate]. AccessProtect _ Semaphore forMutualExclusion ! ! !EventSensor class methodsFor: 'class initialization' stamp: 'nk 4/12/2004 18:55'! eventPollPeriod ^EventPollPeriod ifNil: [ EventPollPeriod _ 500 ].! ! !EventSensor class methodsFor: 'class initialization' stamp: 'nk 4/12/2004 18:55'! eventPollPeriod: msec "Set the number of milliseconds between checking for events to msec." EventPollPeriod _ msec max: 10.! ! !EventSensor class methodsFor: 'class initialization' stamp: 'ar 7/23/2000 15:06'! install "EventSensor install" "Install an EventSensor in place of the current Sensor." | newSensor | Sensor shutDown. newSensor _ self new. newSensor startUp. "Note: We must use #become: here to replace all references to the old sensor with the new one, since Sensor is referenced from all the existing controllers." Sensor becomeForward: newSensor. "done"! ! !False class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream aStream storeObject: false. ^false! ! !Form class methodsFor: 'instance creation' stamp: ''! archiveVersion "universal 2.3, 2.4 format." ^3! ! !Form class methodsFor: 'instance creation' stamp: ''! dearchive2From: anArchiver "If the archiver is a copier, just get a deepCopy directly from it." | anObject | anArchiver isCopier ifFalse: [^super dearchiveFrom: anArchiver]. anObject _ (anArchiver read: self) deepCopy. anArchiver storeObject: anObject. ^anObject! ! !Form class methodsFor: 'instance creation' stamp: ''! dearchive: versionNumber from: aStream "Override this method when implementing new archive versions for a class." ^versionNumber == self archiveVersion ifTrue: [self dearchiveFrom: aStream] ifFalse: [versionNumber == 2 ifTrue: [self dearchive2From: aStream] ifFalse: [self error: 'Can''t dearchive this version.']]! ! !Form class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: anArchiver "Always use store: and read:." | anObject | anObject _ anArchiver read: self. anArchiver isCopier ifTrue: [anObject _ anObject deepCopy]. anArchiver storeObject: anObject. ^anObject! ! !Form class methodsFor: 'instance creation' stamp: 'ssa 11/17/2008 13:50'! dotOfSize: diameter color: aColor "Create a form which contains a round colored dot with transparent background." | radius form bb rect centerX centerY centerYBias centerXBias radiusSquared xOverY maxy dx | radius _ diameter//2. form _ self extent: diameter@diameter depth: Display depth. form offset: (0@0) - (radius@radius). bb _ (BitBlt current toForm: form) sourceX: 0; sourceY: 0; combinationRule: Form over; fillColor: aColor. rect _ form boundingBox. centerX _ rect center x. centerY _ rect center y. centerYBias _ rect height odd ifTrue: [0] ifFalse: [1]. centerXBias _ rect width odd ifTrue: [0] ifFalse: [1]. radiusSquared _ (rect height asFloat / 2.0) squared - 0.01. xOverY _ rect width asFloat / rect height asFloat. maxy _ rect height - 1 // 2. "First do the inner fill, and collect x values" 0 to: maxy do: [:dy | dx _ ((radiusSquared - (dy * dy) asFloat) sqrt * xOverY) truncated. bb destX: centerX - centerXBias - dx destY: centerY - centerYBias - dy width: dx + dx + centerXBias + 1 height: 1; copyBits. bb destY: centerY + dy; copyBits]. form mapColor: Color white to: Color transparent. ^ form " Time millisecondsToRun: [1 to: 30 do: [:i | (Form dotOfSize: i color: Color random) displayAt: (i*30)@(i*30)]] "! ! !Form class methodsFor: 'instance creation' stamp: 'ssa 8/28/2009 19:30'! fromBinaryStream: aBinaryStream "Read a Form or ColorForm from given file, using the first byte of the file to guess its format. Currently handles: GIF, uncompressed BMP, and both old and new DisplayObject writeOn: formats, JPEG, and PCX. Return nil if the file could not be read or was of an unrecognized format." | firstByte | aBinaryStream binary. firstByte _ aBinaryStream next. firstByte = 1 ifTrue: [ "old Squeakform format" ^ self new readFromOldFormat: aBinaryStream]. firstByte = 2 ifTrue: [ "new Squeak form format" ^ self new readFrom: aBinaryStream]. "Try for JPG, GIF, or PCX..." "Note: The following call closes the stream." ^ ImageReadWriter formFromStream: aBinaryStream ! ! !Cursor class methodsFor: 'class initialization' stamp: 'ssa 1/1/1970 00:21'! initAction "Cursor initAction" ActionCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000100000000 2r0010000100001000 2r0001000100010000 2r0000100100100000 2r0000010001000000 2r0000000000000000 2r1111100100111110 2r0000000000000000 2r0000100001000000 2r0001000100100000 2r0010000100010000 2r0100000100001000 2r0000000100000000 2r0000000000000000 2r0) offset: -7@-7). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'ssa 9/19/2008 11:39'! initLeftArrow LeftArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000100000000000 2r0011100000000000 2r1111111110000000 2r0011100000000000 2r0000100000000000 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: -8@0). "Cursor initLeftArrow"! ! !Cursor class methodsFor: 'class initialization' stamp: 'ssa 1/1/1970 00:31'! initialize "Create all the standard cursors..." self initOrigin. self initRightArrow. self initLeftArrow. self initMenu. self initCorner. self initRead. self initWrite. self initWait. BlankCursor _ Cursor new. self initXeq. self initSquare. self initNormalWithMask. self initCrossHair. self initMarker. self initUp. self initDown. self initMove. self initBottomLeft. self initBottomRight. self initAction. self initResizeLeft. self initResizeTop. self initResizeTopLeft. self initResizeTopRight. self initTopLeft. self initTopRight. self makeCursorsWithMask. "Cursor initialize" ! ! !Cursor class methodsFor: 'constants' stamp: 'ssa 9/19/2008 12:03'! action "Answer the instance of me that indicates a mouse action is available" ^ActionCursor! ! !Cursor class methodsFor: 'constants' stamp: 'ssa 9/19/2008 11:24'! leftArrow "Answer the instance of me that is the shape of an arrow pointing to the left." ^LeftArrowCursor! ! !ImageReadWriter class methodsFor: 'instance creation' stamp: ''! on: aStream "Answer an instance of the receiver for encoding and/or decoding images on the given." ^ self new on: aStream ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:59'! allTypicalFileExtensions "Answer a collection of file extensions (lowercase) which files that my subclasses can read might commonly have" "ImageReadWriter allTypicalFileExtensions" | extensions | extensions _ Set new. self allSubclassesDo: [ :cls | extensions addAll: cls typicalFileExtensions ]. ^extensions! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ls 9/15/1998 19:08'! formFromFileNamed: fileName "Answer a ColorForm stored on the file with the given name." | stream | stream _ FileStream readOnlyFileNamed: fileName. ^self formFromStream: stream! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'tk 5/7/1998 17:35'! formFromServerFile: fileName "Answer a ColorForm stored on the file with the given name. Meant to be called from during the getting of updates from the server. That assures that (Utilities serverUrls) returns the right group of servers." | form urls doc | urls _ Utilities serverUrls collect: [:url | url, fileName]. " fileName starts with: 'updates/' " urls do: [:aURL | (fileName findTokens: '.') last asLowercase = 'gif' ifTrue: [ form _ HTTPSocket httpGif: aURL. form = (ColorForm extent: 20@20 depth: 8) ifTrue: [self inform: 'The file ',aURL,' is ill formed.']. ^ form]. (fileName findTokens: '.') last asLowercase = 'bmp' ifTrue: [ doc _ HTTPSocket httpGet: aURL accept: 'image/bmp'. form _ Form fromBMPFile: doc. doc close. form ifNil: [self inform: 'The file ',aURL,' is ill formed.'. ^ Form new] ifNotNil: [^ form]]. self inform: 'File ', fileName, 'does not end with .gif or .bmp']. self inform: 'That file not found on any server we know'.! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'sd 1/30/2004 15:18'! formFromStream: aBinaryStream "Answer a ColorForm stored on the given stream. closes the stream" | reader readerClass form | readerClass _ self withAllSubclasses detect: [:subclass | subclass understandsImageFormat: aBinaryStream] ifNone: [ aBinaryStream close. ^self error: 'image format not recognized']. reader _ readerClass new on: aBinaryStream reset. Cursor read showWhile: [ form _ reader nextImage. reader close]. ^ form ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: ''! putForm: aForm onFileNamed: fileName "Store the given form on a file of the given name." | writer | writer _ self on: (FileStream newFileNamed: fileName) binary. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'tk 9/13/97 16:13'! putForm: aForm onStream: aWriteStream "Store the given form on a file of the given name." | writer | writer _ self on: aWriteStream. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:55'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#()! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ar 3/1/2006 22:59'! understandsImageFormat: aStream ^[(self new on: aStream) understandsImageFormat] on: Error do:[:ex| ex return: false]! ! !BMPReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('bmp')! ! !BMPReadWriter class methodsFor: 'testing' stamp: 'ar 6/16/2002 18:55'! displayAllFrom: fd "BMPReadWriter displayAllFrom: FileDirectory default" fd fileNames do:[:fName| (fName endsWith: '.bmp') ifTrue:[ [(Form fromBinaryStream: (fd readOnlyFileNamed: fName)) display. Display forceDisplayUpdate] on: Error do:[:nix|]. ]. ]. fd directoryNames do:[:fdName| self displayAllFrom: (fd directoryNamed: fdName) ].! ! !BMPReadWriter class methodsFor: 'testing' stamp: 'ar 6/16/2002 18:56'! readAllFrom: fd "MessageTally spyOn:[BMPReadWriter readAllFrom: FileDirectory default]" fd fileNames do:[:fName| (fName endsWith: '.bmp') ifTrue:[ [Form fromBinaryStream: (fd readOnlyFileNamed: fName)] on: Error do:[:nix]. ]. ]. fd directoryNames do:[:fdName| self readAllFrom: (fd directoryNamed: fdName) ].! ! !GIFReadWriter class methodsFor: 'class initialization' stamp: ''! initialize "GIFReadWriter initialize" ImageSeparator _ $, asInteger. Extension _ $!! asInteger. Terminator _ $; asInteger. ! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'bf 5/29/2003 01:56'! exampleAnim "GIFReadWriter exampleAnim" | writer extent center | writer := GIFReadWriter on: (FileStream newFileNamed: 'anim.gif'). writer loopCount: 20. "Repeat 20 times" writer delay: 10. "Wait 10/100 seconds" extent := 42@42. center := extent / 2. Cursor write showWhile: [ [2 to: center x - 1 by: 2 do: [:r | "Make a fancy anim without using Canvas - inefficient as hell" | image | image := ColorForm extent: extent depth: 8. 0.0 to: 359.0 do: [:theta | image colorAt: (center + (Point r: r degrees: theta)) rounded put: Color red]. writer nextPutImage: image] ] ensure: [writer close]].! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'nk 7/30/2004 21:40'! grabScreenAndSaveOnDisk "GIFReaderWriter grabScreenAndSaveOnDisk" | form fileName | form := Form fromUser. form bits size = 0 ifTrue: [^Beeper beep]. fileName := FileDirectory default nextNameFor: 'Squeak' extension: 'gif'. Utilities informUser: 'Writing ' , fileName during: [GIFReadWriter putForm: form onFileNamed: fileName]! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" self allSubclasses detect: [:cls | cls wantsToHandleGIFs ] ifNone: ["if none of my subclasses wants , then i''ll have to do" ^ #('gif' )]. ^ #( )! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! wantsToHandleGIFs ^ false! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'mir 11/18/2003 17:00'! formsFromFileNamed: fileName | stream | stream _ FileStream readOnlyFileNamed: fileName. ^ self formsFromStream: stream! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'mir 11/18/2003 17:00'! formsFromStream: stream | reader | reader _ self new on: stream reset. Cursor read showWhile: [reader allImages. reader close]. ^reader! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 6/12/2004 13:12'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('gif')! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! wantsToHandleGIFs ^true! ! !JPEGHuffmanTable class methodsFor: 'constants' stamp: 'tao 10/21/97 22:15'! lookahead ^ Lookahead! ! !JPEGHuffmanTable class methodsFor: 'initialization' stamp: 'tao 10/21/97 11:06'! initialize Lookahead _ 8. BitBufferSize _ 16! ! !JPEGReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('jpg' 'jpeg')! ! !JPEGReadWriter class methodsFor: 'image reading/writing' stamp: 'ar 6/16/2002 18:54'! understandsImageFormat: aStream (JPEGReadWriter2 understandsImageFormat: aStream) ifTrue:[^false]. aStream reset. aStream next = 16rFF ifFalse: [^ false]. aStream next = 16rD8 ifFalse: [^ false]. ^true! ! !JPEGReadWriter class methodsFor: 'initialization' stamp: 'ar 3/3/2001 23:07'! initialize "JPEGReadWriter initialize" "general constants" DCTSize _ 8. MaxSample _ (2 raisedToInteger: DCTSize) - 1. SampleOffset _ MaxSample // 2. FloatSampleOffset _ SampleOffset asFloat. DCTSize2 _ DCTSize squared. QuantizationTableSize _ 4. HuffmanTableSize _ 4. "floating-point Inverse Discrete Cosine Transform (IDCT) constants" ConstBits _ 13. Pass1Bits _ 2. DCTK1 _ 2 sqrt. DCTK2 _ 1.847759065. DCTK3 _ 1.082392200. DCTK4 _ -2.613125930. Pass1Div _ 1 bitShift: ConstBits - Pass1Bits. Pass2Div _ 1 bitShift: ConstBits + Pass1Bits + 3. "fixed-point Inverse Discrete Cosine Transform (IDCT) constants" FIXn0n298631336 _ 2446. FIXn0n390180644 _ 3196. FIXn0n541196100 _ 4433. FIXn0n765366865 _ 6270. FIXn0n899976223 _ 7373. FIXn1n175875602 _ 9633. FIXn1n501321110 _ 12299. FIXn1n847759065 _ 15137. FIXn1n961570560 _ 16069. FIXn2n053119869 _ 16819. FIXn2n562915447 _ 20995. FIXn3n072711026 _ 25172. "fixed-point color conversion constants" FIXn0n34414 _ 22554. FIXn0n71414 _ 46802. FIXn1n40200 _ 91881. FIXn1n77200 _ 116130. "reordering table from JPEG zig-zag order" JPEGNaturalOrder _ #( 1 2 9 17 10 3 4 11 18 25 33 26 19 12 5 6 13 20 27 34 41 49 42 35 28 21 14 7 8 15 22 29 36 43 50 57 58 51 44 37 30 23 16 24 31 38 45 52 59 60 53 46 39 32 40 47 54 61 62 55 48 56 63 64). "scale factors for the values in the Quantization Tables" QTableScaleFactor _ (0 to: DCTSize-1) collect: [:k | k = 0 ifTrue: [1.0] ifFalse: [(k * Float pi / 16) cos * 2 sqrt]]. "dithering masks" (DitherMasks _ Dictionary new) add: 0 -> 0; add: 1 -> 127; add: 2 -> 63; add: 4 -> 63; add: 8 -> 31; add: 16 -> 7; add: 32 -> 0. "dictionary of marker parsers" (JFIFMarkerParser _ Dictionary new) add: (16r01 -> #parseNOP); add: (16rC0 -> #parseStartOfFile); add: (16rC4 -> #parseHuffmanTable); addAll: ((16rD0 to: 16rD7) collect: [:m | Association key: m value: #parseNOP]); add: (16rD8 -> #parseStartOfInput); add: (16rD9 -> #parseEndOfInput); add: (16rDA -> #parseStartOfScan); add: (16rDB -> #parseQuantizationTable); add: (16rDD -> #parseDecoderRestartInterval); add: (16rE0 -> #parseAPPn); add: (16rE1 -> #parseAPPn)! ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'ar 6/16/2002 18:54'! primJPEGPluginIsPresent ^false! ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'jm 12/22/2001 11:55'! putForm: aForm quality: quality progressiveJPEG: progressiveFlag onFileNamed: fileName "Store the given Form as a JPEG file of the given name, overwriting any existing file of that name. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG." | writer | FileDirectory deleteFilePath: fileName. writer _ self on: (FileStream newFileNamed: fileName) binary. Cursor write showWhile: [ writer nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag]. writer close. ! ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('jpg' 'jpeg')! ! !ListItemWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 3/30/1999 18:28'! with: anObject ^self new setItem: anObject! ! !ListItemWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 16:44'! with: anObject model: aModel ^self new setItem: anObject model: aModel! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 20:36'! fileReaderServicesForFile: fullName suffix: suffix ^(#('gif' 'jpg' 'jpeg' 'bmp')includes: suffix) ifTrue: [ self services] ifFalse: [#()]! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 3/9/2010 12:42'! importGraphic: fileName "self importGraphic:'/Users/samadams/Desktop/ssa working/lockClosed.gif'" | fname image selector | fname _ fileName sansPeriodSuffix. selector _ fname copyFrom: (fname lastIndexOf:$/)+ 1 to: fname size. image _ Form fromFileNamed: fileName. self installGraphic: image named: selector. ! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 11/26/2009 22:54'! installGraphic: aForm named: aString "add a new method to me named aString that regenerates aForm" | selector response code startString | startString _ aString select:[:c| c isLetter | c isDigit]. selector _ (self respondsTo: startString asSymbol) ifTrue:[[response _ FillInTheBlank request:'Selector #',startString,' already used.\Enter a new selector\to store this graphic under' withCRs initialAnswer: startString. response isEmpty ifTrue:[^self]. self respondsTo: response asSymbol] whileTrue. response] ifFalse:[startString]. code _ selector,' "Cursor blank showWhile:[self ',selector,' follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" "FormView open: self ',selector,' named: ''',selector,'''" ^',aForm storeString. self class compile: code classified:'graphics'! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 19:51'! serviceImportGraphic ^SimpleServiceEntry provider: self label: 'import graphic' selector: #importGraphic: description: 'import graphic to LyGraphicLibrary' buttonLabel: 'install'! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 19:48'! services ^ Array with: self serviceImportGraphic ! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/5/2010 20:33'! selfTwistyClosed "Cursor blank showWhile:[self selfTwistyClosed follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 5@10 depth: 8 fromArray: #( 4278190080 0 4294901760 0 4294967040 0 4294967295 0 4294967295 4278190080 4294967295 4278190080 4294967295 0 4294967040 0 4294901760 0 4278190080 0) offset: 0@0) colorsFromArray: #(#( ) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/5/2010 20:33'! selfTwistyOpen "Cursor blank showWhile:[self selfTwistyOpen follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 10@10 depth: 8 fromArray: #( 0 4278190080 0 255 4294901760 0 65535 4294901760 0 16777215 4294967040 0 4294967295 4294967040 0 16777215 4294967295 0 255 4294967295 0 0 16777215 4278190080 0 255 4278190080 0 0 16711680) offset: 0@0) colorsFromArray: #(#( ) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/4/2010 16:22'! workWarningCone "Cursor blank showWhile:[self workWarningCone follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 64@64 depth: 8 fromArray: #( 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4271808092 1549557758 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4266482012 1503549182 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4262222169 1128495870 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1360216899 1128487254 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 135742239 1128481560 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 136201027 524501875 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 140067651 1128481566 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124109 742605599 1128481624 1459551998 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 320806723 524501827 1442774782 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124039 236526106 522133279 1442774782 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278079746 269028884 336863007 2052521726 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278084614 33820180 437919519 2544107262 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278059008 21712149 2223281059 2170748670 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4272103936 1610637408 2164359520 23110654 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267704416 6291457 1616928864 1610711550 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261412960 16810336 1616928769 2170585598 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267713120 1610702944 23093344 2172739838 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2734710784 1616928864 1616904577 1610703011 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1610637313 1616904193 1619091585 2170585473 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 570458368 16810336 2170585440 1619067265 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 23093377 1619067232 1610702977 2172748198 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124116 177443713 2172748161 2172748161 2744355443 1459551998 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124109 135807833 1451853446 2256950614 1499225210 1912536830 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 656296259 1128481603 1130125660 1547918402 1912536830 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124071 675496771 1229144905 1128483139 1229538140 503250686 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278079752 356729667 1128483139 1128874825 1128483145 1938554622 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278085416 356731203 1128874825 1128483139 1229538121 2054094590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278061095 407061315 1128481603 1128874825 1128483139 1131347710 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4269886504 505356063 1128481603 1128481603 1126113091 1230222590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267728903 1126111775 438247199 1126122271 522133315 2309198590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261437536 2205032218 521805599 438247199 524506515 2743173630 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261478400 1619104405 2223409430 1433306757 2510520705 2172739838 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2164285441 1610702977 1652654465 2172748161 2172752513 2172748195 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1616904288 2170577025 1610711425 2172748161 2457960833 2173862273 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 6316128 1610702977 2170585473 2172748161 2172748178 2172748161 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124195 16777312 23093249 1619067265 1652646529 2173862273 2172748161 2784952062 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124128 6324481 1619100000 2172748161 2172748161 2172748161 2457960800 2751397630 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124132 1616928864 1619091585 2172748130 2172740242 2172752513 1619100033 2516516606 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 1684013408 2170552672 2164359553 2172748161 2172748161 1650483787 754908926 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278080551 1292416129 25264513 1619100033 2172748161 2173862290 2170683692 676855550 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124051 270422312 673012102 3028386177 1686208897 2173862290 2172756901 2536256029 946883070 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 671615244 507651880 742015836 1549183400 3030627491 2745414822 2996280648 1112087881 743721308 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278059779 134752019 1127876648 675891523 1229538121 1230784638 2120173897 1230981449 1229537353 493902409 1229586174 4278124286 4278124286 4278124286 4278124286 4278124286 4262200071 134875678 523380520 357122889 1128876355 1229539657 1229539657 1598638409 1229539423 1465152329 1128876542 4278124286 4278124286 4278124286 4278124286 4278124286 4268950279 134752286 1126705192 843663683 1229146441 1229146441 1229544521 1230981471 1229539657 1517383241 1230784841 1560215294 4278124286 4278124286 4278124286 4278124286 4266930691 134875706 1126639660 977486665 1229539651 1229539657 1548306780 1229545289 1600080223 1517383772 1229539679 1228938750 4278124286 4278124286 4278124286 4278124286 4278085939 134875667 1126639656 1212760905 1128876361 1229539657 1230784841 1598643273 1598644060 2117628255 1230784841 1598044211 4278124286 4278124286 4278124286 4278124286 4278124145 1846151692 405219111 1109346627 1128874825 1128876380 1229539679 1230784860 1229539679 1483823689 1548306780 1228943922 4278124286 4278124286 4278124286 4278124286 4278124286 2388069385 167912236 524492611 1128483139 1229146441 1229539657 1229539651 1128487260 2119671369 1229545289 1545418808 3221159678 4278124286 4278124286 4278124286 4278124286 4272786956 51387734 1549344579 524492611 1128481603 1128481603 1128481603 1130121632 1520322889 1230981468 1079676573 3388931838 4278124286 4278124286 4278124286 4278124286 4278095517 320020034 1549556825 1128481603 524501827 1128481603 1497586780 1549574304 1598638409 1598644128 2695732618 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 2685616926 1130143327 2656853081 1549556060 1499225180 1549753439 2694864713 1598638409 2694884768 2915041022 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2911781407 522142537 1553883040 2657067100 2690621600 2694881375 1599889225 1235263661 2695741950 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4273778012 522133315 1128874825 1230784860 1549551945 1128481628 1229545376 2912985276 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 1547902751 1128481603 1128874825 1128481567 1128483164 2695736749 2919169790 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2908504863 522142531 1126122271 1128481603 1549574317 2913861374 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4272791625 1128472387 524501827 1128488096 2913840583 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278100128 1547913539 1229146460 2694884781 3170828030 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 2912985248 2694884781 2696740606 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4273778080 2694888702 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.878 0.815) #(0.972 0.815 0.627) #(0.972 0.784 0.564) #(0.972 0.784 0.47) #(0.972 0.753 0.595) #(0.972 0.753 0.501) #(0.972 0.721 0.564) #(0.972 0.721 0.501) #(0.972 0.721 0.313) #(0.972 0.69 0.439) #(0.972 0.69 0.282) #(0.972 0.658 0.408) #(0.972 0.658 0.376) #(0.972 0.658 0.156) #(0.972 0.627 0.376) #(0.972 0.627 0.345) #(0.972 0.627 0.313) #(0.972 0.627 0.125) #(0.972 0.595 0.282) #(0.972 0.595 0.094) #(0.972 0.564 0.313) #(0.972 0.564 0.219) #(0.972 0.533 0.188) #(0.972 0.533 0.125) #(0.972 0.533 0.063) #(0.972 0.533 0.031) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.219) #(0.972 0.47 0.063) #(0.972 0.47 0.031) #(0.94 0.94 0.972) #(0.94 0.94 0.94) #(0.94 0.909 0.878) #(0.94 0.753 0.627) #(0.94 0.721 0.533) #(0.94 0.69 0.501) #(0.94 0.69 0.47) #(0.94 0.658 0.501) #(0.94 0.658 0.439) #(0.94 0.627 0.47) #(0.94 0.627 0.439) #(0.94 0.627 0.408) #(0.94 0.595 0.408) #(0.94 0.595 0.376) #(0.94 0.595 0.345) #(0.94 0.564 0.376) #(0.94 0.564 0.345) #(0.94 0.564 0.282) #(0.94 0.533 0.345) #(0.94 0.533 0.25) #(0.94 0.501 0.313) #(0.94 0.501 0.282) #(0.94 0.501 0.219) #(0.94 0.501 0.188) #(0.94 0.47 0.25) #(0.94 0.47 0.188) #(0.94 0.47 0.156) #(0.94 0.47 0.0) #(0.94 0.439 0.188) #(0.94 0.439 0.094) #(0.94 0.439 0.063) #(0.94 0.439 0.0) #(0.94 0.408 0.156) #(0.94 0.408 0.125) #(0.94 0.408 0.063) #(0.94 0.408 0.031) #(0.94 0.408 0.0) #(0.94 0.376 0.094) #(0.94 0.376 0.031) #(0.94 0.376 0.0) #(0.94 0.345 0.063) #(0.94 0.313 0.031) #(0.94 0.313 0.0) #(0.909 0.784 0.627) #(0.909 0.721 0.564) #(0.909 0.658 0.47) #(0.909 0.658 0.408) #(0.909 0.627 0.47) #(0.909 0.627 0.439) #(0.909 0.595 0.408) #(0.909 0.595 0.376) #(0.909 0.564 0.282) #(0.909 0.533 0.345) #(0.909 0.501 0.188) #(0.909 0.47 0.156) #(0.909 0.408 0.188) #(0.909 0.408 0.063) #(0.909 0.408 0.0) #(0.909 0.376 0.156) #(0.909 0.376 0.063) #(0.909 0.345 0.031) #(0.909 0.345 0.0) #(0.909 0.313 0.031) #(0.909 0.282 0.0) #(0.878 0.878 0.909) #(0.878 0.878 0.878) #(0.878 0.847 0.847) #(0.878 0.847 0.815) #(0.878 0.815 0.753) #(0.878 0.784 0.721) #(0.878 0.721 0.595) #(0.878 0.658 0.501) #(0.878 0.627 0.501) #(0.878 0.595 0.47) #(0.878 0.533 0.376) #(0.878 0.533 0.313) #(0.878 0.533 0.219) #(0.878 0.501 0.313) #(0.878 0.501 0.282) #(0.878 0.501 0.25) #(0.878 0.47 0.313) #(0.878 0.47 0.282) #(0.878 0.47 0.25) #(0.878 0.47 0.219) #(0.878 0.47 0.188) #(0.878 0.439 0.25) #(0.878 0.439 0.219) #(0.878 0.439 0.188) #(0.878 0.439 0.156) #(0.878 0.439 0.125) #(0.878 0.439 0.094) #(0.878 0.408 0.156) #(0.878 0.408 0.125) #(0.878 0.376 0.125) #(0.878 0.345 0.094) #(0.878 0.313 0.0) #(0.878 0.282 0.0) #(0.847 0.847 0.847) #(0.847 0.815 0.815) #(0.847 0.69 0.627) #(0.847 0.627 0.408) #(0.847 0.595 0.408) #(0.847 0.564 0.345) #(0.847 0.564 0.313) #(0.847 0.501 0.345) #(0.847 0.501 0.25) #(0.847 0.439 0.282) #(0.847 0.439 0.219) #(0.847 0.408 0.156) #(0.847 0.408 0.125) #(0.847 0.345 0.063) #(0.847 0.313 0.063) #(0.815 0.815 0.847) #(0.815 0.815 0.815) #(0.815 0.784 0.753) #(0.815 0.69 0.595) #(0.815 0.69 0.564) #(0.815 0.658 0.564) #(0.815 0.595 0.439) #(0.815 0.533 0.408) #(0.815 0.533 0.345) #(0.815 0.501 0.313) #(0.815 0.439 0.25) #(0.815 0.408 0.219) #(0.815 0.376 0.156) #(0.815 0.345 0.125) #(0.815 0.345 0.0) #(0.815 0.313 0.0) #(0.815 0.282 0.031) #(0.815 0.282 0.0) #(0.815 0.25 0.0) #(0.784 0.784 0.753) #(0.784 0.753 0.784) #(0.784 0.721 0.69) #(0.784 0.69 0.627) #(0.784 0.658 0.595) #(0.784 0.627 0.533) #(0.784 0.501 0.345) #(0.784 0.313 0.094) #(0.784 0.313 0.0) #(0.784 0.282 0.063) #(0.784 0.282 0.031) #(0.784 0.25 0.0) #(0.753 0.753 0.753) #(0.753 0.69 0.658) #(0.753 0.658 0.564) #(0.753 0.595 0.501) #(0.753 0.25 0.0) #(0.721 0.721 0.721) #(0.721 0.69 0.69) #(0.721 0.595 0.564) #(0.721 0.595 0.533) #(0.721 0.408 0.156) #(0.69 0.313 0.125) #(0.69 0.25 0.031) #(0.69 0.25 0.0) #(0.69 0.219 0.0) #(0.658 0.345 0.188) #(0.658 0.313 0.125) #(0.658 0.282 0.094) #(0.658 0.25 0.063) #(0.658 0.219 0.0) #(0.627 0.313 0.156) #(0.627 0.25 0.063) #(0.627 0.219 0.031) #(0.595 0.376 0.282) #(0.595 0.25 0.063) #(0.595 0.188 0.0) #(0.564 0.533 0.533) #(0.564 0.219 0.063) #(0.564 0.188 0.0) #(0.533 0.533 0.533) #(0.533 0.501 0.501) #(0.533 0.156 0.0) #(0.47 0.439 0.439) #(0.47 0.408 0.345) #(0.47 0.345 0.313) #(0.47 0.282 0.188) #(0.47 0.219 0.031) #(0.47 0.188 0.031) #(0.47 0.156 0.0) #(0.439 0.408 0.376) #(0.439 0.219 0.125) #(0.439 0.188 0.094) #(0.439 0.156 0.063) #(0.439 0.156 0.031) #(0.439 0.125 0.0) #(0.408 0.188 0.063) #(0.408 0.156 0.031) #(0.408 0.125 0.0) #(0.376 0.345 0.313) #(0.376 0.313 0.282) #(0.376 0.125 0.0) #(0.345 0.345 0.345) #(0.345 0.282 0.282) #(0.313 0.313 0.313) #(0.313 0.313 0.282) #(0.313 0.094 0.0) #(0.282 0.094 0.0) #(0.25 0.25 0.25) #(0.25 0.125 0.031) #(0.25 0.063 0.0) #(0.219 0.219 0.219) #(0.219 0.188 0.188) #(0.219 0.156 0.125) #(0.219 0.125 0.063) #(0.219 0.125 0.0) #(0.219 0.094 0.031) #(0.219 0.063 0.0) #(0.188 0.188 0.188) #(0.188 0.063 0.0) #(0.156 0.156 0.156) #(0.156 0.031 0.0) #(0.125 0.063 0.031) #(0.125 0.031 0.0) #(0.094 0.094 0.094) #(0.094 0.063 0.063) #(0.094 0.031 0.0) #(0.063 0.031 0.031) #(0.063 0.0 0.0) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #( ) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 12:30'! audition: selector "self audition: #rgbAddButton" "Audition a graphic, resizing it dynamically based on its screen x location, Answering the resized icon" | resized | Sensor waitNoButton. Cursor blank show. [Sensor noButtonPressed] whileTrue:[ resized _ self graphicNamed: selector resizedTo: Sensor cursorPoint. resized follow:[Sensor cursorPoint] while:[false]]. Cursor normal show. ^resized! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 13:14'! graphicNamed: selector resizedTo: anExtentPoint "(self graphicNamed: #rgbAddButton resizedTo: 16@16) followCursor" "(self graphicNamed: #rgbAddButton resizedTo: 400@400) followCursor" | base resized | base _ self perform: selector. resized _ base scaledToSize: anExtentPoint. resized offset: (base offset/ base extent) * resized offset rounded. ^resized! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 17:19'! graphicNamed: selector withWhitemappedTo: aColor "(self graphicNamed: #closedTwisty withWhitemappedTo: Color lightBlue) followCursor" "(self graphicNamed: #closedTwisty withWhitemappedTo: Color green) followCursor" | base | base _ self perform: selector. base mapColor: Color white to: aColor. ^base! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassNameSize "Return the default maximum width of the class name alone" ^30! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassPlusSelectorSize "Return the default maximum width of the class plus selector together (not counting the '>>')" ^60! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:26'! defaultMaxTabs "Return the default number of tabs after which leading white space is compressed" ^18! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:41'! defaultPollPeriod "Answer the number of milliseconds between interrupts for spyOn: and friends. This should be faster for faster machines." ^DefaultPollPeriod ifNil: [ DefaultPollPeriod _ 1 ]! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:41'! defaultPollPeriod: numberOfMilliseconds "Set the default number of milliseconds between interrupts for spyOn: and friends. This should be faster for faster machines." DefaultPollPeriod := numberOfMilliseconds! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:34'! spyOn: aBlock "MessageTally spyOn: [100 timesRepeat: [3.14159 printString]]" | node result | node _ self new. result _ node spyEvery: self defaultPollPeriod on: aBlock. (StringHolder new contents: (String streamContents: [:s | node report: s; close])) openLabel: 'Spy Results'. ^ result! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:34'! spyOn: aBlock toFileNamed: fileName "Spy on the evaluation of aBlock. Write the data collected on a file named fileName." | file value node | node _ self new. value _ node spyEvery: self defaultPollPeriod on: aBlock. file _ FileStream newFileNamed: fileName. node report: file; close. file close. ^value! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:35'! spyOnProcess: aProcess forMilliseconds: msecDuration "| p | p _ [100000 timesRepeat: [3.14159 printString]] fork. (Delay forMilliseconds: 100) wait. MessageTally spyOnProcess: p forMilliseconds: 1000" | node | node _ self new. node spyEvery: self defaultPollPeriod onProcess: aProcess forMilliseconds: msecDuration. (StringHolder new contents: (String streamContents: [:s | node report: s; close])) openLabel: 'Spy Results'! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:35'! spyOnProcess: aProcess forMilliseconds: msecDuration toFileNamed: fileName "Spy on the evaluation of aProcess. Write the data collected on a file named fileName. Will overwrite fileName" | file node | node _ self new. node spyEvery: self defaultPollPeriod onProcess: aProcess forMilliseconds: msecDuration. file _ FileStream fileNamed: fileName. node report: file; close. file close! ! !MessageTally class methodsFor: 'spying' stamp: ''! tallySends: aBlock "MessageTally tallySends: [3.14159 printString]" ^ self tallySendsTo: nil inBlock: aBlock showTree: true! ! !MessageTally class methodsFor: 'spying' stamp: 'tk 5/4/1998 17:01'! tallySendsTo: receiver inBlock: aBlock showTree: treeOption "MessageTally tallySends: [3.14159 printString]" "This method uses the simulator to count the number of calls on each method invoked in evaluating aBlock. If receiver is not nil, then only sends to that receiver are tallied. Results are presented as leaves, sorted by frequency, preceded, optionally, by the whole tree." | prev tallies startTime totalTime | startTime _ Time millisecondClockValue. tallies _ MessageTally new class: aBlock receiver class method: aBlock method. prev _ aBlock. thisContext sender runSimulated: aBlock contextAtEachStep: [:current | current == prev ifFalse: ["call or return" prev sender == nil ifFalse: ["call only" (receiver == nil or: [current receiver == receiver]) ifTrue: [tallies tally: current by: 1]]. prev _ current]]. totalTime _ Time millisecondClockValue - startTime // 1000.0 roundTo: 0.01. (StringHolder new contents: (String streamContents: [:s | s nextPutAll: 'This simulation took ' , totalTime printString , ' seconds.'; cr. treeOption ifTrue: [tallies fullPrintOn: s tallyExact: true orThreshold: 0] ifFalse: [tallies leavesPrintOn: s tallyExact: true orThreshold: 0]. tallies close])) openLabel: 'Spy Results'! ! !MessageTally class methodsFor: 'spying' stamp: ''! time: aBlock ^ Time millisecondsToRun: aBlock! ! !Number class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream ^aStream read: self! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! parent ^parent! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! parent: anObject parent _ anObject! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:49'! selector parent ifNil: [ ^nil ]. ^(parent withoutListWrapper class allInstVarNames includes: itemName) ifTrue: [ itemName asSymbol ]! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:49'! setItem: anObject name: aString model: aModel item _ anObject. model _ aModel. itemName _ aString.! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! setItem: anObject name: aString model: aModel parent: itemParent parent _ itemParent. self setItem: anObject name: aString model: aModel! ! !ObjectExplorerWrapper methodsFor: 'converting' stamp: 'ssa 7/7/2010 11:08'! asString | explorerString string | explorerString _ [item asExplorerString] on: Error do: ['']. string _ (itemName ifNotNil: [itemName , ': '] ifNil: ['']) , explorerString. (string includes: Character cr) ifTrue: [^ string withSeparatorsCompacted]. ^ string! ! !ObjectExplorerWrapper methodsFor: 'converting' stamp: 'nk 7/24/2003 10:16'! itemName ^itemName! ! !ObjectExplorerWrapper methodsFor: 'monitoring' stamp: 'nk 7/12/2003 18:28'! refresh "hack to refresh item given an object and a string that is either an index or an instance variable name." [ | index | (model class allInstVarNames includes: itemName) ifTrue: [ item _ model instVarNamed: itemName ] ifFalse: [ index _ itemName asNumber. (index between: 1 and: model basicSize) ifTrue: [ item _ model basicAt: index]] ] on: Error do: [ :ex | item _ nil ]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 16:17'! contents (item respondsTo: #explorerContents) ifTrue: [^item explorerContents collect:[:e| e parent: self]]. "For all others, show named vars first, then indexed vars" ^(item class allInstVarNames asOrderedCollection withIndexCollect: [:each :index | self class with: (item instVarAt: index) name: each model: item parent: self]) , ((1 to: item basicSize) collect: [:index | self class with: (item basicAt: index) name: index printString model: item parent: self])! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:09'! depth ^self parent isNil ifTrue:[0]ifFalse:[self parent depth + 1]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'RAA 6/21/1999 11:27'! hasContents ^item hasContentsInExplorer ! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:34'! icon "Answer a form to be used as icon" ^ Preferences visualExplorer ifTrue: [item iconOrThumbnailOfSize: 16] ifFalse: [nil]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! isOpen "Answer the value of isOpen" isOpen isNil ifTrue:[self isOpen: false]. ^ isOpen! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! isOpen: anObject "Set the value of isOpen" isOpen _ anObject! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! itemName: anObject "Set the value of itemName" itemName _ anObject! ! !ClassHierarchyExplorerWrapper methodsFor: 'testing' stamp: 'ssa 3/1/2010 12:06'! hasContents ^self item subclasses notEmpty ! ! !ClassHierarchyExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:07'! asString ^self itemName! ! !ClassHierarchyExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:04'! contents ^ self item subclasses collect: [:ea| self class with: ea name: ea name model: item parent: self]! ! !ClassHierarchyExplorerWrapper methodsFor: 'printing' stamp: 'ssa 3/1/2010 12:19'! printOn: aStream aStream nextPutAll:self class name,' on: ',self item printString! ! !ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:50'! with: anObject name: aString model: aModel ^self new setItem: anObject name: aString model: aModel! ! !ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:16'! with: anObject name: aString model: aModel parent: aParent ^self new setItem: anObject name: aString model: aModel parent: aParent ! ! !OpaqueForm methodsFor: 'private' stamp: 'ssa 8/21/2009 20:42'! colormapIfNeededFor: df ^self colorForm colormapIfNeededFor: df! ! !OpaqueForm methodsFor: 'private' stamp: 'ssa 8/22/2009 13:50'! setFigure: figureForm shape: shapeForm "Initialize the instance variables." | figure shape | figure _ figureForm. shape _ ColorForm mappingWhiteToTransparentFrom:( shapeForm asFormOfDepth: 8). figure displayOn: shape at: 0@0 clippingBox: figure boundingBox rule: Form paint fillColor: nil. self colorForm: shape! ! !OpaqueForm methodsFor: 'display box access' stamp: 'ssa 8/21/2009 20:28'! computeBoundingBox "Answer the minimum enclosing rectangle around the image." ^self colorForm boundingBox! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:44'! colorForm "Answer the value of colorForm" self! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:44'! colorForm: anObject "Set the value of colorForm" self become: anObject! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! figure "Answer the visible image of the receiver." ^ self colorForm! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! offset "Answer the offset for displaying the image." ^ self figure offset! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! shape "Answer the form that indicates what part of the background should get occluded in displaying the receiver." ^ self colorForm! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:34'! valueAt: aPoint "Answer the bit of the form image at position aPoint. The value is either 0, 1 or 2 where 0 is white, 1 is black, 2 is transparent." (self colorForm isTransparentAt: aPoint) ifTrue:[^2]. ^(self colorAt: aPoint) isBlack ifTrue:[1]ifFalse:[0]! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:37'! valueAt: aPoint put: value "Store a bit of the form image at position aPoint. The value is either 0, 1 or 2 where 0 is white, 1 is black, 2 is transparent." (1 - (value//2)) = 2 ifTrue:[self colorForm colorAt: aPoint put: Color transparent] ifFalse:[value\\2 = 0 ifTrue:[self colorForm colorAt: aPoint put: Color white] ifFalse:[self colorForm colorAt: aPoint put: Color black]]! ! !OpaqueForm methodsFor: 'displaying' stamp: 'ssa 9/2/2009 09:30'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aColor "Display the receiver on the display medium aDisplayMedium positioned at aDisplayPoint within the rectangle clipRectangle and with the rule, ruleInteger, and mask, aForm. " self colorForm displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aColor! ! !OpaqueForm methodsFor: 'displaying' stamp: 'ssa 8/21/2009 20:39'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aColor "See comment in Form." self colorForm displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: Form under fillColor: aColor! ! !OpaqueForm methodsFor: 'printing' stamp: 'ssa 8/21/2009 20:40'! storeOn: aStream "Append to the argument aStream a sequence of characters that is an expression whose evaluation creates an object similar to the receiver. The general format for OpaqueForm is OpaqueForm figure: ( figure ) shape: ( shape )." aStream nextPutAll: '(OpaqueForm colorForm: ('. self colorForm storeOn: aStream. aStream nextPutAll: '))'! ! !OpaqueForm methodsFor: 'editing' stamp: ''! bitEdit "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." BitEditor openOnForm: self "OpaqueForm makeStar bitEdit."! ! !OpaqueForm class methodsFor: 'examples' stamp: 'ssa 8/21/2009 20:41'! makeStar "Answer a new OpaqueForm in the shape of a five-pointed star filled with black." "OpaqueForm makeStar." "OpaqueForm makeStar bitEdit" | figure shape pen formRect | formRect_ 0@0 extent: 50@50. pen _ Pen new. pen defaultNib: 2. Display fill: formRect fillColor: Color white. pen north; place: formRect center; spiral: 45 angle: 144. shape _ Form fromDisplay: formRect. pen fillColor: Color white; north; place: formRect center; spiral: 30 angle: 144. figure _ Form fromDisplay: formRect. ^ OpaqueForm figure: figure shape: shape! ! !OpaqueForm class methodsFor: 'examples' stamp: ''! starCursor "Make the cursor track a five-pointed star." "OpaqueForm starCursor" Cursor blank showWhile: [self makeStar follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]! ! !OpaqueForm class methodsFor: 'instance creation' stamp: ''! figure: figureForm shape: shapeForm "Answer a new instance of the receiver whose figure and shape forms are defined by the arguments." ^ self new setFigure: figureForm shape: shapeForm! ! !OpaqueForm class methodsFor: 'instance creation' stamp: ''! shape: aSolidForm "Answer a new instance of the receiver that is black where aSolidForm is black and transparent where aSolidForm is white." ^ self new setFigure: aSolidForm shape: aSolidForm! ! !Paragraph methodsFor: 'converting' stamp: 'ssa 9/4/2009 10:44'! asForm "Answer a Form made up of the bits that represent the receiver's displayable text." | theForm oldBackColor oldForeColor | textStyle isTTCStyle ifTrue: [ theForm _ (Form extent: compositionRectangle extent depth: Display depth) offset: offset. ] ifFalse: [ theForm _ (ColorForm extent: compositionRectangle extent) offset: offset; colors: (Array with: (backColor == nil ifTrue: [Color transparent] ifFalse: [backColor]) with: (foreColor == nil ifTrue: [Color black] ifFalse: [foreColor])). ]. oldBackColor _ backColor. oldForeColor _ foreColor. backColor _ Color white. foreColor _ Color black. self displayOn: theForm at: 0@0 clippingBox: theForm boundingBox rule: Form over fillColor: nil. backColor _ oldBackColor. foreColor _ oldForeColor. ^ theForm "Example: | p | p _ 'Abc' asParagraph. p foregroundColor: Color red backgroundColor: Color black. p asForm displayOn: Display at: 30@30 rule: Form over" ! ! !Pen methodsFor: 'accessing' stamp: ''! destForm: aForm "2/14/97 ssa added for compatibility." self flag:#compatibility. destForm _ aForm ! ! !Pen methodsFor: 'operations' stamp: 'ssa 11/29/2009 03:27'! turnToward: aPoint "Aim the receiver at apoint" self north; turn: (self penAngleFrom: self location to: aPoint)! ! !Pen methodsFor: 'geometric designs' stamp: 'ssa 2/16/2009 11:50'! mandala: npoints diameter: d "Display restoreAfter: [Pen new mandala: 30 diameter: 400]" "On a circle of diameter d, place npoints number of points. Draw all possible connecting lines between the circumferential points." | l points | "Display fillWhite." l _ 3.14 * d / npoints. self home; up; turn: -90; go: d // 2; turn: 90; go: 0 - l / 2; down. points _ Array new: npoints. 1 to: npoints do: [:i | points at: i put: location rounded. self go: l; turn: 360.0 / npoints]. npoints // 2 to: 1 by: -1 do: [:i | self color: i. 1 to: npoints do: [:j | self place: (points at: j). self goto: (points at: j + i - 1 \\ npoints + 1)]] ! ! !Pen methodsFor: 'private' stamp: 'ssa 2/6/2009 10:49'! direction: aFloat direction _ aFloat. ! ! !Pen methodsFor: 'functions' stamp: 'ssa 11/29/2009 03:24'! penAngleFrom:firstPoint to: lastPoint | offset x y deg | "return the angle of the vector in Pen degrees (0 = north)" offset _ lastPoint - firstPoint. x _ offset x . y _ offset y. x = 0 ifTrue:[ x _ 0.0001]. deg _ (y / x) arcTan radiansToDegrees. x positive & y positive ifTrue:[ deg _ 90 + deg]. x positive & y negative ifTrue:[ deg _ 90 + deg]. x negative & y positive ifTrue:[ deg _ 270 + deg]. x negative & y negative ifTrue:[ deg _ 270 + deg]. ^deg! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:42'! inspectSelection self selection inspect! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:47'! menu: aMenu aMenu add: 'inspect' action: #inspectSelection. aMenu add: 'outline' action: #outlineSelection. ^ aMenu! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:43'! outlineSelection self selection outline! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:55'! perform: selector orSendTo: otherTarget ^self perform: selector! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:29'! childrenOf: anObject ^anObject subobjects! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:02'! initializeList self list do:[:each| self levels at: each put:0]! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levelOf: anItem ^self levels at: anItem ifAbsent:[0]! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levels "Answer the value of levels" levels isNil ifTrue:[self levels: Dictionary new]. ^ levels! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:00'! levels: anObject "Set the value of levels" levels _ anObject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:39'! list "Answer the value of list" list isNil ifTrue:[self list: (OrderedCollection with:self subject )]. ^ list! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:36'! list: anObject "Set the value of list" list _ anObject asOrderedCollection! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems "Answer the value of openItems" openItems isNil ifTrue:[self openItems: Set new]. ^ openItems! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems: anObject "Set the value of openItems" openItems _ anObject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 13:28'! progenyOf: anObject | all | all _ (self childrenOf: anObject)copy. all isEmpty ifTrue:[^all]. all copy do:[:each| all addAll: (self progenyOf: each)]. ^all ! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:18'! selection "Answer the value of selection" selection isNil ifTrue:[self selection: nil]. ^ selection! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 17:15'! selection: anObject "Set the value of selection" selection _ anObject . ! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 7/7/2010 12:40'! subject "Answer the value of subject" subject isNil ifTrue:[self subject: nil]. ^ subject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 08:25'! subject: anObject "Set the value of subject" subject _ anObject! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 13:02'! hasChildren: anObject ^(self childrenOf: anObject) notEmpty ! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 14:07'! hideChildrenOfSelection | kids | self openItems remove: self selection. kids _ self progenyOf: self selection. kids do:[:each| self levels removeKey: each ifAbsent:[]. self openItems remove: each ifAbsent:[]]. self list removeAll: kids ifAbsent:[] ! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 11:42'! isOpen: anItem ^self openItems includes: anItem! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 12:10'! showChildrenOfSelection | kids nextLevel | self openItems add: self selection. nextLevel _ (self levelOf: self selection) + 1. kids _ self childrenOf: self selection. kids isEmpty ifTrue:[^self error:'should never try to show children of an childless object']. kids do:[:each| self levels at: each put: nextLevel]. self list addAll: kids after: self selection! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/10/2009 07:30'! toggleSelection self selection isNil ifTrue:[^self]. (self isOpen: self selection) ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !PluggableOutline methodsFor: 'arrow keys' stamp: 'ssa 9/9/2009 14:47'! arrowKey: aChar from: view "Process the up and down arrows in a list pane. Note that the listView tells us what index variable, how to get the list, and how to move the index. Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | (#(1 4 11 12 30 31) includes: (keyEvent _ aChar asciiValue)) ifFalse: [ ^ self]. oldSelection := view getCurrentSelectionIndex. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view numSelectionsInView. "get this exactly??" keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [self okToChange ifTrue: [view changeModelSelection: nextSelection. "view controller moveMarker"]] ! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:22'! genericMenu: aMenu aMenu add: 'no menu yet' target: self selector: #yourself. ^aMenu! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:44'! getCurrentSelection ^currentSelection! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:46'! noteNewSelection: x currentSelection _ x. self changed: #getCurrentSelection. currentSelection ifNil: [^self]. currentSelection sendSettingMessageTo: self. ! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:53'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:47'! update: aSymbol aSymbol == #hierarchicalList ifTrue: [ ^self changed: #getList ]. super update: aSymbol! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection "Answer the value of currentSelection" currentSelection isNil ifTrue:[self currentSelection: nil]. ^ currentSelection! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection: anObject "Set the value of currentSelection" currentSelection _ anObject! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser "Answer the value of myBrowser" myBrowser isNil ifTrue:[self myBrowser: nil]. ^ myBrowser! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser: anObject "Set the value of myBrowser" myBrowser _ anObject! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 16:15'! hide: anItem "recursively hide this and all progeny" anItem isOpen ifTrue:[(self listedChildrenOf: anItem) do:[:each| self hide: each]]. self levels removeKey: anItem ifAbsent:[]. self list remove: anItem ifAbsent:[self halt]. anItem isOpen: false. ! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 2/26/2010 13:47'! hideChildrenOfSelection (self listedChildrenOf: self currentSelection ) do:[:each| self hide: each]. self currentSelection isOpen: false. ! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 16:14'! listedChildrenOf: aWrapper ^self list select:[:item| item parent == aWrapper]! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 2/26/2010 13:45'! showChildrenOfSelection | kids | self currentSelection hasContents ifFalse:[^self]. kids _ self currentSelection contents. self list addAll: kids after: self currentSelection. self currentSelection isOpen: true.! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 15:44'! toggleSelection self currentSelection isNil ifTrue:[^self]. self currentSelection isOpen ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:11'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" ^ 1 to: 0 "null selection"! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:40'! defaultRootLabel ^'unlabeled object'! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:15'! doItContext "Answer the context in which a text selection can be evaluated." ^nil! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:19'! doItReceiver "Answer the object that should be informed of the result of evaluating a text selection." currentSelection ifNil: [^rootObject]. ^currentSelection withoutListWrapper ! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 6/17/2010 16:25'! getList ^OrderedCollection with: (ObjectExplorerWrapper with: rootObject name: 'root' model: self parent: nil) ! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! inspector "Answer the value of inspector" inspector isNil ifTrue:[self inspector: nil]. ^ inspector! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! inspector: anObject "Set the value of inspector" inspector _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'hg 9/7/2001 12:12'! label ^ rootObject printStringLimitedTo: 32! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:51'! list "Answer the value of list" list isNil ifTrue:[self list: self getList]. ^ list! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! monitorList: anObject "Set the value of monitorList" monitorList _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 12/17/2009 10:02'! monitorProcess "Answer the value of monitorProcess" monitorProcess isNil ifTrue:[self monitorProcess: nil]. ^ monitorProcess! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 12/17/2009 10:02'! monitorProcess: anObject "Set the value of monitorProcess" monitorProcess _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:43'! object ^currentSelection ifNotNilDo: [ :cs | cs withoutListWrapper ]! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 10:02'! parentObject currentSelection ifNil: [ ^nil ]. currentSelection parent ifNil: [ ^rootObject ]. ^currentSelection parent withoutListWrapper! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:40'! rootLabel "Answer the value of rootLabel" rootLabel isNil ifTrue:[self rootLabel: self defaultRootLabel]. ^ rootLabel! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:39'! rootLabel: anObject "Set the value of rootLabel" rootLabel _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! rootObject "Answer the value of rootObject" rootObject isNil ifTrue:[self rootObject: nil]. ^ rootObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! rootObject: anObject "Set the value of rootObject" rootObject _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:47'! selector ^currentSelection ifNotNilDo: [ :cs | cs selector ]! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/9/2010 04:26'! wrapperFor: anObject ^self list detect:[:wrapper| wrapper item == anObject]ifNone:[^nil]! ! !ObjectExplorer methodsFor: 'error handling' stamp: 'nk 7/24/2003 09:29'! doesNotUnderstand: aMessage inspector ifNotNil: [ (inspector respondsTo: aMessage selector) ifTrue: [ ^inspector perform: aMessage selector withArguments: aMessage arguments ]]. ^super doesNotUnderstand: aMessage! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! chasePointers "Open a PointerFinder on the selected item" | path sel savedRoot saved | path := OrderedCollection new. sel := currentSelection. [ sel isNil ] whileFalse: [ path addFirst: sel asString. sel := sel parent ]. path addFirst: #openPath. path := path asArray. savedRoot := rootObject. saved := self object. [ rootObject := nil. self changed: #getList. (Smalltalk includesKey: #PointerFinder) ifTrue: [PointerFinder on: saved] ifFalse: [self objectReferencesToSelection ]] ensure: [ rootObject := savedRoot. self changed: #getList. self changed: path. ]! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:22'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items" ^ StringHolder basicNew codePaneMenu: aMenu shifted: shifted ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! defsOfSelection "Open a browser on all defining references to the selected instance variable, if that's what's currently selected." | aClass sel | (aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash]. sel := self selector. self systemNavigation browseAllStoresInto: sel from: aClass! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'! exploreSelection "Open an ObjectExplorer on the current selection" self object explore! ! !ObjectExplorer methodsFor: 'menus' stamp: 'ssa 1/6/2010 20:35'! explorerKey: aChar from: view "Similar to #genericMenu:..." | insideObject parentObject | currentSelection ifNotNil: [ insideObject := self object. parentObject := self parentObject. inspector ifNil: [inspector := Inspector new]. inspector inspect: parentObject; object: insideObject. aChar == $i ifTrue: [^ self inspectSelection]. aChar == $e ifTrue: [^ self exploreSelection]. aChar == $b ifTrue: [^ inspector browseMethodFull]. aChar == $h ifTrue: [^ inspector classHierarchy]. aChar == $c ifTrue: [^ inspector copyName]. aChar == $p ifTrue: [^ inspector browseFullProtocol]. aChar == $N ifTrue: [^ inspector browseClassRefs]. aChar == $t ifTrue: [^ inspector tearOffTile]. aChar == $v ifTrue: [^ inspector viewerForValue]]. ^ self arrowKey: aChar from: view! ! !ObjectExplorer methodsFor: 'menus' stamp: 'ssa 12/17/2009 10:13'! genericMenu: aMenu "Borrow a menu from my inspector" | insideObject menu parentObject | currentSelection ifNil: [menu := aMenu. menu add: '*nothing selected*' target: self selector: #yourself argument:nil] ifNotNil: [insideObject := self object. parentObject := self parentObject. inspector ifNil: [inspector := Inspector new]. inspector inspect: parentObject; object: insideObject. aMenu selections do:[:each| aMenu targets add: inspector]. inspector fieldListMenu: aMenu. aMenu selections do:[:each| aMenu targets add: inspector]. aMenu selections do: [:i | (#(#inspectSelection #exploreSelection #referencesToSelection #defsOfSelection #objectReferencesToSelection #chasePointers ) includes: i ) ifTrue: [aMenu targets at:(aMenu selections indexOf:i) put:self]]. aMenu addLine; add: 'monitor changes' target: self selector: #monitor: argument: currentSelection]. monitorList isEmptyOrNil ifFalse: [aMenu addLine; add: 'stop monitoring all' target: self selector: #stopMonitoring argument:nil]. ^ aMenu! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'! inspectSelection "Open an Inspector on the current selection" self object inspect! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:00'! objectReferencesToSelection "Open a browser on all references to the selected instance variable, if that's what currently selected. " self systemNavigation browseAllObjectReferencesTo: self object except: (Array with: self parentObject with: currentSelection with: inspector) ifNone: [:obj | self changed: #flash]. ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! referencesToSelection "Open a browser on all references to the selected instance variable, if that's what's currently selected." | aClass sel | (aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash]. sel := self selector. self systemNavigation browseAllAccessesTo: sel from: aClass! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:19'! selectedClass "Answer the class of the receiver's current selection" ^self doItReceiver class ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'! trash "What goes in the bottom pane" ^ ''! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'! trash: newText "Don't save it" ^ true! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:24'! monitor: anObjectExplorerWrapper "Start stepping and watching the given wrapper for changes." anObjectExplorerWrapper ifNil: [ ^self ]. self monitorList at: anObjectExplorerWrapper put: anObjectExplorerWrapper asString. self monitorProcess isNil ifFalse:[self monitorProcess terminate]. self monitorProcess: [[self monitorList notEmpty]whileTrue:[(Delay forMilliseconds:200)wait. self step]] newProcess. [self monitorProcess resume] fork! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'! monitorList ^monitorList ifNil: [ monitorList := WeakIdentityKeyDictionary new ].! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:06'! release self stopMonitoring. super release.! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/12/2003 17:55'! shouldGetStepsFrom: aWorld ^self monitorList notEmpty! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:20'! step "If there's anything in my monitor list, see if the strings have changed." | string changes | changes := false. self monitorList keysAndValuesDo: [ :k :v | k ifNotNil: [ k refresh. (string := k asString) ~= v ifTrue: [ self monitorList at: k put: string. changes := true ]. ] ]. changes ifTrue: [ | sel | sel := currentSelection. self changed: #list. self noteNewSelection: sel. ]. ! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:06'! stopMonitoring monitorList := nil. self monitorProcess ifNotNil:[self monitorProcess terminate]! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/10/2009 16:51'! explorerFor: anObject ^self explorerFor: anObject withLabel:'Object Explorer'! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 3/24/2010 15:05'! explorerFor: anObject withLabel: label | topView listView ptv | rootObject := anObject. topView := StandardSystemView new label: 'Exploring ',anObject class name,' ',label; model: self; yourself. topView addSubView:(listView := ExplorerListView on: self list: #list selected: #getCurrentSelection changeSelected: #noteNewSelection: menu: #genericMenu: keystroke: #explorerKey:from:) in: (0 @ 0 corner: 1 @ 0.8) borderWidth:1. ptv _ PluggableTextView on: self text: #trash accept: #trash: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. ptv askBeforeDiscardingEdits: false. topView addSubView: ptv in: (0 @ 0.8 corner: 1 @ 1) borderWidth:1. listView autoDeselect: false. ^ topView! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:23'! initialExtent ^300@500! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/10/2009 16:42'! openBrowser: aClass Browser newOnClass: aClass selector: nil! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/11/2009 14:37'! openExplorerFor: anObject " ObjectExplorer new openExplorerFor: Smalltalk " (self explorerFor: anObject) controller open. ^ self ! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! centralClass "Answer the value of centralClass" centralClass isNil ifTrue:[self centralClass: nil]. ^ centralClass! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! centralClass: anObject "Set the value of centralClass" centralClass _ anObject! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! getCentralItem ^Array with: (ClassHierarchyExplorerWrapper with: self centralClass name: self centralClass name model: self) ! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:22'! getList | classList prev | classList _ OrderedCollection new. self centralClass allSuperclasses reverseDo: [:aClass | classList add: aClass]. classList add: self centralClass. self centralClass subclassesDo: [:aClass| classList add: aClass]. prev _nil. ^(classList collect:[:cls| prev _ ClassHierarchyExplorerWrapper with: cls name: cls name model: self parent: prev]) asArray! ! !ClassHierarchyExplorer methodsFor: 'user interface' stamp: 'ssa 3/1/2010 12:01'! explorerFor: anObject withLabel: label | topView listView | self centralClass: anObject. topView := StandardSystemView new label: label; model: self; yourself. topView addSubView:(listView := ExplorerListView on: self list: #list selected: #getCurrentSelection changeSelected: #noteNewSelection: menu: #genericMenu: keystroke: #explorerKey:from:) in: (0 @ 0 corner: 1 @ 1) borderWidth:1. listView autoDeselect: false. ^ topView! ! !ObjectExplorer class methodsFor: 'instance creation' stamp: 'ssa 2/8/2010 14:44'! openExplorerFor: anObject labeled: newRootLabel withLabel: label | exp view | exp _ self new rootLabel: newRootLabel. view _ exp explorerFor: anObject withLabel: label . view controller open! ! !ObjectExplorer class methodsFor: 'instance creation' stamp: 'ssa 2/8/2010 14:33'! openExplorerFor: anObject withLabel: label | exp | exp _ self new explorerFor: anObject withLabel: label . exp controller open! ! !Point methodsFor: 'accessing' stamp: 'ssa 11/16/2008 13:12'! x: aNumber x _ aNumber! ! !Point methodsFor: 'accessing' stamp: 'ssa 11/16/2008 13:12'! y: aNumber y _ aNumber! ! !Point methodsFor: 'arithmetic' stamp: 'ssa 11/27/2009 16:15'! inverted ^1 asPoint / self! ! !Point methodsFor: 'comparing' stamp: 'ssa 9/3/2009 07:11'! maxed ^(x max: y) asPoint! ! !Point methodsFor: 'comparing' stamp: 'ssa 9/3/2009 07:11'! mined ^(x min: y) asPoint! ! !Point methodsFor: 'interpolating' stamp: 'ssa 9/7/2009 21:42'! zeno "(10@10) zeno #(10@10 5.0@5.0 2.5@2.5 1.25@1.25)" "(10@4) zeno #(10@4 5.0@2.0)" "(-10@4) zeno " | steps zx zy minSize | steps _ OrderedCollection new. zx _ x zeno. zy _ y zeno. minSize _ zx size min: zy size. 1 to: minSize do:[:index| steps add:(zx at: index)@(zy at: index)]. ^steps asArray! ! !Point methodsFor: 'point functions' stamp: 'ssa 11/16/2008 02:35'! atRandom ^x atRandom @ y atRandom! ! !Point methodsFor: 'point functions' stamp: 'ssa 1/30/2009 10:04'! mandist: aPoint "Answer the Manhattan distance between aPoint and the receiver." ^(x-aPoint x) abs + (y - aPoint y) abs! ! !Point methodsFor: 'point functions' stamp: 'dmu 4/1/2009 20:49'! manhattanDist: aPoint "Answer the distance between aPoint and the receiver." | p | p _ aPoint - self. ^ p x abs + p y abs! ! !Point methodsFor: 'polar coordinates' stamp: ''! complexProduct: aPoint ^((x * aPoint x) - (y * aPoint y)) @ ((x * aPoint y) + (y * aPoint x))! ! !Point methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:26'! moveBy: aPoint "Alter the receiver by moving it by a Point." x _ x + aPoint x. y _ y + aPoint y.! ! !Point methodsFor: 'transforming' stamp: 'ssa 2/8/2009 20:57'! wrapAround: aRectangle "If the receiver lies outside aRectangle, return the nearest point on the other side of the rectangle, otherwise return self." | newX newY | newX _ x. newY _ y. (aRectangle containsPoint: self) ifTrue: [^ self]. x >= aRectangle right ifTrue:[newX _ aRectangle left]. x <= aRectangle left ifTrue:[newX _ aRectangle right]. y >= aRectangle bottom ifTrue:[newY _ aRectangle top]. y <= aRectangle top ifTrue:[newY _ aRectangle bottom]. ^newX@newY! ! !Point methodsFor: 'truncation and round off' stamp: 'ssa 8/25/2009 14:08'! ceiling "Answer a new Point that is the receiver's x and y ceiling." ^x ceiling @ y ceiling! ! !Point methodsFor: 'truncation and round off' stamp: 'ssa 8/25/2009 14:07'! floor "Answer a new Point that is the receiver's x and y floor." ^x floor @ y floor! ! !Point methodsFor: 'Ly' stamp: 'dmu 1/25/2010 14:02'! minus: arg "Answer a Point that is the difference of the receiver and arg." arg isPoint ifTrue: [^ (x - arg x) @ (y - arg y)]. ^ arg adaptToPoint: self andSend: #-! ! !Point methodsFor: 'Ly' stamp: 'dmu 3/16/2010 23:16'! perturb: n | r | r _ Random new. ^ self + ( r next @r next * n - (n / 2.0) )! ! !PointerExplorer methodsFor: 'accessing' stamp: 'ab 8/22/2003 18:51'! getList ^Array with: (PointerExplorerWrapper with: rootObject name: rootObject identityHash asString model: self) ! ! !PointerExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 16:23'! contents | objects | objects := Utilities pointersTo: item except: (Array with: self with: model). ^(objects reject: [:ea | ea class = self class]) collect: [:ea| self class with: ea name: ea identityHash asString model: item parent: self]! ! !PointerExplorerWrapper methodsFor: 'testing' stamp: 'ab 8/22/2003 18:39'! hasContents ^true! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'ssa 3/9/2010 16:29'! menu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane" ^SelectionMenu labels: 'inpsect search again' lines: #() selections: #(inspectObject searchAgain).! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'ssa 3/9/2010 16:37'! open | topView listView | topView := StandardSystemView new label: 'Pointer FInder'; model: self; yourself. topView addSubView:(listView := PluggableListView on: self list: #pointerList selected: #pointerListIndex changeSelected: #pointerListIndex: menu: #menu:shifted: keystroke: #arrowKey:from:) in:(0@0 extent: 1@1) borderWidth:1. listView backgroundColor: Color lightMagenta. topView controller open! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 9/24/2004 20:49'! pointersTo: anObject "Find all occurrences in the system of pointers to the argument anObject." "(PointerFinder pointersTo: Browser) inspect." ^ self pointersTo: anObject except: #() ! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 11/20/2005 21:28'! pointersTo: anObject except: objectsToExclude "Find all occurrences in the system of pointers to the argument anObject. Remove objects in the exclusion list from the results." | results anObj | Smalltalk garbageCollect. "big collection shouldn't grow, so it's contents array is always the same" results := OrderedCollection new: 1000. "allObjectsDo: is expanded inline to keep spurious method and block contexts out of the results" anObj := self someObject. [0 == anObj] whileFalse: [ anObj isInMemory ifTrue: [ (anObj pointsTo: anObject) ifTrue: [ "exclude the results collector and contexts in call chain" ((anObj ~~ results collector) and: [(anObj ~~ objectsToExclude) and: [(anObj ~~ thisContext) and: [(anObj ~~ thisContext sender) and: [anObj ~~ thisContext sender sender]]]]) ifTrue: [ results add: anObj ]. ]]. anObj := anObj nextObject. ]. objectsToExclude do: [ :obj | results removeAllSuchThat: [ :el | el == obj]]. ^ results asArray ! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 9/24/2004 20:48'! pointersToItem: index of: anArray "Find all occurrences in the system of pointers to the given element of the given array. This is useful for tracing up a pointer chain from an inspector on the results of a previous call of pointersTo:. To find out who points to the second element of the results, one would evaluate: PointerFinder pointersToItem: 2 of: self in the inspector." ^ self pointersTo: (anArray at: index) except: (Array with: anArray)! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ssa 4/19/2010 20:04'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: Sensor cursorPoint! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ssa 4/19/2010 20:12'! startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean "Display the menu, with caption if supplied. Wait for the mouse button to go down, then track the selection as long as the button is pressed. When the button is released, Answer the index of the current selection, or zero if the mouse is not released over any menu item. Location specifies the desired topLeft of the menu body rectangle. The final argument indicates whether the menu should seize the keyboard focus in order to allow the user to navigate it via the keyboard." | maxHeight | "self terminateRedundantUIProcessIfAny." maxHeight _ Display height*3//4. self frameHeight > maxHeight ifTrue: [^ self startUpSegmented: maxHeight withCaption: captionOrNil at: location allowKeyboard: aBoolean]. frame ifNil: [self computeForm]. Cursor normal showWhile: [self displayAt: location withCaption: captionOrNil during: [self controlActivity]]. ^ selection! ! !PopUpMenu methodsFor: 'RVM' stamp: 'ssa 3/1/2010 13:43'! lastStartupTime ^ LastStartupTime ifNil: [LastStartupTime _ 0] ifNotNil: [LastStartupTime] ! ! !PopUpMenu methodsFor: 'RVM' stamp: 'ssa 3/1/2010 13:43'! lastStartupTime: t LastStartupTime _ t ! ! !PopUpMenu methodsFor: 'RVM' stamp: 'dmu 3/11/2010 20:43'! terminateRedundantUIProcessIfAny "kill a redundant UI process if there is one; judge by pop-up time" "[self halt] fork" |now delta | now _ Time millisecondClockValue. delta _ now - self lastStartupTime. (delta <= (RVMTester isRVM ifTrue:[100]ifFalse:[^10]) and: [delta > 0]) ifTrue: [" self lastStartupProcess" Transcript resetSemaphore show: 'terminateRedundantUIProcessIfAny zap!!'; cr. Processor thisProcess terminate ]. self lastStartupTime: now! ! !CustomMenu methodsFor: 'invocation' stamp: 'ssa 12/17/2009 10:10'! invokeOn: targetObject orSendTo: anObject "Pop up this menu and return the result of sending to the target object the selector corresponding to the menu item selected by the user. Return nil if no item is selected. If the chosen selector has arguments, obtain appropriately. If the recipient does not respond to the resulting message, send it to the alternate object provided" | aSelector anIndex recipient | ^ (aSelector _ self startUp) ifNotNil: [anIndex _ self selection. recipient _ (self targets isEmpty or: [anIndex > self targets size]) ifTrue: [targetObject] ifFalse: [self targets at: anIndex]. aSelector numArgs == 0 ifTrue: [recipient perform: aSelector orSendTo: anObject] ifFalse: [recipient perform: aSelector withArguments: (self arguments at: 1)]]! ! !CustomMenu methodsFor: 'invocation' stamp: 'ssa 1/1/1970 00:42'! startUp: initialSelection withCaption: caption at: aPoint "Build and invoke this menu with the given initial selection and caption. Answer the selection associated with the menu item chosen by the user or nil if none is chosen." self build. (initialSelection notNil) ifTrue: [self preSelect: initialSelection]. ^ super startUpWithCaption: caption at: aPoint! ! !PositionableStream methodsFor: 'printing' stamp: 'ssa 8/19/2009 20:08'! printOn: aStream aStream nextPutAll:'@',self position printString,' in '. ^super printOn: aStream! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 20:42'! fillBuffer | byte | [bitsInBuffer <= 16] whileTrue:[ byte _ self next. (byte = 16rFF and: [(self peekFor: 16r00) not]) ifTrue: [self position: self position - 1. ^0]. bitBuffer _ (bitBuffer bitShift: 8) bitOr: byte. bitsInBuffer _ bitsInBuffer + 8]. ^ bitsInBuffer! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 18:43'! getBits: requestedBits | value | requestedBits > bitsInBuffer ifTrue:[ self fillBuffer. requestedBits > bitsInBuffer ifTrue:[ self error: 'not enough bits available to decode']]. value _ bitBuffer bitShift: (requestedBits - bitsInBuffer). bitBuffer _ bitBuffer bitAnd: (1 bitShift: (bitsInBuffer - requestedBits)) -1. bitsInBuffer _ bitsInBuffer - requestedBits. ^ value! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/6/2001 12:34'! nextByte ^self next asInteger! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/6/2001 12:35'! nextBytes: n ^(self next: n) asByteArray! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 17:40'! reset super reset. self resetBitBuffer! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 18:44'! resetBitBuffer bitBuffer _ 0. bitsInBuffer _ 0. ! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 21:06'! buildLookupTable: values counts: counts | min max | min _ max _ nil. 1 to: counts size do:[:i| (counts at: i) = 0 ifFalse:[ min ifNil:[min _ i-1]. max _ i]]. ^self createHuffmanTables: values counts: {0},counts from: min+1 to: max.! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:46'! createHuffmanTables: values counts: counts from: minBits to: maxBits "Create the actual tables" | table tableStart tableSize tableEnd valueIndex tableStack numValues deltaBits maxEntries lastTable lastTableStart tableIndex lastTableIndex | table _ WordArray new: ((4 bitShift: minBits) max: 16). "Create the first entry - this is a dummy. It gives us information about how many bits to fetch initially." table at: 1 put: (minBits bitShift: 24) + 2. "First actual table starts at index 2" "Create the first table from scratch." tableStart _ 2. "See above" tableSize _ 1 bitShift: minBits. tableEnd _ tableStart + tableSize. "Store the terminal symbols" valueIndex _ (counts at: minBits+1). tableIndex _ 0. 1 to: valueIndex do:[:i| table at: tableStart + tableIndex put: (values at: i). tableIndex _ tableIndex + 1]. "Fill up remaining entries with invalid entries" tableStack _ OrderedCollection new: 10. "Should be more than enough" tableStack addLast: (Array with: minBits "Number of bits (e.g., depth) for this table" with: tableStart "Start of table" with: tableIndex "Next index in table" with: minBits "Number of delta bits encoded in table" with: tableSize - valueIndex "Entries remaining in table"). "Go to next value index" valueIndex _ valueIndex + 1. "Walk over remaining bit lengths and create new subtables" minBits+1 to: maxBits do:[:bits| numValues _ counts at: bits+1. [numValues > 0] whileTrue:["Create a new subtable" lastTable _ tableStack last. lastTableStart _ lastTable at: 2. lastTableIndex _ lastTable at: 3. deltaBits _ bits - (lastTable at: 1). "Make up a table of deltaBits size" tableSize _ 1 bitShift: deltaBits. tableStart _ tableEnd. tableEnd _ tableEnd + tableSize. [tableEnd > table size ] whileTrue:[table _ self growHuffmanTable: table]. "Connect to last table" self assert:[(table at: lastTableStart + lastTableIndex) = 0]."Entry must be unused" table at: lastTableStart + lastTableIndex put: (deltaBits bitShift: 24) + tableStart. lastTable at: 3 put: lastTableIndex+1. lastTable at: 5 put: (lastTable at: 5) - 1. self assert:[(lastTable at: 5) >= 0]. "Don't exceed tableSize" "Store terminal values" maxEntries _ numValues min: tableSize. tableIndex _ 0. 1 to: maxEntries do:[:i| table at: tableStart + tableIndex put: (values at: valueIndex). valueIndex _ valueIndex + 1. numValues _ numValues - 1. tableIndex _ tableIndex+1]. "Check if we have filled up the current table completely" maxEntries = tableSize ifTrue:[ "Table has been filled. Back up to the last table with space left." [tableStack isEmpty not and:[(tableStack last at: 5) = 0]] whileTrue:[tableStack removeLast]. ] ifFalse:[ "Table not yet filled. Put it back on the stack." tableStack addLast: (Array with: bits "Nr. of bits in this table" with: tableStart "Start of table" with: tableIndex "Index in table" with: deltaBits "delta bits of table" with: tableSize - maxEntries "Unused entries in table"). ]. ]. ]. ^table copyFrom: 1 to: tableEnd-1! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:44'! decodeValueFrom: table "Decode the next value in the receiver using the given huffman table." | bits bitsNeeded tableIndex value | bitsNeeded _ (table at: 1) bitShift: -24. "Initial bits needed" tableIndex _ 2. "First real table" [bits _ self getBits: bitsNeeded. "Get bits" value _ table at: (tableIndex + bits). "Lookup entry in table" (value bitAnd: 16r3F000000) = 0] "Check if it is a non-leaf node" whileFalse:["Fetch sub table" tableIndex _ value bitAnd: 16rFFFF. "Table offset in low 16 bit" bitsNeeded _ (value bitShift: -24) bitAnd: 255. "Additional bits in high 8 bit" bitsNeeded > MaxBits ifTrue:[^self error:'Invalid huffman table entry']]. ^value! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:21'! growHuffmanTable: table | newTable | newTable _ table species new: table size * 2. newTable replaceFrom: 1 to: table size with: table startingAt: 1. ^newTable! ! !JPEGReadStream class methodsFor: 'class initialization' stamp: 'ar 3/4/2001 18:32'! initialize "JPEGReadStream initialize" MaxBits _ 16.! ! !Preferences class methodsFor: 'get/set' stamp: 'ssa 3/24/2010 15:18'! enable: aSymbol "Shorthand access to enabling a preference of the given name. If there is none in the image, conjure one up" | aPreference | aPreference _ self preferenceAt: aSymbol ifAbsent: [self addPreference: aSymbol category: 'unclassified' default: false balloonHelp: 'this preference was added idiosyncratically and has no help message.'. self preferenceAt: aSymbol]. aPreference preferenceValue: true! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/24/2010 14:44'! addChild: aProcess self children add: aProcess. aProcess parent: self.! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/24/2010 14:42'! children "Answer the value of children" children isNil ifTrue:[self children: WeakSet new]. ^ children! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/24/2010 14:38'! children: anObject "Set the value of children" children _ anObject! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 10:30'! descendantsDo: blk self children do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/26/2010 12:26'! myGeneration ^ self parent ifNil: [{self}] ifNotNil: [self parent children]! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 10:34'! myGenerationAndTheirDescendantsDo: blk self myGeneration do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/24/2010 14:38'! parent "Answer the value of parent" parent isNil ifTrue:[self parent: nil]. ^ parent! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/24/2010 14:38'! parent: anObject "Set the value of parent" parent _ anObject! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 10:34'! siblings ^ self myGeneration copyWithout: self! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 10:32'! siblingsAndTheirDescendantsDo: blk self siblings do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: 'Ly' stamp: 'dmu 3/9/2010 14:59'! stopIfDebugging: whatIAmAboutToDo | | self lyDebuggingBlock ifNil: [^ self]. self lyDebuggingBlock value: whatIAmAboutToDo! ! !Process methodsFor: 'RVM' stamp: 'dmu 5/9/2009 23:08'! isRunning Processor thisProcess == self ifTrue: [^ true]. self isActiveProcess ifTrue: [^ true]. myList ifNil: [^ false]. ^ myList class ~~ Semaphore! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! nilMyListUnlessRVM Processor areRunningProcessesInSchedulerLists ifFalse: [ "primitiveSuspend will use myList to remove from list and will nil it out" myList := nil. ]! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask ^ coreMask! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:40'! coreMask: m coreMask := m! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:56'! creatorEnsemble "Answer the value of creatorEnsemble" creatorEnsemble isNil ifTrue:[self creatorEnsemble: nil]. ^ creatorEnsemble! ! !Process methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:56'! creatorEnsemble: anObject "Set the value of creatorEnsemble" creatorEnsemble _ anObject! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! errorHandler "Answer the value of errorHandler" errorHandler isNil ifTrue:[self errorHandler: nil]. ^ errorHandler! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! errorHandler: anObject "Set the value of errorHandler" errorHandler _ anObject! ! !Process methodsFor: 'RVM' stamp: 'dmu 6/14/2010 15:41'! hostCore ^ hostCore! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! hostCore: anObject "Set the value of hostCore" hostCore := anObject! ! !Process methodsFor: 'accessing' stamp: 'ssa 2/17/2009 22:34'! isActiveProcess ^ suspendedContext isNil and:[myList notNil]! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList "Answer the value of myList" myList isNil ifTrue:[self myList: nil]. ^ myList! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList: anObject "Set the value of myList" myList _ anObject! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/2/2010 17:02'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." "Debugging code below causes terminated running processes to seem not terminated. -- dmu 3/2/10" "(myList isNil and: [RVMTester isRVM]) ifTrue:[self halt]." self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:44'! resume "Allow the process that the receiver represents to continue. Put the receiver in line to become the activeProcess. Check for a nil suspendedContext, which indicates a previously terminated Process that would cause a vm crash if the resume attempt were permitted" self children do: [:c| c resume]. suspendedContext ifNil: [^ self primitiveFailed]. ^ self primitiveResume! ! !Process methodsFor: 'changing process state' stamp: 'dmu 4/7/2009 02:41'! resumeOn: aCore self useOnlyCore: aCore. self resume! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:44'! suspend "Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes." self children do: [:c| c suspend]. self isActiveProcess ifTrue: [ self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ myList ifNotNil: [ myList remove: self ifAbsent: []. myList _ nil]. ]! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:45'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock | self children do: [:c| c terminate]. self == Processor thisProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ unwindBlock := ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ self suspend. myList ifNotNil: [ myList remove: self ifAbsent: []. myList := nil]. suspendedContext ifNotNil: [ ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" self suspend. ^ suspendedContext := suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:01'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | self suspend. ctxt := suspendedContext. suspendedContext := nil. "disable this process while running its stack in active process below" pair := ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext := pair first. error := pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 11/25/2008 00:21'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | (Processor isActive: self) ifTrue: [^ self error: 'An active process cannot pop contexts']. callee := (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." self suspend. suspendedContext == aContext ifTrue: [ ^ suspendedContext _ aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:03'! step self suspend. ^ suspendedContext _ suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! stepToCallee "Step until top context changes" | ctxt | self suspend. ctxt _ suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext _ suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! stepToSendOrReturn self suspend. ^ suspendedContext _ suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:57'! avoidCore: anIndex "Force this process to avoid this core (0-55)" self coreMask: (self coreMask bitClear: (1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:49'! avoidCores: aCollectionOfIndicies "Force this process to avoid these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitClear:mask)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 02:59'! useAdditionalCore: anIndex "Force this process to only urn on this core (0-55)" self coreMask: (self coreMask bitOr:(1 bitShift: anIndex))! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:50'! useAdditionalCores: aCollectionOfIndicies "Allow this process to run on these additional cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitOr:mask)! ! !Process methodsFor: 'core assignment' stamp: 'dmu 5/5/2009 01:32'! useOnlyCore: anIndex "Force this process to only run on this core (0-55)" self coreMask: (1 bitShift: anIndex)! ! !Process methodsFor: 'core assignment' stamp: 'ssa 2/26/2009 03:02'! useOnlyCores: aCollectionOfIndicies "Force this process to only run on these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: mask! ! !Process methodsFor: 'core assignment' stamp: 'dmu 1/25/2010 11:06'! useOnlyMainCore RVMTester isRVM ifTrue: [self useOnlyCore: (RVMMonitor getSample; mainRank)]! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt := self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. Transcript cr; show: 'Suspending siblings & progeny'. self class semaForSupensions critical:[ self siblings size print. self siblingsAndTheirDescendantsDo: [:proc| proc == Processor thisProcess ifFalse: [Transcript cr;show:'suspending proc ',proc identityHash printString. proc suspend]]. ]. Transcript cr; show: 'launching debugger'. Debugger openOn: self context: context label: title contents: nil fullView: bool. ! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debugWithTitle: title "Open debugger on self" | context | context _ self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. self debug: context title: title full: true. ! ! !Process methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:21'! longPrintOn: stream | ctxt | stream nextPutAll: (RVMTester printPrefixFor: self). super printOn: stream. stream cr. ctxt _ self suspendedContext. [ctxt == nil] whileFalse: [ stream space. ctxt printOn: stream. stream cr. ctxt _ ctxt sender. ]. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:31'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self == Processor thisProcess ifFalse: [^self]. self suspend. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:30'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. self suspend. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! !Process class methodsFor: 'instance creation' stamp: 'dmu 3/24/2010 15:46'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess _ self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. [newProcess coreMask:(1 bitShift: 27)]. ^newProcess! ! !Process class methodsFor: 'instance creation' stamp: 'ssa 2/26/2009 02:45'! forContext: aContext priority: anInteger coreMask: anIntegerMask "Answer an instance of me that has suspended aContext at priority anInteger using this coreMask." | newProcess | newProcess _ self forContext: aContext priority: anInteger. newProcess coreMask:anIntegerMask. ^newProcess! ! !Process class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 15:11'! semaForSupensions SemaForSupensions isNil ifTrue:[SemaForSupensions _ Semaphore forMutualExclusion]. ^SemaForSupensions! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'dmu 11/25/2008 00:22'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight := stackList at: stackListIndex]. (Processor isActive: selectedProcess) ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext := selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'ssa 6/11/2010 14:35'! nameAndRulesFor: aProcess "Answer a nickname and two flags: allow-stop, and allow-debug" ^ [aProcess caseOf: { [ProcessorScheduler emergencyProcess] -> [{'emergency evaluator ShftCtrl-A'. false. true}]. [] -> [{'no process'. false. false}]. [Smalltalk lowSpaceWatcherProcess] -> [{'the low space watcher'. false. false}]. [WeakArray runningFinalizationProcess] -> [{'the WeakArray finalization process'. false. false}]. [Processor thisProcess] -> [{'the UI process'. false. true}]. [Processor backgroundProcess] -> [{'the idle process'. false. false}]. [Sensor interruptWatcherProcess] -> [{'the user interrupt watcher'. false. false}]. [Sensor eventTicklerProcess] -> [{'the event tickler'. false. false}]. [Project uiProcess] -> [{'the inactive Morphic UI process'. false. false}]. [Smalltalk at: #SoundPlayer ifPresent: [:sp | sp playerProcess]] -> [{'the Sound Player'. false. false}]. [ScheduledControllers ifNotNil: [ScheduledControllers activeControllerProcess]] -> [{'the inactive MVC controller process'. false. true}]. [Smalltalk at: #CPUWatcher ifPresent: [:cw | cw currentWatcherProcess]] -> [{'the CPUWatcher'. false. false}]} otherwise: [(aProcess priority = Processor timingPriority and: [aProcess suspendedContext receiver == Delay]) ifTrue: [{'the timer interrupt watcher'. false. false}] ifFalse: [{aProcess suspendedContext asString. true. true}]]] ifError: [:err :rcvr | {aProcess suspendedContext asString. true. true}]! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 11/25/2008 00:23'! activePriority "Answer the priority level of the currently running Process." ^self thisProcess priority! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:37'! removeAllPossible "Terminate and remove all processes that you can. This should leave the standard set only" self terminatableProcesses print do:[:proc| proc terminate]! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:31'! terminatableProcesses "Answer all current processes that may be user terminated like in the ProcessBrowser" "self terminatableProcesses" | processList | Smalltalk garbageCollectMost. "lose defunct processes" processList _ Process allSubInstances reject: [:each | each isTerminated]. processList _ processList sortBy: [:a :b | a priority >= b priority]. processList _ WeakArray withAll: processList. ^processList select:[:proc| (ProcessBrowser nameAndRulesFor: proc) at: 2]! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'dmu 11/25/2008 00:23'! terminateActive "Terminate the process that is currently running." self thisProcess terminate! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 4/10/2009 22:48'! areRunningProcessesInSchedulerLists "Our RVM follows Pallas' MS system and keeps runnable processes in the scheduler lists even when running." ^RVMTester isRVM! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 11/25/2008 00:26'! isActive: aProcess ^ aProcess suspendedContext == nil! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 12/7/2008 20:43'! thisProcess "must not specify module in order to hit obsolete_named_primitive_table and thus be local" ^ self activeProcess! ! !ProcessorScheduler methodsFor: 'RVM' stamp: 'dmu 3/22/2010 13:03'! yieldIfFewerCoresThan: n RVMTester coreCount < n ifTrue: [self yield]! ! !ProcessorScheduler class methodsFor: '*RVM' stamp: 'ssa 6/11/2010 14:34'! emergencyProcess ^ EmergencyProcess! ! !ProcessorScheduler class methodsFor: '*RVM' stamp: 'dmu 6/2/2010 23:17'! startEmergencyProcess "Bring up an emergency evaluator if the user hits control-shift-a" "self startEmergencyProcess" "self startEmergencyProcess. RVMTester getEmergencySemaphore signal" | sema | sema _ Semaphore new. RVMTester setEmergencySemaphore: sema. EmergencyProcess ifNotNil: [EmergencyProcess terminate]. ^ EmergencyProcess _ [[sema wait. Transcripter emergencyEvaluator] repeat] forkAt: Processor userInterruptPriority! ! !ProcessorScheduler class methodsFor: 'background process' stamp: 'dmu 6/2/2010 23:20'! startUp "Install a background process of the lowest possible priority that is always runnable." "Details: The virtual machine requires that there is aways some runnable process that can be scheduled; this background process ensures that this is the case." Smalltalk installLowSpaceWatcher. BackgroundProcess == nil ifFalse: [BackgroundProcess terminate]. BackgroundProcess _ [self idleProcess] newProcess. [BackgroundProcess useOnlyCore: (RVMMonitor getSample; mainRank).]. BackgroundProcess priority: SystemRockBottomPriority. BackgroundProcess resume. self startEmergencyProcess ! ! !Project methodsFor: 'initialization' stamp: 'ssa 1/22/2010 14:06'! backgroundColorForMvcProject ^ Color r: 1.0 g: 1.0 b: 0.65! ! !Project methodsFor: 'menu messages' stamp: 'dmu 11/25/2008 00:23'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject _ self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World _ world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World _ nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess _ Processor thisProcess. ! ! !Project class methodsFor: 'utilities' stamp: 'dmu 11/25/2008 00:24'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor thisProcess suspend]! ! !RVMSBinarySampleWriter class methodsFor: 'sample writing' stamp: 'ssa 10/26/2008 23:48'! writeSample: aSample on: aStream "RVMSBinarySampleWriter writeSample: RVMMonitor lastSample on: (FileStream newFileNamed:'binary-sample-writer.test')" "Write the minimum data in aSample to aStream in binary format" | data subData innerCoreStats allSendTallies tallies rcvTallies memoryStats readWriteHeap readMostlyHeap interpStats objTableStats | data _ aSample rawData. aStream binary; nextNumber: 8 put: (data at: 2); "runMask" nextPut: ((data at: 4)) ; "extraYields" nextPut: ((data at: 6)). "extraRemoteContextAllocations" "remember messageNames" subData _ data at: 10. "groupStats" aStream nextPut: ((subData at: 2)); "mainX" nextPut: ((subData at: 4)); "mainY" nextPut: ((subData at: 6)); "mainRank" nextPut: ((subData at: 8)); "width" nextPut: ((subData at: 10)); "height" nextPut: ((subData at: 12)); "groupSize" nextPut: ((subData at: 14)). "remaining" subData _ data at: 12. "allCPUCoreStats" subData do:[:each| aStream nextInt32Put: (each at: 2); "millisecs" nextInt32Put: (each at: 4). "cycles" innerCoreStats _ each at: 6. aStream nextPut: ((innerCoreStats at: 2)); "x" nextPut: ((innerCoreStats at: 4)); "y" nextPut: ((innerCoreStats at: 6)). "rank" allSendTallies _ innerCoreStats at: 8. "sendTalliesByCore" allSendTallies do:[:sndTally| tallies _ allSendTallies at: 2. tallies do:[:tally| aStream nextWordPut: tally]. "a single send tally" ]. rcvTallies _ innerCoreStats at: 10. rcvTallies do:[:tally| aStream nextWordPut: tally]. "a single recieve tally" memoryStats _ each at: 8. "memorySystemStats" aStream nextWordPut: (memoryStats at: 2); "gcCount" nextInt32Put: (memoryStats at: 4); "gcMilliseconds" nextInt32Put: (memoryStats at: 6). "gcCycles" readWriteHeap _ memoryStats at: 8. "readWriteHeapStats" aStream nextInt32Put: (readWriteHeap at: 2); "bytesUsed()" nextInt32Put: (readWriteHeap at: 4); "bytesLeft()" nextInt32Put: (readWriteHeap at: 6); "allocationsSinceLastQuery" nextInt32Put: (readWriteHeap at: 8). "compactionsSinceLastQuery" readMostlyHeap _ memoryStats at: 10. "readMostlyHeapStats" aStream nextInt32Put: (readMostlyHeap at: 2); "bytesUsed()" nextInt32Put: (readMostlyHeap at: 4); "bytesLeft()" nextInt32Put: (readMostlyHeap at: 6); "allocationsSinceLastQuery" nextInt32Put: (readMostlyHeap at: 8). "compactionsSinceLastQuery" interpStats _ each at: 10. "interpreterStats" aStream nextInt32Put: (interpStats at: 2); "bytecodesExecuted" nextInt32Put: (interpStats at: 4); "yieldCount" nextNumber: 6 put: (interpStats at: 6); "cyclesRunning" nextNumber: 6 put: (interpStats at: 8); "cyclesWaiting" nextInt32Put: (interpStats at: 10); "contextChangeCount" nextInt32Put: (interpStats at: 12); "interruptCheckCount" nextInt32Put: (interpStats at: 14); "unforcedInterruptCheckCount" nextInt32Put: (interpStats at: 16); "numberOfMovedMutatedReadMostlyObjects" nextNumber: 6 put: (interpStats at: 18). "cyclesMovingMutatedReadMostlyObjects" ]. objTableStats _ data at: 14. "objectTableStats" aStream nextInt32Put: (objTableStats at: 2); "allocatedEntryCount" nextInt32Put: (objTableStats at: 4); "entryCount" nextInt32Put: (objTableStats at: 6); "allocationsSinceLastQuery" nextInt32Put: (objTableStats at: 8). "entriesFreedSinceLastQuery" aStream nextPut: ((data at: 16)); "extraRunPrimitives" nextPut: ((data at: 18)); "extraDoublewordBroadcasts" nextPut: ((data at: 20)); "extraWordBroadcasts" nextPut: (((data at: 22) ifTrue:[1]ifFalse:[0])); "dontPassTheBatonDefault" nextPut: (((data at: 24) ifTrue:[1]ifFalse:[0])). "fence" ! ! !RVMSampleReader methodsFor: 'common entries' stamp: 'ssa 11/16/2008 15:12'! messageNames "Normally at index 8 in sample raw data array" ^#('noMessage' 'allocateOrRecycleContextMessage' 'allocateOrRecycleContextJustTestingMessage' 'recycleContextIfPossibleMessage' 'flushInterpreterCachesMessage' 'flushMethodCacheMessage' 'flushByMethodMessage' 'flushSelectiveMessage' 'addObjectFromSnapshotMessage' 'addObjectFromSnapshotResponse' 'updateWholeInterpreterMessage' 'updateEnoughInterpreterToTransferControlMessage' 'updateEnoughInterpreterToTransferControlJustTestingMessage' 'updateEnoughInterpreterToTransferControlJustTestingResponse' 'zapUnusedPortionOfHeapMessage' 'zapUnusedPortionOfHeapResponse' 'verifyInterpreterAndHeapMessage' 'doAllRootsThereMessage' 'doAllRootsThereResponse' 'doAllRootsHereMessage' 'hereIsARootResponse' 'newValueForOopMessage' 'noMoreRootsResponse' 'scanCompactOrMakeFreeObjectsMessage' 'scanCompactOrMakeFreeObjectsResponse' 'returnContextMessage' 'runPrimitiveMessage' 'runPrimitiveJustTestingMessage' 'runPrimitiveResponse' 'loadFunctionFromPluginMessage' 'loadFunctionFromPluginResponse' 'broadcastInterpreterDoublewordMessage' 'broadcastInterpreterWordMessage' 'broadcastInterpreterBoolMessage' 'sampleOneCoreMessage' 'sampleOneCoreResponse' 'initiateBarrierMessage' 'respondToBarrierMessage' 'aboutToWriteRead_MostlyMemoryMessage' 'aboutToWriteRead_MostlyMemoryResponse' 'wroteRead_MostlyMemoryMessage' 'flushFreeContextsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse' 'preGCActionMessage' 'preGCActionResponse' 'postGCActionMessage' 'postGCActionResponse' 'startAnotherProcessMessage' 'startAnotherProcessResponse' 'initContextMessage' 'initContextResponse' 'requestSafepointMessage' 'requestSafepointResponse' 'relinquishSafepointMessage' 'relinquishSafepointResponse')! ! !RVMSampleReader methodsFor: 'common entries' stamp: 'ssa 11/16/2008 15:12'! version1messageNames "Normally at index 8 in sample raw data array" ^#('allocateOrRecycleContextMessage' 'allocateOrRecycleContextJustTestingMessage' 'recycleContextIfPossibleMessage' 'flushInterpreterCachesMessage' 'flushMethodCacheMessage' 'flushByMethodMessage' 'flushSelectiveMessage' 'addObjectFromSnapshotMessage' 'addObjectFromSnapshotResponse' 'updateWholeInterpreterMessage' 'updateEnoughInterpreterToTransferControlMessage' 'updateEnoughInterpreterToTransferControlJustTestingMessage' 'updateEnoughInterpreterToTransferControlJustTestingResponse' 'zapUnusedPortionOfHeapMessage' 'zapUnusedPortionOfHeapResponse' 'verifyInterpreterAndHeapMessage' 'doAllRootsThereMessage' 'doAllRootsThereResponse' 'doAllRootsHereMessage' 'hereIsARootResponse' 'newValueForOopMessage' 'noMoreRootsResponse' 'scanCompactOrMakeFreeObjectsMessage' 'scanCompactOrMakeFreeObjectsResponse' 'returnContextMessage' 'runPrimitiveMessage' 'runPrimitiveJustTestingMessage' 'runPrimitiveResponse' 'loadFunctionFromPluginMessage' 'loadFunctionFromPluginResponse' 'broadcastInterpreterDoublewordMessage' 'broadcastInterpreterWordMessage' 'broadcastInterpreterBoolMessage' 'sampleOneCoreMessage' 'sampleOneCoreResponse' 'initiateBarrierMessage' 'respondToBarrierMessage' 'aboutToWriteReadMostlyMemoryMessage' 'aboutToWriteReadMostlyMemoryResponse' 'wroteReadMostlyMemoryMessage' 'flushFreeContextsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse')! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 16:03'! nextAllCPUCoreStats | rawData | rawData _ OrderedCollection new. 56 timesRepeat:[rawData add: self nextCoreStats]. ^rawData asArray! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:31'! nextCoreStats | rawData | rawData _ Array new: 12. rawData at:1 put: 'millisecs'. rawData at:2 put: self next. rawData at:3 put: 'cycles'. rawData at:4 put: self next. rawData at:5 put: 'coreStats'. rawData at:6 put: self nextInnerCoreStats. rawData at:7 put: 'memorySystemStats'. rawData at:8 put: self nextMemorySystemStats. rawData at:9 put: 'interpreterStats'. rawData at:10 put: self nextInterpreterStats. rawData at:11put: 'objectTableStats'. rawData at:12 put: self nextObjectTableStats. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 16:00'! nextGroupStats | rawData | rawData _ Array new: 14. rawData at:1 put: 'mainX'. rawData at:2 put: self next. rawData at:3 put: 'mainY'. rawData at:4 put: self next. rawData at:5 put: 'mainRank'. rawData at:6 put: self next. rawData at:7 put: 'width'. rawData at:8 put: self next. rawData at:9 put: 'height'. rawData at:10 put: self next. rawData at:11 put: 'groupSize'. rawData at:12 put: self next. rawData at:13 put: 'remaining'. rawData at:14 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 19:52'! nextInnerCoreStats | rawData | rawData _ Array new: 11. rawData at:1 put: 'x'. rawData at:2 put: self next. rawData at:3 put: 'y'. rawData at:4 put: self next. rawData at:5 put: 'rank'. rawData at:6 put: self next. rawData at:7 put: 'sendTalliesByCore'. rawData at:8 put: self nextSendTalliesByCore. rawData at:9 put: 'receiveTallies'. rawData at:10 put: self nextReceiveTallies. rawData at:11 put: #(). ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:24'! nextInterpreterStats | rawData | rawData _ Array new: 18. rawData at:1 put: 'bytecodesExecuted'. rawData at:2 put: self next. rawData at:3 put: 'yieldCount'. rawData at:4 put: self next. rawData at:5 put: 'cyclesRunning'. rawData at:6 put: self next. rawData at:7 put: 'cyclesWaiting'. rawData at:8 put: self next. rawData at:9 put: 'contextChangeCount'. rawData at:10 put: self next. rawData at:11 put: 'interruptCheckCount'. rawData at:12 put: self next. rawData at:13 put: 'unforcedInterruptCheckCount'. rawData at:14 put: self next. rawData at:15 put: 'numberOfMovedMutatedRead_MostlyObjects'. rawData at:16 put: self next. rawData at:17 put: 'cyclesMovingMutatedRead_MostlyObjects'. rawData at:18 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 20:10'! nextMemorySystemStats | rawData heap | rawData _ Array new: 10. rawData at:1 put: 'gcCount'. rawData at:2 put: self next. rawData at:3 put: 'gcMilliseconds'. rawData at:4 put: self next. rawData at:5 put: 'gcCycles'. rawData at:6 put: self next. rawData at:7 put: 'readWriteHeapStats'. heap _ Array new:8. heap at: 1 put:'bytesUsed()'. heap at: 2 put:self next. heap at: 3 put:'bytesLeft()'. heap at: 4 put:self next. heap at: 5 put:'allocationsSinceLastQuery'. heap at: 6 put:self next. heap at: 7 put:'compactionsSinceLastQuery'. heap at: 8 put: self next. rawData at:8 put: heap. rawData at:9 put: 'readMostlyHeapStats'. heap _ Array new:8. heap at: 1 put:'bytesUsed()'. heap at: 2 put:self next. heap at: 3 put:'bytesLeft()'. heap at: 4 put:self next. heap at: 5 put:'allocationsSinceLastQuery'. heap at: 6 put:self next. heap at: 7 put:'compactionsSinceLastQuery'. heap at: 8 put: self next. rawData at:10 put: heap. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:25'! nextObjectTableStats | rawData | rawData _ Array new: 8. rawData at:1 put: 'allocatedEntryCount[rank]'. rawData at:2 put: self next. rawData at:3 put: 'entryCount[rank]'. rawData at:4 put: self next. rawData at:5 put: 'allocationsSinceLastQuery[rank]'. rawData at:6 put: self next. rawData at:7 put: 'entriesFreedSinceLastQuery[rank]'. rawData at:8 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 20:00'! nextReceiveTallies ^ self next asArray! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:15'! nextSample | rawData | rawData _ Array new: 22. rawData at:1 put: 'runMask'. rawData at:2 put: self next. rawData at:3 put: 'extraYields'. rawData at:4 put: self next. rawData at:5 put: 'extraRemoteContextAllocations'. rawData at:6 put: self next. rawData at:7 put: 'messageNames'. rawData at:8 put: self messageNames. self next. "consume #messageNames" rawData at:9 put: 'groupStats'. rawData at:10 put: self nextGroupStats. rawData at:11 put: 'allCPUCoreStats'. rawData at:12 put: self nextAllCPUCoreStats. rawData at:13 put: 'extraRunPrimitives'. rawData at:14 put: self next. rawData at:15 put: 'extraDoublewordBroadcasts'. rawData at:16 put: self next. rawData at:17 put: 'extraWordBroadcasts'. rawData at:18 put: self next. rawData at:19 put: 'dontPassTheBatonDefault'. rawData at:20 put: self next. rawData at:21 put: 'fence'. rawData at:22 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 19:58'! nextSendTalliesByCore | rawData | rawData _ Array new: 112. 1 to: 111 by: 2 do:[:index| rawData at: index put: 'sendTallies'. rawData at: index + 1 put: self next asArray]. ^rawData ! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 15:51'! dearchive: aString "RVMSampleReader dearchive: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:24'! dearchiveRawData: aString "RVMSampleReader dearchiveRawData: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:27'! dearchiveRawDataFrom: aStream "| rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: rw. RVMSampleReader dearchiveRawDataFrom: rw reset " | anObject aReader | aReader _ self on: aStream. anObject _ aReader nextSample. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:27'! dearchiveSample: aString "RVMSampleReader dearchiveSample: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^RVMMulticoreSample newFrom:anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:28'! dearchiveSampleFrom: aStream "| rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: RVMMonitor lastSample on: rw. RVMSampleReader dearchiveSampleFrom: rw reset " | anObject aReader | aReader _ self on: aStream. anObject _ aReader nextSample. ^RVMMulticoreSample newFrom:anObject! ! !RVMSampleWriter methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:04'! rawData "Answer the value of rawData" ^ rawData! ! !RVMSampleWriter methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:04'! rawData: anObject "Set the value of rawData" rawData _ anObject! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:42'! archiveAllCPUCoreStats: data "Archive the rawData I have from the sample, minimizing space" | datum | data do:[:batch| 2 to: batch size by: 2 do:[:index| datum _ batch at: index. index = 6 ifTrue:[self archiveCoreStats: datum] ifFalse:[index = 8 ifTrue:[self archiveMemorySystemStats: datum] ifFalse:[(#(10 12) includes:index) ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:18'! archiveCoreStats: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self archiveSendTalliesByCore: datum] ifFalse:[index = 10 ifTrue:[self archiveRecieveTallies: datum] ifFalse:[self nextPut:datum]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:25'! archiveMemorySystemStats: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[index = 10 ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:25'! archiveNameValuePairArray: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. self nextPut: datum]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:20'! archiveRecieveTallies: data "Archive the rawData I have from the sample, minimizing space" self nextPut: data asRunArray ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:31'! archiveSampleData "Archive the rawData I have from the sample, minimizing space" | data datum | data _ self rawData. 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self nextPut: #messageNames] ifFalse:[index = 12 ifTrue:[self archiveAllCPUCoreStats: datum] ifFalse:[(index = 10) ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:19'! archiveSendTalliesByCore: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. self nextPut: datum asRunArray]. ! ! !RVMSampleWriter methodsFor: 'private' stamp: 'ssa 7/7/2010 13:13'! setStream: aWriteStream "Since I only store arrays of numbers, use plain Dictionarys" stream _ aWriteStream. classMap _ Dictionary new: 30. classMap at: self put: 1. objectMap _ Dictionary new: 400. position _ 0 ! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:23'! archive: rawData to: aString "use the other specific versions of me" self shouldNotImplement! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:26'! archiveRawData: rawData on: aStream "RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: (ReadWriteStream on:'')" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | writer | writer _ self on: aStream. writer rawData: rawData. writer archiveSampleData. ^aStream! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:22'! archiveRawData: rawData to: aString "RVMSampleWriter archiveRawData: (RVMMonitor samples first) to: 'sample-writer.test'" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | stream writer | stream _ self fastStreamOn: aString. writer _ self on: stream. writer rawData: rawData. writer archiveSampleData. writer close.! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:26'! archiveSample: aMulticoreSample on: aStream "RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: (ReadWriteStream on:'')" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | writer | writer _ self on: aStream. writer rawData: aMulticoreSample rawData. writer archiveSampleData. ^aStream! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:23'! archiveSample: aMulticoreSample to: aString "RVMSampleWriter archiveRawData: (RVMMonitor samples first) to: 'sample-writer.test'" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | stream writer | stream _ self fastStreamOn: aString. writer _ self on: stream. writer rawData: aMulticoreSample rawData. writer archiveSampleData. writer close.! ! !Rectangle methodsFor: 'accessing' stamp: ''! bottomLeft: aPoint "Set the position of the bottomLeft corner of the receiver." "KSC Extension" origin _ aPoint x @ self top. corner _ self right @ aPoint y! ! !Rectangle methodsFor: 'accessing' stamp: ''! bottomRight: bottomRightPoint "Set the position of the right corner of the bottom horizontal line of the receiver." corner _ bottomRightPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/22/2009 18:02'! corner: aPoint "Set the point at the bottom right corner of the receiver." corner _ aPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/23/2009 14:39'! extent: aPoint corner _ origin + aPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/22/2009 16:32'! height: heightInteger "Change the receiver's bottom y to make its height the argument heightInteger." corner y: origin y + heightInteger! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 9/2/2009 17:10'! origin: aPoint "Set the point at the top left corner of the receiver." origin _ aPoint! ! !Rectangle methodsFor: 'accessing' stamp: ''! topLeft: topLeftPoint "Set the point at the top left corner of the receiver's top horizontal line." origin _ topLeftPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/25/2009 14:40'! topRight: aPoint "Set the position of the top right corner of the receiver." origin _ self left @ aPoint y. corner _ aPoint x @ self bottom! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/31/2009 16:30'! width: widthInteger "Change the receiver's right x to make its width the argument widthInteger." corner x: origin x + widthInteger! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 11/16/2008 02:34'! asRandomPoint "ssa - Answer a random point that lies within my borders" ^self origin + self extent atRandom ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/24/2009 09:39'! intersect: aRectangle "Answer a Rectangle that is the area in which the receiver overlaps with aRectangle. Optimized for speed; old code read: ^Rectangle origin: (origin max: aRectangle origin) corner: (corner min: aRectangle corner) " | aPoint left right top bottom | aPoint _ aRectangle origin copy. aPoint x > origin x ifTrue:[left _ aPoint x] ifFalse:[left _ origin x]. aPoint y > origin y ifTrue:[top _ aPoint y] ifFalse:[top _ origin y]. aPoint _ aRectangle corner copy. aPoint x < corner x ifTrue:[right _ aPoint x] ifFalse:[right _ corner x]. aPoint y < corner y ifTrue:[bottom _ aPoint y] ifFalse:[bottom _ corner y]. ^Rectangle origin: (left@top) corner: (right@bottom) ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/23/2009 17:07'! selfMerge: aRectangle "Alter the receiver so that it contains both self and the argument aRectangle. This is much faster than a merge: but must be used wisely since it modifies both the receiver and the points which make up its origin and corner." "KSC Extension" | hisOrigin hisCorner hisOriginX hisOriginY hisCornerX hisCornerY | hisOrigin _ aRectangle origin. hisCorner _ aRectangle corner. hisOriginX _ hisOrigin x. hisOriginY _ hisOrigin y. hisCornerX _ hisCorner x. hisCornerY _ hisCorner y. origin x > hisOriginX ifTrue: [origin x: hisOriginX]. origin y > hisOriginY ifTrue: [origin y: hisOriginY]. corner x < hisCornerX ifTrue: [corner x: hisCornerX]. corner y < hisCornerY ifTrue: [corner y: hisCornerY].! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 11:39'! subDivideBy: aPoint "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom). columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 12:24'! subDivideRoundedBy: aPoint "ssa - round the orign and extent points" "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom) rounded. columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:24'! fastMoveBy: aPoint "Change the corner positions of the receiver so that its area translates by the amount defined by the argument, aPoint. This is much faster than a merge: but must be used wisely since it modifies both the receiver and the points which make up its origin and corner." origin moveBy: aPoint. corner moveBy: aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:09'! moveBy: aPoint "Change the corner positions of the receiver so that its area translates by the amount defined by the argument, aPoint." origin _ origin + aPoint. corner _ corner + aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:09'! moveTo: aPoint "Change the corners of the receiver so that its top left position is aPoint." corner _ corner + aPoint - origin. origin _ aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 10/8/2008 17:52'! newRectButtonPressedDo: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous. Only tracks while mouse is down." | rect newRect buttonNow delay | delay _ Delay forMilliseconds: 10. buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow] whileTrue: ["delay wait." buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Smalltalk isMorphic ifTrue: []. Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 10/8/2008 17:49'! newRectFrom: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous" | rect newRect buttonStart buttonNow delay | delay _ Delay forMilliseconds: 10. buttonStart _ buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow == buttonStart] whileTrue: ["delay wait." buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/27/2008 04:43'! scaleByRect: scale "Answer a Rectangle scaled by scale, a rectangle." ^Rectangle origin: origin * scale origin corner: corner * scale corner! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:57'! display | quad | quad _ Quadrangle region: self borderWidth: 1 borderColor: Color black insideColor: nil. quad display! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 11/4/2008 19:15'! displayOn: aDisplayMedium withBorderWidths: anArray "Rectangle fromUser displayOn: Display withBorderWidths:#(16 8 4 1)" "anArray = #(left top right bottom ) integers" | quad | quad _ Quadrangle region: self borderWidth: ((anArray at:1)@(anArray at:2) corner: (anArray at:3)@(anArray at:4))borderColor: Color black insideColor: nil. quad displayOn: aDisplayMedium! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 11/4/2008 19:16'! displayWithBorderWidths: anArray "Rectangle fromUser displayWithBorderWidths:#(16 8 4 1)" "anArray = #(left top right bottom ) integers" self displayOn: Display withBorderWidths: anArray! ! !Rectangle methodsFor: 'sizing - Louvre' stamp: 'ssa 12/5/2009 08:28'! size ^self extent! ! !Quadrangle methodsFor: 'bordering' stamp: ''! borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4 "Set the border width of the receiver to a Rectangle that represents the left, right, top, and bottom border widths." borderWidth _ anInteger1 @ anInteger3 corner: anInteger2 @ anInteger4! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/10/2010 10:26'! closeAllUnlockedWindows "ScreenController new closeAllUnlockedWindows" "Close any window that isn't locked." | toClose | toClose _ ScheduledControllers scheduledControllers select: [:c | c preventClosing not]. (SelectionMenu confirm:'Do you really want to close all unlocked windows?') ifFalse: [^ self]. toClose do: [:c | c closeAndUnscheduleIfOkWithModelNoTerminate]. self restoreDisplay. ! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/9/2010 15:26'! closeTopWindow | closeable | closeable _ ScheduledControllers scheduledControllers detect:[:controller| controller preventClosing not] ifNone:[^self]. closeable view flash. sensor commandKeyPressed ifTrue:[closeable closeAndUnscheduleIfOkWithModel]! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/9/2010 15:27'! preventClosing ^true! ! !ScreenController methodsFor: 'control defaults' stamp: 'ssa 3/3/2010 14:37'! controlActivity "Any button opens the screen's menu. If the shift key is down, do find window." sensor leftShiftDown ifTrue: [^ self findWindow]. sensor controlKeyPressed ifTrue: [^self closeTopWindow]. (self projectScreenMenu invokeOn: self) ifNil: [super controlActivity]! ! !ScreenController methodsFor: 'control defaults' stamp: 'ssa 3/3/2010 13:42'! isControlWanted ^ self viewHasCursor and: [sensor anyButtonPressed]! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 1/21/2010 12:17'! exploreViewFromUser "Explore the selected window" | controller | (controller _ ScheduledControllers windowFromUser) notNil ifTrue: [controller view explore]! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 4/20/2010 09:50'! openRVMDashboard "Create and schedule a RVM dashboard." RVMMonitor dashboard! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 5/4/1998 17:25'! openWorkspace "Create and schedule workspace." Workspace open! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 3/24/2010 16:34'! recolorWindows Smalltalk recolorWindows! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/24/2010 16:33'! appearanceMenu "Answer the appearance menu to be put up as a screen submenu" ^ SelectionMenu labelList: #('system fonts...' 'full screen on' 'full screen off' 'recolor windows' 'set display depth...' 'set desktop color...' ) lines: #(1 3) selections: #( configureFonts fullScreenOn fullScreenOff recolorWindows setDisplayDepth setDesktopColor) " ScreenController new appearanceMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'dmu 8/30/2010 10:43'! dashboardMenu | labels selections | labels _ #('RVM dashboard') asOrderedCollection. selections _ #(openRVMDashboard) asOrderedCollection. (Smalltalk includesKey: #Sly3) ifTrue:[ labels add: 'Sly dashboard'. selections add:#openSlyDashboard]. (Smalltalk includesKey: #Ly) ifTrue:[ labels add: 'Ly dashboard'. selections add:#openLyDashboard]. ^ SelectionMenu labelList: labels lines: #() selections: selections " ScreenController new dashboardMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 7/7/2010 11:20'! presentDashboardMenu self popUpMenuFor: #dashboardMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 7/7/2010 11:21'! projectScreenMenu "Answer the project screen menu." ^ SelectionMenu labelList: #( 'previous project' 'jump to project...' 'restore display' 'dashboards...' 'open...' 'windows...' 'changes...' 'help...' 'appearance...' 'do...' 'save' 'save as...' 'save and quit' 'quit') lines: #(3 4 12) selections: #( returnToPreviousProject jumpToProject restoreDisplay presentDashboardMenu presentOpenMenu presentWindowMenu presentChangesMenu presentHelpMenu presentAppearanceMenu commonRequests snapshot saveAs snapshotAndQuit quit ) " ScreenController new projectScreenMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/10/2010 10:01'! windowMenu "Answer a menu for windows-related items. " ^ SelectionMenu labelList: #( 'find window...' 'find changed browsers...' 'find changed windows...' 'collapse all windows' 'expand all windows' 'close unchanged windows' 'close unlocked windows' ) , (Array with: self bitCachingString with: self staggerPolicyString) lines: #(3 7) selections: #( findWindow chooseDirtyBrowser chooseDirtyWindow collapseAll expandAll closeUnchangedWindows closeAllUnlockedWindows fastWindows changeWindowPolicy ) " ScreenController new windowMenu startUp "! ! !ScrollController methodsFor: 'basic control sequence' stamp: 'ssa 9/9/2009 17:06'! controlInitialize "Recompute scroll bars. Save underlying image unless it is already saved." "Hacked to disable flop-out scroll bars when inside an MSWScrollBarView - ssa 12/10/97 15:21" super controlInitialize. scrollBar region: (0 @ 0 extent: 24 @ view apparentDisplayBox height). scrollBar insideColor: view backgroundColor. marker region: self computeMarkerRegion. scrollBar _ scrollBar align: scrollBar topRight with: view apparentDisplayBox topLeft. marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2). savedArea isNil ifTrue: [savedArea _ Form fromDisplay: scrollBar]. (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[scrollBar displayOn: Display]. "Show a border around yellow-button (menu) region" " yellowBar _ Rectangle left: self yellowLine right: scrollBar right + 1 top: scrollBar top bottom: scrollBar bottom. Display border: yellowBar width: 1 mask: Form veryLightGray. " self moveMarker ! ! !ScrollController methodsFor: 'basic control sequence' stamp: 'ssa 9/9/2009 17:07'! controlTerminate super controlTerminate. savedArea notNil ifTrue: [ (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[savedArea displayOn: Display at: scrollBar topLeft]. savedArea _ nil].! ! !ScrollController methodsFor: 'control defaults' stamp: ''! controlActivity "Hacked to supprt MSWScrollBarView - ssa 12/10/97 17:07" (self view superView isKindOf: MSWScrollBarView) ifFalse:[ self scrollBarContainsCursor ifTrue: [self scroll] ifFalse: [super controlActivity]] ifTrue:[super controlActivity]! ! !ScrollController methodsFor: 'control defaults' stamp: ''! isControlActive "Viva la Junta!!" "HACKED to ignore scrollbar in the activity test if contained in a ScrollbarView - ssa 1/8/98 16:24" view isNil ifTrue: [^ false]. (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:["original code" ^(view insetDisplayBox merge: scrollBar inside) containsPoint: sensor cursorPoint] ifTrue:[^view insetDisplayBox containsPoint: sensor cursorPoint]! ! !ScrollController methodsFor: 'marker adjustment' stamp: ''! moveMarker "The view window has changed. Update the marker." "Hacked to suppress flop-out scrollbar updates when the view is encapsulated by an MSWScrollBarView - ssa 12/10/97 15:24" (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[self moveMarker: self markerDelta negated anchorMarker: nil]! ! !ScrollController methodsFor: 'marker adjustment' stamp: ''! moveMarkerTo: aRectangle "Same as markerRegion: aRectangle; moveMarker, except a no-op if the marker would not move." "Hacked to suppress flop-out scrollbar updates when the view is encapsulated by an MSWScrollBarView - ssa 12/10/97 15:24" (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[ (aRectangle height = marker height and: [self viewDelta = 0]) ifFalse: [self markerRegion: aRectangle. self moveMarker]]! ! !ListController methodsFor: 'menu messages' stamp: 'ssa 9/15/2009 16:53'! processKeyboard "Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | sensor keyboardPressed ifFalse: [^ self]. keyEvent := sensor keyboard asciiValue. (keyEvent = $l asciiValue and:[Sensor commandKeyPressed])ifTrue:[self view topView adjustWidths]. oldSelection := view selection. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view clippingBox height // view list lineGrid. keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [model okToChange ifTrue: [self changeModelSelection: nextSelection. self moveMarker]] ! ! !ParagraphEditor methodsFor: 'controlling' stamp: ''! controlActivity "Hacked to supprt MSWScrollBarView - ssa 12/10/97 17:07" self scrollBarContainsCursor ifTrue: [(self view superView isKindOf: MSWScrollBarView) ifFalse:[self scroll]] ifFalse: [self processKeyboard. self processMouseButtons]! ! !ParagraphEditor methodsFor: 'scrolling' stamp: ''! scrollView: anInteger "Paragraph scrolling uses opposite polarity" "Adjusted to keep text from scrolling off the view - ssa 1/15/98 15:22. The - 30 below is the hack to allow for some empty space to show at the bottom." | maximumAmount minimumAmount amount | maximumAmount _ paragraph clippingRectangle top - paragraph compositionRectangle top max: 0. minimumAmount _ paragraph clippingRectangle bottom - paragraph compositionRectangle bottom - 30 min: 0. amount _ (anInteger min: maximumAmount) max: minimumAmount. ^ self scrollBy: amount negated! ! !ParagraphEditor methodsFor: 'scrolling' stamp: ''! updateMarker "Hacked to catch this scrolling 'event'. ssa 12/5/97 16:22" "A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph." self moveMarkerTo: self computeMarkerRegion. "A hack to notify the MSWScrollBarController" (self view superView isKindOf: MSWScrollBarView) ifTrue:[self view superView updateElevator]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 9/15/2009 16:53'! adjustWidths self view topView adjustWidths! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 3/1/2010 11:41'! browseIt "Launch a browser for the current selection, if appropriate" | aSymbol anEntry brow | Preferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt]. self lineSelectAndEmptyCheck: [^ self]. (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash]. self terminateAndInitializeAround: [aSymbol first isUppercase ifTrue: [anEntry _ (Smalltalk at: aSymbol ifAbsent: [ self systemNavigation browseAllImplementorsOf: aSymbol. ^ nil]). anEntry isNil ifTrue: [^ view flash]. (anEntry isKindOf: Class) ifFalse: [anEntry _ anEntry class]. [^ self browseClassFromIt]value. "<<<<<<<<<<<<<<<<<< ssa added" brow _ Preferences browseToolClass new. brow setClass: anEntry selector: nil. brow class openBrowserView: (brow openEditString: nil) label: 'System Browser'] ifFalse: [ self systemNavigation browseAllImplementorsOf: aSymbol]]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 1/21/2010 16:27'! methodSourceContainingIt "Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source). " self lineSelectAndEmptyCheck: [^ self]. self systemNavigation browseMethodsWithSourceString: self selection string! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ssa 9/8/2009 18:28'! buttonIt: characterStream "Called when user hits cmd-B. make a button of the selection" sensor keyboard. self buttonIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ssa 1/6/2010 20:32'! exploreIt: characterStream "Inspect the selection -- invoked via cmd-i. If there is no current selection, use the current line." sensor keyboard. "flush character" self terminateAndInitializeAround: [self exploreIt]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ssa 6/1/2010 16:55'! printIt: characterStream "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 2/29/96 sw: don't call selectLine now, since it's called by doIt" sensor keyboard. "flush character" self terminateAndInitializeAround: [self printIt]. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'ssa 1/20/2010 11:06'! cursorDown: characterStream "Private - Move cursor from position in current line to same position in next line. If next line too short, put at end. If shift key down, select." self closeTypeIn: characterStream. paragraph isEmpty ifTrue:[Sensor flushKeyboard. ^true]. self moveCursor:[:position | self sameColumn: position newLine:[:line | line + 1] forward: true] forward: true specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'ssa 1/20/2010 11:05'! cursorUp: characterStream "Private - Move cursor from position in current line to same position in prior line. If prior line too short, put at end" self closeTypeIn: characterStream. paragraph isEmpty ifTrue:[Sensor flushKeyboard. ^true]. self moveCursor: [:position | self sameColumn: position newLine:[:line | line - 1] forward: false] forward: false specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'private' stamp: 'ssa 1/20/2010 10:55'! sameColumn: start newLine: lineBlock forward: isForward "Private - Compute the index in my text with the line number derived from lineBlock," " a one argument block accepting the old line number. The position inside the line will be preserved as good as possible" "The boolean isForward is used in the border case to determine if we should move to the beginning or the end of the line." | wordStyle column currentLine offsetAtTargetLine targetEOL lines numberOfLines currentLineNumber targetLineNumber | wordStyle _ Preferences wordStyleCursorMovement. wordStyle ifTrue: [ lines _ paragraph lines. numberOfLines := paragraph numberOfLines. currentLineNumber _ paragraph lineIndexOfCharacterIndex: start. currentLine _ lines at: (currentLineNumber max: 1)] ifFalse: [ lines _ self lines. numberOfLines := lines size. currentLine _ lines detect:[:lineInterval | lineInterval last >= start] ifNone:[lines last]. currentLineNumber _ currentLine second]. column _ start - currentLine first. targetLineNumber _ ((lineBlock value: currentLineNumber) max: 1) min: numberOfLines. offsetAtTargetLine _ (lines at: targetLineNumber) first. targetEOL _ (lines at: targetLineNumber) last + (targetLineNumber == numberOfLines ifTrue:[1]ifFalse:[0]). targetLineNumber == currentLineNumber "No movement or movement failed. Move to beginning or end of line." ifTrue:[^isForward ifTrue:[targetEOL] ifFalse:[offsetAtTargetLine]]. ^offsetAtTargetLine + column min: targetEOL.! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 9/8/2009 19:09'! buttonIt "launch a button to evaluate the selection" | topView someCode extent | someCode _ self selection. extent _ (someCode asText asDisplayText extent + (30@20)) max: 80@30. topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: extent . topView maximumSize: extent. topView addSubView: (RVMButtonView label: someCode action:[self evaluate: someCode]). topView controller open! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 8/31/2009 10:30'! compileSelectionFor: anObject in: evalContext | methodNode method | methodNode _ [Compiler new compileNoPattern: self selection in: anObject class context: evalContext notifying: self ifFail: [^nil]] on: OutOfScopeNotification do: [:ex | ex resume: true]. method _ methodNode generate: #(0 0 0 0). ^method copyWithTempNames: methodNode tempNames! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! debugIt | method receiver context | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model debug: self selection asString notifying:self]. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. receiver _ model doItReceiver. context _ model doItContext] ifFalse: [receiver _ context _ nil]. self lineSelectAndEmptyCheck: [^self]. method _ self compileSelectionFor: receiver in: context. method notNil ifTrue: [self debug: method receiver: receiver in: context]. FakeClassPool adopt: nil! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! evaluate: someCode "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | someCode isEmpty ifTrue:[^ '']. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[model evaluate: someCode notifying:self] ifFalse:[ rcvr class evaluatorClass new evaluate: someCode readStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true]. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! evaluateSelection "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | self lineSelectAndEmptyCheck: [^ '']. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[model evaluate: self selection asString notifying:self] ifFalse:[ rcvr class evaluatorClass new evaluate: self selectionAsStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true]. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! exploreIt | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model exploreIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [result explore]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! inspectIt "1/13/96 sw: minor fixup" | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model inspectIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [result inspect]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! installAsTest | | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model installAsTest: self selection asString notifying:self]. self halt:'not implemented for Squeak Workspaces yet'! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! parseIt ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model parseAndExplore: self selection asString notifying:self]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! printIt "Treat the current text selection as an expression; evaluate it. Insert the description of the result of evaluation after the selection and then make this description the new text selection." | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model printIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [self afterSelectionInsertAndSelect: result printString]! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'ssa 2/9/2010 05:23'! initializeTextEditorMenus "Initialize the yellow button pop-up menu and corresponding messages." "ParagraphEditor initializeTextEditorMenus" TextEditorYellowButtonMenu _ SelectionMenu labels: 'find...(f) find again (g) set search string (h) do again (j) undo (z) copy (c) cut (x) paste (v) paste... do it (d) print it (p) inspect it (i) explore it (e) debug it button it (B) accept (s) cancel (l) show bytecodes more...' lines: #(3 5 9 15 17 19) selections: #(find findAgain setSearchString again undo copySelection cut paste pasteRecent doIt printIt inspectIt exploreIt debugIt buttonIt accept cancel showBytecodes shiftedTextPaneMenuRequest).! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'ssa 1/29/2010 12:18'! initializeCmdKeyShortcuts "Initialize the (unshifted) command-key (or alt-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "ParagraphEditor initialize" | cmdMap cmds | cmdMap := Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: 1 + 1 put: #cursorHome:. "home key" cmdMap at: 4 + 1 put: #cursorEnd:. "end key" cmdMap at: 8 + 1 put: #backspace:. "ctrl-H or delete key" cmdMap at: 11 + 1 put: #cursorPageUp:. "page up key" cmdMap at: 12 + 1 put: #cursorPageDown:. "page down key" cmdMap at: 13 + 1 put: #crWithIndent:. "cmd-Return" cmdMap at: 27 + 1 put: #offerMenuFromEsc:. "escape key" cmdMap at: 28 + 1 put: #cursorLeft:. "left arrow key" cmdMap at: 29 + 1 put: #cursorRight:. "right arrow key" cmdMap at: 30 + 1 put: #cursorUp:. "up arrow key" cmdMap at: 31 + 1 put: #cursorDown:. "down arrow key" cmdMap at: 32 + 1 put: #selectWord:. "space bar key" cmdMap at: 127 + 1 put: #forwardDelete:. "del key" '0123456789-=' do: [:char | cmdMap at: char asciiValue + 1 put: #changeEmphasis:]. '([{''"<' do: [:char | cmdMap at: char asciiValue + 1 put: #enclose:]. cmdMap at: $, asciiValue + 1 put: #shiftEnclose:. cmds := #($a #selectAll: $b #browseIt: $c #copySelection: $d #doIt: $e #exploreIt: $f #find: $g #findAgain: $h #setSearchString: $i #inspectIt: $j #doAgainOnce: $k #offerFontMenu: $l #cancel: $m #implementorsOfIt: $n #sendersOfIt: $o #spawnIt: $p #printIt: $q #querySymbol: $r #revert: $s #save: $S saveAs:: $t #tempCommand: $u #align: $v #paste: $w #backWord: $x #cut: $y #swapChars: $z #undo:). 1 to: cmds size by: 2 do: [:i | cmdMap at: (cmds at: i) asciiValue + 1 put: (cmds at: i + 1)]. CmdActions := cmdMap! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'ssa 2/9/2010 05:26'! initializeShiftCmdKeyShortcuts "Initialize the shift-command-key (or control-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "wod 11/3/1998: Fix setting of cmdMap for shifted keys to actually use the capitalized versions of the letters. TPR 2/18/99: add the plain ascii values back in for those VMs that don't return the shifted values." | cmdMap cmds | "shift-command and control shortcuts" cmdMap _ Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: ( 1 + 1) put: #cursorHome:. "home key" cmdMap at: ( 4 + 1) put: #cursorEnd:. "end key" cmdMap at: ( 8 + 1) put: #forwardDelete:. "ctrl-H or delete key" cmdMap at: (11 + 1) put: #cursorPageUp:. "page up key" cmdMap at: (12 + 1) put: #cursorPageDown:. "page down key" cmdMap at: (13 + 1) put: #crWithIndent:. "ctrl-Return" cmdMap at: (27 + 1) put: #offerMenuFromEsc:. "escape key" cmdMap at: (28 + 1) put: #cursorLeft:. "left arrow key" cmdMap at: (29 + 1) put: #cursorRight:. "right arrow key" cmdMap at: (30 + 1) put: #cursorUp:. "up arrow key" cmdMap at: (31 + 1) put: #cursorDown:. "down arrow key" cmdMap at: (32 + 1) put: #selectWord:. "space bar key" cmdMap at: (45 + 1) put: #changeEmphasis:. "cmd-sh-minus" cmdMap at: (61 + 1) put: #changeEmphasis:. "cmd-sh-plus" cmdMap at: (127 + 1) put: #forwardDelete:. "del key" "Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $(" '9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ]. "({< and double-quote" "Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command." "NB: sw 12/9/2001 commented out the idiosyncratic line just below, which was grabbing shift-esc in the text editor and hence which argued with the wish to have shift-esc be a universal gesture for escaping the local context and calling up the desktop menu." "cmdMap at: (27 + 1) put: #shiftEnclose:." "ctrl-[" "'""''(' do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose:]." cmds _ #( $a argAdvance: $b buttonIt: $c compareToClipboard: $d duplicate: $e methodStringsContainingIt: $f displayIfFalse: $g fileItIn: $h cursorTopHome: $i exploreIt: $j doAgainMany: $k changeStyle: $l outdent: $m selectCurrentTypeIn: $n referencesToIt: $p makeProjectLink: $r indent: $s search: $t displayIfTrue: $u changeLfToCr: $v pasteInitials: $w methodNamesContainingIt: $x makeLowercase: $y makeUppercase: $z makeCapitalized: ). 1 to: cmds size by: 2 do: [ :i | cmdMap at: ((cmds at: i) asciiValue + 1) put: (cmds at: i + 1). "plain keys" cmdMap at: ((cmds at: i) asciiValue - 32 + 1) put: (cmds at: i + 1). "shifted keys" cmdMap at: ((cmds at: i) asciiValue - 96 + 1) put: (cmds at: i + 1). "ctrl keys" ]. ShiftCmdActions _ cmdMap! ! !PluggableListController methodsFor: 'private' stamp: 'di 5/25/1998 10:20'! changeModelSelection: anInteger "Let the view handle this." terminateDuringSelect ifTrue: [self controlTerminate]. view changeModelSelection: anInteger. terminateDuringSelect ifTrue: [self controlInitialize].! ! !LyPluggableOutlineController methodsFor: 'selecting' stamp: 'ssa 9/9/2009 16:35'! redButtonActivity super redButtonActivity. self view twistyTargets keys detect:[:box| box containsPoint: Sensor cursorPoint] ifNone:[^self]. self model toggleSelection! ! !PluggableListControllerOfMany methodsFor: 'control defaults' stamp: 'ssa 1/1/1970 00:05'! redButtonActivity | selection firstHit turningOn lastSelection pt scrollFlag | model okToChange ifFalse: [^ self]. "Don't change selection if model refuses to unlock" firstHit _ true. scrollFlag _ false. lastSelection _ 0. [sensor redButtonPressed] whileTrue: [ selection _ view findSelection: (pt _ sensor cursorPoint). selection == nil ifTrue: "Maybe out of box - check for auto-scroll" [pt y < view insetDisplayBox top ifTrue: [self scrollView: view list lineGrid. scrollFlag _ true. selection _ view firstShown]. pt y > view insetDisplayBox bottom ifTrue: [self scrollView: view list lineGrid negated. scrollFlag _ true. selection _ view lastShown]]. (selection == nil or: [selection = lastSelection]) ifFalse: [firstHit ifTrue: [firstHit _ false. turningOn _ (view listSelectionAt: selection) not]. view selection: selection. (view listSelectionAt: selection) == turningOn ifFalse: [view displaySelectionBox. view listSelectionAt: selection put: turningOn]. lastSelection _ selection]]. selection notNil ifTrue: ["Normal protocol delivers change, so unchange first (ugh)" "view listSelectionAt: selection put: (view listSelectionAt: selection) not". self changeModelSelection: selection]. scrollFlag ifTrue: [self moveMarker]! ! !PluggableTextController methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:35'! selectFrom: start to: stop scroll: scrollCommand "Deselect, then select the specified characters inclusive. Be sure the selection is in view." (start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse: [view superView ifNotNil: [self deselect]. self selectInvisiblyFrom: start to: stop]. view superView ifNotNil: [self perform: scrollCommand]! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'ssa 8/22/2009 16:21'! labels: labels lines: linesArray selectors: selectionsArray "ST80 Compatibility" ^ self labels: labels lines: linesArray selections: selectionsArray! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/27/2008 20:34'! rotateBackward "Answer a copy of the receiver with elements rotated toward the front." " 'frog' rotateBackward" | n result | n _ self size. result _ self species new: n. n = 0 ifTrue:[^result]. n = 1 ifTrue:[result at: 1 put: (self at: 1). ^result]. 1 to: n-1 do: [:i | result at: i put: (self at: i + 1)]. result at: n put: self first. ^ result ! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/27/2008 20:33'! rotateForward "Answer a copy of the receiver with elements rotated toward the end." " 'frog' rotateForward" | n result | n _ self size. result _ self species new: n. n = 0 ifTrue:[^result]. n = 1 ifTrue:[result at: 1 put: (self at: 1). ^result]. 2 to: n do: [:i | result at: i put: (self at: i - 1)]. result at: 1 put: self last. ^ result ! ! !SequenceableCollection methodsFor: 'copying' stamp: 'dmu 5/5/2009 01:05'! shuffled ^ self shuffledBy: Collection randomForPicking copy "Examples: ($A to: $Z) shuffled "! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 13:51'! with: secondCollection with: thirdCollection do: threeArgBlock "Evaluate threeArgBlock with corresponding elements from this collection, secondCollection and thirdCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. thirdCollection size = self size ifFalse: [self error: 'thirdCollection must be the same size']. 1 to: self size do: [:index | threeArgBlock value: (self at: index) value: (secondCollection at: index) value: (thirdCollection at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 14:01'! with: secondCollection with: thirdCollection withIndexDo: fourArgBlock "Evaluate fourArgBlock with corresponding elements from this collection, secondCollection and thirdCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. thirdCollection size = self size ifFalse: [self error: 'thirdCollection must be the same size']. 1 to: self size do: [:index | fourArgBlock value: (self at: index) value: (secondCollection at: index) value: (thirdCollection at: index) value: index]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 15:34'! with: secondCollection withIndexDo: threeArgBlock "Evaluate threeArgBlock with corresponding elements from this collection and secondCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. 1 to: self size do: [:index | threeArgBlock value: (self at: index) value: (secondCollection at: index) value: index]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 1/20/2009 14:08'! without: anObject collect: aBlock "Evaluate aBlock with each of the receiver's elements except anObject as the argument. Collect the resulting values into a collection like the receiver. Answer the new collection." | newCollection | newCollection _ self species new: self size - 1. 1 to: self size do: [:index | anObject = (self at: index) ifFalse:[newCollection add: (aBlock value: (self at: index))]]. ^ newCollection! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 1/20/2009 14:11'! without: anObject select: aBlock "Evaluate aBlock with each of the receiver's elements except anObject as the argument. Select the resulting values that pass into a collection like the receiver. Answer the new collection." | newCollection item | newCollection _ self species new: self size - 1. 1 to: self size do: [:index | item _ self at:index. (anObject ~= item and:[aBlock value: item]) ifTrue:[newCollection add: item]]. ^ newCollection! ! !SequenceableCollection methodsFor: 'testing' stamp: 'ssa 8/27/2009 12:44'! is: anObject after: anotherObject ^(self indexOf: anObject)<(self indexOf: anotherObject)! ! !SequenceableCollection methodsFor: 'explorer' stamp: 'hg 9/7/2001 12:01'! explorerContents ^self asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !SequenceableCollection methodsFor: '*connectors-enumerating' stamp: 'ssa 1/1/1970 00:18'! groupsOfNoMoreThan: n atATimeDo: aBlock "Evaluate aBlock with my elements taken n at a time. Handle leftovers at the end." | args remaining | n to: self size by: n do: [:index | args := (self copyFrom: index - n + 1 to: index) asArray. aBlock value: args]. (remaining _ self size \\ n) = 0 ifFalse:["handle leftovers" args := (self copyFrom: self size - remaining + 1 to: self size) asArray. aBlock value: args]! ! !Array methodsFor: 'converting' stamp: 'ssa 10/26/2008 15:00'! asRunArray "Answer a RunArray of me" ^RunArray newFrom: self! ! !Array methodsFor: 'testing' stamp: 'ssa 5/12/2010 19:26'! isArray "Return true if the receiver is an Array" ^true! ! !ArrayWithNilDetector methodsFor: 'accessing' stamp: 'ssa 11/24/2009 20:01'! at: j put: obj obj ifNil:[self halt:'trying to add nil']. ^super at: j put: obj! ! !ArrayWithNilDetector methodsFor: 'accessing' stamp: 'ssa 11/24/2009 20:39'! species (self includes: nil) ifTrue:[self halt:'I found a nil!!!!']. ^super species! ! !ArrayWithNilDetector class methodsFor: 'instance creation' stamp: 'ssa 11/24/2009 20:37'! new: someSize someSize > 0 ifTrue:[self halt:'trying to create a an array with nil elements']. ^super new: someSize! ! !CompiledMethod methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:21'! longPrintOn: aStream indent: tabs "List of all the byte codes in a method with a short description of each" aStream nextPutAll: (RVMTester printPrefixFor: self). self isQuick ifTrue: [self isReturnSpecial ifTrue: [^ aStream tab: tabs; nextPutAll: 'Quick return ' , (#('self' 'true' 'false' 'nil' '-1' '0' '1' '2') at: self primitive - 255)]. ^ aStream nextPutAll: 'Quick return field ' , self returnField printString , ' (0-based)']. self primitive = 0 ifFalse: [ aStream tab: tabs. self printPrimitiveOn: aStream. ]. (InstructionPrinter on: self) indent: tabs; printInstructionsOn: aStream. ! ! !CompiledMethod methodsFor: 'printing' stamp: 'ssa 10/3/2008 18:13'! symbolic "Answer a String that contains a list of all the byte codes in a method with a short description of each." | aStream | aStream _ WriteStream on: (String new: 1000). self longPrintOn: aStream. ^aStream contents! ! !LinkedList methodsFor: 'converting' stamp: 'ssa 1/26/2010 16:24'! asOrderedCollection ^(self collect:[:link| link])asOrderedCollection! ! !LinkedList methodsFor: 'explorer' stamp: 'ssa 1/26/2010 16:32'! hasContentsInExplorer ^self isEmpty not! ! !OrderedCollection methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:44'! inspectorClass ^ OrderedCollectionInspector! ! !OrderedCollection methodsFor: 'adding' stamp: 'ssa 9/9/2009 11:48'! addAll: aCollection after: anObject "Add each element of aCollection at my end. Answer aCollection." | after | after _ anObject. aCollection do:[:each| self add: each after: after. after _ each]. ^aCollection! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:54'! add: newObject newObject ifNil:[self halt:'trying to add nil']. ^super add: newObject! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:56'! addAll: aCollection "Add each element of aCollection at my end. Answer aCollection." (aCollection includes: nil) ifTrue:[self halt:'trying to add nil']. ^ super addAll: aCollection! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:57'! insert: anObject before: spot anObject ifNil:[self halt:'trying to add nil']. ^super insert: anObject before: spot! ! !RunArray methodsFor: 'fileIn/Out' stamp: ''! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: runs size. 1 to: runs size do: [:x | aStream store: (runs at: x). aStream nextPut: (values at: x)]! ! !RunArray class methodsFor: 'instance creation' stamp: ''! archiveVersion ^3! ! !RunArray class methodsFor: 'instance creation' stamp: ''! dearchive2From: aStream | anInteger runs values | anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: aStream next]. ^self runs: runs values: values! ! !RunArray class methodsFor: 'instance creation' stamp: ''! dearchive: versionNumber from: aStream | anInteger runs values | versionNumber = 1 ifTrue: [anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: (aStream read: Integer)]. ^self runs: runs values: values]. versionNumber = 2 ifTrue: [^self dearchive2From: aStream]. versionNumber = self archiveVersion ifTrue: [^self dearchiveFrom: aStream]. self error: 'Can''t dearchive this version.'! ! !RunArray class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream | anObject anInteger runs values | anObject _ self basicNew. aStream storeObject: anObject. anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: aStream next]. ^anObject setRuns: runs setValues: values! ! !Set methodsFor: 'explorer' stamp: 'hg 9/7/2001 11:51'! explorerContents ^self asOrderedCollection withIndexCollect: [:each :index | ObjectExplorerWrapper with: each name: index printString model: self]! ! !Set methodsFor: 'printing' stamp: ''! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self size. self do: [:each | aStream nextPut: each]! ! !Dictionary methodsFor: 'printing' stamp: ''! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self size. self associationsDo: [:each | aStream nextPut: each]! ! !Dictionary methodsFor: 'user interface' stamp: 'hg 10/3/2001 20:47'! explorerContents | contents | contents := OrderedCollection new. self keysSortedSafely do: [:key | contents add: (ObjectExplorerWrapper with: (self at: key) name: (key printString contractTo: 32) model: self)]. ^contents ! ! !Dictionary methodsFor: 'outlining' stamp: 'ssa 9/10/2009 14:30'! subobjects ^self associations asOrderedCollection! ! !Set class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream | anObject anInteger | anInteger _ aStream read: Integer. anObject _ self new: (anInteger * 2 max: 2). aStream storeObject: anObject. anInteger timesRepeat: [anObject add: aStream next]. ^anObject! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:25'! snapshot: save andQuit: quit embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | "Save a copy of the image file before you save the new one" save ifTrue:[(FileDirectory default fileExists: SmalltalkImage current imageName ) ifTrue:[FileDirectory default rename: SmalltalkImage current imageName toBe: SmalltalkImage current imageName , '.prev',Time now hhmm24]]. Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil:[ msg _ String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ]]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position ]. self logChange: msg. Transcript cr; show: msg ]. Smalltalk processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. Smalltalk setGCParameters. resuming == true ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'ssa 10/18/2008 22:56'! oldFileMenu: aDirectory withPattern: aPattern Smalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory withPattern: aPattern]. ^super new oldFileFrom: aDirectory withPattern: aPattern! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:01'! oldFileFrom: aDirectory withPattern: aPattern ^(self oldFileMenu: aDirectory withPattern: aPattern) startUpWithCaption: 'Select a File:' translated! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:12'! oldFileStreamFrom: aDirectory withPattern: aPattern | sfmResult fileStream | sfmResult _ self oldFileFrom: aDirectory withPattern: aPattern. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name. [fileStream isNil] whileTrue: [sfmResult _ self oldFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name]. ^fileStream ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:12'! oldFileStreamWithPattern: aPattern ^self oldFileStreamFrom: (FileDirectory default) withPattern: aPattern ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 22:54'! oldFileWithPattern: aPattern ^self oldFileFrom: (FileDirectory default) withPattern: aPattern! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ssa 10/26/2008 23:47'! nextPut: char "Write the given character to this file." rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. buffer1 byteAt: 1 put: char. self primWrite: fileID from: buffer1 startingAt: 1 count: 1. ^ char ! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:56'! preventClosing "Answer the value of preventClosing" preventClosing isNil ifTrue:[self preventClosing: false]. ^ preventClosing! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:25'! preventClosing: anObject "Set the value of preventClosing" preventClosing _ anObject! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:25'! status "Answer the value of status" status isNil ifTrue:[self status: nil]. ^ status! ! !StandardSystemController methodsFor: 'borders' stamp: ''! adjustWindowCorners | box cornerBox p clicked f2 | box := view windowBox. clicked := false. #(topLeft topRight bottomRight bottomLeft) do: [:readCorner | cornerBox := ((box insetBy: 2) perform: readCorner) - (10@10) extent: 20@20. (cornerBox containsPoint: sensor cursorPoint) ifTrue: ["Display reverse: cornerBox." (Cursor perform: readCorner) showWhile: [[(cornerBox containsPoint: (p := sensor cursorPoint)) and: [(clicked := sensor anyButtonPressed) not]] whileTrue. "Display reverse: cornerBox." clicked ifTrue: [view newFrame: [:f | p := sensor cursorPoint. readCorner = #topLeft ifTrue: [f2 := p corner: f bottomRight]. readCorner = #bottomLeft ifTrue: [f2 := (f withBottom: p y) withLeft: p x]. readCorner = #bottomRight ifTrue: [f2 := f topLeft corner: p]. readCorner = #topRight ifTrue: [f2 := (f withTop: p y) withRight: p x]. f2]]]]]. ^ clicked! ! !StandardSystemController methodsFor: 'borders' stamp: ''! checkForReframe "2/18/97 ssa - added a leftshift hack to prevent over aggressive offerings of reframing help for subpanes." | cp | view isCollapsed ifTrue: [^ self]. cp := sensor cursorPoint. ((view closeBoxFrame expandBy: 2) containsPoint: cp) | ((view growBoxFrame expandBy: 2) containsPoint: cp) ifTrue: [^ self]. "Dont let reframe interfere with close/grow" self adjustWindowCorners. self cursorOnBorder ifFalse: [^ self]. ((view insetDisplayBox insetBy: 2@2) containsPoint: cp) ifFalse: [^ self adjustWindowBorders]. Sensor leftShiftDown ifTrue:[ (view subviewWithLongestSide: [:s | ] near: cp) == nil ifFalse: [^ self adjustPaneBorders]].! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'ssa 3/9/2010 12:58'! blueButtonActivity self blueButtonMenu invokeOn: self! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'dmu 5/3/2009 12:12'! isClosed ^ status == #closed! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'ssa 3/12/2010 09:50'! redButtonActivity "If cursor is in label of a window when red button is pushed, check for closeBox or growBox, else drag the window frame or edit the label." | box p | p _ sensor cursorPoint. self labelHasCursor ifFalse: [super redButtonActivity. ^ self]. ((box _ view closeBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [Sensor shiftPressed ifFalse:[self close. ^ self]ifTrue:[^self togglePreventClosing]]. ^ self]. ((box _ view growBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [Sensor controlKeyPressed ifTrue: [^ self expand; fullScreen]. ^ view isCollapsed ifTrue: [self expand] ifFalse: [self collapse]]. ^ self]. (((box _ view labelTextRegion expandBy: 1) containsPoint: p) and: [Preferences clickOnLabelToEdit or: [sensor leftShiftDown]]) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [^ self label]. ^ self]. self move! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/24/2010 16:12'! close "The receiver's view should be removed from the screen and from the collection of scheduled views." self preventClosing ifTrue:[^self]. model okToChange ifFalse: [^self]. self closeForReal! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/12/2010 09:47'! closeForReal "The receiver's view should be removed from the screen and from the collection of scheduled views." status _ #closed. view erase! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/9/2010 13:00'! togglePreventClosing self preventClosing: self preventClosing not. self view emphasizeLabel.! ! !StandardSystemController methodsFor: 'pluggable menus' stamp: 'ssa 3/12/2010 09:46'! blueButtonMenu ^SelectionMenu labels: 'edit label choose color... two-tone/full color move frame full screen collapse ', (self preventClosing ifTrue:['enable closing']ifFalse:['disable closing close']) lines: #(3 7) selections: #(label chooseColor toggleTwoTone move reframe fullScreen collapse togglePreventClosing close). ! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'ssa 3/3/2010 13:57'! closeAndUnscheduleIfOkWithModel "Erase the receiver's view and remove it from the collection of scheduled views. IF its ok with my model. This catches unsaved changes" model okToChange ifFalse: [^self]. self closeAndUnschedule! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'ssa 3/10/2010 10:07'! closeAndUnscheduleIfOkWithModelNoTerminate "Erase the receiver's view and remove it from the collection of scheduled views. IF its ok with my model. This catches unsaved changes" model okToChange ifFalse: [^self]. self closeAndUnscheduleNoTerminate! ! !MSWSystemController methodsFor: 'accessing' stamp: 'ar 1/22/98 23:30'! lastSystemActivity ^lastSystemActivity ifNil:[lastSystemActivity _ 0]! ! !MSWSystemController methodsFor: 'accessing' stamp: 'ar 1/22/98 23:30'! lastSystemActivity: aNumber lastSystemActivity _ aNumber! ! !MSWSystemController methodsFor: 'basic control sequence' stamp: 'ssa 9/11/2009 16:36'! redButtonActivity | box p | p _ sensor cursorPoint. ((box _ view systemBoxFrame) containsPoint: p) ifTrue: [^self systemActivity]. ((box _ view shrinkBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [self collapse. ^ self]. ^ self]. ((box _ view growBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [view isCollapsed ifTrue:[self expand] ifFalse:[view isFullScreen ifTrue:[self restore] ifFalse:[self fullScreen]]. ^ self]. ^ self]. super redButtonActivity.! ! !MSWSystemController methodsFor: 'basic control sequence' stamp: 'ar 1/22/98 23:33'! systemActivity "The system menu button has been pressed" | time | time _ Time millisecondClockValue. (time- self lastSystemActivity) < self doubleClickTime ifTrue:[^self close]. self lastSystemActivity: time. ^self blueButtonActivity! ! !MSWSystemController methodsFor: 'menu messages' stamp: 'ar 1/22/98 22:41'! restore view restore! ! !MSWSystemController methodsFor: 'private' stamp: 'ar 1/22/98 23:32'! doubleClickTime "Return the maximum delay time for double clicks. This value is in milliseconds." ^500! ! !MSWSystemController methodsFor: 'borders' stamp: 'ssa 1/25/98 00:00'! adjustWindowCorners | box cornerBox p clicked f2 | box _ view windowBox. clicked _ false. #(topLeft topRight bottomRight bottomLeft) do: [:readCorner | cornerBox _ ((box insetBy: 2) perform: readCorner) - (4@4) extent: 8@8. (cornerBox containsPoint: sensor cursorPoint) ifTrue: ["Display reverse: cornerBox." (Cursor perform: readCorner) showWhile: [[(cornerBox containsPoint: (p _ sensor cursorPoint)) and: [(clicked _ sensor anyButtonPressed) not]] whileTrue. "Display reverse: cornerBox." clicked ifTrue: [view newFrame: [:f | p _ sensor cursorPoint. readCorner = #topLeft ifTrue: [f2 _ p corner: f bottomRight]. readCorner = #bottomLeft ifTrue: [f2 _ (f withBottom: p y) withLeft: p x]. readCorner = #bottomRight ifTrue: [f2 _ f topLeft corner: p]. readCorner = #topRight ifTrue: [f2 _ (f withTop: p y) withRight: p x]. f2]]]]]. ^ clicked! ! !MSWSystemController methodsFor: 'borders' stamp: 'ssa 1/24/98 23:47'! cursorOnBorder | cp i box | view isCollapsed ifTrue: [^ false]. cp _ sensor cursorPoint. ((view labelDisplayBox insetBy: 5@5) containsPoint: cp) ifTrue: [^ false]. (i _ view subViews findFirst: [:v | v displayBox containsPoint: cp]) = 0 ifTrue: [box _ view windowBox] ifFalse: [box _ (view subViews at: i) insetDisplayBox]. ^ ((box insetBy: 3) containsPoint: cp) not and: [(box expandBy: 4) containsPoint: cp]! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! ascent: anObject "Set the value of ascent" ascent _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! characterToGlyphMap: anObject "Set the value of characterToGlyphMap" characterToGlyphMap _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! derivativeFonts "Answer the value of derivativeFonts" derivativeFonts isNil ifTrue:[self derivativeFonts: nil]. ^ derivativeFonts! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! derivativeFonts: anObject "Set the value of derivativeFonts" derivativeFonts _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! descent: anObject "Set the value of descent" descent _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! emphasis "Answer the value of emphasis" emphasis isNil ifTrue:[self emphasis: nil]. ^ emphasis! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! glyphs: anObject "Set the value of glyphs" glyphs _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! maxAscii: anObject "Set the value of maxAscii" maxAscii _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! maxWidth: anObject "Set the value of maxWidth" maxWidth _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! minAscii: anObject "Set the value of minAscii" minAscii _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! pointSize: anObject "Set the value of pointSize" pointSize _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! raster "Answer the value of raster" raster isNil ifTrue:[self raster: nil]. ^ raster! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! raster: anObject "Set the value of raster" raster _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! strikeLength "Answer the value of strikeLength" strikeLength isNil ifTrue:[self strikeLength: nil]. ^ strikeLength! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! strikeLength: anObject "Set the value of strikeLength" strikeLength _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! subscript "Answer the value of subscript" subscript isNil ifTrue:[self subscript: nil]. ^ subscript! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! subscript: anObject "Set the value of subscript" subscript _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! superscript "Answer the value of superscript" superscript isNil ifTrue:[self superscript: nil]. ^ superscript! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! superscript: anObject "Set the value of superscript" superscript _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! type "Answer the value of type" type isNil ifTrue:[self type: nil]. ^ type! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! type: anObject "Set the value of type" type _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xOffset "Answer the value of xOffset" xOffset isNil ifTrue:[self xOffset: nil]. ^ xOffset! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xOffset: anObject "Set the value of xOffset" xOffset _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xTable: anObject "Set the value of xTable" xTable _ anObject! ! !StrikeFont methodsFor: 'printing' stamp: ''! archiveOn: aStream "record this instance by its name. On dearchive, the name corresponding to this instance will be looked up." aStream storeObject: self; storeClass: self class; store: self name! ! !StrikeFont class methodsFor: 'archiving' stamp: ''! archiveVersion "This version archives only the name of the strikeFont. On dearchive, the name will be looked up and the appropriate strike font existing in that image will be returned." ^3! ! !StrikeFont class methodsFor: 'archiving' stamp: ''! dearchive: versionNumber from: aStream | aString sf | versionNumber = self archiveVersion ifFalse:[^super dearchiveFrom: aStream]. aString _ aStream read: String. sf _ self allInstances detect:[:inst| inst name = aString] ifNone:[self error:'missing strike font for this image']. aStream storeObject: sf. ^sf! ! !String methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:34'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text string is the receiver." ^Paragraph withText: self asText style: aTextStyle! ! !String methodsFor: 'converting' stamp: 'ssa 9/7/2009 09:29'! asSmalltalkObject ^Compiler evaluate: self! ! !String methodsFor: 'converting' stamp: 'ssa 7/7/2010 20:26'! withoutFirst: n "Answer a string without my first n characters." ^self size > n ifFalse:[''] ifTrue:[self copyFrom: n+1 to: self size]! ! !String methodsFor: 'converting' stamp: 'ssa 4/20/2010 15:52'! withoutLast: n "Answer a string without my last n characters." ^self size > n ifFalse:[''] ifTrue:[self copyFrom: 1 to: self size-n]! ! !String methodsFor: 'printing' stamp: ''! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self! ! !String methodsFor: 'user interface' stamp: 'ssa 1/21/2010 11:47'! buttonIt " 'Display reverse' buttonIt " "launch a button to evaluate this string" | topView someCode extent | someCode _ self. extent _ (someCode asText asDisplayText extent + (30@20)) max: 80@30. topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: extent . topView maximumSize: extent. topView addSubView: (RVMButtonView label: someCode action:[Compiler evaluate: someCode]). topView controller open! ! !String class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream | anObject | anObject _ aStream read: self. aStream storeObject: anObject. ^anObject! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/3/98 22:50'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" ^ 1 to: 0 "null selection"! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! classOrganizer "Answer the value of classOrganizer" classOrganizer isNil ifTrue:[self classOrganizer: nil]. ^ classOrganizer! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! classOrganizer: anObject "Set the value of classOrganizer" classOrganizer _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:40'! lastClassSelected "Answer the value of lastClassSelected" lastClassSelected isNil ifTrue:[self lastClassSelected: self selectedClassOrMetaClass]. ^ lastClassSelected! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! lastClassSelected: anObject "Set the value of lastClassSelected" lastClassSelected _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! metaClassOrganizer "Answer the value of metaClassOrganizer" metaClassOrganizer isNil ifTrue:[self metaClassOrganizer: nil]. ^ metaClassOrganizer! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! metaClassOrganizer: anObject "Set the value of metaClassOrganizer" metaClassOrganizer _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! systemOrganizer "Answer the value of systemOrganizer" systemOrganizer isNil ifTrue:[self systemOrganizer: nil]. ^ systemOrganizer! ! !Browser methodsFor: 'class functions' stamp: 'ssa 8/27/2009 05:09'! createInstVarAccessors "Create getters and setters for all inst vars defined at the level of the current class selection, except do NOT clobber or override any selectors already understood by the instances of the selected class" | aClass newMessage setter | (aClass _ self selectedClassOrMetaClass) ifNotNil: [aClass instVarNames do: [:aName | (aClass canUnderstand: aName asSymbol) ifFalse: [newMessage _ aName, ' "Answer the value of ', aName, '" ',aName,' isNil ifTrue:[self ',aName,': nil]. ^ ', aName. aClass compile: newMessage classified: 'accessing' notifying: nil]. (aClass canUnderstand: (setter _ aName, ':') asSymbol) ifFalse: [newMessage _ setter, ' anObject "Set the value of ', aName, '" ', aName, ' _ anObject'. aClass compile: newMessage classified: 'accessing' notifying: nil]]]. self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged. self selectMessageCategoryNamed:'accessing'! ! !Browser methodsFor: 'class list' stamp: 'ssa 9/9/2009 09:03'! classListIndex: anInteger "Set anInteger to be the index of the current class selection." | className | classListIndex _ anInteger. self lastClassSelected: self selectedClassOrMetaClass. self setClassOrganizer. messageCategoryListIndex _ 0. messageListIndex _ 0. self classCommentIndicated ifTrue: [] ifFalse: [self editSelection: (anInteger = 0 ifTrue: [metaClassIndicated | (systemCategoryListIndex == 0) ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. contents _ nil. self selectedClass isNil ifFalse: [className _ self selectedClass name. (RecentClasses includes: className) ifTrue: [RecentClasses remove: className]. RecentClasses addFirst: className. RecentClasses size > 16 ifTrue: [RecentClasses removeLast]]. self changed: #classSelectionChanged. self changed: #classCommentText. self changed: #classListIndex. "update my selection" self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged! ! !Browser methodsFor: 'initialize-release' stamp: 'ssa 9/10/2009 13:32'! setClass: aBehavior selector: aSymbol "Set the state of a new, uninitialized Browser." | isMeta aClass messageCatIndex | aBehavior ifNil: [^ self]. (aBehavior isKindOf: Metaclass) ifTrue: [ isMeta _ true. aClass _ aBehavior soleInstance] ifFalse: [ isMeta _ false. aClass _ aBehavior]. self selectCategoryForClass: aClass. self classListIndex: ( (SystemOrganization listAtCategoryNamed: self selectedSystemCategoryName) indexOf: aClass name). self metaClassIndicated: isMeta. aSymbol ifNil: [^ self]. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: (messageCatIndex > 0 ifTrue: [messageCatIndex + 1] ifFalse: [0]). messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ( (aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol).! ! !Browser methodsFor: 'message functions' stamp: 'ssa 9/9/2009 09:05'! defineMessage: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer true if compilation succeeds, false otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ self lastClassSelected "selectedClassOrMetaClass" compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ false]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ true! ! !Browser methodsFor: 'message functions' stamp: 'ssa 9/9/2009 09:06'! defineMessageFrom: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer the selector obtained if compilation succeeds, nil otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ (Parser new parseSelector: aString). (self metaClassIndicated and: [(self lastClassSelected "selectedClassOrMetaClass" includesSelector: selector) not and: [Metaclass isScarySelector: selector]]) ifTrue: ["A frist-time definition overlaps the protocol of Metaclasses" (self confirm: ((selector , ' is used in the existing class system. Overriding it could cause serious problems. Is this really what you want to do?') asText makeBoldFrom: 1 to: selector size)) ifFalse: [^nil]]. selector _ self lastClassSelected "selectedClassOrMetaClass" compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ nil]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ selector! ! !Browser methodsFor: 'metaclass' stamp: 'ssa 9/10/2009 08:45'! metaClassIndicated: trueOrFalse "Indicate whether browsing instance or class messages." metaClassIndicated _ trueOrFalse. self setClassOrganizer. systemCategoryListIndex > 0 ifTrue: [self editSelection: (classListIndex = 0 ifTrue: [metaClassIndicated ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. messageCategoryListIndex _ 0. messageListIndex _ 0. contents _ nil. self changed: #classSelectionChanged. self changed: #messageCategoryList. self changed: #messageList. self changed: #contents. self changed: #annotation. self decorateButtons. self lastClassSelected: self selectedClassOrMetaClass. ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 8/28/2009 19:44'! fileContentsMenu: aMenu shifted: shifted "Construct aMenu to have items appropriate for the file browser's code pane, given the shift state provided" | shiftMenu services maybeLine extraLines | shifted ifTrue: [shiftMenu _ ParagraphEditor shiftedYellowButtonMenu. ^ aMenu labels: shiftMenu labelString lines: shiftMenu lineArray selections: shiftMenu selections]. fileName ifNotNil: [services _ OrderedCollection new. (#(briefHex briefFile needToGetBriefHex needToGetBrief) includes: brevityState) ifTrue: [services add: self serviceGet]. (#(fullHex briefHex needToGetFullHex needToGetBriefHex) includes: brevityState) ifFalse: [services add: self serviceGetHex]. maybeLine _ services size. (#('st' 'cs') includes: self suffixOfSelectedFile) ifTrue: [services addAll: (self servicesFromSelectorSpecs: #(fileIntoNewChangeSet: fileIn: browseChangesFile: browseFile:))]. (#('gif' 'jpg' 'bmp') includes: self suffixOfSelectedFile) ifTrue: [services halt addAll: (self servicesFromSelectorSpecs: #(importGraphic))]. extraLines _ OrderedCollection new. maybeLine > 0 ifTrue: [extraLines add: maybeLine]. services size > maybeLine ifTrue: [extraLines add: services size]. aMenu addServices: services for: self fullName extraLines: extraLines]. aMenu addList: { {'find...(f)' translated. #find}. {'find again (g)' translated. #findAgain}. {'set search string (h)' translated. #setSearchString}. #-. {'do again (j)' translated. #again}. {'undo (z)' translated. #undo}. #-. {'copy (c)' translated. #copySelection}. {'cut (x)' translated. #cut}. {'paste (v)' translated. #paste}. {'paste...' translated. #pasteRecent}. #-. {'do it (d)' translated. #doIt}. {'print it (p)' translated. #printIt}. {'inspect it (i)' translated. #inspectIt}. {'fileIn selection (G)' translated. #fileItIn}. #-. {'accept (s)' translated. #accept}. {'cancel (l)' translated. #cancel}. #-. {'more...' translated. #shiftedYellowButtonActivity}}. ^ aMenu ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 8/28/2009 19:14'! fileSelectedMenu: aMenu | firstItems secondItems thirdItems n1 n2 n3 services | firstItems _ self itemsForFile: self fullName. secondItems _ self itemsForAnyFile. thirdItems _ self itemsForNoFile. n1 _ firstItems size. n2 _ n1 + secondItems size. n3 _ n2 + thirdItems size. services _ firstItems, secondItems, thirdItems, self serviceAllFileOptions. services do: [ :svc | svc addDependent: self ]. ^ aMenu addServices2: services for: self extraLines: (Array with: n1 with: n2 with: n3) ! ! !FileList methodsFor: 'file list menu' stamp: 'BG 11/2/2003 21:04'! myServicesForFile: fullName suffix: suffix ^(FileStream isSourceFileSuffix: suffix) ifTrue: [ #() ] ifFalse: [ #() ]! ! !FileList class methodsFor: 'instance creation' stamp: 'ssa 8/22/2009 14:57'! open "Open a view of an instance of me on the default directory." "Added scrollingView to support Windoze - ssa" "FileList open" | dir aFileList topView volListView templateView fileListView fileContentsView | World ifNotNil: [^ self openAsMorph]. dir _ FileDirectory default. aFileList _ self new directory: dir. topView _ StandardSystemView new. topView model: aFileList; label: dir pathName; minimumSize: 200@200. topView borderWidth: 1. volListView _ PluggableListView on: aFileList list: #volumeList selected: #volumeListIndex changeSelected: #volumeListIndex: menu: #volumeMenu:. volListView autoDeselect: false. volListView window: (0@0 extent: 80@45). topView addSubView: volListView. templateView _ PluggableTextView on: aFileList text: #pattern accept: #pattern:. templateView scrollingView askBeforeDiscardingEdits: false. templateView window: (0@0 extent: 80@15). topView addSubView: templateView below: volListView. fileListView _ PluggableListView on: aFileList list: #fileList selected: #fileListIndex changeSelected: #fileListIndex: menu: #fileListMenu:. fileListView window: (0@0 extent: 120@60). topView addSubView: fileListView toRightOf: volListView. "fileListView scrollingView controller terminateDuringSelect: true. " "Pane to left may change under scrollbar" fileContentsView _ PluggableTextView on: aFileList text: #contents accept: #put: readSelection: #contentsSelection menu: #fileContentsMenu:shifted:. fileContentsView window: (0@0 extent: 200@140). topView addSubView: fileContentsView below: templateView. topView controller open. ! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'ssa 9/10/2009 13:34'! setClass: aBehavior selector: aSymbol "Set the state of a new, uninitialized Browser." | isMeta aClass messageCatIndex | aBehavior ifNil: [^ self]. (aBehavior isKindOf: Metaclass) ifTrue: [ isMeta _ true. aClass _ aBehavior soleInstance] ifFalse: [ isMeta _ false. aClass _ aBehavior]. self selectCategoryForClass: aClass. self selectClass: aClass. self metaClassIndicated: isMeta. aSymbol ifNil: [^ self]. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: (messageCatIndex > 0 ifTrue: [messageCatIndex + 1] ifFalse: [0]). messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ( (aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol).! ! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'ssa 3/1/2010 13:54'! newFor: aClass "Open a new HierarchyBrowser on the given class" self newFor: aClass labeled: nil "HierarchyBrowser newFor: Boolean"! ! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'ssa 3/1/2010 13:54'! newFor: aClass labeled: aLabel "Open a new HierarchyBrowser on the given class, using aLabel as the window title." | newBrowser | newBrowser _ self new initHierarchyForClass: aClass. Browser openBrowserView: (newBrowser openSystemCatEditString: nil) label: (aLabel isNil ifTrue:[newBrowser labelString]ifFalse:[aLabel]) "HierarchyBrowser newFor: Boolean labeled: 'Testing'"! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:29'! childrenOf: anObject ^anObject subobjects! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection "Answer the value of currentSelection" currentSelection isNil ifTrue:[self currentSelection: nil]. ^ currentSelection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection: anObject "Set the value of currentSelection" currentSelection _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 3/1/2010 14:12'! getClassList | prev classes | classes _ OrderedCollection new. centralClass allSuperclasses reverseDo: [:aClass | classes add: aClass]. classes add: centralClass. centralClass subclassesDo: [:aClass| classes add: aClass]. prev _nil. ^(classes collect:[:cls| prev _ ClassHierarchyExplorerWrapper with: cls name: cls name model: self parent: prev]) asArray! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:02'! initializeList self list do:[:each| self levels at: each put:0]! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levelOf: anItem ^self levels at: anItem ifAbsent:[0]! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levels "Answer the value of levels" levels isNil ifTrue:[self levels: Dictionary new]. ^ levels! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:00'! levels: anObject "Set the value of levels" levels _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:39'! list "Answer the value of list" list isNil ifTrue:[self list: (OrderedCollection with:self subject )]. ^ list! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:36'! list: anObject "Set the value of list" list _ anObject asOrderedCollection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser "Answer the value of myBrowser" myBrowser isNil ifTrue:[self myBrowser: nil]. ^ myBrowser! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser: anObject "Set the value of myBrowser" myBrowser _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems "Answer the value of openItems" openItems isNil ifTrue:[self openItems: Set new]. ^ openItems! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems: anObject "Set the value of openItems" openItems _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 13:28'! progenyOf: anObject | all | all _ (self childrenOf: anObject)copy. all isEmpty ifTrue:[^all]. all copy do:[:each| all addAll: (self progenyOf: each)]. ^all ! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:18'! selection "Answer the value of selection" selection isNil ifTrue:[self selection: nil]. ^ selection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 17:15'! selection: anObject "Set the value of selection" selection _ anObject . ! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 7/7/2010 12:40'! subject "Answer the value of subject" subject isNil ifTrue:[self subject: Object]. ^ subject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 08:25'! subject: anObject "Set the value of subject" subject _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'user interfacing' stamp: 'ssa 3/1/2010 14:23'! openSystemCatEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers. The top list view is of the currently selected system class category--a single item list." | systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView y annotationPane underPane optionalButtonsView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" systemCategoryListView _ PluggableListView on: self list: #systemCategorySingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #systemCatSingletonMenu: keystroke: #systemCatSingletonKey:from:. systemCategoryListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: systemCategoryListView. classListView _ LyPluggableOutlineView on: self list: #getClassList selected: #currentSelection changeSelected: #currentSelection: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 67 @ 62). topView addSubView: classListView below: systemCategoryListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView controller terminateDuringSelect: true. messageCategoryListView window: (0 @ 0 extent: 66 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. switchView _ self buildInstanceClassSwitchView. switchView window: switchView window viewport: (classListView viewport bottomLeft corner: messageCategoryListView viewport bottomLeft). switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView menuTitleSelector: #messageListSelectorTitle. messageListView window: (0 @ 0 extent: 67 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: switchView. y _ 110 - 12 - self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [y _ 110 - 12. underPane _ switchView]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(getClassList messageCategoryList messageList). ^ topView! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:42'! inspectSelection self selection inspect! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:47'! menu: aMenu aMenu add: 'inspect' action: #inspectSelection. aMenu add: 'outline' action: #outlineSelection. ^ aMenu! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:43'! outlineSelection self selection outline! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'RAA 4/7/1999 16:53'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 13:02'! hasChildren: anObject ^(self childrenOf: anObject) notEmpty ! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 14:07'! hideChildrenOfSelection | kids | self openItems remove: self selection. kids _ self progenyOf: self selection. kids do:[:each| self levels removeKey: each ifAbsent:[]. self openItems remove: each ifAbsent:[]]. self list removeAll: kids ifAbsent:[] ! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 11:42'! isOpen: anItem ^self openItems includes: anItem! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 12:10'! showChildrenOfSelection | kids nextLevel | self openItems add: self selection. nextLevel _ (self levelOf: self selection) + 1. kids _ self childrenOf: self selection. kids isEmpty ifTrue:[^self error:'should never try to show children of an childless object']. kids do:[:each| self levels at: each put: nextLevel]. self list addAll: kids after: self selection! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/10/2009 07:30'! toggleSelection self selection isNil ifTrue:[^self]. (self isOpen: self selection) ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !HierarchyOutlineBrowser methodsFor: 'arrow keys' stamp: 'ssa 9/9/2009 14:47'! arrowKey: aChar from: view "Process the up and down arrows in a list pane. Note that the listView tells us what index variable, how to get the list, and how to move the index. Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | (#(1 4 11 12 30 31) includes: (keyEvent _ aChar asciiValue)) ifFalse: [ ^ self]. oldSelection := view getCurrentSelectionIndex. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view numSelectionsInView. "get this exactly??" keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [self okToChange ifTrue: [view changeModelSelection: nextSelection. "view controller moveMarker"]] ! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:22'! genericMenu: aMenu aMenu add: 'no menu yet' target: self selector: #yourself. ^aMenu! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:44'! getCurrentSelection ^currentSelection! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:46'! noteNewSelection: x currentSelection _ x. self changed: #getCurrentSelection. currentSelection ifNil: [^self]. currentSelection sendSettingMessageTo: self. ! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:47'! update: aSymbol aSymbol == #hierarchicalList ifTrue: [ ^self changed: #getList ]. super update: aSymbol! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionIndex: anObject "Set the value of selectionIndex" selectionIndex _ anObject! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionUpdateTime "Answer the value of selectionUpdateTime" selectionUpdateTime isNil ifTrue:[self selectionUpdateTime: nil]. ^ selectionUpdateTime! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionUpdateTime: anObject "Set the value of selectionUpdateTime" selectionUpdateTime _ anObject! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! timeOfLastListUpdate: anObject "Set the value of timeOfLastListUpdate" timeOfLastListUpdate _ anObject! ! !Inspector methodsFor: 'selecting' stamp: 'tk 4/10/1998 17:57'! selection "The receiver has a list of variables of its inspected object. One of these is selected. Answer the value of the selected variable." | basicIndex | selectionIndex = 0 ifTrue: [^ '']. selectionIndex = 1 ifTrue: [^ object]. selectionIndex = 2 ifTrue: [^ object longPrintString]. (selectionIndex - 2) <= object class instSize ifTrue: [^ object instVarAt: selectionIndex - 2]. basicIndex _ selectionIndex - 2 - object class instSize. (object basicSize <= (self i1 + self i2) or: [basicIndex <= self i1]) ifTrue: [^ object basicAt: basicIndex] ifFalse: [^ object basicAt: object basicSize - (self i1 + self i2) + basicIndex]! ! !Inspector methodsFor: 'selecting' stamp: 'ssa 7/7/2010 19:29'! selectionPrintString | text nm | selectionUpdateTime _ [text _ [(RVMTester printPrefixFor: self selection),(self selection printString)] on: Error do: [nm _ self selectionIndex < 3 ifTrue: ['self'] ifFalse: [self selectedSlotName]. text _ ('') asText. text addAttribute: TextColor red from: 1 to: text size. text]] timeToRun. ^ text! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 1/6/2010 20:21'! exploreSelection "Open an explorer on the receiver's model's currently selected object." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ^ self selection explore! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 7/7/2010 13:04'! fieldListMenu: aMenu "Arm the supplied menu with items for the field-list of the receiver" aMenu addList: #( ('inspect (i)' inspectSelection) ('explore (e)' exploreSelection) ('locate' locateSelection)). self addCollectionItemsTo: aMenu. aMenu addList: #( - ('method refs to this inst var' referencesToSelection) ('methods storing into this inst var' defsOfSelection) ('objects pointing to this value' objectReferencesToSelection) ('chase pointers' chasePointers) - ('browse full (b)' browseMethodFull) ('browse class' browseClass) ('browse hierarchy' classHierarchy) ('browse protocol (p)' browseFullProtocol) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' classVarRefs) ('class variables' browseClassVariables) ('class refs (N)' browseClassRefs) - ('copy name (c)' copyName) ('basic inspect' inspectBasic)). ^ aMenu " - ('alias for this value' aliasForValue) ('watcher for this slot' watcherForSlot)" ! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 7/7/2010 13:04'! inspectorKey: aChar from: view "Respond to a Command key issued while the cursor is over my field list" aChar == $i ifTrue: [^ self selection inspect]. aChar == $e ifTrue: [^ self selection explore]. aChar == $b ifTrue: [^ self browseMethodFull]. aChar == $h ifTrue: [^ self classHierarchy]. aChar == $c ifTrue: [^ self copyName]. aChar == $p ifTrue: [^ self browseFullProtocol]. aChar == $N ifTrue: [^ self browseClassRefs]. "aChar == $t ifTrue: [^ self tearOffTile]." aChar == $v ifTrue: [^ self viewerForValue]. ^ self arrowKey: aChar from: view! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 11/16/2008 01:53'! locateSelection "Open a locator on the receiver's model's currently selected object." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ^ self selection locate! ! !DictionaryInspector methodsFor: 'menu' stamp: 'ssa 1/6/2010 20:24'! dictionaryMenu: aMenu "Set up the key-list menu for a dictionary inspector" aMenu title: 'Dictionary key'. ^ aMenu addList: #( ('inspect' inspectSelection) ('explore' exploreSelection) ('copy name' copyName) ('references' selectionReferences) ('objects pointing to this value' objectReferencesToSelection) ('senders of this key' sendersOfSelectedKey) - ('refresh view' calculateKeyArray) - ('add key' addEntry) ('rename key' renameEntry) ('remove' removeSelection) - ('basic inspect' inspectBasic))! ! !Inspector class methodsFor: 'instance creation' stamp: 'ssa 8/26/2009 11:23'! newFrom: anInspector "Use anInspector's contents for that of a new instance of me" | in | in _ self new. in contents: anInspector contents. in myDependents: anInspector myDependents. in dependents do:[:each| (each respondsTo:#model:) ifTrue:[each model: in]]. in selectionIndex: anInspector selectionIndex. in timeOfLastListUpdate: anInspector timeOfLastListUpdate. in selectionUpdateTime: anInspector selectionUpdateTime. in object: anInspector object. ^in! ! !Inspector class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:43'! openOn: anObject withEvalPane: withEval withLabel: label valueViewClass: valueViewClass | topView inspector listView valueView evalView v | inspector _ self inspect: anObject. topView _ StandardSystemView new model: inspector. topView borderWidth: 1. listView _ PluggableListView on: inspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. (inspector isMemberOf: DictionaryInspector) ifTrue: [listView menu: #dictionaryMenu:]. listView window: (0 @ 0 extent: 40 @ 40). topView addSubView: listView. valueView _ valueViewClass new. "PluggableTextView or PluggableFormView" (valueView respondsTo: #getText) ifTrue: [ valueView on: inspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:]. (valueViewClass inheritsFrom: FormView) ifTrue: [ valueView model: inspector]. v_ "MSWScrollBarView on:" valueView. v window: (0 @ 0 extent: 75 @ 40). topView addSubView: v toRightOf: listView. withEval ifTrue: [evalView _ PluggableTextView new on: inspector text: #trash accept: #trash: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. evalView window: (0 @ 0 extent: 115 @ 20). evalView askBeforeDiscardingEdits: false. topView addSubView: evalView below: listView]. topView label: label. topView minimumSize: 180 @ 120. topView setUpdatablePanesFrom: #(fieldList). topView controller open! ! !PluggableFileList methodsFor: 'StandardFileMenu' stamp: 'ssa 4/19/2010 20:06'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: Sensor cursorPoint! ! !PluggableFileList class methodsFor: 'StandardFileMenu' stamp: 'ssa 10/18/2008 23:10'! oldFileMenu: aDirectory withPattern: aPattern "For compatibility with StandardFileMenu for now, answer a StandardFileMenuResult" ^(self getFilePathNameDialog) resultBlock: self sfmResultBlock; directory: aDirectory; pattern: aPattern; yourself! ! !Symbol methodsFor: 'converting' stamp: 'ssa 5/11/2010 15:14'! asKeyword ^self last == $: ifTrue:[self] ifFalse:[(self copyWith:$:) asSymbol]! ! !Symbol class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 08:08'! readFrom: aStream "Correctly read a Symbol from aStream." | string | aStream skipSeparators. ^(aStream peekFor: $#) ifTrue: [(aStream upTo: Character space) asSymbol] ifFalse: [string _ super readFrom: aStream. (aStream next: 9) = ' asSymbol' ifTrue: [string asSymbol] ifFalse: [self error: 'This ain''t no ', self class name]]! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:25'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | "Simulation guard" topView _ self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor thisProcess suspend. ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:26'! snapshot: save andQuit: quit embedded: embeddedFlag "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. The latter part of this method runs when resuming a previously saved image. The resume logic checks for a document file to process when starting up." | resuming msg sourceLink | Object flushDependents. Object flushEvents. save & (SourceFiles at: 2) notNil ifTrue: [msg _ (quit ifTrue: ['----QUIT----'] ifFalse: ['----SNAPSHOT----']) , Date dateAndTimeNow printString, ' ', (FileDirectory default localNameFor: self imageName). sourceLink _ ' priorSource: ' , LastQuitLogPosition printString. self assureStartupStampLogged. (SourceFiles at: 2) safelyDo: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position. self logChange: msg , sourceLink. ]. Transcript cr; show: msg]. self processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [self clearExternalObjects]. self processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !SystemDictionary methodsFor: 'window preferences' stamp: 'ssa 11/30/2009 17:48'! recolorWindows "Smalltalk recolorWindows" "Let the user define the color scheme for all my windows" | menu choice color | menu _ PopUpMenu labels:'one color for all windows\standard color palette' withCRs. choice _ menu startUp. choice = 0 ifTrue:[^self]. choice = 1 ifTrue:[color _ Color fromUser. Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| color]]. choice = 2 ifTrue:[ Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| Preferences windowColorFor: obj class name]]. self updateAllWindowColors! ! !SystemDictionary methodsFor: 'window preferences' stamp: 'ssa 11/30/2009 17:48'! updateAllWindowColors "Smalltalk updateAllWindowColors" Cursor wait showWhile:[ View allSubInstances do:[:v| v backgroundColor: v model defaultBackgroundColor]. ScheduledControllers unCacheWindows;restore]! ! !Text methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:35'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text is the receiver." ^Paragraph withText: self style: aTextStyle! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:00'! bold "Force this whole text to be bold." string size = 0 ifTrue: [^self]. self makeBoldFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 8/22/2009 17:47'! emphasizeFrom: start to: stop with: emphasis "Set the emphasis for characters in the interval start-stop." runs _ runs copyReplaceFrom: start to: stop with: (RunArray new: stop - start + 1 withAll: emphasis)! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:01'! italic "Force this whole text to be italic." string size = 0 ifTrue: [^self]. self makeItalicFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:01'! makeItalicFrom: start to: stop ^ self addAttribute: TextEmphasis italic from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/27/2009 01:23'! makeUnderlineFrom: start to: stop ^ self addAttribute: TextEmphasis underline from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:03'! makeUnderlinedFrom: start to: stop ^ self addAttribute: TextEmphasis underlined from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/27/2009 01:23'! underline "Force this whole text to be underline." string size = 0 ifTrue: [^self]. self makeUnderlineFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:03'! underlined "Force this whole text to be underlined." string size = 0 ifTrue: [^self]. self makeUnderlinedFrom: 1 to: string size! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 01:09'! font: aFont self addAttribute: (TextFontReference toFont: aFont)! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 01:28'! fontName: fname pointSize: ptsize " ('Hello World' asText fontName: #Accuny pointSize: 24) asParagraph display" | style sizes findex font availableSize | style _ TextStyle named:fname. sizes _ TextStyle fontPointSizesFor: fname. availableSize _ sizes detect:[:each| each >= ptsize] ifNone:[sizes last]. findex _ sizes indexOf: availableSize. font _ style fontAt:findex. self font: font "Accuat #(18 ) Accujen #(9 10 12 14 18 24 ) Accula #(12 24 ) Accumon #(9 10 12 ) Accuny #(9 10 12 14 18 24 ) Accusf #(18 ) Accushi #(12 ) Accuve #(12 14 ) Atlanta #(11 22 ) DefaultFixedTextStyle #(11 22 ) DefaultTextStyle #(9 10 12 14 18 24 )"! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 00:56'! fontNumber: anInteger self addAttribute: (TextFontChange fontNumber:anInteger)! ! !TextBlockDoIt methodsFor: 'accessing' stamp: 'ssa 9/15/2009 09:37'! actionBlock "Answer the value of actionBlock" actionBlock isNil ifTrue:[self actionBlock: [self notify:'default action block']]. ^ actionBlock! ! !TextBlockDoIt methodsFor: 'accessing' stamp: 'ssa 9/15/2009 09:36'! actionBlock: anObject "Set the value of actionBlock" actionBlock _ anObject! ! !TextBlockDoIt methodsFor: 'activating' stamp: 'ssa 9/15/2009 09:38'! actOnClickFor: anObject self actionBlock value. ^true! ! !TextStyle class methodsFor: 'user interface' stamp: 'ssa 9/4/2009 21:20'! mvcPromptForFont: aPrompt "MVC Only!! prompt for a font and if one is provided, send it to aTarget using a message with selector aSelector." | aMenu aChoice aStyle namesAndSizes | "TextStyle mvcPromptForFont: 'Choose system font style' " aMenu _ CustomMenu new. self actualTextStyles keys do: [:styleName | aMenu add: styleName action: styleName]. aChoice _ aMenu startUpWithCaption: aPrompt. aChoice ifNil: [^ self]. aMenu _ CustomMenu new. aStyle _ self named: aChoice. (namesAndSizes _ aStyle fontNamesWithPointSizes) do: [:aString | aMenu add: aString action: aString]. aChoice _ aMenu startUpWithCaption: nil. aChoice ifNil: [^ self]. ^aStyle fontAt: (namesAndSizes indexOf: aChoice). ! ! !TextStyle class methodsFor: 'user interface' stamp: 'ssa 9/4/2009 21:11'! mvcPromptForStyle: aPrompt andSendTo: aTarget withSelector: aSelector "MVC Only!! prompt for a font and if one is provided, send it to aTarget using a message with selector aSelector." | aMenu aChoice aStyle namesAndSizes aFont | "TextStyle mvcPromptForFont: 'Choose system font style' andSendTo: TextStyle withSelector: #setSystemFontTo:" aMenu _ CustomMenu new. self actualTextStyles keys do: [:styleName | aMenu add: styleName action: styleName]. aChoice _ aMenu startUpWithCaption: aPrompt. aChoice ifNil: [^ self]. aMenu _ CustomMenu new. aStyle _ self named: aChoice. (namesAndSizes _ aStyle fontNamesWithPointSizes) do: [:aString | aMenu add: aString action: aString]. aChoice _ aMenu startUpWithCaption: nil. aChoice ifNil: [^ self]. aTarget perform: aSelector with: aStyle! ! !TranscriptStream methodsFor: 'Ly*' stamp: 'dmu 3/22/2010 02:58'! resetSemaphore AccessSema signal! ! !TranscriptStream methodsFor: '*RVM' stamp: 'ssa 3/24/2010 14:03'! showInConsole ^self class showInConsole! ! !TranscriptStream methodsFor: '*RVM' stamp: 'ssa 3/24/2010 14:04'! showInConsole: aBoolean ^self class showInConsole: aBoolean! ! !TranscriptStream methodsFor: '*RVM' stamp: 'ssa 7/5/2010 13:02'! showInConsoleSwitch "Transcript showInConsoleSwitch demo" ^RVMCheckBoxView on: nil label: 'Show Transcript in Console' checkState: [Transcript showInConsole] whenChecked: [Transcript showInConsole: true] whenUnchecked: [Transcript showInConsole: false].! ! !TranscriptStream methodsFor: '*RVM' stamp: 'ssa 3/24/2010 14:04'! toggleShowInConsole self class toggleShowInConsole! ! !TranscriptStream class methodsFor: '*RVM' stamp: 'ssa 3/24/2010 13:58'! showInConsole "A flag to support mirroring the transcript in the RVM console" ShowInConsole isNil ifTrue:[ShowInConsole _ false]. ^ShowInConsole! ! !TranscriptStream class methodsFor: '*RVM' stamp: 'ssa 3/24/2010 13:58'! showInConsole: aBoolean "A flag to support mirroring the transcript in the RVM console" ShowInConsole _ aBoolean! ! !TranscriptStream class methodsFor: '*RVM' stamp: 'ssa 3/24/2010 13:59'! toggleShowInConsole self showInConsole: self showInConsole not! ! !Transcripter methodsFor: 'command line' stamp: 'ssa 7/7/2010 19:30'! readEvalPrint | line okToRevert | Sensor flushKeyboard. okToRevert _ true. [#('quit' 'exit' 'done' 'restart' 'refresh' 'revert') includes: (line _ self request: '>') ] whileFalse: [line = 'refresh' ifTrue:[ScheduledControllers restore halt] ifFalse:[line = 'restart' ifTrue:[ProcessorScheduler removeAllPossible] ifFalse:[line = 'revert' ifTrue: [okToRevert ifTrue: [Utilities revertLastMethodSubmission. self cr; show: 'reverted: ' , Utilities mostRecentlySubmittedMessage. okToRevert _ false] ifFalse: [self cr; show: 'Only one level of revert currently supported']] ifFalse: [self cr; show: ([Compiler evaluate: line] ifError: [:err :ex | err])]]]]! ! !Transcripter class methodsFor: 'utilities' stamp: 'ssa 6/11/2010 13:29'! emergencyEvaluator (Transcripter newInFrame: (0@0 corner: 320@200)) show: 'Type ''revert'' to revert your last method change. Type ''restart'' to restart the processor scheduler. Type ''refresh'' to refresh the display. Type ''exit'' to exit the emergency evaluator.'; readEvalPrint! ! !True methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfTrue self halt! ! !True class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream aStream storeObject: true. ^true! ! !UndefinedObject methodsFor: 'printing' stamp: ''! archiveOn: aStream aStream storeClass: self class! ! !UndefinedObject class methodsFor: 'instance creation' stamp: ''! dearchiveFrom: aStream ^nil! ! !UnhandledError methodsFor: 'priv handling' stamp: 'dmu 11/25/2008 00:25'! devDefaultAction Processor thisProcess debug: exception signalerContext title: exception description! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'ssa 1/21/2010 12:17'! exploreViewFromUser ScheduledControllers screenController exploreViewFromUser! ! !Utilities class methodsFor: 'finding pointers' stamp: 'ar 7/16/2005 19:56'! pointersTo: anObject "Find all occurrences in the system of pointers to the argument anObject." "(Utilities pointersTo: Browser) inspect." ^ self pointersTo: anObject except: #() ! ! !Utilities class methodsFor: 'finding pointers' stamp: 'dmu 3/23/2010 12:31'! pointersTo: anObject except: objectsToExclude "Find all occurrences in the system of pointers to the argument anObject. Remove objects in the exclusion list from the results. " | results anObj | Transcript cr; show: 'Calling garbageCollect from pointersTo:except:'. Smalltalk garbageCollect. "big collection shouldn't grow, so it's contents array is always the same" results := OrderedCollection new: 1000. "allObjectsDo: is expanded inline to keep spurious method and block contexts out of the results" anObj := self someObject. [0 == anObj] whileFalse: [ anObj isInMemory ifTrue: [ (anObj pointsTo: anObject) ifTrue: [ "exclude the results collector and contexts in call chain" (anObj ~~ results collector and: [anObj ~~ objectsToExclude and: [anObj ~~ thisContext and: [anObj ~~ thisContext sender and: [anObj ~~ thisContext sender sender]]]]) ifTrue: [results add: anObj]]]. anObj := anObj nextObject]. objectsToExclude do: [:obj | results removeAllSuchThat: [:el | el == obj]]. ^ results asArray! ! !Utilities class methodsFor: 'finding pointers' stamp: 'ar 7/16/2005 19:56'! pointersToItem: index of: anArray "Find all occurrences in the system of pointers to the given element of the given array. This is useful for tracing up a pointer chain from an inspector on the results of a previous call of pointersTo:. To find out who points to the second element of the results, one would evaluate: Utilities pointersToItem: 2 of: self in the inspector." ^ self pointersTo: (anArray at: index) except: (Array with: anArray)! ! !View methodsFor: 'initialize-release' stamp: 'ssa 11/30/2009 17:50'! setDefaultBackgroundColor self backgroundColor: self model defaultBackgroundColor! ! !View methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:19'! isRVMView ^false! ! !View methodsFor: 'subView access' stamp: 'ssa 1/1/1970 12:58'! allSubViews "Answer the receiver's collection of subViews and their subViews recursively." | all | all _ OrderedCollection new. all addAll: self subViews. self subViews do:[:sub| all addAll: sub allSubViews]. ^all! ! !View methodsFor: 'subView access' stamp: 'ssa 10/19/2008 00:00'! subViewsSatisfying: aBlock "Return the subviews that satisfy aBlock, or #() if none does. 1/31/96 sw" ^ subViews select: [:aView | aBlock value: aView]! ! !View methodsFor: 'lock access' stamp: ''! unlock "Unlock the receiver and all of its subViews (see View|isUnlocked). This has the effect of forcing the display transformation (see View|displayTransformation) and inset display box (see View|insetDisplayBox) of the receiver and all its subViews to be recomputed the next time they are referenced. The locking and unlocking of a View is handled automatically by the internal methods of the View, but can also be done explicitly if desired." "Added a guard clause to protect against empty subview collections. This is one reason why lazy initialization and consistent use of accessor methods is better than direct access. - ssa 2/27/98 11:26" self isUnlocked ifTrue: [^self]. displayTransformation _ nil. insetDisplayBox _ nil. subViews isNil ifFalse:[subViews do: [:aSubView | aSubView unlock]]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:54'! addSubView: aSubView above: lowerView "Adds aView (see View|addSubView:) so that it lies above topView." "ssa - added a hack to allow nil lowerView" lowerView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport bottomLeft with: lowerView viewport topLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:55'! addSubView: aSubView below: lowerView "Add the argument, aSubView, (see View|addSubView:) so that it lies below the view, topView." "ssa - added a hack to allow nil lowerView" lowerView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topLeft with: lowerView viewport bottomLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:55'! addSubView: aSubView toLeftOf: rightView "Adds aView (see addSubView:) so that it lies to the right of rightView." "ssa - added a hack to allow nil rightView" rightView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topRight with: rightView viewport topLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:56'! addSubView: aSubView toRightOf: leftView "Add the argument, aSubView, (see View|addSubView:) so that it lies to the right of the view, leftView." "ssa - added a hack to allow nil leftView" leftView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topLeft with: leftView viewport topRight]! ! !View methodsFor: 'miscellaneous' stamp: 'ssa 10/8/2008 17:54'! stretchFrame: newFrameBlock startingWith: startFrame "Track the outline of a newFrame as long as mouse drags it. Maintain max and min constraints throughout the drag" | frame newFrame click delay | delay _ Delay forMilliseconds: 10. frame _ startFrame origin extent: ((startFrame extent min: self maximumSize) max: self minimumSize). Display border: frame width: 2 rule: Form reverse fillColor: Color gray. click _ false. [click and: [Sensor noButtonPressed]] whileFalse: ["delay wait." click _ click | Sensor anyButtonPressed. newFrame _ newFrameBlock value: frame. newFrame _ newFrame topLeft extent: ((newFrame extent min: self maximumSize) max: self minimumSize). newFrame = frame ifFalse: [Display border: frame width: 2 rule: Form reverse fillColor: Color gray. Display border: newFrame width: 2 rule: Form reverse fillColor: Color gray. frame _ newFrame]]. Display border: frame width: 2 rule: Form reverse fillColor: Color gray. ^ frame! ! !View methodsFor: 'scrolling support' stamp: ''! percentContentVisible "Answer the percent of my content that is visible. ssa 12/5/97 15:37" ^self visibleContentHeight / self totalContentHeight! ! !View methodsFor: 'scrolling support' stamp: ''! percentPrecedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" ^0.0! ! !View methodsFor: 'scrolling support' stamp: ''! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" ^0.0! ! !View methodsFor: 'scrolling support' stamp: ''! percentVisibleContent "Answer the percent of my content that is visible. ssa 12/5/97 15:37" ^self totalContentHeight = 0 ifTrue:[0.0] ifFalse:[self visibleContentHeight / self totalContentHeight]! ! !View methodsFor: 'scrolling support' stamp: ''! totalContentHeight "Answer the height of my content, visible or not. ssa 12/5/97 15:04" ^100 / self unitContentHeight! ! !View methodsFor: 'scrolling support' stamp: ''! unitContentHeight "Answer the unit height of my content. ssa 12/5/97 15:04" ^10.0! ! !View methodsFor: 'scrolling support' stamp: ''! visibleContentHeight "Answer the height of my visible content. ssa 12/5/97 15:04" ^100 / self unitContentHeight! ! !View methodsFor: 'demonstrating' stamp: 'ssa 11/27/2008 10:05'! demo "Add me to a system view and open me on the desktop" self demoSized: self minimumSize! ! !View methodsFor: 'demonstrating' stamp: 'ssa 11/27/2008 10:05'! demoSized: anExtent "Add me to a system view and open me on the desktop" | topView | topView := StandardSystemView new. topView borderWidth:1. topView minimumSize: anExtent. topView addSubView: self . topView label: self class name,' demo'. topView controller open! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! borderColor "Answer the value of borderColor" borderColor isNil ifTrue:[self borderColor: self foregroundColor]. ^ borderColor! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! borderColor: anObject "Set the value of borderColor" borderColor _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! boundingBox: anObject "Set the value of boundingBox" boundingBox _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! displayTransformation: anObject "Set the value of displayTransformation" displayTransformation _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! insetDisplayBox: anObject "Set the value of insetDisplayBox" insetDisplayBox _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! insideColor "Answer the value of insideColor" insideColor isNil ifTrue:[self insideColor: nil]. ^ insideColor! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! subViews: anObject "Set the value of subViews" subViews _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! viewport: anObject "Set the value of viewport" viewport _ anObject! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:52'! moveBy: delta "Move me delta left in my superView" | scaledDelta | scaledDelta _ self viewport width / self insetDisplayBox width * delta. self transformUsing:[:ovp| ovp moveBy: scaledDelta]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveDown "Move me 10 pixels down in my superView" self moveBy:(0@10)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:50'! moveFrom: oldBox "Move me to ensure I refect my window/viewport" self uncacheBits. self displayEmphasized. self moved. "In case its model wishes to take note." (oldBox areasOutside: self windowBox) do: [:rect | ScheduledControllers restore: rect]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveLeft "Move me 10 pixels left in my superView" self moveBy:(-10@0)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveRight "Move me 10 pixels right in my superView" self moveBy:(10@0)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveUp "Move me 10 pixels up in my superView" self moveBy:(0@-10)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:55'! narrower "Make me 5% narrower in my superView" self transformUsing:[:ovp| ovp expandBy:(ovp width*0.05)negated@0]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:57'! shorter "Make me 5% shorter in my superView" self transformUsing:[:ovp| ovp expandBy:0@(ovp height*0.05)negated]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:57'! taller "Make me 5% taller in my superView" self transformUsing:[:ovp| ovp expandBy:0@(ovp height*0.05)]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:43'! transformUsing: aBlock "self transformUsing: [:oldViewport | ...return new viewport... ] " "Change my viewport and update me on the display" | ovp nvp ow | ovp _ self viewport. ow _ self getWindow. nvp _ aBlock value:ovp. self window: self window viewport: nvp. self moveFrom: ow. self unlock.! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:55'! wider "Make me 5% wider in my superView" self transformUsing:[:ovp| ovp expandBy:(ovp width*0.05)@0]! ! !DisplayTextView class methodsFor: 'examples' stamp: 'ssa 9/4/1998 17:29'! example2 "Create a standarad system view with two parts, one editable, the other not." "Modified to support Windoze - ssa" | topView aDisplayTextView | topView _ StandardSystemView new. topView label: 'Text Editor'. aDisplayTextView _ MSWScrollBarView on: (self new model: 'test string label' asDisplayText). aDisplayTextView scrollingView controller: NoController new. aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidthLeft: 2 right: 0 top: 2 bottom: 2. topView addSubView: aDisplayTextView. aDisplayTextView _ MSWScrollBarView on: (self new model: 'test string' asDisplayText). aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidth: 2. topView addSubView: aDisplayTextView align: aDisplayTextView viewport topLeft with: topView lastSubView viewport topRight. topView controller open "DisplayTextView example2"! ! !DisplayTextView class methodsFor: 'examples' stamp: ''! open: textOrString label: aLabel "Create a system view with a paragraph editor in it. 6/2/96 sw" "VIVA LA JUNTA!! Modified to use MSWScrollBarViews - ssa 12/11/97 12:00" | topView aDisplayTextView | aDisplayTextView _ MSWScrollBarView on: (DisplayTextView new model: textOrString asDisplayText). aDisplayTextView borderWidth: 2. topView _ StandardSystemView new. topView label: aLabel. topView addSubView: aDisplayTextView. topView controller open "DisplayTextView open: 'Great green gobs' label: 'Gopher Guts'"! ! !FormView methodsFor: 'displaying' stamp: 'ssa 11/26/2009 22:52'! displayView "Refer to the comment in View|displayView." | oldOffset | super displayView. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: insideColor]. oldOffset _ model offset. model offset: "borderWidth origin" 0@0. model displayOn: Display at: self insetDisplayBox origin clippingBox: self insetDisplayBox rule: Form paint fillColor: nil. model offset: oldOffset! ! !FormView methodsFor: 'private' stamp: 'ssa 11/26/2009 22:42'! defaultRule "The default display rule is 3=over or storing." ^Form paint! ! !FormView class methodsFor: 'examples' stamp: 'ssa 11/26/2009 22:47'! open: aForm named: aString "FormView open: ((ColorForm fromUser) borderWidth: 1) named: 'Squeak' " "Open a window whose model is aForm and whose label is aString." | topView aView | topView _ StandardSystemView new. topView model: aForm. topView label: aString. topView minimumSize: aForm extent+2"; maximumSize: aForm extent + 2". aView _ FormView new. aView model: aForm. "aView window: (aForm boundingBox expandBy: 2)." aView borderWidthLeft: 1 right: 1 top: 2 bottom: 1. topView addSubView: aView. topView controller open! ! !ListView methodsFor: 'displaying' stamp: ''! scrollSelectionIntoView "Selection is assumed to be on and clipped out of view. Uses controller scrollView to keep selection right" | delta | (delta _ self insetDisplayBox bottom - self selectionBox bottom) < 0 ifTrue: [^ self controller scrollView: delta - (list lineGrid-1)]. "up" (delta _ self insetDisplayBox top - self selectionBox top) > 0 ifTrue: [^ self controller scrollView: delta + 1] "down"! ! !ListView methodsFor: 'clipping box access' stamp: 'ssa 9/11/2009 18:25'! clippingBox "Answer the rectangle in which the model can be displayed--this is the insetDisplayBox inset by the height of a line for an item." ^self insetDisplayBox insetBy: (Rectangle left: 0 right: 0 top: 0 bottom: 0 "self insetDisplayBox height \\ list lineGrid")! ! !ListView methodsFor: 'selecting' stamp: 'ssa 9/11/2009 18:25'! findSelection: aPoint "Determine which selection is displayed in an area containing the point, aPoint. Answer the selection if one contains the point, answer nil otherwise." | trialSelection | (self clippingBox containsPoint: aPoint) ifFalse: [^nil]. trialSelection _ aPoint y - list compositionRectangle top // list lineGrid + 1. topDelimiter == nil ifFalse: [trialSelection _ trialSelection - 1]. (trialSelection < 1) | (trialSelection > self maximumSelection) ifTrue: [^ nil] ifFalse: [^ trialSelection]! ! !ListView methodsFor: 'updating' stamp: 'ssa 1/22/2010 14:49'! update: aSymbol "Refer to the comment in View|update:." "Hacked to support MSWScrollBars - ssa 12/11/97 16:42" aSymbol == #list ifTrue: [self list: model list. self displayView] ifFalse:[ aSymbol == #listIndex ifTrue: [self moveSelectionBox: model listIndex]]. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !ListView methodsFor: 'scrolling support' stamp: ''! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" | para lineIndex | para _ self list. lineIndex _ para lineIndexOfTop: para visibleRectangle top. lineIndex = 1 ifTrue:[^0.0]. ^lineIndex / para numberOfLines asFloat ! ! !ListView methodsFor: 'scrolling support' stamp: ''! scrollBy: anInteger "Scroll up by this amount adjusted by lineSpacing and list limits" "Hacked to support MSWScrollBarView - ssa 12/10/97 16:26" | maximumAmount minimumAmount amount | maximumAmount _ 0 max: list clippingRectangle top - list compositionRectangle top. minimumAmount _ 0 min: list clippingRectangle bottom - list compositionRectangle bottom. amount _ (anInteger min: maximumAmount) max: minimumAmount. amount ~= 0 ifTrue: [list scrollBy: amount negated. (self superView isKindOf: MSWScrollBarView) "______HERE IS THE HACK" ifTrue:[self superView updateElevator]. ^ true] ifFalse: [^ false] "Return false if no scrolling took place"! ! !ListView methodsFor: 'scrolling support' stamp: 'ssa 9/9/2009 15:24'! totalContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self list compositionRectangle height / self unitContentHeight! ! !ListView methodsFor: 'scrolling support' stamp: ''! unitContentHeight "Answer the unit height of my contents. ssa 12/5/97 15:16" ^ self list lineGrid asFloat! ! !ListView methodsFor: 'scrolling support' stamp: ''! visibleContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self list clippingRectangle height / self unitContentHeight! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! isEmpty "Answer the value of isEmpty" isEmpty isNil ifTrue:[self isEmpty: nil]. ^ isEmpty! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! isEmpty: anObject "Set the value of isEmpty" isEmpty _ anObject! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! textStyle "Answer the value of textStyle" textStyle isNil ifTrue:[self textStyle: nil]. ^ textStyle! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! textStyle: anObject "Set the value of textStyle" textStyle _ anObject! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 11/30/2009 17:33'! backgroundColor: aColor "Blow the caches" super backgroundColor: aColor. self elevatorCache:nil. self downButtonCache: nil. self upButtonCache: nil. ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 12:24'! downButtonBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, downButtonBox" downButtonBox isNil ifTrue:[self downButtonBox: self determineDownButtonBox]. ^downButtonBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! downButtonBox: aRectangle "" "ssa 12/5/97 11:15 - Set downButtonBox to be aRectangle." downButtonBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:46'! downButtonCache "<^hOf Form>" "ssa 12/11/97 11:43 - Answer the instance variable, downButtonCache" downButtonCache isNil ifTrue:[self downButtonCache: (Form extent:1@1)]. ^downButtonCache! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:43'! downButtonCache: aColorForm "" "ssa 12/11/97 11:43 - Set downButtonCache to be aColorForm." downButtonCache _ aColorForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 16:29'! elevatorBox "Answer the rectangle for the elevator." ^self controller elevatorBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:45'! elevatorCache "<^hOf Form>" "ssa 12/10/97 16:32 - Answer the instance variable, elevatorCache" elevatorCache isNil ifTrue:[self elevatorCache: (Form extent:1@1)]. ^elevatorCache ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/10/97 16:32'! elevatorCache: aForm "" "ssa 12/10/97 16:32 - Set elevatorCache to be aForm." elevatorCache _ aForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:18'! elevatorShaft "<^hOf Rectangle>" "ssa 12/5/97 14:18 - Answer the instance variable, elevatorShaft" elevatorShaft isNil ifTrue:[self elevatorShaft: self determineElevatorShaft]. ^elevatorShaft! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:18'! elevatorShaft: aRectangle "" "ssa 12/5/97 14:18 - Set elevatorShaft to be aRectangle." elevatorShaft _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 12:43'! getWindow "This is here to break a recursive loop caused by the indirection of my display transformation." self window isNil ifTrue:[self window: Display boundingBox]. ^self window! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 8/27/2009 04:51'! model: aModel model ~~ nil & (model ~~ aModel) ifTrue: [model removeDependent: self]. aModel ~~ nil & (aModel ~~ model) ifTrue: [aModel addDependent: self]. model _ aModel. ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:28'! scrollBarBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, scrollBarBox" scrollBarBox isNil ifTrue:[self scrollBarBox: self determineScrollBarBox]. ^scrollBarBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! scrollBarBox: aRectangle "" "ssa 12/5/97 11:15 - Set scrollBarBox to be aRectangle." scrollBarBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/10/97 14:05'! scrollBarWidth "<^hOf Integer>" "ssa 12/5/97 11:27 - Answer the instance variable, scrollBarWidth" scrollBarWidth isNil ifTrue:[self scrollBarWidth: 12]. ^scrollBarWidth! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:27'! scrollBarWidth: anInteger "" "ssa 12/5/97 11:27 - Set scrollBarWidth to be anInteger." scrollBarWidth _ anInteger! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 1/24/98 16:06'! scrollingView ^self subViews isEmpty ifTrue:[nil] ifFalse:[self subViews first]! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 13:59'! upButtonBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, upButtonBox" upButtonBox isNil ifTrue:[self upButtonBox: self determineUpButtonBox]. ^upButtonBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! upButtonBox: aRectangle "" "ssa 12/5/97 11:15 - Set upButtonBox to be aRectangle." upButtonBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:46'! upButtonCache "<^hOf Form>" "ssa 12/11/97 11:43 - Answer the instance variable, upButtonCache" upButtonCache isNil ifTrue:[self upButtonCache: (Form extent:1@1)]. ^upButtonCache! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:43'! upButtonCache: aColorForm "" "ssa 12/11/97 11:43 - Set upButtonCache to be aColorForm." upButtonCache _ aColorForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 12:44'! window "This is here to break a recursive loop caused by the indirection of my display transformation." window isNil ifTrue:[self window: Display boundingBox]. ^window! ! !MSWScrollBarView methodsFor: 'bordering' stamp: 'ssa 1/24/98 16:05'! borderWidth: anything super borderWidth:1. ! ! !MSWScrollBarView methodsFor: 'control defaults' stamp: 'stp 02/18/98 0-11:'! defaultControllerClass ^MSWScrollBarController! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 1/23/98 14:56'! doesNotUnderstand: aMessage "Here it comes, the dreaded doesNotUnderstand: HACK ssa 1/23/98 14:55" ^self scrollingView perform: aMessage selector withArguments: aMessage arguments! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 3/24/2010 14:37'! update: aSymbol self topView ifNotNil:[self topView isCollapsed ifFalse:[self updateElevator]]. super update: aSymbol. "self subViews do:[:each| each update: aSymbol]"! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 1/21/2010 12:24'! update: aSymbol with: aValue self updateElevator. super update: aSymbol with: aValue. "self subViews do:[:each| each update: aSymbol with: aValue]"! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 8/27/2009 04:55'! updateListsAndCodeIn: aWindow self updateElevator. super updateListsAndCodeIn: aWindow. ^self subViews first updateListsAndCodeIn: aWindow! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 8/27/2009 09:29'! determineDownButtonBox "Answer the rectangle for the scroll bar down button." ^self scrollBarBox corner - self scrollBarBox width asPoint extent: (self scrollBarBox width)asPoint! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:38'! determineElevatorBox "Answer the rectangle for the scroll bar elevator." ^self scrollBarBox center - (self scrollBarWidth asPoint // 2) extent: self scrollBarWidth asPoint! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 14:19'! determineElevatorShaft "Answer the rectangle for the scroll bar down button." ^self upButtonBox bottomLeft corner: self downButtonBox topRight! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:47'! determineScrollBarBox "Answer the rectangle for the scroll bar region." ^(self realInsetDisplayBox areasOutside: self insetDisplayBox) first! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:52'! determineUpButtonBox "Answer the rectangle for the scroll bar up button." ^self scrollBarBox origin extent: self scrollBarBox width asPoint! ! !MSWScrollBarView methodsFor: 'display box access' stamp: ''! displayBox "tah -- (17 July 1989 6:37:46 pm ) -- Answer the real displayBox" ^self realInsetDisplayBox expandBy: borderWidth! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:10'! insetDisplayBox "Answer the inset displayBox reduced by the horizontal space for the scroll bar" ^WhereToLocateScrollBars = #left ifTrue:[self insetDisplayBoxLeft] ifFalse:[self insetDisplayBoxRight]! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:09'! insetDisplayBoxLeft "Answer the inset displayBox reduced by the horizontal space for the scroll bar" | box | box _ self realInsetDisplayBox. ^box origin extent: box width - (self borderWidth left + self scrollBarWidth) @ box height ! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:10'! insetDisplayBoxRight "Answer the inset displayBox reduced by the horizontal space for the scroll bar" "Changed to left-side scroll bars--stp." "MSWScrollBarView someInstance" | box | box _ self realInsetDisplayBox. ^((box left + self scrollBarWidth) @ box top) extent: (box width - (self borderWidth left + self scrollBarWidth) @ box height) ! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/15/97 14:50'! realInsetDisplayBox "tah -- (17 July 1989 6:05:48 pm ) -- answer the real inset displayBox " ^super insetDisplayBox! ! !MSWScrollBarView methodsFor: 'display transformation' stamp: ''! displayTransform: anObject "Apply the display transformation of the receiver to anObject (see View|displayTransformation) and answer the resulting scaled, translated object. It is normally applied to Rectangles, Points, and other objects with coordinates defined in the View's local coordinate system in order to get a corresponding object in display coordinates." ^(self realDisplayTransformation applyTo: anObject) rounded! ! !MSWScrollBarView methodsFor: 'display transformation' stamp: 'ssa 12/15/97 14:49'! displayTransformation "This is a hook for to get the real displayTransformation" ^self scrollBarWidth = 0 ifTrue: [self realDisplayTransformation] ifFalse: [WindowingTransformation window: self getWindow viewport: (self realInsetDisplayBox expandBy: self borderWidth)]! ! !MSWScrollBarView methodsFor: 'display transformation' stamp: ''! realDisplayTransformation "This is a hook for labeledView to get the real displayTransformation" ^super displayTransformation! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:44'! deEmphasizeView super deEmphasizeView ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 12/11/97 13:13'! displayDownButton | box | box _ self downButtonBox. self downButtonCache extent = box extent ifFalse:[self drawDownButton]. self downButtonCache displayOn: Display at: box origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 1/20/98 21:45'! displayDownButtonPressed | box cf bb | box _ self downButtonBox. Display fill: box fillColor: Color darkGray. Display fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 260046848 117440512 33554432 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: Display sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 2 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 17:02'! displayElevatorOn: aForm | box shaft | box _ self elevatorBox. shaft _ self elevatorShaft. self elevatorCache extent = box extent ifFalse:[self drawElevator]. self elevatorCache displayOn: aForm at: box origin - shaft origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:52'! displayElevatorShaftOn: aForm | box | box _ self elevatorShaft. aForm fill: (0@0 extent: box extent) fillColor: self backgroundColor darker darker ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 12/11/97 13:18'! displayUpButton | box | box _ self upButtonBox. self upButtonCache extent = box extent ifFalse:[self drawUpButton]. self upButtonCache displayOn: Display at: box origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 1/20/98 21:45'! displayUpButtonPressed | box cf bb | box _ self upButtonBox. Display fill: box fillColor: Color darkGray. Display fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 33554432 117440512 260046848 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: Display sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 2 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:58'! displayView self displayUpButton. self displayDownButton. self updateElevator ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/27/2009 09:30'! drawDownButton | box pen cf bb form | form _ Form extent: self downButtonBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color black. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 260046848 117440512 33554432 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: form sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 1 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits. self downButtonCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/21/2009 13:03'! drawElevator | box pen form | form _ Form extent: self controller elevatorBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: self backgroundColor. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. self elevatorCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/21/2009 13:03'! drawUpButton | box pen cf bb form | form _ Form extent: self upButtonBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: self backgroundColor. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 33554432 117440512 260046848 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: form sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 1 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits. self upButtonCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:46'! emphasizeView self displayView. super emphasizeView! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 15:18'! updateElevator | newForm | newForm _ Form fromDisplay: self elevatorShaft. self displayElevatorShaftOn: newForm. self displayElevatorOn: newForm. newForm displayOn: Display at: self elevatorShaft origin! ! !MSWScrollBarView methodsFor: 'lock access' stamp: 'ssa 12/5/97 16:10'! unlock "Flush the cache." self scrollBarBox: nil. self upButtonBox: nil. self downButtonBox: nil. self elevatorShaft: nil. super unlock! ! !MSWScrollBarView methodsFor: 'subview additions' stamp: 'ssa 1/15/98 15:50'! addSubView: aView in: aRelativeRectangle borderWidth: width "11/3/96 ssa - added for compatibility." "Make 'aView' into a subview. Use 'aRelativeRectangle' and the super view's window to compute (1) a viewport within the superview for 'aView' and (2) the window extent for 'aView'. Note: defining the windowing transformation and deriving the viewport is logically equivalent but does not seem to be easily done" | subViewPort myWindow myExtent myOrigin | self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']. aView borderWidth: width. myWindow _ self window. myExtent _ myWindow extent. myOrigin _ myWindow origin. subViewPort _ myExtent * aRelativeRectangle origin + myOrigin corner: myExtent * aRelativeRectangle corner + myOrigin. aView window: aView window viewport: subViewPort ! ! !MSWScrollBarView methodsFor: 'subview additions' stamp: 'ssa 8/27/2009 04:49'! on: aView "tah -- (17 July 1989 7:17:34 pm ) -- Add a subview to this view" self on: aView borderWidth: 0. self model: aView model! ! !MSWScrollBarView methodsFor: 'subview additions' stamp: ''! on: aView borderWidth: aBorderWidth "tah -- (17 July 1989 7:17:34 pm ) -- Add a subview to this view" self addSubView: aView in: (0@0 extent: (1@1)) borderWidth: aBorderWidth! ! !MSWScrollBarView methodsFor: 'testing' stamp: 'ssa 1/8/98 16:13'! containsPoint: aPoint "Overriden to access my real insetDsiplayBox" ^ self realInsetDisplayBox containsPoint: aPoint! ! !MSWScrollBarView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 15:07'! on: aScrollingView "" "Answer an instance of me that encapsulates aScrollingView by providing Windows-style scroll bars" ^aScrollingView class == self class "prevent scrollbars on scrolbars" ifTrue:[aScrollingView error:'should never try to embed scrollbar views'] ifFalse:[self new on: aScrollingView]! ! !MSWScrollBarView class methodsFor: 'class initialization' stamp: 'ssa 1/5/2010 18:10'! initialize "Make an initial decision as to which side to locate the scrollbars. See preferences to change sides." self locateScrollBarsOnRightSide! ! !MSWScrollBarView class methodsFor: 'preferences' stamp: 'ssa 2/27/98 11:40'! locateScrollBarsOnLeftSide "Set the flag to locate the ScrollBars on the left hand side of the view." "MSWScrollBarView locateScrollBarsOnLeftSide" | openWindows | WhereToLocateScrollBars _ #left. self allInstances do:[:each| each unlock]. openWindows _ ScheduledControllers controllersSatisfying: [:each| (each view respondsTo:#isCollapsed) and:[each view isCollapsed not]]. openWindows reverseDo:[:each| each view uncacheBits display]. ScheduledControllers restore! ! !MSWScrollBarView class methodsFor: 'preferences' stamp: 'ssa 2/27/98 11:39'! locateScrollBarsOnRightSide "Set the flag to locate the ScrollBars on the right hand side of the view." "MSWScrollBarView locateScrollBarsOnRightSide" | openWindows | WhereToLocateScrollBars _ #right. self allInstances do:[:each| each unlock]. openWindows _ ScheduledControllers controllersSatisfying: [:each| (each view respondsTo:#isCollapsed) and:[each view isCollapsed not]]. openWindows reverseDo:[:each| each view uncacheBits display]. ScheduledControllers restore! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'ssa 8/23/2009 13:42'! label: aStringOrDisplayObject "Label this button with the given String or DisplayObject." ((aStringOrDisplayObject isKindOf: Paragraph) or: [aStringOrDisplayObject isForm]) ifTrue: [label _ aStringOrDisplayObject] ifFalse: [label _ aStringOrDisplayObject asParagraph]. self centerLabel. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'acg 2/23/2000 00:18'! displayView "Displays this switch and its label, if any." self clearInside. label ifNotNil: [ (label isKindOf: Paragraph) ifTrue: [ label foregroundColor: self foregroundColor backgroundColor: self backgroundColor]. label displayOn: Display at: label boundingBox topLeft clippingBox: self insetDisplayBox]. complemented _ false.! ! !PluggableButtonView methodsFor: 'other' stamp: 'ssa 8/22/2009 15:54'! performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed." (argumentsSelector isKindOf: BlockContext) ifTrue:[^argumentsSelector value]. argumentsSelector ifNil: [actionSelector ifNotNil: [model perform: actionSelector]] ifNotNil: [model perform: actionSelector withArguments: (Array with: (argumentsProvider perform: argumentsSelector))]! ! !PluggableButtonView methodsFor: 'other' stamp: 'ssa 8/23/2009 13:47'! update: aParameter aParameter == getLabelSelector ifTrue: [ getLabelSelector ifNotNil: [ self label: (model perform: getLabelSelector halt ). self displayView]]. self getModelState ifTrue: [self displayComplemented] ifFalse: [self displayNormal]. ! ! !PluggableListView methodsFor: 'model access' stamp: 'ssa 9/2/2009 20:11'! getList "Answer the list to be displayed." | lst | getListSelector == nil ifTrue: [^ #()]. lst _ model perform: getListSelector. lst == nil ifTrue: [^ #()]. ^ lst ! ! !PluggableListView methodsFor: 'updating' stamp: 'ssa 11/25/2009 14:42'! update: aSymbol "Refer to the comment in View|update:." "Hacked to support Windoze - ssa" aSymbol == getListSelector ifTrue: [self list: self getList. self displayView. self displaySelectionBox]. aSymbol == getSelectionSelector ifTrue: [self moveSelectionBox: self getCurrentSelectionIndex]. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:45'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: nil keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:45'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 9/4/1998 16:00'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." "Added Windoze wrapper - ssa" ^ MSWScrollBarView on: (self new on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel) ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 11/25/2009 12:50'! changeModelSelection: anInteger "Change the model's selected item to be the one at the given index." | item | setSelectionSelector ifNotNil: [ item _ (anInteger = 0 ifTrue: [nil] ifFalse: [self objects at: anInteger]). model perform: setSelectionSelector with: item]. ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:40'! getCurrentSelectionIndex "Answer the index of the current selection." | item | getSelectionSelector == nil ifTrue: [^ 0]. item _ model perform: getSelectionSelector. ^ self objects indexOf: item ifAbsent:[0] ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:47'! labelForItem: anItem "Subclasses may want to override" ^anItem isString ifTrue:[anItem]ifFalse:[anItem printString]! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 6/17/2010 16:40'! list: arrayOfObjects "Set the receivers items to be the given list of objects printStrings." "Note: the instance variable 'objects' holds the original list. The instance variable 'list' is a paragraph constructed from this list." | oldOffset | self scrollCache: (list isNil ifFalse:[list scrollDelta]ifTrue:[0]). self objects: arrayOfObjects. isEmpty _ arrayOfObjects isEmpty. oldOffset _ list isNil ifTrue:[0@0]ifFalse:[list offset]. "add top and bottom delimiters" list _ ListParagraph withArray: (Array streamContents: [:s | s nextPut: topDelimiter. self objects do: [:item | item == nil ifFalse: [s nextPut: (self labelForItem: item)]]. s nextPut: bottomDelimiter]) style: self assuredTextStyle. list offset: oldOffset. selection _ self getCurrentSelectionIndex. self positionList.! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:31'! objects "Answer the value of objects" objects isNil ifTrue:[self objects: OrderedCollection new]. ^ objects! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:29'! objects: anObject "Set the value of objects" objects _ anObject! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/22/2010 14:02'! scrollCache "Answer the value of scrollCache" scrollCache isNil ifTrue:[self scrollCache: 0]. ^ scrollCache! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/22/2010 14:02'! scrollCache: anObject "Set the value of scrollCache" scrollCache _ anObject! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:58'! boxFor: index "Answer the rectangle in which the item is displayed." | offset | offset _ (index - 1 + (topDelimiter == nil ifTrue: [0] ifFalse: [1]))* list lineGrid. ^(self insetDisplayBox left @ (list compositionRectangle top +offset) extent: self insetDisplayBox width @ list lineGrid) insetBy: (Rectangle left: 1 right: 1 top: 1 bottom: 0)! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:52'! getChildrenSelector "Answer the value of getChildrenSelector" getChildrenSelector isNil ifTrue:[self getChildrenSelector: #subobjects]. ^ getChildrenSelector! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:51'! getChildrenSelector: anObject "Set the value of getChildrenSelector" getChildrenSelector _ anObject! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:28'! indentBoxFor: index "Answer the rectangle which counds the whitespace in front of the item at this index" | itemBox indents | itemBox _ self boxFor: index. indents _ self indentFor:(self objects at: index). ^itemBox width: (Paragraph withText: indents asText style: self textStyle) boundingBox width.! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 14:42'! indentFor: anItem | aStream | aStream _ WriteStream on:''. (self levelOf: anItem) timesRepeat:[aStream tab]. ^aStream contents,' '! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/10/2009 16:00'! labelForItem: anItem "Subclasses may want to override" ^(self indentFor: anItem),anItem outlineString! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:59'! levelOf: anItem ^self model levelOf: anItem! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:25'! twistyTargets "Answer the value of twistyTargets" twistyTargets isNil ifTrue:[self twistyTargets: Dictionary new]. ^ twistyTargets! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:24'! twistyTargets: anObject "Set the value of twistyTargets" twistyTargets _ anObject! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 9/11/2009 17:06'! displayTwisties | box isOpen twisty to firstIndex | firstIndex _ self firstShown. firstIndex to: ((self list numberOfLines - 2)min:(firstIndex + self numSelectionsInView )) do:[:index| (self model hasChildren: (self objects at: index)) ifTrue:[ box _ self indentBoxFor: index. isOpen _ self model isOpen:(self objects at: index). twisty _ isOpen ifTrue:[self openedTwistyIcon]ifFalse:[self closedTwistyIcon]. twisty displayOn: Display at: (to_box topRight - (twisty width@0)) clippingBox: (box intersect: self clippingBox) rule: Form paint fillColor: nil. self twistyTargets at:(to extent: twisty extent) put: index]].! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 1/22/2010 14:03'! displayView self list foregroundColor: self foregroundColor backgroundColor: self backgroundColor. self list displayOn: Display at: self insetDisplayBox origin - (0@self scrollCache) clippingBox: self insetDisplayBox. (self insetDisplayBox copy areasOutside: (self insetDisplayBox origin extent: self list compositionRectangle extent )) do:[:box| Display fill: box fillColor: Color white]. self displayTwisties. ! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 11/25/2009 12:55'! positionList list wrappingBox: self wrappingBox clippingBox: self clippingBox! ! !LyPluggableOutlineView methodsFor: 'icons' stamp: 'ssa 9/9/2009 13:33'! closedTwistyIcon ^LyGraphicsLibrary selfTwistyClosed! ! !LyPluggableOutlineView methodsFor: 'icons' stamp: 'ssa 9/9/2009 13:33'! openedTwistyIcon ^LyGraphicsLibrary selfTwistyOpen! ! !LyPluggableOutlineView methodsFor: 'scrolling support' stamp: 'ssa 11/25/2009 12:36'! scrollBy: anInteger super scrollBy: anInteger . self displayTwisties. ^true! ! !LyPluggableOutlineView methodsFor: 'controller access' stamp: 'ssa 9/9/2009 16:34'! defaultControllerClass ^LyPluggableOutlineController! ! !LyPluggableOutlineView methodsFor: 'controller access' stamp: 'ssa 9/9/2009 16:28'! defaultCsntrollerClass ^LyPluggableOutlineController! ! !ExplorerListView methodsFor: 'accessing' stamp: 'ssa 3/9/2010 16:15'! indentFor: anItem | aStream lev | (anItem isKindOf: String) ifTrue:[^'']. aStream _ WriteStream on:''. (lev _ self levelOf: anItem) . lev timesRepeat:[aStream nextPutAll:' ']. ^aStream contents,' '! ! !ExplorerListView methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:33'! levelOf: anItem ^anItem depth! ! !ExplorerListView methodsFor: 'displaying' stamp: 'ssa 2/8/2010 16:17'! displayTwisties | box twisty to firstIndex | firstIndex _ self firstShown. firstIndex to: ((self list numberOfLines -2)min:(firstIndex + self numSelectionsInView )) do:[:index| (self objects at: index) hasContents ifTrue:[ box _ self indentBoxFor: index. twisty _(self objects at: index) isOpen ifTrue:[self openedTwistyIcon]ifFalse:[self closedTwistyIcon]. twisty displayOn: Display at: (to_box topRight- (twisty width@0)) clippingBox: (box intersect: self clippingBox) rule: Form paint fillColor: nil. self twistyTargets at:(to extent: twisty extent) put: index]].! ! !ExplorerListView methodsFor: 'displaying' stamp: 'ssa 6/17/2010 16:32'! labelForItem: anItem "Subclasses may want to override" ^(self indentFor: anItem),' ',anItem asString ! ! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:46'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel ^ self on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: #arrowKey:from: "default"! ! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'ssa 8/21/2009 15:22'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel ^MSWScrollBarView on: ( self new on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel)! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 3/24/2010 16:03'! closeBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (boxHeight negated-9@7)) extent: boxHeight+2@boxHeight "MSWSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:35'! growBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (2*boxHeight negated-12@7)) extent: boxHeight+2@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 2/6/98 14:24'! labelHeight ^self isCollapsed ifFalse:[18 + 6] ifTrue:[(LabelStyle fontAt: 2) height + 14]! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:56'! labelTextRegion labelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0]. ^ (labelText boundingBox align: labelText boundingBox leftCenter with: self labelDisplayBox leftCenter + (25@0)) intersect: (self labelDisplayBox origin corner: self labelDisplayBox corner - (55@0))! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:34'! shrinkBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (3*boxHeight negated-15@7)) extent: boxHeight+2@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:17'! systemBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11 . ^ Rectangle origin: (self labelDisplayBox origin + (7@7)) extent: boxHeight@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'framing' stamp: 'stp 02/18/98 0-15:'! collapse "If the receiver is not already collapsed, change its view to be that of its label only." self isCollapsed ifFalse: [expandedViewport _ self viewport. savedSubViews _ subViews. self resetSubViews. labelText isNil ifTrue: [self label: nil. bitsValid _ false.]. self window: (self inverseDisplayTransform: ((self labelDisplayBox topLeft extent: (labelText extent x + 80) @ self labelHeight) intersect: self labelDisplayBox))]! ! !MSWSystemView methodsFor: 'framing' stamp: 'ar 1/22/98 22:47'! fullScreen | portRect | portRect _ self viewport. growFrame _ portRect topLeft - self labelOffset corner: portRect corner. ^super fullScreen! ! !MSWSystemView methodsFor: 'framing' stamp: 'ar 1/22/98 22:49'! restore self reframeTo: ( growFrame isNil ifTrue:[self initialFrame] ifFalse:[growFrame])! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:27'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: false. self displayLabelTextDeEmphasized. self displayLabelBorder. self displayClosingGuardBoxIfNeeded. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:32'! displayClosingGuardBoxIfNeeded "display closing guard active, if true" | aRect | self controller preventClosing ifTrue:[ aRect _ self closeBoxFrame. self closingGuardIcon displayOn: Display at: aRect origin + (2@1) clippingBox: aRect rule: Form over fillColor: nil]. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:42'! displayDeEmphasizedOLD "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self displayBorder. super displayDeEmphasized. self deEmphasizeLabel! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:43'! displayEmphasizedOLD "Display with label highlighted to indicate that it is active." self displayBorder. super displayEmphasized. self emphasizeLabel ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelBackground: emphasized "Clear or emphasize the inner region of the label" emphasized ifTrue:[Display fill: self labelDisplayBox fillColor: self labelBackgroundColor] ifFalse:[Display fill: self labelDisplayBox fillColor:self labelBackgroundColor darker darker]. self displayLabelBoxes. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:25'! displayLabelBoxes CloseBoxForm ifNil:[CloseBoxForm _ self drawCloseBoxForm]. GrowBoxForm ifNil:[GrowBoxForm _ self drawGrowBoxForm]. ShrinkBoxForm ifNil:[ShrinkBoxForm _ self drawShrinkBoxForm]. SystemBoxForm ifNil:[SystemBoxForm _ self drawSystemBoxForm]. CloseBoxForm displayOn: Display at: self closeBoxFrame origin. GrowBoxForm displayOn: Display at: self growBoxFrame origin. self isCollapsed ifFalse:[ShrinkBoxForm displayOn: Display at: self shrinkBoxFrame origin]. SystemBoxForm displayOn: Display at: self systemBoxFrame origin. "display closing guard active, if true" self displayClosingGuardBoxIfNeeded. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelText "The label goes in the center of the window" | labelRect | labelText foregroundColor: Color black backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. "Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor." labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelTextDeEmphasized | labelRect | labelText foregroundColor: Color gray backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelTextEmphasized | labelRect | labelText foregroundColor: Color black backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'stp 02/18/98 0-13:'! drawCloseBoxForm "Answer a thinner 'X' for the close box." "CloseBoxForm bitEdit" ^Form extent: 15@13 depth: 8 fromArray: #( 50529027 50529027 50529027 50529024 51252750 235802126 235802126 235801600 51249923 50529027 50529027 50531328 51249921 16974595 50528513 50531328 51249923 16843523 50397443 50531328 51249923 50397443 16843523 50531328 51249923 50528513 16974595 50531328 51249923 50397443 16843523 50531328 51249923 16843523 50397443 50531328 51249921 16974595 50528513 50531328 51249923 50529027 50529027 50531328 51249923 50529027 50529027 50531328 51121164 202116108 202116108 202116096) offset: 0@0! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ar 1/22/98 22:10'! drawGrowBoxForm | box pen form | form _ Form extent: self growBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. pen color: Color black. pen place: box topLeft + (3@3). pen goto: box bottomLeft + (3@-3). pen goto: box bottomRight + (-3@-3). pen goto: box topRight + (-3@3). pen defaultNib: 2. pen place: box topRight + (-4@3). pen goto: box topLeft + (3@3). ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ar 1/22/98 22:11'! drawShrinkBoxForm | box pen form | form _ Form extent: self growBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. pen color: Color black. pen defaultNib: 2. pen place: box bottomRight + (-4@-3). pen goto: box bottomLeft + (3@-3). ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 1/24/98 23:09'! drawSystemBoxForm | box pen form | form _ Form extent: self systemBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 1/24/98 22:49'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: true. self displayLabelBoxes. self displayLabelTextEmphasized. self displayLabelBorder! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:44'! labelBackgroundColor ^Color veryLightGray lighter! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:30'! baseColor ^Color gray ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:34'! borderBox: box Display border: (box insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 0@0) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (box insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (box insetBy: 1@1) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker . Display border: (box insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 2@2) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor lighter. ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:39'! borderBoxNoBottom: box Display border: (box insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 0@0) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (box insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (box insetBy: 1@1) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor darker . Display border: (box insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 2@2) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor lighter. ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 9/4/1998 16:52'! borderWidth: anInteger "Override to support standard borders"! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:33'! displayBorder "Display the receiver's border (using the receiver's borderColor)." | | self isCollapsed ifTrue:[^self]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBox: self displayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/24/2010 17:09'! displayBorderOLD "Display the receiver's border (using the receiver's borderColor)." | box | self isCollapsed ifTrue:[^self]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [box _ self displayBox. "left edge" Display fill: (box origin extent: 1@(box height - 1)) fillColor: Color gray. Display fill: (box origin +(1@1) extent: 1@(box height - 2)) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: 2@(box height-4)) fillColor: Color gray. Display fill: (box origin +(4@3) extent: 1@(box height-6)) fillColor: Color veryDarkGray. Display fill: (box origin +(5@4) extent: 1@(box height-8)) fillColor: Color black. "right edge" Display fill: (box topRight -(1@0)extent: 1@(box height - 1)) fillColor: Color black. Display fill: (box topRight +(-2@1) extent: 1@(box height - 2)) fillColor: Color veryDarkGray. Display fill: (box topRight +(-4@2) extent: 2@(box height-4)) fillColor: Color gray. Display fill: (box topRight +(-5@5) extent: 1@(box height-10)) fillColor: Color veryLightGray. Display fill: (box topRight +(-6@6) extent: 1@(box height-12)) fillColor: Color gray. "top edge" Display fill: (box origin extent: box width@1) fillColor: Color gray. Display fill: (box origin +(1@1) extent: (box width - 2)@1) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box origin +(4@4) extent: (box width-8)@1) fillColor: Color veryDarkGray. Display fill: (box origin +(5@5) extent: (box width-10)@1) fillColor: Color black. "bottom edge" Display fill: (box bottomLeft -(0@1) extent: box width @1) fillColor: Color black. Display fill: (box bottomLeft +(1@-2) extent: (box width - 2)@1) fillColor: Color veryDarkGray. Display fill: (box bottomLeft +(2@-4) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box bottomLeft +(4@-5) extent: (box width-7)@1) fillColor: Color veryLightGray. Display fill: (box bottomLeft +(5@-6) extent: (box width-9)@1) fillColor: Color gray. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: self backgroundColor]]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:37'! displayCollaspedLabelBorder "Display the receiver's label border." | | borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBox: self labelDisplayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:39'! displayLabelBorder "Display the receiver's label border." | | self isCollapsed ifTrue:[^self displayCollaspedLabelBorder]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBoxNoBottom: self labelDisplayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:32'! displayLabelBorderOLD "Display the receiver's label border." | box | self isCollapsed ifTrue:[^self displayCollaspedLabelBorder]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [box _ self labelDisplayBox. "left edge" Display fill: (box origin extent: 1@(box height)) fillColor: Color gray. Display fill: (box origin +(1@1) extent: 1@(box height)) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: 2@(box height)) fillColor: Color gray. Display fill: (box origin +(4@3) extent: 1@(box height)) fillColor: Color veryDarkGray. Display fill: (box origin +(5@4) extent: 1@(box height)) fillColor: Color black. "right edge" Display fill: (box topRight -(1@0)extent: 1@(box height)) fillColor: Color black. Display fill: (box topRight +(-2@1) extent: 1@(box height)) fillColor: Color veryDarkGray. Display fill: (box topRight +(-4@2) extent: 2@(box height)) fillColor: Color gray. Display fill: (box topRight +(-5@5) extent: 1@(box height)) fillColor: Color veryLightGray. Display fill: (box topRight +(-6@6) extent: 1@(box height)) fillColor: Color gray. "top edge" Display fill: (box origin extent: box width@1) fillColor: Color gray. Display fill: (box origin +(1@1) extent: (box width - 2)@1) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box origin +(4@4) extent: (box width-8)@1) fillColor: Color veryDarkGray. Display fill: (box origin +(5@5) extent: (box width-10)@1) fillColor: Color black]! ! !MSWSystemView methodsFor: 'testing' stamp: 'ar 1/22/98 22:07'! cacheBitsAsTwoTone ^false! ! !MSWSystemView methodsFor: 'testing' stamp: 'ar 1/22/98 22:37'! isFullScreen | frame | frame _ model fullScreenSize. ^(frame topLeft + self labelOffset corner: frame corner) = self viewport ! ! !MSWSystemView methodsFor: 'controller access' stamp: 'stp 02/18/98 0-11:'! defaultControllerClass ^MSWSystemController! ! !MSWSystemView methodsFor: 'initialize' stamp: 'ssa 3/25/2010 14:36'! initialize "change the default border to 3 to support stylish edges." super initialize. self borderWidthLeft: 3 right: 3 top: 0 bottom: 3! ! !MSWSystemView methodsFor: 'window access' stamp: 'ssa 8/24/2009 10:13'! defaultWindow "Build the minimum Rectangle that encloses all the windows of the receiver's subViews. The answer is a Rectangle obtained by expanding this minimal Rectangle by the borderWidth of the receiver. If the receiver has no subViews, then a Rectangle enclosing the entire display screen is answered. It is used internally by View methods if no window has been specified for the View. Specialized subclasses of View should redefine View|defaultWindow to handle the default case for instances that have no subViews." | aRectangle | subViews isEmpty ifTrue: [^DisplayScreen boundingBox copy]. aRectangle _ self firstSubView viewport. subViews do: [:aView | aRectangle _ aRectangle merge: aView viewport]. ^aRectangle! ! !StandardSystemView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 15:17'! new "This is a rather dirty hack -- but we don't have a window builder yet. (ar 1/22/98 23:36)" ^Preferences nicerSystemViews ifTrue:[MSWSystemView basicNew initialize] ifFalse:[self basicNew initialize]! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssaq 2/27/98 11:17'! initialize "MSWSystemView initialize" self install! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 2/27/98 11:02'! initializeCache "MSWSystemView initializeCache" GrowBoxForm _ nil. ShrinkBoxForm _ nil. SystemBoxForm _ nil. CloseBoxForm _ nil.! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 3/24/2010 15:16'! install "MSWSystemView install" Preferences enable:#nicerSystemViews! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 3/24/2010 15:16'! unInstall "MSWSystemView unInstall" Preferences disable:#nicerSystemViews! ! !StringHolderView methodsFor: 'initialize-release' stamp: 'ssa 1/20/2010 10:35'! initialize "Refer to the comment in View|initialize." super initialize. displayContents _ '' asParagraphWithStyle: self textStyle. hasUnacceptedEdits _ false. askBeforeDiscardingEdits _ true. ! ! !StringHolderView methodsFor: 'updating' stamp: ''! updateDisplayContents "Make the text that is displayed be the contents of the receiver's model." "VIVA LA JUNTA!!!! hack this to update the scroll bar when the contents changes - ssa 1/15/98 14:39" self editString: model contents. self displayView. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !StringHolderView methodsFor: 'model access' stamp: 'ssa 1/20/2010 10:43'! editString: aString "The paragraph to be displayed is created from the characters in aString." displayContents _ Paragraph withText: aString asText style: self textStyle copy compositionRectangle: (self insetDisplayBox insetBy: 6 @ 0) clippingRectangle: self insetDisplayBox foreColor: self foregroundColor backColor: self backgroundColor. (self controller isKindOf: ParagraphEditor) ifTrue: [controller changeParagraph: displayContents]! ! !StringHolderView methodsFor: 'scrolling support' stamp: ''! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" | para lineIndex | para _ self displayContents. lineIndex _ para lineIndexOfTop: para visibleRectangle top. lineIndex = 1 ifTrue:[^0.0]. ^lineIndex / para numberOfLines asFloat ! ! !StringHolderView methodsFor: 'scrolling support' stamp: ''! totalContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self displayContents compositionRectangle height / self unitContentHeight! ! !StringHolderView methodsFor: 'scrolling support' stamp: ''! unitContentHeight "Answer the unit height of my contents. ssa 12/5/97 15:16" ^ self displayContents lineGrid asFloat! ! !StringHolderView methodsFor: 'scrolling support' stamp: ''! visibleContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self displayContents clippingRectangle height / self unitContentHeight! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! askBeforeDiscardingEdits "Answer the value of askBeforeDiscardingEdits" askBeforeDiscardingEdits isNil ifTrue:[self askBeforeDiscardingEdits: nil]. ^ askBeforeDiscardingEdits! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:48'! changeTextStyle: aTextStyle self textStyle: aTextStyle. self displayContents setWithText: self displayContents asText style: self textStyle ! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/27/2010 17:12'! defaultTextStyle ^TextStyle default ! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! displayContents: anObject "Set the value of displayContents" displayContents _ anObject! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:36'! textStyle "Answer the value of textStyle" textStyle isNil ifTrue:[self textStyle: self defaultTextStyle]. ^ textStyle! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! textStyle: anObject "Set the value of textStyle" textStyle _ anObject! ! !StringHolderView class methodsFor: 'instance creation' stamp: ''! open: aStringHolder label: aString "Create a standard system view of the model, aStringHolder, as viewed by an instance of me. The label of the view is aString." "VIVA LA JUNTA!! Modified to use MSWScrollBarViews - ssa 12/11/97 12:00" | aStringHolderView topView shv | aStringHolderView _ self container: aStringHolder. topView _ StandardSystemView new. topView model: aStringHolderView model. topView addSubView: (shv _ MSWScrollBarView on: aStringHolderView ). shv borderWidth: 2. topView label: aString. topView minimumSize: 100 @ 50. topView controller open! ! !PluggableTextView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:35'! on: anObject text: getTextSel accept: setTextSel ^ self on: anObject text: getTextSel accept: setTextSel readSelection: nil menu: nil ! ! !PluggableTextView class methodsFor: 'instance creation' stamp: 'ssa 9/4/1998 16:04'! on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel "Added Windoze wrapper - ssa" ^ MSWScrollBarView on: (self new on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel) ! ! BraceNode subclass: #EnsembleNode instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! Object subclass: #Sly instanceVariableNames: '' classVariableNames: 'KeepFlying' poolDictionaries: '' category: 'Sly'! !EnsembleNode methodsFor: 'printing' stamp: 'ssa 4/19/2010 20:44'! printOn: aStream indent: level aStream nextPut: $%;nextPut: ${. 1 to: elements size do: [:i | (elements at: i) printOn: aStream indent: level. i < elements size ifTrue: [aStream nextPutAll: '. ']]. aStream nextPut: $}! ! !EnsembleNode methodsFor: 'code generation' stamp: 'ssa 4/19/2010 22:35'! emitForValue: stack on: aStream ^ emitNode emitForValue: stack on: aStream! ! !EnsembleNode methodsFor: 'code generation' stamp: 'dmu 9/16/2010 23:44'! sizeForValue: encoder emitNode _ "Long form: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray;asEnsembleOfElements" CascadeNode new receiver: (MessageNode new receiver: (encoder encodeVariable: #Array) selector: #braceStream: arguments: (Array with: (encoder encodeLiteral: elements size)) precedence: 3 from: encoder) messages: (((elements collect: [:elt | MessageNode new receiver: nil selector: #nextPut: arguments: (Array with: elt) precedence: 3 from: encoder]) copyWith: (MessageNode new receiver: nil selector: #braceArray arguments: (Array new) precedence: 1 from: encoder))copyWith: (MessageNode new receiver: nil selector: #asEnsembleOfElements arguments: (Array new) precedence: 1 from: encoder)). ^ emitNode sizeForValue: encoder! ! Object subclass: #SlyBoid instanceVariableNames: 'position velocity neighbors flock lastDrawnPosition lastLastDrawnPosition' classVariableNames: '' poolDictionaries: '' category: 'Sly-Boids'! Object subclass: #SlyBoids instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly-Boids'! Object subclass: #SlyDrawer instanceVariableNames: 'flock' classVariableNames: '' poolDictionaries: '' category: 'Sly-Boids'! Object subclass: #SlyEnsemble instanceVariableNames: 'members' classVariableNames: '' poolDictionaries: '' category: 'Sly'! Object subclass: #SlyEnsembleMessageDispatcher instanceVariableNames: 'members message originalReceiver originalSelector arguments return actualSelector messageAdverb argumentAdverbs messageEnvelopes argumentSources receiverSource receivers usingRoundRobin robinCount gerund executingSerially isAsAWhole' classVariableNames: 'RandomNumberSource' poolDictionaries: '' category: 'Sly'! Object subclass: #SlyFlock instanceVariableNames: 'boids isDone' classVariableNames: '' poolDictionaries: '' category: 'Sly-Boids'! Object subclass: #SlyGraphics instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly'! Object subclass: #SlyMessageEnvelope instanceVariableNames: 'receiver message' classVariableNames: '' poolDictionaries: '' category: 'Sly'! RVMTestSuite subclass: #SlySyntaxTests instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly'! !Scanner class methodsFor: 'class initialization' stamp: 'ssa 4/19/2010 20:31'! initialize | newTable | newTable _ Array new: 256 withAll: #xBinary. "default" newTable atAll: #(9 10 12 13 32 ) put: #xDelimiter. "tab lf ff cr space" newTable atAll: ($0 asciiValue to: $9 asciiValue) put: #xDigit. 1 to: 255 do: [:index | (Character value: index) isLetter ifTrue: [newTable at: index put: #xLetter]]. newTable at: 30 put: #doIt. newTable at: $" asciiValue put: #xDoubleQuote. newTable at: $# asciiValue put: #xLitQuote. newTable at: $% asciiValue put: #percent. newTable at: $$ asciiValue put: #xDollar. newTable at: $' asciiValue put: #xSingleQuote. newTable at: $: asciiValue put: #xColon. newTable at: $( asciiValue put: #leftParenthesis. newTable at: $) asciiValue put: #rightParenthesis. newTable at: $. asciiValue put: #period. newTable at: $; asciiValue put: #semicolon. newTable at: $[ asciiValue put: #leftBracket. newTable at: $] asciiValue put: #rightBracket. newTable at: ${ asciiValue put: #leftBrace. newTable at: $} asciiValue put: #rightBrace. newTable at: $^ asciiValue put: #upArrow. newTable at: $_ asciiValue put: #leftArrow. newTable at: $| asciiValue put: #verticalBar. TypeTable _ newTable "bon voyage!!" "Scanner initialize"! ! !Sly class methodsFor: 'testing' stamp: 'dmu 8/27/2010 13:38'! isSlySelector: aSelector "True if its has SlySelectorModifers" ^(aSelector beginsWith: SlySelectorModifier asAWhole) or:[(aSelector includesSubString: SlySelectorModifier adverbColon) or:[aSelector includesSubString: SlySelectorModifier gerundColon]]! ! Scanner initialize! !Object methodsFor: '*Sly' stamp: 'dmu 9/19/2010 22:45'! comma: x ^self , x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:43'! divideBy: x ^ self / x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:42'! minus: x ^ self - x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:42'! plus: x ^ self + x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:43'! times: x ^ self * x! ! !Object methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:00'! isEnsemble "Sly3Ensemble overrides to true" ^false! ! !Collection methodsFor: '*Sly' stamp: 'ssa 7/7/2010 19:50'! deactivateEnsembleSendsDuring: aBlock "disable messaging dispatching to members and just send it to myself during aBlock" 0 primitiveSetExtraPreheaderWord: self. aBlock value. self primitiveSetExtraPreheaderWord: self. ! ! Object subclass: #Sly3AbstractEnsembleMessageDispatcher instanceVariableNames: 'unprocessedMessage doneBlock ' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Basic-Dispatching'! Sly3AbstractEnsembleMessageDispatcher subclass: #Sly3EnsembleMessageDispatcher instanceVariableNames: 'parsedMessage' classVariableNames: 'RandomNumberSource' poolDictionaries: '' category: 'Sly3-Advanced-Dispatching'! Object subclass: #Sly3UnprocessedEnsembleMessage instanceVariableNames: 'receiver selector arguments members' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Basic-Dispatching'! !Collection methodsFor: '*Sly' stamp: 'dmu 9/8/2010 21:58'! sentToEnsemble: aMessage | r | r _ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage members: self). ^ r! ! !Integer methodsFor: 'explorer' stamp: 'ssa 7/7/2010 21:07'! hasContentsInExplorer ^false! ! !ScreenController methodsFor: 'menu messages' stamp: 'dmu 8/30/2010 10:44'! openSlyDashboard "Create and schedule a Sly dashboard." Sly3 dashboard! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/24/2010 14:13'! presentSlyMenu self popUpMenuFor: #slyMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/24/2010 14:12'! slyMenu ^ SelectionMenu labelList: #( 'dashboard' ) lines: #() selections: #(openSlyDashboard) " ScreenController new slyMenu startUp "! ! !Sly class methodsFor: 'user interfacing' stamp: 'dmu 8/27/2010 14:15'! dashboard "Sly dashboard " | topView buttons lastView subViewCount | topView := RVMStandardSystemView new . topView borderWidth:1. buttons _ { Transcript showInConsoleSwitch. self keepFlyingSwitch. RVMButtonView label:'[ SlyBoids new run ] fork' action:[[ SlyBoids new run ] fork]. RVMButtonView label:'Restore normal cursor' action:[Cursor normal show]. RVMButtonView label:'process browser' action:[ProcessBrowser open]. RVMButtonView label: 'SlySyntaxTests runAll' action: [SlySyntaxTests runAll]. }. lastView _ nil. buttons do:[:view| topView addSubView: view below: lastView. lastView _ view]. topView label: 'Sly'. subViewCount _ topView subViews size. topView minimumSize: 165@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !Sly class methodsFor: 'user interfacing' stamp: 'dmu 8/30/2010 10:44'! keepFlyingSwitch "Sly3 keepFlyingSwitch demo" ^RVMCheckBoxView on: self label: 'Keep SlyBoids Flying' checkState: [Sly3 keepFlying] whenChecked: [Sly3 keepFlying:true] whenUnchecked: [Sly3 keepFlying:false].! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:29'! keepFlying KeepFlying isNil ifTrue:[KeepFlying _ true]. ^KeepFlying! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! keepFlying: aBoolean KeepFlying _ aBoolean! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! toggleKeepFlying self keepFlying: self keepFlying not! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:51'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: #()]. ^ flock! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! flock: anObject "Set the value of flock" flock _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:57'! lastDrawnPosition "Answer the value of lastDrawnPosition" lastDrawnPosition isNil ifTrue:[self lastDrawnPosition: self position]. ^ lastDrawnPosition! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:00'! lastDrawnPosition: anObject "Set the value of lastDrawnPosition" lastDrawnPosition _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/23/2010 00:05'! lastLastDrawnPosition "Answer the value of lastLastDrawnPosition" lastLastDrawnPosition isNil ifTrue:[self lastLastDrawnPosition: self lastDrawnPosition]. ^ lastLastDrawnPosition! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/22/2010 23:53'! lastLastDrawnPosition: anObject "Set the value of lastLastDrawnPosition" lastLastDrawnPosition _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:53'! neighbors "Answer the value of neighbors" neighbors isNil ifTrue:[self neighbors: #()]. ^ neighbors! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! neighbors: anObject "Set the value of neighbors" neighbors _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! position "Answer the value of position" position isNil ifTrue:[self position: 500@500]. ^ position! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! position: anObject "Set the value of position" position _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! velocity "Answer the value of velocity" velocity isNil ifTrue:[self velocity: 0@0]. ^ velocity! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! velocity: anObject "Set the value of velocity" velocity _ anObject! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:42'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." "^500@500" "^ self flock boids positionING: #averaging" "^ self flock boids positionLY: #serially ING: #averaging" ^ (self flock boids members collect: [:m| m position]) average! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:43'! computeNeighbors "^self flock boids yourselfLY:{ #selectively:. [:b| b isNear: self]}" ^self flock boids members select:[:m| m isNear: self]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/22/2010 23:55'! draw | p | self lastDrawnPosition = self position ifTrue: [^ self]. p _ self position. false ifTrue: [ SlyGraphics drawWhiteCircle: self lastDrawnPosition. SlyGraphics drawCircle: p. "SlyGraphics drawFrom: self lastDrawnPosition to: p." ] ifFalse: [ SlyGraphics drawFrom: self lastDrawnPosition to: p. SlyGraphics eraseFrom: self lastLastDrawnPosition to: self lastDrawnPosition. ]. self lastLastDrawnPosition: self lastDrawnPosition. self lastDrawnPosition: p! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'ssa 3/25/2010 16:28'! fly | centroid | [Sly keepFlying] whileTrue:[ centroid _ self computeCentroid. self moveToNewPosition: centroid. self flock maybeYield ]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:15'! go self fly! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:43'! isNear: aBoid ^ (self ~== aBoid) and: [(self position dist: aBoid position) <= 10]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/17/2010 00:10'! keepAwayFromNeighbors | sum | self neighbors ifEmpty: [^ 0@0]. sum _ 0. self neighbors do: [:m | sum _ sum + (self position - m position)]. ^ sum / self neighbors size asFloat! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:30'! limitPositionFrom: min to: max | r pos | pos _ self position. r _ ((pos max: min@min) min: max@max). r = pos ifTrue: [^ self]. pos x < min ifTrue: [r _ min + (min - pos x) @ pos y. self velocity: self velocity x negated @ self velocity y]. pos y < min ifTrue: [r _ pos x @ (min + (min - pos y)). self velocity: self velocity x @ self velocity y negated]. pos x > max ifTrue: [r _ max - (pos x - max) @ pos y. self velocity: self velocity x negated @ self velocity y ]. pos y > max ifTrue: [r _ pos x @ (max - (pos y - max)). self velocity: self velocity x @ self velocity y negated]. self position: r! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:36'! limitVelocityTo: n | ns v vs q | ns _ n * n * 2. v _ self velocity. vs _ v x squared + v y squared. vs <= ns ifTrue: [^ self]. q _ (ns / vs) sqrt. self velocity: v * q.! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:53'! matchVelocityWithNeighbors self neighbors ifEmpty: [^ 0@0]. ^ (self neighbors collect: [:m| m velocity]) average / 8.0! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:04'! moveToNewPosition: centroid | a b c | self neighbors: self computeNeighbors. a _ self moveTowardCentroidOfAllOthers: centroid. b _ self keepAwayFromNeighbors. c _ self matchVelocityWithNeighbors. self velocity: self velocity + a + b + c. self limitVelocityTo: 10. self position: self position + self velocity. self limitPositionFrom: 0 to: 1000! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:43'! moveTowardCentroidOfAllOthers: centroid | perceivedCentroid s | s _ self flock boids members size. "was ENSsize" s < 2 ifTrue: [^ 0@0]. perceivedCentroid _ (centroid * s - self position) / (s - 1). ^ (perceivedCentroid - self position) / 100.0! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:54'! perturb self position: (self position perturb: 100). self velocity: (self velocity perturb: 2).! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:59'! run "Transcript show: (Time millisecondsToRun: [SlyBoids new run]); cr" "[ SlyBoids new run ] fork" | c flock drawer flockAndDrawer n | c _ OrderedCollection new. n _ self flockSize. 1 to: n do: [:i| c add: self boidClass new perturb]. flock _ SlyFlock boids: c asEnsembleOfElements. flock boids flock: flock. drawer _ SlyDrawer flock: flock. flockAndDrawer _ SlyEnsemble with: {flock. drawer}. "SlyGraphics clearScreen." flockAndDrawer go ! ! !SlyBoids class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:30'! run ^ self new run! ! !SlyDrawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: nil]. ^ flock! ! !SlyDrawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock: anObject "Set the value of flock" flock _ anObject! ! !SlyDrawer methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:49'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids members do: [:m | m draw. "self flock maybeYield"] ]! ! !SlyDrawer class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:07'! flock: f ^ self new flock: f! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 7/8/2010 00:50'! ENSsize ^members size! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 8/29/2010 12:53'! doesNotUnderstand: aMessage "Try to process this message as an ensemble dispatch message to help in the case of inlined primitive calls like perform:with:with:" ^ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage theEnsemble: self)! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/29/2010 01:04'! ensembleSpecies ^ SlyEnsemble! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/26/2010 00:34'! ifEmpty: blk ^ self sizeAsAWhole = 0 ifTrue: [blk value]! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 6/11/2010 14:50'! isEnsemble "Object answers false" ^true! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 6/17/2010 10:29'! members "you should never trust that the members collection stays the same within the ensemble" ^members copy! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 7/7/2010 13:57'! members: aCollection self primitiveSetExtraWordSelector: #sentToEnsemble:. aCollection primitiveSetExtraPreheaderWord: self. members _ aCollection. ^ self! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 23:48'! select: aBlock ^ self members select: aBlock! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:13'! size ^ self members size! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:25'! totalWithIdentity: id ^ self plus: id adverb: #reductively! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 16:35'! asExplorerString ^self printString! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 13:48'! printOn: out "Add a string that should compile back into an ensemble like me" out nextPutAll:'%{'. self members do:[:mem| mem ENSprintOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 13:51'! storeOn: out "Write a string on aStream that should compile back into an ensemble like me" out nextPut:$%;nextPut:${. self members do:[:mem| mem ENSstoreOn: out. out nextPut:$.]. out nextPut:$}. ! ! !SlyEnsemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:14'! explorerContents ^self members asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !SlyEnsemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:15'! hasContentsInExplorer ^self members isEmpty not! ! !SlyEnsemble methodsFor: 'disabling' stamp: 'ssa 7/7/2010 19:13'! deactivateEnsembleSendsDuring: aBlock "disable messaging dispatching to members and just send it to the ensemble object itself during aBlock" 0 primitiveSetExtraPreheaderWord: self. aBlock value. self members primitiveSetExtraPreheaderWord: self. ! ! !SlyEnsemble class methodsFor: 'as yet unclassified' stamp: 'dmu 3/28/2010 23:48'! with: aCollection ^ self new members: aCollection! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 10:58'! actualSelector "Answer the value of actualSelector" actualSelector isNil ifTrue:[self determineActualSelector]. ^ actualSelector! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:19'! actualSelector: anObject "Set the value of actualSelector" actualSelector _ anObject asSymbol. "(actualSelector = #readStream) ifTrue:[self halt:'FOUND IT!!']"! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:34'! argumentAdverbs "Answer the value of argumentAdverbs" argumentAdverbs isNil ifTrue:[self argumentAdverbs: "OrderedCollection new "(self arguments collect:[:e| nil])]. ^ argumentAdverbs! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! argumentAdverbs: anObject "Set the value of argumentAdverbs" argumentAdverbs _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:23'! argumentSources "Answer the value of argumentSources" argumentSources isNil ifTrue:[self argumentSources: Dictionary new]. ^ argumentSources! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:23'! argumentSources: anObject "Set the value of argumentSources" argumentSources _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 15:41'! arguments "Answer the value of arguments" arguments isNil ifTrue:[self arguments: self originalArguments]. ^ arguments! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:30'! arguments: anObject "Set the value of arguments" arguments _ anObject asOrderedCollection! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! gerund "Answer the value of gerund, nil, a #symbol, or a block" gerund isNil ifTrue:[self gerund: nil]. ^ gerund! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! gerund: anObject "Set the value of gerund" gerund _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! hasGerund "Answer true if we have a gerund" ^self gerund notNil! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! members "Answer the value of members" members isNil ifTrue:[self members: nil]. ^ members! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! members: anObject "Set the value of members" members _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/17/2010 16:21'! message: anObject "Set the value of message" message _ anObject. "force initialization" self originalReceiver . self arguments.! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! messageAdverb "Answer the value of messageAdverb" messageAdverb isNil ifTrue:[self messageAdverb: nil]. ^ messageAdverb! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! messageAdverb: anObject "Set the value of messageAdverb" messageAdverb _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 16:09'! messageEnvelopes "Answer the value of messageEnvelopes" messageEnvelopes isNil ifTrue:[self messageEnvelopes: OrderedCollection new]. ^ messageEnvelopes! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 16:08'! messageEnvelopes: anObject "Set the value of messageEnvelopes" messageEnvelopes _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:28'! originalArguments ^ self message arguments! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:35'! originalReceiver "Answer the value of originalReceiver" originalReceiver isNil ifTrue:[self error: 'should have been set at instantiation time']. ^ originalReceiver! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! originalReceiver: anObject "Set the value of originalReceiver" originalReceiver _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:22'! originalSelector "Answer the value of originalSelector" originalSelector isNil ifTrue:[self originalSelector: self message selector]. ^ originalSelector! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 18:48'! originalSelector: anObject "Set the value of originalSelector" "anObject = #selector ifTrue:[self halt]." "useful for debugging" Transcript cr;show:'Dispatching #',anObject. originalSelector _ anObject ! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 19:32'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:36'! receiverSource "Answer the value of receiverSource" receiverSource isNil ifTrue:[self receiverSource: self determineReceiverSource]. ^ receiverSource! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:35'! receiverSource: anObject "Set the value of receiverSource" receiverSource _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:41'! receivers "Answer the value of receivers" receivers isNil ifTrue:[self receivers: self determineReceivers]. ^ receivers! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:41'! receivers: anObject "Set the value of receivers" receivers _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/11/2010 11:11'! return "Answer the value of return" self halt:'Special case...hould never access this way'. return isNil ifTrue:[self return: nil]. ^ return! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 16:54'! robinCount "Answer the value of robinCount" robinCount isNil ifTrue:[self robinCount: 0]. ^ robinCount! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 16:54'! robinCount: anObject "Set the value of robinCount" robinCount _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 15:16'! usingRoundRobin "Answer the value of usingRoundRobin" usingRoundRobin isNil ifTrue:[self usingRoundRobin: self determineRoundRobin]. ^ usingRoundRobin! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:47'! usingRoundRobin: anObject "Set the value of usingRoundRobin" usingRoundRobin _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/28/2010 14:26'! applyAdverb: adverb toArgument: argument inEnvelope: envelope "Answer the final argument to send with the message being dispatched via this envelope. Common cases are #wholly (batch all args to each member with the message) #singly (distributed arguments one-to-one over members). Issue here with count mismatch. #roundly (distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs. #duplicatively (each member gets a copy of the arguments). Default case is #wholly" adverb isSymbol ifTrue:[^self perform: ('ARG',adverb,':inEnvelope:') asSymbol with: argument with: envelope]. adverb isBlock ifTrue:[^ adverb value: argument value: envelope]. self error:'adverbs can only be unarySelectors or Blocks at this point'! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/28/2010 17:04'! determineArgumentsForEachReceiver "Support for argument adverbs that allow arguments to be distributed/shared/paired/etc across members." | finalArg | self messageEnvelopes do:[:env| self arguments with: self argumentAdverbs withIndexDo:[:arg :adv :index| finalArg _ adv isNil ifTrue: [arg] ifFalse:["use adverb to determine and process the argument" self applyAdverb: adv toArgument: arg inEnvelope: env]. env message arguments at: index put: finalArg]] ! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 7/16/2010 19:35'! determineRoundRobin "Do any of my argument adverbs imply a round-robin use of my receivers?" self argumentAdverbs isEmpty ifTrue:[^false]. self argumentAdverbs with: self arguments do:[:adv :arg| adv = #roundly ifTrue:[self robinCount: arg ENSsize. ^true]]. ^false! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/12/2010 19:51'! determineSelectorForEachReceiver "Support for message adverbs that allow members to modify the message selector being sent. Expect this case rarely. Implement later. Default case is to use the actualSelector" self messageEnvelopes do:[:each| each message selector: self actualSelector]! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/12/2010 19:27'! receiversForAdverb: anAdverb "Answer the (sub)set of my members to send a message to based on this adverb" anAdverb isSymbol ifTrue:[^self perform: anAdverb]. anAdverb isArray ifTrue:[^self perform: anAdverb first withArguments: anAdverb allButFirst]. anAdverb isBlock ifTrue:[^anAdverb value: self members]. self error:'Expected a #symbol or aBlock for an adverb'! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 16:38'! anding:results "AND the elements in results and return the result. Assumes these elements understand &." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each & result]. ^result! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 7/7/2010 22:06'! applyGerundTo: results "use the gerund that was supplied by the sender to post-process the results of the message. ALL gerund processing starts here" self gerund isSymbol ifTrue:[^self perform: self gerund asKeyword with: results]. self gerund isBlock ifTrue:[^ gerund value: results]. self error:'gerunds can only be unarySelectors or Blocks at this point'! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:47'! averaging:results "Average the elements in results and return the result. Assumes these elements understand +." | sum | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. sum _ self totalling: results. ^sum / results size! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:35'! concatenating: results "Concatenate each element in results and return the result. Assumes these elements are collections of some kind." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ result , each]. ^result! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 16:39'! oring:results "OR the elements in results and return the result. Assumes these elements understand |." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each | result]. ^result! ! !SlyEnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:41'! totalling:results "Sum the elements in results and return the result. Assumes these elements understand +." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ 0. results do:[:each| result _ each + result]. ^result! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:27'! ARGReadMe "Argument adverbs set policies/strategies for how arguments participate in ensemble messages to the members. The ARG selector prefix is used to separate possible naming conflicts between message adverbs and argument adverbs. All argument adverbs found in a selector will get prefixed with ARG before being called. All argument adverb methods should begin with ARG and be of the form 'ARGadverbName: origArg inEnvelope: envelope'"! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:26'! ARGduplicatively: originalArgument inEnvelope: envelope "Each message uses a copy of the original argument" ^originalArgument copy! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:51'! ARGroundly: originalArgument inEnvelope: envelope "Each message uses one of the argument elements. Reuse receivers as needed in round-robin fashion. " ^self nextArgumentFromSource: originalArgument ifAtEnd:[^self] ! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:11'! ARGwholly: originalArgument inEnvelope: envelope "Each message uses original argument" ^originalArgument! ! !SlyEnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:46'! determineReceiverSource "Answer the stream(like) object that serves up my receivers" self usingRoundRobin ifTrue:[^RVMCircularCollection withAll: self receivers]. ^self receivers readStream! ! !SlyEnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:42'! determineReceivers "identify the (sub)set of my members that will actually be sent a message. This can change based on message adverbs (completely, randomly, stochastically:aProbability, selectively:aBooleanBlock, aBlock etc) and argument adverbs (singly, aBlock, etc)" "only handle message adverbs for now, otherwise default to all members" ^self hasMessageAdverb ifTrue:[self receiversForAdverb: self messageAdverb] ifFalse:[self members asOrderedCollection]. ! ! !SlyEnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:35'! nextReceiver "Answer the next receiver from a stream set up over my receivers. This stream will be linear in normal cases and circular in #roundly(round-robin) cases" | source | source _ self receiverSource. source atEnd ifTrue:[self error:'not enough receivers!!']. ^source next! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument sourcing' stamp: 'ssa 5/28/2010 14:50'! nextArgumentFromSource: argument "Answer the next element from a stream set up over argument. NOTE: this implementation assumes that the argument source understands #readStream. May want to have an alternative version passing in a block to do the stream creation" ^self nextArgumentFromSource: argument ifAtEnd: [self error:'not enough argument elements for members']. ! ! !SlyEnsembleMessageDispatcher methodsFor: 'argument sourcing' stamp: 'ssa 7/16/2010 19:28'! nextArgumentFromSource: argument ifAtEnd: aBlock "Answer the next element from a stream set up over argument. NOTE: this implementation assumes that the argument source understands #readStream. May want to have an alternative version passing in a block to do the stream creation" | source | source _ self argumentSources at: argument ifAbsentPut:[argument ENSisEnsemble ifTrue:[argument ENSmembers readStream] ifFalse:[argument readStream]]. source atEnd ifTrue:[aBlock value]. ^source next! ! !SlyEnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/27/2010 14:30'! dispatch | results | "NOTE: using non-local return to allow immediate exit from this method upon return determination" return _ [:result | ^ result]. "(self originalSelector endsWith:'equals:') ifTrue:[self halt]." self determineActualSelector. "gets selector to send to members and finds adverbs, gerunds and ENS" self isAsAWhole ifTrue:[self tryReflectiveMessages ]. self onlyHasGerund ifTrue:[self return: (self applyGerundTo: self members)]. results _ self sendMessageToMembersModeratedByAdverbs. self hasGerund ifTrue:[self return: (self applyGerundTo: results)]. self returnEnsembleContaining: results ! ! !SlyEnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 3/29/2010 00:01'! return: r return value: r! ! !SlyEnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'ssa 6/15/2010 11:17'! returnEnsembleContaining: membersOfResult "self return: ((self originalReceiver perform: #ensembleSpecies) with: membersOfResult)" self return: (SlyEnsemble with: membersOfResult) ! ! !SlyEnsembleMessageDispatcher methodsFor: 'reflection' stamp: 'ssa 6/17/2010 10:37'! OLDtryReflectiveMessages | reflectiveMessages r | self actualSelector = #members ifTrue:[self return: self members]. self actualSelector = #size ifTrue:[self return: self members size]. self actualSelector = #inspect ifTrue:[self return: self originalReceiver mirror inspect]. self actualSelector = #storeString ifTrue:[self return: self storeStringForMyEnsemble]. self actualSelector = #printString ifTrue:[self return: self storeStringForMyEnsemble]. self actualSelector = #printOn: ifTrue:[self return: (self originalArguments first nextPutAll: self storeStringForMyEnsemble)]. reflectiveMessages _ #( #isNil #isNotNil #isKindOf: #isInMemory #pointsTo: #nextObject #mustBeBooleanIn: #class #inspect #explore #hash #printString #printOn:). (reflectiveMessages includes: self actualSelector) ifTrue: [ 0 primitiveSetExtraPreheaderWord: self originalReceiver. r _ self originalReceiver perform: self actualSelector asSymbol withArguments: self originalArguments. self members primitiveSetExtraPreheaderWord: self originalReceiver. self return: r ].! ! !SlyEnsembleMessageDispatcher methodsFor: 'reflection' stamp: 'ssa 7/7/2010 20:15'! tryReflectiveMessages "disable messaging dispatching to members and just send it to the ensemble object itself" | result | 0 primitiveSetExtraPreheaderWord: self message lookupClass "was originalReceiver". result _ self originalReceiver perform: self actualSelector asSymbol withArguments: self originalArguments. self originalReceiver members: self originalReceiver members. "force preheader update" self return: result! ! !SlyEnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'ssa 6/17/2010 10:12'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! !SlyEnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 5/28/2010 17:08'! determineEnvelopes "Determine the number of envelopes needed and create them. NOTE: #roundly argument adverb will impact this number" self usingRoundRobin ifFalse:[self receivers do:[:each| self messageEnvelopes add: (SlyMessageEnvelope receiver: each selector: self actualSelector arguments: self arguments asArray copy)]] ifTrue:[self robinCount timesRepeat:[ self messageEnvelopes add: (SlyMessageEnvelope receiver: self nextReceiver selector: self actualSelector arguments: self arguments asArray copy)]]! ! !SlyEnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 7/8/2010 00:43'! sendMessageToMembersModeratedByAdverbs "default behavior when no adverbs found in message" self hasAdverbs ifFalse:[ self actualSelector = #members ifTrue:[self halt:'should never dispatch #members to members']. ^self members parallelCollect: [:elem| elem perform: self actualSelector withArguments: self arguments asArray]]. "now handle the general case for all possible adverbs" self determineEnvelopes. self determineSelectorForEachReceiver. self determineArgumentsForEachReceiver. self relocateReceiversIfNeeded. self relocateArgumentsIfNeeded. ^self sendMessages! ! !SlyEnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 7/14/2010 13:49'! sendMessages "Deliver the message envelopes and collect results. This must eventually handle adverbs for timing and recurring messages, determining when the ensemble message is 'done'. etc. For now, do the simplest thing, a parallelCollect:" "check for serially flag and handle appropriately" ^self executingSerially ifTrue:[self messageEnvelopes collect:[:env| env deliver]] ifFalse:[self messageEnvelopes parallelCollect: [:env| env deliver]]! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/27/2010 14:36'! completely "A message level adverb indicating all members are to receive the message" ^self members! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:35'! exclusively: aBlock "A message level adverb indicating to exclude certain members from receiving the message" ^self rejectively: aBlock! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:36'! inclusively: aBlock "A message level adverb indicating to include certain members for receiving the message" ^self selectively: aBlock! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:37'! randomly "A message level adverb indicating one member at random to receive the message" ^self randomly: 1! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/27/2010 10:42'! randomly: n "A message level adverb indicating n members at random to receive the message" | remainders chosen picked | remainders _ self members asOrderedCollection. chosen _ OrderedCollection new. n timesRepeat:[ remainders isEmpty ifTrue:[^chosen]. chosen add: (picked _ remainders atRandom). remainders remove: picked]. ^chosen! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 6/1/2010 16:41'! reflectively "A message level adverb indicating the ensemble itself is to receive the message. This duplicates the ENS prefix protocol using message adverbs to make it possible for programmatic reflective messaging without hacking the selector. This approach has the effect of making the ensemble itself appear as the single member of an ensemble" ^self originalReceiver! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:35'! rejectively: aBlock "A message level adverb indicating to exclude certain members from receiving the message" ^self members reject: aBlock! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:36'! selectively: aBlock "A message level adverb indicating to select certain members to receive the message" ^self members select: aBlock! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 6/1/2010 16:38'! stochastically: aProbability "A message level adverb indicating some probalilty (0.0-1.0) for each members to receive the message" ^self members select:[:each| self randomNumberSource next <= aProbability]! ! !SlyEnsembleMessageDispatcher methodsFor: 'relocating' stamp: 'ssa 5/27/2010 11:28'! relocateArgumentsIfNeeded "Supports argument adverbs that desire to be in special core locations relative to each other or to their receiving members. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !SlyEnsembleMessageDispatcher methodsFor: 'relocating' stamp: 'ssa 5/27/2010 11:28'! relocateReceiversIfNeeded "Supports message adverbs that desire to have member in special core locations relative to each other or to arguments. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !SlyEnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 14:30'! determineActualKeywordSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig actual | orig _ self originalSelector. actual _ orig copy asString. (orig beginsWith: SlySelectorModifier asAWhole) ifTrue:[self setAsAWhole. actual _ actual withoutFirst: SlySelectorModifier asAWholeSize]. ((actual includesSubString: SlySelectorModifier adverbColon) or: [actual includesSubString: SlySelectorModifier gerundColon]) ifFalse:[^actual ] ifTrue:[self isAsAWhole ifTrue:[self error:'reflective ENS sends can''t have adverbs or gerunds']. "handle gerund case" (actual last: SlySelectorModifier gerundColonSize)= SlySelectorModifier gerundColon ifTrue:[self gerund: self arguments removeLast. actual _ actual withoutLast: SlySelectorModifier gerundColonSize. ]. "handle adverb cases" ^(actual includesSubString: SlySelectorModifier adverbColon) ifTrue:[self handleAdverbKeywordIn: actual] ifFalse:[actual]. ] "Cases: Normal Smalltalk support: + => + unary => unary keyword: => keyword: Adverb support: unaryLY: => unary LY:keyword: => keyword: LY:keyword:LY: => keyword: LY:keyword:LY:keyword:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword:LY: => keyword:keyword:keyword: LY:keyword:keyword:LY:keyword:LY: => keyword:keyword:keyword: etc., strip all LY:s Gerund (reducer) support: unaryING: => unary keyword:ING: => keyword: keyword:keyword:keyword:keyword:ING: => keyword:keyword:keyword:keyword: etc., strip all ING:s, though there should only be one per selector DotDot, reflective send support: ENSunary => unary ENSkeyword: => keyword: ENSkeywordLY: => error, smae with ING " ! ! !SlyEnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'ssa 5/12/2010 15:51'! determineActualSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed" self actualSelector: self findActualSelector! ! !SlyEnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 14:28'! determineActualUnarySelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig | orig _ self originalSelector. (orig beginsWith: SlySelectorModifier asAWhole) ifTrue:[self isAsAWhole: true. orig _ orig copyFrom: SlySelectorModifier asAWholeSize + 1 to: orig size]. ^orig. "Cases: Normal Smalltalk support: unary => unary Adverb support: unaryLY: => unary Gerund (reducer) support: unaryING: => unary DotDot, reflective send support: ENSunary => unary " ! ! !SlyEnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'ssa 5/12/2010 15:45'! findActualSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig | orig _ self originalSelector. orig isInfix ifTrue:[^orig]. "strategy extensions not supported on binary messages" orig isUnary ifTrue:[^self determineActualUnarySelector]. orig isKeyword ifTrue:[^self determineActualKeywordSelector]. self error:'Unknown selector type for ',orig. "Cases: Normal Smalltalk support: + => + unary => unary keyword: => keyword: Adverb support: unaryLY: => unary LY:keyword: => keyword: LY:keyword:LY: => keyword: LY:keyword:LY:keyword:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword:LY: => keyword:keyword:keyword: LY:keyword:keyword:LY:keyword:LY: => keyword:keyword:keyword: etc., strip all LY:s Gerund (reducer) support: unaryING: => unary keyword:ING: => keyword: keyword:keyword:keyword:keyword:ING: => keyword:keyword:keyword:keyword: etc., strip all ING:s, though there should only be one per selector DotDot, reflective send support: ENSunary => unary ENSkeyword: => keyword: ENSkeywordLY: => error, same with ING " ! ! !SlyEnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 13:46'! handleAdverbKeywordIn: selector "Locate the *LY: keywords and extract adverb arguments, and set real arguments, Answer the selector stripped of LY:s " | keywords adverbOffset keyword argIndex strippedSelector realArgs lastWasAdverb | lastWasAdverb _ true. keywords _ selector subStrings: {$:}. adverbOffset _ 0. realArgs _ OrderedCollection new. strippedSelector _ ''. 1 to: keywords size do:[:index| keyword _ keywords at: index. (keyword endsWith: SlySelectorModifier adverb) ifTrue:["found an adverb keyword" index = 1 ifTrue:["its the message adverb" self messageAdverb: (self arguments first). adverbOffset _ 1. keyword = SlySelectorModifier adverb ifFalse:[" the unary case, e.g., oddLY " strippedSelector _ (keyword withoutLast: SlySelectorModifier adverbSize). keywords size > 1 ifTrue:[strippedSelector _ strippedSelector,':']] ifTrue:["the keyword case LY: adv foo: bar" "do nothing, let the first keyword drop"]] ifFalse:["its an argument adverb" lastWasAdverb _ true. argIndex _ index - adverbOffset. self argumentAdverbs at: argIndex put:(self arguments at: argIndex). "DO NOTHING HERE was: strippedSelector _ strippedSelector,(keyword withoutLast: SlySelectorModifier adverbSize),':'"]] ifFalse:["normal keyword found or ING found" (keyword endsWith: SlySelectorModifier gerund) ifFalse:[ lastWasAdverb ifFalse:[self argumentAdverbs add: nil]. lastWasAdverb _ false. realArgs add:(self arguments at: index). strippedSelector _ strippedSelector,keyword,':']]]. self arguments: realArgs. ^strippedSelector! ! !SlyEnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:12'! hasAdverbs ^self hasMessageAdverb or:[self hasArgumentAdverbs]! ! !SlyEnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:13'! hasArgumentAdverbs self argumentAdverbs detect:[:each| each notNil] ifNone:[^false]. ^true! ! !SlyEnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:13'! hasMessageAdverb ^self messageAdverb notNil! ! !SlyEnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/11/2010 15:45'! onlyHasGerund "True is the selector is only #ING: " ^self originalSelector == #ING:! ! !SlyEnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'ssa 7/8/2010 00:13'! dispatch: aMessage members: aCollection originalReceiver: anObject ^ self new originalReceiver: anObject; message: aMessage; members: aCollection; dispatch! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:39'! boids "Answer the value of boids" ^ boids! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:11'! boids: anObject "Set the value of boids" boids _ anObject! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone "Answer the value of isDone" isDone isNil ifTrue:[self isDone: false]. ^ isDone! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone: anObject "Set the value of isDone" isDone _ anObject! ! !SlyFlock methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:13'! go self isDone: false. boids fly. self isDone: true! ! !SlyFlock methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 17:09'! maybeYield | n | "[Processor yield. ^self]value." n _self boids ENSsize + 1 "1 for Drawer". Processor yieldIfFewerCoresThan: n! ! !SlyFlock class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:11'! boids: b ^ self new boids: b! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! clearScreen Display fillWhite! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! drawCircle: pt Display drawDot5At: pt! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:03'! drawFrom: ptA to: ptB Display drawLineFrom: ptA to: ptB color: Color black! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:04'! drawWhiteCircle: pt Display eraseDot5At: pt! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/23/2010 00:02'! eraseFrom: ptA to: ptB Display eraseLineFrom: ptA to: ptB color: Color black! ! !SlyMessageEnvelope methodsFor: 'delivering' stamp: 'ssa 6/1/2010 16:31'! deliver "send my message to my receiver and return the reply" self message arguments: self message arguments asArray. ^self message sentTo: self receiver! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:03'! message: anObject "Set the value of message" message _ anObject. ! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver "Answer the value of receiver" receiver isNil ifTrue:[self receiver: nil]. ^ receiver! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !SlyMessageEnvelope methodsFor: 'printing' stamp: 'ssa 5/28/2010 16:17'! printOn: aStream aStream nextPutAll:'MsgEnv|rcvr:',self receiver printString,'|message: ',self message printString! ! !SlyMessageEnvelope class methodsFor: 'instance creation' stamp: 'ssa 5/27/2010 10:46'! receiver: anObject selector: aSymbol arguments: anArray ^self new receiver: anObject; message: (Message selector: aSymbol arguments: anArray); yourself! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/14/2010 13:50'! executingSerially "Answer the value of executingSerially" executingSerially isNil ifTrue:[self executingSerially: false]. ^ executingSerially! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/14/2010 13:50'! executingSerially: anObject "Set the value of executingSerially" executingSerially _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 7/14/2010 13:55'! serially "Execute this message serially to all my members. This is a hack since currently all message adverbs must return the members to make envelopes for" self executingSerially:true. ^self members! ! !RVMTester class methodsFor: 'primitives' stamp: 'ssa 7/16/2010 14:59'! numberOfProcessInstances ^Process instanceCount! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 7/16/2010 15:03'! processInstanceCount "Answer the value of processInstanceCount" processInstanceCount isNil ifTrue:[self processInstanceCount: Process instanceCount]. ^ processInstanceCount! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 7/16/2010 15:02'! processInstanceCount: anObject "Set the value of processInstanceCount" processInstanceCount _ anObject! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 7/16/2010 15:21'! processCount ^self processInstanceCount! ! !Object methodsFor: 'comparing' stamp: 'dmu 8/27/2010 13:27'! equals: anObject "a keyword verion of = for use with SlySelectorModifiers" ^self = anObject! ! !Object methodsFor: 'comparing' stamp: 'dmu 8/27/2010 13:26'! doubleEquals: anObject "a keyword verion of == for use with selector modifiers in Sly" ^self == anObject! ! Object subclass: #ClassAndMethodSaver instanceVariableNames: 'rootName rootDirectory classDir baseDir metaDir' classVariableNames: '' poolDictionaries: '' category: 'DMU-Tools'! !ClassAndMethodSaver commentStamp: 'dmu 8/23/2010 13:56'! Save all class definitions and method definitions to a directory tree so I can use FileMerge! !ClassAndMethodSaver methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 14:01'! save self createRoot. self saveAllClasses.! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:41'! createRoot self rootDirectory: ( self createDir: self rootName in: FileDirectory default mustBeNew: false )! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:04'! rootDirectory "Answer the value of rootDirectory" rootDirectory isNil ifTrue:[self rootDirectory: nil]. ^ rootDirectory! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:04'! rootDirectory: anObject "Set the value of rootDirectory" rootDirectory _ anObject! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:00'! rootName "Answer the value of rootName" rootName isNil ifTrue:[self rootName: 'root']. ^ rootName! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:00'! rootName: anObject "Set the value of rootName" rootName _ anObject! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:35'! classCategoryDirFor: cat ^ self createDir: cat in: self rootDirectory mustBeNew: false! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:34'! createDir: leafName in: parentDir mustBeNew: mustBeNew | p d | p _ parentDir pathName, parentDir pathNameDelimiter, leafName. d _ FileDirectory on: p. (mustBeNew and: [d exists]) ifTrue: [self error: p, ' already exists']. d exists ifFalse: [d assureExistence]. ^ d ! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:38'! createDirectoriesFor: cls | catDir | catDir _ self classCategoryDirFor: cls category. classDir _ self createDir: cls name in: catDir mustBeNew: false. baseDir _ self createDir: 'base' in: classDir mustBeNew: false. metaDir _ self createDir: 'meta' in: classDir mustBeNew: false.! ! !ClassAndMethodSaver methodsFor: 'saving methods' stamp: 'dmu 10/1/2010 22:58'! methodSourceFor: sel in: clsHalf | method | method := clsHalf methodDict at: sel ifAbsent: [^ sel printString, 'CORRUPTED']. ^ (method getSourceFor: sel in: clsHalf) asString! ! !ClassAndMethodSaver methodsFor: 'saving methods' stamp: 'dmu 10/1/2010 22:59'! saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir | src fs selOrFoo | src _ self methodSourceFor: sel in: clsHalf. selOrFoo _ (sel isKindOf: String) ifTrue: [sel] ifFalse: [sel printString]. fs _ self fileStreamIn: catDir named: selOrFoo, '.txt'. fs nextPutAll: src. fs close ! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:46'! fileStreamIn: dir named: n | fs | fs _ FileStream fileNamed: dir pathName, dir pathNameDelimiter, n. ^ fs! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:01'! saveAllClasses Smalltalk allClassesDo: [:cls| self saveClass: cls]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 15:00'! saveCategory: cat of: clsHalf in: dir | selectors catDir | catDir _ self createDir: cat in: dir mustBeNew: false. selectors := (cat asString = ClassOrganizer allCategory) ifTrue: [ clsHalf organization allMethodSelectors ] ifFalse: [ clsHalf organization listAtCategoryNamed: cat ]. selectors do: [:sel| self saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:39'! saveClass: cls self createDirectoriesFor: cls. self saveClassHalf: cls in: baseDir. self saveClassHalf: cls class in: metaDir! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:52'! saveClassHalf: clsHalf in: dir self saveClassHalfDefinition: clsHalf in: dir. self saveClassHalfComment: clsHalf in: dir. self saveClassHalfCategories: clsHalf in: dir! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:53'! saveClassHalfCategories: clsHalf in: dir clsHalf organization categories do: [:cat | self saveCategory: cat of: clsHalf in: dir]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 15:15'! saveClassHalfComment: clsHalf in: dir | fs | fs _ self fileStreamIn: dir named: 'comment.txt'. fs nextPutAll: clsHalf organization classComment asString. fs close.! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:48'! saveClassHalfDefinition: clsHalf in: dir | fs | fs _ self fileStreamIn: dir named: 'definition.txt'. fs nextPutAll: clsHalf definition. fs close.! ! ClassAndMethodSaver class instanceVariableNames: ''! !ClassAndMethodSaver class methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 16:32'! save "ClassAndMethodSaver save" ^self saveIn: 'root'! ! !ClassAndMethodSaver class methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 13:59'! saveIn: rootName (self new rootName: rootName) save! ! !Collection methodsFor: 'RVM-converting' stamp: 'dmu 9/16/2010 23:43'! doInParallel: aBlock self parallelCollect: aBlock! ! !SystemDictionary methodsFor: '*Sly' stamp: 'dmu 8/23/2010 15:38'! allClassesDoInParallel: aBlock "Evaluate the argument, aBlock, for each class in the system." (self classNames collect: [:name | self at: name]) doInParallel: aBlock! ! !SystemNavigation methodsFor: '*Sly' stamp: 'dmu 8/23/2010 15:39'! parallelAllMethodsWithSourceString: aString matchCase: caseSensitive "Answer a SortedCollection of all the methods that contain, in source code, aString as a substring. Search the class comments also" "An experiment -- dmu" | list classCount adder sema | list _ Set new. sema _ Semaphore forMutualExclusion. adder _ [ :mrClass :mrSel | sema critical: [list add: ( MethodReference new setStandardClass: mrClass methodSymbol: mrSel)]]. 'Searching all source code...' displayProgressAt: Sensor cursorPoint from: 0 to: Smalltalk classNames size during: [:bar | classCount _ 0. Smalltalk allClassesDoInParallel: [:class | bar value: (classCount _ classCount + 1). (Array with: class with: class class) do: [:cl | cl selectorsDo: [:sel | ((cl sourceCodeAt: sel) findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ sel == #DoIt ifFalse: [adder copy fixTemps value: cl value: sel]]]. (cl organization classComment asString findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ adder copy fixTemps value: cl value: #Comment]. ]]]. ^ list asSortedCollection! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 17:08'! flockSize "RVMTester coreCount - 6 max: 10". ^ 250! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:52'! boidClass ^ SlyBoid! ! !RVMMultiAspectKiviatView methodsFor: 'displaying' stamp: 'dmu 8/23/2010 17:38'! resetAfterCoreCountChange self spokePens: nil. backgroundCanvas _ nil! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:38'! resetAfterCoreCountChange self spokePens: nil. backgroundCanvas _ nil! ! Object subclass: #ChangedMethodFinder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'DMU-Tools'! !ChangedMethodFinder methodsFor: 'no messages' stamp: 'dmu 8/25/2010 15:56'! isMethodChanged: aMethod ^ (SourceFiles at: 1) ~= aMethod sourceFileStream! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:17'! changedMethods "ChangedMethodFinder new changedMethods" | result | result _ OrderedCollection new. Smalltalk allClassesDo: [:cls| {cls. cls class.} do: [:clsHalf| clsHalf methodDict associationsDo: [:a | (self isMethodChanged: a value) ifTrue: [ result add: { cls category. cls name. clsHalf name. clsHalf organization categoryOfElement: a key. a key} ] ] ] ]. ^ result! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:17'! standardClassNames "ChangedMethodFinder new standardClassNames" | result | result _ Set new. Smalltalk allClassesDo: [:cls| {cls. cls class.} do: [:clsHalf| clsHalf methodDict associationsDo: [:a | (self isMethodChanged: a value) ifFalse: [result add: cls name] ] ] ]. ^ result! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:19'! changedMethodsInStandardClasses "ChangedMethodFinder new changedMethodsInStandardClasses" | changedMethods standardClassNames result | changedMethods _ self changedMethods. standardClassNames _ self standardClassNames. result _ changedMethods select: [:e| standardClassNames includes: (e at: 2)]. ^ result! ! Object subclass: #SlySelectorModifier instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly'! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:30'! asAWhole ^ 'ENS'! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:30'! adverb ^ 'LY'! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:30'! gerund ^ 'ING'! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:35'! gerundColon ^ self gerund, ':'! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:35'! adverbColon ^ self adverb, ':'! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:35'! adverbColonSize ^ self adverbColon size! ! !SlySelectorModifier class methodsFor: 'sizes' stamp: 'dmu 8/27/2010 14:17'! gerundColonSize ^ self gerundColon size! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:40'! asAWholeSize ^ self asAWhole size! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:44'! adverbSize ^ self adverb size! ! !SlySelectorModifier class methodsFor: 'commonly modified selectors' stamp: 'dmu 8/29/2010 18:36'! asAWholeify: selector (selector beginsWith: self asAWhole) ifTrue: [^ self]. ^ (self asAWhole, selector) asSymbol! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:52'! sizeAsAWhole ^ self asAWholeify: #size! ! !SlySelectorModifier class methodsFor: 'special selectors' stamp: 'dmu 8/27/2010 13:56'! members ^ #members! ! !SlySelectorModifier class methodsFor: 'special selectors' stamp: 'dmu 8/27/2010 13:59'! equalsAsAWhole ^ ( self asAWhole, 'equals:' ) asSymbol! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:28'! isAsAWhole "Answer the value of isAsAWhole" isAsAWhole isNil ifTrue:[self isAsAWhole: false]. ^ isAsAWhole! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:28'! isAsAWhole: anObject "Set the value of isAsAWhole" isAsAWhole _ anObject! ! !SlyEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:29'! setAsAWhole self isAsAWhole: true! ! Sly3AbstractEnsembleMessageDispatcher subclass: #Sly3ReflectiveMessageDispatcher instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Basic-Dispatching'! !Sly3ReflectiveMessageDispatcher commentStamp: 'dmu 8/27/2010 14:38'! No matter what Sly is, ST depends on some reflective messages. Handle them here. -- dmu Possible useful expressions for doIt or printIt. Structure: instVar1 type -- comment about the purpose of instVar1 instVar2 type -- comment about the purpose of instVar2 Any further useful comments about the general approach of this implementation.! !Sly3ReflectiveMessageDispatcher commentStamp: 'dmu 8/27/2010 14:38'! No matter what Sly is, ST depends on some reflective messages. Handle them here. -- dmu Possible useful expressions for doIt or printIt. Structure: instVar1 type -- comment about the purpose of instVar1 instVar2 type -- comment about the purpose of instVar2 Any further useful comments about the general approach of this implementation.! !Sly3ReflectiveMessageDispatcher methodsFor: 'modifying reflective selectors' stamp: 'dmu 8/29/2010 13:28'! modifyReflectiveSelectorIfNeeded (self unprocessedMessage selector beginsWith: SlySelectorModifier asAWhole) ifTrue: [^ self]. self modifyEquals or: [ self modifyToolMessages or: [ self modifyToolProcesses]]! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'modifying reflective selectors' stamp: 'dmu 8/29/2010 13:29'! modifyEquals self unprocessedMessage selector = #= ifTrue:[self setUnprocessedSelector: SlySelectorModifier equalsAsAWhole. ^ true]. ^ false ! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'modifying reflective selectors' stamp: 'dmu 8/29/2010 13:32'! modifyToolMessages | toolMessages | toolMessages _ #(inspect explore printString asExplorerString hasContentsInExplorer explorerContents halt error: halt:). (toolMessages includes: self unprocessedMessage selector) ifTrue:[ self setUnprocessedSelector: (SlySelectorModifier asAWholeify: self unprocessedMessage selector). ^ true ]. ^ false! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'modifying reflective selectors' stamp: 'dmu 8/29/2010 18:36'! modifyToolProcesses | foundContext toolClasses | toolClasses _ { Inspector. Debugger. PluggableListController}. foundContext _ thisContext findContextSuchThat:[:ctxt| toolClasses includes: ctxt receiver class]. foundContext notNil ifTrue:[ self setUnprocessedSelector: (SlySelectorModifier asAWholeify: self unprocessedMessage selector). ^ true]. ^ false! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 19:04'! originalArguments ^ self unprocessedMessage arguments! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 19:32'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:29'! setAsAWhole self isAsAWhole: true! ! !Sly3EnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'dmu 8/29/2010 19:00'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self unprocessedMessage members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! Sly3EnsembleMessageDispatcher class instanceVariableNames: ''! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:28'! dispatch ! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'dmu 8/29/2010 12:56'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self unprocessedMessage members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! Sly3AbstractEnsembleMessageDispatcher class instanceVariableNames: ''! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! selector "Answer the value of selector" selector isNil ifTrue:[self selector: #noSelector]. ^ selector! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! selector: anObject "Set the value of selector" selector _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! arguments "Answer the value of arguments" arguments isNil ifTrue:[self arguments: #()]. ^ arguments! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! arguments: anObject "Set the value of arguments" arguments _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! members "Answer the value of members" members isNil ifTrue:[self members: #()]. ^ members! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! members: anObject "Set the value of members" members _ anObject! ! !Sly3UnprocessedEnsembleMessage class methodsFor: 'instance creation' stamp: 'dmu 8/30/2010 19:37'! fromMessage: m members: members ^ self new receiver: m lookupClass "VM hack"; selector: m selector; arguments: m arguments; members: members; yourself! ! !Sly3UnprocessedEnsembleMessage class methodsFor: 'instance creation' stamp: 'dmu 8/30/2010 19:38'! fromMessage: m theEnsemble: e ^ self new receiver: e; selector: m selector; arguments: m arguments; members: e members; yourself! ! !Sly3AbstractEnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:27'! dispatch: anUnprocessedMessage self dispatch: anUnprocessedMessage andDo: [:r | ^ r]. self error: 'unhandled'! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:56'! unprocessedMessage "Answer the value of unprocessedMessage" unprocessedMessage isNil ifTrue:[self unprocessedMessage: Sly3UnprocessedEnsembleMessage new]. ^ unprocessedMessage! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:55'! unprocessedMessage: anObject "Set the value of unprocessedMessage" unprocessedMessage _ anObject! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'created processed message' stamp: 'dmu 8/29/2010 18:32'! justReturn: anObject self doneBlock value: anObject! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'created processed message' stamp: 'dmu 9/1/2010 23:30'! sendToMembers: selector self doneBlock value: (Sly3MessageEnvelope receiver: self unprocessedMessage members selector: selector arguments: self unprocessedMessage arguments) deliver! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 9/8/2010 02:54'! tryReflectiveMessageSend | message selector | message _ self unprocessedMessage. selector _ message selector. selector = #members ifTrue: [self justReturn: message members]. ((selector = #isKindOf: and:[message arguments first = FakeClassPool]) or: [(selector = #== ) and:[message arguments first = #failedDoit] ] ) ifTrue:[self justReturn: false]. (#(hash halt error: halt: identityHash == isNil) includes: selector) ifTrue: [self justReturn: (message receiver class deactivateEnsembleSendsFor: message receiver during: [message receiver perform: message selector withArguments: message arguments])]. (selector = #isKindOf:) ifTrue: [self justReturn: (Sly3Ensemble includesBehavior: message arguments first)]! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'nil' stamp: 'dmu 8/29/2010 13:29'! setUnprocessedSelector: sel self unprocessedMessage selector: sel! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:24'! doneBlock "Answer the value of doneBlock" doneBlock isNil ifTrue:[self doneBlock: [:r | ^ r]]. ^ doneBlock! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:24'! doneBlock: anObject "Set the value of doneBlock" doneBlock _ anObject! ! !Sly3AbstractEnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:26'! dispatch: anUnprocessedMessage andDo: doneBlock ^ self new unprocessedMessage: anUnprocessedMessage; doneBlock: [:r | ^ doneBlock value: r]; dispatch! ! !Sly3EnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 9/1/2010 23:18'! dispatch self parsedMessage: self parseMessage. self parsedMessage ifNil: [^ self]. ^ self doneBlock value: ( Sly3MessageEvaluator evaluate: self parsedMessage ) ! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:40'! dispatch self tryReflectiveMessageSend. ! ! Object subclass: #Sly3ReflectiveSelectorChanger instanceVariableNames: 'message selector' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Basic-Dispatching'! !Sly3EnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 12:27'! dispatch: anUnprocessedMessage andDo: doneBlock | newMessage | Sly3ReflectiveMessageDispatcher dispatch: anUnprocessedMessage andDo: [:r| ^ doneBlock value: r]. newMessage _ Sly3ReflectiveSelectorChanger modifyAsNeeded: anUnprocessedMessage. ^super dispatch: newMessage andDo: doneBlock! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:49'! parsedMessage "Answer the value of parsedMessage" parsedMessage isNil ifTrue:[self parsedMessage: nil]. ^ parsedMessage! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:49'! parsedMessage: anObject "Set the value of parsedMessage" parsedMessage _ anObject! ! Object subclass: #Sly3ParsedMessage instanceVariableNames: 'receiverMirror selector gerunds messageAdverbs argumentMirrors argumentAdverbs receiver members arguments' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Advanced-Dispatching'! Object subclass: #SlyModifierString instanceVariableNames: 'modifierName modifierSuffix' classVariableNames: '' poolDictionaries: '' category: 'Sly'! !Sly3EnsembleMessageDispatcher methodsFor: 'parsing message' stamp: 'dmu 8/29/2010 21:54'! parseMessage ^ Sly3MessageParser parse: self unprocessedMessage ! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:08'! selector "Answer the value of selector" selector isNil ifTrue:[self selector: #noSelector]. ^ selector! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:08'! selector: anObject "Set the value of selector" selector _ anObject! ! Sly3Gerund subclass: #Sly3ModAveraging instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Gerund subclass: #Sly3ModConcatenating instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Object subclass: #Sly3MessageParser instanceVariableNames: 'unparsedMessage parsedMessage unparsedSelector arguments keywordModifiersAssociations argumentModifiers messageModifier actualSelector messageModifiers stringsAndModifiersMergingReceiverAndFirstArgument flatStringsAndModifiers foldedFlatStringsAndModifiers modifiersForRcvrAndArgs flatKeywordsAndModifiers modifiersWithDefaults' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Advanced-Dispatching'! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:21'! parsedMessage "Answer the value of parsedMessage" parsedMessage isNil ifTrue:[self parsedMessage: nil]. ^ parsedMessage! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:21'! parsedMessage: anObject "Set the value of parsedMessage" parsedMessage _ anObject! ! !Sly3MessageParser class methodsFor: 'as yet unclassified' stamp: 'dmu 8/29/2010 21:22'! parse: m ^self new unparsedMessage: m; parse; parsedMessage! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:22'! unparsedMessage "Answer the value of unparsedMessage" unparsedMessage isNil ifTrue:[self unparsedMessage: nil]. ^ unparsedMessage! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:22'! unparsedMessage: anObject "Set the value of unparsedMessage" unparsedMessage _ anObject! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 10/1/2010 00:17'! parse unparsedSelector _ self unparsedMessage selector. unparsedSelector = #mustBeBoolean ifTrue: [self halt]. arguments _ self unparsedMessage arguments. flatStringsAndModifiers _ self dissectSelectorIntoStringsAndModifiers: unparsedSelector. flatKeywordsAndModifiers _ self breakStringsIntoKeywords: flatStringsAndModifiers. self foldInIndirectModifiers: [:s :a | foldedFlatStringsAndModifiers _ s. arguments _ a]. actualSelector _ self gatherActualSelector. modifiersForRcvrAndArgs _ self breakModifiersForArguments. modifiersWithDefaults _ self addDefaultModifiersTo: modifiersForRcvrAndArgs. messageModifiers _ modifiersWithDefaults first. argumentModifiers _ modifiersWithDefaults copyWithoutFirst. parsedMessage _ self createParsedMessage.! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/3/2010 19:52'! gatherActualSelector | sel | sel _ ((foldedFlatStringsAndModifiers select: [:a| a isKindOf: String]) gather: [:a | a ]) as: Symbol. ^ sel ifEmpty: [#yourself] ifNotEmpty: [sel]! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/3/2010 19:44'! createParsedMessage. ^ Sly3ParsedMessage receiver: self unparsedMessage receiver members: self unparsedMessage members messageModifiers: messageModifiers selector: actualSelector arguments: self arguments argumentAdverbs: argumentModifiers ! ! Object subclass: #Sly3MessageEvaluator instanceVariableNames: 'message envelopes receiverAndArgumentCounts result defaultingToAsAWhole putResultsIntoAnEnsemble operandTuples' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Advanced-Dispatching'! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:55'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:55'! message: anObject "Set the value of message" message _ anObject! ! !Sly3MessageEvaluator class methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 21:55'! evaluate: message | r | r _ self new message: message; evaluate. ^ r! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 10/6/2010 14:19'! evaluate | r | message selector = #particle:ofSize:movedTo: ifTrue: [self halt]. putResultsIntoAnEnsemble _ false. operandTuples _ self buildOperandTuples. envelopes _ self makeEnvelopes. self stuffSelectors. self stuffReceivers. self stuffArguments. self relocateReceiversIfNeeded. self relocateArgumentsIfNeeded. self setDisableEnsembleBehaviorFlags. result _ self sendMessages. putResultsIntoAnEnsemble _ self calculatePutResultsIntoAnEnsemble. r _ self evaluateGerunds. ^ r ! ! !Sly3ParsedMessage methodsFor: 'testing' stamp: 'dmu 9/1/2010 16:09'! hasGerund ^ gerunds notEmpty ! ! Object subclass: #Sly3Ensemble instanceVariableNames: 'members' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! !Sly3Ensemble methodsFor: 'environment support' stamp: 'dmu 8/29/2010 12:53'! doesNotUnderstand: aMessage "Try to process this message as an ensemble dispatch message to help in the case of inlined primitive calls like perform:with:with:" ^ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage theEnsemble: self)! ! !Sly3Ensemble methodsFor: 'environment support' stamp: 'dmu 3/29/2010 01:04'! ensembleSpecies ^ Sly3Ensemble! ! !Sly3Ensemble methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:55'! ifEmpty: blk ^ self collecitonLYsize = 0 ifTrue: [blk value]! ! !Sly3Ensemble methodsFor: 'testing' stamp: 'dmu 9/3/2010 14:54'! isEnsemble "Sly3Ensemble overrides to true" ^true! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'ssa 6/17/2010 10:29'! members "you should never trust that the members collection stays the same within the ensemble" ^members copy! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/19/2010 22:53'! members: aCollection "crude check:" self primitiveSetExtraWordSelector: #sentToEnsemble:. aCollection primitiveSetExtraPreheaderWord: self. members _ aCollection. ^ self! ! !Sly3Ensemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 23:48'! select: aBlock ^ self members select: aBlock! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 8/30/2010 01:53'! size ^ members size! ! !Sly3Ensemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:25'! totalWithIdentity: id ^ self plus: id adverb: #reductively! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 16:35'! asExplorerString ^self printString! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:50'! printOn: out "Add a string that should compile back into an ensemble like me" out nextPutAll:'%{'. self members do:[:mem| mem printOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:51'! storeOn: out "Write a string on aStream that should compile back into an ensemble like me" out nextPut:$%;nextPut:${. self members do:[:mem| mem storeOn: out. out nextPut:$.]. out nextPut:$}. ! ! !Sly3Ensemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:14'! explorerContents ^self members asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !Sly3Ensemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:15'! hasContentsInExplorer ^self members isEmpty not! ! Sly3Ensemble class instanceVariableNames: ''! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:18'! stuffReceivers envelopes with: operandTuples do: [:e :ot| e receiver: ot first]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/13/2010 00:13'! stuffSelectors "placeholder; could vary" envelopes do: [:e| e message setSelector: message selector]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:21'! stuffArguments envelopes with: operandTuples do: [:e :ot| 1 to: ot size -1 do: [:i| e message arguments at: i put: (ot at: i + 1)]]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 8/30/2010 01:26'! relocateReceiversIfNeeded "Supports message adverbs that desire to have member in special core locations relative to each other or to arguments. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 8/30/2010 01:27'! relocateArgumentsIfNeeded "Supports argument adverbs that desire to be in special core locations relative to each other or to their receiving members. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/21/2010 00:26'! sendMessages "Deliver the message envelopes and collect results. This must eventually handle adverbs for timing and recurring messages, determining when the ensemble message is 'done'. etc. For now, do the simplest thing, a parallelCollect:" | payloadBlock | payloadBlock _ [:env| Processor thisProcess creatorEnsemble: env receiver. env deliver]. "check for serially flag and handle appropriately" ^(message messageAdverbs anySatisfy: [:ad| ad isKindOf: Sly3ModSerially]) ifTrue:[ envelopes collect: payloadBlock] ifFalse:[ envelopes parallelCollect: payloadBlock]! ! !SlySelectorModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 10:01'! isSlySelector: aSelector "True if its has SlySelectorModifers" ^ {self asAWhole. self adverb. self gerundColon} anySatisfy: [:ss | aSelector includesSubString: ss]! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'dmu 9/23/2010 13:41'! dashboard "Sly3 dashboard " | topView buttons lastView subViewCount | topView := RVMStandardSystemView new . topView borderWidth:1. buttons _ { Transcript showInConsoleSwitch. self keepFlyingSwitch. self serializeForDebuggingSwitch. RVMButtonView label: 'Suspend member processes' action: [Processor suspendMemberProcesses]. RVMButtonView label: 'Terminate member processes' action: [Processor terminateMemberProcesses]. RVMButtonView label: 'Debug member processes' action: [Processor suspendMemberProcesses. ProcessBrowser open]. RVMButtonView label:'[ Sly3Boids new run ] fork' action:[[ Sly3Boids new run ] fork]. RVMButtonView label: '[Sly3aBoids new run ] fork' action: [[Sly3aBoids new run ] fork ]. RVMButtonView label:'Restore normal cursor' action:[Cursor normal show]. RVMButtonView label:'process browser' action:[ProcessBrowser open]. RVMButtonView label: 'Sly3SyntaxTests runAll' action: [Sly3SyntaxTests runAll]. }. lastView _ nil. buttons do:[:view| topView addSubView: view below: lastView. lastView _ view]. topView label: 'Sly3'. subViewCount _ topView subViews size. topView minimumSize: 165@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'ssa 3/25/2010 16:41'! keepFlyingSwitch "Sly3 keepFlyingSwitch demo" ^RVMCheckBoxView on: self label: 'Keep SlyBoids Flying' checkState: [Sly3 keepFlying] whenChecked: [Sly3 keepFlying:true] whenUnchecked: [Sly3 keepFlying:false].! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:29'! keepFlying KeepFlying isNil ifTrue:[KeepFlying _ true]. ^KeepFlying! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! keepFlying: aBoolean KeepFlying _ aBoolean! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! toggleKeepFlying self keepFlying: self keepFlying not! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isMessageModifier ^ self class isMessageModifier! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isArgumentModifier ^ self class isArgumentModifier! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isGerund ^ self class isGerund! ! Sly3Gerund subclass: #Sly3ModTotalling instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Gerund subclass: #Sly3ModSelecting instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Gerund subclass: #Sly3ModAverging instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:36'! stringWithLowercaseSuffix ^ self class stringWithLowercaseSuffix! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:33'! isAdverb ^ self class isAdverb! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:37'! uppercaseSuffix ^ self class uppercaseSuffix! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:35'! lowercaseSuffix ^ self class lowercaseSuffix! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:33'! isAdverb ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isArgumentModifier ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isGerund ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isMessageModifier ^ false! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:52'! lowercaseSuffix ^ self uppercaseSuffix asLowercase! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:36'! stringWithLowercaseSuffix "Sly3ModWholly stringWithLowercaseSuffix" ^ (self name copyFrom: 'Sly3Mod' size + 1 to: self name size) asLowercase! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:37'! uppercaseSuffix ^self subclassResponsibility! ! !Sly3Adverb class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:38'! uppercaseSuffix ^ 'LY'! ! !Sly3Gerund class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:38'! uppercaseSuffix ^ 'ING'! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:39'! allUppercaseSuffixes ^ self class allUppercaseSuffixes! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:39'! allUppercaseSuffixes ^ {Sly3Adverb. Sly3Gerund} collect: [:x | x uppercaseSuffix]! ! !Sly3Adverb class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:40'! isAdverb ^ true! ! !Sly3Gerund class methodsFor: 'testing' stamp: 'dmu 9/1/2010 23:44'! isGerund ^ true! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 9/3/2010 12:31'! modifySelector: sel ^ (self stringWithUppercaseSuffix, sel) asSymbol! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:46'! stringWithUppercaseSuffix ^ self stringWithoutSuffix, self uppercaseSuffix! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:47'! stringWithoutSuffix | s ss | s _ self stringWithLowercaseSuffix. ss _ self suffixSize. ^ s copyFrom: 1 to: s size - ss! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 19:00'! isSlySelector: aString " Sly3AbstractModifier isSlySelector: 'abdc' " ^ self allUppercaseSuffixes anySatisfy: [:s | aString includesSubString: s]! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:35'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:41'! suffixSize ^ self class suffixSize! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:41'! suffixSize ^ self uppercaseSuffix size! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:56'! membersSelector ^#members! ! !Sly3AbstractModifier class methodsFor: 'instance creation' stamp: 'dmu 9/1/2010 10:59'! instantiateSpecificFromBaseName: baseName includingSuffix: suffix | specificClassName cls | specificClassName _ 'Sly3Mod', baseName capitalized, suffix asLowercase. cls _ Smalltalk at: specificClassName asSymbol ifAbsent: [self error: 'could not find modifier class: ', specificClassName]. ^ cls new! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/12/2010 21:19'! messageModifiers: anObject "Set the value of messageModifiers" | | gerunds _ anObject select: [:x|x isGerund]. messageAdverbs _ anObject select: [:x| x isAdverb] ! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'printing' stamp: 'dmu 9/1/2010 10:35'! printOn: aStream super printOn: aStream. aStream nextPutAll: '(', self selector, ')'! ! !Sly3ParsedMessage methodsFor: 'printing' stamp: 'dmu 9/1/2010 11:15'! printOn: aStream super printOn: aStream. aStream nextPutAll: ': ', self selector! ! Sly3Gerund subclass: #Sly3ModAnding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Collection methodsFor: '*Sly' stamp: 'dmu 9/1/2010 15:17'! product | r | r _ 1. self do: [:e| r _ r * e]. ^ r! ! !Sly3MessageEvaluator methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:17'! makeEnvelopes ^ (Array new: operandTuples size) collect: [:x|Sly3MessageEnvelope argumentCount: message arguments size]! ! !SlyMessageEnvelope class methodsFor: 'instance creation' stamp: 'dmu 9/1/2010 15:32'! argumentCount: n ^self new message: (Message selector: #none arguments: (Array new: n)); yourself! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedMod "Answer the value of cachedMod" cachedMod isNil ifTrue:[self cachedMod: nil]. ^ cachedMod! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedMod: anObject "Set the value of cachedMod" cachedMod _ anObject! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:51'! cachedEns self unimplemented: 'must get receiver and arg ens and construct a selected ensemble'. ^ cachedEns! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedEns: anObject "Set the value of cachedEns" cachedEns _ anObject! ! !Sly3ModWholly commentStamp: 'dmu 9/1/2010 15:57'! batch all args to each member with the message! !Sly3ModSingly commentStamp: 'dmu 9/1/2010 15:57'! distributed arguments one-to-one over members! !Sly3ModRoundly commentStamp: 'dmu 9/1/2010 15:58'! distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs.! !Sly3ModDuplicatively commentStamp: 'dmu 9/1/2010 15:58'! each member gets a copy of the arguments! Sly3Gerund subclass: #Sly3ModEnsembling instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/3/2010 20:29'! argumentAdverbs: collectionPerArgument "Set the value of argumentModifiers" (collectionPerArgument anySatisfy: [:x | x anySatisfy: [:a | a isAdverb not]]) ifTrue: [self error: 'only adverbs for arguments']. argumentAdverbs _ collectionPerArgument asArray! ! Sly3Gerund subclass: #Sly3ModAndling instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3ModAndling methodsFor: 'as yet unclassified' stamp: 'dmu 9/1/2010 16:25'! reducing: results | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each & result]. ^result! ! Sly3Gerund subclass: #Sly3Concatenating instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! Sly3Gerund subclass: #Sly3ModOring instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3MessageEvaluator methodsFor: 'post-processing' stamp: 'dmu 9/4/2010 15:34'! evaluateGerunds message gerunds reverseDo: [:g| g reduceForEvaluator: self]. ^ result! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 16:34'! gerunds gerunds ifNil: [gerunds _ {}]. ^ gerunds! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 16:46'! messageAdverbs ^ messageAdverbs ifNil: [messageAdverbs _ {}] ifNotNil: [messageAdverbs]! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! gerunds: anObject "Set the value of gerunds" gerunds _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! messageAdverbs: anObject "Set the value of messageAdverbs" messageAdverbs _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! argumentAdverbs "Answer the value of argumentAdverbs" argumentAdverbs isNil ifTrue:[self argumentAdverbs: nil]. ^ argumentAdverbs! ! !Sly3ParsedMessage class methodsFor: 'as yet unclassified' stamp: 'dmu 9/19/2010 21:35'! receiver: ens members: mems messageModifiers: m selector: s arguments: args argumentAdverbs: argumentAdverbs | r | false ifFalse: [ ^ self new receiver: ens; members: mems; messageModifiers: m; selector: s; arguments: args; argumentAdverbs: argumentAdverbs; yourself ]. SupportMultipleAdverbs. "come back here later" r _ self new. r receiverMirror: (Sly3EnsembleMirror forEnsemble: ens members: mems). r messageModifiers: m. r selector: s. r argumentMirrors: (args collect: [:a| Sly3EnsembleMirror forObject: a]). r argumentAdverbs: argumentAdverbs. ^ r! ! !Object methodsFor: '*Sly3' stamp: 'dmu 9/1/2010 23:22'! collectionLY ^ nil! ! !Sly3MessageEnvelope methodsFor: 'delivering' stamp: 'dmu 9/21/2010 00:24'! deliver "send my message to my receiver and return the reply" | e | 1 to: deactivateEnsembleBehaviorFlags size do: [:i| (deactivateEnsembleBehaviorFlags at: i) ifTrue: [ e _ i = 1 ifTrue: [ receiver] ifFalse: [message arguments at: i - 1]. ^ Sly3Ensemble deactivateEnsembleSendsFor: e during: [(self copy at: i putDeactivateEnsembleBehaviorFlag: false) deliver] ] ]. self message arguments: self message arguments asArray. ^self message sentTo: self receiver! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:03'! message: anObject "Set the value of message" message _ anObject. ! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 21:27'! receiver ^ receiver! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3MessageEnvelope methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:51'! printOn: aStream aStream nextPutAll:'MsgEnv|rcvr:',self receiver wholLYprintString,'|message: ',self message printString! ! Sly3MessageEnvelope class instanceVariableNames: ''! !Sly3MessageEnvelope class methodsFor: 'instance creation' stamp: 'dmu 9/3/2010 15:35'! argumentCount: n ^self new message: (Message selector: #none arguments: (Array new: n)); deactivateEnsembleBehaviorFlags: ((Array new: n + 1) collect: [:x| false]); yourself! ! !Sly3MessageEnvelope class methodsFor: 'instance creation' stamp: 'ssa 5/27/2010 10:46'! receiver: anObject selector: aSymbol arguments: anArray ^self new receiver: anObject; message: (Message selector: aSymbol arguments: anArray); yourself! ! Sly3Boid subclass: #Sly3aBoid instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! !Sly3aBoid methodsFor: 'no messages' stamp: 'dmu 9/2/2010 23:59'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." ^ self flock boids averagINGserialLYposition! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:01'! computeNeighbors "should return ensemble" ^ self flock boids selectINGisNear: self! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 15:56'! keepAwayFromNeighbors self neighbors collectionLYsize = 0 ifTrue: [^ 0@0]. ^ self position - self neighbors averagINGserialLYposition! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 03:02'! matchVelocityWithNeighbors self neighbors collectionLYsize = 0 ifTrue: [^ 0@0]. ^ self neighbors averagINGvelocity / 8.0! ! Sly3SyntaxTests class instanceVariableNames: ''! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 14:34'! modifiedSelector ^ Sly3Adverb reflectiveAdverb modifySelector: selector! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/8/2010 21:09'! isEquals ^ selector = #= ifTrue:[self selector: #equals:. true] ifFalse: [false]! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 12:12'! isToolMessage | toolMessages | toolMessages _ #(inspect explore printString asExplorerString hasContentsInExplorer explorerContents halt error: halt: isKindOf:). ^ toolMessages includes: selector! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 12:13'! isToolProcess | foundContext toolClasses | toolClasses _ { Inspector. Debugger. PluggableListController}. foundContext _ thisContext findContextSuchThat:[:ctxt| toolClasses includes: ctxt receiver class]. ^ foundContext notNil! ! !Sly3ReflectiveSelectorChanger methodsFor: 'accessing' stamp: 'dmu 9/3/2010 12:17'! message: m message _ m! ! !Sly3ReflectiveSelectorChanger methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 17:46'! modifyMessageAsNeeded | newSelector | selector _ message selector. newSelector _ self modifySelectorAsNeeded. ^ selector = newSelector ifTrue: [message] ifFalse: [message copy selector: newSelector]! ! !Sly3ReflectiveSelectorChanger methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 17:51'! modifySelectorAsNeeded (self isReflective or: [self isWholly or: [self isCollectionly]]) ifTrue: [^ selector]. ^ (self isEquals or: [self isToolMessage or: [self isToolProcess]]) ifTrue: [self modifiedSelector] ifFalse: [selector] ! ! !Sly3ReflectiveSelectorChanger class methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 12:25'! modifyAsNeeded: aMessage ^self new message: aMessage; modifyMessageAsNeeded! ! !Sly3Gerund methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 14:13'! reduceForEvaluator: ev self subclassResponsibility! ! !Sly3ModAnding methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each & result]. ev result: result! ! !Sly3ModAveraging methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:42'! reduceForEvaluator: ev | sum results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. sum _ results sum. ev result: sum / results size ! ! !Sly3ModConcatenating methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:33'! reduceForEvaluator: ev "Concatenate each element in results and return the result. Assumes these elements are collections of some kind." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ result , each]. ev result: result! ! !Sly3ModEnsembling methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:05'! reduceForEvaluator: ev | results | results _ ev result. ev result: ( ev putResultsIntoAnEnsemble ifTrue: [results asEnsembleOfElements] ifFalse: [results size = 1 ifTrue: [results first] ifFalse: [self error: 'no ensembles dismembered, but yet results have ', results size printString, ' elements']])! ! !Sly3ModOring methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev "OR the elements in results and return the result. Assumes these elements understand |." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each | result]. ev result: result! ! !Sly3ModTotalling methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev "Sum the elements in results and return the result. Assumes these elements understand +." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ 0. results do:[:each| result _ each + result]. ev result: result! ! !Sly3ModSelecting methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:59'! reduceForEvaluator: ev | results members r | results _ ev result. members _ ev message members. r _ OrderedCollection new. members with: results do: [:m :res | res ifTrue: [r add: m]]. ev result: r asEnsembleOfElements! ! Sly3ModWholly subclass: #Sly3Plainly instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3Plainly commentStamp: 'dmu 9/3/2010 14:28'! Disable all ensemble processing for the recursive duration of this send! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 9/3/2010 14:33'! reflectiveAdverb ^Sly3ModPlainly! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 14:35'! isReflective ^ selector beginsWith: Sly3Adverb reflectiveAdverb stringWithUppercaseSuffix! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 15:35'! deactivateEnsembleBehaviorFlags: x deactivateEnsembleBehaviorFlags _ x! ! !Sly3ModPlainly methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:41'! shouldDisableEnsembleBehavior ^ true! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 15:43'! at: rcvrArgIndex putDeactivateEnsembleBehaviorFlag: aBool deactivateEnsembleBehaviorFlags at: rcvrArgIndex put: aBool! ! !Process methodsFor: 'accessing' stamp: 'dmu 9/3/2010 16:30'! lyDebuggingBlock "Answer the value of lyDebuggingBlock" lyDebuggingBlock isNil ifTrue:[self lyDebuggingBlock: nil]. ^ lyDebuggingBlock! ! !Process methodsFor: 'accessing' stamp: 'dmu 9/3/2010 16:30'! lyDebuggingBlock: anObject "Set the value of lyDebuggingBlock" lyDebuggingBlock _ anObject! ! !Sly3ModCollectionly commentStamp: 'dmu 9/3/2010 16:55'! Use members collection of the ensemble! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/7/2010 11:13'! deactivateEnsembleSendsFor: anEnsemble during: aBlock "disable messaging dispatching to members and just send it to the ensemble object itself during aBlock" | members r | members _ anEnsemble members. 0 primitiveSetExtraPreheaderWord: anEnsemble. r _ aBlock ensure: [members primitiveSetExtraPreheaderWord: anEnsemble. ]. ^ r ! ! !Sly3ReflectiveSelectorChanger methodsFor: 'accessing' stamp: 'dmu 9/3/2010 17:49'! selector: x selector _ x! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 17:52'! isWholly ^ selector beginsWith: Sly3ModWholly stringWithUppercaseSuffix! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 17:52'! isCollectionly ^ selector beginsWith: Sly3ModCollectionly stringWithUppercaseSuffix! ! !Sly3ModRandomly methodsFor: 'accessing' stamp: 'dmu 9/3/2010 18:12'! parameter "Answer the value of parameter" parameter isNil ifTrue:[self parameter: 1]. ^ parameter! ! !Sly3Adverb methodsFor: 'testing' stamp: 'dmu 9/3/2010 18:15'! isIndirect ^ false! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/13/2010 00:02'! foldInIndirectModifiers: blk | stringsAndMods args inStringsAndMods inArgs s | stringsAndMods _ OrderedCollection new. args _ OrderedCollection new. inStringsAndMods _ ReadStream on: flatKeywordsAndModifiers. inArgs _ ReadStream on: arguments. [inStringsAndMods atEnd] whileFalse: [ s _ inStringsAndMods next. (s isKindOf: String) ifTrue: [ stringsAndMods addLast: s. (s notEmpty and: [(s last = $:) or: [s first isLetter not]]) ifTrue: [args addLast: inArgs next]. ] ifFalse: [ s isIndirect ifTrue: [ s parameter: inArgs next. ]. stringsAndMods addLast: s. ] ]. blk value: stringsAndMods contents value: args asArray! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/16/2010 23:24'! breakModifiersForArguments | | arguments isEmpty ifTrue: [ ^ self breakUnaryModifiersForArguments]. unparsedSelector isInfix ifTrue: [ ^ OrderedCollection with: (OrderedCollection new) with: (OrderedCollection new) ]. ^ self breakKeywordModifiersForArguments! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 9/3/2010 19:44'! arguments ^ arguments! ! !Sly3ModRandomly methodsFor: 'accessing' stamp: 'dmu 9/3/2010 19:46'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !Sly3Gerund methodsFor: 'testing' stamp: 'dmu 9/3/2010 22:16'! isIndirect ^ false! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 9/3/2010 22:16'! isDirect ^ self isIndirect not! ! !Sly3MessageParser methodsFor: 'dissecting selector' stamp: 'dmu 9/13/2010 00:09'! breakStringsIntoKeywords: inCol | in out x inin outout c | in _ ReadStream on: inCol. out _ WriteStream on: (Array new: inCol size * 2). [in atEnd] whileFalse: [ x _ in next. (x isKindOf: String) ifFalse: [ out nextPut: x] ifTrue: [ inin _ ReadStream on: x. outout _ WriteStream on: (String new: x size). [inin atEnd] whileFalse: [ c _ inin next. outout nextPut: c. c = $: ifTrue: [ out nextPut: (outout contents). outout _ WriteStream on: (String new: x size). ] ]. outout isEmpty ifFalse: [out nextPut: (outout contents)] ] ]. ^ out contents asOrderedCollection! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/4/2010 15:33'! result: r result _ r! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/4/2010 15:34'! result ^ result! ! Sly3OperandDistributor subclass: #Sly3AbstractIndirectAdverb instanceVariableNames: 'parameter' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Modifiers'! !Sly3AbstractIndirectAdverb methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter "Answer the value of parameter" parameter isNil ifTrue:[self parameter: nil]. ^ parameter! ! !Sly3AbstractIndirectAdverb methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter: anObject "Set the value of parameter" parameter _ anObject! ! !Sly3AbstractIndirectAdverb methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:01'! isIndirect ^ true! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! theEnsemble "Answer the value of theEnsemble" theEnsemble isNil ifTrue:[self theEnsemble: nil]. ^ theEnsemble! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! theEnsemble: anObject "Set the value of theEnsemble" theEnsemble _ anObject! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! members "Answer the value of members" members isNil ifTrue:[self members: nil]. ^ members! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! members: anObject "Set the value of members" members _ anObject! ! !Sly3EnsembleMirror class methodsFor: 'as yet unclassified' stamp: 'dmu 9/5/2010 15:27'! forObject: obj self new theEnsemble: obj; members: (obj wholLYisEnsemble ifTrue: [obj collectionLY] ifFalse: [obj]); yourself! ! !Sly3EnsembleMirror class methodsFor: 'as yet unclassified' stamp: 'dmu 9/5/2010 15:27'! forEnsemble: e members: m ^ self new theEnsemble: e; members: m; yourself! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! receiverMirror "Answer the value of receiverMirror" receiverMirror isNil ifTrue:[self receiverMirror: nil]. ^ receiverMirror! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! receiverMirror: anObject "Set the value of receiverMirror" receiverMirror _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! argumentMirrors "Answer the value of argumentMirrors" argumentMirrors isNil ifTrue:[self argumentMirrors: nil]. ^ argumentMirrors! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! argumentMirrors: anObject "Set the value of argumentMirrors" argumentMirrors _ anObject! ! !ClassDescription methodsFor: 'printing' stamp: 'dmu 9/6/2010 16:21'! instanceVariablesString "Answer a string of my instance variable names separated by spaces." ^String streamContents: [ :stream | (self instVarNames isKindOf: Number) ifTrue: [stream nextPutAll: 'EEK'] ifFalse: [ self instVarNames do: [ :each | stream nextPutAll: each ] separatedBy: [ stream space ] ]]! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:37'! receiver "Answer the value of receiver" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. ^ receiver! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:36'! members "Answer the value of members" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. members isNil ifTrue:[self members: nil]. ^ members! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! members: anObject "Set the value of members" members _ anObject! ! FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1 interlock' classVariableNames: 'Registry' poolDictionaries: '' category: 'System-Files'! !StandardFileStream methodsFor: '*RVM' stamp: 'dmu 9/7/2010 14:07'! interlock interlock ifNil: [self interlock: Semaphore forMutualExclusion]. ^ interlock! ! !StandardFileStream methodsFor: '*RVM' stamp: 'dmu 9/7/2010 14:07'! interlock: aSemaphore interlock _ aSemaphore! ! !StandardFileStream methodsFor: '*RVM' stamp: 'dmu 9/7/2010 14:14'! resetInterlock self interlock signal. self interlock: nil! ! !StandardFileStream methodsFor: '*RVM' stamp: 'dmu 9/7/2010 14:09'! safelyDo: aBlock ^ self interlock critical: aBlock! ! !StandardFileStream class methodsFor: '*RVM' stamp: 'dmu 9/7/2010 14:14'! resetAllInterlocks "self resetAllInterlocks" self allSubInstancesDo: [:sfs| sfs resetInterlock]! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:36'! arguments "Answer the value of arguments" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. arguments isNil ifTrue:[self arguments: nil]. ^ arguments! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! arguments: anObject "Set the value of arguments" arguments _ anObject! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:17'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr | (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance classCommented: self. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr _ self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr _ oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file _ SourceFiles at: 2) ifNotNil: [ file safelyDo: [ file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header _ String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance classCommented: self. ! ! !CompiledMethod methodsFor: 'source code management' stamp: 'dmu 9/7/2010 14:23'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString st80str | (SourceFiles == nil or: [(file _ SourceFiles at: fileIndex) == nil]) ifTrue: [^ self become: (self copyWithTempNames: methodNode tempNames)]. SmalltalkImage current assureStartupStampLogged. file safelyDo: [ file setToEnd. preambleBlock value: file. "Write the preamble" (methodNode isKindOf: DialectMethodNode) ifTrue: ["This source was parsed from an alternate syntax. We must convert to ST80 before logging it." st80str _ (DialectStream dialect: #ST80 contents: [:strm | methodNode printOn: strm]) asString. remoteString _ RemoteString newString: st80str onFileNumber: fileIndex toFile: file] ifFalse: [remoteString _ RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file]. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex ]! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'dmu 9/7/2010 14:26'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes _ SourceFiles at: 2. changes safelyDo: [ changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aStringOrText isText ifTrue: [aString _ aStringOrText string] ifFalse: [aString _ aStringOrText]. (aString isMemberOf: String) ifFalse: [self error: 'can''t log this change']. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile _ SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile _ SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp _ nil. self forceChangesToDisk. ]! ! !ChangeList class methodsFor: 'public access' stamp: 'dmu 9/7/2010 14:16'! getRecentLocatorWithPrompt: aPrompt "Prompt with a menu of how far back to go. Return nil if user backs out. Otherwise return the number of characters back from the end of the .changes file the user wishes to include" "ChangeList getRecentPosition" | end changesFile banners positions pos chunk i | changesFile _ (SourceFiles at: 2) readOnlyCopy. banners _ OrderedCollection new. positions _ OrderedCollection new. changesFile safelyDo: [ end _ changesFile size. pos _ SmalltalkImage current lastQuitLogPosition. [pos = 0 or: [banners size > 20]] whileFalse: [ changesFile position: pos. chunk _ changesFile nextChunk. i _ chunk indexOfSubCollection: 'priorSource: ' startingAt: 1. i > 0 ifTrue: [positions addLast: pos. banners addLast: (chunk copyFrom: 5 to: i-2). pos _ Number readFrom: (chunk copyFrom: i+13 to: chunk size)] ifFalse: [pos _ 0]]. changesFile close. pos _ (SelectionMenu labelList: banners selections: positions) startUpWithCaption: aPrompt. pos == nil ifTrue: [^ nil]. ^ end - pos ]! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'dmu 9/7/2010 14:16'! scanVersionsOf: class "Scan for all past versions of the class comment of the given class" | oldCommentRemoteStr sourceFilesCopy position prevPos stamp preamble tokens prevFileIndex | classOfMethod _ class. oldCommentRemoteStr _ class organization commentRemoteStr. currentCompiledMethod _ oldCommentRemoteStr. selectorOfMethod _ #Comment. changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. oldCommentRemoteStr ifNil:[^ nil] ifNotNil: [oldCommentRemoteStr sourcePointer]. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. position _ oldCommentRemoteStr position. file _ sourceFilesCopy at: oldCommentRemoteStr sourceFileNumber. [position notNil & file notNil] whileTrue: [ file position: (0 max: position-150). " Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. prevPos _ nil. stamp _ ''. (preamble findString: 'commentStamp:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble. (tokens at: tokens size-3) = #commentStamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos]] ifFalse: ["The stamp get lost, maybe after a condenseChanges" stamp _ '']. self addItem: (ChangeRecord new file: file position: position type: #classComment class: class name category: nil meta: class stamp: stamp) text: stamp , ' ' , class name , ' class comment'. prevPos = 0 ifTrue:[prevPos _ nil]. position _ prevPos. prevPos notNil ifTrue:[file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:22'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble _ self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble _ '']. method _ self methodDict at: selector. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos _ method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: (self decompilerClass new decompile: selector in: self method: method) decompileString] ifFalse: [sourceFile _ SourceFiles at: method fileIndex. sourceFile safelyDo: [ sourceFile position: oldPos. preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile]. "Copy the method chunk" newPos _ outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "[" "The following chunk may have ]style[" "]" sourceFile peek == "[" $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos _ outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !Parser methodsFor: '*Sly-expression types' stamp: 'dmu 9/16/2010 23:49'! ensembleExpression " %{ elements } => MessageNode(BraceNode asEnsembleOfElements)." | elements locations loc more | elements _ OrderedCollection new. locations _ OrderedCollection new. self advance. "swallow the %" self advance. more _ hereType ~~ #rightBrace. [more] whileTrue: [loc _ hereMark + requestorOffset. self expression ifTrue: [elements addLast: parseNode. locations addLast: loc] ifFalse: [^self expected: 'Variable or expression']. (self match: #period) ifTrue: [more _ hereType ~~ #rightBrace] ifFalse: [more _ false]]. parseNode _ BraceNode new elements: elements sourceLocations: locations. (self match: #rightBrace) ifFalse: [^self expected: 'Period or right brace']. parseNode _ MessageNode new receiver: parseNode selector: #asEnsembleOfElements arguments: #() precedence: 1 "unary" from: encoder sourceRange: (self startOfNextToken to: self endOfLastToken). ^true! ! !Parser methodsFor: '*Sly' stamp: 'dmu 8/30/2010 09:42'! expression "Modified for Sly ensemble literals" (hereType == #word and: [tokenType == #leftArrow]) ifTrue: [^ self assignment: self variable]. hereType == #percent ifTrue: [self ensembleExpression] ifFalse:[ hereType == #leftBrace ifTrue: [self braceExpression] ifFalse: [self primaryExpression ifFalse: [^ false]]]. (self messagePart: 3 repeat: true) ifTrue: [hereType == #semicolon ifTrue: [self cascade]]. ^ true! ! !Parser methodsFor: '*Sly-expression types' stamp: 'dmu 9/12/2010 23:49'! messagePart: level repeat: repeat "Changed to support RVM multicore coordinates and Sly selectors" | start receiver selector args precedence words keywordStart | [receiver _ parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start _ self startOfNextToken. selector _ WriteStream on: (String new: 32). args _ OrderedCollection new. words _ OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart _ self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. (Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ ((RVMTester ifNil: [false] ifNotNil: [RVMTester isMulticoreCoordinate: selector contents]) or:[Sly3AbstractModifier isSlySelector: selector contents]) ifTrue:[selector contents asSymbol] ifFalse:[self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]]. precedence _ 3] ifFalse: [((hereType == #binary or: [hereType == #verticalBar]) and: [level >= 2]) ifTrue: [start _ self startOfNextToken. selector _ self advance asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args _ Array with: parseNode. precedence _ 2] ifFalse: [hereType == #word ifTrue: [start _ self startOfNextToken. selector _ self advance. args _ #(). words _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). (Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ ((RVMTester isMulticoreCoordinate: selector contents) or:[Sly3AbstractModifier isSlySelector: selector contents]) ifTrue:[selector contents asSymbol] ifFalse:[self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]]. precedence _ 1] ifFalse: [^args notNil]]]. parseNode _ MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! ! !Parser methodsFor: 'expression types' stamp: 'dmu 8/30/2010 09:49'! primaryExpression "Added Sly ensembleExpression type" hereType == #word ifTrue: [parseNode _ self variable. (parseNode isUndefTemp and: [self interactive]) ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #percent ifTrue: [self ensembleExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal]]) ifTrue: [parseNode _ encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number]) ifTrue: [self advance. parseNode _ encoder encodeLiteral: self advance negated. ^true]. ^false! ! !CompiledMethod methodsFor: 'printing' stamp: 'dmu 9/7/2010 14:23'! timeStamp "Answer the authoring time-stamp for the given method, retrieved from the sources or changes file. Answer the empty string if no time stamp is available." "(CompiledMethod compiledMethodAt: #timeStamp) timeStamp" | position file preamble stamp tokens tokenCount | self fileIndex == 0 ifTrue: [^ String new]. "no source pointer for this method" position _ self filePosition. file _ SourceFiles at: self fileIndex. file ifNil: [^ String new]. "sources file not available" "file does not exist happens in secure mode" file _ [file readOnlyCopy] on: FileDoesNotExistException do:[:ex| nil]. file ifNil: [^ String new]. file position: (0 max: position - 150). "Skip back to before the preamble" [file position < (position - 1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. stamp _ String new. tokens _ (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [Scanner new scanTokens: preamble] ifFalse: [Array new "ie cant be back ref"]. (((tokenCount _ tokens size) between: 7 and: 8) and: [(tokens at: tokenCount - 5) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount - 2]]. ((tokenCount between: 5 and: 6) and: [(tokens at: tokenCount - 3) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount]]. file close. ^ stamp ! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'dmu 9/7/2010 14:12'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" StandardFileStream resetAllInterlocks. SourceFiles _ self new initialize! ! !Sly3 class methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:24'! serializeForDebugging ^ SerializeForDebugging ifNil: [SerializeForDebugging _ false] ifNotNil: [SerializeForDebugging]! ! !Sly3 class methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:25'! serializeForDebugging: aBool SerializeForDebugging _ aBool! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'dmu 9/7/2010 17:25'! serializeForDebuggingSwitch "Sly3 serializeForDebuggingSwitch demo" ^RVMCheckBoxView on: self label: 'Serialize for debugging' checkState: [Sly3 serializeForDebugging] whenChecked: [Sly3 serializeForDebugging:true] whenUnchecked: [Sly3 serializeForDebugging:false].! ! Object subclass: #Sly3Graphics instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! Sly3Graphics class instanceVariableNames: ''! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! clearScreen Display fillWhite! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! drawCircle: pt Display drawDot5At: pt! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:03'! drawFrom: ptA to: ptB Display drawLineFrom: ptA to: ptB color: Color black! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:04'! drawWhiteCircle: pt Display eraseDot5At: pt! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/23/2010 00:02'! eraseFrom: ptA to: ptB Display eraseLineFrom: ptA to: ptB color: Color black! ! !Sly3aBoids methodsFor: 'no messages' stamp: 'dmu 9/8/2010 02:27'! boidClass ^ Sly3aBoid! ! Object subclass: #Sly3Drawer instanceVariableNames: 'flock' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! Sly3Drawer subclass: #Sly3aDrawer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! !Sly3aDrawer methodsFor: 'no messages' stamp: 'dmu 9/8/2010 02:28'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids serialLYdraw]! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:29'! drawerClass ^ Sly3Drawer! ! !Sly3aBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:30'! drawerClass ^ Sly3aDrawer! ! !Sly3aBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 03:03'! flockSize ^ 30! ! Object subclass: #ParallelRandomBug instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'DMU-Tools'! !ParallelRandomBug class methodsFor: 'as yet unclassified' stamp: 'dmu 9/9/2010 00:13'! test | numWorkers | numWorkers _ 2. 1 to: numWorkers do: [ :w | [ | tr | tr := Random new. 10000 timesRepeat: [ (tr next) < 0.0 ifTrue: [self error: 'neg']. ]. ] fork ]. ! ! !Random methodsFor: 'private' stamp: 'sma 5/12/2000 12:28'! nextValue "This method generates random instances of Integer in the interval 0 to 16r7FFFFFFF. This method does NOT update the seed; repeated sends answer the same value. The algorithm is described in detail in 'Random Number Generators: Good Ones Are Hard to Find' by Stephen K. Park and Keith W. Miller (Comm. Asso. Comp. Mach., 31(10):1192--1201, 1988)." | lo hi aLoRHi answer | hi _ (seed quo: q) asFloat. lo _ seed - (hi * q). " = seed rem: q" aLoRHi _ (a * lo) - (r * hi). answer _ (aLoRHi > 0.0) ifTrue: [aLoRHi] ifFalse: [aLoRHi + m]. ^ answer! ! !ParallelRandomBug class methodsFor: 'as yet unclassified' stamp: 'dmu 9/9/2010 00:28'! test2 | numWorkers randoms | numWorkers _ 2. randoms _ ( Array new: 2) collect: [:x|Random new]. 1 to: numWorkers do: [ :w | [ 10000 timesRepeat: [ ((randoms at: w) next) < 0.0 ifTrue: [self error: 'neg']. ]. ] copy fixTemps fork ]. ! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 9/11/2010 16:58'! isOperandDistributor ^ false! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:16'! isString: x ^ x isKindOf: String! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:17'! isKeyword: x ^ (self isString: x) and: [x last = $:]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:17'! isModifier: x ^ x isKindOf: Sly3AbstractModifier! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:18'! isDirect: x ^ (self isModifier: x) and: [x isDirect]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:18'! isIndirect: x ^ (self isModifier: x) and: [x isIndirect]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:21'! nextOnesIn: aStream suchThat: testBlk | result | result _ OrderedCollection new. [ (aStream atEnd not and: [testBlk value: aStream peek]) ifFalse: [^ result]. result addLast: aStream next ] repeat! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/13/2010 00:03'! isNonKeywordString: x ^ (self isString: x) and: [x isEmpty or: [x last ~= $:]]! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 20:45'! breakUnaryModifiersForArguments ^ OrderedCollection with: (foldedFlatStringsAndModifiers select: [:x | x isKindOf: Sly3AbstractModifier])! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 20:54'! breakModifiersForReceiverIn: s | rcvrDirectMods rcvrIndirectMods | rcvrDirectMods _ self nextOnesIn: s suchThat: [:x| self isDirect: x]. rcvrIndirectMods _ self nextOnesIn: s suchThat: [:x| self isIndirect: x]. ^ rcvrDirectMods, rcvrIndirectMods! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 21:17'! breakKeywordModifiersForArguments | s allOperandMods directsAndStrings argDirectMods argIndirectMods | s _ ReadStream on: foldedFlatStringsAndModifiers. allOperandMods _ OrderedCollection with: (self breakModifiersForReceiverIn: s). [s atEnd] whileFalse: [ directsAndStrings _ self nextOnesIn: s suchThat: [:x| (self isDirect: x) or: [self isNonKeywordString: x]]. argDirectMods _ directsAndStrings select: [:x | self isDirect: x]. (self isKeyword: s peek) ifFalse: [self error: 'expected keyword']. s next. argIndirectMods _ self nextOnesIn: s suchThat: [:x | self isIndirect: x]. allOperandMods addLast: argDirectMods, argIndirectMods. ]. ^ allOperandMods! ! !Sly3MessageParser methodsFor: 'dissecting selector' stamp: 'dmu 9/12/2010 21:02'! dissectSelectorIntoStringsAndModifiers: aString "break up a sequence of characters that are part of a selector" "returns a collection of Strings and Sly3AbstractModifier s" "Examples: snortLY -> adverb is snort selectorPart is empty snortLYfoo -> adverb is snort selectorPart is foo fooSnortLY -> selector part is foo, adverb is Snort" "Sly3MessageParser new breakIntoStringsAndModifiers: #serialLYRoundLYatRoundLY:atRoundLY:atRoundLY:atRoundLY:put:valueLY:" | lastStart i parts modifierString foundSuffix end nextWord c endWord charAfterSuffixIndex pastModifierIndex | parts _ OrderedCollection new. lastStart _ 1. i _ 1. [i <= aString size] whileTrue: [ foundSuffix _ nil. Sly3AbstractModifier allUppercaseSuffixes do: [:suffix| end _ i + suffix size - 1. (aString size >= end and: [ (aString copyFrom: i to: i + suffix size - 1) = suffix ]) ifTrue: [ foundSuffix ifNil: [foundSuffix _ suffix] ifNotNil: [self error: 'ambiguous'] ] ]. foundSuffix ifNotNil: [ charAfterSuffixIndex _ i + foundSuffix size. modifierString _ aString copyFrom: lastStart to: i - 1. parts addLast: (Sly3AbstractModifier instantiateSpecificFromBaseName: modifierString includingSuffix: foundSuffix). parts last isIndirect ifTrue: [ ((aString size >= charAfterSuffixIndex) and: [(aString at: charAfterSuffixIndex) = $:]) ifFalse: [self error: 'indirect modifier should have colon']. ]. pastModifierIndex _ charAfterSuffixIndex + (parts last isIndirect ifTrue: [1] ifFalse: [0]). lastStart _ i _ pastModifierIndex. ] ifNil: [ c _ aString at: i. (c isUppercase or: [c = $:]) ifTrue: [ endWord _ c = $: ifTrue: [i] ifFalse: [i - 1]. nextWord _ aString copyFrom: lastStart to: endWord. parts addLast: ( (parts notEmpty and: [(parts last isKindOf: String) and: [parts last last ~= $:]]) ifFalse: [nextWord] ifTrue: [parts removeLast, nextWord ]). lastStart _ endWord + 1 ]. i _ i + 1 ] ]. lastStart <= aString size ifTrue: [ nextWord _ aString copyFrom: lastStart to: aString size. parts addLast: ( (parts notEmpty and: [parts last isKindOf: String]) ifFalse: [nextWord] ifTrue: [parts removeLast, nextWord capitalized])]. ^ parts ! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/21/2010 00:23'! addDefaultModifiersTo: allMods | r rcvr ms defaultClass ods addDefault | r _ OrderedCollection new. rcvr _ true. allMods do: [:mods | ms _ mods copy. defaultClass _ rcvr ifTrue: [Sly3Adverb defaultReceiverOperandDistributor] ifFalse: [Sly3Adverb defaultArgumentOperandDistributor]. ods _ mods select: [:x|x isOperandDistributor]. addDefault _ ods isEmpty. addDefault ifTrue: [ms addFirst: defaultClass new]. (rcvr and: [mods noneSatisfy:[:x| x isGerund]]) ifTrue: [ms addFirst: Sly3Gerund defaultGerund new]. r addLast: ms. rcvr _ false. ]. ^ r! ! !Sly3Gerund class methodsFor: 'as yet unclassified' stamp: 'dmu 9/12/2010 21:24'! defaultGerund ^Sly3ModEnsembling! ! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 9/19/2010 21:26'! defaultReceiverOperandDistributor ^Sly3ModSingly! ! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 9/12/2010 22:08'! defaultArgumentOperandDistributor ^Sly3ModWholly! ! Sly3MessageEvaluator class instanceVariableNames: ''! Sly3MessageParser class instanceVariableNames: ''! Sly3ParsedMessage class instanceVariableNames: ''! !Debugger class methodsFor: 'opening' stamp: 'dmu 9/17/2010 12:00'! openInterrupt: aString onProcess: interruptedProcess "Open a notifier in response to an interrupt. An interrupt occurs when the user types the interrupt key (cmd-. on Macs, ctrl-c or alt-. on other systems) or when the low-space watcher detects that memory is low." | debugger | "Simulation guard" debugger := self new. interruptedProcess suspend. debugger process: interruptedProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers activeControllerProcess == interruptedProcess]) ifTrue: [ScheduledControllers activeController]) context: interruptedProcess suspendedContextWaitingIfNecessary. debugger externalInterrupt: true. Preferences logDebuggerStackToFile ifTrue: [(aString includesSubString: 'Space') & (aString includesSubString: 'low') ifTrue: [ Smalltalk logError: aString inContext: debugger interruptedContext to:'LowSpaceDebug.log']]. ^ debugger openNotifierContents: nil label: aString ! ! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:37'! withMembersFrom: aCollection ^ self new members: aCollection! ! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:39'! withSoleMember: anObject ^ self withMembersFrom: {anObject}! ! !Collection methodsFor: '*Sly3' stamp: 'dmu 9/16/2010 23:41'! asEnsembleOfElements ^ Sly3Ensemble withMembersFrom: self! ! !Object methodsFor: '*Sly3' stamp: 'dmu 9/16/2010 23:45'! asSingletonEnsemble ^Sly3Ensemble withSoleMember: self! ! !BlockContext methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 10:58'! asSlyMemberProcess ^ self copy fixTemps newProcess beSlyMemberProcess! ! !ProcessorScheduler methodsFor: '*RVM' stamp: 'dmu 9/17/2010 11:02'! userBackgroundPriority ^ UserBackgroundPriority! ! !Process methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 11:12'! beSlyMemberProcess self priority: Processor userBackgroundPriority. Processor thisProcess addChild: self. ^ self! ! !ProcessorScheduler methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 13:04'! suspendMemberProcesses self memberProcesses do: [:p| p suspend]! ! !ProcessorScheduler methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 11:16'! memberProcesses ^Process allInstances select: [:proc | proc creatorEnsemble notNil]! ! !ProcessorScheduler methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 11:17'! terminateMemberProcesses self memberProcesses do: [:p| p terminate]! ! !ProcessorScheduler methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 12:18'! debugMemberProcesses self suspendMemberProcesses. self memberProcesses do: [:p| p debug]! ! !Process methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 11:57'! synchronousSuspend "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." "Send suspend and don't return till the process is really suspended" self suspend. [self suspendedContext isNil] whileTrue.! ! !Process methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 11:59'! suspendedContextWaitingIfNecessary "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." [self suspendedContext isNil] whileTrue. ^ self suspendedContext! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'dmu 9/17/2010 12:00'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector := evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig := evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context := guineaPig suspendedContextWaitingIfNecessary. debugger := Debugger new process: guineaPig controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: context isolationHead: nil. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! View subclass: #StandardSystemView instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes displayInterlock' classVariableNames: 'CacheBits LabelStyle' poolDictionaries: '' category: 'ST80-Support'! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! labelFrame: anObject "Set the value of labelFrame" labelFrame _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! labelText: anObject "Set the value of labelText" labelText _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! isLabelComplemented "Answer the value of isLabelComplemented" isLabelComplemented isNil ifTrue:[self isLabelComplemented: nil]. ^ isLabelComplemented! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! isLabelComplemented: anObject "Set the value of isLabelComplemented" isLabelComplemented _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! savedSubViews "Answer the value of savedSubViews" savedSubViews isNil ifTrue:[self savedSubViews: nil]. ^ savedSubViews! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! savedSubViews: anObject "Set the value of savedSubViews" savedSubViews _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! collapsedViewport "Answer the value of collapsedViewport" collapsedViewport isNil ifTrue:[self collapsedViewport: nil]. ^ collapsedViewport! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! collapsedViewport: anObject "Set the value of collapsedViewport" collapsedViewport _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! expandedViewport "Answer the value of expandedViewport" expandedViewport isNil ifTrue:[self expandedViewport: nil]. ^ expandedViewport! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! expandedViewport: anObject "Set the value of expandedViewport" expandedViewport _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! labelBits "Answer the value of labelBits" labelBits isNil ifTrue:[self labelBits: nil]. ^ labelBits! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! labelBits: anObject "Set the value of labelBits" labelBits _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! windowBits: anObject "Set the value of windowBits" windowBits _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! bitsValid "Answer the value of bitsValid" bitsValid isNil ifTrue:[self bitsValid: nil]. ^ bitsValid! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! bitsValid: anObject "Set the value of bitsValid" bitsValid _ anObject! ! !StandardSystemView methodsFor: 'accessing' stamp: 'dmu 9/17/2010 12:22'! updatablePanes: anObject "Set the value of updatablePanes" updatablePanes _ anObject! ! !StandardSystemView methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 12:37'! displayInterlock displayInterlock ifNil: [self displayInterlock: Mutex new]. ^ displayInterlock! ! !StandardSystemView methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 12:24'! displayInterlock: aSemaphore displayInterlock _ aSemaphore! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:31'! displayEmphasized "Display with label highlighted to indicate that it is active." self critical: [ self displayDeEmphasized; emphasize. isLabelComplemented _ true ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:30'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self critical: [ (bitsValid and: [controller ~~ ScheduledControllers activeController]) ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [Display deferUpdates: true. super display. Display deferUpdates: false; forceToScreen: self windowBox. CacheBits ifTrue: [self cacheBitsAsIs]] ] ! ! !StandardSystemView methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 12:37'! critical: aBlock ^self displayInterlock critical: aBlock! ! Object subclass: #Mutex instanceVariableNames: 'semaphore owner' classVariableNames: '' poolDictionaries: '' category: 'Sly3'! !Mutex commentStamp: ''! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !Mutex methodsFor: 'initialize' stamp: 'das 11/3/2005 22:53'! initialize semaphore := Semaphore forMutualExclusion.! ! !Mutex methodsFor: 'mutual exclusion' stamp: 'dmu 6/14/2010 16:16'! critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess | activeProcess := Processor thisProcess. activeProcess == owner ifTrue:[^aBlock value]. ^semaphore critical:[ owner := activeProcess. aBlock ensure:[owner := nil]].! ! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: true. self displayLabelBoxes. self displayLabelText. ]! ! !StandardSystemView methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 12:47'! resetDisplayInterlock self displayInterlock: nil! ! !ControlManager methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:48'! restore "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." scheduledControllers first view uncacheBits. "assure refresh" self unschedule: screenController; scheduleOnBottom: screenController. screenController view window: Display boundingBox; displayDeEmphasized. self scheduledWindowControllers reverseDo: [:aController | aController view resetDisplayInterlock; displayDeEmphasized]. ! ! !StandardSystemView methodsFor: 'label access' stamp: 'ssa 3/9/2010 12:49'! closingGuardIcon ^(ColorForm extent: 11@11 depth: 1 fromArray: #( 0 520093696 1065353216 830472192 830472192 2143289344 2143289344 2143289344 2143289344 2143289344 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0)#(0.0 0.0 0.0) )! ! !StandardSystemView methodsFor: 'label access' stamp: ''! labelColor "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" ^ self backgroundColor! ! !StandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:05'! initialFrame "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" | rect | rect _ Rectangle originFromUser: self initialExtent + (0@self labelHeight). ^rect origin + (0@ self labelHeight) extent: self initialExtent "RealEstateAgent initialFrameFor: self world: nil"! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 8/24/2009 07:49'! cacheBitsAsTwoTone ^ false! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: false. self displayClosingGuardBoxIfNeeded. self displayLabelText. ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayClosingGuardBoxIfNeeded "display closing guard active, if true" | aRect | self controller preventClosing ifTrue:[ aRect _ self closeBoxFrame. self closingGuardIcon displayOn: Display at: aRect origin clippingBox: aRect rule: Form over fillColor: nil]. ! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayLabelBackground: emphasized "Clear or emphasize the inner region of the label" | r1 r2 r3 c3 c2 c1 | emphasized ifFalse: ["Just clear the label if not emphasized" Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor. ^self displayClosingGuardBoxIfNeeded]. r1 _ self labelDisplayBox insetBy: 2. r2 _ r1 insetBy: 0@2. r3 _ r2 insetBy: 0@3. c3 _ self labelColor. c2 _ c3 dansDarker. c1 _ c2 dansDarker. Display fill: r1 fillColor: c1. Display fill: r2 fillColor: c2. Display fill: r3 fillColor: c3. " Here is the Mac racing stripe code stripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth) with: (Form black pixelWordForDepth: Display depth). self windowOrigin y even ifTrue: [stripes swap: 1 with: 2]. Display fill: (self labelDisplayBox insetBy: 3) fillColor: stripes. "! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayLabelBoxes "closeBox,closingGuard box growBox." | aRect smallRect backColor | aRect _ self closeBoxFrame. backColor _ self labelColor. Display fill: (aRect insetBy: -2) fillColor: backColor. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. "display closing guard active, if true" self displayClosingGuardBoxIfNeeded. aRect _ self growBoxFrame. smallRect _ aRect origin extent: 7@7. Display fill: (aRect insetBy: -2) fillColor: backColor. aRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. Display fillBlack: smallRect. Display fill: (smallRect insetBy: 1) fillColor: backColor! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 15:41'! displayView "Refer to the comment in View|displayView. " labelFrame height = 0 ifTrue: [^ self]. "no label" self displayBox width = labelFrame width ifFalse: ["recompute label width when window changes size" self setLabelRegion]. (labelFrame align: labelFrame topLeft with: self windowOrigin) insideColor: self labelColor; displayOn: Display. self displayClosingGuardBoxIfNeeded. self displayLabelText! ! !StandardSystemView methodsFor: 'updating' stamp: 'ssa 8/21/2009 12:58'! setUpdatablePanesFrom: getSelectors | aList aPane | "Set my updatablePanes inst var to the list of panes which are list panes with the given get-list selectors. Order is important here!! Note that the method is robust in the face of panes not found, but a warning is printed in the transcript in each such case" aList _ OrderedCollection new. getSelectors do: [:sel | aPane _ self subViewSatisfying: [:pane | ((pane isKindOf: PluggableListView) or:[pane isKindOf: MSWScrollBarView]) and: [pane getListSelector == sel]]. aPane ifNotNil: [aList add: aPane] ifNil: [Transcript cr; show: 'Warning: view ', sel, ' not found.']]. updatablePanes _ aList asArray! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'dmu 9/17/2010 15:34'! exampleView8 "RVMAspectTrace exampleView8" | traces | traces _ OrderedCollection new. traces add:(self aspect: #numberOfRunningProcesses size: 100 color: Color random). RVMStripChartView openOnTraces: traces! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'dmu 9/17/2010 16:39'! handleUserInterrupt Preferences cmdDotEnabled ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] forkAt: Processor thisProcess priority + 1]]! ! !Sly3OperandDistributor methodsFor: 'testing' stamp: 'dmu 9/19/2010 20:52'! isOperandDistributor ^ true! ! !Sly3OperandDistributor methodsFor: 'testing' stamp: 'dmu 9/19/2010 20:59'! shouldDisableEnsembleBehavior ^ false! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/22/2010 22:00'! doNotDismember ^ true! ! !Sly3ModCollectionly methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ false! ! !Sly3ModWholly methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ false! ! !Sly3OperandDistributor methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ true! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/22/2010 22:05'! putResultsIntoAnEnsemble ^ putResultsIntoAnEnsemble! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'dmu 9/22/2010 22:17'! fullyExpandStack "Expand the stack to include all of it, rather than the first four or five contexts." self okToChange ifFalse: [^ self]. self newStack: ( contextStackTop contextStackIn: interruptedProcess). self changed: #contextStackList! ! !ContextPart methodsFor: 'debugger access' stamp: 'dmu 9/22/2010 22:18'! contextStackIn: aProcess "Answer an Array of the contexts on the receiver's sender chain." ^self stackOfSize: 100000 in: aProcess! ! !ContextPart methodsFor: 'debugger access' stamp: 'dmu 9/22/2010 22:38'! stackOfSize: limit in: aProcess "Answer an OrderedCollection of the top 'limit' contexts on the receiver's sender chain." | a stack cachedStackTop newLimit p assoc | stack _ OrderedCollection new. stack addLast: (a _ self). p _ aProcess. "Ugh!! I ought to clean this up. -- dmu" [ (assoc _ a senderOrSlyInvokerAndProcessIn: p) ~~ nil and: [stack size < limit]] whileTrue: [ a _ assoc key. p _ assoc value. a hideFromDebugger ifFalse: [stack addLast: a]. a cachesStack ifTrue: [cachedStackTop := a cachedStackTop]]. ^cachedStackTop == nil ifTrue: [stack] ifFalse: [newLimit := limit - stack size. newLimit > 0 ifTrue: [stack addAllLast: (cachedStackTop stackOfSize: newLimit); yourself] ifFalse: [stack]]! ! !ContextPart methodsFor: 'debugger access' stamp: 'dmu 9/22/2010 22:29'! senderOrSlyInvokerIn: aProcess "Answer the context that sent the message that created the receiver." "Follow up the process parent chain to the invoking ensemble process." ^sender ifNotNil: [sender] ifNil: [self halt. aProcess parent ifNil: [nil] ifNotNil: [aProcess parent suspendedContext]]! ! !ContextPart methodsFor: 'debugger access' stamp: 'dmu 9/22/2010 22:38'! senderOrSlyInvokerAndProcessIn: aProcess "Answer the context that sent the message that created the receiver." "Follow up the process parent chain to the invoking ensemble process." ^sender ifNotNil: [sender->aProcess] ifNil: [ aProcess parent ifNil: [nil] ifNotNil: [aProcess parent suspendedContext->aProcess parent]]! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:05'! add: anObject members add: anObject! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:05'! remove: anObject members remove: anObject! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:06'! remove: anObject ifAbsent: blk ^ members remove: anObject ifAbsent: blk! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 16:26'! buildOperandTuples | mems | operandTuples _ OrderedCollection new. operandTuples _ self operandTuplesForObject: message receiver membersOrNil: message members adverbs: message messageAdverbs operandTuplesSoFar: operandTuples. message arguments with: message argumentAdverbs do: [:arg :ads | mems _ arg collectionLY. operandTuples _ self operandTuplesForObject: arg membersOrNil: mems adverbs: ads operandTuplesSoFar: operandTuples]. ^ operandTuples! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 16:16'! operandTuplesForObject: operand membersOrNil: mems adverbs: ads operandTuplesSoFar: operandTuplesSoFar | ods operandTuplesIncludingThisOne | "Return the factor by which to multiply the number of envelopes for this operand." ods _ ads select: [:ad| ad isOperandDistributor]. operandTuplesIncludingThisOne _ ods last extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: mems. ods removeLast. ods reverseDo: [:operandDistributor | operandTuplesIncludingThisOne _ operandDistributor amendOperandTuples: operandTuplesIncludingThisOne ]. ^ operandTuplesIncludingThisOne! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 14:46'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers ^ operandTuplesSoFar ifEmpty: [OrderedCollection with: (OrderedCollection with: operand)] ifNotEmpty: [ operandTuplesSoFar collect: [:tuple | tuple copy addLast: operand; yourself]]! ! !Sly3ModSingly methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:53'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [operandMembers collect: [:m| OrderedCollection with: m]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. operandTuplesSoFar with: mems collect: [:ot :m| ot copy addLast: m; yourself]. ]! ! !Sly3ModSelectively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:03'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [self error: 'cannot be used for receiver'] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'sizes']. mems _ mems copy asOrderedCollection. operandTuplesSoFar select: [:ot | mems removeFirst] ]! ! !Sly3ModRoundly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:32'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [mems asOrderedCollection collect: [:m| OrderedCollection with: m]] ifNotEmpty: [ r _ OrderedCollection new. 1 to: operandMembers size do: [:i | r addAll: (operandTuplesSoFar collect: [:t| t copy addLast: (mems at: i); yourself]).. ]. r ]! ! !Sly3ModDuplicatively methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 14:46'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [operandMembers collect: [:m| OrderedCollection with: m copy]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. r _ OrderedCollection new. operandTuplesSoFar with: mems do: [:ot :m| r addLast: (ot copy addLast: m copy; yourself)]. r]! ! !Sly3ModCollectionly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:01'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [OrderedCollection with: (OrderedCollection with: mems)] ifNotEmpty: [ operandTuplesSoFar collect: [:tuple | tuple copy addLast: mems; yourself]]! ! !Sly3ModValuely methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 14:48'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [mems collect: [:m| OrderedCollection with: (parameter value: m)]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. r _ OrderedCollection new. operandTuplesSoFar with: mems do: [:ot :m| r addLast: (ot copy addLast: (parameter value: m); yourself)]. r]! ! !Sly3ModRandomly methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 00:44'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [ (1 to: parameter) collect: [:m| OrderedCollection with: (mems atRandom: self randomNumberSource)] ] ifNotEmpty: [ r _ OrderedCollection new. parameter timesRepeat: [ r addAll: (operandTuplesSoFar collect: [:t| t copy addLast: (mems atRandom: self randomNumberSource); yourself]). ]. r ]! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:47'! amendOperandTuples: operandTuplesIncludingThisOne | ens | ens _ (operandTuplesIncludingThisOne collect: [:ot| ot last]) asEnsembleOfElements. ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ens; yourself]! ! !Sly3ModSingly methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:10'! amendOperandTuples: operandTuplesIncludingThisOne operandTuplesIncludingThisOne size > 1 ifTrue: [^ self error: 'what?']. ^ operandTuplesIncludingThisOne first last members collect: [:m| operandTuplesIncludingThisOne first copy addLast: m; yourself ]! ! !Sly3ModSelectively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:12'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3ModRoundly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:14'! amendOperandTuples: operandTuplesIncludingThisOne | mems r | mems _ operandTuplesIncludingThisOne collect: [:tup | tup last]. r _ OrderedCollection new. operandTuplesIncludingThisOne do: [:ot| mems do: [:m| r add: (ot copy removeLast; addLast: m; yourself) ] ]. ^ r! ! !Sly3ModDuplicatively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:15'! amendOperandTuples: operandTuplesIncludingThisOne ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ot last copy; yourself]! ! !Sly3ModCollectionly methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 00:46'! amendOperandTuples: operandTuplesIncludingThisOne | ens | ens _ (operandTuplesIncludingThisOne collect: [:ot| ot last]). ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ens; yourself]! ! !Sly3ModValuely methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:16'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3ModRandomly methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:16'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:54'! calculatePutResultsIntoAnEnsemble ((message messageAdverbs select: [:mm| mm isOperandDistributor]) anySatisfy: [:m | m putResultsIntoAnEnsemble]) ifTrue: [^ true]. ^ message argumentAdverbs anySatisfy: [:aa| (aa select: [:mm| mm isOperandDistributor]) anySatisfy: [:m | m putResultsIntoAnEnsemble] ] ! ! !Sly3MessageEvaluator methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:35'! setDisableEnsembleBehaviorFlags | deactivateEnsembleBehaviorFlags | deactivateEnsembleBehaviorFlags _ ((OrderedCollection with: message messageAdverbs) addAll: message argumentAdverbs; yourself) collect: [:adverbs | adverbs anySatisfy: [:adverb| adverb isOperandDistributor and: [adverb shouldDisableEnsembleBehavior]]]. envelopes do: [:e|e deactivateEnsembleBehaviorFlags: deactivateEnsembleBehaviorFlags]! ! !Object methodsFor: 'private' stamp: 'yo 6/29/2004 11:37'! errorNotIndexable "Create an error notification that the receiver is not indexable." self error: ('Instances of {1} are not indexable' translated format: {self class name})! ! !Object methodsFor: 'private' stamp: ''! errorSubscriptBounds: index "Create an error notification that an improper integer was used as an index." self error: 'subscript is out of bounds: ' , index printString! ! !RVMTester class methodsFor: 'primitives' stamp: 'dmu 10/1/2010 19:59'! printObjectForVMDebugging: obj "self printObjectForVMDebugging: 3@4" ! ! Sly3AbstractModifier class instanceVariableNames: ''! Sly3Adverb class instanceVariableNames: ''! Sly3Gerund class instanceVariableNames: ''! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:01'! isIndirect ^ true! ! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter "Answer the value of parameter" parameter isNil ifTrue:[self parameter: nil]. ^ parameter! ! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter: anObject "Set the value of parameter" parameter _ anObject! ! !Sly3ModCollectionly commentStamp: 'dmu 9/3/2010 16:55'! Use members collection of the ensemble! !Sly3ModDuplicatively commentStamp: 'dmu 9/1/2010 15:58'! each member gets a copy of the arguments! !Sly3ModRoundly commentStamp: 'dmu 9/1/2010 15:58'! distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs.! !Sly3ModSingly commentStamp: 'dmu 9/1/2010 15:57'! distributed arguments one-to-one over members! !Sly3ModWholly commentStamp: 'dmu 9/1/2010 15:57'! batch all args to each member with the message! !Sly3ModPlainly commentStamp: 'dmu 9/3/2010 14:28'! Disable all ensemble processing for the recursive duration of this send! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! Sly3EnsembleMirror class instanceVariableNames: ''! Magnitude subclass: #MessageTally instanceVariableNames: 'class method tally receivers senders time gcStats maxClassNameSize maxClassPlusSelectorSize maxTabs' classVariableNames: 'DefaultPollPeriod ObservedProcess Timer' poolDictionaries: '' category: 'Tools-Debugger'! !MessageTally commentStamp: 'nk 3/8/2004 12:43'! My instances observe and report the amount of time spent in methods. NOTE: a higher-level user interface (combining the MessageTally result tree with a method browser) is available from TimeProfileBrowser. MessageTally provides two different strategies available for profiling: * spyOn: and friends use a high-priority Process to interrupt the block or process being spied on at periodic intervals. The interrupted call stack is then examined for caller information. * tallySends: and friends use the interpreter simulator to run the block, recording every method call. The two give you different results: * spyOn: gives you a view of where the time is being spent in your program, at least on a rough statistical level (assuming you've run the block for long enough and have a high enough poll rate). If you're trying to optimize your code, start here and optimize the methods where most of the time is being spent first. * tallySends: gives you accurate counts of how many times methods get called, and by exactly which route. If you're debugging, or trying to figure out if a given method is getting called too many times, this is your tool. You can change the printing format (that is, the whitespace and string compression) by using these instance methods: maxClassNameSize: maxClassPlusSelectorSize: maxTabs: You can change the default polling period (initially set to 1) by calling MessageTally defaultPollPeriod: numberOfMilliseconds Q: How do you interpret MessageTally>>tallySends A: The methods #tallySends and #spyOn: measure two very different quantities, but broken down in the same who-called-who format. #spyOn: is approximate, but more indicative of real time spent, whereas #tallySends is exact and a precise record of how many times each method got executed.! !MessageTally commentStamp: 'nk 3/8/2004 12:43'! My instances observe and report the amount of time spent in methods. NOTE: a higher-level user interface (combining the MessageTally result tree with a method browser) is available from TimeProfileBrowser. MessageTally provides two different strategies available for profiling: * spyOn: and friends use a high-priority Process to interrupt the block or process being spied on at periodic intervals. The interrupted call stack is then examined for caller information. * tallySends: and friends use the interpreter simulator to run the block, recording every method call. The two give you different results: * spyOn: gives you a view of where the time is being spent in your program, at least on a rough statistical level (assuming you've run the block for long enough and have a high enough poll rate). If you're trying to optimize your code, start here and optimize the methods where most of the time is being spent first. * tallySends: gives you accurate counts of how many times methods get called, and by exactly which route. If you're debugging, or trying to figure out if a given method is getting called too many times, this is your tool. You can change the printing format (that is, the whitespace and string compression) by using these instance methods: maxClassNameSize: maxClassPlusSelectorSize: maxTabs: You can change the default polling period (initially set to 1) by calling MessageTally defaultPollPeriod: numberOfMilliseconds Q: How do you interpret MessageTally>>tallySends A: The methods #tallySends and #spyOn: measure two very different quantities, but broken down in the same who-called-who format. #spyOn: is approximate, but more indicative of real time spent, whereas #tallySends is exact and a precise record of how many times each method got executed.! !Sly3ModCollectionly commentStamp: 'dmu 9/3/2010 16:55'! Use members collection of the ensemble! !Sly3ModDuplicatively commentStamp: 'dmu 9/1/2010 15:58'! each member gets a copy of the arguments! !Sly3ModRoundly commentStamp: 'dmu 9/1/2010 15:58'! distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs.! !Sly3ModSingly commentStamp: 'dmu 9/1/2010 15:57'! distributed arguments one-to-one over members! !Sly3ModWholly commentStamp: 'dmu 9/1/2010 15:57'! batch all args to each member with the message! !Sly3ModPlainly commentStamp: 'dmu 9/3/2010 14:28'! Disable all ensemble processing for the recursive duration of this send! !Mutex commentStamp: 'dmu 9/17/2010 12:34'! A Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested. Brought in from Squeak 4.1 because we need it. Instance variables: semaphore The (primitive) semaphore used for synchronization. owner The process owning the mutex.! !TranscriptStream methodsFor: 'Ly*' stamp: 'ssa 7/16/2010 17:06'! nextPutAll: stuff self showInConsole ifTrue:[stuff printConsole]. super nextPutAll: stuff. ! ! MSWSystemView initialize! MSWScrollBarView initialize! JPEGReadStream initialize! JPEGReadWriter initialize! JPEGHuffmanTable initialize! GIFReadWriter initialize! Cursor initialize! Controller initialize! DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine destFormSema' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'! !BitBlt methodsFor: 'copying' stamp: 'ssa 4/7/2009 13:44'! OLDcopyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 5/10/2009 08:43'! copyBits RVMTester isRVM ifFalse:[^self OLDcopyBits]. destForm == Display ifTrue: [self copyBitsOnMain] ifFalse: [self copyBitsLocally]! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards _ (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 _ startPoint. point2 _ stopPoint] ifFalse: [point1 _ stopPoint. point2 _ startPoint]. sourceForm == nil ifTrue: [destX _ point1 x. destY _ point1 y] ifFalse: [width _ sourceForm width. height _ sourceForm height. offset _ sourceForm offset. destX _ (point1 x + offset x) rounded. destY _ (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. (destForm == Display or:[RVMTester isRVM not]) ifTrue: [ self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded] ifFalse: [self drawLoopLocallyX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded]. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/10/2009 22:47'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." ^(destForm == Display or:[RVMTester isRVM not]) ifTrue:[self globalDrawLoopX:xDelta Y: yDelta ] ifFalse:[self localDrawLoopX:xDelta Y: yDelta ]! ! !Paragraph methodsFor: 'RVM' stamp: 'dmu 6/15/2010 11:36'! destFormSema: s destFormSema := s! ! !Paragraph methodsFor: 'private' stamp: 'dmu 4/1/2009 19:38'! compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint compositionRectangle := compositionRect copy. text := aText. textStyle := aTextStyle. rule := DefaultRule. mask := nil. "was DefaultMask " marginTabsLevel := 0. destFormSema := Semaphore forMutualExclusion. self destinationForm: Display. offset := aPoint. ^self composeAll! ! !Paragraph methodsFor: 'private' stamp: 'ssa 4/7/2009 12:39'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | destFormSema isNil ifTrue:[self destFormSema: Semaphore forMutualExclusion]. destFormSema critical: [ saveDestinationForm _ destinationForm. self destinationForm: aDisplayMedium. self displayLines: lineInterval. destinationForm _ saveDestinationForm ]! ! Object subclass: #Sly3Flock instanceVariableNames: 'boids isDone' classVariableNames: '' poolDictionaries: '' category: 'Sly3-Boids'! !Debugger methodsFor: '*Ly' stamp: 'ssa 3/3/2010 22:53'! installListFontInto: aListView "do nothing by default"! ! !Debugger methodsFor: '*Ly' stamp: 'smu 3/4/2010 10:26'! setContextStackIndexFromLyIndex: anIndex | ctx n | ctx _ contextStackTop. n _ 1. [ ctx _ ctx firstContextContainingLyActivation. ctx ifNil: [ Transcript show: 'setContextStackIndexFromLyIndex: missing activation'; cr. ^ self ]. n >= anIndex ifTrue: [ self fullStack. self toggleContextStackIndex: (self contextStack indexOf: ctx). ^ self ]. n _ n + 1. ctx _ ctx sender. ] repeat! ! !Debugger methodsFor: '*Ly' stamp: 'ssa 3/3/2010 20:25'! setContextStackIndexFromOtherIndex: anIndex otherTopContext: ctx self setContextStackIndexFromLyIndex: anIndex! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 23:00'! buildMVCDebuggerViewLabel: aString minSize: aPoint "Build an MVC debugger view around the receiver, and return the StandardSystemView thus created." | topView stackListView stackCodeView rcvrVarView rcvrValView ctxtVarView ctxtValView deltaY underPane annotationPane buttonsView oldContextStackIndex | oldContextStackIndex _ contextStackIndex. self expandStack. "Sets contextStackIndex to zero." contextStackIndex _ oldContextStackIndex. self contextVariablesInspector object: self selectedContext. self receiverInspector object: self receiver. topView _ StandardSystemView new model: self. topView borderWidth: 1. stackListView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #toggleContextStackIndex: menu: #contextStackMenu:shifted: keystroke: #contextStackKey:from:. self installListFontInto: stackListView. stackListView menuTitleSelector: #messageListSelectorTitle. stackListView window: (0 @ 0 extent: 150 @ 50). topView addSubView: stackListView. deltaY _ 0. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 150@self optionalAnnotationHeight). topView addSubView: annotationPane below: stackListView. deltaY _ deltaY + self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [underPane _ stackListView]. self wantsOptionalButtons ifTrue: [buttonsView _ self buildMVCOptionalButtonsButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. deltaY _ deltaY + self optionalButtonHeight]. stackCodeView _ self codeView. stackCodeView window: (0 @ 0 extent: 150 @ (75 - deltaY)). topView addSubView: stackCodeView below: underPane. rcvrVarView _ PluggableListView on: self receiverInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. self installListFontInto: rcvrVarView. rcvrVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: rcvrVarView below: stackCodeView. rcvrValView _ PluggableTextView on: self receiverInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. rcvrValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: rcvrValView toRightOf: rcvrVarView. ctxtVarView _ PluggableListView on: self contextVariablesInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. self installListFontInto: ctxtVarView. ctxtVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: ctxtVarView toRightOf: rcvrValView. ctxtValView _ PluggableTextView on: self contextVariablesInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. ctxtValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: ctxtValView toRightOf: ctxtVarView. topView label: aString. topView minimumSize: aPoint. ^ topView ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 22:55'! buildMVCNotifierViewLabel: aString message: messageString minSize: aPoint | topView notifyView buttonView x y bHeight | self expandStack. topView _ StandardSystemView new model: self. topView borderWidth: 1. buttonView _ self buildMVCNotifierButtonView. topView addSubView: buttonView. notifyView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #debugAt: menu: nil keystroke: nil. self installListFontInto: notifyView. x _ 350 max: (aPoint x). y _ ((4 * 15) + 16) max: (aPoint y - 16 - self optionalButtonHeight). bHeight _ self optionalButtonHeight. y _ y - bHeight. notifyView window: (0@0 extent: x@y). topView addSubView: notifyView below: buttonView; label: aString; minimumSize: aPoint. ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 21:35'! codeView "Answer the code editing view for me" ^PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:! ! !Debugger methodsFor: 'initialize' stamp: 'dmu 3/10/2010 18:15'! customButtonSpecs "Answer an array of elements of the form wording, selector, help-message, that characterize the custom button row of a debugger." | list | list _ #(('Proceed' proceed 'close the debugger and proceed.') ('Restart' restart 'reset this context to its start.') ('Into' send 'step Into message sends') ('Over' doStep 'step Over message sends') ('Through' stepIntoBlock 'step into a block') ('Full Stack' fullStack 'show full stack') ('Where' where 'select current pc range') ('Meta' halt 'go meta & debug the debugger')). list _ list, self otherButtonSpecs. Preferences restartAlsoProceeds ifTrue: [list _ list collect: [:each | each second == #restart ifTrue: [each copy at: 3 put: 'proceed from the beginning of this context.'; yourself] ifFalse: [each]]]. ^ list! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/9/2009 17:35'! debugAt: anInteger self toggleContextStackIndex: anInteger. ^ self debug.! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/10/2009 15:56'! openFullNoSuspendLabel: aString "Create and schedule a full debugger with the given label. Do not terminate the current active process." | topView | topView _ self buildMVCDebuggerViewLabel: aString minSize: 300@200. topView controller openNoTerminate. ^ topView ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/15/2009 14:11'! openNotifierContents: msgString label: label "Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired." "NOTE: When this method returns, a new process has been scheduled to run the windows, and thus this notifier, but the previous active porcess has not been suspended. The sender will do this." | msg topView p | Sensor flushKeyboard. savedCursor _ Sensor currentCursor. Sensor currentCursor: Cursor normal. (label beginsWith: 'Space is low') ifTrue: [msg _ self lowSpaceChoices, (msgString ifNil: [''])] ifFalse: [msg _ msgString]. isolationHead ifNotNil: ["We have already revoked the isolation layer -- now jump to the parent project." msg _ self isolationRecoveryAdvice, msgString. failedProject _ Project current. isolationHead parent enterForEmergencyRecovery]. Display fullScreen. topView _ self buildMVCNotifierViewLabel: label , Time dateAndTimeNow printString message: thisContext sender sender shortStack minSize:600@((14 * 20) + 16 + self optionalButtonHeight). ScheduledControllers activeController ifNil: [p _ Display boundingBox center] ifNotNil: [p _ ScheduledControllers activeController view displayBox center]. topView controller openNoTerminateDisplayAt: (p adhereTo:(Display boundingBox insetBy: topView minimumSize)). ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 7/7/2010 10:48'! otherButtonSpecs | r | r _ OrderedCollection new. (Smalltalk includesKey:#Ly) ifTrue:[ contextStackTop hasLyActivation ifTrue:[r add: #('Debug in Ly' debugInLy 'launch a Ly execution debugger on this stack')]]. ^ r asArray! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 20:55'! release self windowIsClosing. super release. ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 20:58'! terminateInterruptedProcessIfSoleOwner | otherOwners | otherOwners _ Smalltalk pointersTo: interruptedProcess except:{self}. otherOwners detect:[:each| each isKindOf: Debugger] ifNone:[ Transcript show: 'Debugger>>terminateInterruptedProcessIfSoleOwner: ', interruptedProcess identityHash printString; cr. interruptedProcess terminate]. ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 4/20/2010 11:05'! windowIsClosing "My window is being closed; clean up. Restart the low space watcher." interruptedProcess == nil ifTrue: [^ self]. interruptedProcess terminate. "self terminateInterruptedProcessIfSoleOwner." interruptedProcess _ nil. interruptedController _ nil. contextStack _ nil. contextStackTop _ nil. receiverInspector _ nil. contextVariablesInspector _ nil. Smalltalk installLowSpaceWatcher. "restart low space handler" ! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStack "Answer the value of contextStack" contextStack isNil ifTrue:[self contextStack: nil]. ^ contextStack! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStack: anObject "Set the value of contextStack" contextStack _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackIndex: anObject "Set the value of contextStackIndex" contextStackIndex _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackList: anObject "Set the value of contextStackList" contextStackList _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackTop "Answer the value of contextStackTop" contextStackTop isNil ifTrue:[self contextStackTop: nil]. ^ contextStackTop! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackTop: anObject "Set the value of contextStackTop" contextStackTop _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:24'! contextVariablesInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context." contextVariablesInspector isNil ifTrue:[self contextVariablesInspector: self defaultContextVariablesInspector]. ^contextVariablesInspector! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextVariablesInspector: anObject "Set the value of contextVariablesInspector" contextVariablesInspector _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:22'! defaultContextVariablesInspector ^ContextVariablesInspector inspect: nil! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:15'! defaultReceiverInspector ^Inspector inspect: nil! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! errorWasInUIProcess "Answer the value of errorWasInUIProcess" errorWasInUIProcess isNil ifTrue:[self errorWasInUIProcess: nil]. ^ errorWasInUIProcess! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! errorWasInUIProcess: anObject "Set the value of errorWasInUIProcess" errorWasInUIProcess _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! externalInterrupt "Answer the value of externalInterrupt" externalInterrupt isNil ifTrue:[self externalInterrupt: nil]. ^ externalInterrupt! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! failedProject "Answer the value of failedProject" failedProject isNil ifTrue:[self failedProject: nil]. ^ failedProject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! failedProject: anObject "Set the value of failedProject" failedProject _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedController "Answer the value of interruptedController" interruptedController isNil ifTrue:[self interruptedController: nil]. ^ interruptedController! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedController: anObject "Set the value of interruptedController" interruptedController _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedProcess "Answer the value of interruptedProcess" interruptedProcess isNil ifTrue:[self interruptedProcess: nil]. ^ interruptedProcess! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedProcess: anObject "Set the value of interruptedProcess" interruptedProcess _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! isolationHead "Answer the value of isolationHead" isolationHead isNil ifTrue:[self isolationHead: nil]. ^ isolationHead! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! isolationHead: anObject "Set the value of isolationHead" isolationHead _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! proceedValue "Answer the value of proceedValue" proceedValue isNil ifTrue:[self proceedValue: nil]. ^ proceedValue! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:15'! receiverInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context's receiver." receiverInspector isNil ifTrue:[self receiverInspector: self defaultReceiverInspector]. ^receiverInspector! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! receiverInspector: anObject "Set the value of receiverInspector" receiverInspector _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! savedCursor "Answer the value of savedCursor" savedCursor isNil ifTrue:[self savedCursor: nil]. ^ savedCursor! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! savedCursor: anObject "Set the value of savedCursor" savedCursor _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:16'! selectingPC "Answer the value of selectingPC" selectingPC isNil ifTrue:[self selectingPC: false]. ^ selectingPC! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! selectingPC: anObject "Set the value of selectingPC" selectingPC _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! sourceMap "Answer the value of sourceMap" sourceMap isNil ifTrue:[self sourceMap: nil]. ^ sourceMap! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! sourceMap: anObject "Set the value of sourceMap" sourceMap _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! tempNames "Answer the value of tempNames" tempNames isNil ifTrue:[self tempNames: nil]. ^ tempNames! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! tempNames: anObject "Set the value of tempNames" tempNames _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! theMethodNode "Answer the value of theMethodNode" theMethodNode isNil ifTrue:[self theMethodNode: nil]. ^ theMethodNode! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! theMethodNode: anObject "Set the value of theMethodNode" theMethodNode _ anObject! ! !Debugger methodsFor: 'notifier menu' stamp: 'ssa 3/2/2010 18:08'! debug "Open a full DebuggerView." | topView | topView _ self topView. topView isNil ifTrue:[topView _ self buildMVCDebuggerViewLabel: self labelString minSize: 200@200]. topView model: nil. "so close won't release me." topView controller controlTerminate. topView deEmphasize; erase. "a few hacks to get the scroll selection artifacts out when we got here by clicking in the list" topView subViewWantingControl ifNotNil: [ topView subViewWantingControl controller controlTerminate ]. topView controller status: #closed. self openFullNoSuspendLabel: topView label. topView controller closeAndUnscheduleNoErase. Transcript show: 'in debug: ', Processor thisProcess identityHash printString; cr. Processor terminateActive. ! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/10/2010 09:17'! contextStackIndex "Answer the index of the selected context." contextStackIndex isNil ifTrue:[self contextStackIndex: 0]. ^contextStackIndex! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/3/2010 22:23'! expandStack "A Notifier is being turned into a full debugger. Show a substantial amount of stack in the context pane." self newStack: (contextStackTop stackOfSize: 20). contextStackIndex _ 0. receiverInspector _ self defaultReceiverInspector. contextVariablesInspector _ self defaultContextVariablesInspector. proceedValue _ nil! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/2/2010 16:17'! labelForContext: ctxt ^ctxt printString! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 9/15/2009 10:14'! toggleContextStackIndex: anInteger "If anInteger is the same as the index of the selected context, deselect it. Otherwise, the context whose index is anInteger becomes the selected context." self contextStackIndex: (contextStackIndex = anInteger ifTrue: [0] ifFalse: [anInteger]) oldContextWas: ((contextStackIndex = 0 or:[contextStackIndex isNil]) ifTrue: [nil] ifFalse: [contextStack at: contextStackIndex])! ! !Debugger methodsFor: 'code pane' stamp: 'ssa 9/15/2009 10:16'! pcRange "Answer the indices in the source code for the method corresponding to the selected context's program counter value." | i pc end | (self selectingPC and: [contextStackIndex ~= 0]) ifFalse: [^1 to: 0]. sourceMap ifNil: [theMethodNode isNil ifTrue:[^1 to: 0]. sourceMap _ theMethodNode sourceMap. tempNames _ theMethodNode tempNames. self selectedContext method cacheTempNames: tempNames]. (sourceMap size = 0 or: [ self selectedContext isDead ]) ifTrue: [^1 to: 0]. Smalltalk at: #RBProgramNode ifPresent:[:nodeClass| (theMethodNode isKindOf: nodeClass) ifTrue: [ pc _ contextStackIndex = 1 ifTrue: [self selectedContext pc] ifFalse: [self selectedContext previousPc]. i _ sourceMap findLast:[:pcRange | pcRange key <= pc]. i = 0 ifTrue:[^ 1 to: 0]. ^ (sourceMap at: i) value ]. ]. pc_ self selectedContext pc - (("externalInterrupt" true and: [contextStackIndex=1]) ifTrue: [1] ifFalse: [2]). i _ sourceMap indexForInserting: (Association key: pc value: nil). i < 1 ifTrue: [^1 to: 0]. i > sourceMap size ifTrue: [end _ sourceMap inject: 0 into: [:prev :this | prev max: this value last]. ^ end+1 to: end]. ^(sourceMap at: i) value! ! !Debugger methodsFor: 'dependents access' stamp: 'ssa 3/3/2010 22:18'! step "Update the inspectors." self receiverInspector ifNotNil: [self receiverInspector step]. self contextVariablesInspector ifNotNil: [self contextVariablesInspector step]. ! ! !Debugger methodsFor: 'dependents access' stamp: 'ssa 3/3/2010 22:19'! updateInspectors "Update the inspectors on the receiver's variables." self receiverInspector == nil ifFalse: [self receiverInspector update]. self contextVariablesInspector == nil ifFalse: [self contextVariablesInspector update]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/3/2010 21:46'! contextStackIndex: anInteger oldContextWas: oldContext "Change the context stack index to anInteger, perhaps in response to user selection." | newMethod | contextStackIndex := anInteger. anInteger = 0 ifTrue: [currentCompiledMethod := theMethodNode := tempNames := sourceMap := contents := nil. self changed: #contextStackIndex. self decorateButtons. self contentsChanged. contextVariablesInspector object: nil. self updateInspectorToObject: self receiver. ^ self]. (newMethod := oldContext == nil or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)]) ifTrue: [tempNames := sourceMap := nil. theMethodNode := Preferences browseWithPrettyPrint ifTrue: [ self selectedContext methodNodeFormattedAndDecorated: Preferences colorWhenPrettyPrinting ] ifFalse: [ self selectedContext methodNode ]. contents := self selectedMessage. self contentsChanged. self pcRange "will compute tempNamesunless noFrills"]. self changed: #contextStackIndex. self decorateButtons. tempNames == nil ifTrue: [tempNames := self selectedClassOrMetaClass parserClass new parseArgsAndTemps: contents notifying: nil]. contextVariablesInspector object: self selectedContext. self updateInspectorToObject: self receiver. newMethod ifFalse: [self changed: #contentsSelection]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/2/2010 16:16'! newStack: stack | oldStack diff | contextStackTop _ stack first. oldStack _ contextStack. contextStack _ stack. (oldStack == nil or: [oldStack last ~~ stack last]) ifTrue: [contextStackList _ contextStack collect: [:ctx | self labelForContext: ctx ]. ^ self]. "May be able to re-use some of previous list" diff _ stack size - oldStack size. contextStackList _ diff <= 0 ifTrue: [contextStackList copyFrom: 1-diff to: oldStack size] ifFalse: [diff > 1 ifTrue: [contextStack collect: [:ctx | self labelForContext: ctx ]] ifFalse: [(Array with: (self labelForContext:stack first)) , contextStackList]]! ! !Debugger methodsFor: 'private' stamp: 'ssa 9/15/2009 14:25'! process: aProcess controller: aController context: aContext isolationHead: projectOrNil super initialize. Smalltalk at: #MessageTally ifPresentAndInMemory: [:c | c new close]. contents _ nil. interruptedProcess _ aProcess. interruptedController _ aController. contextStackTop _ aContext. self newStack: (contextStackTop stackOfSize: 1). contextStackIndex _ 1. externalInterrupt _ false. selectingPC _ true. isolationHead _ projectOrNil. ! ! !Debugger methodsFor: 'private' stamp: 'dmu 3/10/2010 17:52'! resetContext: aContext "Used when a new context becomes top-of-stack, for instance when the method of the selected context is re-compiled, or the simulator steps or returns to a new method. There is room for much optimization here, first to save recomputing the whole stack list (and text), and secondly to avoid recomposing all that text (by editing the paragraph instead of recreating it)." | oldContext | oldContext _ self selectedContext. contextStackTop _ aContext. self newStack: (contextStackTop ifNil: [^ self release] ifNotNil: [contextStackTop contextStack]). self changed: #contextStackList. self contextStackIndex: 1 oldContextWas: oldContext. self changed: #content.! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/25/2010 16:02'! resumeProcess: aTopView | c | aTopView erase. savedCursor ifNotNil: [Sensor currentCursor: savedCursor]. isolationHead ifNotNil: [failedProject enterForEmergencyRecovery. isolationHead invoke. isolationHead _ nil]. (interruptedProcess isNil or:[interruptedProcess isTerminated]) ifFalse: [ c _ interruptedController ifNil:[ScheduledControllers scheduledControllers last] ifNotNil:[interruptedController]. ScheduledControllers activeControllerNoTerminate: c andProcess: interruptedProcess]. "if old process was terminated, just terminate current one" interruptedProcess _ nil. "Before delete, so release doesn't terminate it" aTopView controller closeAndUnscheduleNoErase. Smalltalk installLowSpaceWatcher. "restart low space handler" errorWasInUIProcess == false ifFalse: [Processor terminateActive]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/10/2010 09:17'! selectedContext self contextStackIndex = 0 ifTrue: [^self contextStackTop] ifFalse: [^self contextStack at: contextStackIndex]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/3/2010 21:48'! updateInspectorToObject: obj self receiverInspector object: obj! ! !Debugger class methodsFor: 'class initialization' stamp: 'dmu 11/25/2008 00:20'! openContext: aContext label: aString contents: contentsStringOrNil | isolationHead | "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." "Simulation guard" ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue: [Smalltalk logError: aString inContext: aContext to: 'SqueakDebug.log']. ErrorRecursion ifTrue: [ErrorRecursion _ false. "(isolationHead _ CurrentProjectRefactoring currentIsolationHead) ifNil: [self primitiveError: aString] ifNotNil: [isolationHead revoke]"]. ErrorRecursion _ true. self informExistingDebugger: aContext label: aString. (Debugger context: aContext isolationHead: nil) openNotifierContents: contentsStringOrNil label: aString. ErrorRecursion _ false. Processor thisProcess suspend. ! ! !Debugger class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:20'! context: aContext isolationHead: isolationHead "Answer an instance of me for debugging the active process starting with the given context." ^ self new process: Processor thisProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: aContext isolationHead: isolationHead ! ! !Debugger class methodsFor: 'opening' stamp: 'dmu 3/10/2010 18:39'! openNoForkSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool selectingOtherIndex: anIndex "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." | controller | controller _ ScheduledControllers activeControllerProcess == process ifTrue: [ScheduledControllers activeController]. [ [ | debugger | debugger _ self new process: process controller: controller context: context. bool ifTrue: [debugger openFullNoSuspendLabel: title] ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]. debugger setContextStackIndexFromOtherIndex: anIndex otherTopContext: context. Preferences logDebuggerStackToFile ifTrue: [ Smalltalk logError: title inContext: context to: 'SqueakDebug.log']. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"]. ] on: Error do: [:ex | self primitiveError: 'Orginal error: ', title asString, '. Debugger error: ', ([ex description] on: Error do: ['a ', ex class printString]), ':' ] ] value! ! !Debugger class methodsFor: 'opening' stamp: 'dmu 3/25/2010 10:22'! openNoSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." | controller | Smalltalk isMorphic ifTrue: [] ifFalse: [controller _ ScheduledControllers activeControllerProcess == process ifTrue: [ScheduledControllers activeController]]. [ [ | debugger | debugger _ self new process: process controller: controller context: context. bool ifTrue: [debugger openFullNoSuspendLabel: title] ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]. Preferences logDebuggerStackToFile ifTrue: [ Smalltalk logError: title inContext: context to: 'SqueakDebug.log']. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"]. ] on: Error do: [:ex | self primitiveError: 'Orginal error: ', title asString, '. Debugger error: ', ([ex description] on: Error do: ['a ', ex class printString]), ':' ] ] fork! ! !Debugger class methodsFor: 'opening' stamp: 'dmu 3/25/2010 10:23'! openOn: process context: context label: title contents: contentsStringOrNil fullView: bool self openNoSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool. process suspend. ! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'dmu 9/7/2010 14:26'! scanVersionsOf: method class: class meta: meta category: category selector: selector | position prevPos prevFileIndex preamble tokens sourceFilesCopy stamp | selectorOfMethod _ selector. currentCompiledMethod _ method. classOfMethod _ meta ifTrue: [class class] ifFalse: [class]. changeList _ OrderedCollection new. list _ OrderedCollection new. self addedChangeRecord ifNotNilDo: [ :change | self addItem: change text: ('{1} (in {2})' translated format: { change stamp. change fileName }) ]. listIndex _ 0. position _ method filePosition. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. method fileIndex == 0 ifTrue: [^ nil]. file _ sourceFilesCopy at: method fileIndex. [position notNil & file notNil] whileTrue: [file position: (0 max: position-150). "Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. "Preamble is likely a linked method preamble, if we're in a changes file (not the sources file). Try to parse it for prior source position and file index" prevPos _ nil. stamp _ ''. (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble] ifFalse: [tokens _ Array new "ie cant be back ref"]. ((tokens size between: 7 and: 8) and: [(tokens at: tokens size-5) = #methodsFor:]) ifTrue: [(tokens at: tokens size-3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos] ifFalse: ["Old format gives no stamp; prior pointer in two parts" prevPos _ tokens at: tokens size-2. prevFileIndex _ tokens last]. (prevPos = 0 or: [prevFileIndex = 0]) ifTrue: [prevPos _ nil]]. ((tokens size between: 5 and: 6) and: [(tokens at: tokens size-3) = #methodsFor:]) ifTrue: [(tokens at: tokens size-1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size]]. self addItem: (ChangeRecord new file: file position: position type: #method class: class name category: category meta: meta stamp: stamp) text: stamp , ' ' , class name , (meta ifTrue: [' class '] ifFalse: [' ']) , selector. position _ prevPos. prevPos notNil ifTrue: [file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !RemoteString methodsFor: 'private' stamp: 'dmu 9/7/2010 14:23'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile _ SourceFiles at: fileNumber. theFile safelyDo: [ theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile] ]! ! !RemoteString methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:19'! text "Answer the receiver's string asText if remote files are enabled." | theFile theText | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile _ SourceFiles at: sourceFileNumber. theFile safelyDo: [ theFile position: filePositionHi. theText _ theFile nextChunkText]. ^theText! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 00:41'! severalIndirectAdverbTests "self severalIndirectAdverbTests run" "self runAll" | theTest | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| %{1. 2. 3} randomLY: 2. %{1. 2. 3} oddRandomLY: 2. %{1. 3. 4} plus: %{4. 5} randomLY: 3. %{2. 4} randomLY: 3 plus: %{2. 6} randomLY: 4 . test assert: true. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'severalIndirectAdverbTests'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tutorial' stamp: 'dmu 9/16/2010 23:51'! tutorialExamples %{1. 2. 3} isNil. "%{false. false. false}." %{1. 2. 3} totallING. "6" %{1. 2. 3} randomLY: 2. "%{1. 3}" %{1. 2. 3} oddRandomLY: 2. "%{true. false}" %{1. 3. 4} plus: %{4. 5} randomLY: 3. "%{5. 8. 8. 6. 7. 8. 6. 8. 8. }" %{2. 4} randomLY: 3 plus: %{2. 6} randomLY: 4. " %{10. 8. 8. 6. 10. 8. 10. 6. 4. 6. 10. 10. }" %{{1. 2}. {3. 4}. {5. 6}} commaWholLY: {9. 10}. "%{#(1 2 9 10). #(3 4 9 10). #(5 6 9 10). }" %{1. 2. 3} collectionLY. " #(1 2 3)" %{10. 20. 30} plusRoundLY: %{4. 5. 6.7. 8. 9} . " %{14. 24. 34. 15. 25. 35. 16.7. 26.7. 36.7. 18. 28. 38. 19. 29. 39. }"! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:59'! plainlyTest "Sly3SyntaxTests plainlyTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{}. result _ ens plainLYisEnsemble. test assert: result. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 14:51'! strategyMultipleAdverbTest "Sly3SyntaxTests strategyMultipleAdverbTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{3. 30}. {4. 40}. {5. 50}}. result _ ens serialLYatRoundLY: %{1. 2} put: %{1. 2. 3. 4. 5. 6} valueLY: [:x| x + 17]. test assert: result members asArray = {18. 19. 20. 21. 22. 23. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'strategyMultipleAdverbTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/17/2010 00:02'! binaryTest "Sly3SyntaxTests binaryTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens + 10. test assert: result members asArray = #(11 12 13). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'binaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/23/2010 13:11'! addTest "Sly3SyntaxTests addTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ {{1. 2}. {3. 4}. {5. 6}} asOrderedCollection asEnsembleOfElements. result _ ens wholLYadd: {7. 8}. test assert: result members asArray = {{1. 2}. {3. 4}. {5. 6}. {7. 8}}. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'addTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/23/2010 13:12'! removeTest "Sly3SyntaxTests removeTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ {{1. 2}. {3. 4}. {5. 6}} asOrderedCollection asEnsembleOfElements. result _ ens wholLYremove: {3. 4}. test assert: result members asArray = {{1. 2}. {5. 6}. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'removeTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 00:54'! singlyTest "Sly3SyntaxTests singlyTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plusSingLY: %{10. 20. 30 }. test assert: result members asArray = {11. 22. 33}. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'singlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! adverbKeywordTest "Sly3SyntaxTests adverbKeywordTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens commaWholLY: {9. 10}. test assert: result members asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! adverbUnaryTest "self adverbUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 1. test assert: (result members size = 1) & (result members first isBoolean). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/22/2010 22:50'! argAdverbRoundlyTest "self argAdverbRoundlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{10. 20. 30}. result _ ens plusRoundLY: %(4. 5. 6. 7. 8. 9}. test assert: result members asArray = {14. 24. 34. 15. 25. 35. 16. 26. 36. 17. 27. 37. 18. 28. 38. 19. 29. 39. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbRoundlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! argAdverbWhollyTest "self argAdverbWhollyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens commaWholLY: {9. 10}. test assert: result members asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbWhollyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundAndingTest "self gerundAndingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens andINGodd. test assert: result = false. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundAndingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/17/2010 16:49'! gerundDoubleKeywordTest "self gerundDoubleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens concatenatINGat: 1 put: #(12 13). test assert: result = #( 12 13 12 13) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundDoubleKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyAveragingTest "self gerundOnlyAveragingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens averagING. test assert: result = 2. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyAveragingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyConcatenatingTest "self gerundOnlyConcatenatingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{'hello'. ' '. 'world'}. result _ ens concatenatING. test assert: result = 'hello world' ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyConcatenatingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyTest "self gerundOnlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallING. test assert: result = 6 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyTotallingTest "self gerundOnlyTotallingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallING. test assert: result = 6 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTotallingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOringTest "self gerundOringTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens orINGodd. test assert: result = true ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOringTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundSingleKeywordTest "self gerundSingleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallINGplus: 1. test assert: result = 9 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundSingleKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundUnaryTest "self gerundUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens andINGodd. test assert: result = false ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvKeywordTest "self msgAdvKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens randomLY: 1 plus:1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvOnlyRandomlyTest "self msgAdvOnlyRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens randomLY: 1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvOnlyRandomlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvRandomly2Test "self msgAdvRandomly2Test run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 2. test assert: (result members size = 2) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomly2Test'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvRandomlyTest "self msgAdvRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:51'! msgAdvSelectivelyTest "self msgAdvSelectivelyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens serialLYselectiveLYvalueLY: [:mbr| mbr odd]. test assert: result members asArray = #(1 3) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSelectivelyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvSeriallyTest "self msgAdvSeriallyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3. 4. 5. 6. 7. 8. 9}. result _ ens serialLY. test assert: (result members asArray = {1. 2. 3. 4. 5. 6. 7. 8. 9}) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSeriallyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! normalBinaryTest "self normalBinaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens +1. test assert: result members = {2. 3. 4} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalBinaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! normalKeywordTest "self normalKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1. test assert: result members = {2. 3. 4} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/22/2010 22:54'! normalUnaryTest "self normalUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens odd. test assert: result members = {true. false. true} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:50'! gerundPerformWithWithTest "CURRENTLY FAILS" "self gerundPerformWithWithTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens perform: #at:put: with: 1 with: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} perform: #at:put: with: 1 with 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundPerformWithWithTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'harness' stamp: 'dmu 9/3/2010 11:50'! runAll super runAll! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! membersTest "Sly3SyntaxTests ensMembersTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens members. test assert: result = {{1. 2}. {3. 4}. {5. 6}} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensMembersTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 00:37'! printStringTest "Sly3SyntaxTests printStringTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plainLYprintString. test assert: result = '%{1. 2. 3. }' ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'printStringTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! sizeTest "Sly3SyntaxTests sizeTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens collectionLYsize. test assert: result = 3 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'sizeTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! adverbKeywordTest "SlySyntaxTests adverbKeywordTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. self halt. result _ ens comma: {9. 10} LY:#wholly. test assert: result ENSmembers asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)) ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} comma: {9. 10} LY:#wholly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! adverbUnaryTest "self adverbUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#randomly. test assert: (result ENSmembers size = 1) & (result ENSmembers first isBoolean) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! argAdverbRoundlyTest "self argAdverbRoundlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: #(4 5 6 7 8 9) LY:#roundly. test assert: result ENSmembers asArray = #(5 7 9 8 10 12) ifFail:[test log:' failed: %{1. 2. 3} plus: #(4 5 6 7 8 9) LY:#roundly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbRoundlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! argAdverbWhollyTest "self argAdverbWhollyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens comma: {9. 10} LY:#wholly. test assert: result ENSmembers asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)) ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} comma: {9. 10} LY:#wholly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbWhollyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensMembersTest "SlySyntaxTests ensMembersTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens ENSmembers. test assert: result = {{1. 2}. {3. 4}. {5. 6}} ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} ENSmembers ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensMembersTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensPrintStringTest "SlySyntaxTests ensPrintStringTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ENSprintString. test assert: result = '%{1. 2. 3. }' ifFail:[test log:' failed: %{1. 2. 3} ENSprintString ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensPrintStringTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensSizeTest "SlySyntaxTests ensSizeTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens ENSsize. test assert: result = 3 ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} ENSsize ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensSizeTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundAndingTest "self gerundAndingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #anding. test assert: result = false ifFail:[test log:' failed: %{1. 2. 3} oddING: #anding ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundAndingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundDoubleKeywordTest "self gerundDoubleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens at: 1 put: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} at: 1 put: 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundDoubleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyAveragingTest "self gerundOnlyAveragingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #averaging. test assert: result = 2 ifFail:[test log:' failed: %{1. 2. 3} ING: #averaging ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyAveragingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyConcatenatingTest "self gerundOnlyConcatenatingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{'hello'. ' '. 'world'}. result _ ens ING: #concatenating. test assert: result = 'hello world' ifFail:[test log:' failed: %{''hello''. '' ''. ''world''} ING:#concatenating ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyConcatenatingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyTest "self gerundOnlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #totalling. test assert: result = 6 ifFail:[test log:' failed: %{1. 2. 3} ING: #totalling ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyTotallingTest "self gerundOnlyTotallingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #totalling. test assert: result = 6 ifFail:[test log:' failed: %{1. 2. 3} ING: #totalling ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTotallingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOringTest "self gerundOringTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #oring. test assert: result = true ifFail:[test log:' failed: %{1. 2. 3} oddING: #oring ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOringTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundSingleKeywordTest "self gerundSingleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1 ING:#totalling. test assert: result = 9 ifFail:[test log:' failed: %{1. 2. 3} plus: 1 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundSingleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundTripleKeywordTest "self gerundTripleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens changed:#foo with:#bar from:self ING:#concatenating. test assert: result = #( 1 2) ifFail:[test log:' failed: %{#(1). #(2)} changed:#foo with:#bar from:self ING:#concatenating ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundTripleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundUnaryTest "self gerundUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #anding. test assert: result = false ifFail:[test log:' failed: %{1. 2. 3} oddING: #anding ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvKeywordTest "self msgAdvKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens LY:#randomly plus:1. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} LY:#randomly plus:1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvOnlyRandomlyTest "self msgAdvOnlyRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens yourselfLY:#randomly. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} LY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvOnlyRandomlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvRandomly2Test "self msgAdvRandomly2Test run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#(#randomly: 2). test assert: (result ENSmembers size = 2) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#(#randomly: 2) ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomly2Test'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvRandomlyTest "self msgAdvRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#randomly. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! msgAdvSelectivelyTest "self msgAdvSelectivelyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens yourselfLY:{#selectively:. [:mbr| mbr odd]}. test assert: result ENSmembers asArray = #(1 3) ifFail:[test log:' failed: %{1. 2. 3} yourselfLy:{#selectively:. [:mbr| mbr odd]} ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSelectivelyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalBinaryTest "self normalBinaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens +1. test assert: result ENSmembers = {2. 3. 4} ifFail:[test log:' failed: %{1. 2. 3} + 1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalBinaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalKeywordTest "self normalKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1. test assert: result ENSmembers = {2. 3. 4} ifFail:[test log:' failed: %{1. 2. 3} plus: 1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalUnaryTest "self normalUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens odd. test assert: result ENSmembers = {true. false. true} ifFail:[test log:' failed: %{1. 2. 3} odd ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:52'! gerundPerformWithWithTest "CURRENTLY FAILS" "self gerundPerformWithWithTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens perform: #at:put: with: 1 with: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} perform: #at:put: with: 1 with 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundPerformWithWithTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! msgAdvSeriallyTest "self msgAdvSeriallyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3. 4. 5. 6. 7. 8. 9}. result _ ens yourselfLY:#serially. test assert: (result ENSmembers asArray = {1. 2. 3. 4. 5. 6. 7. 8. 9}) ifFail:[test log:' failed: %{1. 2. 3. 4. 5. 6. 7. 8. 9} yourselfLY:#serially ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSeriallyTest'. ^theTest! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:51'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: #()]. ^ flock! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! flock: anObject "Set the value of flock" flock _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:57'! lastDrawnPosition "Answer the value of lastDrawnPosition" lastDrawnPosition isNil ifTrue:[self lastDrawnPosition: self position]. ^ lastDrawnPosition! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:00'! lastDrawnPosition: anObject "Set the value of lastDrawnPosition" lastDrawnPosition _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/23/2010 00:05'! lastLastDrawnPosition "Answer the value of lastLastDrawnPosition" lastLastDrawnPosition isNil ifTrue:[self lastLastDrawnPosition: self lastDrawnPosition]. ^ lastLastDrawnPosition! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/22/2010 23:53'! lastLastDrawnPosition: anObject "Set the value of lastLastDrawnPosition" lastLastDrawnPosition _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:53'! neighbors "Answer the value of neighbors" neighbors isNil ifTrue:[self neighbors: #()]. ^ neighbors! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! neighbors: anObject "Set the value of neighbors" neighbors _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! position "Answer the value of position" position isNil ifTrue:[self position: 500@500]. ^ position! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! position: anObject "Set the value of position" position _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! velocity "Answer the value of velocity" velocity isNil ifTrue:[self velocity: 0@0]. ^ velocity! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! velocity: anObject "Set the value of velocity" velocity _ anObject! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:00'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." ^ (self flock boids members collect: [:m| m position]) average! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:01'! computeNeighbors ^self flock boids members select:[:m| m isNear: self]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:07'! draw | p | self lastDrawnPosition = self position ifTrue: [^ self]. p _ self position. false ifTrue: [ Sly3Graphics drawWhiteCircle: self lastDrawnPosition. Sly3Graphics drawCircle: p. "Sly3Graphics drawFrom: self lastDrawnPosition to: p." ] ifFalse: [ Sly3Graphics drawFrom: self lastDrawnPosition to: p. Sly3Graphics eraseFrom: self lastLastDrawnPosition to: self lastDrawnPosition. ]. self lastLastDrawnPosition: self lastDrawnPosition. self lastDrawnPosition: p! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:22'! fly | centroid | [Sly3 keepFlying] whileTrue:[ centroid _ self computeCentroid. self moveToNewPosition: centroid. self flock maybeYield ]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:15'! go self fly! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:43'! isNear: aBoid ^ (self ~== aBoid) and: [(self position dist: aBoid position) <= 10]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:04'! keepAwayFromNeighbors | sum | self neighbors ifEmpty: [^ 0@0]. sum _ 0. self neighbors do: [:m | sum _ sum + (self position - m position)]. ^ sum / self neighbors size asFloat! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:30'! limitPositionFrom: min to: max | r pos | pos _ self position. r _ ((pos max: min@min) min: max@max). r = pos ifTrue: [^ self]. pos x < min ifTrue: [r _ min + (min - pos x) @ pos y. self velocity: self velocity x negated @ self velocity y]. pos y < min ifTrue: [r _ pos x @ (min + (min - pos y)). self velocity: self velocity x @ self velocity y negated]. pos x > max ifTrue: [r _ max - (pos x - max) @ pos y. self velocity: self velocity x negated @ self velocity y ]. pos y > max ifTrue: [r _ pos x @ (max - (pos y - max)). self velocity: self velocity x @ self velocity y negated]. self position: r! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:36'! limitVelocityTo: n | ns v vs q | ns _ n * n * 2. v _ self velocity. vs _ v x squared + v y squared. vs <= ns ifTrue: [^ self]. q _ (ns / vs) sqrt. self velocity: v * q.! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 15:54'! matchVelocityWithNeighbors self neighbors size = 0 ifTrue: [^ 0@0]. ^ (self neighbors collect: [:m| m velocity]) average / 8.0! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:04'! moveToNewPosition: centroid | a b c | self neighbors: self computeNeighbors. a _ self moveTowardCentroidOfAllOthers: centroid. b _ self keepAwayFromNeighbors. c _ self matchVelocityWithNeighbors. self velocity: self velocity + a + b + c. self limitVelocityTo: 10. self position: self position + self velocity. self limitPositionFrom: 0 to: 1000! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:16'! moveTowardCentroidOfAllOthers: centroid | perceivedCentroid s | "collectionLYSize introduces overhead." s _ self flock boids collectionLYsize. s < 2 ifTrue: [^ 0@0]. perceivedCentroid _ (centroid * s - self position) / (s - 1). ^ (perceivedCentroid - self position) / 100.0! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:54'! perturb self position: (self position perturb: 100). self velocity: (self velocity perturb: 2).! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:52'! boidClass ^ Sly3Boid! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 9/17/2010 15:37'! flockSize "RVMTester coreCount - 6 max: 10". ^ 3! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:58'! run "Transcript show: (Time millisecondsToRun: [Sly3Boids new run]); cr" "[ Sly3Boids new run ] fork" | c flock drawer flockAndDrawer n | c _ OrderedCollection new. n _ self flockSize. 1 to: n do: [:i| c add: self boidClass new perturb]. flock _ Sly3Flock boids: c asEnsembleOfElements. flock boids flock: flock. drawer _ self drawerClass flock: flock. flockAndDrawer _ %{flock. drawer}. "SlyGraphics clearScreen." flockAndDrawer go ! ! Sly3Boids class instanceVariableNames: ''! !Sly3Boids class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:30'! run ^ self new run! ! !Sly3Drawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: nil]. ^ flock! ! !Sly3Drawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock: anObject "Set the value of flock" flock _ anObject! ! !Sly3Drawer methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:28'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids members do: [:b| b draw]]! ! Sly3Drawer class instanceVariableNames: ''! !Sly3Drawer class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:07'! flock: f ^ self new flock: f! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:39'! boids "Answer the value of boids" ^ boids! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:11'! boids: anObject "Set the value of boids" boids _ anObject! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone "Answer the value of isDone" isDone isNil ifTrue:[self isDone: false]. ^ isDone! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone: anObject "Set the value of isDone" isDone _ anObject! ! !Sly3Flock methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:13'! go self isDone: false. boids fly. self isDone: true! ! !Sly3Flock methodsFor: 'as yet unclassified' stamp: 'dmu 9/7/2010 17:32'! maybeYield | n | "[Processor yield. ^self]value." Sly3 serializeForDebugging ifTrue: [Processor yield. ^ self]. n _self boids collectionLYsize + 1 "1 for Drawer". Processor yieldIfFewerCoresThan: n! ! Sly3Flock class instanceVariableNames: ''! !Sly3Flock class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:11'! boids: b ^ self new boids: b! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 9/16/2010 23:59'! receiver "Answer the value of receiver" "Send no messages; might be an ensemble" nil == receiver ifTrue:[self receiver: ( %{})]. ^ receiver! ! Preferences disable: #nicerSystemViews! ================================================ FILE: vm/RoarVM.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 0A278518128DBF7400336BDE /* externals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2783F6128DBF7300336BDE /* externals.cpp */; }; 0A278519128DBF7400336BDE /* FilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278400128DBF7300336BDE /* FilePlugin.c */; }; 0A27851A128DBF7400336BDE /* sqFilePluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278402128DBF7300336BDE /* sqFilePluginBasicPrims.c */; }; 0A27851E128DBF7400336BDE /* B2DPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27840F128DBF7300336BDE /* B2DPlugin.c */; }; 0A27851F128DBF7400336BDE /* BitBltPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278411128DBF7300336BDE /* BitBltPlugin.c */; }; 0A278520128DBF7400336BDE /* FloatArrayPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278413128DBF7300336BDE /* FloatArrayPlugin.c */; }; 0A278521128DBF7400336BDE /* LargeIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278415128DBF7300336BDE /* LargeIntegers.c */; }; 0A278522128DBF7400336BDE /* Matrix2x3Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278417128DBF7300336BDE /* Matrix2x3Plugin.c */; }; 0A278523128DBF7400336BDE /* MiscPrimitivePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278419128DBF7300336BDE /* MiscPrimitivePlugin.c */; }; 0A278524128DBF7400336BDE /* SocketPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27841B128DBF7300336BDE /* SocketPlugin.c */; }; 0A278525128DBF7400336BDE /* SoundPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27841D128DBF7300336BDE /* SoundPlugin.c */; }; 0A278529128DBF7400336BDE /* aio.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278426128DBF7300336BDE /* aio.c */; }; 0A278531128DBF7400336BDE /* sqUnixCustomSound.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27843D128DBF7300336BDE /* sqUnixCustomSound.c */; }; 0A278533128DBF7400336BDE /* sqUnixSoundNull.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278442128DBF7300336BDE /* sqUnixSoundNull.c */; }; 0A278534128DBF7400336BDE /* abstract_mark_sweep_collector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278444128DBF7300336BDE /* abstract_mark_sweep_collector.cpp */; }; 0A278535128DBF7400336BDE /* abstract_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278446128DBF7300336BDE /* abstract_object_heap.cpp */; }; 0A278536128DBF7400336BDE /* memory_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27844D128DBF7300336BDE /* memory_system.cpp */; }; 0A278537128DBF7400336BDE /* multicore_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278450128DBF7300336BDE /* multicore_object_heap.cpp */; }; 0A278538128DBF7400336BDE /* multicore_object_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278453128DBF7300336BDE /* multicore_object_table.cpp */; }; 0A27853C128DBF7400336BDE /* squeak_image_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278460128DBF7300336BDE /* squeak_image_reader.cpp */; }; 0A27853D128DBF7400336BDE /* at_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278464128DBF7300336BDE /* at_cache.cpp */; }; 0A27853E128DBF7400336BDE /* interpreter_bytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278467128DBF7300336BDE /* interpreter_bytecodes.cpp */; }; 0A27853F128DBF7400336BDE /* interpreter_primitives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278469128DBF7300336BDE /* interpreter_primitives.cpp */; }; 0A278540128DBF7400336BDE /* method_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846B128DBF7300336BDE /* method_cache.cpp */; }; 0A278541128DBF7400336BDE /* obsolete_indexed_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846D128DBF7300336BDE /* obsolete_indexed_primitive_table.cpp */; }; 0A278542128DBF7400336BDE /* obsolete_named_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846F128DBF7300336BDE /* obsolete_named_primitive_table.cpp */; }; 0A278543128DBF7400336BDE /* primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278471128DBF7300336BDE /* primitive_table.cpp */; }; 0A278544128DBF7400336BDE /* squeak_interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278473128DBF7400336BDE /* squeak_interpreter.cpp */; }; 0A278545128DBF7400336BDE /* abstract_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847B128DBF7400336BDE /* abstract_message.cpp */; }; 0A278546128DBF7400336BDE /* deferred_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847D128DBF7400336BDE /* deferred_request.cpp */; }; 0A278547128DBF7400336BDE /* interactions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847F128DBF7400336BDE /* interactions.cpp */; }; 0A278548128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278481128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp */; }; 0A278549128DBF7400336BDE /* message_classes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278483128DBF7400336BDE /* message_classes.cpp */; }; 0A27854A128DBF7400336BDE /* message_or_ack_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278485128DBF7400336BDE /* message_or_ack_request.cpp */; }; 0A27854B128DBF7400336BDE /* message_statics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278487128DBF7400336BDE /* message_statics.cpp */; }; 0A27854C128DBF7400336BDE /* message_stats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278489128DBF7400336BDE /* message_stats.cpp */; }; 0A27854D128DBF7400336BDE /* receive_marker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27848C128DBF7400336BDE /* receive_marker.cpp */; }; 0A278557128DBF7400336BDE /* header_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784A4128DBF7400336BDE /* header_type.cpp */; }; 0A278558128DBF7400336BDE /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784A6128DBF7400336BDE /* object.cpp */; }; 0A278559128DBF7400336BDE /* process_field_locator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784AB128DBF7400336BDE /* process_field_locator.cpp */; }; 0A27855A128DBF7400336BDE /* roots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784AD128DBF7400336BDE /* roots.cpp */; }; 0A27855B128DBF7400336BDE /* oop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784B3128DBF7400336BDE /* oop.cpp */; }; 0A27855C128DBF7400336BDE /* abstract_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784BB128DBF7400336BDE /* abstract_os_interface.cpp */; }; 0A27855D128DBF7400336BDE /* dummy_cpu_coordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784BE128DBF7400336BDE /* dummy_cpu_coordinate.cpp */; }; 0A278561128DBF7400336BDE /* osx_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784C9128DBF7400336BDE /* osx_os_interface.cpp */; }; 0A278562128DBF7400336BDE /* posix_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784CB128DBF7400336BDE /* posix_os_interface.cpp */; }; 0A278564128DBF7400336BDE /* shared_memory_message_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784CF128DBF7400336BDE /* shared_memory_message_queue.cpp */; }; 0A278565128DBF7400336BDE /* thread_memory_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D1128DBF7400336BDE /* thread_memory_semantics.cpp */; }; 0A278567128DBF7400336BDE /* RVMPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D6128DBF7400336BDE /* RVMPlugin.cpp */; }; 0A278568128DBF7400336BDE /* abstract_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D9128DBF7400336BDE /* abstract_mutex.cpp */; }; 0A278569128DBF7400336BDE /* abstract_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DB128DBF7400336BDE /* abstract_tracer.cpp */; }; 0A27856A128DBF7400336BDE /* bytemap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DD128DBF7400336BDE /* bytemap.cpp */; }; 0A27856B128DBF7400336BDE /* core_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DF128DBF7400336BDE /* core_tracer.cpp */; }; 0A27856C128DBF7400336BDE /* gc_debugging_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E2128DBF7400336BDE /* gc_debugging_tracer.cpp */; }; 0A27856D128DBF7400336BDE /* error_handling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E4128DBF7400336BDE /* error_handling.cpp */; }; 0A27856E128DBF7400336BDE /* execution_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E6128DBF7400336BDE /* execution_tracer.cpp */; }; 0A27856F128DBF7400336BDE /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E9128DBF7400336BDE /* main.cpp */; }; 0A278570128DBF7400336BDE /* measurements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EA128DBF7400336BDE /* measurements.cpp */; }; 0A278571128DBF7400336BDE /* my_rank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EC128DBF7400336BDE /* my_rank.cpp */; }; 0A278572128DBF7400336BDE /* oop_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EE128DBF7400336BDE /* oop_tracer.cpp */; }; 0A278573128DBF7400336BDE /* printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F0128DBF7400336BDE /* printer.cpp */; }; 0A278574128DBF7400336BDE /* profiling_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F2128DBF7400336BDE /* profiling_tracer.cpp */; }; 0A278575128DBF7400336BDE /* rank_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F4128DBF7400336BDE /* rank_set.cpp */; }; 0A278576128DBF7400336BDE /* rvm_bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F7128DBF7400336BDE /* rvm_bitmap.cpp */; }; 0A278577128DBF7400336BDE /* rvm_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F9128DBF7400336BDE /* rvm_config.cpp */; }; 0A278578128DBF7400336BDE /* safepoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FB128DBF7400336BDE /* safepoint.cpp */; }; 0A278579128DBF7400336BDE /* safepoint_ability.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FD128DBF7400336BDE /* safepoint_ability.cpp */; }; 0A27857A128DBF7400336BDE /* safepoint_request_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FF128DBF7400336BDE /* safepoint_request_queue.cpp */; }; 0A27857B128DBF7400336BDE /* scheduler_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278501128DBF7400336BDE /* scheduler_mutex.cpp */; }; 0A27857C128DBF7400336BDE /* semaphore_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278503128DBF7400336BDE /* semaphore_mutex.cpp */; }; 0A27857D128DBF7400336BDE /* squeak_adapters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278505128DBF7400336BDE /* squeak_adapters.cpp */; }; 0A27857E128DBF7400336BDE /* timeout_deferral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278507128DBF7400336BDE /* timeout_deferral.cpp */; }; 0A27857F128DBF7400336BDE /* timeout_timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278509128DBF7400336BDE /* timeout_timer.cpp */; }; 0A278580128DBF7400336BDE /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27850B128DBF7400336BDE /* utils.cpp */; }; 0A2785A6128DC2B700336BDE /* logical_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784C4128DBF7400336BDE /* logical_core.cpp */; }; 0A2785E4128DC3A000336BDE /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A2785E3128DC3A000336BDE /* CoreFoundation.framework */; }; 0A2785EE128DC42800336BDE /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A2785ED128DC42800336BDE /* CoreServices.framework */; }; 0A3FB13614D99C7E0050F39C /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0A3FB13514D99C7E0050F39C /* gtest-all.cc */; }; 0A4D824B135C51D500CD74D8 /* sqNamedPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8249135C51D500CD74D8 /* sqNamedPrims.c */; }; 0A4D824C135C51D500CD74D8 /* sqNamedPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8249135C51D500CD74D8 /* sqNamedPrims.c */; }; 0A4D824D135C51D500CD74D8 /* sqVirtualMachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D824A135C51D500CD74D8 /* sqVirtualMachine.c */; }; 0A4D824E135C51D500CD74D8 /* sqVirtualMachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D824A135C51D500CD74D8 /* sqVirtualMachine.c */; }; 0A4D8253135C523B00CD74D8 /* sqUnixCharConv.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8250135C523B00CD74D8 /* sqUnixCharConv.c */; }; 0A4D8254135C523B00CD74D8 /* sqUnixCharConv.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8250135C523B00CD74D8 /* sqUnixCharConv.c */; }; 0A4D8255135C523B00CD74D8 /* sqUnixExternalPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8251135C523B00CD74D8 /* sqUnixExternalPrims.c */; }; 0A4D8256135C523B00CD74D8 /* sqUnixExternalPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8251135C523B00CD74D8 /* sqUnixExternalPrims.c */; }; 0A4D8257135C523B00CD74D8 /* sqUnixMain.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8252135C523B00CD74D8 /* sqUnixMain.c */; }; 0A4D8258135C523B00CD74D8 /* sqUnixMain.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8252135C523B00CD74D8 /* sqUnixMain.c */; }; 0A4D825A135C526100CD74D8 /* sqUnixX11.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8259135C526100CD74D8 /* sqUnixX11.c */; }; 0A4D825B135C526100CD74D8 /* sqUnixX11.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D8259135C526100CD74D8 /* sqUnixX11.c */; }; 0A4D825D135C526F00CD74D8 /* sqUnixSoundMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D825C135C526F00CD74D8 /* sqUnixSoundMacOSX.c */; }; 0A5D7C99135CC84700D13E53 /* sqUnixSound.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7C98135CC84700D13E53 /* sqUnixSound.c */; }; 0A5D7C9C135CC86800D13E53 /* sqUnixSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7C9B135CC86800D13E53 /* sqUnixSocket.c */; }; 0A6A4834135ADF0A00933643 /* os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6A4832135ADF0A00933643 /* os_interface.cpp */; }; 0A6A4837135AE32D00933643 /* external_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A6A4835135AE32D00933643 /* external_primitive_table.cpp */; }; 0A72A76514432D7C0008E8AC /* tmc_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A72A76314432D7C0008E8AC /* tmc_os_interface.cpp */; }; 0A87AD8A1379573F00337878 /* performance_counters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A87AD891379573E00337878 /* performance_counters.cpp */; }; 0A8C91C712DE62B6007DBAD9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A8C91C612DE62B6007DBAD9 /* IOKit.framework */; }; 0A97FB35128FEA77003A1C74 /* buffered_channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27850F128DBF7400336BDE /* buffered_channel.cpp */; }; 0A97FB36128FEA77003A1C74 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278510128DBF7400336BDE /* main.cpp */; }; 0A97FB37128FEA77003A1C74 /* starter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278511128DBF7400336BDE /* starter.cpp */; }; 0A97FB39128FEA77003A1C74 /* synced_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278513128DBF7400336BDE /* synced_queue.cpp */; }; 0A97FB3A128FEA77003A1C74 /* synced_queue_threaded.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278514128DBF7400336BDE /* synced_queue_threaded.cpp */; }; 0A97FBB512900371003A1C74 /* tracked_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A97FBB412900371003A1C74 /* tracked_ptr.cpp */; }; 0ACF551912E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0ACF551712E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp */; }; 0ADA26E612EF642C009404B0 /* cacheline_alignment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0ADA26B912EF5C00009404B0 /* cacheline_alignment.cpp */; }; 0AE6D0E61531C596001A1018 /* buffered_channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AE6D0E21531C596001A1018 /* buffered_channel.cpp */; }; 0AE6D0E71531C596001A1018 /* synced_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AE6D0E41531C596001A1018 /* synced_queue.cpp */; }; 0AE6D0E91531C63D001A1018 /* buffered_channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AE6D0E21531C596001A1018 /* buffered_channel.cpp */; }; 0AE6D0EA1531C645001A1018 /* synced_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AE6D0E41531C596001A1018 /* synced_queue.cpp */; }; 0AE6D0EB1531C740001A1018 /* squeak_adapters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278505128DBF7400336BDE /* squeak_adapters.cpp */; }; 0AE6D0EC1531C776001A1018 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27850B128DBF7400336BDE /* utils.cpp */; }; 0AE6D0ED1531C78B001A1018 /* oop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784B3128DBF7400336BDE /* oop.cpp */; }; 0AE6D0EE1531C7DE001A1018 /* header_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784A4128DBF7400336BDE /* header_type.cpp */; }; 0AE6D0EF1531C7E3001A1018 /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784A6128DBF7400336BDE /* object.cpp */; }; 0AE6D0F01531C7E7001A1018 /* process_field_locator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784AB128DBF7400336BDE /* process_field_locator.cpp */; }; 0AE6D0F11531C7EB001A1018 /* roots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784AD128DBF7400336BDE /* roots.cpp */; }; 0AE6D0F21531C7FC001A1018 /* abstract_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784BB128DBF7400336BDE /* abstract_os_interface.cpp */; }; 0AE6D0F31531C800001A1018 /* dummy_cpu_coordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784BE128DBF7400336BDE /* dummy_cpu_coordinate.cpp */; }; 0AE6D0F41531C80C001A1018 /* logical_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784C4128DBF7400336BDE /* logical_core.cpp */; }; 0AE6D0F61531C824001A1018 /* shared_memory_message_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784CF128DBF7400336BDE /* shared_memory_message_queue.cpp */; }; 0AE6D0F71531C827001A1018 /* shared_memory_message_queue_per_sender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0ACF551712E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp */; }; 0AE6D0F81531C82A001A1018 /* thread_memory_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D1128DBF7400336BDE /* thread_memory_semantics.cpp */; }; 0AE6D0F91531C832001A1018 /* RVMPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D6128DBF7400336BDE /* RVMPlugin.cpp */; }; 0AE6D0FA1531C838001A1018 /* abstract_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784D9128DBF7400336BDE /* abstract_mutex.cpp */; }; 0AE6D0FB1531C83B001A1018 /* abstract_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DB128DBF7400336BDE /* abstract_tracer.cpp */; }; 0AE6D0FC1531C83E001A1018 /* bytemap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DD128DBF7400336BDE /* bytemap.cpp */; }; 0AE6D0FD1531C842001A1018 /* core_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784DF128DBF7400336BDE /* core_tracer.cpp */; }; 0AE6D0FE1531C846001A1018 /* gc_debugging_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E2128DBF7400336BDE /* gc_debugging_tracer.cpp */; }; 0AE6D0FF1531C849001A1018 /* error_handling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E4128DBF7400336BDE /* error_handling.cpp */; }; 0AE6D1001531C84C001A1018 /* execution_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784E6128DBF7400336BDE /* execution_tracer.cpp */; }; 0AE6D1011531C853001A1018 /* measurements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EA128DBF7400336BDE /* measurements.cpp */; }; 0AE6D1021531C856001A1018 /* my_rank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EC128DBF7400336BDE /* my_rank.cpp */; }; 0AE6D1031531C859001A1018 /* oop_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784EE128DBF7400336BDE /* oop_tracer.cpp */; }; 0AE6D1041531C85D001A1018 /* printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F0128DBF7400336BDE /* printer.cpp */; }; 0AE6D1051531C860001A1018 /* profiling_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F2128DBF7400336BDE /* profiling_tracer.cpp */; }; 0AE6D1061531C864001A1018 /* rank_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F4128DBF7400336BDE /* rank_set.cpp */; }; 0AE6D1071531C868001A1018 /* rvm_bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F7128DBF7400336BDE /* rvm_bitmap.cpp */; }; 0AE6D1081531C884001A1018 /* rvm_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784F9128DBF7400336BDE /* rvm_config.cpp */; }; 0AE6D1091531C887001A1018 /* safepoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FB128DBF7400336BDE /* safepoint.cpp */; }; 0AE6D10A1531C88A001A1018 /* safepoint_ability.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FD128DBF7400336BDE /* safepoint_ability.cpp */; }; 0AE6D10B1531C88E001A1018 /* safepoint_request_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784FF128DBF7400336BDE /* safepoint_request_queue.cpp */; }; 0AE6D10C1531C891001A1018 /* semaphore_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278503128DBF7400336BDE /* semaphore_mutex.cpp */; }; 0AE6D10D1531C894001A1018 /* scheduler_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278501128DBF7400336BDE /* scheduler_mutex.cpp */; }; 0AE6D10E1531C899001A1018 /* timeout_deferral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278507128DBF7400336BDE /* timeout_deferral.cpp */; }; 0AE6D10F1531C89C001A1018 /* timeout_timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278509128DBF7400336BDE /* timeout_timer.cpp */; }; 0AE6D1101531C8A1001A1018 /* debug_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AEC1185128DF0A000EFF6D1 /* debug_helper.cpp */; }; 0AE6D1111531C8A5001A1018 /* performance_counters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A87AD891379573E00337878 /* performance_counters.cpp */; }; 0AE6D1121531C8C4001A1018 /* FilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278400128DBF7300336BDE /* FilePlugin.c */; }; 0AE6D1131531C90F001A1018 /* tmc_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A72A76314432D7C0008E8AC /* tmc_os_interface.cpp */; }; 0AE6D1141531C927001A1018 /* sqFilePluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278402128DBF7300336BDE /* sqFilePluginBasicPrims.c */; }; 0AE6D1161531C931001A1018 /* B2DPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27840F128DBF7300336BDE /* B2DPlugin.c */; }; 0AE6D1171531C935001A1018 /* BitBltPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278411128DBF7300336BDE /* BitBltPlugin.c */; }; 0AE6D1181531C938001A1018 /* FloatArrayPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278413128DBF7300336BDE /* FloatArrayPlugin.c */; }; 0AE6D1191531C93C001A1018 /* LargeIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278415128DBF7300336BDE /* LargeIntegers.c */; }; 0AE6D11A1531C941001A1018 /* Matrix2x3Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278417128DBF7300336BDE /* Matrix2x3Plugin.c */; }; 0AE6D11B1531C944001A1018 /* MiscPrimitivePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278419128DBF7300336BDE /* MiscPrimitivePlugin.c */; }; 0AE6D11C1531C949001A1018 /* SoundPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27841D128DBF7300336BDE /* SoundPlugin.c */; }; 0AE6D11D1531C95E001A1018 /* sqUnixCustomSound.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27843D128DBF7300336BDE /* sqUnixCustomSound.c */; }; 0AE6D11E1531C962001A1018 /* sqUnixSoundMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A4D825C135C526F00CD74D8 /* sqUnixSoundMacOSX.c */; }; 0AE6D11F1531C980001A1018 /* osx_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784C9128DBF7400336BDE /* osx_os_interface.cpp */; }; 0AE6D1201531C98F001A1018 /* posix_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2784CB128DBF7400336BDE /* posix_os_interface.cpp */; }; 0AEC1186128DF0A000EFF6D1 /* debug_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AEC1185128DF0A000EFF6D1 /* debug_helper.cpp */; }; 0AEDCC6315E3CB2B0022DD44 /* sqUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AEDCC6215E3CB2B0022DD44 /* sqUnixFile.c */; }; 0AEDCC6415E3CB2B0022DD44 /* sqUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AEDCC6215E3CB2B0022DD44 /* sqUnixFile.c */; }; 34221D6D13D4D3C50057DCBD /* externals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A2783F6128DBF7300336BDE /* externals.cpp */; }; 34221D6E13D4D3D10057DCBD /* abstract_mark_sweep_collector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278444128DBF7300336BDE /* abstract_mark_sweep_collector.cpp */; }; 34221D6F13D4D3F50057DCBD /* abstract_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278446128DBF7300336BDE /* abstract_object_heap.cpp */; }; 34221D7013D4D3F50057DCBD /* memory_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27844D128DBF7300336BDE /* memory_system.cpp */; }; 34221D7113D4D3F50057DCBD /* multicore_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278450128DBF7300336BDE /* multicore_object_heap.cpp */; }; 34221D7213D4D3F50057DCBD /* multicore_object_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278453128DBF7300336BDE /* multicore_object_table.cpp */; }; 34221D7413D4D3F50057DCBD /* squeak_image_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278460128DBF7300336BDE /* squeak_image_reader.cpp */; }; 34221D7513D4D3F50057DCBD /* at_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278464128DBF7300336BDE /* at_cache.cpp */; }; 34221D7613D4D3F50057DCBD /* interpreter_bytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278467128DBF7300336BDE /* interpreter_bytecodes.cpp */; }; 34221D7713D4D3F50057DCBD /* interpreter_primitives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278469128DBF7300336BDE /* interpreter_primitives.cpp */; }; 34221D7813D4D3F50057DCBD /* method_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846B128DBF7300336BDE /* method_cache.cpp */; }; 34221D7913D4D3F50057DCBD /* obsolete_indexed_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846D128DBF7300336BDE /* obsolete_indexed_primitive_table.cpp */; }; 34221D7A13D4D3F50057DCBD /* obsolete_named_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27846F128DBF7300336BDE /* obsolete_named_primitive_table.cpp */; }; 34221D7B13D4D3F50057DCBD /* primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278471128DBF7300336BDE /* primitive_table.cpp */; }; 34221D7C13D4D3F50057DCBD /* squeak_interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278473128DBF7400336BDE /* squeak_interpreter.cpp */; }; 34221D7D13D4D3F50057DCBD /* abstract_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847B128DBF7400336BDE /* abstract_message.cpp */; }; 34221D7E13D4D3F50057DCBD /* deferred_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847D128DBF7400336BDE /* deferred_request.cpp */; }; 34221D7F13D4D3F50057DCBD /* interactions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27847F128DBF7400336BDE /* interactions.cpp */; }; 34221D8013D4D3F50057DCBD /* interpreter_subset_for_control_transfer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278481128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp */; }; 34221D8113D4D3F50057DCBD /* message_classes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278483128DBF7400336BDE /* message_classes.cpp */; }; 34221D8213D4D3F50057DCBD /* message_or_ack_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278485128DBF7400336BDE /* message_or_ack_request.cpp */; }; 34221D8313D4D3F50057DCBD /* message_statics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278487128DBF7400336BDE /* message_statics.cpp */; }; 34221D8413D4D3F50057DCBD /* message_stats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A278489128DBF7400336BDE /* message_stats.cpp */; }; 34221D8513D4D3F50057DCBD /* receive_marker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A27848C128DBF7400336BDE /* receive_marker.cpp */; }; 34221DBF13D4D9650057DCBD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A2785E3128DC3A000336BDE /* CoreFoundation.framework */; }; 34221DC013D4D9670057DCBD /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A2785ED128DC42800336BDE /* CoreServices.framework */; }; 34221DC113D4D96B0057DCBD /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A8C91C612DE62B6007DBAD9 /* IOKit.framework */; }; 34221DC213D4D98B0057DCBD /* aio.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278426128DBF7300336BDE /* aio.c */; }; 34221DC313D4D9B70057DCBD /* sqUnixSound.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7C98135CC84700D13E53 /* sqUnixSound.c */; }; 34221DC413D4D9D00057DCBD /* sqUnixSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7C9B135CC86800D13E53 /* sqUnixSocket.c */; }; 34221DC513D4D9DC0057DCBD /* SocketPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A27841B128DBF7300336BDE /* SocketPlugin.c */; }; 34221DC613D4D9F10057DCBD /* sqUnixSoundNull.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A278442128DBF7300336BDE /* sqUnixSoundNull.c */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0A2783EB128DBF1000336BDE /* RoarVM */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = RoarVM; sourceTree = BUILT_PRODUCTS_DIR; }; 0A2783F6128DBF7300336BDE /* externals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = externals.cpp; sourceTree = ""; }; 0A2783F7128DBF7300336BDE /* externals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = externals.h; sourceTree = ""; }; 0A2783FC128DBF7300336BDE /* B3DAcceleratorPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = B3DAcceleratorPlugin.h; sourceTree = ""; }; 0A2783FD128DBF7300336BDE /* sqOpenGLRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqOpenGLRenderer.h; sourceTree = ""; }; 0A278400128DBF7300336BDE /* FilePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FilePlugin.c; sourceTree = ""; }; 0A278401128DBF7300336BDE /* FilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePlugin.h; sourceTree = ""; }; 0A278402128DBF7300336BDE /* sqFilePluginBasicPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqFilePluginBasicPrims.c; sourceTree = ""; }; 0A278405128DBF7300336BDE /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; 0A278408128DBF7300336BDE /* SocketPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketPlugin.h; sourceTree = ""; }; 0A27840C128DBF7300336BDE /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqVirtualMachine.h; sourceTree = ""; }; 0A27840F128DBF7300336BDE /* B2DPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = B2DPlugin.c; sourceTree = ""; }; 0A278411128DBF7300336BDE /* BitBltPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BitBltPlugin.c; sourceTree = ""; }; 0A278413128DBF7300336BDE /* FloatArrayPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FloatArrayPlugin.c; sourceTree = ""; }; 0A278415128DBF7300336BDE /* LargeIntegers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LargeIntegers.c; sourceTree = ""; }; 0A278417128DBF7300336BDE /* Matrix2x3Plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Matrix2x3Plugin.c; sourceTree = ""; }; 0A278419128DBF7300336BDE /* MiscPrimitivePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MiscPrimitivePlugin.c; sourceTree = ""; }; 0A27841B128DBF7300336BDE /* SocketPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SocketPlugin.c; sourceTree = ""; }; 0A27841D128DBF7300336BDE /* SoundPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundPlugin.c; sourceTree = ""; }; 0A278421128DBF7300336BDE /* UnixOSProcessPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UnixOSProcessPlugin.c; sourceTree = ""; }; 0A278426128DBF7300336BDE /* aio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aio.c; sourceTree = ""; }; 0A278427128DBF7300336BDE /* dlfcn-dyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "dlfcn-dyld.c"; sourceTree = ""; }; 0A278428128DBF7300336BDE /* interp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interp.h; sourceTree = ""; }; 0A27842A128DBF7300336BDE /* sqaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqaio.h; sourceTree = ""; }; 0A27842B128DBF7300336BDE /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqConfig.h; sourceTree = ""; }; 0A27842C128DBF7300336BDE /* SqDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqDisplay.h; sourceTree = ""; }; 0A27842E128DBF7300336BDE /* SqModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqModule.h; sourceTree = ""; }; 0A27842F128DBF7300336BDE /* sqNamedPrims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqNamedPrims.h; sourceTree = ""; }; 0A278430128DBF7300336BDE /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqPlatformSpecific.h; sourceTree = ""; }; 0A278434128DBF7300336BDE /* SqSound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqSound.h; sourceTree = ""; }; 0A278435128DBF7300336BDE /* sqUnixCharConv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqUnixCharConv.h; sourceTree = ""; }; 0A278436128DBF7300336BDE /* sqUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixEvent.c; sourceTree = ""; }; 0A278437128DBF7300336BDE /* sqUnixGlobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqUnixGlobals.h; sourceTree = ""; }; 0A278438128DBF7300336BDE /* sqUnixMain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqUnixMain.h; sourceTree = ""; }; 0A27843B128DBF7300336BDE /* sqUnixXdnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixXdnd.c; sourceTree = ""; }; 0A27843D128DBF7300336BDE /* sqUnixCustomSound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixCustomSound.c; sourceTree = ""; }; 0A278440128DBF7300336BDE /* sqUnixSoundDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqUnixSoundDebug.h; sourceTree = ""; }; 0A278442128DBF7300336BDE /* sqUnixSoundNull.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixSoundNull.c; sourceTree = ""; }; 0A278444128DBF7300336BDE /* abstract_mark_sweep_collector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_mark_sweep_collector.cpp; sourceTree = ""; }; 0A278445128DBF7300336BDE /* abstract_mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_mark_sweep_collector.h; sourceTree = ""; }; 0A278446128DBF7300336BDE /* abstract_object_heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_object_heap.cpp; sourceTree = ""; }; 0A278447128DBF7300336BDE /* abstract_object_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_heap.h; sourceTree = ""; }; 0A278448128DBF7300336BDE /* abstract_object_heap.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_heap.inline.h; sourceTree = ""; }; 0A278449128DBF7300336BDE /* abstract_object_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_table.h; sourceTree = ""; }; 0A27844A128DBF7300336BDE /* gc_oop_stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gc_oop_stack.h; sourceTree = ""; }; 0A27844B128DBF7300336BDE /* indirect_oop_mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indirect_oop_mark_sweep_collector.h; sourceTree = ""; }; 0A27844C128DBF7300336BDE /* mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mark_sweep_collector.h; sourceTree = ""; }; 0A27844D128DBF7300336BDE /* memory_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_system.cpp; sourceTree = ""; }; 0A27844E128DBF7300336BDE /* memory_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_system.h; sourceTree = ""; }; 0A27844F128DBF7300336BDE /* memory_system.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_system.inline.h; sourceTree = ""; }; 0A278450128DBF7300336BDE /* multicore_object_heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multicore_object_heap.cpp; sourceTree = ""; }; 0A278451128DBF7300336BDE /* multicore_object_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_heap.h; sourceTree = ""; }; 0A278452128DBF7300336BDE /* multicore_object_heap.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_heap.inline.h; sourceTree = ""; }; 0A278453128DBF7300336BDE /* multicore_object_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multicore_object_table.cpp; sourceTree = ""; }; 0A278454128DBF7300336BDE /* multicore_object_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_table.h; sourceTree = ""; }; 0A278455128DBF7300336BDE /* multicore_object_table.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_table.inline.h; sourceTree = ""; }; 0A278456128DBF7300336BDE /* oop_closure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop_closure.h; sourceTree = ""; }; 0A278460128DBF7300336BDE /* squeak_image_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_image_reader.cpp; sourceTree = ""; }; 0A278461128DBF7300336BDE /* squeak_image_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_image_reader.h; sourceTree = ""; }; 0A278463128DBF7300336BDE /* abstract_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_primitive_table.h; sourceTree = ""; }; 0A278464128DBF7300336BDE /* at_cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = at_cache.cpp; sourceTree = ""; }; 0A278465128DBF7300336BDE /* at_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at_cache.h; sourceTree = ""; }; 0A278466128DBF7300336BDE /* external_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = external_primitive_table.h; sourceTree = ""; }; 0A278467128DBF7300336BDE /* interpreter_bytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_bytecodes.cpp; sourceTree = ""; }; 0A278468128DBF7300336BDE /* interpreter_bytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_bytecodes.h; sourceTree = ""; }; 0A278469128DBF7300336BDE /* interpreter_primitives.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_primitives.cpp; sourceTree = ""; }; 0A27846A128DBF7300336BDE /* interpreter_primitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_primitives.h; sourceTree = ""; }; 0A27846B128DBF7300336BDE /* method_cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = method_cache.cpp; sourceTree = ""; }; 0A27846C128DBF7300336BDE /* method_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = method_cache.h; sourceTree = ""; }; 0A27846D128DBF7300336BDE /* obsolete_indexed_primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = obsolete_indexed_primitive_table.cpp; sourceTree = ""; }; 0A27846E128DBF7300336BDE /* obsolete_indexed_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = obsolete_indexed_primitive_table.h; sourceTree = ""; }; 0A27846F128DBF7300336BDE /* obsolete_named_primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = obsolete_named_primitive_table.cpp; sourceTree = ""; }; 0A278470128DBF7300336BDE /* obsolete_named_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = obsolete_named_primitive_table.h; sourceTree = ""; }; 0A278471128DBF7300336BDE /* primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = primitive_table.cpp; sourceTree = ""; }; 0A278472128DBF7400336BDE /* primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = primitive_table.h; sourceTree = ""; }; 0A278473128DBF7400336BDE /* squeak_interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_interpreter.cpp; sourceTree = ""; }; 0A278474128DBF7400336BDE /* squeak_interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_interpreter.h; sourceTree = ""; }; 0A278476128DBF7400336BDE /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; 0A278477128DBF7400336BDE /* Makefile.common */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; indentWidth = 4; path = Makefile.common; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; 0A278478128DBF7400336BDE /* Makefile.debug */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; indentWidth = 4; path = Makefile.debug; sourceTree = ""; tabWidth = 4; }; 0A278479128DBF7400336BDE /* Makefile.opt */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; indentWidth = 4; path = Makefile.opt; sourceTree = ""; tabWidth = 4; }; 0A27847B128DBF7400336BDE /* abstract_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_message.cpp; sourceTree = ""; }; 0A27847C128DBF7400336BDE /* abstract_message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_message.h; sourceTree = ""; }; 0A27847D128DBF7400336BDE /* deferred_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deferred_request.cpp; sourceTree = ""; }; 0A27847E128DBF7400336BDE /* deferred_request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deferred_request.h; sourceTree = ""; }; 0A27847F128DBF7400336BDE /* interactions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interactions.cpp; sourceTree = ""; }; 0A278480128DBF7400336BDE /* interactions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interactions.h; sourceTree = ""; }; 0A278481128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_subset_for_control_transfer.cpp; sourceTree = ""; }; 0A278482128DBF7400336BDE /* interpreter_subset_for_control_transfer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_subset_for_control_transfer.h; sourceTree = ""; }; 0A278483128DBF7400336BDE /* message_classes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_classes.cpp; sourceTree = ""; }; 0A278484128DBF7400336BDE /* message_classes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_classes.h; sourceTree = ""; }; 0A278485128DBF7400336BDE /* message_or_ack_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_or_ack_request.cpp; sourceTree = ""; }; 0A278486128DBF7400336BDE /* message_or_ack_request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_or_ack_request.h; sourceTree = ""; }; 0A278487128DBF7400336BDE /* message_statics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_statics.cpp; sourceTree = ""; }; 0A278488128DBF7400336BDE /* message_statics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_statics.h; sourceTree = ""; }; 0A278489128DBF7400336BDE /* message_stats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_stats.cpp; sourceTree = ""; }; 0A27848A128DBF7400336BDE /* message_stats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_stats.h; sourceTree = ""; }; 0A27848B128DBF7400336BDE /* message_templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_templates.h; sourceTree = ""; }; 0A27848C128DBF7400336BDE /* receive_marker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = receive_marker.cpp; sourceTree = ""; }; 0A27848D128DBF7400336BDE /* receive_marker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = receive_marker.h; sourceTree = ""; }; 0A27848F128DBF7400336BDE /* abstract_zero_copy_command_queue_endpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_zero_copy_command_queue_endpoint.cpp; sourceTree = ""; }; 0A278490128DBF7400336BDE /* abstract_zero_copy_command_queue_endpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_zero_copy_command_queue_endpoint.h; sourceTree = ""; }; 0A278491128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.cpp; sourceTree = ""; }; 0A278492128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.h; sourceTree = ""; }; 0A278493128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_receiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_direct_to_hypervisor_zero_copy_receiver.cpp; sourceTree = ""; }; 0A278494128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_receiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_direct_to_hypervisor_zero_copy_receiver.h; sourceTree = ""; }; 0A278495128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_sender.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_direct_to_hypervisor_zero_copy_sender.cpp; sourceTree = ""; }; 0A278496128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_direct_to_hypervisor_zero_copy_sender.h; sourceTree = ""; }; 0A278497128DBF7400336BDE /* chip_to_chip_zero_copy_command_queue_endpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_zero_copy_command_queue_endpoint.cpp; sourceTree = ""; }; 0A278498128DBF7400336BDE /* chip_to_chip_zero_copy_command_queue_endpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_zero_copy_command_queue_endpoint.h; sourceTree = ""; }; 0A278499128DBF7400336BDE /* chip_to_chip_zero_copy_command_receiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_zero_copy_command_receiver.cpp; sourceTree = ""; }; 0A27849A128DBF7400336BDE /* chip_to_chip_zero_copy_command_receiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_zero_copy_command_receiver.h; sourceTree = ""; }; 0A27849B128DBF7400336BDE /* chip_to_chip_zero_copy_command_sender.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chip_to_chip_zero_copy_command_sender.cpp; sourceTree = ""; }; 0A27849C128DBF7400336BDE /* chip_to_chip_zero_copy_command_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chip_to_chip_zero_copy_command_sender.h; sourceTree = ""; }; 0A27849D128DBF7400336BDE /* host_pci_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = host_pci_info.cpp; sourceTree = ""; }; 0A27849E128DBF7400336BDE /* host_pci_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = host_pci_info.h; sourceTree = ""; }; 0A27849F128DBF7400336BDE /* tilera_chip_to_chip_message_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tilera_chip_to_chip_message_queue.cpp; sourceTree = ""; }; 0A2784A0128DBF7400336BDE /* tilera_chip_to_chip_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tilera_chip_to_chip_message_queue.h; sourceTree = ""; }; 0A2784A2128DBF7400336BDE /* chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chunk.h; sourceTree = ""; }; 0A2784A3128DBF7400336BDE /* chunk.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chunk.inline.h; sourceTree = ""; }; 0A2784A4128DBF7400336BDE /* header_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = header_type.cpp; sourceTree = ""; }; 0A2784A5128DBF7400336BDE /* header_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = header_type.h; sourceTree = ""; }; 0A2784A6128DBF7400336BDE /* object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = object.cpp; sourceTree = ""; }; 0A2784A7128DBF7400336BDE /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.h; sourceTree = ""; }; 0A2784A8128DBF7400336BDE /* object.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.inline.h; sourceTree = ""; }; 0A2784A9128DBF7400336BDE /* object_indices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object_indices.h; sourceTree = ""; }; 0A2784AA128DBF7400336BDE /* preheader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preheader.h; sourceTree = ""; }; 0A2784AB128DBF7400336BDE /* process_field_locator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = process_field_locator.cpp; sourceTree = ""; }; 0A2784AC128DBF7400336BDE /* process_field_locator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process_field_locator.h; sourceTree = ""; }; 0A2784AD128DBF7400336BDE /* roots.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = roots.cpp; sourceTree = ""; }; 0A2784AE128DBF7400336BDE /* roots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = roots.h; sourceTree = ""; }; 0A2784AF128DBF7400336BDE /* special_indices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = special_indices.h; sourceTree = ""; }; 0A2784B0128DBF7400336BDE /* word_containing_object_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = word_containing_object_type.h; sourceTree = ""; }; 0A2784B2128DBF7400336BDE /* abstract_oop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_oop.h; sourceTree = ""; }; 0A2784B3128DBF7400336BDE /* oop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oop.cpp; sourceTree = ""; }; 0A2784B4128DBF7400336BDE /* oop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop.h; sourceTree = ""; }; 0A2784B5128DBF7400336BDE /* oop.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop.inline.h; sourceTree = ""; }; 0A2784B6128DBF7400336BDE /* tags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tags.h; sourceTree = ""; }; 0A2784B8128DBF7400336BDE /* abstract_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_cpu_coordinate.h; sourceTree = ""; }; 0A2784B9128DBF7400336BDE /* abstract_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_memory_semantics.h; sourceTree = ""; }; 0A2784BA128DBF7400336BDE /* abstract_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_message_queue.h; sourceTree = ""; }; 0A2784BB128DBF7400336BDE /* abstract_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_os_interface.cpp; sourceTree = ""; }; 0A2784BC128DBF7400336BDE /* abstract_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_os_interface.h; sourceTree = ""; }; 0A2784BD128DBF7400336BDE /* cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_coordinate.h; sourceTree = ""; }; 0A2784BE128DBF7400336BDE /* dummy_cpu_coordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dummy_cpu_coordinate.cpp; sourceTree = ""; }; 0A2784BF128DBF7400336BDE /* dummy_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummy_cpu_coordinate.h; sourceTree = ""; }; 0A2784C0128DBF7400336BDE /* ilib_message_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ilib_message_queue.cpp; sourceTree = ""; }; 0A2784C1128DBF7400336BDE /* ilib_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ilib_message_queue.h; sourceTree = ""; }; 0A2784C2128DBF7400336BDE /* ilib_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ilib_os_interface.cpp; sourceTree = ""; }; 0A2784C3128DBF7400336BDE /* ilib_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ilib_os_interface.h; sourceTree = ""; }; 0A2784C4128DBF7400336BDE /* logical_core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logical_core.cpp; sourceTree = ""; }; 0A2784C5128DBF7400336BDE /* logical_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logical_core.h; sourceTree = ""; }; 0A2784C6128DBF7400336BDE /* memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_semantics.h; sourceTree = ""; }; 0A2784C7128DBF7400336BDE /* message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_queue.h; sourceTree = ""; }; 0A2784C8128DBF7400336BDE /* os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_interface.h; sourceTree = ""; }; 0A2784C9128DBF7400336BDE /* osx_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osx_os_interface.cpp; sourceTree = ""; }; 0A2784CA128DBF7400336BDE /* osx_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osx_os_interface.h; sourceTree = ""; }; 0A2784CB128DBF7400336BDE /* posix_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = posix_os_interface.cpp; sourceTree = ""; }; 0A2784CC128DBF7400336BDE /* posix_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = posix_os_interface.h; sourceTree = ""; }; 0A2784CD128DBF7400336BDE /* process_memory_semantics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = process_memory_semantics.cpp; sourceTree = ""; }; 0A2784CE128DBF7400336BDE /* process_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process_memory_semantics.h; sourceTree = ""; }; 0A2784CF128DBF7400336BDE /* shared_memory_message_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_message_queue.cpp; sourceTree = ""; }; 0A2784D0128DBF7400336BDE /* shared_memory_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_memory_message_queue.h; sourceTree = ""; }; 0A2784D1128DBF7400336BDE /* thread_memory_semantics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_memory_semantics.cpp; sourceTree = ""; }; 0A2784D2128DBF7400336BDE /* thread_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread_memory_semantics.h; sourceTree = ""; }; 0A2784D3128DBF7400336BDE /* tile_cpu_coordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tile_cpu_coordinate.cpp; sourceTree = ""; }; 0A2784D4128DBF7400336BDE /* tile_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tile_cpu_coordinate.h; sourceTree = ""; }; 0A2784D6128DBF7400336BDE /* RVMPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RVMPlugin.cpp; sourceTree = ""; }; 0A2784D7128DBF7400336BDE /* RVMPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RVMPlugin.h; sourceTree = ""; }; 0A2784D9128DBF7400336BDE /* abstract_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_mutex.cpp; sourceTree = ""; }; 0A2784DA128DBF7400336BDE /* abstract_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_mutex.h; sourceTree = ""; }; 0A2784DB128DBF7400336BDE /* abstract_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_tracer.cpp; sourceTree = ""; }; 0A2784DC128DBF7400336BDE /* abstract_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_tracer.h; sourceTree = ""; }; 0A2784DD128DBF7400336BDE /* bytemap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bytemap.cpp; sourceTree = ""; }; 0A2784DE128DBF7400336BDE /* bytemap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytemap.h; sourceTree = ""; }; 0A2784DF128DBF7400336BDE /* core_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core_tracer.cpp; sourceTree = ""; }; 0A2784E0128DBF7400336BDE /* core_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core_tracer.h; sourceTree = ""; }; 0A2784E1128DBF7400336BDE /* debug_store_checks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_store_checks.h; sourceTree = ""; }; 0A2784E2128DBF7400336BDE /* gc_debugging_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gc_debugging_tracer.cpp; sourceTree = ""; }; 0A2784E3128DBF7400336BDE /* gc_debugging_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gc_debugging_tracer.h; sourceTree = ""; }; 0A2784E4128DBF7400336BDE /* error_handling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = error_handling.cpp; sourceTree = ""; }; 0A2784E5128DBF7400336BDE /* error_handling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error_handling.h; sourceTree = ""; }; 0A2784E6128DBF7400336BDE /* execution_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = execution_tracer.cpp; sourceTree = ""; }; 0A2784E7128DBF7400336BDE /* execution_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = execution_tracer.h; sourceTree = ""; }; 0A2784E8128DBF7400336BDE /* headers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = headers.h; sourceTree = ""; }; 0A2784E9128DBF7400336BDE /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 0A2784EA128DBF7400336BDE /* measurements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = measurements.cpp; sourceTree = ""; }; 0A2784EB128DBF7400336BDE /* measurements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = measurements.h; sourceTree = ""; }; 0A2784EC128DBF7400336BDE /* my_rank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = my_rank.cpp; sourceTree = ""; }; 0A2784ED128DBF7400336BDE /* my_rank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = my_rank.h; sourceTree = ""; }; 0A2784EE128DBF7400336BDE /* oop_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oop_tracer.cpp; sourceTree = ""; }; 0A2784EF128DBF7400336BDE /* oop_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop_tracer.h; sourceTree = ""; }; 0A2784F0128DBF7400336BDE /* printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = printer.cpp; sourceTree = ""; }; 0A2784F1128DBF7400336BDE /* printer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printer.h; sourceTree = ""; }; 0A2784F2128DBF7400336BDE /* profiling_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profiling_tracer.cpp; sourceTree = ""; }; 0A2784F3128DBF7400336BDE /* profiling_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profiling_tracer.h; sourceTree = ""; }; 0A2784F4128DBF7400336BDE /* rank_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rank_set.cpp; sourceTree = ""; }; 0A2784F5128DBF7400336BDE /* rank_set.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rank_set.h; sourceTree = ""; }; 0A2784F6128DBF7400336BDE /* runtime_tester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime_tester.h; sourceTree = ""; }; 0A2784F7128DBF7400336BDE /* rvm_bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rvm_bitmap.cpp; sourceTree = ""; }; 0A2784F8128DBF7400336BDE /* rvm_bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rvm_bitmap.h; sourceTree = ""; }; 0A2784F9128DBF7400336BDE /* rvm_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rvm_config.cpp; sourceTree = ""; }; 0A2784FA128DBF7400336BDE /* rvm_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rvm_config.h; sourceTree = ""; }; 0A2784FB128DBF7400336BDE /* safepoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint.cpp; sourceTree = ""; }; 0A2784FC128DBF7400336BDE /* safepoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint.h; sourceTree = ""; }; 0A2784FD128DBF7400336BDE /* safepoint_ability.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint_ability.cpp; sourceTree = ""; }; 0A2784FE128DBF7400336BDE /* safepoint_ability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint_ability.h; sourceTree = ""; }; 0A2784FF128DBF7400336BDE /* safepoint_request_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint_request_queue.cpp; sourceTree = ""; }; 0A278500128DBF7400336BDE /* safepoint_request_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint_request_queue.h; sourceTree = ""; }; 0A278501128DBF7400336BDE /* scheduler_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scheduler_mutex.cpp; sourceTree = ""; }; 0A278502128DBF7400336BDE /* scheduler_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scheduler_mutex.h; sourceTree = ""; }; 0A278503128DBF7400336BDE /* semaphore_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = semaphore_mutex.cpp; sourceTree = ""; }; 0A278504128DBF7400336BDE /* semaphore_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = semaphore_mutex.h; sourceTree = ""; }; 0A278505128DBF7400336BDE /* squeak_adapters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_adapters.cpp; sourceTree = ""; }; 0A278506128DBF7400336BDE /* squeak_adapters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_adapters.h; sourceTree = ""; }; 0A278507128DBF7400336BDE /* timeout_deferral.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timeout_deferral.cpp; sourceTree = ""; }; 0A278508128DBF7400336BDE /* timeout_deferral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeout_deferral.h; sourceTree = ""; }; 0A278509128DBF7400336BDE /* timeout_timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timeout_timer.cpp; sourceTree = ""; }; 0A27850A128DBF7400336BDE /* timeout_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeout_timer.h; sourceTree = ""; }; 0A27850B128DBF7400336BDE /* utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cpp; sourceTree = ""; }; 0A27850C128DBF7400336BDE /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; 0A27850F128DBF7400336BDE /* buffered_channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buffered_channel.cpp; sourceTree = ""; }; 0A278510128DBF7400336BDE /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 0A278511128DBF7400336BDE /* starter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = starter.cpp; sourceTree = ""; }; 0A278512128DBF7400336BDE /* starter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = starter.h; sourceTree = ""; }; 0A278513128DBF7400336BDE /* synced_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_queue.cpp; sourceTree = ""; }; 0A278514128DBF7400336BDE /* synced_queue_threaded.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_queue_threaded.cpp; sourceTree = ""; }; 0A278516128DBF7400336BDE /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; 0A2785E3128DC3A000336BDE /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; 0A2785ED128DC42800336BDE /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; 0A3FB13514D99C7E0050F39C /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "googletest/src/gtest-all.cc"; sourceTree = SOURCE_ROOT; }; 0A4D8249135C51D500CD74D8 /* sqNamedPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqNamedPrims.c; sourceTree = ""; }; 0A4D824A135C51D500CD74D8 /* sqVirtualMachine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqVirtualMachine.c; sourceTree = ""; }; 0A4D8250135C523B00CD74D8 /* sqUnixCharConv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixCharConv.c; sourceTree = ""; }; 0A4D8251135C523B00CD74D8 /* sqUnixExternalPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixExternalPrims.c; sourceTree = ""; }; 0A4D8252135C523B00CD74D8 /* sqUnixMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixMain.c; sourceTree = ""; }; 0A4D8259135C526100CD74D8 /* sqUnixX11.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixX11.c; sourceTree = ""; }; 0A4D825C135C526F00CD74D8 /* sqUnixSoundMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixSoundMacOSX.c; sourceTree = ""; }; 0A5124F61372077B001008AC /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = iOS/vm/iPhone/config.h; sourceTree = ""; }; 0A5D7C87135C905800D13E53 /* sq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sq.h; sourceTree = ""; }; 0A5D7C88135C90BC00D13E53 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMemoryAccess.h; sourceTree = ""; }; 0A5D7C94135CA28500D13E53 /* rvm_squeak_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rvm_squeak_config.h; sourceTree = ""; }; 0A5D7C98135CC84700D13E53 /* sqUnixSound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqUnixSound.c; path = plugins/SoundPlugin/sqUnixSound.c; sourceTree = ""; }; 0A5D7C9B135CC86800D13E53 /* sqUnixSocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixSocket.c; sourceTree = ""; }; 0A5D7C9E135CC8D700D13E53 /* sqUnixOpenGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqUnixOpenGL.h; path = plugins/B3DAcceleratorPlugin/sqUnixOpenGL.h; sourceTree = ""; }; 0A5D7CA0135CC9D400D13E53 /* SoundPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundPlugin.h; sourceTree = ""; }; 0A6A4832135ADF0A00933643 /* os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = os_interface.cpp; sourceTree = ""; }; 0A6A4835135AE32D00933643 /* external_primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = external_primitive_table.cpp; sourceTree = ""; }; 0A72A76314432D7C0008E8AC /* tmc_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tmc_os_interface.cpp; sourceTree = ""; }; 0A72A76414432D7C0008E8AC /* tmc_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tmc_os_interface.h; sourceTree = ""; }; 0A87AD871378439000337878 /* performance_counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = performance_counters.h; sourceTree = ""; }; 0A87AD891379573E00337878 /* performance_counters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = performance_counters.cpp; sourceTree = ""; }; 0A8C91BC12DE61BB007DBAD9 /* object_p.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object_p.h; sourceTree = ""; }; 0A8C91C612DE62B6007DBAD9 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; 0A97FB26128FE95A003A1C74 /* UnitTests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = UnitTests; sourceTree = BUILT_PRODUCTS_DIR; }; 0A97FBAE12900336003A1C74 /* tracked_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tracked_ptr.h; sourceTree = ""; }; 0A97FBB412900371003A1C74 /* tracked_ptr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tracked_ptr.cpp; sourceTree = ""; }; 0A97FEE412909C92003A1C74 /* test_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_os_interface.h; sourceTree = ""; }; 0A97FEF112909D58003A1C74 /* tracked_ptr_registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tracked_ptr_registry.h; sourceTree = ""; }; 0ACF551712E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_message_queue_per_sender.cpp; sourceTree = ""; }; 0ACF551812E07E7F0010386A /* shared_memory_message_queue_per_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_memory_message_queue_per_sender.h; sourceTree = ""; }; 0ADA26B912EF5C00009404B0 /* cacheline_alignment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cacheline_alignment.cpp; sourceTree = ""; }; 0ADA271212EF66EC009404B0 /* cacheline_aligned.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cacheline_aligned.h; sourceTree = ""; }; 0AE6D0E11531C596001A1018 /* buffered_channel_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffered_channel_debug.h; sourceTree = ""; }; 0AE6D0E21531C596001A1018 /* buffered_channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buffered_channel.cpp; sourceTree = ""; }; 0AE6D0E31531C596001A1018 /* buffered_channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffered_channel.h; sourceTree = ""; }; 0AE6D0E41531C596001A1018 /* synced_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_queue.cpp; sourceTree = ""; }; 0AE6D0E51531C596001A1018 /* synced_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = synced_queue.h; sourceTree = ""; }; 0AEC1184128DF02F00EFF6D1 /* debug_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_helper.h; sourceTree = ""; }; 0AEC1185128DF0A000EFF6D1 /* debug_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_helper.cpp; sourceTree = ""; }; 0AEDCC6215E3CB2B0022DD44 /* sqUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixFile.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 0A2783E9128DBF1000336BDE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 0A2785E4128DC3A000336BDE /* CoreFoundation.framework in Frameworks */, 0A2785EE128DC42800336BDE /* CoreServices.framework in Frameworks */, 0A8C91C712DE62B6007DBAD9 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 0A97FB24128FE95A003A1C74 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 34221DBF13D4D9650057DCBD /* CoreFoundation.framework in Frameworks */, 34221DC013D4D9670057DCBD /* CoreServices.framework in Frameworks */, 34221DC113D4D96B0057DCBD /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0A278283128DBE2700336BDE = { isa = PBXGroup; children = ( 0A27829C128DBEBB00336BDE /* Source */, 0A2783EC128DBF1000336BDE /* Products */, 0A2785E3128DC3A000336BDE /* CoreFoundation.framework */, 0A2785ED128DC42800336BDE /* CoreServices.framework */, 0A8C91C612DE62B6007DBAD9 /* IOKit.framework */, ); sourceTree = ""; }; 0A27829C128DBEBB00336BDE /* Source */ = { isa = PBXGroup; children = ( 0A2783F5128DBF7300336BDE /* externals */, 0A2783F8128DBF7300336BDE /* from_squeak */, 0A278443128DBF7300336BDE /* heap */, 0A27845F128DBF7300336BDE /* image_readers */, 0A278462128DBF7300336BDE /* interpreter */, 0A278475128DBF7400336BDE /* makefiles */, 0A4A612C14F7917F006748DD /* message_buffers */, 0A27847A128DBF7400336BDE /* messages */, 0A27848E128DBF7400336BDE /* multichip */, 0A2784A1128DBF7400336BDE /* objects */, 0A2784B1128DBF7400336BDE /* oops */, 0A2784B7128DBF7400336BDE /* platform */, 0A2784D5128DBF7400336BDE /* primitives */, 0A2784D8128DBF7400336BDE /* runtime */, 0A27850D128DBF7400336BDE /* tests */, 0A278515128DBF7400336BDE /* types */, ); name = Source; sourceTree = ""; }; 0A2783EC128DBF1000336BDE /* Products */ = { isa = PBXGroup; children = ( 0A2783EB128DBF1000336BDE /* RoarVM */, 0A97FB26128FE95A003A1C74 /* UnitTests */, ); name = Products; sourceTree = ""; }; 0A2783F5128DBF7300336BDE /* externals */ = { isa = PBXGroup; children = ( 0A2783F6128DBF7300336BDE /* externals.cpp */, 0A2783F7128DBF7300336BDE /* externals.h */, ); name = externals; path = src/externals; sourceTree = ""; }; 0A2783F8128DBF7300336BDE /* from_squeak */ = { isa = PBXGroup; children = ( 0A5124F31372072C001008AC /* iOS */, 0A2783F9128DBF7300336BDE /* Cross */, 0A27840D128DBF7300336BDE /* intplugins */, 0A278422128DBF7300336BDE /* unix */, ); name = from_squeak; path = src/from_squeak; sourceTree = ""; }; 0A2783F9128DBF7300336BDE /* Cross */ = { isa = PBXGroup; children = ( 0A2783FA128DBF7300336BDE /* plugins */, 0A278409128DBF7300336BDE /* vm */, ); path = Cross; sourceTree = ""; }; 0A2783FA128DBF7300336BDE /* plugins */ = { isa = PBXGroup; children = ( 0A5D7C9F135CC9D400D13E53 /* SoundPlugin */, 0A2783FB128DBF7300336BDE /* B3DAcceleratorPlugin */, 0A2783FF128DBF7300336BDE /* FilePlugin */, 0A278404128DBF7300336BDE /* RePlugin */, 0A278407128DBF7300336BDE /* SocketPlugin */, ); path = plugins; sourceTree = ""; }; 0A2783FB128DBF7300336BDE /* B3DAcceleratorPlugin */ = { isa = PBXGroup; children = ( 0A2783FC128DBF7300336BDE /* B3DAcceleratorPlugin.h */, 0A2783FD128DBF7300336BDE /* sqOpenGLRenderer.h */, ); path = B3DAcceleratorPlugin; sourceTree = ""; }; 0A2783FF128DBF7300336BDE /* FilePlugin */ = { isa = PBXGroup; children = ( 0A278400128DBF7300336BDE /* FilePlugin.c */, 0A278401128DBF7300336BDE /* FilePlugin.h */, 0A278402128DBF7300336BDE /* sqFilePluginBasicPrims.c */, ); path = FilePlugin; sourceTree = ""; }; 0A278404128DBF7300336BDE /* RePlugin */ = { isa = PBXGroup; children = ( 0A278405128DBF7300336BDE /* config.h */, ); path = RePlugin; sourceTree = ""; }; 0A278407128DBF7300336BDE /* SocketPlugin */ = { isa = PBXGroup; children = ( 0A278408128DBF7300336BDE /* SocketPlugin.h */, ); path = SocketPlugin; sourceTree = ""; }; 0A278409128DBF7300336BDE /* vm */ = { isa = PBXGroup; children = ( 0A5D7C87135C905800D13E53 /* sq.h */, 0A5D7C88135C90BC00D13E53 /* sqMemoryAccess.h */, 0A4D8249135C51D500CD74D8 /* sqNamedPrims.c */, 0A4D824A135C51D500CD74D8 /* sqVirtualMachine.c */, 0A27840C128DBF7300336BDE /* sqVirtualMachine.h */, ); path = vm; sourceTree = ""; }; 0A27840D128DBF7300336BDE /* intplugins */ = { isa = PBXGroup; children = ( 0A27840E128DBF7300336BDE /* B2DPlugin */, 0A278410128DBF7300336BDE /* BitBltPlugin */, 0A278412128DBF7300336BDE /* FloatArrayPlugin */, 0A278414128DBF7300336BDE /* LargeIntegers */, 0A278416128DBF7300336BDE /* Matrix2x3Plugin */, 0A278418128DBF7300336BDE /* MiscPrimitivePlugin */, 0A27841A128DBF7300336BDE /* SocketPlugin */, 0A27841C128DBF7300336BDE /* SoundPlugin */, 0A278420128DBF7300336BDE /* UnixOSProcessPlugin */, ); path = intplugins; sourceTree = ""; }; 0A27840E128DBF7300336BDE /* B2DPlugin */ = { isa = PBXGroup; children = ( 0A27840F128DBF7300336BDE /* B2DPlugin.c */, ); path = B2DPlugin; sourceTree = ""; }; 0A278410128DBF7300336BDE /* BitBltPlugin */ = { isa = PBXGroup; children = ( 0A278411128DBF7300336BDE /* BitBltPlugin.c */, ); path = BitBltPlugin; sourceTree = ""; }; 0A278412128DBF7300336BDE /* FloatArrayPlugin */ = { isa = PBXGroup; children = ( 0A278413128DBF7300336BDE /* FloatArrayPlugin.c */, ); path = FloatArrayPlugin; sourceTree = ""; }; 0A278414128DBF7300336BDE /* LargeIntegers */ = { isa = PBXGroup; children = ( 0A278415128DBF7300336BDE /* LargeIntegers.c */, ); path = LargeIntegers; sourceTree = ""; }; 0A278416128DBF7300336BDE /* Matrix2x3Plugin */ = { isa = PBXGroup; children = ( 0A278417128DBF7300336BDE /* Matrix2x3Plugin.c */, ); path = Matrix2x3Plugin; sourceTree = ""; }; 0A278418128DBF7300336BDE /* MiscPrimitivePlugin */ = { isa = PBXGroup; children = ( 0A278419128DBF7300336BDE /* MiscPrimitivePlugin.c */, ); path = MiscPrimitivePlugin; sourceTree = ""; }; 0A27841A128DBF7300336BDE /* SocketPlugin */ = { isa = PBXGroup; children = ( 0A27841B128DBF7300336BDE /* SocketPlugin.c */, ); path = SocketPlugin; sourceTree = ""; }; 0A27841C128DBF7300336BDE /* SoundPlugin */ = { isa = PBXGroup; children = ( 0A27841D128DBF7300336BDE /* SoundPlugin.c */, ); path = SoundPlugin; sourceTree = ""; }; 0A278420128DBF7300336BDE /* UnixOSProcessPlugin */ = { isa = PBXGroup; children = ( 0A278421128DBF7300336BDE /* UnixOSProcessPlugin.c */, ); path = UnixOSProcessPlugin; sourceTree = ""; }; 0A278422128DBF7300336BDE /* unix */ = { isa = PBXGroup; children = ( 0A5D7C96135CC81F00D13E53 /* plugins */, 0A278425128DBF7300336BDE /* vm */, 0A278439128DBF7300336BDE /* vm-display-X11 */, 0A27843C128DBF7300336BDE /* vm-sound-custom */, 0A27843E128DBF7300336BDE /* vm-sound-MacOSX */, 0A278441128DBF7300336BDE /* vm-sound-null */, ); path = unix; sourceTree = ""; }; 0A278425128DBF7300336BDE /* vm */ = { isa = PBXGroup; children = ( 0A278426128DBF7300336BDE /* aio.c */, 0A278427128DBF7300336BDE /* dlfcn-dyld.c */, 0A278428128DBF7300336BDE /* interp.h */, 0A27842A128DBF7300336BDE /* sqaio.h */, 0A27842B128DBF7300336BDE /* sqConfig.h */, 0A27842C128DBF7300336BDE /* SqDisplay.h */, 0A27842E128DBF7300336BDE /* SqModule.h */, 0A27842F128DBF7300336BDE /* sqNamedPrims.h */, 0A278430128DBF7300336BDE /* sqPlatformSpecific.h */, 0A4D8250135C523B00CD74D8 /* sqUnixCharConv.c */, 0A4D8251135C523B00CD74D8 /* sqUnixExternalPrims.c */, 0A4D8252135C523B00CD74D8 /* sqUnixMain.c */, 0A278434128DBF7300336BDE /* SqSound.h */, 0A278435128DBF7300336BDE /* sqUnixCharConv.h */, 0A278436128DBF7300336BDE /* sqUnixEvent.c */, 0A278437128DBF7300336BDE /* sqUnixGlobals.h */, 0A278438128DBF7300336BDE /* sqUnixMain.h */, ); path = vm; sourceTree = ""; }; 0A278439128DBF7300336BDE /* vm-display-X11 */ = { isa = PBXGroup; children = ( 0A4D8259135C526100CD74D8 /* sqUnixX11.c */, 0A27843B128DBF7300336BDE /* sqUnixXdnd.c */, ); path = "vm-display-X11"; sourceTree = ""; }; 0A27843C128DBF7300336BDE /* vm-sound-custom */ = { isa = PBXGroup; children = ( 0A27843D128DBF7300336BDE /* sqUnixCustomSound.c */, ); path = "vm-sound-custom"; sourceTree = ""; }; 0A27843E128DBF7300336BDE /* vm-sound-MacOSX */ = { isa = PBXGroup; children = ( 0A4D825C135C526F00CD74D8 /* sqUnixSoundMacOSX.c */, 0A278440128DBF7300336BDE /* sqUnixSoundDebug.h */, ); path = "vm-sound-MacOSX"; sourceTree = ""; }; 0A278441128DBF7300336BDE /* vm-sound-null */ = { isa = PBXGroup; children = ( 0A278442128DBF7300336BDE /* sqUnixSoundNull.c */, ); path = "vm-sound-null"; sourceTree = ""; }; 0A278443128DBF7300336BDE /* heap */ = { isa = PBXGroup; children = ( 0A278444128DBF7300336BDE /* abstract_mark_sweep_collector.cpp */, 0A278445128DBF7300336BDE /* abstract_mark_sweep_collector.h */, 0A278446128DBF7300336BDE /* abstract_object_heap.cpp */, 0A278447128DBF7300336BDE /* abstract_object_heap.h */, 0A278448128DBF7300336BDE /* abstract_object_heap.inline.h */, 0A278449128DBF7300336BDE /* abstract_object_table.h */, 0A27844A128DBF7300336BDE /* gc_oop_stack.h */, 0A27844B128DBF7300336BDE /* indirect_oop_mark_sweep_collector.h */, 0A27844C128DBF7300336BDE /* mark_sweep_collector.h */, 0A27844D128DBF7300336BDE /* memory_system.cpp */, 0A27844E128DBF7300336BDE /* memory_system.h */, 0A27844F128DBF7300336BDE /* memory_system.inline.h */, 0A278450128DBF7300336BDE /* multicore_object_heap.cpp */, 0A278451128DBF7300336BDE /* multicore_object_heap.h */, 0A278452128DBF7300336BDE /* multicore_object_heap.inline.h */, 0A278453128DBF7300336BDE /* multicore_object_table.cpp */, 0A278454128DBF7300336BDE /* multicore_object_table.h */, 0A278455128DBF7300336BDE /* multicore_object_table.inline.h */, 0A278456128DBF7300336BDE /* oop_closure.h */, ); name = heap; path = src/heap; sourceTree = ""; }; 0A27845F128DBF7300336BDE /* image_readers */ = { isa = PBXGroup; children = ( 0A278460128DBF7300336BDE /* squeak_image_reader.cpp */, 0A278461128DBF7300336BDE /* squeak_image_reader.h */, ); name = image_readers; path = src/image_readers; sourceTree = ""; }; 0A278462128DBF7300336BDE /* interpreter */ = { isa = PBXGroup; children = ( 0A278463128DBF7300336BDE /* abstract_primitive_table.h */, 0A278464128DBF7300336BDE /* at_cache.cpp */, 0A278465128DBF7300336BDE /* at_cache.h */, 0A278466128DBF7300336BDE /* external_primitive_table.h */, 0A278467128DBF7300336BDE /* interpreter_bytecodes.cpp */, 0A278468128DBF7300336BDE /* interpreter_bytecodes.h */, 0A278469128DBF7300336BDE /* interpreter_primitives.cpp */, 0A27846A128DBF7300336BDE /* interpreter_primitives.h */, 0A27846B128DBF7300336BDE /* method_cache.cpp */, 0A27846C128DBF7300336BDE /* method_cache.h */, 0A27846D128DBF7300336BDE /* obsolete_indexed_primitive_table.cpp */, 0A27846E128DBF7300336BDE /* obsolete_indexed_primitive_table.h */, 0A27846F128DBF7300336BDE /* obsolete_named_primitive_table.cpp */, 0A278470128DBF7300336BDE /* obsolete_named_primitive_table.h */, 0A278471128DBF7300336BDE /* primitive_table.cpp */, 0A278472128DBF7400336BDE /* primitive_table.h */, 0A278473128DBF7400336BDE /* squeak_interpreter.cpp */, 0A278474128DBF7400336BDE /* squeak_interpreter.h */, ); name = interpreter; path = src/interpreter; sourceTree = ""; }; 0A278475128DBF7400336BDE /* makefiles */ = { isa = PBXGroup; children = ( 0A278476128DBF7400336BDE /* configure */, 0A278477128DBF7400336BDE /* Makefile.common */, 0A278478128DBF7400336BDE /* Makefile.debug */, 0A278479128DBF7400336BDE /* Makefile.opt */, ); name = makefiles; path = src/makefiles; sourceTree = ""; }; 0A27847A128DBF7400336BDE /* messages */ = { isa = PBXGroup; children = ( 0A27847B128DBF7400336BDE /* abstract_message.cpp */, 0A27847C128DBF7400336BDE /* abstract_message.h */, 0A27847D128DBF7400336BDE /* deferred_request.cpp */, 0A27847E128DBF7400336BDE /* deferred_request.h */, 0A27847F128DBF7400336BDE /* interactions.cpp */, 0A278480128DBF7400336BDE /* interactions.h */, 0A278481128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp */, 0A278482128DBF7400336BDE /* interpreter_subset_for_control_transfer.h */, 0A278483128DBF7400336BDE /* message_classes.cpp */, 0A278484128DBF7400336BDE /* message_classes.h */, 0A278485128DBF7400336BDE /* message_or_ack_request.cpp */, 0A278486128DBF7400336BDE /* message_or_ack_request.h */, 0A278487128DBF7400336BDE /* message_statics.cpp */, 0A278488128DBF7400336BDE /* message_statics.h */, 0A278489128DBF7400336BDE /* message_stats.cpp */, 0A27848A128DBF7400336BDE /* message_stats.h */, 0A27848B128DBF7400336BDE /* message_templates.h */, 0A27848C128DBF7400336BDE /* receive_marker.cpp */, 0A27848D128DBF7400336BDE /* receive_marker.h */, ); name = messages; path = src/messages; sourceTree = ""; }; 0A27848E128DBF7400336BDE /* multichip */ = { isa = PBXGroup; children = ( 0A27848F128DBF7400336BDE /* abstract_zero_copy_command_queue_endpoint.cpp */, 0A278490128DBF7400336BDE /* abstract_zero_copy_command_queue_endpoint.h */, 0A278491128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.cpp */, 0A278492128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_endpoint.h */, 0A278493128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_receiver.cpp */, 0A278494128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_receiver.h */, 0A278495128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_sender.cpp */, 0A278496128DBF7400336BDE /* chip_to_chip_direct_to_hypervisor_zero_copy_sender.h */, 0A278497128DBF7400336BDE /* chip_to_chip_zero_copy_command_queue_endpoint.cpp */, 0A278498128DBF7400336BDE /* chip_to_chip_zero_copy_command_queue_endpoint.h */, 0A278499128DBF7400336BDE /* chip_to_chip_zero_copy_command_receiver.cpp */, 0A27849A128DBF7400336BDE /* chip_to_chip_zero_copy_command_receiver.h */, 0A27849B128DBF7400336BDE /* chip_to_chip_zero_copy_command_sender.cpp */, 0A27849C128DBF7400336BDE /* chip_to_chip_zero_copy_command_sender.h */, 0A27849D128DBF7400336BDE /* host_pci_info.cpp */, 0A27849E128DBF7400336BDE /* host_pci_info.h */, 0A27849F128DBF7400336BDE /* tilera_chip_to_chip_message_queue.cpp */, 0A2784A0128DBF7400336BDE /* tilera_chip_to_chip_message_queue.h */, ); name = multichip; path = src/multichip; sourceTree = ""; }; 0A2784A1128DBF7400336BDE /* objects */ = { isa = PBXGroup; children = ( 0A2784A2128DBF7400336BDE /* chunk.h */, 0A2784A3128DBF7400336BDE /* chunk.inline.h */, 0A2784A4128DBF7400336BDE /* header_type.cpp */, 0A2784A5128DBF7400336BDE /* header_type.h */, 0A2784A6128DBF7400336BDE /* object.cpp */, 0A2784A7128DBF7400336BDE /* object.h */, 0A2784A8128DBF7400336BDE /* object.inline.h */, 0A2784A9128DBF7400336BDE /* object_indices.h */, 0A2784AA128DBF7400336BDE /* preheader.h */, 0A2784AB128DBF7400336BDE /* process_field_locator.cpp */, 0A2784AC128DBF7400336BDE /* process_field_locator.h */, 0A2784AD128DBF7400336BDE /* roots.cpp */, 0A2784AE128DBF7400336BDE /* roots.h */, 0A2784AF128DBF7400336BDE /* special_indices.h */, 0A2784B0128DBF7400336BDE /* word_containing_object_type.h */, 0A8C91BC12DE61BB007DBAD9 /* object_p.h */, ); name = objects; path = src/objects; sourceTree = ""; }; 0A2784B1128DBF7400336BDE /* oops */ = { isa = PBXGroup; children = ( 0A2784B2128DBF7400336BDE /* abstract_oop.h */, 0A2784B3128DBF7400336BDE /* oop.cpp */, 0A2784B4128DBF7400336BDE /* oop.h */, 0A2784B5128DBF7400336BDE /* oop.inline.h */, 0A2784B6128DBF7400336BDE /* tags.h */, ); name = oops; path = src/oops; sourceTree = ""; }; 0A2784B7128DBF7400336BDE /* platform */ = { isa = PBXGroup; children = ( 0A2784B8128DBF7400336BDE /* abstract_cpu_coordinate.h */, 0A2784B9128DBF7400336BDE /* abstract_memory_semantics.h */, 0A2784BA128DBF7400336BDE /* abstract_message_queue.h */, 0A2784BB128DBF7400336BDE /* abstract_os_interface.cpp */, 0A2784BC128DBF7400336BDE /* abstract_os_interface.h */, 0A2784BD128DBF7400336BDE /* cpu_coordinate.h */, 0A2784BE128DBF7400336BDE /* dummy_cpu_coordinate.cpp */, 0A2784BF128DBF7400336BDE /* dummy_cpu_coordinate.h */, 0A2784C0128DBF7400336BDE /* ilib_message_queue.cpp */, 0A2784C1128DBF7400336BDE /* ilib_message_queue.h */, 0A2784C2128DBF7400336BDE /* ilib_os_interface.cpp */, 0A2784C3128DBF7400336BDE /* ilib_os_interface.h */, 0A72A76314432D7C0008E8AC /* tmc_os_interface.cpp */, 0A72A76414432D7C0008E8AC /* tmc_os_interface.h */, 0A2784C4128DBF7400336BDE /* logical_core.cpp */, 0A2784C5128DBF7400336BDE /* logical_core.h */, 0A2784C6128DBF7400336BDE /* memory_semantics.h */, 0A2784C7128DBF7400336BDE /* message_queue.h */, 0A2784C8128DBF7400336BDE /* os_interface.h */, 0A2784C9128DBF7400336BDE /* osx_os_interface.cpp */, 0A2784CA128DBF7400336BDE /* osx_os_interface.h */, 0A2784CB128DBF7400336BDE /* posix_os_interface.cpp */, 0A2784CC128DBF7400336BDE /* posix_os_interface.h */, 0A2784CD128DBF7400336BDE /* process_memory_semantics.cpp */, 0A2784CE128DBF7400336BDE /* process_memory_semantics.h */, 0A2784CF128DBF7400336BDE /* shared_memory_message_queue.cpp */, 0A2784D0128DBF7400336BDE /* shared_memory_message_queue.h */, 0ACF551712E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp */, 0ACF551812E07E7F0010386A /* shared_memory_message_queue_per_sender.h */, 0A2784D1128DBF7400336BDE /* thread_memory_semantics.cpp */, 0A2784D2128DBF7400336BDE /* thread_memory_semantics.h */, 0A2784D3128DBF7400336BDE /* tile_cpu_coordinate.cpp */, 0A2784D4128DBF7400336BDE /* tile_cpu_coordinate.h */, 0ADA271212EF66EC009404B0 /* cacheline_aligned.h */, ); name = platform; path = src/platform; sourceTree = ""; }; 0A2784D5128DBF7400336BDE /* primitives */ = { isa = PBXGroup; children = ( 0A2784D6128DBF7400336BDE /* RVMPlugin.cpp */, 0A2784D7128DBF7400336BDE /* RVMPlugin.h */, ); name = primitives; path = src/primitives; sourceTree = ""; }; 0A2784D8128DBF7400336BDE /* runtime */ = { isa = PBXGroup; children = ( 0A2784D9128DBF7400336BDE /* abstract_mutex.cpp */, 0A2784DA128DBF7400336BDE /* abstract_mutex.h */, 0A2784DB128DBF7400336BDE /* abstract_tracer.cpp */, 0A2784DC128DBF7400336BDE /* abstract_tracer.h */, 0A2784DD128DBF7400336BDE /* bytemap.cpp */, 0A2784DE128DBF7400336BDE /* bytemap.h */, 0A2784DF128DBF7400336BDE /* core_tracer.cpp */, 0A2784E0128DBF7400336BDE /* core_tracer.h */, 0A2784E1128DBF7400336BDE /* debug_store_checks.h */, 0A2784E2128DBF7400336BDE /* gc_debugging_tracer.cpp */, 0A2784E3128DBF7400336BDE /* gc_debugging_tracer.h */, 0A2784E4128DBF7400336BDE /* error_handling.cpp */, 0A2784E5128DBF7400336BDE /* error_handling.h */, 0A2784E6128DBF7400336BDE /* execution_tracer.cpp */, 0A2784E7128DBF7400336BDE /* execution_tracer.h */, 0A2784E8128DBF7400336BDE /* headers.h */, 0A2784E9128DBF7400336BDE /* main.cpp */, 0A2784EA128DBF7400336BDE /* measurements.cpp */, 0A2784EB128DBF7400336BDE /* measurements.h */, 0A2784EC128DBF7400336BDE /* my_rank.cpp */, 0A2784ED128DBF7400336BDE /* my_rank.h */, 0A2784EE128DBF7400336BDE /* oop_tracer.cpp */, 0A2784EF128DBF7400336BDE /* oop_tracer.h */, 0A2784F0128DBF7400336BDE /* printer.cpp */, 0A2784F1128DBF7400336BDE /* printer.h */, 0A2784F2128DBF7400336BDE /* profiling_tracer.cpp */, 0A2784F3128DBF7400336BDE /* profiling_tracer.h */, 0A2784F4128DBF7400336BDE /* rank_set.cpp */, 0A2784F5128DBF7400336BDE /* rank_set.h */, 0A2784F6128DBF7400336BDE /* runtime_tester.h */, 0A2784F7128DBF7400336BDE /* rvm_bitmap.cpp */, 0A2784F8128DBF7400336BDE /* rvm_bitmap.h */, 0A2784F9128DBF7400336BDE /* rvm_config.cpp */, 0A2784FA128DBF7400336BDE /* rvm_config.h */, 0A5D7C94135CA28500D13E53 /* rvm_squeak_config.h */, 0A2784FB128DBF7400336BDE /* safepoint.cpp */, 0A2784FC128DBF7400336BDE /* safepoint.h */, 0A2784FD128DBF7400336BDE /* safepoint_ability.cpp */, 0A2784FE128DBF7400336BDE /* safepoint_ability.h */, 0A2784FF128DBF7400336BDE /* safepoint_request_queue.cpp */, 0A278500128DBF7400336BDE /* safepoint_request_queue.h */, 0A278501128DBF7400336BDE /* scheduler_mutex.cpp */, 0A278502128DBF7400336BDE /* scheduler_mutex.h */, 0A278503128DBF7400336BDE /* semaphore_mutex.cpp */, 0A278504128DBF7400336BDE /* semaphore_mutex.h */, 0A278505128DBF7400336BDE /* squeak_adapters.cpp */, 0A278506128DBF7400336BDE /* squeak_adapters.h */, 0A278507128DBF7400336BDE /* timeout_deferral.cpp */, 0A278508128DBF7400336BDE /* timeout_deferral.h */, 0A278509128DBF7400336BDE /* timeout_timer.cpp */, 0A27850A128DBF7400336BDE /* timeout_timer.h */, 0A27850B128DBF7400336BDE /* utils.cpp */, 0A27850C128DBF7400336BDE /* utils.h */, 0AEC1184128DF02F00EFF6D1 /* debug_helper.h */, 0AEC1185128DF0A000EFF6D1 /* debug_helper.cpp */, 0A97FBAE12900336003A1C74 /* tracked_ptr.h */, 0A97FEF112909D58003A1C74 /* tracked_ptr_registry.h */, 0A87AD871378439000337878 /* performance_counters.h */, 0A87AD891379573E00337878 /* performance_counters.cpp */, ); name = runtime; path = src/runtime; sourceTree = ""; }; 0A27850D128DBF7400336BDE /* tests */ = { isa = PBXGroup; children = ( 0A3FB13514D99C7E0050F39C /* gtest-all.cc */, 0A27850F128DBF7400336BDE /* buffered_channel.cpp */, 0A278510128DBF7400336BDE /* main.cpp */, 0A278511128DBF7400336BDE /* starter.cpp */, 0A278512128DBF7400336BDE /* starter.h */, 0A278513128DBF7400336BDE /* synced_queue.cpp */, 0A278514128DBF7400336BDE /* synced_queue_threaded.cpp */, 0A97FBB412900371003A1C74 /* tracked_ptr.cpp */, 0A97FEE412909C92003A1C74 /* test_os_interface.h */, 0ADA26B912EF5C00009404B0 /* cacheline_alignment.cpp */, 0A6A4832135ADF0A00933643 /* os_interface.cpp */, 0A6A4835135AE32D00933643 /* external_primitive_table.cpp */, ); name = tests; path = src/tests; sourceTree = ""; }; 0A278515128DBF7400336BDE /* types */ = { isa = PBXGroup; children = ( 0A278516128DBF7400336BDE /* types.h */, ); name = types; path = src/types; sourceTree = ""; }; 0A4A612C14F7917F006748DD /* message_buffers */ = { isa = PBXGroup; children = ( 0AE6D0E11531C596001A1018 /* buffered_channel_debug.h */, 0AE6D0E21531C596001A1018 /* buffered_channel.cpp */, 0AE6D0E31531C596001A1018 /* buffered_channel.h */, 0AE6D0E41531C596001A1018 /* synced_queue.cpp */, 0AE6D0E51531C596001A1018 /* synced_queue.h */, ); name = message_buffers; path = src/message_buffers; sourceTree = ""; }; 0A5124F31372072C001008AC /* iOS */ = { isa = PBXGroup; children = ( 0A5124F41372073F001008AC /* vm */, ); name = iOS; sourceTree = ""; }; 0A5124F41372073F001008AC /* vm */ = { isa = PBXGroup; children = ( 0A5124F513720749001008AC /* iPhone */, ); name = vm; sourceTree = ""; }; 0A5124F513720749001008AC /* iPhone */ = { isa = PBXGroup; children = ( 0A5124F61372077B001008AC /* config.h */, ); name = iPhone; sourceTree = ""; }; 0A5D7C96135CC81F00D13E53 /* plugins */ = { isa = PBXGroup; children = ( 0AEDCC6015E3CB2B0022DD44 /* FilePlugin */, 0A5D7C9D135CC8C800D13E53 /* B3DAcceleratorPlugin */, 0A5D7C9A135CC86800D13E53 /* SocketPlugin */, 0A5D7C97135CC83500D13E53 /* SoundPlugin */, ); name = plugins; sourceTree = ""; }; 0A5D7C97135CC83500D13E53 /* SoundPlugin */ = { isa = PBXGroup; children = ( 0A5D7C98135CC84700D13E53 /* sqUnixSound.c */, ); name = SoundPlugin; sourceTree = ""; }; 0A5D7C9A135CC86800D13E53 /* SocketPlugin */ = { isa = PBXGroup; children = ( 0A5D7C9B135CC86800D13E53 /* sqUnixSocket.c */, ); name = SocketPlugin; path = plugins/SocketPlugin; sourceTree = ""; }; 0A5D7C9D135CC8C800D13E53 /* B3DAcceleratorPlugin */ = { isa = PBXGroup; children = ( 0A5D7C9E135CC8D700D13E53 /* sqUnixOpenGL.h */, ); name = B3DAcceleratorPlugin; sourceTree = ""; }; 0A5D7C9F135CC9D400D13E53 /* SoundPlugin */ = { isa = PBXGroup; children = ( 0A5D7CA0135CC9D400D13E53 /* SoundPlugin.h */, ); path = SoundPlugin; sourceTree = ""; }; 0AEDCC6015E3CB2B0022DD44 /* FilePlugin */ = { isa = PBXGroup; children = ( 0AEDCC6215E3CB2B0022DD44 /* sqUnixFile.c */, ); name = FilePlugin; path = plugins/FilePlugin; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXLegacyTarget section */ 0AC76D9212EC5FCD00C86B11 /* make */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION)"; buildConfigurationList = 0AC76D9812EC5FF200C86B11 /* Build configuration list for PBXLegacyTarget "make" */; buildPhases = ( ); buildToolPath = /usr/bin/make; buildWorkingDirectory = "$(SRCROOT)/build/"; dependencies = ( ); name = make; passBuildSettingsInEnvironment = 1; productName = make; }; /* End PBXLegacyTarget section */ /* Begin PBXNativeTarget section */ 0A2783EA128DBF1000336BDE /* RoarVM */ = { isa = PBXNativeTarget; buildConfigurationList = 0A2783F0128DBF1000336BDE /* Build configuration list for PBXNativeTarget "RoarVM" */; buildPhases = ( 0A2783E8128DBF1000336BDE /* Sources */, 0A2783E9128DBF1000336BDE /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = RoarVM; productName = RoarVM; productReference = 0A2783EB128DBF1000336BDE /* RoarVM */; productType = "com.apple.product-type.tool"; }; 0A97FB25128FE95A003A1C74 /* UnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = 0A97FB2B128FE975003A1C74 /* Build configuration list for PBXNativeTarget "UnitTests" */; buildPhases = ( 0A97FB23128FE95A003A1C74 /* Sources */, 0A97FB24128FE95A003A1C74 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = UnitTests; productName = UnitTests; productReference = 0A97FB26128FE95A003A1C74 /* UnitTests */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 0A278285128DBE2700336BDE /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; }; buildConfigurationList = 0A278288128DBE2700336BDE /* Build configuration list for PBXProject "RoarVM" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, Japanese, French, German, ); mainGroup = 0A278283128DBE2700336BDE; productRefGroup = 0A2783EC128DBF1000336BDE /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0A2783EA128DBF1000336BDE /* RoarVM */, 0A97FB25128FE95A003A1C74 /* UnitTests */, 0AC76D9212EC5FCD00C86B11 /* make */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 0A2783E8128DBF1000336BDE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 0A278518128DBF7400336BDE /* externals.cpp in Sources */, 0A278519128DBF7400336BDE /* FilePlugin.c in Sources */, 0A27851A128DBF7400336BDE /* sqFilePluginBasicPrims.c in Sources */, 0A27851E128DBF7400336BDE /* B2DPlugin.c in Sources */, 0A27851F128DBF7400336BDE /* BitBltPlugin.c in Sources */, 0A278520128DBF7400336BDE /* FloatArrayPlugin.c in Sources */, 0A278521128DBF7400336BDE /* LargeIntegers.c in Sources */, 0A278522128DBF7400336BDE /* Matrix2x3Plugin.c in Sources */, 0A278523128DBF7400336BDE /* MiscPrimitivePlugin.c in Sources */, 0A278524128DBF7400336BDE /* SocketPlugin.c in Sources */, 0A278525128DBF7400336BDE /* SoundPlugin.c in Sources */, 0A278529128DBF7400336BDE /* aio.c in Sources */, 0A278531128DBF7400336BDE /* sqUnixCustomSound.c in Sources */, 0A278533128DBF7400336BDE /* sqUnixSoundNull.c in Sources */, 0A278534128DBF7400336BDE /* abstract_mark_sweep_collector.cpp in Sources */, 0A278535128DBF7400336BDE /* abstract_object_heap.cpp in Sources */, 0A278536128DBF7400336BDE /* memory_system.cpp in Sources */, 0A278537128DBF7400336BDE /* multicore_object_heap.cpp in Sources */, 0A278538128DBF7400336BDE /* multicore_object_table.cpp in Sources */, 0A27853C128DBF7400336BDE /* squeak_image_reader.cpp in Sources */, 0A27853D128DBF7400336BDE /* at_cache.cpp in Sources */, 0A27853E128DBF7400336BDE /* interpreter_bytecodes.cpp in Sources */, 0A27853F128DBF7400336BDE /* interpreter_primitives.cpp in Sources */, 0A278540128DBF7400336BDE /* method_cache.cpp in Sources */, 0A278541128DBF7400336BDE /* obsolete_indexed_primitive_table.cpp in Sources */, 0A278542128DBF7400336BDE /* obsolete_named_primitive_table.cpp in Sources */, 0A278543128DBF7400336BDE /* primitive_table.cpp in Sources */, 0A278544128DBF7400336BDE /* squeak_interpreter.cpp in Sources */, 0A278545128DBF7400336BDE /* abstract_message.cpp in Sources */, 0A278546128DBF7400336BDE /* deferred_request.cpp in Sources */, 0A278547128DBF7400336BDE /* interactions.cpp in Sources */, 0A278548128DBF7400336BDE /* interpreter_subset_for_control_transfer.cpp in Sources */, 0A278549128DBF7400336BDE /* message_classes.cpp in Sources */, 0A27854A128DBF7400336BDE /* message_or_ack_request.cpp in Sources */, 0A27854B128DBF7400336BDE /* message_statics.cpp in Sources */, 0A27854C128DBF7400336BDE /* message_stats.cpp in Sources */, 0A27854D128DBF7400336BDE /* receive_marker.cpp in Sources */, 0A278557128DBF7400336BDE /* header_type.cpp in Sources */, 0A278558128DBF7400336BDE /* object.cpp in Sources */, 0A278559128DBF7400336BDE /* process_field_locator.cpp in Sources */, 0A27855A128DBF7400336BDE /* roots.cpp in Sources */, 0A27855B128DBF7400336BDE /* oop.cpp in Sources */, 0A27855C128DBF7400336BDE /* abstract_os_interface.cpp in Sources */, 0A27855D128DBF7400336BDE /* dummy_cpu_coordinate.cpp in Sources */, 0A278561128DBF7400336BDE /* osx_os_interface.cpp in Sources */, 0A278562128DBF7400336BDE /* posix_os_interface.cpp in Sources */, 0A278564128DBF7400336BDE /* shared_memory_message_queue.cpp in Sources */, 0A278565128DBF7400336BDE /* thread_memory_semantics.cpp in Sources */, 0A278567128DBF7400336BDE /* RVMPlugin.cpp in Sources */, 0A278568128DBF7400336BDE /* abstract_mutex.cpp in Sources */, 0A278569128DBF7400336BDE /* abstract_tracer.cpp in Sources */, 0A27856A128DBF7400336BDE /* bytemap.cpp in Sources */, 0A27856B128DBF7400336BDE /* core_tracer.cpp in Sources */, 0A27856C128DBF7400336BDE /* gc_debugging_tracer.cpp in Sources */, 0A27856D128DBF7400336BDE /* error_handling.cpp in Sources */, 0A27856E128DBF7400336BDE /* execution_tracer.cpp in Sources */, 0A27856F128DBF7400336BDE /* main.cpp in Sources */, 0A278570128DBF7400336BDE /* measurements.cpp in Sources */, 0A278571128DBF7400336BDE /* my_rank.cpp in Sources */, 0A278572128DBF7400336BDE /* oop_tracer.cpp in Sources */, 0A278573128DBF7400336BDE /* printer.cpp in Sources */, 0A278574128DBF7400336BDE /* profiling_tracer.cpp in Sources */, 0A278575128DBF7400336BDE /* rank_set.cpp in Sources */, 0A278576128DBF7400336BDE /* rvm_bitmap.cpp in Sources */, 0A278577128DBF7400336BDE /* rvm_config.cpp in Sources */, 0A278578128DBF7400336BDE /* safepoint.cpp in Sources */, 0A278579128DBF7400336BDE /* safepoint_ability.cpp in Sources */, 0A27857A128DBF7400336BDE /* safepoint_request_queue.cpp in Sources */, 0A27857B128DBF7400336BDE /* scheduler_mutex.cpp in Sources */, 0A27857C128DBF7400336BDE /* semaphore_mutex.cpp in Sources */, 0A27857D128DBF7400336BDE /* squeak_adapters.cpp in Sources */, 0A27857E128DBF7400336BDE /* timeout_deferral.cpp in Sources */, 0A27857F128DBF7400336BDE /* timeout_timer.cpp in Sources */, 0A278580128DBF7400336BDE /* utils.cpp in Sources */, 0A2785A6128DC2B700336BDE /* logical_core.cpp in Sources */, 0AEC1186128DF0A000EFF6D1 /* debug_helper.cpp in Sources */, 0ACF551912E07E7F0010386A /* shared_memory_message_queue_per_sender.cpp in Sources */, 0A4D824B135C51D500CD74D8 /* sqNamedPrims.c in Sources */, 0A4D824D135C51D500CD74D8 /* sqVirtualMachine.c in Sources */, 0A4D8253135C523B00CD74D8 /* sqUnixCharConv.c in Sources */, 0A4D8255135C523B00CD74D8 /* sqUnixExternalPrims.c in Sources */, 0A4D8257135C523B00CD74D8 /* sqUnixMain.c in Sources */, 0A4D825A135C526100CD74D8 /* sqUnixX11.c in Sources */, 0A4D825D135C526F00CD74D8 /* sqUnixSoundMacOSX.c in Sources */, 0A5D7C99135CC84700D13E53 /* sqUnixSound.c in Sources */, 0A5D7C9C135CC86800D13E53 /* sqUnixSocket.c in Sources */, 0A87AD8A1379573F00337878 /* performance_counters.cpp in Sources */, 0A72A76514432D7C0008E8AC /* tmc_os_interface.cpp in Sources */, 0AE6D0E61531C596001A1018 /* buffered_channel.cpp in Sources */, 0AE6D0E71531C596001A1018 /* synced_queue.cpp in Sources */, 0AEDCC6315E3CB2B0022DD44 /* sqUnixFile.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0A97FB23128FE95A003A1C74 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 0A97FB35128FEA77003A1C74 /* buffered_channel.cpp in Sources */, 0A97FB36128FEA77003A1C74 /* main.cpp in Sources */, 0A97FB37128FEA77003A1C74 /* starter.cpp in Sources */, 0A97FB39128FEA77003A1C74 /* synced_queue.cpp in Sources */, 0A97FB3A128FEA77003A1C74 /* synced_queue_threaded.cpp in Sources */, 0A97FBB512900371003A1C74 /* tracked_ptr.cpp in Sources */, 0ADA26E612EF642C009404B0 /* cacheline_alignment.cpp in Sources */, 0A6A4834135ADF0A00933643 /* os_interface.cpp in Sources */, 0A6A4837135AE32D00933643 /* external_primitive_table.cpp in Sources */, 0A4D824C135C51D500CD74D8 /* sqNamedPrims.c in Sources */, 0A4D824E135C51D500CD74D8 /* sqVirtualMachine.c in Sources */, 0A4D8254135C523B00CD74D8 /* sqUnixCharConv.c in Sources */, 0A4D8256135C523B00CD74D8 /* sqUnixExternalPrims.c in Sources */, 0A4D8258135C523B00CD74D8 /* sqUnixMain.c in Sources */, 0A4D825B135C526100CD74D8 /* sqUnixX11.c in Sources */, 34221D6D13D4D3C50057DCBD /* externals.cpp in Sources */, 34221D6F13D4D3F50057DCBD /* abstract_object_heap.cpp in Sources */, 34221D7013D4D3F50057DCBD /* memory_system.cpp in Sources */, 34221D7113D4D3F50057DCBD /* multicore_object_heap.cpp in Sources */, 34221D7213D4D3F50057DCBD /* multicore_object_table.cpp in Sources */, 34221D7413D4D3F50057DCBD /* squeak_image_reader.cpp in Sources */, 34221D7513D4D3F50057DCBD /* at_cache.cpp in Sources */, 34221D7613D4D3F50057DCBD /* interpreter_bytecodes.cpp in Sources */, 34221D7713D4D3F50057DCBD /* interpreter_primitives.cpp in Sources */, 34221D7813D4D3F50057DCBD /* method_cache.cpp in Sources */, 34221D7913D4D3F50057DCBD /* obsolete_indexed_primitive_table.cpp in Sources */, 34221D7A13D4D3F50057DCBD /* obsolete_named_primitive_table.cpp in Sources */, 34221D7B13D4D3F50057DCBD /* primitive_table.cpp in Sources */, 34221D7C13D4D3F50057DCBD /* squeak_interpreter.cpp in Sources */, 34221D7D13D4D3F50057DCBD /* abstract_message.cpp in Sources */, 34221D7E13D4D3F50057DCBD /* deferred_request.cpp in Sources */, 34221D7F13D4D3F50057DCBD /* interactions.cpp in Sources */, 34221D8013D4D3F50057DCBD /* interpreter_subset_for_control_transfer.cpp in Sources */, 34221D8113D4D3F50057DCBD /* message_classes.cpp in Sources */, 34221D8213D4D3F50057DCBD /* message_or_ack_request.cpp in Sources */, 34221D8313D4D3F50057DCBD /* message_statics.cpp in Sources */, 34221D8413D4D3F50057DCBD /* message_stats.cpp in Sources */, 34221D8513D4D3F50057DCBD /* receive_marker.cpp in Sources */, 34221D6E13D4D3D10057DCBD /* abstract_mark_sweep_collector.cpp in Sources */, 34221DC213D4D98B0057DCBD /* aio.c in Sources */, 34221DC313D4D9B70057DCBD /* sqUnixSound.c in Sources */, 34221DC413D4D9D00057DCBD /* sqUnixSocket.c in Sources */, 34221DC513D4D9DC0057DCBD /* SocketPlugin.c in Sources */, 34221DC613D4D9F10057DCBD /* sqUnixSoundNull.c in Sources */, 0A3FB13614D99C7E0050F39C /* gtest-all.cc in Sources */, 0AE6D0E91531C63D001A1018 /* buffered_channel.cpp in Sources */, 0AE6D0EA1531C645001A1018 /* synced_queue.cpp in Sources */, 0AE6D0EB1531C740001A1018 /* squeak_adapters.cpp in Sources */, 0AE6D0EC1531C776001A1018 /* utils.cpp in Sources */, 0AE6D0ED1531C78B001A1018 /* oop.cpp in Sources */, 0AE6D0EE1531C7DE001A1018 /* header_type.cpp in Sources */, 0AE6D0EF1531C7E3001A1018 /* object.cpp in Sources */, 0AE6D0F01531C7E7001A1018 /* process_field_locator.cpp in Sources */, 0AE6D0F11531C7EB001A1018 /* roots.cpp in Sources */, 0AE6D0F21531C7FC001A1018 /* abstract_os_interface.cpp in Sources */, 0AE6D0F31531C800001A1018 /* dummy_cpu_coordinate.cpp in Sources */, 0AE6D0F41531C80C001A1018 /* logical_core.cpp in Sources */, 0AE6D0F61531C824001A1018 /* shared_memory_message_queue.cpp in Sources */, 0AE6D0F71531C827001A1018 /* shared_memory_message_queue_per_sender.cpp in Sources */, 0AE6D0F81531C82A001A1018 /* thread_memory_semantics.cpp in Sources */, 0AE6D0F91531C832001A1018 /* RVMPlugin.cpp in Sources */, 0AE6D0FA1531C838001A1018 /* abstract_mutex.cpp in Sources */, 0AE6D0FB1531C83B001A1018 /* abstract_tracer.cpp in Sources */, 0AE6D0FC1531C83E001A1018 /* bytemap.cpp in Sources */, 0AE6D0FD1531C842001A1018 /* core_tracer.cpp in Sources */, 0AE6D0FE1531C846001A1018 /* gc_debugging_tracer.cpp in Sources */, 0AE6D0FF1531C849001A1018 /* error_handling.cpp in Sources */, 0AE6D1001531C84C001A1018 /* execution_tracer.cpp in Sources */, 0AE6D1011531C853001A1018 /* measurements.cpp in Sources */, 0AE6D1021531C856001A1018 /* my_rank.cpp in Sources */, 0AE6D1031531C859001A1018 /* oop_tracer.cpp in Sources */, 0AE6D1041531C85D001A1018 /* printer.cpp in Sources */, 0AE6D1051531C860001A1018 /* profiling_tracer.cpp in Sources */, 0AE6D1061531C864001A1018 /* rank_set.cpp in Sources */, 0AE6D1071531C868001A1018 /* rvm_bitmap.cpp in Sources */, 0AE6D1081531C884001A1018 /* rvm_config.cpp in Sources */, 0AE6D1091531C887001A1018 /* safepoint.cpp in Sources */, 0AE6D10A1531C88A001A1018 /* safepoint_ability.cpp in Sources */, 0AE6D10B1531C88E001A1018 /* safepoint_request_queue.cpp in Sources */, 0AE6D10C1531C891001A1018 /* semaphore_mutex.cpp in Sources */, 0AE6D10D1531C894001A1018 /* scheduler_mutex.cpp in Sources */, 0AE6D10E1531C899001A1018 /* timeout_deferral.cpp in Sources */, 0AE6D10F1531C89C001A1018 /* timeout_timer.cpp in Sources */, 0AE6D1101531C8A1001A1018 /* debug_helper.cpp in Sources */, 0AE6D1111531C8A5001A1018 /* performance_counters.cpp in Sources */, 0AE6D1121531C8C4001A1018 /* FilePlugin.c in Sources */, 0AE6D1131531C90F001A1018 /* tmc_os_interface.cpp in Sources */, 0AE6D1141531C927001A1018 /* sqFilePluginBasicPrims.c in Sources */, 0AE6D1161531C931001A1018 /* B2DPlugin.c in Sources */, 0AE6D1171531C935001A1018 /* BitBltPlugin.c in Sources */, 0AE6D1181531C938001A1018 /* FloatArrayPlugin.c in Sources */, 0AE6D1191531C93C001A1018 /* LargeIntegers.c in Sources */, 0AE6D11A1531C941001A1018 /* Matrix2x3Plugin.c in Sources */, 0AE6D11B1531C944001A1018 /* MiscPrimitivePlugin.c in Sources */, 0AE6D11C1531C949001A1018 /* SoundPlugin.c in Sources */, 0AE6D11D1531C95E001A1018 /* sqUnixCustomSound.c in Sources */, 0AE6D11E1531C962001A1018 /* sqUnixSoundMacOSX.c in Sources */, 0AE6D11F1531C980001A1018 /* osx_os_interface.cpp in Sources */, 0AE6D1201531C98F001A1018 /* posix_os_interface.cpp in Sources */, 0AEDCC6415E3CB2B0022DD44 /* sqUnixFile.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 0A278286128DBE2700336BDE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; VALID_ARCHS = i386; }; name = Debug; }; 0A278287128DBE2700336BDE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; VALID_ARCHS = i386; }; name = Release; }; 0A2783EE128DBF1000336BDE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = NO; GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_ENABLE_OBJC_EXCEPTIONS = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = src/runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( "Use_PerSender_Message_Queue=1", "Print_Scheduler=0", "Extra_Preheader_Word_Experiment=1", "check_assertions=1", "check_many_assertions=0", "Include_Debugging_Code=1", "Trace_For_Debugging=0", "Trace_Execution=0", "Track_OnStackPointer=0", "Collect_Performance_Counters=0", LSB_FIRST, ROAR_VM, ); HEADER_SEARCH_PATHS = ( src/runtime, src/from_squeak/iOS/vm/src/vm, src/from_squeak/iOS/vm/iPhone, src/from_squeak/unix/vm, /opt/X11/include, ); INSTALL_PATH = /usr/local/bin; LD_NO_PIE = YES; LIBRARY_SEARCH_PATHS = /usr/X11/lib; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-lX11", "-lXext", ); PRODUCT_NAME = RoarVM; SDKROOT = macosx; USER_HEADER_SEARCH_PATHS = ""; VALID_ARCHS = i386; }; name = Debug; }; 0A2783EF128DBF1000336BDE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_DEBUGGING_SYMBOLS = full; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_ENABLE_OBJC_EXCEPTIONS = NO; GCC_OPTIMIZATION_LEVEL = 3; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = src/runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( "Print_Scheduler=0", "Extra_Preheader_Word_Experiment=1", "check_assertions=0", "check_many_assertions=0", "Include_Debugging_Code=0", "Trace_For_Debugging=0", "Trace_Execution=0", LSB_FIRST, ROAR_VM, ); HEADER_SEARCH_PATHS = ( src/runtime, src/from_squeak/iOS/vm/src/vm, src/from_squeak/iOS/vm/iPhone, src/from_squeak/unix/vm, /opt/X11/include, ); INSTALL_PATH = /usr/local/bin; LD_NO_PIE = YES; LIBRARY_SEARCH_PATHS = /usr/X11/lib; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-lX11", "-lXext", ); PRODUCT_NAME = RoarVM; SDKROOT = macosx; USER_HEADER_SEARCH_PATHS = ""; VALID_ARCHS = i386; }; name = Release; }; 0A97FB28128FE95A003A1C74 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_DYNAMIC_NO_PIC = NO; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREFIX_HEADER = src/runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( ROAR_VM, LSB_FIRST, ); HEADER_SEARCH_PATHS = ( src/from_squeak/iOS/vm/iPhone, src/from_squeak/unix/vm, googletest/include, googletest, ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = /usr/X11/lib; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "-lXext", "-lX11", ); PRODUCT_NAME = UnitTests; VALID_ARCHS = i386; }; name = Debug; }; 0A97FB29128FE95A003A1C74 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_MODEL_TUNING = G5; GCC_PREFIX_HEADER = src/runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( ROAR_VM, LSB_FIRST, ); HEADER_SEARCH_PATHS = ( src/from_squeak/iOS/vm/iPhone, src/from_squeak/unix/vm, googletest/include, googletest, ); INSTALL_PATH = /usr/local/bin; LIBRARY_SEARCH_PATHS = /usr/X11/lib; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "-lXext", "-lX11", ); PRODUCT_NAME = UnitTests; VALID_ARCHS = i386; ZERO_LINK = NO; }; name = Release; }; 0AC76D9312EC5FCD00C86B11 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; PRODUCT_NAME = make; }; name = Debug; }; 0AC76D9412EC5FCD00C86B11 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; PRODUCT_NAME = make; ZERO_LINK = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 0A278288128DBE2700336BDE /* Build configuration list for PBXProject "RoarVM" */ = { isa = XCConfigurationList; buildConfigurations = ( 0A278286128DBE2700336BDE /* Debug */, 0A278287128DBE2700336BDE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0A2783F0128DBF1000336BDE /* Build configuration list for PBXNativeTarget "RoarVM" */ = { isa = XCConfigurationList; buildConfigurations = ( 0A2783EE128DBF1000336BDE /* Debug */, 0A2783EF128DBF1000336BDE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0A97FB2B128FE975003A1C74 /* Build configuration list for PBXNativeTarget "UnitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 0A97FB28128FE95A003A1C74 /* Debug */, 0A97FB29128FE95A003A1C74 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0AC76D9812EC5FF200C86B11 /* Build configuration list for PBXLegacyTarget "make" */ = { isa = XCConfigurationList; buildConfigurations = ( 0AC76D9312EC5FCD00C86B11 /* Debug */, 0AC76D9412EC5FCD00C86B11 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 0A278285128DBE2700336BDE /* Project object */; } ================================================ FILE: vm/run/reliability-test ================================================ #!/bin/bash echo_usage () { echo "Usage: $0 [args]" echo echo "Runs a command max. n-times and reports whether it failed in the process." echo # return an error code to signal non-success exit 128 } if [[ $# -lt 2 ]] then echo_usage fi # read the required standard arguments n=$1 cmd=$2 shift 2 # build the command, there might be a better way... while [[ $# -gt 0 ]] do cmd="$cmd $1" shift 1 done # do the execution i=1 while [[ $n -gt 0 ]] do echo "$cmd" $cmd if [[ $? -ne 0 ]] then echo "Reliability test failed after run $i ($cmd)" exit 1 fi : $(( n-- )) : $(( i++ )) done echo "Reliability test successful ($cmd)" ================================================ FILE: vm/run/tile-runner ================================================ #!/bin/sh BASE_PATH=`pwd` tile-monitor --pci --rtc --bootrom-file /users/smarr/Projects/Tilera-custom-bootrom/vmlinux-pci-RVM.bootrom \ --huge-pages 80 --export /users/smarr/ --cd $BASE_PATH \ --env DISPLAY=134.184.43.183:0 --env SQUEAK_NOTIMER=1 --run \ --- \ \ "$@" \ --- \ --quit ================================================ FILE: vm/run/tile-rvm ================================================ #!/bin/sh BASE_PATH=`pwd` BUILD_PATH=$BASE_PATH/../build tile-monitor --pci --rtc --bootrom-file /users/smarr/Projects/Tilera-custom-bootrom/vmlinux-pci-RVM.bootrom \ --debug-on-crash \ --huge-pages 80 --export /users/smarr/ --cd $BASE_PATH \ --env DISPLAY=134.184.43.183:0 --env SQUEAK_NOTIMER=1 --run \ --- \ $BUILD_PATH/rvm \ "$@" \ --- \ --quit ================================================ FILE: vm/run/tile-rvm-db ================================================ #!/bin/sh BASE_PATH=`pwd` BUILD_PATH=$BASE_PATH/../build tile-monitor --pci --rtc --bootrom-file /users/smarr/Projects/Tilera-custom-bootrom/vmlinux-pci-RVM.bootrom \ --huge-pages 80 --export /users/smarr/ --cd $BASE_PATH \ --env DISPLAY=134.184.43.183:0 --env SQUEAK_NOTIMER=1 --debug \ --- \ $BUILD_PATH/rvm \ "$@" \ --- ================================================ FILE: vm/src/externals/externals.cpp ================================================ /****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************/ #include "headers.h" char* ioListExternalModule(int) { unimpExt(); return NULL; } int setCompilerInitialized(int /* flagValue */) { unimpExt(); return 0; } int (*compilerHooks[])() = {NULL}; # if On_iOS void setFullScreenFlag(int32 value) { The_Memory_System()->snapshot_window_size.fullScreenFlag(value); } int32 getFullScreenFlag(void) { return The_Memory_System()->snapshot_window_size.fullScreenFlag(); } int32 ioMousePoint() {/*unimpExt();*/ return -1;} int ioGetButtonState() {/*unimpExt();*/ return -1; } int ioGetKeystroke() {/*unimpExt();*/ return -1; } void ioSetCursor(char*, int, int) {unimpExt();} int ioSetCursorWithMask(char*, char*, int, int) {unimpExt(); return 0; } bool ioFormPrint(int32* bitsAddr, int w, int h, int depth, double hScale, double vScale, bool landscapeFlag) {unimpExt(); return 0; } int ioSetDisplayMode(int, int, int, int) {unimpExt(); return true;} # endif // # include "sq.h" int event_type_complex() { return 6 /*UGH*/ /*EventTypeComplex*/; } # if 0 fn_t ioLoadFunctionFrom(const char*, const char*) {unimpExt(); return dummy_fn; } fn_t ioLoadExternalFunctionOfLengthFromModuleOfLength(char*, int, char*, int) { unimpExt(); assert_on_main(); return NULL; } char* ioListBuiltinModule(int) { unimpExt(); return NULL; } void* dummy_fn(...) {unimplemented(); return 0;} int ioGetNextEvent(void*) { unimpExt(); } # if !On_iOS int ioGetButtonState() {unimpExt(); return 0; } int32 ioMousePoint() {unimpExt(); return 0;} int ioSetDisplayMode(int, int, int, int) {unimpExt(); return true;} # endif bool ioHasDisplayDepth(int depth) {unimpExt(); return true;} # endif void sigint() {The_Squeak_Interpreter()->handle_sigint();} ================================================ FILE: vm/src/externals/externals.h ================================================ /****************************************************************************** * Copyright (c) 2008 - 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Ungar, IBM Research - Initial Implementation * Sam Adams, IBM Research - Initial Implementation * Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems ******************************************************************************/ extern "C" { int32 vmPathSize(); void vmPathGetLength(char*, int); void sqGetFilenameFromString(char*, char*, int, int); void rvm_callInitializersInAllModules(); } extern "C" { # if On_iOS void setFullScreenFlag(int32 value); int32 getFullScreenFlag(void); # endif int sqr_main(int, char**, char**); void* dummy_fn(...); void ioBeep(); int ioExit(); void ioForceDisplayUpdate(); bool ioFormPrint(int32* bitsAddr, int w, int h, int depth, double hScale, double vScale, bool landscapeFlag); int ioGetButtonState(); int ioGetNextEvent(void*); bool ioHasDisplayDepth(int depth); char* ioListBuiltinModule(int); char* ioListExternalModule(int); fn_t ioLoadExternalFunctionOfLengthFromModuleOfLength(char*, int, char*, int); fn_t ioLoadFunctionFrom(const char*, const char*); int32 ioMousePoint(); int ioMSecs(); void ioProcessEvents(); void ioRelinquishProcessorForMicroseconds(int); u_int32 ioScreenSize(); void ioSetCursor(char*, int, int); # if On_iOS # define T int # else # define T void # endif T ioSetCursorWithMask(char*, char*, int, int); # undef T void ioSetInputSemaphore(int); int32 ioSeconds(); # if On_iOS # define T int # else # define T bool # endif T ioSetDisplayMode(int, int, int, int); # undef T void ioSetFullScreen(bool); void ioShowDisplay(char*, int, int, int, int, int, int, int); int ioGetKeystroke(); int ioPeekKeystroke(); void clipboardWriteFromAt(int, char*, int); int clipboardSize(); void clipboardReadIntoAt(int, int, char*); void getAttributeIntoLength(int id, char* p, int len); int attributeSize(int id); int setCompilerInitialized(int flagValue); void sigint(); # if On_iOS /* Will be used from Obj-C code to initalize the VM */ void initialize_basic_subsystems(); void set_num_cores(char* num_cores_str); void initialize_interpreter_instances_selftest_and_interpreter_proxy(char** orig_argv); void read_image(char* image_path); void begin_interpretation(); # endif } extern int (*compilerHooks[])(); int event_type_complex(); ================================================ FILE: vm/src/from_squeak/Cross/plugins/AsynchFilePlugin/AsynchFilePlugin.h ================================================ /* Header file for AsynchFile plugin */ /* module initialization/shutdown */ int asyncFileInit(void); int asyncFileShutdown(void); /*** Experimental Asynchronous File I/O ***/ typedef struct { int sessionID; void *state; } AsyncFile; int asyncFileClose(AsyncFile *f); int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex); int asyncFileRecordSize(); int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize); int asyncFileReadStart(AsyncFile *f, int fPosition, int count); int asyncFileWriteResult(AsyncFile *f); int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize); ================================================ FILE: vm/src/from_squeak/Cross/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.h ================================================ /* Header file for 3D accelerator plugin */ #ifdef WIN32 # include #endif #if defined(BUILD_FOR_OSX) #include #else #include #endif /* Vertex buffer flags */ #define B3D_VB_TRACK_AMBIENT 1 #define B3D_VB_TRACK_DIFFUSE 2 #define B3D_VB_TRACK_SPECULAR 4 #define B3D_VB_TRACK_EMISSION 8 #define B3D_VB_HAS_NORMALS 16 #define B3D_VB_HAS_TEXTURES 32 #define B3D_VB_TWO_SIDED 64 #define B3D_VB_LOCAL_VIEWER 128 typedef struct B3DPrimitiveVertex { float position[3]; float normal[3]; float texCoord[2]; float rasterPos[4]; int pixelValue32; int clipFlags; int windowPos[2]; } B3DPrimitiveVertex; typedef struct B3DPrimitiveMaterial { float ambient[4]; float diffuse[4]; float specular[4]; float emission[4]; float shininess; } B3DPrimitiveMaterial; /* Light type flags */ #define B3D_LIGHT_POSITIONAL 0x0001 #define B3D_LIGHT_DIRECTIONAL 0x0002 #define B3D_LIGHT_ATTENUATED 0x0004 #define B3D_LIGHT_HAS_SPOT 0x0008 /* Light color flags */ #define B3D_LIGHT_AMBIENT 0x0100 #define B3D_LIGHT_DIFFUSE 0x0200 #define B3D_LIGHT_SPECULAR 0x0400 typedef struct B3DPrimitiveLight { float ambient[4]; float diffuse[4]; float specular[4]; float position[3]; float direction[3]; float attenuation[3]; int flags; float spotMinCos; float spotMaxCos; float spotDeltaCos; float spotExponent; } B3DPrimitiveLight; /* Renderer creation flags: B3D_SOFTWARE_RENDERER: Enable use of software renderers B3D_HARDWARE_RENDERER: Enable use of hardware renderers B3D_STENCIL_BUFFER: Request stencil buffer B3D_ANTIALIASING: Request antialiasing in the renderer. B3D_STEREO: Request stereo visual from the renderer B3D_SYNCVBL: Request VBL sync More flags may be added - if they are not supported by the platform code the creation primitive should fail. */ #define B3D_SOFTWARE_RENDERER 0x0001 #define B3D_HARDWARE_RENDERER 0x0002 #define B3D_STENCIL_BUFFER 0x0004 #define B3D_ANTIALIASING 0x0008 #define B3D_STEREO 0x0010 #define B3D_SYNCVBL 0x0020 /* Win32 defaults to DUAL D3D/GL interface everyone else to OpenGL */ #if defined(WIN32) # if defined(WIN32_PURE_D3D) # define B3DX_D3D # elif defined(WIN32_PURE_GL) # define B3DX_GL # else # define B3DX_DUAL # endif #else # define B3DX_GL #endif /* b3dxCreateRenderer is now obsolete but older plugin sources may still use it */ #define b3dxCreateRenderer(sw,hw,x,y,w,h) b3dxCreateRendererFlags(x,y,w,h, (sw ? B3D_SOFTWARE_RENDERER : 0) | (hw ? B3D_HARDWARE_RENDERER : 0)) #if defined(B3DX_GL) #define b3dxInitialize glInitialize #define b3dxShutdown glShutdown #define b3dxAllocateTexture glAllocateTexture #define b3dxDestroyTexture glDestroyTexture #define b3dxActualTextureDepth glActualTextureDepth #define b3dxTextureColorMasks glTextureColorMasks #define b3dxUploadTexture glUploadTexture #define b3dxTextureByteSex glTextureByteSex #define b3dxTextureSurfaceHandle glTextureSurfaceHandle #define b3dxCompositeTexture glCompositeTexture #define b3dxCreateRendererFlags glCreateRendererFlags #define b3dxDestroyRenderer glDestroyRenderer #define b3dxIsOverlayRenderer glIsOverlayRenderer #define b3dxGetRendererSurfaceHandle glGetRendererSurfaceHandle #define b3dxGetRendererSurfaceWidth glGetRendererSurfaceWidth #define b3dxGetRendererSurfaceHeight glGetRendererSurfaceHeight #define b3dxGetRendererSurfaceDepth glGetRendererSurfaceDepth #define b3dxGetRendererColorMasks glGetRendererColorMasks #define b3dxSetBufferRect glSetBufferRect #define b3dxSetViewport glSetViewport #define b3dxClearDepthBuffer glClearDepthBuffer #define b3dxClearViewport glClearViewport #define b3dxRenderVertexBuffer glRenderVertexBuffer #define b3dxSetTransform glSetTransform #define b3dxDisableLights glDisableLights #define b3dxLoadLight glLoadLight #define b3dxLoadMaterial glLoadMaterial #define b3dxFlushRenderer glFlushRenderer #define b3dxFinishRenderer glFinishRenderer #define b3dxSwapRendererBuffers glSwapRendererBuffers #define b3dxGetIntProperty glGetIntProperty #define b3dxSetIntProperty glSetIntProperty #define b3dxGetIntPropertyOS glGetIntPropertyOS #define b3dxSetIntPropertyOS glSetIntPropertyOS #define b3dxSetVerboseLevel glSetVerboseLevel #define b3dxSetFog glSetFog #endif #if defined(B3DX_D3D) #define b3dxInitialize d3dInitialize #define b3dxShutdown d3dShutdown #define b3dxAllocateTexture d3dAllocateTexture #define b3dxDestroyTexture d3dDestroyTexture #define b3dxActualTextureDepth d3dActualTextureDepth #define b3dxTextureColorMasks d3dTextureColorMasks #define b3dxUploadTexture d3dUploadTexture #define b3dxTextureByteSex d3dTextureByteSex #define b3dxTextureSurfaceHandle d3dTextureSurfaceHandle #define b3dxCompositeTexture d3dCompositeTexture #define b3dxCreateRendererFlags d3dCreateRendererFlags #define b3dxDestroyRenderer d3dDestroyRenderer #define b3dxGetRendererSurfaceHandle d3dGetRendererSurfaceHandle #define b3dxGetRendererSurfaceWidth d3dGetRendererSurfaceWidth #define b3dxGetRendererSurfaceHeight d3dGetRendererSurfaceHeight #define b3dxGetRendererSurfaceDepth d3dGetRendererSurfaceDepth #define b3dxGetRendererColorMasks d3dGetRendererColorMasks #define b3dxIsOverlayRenderer d3dIsOverlayRenderer #define b3dxSetBufferRect d3dSetBufferRect #define b3dxSetViewport d3dSetViewport #define b3dxClearDepthBuffer d3dClearDepthBuffer #define b3dxClearViewport d3dClearViewport #define b3dxRenderVertexBuffer d3dRenderVertexBuffer #define b3dxSetTransform d3dSetTransform #define b3dxDisableLights d3dDisableLights #define b3dxLoadLight d3dLoadLight #define b3dxLoadMaterial d3dLoadMaterial #define b3dxFlushRenderer d3dFlushRenderer #define b3dxFinishRenderer d3dFinishRenderer #define b3dxSwapRendererBuffers d3dSwapRendererBuffers #define b3dxGetIntProperty d3dGetIntProperty #define b3dxSetIntProperty d3dSetIntProperty #define b3dxSetVerboseLevel d3dSetVerboseLevel #define b3dxSetFog d3dSetFog #endif /* module initialization support */ int b3dxInitialize(void); /* return true on success, false on error */ int b3dxShutdown(void); /* return true on success, false on error */ /* Texture support primitives */ int b3dxAllocateTexture(int renderer, int w, int h, int d); /* return handle or -1 on error */ int b3dxDestroyTexture(int renderer, int handle); /* return true on success, false on error */ int b3dxActualTextureDepth(int renderer, int handle); /* return depth or <0 on error */ int b3dxTextureColorMasks(int renderer, int handle, int masks[4]); /* return true on success, false on error */ int b3dxUploadTexture(int renderer, int handle, int w, int h, int d, void* bits); /* return true on success, false on error */ int b3dxTextureByteSex(int renderer, int handle); /* return > 0 for MSB, = 0 for LSB, < 0 for error */ int b3dxTextureSurfaceHandle(int renderer, int handle); /* return handle or <0 if error */ int b3dxCompositeTexture(int renderer, int handle, int x, int y, int w, int h, int translucent); /* return true on success; else false */ /* Renderer primitives */ int b3dxCreateRendererFlags(int x, int y, int w, int h, int flags); /* return handle or -1 on error */ int b3dxDestroyRenderer(int handle); /* return true on success, else false */ int b3dxIsOverlayRenderer(int handle); /* return true/false */ int b3dxSetBufferRect(int handle, int x, int y, int w, int h); /* return true on success, false on error */ int b3dxGetRendererSurfaceHandle(int handle); /* return handle or <0 if error */ int b3dxGetRendererSurfaceWidth(int handle); /* return width or <0 if error */ int b3dxGetRendererSurfaceHeight(int handle); /* return height or <0 if error */ int b3dxGetRendererSurfaceDepth(int handle); /* return depth or <0 if error */ int b3dxGetRendererColorMasks(int handle, int *masks); /* return true on success, false on error */ int b3dxSetViewport(int handle, int x, int y, int w, int h); /* return true on success, false on error */ int b3dxClearDepthBuffer(int handle); /* return true on success, false on error */ int b3dxClearViewport(int handle, unsigned int rgba, unsigned int pv); /* return true on success, else false */ int b3dxSetTransform(int handle, float *modelView, float *projection); int b3dxDisableLights(int handle); int b3dxLoadLight(int handle, int index, B3DPrimitiveLight *light); int b3dxLoadMaterial(int handle, B3DPrimitiveMaterial *material); int b3dxRenderVertexBuffer(int handle, int primType, int flags, int texHandle, float *vtxArray, int vtxSize, int *idxArray, int idxSize); /* return true on success, false on error */ int b3dxFlushRenderer(int handle); int b3dxFinishRenderer(int handle); int b3dxSwapRendererBuffers(int handle); int b3dxGetIntProperty(int handle, int prop); int b3dxSetIntProperty(int handle, int prop, int value); int b3dxGetIntPropertyOS(int handle, int prop); int b3dxSetIntPropertyOS(int handle, int prop, int value); int b3dxSetVerboseLevel(int level); int b3dxSetFog(int handle, int fogType, double density, double rangeStart, double rangeEnd, int rgba); /* Qwaq primitives */ int b3dDrawArrays(int handle, int mode, int minIdx, int maxIdx); int b3dDrawElements(int handle, int mode, int nFaces, unsigned int *facePtr); int b3dDrawRangeElements(int handle, int mode, int minIdx, int maxIdx, int nFaces, unsigned int *facePtr); #if defined(B3DX_DUAL) extern int glMode; #if 0 /* initializer is special since it decides what to use */ #define b3dxInitialize() \ (glMode ? glInitialize() : d3dInitialize()) #endif #define b3dxShutdown() \ (glMode ? glShutdown() : d3dShutdown()) #define b3dxAllocateTexture(r,w,h,d) \ (glMode ? glAllocateTexture(r,w,h,d) : d3dAllocateTexture(r,w,h,d)) #define b3dxDestroyTexture(r,h) \ (glMode ? glDestroyTexture(r,h) : d3dAllocateTexture(r,h)) #define b3dxActualTextureDepth(r,h) \ (glMode ? glActualTextureDepth(r,h) : d3dActualTextureDepth(r,h)) #define b3dxTextureColorMasks(r,h,m) \ (glMode ? glTextureColorMasks(r,h,m) : d3dTextureColorMasks(r,h,m)) #define b3dxUploadTexture(r,hh,w,h,d,b) \ (glMode ? glUploadTexture(r,hh,w,h,d,b) : d3dUploadTexture(r,hh,w,h,d,b)) #define b3dxTextureByteSex(r,h) \ (glMode ? glTextureByteSex(r,h) : d3dTextureByteSex(r,h)) #define b3dxTextureSurfaceHandle(r,h) \ (glMode ? glTextureSurfaceHandle(r,h) : d3dTextureSurfaceHandle(r,h)) #define b3dxCompositeTexture(r,hh,x,y,w,h,t) \ (glMode ? glCompositeTexture(r,hh,x,y,w,h,t) : d3dCompositeTexture(r,hh,x,y,w,h,t)) #define b3dxCreateRendererFlags(x,y,w,h,f) \ (glMode ? glCreateRendererFlags(x,y,w,h,f) : d3dCreateRendererFlags(x,y,w,h,f)) #define b3dxDestroyRenderer(h) \ (glMode ? glDestroyRenderer(h) : d3dDestroyRenderer(h)) #define b3dxIsOverlayRenderer(h) \ (glMode ? glIsOverlayRenderer(h) : d3dIsOverlayRenderer(h)) #define b3dxSetBufferRect(hh,x,y,w,h) \ (glMode ? glSetBufferRect(hh, x, y, w, h) : d3dSetBufferRect(hh,x,y,w,h)) #define b3dxGetRendererSurfaceHandle(h) \ (glMode ? glGetRendererSurfaceHandle(h) : d3dGetRendererSurfaceHandle(h)) #define b3dxGetRendererSurfaceWidth(h) \ (glMode ? glGetRendererSurfaceWidth(h) : d3dGetRendererSurfaceWidth(h)) #define b3dxGetRendererSurfaceHeight(h) \ (glMode ? glGetRendererSurfaceHeight(h) : d3dGetRendererSurfaceHeight(h)) #define b3dxGetRendererSurfaceDepth(h) \ (glMode ? glGetRendererSurfaceDepth(h) : d3dGetRendererSurfaceDepth(h)) #define b3dxGetRendererColorMasks(h,m) \ (glMode ? glGetRendererColorMasks(h,m) : d3dGetRendererColorMasks(h,m)) #define b3dxSetViewport(hh,x,y,w,h) \ (glMode ? glSetViewport(hh,x,y,w,h) : d3dSetViewport(hh,x,y,w,h)) #define b3dxClearDepthBuffer(h) \ (glMode ? glClearDepthBuffer(h) : d3dClearDepthBuffer(h)) #define b3dxClearViewport(h,rgba,pv) \ (glMode ? glClearViewport(h,rgba, pv) : d3dClearViewport(h,rgba,pv)) #define b3dxSetTransform(h,mv,p) \ (glMode ? glSetTransform(h,mv,p) : d3dSetTransform(h,mv,p)) #define b3dxDisableLights(h) \ (glMode ? glDisableLights(h) : d3dDisableLights(h)) #define b3dxLoadLight(h,i,l) \ (glMode ? glLoadLight(h,i,l) : d3dLoadLight(h,i,l)) #define b3dxLoadMaterial(h,m) \ (glMode ? glLoadMaterial(h,m) : d3dLoadMaterial(h,m)) #define b3dxRenderVertexBuffer(h,p,f,t,va,vs,ia,is) \ (glMode ? glRenderVertexBuffer(h,p,f,t,va,vs,ia,is) : d3dRenderVertexBuffer(h,p,f,t,va,vs,ia,is)) #define b3dxFlushRenderer(h) \ (glMode ? glFlushRenderer(h) : d3dFlushRenderer(h)) #define b3dxFinishRenderer(h) \ (glMode ? glFinishRenderer(h) : d3dFinishRenderer(h)) #define b3dxSwapRendererBuffers(h) \ (glMode ? glSwapRendererBuffers(h) : d3dSwapRendererBuffers(h)) #define b3dxGetIntProperty(h,p) \ (glMode ? glGetIntProperty(h,p) : d3dGetIntProperty(h,p)) #define b3dxSetIntProperty(h,p,v) \ (glMode ? glSetIntProperty(h,p,v) : d3dSetIntProperty(h,p,v)) #define b3dxSetVerboseLevel(l) \ (glMode ? glSetVerboseLevel(l) : d3dSetVerboseLevel(l)) #define b3dxSetFog(h,t,d,s,e,rgba) \ (glMode ? glSetFog(h,t,d,s,e,rgba) : d3dSetFog(h,t,d,s,e,rgba)) #define B3DX_GL #define B3DX_D3D #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/B3DAcceleratorPlugin/sqOpenGLRenderer.c ================================================ /**************************************************************************** * PROJECT: Squeak 3D accelerator * FILE: sqOpenGLRenderer.c * CONTENT: Generic (cross-platform) bindings for OpenGL * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: Andreas.Raab@disney.com * RCSID: $Id: sqOpenGLRenderer.c 909 2004-08-31 21:13:51Z bertf $ * * NOTES: * * *****************************************************************************/ #ifdef WIN32 # include # include #endif #include #include #include #include "sqVirtualMachine.h" #include "sqConfig.h" #include "sqPlatformSpecific.h" #include "B3DAcceleratorPlugin.h" #if defined (B3DX_GL) #include "sqOpenGLRenderer.h" #if !defined(GL_VERSION_1_1) #warning "This system does not support OpenGL 1.1" #endif static float blackLight[4] = { 0.0, 0.0, 0.0, 0.0 }; /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ int glGetRendererSurfaceHandle(int handle) { /* If we were to use p-buffers, this would be the place to return a surface handle for the p-buffer so Squeak can blt directly to it. Note that this is a ZILLION times faster when it comes to compositing; so it is definitely a good idea when supported. However, I don't have the time to figure it out so I'll just leave this as an exercise for the interested reader :-) */ return -1; /* e.g., fail */ } int glGetRendererColorMasks(int handle, int *masks) { /* If a surface is provided, this is the place to fill in the color masks for the surface. Since we don't provide any, we just bail out. */ return 0; /* e.g., fail */ } int glGetRendererSurfaceWidth(int handle) { /* If a surface is provided return the width of it */ return -1; /* e.g., fail */ } int glGetRendererSurfaceHeight(int handle) { /* If a surface is provided return the height of it */ return -1; /* e.g., fail */ } int glGetRendererSurfaceDepth(int handle) { /* If a surface is provided return the depth of it */ return -1; /* e.g., fail */ } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /* texture support */ int glAllocateTexture(int handle, int w, int h, int d) /* return handle or -1 on error */ { GLuint texture; char *errMsg = ""; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(w & (w-1)) return -1; /* not power of two */ if(h & (h-1)) return -1; /* not power of two */ DPRINTF3D(5, (fp, "### Allocating new texture (w = %d, h = %d, d = %d)\n", w, h, d)); errMsg = "glGenTextures() failed"; glGenTextures(1, &texture); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; DPRINTF3D(5, (fp, "Allocated texture id = %d\n", texture)); errMsg = "glBindTexture() failed"; glBindTexture(GL_TEXTURE_2D, texture); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; errMsg = "glTexParameter() failed"; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; errMsg = "glTexImage2D() failed"; glTexImage2D(GL_TEXTURE_2D, /* target */ 0, /* mipmap level */ 4, /* components */ w, /* width */ h, /* height */ 0, /* border */ GL_RGBA, /* format */ GL_UNSIGNED_BYTE, /* type */ NULL /* image data - if NULL contents is unspecified */); if((glErr = glGetError()) != GL_NO_ERROR) goto FAILED; DPRINTF3D(5, (fp,"\tid = %d\n", texture)); return texture; FAILED: DPRINTF3D(1, (fp, "ERROR (glAllocateTexture): %s -- %s\n", errMsg, glErrString())); glDeleteTextures(1, &texture); return -1; } int glDestroyTexture(int rendererHandle, int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(!glIsTexture(handle)) { return 0; } DPRINTF3D(5, (fp, "### Destroying texture (id = %d)\n", handle)); glDeleteTextures(1, (GLuint*) &handle); ERROR_CHECK; return 1; } int glActualTextureDepth(int rendererHandle, int handle) /* return depth or <0 on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return -1; return 32; } int glTextureColorMasks(int rendererHandle, int handle, int masks[4]) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return 0; #ifdef LSB_FIRST masks[3] = 0xFF000000; masks[2] = 0x00FF0000; masks[1] = 0x0000FF00; masks[0] = 0x000000FF; #else masks[0] = 0xFF000000; masks[1] = 0x00FF0000; masks[2] = 0x0000FF00; masks[3] = 0x000000FF; #endif return 1; } int glTextureByteSex(int rendererHandle, int handle) /* return > 0 if MSB, = 0 if LSB, < 0 if error */ { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer) return -1; #ifdef LSB_FIRST return 0; #else return 1; #endif } int glTextureSurfaceHandle(int rendererHandle, int handle) { /* GL textures are not directly accessible */ return -1; } int glUploadTexture(int rendererHandle, int handle, int w, int h, int d, void* bits) { int y; struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(d != 32) return 0; if(!glIsTexture(handle)) { return 0; } DPRINTF3D(5, (fp, "### Uploading texture (w = %d, h = %d, d = %d, id = %d)\n", w, h, d, handle)); glBindTexture(GL_TEXTURE_2D, handle); ERROR_CHECK; for(y = 0; y < h; y++) { glTexSubImage2D(GL_TEXTURE_2D, /* target */ 0, /* level */ 0, /* xoffset */ y, /* yoffset */ w, /* width */ 1, /* height */ GL_RGBA, /* format */ GL_UNSIGNED_BYTE, /* type */ ((char*)bits) + (y*w*4)); ERROR_CHECK; } return 1; } int glCompositeTexture(int rendererHandle, int handle, int x, int y, int w, int h, int translucent) { struct glRenderer *renderer = glRendererFromHandle(rendererHandle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } if(!glIsTexture(handle)) { return 0; } ERROR_CHECK; DPRINTF3D(7, (fp, "glCompositeTexture(%d, %d, %d, %d)\n", x, y, w, h)); { /* setup a transformation so that we're dealing with pixel x/y coordinate systems */ glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); ERROR_CHECK; /* matrix backup complete - now install new mapping */ { int width = renderer->bufferRect[2]; int height = renderer->bufferRect[3]; glViewport(0, 0, width, height); /* now remap from lower left origin to upper left origin while scaling from (-width,+width) to (-1, +1) */ glScaled(2.0/width, -2.0/height, 1.0); /* offset origin to start at 0,0 rather than -width/2,-height/2 */ glTranslated(width*-0.5, height*-0.5, 0.0); ERROR_CHECK; } /* setup the right shading rules */ glPushAttrib(GL_ALL_ATTRIB_BITS); { glShadeModel(GL_FLAT); glEnable(GL_TEXTURE_2D); glDisable(GL_COLOR_MATERIAL); glDisable(GL_DITHER); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDepthMask(GL_FALSE); glColor4d(1.0, 1.0, 1.0, 1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); } ERROR_CHECK; /* prepare for translucency */ if(translucent) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } ERROR_CHECK; } { /* and *THAT* is the hard work ;-))) */ glBindTexture(GL_TEXTURE_2D, handle); ERROR_CHECK; x -= renderer->bufferRect[0]; y -= renderer->bufferRect[1]; DPRINTF3D(7, (fp, "glRecti(%d, %d, %d, %d)\n", x, y, w, h)); glBegin(GL_QUADS); glTexCoord2d(0.0, 0.0); glVertex2i(x, y); glTexCoord2d(1.0, 0.0); glVertex2i(x+w, y); glTexCoord2d(1.0, 1.0); glVertex2i(x+w, y+h); glTexCoord2d(0.0, 1.0); glVertex2i(x, y+h); glEnd(); ERROR_CHECK; } /* and restore everything back to normal */ { glPopAttrib(); /* BUG BUG BUG - Mac OpenGL has a problem with glPushAttrib/glShadeModel/glPopAttrib - BUG BUG BUG */ glShadeModel(GL_SMOOTH); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } ERROR_CHECK; /* done */ return 1; } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ int glSetViewport(int handle, int x, int y, int w, int h) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### New Viewport\n")); DPRINTF3D(5, (fp, "\tx: %d\n\ty: %d\n\tw: %d\n\th: %d\n", x, y, w, h)); renderer->viewport[0] = x; renderer->viewport[1] = y; renderer->viewport[2] = w; renderer->viewport[3] = h; x -= renderer->bufferRect[0]; y -= renderer->bufferRect[1]; DPRINTF3D(5, (fp, "\tx: %d\n\ty: %d\n\tw: %d\n\th: %d\n", x, y, w, h)); glViewport(x, renderer->bufferRect[3] - (y+h), w, h); ERROR_CHECK; return 1; } int glClearDepthBuffer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Clearing depth buffer\n")); glClear(GL_DEPTH_BUFFER_BIT); ERROR_CHECK; return 1; } int glClearViewport(int handle, unsigned int rgba, unsigned int pv) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Clearing viewport buffer\n")); glClearColor( ((rgba >> 16) & 255) / 255.0, ((rgba >> 8) & 255) / 255.0, (rgba & 255) / 255.0, (rgba >> 24) / 255.0); glClear(GL_COLOR_BUFFER_BIT); ERROR_CHECK; return 1; } int glFinishRenderer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Finishing renderer\n")); glFinish(); ERROR_CHECK; return 1; } int glFlushRenderer(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Flushing renderer\n")); glFlush(); ERROR_CHECK; return 1; } int glSwapRendererBuffers(int handle) /* return true on success, false on error */ { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Swapping renderer buffers\n")); glSwapBuffers(renderer); ERROR_CHECK; return 1; } int glSetTransform(int handle, float *modelViewMatrix, float *projectionMatrix) { float matrix[16]; int i, j; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; DPRINTF3D(5, (fp, "### Installing new transformations\n")); glMatrixMode(GL_PROJECTION); ERROR_CHECK; glLoadIdentity(); ERROR_CHECK; if(projectionMatrix) { /* TODO: Check if matrix is simple and don't use glMultMatrixf if so */ for(i=0; i<4; i++) for(j=0; j<4; j++) matrix[i*4+j] = projectionMatrix[j*4+i]; glLoadMatrixf(matrix); ERROR_CHECK; } glMatrixMode(GL_MODELVIEW); ERROR_CHECK; glLoadIdentity(); ERROR_CHECK; if(modelViewMatrix) { /* TODO: Check if matrix is simple and don't use glMultMatrixf if so */ for(i=0; i<4; i++) for(j=0; j<4; j++) matrix[i*4+j] = modelViewMatrix[j*4+i]; glLoadMatrixf(matrix); ERROR_CHECK; } return 1; } int glDisableLights(int handle) { int i; GLint max; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF3D(5, (fp, "### Disabling all lights\n")); glGetIntegerv(GL_MAX_LIGHTS, &max); ERROR_CHECK; for(i = 0; i < max; i++) { glDisable(GL_LIGHT0+i); ERROR_CHECK; if( (glErr = glGetError()) != GL_NO_ERROR) DPRINTF3D(1, (fp,"ERROR (glDisableLights): glDisable(GL_LIGHT%d) failed -- %s\n", i, glErrString())); } return 1; } int glLoadMaterial(int handle, B3DPrimitiveMaterial *mat) { struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF3D(5, (fp, "### New Material\n")); if(!mat) { DPRINTF3D(5, (fp, "\tOFF (material == nil)\n")); glDisable(GL_LIGHTING); ERROR_CHECK; return 1; } DPRINTF3D(5, (fp, "\tambient : %g, %g, %g, %g\n",mat->ambient[0], mat->ambient[1], mat->ambient[2], mat->ambient[3])); DPRINTF3D(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",mat->diffuse[0], mat->diffuse[1], mat->diffuse[2], mat->diffuse[3])); DPRINTF3D(5, (fp, "\tspecular : %g, %g, %g, %g\n",mat->specular[0], mat->specular[1], mat->specular[2], mat->specular[3])); DPRINTF3D(5, (fp, "\temission : %g, %g, %g, %g\n",mat->emission[0], mat->emission[1], mat->emission[2], mat->emission[3])); DPRINTF3D(5, (fp, "\tshininess: %g\n", mat->shininess)); glEnable(GL_LIGHTING); ERROR_CHECK; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat->ambient); ERROR_CHECK; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat->diffuse); ERROR_CHECK; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular); ERROR_CHECK; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat->emission); ERROR_CHECK; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat->shininess); ERROR_CHECK; return 1; } int glLoadLight(int handle, int idx, B3DPrimitiveLight *light) { float pos[4]; int index = GL_LIGHT0 + idx; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF3D(5, (fp, "### New Light (%d)\n", idx)); if(!light) { DPRINTF3D(5, (fp, "\tDISABLED\n")); glDisable(index); ERROR_CHECK; return 1; } glEnable(index); ERROR_CHECK; DPRINTF3D(5, (fp, "\tambient : %g, %g, %g, %g\n",light->ambient[0], light->ambient[1], light->ambient[2], light->ambient[3])); DPRINTF3D(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",light->diffuse[0], light->diffuse[1], light->diffuse[2], light->diffuse[3])); DPRINTF3D(5, (fp, "\tspecular : %g, %g, %g, %g\n",light->specular[0], light->specular[1], light->specular[2], light->specular[3])); DPRINTF3D(5, (fp, "\tposition : %g, %g, %g\n",light->position[0], light->position[1], light->position[2])); DPRINTF3D(5, (fp, "\tdirection : %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); DPRINTF3D(5, (fp, "\tattenuation : %g, %g, %g\n",light->attenuation[0], light->attenuation[1], light->attenuation[2])); DPRINTF3D(5, (fp, "\tflags [%d]:", light->flags)); if(light->flags & B3D_LIGHT_AMBIENT) DPRINTF3D(5,(fp," B3D_LIGHT_AMBIENT")); if(light->flags & B3D_LIGHT_DIFFUSE) DPRINTF3D(5,(fp," B3D_LIGHT_DIFFUSE")); if(light->flags & B3D_LIGHT_SPECULAR) DPRINTF3D(5,(fp," B3D_LIGHT_SPECULAR")); if(light->flags & B3D_LIGHT_POSITIONAL) DPRINTF3D(5,(fp," B3D_LIGHT_POSITIONAL")); if(light->flags & B3D_LIGHT_DIRECTIONAL) DPRINTF3D(5,(fp," B3D_LIGHT_DIRECTIONAL")); if(light->flags & B3D_LIGHT_ATTENUATED) DPRINTF3D(5,(fp," B3D_LIGHT_ATTENUATED")); if(light->flags & B3D_LIGHT_HAS_SPOT) DPRINTF3D(5,(fp," B3D_LIGHT_HAS_SPOT")); DPRINTF3D(5, (fp, "\n")); DPRINTF3D(5, (fp, "\tspot exponent : %g\n", light->spotExponent)); DPRINTF3D(5, (fp, "### Installing Light (%d)\n", idx)); if(light->flags & B3D_LIGHT_AMBIENT) { DPRINTF3D(5, (fp, "\tambient : %g, %g, %g, %g\n",light->ambient[0], light->ambient[1], light->ambient[2], light->ambient[3])); glLightfv(index, GL_AMBIENT, light->ambient); } else { DPRINTF3D(5, (fp, "\tambient : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_AMBIENT, blackLight); } ERROR_CHECK; if(light->flags & B3D_LIGHT_DIFFUSE) { DPRINTF3D(5, (fp, "\tdiffuse : %g, %g, %g, %g\n",light->diffuse[0], light->diffuse[1], light->diffuse[2], light->diffuse[3])); glLightfv(index, GL_DIFFUSE, light->diffuse); } else { DPRINTF3D(5, (fp, "\tdiffuse : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_DIFFUSE, blackLight); } ERROR_CHECK; if(light->flags & B3D_LIGHT_SPECULAR) { DPRINTF3D(5, (fp, "\tspecular : %g, %g, %g, %g\n",light->specular[0], light->specular[1], light->specular[2], light->specular[3])); glLightfv(index, GL_SPECULAR, light->specular); } else { DPRINTF3D(5, (fp, "\tspecular : OFF (0, 0, 0, 1)\n")); glLightfv(index, GL_SPECULAR, blackLight); } ERROR_CHECK; if(light->flags & B3D_LIGHT_POSITIONAL) { DPRINTF3D(5, (fp, "\tposition : %g, %g, %g\n",light->position[0], light->position[1], light->position[2])); pos[0] = light->position[0]; pos[1] = light->position[1]; pos[2] = light->position[2]; pos[3] = 1.0; /* @@@ FIXME: Squeak pre-transforms the light @@@ */ glPushMatrix(); glLoadIdentity(); glLightfv(index, GL_POSITION, pos); glPopMatrix(); } else { if(light->flags & B3D_LIGHT_DIRECTIONAL) { DPRINTF3D(5, (fp, "\tdirection: %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); pos[0] = light->direction[0]; pos[1] = light->direction[1]; pos[2] = light->direction[2]; pos[3] = 0.0; /* @@@ FIXME: Squeak pre-transforms the light @@@ */ glPushMatrix(); glLoadIdentity(); glLightfv(index, GL_POSITION, pos); glPopMatrix(); } } ERROR_CHECK; if(light->flags & B3D_LIGHT_ATTENUATED) { DPRINTF3D(5, (fp, "\tattenuation: %g, %g, %g\n",light->attenuation[0], light->attenuation[1], light->attenuation[2])); glLightf(index, GL_CONSTANT_ATTENUATION, light->attenuation[0]); ERROR_CHECK; glLightf(index, GL_LINEAR_ATTENUATION, light->attenuation[1]); ERROR_CHECK; glLightf(index, GL_QUADRATIC_ATTENUATION, light->attenuation[2]); ERROR_CHECK; } else { DPRINTF3D(5, (fp, "\tattenuation: OFF (1, 0, 0)\n")); glLightf(index, GL_CONSTANT_ATTENUATION, 1.0); ERROR_CHECK; glLightf(index, GL_LINEAR_ATTENUATION, 0.0); ERROR_CHECK; glLightf(index, GL_QUADRATIC_ATTENUATION, 0.0); ERROR_CHECK; } if(light->flags & B3D_LIGHT_HAS_SPOT) { DPRINTF3D(5, (fp, "\tspot exponent : %g\n", light->spotExponent)); DPRINTF3D(5, (fp, "\tspot cutoff : ???\n")); DPRINTF3D(5, (fp, "\tspot direction: %g, %g, %g\n",light->direction[0], light->direction[1], light->direction[2])); glLightf(index, GL_SPOT_EXPONENT, light->spotExponent); ERROR_CHECK; glLightf(index, GL_SPOT_CUTOFF, light->spotExponent); ERROR_CHECK; glLightfv(index, GL_SPOT_DIRECTION, light->direction); ERROR_CHECK; } else { glLightf(index, GL_SPOT_EXPONENT, 0.0); ERROR_CHECK; glLightf(index, GL_SPOT_CUTOFF, 180.0); ERROR_CHECK; } return 1; } int glSetFog(int handle, int fogType, double density, double fogRangeStart, double fogRangeEnd, int rgba) { GLfloat fogColor[4]; glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(fogType == 0) { glDisable(GL_FOG); ERROR_CHECK; return 1; } glEnable(GL_FOG); if(fogType == 1) glFogi(GL_FOG_MODE, GL_LINEAR); if(fogType == 2) glFogi(GL_FOG_MODE, GL_EXP); if(fogType == 3) glFogi(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, (GLfloat)density); glFogf(GL_FOG_START, (GLfloat)fogRangeStart); glFogf(GL_FOG_END, (GLfloat)fogRangeEnd); fogColor[0] = ((rgba >> 16) & 255) / 255.0; fogColor[1] = ((rgba >> 8) & 255) / 255.0; fogColor[2] = (rgba & 255) / 255.0; fogColor[3] = (rgba >> 24) / 255.0; glFogfv(GL_FOG_COLOR, fogColor); /* enable pixel fog */ glHint(GL_FOG_HINT, GL_NICEST); ERROR_CHECK; return 1; } int glGetIntProperty(int handle, int prop) { GLint v; glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(prop < 0) return glGetIntPropertyOS(handle, prop); switch(prop) { case 1: /* backface culling */ if(!glIsEnabled(GL_CULL_FACE)) return 0; glGetIntegerv(GL_FRONT_FACE, &v); if(v == GL_CW) return 1; if(v == GL_CCW) return -1; return 0; case 2: /* polygon mode */ glGetIntegerv(GL_POLYGON_MODE, &v); ERROR_CHECK; return v; case 3: /* point size */ glGetIntegerv(GL_POINT_SIZE, &v); ERROR_CHECK; return v; case 4: /* line width */ glGetIntegerv(GL_LINE_WIDTH, &v); ERROR_CHECK; return v; case 5: /* blend enable */ return glIsEnabled(GL_BLEND); case 6: /* blend source factor */ case 7: /* blend dest factor */ if(prop == 6) glGetIntegerv(GL_BLEND_SRC, &v); else glGetIntegerv(GL_BLEND_DST, &v); ERROR_CHECK; switch(v) { case GL_ZERO: return 0; case GL_ONE: return 1; case GL_SRC_COLOR: return 2; case GL_ONE_MINUS_SRC_COLOR: return 3; case GL_DST_COLOR: return 4; case GL_ONE_MINUS_DST_COLOR: return 5; case GL_SRC_ALPHA: return 6; case GL_ONE_MINUS_SRC_ALPHA: return 7; case GL_DST_ALPHA: return 8; case GL_ONE_MINUS_DST_ALPHA: return 9; case GL_SRC_ALPHA_SATURATE: return 10; default: return -1; } } return 0; } int glSetIntProperty(int handle, int prop, int value) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(prop < 0) return glSetIntPropertyOS(handle, prop, value); switch(prop) { case 1: /* backface culling */ if(!value) { glDisable(GL_CULL_FACE); ERROR_CHECK; return 1; } glEnable(GL_CULL_FACE); glFrontFace(value == 1 ? GL_CCW : GL_CW); ERROR_CHECK; return 1; case 2: /* polygon mode */ if(value == 0) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else if(value == 1) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else if(value == 2) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); else return 0; ERROR_CHECK; return 1; case 3: /* point size */ glPointSize(value); ERROR_CHECK; return 1; case 4: /* line width */ glLineWidth(value); ERROR_CHECK; return 1; case 5: /* blend enable */ if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND); ERROR_CHECK; return 1; case 6: /* blend source factor */ case 7: /* blend dest factor */ { int factor; GLint src, dst; switch(value) { case 0: factor = GL_ZERO; break; case 1: factor = GL_ONE; break; case 2: factor = GL_SRC_COLOR; break; case 3: factor = GL_ONE_MINUS_SRC_COLOR; break; case 4: factor = GL_DST_COLOR; break; case 5: factor = GL_ONE_MINUS_DST_COLOR; break; case 6: factor = GL_SRC_ALPHA; break; case 7: factor = GL_ONE_MINUS_SRC_ALPHA; break; case 8: factor = GL_DST_ALPHA; break; case 9: factor = GL_ONE_MINUS_DST_ALPHA; break; case 10: factor = GL_SRC_ALPHA_SATURATE; break; default: return 0; } glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); if(prop == 6) src = factor; else dst = factor; glBlendFunc(src,dst); ERROR_CHECK; return 1; } } return 0; } #ifndef GL_VERSION_1_1 static void glRenderVertex(B3DPrimitiveVertex *vtx, int flags) { DPRINTF3D(10, (fp, "[")); if(flags & 1) { unsigned int vv = vtx->pixelValue32; DPRINTF3D(10, (fp, "C(%d, %d, %d, %d)",(vv >> 16) & 255, (vv >> 8) & 255, vv & 255, vv >> 24)); glColor4ub( (vv >> 16) & 255, (vv >> 8) & 255, vv & 255, vv >> 24 ); } if(flags & 2) { DPRINTF3D(10, (fp, "N(%g, %g, %g)", vtx->normal[0], vtx->normal[1], vtx->normal[2])); glNormal3fv(vtx->normal); } if(flags & 4) { DPRINTF3D(10, (fp, "T(%g, %g)", vtx->texCoord[0], vtx->texCoord[1])); glTexCoord2fv(vtx->texCoord); } DPRINTF3D(10, (fp, "V(%g, %g, %g)]\n", vtx->position[0], vtx->position[1], vtx->position[2])); glVertex3fv(vtx->position); } #endif /* General dummy for Squeak's primitive faces */ typedef int B3DInputFace; int glRenderVertexBuffer(int handle, int primType, int flags, int texHandle, float *vtxArray, int vtxSize, int *idxArray, int idxSize) { B3DPrimitiveVertex *vtxPointer = (B3DPrimitiveVertex*) vtxArray; B3DInputFace *facePtr = (B3DInputFace*) idxArray; GLuint tracking; int nVertices = vtxSize; int nFaces = 0; int i, vtxFlags; struct glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(4, (fp, "ERROR: Invalid renderer specified\n")); return 0; } DPRINTF3D(5, (fp,"### Primitive : %d\n", primType)); DPRINTF3D(5, (fp,"\ttexHandle : %d\n", texHandle)); DPRINTF3D(5, (fp,"\tcolor flags :")); if(flags & B3D_VB_TRACK_AMBIENT) DPRINTF3D(5,(fp," B3D_VB_TRACK_AMBIENT")); if(flags & B3D_VB_TRACK_DIFFUSE) DPRINTF3D(5,(fp," B3D_VB_TRACK_DIFFUSE")); if(flags & B3D_VB_TRACK_SPECULAR) DPRINTF3D(5,(fp," B3D_VB_TRACK_SPECULAR")); if(flags & B3D_VB_TRACK_EMISSION) DPRINTF3D(5,(fp," B3D_VB_TRACK_EMISSION")); DPRINTF3D(5, (fp,"\n\tlight flags :")); if(flags & B3D_VB_LOCAL_VIEWER) DPRINTF3D(5,(fp," B3D_VB_LOCAL_VIEWER")); if(flags & B3D_VB_TWO_SIDED) DPRINTF3D(5,(fp," B3D_VB_TWO_SIDED")); DPRINTF3D(5, (fp,"\n\tvertex flags:")); if(flags & B3D_VB_HAS_NORMALS) DPRINTF3D(5,(fp," B3D_VB_HAS_NORMALS")); if(flags & B3D_VB_HAS_TEXTURES) DPRINTF3D(5,(fp," B3D_VB_HAS_TEXTURES")); DPRINTF3D(5, (fp, "\n")); /* process VB flags */ tracking = 0; if(flags & B3D_VB_TRACK_AMBIENT) tracking |= GL_AMBIENT; if(flags & B3D_VB_TRACK_DIFFUSE) tracking |= GL_DIFFUSE; if(flags & B3D_VB_TRACK_SPECULAR) tracking |= GL_SPECULAR; if(flags & B3D_VB_TRACK_EMISSION) tracking |= GL_EMISSION; if(tracking) { /* in accordance with glColorMaterial man page noting: Call glColorMaterial before enabling GL_COLOR_MATERIAL. */ glColorMaterial(GL_FRONT_AND_BACK, tracking); ERROR_CHECK; glEnable(GL_COLOR_MATERIAL); ERROR_CHECK; } glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (flags & B3D_VB_LOCAL_VIEWER) ? 1 : 0); ERROR_CHECK; glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (flags & B3D_VB_TWO_SIDED) ? 1 : 0); ERROR_CHECK; if(texHandle > 0) { glEnable(GL_TEXTURE_2D); ERROR_CHECK; glBindTexture(GL_TEXTURE_2D, texHandle); ERROR_CHECK; } else { glDisable(GL_TEXTURE_2D); ERROR_CHECK; } vtxFlags = 0; if(tracking) vtxFlags |= 1; if(flags & B3D_VB_HAS_NORMALS) vtxFlags |= 2; if(flags & B3D_VB_HAS_TEXTURES) vtxFlags |= 4; #ifdef GL_VERSION_1_1 /* use glDrawElements() etc */ /* @@@ HACK!!! */ vtxPointer -= 1; /* that way we can submit all vertices at once */ if(vtxFlags & 1) { /* harumph... we need to rotate all the colors as we're getting ARGB here but GL expects RGBA... */ for(i=1;i<=nVertices;i++) { unsigned int argb = vtxPointer[i].pixelValue32; unsigned int rgba = (argb << 8) | (argb >> 24); vtxPointer[i].pixelValue32 = rgba; } glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(B3DPrimitiveVertex), &(vtxPointer->pixelValue32)); glEnableClientState(GL_COLOR_ARRAY); } if(vtxFlags & 2) { glNormalPointer(GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->normal); glEnableClientState(GL_NORMAL_ARRAY); } if(vtxFlags & 4) { glTexCoordPointer(2, GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->texCoord); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } glVertexPointer(3, GL_FLOAT, sizeof(B3DPrimitiveVertex), vtxPointer->position); glEnableClientState(GL_VERTEX_ARRAY); ERROR_CHECK; /* @@@ HACK!!! */ vtxPointer += 1; /* that way we can submit all vertices at once */ #endif /* GL_VERSION_1_1 */ switch(primType) { case 1: /* points */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_POINTS, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_POINTS); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 2: /* lines */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_LINES, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_LINES); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 3: /* polygon */ #ifdef GL_VERSION_1_1 glDrawArrays(GL_POLYGON, 1, nVertices); #else /* !GL_VERSION_1_1 */ glBegin(GL_POLYGON); for(i=0; i < nVertices; i++) glRenderVertex(vtxPointer + i, vtxFlags); glEnd(); #endif /* GL_VERSION_1_1 */ break; case 4: /* indexed lines */ #ifdef GL_VERSION_1_1 glDrawElements(GL_LINES, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 2; glBegin(GL_LINES); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (2*i); if(face[0] && face[1]) { DPRINTF3D(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; case 5: /* indexed triangles */ #ifdef GL_VERSION_1_1 glDrawElements(GL_TRIANGLES, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 3; glBegin(GL_TRIANGLES); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (3*i); if(face[0] && face[1] && face[2]) { DPRINTF3D(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); glRenderVertex(vtxPointer + face[2] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; case 6: /* indexed quads */ #ifdef GL_VERSION_1_1 glDrawElements(GL_QUADS, idxSize, GL_UNSIGNED_INT, facePtr); #else /* !GL_VERSION_1_1 */ nFaces = idxSize / 4; glBegin(GL_QUADS); for(i = 0; i < nFaces; i++) { B3DInputFace *face = facePtr + (4*i); if(face[0] && face[1] && face[2] && face[3]) { DPRINTF3D(10, (fp,"\n")); glRenderVertex(vtxPointer + face[0] - 1, vtxFlags); glRenderVertex(vtxPointer + face[1] - 1, vtxFlags); glRenderVertex(vtxPointer + face[2] - 1, vtxFlags); glRenderVertex(vtxPointer + face[3] - 1, vtxFlags); } } glEnd(); #endif /* GL_VERSION_1_1 */ break; } ERROR_CHECK; DPRINTF3D(5, (fp,"\n")); glDisable(GL_COLOR_MATERIAL); ERROR_CHECK; #ifdef GL_VERSION_1_1 if(vtxFlags & 1) glDisableClientState(GL_COLOR_ARRAY); if(vtxFlags & 2) glDisableClientState(GL_NORMAL_ARRAY); if(vtxFlags & 4) glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); ERROR_CHECK; #endif /* GL_VERSION_1_1 */ return 1; } /*****************************************************************************/ /*****************************************************************************/ int b3dLoadClientState(int handle, float *vtxData, int vtxSize, float *colorData, int colorSize, float *normalData, int normalSize, float *txData, int txSize) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) { DPRINTF3D(0, (fp, "ERROR: Invalid renderer specified: %d\n", handle)); return 0; } if(colorData) glColorPointer(colorSize, GL_FLOAT, colorSize*4, colorData); else glDisableClientState(GL_COLOR_ARRAY); if(normalData) glNormalPointer(GL_FLOAT, normalSize*4, normalData); else glDisableClientState(GL_NORMAL_ARRAY); if(txData) glTexCoordPointer(txSize, GL_FLOAT, txSize*4, txData); else glDisableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(vtxSize, GL_FLOAT, vtxSize*4, vtxData); return 1; } int b3dDrawRangeElements(int handle, int mode, int minIdx, int maxIdx, int nFaces, unsigned int *facePtr) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; #ifdef WIN32 if(!renderer->glDrawRangeElements) { void *fn; fn = wglGetProcAddress("glDrawRangeElements"); if(!fn) { DPRINTF3D(1, (fp, "ERROR: Cannot find glDrawRangeElements\n")); fn = wglGetProcAddress("glDrawRangeElementsEXT"); if(!fn) { DPRINTF3D(1, (fp, "ERROR: Cannot find glDrawRangeElementsEXT\n")); return 0; } } renderer->glDrawRangeElements = fn; } (*(renderer->glDrawRangeElements)) (mode, minIdx, maxIdx, nFaces, GL_UNSIGNED_INT, facePtr); #else glDrawRangeElements(mode, minIdx, maxIdx, nFaces, GL_UNSIGNED_INT, facePtr); #endif return 1; } int b3dDrawElements(int handle, int mode, int nFaces, unsigned int *facePtr) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; glDrawElements(mode, nFaces, GL_UNSIGNED_INT, facePtr); return 1; } int b3dDrawArrays(int handle, int mode, int minIdx, int maxIdx) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; glDrawArrays(mode, minIdx, maxIdx); return 1; } #endif /* defined B3DX_GL */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/B3DAcceleratorPlugin/sqOpenGLRenderer.h ================================================ #ifndef SQ_OPENGL_RENDERER_H #define SQ_OPENGL_RENDERER_H #if defined(macintoshSqueak) # include "sqMacOpenGL.h" #elif defined(WIN32) # include "sqWin32OpenGL.h" #elif defined(UNIX) # include "sqUnixOpenGL.h" #endif #if !defined(GL_RENDERER_DEFINED) typedef struct glRenderer { GLint bufferRect[4]; GLint viewport[4]; } glRenderer; #endif struct glRenderer *glRendererFromHandle(int rendererHandle); int glMakeCurrentRenderer(struct glRenderer *renderer); int glSwapBuffers(struct glRenderer *renderer); /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ static int glErr = GL_NO_ERROR; /* this is only for debug purposes */ static char *glErrString(void) { static char errString[50]; switch(glErr) { case 0x0500: return "GL_INVALID_ENUM"; case 0x0501: return "GL_INVALID_VALUE"; case 0x0502: return "GL_INVALID_OPERATION"; case 0x0503: return "GL_STACK_OVERFLOW"; case 0x0504: return "GL_STACK_UNDERFLOW"; case 0x0505: return "GL_OUT_OF_MEMORY"; } sprintf(errString, "error code %d", glErr); return errString; } #define ERROR_CHECK_2(glFn, sqFn) \ { if( (glErr = glGetError()) != GL_NO_ERROR) DPRINTF3D(1, (fp,"ERROR (%s): %s failed -- %s\n", sqFn, glFn, glErrString())); } #define ERROR_CHECK_1(glFn) \ { if( (glErr = glGetError()) != GL_NO_ERROR) DPRINTF3D(1, (fp,"ERROR (file %s, line %d): %s failed -- %s\n", __FILE__, __LINE__, glFn, glErrString())); } #define ERROR_CHECK ERROR_CHECK_1("a GL function") /* Verbose level for debugging purposes: 0 - print NO information ever 1 - print critical debug errors 2 - print debug warnings 3 - print extra information 4 - print per-frame statistics 5 - print information about textures, lights, materials, and primitives 6 - print information about background synchronization 10 - print information about each vertex and face */ extern int verboseLevel; /* define forceFlush if we should fflush() before closing file */ #define forceFlush 1 /* Note: Print this stuff into a file in case we lock up*/ #undef DPRINTF3D # define DPRINTF3D(vLevel, args) if(vLevel <= verboseLevel) {\ FILE *fp = fopen("Squeak3D.log", "at");\ if(fp) { fprintf args; if(forceFlush) fflush(fp); fclose(fp); }} #endif /* sqOpenGLRenderer.h */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/BochsIA32Plugin/BochsIA32Plugin.h ================================================ /* Bochs seems to use error code 1 for execution errors. * So we use > 1 for various errors */ #define NoError 0 #define ExecutionError 1 #define BadCPUInstance 2 #define MemoryBoundsError 3 #define PanicError 4 #define UnsupportedOperationError 5 #define SomethingLoggedError 6 #if !defined(ulong) typedef unsigned long ulong; #endif /* * Answer a pointer to a new Bochs IA32 CPU (an instance of C++ class bx_cpu_c) */ extern void *newCPU(); /* * reset the cpu to register contents 0, protected 32-bit mode. */ extern int resetCPU(void *cpu); /* * Single-step *cpu (a bx_cpu_c instance) using memory as its memory. * Answer 0 on success, or an integer error code if something went awry. */ extern int singleStepCPUInSizeMinAddrReadWrite(void *cpu, void *memory, ulong byteSize, ulong minReadAddr, ulong minWriteAddr); /* * Run *cpu (a bx_cpu_c instance) using memory as its memory. * Answer an integer error code when the processor hits some exception. * Answer 0 when it is interrupted. */ extern int runCPUInSizeMinAddrReadWrite(void *cpu, void *memory, ulong byteSize, ulong minReadAddr, ulong minWriteAddr); /* * Flush any icache entries from start to end */ extern void flushICacheFromTo(void *cpu, ulong strt, ulong nd); /* * force runCPUInSize to exit asap. Used by interrupts. */ extern void forceStopRunning(void); /* * The previous entry in the interruptCheckChain so forceStopRunning can chain. */ extern void (*prevInterruptCheckChain)(); /* * Disassemble the instruction at address in memory, writing the output to the * log. */ extern int disassembleForAtInSize(void *cpu, ulong laddr, void *memory, ulong byteSize); /* * The saved error if the previous singleStepIn failed. */ extern int errorAcorn(); /* * The current log (if singleStep failed with SomethingLoggedError). */ extern char *getlog(long *len); ================================================ FILE: vm/src/from_squeak/Cross/plugins/BochsIA32Plugin/sqBochsIA32Plugin.cpp ================================================ #include #define COG 1 #define FOR_COG_PLUGIN 1 // Requires per-target include paths: // ../../processors/IA32/bochs ../../processors/IA32/bochs/instrument/stubs #include #include #include #define min(a,b) ((a)<=(b)?(a):(b)) /* * Define setjmp and longjmp to be the most minimal setjmp/longjmp available * on the platform. */ #if !WIN32 # define setjmp(jb) _setjmp(jb) # define longjmp(jb,v) _longjmp(jb,v) #endif BOCHSAPI BX_CPU_C bx_cpu; extern "C" { #include "BochsIA32Plugin.h" static int cpu_has_been_reset = 0; #define LOGSIZE 4096 static char bochs_log[LOGSIZE + 1]; static int blidx = 0; static unsigned char *theMemory = 0; static unsigned long theMemorySize; static unsigned long minReadAddress; static unsigned long minWriteAddress; static int theErrorAcorn; static bx_address last_read_address = (bx_address)-1; /* for RMW cycles */ void (*prevInterruptCheckChain)() = 0; int resetCPU(void *cpu); void * newCPU() { if (!cpu_has_been_reset) { resetCPU(&bx_cpu); cpu_has_been_reset = 1; } return &bx_cpu; } int resetCPU(void *cpu) { BX_CPU_C *anx86 = (BX_CPU_C *)cpu; if (anx86 != &bx_cpu) return BadCPUInstance; blidx = 0; #define RESET_FROM_COG BX_RESET_HARDWARE + 1 bx_cpu.reset(RESET_FROM_COG); bx_cpu.SetCR0(0x80000001); // Enter protected mode // Origin the code, data & stack segments at 0 bx_cpu.parse_selector(0x0000,&bx_cpu.sregs[BX_SEG_REG_CS].selector); bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32-bit seg bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xffff; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xffffffff; bx_cpu.parse_selector(0x0000,&bx_cpu.sregs[BX_SEG_REG_DS].selector); bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.base = 0; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32-bit seg bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xffff; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xffffffff; bx_cpu.parse_selector(0x0000,&bx_cpu.sregs[BX_SEG_REG_SS].selector); bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; // 32-bit seg bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit = 0xffff; bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xffffffff; bx_cpu.gen_reg[BX_32BIT_REG_EDX].dword.erx = 0; bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx = 0; return 0; } int singleStepCPUInSizeMinAddressReadWrite(void *cpu, void *memory, ulong byteSize, ulong minAddr, ulong minWriteMaxExecAddr) { BX_CPU_C *anx86 = (BX_CPU_C *)cpu; if (anx86 != &bx_cpu) return BadCPUInstance; theMemory = (unsigned char *)memory; theMemorySize = byteSize; minReadAddress = minAddr; minWriteAddress = minWriteMaxExecAddr; if ((theErrorAcorn = setjmp(anx86->jmp_buf_env)) != 0) { anx86->gen_reg[BX_32BIT_REG_EIP].dword.erx = anx86->prev_rip; return theErrorAcorn; } blidx = 0; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = minWriteMaxExecAddr > 0 ? minWriteMaxExecAddr - 1 : 0; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = byteSize; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit = minWriteMaxExecAddr >> 16; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit = bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit = byteSize >> 16; anx86->eipFetchPtr = theMemory; anx86->eipPageWindowSize = minWriteMaxExecAddr; anx86->cpu_single_step(); return blidx == 0 ? 0 : SomethingLoggedError; } int runCPUInSizeMinAddressReadWrite(void *cpu, void *memory, ulong byteSize, ulong minAddr, ulong minWriteMaxExecAddr) { BX_CPU_C *anx86 = (BX_CPU_C *)cpu; if (anx86 != &bx_cpu) return BadCPUInstance; theMemory = (unsigned char *)memory; theMemorySize = byteSize; minReadAddress = minAddr; minWriteAddress = minWriteMaxExecAddr; if ((theErrorAcorn = setjmp(anx86->jmp_buf_env)) != 0) { anx86->gen_reg[BX_32BIT_REG_EIP].dword.erx = anx86->prev_rip; return theErrorAcorn; } blidx = 0; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = minWriteMaxExecAddr > 0 ? minWriteMaxExecAddr - 1 : 0; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = byteSize; bx_cpu.sregs[BX_SEG_REG_CS].cache.u.segment.limit = minWriteMaxExecAddr >> 16; bx_cpu.sregs[BX_SEG_REG_DS].cache.u.segment.limit = bx_cpu.sregs[BX_SEG_REG_SS].cache.u.segment.limit = byteSize >> 16; anx86->eipFetchPtr = theMemory; anx86->eipPageWindowSize = minWriteMaxExecAddr; bx_pc_system.kill_bochs_request = 0; anx86->cpu_loop(0 /* = "run forever" until exception or interupt */); if (anx86->stop_reason != STOP_NO_REASON) { anx86->gen_reg[BX_32BIT_REG_EIP].dword.erx = anx86->prev_rip; if (theErrorAcorn == NoError) theErrorAcorn = ExecutionError; return theErrorAcorn; } return blidx == 0 ? 0 : SomethingLoggedError; } /* * Currently a dummy for Bochs. */ void flushICacheFromTo(void *cpu, ulong saddr, ulong eaddr) { #if BX_SUPPORT_ICACHE # error not yet implemented #endif } int disassembleForAtInSize(void *cpu, ulong laddr, void *memory, ulong byteSize) { BX_CPU_C *anx86 = (BX_CPU_C *)cpu; Bit8u instr_buf[16]; size_t i=0; static char letters[] = "0123456789ABCDEF"; static disassembler bx_disassemble; long remainsInPage = byteSize - laddr; if (remainsInPage < 0) { theErrorAcorn = MemoryBoundsError; return -MemoryBoundsError; } memcpy(instr_buf, (char *)memory + laddr, min(15,byteSize - laddr)); i = sprintf(bochs_log, "%08lx: ", laddr); bx_disassemble.set_syntax_att(); unsigned isize = bx_disassemble.disasm( anx86->sregs[BX_SEG_REG_CS].cache.u.segment.d_b, anx86->cpu_mode == BX_MODE_LONG_64, anx86->get_segment_base(BX_SEG_REG_CS), laddr, instr_buf, bochs_log+i); if (isize <= remainsInPage) { i=strlen(bochs_log); bochs_log[i++] = ' '; bochs_log[i++] = ':'; bochs_log[i++] = ' '; for (unsigned j=0; j> 4) & 0xf]; bochs_log[i++] = letters[(instr_buf[j] >> 0) & 0xf]; bochs_log[i++] = ' '; } } bochs_log[blidx = i] = 0; return isize; } void forceStopRunning(void) { if (prevInterruptCheckChain) prevInterruptCheckChain(); bx_pc_system.kill_bochs_request = 1; bx_cpu.async_event = 1; } int errorAcorn(void) { return theErrorAcorn; } char * getlog(long *len) { *len = blidx; return bochs_log; } } // extern "C" /* * With COG we implement the paging access_read/write_linear level here * to access data to/from the current Bitmap memory object. This is hence * a simplified subset of cpu/paging.cc. */ #define LOG_THIS BX_CPU_THIS_PTR #define BX_PHY_ADDRESS_MASK ((((Bit64u)(1)) << BX_PHY_ADDRESS_WIDTH) - 1) #define BX_PHY_ADDRESS_RESERVED_BITS \ (~BX_PHY_ADDRESS_MASK & BX_CONST64(0xfffffffffffff)) // bit [11] of the TLB lpf used for TLB_HostPtr valid indication #define TLB_LPFOf(laddr) AlignedAccessLPFOf(laddr, 0x7ff) void BX_CPP_AttrRegparmN(2) BX_CPU_C::pagingCR0Changed(Bit32u oldCR0, Bit32u newCR0) { // Modification of PG,PE flushes TLB cache according to docs. // Additionally, the TLB strategy is based on the current value of // WP, so if that changes we must also flush the TLB. if ((oldCR0 & 0x80010001) != (newCR0 & 0x80010001)) TLB_flush(); // Flush Global entries also. } void BX_CPP_AttrRegparmN(2) BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4) { // Modification of PGE,PAE,PSE flushes TLB cache according to docs. if ((oldCR4 & 0x000000b0) != (newCR4 & 0x000000b0)) TLB_flush(); // Flush Global entries also. } void BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR3(bx_address val) { // flush TLB even if value does not change #if BX_SUPPORT_GLOBAL_PAGES if (BX_CPU_THIS_PTR cr4.get_PGE()) TLB_flushNonGlobal(); // Don't flush Global entries. else #endif TLB_flush(); // Flush Global entries also. { #if BX_PHY_ADDRESS_WIDTH == 32 if (val & BX_CONST64(0x000fffff00000000)) { BX_PANIC(("SetCR3() 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(val), GET32L(val))); } #endif if (val & BX_PHY_ADDRESS_RESERVED_BITS) { BX_ERROR(("SetCR3(): Attempt to write to reserved bits of CR3")); exception(BX_GP_EXCEPTION, 0, 0); } BX_CPU_THIS_PTR cr3_masked = val & BX_CONST64(0x000ffffffffff000); } BX_CPU_THIS_PTR cr3 = val; } // Called to initialize the TLB upon startup. // Unconditional initialization of all TLB entries. void BX_CPU_C::TLB_init(void) { TLB_flush(); } void BX_CPU_C::TLB_flush(void) { } void BX_CPU_C::TLB_invlpg(bx_address laddr) { } void BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPG(bxInstruction_c* i) { #if BX_CPU_LEVEL >= 4 BX_ERROR(("INVLPG: priviledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0, 0); #else BX_INFO(("INVLPG: required i486, use --enable-cpu=4 option")); exception(BX_UD_EXCEPTION, 0, 0); #endif } // error checking order - page not present, reserved bits, protection #define ERROR_NOT_PRESENT 0x00 #define ERROR_PROTECTION 0x01 #define ERROR_RESERVED 0x08 #define ERROR_CODE_ACCESS 0x10 /* PSE PDE4M: bits [21:17] */ #define PAGING_PSE_PDE4M_RESERVED_BITS \ (BX_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x003E0000)) // Translate a linear address to a physical address bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, unsigned rw, unsigned access_type) { return laddr; } #if BX_DEBUGGER || BX_DISASM || BX_INSTRUMENTATION || BX_GDBSTUB bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy) { *phy = (bx_phy_address) laddr; return 1; } #endif void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data) { #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, len, BX_WRITE); #endif if (laddr < minWriteAddress || laddr + len > theMemorySize) longjmp(bx_cpu.jmp_buf_env,MemoryBoundsError); memcpy(theMemory + laddr, data, len); } void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned xlate_rw, void *data) { BX_ASSERT(xlate_rw == BX_READ || xlate_rw == BX_RW); if (laddr < minReadAddress || laddr + len > theMemorySize) longjmp(bx_cpu.jmp_buf_env,MemoryBoundsError); last_read_address = laddr; /* for RMW write cycles below */ memcpy(data, theMemory + laddr, len); } /* * With COG we implement the paging access_read/write_linear level here * to access data to/from the current Bitmap memory object. This is hence * a simplified subset of the RMW operations in cpu/access32.cc */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_byte(Bit8u val8) { if (last_read_address == (bx_address)-1) longjmp(bx_cpu.jmp_buf_env,PanicError); memcpy(theMemory + last_read_address, &val8, 1); last_read_address = (bx_address)-1; } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_word(Bit16u val16) { if (last_read_address == (bx_address)-1) longjmp(bx_cpu.jmp_buf_env,PanicError); memcpy(theMemory + last_read_address, &val16, 2); last_read_address = (bx_address)-1; } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_dword(Bit32u val32) { if (last_read_address == (bx_address)-1) longjmp(bx_cpu.jmp_buf_env,PanicError); memcpy(theMemory + last_read_address, &val32, 4); last_read_address = (bx_address)-1; } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_qword(Bit64u val64) { if (last_read_address == (bx_address)-1) longjmp(bx_cpu.jmp_buf_env,PanicError); memcpy(theMemory + last_read_address, &val64, 8); last_read_address = (bx_address)-1; } // Cut-down parts of memory/misc_mem.cc for cpu/debugstuff.cc bx_bool BX_MEM_C::dbg_fetch_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf) { if (addr + len > theMemorySize) return 0; memcpy(buf, theMemory + addr, len); return 1; } // Cut-down cpu/smm.cc void BX_CPP_AttrRegparmN(1) BX_CPU_C::RSM(bxInstruction_c *i) { BX_ERROR(("BX_CPU_C::RSM not yet implemented")); theErrorAcorn = UnsupportedOperationError; longjmp(bx_cpu.jmp_buf_env,1); } void BX_CPU_C::enter_system_management_mode(void) { BX_ERROR(("BX_CPU_C::enter_system_management_mode not yet implemented")); theErrorAcorn = UnsupportedOperationError; longjmp(bx_cpu.jmp_buf_env,1); } // Cut-down cpu/io_pro.cc Bit32u BX_CPP_AttrRegparmN(2) bx_devices_c::inp(Bit16u addr, unsigned io_len) { BX_ERROR(("BX_CPU_C::inp not yet implemented")); theErrorAcorn = UnsupportedOperationError; longjmp(bx_cpu.jmp_buf_env,1); return 0; } void BX_CPP_AttrRegparmN(3) bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) { BX_ERROR(("BX_CPU_C::outp not yet implemented")); theErrorAcorn = UnsupportedOperationError; longjmp(bx_cpu.jmp_buf_env,1); } // Cut-down gui/siminterface.cc static logfunctions thePluginLog; logfunctions *pluginlog = &thePluginLog; // Dummy SIM object; we don't use the SIM interface or libgui.a bx_simulator_interface_c *SIM = NULL; #undef LOG_THIS #define LOG_THIS bx_pc_system. // Dummy pc_system object; we don't have a pc, but this contains the // bx_pc_system.kill_bochs_request flag we use to break out of loops. bx_pc_system_c bx_pc_system; // constructor bx_pc_system_c::bx_pc_system_c() { BX_ASSERT(numTimers == 0); // Timer[0] is the null timer. It is initialized as a special // case here. It should never be turned off or modified, and its // duration should always remain the same. ticksTotal = 0; // Reset ticks since emulator started. timer[0].inUse = 1; timer[0].period = 0xffffffff; // see NullTimerInterval in pc_system.cc timer[0].active = 1; timer[0].continuous = 1; timer[0].funct = (void (*)(void *))0; // see nullTimer in pc_system.cc timer[0].this_ptr = this; numTimers = 1; // So far, only the nullTimer. kill_bochs_request = 0; } int bx_pc_system_c::Reset(unsigned type) { // type is BX_RESET_HARDWARE or BX_RESET_SOFTWARE BX_INFO(("bx_pc_system_c::Reset(%s) called",type==BX_RESET_HARDWARE?"HARDWARE":"SOFTWARE")); // Always reset cpu for (int i=0; ireset(type); } return(0); } #undef LOG_THIS // Cut-down bx_devices (see iodev/devices.cc) bx_devices_c bx_devices; // constructor for bx_devices_c bx_devices_c::bx_devices_c() { settype(DEVLOG); read_port_to_handler = NULL; write_port_to_handler = NULL; io_read_handlers.next = NULL; io_read_handlers.handler_name = NULL; io_write_handlers.next = NULL; io_write_handlers.handler_name = NULL; for (unsigned i=0; i < BX_MAX_IRQS; i++) irq_handler_name[i] = NULL; } bx_devices_c::~bx_devices_c() { // nothing needed for now timer_handle = BX_NULL_TIMER_HANDLE; } // Versions of the iofunctions that libcpu uses that log to a buffer // // logfunctions::put(char const*) // logfunctions::info(char const*, ...) // logfunctions::panic(char const*, ...) // logfunctions::ldebug(char const*, ...) // logfunctions::settype(int) // logfunctions::logfunctions() // logfunctions::~logfunctions() // logfunctions::error(char const*, ...) logfunctions::logfunctions(void) {} logfunctions::~logfunctions() {} #define sprintlog(fmt, ap) \ do { \ va_list ap; \ va_start(ap, fmt); \ int len = vsnprintf(bochs_log + blidx, LOGSIZE-blidx, fmt, ap); \ if ((blidx = min(blidx + len, LOGSIZE)) < LOGSIZE - 1) { \ bochs_log[blidx] = '\r'; \ bochs_log[++blidx] = 0; \ } \ } while (0) void logfunctions::put(const char *p) { int len = strlen(p); strncpy(bochs_log + blidx, p, min(len,LOGSIZE-blidx)); blidx = min(blidx + len, LOGSIZE); bochs_log[blidx] = 0; } void logfunctions::settype(int t) {} void logfunctions::info(const char *fmt, ...) { sprintlog(fmt,ap); } void logfunctions::error(const char *fmt, ...) { sprintlog(fmt,ap); } void logfunctions::panic(const char *fmt, ...) { sprintlog(fmt,ap); longjmp(bx_cpu.jmp_buf_env,PanicError); } void logfunctions::ldebug(const char *fmt, ...) { sprintlog(fmt,ap); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/CroquetPlugin/CroquetPlugin.h ================================================ #ifndef CROQUET_PLUGIN_H #define CROQUET_PLUGIN_H /* CroquetPlugin.h include file */ /* Include MD5 code for primitives */ #include "md5.h" /* ioGatherEntropy: Fill a buffer with high-quality entropy. Return true on success, false if no high-quality source is available or if the source couldn't be used for some reason. On *nix platforms, the Right Thing To Do is to use /dev/urandom for filling the buffer so the implementation gets trivial (open /dev/urandom, read bufSize bytes, return true). Arguments: bufPtr - the buffer to fill bufSize - the number of bytes to place in the buffer Return value: Non-zero if successful, zero otherwise. */ int ioGatherEntropy(char *bufPtr, int bufSize); /* Imported from tribox.c */ int triBoxOverlap(float minCorner[3],float maxCorner[3], float vert0[3], float vert1[3], float vert2[3]); #endif /* CROQUET_PLUGIN_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/CroquetPlugin/CroquetPlugin.st ================================================ 'From Croquet1.0beta of 24 March 2006 [latest update: #6665] on 26 March 2006 at 8:26:17 pm'! InterpreterPlugin subclass: #CroquetPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !CroquetPlugin commentStamp: '' prior: 0! An assorted list of useful primitives for Croquet.! !CroquetPlugin methodsFor: 'primitives' stamp: 'ar 3/26/2006 19:59'! primitiveARC4Transform "Perform an ARC4 transform of input. Arguments: buffer transformed data startIndex start of transform stopIndex end of transform m key stream data x key state value y key state value Return value: x@y - updated key state value " | y x mOop stopIndex startIndex bufOop bufSize buffer a m b mask ptOop xOop yOop | self export: true. self var: 'buffer' type: 'unsigned char *'. self var: 'm' type: 'unsigned char *'. interpreterProxy methodArgumentCount = 6 ifFalse:[^interpreterProxy primitiveFail]. "pick up arguments" y := interpreterProxy stackIntegerValue: 0. x := interpreterProxy stackIntegerValue: 1. mOop := interpreterProxy stackObjectValue: 2. stopIndex := interpreterProxy stackIntegerValue: 3. startIndex := interpreterProxy stackIntegerValue: 4. bufOop := interpreterProxy stackObjectValue: 5. interpreterProxy failed ifTrue:[^nil]. ((interpreterProxy isBytes: mOop) and:[interpreterProxy isBytes: bufOop]) ifFalse:[^interpreterProxy primitiveFail]. (interpreterProxy byteSizeOf: mOop) = 256 ifFalse:[^interpreterProxy primitiveFail]. bufSize := interpreterProxy byteSizeOf: bufOop. (startIndex > 0 and:[startIndex <= bufSize]) ifFalse:[^interpreterProxy primitiveFail]. (stopIndex > startIndex and:[stopIndex <= bufSize]) ifFalse:[^interpreterProxy primitiveFail]. m := interpreterProxy firstIndexableField: mOop. buffer := interpreterProxy firstIndexableField: bufOop. startIndex-1 to: stopIndex-1 do:[:i| x := (x + 1) bitAnd: 255. a := m at: x. y := (y + a) bitAnd: 255. b := m at: y. m at: x put: b. m at: y put: a. mask := m at: ((a + b) bitAnd: 255). buffer at: i put: ((buffer at: i) bitXor: mask). ]. ptOop := interpreterProxy instantiateClass: interpreterProxy classPoint indexableSize: 0. interpreterProxy pushRemappableOop: ptOop. xOop := interpreterProxy positive32BitIntegerFor: x. interpreterProxy pushRemappableOop: xOop. yOop := interpreterProxy positive32BitIntegerFor: x. xOop := interpreterProxy popRemappableOop. ptOop := interpreterProxy popRemappableOop. interpreterProxy storePointer: 0 ofObject: ptOop withValue: xOop. interpreterProxy storePointer: 1 ofObject: ptOop withValue: yOop. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy push: ptOop. ! ! !CroquetPlugin methodsFor: 'primitives' stamp: 'ar 3/26/2006 19:45'! primitiveMD5Transform "Perform an MD5 transform of input" | bufOop hashOop hash buffer | self export: true. self var: 'hash' type: 'unsigned int *'. self var: 'buffer' type: 'unsigned int *'. interpreterProxy methodArgumentCount = 2 ifFalse:[^interpreterProxy primitiveFail]. hashOop := interpreterProxy stackObjectValue: 0. ((interpreterProxy isWords: hashOop) and:[(interpreterProxy slotSizeOf: hashOop) = 4]) ifFalse:[^interpreterProxy primitiveFail]. hash := interpreterProxy firstIndexableField: hashOop. bufOop := interpreterProxy stackObjectValue: 1. ((interpreterProxy isWords: bufOop) and:[(interpreterProxy slotSizeOf: bufOop) = 16]) ifFalse:[^interpreterProxy primitiveFail]. buffer := interpreterProxy firstIndexableField: bufOop. self cCode:'MD5Transform(hash, buffer)' inSmalltalk:[ hash. buffer. ^interpreterProxy primitiveFail]. "Pop args; return buffer" interpreterProxy pop: interpreterProxy methodArgumentCount+1. interpreterProxy push: bufOop.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CroquetPlugin class instanceVariableNames: ''! !CroquetPlugin class methodsFor: 'as yet unclassified' stamp: 'ar 3/26/2006 19:37'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !CroquetPlugin class methodsFor: 'as yet unclassified' stamp: 'ar 3/26/2006 19:37'! requiresCrossPlatformFiles "default is ok for most, any plugin needing platform specific files must say so" ^true! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/CroquetPlugin/md5.h ================================================ /* * MD5 transform algorithm, taken from code written by Colin Plumb, * and put into the public domain * */ /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(unsigned int buf[4], unsigned int const in[16]) { unsigned int a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #undef F1 #undef F2 #undef F3 #undef F4 #undef MD5STEP ================================================ FILE: vm/src/from_squeak/Cross/plugins/CroquetPlugin/tribox.c ================================================ /********************************************************/ /* AABB-triangle overlap test code */ /* by Tomas Akenine-Mller */ /* Function: int triBoxOverlap(float boxcenter[3], */ /* float boxhalfsize[3],float triverts[3][3]); */ /* History: */ /* 2001-03-05: released the code in its first version */ /* 2001-06-18: changed the order of the tests, faster */ /* */ /* Acknowledgement: Many thanks to Pierre Terdiman for */ /* suggestions and discussions on how to optimize code. */ /* Thanks to David Hunt for finding a ">="-bug! */ /********************************************************/ #include #include #define X 0 #define Y 1 #define Z 2 #define CROSS(dest,v1,v2) \ dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) #define SUB(dest,v1,v2) \ dest[0]=v1[0]-v2[0]; \ dest[1]=v1[1]-v2[1]; \ dest[2]=v1[2]-v2[2]; #define MID(dest,v1,v2) \ dest[0]=(v1[0]+v2[0])*0.5; \ dest[1]=(v1[1]+v2[1])*0.5; \ dest[2]=(v1[2]+v2[2])*0.5; #define FINDMINMAX(x0,x1,x2,min,max) \ min = max = x0; \ if(x1max) max=x1;\ if(x2max) max=x2; int planeBoxOverlap(float normal[3],float vert[3], float maxbox[3]) { int q; float vmin[3],vmax[3],v; for(q=X;q<=Z;q++) { v = vert[q]; if(normal[q]>0.0f) { vmin[q]=-maxbox[q] - v; vmax[q]= maxbox[q] - v; } else { vmin[q]= maxbox[q] - v; vmax[q]=-maxbox[q] - v; } } if(DOT(normal,vmin)> 0.0f) return 0; if(DOT(normal,vmax)>=0.0f) return 1; return 0; } /*======================== X-tests ========================*/ #define AXISTEST_X01(a, b, fa, fb) \ p0 = a*v0[Y] - b*v0[Z]; \ p2 = a*v2[Y] - b*v2[Z]; \ if(p0rad || max<-rad) return 0; #define AXISTEST_X2(a, b, fa, fb) \ p0 = a*v0[Y] - b*v0[Z]; \ p1 = a*v1[Y] - b*v1[Z]; \ if(p0rad || max<-rad) return 0; /*======================== Y-tests ========================*/ #define AXISTEST_Y02(a, b, fa, fb) \ p0 = -a*v0[X] + b*v0[Z]; \ p2 = -a*v2[X] + b*v2[Z]; \ if(p0rad || max<-rad) return 0; #define AXISTEST_Y1(a, b, fa, fb) \ p0 = -a*v0[X] + b*v0[Z]; \ p1 = -a*v1[X] + b*v1[Z]; \ if(p0rad || max<-rad) return 0; /*======================== Z-tests ========================*/ #define AXISTEST_Z12(a, b, fa, fb) \ p1 = a*v1[X] - b*v1[Y]; \ p2 = a*v2[X] - b*v2[Y]; \ if(p2rad || max<-rad) return 0; #define AXISTEST_Z0(a, b, fa, fb) \ p0 = a*v0[X] - b*v0[Y]; \ p1 = a*v1[X] - b*v1[Y]; \ if(p0rad || max<-rad) return 0; int triBoxOverlap(float minCorner[3],float maxCorner[3], float vert0[3], float vert1[3], float vert2[3]) { /* use separating axis theorem to test overlap between triangle and box */ /* need to test for overlap in these directions: */ /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ /* we do not even need to test these) */ /* 2) normal of the triangle */ /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ /* this gives 3x3=9 more tests */ float v0[3],v1[3],v2[3]; float min,max,p0,p1,p2,rad,fex,fey,fez; float normal[3],e0[3],e1[3],e2[3]; float boxcenter[3]; float boxhalfsize[3]; MID(boxcenter, minCorner, maxCorner); SUB(boxhalfsize, boxcenter, minCorner); /* This is the fastest branch on Sun */ /* move everything so that the boxcenter is in (0,0,0) */ SUB(v0,vert0,boxcenter); SUB(v1,vert1,boxcenter); SUB(v2,vert2,boxcenter); /* compute triangle edges */ SUB(e0,v1,v0); /* tri edge 0 */ SUB(e1,v2,v1); /* tri edge 1 */ SUB(e2,v0,v2); /* tri edge 2 */ /* Bullet 3: */ /* test the 9 tests first (this was faster) */ fex = fabsf(e0[X]); fey = fabsf(e0[Y]); fez = fabsf(e0[Z]); AXISTEST_X01(e0[Z], e0[Y], fez, fey); AXISTEST_Y02(e0[Z], e0[X], fez, fex); AXISTEST_Z12(e0[Y], e0[X], fey, fex); fex = fabsf(e1[X]); fey = fabsf(e1[Y]); fez = fabsf(e1[Z]); AXISTEST_X01(e1[Z], e1[Y], fez, fey); AXISTEST_Y02(e1[Z], e1[X], fez, fex); AXISTEST_Z0(e1[Y], e1[X], fey, fex); fex = fabsf(e2[X]); fey = fabsf(e2[Y]); fez = fabsf(e2[Z]); AXISTEST_X2(e2[Z], e2[Y], fez, fey); AXISTEST_Y1(e2[Z], e2[X], fez, fex); AXISTEST_Z12(e2[Y], e2[X], fey, fex); /* Bullet 1: */ /* first test overlap in the {x,y,z}-directions */ /* find min, max of the triangle each direction, and test for overlap in */ /* that direction -- this is equivalent to testing a minimal AABB around */ /* the triangle against the AABB */ /* test in X-direction */ FINDMINMAX(v0[X],v1[X],v2[X],min,max); if(min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0; /* test in Y-direction */ FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max); if(min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0; /* test in Z-direction */ FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max); if(min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0; /* Bullet 2: */ /* test if the box intersects the plane of the triangle */ /* compute plane equation of triangle: normal*x+d=0 */ CROSS(normal,e0,e1); if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0; return 1; /* box and triangle overlaps */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/DropPlugin/DropPlugin.h ================================================ /* drop support primitives */ /* module initialization/shutdown */ int dropInit(void); int dropShutdown(void); char* dropRequestFileName(int dropIndex); /* return name of file or NULL if error */ /* note: dropRequestFileHandle needs to bypass plugin security checks when implemented */ int dropRequestFileHandle(int dropIndex); /* return READ-ONLY file handle OOP or nilObject if error */ int sqSecFileAccessCallback(void *); void sqSetNumberOfDropFiles(int numberOfFiles); void sqSetFileInformation(int dropIndex, void *dropFile); void sqDragTriggerData(char *aByteArray, int dataLength, char *aFormat, int formatLength); ================================================ FILE: vm/src/from_squeak/Cross/plugins/ExampleSurfacePlugin/ExampleSurfacePlugin.h ================================================ /* example surface plugin header file */ int memInitialize(void); int memCreateSurfaceWidthHeightDepth(int width, int height, int depth); int memDestroySurface(int id); int memGetSurfaceWidth(int id); int memGetSurfaceHeight(int id); int memGetSurfaceDepth(int id); ================================================ FILE: vm/src/from_squeak/Cross/plugins/ExampleSurfacePlugin/SurfacePlugin-Examples.st ================================================ Form subclass: #ExampleSurface instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'SurfacePlugin-Examples'! !ExampleSurface commentStamp: '' prior: 0! An example surface for the example surface plugin.! !ExampleSurface methodsFor: 'initialize' stamp: 'ar 4/26/2006 13:55'! destroy "Free my bits" self primitiveDestroySurface: bits. ! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:54'! fromHandle: h "Create me from the given handle" width := self primitiveGetSurfaceWidth: h. height := self primitiveGetSurfaceHeight: h. depth := self primitiveGetSurfaceDepth: h. bits := h.! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:53'! primitiveCreateSurfaceWidth: width height: height depth: bitsPerPixel ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:55'! primitiveDestroySurface: h ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:54'! primitiveGetSurfaceBits: h ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:54'! primitiveGetSurfaceDepth: h ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:54'! primitiveGetSurfaceHeight: h ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:54'! primitiveGetSurfaceWidth: h ^self primitiveFailed! ! !ExampleSurface methodsFor: 'private' stamp: 'ar 4/26/2006 13:52'! setExtent: extent depth: bitsPerPixel "Create a virtual bit map with the given extent and bitsPerPixel." width := extent x asInteger. width < 0 ifTrue: [width := 0]. height := extent y asInteger. height < 0 ifTrue: [height := 0]. depth := bitsPerPixel. bits := self primitiveCreateSurfaceWidth: width height: height depth: bitsPerPixel.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ExampleSurface class instanceVariableNames: ''! !ExampleSurface class methodsFor: 'examples' stamp: 'ar 4/26/2006 14:00'! example "ExampleSurface example" "Create a new example surface; then one from its handle; then copy between them etc" | formA formB | formA := self extent: 100@100 depth: (Display depth max: 8). "Copy from display to external form" Display displayOn: formA at: 0@0. "Copy from external form to display" formA displayOn: Display at: 0@0. "Create a form from a handle - this is literally the same form!!" formB := self new fromHandle: formA bits. "Display right next to formA" formB displayOn: Display at: formA width@0. "Do an overlapping blt between formA and formB" formA displayOn: formB at: formA extent // 2. "Show the result" formA displayOn: Display at: 0@0. formB displayOn: Display at: formA width@0. ! ! InterpreterPlugin subclass: #ExampleSurfacePlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'SurfacePlugin-Examples'! !ExampleSurfacePlugin commentStamp: '' prior: 0! This is an example for using the surface plugin.! !ExampleSurfacePlugin methodsFor: 'initialize' stamp: 'ar 4/26/2006 13:46'! initialiseModule self export: true. ^self memInitialize! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:50'! primitiveCreateSurface "Primitive. Create a surface of the given width/height/depth. Answer the handle." | depth height width id | self export: true. interpreterProxy methodArgumentCount = 3 ifFalse:[^interpreterProxy primitiveFail]. depth := interpreterProxy stackIntegerValue: 0. height := interpreterProxy stackIntegerValue: 1. width := interpreterProxy stackIntegerValue: 2. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" "make sure depth is power of two" (depth bitAnd: depth-1) = 0 ifFalse:[^interpreterProxy primitiveFail]. "Create bitmap surface" id := self memCreateSurfaceWidth: width Height: height Depth: depth. id < 0 ifTrue:[^interpreterProxy primitiveFail]. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args+rcvr" interpreterProxy pushInteger: id.! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:49'! primitiveDestroySurface "Primitive. Destroy a surface." | id ok | self export: true. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. id := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" ok := self memDestroySurface: id. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args + rcvr" interpreterProxy pushBool: ok.! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:49'! primitiveGetSurfaceBits "Primitive. Return the witdth of a surface." | id result | self export: true. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. id := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" result := self memGetSurfaceBits: id. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args+rcvr" interpreterProxy push: (interpreterProxy positive32BitIntegerFor: result).! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:50'! primitiveGetSurfaceDepth "Primitive. Return the height of a surface." | id result | self export: true. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. id := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" result := self memGetSurfaceDepth: id. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args+rcvr" interpreterProxy pushInteger: result.! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:50'! primitiveGetSurfaceHeight "Primitive. Return the height of a surface." | id result | self export: true. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. id := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" result := self memGetSurfaceHeight: id. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args+rcvr" interpreterProxy pushInteger: result.! ! !ExampleSurfacePlugin methodsFor: 'primitives' stamp: 'ar 4/26/2006 13:50'! primitiveGetSurfaceWidth "Primitive. Return the witdth of a surface." | id result | self export: true. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. id := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. "invalid arguments" result := self memGetSurfaceWidth: id. interpreterProxy pop: interpreterProxy methodArgumentCount+1. "args+rcvr" interpreterProxy pushInteger: result.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ExampleSurfacePlugin class instanceVariableNames: ''! !ExampleSurfacePlugin class methodsFor: 'accessing' stamp: 'ar 4/26/2006 12:35'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !ExampleSurfacePlugin class methodsFor: 'accessing' stamp: 'ar 4/26/2006 12:35'! requiresCrossPlatformFiles "default is ok for most, any plugin needing platform specific files must say so" ^true! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/ExampleSurfacePlugin/sqMemorySurface.c ================================================ /* sample memory surface plugin implementation */ #include #include "sqVirtualMachine.h" #include "ExampleSurfacePlugin.h" #include "../SurfacePlugin/SurfacePlugin.h" typedef struct memSurface { int width, height, depth, stride; void *bits; } memSurface; /* entry points for surface manager; looked up at startup */ static fn_ioRegisterSurface registerSurface = 0; static fn_ioUnregisterSurface unregisterSurface = 0; static fn_ioFindSurface findSurface = 0; extern struct VirtualMachine *interpreterProxy; /******************* Surface manager entry points *******************/ static int memGetSurfaceFormat(memSurface *ms, int *w, int *h, int *d, int *msbFlag) { *w = ms->width; *h = ms->height; *d = ms->depth; *msbFlag = 0; /* should really depend on platform */ return 1; } static int memLock(memSurface *ms, int *stride, int x, int y, int w, int h){ /* Locking can be safely ignored for memory surfaces but we need to fill in the stride and return the bits */ *stride = ms->stride; return (int)ms->bits; } static int memUnlock(memSurface *ms, int x, int y, int w, int h){ return 1; /* ignored */ } static int memShow(memSurface *ms, int x, int y, int w, int h) { /* unsupported */ return 0; } static sqSurfaceDispatch memSurfaceDispatch = { 1, 0, (fn_getSurfaceFormat) memGetSurfaceFormat, (fn_lockSurface) memLock, (fn_unlockSurface) memUnlock, (fn_showSurface) memShow }; /******************* primitive entry points *******************/ int memCreateSurfaceWidthHeightDepth(int w, int h, int d) { memSurface *ms; int id; /* since I'm lazy I'll only deal with d >= 8 */ if(d < 8) return -1; /* indicates failure */ /* create the memory surface */ ms = calloc(1, sizeof(memSurface)); ms->width = w; ms->height = h; ms->depth = d; ms->stride = w * (d >> 3); ms->bits = calloc(ms->stride, ms->height); /* register memory surface */ if(!(*registerSurface)((int)ms, &memSurfaceDispatch, &id)) { /* registration failed; bail */ free(ms->bits); free(ms); return -1; } return id; } int memDestroySurface(int id) { memSurface *ms; if(!(*findSurface)(id, &memSurfaceDispatch, (int*) &ms)) return 0; (*unregisterSurface)(id); free(ms->bits); free(ms); return 1; } int memGetSurfaceWidth(int id) { memSurface *ms; if(!(*findSurface)(id, &memSurfaceDispatch, (int*) &ms)) return 0; return ms->width; } int memGetSurfaceHeight(int id) { memSurface *ms; if(!(*findSurface)(id, &memSurfaceDispatch, (int*) &ms)) return 0; return ms->height; } int memGetSurfaceDepth(int id) { memSurface *ms; if(!(*findSurface)(id, &memSurfaceDispatch, (int*) &ms)) return 0; return ms->depth; } int memGetSurfaceBits(int id) { memSurface *ms; if(!(*findSurface)(id, &memSurfaceDispatch, (int*) &ms)) return 0; return (int) ms->bits; } int memInitialize(void) { /* look up the required entry points */ registerSurface = (fn_ioRegisterSurface) interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface","SurfacePlugin"); unregisterSurface = (fn_ioUnregisterSurface) interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface","SurfacePlugin"); findSurface = (fn_ioFindSurface) interpreterProxy->ioLoadFunctionFrom("ioFindSurface","SurfacePlugin"); /* if any of the above fail we won't load the plugin */ if(!registerSurface) return 0; if(!unregisterSurface) return 0; if(!findSurface) return 0; return 1; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FileCopyPlugin/FileCopyPlugin.h ================================================ /* This is a hopefully temporary plugin that provides a platform specific way * to copy files with all the type and status information intact - * rather useful for makefiles, unix shell scripts, Mac resources etc * It will fade away once Squeak has decent file handling. */ int sqCopyFilesizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize); int sqCopyDirectorysizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize); ================================================ FILE: vm/src/from_squeak/Cross/plugins/FilePlugin/FilePlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker.oscog-eem.97 uuid: e5a88d4c-b638-4228-8a1d-39d5af02c8d8 from FilePlugin VMMaker.oscog-eem.97 uuid: e5a88d4c-b638-4228-8a1d-39d5af02c8d8 */ static char __buildInfo[] = "FilePlugin VMMaker.oscog-eem.97 uuid: e5a88d4c-b638-4228-8a1d-39d5af02c8d8 " __DATE__ ; #include #include #include #include #include # include "squeak_adapters.h" /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "FilePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ #define COGMTVM 0 #define DirBadPath 2 #define DirNoMoreEntries 1 #define PrimErrBadArgument 3 #define PrimErrBadIndex 4 #define PrimErrNoMemory 9 #define PrimErrObjectMayMove 14 #define PrimErrUnsupported 7 #define PrimNoErr 0 /*** Function Prototypes ***/ static sqInt asciiDirectoryDelimiter(void); EXPORT(sqInt) fileOpenNamesizewritesecure(char * nameIndex, sqInt nameSize, sqInt writeFlag, sqInt secureFlag); sqInt fileRecordSize(void); SQFile * fileValueOf(sqInt objectPointer); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); EXPORT(sqInt) getThisSession(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt makeDirEntryNamesizecreateDatemodDateisDirfileSize(char * entryName, sqInt entryNameSize, sqInt createDate, sqInt modifiedDate, sqInt dirFlag, squeakFileOffsetType fileSize); EXPORT(sqInt) moduleUnloaded(char * aModuleName); static sqInt msg(char * s); EXPORT(sqInt) primitiveDirectoryCreate(void); EXPORT(sqInt) primitiveDirectoryDelete(void); EXPORT(sqInt) primitiveDirectoryDelimitor(void); EXPORT(sqInt) primitiveDirectoryEntry(void); EXPORT(sqInt) primitiveDirectoryGetMacTypeAndCreator(void); EXPORT(sqInt) primitiveDirectoryLookup(void); EXPORT(sqInt) primitiveDirectorySetMacTypeAndCreator(void); EXPORT(sqInt) primitiveDisableFileAccess(void); EXPORT(sqInt) primitiveFileAtEnd(void); EXPORT(sqInt) primitiveFileClose(void); EXPORT(sqInt) primitiveFileDelete(void); EXPORT(sqInt) primitiveFileFlush(void); EXPORT(sqInt) primitiveFileGetPosition(void); EXPORT(sqInt) primitiveFileOpen(void); EXPORT(sqInt) primitiveFileRead(void); EXPORT(sqInt) primitiveFileRename(void); EXPORT(sqInt) primitiveFileSetPosition(void); EXPORT(sqInt) primitiveFileSize(void); EXPORT(sqInt) primitiveFileStdioHandles(void); EXPORT(sqInt) primitiveFileTruncate(void); EXPORT(sqInt) primitiveFileWrite(void); EXPORT(sqInt) primitiveHasFileAccess(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); EXPORT(sqInt) setMacFileTypeAndCreator(char * fileName, char * typeString, char * creatorString); EXPORT(sqInt) shutdownModule(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FilePlugin VMMaker.oscog-eem.97 (i)" #else "FilePlugin VMMaker.oscog-eem.97 (e)" #endif ; static void * sCCPfn; static void * sCDFfn; static void * sCDPfn; static void * sCGFTfn; static void * sCLPfn; static void * sCOFfn; static void * sCRFfn; static void * sCSFTfn; static void * sDFAfn; static void * sHFAfn; static sqInt asciiDirectoryDelimiter(void) { return dir_Delimitor(); } /* Open the named file, possibly checking security. Answer the file oop. */ EXPORT(sqInt) fileOpenNamesizewritesecure(char * nameIndex_xxx_dmu, sqInt nameSize, sqInt writeFlag, sqInt secureFlag) { SQFile * file; sqInt fileOop; sqInt okToOpen; char* nameIndex_xxx_dmu1 = malloc(nameSize); memmove(nameIndex_xxx_dmu1, nameIndex_xxx_dmu, nameSize); fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(SQFile)); /* begin fileValueOf: */ if (!((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->arrayValueOf(fileOop); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { if (secureFlag) { if (sCOFfn != 0) { okToOpen = ((sqInt (*) (char *, sqInt, sqInt)) sCOFfn)(nameIndex_xxx_dmu1, nameSize, writeFlag); if (!(okToOpen)) { interpreterProxy->primitiveFail(); } } } } if (!(interpreterProxy->failed())) { sqFileOpen(file, nameIndex_xxx_dmu1, nameSize, writeFlag); } free(nameIndex_xxx_dmu1); return fileOop; } /* Return the size of a Smalltalk file record in bytes. */ sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the file record within the given Smalltalk object, or nil if objectPointer is not a file record. */ SQFile * fileValueOf(sqInt objectPointer) { if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); return null; } return interpreterProxy->firstIndexableField(objectPointer); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } /* Exported entry point for the VM. Only used by AsynchFilePlugin and needs to be reowrked now we have a VM global session Id capability */ EXPORT(sqInt) getThisSession(void) { return sqFileThisSession(); } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { sCCPfn = interpreterProxy->ioLoadFunctionFrom("secCanCreatePathOfSize", "SecurityPlugin"); sCDPfn = interpreterProxy->ioLoadFunctionFrom("secCanDeletePathOfSize", "SecurityPlugin"); sCGFTfn = interpreterProxy->ioLoadFunctionFrom("secCanGetFileTypeOfSize", "SecurityPlugin"); sCLPfn = interpreterProxy->ioLoadFunctionFrom("secCanListPathOfSize", "SecurityPlugin"); sCSFTfn = interpreterProxy->ioLoadFunctionFrom("secCanSetFileTypeOfSize", "SecurityPlugin"); sDFAfn = interpreterProxy->ioLoadFunctionFrom("secDisableFileAccess", "SecurityPlugin"); sCDFfn = interpreterProxy->ioLoadFunctionFrom("secCanDeleteFileOfSize", "SecurityPlugin"); sCOFfn = interpreterProxy->ioLoadFunctionFrom("secCanOpenFileOfSizeWritable", "SecurityPlugin"); sCRFfn = interpreterProxy->ioLoadFunctionFrom("secCanRenameFileOfSize", "SecurityPlugin"); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); return sqFileInit(); } static sqInt makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, sqInt entryNameSize, sqInt createDate, sqInt modifiedDate, sqInt dirFlag, squeakFileOffsetType fileSize) { sqInt createDateOop; sqInt fileSizeOop; sqInt i; sqInt modDateOop; sqInt nameString; sqInt results; char *stringPtr; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 5)); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), entryNameSize)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(createDate)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(modifiedDate)); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor(fileSize)); fileSizeOop = interpreterProxy->popRemappableOop(); modDateOop = interpreterProxy->popRemappableOop(); createDateOop = interpreterProxy->popRemappableOop(); nameString = interpreterProxy->popRemappableOop(); /* copy name into Smalltalk string */ results = interpreterProxy->popRemappableOop(); stringPtr = interpreterProxy->firstIndexableField(nameString); for (i = 0; i <= (entryNameSize - 1); i += 1) { stringPtr[i] = (entryName[i]); } interpreterProxy->storePointerofObjectwithValue(0, results, nameString); interpreterProxy->storePointerofObjectwithValue(1, results, createDateOop); interpreterProxy->storePointerofObjectwithValue(2, results, modDateOop); if (dirFlag) { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->trueObject()); } else { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->falseObject()); } interpreterProxy->storePointerofObjectwithValue(4, results, fileSizeOop); return results; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SecurityPlugin")) == 0) { sCCPfn = (sCDPfn = (sCGFTfn = (sCLPfn = (sCSFTfn = (sDFAfn = (sCDFfn = (sCOFfn = (sCRFfn = (sHFAfn = 0))))))))); } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveDirectoryCreate(void) { sqInt dirName; char * dirNameIndex; sqInt dirNameSize; sqInt okToCreate; dirName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(dirName))) { return interpreterProxy->primitiveFail(); } dirNameIndex = interpreterProxy->firstIndexableField(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ dirNameSize = interpreterProxy->byteSizeOf(dirName); if (sCCPfn != 0) { okToCreate = ((sqInt (*)(char *, sqInt))sCCPfn)(dirNameIndex, dirNameSize); if (!(okToCreate)) { return interpreterProxy->primitiveFail(); } } if (!(dir_Create(dirNameIndex, dirNameSize))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDirectoryDelete(void) { sqInt dirName; char * dirNameIndex; sqInt dirNameSize; sqInt okToDelete; dirName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(dirName))) { return interpreterProxy->primitiveFail(); } dirNameIndex = interpreterProxy->firstIndexableField(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ dirNameSize = interpreterProxy->byteSizeOf(dirName); if (sCDPfn != 0) { okToDelete = ((sqInt (*)(char *, sqInt))sCDPfn)(dirNameIndex, dirNameSize); if (!(okToDelete)) { return interpreterProxy->primitiveFail(); } } if (!(dir_Delete(dirNameIndex, dirNameSize))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDirectoryDelimitor(void) { sqInt ascii; ascii = asciiDirectoryDelimiter(); if (!((ascii >= 0) && (ascii <= 255))) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(1, interpreterProxy->fetchPointerofObject(ascii, interpreterProxy->characterTable())); // OK xxx_dmu } /* Two arguments - directory path, and simple file name; returns an array (see primitiveDirectoryLookup) describing the file or directory, or nil if it does not exist. Primitive fails if the outer path does not identify a readable directory. (This is a lookup-by-name variant of primitiveDirectoryLookup.) */ EXPORT(sqInt) primitiveDirectoryEntry(void) { sqInt createDate; sqInt dirFlag; char entryName[256]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt modifiedDate; sqInt okToList; sqInt pathName; char *pathNameIndex; sqInt pathNameSize; char *reqNameIndex; sqInt reqNameSize; sqInt requestedName; sqInt status; requestedName = interpreterProxy->stackValue(0); pathName = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(pathName))) { return interpreterProxy->primitiveFail(); } pathNameIndex = interpreterProxy->firstIndexableField(pathName); pathNameSize = interpreterProxy->byteSizeOf(pathName); reqNameIndex = interpreterProxy->firstIndexableField(requestedName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ reqNameSize = interpreterProxy->byteSizeOf(requestedName); if (sCLPfn != 0) { okToList = ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize); } else { okToList = 1; } if (okToList) { status = dir_EntryLookup(pathNameIndex, pathNameSize, reqNameIndex, reqNameSize, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize); } else { status = DirNoMoreEntries; } if (interpreterProxy->failed()) { return null; } if (status == DirNoMoreEntries) { interpreterProxy->popthenPush(3, interpreterProxy->nilObject()); return null; } if (status == DirBadPath) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(3, makeDirEntryNamesizecreateDatemodDateisDirfileSize(entryName, entryNameSize, createDate, modifiedDate, dirFlag, fileSize)); } EXPORT(sqInt) primitiveDirectoryGetMacTypeAndCreator(void) { sqInt creatorString; char * creatorStringIndex; sqInt fileName; char *fileNameIndex; sqInt fileNameSize; sqInt okToGet; sqInt typeString; char *typeStringIndex; creatorString = interpreterProxy->stackValue(0); typeString = interpreterProxy->stackValue(1); fileName = interpreterProxy->stackValue(2); if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(fileName))) { return interpreterProxy->primitiveFail(); } creatorStringIndex = interpreterProxy->firstIndexableField(creatorString); typeStringIndex = interpreterProxy->firstIndexableField(typeString); fileNameIndex = interpreterProxy->firstIndexableField(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ fileNameSize = interpreterProxy->byteSizeOf(fileName); if (sCGFTfn != 0) { okToGet = ((sqInt (*)(char *, sqInt))sCGFTfn)(fileNameIndex, fileNameSize); if (!(okToGet)) { return interpreterProxy->primitiveFail(); } } if (!(dir_GetMacFileTypeAndCreator(fileNameIndex, fileNameSize, typeStringIndex, creatorStringIndex))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); } EXPORT(sqInt) primitiveDirectoryLookup(void) { sqInt createDate; sqInt dirFlag; char entryName[256]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt index; sqInt modifiedDate; sqInt okToList; sqInt pathName; char *pathNameIndex; sqInt pathNameSize; sqInt status; index = interpreterProxy->stackIntegerValue(0); pathName = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(pathName))) { return interpreterProxy->primitiveFail(); } pathNameIndex = interpreterProxy->firstIndexableField(pathName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ pathNameSize = interpreterProxy->byteSizeOf(pathName); if (sCLPfn != 0) { okToList = ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize); } else { okToList = 1; } if (okToList) { status = dir_Lookup(pathNameIndex, pathNameSize, index, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize); } else { status = DirNoMoreEntries; } if (interpreterProxy->failed()) { return null; } if (status == DirNoMoreEntries) { interpreterProxy->popthenPush(3, interpreterProxy->nilObject()); return null; } if (status == DirBadPath) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(3, makeDirEntryNamesizecreateDatemodDateisDirfileSize(entryName, entryNameSize, createDate, modifiedDate, dirFlag, fileSize)); } EXPORT(sqInt) primitiveDirectorySetMacTypeAndCreator(void) { sqInt creatorString; char * creatorStringIndex; sqInt fileName; char *fileNameIndex; sqInt fileNameSize; sqInt okToSet; sqInt typeString; char *typeStringIndex; creatorString = interpreterProxy->stackValue(0); typeString = interpreterProxy->stackValue(1); fileName = interpreterProxy->stackValue(2); if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(fileName))) { return interpreterProxy->primitiveFail(); } creatorStringIndex = interpreterProxy->firstIndexableField(creatorString); typeStringIndex = interpreterProxy->firstIndexableField(typeString); fileNameIndex = interpreterProxy->firstIndexableField(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ fileNameSize = interpreterProxy->byteSizeOf(fileName); if (sCSFTfn != 0) { okToSet = ((sqInt (*)(char *, sqInt))sCSFTfn)(fileNameIndex, fileNameSize); if (!(okToSet)) { return interpreterProxy->primitiveFail(); } } if (!(dir_SetMacFileTypeAndCreator(fileNameIndex, fileNameSize,typeStringIndex, creatorStringIndex))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); } /* If the security plugin can be loaded, use it to turn off file access If not, assume it's ok */ EXPORT(sqInt) primitiveDisableFileAccess(void) { if (sDFAfn != 0) { ((sqInt (*)(void))sDFAfn)(); } } EXPORT(sqInt) primitiveFileAtEnd(void) { sqInt atEnd; SQFile * file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { atEnd = sqFileAtEnd(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); interpreterProxy->pushBool(atEnd); } } EXPORT(sqInt) primitiveFileClose(void) { SQFile * file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileClose(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileDelete(void) { char *nameIndex; sqInt namePointer; sqInt nameSize; sqInt okToDelete; namePointer = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(namePointer))) { return interpreterProxy->primitiveFail(); } nameIndex = interpreterProxy->firstIndexableField(namePointer); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ nameSize = interpreterProxy->byteSizeOf(namePointer); if (sCDFfn != 0) { okToDelete = ((sqInt (*)(char *, sqInt))sCDFfn)(nameIndex, nameSize); if (!(okToDelete)) { return interpreterProxy->primitiveFail(); } } sqFileDeleteNameSize(nameIndex, nameSize); if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileFlush(void) { SQFile * file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileFlush(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileGetPosition(void) { SQFile * file; sqInt objectPointer; squeakFileOffsetType position; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { position = sqFileGetPosition(file); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(2, interpreterProxy->positive64BitIntegerFor(position)); } } EXPORT(sqInt) primitiveFileOpen(void) { sqInt filePointer; char * nameIndex; sqInt namePointer; sqInt nameSize; sqInt writeFlag; writeFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); namePointer = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(namePointer))) { return interpreterProxy->primitiveFail(); } nameIndex = interpreterProxy->firstIndexableField(namePointer); nameSize = interpreterProxy->byteSizeOf(namePointer); filePointer = fileOpenNamesizewritesecure(nameIndex, nameSize, writeFlag, 1); if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(3, filePointer); } } EXPORT(sqInt) primitiveFileRead(void) { sqInt array; sqInt bytesRead; size_t count; size_t elementSize; SQFile *file; sqInt objectPointer; sqInt retryCount; size_t startIndex; retryCount = 0; count = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); startIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); while (1) { array = interpreterProxy->stackValue(2); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(3); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if ((interpreterProxy->failed()) || (!(interpreterProxy->isWordsOrBytes(array)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } elementSize = (interpreterProxy->isWords(array) ? (4) : (1)); if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } bytesRead = sqFileReadIntoAt(file, count * elementSize, ((char *) (interpreterProxy->firstIndexableField(array))), (startIndex - 1) * elementSize); if (!(((interpreterProxy->primitiveFailureCode()) == PrimErrObjectMayMove) && (((retryCount += 1)) <= 2))) break; interpreterProxy->tenuringIncrementalGC(); interpreterProxy->primitiveFailFor(PrimNoErr); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(5, (((bytesRead / elementSize) << 1) | 1)); } } EXPORT(sqInt) primitiveFileRename(void) { char * newNameIndex; sqInt newNamePointer; sqInt newNameSize; sqInt okToRename; char *oldNameIndex; sqInt oldNamePointer; sqInt oldNameSize; newNamePointer = interpreterProxy->stackValue(0); oldNamePointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(newNamePointer)) && (interpreterProxy->isBytes(oldNamePointer)))) { return interpreterProxy->primitiveFail(); } newNameIndex = interpreterProxy->firstIndexableField(newNamePointer); newNameSize = interpreterProxy->byteSizeOf(newNamePointer); oldNameIndex = interpreterProxy->firstIndexableField(oldNamePointer); /* If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok */ oldNameSize = interpreterProxy->byteSizeOf(oldNamePointer); if (sCRFfn != 0) { okToRename = ((sqInt (*)(char *, sqInt))sCRFfn)(oldNameIndex, oldNameSize); if (!(okToRename)) { return interpreterProxy->primitiveFail(); } } sqFileRenameOldSizeNewSize(oldNameIndex, oldNameSize, newNameIndex, newNameSize); if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileSetPosition(void) { SQFile *file; squeakFileOffsetType newPosition; sqInt objectPointer; sqInt sz; if (!(((interpreterProxy->stackValue(0)) & 1))) { sz = sizeof(squeakFileOffsetType); if ((interpreterProxy->byteSizeOf(interpreterProxy->stackValue(0))) > sz) { return interpreterProxy->primitiveFail(); } } newPosition = interpreterProxy->positive64BitValueOf(interpreterProxy->stackValue(0)); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileSetPosition(file, newPosition); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileSize(void) { SQFile * file; sqInt objectPointer; squeakFileOffsetType size; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { size = sqFileSize(file); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(2, interpreterProxy->positive64BitIntegerFor(size)); } } /* Answer an Array of file handles for standard in, standard out and standard error, with nil in entries that are unvailable, e.g. because the platform does not provide standard error, etc. Fail if there are no standard i/o facilities on the platform or if the security plugin denies access or if memory runs out. */ EXPORT(sqInt) primitiveFileStdioHandles(void) { SQFile fileRecords[3]; sqInt index; sqInt result; sqInt validMask; if (sHFAfn != 0) { if (!( ((sqInt (*)(void))sHFAfn)())) { return interpreterProxy->primitiveFailFor(PrimErrUnsupported); } } ; validMask = sqFileStdioHandlesInto(fileRecords); if (validMask == 0) { return interpreterProxy->primitiveFailFor(PrimErrUnsupported); } result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); if (result == null) { return interpreterProxy->primitiveFailFor(PrimErrNoMemory); } interpreterProxy->pushRemappableOop(result); for (index = 0; index <= 2; index += 1) { if ((validMask & (1 << index)) != 0) { result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(SQFile)); if (result == null) { interpreterProxy->popRemappableOop(); return interpreterProxy->primitiveFailFor(PrimErrNoMemory); } interpreterProxy->storePointerofObjectwithValue(index, interpreterProxy->topRemappableOop(), result); memcpy(interpreterProxy->firstIndexableField(result), (&(fileRecords[index])), sizeof(SQFile)); } } # if COGMTVM interpreterProxy->fullGC(); # endif /* COGMTVM */ result = interpreterProxy->popRemappableOop(); interpreterProxy->popthenPush(1, result); } /* ftruncate is not an ansi function so we have a macro to point to a suitable platform implementation */ EXPORT(sqInt) primitiveFileTruncate(void) { SQFile * file; sqInt objectPointer; sqInt sz; squeakFileOffsetType truncatePosition; if (!(((interpreterProxy->stackValue(0)) & 1))) { sz = sizeof(squeakFileOffsetType); if ((interpreterProxy->byteSizeOf(interpreterProxy->stackValue(0))) > sz) { return interpreterProxy->primitiveFail(); } } truncatePosition = interpreterProxy->positive64BitValueOf(interpreterProxy->stackValue(0)); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileTruncate(file, truncatePosition); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileWrite(void) { sqInt array; char *arrayIndex; size_t byteSize; sqInt bytesWritten; size_t count; SQFile * file; sqInt objectPointer; size_t startIndex; count = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); startIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); array = interpreterProxy->stackValue(2); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(3); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->isWordsOrBytes(array))) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { /* Note: adjust startIndex for zero-origin indexing */ arrayIndex = interpreterProxy->firstIndexableField(array); bytesWritten = sqFileWriteFromAt(file, count * byteSize, arrayIndex, (startIndex - 1) * byteSize); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(5, (((bytesWritten / byteSize) << 1) | 1)); } } EXPORT(sqInt) primitiveHasFileAccess(void) { sqInt hasAccess; if (sHFAfn != 0) { hasAccess = ((sqInt (*)(void))sHFAfn)(); } else { hasAccess = 1; } interpreterProxy->pop(1); interpreterProxy->pushBool(hasAccess); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Exported entry point for the VM. Needed for image saving only and no-op on anything but Macs. */ EXPORT(sqInt) setMacFileTypeAndCreator(char *fileName, char *typeString, char *creatorString) { return dir_SetMacFileTypeAndCreator(fileName, strlen(fileName), typeString, creatorString); } EXPORT(sqInt) shutdownModule(void) { return sqFileShutdown(); } #ifdef SQUEAK_BUILTIN_PLUGIN void* FilePlugin_exports[][3] = { {"FilePlugin", "fileOpenNamesizewritesecure", (void*)fileOpenNamesizewritesecure}, {"FilePlugin", "getModuleName", (void*)getModuleName}, {"FilePlugin", "getThisSession", (void*)getThisSession}, {"FilePlugin", "initialiseModule", (void*)initialiseModule}, {"FilePlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"FilePlugin", "primitiveDirectoryCreate", (void*)primitiveDirectoryCreate}, {"FilePlugin", "primitiveDirectoryDelete", (void*)primitiveDirectoryDelete}, {"FilePlugin", "primitiveDirectoryDelimitor", (void*)primitiveDirectoryDelimitor}, {"FilePlugin", "primitiveDirectoryEntry", (void*)primitiveDirectoryEntry}, {"FilePlugin", "primitiveDirectoryGetMacTypeAndCreator", (void*)primitiveDirectoryGetMacTypeAndCreator}, {"FilePlugin", "primitiveDirectoryLookup", (void*)primitiveDirectoryLookup}, {"FilePlugin", "primitiveDirectorySetMacTypeAndCreator", (void*)primitiveDirectorySetMacTypeAndCreator}, {"FilePlugin", "primitiveDisableFileAccess", (void*)primitiveDisableFileAccess}, {"FilePlugin", "primitiveFileAtEnd", (void*)primitiveFileAtEnd}, {"FilePlugin", "primitiveFileClose", (void*)primitiveFileClose}, {"FilePlugin", "primitiveFileDelete", (void*)primitiveFileDelete}, {"FilePlugin", "primitiveFileFlush", (void*)primitiveFileFlush}, {"FilePlugin", "primitiveFileGetPosition", (void*)primitiveFileGetPosition}, {"FilePlugin", "primitiveFileOpen", (void*)primitiveFileOpen}, {"FilePlugin", "primitiveFileRead", (void*)primitiveFileRead}, {"FilePlugin", "primitiveFileRename", (void*)primitiveFileRename}, {"FilePlugin", "primitiveFileSetPosition", (void*)primitiveFileSetPosition}, {"FilePlugin", "primitiveFileSize", (void*)primitiveFileSize}, {"FilePlugin", "primitiveFileStdioHandles", (void*)primitiveFileStdioHandles}, {"FilePlugin", "primitiveFileTruncate", (void*)primitiveFileTruncate}, {"FilePlugin", "primitiveFileWrite", (void*)primitiveFileWrite}, {"FilePlugin", "primitiveHasFileAccess", (void*)primitiveHasFileAccess}, {"FilePlugin", "setInterpreter", (void*)setInterpreter}, {"FilePlugin", "setMacFileTypeAndCreator", (void*)setMacFileTypeAndCreator}, {"FilePlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/FilePlugin/FilePlugin.h ================================================ /**************************************************************************** * PROJECT: Common include * FILE: FilePlugin.h * CONTENT: * * AUTHOR: * ADDRESS: * EMAIL: * RCSID: $Id: FilePlugin.h 1283 2005-12-31 00:51:12Z rowledge $ * * 2009-05-15 EEM add stdio flag; reorder SQFile to make it more compact * 2005-03-26 IKP fix unaligned accesses to file member * 2004-06-10 IKP 64-bit cleanliness * 01/22/2002 JMM change off_t to squeakOffsetFileType */ /* File support definitions */ #include "sqMemoryAccess.h" /* squeak file record; see sqFilePrims.c for details */ typedef struct { int sessionID; /* ikp: must be first */ void *file; squeakFileOffsetType fileSize; /* 64-bits we hope. */ char writable; char lastOp; /* 0 = uncommitted, 1 = read, 2 = write */ char lastChar; char isStdioStream; } SQFile; /* file i/o */ sqInt sqFileAtEnd(SQFile *f); sqInt sqFileClose(SQFile *f); sqInt sqFileDeleteNameSize(char* sqFileNameIndex, sqInt sqFileNameSize); squeakFileOffsetType sqFileGetPosition(SQFile *f); sqInt sqFileInit(void); sqInt sqFileShutdown(void); sqInt sqFileOpen(SQFile *f, char* sqFileNameIndex, sqInt sqFileNameSize, sqInt writeFlag); size_t sqFileReadIntoAt(SQFile *f, size_t count, char* byteArrayIndex, size_t startIndex); sqInt sqFileRenameOldSizeNewSize(char* oldNameIndex, sqInt oldNameSize, char* newNameIndex, sqInt newNameSize); sqInt sqFileSetPosition(SQFile *f, squeakFileOffsetType position); squeakFileOffsetType sqFileSize(SQFile *f); sqInt sqFileValid(SQFile *f); size_t sqFileWriteFromAt(SQFile *f, size_t count, char* byteArrayIndex, size_t startIndex); sqInt sqFileFlush(SQFile *f); sqInt sqFileTruncate(SQFile *f,squeakFileOffsetType offset); sqInt sqFileThisSession(void); sqInt sqFileStdioHandlesInto(SQFile files[3]); /* directories */ sqInt dir_Create(char *pathString, sqInt pathStringLength); sqInt dir_Delete(char *pathString, sqInt pathStringLength); sqInt dir_Delimitor(void); sqInt dir_Lookup(char *pathString, sqInt pathStringLength, sqInt index, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile); sqInt dir_PathToWorkingDir(char *pathName, sqInt pathNameMax); sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator); sqInt dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator); ================================================ FILE: vm/src/from_squeak/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c ================================================ /**************************************************************************** * PROJECT: File Interface * FILE: sqFilePluginBasicPrims.c * CONTENT: * * AUTHOR: * ADDRESS: * EMAIL: ] * RCSID: $Id: sqFilePluginBasicPrims.c 1283 2005-12-31 00:51:12Z rowledge $ * * NOTES: See change log below. * 2005-03-26 IKP fix unaligned accesses to file[Size] members * 2004-06-10 IKP 64-bit cleanliness * 1/28/02 Tim remove non-ansi stuff * unistd.h ftello fseeko ftruncate & fileno macro-ise use of sqFTruncate to avoid non-ansi * 1/22/2002 JMM Use squeakFileOffsetType versus off_t * *****************************************************************************/ /* The basic prim code for file operations. See also the platform specific * files typically named 'sq{blah}Directory.c' for details of the directory * handling code. Note that the win32 platform #defines NO_STD_FILE_SUPPORT * and thus bypasses this file */ #include #include "sq.h" #ifndef NO_STD_FILE_SUPPORT #include "FilePlugin.h" /*** The state of a file is kept in the following structure, which is stored directly in a Squeak bytes object. NOTE: The Squeak side is responsible for creating an object with enough room to store sizeof(SQFile) bytes. The session ID is used to detect stale file objects-- files that were still open when an image was written. The file pointer of such files is meaningless. Files are always opened in binary mode; Smalltalk code does (or someday will do) line-end conversion if needed. Writeable files are opened read/write. The stdio spec requires that a positioning operation be done when switching between reading and writing of a read/write filestream. The lastOp field records whether the last operation was a read or write operation, allowing this positioning operation to be done automatically if needed. typedef struct { int sessionID; File *file; squeakFileOffsetType fileSize; //JMM Nov 8th 2001 64bits we hope char writable; char lastOp; // 0 = uncommitted, 1 = read, 2 = write // char lastChar; // one character peek for stdin // char isStdioStream; } SQFile; ***/ /*** Constants ***/ #define UNCOMMITTED 0 #define READ_OP 1 #define WRITE_OP 2 #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif /*** Variables ***/ int thisSession = 0; extern struct VirtualMachine * interpreterProxy; /* Since SQFile instaces are held on the heap in 32-bit-aligned byte arrays we * may need to use memcpy to avoid alignment faults. */ #if DOUBLE_WORD_ALIGNMENT static void setFile(SQFile *f, FILE *file) { void *in= (void *)&file; void *out= (void *)&f->file; memcpy(out, in, sizeof(FILE *)); } #else # define setFile(f,fileptr) ((f)->file = (fileptr)) #endif #if DOUBLE_WORD_ALIGNMENT static void setSize(SQFile *f, squeakFileOffsetType size) { void *in= (void *)&size; void *out= (void *)&f->fileSize; memcpy(out, in, sizeof(squeakFileOffsetType)); } #else # define setSize(f,size) ((f)->fileSize = (size)) #endif #if DOUBLE_WORD_ALIGNMENT static FILE *getFile(SQFile *f) { FILE *file; void *in= (void *)&f->file; void *out= (void *)&file; memcpy(out, in, sizeof(FILE *)); return file; } #else # define getFile(f) ((FILE *)((f)->file)) #endif #if DOUBLE_WORD_ALIGNMENT static squeakFileOffsetType getSize(SQFile *f) { squeakFileOffsetType size; void *in= (void *)&f->fileSize; void *out= (void *)&size; memcpy(out, in, sizeof(squeakFileOffsetType)); return size; } #else # define getSize(f) ((f)->fileSize) #endif #if 0 # define pentry(func) do { int fn = fileno(getFile(f)); if (f->isStdioStream) printf("\n"#func "(%s) %lld %d\n", fn == 0 ? "in" : fn == 1 ? "out" : "err", (long long)ftell(getFile(f)), f->lastChar); } while (0) # define pexit(expr) (f->isStdioStream && printf("\n\t^"#expr " %lld %d\n", (long long)(sqFileValid(f) ? ftell(getFile(f)) : -1), f->lastChar)), expr # define pfail() printf("\tFAIL\n"); #else # define pentry(func) 0 # define pexit(expr) expr # define pfail() 0 #endif sqInt sqFileAtEnd(SQFile *f) { /* Return true if the file's read/write head is at the end of the file. */ if (!sqFileValid(f)) return interpreterProxy->success(false); pentry(sqFileAtEnd); if (f->isStdioStream) return pexit(feof(getFile(f))); return ftell(getFile(f)) == getSize(f); } sqInt sqFileClose(SQFile *f) { /* Close the given file. */ if (!sqFileValid(f)) return interpreterProxy->success(false); fclose(getFile(f)); setFile(f, 0); f->sessionID = 0; f->writable = false; setSize(f, 0); f->lastOp = UNCOMMITTED; return 1; } sqInt sqFileDeleteNameSize(char* sqFileName, sqInt sqFileNameSize) { char cFileName[1000]; int err; if (sqFileNameSize >= 1000) { return interpreterProxy->success(false); } /* copy the file name into a null-terminated C string */ interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cFileName, sqFileName, sqFileNameSize, false); err = remove(cFileName); if (err) { return interpreterProxy->success(false); } return 1; } squeakFileOffsetType sqFileGetPosition(SQFile *f) { /* Return the current position of the file's read/write head. */ squeakFileOffsetType position; if (!sqFileValid(f)) return interpreterProxy->success(false); pentry(sqFileGetPosition); if (f->isStdioStream && !f->writable) return pexit(f->lastChar == EOF ? 0 : 1); position = ftell(getFile(f)); if (position == -1) return interpreterProxy->success(false); return position; } sqInt sqFileInit(void) { /* Create a session ID that is unlikely to be repeated. Zero is never used for a valid session number. Should be called once at startup time. */ #if VM_PROXY_MINOR > 6 thisSession = interpreterProxy->getThisSessionID(); #else thisSession = ioLowResMSecs() + time(NULL); if (thisSession == 0) thisSession = 1; /* don't use 0 */ #endif return 1; } sqInt sqFileShutdown(void) { return 1; } sqInt sqFileOpen(SQFile *f, char* sqFileName, sqInt sqFileNameSize, sqInt writeFlag) { /* Opens the given file using the supplied sqFile structure to record its state. Fails with no side effects if f is already open. Files are always opened in binary mode; Squeak must take care of any line-end character mapping. */ char cFileName[1001]; /* don't open an already open file */ if (sqFileValid(f)) return interpreterProxy->success(false); /* copy the file name into a null-terminated C string */ if (sqFileNameSize > 1000) { return interpreterProxy->success(false); } interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cFileName, sqFileName, sqFileNameSize, true); if (writeFlag) { /* First try to open an existing file read/write: */ setFile(f, fopen(cFileName, "r+b")); if (getFile(f) == NULL) { /* Previous call fails if file does not exist. In that case, try opening it in write mode to create a new, empty file. */ setFile(f, fopen(cFileName, "w+b")); if (getFile(f) != NULL) { char type[4],creator[4]; dir_GetMacFileTypeAndCreator(sqFileName, sqFileNameSize, type, creator); if (strncmp(type,"BINA",4) == 0 || strncmp(type,"????",4) == 0 || *(int *)type == 0 ) dir_SetMacFileTypeAndCreator(sqFileName, sqFileNameSize,"TEXT","R*ch"); } } f->writable = true; } else { setFile(f, fopen(cFileName, "rb")); f->writable = false; } if (getFile(f) == NULL) { f->sessionID = 0; setSize(f, 0); return interpreterProxy->success(false); } else { FILE *file= getFile(f); f->sessionID = thisSession; /* compute and cache file size */ fseek(file, 0, SEEK_END); setSize(f, ftell(file)); fseek(file, 0, SEEK_SET); } f->lastOp = UNCOMMITTED; return 1; } /* * Fill-in files with handles for stdin, stdout and stderr as available and * answer a bit-mask of the availability, 1 corresponding to stdin, 2 to stdout * and 4 to stderr, with 0 on error or unavailablity. */ sqInt sqFileStdioHandlesInto(SQFile files[3]) { #if defined(_IONBF) && 0 if (isatty(fileno(stdin))) # if 0 setvbuf(stdin,0,_IONBF,1); # else setvbuf(stdin,0,_IOFBF,0); # endif #endif files[0].sessionID = thisSession; files[0].file = stdin; files[0].fileSize = 0; files[0].writable = false; files[0].lastOp = READ_OP; files[0].isStdioStream = true; files[0].lastChar = EOF; files[1].sessionID = thisSession; files[1].file = stdout; files[1].fileSize = 0; files[1].writable = true; files[1].isStdioStream = true; files[1].lastChar = EOF; files[1].lastOp = WRITE_OP; files[2].sessionID = thisSession; files[2].file = stderr; files[2].fileSize = 0; files[2].writable = true; files[2].isStdioStream = true; files[2].lastChar = EOF; files[2].lastOp = WRITE_OP; return 7; } size_t sqFileReadIntoAt(SQFile *f, size_t count, char* byteArrayIndex, size_t startIndex) { /* Read count bytes from the given file into byteArray starting at startIndex. byteArray is the address of the first byte of a Squeak bytes object (e.g. String or ByteArray). startIndex is a zero-based index; that is a startIndex of 0 starts writing at the first byte of byteArray. */ char *dst; size_t bytesRead; FILE *file; #if COGMTVM sqInt myThreadIndex; #endif if (!sqFileValid(f)) return interpreterProxy->success(false); pentry(sqFileReadIntoAt); file = getFile(f); if (f->writable) { if (f->isStdioStream) return interpreterProxy->success(false); if (f->lastOp == WRITE_OP) fseek(file, 0, SEEK_CUR); /* seek between writing and reading */ } dst = byteArrayIndex + startIndex; #if COGMTVM if (f->isStdioStream) { if (interpreterProxy->isInMemory((sqInt)f) && interpreterProxy->isYoung((sqInt)f) || interpreterProxy->isInMemory((sqInt)dst) && interpreterProxy->isYoung((sqInt)dst)) { interpreterProxy->primitiveFailFor(PrimErrObjectMayMove); return 0; } myThreadIndex = interpreterProxy->disownVM(DisownVMLockOutFullGC); } #endif do { clearerr(file); bytesRead = fread(dst, 1, count, file); } while (bytesRead <= 0 && ferror(file) && errno == EINTR); #if COGMTVM if (f->isStdioStream) interpreterProxy->ownVM(myThreadIndex); #endif /* support for skipping back 1 character for stdio streams */ if (f->isStdioStream) if (bytesRead > 0) f->lastChar = dst[bytesRead-1]; f->lastOp = READ_OP; return pexit(bytesRead); } sqInt sqFileRenameOldSizeNewSize(char* oldNameIndex, sqInt oldNameSize, char* newNameIndex, sqInt newNameSize) { char cOldName[1000], cNewName[1000]; int err; if ((oldNameSize >= 1000) || (newNameSize >= 1000)) { return interpreterProxy->success(false); } /* copy the file names into null-terminated C strings */ interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cOldName, oldNameIndex, oldNameSize, false); interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cNewName, newNameIndex, newNameSize, false); err = rename(cOldName, cNewName); if (err) { return interpreterProxy->success(false); } return 1; } sqInt sqFileSetPosition(SQFile *f, squeakFileOffsetType position) { /* Set the file's read/write head to the given position. */ if (!sqFileValid(f)) return interpreterProxy->success(false); if (f->isStdioStream) { pentry(sqFileSetPosition); /* support one character of pushback for stdio streams. */ if (!f->writable && f->lastChar != EOF) { squeakFileOffsetType currentPos = f->lastChar == EOF ? 0 : 1; if (currentPos == position) return pexit(1); if (currentPos - 1 == position) { ungetc(f->lastChar, getFile(f)); f->lastChar = EOF; return pexit(1); } } pfail(); return interpreterProxy->success(false); } fseek(getFile(f), position, SEEK_SET); f->lastOp = UNCOMMITTED; return 1; } squeakFileOffsetType sqFileSize(SQFile *f) { /* Return the length of the given file. */ if (!sqFileValid(f)) return interpreterProxy->success(false); if (f->isStdioStream) return interpreterProxy->success(false); return getSize(f); } sqInt sqFileFlush(SQFile *f) { if (!sqFileValid(f)) return interpreterProxy->success(false); pentry(sqFileFlush); fflush(getFile(f)); return 1; } sqInt sqFileTruncate(SQFile *f,squeakFileOffsetType offset) { if (!sqFileValid(f)) return interpreterProxy->success(false); if (sqFTruncate(getFile(f), offset)) return interpreterProxy->success(false); setSize(f, ftell(getFile(f))); return 1; } sqInt sqFileValid(SQFile *f) { return ( (f != NULL) && (getFile(f) != NULL) && (f->sessionID == thisSession)); } size_t sqFileWriteFromAt(SQFile *f, size_t count, char* byteArrayIndex, size_t startIndex) { /* Write count bytes to the given writable file starting at startIndex in the given byteArray. (See comment in sqFileReadIntoAt for interpretation of byteArray and startIndex). */ char *src; size_t bytesWritten; squeakFileOffsetType position; FILE *file; if (!(sqFileValid(f) && f->writable)) return interpreterProxy->success(false); pentry(sqFileWriteFromAt); file = getFile(f); if (f->lastOp == READ_OP) fseek(file, 0, SEEK_CUR); /* seek between reading and writing */ src = byteArrayIndex + startIndex; bytesWritten = fwrite(src, 1, count, file); position = ftell(file); if (position > getSize(f)) { setSize(f, position); /* update file size */ } if (bytesWritten != count) { interpreterProxy->success(false); } f->lastOp = WRITE_OP; return pexit(bytesWritten); } sqInt sqFileThisSession() { return thisSession; } #endif /* NO_STD_FILE_SUPPORT */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/FloatMathPlugin.h ================================================ /* we only declare those functions from fdlibm that we actually use and avoid including fdlibm.h alltogether as it conflicts with math.h */ /* #define NO_ISNAN -- do NOT define this by default but in command line*/ #ifndef NO_ISNAN /* by default we use fdlibm's isnan() */ extern int isnan(double); #endif extern double __ieee754_sqrt(double); extern double __ieee754_acos(double); extern double __ieee754_acosh(double); extern double __ieee754_asin(double); extern double __ieee754_asinh(double); extern double __ieee754_atan(double); extern double __ieee754_atan2(double,double); extern double __ieee754_atanh(double); extern double __ieee754_cos(double); extern double __ieee754_cosh(double); extern double __ieee754_exp(double); extern double __ieee754_fmod(double,double); extern double __ieee754_modf(double,double*); extern double __ieee754_hypot(double,double); extern double __ieee754_log10(double); extern double __ieee754_log(double); extern double __ieee754_pow(double,double); extern double __ieee754_sin(double); extern double __ieee754_sinh(double); extern double __ieee754_sqrt(double); extern double __ieee754_tan(double); extern double __ieee754_tanh(double); extern double __ieee754_ldexp(double, int); ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/FloatMathPlugin.st ================================================ 'From Croquet1.0beta of 24 March 2006 [latest update: #6665] on 26 March 2006 at 6:00:28 pm'! InterpreterPlugin subclass: #FloatMathPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcCos "Computes acos(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_acos(rcvr)' inSmalltalk: [rcvr arcCos]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcCosH "Computes acosh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_acosh(rcvr)' inSmalltalk: [rcvr arcCosH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcSin "Computes asin(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_asin(rcvr)' inSmalltalk: [rcvr arcSin]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcSinH "Computes asinh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_asinh(rcvr)' inSmalltalk: [rcvr arcSinH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcTan "Computes atan(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_atan(rcvr)' inSmalltalk: [rcvr arcTan]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcTan2 "Computes atan2(receiver, arg)" | rcvr arg result | self export: true. self var: #rcvr type: 'double'. self var: #arg type: 'double'. self var: #result type: 'double'. arg := interpreterProxy stackFloatValue: 0. rcvr := interpreterProxy stackFloatValue: 1. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_atan2(rcvr, arg)' inSmalltalk: [rcvr arcTan: arg]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveArcTanH "Computes atanh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_atanh(rcvr)' inSmalltalk: [rcvr arcTanH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveCos "Computes cos(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_cos(rcvr)' inSmalltalk: [rcvr cos]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:24'! primitiveCosH "Computes cosh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_cosh(rcvr)' inSmalltalk: [rcvr cosH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 11/6/2005 03:01'! primitiveExp "Computes E raised to the receiver power." | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := (self cCode: '__ieee754_exp(rcvr)' inSmalltalk: [rcvr exp]). interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:21'! primitiveFMod "Computes receiver \\ arg" | rcvr arg result | self export: true. self var: #rcvr type: 'double'. self var: #arg type: 'double'. self var: #result type: 'double'. arg := interpreterProxy stackFloatValue: 0. rcvr := interpreterProxy stackFloatValue: 1. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_fmod(rcvr, arg)' inSmalltalk: [rcvr \\ arg]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:21'! primitiveFractionalPart "Computes receiver \\ 1.0" | rcvr result trunc| self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. self var: #trunc type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_modf(rcvr, &trunc)' inSmalltalk: [rcvr fractionPart]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 11/6/2005 16:13'! primitiveHypot "hypot(x,y) returns sqrt(x^2+y^2) with error less than 1 ulps" | rcvr arg result | self export: true. self var: #rcvr type: 'double'. self var: #arg type: 'double'. self var: #result type: 'double'. arg := interpreterProxy stackFloatValue: 0. rcvr := interpreterProxy stackFloatValue: 1. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_hypot(rcvr, arg)' inSmalltalk: [rcvr hypot: arg]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:25'! primitiveLog10 "Computes log10(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. rcvr < 0.0 ifTrue:[^interpreterProxy primitiveFail]. result := self cCode: '__ieee754_log10(rcvr)' inSmalltalk: [rcvr log: 10]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 17:24'! primitiveLogN "Computes log(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. rcvr < 0.0 ifTrue:[^interpreterProxy primitiveFail]. result := self cCode: '__ieee754_log(rcvr)' inSmalltalk: [rcvr ln]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:23'! primitiveRaisedToPower "Computes receiver**arg" | rcvr arg result | self export: true. self var: #rcvr type: 'double'. self var: #arg type: 'double'. self var: #result type: 'double'. arg := interpreterProxy stackFloatValue: 0. rcvr := interpreterProxy stackFloatValue: 1. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_pow(rcvr, arg)' inSmalltalk: [rcvr raisedTo: arg]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:23'! primitiveSin "Computes sin(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_sin(rcvr)' inSmalltalk: [rcvr sin]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:23'! primitiveSinH "Computes sinh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_sinh(rcvr)' inSmalltalk: [rcvr sinH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:22'! primitiveSqrt "Computes sqrt(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. rcvr < 0.0 ifTrue:[^interpreterProxy primitiveFail]. result := self cCode: '__ieee754_sqrt(rcvr)' inSmalltalk: [rcvr sqrt]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:23'! primitiveTan "Computes tan(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_tan(rcvr)' inSmalltalk: [rcvr tan]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 15:23'! primitiveTanH "Computes tanh(receiver)" | rcvr result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. rcvr := interpreterProxy stackFloatValue: 0. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_tanh(rcvr)' inSmalltalk: [rcvr tanH]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! !FloatMathPlugin methodsFor: 'float primitives' stamp: 'ar 3/26/2006 14:06'! primitiveTimesTwoPower "Computes E raised to the receiver power." | rcvr arg result | self export: true. self var: #rcvr type: 'double'. self var: #result type: 'double'. arg := interpreterProxy stackIntegerValue: 0. rcvr := interpreterProxy stackFloatValue: 1. (interpreterProxy failed) ifTrue:[^nil]. result := self cCode: '__ieee754_ldexp(rcvr, arg)' inSmalltalk: [rcvr timesTwoPower: arg]. interpreterProxy pop: interpreterProxy methodArgumentCount + 1. interpreterProxy pushFloat: result.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FloatMathPlugin class instanceVariableNames: ''! !FloatMathPlugin class methodsFor: 'as yet unclassified' stamp: 'ar 11/6/2005 02:48'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !FloatMathPlugin class methodsFor: 'as yet unclassified' stamp: 'ar 11/6/2005 16:20'! requiresCrossPlatformFiles "default is ok for most, any plugin needing platform specific files must say so" ^true! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/FloatMathPluginTests.st ================================================ 'From Croquet1.0beta of 24 March 2006 [latest update: #6665] on 26 March 2006 at 6:00:26 pm'! TestCase subclass: #FloatMathPluginTests instanceVariableNames: 'random' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !FloatMathPluginTests commentStamp: '' prior: 0! FloatMathPluginTests buildSuite run.! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 16:52'! makeLargeTestData "self basicNew makeLargeTestData" self makeTestData: 'sin-large.dat' using:[:f| self sin: f] seed: 432567 rounds: 1000000. self makeTestData: 'log-large.dat' using:[:f| self ln: f abs] seed: 432567 rounds: 1000000. self makeTestData: 'sqrt-large.dat' using:[:f| self sqrt: f abs] seed: 432567 rounds: 1000000. self makeTestData: 'atan-large.dat' using:[:f| self arcTan: f] seed: 432567 rounds: 1000000. self makeTestData: 'exp-large.dat' using:[:f| self exp: f] seed: 432567 rounds: 1000000. ! ! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 16:52'! makeSmallTestData "self basicNew makeSmallTestData" self makeTestData: 'sin-small.dat' using:[:f| self sin: f] seed: 321567 rounds: 10000. self makeTestData: 'log-small.dat' using:[:f| self ln: f abs] seed: 321567 rounds: 10000. self makeTestData: 'sqrt-small.dat' using:[:f| self sqrt: f abs] seed: 321567 rounds: 10000. self makeTestData: 'atan-small.dat' using:[:f| self arcTan: f] seed: 321567 rounds: 10000. self makeTestData: 'exp-small.dat' using:[:f| self exp: f] seed: 321567 rounds: 10000. ! ! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 16:11'! makeTestData: fileName using: aBlock seed: seed rounds: rounds | bytes out float result | bytes := ByteArray new: 8. out := FileStream newFileNamed: fileName. [ out binary. out nextNumber: 4 put: rounds. out nextNumber: 4 put: seed. random := Random seed: seed. float := Float basicNew: 2. 'Creating test data for: ', fileName displayProgressAt: Sensor cursorPoint from: 1 to: rounds during:[:bar| 1 to: rounds do:[:i| i \\ 10000 = 0 ifTrue:[bar value: i]. [1 to: 8 do:[:j| bytes at: j put: (random nextInt: 256)-1]. float basicAt: 1 put: (bytes unsignedLongAt: 1 bigEndian: true). float basicAt: 2 put: (bytes unsignedLongAt: 5 bigEndian: true). float isNaN] whileTrue. result := aBlock value: float. out nextNumber: 4 put: (result basicAt: 1). out nextNumber: 4 put: (result basicAt: 2). ]. ]. ] ensure:[out close]. ! ! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 16:58'! runTest: aBlock | bytes out float result | bytes := ByteArray new: 8. out := WriteStream on: ByteArray new. float := Float basicNew: 2. 1 to: 10000 do:[:i| [1 to: 8 do:[:j| bytes at: j put: (random nextInt: 256)-1]. float basicAt: 1 put: (bytes unsignedLongAt: 1 bigEndian: true). float basicAt: 2 put: (bytes unsignedLongAt: 5 bigEndian: true). float isNaN] whileTrue. result := aBlock value: float. out nextNumber: 4 put: (result basicAt: 1). out nextNumber: 4 put: (result basicAt: 2). ]. ^self md5HashMessage: out contents.! ! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 14:38'! setUp random := Random seed: 253213.! ! !FloatMathPluginTests methodsFor: 'running' stamp: 'ar 3/26/2006 16:53'! verifyTestData: fileName using: aBlock | rounds seed bytes float result in expected count bits | in := [FileStream readOnlyFileNamed: fileName] on: FileDoesNotExistException do:[:ex| ex return: nil]. in ifNil:[^nil]. count := bits := 0. bytes := ByteArray new: 8. [ in binary. rounds := in nextNumber: 4. seed := in nextNumber: 4. random := Random seed: seed. float := Float basicNew: 2. expected := Float basicNew: 2. 'Verifying test data from: ', fileName displayProgressAt: Sensor cursorPoint from: 1 to: rounds during:[:bar| 1 to: rounds do:[:i| i \\ 10000 = 0 ifTrue:[bar value: i]. [1 to: 8 do:[:j| bytes at: j put: (random nextInt: 256)-1]. float basicAt: 1 put: (bytes unsignedLongAt: 1 bigEndian: true). float basicAt: 2 put: (bytes unsignedLongAt: 5 bigEndian: true). float isNaN] whileTrue. result := aBlock value: float. expected basicAt: 1 put: (in nextNumber: 4). expected basicAt: 2 put: (in nextNumber: 4). ((expected isNaN and:[result isNaN]) or:[expected = result]) ifFalse:[ (expected basicAt: 1) = (result basicAt: 1) ifFalse:[self error: 'Verification failure']. count := count + 1. bits := bits + ((expected basicAt: 2) - (result basicAt: 2)) abs. ]. ]. ]. ] ensure:[in close]. self assert: count = 0. "all the same"! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:42'! testArcCos | hash | hash := self runTest:[:f| self arcCos: f]. self assert: hash = 175366936335278026567589867783483480383! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:44'! testArcCosH | hash | hash := self runTest:[:f| self arcCosH: f]. self assert: hash = 6724426144112251941037505276242428134! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:43'! testArcSin | hash | hash := self runTest:[:f| self arcSin: f]. self assert: hash = 27372132577303862731837100895783885417! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:42'! testArcSinH | hash | hash := self runTest:[:f| self arcSinH: f]. self assert: hash = 255911863578190171815115260235896145802! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:43'! testArcTan | hash | hash := self runTest:[:f| self arcTan: f]. self assert: hash = 17311773710959114634056077345168823659! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:51'! testArcTan2 | hash | hash := self runTest:[:f| self arcTan2: f with: f]. self assert: hash = 287068347279655848752274030373495709564! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:44'! testArcTanH | hash | hash := self runTest:[:f| self arcTanH: f]. self assert: hash = 295711907369004359459882231908879164929! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:45'! testCos | hash | hash := self runTest:[:f| self cos: f]. self assert: hash = 110207739557966732640546618158077332978! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:42'! testCosH | hash | hash := self runTest:[:f| self cosH: f]. self assert: hash = 139309299067563830037108641802292492276! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:27'! testExp | hash | hash := self runTest:[:f| self exp: f]. self assert: hash = 264681209343177480335132131244505189510! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:27'! testFloatAt | hash flt | flt := FloatArray new: 1. hash := self runTest:[:f| flt at: 1 put: f. flt at: 1]. self assert: hash = 80498428122197125691266588764018905399! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:27'! testFraction | hash | hash := self runTest:[:f| self fractionPart: f]. self assert: hash = 320444785026869345695277323179170692004! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:51'! testHypot | hash | hash := self runTest:[:f| self hypot: f with: f+1]. self assert: hash = 217113721886532765853628735806816720346! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:27'! testLog | hash | hash := self runTest:[:f| self ln: f abs]. self assert: hash = 24389651894375564945708989023746058645! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:42'! testLog10 | hash | hash := self runTest:[:f| self log10: f abs]. self assert: hash = 135564553959509933253581837789050718785! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:44'! testSin | hash | hash := self runTest:[:f| self sin: f]. self assert: hash = 290162321010315440569513182938961037473! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:44'! testSinH | hash | hash := self runTest:[:f| self sinH: f]. self assert: hash = 146029709156303766079448006055284064911! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:28'! testSqrt | hash | hash := self runTest:[:f| self sqrt: f abs]. self assert: hash = 112236588358122834093969606123302196127! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:45'! testTan | hash | hash := self runTest:[:f| self tan: f]. self assert: hash = 169918898922109300293069449425089094780! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 17:43'! testTanH | hash | hash := self runTest:[:f| self tanH: f]. self assert: hash = 15738508136206638425252880299326548123! ! !FloatMathPluginTests methodsFor: 'tests' stamp: 'ar 3/26/2006 14:28'! testTimesTwoPower | hash | hash := self runTest:[:f| self timesTwoPower: f with: (random nextInt: 200) - 100]. self assert: hash = 278837335583284459890979576373223649870.! ! !FloatMathPluginTests methodsFor: 'data' stamp: 'ar 3/26/2006 17:56'! testAtanData self verifyTestData: 'atan-small.dat' using:[:f| self arcTan: f]. self verifyTestData: 'atan-large.dat' using:[:f| self arcTan: f]. ! ! !FloatMathPluginTests methodsFor: 'data' stamp: 'ar 3/26/2006 17:56'! testExpData self verifyTestData: 'exp-small.dat' using:[:f| self exp: f]. self verifyTestData: 'exp-large.dat' using:[:f| self exp: f]. ! ! !FloatMathPluginTests methodsFor: 'data' stamp: 'ar 3/26/2006 17:56'! testLogData self verifyTestData: 'log-small.dat' using:[:f| self ln: f abs]. self verifyTestData: 'log-large.dat' using:[:f| self ln: f abs]. ! ! !FloatMathPluginTests methodsFor: 'data' stamp: 'ar 3/26/2006 17:56'! testSinData self verifyTestData: 'sin-small.dat' using:[:f| self sin: f]. self verifyTestData: 'sin-large.dat' using:[:f| self sin: f]. ! ! !FloatMathPluginTests methodsFor: 'data' stamp: 'ar 3/26/2006 17:56'! testSqrtData self verifyTestData: 'sqrt-small.dat' using:[:f| self sqrt: f abs]. self verifyTestData: 'sqrt-large.dat' using:[:f| self sqrt: f abs].! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:34'! arcCosH: f ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:34'! arcCos: f ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:34'! arcSinH: f ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:34'! arcSin: f ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:35'! arcTan2: value with: arg ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:35'! arcTanH: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! arcTan: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:35'! cosH: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:35'! cos: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! exp: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! fractionPart: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:36'! hypot: x with: y ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:24'! ln: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:41'! log10: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:37'! sinH: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! sin: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! sqrt: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:37'! tanH: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 17:37'! tan: value ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'math' stamp: 'ar 3/26/2006 14:29'! timesTwoPower: f with: arg ^self primitiveFailed! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! md5HashMessage: aStringOrByteArray ^ self md5HashStream: (ReadStream on: aStringOrByteArray asByteArray) ! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! md5HashStream: aStream | start buffer bytes sz n words hash large | hash := Array with: 16r67452301 with: 16rEFCDAB89 with: 16r98BADCFE with: 16r10325476. words := Array new: 16. buffer := ByteArray new: 64. start _ aStream position. [aStream atEnd] whileFalse: [ bytes _ aStream nextInto: buffer. (bytes size < 64 or:[aStream atEnd]) ifTrue:[ sz := bytes size. buffer replaceFrom: 1 to: sz with: bytes startingAt: 1. buffer from: sz+1 to: buffer size put: 0. sz < 56 ifTrue:[ buffer at: sz + 1 put: 128. "trailing bit" ] ifFalse:[ "not enough room for the length, so just pad this one, then..." sz < 64 ifTrue:[buffer at: sz + 1 put: 128]. 1 to: 16 do:[:i| words at: i put: (buffer unsignedLongAt: i*4-3 bigEndian: false)]. self md5Transform: words hash: hash. "process one additional block of padding ending with the length" buffer atAllPut: 0. sz = 64 ifTrue: [buffer at: 1 put: 128]. ]. "Fill in the final 8 bytes with the 64-bit length in bits." n _ (aStream position - start) * 8. 7 to: 0 by: -1 do:[:i| buffer at: (buffer size - i) put: ((n bitShift: 7-i*-8) bitAnd: 255)]. ]. 1 to: 16 do:[:i| words at: i put: (buffer unsignedLongAt: i*4-3 bigEndian: false)]. self md5Transform: words hash: hash. ]. bytes := ByteArray new: 16. bytes unsignedLongAt: 1 put: (hash at: 4) bigEndian: true. bytes unsignedLongAt: 5 put: (hash at: 3) bigEndian: true. bytes unsignedLongAt: 9 put: (hash at: 2) bigEndian: true. bytes unsignedLongAt: 13 put: (hash at: 1) bigEndian: true. large := LargePositiveInteger new: 16. 1 to: 16 do:[:i| large digitAt: i put: (bytes at: i)]. ^large normalize! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! md5Transform: in hash: hash "This adds the incoming words to the existing hash" | a b c d | a := hash at: 1. b := hash at: 2. c := hash at: 3. d := hash at: 4. a := self step1: a x: b y: c z: d data: (in at: 1) add: 16rD76AA478 shift: 7. d := self step1: d x: a y: b z: c data: (in at: 2) add: 16rE8C7B756 shift: 12. c := self step1: c x: d y: a z: b data: (in at: 3) add: 16r242070DB shift: 17. b := self step1: b x: c y: d z: a data: (in at: 4) add: 16rC1BDCEEE shift: 22. a := self step1: a x: b y: c z: d data: (in at: 5) add: 16rF57C0FAF shift: 7. d := self step1: d x: a y: b z: c data: (in at: 6) add: 16r4787C62A shift: 12. c := self step1: c x: d y: a z: b data: (in at: 7) add: 16rA8304613 shift: 17. b := self step1: b x: c y: d z: a data: (in at: 8) add: 16rFD469501 shift: 22. a := self step1: a x: b y: c z: d data: (in at: 9) add: 16r698098D8 shift: 7. d := self step1: d x: a y: b z: c data: (in at: 10) add: 16r8B44F7AF shift: 12. c := self step1: c x: d y: a z: b data: (in at: 11) add: 16rFFFF5BB1 shift: 17. b := self step1: b x: c y: d z: a data: (in at: 12) add: 16r895CD7BE shift: 22. a := self step1: a x: b y: c z: d data: (in at: 13) add: 16r6B901122 shift: 7. d := self step1: d x: a y: b z: c data: (in at: 14) add: 16rFD987193 shift: 12. c := self step1: c x: d y: a z: b data: (in at: 15) add: 16rA679438E shift: 17. b := self step1: b x: c y: d z: a data: (in at: 16) add: 16r49B40821 shift: 22. a := self step2: a x: b y: c z: d data: (in at: 2) add: 16rF61E2562 shift: 5. d := self step2: d x: a y: b z: c data: (in at: 7) add: 16rC040B340 shift: 9. c := self step2: c x: d y: a z: b data: (in at: 12) add: 16r265E5A51 shift: 14. b := self step2: b x: c y: d z: a data: (in at: 1) add: 16rE9B6C7AA shift: 20. a := self step2: a x: b y: c z: d data: (in at: 6) add: 16rD62F105D shift: 5. d := self step2: d x: a y: b z: c data: (in at: 11) add: 16r02441453 shift: 9. c := self step2: c x: d y: a z: b data: (in at: 16) add: 16rD8A1E681 shift: 14. b := self step2: b x: c y: d z: a data: (in at: 5) add: 16rE7D3FBC8 shift: 20. a := self step2: a x: b y: c z: d data: (in at: 10) add: 16r21E1CDE6 shift: 5. d := self step2: d x: a y: b z: c data: (in at: 15) add: 16rC33707D6 shift: 9. c := self step2: c x: d y: a z: b data: (in at: 4) add: 16rF4D50D87 shift: 14. b := self step2: b x: c y: d z: a data: (in at: 9) add: 16r455A14ED shift: 20. a := self step2: a x: b y: c z: d data: (in at: 14) add: 16rA9E3E905 shift: 5. d := self step2: d x: a y: b z: c data: (in at: 3) add: 16rFCEFA3F8 shift: 9. c := self step2: c x: d y: a z: b data: (in at: 8) add: 16r676F02D9 shift: 14. b := self step2: b x: c y: d z: a data: (in at: 13) add: 16r8D2A4C8A shift: 20. a := self step3: a x: b y: c z: d data: (in at: 6) add: 16rFFFA3942 shift: 4. d := self step3: d x: a y: b z: c data: (in at: 9) add: 16r8771F681 shift: 11. c := self step3: c x: d y: a z: b data: (in at: 12) add: 16r6D9D6122 shift: 16. b := self step3: b x: c y: d z: a data: (in at: 15) add: 16rFDE5380C shift: 23. a := self step3: a x: b y: c z: d data: (in at: 2) add: 16rA4BEEA44 shift: 4. d := self step3: d x: a y: b z: c data: (in at: 5) add: 16r4BDECFA9 shift: 11. c := self step3: c x: d y: a z: b data: (in at: 8) add: 16rF6BB4B60 shift: 16. b := self step3: b x: c y: d z: a data: (in at: 11) add: 16rBEBFBC70 shift: 23. a := self step3: a x: b y: c z: d data: (in at: 14) add: 16r289B7EC6 shift: 4. d := self step3: d x: a y: b z: c data: (in at: 1) add: 16rEAA127FA shift: 11. c := self step3: c x: d y: a z: b data: (in at: 4) add: 16rD4EF3085 shift: 16. b := self step3: b x: c y: d z: a data: (in at: 7) add: 16r04881D05 shift: 23. a := self step3: a x: b y: c z: d data: (in at: 10) add: 16rD9D4D039 shift: 4. d := self step3: d x: a y: b z: c data: (in at: 13) add: 16rE6DB99E5 shift: 11. c := self step3: c x: d y: a z: b data: (in at: 16) add: 16r1FA27CF8 shift: 16. b := self step3: b x: c y: d z: a data: (in at: 3) add: 16rC4AC5665 shift: 23. a := self step4: a x: b y: c z: d data: (in at: 1) add: 16rF4292244 shift: 6. d := self step4: d x: a y: b z: c data: (in at: 8) add: 16r432AFF97 shift: 10. c := self step4: c x: d y: a z: b data: (in at: 15) add: 16rAB9423A7 shift: 15. b := self step4: b x: c y: d z: a data: (in at: 6) add: 16rFC93A039 shift: 21. a := self step4: a x: b y: c z: d data: (in at: 13) add: 16r655B59C3 shift: 6. d := self step4: d x: a y: b z: c data: (in at: 4) add: 16r8F0CCC92 shift: 10. c := self step4: c x: d y: a z: b data: (in at: 11) add: 16rFFEFF47D shift: 15. b := self step4: b x: c y: d z: a data: (in at: 2) add: 16r85845DD1 shift: 21. a := self step4: a x: b y: c z: d data: (in at: 9) add: 16r6FA87E4F shift: 6. d := self step4: d x: a y: b z: c data: (in at: 16) add: 16rFE2CE6E0 shift: 10. c := self step4: c x: d y: a z: b data: (in at: 7) add: 16rA3014314 shift: 15. b := self step4: b x: c y: d z: a data: (in at: 14) add: 16r4E0811A1 shift: 21. a := self step4: a x: b y: c z: d data: (in at: 5) add: 16rF7537E82 shift: 6. d := self step4: d x: a y: b z: c data: (in at: 12) add: 16rBD3AF235 shift: 10. c := self step4: c x: d y: a z: b data: (in at: 3) add: 16r2AD7D2BB shift: 15. b := self step4: b x: c y: d z: a data: (in at: 10) add: 16rEB86D391 shift: 21. a := (a + (hash at: 1)) bitAnd: 16rFFFFFFFF. hash at: 1 put: a. b := (b + (hash at: 2)) bitAnd: 16rFFFFFFFF. hash at: 2 put: b. c := (c + (hash at: 3)) bitAnd: 16rFFFFFFFF. hash at: 3 put: c. d := (d + (hash at: 4)) bitAnd: 16rFFFFFFFF. hash at: 4 put: d. ^hash! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! rotate: value by: amount "Rotate value left by amount" | lowMask highMask | lowMask := (1 bitShift: 32-amount) - 1. highMask := 16rFFFFFFFF - lowMask. ^((value bitAnd: lowMask) bitShift: amount) + ((value bitAnd: highMask) bitShift: amount-32)! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! step1: w x: x y: y z: z data: data add: add shift: s "First step in MD5 transformation" | f result | f := z bitXor: (x bitAnd: (y bitXor: z)). result := w + f + data + add. result := self rotate: result by: s. ^result + x bitAnd: 16rFFFFFFFF! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! step2: w x: x y: y z: z data: data add: add shift: s "First step in MD5 transformation" | f result | f := y bitXor: (z bitAnd: (x bitXor: y)). result := w + f + data + add. result := self rotate: result by: s. ^result + x bitAnd: 16rFFFFFFFF! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! step3: w x: x y: y z: z data: data add: add shift: s "First step in MD5 transformation" | f result | f := (x bitXor: y) bitXor: z. result := w + f + data + add. result := self rotate: result by: s. ^result + x bitAnd: 16rFFFFFFFF! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:19'! step4: w x: x y: y z: z data: data add: add shift: s "First step in MD5 transformation" | f result | f := y bitXor: (x bitOr: (z bitXor: 16rFFFFFFFF)). result := w + f + data + add. result := self rotate: result by: s. ^result + x bitAnd: 16rFFFFFFFF! ! !FloatMathPluginTests methodsFor: 'md5' stamp: 'ar 3/26/2006 15:20'! testMD5 self assert: (self md5HashMessage: 'a') = 16r0CC175B9C0F1B6A831C399E269772661. self assert: (self md5HashMessage: 'abc') = 16r900150983CD24FB0D6963F7D28E17F72. self assert: (self md5HashMessage: 'message digest') = 16rF96B697D7CB7938D525A2F31AAF161D0. self assert: (self md5HashMessage: 'abcdefghijklmnopqrstuvwxyz') = 16rC3FCD3D76192E4007DFB496CCA67E13B. self assert: (self md5HashMessage: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') = 16rD174AB98D277D9F5A5611C2C9F419D9F. self assert: (self md5HashMessage: '12345678901234567890123456789012345678901234567890123456789012345678901234567890') = 16r57EDF4A22BE3C955AC49DA2E2107B67A.! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/acos.c ================================================ #include "ieee754names.h" #include "fdlibm/e_acos.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/acosh.c ================================================ #include "ieee754names.h" #include "fdlibm/e_acosh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/asin.c ================================================ #include "ieee754names.h" #include "fdlibm/e_asin.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/asinh.c ================================================ #include "ieee754names.h" #include "fdlibm/s_asinh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/atan.c ================================================ #include "ieee754names.h" #include "fdlibm/s_atan.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/atan2.c ================================================ #include "ieee754names.h" #include "fdlibm/e_atan2.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/atanh.c ================================================ #include "ieee754names.h" #include "fdlibm/e_atanh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/copysign.c ================================================ #include "ieee754names.h" #include "fdlibm/s_copysign.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/cos.c ================================================ #include "ieee754names.h" #include "fdlibm/s_cos.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/cosh.c ================================================ #include "ieee754names.h" #include "fdlibm/e_cosh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/exp.c ================================================ #include "ieee754names.h" #include "fdlibm/e_exp.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/expm1.c ================================================ #include "ieee754names.h" #include "fdlibm/s_expm1.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/MD5 ================================================ -----BEGIN PGP SIGNED MESSAGE----- # netlib-bl master Mon May 17 03:35:14 EDT 2004 # http://cm.bell-labs.com/netlib/crc/netlib-bl.html xqdt0SfICJbYU285K5kg9g changes vXBJ84aVdIHpqtTdjwinqQ configure ydqnyJgYpziE8zrr/WU4/g configure.in P2sEgHh/v3RHTsLuS1UeTw e_acos.c SReAT7diAMhuAtChHm1nLQ e_acosh.c xsqL2/A2cuTbG4ZabFtgQg e_asin.c uXwtBvNUrnsWp2lWS/ZPzg e_atan2.c 7+Zmokqk6yU+4B/dPWLVnQ e_atanh.c FFRFIVaqeYuPIbZDy+GPLQ e_cosh.c lGljkqn5/mLxl0XkN4fWxQ e_exp.c ladlzVeoGGhd+r/RvPJUsw e_fmod.c WwWDDWUnqoeniw5c6ShWUQ e_gamma.c +rYzLHXdv60VBR9GpEVA7Q e_gamma_r.c BUemgwLOjQ2tpsWv8fQOWA e_hypot.c um0j/BMMHd0mEzOIg/iTIw e_j0.c 023e/9GjB47rNsYlxW9/Ug e_j1.c X2UtLCi/Hg5Xx0ZAiaUHXQ e_jn.c bBStzzLdDSzNsVlhy/Isdw e_lgamma.c pYie2c6jvQAObJMq2IhNGQ e_lgamma_r.c mj6pKYX+E8euiAP6577R4A e_log.c fEuDo4brNfU8HRqvM0syqQ e_log10.c ryT3m0UgTGJarnV+NzNhNQ e_pow.c L/2ye70MqZA7YqsCtgMQlQ e_rem_pio2.c kdemnBPRKpa3661lnjEcyw e_remainder.c DW4MDjGPgkJLg4PBGX5yGg e_scalb.c LiW0gFPaN5JVIuQZW4XbVQ e_sinh.c JPBrE86qzL59qF5PFCDA/Q e_sqrt.c uHfh5HgtlKGibLxJYYBFCg fdlibm.h G21yQjn+xOAex15TPeLfBQ index sDIZFCqsPOqSl9ykcjky8w k_cos.c 1t3fuGir+TOYRAO0N8Chng k_rem_pio2.c 1Fi/fEeHcsIq50vVplKVzQ k_sin.c 1ufaWqW1PRP1cOuPtb7O7A k_standard.c 0axra6/ERRuXJJcCc5js/Q k_tan.c wDXTC07GG4Bd+EnUjk/MVw makefile 0ffZi8Ey9JbRT9vCxp4LLg makefile.in Tw07rtlUiXvlgwzbRb632Q readme WDSYQ245qaKiYXtEn9qSdg s_asinh.c ucf0ncFkne9OW4Uv+CxRrQ s_atan.c w2/WG3x7j7+b9uydji3FZg s_cbrt.c YqCYHnPBw1dDvbYwjWJNbw s_ceil.c JX6gTEPMyjuTQclyjiLC2w s_copysign.c 91ARVh9L6LTc2i9VGu9DSg s_cos.c 0Jwhkbo/6ewEss7CW1PI9w s_erf.c cpq+MFqK2Vi883y8LA/hxA s_expm1.c K6LRiJVYLNzThuQaOyibVA s_fabs.c uvNnsV4Fmj90jAbySXd54w s_finite.c etEc6khe9K27aeE+6ZpW0A s_floor.c 5KDyugUMkjOsPsq6fygPjg s_frexp.c UWvuamu8A+XGSwi9twc/vQ s_ilogb.c /KmGbiWbhyiZCru0HbLUpw s_isnan.c +OZ/WHEZ12FiA8mZ7hk4rA s_ldexp.c g33PLRuQjT5HRX4ZozySGA s_lib_version.c MHsSOIzpsdw4sVVtAu4GTQ s_log1p.c qWJm/3AkemsNi7aF295SGA s_logb.c QGkKHdTmho+2Xbd0rObCmA s_matherr.c Tfmhq38TAJspcNpJT9Tcww s_modf.c k+onjlepmLUH/9xA+Wdqaw s_nextafter.c omWcOHAaAKLjMuuSirX8Lw s_rint.c 6w2X17eamkvE+pCZlPm8Xg s_scalbn.c z93vZw0EQ1IQUSqJMRu/IA s_signgam.c S3OtNFaARNk7TltgUoVs+Q s_significand.c yYuvBWZCWR0Y/YT6pmIr0w s_sin.c LhJVti8VVlaWbptWR88XGg s_tan.c QfLTJ1iGqgC7RhZWHi0PTQ s_tanh.c vR2IBXoLtHZh+GHCV+Iydg w_acos.c ZbhbPlbMYiu8Z1NXaDiPDQ w_acosh.c KsvLAMHSqu1b72p5kYkJyQ w_asin.c ENaJir3y0hZ4yWWKzBs89w w_atan2.c +jLlTCXpNVY6yuncPyfWyw w_atanh.c 84kcBUnnIU16mG+cChPbRA w_cosh.c bjKr6q9UZYgun3LytNO+1A w_exp.c WQG0A3Gk/MlFkjx4h3yw6Q w_fmod.c MNIqntvhf0fvFvKfzcPR1g w_gamma.c TnrF3OPpiAEUymzT0PZiDw w_gamma_r.c OLFqJDwkIZmIF7vm6BQuGQ w_hypot.c cvayKIzuZlCxTj6dLXe+qQ w_j0.c PB3rNmFTtPoMICeJFkAMeg w_j1.c 7qCc7gGMiRIp1GY0UQ3gLg w_jn.c 8URUp8BmBP32s79GRllwdw w_lgamma.c AJyN8jlYXVe1Dwx+w6qlEQ w_lgamma_r.c 8fmXSpy3xt0Mgd+9BkKHRg w_log.c /+qteyYx+IKTmLuv1fxqPQ w_log10.c +o/ImP/JfknQmSxM4TA1ag w_pow.c BkF5AkqkRA4Py2Y1p0bQIA w_remainder.c 77arOaApwrSQngHv26UWrg w_scalb.c SgGvz6WUAuHs90sDA/GDbA w_sinh.c 2aR8vbagrVvvMtXPktM6CQ w_sqrt.c -----BEGIN PGP SIGNATURE----- Version: 2.6.2 iQCVAwUBQKhrNb5pvxO9gjtZAQGFgAP9GkR1sBbpgy/sXcoyIj/LMfystMc5ljYC WeqSep2+0gmE3l/aLWBaEL/ngyVY8fWNV7lll/DKGA4oJBTWtozHhWGl2g8+tb+L afoMIwLTbSMMkB4bPGfZm1MevZmOn5g4WLOHQ3aTPlykkBw8QDgmLm+7cWZrbHao SJ+0t7F/FWI= =aGTu -----END PGP SIGNATURE----- ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/changes ================================================ 21 Oct 2002 bug fix in e_pow.c from "David G Hough at validlab.com" . credit for bug report goes to andrew_johnson@uk.ibm.com test example: ----------------------------- static int fail=0; trypow(x,y,z) double x,y,z; { extern double pow(); double p ; p = pow(x,y); if (p != z) { printf(" pow failure x %e y %e computed %e correct %e \n",x,y,p,z); fail++; return; } if (1/p != 1/z) { printf(" pow failure x %e y %e computed %e correct %e \n",x,y,p,z); fail++; return; } } main() { trypow( 1.0000000001, 1.0000000001E10, 2.7182820535066154); trypow(-1.0000000001, 1.0000000001E10, -2.7182820535066154); trypow(-0.001, 1.0000000001E10, -0.0); trypow(-1000.0, 1.0000000001E10, -1.0/0.0); if (fail == 0) { printf(" fdlibm e_pow.c seems to be current \n"); exit(0); } else { printf(" fdlibm e_pow.c seems to be out of date \n"); exit(1); } } ----------------------------- What's new in FDLIBM 5.3? CONFIGURE To build FDLIBM, edit the supplied Makefile or create a local Makefile by running "sh configure" using the supplied configure script contributed by Nelson Beebe BUGS FIXED 1. e_pow.c incorrect results when x is very close to -1.0 and y is very large, e.g. pow(-1.0000000000000002e+00,4.5035996273704970e+15) = 0 pow(-9.9999999999999978e-01,4.5035996273704970e+15) = 0 Correct results are close to -e and -1/e. 2. k_tan.c error was > 1 ulp target for FDLIBM 5.2: Worst error at least 1.45 ulp at tan(1.7765241907548024E+269) = 1.7733884462610958E+16 5.3: Worst error 0.96 ulp NOT FIXED YET 3. Compiler failure on non-standard code Statements like *(1+(int*)&t1) = 0; are not standard C and cause some optimizing compilers (e.g. GCC) to generate bad code under optimization. These cases are to be addressed in the next release. ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for fdlibm 5.3. # # Report bugs to >. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='fdlibm' PACKAGE_TARNAME='fdlibm' PACKAGE_VERSION='5.3' PACKAGE_STRING='fdlibm 5.3' PACKAGE_BUGREPORT='FDLIBM COMMENTS ' ac_unique_file="e_acos.c" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT AR CHMOD CP RANLIB RM LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures fdlibm 5.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of fdlibm 5.3:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to > _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF fdlibm configure 5.3 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by fdlibm $as_me 5.3, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AR" && break done for ac_prog in chmod do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CHMOD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CHMOD"; then ac_cv_prog_CHMOD="$CHMOD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CHMOD="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CHMOD=$ac_cv_prog_CHMOD if test -n "$CHMOD"; then echo "$as_me:$LINENO: result: $CHMOD" >&5 echo "${ECHO_T}$CHMOD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CHMOD" && break done for ac_prog in cp do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CP"; then ac_cv_prog_CP="$CP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CP="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CP=$ac_cv_prog_CP if test -n "$CP"; then echo "$as_me:$LINENO: result: $CP" >&5 echo "${ECHO_T}$CP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CP" && break done for ac_prog in ranlib echo do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$RANLIB" && break done for ac_prog in /bin/rm rm do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_RM+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $RM in [\\/]* | ?:[\\/]*) ac_cv_path_RM="$RM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi RM=$ac_cv_path_RM if test -n "$RM"; then echo "$as_me:$LINENO: result: $RM" >&5 echo "${ECHO_T}$RM" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$RM" && break done ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then we branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. cat >confdef2opt.sed <<\_ACEOF t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g t quote s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g t quote d : quote s,[ `~#$^&*(){}\\|;'"<>?],\\&,g s,\[,\\&,g s,\],\\&,g s,\$,$$,g p _ACEOF # We use echo to avoid assuming a particular line-breaking character. # The extra dot is to prevent the shell from consuming trailing # line-breaks from the sub-command output. A line-break within # single-quotes doesn't work because, if this script is created in a # platform that uses two characters for line-breaks (e.g., DOS), tr # would break. ac_LF_and_DOT=`echo; echo .` DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` rm -f confdef2opt.sed ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by fdlibm $as_me 5.3, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ fdlibm config.status 5.3 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@AR@,$AR,;t t s,@CHMOD@,$CHMOD,;t t s,@CP@,$CP,;t t s,@RANLIB@,$RANLIB,;t t s,@RM@,$RM,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/configure.in ================================================ dnl Process this file with autoconf to produce a configure script AC_INIT(fdlibm,5.3,[FDLIBM COMMENTS ]) AC_CONFIG_SRCDIR(e_acos.c) dnl Checks for programs AC_PROG_CC AC_CHECK_PROGS(AR, ar) AC_CHECK_PROGS(CHMOD, chmod) AC_CHECK_PROGS(CP, cp) AC_CHECK_PROGS(RANLIB, [ranlib echo]) AC_PATH_PROGS(RM, [/bin/rm rm]) AC_OUTPUT(Makefile) ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_acos.c ================================================ /* @(#)e_acos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_acos(x) * Method : * acos(x) = pi/2 - asin(x) * acos(-x) = pi/2 + asin(x) * For |x|<=0.5 * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) * For x>0.5 * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) * = 2asin(sqrt((1-x)/2)) * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) * = 2f + (2c + 2s*z*R(z)) * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term * for f so that f+c ~ sqrt(z). * For x<-0.5 * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * * Function needed: sqrt */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ #ifdef __STDC__ double __ieee754_acos(double x) #else double __ieee754_acos(x) double x; #endif { double z,p,q,r,w,s,c,df; int hx,ix; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x3ff00000) { /* |x| >= 1 */ if(((ix-0x3ff00000)|__LO(x))==0) { /* |x|==1 */ if(hx>0) return 0.0; /* acos(1) = 0 */ else return pi+2.0*pio2_lo; /* acos(-1)= pi */ } return (x-x)/(x-x); /* acos(|x|>1) is NaN */ } if(ix<0x3fe00000) { /* |x| < 0.5 */ if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ z = x*x; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); r = p/q; return pio2_hi - (x - (pio2_lo-x*r)); } else if (hx<0) { /* x < -0.5 */ z = (one+x)*0.5; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); s = sqrt(z); r = p/q; w = r*s-pio2_lo; return pi - 2.0*(s+w); } else { /* x > 0.5 */ z = (one-x)*0.5; s = sqrt(z); df = s; __LO(df) = 0; c = (z-df*df)/(s+df); p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); r = p/q; w = r*s+c; return 2.0*(df+w); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_acosh.c ================================================ /* @(#)e_acosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_acosh(x) * Method : * Based on * acosh(x) = log [ x + sqrt(x*x-1) ] * we have * acosh(x) := log(x)+ln2, if x is large; else * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. * * Special cases: * acosh(x) is NaN with signal if x<1. * acosh(NaN) is NaN without signal. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.0, ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ #ifdef __STDC__ double __ieee754_acosh(double x) #else double __ieee754_acosh(x) double x; #endif { double t; int hx; hx = __HI(x); if(hx<0x3ff00000) { /* x < 1 */ return (x-x)/(x-x); } else if(hx >=0x41b00000) { /* x > 2**28 */ if(hx >=0x7ff00000) { /* x is inf of NaN */ return x+x; } else return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */ } else if(((hx-0x3ff00000)|__LO(x))==0) { return 0.0; /* acosh(1) = 0 */ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ t=x*x; return __ieee754_log(2.0*x-one/(x+sqrt(t-one))); } else { /* 10.98 * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) * For x<=0.98, let pio4_hi = pio2_hi/2, then * f = hi part of s; * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) * and * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ huge = 1.000e+300, pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ /* coefficient for R(x^2) */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ #ifdef __STDC__ double __ieee754_asin(double x) #else double __ieee754_asin(x) double x; #endif { double t,w,p,q,c,r,s; int hx,ix; hx = __HI(x); ix = hx&0x7fffffff; if(ix>= 0x3ff00000) { /* |x|>= 1 */ if(((ix-0x3ff00000)|__LO(x))==0) /* asin(1)=+-pi/2 with inexact */ return x*pio2_hi+x*pio2_lo; return (x-x)/(x-x); /* asin(|x|>1) is NaN */ } else if (ix<0x3fe00000) { /* |x|<0.5 */ if(ix<0x3e400000) { /* if |x| < 2**-27 */ if(huge+x>one) return x;/* return x with inexact if x!=0*/ } else t = x*x; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); w = p/q; return x+x*w; } /* 1> |x|>= 0.5 */ w = one-fabs(x); t = w*0.5; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); s = sqrt(t); if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ w = p/q; t = pio2_hi-(2.0*(s+s*w)-pio2_lo); } else { w = s; __LO(w) = 0; c = (t-w*w)/(s+w); r = p/q; p = 2.0*s*r-(pio2_lo-2.0*c); q = pio4_hi-2.0*w; t = pio4_hi-(p-q); } if(hx>0) return t; else return -t; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_atan2.c ================================================ /* @(#)e_atan2.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_atan2(y,x) * Method : * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). * 2. Reduce x to positive by (if x and y are unexceptional): * ARG (x+iy) = arctan(y/x) ... if x > 0, * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, * * Special cases: * * ATAN2((anything), NaN ) is NaN; * ATAN2(NAN , (anything) ) is NaN; * ATAN2(+-0, +(anything but NaN)) is +-0 ; * ATAN2(+-0, -(anything but NaN)) is +-pi ; * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; * ATAN2(+-INF,+INF ) is +-pi/4 ; * ATAN2(+-INF,-INF ) is +-3pi/4; * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif tiny = 1.0e-300, zero = 0.0, pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ #ifdef __STDC__ double __ieee754_atan2(double y, double x) #else double __ieee754_atan2(y,x) double y,x; #endif { double z; int k,m,hx,hy,ix,iy; unsigned lx,ly; hx = __HI(x); ix = hx&0x7fffffff; lx = __LO(x); hy = __HI(y); iy = hy&0x7fffffff; ly = __LO(y); if(((ix|((lx|-lx)>>31))>0x7ff00000)|| ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ return x+y; if((hx-0x3ff00000|lx)==0) return __ieee754_atan(y); /* x=1.0 */ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ /* when y = 0 */ if((iy|ly)==0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi+tiny;/* atan(+0,-anything) = pi */ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* when x is INF */ if(ix==0x7ff00000) { if(iy==0x7ff00000) { switch(m) { case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ } } else { switch(m) { case 0: return zero ; /* atan(+...,+INF) */ case 1: return -zero ; /* atan(-...,+INF) */ case 2: return pi+tiny ; /* atan(+...,-INF) */ case 3: return -pi-tiny ; /* atan(-...,-INF) */ } } } /* when y is INF */ if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; /* compute y/x */ k = (iy-ix)>>20; if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ else z=__ieee754_atan(fabs(y/x)); /* safe to do y/x */ switch (m) { case 0: return z ; /* atan(+,+) */ case 1: __HI(z) ^= 0x80000000; return z ; /* atan(-,+) */ case 2: return pi-(z-pi_lo);/* atan(+,-) */ default: /* case 3 */ return (z-pi_lo)-pi;/* atan(-,-) */ } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_atanh.c ================================================ /* @(#)e_atanh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_atanh(x) * Method : * 1.Reduced x to positive by atanh(-x) = -atanh(x) * 2.For x>=0.5 * 1 2x x * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) * 2 1 - x 1 - x * * For x<0.5 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) * * Special cases: * atanh(x) is NaN if |x| > 1 with signal; * atanh(NaN) is that NaN with no signal; * atanh(+-1) is +-INF with signal. * */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0, huge = 1e300; #else static double one = 1.0, huge = 1e300; #endif static double zero = 0.0; #ifdef __STDC__ double __ieee754_atanh(double x) #else double __ieee754_atanh(x) double x; #endif { double t; int hx,ix; unsigned lx; hx = __HI(x); /* high word */ lx = __LO(x); /* low word */ ix = hx&0x7fffffff; if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */ return (x-x)/(x-x); if(ix==0x3ff00000) return x/zero; if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */ __HI(x) = ix; /* x <- |x| */ if(ix<0x3fe00000) { /* x < 0.5 */ t = x+x; t = 0.5*log1p(t+t*x/(one-x)); } else t = 0.5*log1p((x+x)/(one-x)); if(hx>=0) return t; else return -t; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_cosh.c ================================================ /* @(#)e_cosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_cosh(x) * Method : * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 * 1. Replace x by |x| (cosh(x) = cosh(-x)). * 2. * [ exp(x) - 1 ]^2 * 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- * 2*exp(x) * * exp(x) + 1/exp(x) * ln2/2 <= x <= 22 : cosh(x) := ------------------- * 2 * 22 <= x <= lnovft : cosh(x) := exp(x)/2 * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) * ln2ovft < x : cosh(x) := huge*huge (overflow) * * Special cases: * cosh(x) is |x| if x is +INF, -INF, or NaN. * only cosh(0)=1 is exact for finite x. */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0, half=0.5, huge = 1.0e300; #else static double one = 1.0, half=0.5, huge = 1.0e300; #endif #ifdef __STDC__ double __ieee754_cosh(double x) #else double __ieee754_cosh(x) double x; #endif { double t,w; int ix; unsigned lx; /* High word of |x|. */ ix = __HI(x); ix &= 0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3fd62e43) { t = expm1(fabs(x)); w = one+t; if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ return one+(t*t)/(w+w); } /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ if (ix < 0x40360000) { t = __ieee754_exp(fabs(x)); return half*t+half/t; } /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); if (ix<0x408633CE || (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { w = __ieee754_exp(half*fabs(x)); t = half*w; return t*w; } /* |x| > overflowthresold, cosh(x) overflow */ return huge*huge; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_exp.c ================================================ /* @(#)e_exp.c 1.6 04/04/22 */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_exp(x) * Returns the exponential of x. * * Method * 1. Argument reduction: * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2. * * Here r will be represented as r = hi-lo for better * accuracy. * * 2. Approximation of exp(r) by a special rational function on * the interval [0,0.34658]: * Write * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... * We use a special Remes algorithm on [0,0.34658] to generate * a polynomial of degree 5 to approximate R. The maximum error * of this polynomial approximation is bounded by 2**-59. In * other words, * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 * (where z=r*r, and the values of P1 to P5 are listed below) * and * | 5 | -59 * | 2.0+P1*z+...+P5*z - R(z) | <= 2 * | | * The computation of exp(r) thus becomes * 2*r * exp(r) = 1 + ------- * R - r * r*R1(r) * = 1 + r + ----------- (for better accuracy) * 2 - R1(r) * where * 2 4 10 * R1(r) = r - (P1*r + P2*r + ... + P5*r ). * * 3. Scale back to obtain exp(x): * From step 1, we have * exp(x) = 2^k * exp(r) * * Special cases: * exp(INF) is INF, exp(NaN) is NaN; * exp(-INF) is 0, and * for finite argument, only exp(0)=1 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 7.09782712893383973096e+02 then exp(x) overflow * if x < -7.45133219101941108420e+02 then exp(x) underflow * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.0, halF[2] = {0.5,-0.5,}, huge = 1.0e+300, twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ #ifdef __STDC__ double __ieee754_exp(double x) /* default IEEE double exp */ #else double __ieee754_exp(x) /* default IEEE double exp */ double x; #endif { double y,hi,lo,c,t; int k,xsb; unsigned hx; hx = __HI(x); /* high word of x */ xsb = (hx>>31)&1; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out non-finite argument */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { if(((hx&0xfffff)|__LO(x))!=0) return x+x; /* NaN */ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ } if(x > o_threshold) return huge*huge; /* overflow */ if(x < u_threshold) return twom1000*twom1000; /* underflow */ } /* argument reduction */ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; } else { k = (int)(invln2*x+halF[xsb]); t = k; hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ lo = t*ln2LO[0]; } x = hi - lo; } else if(hx < 0x3e300000) { /* when |x|<2**-28 */ if(huge+x>one) return one+x;/* trigger inexact */ } else k = 0; /* x is now in primary range */ t = x*x; c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); if(k==0) return one-((x*c)/(c-2.0)-x); else y = one-((lo-(x*c)/(2.0-c))-hi); if(k >= -1021) { __HI(y) += (k<<20); /* add k to y's exponent */ return y; } else { __HI(y) += ((k+1000)<<20);/* add k to y's exponent */ return y*twom1000; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_fmod.c ================================================ /* @(#)e_fmod.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __ieee754_fmod(x,y) * Return x mod y in exact arithmetic * Method: shift and subtract */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0, Zero[] = {0.0, -0.0,}; #else static double one = 1.0, Zero[] = {0.0, -0.0,}; #endif #ifdef __STDC__ double __ieee754_fmod(double x, double y) #else double __ieee754_fmod(x,y) double x,y ; #endif { int n,hx,hy,hz,ix,iy,sx,i; unsigned lx,ly,lz; hx = __HI(x); /* high word of x */ lx = __LO(x); /* low word of x */ hy = __HI(y); /* high word of y */ ly = __LO(y); /* low word of y */ sx = hx&0x80000000; /* sign of x */ hx ^=sx; /* |x| */ hy &= 0x7fffffff; /* |y| */ /* purge off exception values */ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */ return (x*y)/(x*y); if(hx<=hy) { if((hx>31]; /* |x|=|y| return x*0*/ } /* determine ix = ilogb(x) */ if(hx<0x00100000) { /* subnormal x */ if(hx==0) { for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; } else { for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; } } else ix = (hx>>20)-1023; /* determine iy = ilogb(y) */ if(hy<0x00100000) { /* subnormal y */ if(hy==0) { for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; } else { for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; } } else iy = (hy>>20)-1023; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -1022) hx = 0x00100000|(0x000fffff&hx); else { /* subnormal x, shift x to normal */ n = -1022-ix; if(n<=31) { hx = (hx<>(32-n)); lx <<= n; } else { hx = lx<<(n-32); lx = 0; } } if(iy >= -1022) hy = 0x00100000|(0x000fffff&hy); else { /* subnormal y, shift y to normal */ n = -1022-iy; if(n<=31) { hy = (hy<>(32-n)); ly <<= n; } else { hy = ly<<(n-32); ly = 0; } } /* fix point fmod */ n = ix - iy; while(n--) { hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} else { if((hz|lz)==0) /* return sign(x)*0 */ return Zero[(unsigned)sx>>31]; hx = hz+hz+(lz>>31); lx = lz+lz; } } hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} /* convert back to floating value and restore the sign */ if((hx|lx)==0) /* return sign(x)*0 */ return Zero[(unsigned)sx>>31]; while(hx<0x00100000) { /* normalize x */ hx = hx+hx+(lx>>31); lx = lx+lx; iy -= 1; } if(iy>= -1022) { /* normalize output */ hx = ((hx-0x00100000)|((iy+1023)<<20)); __HI(x) = hx|sx; __LO(x) = lx; } else { /* subnormal output */ n = -1022 - iy; if(n<=20) { lx = (lx>>n)|((unsigned)hx<<(32-n)); hx >>= n; } else if (n<=31) { lx = (hx<<(32-n))|(lx>>n); hx = sx; } else { lx = hx>>(n-32); hx = sx; } __HI(x) = hx|sx; __LO(x) = lx; x *= one; /* create necessary signal */ } return x; /* exact output */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_gamma.c ================================================ /* @(#)e_gamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_gamma(x) * Return the logarithm of the Gamma function of x. * * Method: call __ieee754_gamma_r */ #include "fdlibm.h" extern int signgam; #ifdef __STDC__ double __ieee754_gamma(double x) #else double __ieee754_gamma(x) double x; #endif { return __ieee754_gamma_r(x,&signgam); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_gamma_r.c ================================================ /* @(#)e_gamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_gamma_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function * with user provide pointer for the sign of Gamma(x). * * Method: See __ieee754_lgamma_r */ #include "fdlibm.h" #ifdef __STDC__ double __ieee754_gamma_r(double x, int *signgamp) #else double __ieee754_gamma_r(x,signgamp) double x; int *signgamp; #endif { return __ieee754_lgamma_r(x,signgamp); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_hypot.c ================================================ /* @(#)e_hypot.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_hypot(x,y) * * Method : * If (assume round-to-nearest) z=x*x+y*y * has error less than sqrt(2)/2 ulp, than * sqrt(z) has error less than 1 ulp (exercise). * * So, compute sqrt(x*x+y*y) with some care as * follows to get the error below 1 ulp: * * Assume x>y>0; * (if possible, set rounding to round-to-nearest) * 1. if x > 2y use * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y * where x1 = x with lower 32 bits cleared, x2 = x-x1; else * 2. if x <= 2y use * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, * y1= y with lower 32 bits chopped, y2 = y-y1. * * NOTE: scaling may be necessary if some argument is too * large or too tiny * * Special cases: * hypot(x,y) is INF if x or y is +INF or -INF; else * hypot(x,y) is NAN if x or y is NAN. * * Accuracy: * hypot(x,y) returns sqrt(x^2+y^2) with error less * than 1 ulps (units in the last place) */ #include "fdlibm.h" #ifdef __STDC__ double __ieee754_hypot(double x, double y) #else double __ieee754_hypot(x,y) double x, y; #endif { double a=x,b=y,t1,t2,y1,y2,w; int j,k,ha,hb; ha = __HI(x)&0x7fffffff; /* high word of x */ hb = __HI(y)&0x7fffffff; /* high word of y */ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} __HI(a) = ha; /* a <- |a| */ __HI(b) = hb; /* b <- |b| */ if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ k=0; if(ha > 0x5f300000) { /* a>2**500 */ if(ha >= 0x7ff00000) { /* Inf or NaN */ w = a+b; /* for sNaN */ if(((ha&0xfffff)|__LO(a))==0) w = a; if(((hb^0x7ff00000)|__LO(b))==0) w = b; return w; } /* scale a and b by 2**-600 */ ha -= 0x25800000; hb -= 0x25800000; k += 600; __HI(a) = ha; __HI(b) = hb; } if(hb < 0x20b00000) { /* b < 2**-500 */ if(hb <= 0x000fffff) { /* subnormal b or 0 */ if((hb|(__LO(b)))==0) return a; t1=0; __HI(t1) = 0x7fd00000; /* t1=2^1022 */ b *= t1; a *= t1; k -= 1022; } else { /* scale a and b by 2^600 */ ha += 0x25800000; /* a *= 2^600 */ hb += 0x25800000; /* b *= 2^600 */ k -= 600; __HI(a) = ha; __HI(b) = hb; } } /* medium size a and b */ w = a-b; if (w>b) { t1 = 0; __HI(t1) = ha; t2 = a-t1; w = sqrt(t1*t1-(b*(-b)-t2*(a+t1))); } else { a = a+a; y1 = 0; __HI(y1) = hb; y2 = b - y1; t1 = 0; __HI(t1) = ha+0x00100000; t2 = a - t1; w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { t1 = 1.0; __HI(t1) += (k<<20); return t1*w; } else return w; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_j0.c ================================================ /* @(#)e_j0.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_j0(x), __ieee754_y0(x) * Bessel function of the first and second kinds of order zero. * Method -- j0(x): * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... * 2. Reduce x to |x| since j0(x)=j0(-x), and * for x in (0,2) * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) * for x in (2,inf) * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) * as follow: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (cos(x) + sin(x)) * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * (To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one.) * * 3 Special cases * j0(nan)= nan * j0(0) = 1 * j0(inf) = 0 * * Method -- y0(x): * 1. For x<2. * Since * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. * We use the following function to approximate y0, * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 * where * U(z) = u00 + u01*z + ... + u06*z^6 * V(z) = 1 + v01*z + ... + v04*z^4 * with absolute approximation error bounded by 2**-72. * Note: For tiny x, U/V = u0 and j0(x)~1, hence * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) * 2. For x>=2. * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) * by the method mentioned above. * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. */ #include "fdlibm.h" #ifdef __STDC__ static double pzero(double), qzero(double); #else static double pzero(), qzero(); #endif #ifdef __STDC__ static const double #else static double #endif huge = 1e300, one = 1.0, invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ /* R0/S0 on [0, 2.00] */ R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ static double zero = 0.0; #ifdef __STDC__ double __ieee754_j0(double x) #else double __ieee754_j0(x) double x; #endif { double z, s,c,ss,cc,r,u,v; int hx,ix; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return one/(x*x); x = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ s = sin(x); c = cos(x); ss = s-c; cc = s+c; if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = -cos(x+x); if ((s*c)0x48000000) z = (invsqrtpi*cc)/sqrt(x); else { u = pzero(x); v = qzero(x); z = invsqrtpi*(u*cc-v*ss)/sqrt(x); } return z; } if(ix<0x3f200000) { /* |x| < 2**-13 */ if(huge+x>one) { /* raise inexact if x != 0 */ if(ix<0x3e400000) return one; /* |x|<2**-27 */ else return one - 0.25*x*x; } } z = x*x; r = z*(R02+z*(R03+z*(R04+z*R05))); s = one+z*(S01+z*(S02+z*(S03+z*S04))); if(ix < 0x3FF00000) { /* |x| < 1.00 */ return one + z*(-0.25+(r/s)); } else { u = 0.5*x; return((one+u)*(one-u)+z*(r/s)); } } #ifdef __STDC__ static const double #else static double #endif u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ #ifdef __STDC__ double __ieee754_y0(double x) #else double __ieee754_y0(x) double x; #endif { double z, s,c,ss,cc,u,v; int hx,ix,lx; hx = __HI(x); ix = 0x7fffffff&hx; lx = __LO(x); /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ if(ix>=0x7ff00000) return one/(x+x*x); if((ix|lx)==0) return -one/zero; if(hx<0) return zero/zero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) * where x0 = x-pi/4 * Better formula: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) + cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ s = sin(x); c = cos(x); ss = s-c; cc = s+c; /* * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) */ if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = -cos(x+x); if ((s*c)0x48000000) z = (invsqrtpi*ss)/sqrt(x); else { u = pzero(x); v = qzero(x); z = invsqrtpi*(u*ss+v*cc)/sqrt(x); } return z; } if(ix<=0x3e400000) { /* x < 2**-27 */ return(u00 + tpi*__ieee754_log(x)); } z = x*x; u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); v = one+z*(v01+z*(v02+z*(v03+z*v04))); return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); } /* The asymptotic expansions of pzero is * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. * For x >= 2, We approximate pzero by * pzero(x) = 1 + (R/S) * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 * S = 1 + pS0*s^2 + ... + pS4*s^10 * and * | pzero(x)-1-R/S | <= 2 ** ( -60.26) */ #ifdef __STDC__ static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #else static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #endif 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ }; #ifdef __STDC__ static const double pS8[5] = { #else static double pS8[5] = { #endif 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ }; #ifdef __STDC__ static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #else static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #endif -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ }; #ifdef __STDC__ static const double pS5[5] = { #else static double pS5[5] = { #endif 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ }; #ifdef __STDC__ static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #else static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #endif -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ }; #ifdef __STDC__ static const double pS3[5] = { #else static double pS3[5] = { #endif 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ }; #ifdef __STDC__ static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #else static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #endif -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ }; #ifdef __STDC__ static const double pS2[5] = { #else static double pS2[5] = { #endif 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ }; #ifdef __STDC__ static double pzero(double x) #else static double pzero(x) double x; #endif { #ifdef __STDC__ const double *p,*q; #else double *p,*q; #endif double z,r,s; int ix; ix = 0x7fffffff&__HI(x); if(ix>=0x40200000) {p = pR8; q= pS8;} else if(ix>=0x40122E8B){p = pR5; q= pS5;} else if(ix>=0x4006DB6D){p = pR3; q= pS3;} else if(ix>=0x40000000){p = pR2; q= pS2;} z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qzero is * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. * We approximate pzero by * qzero(x) = s*(-1.25 + (R/S)) * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 * S = 1 + qS0*s^2 + ... + qS5*s^12 * and * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) */ #ifdef __STDC__ static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #else static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #endif 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ }; #ifdef __STDC__ static const double qS8[6] = { #else static double qS8[6] = { #endif 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ }; #ifdef __STDC__ static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #else static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #endif 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ }; #ifdef __STDC__ static const double qS5[6] = { #else static double qS5[6] = { #endif 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ }; #ifdef __STDC__ static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #else static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #endif 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ }; #ifdef __STDC__ static const double qS3[6] = { #else static double qS3[6] = { #endif 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ }; #ifdef __STDC__ static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #else static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #endif 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ }; #ifdef __STDC__ static const double qS2[6] = { #else static double qS2[6] = { #endif 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ }; #ifdef __STDC__ static double qzero(double x) #else static double qzero(x) double x; #endif { #ifdef __STDC__ const double *p,*q; #else double *p,*q; #endif double s,r,z; int ix; ix = 0x7fffffff&__HI(x); if(ix>=0x40200000) {p = qR8; q= qS8;} else if(ix>=0x40122E8B){p = qR5; q= qS5;} else if(ix>=0x4006DB6D){p = qR3; q= qS3;} else if(ix>=0x40000000){p = qR2; q= qS2;} z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return (-.125 + r/s)/x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_j1.c ================================================ /* @(#)e_j1.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_j1(x), __ieee754_y1(x) * Bessel function of the first and second kinds of order zero. * Method -- j1(x): * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... * 2. Reduce x to |x| since j1(x)=-j1(-x), and * for x in (0,2) * j1(x) = x/2 + x*z*R0/S0, where z = x*x; * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) * for x in (2,inf) * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) * as follow: * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (sin(x) + cos(x)) * (To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one.) * * 3 Special cases * j1(nan)= nan * j1(0) = 0 * j1(inf) = 0 * * Method -- y1(x): * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN * 2. For x<2. * Since * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. * We use the following function to approximate y1, * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 * where for x in [0,2] (abs err less than 2**-65.89) * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 * Note: For tiny x, 1/x dominate y1 and hence * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) * 3. For x>=2. * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) * by method mentioned above. */ #include "fdlibm.h" #ifdef __STDC__ static double pone(double), qone(double); #else static double pone(), qone(); #endif #ifdef __STDC__ static const double #else static double #endif huge = 1e300, one = 1.0, invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ /* R0/S0 on [0,2] */ r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ static double zero = 0.0; #ifdef __STDC__ double __ieee754_j1(double x) #else double __ieee754_j1(x) double x; #endif { double z, s,c,ss,cc,r,u,v,y; int hx,ix; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return one/x; y = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ s = sin(y); c = cos(y); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure y+y not overflow */ z = cos(y+y); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) */ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y); else { u = pone(y); v = qone(y); z = invsqrtpi*(u*cc-v*ss)/sqrt(y); } if(hx<0) return -z; else return z; } if(ix<0x3e400000) { /* |x|<2**-27 */ if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ } z = x*x; r = z*(r00+z*(r01+z*(r02+z*r03))); s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); r *= x; return(x*0.5+r/s); } #ifdef __STDC__ static const double U0[5] = { #else static double U0[5] = { #endif -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ }; #ifdef __STDC__ static const double V0[5] = { #else static double V0[5] = { #endif 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ }; #ifdef __STDC__ double __ieee754_y1(double x) #else double __ieee754_y1(x) double x; #endif { double z, s,c,ss,cc,u,v; int hx,ix,lx; hx = __HI(x); ix = 0x7fffffff&hx; lx = __LO(x); /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ if(ix>=0x7ff00000) return one/(x+x*x); if((ix|lx)==0) return -one/zero; if(hx<0) return zero/zero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ s = sin(x); c = cos(x); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure x+x not overflow */ z = cos(x+x); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) * where x0 = x-3pi/4 * Better formula: * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (cos(x) + sin(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x); else { u = pone(x); v = qone(x); z = invsqrtpi*(u*ss+v*cc)/sqrt(x); } return z; } if(ix<=0x3c900000) { /* x < 2**-54 */ return(-tpi/x); } z = x*x; u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); } /* For x >= 8, the asymptotic expansions of pone is * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. * We approximate pone by * pone(x) = 1 + (R/S) * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 * S = 1 + ps0*s^2 + ... + ps4*s^10 * and * | pone(x)-1-R/S | <= 2 ** ( -60.06) */ #ifdef __STDC__ static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #else static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #endif 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ }; #ifdef __STDC__ static const double ps8[5] = { #else static double ps8[5] = { #endif 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ }; #ifdef __STDC__ static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #else static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #endif 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ }; #ifdef __STDC__ static const double ps5[5] = { #else static double ps5[5] = { #endif 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ }; #ifdef __STDC__ static const double pr3[6] = { #else static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #endif 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ }; #ifdef __STDC__ static const double ps3[5] = { #else static double ps3[5] = { #endif 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ }; #ifdef __STDC__ static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #else static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #endif 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ }; #ifdef __STDC__ static const double ps2[5] = { #else static double ps2[5] = { #endif 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ }; #ifdef __STDC__ static double pone(double x) #else static double pone(x) double x; #endif { #ifdef __STDC__ const double *p,*q; #else double *p,*q; #endif double z,r,s; int ix; ix = 0x7fffffff&__HI(x); if(ix>=0x40200000) {p = pr8; q= ps8;} else if(ix>=0x40122E8B){p = pr5; q= ps5;} else if(ix>=0x4006DB6D){p = pr3; q= ps3;} else if(ix>=0x40000000){p = pr2; q= ps2;} z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); return one+ r/s; } /* For x >= 8, the asymptotic expansions of qone is * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. * We approximate pone by * qone(x) = s*(0.375 + (R/S)) * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 * S = 1 + qs1*s^2 + ... + qs6*s^12 * and * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) */ #ifdef __STDC__ static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #else static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ #endif 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ }; #ifdef __STDC__ static const double qs8[6] = { #else static double qs8[6] = { #endif 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ }; #ifdef __STDC__ static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #else static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ #endif -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ }; #ifdef __STDC__ static const double qs5[6] = { #else static double qs5[6] = { #endif 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ }; #ifdef __STDC__ static const double qr3[6] = { #else static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ #endif -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ }; #ifdef __STDC__ static const double qs3[6] = { #else static double qs3[6] = { #endif 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ }; #ifdef __STDC__ static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #else static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ #endif -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ }; #ifdef __STDC__ static const double qs2[6] = { #else static double qs2[6] = { #endif 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ }; #ifdef __STDC__ static double qone(double x) #else static double qone(x) double x; #endif { #ifdef __STDC__ const double *p,*q; #else double *p,*q; #endif double s,r,z; int ix; ix = 0x7fffffff&__HI(x); if(ix>=0x40200000) {p = qr8; q= qs8;} else if(ix>=0x40122E8B){p = qr5; q= qs5;} else if(ix>=0x4006DB6D){p = qr3; q= qs3;} else if(ix>=0x40000000){p = qr2; q= qs2;} z = one/(x*x); r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); return (.375 + r/s)/x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_jn.c ================================================ /* @(#)e_jn.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __ieee754_jn(n, x), __ieee754_yn(n, x) * floating point Bessel's function of the 1st and 2nd kind * of order n * * Special cases: * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. * Note 2. About jn(n,x), yn(n,x) * For n=0, j0(x) is called, * for n=1, j1(x) is called, * for nx, a continued fraction approximation to * j(n,x)/j(n-1,x) is evaluated and then backward * recursion is used starting from a supposed value * for j(n,x). The resulting value of j(0,x) is * compared with the actual value to correct the * supposed value of j(n,x). * * yn(n,x) is similar in all respects, except * that forward recursion is used for all * values of n>1. * */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ static double zero = 0.00000000000000000000e+00; #ifdef __STDC__ double __ieee754_jn(int n, double x) #else double __ieee754_jn(n,x) int n; double x; #endif { int i,hx,ix,lx, sgn; double a, b, temp, di; double z, w; /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) * Thus, J(-n,x) = J(n,-x) */ hx = __HI(x); ix = 0x7fffffff&hx; lx = __LO(x); /* if J(n,NaN) is NaN */ if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; if(n<0){ n = -n; x = -x; hx ^= 0x80000000; } if(n==0) return(__ieee754_j0(x)); if(n==1) return(__ieee754_j1(x)); sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ x = fabs(x); if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ b = zero; else if((double)n<=x) { /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ if(ix>=0x52D00000) { /* x > 2**302 */ /* (x >> n**2) * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Let s=sin(x), c=cos(x), * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then * * n sin(xn)*sqt2 cos(xn)*sqt2 * ---------------------------------- * 0 s-c c+s * 1 -s-c -c+s * 2 -s+c -c-s * 3 s+c c-s */ switch(n&3) { case 0: temp = cos(x)+sin(x); break; case 1: temp = -cos(x)+sin(x); break; case 2: temp = -cos(x)-sin(x); break; case 3: temp = cos(x)-sin(x); break; } b = invsqrtpi*temp/sqrt(x); } else { a = __ieee754_j0(x); b = __ieee754_j1(x); for(i=1;i33) /* underflow */ b = zero; else { temp = x*0.5; b = temp; for (a=one,i=2;i<=n;i++) { a *= (double)i; /* a = n! */ b *= temp; /* b = (x/2)^n */ } b = b/a; } } else { /* use backward recurrence */ /* x x^2 x^2 * J(n,x)/J(n-1,x) = ---- ------ ------ ..... * 2n - 2(n+1) - 2(n+2) * * 1 1 1 * (for large x) = ---- ------ ------ ..... * 2n 2(n+1) 2(n+2) * -- - ------ - ------ - * x x x * * Let w = 2n/x and h=2/x, then the above quotient * is equal to the continued fraction: * 1 * = ----------------------- * 1 * w - ----------------- * 1 * w+h - --------- * w+2h - ... * * To determine how many terms needed, let * Q(0) = w, Q(1) = w(w+h) - 1, * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), * When Q(k) > 1e4 good for single * When Q(k) > 1e9 good for double * When Q(k) > 1e17 good for quadruple */ /* determine k */ double t,v; double q0,q1,h,tmp; int k,m; w = (n+n)/(double)x; h = 2.0/(double)x; q0 = w; z = w+h; q1 = w*z - 1.0; k=1; while(q1<1.0e9) { k += 1; z += h; tmp = z*q1 - q0; q0 = q1; q1 = tmp; } m = n+n; for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); a = t; b = one; /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) * Hence, if n*(log(2n/x)) > ... * single 8.8722839355e+01 * double 7.09782712893383973096e+02 * long double 1.1356523406294143949491931077970765006170e+04 * then recurrent value may overflow and the result is * likely underflow to zero */ tmp = n; v = two/x; tmp = tmp*__ieee754_log(fabs(v*tmp)); if(tmp<7.09782712893383973096e+02) { for(i=n-1,di=(double)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; } } else { for(i=n-1,di=(double)(i+i);i>0;i--){ temp = b; b *= di; b = b/x - a; a = temp; di -= two; /* scale b to avoid spurious overflow */ if(b>1e100) { a /= b; t /= b; b = one; } } } b = (t*__ieee754_j0(x)/b); } } if(sgn==1) return -b; else return b; } #ifdef __STDC__ double __ieee754_yn(int n, double x) #else double __ieee754_yn(n,x) int n; double x; #endif { int i,hx,ix,lx; int sign; double a, b, temp; hx = __HI(x); ix = 0x7fffffff&hx; lx = __LO(x); /* if Y(n,NaN) is NaN */ if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; if((ix|lx)==0) return -one/zero; if(hx<0) return zero/zero; sign = 1; if(n<0){ n = -n; sign = 1 - ((n&1)<<1); } if(n==0) return(__ieee754_y0(x)); if(n==1) return(sign*__ieee754_y1(x)); if(ix==0x7ff00000) return zero; if(ix>=0x52D00000) { /* x > 2**302 */ /* (x >> n**2) * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) * Let s=sin(x), c=cos(x), * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then * * n sin(xn)*sqt2 cos(xn)*sqt2 * ---------------------------------- * 0 s-c c+s * 1 -s-c -c+s * 2 -s+c -c-s * 3 s+c c-s */ switch(n&3) { case 0: temp = sin(x)-cos(x); break; case 1: temp = -sin(x)-cos(x); break; case 2: temp = -sin(x)+cos(x); break; case 3: temp = sin(x)+cos(x); break; } b = invsqrtpi*temp/sqrt(x); } else { a = __ieee754_y0(x); b = __ieee754_y1(x); /* quit if b is -inf */ for(i=1;i0) return b; else return -b; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_lgamma.c ================================================ /* @(#)e_lgamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_lgamma(x) * Return the logarithm of the Gamma function of x. * * Method: call __ieee754_lgamma_r */ #include "fdlibm.h" extern int signgam; #ifdef __STDC__ double __ieee754_lgamma(double x) #else double __ieee754_lgamma(x) double x; #endif { return __ieee754_lgamma_r(x,&signgam); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_lgamma_r.c ================================================ /* @(#)e_lgamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_lgamma_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function * with user provide pointer for the sign of Gamma(x). * * Method: * 1. Argument Reduction for 0 < x <= 8 * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may * reduce x to a number in [1.5,2.5] by * lgamma(1+s) = log(s) + lgamma(s) * for example, * lgamma(7.3) = log(6.3) + lgamma(6.3) * = log(6.3*5.3) + lgamma(5.3) * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) * 2. Polynomial approximation of lgamma around its * minimun ymin=1.461632144968362245 to maintain monotonicity. * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use * Let z = x-ymin; * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) * where * poly(z) is a 14 degree polynomial. * 2. Rational approximation in the primary interval [2,3] * We use the following approximation: * s = x-2.0; * lgamma(x) = 0.5*s + s*P(s)/Q(s) * with accuracy * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 * Our algorithms are based on the following observation * * zeta(2)-1 2 zeta(3)-1 3 * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... * 2 3 * * where Euler = 0.5771... is the Euler constant, which is very * close to 0.5. * * 3. For x>=8, we have * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... * (better formula: * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) * Let z = 1/x, then we approximation * f(z) = lgamma(x) - (x-0.5)(log(x)-1) * by * 3 5 11 * w = w0 + w1*z + w2*z + w3*z + ... + w6*z * where * |w - f(z)| < 2**-58.74 * * 4. For negative x, since (G is gamma function) * -x*G(-x)*G(x) = pi/sin(pi*x), * we have * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 * Hence, for x<0, signgam = sign(sin(pi*x)) and * lgamma(x) = log(|Gamma(x)|) * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); * Note: one should avoid compute pi*(-x) directly in the * computation of sin(pi*(-x)). * * 5. Special Cases * lgamma(2+s) ~ s*(1-Euler) for tiny s * lgamma(1)=lgamma(2)=0 * lgamma(x) ~ -log(x) for tiny x * lgamma(0) = lgamma(inf) = inf * lgamma(-integer) = +-inf * */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ /* tt = -(tail of tf) */ tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ static double zero= 0.00000000000000000000e+00; #ifdef __STDC__ static double sin_pi(double x) #else static double sin_pi(x) double x; #endif { double y,z; int n,ix; ix = 0x7fffffff&__HI(x); if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0); y = -x; /* x is assume negative */ /* * argument reduction, make sure inexact flag not raised if input * is an integer */ z = floor(y); if(z!=y) { /* inexact anyway */ y *= 0.5; y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */ n = (int) (y*4.0); } else { if(ix>=0x43400000) { y = zero; n = 0; /* y must be even */ } else { if(ix<0x43300000) z = y+two52; /* exact */ n = __LO(z)&1; /* lower word of z */ y = n; n<<= 2; } } switch (n) { case 0: y = __kernel_sin(pi*y,zero,0); break; case 1: case 2: y = __kernel_cos(pi*(0.5-y),zero); break; case 3: case 4: y = __kernel_sin(pi*(one-y),zero,0); break; case 5: case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; default: y = __kernel_sin(pi*(y-2.0),zero,0); break; } return -y; } #ifdef __STDC__ double __ieee754_lgamma_r(double x, int *signgamp) #else double __ieee754_lgamma_r(x,signgamp) double x; int *signgamp; #endif { double t,y,z,nadj,p,p1,p2,p3,q,r,w; int i,hx,lx,ix; hx = __HI(x); lx = __LO(x); /* purge off +-inf, NaN, +-0, and negative arguments */ *signgamp = 1; ix = hx&0x7fffffff; if(ix>=0x7ff00000) return x*x; if((ix|lx)==0) return one/zero; if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ if(hx<0) { *signgamp = -1; return -__ieee754_log(-x); } else return -__ieee754_log(x); } if(hx<0) { if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ return one/zero; t = sin_pi(x); if(t==zero) return one/zero; /* -integer */ nadj = __ieee754_log(pi/fabs(t*x)); if(t=0x3FE76944) {y = one-x; i= 0;} else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); p = y*p1+p2; r += (p-0.5*y); break; case 1: z = y*y; w = z*y; p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); p = z*p1-(tt-w*(p2+y*p3)); r += (tf + p); break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); r += (-0.5*y + p1/p2); } } else if(ix<0x40200000) { /* x < 8.0 */ i = (int)x; t = zero; y = x-(double)i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); r = half*y+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+6.0); /* FALLTHRU */ case 6: z *= (y+5.0); /* FALLTHRU */ case 5: z *= (y+4.0); /* FALLTHRU */ case 4: z *= (y+3.0); /* FALLTHRU */ case 3: z *= (y+2.0); /* FALLTHRU */ r += __ieee754_log(z); break; } /* 8.0 <= x < 2**58 */ } else if (ix < 0x43900000) { t = __ieee754_log(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); r = (x-half)*(t-one)+w; } else /* 2**58 <= x <= inf */ r = x*(__ieee754_log(x)-one); if(hx<0) r = nadj - r; return r; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_log.c ================================================ /* @(#)e_log.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_log(x) * Return the logrithm of x * * Method : * 1. Argument Reduction: find k and f such that * x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * 2. Approximation of log(1+f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Reme algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s * (the values of Lg1 to Lg7 are listed in the program) * and * | 2 14 | -58.45 * | Lg1*s +...+Lg7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log(1+f) = f - s*(f - R) (if f is not too large) * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) * * 3. Finally, log(x) = k*ln2 + log(1+f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log(x) is NaN with signal if x < 0 (including -INF) ; * log(+INF) is +INF; log(0) is -INF with signal; * log(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ static double zero = 0.0; #ifdef __STDC__ double __ieee754_log(double x) #else double __ieee754_log(x) double x; #endif { double hfsq,f,s,z,R,w,t1,t2,dk; int k,hx,i,j; unsigned lx; hx = __HI(x); /* high word of x */ lx = __LO(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ hx = __HI(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; __HI(x) = hx|(i^0x3ff00000); /* normalize x or x/2 */ k += (i>>20); f = x-1.0; if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ if(f==zero) if(k==0) return zero; else {dk=(double)k; return dk*ln2_hi+dk*ln2_lo;} R = f*f*(0.5-0.33333333333333333*f); if(k==0) return f-R; else {dk=(double)k; return dk*ln2_hi-((R-dk*ln2_lo)-f);} } s = f/(2.0+f); dk = (double)k; z = s*s; i = hx-0x6147a; w = z*z; j = 0x6b851-hx; t1= w*(Lg2+w*(Lg4+w*Lg6)); t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); i |= j; R = t2+t1; if(i>0) { hfsq=0.5*f*f; if(k==0) return f-(hfsq-s*(hfsq+R)); else return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); } else { if(k==0) return f-s*(f-R); else return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_log10.c ================================================ /* @(#)e_log10.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_log10(x) * Return the base 10 logarithm of x * * Method : * Let log10_2hi = leading 40 bits of log10(2) and * log10_2lo = log10(2) - log10_2hi, * ivln10 = 1/log(10) rounded. * Then * n = ilogb(x), * if(n<0) n = n+1; * x = scalbn(x,-n); * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x)) * * Note 1: * To guarantee log10(10**n)=n, where 10**n is normal, the rounding * mode must set to Round-to-Nearest. * Note 2: * [1/log(10)] rounded to 53 bits has error .198 ulps; * log10 is monotonic at all binary break points. * * Special cases: * log10(x) is NaN with signal if x < 0; * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; * log10(NaN) is that NaN with no signal; * log10(10**N) = N for N=0,1,...,22. * * Constants: * The hexadecimal values are the intended ones for the following constants. * The decimal values may be used, provided that the compiler will convert * from decimal to binary accurately enough to produce the hexadecimal values * shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */ log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ static double zero = 0.0; #ifdef __STDC__ double __ieee754_log10(double x) #else double __ieee754_log10(x) double x; #endif { double y,z; int i,k,hx; unsigned lx; hx = __HI(x); /* high word of x */ lx = __LO(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ hx = __HI(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; i = ((unsigned)k&0x80000000)>>31; hx = (hx&0x000fffff)|((0x3ff-i)<<20); y = (double)(k+i); __HI(x) = hx; z = y*log10_2lo + ivln10*__ieee754_log(x); return z+y*log10_2hi; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_pow.c ================================================ #ifndef lint static char sccsid[] = "@(#)e_pow.c 1.5 04/04/22 SMI"; #endif /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_pow(x,y) return x**y * * n * Method: Let x = 2 * (1+f) * 1. Compute and return log2(x) in two pieces: * log2(x) = w1 + w2, * where w1 has 53-24 = 29 bit trailing zeros. * 2. Perform y*log2(x) = n+y' by simulating muti-precision * arithmetic, where |y'|<=0.5. * 3. Return x**y = 2**n*exp(y'*log2) * * Special cases: * 1. (anything) ** 0 is 1 * 2. (anything) ** 1 is itself * 3. (anything) ** NAN is NAN * 4. NAN ** (anything except 0) is NAN * 5. +-(|x| > 1) ** +INF is +INF * 6. +-(|x| > 1) ** -INF is +0 * 7. +-(|x| < 1) ** +INF is +0 * 8. +-(|x| < 1) ** -INF is +INF * 9. +-1 ** +-INF is NAN * 10. +0 ** (+anything except 0, NAN) is +0 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 * 12. +0 ** (-anything except 0, NAN) is +INF * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) * 15. +INF ** (+anything except 0,NAN) is +INF * 16. +INF ** (-anything except 0,NAN) is +0 * 17. -INF ** (anything) = -0 ** (-anything) * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) * 19. (-anything except 0 and inf) ** (non-integer) is NAN * * Accuracy: * pow(x,y) returns x**y nearly rounded. In particular * pow(integer,integer) * always returns the correct integer provided it is * representable. * * Constants : * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif bp[] = {1.0, 1.5,}, dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ zero = 0.0, one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ huge = 1.0e300, tiny = 1.0e-300, /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ #ifdef __STDC__ double __ieee754_pow(double x, double y) #else double __ieee754_pow(x,y) double x, y; #endif { double z,ax,z_h,z_l,p_h,p_l; double y1,t1,t2,r,s,t,u,v,w; int i0,i1,i,j,k,yisint,n; int hx,hy,ix,iy; unsigned lx,ly; i0 = ((*(int*)&one)>>29)^1; i1=1-i0; hx = __HI(x); lx = __LO(x); hy = __HI(y); ly = __LO(y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ if((iy|ly)==0) return one; /* +-NaN return x+y */ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) return x+y; /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if(hx<0) { if(iy>=0x43400000) yisint = 2; /* even integer y */ else if(iy>=0x3ff00000) { k = (iy>>20)-0x3ff; /* exponent */ if(k>20) { j = ly>>(52-k); if((j<<(52-k))==ly) yisint = 2-(j&1); } else if(ly==0) { j = iy>>(20-k); if((j<<(20-k))==iy) yisint = 2-(j&1); } } } /* special value of y */ if(ly==0) { if (iy==0x7ff00000) { /* y is +-inf */ if(((ix-0x3ff00000)|lx)==0) return y - y; /* inf**+-1 is NaN */ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ return (hy>=0)? y: zero; else /* (|x|<1)**-,+inf = inf,0 */ return (hy<0)?-y: zero; } if(iy==0x3ff00000) { /* y is +-1 */ if(hy<0) return one/x; else return x; } if(hy==0x40000000) return x*x; /* y is 2 */ if(hy==0x3fe00000) { /* y is 0.5 */ if(hx>=0) /* x >= +0 */ return sqrt(x); } } ax = fabs(x); /* special value of x */ if(lx==0) { if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ z = ax; /*x is +-0,+-inf,+-1*/ if(hy<0) z = one/z; /* z = (1/|x|) */ if(hx<0) { if(((ix-0x3ff00000)|yisint)==0) { z = (z-z)/(z-z); /* (-1)**non-int is NaN */ } else if(yisint==1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } } n = (hx>>31)+1; /* (x<0)**(non-int) is NaN */ if((n|yisint)==0) return (x-x)/(x-x); s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ /* |y| is huge */ if(iy>0x41e00000) { /* if |y| > 2**31 */ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; } /* over/underflow if x is not close to one */ if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny; if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny; /* now |1-x| is tiny <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax-one; /* t has 20 trailing zeros */ w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ v = t*ivln2_l-w*ivln2; t1 = u+v; __LO(t1) = 0; t2 = v-(t1-u); } else { double ss,s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if(ix<0x00100000) {ax *= two53; n -= 53; ix = __HI(ax); } n += ((ix)>>20)-0x3ff; j = ix&0x000fffff; /* determine interval */ ix = j|0x3ff00000; /* normalize ix */ if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ s2 = ss*ss; r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); r += s_l*(s_h+ss); s2 = s_h*s_h; t_h = 3.0+s2+r; __LO(t_h) = 0; t_l = r-((t_h-3.0)-s2); /* u+v = ss*(1+...) */ u = s_h*t_h; v = s_l*t_h+t_l*ss; /* 2/(3log2)*(ss+...) */ p_h = u+v; __LO(p_h) = 0; p_l = v-(p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp+dp_l[k]; /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = (double)n; t1 = (((z_h+z_l)+dp_h[k])+t); __LO(t1) = 0; t2 = z_l-(((t1-t)-dp_h[k])-z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ y1 = y; __LO(y1) = 0; p_l = (y-y1)*t1+y*t2; p_h = y1*t1; z = p_l+p_h; j = __HI(z); i = __LO(z); if (j>=0x40900000) { /* z >= 1024 */ if(((j-0x40900000)|i)!=0) /* if z > 1024 */ return s*huge*huge; /* overflow */ else { if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ } } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ return s*tiny*tiny; /* underflow */ else { if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ } } /* * compute 2**(p_h+p_l) */ i = j&0x7fffffff; k = (i>>20)-0x3ff; n = 0; if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ n = j+(0x00100000>>(k+1)); k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ t = zero; __HI(t) = (n&~(0x000fffff>>k)); n = ((n&0x000fffff)|0x00100000)>>(20-k); if(j<0) n = -n; p_h -= t; } t = p_l+p_h; __LO(t) = 0; u = t*lg2_h; v = (p_l-(t-p_h))*lg2+t*lg2_l; z = u+v; w = v-(z-u); t = z*z; t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-two)-(w+z*w); z = one-(r-z); j = __HI(z); j += (n<<20); if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ else __HI(z) += (n<<20); return s*z; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_rem_pio2.c ================================================ /* @(#)e_rem_pio2.c 1.4 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_rem_pio2(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __kernel_rem_pio2() */ #include "fdlibm.h" /* * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi */ #ifdef __STDC__ static const int two_over_pi[] = { #else static int two_over_pi[] = { #endif 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, }; #ifdef __STDC__ static const int npio2_hw[] = { #else static int npio2_hw[] = { #endif 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, 0x404858EB, 0x404921FB, }; /* * invpio2: 53 bits of 2/pi * pio2_1: first 33 bit of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 33 bit of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 33 bit of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ #ifdef __STDC__ static const double #else static double #endif zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ #ifdef __STDC__ int __ieee754_rem_pio2(double x, double *y) #else int __ieee754_rem_pio2(x,y) double x,y[]; #endif { double z,w,t,r,fn; double tx[3]; int e0,i,j,nx,n,ix,hx; hx = __HI(x); /* high word of x */ ix = hx&0x7fffffff; if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ {y[0] = x; y[1] = 0; return 0;} if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ if(hx>0) { z = x - pio2_1; if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ y[0] = z - pio2_1t; y[1] = (z-y[0])-pio2_1t; } else { /* near pi/2, use 33+33+53 bit pi */ z -= pio2_2; y[0] = z - pio2_2t; y[1] = (z-y[0])-pio2_2t; } return 1; } else { /* negative x */ z = x + pio2_1; if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ y[0] = z + pio2_1t; y[1] = (z-y[0])+pio2_1t; } else { /* near pi/2, use 33+33+53 bit pi */ z += pio2_2; y[0] = z + pio2_2t; y[1] = (z-y[0])+pio2_2t; } return -1; } } if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ t = fabs(x); n = (int) (t*invpio2+half); fn = (double)n; r = t-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 85 bit */ if(n<32&&ix!=npio2_hw[n-1]) { y[0] = r-w; /* quick check no cancellation */ } else { j = ix>>20; y[0] = r-w; i = j-(((__HI(y[0]))>>20)&0x7ff); if(i>16) { /* 2nd iteration needed, good to 118 */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; i = j-(((__HI(y[0]))>>20)&0x7ff); if(i>49) { /* 3rd iteration need, 151 bits acc */ t = r; /* will cover all possible cases */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); y[0] = r-w; } } } y[1] = (r-y[0])-w; if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} else return n; } /* * all other (large) arguments */ if(ix>=0x7ff00000) { /* x is inf or NaN */ y[0]=y[1]=x-x; return 0; } /* set z = scalbn(|x|,ilogb(x)-23) */ __LO(z) = __LO(x); e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ __HI(z) = ix - (e0<<20); for(i=0;i<2;i++) { tx[i] = (double)((int)(z)); z = (z-tx[i])*two24; } tx[2] = z; nx = 3; while(tx[nx-1]==zero) nx--; /* skip zero term */ n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} return n; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_remainder.c ================================================ /* @(#)e_remainder.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_remainder(x,p) * Return : * returns x REM p = x - [x/p]*p as if in infinite * precise arithmetic, where [x/p] is the (infinite bit) * integer nearest x/p (in half way case choose the even one). * Method : * Based on fmod() return x-[x/p]chopped*p exactlp. */ #include "fdlibm.h" #ifdef __STDC__ static const double zero = 0.0; #else static double zero = 0.0; #endif #ifdef __STDC__ double __ieee754_remainder(double x, double p) #else double __ieee754_remainder(x,p) double x,p; #endif { int hx,hp; unsigned sx,lx,lp; double p_half; hx = __HI(x); /* high word of x */ lx = __LO(x); /* low word of x */ hp = __HI(p); /* high word of p */ lp = __LO(p); /* low word of p */ sx = hx&0x80000000; hp &= 0x7fffffff; hx &= 0x7fffffff; /* purge off exception values */ if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */ if((hx>=0x7ff00000)|| /* x not finite */ ((hp>=0x7ff00000)&& /* p is NaN */ (((hp-0x7ff00000)|lp)!=0))) return (x*p)/(x*p); if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */ if (((hx-hp)|(lx-lp))==0) return zero*x; x = fabs(x); p = fabs(p); if (hp<0x00200000) { if(x+x>p) { x-=p; if(x+x>=p) x -= p; } } else { p_half = 0.5*p; if(x>p_half) { x-=p; if(x>=p_half) x -= p; } } __HI(x) ^= sx; return x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_scalb.c ================================================ /* @(#)e_scalb.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __ieee754_scalb(x, fn) is provide for * passing various standard test suite. One * should use scalbn() instead. */ #include "fdlibm.h" #ifdef _SCALB_INT #ifdef __STDC__ double __ieee754_scalb(double x, int fn) #else double __ieee754_scalb(x,fn) double x; int fn; #endif #else #ifdef __STDC__ double __ieee754_scalb(double x, double fn) #else double __ieee754_scalb(x,fn) double x, fn; #endif #endif { #ifdef _SCALB_INT return scalbn(x,fn); #else if (isnan(x)||isnan(fn)) return x*fn; if (!finite(fn)) { if(fn>0.0) return x*fn; else return x/(-fn); } if (rint(fn)!=fn) return (fn-fn)/(fn-fn); if ( fn > 65000.0) return scalbn(x, 65000); if (-fn > 65000.0) return scalbn(x,-65000); return scalbn(x,(int)fn); #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_sinh.c ================================================ /* @(#)e_sinh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_sinh(x) * Method : * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 * 1. Replace x by |x| (sinh(-x) = -sinh(x)). * 2. * E + E/(E+1) * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) * 2 * * 22 <= x <= lnovft : sinh(x) := exp(x)/2 * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) * ln2ovft < x : sinh(x) := x*shuge (overflow) * * Special cases: * sinh(x) is |x| if x is +INF, -INF, or NaN. * only sinh(0)=0 is exact for finite x. */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0, shuge = 1.0e307; #else static double one = 1.0, shuge = 1.0e307; #endif #ifdef __STDC__ double __ieee754_sinh(double x) #else double __ieee754_sinh(x) double x; #endif { double t,w,h; int ix,jx; unsigned lx; /* High word of |x|. */ jx = __HI(x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x+x; h = 0.5; if (jx<0) h = -h; /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ if (ix < 0x40360000) { /* |x|<22 */ if (ix<0x3e300000) /* |x|<2**-28 */ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ t = expm1(fabs(x)); if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); return h*(t+t/(t+one)); } /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); if (ix<0x408633CE || (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { w = __ieee754_exp(0.5*fabs(x)); t = h*w; return t*w; } /* |x| > overflowthresold, sinh(x) overflow */ return x*shuge; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/e_sqrt.c ================================================ /* @(#)e_sqrt.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __ieee754_sqrt(x) * Return correctly rounded sqrt. * ------------------------------------------ * | Use the hardware sqrt if you have one | * ------------------------------------------ * Method: * Bit by bit method using integer arithmetic. (Slow, but portable) * 1. Normalization * Scale x to y in [1,4) with even powers of 2: * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then * sqrt(x) = 2^k * sqrt(y) * 2. Bit by bit computation * Let q = sqrt(y) truncated to i bit after binary point (q = 1), * i 0 * i+1 2 * s = 2*q , and y = 2 * ( y - q ). (1) * i i i i * * To compute q from q , one checks whether * i+1 i * * -(i+1) 2 * (q + 2 ) <= y. (2) * i * -(i+1) * If (2) is false, then q = q ; otherwise q = q + 2 . * i+1 i i+1 i * * With some algebric manipulation, it is not difficult to see * that (2) is equivalent to * -(i+1) * s + 2 <= y (3) * i i * * The advantage of (3) is that s and y can be computed by * i i * the following recurrence formula: * if (3) is false * * s = s , y = y ; (4) * i+1 i i+1 i * * otherwise, * -i -(i+1) * s = s + 2 , y = y - s - 2 (5) * i+1 i i+1 i i * * One may easily use induction to prove (4) and (5). * Note. Since the left hand side of (3) contain only i+2 bits, * it does not necessary to do a full (53-bit) comparison * in (3). * 3. Final rounding * After generating the 53 bits result, we compute one more bit. * Together with the remainder, we can decide whether the * result is exact, bigger than 1/2ulp, or less than 1/2ulp * (it will never equal to 1/2ulp). * The rounding mode can be detected by checking whether * huge + tiny is equal to huge, and whether huge - tiny is * equal to huge for some floating point number "huge" and "tiny". * * Special cases: * sqrt(+-0) = +-0 ... exact * sqrt(inf) = inf * sqrt(-ve) = NaN ... with invalid signal * sqrt(NaN) = NaN ... with invalid signal for signaling NaN * * Other methods : see the appended file at the end of the program below. *--------------- */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0, tiny=1.0e-300; #else static double one = 1.0, tiny=1.0e-300; #endif #ifdef __STDC__ double __ieee754_sqrt(double x) #else double __ieee754_sqrt(x) double x; #endif { double z; int sign = (int)0x80000000; unsigned r,t1,s1,ix1,q1; int ix0,s0,q,m,t,i; ix0 = __HI(x); /* high word of x */ ix1 = __LO(x); /* low word of x */ /* take care of Inf and NaN */ if((ix0&0x7ff00000)==0x7ff00000) { return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf sqrt(-inf)=sNaN */ } /* take care of zero */ if(ix0<=0) { if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ else if(ix0<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ } /* normalize x */ m = (ix0>>20); if(m==0) { /* subnormal x */ while(ix0==0) { m -= 21; ix0 |= (ix1>>11); ix1 <<= 21; } for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; m -= i-1; ix0 |= (ix1>>(32-i)); ix1 <<= i; } m -= 1023; /* unbias exponent */ ix0 = (ix0&0x000fffff)|0x00100000; if(m&1){ /* odd m, double x to make it even */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; } m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ r = 0x00200000; /* r = moving bit from right to left */ while(r!=0) { t = s0+r; if(t<=ix0) { s0 = t+r; ix0 -= t; q += r; } ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; r>>=1; } r = sign; while(r!=0) { t1 = s1+r; t = s0; if((t>31); ix1 += ix1; r>>=1; } /* use floating add to find out rounding direction */ if((ix0|ix1)!=0) { z = one-tiny; /* trigger inexact flag */ if (z>=one) { z = one+tiny; if (q1==(unsigned)0xffffffff) { q1=0; q += 1;} else if (z>one) { if (q1==(unsigned)0xfffffffe) q+=1; q1+=2; } else q1 += (q1&1); } } ix0 = (q>>1)+0x3fe00000; ix1 = q1>>1; if ((q&1)==1) ix1 |= sign; ix0 += (m <<20); __HI(z) = ix0; __LO(z) = ix1; return z; } /* Other methods (use floating-point arithmetic) ------------- (This is a copy of a drafted paper by Prof W. Kahan and K.C. Ng, written in May, 1986) Two algorithms are given here to implement sqrt(x) (IEEE double precision arithmetic) in software. Both supply sqrt(x) correctly rounded. The first algorithm (in Section A) uses newton iterations and involves four divisions. The second one uses reciproot iterations to avoid division, but requires more multiplications. Both algorithms need the ability to chop results of arithmetic operations instead of round them, and the INEXACT flag to indicate when an arithmetic operation is executed exactly with no roundoff error, all part of the standard (IEEE 754-1985). The ability to perform shift, add, subtract and logical AND operations upon 32-bit words is needed too, though not part of the standard. A. sqrt(x) by Newton Iteration (1) Initial approximation Let x0 and x1 be the leading and the trailing 32-bit words of a floating point number x (in IEEE double format) respectively 1 11 52 ...widths ------------------------------------------------------ x: |s| e | f | ------------------------------------------------------ msb lsb msb lsb ...order ------------------------ ------------------------ x0: |s| e | f1 | x1: | f2 | ------------------------ ------------------------ By performing shifts and subtracts on x0 and x1 (both regarded as integers), we obtain an 8-bit approximation of sqrt(x) as follows. k := (x0>>1) + 0x1ff80000; y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits Here k is a 32-bit integer and T1[] is an integer array containing correction terms. Now magically the floating value of y (y's leading 32-bit word is y0, the value of its trailing word is 0) approximates sqrt(x) to almost 8-bit. Value of T1: static int T1[32]= { 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; (2) Iterative refinement Apply Heron's rule three times to y, we have y approximates sqrt(x) to within 1 ulp (Unit in the Last Place): y := (y+x/y)/2 ... almost 17 sig. bits y := (y+x/y)/2 ... almost 35 sig. bits y := y-(y-x/y)/2 ... within 1 ulp Remark 1. Another way to improve y to within 1 ulp is: y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) 2 (x-y )*y y := y + 2* ---------- ...within 1 ulp 2 3y + x This formula has one division fewer than the one above; however, it requires more multiplications and additions. Also x must be scaled in advance to avoid spurious overflow in evaluating the expression 3y*y+x. Hence it is not recommended uless division is slow. If division is very slow, then one should use the reciproot algorithm given in section B. (3) Final adjustment By twiddling y's last bit it is possible to force y to be correctly rounded according to the prevailing rounding mode as follows. Let r and i be copies of the rounding mode and inexact flag before entering the square root program. Also we use the expression y+-ulp for the next representable floating numbers (up and down) of y. Note that y+-ulp = either fixed point y+-1, or multiply y by nextafter(1,+-inf) in chopped mode. I := FALSE; ... reset INEXACT flag I R := RZ; ... set rounding mode to round-toward-zero z := x/y; ... chopped quotient, possibly inexact If(not I) then { ... if the quotient is exact if(z=y) { I := i; ... restore inexact flag R := r; ... restore rounded mode return sqrt(x):=y. } else { z := z - ulp; ... special rounding } } i := TRUE; ... sqrt(x) is inexact If (r=RN) then z=z+ulp ... rounded-to-nearest If (r=RP) then { ... round-toward-+inf y = y+ulp; z=z+ulp; } y := y+z; ... chopped sum y0:=y0-0x00100000; ... y := y/2 is correctly rounded. I := i; ... restore inexact flag R := r; ... restore rounded mode return sqrt(x):=y. (4) Special cases Square root of +inf, +-0, or NaN is itself; Square root of a negative number is NaN with invalid signal. B. sqrt(x) by Reciproot Iteration (1) Initial approximation Let x0 and x1 be the leading and the trailing 32-bit words of a floating point number x (in IEEE double format) respectively (see section A). By performing shifs and subtracts on x0 and y0, we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. k := 0x5fe80000 - (x0>>1); y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits Here k is a 32-bit integer and T2[] is an integer array containing correction terms. Now magically the floating value of y (y's leading 32-bit word is y0, the value of its trailing word y1 is set to zero) approximates 1/sqrt(x) to almost 7.8-bit. Value of T2: static int T2[64]= { 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; (2) Iterative refinement Apply Reciproot iteration three times to y and multiply the result by x to get an approximation z that matches sqrt(x) to about 1 ulp. To be exact, we will have -1ulp < sqrt(x)-z<1.0625ulp. ... set rounding mode to Round-to-nearest y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) ... special arrangement for better accuracy z := x*y ... 29 bits to sqrt(x), with z*y<1 z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that (a) the term z*y in the final iteration is always less than 1; (b) the error in the final result is biased upward so that -1 ulp < sqrt(x) - z < 1.0625 ulp instead of |sqrt(x)-z|<1.03125ulp. (3) Final adjustment By twiddling y's last bit it is possible to force y to be correctly rounded according to the prevailing rounding mode as follows. Let r and i be copies of the rounding mode and inexact flag before entering the square root program. Also we use the expression y+-ulp for the next representable floating numbers (up and down) of y. Note that y+-ulp = either fixed point y+-1, or multiply y by nextafter(1,+-inf) in chopped mode. R := RZ; ... set rounding mode to round-toward-zero switch(r) { case RN: ... round-to-nearest if(x<= z*(z-ulp)...chopped) z = z - ulp; else if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; break; case RZ:case RM: ... round-to-zero or round-to--inf R:=RP; ... reset rounding mod to round-to-+inf if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; break; case RP: ... round-to-+inf if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else if(x>z*z ...chopped) z = z+ulp; break; } Remark 3. The above comparisons can be done in fixed point. For example, to compare x and w=z*z chopped, it suffices to compare x1 and w1 (the trailing parts of x and w), regarding them as two's complement integers. ...Is z an exact square root? To determine whether z is an exact square root of x, let z1 be the trailing part of z, and also let x0 and x1 be the leading and trailing parts of x. If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 I := 1; ... Raise Inexact flag: z is not exact else { j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 k := z1 >> 26; ... get z's 25-th and 26-th fraction bits I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); } R:= r ... restore rounded mode return sqrt(x):=z. If multiplication is cheaper then the foregoing red tape, the Inexact flag can be evaluated by I := i; I := (z*z!=x) or I. Note that z*z can overwrite I; this value must be sensed if it is True. Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be zero. -------------------- z1: | f2 | -------------------- bit 31 bit 0 Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd or even of logb(x) have the following relations: ------------------------------------------------- bit 27,26 of z1 bit 1,0 of x1 logb(x) ------------------------------------------------- 00 00 odd and even 01 01 even 10 10 odd 10 00 even 11 01 even ------------------------------------------------- (4) Special cases (see (4) of Section A). */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/fdlibm.h ================================================ /* @(#)fdlibm.h 1.5 04/04/22 */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* Sometimes it's necessary to define __LITTLE_ENDIAN explicitly but these catch some common cases. */ #if defined(i386) || defined(i486) || \ defined(intel) || defined(x86) || defined(i86pc) || \ defined(__alpha) || defined(__osf__) #define __LITTLE_ENDIAN #endif #ifdef __LITTLE_ENDIAN #define __HI(x) *(1+(int*)&x) #define __LO(x) *(int*)&x #define __HIp(x) *(1+(int*)x) #define __LOp(x) *(int*)x #else #define __HI(x) *(int*)&x #define __LO(x) *(1+(int*)&x) #define __HIp(x) *(int*)x #define __LOp(x) *(1+(int*)x) #endif #ifdef __STDC__ #define __P(p) p #else #define __P(p) () #endif /* * ANSI/POSIX */ extern int signgam; #define MAXFLOAT ((float)3.40282346638528860e+38) enum fdversion {fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix}; #define _LIB_VERSION_TYPE enum fdversion #define _LIB_VERSION _fdlib_version /* if global variable _LIB_VERSION is not desirable, one may * change the following to be a constant by: * #define _LIB_VERSION_TYPE const enum version * In that case, after one initializes the value _LIB_VERSION (see * s_lib_version.c) during compile time, it cannot be modified * in the middle of a program */ extern _LIB_VERSION_TYPE _LIB_VERSION; #define _IEEE_ fdlibm_ieee #define _SVID_ fdlibm_svid #define _XOPEN_ fdlibm_xopen #define _POSIX_ fdlibm_posix struct exception { int type; char *name; double arg1; double arg2; double retval; }; #define HUGE MAXFLOAT /* * set X_TLOSS = pi*2**52, which is possibly defined in * (one may replace the following line by "#include ") */ #define X_TLOSS 1.41484755040568800000e+16 #define DOMAIN 1 #define SING 2 #define OVERFLOW 3 #define UNDERFLOW 4 #define TLOSS 5 #define PLOSS 6 /* * ANSI/POSIX */ extern double acos __P((double)); extern double asin __P((double)); extern double atan __P((double)); extern double atan2 __P((double, double)); extern double cos __P((double)); extern double sin __P((double)); extern double tan __P((double)); extern double cosh __P((double)); extern double sinh __P((double)); extern double tanh __P((double)); extern double exp __P((double)); extern double frexp __P((double, int *)); extern double ldexp __P((double, int)); extern double log __P((double)); extern double log10 __P((double)); extern double modf __P((double, double *)); extern double pow __P((double, double)); extern double sqrt __P((double)); extern double ceil __P((double)); extern double fabs __P((double)); extern double floor __P((double)); extern double fmod __P((double, double)); extern double erf __P((double)); extern double erfc __P((double)); extern double gamma __P((double)); extern double hypot __P((double, double)); extern int isnan __P((double)); extern int finite __P((double)); extern double j0 __P((double)); extern double j1 __P((double)); extern double jn __P((int, double)); extern double lgamma __P((double)); extern double y0 __P((double)); extern double y1 __P((double)); extern double yn __P((int, double)); extern double acosh __P((double)); extern double asinh __P((double)); extern double atanh __P((double)); extern double cbrt __P((double)); extern double logb __P((double)); extern double nextafter __P((double, double)); extern double remainder __P((double, double)); #ifdef _SCALB_INT extern double scalb __P((double, int)); #else extern double scalb __P((double, double)); #endif extern int matherr __P((struct exception *)); /* * IEEE Test Vector */ extern double significand __P((double)); /* * Functions callable from C, intended to support IEEE arithmetic. */ extern double copysign __P((double, double)); extern int ilogb __P((double)); extern double rint __P((double)); extern double scalbn __P((double, int)); /* * BSD math library entry points */ extern double expm1 __P((double)); extern double log1p __P((double)); /* * Reentrant version of gamma & lgamma; passes signgam back by reference * as the second argument; user must allocate space for signgam. */ #ifdef _REENTRANT extern double gamma_r __P((double, int *)); extern double lgamma_r __P((double, int *)); #endif /* _REENTRANT */ /* ieee style elementary functions */ extern double __ieee754_sqrt __P((double)); extern double __ieee754_acos __P((double)); extern double __ieee754_acosh __P((double)); extern double __ieee754_log __P((double)); extern double __ieee754_atanh __P((double)); extern double __ieee754_atan __P((double)); extern double __ieee754_asin __P((double)); extern double __ieee754_atan2 __P((double,double)); extern double __ieee754_exp __P((double)); extern double __ieee754_cosh __P((double)); extern double __ieee754_fmod __P((double,double)); extern double __ieee754_pow __P((double,double)); extern double __ieee754_lgamma_r __P((double,int *)); extern double __ieee754_gamma_r __P((double,int *)); extern double __ieee754_lgamma __P((double)); extern double __ieee754_gamma __P((double)); extern double __ieee754_log10 __P((double)); extern double __ieee754_sinh __P((double)); extern double __ieee754_hypot __P((double,double)); extern double __ieee754_j0 __P((double)); extern double __ieee754_j1 __P((double)); extern double __ieee754_y0 __P((double)); extern double __ieee754_y1 __P((double)); extern double __ieee754_jn __P((int,double)); extern double __ieee754_yn __P((int,double)); extern double __ieee754_remainder __P((double,double)); extern int __ieee754_rem_pio2 __P((double,double*)); #ifdef _SCALB_INT extern double __ieee754_scalb __P((double,int)); #else extern double __ieee754_scalb __P((double,double)); #endif /* fdlibm kernel function */ extern double __kernel_standard __P((double,double,int)); extern double __kernel_sin __P((double,double,int)); extern double __kernel_cos __P((double,double)); extern double __kernel_tan __P((double,double,int)); extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*)); ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/index ================================================ file fdlibm/fdlibm.h file fdlibm/index file fdlibm/e_acos.c file fdlibm/e_acosh.c file fdlibm/e_asin.c file fdlibm/e_atan2.c file fdlibm/e_atanh.c file fdlibm/e_cosh.c file fdlibm/e_exp.c file fdlibm/e_fmod.c file fdlibm/e_gamma.c file fdlibm/e_gamma_r.c file fdlibm/e_hypot.c file fdlibm/e_j0.c file fdlibm/e_j1.c file fdlibm/e_jn.c file fdlibm/e_lgamma.c file fdlibm/e_lgamma_r.c file fdlibm/e_log.c file fdlibm/e_log10.c file fdlibm/e_pow.c file fdlibm/e_rem_pio2.c file fdlibm/e_remainder.c file fdlibm/e_scalb.c file fdlibm/e_sinh.c file fdlibm/e_sqrt.c file fdlibm/k_cos.c file fdlibm/k_rem_pio2.c file fdlibm/k_sin.c file fdlibm/k_standard.c file fdlibm/k_tan.c file fdlibm/makefile file fdlibm/s_asinh.c file fdlibm/s_atan.c file fdlibm/s_cbrt.c file fdlibm/s_ceil.c file fdlibm/s_copysign.c file fdlibm/s_cos.c file fdlibm/s_erf.c file fdlibm/s_expm1.c file fdlibm/s_fabs.c file fdlibm/s_finite.c file fdlibm/s_floor.c file fdlibm/s_frexp.c file fdlibm/s_ilogb.c file fdlibm/s_isnan.c file fdlibm/s_ldexp.c file fdlibm/s_lib_version.c file fdlibm/s_log1p.c file fdlibm/s_logb.c file fdlibm/s_matherr.c file fdlibm/s_modf.c file fdlibm/s_nextafter.c file fdlibm/s_rint.c file fdlibm/s_scalbn.c file fdlibm/s_signgam.c file fdlibm/s_significand.c file fdlibm/s_sin.c file fdlibm/s_tan.c file fdlibm/s_tanh.c file fdlibm/w_acos.c file fdlibm/w_acosh.c file fdlibm/w_asin.c file fdlibm/w_atan2.c file fdlibm/w_atanh.c file fdlibm/w_cosh.c file fdlibm/w_exp.c file fdlibm/w_fmod.c file fdlibm/w_gamma.c file fdlibm/w_gamma_r.c file fdlibm/w_hypot.c file fdlibm/w_j0.c file fdlibm/w_j1.c file fdlibm/w_jn.c file fdlibm/w_lgamma.c file fdlibm/w_lgamma_r.c file fdlibm/w_log.c file fdlibm/w_log10.c file fdlibm/w_pow.c file fdlibm/w_remainder.c file fdlibm/w_scalb.c file fdlibm/w_sinh.c file fdlibm/w_sqrt.c file fdlibm/readme ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/index.html ================================================ fdlibm

fdlibm

Click here to see the number of accesses to this library.


file	fdlibm.h

file	index

file	e_acos.c  e_acos.c plus dependencies

file	e_acosh.c  e_acosh.c plus dependencies

file	e_asin.c  e_asin.c plus dependencies

file	e_atan2.c  e_atan2.c plus dependencies

file	e_atanh.c  e_atanh.c plus dependencies

file	e_cosh.c  e_cosh.c plus dependencies

file	e_exp.c  e_exp.c plus dependencies

file	e_fmod.c  e_fmod.c plus dependencies

file	e_gamma.c  e_gamma.c plus dependencies

file	e_gamma_r.c  e_gamma_r.c plus dependencies

file	e_hypot.c  e_hypot.c plus dependencies

file	e_j0.c  e_j0.c plus dependencies

file	e_j1.c  e_j1.c plus dependencies

file	e_jn.c  e_jn.c plus dependencies

file	e_lgamma.c  e_lgamma.c plus dependencies

file	e_lgamma_r.c  e_lgamma_r.c plus dependencies

file	e_log.c  e_log.c plus dependencies

file	e_log10.c  e_log10.c plus dependencies

file	e_pow.c  e_pow.c plus dependencies

file	e_rem_pio2.c  e_rem_pio2.c plus dependencies

file	e_remainder.c  e_remainder.c plus dependencies

file	e_scalb.c  e_scalb.c plus dependencies

file	e_sinh.c  e_sinh.c plus dependencies

file	e_sqrt.c  e_sqrt.c plus dependencies

file	k_cos.c  k_cos.c plus dependencies

file	k_rem_pio2.c  k_rem_pio2.c plus dependencies

file	k_sin.c  k_sin.c plus dependencies

file	k_standard.c  k_standard.c plus dependencies

file	k_tan.c  k_tan.c plus dependencies

file	makefile

file	s_asinh.c  s_asinh.c plus dependencies

file	s_atan.c  s_atan.c plus dependencies

file	s_cbrt.c  s_cbrt.c plus dependencies

file	s_ceil.c  s_ceil.c plus dependencies

file	s_copysign.c  s_copysign.c plus dependencies

file	s_cos.c  s_cos.c plus dependencies

file	s_erf.c  s_erf.c plus dependencies

file	s_expm1.c  s_expm1.c plus dependencies

file	s_fabs.c  s_fabs.c plus dependencies

file	s_finite.c  s_finite.c plus dependencies

file	s_floor.c  s_floor.c plus dependencies

file	s_frexp.c  s_frexp.c plus dependencies

file	s_ilogb.c  s_ilogb.c plus dependencies

file	s_isnan.c  s_isnan.c plus dependencies

file	s_ldexp.c  s_ldexp.c plus dependencies

file	s_lib_version.c  s_lib_version.c plus dependencies

file	s_log1p.c  s_log1p.c plus dependencies

file	s_logb.c  s_logb.c plus dependencies

file	s_matherr.c  s_matherr.c plus dependencies

file	s_modf.c  s_modf.c plus dependencies

file	s_nextafter.c  s_nextafter.c plus dependencies

file	s_rint.c  s_rint.c plus dependencies

file	s_scalbn.c  s_scalbn.c plus dependencies

file	s_signgam.c  s_signgam.c plus dependencies

file	s_significand.c  s_significand.c plus dependencies

file	s_sin.c  s_sin.c plus dependencies

file	s_tan.c  s_tan.c plus dependencies

file	s_tanh.c  s_tanh.c plus dependencies

file	w_acos.c  w_acos.c plus dependencies

file	w_acosh.c  w_acosh.c plus dependencies

file	w_asin.c  w_asin.c plus dependencies

file	w_atan2.c  w_atan2.c plus dependencies

file	w_atanh.c  w_atanh.c plus dependencies

file	w_cosh.c  w_cosh.c plus dependencies

file	w_exp.c  w_exp.c plus dependencies

file	w_fmod.c  w_fmod.c plus dependencies

file	w_gamma.c  w_gamma.c plus dependencies

file	w_gamma_r.c  w_gamma_r.c plus dependencies

file	w_hypot.c  w_hypot.c plus dependencies

file	w_j0.c  w_j0.c plus dependencies

file	w_j1.c  w_j1.c plus dependencies

file	w_jn.c  w_jn.c plus dependencies

file	w_lgamma.c  w_lgamma.c plus dependencies

file	w_lgamma_r.c  w_lgamma_r.c plus dependencies

file	w_log.c  w_log.c plus dependencies

file	w_log10.c  w_log10.c plus dependencies

file	w_pow.c  w_pow.c plus dependencies

file	w_remainder.c  w_remainder.c plus dependencies

file	w_scalb.c  w_scalb.c plus dependencies

file	w_sinh.c  w_sinh.c plus dependencies

file	w_sqrt.c  w_sqrt.c plus dependencies

file	readme

================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/k_cos.c ================================================ /* @(#)k_cos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __kernel_cos( x, y ) * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * * Algorithm * 1. Since cos(-x) = cos(x), we need only to consider positive x. * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. * 3. cos(x) is approximated by a polynomial of degree 14 on * [0,pi/4] * 4 14 * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x * where the remez error is * * | 2 4 6 8 10 12 14 | -58 * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 * | | * * 4 6 8 10 12 14 * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then * cos(x) = 1 - x*x/2 + r * since cos(x+y) ~ cos(x) - sin(x)*y * ~ cos(x) - x*y, * a correction term is necessary in cos(x) and hence * cos(x+y) = 1 - (x*x/2 - (r - x*y)) * For better accuracy when x > 0.3, let qx = |x|/4 with * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. * Then * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). * Note that 1-qx and (x*x/2-qx) is EXACT here, and the * magnitude of the latter is at least a quarter of x*x/2, * thus, reducing the rounding error in the subtraction. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ #ifdef __STDC__ double __kernel_cos(double x, double y) #else double __kernel_cos(x, y) double x,y; #endif { double a,hz,z,r,qx; int ix; ix = __HI(x)&0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); if(ix < 0x3FD33333) /* if |x| < 0.3 */ return one - (0.5*z - (z*r - x*y)); else { if(ix > 0x3fe90000) { /* x > 0.78125 */ qx = 0.28125; } else { __HI(qx) = ix-0x00200000; /* x/4 */ __LO(qx) = 0; } hz = 0.5*z-qx; a = one-qx; return a - (hz - (z*r-x*y)); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/k_rem_pio2.c ================================================ /* @(#)k_rem_pio2.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) * double x[],y[]; int e0,nx,prec; int ipio2[]; * * __kernel_rem_pio2 return the last three digits of N with * y = x - N*pi/2 * so that |y| < pi/2. * * The method is to compute the integer (mod 8) and fraction parts of * (2/pi)*x without doing the full multiplication. In general we * skip the part of the product that are known to be a huge integer ( * more accurately, = 0 mod 8 ). Thus the number of operations are * independent of the exponent of the input. * * (2/pi) is represented by an array of 24-bit integers in ipio2[]. * * Input parameters: * x[] The input value (must be positive) is broken into nx * pieces of 24-bit integers in double precision format. * x[i] will be the i-th 24 bit of x. The scaled exponent * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 * match x's up to 24 bits. * * Example of breaking a double positive z into x[0]+x[1]+x[2]: * e0 = ilogb(z)-23 * z = scalbn(z,-e0) * for i = 0,1,2 * x[i] = floor(z) * z = (z-x[i])*2**24 * * * y[] ouput result in an array of double precision numbers. * The dimension of y[] is: * 24-bit precision 1 * 53-bit precision 2 * 64-bit precision 2 * 113-bit precision 3 * The actual value is the sum of them. Thus for 113-bit * precison, one may have to do something like: * * long double t,w,r_head, r_tail; * t = (long double)y[2] + (long double)y[1]; * w = (long double)y[0]; * r_head = t+w; * r_tail = w - (r_head - t); * * e0 The exponent of x[0] * * nx dimension of x[] * * prec an integer indicating the precision: * 0 24 bits (single) * 1 53 bits (double) * 2 64 bits (extended) * 3 113 bits (quad) * * ipio2[] * integer array, contains the (24*i)-th to (24*i+23)-th * bit of 2/pi after binary point. The corresponding * floating value is * * ipio2[i] * 2^(-24(i+1)). * * External function: * double scalbn(), floor(); * * * Here is the description of some local variables: * * jk jk+1 is the initial number of terms of ipio2[] needed * in the computation. The recommended value is 2,3,4, * 6 for single, double, extended,and quad. * * jz local integer variable indicating the number of * terms of ipio2[] used. * * jx nx - 1 * * jv index for pointing to the suitable ipio2[] for the * computation. In general, we want * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 * is an integer. Thus * e0-3-24*jv >= 0 or (e0-3)/24 >= jv * Hence jv = max(0,(e0-3)/24). * * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. * * q[] double array with integral value, representing the * 24-bits chunk of the product of x and 2/pi. * * q0 the corresponding exponent of q[0]. Note that the * exponent for q[i] would be q0-24*i. * * PIo2[] double precision array, obtained by cutting pi/2 * into 24 bits chunks. * * f[] ipio2[] in floating point * * iq[] integer array by breaking up q[] in 24-bits chunk. * * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] * * ih integer. If >0 it indicates q[] is >= 0.5, hence * it also indicates the *sign* of the result. * */ /* * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ #else static int init_jk[] = {2,3,4,6}; #endif #ifdef __STDC__ static const double PIo2[] = { #else static double PIo2[] = { #endif 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ }; #ifdef __STDC__ static const double #else static double #endif zero = 0.0, one = 1.0, two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ #ifdef __STDC__ int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int *ipio2) #else int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) double x[], y[]; int e0,nx,prec; int ipio2[]; #endif { int jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; double z,fw,f[20],fq[20],q[20]; /* initialize jk*/ jk = init_jk[prec]; jp = jk; /* determine jx,jv,q0, note that 3>q0 */ jx = nx-1; jv = (e0-3)/24; if(jv<0) jv=0; q0 = e0-24*(jv+1); /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ j = jv-jx; m = jx+jk; for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; /* compute q[0],q[1],...q[jk] */ for (i=0;i<=jk;i++) { for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz = jk; recompute: /* distill q[] into iq[] reversingly */ for(i=0,j=jz,z=q[jz];j>0;i++,j--) { fw = (double)((int)(twon24* z)); iq[i] = (int)(z-two24*fw); z = q[j-1]+fw; } /* compute n */ z = scalbn(z,q0); /* actual value of z */ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ n = (int) z; z -= (double)n; ih = 0; if(q0>0) { /* need iq[jz-1] to determine n */ i = (iq[jz-1]>>(24-q0)); n += i; iq[jz-1] -= i<<(24-q0); ih = iq[jz-1]>>(23-q0); } else if(q0==0) ih = iq[jz-1]>>23; else if(z>=0.5) ih=2; if(ih>0) { /* q > 0.5 */ n += 1; carry = 0; for(i=0;i0) { /* rare case: chance is 1 in 12 */ switch(q0) { case 1: iq[jz-1] &= 0x7fffff; break; case 2: iq[jz-1] &= 0x3fffff; break; } } if(ih==2) { z = one - z; if(carry!=0) z -= scalbn(one,q0); } } /* check if recomputation is needed */ if(z==zero) { j = 0; for (i=jz-1;i>=jk;i--) j |= iq[i]; if(j==0) { /* need recomputation */ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ f[jx+i] = (double) ipio2[jv+i]; for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz += k; goto recompute; } } /* chop off zero terms */ if(z==0.0) { jz -= 1; q0 -= 24; while(iq[jz]==0) { jz--; q0-=24;} } else { /* break z into 24-bit if necessary */ z = scalbn(z,-q0); if(z>=two24) { fw = (double)((int)(twon24*z)); iq[jz] = (int)(z-two24*fw); jz += 1; q0 += 24; iq[jz] = (int) fw; } else iq[jz] = (int) z ; } /* convert integer "bit" chunk to floating-point value */ fw = scalbn(one,q0); for(i=jz;i>=0;i--) { q[i] = fw*(double)iq[i]; fw*=twon24; } /* compute PIo2[0,...,jp]*q[jz,...,0] */ for(i=jz;i>=0;i--) { for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; fq[jz-i] = fw; } /* compress fq[] into y[] */ switch(prec) { case 0: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; y[0] = (ih==0)? fw: -fw; break; case 1: case 2: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; y[0] = (ih==0)? fw: -fw; fw = fq[0]-fw; for (i=1;i<=jz;i++) fw += fq[i]; y[1] = (ih==0)? fw: -fw; break; case 3: /* painful */ for (i=jz;i>0;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (i=jz;i>1;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; if(ih==0) { y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; } else { y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; } } return n&7; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/k_sin.c ================================================ /* @(#)k_sin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __kernel_sin( x, y, iy) * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). * * Algorithm * 1. Since sin(-x) = -sin(x), we need only to consider positive x. * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. * 3. sin(x) is approximated by a polynomial of degree 13 on * [0,pi/4] * 3 13 * sin(x) ~ x + S1*x + ... + S6*x * where * * |sin(x) 2 4 6 8 10 12 | -58 * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 * | x | * * 4. sin(x+y) = sin(x) + sin'(x')*y * ~ sin(x) + (1-x*x/2)*y * For better accuracy, let * 3 2 2 2 2 * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) * then 3 2 * sin(x) = x + (S1*x + (x *(r-y/2)+y)) */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ #ifdef __STDC__ double __kernel_sin(double x, double y, int iy) #else double __kernel_sin(x, y, iy) double x,y; int iy; /* iy=0 if y is zero */ #endif { double z,r,v; int ix; ix = __HI(x)&0x7fffffff; /* high word of x */ if(ix<0x3e400000) /* |x| < 2**-27 */ {if((int)x==0) return x;} /* generate inexact */ z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*S6))); if(iy==0) return x+v*(S1+z*r); else return x-((z*(half*y-v*r)-y)-v*S1); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/k_standard.c ================================================ /* @(#)k_standard.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ #include "fdlibm.h" #include #ifndef _USE_WRITE #include /* fputs(), stderr */ #define WRITE2(u,v) fputs(u, stderr) #else /* !defined(_USE_WRITE) */ #include /* write */ #define WRITE2(u,v) write(2, u, v) #undef fflush #endif /* !defined(_USE_WRITE) */ static double zero = 0.0; /* used as const */ /* * Standard conformance (non-IEEE) on exception cases. * Mapping: * 1 -- acos(|x|>1) * 2 -- asin(|x|>1) * 3 -- atan2(+-0,+-0) * 4 -- hypot overflow * 5 -- cosh overflow * 6 -- exp overflow * 7 -- exp underflow * 8 -- y0(0) * 9 -- y0(-ve) * 10-- y1(0) * 11-- y1(-ve) * 12-- yn(0) * 13-- yn(-ve) * 14-- lgamma(finite) overflow * 15-- lgamma(-integer) * 16-- log(0) * 17-- log(x<0) * 18-- log10(0) * 19-- log10(x<0) * 20-- pow(0.0,0.0) * 21-- pow(x,y) overflow * 22-- pow(x,y) underflow * 23-- pow(0,negative) * 24-- pow(neg,non-integral) * 25-- sinh(finite) overflow * 26-- sqrt(negative) * 27-- fmod(x,0) * 28-- remainder(x,0) * 29-- acosh(x<1) * 30-- atanh(|x|>1) * 31-- atanh(|x|=1) * 32-- scalb overflow * 33-- scalb underflow * 34-- j0(|x|>X_TLOSS) * 35-- y0(x>X_TLOSS) * 36-- j1(|x|>X_TLOSS) * 37-- y1(x>X_TLOSS) * 38-- jn(|x|>X_TLOSS, n) * 39-- yn(x>X_TLOSS, n) * 40-- gamma(finite) overflow * 41-- gamma(-integer) * 42-- pow(NaN,0.0) */ #ifdef __STDC__ double __kernel_standard(double x, double y, int type) #else double __kernel_standard(x,y,type) double x,y; int type; #endif { struct exception exc; #ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ #define HUGE_VAL inf double inf = 0.0; __HI(inf) = 0x7ff00000; /* set inf to infinite */ #endif #ifdef _USE_WRITE (void) fflush(stdout); #endif exc.arg1 = x; exc.arg2 = y; switch(type) { case 1: /* acos(|x|>1) */ exc.type = DOMAIN; exc.name = "acos"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if(_LIB_VERSION == _SVID_) { (void) WRITE2("acos: DOMAIN error\n", 19); } errno = EDOM; } break; case 2: /* asin(|x|>1) */ exc.type = DOMAIN; exc.name = "asin"; exc.retval = zero; if(_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if(_LIB_VERSION == _SVID_) { (void) WRITE2("asin: DOMAIN error\n", 19); } errno = EDOM; } break; case 3: /* atan2(+-0,+-0) */ exc.arg1 = y; exc.arg2 = x; exc.type = DOMAIN; exc.name = "atan2"; exc.retval = zero; if(_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if(_LIB_VERSION == _SVID_) { (void) WRITE2("atan2: DOMAIN error\n", 20); } errno = EDOM; } break; case 4: /* hypot(finite,finite) overflow */ exc.type = OVERFLOW; exc.name = "hypot"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 5: /* cosh(finite) overflow */ exc.type = OVERFLOW; exc.name = "cosh"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 6: /* exp(finite) overflow */ exc.type = OVERFLOW; exc.name = "exp"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 7: /* exp(finite) underflow */ exc.type = UNDERFLOW; exc.name = "exp"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 8: /* y0(0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "y0"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("y0: DOMAIN error\n", 17); } errno = EDOM; } break; case 9: /* y0(x<0) = NaN */ exc.type = DOMAIN; exc.name = "y0"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("y0: DOMAIN error\n", 17); } errno = EDOM; } break; case 10: /* y1(0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "y1"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("y1: DOMAIN error\n", 17); } errno = EDOM; } break; case 11: /* y1(x<0) = NaN */ exc.type = DOMAIN; exc.name = "y1"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("y1: DOMAIN error\n", 17); } errno = EDOM; } break; case 12: /* yn(n,0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "yn"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("yn: DOMAIN error\n", 17); } errno = EDOM; } break; case 13: /* yn(x<0) = NaN */ exc.type = DOMAIN; exc.name = "yn"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("yn: DOMAIN error\n", 17); } errno = EDOM; } break; case 14: /* lgamma(finite) overflow */ exc.type = OVERFLOW; exc.name = "lgamma"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 15: /* lgamma(-integer) or lgamma(0) */ exc.type = SING; exc.name = "lgamma"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("lgamma: SING error\n", 19); } errno = EDOM; } break; case 16: /* log(0) */ exc.type = SING; exc.name = "log"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("log: SING error\n", 16); } errno = EDOM; } break; case 17: /* log(x<0) */ exc.type = DOMAIN; exc.name = "log"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("log: DOMAIN error\n", 18); } errno = EDOM; } break; case 18: /* log10(0) */ exc.type = SING; exc.name = "log10"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("log10: SING error\n", 18); } errno = EDOM; } break; case 19: /* log10(x<0) */ exc.type = DOMAIN; exc.name = "log10"; if (_LIB_VERSION == _SVID_) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("log10: DOMAIN error\n", 20); } errno = EDOM; } break; case 20: /* pow(0.0,0.0) */ /* error only if _LIB_VERSION == _SVID_ */ exc.type = DOMAIN; exc.name = "pow"; exc.retval = zero; if (_LIB_VERSION != _SVID_) exc.retval = 1.0; else if (!matherr(&exc)) { (void) WRITE2("pow(0,0): DOMAIN error\n", 23); errno = EDOM; } break; case 21: /* pow(x,y) overflow */ exc.type = OVERFLOW; exc.name = "pow"; if (_LIB_VERSION == _SVID_) { exc.retval = HUGE; y *= 0.5; if(xzero) ? HUGE : -HUGE); else exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 26: /* sqrt(x<0) */ exc.type = DOMAIN; exc.name = "sqrt"; if (_LIB_VERSION == _SVID_) exc.retval = zero; else exc.retval = zero/zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("sqrt: DOMAIN error\n", 19); } errno = EDOM; } break; case 27: /* fmod(x,0) */ exc.type = DOMAIN; exc.name = "fmod"; if (_LIB_VERSION == _SVID_) exc.retval = x; else exc.retval = zero/zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("fmod: DOMAIN error\n", 20); } errno = EDOM; } break; case 28: /* remainder(x,0) */ exc.type = DOMAIN; exc.name = "remainder"; exc.retval = zero/zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("remainder: DOMAIN error\n", 24); } errno = EDOM; } break; case 29: /* acosh(x<1) */ exc.type = DOMAIN; exc.name = "acosh"; exc.retval = zero/zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("acosh: DOMAIN error\n", 20); } errno = EDOM; } break; case 30: /* atanh(|x|>1) */ exc.type = DOMAIN; exc.name = "atanh"; exc.retval = zero/zero; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("atanh: DOMAIN error\n", 20); } errno = EDOM; } break; case 31: /* atanh(|x|=1) */ exc.type = SING; exc.name = "atanh"; exc.retval = x/zero; /* sign(x)*inf */ if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("atanh: SING error\n", 18); } errno = EDOM; } break; case 32: /* scalb overflow; SVID also returns +-HUGE_VAL */ exc.type = OVERFLOW; exc.name = "scalb"; exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 33: /* scalb underflow */ exc.type = UNDERFLOW; exc.name = "scalb"; exc.retval = copysign(zero,x); if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 34: /* j0(|x|>X_TLOSS) */ exc.type = TLOSS; exc.name = "j0"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 35: /* y0(x>X_TLOSS) */ exc.type = TLOSS; exc.name = "y0"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 36: /* j1(|x|>X_TLOSS) */ exc.type = TLOSS; exc.name = "j1"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 37: /* y1(x>X_TLOSS) */ exc.type = TLOSS; exc.name = "y1"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 38: /* jn(|x|>X_TLOSS) */ exc.type = TLOSS; exc.name = "jn"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 39: /* yn(x>X_TLOSS) */ exc.type = TLOSS; exc.name = "yn"; exc.retval = zero; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2(exc.name, 2); (void) WRITE2(": TLOSS error\n", 14); } errno = ERANGE; } break; case 40: /* gamma(finite) overflow */ exc.type = OVERFLOW; exc.name = "gamma"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } break; case 41: /* gamma(-integer) or gamma(0) */ exc.type = SING; exc.name = "gamma"; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { if (_LIB_VERSION == _SVID_) { (void) WRITE2("gamma: SING error\n", 18); } errno = EDOM; } break; case 42: /* pow(NaN,0.0) */ /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ exc.type = DOMAIN; exc.name = "pow"; exc.retval = x; if (_LIB_VERSION == _IEEE_ || _LIB_VERSION == _POSIX_) exc.retval = 1.0; else if (!matherr(&exc)) { errno = EDOM; } break; } return exc.retval; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/k_tan.c ================================================ #pragma ident "@(#)k_tan.c 1.5 04/04/22 SMI" /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* INDENT OFF */ /* __kernel_tan( x, y, k ) * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned. * * Algorithm * 1. Since tan(-x) = -tan(x), we need only to consider positive x. * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. * 3. tan(x) is approximated by a odd polynomial of degree 27 on * [0,0.67434] * 3 27 * tan(x) ~ x + T1*x + ... + T13*x * where * * |tan(x) 2 4 26 | -59.2 * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 * | x | * * Note: tan(x+y) = tan(x) + tan'(x)*y * ~ tan(x) + (1+x*x)*y * Therefore, for better accuracy in computing tan(x+y), let * 3 2 2 2 2 * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) * then * 3 2 * tan(x+y) = x + (T1*x + (x *(r+y)+y)) * * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) */ #include "fdlibm.h" static const double xxx[] = { 3.33333333333334091986e-01, /* 3FD55555, 55555563 */ 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */ 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */ 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */ 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */ 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */ 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */ 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */ 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */ 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */ 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */ -1.85586374855275456654e-05, /* BEF375CB, DB605373 */ 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */ /* one */ 1.00000000000000000000e+00, /* 3FF00000, 00000000 */ /* pio4 */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */ /* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */ }; #define one xxx[13] #define pio4 xxx[14] #define pio4lo xxx[15] #define T xxx /* INDENT ON */ double __kernel_tan(double x, double y, int iy) { double z, r, v, w, s; int ix, hx; hx = __HI(x); /* high word of x */ ix = hx & 0x7fffffff; /* high word of |x| */ if (ix < 0x3e300000) { /* x < 2**-28 */ if ((int) x == 0) { /* generate inexact */ if (((ix | __LO(x)) | (iy + 1)) == 0) return one / fabs(x); else { if (iy == 1) return x; else { /* compute -1 / (x+y) carefully */ double a, t; z = w = x + y; __LO(z) = 0; v = y - (z - x); t = a = -one / w; __LO(t) = 0; s = one + t * z; return t + a * (s + t * v); } } } } if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */ if (hx < 0) { x = -x; y = -y; } z = pio4 - x; w = pio4lo - y; x = z + w; y = 0.0; } z = x * x; w = z * z; /* * Break x^5*(T[1]+x^2*T[2]+...) into * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) */ r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11])))); v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12]))))); s = z * x; r = y + z * (s * (r + v) + y); r += T[0] * s; w = x + r; if (ix >= 0x3FE59428) { v = (double) iy; return (double) (1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r))); } if (iy == 1) return w; else { /* * if allow error up to 2 ulp, simply return * -1.0 / (x+r) here */ /* compute -1.0 / (x+r) accurately */ double a, t; z = w; __LO(z) = 0; v = r - (z - x); /* z+v = r+x */ t = a = -1.0 / w; /* a = -1.0/w */ __LO(t) = 0; s = 1.0 + t * z; return t + a * (s + t * v); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/makefile ================================================ # # @(#)Makefile 1.4 95/01/18 # # ==================================================== # Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. # # Developed at SunSoft, a Sun Microsystems, Inc. business. # Permission to use, copy, modify, and distribute this # software is freely granted, provided that this notice # is preserved. # ==================================================== # # # # There are two options in making libm at fdlibm compile time: # _IEEE_LIBM --- IEEE libm; smaller, and somewhat faster # _MULTI_LIBM --- Support multi-standard at runtime by # imposing wrapper functions defined in # fdlibm.h: # _IEEE_MODE -- IEEE # _XOPEN_MODE -- X/OPEN # _POSIX_MODE -- POSIX/ANSI # _SVID3_MODE -- SVID # # Here is how to set up CFLAGS to create the desired libm at # compile time: # # CFLAGS = -D_IEEE_LIBM ... IEEE libm (recommended) # CFLAGS = -D_SVID3_MODE ... Multi-standard supported # libm with SVID as the # default standard # CFLAGS = -D_XOPEN_MODE ... Multi-standard supported # libm with XOPEN as the # default standard # CFLAGS = -D_POSIX_MODE ... Multi-standard supported # libm with POSIX as the # default standard # CFLAGS = ... Multi-standard supported # libm with IEEE as the # default standard # # NOTE: if scalb's second arguement is an int, then one must # define _SCALB_INT in CFLAGS. The default prototype of scalb # is double scalb(double, double) # # # Default IEEE libm # CFLAGS = -D_IEEE_LIBM CC = cc INCFILES = fdlibm.h .INIT: $(INCFILES) .KEEP_STATE: src = k_standard.c k_rem_pio2.c \ k_cos.c k_sin.c k_tan.c \ e_acos.c e_acosh.c e_asin.c e_atan2.c \ e_atanh.c e_cosh.c e_exp.c e_fmod.c \ e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c \ e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \ e_scalb.c e_sinh.c e_sqrt.c \ w_acos.c w_acosh.c w_asin.c w_atan2.c \ w_atanh.c w_cosh.c w_exp.c w_fmod.c \ w_gamma.c w_gamma_r.c w_hypot.c w_j0.c \ w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ w_log.c w_log10.c w_pow.c w_remainder.c \ w_scalb.c w_sinh.c w_sqrt.c \ s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c \ s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \ s_frexp.c s_ilogb.c s_isnan.c s_ldexp.c s_lib_version.c \ s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \ s_tan.c s_tanh.c obj = k_standard.o k_rem_pio2.o \ k_cos.o k_sin.o k_tan.o \ e_acos.o e_acosh.o e_asin.o e_atan2.o \ e_atanh.o e_cosh.o e_exp.o e_fmod.o \ e_gamma.o e_gamma_r.o e_hypot.o e_j0.o \ e_j1.o e_jn.o e_lgamma.o e_lgamma_r.o \ e_log.o e_log10.o e_pow.o e_rem_pio2.o e_remainder.o \ e_scalb.o e_sinh.o e_sqrt.o \ w_acos.o w_acosh.o w_asin.o w_atan2.o \ w_atanh.o w_cosh.o w_exp.o w_fmod.o \ w_gamma.o w_gamma_r.o w_hypot.o w_j0.o \ w_j1.o w_jn.o w_lgamma.o w_lgamma_r.o \ w_log.o w_log10.o w_pow.o w_remainder.o \ w_scalb.o w_sinh.o w_sqrt.o \ s_asinh.o s_atan.o s_cbrt.o s_ceil.o s_copysign.o \ s_cos.o s_erf.o s_expm1.o s_fabs.o s_finite.o s_floor.o \ s_frexp.o s_ilogb.o s_isnan.o s_ldexp.o s_lib_version.o \ s_log1p.o s_logb.o s_matherr.o s_modf.o s_nextafter.o \ s_rint.o s_scalbn.o s_signgam.o s_significand.o s_sin.o \ s_tan.o s_tanh.o all: libm.a libm.a : $(obj) ar cru libm.a $(obj) ranlib libm.a source: $(src) README clean: /bin/rm -f $(obj) a.out libm.a ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/makefile.in ================================================ # # @(#)Makefile 1.4 95/01/18 # # ==================================================== # Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. # # Developed at SunSoft, a Sun Microsystems, Inc. business. # Permission to use, copy, modify, and distribute this # software is freely granted, provided that this notice # is preserved. # ==================================================== # # # # There are two options in making libm at fdlibm compile time: # _IEEE_LIBM --- IEEE libm; smaller, and somewhat faster # _MULTI_LIBM --- Support multi-standard at runtime by # imposing wrapper functions defined in # fdlibm.h: # _IEEE_MODE -- IEEE # _XOPEN_MODE -- X/OPEN # _POSIX_MODE -- POSIX/ANSI # _SVID3_MODE -- SVID # # Here is how to set up CFLAGS to create the desired libm at # compile time: # # CFLAGS = -D_IEEE_LIBM ... IEEE libm (recommended) # CFLAGS = -D_SVID3_MODE ... Multi-standard supported # libm with SVID as the # default standard # CFLAGS = -D_XOPEN_MODE ... Multi-standard supported # libm with XOPEN as the # default standard # CFLAGS = -D_POSIX_MODE ... Multi-standard supported # libm with POSIX as the # default standard # CFLAGS = ... Multi-standard supported # libm with IEEE as the # default standard # # NOTE: if scalb's second arguement is an int, then one must # define _SCALB_INT in CFLAGS. The default prototype of scalb # is double scalb(double, double) # prefix = @prefix@ AR = @AR@ CC = @CC@ # # Default IEEE libm # CFLAGS = @CFLAGS@ -D_IEEE_LIBM CHMOD = @CHMOD@ CP = @CP@ INCFILES = fdlibm.h LDFLAGS = @LDFLAGS@ LIB = libfdm.a LIBS = @LIBS@ RANLIB = @RANLIB@ RM = @RM@ -f .INIT: $(INCFILES) .KEEP_STATE: src = k_standard.c k_rem_pio2.c \ k_cos.c k_sin.c k_tan.c \ e_acos.c e_acosh.c e_asin.c e_atan2.c \ e_atanh.c e_cosh.c e_exp.c e_fmod.c \ e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c \ e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \ e_scalb.c e_sinh.c e_sqrt.c \ w_acos.c w_acosh.c w_asin.c w_atan2.c \ w_atanh.c w_cosh.c w_exp.c w_fmod.c \ w_gamma.c w_gamma_r.c w_hypot.c w_j0.c \ w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ w_log.c w_log10.c w_pow.c w_remainder.c \ w_scalb.c w_sinh.c w_sqrt.c \ s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c \ s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \ s_frexp.c s_ilogb.c s_isnan.c s_ldexp.c s_lib_version.c \ s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \ s_tan.c s_tanh.c obj = k_standard.o k_rem_pio2.o \ k_cos.o k_sin.o k_tan.o \ e_acos.o e_acosh.o e_asin.o e_atan2.o \ e_atanh.o e_cosh.o e_exp.o e_fmod.o \ e_gamma.o e_gamma_r.o e_hypot.o e_j0.o \ e_j1.o e_jn.o e_lgamma.o e_lgamma_r.o \ e_log.o e_log10.o e_pow.o e_rem_pio2.o e_remainder.o \ e_scalb.o e_sinh.o e_sqrt.o \ w_acos.o w_acosh.o w_asin.o w_atan2.o \ w_atanh.o w_cosh.o w_exp.o w_fmod.o \ w_gamma.o w_gamma_r.o w_hypot.o w_j0.o \ w_j1.o w_jn.o w_lgamma.o w_lgamma_r.o \ w_log.o w_log10.o w_pow.o w_remainder.o \ w_scalb.o w_sinh.o w_sqrt.o \ s_asinh.o s_atan.o s_cbrt.o s_ceil.o s_copysign.o \ s_cos.o s_erf.o s_expm1.o s_fabs.o s_finite.o s_floor.o \ s_frexp.o s_ilogb.o s_isnan.o s_ldexp.o s_lib_version.o \ s_log1p.o s_logb.o s_matherr.o s_modf.o s_nextafter.o \ s_rint.o s_scalbn.o s_signgam.o s_significand.o s_sin.o \ s_tan.o s_tanh.o all: $(LIB) check: @echo This package does not have a validation suite. clean: -$(RM) *~ #* core a.out distclean: mostlyclean -$(RM) $(LIB) -$(RM) -r autom4te.cache/ -$(RM) config.cache config.log config.status Makefile install: $(LIB) uninstall $(CP) $(LIB) $(prefix)/lib/$(LIB) $(CHMOD) 664 $(prefix)/lib/$(LIB) $(RANLIB) $(prefix)/lib/$(LIB) || true $(LIB) : $(obj) $(AR) cru $(LIB) $(obj) $(RANLIB) $(LIB) || true maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." -$(RM) configure mostlyclean: clean -$(RM) $(obj) source: $(src) README uninstall: -$(RM) $(prefix)/lib/$(LIB) ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/readme ================================================ ********************************* * Announcing FDLIBM Version 5.3 * ********************************* ============================================================ FDLIBM ============================================================ developed at Sun Microsystems, Inc. What's new in FDLIBM 5.3? CONFIGURE To build FDLIBM, edit the supplied Makefile or create a local Makefile by running "sh configure" using the supplied configure script contributed by Nelson Beebe BUGS FIXED 1. e_pow.c incorrect results when x is very close to -1.0 and y is very large, e.g. pow(-1.0000000000000002e+00,4.5035996273704970e+15) = 0 pow(-9.9999999999999978e-01,4.5035996273704970e+15) = 0 Correct results are close to -e and -1/e. 2. k_tan.c error was > 1 ulp target for FDLIBM 5.2: Worst error at least 1.45 ulp at tan(1.7765241907548024E+269) = 1.7733884462610958E+16 5.3: Worst error 0.96 ulp NOT FIXED YET 3. Compiler failure on non-standard code Statements like *(1+(int*)&t1) = 0; are not standard C and cause some optimizing compilers (e.g. GCC) to generate bad code under optimization. These cases are to be addressed in the next release. FDLIBM (Freely Distributable LIBM) is a C math library for machines that support IEEE 754 floating-point arithmetic. In this release, only double precision is supported. FDLIBM is intended to provide a reasonably portable (see assumptions below), reference quality (below one ulp for major functions like sin,cos,exp,log) math library (libm.a). For a copy of FDLIBM, please see http://www.netlib.org/fdlibm/ or http://www.validlab.com/software/ -------------- 1. ASSUMPTIONS -------------- FDLIBM (double precision version) assumes: a. IEEE 754 style (if not precise compliance) arithmetic; b. 32 bit 2's complement integer arithmetic; c. Each double precision floating-point number must be in IEEE 754 double format, and that each number can be retrieved as two 32-bit integers through the using of pointer bashing as in the example below: Example: let y = 2.0 double fp number y: 2.0 IEEE double format: 0x4000000000000000 Referencing y as two integers: *(int*)&y,*(1+(int*)&y) = {0x40000000,0x0} (on sparc) {0x0,0x40000000} (on 386) Note: Four macros are defined in fdlibm.h to handle this kind of retrieving: __HI(x) the high part of a double x (sign,exponent,the first 21 significant bits) __LO(x) the least 32 significant bits of x __HIp(x) same as __HI except that the argument is a pointer to a double __LOp(x) same as __LO except that the argument is a pointer to a double To ensure obtaining correct ordering, one must define __LITTLE_ENDIAN during compilation for little endian machine (like 386,486). The default is big endian. If the behavior of pointer bashing is undefined, one may hack on the macro in fdlibm.h. d. IEEE exceptions may trigger "signals" as is common in Unix implementations. ------------------- 2. EXCEPTION CASES ------------------- All exception cases in the FDLIBM functions will be mapped to one of the following four exceptions: +-huge*huge, +-tiny*tiny, +-1.0/0.0, +-0.0/0.0 (overflow) (underflow) (divided-by-zero) (invalid) For example, log(0) is a singularity and is thus mapped to -1.0/0.0 = -infinity. That is, FDLIBM's log will compute -one/zero and return the computed value. On an IEEE machine, this will trigger the divided-by-zero exception and a negative infinity is returned by default. Similarly, exp(-huge) will be mapped to tiny*tiny to generate an underflow signal. -------------------------------- 3. STANDARD CONFORMANCE WRAPPER -------------------------------- The default FDLIBM functions (compiled with -D_IEEE_LIBM flag) are in "IEEE spirit" (i.e., return the most reasonable result in floating-point arithmetic). If one wants FDLIBM to comply with standards like SVID, X/OPEN, or POSIX/ANSI, then one can create a multi-standard compliant FDLIBM. In this case, each function in FDLIBM is actually a standard compliant wrapper function. File organization: 1. For FDLIBM's kernel (internal) function, File name Entry point --------------------------- k_sin.c __kernel_sin k_tan.c __kernel_tan --------------------------- 2. For functions that have no standards conflict File name Entry point --------------------------- s_sin.c sin s_erf.c erf --------------------------- 3. Ieee754 core functions File name Entry point --------------------------- e_exp.c __ieee754_exp e_sinh.c __ieee754_sinh --------------------------- 4. Wrapper functions File name Entry point --------------------------- w_exp.c exp w_sinh.c sinh --------------------------- Wrapper functions will twist the result of the ieee754 function to comply to the standard specified by the value of _LIB_VERSION if _LIB_VERSION = _IEEE_, return the ieee754 result; if _LIB_VERSION = _SVID_, return SVID result; if _LIB_VERSION = _XOPEN_, return XOPEN result; if _LIB_VERSION = _POSIX_, return POSIX/ANSI result. (These are macros, see fdlibm.h for their definition.) -------------------------------- 4. HOW TO CREATE FDLIBM's libm.a -------------------------------- There are two types of libm.a. One is IEEE only, and the other is multi-standard compliant (supports IEEE,XOPEN,POSIX/ANSI,SVID). To create the IEEE only libm.a, use make "CFLAGS = -D_IEEE_LIBM" This will create an IEEE libm.a, which is smaller in size, and somewhat faster. To create a multi-standard compliant libm, use make "CFLAGS = -D_IEEE_MODE" --- multi-standard fdlibm: default to IEEE make "CFLAGS = -D_XOPEN_MODE" --- multi-standard fdlibm: default to X/OPEN make "CFLAGS = -D_POSIX_MODE" --- multi-standard fdlibm: default to POSIX/ANSI make "CFLAGS = -D_SVID3_MODE" --- multi-standard fdlibm: default to SVID Here is how one makes a SVID compliant libm. Make the library by make "CFLAGS = -D_SVID3_MODE". The libm.a of FDLIBM will be multi-standard compliant and _LIB_VERSION is initialized to the value _SVID_ . example1: --------- main() { double y0(); printf("y0(1e300) = %1.20e\n",y0(1e300)); exit(0); } % cc example1.c libm.a % a.out y0: TLOSS error y0(1e300) = 0.00000000000000000000e+00 It is possible to change the default standard in multi-standard fdlibm. Here is an example of how to do it: example2: --------- #include "fdlibm.h" /* must include FDLIBM's fdlibm.h */ main() { double y0(); _LIB_VERSION = _IEEE_; printf("IEEE: y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _XOPEN_; printf("XOPEN y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _POSIX_; printf("POSIX y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _SVID_; printf("SVID y0(1e300) = %1.20e\n",y0(1e300)); exit(0); } % cc example2.c libm.a % a.out IEEE: y0(1e300) = -1.36813604503424810557e-151 XOPEN y0(1e300) = 0.00000000000000000000e+00 POSIX y0(1e300) = 0.00000000000000000000e+00 y0: TLOSS error SVID y0(1e300) = 0.00000000000000000000e+00 Note: Here _LIB_VERSION is a global variable. If global variables are forbidden, then one should modify fdlibm.h to change _LIB_VERSION to be a global constant. In this case, one may not change the value of _LIB_VERSION as in example2. --------------------------- 5. NOTES ON PORTING FDLIBM --------------------------- Care must be taken when installing FDLIBM over existing libm.a. All co-existing function prototypes must agree, otherwise users will encounter mysterious failures. So far, the only known likely conflict is the declaration of the IEEE recommended function scalb: double scalb(double,double) (1) SVID3 defined double scalb(double,int) (2) IBM,DEC,... FDLIBM follows Sun definition and use (1) as default. If one's existing libm.a uses (2), then one may raise the flags _SCALB_INT during the compilation of FDLIBM to get the correct function prototype. (E.g., make "CFLAGS = -D_IEEE_LIBM -D_SCALB_INT".) NOTE that if -D_SCALB_INT is raised, it won't be SVID3 conformant. -------------- 6. PROBLEMS ? -------------- Please send comments and bug reports to the electronic mail address suggested by: fdlibm-comments AT sun.com ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_asinh.c ================================================ /* @(#)s_asinh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* asinh(x) * Method : * Based on * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] * we have * asinh(x) := x if 1+x*x=1, * := sign(x)*(log(x)+ln2)) for large |x|, else * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ huge= 1.00000000000000000000e+300; #ifdef __STDC__ double asinh(double x) #else double asinh(x) double x; #endif { double t,w; int hx,ix; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */ if(ix< 0x3e300000) { /* |x|<2**-28 */ if(huge+x>one) return x; /* return x inexact except 0 */ } if(ix>0x41b00000) { /* |x| > 2**28 */ w = __ieee754_log(fabs(x))+ln2; } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ t = fabs(x); w = __ieee754_log(2.0*t+one/(sqrt(x*x+one)+t)); } else { /* 2.0 > |x| > 2**-28 */ t = x*x; w =log1p(fabs(x)+t/(one+sqrt(one+t))); } if(hx>0) return w; else return -w; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_atan.c ================================================ /* @(#)s_atan.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* atan(x) * Method * 1. Reduce x to positive by atan(x) = -atan(-x). * 2. According to the integer k=4t+0.25 chopped, t=x, the argument * is further reduced to one of the following intervals and the * arctangent of t is evaluated by the corresponding formula: * * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double atanhi[] = { #else static double atanhi[] = { #endif 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ }; #ifdef __STDC__ static const double atanlo[] = { #else static double atanlo[] = { #endif 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ }; #ifdef __STDC__ static const double aT[] = { #else static double aT[] = { #endif 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ }; #ifdef __STDC__ static const double #else static double #endif one = 1.0, huge = 1.0e300; #ifdef __STDC__ double __ieee754_atan(double x) #else double __ieee754_atan(x) double x; #endif { double w,s1,s2,z; int ix,hx,id; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x44100000) { /* if |x| >= 2^66 */ if(ix>0x7ff00000|| (ix==0x7ff00000&&(__LO(x)!=0))) return x+x; /* NaN */ if(hx>0) return atanhi[3]+atanlo[3]; else return -atanhi[3]-atanlo[3]; } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ if (ix < 0x3e200000) { /* |x| < 2^-29 */ if(huge+x>one) return x; /* raise inexact */ } id = -1; } else { x = fabs(x); if (ix < 0x3ff30000) { /* |x| < 1.1875 */ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ id = 0; x = (2.0*x-one)/(2.0+x); } else { /* 11/16<=|x|< 19/16 */ id = 1; x = (x-one)/(x+one); } } else { if (ix < 0x40038000) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(one+1.5*x); } else { /* 2.4375 <= |x| < 2^66 */ id = 3; x = -1.0/x; } }} /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); if (id<0) return x - x*(s1+s2); else { z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return (hx<0)? -z:z; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_cbrt.c ================================================ /* @(#)s_cbrt.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ #include "fdlibm.h" /* cbrt(x) * Return cube root of x */ #ifdef __STDC__ static const unsigned #else static unsigned #endif B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ #ifdef __STDC__ static const double #else static double #endif C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ #ifdef __STDC__ double cbrt(double x) #else double cbrt(x) double x; #endif { int hx; double r,s,t=0.0,w; unsigned sign; hx = __HI(x); /* high word of x */ sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ if((hx|__LO(x))==0) return(x); /* cbrt(0) is itself */ __HI(x) = hx; /* x <- |x| */ /* rough cbrt to 5 bits */ if(hx<0x00100000) /* subnormal number */ {__HI(t)=0x43500000; /* set t= 2**54 */ t*=x; __HI(t)=__HI(t)/3+B2; } else __HI(t)=hx/3+B1; /* new cbrt to 23 bits, may be implemented in single precision */ r=t*t/x; s=C+r*t; t*=G+F/(s+E+D/s); /* chopped to 20 bits and make it larger than cbrt(x) */ __LO(t)=0; __HI(t)+=0x00000001; /* one step newton iteration to 53 bits with error less than 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; w=t+t; r=(r-t)/(w+r); /* r-s is exact */ t=t+t*r; /* retore the sign bit */ __HI(t) |= sign; return(t); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_ceil.c ================================================ /* @(#)s_ceil.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * ceil(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to ceil(x). */ #include "fdlibm.h" #ifdef __STDC__ static const double huge = 1.0e300; #else static double huge = 1.0e300; #endif #ifdef __STDC__ double ceil(double x) #else double ceil(x) double x; #endif { int i0,i1,j0; unsigned i,j; i0 = __HI(x); i1 = __LO(x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ if(i0<0) {i0=0x80000000;i1=0;} else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} } } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0>0) i0 += (0x00100000)>>j0; i0 &= (~i); i1=0; } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((unsigned)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0>0) { if(j0==20) i0+=1; else { j = i1 + (1<<(52-j0)); if(j=0x7ff00000) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); switch(n&3) { case 0: return __kernel_cos(y[0],y[1]); case 1: return -__kernel_sin(y[0],y[1],1); case 2: return -__kernel_cos(y[0],y[1]); default: return __kernel_sin(y[0],y[1],1); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_erf.c ================================================ /* @(#)s_erf.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* double erf(double x) * double erfc(double x) * x * 2 |\ * erf(x) = --------- | exp(-t*t)dt * sqrt(pi) \| * 0 * * erfc(x) = 1-erf(x) * Note that * erf(-x) = -erf(x) * erfc(-x) = 2 - erfc(x) * * Method: * 1. For |x| in [0, 0.84375] * erf(x) = x + x*R(x^2) * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] * where R = P/Q where P is an odd poly of degree 8 and * Q is an odd poly of degree 10. * -57.90 * | R - (erf(x)-x)/x | <= 2 * * * Remark. The formula is derived by noting * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) * and that * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 * is close to one. The interval is chosen because the fix * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is * near 0.6174), and by some experiment, 0.84375 is chosen to * guarantee the error is less than one ulp for erf. * * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and * c = 0.84506291151 rounded to single (24 bits) * erf(x) = sign(x) * (c + P1(s)/Q1(s)) * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 * 1+(c+P1(s)/Q1(s)) if x < 0 * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 * Remark: here we use the taylor series expansion at x=1. * erf(1+s) = erf(1) + s*Poly(s) * = 0.845.. + P1(s)/Q1(s) * That is, we use rational approximation to approximate * erf(1+s) - (c = (single)0.84506291151) * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] * where * P1(s) = degree 6 poly in s * Q1(s) = degree 6 poly in s * * 3. For x in [1.25,1/0.35(~2.857143)], * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) * erf(x) = 1 - erfc(x) * where * R1(z) = degree 7 poly in z, (z=1/x^2) * S1(z) = degree 8 poly in z * * 4. For x in [1/0.35,28] * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 * erf(x) = sign(x) *(1 - tiny) (raise inexact) * erfc(x) = tiny*tiny (raise underflow) if x > 0 * = 2 - tiny if x<0 * * 7. Special case: * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, * erfc/erf(NaN) is NaN */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif tiny = 1e-300, half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ /* c = (float)0.84506291151 */ erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ /* * Coefficients for approximation to erf on [0,0.84375] */ efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ /* * Coefficients for approximation to erf in [0.84375,1.25] */ pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ /* * Coefficients for approximation to erfc in [1.25,1/0.35] */ ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ /* * Coefficients for approximation to erfc in [1/.35,28] */ rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ #ifdef __STDC__ double erf(double x) #else double erf(x) double x; #endif { int hx,ix,i; double R,S,P,Q,s,y,z,r; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) { /* erf(nan)=nan */ i = ((unsigned)hx>>31)<<1; return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ } if(ix < 0x3feb0000) { /* |x|<0.84375 */ if(ix < 0x3e300000) { /* |x|<2**-28 */ if (ix < 0x00800000) return 0.125*(8.0*x+efx8*x); /*avoid underflow */ return x + efx*x; } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; return x + x*y; } if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ s = fabs(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) return erx + P/Q; else return -erx - P/Q; } if (ix >= 0x40180000) { /* inf>|x|>=6 */ if(hx>=0) return one-tiny; else return tiny-one; } x = fabs(x); s = one/(x*x); if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( sa5+s*(sa6+s*(sa7+s*sa8))))))); } else { /* |x| >= 1/0.35 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( sb5+s*(sb6+s*sb7)))))); } z = x; __LO(z) = 0; r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); if(hx>=0) return one-r/x; else return r/x-one; } #ifdef __STDC__ double erfc(double x) #else double erfc(x) double x; #endif { int hx,ix; double R,S,P,Q,s,y,z,r; hx = __HI(x); ix = hx&0x7fffffff; if(ix>=0x7ff00000) { /* erfc(nan)=nan */ /* erfc(+-inf)=0,2 */ return (double)(((unsigned)hx>>31)<<1)+one/x; } if(ix < 0x3feb0000) { /* |x|<0.84375 */ if(ix < 0x3c700000) /* |x|<2**-56 */ return one-x; z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; if(hx < 0x3fd00000) { /* x<1/4 */ return one-(x+x*y); } else { r = x*y; r += (x-half); return half - r ; } } if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ s = fabs(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) { z = one-erx; return z - P/Q; } else { z = erx+P/Q; return one+z; } } if (ix < 0x403c0000) { /* |x|<28 */ x = fabs(x); s = one/(x*x); if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( sa5+s*(sa6+s*(sa7+s*sa8))))))); } else { /* |x| >= 1/.35 ~ 2.857143 */ if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( sb5+s*(sb6+s*sb7)))))); } z = x; __LO(z) = 0; r = __ieee754_exp(-z*z-0.5625)* __ieee754_exp((z-x)*(z+x)+R/S); if(hx>0) return r/x; else return two-r/x; } else { if(hx>0) return tiny*tiny; else return two-tiny; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_expm1.c ================================================ /* @(#)s_expm1.c 1.5 04/04/22 */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* expm1(x) * Returns exp(x)-1, the exponential of x minus 1. * * Method * 1. Argument reduction: * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 * * Here a correction term c will be computed to compensate * the error in r when rounded to a floating-point number. * * 2. Approximating expm1(r) by a special rational function on * the interval [0,0.34658]: * Since * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... * we define R1(r*r) by * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) * That is, * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... * We use a special Remes algorithm on [0,0.347] to generate * a polynomial of degree 5 in r*r to approximate R1. The * maximum error of this polynomial approximation is bounded * by 2**-61. In other words, * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 * where Q1 = -1.6666666666666567384E-2, * Q2 = 3.9682539681370365873E-4, * Q3 = -9.9206344733435987357E-6, * Q4 = 2.5051361420808517002E-7, * Q5 = -6.2843505682382617102E-9; * (where z=r*r, and the values of Q1 to Q5 are listed below) * with error bounded by * | 5 | -61 * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 * | | * * expm1(r) = exp(r)-1 is then computed by the following * specific way which minimize the accumulation rounding error: * 2 3 * r r [ 3 - (R1 + R1*r/2) ] * expm1(r) = r + --- + --- * [--------------------] * 2 2 [ 6 - r*(3 - R1*r/2) ] * * To compensate the error in the argument reduction, we use * expm1(r+c) = expm1(r) + c + expm1(r)*c * ~ expm1(r) + c + r*c * Thus c+r*c will be added in as the correction terms for * expm1(r+c). Now rearrange the term to avoid optimization * screw up: * ( 2 2 ) * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) * ( ) * * = r - E * 3. Scale back to obtain expm1(x): * From step 1, we have * expm1(x) = either 2^k*[expm1(r)+1] - 1 * = or 2^k*[expm1(r) + (1-2^-k)] * 4. Implementation notes: * (A). To save one multiplication, we scale the coefficient Qi * to Qi*2^i, and replace z by (x^2)/2. * (B). To achieve maximum accuracy, we compute expm1(x) by * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) * (ii) if k=0, return r-E * (iii) if k=-1, return 0.5*(r-E)-0.5 * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) * else return 1.0+2.0*(r-E); * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else * (vii) return 2^k(1-((E+2^-k)-r)) * * Special cases: * expm1(INF) is INF, expm1(NaN) is NaN; * expm1(-INF) is -1, and * for finite argument, only expm1(0)=0 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 7.09782712893383973096e+02 then expm1(x) overflow * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif one = 1.0, huge = 1.0e+300, tiny = 1.0e-300, o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ /* scaled coefficients related to expm1 */ Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ #ifdef __STDC__ double expm1(double x) #else double expm1(x) double x; #endif { double y,hi,lo,c,t,e,hxs,hfx,r1; int k,xsb; unsigned hx; hx = __HI(x); /* high word of x */ xsb = hx&0x80000000; /* sign bit of x */ if(xsb==0) y=x; else y= -x; /* y = |x| */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out huge and non-finite argument */ if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { if(((hx&0xfffff)|__LO(x))!=0) return x+x; /* NaN */ else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ } if(x > o_threshold) return huge*huge; /* overflow */ } if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ if(x+tiny<0.0) /* raise inexact */ return tiny-one; /* return -1 */ } } /* argument reduction */ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ if(xsb==0) {hi = x - ln2_hi; lo = ln2_lo; k = 1;} else {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} } else { k = invln2*x+((xsb==0)?0.5:-0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } x = hi - lo; c = (hi-x)-lo; } else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ t = huge+x; /* return x with inexact flags when x!=0 */ return x - (t-(huge+x)); } else k = 0; /* x is now in primary range */ hfx = 0.5*x; hxs = x*hfx; r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); t = 3.0-r1*hfx; e = hxs*((r1-t)/(6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { e = (x*(e-c)-c); e -= hxs; if(k== -1) return 0.5*(x-e)-0.5; if(k==1) if(x < -0.25) return -2.0*(e-(x+0.5)); else return one+2.0*(x-e); if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ y = one-(e-x); __HI(y) += (k<<20); /* add k to y's exponent */ return y-one; } t = one; if(k<20) { __HI(t) = 0x3ff00000 - (0x200000>>k); /* t=1-2^-k */ y = t-(e-x); __HI(y) += (k<<20); /* add k to y's exponent */ } else { __HI(t) = ((0x3ff-k)<<20); /* 2^-k */ y = x-(e+t); y += one; __HI(y) += (k<<20); /* add k to y's exponent */ } } return y; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_fabs.c ================================================ /* @(#)s_fabs.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * fabs(x) returns the absolute value of x. */ #include "fdlibm.h" #ifdef __STDC__ double fabs(double x) #else double fabs(x) double x; #endif { __HI(x) &= 0x7fffffff; return x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_finite.c ================================================ /* @(#)s_finite.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * finite(x) returns 1 is x is finite, else 0; * no branching! */ #include "fdlibm.h" #ifdef __STDC__ int finite(double x) #else int finite(x) double x; #endif { int hx; hx = __HI(x); return (unsigned)((hx&0x7fffffff)-0x7ff00000)>>31; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_floor.c ================================================ /* @(#)s_floor.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * floor(x) * Return x rounded toward -inf to integral value * Method: * Bit twiddling. * Exception: * Inexact flag raised if x not equal to floor(x). */ #include "fdlibm.h" #ifdef __STDC__ static const double huge = 1.0e300; #else static double huge = 1.0e300; #endif #ifdef __STDC__ double floor(double x) #else double floor(x) double x; #endif { int i0,i1,j0; unsigned i,j; i0 = __HI(x); i1 = __LO(x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { /* raise inexact if x != 0 */ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ if(i0>=0) {i0=i1=0;} else if(((i0&0x7fffffff)|i1)!=0) { i0=0xbff00000;i1=0;} } } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0<0) i0 += (0x00100000)>>j0; i0 &= (~i); i1=0; } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((unsigned)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ if(huge+x>0.0) { /* raise inexact flag */ if(i0<0) { if(j0==20) i0+=1; else { j = i1+(1<<(52-j0)); if(j=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ if (ix<0x00100000) { /* subnormal */ x *= two54; hx = __HI(x); ix = hx&0x7fffffff; *eptr = -54; } *eptr += (ix>>20)-1022; hx = (hx&0x800fffff)|0x3fe00000; __HI(x) = hx; return x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_ilogb.c ================================================ /* @(#)s_ilogb.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* ilogb(double x) * return the binary exponent of non-zero x * ilogb(0) = 0x80000001 * ilogb(inf/NaN) = 0x7fffffff (no signal is raised) */ #include "fdlibm.h" #ifdef __STDC__ int ilogb(double x) #else int ilogb(x) double x; #endif { int hx,lx,ix; hx = (__HI(x))&0x7fffffff; /* high word of x */ if(hx<0x00100000) { lx = __LO(x); if((hx|lx)==0) return 0x80000001; /* ilogb(0) = 0x80000001 */ else /* subnormal x */ if(hx==0) { for (ix = -1043; lx>0; lx<<=1) ix -=1; } else { for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; } return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; else return 0x7fffffff; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_isnan.c ================================================ /* @(#)s_isnan.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * isnan(x) returns 1 is x is nan, else 0; * no branching! */ #include "fdlibm.h" #ifdef __STDC__ int isnan(double x) #else int isnan(x) double x; #endif { int hx,lx; hx = (__HI(x)&0x7fffffff); lx = __LO(x); hx |= (unsigned)(lx|(-lx))>>31; hx = 0x7ff00000 - hx; return ((unsigned)(hx))>>31; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_ldexp.c ================================================ /* @(#)s_ldexp.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #include #ifdef __STDC__ double ldexp(double value, int exp) #else double ldexp(value, exp) double value; int exp; #endif { if(!finite(value)||value==0.0) return value; value = scalbn(value,exp); if(!finite(value)||value==0.0) errno = ERANGE; return value; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_lib_version.c ================================================ /* @(#)s_lib_version.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * MACRO for standards */ #include "fdlibm.h" /* * define and initialize _LIB_VERSION */ #ifdef _POSIX_MODE _LIB_VERSION_TYPE _LIB_VERSION = _POSIX_; #else #ifdef _XOPEN_MODE _LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_; #else #ifdef _SVID3_MODE _LIB_VERSION_TYPE _LIB_VERSION = _SVID_; #else /* default _IEEE_MODE */ _LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; #endif #endif #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_log1p.c ================================================ /* @(#)s_log1p.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* double log1p(double x) * * Method : * 1. Argument Reduction: find k and f such that * 1+x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * Note. If k=0, then f=x is exact. However, if k!=0, then f * may not be representable exactly. In that case, a correction * term is need. Let u=1+x rounded. Let c = (1+x)-u, then * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), * and add back the correction term c/u. * (Note: when x > 2**53, one can simply return log(x)) * * 2. Approximation of log1p(f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Reme algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s * (the values of Lp1 to Lp7 are listed in the program) * and * | 2 14 | -58.45 * | Lp1*s +...+Lp7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log1p(f) = f - (hfsq - s*(hfsq+R)). * * 3. Finally, log1p(x) = k*ln2 + log1p(f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log1p(x) is NaN with signal if x < -1 (including -INF) ; * log1p(+INF) is +INF; log1p(-1) is -INF with signal; * log1p(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. * * Note: Assuming log() return accurate answer, the following * algorithm can be used to compute log1p(x) to within a few ULP: * * u = 1+x; * if(u==1.0) return x ; else * return log(u)*(x/(u-1.0)); * * See HP-15C Advanced Functions Handbook, p.193. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ static double zero = 0.0; #ifdef __STDC__ double log1p(double x) #else double log1p(x) double x; #endif { double hfsq,f,c,s,z,R,u; int k,hx,hu,ax; hx = __HI(x); /* high word of x */ ax = hx&0x7fffffff; k = 1; if (hx < 0x3FDA827A) { /* x < 0.41422 */ if(ax>=0x3ff00000) { /* x <= -1.0 */ if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ } if(ax<0x3e200000) { /* |x| < 2**-29 */ if(two54+x>zero /* raise inexact */ &&ax<0x3c900000) /* |x| < 2**-54 */ return x; else return x - x*x*0.5; } if(hx>0||hx<=((int)0xbfd2bec3)) { k=0;f=x;hu=1;} /* -0.2929= 0x7ff00000) return x+x; if(k!=0) { if(hx<0x43400000) { u = 1.0+x; hu = __HI(u); /* high word of u */ k = (hu>>20)-1023; c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ c /= u; } else { u = x; hu = __HI(u); /* high word of u */ k = (hu>>20)-1023; c = 0; } hu &= 0x000fffff; if(hu<0x6a09e) { __HI(u) = hu|0x3ff00000; /* normalize u */ } else { k += 1; __HI(u) = hu|0x3fe00000; /* normalize u/2 */ hu = (0x00100000-hu)>>2; } f = u-1.0; } hfsq=0.5*f*f; if(hu==0) { /* |f| < 2**-20 */ if(f==zero) if(k==0) return zero; else {c += k*ln2_lo; return k*ln2_hi+c;} R = hfsq*(1.0-0.66666666666666666*f); if(k==0) return f-R; else return k*ln2_hi-((R-(k*ln2_lo+c))-f); } s = f/(2.0+f); z = s*s; R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); if(k==0) return f-(hfsq-s*(hfsq+R)); else return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_logb.c ================================================ /* @(#)s_logb.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * double logb(x) * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. * Use ilogb instead. */ #include "fdlibm.h" #ifdef __STDC__ double logb(double x) #else double logb(x) double x; #endif { int lx,ix; ix = (__HI(x))&0x7fffffff; /* high |x| */ lx = __LO(x); /* low x */ if((ix|lx)==0) return -1.0/fabs(x); if(ix>=0x7ff00000) return x*x; if((ix>>=20)==0) /* IEEE 754 logb */ return -1022.0; else return (double) (ix-1023); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_matherr.c ================================================ /* @(#)s_matherr.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ int matherr(struct exception *x) #else int matherr(x) struct exception *x; #endif { int n=0; if(x->arg1!=x->arg1) return 0; return n; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_modf.c ================================================ /* @(#)s_modf.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * modf(double x, double *iptr) * return fraction part of x, and return x's integral part in *iptr. * Method: * Bit twiddling. * * Exception: * No exception. */ #include "fdlibm.h" #ifdef __STDC__ static const double one = 1.0; #else static double one = 1.0; #endif #ifdef __STDC__ double modf(double x, double *iptr) #else double modf(x, iptr) double x,*iptr; #endif { int i0,i1,j0; unsigned i; i0 = __HI(x); /* high x */ i1 = __LO(x); /* low x */ j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ if(j0<20) { /* integer part in high x */ if(j0<0) { /* |x|<1 */ __HIp(iptr) = i0&0x80000000; __LOp(iptr) = 0; /* *iptr = +-0 */ return x; } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) { /* x is integral */ *iptr = x; __HI(x) &= 0x80000000; __LO(x) = 0; /* return +-0 */ return x; } else { __HIp(iptr) = i0&(~i); __LOp(iptr) = 0; return x - *iptr; } } } else if (j0>51) { /* no fraction part */ *iptr = x*one; __HI(x) &= 0x80000000; __LO(x) = 0; /* return +-0 */ return x; } else { /* fraction part in low x */ i = ((unsigned)(0xffffffff))>>(j0-20); if((i1&i)==0) { /* x is integral */ *iptr = x; __HI(x) &= 0x80000000; __LO(x) = 0; /* return +-0 */ return x; } else { __HIp(iptr) = i0; __LOp(iptr) = i1&(~i); return x - *iptr; } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_nextafter.c ================================================ /* @(#)s_nextafter.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* IEEE functions * nextafter(x,y) * return the next machine floating-point number of x in the * direction toward y. * Special cases: */ #include "fdlibm.h" #ifdef __STDC__ double nextafter(double x, double y) #else double nextafter(x,y) double x,y; #endif { int hx,hy,ix,iy; unsigned lx,ly; hx = __HI(x); /* high word of x */ lx = __LO(x); /* low word of x */ hy = __HI(y); /* high word of y */ ly = __LO(y); /* low word of y */ ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return x; /* x=y, return x */ if((ix|lx)==0) { /* x == 0 */ __HI(x) = hy&0x80000000; /* return +-minsubnormal */ __LO(x) = 1; y = x*x; if(y==x) return y; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } hy = hx&0x7ff00000; if(hy>=0x7ff00000) return x+x; /* overflow */ if(hy<0x00100000) { /* underflow */ y = x*x; if(y!=x) { /* raise underflow flag */ __HI(y) = hx; __LO(y) = lx; return y; } } __HI(x) = hx; __LO(x) = lx; return x; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_rint.c ================================================ /* @(#)s_rint.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * rint(x) * Return x rounded to integral value according to the prevailing * rounding mode. * Method: * Using floating addition. * Exception: * Inexact flag raised if x not equal to rint(x). */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif TWO52[2]={ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ }; #ifdef __STDC__ double rint(double x) #else double rint(x) double x; #endif { int i0,j0,sx; unsigned i,i1; double w,t; i0 = __HI(x); sx = (i0>>31)&1; i1 = __LO(x); j0 = ((i0>>20)&0x7ff)-0x3ff; if(j0<20) { if(j0<0) { if(((i0&0x7fffffff)|i1)==0) return x; i1 |= (i0&0x0fffff); i0 &= 0xfffe0000; i0 |= ((i1|-i1)>>12)&0x80000; __HI(x)=i0; w = TWO52[sx]+x; t = w-TWO52[sx]; i0 = __HI(t); __HI(t) = (i0&0x7fffffff)|(sx<<31); return t; } else { i = (0x000fffff)>>j0; if(((i0&i)|i1)==0) return x; /* x is integral */ i>>=1; if(((i0&i)|i1)!=0) { if(j0==19) i1 = 0x40000000; else i0 = (i0&(~i))|((0x20000)>>j0); } } } else if (j0>51) { if(j0==0x400) return x+x; /* inf or NaN */ else return x; /* x is integral */ } else { i = ((unsigned)(0xffffffff))>>(j0-20); if((i1&i)==0) return x; /* x is integral */ i>>=1; if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); } __HI(x) = i0; __LO(x) = i1; w = TWO52[sx]+x; return w-TWO52[sx]; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_scalbn.c ================================================ /* @(#)s_scalbn.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * scalbn (double x, int n) * scalbn(x,n) returns x* 2**n computed by exponent * manipulation rather than by actually performing an * exponentiation or a multiplication. */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ huge = 1.0e+300, tiny = 1.0e-300; #ifdef __STDC__ double scalbn (double x, int n) #else double scalbn (x,n) double x; int n; #endif { int k,hx,lx; hx = __HI(x); lx = __LO(x); k = (hx&0x7ff00000)>>20; /* extract exponent */ if (k==0) { /* 0 or subnormal x */ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ x *= two54; hx = __HI(x); k = ((hx&0x7ff00000)>>20) - 54; if (n< -50000) return tiny*x; /*underflow*/ } if (k==0x7ff) return x+x; /* NaN or Inf */ k = k+n; if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */ if (k > 0) /* normal result */ {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} if (k <= -54) if (n > 50000) /* in case integer overflow in n+k */ return huge*copysign(huge,x); /*overflow*/ else return tiny*copysign(tiny,x); /*underflow*/ k += 54; /* subnormal result */ __HI(x) = (hx&0x800fffff)|(k<<20); return x*twom54; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_signgam.c ================================================ #include "fdlibm.h" int signgam = 0; ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_significand.c ================================================ /* @(#)s_significand.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * significand(x) computes just * scalb(x, (double) -ilogb(x)), * for exercising the fraction-part(F) IEEE 754-1985 test vector. */ #include "fdlibm.h" #ifdef __STDC__ double significand(double x) #else double significand(x) double x; #endif { return __ieee754_scalb(x,(double) -ilogb(x)); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_sin.c ================================================ /* @(#)s_sin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* sin(x) * Return sine function of x. * * kernel function: * __kernel_sin ... sine function on [-pi/4,pi/4] * __kernel_cos ... cose function on [-pi/4,pi/4] * __ieee754_rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include "fdlibm.h" #ifdef __STDC__ double sin(double x) #else double sin(x) double x; #endif { double y[2],z=0.0; int n, ix; /* High word of x. */ ix = __HI(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); /* sin(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); switch(n&3) { case 0: return __kernel_sin(y[0],y[1],1); case 1: return __kernel_cos(y[0],y[1]); case 2: return -__kernel_sin(y[0],y[1],1); default: return -__kernel_cos(y[0],y[1]); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_tan.c ================================================ /* @(#)s_tan.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* tan(x) * Return tangent function of x. * * kernel function: * __kernel_tan ... tangent function on [-pi/4,pi/4] * __ieee754_rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include "fdlibm.h" #ifdef __STDC__ double tan(double x) #else double tan(x) double x; #endif { double y[2],z=0.0; int n, ix; /* High word of x. */ ix = __HI(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); /* tan(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* NaN */ /* argument reduction needed */ else { n = __ieee754_rem_pio2(x,y); return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even -1 -- n odd */ } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/s_tanh.c ================================================ /* @(#)s_tanh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* Tanh(x) * Return the Hyperbolic Tangent of x * * Method : * x -x * e - e * 0. tanh(x) is defined to be ----------- * x -x * e + e * 1. reduce x to non-negative by tanh(-x) = -tanh(x). * 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) * -t * 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) * t + 2 * 2 * 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x) * t + 2 * 22.0 < x <= INF : tanh(x) := 1. * * Special cases: * tanh(NaN) is NaN; * only tanh(0)=0 is exact for finite argument. */ #include "fdlibm.h" #ifdef __STDC__ static const double one=1.0, two=2.0, tiny = 1.0e-300; #else static double one=1.0, two=2.0, tiny = 1.0e-300; #endif #ifdef __STDC__ double tanh(double x) #else double tanh(x) double x; #endif { double t,z; int jx,ix; /* High word of |x|. */ jx = __HI(x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) { if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ else return one/x-one; /* tanh(NaN) = NaN */ } /* |x| < 22 */ if (ix < 0x40360000) { /* |x|<22 */ if (ix<0x3c800000) /* |x|<2**-55 */ return x*(one+x); /* tanh(small) = small */ if (ix>=0x3ff00000) { /* |x|>=1 */ t = expm1(two*fabs(x)); z = one - two/(t+two); } else { t = expm1(-two*fabs(x)); z= -t/(t+two); } /* |x| > 22, return +-1 */ } else { z = one - tiny; /* raised inexact flag */ } return (jx>=0)? z: -z; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_acos.c ================================================ /* @(#)w_acos.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrap_acos(x) */ #include "fdlibm.h" #ifdef __STDC__ double acos(double x) /* wrapper acos */ #else double acos(x) /* wrapper acos */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_acos(x); #else double z; z = __ieee754_acos(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(fabs(x)>1.0) { return __kernel_standard(x,x,1); /* acos(|x|>1) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_acosh.c ================================================ /* @(#)w_acosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* * wrapper acosh(x) */ #include "fdlibm.h" #ifdef __STDC__ double acosh(double x) /* wrapper acosh */ #else double acosh(x) /* wrapper acosh */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_acosh(x); #else double z; z = __ieee754_acosh(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(x<1.0) { return __kernel_standard(x,x,29); /* acosh(x<1) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_asin.c ================================================ /* @(#)w_asin.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* * wrapper asin(x) */ #include "fdlibm.h" #ifdef __STDC__ double asin(double x) /* wrapper asin */ #else double asin(x) /* wrapper asin */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_asin(x); #else double z; z = __ieee754_asin(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(fabs(x)>1.0) { return __kernel_standard(x,x,2); /* asin(|x|>1) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_atan2.c ================================================ /* @(#)w_atan2.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* * wrapper atan2(y,x) */ #include "fdlibm.h" #ifdef __STDC__ double atan2(double y, double x) /* wrapper atan2 */ #else double atan2(y,x) /* wrapper atan2 */ double y,x; #endif { #ifdef _IEEE_LIBM return __ieee754_atan2(y,x); #else double z; z = __ieee754_atan2(y,x); if(_LIB_VERSION == _IEEE_||isnan(x)||isnan(y)) return z; if(x==0.0&&y==0.0) { return __kernel_standard(y,x,3); /* atan2(+-0,+-0) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_atanh.c ================================================ /* @(#)w_atanh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper atanh(x) */ #include "fdlibm.h" #ifdef __STDC__ double atanh(double x) /* wrapper atanh */ #else double atanh(x) /* wrapper atanh */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_atanh(x); #else double z,y; z = __ieee754_atanh(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; y = fabs(x); if(y>=1.0) { if(y>1.0) return __kernel_standard(x,x,30); /* atanh(|x|>1) */ else return __kernel_standard(x,x,31); /* atanh(|x|==1) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_cosh.c ================================================ /* @(#)w_cosh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper cosh(x) */ #include "fdlibm.h" #ifdef __STDC__ double cosh(double x) /* wrapper cosh */ #else double cosh(x) /* wrapper cosh */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_cosh(x); #else double z; z = __ieee754_cosh(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(fabs(x)>7.10475860073943863426e+02) { return __kernel_standard(x,x,5); /* cosh overflow */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_exp.c ================================================ /* @(#)w_exp.c 1.4 04/04/22 */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper exp(x) */ #include "fdlibm.h" #ifdef __STDC__ static const double #else static double #endif o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ #ifdef __STDC__ double exp(double x) /* wrapper exp */ #else double exp(x) /* wrapper exp */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_exp(x); #else double z; z = __ieee754_exp(x); if(_LIB_VERSION == _IEEE_) return z; if(finite(x)) { if(x>o_threshold) return __kernel_standard(x,x,6); /* exp overflow */ else if(xX_TLOSS) { return __kernel_standard(x,x,34); /* j0(|x|>X_TLOSS) */ } else return z; #endif } #ifdef __STDC__ double y0(double x) /* wrapper y0 */ #else double y0(x) /* wrapper y0 */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_y0(x); #else double z; z = __ieee754_y0(x); if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; if(x <= 0.0){ if(x==0.0) /* d= -one/(x-x); */ return __kernel_standard(x,x,8); else /* d = zero/(x-x); */ return __kernel_standard(x,x,9); } if(x>X_TLOSS) { return __kernel_standard(x,x,35); /* y0(x>X_TLOSS) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_j1.c ================================================ /* @(#)w_j1.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper of j1,y1 */ #include "fdlibm.h" #ifdef __STDC__ double j1(double x) /* wrapper j1 */ #else double j1(x) /* wrapper j1 */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_j1(x); #else double z; z = __ieee754_j1(x); if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; if(fabs(x)>X_TLOSS) { return __kernel_standard(x,x,36); /* j1(|x|>X_TLOSS) */ } else return z; #endif } #ifdef __STDC__ double y1(double x) /* wrapper y1 */ #else double y1(x) /* wrapper y1 */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_y1(x); #else double z; z = __ieee754_y1(x); if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; if(x <= 0.0){ if(x==0.0) /* d= -one/(x-x); */ return __kernel_standard(x,x,10); else /* d = zero/(x-x); */ return __kernel_standard(x,x,11); } if(x>X_TLOSS) { return __kernel_standard(x,x,37); /* y1(x>X_TLOSS) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_jn.c ================================================ /* @(#)w_jn.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper jn(int n, double x), yn(int n, double x) * floating point Bessel's function of the 1st and 2nd kind * of order n * * Special cases: * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. * Note 2. About jn(n,x), yn(n,x) * For n=0, j0(x) is called, * for n=1, j1(x) is called, * for nx, a continued fraction approximation to * j(n,x)/j(n-1,x) is evaluated and then backward * recursion is used starting from a supposed value * for j(n,x). The resulting value of j(0,x) is * compared with the actual value to correct the * supposed value of j(n,x). * * yn(n,x) is similar in all respects, except * that forward recursion is used for all * values of n>1. * */ #include "fdlibm.h" #ifdef __STDC__ double jn(int n, double x) /* wrapper jn */ #else double jn(n,x) /* wrapper jn */ double x; int n; #endif { #ifdef _IEEE_LIBM return __ieee754_jn(n,x); #else double z; z = __ieee754_jn(n,x); if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; if(fabs(x)>X_TLOSS) { return __kernel_standard((double)n,x,38); /* jn(|x|>X_TLOSS,n) */ } else return z; #endif } #ifdef __STDC__ double yn(int n, double x) /* wrapper yn */ #else double yn(n,x) /* wrapper yn */ double x; int n; #endif { #ifdef _IEEE_LIBM return __ieee754_yn(n,x); #else double z; z = __ieee754_yn(n,x); if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; if(x <= 0.0){ if(x==0.0) /* d= -one/(x-x); */ return __kernel_standard((double)n,x,12); else /* d = zero/(x-x); */ return __kernel_standard((double)n,x,13); } if(x>X_TLOSS) { return __kernel_standard((double)n,x,39); /* yn(x>X_TLOSS,n) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_lgamma.c ================================================ /* @(#)w_lgamma.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* double lgamma(double x) * Return the logarithm of the Gamma function of x. * * Method: call __ieee754_lgamma_r */ #include "fdlibm.h" extern int signgam; #ifdef __STDC__ double lgamma(double x) #else double lgamma(x) double x; #endif { #ifdef _IEEE_LIBM return __ieee754_lgamma_r(x,&signgam); #else double y; y = __ieee754_lgamma_r(x,&signgam); if(_LIB_VERSION == _IEEE_) return y; if(!finite(y)&&finite(x)) { if(floor(x)==x&&x<=0.0) return __kernel_standard(x,x,15); /* lgamma pole */ else return __kernel_standard(x,x,14); /* lgamma overflow */ } else return y; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_lgamma_r.c ================================================ /* @(#)w_lgamma_r.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper double lgamma_r(double x, int *signgamp) */ #include "fdlibm.h" #ifdef __STDC__ double lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */ #else double lgamma_r(x,signgamp) /* wrapper lgamma_r */ double x; int *signgamp; #endif { #ifdef _IEEE_LIBM return __ieee754_lgamma_r(x,signgamp); #else double y; y = __ieee754_lgamma_r(x,signgamp); if(_LIB_VERSION == _IEEE_) return y; if(!finite(y)&&finite(x)) { if(floor(x)==x&&x<=0.0) return __kernel_standard(x,x,15); /* lgamma pole */ else return __kernel_standard(x,x,14); /* lgamma overflow */ } else return y; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_log.c ================================================ /* @(#)w_log.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper log(x) */ #include "fdlibm.h" #ifdef __STDC__ double log(double x) /* wrapper log */ #else double log(x) /* wrapper log */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_log(x); #else double z; z = __ieee754_log(x); if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z; if(x==0.0) return __kernel_standard(x,x,16); /* log(0) */ else return __kernel_standard(x,x,17); /* log(x<0) */ #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_log10.c ================================================ /* @(#)w_log10.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper log10(X) */ #include "fdlibm.h" #ifdef __STDC__ double log10(double x) /* wrapper log10 */ #else double log10(x) /* wrapper log10 */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_log10(x); #else double z; z = __ieee754_log10(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(x<=0.0) { if(x==0.0) return __kernel_standard(x,x,18); /* log10(0) */ else return __kernel_standard(x,x,19); /* log10(x<0) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_pow.c ================================================ /* @(#)w_pow.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper pow(x,y) return x**y */ #include "fdlibm.h" #ifdef __STDC__ double pow(double x, double y) /* wrapper pow */ #else double pow(x,y) /* wrapper pow */ double x,y; #endif { #ifdef _IEEE_LIBM return __ieee754_pow(x,y); #else double z; z=__ieee754_pow(x,y); if(_LIB_VERSION == _IEEE_|| isnan(y)) return z; if(isnan(x)) { if(y==0.0) return __kernel_standard(x,y,42); /* pow(NaN,0.0) */ else return z; } if(x==0.0){ if(y==0.0) return __kernel_standard(x,y,20); /* pow(0.0,0.0) */ if(finite(y)&&y<0.0) return __kernel_standard(x,y,23); /* pow(0.0,negative) */ return z; } if(!finite(z)) { if(finite(x)&&finite(y)) { if(isnan(z)) return __kernel_standard(x,y,24); /* pow neg**non-int */ else return __kernel_standard(x,y,21); /* pow overflow */ } } if(z==0.0&&finite(x)&&finite(y)) return __kernel_standard(x,y,22); /* pow underflow */ return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_remainder.c ================================================ /* @(#)w_remainder.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper remainder(x,p) */ #include "fdlibm.h" #ifdef __STDC__ double remainder(double x, double y) /* wrapper remainder */ #else double remainder(x,y) /* wrapper remainder */ double x,y; #endif { #ifdef _IEEE_LIBM return __ieee754_remainder(x,y); #else double z; z = __ieee754_remainder(x,y); if(_LIB_VERSION == _IEEE_ || isnan(y)) return z; if(y==0.0) return __kernel_standard(x,y,28); /* remainder(x,0) */ else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_scalb.c ================================================ /* @(#)w_scalb.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper scalb(double x, double fn) is provide for * passing various standard test suite. One * should use scalbn() instead. */ #include "fdlibm.h" #include #ifdef __STDC__ #ifdef _SCALB_INT double scalb(double x, int fn) /* wrapper scalb */ #else double scalb(double x, double fn) /* wrapper scalb */ #endif #else double scalb(x,fn) /* wrapper scalb */ #ifdef _SCALB_INT double x; int fn; #else double x,fn; #endif #endif { #ifdef _IEEE_LIBM return __ieee754_scalb(x,fn); #else double z; z = __ieee754_scalb(x,fn); if(_LIB_VERSION == _IEEE_) return z; if(!(finite(z)||isnan(z))&&finite(x)) { return __kernel_standard(x,(double)fn,32); /* scalb overflow */ } if(z==0.0&&z!=x) { return __kernel_standard(x,(double)fn,33); /* scalb underflow */ } #ifndef _SCALB_INT if(!finite(fn)) errno = ERANGE; #endif return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_sinh.c ================================================ /* @(#)w_sinh.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper sinh(x) */ #include "fdlibm.h" #ifdef __STDC__ double sinh(double x) /* wrapper sinh */ #else double sinh(x) /* wrapper sinh */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_sinh(x); #else double z; z = __ieee754_sinh(x); if(_LIB_VERSION == _IEEE_) return z; if(!finite(z)&&finite(x)) { return __kernel_standard(x,x,25); /* sinh overflow */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fdlibm/w_sqrt.c ================================================ /* @(#)w_sqrt.c 1.3 95/01/18 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * wrapper sqrt(x) */ #include "fdlibm.h" #ifdef __STDC__ double sqrt(double x) /* wrapper sqrt */ #else double sqrt(x) /* wrapper sqrt */ double x; #endif { #ifdef _IEEE_LIBM return __ieee754_sqrt(x); #else double z; z = __ieee754_sqrt(x); if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; if(x<0.0) { return __kernel_standard(x,x,26); /* sqrt(negative) */ } else return z; #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/finite.c ================================================ #include "ieee754names.h" #include "fdlibm/s_finite.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/fmod.c ================================================ #include "ieee754names.h" #include "fdlibm/e_fmod.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/hypot.c ================================================ #include "ieee754names.h" #include "fdlibm/e_hypot.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/ieee754names.h ================================================ /* Re-define all of the conflicting names of fdlibm to use __ieee754_ prefix */ #define asinh __ieee754_asinh #define atan __ieee754_atan #define cos __ieee754_cos #define expm1 __ieee754_expm1 #define finite __ieee754_finite #define ldexp __ieee754_ldexp #define scalbn __ieee754_scalbn #define log1p __ieee754_log1p #define modf __ieee754_modf #define rint __ieee754_rint #define sin __ieee754_sin #define tan __ieee754_tan #define tanh __ieee754_tanh ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/isnan.c ================================================ #include "ieee754names.h" #include "fdlibm/s_isnan.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/k_cos.c ================================================ #include "ieee754names.h" #include "fdlibm/k_cos.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/k_rem_pio2.c ================================================ #include "ieee754names.h" #include "fdlibm/k_rem_pio2.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/k_sin.c ================================================ #include "ieee754names.h" #include "fdlibm/k_sin.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/k_tan.c ================================================ #include "ieee754names.h" #include "fdlibm/k_tan.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/ldexp.c ================================================ #include "ieee754names.h" #include "fdlibm/s_ldexp.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/log.c ================================================ #include "ieee754names.h" #include "fdlibm/e_log.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/log10.c ================================================ #include "ieee754names.h" #include "fdlibm/e_log10.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/log1p.c ================================================ #include "ieee754names.h" #include "fdlibm/s_log1p.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/modf.c ================================================ #include "ieee754names.h" #include "fdlibm/s_modf.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/pow.c ================================================ #include "ieee754names.h" #include "fdlibm/e_pow.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/rem_pio2.c ================================================ #include "ieee754names.h" #include "fdlibm/e_rem_pio2.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/rint.c ================================================ #include "ieee754names.h" #include "fdlibm/s_rint.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/scalb.c ================================================ #include "ieee754names.h" #include "fdlibm/e_scalb.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/scalbn.c ================================================ #include "ieee754names.h" #include "fdlibm/s_scalbn.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/sin.c ================================================ #include "ieee754names.h" #include "fdlibm/s_sin.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/sinh.c ================================================ #include "ieee754names.h" #include "fdlibm/e_sinh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/sqrt.c ================================================ #include "ieee754names.h" #include "fdlibm/e_sqrt.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/tan.c ================================================ #include "ieee754names.h" #include "fdlibm/s_tan.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/FloatMathPlugin/tanh.c ================================================ #include "ieee754names.h" #include "fdlibm/s_tanh.c" ================================================ FILE: vm/src/from_squeak/Cross/plugins/GStreamerPlugin/squeakAudioVideoPipeLineSignalInterface.c ================================================ /* * squeakAudioVideoPipeLineSignalInterface.c * GStreamer * * Created by John M McIntosh on 3/29/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.con All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php * */ #include #include #include #include "squeakAudioVideoPipeLineSignalInterface.h" #include "sqVirtualMachine.h" void gst_SqueakVideoSink_set_caps (SqueakAudioVideoSinkPtr sink, GstCaps * caps); void gst_SqueakAudioSink_sink_write(GstElement* plugin, SqueakAudioVideoSinkPtr sink, gpointer data, guint length, GstClockTime duration); /* Element Signals: "handoff" : void user_function (GstElement* object, GstBuffer* arg0, GstPad* arg1, gpointer user_data); "preroll-handoff" : void user_function (GstElement* object, GstBuffer* arg0, GstPad* arg1, gpointer user_data); */ void squeakVideoHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data) { GST_LOCK(object); { SqueakAudioVideoSinkPtr squeaker = (SqueakAudioVideoSinkPtr) user_data; if (squeaker->width == 0) gst_SqueakVideoSink_set_caps(squeaker,GST_BUFFER_CAPS(buf)); if (squeaker->width == 0) { GST_UNLOCK(object); return; /* should not happen but let's check */ } if (GST_BUFFER_DATA(buf)) { guint totalBytes = (squeaker->depth == 24 ? 4 : 2)*squeaker->width*squeaker->height; squeaker->frame_ready = TRUE; if (totalBytes != squeaker->allocbytes) { if (squeaker->copyToSendToSqueakVideo) g_free(squeaker->copyToSendToSqueakVideo); squeaker->copyToSendToSqueakVideo = g_malloc(totalBytes); squeaker->allocbytes = totalBytes; } memcpy(squeaker->copyToSendToSqueakVideo,GST_BUFFER_DATA(buf),totalBytes); } } GST_UNLOCK(object); } void squeakSrcHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data) { GST_LOCK(object); { SqueakAudioVideoSinkPtr squeaker = (SqueakAudioVideoSinkPtr) user_data; if (squeaker->frame_ready) { squeaker->frame_ready = FALSE; if (squeaker->semaphoreIndexForSink && squeaker->interpreterProxy) { squeaker->interpreterProxy->signalSemaphoreWithIndex(squeaker->semaphoreIndexForSink); } if (GST_BUFFER_SIZE (buf) >= squeaker->actualbytes) memcpy(GST_BUFFER_DATA(buf),squeaker->copyToSendToSqueakVideo,squeaker->actualbytes); GST_BUFFER_TIMESTAMP(buf) = squeaker->startTime; GST_BUFFER_DURATION(buf) = squeaker->duration; } } GST_UNLOCK(object); } void gst_SqueakVideoSink_set_caps (SqueakAudioVideoSinkPtr sink, GstCaps * caps) { GstStructure *structure; int width, height, depth; gboolean ret; const GValue *fps; structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "width", &width); ret = ret && gst_structure_get_int (structure, "height", &height); ret = ret && gst_structure_get_int (structure, "depth", &depth); fps = gst_structure_get_value (structure, "framerate"); ret = ret && (fps != NULL); if (!ret) return; sink->width = width; sink->height = height; sink->depth = depth; sink->fps_n = gst_value_get_fraction_numerator(fps); sink->fps_d = gst_value_get_fraction_denominator(fps); sink->width = width; sink->height = height; } void squeakAudioHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data) { SqueakAudioVideoSinkPtr squeaker = (SqueakAudioVideoSinkPtr) user_data; if (GST_BUFFER_DATA(buf)) { gst_SqueakAudioSink_sink_write(object, squeaker,GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf),GST_BUFFER_DURATION(buf)); } } void gst_SqueakAudioSink_sink_write(GstElement* plugin, SqueakAudioVideoSinkPtr sink, gpointer data,guint length, GstClockTime duration) { guint64 squeakbuffersize; guint8 * startLocation; GST_LOCK(plugin); if (sink->copyToSendToSqueakAudio == NULL) { sink->copyToSendToSqueakAudio = gst_buffer_new_and_alloc(22050*8); /* 2.0 second of data */ GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio) = 0; } squeakbuffersize = GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio); /* semaphore not signalled and if we go over X then we want to signal the semaphore if it exits, but only once */ if ((sink->semaphoreWasSignaled == 0) && ((squeakbuffersize + length) > 22050)) { sink->semaphoreWasSignaled = 1; if (sink->semaphoreIndexForSink && sink->interpreterProxy) { sink->interpreterProxy->signalSemaphoreWithIndex(sink->semaphoreIndexForSink); } } /* if squeakbuffersize + incoming length <= 22050*8 then allow the copy, otherwise we FLUSH the buffer and start over */ if ((squeakbuffersize + length) <= 22050*8) { startLocation = GST_BUFFER_DATA(sink->copyToSendToSqueakAudio) + squeakbuffersize; } else { /* buffer full and squeak not getting data, please wait */ GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio) = 0; startLocation = GST_BUFFER_DATA(sink->copyToSendToSqueakAudio); } /* copy data to the start of the squeak buffer or to some offset, and not run over the end! */ memcpy(startLocation,data,length); GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio) = GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio) + length; if (sink->prerollCounter) { sink->prerollCounter = sink->prerollCounter -1; GST_UNLOCK(plugin); return; } GST_UNLOCK(plugin); { /* Wait for this many milliseconds so squeak can catch up per buffer write */ /* GstClock *clock; GstClockID id; GstClockTime base; GstClockReturn result; gdouble millisecondestimate; millisecondestimate = (duration/1000000); clock = gst_system_clock_obtain (); base = gst_clock_get_time (clock); id = gst_clock_new_single_shot_id (clock, base + (gint)millisecondestimate); result = gst_clock_id_wait (id, NULL); gst_clock_id_unref(id); */ } return; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/GStreamerPlugin/squeakAudioVideoPipeLineSignalInterface.h ================================================ /* * squeakAudioVideoPipeLineSignalInterface.h * GStreamer * * Created by John M McIntosh on 4/1/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.con All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php * */ struct _SqueakAudioVideoSink { GstElement *owner; void* handler; GstBuffer *copyToSendToSqueakAudio; gboolean semaphoreWasSignaled; gint semaphoreIndexForSink; gint prerollCounter; guchar *copyToSendToSqueakVideo; guint allocbytes; guint actualbytes; guint width; guint height; guint fps_n; guint fps_d; guint depth; GstClockTime startTime; GstClockTime duration; gboolean frame_ready; struct VirtualMachine* interpreterProxy; }; typedef struct _SqueakAudioVideoSink SqueakAudioVideoSink; typedef struct _SqueakAudioVideoSink *SqueakAudioVideoSinkPtr; void squeakVideoHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data); void squeakAudioHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data); void squeakSrcHandOff (GstElement* object, GstBuffer* buf, GstPad* pad, gpointer user_data); #define GST_LOCK(obj) (g_mutex_lock(GST_OBJECT_CAST(obj)->lock)) #define GST_UNLOCK(obj) (g_mutex_unlock(GST_OBJECT_CAST(obj)->lock)) ================================================ FILE: vm/src/from_squeak/Cross/plugins/HostWindowPlugin/HostWindowPlugin.h ================================================ /* Host windows plugin header file * tim@sumeru.stanford.edu * All sizes are in pixels; convert from OS abstract units as needed * windowHandles etc are expected to be SmallInteger valid values * windowHandle 1 is the traditional main window */ /* closeWindow: arg is sqInt windowIndex. Fail (return 0) if anything goes wrong * - typically the windowIndex invalid or similar */ extern sqInt closeWindow(sqInt index); /* createWindow: takes sqInt width, height and origin x/y plus a char* list of * as yet undefined attributes. Returns an sqInt window index or 0 for failure * Failure may occur because of an inability to add the window, too many * windows already extant (platform dependant), the specified size being * unreasonable etc. */ extern sqInt createWindowWidthheightoriginXyattrlength(sqInt w, sqInt h, sqInt x, sqInt y, char * list, sqInt attributeListLength); /* ioShowDisplayOnWindow: similar to ioShowDisplay but adds the sqInt windowIndex * Return true if ok, false if not, but not currently checked */ extern sqInt ioShowDisplayOnWindow( unsigned char* dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB, sqInt windowIndex); /* ioSizeOfWindow: arg is sqInt windowIndex. Return the size of the specified * window in (width<<16 || height) format like ioScreenSize. * Return -1 for failure - typically invalid windowIndex * -1 is chosen since itwould correspond to a window size of 64k@64k which * I hope is unlikely for some time to come */ extern sqInt ioSizeOfWindow(sqInt windowIndex); /* ioSizeOfWindowSetxy: args are sqInt windowIndex, sqInt w & h for the * width / height to make the window. Return the actual size the OS * produced in (width<<16 || height) format or -1 for failure as above. */ extern sqInt ioSizeOfWindowSetxy(sqInt windowIndex, sqInt w, sqInt h); /* ioPositionOfWindow: arg is sqInt windowIndex. Return the pos of the specified * window in (left<<16 || top) format like ioScreenSize. * Return -1 (as above) for failure - tpyically invalid windowIndex */ extern sqInt ioPositionOfWindow(sqInt windowIndex); /* ioPositionOfWindowSetxy: args are sqInt windowIndex, sqInt x & y for the * origin x/y for the window. Return the actual origin the OS * produced in (left<<16 || top) format or -1 for failure, as above */ extern sqInt ioPositionOfWindowSetxy(sqInt windowIndex, sqInt x, sqInt y); /* ioSetTitleOfWindow: args are sqInt windowIndex, char* newTitle and * sqInt size of new title. Fail with -1 if windowIndex is invalid, string is too long for platform etc. Leave previous title in place on failure */ sqInt ioSetTitleOfWindow(sqInt windowIndex, char * newTitle, sqInt sizeOfTitle); /* ioCloseAllWindows: sqIntended for VM shutdown. * Close all the windows that appear to be open. * No useful return value since we're getting out of Dodge anyway. */ extern sqInt ioCloseAllWindows(void); ================================================ FILE: vm/src/from_squeak/Cross/plugins/IA32ABI/dabusiness.h ================================================ /* * dabusiness.h * * Written by Eliot Miranda 11/07. * Copyright 2007 Cadence Design Systems. All rights reserved. * * Body of the various callIA32XXXReturn functions. * Call a foreign function according to IA32-ish ABI rules. */ long i, size; sqInt funcAlien, resultMaybeAlien; char *argvec; #if STACK_ALIGN_BYTES char *argstart; #endif for (i = numArgs, size = 0; --i >= 0;) { sqInt arg = argVector[i]; if (objIsAlien(arg) && sizeField(arg)) size += moduloPOT(sizeof(long),abs(sizeField(arg))); else /* assume an integer or pointer. check below. */ size += sizeof(long); } #if STACK_ALIGN_BYTES /* At point of call stack must be aligned to STACK_ALIGN_BYTES. So alloca * at least enough for this plus the argvector, and start writing argvector * at aligned point. Then just prior to call cut-back stack to aligned. */ argvec = alloca(STACK_ALIGN_BYTES + moduloPOT(STACK_ALIGN_BYTES,size)); argvec = alignModuloPOT(STACK_ALIGN_BYTES, argvec); argstart = argvec; #else argvec = alloca(moduloPOT(sizeof(long),size)); # if defined(__MINGW32__) && (__GNUC__ >= 3) /* * cygwin & MinGW's gcc 3.4.x's alloca is a library routine that answers * %esp + 4, so the outgoing stack is offset by one word if uncorrected. * Grab the actual stack pointer to correct. */ argvec = getsp(); # endif #endif for (i = 0; i < numArgs; i++) { sqInt arg = argVector[i]; if (isSmallInt(arg)) { *(long *)argvec = intVal(arg); argvec += sizeof(long); } else if (objIsAlien(arg)) { long argByteSize; if (!(size = sizeField(arg))) size = argByteSize = sizeof(void *); else argByteSize = abs(size); memcpy(argvec, startOfDataWithSize(arg,size), argByteSize); argvec += moduloPOT(sizeof(long), argByteSize); } else if (objIsUnsafeAlien(arg)) { sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg); void *v = interpreterProxy->firstIndexableField(bitsObj); *(void **)argvec = v; argvec += sizeof(long); } else { long v = interpreterProxy->signed32BitValueOf(arg); if (interpreterProxy->failed()) return PrimErrBadArgument; *(long *)argvec = v; argvec += sizeof(long); } } funcAlien = interpreterProxy->stackValue(funcOffset); f = *(void **)startOfParameterData(funcAlien); #if STACK_ALIGN_BYTES /* cut stack back to start of aligned args */ setsp(argstart); #endif r = f(); /* post call need to refresh stack pointer in case of call-back and GC. */ resultMaybeAlien = interpreterProxy->stackValue(resultOffset); if (objIsAlien(resultMaybeAlien)) { if (!(size = sizeField(resultMaybeAlien))) size = sizeof(void *); memcpy(startOfDataWithSize(resultMaybeAlien,size), &r, min(abs(size), sizeof(r))); } return PrimNoErr; ================================================ FILE: vm/src/from_squeak/Cross/plugins/IA32ABI/ia32abi.h ================================================ /* * platforms/Cross/plugins/IA32ABI/ia32abi.h * * Written by Eliot Miranda 11/07. * Copyright 2007 Cadence Design Systems. All rights reserved. * * Call foreign functons returning results in either %eax, %edx (Integral) * or %f0 (Float, Double). * * The primitive will have signatures of the form * * primFFIResult: result call: functionAddress * with: firstArg ... with: lastArg * * * result primFFICall: functionAddress * with: firstArg ... with: lastArg * * * functionAddress primFFICallResult: result * with: firstArg ... with: lastArg * */ #define SIGNATURE sqInt *argVector/* call args on stack or in array */, \ int numArgs, /* arg count of function to call */ \ int funcOffset, /* stack offset of func Alien */ \ int resultOffset/* stack offset of result Alien */ extern sqInt callIA32IntegralReturn(SIGNATURE); extern sqInt callIA32FloatReturn (SIGNATURE); extern sqInt callIA32DoubleReturn (SIGNATURE); extern long thunkEntry (void *thunkp, long *stackp); extern void *allocateExecutablePage(long *pagesize); /* Use the most minimal setjmp/longjmp pair available; no signal handling * wanted or necessary. */ #if !defined(WIN32) # define setjmp _setjmp # define longjmp _longjmp #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/IA32ABI/ia32abicc.c ================================================ /* * ia32abicc.c * * Support for Call-outs and Call-backs from the Plugin. * Written by Eliot Miranda 11/07. * Copyright 2007 Cadence Design Systems. All rights reserved. * */ #if defined(_MSC_VER) || defined(__MINGW32__) # include "windows.h" /* for GetSystemInfo & VirtualAlloc */ #elif __APPLE__ && __MACH__ # include /* for mprotect */ # if OBJC_DEBUG /* define this to get debug info for struct objc_class et al */ # include # include struct objc_class *baz; void setbaz(void *p) { baz = p; } void *getbaz() { return baz; } # endif # include /* for valloc */ # include /* for mprotect */ #else # include /* for valloc */ # include /* for mprotect */ #endif #include #include /* for fprintf(stderr,...) */ #include "vmCallback.h" #include "sqMemoryAccess.h" #include "sqVirtualMachine.h" #include "ia32abi.h" #if !defined(min) # define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; #if defined(SQ_IMAGE32) # define BytesPerOop 4 #elif defined(SQ_IMAGE64) # define BytesPerOop 8 #else # error cannot determine image word size/object header size #endif #define BaseHeaderSize BytesPerOop #ifdef _MSC_VER # define alloca _alloca #endif #if __GNUC__ # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp)) # define getsp() ({ void *esp; asm volatile ("movl %%esp,%0" : "=r"(esp) : ); esp;}) #endif #if __APPLE__ && __MACH__ && __i386__ # define STACK_ALIGN_BYTES 16 #endif #if !defined(setsp) # define setsp(ignored) 0 #endif #define moduloPOT(m,v) ((v)+(m)-1 & ~((m)-1)) #define alignModuloPOT(m,v) ((void *)moduloPOT(m,(unsigned long)(v))) #define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien())) #define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien())) #define sizeField(alien) (*(long *)pointerForOop((sqInt)(alien) + BaseHeaderSize)) #define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop) #if 0 /* obsolete after adding pointer Aliens with size field == 0 */ # define isIndirectOrPointer(alien) (sizeField(alien) <= 0) # define startOfData(alien) (isIndirectOrPointer(alien) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #endif #define isIndirect(alien) (sizeField(alien) < 0) #define startOfParameterData(alien) (isIndirect(alien) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isIndirectSize(size) ((size) < 0) #define startOfDataWithSize(alien,size) (isIndirectSize(size) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isSmallInt(oop) ((oop)&1) #define intVal(oop) (((long)(oop))>>1) /* * Call a foreign function that answers an integral result in %eax (and * possibly %edx) according to IA32-ish ABI rules. */ sqInt callIA32IntegralReturn(SIGNATURE) { #ifdef _MSC_VER __int64 (*f)(), r; #else long long (*f)(), r; #endif #include "dabusiness.h" } /* * Call a foreign function that answers a single-precision floating-point * result in %f0 according to IA32-ish ABI rules. */ sqInt callIA32FloatReturn(SIGNATURE) { float (*f)(), r; #include "dabusiness.h" } /* * Call a foreign function that answers a double-precision floating-point * result in %f0 according to IA32-ish ABI rules. */ sqInt callIA32DoubleReturn(SIGNATURE) { double (*f)(), r; #include "dabusiness.h" } /* * Entry-point for call-back thunks. Args are thunk address and stack pointer, * where the stack pointer is pointing one word below the return address of the * thunk's callee, 4 bytes below the thunk's first argument. The stack is: * callback * arguments * retpc (thunk) <--\ * address of retpc-/ <--\ * address of address of ret pc-/ * thunkp * esp->retpc (thunkEntry) * * The stack pointer is pushed twice to keep the stack alignment to 16 bytes, a * requirement on platforms using SSE2 such as Mac OS X, and harmless elsewhere. * * This function's roles are to use setjmp/longjmp to save the call point * and return to it, and to return any of the various values from the callback. * * Looking forward to support for x86-64, which typically has 6 register * arguments, the function would take 8 arguments, the 6 register args as * longs, followed by the thunkp and stackp passed on the stack. The register * args would get copied into a struct on the stack. A pointer to the struct * is then passed as an element of the VMCallbackContext. */ long thunkEntry(void *thunkp, long *stackp) { VMCallbackContext vmcc; int flags, returnType; if ((flags = interpreterProxy->ownVM(0)) < 0) { fprintf(stderr,"Warning; callback failed to own the VM\n"); return -1; } if (!(returnType = setjmp(vmcc.trampoline))) { vmcc.thunkp = thunkp; vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */ vmcc.intregargsp = 0; vmcc.floatregargsp = 0; interpreterProxy->sendInvokeCallbackContext(&vmcc); fprintf(stderr,"Warning; callback failed to invoke\n"); interpreterProxy->disownVM(flags); return -1; } interpreterProxy->disownVM(flags); switch (returnType) { case retword: return vmcc.rvs.valword; case retword64: { long vhigh = vmcc.rvs.valleint64.high; #if _MSC_VER _asm mov edx, dword ptr vhigh; #elif __GNUC__ asm("mov %0,%%edx" : : "m"(vhigh)); #else # error need to load edx with vmcc.rvs.valleint64.high on this compiler #endif return vmcc.rvs.valleint64.low; } case retdouble: { double valflt64 = vmcc.rvs.valflt64; #if _MSC_VER _asm fld qword ptr valflt64; #elif __GNUC__ asm("fldl %0" : : "m"(valflt64)); #else # error need to load %f0 with vmcc.rvs.valflt64 on this compiler #endif return 0; } case retstruct: memcpy( (void *)(stackp[1]), vmcc.rvs.valstruct.addr, vmcc.rvs.valstruct.size); return stackp[1]; } fprintf(stderr,"Warning; invalid callback return type\n"); return 0; } /* * Thunk allocation support. Since thunks must be exectuable and some OSs * may not provide default execute permission on memory returned by malloc * we must provide memory that is guaranteed to be executable. The abstraction * is to answer an Alien that references an executable piece of memory that * is some (possiby unitary) multiple of the pagesize. * * We assume the Smalltalk image code will manage subdividing the executable * page amongst thunks so there is no need to free these pages, since the image * will recycle parts of the page for reclaimed thunks. */ #if defined(_MSC_VER) || defined(__MINGW32__) static unsigned long pagesize = 0; #endif void * allocateExecutablePage(long *size) { void *mem; #if defined(_MSC_VER) || defined(__MINGW32__) #if !defined(MEM_TOP_DOWN) # define MEM_TOP_DOWN 0x100000 #endif if (!pagesize) { SYSTEM_INFO sysinf; GetSystemInfo(&sysinf); pagesize = sysinf.dwPageSize; } /* N.B. VirtualAlloc MEM_COMMIT initializes the memory returned to zero. */ mem = VirtualAlloc( 0, pagesize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if (mem) *size = pagesize; #else long pagesize = getpagesize(); if (!(mem = valloc(pagesize))) return 0; memset(mem, 0, pagesize); if (mprotect(mem, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { free(mem); return 0; } *size = pagesize; #endif return mem; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/InternetConfigPlugin/InternetConfigPlugin.h ================================================ int sqInternetConfigurationInit(void); int sqInternetConfigurationGetStringKeyedBykeySizeinto(char * aKey, int keyLength, char *nameptr); int sqInternetConfigurationShutdown(void); #pragma export on void sqInternetGetMacintoshFileTypeAndCreatorFromkeySizeinto(char * aFileName, int keyLength, char * creator); #pragma export off ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/Error.c ================================================ #include #include "jpeglib.h" #include struct error_mgr2 { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct error_mgr2 * error_ptr2; /* * Here's the routine that will replace the standard error_exit method: */ void error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a error_mgr2 struct, so coerce pointer */ error_ptr2 myerr = (error_ptr2) cinfo->err; /* Return control to the setjmp point */ longjmp(myerr->setjmp_buffer, 1); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.h ================================================ #include /* Interface to JPEG code */ #include "jpeglib.h" #include struct error_mgr2 { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct error_mgr2* error_ptr2; void error_exit (j_common_ptr cinfo); GLOBAL(void) jpeg_mem_src (j_decompress_ptr cinfo, char * pSourceData, unsigned sourceDataSize); GLOBAL(int) jpeg_mem_src_newLocationOfData (j_decompress_ptr cinfo, char * pSourceData, unsigned sourceDataSize); GLOBAL(void) jpeg_mem_dest (j_compress_ptr cinfo, char * pDestination, unsigned *pDestinationSize); ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/ReadMe.txt ================================================ Project Smarts - C Dynamic Link Library application README ---------------------------------------------------------- Select "Build Normal" on the project's pop-up menu to build the project target, a DLL file.  ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcapimin.c ================================================ /* * jcapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half * of the JPEG library. These are the "minimum" API routines that may be * needed in either the normal full-compression case or the transcoding-only * case. * * Most of the routines intended to be called directly by an application * are in this file or in jcapistd.c. But also see jcparam.c for * parameter-setup helper routines, jcomapi.c for routines shared by * compression and decompression, and jctrans.c for the transcoding case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG compression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) { int i; /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_compress_struct)) ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set * client_data, so we have to save and restore those fields. * Note: if application hasn't set client_data, tools like Purify may * complain here. */ { struct jpeg_error_mgr * err = cinfo->err; void * client_data = cinfo->client_data; /* ignore Purify complaint here */ MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); cinfo->err = err; cinfo->client_data = client_data; } cinfo->is_decompressor = FALSE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->dest = NULL; cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->script_space = NULL; cinfo->input_gamma = 1.0; /* in case application forgets */ /* OK, I'm ready */ cinfo->global_state = CSTATE_START; } /* * Destruction of a JPEG compression object */ GLOBAL(void) jpeg_destroy_compress (j_compress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Abort processing of a JPEG compression operation, * but don't destroy the object itself. */ GLOBAL(void) jpeg_abort_compress (j_compress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } /* * Forcibly suppress or un-suppress all quantization and Huffman tables. * Marks all currently defined tables as already written (if suppress) * or not written (if !suppress). This will control whether they get emitted * by a subsequent jpeg_start_compress call. * * This routine is exported for use by applications that want to produce * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but * since it is called by jpeg_start_compress, we put it here --- otherwise * jcparam.o would be linked whether the application used it or not. */ GLOBAL(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) { int i; JQUANT_TBL * qtbl; JHUFF_TBL * htbl; for (i = 0; i < NUM_QUANT_TBLS; i++) { if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) qtbl->sent_table = suppress; } for (i = 0; i < NUM_HUFF_TBLS; i++) { if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; } } /* * Finish JPEG compression. * * If a multipass operating mode was selected, this may do a great deal of * work including most of the actual output. */ GLOBAL(void) jpeg_finish_compress (j_compress_ptr cinfo) { JDIMENSION iMCU_row; if (cinfo->global_state == CSTATE_SCANNING || cinfo->global_state == CSTATE_RAW_OK) { /* Terminate first pass */ if (cinfo->next_scanline < cinfo->image_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_pass) (cinfo); } else if (cinfo->global_state != CSTATE_WRCOEFS) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any remaining passes */ while (! cinfo->master->is_last_pass) { (*cinfo->master->prepare_for_pass) (cinfo); for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) iMCU_row; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); } /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); } /* * Write a special marker. * This is only recommended for writing COM or APPn markers. * Must be called after jpeg_start_compress() and before * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). */ GLOBAL(void) jpeg_write_marker (j_compress_ptr cinfo, int marker, const JOCTET *dataptr, unsigned int datalen) { JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); if (cinfo->next_scanline != 0 || (cinfo->global_state != CSTATE_SCANNING && cinfo->global_state != CSTATE_RAW_OK && cinfo->global_state != CSTATE_WRCOEFS)) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ while (datalen--) { (*write_marker_byte) (cinfo, *dataptr); dataptr++; } } /* Same, but piecemeal. */ GLOBAL(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) { if (cinfo->next_scanline != 0 || (cinfo->global_state != CSTATE_SCANNING && cinfo->global_state != CSTATE_RAW_OK && cinfo->global_state != CSTATE_WRCOEFS)) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); } GLOBAL(void) jpeg_write_m_byte (j_compress_ptr cinfo, int val) { (*cinfo->marker->write_marker_byte) (cinfo, val); } /* * Alternate compression function: just write an abbreviated table file. * Before calling this, all parameters and a data destination must be set up. * * To produce a pair of files containing abbreviated tables and abbreviated * image data, one would proceed as follows: * * initialize JPEG object * set JPEG parameters * set destination to table file * jpeg_write_tables(cinfo); * set destination to image file * jpeg_start_compress(cinfo, FALSE); * write data... * jpeg_finish_compress(cinfo); * * jpeg_write_tables has the side effect of marking all tables written * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress * will not re-emit the tables unless it is passed write_all_tables=TRUE. */ GLOBAL(void) jpeg_write_tables (j_compress_ptr cinfo) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Initialize the marker writer ... bit of a crock to do it here. */ jinit_marker_writer(cinfo); /* Write them tables! */ (*cinfo->marker->write_tables_only) (cinfo); /* And clean up. */ (*cinfo->dest->term_destination) (cinfo); /* * In library releases up through v6a, we called jpeg_abort() here to free * any working memory allocated by the destination manager and marker * writer. Some applications had a problem with that: they allocated space * of their own from the library memory manager, and didn't want it to go * away during write_tables. So now we do nothing. This will cause a * memory leak if an app calls write_tables repeatedly without doing a full * compression cycle or otherwise resetting the JPEG object. However, that * seems less bad than unexpectedly freeing memory in the normal case. * An app that prefers the old behavior can call jpeg_abort for itself after * each call to jpeg_write_tables(). */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcapistd.c ================================================ /* * jcapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half * of the JPEG library. These are the "standard" API routines that are * used in the normal full-compression case. They are not used by a * transcoding-only application. Note that if an application links in * jpeg_start_compress, it will end up linking in the entire compressor. * We thus must separate this file from jcapimin.c to avoid linking the * whole compression library into a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Compression initialization. * Before calling this, all parameters and a data destination must be set up. * * We require a write_all_tables parameter as a failsafe check when writing * multiple datastreams from the same compression object. Since prior runs * will have left all the tables marked sent_table=TRUE, a subsequent run * would emit an abbreviated stream (no tables) by default. This may be what * is wanted, but for safety's sake it should not be the default behavior: * programmers should have to make a deliberate choice to emit abbreviated * images. Therefore the documentation and examples should encourage people * to pass write_all_tables=TRUE; then it will take active thought to do the * wrong thing. */ GLOBAL(void) jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ jinit_compress_master(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); /* Ready for application to drive first pass through jpeg_write_scanlines * or jpeg_write_raw_data. */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); } /* * Write some scanlines of data to the JPEG compressor. * * The return value will be the number of lines actually written. * This should be less than the supplied num_lines only in case that * the data destination module has requested suspension of the compressor, * or if more than image_height scanlines are passed in. * * Note: we warn about excess calls to jpeg_write_scanlines() since * this likely signals an application programmer error. However, * excess scanlines passed in the last valid call are *silently* ignored, * so that the application need not adjust num_lines for end-of-image * when using a multiple-scanline buffer. */ GLOBAL(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines) { JDIMENSION row_ctr, rows_left; if (cinfo->global_state != CSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) WARNMS(cinfo, JWRN_TOO_MUCH_DATA); /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->next_scanline; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Give master control module another chance if this is first call to * jpeg_write_scanlines. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between * jpeg_start_compress and jpeg_write_scanlines. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); /* Ignore any extra scanlines at bottom of image. */ rows_left = cinfo->image_height - cinfo->next_scanline; if (num_lines > rows_left) num_lines = rows_left; row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); cinfo->next_scanline += row_ctr; return row_ctr; } /* * Alternate entry point to write raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != CSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->next_scanline; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Give master control module another chance if this is first call to * jpeg_write_raw_data. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between * jpeg_start_compress and jpeg_write_raw_data. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); /* Verify that at least one iMCU row has been passed. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; if (num_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Directly compress the row. */ if (! (*cinfo->coef->compress_data) (cinfo, data)) { /* If compressor did not consume the whole row, suspend processing. */ return 0; } /* OK, we processed one iMCU row. */ cinfo->next_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jccoefct.c ================================================ /* * jccoefct.c * * Copyright (C) 1994-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for compression. * This controller is the top level of the JPEG compressor proper. * The coefficient buffer lies between forward-DCT and entropy encoding steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* We use a full-image coefficient buffer when doing Huffman optimization, * and also for writing multiple-scan JPEG files. In all cases, the DCT * step is run during the first pass, and subsequent passes need only read * the buffered coefficients. */ #ifdef ENTROPY_OPT_SUPPORTED #define FULL_COEF_BUFFER_SUPPORTED #else #ifdef C_MULTISCAN_FILES_SUPPORTED #define FULL_COEF_BUFFER_SUPPORTED #endif #endif /* Private buffer controller object */ typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* For single-pass compression, it's sufficient to buffer just one MCU * (although this may prove a bit slow in practice). We allocate a * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each * MCU constructed and sent. (On 80x86, the workspace is FAR even though * it's not really very big; this is to keep the module interfaces unchanged * when a large coefficient buffer is necessary.) * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays. */ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(boolean) compress_data JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #ifdef FULL_COEF_BUFFER_SUPPORTED METHODDEF(boolean) compress_first_pass JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); METHODDEF(boolean) compress_output JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #endif LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->mcu_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; coef->iMCU_row_num = 0; start_iMCU_row(cinfo); switch (pass_mode) { case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_output; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data in the single-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the image. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf contains a plane for each component in image, * which we index according to the component's SOF position. */ METHODDEF(boolean) compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, bi, ci, yindex, yoffset, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks * sequentially. Dummy blocks at the right or bottom edge are filled in * specially. The data in them does not matter for image reconstruction, * so we fill them with values that will encode to the smallest amount of * data, viz: all zeroes in the AC entries, DC entries equal to previous * block's DC value. (Thanks to Thomas Kinsman for this idea.) */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[compptr->component_index], coef->MCU_buffer[blkn], ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; } } } else { /* Create a row of dummy blocks at the bottom of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn], compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; } } blkn += compptr->MCU_width; ypos += DCTSIZE; } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } #ifdef FULL_COEF_BUFFER_SUPPORTED /* * Process some data in the first pass of a multi-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the image. * This amount of data is read from the source buffer, DCT'd and quantized, * and saved into the virtual arrays. We also generate suitable dummy blocks * as needed at the right and lower edges. (The dummy blocks are constructed * in the virtual arrays, which have been padded appropriately.) This makes * it possible for subsequent passes not to worry about real vs. dummy blocks. * * We must also emit the data to the entropy encoder. This is conveniently * done by calling compress_output() after we've loaded the current strip * of the virtual arrays. * * NB: input_buf contains a plane for each component in image. All * components are DCT'd and loaded into the virtual arrays in this pass. * However, it may be that only a subset of the components are emitted to * the entropy encoder during this first pass; be careful about looking * at the scan-dependent variables (MCU dimensions, etc). */ METHODDEF(boolean) compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; JCOEF lastDC; jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Count non-dummy DCT block rows in this iMCU row. */ if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, (JDIMENSION) (block_row * DCTSIZE), (JDIMENSION) 0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } } } /* If at end of image, create dummy block rows as needed. * The tricky part here is that within each MCU, we want the DC values * of the dummy blocks to match the last real block's DC value. * This squeezes a few more bytes out of the resulting file... */ if (coef->iMCU_row_num == last_iMCU_row) { blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; jzero_far((void FAR *) thisblockrow, (size_t) (blocks_across * SIZEOF(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } } } } /* NB: compress_output will increment iMCU_row_num if successful. * A suspension return will result in redoing all the work above next time. */ /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); } /* * Process some data in subsequent passes of a multi-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the scan. * The data is obtained from the virtual arrays and fed to the entropy coder. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf is ignored; it is likely to be a NULL pointer. */ METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. * NB: during first pass, this is safe only because the buffers will * already be aligned properly, so jmemmgr.c won't need to do any I/O. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { coef->MCU_buffer[blkn++] = buffer_ptr++; } } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } #endif /* FULL_COEF_BUFFER_SUPPORTED */ /* * Initialize coefficient buffer controller. */ GLOBAL(void) jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ int ci; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->whole_image[0] = NULL; /* flag for no virtual arrays */ } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jccolor.c ================================================ /* * jccolor.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_converter pub; /* public fields */ /* Private state for RGB->YCC conversion */ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ } my_color_converter; typedef my_color_converter * my_cconvert_ptr; /**************** RGB -> YCbCr conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) * were not represented exactly. Now we sacrifice exact representation of * maximum red and maximum blue in order to get exact grayscales. * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< Y section */ #define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ #define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ #define R_CB_OFF (3*(MAXJSAMPLE+1)) #define G_CB_OFF (4*(MAXJSAMPLE+1)) #define B_CB_OFF (5*(MAXJSAMPLE+1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ #define G_CR_OFF (6*(MAXJSAMPLE+1)) #define B_CR_OFF (7*(MAXJSAMPLE+1)) #define TABLE_SIZE (8*(MAXJSAMPLE+1)) /* * Initialize for RGB->YCC colorspace conversion. */ METHODDEF(void) rgb_ycc_start (j_compress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 * rgb_ycc_tab; INT32 i; /* Allocate and fill in the conversion tables. */ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. * This ensures that the maximum output will round to MAXJSAMPLE * not MAXJSAMPLE+1, and thus that we don't have to range-limit. */ rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; /* B=>Cb and R=>Cr tables are the same rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; */ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; } } /* * Convert some rows of samples to the JPEG colorspace. * * Note that we change from the application's interleaved-pixel format * to our internal noninterleaved, one-plane-per-component format. * The input buffer is therefore three times as wide as the output buffer. * * A starting row offset is provided only for the output buffer. The caller * can easily adjust the passed input_buf value to accommodate any row * offset required on that side. */ METHODDEF(void) rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /**************** Cases other than RGB -> YCbCr **************/ /* * Convert some rows of samples to the JPEG colorspace. * This version handles RGB->grayscale conversion, which is the same * as the RGB->Y portion of RGB->YCbCr. * We assume rgb_ycc_start has been called (we only use the Y tables). */ METHODDEF(void) rgb_gray_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* Y */ outptr[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles Adobe-style CMYK->YCCK conversion, * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same * conversion as above, while passing K (black) unchanged. * We assume rgb_ycc_start has been called. */ METHODDEF(void) cmyk_ycck_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ inptr += 4; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles grayscale output with no conversion. * The source can be either plain grayscale or YCbCr (since Y == gray). */ METHODDEF(void) grayscale_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; int instride = cinfo->input_components; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ inptr += instride; } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles multi-component colorspaces without conversion. * We assume input_components == num_components. */ METHODDEF(void) null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; register int ci; int nc = cinfo->num_components; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { /* It seems fastest to make a separate pass for each component. */ for (ci = 0; ci < nc; ci++) { inptr = *input_buf; outptr = output_buf[ci][output_row]; for (col = 0; col < num_cols; col++) { outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ inptr += nc; } } input_buf++; output_row++; } } /* * Empty method for start_pass. */ METHODDEF(void) null_method (j_compress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for input colorspace conversion. */ GLOBAL(void) jinit_color_converter (j_compress_ptr cinfo) { my_cconvert_ptr cconvert; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_converter)); cinfo->cconvert = (struct jpeg_color_converter *) cconvert; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; /* Make sure input_components agrees with in_color_space */ switch (cinfo->in_color_space) { case JCS_GRAYSCALE: if (cinfo->input_components != 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_RGB: #if RGB_PIXELSIZE != 3 if (cinfo->input_components != RGB_PIXELSIZE) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; #endif /* else share code with YCbCr */ case JCS_YCbCr: if (cinfo->input_components != 3) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->input_components != 4) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->input_components < 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; } /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_GRAYSCALE) cconvert->pub.color_convert = grayscale_convert; else if (cinfo->in_color_space == JCS_RGB) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_gray_convert; } else if (cinfo->in_color_space == JCS_YCbCr) cconvert->pub.color_convert = grayscale_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_RGB) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; } else if (cinfo->in_color_space == JCS_YCbCr) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = cmyk_ycck_convert; } else if (cinfo->in_color_space == JCS_YCCK) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* allow null conversion of JCS_UNKNOWN */ if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cconvert->pub.color_convert = null_convert; break; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcdctmgr.c ================================================ /* * jcdctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the forward-DCT management logic. * This code selects a particular DCT implementation to be used, * and it performs related housekeeping chores including coefficient * quantization. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* Private subobject for this module */ typedef struct { struct jpeg_forward_dct pub; /* public fields */ /* Pointer to the DCT routine actually in use */ forward_DCT_method_ptr do_dct; /* The actual post-DCT divisors --- not identical to the quant table * entries, because of scaling (especially for an unnormalized DCT). * Each table is given in normal array order. */ DCTELEM * divisors[NUM_QUANT_TBLS]; #ifdef DCT_FLOAT_SUPPORTED /* Same as above for the floating-point case. */ float_DCT_method_ptr do_float_dct; FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; #endif } my_fdct_controller; typedef my_fdct_controller * my_fdct_ptr; /* * Initialize for a processing pass. * Verify that all referenced Q-tables are present, and set up * the divisor table for each one. * In the current implementation, DCT of all components is done during * the first pass, even if only some components will be output in the * first scan. Hence all components should be examined here. */ METHODDEF(void) start_pass_fdctmgr (j_compress_ptr cinfo) { my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; int ci, qtblno, i; jpeg_component_info *compptr; JQUANT_TBL * qtbl; DCTELEM * dtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { qtblno = compptr->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); qtbl = cinfo->quant_tbl_ptrs[qtblno]; /* Compute divisors for this quant table */ /* We may do this more than once for same table, but it's not a big deal */ switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: /* For LL&M IDCT method, divisors are equal to raw quantization * coefficients multiplied by 8 (to counteract scaling). */ if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. */ #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = (DCTELEM) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), CONST_BITS-3); } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. * What's actually stored is 1/divisor so that the inner loop can * use a multiplication rather than a division. */ FAST_FLOAT * fdtbl; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; if (fdct->float_divisors[qtblno] == NULL) { fdct->float_divisors[qtblno] = (FAST_FLOAT *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(FAST_FLOAT)); } fdtbl = fdct->float_divisors[qtblno]; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fdtbl[i] = (FAST_FLOAT) (1.0 / (((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col] * 8.0))); i++; } } } break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } } /* * Perform forward DCT on one or more blocks of a component. * * The input samples are taken from the sample_data[] array starting at * position start_row/start_col, and moving to the right for any additional * blocks. The quantized coefficients are returned in coef_blocks[]. */ METHODDEF(void) forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; forward_DCT_method_ptr do_dct = fdct->do_dct; DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { /* Load data into workspace, applying unsigned->signed conversion */ { register DCTELEM *workspaceptr; register JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; } } #endif } } /* Perform the DCT */ (*do_dct) (workspace); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register DCTELEM temp, qval; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { qval = divisors[i]; temp = workspace[i]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } output_ptr[i] = (JCOEF) temp; } } } } #ifdef DCT_FLOAT_SUPPORTED METHODDEF(void) forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for floating-point DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; float_DCT_method_ptr do_dct = fdct->do_float_dct; FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { /* Load data into workspace, applying unsigned->signed conversion */ { register FAST_FLOAT *workspaceptr; register JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *workspaceptr++ = (FAST_FLOAT) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); } } #endif } } /* Perform the DCT */ (*do_dct) (workspace); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register FAST_FLOAT temp; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { /* Apply the quantization and scaling factor */ temp = workspace[i] * divisors[i]; /* Round to nearest integer. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * The maximum coefficient size is +-16K (for 12-bit data), so this * code should work for either 16-bit or 32-bit ints. */ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); } } } } #endif /* DCT_FLOAT_SUPPORTED */ /* * Initialize FDCT manager. */ GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo) { my_fdct_ptr fdct; int i; fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_fdct_controller)); cinfo->fdct = (struct jpeg_forward_dct *) fdct; fdct->pub.start_pass = start_pass_fdctmgr; switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: fdct->pub.forward_DCT = forward_DCT; fdct->do_dct = jpeg_fdct_islow; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: fdct->pub.forward_DCT = forward_DCT; fdct->do_dct = jpeg_fdct_ifast; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: fdct->pub.forward_DCT = forward_DCT_float; fdct->do_float_dct = jpeg_fdct_float; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } /* Mark divisor tables unallocated */ for (i = 0; i < NUM_QUANT_TBLS; i++) { fdct->divisors[i] = NULL; #ifdef DCT_FLOAT_SUPPORTED fdct->float_divisors[i] = NULL; #endif } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jchuff.c ================================================ /* * jchuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. * * Much of the complexity here has to do with supporting output suspension. * If the data destination module demands suspension, we want to be able to * back up to the start of the current MCU. To do this, we copy state * variables into local working storage, and update them back to the * permanent JPEG objects only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jchuff.h" /* Declarations shared with jcphuff.c */ /* Expanded entropy encoder object for Huffman encoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken * structure assignment. You'll need to fix this code if you have * such a compiler and you change MAX_COMPS_IN_SCAN. */ #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ ((dest).put_buffer = (src).put_buffer, \ (dest).put_bits = (src).put_bits, \ (dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ savable_state saved; /* Bit buffer & DC state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ /* Pointers to derived tables (these workspaces have image lifespan) */ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; #ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ long * dc_count_ptrs[NUM_HUFF_TBLS]; long * ac_count_ptrs[NUM_HUFF_TBLS]; #endif } huff_entropy_encoder; typedef huff_entropy_encoder * huff_entropy_ptr; /* Working state while writing an MCU. * This struct contains all the fields that are needed by subroutines. */ typedef struct { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ savable_state cur; /* Current bit buffer & DC state */ j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; /* Forward declarations */ METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); #ifdef ENTROPY_OPT_SUPPORTED METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); #endif /* * Initialize for a Huffman-compressed scan. * If gather_statistics is TRUE, we do not output anything during the scan, * just count the Huffman symbols used and generate Huffman code tables. */ METHODDEF(void) start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, dctbl, actbl; jpeg_component_info * compptr; if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED entropy->pub.encode_mcu = encode_mcu_gather; entropy->pub.finish_pass = finish_pass_gather; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { entropy->pub.encode_mcu = encode_mcu_huff; entropy->pub.finish_pass = finish_pass_huff; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED /* Check for invalid table indexes */ /* (make_c_derived_tbl does this in the other path) */ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); if (actbl < 0 || actbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); /* Allocate and zero the statistics tables */ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ if (entropy->dc_count_ptrs[dctbl] == NULL) entropy->dc_count_ptrs[dctbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); if (entropy->ac_count_ptrs[actbl] == NULL) entropy->ac_count_ptrs[actbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); #endif } else { /* Compute derived values for Huffman tables */ /* We may do this more than once for a table, but it's not expensive */ jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, & entropy->dc_derived_tbls[dctbl]); jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, & entropy->ac_derived_tbls[actbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Initialize bit buffer to empty */ entropy->saved.put_buffer = 0; entropy->saved.put_bits = 0; /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * * Note this is also used by jcphuff.c. */ GLOBAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; c_derived_tbl *dtbl; int p, i, l, lastp, si, maxsymbol; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (c_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_derived_tbl)); dtbl = *pdtbl; /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. */ if (((INT32) code) >= (((INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set all codeless symbols to have code length 0; * this lets us detect duplicate VAL entries here, and later * allows emit_bits to detect any attempt to emit such symbols. */ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); /* This is also a convenient place to check for out-of-range * and duplicated VAL entries. We allow 0..255 for AC symbols * but only 0..15 for DC. (We could constrain them further * based on data depth and mode, but this seems enough.) */ maxsymbol = isDC ? 15 : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); dtbl->ehufco[i] = huffcode[p]; dtbl->ehufsi[i] = huffsize[p]; } } /* Outputting bytes to the file */ /* Emit a byte, taking 'action' if must suspend. */ #define emit_byte(state,val,action) \ { *(state)->next_output_byte++ = (JOCTET) (val); \ if (--(state)->free_in_buffer == 0) \ if (! dump_buffer(state)) \ { action; } } LOCAL(boolean) dump_buffer (working_state * state) /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ { struct jpeg_destination_mgr * dest = state->cinfo->dest; if (! (*dest->empty_output_buffer) (state->cinfo)) return FALSE; /* After a successful buffer dump, must reset buffer pointers */ state->next_output_byte = dest->next_output_byte; state->free_in_buffer = dest->free_in_buffer; return TRUE; } /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in put_buffer * between calls, so 24 bits are sufficient. */ INLINE LOCAL(boolean) emit_bits (working_state * state, unsigned int code, int size) /* Emit some bits; return TRUE if successful, FALSE if must suspend */ { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = (INT32) code; register int put_bits = state->cur.put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte(state, c, return FALSE); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte(state, 0, return FALSE); } put_buffer <<= 8; put_bits -= 8; } state->cur.put_buffer = put_buffer; /* update state variables */ state->cur.put_bits = put_bits; return TRUE; } LOCAL(boolean) flush_bits (working_state * state) { if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ return FALSE; state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; return TRUE; } /* Encode a single block's worth of coefficients */ LOCAL(boolean) encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) { register int temp, temp2; register int nbits; register int k, r, i; /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0] - last_dc_val; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > MAX_COEF_BITS+1) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[jpeg_natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) return FALSE; return TRUE; } /* * Emit a restart marker & resynchronize predictions. */ LOCAL(boolean) emit_restart (working_state * state, int restart_num) { int ci; if (! flush_bits(state)) return FALSE; emit_byte(state, 0xFF, return FALSE); emit_byte(state, JPEG_RST0 + restart_num, return FALSE); /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) state->cur.last_dc_val[ci] = 0; /* The restart counter is not updated until we successfully write the MCU. */ return TRUE; } /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; int blkn, ci; jpeg_component_info * compptr; /* Load up working state */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! emit_restart(&state, entropy->next_restart_num)) return FALSE; } /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; if (! encode_one_block(&state, MCU_data[blkn][0], state.cur.last_dc_val[ci], entropy->dc_derived_tbls[compptr->dc_tbl_no], entropy->ac_derived_tbls[compptr->ac_tbl_no])) return FALSE; /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } /* Completed MCU, so update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF(void) finish_pass_huff (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; /* Load up working state ... flush_bits needs it */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; /* Flush out the last data */ if (! flush_bits(&state)) ERREXIT(cinfo, JERR_CANT_SUSPEND); /* Update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); } /* * Huffman coding optimization. * * We first scan the supplied data and count the number of uses of each symbol * that is to be Huffman-coded. (This process MUST agree with the code above.) * Then we build a Huffman coding tree for the observed counts. * Symbols which are not needed at all for the particular image are not * assigned any code, which saves space in the DHT marker as well as in * the compressed data. */ #ifdef ENTROPY_OPT_SUPPORTED /* Process a single block's worth of coefficients */ LOCAL(void) htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, long dc_counts[], long ac_counts[]) { register int temp; register int nbits; register int k, r; /* Encode the DC coefficient difference per section F.1.2.1 */ temp = block[0] - last_dc_val; if (temp < 0) temp = -temp; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > MAX_COEF_BITS+1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count the Huffman symbol for the number of bits */ dc_counts[nbits]++; /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[jpeg_natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { ac_counts[0xF0]++; r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ if (temp < 0) temp = -temp; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count Huffman symbol for run length / number of bits */ ac_counts[(r << 4) + nbits]++; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) ac_counts[0]++; } /* * Trial-encode one MCU's worth of Huffman-compressed coefficients. * No data is actually output, so no suspension return is possible. */ METHODDEF(boolean) encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int blkn, ci; jpeg_component_info * compptr; /* Take care of restart intervals if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Update restart state */ entropy->restarts_to_go = cinfo->restart_interval; } entropy->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], entropy->dc_count_ptrs[compptr->dc_tbl_no], entropy->ac_count_ptrs[compptr->ac_tbl_no]); entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; } return TRUE; } /* * Generate the best Huffman code table for the given counts, fill htbl. * Note this is also used by jcphuff.c. * * The JPEG standard requires that no symbol be assigned a codeword of all * one bits (so that padding bits added at the end of a compressed segment * can't look like a valid code). Because of the canonical ordering of * codewords, this just means that there must be an unused slot in the * longest codeword length category. Section K.2 of the JPEG spec suggests * reserving such a slot by pretending that symbol 256 is a valid symbol * with count 1. In theory that's not optimal; giving it count zero but * including it in the symbol set anyway should give a better Huffman code. * But the theoretically better code actually seems to come out worse in * practice, because it produces more all-ones bytes (which incur stuffed * zero bytes in the final file). In any case the difference is tiny. * * The JPEG standard requires Huffman codes to be no more than 16 bits long. * If some symbols have a very small but nonzero probability, the Huffman tree * must be adjusted to meet the code length restriction. We currently use * the adjustment method suggested in JPEG section K.2. This method is *not* * optimal; it may not choose the best possible limited-length code. But * typically only very-low-frequency symbols will be given less-than-optimal * lengths, so the code is almost optimal. Experimental comparisons against * an optimal limited-length-code algorithm indicate that the difference is * microscopic --- usually less than a hundredth of a percent of total size. * So the extra complexity of an optimal algorithm doesn't seem worthwhile. */ GLOBAL(void) jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ int codesize[257]; /* codesize[k] = code length of symbol k */ int others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; long v; /* This algorithm is explained in section K.2 of the JPEG standard */ MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ freq[256] = 1; /* make sure 256 has a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 * will be placed last in the largest codeword category. */ /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { /* Find the smallest nonzero frequency, set c1 = its symbol */ /* In case of ties, take the larger symbol number */ c1 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; } } /* Find the next smallest nonzero frequency, set c2 = its symbol */ /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } others[c1] = c2; /* chain c2 onto c1's tree branch */ /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. * Here is what the JPEG spec says about how this next bit works: * Since symbols are paired for the longest Huffman code, the symbols are * removed from this length category two at a time. The prefix for the pair * (which is one bit shorter) is allocated to one of the pair; then, * skipping the BITS entry for that prefix length, a code word from the next * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) j--; bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ bits[j]--; /* symbol of this length is now a prefix */ } } /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. */ p = 0; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { htbl->huffval[p] = (UINT8) j; p++; } } } /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; } /* * Finish up a statistics-gathering pass and create the new Huffman tables. */ METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, dctbl, actbl; jpeg_component_info * compptr; JHUFF_TBL **htblptr; boolean did_dc[NUM_HUFF_TBLS]; boolean did_ac[NUM_HUFF_TBLS]; /* It's important not to apply jpeg_gen_optimal_table more than once * per table, because it clobbers the input frequency counts! */ MEMZERO(did_dc, SIZEOF(did_dc)); MEMZERO(did_ac, SIZEOF(did_ac)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; if (! did_dc[dctbl]) { htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); did_dc[dctbl] = TRUE; } if (! did_ac[actbl]) { htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); did_ac[actbl] = TRUE; } } } #endif /* ENTROPY_OPT_SUPPORTED */ /* * Module initialization routine for Huffman entropy encoding. */ GLOBAL(void) jinit_huff_encoder (j_compress_ptr cinfo) { huff_entropy_ptr entropy; int i; entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_encoder)); cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; entropy->pub.start_pass = start_pass_huff; /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; #ifdef ENTROPY_OPT_SUPPORTED entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; #endif } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jchuff.h ================================================ /* * jchuff.h * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains declarations for Huffman entropy encoding routines * that are shared between the sequential encoder (jchuff.c) and the * progressive encoder (jcphuff.c). No other modules need to see these. */ /* The legal range of a DCT coefficient is * -1024 .. +1023 for 8-bit data; * -16384 .. +16383 for 12-bit data. * Hence the magnitude should always fit in 10 or 14 bits respectively. */ #if BITS_IN_JSAMPLE == 8 #define MAX_COEF_BITS 10 #else #define MAX_COEF_BITS 14 #endif /* Derived data constructed for each Huffman table */ typedef struct { unsigned int ehufco[256]; /* code for each symbol */ char ehufsi[256]; /* length of code for each symbol */ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ } c_derived_tbl; /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_make_c_derived_tbl jMkCDerived #define jpeg_gen_optimal_table jGenOptTbl #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Expand a Huffman table definition into the derived format */ EXTERN(void) jpeg_make_c_derived_tbl JPP((j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl)); /* Generate an optimal table definition given the specified counts */ EXTERN(void) jpeg_gen_optimal_table JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcinit.c ================================================ /* * jcinit.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains initialization logic for the JPEG compressor. * This routine is in charge of selecting the modules to be executed and * making an initialization call to each one. * * Logically, this code belongs in jcmaster.c. It's split out because * linking this routine implies linking the entire compression library. * For a transcoding-only application, we want to be able to use jcmaster.c * without linking in the whole library. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Master selection of compression modules. * This is done once at the start of processing an image. We determine * which modules will be used and give them appropriate initialization calls. */ GLOBAL(void) jinit_compress_master (j_compress_ptr cinfo) { /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, FALSE /* full compression */); /* Preprocessing */ if (! cinfo->raw_data_in) { jinit_color_converter(cinfo); jinit_downsampler(cinfo); jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); } /* Forward DCT */ jinit_forward_dct(cinfo); /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED jinit_phuff_encoder(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else jinit_huff_encoder(cinfo); } /* Need a full-image coefficient buffer in any multi-pass mode. */ jinit_c_coef_controller(cinfo, (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Write the datastream header (SOI) immediately. * Frame and scan headers are postponed till later. * This lets application insert special markers after the SOI. */ (*cinfo->marker->write_file_header) (cinfo); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcmainct.c ================================================ /* * jcmainct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for compression. * The main buffer lies between the pre-processor and the JPEG * compressor proper; it holds downsampled data in the JPEG colorspace. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Note: currently, there is no operating mode in which a full-image buffer * is needed at this step. If there were, that mode could not be used with * "raw data" input, since this module is bypassed in that case. However, * we've left the code here for possible use in special applications. */ #undef FULL_MAIN_BUFFER_SUPPORTED /* Private buffer controller object */ typedef struct { struct jpeg_c_main_controller pub; /* public fields */ JDIMENSION cur_iMCU_row; /* number of current iMCU row */ JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ boolean suspended; /* remember if we suspended output */ J_BUF_MODE pass_mode; /* current operating mode */ /* If using just a strip buffer, this points to the entire set of buffers * (we allocate one for each component). In the full-image case, this * points to the currently accessible strips of the virtual arrays. */ JSAMPARRAY buffer[MAX_COMPONENTS]; #ifdef FULL_MAIN_BUFFER_SUPPORTED /* If using full-image storage, this array holds pointers to virtual-array * control blocks for each component. Unused if not full-image storage. */ jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; #endif } my_main_controller; typedef my_main_controller * my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #ifdef FULL_MAIN_BUFFER_SUPPORTED METHODDEF(void) process_data_buffer_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #endif /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr main = (my_main_ptr) cinfo->main; /* Do nothing in raw-data mode. */ if (cinfo->raw_data_in) return; main->cur_iMCU_row = 0; /* initialize counters */ main->rowgroup_ctr = 0; main->suspended = FALSE; main->pass_mode = pass_mode; /* save mode for use by process_data */ switch (pass_mode) { case JBUF_PASS_THRU: #ifdef FULL_MAIN_BUFFER_SUPPORTED if (main->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif main->pub.process_data = process_data_simple_main; break; #ifdef FULL_MAIN_BUFFER_SUPPORTED case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: if (main->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); main->pub.process_data = process_data_buffer_main; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data. * This routine handles the simple pass-through mode, * where we have only a strip buffer. */ METHODDEF(void) process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ if (main->rowgroup_ctr < DCTSIZE) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ if (main->rowgroup_ctr != DCTSIZE) return; /* Send the completed row to the compressor */ if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (! main->suspended) { (*in_row_ctr)--; main->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (main->suspended) { (*in_row_ctr)++; main->suspended = FALSE; } main->rowgroup_ctr = 0; main->cur_iMCU_row++; } } #ifdef FULL_MAIN_BUFFER_SUPPORTED /* * Process some data. * This routine handles all of the modes that use a full-size buffer. */ METHODDEF(void) process_data_buffer_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci; jpeg_component_info *compptr; boolean writing = (main->pass_mode != JBUF_CRANK_DEST); while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Realign the virtual buffers if at the start of an iMCU row. */ if (main->rowgroup_ctr == 0) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, main->whole_image[ci], main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); } /* In a read pass, pretend we just read some source data. */ if (! writing) { *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; main->rowgroup_ctr = DCTSIZE; } } /* If a write pass, read input data until the current iMCU row is full. */ /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ if (writing) { (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* Return to application if we need more data to fill the iMCU row. */ if (main->rowgroup_ctr < DCTSIZE) return; } /* Emit data, unless this is a sink-only pass. */ if (main->pass_mode != JBUF_SAVE_SOURCE) { if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (! main->suspended) { (*in_row_ctr)--; main->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (main->suspended) { (*in_row_ctr)++; main->suspended = FALSE; } } /* If get here, we are done with this iMCU row. Mark buffer empty. */ main->rowgroup_ctr = 0; main->cur_iMCU_row++; } } #endif /* FULL_MAIN_BUFFER_SUPPORTED */ /* * Initialize main buffer controller. */ GLOBAL(void) jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main; int ci; jpeg_component_info *compptr; main = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_c_main_controller *) main; main->pub.start_pass = start_pass_main; /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) return; /* Create the buffer. It holds downsampled data, so each component * may be of a different size. */ if (need_full_buffer) { #ifdef FULL_MAIN_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component */ /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor) * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED main->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcmarker.c ================================================ /* * jcmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write JPEG datastream markers. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* Private state */ typedef struct { struct jpeg_marker_writer pub; /* public fields */ unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ } my_marker_writer; typedef my_marker_writer * my_marker_ptr; /* * Basic output routines. * * Note that we do not support suspension while writing a marker. * Therefore, an application using suspension must ensure that there is * enough buffer space for the initial markers (typ. 600-700 bytes) before * calling jpeg_start_compress, and enough space to write the trailing EOI * (a few bytes) before calling jpeg_finish_compress. Multipass compression * modes are not supported at all with suspension, so those two are the only * points where markers will be written. */ LOCAL(void) emit_byte (j_compress_ptr cinfo, int val) /* Emit a byte */ { struct jpeg_destination_mgr * dest = cinfo->dest; *(dest->next_output_byte)++ = (JOCTET) val; if (--dest->free_in_buffer == 0) { if (! (*dest->empty_output_buffer) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } } LOCAL(void) emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) /* Emit a marker code */ { emit_byte(cinfo, 0xFF); emit_byte(cinfo, (int) mark); } LOCAL(void) emit_2bytes (j_compress_ptr cinfo, int value) /* Emit a 2-byte integer; these are always MSB first in JPEG files */ { emit_byte(cinfo, (value >> 8) & 0xFF); emit_byte(cinfo, value & 0xFF); } /* * Routines to write specific marker types. */ LOCAL(int) emit_dqt (j_compress_ptr cinfo, int index) /* Emit a DQT marker */ /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ { JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; int prec; int i; if (qtbl == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; for (i = 0; i < DCTSIZE2; i++) { if (qtbl->quantval[i] > 255) prec = 1; } if (! qtbl->sent_table) { emit_marker(cinfo, M_DQT); emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); for (i = 0; i < DCTSIZE2; i++) { /* The table entries must be emitted in zigzag order. */ unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; if (prec) emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval & 0xFF)); } qtbl->sent_table = TRUE; } return prec; } LOCAL(void) emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) /* Emit a DHT marker */ { JHUFF_TBL * htbl; int length, i; if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ } else { htbl = cinfo->dc_huff_tbl_ptrs[index]; } if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); htbl->sent_table = TRUE; } } LOCAL(void) emit_dac (j_compress_ptr cinfo) /* Emit a DAC marker */ /* Since the useful info is so small, we want to emit all the tables in */ /* one DAC marker. Therefore this routine does its own scan of the table. */ { #ifdef C_ARITH_CODING_SUPPORTED char dc_in_use[NUM_ARITH_TBLS]; char ac_in_use[NUM_ARITH_TBLS]; int length, i; jpeg_component_info *compptr; for (i = 0; i < NUM_ARITH_TBLS; i++) dc_in_use[i] = ac_in_use[i] = 0; for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; dc_in_use[compptr->dc_tbl_no] = 1; ac_in_use[compptr->ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) length += dc_in_use[i] + ac_in_use[i]; emit_marker(cinfo, M_DAC); emit_2bytes(cinfo, length*2 + 2); for (i = 0; i < NUM_ARITH_TBLS; i++) { if (dc_in_use[i]) { emit_byte(cinfo, i); emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); } if (ac_in_use[i]) { emit_byte(cinfo, i + 0x10); emit_byte(cinfo, cinfo->arith_ac_K[i]); } } #endif /* C_ARITH_CODING_SUPPORTED */ } LOCAL(void) emit_dri (j_compress_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); } LOCAL(void) emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) /* Emit a SOF marker */ { int ci; jpeg_component_info *compptr; emit_marker(cinfo, code); emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ if ((long) cinfo->image_height > 65535L || (long) cinfo->image_width > 65535L) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); emit_2bytes(cinfo, (int) cinfo->image_height); emit_2bytes(cinfo, (int) cinfo->image_width); emit_byte(cinfo, cinfo->num_components); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { emit_byte(cinfo, compptr->component_id); emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(cinfo, compptr->quant_tbl_no); } } LOCAL(void) emit_sos (j_compress_ptr cinfo) /* Emit a SOS marker */ { int i, td, ta; jpeg_component_info *compptr; emit_marker(cinfo, M_SOS); emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ emit_byte(cinfo, cinfo->comps_in_scan); for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); td = compptr->dc_tbl_no; ta = compptr->ac_tbl_no; if (cinfo->progressive_mode) { /* Progressive mode: only DC or only AC tables are used in one scan; * furthermore, Huffman coding of DC refinement uses no table at all. * We emit 0 for unused field(s); this is recommended by the P&M text * but does not seem to be specified in the standard. */ if (cinfo->Ss == 0) { ta = 0; /* DC scan */ if (cinfo->Ah != 0 && !cinfo->arith_code) td = 0; /* no DC table either */ } else { td = 0; /* AC scan */ } } emit_byte(cinfo, (td << 4) + ta); } emit_byte(cinfo, cinfo->Ss); emit_byte(cinfo, cinfo->Se); emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); } LOCAL(void) emit_jfif_app0 (j_compress_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ { /* * Length of APP0 block (2 bytes) * Block ID (4 bytes - ASCII "JFIF") * Zero byte (1 byte to terminate the ID string) * Version Major, Minor (2 bytes - major first) * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) * Xdpu (2 bytes - dots per unit horizontal) * Ydpu (2 bytes - dots per unit vertical) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ emit_marker(cinfo, M_APP0); emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x49); emit_byte(cinfo, 0x46); emit_byte(cinfo, 0); emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ emit_byte(cinfo, cinfo->JFIF_minor_version); emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ emit_2bytes(cinfo, (int) cinfo->X_density); emit_2bytes(cinfo, (int) cinfo->Y_density); emit_byte(cinfo, 0); /* No thumbnail image */ emit_byte(cinfo, 0); } LOCAL(void) emit_adobe_app14 (j_compress_ptr cinfo) /* Emit an Adobe APP14 marker */ { /* * Length of APP14 block (2 bytes) * Block ID (5 bytes - ASCII "Adobe") * Version Number (2 bytes - currently 100) * Flags0 (2 bytes - currently 0) * Flags1 (2 bytes - currently 0) * Color transform (1 byte) * * Although Adobe TN 5116 mentions Version = 101, all the Adobe files * now in circulation seem to use Version = 100, so that's what we write. * * We write the color transform byte as 1 if the JPEG color space is * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with * whether the encoder performed a transformation, which is pretty useless. */ emit_marker(cinfo, M_APP14); emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ emit_byte(cinfo, 0x64); emit_byte(cinfo, 0x6F); emit_byte(cinfo, 0x62); emit_byte(cinfo, 0x65); emit_2bytes(cinfo, 100); /* Version */ emit_2bytes(cinfo, 0); /* Flags0 */ emit_2bytes(cinfo, 0); /* Flags1 */ switch (cinfo->jpeg_color_space) { case JCS_YCbCr: emit_byte(cinfo, 1); /* Color transform = 1 */ break; case JCS_YCCK: emit_byte(cinfo, 2); /* Color transform = 2 */ break; default: emit_byte(cinfo, 0); /* Color transform = 0 */ break; } } /* * These routines allow writing an arbitrary marker with parameters. * The only intended use is to emit COM or APPn markers after calling * write_file_header and before calling write_frame_header. * Other uses are not guaranteed to produce desirable results. * Counting the parameter bytes properly is the caller's responsibility. */ METHODDEF(void) write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) /* Emit an arbitrary marker header */ { if (datalen > (unsigned int) 65533) /* safety check */ ERREXIT(cinfo, JERR_BAD_LENGTH); emit_marker(cinfo, (JPEG_MARKER) marker); emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ } METHODDEF(void) write_marker_byte (j_compress_ptr cinfo, int val) /* Emit one byte of marker parameters following write_marker_header */ { emit_byte(cinfo, val); } /* * Write datastream header. * This consists of an SOI and optional APPn markers. * We recommend use of the JFIF marker, but not the Adobe marker, * when using YCbCr or grayscale data. The JFIF marker should NOT * be used for any other JPEG colorspace. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after * jpeg_start_compress returns. */ METHODDEF(void) write_file_header (j_compress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; emit_marker(cinfo, M_SOI); /* first the SOI */ /* SOI is defined to reset restart interval to 0 */ marker->last_restart_interval = 0; if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ emit_jfif_app0(cinfo); if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ emit_adobe_app14(cinfo); } /* * Write frame header. * This consists of DQT and SOFn markers. * Note that we do not emit the SOF until we have emitted the DQT(s). * This avoids compatibility problems with incorrect implementations that * try to error-check the quant table numbers as soon as they see the SOF. */ METHODDEF(void) write_frame_header (j_compress_ptr cinfo) { int ci, prec; boolean is_baseline; jpeg_component_info *compptr; /* Emit DQT for each quantization table. * Note that emit_dqt() suppresses any duplicate tables. */ prec = 0; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { prec += emit_dqt(cinfo, compptr->quant_tbl_no); } /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ if (cinfo->arith_code || cinfo->progressive_mode || cinfo->data_precision != 8) { is_baseline = FALSE; } else { is_baseline = TRUE; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) is_baseline = FALSE; } if (prec && is_baseline) { is_baseline = FALSE; /* If it's baseline except for quantizer size, warn the user */ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); } } /* Emit the proper SOF marker */ if (cinfo->arith_code) { emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ } else { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } } /* * Write scan header. * This consists of DHT or DAC markers, optional DRI, and SOS. * Compressed data will be written following the SOS. */ METHODDEF(void) write_scan_header (j_compress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; int i; jpeg_component_info *compptr; if (cinfo->arith_code) { /* Emit arith conditioning info. We may have some duplication * if the file has multiple scans, but it's so small it's hardly * worth worrying about. */ emit_dac(cinfo); } else { /* Emit Huffman tables. * Note that emit_dht() suppresses any duplicate tables. */ for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; if (cinfo->progressive_mode) { /* Progressive mode: only DC or only AC tables are used in one scan */ if (cinfo->Ss == 0) { if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ emit_dht(cinfo, compptr->dc_tbl_no, FALSE); } else { emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } else { /* Sequential mode: need both DC and AC tables */ emit_dht(cinfo, compptr->dc_tbl_no, FALSE); emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } } /* Emit DRI if required --- note that DRI value could change for each scan. * We avoid wasting space with unnecessary DRIs, however. */ if (cinfo->restart_interval != marker->last_restart_interval) { emit_dri(cinfo); marker->last_restart_interval = cinfo->restart_interval; } emit_sos(cinfo); } /* * Write datastream trailer. */ METHODDEF(void) write_file_trailer (j_compress_ptr cinfo) { emit_marker(cinfo, M_EOI); } /* * Write an abbreviated table-specification datastream. * This consists of SOI, DQT and DHT tables, and EOI. * Any table that is defined and not marked sent_table = TRUE will be * emitted. Note that all tables will be marked sent_table = TRUE at exit. */ METHODDEF(void) write_tables_only (j_compress_ptr cinfo) { int i; emit_marker(cinfo, M_SOI); for (i = 0; i < NUM_QUANT_TBLS; i++) { if (cinfo->quant_tbl_ptrs[i] != NULL) (void) emit_dqt(cinfo, i); } if (! cinfo->arith_code) { for (i = 0; i < NUM_HUFF_TBLS; i++) { if (cinfo->dc_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, FALSE); if (cinfo->ac_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, TRUE); } } emit_marker(cinfo, M_EOI); } /* * Initialize the marker writer module. */ GLOBAL(void) jinit_marker_writer (j_compress_ptr cinfo) { my_marker_ptr marker; /* Create the subobject */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_marker_writer)); cinfo->marker = (struct jpeg_marker_writer *) marker; /* Initialize method pointers */ marker->pub.write_file_header = write_file_header; marker->pub.write_frame_header = write_frame_header; marker->pub.write_scan_header = write_scan_header; marker->pub.write_file_trailer = write_file_trailer; marker->pub.write_tables_only = write_tables_only; marker->pub.write_marker_header = write_marker_header; marker->pub.write_marker_byte = write_marker_byte; /* Initialize private state */ marker->last_restart_interval = 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcmaster.c ================================================ /* * jcmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG compressor. * These routines are concerned with parameter validation, initial setup, * and inter-pass control (determining the number of passes and the work * to be done in each pass). */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef enum { main_pass, /* input data, also do first output step */ huff_opt_pass, /* Huffman code optimization pass */ output_pass /* data output pass */ } c_pass_type; typedef struct { struct jpeg_comp_master pub; /* public fields */ c_pass_type pass_type; /* the type of the current pass */ int pass_number; /* # of passes completed */ int total_passes; /* total # of passes needed */ int scan_number; /* current index in scan_info[] */ } my_comp_master; typedef my_comp_master * my_master_ptr; /* * Support routines that do various essential calculations. */ LOCAL(void) initial_setup (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { int ci; jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; /* Sanity check on image dimensions */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0 || cinfo->input_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* Width of an input scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Fill in the correct component_index value; don't rely on application */ compptr->component_index = ci; /* For compression, we never do DCT scaling. */ compptr->DCT_scaled_size = DCTSIZE; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed (this flag isn't actually used for compression) */ compptr->component_needed = TRUE; } /* Compute number of fully interleaved MCU rows (number of times that * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); } #ifdef C_MULTISCAN_FILES_SUPPORTED LOCAL(void) validate_script (j_compress_ptr cinfo) /* Verify that the scan script in cinfo->scan_info[] is valid; also * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. */ { const jpeg_scan_info * scanptr; int scanno, ncomps, ci, coefi, thisi; int Ss, Se, Ah, Al; boolean component_sent[MAX_COMPONENTS]; #ifdef C_PROGRESSIVE_SUPPORTED int * last_bitpos_ptr; int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; /* -1 until that coefficient has been seen; then last Al for it */ #endif if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ scanptr = cinfo->scan_info; if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; last_bitpos_ptr = & last_bitpos[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) *last_bitpos_ptr++ = -1; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { cinfo->progressive_mode = FALSE; for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { /* Validate component indexes */ ncomps = scanptr->comps_in_scan; if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (thisi < 0 || thisi >= cinfo->num_components) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); /* Components must appear in SOF order within each scan */ if (ci > 0 && thisi <= scanptr->component_index[ci-1]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); } /* Validate progression parameters */ Ss = scanptr->Ss; Se = scanptr->Se; Ah = scanptr->Ah; Al = scanptr->Al; if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that * seems wrong: the upper bound ought to depend on data precision. * Perhaps they really meant 0..N+1 for N-bit precision. * Here we allow 0..10 for 8-bit data; Al larger than 10 results in * out-of-range reconstructed DC values during the first DC scan, * which might cause problems for some decoders. */ #if BITS_IN_JSAMPLE == 8 #define MAX_AH_AL 10 #else #define MAX_AH_AL 13 #endif if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { if (ncomps != 1) /* AC scans must be for only one component */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } for (ci = 0; ci < ncomps; ci++) { last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); for (coefi = Ss; coefi <= Se; coefi++) { if (last_bitpos_ptr[coefi] < 0) { /* first scan of this coefficient */ if (Ah != 0) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { /* not first scan */ if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } last_bitpos_ptr[coefi] = Al; } } #endif } else { /* For sequential JPEG, all progression parameters must be these: */ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (component_sent[thisi]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); component_sent[thisi] = TRUE; } } } /* Now verify that everything got sent. */ if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* For progressive mode, we only check that at least some DC data * got sent for each component; the spec does not require that all bits * of all coefficients be transmitted. Would it be wiser to enforce * transmission of all coefficient bits?? */ for (ci = 0; ci < cinfo->num_components; ci++) { if (last_bitpos[ci][0] < 0) ERREXIT(cinfo, JERR_MISSING_DATA); } #endif } else { for (ci = 0; ci < cinfo->num_components; ci++) { if (! component_sent[ci]) ERREXIT(cinfo, JERR_MISSING_DATA); } } } #endif /* C_MULTISCAN_FILES_SUPPORTED */ LOCAL(void) select_scan_parameters (j_compress_ptr cinfo) /* Set up the scan parameters for the current scan */ { int ci; #ifdef C_MULTISCAN_FILES_SUPPORTED if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr) cinfo->master; const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; cinfo->comps_in_scan = scanptr->comps_in_scan; for (ci = 0; ci < scanptr->comps_in_scan; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[scanptr->component_index[ci]]; } cinfo->Ss = scanptr->Ss; cinfo->Se = scanptr->Se; cinfo->Ah = scanptr->Ah; cinfo->Al = scanptr->Al; } else #endif { /* Prepare for single sequential-JPEG scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPS_IN_SCAN); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } cinfo->Ss = 0; cinfo->Se = DCTSIZE2-1; cinfo->Ah = 0; cinfo->Al = 0; } } LOCAL(void) per_scan_setup (j_compress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = DCTSIZE; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); } } /* * Per-pass setup. * This is called at the beginning of each pass. We determine which modules * will be active during this pass and give them appropriate start_pass calls. * We also set is_last_pass to indicate whether any more passes will be * required. */ METHODDEF(void) prepare_for_pass (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; switch (master->pass_type) { case main_pass: /* Initial pass: will collect input data, and do either Huffman * optimization or data output for the first scan. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (! cinfo->raw_data_in) { (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); } (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); (*cinfo->coef->start_pass) (cinfo, (master->total_passes > 1 ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); if (cinfo->optimize_coding) { /* No immediate data output; postpone writing frame/scan headers */ master->pub.call_pass_startup = FALSE; } else { /* Will write frame/scan headers at first jpeg_write_scanlines call */ master->pub.call_pass_startup = TRUE; } break; #ifdef ENTROPY_OPT_SUPPORTED case huff_opt_pass: /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; break; } /* Special case: Huffman DC refinement scans need no Huffman table * and therefore we can skip the optimization pass for them. */ master->pass_type = output_pass; master->pass_number++; /*FALLTHROUGH*/ #endif case output_pass: /* Do a data-output pass. */ /* We need not repeat per-scan setup if prior optimization pass did it. */ if (! cinfo->optimize_coding) { select_scan_parameters(cinfo); per_scan_setup(cinfo); } (*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); /* We emit frame/scan headers now */ if (master->scan_number == 0) (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); master->pub.call_pass_startup = FALSE; break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); } master->pub.is_last_pass = (master->pass_number == master->total_passes-1); /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->total_passes; } } /* * Special start-of-pass hook. * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. * In single-pass processing, we need this hook because we don't want to * write frame/scan headers during jpeg_start_compress; we want to let the * application write COM markers etc. between jpeg_start_compress and the * jpeg_write_scanlines loop. * In multi-pass processing, this routine is not used. */ METHODDEF(void) pass_startup (j_compress_ptr cinfo) { cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); } /* * Finish up at end of pass. */ METHODDEF(void) finish_pass_master (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; /* The entropy coder always needs an end-of-pass call, * either to analyze statistics or to flush its output buffer. */ (*cinfo->entropy->finish_pass) (cinfo); /* Update state for next pass */ switch (master->pass_type) { case main_pass: /* next pass is either output of scan 0 (after optimization) * or output of scan 1 (if no optimization). */ master->pass_type = output_pass; if (! cinfo->optimize_coding) master->scan_number++; break; case huff_opt_pass: /* next pass is always output of current scan */ master->pass_type = output_pass; break; case output_pass: /* next pass is either optimization or output of next scan */ if (cinfo->optimize_coding) master->pass_type = huff_opt_pass; master->scan_number++; break; } master->pass_number++; } /* * Initialize master compression control. */ GLOBAL(void) jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_comp_master)); cinfo->master = (struct jpeg_comp_master *) master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; /* Validate parameters, determine derived values */ initial_setup(cinfo); if (cinfo->scan_info != NULL) { #ifdef C_MULTISCAN_FILES_SUPPORTED validate_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { cinfo->progressive_mode = FALSE; cinfo->num_scans = 1; } if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ /* Initialize my private state */ if (transcode_only) { /* no main pass in transcoding */ if (cinfo->optimize_coding) master->pass_type = huff_opt_pass; else master->pass_type = output_pass; } else { /* for normal compression, first pass is always this type: */ master->pass_type = main_pass; } master->scan_number = 0; master->pass_number = 0; if (cinfo->optimize_coding) master->total_passes = cinfo->num_scans * 2; else master->total_passes = cinfo->num_scans; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcomapi.c ================================================ /* * jcomapi.c * * Copyright (C) 1994-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface routines that are used for both * compression and decompression. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Abort processing of a JPEG compression or decompression operation, * but don't destroy the object itself. * * For this, we merely clean up all the nonpermanent memory pools. * Note that temp files (virtual arrays) are not allowed to belong to * the permanent pool, so we will be able to close all temp files here. * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL(void) jpeg_abort (j_common_ptr cinfo) { int pool; /* Do nothing if called on a not-initialized or destroyed JPEG object. */ if (cinfo->mem == NULL) return; /* Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { (*cinfo->mem->free_pool) (cinfo, pool); } /* Reset overall state for possible reuse of object */ if (cinfo->is_decompressor) { cinfo->global_state = DSTATE_START; /* Try to keep application from accessing now-deleted marker list. * A bit kludgy to do it here, but this is the most central place. */ ((j_decompress_ptr) cinfo)->marker_list = NULL; } else { cinfo->global_state = CSTATE_START; } } /* * Destruction of a JPEG object. * * Everything gets deallocated except the master jpeg_compress_struct itself * and the error manager struct. Both of these are supplied by the application * and must be freed, if necessary, by the application. (Often they are on * the stack and so don't need to be freed anyway.) * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL(void) jpeg_destroy (j_common_ptr cinfo) { /* We need only tell the memory manager to release everything. */ /* NB: mem pointer is NULL if memory mgr failed to initialize. */ if (cinfo->mem != NULL) (*cinfo->mem->self_destruct) (cinfo); cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ cinfo->global_state = 0; /* mark it destroyed */ } /* * Convenience routines for allocating quantization and Huffman tables. * (Would jutils.c be a more reasonable place to put these?) */ GLOBAL(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo) { JQUANT_TBL *tbl; tbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } GLOBAL(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo) { JHUFF_TBL *tbl; tbl = (JHUFF_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jconfig.h ================================================ /* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define BMP_SUPPORTED /* BMP image file format */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcparam.c ================================================ /* * jcparam.c * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains optional default-setting code for the JPEG compressor. * Applications do not have to use this file, but those that don't use it * must know a lot more about the innards of the JPEG code. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Quantization table setup routines */ GLOBAL(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries * are limited to 1..255 for JPEG baseline compatibility. */ { JQUANT_TBL ** qtblptr; int i; long temp; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); for (i = 0; i < DCTSIZE2; i++) { temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; /* limit the values to the valid range */ if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if (force_baseline && temp > 255L) temp = 255L; /* limit to baseline range if requested */ (*qtblptr)->quantval[i] = (UINT16) temp; } /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*qtblptr)->sent_table = FALSE; } GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables * and a straight percentage-scaling quality scale. In most cases it's better * to use jpeg_set_quality (below); this entry point is provided for * applications that insist on a linear percentage scaling. */ { /* These are the sample quantization tables given in JPEG spec section K.1. * The spec says that the values given produce "good" quality, and * when divided by 2, "very good" quality. */ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 }; static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, scale_factor, force_baseline); } GLOBAL(int) jpeg_quality_scaling (int quality) /* Convert a user-specified quality rating to a percentage scaling factor * for an underlying quantization table, using our recommended scaling curve. * The input 'quality' factor should be 0 (terrible) to 100 (very good). */ { /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; /* The basic table is used as-is (scaling 100) for a quality of 50. * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table * to make all the table entries 1 (hence, minimum quantization loss). * Qualities 1..50 are converted to scaling percentage 5000/Q. */ if (quality < 50) quality = 5000 / quality; else quality = 200 - quality*2; return quality; } GLOBAL(void) jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables * would use the preceding three routines directly. */ { /* Convert user 0-100 rating to percentage scaling */ quality = jpeg_quality_scaling(quality); /* Set up standard quality tables */ jpeg_set_linear_quality(cinfo, quality, force_baseline); } /* * Huffman table setup routines */ LOCAL(void) add_huff_table (j_compress_ptr cinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) /* Define a Huffman table */ { int nsymbols, len; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); /* Copy the number-of-symbols-of-each-code-length counts */ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); /* Validate the counts. We do this here mainly so we can copy the right * number of symbols from the val[] array, without risking marching off * the end of memory. jchuff.c will do a more thorough test later. */ nsymbols = 0; for (len = 1; len <= 16; len++) nsymbols += bits[len]; if (nsymbols < 1 || nsymbols > 256) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*htblptr)->sent_table = FALSE; } LOCAL(void) std_huff_tables (j_compress_ptr cinfo) /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ /* IMPORTANT: these are only valid for 8-bit data precision! */ { static const UINT8 bits_dc_luminance[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], bits_ac_luminance, val_ac_luminance); add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], bits_dc_chrominance, val_dc_chrominance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], bits_ac_chrominance, val_ac_chrominance); } /* * Default parameter setup for compression. * * Applications that don't choose to use this routine must do their * own setup of all these parameters. Alternately, you can call this * to establish defaults and then alter parameters selectively. This * is the recommended approach since, if we add any new parameters, * your code will still work (they'll be set to reasonable defaults). */ GLOBAL(void) jpeg_set_defaults (j_compress_ptr cinfo) { int i; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Allocate comp_info array large enough for maximum component count. * Array is made permanent in case application wants to compress * multiple images at same param settings. */ if (cinfo->comp_info == NULL) cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, MAX_COMPONENTS * SIZEOF(jpeg_component_info)); /* Initialize everything not dependent on the color space */ cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); /* Set up two Huffman tables */ std_huff_tables(cinfo); /* Initialize default arithmetic coding conditioning */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } /* Default is no multiple-scan output */ cinfo->scan_info = NULL; cinfo->num_scans = 0; /* Expect normal source image, not raw downsampled data */ cinfo->raw_data_in = FALSE; /* Use Huffman coding, not arithmetic coding, by default */ cinfo->arith_code = FALSE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; /* The standard Huffman tables are only valid for 8-bit data precision. * If the precision is higher, force optimization on so that usable * tables will be computed. This test can be removed if default tables * are supplied that are valid for the desired precision. */ if (cinfo->data_precision > 8) cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; /* No input smoothing */ cinfo->smoothing_factor = 0; /* DCT algorithm preference */ cinfo->dct_method = JDCT_DEFAULT; /* No restart markers */ cinfo->restart_interval = 0; cinfo->restart_in_rows = 0; /* Fill in default JFIF marker parameters. Note that whether the marker * will actually be written is determined by jpeg_set_colorspace. * * By default, the library emits JFIF version code 1.01. * An application that wants to emit JFIF 1.02 extension markers should set * JFIF_minor_version to 2. We could probably get away with just defaulting * to 1.02, but there may still be some decoders in use that will complain * about that; saying 1.01 should minimize compatibility problems. */ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ cinfo->JFIF_minor_version = 1; cinfo->density_unit = 0; /* Pixel size is unknown by default */ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; /* Choose JPEG colorspace based on input space, set defaults accordingly */ jpeg_default_colorspace(cinfo); } /* * Select an appropriate JPEG colorspace for in_color_space. */ GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo) { switch (cinfo->in_color_space) { case JCS_GRAYSCALE: jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); break; case JCS_RGB: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_CMYK: jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ break; case JCS_YCCK: jpeg_set_colorspace(cinfo, JCS_YCCK); break; case JCS_UNKNOWN: jpeg_set_colorspace(cinfo, JCS_UNKNOWN); break; default: ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } } /* * Set the JPEG colorspace, and choose colorspace-dependent default values. */ GLOBAL(void) jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) { jpeg_component_info * compptr; int ci; #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ (compptr = &cinfo->comp_info[index], \ compptr->component_id = (id), \ compptr->h_samp_factor = (hsamp), \ compptr->v_samp_factor = (vsamp), \ compptr->quant_tbl_no = (quant), \ compptr->dc_tbl_no = (dctbl), \ compptr->ac_tbl_no = (actbl) ) /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* For all colorspaces, we use Q and Huff tables 0 for luminance components, * tables 1 for chrominance components. */ cinfo->jpeg_color_space = colorspace; cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ SET_COMP(0, 1, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ /* We default to 2x2 subsamples of chrominance */ SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ cinfo->num_components = 4; SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); break; case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); SET_COMP(3, 4, 2,2, 0, 0,0); break; case JCS_UNKNOWN: cinfo->num_components = cinfo->input_components; if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); for (ci = 0; ci < cinfo->num_components; ci++) { SET_COMP(ci, ci, 1,1, 0, 0,0); } break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } } #ifdef C_PROGRESSIVE_SUPPORTED LOCAL(jpeg_scan_info *) fill_a_scan (jpeg_scan_info * scanptr, int ci, int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for specified component */ { scanptr->comps_in_scan = 1; scanptr->component_index[0] = ci; scanptr->Ss = Ss; scanptr->Se = Se; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; return scanptr; } LOCAL(jpeg_scan_info *) fill_scans (jpeg_scan_info * scanptr, int ncomps, int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for each component */ { int ci; for (ci = 0; ci < ncomps; ci++) { scanptr->comps_in_scan = 1; scanptr->component_index[0] = ci; scanptr->Ss = Ss; scanptr->Se = Se; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; } return scanptr; } LOCAL(jpeg_scan_info *) fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) /* Support routine: generate interleaved DC scan if possible, else N scans */ { int ci; if (ncomps <= MAX_COMPS_IN_SCAN) { /* Single interleaved DC scan */ scanptr->comps_in_scan = ncomps; for (ci = 0; ci < ncomps; ci++) scanptr->component_index[ci] = ci; scanptr->Ss = scanptr->Se = 0; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; } else { /* Noninterleaved DC scan for each component */ scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); } return scanptr; } /* * Create a recommended progressive-JPEG script. * cinfo->num_components and cinfo->jpeg_color_space must be correct. */ GLOBAL(void) jpeg_simple_progression (j_compress_ptr cinfo) { int ncomps = cinfo->num_components; int nscans; jpeg_scan_info * scanptr; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Figure space needed for script. Calculation must match code below! */ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { /* Custom script for YCbCr color images. */ nscans = 10; } else { /* All-purpose script for other color spaces. */ if (ncomps > MAX_COMPS_IN_SCAN) nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ else nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ } /* Allocate space for script. * We need to put it in the permanent pool in case the application performs * multiple compressions without changing the settings. To avoid a memory * leak if jpeg_simple_progression is called repeatedly for the same JPEG * object, we try to re-use previously allocated space, and we allocate * enough space to handle YCbCr even if initially asked for grayscale. */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { cinfo->script_space_size = MAX(nscans, 10); cinfo->script_space = (jpeg_scan_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, cinfo->script_space_size * SIZEOF(jpeg_scan_info)); } scanptr = cinfo->script_space; cinfo->scan_info = scanptr; cinfo->num_scans = nscans; if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { /* Custom script for YCbCr color images. */ /* Initial DC scan */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); /* Initial AC scan: get some luma data out in a hurry */ scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); /* Chroma data is too small to be worth expending many scans on */ scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); /* Complete spectral selection for luma AC */ scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); /* Refine next bit of luma AC */ scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); /* Finish DC successive approximation */ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); /* Finish AC successive approximation */ scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); /* Luma bottom bit comes last since it's usually largest scan */ scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); } else { /* All-purpose script for other color spaces. */ /* Successive approximation first pass */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); /* Successive approximation second pass */ scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); /* Successive approximation final pass */ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); } } #endif /* C_PROGRESSIVE_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcphuff.c ================================================ /* * jcphuff.c * * Copyright (C) 1995-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines for progressive JPEG. * * We do not support output suspension in this module, since the library * currently does not allow multiple-scan files to be written with output * suspension. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jchuff.h" /* Declarations shared with jchuff.c */ #ifdef C_PROGRESSIVE_SUPPORTED /* Expanded entropy encoder object for progressive Huffman encoding. */ typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ /* Mode flag: TRUE for optimization, FALSE for actual data output */ boolean gather_statistics; /* Bit-level coding status. * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. */ JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ /* Coding status for DC components */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ /* Coding status for AC components */ int ac_tbl_no; /* the table number of the single component */ unsigned int EOBRUN; /* run length of EOBs */ unsigned int BE; /* # of buffered correction bits before MCU */ char * bit_buffer; /* buffer for correction bits (1 per char) */ /* packing correction bits tightly would save some space but cost time... */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ /* Pointers to derived tables (these workspaces have image lifespan). * Since any one scan codes only DC or only AC, we only need one set * of tables, not one for DC and one for AC. */ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; /* Statistics tables for optimization; again, one set is enough */ long * count_ptrs[NUM_HUFF_TBLS]; } phuff_entropy_encoder; typedef phuff_entropy_encoder * phuff_entropy_ptr; /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit * buffer can hold. Larger sizes may slightly improve compression, but * 1000 is already well into the realm of overkill. * The minimum safe size is 64 bits. */ #define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. * We assume that int right shift is unsigned if INT32 right shift is, * which should be safe. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ ((ishift_temp = (x)) < 0 ? \ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* Forward declarations */ METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); /* * Initialize for a Huffman-compressed scan using progressive JPEG. */ METHODDEF(void) start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; boolean is_DC_band; int ci, tbl; jpeg_component_info * compptr; entropy->cinfo = cinfo; entropy->gather_statistics = gather_statistics; is_DC_band = (cinfo->Ss == 0); /* We assume jcmaster.c already validated the scan parameters. */ /* Select execution routines */ if (cinfo->Ah == 0) { if (is_DC_band) entropy->pub.encode_mcu = encode_mcu_DC_first; else entropy->pub.encode_mcu = encode_mcu_AC_first; } else { if (is_DC_band) entropy->pub.encode_mcu = encode_mcu_DC_refine; else { entropy->pub.encode_mcu = encode_mcu_AC_refine; /* AC refinement needs a correction bit buffer */ if (entropy->bit_buffer == NULL) entropy->bit_buffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, MAX_CORR_BITS * SIZEOF(char)); } } if (gather_statistics) entropy->pub.finish_pass = finish_pass_gather_phuff; else entropy->pub.finish_pass = finish_pass_phuff; /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 * for AC coefficients. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Initialize DC predictions to 0 */ entropy->last_dc_val[ci] = 0; /* Get table index */ if (is_DC_band) { if (cinfo->Ah != 0) /* DC refinement needs no table */ continue; tbl = compptr->dc_tbl_no; } else { entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; } if (gather_statistics) { /* Check for invalid table index */ /* (make_c_derived_tbl does this in the other path) */ if (tbl < 0 || tbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); /* Allocate and zero the statistics tables */ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ if (entropy->count_ptrs[tbl] == NULL) entropy->count_ptrs[tbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); } else { /* Compute derived values for Huffman table */ /* We may do this more than once for a table, but it's not expensive */ jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, & entropy->derived_tbls[tbl]); } } /* Initialize AC stuff */ entropy->EOBRUN = 0; entropy->BE = 0; /* Initialize bit buffer to empty */ entropy->put_buffer = 0; entropy->put_bits = 0; /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } /* Outputting bytes to the file. * NB: these must be called only when actually outputting, * that is, entropy->gather_statistics == FALSE. */ /* Emit a byte */ #define emit_byte(entropy,val) \ { *(entropy)->next_output_byte++ = (JOCTET) (val); \ if (--(entropy)->free_in_buffer == 0) \ dump_buffer(entropy); } LOCAL(void) dump_buffer (phuff_entropy_ptr entropy) /* Empty the output buffer; we do not support suspension in this module. */ { struct jpeg_destination_mgr * dest = entropy->cinfo->dest; if (! (*dest->empty_output_buffer) (entropy->cinfo)) ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); /* After a successful buffer dump, must reset buffer pointers */ entropy->next_output_byte = dest->next_output_byte; entropy->free_in_buffer = dest->free_in_buffer; } /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in put_buffer * between calls, so 24 bits are sufficient. */ INLINE LOCAL(void) emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) /* Emit some bits, unless we are in gather mode */ { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = (INT32) code; register int put_bits = entropy->put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); if (entropy->gather_statistics) return; /* do nothing if we're only getting stats */ put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte(entropy, c); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte(entropy, 0); } put_buffer <<= 8; put_bits -= 8; } entropy->put_buffer = put_buffer; /* update variables */ entropy->put_bits = put_bits; } LOCAL(void) flush_bits (phuff_entropy_ptr entropy) { emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ entropy->put_buffer = 0; /* and reset bit-buffer to empty */ entropy->put_bits = 0; } /* * Emit (or just count) a Huffman symbol. */ INLINE LOCAL(void) emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) { if (entropy->gather_statistics) entropy->count_ptrs[tbl_no][symbol]++; else { c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); } } /* * Emit bits from a correction bit buffer. */ LOCAL(void) emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, unsigned int nbits) { if (entropy->gather_statistics) return; /* no real work */ while (nbits > 0) { emit_bits(entropy, (unsigned int) (*bufstart), 1); bufstart++; nbits--; } } /* * Emit any pending EOBRUN symbol. */ LOCAL(void) emit_eobrun (phuff_entropy_ptr entropy) { register int temp, nbits; if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ temp = entropy->EOBRUN; nbits = 0; while ((temp >>= 1)) nbits++; /* safety check: shouldn't happen given limited correction-bit buffer */ if (nbits > 14) ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); if (nbits) emit_bits(entropy, entropy->EOBRUN, nbits); entropy->EOBRUN = 0; /* Emit any buffered correction bits */ emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); entropy->BE = 0; } } /* * Emit a restart marker & resynchronize predictions. */ LOCAL(void) emit_restart (phuff_entropy_ptr entropy, int restart_num) { int ci; emit_eobrun(entropy); if (! entropy->gather_statistics) { flush_bits(entropy); emit_byte(entropy, 0xFF); emit_byte(entropy, JPEG_RST0 + restart_num); } if (entropy->cinfo->Ss == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) entropy->last_dc_val[ci] = 0; } else { /* Re-initialize all AC-related fields to 0 */ entropy->EOBRUN = 0; entropy->BE = 0; } } /* * MCU encoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; register int temp, temp2; register int nbits; int blkn, ci; int Al = cinfo->Al; JBLOCKROW block; jpeg_component_info * compptr; ISHIFT_TEMPS entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart(entropy, entropy->next_restart_num); /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Compute the DC value after the required point transform by Al. * This is simply an arithmetic right shift. */ temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); /* DC differences are figured on the point-transformed values. */ temp = temp2 - entropy->last_dc_val[ci]; entropy->last_dc_val[ci] = temp2; /* Encode the DC coefficient difference per section G.1.2.1 */ temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > MAX_COEF_BITS+1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit the Huffman-coded symbol for the number of bits */ emit_symbol(entropy, compptr->dc_tbl_no, nbits); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ emit_bits(entropy, (unsigned int) temp2, nbits); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; register int temp, temp2; register int nbits; register int r, k; int Se = cinfo->Se; int Al = cinfo->Al; JBLOCKROW block; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart(entropy, entropy->next_restart_num); /* Encode the MCU data block */ block = MCU_data[0]; /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ r = 0; /* r = run length of zeros */ for (k = cinfo->Ss; k <= Se; k++) { if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { r++; continue; } /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value; so the code is * interwoven with finding the abs value (temp) and output bits (temp2). */ if (temp < 0) { temp = -temp; /* temp is abs value of input */ temp >>= Al; /* apply the point transform */ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ temp2 = ~temp; } else { temp >>= Al; /* apply the point transform */ temp2 = temp; } /* Watch out for case that nonzero coef is zero after point transform */ if (temp == 0) { r++; continue; } /* Emit any pending EOBRUN */ if (entropy->EOBRUN > 0) emit_eobrun(entropy); /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit Huffman symbol for run length / number of bits */ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ emit_bits(entropy, (unsigned int) temp2, nbits); r = 0; /* reset zero run length */ } if (r > 0) { /* If there are trailing zeroes, */ entropy->EOBRUN++; /* count an EOB */ if (entropy->EOBRUN == 0x7FFF) emit_eobrun(entropy); /* force it out to avoid overflow */ } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, although the spec * is not very clear on the point. */ METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; register int temp; int blkn; int Al = cinfo->Al; JBLOCKROW block; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart(entropy, entropy->next_restart_num); /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; /* We simply emit the Al'th bit of the DC coefficient value. */ temp = (*block)[0]; emit_bits(entropy, (unsigned int) (temp >> Al), 1); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for AC successive approximation refinement scan. */ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; register int temp; register int r, k; int EOB; char *BR_buffer; unsigned int BR; int Se = cinfo->Se; int Al = cinfo->Al; JBLOCKROW block; int absvalues[DCTSIZE2]; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart(entropy, entropy->next_restart_num); /* Encode the MCU data block */ block = MCU_data[0]; /* It is convenient to make a pre-pass to determine the transformed * coefficients' absolute values and the EOB position. */ EOB = 0; for (k = cinfo->Ss; k <= Se; k++) { temp = (*block)[jpeg_natural_order[k]]; /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value. */ if (temp < 0) temp = -temp; /* temp is abs value of input */ temp >>= Al; /* apply the point transform */ absvalues[k] = temp; /* save abs value for main pass */ if (temp == 1) EOB = k; /* EOB = index of last newly-nonzero coef */ } /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ r = 0; /* r = run length of zeros */ BR = 0; /* BR = count of buffered bits added now */ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ for (k = cinfo->Ss; k <= Se; k++) { if ((temp = absvalues[k]) == 0) { r++; continue; } /* Emit any required ZRLs, but not if they can be folded into EOB */ while (r > 15 && k <= EOB) { /* emit any pending EOBRUN and the BE correction bits */ emit_eobrun(entropy); /* Emit ZRL */ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); r -= 16; /* Emit buffered correction bits that must be associated with ZRL */ emit_buffered_bits(entropy, BR_buffer, BR); BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ BR = 0; } /* If the coef was previously nonzero, it only needs a correction bit. * NOTE: a straight translation of the spec's figure G.7 would suggest * that we also need to test r > 15. But if r > 15, we can only get here * if k > EOB, which implies that this coefficient is not 1. */ if (temp > 1) { /* The correction bit is the next bit of the absolute value. */ BR_buffer[BR++] = (char) (temp & 1); continue; } /* Emit any pending EOBRUN and the BE correction bits */ emit_eobrun(entropy); /* Count/emit Huffman symbol for run length / number of bits */ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); /* Emit output bit for newly-nonzero coef */ temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; emit_bits(entropy, (unsigned int) temp, 1); /* Emit buffered correction bits that must be associated with this code */ emit_buffered_bits(entropy, BR_buffer, BR); BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ BR = 0; r = 0; /* reset zero run length */ } if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ entropy->EOBRUN++; /* count an EOB */ entropy->BE += BR; /* concat my correction bits to older ones */ /* We force out the EOB if we risk either: * 1. overflow of the EOB counter; * 2. overflow of the correction bit buffer during the next MCU. */ if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) emit_eobrun(entropy); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * Finish up at the end of a Huffman-compressed progressive scan. */ METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Flush out any buffered data */ emit_eobrun(entropy); flush_bits(entropy); cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; } /* * Finish up a statistics-gathering pass and create the new Huffman tables. */ METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; boolean is_DC_band; int ci, tbl; jpeg_component_info * compptr; JHUFF_TBL **htblptr; boolean did[NUM_HUFF_TBLS]; /* Flush out buffered data (all we care about is counting the EOB symbol) */ emit_eobrun(entropy); is_DC_band = (cinfo->Ss == 0); /* It's important not to apply jpeg_gen_optimal_table more than once * per table, because it clobbers the input frequency counts! */ MEMZERO(did, SIZEOF(did)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (is_DC_band) { if (cinfo->Ah != 0) /* DC refinement needs no table */ continue; tbl = compptr->dc_tbl_no; } else { tbl = compptr->ac_tbl_no; } if (! did[tbl]) { if (is_DC_band) htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; else htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); did[tbl] = TRUE; } } } /* * Module initialization routine for progressive Huffman entropy encoding. */ GLOBAL(void) jinit_phuff_encoder (j_compress_ptr cinfo) { phuff_entropy_ptr entropy; int i; entropy = (phuff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(phuff_entropy_encoder)); cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; entropy->pub.start_pass = start_pass_phuff; /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->derived_tbls[i] = NULL; entropy->count_ptrs[i] = NULL; } entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ } #endif /* C_PROGRESSIVE_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcprepct.c ================================================ /* * jcprepct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the compression preprocessing controller. * This controller manages the color conversion, downsampling, * and edge expansion steps. * * Most of the complexity here is associated with buffering input rows * as required by the downsampler. See the comments at the head of * jcsample.c for the downsampler's needs. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* At present, jcsample.c can request context rows only for smoothing. * In the future, we might also need context rows for CCIR601 sampling * or other more-complex downsampling procedures. The code to support * context rows should be compiled only if needed. */ #ifdef INPUT_SMOOTHING_SUPPORTED #define CONTEXT_ROWS_SUPPORTED #endif /* * For the simple (no-context-row) case, we just need to buffer one * row group's worth of pixels for the downsampling step. At the bottom of * the image, we pad to a full row group by replicating the last pixel row. * The downsampler's last output row is then replicated if needed to pad * out to a full iMCU row. * * When providing context rows, we must buffer three row groups' worth of * pixels. Three row groups are physically allocated, but the row pointer * arrays are made five row groups high, with the extra pointers above and * below "wrapping around" to point to the last and first real row groups. * This allows the downsampler to access the proper context rows. * At the top and bottom of the image, we create dummy context rows by * copying the first or last real pixel row. This copying could be avoided * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the * trouble on the compression side. */ /* Private buffer controller object */ typedef struct { struct jpeg_c_prep_controller pub; /* public fields */ /* Downsampling input buffer. This buffer holds color-converted data * until we have enough to do a downsample step. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; JDIMENSION rows_to_go; /* counts rows remaining in source image */ int next_buf_row; /* index of next row to store in color_buf */ #ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ int this_row_group; /* starting row index of group to process */ int next_buf_stop; /* downsample when we reach this index */ #endif } my_prep_controller; typedef my_prep_controller * my_prep_ptr; /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; if (pass_mode != JBUF_PASS_THRU) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); /* Initialize total-height counter for detecting bottom of image */ prep->rows_to_go = cinfo->image_height; /* Mark the conversion buffer empty */ prep->next_buf_row = 0; #ifdef CONTEXT_ROWS_SUPPORTED /* Preset additional state variables for context mode. * These aren't used in non-context mode, so we needn't test which mode. */ prep->this_row_group = 0; /* Set next_buf_stop to stop after two row groups have been read in. */ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; #endif } /* * Expand an image vertically from height input_rows to height output_rows, * by duplicating the bottom row. */ LOCAL(void) expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { jcopy_sample_rows(image_data, input_rows-1, image_data, row, 1, num_cols); } } /* * Process some data in the simple no-context case. * * Preprocessor output data is counted in "row groups". A row group * is defined to be v_samp_factor sample rows of each component. * Downsampling will produce this much data from each max_v_samp_factor * input rows. */ METHODDEF(void) pre_process_data (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; JDIMENSION inrows; jpeg_component_info * compptr; while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->next_buf_row, numrows); *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; /* If at bottom of image, pad to fill the conversion buffer. */ if (prep->rows_to_go == 0 && prep->next_buf_row < cinfo->max_v_samp_factor) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->next_buf_row, cinfo->max_v_samp_factor); } prep->next_buf_row = cinfo->max_v_samp_factor; } /* If we've filled the conversion buffer, empty it. */ if (prep->next_buf_row == cinfo->max_v_samp_factor) { (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) 0, output_buf, *out_row_group_ctr); prep->next_buf_row = 0; (*out_row_group_ctr)++; } /* If at bottom of image, pad the output to a full iMCU height. * Note we assume the caller is providing a one-iMCU-height output buffer! */ if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE, (int) (*out_row_group_ctr * compptr->v_samp_factor), (int) (out_row_groups_avail * compptr->v_samp_factor)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ } } } #ifdef CONTEXT_ROWS_SUPPORTED /* * Process some data in the context case. */ METHODDEF(void) pre_process_context (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; int buf_height = cinfo->max_v_samp_factor * 3; JDIMENSION inrows; while (*out_row_group_ctr < out_row_groups_avail) { if (*in_row_ctr < in_rows_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = prep->next_buf_stop - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->next_buf_row, numrows); /* Pad at top of image, if first time through */ if (prep->rows_to_go == cinfo->image_height) { for (ci = 0; ci < cinfo->num_components; ci++) { int row; for (row = 1; row <= cinfo->max_v_samp_factor; row++) { jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci], -row, 1, cinfo->image_width); } } } *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; } else { /* Return for more data, unless we are at the bottom of the image. */ if (prep->rows_to_go != 0) break; /* When at bottom of image, pad to fill the conversion buffer. */ if (prep->next_buf_row < prep->next_buf_stop) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->next_buf_row, prep->next_buf_stop); } prep->next_buf_row = prep->next_buf_stop; } } /* If we've gotten enough data, downsample a row group. */ if (prep->next_buf_row == prep->next_buf_stop) { (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) prep->this_row_group, output_buf, *out_row_group_ctr); (*out_row_group_ctr)++; /* Advance pointers with wraparound as necessary. */ prep->this_row_group += cinfo->max_v_samp_factor; if (prep->this_row_group >= buf_height) prep->this_row_group = 0; if (prep->next_buf_row >= buf_height) prep->next_buf_row = 0; prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; } } } /* * Create the wrapped-around downsampling input buffer needed for context mode. */ LOCAL(void) create_context_buffer (j_compress_ptr cinfo) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int rgroup_height = cinfo->max_v_samp_factor; int ci, i; jpeg_component_info * compptr; JSAMPARRAY true_buffer, fake_buffer; /* Grab enough space for fake row pointers for all the components; * we need five row groups' worth of pointers for each component. */ fake_buffer = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (cinfo->num_components * 5 * rgroup_height) * SIZEOF(JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Allocate the actual buffer space (3 row groups) for this component. * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ true_buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) (3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ MEMCOPY(fake_buffer + rgroup_height, true_buffer, 3 * rgroup_height * SIZEOF(JSAMPROW)); /* Fill in the above and below wraparound pointers */ for (i = 0; i < rgroup_height; i++) { fake_buffer[i] = true_buffer[2 * rgroup_height + i]; fake_buffer[4 * rgroup_height + i] = true_buffer[i]; } prep->color_buf[ci] = fake_buffer + rgroup_height; fake_buffer += 5 * rgroup_height; /* point to space for next component */ } } #endif /* CONTEXT_ROWS_SUPPORTED */ /* * Initialize preprocessing controller. */ GLOBAL(void) jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_prep_ptr prep; int ci; jpeg_component_info * compptr; if (need_full_buffer) /* safety check */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); prep = (my_prep_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_prep_controller)); cinfo->prep = (struct jpeg_c_prep_controller *) prep; prep->pub.start_pass = start_pass_prep; /* Allocate the color conversion buffer. * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ if (cinfo->downsample->need_context_rows) { /* Set up to provide context rows */ #ifdef CONTEXT_ROWS_SUPPORTED prep->pub.pre_process_data = pre_process_context; create_context_buffer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* No context, just make it tall enough for one row group */ prep->pub.pre_process_data = pre_process_data; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jcsample.c ================================================ /* * jcsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains downsampling routines. * * Downsampling input data is counted in "row groups". A row group * is defined to be max_v_samp_factor pixel rows of each component, * from which the downsampler produces v_samp_factor sample rows. * A single row group is processed in each call to the downsampler module. * * The downsampler is responsible for edge-expansion of its output data * to fill an integral number of DCT blocks horizontally. The source buffer * may be modified if it is helpful for this purpose (the source buffer is * allocated wide enough to correspond to the desired output width). * The caller (the prep controller) is responsible for vertical padding. * * The downsampler may request "context rows" by setting need_context_rows * during startup. In this case, the input arrays will contain at least * one row group's worth of pixels above and below the passed-in data; * the caller will create dummy rows at image top and bottom by replicating * the first or last real pixel row. * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. * * The downsampling algorithm used here is a simple average of the source * pixels covered by the output pixel. The hi-falutin sampling literature * refers to this as a "box filter". In general the characteristics of a box * filter are not very good, but for the specific cases we normally use (1:1 * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not * nearly so bad. If you intend to use other sampling ratios, you'd be well * advised to improve this code. * * A simple input-smoothing capability is provided. This is mainly intended * for cleaning up color-dithered GIF input files (if you find it inadequate, * we suggest using an external filtering program such as pnmconvol). When * enabled, each input pixel P is replaced by a weighted sum of itself and its * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, * where SF = (smoothing_factor / 1024). * Currently, smoothing is only supported for 2h2v sampling factors. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Pointer to routine to downsample a single component */ typedef JMETHOD(void, downsample1_ptr, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data)); /* Private subobject */ typedef struct { struct jpeg_downsampler pub; /* public fields */ /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; /* * Initialize for a downsampling pass. */ METHODDEF(void) start_pass_downsample (j_compress_ptr cinfo) { /* no work for now */ } /* * Expand a component horizontally from width input_cols to width output_cols, * by duplicating the rightmost samples. */ LOCAL(void) expand_right_edge (JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) { register JSAMPROW ptr; register JSAMPLE pixval; register int count; int row; int numcols = (int) (output_cols - input_cols); if (numcols > 0) { for (row = 0; row < num_rows; row++) { ptr = image_data[row] + input_cols; pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ for (count = numcols; count > 0; count--) *ptr++ = pixval; } } } /* * Do downsampling for a whole row group (all components). * * In this version we simply downsample each component independently. */ METHODDEF(void) sep_downsample (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int ci; jpeg_component_info * compptr; JSAMPARRAY in_ptr, out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { in_ptr = input_buf[ci] + in_row_index; out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } /* * Downsample pixel values of a single component. * One row group is processed per call. * This version handles arbitrary integral sampling ratios, without smoothing. * Note that this version is not actually used for customary sampling ratios. */ METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; JSAMPROW inptr, outptr; INT32 outvalue; h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; numpix = h_expand * v_expand; numpix2 = numpix/2; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * h_expand); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { outvalue = 0; for (v = 0; v < v_expand; v++) { inptr = input_data[inrow+v] + outcol_h; for (h = 0; h < h_expand; h++) { outvalue += (INT32) GETJSAMPLE(*inptr++); } } *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * without smoothing. */ METHODDEF(void) fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { /* Copy the data */ jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, compptr->width_in_blocks * DCTSIZE); } /* * Downsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 1:1 vertical, * without smoothing. * * A note about the "bias" calculations: when rounding fractional values to * integer, we do not want to always round 0.5 up to the next integer. * If we did that, we'd introduce a noticeable bias towards larger values. * Instead, this code is arranged so that 0.5 will be rounded up or down at * alternate pixel locations (a simple ordered dither pattern). */ METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } } } /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * without smoothing. */ METHODDEF(void) h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr0, inptr1, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } inrow += 2; } } #ifdef INPUT_SMOOTHING_SUPPORTED /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * with smoothing. One row of context is required. */ METHODDEF(void) h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols * 2); /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four * smoothed values. Each of the four member pixels contributes a fraction * (1-8*SF) to its own smoothed image and a fraction SF to each of the three * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final * output. The four corner-adjacent neighbor pixels contribute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; above_ptr = input_data[inrow-1]; below_ptr = input_data[inrow+2]; /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); inrow += 2; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * with smoothing. One row of context is required. */ METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols); /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; above_ptr = input_data[outrow-1]; below_ptr = input_data[outrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); } } #endif /* INPUT_SMOOTHING_SUPPORTED */ /* * Module initialization routine for downsampling. * Note that we must select a routine for each component. */ GLOBAL(void) jinit_downsampler (j_compress_ptr cinfo) { my_downsample_ptr downsample; int ci; jpeg_component_info * compptr; boolean smoothok = TRUE; downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *) downsample; downsample->pub.start_pass = start_pass_downsample; downsample->pub.downsample = sep_downsample; downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = fullsize_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = h2v2_downsample; } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor && !smoothok) TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jctrans.c ================================================ /* * jctrans.c * * Copyright (C) 1995-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains library routines for transcoding compression, * that is, writing raw DCT coefficient arrays to an output JPEG file. * The routines in jcapimin.c will also be needed by a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(void) transencode_master_selection JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); LOCAL(void) transencode_coef_controller JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); /* * Compression initialization for writing raw-coefficient data. * Before calling this, all parameters and a data destination must be set up. * Call jpeg_finish_compress() to actually write the data. * * The number of passed virtual arrays must match cinfo->num_components. * Note that the virtual arrays need not be filled or even realized at * the time write_coefficients is called; indeed, if the virtual arrays * were requested from this compression object's memory manager, they * typically will be realized during this routine and filled afterwards. */ GLOBAL(void) jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Mark all tables to be written */ jpeg_suppress_tables(cinfo, FALSE); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ transencode_master_selection(cinfo, coef_arrays); /* Wait for jpeg_finish_compress() call */ cinfo->next_scanline = 0; /* so jpeg_write_marker works */ cinfo->global_state = CSTATE_WRCOEFS; } /* * Initialize the compression object with default parameters, * then copy from the source object all parameters needed for lossless * transcoding. Parameters that can be varied without loss (such as * scan script and Huffman optimization) are left in their default states. */ GLOBAL(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, j_compress_ptr dstinfo) { JQUANT_TBL ** qtblptr; jpeg_component_info *incomp, *outcomp; JQUANT_TBL *c_quant, *slot_quant; int tblno, ci, coefi; /* Safety check to ensure start_compress not called yet. */ if (dstinfo->global_state != CSTATE_START) ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); /* Copy fundamental image dimensions */ dstinfo->image_width = srcinfo->image_width; dstinfo->image_height = srcinfo->image_height; dstinfo->input_components = srcinfo->num_components; dstinfo->in_color_space = srcinfo->jpeg_color_space; /* Initialize all parameters to default values */ jpeg_set_defaults(dstinfo); /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. * Fix it to get the right header markers for the image colorspace. */ jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); dstinfo->data_precision = srcinfo->data_precision; dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; /* Copy the source's quantization tables. */ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); MEMCOPY((*qtblptr)->quantval, srcinfo->quant_tbl_ptrs[tblno]->quantval, SIZEOF((*qtblptr)->quantval)); (*qtblptr)->sent_table = FALSE; } } /* Copy the source's per-component info. * Note we assume jpeg_set_defaults has allocated the dest comp_info array. */ dstinfo->num_components = srcinfo->num_components; if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, MAX_COMPONENTS); for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; ci < dstinfo->num_components; ci++, incomp++, outcomp++) { outcomp->component_id = incomp->component_id; outcomp->h_samp_factor = incomp->h_samp_factor; outcomp->v_samp_factor = incomp->v_samp_factor; outcomp->quant_tbl_no = incomp->quant_tbl_no; /* Make sure saved quantization table for component matches the qtable * slot. If not, the input file re-used this qtable slot. * IJG encoder currently cannot duplicate this. */ tblno = outcomp->quant_tbl_no; if (tblno < 0 || tblno >= NUM_QUANT_TBLS || srcinfo->quant_tbl_ptrs[tblno] == NULL) ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); slot_quant = srcinfo->quant_tbl_ptrs[tblno]; c_quant = incomp->quant_table; if (c_quant != NULL) { for (coefi = 0; coefi < DCTSIZE2; coefi++) { if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); } } /* Note: we do not copy the source's Huffman table assignments; * instead we rely on jpeg_set_colorspace to have made a suitable choice. */ } /* Also copy JFIF version and resolution information, if available. * Strictly speaking this isn't "critical" info, but it's nearly * always appropriate to copy it if available. In particular, * if the application chooses to copy JFIF 1.02 extension markers from * the source file, we need to copy the version to make sure we don't * emit a file that has 1.02 extensions but a claimed version of 1.01. * We will *not*, however, copy version info from mislabeled "2.01" files. */ if (srcinfo->saw_JFIF_marker) { if (srcinfo->JFIF_major_version == 1) { dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; } dstinfo->density_unit = srcinfo->density_unit; dstinfo->X_density = srcinfo->X_density; dstinfo->Y_density = srcinfo->Y_density; } } /* * Master selection of compression modules for transcoding. * This substitutes for jcinit.c's initialization of the full compressor. */ LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { /* Although we don't actually use input_components for transcoding, * jcmaster.c's initial_setup will complain if input_components is 0. */ cinfo->input_components = 1; /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED jinit_phuff_encoder(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else jinit_huff_encoder(cinfo); } /* We need a special coefficient buffer controller. */ transencode_coef_controller(cinfo, coef_arrays); jinit_marker_writer(cinfo); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Write the datastream header (SOI, JFIF) immediately. * Frame and scan headers are postponed till later. * This lets application insert special markers after the SOI. */ (*cinfo->marker->write_file_header) (cinfo); } /* * The rest of this file is a special implementation of the coefficient * buffer controller. This is similar to jccoefct.c, but it handles only * output from presupplied virtual arrays. Furthermore, we generate any * dummy padding blocks on-the-fly rather than expecting them to be present * in the arrays. */ /* Private buffer controller object */ typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* Virtual block array for each component. */ jvirt_barray_ptr * whole_image; /* Workspace for constructing dummy blocks at right/bottom edges. */ JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->mcu_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; if (pass_mode != JBUF_CRANK_DEST) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->iMCU_row_num = 0; start_iMCU_row(cinfo); } /* * Process some data. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the scan. * The data is obtained from the virtual arrays and fed to the entropy coder. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf is ignored; it is likely to be a NULL pointer. */ METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, blockcnt; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yindex+yoffset < compptr->last_row_height) { /* Fill in pointers to real blocks in this row */ buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < blockcnt; xindex++) MCU_buffer[blkn++] = buffer_ptr++; } else { /* At bottom of image, need a whole row of dummy blocks */ xindex = 0; } /* Fill in any dummy blocks needed in this row. * Dummy blocks are filled in the same way as in jccoefct.c: * all zeroes in the AC entries, DC entries equal to previous * block's DC value. The init routine has already zeroed the * AC entries, so we need only set the DC entries correctly. */ for (; xindex < compptr->MCU_width; xindex++) { MCU_buffer[blkn] = coef->dummy_buffer[blkn]; MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; blkn++; } } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } /* * Initialize coefficient buffer controller. * * Each passed coefficient array must be the right size for that * coefficient: width_in_blocks wide and height_in_blocks high, * with unitheight at least v_samp_factor. */ LOCAL(void) transencode_coef_controller (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { my_coef_ptr coef; JBLOCKROW buffer; int i; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->dummy_buffer[i] = buffer + i; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdapimin.c ================================================ /* * jdapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the decompression half * of the JPEG library. These are the "minimum" API routines that may be * needed in either the normal full-decompression case or the * transcoding-only case. * * Most of the routines intended to be called directly by an application * are in this file or in jdapistd.c. But also see jcomapi.c for routines * shared by compression and decompression, and jdtrans.c for the transcoding * case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG decompression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) { int i; /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_decompress_struct)) ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set * client_data, so we have to save and restore those fields. * Note: if application hasn't set client_data, tools like Purify may * complain here. */ { struct jpeg_error_mgr * err = cinfo->err; void * client_data = cinfo->client_data; /* ignore Purify complaint here */ MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); cinfo->err = err; cinfo->client_data = client_data; } cinfo->is_decompressor = TRUE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->src = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } /* Initialize marker processor so application can override methods * for COM, APPn markers before calling jpeg_read_header. */ cinfo->marker_list = NULL; jinit_marker_reader(cinfo); /* And initialize the overall input controller. */ jinit_input_controller(cinfo); /* OK, I'm ready */ cinfo->global_state = DSTATE_START; } /* * Destruction of a JPEG decompression object */ GLOBAL(void) jpeg_destroy_decompress (j_decompress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Abort processing of a JPEG decompression operation, * but don't destroy the object itself. */ GLOBAL(void) jpeg_abort_decompress (j_decompress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } /* * Set default decompression parameters. */ LOCAL(void) default_decompress_parms (j_decompress_ptr cinfo) { /* Guess the input colorspace, and set output colorspace accordingly. */ /* (Wish JPEG committee had provided a real way to specify this...) */ /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE; break; case 3: if (cinfo->saw_JFIF_marker) { cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ } else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_RGB; break; case 1: cinfo->jpeg_color_space = JCS_YCbCr; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ break; } } else { /* Saw no special markers, try to guess from the component IDs */ int cid0 = cinfo->comp_info[0].component_id; int cid1 = cinfo->comp_info[1].component_id; int cid2 = cinfo->comp_info[2].component_id; if (cid0 == 1 && cid1 == 2 && cid2 == 3) cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ else if (cid0 == 82 && cid1 == 71 && cid2 == 66) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } } /* Always guess RGB is proper output colorspace. */ cinfo->out_color_space = JCS_RGB; break; case 4: if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_CMYK; break; case 2: cinfo->jpeg_color_space = JCS_YCCK; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ break; } } else { /* No special markers, assume straight CMYK. */ cinfo->jpeg_color_space = JCS_CMYK; } cinfo->out_color_space = JCS_CMYK; break; default: cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->out_color_space = JCS_UNKNOWN; break; } /* Set defaults for other decompression parameters. */ cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; cinfo->output_gamma = 1.0; cinfo->buffered_image = FALSE; cinfo->raw_data_out = FALSE; cinfo->dct_method = JDCT_DEFAULT; cinfo->do_fancy_upsampling = TRUE; cinfo->do_block_smoothing = TRUE; cinfo->quantize_colors = FALSE; /* We set these in case application only sets quantize_colors. */ cinfo->dither_mode = JDITHER_FS; #ifdef QUANT_2PASS_SUPPORTED cinfo->two_pass_quantize = TRUE; #else cinfo->two_pass_quantize = FALSE; #endif cinfo->desired_number_of_colors = 256; cinfo->colormap = NULL; /* Initialize for no mode change in buffered-image mode. */ cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } /* * Decompression startup: read start of JPEG datastream to see what's there. * Need only initialize JPEG object and supply a data source before calling. * * This routine will read as far as the first SOS marker (ie, actual start of * compressed data), and will save all tables and parameters in the JPEG * object. It will also initialize the decompression parameters to default * values, and finally return JPEG_HEADER_OK. On return, the application may * adjust the decompression parameters and then call jpeg_start_decompress. * (Or, if the application only wanted to determine the image parameters, * the data need not be decompressed. In that case, call jpeg_abort or * jpeg_destroy to release any temporary space.) * If an abbreviated (tables only) datastream is presented, the routine will * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then * re-use the JPEG object to read the abbreviated image datastream(s). * It is unnecessary (but OK) to call jpeg_abort in this case. * The JPEG_SUSPENDED return code only occurs if the data source module * requests suspension of the decompressor. In this case the application * should load more source data and then re-call jpeg_read_header to resume * processing. * If a non-suspending data source is used and require_image is TRUE, then the * return code need not be inspected since only JPEG_HEADER_OK is possible. * * This routine is now just a front end to jpeg_consume_input, with some * extra error checking. */ GLOBAL(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) { int retcode; if (cinfo->global_state != DSTATE_START && cinfo->global_state != DSTATE_INHEADER) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); retcode = jpeg_consume_input(cinfo); switch (retcode) { case JPEG_REACHED_SOS: retcode = JPEG_HEADER_OK; break; case JPEG_REACHED_EOI: if (require_image) /* Complain if application wanted an image */ ERREXIT(cinfo, JERR_NO_IMAGE); /* Reset to start state; it would be safer to require the application to * call jpeg_abort, but we can't change it now for compatibility reasons. * A side effect is to free any temporary memory (there shouldn't be any). */ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ retcode = JPEG_HEADER_TABLES_ONLY; break; case JPEG_SUSPENDED: /* no work */ break; } return retcode; } /* * Consume data in advance of what the decompressor requires. * This can be called at any time once the decompressor object has * been created and a data source has been set up. * * This routine is essentially a state machine that handles a couple * of critical state-transition actions, namely initial setup and * transition from header scanning to ready-for-start_decompress. * All the actual input is done via the input controller's consume_input * method. */ GLOBAL(int) jpeg_consume_input (j_decompress_ptr cinfo) { int retcode = JPEG_SUSPENDED; /* NB: every possible DSTATE value should be listed in this switch */ switch (cinfo->global_state) { case DSTATE_START: /* Start-of-datastream actions: reset appropriate modules */ (*cinfo->inputctl->reset_input_controller) (cinfo); /* Initialize application's data source module */ (*cinfo->src->init_source) (cinfo); cinfo->global_state = DSTATE_INHEADER; /*FALLTHROUGH*/ case DSTATE_INHEADER: retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ /* Set up default parameters based on header data */ default_decompress_parms(cinfo); /* Set global state: ready for start_decompress */ cinfo->global_state = DSTATE_READY; } break; case DSTATE_READY: /* Can't advance past first SOS until start_decompress is called */ retcode = JPEG_REACHED_SOS; break; case DSTATE_PRELOAD: case DSTATE_PRESCAN: case DSTATE_SCANNING: case DSTATE_RAW_OK: case DSTATE_BUFIMAGE: case DSTATE_BUFPOST: case DSTATE_STOPPING: retcode = (*cinfo->inputctl->consume_input) (cinfo); break; default: ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } return retcode; } /* * Have we finished reading the input file? */ GLOBAL(boolean) jpeg_input_complete (j_decompress_ptr cinfo) { /* Check for valid jpeg object */ if (cinfo->global_state < DSTATE_START || cinfo->global_state > DSTATE_STOPPING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->eoi_reached; } /* * Is there more than one scan? */ GLOBAL(boolean) jpeg_has_multiple_scans (j_decompress_ptr cinfo) { /* Only valid after jpeg_read_header completes */ if (cinfo->global_state < DSTATE_READY || cinfo->global_state > DSTATE_STOPPING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->has_multiple_scans; } /* * Finish JPEG decompression. * * This will normally just verify the file trailer and release temp storage. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { /* Terminate final pass of non-buffered mode */ if (cinfo->output_scanline < cinfo->output_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_output_pass) (cinfo); cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state == DSTATE_BUFIMAGE) { /* Finishing after a buffered-image operation */ cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state != DSTATE_STOPPING) { /* STOPPING = repeat call after a suspension, anything else is error */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } /* Read until EOI */ while (! cinfo->inputctl->eoi_reached) { if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) return FALSE; /* Suspend, come back later */ } /* Do final cleanup */ (*cinfo->src->term_source) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); return TRUE; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdapistd.c ================================================ /* * jdapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the decompression half * of the JPEG library. These are the "standard" API routines that are * used in the normal full-decompression case. They are not used by a * transcoding-only application. Note that if an application links in * jpeg_start_decompress, it will end up linking in the entire decompressor. * We thus must separate this file from jdapimin.c to avoid linking the * whole decompression library into a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); /* * Decompression initialization. * jpeg_read_header must be completed before calling this. * * If a multipass operating mode was selected, this will do all but the * last pass, and thus may take a great deal of time. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_start_decompress (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize master control, select active modules */ jinit_master_decompress(cinfo); if (cinfo->buffered_image) { /* No more work here; expecting jpeg_start_output next */ cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; } cinfo->global_state = DSTATE_PRELOAD; } if (cinfo->global_state == DSTATE_PRELOAD) { /* If file has multiple scans, absorb them all into the coef buffer */ if (cinfo->inputctl->has_multiple_scans) { #ifdef D_MULTISCAN_FILES_SUPPORTED for (;;) { int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return FALSE; if (retcode == JPEG_REACHED_EOI) break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { /* jdmaster underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } } #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* D_MULTISCAN_FILES_SUPPORTED */ } cinfo->output_scan_number = cinfo->input_scan_number; } else if (cinfo->global_state != DSTATE_PRESCAN) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any dummy output passes, and set up for the final pass */ return output_pass_setup(cinfo); } /* * Set up for an output pass, and perform any dummy pass(es) needed. * Common subroutine for jpeg_start_decompress and jpeg_start_output. * Entry: global_state = DSTATE_PRESCAN only if previously suspended. * Exit: If done, returns TRUE and sets global_state for proper output mode. * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. */ LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo) { if (cinfo->global_state != DSTATE_PRESCAN) { /* First call: do pass setup */ (*cinfo->master->prepare_for_output_pass) (cinfo); cinfo->output_scanline = 0; cinfo->global_state = DSTATE_PRESCAN; } /* Loop over any required dummy passes */ while (cinfo->master->is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED /* Crank through the dummy pass */ while (cinfo->output_scanline < cinfo->output_height) { JDIMENSION last_scanline; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Process some data */ last_scanline = cinfo->output_scanline; (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, &cinfo->output_scanline, (JDIMENSION) 0); if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } /* Finish up dummy pass, and set up for another one */ (*cinfo->master->finish_output_pass) (cinfo); (*cinfo->master->prepare_for_output_pass) (cinfo); cinfo->output_scanline = 0; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } /* Ready for application to drive output pass through * jpeg_read_scanlines or jpeg_read_raw_data. */ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; return TRUE; } /* * Read some scanlines of data from the JPEG decompressor. * * The return value will be the number of lines actually read. * This may be less than the number requested in several cases, * including bottom of image, data source suspension, and operating * modes that emit multiple scanlines at a time. * * Note: we warn about excess calls to jpeg_read_scanlines() since * this likely signals an application programmer error. However, * an oversize buffer (max_lines > scanlines remaining) is not an error. */ GLOBAL(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines) { JDIMENSION row_ctr; if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Process some data */ row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; } /* * Alternate entry point to read raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != DSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Verify that at least one iMCU row can be returned. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; if (max_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ if (! (*cinfo->coef->decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ cinfo->output_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } /* Additional entry points for buffered-image mode. */ #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Initialize for an output pass in buffered-image mode. */ GLOBAL(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number) { if (cinfo->global_state != DSTATE_BUFIMAGE && cinfo->global_state != DSTATE_PRESCAN) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Limit scan number to valid range */ if (scan_number <= 0) scan_number = 1; if (cinfo->inputctl->eoi_reached && scan_number > cinfo->input_scan_number) scan_number = cinfo->input_scan_number; cinfo->output_scan_number = scan_number; /* Perform any dummy output passes, and set up for the real pass */ return output_pass_setup(cinfo); } /* * Finish up after an output pass in buffered-image mode. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_finish_output (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { /* Terminate this pass. */ /* We do not require the whole pass to have been completed. */ (*cinfo->master->finish_output_pass) (cinfo); cinfo->global_state = DSTATE_BUFPOST; } else if (cinfo->global_state != DSTATE_BUFPOST) { /* BUFPOST = repeat call after a suspension, anything else is error */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } /* Read markers looking for SOS or EOI */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) return FALSE; /* Suspend, come back later */ } cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdatadst.c ================================================ /* * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of * emitting JPEG data to a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data destination object for stdio output */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ FILE * outfile; /* target stream */ JOCTET * buffer; /* start of buffer */ } my_destination_mgr; typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ METHODDEF(void) init_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } /* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines). The * application should resume compression after it has made more room in the * output buffer. Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */ METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != (size_t) OUTPUT_BUF_SIZE) ERREXIT(cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; /* Write any data remaining in the buffer */ if (datacount > 0) { if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) ERREXIT(cinfo, JERR_FILE_WRITE); } fflush(dest->outfile); /* Make sure we wrote the output file OK */ if (ferror(dest->outfile)) ERREXIT(cinfo, JERR_FILE_WRITE); } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing compression. */ GLOBAL(void) jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) { my_dest_ptr dest; /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outfile = outfile; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdatasrc.c ================================================ /* * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ FILE * infile; /* source stream */ JOCTET * buffer; /* start of buffer */ boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF(void) init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; /* We reset the empty-input-file flag for each image, * but we don't clear the input buffer. * This is correct behavior for reading a series of images from one source. */ src->start_of_file = TRUE; } /* * Fill the input buffer --- called whenever buffer is emptied. * * In typical applications, this should read fresh data into the buffer * (ignoring the current state of next_input_byte & bytes_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been reloaded. It is not necessary to * fill the buffer entirely, only to obtain at least one more byte. * * There is no such thing as an EOF return. If the end of the file has been * reached, the routine has a choice of ERREXIT() or inserting fake data into * the buffer. In most cases, generating a warning message and inserting a * fake EOI marker is the best course of action --- this will allow the * decompressor to output however much of the image is there. However, * the resulting error message is misleading if the real problem is an empty * input file, so we handle that case specially. * * In applications that need to be able to suspend compression due to input * not being available yet, a FALSE return indicates that no more data can be * obtained right now, but more may be forthcoming later. In this situation, * the decompressor will return to its caller (with an indication of the * number of scanlines it has read, if any). The application should resume * decompression after it has loaded more data into the input buffer. Note * that there are substantial restrictions on the use of suspension --- see * the documentation. * * When suspending, the decompressor will back up to a convenient restart point * (typically the start of the current MCU). next_input_byte & bytes_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point must be rescanned after resumption, so move it to * the front of the buffer rather than discarding it. */ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); if (nbytes <= 0) { if (src->start_of_file) /* Treat empty input file as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY); WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; src->start_of_file = FALSE; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data * is not granted the right to give a suspension return. If the skip extends * beyond the data currently in the buffer, the buffer can be marked empty so * that the next read will cause a fill_input_buffer call that can suspend. * Arranging for additional bytes to be discarded before reloading the input * buffer is the application writer's problem. */ METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) fill_input_buffer(cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for input from a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing decompression. */ GLOBAL(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) { my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->infile = infile; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdcoefct.c ================================================ /* * jdcoefct.c * * Copyright (C) 1994-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for decompression. * This controller is the top level of the JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * In buffered-image mode, this controller is the interface between * input-oriented processing and output-oriented processing. * Also, the input side (only) is used when reading a file for transcoding. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED #endif /* Private buffer controller object */ typedef struct { struct jpeg_d_coef_controller pub; /* public fields */ /* These variables keep track of the current location of the input side. */ /* cinfo->input_iMCU_row is also used for this. */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* The output side's location is represented by cinfo->output_iMCU_row. */ /* In single-pass modes, it's sufficient to buffer just one MCU. * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, * and let the entropy decoder write into that workspace each time. * (On 80x86, the workspace is FAR even though it's not really very big; * this is to keep the module interfaces unchanged when a large coefficient * buffer is necessary.) * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays; it is used only by the input side. */ JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; #ifdef D_MULTISCAN_FILES_SUPPORTED /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; #endif #ifdef BLOCK_SMOOTHING_SUPPORTED /* When doing block smoothing, we latch coefficient Al values here */ int * coef_bits_latch; #define SAVED_COEFS 6 /* we save coef_bits[0..5] */ #endif } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(int) decompress_onepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #ifdef D_MULTISCAN_FILES_SUPPORTED METHODDEF(int) decompress_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); METHODDEF(int) decompress_smooth_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif LOCAL(void) start_iMCU_row (j_decompress_ptr cinfo) /* Reset within-iMCU-row counters for a new row (input side) */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for an input processing pass. */ METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { cinfo->input_iMCU_row = 0; start_iMCU_row(cinfo); } /* * Initialize for an output processing pass. */ METHODDEF(void) start_output_pass (j_decompress_ptr cinfo) { #ifdef BLOCK_SMOOTHING_SUPPORTED my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* If multipass, check to see whether to use block smoothing on this pass */ if (coef->pub.coef_arrays != NULL) { if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) coef->pub.decompress_data = decompress_smooth_data; else coef->pub.decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; } /* * Decompress and return some data in the single-pass case. * Always attempts to emit one fully interleaved MCU row ("iMCU" row). * Input and output must run in lockstep since we have only a one-MCU buffer. * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. * * NB: output_buf contains a plane for each component in image, * which we index according to the component's SOF position. */ METHODDEF(int) decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, useful_width; JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ jzero_far((void FAR *) coef->MCU_buffer[0], (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkn gets * incremented past them!). Note the inner loop relies on having * allocated the MCU_buffer[] blocks sequentially. */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { blkn += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + yoffset * compptr->DCT_scaled_size; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (cinfo->input_iMCU_row < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { output_col = start_col; for (xindex = 0; xindex < useful_width; xindex++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn+xindex], output_ptr, output_col); output_col += compptr->DCT_scaled_size; } } blkn += compptr->MCU_width; output_ptr += compptr->DCT_scaled_size; } } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ cinfo->output_iMCU_row++; if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } /* * Dummy consume-input routine for single-pass operation. */ METHODDEF(int) dummy_consume_data (j_decompress_ptr cinfo) { return JPEG_SUSPENDED; /* Always indicate nothing was done */ } #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Consume input data and store it in the full-image coefficient buffer. * We read as much as one fully interleaved MCU row ("iMCU" row) per call, * ie, v_samp_factor block rows for each component in the scan. * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. */ METHODDEF(int) consume_data (j_decompress_ptr cinfo) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], cinfo->input_iMCU_row * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Note: entropy decoder expects buffer to be zeroed, * but this is handled automatically by the memory manager * because we requested a pre-zeroed array. */ } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { coef->MCU_buffer[blkn++] = buffer_ptr++; } } } /* Try to fetch the MCU. */ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } /* * Decompress and return some data in the multi-pass case. * Always attempts to emit one fully interleaved MCU row ("iMCU" row). * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. * * NB: output_buf contains a plane for each component in image. */ METHODDEF(int) decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num; int ci, block_row, block_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr; JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || (cinfo->input_scan_number == cinfo->output_scan_number && cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; } /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) continue; /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], cinfo->output_iMCU_row * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); /* Count non-dummy DCT block rows in this iMCU row. */ if (cinfo->output_iMCU_row < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here; it is input-side-dependent! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; output_col = 0; for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, output_ptr, output_col); buffer_ptr++; output_col += compptr->DCT_scaled_size; } output_ptr += compptr->DCT_scaled_size; } } if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ #ifdef BLOCK_SMOOTHING_SUPPORTED /* * This code applies interblock smoothing as described by section K.8 * of the JPEG standard: the first 5 AC coefficients are estimated from * the DC values of a DCT block and its 8 neighboring blocks. * We apply smoothing only for progressive JPEG decoding, and only if * the coefficients it can estimate are not yet known to full precision. */ /* Natural-order array positions of the first 5 zigzag-order coefficients */ #define Q01_POS 1 #define Q10_POS 8 #define Q20_POS 16 #define Q11_POS 9 #define Q02_POS 2 /* * Determine whether block smoothing is applicable and safe. * We also latch the current states of the coef_bits[] entries for the * AC coefficients; otherwise, if the input side of the decompressor * advances into a new scan, we might think the coefficients are known * more accurately than they really are. */ LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; boolean smoothing_useful = FALSE; int ci, coefi; jpeg_component_info *compptr; JQUANT_TBL * qtable; int * coef_bits; int * coef_bits_latch; if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) return FALSE; /* Allocate latch area if not already done */ if (coef->coef_bits_latch == NULL) coef->coef_bits_latch = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * (SAVED_COEFS * SIZEOF(int))); coef_bits_latch = coef->coef_bits_latch; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* All components' quantization values must already be latched. */ if ((qtable = compptr->quant_table) == NULL) return FALSE; /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ if (qtable->quantval[0] == 0 || qtable->quantval[Q01_POS] == 0 || qtable->quantval[Q10_POS] == 0 || qtable->quantval[Q20_POS] == 0 || qtable->quantval[Q11_POS] == 0 || qtable->quantval[Q02_POS] == 0) return FALSE; /* DC values must be at least partly known for all components. */ coef_bits = cinfo->coef_bits[ci]; if (coef_bits[0] < 0) return FALSE; /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ for (coefi = 1; coefi <= 5; coefi++) { coef_bits_latch[coefi] = coef_bits[coefi]; if (coef_bits[coefi] != 0) smoothing_useful = TRUE; } coef_bits_latch += SAVED_COEFS; } return smoothing_useful; } /* * Variant of decompress_data for use when doing block smoothing. */ METHODDEF(int) decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num, last_block_column; int ci, block_row, block_rows, access_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr, prev_block_row, next_block_row; JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; boolean first_row, last_row; JBLOCK workspace; int *coef_bits; JQUANT_TBL *quanttbl; INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; int Al, pred; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { if (cinfo->input_scan_number == cinfo->output_scan_number) { /* If input is working on current scan, we ordinarily want it to * have completed the current row. But if input scan is DC, * we want it to keep one row ahead so that next block row's DC * values are up to date. */ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) break; } if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; } /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) continue; /* Count non-dummy DCT block rows in this iMCU row. */ if (cinfo->output_iMCU_row < last_iMCU_row) { block_rows = compptr->v_samp_factor; access_rows = block_rows * 2; /* this and next iMCU row */ last_row = FALSE; } else { /* NB: can't use last_row_height here; it is input-side-dependent! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; access_rows = block_rows; /* this iMCU row only */ last_row = TRUE; } /* Align the virtual buffer for this component. */ if (cinfo->output_iMCU_row > 0) { access_rows += compptr->v_samp_factor; /* prior iMCU row too */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, (JDIMENSION) access_rows, FALSE); buffer += compptr->v_samp_factor; /* point to current iMCU row */ first_row = FALSE; } else { buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); first_row = TRUE; } /* Fetch component-dependent info */ coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); quanttbl = compptr->quant_table; Q00 = quanttbl->quantval[0]; Q01 = quanttbl->quantval[Q01_POS]; Q10 = quanttbl->quantval[Q10_POS]; Q20 = quanttbl->quantval[Q20_POS]; Q11 = quanttbl->quantval[Q11_POS]; Q02 = quanttbl->quantval[Q02_POS]; inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; if (first_row && block_row == 0) prev_block_row = buffer_ptr; else prev_block_row = buffer[block_row-1]; if (last_row && block_row == block_rows-1) next_block_row = buffer_ptr; else next_block_row = buffer[block_row+1]; /* We fetch the surrounding DC values using a sliding-register approach. * Initialize all nine here so as to do the right thing on narrow pics. */ DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; DC7 = DC8 = DC9 = (int) next_block_row[0][0]; output_col = 0; last_block_column = compptr->width_in_blocks - 1; for (block_num = 0; block_num <= last_block_column; block_num++) { /* Fetch current DCT block into workspace so we can modify it. */ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); /* Update DC values */ if (block_num < last_block_column) { DC3 = (int) prev_block_row[1][0]; DC6 = (int) buffer_ptr[1][0]; DC9 = (int) next_block_row[1][0]; } /* Compute coefficient estimates per K.8. * An estimate is applied only if coefficient is still zero, * and is not known to be fully accurate. */ /* AC01 */ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { num = 36 * Q00 * (DC4 - DC6); if (num >= 0) { pred = (int) (((Q01<<7) + num) / (Q01<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q10<<7) + num) / (Q10<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q20<<7) + num) / (Q20<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q11<<7) + num) / (Q11<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q02<<7) + num) / (Q02<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; } output_ptr += compptr->DCT_scaled_size; } } if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } #endif /* BLOCK_SMOOTHING_SUPPORTED */ /* * Initialize coefficient buffer controller. */ GLOBAL(void) jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; #ifdef BLOCK_SMOOTHING_SUPPORTED coef->coef_bits_latch = NULL; #endif /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ /* Note we ask for a pre-zeroed array. */ int ci, access_rows; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ if (cinfo->progressive_mode) access_rows *= 3; #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } coef->pub.consume_data = consume_data; coef->pub.decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data = dummy_consume_data; coef->pub.decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdcolor.c ================================================ /* * jdcolor.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains output colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; /**************** YCbCr -> RGB conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * R = Y + 1.40200 * Cr * G = Y - 0.34414 * Cb - 0.71414 * Cr * B = Y + 1.77200 * Cb * where Cb and Cr represent the incoming values less CENTERJSAMPLE. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * Notice that Y, being an integral input, does not contribute any fraction * so it need not participate in the rounding. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; INT32 x; SHIFT_TEMPS cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ cconvert->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); /* Cb=>B value is nearest int to 1.77200 * x */ cconvert->Cb_b_tab[i] = (int) RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); /* Cr=>G value is scaled-up -0.71414 * x */ cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; /* Cb=>G value is scaled-up -0.34414 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; } } /* * Convert some rows of samples to the output colorspace. * * Note that we change from noninterleaved, one-plane-per-component format * to interleaved-pixel format. The output buffer is therefore three times * as wide as the input buffer. * A starting row offset is provided only for the input buffer. The caller * can easily adjust the passed output_buf value to accommodate any row * offset required on that side. */ METHODDEF(void) ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Range-limiting is essential due to noise introduced by DCT losses. */ outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; outptr[RGB_GREEN] = range_limit[y + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; outptr += RGB_PIXELSIZE; } } } /**************** Cases other than YCbCr -> RGB **************/ /* * Color conversion for no colorspace change: just copy the data, * converting from separate-planes to interleaved representation. */ METHODDEF(void) null_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW inptr, outptr; register JDIMENSION count; register int num_components = cinfo->num_components; JDIMENSION num_cols = cinfo->output_width; int ci; while (--num_rows >= 0) { for (ci = 0; ci < num_components; ci++) { inptr = input_buf[ci][input_row]; outptr = output_buf[0] + ci; for (count = num_cols; count > 0; count--) { *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ outptr += num_components; } } input_row++; output_buf++; } } /* * Color conversion for grayscale: just copy the data. * This also works for YCbCr -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF(void) grayscale_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, num_rows, cinfo->output_width); } /* * Convert grayscale to RGB: just duplicate the graylevel three times. * This is provided to support applications that don't want to cope * with grayscale as a separate case. */ METHODDEF(void) gray_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW inptr, outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr = input_buf[0][input_row++]; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { /* We can dispense with GETJSAMPLE() here */ outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; outptr += RGB_PIXELSIZE; } } } /* * Adobe-style YCCK->CMYK conversion. * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same * conversion as above, while passing K (black) unchanged. * We assume build_ycc_rgb_table has been called. */ METHODDEF(void) ycck_cmyk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; inptr3 = input_buf[3][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Range-limiting is essential due to noise introduced by DCT losses. */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 4; } } } /* * Empty method for start_pass. */ METHODDEF(void) start_pass_dcolor (j_decompress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for output colorspace conversion. */ GLOBAL(void) jinit_color_deconverter (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; cconvert->pub.start_pass = start_pass_dcolor; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->num_components < 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; } /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: cinfo->out_color_components = RGB_PIXELSIZE; if (cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { cconvert->pub.color_convert = gray_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { cconvert->pub.color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_CMYK) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; cconvert->pub.color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; } if (cinfo->quantize_colors) cinfo->output_components = 1; /* single colormapped output component */ else cinfo->output_components = cinfo->out_color_components; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdct.h ================================================ /* * jdct.h * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file contains common declarations for the forward and * inverse DCT modules. These declarations are private to the DCT managers * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. * The individual DCT algorithms are kept in separate files to ease * machine-dependent tuning (e.g., assembly coding). */ /* * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; * the DCT is to be performed in-place in that buffer. Type DCTELEM is int * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT * implementations use an array of type FAST_FLOAT, instead.) * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some * work in floating-point ones. * Quantization of the output coefficients is done by jcdctmgr.c. */ #if BITS_IN_JSAMPLE == 8 typedef int DCTELEM; /* 16 or 32 bits is fine */ #else typedef INT32 DCTELEM; /* must have 32 bits */ #endif typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); /* * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer * to an output sample array. The routine must dequantize the input data as * well as perform the IDCT; for dequantization, it uses the multiplier table * pointed to by compptr->dct_table. The output data is to be placed into the * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is * DCT_scaled_size * DCT_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ /* * Each IDCT routine has its own ideas about the best dct_table element type. */ typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ #if BITS_IN_JSAMPLE == 8 typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ #define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ #else typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ #define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ #endif typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ /* * Each IDCT routine is responsible for range-limiting its results and * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method * to do the combined operations quickly. See the comments with * prepare_range_limit_table (in jdmaster.c) for more info. */ #define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) #define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast #define jpeg_fdct_float jFDfloat #define jpeg_idct_islow jRDislow #define jpeg_idct_ifast jRDifast #define jpeg_idct_float jRDfloat #define jpeg_idct_4x4 jRD4x4 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_ifast JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* * Macros for handling fixed-point arithmetic; these are used by many * but not all of the DCT/IDCT modules. * * All values are expected to be of type INT32. * Fractional constants are scaled left by CONST_BITS bits. * CONST_BITS is defined within each module using these macros, * and may differ from one module to the next. */ #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, * thus causing a lot of useless floating-point operations at run time. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * This macro is used only when the two inputs will actually be no more than * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a * full 32x32 multiply. This provides a useful speedup on many machines. * Unfortunately there is no way to specify a 16x16->32 multiply portably * in C, but some C compilers will do the right thing if you provide the * correct combination of casts. */ #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #ifndef MULTIPLY16C16 /* default definition */ #define MULTIPLY16C16(var,const) ((var) * (const)) #endif /* Same except both inputs are variables. */ #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) #endif #ifndef MULTIPLY16V16 /* default definition */ #define MULTIPLY16V16(var1,var2) ((var1) * (var2)) #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jddctmgr.c ================================================ /* * jddctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the inverse-DCT management logic. * This code selects a particular IDCT implementation to be used, * and it performs related housekeeping chores. No code in this file * is executed per IDCT step, only during output pass setup. * * Note that the IDCT routines are responsible for performing coefficient * dequantization as well as the IDCT proper. This module sets up the * dequantization multiplier table needed by the IDCT routine. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* * The decompressor input side (jdinput.c) saves away the appropriate * quantization table for each component at the start of the first scan * involving that component. (This is necessary in order to correctly * decode files that reuse Q-table slots.) * When we are ready to make an output pass, the saved Q-table is converted * to a multiplier table that will actually be used by the IDCT routine. * The multiplier table contents are IDCT-method-dependent. To support * application changes in IDCT method between scans, we can remake the * multiplier tables if necessary. * In buffered-image mode, the first output pass may occur before any data * has been seen for some components, and thus before their Q-tables have * been saved away. To handle this case, multiplier tables are preset * to zeroes; the result of the IDCT will be a neutral gray level. */ /* Private subobject for this module */ typedef struct { struct jpeg_inverse_dct pub; /* public fields */ /* This array contains the IDCT method code that each multiplier table * is currently set up for, or -1 if it's not yet set up. * The actual multiplier tables are pointed to by dct_table in the * per-component comp_info structures. */ int cur_method[MAX_COMPONENTS]; } my_idct_controller; typedef my_idct_controller * my_idct_ptr; /* Allocated multiplier tables: big enough for any supported variant */ typedef union { ISLOW_MULT_TYPE islow_array[DCTSIZE2]; #ifdef DCT_IFAST_SUPPORTED IFAST_MULT_TYPE ifast_array[DCTSIZE2]; #endif #ifdef DCT_FLOAT_SUPPORTED FLOAT_MULT_TYPE float_array[DCTSIZE2]; #endif } multiplier_table; /* The current scaled-IDCT routines require ISLOW-style multiplier tables, * so be sure to compile that code if either ISLOW or SCALING is requested. */ #ifdef DCT_ISLOW_SUPPORTED #define PROVIDE_ISLOW_TABLES #else #ifdef IDCT_SCALING_SUPPORTED #define PROVIDE_ISLOW_TABLES #endif #endif /* * Prepare for an output pass. * Here we select the proper IDCT routine for each component and build * a matching multiplier table. */ METHODDEF(void) start_pass (j_decompress_ptr cinfo) { my_idct_ptr idct = (my_idct_ptr) cinfo->idct; int ci, i; jpeg_component_info *compptr; int method = 0; inverse_DCT_method_ptr method_ptr = NULL; JQUANT_TBL * qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper IDCT routine for this component's scaling */ switch (compptr->DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case 1: method_ptr = jpeg_idct_1x1; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 2: method_ptr = jpeg_idct_2x2; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 4: method_ptr = jpeg_idct_4x4; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; #endif case DCTSIZE: switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: method_ptr = jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: method_ptr = jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: method_ptr = jpeg_idct_float; method = JDCT_FLOAT; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } break; default: ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); break; } idct->pub.inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table * has yet been saved for the component, we leave the * multiplier table all-zero; we'll be reading zeroes from the * coefficient controller's buffer anyway. */ if (! compptr->component_needed || idct->cur_method[ci] == method) continue; qtbl = compptr->quant_table; if (qtbl == NULL) /* happens if no data yet for component */ continue; idct->cur_method[ci] = method; switch (method) { #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: { /* For LL&M IDCT method, multipliers are equal to raw quantization * coefficients, but are stored as ints to ensure access efficiency. */ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; } } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * For integer operation, the multiplier table is to be scaled by * IFAST_SCALE_BITS. */ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS for (i = 0; i < DCTSIZE2; i++) { ifmtbl[i] = (IFAST_MULT_TYPE) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), CONST_BITS-IFAST_SCALE_BITS); } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 */ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fmtbl[i] = (FLOAT_MULT_TYPE) ((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col]); i++; } } } break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } } /* * Initialize IDCT manager. */ GLOBAL(void) jinit_inverse_dct (j_decompress_ptr cinfo) { my_idct_ptr idct; int ci; jpeg_component_info *compptr; idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_idct_controller)); cinfo->idct = (struct jpeg_inverse_dct *) idct; idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Allocate and pre-zero a multiplier table for each component */ compptr->dct_table = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(multiplier_table)); MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); /* Mark multiplier table not yet set up for any method */ idct->cur_method[ci] = -1; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdhuff.c ================================================ /* * jdhuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines. * * Much of the complexity here has to do with supporting input suspension. * If the data source module demands suspension, we want to be able to back * up to the start of the current MCU. To do this, we copy state variables * into local working storage, and update them back to the permanent * storage only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdhuff.h" /* Declarations shared with jdphuff.c */ /* * Expanded entropy decoder object for Huffman decoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken * structure assignment. You'll need to fix this code if you have * such a compiler and you change MAX_COMPS_IN_SCAN. */ #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ ((dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ /* These fields are loaded into local variables at start of each MCU. * In case of suspension, we exit WITHOUT updating them. */ bitread_perm_state bitstate; /* Bit buffer at start of MCU */ savable_state saved; /* Other state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; /* Precalculated info set up by start_pass for use in decode_mcu: */ /* Pointers to derived tables to be used for each block within an MCU */ d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; /* Whether we care about the DC and AC coefficient values for each block */ boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; } huff_entropy_decoder; typedef huff_entropy_decoder * huff_entropy_ptr; /* * Initialize for a Huffman-compressed scan. */ METHODDEF(void) start_pass_huff_decoder (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, blkn, dctbl, actbl; jpeg_component_info * compptr; /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. * This ought to be an error condition, but we make it a warning because * there are some baseline files out there with all zeroes in these bytes. */ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || cinfo->Ah != 0 || cinfo->Al != 0) WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; /* Compute derived values for Huffman tables */ /* We may do this more than once for a table, but it's not expensive */ jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, & entropy->dc_derived_tbls[dctbl]); jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, & entropy->ac_derived_tbls[actbl]); /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Precalculate decoding info for each block in an MCU of this scan */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Precalculate which table to use for each block */ entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; /* Decide whether we really care about the coefficient values */ if (compptr->component_needed) { entropy->dc_needed[blkn] = TRUE; /* we don't need the ACs if producing a 1/8th-size image */ entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); } else { entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; } } /* Initialize bitread state variables */ entropy->bitstate.bits_left = 0; entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ entropy->pub.insufficient_data = FALSE; /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * * Note this is also used by jdphuff.c. */ GLOBAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; d_derived_tbl *dtbl; int p, i, l, si, numsymbols; int lookbits, ctr; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (d_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; numsymbols = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. */ if (((INT32) code) >= (((INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->bits[l]) { /* valoffset[l] = huffval[] index of 1st symbol of code length l, * minus the minimum code of length l */ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; p += htbl->bits[l]; dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ } } dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ /* Compute lookahead tables to speed up decoding. * First we set all the table entries to 0, indicating "too long"; * then we iterate through the Huffman codes that are short enough and * fill in all the entries that correspond to bit sequences starting * with that code. */ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { /* l = current code's length, p = its index in huffcode[] & huffval[]. */ /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { dtbl->look_nbits[lookbits] = l; dtbl->look_sym[lookbits] = htbl->huffval[p]; lookbits++; } } } /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. * For DC tables, we require the symbols to be in range 0..15. * (Tighter bounds could be applied depending on the data depth and mode, * but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; if (sym < 0 || sym > 15) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } } /* * Out-of-line code for bit fetching (shared with jdphuff.c). * See jdhuff.h for info about usage. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. * * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width * of get_buffer to be used. (On machines with wider words, an even larger * buffer could be used.) However, on some machines 32-bit shifts are * quite slow and take time proportional to the number of places shifted. * (This is true with most PC compilers, for instance.) In this case it may * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. */ #ifdef SLOW_SHIFT_32 #define MIN_GET_BITS 15 /* minimum allowable value */ #else #define MIN_GET_BITS (BIT_BUF_SIZE-7) #endif GLOBAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, int nbits) /* Load up the bit buffer to a depth of at least nbits */ { /* Copy heavily used state fields into locals (hopefully registers) */ register const JOCTET * next_input_byte = state->next_input_byte; register size_t bytes_in_buffer = state->bytes_in_buffer; j_decompress_ptr cinfo = state->cinfo; /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ /* (It is assumed that no request will be for more than that many bits.) */ /* We fail to do so only if we hit a marker or are forced to suspend. */ if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ while (bits_left < MIN_GET_BITS) { register int c; /* Attempt to read a byte */ if (bytes_in_buffer == 0) { if (! (*cinfo->src->fill_input_buffer) (cinfo)) return FALSE; next_input_byte = cinfo->src->next_input_byte; bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == 0xFF) { /* Loop here to discard any padding FF's on terminating marker, * so that we can save a valid unread_marker value. NOTE: we will * accept multiple FF's followed by a 0 as meaning a single FF data * byte. This data pattern is not valid according to the standard. */ do { if (bytes_in_buffer == 0) { if (! (*cinfo->src->fill_input_buffer) (cinfo)) return FALSE; next_input_byte = cinfo->src->next_input_byte; bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); } while (c == 0xFF); if (c == 0) { /* Found FF/00, which represents an FF data byte */ c = 0xFF; } else { /* Oops, it's actually a marker indicating end of compressed data. * Save the marker code for later use. * Fine point: it might appear that we should save the marker into * bitread working state, not straight into permanent state. But * once we have hit a marker, we cannot need to suspend within the * current MCU, because we will read no more bytes from the data * source. So it is OK to update permanent state right away. */ cinfo->unread_marker = c; /* See if we need to insert some fake zero bits. */ goto no_more_bytes; } } /* OK, load c into get_buffer */ get_buffer = (get_buffer << 8) | c; bits_left += 8; } /* end while */ } else { no_more_bytes: /* We get here if we've read the marker that terminates the compressed * data segment. There should be enough bits in the buffer register * to satisfy the request; if so, no problem. */ if (nbits > bits_left) { /* Uh-oh. Report corrupted data to user and stuff zeroes into * the data stream, so that we can produce some kind of image. * We use a nonvolatile flag to ensure that only one warning message * appears per data segment. */ if (! cinfo->entropy->insufficient_data) { WARNMS(cinfo, JWRN_HIT_MARKER); cinfo->entropy->insufficient_data = TRUE; } /* Fill the buffer with zero bits */ get_buffer <<= MIN_GET_BITS - bits_left; bits_left = MIN_GET_BITS; } } /* Unload the local registers */ state->next_input_byte = next_input_byte; state->bytes_in_buffer = bytes_in_buffer; state->get_buffer = get_buffer; state->bits_left = bits_left; return TRUE; } /* * Out-of-line code for Huffman code decoding. * See jdhuff.h for info about usage. */ GLOBAL(int) jpeg_huff_decode (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl * htbl, int min_bits) { register int l = min_bits; register INT32 code; /* HUFF_DECODE has determined that the code is at least min_bits */ /* bits long, so fetch that many bits in one swoop. */ CHECK_BIT_BUFFER(*state, l, return -1); code = GET_BITS(l); /* Collect the rest of the Huffman code one bit at a time. */ /* This is per Figure F.16 in the JPEG spec. */ while (code > htbl->maxcode[l]) { code <<= 1; CHECK_BIT_BUFFER(*state, 1, return -1); code |= GET_BITS(1); l++; } /* Unload the local registers */ state->get_buffer = get_buffer; state->bits_left = bits_left; /* With garbage input we may reach the sentinel value l = 17. */ if (l > 16) { WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); return 0; /* fake a zero as the safest result */ } return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; } /* * Figure F.12: extend sign bit. * On some machines, a shift and add will be faster than a table lookup. */ #ifdef AVOID_TABLES #define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) #else #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; #endif /* AVOID_TABLES */ /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. */ LOCAL(boolean) process_restart (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci; /* Throw away any unused bits remaining in bit buffer; */ /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; entropy->bitstate.bits_left = 0; /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) return FALSE; /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; /* Reset out-of-data flag, unless read_restart_marker left us smack up * against a marker. In that case we will end up treating the next data * segment as empty, and we can avoid producing bogus output pixels by * leaving the flag set. */ if (cinfo->unread_marker == 0) entropy->pub.insufficient_data = FALSE; return TRUE; } /* * Decode and return one MCU's worth of Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. * (Wholesale zeroing is usually a little faster than retail...) * * Returns FALSE if data source requested suspension. In that case no * changes have been made to permanent state. (Exception: some output * coefficients may already have been assigned. This is harmless for * this module, since we'll just re-assign them on the next call.) */ METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int blkn; BITREAD_STATE_VARS; savable_state state; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->pub.insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); ASSIGN_STATE(state, entropy->saved); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { JBLOCKROW block = MCU_data[blkn]; d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; register int s, k, r; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } if (entropy->dc_needed[blkn]) { /* Convert DC difference to actual value, update last_dc_val */ int ci = cinfo->MCU_membership[blkn]; s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ (*block)[0] = (JCOEF) s; } if (entropy->ac_needed[blkn]) { /* Section F.2.2.2: decode the AC coefficients */ /* Since zeroes are skipped, output area must be cleared beforehand */ for (k = 1; k < DCTSIZE2; k++) { HUFF_DECODE(s, br_state, actbl, return FALSE, label2); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); /* Output coefficient in natural (dezigzagged) order. * Note: the extra entries in jpeg_natural_order[] will save us * if k >= DCTSIZE2, which could happen if the data is corrupted. */ (*block)[jpeg_natural_order[k]] = (JCOEF) s; } else { if (r != 15) break; k += 15; } } } else { /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (k = 1; k < DCTSIZE2; k++) { HUFF_DECODE(s, br_state, actbl, return FALSE, label3); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); DROP_BITS(s); } else { if (r != 15) break; k += 15; } } } } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } /* * Module initialization routine for Huffman entropy decoding. */ GLOBAL(void) jinit_huff_decoder (j_decompress_ptr cinfo) { huff_entropy_ptr entropy; int i; entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_decoder)); cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; entropy->pub.start_pass = start_pass_huff_decoder; entropy->pub.decode_mcu = decode_mcu; /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdhuff.h ================================================ /* * jdhuff.h * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains declarations for Huffman entropy decoding routines * that are shared between the sequential decoder (jdhuff.c) and the * progressive decoder (jdphuff.c). No other modules need to see these. */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_make_d_derived_tbl jMkDDerived #define jpeg_fill_bit_buffer jFilBitBuf #define jpeg_huff_decode jHufDecode #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Derived data constructed for each Huffman table */ #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ typedef struct { /* Basic tables: (element [0] of each array is unused) */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ INT32 valoffset[17]; /* huffval[] offset for codes of length k */ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less * the smallest code of length k; so given a code of length k, the * corresponding symbol is huffval[code + valoffset[k]] */ /* Link to public Huffman table (needed only in jpeg_huff_decode) */ JHUFF_TBL *pub; /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of * the input data stream. If the next Huffman code is no more * than HUFF_LOOKAHEAD bits long, we can obtain its length and * the corresponding symbol directly from these tables. */ int look_nbits[1< 32 bits on your machine, and shifting/masking longs is * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE * appropriately should be a win. Unfortunately we can't define the size * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) * because not all machines measure sizeof in 8-bit bytes. */ typedef struct { /* Bitreading state saved across MCUs */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ } bitread_perm_state; typedef struct { /* Bitreading working state within an MCU */ /* Current data source location */ /* We need a copy, rather than munging the original, in case of suspension */ const JOCTET * next_input_byte; /* => next byte to read from source */ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ /* Bit input buffer --- note these values are kept in register variables, * not in this struct, inside the inner loops. */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ /* Pointer needed by jpeg_fill_bit_buffer. */ j_decompress_ptr cinfo; /* back link to decompress master record */ } bitread_working_state; /* Macros to declare and load/save bitread local variables. */ #define BITREAD_STATE_VARS \ register bit_buf_type get_buffer; \ register int bits_left; \ bitread_working_state br_state #define BITREAD_LOAD_STATE(cinfop,permstate) \ br_state.cinfo = cinfop; \ br_state.next_input_byte = cinfop->src->next_input_byte; \ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ get_buffer = permstate.get_buffer; \ bits_left = permstate.bits_left; #define BITREAD_SAVE_STATE(cinfop,permstate) \ cinfop->src->next_input_byte = br_state.next_input_byte; \ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ permstate.get_buffer = get_buffer; \ permstate.bits_left = bits_left /* * These macros provide the in-line portion of bit fetching. * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer * before using GET_BITS, PEEK_BITS, or DROP_BITS. * The variables get_buffer and bits_left are assumed to be locals, * but the state struct might not be (jpeg_huff_decode needs this). * CHECK_BIT_BUFFER(state,n,action); * Ensure there are N bits in get_buffer; if suspend, take action. * val = GET_BITS(n); * Fetch next N bits. * val = PEEK_BITS(n); * Fetch next N bits without removing them from the buffer. * DROP_BITS(n); * Discard next N bits. * The value N should be a simple variable, not an expression, because it * is evaluated multiple times. */ #define CHECK_BIT_BUFFER(state,nbits,action) \ { if (bits_left < (nbits)) { \ if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ { action; } \ get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } #define GET_BITS(nbits) \ (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) #define PEEK_BITS(nbits) \ (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) #define DROP_BITS(nbits) \ (bits_left -= (nbits)) /* Load up the bit buffer to a depth of at least nbits */ EXTERN(boolean) jpeg_fill_bit_buffer JPP((bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, int nbits)); /* * Code for extracting next Huffman-coded symbol from input bit stream. * Again, this is time-critical and we make the main paths be macros. * * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits * without looping. Usually, more than 95% of the Huffman codes will be 8 * or fewer bits long. The few overlength codes are handled with a loop, * which need not be inline code. * * Notes about the HUFF_DECODE macro: * 1. Near the end of the data segment, we may fail to get enough bits * for a lookahead. In that case, we do it the hard way. * 2. If the lookahead table contains no entry, the next code must be * more than HUFF_LOOKAHEAD bits long. * 3. jpeg_huff_decode returns -1 if forced to suspend. */ #define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ { register int nb, look; \ if (bits_left < HUFF_LOOKAHEAD) { \ if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ get_buffer = state.get_buffer; bits_left = state.bits_left; \ if (bits_left < HUFF_LOOKAHEAD) { \ nb = 1; goto slowlabel; \ } \ } \ look = PEEK_BITS(HUFF_LOOKAHEAD); \ if ((nb = htbl->look_nbits[look]) != 0) { \ DROP_BITS(nb); \ result = htbl->look_sym[look]; \ } else { \ nb = HUFF_LOOKAHEAD+1; \ slowlabel: \ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ { failaction; } \ get_buffer = state.get_buffer; bits_left = state.bits_left; \ } \ } /* Out-of-line case for Huffman code fetching */ EXTERN(int) jpeg_huff_decode JPP((bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl * htbl, int min_bits)); ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdinput.c ================================================ /* * jdinput.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input * processing (marker reading and coefficient decoding). The actual input * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_input_controller pub; /* public fields */ boolean inheaders; /* TRUE until first SOS is reached */ } my_input_controller; typedef my_input_controller * my_inputctl_ptr; /* Forward declarations */ METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); /* * Routines to calculate various quantities related to the size of the image. */ LOCAL(void) initial_setup (j_decompress_ptr cinfo) /* Called once, when first SOS marker is reached */ { int ci; jpeg_component_info *compptr; /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. * In the full decompressor, this will be overridden by jdmaster.c; * but in the transcoder, jdmaster.c is not used, so we must do it here. */ cinfo->min_DCT_scaled_size = DCTSIZE; /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->DCT_scaled_size = DCTSIZE; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. */ /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed, until color conversion says otherwise */ compptr->component_needed = TRUE; /* Mark no quantization table yet saved for component */ compptr->quant_table = NULL; } /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) cinfo->inputctl->has_multiple_scans = TRUE; else cinfo->inputctl->has_multiple_scans = FALSE; } LOCAL(void) per_scan_setup (j_decompress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->DCT_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } } /* * Save away a copy of the Q-table referenced by each component present * in the current scan, unless already saved during a prior scan. * * In a multiple-scan JPEG file, the encoder could assign different components * the same Q-table slot number, but change table definitions between scans * so that each component uses a different Q-table. (The IJG encoder is not * currently capable of doing this, but other encoders might.) Since we want * to be able to dequantize all the components at the end of the file, this * means that we have to save away the table actually used for each component. * We do this by copying the table at the start of the first scan containing * the component. * The JPEG spec prohibits the encoder from changing the contents of a Q-table * slot between scans of a component using that slot. If the encoder does so * anyway, this decoder will simply use the Q-table values that were current * at the start of the first scan for the component. * * The decompressor output side looks only at the saved quant tables, * not at the current Q-table slots. */ LOCAL(void) latch_quant_tables (j_decompress_ptr cinfo) { int ci, qtblno; jpeg_component_info *compptr; JQUANT_TBL * qtbl; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* No work if we already saved Q-table for this component */ if (compptr->quant_table != NULL) continue; /* Make sure specified quantization table is present */ qtblno = compptr->quant_tbl_no; if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); /* OK, save away the quantization table */ qtbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(JQUANT_TBL)); MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); compptr->quant_table = qtbl; } } /* * Initialize the input modules to read a scan of compressed data. * The first call to this is done by jdmaster.c after initializing * the entire decompressor (during jpeg_start_decompress). * Subsequent calls come from consume_markers, below. */ METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { per_scan_setup(cinfo); latch_quant_tables(cinfo); (*cinfo->entropy->start_pass) (cinfo); (*cinfo->coef->start_input_pass) (cinfo); cinfo->inputctl->consume_input = cinfo->coef->consume_data; } /* * Finish up after inputting a compressed-data scan. * This is called by the coefficient controller after it's read all * the expected data of the scan. */ METHODDEF(void) finish_input_pass (j_decompress_ptr cinfo) { cinfo->inputctl->consume_input = consume_markers; } /* * Read JPEG markers before, between, or after compressed-data scans. * Change state as necessary when a new scan is reached. * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. * * The consume_input method pointer points either here or to the * coefficient controller's consume_data routine, depending on whether * we are reading a compressed data segment or inter-segment markers. */ METHODDEF(int) consume_markers (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; int val; if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ return JPEG_REACHED_EOI; val = (*cinfo->marker->read_markers) (cinfo); switch (val) { case JPEG_REACHED_SOS: /* Found SOS */ if (inputctl->inheaders) { /* 1st SOS */ initial_setup(cinfo); inputctl->inheaders = FALSE; /* Note: start_input_pass must be called by jdmaster.c * before any more input can be consumed. jdapimin.c is * responsible for enforcing this sequencing. */ } else { /* 2nd or later SOS marker */ if (! inputctl->pub.has_multiple_scans) ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ start_input_pass(cinfo); } break; case JPEG_REACHED_EOI: /* Found EOI */ inputctl->pub.eoi_reached = TRUE; if (inputctl->inheaders) { /* Tables-only datastream, apparently */ if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_NO_SOS); } else { /* Prevent infinite loop in coef ctlr's decompress_data routine * if user set output_scan_number larger than number of scans. */ if (cinfo->output_scan_number > cinfo->input_scan_number) cinfo->output_scan_number = cinfo->input_scan_number; } break; case JPEG_SUSPENDED: break; } return val; } /* * Reset state to begin a fresh datastream. */ METHODDEF(void) reset_input_controller (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; inputctl->pub.consume_input = consume_markers; inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = TRUE; /* Reset other modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); /* Reset progression state -- would be cleaner if entropy decoder did this */ cinfo->coef_bits = NULL; } /* * Initialize the input controller module. * This is called only once, when the decompression object is created. */ GLOBAL(void) jinit_input_controller (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl; /* Create subobject in permanent pool */ inputctl = (my_inputctl_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_input_controller)); cinfo->inputctl = (struct jpeg_input_controller *) inputctl; /* Initialize method pointers */ inputctl->pub.consume_input = consume_markers; inputctl->pub.reset_input_controller = reset_input_controller; inputctl->pub.start_input_pass = start_input_pass; inputctl->pub.finish_input_pass = finish_input_pass; /* Initialize state: can't use reset_input_controller since we don't * want to try to reset other modules yet. */ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = TRUE; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdmainct.c ================================================ /* * jdmainct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for decompression. * The main buffer lies between the JPEG decompressor proper and the * post-processor; it holds downsampled data in the JPEG colorspace. * * Note that this code is bypassed in raw-data mode, since the application * supplies the equivalent of the main buffer in that case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * In the current system design, the main buffer need never be a full-image * buffer; any full-height buffers will be found inside the coefficient or * postprocessing controllers. Nonetheless, the main controller is not * trivial. Its responsibility is to provide context rows for upsampling/ * rescaling, and doing this in an efficient fashion is a bit tricky. * * Postprocessor input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) * sample rows of each component. (We require DCT_scaled_size values to be * chosen such that these numbers are integers. In practice DCT_scaled_size * values will likely be powers of two, so we actually have the stronger * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) * Upsampling will typically produce max_v_samp_factor pixel rows from each * row group (times any additional scale factor that the upsampler is * applying). * * The coefficient controller will deliver data to us one iMCU row at a time; * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or * exactly min_DCT_scaled_size row groups. (This amount of data corresponds * to one row of MCUs when the image is fully interleaved.) Note that the * number of sample rows varies across components, but the number of row * groups does not. Some garbage sample rows may be included in the last iMCU * row at the bottom of the image. * * Depending on the vertical scaling algorithm used, the upsampler may need * access to the sample row(s) above and below its current input row group. * The upsampler is required to set need_context_rows TRUE at global selection * time if so. When need_context_rows is FALSE, this controller can simply * obtain one iMCU row at a time from the coefficient controller and dole it * out as row groups to the postprocessor. * * When need_context_rows is TRUE, this controller guarantees that the buffer * passed to postprocessing contains at least one row group's worth of samples * above and below the row group(s) being processed. Note that the context * rows "above" the first passed row group appear at negative row offsets in * the passed buffer. At the top and bottom of the image, the required * context rows are manufactured by duplicating the first or last real sample * row; this avoids having special cases in the upsampling inner loops. * * The amount of context is fixed at one row group just because that's a * convenient number for this controller to work with. The existing * upsamplers really only need one sample row of context. An upsampler * supporting arbitrary output rescaling might wish for more than one row * group of context when shrinking the image; tough, we don't handle that. * (This is justified by the assumption that downsizing will be handled mostly * by adjusting the DCT_scaled_size values, so that the actual scale factor at * the upsample step needn't be much less than one.) * * To provide the desired context, we have to retain the last two row groups * of one iMCU row while reading in the next iMCU row. (The last row group * can't be processed until we have another row group for its below-context, * and so we have to save the next-to-last group too for its above-context.) * We could do this most simply by copying data around in our buffer, but * that'd be very slow. We can avoid copying any data by creating a rather * strange pointer structure. Here's how it works. We allocate a workspace * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number * of row groups per iMCU row). We create two sets of redundant pointers to * the workspace. Labeling the physical row groups 0 to M+1, the synthesized * pointer lists look like this: * M+1 M-1 * master pointer --> 0 master pointer --> 0 * 1 1 * ... ... * M-3 M-3 * M-2 M * M-1 M+1 * M M-2 * M+1 M-1 * 0 0 * We read alternate iMCU rows using each master pointer; thus the last two * row groups of the previous iMCU row remain un-overwritten in the workspace. * The pointer lists are set up so that the required context rows appear to * be adjacent to the proper places when we pass the pointer lists to the * upsampler. * * The above pictures describe the normal state of the pointer lists. * At top and bottom of the image, we diddle the pointer lists to duplicate * the first or last sample row as necessary (this is cheaper than copying * sample rows around). * * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that * situation each iMCU row provides only one row group so the buffering logic * must be different (eg, we must read two iMCU rows before we can emit the * first row group). For now, we simply do not support providing context * rows when min_DCT_scaled_size is 1. That combination seems unlikely to * be worth providing --- if someone wants a 1/8th-size preview, they probably * want it quick and dirty, so a context-free upsampler is sufficient. */ /* Private buffer controller object */ typedef struct { struct jpeg_d_main_controller pub; /* public fields */ /* Pointer to allocated workspace (M or M+2 row groups). */ JSAMPARRAY buffer[MAX_COMPONENTS]; boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ /* Remaining fields are only used in the context case. */ /* These are the master pointers to the funny-order pointer lists. */ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ } my_main_controller; typedef my_main_controller * my_main_ptr; /* context_state values: */ #define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ #define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ #define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ /* Forward declarations */ METHODDEF(void) process_data_simple_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) process_data_context_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif LOCAL(void) alloc_funny_pointers (j_decompress_ptr cinfo) /* Allocate space for the funny pointer lists. * This is done only once, not once per pass. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, rgroup; int M = cinfo->min_DCT_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ main->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ xbuf = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ main->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); main->xbuffer[1][ci] = xbuf; } } LOCAL(void) make_funny_pointers (j_decompress_ptr cinfo) /* Create the funny pointer lists discussed in the comments above. * The actual workspace is already allocated (in main->buffer), * and the space for the pointer lists is allocated too. * This routine just fills in the curiously ordered lists. * This will be repeated at the beginning of each pass. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size; jpeg_component_info *compptr; JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ xbuf0 = main->xbuffer[0][ci]; xbuf1 = main->xbuffer[1][ci]; /* First copy the workspace pointers as-is */ buf = main->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) { xbuf0[i] = xbuf1[i] = buf[i]; } /* In the second list, put the last four row groups in swapped order */ for (i = 0; i < rgroup * 2; i++) { xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; } /* The wraparound pointers at top and bottom will be filled later * (see set_wraparound_pointers, below). Initially we want the "above" * pointers to duplicate the first actual data line. This only needs * to happen in xbuffer[0]. */ for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[0]; } } } LOCAL(void) set_wraparound_pointers (j_decompress_ptr cinfo) /* Set up the "wraparound" pointers at top and bottom of the pointer lists. * This changes the pointer list state from top-of-image to the normal state. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ xbuf0 = main->xbuffer[0][ci]; xbuf1 = main->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; xbuf0[rgroup*(M+2) + i] = xbuf0[i]; xbuf1[rgroup*(M+2) + i] = xbuf1[i]; } } } LOCAL(void) set_bottom_pointers (j_decompress_ptr cinfo) /* Change the pointer lists to duplicate the last sample row at the bottom * of the image. whichptr indicates which xbuffer holds the final iMCU row. * Also sets rowgroups_avail to indicate number of nondummy row groups in row. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Count sample rows in one iMCU row and in one row group */ iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; rgroup = iMCUheight / cinfo->min_DCT_scaled_size; /* Count nondummy sample rows remaining for this component */ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; /* Count nondummy row groups. Should get same answer for each component, * so we need only do it once. */ if (ci == 0) { main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); } /* Duplicate the last real sample row rgroup*2 times; this pads out the * last partial rowgroup and ensures at least one full rowgroup of context. */ xbuf = main->xbuffer[main->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) { xbuf[rows_left + i] = xbuf[rows_left-1]; } } } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr main = (my_main_ptr) cinfo->main; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { main->pub.process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ main->context_state = CTX_PREPARE_FOR_IMCU; main->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ main->pub.process_data = process_data_simple_main; } main->buffer_full = FALSE; /* Mark buffer empty */ main->rowgroup_ctr = 0; break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ main->pub.process_data = process_data_crank_post; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data. * This handles the simple case where no context is required. */ METHODDEF(void) process_data_simple_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; JDIMENSION rowgroups_avail; /* Read input data if we haven't filled the main buffer yet */ if (! main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) return; /* suspension forced, can do nothing more */ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } /* There are always min_DCT_scaled_size row groups in an iMCU row. */ rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; /* Note: at the bottom of the image, we may pass extra garbage row groups * to the postprocessor. The postprocessor has to check for bottom * of image anyway (at row resolution), so no point in us doing it too. */ /* Feed the postprocessor */ (*cinfo->post->post_process_data) (cinfo, main->buffer, &main->rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (main->rowgroup_ctr >= rowgroups_avail) { main->buffer_full = FALSE; main->rowgroup_ctr = 0; } } /* * Process some data. * This handles the case where context rows must be provided. */ METHODDEF(void) process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (! main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, main->xbuffer[main->whichptr])) return; /* suspension forced, can do nothing more */ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ main->iMCU_row_ctr++; /* count rows received */ } /* Postprocessor typically will not swallow all the input data it is handed * in one call (due to filling the output buffer first). Must be prepared * to exit and restart. This switch lets us keep track of how far we got. * Note that each case falls through to the next on successful completion. */ switch (main->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], &main->rowgroup_ctr, main->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (main->rowgroup_ctr < main->rowgroups_avail) return; /* Need to suspend */ main->context_state = CTX_PREPARE_FOR_IMCU; if (*out_row_ctr >= out_rows_avail) return; /* Postprocessor exactly filled output buf */ /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ main->rowgroup_ctr = 0; main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) set_bottom_pointers(cinfo); main->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], &main->rowgroup_ctr, main->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (main->rowgroup_ctr < main->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ if (main->iMCU_row_ctr == 1) set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */ main->whichptr ^= 1; /* 0=>1 or 1=>0 */ main->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); main->context_state = CTX_POSTPONED_ROW; } } /* * Process some data. * Final pass of two-pass quantization: just call the postprocessor. * Source data will be the postprocessor controller's internal buffer. */ #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, (JDIMENSION *) NULL, (JDIMENSION) 0, output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize main buffer controller. */ GLOBAL(void) jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main; int ci, rgroup, ngroups; jpeg_component_info *compptr; main = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_d_main_controller *) main; main->pub.start_pass = start_pass_main; if (need_full_buffer) /* shouldn't happen */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); /* Allocate the workspace. * ngroups is the number of row groups we need. */ if (cinfo->upsample->need_context_rows) { if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ ERREXIT(cinfo, JERR_NOTIMPL); alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ ngroups = cinfo->min_DCT_scaled_size + 2; } else { ngroups = cinfo->min_DCT_scaled_size; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->DCT_scaled_size, (JDIMENSION) (rgroup * ngroups)); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdmarker.c ================================================ /* * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to decode JPEG datastream markers. * Most of the complexity arises from our desire to support input * suspension: if not all of the data for a marker is available, * we must exit back to the application. On resumption, we reprocess * the marker. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* Private state */ typedef struct { struct jpeg_marker_reader pub; /* public fields */ /* Application-overridable marker processing methods */ jpeg_marker_parser_method process_COM; jpeg_marker_parser_method process_APPn[16]; /* Limit on marker data length to save for each marker type */ unsigned int length_limit_COM; unsigned int length_limit_APPn[16]; /* Status of COM/APPn marker saving */ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ unsigned int bytes_read; /* data bytes read so far in marker */ /* Note: cur_marker is not linked into marker_list until it's all read. */ } my_marker_reader; typedef my_marker_reader * my_marker_ptr; /* * Macros for fetching data from the data source module. * * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect * the current restart point; we update them only when we have reached a * suitable place to restart if a suspension occurs. */ /* Declare and initialize local copies of input pointer/count */ #define INPUT_VARS(cinfo) \ struct jpeg_source_mgr * datasrc = (cinfo)->src; \ const JOCTET * next_input_byte = datasrc->next_input_byte; \ size_t bytes_in_buffer = datasrc->bytes_in_buffer /* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \ ( datasrc->next_input_byte = next_input_byte, \ datasrc->bytes_in_buffer = bytes_in_buffer ) /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \ ( next_input_byte = datasrc->next_input_byte, \ bytes_in_buffer = datasrc->bytes_in_buffer ) /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, * but we must reload the local copies after a successful fill. */ #define MAKE_BYTE_AVAIL(cinfo,action) \ if (bytes_in_buffer == 0) { \ if (! (*datasrc->fill_input_buffer) (cinfo)) \ { action; } \ INPUT_RELOAD(cinfo); \ } /* Read a byte into variable V. * If must suspend, take the specified action (typically "return FALSE"). */ #define INPUT_BYTE(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V += GETJOCTET(*next_input_byte++); ) /* * Routines to process JPEG markers. * * Entry condition: JPEG marker itself has been read and its code saved * in cinfo->unread_marker; input restart point is just after the marker. * * Exit: if return TRUE, have read and processed any parameters, and have * updated the restart point to point after the parameters. * If return FALSE, was forced to suspend before reaching end of * marker parameters; restart point has not been moved. Same routine * will be called again after application supplies more input data. * * This approach to suspension assumes that all of a marker's parameters * can fit into a single input bufferload. This should hold for "normal" * markers. Some COM/APPn markers might have large parameter segments * that might not fit. If we are simply dropping such a marker, we use * skip_input_data to get past it, and thereby put the problem on the * source manager's shoulders. If we are saving the marker's contents * into memory, we use a slightly different convention: when forced to * suspend, the marker processor updates the restart point to the end of * what it's consumed (ie, the end of the buffer) before returning FALSE. * On resumption, cinfo->unread_marker still contains the marker code, * but the data source will point to the next chunk of marker data. * The marker processor must retain internal state to deal with this. * * Note that we don't bother to avoid duplicate trace messages if a * suspension occurs within marker parameters. Other side effects * require more care. */ LOCAL(boolean) get_soi (j_decompress_ptr cinfo) /* Process an SOI marker */ { int i; TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) ERREXIT(cinfo, JERR_SOI_DUPLICATE); /* Reset all parameters that are defined to be reset by SOI */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } cinfo->restart_interval = 0; /* Set initial assumptions for colorspace etc */ cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ cinfo->saw_JFIF_marker = FALSE; cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ cinfo->JFIF_minor_version = 1; cinfo->density_unit = 0; cinfo->X_density = 1; cinfo->Y_density = 1; cinfo->saw_Adobe_marker = FALSE; cinfo->Adobe_transform = 0; cinfo->marker->saw_SOI = TRUE; return TRUE; } LOCAL(boolean) get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) /* Process a SOFn marker */ { INT32 length; int c, ci; jpeg_component_info * compptr; INPUT_VARS(cinfo); cinfo->progressive_mode = is_prog; cinfo->arith_code = is_arith; INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); length -= 8; TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, (int) cinfo->image_width, (int) cinfo->image_height, cinfo->num_components); if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_DUPLICATE); /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); if (length != (cinfo->num_components * 3)) ERREXIT(cinfo, JERR_BAD_LENGTH); if (cinfo->comp_info == NULL) /* do only once, even if suspend */ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->component_index = ci; INPUT_BYTE(cinfo, compptr->component_id, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, compptr->component_id, compptr->h_samp_factor, compptr->v_samp_factor, compptr->quant_tbl_no); } cinfo->marker->saw_SOF = TRUE; INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_sos (j_decompress_ptr cinfo) /* Process a SOS marker */ { INT32 length; int i, ci, n, c, cc; jpeg_component_info * compptr; INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOS_NO_SOF); INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ TRACEMS1(cinfo, 1, JTRC_SOS, n); if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) ERREXIT(cinfo, JERR_BAD_LENGTH); cinfo->comps_in_scan = n; /* Collect the component-spec parameters */ for (i = 0; i < n; i++) { INPUT_BYTE(cinfo, cc, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (cc == compptr->component_id) goto id_found; } ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); id_found: cinfo->cur_comp_info[i] = compptr; compptr->dc_tbl_no = (c >> 4) & 15; compptr->ac_tbl_no = (c ) & 15; TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, compptr->dc_tbl_no, compptr->ac_tbl_no); } /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Se = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ah = (c >> 4) & 15; cinfo->Al = (c ) & 15; TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; /* Count another SOS marker */ cinfo->input_scan_number++; INPUT_SYNC(cinfo); return TRUE; } #ifdef D_ARITH_CODING_SUPPORTED LOCAL(boolean) get_dac (j_decompress_ptr cinfo) /* Process a DAC marker */ { INT32 length; int index, val; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); INPUT_BYTE(cinfo, val, return FALSE); length -= 2; TRACEMS2(cinfo, 1, JTRC_DAC, index, val); if (index < 0 || index >= (2*NUM_ARITH_TBLS)) ERREXIT1(cinfo, JERR_DAC_INDEX, index); if (index >= NUM_ARITH_TBLS) { /* define AC table */ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; } else { /* define DC table */ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); cinfo->arith_dc_U[index] = (UINT8) (val >> 4); if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) ERREXIT1(cinfo, JERR_DAC_VALUE, val); } } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } #else /* ! D_ARITH_CODING_SUPPORTED */ #define get_dac(cinfo) skip_variable(cinfo) #endif /* D_ARITH_CODING_SUPPORTED */ LOCAL(boolean) get_dht (j_decompress_ptr cinfo) /* Process a DHT marker */ { INT32 length; UINT8 bits[17]; UINT8 huffval[256]; int i, index, count; JHUFF_TBL **htblptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 16) { INPUT_BYTE(cinfo, index, return FALSE); TRACEMS1(cinfo, 1, JTRC_DHT, index); bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { INPUT_BYTE(cinfo, bits[i], return FALSE); count += bits[i]; } length -= 1 + 16; TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]); TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]); /* Here we just do minimal validation of the counts to avoid walking * off the end of our table space. jdhuff.c will check more carefully. */ if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); for (i = 0; i < count; i++) INPUT_BYTE(cinfo, huffval[i], return FALSE); length -= count; if (index & 0x10) { /* AC table definition */ index -= 0x10; htblptr = &cinfo->ac_huff_tbl_ptrs[index]; } else { /* DC table definition */ htblptr = &cinfo->dc_huff_tbl_ptrs[index]; } if (index < 0 || index >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_DHT_INDEX, index); if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */ { INT32 length; int n, i, prec; unsigned int tmp; JQUANT_TBL *quant_ptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, n, return FALSE); prec = n >> 4; n &= 0x0F; TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, n); if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; for (i = 0; i < DCTSIZE2; i++) { if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); else INPUT_BYTE(cinfo, tmp, return FALSE); /* We convert the zigzag-order table to natural array order. */ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; } if (cinfo->err->trace_level >= 2) { for (i = 0; i < DCTSIZE2; i += 8) { TRACEMS8(cinfo, 2, JTRC_QUANTVALS, quant_ptr->quantval[i], quant_ptr->quantval[i+1], quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); } } length -= DCTSIZE2+1; if (prec) length -= DCTSIZE2; } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_dri (j_decompress_ptr cinfo) /* Process a DRI marker */ { INT32 length; unsigned int tmp; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); if (length != 4) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_2BYTES(cinfo, tmp, return FALSE); TRACEMS1(cinfo, 1, JTRC_DRI, tmp); cinfo->restart_interval = tmp; INPUT_SYNC(cinfo); return TRUE; } /* * Routines for processing APPn and COM markers. * These are either saved in memory or discarded, per application request. * APP0 and APP14 are specially checked to see if they are * JFIF and Adobe markers, respectively. */ #define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ #define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ #define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ LOCAL(void) examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP0. * Take appropriate action if it is a JFIF marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. */ { INT32 totallen = (INT32) datalen + remaining; if (datalen >= APP0_DATA_LEN && GETJOCTET(data[0]) == 0x4A && GETJOCTET(data[1]) == 0x46 && GETJOCTET(data[2]) == 0x49 && GETJOCTET(data[3]) == 0x46 && GETJOCTET(data[4]) == 0) { /* Found JFIF APP0 marker: save info */ cinfo->saw_JFIF_marker = TRUE; cinfo->JFIF_major_version = GETJOCTET(data[5]); cinfo->JFIF_minor_version = GETJOCTET(data[6]); cinfo->density_unit = GETJOCTET(data[7]); cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); /* Check version. * Major version must be 1, anything else signals an incompatible change. * (We used to treat this as an error, but now it's a nonfatal warning, * because some bozo at Hijaak couldn't read the spec.) * Minor version should be 0..2, but process anyway if newer. */ if (cinfo->JFIF_major_version != 1) WARNMS2(cinfo, JWRN_JFIF_MAJOR, cinfo->JFIF_major_version, cinfo->JFIF_minor_version); /* Generate trace messages */ TRACEMS5(cinfo, 1, JTRC_JFIF, cinfo->JFIF_major_version, cinfo->JFIF_minor_version, cinfo->X_density, cinfo->Y_density, cinfo->density_unit); /* Validate thumbnail dimensions and issue appropriate messages */ if (GETJOCTET(data[12]) | GETJOCTET(data[13])) TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, GETJOCTET(data[12]), GETJOCTET(data[13])); totallen -= APP0_DATA_LEN; if (totallen != ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); } else if (datalen >= 6 && GETJOCTET(data[0]) == 0x4A && GETJOCTET(data[1]) == 0x46 && GETJOCTET(data[2]) == 0x58 && GETJOCTET(data[3]) == 0x58 && GETJOCTET(data[4]) == 0) { /* Found JFIF "JFXX" extension APP0 marker */ /* The library doesn't actually do anything with these, * but we try to produce a helpful trace message. */ switch (GETJOCTET(data[5])) { case 0x10: TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); break; case 0x11: TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); break; case 0x13: TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); break; default: TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, GETJOCTET(data[5]), (int) totallen); break; } } else { /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); } } LOCAL(void) examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP14. * Take appropriate action if it is an Adobe marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. */ { unsigned int version, flags0, flags1, transform; if (datalen >= APP14_DATA_LEN && GETJOCTET(data[0]) == 0x41 && GETJOCTET(data[1]) == 0x64 && GETJOCTET(data[2]) == 0x6F && GETJOCTET(data[3]) == 0x62 && GETJOCTET(data[4]) == 0x65) { /* Found Adobe APP14 marker */ version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); transform = GETJOCTET(data[11]); TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); cinfo->saw_Adobe_marker = TRUE; cinfo->Adobe_transform = (UINT8) transform; } else { /* Start of APP14 does not match "Adobe", or too short */ TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); } } METHODDEF(boolean) get_interesting_appn (j_decompress_ptr cinfo) /* Process an APP0 or APP14 marker without saving it */ { INT32 length; JOCTET b[APPN_DATA_LEN]; unsigned int i, numtoread; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; /* get the interesting part of the marker data */ if (length >= APPN_DATA_LEN) numtoread = APPN_DATA_LEN; else if (length > 0) numtoread = (unsigned int) length; else numtoread = 0; for (i = 0; i < numtoread; i++) INPUT_BYTE(cinfo, b[i], return FALSE); length -= numtoread; /* process it */ switch (cinfo->unread_marker) { case M_APP0: examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); break; case M_APP14: examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); break; default: /* can't get here unless jpeg_save_markers chooses wrong processor */ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); break; } /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } #ifdef SAVE_MARKERS_SUPPORTED METHODDEF(boolean) save_marker (j_decompress_ptr cinfo) /* Save an APPn or COM marker into the marker list */ { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; jpeg_saved_marker_ptr cur_marker = marker->cur_marker; unsigned int bytes_read, data_length; JOCTET FAR * data; INT32 length = 0; INPUT_VARS(cinfo); if (cur_marker == NULL) { /* begin reading a marker */ INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; if (length >= 0) { /* watch out for bogus length word */ /* figure out how much we want to save */ unsigned int limit; if (cinfo->unread_marker == (int) M_COM) limit = marker->length_limit_COM; else limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; if ((unsigned int) length < limit) limit = (unsigned int) length; /* allocate and initialize the marker item */ cur_marker = (jpeg_saved_marker_ptr) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(struct jpeg_marker_struct) + limit); cur_marker->next = NULL; cur_marker->marker = (UINT8) cinfo->unread_marker; cur_marker->original_length = (unsigned int) length; cur_marker->data_length = limit; /* data area is just beyond the jpeg_marker_struct */ data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); marker->cur_marker = cur_marker; marker->bytes_read = 0; bytes_read = 0; data_length = limit; } else { /* deal with bogus length word */ bytes_read = data_length = 0; data = NULL; } } else { /* resume reading a marker */ bytes_read = marker->bytes_read; data_length = cur_marker->data_length; data = cur_marker->data + bytes_read; } while (bytes_read < data_length) { INPUT_SYNC(cinfo); /* move the restart point to here */ marker->bytes_read = bytes_read; /* If there's not at least one byte in buffer, suspend */ MAKE_BYTE_AVAIL(cinfo, return FALSE); /* Copy bytes with reasonable rapidity */ while (bytes_read < data_length && bytes_in_buffer > 0) { *data++ = *next_input_byte++; bytes_in_buffer--; bytes_read++; } } /* Done reading what we want to read */ if (cur_marker != NULL) { /* will be NULL if bogus length word */ /* Add new marker to end of list */ if (cinfo->marker_list == NULL) { cinfo->marker_list = cur_marker; } else { jpeg_saved_marker_ptr prev = cinfo->marker_list; while (prev->next != NULL) prev = prev->next; prev->next = cur_marker; } /* Reset pointer & calc remaining data length */ data = cur_marker->data; length = cur_marker->original_length - data_length; } /* Reset to initial state for next marker */ marker->cur_marker = NULL; /* Process the marker if interesting; else just make a generic trace msg */ switch (cinfo->unread_marker) { case M_APP0: examine_app0(cinfo, data, data_length, length); break; case M_APP14: examine_app14(cinfo, data, data_length, length); break; default: TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) (data_length + length)); break; } /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } #endif /* SAVE_MARKERS_SUPPORTED */ METHODDEF(boolean) skip_variable (j_decompress_ptr cinfo) /* Skip over an unknown or uninteresting variable-length marker */ { INT32 length; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } /* * Find the next JPEG marker, save it in cinfo->unread_marker. * Returns FALSE if had to suspend before reaching a marker; * in that case cinfo->unread_marker is unchanged. * * Note that the result might not be a valid marker code, * but it will never be 0 or FF. */ LOCAL(boolean) next_marker (j_decompress_ptr cinfo) { int c; INPUT_VARS(cinfo); for (;;) { INPUT_BYTE(cinfo, c, return FALSE); /* Skip any non-FF bytes. * This may look a bit inefficient, but it will not occur in a valid file. * We sync after each discarded byte so that a suspending data source * can discard the byte from its buffer. */ while (c != 0xFF) { cinfo->marker->discarded_bytes++; INPUT_SYNC(cinfo); INPUT_BYTE(cinfo, c, return FALSE); } /* This loop swallows any duplicate FF bytes. Extra FFs are legal as * pad bytes, so don't count them in discarded_bytes. We assume there * will not be so many consecutive FF bytes as to overflow a suspending * data source's input buffer. */ do { INPUT_BYTE(cinfo, c, return FALSE); } while (c == 0xFF); if (c != 0) break; /* found a valid marker, exit loop */ /* Reach here if we found a stuffed-zero data sequence (FF/00). * Discard it and loop back to try again. */ cinfo->marker->discarded_bytes += 2; INPUT_SYNC(cinfo); } if (cinfo->marker->discarded_bytes != 0) { WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); cinfo->marker->discarded_bytes = 0; } cinfo->unread_marker = c; INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) first_marker (j_decompress_ptr cinfo) /* Like next_marker, but used to obtain the initial SOI marker. */ /* For this marker, we do not allow preceding garbage or fill; otherwise, * we might well scan an entire input file before realizing it ain't JPEG. * If an application wants to process non-JFIF files, it must seek to the * SOI before calling the JPEG library. */ { int c, c2; INPUT_VARS(cinfo); INPUT_BYTE(cinfo, c, return FALSE); INPUT_BYTE(cinfo, c2, return FALSE); if (c != 0xFF || c2 != (int) M_SOI) ERREXIT2(cinfo, JERR_NO_SOI, c, c2); cinfo->unread_marker = c2; INPUT_SYNC(cinfo); return TRUE; } /* * Read markers until SOS or EOI. * * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. */ METHODDEF(int) read_markers (j_decompress_ptr cinfo) { /* Outer loop repeats once for each marker. */ for (;;) { /* Collect the marker proper, unless we already did. */ /* NB: first_marker() enforces the requirement that SOI appear first. */ if (cinfo->unread_marker == 0) { if (! cinfo->marker->saw_SOI) { if (! first_marker(cinfo)) return JPEG_SUSPENDED; } else { if (! next_marker(cinfo)) return JPEG_SUSPENDED; } } /* At this point cinfo->unread_marker contains the marker code and the * input point is just past the marker proper, but before any parameters. * A suspension will cause us to return with this state still true. */ switch (cinfo->unread_marker) { case M_SOI: if (! get_soi(cinfo)) return JPEG_SUSPENDED; break; case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ if (! get_sof(cinfo, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ if (! get_sof(cinfo, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ if (! get_sof(cinfo, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ if (! get_sof(cinfo, TRUE, TRUE)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); break; case M_SOS: if (! get_sos(cinfo)) return JPEG_SUSPENDED; cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_SOS; case M_EOI: TRACEMS(cinfo, 1, JTRC_EOI); cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_EOI; case M_DAC: if (! get_dac(cinfo)) return JPEG_SUSPENDED; break; case M_DHT: if (! get_dht(cinfo)) return JPEG_SUSPENDED; break; case M_DQT: if (! get_dqt(cinfo)) return JPEG_SUSPENDED; break; case M_DRI: if (! get_dri(cinfo)) return JPEG_SUSPENDED; break; case M_APP0: case M_APP1: case M_APP2: case M_APP3: case M_APP4: case M_APP5: case M_APP6: case M_APP7: case M_APP8: case M_APP9: case M_APP10: case M_APP11: case M_APP12: case M_APP13: case M_APP14: case M_APP15: if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ cinfo->unread_marker - (int) M_APP0]) (cinfo)) return JPEG_SUSPENDED; break; case M_COM: if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) return JPEG_SUSPENDED; break; case M_RST0: /* these are all parameterless */ case M_RST1: case M_RST2: case M_RST3: case M_RST4: case M_RST5: case M_RST6: case M_RST7: case M_TEM: TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); break; case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ if (! skip_variable(cinfo)) return JPEG_SUSPENDED; break; default: /* must be DHP, EXP, JPGn, or RESn */ /* For now, we treat the reserved markers as fatal errors since they are * likely to be used to signal incompatible JPEG Part 3 extensions. * Once the JPEG 3 version-number marker is well defined, this code * ought to change! */ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); break; } /* Successfully processed marker, so reset state variable */ cinfo->unread_marker = 0; } /* end loop */ } /* * Read a restart marker, which is expected to appear next in the datastream; * if the marker is not there, take appropriate recovery action. * Returns FALSE if suspension is required. * * This is called by the entropy decoder after it has read an appropriate * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder * has already read a marker from the data source. Under normal conditions * cinfo->unread_marker will be reset to 0 before returning; if not reset, * it holds a marker which the decoder will be unable to read past. */ METHODDEF(boolean) read_restart_marker (j_decompress_ptr cinfo) { /* Obtain a marker unless we already did. */ /* Note that next_marker will complain if it skips any data. */ if (cinfo->unread_marker == 0) { if (! next_marker(cinfo)) return FALSE; } if (cinfo->unread_marker == ((int) M_RST0 + cinfo->marker->next_restart_num)) { /* Normal case --- swallow the marker and let entropy decoder continue */ TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); cinfo->unread_marker = 0; } else { /* Uh-oh, the restart markers have been messed up. */ /* Let the data source manager determine how to resync. */ if (! (*cinfo->src->resync_to_restart) (cinfo, cinfo->marker->next_restart_num)) return FALSE; } /* Update next-restart state */ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; return TRUE; } /* * This is the default resync_to_restart method for data source managers * to use if they don't have any better approach. Some data source managers * may be able to back up, or may have additional knowledge about the data * which permits a more intelligent recovery strategy; such managers would * presumably supply their own resync method. * * read_restart_marker calls resync_to_restart if it finds a marker other than * the restart marker it was expecting. (This code is *not* used unless * a nonzero restart interval has been declared.) cinfo->unread_marker is * the marker code actually found (might be anything, except 0 or FF). * The desired restart marker number (0..7) is passed as a parameter. * This routine is supposed to apply whatever error recovery strategy seems * appropriate in order to position the input stream to the next data segment. * Note that cinfo->unread_marker is treated as a marker appearing before * the current data-source input point; usually it should be reset to zero * before returning. * Returns FALSE if suspension is required. * * This implementation is substantially constrained by wanting to treat the * input as a data stream; this means we can't back up. Therefore, we have * only the following actions to work with: * 1. Simply discard the marker and let the entropy decoder resume at next * byte of file. * 2. Read forward until we find another marker, discarding intervening * data. (In theory we could look ahead within the current bufferload, * without having to discard data if we don't find the desired marker. * This idea is not implemented here, in part because it makes behavior * dependent on buffer size and chance buffer-boundary positions.) * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). * This will cause the entropy decoder to process an empty data segment, * inserting dummy zeroes, and then we will reprocess the marker. * * #2 is appropriate if we think the desired marker lies ahead, while #3 is * appropriate if the found marker is a future restart marker (indicating * that we have missed the desired restart marker, probably because it got * corrupted). * We apply #2 or #3 if the found marker is a restart marker no more than * two counts behind or ahead of the expected one. We also apply #2 if the * found marker is not a legal JPEG marker code (it's certainly bogus data). * If the found marker is a restart marker more than 2 counts away, we do #1 * (too much risk that the marker is erroneous; with luck we will be able to * resync at some future point). * For any valid non-restart JPEG marker, we apply #3. This keeps us from * overrunning the end of a scan. An implementation limited to single-scan * files might find it better to apply #2 for markers other than EOI, since * any other marker would have to be bogus data in that case. */ GLOBAL(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) { int marker = cinfo->unread_marker; int action = 1; /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) action = 2; /* invalid marker */ else if (marker < (int) M_RST0 || marker > (int) M_RST7) action = 3; /* valid non-restart marker */ else { if (marker == ((int) M_RST0 + ((desired+1) & 7)) || marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ else action = 1; /* desired restart or too far away */ } TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); switch (action) { case 1: /* Discard marker and let entropy decoder resume processing. */ cinfo->unread_marker = 0; return TRUE; case 2: /* Scan to the next marker, and repeat the decision loop. */ if (! next_marker(cinfo)) return FALSE; marker = cinfo->unread_marker; break; case 3: /* Return without advancing past this marker. */ /* Entropy decoder will be forced to process an empty segment. */ return TRUE; } } /* end loop */ } /* * Reset marker processing state to begin a fresh datastream. */ METHODDEF(void) reset_marker_reader (j_decompress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; cinfo->comp_info = NULL; /* until allocated by get_sof */ cinfo->input_scan_number = 0; /* no SOS seen yet */ cinfo->unread_marker = 0; /* no pending marker */ marker->pub.saw_SOI = FALSE; /* set internal state too */ marker->pub.saw_SOF = FALSE; marker->pub.discarded_bytes = 0; marker->cur_marker = NULL; } /* * Initialize the marker reader module. * This is called only once, when the decompression object is created. */ GLOBAL(void) jinit_marker_reader (j_decompress_ptr cinfo) { my_marker_ptr marker; int i; /* Create subobject in permanent pool */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_marker_reader)); cinfo->marker = (struct jpeg_marker_reader *) marker; /* Initialize public method pointers */ marker->pub.reset_marker_reader = reset_marker_reader; marker->pub.read_markers = read_markers; marker->pub.read_restart_marker = read_restart_marker; /* Initialize COM/APPn processing. * By default, we examine and then discard APP0 and APP14, * but simply discard COM and all other APPn. */ marker->process_COM = skip_variable; marker->length_limit_COM = 0; for (i = 0; i < 16; i++) { marker->process_APPn[i] = skip_variable; marker->length_limit_APPn[i] = 0; } marker->process_APPn[0] = get_interesting_appn; marker->process_APPn[14] = get_interesting_appn; /* Reset marker processing state */ reset_marker_reader(cinfo); } /* * Control saving of COM and APPn markers into marker_list. */ #ifdef SAVE_MARKERS_SUPPORTED GLOBAL(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, unsigned int length_limit) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; long maxlength; jpeg_marker_parser_method processor; /* Length limit mustn't be larger than what we can allocate * (should only be a concern in a 16-bit environment). */ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); if (((long) length_limit) > maxlength) length_limit = (unsigned int) maxlength; /* Choose processor routine to use. * APP0/APP14 have special requirements. */ if (length_limit) { processor = save_marker; /* If saving APP0/APP14, save at least enough for our internal use. */ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) length_limit = APP0_DATA_LEN; else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) length_limit = APP14_DATA_LEN; } else { processor = skip_variable; /* If discarding APP0/APP14, use our regular on-the-fly processor. */ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) processor = get_interesting_appn; } if (marker_code == (int) M_COM) { marker->process_COM = processor; marker->length_limit_COM = length_limit; } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { marker->process_APPn[marker_code - (int) M_APP0] = processor; marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; } else ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } #endif /* SAVE_MARKERS_SUPPORTED */ /* * Install a special processing method for COM or APPn markers. */ GLOBAL(void) jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, jpeg_marker_parser_method routine) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; if (marker_code == (int) M_COM) marker->process_COM = routine; else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) marker->process_APPn[marker_code - (int) M_APP0] = routine; else ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdmaster.c ================================================ /* * jdmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG decompressor. * These routines are concerned with selecting the modules to be executed * and with determining the number of passes and the work to be done in each * pass. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_decomp_master pub; /* public fields */ int pass_number; /* # of passes completed */ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ /* Saved references to initialized quantizer modules, * in case we need to switch modes. */ struct jpeg_color_quantizer * quantizer_1pass; struct jpeg_color_quantizer * quantizer_2pass; } my_decomp_master; typedef my_decomp_master * my_master_ptr; /* * Determine whether merged upsample/color conversion should be used. * CRUCIAL: this must match the actual capabilities of jdmerge.c! */ LOCAL(boolean) use_merged_upsample (j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED /* Merging is the equivalent of plain box-filter upsampling */ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) return FALSE; /* jdmerge.c only supports YCC=>RGB color conversion */ if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || cinfo->out_color_space != JCS_RGB || cinfo->out_color_components != RGB_PIXELSIZE) return FALSE; /* and it only handles 2h1v or 2h2v sampling ratios */ if (cinfo->comp_info[0].h_samp_factor != 2 || cinfo->comp_info[1].h_samp_factor != 1 || cinfo->comp_info[2].h_samp_factor != 1 || cinfo->comp_info[0].v_samp_factor > 2 || cinfo->comp_info[1].v_samp_factor != 1 || cinfo->comp_info[2].v_samp_factor != 1) return FALSE; /* furthermore, it doesn't work if we've scaled the IDCTs differently */ if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) return FALSE; /* ??? also need to test for upsample-time rescaling, when & if supported */ return TRUE; /* by golly, it'll work... */ #else return FALSE; #endif } /* * Compute output image dimensions and related values. * NOTE: this is exported for possible use by application. * Hence it mustn't do anything that can't be done twice. * Also note that it may be called before the master module is initialized! */ GLOBAL(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo) /* Do computations that are needed before master selection phase */ { #ifdef IDCT_SCALING_SUPPORTED int ci; jpeg_component_info *compptr; #endif /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_READY) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); #ifdef IDCT_SCALING_SUPPORTED /* Compute actual output image dimensions and DCT scaling choices. */ if (cinfo->scale_num * 8 <= cinfo->scale_denom) { /* Provide 1/8 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 8L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 8L); cinfo->min_DCT_scaled_size = 1; } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { /* Provide 1/4 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 4L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 4L); cinfo->min_DCT_scaled_size = 2; } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { /* Provide 1/2 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 2L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 2L); cinfo->min_DCT_scaled_size = 4; } else { /* Provide 1/1 scaling */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; cinfo->min_DCT_scaled_size = DCTSIZE; } /* In selecting the actual DCT scaling for each component, we try to * scale up the chroma components via IDCT scaling rather than upsampling. * This saves time if the upsampler gets to use 1:1 scaling. * Note this code assumes that the supported DCT scalings are powers of 2. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { int ssize = cinfo->min_DCT_scaled_size; while (ssize < DCTSIZE && (compptr->h_samp_factor * ssize * 2 <= cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && (compptr->v_samp_factor * ssize * 2 <= cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { ssize = ssize * 2; } compptr->DCT_scaled_size = ssize; } /* Recompute downsampled dimensions of components; * application needs to know these if using raw downsampled data. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Size in samples, after IDCT scaling */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), (long) (cinfo->max_v_samp_factor * DCTSIZE)); } #else /* !IDCT_SCALING_SUPPORTED */ /* Hardwire it to "no scaling" */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, * and has computed unscaled downsampled_width and downsampled_height. */ #endif /* IDCT_SCALING_SUPPORTED */ /* Report number of components in selected colorspace. */ /* Probably this should be in the color conversion module... */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; break; case JCS_RGB: #if RGB_PIXELSIZE != 3 cinfo->out_color_components = RGB_PIXELSIZE; break; #endif /* else share code with YCbCr */ case JCS_YCbCr: cinfo->out_color_components = 3; break; case JCS_CMYK: case JCS_YCCK: cinfo->out_color_components = 4; break; default: /* else must be same colorspace as in file */ cinfo->out_color_components = cinfo->num_components; break; } cinfo->output_components = (cinfo->quantize_colors ? 1 : cinfo->out_color_components); /* See if upsampler will want to emit more than one row at a time */ if (use_merged_upsample(cinfo)) cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; else cinfo->rec_outbuf_height = 1; } /* * Several decompression processes need to range-limit values to the range * 0..MAXJSAMPLE; the input value may fall somewhat outside this range * due to noise introduced by quantization, roundoff error, etc. These * processes are inner loops and need to be as fast as possible. On most * machines, particularly CPUs with pipelines or instruction prefetch, * a (subscript-check-less) C table lookup * x = sample_range_limit[x]; * is faster than explicit tests * if (x < 0) x = 0; * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; * These processes all use a common table prepared by the routine below. * * For most steps we can mathematically guarantee that the initial value * of x is within MAXJSAMPLE+1 of the legal range, so a table running from * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial * limiting step (just after the IDCT), a wildly out-of-range value is * possible if the input data is corrupt. To avoid any chance of indexing * off the end of memory and getting a bad-pointer trap, we perform the * post-IDCT limiting thus: * x = range_limit[x & MASK]; * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit * samples. Under normal circumstances this is more than enough range and * a correct output will be generated; with bogus input data the mask will * cause wraparound, and we will safely generate a bogus-but-in-range output. * For the post-IDCT step, we want to convert the data from signed to unsigned * representation by adding CENTERJSAMPLE at the same time that we limit it. * So the post-IDCT limiting table ends up looking like this: * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), * 0,1,...,CENTERJSAMPLE-1 * Negative inputs select values from the upper half of the table after * masking. * * We can save some space by overlapping the start of the post-IDCT table * with the simpler range limiting table. The post-IDCT table begins at * sample_range_limit + CENTERJSAMPLE. * * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. */ LOCAL(void) prepare_range_limit_table (j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE * table; int i; table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ cinfo->sample_range_limit = table; /* First segment of "simple" table: limit[x] = 0 for x < 0 */ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); /* Main part of "simple" table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ /* End of simple table, rest of first half of post-IDCT table */ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; /* Second half of post-IDCT table */ MEMZERO(table + (2 * (MAXJSAMPLE+1)), (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); } /* * Master selection of decompression modules. * This is done once at jpeg_start_decompress time. We determine * which modules will be used and give them appropriate initialization calls. * We also initialize the decompressor input side to begin consuming data. * * Since jpeg_read_header has finished, we know what is in the SOF * and (first) SOS markers. We also have all the application parameter * settings. */ LOCAL(void) master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; boolean use_c_buffer; long samplesperrow; JDIMENSION jd_samplesperrow; /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; /* No mode changes if not using buffered-image mode. */ if (! cinfo->quantize_colors || ! cinfo->buffered_image) { cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } if (cinfo->quantize_colors) { if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ if (cinfo->out_color_components != 3) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; cinfo->colormap = NULL; } else if (cinfo->colormap != NULL) { cinfo->enable_external_quant = TRUE; } else if (cinfo->two_pass_quantize) { cinfo->enable_2pass_quant = TRUE; } else { cinfo->enable_1pass_quant = TRUE; } if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* If both quantizers are initialized, the 2-pass one is left active; * this is necessary for starting with quantization to an external map. */ } /* Post-processing: in particular, color conversion first */ if (! cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { jinit_color_deconverter(cinfo); jinit_upsampler(cinfo); } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED jinit_phuff_decoder(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (! cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); #ifdef D_MULTISCAN_FILES_SUPPORTED /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (cinfo->progress != NULL && ! cinfo->buffered_image && cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); /* Count the input pass as done */ master->pass_number++; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ } /* * Per-pass setup. * This is called at the beginning of each output pass. We determine which * modules will be active during this pass and give them appropriate * start_pass calls. We also set is_dummy_pass to indicate whether this * is a "real" output pass or a dummy pass for color quantization. * (In the latter case, jdapistd.c will crank the pass to completion.) */ METHODDEF(void) prepare_for_output_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; if (master->pub.is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED /* Final pass of 2-pass quantization */ master->pub.is_dummy_pass = FALSE; (*cinfo->cquantize->start_pass) (cinfo, FALSE); (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } else { if (cinfo->quantize_colors && cinfo->colormap == NULL) { /* Select new quantization method */ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { cinfo->cquantize = master->quantizer_2pass; master->pub.is_dummy_pass = TRUE; } else if (cinfo->enable_1pass_quant) { cinfo->cquantize = master->quantizer_1pass; } else { ERREXIT(cinfo, JERR_MODE_CHANGE); } } (*cinfo->idct->start_pass) (cinfo); (*cinfo->coef->start_output_pass) (cinfo); if (! cinfo->raw_data_out) { if (! master->using_merged_upsample) (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->upsample->start_pass) (cinfo); if (cinfo->quantize_colors) (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); (*cinfo->post->start_pass) (cinfo, (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); } } /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->pass_number + (master->pub.is_dummy_pass ? 2 : 1); /* In buffered-image mode, we assume one more output pass if EOI not * yet reached, but no more passes if EOI has been reached. */ if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); } } } /* * Finish up at end of an output pass. */ METHODDEF(void) finish_output_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; if (cinfo->quantize_colors) (*cinfo->cquantize->finish_pass) (cinfo); master->pass_number++; } #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Switch to a new external colormap between output passes. */ GLOBAL(void) jpeg_new_colormap (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_BUFIMAGE) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->quantize_colors && cinfo->enable_external_quant && cinfo->colormap != NULL) { /* Select 2-pass quantizer for external colormap use */ cinfo->cquantize = master->quantizer_2pass; /* Notify quantizer of colormap change */ (*cinfo->cquantize->new_color_map) (cinfo); master->pub.is_dummy_pass = FALSE; /* just in case */ } else ERREXIT(cinfo, JERR_MODE_CHANGE); } #endif /* D_MULTISCAN_FILES_SUPPORTED */ /* * Initialize master decompression control and select active modules. * This is performed at the start of jpeg_start_decompress. */ GLOBAL(void) jinit_master_decompress (j_decompress_ptr cinfo) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_decomp_master)); cinfo->master = (struct jpeg_decomp_master *) master; master->pub.prepare_for_output_pass = prepare_for_output_pass; master->pub.finish_output_pass = finish_output_pass; master->pub.is_dummy_pass = FALSE; master_selection(cinfo); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdmerge.c ================================================ /* * jdmerge.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains code for merged upsampling/color conversion. * * This file combines functions from jdsample.c and jdcolor.c; * read those files first to understand what's going on. * * When the chroma components are to be upsampled by simple replication * (ie, box filtering), we can save some work in color conversion by * calculating all the output pixels corresponding to a pair of chroma * samples at one time. In the conversion equations * R = Y + K1 * Cr * G = Y + K2 * Cb + K3 * Cr * B = Y + K4 * Cb * only the Y term varies among the group of pixels corresponding to a pair * of chroma samples, so the rest of the terms can be calculated just once. * At typical sampling ratios, this eliminates half or three-quarters of the * multiplications needed for color conversion. * * This file currently provides implementations for the following cases: * YCbCr => RGB color conversion only. * Sampling ratios of 2h1v or 2h2v. * No scaling needed at upsample time. * Corner-aligned (non-CCIR601) sampling alignment. * Other special cases could be added, but in most applications these are * the only common cases. (For uncommon cases we fall back on the more * general code in jdsample.c and jdcolor.c.) */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef UPSAMPLE_MERGING_SUPPORTED /* Private subobject */ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Pointer to routine to do actual upsampling/conversion of one row group */ JMETHOD(void, upmethod, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)); /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ /* For 2:1 vertical sampling, we produce two output rows at a time. * We need a "spare" row buffer to hold the second output row if the * application provides just a one-row buffer; we also use the spare * to discard the dummy last row if the image height is odd. */ JSAMPROW spare_row; boolean spare_full; /* T if spare buffer is occupied */ JDIMENSION out_row_width; /* samples per output row */ JDIMENSION rows_to_go; /* counts rows remaining in image */ } my_upsampler; typedef my_upsampler * my_upsample_ptr; #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. * This is taken directly from jdcolor.c; see that file for more info. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int i; INT32 x; SHIFT_TEMPS upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); upsample->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ upsample->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); /* Cb=>B value is nearest int to 1.77200 * x */ upsample->Cb_b_tab[i] = (int) RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); /* Cr=>G value is scaled-up -0.71414 * x */ upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; /* Cb=>G value is scaled-up -0.34414 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; } } /* * Initialize for an upsampling pass. */ METHODDEF(void) start_pass_merged_upsample (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Mark the spare buffer empty */ upsample->spare_full = FALSE; /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } /* * Control routine to do upsampling (and color conversion). * * The control routine just handles the row buffering considerations. */ METHODDEF(void) merged_2v_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 2:1 vertical sampling case: may need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPROW work_ptrs[2]; JDIMENSION num_rows; /* number of rows returned to caller */ if (upsample->spare_full) { /* If we have a spare row saved from a previous cycle, just return it. */ jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 1, upsample->out_row_width); num_rows = 1; upsample->spare_full = FALSE; } else { /* Figure number of rows to return to caller. */ num_rows = 2; /* Not more than the distance to the end of the image. */ if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) num_rows = out_rows_avail; /* Create output pointer array for upsampler. */ work_ptrs[0] = output_buf[*out_row_ctr]; if (num_rows > 1) { work_ptrs[1] = output_buf[*out_row_ctr + 1]; } else { work_ptrs[1] = upsample->spare_row; upsample->spare_full = TRUE; } /* Now do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); } /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; /* When the buffer is emptied, declare this input row group consumed */ if (! upsample->spare_full) (*in_row_group_ctr)++; } METHODDEF(void) merged_1v_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 1:1 vertical sampling case: much easier, never need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Just do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, output_buf + *out_row_ctr); /* Adjust counts */ (*out_row_ctr)++; (*in_row_group_ctr)++; } /* * These are the routines invoked by the control routines to do * the actual upsampling/conversion. One row group is processed per call. * * Note: since we may be writing directly into application-supplied buffers, * we have to be honest about the output width; we can't assume the buffer * has been rounded up to an even width. */ /* * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. */ METHODDEF(void) h2v1_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr; JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; SHIFT_TEMPS inptr0 = input_buf[0][in_row_group_ctr]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr = output_buf[0]; /* Loop for each pair of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; /* Fetch 2 Y values and emit 2 pixels */ y = GETJSAMPLE(*inptr0++); outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr0++); outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr0); outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; } } /* * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. */ METHODDEF(void) h2v2_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr0, outptr1; JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; SHIFT_TEMPS inptr00 = input_buf[0][in_row_group_ctr*2]; inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr0 = output_buf[0]; outptr1 = output_buf[1]; /* Loop for each group of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr00); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; y = GETJSAMPLE(*inptr01); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; } } /* * Module initialization routine for merged upsampling/color conversion. * * NB: this is called under the conditions determined by use_merged_upsample() * in jdmaster.c. That routine MUST correspond to the actual capabilities * of this module; no safety checks are made here. */ GLOBAL(void) jinit_merged_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *) upsample; upsample->pub.start_pass = start_pass_merged_upsample; upsample->pub.need_context_rows = FALSE; upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; if (cinfo->max_v_samp_factor == 2) { upsample->pub.upsample = merged_2v_upsample; upsample->upmethod = h2v2_merged_upsample; /* Allocate a spare row buffer */ upsample->spare_row = (JSAMPROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); } else { upsample->pub.upsample = merged_1v_upsample; upsample->upmethod = h2v1_merged_upsample; /* No spare row needed */ upsample->spare_row = NULL; } build_ycc_rgb_table(cinfo); } #endif /* UPSAMPLE_MERGING_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdphuff.c ================================================ /* * jdphuff.c * * Copyright (C) 1995-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines for progressive JPEG. * * Much of the complexity here has to do with supporting input suspension. * If the data source module demands suspension, we want to be able to back * up to the start of the current MCU. To do this, we copy state variables * into local working storage, and update them back to the permanent * storage only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdhuff.h" /* Declarations shared with jdhuff.c */ #ifdef D_PROGRESSIVE_SUPPORTED /* * Expanded entropy decoder object for progressive Huffman decoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken * structure assignment. You'll need to fix this code if you have * such a compiler and you change MAX_COMPS_IN_SCAN. */ #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ ((dest).EOBRUN = (src).EOBRUN, \ (dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ /* These fields are loaded into local variables at start of each MCU. * In case of suspension, we exit WITHOUT updating them. */ bitread_perm_state bitstate; /* Bit buffer at start of MCU */ savable_state saved; /* Other state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ } phuff_entropy_decoder; typedef phuff_entropy_decoder * phuff_entropy_ptr; /* Forward declarations */ METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); /* * Initialize for a Huffman-compressed scan. */ METHODDEF(void) start_pass_phuff_decoder (j_decompress_ptr cinfo) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; boolean is_DC_band, bad; int ci, coefi, tbl; int *coef_bit_ptr; jpeg_component_info * compptr; is_DC_band = (cinfo->Ss == 0); /* Validate scan parameters */ bad = FALSE; if (is_DC_band) { if (cinfo->Se != 0) bad = TRUE; } else { /* need not check Ss/Se < 0 since they came from unsigned bytes */ if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) bad = TRUE; /* AC scans may have only one component */ if (cinfo->comps_in_scan != 1) bad = TRUE; } if (cinfo->Ah != 0) { /* Successive approximation refinement scan: must have Al = Ah-1. */ if (cinfo->Al != cinfo->Ah-1) bad = TRUE; } if (cinfo->Al > 13) /* need not check for < 0 */ bad = TRUE; /* Arguably the maximum Al value should be less than 13 for 8-bit precision, * but the spec doesn't say so, and we try to be liberal about what we * accept. Note: large Al values could result in out-of-range DC * coefficients during early scans, leading to bizarre displays due to * overflows in the IDCT math. But we won't crash. */ if (bad) ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); /* Update progression status, and verify that scan order is legal. * Note that inter-scan inconsistencies are treated as warnings * not fatal errors ... not clear if this is right way to behave. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { int cindex = cinfo->cur_comp_info[ci]->component_index; coef_bit_ptr = & cinfo->coef_bits[cindex][0]; if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; if (cinfo->Ah != expected) WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); coef_bit_ptr[coefi] = cinfo->Al; } } /* Select MCU decoding routine */ if (cinfo->Ah == 0) { if (is_DC_band) entropy->pub.decode_mcu = decode_mcu_DC_first; else entropy->pub.decode_mcu = decode_mcu_AC_first; } else { if (is_DC_band) entropy->pub.decode_mcu = decode_mcu_DC_refine; else entropy->pub.decode_mcu = decode_mcu_AC_refine; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Make sure requested tables are present, and compute derived tables. * We may build same derived table more than once, but it's not expensive. */ if (is_DC_band) { if (cinfo->Ah == 0) { /* DC refinement needs no table */ tbl = compptr->dc_tbl_no; jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, & entropy->derived_tbls[tbl]); } } else { tbl = compptr->ac_tbl_no; jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, & entropy->derived_tbls[tbl]); /* remember the single active table */ entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Initialize bitread state variables */ entropy->bitstate.bits_left = 0; entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ entropy->pub.insufficient_data = FALSE; /* Initialize private state variables */ entropy->saved.EOBRUN = 0; /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } /* * Figure F.12: extend sign bit. * On some machines, a shift and add will be faster than a table lookup. */ #ifdef AVOID_TABLES #define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) #else #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; #endif /* AVOID_TABLES */ /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. */ LOCAL(boolean) process_restart (j_decompress_ptr cinfo) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; int ci; /* Throw away any unused bits remaining in bit buffer; */ /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; entropy->bitstate.bits_left = 0; /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) return FALSE; /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Re-init EOB run count, too */ entropy->saved.EOBRUN = 0; /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; /* Reset out-of-data flag, unless read_restart_marker left us smack up * against a marker. In that case we will end up treating the next data * segment as empty, and we can avoid producing bogus output pixels by * leaving the flag set. */ if (cinfo->unread_marker == 0) entropy->pub.insufficient_data = FALSE; return TRUE; } /* * Huffman MCU decoding. * Each of these routines decodes and returns one MCU's worth of * Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. * * We return FALSE if data source requested suspension. In that case no * changes have been made to permanent state. (Exception: some output * coefficients may already have been assigned. This is harmless for * spectral selection, since we'll just re-assign them on the next call. * Successive approximation AC refinement has to be more careful, however.) */ /* * MCU decoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; int Al = cinfo->Al; register int s, r; int blkn, ci; JBLOCKROW block; BITREAD_STATE_VARS; savable_state state; d_derived_tbl * tbl; jpeg_component_info * compptr; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->pub.insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); ASSIGN_STATE(state, entropy->saved); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; tbl = entropy->derived_tbls[compptr->dc_tbl_no]; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ HUFF_DECODE(s, br_state, tbl, return FALSE, label1); if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } /* Convert DC difference to actual value, update last_dc_val */ s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ (*block)[0] = (JCOEF) (s << Al); } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; int Se = cinfo->Se; int Al = cinfo->Al; register int s, k, r; unsigned int EOBRUN; JBLOCKROW block; BITREAD_STATE_VARS; d_derived_tbl * tbl; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->pub.insufficient_data) { /* Load up working state. * We can avoid loading/saving bitread state if in an EOB run. */ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ /* There is always only one block per MCU */ if (EOBRUN > 0) /* if it's a band of zeroes... */ EOBRUN--; /* ...process it now (we do nothing) */ else { BITREAD_LOAD_STATE(cinfo,entropy->bitstate); block = MCU_data[0]; tbl = entropy->ac_derived_tbl; for (k = cinfo->Ss; k <= Se; k++) { HUFF_DECODE(s, br_state, tbl, return FALSE, label2); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); /* Scale and output coefficient in natural (dezigzagged) order */ (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); } else { if (r == 15) { /* ZRL */ k += 15; /* skip 15 zeroes in band */ } else { /* EOBr, run length is 2^r + appended bits */ EOBRUN = 1 << r; if (r) { /* EOBr, r > 0 */ CHECK_BIT_BUFFER(br_state, r, return FALSE); r = GET_BITS(r); EOBRUN += r; } EOBRUN--; /* this band is processed at this moment */ break; /* force end-of-band */ } } } BITREAD_SAVE_STATE(cinfo,entropy->bitstate); } /* Completed MCU, so update state */ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, although the spec * is not very clear on the point. */ METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ int blkn; JBLOCKROW block; BITREAD_STATE_VARS; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* Not worth the cycles to check insufficient_data here, * since we will not change the data anyway if we read zeroes. */ /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; /* Encoded data is simply the next bit of the two's-complement DC value */ CHECK_BIT_BUFFER(br_state, 1, return FALSE); if (GET_BITS(1)) (*block)[0] |= p1; /* Note: since we use |=, repeating the assignment later is safe */ } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for AC successive approximation refinement scan. */ METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; int Se = cinfo->Se; int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ register int s, k, r; unsigned int EOBRUN; JBLOCKROW block; JCOEFPTR thiscoef; BITREAD_STATE_VARS; d_derived_tbl * tbl; int num_newnz; int newnz_pos[DCTSIZE2]; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, don't modify the MCU. */ if (! entropy->pub.insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ /* There is always only one block per MCU */ block = MCU_data[0]; tbl = entropy->ac_derived_tbl; /* If we are forced to suspend, we must undo the assignments to any newly * nonzero coefficients in the block, because otherwise we'd get confused * next time about which coefficients were already nonzero. * But we need not undo addition of bits to already-nonzero coefficients; * instead, we can test the current bit to see if we already did it. */ num_newnz = 0; /* initialize coefficient loop counter to start of band */ k = cinfo->Ss; if (EOBRUN == 0) { for (; k <= Se; k++) { HUFF_DECODE(s, br_state, tbl, goto undoit, label3); r = s >> 4; s &= 15; if (s) { if (s != 1) /* size of new coef should always be 1 */ WARNMS(cinfo, JWRN_HUFF_BAD_CODE); CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) s = p1; /* newly nonzero coef is positive */ else s = m1; /* newly nonzero coef is negative */ } else { if (r != 15) { EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ if (r) { CHECK_BIT_BUFFER(br_state, r, goto undoit); r = GET_BITS(r); EOBRUN += r; } break; /* rest of block is handled by EOB logic */ } /* note s = 0 for processing ZRL */ } /* Advance over already-nonzero coefs and r still-zero coefs, * appending correction bits to the nonzeroes. A correction bit is 1 * if the absolute value of the coefficient must be increased. */ do { thiscoef = *block + jpeg_natural_order[k]; if (*thiscoef != 0) { CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) { if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ if (*thiscoef >= 0) *thiscoef += p1; else *thiscoef += m1; } } } else { if (--r < 0) break; /* reached target zero coefficient */ } k++; } while (k <= Se); if (s) { int pos = jpeg_natural_order[k]; /* Output newly nonzero coefficient */ (*block)[pos] = (JCOEF) s; /* Remember its position in case we have to suspend */ newnz_pos[num_newnz++] = pos; } } } if (EOBRUN > 0) { /* Scan any remaining coefficient positions after the end-of-band * (the last newly nonzero coefficient, if any). Append a correction * bit to each already-nonzero coefficient. A correction bit is 1 * if the absolute value of the coefficient must be increased. */ for (; k <= Se; k++) { thiscoef = *block + jpeg_natural_order[k]; if (*thiscoef != 0) { CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) { if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ if (*thiscoef >= 0) *thiscoef += p1; else *thiscoef += m1; } } } } /* Count one block completed in EOB run */ EOBRUN--; } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; undoit: /* Re-zero any output coefficients that we made newly nonzero */ while (num_newnz > 0) (*block)[newnz_pos[--num_newnz]] = 0; return FALSE; } /* * Module initialization routine for progressive Huffman entropy decoding. */ GLOBAL(void) jinit_phuff_decoder (j_decompress_ptr cinfo) { phuff_entropy_ptr entropy; int *coef_bit_ptr; int ci, i; entropy = (phuff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(phuff_entropy_decoder)); cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; entropy->pub.start_pass = start_pass_phuff_decoder; /* Mark derived tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->derived_tbls[i] = NULL; } /* Create progression status table */ cinfo->coef_bits = (int (*)[DCTSIZE2]) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components*DCTSIZE2*SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (i = 0; i < DCTSIZE2; i++) *coef_bit_ptr++ = -1; } #endif /* D_PROGRESSIVE_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdpostct.c ================================================ /* * jdpostct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the decompression postprocessing controller. * This controller manages the upsampling, color conversion, and color * quantization/reduction steps; specifically, it controls the buffering * between upsample/color conversion and color quantization/reduction. * * If no color quantization/reduction is required, then this module has no * work to do, and it just hands off to the upsample/color conversion code. * An integrated upsample/convert/quantize process would replace this module * entirely. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_d_post_controller pub; /* public fields */ /* Color quantization source buffer: this holds output data from * the upsample/color conversion step to be passed to the quantizer. * For two-pass color quantization, we need a full-image buffer; * for one-pass operation, a strip buffer is sufficient. */ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ JDIMENSION next_row; /* index of next row to fill/empty in strip */ } my_post_controller; typedef my_post_controller * my_post_ptr; /* Forward declarations */ METHODDEF(void) post_process_1pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) post_process_prepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) post_process_2pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_post_ptr post = (my_post_ptr) cinfo->post; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->quantize_colors) { /* Single-pass processing with color quantization. */ post->pub.post_process_data = post_process_1pass; /* We could be doing buffered-image output before starting a 2-pass * color quantization; in that case, jinit_d_post_controller did not * allocate a strip buffer. Use the virtual-array buffer as workspace. */ if (post->buffer == NULL) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, (JDIMENSION) 0, post->strip_height, TRUE); } } else { /* For single-pass processing without color quantization, * I have no work to do; just call the upsampler directly. */ post->pub.post_process_data = cinfo->upsample->upsample; } break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_SAVE_AND_PASS: /* First pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_prepass; break; case JBUF_CRANK_DEST: /* Second pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_2pass; break; #endif /* QUANT_2PASS_SUPPORTED */ default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } post->starting_row = post->next_row = 0; } /* * Process some data in the one-pass (strip buffer) case. * This is used for color precision reduction as well as one-pass quantization. */ METHODDEF(void) post_process_1pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Fill the buffer, but not more than what we can dump out in one go. */ /* Note we rely on the upsampler to detect bottom of image. */ max_rows = out_rows_avail - *out_row_ctr; if (max_rows > post->strip_height) max_rows = post->strip_height; num_rows = 0; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &num_rows, max_rows); /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; } #ifdef QUANT_2PASS_SUPPORTED /* * Process some data in the first pass of 2-pass quantization. */ METHODDEF(void) post_process_prepass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION old_next_row, num_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, (JSAMPARRAY) NULL, (int) num_rows); *out_row_ctr += num_rows; } /* Advance if we filled the strip. */ if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } /* * Process some data in the second pass of 2-pass quantization. */ METHODDEF(void) post_process_2pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, FALSE); } /* Determine number of rows to emit. */ num_rows = post->strip_height - post->next_row; /* available in strip */ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ if (num_rows > max_rows) num_rows = max_rows; /* We have to check bottom of image here, can't depend on upsampler. */ max_rows = cinfo->output_height - post->starting_row; if (num_rows > max_rows) num_rows = max_rows; /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ post->next_row += num_rows; if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize postprocessing controller. */ GLOBAL(void) jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->whole_image = NULL; /* flag for no virtual arrays */ post->buffer = NULL; /* flag for no strip buffer */ /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) */ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; if (need_full_buffer) { /* Two-pass color quantization: need full-image storage. */ /* We round up the number of rows to a multiple of the strip height. */ #ifdef QUANT_2PASS_SUPPORTED post->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, cinfo->output_width * cinfo->out_color_components, (JDIMENSION) jround_up((long) cinfo->output_height, (long) post->strip_height), post->strip_height); #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ post->buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdsample.c ================================================ /* * jdsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * * Upsampling input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) * sample rows of each component. Upsampling will normally produce * max_v_samp_factor pixel rows from each row group (but this could vary * if the upsampler is applying a scale factor of its own). * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Pointer to routine to upsample a single component */ typedef JMETHOD(void, upsample1_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); /* Private subobject */ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Color conversion buffer. When using separate upsampling and color * conversion steps, this buffer holds one upsampled row group until it * has been color converted and output. * Note: we do not allocate any storage for component(s) which are full-size, * ie do not need rescaling. The corresponding entry of color_buf[] is * simply set to point to the input data array, thereby avoiding copying. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; int next_row_out; /* counts rows emitted from color_buf */ JDIMENSION rows_to_go; /* counts rows remaining in image */ /* Height of an input row group for each component. */ int rowgroup_height[MAX_COMPONENTS]; /* These arrays save pixel expansion factors so that int_expand need not * recompute them each time. They are unused for other upsampling methods. */ UINT8 h_expand[MAX_COMPONENTS]; UINT8 v_expand[MAX_COMPONENTS]; } my_upsampler; typedef my_upsampler * my_upsample_ptr; /* * Initialize for an upsampling pass. */ METHODDEF(void) start_pass_upsample (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Mark the conversion buffer empty */ upsample->next_row_out = cinfo->max_v_samp_factor; /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } /* * Control routine to do upsampling (and color conversion). * * In this version we upsample each component independently. * We upsample one row group into the conversion buffer, then apply * color conversion a row at a time. */ METHODDEF(void) sep_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int ci; jpeg_component_info * compptr; JDIMENSION num_rows; /* Fill the conversion buffer, if it's empty */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Invoke per-component upsample method. Notice we pass a POINTER * to color_buf[ci], so that fullsize_upsample can change it. */ (*upsample->methods[ci]) (cinfo, compptr, input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), upsample->color_buf + ci); } upsample->next_row_out = 0; } /* Color-convert and emit rows */ /* How many we have in the buffer: */ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); /* Not more than the distance to the end of the image. Need this test * in case the image height is not a multiple of max_v_samp_factor: */ if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) num_rows = out_rows_avail; (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, (JDIMENSION) upsample->next_row_out, output_buf + *out_row_ctr, (int) num_rows); /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; upsample->next_row_out += num_rows; /* When the buffer is emptied, declare this input row group consumed */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) (*in_row_group_ctr)++; } /* * These are the routines invoked by sep_upsample to upsample pixel values * of a single component. One row group is processed per call. */ /* * For full-size components, we just make color_buf[ci] point at the * input buffer, and thus avoid copying any data. Note that this is * safe only because sep_upsample doesn't declare the input row group * "consumed" until we are done color converting and emitting it. */ METHODDEF(void) fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = input_data; } /* * This is a no-op version used for "uninteresting" components. * These components will not be referenced by color conversion. */ METHODDEF(void) noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } /* * This version handles any integral sampling ratios. * This is not used for typical JPEG files, so it need not be fast. * Nor, for that matter, is it particularly accurate: the algorithm is * simple replication of the input pixel onto the corresponding output * pixels. The hi-falutin sampling literature refers to this as a * "box filter". A box filter tends to introduce visible artifacts, * so if you are actually going to use 3:1 or 4:1 sampling ratios * you would be well advised to improve this code. */ METHODDEF(void) int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; register int h; JSAMPROW outend; int h_expand, v_expand; int inrow, outrow; h_expand = upsample->h_expand[compptr->component_index]; v_expand = upsample->v_expand[compptr->component_index]; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { /* Generate one output row with proper horizontal expansion */ inptr = input_data[inrow]; outptr = output_data[outrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ for (h = h_expand; h > 0; h--) { *outptr++ = invalue; } } /* Generate any additional output rows by duplicating the first one */ if (v_expand > 1) { jcopy_sample_rows(output_data, outrow, output_data, outrow+1, v_expand-1, cinfo->output_width); } inrow++; outrow += v_expand; } } /* * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. * It's still a box filter. */ METHODDEF(void) h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { inptr = input_data[inrow]; outptr = output_data[inrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ *outptr++ = invalue; *outptr++ = invalue; } } } /* * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. * It's still a box filter. */ METHODDEF(void) h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; int inrow, outrow; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { inptr = input_data[inrow]; outptr = output_data[outrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ *outptr++ = invalue; *outptr++ = invalue; } jcopy_sample_rows(output_data, outrow, output_data, outrow+1, 1, cinfo->output_width); inrow++; outrow += 2; } } /* * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. * * The upsampling algorithm is linear interpolation between pixel centers, * also known as a "triangle filter". This is a good compromise between * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 * of the way between input pixel centers. * * A note about the "bias" calculations: when rounding fractional values to * integer, we do not want to always round 0.5 up to the next integer. * If we did that, we'd introduce a noticeable bias towards larger values. * Instead, this code is arranged so that 0.5 will be rounded up or down at * alternate pixel locations (a simple ordered dither pattern). */ METHODDEF(void) h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register int invalue; register JDIMENSION colctr; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { inptr = input_data[inrow]; outptr = output_data[inrow]; /* Special case for first column */ invalue = GETJSAMPLE(*inptr++); *outptr++ = (JSAMPLE) invalue; *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ invalue = GETJSAMPLE(*inptr++) * 3; *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); } /* Special case for last column */ invalue = GETJSAMPLE(*inptr); *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); *outptr++ = (JSAMPLE) invalue; } } /* * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. * Again a triangle filter; see comments for h2v1 case, above. * * It is OK for us to reference the adjacent input rows because we demanded * context from the main buffer controller (see initialization code). */ METHODDEF(void) h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 register int thiscolsum, lastcolsum, nextcolsum; #else register INT32 thiscolsum, lastcolsum, nextcolsum; #endif register JDIMENSION colctr; int inrow, outrow, v; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { for (v = 0; v < 2; v++) { /* inptr0 points to nearest input row, inptr1 points to next nearest */ inptr0 = input_data[inrow]; if (v == 0) /* next nearest is row above */ inptr1 = input_data[inrow-1]; else /* next nearest is row below */ inptr1 = input_data[inrow+1]; outptr = output_data[outrow++]; /* Special case for first column */ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); } inrow++; } } /* * Module initialization routine for upsampling. */ GLOBAL(void) jinit_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *) upsample; upsample->pub.start_pass = start_pass_upsample; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, * so don't ask for it. */ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Compute size of an "input group" after IDCT scaling. This many samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ need_buffer = TRUE; if (! compptr->component_needed) { /* Don't bother to upsample an uninteresting component. */ upsample->methods[ci] = noop_upsample; need_buffer = FALSE; } else if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; need_buffer = FALSE; } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special cases for 2h1v upsampling */ if (do_fancy && compptr->downsampled_width > 2) upsample->methods[ci] = h2v1_fancy_upsample; else upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { /* Special cases for 2h2v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; } else upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ upsample->methods[ci] = int_upsample; upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); if (need_buffer) { upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) cinfo->output_width, (long) cinfo->max_h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jdtrans.c ================================================ /* * jdtrans.c * * Copyright (C) 1995-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains library routines for transcoding decompression, * that is, reading raw DCT coefficient arrays from an input JPEG file. * The routines in jdapimin.c will also be needed by a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); /* * Read the coefficient arrays from a JPEG file. * jpeg_read_header must be completed before calling this. * * The entire image is read into a set of virtual coefficient-block arrays, * one per component. The return value is a pointer to the array of * virtual-array descriptors. These can be manipulated directly via the * JPEG memory manager, or handed off to jpeg_write_coefficients(). * To release the memory occupied by the virtual arrays, call * jpeg_finish_decompress() when done with the data. * * An alternative usage is to simply obtain access to the coefficient arrays * during a buffered-image-mode decompression operation. This is allowed * after any jpeg_finish_output() call. The arrays can be accessed until * jpeg_finish_decompress() is called. (Note that any call to the library * may reposition the arrays, so don't rely on access_virt_barray() results * to stay valid across library calls.) * * Returns NULL if suspended. This case need be checked only if * a suspending data source is used. */ GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize active modules */ transdecode_master_selection(cinfo); cinfo->global_state = DSTATE_RDCOEFS; } if (cinfo->global_state == DSTATE_RDCOEFS) { /* Absorb whole file into the coef buffer */ for (;;) { int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return NULL; if (retcode == JPEG_REACHED_EOI) break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { /* startup underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } } /* Set state so that jpeg_finish_decompress does the right thing */ cinfo->global_state = DSTATE_STOPPING; } /* At this point we should be in state DSTATE_STOPPING if being used * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access * to the coefficients during a full buffered-image-mode decompression. */ if ((cinfo->global_state == DSTATE_STOPPING || cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { return cinfo->coef->coef_arrays; } /* Oops, improper usage */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return NULL; /* keep compiler happy */ } /* * Master selection of decompression modules for transcoding. * This substitutes for jdmaster.c's initialization of the full decompressor. */ LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo) { /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED jinit_phuff_decoder(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else jinit_huff_decoder(cinfo); } /* Always get a full-image coefficient buffer. */ jinit_d_coef_controller(cinfo, TRUE); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); /* Initialize progress monitoring. */ if (cinfo->progress != NULL) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else if (cinfo->inputctl->has_multiple_scans) { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } else { nscans = 1; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = 1; } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jerror.c ================================================ /* * jerror.c * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains simple error-reporting and trace-message routines. * These are suitable for Unix-like systems and others where writing to * stderr is the right thing to do. Many applications will want to replace * some or all of these routines. * * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, * you get a Windows-specific hack to display error messages in a dialog box. * It ain't much, but it beats dropping error messages into the bit bucket, * which is what happens to output to stderr under most Windows C compilers. * * These routines are used by both the compression and decompression code. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jversion.h" #include "jerror.h" #ifdef USE_WINDOWS_MESSAGEBOX #include #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif /* * Create the message string table. * We do this from the master message list in jerror.h by re-reading * jerror.h with a suitable definition for macro JMESSAGE. * The message table is made an external symbol just in case any applications * want to refer to it directly. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_message_table jMsgTable #endif #define JMESSAGE(code,string) string , const char * const jpeg_std_message_table[] = { #include "jerror.h" NULL }; /* * Error exit handler: must not return to caller. * * Applications may override this if they want to get control back after * an error. Typically one would longjmp somewhere instead of exiting. * The setjmp buffer can be made a private field within an expanded error * handler object. Note that the info needed to generate an error message * is stored in the error object, so you can generate the message now or * later, at your convenience. * You should make sure that the JPEG object is cleaned up (with jpeg_abort * or jpeg_destroy) at some point. */ METHODDEF(void) error_exit (j_common_ptr cinfo) { /* Always display the message */ (*cinfo->err->output_message) (cinfo); /* Let the memory manager delete any temp files before we die */ jpeg_destroy(cinfo); exit(EXIT_FAILURE); } /* * Actual output of an error or trace message. * Applications may override this method to send JPEG messages somewhere * other than stderr. * * On Windows, printing to stderr is generally completely useless, * so we provide optional code to produce an error-dialog popup. * Most Windows applications will still prefer to override this routine, * but if they don't, it'll do something at least marginally useful. * * NOTE: to use the library in an environment that doesn't support the * C stdio library, you may have to delete the call to fprintf() entirely, * not just not use this routine. */ METHODDEF(void) output_message (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); #ifdef USE_WINDOWS_MESSAGEBOX /* Display it in a message dialog box */ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", MB_OK | MB_ICONERROR); #else /* Send it to stderr, adding a newline */ fprintf(stderr, "%s\n", buffer); #endif } /* * Decide whether to emit a trace or warning message. * msg_level is one of: * -1: recoverable corrupt-data warning, may want to abort. * 0: important advisory messages (always display to user). * 1: first level of tracing detail. * 2,3,...: successively more detailed tracing messages. * An application might override this method if it wanted to abort on warnings * or change the policy about which messages to display. */ METHODDEF(void) emit_message (j_common_ptr cinfo, int msg_level) { struct jpeg_error_mgr * err = cinfo->err; if (msg_level < 0) { /* It's a warning message. Since corrupt files may generate many warnings, * the policy implemented here is to show only the first warning, * unless trace_level >= 3. */ if (err->num_warnings == 0 || err->trace_level >= 3) (*err->output_message) (cinfo); /* Always count warnings in num_warnings. */ err->num_warnings++; } else { /* It's a trace message. Show it if trace_level >= msg_level. */ if (err->trace_level >= msg_level) (*err->output_message) (cinfo); } } /* * Format a message string for the most recent JPEG error or message. * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX * characters. Note that no '\n' character is added to the string. * Few applications should need to override this method. */ METHODDEF(void) format_message (j_common_ptr cinfo, char * buffer) { struct jpeg_error_mgr * err = cinfo->err; int msg_code = err->msg_code; const char * msgtext = NULL; const char * msgptr; char ch; boolean isstring; /* Look up message string in proper table */ if (msg_code > 0 && msg_code <= err->last_jpeg_message) { msgtext = err->jpeg_message_table[msg_code]; } else if (err->addon_message_table != NULL && msg_code >= err->first_addon_message && msg_code <= err->last_addon_message) { msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } /* Defend against bogus message number */ if (msgtext == NULL) { err->msg_parm.i[0] = msg_code; msgtext = err->jpeg_message_table[0]; } /* Check for string parameter, as indicated by %s in the message text */ isstring = FALSE; msgptr = msgtext; while ((ch = *msgptr++) != '\0') { if (ch == '%') { if (*msgptr == 's') isstring = TRUE; break; } } /* Format the message into the passed buffer */ if (isstring) sprintf(buffer, msgtext, err->msg_parm.s); else sprintf(buffer, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], err->msg_parm.i[6], err->msg_parm.i[7]); } /* * Reset error state variables at start of a new image. * This is called during compression startup to reset trace/error * processing to default state, without losing any application-specific * method pointers. An application might possibly want to override * this method if it has additional error processing state. */ METHODDEF(void) reset_error_mgr (j_common_ptr cinfo) { cinfo->err->num_warnings = 0; /* trace_level is not reset since it is an application-supplied parameter */ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ } /* * Fill in the standard error-handling methods in a jpeg_error_mgr object. * Typical call is: * struct jpeg_compress_struct cinfo; * struct jpeg_error_mgr err; * * cinfo.err = jpeg_std_error(&err); * after which the application may override some of the methods. */ GLOBAL(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr * err) { err->error_exit = error_exit; err->emit_message = emit_message; err->output_message = output_message; err->format_message = format_message; err->reset_error_mgr = reset_error_mgr; err->trace_level = 0; /* default = no tracing */ err->num_warnings = 0; /* no warnings emitted yet */ err->msg_code = 0; /* may be useful as a flag for "no error" */ /* Initialize message table pointers */ err->jpeg_message_table = jpeg_std_message_table; err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; err->addon_message_table = NULL; err->first_addon_message = 0; /* for safety */ err->last_addon_message = 0; return err; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jerror.h ================================================ /* * jerror.h * * Copyright (C) 1994-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the JPEG library. * Edit this file to add new codes, or to translate the message strings to * some other language. * A set of error-reporting macros are defined too. Some applications using * the JPEG library may wish to include this file to get the error codes * and/or the macros. */ /* * To define the enum list of message codes, include this file without * defining macro JMESSAGE. To create a message string table, include it * again with a suitable JMESSAGE definition (see jerror.c for an example). */ #ifndef JMESSAGE #ifndef JERROR_H /* First time through, define the enum list */ #define JMAKE_ENUM_LIST #else /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ #define JMESSAGE(code,string) #endif /* JERROR_H */ #endif /* JMESSAGE */ #ifdef JMAKE_ENUM_LIST typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_ENUM_LIST */ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_LIB_VERSION, "Wrong JPEG library version: library is %d, caller expects %d") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_PROGRESSION, "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, "Invalid progressive parameters at scan script entry %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") JMESSAGE(JERR_BAD_STRUCT_SIZE, "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") JMESSAGE(JERR_EMS_READ, "Read from EMS failed") JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") JMESSAGE(JERR_FILE_READ, "Input file read error") JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, "Cannot transcode due to multiple use of quantization table %d") JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") JMESSAGE(JERR_QUANT_COMPONENTS, "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") JMESSAGE(JERR_TFILE_WRITE, "Write failed on temporary file --- out of disk space?") JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") JMESSAGE(JERR_XMS_READ, "Read from XMS failed") JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) JMESSAGE(JMSG_VERSION, JVERSION) JMESSAGE(JTRC_16BIT_TABLES, "Caution: quantization tables are too coarse for baseline JPEG") JMESSAGE(JTRC_ADOBE, "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") JMESSAGE(JTRC_DRI, "Define Restart Interval %u") JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") JMESSAGE(JTRC_EOI, "End Of Image") JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, "Warning: thumbnail image size does not match data length %u") JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") JMESSAGE(JTRC_RST, "RST%d") JMESSAGE(JTRC_SMOOTH_NOTIMPL, "Smoothing not supported with nonstandard sampling ratios") JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") JMESSAGE(JTRC_SOI, "Start of Image") JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") JMESSAGE(JTRC_THUMB_JPEG, "JFIF extension marker: JPEG-compressed thumbnail image, length %u") JMESSAGE(JTRC_THUMB_PALETTE, "JFIF extension marker: palette thumbnail image, length %u") JMESSAGE(JTRC_THUMB_RGB, "JFIF extension marker: RGB thumbnail image, length %u") JMESSAGE(JTRC_UNKNOWN_IDS, "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #ifdef JMAKE_ENUM_LIST JMSG_LASTMSGCODE } J_MESSAGE_CODE; #undef JMAKE_ENUM_LIST #endif /* JMAKE_ENUM_LIST */ /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ #undef JMESSAGE #ifndef JERROR_H #define JERROR_H /* Macros to simplify using the error and trace message stuff */ /* The first parameter is either type of cinfo pointer */ /* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT3(cinfo,code,p1,p2,p3) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXITS(cinfo,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define MAKESTMT(stuff) do { stuff } while (0) /* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) /* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS1(cinfo,lvl,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS2(cinfo,lvl,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMSS(cinfo,lvl,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #endif /* JERROR_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jfdctflt.c ================================================ /* * jfdctflt.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a floating-point implementation of the * forward DCT (Discrete Cosine Transform). * * This implementation should be more accurate than either of the integer * DCT implementations. However, it may not give the same results on all * machines because of differences in roundoff behavior. Speed will depend * on the hardware's floating point capacity. * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with a fixed-point * implementation, accuracy is lost due to imprecise representation of the * scaled quantization values. However, that problem does not arise if * we use floating point arithmetic. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_FLOAT_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * Perform the forward DCT on one block of samples. */ GLOBAL(void) jpeg_fdct_float (FAST_FLOAT * data) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; FAST_FLOAT *dataptr; int ctr; /* Pass 1: process rows. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } } #endif /* DCT_FLOAT_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jfdctfst.c ================================================ /* * jfdctfst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a fast, not so accurate integer implementation of the * forward DCT (Discrete Cosine Transform). * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with fixed-point math, * accuracy is lost due to imprecise representation of the scaled * quantization values. The smaller the quantization table entry, the less * precise the scaled value, so this implementation does worse with high- * quality-setting files than with low-quality ones. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_IFAST_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* Scaling decisions are generally the same as in the LL&M algorithm; * see jfdctint.c for more details. However, we choose to descale * (right shift) multiplication products as soon as they are formed, * rather than carrying additional fractional bits into subsequent additions. * This compromises accuracy slightly, but it lets us save a few shifts. * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) * everywhere except in the multiplications proper; this saves a good deal * of work on 16-bit-int machines. * * Again to save a few shifts, the intermediate results between pass 1 and * pass 2 are not upscaled, but are represented only to integral precision. * * A final compromise is to represent the multiplicative constants to only * 8 fractional bits, rather than 13. This saves some shifting work on some * machines, and may also reduce the cost of multiplication (since there * are fewer one-bits in the constants). */ #define CONST_BITS 8 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 8 #define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ #define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ #define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ #define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ #else #define FIX_0_382683433 FIX(0.382683433) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_707106781 FIX(0.707106781) #define FIX_1_306562965 FIX(1.306562965) #endif /* We can gain a little more speed, with a further compromise in accuracy, * by omitting the addition in a descaling shift. This yields an incorrectly * rounded result half the time... */ #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif /* Multiply a DCTELEM variable by an INT32 constant, and immediately * descale to yield a DCTELEM result. */ #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) /* * Perform the forward DCT on one block of samples. */ GLOBAL(void) jpeg_fdct_ifast (DCTELEM * data) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z1, z2, z3, z4, z5, z11, z13; DCTELEM *dataptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = tmp10 + tmp11; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } } #endif /* DCT_IFAST_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jfdctint.c ================================================ /* * jfdctint.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a slow-but-accurate integer implementation of the * forward DCT (Discrete Cosine Transform). * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_ISLOW_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * The poop on this scaling stuff is as follows: * * Each 1-D DCT step produces outputs which are a factor of sqrt(N) * larger than the true DCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D DCT, * because the y0 and y4 outputs need not be divided by sqrt(N). * In the IJG code, this factor of 8 is removed by the quantization step * (in jcdctmgr.c), NOT in this module. * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (For 12-bit sample data, the intermediate * array is INT32 anyway.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. * For 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the forward DCT on one block of samples. */ GLOBAL(void) jpeg_fdct_islow (DCTELEM * data) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; DCTELEM *dataptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ /* Note results are scaled up by sqrt(8) compared to a true DCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } #endif /* DCT_ISLOW_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jidctflt.c ================================================ /* * jidctflt.c * * Copyright (C) 1994-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a floating-point implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * This implementation should be more accurate than either of the integer * IDCT implementations. However, it may not give the same results on all * machines because of differences in roundoff behavior. Speed will depend * on the hardware's floating point capacity. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with a fixed-point * implementation, accuracy is lost due to imprecise representation of the * scaled quantization values. However, that problem does not arise if * we use floating point arithmetic. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_FLOAT_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce a float result. */ #define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) /* * Perform dequantization and inverse DCT on one block of coefficients. */ GLOBAL(void) jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z5, z10, z11, z12, z13; JCOEFPTR inptr; FLOAT_MULT_TYPE * quantptr; FAST_FLOAT * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = tmp0 + tmp2; /* phase 3 */ tmp11 = tmp0 - tmp2; tmp13 = tmp1 + tmp3; /* phases 5-3 */ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; /* phase 2 */ tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z13 = tmp6 + tmp5; /* phase 6 */ z10 = tmp6 - tmp5; z11 = tmp4 + tmp7; z12 = tmp4 - tmp7; tmp7 = z11 + z13; /* phase 5 */ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; wsptr[DCTSIZE*0] = tmp0 + tmp7; wsptr[DCTSIZE*7] = tmp0 - tmp7; wsptr[DCTSIZE*1] = tmp1 + tmp6; wsptr[DCTSIZE*6] = tmp1 - tmp6; wsptr[DCTSIZE*2] = tmp2 + tmp5; wsptr[DCTSIZE*5] = tmp2 - tmp5; wsptr[DCTSIZE*4] = tmp3 + tmp4; wsptr[DCTSIZE*3] = tmp3 - tmp4; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. */ /* Note that we must descale the results by a factor of 8 == 2**3. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * And testing floats for zero is relatively expensive, so we don't bother. */ /* Even part */ tmp10 = wsptr[0] + wsptr[4]; tmp11 = wsptr[0] - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ z13 = wsptr[5] + wsptr[3]; z10 = wsptr[5] - wsptr[3]; z11 = wsptr[1] + wsptr[7]; z12 = wsptr[1] - wsptr[7]; tmp7 = z11 + z13; tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ tmp6 = tmp12 - tmp7; tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; /* Final output stage: scale down by a factor of 8 and range-limit */ outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) & RANGE_MASK]; outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) & RANGE_MASK]; outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) & RANGE_MASK]; outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) & RANGE_MASK]; outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) & RANGE_MASK]; outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) & RANGE_MASK]; outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_FLOAT_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jidctfst.c ================================================ /* * jidctfst.c * * Copyright (C) 1994-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a fast, not so accurate integer implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with fixed-point math, * accuracy is lost due to imprecise representation of the scaled * quantization values. The smaller the quantization table entry, the less * precise the scaled value, so this implementation does worse with high- * quality-setting files than with low-quality ones. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_IFAST_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* Scaling decisions are generally the same as in the LL&M algorithm; * see jidctint.c for more details. However, we choose to descale * (right shift) multiplication products as soon as they are formed, * rather than carrying additional fractional bits into subsequent additions. * This compromises accuracy slightly, but it lets us save a few shifts. * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) * everywhere except in the multiplications proper; this saves a good deal * of work on 16-bit-int machines. * * The dequantized coefficients are not integers because the AA&N scaling * factors have been incorporated. We represent them scaled up by PASS1_BITS, * so that the first and second IDCT rounds have the same input scaling. * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to * avoid a descaling shift; this compromises accuracy rather drastically * for small quantization table entries, but it saves a lot of shifts. * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, * so we use a much larger scaling factor to preserve accuracy. * * A final compromise is to represent the multiplicative constants to only * 8 fractional bits, rather than 13. This saves some shifting work on some * machines, and may also reduce the cost of multiplication (since there * are fewer one-bits in the constants). */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 8 #define PASS1_BITS 2 #else #define CONST_BITS 8 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 8 #define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ #define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ #define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ #define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ #else #define FIX_1_082392200 FIX(1.082392200) #define FIX_1_414213562 FIX(1.414213562) #define FIX_1_847759065 FIX(1.847759065) #define FIX_2_613125930 FIX(2.613125930) #endif /* We can gain a little more speed, with a further compromise in accuracy, * by omitting the addition in a descaling shift. This yields an incorrectly * rounded result half the time... */ #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif /* Multiply a DCTELEM variable by an INT32 constant, and immediately * descale to yield a DCTELEM result. */ #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 * multiplication will do. For 12-bit data, the multiplier table is * declared INT32, so a 32-bit multiply will be used. */ #if BITS_IN_JSAMPLE == 8 #define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) #else #define DEQUANTIZE(coef,quantval) \ DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) #endif /* Like DESCALE, but applies to a DCTELEM and produces an int. * We assume that int right shift is unsigned if INT32 right shift is. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS DCTELEM ishift_temp; #if BITS_IN_JSAMPLE == 8 #define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ #else #define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ #endif #define IRIGHT_SHIFT(x,shft) \ ((ishift_temp = (x)) < 0 ? \ (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif #ifdef USE_ACCURATE_ROUNDING #define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) #else #define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) #endif /* * Perform dequantization and inverse DCT on one block of coefficients. */ GLOBAL(void) jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z5, z10, z11, z12, z13; JCOEFPTR inptr; IFAST_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ ISHIFT_TEMPS /* for IDESCALE */ /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = tmp0 + tmp2; /* phase 3 */ tmp11 = tmp0 - tmp2; tmp13 = tmp1 + tmp3; /* phases 5-3 */ tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; /* phase 2 */ tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z13 = tmp6 + tmp5; /* phase 6 */ z10 = tmp6 - tmp5; z11 = tmp4 + tmp7; z12 = tmp4 - tmp7; tmp7 = z11 + z13; /* phase 5 */ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; outptr[4] = dcval; outptr[5] = dcval; outptr[6] = dcval; outptr[7] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - tmp13; tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; tmp7 = z11 + z13; /* phase 5 */ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; /* Final output stage: scale down by a factor of 8 and range-limit */ outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_IFAST_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jidctint.c ================================================ /* * jidctint.c * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a slow-but-accurate integer implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_ISLOW_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * The poop on this scaling stuff is as follows: * * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) * larger than the true IDCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D IDCT, * because the y0 and y4 inputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data further, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. * For 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce an int result. In this module, both inputs and result * are 16 bits or less, so either int or short multiply will work. */ #define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) /* * Perform dequantization and inverse DCT on one block of coefficients. */ GLOBAL(void) jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; outptr[4] = dcval; outptr[5] = dcval; outptr[6] = dcval; outptr[7] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) wsptr[7]; tmp1 = (INT32) wsptr[5]; tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_ISLOW_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jidctred.c ================================================ /* * jidctred.c * * Copyright (C) 1994-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains inverse-DCT routines that produce reduced-size output: * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. * * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step * with an 8-to-4 step that produces the four averages of two adjacent outputs * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). * These steps were derived by computing the corresponding values at the end * of the normal LL&M code, then simplifying as much as possible. * * 1x1 is trivial: just take the DC coefficient divided by 8. * * See jidctint.c for additional comments. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef IDCT_SCALING_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* Scaling is the same as in jidctint.c. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ #define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ #define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ #define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ #define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ #define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ #else #define FIX_0_211164243 FIX(0.211164243) #define FIX_0_509795579 FIX(0.509795579) #define FIX_0_601344887 FIX(0.601344887) #define FIX_0_720959822 FIX(0.720959822) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_850430095 FIX(0.850430095) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_061594337 FIX(1.061594337) #define FIX_1_272758580 FIX(1.272758580) #define FIX_1_451774981 FIX(1.451774981) #define FIX_1_847759065 FIX(1.847759065) #define FIX_2_172734803 FIX(2.172734803) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_624509785 FIX(3.624509785) #endif /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. * For 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce an int result. In this module, both inputs and result * are 16 bits or less, so either int or short multiply will work. */ #define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 4x4 output block. */ GLOBAL(void) jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE*4]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { /* Don't bother to process column 4, because second pass won't use it */ if (ctr == DCTSIZE-4) continue; if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero; we need not examine term 4 for 4x4 output */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; continue; } /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= (CONST_BITS+1); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ /* Final output stage */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); } /* Pass 2: process 4 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; /* It's not clear whether a zero row test is worthwhile here ... */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; /* Odd part */ z1 = (INT32) wsptr[7]; z2 = (INT32) wsptr[5]; z3 = (INT32) wsptr[3]; z4 = (INT32) wsptr[1]; tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ /* Final output stage */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 2x2 output block. */ GLOBAL(void) jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp10, z1; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE*2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { /* Don't bother to process columns 2,4,6 */ if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) continue; if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; continue; } /* Even part */ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp10 = z1 << (CONST_BITS+2); /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ /* Final output stage */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); } /* Pass 2: process 2 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 2; ctr++) { outptr = output_buf[ctr] + output_col; /* It's not clear whether a zero row test is worthwhile here ... */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); /* Odd part */ tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ /* Final output stage */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3+2) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3+2) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 1x1 output block. */ GLOBAL(void) jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { int dcval; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); SHIFT_TEMPS /* We hardly need an inverse DCT routine for this: just take the * average pixel value, which is one-eighth of the DC coefficient. */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; dcval = DEQUANTIZE(coef_block[0], quantptr[0]); dcval = (int) DESCALE((INT32) dcval, 3); output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; } #endif /* IDCT_SCALING_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jinclude.h ================================================ /* * jinclude.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file exists to provide a single place to fix any problems with * including the wrong system include files. (Common problems are taken * care of by the standard jconfig symbols, but on really weird systems * you may have to edit this file.) * * NOTE: this file is NOT intended to be included by applications using the * JPEG library. Most applications need only include jpeglib.h. */ /* Include auto-config file to find out which system include files we need. */ #include "jconfig.h" /* auto configuration options */ #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ /* * We need the NULL macro and size_t typedef. * On an ANSI-conforming system it is sufficient to include . * Otherwise, we get them from or ; we may have to * pull in as well. * Note that the core JPEG library does not require ; * only the default error handler and data source/destination modules do. * But we must pull it in because of the references to FILE in jpeglib.h. * You can remove those references if you want to compile without . */ #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* * We need memory copying and zeroing functions, plus strncpy(). * ANSI and System V implementations declare these in . * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). * Some systems may declare memset and memcpy in . * * NOTE: we assume the size parameters to these functions are of type size_t. * Change the casts in these macros if not! */ #ifdef NEED_BSD_STRINGS #include #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume ANSI/SysV string lib */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #endif /* * In ANSI C, and indeed any rational implementation, size_t is also the * type returned by sizeof(). However, it seems there are some irrational * implementations out there, in which sizeof() returns an int even though * size_t is defined as long or unsigned long. To ensure consistent results * we always use this SIZEOF() macro in place of using sizeof() directly. */ #define SIZEOF(object) ((size_t) sizeof(object)) /* * The modules that use fread() and fwrite() always invoke them through * these macros. On some systems you may need to twiddle the argument casts. * CAUTION: argument order is different from underlying functions! */ #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmemdatadst.c ================================================ /* Modified to work on memory rather than files. Based on: * * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of * emitting JPEG data to a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data destination object for stdio output */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ char * actualPos; /* points to first byte not yet filled */ unsigned spaceLeft; /* bytes still not filled in destination */ unsigned *pSpaceUsed; /* to answer actual compressed size */ JOCTET * buffer; /* start of buffer */ } my_destination_mgr; typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ METHODDEF(void) init_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } /* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines). The * application should resume compression after it has made more room in the * output buffer. Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */ METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t nbytes; nbytes = (OUTPUT_BUF_SIZE < dest->spaceLeft) ? OUTPUT_BUF_SIZE : dest->spaceLeft; memcpy(dest->actualPos, dest->buffer, nbytes); dest->actualPos = (dest->actualPos) + nbytes; dest->spaceLeft = (dest->spaceLeft) - nbytes; *(dest->pSpaceUsed) = *(dest->pSpaceUsed) + nbytes; if (nbytes != (size_t) OUTPUT_BUF_SIZE) ERREXIT(cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; size_t nbytes; /* Write any data remaining in the buffer */ if (datacount > 0) { nbytes = (datacount < dest->spaceLeft) ? datacount : dest->spaceLeft; memcpy(dest->actualPos, dest->buffer, nbytes); dest->actualPos = dest->actualPos + nbytes; dest->spaceLeft = dest->spaceLeft - nbytes; *(dest->pSpaceUsed) = *(dest->pSpaceUsed) + nbytes; if (nbytes != datacount) ERREXIT(cinfo, JERR_FILE_WRITE); } } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing compression. */ GLOBAL(void) jpeg_mem_dest (j_compress_ptr cinfo, char * pDestination, unsigned *pDestinationSize) { my_dest_ptr dest; /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->actualPos = pDestination; dest->spaceLeft = *pDestinationSize; dest->pSpaceUsed = pDestinationSize; *(dest->pSpaceUsed) = 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmemdatasrc.c ================================================ /* Modified to work on memory rather than files. Based on: * * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ char * pSourceData; /* source data start */ char * actualPos; /* points to first byte not yet delivered */ unsigned bytesLeft; /* bytes still not read in data source */ JOCTET * buffer; /* start of buffer */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF(void) init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; /* We don't clear the input buffer. * This is correct behavior for reading a series of images from one source. */ } /* * Fill the input buffer --- called whenever buffer is emptied. * * In typical applications, this should read fresh data into the buffer * (ignoring the current state of next_input_byte & bytes_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been reloaded. It is not necessary to * fill the buffer entirely, only to obtain at least one more byte. * * There is no such thing as an EOF return. If the end of the file has been * reached, the routine has a choice of ERREXIT() or inserting fake data into * the buffer. In most cases, generating a warning message and inserting a * fake EOI marker is the best course of action --- this will allow the * decompressor to output however much of the image is there. However, * the resulting error message is misleading if the real problem is an empty * input file, so we handle that case specially. * * In applications that need to be able to suspend compression due to input * not being available yet, a FALSE return indicates that no more data can be * obtained right now, but more may be forthcoming later. In this situation, * the decompressor will return to its caller (with an indication of the * number of scanlines it has read, if any). The application should resume * decompression after it has loaded more data into the input buffer. Note * that there are substantial restrictions on the use of suspension --- see * the documentation. * * When suspending, the decompressor will back up to a convenient restart point * (typically the start of the current MCU). next_input_byte & bytes_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point must be rescanned after resumption, so move it to * the front of the buffer rather than discarding it. */ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; nbytes = (INPUT_BUF_SIZE < src->bytesLeft) ? INPUT_BUF_SIZE : src->bytesLeft; memcpy(src->buffer, src->actualPos, nbytes); src->actualPos = src->actualPos + nbytes; src->bytesLeft = src->bytesLeft - nbytes; if (nbytes <= 0) { WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data * is not granted the right to give a suspension return. If the skip extends * beyond the data currently in the buffer, the buffer can be marked empty so * that the next read will cause a fill_input_buffer call that can suspend. * Arranging for additional bytes to be discarded before reloading the input * buffer is the application writer's problem. */ METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) fill_input_buffer(cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for input from a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing decompression. */ GLOBAL(void) jpeg_mem_src (j_decompress_ptr cinfo, char * pSourceData, unsigned sourceDataSize) { my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->pSourceData = pSourceData; src->actualPos = pSourceData; src->bytesLeft = sourceDataSize; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } /* This function allows data to be moved if necessary */ GLOBAL(int) jpeg_mem_src_newLocationOfData (j_decompress_ptr cinfo, char * pSourceData, unsigned sourceDataSize) { my_src_ptr src; unsigned offset; src = (my_src_ptr) cinfo->src; offset = (src->actualPos) - (src->pSourceData); src->pSourceData = pSourceData; src->actualPos = pSourceData + offset; return((src->actualPos + src->bytesLeft) == (pSourceData + sourceDataSize)); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmemmgr.c ================================================ /* * jmemmgr.c * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the JPEG system-independent memory management * routines. This code is usable across a wide variety of machines; most * of the system dependencies have been isolated in a separate file. * The major functions provided here are: * * pool-based allocation and freeing of memory; * * policy decisions about how to divide available memory among the * virtual arrays; * * control logic for swapping virtual arrays between main memory and * backing storage. * The separate system-dependent file provides the actual backing-storage * access code, and it contains the policy decision about how much total * main memory to use. * This file is system-dependent in the sense that some of its functions * are unnecessary in some systems. For example, if there is enough virtual * memory so that backing storage will never be used, much of the virtual * array control logic could be removed. (Of course, if you have that much * memory then you shouldn't care about a little bit of unused code...) */ #define JPEG_INTERNALS #define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef NO_GETENV #ifndef HAVE_STDLIB_H /* should declare getenv() */ extern char * getenv JPP((const char * name)); #endif #endif /* * Some important notes: * The allocation routines provided here must never return NULL. * They should exit to error_exit if unsuccessful. * * It's not a good idea to try to merge the sarray and barray routines, * even though they are textually almost the same, because samples are * usually stored as bytes while coefficients are shorts or ints. Thus, * in machines where byte pointers have a different representation from * word pointers, the resulting machine code could not be the same. */ /* * Many machines require storage alignment: longs must start on 4-byte * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() * always returns pointers that are multiples of the worst-case alignment * requirement, and we had better do so too. * There isn't any really portable way to determine the worst-case alignment * requirement. This module assumes that the alignment requirement is * multiples of sizeof(ALIGN_TYPE). * By default, we define ALIGN_TYPE as double. This is necessary on some * workstations (where doubles really do need 8-byte alignment) and will work * fine on nearly everything. If your machine has lesser alignment needs, * you can save a few bytes by making ALIGN_TYPE smaller. * The only place I know of where this will NOT work is certain Macintosh * 680x0 compilers that define double as a 10-byte IEEE extended float. * Doing 10-byte alignment is counterproductive because longwords won't be * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have * such a compiler. */ #ifndef ALIGN_TYPE /* so can override from jconfig.h */ #define ALIGN_TYPE double #endif /* * We allocate objects from "pools", where each pool is gotten with a single * request to jpeg_get_small() or jpeg_get_large(). There is no per-object * overhead within a pool, except for alignment padding. Each pool has a * header with a link to the next pool of the same class. * Small and large pool headers are identical except that the latter's * link pointer must be FAR on 80x86 machines. * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple * of the alignment requirement of ALIGN_TYPE. */ typedef union small_pool_struct * small_pool_ptr; typedef union small_pool_struct { struct { small_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } small_pool_hdr; typedef union large_pool_struct FAR * large_pool_ptr; typedef union large_pool_struct { struct { large_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } large_pool_hdr; /* * Here is the full definition of a memory manager object. */ typedef struct { struct jpeg_memory_mgr pub; /* public fields */ /* Each pool identifier (lifetime class) names a linked list of pools. */ small_pool_ptr small_list[JPOOL_NUMPOOLS]; large_pool_ptr large_list[JPOOL_NUMPOOLS]; /* Since we only have one lifetime class of virtual arrays, only one * linked list is necessary (for each datatype). Note that the virtual * array control blocks being linked together are actually stored somewhere * in the small-pool list. */ jvirt_sarray_ptr virt_sarray_list; jvirt_barray_ptr virt_barray_list; /* This counts total space obtained from jpeg_get_small/large */ long total_space_allocated; /* alloc_sarray and alloc_barray set this value for use by virtual * array routines. */ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ } my_memory_mgr; typedef my_memory_mgr * my_mem_ptr; /* * The control blocks for virtual arrays. * Note that these blocks are allocated in the "small" pool area. * System-dependent info for the associated backing store (if any) is hidden * inside the backing_store_info struct. */ struct jvirt_sarray_control { JSAMPARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ JDIMENSION first_undef_row; /* row # of first uninitialized row */ boolean pre_zero; /* pre-zero mode requested? */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_sarray_ptr next; /* link to next virtual sarray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; struct jvirt_barray_control { JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ JDIMENSION first_undef_row; /* row # of first uninitialized row */ boolean pre_zero; /* pre-zero mode requested? */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_barray_ptr next; /* link to next virtual barray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; #ifdef MEM_STATS /* optional extra stuff for statistics */ LOCAL(void) print_mem_stats (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; /* Since this is only a debugging stub, we can cheat a little by using * fprintf directly rather than going through the trace message code. * This is helpful because message parm array can't handle longs. */ fprintf(stderr, "Freeing pool %d, total space = %ld\n", pool_id, mem->total_space_allocated); for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; lhdr_ptr = lhdr_ptr->hdr.next) { fprintf(stderr, " Large chunk used %ld\n", (long) lhdr_ptr->hdr.bytes_used); } for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; shdr_ptr = shdr_ptr->hdr.next) { fprintf(stderr, " Small chunk used %ld free %ld\n", (long) shdr_ptr->hdr.bytes_used, (long) shdr_ptr->hdr.bytes_left); } } #endif /* MEM_STATS */ LOCAL(void) out_of_memory (j_common_ptr cinfo, int which) /* Report an out-of-memory error and stop execution */ /* If we compiled MEM_STATS support, report alloc requests before dying */ { #ifdef MEM_STATS cinfo->err->trace_level = 2; /* force self_destruct to report stats */ #endif ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); } /* * Allocation of "small" objects. * * For these, we use pooled storage. When a new pool must be created, * we try to get enough space for the current request plus a "slop" factor, * where the slop will be the amount of leftover space in the new pool. * The speed vs. space tradeoff is largely determined by the slop values. * A different slop value is provided for each pool class (lifetime), * and we also distinguish the first pool of a class from later ones. * NOTE: the values given work fairly well on both 16- and 32-bit-int * machines, but may be too small if longs are 64 bits or more. */ static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { 1600, /* first PERMANENT pool */ 16000 /* first IMAGE pool */ }; static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = { 0, /* additional PERMANENT pools */ 5000 /* additional IMAGE pools */ }; #define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ METHODDEF(void *) alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "small" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr hdr_ptr, prev_hdr_ptr; char * data_ptr; size_t odd_bytes, min_request, slop; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; /* See if space is available in any existing pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ prev_hdr_ptr = NULL; hdr_ptr = mem->small_list[pool_id]; while (hdr_ptr != NULL) { if (hdr_ptr->hdr.bytes_left >= sizeofobject) break; /* found pool with enough space */ prev_hdr_ptr = hdr_ptr; hdr_ptr = hdr_ptr->hdr.next; } /* Time to make a new pool? */ if (hdr_ptr == NULL) { /* min_request is what we need now, slop is what will be leftover */ min_request = sizeofobject + SIZEOF(small_pool_hdr); if (prev_hdr_ptr == NULL) /* first pool in class? */ slop = first_pool_slop[pool_id]; else slop = extra_pool_slop[pool_id]; /* Don't ask for more than MAX_ALLOC_CHUNK */ if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) slop = (size_t) (MAX_ALLOC_CHUNK-min_request); /* Try to get space, if fail reduce slop and try again */ for (;;) { hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); if (hdr_ptr != NULL) break; slop /= 2; if (slop < MIN_SLOP) /* give up when it gets real small */ out_of_memory(cinfo, 2); /* jpeg_get_small failed */ } mem->total_space_allocated += min_request + slop; /* Success, initialize the new pool header and add to end of list */ hdr_ptr->hdr.next = NULL; hdr_ptr->hdr.bytes_used = 0; hdr_ptr->hdr.bytes_left = sizeofobject + slop; if (prev_hdr_ptr == NULL) /* first pool in class? */ mem->small_list[pool_id] = hdr_ptr; else prev_hdr_ptr->hdr.next = hdr_ptr; } /* OK, allocate the object from the current pool */ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ hdr_ptr->hdr.bytes_used += sizeofobject; hdr_ptr->hdr.bytes_left -= sizeofobject; return (void *) data_ptr; } /* * Allocation of "large" objects. * * The external semantics of these are the same as "small" objects, * except that FAR pointers are used on 80x86. However the pool * management heuristics are quite different. We assume that each * request is large enough that it may as well be passed directly to * jpeg_get_large; the pool management just links everything together * so that we can free it all on demand. * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY * structures. The routines that create these structures (see below) * deliberately bunch rows together to ensure a large request size. */ METHODDEF(void FAR *) alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "large" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; large_pool_ptr hdr_ptr; size_t odd_bytes; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; /* Always make a new pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + SIZEOF(large_pool_hdr)); if (hdr_ptr == NULL) out_of_memory(cinfo, 4); /* jpeg_get_large failed */ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); /* Success, initialize the new pool header and add to list */ hdr_ptr->hdr.next = mem->large_list[pool_id]; /* We maintain space counts in each pool header for statistical purposes, * even though they are not needed for allocation. */ hdr_ptr->hdr.bytes_used = sizeofobject; hdr_ptr->hdr.bytes_left = 0; mem->large_list[pool_id] = hdr_ptr; return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ } /* * Creation of 2-D sample arrays. * The pointers are in near heap, the samples themselves in FAR heap. * * To minimize allocation overhead and to allow I/O of large contiguous * blocks, we allocate the sample rows in groups of as many rows as possible * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. * NB: the virtual array control routines, later in this file, know about * this chunking of rows. The rowsperchunk value is left in the mem manager * object so that it can be saved away if this sarray is the workspace for * a virtual array. */ METHODDEF(JSAMPARRAY) alloc_sarray (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows) /* Allocate a 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JSAMPARRAY result; JSAMPROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) samplesperrow * SIZEOF(JSAMPLE)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JSAMPARRAY) alloc_small(cinfo, pool_id, (size_t) (numrows * SIZEOF(JSAMPROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JSAMPROW) alloc_large(cinfo, pool_id, (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow * SIZEOF(JSAMPLE))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += samplesperrow; } } return result; } /* * Creation of 2-D coefficient-block arrays. * This is essentially the same as the code for sample arrays, above. */ METHODDEF(JBLOCKARRAY) alloc_barray (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows) /* Allocate a 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JBLOCKARRAY result; JBLOCKROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) blocksperrow * SIZEOF(JBLOCK)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, (size_t) (numrows * SIZEOF(JBLOCKROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow * SIZEOF(JBLOCK))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += blocksperrow; } } return result; } /* * About virtual array management: * * The above "normal" array routines are only used to allocate strip buffers * (as wide as the image, but just a few rows high). Full-image-sized buffers * are handled as "virtual" arrays. The array is still accessed a strip at a * time, but the memory manager must save the whole array for repeated * accesses. The intended implementation is that there is a strip buffer in * memory (as high as is possible given the desired memory limit), plus a * backing file that holds the rest of the array. * * The request_virt_array routines are told the total size of the image and * the maximum number of rows that will be accessed at once. The in-memory * buffer must be at least as large as the maxaccess value. * * The request routines create control blocks but not the in-memory buffers. * That is postponed until realize_virt_arrays is called. At that time the * total amount of space needed is known (approximately, anyway), so free * memory can be divided up fairly. * * The access_virt_array routines are responsible for making a specific strip * area accessible (after reading or writing the backing file, if necessary). * Note that the access routines are told whether the caller intends to modify * the accessed strip; during a read-only pass this saves having to rewrite * data to disk. The access routines are also responsible for pre-zeroing * any newly accessed rows, if pre-zeroing was requested. * * In current usage, the access requests are usually for nonoverlapping * strips; that is, successive access start_row numbers differ by exactly * num_rows = maxaccess. This means we can get good performance with simple * buffer dump/reload logic, by making the in-memory buffer be a multiple * of the access height; then there will never be accesses across bufferload * boundaries. The code will still work with overlapping access requests, * but it doesn't handle bufferload overlaps very efficiently. */ METHODDEF(jvirt_sarray_ptr) request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION maxaccess) /* Request a virtual 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_sarray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* get control block */ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_sarray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->samplesperrow = samplesperrow; result->maxaccess = maxaccess; result->pre_zero = pre_zero; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ mem->virt_sarray_list = result; return result; } METHODDEF(jvirt_barray_ptr) request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess) /* Request a virtual 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_barray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* get control block */ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_barray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->blocksperrow = blocksperrow; result->maxaccess = maxaccess; result->pre_zero = pre_zero; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_barray_list; /* add to list of virtual arrays */ mem->virt_barray_list = result; return result; } METHODDEF(void) realize_virt_arrays (j_common_ptr cinfo) /* Allocate the in-memory buffers for any unrealized virtual arrays */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; long space_per_minheight, maximum_space, avail_mem; long minheights, max_minheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; /* Compute the minimum space needed (maxaccess rows in each buffer) * and the maximum space needed (full image height in each buffer). * These may be of use to the system-dependent jpeg_mem_available routine. */ space_per_minheight = 0; maximum_space = 0; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ space_per_minheight += (long) sptr->maxaccess * (long) sptr->samplesperrow * SIZEOF(JSAMPLE); maximum_space += (long) sptr->rows_in_array * (long) sptr->samplesperrow * SIZEOF(JSAMPLE); } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ space_per_minheight += (long) bptr->maxaccess * (long) bptr->blocksperrow * SIZEOF(JBLOCK); maximum_space += (long) bptr->rows_in_array * (long) bptr->blocksperrow * SIZEOF(JBLOCK); } } if (space_per_minheight <= 0) return; /* no unrealized arrays, no work */ /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, mem->total_space_allocated); /* If the maximum space needed is available, make all the buffers full * height; otherwise parcel it out with the same number of minheights * in each buffer. */ if (avail_mem >= maximum_space) max_minheights = 1000000000L; else { max_minheights = avail_mem / space_per_minheight; /* If there doesn't seem to be enough space, try to get the minimum * anyway. This allows a "stub" implementation of jpeg_mem_available(). */ if (max_minheights <= 0) max_minheights = 1; } /* Allocate the in-memory buffers and initialize backing store as needed. */ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; if (minheights <= max_minheights) { /* This buffer fits in memory */ sptr->rows_in_mem = sptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); jpeg_open_backing_store(cinfo, & sptr->b_s_info, (long) sptr->rows_in_array * (long) sptr->samplesperrow * (long) SIZEOF(JSAMPLE)); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, sptr->samplesperrow, sptr->rows_in_mem); sptr->rowsperchunk = mem->last_rowsperchunk; sptr->cur_start_row = 0; sptr->first_undef_row = 0; sptr->dirty = FALSE; } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; if (minheights <= max_minheights) { /* This buffer fits in memory */ bptr->rows_in_mem = bptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); jpeg_open_backing_store(cinfo, & bptr->b_s_info, (long) bptr->rows_in_array * (long) bptr->blocksperrow * (long) SIZEOF(JBLOCK)); bptr->b_s_open = TRUE; } bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, bptr->blocksperrow, bptr->rows_in_mem); bptr->rowsperchunk = mem->last_rowsperchunk; bptr->cur_start_row = 0; bptr->first_undef_row = 0; bptr->dirty = FALSE; } } } LOCAL(void) do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than is currently defined */ thisrow = (long) ptr->cur_start_row + i; rows = MIN(rows, (long) ptr->first_undef_row - thisrow); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - thisrow); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } LOCAL(void) do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual coefficient-block array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than is currently defined */ thisrow = (long) ptr->cur_start_row + i; rows = MIN(rows, (long) ptr->first_undef_row - thisrow); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - thisrow); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } METHODDEF(JSAMPARRAY) access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable) /* Access the part of a virtual sample array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_sarray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. * During the initial write pass, we will do no actual read * because the selected part is all undefined. */ do_sarray_io(cinfo, ptr, FALSE); } /* Ensure the accessed part of the array is defined; prezero if needed. * To improve locality of access, we only prezero the part of the array * that the caller is about to access, not the entire in-memory array. */ if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; } if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF(JBLOCKARRAY) access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable) /* Access the part of a virtual block array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_barray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. * During the initial write pass, we will do no actual read * because the selected part is all undefined. */ do_barray_io(cinfo, ptr, FALSE); } /* Ensure the accessed part of the array is defined; prezero if needed. * To improve locality of access, we only prezero the part of the array * that the caller is about to access, not the entire in-memory array. */ if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; } if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } /* * Release all objects belonging to a specified pool. */ METHODDEF(void) free_pool (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; size_t space_freed; if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ #ifdef MEM_STATS if (cinfo->err->trace_level > 1) print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ #endif /* If freeing IMAGE pool, close any virtual arrays first */ if (pool_id == JPOOL_IMAGE) { jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->b_s_open) { /* there may be no backing store */ sptr->b_s_open = FALSE; /* prevent recursive close if error */ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); } } mem->virt_sarray_list = NULL; for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->b_s_open) { /* there may be no backing store */ bptr->b_s_open = FALSE; /* prevent recursive close if error */ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); } } mem->virt_barray_list = NULL; } /* Release large objects */ lhdr_ptr = mem->large_list[pool_id]; mem->large_list[pool_id] = NULL; while (lhdr_ptr != NULL) { large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; space_freed = lhdr_ptr->hdr.bytes_used + lhdr_ptr->hdr.bytes_left + SIZEOF(large_pool_hdr); jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); mem->total_space_allocated -= space_freed; lhdr_ptr = next_lhdr_ptr; } /* Release small objects */ shdr_ptr = mem->small_list[pool_id]; mem->small_list[pool_id] = NULL; while (shdr_ptr != NULL) { small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; space_freed = shdr_ptr->hdr.bytes_used + shdr_ptr->hdr.bytes_left + SIZEOF(small_pool_hdr); jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); mem->total_space_allocated -= space_freed; shdr_ptr = next_shdr_ptr; } } /* * Close up shop entirely. * Note that this cannot be called unless cinfo->mem is non-NULL. */ METHODDEF(void) self_destruct (j_common_ptr cinfo) { int pool; /* Close all backing store, release all memory. * Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { free_pool(cinfo, pool); } /* Release the memory manager control block too. */ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); cinfo->mem = NULL; /* ensures I will be called only once */ jpeg_mem_term(cinfo); /* system-dependent cleanup */ } /* * Memory manager initialization. * When this is called, only the error manager pointer is valid in cinfo! */ GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo) { my_mem_ptr mem; long max_to_use; int pool; size_t test_mac; cinfo->mem = NULL; /* for safety if init fails */ /* Check for configuration errors. * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably * doesn't reflect any real hardware alignment requirement. * The test is a little tricky: for X>0, X and X-1 have no one-bits * in common if and only if X is a power of 2, ie has only one one-bit. * Some compilers may give an "unreachable code" warning here; ignore it. */ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be * a multiple of SIZEOF(ALIGN_TYPE). * Again, an "unreachable code" warning may be ignored here. * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. */ test_mac = (size_t) MAX_ALLOC_CHUNK; if ((long) test_mac != MAX_ALLOC_CHUNK || (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ /* Attempt to allocate memory manager's control block */ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); if (mem == NULL) { jpeg_mem_term(cinfo); /* system-dependent cleanup */ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); } /* OK, fill in the method pointers */ mem->pub.alloc_small = alloc_small; mem->pub.alloc_large = alloc_large; mem->pub.alloc_sarray = alloc_sarray; mem->pub.alloc_barray = alloc_barray; mem->pub.request_virt_sarray = request_virt_sarray; mem->pub.request_virt_barray = request_virt_barray; mem->pub.realize_virt_arrays = realize_virt_arrays; mem->pub.access_virt_sarray = access_virt_sarray; mem->pub.access_virt_barray = access_virt_barray; mem->pub.free_pool = free_pool; mem->pub.self_destruct = self_destruct; /* Make MAX_ALLOC_CHUNK accessible to other modules */ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; /* Initialize working state */ mem->pub.max_memory_to_use = max_to_use; for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { mem->small_list[pool] = NULL; mem->large_list[pool] = NULL; } mem->virt_sarray_list = NULL; mem->virt_barray_list = NULL; mem->total_space_allocated = SIZEOF(my_memory_mgr); /* Declare ourselves open for business */ cinfo->mem = & mem->pub; /* Check for an environment variable JPEGMEM; if found, override the * default max_memory setting from jpeg_mem_init. Note that the * surrounding application may again override this value. * If your system doesn't support getenv(), define NO_GETENV to disable * this feature. */ #ifndef NO_GETENV { char * memenv; if ((memenv = getenv("JPEGMEM")) != NULL) { char ch = 'x'; if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { if (ch == 'm' || ch == 'M') max_to_use *= 1000L; mem->pub.max_memory_to_use = max_to_use * 1000L; } } } #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmemnobs.c ================================================ /* * jmemnobs.c * * Copyright (C) 1992-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a really simple implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that no backing-store files are needed: all required space * can be obtained from malloc(). * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. * Note that the max_memory_to_use option is ignored by this implementation. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL(void) jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are treated the same as "small" ones. * NB: although we include FAR keywords in the routine declarations, * this file won't actually work in 80x86 small/medium model; at least, * you probably won't be able to process useful-size images in only 64KB. */ GLOBAL(void FAR *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) malloc(sizeofobject); } GLOBAL(void) jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { free(object); } /* * This routine computes the total memory space available for allocation. * Here we always say, "we got all you want bud!" */ GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { return max_bytes_needed; } /* * Backing store (temporary file) management. * Since jpeg_mem_available always promised the moon, * this should never be called and we can just error out. */ GLOBAL(void) jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); } /* * These routines take care of any system-dependent initialization and * cleanup required. Here, there isn't any. */ GLOBAL(long) jpeg_mem_init (j_common_ptr cinfo) { return 0; /* just set max_memory_to_use to 0 */ } GLOBAL(void) jpeg_mem_term (j_common_ptr cinfo) { /* no work */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmemsys.h ================================================ /* * jmemsys.h * * Copyright (C) 1992-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file defines the interface between the system-independent * and system-dependent portions of the JPEG memory manager. No other * modules need include it. (The system-independent portion is jmemmgr.c; * there are several different versions of the system-dependent portion.) * * This file works as-is for the system-dependent memory managers supplied * in the IJG distribution. You may need to modify it if you write a * custom memory manager. If system-dependent changes are needed in * this file, the best method is to #ifdef them based on a configuration * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR * and USE_MAC_MEMMGR. */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_get_small jGetSmall #define jpeg_free_small jFreeSmall #define jpeg_get_large jGetLarge #define jpeg_free_large jFreeLarge #define jpeg_mem_available jMemAvail #define jpeg_open_backing_store jOpenBackStore #define jpeg_mem_init jMemInit #define jpeg_mem_term jMemTerm #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* * These two functions are used to allocate and release small chunks of * memory. (Typically the total amount requested through jpeg_get_small is * no more than 20K or so; this will be requested in chunks of a few K each.) * Behavior should be the same as for the standard library functions malloc * and free; in particular, jpeg_get_small must return NULL on failure. * On most systems, these ARE malloc and free. jpeg_free_small is passed the * size of the object being freed, just in case it's needed. * On an 80x86 machine using small-data memory model, these manage near heap. */ EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, size_t sizeofobject)); /* * These two functions are used to allocate and release large chunks of * memory (up to the total free space designated by jpeg_mem_available). * The interface is the same as above, except that on an 80x86 machine, * far pointers are used. On most other machines these are identical to * the jpeg_get/free_small routines; but we keep them separate anyway, * in case a different allocation strategy is desirable for large chunks. */ EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, size_t sizeofobject)); /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may * be requested in a single call to jpeg_get_large (and jpeg_get_small for that * matter, but that case should never come into play). This macro is needed * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. * On those machines, we expect that jconfig.h will provide a proper value. * On machines with 32-bit flat address spaces, any large constant may be used. * * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type * size_t and will be a multiple of sizeof(align_type). */ #ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ #define MAX_ALLOC_CHUNK 1000000000L #endif /* * This routine computes the total space still available for allocation by * jpeg_get_large. If more space than this is needed, backing store will be * used. NOTE: any memory already allocated must not be counted. * * There is a minimum space requirement, corresponding to the minimum * feasible buffer sizes; jmemmgr.c will request that much space even if * jpeg_mem_available returns zero. The maximum space needed, enough to hold * all working storage in memory, is also passed in case it is useful. * Finally, the total space already allocated is passed. If no better * method is available, cinfo->mem->max_memory_to_use - already_allocated * is often a suitable calculation. * * It is OK for jpeg_mem_available to underestimate the space available * (that'll just lead to more backing-store access than is really necessary). * However, an overestimate will lead to failure. Hence it's wise to subtract * a slop factor from the true available space. 5% should be enough. * * On machines with lots of virtual memory, any large constant may be returned. * Conversely, zero may be returned to always use the minimum amount of memory. */ EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated)); /* * This structure holds whatever state is needed to access a single * backing-store object. The read/write/close method pointers are called * by jmemmgr.c to manipulate the backing-store object; all other fields * are private to the system-dependent backing store routines. */ #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ #ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ typedef unsigned short XMSH; /* type of extended-memory handles */ typedef unsigned short EMSH; /* type of expanded-memory handles */ typedef union { short file_handle; /* DOS file handle if it's a temp file */ XMSH xms_handle; /* handle if it's a chunk of XMS */ EMSH ems_handle; /* handle if it's a chunk of EMS */ } handle_union; #endif /* USE_MSDOS_MEMMGR */ #ifdef USE_MAC_MEMMGR /* Mac-specific junk */ #include #endif /* USE_MAC_MEMMGR */ typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ JMETHOD(void, read_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, write_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, close_backing_store, (j_common_ptr cinfo, backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ #ifdef USE_MSDOS_MEMMGR /* For the MS-DOS manager (jmemdos.c), we need: */ handle_union handle; /* reference to backing-store storage object */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else #ifdef USE_MAC_MEMMGR /* For the Mac manager (jmemmac.c), we need: */ short temp_file; /* file reference number to temp file */ FSSpec tempSpec; /* the FSSpec for the temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else /* For a typical implementation with temp files, we need: */ FILE * temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ #endif #endif } backing_store_info; /* * Initial opening of a backing-store object. This must fill in the * read/write/close pointers in the object. The read/write routines * may take an error exit if the specified maximum file size is exceeded. * (If jpeg_mem_available always returns a large value, this routine can * just take an error exit.) */ EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed)); /* * These routines take care of any system-dependent initialization and * cleanup required. jpeg_mem_init will be called before anything is * allocated (and, therefore, nothing in cinfo is of use except the error * manager pointer). It should return a suitable default value for * max_memory_to_use; this may subsequently be overridden by the surrounding * application. (Note that max_memory_to_use is only important if * jpeg_mem_available chooses to consult it ... no one else will.) * jpeg_mem_term may assume that all requested memory has been freed and that * all opened backing-store objects have been closed. */ EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jmorecfg.h ================================================ /* * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains additional configuration options that customize the * JPEG software for special applications or support machine-dependent * optimizations. Most users will not need to touch this file. */ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) * 12 for 12-bit sample values * Only 8 and 12 are legal data precisions for lossy JPEG according to the * JPEG standard, and the IJG code does not support anything else! * We do not support run-time selection of data precision, sorry. */ #define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn * few applications need more than 4 channels (maybe 5 for CMYK + alpha * mask). We recommend 10 as a reasonable compromise; use 4 if you are * really short on memory. (Each allowed component costs a hundred or so * bytes of storage, whether actually used in an image or not.) */ #define MAX_COMPONENTS 10 /* maximum number of image components */ /* * Basic data types. * You may need to change these if you have a machine with unusual data * type sizes; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* Representation of a single sample (pixel element value). * We frequently allocate large arrays of these, so it's important to keep * them small. But if you have memory to burn and access to char or short * arrays is very slow on your hardware, you might want to change these. */ #if BITS_IN_JSAMPLE == 8 /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JSAMPLE; #ifdef CHAR_IS_UNSIGNED #define GETJSAMPLE(value) ((int) (value)) #else #define GETJSAMPLE(value) ((int) (value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* BITS_IN_JSAMPLE == 12 */ /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int * if you have memory to burn and "short" is really slow. */ typedef short JCOEF; /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination * managers, this is also the data type passed to fread/fwrite. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; #define GETJOCTET(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JOCTET; #ifdef CHAR_IS_UNSIGNED #define GETJOCTET(value) (value) #else #define GETJOCTET(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* These typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif /* INT32 must hold at least signed 32-bit values. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore * "unsigned int" is sufficient on all machines. However, if you need to * handle larger images and you don't mind deviating from the spec, you * can change this datatype. */ typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ /* These macros are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions; * in particular, you'll need to do that to make the library a Windows DLL. * Another application is to make all functions global for use with debuggers * or code profilers that require it. */ /* a function called through method pointers: */ #define METHODDEF(type) static type /* a function used only in its module: */ #define LOCAL(type) static type /* a function referenced thru EXTERNs: */ #define GLOBAL(type) type /* a reference to a GLOBAL function: */ #define EXTERN(type) extern type /* This macro is used to declare a "method", that is, a function pointer. * We want to supply prototype parameters if the compiler can cope. * Note that the arglist parameter must be parenthesized! * Again, you can customize this if you need special linkage keywords. */ #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif /* * On a few systems, type boolean and/or its values FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ #ifndef HAVE_BOOLEAN typedef int boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif /* * The remaining options affect code selection within the JPEG library, * but they don't need to be visible to most applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. */ #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * library. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ #define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ #define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ /* Encoder capability options: */ #undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. * The exact same statements apply for progressive JPEG: the default tables * don't work for progressive mode. (This may get fixed, however.) */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ #define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ /* more capability options later, no doubt */ /* * Ordering of RGB data in scanlines passed to or from the application. * If your application wants to deal with data in the order B,G,R, just * change these macros. You can also deal with formats such as R,G,B,X * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing * the offsets will also change the order in which colormap data is organized. * RESTRICTIONS: * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not * useful if you are using JPEG color spaces other than YCbCr or grayscale. * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE * is not 3 (they don't understand about dummy color components!). So you * can't use color quantization if you change that value. */ #define RGB_RED 0 /* Offset of Red in an RGB scanline element */ #define RGB_GREEN 1 /* Offset of Green */ #define RGB_BLUE 2 /* Offset of Blue */ #define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ /* Definitions for speed-related optimizations. */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE #define INLINE /* default is to define it as empty */ #endif #endif /* On some machines (notably 68000 series) "int" is 32 bits, but multiplying * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER * as short on such a machine. MULTIPLIER must be at least 16 bits wide. */ #ifndef MULTIPLIER #define MULTIPLIER int /* type for fastest integer multiply */ #endif /* FAST_FLOAT should be either float or double, whichever is done faster * by your compiler. (Note that this type is only used in the floating point * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) * Typically, float is faster in ANSI C compilers, while double is faster in * pre-ANSI compilers (because they insist on converting to double anyway). * The code below therefore chooses float if we have ANSI-style prototypes. */ #ifndef FAST_FLOAT #ifdef HAVE_PROTOTYPES #define FAST_FLOAT float #else #define FAST_FLOAT double #endif #endif #endif /* JPEG_INTERNAL_OPTIONS */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jpegint.h ================================================ /* * jpegint.h * * Copyright (C) 1991-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides common declarations for the various JPEG modules. * These declarations are considered internal to the JPEG library; most * applications using the library shouldn't need to include this file. */ /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ JBUF_PASS_THRU, /* Plain stripwise operation */ /* Remaining modes require a full-image buffer to have been created */ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ } J_BUF_MODE; /* Values of global_state field (jdapi.c has some dependencies on ordering!) */ #define CSTATE_START 100 /* after create_compress */ #define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ #define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ #define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ #define DSTATE_START 200 /* after create_decompress */ #define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ #define DSTATE_READY 202 /* found SOS, ready for start_decompress */ #define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ #define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ #define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ #define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ #define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ #define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ #define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ #define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ /* Declarations for compression modules */ /* Master control module */ struct jpeg_comp_master { JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_c_main_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); }; /* Compression preprocessing (downsampling input buffer control) */ struct jpeg_c_prep_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail)); }; /* Coefficient buffer control */ struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, JSAMPIMAGE input_buf)); }; /* Colorspace conversion */ struct jpeg_color_converter { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, color_convert, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); }; /* Downsampling */ struct jpeg_downsampler { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, downsample, (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Forward DCT (also controls coefficient quantization) */ struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); /* perhaps this should be an array??? */ JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)); }; /* Entropy encoding */ struct jpeg_entropy_encoder { JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); }; /* Marker writing */ struct jpeg_marker_writer { JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); /* These routines are exported to allow insertion of extra markers */ /* Probably only COM and APPn markers should be written this way */ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, unsigned int datalen)); JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); }; /* Declarations for decompression modules */ /* Master control module */ struct jpeg_decomp_master { JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); /* State variables made visible to other modules */ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ }; /* Input control module */ struct jpeg_input_controller { JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); /* State variables made visible to other modules */ boolean has_multiple_scans; /* True if file has multiple scans */ boolean eoi_reached; /* True when EOI has been consumed */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_d_main_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Coefficient buffer control */ struct jpeg_d_coef_controller { JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; /* Decompression postprocessing (color quantization buffer control) */ struct jpeg_d_post_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Marker reading & parsing */ struct jpeg_marker_reader { JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); /* Read markers until SOS or EOI. * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. */ JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); /* Read a restart marker --- exported for use by entropy decoder only */ jpeg_marker_parser_method read_restart_marker; /* State of marker reader --- nominally internal, but applications * supplying COM or APPn handlers might like to know the state. */ boolean saw_SOI; /* found SOI? */ boolean saw_SOF; /* found SOF? */ int next_restart_num; /* next restart number expected (0-7) */ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ }; /* Entropy decoding */ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); /* This is here to share code between baseline and progressive decoders; */ /* other modules probably should not use it */ boolean insufficient_data; /* set TRUE after emitting warning */ }; /* Inverse DCT (also performs dequantization) */ typedef JMETHOD(void, inverse_DCT_method_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); struct jpeg_inverse_dct { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); /* It is useful to allow each component to have a separate IDCT method. */ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; }; /* Upsampling (note that upsampler must also call color converter) */ struct jpeg_upsampler { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, upsample, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Colorspace conversion */ struct jpeg_color_deconverter { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, color_convert, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)); }; /* Color quantization or color precision reduction */ struct jpeg_color_quantizer { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)); JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); }; /* Miscellaneous useful macros */ #undef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* We assume that right shift corresponds to signed division by 2 with * rounding towards minus infinity. This is correct for typical "arithmetic * shift" instructions that shift in copies of the sign bit. But some * C compilers implement >> with an unsigned shift. For these machines you * must define RIGHT_SHIFT_IS_UNSIGNED. * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. * It is only applied with constant shift counts. SHIFT_TEMPS must be * included in the variables of any routine using RIGHT_SHIFT. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ ((shift_temp = (x)) < 0 ? \ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ (shift_temp >> (shft))) #else #define SHIFT_TEMPS #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jinit_compress_master jICompress #define jinit_c_master_control jICMaster #define jinit_c_main_controller jICMainC #define jinit_c_prep_controller jICPrepC #define jinit_c_coef_controller jICCoefC #define jinit_color_converter jICColor #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT #define jinit_huff_encoder jIHEncoder #define jinit_phuff_encoder jIPHEncoder #define jinit_marker_writer jIMWriter #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC #define jinit_d_coef_controller jIDCoefC #define jinit_d_post_controller jIDPostC #define jinit_input_controller jIInCtlr #define jinit_marker_reader jIMReader #define jinit_huff_decoder jIHDecoder #define jinit_phuff_decoder jIPHDecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor #define jinit_1pass_quantizer jI1Quant #define jinit_2pass_quantizer jI2Quant #define jinit_merged_upsampler jIMUpsampler #define jinit_memory_mgr jIMemMgr #define jdiv_round_up jDivRound #define jround_up jRound #define jcopy_sample_rows jCopySamples #define jcopy_block_row jCopyBlocks #define jzero_far jZeroFar #define jpeg_zigzag_order jZIGTable #define jpeg_natural_order jZAGTable #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Compression module initialization routines */ EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, boolean transcode_only)); EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); /* Memory manager initialization */ EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); /* Utility routines in jutils.c */ EXTERN(long) jdiv_round_up JPP((long a, long b)); EXTERN(long) jround_up JPP((long a, long b)); EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols)); EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); /* Constant tables in jutils.c */ #if 0 /* This table is not actually needed in v6a */ extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ /* Suppress undefined-structure complaints if necessary. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; #endif #endif /* INCOMPLETE_TYPES_BROKEN */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jpeglib.h ================================================ /* * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the application interface for the JPEG library. * Most applications using the library need only include this file, * and perhaps jerror.h if they want to know the exact error codes. */ #ifndef JPEGLIB_H #define JPEGLIB_H /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be * generated automatically for many systems. jmorecfg.h contains * manual configuration options that most people need not worry about. */ #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ #include "jconfig.h" /* widely used configuration options */ #endif #include "jmorecfg.h" /* seldom changed options */ /* Version ID for the JPEG library. * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". */ #define JPEG_LIB_VERSION 62 /* Version 6b */ /* Various constants determining the sizes of things. * All of these are specified by the JPEG standard, so don't change them * if you want to be compatible. */ #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU * to handle it. We even let you do this from the jconfig.h file. However, * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe * sometimes emits noncompliant files doesn't mean you should too. */ #define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ #ifndef D_MAX_BLOCKS_IN_MCU #define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ #endif /* Data structures for images (arrays of samples and of DCT coefficients). * On 80x86 machines, the image arrays are too big for near pointers, * but the pointer arrays can fit in near memory. */ typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ /* Types for JPEG compression parameters and working tables. */ /* DCT coefficient quantization tables. */ typedef struct { /* This array gives the coefficient quantizers in natural array order * (not the zigzag order in which they are stored in a JPEG DQT marker). * CAUTION: IJG versions prior to v6a kept this array in zigzag order. */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ } JQUANT_TBL; /* Huffman coding tables. */ typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ } JHUFF_TBL; /* Basic info about one component (color channel). */ typedef struct { /* These values are fixed over the whole image. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOF marker. */ int component_id; /* identifier for this component (0..255) */ int component_index; /* its index in SOF or cinfo->comp_info[] */ int h_samp_factor; /* horizontal sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */ int quant_tbl_no; /* quantization table selector (0..3) */ /* These values may vary between scans. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOS marker. */ /* The decompressor output side may not use these variables. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ /* Component's size in DCT blocks. * Any dummy blocks added to complete an MCU are not counted; therefore * these values do not depend on whether a scan is interleaved or not. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; /* Size of a DCT block in samples. Always DCTSIZE for compression. * For decompression this is the size of the output from one DCT block, * reflecting any scaling we choose to apply during the IDCT step. * Values of 1,2,4,8 are likely to be supported. Note that different * components may receive different IDCT scalings. */ int DCT_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface), thus * downsampled_width = ceil(image_width * Hi/Hmax) * and similarly for height. For decompression, IDCT scaling is included, so * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ /* This flag is used only for decompression. In cases where some of the * components will be ignored (eg grayscale output from YCbCr image), * we can skip most computations for the unused components. */ boolean component_needed; /* do we need the value of this component? */ /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ /* Saved quantization table for component; NULL if none yet saved. * See jdinput.c comments about the need for this information. * This field is currently used only for decompression. */ JQUANT_TBL * quant_table; /* Private per-component storage for DCT or IDCT subsystem. */ void * dct_table; } jpeg_component_info; /* The script for encoding a multiple-scan file is an array of these: */ typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ int Ss, Se; /* progressive JPEG spectral selection parms */ int Ah, Al; /* progressive JPEG successive approx. parms */ } jpeg_scan_info; /* The decompressor can save APPn and COM markers in a list of these: */ typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; struct jpeg_marker_struct { jpeg_saved_marker_ptr next; /* next in list, or NULL */ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ unsigned int original_length; /* # bytes of data in the file */ unsigned int data_length; /* # bytes of data saved at data[] */ JOCTET FAR * data; /* the data contained in the marker */ /* the marker length word is not counted in data_length or original_length */ }; /* Known color spaces. */ typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ JCS_RGB, /* red/green/blue */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ JCS_CMYK, /* C/M/Y/K */ JCS_YCCK /* Y/Cb/Cr/K */ } J_COLOR_SPACE; /* DCT/IDCT algorithm options. */ typedef enum { JDCT_ISLOW, /* slow but accurate integer algorithm */ JDCT_IFAST, /* faster, less accurate integer method */ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ } J_DCT_METHOD; #ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ #define JDCT_DEFAULT JDCT_ISLOW #endif #ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ #define JDCT_FASTEST JDCT_IFAST #endif /* Dithering options for decompression. */ typedef enum { JDITHER_NONE, /* no dithering */ JDITHER_ORDERED, /* simple ordered dither */ JDITHER_FS /* Floyd-Steinberg error diffusion dither */ } J_DITHER_MODE; /* Common fields between JPEG compression and decompression master structs. */ #define jpeg_common_fields \ struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ void * client_data; /* Available for use by application */\ boolean is_decompressor; /* So common code can tell which is which */\ int global_state /* For checking call sequence validity */ /* Routines that are to be used by both halves of the library are declared * to receive a pointer to this structure. There are no actual instances of * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. */ struct jpeg_common_struct { jpeg_common_fields; /* Fields common to both master struct types */ /* Additional fields follow in an actual jpeg_compress_struct or * jpeg_decompress_struct. All three structs must agree on these * initial fields! (This would be a lot cleaner in C++.) */ }; typedef struct jpeg_common_struct * j_common_ptr; typedef struct jpeg_compress_struct * j_compress_ptr; typedef struct jpeg_decompress_struct * j_decompress_ptr; /* Master record for a compression instance */ struct jpeg_compress_struct { jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ /* Destination for compressed data */ struct jpeg_destination_mgr * dest; /* Description of source image --- these fields must be filled in by * outer application before starting compression. in_color_space must * be correct before you can even call jpeg_set_defaults(). */ JDIMENSION image_width; /* input image width */ JDIMENSION image_height; /* input image height */ int input_components; /* # of color components in input image */ J_COLOR_SPACE in_color_space; /* colorspace of input image */ double input_gamma; /* image gamma of input image */ /* Compression parameters --- these fields must be set before calling * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to * initialize everything to reasonable defaults, then changing anything * the application specifically wants to change. That way you won't get * burnt when new parameters are added. Also note that there are several * helper routines to simplify changing parameters. */ int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ int num_scans; /* # of entries in scan_info array */ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ /* The default value of scan_info is NULL, which causes a single-scan * sequential JPEG file to be emitted. To create a multi-scan file, * set num_scans and scan_info to point to an array of scan definitions. */ boolean raw_data_in; /* TRUE=caller supplies downsampled data */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ /* The restart interval can be specified in absolute MCUs by setting * restart_interval, or in MCU rows by setting restart_in_rows * (in which case the correct restart_interval will be figured * for each scan). */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ int restart_in_rows; /* if > 0, MCU rows per restart interval */ /* Parameters controlling emission of special markers. */ boolean write_JFIF_header; /* should a JFIF marker be written? */ UINT8 JFIF_major_version; /* What to write for the JFIF version number */ UINT8 JFIF_minor_version; /* These three values are not used by the JPEG code, merely copied */ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ /* ratio is defined by X_density/Y_density even when density_unit=0. */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ /* State variable: index of next scanline to be written to * jpeg_write_scanlines(). Application may use this to control its * processing loop, e.g., "while (next_scanline < image_height)". */ JDIMENSION next_scanline; /* 0 .. image_height-1 */ /* Remaining fields are known throughout compressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during compression startup */ boolean progressive_mode; /* TRUE if scan script uses progressive mode */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ /* The coefficient controller receives data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). * There are v_samp_factor * DCTSIZE sample rows of each component in an * "iMCU" (interleaved MCU) row. */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ /* * Links to compression subobjects (methods and private variables of modules) */ struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; struct jpeg_c_coef_controller * coef; struct jpeg_marker_writer * marker; struct jpeg_color_converter * cconvert; struct jpeg_downsampler * downsample; struct jpeg_forward_dct * fdct; struct jpeg_entropy_encoder * entropy; jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ int script_space_size; }; /* Master record for a decompression instance */ struct jpeg_decompress_struct { jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ /* Source of compressed data */ struct jpeg_source_mgr * src; /* Basic description of image --- filled in by jpeg_read_header(). */ /* Application may inspect these values to decide how to process image. */ JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_height; /* nominal image height */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ /* Decompression processing parameters --- these fields must be set before * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes * them to default values. */ J_COLOR_SPACE out_color_space; /* colorspace for output */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ double output_gamma; /* image gamma wanted in output */ boolean buffered_image; /* TRUE=multiple output passes */ boolean raw_data_out; /* TRUE=downsampled data wanted */ J_DCT_METHOD dct_method; /* IDCT algorithm selector */ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ boolean quantize_colors; /* TRUE=colormapped output wanted */ /* the following are ignored if not quantize_colors: */ J_DITHER_MODE dither_mode; /* type of color dithering to use */ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ int desired_number_of_colors; /* max # colors to use in created colormap */ /* these are significant only in buffered-image mode: */ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ boolean enable_external_quant;/* enable future use of external colormap */ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ /* Description of actual output image that will be returned to application. * These fields are computed by jpeg_start_decompress(). * You can also use jpeg_calc_output_dimensions() to determine these values * in advance of calling jpeg_start_decompress(). */ JDIMENSION output_width; /* scaled image width */ JDIMENSION output_height; /* scaled image height */ int out_color_components; /* # of color components in out_color_space */ int output_components; /* # of color components returned */ /* output_components is 1 (a colormap index) when quantizing colors; * otherwise it equals out_color_components. */ int rec_outbuf_height; /* min recommended height of scanline buffer */ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows * high, space and time will be wasted due to unnecessary data copying. * Usually rec_outbuf_height will be 1 or 2, at most 4. */ /* When quantizing colors, the output colormap is described by these fields. * The application can supply a colormap by setting colormap non-NULL before * calling jpeg_start_decompress; otherwise a colormap is created during * jpeg_start_decompress or jpeg_start_output. * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ /* State variables: these variables indicate the progress of decompression. * The application may examine these but must not modify them. */ /* Row index of next scanline to be read from jpeg_read_scanlines(). * Application may use this to control its processing loop, e.g., * "while (output_scanline < output_height)". */ JDIMENSION output_scanline; /* 0 .. output_height-1 */ /* Current input scan number and number of iMCU rows completed in scan. * These indicate the progress of the decompressor input side. */ int input_scan_number; /* Number of SOS markers seen so far */ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ /* The "output scan number" is the notional scan being displayed by the * output side. The decompressor will not allow output scan/row number * to get ahead of input scan/row, but it can fall arbitrarily far behind. */ int output_scan_number; /* Nominal scan number being displayed */ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ /* Current progression status. coef_bits[c][i] indicates the precision * with which component c's DCT coefficient i (in zigzag order) is known. * It is -1 when no data has yet been received, otherwise it is the point * transform (shift) value for the most recent scan of the coefficient * (thus, 0 at completion of the progression). * This pointer is NULL when reading a non-progressive file. */ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ /* Internal JPEG parameters --- the application usually need not look at * these fields. Note that the decompressor output side may not use * any parameters that can change between scans. */ /* Quantization and Huffman tables are carried forward across input * datastreams when processing abbreviated JPEG datastreams. */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ /* These parameters are never carried across datastreams, since they * are given in SOF/SOS markers or defined to be reset by SOI. */ int data_precision; /* bits of precision in image data */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ /* These fields record data obtained from optional markers recognized by * the JPEG library. */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ UINT8 JFIF_major_version; /* JFIF version number */ UINT8 JFIF_minor_version; UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ /* Aside from the specific data retained from APPn markers known to the * library, the uninterpreted contents of any or all APPn and COM markers * can be saved in a list for examination by the application. */ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ /* Remaining fields are known throughout decompressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during decompression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ /* The coefficient controller's input and output progress is measured in * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows * in fully interleaved JPEG scans, but are used whether the scan is * interleaved or not. We define an iMCU row as v_samp_factor DCT block * rows of each component. Therefore, the IDCT output contains * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. * Note that the decompressor output side must not use these fields. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[D_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. */ int unread_marker; /* * Links to decompression subobjects (methods, private variables of modules) */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; struct jpeg_d_coef_controller * coef; struct jpeg_d_post_controller * post; struct jpeg_input_controller * inputctl; struct jpeg_marker_reader * marker; struct jpeg_entropy_decoder * entropy; struct jpeg_inverse_dct * idct; struct jpeg_upsampler * upsample; struct jpeg_color_deconverter * cconvert; struct jpeg_color_quantizer * cquantize; }; /* "Object" declarations for JPEG modules that may be supplied or called * directly by the surrounding application. * As with all objects in the JPEG library, these structs only define the * publicly visible methods and state variables of a module. Additional * private fields may exist after the public ones. */ /* Error handler object */ struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ JMETHOD(void, error_exit, (j_common_ptr cinfo)); /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); /* Routine that actually outputs a trace or error message */ JMETHOD(void, output_message, (j_common_ptr cinfo)); /* Format a message string for the most recent JPEG error or message */ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ int msg_code; #define JMSG_STR_PARM_MAX 80 union { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; /* Standard state variables for error facility */ int trace_level; /* max msg_level that will be displayed */ /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application * can check for bad data by seeing if num_warnings is nonzero at the * end of processing. */ long num_warnings; /* number of corrupt-data warnings */ /* These fields point to the table(s) of error message strings. * An application can change the table pointer to switch to a different * message list (typically, to change the language in which errors are * reported). Some applications may wish to add additional error codes * that will be handled by the JPEG library error mechanism; the second * table pointer is used for this purpose. * * First table includes all errors generated by JPEG library itself. * Error code 0 is reserved for a "no such error string" message. */ const char * const * jpeg_message_table; /* Library errors */ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ /* Second table can be added by application (see cjpeg/djpeg for example). * It contains strings numbered first_addon_message..last_addon_message. */ const char * const * addon_message_table; /* Non-library errors */ int first_addon_message; /* code for first string in addon table */ int last_addon_message; /* code for last string in addon table */ }; /* Progress monitor object */ struct jpeg_progress_mgr { JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); long pass_counter; /* work units completed in this pass */ long pass_limit; /* total number of work units in this pass */ int completed_passes; /* passes completed so far */ int total_passes; /* total number of passes expected */ }; /* Data destination object for compression */ struct jpeg_destination_mgr { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ JMETHOD(void, init_destination, (j_compress_ptr cinfo)); JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); JMETHOD(void, term_destination, (j_compress_ptr cinfo)); }; /* Data source object for decompression */ struct jpeg_source_mgr { const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ JMETHOD(void, init_source, (j_decompress_ptr cinfo)); JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); JMETHOD(void, term_source, (j_decompress_ptr cinfo)); }; /* Memory manager object. * Allocates "small" objects (a few K total), "large" objects (tens of K), * and "really big" objects (virtual arrays with backing store if needed). * The memory manager does not allow individual objects to be freed; rather, * each created object is assigned to a pool, and whole pools can be freed * at once. This is faster and more convenient than remembering exactly what * to free, especially where malloc()/free() are not too speedy. * NB: alloc routines never return NULL. They exit to error_exit if not * successful. */ #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_NUMPOOLS 2 typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION maxaccess)); JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess)); JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); /* Limit on memory allocation for this JPEG object. (Note that this is * merely advisory, not a guaranteed maximum; it only affects the space * used for virtual-array buffers.) May be changed by outer application * after creating the JPEG object. */ long max_memory_to_use; /* Maximum allocation request accepted by alloc_large. */ long max_alloc_chunk; }; /* Routine signature for application-supplied marker processing methods. * Need not pass marker code since it is stored in cinfo->unread_marker. */ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); /* Declarations for routines called by application. * The JPP macro hides prototype parameters from compilers that can't cope. * Note JPP requires double parentheses. */ #ifdef HAVE_PROTOTYPES #define JPP(arglist) arglist #else #define JPP(arglist) () #endif /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_error jStdError #define jpeg_CreateCompress jCreaCompress #define jpeg_CreateDecompress jCreaDecompress #define jpeg_destroy_compress jDestCompress #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_default_colorspace jDefColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_simple_progression jSimProgress #define jpeg_suppress_tables jSuppressTables #define jpeg_alloc_quant_table jAlcQTable #define jpeg_alloc_huff_table jAlcHTable #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress #define jpeg_write_raw_data jWrtRawData #define jpeg_write_marker jWrtMarker #define jpeg_write_m_header jWrtMHeader #define jpeg_write_m_byte jWrtMByte #define jpeg_write_tables jWrtTables #define jpeg_read_header jReadHeader #define jpeg_start_decompress jStrtDecompress #define jpeg_read_scanlines jReadScanlines #define jpeg_finish_decompress jFinDecompress #define jpeg_read_raw_data jReadRawData #define jpeg_has_multiple_scans jHasMultScn #define jpeg_start_output jStrtOutput #define jpeg_finish_output jFinOutput #define jpeg_input_complete jInComplete #define jpeg_new_colormap jNewCMap #define jpeg_consume_input jConsumeInput #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_save_markers jSaveMarkers #define jpeg_set_marker_processor jSetMarker #define jpeg_read_coefficients jReadCoefs #define jpeg_write_coefficients jWrtCoefs #define jpeg_copy_critical_parameters jCopyCrit #define jpeg_abort_compress jAbrtCompress #define jpeg_abort_decompress jAbrtDecompress #define jpeg_abort jAbort #define jpeg_destroy jDestroy #define jpeg_resync_to_restart jResyncRestart #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Default error-management setup */ EXTERN(struct jpeg_error_mgr *) jpeg_std_error JPP((struct jpeg_error_mgr * err)); /* Initialization of JPEG compression objects. * jpeg_create_compress() and jpeg_create_decompress() are the exported * names that applications should call. These expand to calls on * jpeg_CreateCompress and jpeg_CreateDecompress with additional information * passed for version mismatch checking. * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. */ #define jpeg_create_compress(cinfo) \ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_compress_struct)) #define jpeg_create_decompress(cinfo) \ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_decompress_struct)) EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, int version, size_t structsize)); EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, int version, size_t structsize)); /* Destruction of JPEG compression objects */ EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); /* Standard data source and destination managers: stdio streams. */ /* Caller is responsible for opening the file before and closing after. */ EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, J_COLOR_SPACE colorspace)); EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, boolean force_baseline)); EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); EXTERN(int) jpeg_quality_scaling JPP((int quality)); EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, boolean suppress)); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); /* Main entry points for compression */ EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, boolean write_all_tables)); EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines)); /* Write a special marker. See libjpeg.doc concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, const JOCTET * dataptr, unsigned int datalen)); /* Same, but piecemeal. */ EXTERN(void) jpeg_write_m_header JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); EXTERN(void) jpeg_write_m_byte JPP((j_compress_ptr cinfo, int val)); /* Alternate compression function: just write an abbreviated table file */ EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); /* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, boolean require_image)); /* Return value is one of: */ #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ #define JPEG_HEADER_OK 1 /* Found valid image datastream */ #define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ /* If you pass require_image = TRUE (normal case), you need not check for * a TABLES_ONLY return code; an abbreviated file will cause an error exit. * JPEG_SUSPENDED is only possible if you use a data source module that can * give a suspension return (the stdio source module doesn't). */ /* Main entry points for decompression */ EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines)); EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines)); /* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, int scan_number)); EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); /* Return value is one of: */ /* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ #define JPEG_REACHED_SOS 1 /* Reached start of new scan */ #define JPEG_REACHED_EOI 2 /* Reached end of image */ #define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ /* Precalculate output dimensions for current decompression parameters. */ EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ EXTERN(void) jpeg_save_markers JPP((j_decompress_ptr cinfo, int marker_code, unsigned int length_limit)); /* Install a special processing method for COM or APPn markers. */ EXTERN(void) jpeg_set_marker_processor JPP((j_decompress_ptr cinfo, int marker_code, jpeg_marker_parser_method routine)); /* Read or write raw DCT coefficients --- useful for lossless transcoding. */ EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo)); /* If you choose to abort compression or decompression before completing * jpeg_finish_(de)compress, then you need to clean up to release memory, * temporary files, etc. You can just call jpeg_destroy_(de)compress * if you're done with the JPEG object, but if you want to clean it up and * reuse it, call this: */ EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); /* Generic versions of jpeg_abort and jpeg_destroy that work on either * flavor of JPEG object. These may be more convenient in some places. */ EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); /* Default restart-marker-resync procedure for use by data source modules */ EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, int desired)); /* These marker codes are exported since applications and data source modules * are likely to want to use them. */ #define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_COM 0xFE /* COM marker code */ /* If we have a brain-damaged compiler that emits warnings (or worse, errors) * for structure definitions that are never filled in, keep it quiet by * supplying dummy definitions for the various substructures. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; struct jpeg_comp_master { long dummy; }; struct jpeg_c_main_controller { long dummy; }; struct jpeg_c_prep_controller { long dummy; }; struct jpeg_c_coef_controller { long dummy; }; struct jpeg_marker_writer { long dummy; }; struct jpeg_color_converter { long dummy; }; struct jpeg_downsampler { long dummy; }; struct jpeg_forward_dct { long dummy; }; struct jpeg_entropy_encoder { long dummy; }; struct jpeg_decomp_master { long dummy; }; struct jpeg_d_main_controller { long dummy; }; struct jpeg_d_coef_controller { long dummy; }; struct jpeg_d_post_controller { long dummy; }; struct jpeg_input_controller { long dummy; }; struct jpeg_marker_reader { long dummy; }; struct jpeg_entropy_decoder { long dummy; }; struct jpeg_inverse_dct { long dummy; }; struct jpeg_upsampler { long dummy; }; struct jpeg_color_deconverter { long dummy; }; struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ /* * The JPEG library modules define JPEG_INTERNALS before including this file. * The internal structure declarations are read only when that is true. * Applications using the library should not include jpegint.h, but may wish * to include jerror.h. */ #ifdef JPEG_INTERNALS #include "jpegint.h" /* fetch private declarations */ #include "jerror.h" /* fetch error codes too */ #endif #endif /* JPEGLIB_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jquant1.c ================================================ /* * jquant1.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 1-pass color quantization (color mapping) routines. * These routines provide mapping to a fixed color map using equally spaced * color values. Optional Floyd-Steinberg or ordered dithering is available. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_1PASS_SUPPORTED /* * The main purpose of 1-pass quantization is to provide a fast, if not very * high quality, colormapped output capability. A 2-pass quantizer usually * gives better visual quality; however, for quantized grayscale output this * quantizer is perfectly adequate. Dithering is highly recommended with this * quantizer, though you can turn it off if you really want to. * * In 1-pass quantization the colormap must be chosen in advance of seeing the * image. We use a map consisting of all combinations of Ncolors[i] color * values for the i'th component. The Ncolors[] values are chosen so that * their product, the total number of colors, is no more than that requested. * (In most cases, the product will be somewhat less.) * * Since the colormap is orthogonal, the representative value for each color * component can be determined without considering the other components; * then these indexes can be combined into a colormap index by a standard * N-dimensional-array-subscript calculation. Most of the arithmetic involved * can be precalculated and stored in the lookup table colorindex[]. * colorindex[i][j] maps pixel value j in component i to the nearest * representative value (grid plane) for that component; this index is * multiplied by the array stride for component i, so that the * index of the colormap entry closest to a given pixel value is just * sum( colorindex[component-number][pixel-component-value] ) * Aside from being fast, this scheme allows for variable spacing between * representative values with no additional lookup cost. * * If gamma correction has been applied in color conversion, it might be wise * to adjust the color grid spacing so that the representative colors are * equidistant in linear space. At this writing, gamma correction is not * implemented by jdcolor, so nothing is done here. */ /* Declarations for ordered dithering. * * We use a standard 16x16 ordered dither array. The basic concept of ordered * dithering is described in many references, for instance Dale Schumacher's * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). * In place of Schumacher's comparisons against a "threshold" value, we add a * "dither" value to the input pixel and then round the result to the nearest * output value. The dither value is equivalent to (0.5 - threshold) times * the distance between output values. For ordered dithering, we assume that * the output colors are equally spaced; if not, results will probably be * worse, since the dither may be too much or too little at a given point. * * The normal calculation would be to form pixel value + dither, range-limit * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. * We can skip the separate range-limiting step by extending the colorindex * table in both directions. */ #define ODITHER_SIZE 16 /* dimension of dither matrix */ /* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ #define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ #define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { /* Bayer's order-4 dither array. Generated by the code given in * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. * The values in this array must range from 0 to ODITHER_CELLS-1. */ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } }; /* Declarations for Floyd-Steinberg dithering. * * Errors are accumulated into the array fserrors[], at a resolution of * 1/16th of a pixel count. The error at a given pixel is propagated * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * * We can get away with a single array (holding one row's worth of errors) * by using it to store the current row's errors at pixel columns not yet * processed, but the next row's errors at columns already processed. We * need only a few extra variables to hold the errors immediately around the * current column. (If we are lucky, those variables are in registers, but * even if not, they're probably cheaper to access than array elements are.) * * The fserrors[] array is indexed [component#][position]. * We provide (#columns + 2) entries per component; the extra entry at each * end saves us from special-casing the first and last pixels. * * Note: on a wide image, we might not have enough room in a PC's near data * segment to hold the error array; so it is allocated with alloc_large. */ #if BITS_IN_JSAMPLE == 8 typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else typedef INT32 FSERROR; /* may need more than 16 bits */ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ /* Private subobject */ #define MAX_Q_COMPS 4 /* max components I can handle */ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Initially allocated colormap is saved here */ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ int sv_actual; /* number of entries in use */ JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into * JSAMPLEs, the entries of this array will too. */ boolean is_padded; /* is the colorindex padded for odither? */ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ /* Variables for ordered dithering */ int row_index; /* cur row's vertical index in dither matrix */ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ /* Variables for Floyd-Steinberg dithering */ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ boolean on_odd_row; /* flag to remember which row we are on */ } my_cquantizer; typedef my_cquantizer * my_cquantize_ptr; /* * Policy-making subroutines for create_colormap and create_colorindex. * These routines determine the colormap to be used. The rest of the module * only assumes that the colormap is orthogonal. * * * select_ncolors decides how to divvy up the available colors * among the components. * * output_value defines the set of representative values for a component. * * largest_input_value defines the mapping from input values to * representative values for a component. * Note that the latter two routines may impose different policies for * different components, though this is not currently done. */ LOCAL(int) select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) /* Determine allocation of desired colors to components, */ /* and fill in Ncolors[] array to indicate choice. */ /* Return value is total number of colors (product of Ncolors[] values). */ { int nc = cinfo->out_color_components; /* number of color components */ int max_colors = cinfo->desired_number_of_colors; int total_colors, iroot, i, j; boolean changed; long temp; static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; /* We can allocate at least the nc'th root of max_colors per component. */ /* Compute floor(nc'th root of max_colors). */ iroot = 1; do { iroot++; temp = iroot; /* set temp = iroot ** nc */ for (i = 1; i < nc; i++) temp *= iroot; } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ iroot--; /* now iroot = floor(root) */ /* Must have at least 2 color values per component */ if (iroot < 2) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); /* Initialize to iroot color values for each component */ total_colors = 1; for (i = 0; i < nc; i++) { Ncolors[i] = iroot; total_colors *= iroot; } /* We may be able to increment the count for one or more components without * exceeding max_colors, though we know not all can be incremented. * Sometimes, the first component can be incremented more than once! * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) * In RGB colorspace, try to increment G first, then R, then B. */ do { changed = FALSE; for (i = 0; i < nc; i++) { j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); /* calculate new total_colors if Ncolors[j] is incremented */ temp = total_colors / Ncolors[j]; temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ if (temp > (long) max_colors) break; /* won't fit, done with this pass */ Ncolors[j]++; /* OK, apply the increment */ total_colors = (int) temp; changed = TRUE; } } while (changed); return total_colors; } LOCAL(int) output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ /* The output values must fall in 0..MAXJSAMPLE in increasing order */ { /* We always provide values 0 and MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); } LOCAL(int) largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); } /* * Create the colormap. */ LOCAL(void) create_colormap (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colormap; /* Created colormap */ int total_colors; /* Number of distinct output colors */ int i,j,k, nci, blksize, blkdist, ptr, val; /* Select number of colors for each component */ total_colors = select_ncolors(cinfo, cquantize->Ncolors); /* Report selected color counts */ if (cinfo->out_color_components == 3) TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, total_colors, cquantize->Ncolors[0], cquantize->Ncolors[1], cquantize->Ncolors[2]); else TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); /* Allocate and fill in the colormap. */ /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ /* blkdist is distance between groups of identical entries for a component */ blkdist = total_colors; for (i = 0; i < cinfo->out_color_components; i++) { /* fill in colormap entries for i'th color component */ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ blksize = blkdist / nci; for (j = 0; j < nci; j++) { /* Compute j'th output value (out of nci) for component */ val = output_value(cinfo, i, j, nci-1); /* Fill in all colormap entries that have this value of this component */ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) colormap[i][ptr+k] = (JSAMPLE) val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ } /* Save the colormap in private storage, * where it will survive color quantization mode changes. */ cquantize->sv_colormap = colormap; cquantize->sv_actual = total_colors; } /* * Create the color index table. */ LOCAL(void) create_colorindex (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPROW indexptr; int i,j,k, nci, blksize, val, pad; /* For ordered dither, we pad the color index tables by MAXJSAMPLE in * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). * This is not necessary in the other dithering modes. However, we * flag whether it was done in case user changes dithering mode. */ if (cinfo->dither_mode == JDITHER_ORDERED) { pad = MAXJSAMPLE*2; cquantize->is_padded = TRUE; } else { pad = 0; cquantize->is_padded = FALSE; } cquantize->colorindex = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (MAXJSAMPLE+1 + pad), (JDIMENSION) cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ blksize = cquantize->sv_actual; for (i = 0; i < cinfo->out_color_components; i++) { /* fill in colorindex entries for i'th color component */ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ blksize = blksize / nci; /* adjust colorindex pointers to provide padding at negative indexes. */ if (pad) cquantize->colorindex[i] += MAXJSAMPLE; /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ indexptr = cquantize->colorindex[i]; val = 0; k = largest_input_value(cinfo, i, 0, nci-1); for (j = 0; j <= MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci-1); /* premultiply so that no multiplication needed in main processing */ indexptr[j] = (JSAMPLE) (val * blksize); } /* Pad at both ends if necessary */ if (pad) for (j = 1; j <= MAXJSAMPLE; j++) { indexptr[-j] = indexptr[0]; indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; } } } /* * Create an ordered-dither array for a component having ncolors * distinct output values. */ LOCAL(ODITHER_MATRIX_PTR) make_odither_array (j_decompress_ptr cinfo, int ncolors) { ODITHER_MATRIX_PTR odither; int j,k; INT32 num,den; odither = (ODITHER_MATRIX_PTR) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ODITHER_MATRIX)); /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). * Hence the dither value for the matrix cell with fill order f * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). * On 16-bit-int machine, be careful to avoid overflow. */ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); for (j = 0; j < ODITHER_SIZE; j++) { for (k = 0; k < ODITHER_SIZE; k++) { num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) * MAXJSAMPLE; /* Ensure round towards zero despite C's lack of consistency * about rounding negative values in integer division... */ odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); } } return odither; } /* * Create the ordered-dither tables. * Components having the same number of representative colors may * share a dither table. */ LOCAL(void) create_odither_tables (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; ODITHER_MATRIX_PTR odither; int i, j, nci; for (i = 0; i < cinfo->out_color_components; i++) { nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ odither = NULL; /* search for matching prior component */ for (j = 0; j < i; j++) { if (nci == cquantize->Ncolors[j]) { odither = cquantize->odither[j]; break; } } if (odither == NULL) /* need a new table? */ odither = make_odither_array(cinfo, nci); cquantize->odither[i] = odither; } } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF(void) color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colorindex = cquantize->colorindex; register int pixcode, ci; register JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; register int nc = cinfo->out_color_components; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = 0; for (ci = 0; ci < nc; ci++) { pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); } *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF(void) color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; register JSAMPROW ptrin, ptrout; JSAMPROW colorindex0 = cquantize->colorindex[0]; JSAMPROW colorindex1 = cquantize->colorindex[1]; JSAMPROW colorindex2 = cquantize->colorindex[2]; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF(void) quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; int * dither; /* points to active row of dither matrix */ int row_index, col_index; /* current indexes into dither matrix */ int nc = cinfo->out_color_components; int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ jzero_far((void FAR *) output_buf[row], (size_t) (width * SIZEOF(JSAMPLE))); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; colorindex_ci = cquantize->colorindex[ci]; dither = cquantize->odither[ci][row_index]; col_index = 0; for (col = width; col > 0; col--) { /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, * select output value, accumulate into output code for this pixel. * Range-limiting need not be done explicitly, as we have extended * the colorindex table to produce the right answers for out-of-range * inputs. The maximum dither is +- MAXJSAMPLE; this sets the * required amount of padding. */ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; input_ptr += nc; output_ptr++; col_index = (col_index + 1) & ODITHER_MASK; } } /* Advance row index for next row */ row_index = (row_index + 1) & ODITHER_MASK; cquantize->row_index = row_index; } } METHODDEF(void) quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex0 = cquantize->colorindex[0]; JSAMPROW colorindex1 = cquantize->colorindex[1]; JSAMPROW colorindex2 = cquantize->colorindex[2]; int * dither0; /* points to active row of dither matrix */ int * dither1; int * dither2; int row_index, col_index; /* current indexes into dither matrix */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { row_index = cquantize->row_index; input_ptr = input_buf[row]; output_ptr = output_buf[row]; dither0 = cquantize->odither[0][row_index]; dither1 = cquantize->odither[1][row_index]; dither2 = cquantize->odither[2][row_index]; col_index = 0; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]); *output_ptr++ = (JSAMPLE) pixcode; col_index = (col_index + 1) & ODITHER_MASK; } row_index = (row_index + 1) & ODITHER_MASK; cquantize->row_index = row_index; } } METHODDEF(void) quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register LOCFSERROR cur; /* current error or pixel value */ LOCFSERROR belowerr; /* error for pixel below cur */ LOCFSERROR bpreverr; /* error for below/prev col */ LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ int dirnc; /* dir * nc */ int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ jzero_far((void FAR *) output_buf[row], (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ input_ptr += (width-1) * nc; /* so point to rightmost pixel */ output_ptr += width-1; dir = -1; dirnc = -nc; errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ } else { /* work left to right in this row */ dir = 1; dirnc = nc; errorptr = cquantize->fserrors[ci]; /* => entry before first column */ } colorindex_ci = cquantize->colorindex[ci]; colormap_ci = cquantize->sv_colormap[ci]; /* Preset error values: no error propagated to first pixel from left */ cur = 0; /* and no error propagated to row below yet */ belowerr = bpreverr = 0; for (col = width; col > 0; col--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr + cur); cur += delta; /* form error * 5 */ bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ input_ptr += dirnc; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); } } /* * Allocate workspace for Floyd-Steinberg errors. */ LOCAL(void) alloc_fs_workspace (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; size_t arraysize; int i; arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->out_color_components; i++) { cquantize->fserrors[i] = (FSERRPTR) (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); } } /* * Initialize for one-pass color quantization. */ METHODDEF(void) start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; size_t arraysize; int i; /* Install my colormap. */ cinfo->colormap = cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = color_quantize3; else cquantize->pub.color_quantize = color_quantize; break; case JDITHER_ORDERED: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = quantize3_ord_dither; else cquantize->pub.color_quantize = quantize_ord_dither; cquantize->row_index = 0; /* initialize state for ordered dither */ /* If user changed to ordered dither from another mode, * we must recreate the color index table with padding. * This will cost extra space, but probably isn't very likely. */ if (! cquantize->is_padded) create_colorindex(cinfo); /* Create ordered-dither tables if we didn't already. */ if (cquantize->odither[0] == NULL) create_odither_tables(cinfo); break; case JDITHER_FS: cquantize->pub.color_quantize = quantize_fs_dither; cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ /* Allocate Floyd-Steinberg workspace if didn't already. */ if (cquantize->fserrors[0] == NULL) alloc_fs_workspace(cinfo); /* Initialize the propagated errors to zero. */ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->out_color_components; i++) jzero_far((void FAR *) cquantize->fserrors[i], arraysize); break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } /* * Finish up at the end of the pass. */ METHODDEF(void) finish_pass_1_quant (j_decompress_ptr cinfo) { /* no work in 1-pass case */ } /* * Switch to a new external colormap between output passes. * Shouldn't get to this module! */ METHODDEF(void) new_color_map_1_quant (j_decompress_ptr cinfo) { ERREXIT(cinfo, JERR_MODE_CHANGE); } /* * Module initialization routine for 1-pass color quantization. */ GLOBAL(void) jinit_1pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_1_quant; cquantize->pub.finish_pass = finish_pass_1_quant; cquantize->pub.new_color_map = new_color_map_1_quant; cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); /* Create the colormap and color index table. */ create_colormap(cinfo); create_colorindex(cinfo); /* Allocate Floyd-Steinberg workspace now if requested. * We do this now since it is FAR storage and may affect the memory * manager's space calculations. If the user changes to FS dither * mode in a later pass, we will allocate the space then, and will * possibly overrun the max_memory_to_use setting. */ if (cinfo->dither_mode == JDITHER_FS) alloc_fs_workspace(cinfo); } #endif /* QUANT_1PASS_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jquant2.c ================================================ /* * jquant2.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 2-pass color quantization (color mapping) routines. * These routines provide selection of a custom color map for an image, * followed by mapping of the image to that color map, with optional * Floyd-Steinberg dithering. * It is also possible to use just the second pass to map to an arbitrary * externally-given color map. * * Note: ordered dithering is not supported, since there isn't any fast * way to compute intercolor distances; it's unclear that ordered dither's * fundamental assumptions even hold with an irregularly spaced color map. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_2PASS_SUPPORTED /* * This module implements the well-known Heckbert paradigm for color * quantization. Most of the ideas used here can be traced back to * Heckbert's seminal paper * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. * * In the first pass over the image, we accumulate a histogram showing the * usage count of each possible color. To keep the histogram to a reasonable * size, we reduce the precision of the input; typical practice is to retain * 5 or 6 bits per color, so that 8 or 4 different input values are counted * in the same histogram cell. * * Next, the color-selection step begins with a box representing the whole * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires * considerable care. * * Heckbert-style quantizers vary a good deal in their policies for choosing * the "largest" box and deciding where to cut it. The particular policies * used here have proved out well in experimental comparisons, but better ones * may yet be found. * * In earlier versions of the IJG code, this module quantized in YCbCr color * space, processing the raw upsampled data without a color conversion step. * This allowed the color conversion math to be done only once per colormap * entry, not once per pixel. However, that optimization precluded other * useful optimizations (such as merging color conversion with upsampling) * and it also interfered with desired capabilities such as quantizing to an * externally-supplied colormap. We have therefore abandoned that approach. * The present code works in the post-conversion color space, typically RGB. * * To improve the visual quality of the results, we actually work in scaled * RGB space, giving G distances more weight than R, and R in turn more than * B. To do everything in integer math, we must use integer scale factors. * The 2/3/1 scale factors used here correspond loosely to the relative * weights of the colors in the NTSC grayscale equation. * If you want to use this code to quantize a non-RGB color space, you'll * probably need to change these scale factors. */ #define R_SCALE 2 /* scale R distances by this much */ #define G_SCALE 3 /* scale G distances by this much */ #define B_SCALE 1 /* and B by this much */ /* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B * and B,G,R orders. If you define some other weird order in jmorecfg.h, * you'll get compile errors until you extend this logic. In that case * you'll probably want to tweak the histogram sizes too. */ #if RGB_RED == 0 #define C0_SCALE R_SCALE #endif #if RGB_BLUE == 0 #define C0_SCALE B_SCALE #endif #if RGB_GREEN == 1 #define C1_SCALE G_SCALE #endif #if RGB_RED == 2 #define C2_SCALE R_SCALE #endif #if RGB_BLUE == 2 #define C2_SCALE B_SCALE #endif /* * First we have the histogram data structure and routines for creating it. * * The number of bits of precision can be adjusted by changing these symbols. * We recommend keeping 6 bits for G and 5 each for R and B. * If you have plenty of memory and cycles, 6 bits all around gives marginally * better results; if you are short of memory, 5 bits all around will save * some space but degrade the results. * To maintain a fully accurate histogram, we'd need to allocate a "long" * (preferably unsigned long) for each cell. In practice this is overkill; * we can get by with 16 bits per cell. Few of the cell counts will overflow, * and clamping those that do overflow to the maximum value will give close- * enough results. This reduces the recommended histogram size from 256Kb * to 128Kb, which is a useful savings on PC-class machines. * (In the second pass the histogram space is re-used for pixel mapping data; * in that capacity, each cell must be able to store zero to the number of * desired colors. 16 bits/cell is plenty for that too.) * Since the JPEG code is intended to run in small memory model on 80x86 * machines, we can't just allocate the histogram in one chunk. Instead * of a true 3-D array, we use a row of pointers to 2-D arrays. Each * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that * on 80x86 machines, the pointer row is in near memory but the actual * arrays are in far memory (same arrangement as we use for image arrays). */ #define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ /* These will do the right thing for either R,G,B or B,G,R color order, * but you may not like the results for other color orders. */ #define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ #define HIST_C1_BITS 6 /* bits of precision in G histogram */ #define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ /* Number of elements along histogram axes. */ #define HIST_C0_ELEMS (1<cquantize; register JSAMPROW ptr; register histptr histp; register hist3d histogram = cquantize->histogram; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { ptr = input_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the histogram */ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] [GETJSAMPLE(ptr[1]) >> C1_SHIFT] [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; /* increment, check for overflow and undo increment if so. */ if (++(*histp) <= 0) (*histp)--; ptr += 3; } } } /* * Next we have the really interesting routines: selection of a colormap * given the completed histogram. * These routines work with a list of "boxes", each representing a rectangular * subset of the input color space (to histogram precision). */ typedef struct { /* The bounds of the box (inclusive); expressed as histogram indexes */ int c0min, c0max; int c1min, c1max; int c2min, c2max; /* The volume (actually 2-norm) of the box */ INT32 volume; /* The number of nonzero histogram cells within this box */ long colorcount; } box; typedef box * boxptr; LOCAL(boxptr) find_biggest_color_pop (boxptr boxlist, int numboxes) /* Find the splittable box with the largest color population */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register long maxc = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > maxc && boxp->volume > 0) { which = boxp; maxc = boxp->colorcount; } } return which; } LOCAL(boxptr) find_biggest_volume (boxptr boxlist, int numboxes) /* Find the splittable box with the largest (scaled) volume */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register INT32 maxv = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > maxv) { which = boxp; maxv = boxp->volume; } } return which; } LOCAL(void) update_box (j_decompress_ptr cinfo, boxptr boxp) /* Shrink the min/max bounds of a box to enclose only nonzero elements, */ /* and recompute its volume and population */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; INT32 dist0,dist1,dist2; long ccount; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0min = c0min = c0; goto have_c0min; } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0max = c0max = c0; goto have_c0max; } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1min = c1min = c1; goto have_c1min; } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1max = c1max = c1; goto have_c1max; } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { boxp->c2min = c2min = c2; goto have_c2min; } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { boxp->c2max = c2max = c2; goto have_c2max; } } have_c2max: /* Update box volume. * We use 2-norm rather than real volume here; this biases the method * against making long narrow boxes, and it has the side benefit that * a box is splittable iff norm > 0. * Since the differences are expressed in histogram-cell units, * we have to shift back to JSAMPLE units to get consistent distances; * after which, we scale according to the selected distance scale factors. */ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) if (*histp != 0) { ccount++; } } boxp->colorcount = ccount; } LOCAL(int) median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; int c0,c1,c2,cmax; register boxptr b1,b2; while (numboxes < desired_colors) { /* Select box to split. * Current algorithm: by population for first half, then by volume. */ if (numboxes*2 <= desired_colors) { b1 = find_biggest_color_pop(boxlist, numboxes); } else { b1 = find_biggest_volume(boxlist, numboxes); } if (b1 == NULL) /* no splittable boxes left! */ break; b2 = &boxlist[numboxes]; /* where new box will go */ /* Copy the color bounds to the new box. */ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; /* Choose which axis to split the box on. * Current algorithm: longest scaled axis. * See notes in update_box about scaling distances. */ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; /* We want to break any ties in favor of green, then red, blue last. * This code does the right thing for R,G,B or B,G,R color orders only. */ #if RGB_RED == 0 cmax = c1; n = 1; if (c0 > cmax) { cmax = c0; n = 0; } if (c2 > cmax) { n = 2; } #else cmax = c1; n = 1; if (c2 > cmax) { cmax = c2; n = 2; } if (c0 > cmax) { n = 0; } #endif /* Choose split point along selected axis, and update box bounds. * Current algorithm: split at halfway point. * (Since the box has been shrunk to minimum volume, * any split will produce two nonempty subboxes.) * Note that lb value is max for lower box, so must be < old max. */ switch (n) { case 0: lb = (b1->c0max + b1->c0min) / 2; b1->c0max = lb; b2->c0min = lb+1; break; case 1: lb = (b1->c1max + b1->c1min) / 2; b1->c1max = lb; b2->c1min = lb+1; break; case 2: lb = (b1->c2max + b1->c2min) / 2; b1->c2max = lb; b2->c2min = lb+1; break; } /* Update stats for boxes */ update_box(cinfo, b1); update_box(cinfo, b2); numboxes++; } return numboxes; } LOCAL(void) compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) /* Compute representative color for a box, put it in colormap[icolor] */ { /* Current algorithm: mean weighted by pixels (not colors) */ /* Note it is important to get the rounding correct! */ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long count; long total = 0; long c0total = 0; long c1total = 0; long c2total = 0; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { if ((count = *histp++) != 0) { total += count; c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; } } } cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); } LOCAL(void) select_colors (j_decompress_ptr cinfo, int desired_colors) /* Master routine for color selection */ { boxptr boxlist; int numboxes; int i; /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; boxlist[0].c1min = 0; boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; boxlist[0].c2min = 0; boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, & boxlist[0]); /* Perform median-cut to produce final box list */ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); /* Compute the representative color for each box, fill colormap */ for (i = 0; i < numboxes; i++) compute_color(cinfo, & boxlist[i], i); cinfo->actual_number_of_colors = numboxes; TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); } /* * These routines are concerned with the time-critical task of mapping input * colors to the nearest color in the selected colormap. * * We re-use the histogram space as an "inverse color map", essentially a * cache for the results of nearest-color searches. All colors within a * histogram cell will be mapped to the same colormap entry, namely the one * closest to the cell's center. This may not be quite the closest entry to * the actual input color, but it's almost as good. A zero in the cache * indicates we haven't found the nearest color for that cell yet; the array * is cleared to zeroes before starting the mapping pass. When we find the * nearest color for a cell, its colormap index plus one is recorded in the * cache for future use. The pass2 scanning routines call fill_inverse_cmap * when they need to use an unfilled entry in the cache. * * Our method of efficiently finding nearest colors is based on the "locally * sorted search" idea described by Heckbert and on the incremental distance * calculation described by Spencer W. Thomas in chapter III.1 of Graphics * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that * the distances from a given colormap entry to each cell of the histogram can * be computed quickly using an incremental method: the differences between * distances to adjacent cells themselves differ by a constant. This allows a * fairly fast implementation of the "brute force" approach of computing the * distance from every colormap entry to every histogram cell. Unfortunately, * it needs a work array to hold the best-distance-so-far for each histogram * cell (because the inner loop has to be over cells, not colormap entries). * The work array elements have to be INT32s, so the work array would need * 256Kb at our recommended precision. This is not feasible in DOS machines. * * To get around these problems, we apply Thomas' method to compute the * nearest colors for only the cells within a small subbox of the histogram. * The work array need be only as big as the subbox, so the memory usage * problem is solved. Furthermore, we need not fill subboxes that are never * referenced in pass2; many images use only part of the color gamut, so a * fair amount of work is saved. An additional advantage of this * approach is that we can apply Heckbert's locality criterion to quickly * eliminate colormap entries that are far away from the subbox; typically * three-fourths of the colormap entries are rejected by Heckbert's criterion, * and we need not compute their distances to individual cells in the subbox. * The speed of this approach is heavily influenced by the subbox size: too * small means too much overhead, too big loses because Heckbert's criterion * can't eliminate as many colormap entries. Empirically the best subbox * size seems to be about 1/512th of the histogram (1/8th in each direction). * * Thomas' article also describes a refined method which is asymptotically * faster than the brute-force method, but it is also far more complex and * cannot efficiently be applied to small subboxes. It is therefore not * useful for programs intended to be portable to DOS machines. On machines * with plenty of memory, filling the whole histogram in one shot with Thomas' * refined method might be faster than the present code --- but then again, * it might not be any faster, and it's certainly more complicated. */ /* log2(histogram cells in update box) for each axis; this can be adjusted */ #define BOX_C0_LOG (HIST_C0_BITS-3) #define BOX_C1_LOG (HIST_C1_BITS-3) #define BOX_C2_LOG (HIST_C2_BITS-3) #define BOX_C0_ELEMS (1<actual_number_of_colors; int maxc0, maxc1, maxc2; int centerc0, centerc1, centerc2; int i, x, ncolors; INT32 minmaxdist, min_dist, max_dist, tdist; INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ /* Compute true coordinates of update box's upper corner and center. * Actually we compute the coordinates of the center of the upper-corner * histogram cell, which are the upper bounds of the volume we care about. * Note that since ">>" rounds down, the "center" values may be closer to * min than to max; hence comparisons to them must be "<=", not "<". */ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); centerc0 = (minc0 + maxc0) >> 1; maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); centerc1 = (minc1 + maxc1) >> 1; maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); centerc2 = (minc2 + maxc2) >> 1; /* For each color in colormap, find: * 1. its minimum squared-distance to any point in the update box * (zero if color is within update box); * 2. its maximum squared-distance to any point in the update box. * Both of these can be found by considering only the corners of the box. * We save the minimum distance for each color in mindist[]; * only the smallest maximum distance is of interest. */ minmaxdist = 0x7FFFFFFFL; for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ x = GETJSAMPLE(cinfo->colormap[0][i]); if (x < minc0) { tdist = (x - minc0) * C0_SCALE; min_dist = tdist*tdist; tdist = (x - maxc0) * C0_SCALE; max_dist = tdist*tdist; } else if (x > maxc0) { tdist = (x - maxc0) * C0_SCALE; min_dist = tdist*tdist; tdist = (x - minc0) * C0_SCALE; max_dist = tdist*tdist; } else { /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { tdist = (x - maxc0) * C0_SCALE; max_dist = tdist*tdist; } else { tdist = (x - minc0) * C0_SCALE; max_dist = tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[1][i]); if (x < minc1) { tdist = (x - minc1) * C1_SCALE; min_dist += tdist*tdist; tdist = (x - maxc1) * C1_SCALE; max_dist += tdist*tdist; } else if (x > maxc1) { tdist = (x - maxc1) * C1_SCALE; min_dist += tdist*tdist; tdist = (x - minc1) * C1_SCALE; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { tdist = (x - maxc1) * C1_SCALE; max_dist += tdist*tdist; } else { tdist = (x - minc1) * C1_SCALE; max_dist += tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[2][i]); if (x < minc2) { tdist = (x - minc2) * C2_SCALE; min_dist += tdist*tdist; tdist = (x - maxc2) * C2_SCALE; max_dist += tdist*tdist; } else if (x > maxc2) { tdist = (x - maxc2) * C2_SCALE; min_dist += tdist*tdist; tdist = (x - minc2) * C2_SCALE; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { tdist = (x - maxc2) * C2_SCALE; max_dist += tdist*tdist; } else { tdist = (x - minc2) * C2_SCALE; max_dist += tdist*tdist; } } mindist[i] = min_dist; /* save away the results */ if (max_dist < minmaxdist) minmaxdist = max_dist; } /* Now we know that no cell in the update box is more than minmaxdist * away from some colormap entry. Therefore, only colors that are * within minmaxdist of some part of the box need be considered. */ ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) colorlist[ncolors++] = (JSAMPLE) i; } return ncolors; } LOCAL(void) find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. * This routine uses Thomas' incremental distance calculation method to * find the distance from a colormap entry to successive cells in the box. */ { int ic0, ic1, ic2; int i, icolor; register INT32 * bptr; /* pointer into bestdist[] array */ JSAMPLE * cptr; /* pointer into bestcolor[] array */ INT32 dist0, dist1; /* initial distance values */ register INT32 dist2; /* current distance in inner loop */ INT32 xx0, xx1; /* distance increments */ register INT32 xx2; INT32 inc0, inc1, inc2; /* initial values for increments */ /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Initialize best-distance for each cell of the update box */ bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; dist0 = inc0*inc0; inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; dist0 += inc1*inc1; inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; dist0 += inc2*inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; /* Now loop over all cells in box, updating distance per Thomas method */ bptr = bestdist; cptr = bestcolor; xx0 = inc0; for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { dist1 = dist0; xx1 = inc1; for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { dist2 = dist1; xx2 = inc2; for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; *cptr = (JSAMPLE) icolor; } dist2 += xx2; xx2 += 2 * STEP_C2 * STEP_C2; bptr++; cptr++; } dist1 += xx1; xx1 += 2 * STEP_C1 * STEP_C1; } dist0 += xx0; xx0 += 2 * STEP_C0 * STEP_C0; } } } LOCAL(void) fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) /* Fill the inverse-colormap entries in the update box that contains */ /* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ /* we can fill as many others as we wish.) */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; register JSAMPLE * cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_C0_LOG; c1 >>= BOX_C1_LOG; c2 >>= BOX_C2_LOG; /* Compute true coordinates of update box's origin corner. * Actually we compute the coordinates of the center of the corner * histogram cell, which are the lower bounds of the volume we care about. */ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_C1_LOG; c2 <<= BOX_C2_LOG; cptr = bestcolor; for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF(void) pass2_no_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register JSAMPROW inptr, outptr; register histptr cachep; register int c0, c1, c2; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the cache */ c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; cachep = & histogram[c0][c1][c2]; /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } } } METHODDEF(void) pass2_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ JSAMPROW inptr; /* => current input pixel */ JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing inptr & errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; int *error_limit = cquantize->error_limiter; JSAMPROW colormap0 = cinfo->colormap[0]; JSAMPROW colormap1 = cinfo->colormap[1]; JSAMPROW colormap2 = cinfo->colormap[2]; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ inptr += (width-1) * 3; /* so point to rightmost pixel */ outptr += width-1; dir = -1; dir3 = -3; errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ cquantize->on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; dir3 = 3; errorptr = cquantize->fserrors; /* => entry before first real column */ cquantize->on_odd_row = TRUE; /* flip for next time */ } /* Preset error values: no error propagated to first pixel from left */ cur0 = cur1 = cur2 = 0; /* and no error propagated to row below yet */ belowerr0 = belowerr1 = belowerr2 = 0; bpreverr0 = bpreverr1 = bpreverr2 = 0; for (col = width; col > 0; col--) { /* curN holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); /* Limit the error using transfer function set by init_error_limit. * See comments with init_error_limit for rationale. */ cur0 = error_limit[cur0]; cur1 = error_limit[cur1]; cur2 = error_limit[cur2]; /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE (or less with error limiting); * this sets the required size of the range_limit array. */ cur0 += GETJSAMPLE(inptr[0]); cur1 += GETJSAMPLE(inptr[1]); cur2 += GETJSAMPLE(inptr[2]); cur0 = GETJSAMPLE(range_limit[cur0]); cur1 = GETJSAMPLE(range_limit[cur1]); cur2 = GETJSAMPLE(range_limit[cur2]); /* Index into the cache with adjusted pixel value */ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; *outptr = (JSAMPLE) pixcode; /* Compute representation error for this pixel */ cur0 -= GETJSAMPLE(colormap0[pixcode]); cur1 -= GETJSAMPLE(colormap1[pixcode]); cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ { register LOCFSERROR bnexterr, delta; bnexterr = cur0; /* Process component 0 */ delta = cur0 * 2; cur0 += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr0 + cur0); cur0 += delta; /* form error * 5 */ bpreverr0 = belowerr0 + cur0; belowerr0 = bnexterr; cur0 += delta; /* form error * 7 */ bnexterr = cur1; /* Process component 1 */ delta = cur1 * 2; cur1 += delta; /* form error * 3 */ errorptr[1] = (FSERROR) (bpreverr1 + cur1); cur1 += delta; /* form error * 5 */ bpreverr1 = belowerr1 + cur1; belowerr1 = bnexterr; cur1 += delta; /* form error * 7 */ bnexterr = cur2; /* Process component 2 */ delta = cur2 * 2; cur2 += delta; /* form error * 3 */ errorptr[2] = (FSERROR) (bpreverr2 + cur2); cur2 += delta; /* form error * 5 */ bpreverr2 = belowerr2 + cur2; belowerr2 = bnexterr; cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ inptr += dir3; /* Advance pixel pointers to next column */ outptr += dir; errorptr += dir3; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error values into the * final fserrors[] entry. Note we need not unload belowerrN because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ errorptr[1] = (FSERROR) bpreverr1; errorptr[2] = (FSERROR) bpreverr2; } } /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright * pixels in a dark area, etc.) The standard advice for avoiding this problem * is to ensure that the "corners" of the color cube are allocated as output * colors; then repeated errors in the same direction cannot cause cascading * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ LOCAL(void) init_error_limit (j_decompress_ptr cinfo) /* Allocate and fill in the error_limiter table */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; int * table; int in, out; table = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ cquantize->error_limiter = table; #define STEPSIZE ((MAXJSAMPLE+1)/16) /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ for (; in <= MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #undef STEPSIZE } /* * Finish up at the end of each pass. */ METHODDEF(void) finish_pass1 (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; /* Select the representative colors and fill in cinfo->colormap */ cinfo->colormap = cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); /* Force next pass to zero the color index table */ cquantize->needs_zeroed = TRUE; } METHODDEF(void) finish_pass2 (j_decompress_ptr cinfo) { /* no work */ } /* * Initialize for each processing pass. */ METHODDEF(void) start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int i; /* Only F-S dithering or no dithering is supported. */ /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) cinfo->dither_mode = JDITHER_FS; if (is_pre_scan) { /* Set up method pointers */ cquantize->pub.color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { /* Set up method pointers */ if (cinfo->dither_mode == JDITHER_FS) cquantize->pub.color_quantize = pass2_fs_dither; else cquantize->pub.color_quantize = pass2_no_dither; cquantize->pub.finish_pass = finish_pass2; /* Make sure color count is acceptable */ i = cinfo->actual_number_of_colors; if (i < 1) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); if (i > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); if (cinfo->dither_mode == JDITHER_FS) { size_t arraysize = (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))); /* Allocate Floyd-Steinberg workspace if we didn't already. */ if (cquantize->fserrors == NULL) cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ jzero_far((void FAR *) cquantize->fserrors, arraysize); /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) init_error_limit(cinfo); cquantize->on_odd_row = FALSE; } } /* Zero the histogram or inverse color map, if necessary */ if (cquantize->needs_zeroed) { for (i = 0; i < HIST_C0_ELEMS; i++) { jzero_far((void FAR *) histogram[i], HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = FALSE; } } /* * Switch to a new external colormap between output passes. */ METHODDEF(void) new_color_map_2_quant (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; /* Reset the inverse color map */ cquantize->needs_zeroed = TRUE; } /* * Module initialization routine for 2-pass color quantization. */ GLOBAL(void) jinit_2pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_2_quant; cquantize->pub.new_color_map = new_color_map_2_quant; cquantize->fserrors = NULL; /* flag optional arrays not allocated */ cquantize->error_limiter = NULL; /* Make sure jdmaster didn't give me a case I can't handle */ if (cinfo->out_color_components != 3) ERREXIT(cinfo, JERR_NOTIMPL); /* Allocate the histogram/inverse colormap storage */ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); for (i = 0; i < HIST_C0_ELEMS; i++) { cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ /* Allocate storage for the completed colormap, if required. * We do this now since it is FAR storage and may affect * the memory manager's space calculations. */ if (cinfo->enable_2pass_quant) { /* Make sure color count is acceptable */ int desired = cinfo->desired_number_of_colors; /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (desired < 8) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (desired > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); cquantize->desired = desired; } else cquantize->sv_colormap = NULL; /* Only F-S dithering or no dithering is supported. */ /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) cinfo->dither_mode = JDITHER_FS; /* Allocate Floyd-Steinberg workspace if necessary. * This isn't really needed until pass 2, but again it is FAR storage. * Although we will cope with a later change in dither_mode, * we do not promise to honor max_memory_to_use if dither_mode changes. */ if (cinfo->dither_mode == JDITHER_FS) { cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); /* Might as well create the error-limiting table too. */ init_error_limit(cinfo); } } #endif /* QUANT_2PASS_SUPPORTED */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jutils.c ================================================ /* * jutils.c * * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains tables and miscellaneous utility routines needed * for both compression and decompression. * Note we prefix all global names with "j" to minimize conflicts with * a surrounding application. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element * of a DCT block read in natural order (left to right, top to bottom). */ #if 0 /* This table is not actually needed in v6a */ const int jpeg_zigzag_order[DCTSIZE2] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; #endif /* * jpeg_natural_order[i] is the natural-order position of the i'th element * of zigzag order. * * When reading corrupted data, the Huffman decoders could attempt * to reference an entry beyond the end of this array (if the decoded * zero run length reaches past the end of the block). To prevent * wild stores without adding an inner-loop test, we put some extra * "63"s after the real entries. This will cause the extra coefficient * to be stored in location 63 of the block, not somewhere random. * The worst case would be a run-length of 15, which means we need 16 * fake entries. */ const int jpeg_natural_order[DCTSIZE2+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; /* * Arithmetic utilities */ GLOBAL(long) jdiv_round_up (long a, long b) /* Compute a/b rounded up to next integer, ie, ceil(a/b) */ /* Assumes a >= 0, b > 0 */ { return (a + b - 1L) / b; } GLOBAL(long) jround_up (long a, long b) /* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ /* Assumes a >= 0, b > 0 */ { a += b - 1L; return a - (a % b); } /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays * and coefficient-block arrays. This won't work on 80x86 because the arrays * are FAR and we're assuming a small-pointer memory model. However, some * DOS compilers provide far-pointer versions of memcpy() and memset() even * in the small-model libraries. These will be used if USE_FMEM is defined. * Otherwise, the routines below do it the hard way. (The performance cost * is not all that great, because these routines aren't very heavily used.) */ #ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) #define FMEMZERO(target,size) MEMZERO(target,size) #else /* 80x86 case, define if we can */ #ifdef USE_FMEM #define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) #define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) #endif #endif GLOBAL(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas may overlap for duplication. * The source and destination arrays must be at least as wide as num_cols. */ { register JSAMPROW inptr, outptr; #ifdef FMEMCOPY register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); #else register JDIMENSION count; #endif register int row; input_array += source_row; output_array += dest_row; for (row = num_rows; row > 0; row--) { inptr = *input_array++; outptr = *output_array++; #ifdef FMEMCOPY FMEMCOPY(outptr, inptr, count); #else for (count = num_cols; count > 0; count--) *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ #endif } } GLOBAL(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks) /* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); #else register JCOEFPTR inptr, outptr; register long count; inptr = (JCOEFPTR) input_row; outptr = (JCOEFPTR) output_row; for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { *outptr++ = *inptr++; } #endif } GLOBAL(void) jzero_far (void FAR * target, size_t bytestozero) /* Zero out a chunk of FAR memory. */ /* This might be sample-array data, block-array data, or alloc_large data. */ { #ifdef FMEMZERO FMEMZERO(target, bytestozero); #else register char FAR * ptr = (char FAR *) target; register size_t count; for (count = bytestozero; count > 0; count--) { *ptr++ = 0; } #endif } ================================================ FILE: vm/src/from_squeak/Cross/plugins/JPEGReadWriter2Plugin/jversion.h ================================================ /* * jversion.h * * Copyright (C) 1991-1998, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains software version identification. */ #define JVERSION "6b 27-Mar-1998" #define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" ================================================ FILE: vm/src/from_squeak/Cross/plugins/JoystickTabletPlugin/JoystickTabletPlugin.h ================================================ /* joystick & graphics tablet support */ /* module initialization/shutdown */ int joystickInit(void); int joystickShutdown(void); int joystickRead(int stickIndex); /*** tablet support ***/ int tabletGetParameters(int cursorIndex, int result[]); int tabletRead(int cursorIndex, int result[]); int tabletResultSize(void); ================================================ FILE: vm/src/from_squeak/Cross/plugins/LocalePlugin/LocalePlugin.h ================================================ /**************************************************************************** * PROJECT: Common include * FILE: LocalePlugin.h * CONTENT: * * AUTHOR: tim@rowledge.org * ADDRESS: * EMAIL: * RCSID: $Id: LocalePlugin.h * */ /* Locale support definitions */ sqInt sqLocInitialize(void); /************** Country and language ******************/ /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str); /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str); /***************** Currency ********************/ /* return true if the currency symbol is to be placed in front of the currency * amount */ sqInt sqLocCurrencyNotation(void); /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void); /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str); /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void); /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str); /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str); /****************** time and date *********************/ /* return in minutes the offset between thisVM and UTC. */ sqInt sqLocGetVMOffsetToUTC(void); /* return in minutes the offset between the currenct timezone and UTC */ sqInt sqLocGetTimezoneOffset(void); /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void); /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void); /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str); /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(); /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str); /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void); /* write the string describing the time formatting into string ptr. /* Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str); ================================================ FILE: vm/src/from_squeak/Cross/plugins/MIDIPlugin/MIDIPlugin.h ================================================ /* MIDI primitives */ /* module initialization/shutdown */ int midiInit(void); int midiShutdown(void); int sqMIDIGetClock(void); int sqMIDIGetPortCount(void); int sqMIDIGetPortDirectionality(int portNum); int sqMIDIGetPortName(int portNum, int namePtr, int length); int sqMIDIClosePort(int portNum); int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate); int sqMIDIParameterSet(int whichParameter, int newValue); int sqMIDIParameterGet(int whichParameter); int sqMIDIPortReadInto(int portNum, int count, int bufferPtr); int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time); ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/COPYING ================================================ Original license for libMPEG3 was GPL. But on nov 1st 2000, then author granted the following change to the Squeak community. ___Nov 1st_____ 2000 To whom it may concern: I hereby grant and jointly license my software, ________LibMPEG3_______, under the terms of either the GNU Lesser General Public License, also known as the "LGPL", or the Squeak License set forth below, at the option of the licensee or any sublicensees. Thus, my software may be reproduced, distributed and derivative works made there from pursuant to the terms of either: a) the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1, or (at your option) any later version; or b) the Squeak License; either as published on http://www.squeak.org/license.html, as of the date of this license, or (at your option) any later version. My software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU Lesser General Public License or the Squeak License. __________(Signed)____________ Adam Williams GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Squeak License. Apple Computer, Inc. Software License PLEASE READ THIS SOFTWARE LICENSE AGREEMENT "LICENSE" CAREFULLY BEFORE DOWNLOADING THIS SOFTWARE. BY DOWNLOADING THIS SOFTWARE YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, DO NOT DOWNLOAD. 1. License. The software, documentation and any fonts which you will receive by downloading this software (the "Apple Software") are licensed, not sold, to you by Apple Computer, Inc. or its local subsidiary, if any. Apple and/or Apple's licensor(s) retain title to the Apple Software, and the Apple Software and any copies which this License authorizes you to make are subject to this License. This License grants no right or license under any trademarks, service marks, or tradenames of Apple. 2. Permitted Uses and Restrictions. This License allows you to copy, install and use the Apple Software on an unlimited number of computers under your direct control. You may modify and create derivative works of the Apple Software ("Modified Software"), however, you may not modify or create derivative works of the fonts provided by Apple ("Fonts"). You may distribute and sublicense such Modified Software only under the terms of a valid, binding license that makes no representations or warranties on behalf of Apple, and is no less protective of Apple and Apple's rights than this License. You may distribute and sublicense the Fonts only as a part of and for use with Modified Software, and not as a part of or for use with Modified Software that is distributed or sublicensed for a fee or for other valuable consideration. If the Modified Software contains modifications, overwrites, replacements, deletions, additions, or ports to new platforms of: (1) the methods of existing class objects or their existing relationships, or (2) any part of the virtual machine, then for so long as the Modified Software is distributed or sublicensed to others, such modified, overwritten, replaced, deleted, added and ported portions of the Modified Software must be made publicly available, preferably by means of download from a website, at no charge under the terms set forth in Exhibit A below. You may transfer your rights under this License provided you transfer this License and a copy of the Apple Software to a party who agrees to accept the terms of this License and destroy any other copies of the Apple Software in your possession. Your rights under this License will terminate automatically without notice from Apple if you fail to comply with any term(s) of this License. 3. Disclaimer Of Warranty. The Apple Software is pre-release, and untested, or not fully tested. The Apple Software may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies. You expressly acknowledge and agree that use of the Apple Software is at your sole risk. You acknowledge that Apple has not publicly announced, nor promised or guaranteed to you, that Apple will release a final, commercial or any future pre-release version of the Apple Software to you or anyone in the future, and that Apple has no express or implied obligation to announce or introduce a final, commercial or any future pre-release version of the Apple Software or any similar or compatible product, or to continue to offer or support the Apple Software in the future. The Apple Software is provided "AS-IS" and without warranty of any kind and Apple and Apple's licensor(s) (for the purposes of Sections 3 and 4, Apple and Apple's licensor(s) shall be collectively referred to as "Apple") EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY OR SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE APPLE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF THE APPLE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE APPLE SOFTWARE WILL BE CORRECTED. FURTHERMORE, APPLE DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OR THE RESULTS OF THE USE OF THE APPLE SOFTWARE OR RELATED DOCUMENTATION IN TERMS OF THEIR CORRECTNESS, ACCURACY, RELIABILITY, OR OTHERWISE. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE SCOPE OF THIS WARRANTY. SHOULD THE APPLE SOFTWARE PROVE DEFECTIVE, YOU (AND NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU. THE TERMS OF THIS DISCLAIMER DO NOT AFFECT OR PREJUDICE THE STATUTORY RIGHTS OF A CONSUMER ACQUIRING APPLE PRODUCTS OTHERWISE THAN IN THE COURSE OF A BUSINESS, NEITHER DO THEY LIMIT OR EXCLUDE ANY LIABILITY FOR DEATH OR PERSONAL INJURY CAUSED BY APPLE'S NEGLIGENCE. 4. Limitation of Liability. UNDER NO CIRCUMSTANCES, INCLUDING NEGLIGENCE, SHALL APPLE BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to you for all damages exceed the amount of fifty dollars ($50.00). 5. Indemnification. You agree to indemnify and hold Apple harmless from any and all damages, liabilities, costs and expenses (including but not limited to attorneys' fees and costs of suit) incurred by Apple as a result of any claim, proceeding, and/or judgment to the extent it arises out of or is connected in any manner with the operation, use, distribution or modification of Modified Software, or the combination of Apple Software or Modified Software with other programs; provided that Apple notifies Licensee of any such claim or proceeding in writing, tenders to Licensee the opportunity to defend or settle such claim or proceeding at Licensee's expense, and cooperates with Licensee in defending or settling such claim or proceeding. 6. Export Law Assurances. You may not use or otherwise export or reexport the Apple Software except as authorized by United States law and the laws of the jurisdiction in which the Apple Software was obtained. In particular, but without limitation, the Apple Software may not be exported or reexported (i) into (or to a national or resident of) any U.S. embargoed country or (ii) to anyone on the U.S. Treasury Department's list of Specially Designated Nationals or the U.S. Department of Commerce's Table of Denial Orders. By using the Apple Software, you represent and warrant that you are not located in, under control of, or a national or resident of any such country or on any such list. 7. Government End Users. If the Apple Software is supplied to the United States Government, the Apple Software is classified as "restricted computer software" as defined in clause 52.227-19 of the FAR. The United States Government's rights to the Apple Software are as provided in clause 52.227-19 of the FAR. 8. Controlling Law and Severability. If there is a local subsidiary of Apple in the country in which the Apple Software License was obtained, then the local law in which the subsidiary sits shall govern this License. Otherwise, this License shall be governed by the laws of the United States and the State of California. If for any reason a court of competent jurisdiction finds any provision, or portion thereof, to be unenforceable, the remainder of this License shall continue in full force and effect. 9. Complete Agreement. This License constitutes the entire agreement between the parties with respect to the use of the Apple Software and supersedes all prior or contemporaneous understandings regarding such subject matter. No amendment to or modification of this License will be binding unless in writing and signed by Apple. Where the Licensee is located in the province of Quebec, Canada, the following clause applies: The parties hereto confirm that they have requested that this Agreement and all related documents be drafted in English. Les parties ont exig que le prsent contrat et tous les documents connexes soient rdigs en anglais. EXHIBIT A License. You may copy, install, use, modify and create derivative works of the [Modified Software] "Changed Software" (but you may not modify or create derivative works of the [Fonts]) and distribute and sublicense such Changed Software, provided however, that if the Changed Software contains modifications, overwrites, replacements, deletions, additions, or ports to new platforms of: (1) the methods of existing classes objects or their existing relationships, or (2) any part of the virtual machine, then for so long as the Changed Software is distributed or sublicensed to others, such modified, overwritten, replaced, deleted, added and ported portions of the Changed Software must be made publicly available, preferably by means of download from a website, at no charge under the terms of a license that makes no representations or warranties on behalf of any third party, is no less protective of [the licensors of the Modified Software] and its licensors, and contains the terms set forth in Exhibit A below [which should contain the terms of this Exhibit A]. You may distribute and sublicense the [Fonts] only as a part of and for use with Changed Software, and not as a part of or for use with Changed Software that is distributed or sublicensed for a fee or for other valuable consideration. ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/JMMMpegBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 26 February 2006 at 1:16:15 pm'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer ' classVariableNames: 'Registry ' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer ' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 18:12'! buffer ^buffer! ! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 23:15'! isBufferBased ^(buffer == nil) not ! ! !MPEGFile methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:11'! openBuffer: aByteArray pathToFile := nil. buffer _ aByteArray. fileBits := self primFileOpenABuffer: aByteArray size: aByteArray size. fileBits notNil ifTrue: [fileIndex := Smalltalk registerExternalObject: fileBits. self register.] ! ! !MPEGFile methodsFor: 'primitives' stamp: 'JMM 1/20/2006 17:52'! primFileOpenABuffer: buffer size: aSize "Open the file" self primitiveFailed! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:18'! openBuffer: aBuffer ^self new openBuffer: aBuffer! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 23:05'! openFileUseBuffer: aPath | bar bytes | bar _ StandardFileStream oldFileNamed: aPath. bar binary. bytes _ bar contents. ^self new openBuffer: bytes! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:10'! external [external hasVideo] on: Error do: [self isBuffer ifTrue: [external := MPEGFile openBuffer: external buffer] ifFalse: [(MPEGFile isFileValidMPEG: external fileName) ifFalse: [^self error: 'Mpeg File is invalid']. external := MPEGFile openFile: external fileName]]. ^external! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:05'! isBuffer ^isBuffer == true! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:17'! initializeWithBuffer: aBuffer form: aForm isBuffer := true. buffer := aBuffer. self initialize: aBuffer. self form: aForm. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:07'! initializeWithBuffer: aBuffer morph: aMorphic isBuffer _ true. buffer _ aBuffer. self initialize: aBuffer. self morph: aMorphic. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:54'! initialize: aPath self halt. self isBuffer ifTrue: [external := MPEGFile openBuffer: buffer] ifFalse: [(MPEGFile isFileValidMPEG: aPath) ifFalse: [^nil]. external := MPEGFile openFile: aPath.]. self playerProcessPriority: Processor userSchedulingPriority. self lastDelay: 10. volume := 1.0. errorForSoundStart := 500. semaphoreForSound := Semaphore new. self startTime: (Array new: self totalVideoStreams). self clockBias: (Array new: self totalVideoStreams withAll: 0).! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:16'! playBuffer: aBuffer onForm: aForm ^self new initializeWithBuffer: aBuffer morph: aForm! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:06'! playBuffer: aBuffer onMorph: aMorph ^self new initializeWithBuffer: aBuffer morph: aMorph! ! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer' classVariableNames: 'Registry' poolDictionaries: '' category: 'Movies-Kernel'! ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/JMMMpegBufferTest.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 26 February 2006 at 1:16:22 pm'! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! isThereAFile mpegFile isBufferBased ifTrue: [^true]. ^(FileStream isAFileNamed: mpegFile fileName)! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! moviePosition "Answer a number between 0.0 and 1.0 indicating the current position within the movie." mpegFile ifNil: [^ 0.0]. mpegFile fileHandle ifNil: [^ 0.0]. self isThereAFile ifFalse: [^0.0]. mpegFile hasVideo ifTrue: [^ ((mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0)) min: 1.0]. soundTrack ifNotNil: [^ soundTrack soundPosition]. ^ 0.0 ! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalFrames "Answer the total number of frames in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ mpegFile videoFrames: 0! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalSeconds "Answer the total number of seconds in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ self totalFrames asFloat / (mpegFile videoFrameRate: 0)! ! !MPEGDisplayMorph methodsFor: 'commands' stamp: 'JMM 1/20/2006 23:09'! startPlaying "Start playing the movie at the current position." | frameIndex | self stopPlaying. stopFrame := nil. self mpegFileIsOpen ifFalse: [^ self]. (mpegFile fileName notNil) ifTrue: [(FileStream isAFileNamed: mpegFile fileName) ifFalse: [ | newFileResult newFileName | self inform: 'Path changed. Enter new one for: ', (FileDirectory localNameFor: mpegFile fileName). newFileResult := StandardFileMenu oldFile. newFileName := newFileResult directory fullNameFor: newFileResult name. mpegFile openFile: newFileName]]. mpegFile hasAudio ifTrue: [mpegFile hasVideo ifTrue: ["set movie frame position from soundTrack position" soundTrack reset. "ensure file is open before positioning" soundTrack soundPosition: (mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0). "now set frame index from the soundtrack position for best sync" frameIndex := ((soundTrack millisecondsSinceStart * desiredFrameRate) // 1000). frameIndex := (frameIndex max: 0) min: ((mpegFile videoFrames: 0) - 3). mpegFile videoSetFrame: frameIndex stream: 0]. SoundPlayer stopReverb. soundTrack volume: volume. soundTrack repeat: repeat. soundTrack resumePlaying. startFrame := startMSecs := 0] ifFalse: [soundTrack := nil. startFrame := mpegFile videoGetFrame: 0. startMSecs := Time millisecondClockValue]. running := true! ! !MPEGDisplayMorph methodsFor: 'file open/close' stamp: 'JMM 1/20/2006 23:02'! openFileNamed: mpegFileName "Try to open the MPEG file with the given name. Answer true if successful." | e | self closeFile. (FileDirectory default fileExists: mpegFileName) ifFalse: [self inform: ('File not found: {1}' translated format: {mpegFileName}). ^ false]. (MPEGFile isFileValidMPEG: mpegFileName) ifTrue: [mpegFile := MPEGFile openFileUseBuffer: mpegFileName] ifFalse: [ (JPEGMovieFile isJPEGMovieFile: mpegFileName) ifTrue: [mpegFile := JPEGMovieFile new openFileNamed: mpegFileName] ifFalse: [self inform: ('Not an MPEG or JPEG movie file: {1}' translated format: {mpegFileName}). ^ false]]. mpegFile fileHandle ifNil: [^ false]. "initialize soundTrack" mpegFile hasAudio ifTrue: [soundTrack := mpegFile audioPlayerForChannel: 1] ifFalse: [soundTrack := nil]. mpegFile hasVideo ifTrue: [ "set screen size and display first frame" desiredFrameRate := mpegFile videoFrameRate: 0. soundTrack ifNotNil: [ "compute frame rate from length of audio track" desiredFrameRate := (mpegFile videoFrames: 0) / soundTrack duration]. e := (mpegFile videoFrameWidth: 0)@(mpegFile videoFrameHeight: 0). frameBuffer := Form extent: e depth: (Display depth max: 16). super extent: e. self nextFrame] ifFalse: [ "hide screen for audio-only files" super extent: 250@0]. ! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/JMMMpegPluginBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 26 February 2006 at 1:16:10 pm'! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:07'! primitiveMPEG3CheckSig: path | result sz storage | "int mpeg3_check_sig(char *path)" self var: #storage declareC: 'char storage[1024] '. self primitive: 'primitiveMPEG3CheckSig' parameters: #(String). sz _ interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. self cCode: 'result = mpeg3_check_sig(storage)'. ^result asOop: Boolean ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 18:38'! primitiveMPEG3OpenABuffer: path size: size | mpeg3Oop index | self var: #index declareC: 'mpeg3_t ** index'. self primitive: 'primitiveMPEG3OpenABuffer' parameters: #(String SmallInteger). mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(path,size); makeFileEntry(*index)'. ^mpeg3Oop. ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:11'! primitiveMPEG3Open: path | mpeg3Oop index sz storage | "mpeg3_t* mpeg3_open(char *path)" self var: #index declareC: 'mpeg3_t ** index'. self var: #storage declareC: 'char storage[1024]'. self primitive: 'primitiveMPEG3Open' parameters: #(String). sz := interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(storage,0); makeFileEntry(*index)'. ^mpeg3Oop. ! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/JMMMpegPluginaddBufferOffsetting.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 26 February 2006 at 1:12:11 pm'! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 2/26/2006 13:02'! primitiveMPEG3ReadFrame: fileHandle buffer: aBuffer bufferOffset: aBufferOffset x: xNumber y: yNumber w: width h: height ow: outWidth oh: outHeight colorModel: model stream: aNumber bytesPerRow: aByteNumber | file result outputRowsPtr bufferBaseAddr | "int mpeg3_read_frame(mpeg3_t *file, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model, int stream)" self primitive: 'primitiveMPEG3ReadFrameBufferOffset' parameters: #(Oop WordArray SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger). self var: #file declareC: 'mpeg3_t * file'. self var: #bufferBaseAddr declareC: 'unsigned char *bufferBaseAddr'. self var: #outputRowsPtr declareC: 'unsigned char ** outputRowsPtr'. file := self mpeg3tValueOf: fileHandle. file = nil ifTrue: [^0]. aNumber < 0 ifTrue: [ interpreterProxy success: false. ^nil ]. aNumber >= (self cCode: 'result = mpeg3_total_vstreams(file)') ifTrue: [ interpreterProxy success: false. ^0 ]. bufferBaseAddr := self cCoerce: aBuffer to: 'unsigned char *'. self cCode: 'outputRowsPtr = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * outHeight)'. 0 to: outHeight-1 do: [:i | outputRowsPtr at: i put: (bufferBaseAddr + aBufferOffset + (aByteNumber*i))]. self cCode: 'result = mpeg3_read_frame(file,outputRowsPtr,xNumber,yNumber,width,height,outWidth,outHeight,model,aNumber)'. self cCode: 'memoryFree(outputRowsPtr)'. ^result asSmallIntegerObj ! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/JMMMpegaddBufferOffsetting.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 26 February 2006 at 1:12:11 pm'! !MPEGFile methodsFor: 'primitives' stamp: 'JMM 2/26/2006 13:08'! primVideoReadNextFrameFor: aFileHandle into: aFormBuffer offset: aBufferOffsetInBytes x: x y: y width: width height: height outWidth: aTargetWidth outHeight: aTargetHeight colorModel: colorModel stream: aStream bytesPerRow: aByteCount ! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/Mpeg3Plugin.h ================================================ #include "changesForSqueak.h" #include "libmpeg3.h" ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/README ================================================ /******************************************************** * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html * *******************************************************/ /********************************************************** * Credits: *********************************************************/ Port to Squeak and Macintosh By John M McIntosh (johnmci@smalltalkconsulting.com) Problems: Streams where the multiplexing packet size changes at random. ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/docs/index.html ================================================ LibMPEG3
Using LibMPEG3 to make your own MPEG applications

Author: Adam Williams broadcast@earthling.net
Homepage: heroinewarrior.com

LibMPEG3 decodes the many many derivatives of MPEG standards into uncompressed data suitable for editing and playback.

libmpeg3 currently decodes:

MPEG-2 video
MPEG-1 video
mp3 audio
mp2 audio
ac3 audio (not in Squeak)
MPEG-2 system streams
MPEG-1 system streams

The video output can be in many different color models and frame sizes. The audio output can be in twos compliment or floating point.

STEP 1: Verifying file compatibility

Programs using libmpeg3 must #include "libmpeg3.h".

Call mpeg3_check_sig to verify if the file can be read by libmpeg3. This returns a 1 if it is compatible and 0 if it isn't.

STEP 2: Open the file

You need an mpeg3_t* file descriptor:

mpeg3_t* file;

Then you need to open the file:

file = mpeg3_open(char *path);

mpeg3_open returns a NULL if the file couldn't be opened for some reason. Be sure to check this. Everything you do with libmpeg3 requires passing the file pointer.

STEP 3: How many CPUs do you want to use?

Call mpeg3_set_cpus(mpeg3_t *file, int cpus) to set how many CPUs should be devoted to video decompression. LibMPEG3 can use any number. If you don't call this right after opening the file, the CPU number defaults to 1.

STEP 4: Get some information about the file.

There are a number of queries for the audio components of the stream:

int mpeg3_has_audio(mpeg3_t *file);
int mpeg3_total_astreams(mpeg3_t *file);             // Number of multiplexed audio streams
int mpeg3_audio_channels(mpeg3_t *file, int stream);
int mpeg3_sample_rate(mpeg3_t *file, int stream);
long mpeg3_audio_samples(mpeg3_t *file, int stream); // Total length
The audio is presented as a number of streams starting at 0 and including mpeg3_total_astreams - 1. Each stream contains a certain number of channels starting at 0 and including mpeg3_audio_channels - 1. The methodology is first determine if the file has audio, then get the number of streams in the file, then for each stream get the number of channels, sample rate, and length.

There are also queries for the video components:

int mpeg3_has_video(mpeg3_t *file);
int mpeg3_total_vstreams(mpeg3_t *file);            // Number of multiplexed video streams
int mpeg3_video_width(mpeg3_t *file, int stream);
int mpeg3_video_height(mpeg3_t *file, int stream);
float mpeg3_frame_rate(mpeg3_t *file, int stream);  // Frames/sec
long mpeg3_video_frames(mpeg3_t *file, int stream); // Total length
The video behavior is the same as with audio, except that video has no subdivision under streams. Frame rate is a floating point number of frames per second.

STEP 5: Seeking to a point in the file

Each audio stream and each video stream has a position in the file independant of each other stream. A variety of methods are available for specifying the position of a stream: percentage, frame, sample. Which method you use depends on whether you're seeking audio or video and whether you're seeking all tracks to a percentage of the file.

The preferred seeking method if you're writing a player is:

int mpeg3_seek_percentage(mpeg3_t *file, double percentage);
double mpeg3_tell_percentage(mpeg3_t *file);
This seeks all tracks to a percentage of the file length. The percentage is from 0 to 1.

The alternative is absolute seeking. The audio seeking is handled by:

int mpeg3_set_sample(mpeg3_t *file, long sample, int stream);    // Seek
long mpeg3_get_sample(mpeg3_t *file, int stream);    // Tell current position
and the video seeking is handled by:

int mpeg3_set_frame(mpeg3_t *file, long frame, int stream); // Seek
long mpeg3_get_frame(mpeg3_t *file, int stream);            // Tell current position
You can either perform percentage seeking or absolute seeking but not both on the same file handle. Once you perform either method, the file becomes configured for that method.

If you're in percentage seeking mode and you want the current time stamp in the file you can't use mpeg3_tell_percentage because you don't know how many seconds the total length is. The mpeg3_audio_samples and mpeg3_video_frames commands don't work in percentage seeking. Instead use

double mpeg3_get_time(mpeg3_t *file);
which gives you the last timecode read in seconds. The MPEG standard specifies timecodes being placed in the streams.

STEP 6: Read the data

To read audio data use:

int mpeg3_read_audio(mpeg3_t *file, 
		float *output_f,      // Pointer to pre-allocated buffer of floats
		short *output_i,      // Pointer to pre-allocated buffer if int16's
		int channel,          // Channel to decode
		long samples,         // Number of samples to decode
		int stream);          // Stream containing the channel
This decodes a buffer of sequential floats or int16's for a single channel, depending on which *output... parameter has a nonzero argument. To get a floating point buffer pass a pre-allocated buffer to output_f and NULL to output_i. To get an int16 buffer pass NULL to output_f and a pre-allocated buffer to output_i.

After reading an audio buffer, the current position in the one stream is advanced. How then, do you read more than one channel of audio data? Use

mpeg3_reread_audio(mpeg3_t *file, 
		float *output_f,      /* Pointer to pre-allocated buffer of floats */
		short *output_i,      /* Pointer to pre-allocated buffer of int16's */
		int channel,          /* Channel to decode */
		long samples,         /* Number of samples to decode */
		int stream);
to read each remaining channel after the first channel.

To read video data there are two methods. RGB frames or YUV frames. To get an RGB frame use:

int mpeg3_read_frame(mpeg3_t *file, 
		unsigned char **output_rows, // Array of pointers to the start of each output row
		int in_x,                    // Location in input frame to take picture
		int in_y, 
		int in_w, 
		int in_h, 
		int out_w,                   // Dimensions of output_rows
		int out_h, 
		int color_model,             // One of the color model #defines given above.
		int stream);
The video decoding works like a camcorder taking copy of a movie screen. The decoder "sees" a region of the movie screen defined by in_x, in_y, in_w, in_h and transfers it to the frame buffer defined by **output_rows. The input values must be within the boundaries given by mpeg3_video_width and mpeg3_video_height. The size of the frame buffer is defined by out_w, out_h. Although the input dimensions are constrained, the frame buffer can be any size.

color_model defines which RGB color model the picture should be decoded to and the possible values are given in libmpeg3.h. The frame buffer pointed to by output_rows must have enough memory allocated to store the color model you select.

You must allocate 4 extra bytes in the last output_row. This is scratch area for the MMX routines.

mpeg3_read_frame advances the position in the one stream by 1 frame.

The alternative is YUV frames:

int mpeg3_read_yuvframe(mpeg3_t *file,
		char *y_output,
		char *u_output,
		char *v_output,
		int in_x,
		int in_y,
		int in_w,
		int in_h,
		int stream);
The behavior of in_x, in_y, in_w, in_h is identical to mpeg3_read_frame except here you have no control over the output frame size. You must allocate in_w * in_h for the y_output, and in_w * in_h / 4 for the chroma outputs.

STEP 7: Close the file

Be sure to close the file with mpeg3_close(mpeg3_t *file) when you're done with it. ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/examplesSqueak.txt ================================================ "Find a file" MPEGFile isFileValidMPEG: 'randomalien.mpg'. "Explore the file" | foo | foo _ MPEGFile openFile: 'randomalien.mpg'. foo hasVideo. foo hasAudio. foo endOfVideo: 0. foo endOfAudio: 0. foo audioChannels: 0. foo audioSamples: 0. foo audioGetSample: 0. foo audioSampleRate: 0. foo videoFrameRate: 0. foo videoGetFrame: 0. foo audioGetSample: 0. foo getTimeCode. foo videoPreviousFrame: 0. foo videoSetCPUs: 1. foo videoSetFrame: 44 stream: 0. foo setMMX: true. foo audioSetSample: 44 stream: 0. foo totalAudioStreams. foo totalVideoStreams. foo videoFrames: 0. foo videoFrameHeight: 0. foo videoFrameWidth: 0. foo seekPercentage: 0.5. foo getPercentage. foo videoSetCPUs: 1. foo setMMX: true. foo closeFile. ----------------------------------- "Simply get the video start at 700 and run 50 frames then debug" "Better code is in the player, don't use this code, but it's an example" | foo x y counter fum | foo _ MPEGFile openFile: 'randomalien.mpg'. stream _ 0. counter _ 0. y _ foo videoFrameHeight: stream. x _ foo videoFrameWidth: stream. fum _ Form extent: x@y depth: 32. frames _ foo videoFrames: stream. foo videoSetFrame: 700 stream: stream. [foo endOfVideo: stream] whileFalse: [foo videoReadNextFrameInto: fum bits width: fum width height: fum height stream: stream. fum displayOn: Display. (counter _ counter + 1) == 50 ifTrue: [self halt]]. foo closeFile. ----------------------------------- "Play the audio" "There is more than one way to do this" "This is my first technically correct try" "DO not use this code, better code is in the player" | foo buffer sound soundOther | foo _ MPEGFile openFile: 'randomalien.mpg'. channels _ foo audioChannels: 0. sampleRate _ foo audioSampleRate: 0. totalSamples _ foo audioSamples: 0. buffer _ ByteArray new: 1024*1024*1. SoundPlayer startPlayerProcessBufferSize: 8192 rate: sampleRate stereo: true. result _ foo audioReadBuffer: buffer stream: 0 channel: 0 samples: 1024*1024//2. sound _ SampledSound samples: (SampledSound convertBytesTo16BitSamples: buffer mostSignificantByteFirst: true) samplingRate: sampleRate. result _ foo audioReReadBuffer: buffer stream: 0 channel: 1 samples: 1024*1024//2. soundOther _ SampledSound samples: (SampledSound convertBytesTo16BitSamples: buffer mostSignificantByteFirst: true) samplingRate: sampleRate. sound _ MixedSound new add: sound pan: 0; add: soundOther pan: 1.0. sound play ----------------------------------- "Ok make it simple for Audio" | foo | form _ Form extent: 320@240 depth: 16. foo _ MPEGPlayer playFile: 'randomAlien.mpg' onForm: form. foo playAudioStreamWaitTilDone: 0. ----------------------------------- "Ok make it simple for Video" | foo | form _ Form extent: 320@240 depth: 32. foo _ MPEGPlayer playFile: 'randomAlien.mpg' onForm: form. foo playVideoStreamWaitTilDone: 0. ----------------------------------- "Play the video in the background" | foo | form _ Form extent: 320@240 depth: 16. foo _ MPEGPlayer playFile: 'randomAlien.mpg' onForm: form. foo playVideoStream: 0. foo inspect. ----------------------------------- "Play both in the background" | foo | form _ Form extent: 320@240 depth: 16. foo _ MPEGPlayer playFile: 'randomAlien.mpg' onForm: form. foo playStream: 0. foo inspect. ------------------------- " In Morphic do " | foo | form _ Form extent: 320@240 depth: 32. morph _ SketchMorph withForm: form. morph openInWorld. foo _ MPEGPlayer playFile: 'randomAlien.mpg' onMorph: morph. foo morph: morph. foo playStream: 0. foo inspect. ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/Makefile ================================================ ### automatically generated by ./mkMakefile ### settings for building libmpeg by itself LIBMPEG_CC=cc LIBMPEG_CFLAGS= LIBMPEG_LINKLIB=ar rcs LIBMPEG_NASM=nasm -f elf LIBMPEG_SOURCE_DIR=. LIBMPEG_BUILD_DIR=. LIBMPEG_OBJECT_EXT=o LIBMPEG_LIBRARY_EXT=a ### default rule: build the library default : libmpeg3.a ### Update the makefile when needed Makefile : mkMakefile ./mkMakefile #### automatically generated by ./mkMakefile # flags for compiling libmpeg LIBMPEG_CFLAGS += -I$(LIBMPEG_SOURCE_DIR) -I$(LIBMPEG_SOURCE_DIR)/audio -I$(LIBMPEG_SOURCE_DIR)/video # a file that indicates the build tree has been created LIBMPEG_BUILD_DIR_CREATED=$(LIBMPEG_BUILD_DIR)/tree.created LIBMPEG_CFLAGS += -DNOPTHREADS $(LIBMPEG_BUILD_DIR_CREATED): mkdir -p $(LIBMPEG_BUILD_DIR) mkdir -p $(LIBMPEG_BUILD_DIR)/audio mkdir -p $(LIBMPEG_BUILD_DIR)/video touch $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_BUILD_DIR)/bitstream.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/bitstream.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/bitstream.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/bitstream.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/libmpeg3.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/libmpeg3.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/mpeg3atrack.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/mpeg3atrack.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/mpeg3atrack.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/mpeg3atrack.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/mpeg3demux.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/mpeg3demux.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/mpeg3demux.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/mpeg3demux.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/mpeg3io.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/mpeg3io.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/mpeg3io.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/mpeg3io.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/mpeg3title.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/mpeg3title.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/mpeg3title.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/mpeg3title.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/mpeg3vtrack.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/mpeg3vtrack.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/mpeg3vtrack.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/mpeg3vtrack.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/changesForSqueak.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/changesForSqueak.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/changesForSqueak.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/changesForSqueak.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/dct.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/dct.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/dct.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/dct.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/header.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/header.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/header.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/header.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/layer2.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/layer2.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/layer2.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/layer2.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/layer3.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/layer3.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/layer3.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/layer3.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/mpeg3audio.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/mpeg3audio.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/mpeg3audio.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/mpeg3audio.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/pcm.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/pcm.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/pcm.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/pcm.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/synthesizers.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/synthesizers.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/synthesizers.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/synthesizers.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/audio/tables.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/audio/tables.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/audio/tables.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/audio/tables.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/getpicture.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/getpicture.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/getpicture.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/getpicture.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/headers.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/headers.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/headers.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/headers.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/idct.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/idct.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/idct.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/idct.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/macroblocks.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/macroblocks.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/macroblocks.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/macroblocks.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/mmxtest.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/mmxtest.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/mmxtest.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/mmxtest.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/motion.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/motion.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/motion.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/motion.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/mpeg3video.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/mpeg3video.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/mpeg3video.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/mpeg3video.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/output.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/output.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/output.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/output.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/reconstruct.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/reconstruct.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/reconstruct.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/reconstruct.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/seek.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/seek.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/seek.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/seek.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/slice.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/slice.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/slice.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/slice.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/video/vlc.$(LIBMPEG_OBJECT_EXT): $(LIBMPEG_BUILD_DIR_CREATED) $(LIBMPEG_SOURCE_DIR)/video/vlc.c $(LIBMPEG_CC) -o $(LIBMPEG_BUILD_DIR)/video/vlc.$(LIBMPEG_OBJECT_EXT) -c $(LIBMPEG_SOURCE_DIR)/video/vlc.c $(LIBMPEG_CFLAGS) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_LIBRARY_EXT): $(LIBMPEG_BUILD_DIR)/bitstream.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3atrack.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3demux.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3io.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3title.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3vtrack.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/changesForSqueak.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/dct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/header.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/layer2.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/layer3.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/mpeg3audio.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/pcm.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/synthesizers.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/tables.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/getpicture.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/headers.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/idct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/macroblocks.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/mmxtest.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/motion.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/mpeg3video.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/output.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/reconstruct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/seek.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/slice.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/vlc.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_LINKLIB) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_LIBRARY_EXT) $(LIBMPEG_BUILD_DIR)/bitstream.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3atrack.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3demux.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3io.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3title.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/mpeg3vtrack.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/changesForSqueak.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/dct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/header.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/layer2.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/layer3.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/mpeg3audio.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/pcm.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/synthesizers.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/audio/tables.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/getpicture.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/headers.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/idct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/macroblocks.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/mmxtest.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/motion.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/mpeg3video.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/output.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/reconstruct.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/seek.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/slice.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/video/vlc.$(LIBMPEG_OBJECT_EXT) clean: clean_libmpeg clean_libmpeg: rm -f $(LIBMPEG_BUILD_DIR)/*.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/*/*.$(LIBMPEG_OBJECT_EXT) $(LIBMPEG_BUILD_DIR)/libmpeg3.$(LIBMPEG_LIBRARY_EXT) $(LIBMPEG_BUILD_DIR_CREATED) #### end of rules generated by ./mkMakefile ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/ac3.h ================================================ #ifndef AC3_H #define AC3_H #define MAX_AC3_FRAMESIZE 1920 * 2 + 512 //extern int mpeg3_ac3_samplerates[3]; /* Exponent strategy constants */ #define MPEG3_EXP_REUSE (0) #define MPEG3_EXP_D15 (1) #define MPEG3_EXP_D25 (2) #define MPEG3_EXP_D45 (3) /* Delta bit allocation constants */ #define DELTA_BIT_REUSE (0) #define DELTA_BIT_NEW (1) #define DELTA_BIT_NONE (2) #define DELTA_BIT_RESERVED (3) typedef float mpeg3ac3_stream_samples_t[6][256]; typedef struct { /* Bit stream identification == 0x8 */ int bsid; /* Bit stream mode */ int bsmod; /* Audio coding mode */ int acmod; /* If we're using the centre channel then */ /* centre mix level */ int cmixlev; /* If we're using the surround channel then */ /* surround mix level */ int surmixlev; /* If we're in 2/0 mode then */ /* Dolby surround mix level - NOT USED - */ int dsurmod; /* Low frequency effects on */ int lfeon; /* Dialogue Normalization level */ int dialnorm; /* Compression exists */ int compre; /* Compression level */ int compr; /* Language code exists */ int langcode; /* Language code */ int langcod; /* Audio production info exists*/ unsigned int audprodie; int mixlevel; int roomtyp; /* If we're in dual mono mode (acmod == 0) then extra stuff */ int dialnorm2; int compr2e; int compr2; int langcod2e; int langcod2; int audprodi2e; int mixlevel2; int roomtyp2; /* Copyright bit */ int copyrightb; /* Original bit */ int origbs; /* Timecode 1 exists */ int timecod1e; /* Timecode 1 */ unsigned int timecod1; /* Timecode 2 exists */ int timecod2e; /* Timecode 2 */ unsigned int timecod2; /* Additional bit stream info exists */ int addbsie; /* Additional bit stream length - 1 (in bytes) */ int addbsil; /* Additional bit stream information (max 64 bytes) */ unsigned char addbsi[64]; /* Information not in the AC-3 bitstream, but derived */ /* Number of channels (excluding LFE) * Derived from acmod */ int nfchans; } mpeg3_ac3bsi_t; typedef struct { /* block switch bit indexed by channel num */ unsigned short blksw[5]; /* dither enable bit indexed by channel num */ unsigned short dithflag[5]; /* dynamic range gain exists */ int dynrnge; /* dynamic range gain */ int dynrng; /* if acmod==0 then */ /* dynamic range 2 gain exists */ int dynrng2e; /* dynamic range 2 gain */ int dynrng2; /* coupling strategy exists */ int cplstre; /* coupling in use */ int cplinu; /* channel coupled */ unsigned short chincpl[5]; /* if acmod==2 then */ /* Phase flags in use */ int phsflginu; /* coupling begin frequency code */ int cplbegf; /* coupling end frequency code */ int cplendf; /* coupling band structure bits */ unsigned short cplbndstrc[18]; /* Do coupling co-ords exist for this channel? */ unsigned short cplcoe[5]; /* Master coupling co-ordinate */ unsigned short mstrcplco[5]; /* Per coupling band coupling co-ordinates */ unsigned short cplcoexp[5][18]; unsigned short cplcomant[5][18]; /* Phase flags for dual mono */ unsigned short phsflg[18]; /* Is there a rematrixing strategy */ unsigned int rematstr; /* Rematrixing bits */ unsigned short rematflg[4]; /* Coupling exponent strategy */ int cplexpstr; /* Exponent strategy for full bandwidth channels */ unsigned short chexpstr[5]; /* Exponent strategy for lfe channel */ int lfeexpstr; /* Channel bandwidth for independent channels */ unsigned short chbwcod[5]; /* The absolute coupling exponent */ int cplabsexp; /* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */ unsigned short cplexps[18 * 12 / 3]; /* fbw channel exponents */ unsigned short exps[5][252 / 3]; /* channel gain range */ unsigned short gainrng[5]; /* low frequency exponents */ unsigned short lfeexps[3]; /* Bit allocation info */ int baie; /* Slow decay code */ int sdcycod; /* Fast decay code */ int fdcycod; /* Slow gain code */ int sgaincod; /* dB per bit code */ int dbpbcod; /* masking floor code */ int floorcod; /* SNR offset info */ int snroffste; /* coarse SNR offset */ int csnroffst; /* coupling fine SNR offset */ int cplfsnroffst; /* coupling fast gain code */ int cplfgaincod; /* fbw fine SNR offset */ unsigned short fsnroffst[5]; /* fbw fast gain code */ unsigned short fgaincod[5]; /* lfe fine SNR offset */ int lfefsnroffst; /* lfe fast gain code */ int lfefgaincod; /* Coupling leak info */ int cplleake; /* coupling fast leak initialization */ int cplfleak; /* coupling slow leak initialization */ int cplsleak; /* delta bit allocation info */ int deltbaie; /* coupling delta bit allocation exists */ int cpldeltbae; /* fbw delta bit allocation exists */ unsigned short deltbae[5]; /* number of cpl delta bit segments */ int cpldeltnseg; /* coupling delta bit allocation offset */ unsigned short cpldeltoffst[8]; /* coupling delta bit allocation length */ unsigned short cpldeltlen[8]; /* coupling delta bit allocation length */ unsigned short cpldeltba[8]; /* number of delta bit segments */ unsigned short deltnseg[5]; /* fbw delta bit allocation offset */ unsigned short deltoffst[5][8]; /* fbw delta bit allocation length */ unsigned short deltlen[5][8]; /* fbw delta bit allocation length */ unsigned short deltba[5][8]; /* skip length exists */ int skiple; /* skip length */ int skipl; /* channel mantissas */ short chmant[5][256]; /* coupling mantissas */ unsigned short cplmant[256]; /* coupling mantissas */ unsigned short lfemant[7]; /* -- Information not in the bitstream, but derived thereof -- */ /* Number of coupling sub-bands */ int ncplsubnd; /* Number of combined coupling sub-bands * Derived from ncplsubnd and cplbndstrc */ int ncplbnd; /* Number of exponent groups by channel * Derived from strmant, endmant */ int nchgrps[5]; /* Number of coupling exponent groups * Derived from cplbegf, cplendf, cplexpstr */ int ncplgrps; /* End mantissa numbers of fbw channels */ unsigned short endmant[5]; /* Start and end mantissa numbers for the coupling channel */ int cplstrtmant; int cplendmant; /* Decoded exponent info */ unsigned short fbw_exp[5][256]; unsigned short cpl_exp[256]; unsigned short lfe_exp[7]; /* Bit allocation pointer results */ unsigned short fbw_bap[5][256]; /*FIXME figure out exactly how many entries there should be (253-37?) */ unsigned short cpl_bap[256]; unsigned short lfe_bap[7]; } mpeg3_ac3audblk_t; /* Bit allocation data */ typedef struct { int sdecay; int fdecay; int sgain; int dbknee; int floor; short psd[256]; short bndpsd[256]; short excite[256]; short mask[256]; } mpeg3_ac3_bitallocation_t; /* Mantissa data */ typedef struct { unsigned short m_1[3]; unsigned short m_2[3]; unsigned short m_4[2]; unsigned short m_1_pointer; unsigned short m_2_pointer; unsigned short m_4_pointer; } mpeg3_ac3_mantissa_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/dct.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* * Discrete Cosine Tansform (DCT) for subband synthesis * optimized for machines with no auto-increment. * The performance is highly compiler dependend. Maybe * the dct64.c version for 'normal' processor may be faster * even for Intel processors. */ #include "mpeg3audio.h" #include "tables.h" #include int mpeg3audio_dct64_1(float *out0, float *out1, float *b1, float *b2, float *samples) { register float *costab = mpeg3_pnts[0]; b1[0x00] = samples[0x00] + samples[0x1F]; b1[0x01] = samples[0x01] + samples[0x1E]; b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; b1[0x02] = samples[0x02] + samples[0x1D]; b1[0x03] = samples[0x03] + samples[0x1C]; b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; b1[0x04] = samples[0x04] + samples[0x1B]; b1[0x05] = samples[0x05] + samples[0x1A]; b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; b1[0x06] = samples[0x06] + samples[0x19]; b1[0x07] = samples[0x07] + samples[0x18]; b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; b1[0x08] = samples[0x08] + samples[0x17]; b1[0x09] = samples[0x09] + samples[0x16]; b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; b1[0x0A] = samples[0x0A] + samples[0x15]; b1[0x0B] = samples[0x0B] + samples[0x14]; b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; b1[0x0C] = samples[0x0C] + samples[0x13]; b1[0x0D] = samples[0x0D] + samples[0x12]; b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; b1[0x0E] = samples[0x0E] + samples[0x11]; b1[0x0F] = samples[0x0F] + samples[0x10]; b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; costab = mpeg3_pnts[1]; b2[0x00] = b1[0x00] + b1[0x0F]; b2[0x01] = b1[0x01] + b1[0x0E]; b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; b2[0x02] = b1[0x02] + b1[0x0D]; b2[0x03] = b1[0x03] + b1[0x0C]; b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; b2[0x04] = b1[0x04] + b1[0x0B]; b2[0x05] = b1[0x05] + b1[0x0A]; b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; b2[0x06] = b1[0x06] + b1[0x09]; b2[0x07] = b1[0x07] + b1[0x08]; b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; /* */ b2[0x10] = b1[0x10] + b1[0x1F]; b2[0x11] = b1[0x11] + b1[0x1E]; b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; b2[0x12] = b1[0x12] + b1[0x1D]; b2[0x13] = b1[0x13] + b1[0x1C]; b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; b2[0x14] = b1[0x14] + b1[0x1B]; b2[0x15] = b1[0x15] + b1[0x1A]; b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; b2[0x16] = b1[0x16] + b1[0x19]; b2[0x17] = b1[0x17] + b1[0x18]; b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; costab = mpeg3_pnts[2]; b1[0x00] = b2[0x00] + b2[0x07]; b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; b1[0x01] = b2[0x01] + b2[0x06]; b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; b1[0x02] = b2[0x02] + b2[0x05]; b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; b1[0x03] = b2[0x03] + b2[0x04]; b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; b1[0x08] = b2[0x08] + b2[0x0F]; b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; b1[0x09] = b2[0x09] + b2[0x0E]; b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; b1[0x0A] = b2[0x0A] + b2[0x0D]; b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; b1[0x0B] = b2[0x0B] + b2[0x0C]; b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; b1[0x10] = b2[0x10] + b2[0x17]; b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; b1[0x11] = b2[0x11] + b2[0x16]; b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; b1[0x12] = b2[0x12] + b2[0x15]; b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; b1[0x13] = b2[0x13] + b2[0x14]; b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; b1[0x18] = b2[0x18] + b2[0x1F]; b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; b1[0x19] = b2[0x19] + b2[0x1E]; b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; b1[0x1A] = b2[0x1A] + b2[0x1D]; b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; b1[0x1B] = b2[0x1B] + b2[0x1C]; b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; { register float const cos0 = mpeg3_pnts[3][0]; register float const cos1 = mpeg3_pnts[3][1]; b2[0x00] = b1[0x00] + b1[0x03]; b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; b2[0x01] = b1[0x01] + b1[0x02]; b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; b2[0x04] = b1[0x04] + b1[0x07]; b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; b2[0x05] = b1[0x05] + b1[0x06]; b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; b2[0x08] = b1[0x08] + b1[0x0B]; b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; b2[0x09] = b1[0x09] + b1[0x0A]; b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; b2[0x0C] = b1[0x0C] + b1[0x0F]; b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; b2[0x0D] = b1[0x0D] + b1[0x0E]; b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; b2[0x10] = b1[0x10] + b1[0x13]; b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; b2[0x11] = b1[0x11] + b1[0x12]; b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; b2[0x14] = b1[0x14] + b1[0x17]; b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; b2[0x15] = b1[0x15] + b1[0x16]; b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; b2[0x18] = b1[0x18] + b1[0x1B]; b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; b2[0x19] = b1[0x19] + b1[0x1A]; b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; b2[0x1C] = b1[0x1C] + b1[0x1F]; b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; b2[0x1D] = b1[0x1D] + b1[0x1E]; b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; } { register float const cos0 = mpeg3_pnts[4][0]; b1[0x00] = b2[0x00] + b2[0x01]; b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; b1[0x02] = b2[0x02] + b2[0x03]; b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; b1[0x02] += b1[0x03]; b1[0x04] = b2[0x04] + b2[0x05]; b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; b1[0x06] = b2[0x06] + b2[0x07]; b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; b1[0x06] += b1[0x07]; b1[0x04] += b1[0x06]; b1[0x06] += b1[0x05]; b1[0x05] += b1[0x07]; b1[0x08] = b2[0x08] + b2[0x09]; b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; b1[0x0A] = b2[0x0A] + b2[0x0B]; b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; b1[0x0A] += b1[0x0B]; b1[0x0C] = b2[0x0C] + b2[0x0D]; b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; b1[0x0E] = b2[0x0E] + b2[0x0F]; b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; b1[0x0E] += b1[0x0F]; b1[0x0C] += b1[0x0E]; b1[0x0E] += b1[0x0D]; b1[0x0D] += b1[0x0F]; b1[0x10] = b2[0x10] + b2[0x11]; b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; b1[0x12] = b2[0x12] + b2[0x13]; b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; b1[0x12] += b1[0x13]; b1[0x14] = b2[0x14] + b2[0x15]; b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; b1[0x16] = b2[0x16] + b2[0x17]; b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; b1[0x16] += b1[0x17]; b1[0x14] += b1[0x16]; b1[0x16] += b1[0x15]; b1[0x15] += b1[0x17]; b1[0x18] = b2[0x18] + b2[0x19]; b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; b1[0x1A] = b2[0x1A] + b2[0x1B]; b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; b1[0x1A] += b1[0x1B]; b1[0x1C] = b2[0x1C] + b2[0x1D]; b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; b1[0x1E] = b2[0x1E] + b2[0x1F]; b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; b1[0x1E] += b1[0x1F]; b1[0x1C] += b1[0x1E]; b1[0x1E] += b1[0x1D]; b1[0x1D] += b1[0x1F]; } out0[0x10*16] = b1[0x00]; out0[0x10*12] = b1[0x04]; out0[0x10* 8] = b1[0x02]; out0[0x10* 4] = b1[0x06]; out0[0x10* 0] = b1[0x01]; out1[0x10* 0] = b1[0x01]; out1[0x10* 4] = b1[0x05]; out1[0x10* 8] = b1[0x03]; out1[0x10*12] = b1[0x07]; out0[0x10*14] = b1[0x08] + b1[0x0C]; out0[0x10*10] = b1[0x0C] + b1[0x0a]; out0[0x10* 6] = b1[0x0A] + b1[0x0E]; out0[0x10* 2] = b1[0x0E] + b1[0x09]; out1[0x10* 2] = b1[0x09] + b1[0x0D]; out1[0x10* 6] = b1[0x0D] + b1[0x0B]; out1[0x10*10] = b1[0x0B] + b1[0x0F]; out1[0x10*14] = b1[0x0F]; { register float tmp; tmp = b1[0x18] + b1[0x1C]; out0[0x10*15] = tmp + b1[0x10]; out0[0x10*13] = tmp + b1[0x14]; tmp = b1[0x1C] + b1[0x1A]; out0[0x10*11] = tmp + b1[0x14]; out0[0x10* 9] = tmp + b1[0x12]; tmp = b1[0x1A] + b1[0x1E]; out0[0x10* 7] = tmp + b1[0x12]; out0[0x10* 5] = tmp + b1[0x16]; tmp = b1[0x1E] + b1[0x19]; out0[0x10* 3] = tmp + b1[0x16]; out0[0x10* 1] = tmp + b1[0x11]; tmp = b1[0x19] + b1[0x1D]; out1[0x10* 1] = tmp + b1[0x11]; out1[0x10* 3] = tmp + b1[0x15]; tmp = b1[0x1D] + b1[0x1B]; out1[0x10* 5] = tmp + b1[0x15]; out1[0x10* 7] = tmp + b1[0x13]; tmp = b1[0x1B] + b1[0x1F]; out1[0x10* 9] = tmp + b1[0x13]; out1[0x10*11] = tmp + b1[0x17]; out1[0x10*13] = b1[0x17] + b1[0x1F]; out1[0x10*15] = b1[0x1F]; } return 0; } /* * the call via dct64 is a trick to force GCC to use * (new) registers for the b1,b2 pointer to the bufs[xx] field */ int mpeg3audio_dct64(float *a, float *b, float *c) { float bufs[0x40]; return mpeg3audio_dct64_1(a, b, bufs, bufs + 0x20, c); } /*//////////////////////////////////////////////////////////////// */ /* */ /* 9 Point Inverse Discrete Cosine Transform */ /* */ /* This piece of code is Copyright 1997 Mikko Tommila and is freely usable */ /* by anybody. The algorithm itself is of course in the public domain. */ /* */ /* Again derived heuristically from the 9-point WFTA. */ /* */ /* The algorithm is optimized (?) for speed, not for small rounding errors or */ /* good readability. */ /* */ /* 36 additions, 11 multiplications */ /* */ /* Again this is very likely sub-optimal. */ /* */ /* The code is optimized to use a minimum number of temporary variables, */ /* so it should compile quite well even on 8-register Intel x86 processors. */ /* This makes the code quite obfuscated and very difficult to understand. */ /* */ /* References: */ /* [1] S. Winograd: "On Computing the Discrete Fourier Transform", */ /* Mathematics of Computation, Volume 32, Number 141, January 1978, */ /* Pages 175-199 */ /*------------------------------------------------------------------*/ /* */ /* Function: Calculation of the inverse MDCT */ /* */ /*------------------------------------------------------------------*/ int mpeg3audio_dct36(float *inbuf, float *o1, float *o2, float *wintab, float *tsbuf) { float tmp[18]; { register float *in = inbuf; in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; in[2] +=in[1]; in[1] +=in[0]; in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; { float t3; { float t0, t1, t2; t0 = mpeg3_COS6_2 * (in[8] + in[16] - in[4]); t1 = mpeg3_COS6_2 * in[12]; t3 = in[0]; t2 = t3 - t1 - t1; tmp[1] = tmp[7] = t2 - t0; tmp[4] = t2 + t0 + t0; t3 += t1; t2 = mpeg3_COS6_1 * (in[10] + in[14] - in[2]); tmp[1] -= t2; tmp[7] += t2; } { float t0, t1, t2; t0 = mpeg3_cos9[0] * (in[4] + in[8] ); t1 = mpeg3_cos9[1] * (in[8] - in[16]); t2 = mpeg3_cos9[2] * (in[4] + in[16]); tmp[2] = tmp[6] = t3 - t0 - t2; tmp[0] = tmp[8] = t3 + t0 + t1; tmp[3] = tmp[5] = t3 - t1 + t2; } } { float t1, t2, t3; t1 = mpeg3_cos18[0] * (in[2] + in[10]); t2 = mpeg3_cos18[1] * (in[10] - in[14]); t3 = mpeg3_COS6_1 * in[6]; { float t0 = t1 + t2 + t3; tmp[0] += t0; tmp[8] -= t0; } t2 -= t3; t1 -= t3; t3 = mpeg3_cos18[2] * (in[2] + in[14]); t1 += t3; tmp[3] += t1; tmp[5] -= t1; t2 -= t3; tmp[2] += t2; tmp[6] -= t2; } { float t0, t1, t2, t3, t4, t5, t6, t7; t1 = mpeg3_COS6_2 * in[13]; t2 = mpeg3_COS6_2 * (in[9] + in[17] - in[5]); t3 = in[1] + t1; t4 = in[1] - t1 - t1; t5 = t4 - t2; t0 = mpeg3_cos9[0] * (in[5] + in[9]); t1 = mpeg3_cos9[1] * (in[9] - in[17]); tmp[13] = (t4 + t2 + t2) * mpeg3_tfcos36[17-13]; t2 = mpeg3_cos9[2] * (in[5] + in[17]); t6 = t3 - t0 - t2; t0 += t3 + t1; t3 += t2 - t1; t2 = mpeg3_cos18[0] * (in[3] + in[11]); t4 = mpeg3_cos18[1] * (in[11] - in[15]); t7 = mpeg3_COS6_1 * in[7]; t1 = t2 + t4 + t7; tmp[17] = (t0 + t1) * mpeg3_tfcos36[17-17]; tmp[9] = (t0 - t1) * mpeg3_tfcos36[17-9]; t1 = mpeg3_cos18[2] * (in[3] + in[15]); t2 += t1 - t7; tmp[14] = (t3 + t2) * mpeg3_tfcos36[17-14]; t0 = mpeg3_COS6_1 * (in[11] + in[15] - in[3]); tmp[12] = (t3 - t2) * mpeg3_tfcos36[17-12]; t4 -= t1 + t7; tmp[16] = (t5 - t0) * mpeg3_tfcos36[17-16]; tmp[10] = (t5 + t0) * mpeg3_tfcos36[17-10]; tmp[15] = (t6 + t4) * mpeg3_tfcos36[17-15]; tmp[11] = (t6 - t4) * mpeg3_tfcos36[17-11]; } #define MACRO(v) \ { \ float tmpval; \ tmpval = tmp[(v)] + tmp[17-(v)]; \ out2[9+(v)] = tmpval * w[27+(v)]; \ out2[8-(v)] = tmpval * w[26-(v)]; \ tmpval = tmp[(v)] - tmp[17-(v)]; \ ts[SBLIMIT*(8-(v))] = out1[8-(v)] + tmpval * w[8-(v)]; \ ts[SBLIMIT*(9+(v))] = out1[9+(v)] + tmpval * w[9+(v)]; \ } { register float *out2 = o2; register float *w = wintab; register float *out1 = o1; register float *ts = tsbuf; MACRO(0); MACRO(1); MACRO(2); MACRO(3); MACRO(4); MACRO(5); MACRO(6); MACRO(7); MACRO(8); } } return 0; } /* * new DCT12 */ int mpeg3audio_dct12(float *in,float *rawout1,float *rawout2,register float *wi,register float *ts) { #define DCT12_PART1 \ in5 = in[5*3]; \ in5 += (in4 = in[4*3]); \ in4 += (in3 = in[3*3]); \ in3 += (in2 = in[2*3]); \ in2 += (in1 = in[1*3]); \ in1 += (in0 = in[0*3]); \ \ in5 += in3; in3 += in1; \ \ in2 *= mpeg3_COS6_1; \ in3 *= mpeg3_COS6_1; \ #define DCT12_PART2 \ in0 += in4 * mpeg3_COS6_2; \ \ in4 = in0 + in2; \ in0 -= in2; \ \ in1 += in5 * mpeg3_COS6_2; \ \ in5 = (in1 + in3) * mpeg3_tfcos12[0]; \ in1 = (in1 - in3) * mpeg3_tfcos12[2]; \ \ in3 = in4 + in5; \ in4 -= in5; \ \ in2 = in0 + in1; \ in0 -= in1; { float in0,in1,in2,in3,in4,in5; register float *out1 = rawout1; ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; DCT12_PART1 { float tmp0,tmp1 = (in0 - in4); { float tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; } DCT12_PART2 ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; } in++; { float in0,in1,in2,in3,in4,in5; register float *out2 = rawout2; DCT12_PART1 { float tmp0,tmp1 = (in0 - in4); { float tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[5-1] = tmp0 * wi[11-1]; out2[0+1] = tmp0 * wi[6+1]; ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; } DCT12_PART2 out2[5-0] = in2 * wi[11-0]; out2[0+0] = in2 * wi[6+0]; out2[0+2] = in3 * wi[6+2]; out2[5-2] = in3 * wi[11-2]; ts[(12+0)*SBLIMIT] += in0 * wi[0]; ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; ts[(12+2)*SBLIMIT] += in4 * wi[2]; ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; } in++; { float in0,in1,in2,in3,in4,in5; register float *out2 = rawout2; out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; DCT12_PART1 { float tmp0,tmp1 = (in0 - in4); { float tmp2 = (in1 - in5) * mpeg3_tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[11-1] = tmp0 * wi[11-1]; out2[6 +1] = tmp0 * wi[6+1]; out2[0+1] += tmp1 * wi[1]; out2[5-1] += tmp1 * wi[5-1]; } DCT12_PART2 out2[11-0] = in2 * wi[11-0]; out2[6 +0] = in2 * wi[6+0]; out2[6 +2] = in3 * wi[6+2]; out2[11-2] = in3 * wi[11-2]; out2[0+0] += in0 * wi[0]; out2[5-0] += in0 * wi[5-0]; out2[0+2] += in4 * wi[2]; out2[5-2] += in4 * wi[5-2]; } return 0; } /* AC3 IMDCT tables */ /* Twiddle factors for IMDCT */ static float mpeg3_xcos1[AC3_N / 4]; static float mpeg3_xsin1[AC3_N / 4]; static float mpeg3_xcos2[AC3_N / 8]; static float mpeg3_xsin2[AC3_N / 8]; /* 128 point bit-reverse LUT */ static unsigned char mpeg3_bit_reverse_512[] = { 0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70, 0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78, 0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74, 0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c, 0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72, 0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a, 0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76, 0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e, 0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71, 0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79, 0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75, 0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d, 0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73, 0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b, 0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77, 0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f }; static unsigned char mpeg3_bit_reverse_256[] = { 0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38, 0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c, 0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a, 0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e, 0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39, 0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d, 0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b, 0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f }; /* Windowing function for Modified DCT - Thank you acroread */ static float mpeg3_window[] = { 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130, 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443, 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061, 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121, 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770, 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153, 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389, 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563, 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699, 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757, 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626, 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126, 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019, 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031, 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873, 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269, 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981, 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831, 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716, 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610, 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560, 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674, 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099, 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994, 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513, 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788, 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919, 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974, 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993, 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999, 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 }; mpeg3_complex_t cmplx_mult(mpeg3_complex_t a, mpeg3_complex_t b) { mpeg3_complex_t ret; ret.real = a.real * b.real - a.imag * b.imag; ret.imag = a.real * b.imag + a.imag * b.real; return ret; } int mpeg3audio_imdct_init(mpeg3audio_t *audio) { int i, k; mpeg3_complex_t angle_step; mpeg3_complex_t current_angle; /* Twiddle factors to turn IFFT into IMDCT */ for(i = 0; i < AC3_N / 4; i++) { mpeg3_xcos1[i] = -cos(2.0f * M_PI * (8 * i + 1 ) / ( 8 * AC3_N)); mpeg3_xsin1[i] = -sin(2.0f * M_PI * (8 * i + 1 ) / ( 8 * AC3_N)); } /* More twiddle factors to turn IFFT into IMDCT */ for(i = 0; i < AC3_N / 8; i++) { mpeg3_xcos2[i] = -cos(2.0f * M_PI * (8 * i + 1 ) / ( 4 * AC3_N)); mpeg3_xsin2[i] = -sin(2.0f * M_PI * (8 * i + 1 ) / ( 4 * AC3_N)); } /* Canonical twiddle factors for FFT */ audio->ac3_w[0] = audio->ac3_w_1; audio->ac3_w[1] = audio->ac3_w_2; audio->ac3_w[2] = audio->ac3_w_4; audio->ac3_w[3] = audio->ac3_w_8; audio->ac3_w[4] = audio->ac3_w_16; audio->ac3_w[5] = audio->ac3_w_32; audio->ac3_w[6] = audio->ac3_w_64; for(i = 0; i < 7; i++) { angle_step.real = cos(-2.0f * M_PI / (1 << (i + 1))); angle_step.imag = sin(-2.0f * M_PI / (1 << (i + 1))); current_angle.real = 1.0f; current_angle.imag = 0.0f; for (k = 0; k < 1 << i; k++) { audio->ac3_w[i][k] = current_angle; current_angle = cmplx_mult(current_angle, angle_step); } } return 0; } inline void swap_cmplx(mpeg3_complex_t *a, mpeg3_complex_t *b) { mpeg3_complex_t tmp; tmp = *a; *a = *b; *b = tmp; } void mpeg3audio_ac3_imdct_do_512(mpeg3audio_t *audio, float data[], float *y, int step, float *delay) { int i, k; int p, q; int m; int two_m; int two_m_plus_one; float tmp_a_i; float tmp_a_r; float tmp_b_i; float tmp_b_r; float *y_ptr; float *delay_ptr; float *window_ptr; mpeg3_complex_t *buf = audio->ac3_imdct_buf; /* Pre IFFT complex multiply plus IFFT cmplx conjugate */ for(i = 0; i < AC3_N / 4; i++) { buf[i].real = (data[AC3_N / 2 - 2 * i - 1] * mpeg3_xcos1[i]) - (data[2 * i] * mpeg3_xsin1[i]); buf[i].imag = -((data[2 * i] * mpeg3_xcos1[i]) + (data[AC3_N / 2 - 2 * i - 1] * mpeg3_xsin1[i])); } /* Bit reversed shuffling */ for(i = 0; i < AC3_N / 4; i++) { k = mpeg3_bit_reverse_512[i]; if(k < i) swap_cmplx(&buf[i], &buf[k]); } /* FFT Merge */ for(m = 0; m < 7; m++) { if(m) two_m = (1 << m); else two_m = 1; two_m_plus_one = (1 << (m + 1)); for(k = 0; k < two_m; k++) { for(i = 0; i < AC3_N / 4; i += two_m_plus_one) { p = k + i; q = p + two_m; tmp_a_r = buf[p].real; tmp_a_i = buf[p].imag; tmp_b_r = buf[q].real * audio->ac3_w[m][k].real - buf[q].imag * audio->ac3_w[m][k].imag; tmp_b_i = buf[q].imag * audio->ac3_w[m][k].real + buf[q].real * audio->ac3_w[m][k].imag; buf[p].real = tmp_a_r + tmp_b_r; buf[p].imag = tmp_a_i + tmp_b_i; buf[q].real = tmp_a_r - tmp_b_r; buf[q].imag = tmp_a_i - tmp_b_i; } } } /* Post IFFT complex multiply plus IFFT complex conjugate*/ for(i = 0; i < AC3_N / 4; i++) { tmp_a_r = buf[i].real; tmp_a_i = -buf[i].imag; buf[i].real = (tmp_a_r * mpeg3_xcos1[i]) - (tmp_a_i * mpeg3_xsin1[i]); buf[i].imag = (tmp_a_r * mpeg3_xsin1[i]) + (tmp_a_i * mpeg3_xcos1[i]); } y_ptr = y; delay_ptr = delay; window_ptr = mpeg3_window; /* Window and convert to real valued signal */ for(i = 0; i < AC3_N / 8; i++) { *y_ptr = -buf[AC3_N / 8 + i].imag * *window_ptr++ + *delay_ptr++; y_ptr += step; *y_ptr = buf[AC3_N / 8 - i - 1].real * *window_ptr++ + *delay_ptr++; y_ptr += step; } for(i = 0; i < AC3_N / 8; i++) { *y_ptr = -buf[i].real * *window_ptr++ + *delay_ptr++; y_ptr += step; *y_ptr = buf[AC3_N / 4 - i - 1].imag * *window_ptr++ + *delay_ptr++; y_ptr += step; } /* The trailing edge of the window goes into the delay line */ delay_ptr = delay; for(i = 0; i < AC3_N / 8; i++) { *delay_ptr++ = -buf[AC3_N / 8 + i].real * *--window_ptr; *delay_ptr++ = buf[AC3_N / 8 - i - 1].imag * *--window_ptr; } for(i = 0; i < AC3_N / 8; i++) { *delay_ptr++ = buf[i].imag * *--window_ptr; *delay_ptr++ = -buf[AC3_N / 4 - i - 1].real * *--window_ptr; } } void mpeg3audio_ac3_imdct_do_256(mpeg3audio_t *audio, float data[], float *y, int step, float *delay) { int i, k; int p, q; int m; int two_m; int two_m_plus_one; mpeg3_complex_t *buf = audio->ac3_imdct_buf; float *y_ptr; float *delay_ptr; float *window_ptr; float tmp_a_i; float tmp_a_r; float tmp_b_i; float tmp_b_r; mpeg3_complex_t *buf_1, *buf_2; buf_1 = &buf[0]; buf_2 = &buf[64]; /* Pre IFFT complex multiply plus IFFT cmplx conjugate */ for(k = 0; k < AC3_N / 8; k++) { p = 2 * (AC3_N / 4 - 2 * k - 1); q = 2 * (2 * k); buf_1[k].real = data[p] * mpeg3_xcos2[k] - data[q] * mpeg3_xsin2[k]; buf_1[k].imag = - (data[q] * mpeg3_xcos2[k] + data[p] * mpeg3_xsin2[k]); buf_2[k].real = data[p + 1] * mpeg3_xcos2[k] - data[q + 1] * mpeg3_xsin2[k]; buf_2[k].imag = - (data[q + 1] * mpeg3_xcos2[k] + data[p + 1] * mpeg3_xsin2[k]); } /* IFFT Bit reversed shuffling */ for(i = 0; i < AC3_N / 8; i++) { k = mpeg3_bit_reverse_256[i]; if(k < i) { swap_cmplx(&buf_1[i], &buf_1[k]); swap_cmplx(&buf_2[i], &buf_2[k]); } } /* FFT Merge */ for(m = 0; m < 6; m++) { if(m) two_m = (1 << m); else two_m = 1; two_m_plus_one = (1 << (m + 1)); for(k = 0; k < two_m; k++) { for(i = 0; i < AC3_N / 8; i += two_m_plus_one) { p = k + i; q = p + two_m; /* Do block 1 */ tmp_a_r = buf_1[p].real; tmp_a_i = buf_1[p].imag; tmp_b_r = buf_1[q].real * audio->ac3_w[m][k].real - buf_1[q].imag * audio->ac3_w[m][k].imag; tmp_b_i = buf_1[q].imag * audio->ac3_w[m][k].real + buf_1[q].real * audio->ac3_w[m][k].imag; buf_1[p].real = tmp_a_r + tmp_b_r; buf_1[p].imag = tmp_a_i + tmp_b_i; buf_1[q].real = tmp_a_r - tmp_b_r; buf_1[q].imag = tmp_a_i - tmp_b_i; /* Do block 2 */ tmp_a_r = buf_2[p].real; tmp_a_i = buf_2[p].imag; tmp_b_r = buf_2[q].real * audio->ac3_w[m][k].real - buf_2[q].imag * audio->ac3_w[m][k].imag; tmp_b_i = buf_2[q].imag * audio->ac3_w[m][k].real + buf_2[q].real * audio->ac3_w[m][k].imag; buf_2[p].real = tmp_a_r + tmp_b_r; buf_2[p].imag = tmp_a_i + tmp_b_i; buf_2[q].real = tmp_a_r - tmp_b_r; buf_2[q].imag = tmp_a_i - tmp_b_i; } } } /* Post IFFT complex multiply */ for(i = 0; i < AC3_N / 8; i++) { tmp_a_r = buf_1[i].real; tmp_a_i = -buf_1[i].imag; buf_1[i].real = (tmp_a_r * mpeg3_xcos2[i]) - (tmp_a_i * mpeg3_xsin2[i]); buf_1[i].imag = (tmp_a_r * mpeg3_xsin2[i]) + (tmp_a_i * mpeg3_xcos2[i]); tmp_a_r = buf_2[i].real; tmp_a_i = -buf_2[i].imag; buf_2[i].real = (tmp_a_r * mpeg3_xcos2[i]) - (tmp_a_i * mpeg3_xsin2[i]); buf_2[i].imag = (tmp_a_r * mpeg3_xsin2[i]) + (tmp_a_i * mpeg3_xcos2[i]); } /* Window and convert to real valued signal */ y_ptr = y; delay_ptr = delay; window_ptr = mpeg3_window; for(i = 0; i < AC3_N / 8; i++) { *y_ptr = -buf[AC3_N / 8 + i].imag * *window_ptr++ + *delay_ptr++; y_ptr += step; *y_ptr = buf[AC3_N / 8 - i - 1].real * *window_ptr++ + *delay_ptr++; y_ptr += step; } for(i = 0; i < AC3_N / 8; i++) { *y_ptr = -buf[i].real * *window_ptr++ + *delay_ptr++; y_ptr += step; *y_ptr = buf[AC3_N / 4 - i - 1].imag * *window_ptr++ + *delay_ptr++; y_ptr += step; } /* The trailing edge of the window goes into the delay line */ delay_ptr = delay; for(i = 0; i < AC3_N / 8; i++) { *delay_ptr++ = -buf[AC3_N / 8 + i].real * *--window_ptr; *delay_ptr++ = buf[AC3_N / 8 - i - 1].imag * *--window_ptr; } for(i = 0; i < AC3_N / 8; i++) { *delay_ptr++ = buf[i].imag * *--window_ptr; *delay_ptr++ = -buf[AC3_N / 4 - i - 1].real * *--window_ptr; } } int mpeg3audio_ac3_imdct(mpeg3audio_t *audio, mpeg3_ac3bsi_t *bsi, mpeg3_ac3audblk_t *audblk, mpeg3ac3_stream_samples_t samples) { int i; for(i = 0; i < bsi->nfchans; i++) { if(audblk->blksw[i]) mpeg3audio_ac3_imdct_do_256(audio, samples[i], audio->pcm_sample + audio->pcm_point + i, bsi->nfchans, audio->ac3_delay[i]); else mpeg3audio_ac3_imdct_do_512(audio, samples[i], audio->pcm_sample + audio->pcm_point + i, bsi->nfchans, audio->ac3_delay[i]); } audio->pcm_point += AC3_N / 2 * bsi->nfchans; return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/header.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3audio.h" #include "tables.h" #include /* Return 1 if the head check doesn't find a header. */ int mpeg3audio_head_check(unsigned long head) { if((head & 0xffe00000) != 0xffe00000) return 1; if(!((head >> 17) & 3)) return 1; if(((head >> 12) & 0xf) == 0xf) return 1; if(!((head >> 12) & 0xf)) return 1; if(((head >> 10) & 0x3) == 0x3 ) return 1; if(((head >> 19) & 1) == 1 && ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) return 1; if((head & 0xffff0000) == 0xfffe0000) return 1; return 0; } int mpeg3audio_decode_header(mpeg3audio_t *audio) { if(audio->newhead & (1 << 20)) { audio->lsf = (audio->newhead & (1 << 19)) ? 0x0 : 0x1; audio->mpeg35 = 0; } else { audio->lsf = 1; audio->mpeg35 = 1; } audio->layer = 4 - ((audio->newhead >> 17) & 3); if(audio->mpeg35) audio->sampling_frequency_code = 6 + ((audio->newhead >> 10) & 0x3); else audio->sampling_frequency_code = ((audio->newhead >> 10) & 0x3) + (audio->lsf * 3); audio->error_protection = ((audio->newhead >> 16) & 0x1) ^ 0x1; audio->bitrate_index = ((audio->newhead >> 12) & 0xf); audio->padding = ((audio->newhead >> 9) & 0x1); audio->extension = ((audio->newhead >> 8) & 0x1); audio->mode = ((audio->newhead >> 6) & 0x3); audio->mode_ext = ((audio->newhead >> 4) & 0x3); audio->copyright = ((audio->newhead >> 3) & 0x1); audio->original = ((audio->newhead >> 2) & 0x1); audio->emphasis = audio->newhead & 0x3; audio->channels = (audio->mode == MPG_MD_MONO) ? 1 : 2; if(audio->channels > 1) audio->single = -1; else audio->single = 3; audio->prev_framesize = audio->framesize; if(!audio->bitrate_index) return 1; audio->bitrate = 1000 * mpeg3_tabsel_123[audio->lsf][audio->layer - 1][audio->bitrate_index]; switch(audio->layer) { case 1: audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][0][audio->bitrate_index] * 12000; audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code]; audio->framesize = ((audio->framesize + audio->padding) << 2) - 4; break; case 2: audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][1][audio->bitrate_index] * 144000; audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code]; audio->framesize += audio->padding - 4; break; case 3: if(audio->lsf) audio->ssize = (audio->channels == 1) ? 9 : 17; else audio->ssize = (audio->channels == 1) ? 17 : 32; if(audio->error_protection) audio->ssize += 2; audio->framesize = (long)mpeg3_tabsel_123[audio->lsf][2][audio->bitrate_index] * 144000; audio->framesize /= mpeg3_freqs[audio->sampling_frequency_code] << (audio->lsf); audio->framesize = audio->framesize + audio->padding - 4; break; default: return 1; } if(audio->framesize > MAXFRAMESIZE) return 1; return 0; } int mpeg3audio_read_frame_body(mpeg3audio_t *audio) { int i; for(i = 0; i < audio->framesize; i++) { audio->bsbuf[i] = mpeg3bits_getbits(audio->astream, 8); } return 0; } /* Seek to the start of the previous header */ int mpeg3audio_prev_header(mpeg3audio_t *audio) { int result = 0, i, len = audio->avg_framesize; for(i = 0; i < len && !result; i++) { mpeg3bits_getbits_reverse(audio->astream, 8); } /* Get reading in the forward direction again. */ result |= mpeg3bits_refill(audio->astream); return result; } /* Read the next header */ int mpeg3audio_read_header(mpeg3audio_t *audio) { unsigned int code; int i; int try2 = 0; int result = 0; switch(audio->format) { case AUDIO_AC3: //JMM result = mpeg3audio_read_ac3_header(audio); break; case AUDIO_MPEG: /* Layer 1 not supported */ if(audio->layer == 1) { fprintf(stderr, "mpeg3audio_new: layer 1 not supported\n"); result = 1; } audio->newhead = mpeg3bits_showbits(audio->astream, 32); if(!mpeg3bits_eof(audio->astream) && (mpeg3audio_head_check(audio->newhead) || mpeg3audio_decode_header(audio))) { do { try2++; mpeg3bits_getbyte_noptr(audio->astream); audio->newhead = mpeg3bits_showbits(audio->astream, 32); }while(!mpeg3bits_eof(audio->astream) && try2 < 65536 && (mpeg3audio_head_check(audio->newhead) || mpeg3audio_decode_header(audio))); } /* Skip the 4 bytes containing the header */ mpeg3bits_getbits(audio->astream, 32); break; case AUDIO_PCM: mpeg3audio_read_pcm_header(audio); break; } return mpeg3bits_eof(audio->astream); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/huffman.h ================================================ #ifndef HUFFMAN_H #define HUFFMAN_H /* * huffman tables ... recalcualted to work with my optimzed * decoder scheme (MH) * * probably we could save a few bytes of memory, because the * smaller tables are often the part of a bigger table */ struct newhuff { unsigned int linbits; short *table; }; static short mpeg3_tab0[] = { 0 }; static short mpeg3_tab1[] = { -5, -3, -1, 17, 1, 16, 0 }; static short mpeg3_tab2[] = { -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, 16, 0 }; static short mpeg3_tab3[] = { -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, 1, 0 }; static short mpeg3_tab5[] = { -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static short mpeg3_tab6[] = { -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, 0 }; static short mpeg3_tab7[] = { -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static short mpeg3_tab8[] = { -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 }; static short mpeg3_tab9[] = { -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 }; static short mpeg3_tab10[] = { -125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static short mpeg3_tab11[] = { -121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static short mpeg3_tab12[] = { -115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, 2, 32, 0, 17, -1, 1, 16 }; static short mpeg3_tab13[] = { -509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static short mpeg3_tab15[] = { -495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static short mpeg3_tab16[] = { -509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static short mpeg3_tab24[] = { -451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, -143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, 0 }; static short mpeg3_tab_c0[] = { -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, 0 }; static short mpeg3_tab_c1[] = { -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, 0 }; static struct newhuff mpeg3_ht[] = { { /* 0 */ 0 , mpeg3_tab0 } , { /* 2 */ 0 , mpeg3_tab1 } , { /* 3 */ 0 , mpeg3_tab2 } , { /* 3 */ 0 , mpeg3_tab3 } , { /* 0 */ 0 , mpeg3_tab0 } , { /* 4 */ 0 , mpeg3_tab5 } , { /* 4 */ 0 , mpeg3_tab6 } , { /* 6 */ 0 , mpeg3_tab7 } , { /* 6 */ 0 , mpeg3_tab8 } , { /* 6 */ 0 , mpeg3_tab9 } , { /* 8 */ 0 , mpeg3_tab10 } , { /* 8 */ 0 , mpeg3_tab11 } , { /* 8 */ 0 , mpeg3_tab12 } , { /* 16 */ 0 , mpeg3_tab13 } , { /* 0 */ 0 , mpeg3_tab0 } , { /* 16 */ 0 , mpeg3_tab15 } , { /* 16 */ 1 , mpeg3_tab16 } , { /* 16 */ 2 , mpeg3_tab16 } , { /* 16 */ 3 , mpeg3_tab16 } , { /* 16 */ 4 , mpeg3_tab16 } , { /* 16 */ 6 , mpeg3_tab16 } , { /* 16 */ 8 , mpeg3_tab16 } , { /* 16 */ 10, mpeg3_tab16 } , { /* 16 */ 13, mpeg3_tab16 } , { /* 16 */ 4 , mpeg3_tab24 } , { /* 16 */ 5 , mpeg3_tab24 } , { /* 16 */ 6 , mpeg3_tab24 } , { /* 16 */ 7 , mpeg3_tab24 } , { /* 16 */ 8 , mpeg3_tab24 } , { /* 16 */ 9 , mpeg3_tab24 } , { /* 16 */ 11, mpeg3_tab24 } , { /* 16 */ 13, mpeg3_tab24 } }; static struct newhuff mpeg3_htc[] = { { /* 1 , 1 , */ 0 , mpeg3_tab_c0 } , { /* 1 , 1 , */ 0 , mpeg3_tab_c1 } }; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/layer1.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3audio.h" int mpeg3audio_dolayer1(mpeg3audio_t *audio) { ; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/layer2.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* * most other tables are calculated on program start (which is (of course) * not ISO-conform) .. * Layer-3 huffman table is in huffman.h */ #include "mpeg3audio.h" #include "tables.h" struct al_table alloc_0[] = { {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767} }; struct al_table alloc_1[] = { {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767} }; struct al_table alloc_2[] = { {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; struct al_table alloc_3[] = { {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; struct al_table alloc_4[] = { {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9} }; int mpeg3audio_II_select_table(mpeg3audio_t *audio) { static int translate[3][2][16] = {{{ 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0}, { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0}}, {{ 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0}, { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0}}, {{ 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0}, { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0}}}; int table, sblim; static struct al_table *tables[5] = {alloc_0, alloc_1, alloc_2, alloc_3, alloc_4}; static int sblims[5] = {27, 30, 8, 12, 30}; if(audio->lsf) table = 4; else table = translate[audio->sampling_frequency_code][2 - audio->channels][audio->bitrate_index]; sblim = sblims[table]; audio->alloc = tables[table]; audio->II_sblimit = sblim; return 0; } int mpeg3audio_II_step_one(mpeg3audio_t *audio, unsigned int *bit_alloc, int *scale) { int stereo = audio->channels - 1; int sblimit = audio->II_sblimit; int jsbound = audio->jsbound; int sblimit2 = audio->II_sblimit << stereo; struct al_table *alloc1 = audio->alloc; int i, result = 0; unsigned int *scfsi_buf = audio->layer2_scfsi_buf; unsigned int *scfsi, *bita; int sc, step; bita = bit_alloc; if(stereo) { /* Stereo */ for(i = jsbound;i ; i--, alloc1 += (1 << step)) { *bita++ = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); *bita++ = (char)mpeg3bits_getbits(audio->astream, step); } for(i = sblimit-jsbound; i; i--, alloc1 += (1 << step)) { bita[0] = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); bita[1] = bita[0]; bita += 2; } bita = bit_alloc; scfsi = scfsi_buf; for(i = sblimit2; i; i--) if(*bita++) *scfsi++ = (char)mpeg3bits_getbits(audio->astream, 2); } else { /* mono */ for(i = sblimit; i; i--, alloc1 += (1 << step)) *bita++ = (char)mpeg3bits_getbits(audio->astream, step = alloc1->bits); bita = bit_alloc; scfsi = scfsi_buf; for(i = sblimit; i; i--) if (*bita++) *scfsi++ = (char)mpeg3bits_getbits(audio->astream, 2); } bita = bit_alloc; scfsi = scfsi_buf; for(i = sblimit2; i; i--) { if(*bita++) switch(*scfsi++) { case 0: *scale++ = mpeg3bits_getbits(audio->astream, 6); *scale++ = mpeg3bits_getbits(audio->astream, 6); *scale++ = mpeg3bits_getbits(audio->astream, 6); break; case 1 : *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); *scale++ = sc; *scale++ = mpeg3bits_getbits(audio->astream, 6); break; case 2: *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); *scale++ = sc; *scale++ = sc; break; default: /* case 3 */ *scale++ = mpeg3bits_getbits(audio->astream, 6); *scale++ = sc = mpeg3bits_getbits(audio->astream, 6); *scale++ = sc; break; } } return result | mpeg3bits_error(audio->astream); } int mpeg3audio_II_step_two(mpeg3audio_t *audio, unsigned int *bit_alloc, float fraction[2][4][SBLIMIT], int *scale, int x1) { int i, j, k, ba, result = 0; int channels = audio->channels; int sblimit = audio->II_sblimit; int jsbound = audio->jsbound; struct al_table *alloc2, *alloc1 = audio->alloc; unsigned int *bita = bit_alloc; int d1, step, test; for(i = 0; i < jsbound; i++, alloc1 += (1 << step)) { step = alloc1->bits; for(j = 0; j < channels; j++) { if(ba = *bita++) { k = (alloc2 = alloc1 + ba)->bits; if((d1 = alloc2->d) < 0) { float cm = mpeg3_muls[k][scale[x1]]; fraction[j][0][i] = ((float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; fraction[j][1][i] = ((float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; fraction[j][2][i] = ((float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; } else { static int *table[] = {0, 0, 0, mpeg3_grp_3tab, 0, mpeg3_grp_5tab, 0, 0, 0, mpeg3_grp_9tab}; unsigned int idx, *tab, m = scale[x1]; idx = (unsigned int)mpeg3bits_getbits(audio->astream, k); tab = (unsigned int*)(table[d1] + idx + idx + idx); fraction[j][0][i] = mpeg3_muls[*tab++][m]; fraction[j][1][i] = mpeg3_muls[*tab++][m]; fraction[j][2][i] = mpeg3_muls[*tab][m]; } scale += 3; } else fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; } } for(i = jsbound; i < sblimit; i++, alloc1 += (1 << step)) { step = alloc1->bits; /* channel 1 and channel 2 bitalloc are the same */ bita++; if((ba = *bita++)) { k=(alloc2 = alloc1+ba)->bits; if((d1 = alloc2->d) < 0) { float cm; cm = mpeg3_muls[k][scale[x1 + 3]]; fraction[1][0][i] = (fraction[0][0][i] = (float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; fraction[1][1][i] = (fraction[0][1][i] = (float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; fraction[1][2][i] = (fraction[0][2][i] = (float)((int)mpeg3bits_getbits(audio->astream, k) + d1)) * cm; cm = mpeg3_muls[k][scale[x1]]; fraction[0][0][i] *= cm; fraction[0][1][i] *= cm; fraction[0][2][i] *= cm; } else { static int *table[] = {0, 0, 0, mpeg3_grp_3tab, 0, mpeg3_grp_5tab, 0, 0, 0, mpeg3_grp_9tab}; unsigned int idx, *tab, m1, m2; m1 = scale[x1]; m2 = scale[x1+3]; idx = (unsigned int)mpeg3bits_getbits(audio->astream, k); tab = (unsigned int*)(table[d1] + idx + idx + idx); fraction[0][0][i] = mpeg3_muls[*tab][m1]; fraction[1][0][i] = mpeg3_muls[*tab++][m2]; fraction[0][1][i] = mpeg3_muls[*tab][m1]; fraction[1][1][i] = mpeg3_muls[*tab++][m2]; fraction[0][2][i] = mpeg3_muls[*tab][m1]; fraction[1][2][i] = mpeg3_muls[*tab][m2]; } scale += 6; } else { fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; } /* should we use individual scalefac for channel 2 or is the current way the right one , where we just copy channel 1 to channel 2 ?? The current 'strange' thing is, that we throw away the scalefac values for the second channel ...!! -> changed .. now we use the scalefac values of channel one !! */ } if(sblimit > SBLIMIT) sblimit = SBLIMIT; for(i = sblimit; i < SBLIMIT; i++) for(j = 0; j < channels; j++) fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; return result | mpeg3bits_error(audio->astream); } int mpeg3audio_dolayer2(mpeg3audio_t *audio) { int i, j, result = 0; int channels = audio->channels; float fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ unsigned int bit_alloc[64]; int scale[192]; int single = audio->single; if(audio->error_protection) mpeg3bits_getbits(audio->astream, 16); mpeg3audio_II_select_table(audio); audio->jsbound = (audio->mode == MPG_MD_JOINT_STEREO) ? (audio->mode_ext << 2) + 4 : audio->II_sblimit; if(channels == 1 || single == 3) single = 0; result |= mpeg3audio_II_step_one(audio, bit_alloc, scale); for(i = 0; i < SCALE_BLOCK && !result; i++) { result |= mpeg3audio_II_step_two(audio, bit_alloc, fraction, scale, i >> 2); for(j = 0; j < 3; j++) { if(single >= 0) { /* Monaural */ mpeg3audio_synth_mono(audio, fraction[single][j], audio->pcm_sample, &(audio->pcm_point)); } else { /* Stereo */ int p1 = audio->pcm_point; mpeg3audio_synth_stereo(audio, fraction[0][j], 0, audio->pcm_sample, &p1); mpeg3audio_synth_stereo(audio, fraction[1][j], 1, audio->pcm_sample, &(audio->pcm_point)); } if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) { /* Need more room */ mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); } } } return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/layer3.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "huffman.h" #include "mpeg3audio.h" #include "tables.h" #include #include struct gr_info_s { int scfsi; unsigned part2_3_length; unsigned big_values; unsigned scalefac_compress; unsigned block_type; unsigned mixed_block_flag; unsigned table_select[3]; unsigned subblock_gain[3]; unsigned maxband[3]; unsigned maxbandl; unsigned maxb; unsigned region1start; unsigned region2start; unsigned preflag; unsigned scalefac_scale; unsigned count1table_select; float *full_gain[3]; float *pow2gain; }; struct mpeg3_III_sideinfo { unsigned main_data_begin; unsigned private_bits; struct { struct gr_info_s gr[2]; } ch[2]; }; int mpeg3audio_III_get_scale_factors_1(mpeg3audio_t *audio, int *scf, struct gr_info_s *gr_info, int ch, int gr) { static unsigned char slen[2][16] = {{0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}}; int numbits; int num0 = slen[0][gr_info->scalefac_compress]; int num1 = slen[1][gr_info->scalefac_compress]; if (gr_info->block_type == 2) { int i = 18; numbits = (num0 + num1) * 18; if (gr_info->mixed_block_flag) { for(i = 8; i; i--) *scf++ = mpeg3bits_getbits(audio->astream, num0); i = 9; /* num0 * 17 + num1 * 18 */ numbits -= num0; } for( ; i; i--) *scf++ = mpeg3bits_getbits(audio->astream, num0); for(i = 18; i; i--) *scf++ = mpeg3bits_getbits(audio->astream, num1); /* short[13][0..2] = 0 */ *scf++ = 0; *scf++ = 0; *scf++ = 0; } else { int i; int scfsi = gr_info->scfsi; if(scfsi < 0) { /* scfsi < 0 => granule == 0 */ for(i = 11; i; i--) { *scf++ = mpeg3bits_getbits(audio->astream, num0); } for(i = 10; i; i--) *scf++ = mpeg3bits_getbits(audio->astream, num1); numbits = (num0 + num1) * 10 + num0; *scf++ = 0; } else { numbits = 0; if(!(scfsi & 0x8)) { for(i = 0; i < 6; i++) { *scf++ = mpeg3bits_getbits(audio->astream, num0); } numbits += num0 * 6; } else { scf += 6; } if(!(scfsi & 0x4)) { for(i = 0; i < 5; i++) *scf++ = mpeg3bits_getbits(audio->astream, num0); numbits += num0 * 5; } else { scf += 5; } if(!(scfsi & 0x2)) { for(i = 0; i < 5; i++) *scf++ = mpeg3bits_getbits(audio->astream, num1); numbits += num1 * 5; } else { scf += 5; } if(!(scfsi & 0x1)) { for(i = 0; i < 5; i++) *scf++ = mpeg3bits_getbits(audio->astream, num1); numbits += num1 * 5; } else { scf += 5; } *scf++ = 0; /* no l[21] in original sources */ } } return numbits; } int mpeg3audio_III_get_scale_factors_2(mpeg3audio_t *audio, int *scf, struct gr_info_s *gr_info, int i_stereo) { unsigned char *pnt; int i, j, n = 0, numbits = 0; unsigned int slen; static unsigned char stab[3][6][4] = {{{ 6, 5, 5,5 }, { 6, 5, 7,3 }, { 11,10,0,0}, { 7, 7, 7,0 }, { 6, 6, 6,3 }, { 8, 8,5,0}}, {{ 9, 9, 9,9 }, { 9, 9,12,6 }, { 18,18,0,0}, {12,12,12,0 }, {12, 9, 9,6 }, { 15,12,9,0}}, {{ 6, 9, 9,9 }, { 6, 9,12,6 }, { 15,18,0,0}, { 6,15,12,0 }, { 6,12, 9,6 }, { 6,18,9,0}}}; /* i_stereo AND second channel -> do_layer3() checks this */ if(i_stereo) slen = mpeg3_i_slen2[gr_info->scalefac_compress >> 1]; else slen = mpeg3_n_slen2[gr_info->scalefac_compress]; gr_info->preflag = (slen >> 15) & 0x1; n = 0; if(gr_info->block_type == 2 ) { n++; if(gr_info->mixed_block_flag) n++; } pnt = stab[n][(slen >> 12) & 0x7]; for(i = 0; i < 4; i++) { int num = slen & 0x7; slen >>= 3; if(num) { for(j = 0; j < (int)(pnt[i]); j++) *scf++ = mpeg3bits_getbits(audio->astream, num); numbits += pnt[i] * num; } else { for(j = 0; j < (int)(pnt[i]); j++) *scf++ = 0; } } n = (n << 1) + 1; for(i = 0; i < n; i++) *scf++ = 0; return numbits; } static int pretab1[22] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0}; static int pretab2[22] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* * Dequantize samples (includes huffman decoding) * * 24 is enough because tab13 has max. a 19 bit huffvector */ #define BITSHIFT ((sizeof(long) - 1) * 8) #define REFRESH_MASK \ while(num < BITSHIFT) \ { \ mask |= mpeg3bits_getbits(audio->astream, 8) << (BITSHIFT - num); \ num += 8; \ part2remain -= 8; \ } int mpeg3audio_III_dequantize_sample(mpeg3audio_t *audio, float xr[SBLIMIT][SSLIMIT], int *scf, struct gr_info_s *gr_info, int sfreq, int part2bits) { int shift = 1 + gr_info->scalefac_scale; float *xrpnt = (float*)xr; int l[3],l3; int part2remain = gr_info->part2_3_length - part2bits; int *me; int num = mpeg3bits_getbitoffset(audio->astream); long mask = mpeg3bits_getbits(audio->astream, num); //printf("III_dequantize_sample 1 %08x %d\n", mask, num); mask = mask << (BITSHIFT + 8 - num); part2remain -= num; { int bv = gr_info->big_values; int region1 = gr_info->region1start; int region2 = gr_info->region2start; l3 = ((576 >> 1) - bv) >> 1; /* * we may lose the 'odd' bit here !! * check this later again */ if(bv <= region1) { l[0] = bv; l[1] = 0; l[2] = 0; } else { l[0] = region1; if(bv <= region2) { l[1] = bv - l[0]; l[2] = 0; } else { l[1] = region2 - l[0]; l[2] = bv - region2; } } } if(gr_info->block_type == 2) { /* * decoding with short or mixed mode BandIndex table */ int i, max[4]; int step = 0, lwin = 3, cb = 0; register float v = 0.0; register int *m, mc; if(gr_info->mixed_block_flag) { max[3] = -1; max[0] = max[1] = max[2] = 2; m = mpeg3_map[sfreq][0]; me = mpeg3_mapend[sfreq][0]; } else { max[0] = max[1] = max[2] = max[3] = -1; /* max[3] not floatly needed in this case */ m = mpeg3_map[sfreq][1]; me = mpeg3_mapend[sfreq][1]; } mc = 0; for(i = 0; i < 2; i++) { int lp = l[i]; struct newhuff *h = mpeg3_ht + gr_info->table_select[i]; for( ; lp; lp--, mc--) { register int x,y; if(!mc) { mc = *m++; xrpnt = ((float*)xr) + (*m++); lwin = *m++; cb = *m++; if(lwin == 3) { v = gr_info->pow2gain[(*scf++) << shift]; step = 1; } else { v = gr_info->full_gain[lwin][(*scf++) << shift]; step = 3; } } { register short *val = h->table; REFRESH_MASK; while((y = *val++) < 0) { if (mask < 0) val -= y; num--; mask <<= 1; } x = y >> 4; y &= 0xf; } if(x == 15 && h->linbits) { max[lwin] = cb; REFRESH_MASK; x += ((unsigned long)mask) >> (BITSHIFT + 8 - h->linbits); num -= h->linbits + 1; mask <<= h->linbits; if(mask < 0) *xrpnt = -mpeg3_ispow[x] * v; else *xrpnt = mpeg3_ispow[x] * v; mask <<= 1; } else if(x) { max[lwin] = cb; if(mask < 0) *xrpnt = -mpeg3_ispow[x] * v; else *xrpnt = mpeg3_ispow[x] * v; num--; mask <<= 1; } else *xrpnt = 0.0; xrpnt += step; if(y == 15 && h->linbits) { max[lwin] = cb; REFRESH_MASK; y += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); num -= h->linbits + 1; mask <<= h->linbits; if(mask < 0) *xrpnt = -mpeg3_ispow[y] * v; else *xrpnt = mpeg3_ispow[y] * v; mask <<= 1; } else if(y) { max[lwin] = cb; if(mask < 0) *xrpnt = -mpeg3_ispow[y] * v; else *xrpnt = mpeg3_ispow[y] * v; num--; mask <<= 1; } else *xrpnt = 0.0; xrpnt += step; } } for( ;l3 && (part2remain + num > 0); l3--) { struct newhuff *h = mpeg3_htc + gr_info->count1table_select; register short *val = h->table, a; REFRESH_MASK; while((a = *val++) < 0) { if (mask < 0) val -= a; num--; mask <<= 1; } if(part2remain + num <= 0) { num -= part2remain + num; break; } for(i = 0; i < 4; i++) { if(!(i & 1)) { if(!mc) { mc = *m++; xrpnt = ((float*)xr) + (*m++); lwin = *m++; cb = *m++; if(lwin == 3) { v = gr_info->pow2gain[(*scf++) << shift]; step = 1; } else { v = gr_info->full_gain[lwin][(*scf++) << shift]; step = 3; } } mc--; } if((a & (0x8 >> i))) { max[lwin] = cb; if(part2remain + num <= 0) { break; } if(mask < 0) *xrpnt = -v; else *xrpnt = v; num--; mask <<= 1; } else *xrpnt = 0.0; xrpnt += step; } } if(lwin < 3) { /* short band? */ while(1) { for( ;mc > 0; mc--) { /* short band -> step=3 */ *xrpnt = 0.0; xrpnt += 3; *xrpnt = 0.0; xrpnt += 3; } if(m >= me) break; mc = *m++; xrpnt = ((float*)xr) + *m++; /* optimize: field will be set to zero at the end of the function */ if(*m++ == 0) break; /* cb */ m++; } } gr_info->maxband[0] = max[0] + 1; gr_info->maxband[1] = max[1] + 1; gr_info->maxband[2] = max[2] + 1; gr_info->maxbandl = max[3] + 1; { int rmax = max[0] > max[1] ? max[0] : max[1]; rmax = (rmax > max[2] ? rmax : max[2]) + 1; gr_info->maxb = rmax ? mpeg3_shortLimit[sfreq][rmax] : mpeg3_longLimit[sfreq][max[3] + 1]; } } else { /* * decoding with 'long' BandIndex table (block_type != 2) */ int *pretab = gr_info->preflag ? pretab1 : pretab2; int i, max = -1; int cb = 0; int *m = mpeg3_map[sfreq][2]; register float v = 0.0; int mc = 0; /* * long hash table values */ for(i = 0; i < 3; i++) { int lp = l[i]; struct newhuff *h = mpeg3_ht + gr_info->table_select[i]; for(; lp; lp--, mc--) { int x, y; if(!mc) { mc = *m++; cb = *m++; if(cb == 21) v = 0.0; else v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; } { register short *val = h->table; REFRESH_MASK; while((y = *val++) < 0) { if(mask < 0) val -= y; num--; mask <<= 1; } x = y >> 4; y &= 0xf; } if(x == 15 && h->linbits) { max = cb; REFRESH_MASK; x += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); num -= h->linbits + 1; mask <<= h->linbits; if(mask < 0) *xrpnt++ = -mpeg3_ispow[x] * v; else *xrpnt++ = mpeg3_ispow[x] * v; mask <<= 1; } else if(x) { max = cb; if(mask < 0) *xrpnt++ = -mpeg3_ispow[x] * v; else *xrpnt++ = mpeg3_ispow[x] * v; num--; mask <<= 1; } else *xrpnt++ = 0.0; if(y == 15 && h->linbits) { max = cb; REFRESH_MASK; y += ((unsigned long) mask) >> (BITSHIFT + 8 - h->linbits); num -= h->linbits + 1; mask <<= h->linbits; if(mask < 0) *xrpnt++ = -mpeg3_ispow[y] * v; else *xrpnt++ = mpeg3_ispow[y] * v; mask <<= 1; } else if(y) { max = cb; if(mask < 0) *xrpnt++ = -mpeg3_ispow[y] * v; else *xrpnt++ = mpeg3_ispow[y] * v; num--; mask <<= 1; } else *xrpnt++ = 0.0; } } /* * short (count1table) values */ for( ; l3 && (part2remain + num > 0); l3--) { struct newhuff *h = mpeg3_htc + gr_info->count1table_select; register short *val = h->table, a; REFRESH_MASK; while((a = *val++) < 0) { if(mask < 0) val -= a; num--; mask <<= 1; } if(part2remain + num <= 0) { num -= part2remain + num; break; } for(i = 0; i < 4; i++) { if(!(i & 1)) { if(!mc) { mc = *m++; cb = *m++; if(cb == 21) v = 0.0; else v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift]; } mc--; } if((a & (0x8 >> i))) { max = cb; if(part2remain + num <= 0) { break; } if(mask < 0) *xrpnt++ = -v; else *xrpnt++ = v; num--; mask <<= 1; } else *xrpnt++ = 0.0; } } gr_info->maxbandl = max + 1; gr_info->maxb = mpeg3_longLimit[sfreq][gr_info->maxbandl]; } part2remain += num; //printf("III_dequantize_sample 2 %d %04x\n", num, mpeg3bits_showbits(audio->astream, 16)); mpeg3bits_start_reverse(audio->astream); mpeg3bits_getbits_reverse(audio->astream, num); mpeg3bits_start_forward(audio->astream); //printf("III_dequantize_sample 3 %d %04x\n", audio->astream->bit_number, mpeg3bits_showbits(audio->astream, 16)); num = 0; while(xrpnt < &xr[SBLIMIT][0]) *xrpnt++ = 0.0; while(part2remain > 16) { mpeg3bits_getbits(audio->astream, 16); /* Dismiss stuffing Bits */ part2remain -= 16; } if(part2remain > 0) { mpeg3bits_getbits(audio->astream, part2remain); } else if(part2remain < 0) { fprintf(stderr,"mpeg3audio_III_dequantize_sample: Can't rewind stream %d bits!\n", -part2remain); return 1; /* -> error */ } return 0; } int mpeg3audio_III_get_side_info(mpeg3audio_t *audio, struct mpeg3_III_sideinfo *si, int channels, int ms_stereo, long sfreq, int single, int lsf) { int ch, gr; int powdiff = (single == 3) ? 4 : 0; static const int tabs[2][5] = { { 2,9,5,3,4 } , { 1,8,1,2,9 } }; const int *tab = tabs[lsf]; si->main_data_begin = mpeg3bits_getbits(audio->astream, tab[1]); if(channels == 1) si->private_bits = mpeg3bits_getbits(audio->astream, tab[2]); else si->private_bits = mpeg3bits_getbits(audio->astream, tab[3]); if(!lsf) { for(ch = 0; ch < channels; ch++) { si->ch[ch].gr[0].scfsi = -1; si->ch[ch].gr[1].scfsi = mpeg3bits_getbits(audio->astream, 4); } } for(gr = 0; gr < tab[0]; gr++) { for(ch = 0; ch < channels; ch++) { register struct gr_info_s *gr_info = &(si->ch[ch].gr[gr]); gr_info->part2_3_length = mpeg3bits_getbits(audio->astream, 12); gr_info->big_values = mpeg3bits_getbits(audio->astream, 9); if(gr_info->big_values > 288) { fprintf(stderr,"mpeg3_III_get_side_info: big_values too large!\n"); gr_info->big_values = 288; } gr_info->pow2gain = mpeg3_gainpow2 + 256 - mpeg3bits_getbits(audio->astream, 8) + powdiff; if(ms_stereo) gr_info->pow2gain += 2; gr_info->scalefac_compress = mpeg3bits_getbits(audio->astream, tab[4]); if(mpeg3bits_getbits(audio->astream, 1)) { /* window switch flag */ int i; gr_info->block_type = mpeg3bits_getbits(audio->astream, 2); gr_info->mixed_block_flag = mpeg3bits_getbits(audio->astream, 1); gr_info->table_select[0] = mpeg3bits_getbits(audio->astream, 5); gr_info->table_select[1] = mpeg3bits_getbits(audio->astream, 5); /* * table_select[2] not needed, because there is no region2, * but to satisfy some verifications tools we set it either. */ gr_info->table_select[2] = 0; for(i = 0; i < 3; i++) gr_info->full_gain[i] = gr_info->pow2gain + (mpeg3bits_getbits(audio->astream, 3) << 3); if(gr_info->block_type == 0) { fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.\n"); return 1; } /* region_count/start parameters are implicit in this case. */ if(!lsf || gr_info->block_type == 2) gr_info->region1start = 36 >> 1; else { /* check this again for 2.5 and sfreq=8 */ if(sfreq == 8) gr_info->region1start = 108 >> 1; else gr_info->region1start = 54 >> 1; } gr_info->region2start = 576 >> 1; } else { int i, r0c, r1c; for(i = 0; i < 3; i++) gr_info->table_select[i] = mpeg3bits_getbits(audio->astream, 5); r0c = mpeg3bits_getbits(audio->astream, 4); r1c = mpeg3bits_getbits(audio->astream, 3); gr_info->region1start = mpeg3_bandInfo[sfreq].longIdx[r0c + 1] >> 1 ; gr_info->region2start = mpeg3_bandInfo[sfreq].longIdx[r0c + 1 + r1c + 1] >> 1; gr_info->block_type = 0; gr_info->mixed_block_flag = 0; } if(!lsf) gr_info->preflag = mpeg3bits_getbits(audio->astream, 1); gr_info->scalefac_scale = mpeg3bits_getbits(audio->astream, 1); gr_info->count1table_select = mpeg3bits_getbits(audio->astream, 1); } } return 0; } int mpeg3audio_III_hybrid(mpeg3audio_t *audio, float fsIn[SBLIMIT][SSLIMIT], float tsOut[SSLIMIT][SBLIMIT], int ch, struct gr_info_s *gr_info) { float *tspnt = (float *) tsOut; float *rawout1,*rawout2; int bt, sb = 0; { int b = audio->mp3_blc[ch]; rawout1 = audio->mp3_block[b][ch]; b = -b + 1; rawout2 = audio->mp3_block[b][ch]; audio->mp3_blc[ch] = b; } if(gr_info->mixed_block_flag) { sb = 2; mpeg3audio_dct36(fsIn[0], rawout1, rawout2, mpeg3_win[0], tspnt); mpeg3audio_dct36(fsIn[1], rawout1 + 18, rawout2 + 18, mpeg3_win1[0], tspnt + 1); rawout1 += 36; rawout2 += 36; tspnt += 2; } bt = gr_info->block_type; if(bt == 2) { for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { mpeg3audio_dct12(fsIn[sb] ,rawout1 ,rawout2 ,mpeg3_win[2] ,tspnt); mpeg3audio_dct12(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, mpeg3_win1[2], tspnt + 1); } } else { for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { mpeg3audio_dct36(fsIn[sb], rawout1, rawout2, mpeg3_win[bt], tspnt); mpeg3audio_dct36(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, mpeg3_win1[bt], tspnt + 1); } } for( ; sb < SBLIMIT; sb++, tspnt++) { int i; for(i = 0; i < SSLIMIT; i++) { tspnt[i * SBLIMIT] = *rawout1++; *rawout2++ = 0.0; } } return 0; } int mpeg3audio_III_antialias(mpeg3audio_t *audio, float xr[SBLIMIT][SSLIMIT], struct gr_info_s *gr_info) { int sblim; if(gr_info->block_type == 2) { if(!gr_info->mixed_block_flag) return; sblim = 1; } else { sblim = gr_info->maxb-1; } /* 31 alias-reduction operations between each pair of sub-bands */ /* with 8 butterflies between each pair */ { int sb; float *xr1 = (float*)xr[1]; for(sb = sblim; sb; sb--, xr1 += 10) { int ss; float *cs, *ca; float *xr2; cs = mpeg3_aa_cs; ca = mpeg3_aa_ca; xr2 = xr1; for(ss = 7; ss >= 0; ss--) { /* upper and lower butterfly inputs */ register float bu, bd; bu = *--xr2; bd = *xr1; *xr2 = (bu * (*cs) ) - (bd * (*ca) ); *xr1++ = (bd * (*cs++) ) + (bu * (*ca++) ); } } } return 0; } /* * III_stereo: calculate float channel values for Joint-I-Stereo-mode */ int mpeg3audio_III_i_stereo(mpeg3audio_t *audio, float xr_buf[2][SBLIMIT][SSLIMIT], int *scalefac, struct gr_info_s *gr_info, int sfreq, int ms_stereo, int lsf) { float (*xr)[SBLIMIT*SSLIMIT] = (float (*)[SBLIMIT*SSLIMIT] ) xr_buf; struct mpeg3_bandInfoStruct *bi = &mpeg3_bandInfo[sfreq]; const float *tab1, *tab2; int tab; /* TODO: optimize as static */ static const float *tabs[3][2][2] = { { { mpeg3_tan1_1, mpeg3_tan2_1 } , { mpeg3_tan1_2, mpeg3_tan2_2 } }, { { mpeg3_pow1_1[0], mpeg3_pow2_1[0] } , { mpeg3_pow1_2[0], mpeg3_pow2_2[0] } } , { { mpeg3_pow1_1[1], mpeg3_pow2_1[1] } , { mpeg3_pow1_2[1], mpeg3_pow2_2[1] } } }; tab = lsf + (gr_info->scalefac_compress & lsf); tab1 = tabs[tab][ms_stereo][0]; tab2 = tabs[tab][ms_stereo][1]; if(gr_info->block_type == 2) { int lwin,do_l = 0; if(gr_info->mixed_block_flag) do_l = 1; for(lwin = 0; lwin < 3; lwin++) { /* process each window */ /* get first band with zero values */ /* sfb is minimal 3 for mixed mode */ int is_p, sb, idx, sfb = gr_info->maxband[lwin]; if(sfb > 3) do_l = 0; for( ; sfb < 12 ; sfb++) { /* scale: 0-15 */ is_p = scalefac[sfb * 3 + lwin - gr_info->mixed_block_flag]; if(is_p != 7) { float t1, t2; sb = bi->shortDiff[sfb]; idx = bi->shortIdx[sfb] + lwin; t1 = tab1[is_p]; t2 = tab2[is_p]; for( ; sb > 0; sb--, idx += 3) { float v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } /* in the original: copy 10 to 11 , here: copy 11 to 12 maybe still wrong??? (copy 12 to 13?) */ /* scale: 0-15 */ is_p = scalefac[11 * 3 + lwin - gr_info->mixed_block_flag]; sb = bi->shortDiff[12]; idx = bi->shortIdx[12] + lwin; if(is_p != 7) { float t1, t2; t1 = tab1[is_p]; t2 = tab2[is_p]; for( ; sb > 0; sb--, idx += 3) { float v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } /* end for(lwin; .. ; . ) */ /* also check l-part, if ALL bands in the three windows are 'empty' * and mode = mixed_mode */ if(do_l) { int sfb = gr_info->maxbandl; int idx = bi->longIdx[sfb]; for ( ; sfb < 8; sfb++) { int sb = bi->longDiff[sfb]; /* scale: 0-15 */ int is_p = scalefac[sfb]; if(is_p != 7) { float t1, t2; t1 = tab1[is_p]; t2 = tab2[is_p]; for( ; sb > 0; sb--, idx++) { float v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } else idx += sb; } } } else { /* ((gr_info->block_type != 2)) */ int sfb = gr_info->maxbandl; int is_p, idx = bi->longIdx[sfb]; for( ; sfb < 21; sfb++) { int sb = bi->longDiff[sfb]; /* scale: 0-15 */ is_p = scalefac[sfb]; if(is_p != 7) { float t1, t2; t1 = tab1[is_p]; t2 = tab2[is_p]; for( ; sb > 0; sb--, idx++) { float v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } else idx += sb; } is_p = scalefac[20]; if(is_p != 7) { /* copy l-band 20 to l-band 21 */ int sb; float t1 = tab1[is_p], t2 = tab2[is_p]; for(sb = bi->longDiff[21]; sb > 0; sb--, idx++) { float v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } /* ... */ } /* Read just the frame after a seek. */ int mpeg3audio_read_layer3_frame(mpeg3audio_t *audio) { int result = 0; result = mpeg3audio_read_header(audio); if(!result) { audio->bsbufold = audio->bsbuf; audio->bsbuf = audio->bsspace[audio->bsnum] + 512; audio->bsnum ^= 1; result = mpeg3bits_read_buffer(audio->astream, audio->bsbuf, audio->framesize); } return result; } int mpeg3audio_dolayer3(mpeg3audio_t *audio) { int gr, ch, ss; int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ struct mpeg3_III_sideinfo sideinfo; int channels = audio->channels; int single = audio->single; int ms_stereo, i_stereo; int sfreq = audio->sampling_frequency_code; int stereo1, granules; int i; /* flip/init buffer */ audio->bsbufold = audio->bsbuf; audio->bsbuf = audio->bsspace[audio->bsnum] + 512; audio->bsnum ^= 1; /* read main data into memory */ if(mpeg3bits_read_buffer(audio->astream, audio->bsbuf, audio->framesize)) return 1; mpeg3bits_use_ptr(audio->astream, audio->bsbuf); /* CRC must be skipped here for proper alignment with the backstep */ if(audio->error_protection) mpeg3bits_getbits(audio->astream, 16); if(channels == 1) { /* stream is mono */ stereo1 = 1; single = 0; } else { /* Stereo */ stereo1 = 2; } if(audio->mode == MPG_MD_JOINT_STEREO) { ms_stereo = (audio->mode_ext & 0x2) >> 1; i_stereo = audio->mode_ext & 0x1; } else ms_stereo = i_stereo = 0; if(audio->lsf) { granules = 1; } else { granules = 2; } if(mpeg3audio_III_get_side_info(audio, &sideinfo, channels, ms_stereo, sfreq, single, audio->lsf)) return 1; /* Step back */ if(sideinfo.main_data_begin >= 512) return 1; if(sideinfo.main_data_begin) { memcpy(audio->bsbuf + audio->ssize - sideinfo.main_data_begin, audio->bsbufold + audio->prev_framesize - sideinfo.main_data_begin, sideinfo.main_data_begin); mpeg3bits_use_ptr(audio->astream, audio->bsbuf + audio->ssize - sideinfo.main_data_begin); } for(gr = 0; gr < granules; gr++) { float hybridIn [2][SBLIMIT][SSLIMIT]; float hybridOut[2][SSLIMIT][SBLIMIT]; { struct gr_info_s *gr_info = &(sideinfo.ch[0].gr[gr]); long part2bits; if(audio->lsf) part2bits = mpeg3audio_III_get_scale_factors_2(audio, scalefacs[0], gr_info, 0); else part2bits = mpeg3audio_III_get_scale_factors_1(audio, scalefacs[0], gr_info, 0, gr); //printf("dolayer3 4 %04x\n", mpeg3bits_showbits(audio->astream, 16)); if(mpeg3audio_III_dequantize_sample(audio, hybridIn[0], scalefacs[0], gr_info, sfreq, part2bits)) { mpeg3bits_use_demuxer(audio->astream); return 1; } //printf("dolayer3 5 %04x\n", mpeg3bits_showbits(audio->astream, 16)); } if(channels == 2) { struct gr_info_s *gr_info = &(sideinfo.ch[1].gr[gr]); long part2bits; if(audio->lsf) part2bits = mpeg3audio_III_get_scale_factors_2(audio, scalefacs[1], gr_info, i_stereo); else part2bits = mpeg3audio_III_get_scale_factors_1(audio, scalefacs[1], gr_info, 1, gr); if(mpeg3audio_III_dequantize_sample(audio, hybridIn[1], scalefacs[1], gr_info, sfreq, part2bits)) { mpeg3bits_use_demuxer(audio->astream); return 1; } if(ms_stereo) { int i; int maxb = sideinfo.ch[0].gr[gr].maxb; if(sideinfo.ch[1].gr[gr].maxb > maxb) maxb = sideinfo.ch[1].gr[gr].maxb; for(i = 0; i < SSLIMIT * maxb; i++) { float tmp0 = ((float*)hybridIn[0])[i]; float tmp1 = ((float*)hybridIn[1])[i]; ((float*)hybridIn[0])[i] = tmp0 + tmp1; ((float*)hybridIn[1])[i] = tmp0 - tmp1; } } if(i_stereo) mpeg3audio_III_i_stereo(audio, hybridIn, scalefacs[1], gr_info, sfreq, ms_stereo, audio->lsf); if(ms_stereo || i_stereo || (single == 3)) { if(gr_info->maxb > sideinfo.ch[0].gr[gr].maxb) sideinfo.ch[0].gr[gr].maxb = gr_info->maxb; else gr_info->maxb = sideinfo.ch[0].gr[gr].maxb; } switch(single) { case 3: { register int i; register float *in0 = (float*)hybridIn[0], *in1 = (float*)hybridIn[1]; /* *0.5 done by pow-scale */ for(i = 0; i < SSLIMIT * gr_info->maxb; i++, in0++) *in0 = (*in0 + *in1++); } break; case 1: { register int i; register float *in0 = (float*)hybridIn[0], *in1 = (float*)hybridIn[1]; for(i = 0; i < SSLIMIT * gr_info->maxb; i++) *in0++ = *in1++; } break; } } for(ch = 0; ch < stereo1; ch++) { struct gr_info_s *gr_info = &(sideinfo.ch[ch].gr[gr]); mpeg3audio_III_antialias(audio, hybridIn[ch], gr_info); mpeg3audio_III_hybrid(audio, hybridIn[ch], hybridOut[ch], ch, gr_info); } for(ss = 0; ss < SSLIMIT; ss++) { if(single >= 0) { mpeg3audio_synth_mono(audio, hybridOut[0][ss], audio->pcm_sample, &(audio->pcm_point)); } else { int p1 = audio->pcm_point; mpeg3audio_synth_stereo(audio, hybridOut[0][ss], 0, audio->pcm_sample, &p1); mpeg3audio_synth_stereo(audio, hybridOut[1][ss], 1, audio->pcm_sample, &(audio->pcm_point)); } if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) { /* Need more room */ mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); } } } mpeg3bits_use_demuxer(audio->astream); return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/mpeg3audio.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "libmpeg3.h" #include "mpeg3private.h" #include "mpeg3protos.h" #include "mpeg3audio.h" #include "tables.h" #include #include mpeg3audio_t* mpeg3audio_allocate_struct(mpeg3_t *file, mpeg3_atrack_t *track) { mpeg3audio_t *audio = (mpeg3audio_t *) memoryAllocate(1, sizeof(mpeg3audio_t)); audio->file = file; audio->track = track; audio->astream = mpeg3bits_new_stream(file, track->demuxer); audio->outscale = 1; audio->bsbuf = audio->bsspace[1]; audio->init = 1; audio->bo = 1; audio->channels = 1; return audio; } int mpeg3audio_delete_struct(mpeg3audio_t *audio) { mpeg3bits_delete_stream(audio->astream); if(audio->pcm_sample) memoryFree(audio->pcm_sample); memoryFree(audio); return 0; } int mpeg3audio_replace_buffer(mpeg3audio_t *audio, long new_allocation) { long i; if(!audio->pcm_sample) { audio->pcm_sample = (float *) memoryAllocate(1,sizeof(float) * new_allocation * audio->channels); audio->pcm_allocated = new_allocation; } else { float *new_samples = (float *) memoryAllocate(1,sizeof(float) * new_allocation * audio->channels); for(i = 0; i < audio->pcm_allocated * audio->channels; i++) { new_samples[i] = audio->pcm_sample[i]; } memoryFree(audio->pcm_sample); audio->pcm_sample = new_samples; audio->pcm_allocated = new_allocation; } return 0; } int mpeg3audio_read_frame(mpeg3audio_t *audio) { int result = 0; result = mpeg3audio_read_header(audio); if(!result) { switch(audio->format) { case AUDIO_AC3: //JMM result = mpeg3audio_do_ac3(audio); result = -1; //JMM break; case AUDIO_MPEG: switch(audio->layer) { case 1: break; case 2: result = mpeg3audio_dolayer2(audio); break; case 3: result = mpeg3audio_dolayer3(audio); break; default: result = 1; break; } break; case AUDIO_PCM: result = mpeg3audio_do_pcm(audio); break; } } if(!result) { /* Byte align the stream */ mpeg3bits_byte_align(audio->astream); } return result; } /* Get the length but also initialize the frame sizes. */ int mpeg3audio_get_length(mpeg3audio_t *audio, mpeg3_atrack_t *track) { long result = 0; long framesize1 = 0, total1 = 0; long framesize2 = 0, total2 = 0; long total_framesize = 0, total_frames = 0; long byte_limit = 131072; /* Total bytes to gather information from */ long total_bytes = 0; long major_framesize; /* Bigger framesize + header */ long minor_framesize; /* Smaller framesize + header */ long major_total; long minor_total; mpeg3_t *file = (mpeg3_t *) audio->file; /* Get the frame sizes */ mpeg3bits_seek_start(audio->astream); audio->pcm_point = 0; result = mpeg3audio_read_frame(audio); /* Stores the framesize */ audio->samples_per_frame = audio->pcm_point / audio->channels; switch(audio->format) { case AUDIO_AC3: audio->avg_framesize = audio->framesize; break; case AUDIO_MPEG: framesize1 = audio->framesize; total_bytes += audio->framesize; total1 = 1; while(!result && total_bytes < byte_limit) { audio->pcm_point = 0; result = mpeg3audio_read_frame(audio); total_bytes += audio->framesize; if(audio->framesize != framesize1) { framesize2 = audio->framesize; total2 = 1; break; } else { total1++; } } while(!result && total_bytes < byte_limit) { audio->pcm_point = 0; result = mpeg3audio_read_frame(audio); total_bytes += audio->framesize; if(audio->framesize != framesize2) { break; } else { total2++; } } audio->pcm_point = 0; result = mpeg3audio_read_frame(audio); if(audio->framesize != framesize1 && audio->framesize != framesize2) { /* Variable bit rate. Get the average frame size. */ while(!result && total_bytes < byte_limit) { audio->pcm_point = 0; result = mpeg3audio_read_frame(audio); total_bytes += audio->framesize; if(!result) { total_framesize += audio->framesize; total_frames++; } } audio->avg_framesize = 4 + (float)(total_framesize + framesize1 + framesize2) / (total_frames + total1 + total2); } else { major_framesize = framesize2 > framesize1 ? framesize2 : framesize1; major_total = framesize2 > framesize1 ? total2 : total1; minor_framesize = framesize2 > framesize1 ? framesize1 : framesize2; minor_total = framesize2 > framesize1 ? total1 : total2; /* Add the headers to the framesizes */ audio->avg_framesize = 4 + (float)(major_framesize * major_total + minor_framesize * minor_total) / (major_total + minor_total); } break; case AUDIO_PCM: break; } /* Estimate the total samples */ if(file->is_audio_stream) { /* From the raw file */ result = (long)((float)mpeg3demuxer_total_bytes(audio->astream->demuxer) / audio->avg_framesize * audio->samples_per_frame); } else { /* Gross approximation from a multiplexed file. */ result = (long)(mpeg3demux_length(audio->astream->demuxer) * track->sample_rate); /* result = (long)((float)mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0) * track->sample_rate); */ /* We would scan the multiplexed packets here for the right timecode if only */ /* they had meaningful timecode. */ } audio->pcm_point = 0; mpeg3bits_seek_start(audio->astream); mpeg3audio_reset_synths(audio); return result; } int mpeg3audio_seek(mpeg3audio_t *audio, long position) { int result = 0; mpeg3_t *file = (mpeg3_t *) audio->file; mpeg3_atrack_t *track = (mpeg3_atrack_t *) audio->track; long frame_number; long byte_position = 0; double time_position; /* Sample seek wasn't requested */ if(audio->sample_seek < 0) { audio->pcm_position = position; audio->pcm_size = 0; return 0; } /* Can't slide buffer. Seek instead. */ if(!file->is_audio_stream) { /* Seek in a multiplexed stream using the multiplexer. */ time_position = (double)position / track->sample_rate; result |= mpeg3bits_seek_time(audio->astream, time_position); audio->pcm_position = mpeg3bits_packet_time(audio->astream) * track->sample_rate; /*printf("wanted %f got %f\n", time_position, mpeg3bits_packet_time(audio->astream)); */ } else { /* Seek in an elemental stream. This algorithm achieves sample accuracy on fixed bitrates. */ /* Forget about variable bitrates or program streams. */ frame_number = position / audio->samples_per_frame; byte_position = (long)(audio->avg_framesize * frame_number); audio->pcm_position = frame_number * audio->samples_per_frame; if(byte_position < audio->avg_framesize * 2) { result |= mpeg3bits_seek_start(audio->astream); audio->pcm_position = 0; } else { result |= mpeg3bits_seek_byte(audio->astream, byte_position); } } /* Arm the backstep buffer for layer 3 if not at the beginning already. */ if(byte_position >= audio->avg_framesize * 2 && audio->layer == 3 && !result) { result |= mpeg3audio_prev_header(audio); result |= mpeg3audio_read_layer3_frame(audio); } /* Reset the tables. */ mpeg3audio_reset_synths(audio); audio->pcm_size = 0; audio->pcm_point = 0; return result; } /* ================================================================ */ /* ENTRY POINTS */ /* ================================================================ */ mpeg3audio_t* mpeg3audio_new(mpeg3_t *file, mpeg3_atrack_t *track, int format) { mpeg3audio_t *audio = mpeg3audio_allocate_struct(file, track); int result = 0; /* Init tables */ mpeg3audio_new_decode_tables(audio); audio->percentage_seek = -1; audio->sample_seek = -1; audio->format = format; /* Determine the format of the stream */ if(format == AUDIO_UNKNOWN) { if(((mpeg3bits_showbits(audio->astream, 32) & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) audio->format = AUDIO_AC3; else audio->format = AUDIO_MPEG; } /* get channel count */ result = mpeg3audio_read_header(audio); /* Set up the sample buffer */ mpeg3audio_replace_buffer(audio, 262144); /* Copy information to the mpeg struct */ if(!result) { track->channels = audio->channels; switch(audio->format) { case AUDIO_AC3: //JMM track->sample_rate = mpeg3_ac3_samplerates[audio->sampling_frequency_code]; break; case AUDIO_MPEG: track->sample_rate = mpeg3_freqs[audio->sampling_frequency_code]; break; case AUDIO_PCM: track->sample_rate = 48000; break; } track->total_samples = mpeg3audio_get_length(audio, track); result |= mpeg3bits_seek_start(audio->astream); } else { mpeg3audio_delete_struct(audio); audio = 0; } return audio; } int mpeg3audio_delete(mpeg3audio_t *audio) { mpeg3audio_delete_struct(audio); return 0; } int mpeg3audio_seek_percentage(mpeg3audio_t *audio, double percentage) { audio->percentage_seek = percentage; return 0; } int mpeg3audio_seek_sample(mpeg3audio_t *audio, long sample) { audio->sample_seek = sample; return 0; } /* Read raw frames for concatenation purposes */ int mpeg3audio_read_raw(mpeg3audio_t *audio, unsigned char *output, long *size, long max_size) { int result = 0; int i; *size = 0; switch(audio->format) { case AUDIO_AC3: /* Just write the AC3 stream */ if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) return 1; *size = audio->framesize; break; case AUDIO_MPEG: /* Fix the mpeg stream */ result = mpeg3audio_read_header(audio); if(!result) { if(max_size < 4) return 1; *output++ = (audio->newhead & 0xff000000) >> 24; *output++ = (audio->newhead & 0xff0000) >> 16; *output++ = (audio->newhead & 0xff00) >> 8; *output++ = (audio->newhead & 0xff); *size += 4; if(max_size < 4 + audio->framesize) return 1; if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) return 1; *size += audio->framesize; } break; case AUDIO_PCM: if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize)) return 1; *size = audio->framesize; break; } return result; } /* Channel is 0 to channels - 1 */ int mpeg3audio_decode_audio(mpeg3audio_t *audio, float *output_f, short *output_i, int channel, long start_position, long len) { long allocation_needed = len + MPEG3AUDIO_PADDING; long i, j, result = 0; mpeg3_t *file = (mpeg3_t *) audio->file; mpeg3_atrack_t *atrack = (mpeg3_atrack_t *) audio->track; long attempts; /* Create new buffer */ if(audio->pcm_allocated < allocation_needed) { mpeg3audio_replace_buffer(audio, allocation_needed); } /* There was a percentage seek */ if(audio->percentage_seek >= 0) { mpeg3bits_seek_percentage(audio->astream, audio->percentage_seek); /* Force the pcm buffer to be reread. */ audio->pcm_position = start_position; audio->pcm_size = 0; audio->percentage_seek = -1; } else { /* Entire output is in buffer so don't do anything. */ if(start_position >= audio->pcm_position && start_position < audio->pcm_position + audio->pcm_size && start_position + len <= audio->pcm_size) { ; } else /* Output starts in buffer but ends later so slide it back. */ if(start_position <= audio->pcm_position + audio->pcm_size && start_position >= audio->pcm_position) { for(i = 0, j = (start_position - audio->pcm_position) * audio->channels; j < audio->pcm_size * audio->channels; i++, j++) { audio->pcm_sample[i] = audio->pcm_sample[j]; } audio->pcm_point = i; audio->pcm_size -= start_position - audio->pcm_position; audio->pcm_position = start_position; } else { /* Output is outside buffer completely. */ result = mpeg3audio_seek(audio, start_position); audio->sample_seek = -1; /* Check sanity */ if(start_position < audio->pcm_position) audio->pcm_position = start_position; } audio->sample_seek = -1; } /* Read packets until the buffer is full. */ if(!result) { attempts = 0; while(attempts < 6 && !mpeg3bits_eof(audio->astream) && audio->pcm_size + audio->pcm_position < start_position + len) { result = mpeg3audio_read_frame(audio); if(result) attempts++; audio->pcm_size = audio->pcm_point / audio->channels; } } /* Copy the buffer to the output */ if(output_f) { for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel; i < len && j < audio->pcm_size * audio->channels; i++, j += audio->channels) { output_f[i] = audio->pcm_sample[j]; } for( ; i < len; i++) { output_f[i] = 0; } } else if(output_i) { int sample; for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel; i < len && j < audio->pcm_size * audio->channels; i++, j += audio->channels) { sample = (int)(audio->pcm_sample[j] * 32767); if(sample > 32767) sample = 32767; else if(sample < -32768) sample = -32768; output_i[i] = sample; } for( ; i < len; i++) { output_i[i] = 0; } } if(audio->pcm_point > 0) return 0; else return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/mpeg3audio.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef MPEG3AUDIO_H #define MPEG3AUDIO_H #include "ac3.h" #include "bitstream.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #define M_SQRT2 1.41421356237309504880 #endif #define MAXFRAMESIZE 1792 #define HDRCMPMASK 0xfffffd00 #define SBLIMIT 32 #define SSLIMIT 18 #define SCALE_BLOCK 12 #define MPEG3AUDIO_PADDING 1024 /* Values for mode */ #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 /* IMDCT variables */ typedef struct { float real; float imag; } mpeg3_complex_t; #define AC3_N 512 struct al_table { short bits; short d; }; typedef struct { void* file; void* track; mpeg3_bits_t *astream; /* In order of importance */ int format; /* format of audio */ int layer; /* layer if mpeg */ int channels; long outscale; long framenum; long prev_framesize; long framesize; /* For mp3 current framesize without header. For AC3 current framesize with header. */ float avg_framesize; /* Includes the 4 byte header */ float *pcm_sample; /* Interlaced output from synthesizer in floats */ int pcm_point; /* Float offset in pcm_sample to write to */ long pcm_position; /* Sample start of pcm_samples in file */ long pcm_size; /* Number of pcm samples in the buffer */ long pcm_allocated; /* Allocated number of samples in pcm_samples */ int sample_seek; double percentage_seek; unsigned long oldhead; unsigned long newhead; unsigned long firsthead; int bsnum; int lsf; int mpeg35; int sampling_frequency_code; int bitrate_index; int bitrate; int samples_per_frame; int padding; int extension; int mode; int mode_ext; int copyright; int original; int emphasis; int error_protection; /* Back step buffers for mp3 */ unsigned char bsspace[2][MAXFRAMESIZE + 512]; /* MAXFRAMESIZE */ unsigned char *bsbuf, *bsbufold; long ssize; int init; int single; struct al_table *alloc; int II_sblimit; int jsbound; int bo; /* Static variable in synthesizer */ /* MP3 Static arrays here */ float synth_stereo_buffs[2][2][0x110]; float synth_mono_buff[64]; unsigned int layer2_scfsi_buf[64]; float mp3_block[2][2][SBLIMIT * SSLIMIT]; int mp3_blc[2]; /* AC3 specific stuff. AC3 also shares objects with MPEG */ unsigned int ac3_framesize_code; mpeg3_ac3bsi_t ac3_bsi; mpeg3_ac3audblk_t ac3_audblk; mpeg3_ac3_bitallocation_t ac3_bit_allocation; mpeg3_ac3_mantissa_t ac3_mantissa; mpeg3_complex_t ac3_imdct_buf[AC3_N / 4]; /* Delay buffer for DCT interleaving */ float ac3_delay[6][AC3_N / 2]; /* Twiddle factor LUT */ mpeg3_complex_t *ac3_w[7]; mpeg3_complex_t ac3_w_1[1]; mpeg3_complex_t ac3_w_2[2]; mpeg3_complex_t ac3_w_4[4]; mpeg3_complex_t ac3_w_8[8]; mpeg3_complex_t ac3_w_16[16]; mpeg3_complex_t ac3_w_32[32]; mpeg3_complex_t ac3_w_64[64]; int ac3_lfsr_state; unsigned char ac3_buffer[MAX_AC3_FRAMESIZE]; mpeg3ac3_stream_samples_t ac3_samples; } mpeg3audio_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/pcm.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3audio.h" #include "mpeg3private.inc" int mpeg3audio_read_pcm_header(mpeg3audio_t *audio) { unsigned int code; code = mpeg3bits_getbits(audio->astream, 16); while(!mpeg3bits_eof(audio->astream) && code != MPEG3_PCM_START_CODE) { code <<= 8; code &= 0xffff; code |= mpeg3bits_getbits(audio->astream, 8); } audio->avg_framesize = audio->framesize = 0x7db; audio->channels = 2; return mpeg3bits_eof(audio->astream); } int mpeg3audio_do_pcm(mpeg3audio_t *audio) { int i, j, k; MPEG3_INT16 sample; int frame_samples = (audio->framesize - 3) / audio->channels / 2; if(mpeg3bits_read_buffer(audio->astream, audio->ac3_buffer, frame_samples * audio->channels * 2)) return 1; /* Need more room */ if(audio->pcm_point / audio->channels >= audio->pcm_allocated - MPEG3AUDIO_PADDING * audio->channels) { mpeg3audio_replace_buffer(audio, audio->pcm_allocated + MPEG3AUDIO_PADDING * audio->channels); } k = 0; for(i = 0; i < frame_samples; i++) { for(j = 0; j < audio->channels; j++) { sample = ((MPEG3_INT16)(audio->ac3_buffer[k++])) << 8; sample |= audio->ac3_buffer[k++]; audio->pcm_sample[audio->pcm_point + i * audio->channels + j] = (float)sample / 32767; } } audio->pcm_point += frame_samples * audio->channels; return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/synthesizers.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3audio.h" #include "tables.h" #define WRITE_SAMPLE(samples, sum) \ { \ (*samples) = (sum); \ } int mpeg3audio_synth_stereo(mpeg3audio_t *audio, float *bandPtr, int channel, float *out, int *pnt) { const int step = 2; float *samples = out + *pnt; register float sum; float *b0, (*buf)[0x110]; int bo1; if(!channel) { audio->bo--; audio->bo &= 0xf; buf = audio->synth_stereo_buffs[0]; } else { samples++; buf = audio->synth_stereo_buffs[1]; } if(audio->bo & 0x1) { b0 = buf[0]; bo1 = audio->bo; mpeg3audio_dct64(buf[1] + ((audio->bo + 1) & 0xf), buf[0] + audio->bo, bandPtr); } else { b0 = buf[1]; bo1 = audio->bo + 1; mpeg3audio_dct64(buf[0] + audio->bo, buf[1] + audio->bo + 1, bandPtr); } /*printf("%f %f %f\n", buf[0][0], buf[1][0], bandPtr[0]); */ { register int j; float *window = mpeg3_decwin + 16 - bo1; for(j = 16; j; j--, b0 += 0x10, window += 0x20, samples += step) { sum = window[0x0] * b0[0x0]; sum -= window[0x1] * b0[0x1]; sum += window[0x2] * b0[0x2]; sum -= window[0x3] * b0[0x3]; sum += window[0x4] * b0[0x4]; sum -= window[0x5] * b0[0x5]; sum += window[0x6] * b0[0x6]; sum -= window[0x7] * b0[0x7]; sum += window[0x8] * b0[0x8]; sum -= window[0x9] * b0[0x9]; sum += window[0xA] * b0[0xA]; sum -= window[0xB] * b0[0xB]; sum += window[0xC] * b0[0xC]; sum -= window[0xD] * b0[0xD]; sum += window[0xE] * b0[0xE]; sum -= window[0xF] * b0[0xF]; WRITE_SAMPLE(samples, sum); } sum = window[0x0] * b0[0x0]; sum += window[0x2] * b0[0x2]; sum += window[0x4] * b0[0x4]; sum += window[0x6] * b0[0x6]; sum += window[0x8] * b0[0x8]; sum += window[0xA] * b0[0xA]; sum += window[0xC] * b0[0xC]; sum += window[0xE] * b0[0xE]; WRITE_SAMPLE(samples, sum); b0 -= 0x10; window -= 0x20; samples += step; window += bo1 << 1; for(j = 15; j; j--, b0 -= 0x10, window -= 0x20, samples += step) { sum = -window[-0x1] * b0[0x0]; sum -= window[-0x2] * b0[0x1]; sum -= window[-0x3] * b0[0x2]; sum -= window[-0x4] * b0[0x3]; sum -= window[-0x5] * b0[0x4]; sum -= window[-0x6] * b0[0x5]; sum -= window[-0x7] * b0[0x6]; sum -= window[-0x8] * b0[0x7]; sum -= window[-0x9] * b0[0x8]; sum -= window[-0xA] * b0[0x9]; sum -= window[-0xB] * b0[0xA]; sum -= window[-0xC] * b0[0xB]; sum -= window[-0xD] * b0[0xC]; sum -= window[-0xE] * b0[0xD]; sum -= window[-0xF] * b0[0xE]; sum -= window[-0x0] * b0[0xF]; WRITE_SAMPLE(samples, sum); } } *pnt += 64; return 0; } int mpeg3audio_synth_mono(mpeg3audio_t *audio, float *bandPtr, float *samples, int *pnt) { float *samples_tmp = audio->synth_mono_buff; float *tmp1 = samples_tmp; int i, ret; int pnt1 = 0; ret = mpeg3audio_synth_stereo(audio, bandPtr, 0, samples_tmp, &pnt1); samples += *pnt; for(i = 0; i < 32; i++) { *samples = *tmp1; samples++; tmp1 += 2; } *pnt += 32; return ret; } /* Call this after every seek to reset the buffers */ int mpeg3audio_reset_synths(mpeg3audio_t *audio) { int i, j, k; for(i = 0; i < 2; i++) { for(j = 0; j < 2; j++) { for(k = 0; k < 0x110; k++) { audio->synth_stereo_buffs[i][j][k] = 0; } } } for(i = 0; i < 64; i++) { audio->synth_mono_buff[i] = 0; audio->layer2_scfsi_buf[i] = 0; } for(i = 0; i < 2; i++) { for(j = 0; j < 2; j++) { for(k = 0; k < SBLIMIT * SSLIMIT; k++) { audio->mp3_block[i][j][k] = 0; } } } audio->mp3_blc[0] = 0; audio->mp3_blc[1] = 0; for(i = 0; i < audio->channels; i++) { for(j = 0; j < AC3_N / 2; j++) { audio->ac3_delay[i][j] = 0; } } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/tables.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3audio.h" #include "tables.h" #include /* Bitrate indexes */ int mpeg3_tabsel_123[2][3][16] = { { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } }; long mpeg3_freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 }; #ifdef USE_3DNOW float mpeg3_decwin[2 * (512 + 32)]; float mpeg3_cos64[32], mpeg3_cos32[16], mpeg3_cos16[8], mpeg3_cos8[4], mpeg3_cos4[2]; #else float mpeg3_decwin[512 + 32]; float mpeg3_cos64[16], mpeg3_cos32[8], mpeg3_cos16[4], mpeg3_cos8[2], mpeg3_cos4[1]; #endif float *mpeg3_pnts[] = { mpeg3_cos64, mpeg3_cos32, mpeg3_cos16, mpeg3_cos8, mpeg3_cos4 }; int mpeg3_grp_3tab[32 * 3] = { 0, }; /* used: 27 */ int mpeg3_grp_5tab[128 * 3] = { 0, }; /* used: 125 */ int mpeg3_grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ float mpeg3_muls[27][64]; /* also used by layer 1 */ float mpeg3_gainpow2[256 + 118 + 4]; float mpeg3_ispow[8207]; float mpeg3_aa_ca[8], mpeg3_aa_cs[8]; float mpeg3_win[4][36]; float mpeg3_win1[4][36]; float mpeg3_COS1[12][6]; float mpeg3_COS9[9]; float mpeg3_COS6_1, mpeg3_COS6_2; float mpeg3_tfcos36[9]; float mpeg3_tfcos12[3]; float mpeg3_cos9[3], mpeg3_cos18[3]; float mpeg3_tan1_1[16], mpeg3_tan2_1[16], mpeg3_tan1_2[16], mpeg3_tan2_2[16]; float mpeg3_pow1_1[2][16], mpeg3_pow2_1[2][16], mpeg3_pow1_2[2][16], mpeg3_pow2_2[2][16]; long mpeg3_intwinbase[] = { 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -4, -4, -5, -5, -6, -7, -7, -8, -9, -10, -11, -13, -14, -16, -17, -19, -21, -24, -26, -29, -31, -35, -38, -41, -45, -49, -53, -58, -63, -68, -73, -79, -85, -91, -97, -104, -111, -117, -125, -132, -139, -147, -154, -161, -169, -176, -183, -190, -196, -202, -208, -213, -218, -222, -225, -227, -228, -228, -227, -224, -221, -215, -208, -200, -189, -177, -163, -146, -127, -106, -83, -57, -29, 2, 36, 72, 111, 153, 197, 244, 294, 347, 401, 459, 519, 581, 645, 711, 779, 848, 919, 991, 1064, 1137, 1210, 1283, 1356, 1428, 1498, 1567, 1634, 1698, 1759, 1817, 1870, 1919, 1962, 2001, 2032, 2057, 2075, 2085, 2087, 2080, 2063, 2037, 2000, 1952, 1893, 1822, 1739, 1644, 1535, 1414, 1280, 1131, 970, 794, 605, 402, 185, -45, -288, -545, -814, -1095, -1388, -1692, -2006, -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, -7910, -8209, -8491, -8755, -8998, -9219, -9416, -9585, -9727, -9838, -9916, -9959, -9966, -9935, -9863, -9750, -9592, -9389, -9139, -8840, -8492, -8092, -7640, -7134, -6574, -5959, -5288, -4561, -3776, -2935, -2037, -1082, -70, 998, 2122, 3300, 4533, 5818, 7154, 8540, 9975, 11455, 12980, 14548, 16155, 17799, 19478, 21189, 22929, 24694, 26482, 28289, 30112, 31947, 33791, 35640, 37489, 39336, 41176, 43006, 44821, 46617, 48390, 50137, 51853, 53534, 55178, 56778, 58333, 59838, 61289, 62684, 64019, 65290, 66494, 67629, 68692, 69679, 70590, 71420, 72169, 72835, 73415, 73908, 74313, 74630, 74856, 74992, 75038 }; int mpeg3_longLimit[9][23]; int mpeg3_shortLimit[9][14]; struct mpeg3_bandInfoStruct mpeg3_bandInfo[9] = { /* MPEG 1.0 */ { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, {4,4,4,4,6,8,10,12,14,18,22,30,56} } , { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, {4,4,4,4,6,6,10,12,14,16,20,26,66} } , { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , {4,4,4,4,6,8,12,16,20,26,34,42,12} } , /* MPEG 2.0 */ { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576}, {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,52,64,70,76,36 } , {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , /* MPEG 2.5 */ { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, {4,4,4,6,8,10,12,14,18,24,30,40,18} }, { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, {4,4,4,6,8,10,12,14,18,24,30,40,18} }, { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, {8,8,8,12,16,20,24,28,36,2,2,2,26} } , }; int mpeg3_mapbuf0[9][152]; int mpeg3_mapbuf1[9][156]; int mpeg3_mapbuf2[9][44]; int *mpeg3_map[9][3]; int *mpeg3_mapend[9][3]; unsigned int mpeg3_n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ unsigned int mpeg3_i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ int mpeg3audio_init_layer2(mpeg3audio_t *audio) { static double mulmul[27] = { 0.0 , -2.0/3.0 , 2.0/3.0 , 2.0/7.0 , 2.0/15.0 , 2.0/31.0, 2.0/63.0 , 2.0/127.0 , 2.0/255.0 , 2.0/511.0 , 2.0/1023.0 , 2.0/2047.0 , 2.0/4095.0 , 2.0/8191.0 , 2.0/16383.0 , 2.0/32767.0 , 2.0/65535.0 , -4.0/5.0 , -2.0/5.0 , 2.0/5.0, 4.0/5.0 , -8.0/9.0 , -4.0/9.0 , -2.0/9.0 , 2.0/9.0 , 4.0/9.0 , 8.0/9.0 }; static int base[3][9] = { { 1 , 0, 2 , } , { 17, 18, 0 , 19, 20 , } , { 21, 1, 22, 23, 0, 24, 25, 2, 26 } }; static int tablen[3] = { 3, 5, 9 }; static int *itable, *tables[3] = {mpeg3_grp_3tab, mpeg3_grp_5tab, mpeg3_grp_9tab}; int i, j, k, l, len; float *table; for(i = 0; i < 3; i++) { itable = tables[i]; len = tablen[i]; for(j = 0; j < len; j++) for(k = 0; k < len; k++) for(l = 0; l < len; l++) { *itable++ = base[i][l]; *itable++ = base[i][k]; *itable++ = base[i][j]; } } for(k = 0; k < 27; k++) { double m = mulmul[k]; table = mpeg3_muls[k]; for(j = 3, i = 0; i < 63; i++, j--) *table++ = m * pow(2.0, (double)j / 3.0); *table++ = 0.0; } return 0; } int mpeg3audio_init_layer3(mpeg3audio_t *audio) { int i, j, k, l; int down_sample_sblimit = 32; audio->mp3_block[0][0][0] = 0; audio->mp3_blc[0] = 0; audio->mp3_blc[1] = 0; for(i = -256; i < 118 + 4; i++) mpeg3_gainpow2[i + 256] = pow((double)2.0, -0.25 * (double)(i + 210)); for(i = 0; i < 8207; i++) mpeg3_ispow[i] = pow((double)i, (double)4.0 / 3.0); for(i = 0; i < 8; i++) { static double Ci[8] = {-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037}; double sq = sqrt(1.0+Ci[i]*Ci[i]); mpeg3_aa_cs[i] = 1.0/sq; mpeg3_aa_ca[i] = Ci[i]/sq; } for(i = 0; i < 18; i++) { mpeg3_win[0][i] = mpeg3_win[1][i] = 0.5 * sin( M_PI / 72.0 * (double)(2 * (i + 0) + 1) ) / cos (M_PI * (double)(2 * (i + 0) + 19) / 72.0); mpeg3_win[0][i+18] = mpeg3_win[3][i+18] = 0.5 * sin( M_PI / 72.0 * (double)(2 * (i + 18) + 1) ) / cos (M_PI * (double)(2 * (i + 18) + 19) / 72.0); } for(i = 0; i < 6; i++) { mpeg3_win[1][i + 18] = 0.5 / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); mpeg3_win[3][i + 12] = 0.5 / cos ( M_PI * (double) (2*(i+12)+19) / 72.0 ); mpeg3_win[1][i + 24] = 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 13) ) / cos (M_PI * (double)(2 * (i + 24)+ 19) / 72.0 ); mpeg3_win[1][i + 30] = mpeg3_win[3][i] = 0.0; mpeg3_win[3][i + 6 ] = 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 1) ) / cos (M_PI * (double)(2 * (i + 6 )+ 19) / 72.0 ); } for(i = 0; i < 9; i++) mpeg3_COS9[i] = cos(M_PI / 18.0 * (double)i); for(i = 0; i < 9; i++) mpeg3_tfcos36[i] = 0.5 / cos (M_PI * (double) (i*2+1) / 36.0); for(i = 0; i < 3; i++) mpeg3_tfcos12[i] = 0.5 / cos (M_PI * (double) (i*2+1) / 12.0); mpeg3_COS6_1 = cos( M_PI / 6.0 * (double) 1); mpeg3_COS6_2 = cos( M_PI / 6.0 * (double) 2); mpeg3_cos9[0] = cos(1.0 * M_PI / 9.0); mpeg3_cos9[1] = cos(5.0 * M_PI / 9.0); mpeg3_cos9[2] = cos(7.0 * M_PI / 9.0); mpeg3_cos18[0] = cos(1.0 * M_PI / 18.0); mpeg3_cos18[1] = cos(11.0 * M_PI / 18.0); mpeg3_cos18[2] = cos(13.0 * M_PI / 18.0); for(i = 0; i < 12; i++) { mpeg3_win[2][i] = 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double)(2 * i + 7) / 24.0); for(j = 0; j < 6; j++) mpeg3_COS1[i][j] = cos(M_PI / 24.0 * (double) ((2 * i + 7) * (2 * j + 1))); } for(j = 0; j < 4; j++) { static int len[4] = {36, 36, 12, 36}; for(i = 0; i < len[j]; i += 2) mpeg3_win1[j][i] = + mpeg3_win[j][i]; for(i = 1; i < len[j]; i += 2) mpeg3_win1[j][i] = - mpeg3_win[j][i]; } for(i = 0; i < 16; i++) { double t = tan( (double) i * M_PI / 12.0 ); mpeg3_tan1_1[i] = t / (1.0 + t); mpeg3_tan2_1[i] = 1.0 / (1.0 + t); mpeg3_tan1_2[i] = M_SQRT2 * t / (1.0 + t); mpeg3_tan2_2[i] = M_SQRT2 / (1.0 + t); for(j = 0; j < 2; j++) { double base = pow(2.0, -0.25 * (j + 1.0)); double p1 = 1.0,p2 = 1.0; if(i > 0) { if( i & 1 ) p1 = pow(base, (i + 1.0) * 0.5); else p2 = pow(base, i * 0.5); } mpeg3_pow1_1[j][i] = p1; mpeg3_pow2_1[j][i] = p2; mpeg3_pow1_2[j][i] = M_SQRT2 * p1; mpeg3_pow2_2[j][i] = M_SQRT2 * p2; } } for(j = 0; j < 9; j++) { struct mpeg3_bandInfoStruct *bi = &mpeg3_bandInfo[j]; int *mp; int cb,lwin; int *bdf; mp = mpeg3_map[j][0] = mpeg3_mapbuf0[j]; bdf = bi->longDiff; for(i = 0, cb = 0; cb < 8; cb++, i += *bdf++) { *mp++ = (*bdf) >> 1; *mp++ = i; *mp++ = 3; *mp++ = cb; } bdf = bi->shortDiff + 3; for(cb = 3; cb < 13; cb++) { int l = (*bdf++) >> 1; for(lwin = 0; lwin < 3; lwin++) { *mp++ = l; *mp++ = i + lwin; *mp++ = lwin; *mp++ = cb; } i += 6 * l; } mpeg3_mapend[j][0] = mp; mp = mpeg3_map[j][1] = mpeg3_mapbuf1[j]; bdf = bi->shortDiff+0; for(i = 0,cb = 0; cb < 13; cb++) { int l = (*bdf++) >> 1; for(lwin = 0; lwin < 3; lwin++) { *mp++ = l; *mp++ = i + lwin; *mp++ = lwin; *mp++ = cb; } i += 6 * l; } mpeg3_mapend[j][1] = mp; mp = mpeg3_map[j][2] = mpeg3_mapbuf2[j]; bdf = bi->longDiff; for(cb = 0; cb < 22 ; cb++) { *mp++ = (*bdf++) >> 1; *mp++ = cb; } mpeg3_mapend[j][2] = mp; } for(j = 0; j < 9; j++) { for(i = 0; i < 23; i++) { mpeg3_longLimit[j][i] = (mpeg3_bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; if(mpeg3_longLimit[j][i] > (down_sample_sblimit)) mpeg3_longLimit[j][i] = down_sample_sblimit; } for(i = 0; i < 14; i++) { mpeg3_shortLimit[j][i] = (mpeg3_bandInfo[j].shortIdx[i] - 1) / 18 + 1; if(mpeg3_shortLimit[j][i] > (down_sample_sblimit) ) mpeg3_shortLimit[j][i] = down_sample_sblimit; } } for(i = 0; i < 5; i++) { for(j = 0; j < 6; j++) { for(k = 0; k < 6; k++) { int n = k + j * 6 + i * 36; mpeg3_i_slen2[n] = i | (j << 3) | (k << 6) | (3 << 12); } } } for(i = 0; i < 4; i++) { for(j = 0; j < 4; j++) { for(k = 0; k < 4; k++) { int n = k + j * 4 + i * 16; mpeg3_i_slen2[n+180] = i | (j << 3) | (k << 6) | (4 << 12); } } } for(i = 0; i < 4; i++) { for(j = 0; j < 3; j++) { int n = j + i * 3; mpeg3_i_slen2[n + 244] = i | (j << 3) | (5 << 12); mpeg3_n_slen2[n + 500] = i | (j << 3) | (2 << 12) | (1 << 15); } } for(i = 0; i < 5; i++) { for(j = 0; j < 5; j++) { for(k = 0; k < 4; k++) { for(l = 0; l < 4; l++) { int n = l + k * 4 + j * 16 + i * 80; mpeg3_n_slen2[n] = i | (j << 3) | ( k << 6) | (l << 9) | (0 << 12); } } } } for(i = 0; i < 5; i++) { for(j = 0; j < 5; j++) { for(k = 0; k < 4; k++) { int n = k + j * 4 + i * 20; mpeg3_n_slen2[n + 400] = i | (j << 3) | (k << 6) | (1 << 12); } } } return 0; } int mpeg3audio_new_decode_tables(mpeg3audio_t *audio) { int i, j, k, kr, divv; float *costab; int idx; long scaleval = audio->outscale; for(i = 0; i < 5; i++) { kr = 0x10 >> i; divv = 0x40 >> i; costab = mpeg3_pnts[i]; for(k = 0; k < kr; k++) costab[k] = 1.0 / (2.0 * cos(M_PI * ((double)k * 2.0 + 1.0) / (double)divv)); #ifdef USE_3DNOW for(k = 0; k < kr; k++) costab[k + kr] = -costab[k]; #endif } idx = 0; scaleval = -scaleval; for(i = 0, j = 0; i < 256; i++, j++,idx += 32) { if(idx < 512 + 16) mpeg3_decwin[idx+16] = mpeg3_decwin[idx] = (double)mpeg3_intwinbase[j] / 65536.0 * (double)scaleval; if(i % 32 == 31) idx -= 1023; if(i % 64 == 63) scaleval = -scaleval; } for( ; i < 512; i++, j--, idx += 32) { if(idx < 512 + 16) mpeg3_decwin[idx + 16] = mpeg3_decwin[idx] = (double)mpeg3_intwinbase[j] / 65536.0 * (double)scaleval; if(i % 32 == 31) idx -= 1023; if(i % 64 == 63) scaleval = -scaleval; } #ifdef USE_3DNOW if(!param.down_sample) { for(i = 0; i < 512 + 32; i++) { mpeg3_decwin[512 + 31 - i] *= 65536.0; /* allows faster clipping in 3dnow code */ mpeg3_decwin[512 + 32 + i] = mpeg3_decwin[512 + 31 - i]; } } #endif /* Initialize AC3 */ audio->ac3_lfsr_state = 1; mpeg3audio_imdct_init(audio); /* Initialize MPEG */ mpeg3audio_init_layer2(audio); /* inits also shared tables with layer1 */ mpeg3audio_init_layer3(audio); return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/audio/tables.h ================================================ #ifndef TABLES_H #define TABLES_H extern int mpeg3_tabsel_123[2][3][16]; extern long mpeg3_freqs[9]; struct mpeg3_bandInfoStruct { int longIdx[23]; int longDiff[22]; int shortIdx[14]; int shortDiff[13]; }; extern float mpeg3_decwin[512 + 32]; extern float mpeg3_cos64[16], mpeg3_cos32[8], mpeg3_cos16[4], mpeg3_cos8[2], mpeg3_cos4[1]; extern float *mpeg3_pnts[5]; extern int mpeg3_grp_3tab[32 * 3]; /* used: 27 */ extern int mpeg3_grp_5tab[128 * 3]; /* used: 125 */ extern int mpeg3_grp_9tab[1024 * 3]; /* used: 729 */ extern float mpeg3_muls[27][64]; /* also used by layer 1 */ extern float mpeg3_gainpow2[256 + 118 + 4]; extern long mpeg3_intwinbase[257]; extern float mpeg3_ispow[8207]; extern float mpeg3_aa_ca[8], mpeg3_aa_cs[8]; extern float mpeg3_win[4][36]; extern float mpeg3_win1[4][36]; extern float mpeg3_COS1[12][6]; extern float mpeg3_COS9[9]; extern float mpeg3_COS6_1, mpeg3_COS6_2; extern float mpeg3_tfcos36[9]; extern float mpeg3_tfcos12[3]; extern float mpeg3_cos9[3], mpeg3_cos18[3]; extern float mpeg3_tan1_1[16], mpeg3_tan2_1[16], mpeg3_tan1_2[16], mpeg3_tan2_2[16]; extern float mpeg3_pow1_1[2][16], mpeg3_pow2_1[2][16], mpeg3_pow1_2[2][16], mpeg3_pow2_2[2][16]; extern int mpeg3_longLimit[9][23]; extern int mpeg3_shortLimit[9][14]; extern struct mpeg3_bandInfoStruct mpeg3_bandInfo[9]; extern int mpeg3_mapbuf0[9][152]; extern int mpeg3_mapbuf1[9][156]; extern int mpeg3_mapbuf2[9][44]; extern int *mpeg3_map[9][3]; extern int *mpeg3_mapend[9][3]; extern unsigned int mpeg3_n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ extern unsigned int mpeg3_i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/bitstream.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3protos.h" #include mpeg3_bits_t* mpeg3bits_new_stream(mpeg3_t *file, mpeg3_demuxer_t *demuxer) { mpeg3_bits_t *stream = (mpeg3_bits_t *) memoryAllocate(1,sizeof(mpeg3_bits_t)); stream->bfr = 0; stream->bfr_size = 0; stream->bit_number = 0; stream->file = file; stream->demuxer = demuxer; stream->input_ptr = 0; return stream; } int mpeg3bits_delete_stream(mpeg3_bits_t* stream) { memoryFree(stream); return 0; } /* Fill a buffer. Only works if bit_number is on an 8 bit boundary */ int mpeg3bits_read_buffer(mpeg3_bits_t* stream, unsigned char *buffer, int bytes) { int result, i = 0; while(stream->bit_number > 0) { stream->bit_number -= 8; mpeg3demux_read_prev_char(stream->demuxer); } stream->bit_number = 0; stream->bfr_size = 0; stream->bfr = 0; result = mpeg3demux_read_data(stream->demuxer, buffer, bytes); return result; } /* For mp3 decompression use a pointer in a buffer for getbits. */ int mpeg3bits_use_ptr(mpeg3_bits_t* stream, unsigned char *buffer) { stream->bfr_size = stream->bit_number = 0; stream->bfr = 0; stream->input_ptr = buffer; return 0; } /* Go back to using the demuxer for getbits in mp3. */ int mpeg3bits_use_demuxer(mpeg3_bits_t* stream) { if(stream->input_ptr) { stream->bfr_size = stream->bit_number = 0; stream->input_ptr = 0; stream->bfr = 0; } return 0; } /* Reconfigure for reverse operation */ /* Default is forward operation */ void mpeg3bits_start_reverse(mpeg3_bits_t* stream) { int i; for(i = 0; i < stream->bfr_size; i += 8) if(stream->input_ptr) stream->input_ptr--; else mpeg3demux_read_prev_char(stream->demuxer); } /* Reconfigure for forward operation */ void mpeg3bits_start_forward(mpeg3_bits_t* stream) { int i; for(i = 0; i < stream->bfr_size; i += 8) if(stream->input_ptr) stream->input_ptr++; else mpeg3demux_read_char(stream->demuxer); } /* Erase the buffer with the next 4 bytes in the file. */ int mpeg3bits_refill(mpeg3_bits_t* stream) { stream->bit_number = 32; stream->bfr_size = 32; if(stream->input_ptr) { stream->bfr = (unsigned int)(*stream->input_ptr++) << 24; stream->bfr |= (unsigned int)(*stream->input_ptr++) << 16; stream->bfr |= (unsigned int)(*stream->input_ptr++) << 8; stream->bfr |= *stream->input_ptr++; } else { stream->bfr = mpeg3demux_read_char(stream->demuxer) << 24; stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 16; stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 8; stream->bfr |= mpeg3demux_read_char(stream->demuxer); } return mpeg3demux_eof(stream->demuxer); } /* Erase the buffer with the previous 4 bytes in the file. */ int mpeg3bits_refill_backwards(mpeg3_bits_t* stream) { stream->bit_number = 0; stream->bfr_size = 32; stream->bfr = mpeg3demux_read_prev_char(stream->demuxer); stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 8; stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 16; stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 24; return mpeg3demux_eof(stream->demuxer); } int mpeg3bits_byte_align(mpeg3_bits_t *stream) { stream->bit_number = (stream->bit_number + 7) & 0xf8; return 0; } int mpeg3bits_seek_end(mpeg3_bits_t* stream) { stream->bfr_size = stream->bit_number = 0; return mpeg3demux_seek_byte(stream->demuxer, mpeg3demuxer_total_bytes(stream->demuxer)); } int mpeg3bits_seek_start(mpeg3_bits_t* stream) { stream->bfr_size = stream->bit_number = 0; return mpeg3demux_seek_byte(stream->demuxer, 0); } int mpeg3bits_seek_time(mpeg3_bits_t* stream, double time_position) { stream->bfr_size = stream->bit_number = 0; return mpeg3demux_seek_time(stream->demuxer, time_position); } int mpeg3bits_seek_byte(mpeg3_bits_t* stream, long position) { stream->bfr_size = stream->bit_number = 0; return mpeg3demux_seek_byte(stream->demuxer, position); } int mpeg3bits_seek_percentage(mpeg3_bits_t* stream, double percentage) { stream->bfr_size = stream->bit_number = 0; return mpeg3demux_seek_percentage(stream->demuxer, percentage); } int mpeg3bits_tell(mpeg3_bits_t* stream) { return mpeg3demux_tell(stream->demuxer); } int mpeg3bits_getbitoffset(mpeg3_bits_t *stream) { return stream->bit_number & 7; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/bitstream.h ================================================ #ifndef BITSTREAM_H #define BITSTREAM_H #include "mpeg3demux.h" // next bit in forward direction // next bit in reverse direction | // v v // | | | | | | | | | | | | | | | | | | | | | | | | | | |1|1|1|1|1|1| */ // ^ ^ // | bit_number = 1 // bfr_size = 6 typedef struct { unsigned MPEG3_INT32 bfr; /* bfr = buffer for bits */ int bit_number; /* position of pointer in bfr */ int bfr_size; /* number of bits in bfr. Should always be a multiple of 8 */ void *file; /* Mpeg2 file */ mpeg3_demuxer_t *demuxer; /* Mpeg2 demuxer */ /* If the input ptr is true, data is read from it instead of the demuxer. */ unsigned char *input_ptr; } mpeg3_bits_t; unsigned int mpeg3demux_read_char_packet(mpeg3_demuxer_t *demuxer); unsigned int mpeg3demux_read_prev_char_packet(mpeg3_demuxer_t *demuxer); /* ======================================================================== */ /* Entry Points */ /* ======================================================================== */ #define mpeg3bits_tell_percentage(stream) mpeg3demux_tell_percentage((stream)->demuxer) #define mpeg3bits_packet_time(stream) mpeg3demux_current_time((stream)->demuxer) #define mpeg3bits_time_offset(stream) mepg2demux_time_offset((stream)->demuxer) #define mpeg3bits_error(stream) mpeg3demux_error((stream)->demuxer) #define mpeg3bits_eof(stream) mpeg3demux_eof((stream)->demuxer) #define mpeg3bits_bof(stream) mpeg3demux_bof((stream)->demuxer) /* Read bytes backward from the file until the reverse_bits is full. */ static inline void mpeg3bits_fill_reverse_bits(mpeg3_bits_t* stream, int bits) { // Right justify while(stream->bit_number > 7) { stream->bfr >>= 8; stream->bfr_size -= 8; stream->bit_number -= 8; } // Insert bytes before bfr_size while(stream->bfr_size - stream->bit_number < bits) { if(stream->input_ptr) stream->bfr |= (unsigned int)(*--stream->input_ptr) << stream->bfr_size; else stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << stream->bfr_size; stream->bfr_size += 8; } } /* Read bytes forward from the file until the forward_bits is full. */ static inline void mpeg3bits_fill_bits(mpeg3_bits_t* stream, int bits) { while(stream->bit_number < bits) { stream->bfr <<= 8; if(stream->input_ptr) { stream->bfr |= *stream->input_ptr++; } else { stream->bfr |= mpeg3demux_read_char(stream->demuxer); } stream->bit_number += 8; stream->bfr_size += 8; if(stream->bfr_size > 32) stream->bfr_size = 32; } } /* Return 8 bits, advancing the file position. */ static inline unsigned int mpeg3bits_getbyte_noptr(mpeg3_bits_t* stream) { if(stream->bit_number < 8) { stream->bfr <<= 8; if(stream->input_ptr) stream->bfr |= *stream->input_ptr++; else stream->bfr |= mpeg3demux_read_char(stream->demuxer); stream->bfr_size += 8; if(stream->bfr_size > 32) stream->bfr_size = 32; return (stream->bfr >> stream->bit_number) & 0xff; } return (stream->bfr >> (stream->bit_number -= 8)) & 0xff; } static inline unsigned int mpeg3bits_getbit_noptr(mpeg3_bits_t* stream) { if(!stream->bit_number) { stream->bfr <<= 8; stream->bfr |= mpeg3demux_read_char(stream->demuxer); stream->bfr_size += 8; if(stream->bfr_size > 32) stream->bfr_size = 32; stream->bit_number = 7; return (stream->bfr >> 7) & 0x1; } return (stream->bfr >> (--stream->bit_number)) & (0x1); } /* Return n number of bits, advancing the file position. */ /* Use in place of flushbits */ static inline unsigned int mpeg3bits_getbits(mpeg3_bits_t* stream, int bits) { if(bits <= 0) return 0; mpeg3bits_fill_bits(stream, bits); return (stream->bfr >> (stream->bit_number -= bits)) & (0xffffffff >> (32 - bits)); } static inline unsigned int mpeg3bits_showbits24_noptr(mpeg3_bits_t* stream) { while(stream->bit_number < 24) { stream->bfr <<= 8; stream->bfr |= mpeg3demux_read_char(stream->demuxer); stream->bit_number += 8; stream->bfr_size += 8; if(stream->bfr_size > 32) stream->bfr_size = 32; } return (stream->bfr >> (stream->bit_number - 24)) & 0xffffff; } static inline unsigned int mpeg3bits_showbits32_noptr(mpeg3_bits_t* stream) { while(stream->bit_number < 32) { stream->bfr <<= 8; stream->bfr |= mpeg3demux_read_char(stream->demuxer); stream->bit_number += 8; stream->bfr_size += 8; if(stream->bfr_size > 32) stream->bfr_size = 32; } return stream->bfr; } static inline unsigned int mpeg3bits_showbits(mpeg3_bits_t* stream, int bits) { mpeg3bits_fill_bits(stream, bits); return (stream->bfr >> (stream->bit_number - bits)) & (0xffffffff >> (32 - bits)); } static inline unsigned int mpeg3bits_getbits_reverse(mpeg3_bits_t* stream, int bits) { unsigned int result; mpeg3bits_fill_reverse_bits(stream, bits); result = (stream->bfr >> stream->bit_number) & (0xffffffff >> (32 - bits)); stream->bit_number += bits; return result; } static inline unsigned int mpeg3bits_showbits_reverse(mpeg3_bits_t* stream, int bits) { unsigned int result; mpeg3bits_fill_reverse_bits(stream, bits); result = (stream->bfr >> stream->bit_number) & (0xffffffff >> (32 - bits)); return result; } #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/changesForSqueak.c ================================================ /**************************************************************************** * PROJECT: Changes for Squeak * FILE: changesForSqueak.c * CONTENT: * * AUTHOR: John McIntosh, and others. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: changesForSqueak.c 506 2003-02-08 18:23:30Z johnmci $ * * NOTES: See change log below. * 12/27/2001 JMM added support to build as a OS-X Bundle, a bit werid because its a mixture of unix and mac OS *****************************************************************************/ /* Squeak on MPEG by John M McIntosh johnmci#smalltalkconsulting.com Sept 2000 For the macintosh I've 1) coded up #ifdef for TARGET_OS_MAC 2) Coded around the pthreads 3) ignored most of mpeg3io_device 4) some changes to make CodeWarrior 5 happy In General 1) Added some casts 2) had some problems with Mpeg3_stream_coeffs_t 3) coded up memoryAllocate/memoryFree versus malloc/cmalloc/free 4) created a mpeg3_generate_toc_for_Squeak 5) Ignore perror */ // Nov 2nd, 2000 JMM changed memoryAllocate, use calloc // Sept 7nd, 2001 JMM added carbon logic // May 31st, 2002 JMM a few additions to make it compile on the mac with latest code #include #include "mpeg3private.h" #include "changesForSqueak.h" #if defined(TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ ) #include #include #include "sq.h" #endif #ifdef WIN32 #include #endif mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id); mpeg3_title_t* mpeg3_new_title(mpeg3_t *file, char *path); mpeg3demux_timecode_t* mpeg3_append_timecode(mpeg3_demuxer_t *demuxer, mpeg3_title_t *title, long prev_byte, double prev_time, long next_byte, double next_time, int dont_store); void appendStringToBufferIfPossible(char *buffer,char *append,int bufferSize); static long counter = 0; void * memoryAllocate(int number,unsigned size) { void * stuff; #if defined(TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ ) #if TARGET_API_MAC_CARBON stuff = (void *) NewPtrClear(size*number); #else stuff = (void *) NewPtrSysClear(size*number); #endif // if (stuff == nil) Debugger(); #else stuff = (void *) calloc(size,number); #endif counter++; return stuff; } void memoryFree(void *stuff) { counter--; #if defined(TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ ) DisposePtr((char *)stuff); #else free(stuff); #endif } #if (defined(TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ )) || defined(WIN32) #define NEEDSTRFUNCS #endif #ifdef NEEDSTRFUNCS void perror(const char * string) { } int strncasecmp(const char *str1, const char *str2, size_t nchars); int strcasecmp (const char *str1, const char *str2); int strncasecmp(const char *s1, const char *s2, size_t len) { /* Return true if the two strings are the same, not considering case. */ int i, c1, c2; for (i = 0; i < len; i++) { c1 = s1[i]; c2 = s2[i]; if ((c1 >= 'a') && (c1 <= 'z')) { c1 = c1 - ('a' - 'A'); } if ((c2 >= 'a') && (c2 <= 'z')) { c2 = c2 - ('a' - 'A'); } if (c1 != c2) return 0; } return 1; } int strcasecmp (const char *str1, const char *str2) { if (strlen(str1) != strlen(str2)) return 0; return strncasecmp(str1,str2,strlen(str1)); } #endif #ifdef WIN32 int bzero(char* block, long size) { ZeroMemory(block,size); } #endif #if defined(TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ ) int bzero(char *block,long size) { BlockZero(block,size); } int main () { } #endif #if defined(TARGET_OS_MAC) && defined ( __APPLE__ ) && defined ( __MACH__ ) int isSystem9_0_or_better(void) { return 1; } #endif void appendStringToBufferIfPossible(char *buffer,char *append,int bufferSize) { if (strlen(append) + strlen(buffer) < bufferSize) strcat(buffer,append); } int mpeg3_generate_toc_for_Squeak(mpeg3_t *file, int timecode_search, int print_streams, char *buffer, int bufferSize) { mpeg3_demuxer_t *demuxer; int i; char temp_buffer[256]; if(file) { buffer[0] = 0x00; demuxer = mpeg3_new_demuxer(file, 0, 0, -1); mpeg3demux_create_title_for_Squeak(demuxer, timecode_search, buffer, bufferSize); /* Just print the first title's streams */ if(print_streams) mpeg3demux_print_streams_for_Squeak(demuxer, buffer,bufferSize); sprintf(temp_buffer, "SIZE: %ld\n", demuxer->titles[demuxer->current_title]->total_bytes); appendStringToBufferIfPossible(buffer,temp_buffer,bufferSize); sprintf(temp_buffer, "PACKETSIZE: %ld\n", demuxer->packet_size); appendStringToBufferIfPossible(buffer,temp_buffer,bufferSize); mpeg3demux_print_timecodes(demuxer->titles[demuxer->current_title], buffer); mpeg3_delete_demuxer(demuxer); return 0; } return 1; } /* Create a title. */ /* Build a table of timecodes contained in the program stream. */ /* If toc is 0 just read the first and last timecode. */ int mpeg3demux_create_title_for_Squeak(mpeg3_demuxer_t *demuxer, int timecode_search, char *buffer,int buffer_size) { int result = 0, done = 0, counter_start, counter; mpeg3_t *file = (mpeg3_t *) demuxer->file; long next_byte=0, prev_byte=0; double next_time, prev_time, absolute_time; long i; mpeg3_title_t *title; unsigned long test_header = 0; mpeg3demux_timecode_t *timecode = 0; char temp_buffer[256]; demuxer->error_flag = 0; demuxer->generating_timecode = 1; /* Create a single title */ if(!demuxer->total_titles) { demuxer->titles[0] = mpeg3_new_title(file, file->fs->path); demuxer->total_titles = 1; mpeg3demux_open_title(demuxer, 0); } title = demuxer->titles[0]; title->total_bytes = mpeg3io_total_bytes(title->fs); /* Get the packet size from the file */ if(file->is_program_stream) { mpeg3io_seek(title->fs, 4); for(i = 0; i < MPEG3_MAX_PACKSIZE && test_header != MPEG3_PACK_START_CODE; i++) { test_header <<= 8; test_header |= mpeg3io_read_char(title->fs); } if(i < MPEG3_MAX_PACKSIZE) demuxer->packet_size = i; mpeg3io_seek(title->fs, 0); } else demuxer->packet_size = file->packet_size; /* Get timecodes for the title */ if(file->is_transport_stream || file->is_program_stream) { mpeg3io_seek(title->fs, 0); while(!done && !result && !mpeg3io_eof(title->fs)) { next_byte = mpeg3io_tell(title->fs); result = mpeg3_read_next_packet(demuxer); if(!result) { next_time = demuxer->time; sprintf(temp_buffer,"%f %f\n", next_time, prev_time); appendStringToBufferIfPossible(buffer,temp_buffer,buffer_size); if(next_time < prev_time || next_time - prev_time > MPEG3_CONTIGUOUS_THRESHOLD || !title->timecode_table_size) { /* Discontinuous */ timecode = mpeg3_append_timecode(demuxer, title, prev_byte, prev_time, next_byte, next_time, 0); sprintf(temp_buffer,"timecode: %ld %ld %f %f\n", timecode->start_byte, timecode->end_byte, timecode->start_time, timecode->end_time); appendStringToBufferIfPossible(buffer,temp_buffer,buffer_size); counter_start = next_time; } prev_time = next_time; prev_byte = next_byte; counter = next_time; } /* Just get the first bytes if not building a toc to get the stream ID's. */ if(next_byte > 0x100000 && (!timecode_search || !buffer)) done = 1; } /* Get the last timecode */ if(!buffer || !timecode_search) { result = mpeg3io_seek(title->fs, title->total_bytes); if(!result) result = mpeg3_read_prev_packet(demuxer); } if(title->timecode_table && timecode) { timecode->end_byte = title->total_bytes; // timecode->end_byte = mpeg3io_tell(title->fs)/* + demuxer->packet_size */; timecode->end_time = demuxer->time; timecode->absolute_end_time = timecode->end_time - timecode->start_time; } } mpeg3io_seek(title->fs, 0); demuxer->generating_timecode = 0; return 0; } int mpeg3demux_print_streams_for_Squeak(mpeg3_demuxer_t *demuxer, char *buffer,int buffer_size) { int i; char temp_buffer[256]; /* Print the stream information */ for(i = 0; i < MPEG3_MAX_STREAMS; i++) { if(demuxer->astream_table[i]) { sprintf(temp_buffer, "ASTREAM: %d %d\n", i, demuxer->astream_table[i]); appendStringToBufferIfPossible(buffer,temp_buffer,buffer_size); } if(demuxer->vstream_table[i]) { sprintf(temp_buffer, "VSTREAM: %d %d\n", i, demuxer->vstream_table[i]); appendStringToBufferIfPossible(buffer,temp_buffer,buffer_size); } } return 0; } mpeg3_css_t* mpeg3_new_css() { return 0; } int mpeg3_delete_css(mpeg3_css_t *css) { return 0; } int mpeg3_get_keys(mpeg3_css_t *css, char *path) { return 1; } int mpeg3_decrypt_packet(mpeg3_css_t *css, unsigned char *sector) { return 1; } /*** System Attributes ***/ int IsImageName(char *name) { char *suffix; suffix = strrchr(name, '.'); /* pointer to last period in name */ if (suffix == NULL) return 0; if (strcmp(suffix, ".ima") == 0) return 1; if (strcmp(suffix, ".image") == 0) return 1; if (strcmp(suffix, ".IMA") == 0) return 1; if (strcmp(suffix, ".IMAGE") == 0) return 1; return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/changesForSqueak.h ================================================ #include "mpeg3private.h" int mpeg3_generate_toc_for_Squeak(mpeg3_t *file, int timecode_search, int print_streams, char *buffer, int buffer_size); void * memoryAllocate(int number,unsigned size); void memoryFree(void *stuff); ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/configure ================================================ #!/bin/sh USE_MMX=1 for ac_option do case "$ac_option" in --no-mmx) USE_MMX=0 ;; -h | --help | -help) cat << EOF Options: --no-mmx Compile libmpeg3 with no MMX support. EOF exit 0 ;; *) ;; esac done echo "Configuring libmpeg3" cat > global_config << EOF # DO NOT EDIT. EDIT ./configure INSTEAD AND RERUN IT. EOF if test -z "$CFLAGS"; then echo >> global_config "CFLAGS = -O3 -funroll-loops -fomit-frame-pointer -I. -Ivideo -Iaudio" # echo >> global_config "CFLAGS = -g -I. -Ivideo -Iaudio" fi cat >> global_config << EOF CC = gcc NASM = nasm EOF if [ ${USE_MMX} = 1 ]; then cat >> global_config << EOF CFLAGS += -DHAVE_MMX MMXOBJS = \ video/mmxidct.o \ video/reconmmx.o MMXOBJS2 = \ mmxidct.o \ reconmmx.o EOF fi echo "done" ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/dump.c ================================================ #include "libmpeg3.h" #include #include #include #include #include #include #include #include #include #include #include #include #include void * memoryAllocate(int number,unsigned size); void memoryFree(void *stuff); int strncasecmp(const char *str1, const char *str2, size_t nchars); int strcasecmp (const char *str1, const char *str2); inline BitMap * GetPortBitMapForCopyBits (CGrafPtr w) { return &((GrafPtr)w)->portBits;} inline Rect *GetPortBounds(CGrafPtr w,Rect *r) { *r = w->portRect; return &w->portRect;} void mpeg3video_init_scantables(mpeg3video_t *video); WindowPtr pWindow; GWorldPtr gpGWOffScreen = NULL; long counter = 0; #define BUFSIZE 1000000 int main2(); int main () { int ret; Rect windRect; long start,end,amount; /* Initialize all the needed managers. */ InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); //ProfilerInit(collectDetailed, bestTimeBase, 1000, 50); //ProfilerSetStatus(true); windRect = qd.screenBits.bounds; InsetRect(&windRect, 50, 50); pWindow = NewCWindow(nil, &windRect, "\pMpeg", true, documentProc, (WindowPtr) -1, false, 0); start = TickCount(); main2(); end = TickCount(); amount = end - start; fprintf(stderr, "Time taken %d memoryAllocator %d \n", amount,counter); // ProfilerDump("\pProfile.out"); do { } while (!Button()); } int main2() { mpeg3_t *file; int i, result = 0; unsigned char *output, **output_rows; float *audio_output_f; short *audio_output_i; long total_samples = 0; Rect sourceRect; OSErr error; PixMapHandle hPixmap; Ptr gBaseLocation; long targetRowBytes; file = mpeg3_open("randomAlien.mpg"); if(file) { mpeg3_set_cpus(file, 1); //audio_output_f = (float *) memoryAllocate(1,BUFSIZE * sizeof(float)); //audio_output_i = (short *) memoryAllocate(1,BUFSIZE * sizeof(short)); //mpeg3_set_sample(file, 11229518, 0); //result = mpeg3_read_audio(file, audio_output_f, 0, 0, BUFSIZE, 0); // result = mpeg3_read_audio(file, 0, audio_output_i, 1, BUFSIZE, 0); // fwrite(audio_output_i, BUFSIZE, 1, stdout); //mpeg3_set_frame(file, 1000, 0); sourceRect.top = 0; sourceRect.left = 0; sourceRect.bottom = mpeg3_video_height(file, 0); sourceRect.right = mpeg3_video_width(file, 0); error = NewGWorld (&gpGWOffScreen, 32, &sourceRect, NULL, NULL, keepLocal); if (error != noErr) { DebugStr ("\pUnable to allocate off screen image"); } hPixmap = GetGWorldPixMap (gpGWOffScreen); error = LockPixels (hPixmap); gBaseLocation = GetPixBaseAddr(hPixmap); targetRowBytes = ((**hPixmap).rowBytes & 0x3FFF)/4; output_rows = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * mpeg3_video_height(file, 0)); for(i = 0; i < mpeg3_video_height(file, 0); i++) output_rows[i] = (unsigned char*) gBaseLocation + i * targetRowBytes*4; for (i=0;i < mpeg3_video_frames(file, 0);i++) { result = mpeg3_read_frame(file, output_rows, 0, 0, mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), MPEG3_RGBAF8888, 0); CopyBits (GetPortBitMapForCopyBits(gpGWOffScreen), GetPortBitMapForCopyBits(GetWindowPort(pWindow)), &sourceRect, &sourceRect, srcCopy, NULL); } UnlockPixels (hPixmap); DisposeGWorld(gpGWOffScreen); memoryFree(output_rows); fprintf(stderr, "Audio streams: %d\n", mpeg3_total_astreams(file)); for(i = 0; i < mpeg3_total_astreams(file); i++) { fprintf(stderr, " Stream %d: channels %d sample rate %d total samples %ld\n", i, mpeg3_audio_channels(file, i), mpeg3_sample_rate(file, i), mpeg3_audio_samples(file, i)); } fprintf(stderr, "Video streams: %d\n", mpeg3_total_vstreams(file)); for(i = 0; i < mpeg3_total_vstreams(file); i++) { fprintf(stderr, " Stream %d: width %d height %d frame rate %0.3f total frames %ld\n", i, mpeg3_video_width(file, i), mpeg3_video_height(file, i), mpeg3_frame_rate(file, i), mpeg3_video_frames(file, i)); } mpeg3_close(file); } return 0; } int strncasecmp(const char *str1, const char *str2, size_t nchars) { return strncmp(str1,str2,nchars); } int strcasecmp (const char *str1, const char *str2) { return strcmp(str1,str2); } void * memoryAllocate(int number,unsigned size) { char * stuff; stuff = NewPtrClear(size*number); if (stuff == 0L) Debugger(); counter ++; return stuff; } void memoryFree(void *stuff) { counter --; DisposePtr((char *)stuff); } int bzero(char *block,long size) { BlockZero(block,size); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/dump2.c ================================================ #include "libmpeg3.h" #include #define BUFSIZE 10000000 int main(int argc, char *argv[]) { mpeg3_t *file; int i, result = 0; unsigned char *output, **output_rows; float *audio_output_f; short *audio_output_i; long total_samples = 0; if(argc < 2) { printf("Need an MPEG stream.\n"); exit(1); } file = mpeg3_open(argv[1]); if(file) { fprintf(stderr, "MMX supported %d\n", file->have_mmx); fprintf(stderr, "Audio streams: %d\n", mpeg3_total_astreams(file)); for(i = 0; i < mpeg3_total_astreams(file); i++) { fprintf(stderr, " Stream %d: channels %d sample rate %d total samples %ld\n", i, mpeg3_audio_channels(file, i), mpeg3_sample_rate(file, i), mpeg3_audio_samples(file, i)); } fprintf(stderr, "Video streams: %d\n", mpeg3_total_vstreams(file)); for(i = 0; i < mpeg3_total_vstreams(file); i++) { fprintf(stderr, " Stream %d: width %d height %d frame rate %0.3f total frames %ld\n", i, mpeg3_video_width(file, i), mpeg3_video_height(file, i), mpeg3_frame_rate(file, i), mpeg3_video_frames(file, i)); } mpeg3_set_cpus(file, 1); /* audio_output_f = malloc(BUFSIZE * sizeof(float)); */ audio_output_i = malloc(BUFSIZE * sizeof(short)); /* mpeg3_set_sample(file, 11229518, 0); */ /* result = mpeg3_read_audio(file, audio_output_f, 0, 0, BUFSIZE, 0); */ // result = mpeg3_read_audio(file, 0, audio_output_i, 1, BUFSIZE, 0); fwrite(audio_output_i, BUFSIZE, 1, stdout); output = malloc(mpeg3_video_width(file, 0) * mpeg3_video_height(file, 0) * 3 + 4); output_rows = malloc(sizeof(unsigned char*) * mpeg3_video_height(file, 0)); for(i = 0; i < mpeg3_video_height(file, 0); i++) output_rows[i] = &output[i * mpeg3_video_width(file, 0) * 3]; // mpeg3_set_frame(file, 1000, 0); result = mpeg3_read_frame(file, output_rows, 0, 0, mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), MPEG3_RGB888, 0); mpeg3_close(file); } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/global_config ================================================ # DO NOT EDIT. EDIT ./configure INSTEAD AND RERUN IT. CFLAGS = -O3 -funroll-loops -fomit-frame-pointer -I. -Ivideo -Iaudio CC = gcc NASM = nasm CFLAGS += -DHAVE_MMX MMXOBJS = video/mmxidct.o video/reconmmx.o MMXOBJS2 = mmxidct.o reconmmx.o ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/ioctl.h ================================================ /* sys/ioctl.h */ #ifndef _SYS_IOCTL_H #define _SYS_IOCTL_H #include /* /dev/windows ioctls */ #define WINDOWS_POST 0 /* Set write() behavior to PostMessage() */ #define WINDOWS_SEND 1 /* Set write() behavior to SendMessage() */ #define WINDOWS_HWND 2 /* Set hWnd for read() calls */ __BEGIN_DECLS int ioctl (int __fd, int __cmd, void *); __END_DECLS #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/libmpeg3.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak Changed Dec 3rd 2001 by John M McIntosh to ignore extents on file names */ #include "libmpeg3.h" #include "mpeg3protos.h" #include #include #define MAX(a, b) ((a) > (b) ? (a) : (b)) mpeg3_t* mpeg3_new(char *path,int size) { int i; mpeg3_t *file = (mpeg3_t *) memoryAllocate(1, sizeof(mpeg3_t)); file->cpus = 1; file->fs = mpeg3_new_fs(path,size); file->have_mmx = mpeg3_mmx_test(); file->demuxer = mpeg3_new_demuxer(file, 0, 0, -1); return file; } int mpeg3_delete(mpeg3_t *file) { int i; for(i = 0; i < file->total_vstreams; i++) mpeg3_delete_vtrack(file, file->vtrack[i]); for(i = 0; i < file->total_astreams; i++) mpeg3_delete_atrack(file, file->atrack[i]); mpeg3_delete_fs(file->fs); mpeg3_delete_demuxer(file->demuxer); memoryFree(file); } int mpeg3_check_sig(char *path) { mpeg3_fs_t *fs; unsigned int bits; char *ext; int result = 0; fs = mpeg3_new_fs(path,0); if(mpeg3io_open_file(fs)) { /* File not found */ return 0; } bits = mpeg3io_read_int32(fs); /* Test header */ if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) { result = 1; } else if((((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) || (bits == MPEG3_PACK_START_CODE) || ((bits & 0xfff00000) == 0xfff00000) || (bits == MPEG3_SEQUENCE_START_CODE) || (bits == MPEG3_PICTURE_START_CODE) || /*JMM (((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) || */ ((bits >> 8) == MPEG3_ID3_PREFIX) || (bits == MPEG3_RIFF_CODE)) { result = 1; /* JMM Don't want extends, too ugly ext = strrchr(path, '.'); if(ext) { /* Test file extension. if(strncasecmp(ext, ".mp2", 4) && strncasecmp(ext, ".mp3", 4) && strncasecmp(ext, ".m1v", 4) && strncasecmp(ext, ".m2v", 4) && strncasecmp(ext, ".m2s", 4) && strncasecmp(ext, ".mpg", 4) && strncasecmp(ext, ".vob", 4) && strncasecmp(ext, ".mpeg", 4) /* JMM && strncasecmp(ext, ".ac3", 4) ) result = 0; } */ } mpeg3io_close_file(fs); mpeg3_delete_fs(fs); return result; } mpeg3_t* mpeg3_open_copy(char *path, mpeg3_t *old_file,int size) { mpeg3_t *file = 0; unsigned int bits; int i, done; /* Initialize the file structure */ file = mpeg3_new(path,size); /* Need to perform authentication before reading a single byte. */ if(mpeg3io_open_file(file->fs)) { mpeg3_delete(file); return 0; } /* =============================== Create the title objects ========================= */ bits = mpeg3io_read_int32(file->fs); if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) /* TOCV */ { /* Table of contents for another file */ if(mpeg3_read_toc(file)) { mpeg3_delete(file); return 0; } mpeg3io_close_file(file->fs); } else if(((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) { /* Transport stream */ file->packet_size = MPEG3_TS_PACKET_SIZE; file->is_transport_stream = 1; } else if(bits == MPEG3_PACK_START_CODE) { /* Program stream */ file->packet_size = MPEG3_DVD_PACKET_SIZE; file->is_program_stream = 1; } else if((bits & 0xfff00000) == 0xfff00000 || ((bits >> 8) == MPEG3_ID3_PREFIX) || (bits == MPEG3_RIFF_CODE)) { /* MPEG Audio only */ file->packet_size = MPEG3_DVD_PACKET_SIZE; file->has_audio = 1; file->is_audio_stream = 1; } else if(bits == MPEG3_SEQUENCE_START_CODE || bits == MPEG3_PICTURE_START_CODE) { /* Video only */ file->packet_size = MPEG3_DVD_PACKET_SIZE; file->is_video_stream = 1; } else if(((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) { /* AC3 Audio only */ file->packet_size = MPEG3_DVD_PACKET_SIZE; file->has_audio = 1; file->is_audio_stream = 1; } else { /* file->packet_size = MPEG3_DVD_PACKET_SIZE; */ /* file->is_audio_stream = 1; */ mpeg3_delete(file); fprintf(stderr, "mpeg3_open: not an MPEG 2 stream\n"); return 0; } /* Create title */ /* Copy timecodes from an old demuxer */ if(old_file && mpeg3_get_demuxer(old_file)) { mpeg3demux_copy_titles(file->demuxer, mpeg3_get_demuxer(old_file)); } else /* Start from scratch */ if(!file->demuxer->total_titles) { mpeg3demux_create_title(file->demuxer, 0, 0); } /* =============================== Get title information ========================= */ if(file->is_transport_stream || file->is_program_stream) { /* Create video tracks */ /* Video must be created before audio because audio uses the video timecode */ /* to get its length. */ for(i = 0; i < MPEG3_MAX_STREAMS; i++) { if(file->demuxer->vstream_table[i]) { file->vtrack[file->total_vstreams] = mpeg3_new_vtrack(file, i, file->demuxer); if(file->vtrack[file->total_vstreams]) file->total_vstreams++; } } /* Create audio tracks */ for(i = 0; i < MPEG3_MAX_STREAMS; i++) { if(file->demuxer->astream_table[i]) { file->atrack[file->total_astreams] = mpeg3_new_atrack(file, i, file->demuxer->astream_table[i], file->demuxer); if(file->atrack[file->total_astreams]) file->total_astreams++; } } } else if(file->is_video_stream) { /* Create video tracks */ file->vtrack[0] = mpeg3_new_vtrack(file, -1, file->demuxer); if(file->vtrack[0]) file->total_vstreams++; } else if(file->is_audio_stream) { /* Create audio tracks */ file->atrack[0] = mpeg3_new_atrack(file, -1, AUDIO_UNKNOWN, file->demuxer); if(file->atrack[0]) file->total_astreams++; } if(file->total_vstreams) file->has_video = 1; if(file->total_astreams) file->has_audio = 1; mpeg3io_close_file(file->fs); return file; } mpeg3_t* mpeg3_open(char *path,int size) { return mpeg3_open_copy(path, 0,size); } int mpeg3_close(mpeg3_t *file) { /* File is closed in the same procedure it is opened in. */ mpeg3_delete(file); return 0; } int mpeg3_set_cpus(mpeg3_t *file, int cpus) { int i; file->cpus = cpus; for(i = 0; i < file->total_vstreams; i++) mpeg3video_set_cpus(file->vtrack[i]->video, cpus); return 0; } int mpeg3_set_mmx(mpeg3_t *file, int use_mmx) { int i; file->have_mmx = use_mmx; for(i = 0; i < file->total_vstreams; i++) mpeg3video_set_mmx(file->vtrack[i]->video, use_mmx); return 0; } int mpeg3_generate_toc(FILE *output, char *path, int timecode_search, int print_streams) { mpeg3_t *file = mpeg3_open(path,0); mpeg3_demuxer_t *demuxer; int i; if(file) { fprintf(output, "TOCVERSION 2\n" "PATH: %s\n", path); demuxer = mpeg3_new_demuxer(file, 0, 0, -1); mpeg3demux_create_title(demuxer, timecode_search, output); /* Just print the first title's streams */ if(print_streams) mpeg3demux_print_streams(demuxer, output); fprintf(output, "SIZE: %ld\n", demuxer->titles[demuxer->current_title]->total_bytes); fprintf(output, "PACKETSIZE: %ld\n", demuxer->packet_size); mpeg3demux_print_timecodes(demuxer->titles[demuxer->current_title], output); mpeg3_delete_demuxer(demuxer); mpeg3_close(file); return 0; } return 1; } int mpeg3_read_toc(mpeg3_t *file) { char string[MPEG3_STRLEN]; int number1; /* Test version number */ file->is_program_stream = 1; mpeg3io_seek(file->fs, 0); // fscanf(file->fs->fd, "%s %d", string, &number1); // Jan 20th 2006, John M Mcintosh (johnmci@smalltalkconsulting.com move logic to mpeg3io.c mpeg3io_scanf(file->fs,"%s %d",string,&number1); if(number1 > 2 || number1 < 2) return 1; /* Read titles */ mpeg3demux_read_titles(file->demuxer); return 0; } int mpeg3_has_audio(mpeg3_t *file) { return file->has_audio; } int mpeg3_total_astreams(mpeg3_t *file) { return file->total_astreams; } int mpeg3_audio_channels(mpeg3_t *file, int stream) { if(file->has_audio) return file->atrack[stream]->channels; return -1; } int mpeg3_sample_rate(mpeg3_t *file, int stream) { if(file->has_audio) return file->atrack[stream]->sample_rate; return -1; } long mpeg3_get_sample(mpeg3_t *file, int stream) { if(file->has_audio) return file->atrack[stream]->current_position; return -1; } int mpeg3_set_sample(mpeg3_t *file, long sample, int stream) { if(file->has_audio) { file->atrack[stream]->current_position = sample; mpeg3audio_seek_sample(file->atrack[stream]->audio, sample); return 0; } return -1; } long mpeg3_audio_samples(mpeg3_t *file, int stream) { if(file->has_audio) return file->atrack[stream]->total_samples; return -1; } int mpeg3_has_video(mpeg3_t *file) { return file->has_video; } int mpeg3_total_vstreams(mpeg3_t *file) { return file->total_vstreams; } int mpeg3_video_width(mpeg3_t *file, int stream) { if(file->has_video) return file->vtrack[stream]->width; return -1; } int mpeg3_video_height(mpeg3_t *file, int stream) { if(file->has_video) return file->vtrack[stream]->height; return -1; } float mpeg3_frame_rate(mpeg3_t *file, int stream) { if(file->has_video) return file->vtrack[stream]->frame_rate; return -1; } long mpeg3_video_frames(mpeg3_t *file, int stream) { if(file->has_video) return file->vtrack[stream]->total_frames; return -1; } long mpeg3_get_frame(mpeg3_t *file, int stream) { if(file->has_video) return file->vtrack[stream]->current_position; return -1; } int mpeg3_set_frame(mpeg3_t *file, long frame, int stream) { if(file->has_video) { file->vtrack[stream]->current_position = frame; mpeg3video_seek_frame(file->vtrack[stream]->video, frame); return 0; } return -1; } int mpeg3_seek_percentage(mpeg3_t *file, double percentage) { int i; for(i = 0; i < file->total_astreams; i++) { mpeg3audio_seek_percentage(file->atrack[i]->audio, percentage); } for(i = 0; i < file->total_vstreams; i++) { mpeg3video_seek_percentage(file->vtrack[i]->video, percentage); } return 0; } int mpeg3_previous_frame(mpeg3_t *file, int stream) { file->last_type_read = 2; file->last_stream_read = stream; if(file->has_video) return mpeg3video_previous_frame(file->vtrack[stream]->video); } double mpeg3_tell_percentage(mpeg3_t *file) { double percent = 0; if(file->last_type_read == 1) { percent = mpeg3demux_tell_percentage(file->atrack[file->last_stream_read]->demuxer); } if(file->last_type_read == 2) { percent = mpeg3demux_tell_percentage(file->vtrack[file->last_stream_read]->demuxer); } return percent; } double mpeg3_get_time(mpeg3_t *file) { double atime = 0, vtime = 0; if(file->is_transport_stream || file->is_program_stream) { /* Timecode only available in transport stream */ if(file->last_type_read == 1) { atime = mpeg3demux_get_time(file->atrack[file->last_stream_read]->demuxer); } else if(file->last_type_read == 2) { vtime = mpeg3demux_get_time(file->vtrack[file->last_stream_read]->demuxer); } } else { /* Use percentage and total time */ if(file->has_audio) { atime = mpeg3demux_tell_percentage(file->atrack[0]->demuxer) * mpeg3_audio_samples(file, 0) / mpeg3_sample_rate(file, 0); } if(file->has_video) { vtime = mpeg3demux_tell_percentage(file->vtrack[0]->demuxer) * mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0); } } return MAX(atime, vtime); } int mpeg3_end_of_audio(mpeg3_t *file, int stream) { int result = 0; result = mpeg3demux_eof(file->atrack[stream]->demuxer); return result; } int mpeg3_end_of_video(mpeg3_t *file, int stream) { int result = 0; result = mpeg3demux_eof(file->vtrack[stream]->demuxer); return result; } int mpeg3_read_frame(mpeg3_t *file, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model, int stream) { int result = -1; if(file->has_video) { result = mpeg3video_read_frame(file->vtrack[stream]->video, file->vtrack[stream]->current_position, output_rows, in_x, in_y, in_w, in_h, out_w, out_h, color_model); file->last_type_read = 2; file->last_stream_read = stream; file->vtrack[stream]->current_position++; } return result; } int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream) { int result = -1; if(file->has_video) { result = mpeg3video_drop_frames(file->vtrack[stream]->video, frames); if(frames > 0) file->vtrack[stream]->current_position += frames; file->last_type_read = 2; file->last_stream_read = stream; } return result; } int mpeg3_read_yuvframe(mpeg3_t *file, char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream) { int result = -1; //printf("mpeg3_read_yuvframe 1 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); if(file->has_video) { result = mpeg3video_read_yuvframe(file->vtrack[stream]->video, file->vtrack[stream]->current_position, y_output, u_output, v_output, in_x, in_y, in_w, in_h); file->last_type_read = 2; file->last_stream_read = stream; file->vtrack[stream]->current_position++; } //printf("mpeg3_read_yuvframe 2 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); return result; } int mpeg3_read_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) { int result = -1; //printf("mpeg3_read_audio 1 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); if(file->has_audio) { result = mpeg3audio_decode_audio(file->atrack[stream]->audio, output_f, output_i, channel, file->atrack[stream]->current_position, samples); file->last_type_read = 1; file->last_stream_read = stream; file->atrack[stream]->current_position += samples; } //printf("mpeg3_read_audio 2 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); return result; } int mpeg3_reread_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) { if(file->has_audio) { mpeg3_set_sample(file, file->atrack[stream]->current_position - samples, stream); file->last_type_read = 1; file->last_stream_read = stream; return mpeg3_read_audio(file, output_f, output_i, channel, samples, stream); } return -1; } int mpeg3_read_audio_chunk(mpeg3_t *file, unsigned char *output, long *size, long max_size, int stream) { int result = 0; if(file->has_audio) { result = mpeg3audio_read_raw(file->atrack[stream]->audio, output, size, max_size); file->last_type_read = 1; file->last_stream_read = stream; } return result; } int mpeg3_read_video_chunk(mpeg3_t *file, unsigned char *output, long *size, long max_size, int stream) { int result = 0; if(file->has_video) { result = mpeg3video_read_raw(file->vtrack[stream]->video, output, size, max_size); file->last_type_read = 2; file->last_stream_read = stream; } return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/libmpeg3.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef LIBMPEG3_H #define LIBMPEG3_H #ifdef __cplusplus extern "C" { #endif #include "mpeg3private.h" /* Supported color models for mpeg3_read_frame */ #define MPEG3_RGB565 2 #define MPEG3_RGB555 14 //JMM for mac #define MPEG3_RGBI555 16 //SVP for intel #define MPEG3_BGR888 0 #define MPEG3_BGRA8888 1 #define MPEG3_RGB888 3 #define MPEG3_RGBA8888 4 #define MPEG3_ARGB8888 13 //JMM for mac #define MPEG3_RGBA16161616 5 /* Color models for the 601 to RGB conversion */ /* 601 not implemented for scalar code */ #define MPEG3_601_RGB565 11 #define MPEG3_601_RGB555 15 //JMM for Squeak #define MPEG3_601_RGBI555 17 //SVP for intel #define MPEG3_601_BGR888 7 #define MPEG3_601_BGRA8888 8 #define MPEG3_601_RGB888 9 #define MPEG3_601_RGBA8888 10 #define MPEG3_601_ARGB8888 12 //JMM for Squeak /* Check for file compatibility. Return 1 if compatible. */ int mpeg3_check_sig(char *path); /* Open the MPEG3 stream. */ mpeg3_t* mpeg3_open(char *path,int size); /* Open the MPEG3 stream and copy the tables from an already open stream. */ /* Eliminates the initial timecode search. */ mpeg3_t* mpeg3_open_copy(char *path, mpeg3_t *old_file,int size); int mpeg3_close(mpeg3_t *file); /* Performance */ int mpeg3_set_cpus(mpeg3_t *file, int cpus); int mpeg3_set_mmx(mpeg3_t *file, int use_mmx); /* Query the MPEG3 stream about audio. */ int mpeg3_has_audio(mpeg3_t *file); int mpeg3_total_astreams(mpeg3_t *file); /* Number of multiplexed audio streams */ int mpeg3_audio_channels(mpeg3_t *file, int stream); int mpeg3_sample_rate(mpeg3_t *file, int stream); /* Total length obtained from the timecode. */ /* For DVD files, this is unreliable. */ long mpeg3_audio_samples(mpeg3_t *file, int stream); int mpeg3_set_sample(mpeg3_t *file, long sample, int stream); /* Seek to a sample */ long mpeg3_get_sample(mpeg3_t *file, int stream); /* Tell current position */ /* Read a PCM buffer of audio from 1 channel and advance the position. */ /* Return a 1 if error. */ /* Stream defines the number of the multiplexed stream to read. */ int mpeg3_read_audio(mpeg3_t *file, float *output_f, /* Pointer to pre-allocated buffer of floats */ short *output_i, /* Pointer to pre-allocated buffer of int16's */ int channel, /* Channel to decode */ long samples, /* Number of samples to decode */ int stream); /* Stream containing the channel */ /* Reread the last PCM buffer from a different channel and advance the position */ int mpeg3_reread_audio(mpeg3_t *file, float *output_f, /* Pointer to pre-allocated buffer of floats */ short *output_i, /* Pointer to pre-allocated buffer of int16's */ int channel, /* Channel to decode */ long samples, /* Number of samples to decode */ int stream); /* Stream containing the channel */ /* Read the next compressed audio chunk. Store the size in size and return a */ /* 1 if error. */ /* Stream defines the number of the multiplexed stream to read. */ int mpeg3_read_audio_chunk(mpeg3_t *file, unsigned char *output, long *size, long max_size, int stream); /* Query the stream about video. */ int mpeg3_has_video(mpeg3_t *file); int mpeg3_total_vstreams(mpeg3_t *file); /* Number of multiplexed video streams */ int mpeg3_video_width(mpeg3_t *file, int stream); int mpeg3_video_height(mpeg3_t *file, int stream); float mpeg3_frame_rate(mpeg3_t *file, int stream); /* Frames/sec */ /* Total length. */ /* For DVD files, this is 1 indicating only percentage seeking is available. */ long mpeg3_video_frames(mpeg3_t *file, int stream); int mpeg3_set_frame(mpeg3_t *file, long frame, int stream); /* Seek to a frame */ int mpeg3_skip_frames(); long mpeg3_get_frame(mpeg3_t *file, int stream); /* Tell current position */ /* Seek all the tracks based on a percentage of the total bytes in the */ /* file or the total */ /* time in a toc if one exists. Percentage is a 0 to 1 double. */ /* This eliminates the need for tocs and 64 bit longs but doesn't */ /* give frame accuracy. */ int mpeg3_seek_percentage(mpeg3_t *file, double percentage); double mpeg3_tell_percentage(mpeg3_t *file); int mpeg3_previous_frame(mpeg3_t *file, int stream); int mpeg3_end_of_audio(mpeg3_t *file, int stream); int mpeg3_end_of_video(mpeg3_t *file, int stream); /* Give the seconds time in the last packet read */ double mpeg3_get_time(mpeg3_t *file); /* Read a frame. The dimensions of the input area and output frame must be supplied. */ /* The frame is taken from the input area and scaled to fit the output frame in 1 step. */ /* Stream defines the number of the multiplexed stream to read. */ /* The last row of **output_rows must contain 4 extra bytes for scratch work. */ int mpeg3_read_frame(mpeg3_t *file, unsigned char **output_rows, /* Array of pointers to the start of each output row */ int in_x, /* Location in input frame to take picture */ int in_y, int in_w, int in_h, int out_w, /* Dimensions of output_rows */ int out_h, int color_model, /* One of the color model #defines */ int stream); /* Read a YUV frame. The 3 planes are copied into the y, u, and v buffers provided. */ /* The input is cropped to the dimensions given but not scaled. */ int mpeg3_read_yuvframe(mpeg3_t *file, char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h, int stream); int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream); /* Read the next compressed frame including headers. */ /* Store the size in size and return a 1 if error. */ /* Stream defines the number of the multiplexed stream to read. */ int mpeg3_read_video_chunk(mpeg3_t *file, unsigned char *output, long *size, long max_size, int stream); /* Master control */ int mpeg3_total_programs(); int mpeg3_set_program(int program); #ifdef __cplusplus } #endif #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/make_package ================================================ #!/bin/sh VERSION=1.2.1 rm -r /tmp/libmpeg3-$VERSION mkdir -p /tmp/libmpeg3-$VERSION make clean cp -rd * /tmp/libmpeg3-$VERSION cd /tmp tar zcf libmpeg3-$VERSION.tar.gz libmpeg3-$VERSION ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3atrack.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "libmpeg3.h" #include "mpeg3protos.h" #include mpeg3_atrack_t* mpeg3_new_atrack(mpeg3_t *file, int stream_id, int format, mpeg3_demuxer_t *demuxer) { mpeg3_atrack_t *new_atrack; new_atrack = (mpeg3_atrack_t *) memoryAllocate(1, sizeof(mpeg3_atrack_t)); new_atrack->channels = 0; new_atrack->sample_rate = 0; new_atrack->total_samples = 0; new_atrack->current_position = 0; new_atrack->demuxer = mpeg3_new_demuxer(file, 1, 0, stream_id); if(demuxer) mpeg3demux_copy_titles(new_atrack->demuxer, demuxer); new_atrack->audio = mpeg3audio_new(file, new_atrack, format); if(!new_atrack->audio) { /* Failed */ mpeg3_delete_atrack(file, new_atrack); new_atrack = 0; } return new_atrack; } int mpeg3_delete_atrack(mpeg3_t *file, mpeg3_atrack_t *atrack) { if(atrack->audio) mpeg3audio_delete(atrack->audio); if(atrack->demuxer) mpeg3_delete_demuxer(atrack->demuxer); memoryFree(atrack); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3atrack.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef MPEG3ATRACK_H #define MPEG3ATRACK_H #include "mpeg3demux.h" #include "mpeg3audio.h" typedef struct { int channels; int sample_rate; mpeg3_demuxer_t *demuxer; mpeg3audio_t *audio; long current_position; long total_samples; } mpeg3_atrack_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3cat.c ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak * * Concatenate elementary streams */ #include "libmpeg3.h" #include #include #include #define MPEG3_SEQUENCE_START_CODE 0x000001b3 #define BUFFER_SIZE 1000000 int main(int argc, char *argv[]) { char inpath[1024]; mpeg3_t *in; int current_file, current_output_file = 0, i; unsigned int bits; unsigned char *buffer; long output_size; int result = 0; long total_frames = 0; int do_audio = 0, do_video = 0; int stream = 0; if(argc < 2) { fprintf(stderr, "Concatenate elementary streams or demultiplex a program stream.\n" "Usage: mpeg3cat -[av0123456789] [infile...] > \n\n" "Example: Concatenate 2 video files: mpeg3cat xena1.m2v xena2.m2v > xena.m2v\n" " Extract audio stream 0: mpeg3cat -a0 xena.vob > war_cry.ac3\n"); exit(1); } for(i = 1; i < argc; i++) { if(argv[i][0] == '-') { if(argv[i][1] != 'a' && argv[i][1] != 'v') { fprintf(stderr, "invalid option %s\n", argv[i]); } else { if(argv[i][1] == 'a') do_audio = 1; else if(argv[i][1] == 'v') do_video = 1; if(argv[i][2] != 0) { stream = argv[i][2] - 48; } } } } buffer = (unsigned char *) malloc(BUFFER_SIZE); for(current_file = 1; current_file < argc; current_file++) { if(argv[current_file][0] == '-') continue; strcpy(inpath, argv[current_file]); if(!(in = mpeg3_open(inpath))) { fprintf(stderr, "Skipping %s\n", inpath); continue; } if((mpeg3_has_audio(in) && in->is_audio_stream) || (do_audio && !in->is_audio_stream && !in->is_video_stream)) { do_audio = 1; /* Add audio stream to end */ while(!mpeg3_read_audio_chunk(in, buffer, &output_size, BUFFER_SIZE, stream)) { result = !fwrite(buffer, output_size, 1, stdout); if(result) { perror("fwrite audio chunk"); break; } } } else if((mpeg3_has_video(in) && in->is_video_stream) || (do_video && !in->is_video_stream && !in->is_audio_stream)) { /* Add video stream to end */ int hour, minute, second, frame; long gop_frame; unsigned long code; float carry; int i, offset; do_video = 1; while(!mpeg3_read_video_chunk(in, buffer, &output_size, BUFFER_SIZE, stream) && output_size >= 4) { code = (unsigned long)buffer[output_size - 4] << 24; code |= (unsigned long)buffer[output_size - 3] << 16; code |= (unsigned long)buffer[output_size - 2] << 8; code |= (unsigned long)buffer[output_size - 1]; /* Got a frame at the end of this buffer. */ if(code == MPEG3_PICTURE_START_CODE) { total_frames++; } else if(code == MPEG3_SEQUENCE_END_CODE) { /* Got a sequence end code at the end of this buffer. */ output_size -= 4; } code = (unsigned long)buffer[0] << 24; code |= (unsigned long)buffer[1] << 16; code |= (unsigned long)buffer[2] << 8; code |= buffer[3]; i = 0; offset = 0; if(code == MPEG3_SEQUENCE_START_CODE && current_output_file > 0) { /* Skip the sequence start code */ i += 4; while(i < output_size && code != MPEG3_GOP_START_CODE) { code <<= 8; code |= buffer[i++]; } i -= 4; offset = i; } /* Search for GOP header to fix */ code = (unsigned long)buffer[i++] << 24; code |= (unsigned long)buffer[i++] << 16; code |= (unsigned long)buffer[i++] << 8; code |= buffer[i++]; while(i < output_size && code != MPEG3_GOP_START_CODE) { code <<= 8; code |= buffer[i++]; } if(code == MPEG3_GOP_START_CODE) { /* Get the time code */ code = (unsigned long)buffer[i] << 24; code |= (unsigned long)buffer[i + 1] << 16; code |= (unsigned long)buffer[i + 2] << 8; code |= (unsigned long)buffer[i + 3]; hour = code >> 26 & 0x1f; minute = code >> 20 & 0x3f; second = code >> 13 & 0x3f; frame = code >> 7 & 0x3f; gop_frame = (long)(hour * 3600 * mpeg3_frame_rate(in, stream) + minute * 60 * mpeg3_frame_rate(in, stream) + second * mpeg3_frame_rate(in, stream) + frame); /* fprintf(stderr, "old: %02d:%02d:%02d:%02d ", hour, minute, second, frame); */ /* Write a new time code */ hour = (long)((float)(total_frames - 1) / mpeg3_frame_rate(in, stream) / 3600); carry = hour * 3600 * mpeg3_frame_rate(in, stream); minute = (long)((float)(total_frames - 1 - carry) / mpeg3_frame_rate(in, stream) / 60); carry += minute * 60 * mpeg3_frame_rate(in, stream); second = (long)((float)(total_frames - 1 - carry) / mpeg3_frame_rate(in, stream)); carry += second * mpeg3_frame_rate(in, stream); frame = (total_frames - 1 - carry); buffer[i] = ((code >> 24) & 0x80) | (hour << 2) | (minute >> 4); buffer[i + 1] = ((code >> 16) & 0x08) | ((minute & 0xf) << 4) | (second >> 3); buffer[i + 2] = ((second & 0x7) << 5) | (frame >> 1); buffer[i + 3] = (code & 0x7f) | ((frame & 0x1) << 7); /* fprintf(stderr, "new: %02d:%02d:%02d:%02d\n", hour, minute, second, frame); */ } /* Write the frame */ result = !fwrite(buffer + offset, output_size - offset, 1, stdout); if(result) { perror("fwrite video chunk"); break; } } } else { fprintf(stderr, "Unsupported stream type.\n"); mpeg3_close(in); in = 0; continue; } mpeg3_close(in); in = 0; current_output_file++; } /* Terminate output */ if(current_output_file > 0 && do_video) { /*fprintf(stderr, "\n"); */ /* Write new end of sequence */ buffer[0] = MPEG3_SEQUENCE_END_CODE >> 24; buffer[1] = (MPEG3_SEQUENCE_END_CODE >> 16) & 0xff; buffer[2] = (MPEG3_SEQUENCE_END_CODE >> 8) & 0xff; buffer[3] = MPEG3_SEQUENCE_END_CODE & 0xff; result = !fwrite(buffer, 4, 1, stdout); } exit(0); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3css.h ================================================ #ifndef MPEG3CSS_H #define MPEG3CSS_H #include "mpeg3private.inc" struct mpeg3_block { char huh; }; struct mpeg3_playkey { char huh; }; typedef struct { char huh; } mpeg3_css_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3demux.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "libmpeg3.h" #include "mpeg3io.h" #include "mpeg3protos.h" #include #include #include #define ABS(x) ((x) >= 0 ? (x) : -(x)) /* Don't advance pointer */ static inline unsigned char mpeg3packet_next_char(mpeg3_demuxer_t *demuxer) { return demuxer->raw_data[demuxer->raw_offset]; } unsigned char mpeg3packet_read_char(mpeg3_demuxer_t *demuxer) { unsigned char result = demuxer->raw_data[demuxer->raw_offset++]; return result; } static inline unsigned int mpeg3packet_read_int16(mpeg3_demuxer_t *demuxer) { unsigned int a, b, result; a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 8) | b; return result; } static inline unsigned int mpeg3packet_next_int24(mpeg3_demuxer_t *demuxer) { unsigned int a, b, c, result; a = demuxer->raw_data[demuxer->raw_offset]; b = demuxer->raw_data[demuxer->raw_offset + 1]; c = demuxer->raw_data[demuxer->raw_offset + 2]; result = (a << 16) | (b << 8) | c; return result; } static inline unsigned int mpeg3packet_read_int24(mpeg3_demuxer_t *demuxer) { unsigned int a, b, c, result; a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; c = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 16) | (b << 8) | c; return result; } static inline unsigned int mpeg3packet_read_int32(mpeg3_demuxer_t *demuxer) { unsigned int a, b, c, d, result; a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; c = demuxer->raw_data[demuxer->raw_offset++]; d = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 24) | (b << 16) | (c << 8) | d; return result; } static inline unsigned int mpeg3packet_skip(mpeg3_demuxer_t *demuxer, long length) { demuxer->raw_offset += length; return 0; } int mpeg3_get_adaptation_field(mpeg3_demuxer_t *demuxer) { long length; int pcr_flag; demuxer->adaptation_fields++; /* get adaptation field length */ length = mpeg3packet_read_char(demuxer); /* get first byte */ pcr_flag = (mpeg3packet_read_char(demuxer) >> 4) & 1; if(pcr_flag) { unsigned long clk_ref_base = mpeg3packet_read_int32(demuxer); unsigned int clk_ref_ext = mpeg3packet_read_int16(demuxer); if (clk_ref_base > 0x7fffffff) { /* correct for invalid numbers */ clk_ref_base = 0; /* ie. longer than 32 bits when multiplied by 2 */ clk_ref_ext = 0; /* multiplied by 2 corresponds to shift left 1 (<<=1) */ } else { clk_ref_base <<= 1; /* Create space for bit */ clk_ref_base |= (clk_ref_ext >> 15); /* Take bit */ clk_ref_ext &= 0x01ff; /* Only lower 9 bits */ } demuxer->time = clk_ref_base + clk_ref_ext / 300; if(length) mpeg3packet_skip(demuxer, length - 7); } else mpeg3packet_skip(demuxer, length - 1); return 0; } int mpeg3_get_program_association_table(mpeg3_demuxer_t *demuxer) { demuxer->program_association_tables++; demuxer->table_id = mpeg3packet_read_char(demuxer); demuxer->section_length = mpeg3packet_read_int16(demuxer) & 0xfff; demuxer->transport_stream_id = mpeg3packet_read_int16(demuxer); mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } int mpeg3packet_get_data_buffer(mpeg3_demuxer_t *demuxer) { while(demuxer->raw_offset < demuxer->raw_size && demuxer->data_size < demuxer->data_allocated) { demuxer->data_buffer[demuxer->data_size++] = demuxer->raw_data[demuxer->raw_offset++]; } return 0; } int mpeg3_get_pes_packet_header(mpeg3_demuxer_t *demuxer, unsigned long *pts, unsigned long *dts) { unsigned int pes_header_bytes = 0; unsigned int pts_dts_flags; int pes_header_data_length; /* drop first 8 bits */ mpeg3packet_read_char(demuxer); pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; pes_header_data_length = mpeg3packet_read_char(demuxer); /* Get Presentation Time stamps and Decoding Time Stamps */ if(pts_dts_flags == 2) { *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *pts <<= 15; *pts |= (mpeg3packet_read_int16(demuxer) >> 1); *pts <<= 15; *pts |= (mpeg3packet_read_int16(demuxer) >> 1); pes_header_bytes += 5; } else if(pts_dts_flags == 3) { *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *pts <<= 15; *pts |= (mpeg3packet_read_int16(demuxer) >> 1); *pts <<= 15; *pts |= (mpeg3packet_read_int16(demuxer) >> 1); *dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *dts <<= 15; *dts |= (mpeg3packet_read_int16(demuxer) >> 1); *dts <<= 15; *dts |= (mpeg3packet_read_int16(demuxer) >> 1); pes_header_bytes += 10; } /* extract other stuff here! */ mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); return 0; } int get_unknown_data(mpeg3_demuxer_t *demuxer) { mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } int mpeg3_get_pes_packet_data(mpeg3_demuxer_t *demuxer, unsigned int stream_id) { unsigned long pts = 0, dts = 0; if((stream_id >> 4) == 12 || (stream_id >> 4) == 13) { /* Just pick the first available stream if no ID is set */ if(demuxer->astream == -1) demuxer->astream = (stream_id & 0x0f); if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) { mpeg3_get_pes_packet_header(demuxer, &pts, &dts); demuxer->pes_audio_time = pts; demuxer->audio_pid = demuxer->pid; return mpeg3packet_get_data_buffer(demuxer); } } else if((stream_id >> 4)==14) { /* Just pick the first available stream if no ID is set */ if(demuxer->vstream == -1) demuxer->vstream = (stream_id & 0x0f); if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) { mpeg3_get_pes_packet_header(demuxer, &pts, &dts); demuxer->pes_video_time = pts; demuxer->video_pid = demuxer->pid; return mpeg3packet_get_data_buffer(demuxer); } } else { return get_unknown_data(demuxer); } mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } int mpeg3_get_pes_packet(mpeg3_demuxer_t *demuxer) { unsigned int stream_id; demuxer->pes_packets++; stream_id = mpeg3packet_read_char(demuxer); /* Skip startcode */ mpeg3packet_read_int24(demuxer); /* Skip pes packet length */ mpeg3packet_read_int16(demuxer); if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) { return mpeg3_get_pes_packet_data(demuxer, stream_id); } else if(stream_id == MPEG3_PRIVATE_STREAM_2) { /* Dump private data! */ fprintf(stderr, "stream_id == MPEG3_PRIVATE_STREAM_2\n"); mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } else if(stream_id == MPEG3_PADDING_STREAM) { mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } else { fprintf(stderr, "unknown stream_id in pes packet"); return 1; } return 0; } int mpeg3_get_payload(mpeg3_demuxer_t *demuxer) { if(demuxer->payload_unit_start_indicator) { if(demuxer->pid==0) mpeg3_get_program_association_table(demuxer); else if(mpeg3packet_next_int24(demuxer) == MPEG3_PACKET_START_CODE_PREFIX) mpeg3_get_pes_packet(demuxer); else mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); } else { if(demuxer->pid == demuxer->audio_pid && demuxer->do_audio) { mpeg3packet_get_data_buffer(demuxer); } else if(demuxer->pid == demuxer->video_pid && demuxer->do_video) { mpeg3packet_get_data_buffer(demuxer); } else mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); } return 0; } /* Read a transport packet */ int mpeg3_read_transport(mpeg3_demuxer_t *demuxer) { mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); unsigned int bits; int table_entry; demuxer->raw_size = demuxer->packet_size; demuxer->raw_offset = 0; if(result) { perror("mpeg3_read_transport"); return 1; } /* Sync byte */ if(mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE) { fprintf(stderr, "mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE\n"); return 1; } /* bits = mpeg3packet_read_int24(demuxer) & 0x0000ffff; */ /* demuxer->transport_error_indicator = bits >> 15; */ /* demuxer->payload_unit_start_indicator = (bits >> 14) & 1; */ /* demuxer->pid = bits & 0x00001fff; */ /* demuxer->transport_scrambling_control = (mpeg3packet_next_char(demuxer) >> 6) & 0x3; */ /* demuxer->adaptation_field_control = (mpeg3packet_next_char(demuxer) >> 4) & 0x3; */ /* demuxer->continuity_counter = (mpeg3packet_read_char(demuxer) & 0xf); */ bits = mpeg3packet_read_int24(demuxer) & 0x00ffffff; demuxer->transport_error_indicator = (bits >> 23) & 0x1; demuxer->payload_unit_start_indicator = (bits >> 22) & 0x1; demuxer->pid = (bits >> 8) & 0x00001fff; demuxer->transport_scrambling_control = (bits >> 6) & 0x3; demuxer->adaptation_field_control = (bits >> 4) & 0x3; demuxer->continuity_counter = bits & 0xf; if(demuxer->transport_error_indicator) { fprintf(stderr, "demuxer->transport_error_indicator\n"); return 1; } if (demuxer->pid == 0x1fff) { demuxer->is_padding = 1; /* padding; just go to next */ return 0; } else { demuxer->is_padding = 0; } /* Get pid */ for(table_entry = 0, result = 0; table_entry < demuxer->total_pids; table_entry++) { if(demuxer->pid == demuxer->pid_table[table_entry]) { result = 1; break; } } /* Not in pid table */ if(!result) { demuxer->pid_table[table_entry] = demuxer->pid; demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; /* init */ demuxer->total_pids++; } result = 0; /* Check counters */ if(demuxer->pid != MPEG3_PROGRAM_ASSOCIATION_TABLE && demuxer->pid != MPEG3_CONDITIONAL_ACCESS_TABLE && (demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3)) { if(demuxer->continuity_counters[table_entry] != demuxer->continuity_counter) { fprintf(stderr, "demuxer->continuity_counters[table_entry] != demuxer->continuity_counter\n"); /* Reset it */ demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; } if(++(demuxer->continuity_counters[table_entry]) > 15) demuxer->continuity_counters[table_entry] = 0; } if(demuxer->adaptation_field_control == 2 || demuxer->adaptation_field_control == 3) result = mpeg3_get_adaptation_field(demuxer); if(demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3) result = mpeg3_get_payload(demuxer); return result; } int mpeg3_get_system_header(mpeg3_demuxer_t *demuxer) { int length = mpeg3packet_read_int16(demuxer); mpeg3packet_skip(demuxer, length); return 0; } unsigned long mpeg3_get_timestamp(mpeg3_demuxer_t *demuxer) { unsigned long timestamp; /* Only low 4 bits (7==1111) */ timestamp = (mpeg3packet_read_char(demuxer) >> 1) & 7; timestamp <<= 15; timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); timestamp <<= 15; timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); return timestamp; } int mpeg3_get_pack_header(mpeg3_demuxer_t *demuxer, unsigned int *header) { unsigned long i, j; unsigned long clock_ref, clock_ref_ext; /* Get the time code */ if((mpeg3packet_next_char(demuxer) >> 4) == 2) { /* MPEG-1 */ demuxer->time = (double)mpeg3_get_timestamp(demuxer) / 90000; /* Skip 3 bytes */ mpeg3packet_read_int24(demuxer); } else if(mpeg3packet_next_char(demuxer) & 0x40) { i = mpeg3packet_read_int32(demuxer); j = mpeg3packet_read_int16(demuxer); if(i & 0x40000000 || (i >> 28) == 2) { clock_ref = ((i & 0x38000000) << 3); // JMM fix was 0x31 see http://sourceforge.net/tracker/index.php?func=detail&aid=439528&group_id=13554&atid=313554 clock_ref |= ((i & 0x03fff800) << 4); clock_ref |= ((i & 0x000003ff) << 5); clock_ref |= ((j & 0xf800) >> 11); clock_ref_ext = (j >> 1) & 0x1ff; demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000; /* Skip 3 bytes */ mpeg3packet_read_int24(demuxer); i = mpeg3packet_read_char(demuxer) & 0x7; /* stuffing */ mpeg3packet_skip(demuxer, i); } } else { mpeg3packet_skip(demuxer, 2); } *header = mpeg3packet_read_int32(demuxer); if(*header == MPEG3_SYSTEM_START_CODE) { mpeg3_get_system_header(demuxer); *header = mpeg3packet_read_int32(demuxer); } return 0; } /* Program packet reading core */ int mpeg3_get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int *header) { unsigned long pts = 0, dts = 0; int stream_id; int pes_packet_length; int pes_packet_start; int i; mpeg3_t *file = (mpeg3_t *) demuxer->file; stream_id = *header & 0xff; pes_packet_length = mpeg3packet_read_int16(demuxer); pes_packet_start = demuxer->raw_offset; if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) { if((mpeg3packet_next_char(demuxer) >> 6) == 0x02) { /* Get MPEG-2 packet */ int pes_header_bytes = 0; int scrambling = (mpeg3packet_read_char(demuxer) >> 4) & 0x3; int pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; int pes_header_data_length = mpeg3packet_read_char(demuxer); if(scrambling && (demuxer->do_audio || demuxer->do_video)) { /* Decrypt it */ if(mpeg3_decrypt_packet(demuxer->titles[demuxer->current_title]->fs->css, demuxer->raw_data)) { fprintf(stderr, "mpeg3_get_ps_pes_packet: Decryption not available\n"); return 1; } } /* Get Presentation and Decoding Time Stamps */ if(pts_dts_flags == 2) { pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ pts <<= 15; pts |= (mpeg3packet_read_int16(demuxer) >> 1); pts <<= 15; pts |= (mpeg3packet_read_int16(demuxer) >> 1); pes_header_bytes += 5; } else if(pts_dts_flags == 3) { pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ pts <<= 15; pts |= (mpeg3packet_read_int16(demuxer) >> 1); pts <<= 15; pts |= (mpeg3packet_read_int16(demuxer) >> 1); dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ dts <<= 15; dts |= (mpeg3packet_read_int16(demuxer) >> 1); dts <<= 15; dts |= (mpeg3packet_read_int16(demuxer) >> 1); pes_header_bytes += 10; } /* Skip unknown */ mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); } else { int pts_dts_flags; /* Get MPEG-1 packet */ while(mpeg3packet_next_char(demuxer) == 0xff) { mpeg3packet_read_char(demuxer); } /* Skip STD buffer scale */ if((mpeg3packet_next_char(demuxer) & 0x40) == 0x40) { mpeg3packet_skip(demuxer, 2); } /* Decide which timestamps are available */ pts_dts_flags = mpeg3packet_next_char(demuxer); if(pts_dts_flags >= 0x30) { /* Get the presentation and decoding time stamp */ pts = mpeg3_get_timestamp(demuxer); dts = mpeg3_get_timestamp(demuxer); } else if(pts_dts_flags >= 0x20) { /* Get just the presentation time stamp */ pts = mpeg3_get_timestamp(demuxer); } else if(pts_dts_flags == 0x0f) { /* End of timestamps */ mpeg3packet_read_char(demuxer); } else { return 1; /* Error */ } } /* Now extract the payload. */ if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd) { /* Audio data */ /* Take first stream ID if -1 */ pes_packet_length -= demuxer->raw_offset - pes_packet_start; if(!demuxer->do_audio && !demuxer->do_video) demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG; else if(demuxer->astream == -1) demuxer->astream = stream_id & 0x0f; if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) { if(pts) demuxer->pes_audio_time = pts; memcpy(&demuxer->data_buffer[demuxer->data_size], &demuxer->raw_data[demuxer->raw_offset], pes_packet_length); demuxer->data_size += pes_packet_length; demuxer->raw_offset += pes_packet_length; } else { mpeg3packet_skip(demuxer, pes_packet_length); } } else if((stream_id >> 4) == 0xe) { /* Video data */ /* Take first stream ID if -1 */ if(!demuxer->do_audio && !demuxer->do_video) demuxer->vstream_table[stream_id & 0x0f] = 1; else if(demuxer->vstream == -1) demuxer->vstream = stream_id & 0x0f; pes_packet_length -= demuxer->raw_offset - pes_packet_start; if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) { if(pts) demuxer->pes_video_time = pts; memcpy(&demuxer->data_buffer[demuxer->data_size], &demuxer->raw_data[demuxer->raw_offset], pes_packet_length); demuxer->data_size += pes_packet_length; demuxer->raw_offset += pes_packet_length; } else { mpeg3packet_skip(demuxer, pes_packet_length); } } else if(stream_id == 0xbd && demuxer->raw_data[demuxer->raw_offset] != 0xff) { /* DVD audio data */ /* Get the audio format */ int format; if((demuxer->raw_data[demuxer->raw_offset] & 0xf0) == 0xa0) format = AUDIO_PCM; else format = AUDIO_AC3; stream_id = demuxer->raw_data[demuxer->raw_offset] - 0x80; /* Take first stream ID if not building TOC. */ if(!demuxer->do_audio && !demuxer->do_video) demuxer->astream_table[stream_id] = format; else if(demuxer->astream == -1) demuxer->astream = stream_id; if(stream_id == demuxer->astream && demuxer->do_audio) { demuxer->aformat = format; if(pts) demuxer->pes_audio_time = pts; mpeg3packet_read_int32(demuxer); pes_packet_length -= demuxer->raw_offset - pes_packet_start; memcpy(&demuxer->data_buffer[demuxer->data_size], &demuxer->raw_data[demuxer->raw_offset], pes_packet_length); demuxer->data_size += pes_packet_length; demuxer->raw_offset += pes_packet_length; } else { pes_packet_length -= demuxer->raw_offset - pes_packet_start; mpeg3packet_skip(demuxer, pes_packet_length); } } else if(stream_id == 0xbc || 1) { pes_packet_length -= demuxer->raw_offset - pes_packet_start; mpeg3packet_skip(demuxer, pes_packet_length); } } else if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM) { pes_packet_length -= demuxer->raw_offset - pes_packet_start; mpeg3packet_skip(demuxer, pes_packet_length); } while(demuxer->raw_offset + 4 < demuxer->raw_size) { *header = mpeg3packet_read_int32(demuxer); if((*header >> 8) != MPEG3_PACKET_START_CODE_PREFIX) demuxer->raw_offset -= 3; else break; } return 0; } int mpeg3_read_program(mpeg3_demuxer_t *demuxer) { int result = 0, count = 0; mpeg3_t *file = (mpeg3_t *) demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; unsigned int header; demuxer->raw_size = demuxer->packet_size; demuxer->raw_offset = 0; demuxer->data_size = 0; /* Search backward for it. */ header = mpeg3io_read_int32(title->fs); result = mpeg3io_eof(title->fs); if(!result) result = mpeg3io_seek_relative(title->fs, -4); // Search backwards for header while(header != MPEG3_PACK_START_CODE && !result && count < (demuxer->packet_size)) { result = mpeg3io_seek_relative(title->fs, -1); if(!result) { header >>= 8; header |= mpeg3io_read_char(title->fs) << 24; result = mpeg3io_seek_relative(title->fs, -1); } count++; } if ((header != MPEG3_PACK_START_CODE) || (result) ) { // couldn't find MPEG3_PACK_START_CODE return 1; } result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); if(result) { perror("mpeg3_read_program"); return 1; } // fprintf(stderr, "Got data %ld\n", title->fs->current_byte); header = mpeg3packet_read_int32(demuxer); while(demuxer->raw_offset + 4 < demuxer->raw_size && !result) { if(header == MPEG3_PACK_START_CODE) { result = mpeg3_get_pack_header(demuxer, &header); } else if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX) { result = mpeg3_get_ps_pes_packet(demuxer, &header); } } return result; } double mpeg3_lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte) { int i; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; if(!title->timecode_table_size) return 0; for(i = title->timecode_table_size - 1; i >= 0 && title->timecode_table[i].start_byte > byte; i--) ; if(i < 0) i = 0; return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time; } int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer, int reverse) { mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int result = 0; int do_seek = 0; /* Skip timecode advancing when constructing timecode table */ if(!title->timecode_table || !title->timecode_table_size || demuxer->generating_timecode) return 0; if(!reverse) { /* Get inside the current timecode */ if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte) { mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); } /* Get the next timecode */ while(!result && (mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte || demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) { /* * printf("mpeg3_advance_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); */ demuxer->current_timecode++; if(demuxer->current_timecode >= title->timecode_table_size) { demuxer->current_timecode = 0; if(demuxer->current_title + 1 < demuxer->total_titles) { mpeg3demux_open_title(demuxer, demuxer->current_title + 1); do_seek = 1; } else { mpeg3io_seek(title->fs, mpeg3io_total_bytes(title->fs)); result = 1; } } title = demuxer->titles[demuxer->current_title]; } if(!result && do_seek) { mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); } } else { /* Get the previous timecode */ while(!result && (mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte || demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) { /* * if(demuxer->do_audio) printf("mpeg3_reverse_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); */ demuxer->current_timecode--; if(demuxer->current_timecode < 0) { if(demuxer->current_title > 0) { mpeg3demux_open_title(demuxer, demuxer->current_title - 1); title = demuxer->titles[demuxer->current_title]; demuxer->current_timecode = title->timecode_table_size - 1; do_seek = 1; } else { mpeg3io_seek(title->fs, 0); demuxer->current_timecode = 0; result = 1; } } } if(!result && do_seek) mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); } return result; } /* Read packet in the forward direction */ int mpeg3_read_next_packet(mpeg3_demuxer_t *demuxer) { int result = 0; long current_position; mpeg3_t *file = (mpeg3_t *) demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; demuxer->data_size = 0; demuxer->data_position = 0; /* Flip the file descriptor back to the end of the packet for forward */ /* reading. */ if(demuxer->reverse) { result = mpeg3io_seek_relative(title->fs, demuxer->packet_size); demuxer->reverse = 0; } /* Read packets until the output buffer is full */ if(!result) { long p1; // BGF added this protection against infinite-looping here. do { p1 = title->fs->current_byte; result = mpeg3_advance_timecode(demuxer, 0); if(!result) { demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); if(file->is_transport_stream) { result = mpeg3_read_transport(demuxer); } else if(file->is_program_stream) { result = mpeg3_read_program(demuxer); } else { /* Read elementary stream. */ result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); if(!result) demuxer->data_size = demuxer->packet_size; } // We can spin out on attempts to read the last packet over and over. if (p1 >= title->fs->current_byte) { result = -1; title->fs->current_byte = title->fs->total_bytes; // So EOF checks start to fire. fprintf(stderr, "Stopping demux-stream to prevent spin."); } } } while (!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); } return result; } /* Read the packet right before the packet we're currently on. */ int mpeg3_read_prev_packet(mpeg3_demuxer_t *demuxer) { int result = 0; mpeg3_t *file = (mpeg3_t *) demuxer->file; long current_position; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; demuxer->data_size = 0; demuxer->data_position = 0; do { /* Rewind to the start of the packet to be read. */ result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); if(!result) result = mpeg3_advance_timecode(demuxer, 1); if(!result) demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); if(file->is_transport_stream && !result) { result = mpeg3_read_transport(demuxer); if(!mpeg3io_bof(title->fs)) /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); } else if(file->is_program_stream && !result) { result = mpeg3_read_program(demuxer); if(!mpeg3io_bof(title->fs)) /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); } else if(!result) { /* Elementary stream */ /* Read the packet forwards and seek back to the start */ result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); if(!result) { demuxer->data_size = demuxer->packet_size; result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); } } }while(!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); /* Remember that the file descriptor is at the beginning of the packet just read. */ demuxer->reverse = 1; demuxer->error_flag = result; return result; } /* Used for audio */ int mpeg3demux_read_data(mpeg3_demuxer_t *demuxer, unsigned char *output, long size) { long i; int result = 0; mpeg3_t *file = (mpeg3_t *) demuxer->file; demuxer->error_flag = 0; if(demuxer->data_position >= 0) { /* Read forwards */ for(i = 0; i < size && !result; ) { int fragment_size = size - i; if(fragment_size > demuxer->data_size - demuxer->data_position) fragment_size = demuxer->data_size - demuxer->data_position; memcpy(output + i, demuxer->data_buffer + demuxer->data_position, fragment_size); demuxer->data_position += fragment_size; i += fragment_size; if(i < size) { result = mpeg3_read_next_packet(demuxer); } } } else { /* Read backwards a full packet. */ /* Only good for reading less than the size of a full packet, but */ /* this routine should only be used for searching for previous markers. */ long current_position = demuxer->data_position; result = mpeg3_read_prev_packet(demuxer); if(!result) demuxer->data_position = demuxer->data_size + current_position; memcpy(output, demuxer->data_buffer + demuxer->data_position, size); demuxer->data_position += size; } demuxer->error_flag = result; return result; } unsigned int mpeg3demux_read_char_packet(mpeg3_demuxer_t *demuxer) { demuxer->error_flag = 0; if(demuxer->data_position >= demuxer->data_size) demuxer->error_flag = mpeg3_read_next_packet(demuxer); demuxer->next_char = demuxer->data_buffer[demuxer->data_position++]; return demuxer->next_char; } unsigned int mpeg3demux_read_prev_char_packet(mpeg3_demuxer_t *demuxer) { demuxer->error_flag = 0; demuxer->data_position--; if(demuxer->data_position < 0) { demuxer->error_flag = mpeg3_read_prev_packet(demuxer); if(!demuxer->error_flag) demuxer->data_position = demuxer->data_size - 1; } demuxer->next_char = demuxer->data_buffer[demuxer->data_position]; return demuxer->next_char; } mpeg3demux_timecode_t* mpeg3_append_timecode(mpeg3_demuxer_t *demuxer, mpeg3_title_t *title, long prev_byte, double prev_time, long next_byte, double next_time, int dont_store) { mpeg3demux_timecode_t *new_table; mpeg3demux_timecode_t *new_timecode = NULL, *old_timecode = NULL; long i; if(!title->timecode_table || title->timecode_table_allocation <= title->timecode_table_size) { if(title->timecode_table_allocation == 0) title->timecode_table_allocation = 1; else title->timecode_table_allocation *= 2; new_table = (mpeg3demux_timecode_t *) memoryAllocate(1, sizeof(mpeg3demux_timecode_t) * title->timecode_table_allocation); if(title->timecode_table) { for(i = 0; i < title->timecode_table_size; i++) { new_table[i] = title->timecode_table[i]; } memoryFree(title->timecode_table); } title->timecode_table = new_table; } if(!dont_store) { new_timecode = &title->timecode_table[title->timecode_table_size]; new_timecode->start_byte = next_byte; new_timecode->start_time = next_time; new_timecode->absolute_start_time = 0; if(title->timecode_table_size > 0) { old_timecode = &title->timecode_table[title->timecode_table_size - 1]; old_timecode->end_byte = prev_byte; old_timecode->end_time = prev_time; new_timecode->absolute_start_time = prev_time - old_timecode->start_time + old_timecode->absolute_start_time; new_timecode->absolute_end_time = next_time; } } title->timecode_table_size++; return new_timecode; } mpeg3demux_timecode_t* mpeg3demux_next_timecode(mpeg3_demuxer_t *demuxer, int *current_title, int *current_timecode, int current_program) { int done = 0; while(!done) { /* Increase timecode number */ if(*current_timecode < demuxer->titles[*current_title]->timecode_table_size - 1) { (*current_timecode)++; if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); } else /* Increase title number */ if(*current_title < demuxer->total_titles - 1) { (*current_title)++; (*current_timecode) = 0; if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); } else /* End of disk */ done = 1; } return 0; } mpeg3demux_timecode_t* mpeg3demux_prev_timecode(mpeg3_demuxer_t *demuxer, int *current_title, int *current_timecode, int current_program) { int done = 0; while(!done) { /* Increase timecode number */ if(*current_timecode > 0) { (*current_timecode)--; if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); } else /* Increase title number */ if(*current_title > 0) { (*current_title)--; (*current_timecode) = demuxer->titles[*current_title]->timecode_table_size - 1; if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); } else /* End of disk */ done = 1; } return 0; } int mpeg3demux_open_title(mpeg3_demuxer_t *demuxer, int title_number) { mpeg3_title_t *title; if(title_number < demuxer->total_titles) { if(demuxer->current_title >= 0) { mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); demuxer->current_title = -1; } title = demuxer->titles[title_number]; if(mpeg3io_open_file(title->fs)) { demuxer->error_flag = 1; perror("mpeg3demux_open_title"); } else { demuxer->current_title = title_number; } } demuxer->current_timecode = 0; return demuxer->error_flag; } /* Assign program numbers to interleaved programs */ int mpeg3demux_assign_programs(mpeg3_demuxer_t *demuxer) { int current_program = 0; int current_title = 0, previous_title; int current_timecode = 0, previous_timecode; double current_time, current_length; int done = 0; int interleaved = 0; mpeg3demux_timecode_t *timecode1, *timecode2; double program_times[MPEG3_MAX_STREAMS]; int total_programs = 1; int i, j; int program_exists, last_program_assigned = 0; int total_timecodes; mpeg3_title_t **titles = demuxer->titles; for(i = 0, total_timecodes = 0; i < demuxer->total_titles; i++) total_timecodes += demuxer->titles[i]->timecode_table_size; // if(total_timecodes < 3) return 0; /* * // Assign programs based on length of contiguous timecode * timecode1 = demuxer->titles[current_title]->timecode_table; * while(!done) * { * if(!timecode1) done = 1; * else * if(timecode1->end_time - timecode1->start_time < MPEG3_PROGRAM_THRESHOLD) * { * // Got interleaved section * interleaved = 1; * program_times[0] = timecode1->end_time; * * while(interleaved && !done) * { * timecode2 = mpeg3demux_next_timecode(demuxer, * ¤t_title, * ¤t_timecode, * 0); * * if(!timecode2) done = 1; * else * { * // Another segment of interleaved data * if(timecode2->end_time - timecode2->start_time < MPEG3_PROGRAM_THRESHOLD) * { * // Search program times for where the previous instance of the program left off * for(program_exists = 0, i = 0; * i < total_programs && !program_exists; * i++) * { * // Got a previous instance of the program * if(program_times[i] + 0.5 > timecode2->start_time && * program_times[i] - 0.5 < timecode2->start_time) * { * program_times[i] = timecode2->end_time; * timecode2->program = i; * program_exists = 1; * * // Programs must always start at 0 for an interleaved section * if(i < last_program_assigned && i != 0) * { * // Shift programs in the interleaved section down until they start at 0 * for(j = 0; j < total_programs - 1; j++) * program_times[j] = program_times[j + 1]; * * for(previous_title = current_title, previous_timecode = current_timecode; * titles[previous_title]->timecode_table[previous_timecode].program > 0 && * (previous_title >= 0 || previous_timecode >= 0); ) * { * titles[previous_title]->timecode_table[previous_timecode].program--; * previous_timecode--; * if(previous_timecode < 0 && previous_title > 0) * { * previous_title--; * previous_timecode = titles[previous_title]->timecode_table_size - 1; * } * } * } * } * } * * // Didn't get one * if(!program_exists) * { * program_times[total_programs] = timecode2->end_time; * timecode2->program = total_programs++; * } * last_program_assigned = timecode2->program; * } * // No more interleaved section * else * { * interleaved = 0; * // Restart program table from the beginning * total_programs = 1; * last_program_assigned = 0; * timecode1 = mpeg3demux_next_timecode(demuxer, * ¤t_title, * ¤t_timecode, * 0); * } * } * } * } * else * // Get next timecode * timecode1 = mpeg3demux_next_timecode(demuxer, * ¤t_title, * ¤t_timecode, * 0); * } * * demuxer->total_programs = total_programs; */ /* Assign absolute timecodes in each program. */ for(current_program = 0; current_program < total_programs; current_program++) { current_time = 0; current_title = 0; current_timecode = -1; while(timecode1 = mpeg3demux_next_timecode(demuxer, ¤t_title, ¤t_timecode, current_program)) { timecode1->absolute_start_time = current_time; current_time += timecode1->end_time - timecode1->start_time; timecode1->absolute_end_time = current_time; } } //for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]); demuxer->current_program = 0; return 0; } /* ==================================================================== */ /* Entry points */ /* ==================================================================== */ mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id) { mpeg3_demuxer_t *demuxer = (mpeg3_demuxer_t *) memoryAllocate(1, sizeof(mpeg3_demuxer_t)); int i; /* The demuxer will change the default packet size for its own use. */ demuxer->file = file; demuxer->packet_size = file->packet_size; demuxer->do_audio = do_audio; demuxer->do_video = do_video; /* Allocate buffer + padding */ demuxer->raw_data = (unsigned char*)memoryAllocate(1, MPEG3_MAX_PACKSIZE); demuxer->data_buffer = (unsigned char*)memoryAllocate(1, MPEG3_MAX_PACKSIZE); demuxer->data_allocated = MPEG3_MAX_PACKSIZE; /* System specific variables */ demuxer->audio_pid = stream_id; demuxer->video_pid = stream_id; demuxer->astream = stream_id; demuxer->vstream = stream_id; demuxer->current_title = -1; return demuxer; } int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer) { int i; if(demuxer->current_title >= 0) { mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); } for(i = 0; i < demuxer->total_titles; i++) { mpeg3_delete_title(demuxer->titles[i]); } if(demuxer->data_buffer) memoryFree(demuxer->data_buffer); memoryFree(demuxer->raw_data); memoryFree(demuxer); } /* Create a title. */ /* Build a table of timecodes contained in the program stream. */ /* If toc is 0 just read the first and last timecode. */ int mpeg3demux_create_title(mpeg3_demuxer_t *demuxer, int timecode_search, FILE *toc) { int result = 0, done = 0, counter_start, counter; mpeg3_t *file = (mpeg3_t *) demuxer->file; long next_byte=0, prev_byte=0; double next_time, prev_time, absolute_time; long i; mpeg3_title_t *title; unsigned long test_header = 0; mpeg3demux_timecode_t *timecode = 0; demuxer->error_flag = 0; demuxer->generating_timecode = 1; /* Create a single title */ if(!demuxer->total_titles) { demuxer->titles[0] = mpeg3_new_title(file, file->fs->path); demuxer->total_titles = 1; mpeg3demux_open_title(demuxer, 0); } title = demuxer->titles[0]; title->total_bytes = mpeg3io_total_bytes(title->fs); /* Get the packet size from the file */ if(file->is_program_stream) { mpeg3io_seek(title->fs, 4); for(i = 0; i < MPEG3_MAX_PACKSIZE && test_header != MPEG3_PACK_START_CODE; i++) { test_header <<= 8; test_header |= mpeg3io_read_char(title->fs); } if(i < MPEG3_MAX_PACKSIZE) demuxer->packet_size = i; mpeg3io_seek(title->fs, 0); } else demuxer->packet_size = file->packet_size; /* Get timecodes for the title */ if(file->is_transport_stream || file->is_program_stream) { mpeg3io_seek(title->fs, 0); while(!done && !result && !mpeg3io_eof(title->fs)) { next_byte = mpeg3io_tell(title->fs); result = mpeg3_read_next_packet(demuxer); if(!result) { next_time = demuxer->time; //printf("%f %f\n", next_time, prev_time); if(next_time < prev_time || next_time - prev_time > MPEG3_CONTIGUOUS_THRESHOLD || !title->timecode_table_size) { /* Discontinuous */ timecode = mpeg3_append_timecode(demuxer, title, prev_byte, prev_time, next_byte, next_time, 0); /* * printf("timecode: %ld %ld %f %f\n", * timecode->start_byte, * timecode->end_byte, * timecode->start_time, * timecode->end_time); */ counter_start = next_time; } prev_time = next_time; prev_byte = next_byte; counter = next_time; } /* Just get the first bytes if not building a toc to get the stream ID's. */ if(next_byte > 0x100000 && (!timecode_search || !toc)) done = 1; } /* Get the last timecode */ if(!toc || !timecode_search) { result = mpeg3io_seek(title->fs, title->total_bytes); if(!result) result = mpeg3_read_prev_packet(demuxer); } if(title->timecode_table && timecode) { timecode->end_byte = title->total_bytes; // timecode->end_byte = mpeg3io_tell(title->fs)/* + demuxer->packet_size */; timecode->end_time = demuxer->time; timecode->absolute_end_time = timecode->end_time - timecode->start_time; } } mpeg3io_seek(title->fs, 0); demuxer->generating_timecode = 0; return 0; } int mpeg3demux_print_timecodes(mpeg3_title_t *title, FILE *output) { mpeg3demux_timecode_t *timecode; int i; if(title->timecode_table) { for(i = 0; i < title->timecode_table_size; i++) { timecode = &title->timecode_table[i]; fprintf(output, "REGION: %ld %ld %f %f\n", timecode->start_byte, timecode->end_byte, timecode->start_time, timecode->end_time); } } return 0; } /* Read the title information from a toc */ int mpeg3demux_read_titles(mpeg3_demuxer_t *demuxer) { char string1[MPEG3_STRLEN], string2[MPEG3_STRLEN]; long start_byte, end_byte; float start_time, end_time; mpeg3_title_t *title = 0; mpeg3_t *file = (mpeg3_t *) demuxer->file; // Eventually use IFO file to generate titles while(!mpeg3io_end_of_file(file->fs)) //JMM use accessors { mpeg3io_scanf5(file->fs, "%s %s %ld %f %f %f", string1, string2, &end_byte, &start_time, &end_time); //JMM use accessors if(!strncasecmp(string1, "PATH:", 5)) { title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, string2); if(demuxer->current_title < 0) mpeg3demux_open_title(demuxer, 0); } else if(title) { start_byte = atol(string2); if(!strcasecmp(string1, "REGION:")) { mpeg3_append_timecode(demuxer, title, 0, 0, 0, 0, 1); title->timecode_table[title->timecode_table_size - 1].start_byte = start_byte; title->timecode_table[title->timecode_table_size - 1].end_byte = end_byte; title->timecode_table[title->timecode_table_size - 1].start_time = start_time; title->timecode_table[title->timecode_table_size - 1].end_time = end_time; } else if(!strcasecmp(string1, "ASTREAM:")) demuxer->astream_table[start_byte] = end_byte; else if(!strcasecmp(string1, "VSTREAM:")) demuxer->vstream_table[start_byte] = end_byte; else if(!strcasecmp(string1, "SIZE:")) title->total_bytes = start_byte; else if(!strcasecmp(string1, "PACKETSIZE:")) demuxer->packet_size = start_byte; } } mpeg3demux_assign_programs(demuxer); return 0; } int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src) { long i; mpeg3_t *file = (mpeg3_t *)dst->file; mpeg3_title_t *dst_title, *src_title; dst->packet_size = src->packet_size; dst->total_titles = src->total_titles; dst->total_programs = src->total_programs; for(i = 0; i < MPEG3_MAX_STREAMS; i++) { dst->astream_table[i] = src->astream_table[i]; dst->vstream_table[i] = src->vstream_table[i]; } for(i = 0; i < src->total_titles; i++) { src_title = src->titles[i]; dst_title = dst->titles[i] = mpeg3_new_title(file, src->titles[i]->fs->path); mpeg3_copy_title(dst_title, src_title); } mpeg3demux_open_title(dst, src->current_title); return 0; } int mpeg3demux_print_streams(mpeg3_demuxer_t *demuxer, FILE *toc) { int i; /* Print the stream information */ for(i = 0; i < MPEG3_MAX_STREAMS; i++) { if(demuxer->astream_table[i]) fprintf(toc, "ASTREAM: %d %d\n", i, demuxer->astream_table[i]); if(demuxer->vstream_table[i]) fprintf(toc, "VSTREAM: %d %d\n", i, demuxer->vstream_table[i]); } return 0; } /* Need a timecode table to do this */ double mpeg3demux_length(mpeg3_demuxer_t *demuxer) { mpeg3_title_t *title; int i, j; double length; for(i = demuxer->total_titles - 1; i >= 0; i--) { title = demuxer->titles[i]; for(j = title->timecode_table_size - 1; j >= 0; j--) { if(title->timecode_table[j].program == demuxer->current_program) { return title->timecode_table[j].end_time - title->timecode_table[j].start_time + title->timecode_table[j].absolute_start_time; } } } return 1; } int mpeg3demux_eof(mpeg3_demuxer_t *demuxer) { if(demuxer->current_title >= 0) { if(mpeg3io_eof(demuxer->titles[demuxer->current_title]->fs) && demuxer->current_title >= demuxer->total_titles - 1) return 1; } return 0; } int mpeg3demux_bof(mpeg3_demuxer_t *demuxer) { if(demuxer->current_title >= 0) { if(mpeg3io_bof(demuxer->titles[demuxer->current_title]->fs) && demuxer->current_title <= 0) return 1; } return 0; } /* For elemental streams seek to a byte */ int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, long byte) { long current_position; mpeg3_t *file = (mpeg3_t *) demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; demuxer->data_position = 0; demuxer->data_size = 0; demuxer->error_flag = mpeg3io_seek(title->fs, byte); if(!demuxer->error_flag && (file->is_transport_stream || file->is_program_stream)) { /* Get on a packet boundary only for system streams. */ current_position = mpeg3io_tell(title->fs); if(byte % demuxer->packet_size) { demuxer->error_flag |= mpeg3io_seek(title->fs, current_position - (current_position % demuxer->packet_size)); } } return demuxer->error_flag; } /* For programs streams and toc seek to a time */ int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time) { int i, j, done = 0, result = 0; double byte_offset, new_byte_offset; double guess = 0, minimum = 65535; mpeg3_title_t *title; mpeg3demux_timecode_t *timecode; demuxer->error_flag = 0; i = 0; j = 0; title = demuxer->titles[i]; timecode = &title->timecode_table[j]; /* Get the title and timecode of the new position */ while(!demuxer->error_flag && !(timecode->absolute_start_time <= new_time && timecode->absolute_end_time > new_time && timecode->program == demuxer->current_program)) { /* Next timecode */ j++; if(j >= title->timecode_table_size) { i++; j = 0; if(i >= demuxer->total_titles) { demuxer->error_flag = 1; return 1; } else { mpeg3demux_open_title(demuxer, i); } } title = demuxer->titles[i]; timecode = &title->timecode_table[j]; } /* Guess the new byte position */ demuxer->current_timecode = j; byte_offset = ((new_time - timecode->absolute_start_time) / (timecode->absolute_end_time - timecode->absolute_start_time) * (timecode->end_byte - timecode->start_byte) + timecode->start_byte); //printf("mpeg3demux_seek_time %f %f\n", new_time, byte_offset); while(!done && !result && byte_offset >= 0) { result = mpeg3demux_seek_byte(demuxer, (long)byte_offset); //printf("seek_time 0 byte %.0f want %f result %d\n", byte_offset, new_time, result); if(!result) { result = mpeg3_read_next_packet(demuxer); // printf("seek_time 1 guess %f want %f\n", guess, new_time); guess = demuxer->time + demuxer->time_offset; if(fabs(new_time - guess) >= fabs(minimum)) done = 1; else { minimum = guess - new_time; new_byte_offset = byte_offset + ((new_time - guess) / (timecode->end_time - timecode->start_time) * (timecode->end_byte - timecode->start_byte)); if(labs((long)new_byte_offset - (long)byte_offset) < demuxer->packet_size) done = 1; byte_offset = new_byte_offset; } } } /* Get one packet before the packet just read */ if(!result && byte_offset > demuxer->packet_size && minimum > 0) { mpeg3_read_prev_packet(demuxer); mpeg3_read_prev_packet(demuxer); } //printf("seek_time %d %d %d\n", demuxer->current_title, demuxer->current_timecode, mpeg3demux_tell(demuxer)); demuxer->error_flag = result; return result; } int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage) { double total_bytes = 0; double absolute_position; long relative_position; int i, new_title; mpeg3_title_t *title; demuxer->error_flag = 0; /* Get the absolute byte position; */ for(i = 0; i < demuxer->total_titles; i++) total_bytes += demuxer->titles[i]->total_bytes; absolute_position = percentage * total_bytes; /* Get the title the byte is inside */ for(new_title = 0, total_bytes = 0; new_title < demuxer->total_titles; new_title++) { total_bytes += demuxer->titles[new_title]->total_bytes; if(absolute_position < total_bytes) break; } if(new_title >= demuxer->total_titles) { new_title = demuxer->total_titles - 1; } /* Got a title */ title = demuxer->titles[new_title]; total_bytes -= title->total_bytes; relative_position = (long)(absolute_position - total_bytes); /* Get the timecode the byte is inside */ for(demuxer->current_timecode = 0; demuxer->current_timecode < title->timecode_table_size; demuxer->current_timecode++) { if(title->timecode_table[demuxer->current_timecode].start_byte <= relative_position && title->timecode_table[demuxer->current_timecode].end_byte > relative_position) { break; } } if(demuxer->current_timecode >= title->timecode_table_size) demuxer->current_timecode = title->timecode_table_size - 1; /* Get the nearest timecode in the same program */ while(demuxer->current_timecode < title->timecode_table_size - 1 && title->timecode_table[demuxer->current_timecode].program != demuxer->current_program) { demuxer->current_timecode++; } /* Open the new title and seek to the correct byte */ if(new_title != demuxer->current_title) { demuxer->error_flag = mpeg3demux_open_title(demuxer, new_title); } if(!demuxer->error_flag) demuxer->error_flag = mpeg3io_seek(title->fs, relative_position); return demuxer->error_flag; } double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer) { double total_bytes = 0; double position = 0; int i; demuxer->error_flag = 0; position = mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); for(i = 0; i < demuxer->total_titles; i++) { if(i == demuxer->current_title) { position += total_bytes; } total_bytes += demuxer->titles[i]->total_bytes; } return position / total_bytes; } double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer) { return demuxer->time; } long mpeg3demux_tell(mpeg3_demuxer_t *demuxer) { return mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); } long mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer) { mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; return title->total_bytes; } mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file) { if(file->is_program_stream || file->is_transport_stream) { if(file->has_audio) return file->atrack[0]->demuxer; else if(file->has_video) return file->vtrack[0]->demuxer; } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3demux.h ================================================ #ifndef MPEG3DEMUX_H #define MPEG3DEMUX_H #include "mpeg3title.h" #include typedef struct { void* file; /* Data consisting of the multiplexed packet */ unsigned char *raw_data; long raw_offset; int raw_size; long packet_size; /* Only one is on depending on which track owns the demultiplexer. */ int do_audio; int do_video; /* Data consisting of the elementary stream */ unsigned char *data_buffer; long data_size; long data_position; long data_allocated; /* Remember when the file descriptor is at the beginning of the packet just read. */ int reverse; /* Set to 1 when eof or attempt to read before beginning */ int error_flag; /* Temp variables for returning */ unsigned char next_char; /* Correction factor for time discontinuity */ double time_offset; int generating_timecode; /* Titles */ mpeg3_title_t *titles[MPEG3_MAX_STREAMS]; int total_titles; int current_title; /* Tables of every stream ID encountered */ int astream_table[MPEG3_MAX_STREAMS]; /* macro of audio format if audio */ int vstream_table[MPEG3_MAX_STREAMS]; /* 1 if video */ /* Programs */ int total_programs; int current_program; /* Timecode in the current title */ int current_timecode; /* Byte position in the current title */ long current_byte; int transport_error_indicator; int payload_unit_start_indicator; int pid; int transport_scrambling_control; int adaptation_field_control; int continuity_counter; int is_padding; int pid_table[MPEG3_PIDMAX]; int continuity_counters[MPEG3_PIDMAX]; int total_pids; int adaptation_fields; double time; /* Time in seconds */ int audio_pid; int video_pid; int astream; /* Video stream ID being decoded. -1 = select first ID in stream */ int vstream; /* Audio stream ID being decoded. -1 = select first ID in stream */ int aformat; /* format of the audio derived from multiplexing codes */ long program_association_tables; int table_id; int section_length; int transport_stream_id; long pes_packets; double pes_audio_time; /* Presentation Time stamps */ double pes_video_time; /* Presentation Time stamps */ } mpeg3_demuxer_t; /* ========================================================================= */ /* Entry points */ /* ========================================================================= */ #define mpeg3demux_error(demuxer) (((mpeg3_demuxer_t *)(demuxer))->error_flag) #define mpeg3demux_time_offset(demuxer) (((mpeg3_demuxer_t *)(demuxer))->time_offset) #define mpeg3demux_current_time(demuxer) (((mpeg3_demuxer_t *)(demuxer))->time + ((mpeg3_demuxer_t *)(demuxer))->time_offset) #define mpeg3demux_read_char(demuxer) \ ((((mpeg3_demuxer_t *)(demuxer))->data_position < ((mpeg3_demuxer_t *)(demuxer))->data_size) ? \ ((mpeg3_demuxer_t *)(demuxer))->data_buffer[((mpeg3_demuxer_t *)(demuxer))->data_position++] : \ mpeg3demux_read_char_packet(demuxer)) #define mpeg3demux_read_prev_char(demuxer) \ ((((mpeg3_demuxer_t *)(demuxer))->data_position != 0) ? \ ((mpeg3_demuxer_t *)(demuxer))->data_buffer[((mpeg3_demuxer_t *)(demuxer))->data_position--] : \ mpeg3demux_read_prev_char_packet(demuxer)) #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3io.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ /* Changed May 23 by Jason Dufair to handle mp3 files with ID3v2 tags (specifically ones with binary data in them) - Added mpeg3io_get_id3v2_size - modified all fseek's to use the id3v2 offset Changed Jan 20th 2006 by John M McIntosh to support reading mpeg file from a buffer setvbuf(remember,0, _IOFBF, 64*1024); //JMM Feb 26th, 2006 for CD reader performance */ #include "mpeg3private.h" #include "mpeg3protos.h" #if defined(__linux__) #include #endif #if defined( TARGET_OS_MAC) && !defined ( __APPLE__ ) && !defined ( __MACH__ ) #include #else #include #endif #include #include mpeg3_fs_t* mpeg3_new_fs(char *path,int size) { mpeg3_fs_t *fs = (mpeg3_fs_t *) memoryAllocate(1, sizeof(mpeg3_fs_t)); fs->css = mpeg3_new_css(); if (size) { fs->mpeg_is_in_buffer = (char *) memoryAllocate(1, size); fs->mpeg_is_in_buffer_file_position = 0; fs->mpeg_buffer_size = size; memmove(fs->mpeg_is_in_buffer,path,size); fs->path[0] = 0x00; } else { strcpy(fs->path, path); fs->mpeg_is_in_buffer = NULL; fs->mpeg_is_in_buffer_file_position = 0; fs->mpeg_buffer_size = 0; } return fs; } int mpeg3_delete_fs(mpeg3_fs_t *fs) { mpeg3_delete_css(fs->css); if (fs->mpeg_is_in_buffer) memoryFree(fs->mpeg_is_in_buffer); fs->mpeg_is_in_buffer = NULL; memoryFree(fs); return 0; } int mpeg3_copy_fs(mpeg3_fs_t *dst, mpeg3_fs_t *src) { strcpy(dst->path, src->path); dst->current_byte = 0; return 0; } long mpeg3io_get_total_bytes(mpeg3_fs_t *fs) { /* * struct stat st; * if(stat(fs->path, &st) < 0) return 0; * return (long)st.st_size; */ if (fs->mpeg_is_in_buffer) { fs->total_bytes = fs->mpeg_buffer_size - fs->id3v2_offset; fs->mpeg_is_in_buffer_file_position = fs->id3v2_offset; return fs->total_bytes; } if (! fs->fd) { // bgf error protection for win return 0; } fseek(fs->fd, 0, SEEK_END); fs->total_bytes = ftell(fs->fd) - fs->id3v2_offset; fseek(fs->fd, fs->id3v2_offset, SEEK_SET); return fs->total_bytes; } int mpeg3io_get_id3v2_size(mpeg3_fs_t *fs) { unsigned long synchsafe_size = 0; if (fs->mpeg_is_in_buffer) { fs->mpeg_is_in_buffer_file_position = 6; } else { if (! fs->fd) return 0; fseek(fs->fd, 6, SEEK_SET); } synchsafe_size = mpeg3io_read_int32(fs); return ((synchsafe_size & 0xff) | (synchsafe_size & 0xff00) >> 1 | (synchsafe_size & 0xff0000) >> 2 | (synchsafe_size & 0xff000000) >> 3) + 10; } int mpeg3io_open_file(mpeg3_fs_t *fs) { unsigned int bits; if (!fs->mpeg_is_in_buffer) { /* Need to perform authentication before reading a single byte. */ mpeg3_get_keys(fs->css, fs->path); if(!(fs->fd = fopen(fs->path, "rb"))) { perror("mpeg3io_open_file"); return 1; } setvbuf(fs->fd,0, _IOFBF, 64*1024); //JMM Feb 26th, 2006 for CD reader performance } bits = mpeg3io_read_int32(fs); if ((bits >> 8) == MPEG3_ID3_PREFIX) { fs->id3v2_offset = mpeg3io_get_id3v2_size(fs); } else { fs->id3v2_offset = 0; } fs->total_bytes = mpeg3io_get_total_bytes(fs); if(!fs->total_bytes) { if (!fs->mpeg_is_in_buffer) { if (fs->fd) fclose(fs->fd); } fprintf(stderr, "MP2 - empty file %s\n", fs->path); fs->fd = NULL; return 1; } fs->current_byte = 0; return 0; } int mpeg3io_close_file(mpeg3_fs_t *fs) { if (!fs->mpeg_is_in_buffer) if(fs->fd) fclose(fs->fd); else { if (fs->mpeg_is_in_buffer) memoryFree(fs->mpeg_is_in_buffer); fs->mpeg_is_in_buffer = 0; } /* fprintf (stderr, "MP2 closing %s\n", fs->path); */ fs->fd = 0; return 0; } int mpeg3io_read_data(unsigned char *buffer, long bytes, mpeg3_fs_t *fs) { int result = 0; if (fs->mpeg_is_in_buffer) { int normalizedBytes; normalizedBytes = fs->mpeg_is_in_buffer_file_position + bytes; if (normalizedBytes > fs->mpeg_buffer_size) { normalizedBytes = fs->mpeg_buffer_size - fs->mpeg_is_in_buffer_file_position; } else normalizedBytes = bytes; memmove(buffer,fs->mpeg_is_in_buffer+fs->mpeg_is_in_buffer_file_position,normalizedBytes); fs->mpeg_is_in_buffer_file_position += normalizedBytes; result = !normalizedBytes; } else { result = (fs->fd != NULL) && !fread(buffer, 1, bytes, fs->fd); } fs->current_byte += bytes; return (result && bytes); } int mpeg3io_device(char *path, char *device) { struct stat file_st, device_st; #if defined(__linux__) struct mntent *mnt; #endif FILE *fp; if(stat(path, &file_st) < 0) { perror("mpeg3io_device"); return 1; } #if defined(__linux__) fp = setmntent(MOUNTED, "r"); while(fp && (mnt = getmntent(fp))) { if(stat(mnt->mnt_fsname, &device_st) < 0) continue; if(device_st.st_rdev == file_st.st_dev) { strncpy(device, mnt->mnt_fsname, MPEG3_STRLEN); break; } } endmntent(fp); #endif return 0; } int mpeg3io_seek(mpeg3_fs_t *fs, long byte) { fs->current_byte = byte; if (fs->mpeg_is_in_buffer) { int target; target = byte + fs->id3v2_offset; if (target > fs->mpeg_buffer_size) return -1; if (target < 0) return -1; fs->mpeg_is_in_buffer_file_position = target; return 0; } // For Squeak-Teleplace, where we only deal in static mpeg files. // No seek beyond the EOF. Partly to protect against win32 seek woes. if (byte < 0) { return -1; } else if (fs->total_bytes && (byte > fs->total_bytes)) { /* fprintf(stderr, "libmpeg3 seek out of range %ld vs %ld\n", byte, fs->total_bytes); */ return -1; } else { if (fs->fd) { return fseek(fs->fd, (byte + fs->id3v2_offset), SEEK_SET); } fprintf(stderr, "MP2: seek no fd\n"); return -1; } } int mpeg3io_seek_relative(mpeg3_fs_t *fs, long bytes) { long old_current_byte = fs->current_byte; fs->current_byte += bytes; if (fs->mpeg_is_in_buffer) { long target = fs->current_byte + fs->id3v2_offset; if (target > fs->mpeg_buffer_size) return -1; if (target < 0) { return -1; } fs->mpeg_is_in_buffer_file_position = target; return 0; } if (fs->current_byte < 0) { return -1; } else if (fs->total_bytes && (fs->current_byte > fs->total_bytes)) { /* For Squeak-Teleplace, where we only deal in static mpeg files. */ /* No seek beyond the EOF. Partly to protect against win32 seek woes. */ return -1; } if (fs->fd) { return fseek(fs->fd, fs->current_byte + fs->id3v2_offset, SEEK_SET); } fprintf(stderr, "MP2: rel seek no fd\n"); return -1; } int mpeg3io_scanf (mpeg3_fs_t *fs,char *format, void * string1, void * string2) { int return_value; if (fs->mpeg_is_in_buffer) { return_value = sscanf(fs->mpeg_is_in_buffer+fs->mpeg_is_in_buffer_file_position,format, string1, string2); return return_value; } if (! fs->fd) { fprintf(stderr, "MP2 scan3 - no file\n"); return -1; } return_value = fscanf(fs->fd,format, string1, string2); return return_value; } int mpeg3io_scanf5 (mpeg3_fs_t *fs,char *format, void * string1, void * string2, void * string3, void * string4, void * string5) { int return_value; if (fs->mpeg_is_in_buffer) { return_value = sscanf(fs->mpeg_is_in_buffer+fs->mpeg_is_in_buffer_file_position,format, string1, string2, string3, string4, string5); return return_value; } if (! fs->fd) { fprintf(stderr, "MP2 scan5 - no file\n"); return -1; } return_value = fscanf(fs->fd,format, string1, string2, string3, string4, string5); return return_value; } int mpeg3io_end_of_file(mpeg3_fs_t *fs ) { if (fs->mpeg_is_in_buffer) { return fs->mpeg_is_in_buffer_file_position == fs->mpeg_buffer_size; } return ( ! fs->fd ) || feof(fs->fd); } inline int mpeg3io_fgetc(mpeg3_fs_t *fs) { if (fs->mpeg_is_in_buffer) { unsigned int value; fs->mpeg_is_in_buffer_file_position++; if (fs->mpeg_is_in_buffer_file_position >= fs->mpeg_buffer_size) { fs->mpeg_is_in_buffer_file_position = fs->mpeg_buffer_size; return 0; } value = (unsigned int) fs->mpeg_is_in_buffer[fs->mpeg_is_in_buffer_file_position-1]; return value; } return (fs->fd ? fgetc(fs->fd) : 0); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3io.h ================================================ #ifndef MPEG3IO_H #define MPEG3IO_H #include #include "mpeg3css.h" #include "mpeg3private.inc" /* Filesystem structure */ typedef struct { FILE *fd; mpeg3_css_t *css; /* Encryption object */ char path[MPEG3_STRLEN]; /* Hypothetical position of file pointer */ long current_byte; long total_bytes; unsigned long id3v2_offset; unsigned char* mpeg_is_in_buffer; long mpeg_is_in_buffer_file_position; long mpeg_buffer_size; } mpeg3_fs_t; #define mpeg3io_tell(fs) (((mpeg3_fs_t *)(fs))->current_byte) // End of file #define mpeg3io_eof(fs) (((mpeg3_fs_t *)(fs))->current_byte >= ((mpeg3_fs_t *)(fs))->total_bytes) // Beginning of file #define mpeg3io_bof(fs) (((mpeg3_fs_t *)(fs))->current_byte < 0) #ifdef WIN32 #define inline __inline #endif #define mpeg3io_total_bytes(fs) (((mpeg3_fs_t *)(fs))->total_bytes) inline int mpeg3io_fgetc(mpeg3_fs_t *fs); static inline unsigned int mpeg3io_read_int32(mpeg3_fs_t *fs) { int a, b, c, d; unsigned int result; /* Do not fread. This breaks byte ordering. */ a = (unsigned char)mpeg3io_fgetc(fs); b = (unsigned char)mpeg3io_fgetc(fs); c = (unsigned char)mpeg3io_fgetc(fs); d = (unsigned char)mpeg3io_fgetc(fs); result = ((int)a << 24) | ((int)b << 16) | ((int)c << 8) | ((int)d); fs->current_byte += 4; return result; } static inline unsigned int mpeg3io_read_char(mpeg3_fs_t *fs) { fs->current_byte++; return mpeg3io_fgetc(fs); } #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3private.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef MPEG3PRIVATE_H #define MPEG3PRIVATE_H /** configuration **/ #if defined(__MWERKS__) #define TARGET_MAC_OS 1 #endif /* how should functions be inlined? */ #ifndef INLINE #ifdef TARGET_MAC_OS #define INLINE #else #define INLINE inline #endif #endif #ifdef _MSC_VER /* disallow INLINE since those functions cannot be linked */ #undef INLINE #define INLINE #endif /* use pthreads? */ #ifndef NOPTHREADS #ifndef TARGET_MAC_OS #define USE_PTHREADS #endif #endif #include "mpeg3atrack.h" #include "mpeg3css.h" #include "mpeg3io.h" #include "mpeg3private.inc" #include "mpeg3title.h" #include "mpeg3vtrack.h" typedef struct { mpeg3_fs_t *fs; /* Store entry path here */ mpeg3_demuxer_t *demuxer; /* Master tables */ /* Media specific */ int has_audio; int has_video; int total_astreams; int total_vstreams; mpeg3_atrack_t *atrack[MPEG3_MAX_STREAMS]; mpeg3_vtrack_t *vtrack[MPEG3_MAX_STREAMS]; /* Only one of these is set to 1 to specify what kind of stream we have. */ int is_transport_stream; int is_program_stream; int is_audio_stream; /* Elemental stream */ int is_video_stream; /* Elemental stream */ long packet_size; /* Type and stream for getting current percentage */ int last_type_read; /* 1 - audio 2 - video */ int last_stream_read; int program; /* Number of program to play */ int cpus; int have_mmx; } mpeg3_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3private.inc ================================================ #ifndef LIBMPEG3_INC #define LIBMPEG3_INC #define MPEG3_FLOAT32 float #define MPEG3_INT16 short int #define MPEG3_INT32 int #define MPEG3_INT64 long #define MPEG3_TOC_PREFIX 0x544f4356 #define MPEG3_TOC_PREFIXLOWER 0x746f6376 #define MPEG3_ID3_PREFIX 0x494433 #define MPEG3_RIFF_CODE 0x52494646 #define MPEG3_PROC_CPUINFO "/proc/cpuinfo" #define MPEG3_TS_PACKET_SIZE 188 #define MPEG3_DVD_PACKET_SIZE 0x800 #define MPEG3_SYNC_BYTE 0x47 #define MPEG3_PACK_START_CODE 0x000001ba #define MPEG3_SEQUENCE_START_CODE 0x000001b3 #define MPEG3_SEQUENCE_END_CODE 0x000001b7 #define MPEG3_SYSTEM_START_CODE 0x000001bb #define MPEG3_STRLEN 1024 #define MPEG3_PIDMAX 20 /* Maximum number of PIDs in one stream */ #define MPEG3_PROGRAM_ASSOCIATION_TABLE 0x00 #define MPEG3_CONDITIONAL_ACCESS_TABLE 0x01 #define MPEG3_PACKET_START_CODE_PREFIX 0x000001 #define MPEG3_PRIVATE_STREAM_2 0xbf #define MPEG3_PADDING_STREAM 0xbe #define MPEG3_GOP_START_CODE 0x000001b8 #define MPEG3_PICTURE_START_CODE 0x00000100 #define MPEG3_EXT_START_CODE 0x000001b5 #define MPEG3_USER_START_CODE 0x000001b2 #define MPEG3_SLICE_MIN_START 0x00000101 #define MPEG3_SLICE_MAX_START 0x000001af #define MPEG3_AC3_START_CODE 0x0b77 #define MPEG3_PCM_START_CODE 0x0180 #define MPEG3_MAX_CPUS 256 #define MPEG3_MAX_STREAMS 256 #define MPEG3_MAX_PACKSIZE 262144 #define MPEG3_CONTIGUOUS_THRESHOLD 10 /* Positive difference before declaring timecodes discontinuous */ #define MPEG3_PROGRAM_THRESHOLD 5 /* Minimum number of seconds before interleaving programs */ #define MPEG3_SEEK_THRESHOLD 16 /* Number of frames difference before absolute seeking */ /* Values for audio format */ #define AUDIO_UNKNOWN 0 #define AUDIO_MPEG 1 #define AUDIO_AC3 2 #define AUDIO_PCM 3 #define AUDIO_AAC 4 #define AUDIO_JESUS 5 #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3protos.h ================================================ #ifndef MPEG3PROTOS_H #define MPEG3PROTOS_H /* CSS */ mpeg3_css_t* mpeg3_new_css(); /* DEMUX */ mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id); int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer); int mpeg3demux_read_data(mpeg3_demuxer_t *demuxer, unsigned char *output, long size); unsigned int mpeg3demux_read_int32(mpeg3_demuxer_t *demuxer); unsigned int mpeg3demux_read_int24(mpeg3_demuxer_t *demuxer); unsigned int mpeg3demux_read_int16(mpeg3_demuxer_t *demuxer); double mpeg3demux_length(mpeg3_demuxer_t *demuxer); mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file); long mpeg3demux_tell(mpeg3_demuxer_t *demuxer); double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer); double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer); int mpeg3demux_eof(mpeg3_demuxer_t *demuxer); int mpeg3demux_bof(mpeg3_demuxer_t *demuxer); /* TITLE */ mpeg3_title_t* mpeg3_new_title(mpeg3_t *file, char *path); /* ATRACK */ mpeg3_atrack_t* mpeg3_new_atrack(mpeg3_t *file, int stream_id, int is_ac3, mpeg3_demuxer_t *demuxer); int mpeg3_delete_atrack(mpeg3_t *file, mpeg3_atrack_t *atrack); /* VTRACK */ mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, int stream_id, mpeg3_demuxer_t *demuxer); int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack); /* AUDIO */ mpeg3audio_t* mpeg3audio_new(mpeg3_t *file, mpeg3_atrack_t *track, int is_ac3); int mpeg3audio_delete(mpeg3audio_t *audio); /* VIDEO */ mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track); int mpeg3video_delete(mpeg3video_t *video); int mpeg3video_read_frame(mpeg3video_t *video, long frame_number, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model); /* FILESYSTEM */ mpeg3_fs_t* mpeg3_new_fs(char *path,int size); int mpeg3_delete_fs(mpeg3_fs_t *fs); int mpeg3io_open_file(mpeg3_fs_t *fs); int mpeg3io_close_file(mpeg3_fs_t *fs); int mpeg3io_read_data(unsigned char *buffer, long bytes, mpeg3_fs_t *fs); int mpeg3io_end_of_file(mpeg3_fs_t *fs); int mpeg3io_scanf (mpeg3_fs_t *fs,char *format, void * string1, void * string2); int mpeg3io_scanf5 (mpeg3_fs_t *fs,char *format, void * string1, void * string2, void * string3, void * string4, void * string5); int mpeg3io_fgetc(mpeg3_fs_t *fs); /* BITSTREAM */ mpeg3_bits_t* mpeg3bits_new_stream(mpeg3_t *file, mpeg3_demuxer_t *demuxer); unsigned int mpeg3bits_getbits(mpeg3_bits_t* stream, int n); #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3title.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3protos.h" #include "mpeg3title.h" #include mpeg3_title_t* mpeg3_new_title(mpeg3_t *file, char *path) { mpeg3_title_t *title = (mpeg3_title_t *) memoryAllocate(1, sizeof(mpeg3_title_t)); if (file->fs->mpeg_buffer_size) { title->fs = mpeg3_new_fs(file->fs->mpeg_is_in_buffer,file->fs->mpeg_buffer_size); } else { title->fs = mpeg3_new_fs(path,0); } title->file = file; return title; } int mpeg3_delete_title(mpeg3_title_t *title) { mpeg3_delete_fs(title->fs); if(title->timecode_table_size) { memoryFree(title->timecode_table); } memoryFree(title); return 0; } int mpeg3_copy_title(mpeg3_title_t *dst, mpeg3_title_t *src) { int i; mpeg3_copy_fs(dst->fs, src->fs); dst->total_bytes = src->total_bytes; if(src->timecode_table_size) { dst->timecode_table_allocation = src->timecode_table_allocation; dst->timecode_table_size = src->timecode_table_size; dst->timecode_table = (mpeg3demux_timecode_t *) memoryAllocate(1, sizeof(mpeg3demux_timecode_t) * dst->timecode_table_allocation); for(i = 0; i < dst->timecode_table_size; i++) { dst->timecode_table[i] = src->timecode_table[i]; } } } int mpeg3_dump_title(mpeg3_title_t *title) { int i; for(i = 0; i < title->timecode_table_size; i++) { printf("%f: %d - %d %f %f %d\n", title->timecode_table[i].absolute_start_time, title->timecode_table[i].start_byte, title->timecode_table[i].end_byte, title->timecode_table[i].start_time, title->timecode_table[i].end_time, title->timecode_table[i].program); } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3title.h ================================================ #ifndef MPEG3TITLE_H #define MPEG3TITLE_H #include "mpeg3io.h" typedef struct { long start_byte; double start_time; double absolute_start_time; double absolute_end_time; long end_byte; double end_time; int program; } mpeg3demux_timecode_t; typedef struct { void *file; mpeg3_fs_t *fs; long total_bytes; /* Total bytes in file. Critical for seeking and length. */ /* Timecode table */ mpeg3demux_timecode_t *timecode_table; long timecode_table_size; /* Number of entries */ long timecode_table_allocation; /* Number of available slots */ } mpeg3_title_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3toc.c ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "libmpeg3.h" #include #include #ifdef MACINTOSH #include #else #include #endif int main(int argc, char *argv[]) { int i; /* FILE *output; */ char new_path[1024], *ext; struct stat st; long size; int timecode_search = 0; if(argc < 2) { fprintf(stderr, "Create a table of contents for a DVD.\n" " Usage: mpeg3toc [-t] ...\n" " -t Perform timecode search.\n" "\n" " The filenames should be absolute paths unless you plan\n" " to always run your movie player from the same directory\n" " as the filename. Alternatively you can edit the toc by\n" " hand.\n" " The timecode search allows XMovie to play the Matrix.\n" "Example: mpeg3toc /cd2/video_ts/vts_01_*.vob > titanic.toc\n"); exit(1); } for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-t")) { timecode_search = 1; } else { /* Get just name */ ext = strrchr(argv[i], '/'); if(ext) { ext++; strcpy(new_path, ext); } else strcpy(new_path, argv[i]); /* Replace suffix */ ext = strrchr(new_path, '.'); if(ext) { sprintf(ext, ".toc"); } else strcat(new_path, ".toc"); /* fprintf(stderr, "Creating %s\n", new_path); */ stat(argv[i], &st); size = (long)st.st_size; if(!size) { fprintf(stderr, "%s is 0 length. Skipping\n", new_path); } else { /* Just want the first title's streams */ if(mpeg3_generate_toc(stdout, argv[i], timecode_search, i == argc - 1)) { fprintf(stderr, "Skipping %s\n", argv[i]); } } } } } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3vtrack.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "libmpeg3.h" #include "mpeg3protos.h" #include mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, int stream_id, mpeg3_demuxer_t *demuxer) { int result = 0; mpeg3_vtrack_t *new_vtrack; new_vtrack = (mpeg3_vtrack_t *) memoryAllocate(1, sizeof(mpeg3_vtrack_t)); new_vtrack->demuxer = mpeg3_new_demuxer(file, 0, 1, stream_id); if(demuxer) mpeg3demux_copy_titles(new_vtrack->demuxer, demuxer); new_vtrack->current_position = 0; /* Get information about the track here. */ new_vtrack->video = mpeg3video_new(file, new_vtrack); if(!new_vtrack->video) { /* Failed */ mpeg3_delete_vtrack(file, new_vtrack); new_vtrack = 0; } return new_vtrack; } int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack) { if(vtrack->video) mpeg3video_delete(vtrack->video); if(vtrack->demuxer) mpeg3_delete_demuxer(vtrack->demuxer); memoryFree(vtrack); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/mpeg3vtrack.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef MPEG3_VTRACK_H #define MPEG3_VTRACK_H #include "mpeg3demux.h" #include "mpeg3video.h" typedef struct { int width; int height; float frame_rate; mpeg3_demuxer_t *demuxer; mpeg3video_t *video; long current_position; /* Number of next frame to be played */ long total_frames; /* Total frames in the file */ } mpeg3_vtrack_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/test.c ================================================ /* Lex's test program.... */ #include #include int main() { mpeg3_t *file; int width; int height; unsigned char buf[400][400] = { {0} }; unsigned char * rowPtrs[400]; int i; int iter; file = mpeg3_open("/home/lex/piper.closeup.mpg"); if(file == NULL) { printf("couldn't open file\n"); return 1; } width = mpeg3_video_width(file, 0); height = mpeg3_video_height(file, 0); printf("dimensions are: %d x %d\n", width, height); for(i=0; i<400; i++) rowPtrs[i] = buf[i]; printf("buf = "); for(i=0; i<8; i++) printf(" %d", buf[0][i]); printf("\n"); for(iter=0; iter<100; iter++) { printf("iter = %d\n", iter); mpeg3_read_frame(file, rowPtrs, 0, 0, width, height, width, height, MPEG3_RGBA8888, 0); printf("buf = "); for(i=0; i<8; i++) printf(" %d", buf[0][i]); printf("\n"); } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/testaudio.c ================================================ /* Lex's test program.... */ #include #include int main() { mpeg3_t *file; int width; int height; unsigned char buf[100000] = { 0 }; int i; int iter; file = mpeg3_open("/home/lex/mp3/bach/lilfug.mp3"); if(file == NULL) { printf("couldn't open file\n"); return 1; } printf("buf = "); for(i=0; i<8; i++) printf(" %d", buf[i]); printf("\n"); for(iter=0; iter<100; iter++) { printf("iter = %d\n", iter); mpeg3_read_audio(file, NULL, (short *) buf, 1, 1000, 0); printf("buf = "); for(i=0; i<8; i++) printf(" %d", buf[i]); printf("\n"); } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/timecode.h ================================================ #ifndef TIMECODE_H #define TIMECODE_H typedef struct { long hour; long minute; long second; long frame; } mpeg3_timecode_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/udump.c ================================================ #include "libmpeg3.h" #include #define BUFSIZE 10000000 int main(int argc, char *argv[]) { mpeg3_t *file; int i, result = 0; unsigned char *output, **output_rows; float *audio_output_f; short *audio_output_i; long total_samples = 0; if(argc < 2) { printf("Need an MPEG stream.\n"); exit(1); } file = mpeg3_open(argv[1]); if(file) { fprintf(stderr, "MMX supported %d\n", file->have_mmx); fprintf(stderr, "Audio streams: %d\n", mpeg3_total_astreams(file)); for(i = 0; i < mpeg3_total_astreams(file); i++) { fprintf(stderr, " Stream %d: channels %d sample rate %d total samples %ld\n", i, mpeg3_audio_channels(file, i), mpeg3_sample_rate(file, i), mpeg3_audio_samples(file, i)); } fprintf(stderr, "Video streams: %d\n", mpeg3_total_vstreams(file)); for(i = 0; i < mpeg3_total_vstreams(file); i++) { fprintf(stderr, " Stream %d: width %d height %d frame rate %0.3f total frames %ld\n", i, mpeg3_video_width(file, i), mpeg3_video_height(file, i), mpeg3_frame_rate(file, i), mpeg3_video_frames(file, i)); } mpeg3_set_cpus(file, 1); /* audio_output_f = malloc(BUFSIZE * sizeof(float)); */ audio_output_i = malloc(BUFSIZE * sizeof(short)); /* mpeg3_set_sample(file, 11229518, 0); */ /* result = mpeg3_read_audio(file, audio_output_f, 0, 0, BUFSIZE, 0); */ // result = mpeg3_read_audio(file, 0, audio_output_i, 1, BUFSIZE, 0); fwrite(audio_output_i, BUFSIZE, 1, stdout); output = malloc(mpeg3_video_width(file, 0) * mpeg3_video_height(file, 0) * 3 + 4); output_rows = malloc(sizeof(unsigned char*) * mpeg3_video_height(file, 0)); for(i = 0; i < mpeg3_video_height(file, 0); i++) output_rows[i] = &output[i * mpeg3_video_width(file, 0) * 3]; // mpeg3_set_frame(file, 1000, 0); result = mpeg3_read_frame(file, output_rows, 0, 0, mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), mpeg3_video_width(file, 0), mpeg3_video_height(file, 0), MPEG3_RGB888, 0); mpeg3_close(file); } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/getpicture.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3video.h" #include "vlc.h" #include #include #include int mpeg3video_get_cbp(mpeg3_slice_t *slice) { int code; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if((code = mpeg3slice_showbits9(slice_buffer)) >= 128) { code >>= 4; mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab0[code].len); return mpeg3_CBPtab0[code].val; } if(code >= 8) { code >>= 1; mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab1[code].len); return mpeg3_CBPtab1[code].val; } if(code < 1) { /* fprintf(stderr,"mpeg3video_get_cbp: invalid coded_block_pattern code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab2[code].len); return mpeg3_CBPtab2[code].val; } /* set block to zero */ int mpeg3video_clearblock(mpeg3_slice_t *slice, int comp, int size) { slice->sparse[comp] = 1; /* Compiler error */ /* * for(i = 0; i < size; i++) * { * bzero(slice->block[comp] + sizeof(short) * 64 * i, sizeof(short) * 64); * } */ if(size == 6) { bzero(slice->block[comp], sizeof(short) * 64 * 6); } else { memset(slice->block[comp], 0, sizeof(short) * 64 * size); } return 0; } static inline int mpeg3video_getdclum(mpeg3_slice_buffer_t *slice_buffer) { int code, size, val; /* decode length */ code = mpeg3slice_showbits5(slice_buffer); if(code < 31) { size = mpeg3_DClumtab0[code].val; mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab0[code].len); } else { code = mpeg3slice_showbits9(slice_buffer) - 0x1f0; size = mpeg3_DClumtab1[code].val; mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab1[code].len); } if(size == 0) val = 0; else { val = mpeg3slice_getbits(slice_buffer, size); if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; } return val; } int mpeg3video_getdcchrom(mpeg3_slice_buffer_t *slice_buffer) { int code, size, val; /* decode length */ code = mpeg3slice_showbits5(slice_buffer); if(code < 31) { size = mpeg3_DCchromtab0[code].val; mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab0[code].len); } else { code = mpeg3slice_showbits(slice_buffer, 10) - 0x3e0; size = mpeg3_DCchromtab1[code].val; mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab1[code].len); } if(size == 0) val = 0; else { val = mpeg3slice_getbits(slice_buffer, size); if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; } return val; } /* decode one intra coded MPEG-1 block */ int mpeg3video_getintrablock(mpeg3_slice_t *slice, mpeg3video_t *video, int comp, int dc_dct_pred[]) { int val, i, j=0, sign; unsigned int code; mpeg3_DCTtab_t *tab = 0; short *bp = slice->block[comp]; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; /* decode DC coefficients */ if(comp < 4) bp[0] = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)) << 3; else if(comp == 4) bp[0] = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)) << 3; else bp[0] = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)) << 3; #ifdef HAVE_MMX if(video->have_mmx) bp[0] <<= 4; #endif if(slice->fault) return 1; /* decode AC coefficients */ for(i = 1; ; i++) { code = mpeg3slice_showbits16(slice_buffer); if(code >= 16384) tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; else if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; else if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; else if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; else if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; else if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; else if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; else if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; else { /* fprintf(stderr, "mpeg3video_getintrablock: invalid Huffman code\n"); */ slice->fault = 1; return; } mpeg3slice_flushbits(slice_buffer, tab->len); if(tab->run == 64) break; /* end_of_block */ if(tab->run == 65) { /* escape */ i += mpeg3slice_getbits(slice_buffer, 6); if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) val = mpeg3slice_getbits(slice_buffer, 8); else if(val == 128) val = mpeg3slice_getbits(slice_buffer, 8) - 256; else if(val > 128) val -= 256; if((sign = (val < 0)) != 0) val= -val; } else { i += tab->run; val = tab->level; sign = mpeg3slice_getbit(slice_buffer); } if(i < 64) j = video->mpeg3_zigzag_scan_table[i]; else { slice->fault = 1; return; } #ifdef HAVE_MMX if(video->have_mmx) { val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) << 1; val = (val - 16) | 16; } else #endif { val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) >> 3; val = (val - 1) | 1; } bp[j] = sign ? -val : val; } if(j != 0) { /* not a sparse matrix ! */ slice->sparse[comp] = 0; } return 0; } /* decode one non-intra coded MPEG-1 block */ int mpeg3video_getinterblock(mpeg3_slice_t *slice, mpeg3video_t *video, int comp) { int val, i, j=0, sign; unsigned int code; mpeg3_DCTtab_t *tab; short *bp = slice->block[comp]; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; /* decode AC coefficients */ for(i = 0; ; i++) { code = mpeg3slice_showbits16(slice_buffer); if(code >= 16384) { if(i == 0) tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; else tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; } else if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; else if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; else if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; else if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; else if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; else if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; else if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; else { // invalid Huffman code slice->fault = 1; return 1; } mpeg3slice_flushbits(slice_buffer, tab->len); /* end of block */ if(tab->run == 64) break; if(tab->run == 65) { /* escape */ i += mpeg3slice_getbits(slice_buffer, 6); if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) val = mpeg3slice_getbits(slice_buffer, 8); else if(val == 128) val = mpeg3slice_getbits(slice_buffer, 8) - 256; else if(val > 128) val -= 256; if((sign = (val < 0)) != 0) val = -val; } else { i += tab->run; val = tab->level; sign = mpeg3slice_getbit(slice_buffer); } j = video->mpeg3_zigzag_scan_table[i]; #ifdef HAVE_MMX if(video->have_mmx) { val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]); val = (val - 16) | 16; } else #endif { val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]) >> 4; val = (val - 1) | 1; } bp[j] = sign ? -val : val; } if(j != 0) { /* not a sparse matrix ! */ slice->sparse[comp] = 0; } return 0; } /* decode one intra coded MPEG-2 block */ int mpeg3video_getmpg2intrablock(mpeg3_slice_t *slice, mpeg3video_t *video, int comp, int dc_dct_pred[]) { int val, i, j=0, sign, nc; unsigned int code; mpeg3_DCTtab_t *tab; short *bp; int *qmat; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; /* with data partitioning, data always goes to base layer */ bp = slice->block[comp]; qmat = (comp < 4 || video->chroma_format == CHROMA420) ? video->intra_quantizer_matrix : video->chroma_intra_quantizer_matrix; /* decode DC coefficients */ if(comp < 4) val = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)); else if((comp & 1) == 0) val = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)); else val = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)); if(slice->fault) return; #ifdef HAVE_MMX if(video->have_mmx) bp[0] = val << (7 - video->dc_prec); else #endif bp[0] = val << (3 - video->dc_prec); nc = 0; /* decode AC coefficients */ for(i = 1; ; i++) { code = mpeg3slice_showbits16(slice_buffer); if(code >= 16384 && !video->intravlc) tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; else if(code >= 1024) { if(video->intravlc) tab = &mpeg3_DCTtab0a[(code >> 8) - 4]; else tab = &mpeg3_DCTtab0[(code >> 8) - 4]; } else if(code >= 512) { if(video->intravlc) tab = &mpeg3_DCTtab1a[(code >> 6) - 8]; else tab = &mpeg3_DCTtab1[(code >> 6) - 8]; } else if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; else if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; else if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; else if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; else if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; else { /* fprintf(stderr,"mpeg3video_getmpg2intrablock: invalid Huffman code\n"); */ slice->fault = 1; return 1; } mpeg3slice_flushbits(slice_buffer, tab->len); /* end_of_block */ if(tab->run == 64) break; if(tab->run == 65) { /* escape */ i += mpeg3slice_getbits(slice_buffer, 6); val = mpeg3slice_getbits(slice_buffer, 12); if((val & 2047) == 0) { // invalid signed_level (escape) slice->fault = 1; return; } if((sign = (val >= 2048)) != 0) val = 4096 - val; } else { i += tab->run; val = tab->level; sign = mpeg3slice_getbit(slice_buffer); } j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; #ifdef HAVE_MMX if(video->have_mmx) val = (val * slice->quant_scale * qmat[j]); else #endif val = (val * slice->quant_scale * qmat[j]) >> 4; bp[j] = sign ? -val : val; nc++; } if(j != 0) { /* not a sparse matrix ! */ slice->sparse[comp] = 0; } return 1; } /* decode one non-intra coded MPEG-2 block */ int mpeg3video_getmpg2interblock(mpeg3_slice_t *slice, mpeg3video_t *video, int comp) { int val, i, j=0, sign, nc; unsigned int code; mpeg3_DCTtab_t *tab; short *bp; int *qmat; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; /* with data partitioning, data always goes to base layer */ bp = slice->block[comp]; qmat = (comp < 4 || video->chroma_format == CHROMA420) ? video->non_intra_quantizer_matrix : video->chroma_non_intra_quantizer_matrix; nc = 0; /* decode AC coefficients */ for(i = 0; ; i++) { code = mpeg3slice_showbits16(slice_buffer); if(code >= 16384) { if(i == 0) tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; else tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; } else if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; else if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; else if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; else if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; else if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; else if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; else if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; else { // invalid Huffman code slice->fault = 1; return; } mpeg3slice_flushbits(slice_buffer, tab->len); /* end_of_block */ if(tab->run == 64) break; if(tab->run == 65) { /* escape */ i += mpeg3slice_getbits(slice_buffer, 6); val = mpeg3slice_getbits(slice_buffer, 12); if((val & 2047) == 0) { /* fprintf(stderr, "mpeg3video_getmpg2interblock: invalid signed_level (escape)\n"); */ slice->fault = 1; return 1; } if((sign = (val >= 2048)) != 0) val = 4096 - val; } else { i += tab->run; val = tab->level; sign = mpeg3slice_getbit(slice_buffer); } j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; #ifdef HAVE_MMX if(video->have_mmx) val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 1; else #endif val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 5; bp[j] = sign ? (-val) : val ; nc++; } if(j != 0) { slice->sparse[comp] = 0; } return 0; } /* decode all macroblocks of the current picture */ int mpeg3video_get_macroblocks(mpeg3video_t *video, int framenum) { unsigned int code; mpeg3_slice_buffer_t *slice_buffer; /* Buffer being loaded */ int i; int current_buffer; mpeg3_bits_t *vstream = video->vstream; /* Load every slice into a buffer array */ video->total_slice_buffers = 0; current_buffer = 0; while(!mpeg3bits_eof(vstream) && mpeg3bits_showbits32_noptr(vstream) >= MPEG3_SLICE_MIN_START && mpeg3bits_showbits32_noptr(vstream) <= MPEG3_SLICE_MAX_START) { /* Initialize the buffer */ if(current_buffer >= video->slice_buffers_initialized) mpeg3_new_slice_buffer(&(video->slice_buffers[video->slice_buffers_initialized++])); slice_buffer = &(video->slice_buffers[current_buffer]); slice_buffer->buffer_size = 0; slice_buffer->current_position = 0; slice_buffer->bits_size = 0; slice_buffer->done = 0; /* Read the slice into the buffer including the slice start code */ do { /* Expand buffer */ if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size) mpeg3_expand_slice_buffer(slice_buffer); /* Load 1 char into buffer */ slice_buffer->data[slice_buffer->buffer_size++] = mpeg3bits_getbyte_noptr(vstream); }while(!mpeg3bits_eof(vstream) && mpeg3bits_showbits24_noptr(vstream) != MPEG3_PACKET_START_CODE_PREFIX); /* Pad the buffer to get the last macroblock */ if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size + 4) mpeg3_expand_slice_buffer(slice_buffer); slice_buffer->data[slice_buffer->buffer_size++] = 0; slice_buffer->data[slice_buffer->buffer_size++] = 0; slice_buffer->data[slice_buffer->buffer_size++] = 1; slice_buffer->data[slice_buffer->buffer_size++] = 0; slice_buffer->bits_size = 0; #ifdef USE_PTHREADS pthread_mutex_lock(&(slice_buffer->completion_lock)); #endif fflush(stdout); current_buffer++; video->total_slice_buffers++; } /* Run the slice decoders */ if(video->total_slice_buffers > 0) { for(i = 0; i < video->total_slice_decoders; i++) { if(i == 0 && video->total_slice_decoders > 1) { video->slice_decoders[i].current_buffer = 0; video->slice_decoders[i].buffer_step = 1; video->slice_decoders[i].last_buffer = (video->total_slice_buffers - 1); } else if(i == 1) { video->slice_decoders[i].current_buffer = video->total_slice_buffers - 1; video->slice_decoders[i].buffer_step = -1; video->slice_decoders[i].last_buffer = 0; } else { video->slice_decoders[i].current_buffer = i; video->slice_decoders[i].buffer_step = 1; video->slice_decoders[i].last_buffer = video->total_slice_buffers - 1; } #ifdef USE_PTHREADS pthread_mutex_unlock(&(video->slice_decoders[i].input_lock)); #endif } } /* Wait for the slice decoders to finish */ if(video->total_slice_buffers > 0) { #ifdef USE_PTHREADS for(i = 0; i < video->total_slice_buffers; i++) { pthread_mutex_lock(&(video->slice_buffers[i].completion_lock)); pthread_mutex_unlock(&(video->slice_buffers[i].completion_lock)); #else for(i = 0; i < video->total_slice_decoders; i++) { mpeg3_slice_loop(&video->slice_decoders[i]); #endif } } return 0; } int mpeg3video_allocate_decoders(mpeg3video_t *video, int decoder_count) { int i; mpeg3_t *file = (mpeg3_t *) video->file; /* Get the slice decoders */ if(video->total_slice_decoders != file->cpus) { for(i = 0; i < video->total_slice_decoders; i++) { mpeg3_delete_slice_decoder(video->slice_decoders[i]); } for(i = 0; i < file->cpus && i < MPEG3_MAX_CPUS; i++) { mpeg3_new_slice_decoder(video, &(video->slice_decoders[i])); video->slice_decoders[i].thread_number = i; } video->total_slice_decoders = file->cpus; } return 0; } /* decode one frame or field picture */ int mpeg3video_getpicture(mpeg3video_t *video, int framenum) { int i, result = 0; mpeg3_t *file = (mpeg3_t *) video->file; if(video->pict_struct == FRAME_PICTURE && video->secondfield) { /* recover from illegal number of field pictures */ video->secondfield = 0; } if(!video->mpeg2) { video->current_repeat = video->repeat_count = 0; } mpeg3video_allocate_decoders(video, file->cpus); for(i = 0; i < 3; i++) { if(video->pict_type == B_TYPE) { video->newframe[i] = video->auxframe[i]; } else { if(!video->secondfield && !video->current_repeat) { /* Swap refframes for I frames */ unsigned char* tmp = video->oldrefframe[i]; video->oldrefframe[i] = video->refframe[i]; video->refframe[i] = tmp; } video->newframe[i] = video->refframe[i]; } if(video->pict_struct == BOTTOM_FIELD) { /* Only used if fields are in different pictures */ video->newframe[i] += (i == 0) ? video->coded_picture_width : video->chrom_width; } } /* The problem is when a B frame lands on the first repeat and is skipped, */ /* the second repeat goes for the same bitmap as the skipped repeat, */ /* so it picks up a frame from 3 frames back. */ /* The first repeat must consititutively read a B frame if its B frame is going to be */ /* used in a later repeat. */ if(!video->current_repeat) if(!(video->skip_bframes && video->pict_type == B_TYPE) || (video->repeat_count >= 100 + 100 * video->skip_bframes)) result = mpeg3video_get_macroblocks(video, framenum); /* Set the frame to display */ video->output_src = 0; if(framenum > -1 && !result) { if(video->pict_struct == FRAME_PICTURE || video->secondfield) { if(video->pict_type == B_TYPE) { video->output_src = video->auxframe; } else { video->output_src = video->oldrefframe; } } else { mpeg3video_display_second_field(video); } } if(video->mpeg2) { video->current_repeat += 100; } if(video->pict_struct != FRAME_PICTURE) video->secondfield = !video->secondfield; return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/headers.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3demux.h" #include "mpeg3private.h" #include "mpeg3video.h" #include #include int mpeg3video_getseqhdr(mpeg3video_t *video) { int i; mpeg3_t *file = (mpeg3_t *) video->file; int aspect_ratio, picture_rate, vbv_buffer_size; int constrained_parameters_flag; int load_intra_quantizer_matrix, load_non_intra_quantizer_matrix; video->horizontal_size = mpeg3bits_getbits(video->vstream, 12); video->vertical_size = mpeg3bits_getbits(video->vstream, 12); aspect_ratio = mpeg3bits_getbits(video->vstream, 4); video->framerate_code = mpeg3bits_getbits(video->vstream, 4); video->bitrate = mpeg3bits_getbits(video->vstream, 18); mpeg3bits_getbit_noptr(video->vstream); /* marker bit (=1) */ vbv_buffer_size = mpeg3bits_getbits(video->vstream, 10); constrained_parameters_flag = mpeg3bits_getbit_noptr(video->vstream); video->frame_rate = mpeg3_frame_rate_table[video->framerate_code]; load_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); if(load_intra_quantizer_matrix) { for(i = 0; i < 64; i++) video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } else { for(i = 0; i < 64; i++) video->intra_quantizer_matrix[i] = mpeg3_default_intra_quantizer_matrix[i]; } load_non_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); if(load_non_intra_quantizer_matrix) { for(i = 0; i < 64; i++) video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } else { for(i = 0; i < 64; i++) video->non_intra_quantizer_matrix[i] = 16; } /* copy luminance to chrominance matrices */ for(i = 0; i < 64; i++) { video->chroma_intra_quantizer_matrix[i] = video->intra_quantizer_matrix[i]; video->chroma_non_intra_quantizer_matrix[i] = video->non_intra_quantizer_matrix[i]; } return 0; } /* decode sequence extension */ int mpeg3video_sequence_extension(mpeg3video_t *video) { int prof_lev; int horizontal_size_extension, vertical_size_extension; int bit_rate_extension, vbv_buffer_size_extension, low_delay; int frame_rate_extension_n, frame_rate_extension_d; int pos = 0; video->mpeg2 = 1; video->scalable_mode = SC_NONE; /* unless overwritten by seq. scal. ext. */ prof_lev = mpeg3bits_getbyte_noptr(video->vstream); video->prog_seq = mpeg3bits_getbit_noptr(video->vstream); video->chroma_format = mpeg3bits_getbits(video->vstream, 2); horizontal_size_extension = mpeg3bits_getbits(video->vstream, 2); vertical_size_extension = mpeg3bits_getbits(video->vstream, 2); bit_rate_extension = mpeg3bits_getbits(video->vstream, 12); mpeg3bits_getbit_noptr(video->vstream); vbv_buffer_size_extension = mpeg3bits_getbyte_noptr(video->vstream); low_delay = mpeg3bits_getbit_noptr(video->vstream); frame_rate_extension_n = mpeg3bits_getbits(video->vstream, 2); frame_rate_extension_d = mpeg3bits_getbits(video->vstream, 5); video->horizontal_size = (horizontal_size_extension << 12) | (video->horizontal_size & 0x0fff); video->vertical_size = (vertical_size_extension << 12) | (video->vertical_size & 0x0fff); } /* decode sequence display extension */ int mpeg3video_sequence_display_extension(mpeg3video_t *video) { int colour_primaries = 0, transfer_characteristics = 0; int display_horizontal_size, display_vertical_size; int pos = 0; int video_format = mpeg3bits_getbits(video->vstream, 3); int colour_description = mpeg3bits_getbit_noptr(video->vstream); if(colour_description) { colour_primaries = mpeg3bits_getbyte_noptr(video->vstream); transfer_characteristics = mpeg3bits_getbyte_noptr(video->vstream); video->matrix_coefficients = mpeg3bits_getbyte_noptr(video->vstream); } display_horizontal_size = mpeg3bits_getbits(video->vstream, 14); mpeg3bits_getbit_noptr(video->vstream); display_vertical_size = mpeg3bits_getbits(video->vstream, 14); } /* decode quant matrix entension */ int mpeg3video_quant_matrix_extension(mpeg3video_t *video) { int i; int load_intra_quantiser_matrix, load_non_intra_quantiser_matrix; int load_chroma_intra_quantiser_matrix; int load_chroma_non_intra_quantiser_matrix; int pos = 0; if((load_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) { for(i = 0; i < 64; i++) { video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } } if((load_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) { for (i = 0; i < 64; i++) { video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } } if((load_chroma_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) { for(i = 0; i < 64; i++) video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } if((load_chroma_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) { for(i = 0; i < 64; i++) video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); } } /* decode sequence scalable extension */ int mpeg3video_sequence_scalable_extension(mpeg3video_t *video) { int layer_id; video->scalable_mode = mpeg3bits_getbits(video->vstream, 2) + 1; /* add 1 to make SC_DP != SC_NONE */ layer_id = mpeg3bits_getbits(video->vstream, 4); if(video->scalable_mode == SC_SPAT) { video->llw = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_horizontal_size */ mpeg3bits_getbit_noptr(video->vstream); video->llh = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_vertical_size */ video->hm = mpeg3bits_getbits(video->vstream, 5); video->hn = mpeg3bits_getbits(video->vstream, 5); video->vm = mpeg3bits_getbits(video->vstream, 5); video->vn = mpeg3bits_getbits(video->vstream, 5); } if(video->scalable_mode == SC_TEMP) fprintf(stderr, "mpeg3video_sequence_scalable_extension: temporal scalability not implemented\n"); } /* decode picture display extension */ int mpeg3video_picture_display_extension(mpeg3video_t *video) { int n, i; short frame_centre_horizontal_offset[3]; short frame_centre_vertical_offset[3]; if(video->prog_seq || video->pict_struct != FRAME_PICTURE) n = 1; else n = video->repeatfirst ? 3 : 2; for(i = 0; i < n; i++) { frame_centre_horizontal_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); mpeg3bits_getbit_noptr(video->vstream); frame_centre_vertical_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); mpeg3bits_getbit_noptr(video->vstream); } } /* decode picture coding extension */ int mpeg3video_picture_coding_extension(mpeg3video_t *video) { int chroma_420_type, composite_display_flag; int v_axis = 0, field_sequence = 0, sub_carrier = 0, burst_amplitude = 0, sub_carrier_phase = 0; video->h_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; video->v_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; video->h_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; video->v_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; video->dc_prec = mpeg3bits_getbits(video->vstream, 2); video->pict_struct = mpeg3bits_getbits(video->vstream, 2); video->topfirst = mpeg3bits_getbit_noptr(video->vstream); video->frame_pred_dct = mpeg3bits_getbit_noptr(video->vstream); video->conceal_mv = mpeg3bits_getbit_noptr(video->vstream); video->qscale_type = mpeg3bits_getbit_noptr(video->vstream); video->intravlc = mpeg3bits_getbit_noptr(video->vstream); video->altscan = mpeg3bits_getbit_noptr(video->vstream); video->repeatfirst = mpeg3bits_getbit_noptr(video->vstream); chroma_420_type = mpeg3bits_getbit_noptr(video->vstream); video->prog_frame = mpeg3bits_getbit_noptr(video->vstream); if(video->repeat_count > 100) video->repeat_count = 0; video->repeat_count += 100; video->current_repeat = 0; if(video->prog_seq) { if(video->repeatfirst) { if(video->topfirst) video->repeat_count += 200; else video->repeat_count += 100; } } else if(video->prog_frame) { if(video->repeatfirst) { video->repeat_count += 50; } } /*printf("mpeg3video_picture_coding_extension %d\n", video->repeat_count); */ composite_display_flag = mpeg3bits_getbit_noptr(video->vstream); if(composite_display_flag) { v_axis = mpeg3bits_getbit_noptr(video->vstream); field_sequence = mpeg3bits_getbits(video->vstream, 3); sub_carrier = mpeg3bits_getbit_noptr(video->vstream); burst_amplitude = mpeg3bits_getbits(video->vstream, 7); sub_carrier_phase = mpeg3bits_getbyte_noptr(video->vstream); } } /* decode picture spatial scalable extension */ int mpeg3video_picture_spatial_scalable_extension(mpeg3video_t *video) { video->pict_scal = 1; /* use spatial scalability in this picture */ video->lltempref = mpeg3bits_getbits(video->vstream, 10); mpeg3bits_getbit_noptr(video->vstream); video->llx0 = mpeg3bits_getbits(video->vstream, 15); if(video->llx0 >= 16384) video->llx0 -= 32768; mpeg3bits_getbit_noptr(video->vstream); video->lly0 = mpeg3bits_getbits(video->vstream, 15); if(video->lly0 >= 16384) video->lly0 -= 32768; video->stwc_table_index = mpeg3bits_getbits(video->vstream, 2); video->llprog_frame = mpeg3bits_getbit_noptr(video->vstream); video->llfieldsel = mpeg3bits_getbit_noptr(video->vstream); } /* decode picture temporal scalable extension * * not implemented * */ int mpeg3video_picture_temporal_scalable_extension(mpeg3video_t *video) { fprintf(stderr, "mpeg3video_picture_temporal_scalable_extension: temporal scalability not supported\n"); } /* decode extension and user data */ int mpeg3video_ext_user_data(mpeg3video_t *video) { int code = mpeg3bits_next_startcode(video->vstream); while(code == MPEG3_EXT_START_CODE || code == MPEG3_USER_START_CODE && !mpeg3bits_eof(video->vstream)) { mpeg3bits_refill(video->vstream); if(code == MPEG3_EXT_START_CODE) { int ext_id = mpeg3bits_getbits(video->vstream, 4); switch(ext_id) { case SEQ_ID: mpeg3video_sequence_extension(video); break; case DISP_ID: mpeg3video_sequence_display_extension(video); break; case QUANT_ID: mpeg3video_quant_matrix_extension(video); break; case SEQSCAL_ID: mpeg3video_sequence_scalable_extension(video); break; case PANSCAN_ID: mpeg3video_picture_display_extension(video); break; case CODING_ID: mpeg3video_picture_coding_extension(video); break; case SPATSCAL_ID: mpeg3video_picture_spatial_scalable_extension(video); break; case TEMPSCAL_ID: mpeg3video_picture_temporal_scalable_extension(video); break; default: fprintf(stderr,"mpeg3video_ext_user_data: reserved extension start code ID %d\n", ext_id); break; } } code = mpeg3bits_next_startcode(video->vstream); } } /* decode group of pictures header */ int mpeg3video_getgophdr(mpeg3video_t *video) { int drop_flag, closed_gop, broken_link; drop_flag = mpeg3bits_getbit_noptr(video->vstream); video->gop_timecode.hour = mpeg3bits_getbits(video->vstream, 5); video->gop_timecode.minute = mpeg3bits_getbits(video->vstream, 6); mpeg3bits_getbit_noptr(video->vstream); video->gop_timecode.second = mpeg3bits_getbits(video->vstream, 6); video->gop_timecode.frame = mpeg3bits_getbits(video->vstream, 6); closed_gop = mpeg3bits_getbit_noptr(video->vstream); broken_link = mpeg3bits_getbit_noptr(video->vstream); /* * printf("%d:%d:%d:%d %d %d %d\n", video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, * drop_flag, closed_gop, broken_link); */ return mpeg3bits_error(video->vstream); } /* decode picture header */ int mpeg3video_getpicturehdr(mpeg3video_t *video) { int temp_ref, vbv_delay; video->pict_scal = 0; /* unless overwritten by pict. spat. scal. ext. */ temp_ref = mpeg3bits_getbits(video->vstream, 10); video->pict_type = mpeg3bits_getbits(video->vstream, 3); vbv_delay = mpeg3bits_getbits(video->vstream, 16); if(video->pict_type == P_TYPE || video->pict_type == B_TYPE) { video->full_forw = mpeg3bits_getbit_noptr(video->vstream); video->forw_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; } if(video->pict_type == B_TYPE) { video->full_back = mpeg3bits_getbit_noptr(video->vstream); video->back_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; } /* get extra bit picture */ while(mpeg3bits_getbit_noptr(video->vstream) && !mpeg3bits_eof(video->vstream)) mpeg3bits_getbyte_noptr(video->vstream); return 0; } int mpeg3video_get_header(mpeg3video_t *video, int dont_repeat) { unsigned int code; /* a sequence header should be found before returning from `getheader' the */ /* first time (this is to set horizontal/vertical size properly) */ /* Repeat the frame until it's less than 1 count from repeat_count */ if(video->repeat_count - video->current_repeat >= 100 && !dont_repeat) { return 0; } if(dont_repeat) { video->repeat_count = 0; video->current_repeat = 0; } else video->repeat_count -= video->current_repeat; while(1) { /* look for startcode */ code = mpeg3bits_next_startcode(video->vstream); if(mpeg3bits_eof(video->vstream)) return 1; if(code != MPEG3_SEQUENCE_END_CODE) mpeg3bits_refill(video->vstream); switch(code) { case MPEG3_SEQUENCE_START_CODE: video->found_seqhdr = 1; mpeg3video_getseqhdr(video); mpeg3video_ext_user_data(video); break; case MPEG3_GOP_START_CODE: mpeg3video_getgophdr(video); mpeg3video_ext_user_data(video); break; case MPEG3_PICTURE_START_CODE: mpeg3video_getpicturehdr(video); mpeg3video_ext_user_data(video); if(video->found_seqhdr) return 0; /* Exit here */ break; case MPEG3_SEQUENCE_END_CODE: // Continue until the end mpeg3bits_refill(video->vstream); break; default: break; } } return 1; /* Shouldn't be reached. */ } int mpeg3video_ext_bit_info(mpeg3_slice_buffer_t *slice_buffer) { while(mpeg3slice_getbit(slice_buffer)) mpeg3slice_getbyte(slice_buffer); return 0; } /* decode slice header */ int mpeg3video_getslicehdr(mpeg3_slice_t *slice, mpeg3video_t *video) { int slice_vertical_position_extension, intra_slice; int qs; slice_vertical_position_extension = (video->mpeg2 && video->vertical_size > 2800) ? mpeg3slice_getbits(slice->slice_buffer, 3) : 0; if(video->scalable_mode == SC_DP) slice->pri_brk = mpeg3slice_getbits(slice->slice_buffer, 7); qs = mpeg3slice_getbits(slice->slice_buffer, 5); slice->quant_scale = video->mpeg2 ? (video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1)) : qs; if(mpeg3slice_getbit(slice->slice_buffer)) { intra_slice = mpeg3slice_getbit(slice->slice_buffer); mpeg3slice_getbits(slice->slice_buffer, 7); mpeg3video_ext_bit_info(slice->slice_buffer); } else intra_slice = 0; return slice_vertical_position_extension; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/idct.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "idct.h" #include #ifdef _MSC_VER /* inline is unrecognized keyword in C mode of MSVC */ #define inline __inline #endif /**********************************************************/ /* inverse two dimensional DCT, Chen-Wang algorithm */ /* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */ /* 32-bit integer arithmetic (8 bit coefficients) */ /* 11 mults, 29 adds per DCT */ /* sE, 18.8.91 */ /**********************************************************/ /* coefficients extended to 12 bit for IEEE1180-1990 */ /* compliance sE, 2.1.94 */ /**********************************************************/ /* this code assumes >> to be a two's-complement arithmetic */ /* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */ #define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */ #define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */ #define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */ #define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */ #define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */ #define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */ /* row (horizontal) IDCT * * 7 pi 1 * dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l ) * l=0 8 2 * * where: c[0] = 128 * c[1..7] = 128*sqrt(2) */ inline int mpeg3video_idctrow(short *blk) { int x0, x1, x2, x3, x4, x5, x6, x7, x8; /* shortcut */ if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) | (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) { blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3; return; } x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */ /* first stage */ x8 = W7*(x4+x5); x4 = x8 + (W1-W7)*x4; x5 = x8 - (W1+W7)*x5; x8 = W3*(x6+x7); x6 = x8 - (W3-W5)*x6; x7 = x8 - (W3+W5)*x7; /* second stage */ x8 = x0 + x1; x0 -= x1; x1 = W6*(x3+x2); x2 = x1 - (W2+W6)*x2; x3 = x1 + (W2-W6)*x3; x1 = x4 + x6; x4 -= x6; x6 = x5 + x7; x5 -= x7; /* third stage */ x7 = x8 + x3; x8 -= x3; x3 = x0 + x2; x0 -= x2; x2 = (181*(x4+x5)+128)>>8; x4 = (181*(x4-x5)+128)>>8; /* fourth stage */ blk[0] = (x7+x1)>>8; blk[1] = (x3+x2)>>8; blk[2] = (x0+x4)>>8; blk[3] = (x8+x6)>>8; blk[4] = (x8-x6)>>8; blk[5] = (x0-x4)>>8; blk[6] = (x3-x2)>>8; blk[7] = (x7-x1)>>8; } /* column (vertical) IDCT * * 7 pi 1 * dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l ) * l=0 8 2 * * where: c[0] = 1/1024 * c[1..7] = (1/1024)*sqrt(2) */ inline int mpeg3video_idctcol(short *blk) { int x0, x1, x2, x3, x4, x5, x6, x7, x8; /* shortcut */ if (!((x1 = (blk[8 * 4]<<8)) | (x2 = blk[8 * 6]) | (x3 = blk[8 * 2]) | (x4 = blk[8*1]) | (x5 = blk[8 * 7]) | (x6 = blk[8 * 5]) | (x7 = blk[8 * 3]))){ blk[8*0]=blk[8*1]=blk[8 * 2]=blk[8 * 3]=blk[8 * 4]=blk[8 * 5]=blk[8 * 6]=blk[8 * 7]= (blk[8*0]+32)>>6; return; } x0 = (blk[8*0]<<8) + 8192; /* first stage */ x8 = W7*(x4+x5) + 4; x4 = (x8+(W1-W7)*x4)>>3; x5 = (x8-(W1+W7)*x5)>>3; x8 = W3*(x6+x7) + 4; x6 = (x8-(W3-W5)*x6)>>3; x7 = (x8-(W3+W5)*x7)>>3; /* second stage */ x8 = x0 + x1; x0 -= x1; x1 = W6*(x3+x2) + 4; x2 = (x1-(W2+W6)*x2)>>3; x3 = (x1+(W2-W6)*x3)>>3; x1 = x4 + x6; x4 -= x6; x6 = x5 + x7; x5 -= x7; /* third stage */ x7 = x8 + x3; x8 -= x3; x3 = x0 + x2; x0 -= x2; x2 = (181 * (x4 + x5) + 128) >> 8; x4 = (181 * (x4 - x5) + 128) >> 8; /* fourth stage */ blk[8 * 0] = (x7 + x1) >> 14; blk[8 * 1] = (x3 + x2) >> 14; blk[8 * 2] = (x0 + x4) >> 14; blk[8 * 3] = (x8 + x6) >> 14; blk[8 * 4] = (x8 - x6) >> 14; blk[8 * 5] = (x0 - x4) >> 14; blk[8 * 6] = (x3 - x2) >> 14; blk[8 * 7] = (x7 - x1) >> 14; } /* two dimensional inverse discrete cosine transform */ void mpeg3video_idct_conversion(short* block) { int i; for(i = 0; i < 8; i++) mpeg3video_idctrow(block + 8 * i); for(i = 0; i < 8; i++) mpeg3video_idctcol(block + i); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/idct.h ================================================ #ifndef IDCT_H #define IDCT_H #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/layerdata.h ================================================ #ifndef LAYERDATA_H #define LAYERDATA_H typedef struct { /* sequence header */ int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; int mpeg2; int qscale_type, altscan; /* picture coding extension */ int pict_scal; /* picture spatial scalable extension */ int scalable_mode; /* sequence scalable extension */ } mpeg3_layerdata_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/macroblocks.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3video.h" #include "slice.h" #include "vlc.h" #include int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice) { int code, val = 0; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; while((code = mpeg3slice_showbits(slice_buffer, 11)) < 24) { /* Is not macroblock_stuffing */ if(code != 15) { /* Is macroblock_escape */ if(code == 8) { val += 33; } else { /* fprintf(stderr, "mpeg3video_get_macroblock_address: invalid macroblock_address_increment code\n"); */ slice->fault = 1; return 1; } } mpeg3slice_flushbits(slice_buffer, 11); } if(code >= 1024) { mpeg3slice_flushbit(slice_buffer); return val + 1; } if(code >= 128) { code >>= 6; mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab1[code].len); return val + mpeg3_MBAtab1[code].val; } code -= 24; mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab2[code].len); return val + mpeg3_MBAtab2[code].val; } /* macroblock_type for pictures with spatial scalability */ static inline int mpeg3video_getsp_imb_type(mpeg3_slice_t *slice) { mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; unsigned int code = mpeg3slice_showbits(slice_buffer, 4); if(!code) { /* fprintf(stderr,"mpeg3video_getsp_imb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, mpeg3_spIMBtab[code].len); return mpeg3_spIMBtab[code].val; } static inline int mpeg3video_getsp_pmb_type(mpeg3_slice_t *slice) { mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; int code = mpeg3slice_showbits(slice_buffer, 7); if(code < 2) { /* fprintf(stderr,"mpeg3video_getsp_pmb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } if(code >= 16) { code >>= 3; mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab0[code].len); return mpeg3_spPMBtab0[code].val; } mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab1[code].len); return mpeg3_spPMBtab1[code].val; } static inline int mpeg3video_getsp_bmb_type(mpeg3_slice_t *slice) { mpeg3_VLCtab_t *p; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; int code = mpeg3slice_showbits9(slice_buffer); if(code >= 64) p = &mpeg3_spBMBtab0[(code >> 5) - 2]; else if(code >= 16) p = &mpeg3_spBMBtab1[(code >> 2) - 4]; else if(code >= 8) p = &mpeg3_spBMBtab2[code - 8]; else { /* fprintf(stderr,"mpeg3video_getsp_bmb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, p->len); return p->val; } static inline int mpeg3video_get_imb_type(mpeg3_slice_t *slice) { mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if(mpeg3slice_getbit(slice_buffer)) { return 1; } if(!mpeg3slice_getbit(slice_buffer)) { /* fprintf(stderr,"mpeg3video_get_imb_type: invalid macroblock_type code\n"); */ slice->fault = 1; } return 17; } static inline int mpeg3video_get_pmb_type(mpeg3_slice_t *slice) { int code; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) { code >>= 3; mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab0[code].len); return mpeg3_PMBtab0[code].val; } if(code == 0) { /* fprintf(stderr,"mpeg3video_get_pmb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab1[code].len); return mpeg3_PMBtab1[code].val; } static inline int mpeg3video_get_bmb_type(mpeg3_slice_t *slice) { int code; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) { code >>= 2; mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab0[code].len); return mpeg3_BMBtab0[code].val; } if(code == 0) { /* fprintf(stderr,"mpeg3video_get_bmb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab1[code].len); return mpeg3_BMBtab1[code].val; } static inline int mpeg3video_get_dmb_type(mpeg3_slice_t *slice) { if(!mpeg3slice_getbit(slice->slice_buffer)) { /* fprintf(stderr,"mpeg3video_get_dmb_type: invalid macroblock_type code\n"); */ slice->fault=1; } return 1; } static inline int mpeg3video_get_snrmb_type(mpeg3_slice_t *slice) { mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; int code = mpeg3slice_showbits(slice_buffer, 3); if(code == 0) { /* fprintf(stderr,"mpeg3video_get_snrmb_type: invalid macroblock_type code\n"); */ slice->fault = 1; return 0; } mpeg3slice_flushbits(slice_buffer, mpeg3_SNRMBtab[code].len); return mpeg3_SNRMBtab[code].val; } int mpeg3video_get_mb_type(mpeg3_slice_t *slice, mpeg3video_t *video) { if(video->scalable_mode == SC_SNR) { return mpeg3video_get_snrmb_type(slice); } else { switch(video->pict_type) { case I_TYPE: return video->pict_scal ? mpeg3video_getsp_imb_type(slice) : mpeg3video_get_imb_type(slice); case P_TYPE: return video->pict_scal ? mpeg3video_getsp_pmb_type(slice) : mpeg3video_get_pmb_type(slice); case B_TYPE: return video->pict_scal ? mpeg3video_getsp_bmb_type(slice) : mpeg3video_get_bmb_type(slice); case D_TYPE: return mpeg3video_get_dmb_type(slice); default: /*fprintf(stderr, "mpeg3video_getmbtype: unknown coding type\n"); */ break; /* MPEG-1 only, not implemented */ } } return 0; } int mpeg3video_macroblock_modes(mpeg3_slice_t *slice, mpeg3video_t *video, int *pmb_type, int *pstwtype, int *pstwclass, int *pmotion_type, int *pmv_count, int *pmv_format, int *pdmv, int *pmvscale, int *pdct_type) { int mb_type; int stwtype, stwcode, stwclass; int motion_type = 0, mv_count, mv_format, dmv, mvscale; int dct_type; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; static unsigned char stwc_table[3][4] = { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} }; static unsigned char stwclass_table[9] = {0, 1, 2, 1, 1, 2, 3, 3, 4}; /* get macroblock_type */ mb_type = mpeg3video_get_mb_type(slice, video); if(slice->fault) return 1; /* get spatial_temporal_weight_code */ if(mb_type & MB_WEIGHT) { if(video->stwc_table_index == 0) stwtype = 4; else { stwcode = mpeg3slice_getbits2(slice_buffer); stwtype = stwc_table[video->stwc_table_index - 1][stwcode]; } } else stwtype = (mb_type & MB_CLASS4) ? 8 : 0; /* derive spatial_temporal_weight_class (Table 7-18) */ stwclass = stwclass_table[stwtype]; /* get frame/field motion type */ if(mb_type & (MB_FORWARD | MB_BACKWARD)) { if(video->pict_struct == FRAME_PICTURE) { /* frame_motion_type */ motion_type = video->frame_pred_dct ? MC_FRAME : mpeg3slice_getbits2(slice_buffer); } else { /* field_motion_type */ motion_type = mpeg3slice_getbits2(slice_buffer); } } else if((mb_type & MB_INTRA) && video->conceal_mv) { /* concealment motion vectors */ motion_type = (video->pict_struct == FRAME_PICTURE) ? MC_FRAME : MC_FIELD; } /* derive mv_count, mv_format and dmv, (table 6-17, 6-18) */ if(video->pict_struct == FRAME_PICTURE) { mv_count = (motion_type == MC_FIELD && stwclass < 2) ? 2 : 1; mv_format = (motion_type == MC_FRAME) ? MV_FRAME : MV_FIELD; } else { mv_count = (motion_type == MC_16X8) ? 2 : 1; mv_format = MV_FIELD; } dmv = (motion_type == MC_DMV); /* dual prime */ /* field mv predictions in frame pictures have to be scaled */ mvscale = ((mv_format == MV_FIELD) && (video->pict_struct == FRAME_PICTURE)); /* get dct_type (frame DCT / field DCT) */ dct_type = (video->pict_struct == FRAME_PICTURE) && (!video->frame_pred_dct) && (mb_type & (MB_PATTERN | MB_INTRA)) ? mpeg3slice_getbit(slice_buffer) : 0; /* return values */ *pmb_type = mb_type; *pstwtype = stwtype; *pstwclass = stwclass; *pmotion_type = motion_type; *pmv_count = mv_count; *pmv_format = mv_format; *pdmv = dmv; *pmvscale = mvscale; *pdct_type = dct_type; return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mmxidct.S ================================================ /* * the input data is tranposed and each 16 bit element in the 8x8 matrix * is left aligned: * for example in 11...1110000 format * If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component * (element[0][0] of the matrix) */ /* extrn re_matrix */ /* constants */ .data .align 16 .type preSC, @object preSC: .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270 .short 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906 .short 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315 .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 12873, 17855, 16819, 15137, 25746, 20228, 13933, 7103 .short 17734, 24598, 23170, 20853, 17734, 13933, 9597, 4892 .short 18081, 25080, 23624, 21261, 18081, 14206, 9785, 4988 .size preSC, 128 .align 8 .type x0005000200010001, @object .size x0005000200010001, 8 x0005000200010001: .long 0x00010001, 0x00050002 .align 8 .type x0040000000000000, @object .size x0040000000000000, 8 x0040000000000000: .long 0, 0x00400000 .align 8 .type x5a825a825a825a82, @object .size x5a825a825a825a82, 8 x5a825a825a825a82: .long 0x5a825a82, 0x5a825a82 .align 8 .type x539f539f539f539f, @object .size x539f539f539f539f, 8 x539f539f539f539f: .long 0x539f539f, 0x539f539f .align 8 .type x4546454645464546, @object .size x4546454645464546, 8 x4546454645464546: .long 0x45464546, 0x45464546 .align 8 .type x61f861f861f861f8, @object .size x61f861f861f861f8, 8 x61f861f861f861f8: .long 0x61f861f8, 0x61f861f8 /* Static variables */ .align 8 .type x0, @object .size x0, 8 x0: .long 0, 0 /* Procedure */ .align 8 .text .align 4 .globl IDCT_mmx .type IDCT_mmx, @function IDCT_mmx: pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx pushl %esi pushl %edi pushl $0 /* allocate the temp variables */ pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 movl 8(%ebp), %esi /* source matrix */ leal preSC, %ecx /* column 0: even part * use V4, V12, V0, V8 to produce V22..V25 */ movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */ /* with the dequantization in iHuff module */ pmulhw 8*12(%esi), %mm0 /* V12 */ movq 8*4(%ecx), %mm1 pmulhw 8*4(%esi), %mm1 /* V4 */ movq (%ecx), %mm3 psraw $1, %mm0 /* t64=t66 */ pmulhw (%esi), %mm3 /* V0 */ movq 8*8(%ecx), %mm5 /* duplicate V4 */ movq %mm1, %mm2 /* added 11/1/96 */ pmulhw 8*8(%esi),%mm5 /* V8 */ psubsw %mm0, %mm1 /* V16 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */ paddsw %mm0, %mm2 /* V17 */ movq %mm2, %mm0 /* duplicate V17 */ psraw $1, %mm2 /* t75=t82 */ psraw $2, %mm0 /* t72 */ movq %mm3, %mm4 /* duplicate V0 */ paddsw %mm5, %mm3 /* V19 */ psubsw %mm5, %mm4 /* V20 ;mm5 free */ /* moved from the block below */ movq 8*10(%ecx), %mm7 psraw $1, %mm3 /* t74=t81 */ movq %mm3, %mm6 /* duplicate t74=t81 */ psraw $2, %mm4 /* t77=t79 */ psubsw %mm0, %mm1 /* V21 ; mm0 free */ paddsw %mm2, %mm3 /* V22 */ movq %mm1, %mm5 /* duplicate V21 */ paddsw %mm4, %mm1 /* V23 */ movq %mm3, 8*4(%esi) /* V22 */ psubsw %mm5, %mm4 /* V24; mm5 free */ movq %mm1, 8*12(%esi) /* V23 */ psubsw %mm2, %mm6 /* V25; mm2 free */ movq %mm4, (%esi) /* V24 */ /* keep mm6 alive all along the next block */ /* movq %mm6, 8*8(%esi) V25 */ /* column 0: odd part * use V2, V6, V10, V14 to produce V31, V39, V40, V41 */ /* moved above: movq 8*10(%ecx), %mm7 */ pmulhw 8*10(%esi), %mm7 /* V10 */ movq 8*6(%ecx), %mm0 pmulhw 8*6(%esi), %mm0 /* V6 */ movq 8*2(%ecx), %mm5 movq %mm7, %mm3 /* duplicate V10 */ pmulhw 8*2(%esi), %mm5 /* V2 */ movq 8*14(%ecx), %mm4 psubsw %mm0, %mm7 /* V26 */ pmulhw 8*14(%esi), %mm4 /* V14 */ paddsw %mm0, %mm3 /* V29 ; free mm0 */ movq %mm7, %mm1 /* duplicate V26 */ psraw $1, %mm3 /* t91=t94 */ pmulhw x539f539f539f539f,%mm7 /* V33 */ psraw $1, %mm1 /* t96 */ movq %mm5, %mm0 /* duplicate V2 */ psraw $2, %mm4 /* t85=t87 */ paddsw %mm4,%mm5 /* V27 */ psubsw %mm4, %mm0 /* V28 ; free mm4 */ movq %mm0, %mm2 /* duplicate V28 */ psraw $1, %mm5 /* t90=t93 */ pmulhw x4546454645464546,%mm0 /* V35 */ psraw $1, %mm2 /* t97 */ movq %mm5, %mm4 /* duplicate t90=t93 */ psubsw %mm2, %mm1 /* V32 ; free mm2 */ pmulhw x61f861f861f861f8,%mm1 /* V36 */ psllw $1, %mm7 /* t107 */ paddsw %mm3, %mm5 /* V31 */ psubsw %mm3, %mm4 /* V30 ; free mm3 */ pmulhw x5a825a825a825a82,%mm4 /* V34 */ nop psubsw %mm1, %mm0 /* V38 */ psubsw %mm7, %mm1 /* V37 ; free mm7 */ psllw $1, %mm1 /* t114 */ /* move from the next block */ movq %mm6, %mm3 /* duplicate V25 */ /* move from the next block */ movq 8*4(%esi), %mm7 /* V22 */ psllw $1, %mm0 /* t110 */ psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */ psllw $2, %mm4 /* t112 */ /* moved from the next block */ movq 8*12(%esi), %mm2 /* V23 */ psubsw %mm0, %mm4 /* V40 */ paddsw %mm4, %mm1 /* V41; free mm0 */ /* moved from the next block */ psllw $1, %mm2 /* t117=t125 */ /* column 0: output butterfly */ /* moved above: * movq %mm6, %mm3 duplicate V25 * movq 8*4(%esi), %mm7 V22 * movq 8*12(%esi), %mm2 V23 * psllw $1, %mm2 t117=t125 */ psubsw %mm1, %mm6 /* tm6 */ paddsw %mm1, %mm3 /* tm8; free mm1 */ movq %mm7, %mm1 /* duplicate V22 */ paddsw %mm5, %mm7 /* tm0 */ movq %mm3, 8*8(%esi) /* tm8; free mm3 */ psubsw %mm5, %mm1 /* tm14; free mm5 */ movq %mm6, 8*6(%esi) /* tm6; free mm6 */ movq %mm2, %mm3 /* duplicate t117=t125 */ movq (%esi), %mm6 /* V24 */ paddsw %mm0, %mm2 /* tm2 */ movq %mm7, (%esi) /* tm0; free mm7 */ psubsw %mm0, %mm3 /* tm12; free mm0 */ movq %mm1, 8*14(%esi) /* tm14; free mm1 */ psllw $1, %mm6 /* t119=t123 */ movq %mm2, 8*2(%esi) /* tm2; free mm2 */ movq %mm6, %mm0 /* duplicate t119=t123 */ movq %mm3, 8*12(%esi) /* tm12; free mm3 */ paddsw %mm4, %mm6 /* tm4 */ /* moved from next block */ movq 8*5(%ecx), %mm1 psubsw %mm4, %mm0 /* tm10; free mm4 */ /* moved from next block */ pmulhw 8*5(%esi), %mm1 /* V5 */ movq %mm6, 8*4(%esi) /* tm4; free mm6 */ movq %mm0, 8*10(%esi) /* tm10; free mm0 */ /* column 1: even part * use V5, V13, V1, V9 to produce V56..V59 */ /* moved to prev block: * movq 8*5(%ecx), %mm1 * pmulhw 8*5(%esi), %mm1 V5 */ movq 8*13(%ecx), %mm7 psllw $1, %mm1 /* t128=t130 */ pmulhw 8*13(%esi), %mm7 /* V13 */ movq %mm1, %mm2 /* duplicate t128=t130 */ movq 8(%ecx), %mm3 pmulhw 8(%esi), %mm3 /* V1 */ movq 8*9(%ecx), %mm5 psubsw %mm7, %mm1 /* V50 */ pmulhw 8*9(%esi), %mm5 /* V9 */ paddsw %mm7, %mm2 /* V51 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */ movq %mm2, %mm6 /* duplicate V51 */ psraw $1, %mm2 /* t138=t144 */ movq %mm3, %mm4 /* duplicate V1 */ psraw $2, %mm6 /* t136 */ paddsw %mm5, %mm3 /* V53 */ psubsw %mm5, %mm4 /* V54 ;mm5 free */ movq %mm3, %mm7 /* duplicate V53 */ /* moved from next block */ movq 8*11(%ecx), %mm0 psraw $1, %mm4 /* t140=t142 */ psubsw %mm6, %mm1 /* V55 ; mm6 free */ paddsw %mm2, %mm3 /* V56 */ movq %mm4, %mm5 /* duplicate t140=t142 */ paddsw %mm1, %mm4 /* V57 */ movq %mm3, 8*5(%esi) /* V56 */ psubsw %mm1, %mm5 /* V58; mm1 free */ movq %mm4, 8*13(%esi) /* V57 */ psubsw %mm2, %mm7 /* V59; mm2 free */ movq %mm5, 8*9(%esi) /* V58 */ /* keep mm7 alive all along the next block * movq %mm7, 8(%esi) V59 * moved above * movq 8*11(%ecx), %mm0 */ pmulhw 8*11(%esi), %mm0 /* V11 */ movq 8*7(%ecx), %mm6 pmulhw 8*7(%esi), %mm6 /* V7 */ movq 8*15(%ecx), %mm4 movq %mm0, %mm3 /* duplicate V11 */ pmulhw 8*15(%esi), %mm4 /* V15 */ movq 8*3(%ecx), %mm5 psllw $1, %mm6 /* t146=t152 */ pmulhw 8*3(%esi), %mm5 /* V3 */ paddsw %mm6, %mm0 /* V63 */ /* note that V15 computation has a correction step: * this is a 'magic' constant that rebiases the results to be closer to the * expected result. this magic constant can be refined to reduce the error * even more by doing the correction step in a later stage when the number * is actually multiplied by 16 */ paddw x0005000200010001, %mm4 psubsw %mm6, %mm3 /* V60 ; free mm6 */ psraw $1, %mm0 /* t154=t156 */ movq %mm3, %mm1 /* duplicate V60 */ pmulhw x539f539f539f539f, %mm1 /* V67 */ movq %mm5, %mm6 /* duplicate V3 */ psraw $2, %mm4 /* t148=t150 */ paddsw %mm4, %mm5 /* V61 */ psubsw %mm4, %mm6 /* V62 ; free mm4 */ movq %mm5, %mm4 /* duplicate V61 */ psllw $1, %mm1 /* t169 */ paddsw %mm0, %mm5 /* V65 -> result */ psubsw %mm0, %mm4 /* V64 ; free mm0 */ pmulhw x5a825a825a825a82, %mm4 /* V68 */ psraw $1, %mm3 /* t158 */ psubsw %mm6, %mm3 /* V66 */ movq %mm5, %mm2 /* duplicate V65 */ pmulhw x61f861f861f861f8, %mm3 /* V70 */ psllw $1, %mm6 /* t165 */ pmulhw x4546454645464546, %mm6 /* V69 */ psraw $1, %mm2 /* t172 */ /* moved from next block */ movq 8*5(%esi), %mm0 /* V56 */ psllw $1, %mm4 /* t174 */ /* moved from next block */ psraw $1, %mm0 /* t177=t188 */ nop psubsw %mm3, %mm6 /* V72 */ psubsw %mm1, %mm3 /* V71 ; free mm1 */ psubsw %mm2, %mm6 /* V73 ; free mm2 */ /* moved from next block */ psraw $1, %mm5 /* t178=t189 */ psubsw %mm6, %mm4 /* V74 */ /* moved from next block */ movq %mm0, %mm1 /* duplicate t177=t188 */ paddsw %mm4, %mm3 /* V75 */ /* moved from next block */ paddsw %mm5, %mm0 /* tm1 */ /* location * 5 - V56 * 13 - V57 * 9 - V58 * X - V59, mm7 * X - V65, mm5 * X - V73, mm6 * X - V74, mm4 * X - V75, mm3 * free mm0, mm1 & mm2 * moved above * movq 8*5(%esi), %mm0 V56 * psllw $1, %mm0 t177=t188 ! new !! * psllw $1, %mm5 t178=t189 ! new !! * movq %mm0, %mm1 duplicate t177=t188 * paddsw %mm5, %mm0 tm1 */ movq 8*13(%esi), %mm2 /* V57 */ psubsw %mm5, %mm1 /* tm15; free mm5 */ movq %mm0, 8(%esi) /* tm1; free mm0 */ psraw $1, %mm7 /* t182=t184 ! new !! */ /* save the store as used directly in the transpose * movq %mm1, 120(%esi) tm15; free mm1 */ movq %mm7, %mm5 /* duplicate t182=t184 */ psubsw %mm3, %mm7 /* tm7 */ paddsw %mm3, %mm5 /* tm9; free mm3 */ movq 8*9(%esi), %mm0 /* V58 */ movq %mm2, %mm3 /* duplicate V57 */ movq %mm7, 8*7(%esi) /* tm7; free mm7 */ psubsw %mm6, %mm3 /* tm13 */ paddsw %mm6, %mm2 /* tm3 ; free mm6 */ /* moved up from the transpose */ movq %mm3, %mm7 /* moved up from the transpose */ punpcklwd %mm1, %mm3 movq %mm0, %mm6 /* duplicate V58 */ movq %mm2, 8*3(%esi) /* tm3; free mm2 */ paddsw %mm4, %mm0 /* tm5 */ psubsw %mm4, %mm6 /* tm11; free mm4 */ /* moved up from the transpose */ punpckhwd %mm1, %mm7 movq %mm0, 8*5(%esi) /* tm5; free mm0 */ /* moved up from the transpose */ movq %mm5, %mm2 /* transpose - M4 part * --------- --------- * | M1 | M2 | | M1'| M3'| * --------- --> --------- * | M3 | M4 | | M2'| M4'| * --------- --------- * Two alternatives: use full mmword approach so the following code can be * scheduled before the transpose is done without stores, or use the faster * half mmword stores (when possible) */ movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */ punpcklwd %mm6, %mm5 movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */ punpckhwd %mm6, %mm2 movd %mm5, 8*9(%esi) /* LS part of tmt9 */ punpckhdq %mm3, %mm5 /* free mm3 */ movd %mm2, 8*13(%esi) /* LS part of tmt13 */ punpckhdq %mm7, %mm2 /* free mm7 */ /* moved up from the M3 transpose */ movq 8*8(%esi), %mm0 /* moved up from the M3 transpose */ movq 8*10(%esi), %mm1 /* moved up from the M3 transpose */ movq %mm0, %mm3 /* shuffle the rest of the data, and write it with 2 mmword writes */ movq %mm5, 8*11(%esi) /* tmt11 */ /* moved up from the M3 transpose */ punpcklwd %mm1, %mm0 movq %mm2, 8*15(%esi) /* tmt15 */ /* moved up from the M3 transpose */ punpckhwd %mm1, %mm3 /* transpose - M3 part * moved up to previous code section * movq 8*8(%esi), %mm0 * movq 8*10(%esi), %mm1 * movq %mm0, %mm3 * punpcklwd %mm1, %mm0 * punpckhwd %mm1, %mm3 */ movq 8*12(%esi), %mm6 movq 8*14(%esi), %mm4 movq %mm6, %mm2 /* shuffle the data and write the lower parts of the transposed in 4 dwords */ punpcklwd %mm4, %mm6 movq %mm0, %mm1 punpckhdq %mm6, %mm1 movq %mm3, %mm7 punpckhwd %mm4, %mm2 /* free mm4 */ punpckldq %mm6, %mm0 /* free mm6 */ /* moved from next block */ movq 8*13(%esi), %mm4 /* tmt13 */ punpckldq %mm2, %mm3 punpckhdq %mm2, %mm7 /* free mm2 */ /* moved from next block */ movq %mm3, %mm5 /* duplicate tmt5 */ /* column 1: even part (after transpose) * moved above * movq %mm3, %mm5 duplicate tmt5 * movq 8*13(%esi), %mm4 tmt13 */ psubsw %mm4, %mm3 /* V134 */ pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */ movq 8*9(%esi), %mm6 /* tmt9 */ paddsw %mm4, %mm5 /* V135 ; mm4 free */ movq %mm0, %mm4 /* duplicate tmt1 */ paddsw %mm6, %mm0 /* V137 */ psubsw %mm6, %mm4 /* V138 ; mm6 free */ psllw $2, %mm3 /* t290 */ psubsw %mm5, %mm3 /* V139 */ movq %mm0, %mm6 /* duplicate V137 */ paddsw %mm5, %mm0 /* V140 */ movq %mm4, %mm2 /* duplicate V138 */ paddsw %mm3, %mm2 /* V141 */ psubsw %mm3, %mm4 /* V142 ; mm3 free */ movq %mm0, 8*9(%esi) /* V140 */ psubsw %mm5, %mm6 /* V143 ; mm5 free */ /* moved from next block */ movq 8*11(%esi), %mm0 /* tmt11 */ movq %mm2, 8*13(%esi) /* V141 */ /* moved from next block */ movq %mm0, %mm2 /* duplicate tmt11 */ /* column 1: odd part (after transpose) */ /* moved up to the prev block * movq 8*11(%esi), %mm0 tmt11 * movq %mm0, %mm2 duplicate tmt11 */ movq 8*15(%esi), %mm5 /* tmt15 */ psubsw %mm7, %mm0 /* V144 */ movq %mm0, %mm3 /* duplicate V144 */ paddsw %mm7, %mm2 /* V147 ; free mm7 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */ movq %mm1, %mm7 /* duplicate tmt3 */ paddsw %mm5, %mm7 /* V145 */ psubsw %mm5, %mm1 /* V146 ; free mm5 */ psubsw %mm1, %mm3 /* V150 */ movq %mm7, %mm5 /* duplicate V145 */ pmulhw x4546454645464546, %mm1 /* 17734-> V153 */ psubsw %mm2, %mm5 /* V148 */ pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */ psllw $2, %mm0 /* t311 */ pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */ paddsw %mm2, %mm7 /* V149 ; free mm2 */ psllw $1, %mm1 /* t313 */ nop /* without the nop - freeze here for one clock */ movq %mm3, %mm2 /* duplicate V154 */ psubsw %mm0, %mm3 /* V155 ; free mm0 */ psubsw %mm2, %mm1 /* V156 ; free mm2 */ /* moved from the next block */ movq %mm6, %mm2 /* duplicate V143 */ /* moved from the next block */ movq 8*13(%esi), %mm0 /* V141 */ psllw $1, %mm1 /* t315 */ psubsw %mm7, %mm1 /* V157 (keep V149) */ psllw $2, %mm5 /* t317 */ psubsw %mm1, %mm5 /* V158 */ psllw $1, %mm3 /* t319 */ paddsw %mm5, %mm3 /* V159 */ /* column 1: output butterfly (after transform) * moved to the prev block * movq %mm6, %mm2 duplicate V143 * movq 8*13(%esi), %mm0 V141 */ psubsw %mm3, %mm2 /* V163 */ paddsw %mm3, %mm6 /* V164 ; free mm3 */ movq %mm4, %mm3 /* duplicate V142 */ psubsw %mm5, %mm4 /* V165 ; free mm5 */ movq %mm2, (%esp) /* out7 */ psraw $4, %mm6 psraw $4, %mm4 paddsw %mm5, %mm3 /* V162 */ movq 8*9(%esi), %mm2 /* V140 */ movq %mm0, %mm5 /* duplicate V141 */ /* in order not to perculate this line up, * we read 72(%esi) very near to this location */ movq %mm6, 8*9(%esi) /* out9 */ paddsw %mm1, %mm0 /* V161 */ movq %mm3, 8(%esp) /* out5 */ psubsw %mm1, %mm5 /* V166 ; free mm1 */ movq %mm4, 8*11(%esi) /* out11 */ psraw $4, %mm5 movq %mm0, 16(%esp) /* out3 */ movq %mm2, %mm4 /* duplicate V140 */ movq %mm5, 8*13(%esi) /* out13 */ paddsw %mm7, %mm2 /* V160 */ /* moved from the next block */ movq 8(%esi), %mm0 psubsw %mm7, %mm4 /* V167 ; free mm7 */ /* moved from the next block */ movq 8*3(%esi), %mm7 psraw $4, %mm4 movq %mm2, 24(%esp) /* out1 */ /* moved from the next block */ movq %mm0, %mm1 movq %mm4, 8*15(%esi) /* out15 */ /* moved from the next block */ punpcklwd %mm7, %mm0 /* transpose - M2 parts * moved up to the prev block * movq 8(%esi), %mm0 * movq 8*3(%esi), %mm7 * movq %mm0, %mm1 * punpcklwd %mm7, %mm0 */ movq 8*5(%esi), %mm5 punpckhwd %mm7, %mm1 movq 8*7(%esi), %mm4 movq %mm5, %mm3 /* shuffle the data and write the lower parts of the trasposed in 4 dwords */ movd %mm0, 8*8(%esi) /* LS part of tmt8 */ punpcklwd %mm4, %mm5 movd %mm1, 8*12(%esi) /* LS part of tmt12 */ punpckhwd %mm4, %mm3 movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */ punpckhdq %mm5, %mm0 /* tmt10 */ movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */ punpckhdq %mm3, %mm1 /* tmt14 */ /* transpose - M1 parts */ movq (%esi), %mm7 movq 8*2(%esi), %mm2 movq %mm7, %mm6 movq 8*4(%esi), %mm5 punpcklwd %mm2, %mm7 movq 8*6(%esi), %mm4 punpckhwd %mm2, %mm6 /* free mm2 */ movq %mm5, %mm3 punpcklwd %mm4, %mm5 punpckhwd %mm4, %mm3 /* free mm4 */ movq %mm7, %mm2 movq %mm6, %mm4 punpckldq %mm5, %mm7 /* tmt0 */ punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */ /* shuffle the rest of the data, and write it with 2 mmword writes */ punpckldq %mm3, %mm6 /* tmt4 */ /* moved from next block */ movq %mm2, %mm5 /* duplicate tmt2 */ punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */ /* moved from next block */ movq %mm0, %mm3 /* duplicate tmt10 */ /* column 0: odd part (after transpose) *moved up to prev block * movq %mm0, %mm3 duplicate tmt10 * movq %mm2, %mm5 duplicate tmt2 */ psubsw %mm4, %mm0 /* V110 */ paddsw %mm4, %mm3 /* V113 ; free mm4 */ movq %mm0, %mm4 /* duplicate V110 */ paddsw %mm1, %mm2 /* V111 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */ psubsw %mm1, %mm5 /* V112 ; free mm1 */ psubsw %mm5, %mm4 /* V116 */ movq %mm2, %mm1 /* duplicate V111 */ pmulhw x4546454645464546, %mm5 /* 17734-> V119 */ psubsw %mm3, %mm2 /* V114 */ pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */ paddsw %mm3, %mm1 /* V115 ; free mm3 */ pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */ psllw $2, %mm0 /* t266 */ movq %mm1, (%esi) /* save V115 */ psllw $1, %mm5 /* t268 */ psubsw %mm4, %mm5 /* V122 */ psubsw %mm0, %mm4 /* V121 ; free mm0 */ psllw $1, %mm5 /* t270 */ psubsw %mm1, %mm5 /* V123 ; free mm1 */ psllw $2, %mm2 /* t272 */ psubsw %mm5, %mm2 /* V124 (keep V123) */ psllw $1, %mm4 /* t274 */ movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */ paddsw %mm2, %mm4 /* V125 (keep V124) */ /* column 0: even part (after transpose) */ movq 8*12(%esi), %mm0 /* tmt12 */ movq %mm6, %mm3 /* duplicate tmt4 */ psubsw %mm0, %mm6 /* V100 */ paddsw %mm0, %mm3 /* V101 ; free mm0 */ pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */ movq %mm7, %mm5 /* duplicate tmt0 */ movq 8*8(%esi), %mm1 /* tmt8 */ paddsw %mm1, %mm7 /* V103 */ psubsw %mm1, %mm5 /* V104 ; free mm1 */ movq %mm7, %mm0 /* duplicate V103 */ psllw $2, %mm6 /* t245 */ paddsw %mm3, %mm7 /* V106 */ movq %mm5, %mm1 /* duplicate V104 */ psubsw %mm3, %mm6 /* V105 */ psubsw %mm3, %mm0 /* V109; free mm3 */ paddsw %mm6, %mm5 /* V107 */ psubsw %mm6, %mm1 /* V108 ; free mm6 */ /* column 0: output butterfly (after transform) */ movq %mm1, %mm3 /* duplicate V108 */ paddsw %mm2, %mm1 /* out4 */ psraw $4, %mm1 psubsw %mm2, %mm3 /* out10 ; free mm2 */ psraw $4, %mm3 movq %mm0, %mm6 /* duplicate V109 */ movq %mm1, 8*4(%esi) /* out4 ; free mm1 */ psubsw %mm4, %mm0 /* out6 */ movq %mm3, 8*10(%esi) /* out10 ; free mm3 */ psraw $4, %mm0 paddsw %mm4, %mm6 /* out8 ; free mm4 */ movq %mm7, %mm1 /* duplicate V106 */ movq %mm0, 8*6(%esi) /* out6 ; free mm0 */ psraw $4, %mm6 movq (%esi), %mm4 /* V115 */ movq %mm6, 8*8(%esi) /* out8 ; free mm6 */ movq %mm5, %mm2 /* duplicate V107 */ movq 8*2(%esi), %mm3 /* V123 */ paddsw %mm4, %mm7 /* out0 */ /* moved up from next block */ movq 16(%esp), %mm0 psraw $4, %mm7 /* moved up from next block */ movq 8(%esp), %mm6 psubsw %mm4, %mm1 /* out14 ; free mm4 */ paddsw %mm3, %mm5 /* out2 */ psraw $4, %mm1 movq %mm7, (%esi) /* out0 ; free mm7 */ psraw $4, %mm5 movq %mm1, 8*14(%esi) /* out14 ; free mm1 */ psubsw %mm3, %mm2 /* out12 ; free mm3 */ movq %mm5, 8*2(%esi) /* out2 ; free mm5 */ psraw $4, %mm2 /* moved up to the prev block */ movq (%esp), %mm4 /* moved up to the prev block */ psraw $4, %mm0 movq %mm2, 8*12(%esi) /* out12 ; free mm2 */ /* moved up to the prev block */ psraw $4, %mm6 /* move back the data to its correct place * moved up to the prev block * movq 16(%esp), %mm0 * movq 8(%esp), %mm6 * movq (%esp), %mm4 * psraw $4, %mm0 * psraw $4, %mm6 */ movq 24(%esp), %mm1 psraw $4, %mm4 movq %mm0, 8*3(%esi) /* out3 */ psraw $4, %mm1 movq %mm6, 8*5(%esi) /* out5 */ movq %mm4, 8*7(%esi) /* out7 */ movq %mm1, 8(%esi) /* out1 */ popl %edi /* Pop off the temp variables */ popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi /* Pop off the old variables */ popl %esi popl %edx popl %ecx popl %ebx movl %ebp, %esp popl %ebp ret .Lfe1: .size IDCT_mmx,.Lfe1-IDCT_mmx ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mmxidct_gasp.s ================================================ /* * the input data is tranposed and each 16 bit element in the 8x8 matrix * is left aligned: * for example in 11...1110000 format * If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component * (element[0][0] of the matrix) */ /* extrn re_matrix */ /* constants */ .long .align 16 .type preSC, @object preSC: .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270 .short 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906 .short 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315 .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 12873, 17855, 16819, 15137, 25746, 20228, 13933, 7103 .short 17734, 24598, 23170, 20853, 17734, 13933, 9597, 4892 .short 18081, 25080, 23624, 21261, 18081, 14206, 9785, 4988 .size preSC, 128 .align 8 .type x0005000200010001, @object .size x0005000200010001, 8 x0005000200010001: .long 0x00010001, 0x00050002 .align 8 .type x0040000000000000, @object .size x0040000000000000, 8 x0040000000000000: .long 0, 0x00400000 .align 8 .type x5a825a825a825a82, @object .size x5a825a825a825a82, 8 x5a825a825a825a82: .long 0x5a825a82, 0x5a825a82 .align 8 .type x539f539f539f539f, @object .size x539f539f539f539f, 8 x539f539f539f539f: .long 0x539f539f, 0x539f539f .align 8 .type x4546454645464546, @object .size x4546454645464546, 8 x4546454645464546: .long 0x45464546, 0x45464546 .align 8 .type x61f861f861f861f8, @object .size x61f861f861f861f8, 8 x61f861f861f861f8: .long 0x61f861f8, 0x61f861f8 /* Static variables */ .align 8 .type x0, @object .size x0, 8 x0: .long 0, 0 /* Procedure */ .align 8 .text .align 4 .globl IDCT_mmx .type IDCT_mmx, @function IDCT_mmx: pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx pushl %esi pushl %edi pushl $0 /* allocate the temp variables */ pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 movl 8(%ebp), %esi /* source matrix */ leal preSC, %ecx /* column 0: even part * use V4, V12, V0, V8 to produce V22..V25 */ movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */ /* with the dequantization in iHuff module */ pmulhw 8*12(%esi), %mm0 /* V12 */ movq 8*4(%ecx), %mm1 pmulhw 8*4(%esi), %mm1 /* V4 */ movq (%ecx), %mm3 psraw $1, %mm0 /* t64=t66 */ pmulhw (%esi), %mm3 /* V0 */ movq 8*8(%ecx), %mm5 /* duplicate V4 */ movq %mm1, %mm2 /* added 11/1/96 */ pmulhw 8*8(%esi),%mm5 /* V8 */ psubsw %mm0, %mm1 /* V16 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */ paddsw %mm0, %mm2 /* V17 */ movq %mm2, %mm0 /* duplicate V17 */ psraw $1, %mm2 /* t75=t82 */ psraw $2, %mm0 /* t72 */ movq %mm3, %mm4 /* duplicate V0 */ paddsw %mm5, %mm3 /* V19 */ psubsw %mm5, %mm4 /* V20 ;mm5 free */ /* moved from the block below */ movq 8*10(%ecx), %mm7 psraw $1, %mm3 /* t74=t81 */ movq %mm3, %mm6 /* duplicate t74=t81 */ psraw $2, %mm4 /* t77=t79 */ psubsw %mm0, %mm1 /* V21 ; mm0 free */ paddsw %mm2, %mm3 /* V22 */ movq %mm1, %mm5 /* duplicate V21 */ paddsw %mm4, %mm1 /* V23 */ movq %mm3, 8*4(%esi) /* V22 */ psubsw %mm5, %mm4 /* V24; mm5 free */ movq %mm1, 8*12(%esi) /* V23 */ psubsw %mm2, %mm6 /* V25; mm2 free */ movq %mm4, (%esi) /* V24 */ /* keep mm6 alive all along the next block */ /* movq %mm6, 8*8(%esi) V25 */ /* column 0: odd part * use V2, V6, V10, V14 to produce V31, V39, V40, V41 */ /* moved above: movq 8*10(%ecx), %mm7 */ pmulhw 8*10(%esi), %mm7 /* V10 */ movq 8*6(%ecx), %mm0 pmulhw 8*6(%esi), %mm0 /* V6 */ movq 8*2(%ecx), %mm5 movq %mm7, %mm3 /* duplicate V10 */ pmulhw 8*2(%esi), %mm5 /* V2 */ movq 8*14(%ecx), %mm4 psubsw %mm0, %mm7 /* V26 */ pmulhw 8*14(%esi), %mm4 /* V14 */ paddsw %mm0, %mm3 /* V29 ; free mm0 */ movq %mm7, %mm1 /* duplicate V26 */ psraw $1, %mm3 /* t91=t94 */ pmulhw x539f539f539f539f,%mm7 /* V33 */ psraw $1, %mm1 /* t96 */ movq %mm5, %mm0 /* duplicate V2 */ psraw $2, %mm4 /* t85=t87 */ paddsw %mm4,%mm5 /* V27 */ psubsw %mm4, %mm0 /* V28 ; free mm4 */ movq %mm0, %mm2 /* duplicate V28 */ psraw $1, %mm5 /* t90=t93 */ pmulhw x4546454645464546,%mm0 /* V35 */ psraw $1, %mm2 /* t97 */ movq %mm5, %mm4 /* duplicate t90=t93 */ psubsw %mm2, %mm1 /* V32 ; free mm2 */ pmulhw x61f861f861f861f8,%mm1 /* V36 */ psllw $1, %mm7 /* t107 */ paddsw %mm3, %mm5 /* V31 */ psubsw %mm3, %mm4 /* V30 ; free mm3 */ pmulhw x5a825a825a825a82,%mm4 /* V34 */ nop psubsw %mm1, %mm0 /* V38 */ psubsw %mm7, %mm1 /* V37 ; free mm7 */ psllw $1, %mm1 /* t114 */ /* move from the next block */ movq %mm6, %mm3 /* duplicate V25 */ /* move from the next block */ movq 8*4(%esi), %mm7 /* V22 */ psllw $1, %mm0 /* t110 */ psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */ psllw $2, %mm4 /* t112 */ /* moved from the next block */ movq 8*12(%esi), %mm2 /* V23 */ psubsw %mm0, %mm4 /* V40 */ paddsw %mm4, %mm1 /* V41; free mm0 */ /* moved from the next block */ psllw $1, %mm2 /* t117=t125 */ /* column 0: output butterfly */ /* moved above: * movq %mm6, %mm3 duplicate V25 * movq 8*4(%esi), %mm7 V22 * movq 8*12(%esi), %mm2 V23 * psllw $1, %mm2 t117=t125 */ psubsw %mm1, %mm6 /* tm6 */ paddsw %mm1, %mm3 /* tm8; free mm1 */ movq %mm7, %mm1 /* duplicate V22 */ paddsw %mm5, %mm7 /* tm0 */ movq %mm3, 8*8(%esi) /* tm8; free mm3 */ psubsw %mm5, %mm1 /* tm14; free mm5 */ movq %mm6, 8*6(%esi) /* tm6; free mm6 */ movq %mm2, %mm3 /* duplicate t117=t125 */ movq (%esi), %mm6 /* V24 */ paddsw %mm0, %mm2 /* tm2 */ movq %mm7, (%esi) /* tm0; free mm7 */ psubsw %mm0, %mm3 /* tm12; free mm0 */ movq %mm1, 8*14(%esi) /* tm14; free mm1 */ psllw $1, %mm6 /* t119=t123 */ movq %mm2, 8*2(%esi) /* tm2; free mm2 */ movq %mm6, %mm0 /* duplicate t119=t123 */ movq %mm3, 8*12(%esi) /* tm12; free mm3 */ paddsw %mm4, %mm6 /* tm4 */ /* moved from next block */ movq 8*5(%ecx), %mm1 psubsw %mm4, %mm0 /* tm10; free mm4 */ /* moved from next block */ pmulhw 8*5(%esi), %mm1 /* V5 */ movq %mm6, 8*4(%esi) /* tm4; free mm6 */ movq %mm0, 8*10(%esi) /* tm10; free mm0 */ /* column 1: even part * use V5, V13, V1, V9 to produce V56..V59 */ /* moved to prev block: * movq 8*5(%ecx), %mm1 * pmulhw 8*5(%esi), %mm1 V5 */ movq 8*13(%ecx), %mm7 psllw $1, %mm1 /* t128=t130 */ pmulhw 8*13(%esi), %mm7 /* V13 */ movq %mm1, %mm2 /* duplicate t128=t130 */ movq 8(%ecx), %mm3 pmulhw 8(%esi), %mm3 /* V1 */ movq 8*9(%ecx), %mm5 psubsw %mm7, %mm1 /* V50 */ pmulhw 8*9(%esi), %mm5 /* V9 */ paddsw %mm7, %mm2 /* V51 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */ movq %mm2, %mm6 /* duplicate V51 */ psraw $1, %mm2 /* t138=t144 */ movq %mm3, %mm4 /* duplicate V1 */ psraw $2, %mm6 /* t136 */ paddsw %mm5, %mm3 /* V53 */ psubsw %mm5, %mm4 /* V54 ;mm5 free */ movq %mm3, %mm7 /* duplicate V53 */ /* moved from next block */ movq 8*11(%ecx), %mm0 psraw $1, %mm4 /* t140=t142 */ psubsw %mm6, %mm1 /* V55 ; mm6 free */ paddsw %mm2, %mm3 /* V56 */ movq %mm4, %mm5 /* duplicate t140=t142 */ paddsw %mm1, %mm4 /* V57 */ movq %mm3, 8*5(%esi) /* V56 */ psubsw %mm1, %mm5 /* V58; mm1 free */ movq %mm4, 8*13(%esi) /* V57 */ psubsw %mm2, %mm7 /* V59; mm2 free */ movq %mm5, 8*9(%esi) /* V58 */ /* keep mm7 alive all along the next block * movq %mm7, 8(%esi) V59 * moved above * movq 8*11(%ecx), %mm0 */ pmulhw 8*11(%esi), %mm0 /* V11 */ movq 8*7(%ecx), %mm6 pmulhw 8*7(%esi), %mm6 /* V7 */ movq 8*15(%ecx), %mm4 movq %mm0, %mm3 /* duplicate V11 */ pmulhw 8*15(%esi), %mm4 /* V15 */ movq 8*3(%ecx), %mm5 psllw $1, %mm6 /* t146=t152 */ pmulhw 8*3(%esi), %mm5 /* V3 */ paddsw %mm6, %mm0 /* V63 */ /* note that V15 computation has a correction step: * this is a0magic' constant that rebiases the results to be closer to the * expected result. this magic constant can be refined to reduce the error * even more by doing the correction step in a later stage when the number * is actually multiplied by 16 */ paddw x0005000200010001, %mm4 psubsw %mm6, %mm3 /* V60 ; free mm6 */ psraw $1, %mm0 /* t154=t156 */ movq %mm3, %mm1 /* duplicate V60 */ pmulhw x539f539f539f539f, %mm1 /* V67 */ movq %mm5, %mm6 /* duplicate V3 */ psraw $2, %mm4 /* t148=t150 */ paddsw %mm4, %mm5 /* V61 */ psubsw %mm4, %mm6 /* V62 ; free mm4 */ movq %mm5, %mm4 /* duplicate V61 */ psllw $1, %mm1 /* t169 */ paddsw %mm0, %mm5 /* V65 -> result */ psubsw %mm0, %mm4 /* V64 ; free mm0 */ pmulhw x5a825a825a825a82, %mm4 /* V68 */ psraw $1, %mm3 /* t158 */ psubsw %mm6, %mm3 /* V66 */ movq %mm5, %mm2 /* duplicate V65 */ pmulhw x61f861f861f861f8, %mm3 /* V70 */ psllw $1, %mm6 /* t165 */ pmulhw x4546454645464546, %mm6 /* V69 */ psraw $1, %mm2 /* t172 */ /* moved from next block */ movq 8*5(%esi), %mm0 /* V56 */ psllw $1, %mm4 /* t174 */ /* moved from next block */ psraw $1, %mm0 /* t177=t188 */ nop psubsw %mm3, %mm6 /* V72 */ psubsw %mm1, %mm3 /* V71 ; free mm1 */ psubsw %mm2, %mm6 /* V73 ; free mm2 */ /* moved from next block */ psraw $1, %mm5 /* t178=t189 */ psubsw %mm6, %mm4 /* V74 */ /* moved from next block */ movq %mm0, %mm1 /* duplicate t177=t188 */ paddsw %mm4, %mm3 /* V75 */ /* moved from next block */ paddsw %mm5, %mm0 /* tm1 */ /* location * 5 - V56 * 13 - V57 * 9 - V58 * X - V59, mm7 * X - V65, mm5 * X - V73, mm6 * X - V74, mm4 * X - V75, mm3 * free mm0, mm1 & mm2 * moved above * movq 8*5(%esi), %mm0 V56 * psllw $1, %mm0 t177=t188 ! new !! * psllw $1, %mm5 t178=t189 ! new !! * movq %mm0, %mm1 duplicate t177=t188 * paddsw %mm5, %mm0 tm1 */ movq 8*13(%esi), %mm2 /* V57 */ psubsw %mm5, %mm1 /* tm15; free mm5 */ movq %mm0, 8(%esi) /* tm1; free mm0 */ psraw $1, %mm7 /* t182=t184 ! new !! */ /* save the store as used directly in the transpose * movq %mm1, 120(%esi) tm15; free mm1 */ movq %mm7, %mm5 /* duplicate t182=t184 */ psubsw %mm3, %mm7 /* tm7 */ paddsw %mm3, %mm5 /* tm9; free mm3 */ movq 8*9(%esi), %mm0 /* V58 */ movq %mm2, %mm3 /* duplicate V57 */ movq %mm7, 8*7(%esi) /* tm7; free mm7 */ psubsw %mm6, %mm3 /* tm13 */ paddsw %mm6, %mm2 /* tm3 ; free mm6 */ /* moved up from the transpose */ movq %mm3, %mm7 /* moved up from the transpose */ punpcklwd %mm1, %mm3 movq %mm0, %mm6 /* duplicate V58 */ movq %mm2, 8*3(%esi) /* tm3; free mm2 */ paddsw %mm4, %mm0 /* tm5 */ psubsw %mm4, %mm6 /* tm11; free mm4 */ /* moved up from the transpose */ punpckhwd %mm1, %mm7 movq %mm0, 8*5(%esi) /* tm5; free mm0 */ /* moved up from the transpose */ movq %mm5, %mm2 /* transpose - M4 part * --------- --------- * | M1 | M2 | | M1'| M3'| * --------- --> --------- * | M3 | M4 | | M2'| M4'| * --------- --------- * Two alternatives: use full mmword approach so the following code can be * scheduled before the transpose is done without stores, or use the faster * half mmword stores (when possible) */ movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */ punpcklwd %mm6, %mm5 movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */ punpckhwd %mm6, %mm2 movd %mm5, 8*9(%esi) /* LS part of tmt9 */ punpckhdq %mm3, %mm5 /* free mm3 */ movd %mm2, 8*13(%esi) /* LS part of tmt13 */ punpckhdq %mm7, %mm2 /* free mm7 */ /* moved up from the M3 transpose */ movq 8*8(%esi), %mm0 /* moved up from the M3 transpose */ movq 8*10(%esi), %mm1 /* moved up from the M3 transpose */ movq %mm0, %mm3 /* shuffle the rest of the data, and write it with 2 mmword writes */ movq %mm5, 8*11(%esi) /* tmt11 */ /* moved up from the M3 transpose */ punpcklwd %mm1, %mm0 movq %mm2, 8*15(%esi) /* tmt15 */ /* moved up from the M3 transpose */ punpckhwd %mm1, %mm3 /* transpose - M3 part * moved up to previous code section * movq 8*8(%esi), %mm0 * movq 8*10(%esi), %mm1 * movq %mm0, %mm3 * punpcklwd %mm1, %mm0 * punpckhwd %mm1, %mm3 */ movq 8*12(%esi), %mm6 movq 8*14(%esi), %mm4 movq %mm6, %mm2 /* shuffle the data and write the lower parts of the transposed in 4 dwords */ punpcklwd %mm4, %mm6 movq %mm0, %mm1 punpckhdq %mm6, %mm1 movq %mm3, %mm7 punpckhwd %mm4, %mm2 /* free mm4 */ punpckldq %mm6, %mm0 /* free mm6 */ /* moved from next block */ movq 8*13(%esi), %mm4 /* tmt13 */ punpckldq %mm2, %mm3 punpckhdq %mm2, %mm7 /* free mm2 */ /* moved from next block */ movq %mm3, %mm5 /* duplicate tmt5 */ /* column 1: even part (after transpose) * moved above * movq %mm3, %mm5 duplicate tmt5 * movq 8*13(%esi), %mm4 tmt13 */ psubsw %mm4, %mm3 /* V134 */ pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */ movq 8*9(%esi), %mm6 /* tmt9 */ paddsw %mm4, %mm5 /* V135 ; mm4 free */ movq %mm0, %mm4 /* duplicate tmt1 */ paddsw %mm6, %mm0 /* V137 */ psubsw %mm6, %mm4 /* V138 ; mm6 free */ psllw $2, %mm3 /* t290 */ psubsw %mm5, %mm3 /* V139 */ movq %mm0, %mm6 /* duplicate V137 */ paddsw %mm5, %mm0 /* V140 */ movq %mm4, %mm2 /* duplicate V138 */ paddsw %mm3, %mm2 /* V141 */ psubsw %mm3, %mm4 /* V142 ; mm3 free */ movq %mm0, 8*9(%esi) /* V140 */ psubsw %mm5, %mm6 /* V143 ; mm5 free */ /* moved from next block */ movq 8*11(%esi), %mm0 /* tmt11 */ movq %mm2, 8*13(%esi) /* V141 */ /* moved from next block */ movq %mm0, %mm2 /* duplicate tmt11 */ /* column 1: odd part (after transpose) */ /* moved up to the prev block * movq 8*11(%esi), %mm0 tmt11 * movq %mm0, %mm2 duplicate tmt11 */ movq 8*15(%esi), %mm5 /* tmt15 */ psubsw %mm7, %mm0 /* V144 */ movq %mm0, %mm3 /* duplicate V144 */ paddsw %mm7, %mm2 /* V147 ; free mm7 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */ movq %mm1, %mm7 /* duplicate tmt3 */ paddsw %mm5, %mm7 /* V145 */ psubsw %mm5, %mm1 /* V146 ; free mm5 */ psubsw %mm1, %mm3 /* V150 */ movq %mm7, %mm5 /* duplicate V145 */ pmulhw x4546454645464546, %mm1 /* 17734-> V153 */ psubsw %mm2, %mm5 /* V148 */ pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */ psllw $2, %mm0 /* t311 */ pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */ paddsw %mm2, %mm7 /* V149 ; free mm2 */ psllw $1, %mm1 /* t313 */ nop /* without the nop - freeze here for one clock */ movq %mm3, %mm2 /* duplicate V154 */ psubsw %mm0, %mm3 /* V155 ; free mm0 */ psubsw %mm2, %mm1 /* V156 ; free mm2 */ /* moved from the next block */ movq %mm6, %mm2 /* duplicate V143 */ /* moved from the next block */ movq 8*13(%esi), %mm0 /* V141 */ psllw $1, %mm1 /* t315 */ psubsw %mm7, %mm1 /* V157 (keep V149) */ psllw $2, %mm5 /* t317 */ psubsw %mm1, %mm5 /* V158 */ psllw $1, %mm3 /* t319 */ paddsw %mm5, %mm3 /* V159 */ /* column 1: output butterfly (after transform) * moved to the prev block * movq %mm6, %mm2 duplicate V143 * movq 8*13(%esi), %mm0 V141 */ psubsw %mm3, %mm2 /* V163 */ paddsw %mm3, %mm6 /* V164 ; free mm3 */ movq %mm4, %mm3 /* duplicate V142 */ psubsw %mm5, %mm4 /* V165 ; free mm5 */ movq %mm2, (%esp) /* out7 */ psraw $4, %mm6 psraw $4, %mm4 paddsw %mm5, %mm3 /* V162 */ movq 8*9(%esi), %mm2 /* V140 */ movq %mm0, %mm5 /* duplicate V141 */ /* in order not to perculate this line up, * we read 72(%esi) very near to this location */ movq %mm6, 8*9(%esi) /* out9 */ paddsw %mm1, %mm0 /* V161 */ movq %mm3, 8(%esp) /* out5 */ psubsw %mm1, %mm5 /* V166 ; free mm1 */ movq %mm4, 8*11(%esi) /* out11 */ psraw $4, %mm5 movq %mm0, 16(%esp) /* out3 */ movq %mm2, %mm4 /* duplicate V140 */ movq %mm5, 8*13(%esi) /* out13 */ paddsw %mm7, %mm2 /* V160 */ /* moved from the next block */ movq 8(%esi), %mm0 psubsw %mm7, %mm4 /* V167 ; free mm7 */ /* moved from the next block */ movq 8*3(%esi), %mm7 psraw $4, %mm4 movq %mm2, 24(%esp) /* out1 */ /* moved from the next block */ movq %mm0, %mm1 movq %mm4, 8*15(%esi) /* out15 */ /* moved from the next block */ punpcklwd %mm7, %mm0 /* transpose - M2 parts * moved up to the prev block * movq 8(%esi), %mm0 * movq 8*3(%esi), %mm7 * movq %mm0, %mm1 * punpcklwd %mm7, %mm0 */ movq 8*5(%esi), %mm5 punpckhwd %mm7, %mm1 movq 8*7(%esi), %mm4 movq %mm5, %mm3 /* shuffle the data and write the lower parts of the trasposed in 4 dwords */ movd %mm0, 8*8(%esi) /* LS part of tmt8 */ punpcklwd %mm4, %mm5 movd %mm1, 8*12(%esi) /* LS part of tmt12 */ punpckhwd %mm4, %mm3 movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */ punpckhdq %mm5, %mm0 /* tmt10 */ movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */ punpckhdq %mm3, %mm1 /* tmt14 */ /* transpose - M1 parts */ movq (%esi), %mm7 movq 8*2(%esi), %mm2 movq %mm7, %mm6 movq 8*4(%esi), %mm5 punpcklwd %mm2, %mm7 movq 8*6(%esi), %mm4 punpckhwd %mm2, %mm6 /* free mm2 */ movq %mm5, %mm3 punpcklwd %mm4, %mm5 punpckhwd %mm4, %mm3 /* free mm4 */ movq %mm7, %mm2 movq %mm6, %mm4 punpckldq %mm5, %mm7 /* tmt0 */ punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */ /* shuffle the rest of the data, and write it with 2 mmword writes */ punpckldq %mm3, %mm6 /* tmt4 */ /* moved from next block */ movq %mm2, %mm5 /* duplicate tmt2 */ punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */ /* moved from next block */ movq %mm0, %mm3 /* duplicate tmt10 */ /* column 0: odd part (after transpose) *moved up to prev block * movq %mm0, %mm3 duplicate tmt10 * movq %mm2, %mm5 duplicate tmt2 */ psubsw %mm4, %mm0 /* V110 */ paddsw %mm4, %mm3 /* V113 ; free mm4 */ movq %mm0, %mm4 /* duplicate V110 */ paddsw %mm1, %mm2 /* V111 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */ psubsw %mm1, %mm5 /* V112 ; free mm1 */ psubsw %mm5, %mm4 /* V116 */ movq %mm2, %mm1 /* duplicate V111 */ pmulhw x4546454645464546, %mm5 /* 17734-> V119 */ psubsw %mm3, %mm2 /* V114 */ pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */ paddsw %mm3, %mm1 /* V115 ; free mm3 */ pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */ psllw $2, %mm0 /* t266 */ movq %mm1, (%esi) /* save V115 */ psllw $1, %mm5 /* t268 */ psubsw %mm4, %mm5 /* V122 */ psubsw %mm0, %mm4 /* V121 ; free mm0 */ psllw $1, %mm5 /* t270 */ psubsw %mm1, %mm5 /* V123 ; free mm1 */ psllw $2, %mm2 /* t272 */ psubsw %mm5, %mm2 /* V124 (keep V123) */ psllw $1, %mm4 /* t274 */ movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */ paddsw %mm2, %mm4 /* V125 (keep V124) */ /* column 0: even part (after transpose) */ movq 8*12(%esi), %mm0 /* tmt12 */ movq %mm6, %mm3 /* duplicate tmt4 */ psubsw %mm0, %mm6 /* V100 */ paddsw %mm0, %mm3 /* V101 ; free mm0 */ pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */ movq %mm7, %mm5 /* duplicate tmt0 */ movq 8*8(%esi), %mm1 /* tmt8 */ paddsw %mm1, %mm7 /* V103 */ psubsw %mm1, %mm5 /* V104 ; free mm1 */ movq %mm7, %mm0 /* duplicate V103 */ psllw $2, %mm6 /* t245 */ paddsw %mm3, %mm7 /* V106 */ movq %mm5, %mm1 /* duplicate V104 */ psubsw %mm3, %mm6 /* V105 */ psubsw %mm3, %mm0 /* V109; free mm3 */ paddsw %mm6, %mm5 /* V107 */ psubsw %mm6, %mm1 /* V108 ; free mm6 */ /* column 0: output butterfly (after transform) */ movq %mm1, %mm3 /* duplicate V108 */ paddsw %mm2, %mm1 /* out4 */ psraw $4, %mm1 psubsw %mm2, %mm3 /* out10 ; free mm2 */ psraw $4, %mm3 movq %mm0, %mm6 /* duplicate V109 */ movq %mm1, 8*4(%esi) /* out4 ; free mm1 */ psubsw %mm4, %mm0 /* out6 */ movq %mm3, 8*10(%esi) /* out10 ; free mm3 */ psraw $4, %mm0 paddsw %mm4, %mm6 /* out8 ; free mm4 */ movq %mm7, %mm1 /* duplicate V106 */ movq %mm0, 8*6(%esi) /* out6 ; free mm0 */ psraw $4, %mm6 movq (%esi), %mm4 /* V115 */ movq %mm6, 8*8(%esi) /* out8 ; free mm6 */ movq %mm5, %mm2 /* duplicate V107 */ movq 8*2(%esi), %mm3 /* V123 */ paddsw %mm4, %mm7 /* out0 */ /* moved up from next block */ movq 16(%esp), %mm0 psraw $4, %mm7 /* moved up from next block */ movq 8(%esp), %mm6 psubsw %mm4, %mm1 /* out14 ; free mm4 */ paddsw %mm3, %mm5 /* out2 */ psraw $4, %mm1 movq %mm7, (%esi) /* out0 ; free mm7 */ psraw $4, %mm5 movq %mm1, 8*14(%esi) /* out14 ; free mm1 */ psubsw %mm3, %mm2 /* out12 ; free mm3 */ movq %mm5, 8*2(%esi) /* out2 ; free mm5 */ psraw $4, %mm2 /* moved up to the prev block */ movq (%esp), %mm4 /* moved up to the prev block */ psraw $4, %mm0 movq %mm2, 8*12(%esi) /* out12 ; free mm2 */ /* moved up to the prev block */ psraw $4, %mm6 /* move back the data to its correct place * moved up to the prev block * movq 16(%esp), %mm0 * movq 8(%esp), %mm6 * movq (%esp), %mm4 * psraw $4, %mm0 * psraw $4, %mm6 */ movq 24(%esp), %mm1 psraw $4, %mm4 movq %mm0, 8*3(%esi) /* out3 */ psraw $4, %mm1 movq %mm6, 8*5(%esi) /* out5 */ movq %mm4, 8*7(%esi) /* out7 */ movq %mm1, 8(%esi) /* out1 */ popl %edi /* Pop off the temp variables */ popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi /* Pop off the old variables */ popl %esi popl %edx popl %ecx popl %ebx movl %ebp, %esp popl %ebp ret .Lfe1: .size IDCT_mmx,.Lfe1-IDCT_mmx ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mmxidct_orig.S ================================================ /* * the input data is tranposed and each 16 bit element in the 8x8 matrix * is left aligned: * for example in 11...1110000 format * If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component * (element[0][0] of the matrix) */ /* extrn re_matrix */ /* constants */ .data .align 16 .type preSC, @object preSC: .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270 .short 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906 .short 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315 .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 .short 12873, 17855, 16819, 15137, 25746, 20228, 13933, 7103 .short 17734, 24598, 23170, 20853, 17734, 13933, 9597, 4892 .short 18081, 25080, 23624, 21261, 18081, 14206, 9785, 4988 .size preSC, 128 .align 8 .type x0005000200010001, @object .size x0005000200010001, 8 x0005000200010001: .long 0x00010001, 0x00050002 .align 8 .type x0040000000000000, @object .size x0040000000000000, 8 x0040000000000000: .long 0, 0x00400000 .align 8 .type x5a825a825a825a82, @object .size x5a825a825a825a82, 8 x5a825a825a825a82: .long 0x5a825a82, 0x5a825a82 .align 8 .type x539f539f539f539f, @object .size x539f539f539f539f, 8 x539f539f539f539f: .long 0x539f539f, 0x539f539f .align 8 .type x4546454645464546, @object .size x4546454645464546, 8 x4546454645464546: .long 0x45464546, 0x45464546 .align 8 .type x61f861f861f861f8, @object .size x61f861f861f861f8, 8 x61f861f861f861f8: .long 0x61f861f8, 0x61f861f8 /* Static variables */ .align 8 .type x0, @object .size x0, 8 x0: .long 0, 0 /* Procedure */ .align 8 .text .align 4 .globl IDCT_mmx .type IDCT_mmx, @function IDCT_mmx: pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx pushl %esi pushl %edi pushl $0 /* allocate the temp variables */ pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 pushl $0 movl 8(%ebp), %esi /* source matrix */ leal preSC, %ecx /* column 0: even part * use V4, V12, V0, V8 to produce V22..V25 */ movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */ /* with the dequantization in iHuff module */ pmulhw 8*12(%esi), %mm0 /* V12 */ movq 8*4(%ecx), %mm1 pmulhw 8*4(%esi), %mm1 /* V4 */ movq (%ecx), %mm3 psraw $1, %mm0 /* t64=t66 */ pmulhw (%esi), %mm3 /* V0 */ movq 8*8(%ecx), %mm5 /* duplicate V4 */ movq %mm1, %mm2 /* added 11/1/96 */ pmulhw 8*8(%esi),%mm5 /* V8 */ psubsw %mm0, %mm1 /* V16 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */ paddsw %mm0, %mm2 /* V17 */ movq %mm2, %mm0 /* duplicate V17 */ psraw $1, %mm2 /* t75=t82 */ psraw $2, %mm0 /* t72 */ movq %mm3, %mm4 /* duplicate V0 */ paddsw %mm5, %mm3 /* V19 */ psubsw %mm5, %mm4 /* V20 ;mm5 free */ /* moved from the block below */ movq 8*10(%ecx), %mm7 psraw $1, %mm3 /* t74=t81 */ movq %mm3, %mm6 /* duplicate t74=t81 */ psraw $2, %mm4 /* t77=t79 */ psubsw %mm0, %mm1 /* V21 ; mm0 free */ paddsw %mm2, %mm3 /* V22 */ movq %mm1, %mm5 /* duplicate V21 */ paddsw %mm4, %mm1 /* V23 */ movq %mm3, 8*4(%esi) /* V22 */ psubsw %mm5, %mm4 /* V24; mm5 free */ movq %mm1, 8*12(%esi) /* V23 */ psubsw %mm2, %mm6 /* V25; mm2 free */ movq %mm4, (%esi) /* V24 */ /* keep mm6 alive all along the next block */ /* movq %mm6, 8*8(%esi) V25 */ /* column 0: odd part * use V2, V6, V10, V14 to produce V31, V39, V40, V41 */ /* moved above: movq 8*10(%ecx), %mm7 */ pmulhw 8*10(%esi), %mm7 /* V10 */ movq 8*6(%ecx), %mm0 pmulhw 8*6(%esi), %mm0 /* V6 */ movq 8*2(%ecx), %mm5 movq %mm7, %mm3 /* duplicate V10 */ pmulhw 8*2(%esi), %mm5 /* V2 */ movq 8*14(%ecx), %mm4 psubsw %mm0, %mm7 /* V26 */ pmulhw 8*14(%esi), %mm4 /* V14 */ paddsw %mm0, %mm3 /* V29 ; free mm0 */ movq %mm7, %mm1 /* duplicate V26 */ psraw $1, %mm3 /* t91=t94 */ pmulhw x539f539f539f539f,%mm7 /* V33 */ psraw $1, %mm1 /* t96 */ movq %mm5, %mm0 /* duplicate V2 */ psraw $2, %mm4 /* t85=t87 */ paddsw %mm4,%mm5 /* V27 */ psubsw %mm4, %mm0 /* V28 ; free mm4 */ movq %mm0, %mm2 /* duplicate V28 */ psraw $1, %mm5 /* t90=t93 */ pmulhw x4546454645464546,%mm0 /* V35 */ psraw $1, %mm2 /* t97 */ movq %mm5, %mm4 /* duplicate t90=t93 */ psubsw %mm2, %mm1 /* V32 ; free mm2 */ pmulhw x61f861f861f861f8,%mm1 /* V36 */ psllw $1, %mm7 /* t107 */ paddsw %mm3, %mm5 /* V31 */ psubsw %mm3, %mm4 /* V30 ; free mm3 */ pmulhw x5a825a825a825a82,%mm4 /* V34 */ nop psubsw %mm1, %mm0 /* V38 */ psubsw %mm7, %mm1 /* V37 ; free mm7 */ psllw $1, %mm1 /* t114 */ /* move from the next block */ movq %mm6, %mm3 /* duplicate V25 */ /* move from the next block */ movq 8*4(%esi), %mm7 /* V22 */ psllw $1, %mm0 /* t110 */ psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */ psllw $2, %mm4 /* t112 */ /* moved from the next block */ movq 8*12(%esi), %mm2 /* V23 */ psubsw %mm0, %mm4 /* V40 */ paddsw %mm4, %mm1 /* V41; free mm0 */ /* moved from the next block */ psllw $1, %mm2 /* t117=t125 */ /* column 0: output butterfly */ /* moved above: * movq %mm6, %mm3 duplicate V25 * movq 8*4(%esi), %mm7 V22 * movq 8*12(%esi), %mm2 V23 * psllw $1, %mm2 t117=t125 */ psubsw %mm1, %mm6 /* tm6 */ paddsw %mm1, %mm3 /* tm8; free mm1 */ movq %mm7, %mm1 /* duplicate V22 */ paddsw %mm5, %mm7 /* tm0 */ movq %mm3, 8*8(%esi) /* tm8; free mm3 */ psubsw %mm5, %mm1 /* tm14; free mm5 */ movq %mm6, 8*6(%esi) /* tm6; free mm6 */ movq %mm2, %mm3 /* duplicate t117=t125 */ movq (%esi), %mm6 /* V24 */ paddsw %mm0, %mm2 /* tm2 */ movq %mm7, (%esi) /* tm0; free mm7 */ psubsw %mm0, %mm3 /* tm12; free mm0 */ movq %mm1, 8*14(%esi) /* tm14; free mm1 */ psllw $1, %mm6 /* t119=t123 */ movq %mm2, 8*2(%esi) /* tm2; free mm2 */ movq %mm6, %mm0 /* duplicate t119=t123 */ movq %mm3, 8*12(%esi) /* tm12; free mm3 */ paddsw %mm4, %mm6 /* tm4 */ /* moved from next block */ movq 8*5(%ecx), %mm1 psubsw %mm4, %mm0 /* tm10; free mm4 */ /* moved from next block */ pmulhw 8*5(%esi), %mm1 /* V5 */ movq %mm6, 8*4(%esi) /* tm4; free mm6 */ movq %mm0, 8*10(%esi) /* tm10; free mm0 */ /* column 1: even part * use V5, V13, V1, V9 to produce V56..V59 */ /* moved to prev block: * movq 8*5(%ecx), %mm1 * pmulhw 8*5(%esi), %mm1 V5 */ movq 8*13(%ecx), %mm7 psllw $1, %mm1 /* t128=t130 */ pmulhw 8*13(%esi), %mm7 /* V13 */ movq %mm1, %mm2 /* duplicate t128=t130 */ movq 8(%ecx), %mm3 pmulhw 8(%esi), %mm3 /* V1 */ movq 8*9(%ecx), %mm5 psubsw %mm7, %mm1 /* V50 */ pmulhw 8*9(%esi), %mm5 /* V9 */ paddsw %mm7, %mm2 /* V51 */ pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */ movq %mm2, %mm6 /* duplicate V51 */ psraw $1, %mm2 /* t138=t144 */ movq %mm3, %mm4 /* duplicate V1 */ psraw $2, %mm6 /* t136 */ paddsw %mm5, %mm3 /* V53 */ psubsw %mm5, %mm4 /* V54 ;mm5 free */ movq %mm3, %mm7 /* duplicate V53 */ /* moved from next block */ movq 8*11(%ecx), %mm0 psraw $1, %mm4 /* t140=t142 */ psubsw %mm6, %mm1 /* V55 ; mm6 free */ paddsw %mm2, %mm3 /* V56 */ movq %mm4, %mm5 /* duplicate t140=t142 */ paddsw %mm1, %mm4 /* V57 */ movq %mm3, 8*5(%esi) /* V56 */ psubsw %mm1, %mm5 /* V58; mm1 free */ movq %mm4, 8*13(%esi) /* V57 */ psubsw %mm2, %mm7 /* V59; mm2 free */ movq %mm5, 8*9(%esi) /* V58 */ /* keep mm7 alive all along the next block * movq %mm7, 8(%esi) V59 * moved above * movq 8*11(%ecx), %mm0 */ pmulhw 8*11(%esi), %mm0 /* V11 */ movq 8*7(%ecx), %mm6 pmulhw 8*7(%esi), %mm6 /* V7 */ movq 8*15(%ecx), %mm4 movq %mm0, %mm3 /* duplicate V11 */ pmulhw 8*15(%esi), %mm4 /* V15 */ movq 8*3(%ecx), %mm5 psllw $1, %mm6 /* t146=t152 */ pmulhw 8*3(%esi), %mm5 /* V3 */ paddsw %mm6, %mm0 /* V63 */ /* note that V15 computation has a correction step: * this is a 'magic' constant that rebiases the results to be closer to the * expected result. this magic constant can be refined to reduce the error * even more by doing the correction step in a later stage when the number * is actually multiplied by 16 */ paddw x0005000200010001, %mm4 psubsw %mm6, %mm3 /* V60 ; free mm6 */ psraw $1, %mm0 /* t154=t156 */ movq %mm3, %mm1 /* duplicate V60 */ pmulhw x539f539f539f539f, %mm1 /* V67 */ movq %mm5, %mm6 /* duplicate V3 */ psraw $2, %mm4 /* t148=t150 */ paddsw %mm4, %mm5 /* V61 */ psubsw %mm4, %mm6 /* V62 ; free mm4 */ movq %mm5, %mm4 /* duplicate V61 */ psllw $1, %mm1 /* t169 */ paddsw %mm0, %mm5 /* V65 -> result */ psubsw %mm0, %mm4 /* V64 ; free mm0 */ pmulhw x5a825a825a825a82, %mm4 /* V68 */ psraw $1, %mm3 /* t158 */ psubsw %mm6, %mm3 /* V66 */ movq %mm5, %mm2 /* duplicate V65 */ pmulhw x61f861f861f861f8, %mm3 /* V70 */ psllw $1, %mm6 /* t165 */ pmulhw x4546454645464546, %mm6 /* V69 */ psraw $1, %mm2 /* t172 */ /* moved from next block */ movq 8*5(%esi), %mm0 /* V56 */ psllw $1, %mm4 /* t174 */ /* moved from next block */ psraw $1, %mm0 /* t177=t188 */ nop psubsw %mm3, %mm6 /* V72 */ psubsw %mm1, %mm3 /* V71 ; free mm1 */ psubsw %mm2, %mm6 /* V73 ; free mm2 */ /* moved from next block */ psraw $1, %mm5 /* t178=t189 */ psubsw %mm6, %mm4 /* V74 */ /* moved from next block */ movq %mm0, %mm1 /* duplicate t177=t188 */ paddsw %mm4, %mm3 /* V75 */ /* moved from next block */ paddsw %mm5, %mm0 /* tm1 */ /* location * 5 - V56 * 13 - V57 * 9 - V58 * X - V59, mm7 * X - V65, mm5 * X - V73, mm6 * X - V74, mm4 * X - V75, mm3 * free mm0, mm1 & mm2 * moved above * movq 8*5(%esi), %mm0 V56 * psllw $1, %mm0 t177=t188 ! new !! * psllw $1, %mm5 t178=t189 ! new !! * movq %mm0, %mm1 duplicate t177=t188 * paddsw %mm5, %mm0 tm1 */ movq 8*13(%esi), %mm2 /* V57 */ psubsw %mm5, %mm1 /* tm15; free mm5 */ movq %mm0, 8(%esi) /* tm1; free mm0 */ psraw $1, %mm7 /* t182=t184 ! new !! */ /* save the store as used directly in the transpose * movq %mm1, 120(%esi) tm15; free mm1 */ movq %mm7, %mm5 /* duplicate t182=t184 */ psubsw %mm3, %mm7 /* tm7 */ paddsw %mm3, %mm5 /* tm9; free mm3 */ movq 8*9(%esi), %mm0 /* V58 */ movq %mm2, %mm3 /* duplicate V57 */ movq %mm7, 8*7(%esi) /* tm7; free mm7 */ psubsw %mm6, %mm3 /* tm13 */ paddsw %mm6, %mm2 /* tm3 ; free mm6 */ /* moved up from the transpose */ movq %mm3, %mm7 /* moved up from the transpose */ punpcklwd %mm1, %mm3 movq %mm0, %mm6 /* duplicate V58 */ movq %mm2, 8*3(%esi) /* tm3; free mm2 */ paddsw %mm4, %mm0 /* tm5 */ psubsw %mm4, %mm6 /* tm11; free mm4 */ /* moved up from the transpose */ punpckhwd %mm1, %mm7 movq %mm0, 8*5(%esi) /* tm5; free mm0 */ /* moved up from the transpose */ movq %mm5, %mm2 /* transpose - M4 part * --------- --------- * | M1 | M2 | | M1'| M3'| * --------- --> --------- * | M3 | M4 | | M2'| M4'| * --------- --------- * Two alternatives: use full mmword approach so the following code can be * scheduled before the transpose is done without stores, or use the faster * half mmword stores (when possible) */ movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */ punpcklwd %mm6, %mm5 movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */ punpckhwd %mm6, %mm2 movd %mm5, 8*9(%esi) /* LS part of tmt9 */ punpckhdq %mm3, %mm5 /* free mm3 */ movd %mm2, 8*13(%esi) /* LS part of tmt13 */ punpckhdq %mm7, %mm2 /* free mm7 */ /* moved up from the M3 transpose */ movq 8*8(%esi), %mm0 /* moved up from the M3 transpose */ movq 8*10(%esi), %mm1 /* moved up from the M3 transpose */ movq %mm0, %mm3 /* shuffle the rest of the data, and write it with 2 mmword writes */ movq %mm5, 8*11(%esi) /* tmt11 */ /* moved up from the M3 transpose */ punpcklwd %mm1, %mm0 movq %mm2, 8*15(%esi) /* tmt15 */ /* moved up from the M3 transpose */ punpckhwd %mm1, %mm3 /* transpose - M3 part * moved up to previous code section * movq 8*8(%esi), %mm0 * movq 8*10(%esi), %mm1 * movq %mm0, %mm3 * punpcklwd %mm1, %mm0 * punpckhwd %mm1, %mm3 */ movq 8*12(%esi), %mm6 movq 8*14(%esi), %mm4 movq %mm6, %mm2 /* shuffle the data and write the lower parts of the transposed in 4 dwords */ punpcklwd %mm4, %mm6 movq %mm0, %mm1 punpckhdq %mm6, %mm1 movq %mm3, %mm7 punpckhwd %mm4, %mm2 /* free mm4 */ punpckldq %mm6, %mm0 /* free mm6 */ /* moved from next block */ movq 8*13(%esi), %mm4 /* tmt13 */ punpckldq %mm2, %mm3 punpckhdq %mm2, %mm7 /* free mm2 */ /* moved from next block */ movq %mm3, %mm5 /* duplicate tmt5 */ /* column 1: even part (after transpose) * moved above * movq %mm3, %mm5 duplicate tmt5 * movq 8*13(%esi), %mm4 tmt13 */ psubsw %mm4, %mm3 /* V134 */ pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */ movq 8*9(%esi), %mm6 /* tmt9 */ paddsw %mm4, %mm5 /* V135 ; mm4 free */ movq %mm0, %mm4 /* duplicate tmt1 */ paddsw %mm6, %mm0 /* V137 */ psubsw %mm6, %mm4 /* V138 ; mm6 free */ psllw $2, %mm3 /* t290 */ psubsw %mm5, %mm3 /* V139 */ movq %mm0, %mm6 /* duplicate V137 */ paddsw %mm5, %mm0 /* V140 */ movq %mm4, %mm2 /* duplicate V138 */ paddsw %mm3, %mm2 /* V141 */ psubsw %mm3, %mm4 /* V142 ; mm3 free */ movq %mm0, 8*9(%esi) /* V140 */ psubsw %mm5, %mm6 /* V143 ; mm5 free */ /* moved from next block */ movq 8*11(%esi), %mm0 /* tmt11 */ movq %mm2, 8*13(%esi) /* V141 */ /* moved from next block */ movq %mm0, %mm2 /* duplicate tmt11 */ /* column 1: odd part (after transpose) */ /* moved up to the prev block * movq 8*11(%esi), %mm0 tmt11 * movq %mm0, %mm2 duplicate tmt11 */ movq 8*15(%esi), %mm5 /* tmt15 */ psubsw %mm7, %mm0 /* V144 */ movq %mm0, %mm3 /* duplicate V144 */ paddsw %mm7, %mm2 /* V147 ; free mm7 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */ movq %mm1, %mm7 /* duplicate tmt3 */ paddsw %mm5, %mm7 /* V145 */ psubsw %mm5, %mm1 /* V146 ; free mm5 */ psubsw %mm1, %mm3 /* V150 */ movq %mm7, %mm5 /* duplicate V145 */ pmulhw x4546454645464546, %mm1 /* 17734-> V153 */ psubsw %mm2, %mm5 /* V148 */ pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */ psllw $2, %mm0 /* t311 */ pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */ paddsw %mm2, %mm7 /* V149 ; free mm2 */ psllw $1, %mm1 /* t313 */ nop /* without the nop - freeze here for one clock */ movq %mm3, %mm2 /* duplicate V154 */ psubsw %mm0, %mm3 /* V155 ; free mm0 */ psubsw %mm2, %mm1 /* V156 ; free mm2 */ /* moved from the next block */ movq %mm6, %mm2 /* duplicate V143 */ /* moved from the next block */ movq 8*13(%esi), %mm0 /* V141 */ psllw $1, %mm1 /* t315 */ psubsw %mm7, %mm1 /* V157 (keep V149) */ psllw $2, %mm5 /* t317 */ psubsw %mm1, %mm5 /* V158 */ psllw $1, %mm3 /* t319 */ paddsw %mm5, %mm3 /* V159 */ /* column 1: output butterfly (after transform) * moved to the prev block * movq %mm6, %mm2 duplicate V143 * movq 8*13(%esi), %mm0 V141 */ psubsw %mm3, %mm2 /* V163 */ paddsw %mm3, %mm6 /* V164 ; free mm3 */ movq %mm4, %mm3 /* duplicate V142 */ psubsw %mm5, %mm4 /* V165 ; free mm5 */ movq %mm2, (%esp) /* out7 */ psraw $4, %mm6 psraw $4, %mm4 paddsw %mm5, %mm3 /* V162 */ movq 8*9(%esi), %mm2 /* V140 */ movq %mm0, %mm5 /* duplicate V141 */ /* in order not to perculate this line up, * we read 72(%esi) very near to this location */ movq %mm6, 8*9(%esi) /* out9 */ paddsw %mm1, %mm0 /* V161 */ movq %mm3, 8(%esp) /* out5 */ psubsw %mm1, %mm5 /* V166 ; free mm1 */ movq %mm4, 8*11(%esi) /* out11 */ psraw $4, %mm5 movq %mm0, 16(%esp) /* out3 */ movq %mm2, %mm4 /* duplicate V140 */ movq %mm5, 8*13(%esi) /* out13 */ paddsw %mm7, %mm2 /* V160 */ /* moved from the next block */ movq 8(%esi), %mm0 psubsw %mm7, %mm4 /* V167 ; free mm7 */ /* moved from the next block */ movq 8*3(%esi), %mm7 psraw $4, %mm4 movq %mm2, 24(%esp) /* out1 */ /* moved from the next block */ movq %mm0, %mm1 movq %mm4, 8*15(%esi) /* out15 */ /* moved from the next block */ punpcklwd %mm7, %mm0 /* transpose - M2 parts * moved up to the prev block * movq 8(%esi), %mm0 * movq 8*3(%esi), %mm7 * movq %mm0, %mm1 * punpcklwd %mm7, %mm0 */ movq 8*5(%esi), %mm5 punpckhwd %mm7, %mm1 movq 8*7(%esi), %mm4 movq %mm5, %mm3 /* shuffle the data and write the lower parts of the trasposed in 4 dwords */ movd %mm0, 8*8(%esi) /* LS part of tmt8 */ punpcklwd %mm4, %mm5 movd %mm1, 8*12(%esi) /* LS part of tmt12 */ punpckhwd %mm4, %mm3 movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */ punpckhdq %mm5, %mm0 /* tmt10 */ movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */ punpckhdq %mm3, %mm1 /* tmt14 */ /* transpose - M1 parts */ movq (%esi), %mm7 movq 8*2(%esi), %mm2 movq %mm7, %mm6 movq 8*4(%esi), %mm5 punpcklwd %mm2, %mm7 movq 8*6(%esi), %mm4 punpckhwd %mm2, %mm6 /* free mm2 */ movq %mm5, %mm3 punpcklwd %mm4, %mm5 punpckhwd %mm4, %mm3 /* free mm4 */ movq %mm7, %mm2 movq %mm6, %mm4 punpckldq %mm5, %mm7 /* tmt0 */ punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */ /* shuffle the rest of the data, and write it with 2 mmword writes */ punpckldq %mm3, %mm6 /* tmt4 */ /* moved from next block */ movq %mm2, %mm5 /* duplicate tmt2 */ punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */ /* moved from next block */ movq %mm0, %mm3 /* duplicate tmt10 */ /* column 0: odd part (after transpose) *moved up to prev block * movq %mm0, %mm3 duplicate tmt10 * movq %mm2, %mm5 duplicate tmt2 */ psubsw %mm4, %mm0 /* V110 */ paddsw %mm4, %mm3 /* V113 ; free mm4 */ movq %mm0, %mm4 /* duplicate V110 */ paddsw %mm1, %mm2 /* V111 */ pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */ psubsw %mm1, %mm5 /* V112 ; free mm1 */ psubsw %mm5, %mm4 /* V116 */ movq %mm2, %mm1 /* duplicate V111 */ pmulhw x4546454645464546, %mm5 /* 17734-> V119 */ psubsw %mm3, %mm2 /* V114 */ pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */ paddsw %mm3, %mm1 /* V115 ; free mm3 */ pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */ psllw $2, %mm0 /* t266 */ movq %mm1, (%esi) /* save V115 */ psllw $1, %mm5 /* t268 */ psubsw %mm4, %mm5 /* V122 */ psubsw %mm0, %mm4 /* V121 ; free mm0 */ psllw $1, %mm5 /* t270 */ psubsw %mm1, %mm5 /* V123 ; free mm1 */ psllw $2, %mm2 /* t272 */ psubsw %mm5, %mm2 /* V124 (keep V123) */ psllw $1, %mm4 /* t274 */ movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */ paddsw %mm2, %mm4 /* V125 (keep V124) */ /* column 0: even part (after transpose) */ movq 8*12(%esi), %mm0 /* tmt12 */ movq %mm6, %mm3 /* duplicate tmt4 */ psubsw %mm0, %mm6 /* V100 */ paddsw %mm0, %mm3 /* V101 ; free mm0 */ pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */ movq %mm7, %mm5 /* duplicate tmt0 */ movq 8*8(%esi), %mm1 /* tmt8 */ paddsw %mm1, %mm7 /* V103 */ psubsw %mm1, %mm5 /* V104 ; free mm1 */ movq %mm7, %mm0 /* duplicate V103 */ psllw $2, %mm6 /* t245 */ paddsw %mm3, %mm7 /* V106 */ movq %mm5, %mm1 /* duplicate V104 */ psubsw %mm3, %mm6 /* V105 */ psubsw %mm3, %mm0 /* V109; free mm3 */ paddsw %mm6, %mm5 /* V107 */ psubsw %mm6, %mm1 /* V108 ; free mm6 */ /* column 0: output butterfly (after transform) */ movq %mm1, %mm3 /* duplicate V108 */ paddsw %mm2, %mm1 /* out4 */ psraw $4, %mm1 psubsw %mm2, %mm3 /* out10 ; free mm2 */ psraw $4, %mm3 movq %mm0, %mm6 /* duplicate V109 */ movq %mm1, 8*4(%esi) /* out4 ; free mm1 */ psubsw %mm4, %mm0 /* out6 */ movq %mm3, 8*10(%esi) /* out10 ; free mm3 */ psraw $4, %mm0 paddsw %mm4, %mm6 /* out8 ; free mm4 */ movq %mm7, %mm1 /* duplicate V106 */ movq %mm0, 8*6(%esi) /* out6 ; free mm0 */ psraw $4, %mm6 movq (%esi), %mm4 /* V115 */ movq %mm6, 8*8(%esi) /* out8 ; free mm6 */ movq %mm5, %mm2 /* duplicate V107 */ movq 8*2(%esi), %mm3 /* V123 */ paddsw %mm4, %mm7 /* out0 */ /* moved up from next block */ movq 16(%esp), %mm0 psraw $4, %mm7 /* moved up from next block */ movq 8(%esp), %mm6 psubsw %mm4, %mm1 /* out14 ; free mm4 */ paddsw %mm3, %mm5 /* out2 */ psraw $4, %mm1 movq %mm7, (%esi) /* out0 ; free mm7 */ psraw $4, %mm5 movq %mm1, 8*14(%esi) /* out14 ; free mm1 */ psubsw %mm3, %mm2 /* out12 ; free mm3 */ movq %mm5, 8*2(%esi) /* out2 ; free mm5 */ psraw $4, %mm2 /* moved up to the prev block */ movq (%esp), %mm4 /* moved up to the prev block */ psraw $4, %mm0 movq %mm2, 8*12(%esi) /* out12 ; free mm2 */ /* moved up to the prev block */ psraw $4, %mm6 /* move back the data to its correct place * moved up to the prev block * movq 16(%esp), %mm0 * movq 8(%esp), %mm6 * movq (%esp), %mm4 * psraw $4, %mm0 * psraw $4, %mm6 */ movq 24(%esp), %mm1 psraw $4, %mm4 movq %mm0, 8*3(%esi) /* out3 */ psraw $4, %mm1 movq %mm6, 8*5(%esi) /* out5 */ movq %mm4, 8*7(%esi) /* out7 */ movq %mm1, 8(%esi) /* out1 */ popl %edi /* Pop off the temp variables */ popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi popl %edi /* Pop off the old variables */ popl %esi popl %edx popl %ecx popl %ebx movl %ebp, %esp popl %ebp ret .Lfe1: .size IDCT_mmx,.Lfe1-IDCT_mmx ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mmxtest.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.inc" #include #include int mpeg3_mmx_test() { int result = 0; FILE *proc; char string[MPEG3_STRLEN]; #ifdef HAVE_MMX if(!(proc = fopen(MPEG3_PROC_CPUINFO, "r"))) { return 0; } while(!feof(proc)) { fgets(string, MPEG3_STRLEN, proc); /* Got the flags line */ if(!strncmp(string, "flags", 5)) { char *needle; needle = strstr(string, "mmx"); if(!needle) return 0; if(!strncmp(needle, "mmx", 3)) return 1; } } #endif return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/motion.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3video.h" #include "vlc.h" #include /* calculate motion vector component */ static inline void mpeg3video_calc_mv(int *pred, int r_size, int motion_code, int motion_r, int full_pel_vector) { int lim = 16 << r_size; int vec = full_pel_vector ? (*pred >> 1) : (*pred); if(motion_code > 0) { vec += ((motion_code - 1) << r_size) + motion_r + 1; if(vec >= lim) vec -= lim + lim; } else if(motion_code < 0) { vec -= ((-motion_code - 1) << r_size) + motion_r + 1; if(vec < -lim) vec += lim + lim; } *pred = full_pel_vector ? (vec << 1) : vec; } /* int *dmvector, * differential motion vector * int mvx, int mvy * decoded mv components (always in field format) * */ #if !defined(sun) INLINE #endif void mpeg3video_calc_dmv(mpeg3video_t *video, int DMV[][2], int *dmvector, int mvx, int mvy) { if(video->pict_struct == FRAME_PICTURE) { if(video->topfirst) { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; DMV[0][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((3 * mvx + (mvx > 0)) >> 1) + dmvector[0]; DMV[1][1] = ((3 * mvy + (mvy > 0)) >> 1) + dmvector[1] + 1; } else { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((3 * mvx + (mvx>0)) >> 1) + dmvector[0]; DMV[0][1] = ((3 * mvy + (mvy>0)) >> 1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; DMV[1][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] + 1; } } else { /* vector for prediction from field of opposite 'parity' */ DMV[0][0] = ((mvx + (mvx > 0)) >> 1) + dmvector[0]; DMV[0][1] = ((mvy + (mvy > 0)) >> 1) + dmvector[1]; /* correct for vertical field shift */ if(video->pict_struct == TOP_FIELD) DMV[0][1]--; else DMV[0][1]++; } } static inline int mpeg3video_get_mv(mpeg3_slice_t *slice) { int code; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if(mpeg3slice_getbit(slice_buffer)) { return 0; } if((code = mpeg3slice_showbits9(slice_buffer)) >= 64) { code >>= 6; mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab0[code].len); return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab0[code].val : mpeg3_MVtab0[code].val; } if(code >= 24) { code >>= 3; mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab1[code].len); return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab1[code].val : mpeg3_MVtab1[code].val; } if((code -= 12) < 0) { /* fprintf(stdout,"mpeg3video_get_mv: invalid motion_vector code\n"); */ slice->fault = 1; return 1; } mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab2[code].len); return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab2[code].val : mpeg3_MVtab2[code].val; } /* get differential motion vector (for dual prime prediction) */ static inline int mpeg3video_get_dmv(mpeg3_slice_t *slice) { mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if(mpeg3slice_getbit(slice_buffer)) { return mpeg3slice_getbit(slice_buffer) ? -1 : 1; } else { return 0; } } /* get and decode motion vector and differential motion vector */ void mpeg3video_motion_vector(mpeg3_slice_t *slice, mpeg3video_t *video, int *PMV, int *dmvector, int h_r_size, int v_r_size, int dmv, int mvscale, int full_pel_vector) { int motion_r; int motion_code = mpeg3video_get_mv(slice); mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if(slice->fault) return; motion_r = (h_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, h_r_size) : 0; mpeg3video_calc_mv(&PMV[0], h_r_size, motion_code, motion_r, full_pel_vector); if(dmv) dmvector[0] = mpeg3video_get_dmv(slice); motion_code = mpeg3video_get_mv(slice); if(slice->fault) return; motion_r = (v_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, v_r_size) : 0; /* DIV 2 */ if(mvscale) PMV[1] >>= 1; mpeg3video_calc_mv(&PMV[1], v_r_size, motion_code, motion_r, full_pel_vector); if(mvscale) PMV[1] <<= 1; if(dmv) dmvector[1] = mpeg3video_get_dmv(slice); } int mpeg3video_motion_vectors(mpeg3_slice_t *slice, mpeg3video_t *video, int PMV[2][2][2], int dmvector[2], int mv_field_sel[2][2], int s, int mv_count, int mv_format, int h_r_size, int v_r_size, int dmv, int mvscale) { int result = 0; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; if(mv_count == 1) { if(mv_format == MV_FIELD && !dmv) { mv_field_sel[1][s] = mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); } mpeg3video_motion_vector(slice, video, PMV[0][s], dmvector, h_r_size, v_r_size, dmv, mvscale, 0); if(slice->fault) return 1; /* update other motion vector predictors */ PMV[1][s][0] = PMV[0][s][0]; PMV[1][s][1] = PMV[0][s][1]; } else { mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); mpeg3video_motion_vector(slice, video, PMV[0][s], dmvector, h_r_size, v_r_size, dmv, mvscale, 0); if(slice->fault) return 1; mv_field_sel[1][s] = mpeg3slice_getbit(slice_buffer); mpeg3video_motion_vector(slice, video, PMV[1][s], dmvector, h_r_size, v_r_size, dmv, mvscale, 0); if(slice->fault) return 1; } return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mpeg3video.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3protos.h" #include "mpeg3video.h" #include "mpeg3videoprotos.h" #include unsigned char mpeg3_zig_zag_scan_mmx[64] = { 0*8+0 /* 0*/, 1*8+0 /* 1*/, 0*8+1 /* 8*/, 0*8+2 /*16*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 3*8+0 /* 3*/, 2*8+1 /*10*/, 1*8+2 /*17*/, 0*8+3 /*24*/, 0*8+4 /*32*/, 1*8+3 /*25*/, 2*8+2 /*18*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 5*8+0 /* 5*/, 4*8+1 /*12*/, 5*8+2 /*19*/, 2*8+3 /*26*/, 1*8+4 /*33*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 1*8+5 /*41*/, 2*8+4 /*34*/, 3*8+3 /*27*/, 4*8+2 /*20*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 7*8+0 /* 7*/, 6*8+1 /*14*/, 5*8+2 /*21*/, 4*8+3 /*28*/, 3*8+4 /*35*/, 2*8+5 /*42*/, 1*8+6 /*49*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 2*8+6 /*50*/, 3*8+5 /*43*/, 4*8+4 /*36*/, 5*8+3 /*29*/, 6*8+2 /*22*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 6*8+3 /*30*/, 5*8+4 /*37*/, 4*8+5 /*44*/, 3*8+6 /*51*/, 2*8+7 /*58*/, 3*8+7 /*59*/, 4*8+6 /*52*/, 5*8+5 /*45*/, 6*8+4 /*38*/, 7*8+3 /*31*/, 7*8+4 /*39*/, 6*8+5 /*46*/, 7*8+6 /*53*/, 4*8+7 /*60*/, 5*8+7 /*61*/, 6*8+6 /*54*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 6*8+7 /*62*/, 7*8+7 /*63*/ }; /* alternate scan */ unsigned char mpeg3_alternate_scan_mmx[64] = { 0*8+0 /*0 */, 0*8+1 /* 8*/, 0*8+2 /*16*/, 0*8+3 /*24*/, 1*8+0 /* 1*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 2*8+1 /*10*/, 1*8+2 /*17*/, 1*8+3 /*25*/, 0*8+4 /*32*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 1*8+6 /*49*/, 1*8+5 /*41*/, 1*8+4 /*33*/, 2*8+3 /*26*/, 2*8+2 /*18*/, 3*8+0 /* 3*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 4*8+1 /*12*/, 3*8+2 /*19*/, 3*8+3 /*27*/, 2*8+4 /*34*/, 2*8+5 /*42*/, 2*8+6 /*50*/, 2*8+7 /*58*/, 3*8+4 /*35*/, 3*8+5 /*43*/, 3*8+6 /*51*/, 3*8+7 /*59*/, 4*8+2 /*20*/, 4*8+3 /*28*/, 5*8+0 /* 5*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 6*8+1 /*14*/, 5*8+2 /*21*/, 5*8+3 /*29*/, 4*8+4 /*36*/, 4*8+5 /*44*/, 4*8+6 /*52*/, 4*8+7 /*60*/, 5*8+4 /*37*/, 5*8+5 /*45*/, 5*8+6 /*53*/, 5*8+7 /*61*/, 6*8+2 /*22*/, 6*8+3 /*30*/, 7*8+0 /* 7*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 7*8+3 /*31*/, 6*8+4 /*38*/, 6*8+5 /*46*/, 6*8+6 /*54*/, 6*8+7 /*62*/, 7*8+4 /*39*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 7*8+6 /*63*/ }; /* zig-zag scan */ unsigned char mpeg3_zig_zag_scan_nommx[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; /* alternate scan */ unsigned char mpeg3_alternate_scan_nommx[64] = { 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 }; /* default intra quantization matrix */ unsigned char mpeg3_default_intra_quantizer_matrix[64] = { 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40, 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58, 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83 }; unsigned char mpeg3_non_linear_mquant_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }; double mpeg3_frame_rate_table[16] = { 0.0, /* Pad */ 24000.0/1001.0, /* Official frame rates */ 24.0, 25.0, 30000.0/1001.0, 30.0, 50.0, ((60.0*1000.0)/1001.0), 60.0, 1, /* Unofficial economy rates */ 5, 10, 12, 15, 0, 0, }; int mpeg3video_initdecoder(mpeg3video_t *video) { int blk_cnt_tab[3] = {6, 8, 12}; int cc; int i; long size[4], padding[2]; /* Size of Y, U, and V buffers */ if(!video->mpeg2) { /* force MPEG-1 parameters */ video->prog_seq = 1; video->prog_frame = 1; video->pict_struct = FRAME_PICTURE; video->frame_pred_dct = 1; video->chroma_format = CHROMA420; video->matrix_coefficients = 5; } /* Get dimensions rounded to nearest multiple of coded macroblocks */ video->mb_width = (video->horizontal_size + 15) / 16; video->mb_height = (video->mpeg2 && !video->prog_seq) ? (2 * ((video->vertical_size + 31) / 32)) : ((video->vertical_size + 15) / 16); video->coded_picture_width = 16 * video->mb_width; video->coded_picture_height = 16 * video->mb_height; video->chrom_width = (video->chroma_format == CHROMA444) ? video->coded_picture_width : (video->coded_picture_width >> 1); video->chrom_height = (video->chroma_format != CHROMA420) ? video->coded_picture_height : (video->coded_picture_height >> 1); video->blk_cnt = blk_cnt_tab[video->chroma_format - 1]; /* Get sizes of YUV buffers */ padding[0] = 16 * video->coded_picture_width; size[0] = video->coded_picture_width * video->coded_picture_height + padding[0] * 2; padding[1] = 16 * video->chrom_width; size[1] = video->chrom_width * video->chrom_height + 2 * padding[1]; size[2] = (video->llw * video->llh); size[3] = (video->llw * video->llh) / 4; /* Allocate contiguous fragments for YUV buffers for hardware YUV decoding */ video->yuv_buffer[0] = (unsigned char*)memoryAllocate(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); video->yuv_buffer[1] = (unsigned char*)memoryAllocate(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); video->yuv_buffer[2] = (unsigned char*)memoryAllocate(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); if(video->scalable_mode == SC_SPAT) { video->yuv_buffer[3] = (unsigned char*)memoryAllocate(1, size[2] + 2 * size[3]); video->yuv_buffer[4] = (unsigned char*)memoryAllocate(1, size[2] + 2 * size[3]); } /* Direct pointers to areas of contiguous fragments in YVU order per Microsoft */ for(cc = 0; cc < 3; cc++) { video->llframe0[cc] = 0; video->llframe1[cc] = 0; video->newframe[cc] = 0; } video->refframe[0] = video->yuv_buffer[0]; video->oldrefframe[0] = video->yuv_buffer[1]; video->auxframe[0] = video->yuv_buffer[2]; video->refframe[2] = video->yuv_buffer[0] + size[0] + padding[0]; video->oldrefframe[2] = video->yuv_buffer[1] + size[0] + padding[0]; video->auxframe[2] = video->yuv_buffer[2] + size[0] + padding[0]; video->refframe[1] = video->yuv_buffer[0] + size[0] + padding[0] + size[1] + padding[1]; video->oldrefframe[1] = video->yuv_buffer[1] + size[0] + padding[0] + size[1] + padding[1]; video->auxframe[1] = video->yuv_buffer[2] + size[0] + padding[0] + size[1] + padding[1]; if(video->scalable_mode == SC_SPAT) { /* this assumes lower layer is 4:2:0 */ video->llframe0[0] = video->yuv_buffer[3] + padding[0] ; video->llframe1[0] = video->yuv_buffer[4] + padding[0] ; video->llframe0[2] = video->yuv_buffer[3] + padding[1] + size[2] ; video->llframe1[2] = video->yuv_buffer[4] + padding[1] + size[2] ; video->llframe0[1] = video->yuv_buffer[3] + padding[1] + size[2] + size[3]; video->llframe1[1] = video->yuv_buffer[4] + padding[1] + size[2] + size[3]; } /* Initialize the YUV tables for software YUV decoding */ video->cr_to_r = (long *) memoryAllocate(1,sizeof(long) * 256); video->cr_to_g = (long *) memoryAllocate(1,sizeof(long) * 256); video->cb_to_g = (long *) memoryAllocate(1,sizeof(long) * 256); video->cb_to_b = (long *) memoryAllocate(1,sizeof(long) * 256); video->cr_to_r_ptr = video->cr_to_r + 128; video->cr_to_g_ptr = video->cr_to_g + 128; video->cb_to_g_ptr = video->cb_to_g + 128; video->cb_to_b_ptr = video->cb_to_b + 128; for(i = -128; i < 128; i++) { video->cr_to_r_ptr[i] = (long)( 1.371 * 65536 * i); video->cr_to_g_ptr[i] = (long)(-0.698 * 65536 * i); video->cb_to_g_ptr[i] = (long)(-0.336 * 65536 * i); video->cb_to_b_ptr[i] = (long)( 1.732 * 65536 * i); } return 0; } int mpeg3video_deletedecoder(mpeg3video_t *video) { int i, padding; memoryFree(video->yuv_buffer[0]); memoryFree(video->yuv_buffer[1]); memoryFree(video->yuv_buffer[2]); if(video->llframe0[0]) { memoryFree(video->yuv_buffer[3]); memoryFree(video->yuv_buffer[4]); } memoryFree(video->cr_to_r); memoryFree(video->cr_to_g); memoryFree(video->cb_to_g); memoryFree(video->cb_to_b); return 0; } void mpeg3video_init_scantables(mpeg3video_t *video) { #ifdef HAVE_MMX if(video->have_mmx) { video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_mmx; video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_mmx; } else #endif { video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_nommx; video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_nommx; } } mpeg3video_t* mpeg3video_allocate_struct(mpeg3_t *file, mpeg3_vtrack_t *track) { int i; mpeg3video_t *video = (mpeg3video_t *) memoryAllocate(1, sizeof(mpeg3video_t)); #ifdef USE_PTHREADS pthread_mutexattr_t mutex_attr; #endif video->file = file; video->track = track; video->vstream = mpeg3bits_new_stream(file, track->demuxer); video->last_number = -1; /* First frame is all green */ video->framenum = -1; video->have_mmx = file->have_mmx; video->percentage_seek = -1; video->frame_seek = -1; mpeg3video_init_scantables(video); mpeg3video_init_output(); #ifdef USE_PTHREADS pthread_mutexattr_init(&mutex_attr); pthread_mutex_init(&(video->test_lock), &mutex_attr); pthread_mutex_init(&(video->slice_lock), &mutex_attr); #endif return video; } int mpeg3video_delete_struct(mpeg3video_t *video) { int i; mpeg3bits_delete_stream(video->vstream); #ifdef USE_PTHREADS pthread_mutex_destroy(&(video->test_lock)); pthread_mutex_destroy(&(video->slice_lock)); #endif if(video->x_table) { memoryFree(video->x_table); memoryFree(video->y_table); } if(video->total_slice_decoders) { for(i = 0; i < video->total_slice_decoders; i++) mpeg3_delete_slice_decoder(video->slice_decoders[i]); } for(i = 0; i < video->slice_buffers_initialized; i++) mpeg3_delete_slice_buffer(&(video->slice_buffers[i])); memoryFree(video); } int mpeg3video_read_frame_backend(mpeg3video_t *video, int skip_bframes) { int result = 0; if(mpeg3bits_eof(video->vstream)) result = 1; if(!result) result = mpeg3video_get_header(video, 0); //printf("frame type %d\n", video->pict_type); /* skip_bframes is the number of bframes we can skip successfully. */ /* This is in case a skipped B-frame is repeated and the second repeat happens */ /* to be a B frame we need. */ video->skip_bframes = skip_bframes; if(!result) result = mpeg3video_getpicture(video, video->framenum); #ifdef HAVE_MMX if(video->have_mmx) __asm__ __volatile__ ("emms"); #endif if(!result) { video->last_number = video->framenum; video->framenum++; } return result; } int* mpeg3video_get_scaletable(int input_w, int output_w) { int *result = (int *) memoryAllocate(1,sizeof(int) * output_w); float i; float scale = (float)input_w / output_w; for(i = 0; i < output_w; i++) { result[(int)i] = (int)(scale * i); } return result; } /* Get the first frame read. */ int mpeg3video_get_firstframe(mpeg3video_t *video) { int result = 0; if(video->framenum < 0) { video->repeat_count = video->current_repeat = 0; result = mpeg3video_read_frame_backend(video, 0); mpeg3bits_seek_byte(video->vstream, 0); mpeg3video_match_refframes(video); } return result; } /* ======================================================================= */ /* ENTRY POINTS */ /* ======================================================================= */ mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track) { mpeg3video_t *video; int result = 0; video = mpeg3video_allocate_struct(file, track); result = mpeg3video_get_header(video, 1); if(!result) { int hour, minute, second, frame; int gop_found; mpeg3video_initdecoder(video); video->decoder_initted = 1; track->width = video->horizontal_size; track->height = video->vertical_size; track->frame_rate = video->frame_rate; /* Get the length of the file from an elementary stream */ if(file->is_video_stream) { /* Load the first GOP */ mpeg3bits_seek_start(video->vstream); result = mpeg3video_next_code(video->vstream, MPEG3_GOP_START_CODE); if(!result) mpeg3bits_getbits(video->vstream, 32); if(!result) result = mpeg3video_getgophdr(video); hour = video->gop_timecode.hour; minute = video->gop_timecode.minute; second = video->gop_timecode.second; frame = video->gop_timecode.frame; video->first_frame = (long)(hour * 3600 * video->frame_rate + minute * 60 * video->frame_rate + second * video->frame_rate + frame); /* GOPs always have 16 frames */ video->frames_per_gop = 16; /* Read the last GOP in the file by seeking backward. */ mpeg3bits_seek_end(video->vstream); mpeg3bits_start_reverse(video->vstream); result = mpeg3video_prev_code(video->vstream, MPEG3_GOP_START_CODE); mpeg3bits_start_forward(video->vstream); mpeg3bits_getbits(video->vstream, 8); if(!result) result = mpeg3video_getgophdr(video); hour = video->gop_timecode.hour; minute = video->gop_timecode.minute; second = video->gop_timecode.second; frame = video->gop_timecode.frame; video->last_frame = (long)(hour * 3600 * video->frame_rate + minute * 60 * video->frame_rate + second * video->frame_rate + frame); /* Count number of frames to end */ while(!result) { result = mpeg3video_next_code(video->vstream, MPEG3_PICTURE_START_CODE); if(!result) { mpeg3bits_getbyte_noptr(video->vstream); video->last_frame++; } } track->total_frames = video->last_frame - video->first_frame + 1; mpeg3bits_seek_start(video->vstream); } else { /* Gross approximation from a multiplexed file. */ video->first_frame = 0; track->total_frames = video->last_frame = (long)(mpeg3demux_length(video->vstream->demuxer) * video->frame_rate); video->first_frame = 0; } video->maxframe = track->total_frames; mpeg3bits_seek_start(video->vstream); } else { mpeg3video_delete(video); video = 0; } return video; } int mpeg3video_delete(mpeg3video_t *video) { if(video->decoder_initted) { mpeg3video_deletedecoder(video); } mpeg3video_delete_struct(video); return 0; } int mpeg3video_set_cpus(mpeg3video_t *video, int cpus) { return 0; } int mpeg3video_set_mmx(mpeg3video_t *video, int use_mmx) { video->have_mmx = use_mmx; mpeg3video_init_scantables(video); return 0; } int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage) { video->percentage_seek = percentage; return 0; } int mpeg3video_previous_frame(mpeg3video_t *video) { if(mpeg3bits_tell_percentage(video->vstream) <= 0) return 1; mpeg3bits_start_reverse(video->vstream); mpeg3video_prev_code(video->vstream, MPEG3_PICTURE_START_CODE); mpeg3bits_getbits_reverse(video->vstream, 32); if(mpeg3bits_bof(video->vstream)) mpeg3bits_seek_percentage(video->vstream, 0); mpeg3bits_start_forward(video->vstream); video->repeat_count = 0; return 0; } int mpeg3video_seek_frame(mpeg3video_t *video, long frame) { video->frame_seek = frame; return 0; } /* Read all the way up to and including the next picture start code */ int mpeg3video_read_raw(mpeg3video_t *video, unsigned char *output, long *size, long max_size) { unsigned MPEG3_INT32 code = 0; mpeg3_bits_t *vstream = video->vstream; *size = 0; while(code != MPEG3_PICTURE_START_CODE && code != MPEG3_SEQUENCE_END_CODE && *size < max_size && !mpeg3bits_eof(vstream)) { code <<= 8; *output = mpeg3bits_getbyte_noptr(vstream); code |= *output++; (*size)++; } return mpeg3bits_eof(vstream); } int mpeg3video_read_frame(mpeg3video_t *video, long frame_number, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model) { int result = 0; video->want_yvu = 0; video->output_rows = output_rows; video->color_model = color_model; /* Get scaling tables */ if(video->out_w != out_w || video->out_h != out_h || video->in_w != in_w || video->in_h != in_h || video->in_x != in_x || video->in_y != in_y) { if(video->x_table) { memoryFree(video->x_table); memoryFree(video->y_table); video->x_table = 0; video->y_table = 0; } } video->out_w = out_w; video->out_h = out_h; video->in_w = in_w; video->in_h = in_h; video->in_x = in_x; video->in_y = in_y; if(!video->x_table) { video->x_table = mpeg3video_get_scaletable(video->in_w, video->out_w); video->y_table = mpeg3video_get_scaletable(video->in_h, video->out_h); } mpeg3video_get_firstframe(video); if(!result) result = mpeg3video_seek(video); if(!result) result = mpeg3video_read_frame_backend(video, 0); if(video->output_src) mpeg3video_present_frame(video); video->percentage_seek = -1; return result; } int mpeg3video_read_yuvframe(mpeg3video_t *video, long frame_number, char *y_output, char *u_output, char *v_output, int in_x, int in_y, int in_w, int in_h) { int result = 0; video->want_yvu = 1; video->y_output = y_output; video->u_output = u_output; video->v_output = v_output; video->in_x = in_x; video->in_y = in_y; video->in_w = in_w; video->in_h = in_h; mpeg3video_get_firstframe(video); if(!result) result = mpeg3video_seek(video); if(!result) result = mpeg3video_read_frame_backend(video, 0); if(video->output_src) mpeg3video_present_frame(video); video->want_yvu = 0; video->percentage_seek = -1; return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mpeg3video.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef MPEGVIDEO_H #define MPEGVIDEO_H #include "bitstream.h" #include "mpeg3private.inc" #include "timecode.h" #include "idct.h" #include "slice.h" /* zig-zag scan */ extern unsigned char mpeg3_zig_zag_scan_nommx[64]; extern unsigned char mpeg3_zig_zag_scan_mmx[64]; /* alternate scan */ extern unsigned char mpeg3_alternate_scan_nommx[64]; extern unsigned char mpeg3_alternate_scan_mmx[64]; /* default intra quantization matrix */ extern unsigned char mpeg3_default_intra_quantizer_matrix[64]; /* Frame rate table must agree with the one in the encoder */ extern double mpeg3_frame_rate_table[16]; /* non-linear quantization coefficient table */ extern unsigned char mpeg3_non_linear_mquant_table[32]; #define CHROMA420 1 /* chroma_format */ #define CHROMA422 2 #define CHROMA444 3 #define TOP_FIELD 1 /* picture structure */ #define BOTTOM_FIELD 2 #define FRAME_PICTURE 3 #define SEQ_ID 1 /* extension start code IDs */ #define DISP_ID 2 #define QUANT_ID 3 #define SEQSCAL_ID 5 #define PANSCAN_ID 7 #define CODING_ID 8 #define SPATSCAL_ID 9 #define TEMPSCAL_ID 10 #define MPERROR (-1) #define SC_NONE 0 /* scalable_mode */ #define SC_DP 1 #define SC_SPAT 2 #define SC_SNR 3 #define SC_TEMP 4 #define I_TYPE 1 /* picture coding type */ #define P_TYPE 2 #define B_TYPE 3 #define D_TYPE 4 #define MB_INTRA 1 /* macroblock type */ #define MB_PATTERN 2 #define MB_BACKWARD 4 #define MB_FORWARD 8 #define MB_QUANT 16 #define MB_WEIGHT 32 #define MB_CLASS4 64 #define MC_FIELD 1 /* motion_type */ #define MC_FRAME 2 #define MC_16X8 2 #define MC_DMV 3 #define MV_FIELD 0 /* mv_format */ #define MV_FRAME 1 #define CLIP(x) ((x) >= 0 ? ((x) < 255 ? (x) : 255) : 0) /* Statically allocate as little as possible so a fake video struct */ /* can be used for reading the GOP headers. */ typedef struct { void* file; void* track; /* ================================= Seeking variables ========================= */ mpeg3_bits_t *vstream; int decoder_initted; unsigned char **output_rows; /* Output frame buffer supplied by user */ int in_x, in_y, in_w, in_h, out_w, out_h; /* Output dimensions */ int *x_table, *y_table; /* Location of every output pixel in the input */ int color_model; int want_yvu; /* Want to return a YUV frame */ char *y_output, *u_output, *v_output; /* Output pointers for a YUV frame */ mpeg3_slice_t slice_decoders[MPEG3_MAX_CPUS]; /* One slice decoder for every CPU */ int total_slice_decoders; /* Total slice decoders in use */ mpeg3_slice_buffer_t slice_buffers[MPEG3_MAX_CPUS]; /* Buffers for holding the slice data */ int total_slice_buffers; /* Total buffers in the array to be decompressed */ int slice_buffers_initialized; /* Total buffers initialized in the array */ #ifdef USE_PTHREADS pthread_mutex_t slice_lock; /* Lock slice array while getting the next buffer */ pthread_mutex_t test_lock; #endif int blockreadsize; long maxframe; /* Max value of frame num to read */ double percentage_seek; /* Perform a percentage seek before the next frame is read */ int frame_seek; /* Perform a frame seek before the next frame is read */ long framenum; /* Number of the next frame to be decoded */ long last_number; /* Last framenum rendered */ int found_seqhdr; long bitrate; mpeg3_timecode_t gop_timecode; /* Timecode for the last GOP header read. */ /* These are only available from elementary streams. */ long frames_per_gop; /* Frames per GOP after the first GOP. */ long first_gop_frames; /* Frames in the first GOP. */ long first_frame; /* Number of first frame stored in timecode */ long last_frame; /* Last frame in file */ /* ================================= Compression variables ===================== */ /* Malloced frame buffers. 2 refframes are swapped in and out. */ /* while only 1 auxframe is used. */ unsigned char *yuv_buffer[5]; /* Make YVU buffers contiguous for all frames */ unsigned char *oldrefframe[3], *refframe[3], *auxframe[3]; unsigned char *llframe0[3], *llframe1[3]; unsigned char *mpeg3_zigzag_scan_table; unsigned char *mpeg3_alternate_scan_table; // Source for the next frame presentation unsigned char **output_src; /* Pointers to frame buffers. */ unsigned char *newframe[3]; int horizontal_size, vertical_size, mb_width, mb_height; int coded_picture_width, coded_picture_height; int chroma_format, chrom_width, chrom_height, blk_cnt; int pict_type; int forw_r_size, back_r_size, full_forw, full_back; int prog_seq, prog_frame; int h_forw_r_size, v_forw_r_size, h_back_r_size, v_back_r_size; int dc_prec, pict_struct, topfirst, frame_pred_dct, conceal_mv; int intravlc; int repeatfirst; int repeat_count; /* Number of times to repeat the current frame * 100 since floating point is impossible in MMX */ int current_repeat; /* Number of times the current frame has been repeated * 100 */ int secondfield; int skip_bframes; int stwc_table_index, llw, llh, hm, hn, vm, vn; int lltempref, llx0, lly0, llprog_frame, llfieldsel; int matrix_coefficients; int framerate_code; float frame_rate; long *cr_to_r, *cr_to_g, *cb_to_g, *cb_to_b; long *cr_to_r_ptr, *cr_to_g_ptr, *cb_to_g_ptr, *cb_to_b_ptr; int have_mmx; int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; int mpeg2; int qscale_type, altscan; /* picture coding extension */ int pict_scal; /* picture spatial scalable extension */ int scalable_mode; /* sequence scalable extension */ } mpeg3video_t; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/mpeg3videoprotos.h ================================================ #ifndef MPEG3VIDEOPROTOS_H #define MPEG3VIDEOPROTOS_H void mpeg3video_idct_conversion(short* block); unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits); #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/output.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak Feb/march 2001, JMM tuning for the mac I've coded up mpeg3video_ditherframeFastRGB555 and mpeg3video_ditherframeFastRGBA which do specialized 16 and 32 bit Crb to rgb mapping (Intel should do this too?) I also coded up clip arrays versus using CLIP() This avoid test/branchs which slows things down May 19th, 2003, Ivo Roessling changes to asm syntax to enable compile in GCC 3.3.x March 17th, 2006, John M McIntosh, set alpha to 0xff versus 0x00. */ #include "libmpeg3.h" #include "mpeg3video.h" #include unsigned char gClipArray[1026]; unsigned short gClipArray16r[1026],gClipArray16g[1026],gClipArray16b[1026]; unsigned char *gClipArray_ptr=&gClipArray[512]; unsigned short *gClipArray_ptr16r=&gClipArray16r[512]; unsigned short *gClipArray_ptr16g=&gClipArray16g[512]; unsigned short *gClipArray_ptr16b=&gClipArray16b[512]; int doClippingArrays=1; static unsigned char mpeg3_601_to_rgb[256]; #ifdef HAVE_MMX #warning Beware of alpha this is not in the mmx code, and it appears tweak really wants it now static long long mpeg3_MMX_0 = 0L; static unsigned long mpeg3_MMX_10w[] = {0x00100010, 0x00100010}; /*dd 00010 0010h, 000100010h */ static unsigned long mpeg3_MMX_80w[] = {0x00800080, 0x00800080}; /*dd 00080 0080h, 000800080h */ static unsigned long mpeg3_MMX_00FFw[] = {0x00ff00ff, 0x00ff00ff}; /*dd 000FF 00FFh, 000FF00FFh */ static unsigned short mpeg3_MMX_Ublucoeff[] = {0x81, 0x81, 0x81, 0x81}; /*dd 00081 0081h, 000810081h */ static unsigned short mpeg3_MMX_Vredcoeff[] = {0x66, 0x66, 0x66, 0x66}; /*dd 00066 0066h, 000660066h */ static unsigned short mpeg3_MMX_Ugrncoeff[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8}; /*dd 0FFE7 FFE7h, 0FFE7FFE7h */ static unsigned short mpeg3_MMX_Vgrncoeff[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd}; /*dd 0FFCC FFCCh, 0FFCCFFCCh */ static unsigned short mpeg3_MMX_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a}; /*dd 0004A 004Ah, 0004A004Ah */ static unsigned short mpeg3_MMX_redmask[] = {0xf800, 0xf800, 0xf800, 0xf800}; /*dd 07c00 7c00h, 07c007c00h */ static unsigned short mpeg3_MMX_grnmask[] = {0x7e0, 0x7e0, 0x7e0, 0x7e0}; /*dd 003e0 03e0h, 003e003e0h */ /* Algorithm */ /* r = (int)(*y + 1.371 * (*cr - 128)); */ /* g = (int)(*y - 0.698 * (*cr - 128) - 0.336 * (*cb - 128)); */ /* b = (int)(*y + 1.732 * (*cb - 128)); */ inline void mpeg3video_rgb16_mmx(unsigned char *lum, unsigned char *cr, unsigned char *cb, unsigned char *out, int rows, int cols, int mod) { unsigned short *row1; int x; unsigned char *y; int col1; row1 = (unsigned short *)out; col1 = cols + mod; mod += cols + mod; mod *= 2; y = lum + cols * rows; x = 0; __asm__ __volatile__( //"align 8\n" "1:\n" "movd (%1), %%mm0\n" /* 4 Cb 0 0 0 0 u3 u2 u1 u0 */ "pxor %%mm7, %%mm7\n" "movd (%0), %%mm1\n" /* 4 Cr 0 0 0 0 v3 v2 v1 v0 */ "punpcklbw %%mm7, %%mm0\n" /* 4 W cb 0 u3 0 u2 0 u1 0 u0 */ "punpcklbw %%mm7, %%mm1\n" /* 4 W cr 0 v3 0 v2 0 v1 0 v0 */ "psubw _mpeg3_MMX_80w, %%mm0\n" "psubw _mpeg3_MMX_80w, %%mm1\n" "movq %%mm0, %%mm2\n" /* Cb 0 u3 0 u2 0 u1 0 u0 */ "movq %%mm1, %%mm3\n" /* Cr */ "pmullw _mpeg3_MMX_Ugrncoeff, %%mm2\n" /* Cb2green 0 R3 0 R2 0 R1 0 R0 */ "movq (%2), %%mm6\n" /* L1 l7 L6 L5 L4 L3 L2 L1 L0 */ "pmullw _mpeg3_MMX_Ublucoeff, %%mm0\n" /* Cb2blue */ "pand _mpeg3_MMX_00FFw, %%mm6\n" /* L1 00 L6 00 L4 00 L2 00 L0 */ "pmullw _mpeg3_MMX_Vgrncoeff, %%mm3\n" /* Cr2green */ "movq (%2), %%mm7\n" /* L2 */ "pmullw _mpeg3_MMX_Vredcoeff, %%mm1\n" /* Cr2red */ "psrlw $8, %%mm7\n" /* L2 00 L7 00 L5 00 L3 00 L1 */ "pmullw _mpeg3_MMX_Ycoeff, %%mm6\n" /* lum1 */ "paddw %%mm3, %%mm2\n" /* Cb2green + Cr2green == green */ "pmullw _mpeg3_MMX_Ycoeff, %%mm7\n" /* lum2 */ "movq %%mm6, %%mm4\n" /* lum1 */ "paddw %%mm0, %%mm6\n" /* lum1 +blue 00 B6 00 B4 00 B2 00 B0 */ "movq %%mm4, %%mm5\n" /* lum1 */ "paddw %%mm1, %%mm4\n" /* lum1 +red 00 R6 00 R4 00 R2 00 R0 */ "paddw %%mm2, %%mm5\n" /* lum1 +green 00 G6 00 G4 00 G2 00 G0 */ "psraw $6, %%mm4\n" /* R1 0 .. 64 */ "movq %%mm7, %%mm3\n" /* lum2 00 L7 00 L5 00 L3 00 L1 */ "psraw $6, %%mm5\n" /* G1 - .. + */ "paddw %%mm0, %%mm7\n" /* Lum2 +blue 00 B7 00 B5 00 B3 00 B1 */ "psraw $6, %%mm6\n" /* B1 0 .. 64 */ "packuswb %%mm4, %%mm4\n" /* R1 R1 */ "packuswb %%mm5, %%mm5\n" /* G1 G1 */ "packuswb %%mm6, %%mm6\n" /* B1 B1 */ "punpcklbw %%mm4, %%mm4\n" "punpcklbw %%mm5, %%mm5\n" "pand _mpeg3_MMX_redmask, %%mm4\n" "psllw $3, %%mm5\n" /* GREEN 1 */ "punpcklbw %%mm6, %%mm6\n" "pand _mpeg3_MMX_grnmask, %%mm5\n" "pand _mpeg3_MMX_redmask, %%mm6\n" "por %%mm5, %%mm4\n" /* */ "psrlw $11, %%mm6\n" /* BLUE 1 */ "movq %%mm3, %%mm5\n" /* lum2 */ "paddw %%mm1, %%mm3\n" /* lum2 +red 00 R7 00 R5 00 R3 00 R1 */ "paddw %%mm2, %%mm5\n" /* lum2 +green 00 G7 00 G5 00 G3 00 G1 */ "psraw $6, %%mm3\n" /* R2 */ "por %%mm6, %%mm4\n" /* MM4 */ "psraw $6, %%mm5\n" /* G2 */ "movq (%2, %3), %%mm6\n" /* L3 */ "psraw $6, %%mm7\n" "packuswb %%mm3, %%mm3\n" "packuswb %%mm5, %%mm5\n" "packuswb %%mm7, %%mm7\n" "pand _mpeg3_MMX_00FFw, %%mm6\n" /* L3 */ "punpcklbw %%mm3, %%mm3\n" "punpcklbw %%mm5, %%mm5\n" "pmullw _mpeg3_MMX_Ycoeff, %%mm6\n" /* lum3 */ "punpcklbw %%mm7, %%mm7\n" "psllw $3, %%mm5\n" /* GREEN 2 */ "pand _mpeg3_MMX_redmask, %%mm7\n" "pand _mpeg3_MMX_redmask, %%mm3\n" "psrlw $11, %%mm7\n" /* BLUE 2 */ "pand _mpeg3_MMX_grnmask, %%mm5\n" "por %%mm7, %%mm3\n" "movq (%2,%3), %%mm7\n" /* L4 */ "por %%mm5, %%mm3\n" /* */ "psrlw $8, %%mm7\n" /* L4 */ "movq %%mm4, %%mm5\n" "punpcklwd %%mm3, %%mm4\n" "pmullw _mpeg3_MMX_Ycoeff, %%mm7\n" /* lum4 */ "punpckhwd %%mm3, %%mm5\n" "movq %%mm4, (%4)\n" "movq %%mm5, 8(%4)\n" "movq %%mm6, %%mm4\n" /* Lum3 */ "paddw %%mm0, %%mm6\n" /* Lum3 +blue */ "movq %%mm4, %%mm5\n" /* Lum3 */ "paddw %%mm1, %%mm4\n" /* Lum3 +red */ "paddw %%mm2, %%mm5\n" /* Lum3 +green */ "psraw $6, %%mm4\n" "movq %%mm7, %%mm3\n" /* Lum4 */ "psraw $6, %%mm5\n" "paddw %%mm0, %%mm7\n" /* Lum4 +blue */ "psraw $6, %%mm6\n" /* Lum3 +blue */ "movq %%mm3, %%mm0\n" /* Lum4 */ "packuswb %%mm4, %%mm4\n" "paddw %%mm1, %%mm3\n" /* Lum4 +red */ "packuswb %%mm5, %%mm5\n" "paddw %%mm2, %%mm0\n" /* Lum4 +green */ "packuswb %%mm6, %%mm6\n" "punpcklbw %%mm4, %%mm4\n" "punpcklbw %%mm5, %%mm5\n" "punpcklbw %%mm6, %%mm6\n" "psllw $3, %%mm5\n" /* GREEN 3 */ "pand _mpeg3_MMX_redmask, %%mm4\n" "psraw $6, %%mm3\n" /* psr 6 */ "psraw $6, %%mm0\n" "pand _mpeg3_MMX_redmask, %%mm6\n" /* BLUE */ "pand _mpeg3_MMX_grnmask, %%mm5\n" "psrlw $11, %%mm6\n" /* BLUE 3 */ "por %%mm5, %%mm4\n" "psraw $6, %%mm7\n" "por %%mm6, %%mm4\n" "packuswb %%mm3, %%mm3\n" "packuswb %%mm0, %%mm0\n" "packuswb %%mm7, %%mm7\n" "punpcklbw %%mm3, %%mm3\n" "punpcklbw %%mm0, %%mm0\n" "punpcklbw %%mm7, %%mm7\n" "pand _mpeg3_MMX_redmask, %%mm3\n" "pand _mpeg3_MMX_redmask, %%mm7\n" /* BLUE */ "psllw $3, %%mm0\n" /* GREEN 4 */ "psrlw $11, %%mm7\n" "pand _mpeg3_MMX_grnmask, %%mm0\n" "por %%mm7, %%mm3\n" "addl $8, %6\n" "por %%mm0, %%mm3\n" "movq %%mm4, %%mm5\n" "punpcklwd %%mm3, %%mm4\n" "punpckhwd %%mm3, %%mm5\n" "movq %%mm4, (%4,%5,2)\n" "movq %%mm5, 8(%4,%5,2)\n" "addl $8, %2\n" "addl $4, %0\n" "addl $4, %1\n" "cmpl %3, %6\n" "leal 16(%4), %4\n" "jl 1b\n" "addl %3, %2\n" /* lum += cols */ "addl %7, %4\n" /* row1 += mod */ "movl $0, %6\n" "cmpl %8, %2\n" "jl 1b\n" : : "r" (cr), "r" (cb), "r" (lum), "r" (cols), "r" (row1) , "r" (col1), "m" (x), "m" (mod), "m" (y) ); } static unsigned long long mpeg3_MMX_U_80 = 0x0000008000800000LL; static unsigned long long mpeg3_MMX_V_80 = 0x0000000000800080LL; static long long mpeg3_MMX_U_COEF = 0x00000058ffd30000LL; static long long mpeg3_MMX_V_COEF = 0x00000000ffea006fLL; static long long mpeg3_MMX_601_Y_COEF = 0x0000004800480048LL; static long long mpeg3_MMX_601_Y_DIFF = 0x0000000000000010LL; inline void mpeg3_bgra32_mmx(unsigned long y, unsigned long u, unsigned long v, unsigned long *output) { asm( "\n" "/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */\n" "/* for bgr24. */\n" " movd (%0), %%mm0; /* Load y 0x00000000000000yy */\n" " movd (%1), %%mm1; /* Load u 0x00000000000000cr */\n" " movq %%mm0, %%mm3; /* Copy y to temp */\n" " psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */\n" " movd (%2), %%mm2; /* Load v 0x00000000000000cb */\n" " psllq $16, %%mm3; /* Shift y */\n" " movq %%mm1, %%mm4; /* Copy u to temp */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */\n" " psllq $16, %%mm4; /* Shift u */\n" " movq %%mm2, %%mm5; /* Copy v to temp */\n" " psllq $16, %%mm3; /* Shift y */\n" " por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */\n" " psllq $16, %%mm5; /* Shift v */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */\n" " por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */\n" " psubw _mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */\n" " pmullw _mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */\n" " psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */\n" " psubw _mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */\n" " pmullw _mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */\n" " paddsw %%mm1, %%mm0; /* Add u to result */\n" " paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */\n" " psraw $6, %%mm0; /* Demote precision */\n" " packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */\n" " movd %%mm0, (%3); /* Store output */\n" " \n" : : "r" (&y), "r" (&u), "r" (&v), "r" (output)); } inline void mpeg3_601_bgra32_mmx(unsigned long y, unsigned long u, unsigned long v, unsigned long *output) { asm("\n" "/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */\n" "/* for bgr24. */\n" " movd (%0), %%mm0; /* Load y 0x00000000000000yy */\n" " psubsw _mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */\n" " movd (%1), %%mm1; /* Load u 0x00000000000000cr */\n" " movq %%mm0, %%mm3; /* Copy y to temp */\n" " psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */\n" " movd (%2), %%mm2; /* Load v 0x00000000000000cb */\n" " psllq $16, %%mm3; /* Shift y */\n" " movq %%mm1, %%mm4; /* Copy u to temp */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */\n" " psllq $16, %%mm4; /* Shift u */\n" " movq %%mm2, %%mm5; /* Copy v to temp */\n" " psllq $16, %%mm3; /* Shift y */\n" " por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */\n" " psllq $16, %%mm5; /* Shift v */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */\n" " por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */\n" " pmullw _mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale and shift y coeffs */\n" " psubw _mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */\n" " pmullw _mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */\n" " psubw _mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */\n" " pmullw _mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */\n" " paddsw %%mm1, %%mm0; /* Add u to result */\n" " paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */\n" " psraw $6, %%mm0; /* Demote precision */\n" " packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */\n" " movd %%mm0, (%3); /* Store output */\n" " \n" : : "r" (&y), "r" (&u), "r" (&v), "r" (output)); } static unsigned long long mpeg3_MMX_U_80_RGB = 0x0000000000800080LL; static unsigned long long mpeg3_MMX_V_80_RGB = 0x0000008000800000LL; static long long mpeg3_MMX_U_COEF_RGB = 0x00000000ffd30058LL; static long long mpeg3_MMX_V_COEF_RGB = 0x0000006fffea0000LL; inline void mpeg3_rgba32_mmx(unsigned long y, unsigned long u, unsigned long v, unsigned long *output) { asm("\n" "/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */\n" "/* for rgb24. */\n" " movd (%0), %%mm0; /* Load y 0x00000000000000yy */\n" " movd (%1), %%mm1; /* Load v 0x00000000000000vv */\n" " movq %%mm0, %%mm3; /* Copy y to temp */\n" " psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */\n" " movd (%2), %%mm2; /* Load u 0x00000000000000uu */\n" " psllq $16, %%mm3; /* Shift y */\n" " movq %%mm1, %%mm4; /* Copy v to temp */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */\n" " psllq $16, %%mm4; /* Shift v */\n" " movq %%mm2, %%mm5; /* Copy u to temp */\n" " psllq $16, %%mm3; /* Shift y */\n" " por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */\n" " psllq $16, %%mm5; /* Shift u */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */\n" " por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */\n" " psubw _mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */\n" " pmullw _mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */\n" " psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */\n" " psubw _mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */\n" " pmullw _mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */\n" " paddsw %%mm1, %%mm0; /* Add v to result */\n" " paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */\n" " psraw $6, %%mm0; /* Demote precision */\n" " packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */\n" " movd %%mm0, (%3); /* Store output */\n" " \n" : : "r" (&y), "r" (&v), "r" (&u), "r" (output)); } inline void mpeg3_601_rgba32_mmx(unsigned long y, unsigned long u, unsigned long v, unsigned long *output) { asm("\n" "/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */\n" "/* for rgb24. */\n" " movd (%0), %%mm0; /* Load y 0x00000000000000yy */\n" " psubsw _mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */\n" " movd (%1), %%mm1; /* Load v 0x00000000000000vv */\n" " movq %%mm0, %%mm3; /* Copy y to temp */\n" " psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */\n" " movd (%2), %%mm2; /* Load u 0x00000000000000uu */\n" " psllq $16, %%mm3; /* Shift y */\n" " movq %%mm1, %%mm4; /* Copy v to temp */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */\n" " psllq $16, %%mm4; /* Shift v */\n" " movq %%mm2, %%mm5; /* Copy u to temp */\n" " psllq $16, %%mm3; /* Shift y */\n" " por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */\n" " psllq $16, %%mm5; /* Shift u */\n" " por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */\n" " por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */\n" " pmullw _mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale y coeffs */\n" " psubw _mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */\n" " pmullw _mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */\n" " psubw _mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */\n" " pmullw _mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */\n" "\n" "/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */\n" " paddsw %%mm1, %%mm0; /* Add v to result */\n" " paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */\n" " psraw $6, %%mm0; /* Demote precision */\n" " packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */\n" " movd %%mm0, (%3); /* Store output */\n" " \n" : : "r" (&y), "r" (&v), "r" (&u), "r" (output)); } #endif #define DITHER_ROW_HEAD \ for(h = 0; h < video->out_h; h++) \ { \ y_in = &src[0][(video->y_table[h] + video->in_y) * video->coded_picture_width] + video->in_x; \ cb_in = &src[1][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 2); \ cr_in = &src[2][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 1); \ data = output_rows[h]; #define DITHER_ROW_TAIL \ } #define DITHER_SCALE_HEAD \ for(w = 0; w < video->out_w; w++) \ { \ uv_subscript = video->x_table[w] / 2; \ y_l = y_in[video->x_table[w]]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; #define DITHER_SCALE_601_HEAD \ for(w = 0; w < video->out_w; w++) \ { \ uv_subscript = video->x_table[w] / 2; \ y_l = mpeg3_601_to_rgb[y_in[video->x_table[w]]]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; #define DITHER_SCALE_TAIL \ } #define DITHER_MMX_SCALE_HEAD \ for(w = 0; w < video->out_w; w++) \ { \ uv_subscript = video->x_table[w] / 2; #define DITHER_MMX_SCALE_TAIL \ data += step; \ } #define DITHER_MMX_HEAD \ for(w = 0; w < video->out_w; w += 2) \ { #define DITHER_MMX_TAIL \ data += step; \ cr_in++; \ cb_in++; \ } #define DITHER_HEAD \ for(w = 0; w < video->horizontal_size; w++) \ { \ y_l = *y_in++; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; #define DITHER_601_HEAD \ for(w = 0; w < video->horizontal_size; w++) \ { \ y_l = mpeg3_601_to_rgb[*y_in++]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; #define DITHER_TAIL \ if(w & 1) \ { \ cr_in++; \ cb_in++; \ } \ } #define STORE_PIXEL_BGR888 \ *data++ = clipArray_ptr[b_l]; \ *data++ = clipArray_ptr[g_l]; \ *data++ = clipArray_ptr[r_l]; #define STORE_PIXEL_BGRA8888 \ *data++ = clipArray_ptr[b_l]; \ *data++ = clipArray_ptr[g_l]; \ *data++ = clipArray_ptr[r_l]; \ *data++ = 0xFF; #define STORE_PIXEL_RGB565 \ foo = ((clipArray_ptr[r_l] & 0xf8) << 8) | \ ((clipArray_ptr[g_l] & 0xfc) << 3) | \ ((clipArray_ptr[b_l] & 0xf8) >> 3); *(unsigned short*)data = foo; data += 2; #define STORE_PIXEL_RGB555 \ foo = ((clipArray_ptr[r_l] & 0xf8) << 7) | \ ((clipArray_ptr[g_l] & 0xf8) << 2) | \ ((clipArray_ptr[b_l] & 0xf8) >> 3); *(unsigned short*)data = foo; data += 2; #define STORE_PIXEL_RGBI555 \ foo = ((clipArray_ptr[r_l] & 0xf8) << 7) | \ ((clipArray_ptr[g_l] & 0xf8) << 2) | \ ((clipArray_ptr[b_l] & 0xf8) >> 3); \ if((unsigned long)data & 0x00000002L) { \ data -= 2; \ *(unsigned short*)data = foo; \ data += 4; \ } else { \ data += 2; \ *(unsigned short*)data = foo; \ } #define STORE_PIXEL_RGB888 \ *data++ = clipArray_ptr[r_l]; \ *data++ = clipArray_ptr[g_l]; \ *data++ = clipArray_ptr[b_l]; #define STORE_PIXEL_RGBA8888 \ *data++ = clipArray_ptr[r_l]; \ *data++ = clipArray_ptr[g_l]; \ *data++ = clipArray_ptr[b_l]; \ *data++ = 0xFF; #define STORE_PIXEL_ARGB8888 \ *data++ = 0xFF; \ *data++ = clipArray_ptr[r_l]; \ *data++ = clipArray_ptr[g_l]; \ *data++ = clipArray_ptr[b_l]; #define STORE_PIXEL_RGBA16161616 \ *data_s++ = clipArray_ptr[r_l]; \ *data_s++ = clipArray_ptr[g_l]; \ *data_s++ = clipArray_ptr[b_l]; \ *data_s++ = 0xFFFF; /* Only good for YUV 4:2:0 */ int mpeg3video_ditherframe(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) { int h = 0; register unsigned char *y_in, *cb_in, *cr_in; long y_l, r_l, b_l, g_l; register unsigned char *data,*clipArray_ptr=gClipArray_ptr; register int uv_subscript, step, w = -1; register short foo; #ifdef HAVE_MMX /* =================================== MMX ===================================== */ if(video->have_mmx && video->out_w == video->horizontal_size && video->out_h == video->vertical_size && video->in_w == video->out_w && video->in_h == video->out_h && video->in_x == 0 && video->in_y == 0 && (video->color_model == MPEG3_RGB565 || video->color_model == MPEG3_601_RGB565 || video->color_model == MPEG3_RGB555 || video->color_model == MPEG3_601_RGB555 || video->color_model == MPEG3_RGBI555 || video->color_model == MPEG3_601_RGBI555 )) { /* Unscaled 16 bit */ mpeg3video_rgb16_mmx(src[0], src[2], src[1], output_rows[0], video->out_h, video->out_w, (output_rows[1] - output_rows[0]) / 2 - video->out_w); } else if(video->have_mmx && (video->color_model == MPEG3_BGRA8888 || video->color_model == MPEG3_BGR888 || /* video->color_model == MPEG3_RGB888 || */ video->color_model == MPEG3_RGBA8888 || video->color_model == MPEG3_ARGB8888 || video->color_model == MPEG3_601_BGR888 || video->color_model == MPEG3_601_BGRA8888 || video->color_model == MPEG3_601_RGB888 || video->color_model == MPEG3_601_RGBA8888|| video->color_model == MPEG3_601_ARGB8888)) { /* Original MMX */ if(video->color_model == MPEG3_BGRA8888 || video->color_model == MPEG3_RGBA8888 || video->color_model == MPEG3_ARGB8888 || video->color_model == MPEG3_601_BGRA8888 || video->color_model == MPEG3_601_RGBA8888 || video->color_model == MPEG3_601_ARGB8888) step = 4; else if(video->color_model == MPEG3_BGR888 || video->color_model == MPEG3_RGB888 || video->color_model == MPEG3_601_BGR888 || video->color_model == MPEG3_601_RGB888) step = 3; DITHER_ROW_HEAD /* Transfer row with scaling */ if(video->out_w != video->horizontal_size) { switch(video->color_model) { case MPEG3_BGRA8888: case MPEG3_BGR888: DITHER_MMX_SCALE_HEAD mpeg3_bgra32_mmx(y_in[video->x_table[w]], cr_in[uv_subscript], cb_in[uv_subscript], (unsigned long*)data); DITHER_MMX_SCALE_TAIL break; case MPEG3_601_BGRA8888: case MPEG3_601_BGR888: DITHER_MMX_SCALE_HEAD mpeg3_601_bgra32_mmx(y_in[video->x_table[w]], cr_in[uv_subscript], cb_in[uv_subscript], (unsigned long*)data); DITHER_MMX_SCALE_TAIL break; case MPEG3_RGBA8888: case MPEG3_ARGB8888: case MPEG3_RGB888: DITHER_MMX_SCALE_HEAD mpeg3_rgba32_mmx(y_in[video->x_table[w]], cr_in[uv_subscript], cb_in[uv_subscript], (unsigned long*)data); DITHER_MMX_SCALE_TAIL break; case MPEG3_601_RGBA8888: case MPEG3_601_ARGB8888: case MPEG3_601_RGB888: DITHER_MMX_SCALE_HEAD mpeg3_601_rgba32_mmx(y_in[video->x_table[w]], cr_in[uv_subscript], cb_in[uv_subscript], (unsigned long*)data); DITHER_MMX_SCALE_TAIL break; } } else /* Transfer row unscaled */ { switch(video->color_model) { /* MMX byte swap 24 and 32 bit */ case MPEG3_BGRA8888: case MPEG3_BGR888: DITHER_MMX_HEAD mpeg3_bgra32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); data += step; mpeg3_bgra32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); DITHER_MMX_TAIL break; /* MMX 601 byte swap 24 and 32 bit */ case MPEG3_601_BGRA8888: case MPEG3_601_BGR888: DITHER_MMX_HEAD mpeg3_601_bgra32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); data += step; mpeg3_601_bgra32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); DITHER_MMX_TAIL break; /* MMX 24 and 32 bit no byte swap */ case MPEG3_RGBA8888: case MPEG3_ARGB8888: case MPEG3_RGB888: DITHER_MMX_HEAD mpeg3_rgba32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); data += step; mpeg3_rgba32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); DITHER_MMX_TAIL break; /* MMX 601 24 and 32 bit no byte swap */ case MPEG3_601_RGBA8888: case MPEG3_601_ARGB8888: case MPEG3_601_RGB888: DITHER_MMX_HEAD mpeg3_601_rgba32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); data += step; mpeg3_601_rgba32_mmx(*y_in++, *cr_in, *cb_in, (unsigned long*)data); DITHER_MMX_TAIL break; } } DITHER_ROW_TAIL } else #endif /* ================================== NO MMX ==================================== */ { DITHER_ROW_HEAD /* Transfer row with scaling */ if(video->out_w != video->horizontal_size) { switch(video->color_model) { case MPEG3_BGR888: DITHER_SCALE_HEAD STORE_PIXEL_BGR888 DITHER_SCALE_TAIL break; case MPEG3_BGRA8888: DITHER_SCALE_HEAD STORE_PIXEL_BGRA8888 DITHER_SCALE_TAIL break; case MPEG3_RGB565: DITHER_SCALE_HEAD STORE_PIXEL_RGB565 DITHER_SCALE_TAIL break; case MPEG3_RGB555: DITHER_SCALE_HEAD STORE_PIXEL_RGB555 DITHER_SCALE_TAIL break; case MPEG3_RGBI555: DITHER_SCALE_HEAD STORE_PIXEL_RGBI555 DITHER_SCALE_TAIL break; case MPEG3_RGB888: DITHER_SCALE_HEAD STORE_PIXEL_RGB888 DITHER_SCALE_TAIL break; case MPEG3_RGBA8888: DITHER_SCALE_HEAD STORE_PIXEL_RGBA8888 DITHER_SCALE_TAIL break; case MPEG3_ARGB8888: DITHER_SCALE_HEAD STORE_PIXEL_ARGB8888 DITHER_SCALE_TAIL break; case MPEG3_601_BGR888: DITHER_SCALE_601_HEAD STORE_PIXEL_BGR888 DITHER_SCALE_TAIL break; case MPEG3_601_BGRA8888: DITHER_SCALE_601_HEAD STORE_PIXEL_BGRA8888 DITHER_SCALE_TAIL break; case MPEG3_601_RGB565: DITHER_SCALE_601_HEAD STORE_PIXEL_RGB565 DITHER_SCALE_TAIL break; case MPEG3_601_RGB555: DITHER_SCALE_601_HEAD STORE_PIXEL_RGB555 DITHER_SCALE_TAIL break; case MPEG3_601_RGBI555: DITHER_SCALE_601_HEAD STORE_PIXEL_RGBI555 DITHER_SCALE_TAIL break; case MPEG3_601_RGB888: DITHER_SCALE_601_HEAD STORE_PIXEL_RGB888 DITHER_SCALE_TAIL break; case MPEG3_601_RGBA8888: DITHER_SCALE_601_HEAD STORE_PIXEL_RGBA8888 DITHER_SCALE_TAIL break; case MPEG3_601_ARGB8888: DITHER_SCALE_601_HEAD STORE_PIXEL_ARGB8888 DITHER_SCALE_TAIL break; case MPEG3_RGBA16161616: { register unsigned short *data_s = (unsigned short*)data; DITHER_SCALE_HEAD STORE_PIXEL_RGBA16161616 DITHER_SCALE_TAIL } break; } } else { /* Transfer row unscaled */ switch(video->color_model) { case MPEG3_BGR888: DITHER_HEAD STORE_PIXEL_BGR888 DITHER_TAIL break; case MPEG3_BGRA8888: DITHER_HEAD STORE_PIXEL_BGRA8888 DITHER_TAIL break; case MPEG3_RGB565: DITHER_HEAD STORE_PIXEL_RGB565 DITHER_TAIL break; case MPEG3_RGB555: DITHER_HEAD STORE_PIXEL_RGB555 DITHER_TAIL break; case MPEG3_RGBI555: DITHER_HEAD STORE_PIXEL_RGBI555 DITHER_TAIL break; case MPEG3_RGB888: DITHER_HEAD STORE_PIXEL_RGB888 DITHER_TAIL break; case MPEG3_RGBA8888: DITHER_HEAD STORE_PIXEL_RGBA8888 DITHER_TAIL break; case MPEG3_ARGB8888: DITHER_HEAD STORE_PIXEL_ARGB8888 DITHER_TAIL break; case MPEG3_601_BGR888: DITHER_601_HEAD STORE_PIXEL_BGR888 DITHER_TAIL break; case MPEG3_601_BGRA8888: DITHER_601_HEAD STORE_PIXEL_RGB565 /*? JMM */ DITHER_TAIL break; case MPEG3_601_RGB565: DITHER_601_HEAD STORE_PIXEL_RGB565 DITHER_TAIL break; case MPEG3_601_RGB555: DITHER_601_HEAD STORE_PIXEL_RGB555 DITHER_TAIL break; case MPEG3_601_RGBI555: DITHER_601_HEAD STORE_PIXEL_RGBI555 DITHER_TAIL break; case MPEG3_601_RGB888: DITHER_601_HEAD STORE_PIXEL_RGB888 DITHER_TAIL break; case MPEG3_601_RGBA8888: DITHER_601_HEAD STORE_PIXEL_RGBA8888 DITHER_TAIL break; case MPEG3_601_ARGB8888: DITHER_601_HEAD STORE_PIXEL_ARGB8888 DITHER_TAIL break; case MPEG3_RGBA16161616: { register unsigned short *data_s = (unsigned short*)data; DITHER_HEAD STORE_PIXEL_RGBA16161616 DITHER_TAIL } break; } } DITHER_ROW_TAIL } /* End of non-MMX */ #ifdef HAVE_MMX if(video->have_mmx) __asm__ __volatile__ ("emms"); #endif return 0; } int mpeg3video_ditherframe444(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_dithertop(mpeg3video_t *video, unsigned char *src[]) { if (video->color_model == MPEG3_RGB555) return mpeg3video_ditherframeFastRGB555(video, src, video->output_rows); else if (video->color_model == MPEG3_ARGB8888) return mpeg3video_ditherframeFastRGBA(video, src, video->output_rows); else return mpeg3video_ditherframe(video, src, video->output_rows); } int mpeg3video_dithertop444(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_ditherbot(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_ditherbot444(mpeg3video_t *video, unsigned char *src[]) { return 0; } void memcpy_fast(unsigned char *output, unsigned char *input, long len) { int i, len2; /* 8 byte alignment */ /* * if(!((long)input & 0x7)) * { * len2 = len >> 4; * for(i = 0; i < len2; ) * { * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; * i++; * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; * i++; * } * * for(i *= 16; i < len; i++) * { * output[i] = input[i]; * } * } * else */ memcpy(output, input, len); } int mpeg3video_init_output() { int i, value; for(i = 0; i < 256; i++) { value = (int)(1.1644 * i - 255 * 0.0627 + 0.5); if(value < 0) value = 0; else if(value > 255) value = 255; mpeg3_601_to_rgb[i] = value; } return 0; } int mpeg3video_ditherframeFastRGBA(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) { int h = 0; register unsigned char *y_in, *cb_in, *cr_in, *clipArray_ptr; long y_l, r_l, b_l, g_l; register unsigned long *data; register int uv_subscript, step, w = -1,t1,t2,alpha; register long *cr_to_gPtr,*cr_to_rPtr,*cb_to_bPtr,*cb_to_gPtr; clipArray_ptr = gClipArray_ptr; cr_to_rPtr = &video->cr_to_r[0]; cr_to_gPtr = &video->cr_to_g[0]; cb_to_bPtr = &video->cb_to_b[0]; cb_to_gPtr = &video->cb_to_g[0]; alpha = 0xFF000000; for(h = 0; h < video->out_h; h++) { t1 = video->y_table[h] + video->in_y; t2 = (t1 >> 1) * video->chrom_width; y_in = &src[0][t1 * video->coded_picture_width] + video->in_x; cb_in = &src[1][t2] + (video->in_x >> 2); cr_in = &src[2][t2] + (video->in_x >> 1); data = (unsigned long *) output_rows[h]; if(video->out_w == video->horizontal_size) { for(w = 0; w < video->horizontal_size; w++) { y_l = *y_in++; r_l = g_l = b_l = y_l << 16; g_l = (g_l + cr_to_gPtr[*cr_in] + cb_to_gPtr[*cb_in]) >> 16; r_l = (r_l + cr_to_rPtr[*cr_in]) >> 16; b_l = (b_l + cb_to_bPtr[*cb_in]) >> 16; *data++ = alpha |(clipArray_ptr[r_l] << 16) | (clipArray_ptr[g_l] << 8) | clipArray_ptr[b_l]; if(w & 1) { cr_in++; cb_in++; } } } else { for(w = 0; w < video->out_w; w++) { uv_subscript = video->x_table[w] / 2; r_l = g_l = b_l = (y_in[video->x_table[w]]) << 16; t1 = cr_in[uv_subscript]; t2 = cb_in[uv_subscript]; g_l = (g_l + cr_to_gPtr[t1] + cb_to_gPtr[t2]) >> 16; r_l = (r_l + cr_to_rPtr[t1]) >> 16; b_l = (b_l + cb_to_bPtr[t2]) >> 16; *data++ = alpha | (clipArray_ptr[r_l] << 16) | (clipArray_ptr[g_l] << 8) | clipArray_ptr[b_l]; } } } return 0; } int mpeg3video_ditherframeFastRGB555(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) { int h = 0; register unsigned char *y_in, *cb_in, *cr_in, *clipArray_ptr; register unsigned short *clipArray_ptr16r,*clipArray_ptr16g,*clipArray_ptr16b; long y_l, r_l, b_l, g_l; register unsigned short *data; register int uv_subscript, step, w = -1,t1,t2,video_horizontal_size; register long *cr_to_gPtr,*cr_to_rPtr,*cb_to_bPtr,*cb_to_gPtr;; clipArray_ptr = gClipArray_ptr; clipArray_ptr16r = gClipArray_ptr16r; clipArray_ptr16g = gClipArray_ptr16g; clipArray_ptr16b = gClipArray_ptr16b; cr_to_rPtr = &video->cr_to_r[0]; cr_to_gPtr = &video->cr_to_g[0]; cb_to_bPtr = &video->cb_to_b[0]; cb_to_gPtr = &video->cb_to_g[0]; video_horizontal_size = video->horizontal_size; for(h = 0; h < video->out_h; h++) { t1 = video->y_table[h] + video->in_y; t2 = (t1 >> 1) * video->chrom_width; y_in = &src[0][t1 * video->coded_picture_width] + video->in_x; cb_in = &src[1][t2] + (video->in_x >> 2); cr_in = &src[2][t2] + (video->in_x >> 1); data = (unsigned short*) output_rows[h]; if(video->out_w == video_horizontal_size) { for(w = 0; w < video_horizontal_size; w++) { y_l = *y_in++; r_l = g_l = b_l = y_l << 16; g_l = (g_l + cr_to_gPtr[*cr_in] + cb_to_gPtr[*cb_in]) >> 16; r_l = (r_l + cr_to_rPtr[*cr_in]) >> 16; b_l = (b_l + cb_to_bPtr[*cb_in]) >> 16; *data++ = clipArray_ptr16r[r_l] | clipArray_ptr16g[g_l] | clipArray_ptr16b[b_l]; if(w & 1) { cr_in++; cb_in++; } } } else { for(w = 0; w < video->out_w; w++) { uv_subscript = video->x_table[w] / 2; r_l = g_l = b_l = (y_in[video->x_table[w]]) << 16; t1 = cr_in[uv_subscript]; t2 = cb_in[uv_subscript]; g_l = (g_l + cr_to_gPtr[t1] + cb_to_gPtr[t2]) >> 16; r_l = (r_l + cr_to_rPtr[t1]) >> 16; b_l = (b_l + cb_to_bPtr[t2]) >> 16; *data++ = clipArray_ptr16r[r_l] | clipArray_ptr16g[g_l] | clipArray_ptr16b[b_l]; } } } return 0; } int mpeg3video_present_frame(mpeg3video_t *video) { int i, j, k, l, h; unsigned char **src = video->output_src; if (doClippingArrays) { for(h=-512;h<=512;h++) { gClipArray_ptr[h]=CLIP(h); gClipArray_ptr16r[h]=(CLIP(h) & 0xf8) << 7; gClipArray_ptr16g[h]=(CLIP(h) & 0xf8) << 2; gClipArray_ptr16b[h]=(CLIP(h) & 0xf8) >> 3; if (gClipArray_ptr[h] == 0x00) gClipArray_ptr[h] = 0x01; if (gClipArray_ptr16b[h] == 0x00) gClipArray_ptr16b[h] = 0x01; } doClippingArrays = 0; } /* Copy YUV buffers */ if(video->want_yvu) { long size[2]; long offset[2]; /* Drop a frame */ if(!video->y_output) return 0; /* Copy a frame */ if(video->in_x == 0 && video->in_w >= video->coded_picture_width) { size[0] = video->coded_picture_width * video->in_h; size[1] = video->chrom_width * (int)((float)video->in_h / 2 + 0.5); offset[0] = video->coded_picture_width * video->in_y; offset[1] = video->chrom_width * (int)((float)video->in_y / 2 + 0.5); /* * if(video->in_y > 0) * { * offset[1] += video->chrom_width / 2; * size[1] += video->chrom_width / 2; * } */ memcpy(video->y_output, src[0] + offset[0], size[0]); memcpy(video->u_output, src[1] + offset[1], size[1]); memcpy(video->v_output, src[2] + offset[1], size[1]); } else { for(i = 0, j = video->in_y; i < video->in_h; i++, j++) { memcpy(video->y_output + i * video->in_w, src[0] + j * video->coded_picture_width + video->in_x, video->in_w); memcpy(video->u_output + i * video->in_w / 4, src[1] + j * video->chrom_width / 2 + video->in_x / 4, video->in_w / 4); memcpy(video->v_output + i * video->in_w / 4, src[2] + j * video->chrom_width / 2 + video->in_x / 4, video->in_w / 4); } } return 0; } /* Want RGB buffer */ /* Copy the frame to the output with YUV to RGB conversion */ if(video->prog_seq) { if(video->chroma_format != CHROMA444) { if (video->color_model == MPEG3_RGB555) mpeg3video_ditherframeFastRGB555(video, src, video->output_rows); else if (video->color_model == MPEG3_ARGB8888) mpeg3video_ditherframeFastRGBA(video, src, video->output_rows); else mpeg3video_ditherframe(video, src, video->output_rows); } else mpeg3video_ditherframe444(video, src); } else { if((video->pict_struct == FRAME_PICTURE && video->topfirst) || video->pict_struct == BOTTOM_FIELD) { /* top field first */ if(video->chroma_format != CHROMA444) { mpeg3video_dithertop(video, src); mpeg3video_ditherbot(video, src); } else { mpeg3video_dithertop444(video, src); mpeg3video_ditherbot444(video, src); } } else { /* bottom field first */ if(video->chroma_format != CHROMA444) { mpeg3video_ditherbot(video, src); mpeg3video_dithertop(video, src); } else { mpeg3video_ditherbot444(video, src); mpeg3video_dithertop444(video, src); } } } return 0; } int mpeg3video_display_second_field(mpeg3video_t *video) { /* Not used */ return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/reconmmx.s ================================================ ADD_1: dd 01010101h, 01010101h MASK_AND: dd 7f7f7f7fh, 7f7f7f7fh PLUS_384: dd 01800180h, 01800180h PLUS_128: dd 00800080h, 00800080h %assign LocalFrameSize 0 %assign RegisterStorageSize 16 ; Arguments: %assign source LocalFrameSize + RegisterStorageSize + 4 %assign dest LocalFrameSize + RegisterStorageSize + 8 %assign lx2 LocalFrameSize + RegisterStorageSize + 12 %assign h LocalFrameSize + RegisterStorageSize + 16 ; Locals (on local stack frame) ; extern void C rec_mmx ( ; unsigned char *source, ; unsigned char *dest, ; int lx2, ; int h ; ; The local variables are on the stack, ; global recva_mmx global recvac_mmx global rech_mmx global rechc_mmx global add_block_mmx global set_block_mmx align 16 rech_mmx: push esi push edi push ecx push ebx mov esi, [esp+source] mov edi, [esp+dest] mov ecx, [esp+h] mov ebx, [esp+lx2] movq mm5, [MASK_AND] movq mm6, [ADD_1] .rech1: movq mm0,[esi] movq mm1,[esi+1] movq mm2,[esi+8] movq mm3,[esi+9] psrlw mm0,1 psrlw mm1,1 psrlw mm2,1 psrlw mm3,1 pand mm0,mm5 pand mm1,mm5 pand mm2,mm5 pand mm3,mm5 paddusb mm0,mm1 paddusb mm2,mm3 paddusb mm0,mm6 paddusb mm2,mm6 movq [edi],mm0 add esi,ebx movq [edi+8],mm2 add edi,ebx dec ecx jnz .rech1 emms pop ebx pop ecx pop edi pop esi ret align 16 rechc_mmx: push esi push edi push ecx push ebx ; sub esp, LocalFrameSize mov esi, [esp+source] mov edi, [esp+dest] mov ecx, [esp+h] mov ebx, [esp+lx2] movq mm5, [MASK_AND] movq mm6, [ADD_1] .rechc1: movq mm0,[esi] movq mm1,[esi+1] psrlw mm0,1 psrlw mm1,1 pand mm0,mm5 pand mm1,mm5 paddusb mm0,mm1 paddusb mm0,mm6 movq [edi],mm0 add edi,ebx add esi,ebx dec ecx jnz .rechc1 emms ; add esp, LocalFrameSize pop ebx pop ecx pop edi pop esi ret %assign RegisterStorageSize 20 %assign source LocalFrameSize + RegisterStorageSize + 4 %assign dest LocalFrameSize + RegisterStorageSize + 8 %assign lx LocalFrameSize + RegisterStorageSize + 12 %assign lx2 LocalFrameSize + RegisterStorageSize + 16 %assign h LocalFrameSize + RegisterStorageSize + 20 align 16 recva_mmx: push esi push edi push ecx push ebx push edx mov esi, [esp+source] mov edi, [esp+dest] mov ecx, [esp+h] mov ebx, [esp+lx2] mov edx, [esp+lx] movq mm7, [MASK_AND] movq mm6, [ADD_1] .recva1: movq mm0,[esi] movq mm1,[esi+edx] movq mm2,[esi+8] movq mm3,[esi+edx+8] movq mm4,[edi] movq mm5,[edi+8] psrlw mm0,1 psrlw mm1,1 psrlw mm2,1 psrlw mm3,1 psrlw mm4,1 psrlw mm5,1 pand mm0,mm7 pand mm1,mm7 pand mm2,mm7 pand mm3,mm7 pand mm4,mm7 pand mm5,mm7 paddusb mm0,mm1 paddusb mm2,mm3 paddusb mm0,mm6 paddusb mm2,mm6 psrlw mm0,1 psrlw mm2,1 pand mm0,mm7 pand mm2,mm7 paddusb mm4,mm0 paddusb mm5,mm2 paddusb mm4,mm6 paddusb mm5,mm6 movq [edi],mm4 movq [edi+8],mm5 add edi,ebx add esi,ebx dec ecx jnz near .recva1 emms pop edx pop ebx pop ecx pop edi pop esi ret align 16 recvac_mmx: push esi push edi push ecx push ebx push edx mov esi, [esp+source] mov edi, [esp+dest] mov ecx, [esp+h] mov ebx, [esp+lx2] mov edx, [esp+lx] movq mm5, [MASK_AND] movq mm6, [ADD_1] .recvac1: movq mm0,[esi] movq mm1,[esi+edx] movq mm4,[edi] psrlw mm0,1 psrlw mm1,1 psrlw mm4,1 pand mm0,mm5 pand mm1,mm5 pand mm4,mm5 paddusb mm0,mm1 paddusb mm0,mm6 psrlw mm0,1 pand mm0,mm5 paddusb mm4,mm0 paddusb mm4,mm6 movq [edi],mm4 add edi,ebx add esi,ebx dec ecx jnz .recvac1 emms pop edx pop ebx pop ecx pop edi pop esi ret %assign RegisterStorageSize 20 %assign rfp LocalFrameSize + RegisterStorageSize + 4 %assign bp LocalFrameSize + RegisterStorageSize + 8 %assign iincr LocalFrameSize + RegisterStorageSize + 12 ; FIXME clipping needs to be done align 16 add_block_mmx: push esi push edi push ecx push ebx push edx mov esi, [esp+bp] mov edi, [esp+rfp] mov ebx, [esp+iincr] ; movq mm7, [PLUS_384] mov ecx,8 pxor mm2,mm2 ; clear %rep 8 movq mm0, [edi] ; get dest movq mm1,mm0 punpcklbw mm0,mm2 punpckhbw mm1,mm2 paddsw mm0, [esi] paddsw mm1, [esi+8] ; paddsw mm0, mm7 ; paddsw mm1, mm7 packuswb mm0,mm1 movq [edi], mm0 add edi,ebx add esi,16 %endrep emms pop edx pop ebx pop ecx pop edi pop esi ret align 16 set_block_mmx: push esi push edi push ecx push ebx push edx mov esi, [esp+bp] mov edi, [esp+rfp] mov ebx, [esp+iincr] movq mm7, [PLUS_128] %rep 4 movq mm0, [esi] movq mm1, [esi+8] paddsw mm0, mm7 movq mm2, [esi+16] paddsw mm1, mm7 movq mm3, [esi+24] paddsw mm2, mm7 packuswb mm0, mm1 paddsw mm3, mm7 movq [edi], mm0 packuswb mm2, mm3 add edi, ebx add esi, 32 movq [edi], mm2 add edi, ebx %endrep emms pop edx pop ebx pop ecx pop edi pop esi ret ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/reconstruct.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3video.h" #include #ifdef HAVE_MMX #ifdef HAVE_3Dnow static inline void recva_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { __asm__( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq (%4), %%mm2\n" /* 8 s +lx */ "movq 8(%4), %%mm3\n" /* 8 s +lx **/ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "pavgusb %%mm3, %%mm1\n" "movq (%2), %%mm2\n" /* 8 d */ "movq 8(%2), %%mm3\n" /* 8 d */ "pavgusb %%mm2, %%mm0\n" "addl %3, %4\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "movq %%mm1, 8(%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } static inline void recvac_mmx(unsigned char *s, unsigned char *d, int lx,int lx2, int h) { __asm__( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq (%4), %%mm2\n" /* 8 s +lx */ "addl %3, %1\n" "pavgusb %%mm2, %%mm0\n" "movq (%2), %%mm3\n" /* 8 d */ "addl %3, %4\n" "pavgusb %%mm3, %%mm0\n" "movq %%mm0, (%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } static inline void rech_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s */ "movq 9(%1), %%mm3\n" /* 8 s */ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "movq %%mm1, 8(%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void rechc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s +1 */ "addl %3, %1\n" "pavgusb %%mm2, %%mm0\n" "movq %%mm0, (%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void recha_mmx(unsigned char *s, unsigned char *d,int lx2, int h) { __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s */ "movq 9(%1), %%mm3\n" /* 8 s */ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "pavgusb %%mm3, %%mm1\n" "movq (%2), %%mm2\n" /* 8 d */ "movq 8(%2), %%mm3\n" /* 8 d */ "pavgusb %%mm2, %%mm0\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "movq %%mm1, 8(%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void rechac_mmx(unsigned char *s,unsigned char *d, int lx2, int h) { __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s */ "addl %3, %1\n" "pavgusb %%mm2, %%mm0\n" "movq (%2), %%mm1\n" /* 8 d */ "pavgusb %%mm1, %%mm0\n" "movq %%mm0, (%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void rec4_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { __asm__ __volatile__( "movq (%1), %%mm0\n" /* 8 s */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s +1*/ "movq 9(%1), %%mm3\n" /* 8 s +1*/ ".align 8\n" "1:" "movq (%4), %%mm4\n" /* 8 s+lx */ "pavgusb %%mm2, %%mm0\n" "movq 8(%4), %%mm5\n" /* 8 s+lx */ "pavgusb %%mm3, %%mm1\n" "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ "pavgusb %%mm4, %%mm0\n" "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ "pavgusb %%mm5, %%mm1\n" "pavgusb %%mm6, %%mm0\n" "addl %3, %4\n" "pavgusb %%mm7, %%mm1\n" "movq %%mm0, (%2)\n" "movq %%mm6, %%mm2\n" "movq %%mm7, %%mm3\n" "movq %%mm1, 8(%2)\n" "movq %%mm4, %%mm0\n" "movq %%mm5, %%mm1\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } static inline void rec4c_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { __asm__ __volatile__( "movq (%1), %%mm0\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s +1*/ ".align 8\n" "1:" "movq (%4), %%mm4\n" /* 8 s+lx */ "pavgusb %%mm2, %%mm0\n" "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ "pavgusb %%mm4, %%mm0\n" "addl %3, %4\n" "pavgusb %%mm6, %%mm0\n" "movq %%mm0, (%2)\n" "movq %%mm6, %%mm2\n" "movq %%mm4, %%mm0\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } static inline void rec4a_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { __asm__ __volatile__( "movq (%1), %%mm0\n" /* 8 s */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s +1*/ "movq 9(%1), %%mm3\n" /* 8 s +1*/ ".align 8\n" "1:" "movq (%4), %%mm4\n" /* 8 s+lx */ "pavgusb %%mm2, %%mm0\n" "movq 8(%4), %%mm5\n" /* 8 s+lx */ "pavgusb %%mm3, %%mm1\n" "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ "pavgusb %%mm4, %%mm0\n" "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ "pavgusb %%mm5, %%mm1\n" "movq (%2), %%mm2\n" "pavgusb %%mm6, %%mm0\n" "movq 8(%2), %%mm3\n" "pavgusb %%mm2, %%mm0\n" "addl %3, %4\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "pavgusb %%mm7, %%mm1\n" "movq %%mm6, %%mm2\n" "movq %%mm7, %%mm3\n" "movq %%mm1, 8(%2)\n" "movq %%mm4, %%mm0\n" "movq %%mm5, %%mm1\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } static inline void rec4ac_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { __asm__ __volatile__( "movq (%1), %%mm0\n" /* 8 s */ "movq 1(%1), %%mm2\n" /* 8 s +1*/ ".align 8\n" "1:" "movq (%4), %%mm4\n" /* 8 s+lx */ "pavgusb %%mm2, %%mm0\n" "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ "pavgusb %%mm4, %%mm0\n" "movq (%2), %%mm1\n" /* 8 d */ "pavgusb %%mm6, %%mm0\n" "addl %3, %4\n" "pavgusb %%mm1, %%mm0\n" "movq %%mm6, %%mm2\n" "movq %%mm0, (%2)\n" "movq %%mm4, %%mm0\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); } #else // HAVE_3DNOW static long long ADD_1 = 0x0101010101010101LL; static long long MASK_AND = 0x7f7f7f7f7f7f7f7fLL; #endif static inline void rec_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { __asm__ __volatile__( ".align 8\n" "1:\t" "movq ( %1 ), %%mm0\n" /* 8 s */ "movq 8( %1 ), %%mm2\n" /* 16 s */ "movq %%mm0, ( %2 )\n" "addl %3, %1\n" "movq %%mm2, 8( %2 )\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void recc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { __asm__ __volatile__( ".align 8\n" "1:\t" "movq ( %1 ), %%mm0\n" "addl %3, %1\n" "movq %%mm0, ( %2 )\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); } static inline void reca_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { #ifdef HAVE_3Dnow __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq (%2), %%mm2\n" /* 8 d */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 8(%2), %%mm3\n" /* 8 d */ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "movq %%mm1, 8(%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); #else /* No 3dnow */ __asm__ ( "movq _MASK_AND, %%mm5\n" "movq _ADD_1, %%mm6\n" "1:\t" "movq (%1),%%mm0\n" /* Load 16 pixels from each row */ "movq (%2),%%mm1\n" "movq 8(%1),%%mm2\n" "movq 8(%2),%%mm3\n" "psrlw $1,%%mm0\n" /* Shift pixels down */ "psrlw $1,%%mm1\n" "pand %%mm5,%%mm0\n" /* Zero out significant bit */ "psrlw $1,%%mm2\n" "pand %%mm5,%%mm1\n" "psrlw $1,%%mm3\n" "pand %%mm5,%%mm2\n" "paddusb %%mm1,%%mm0\n" /* Add pixels */ "pand %%mm5,%%mm3\n" "paddusb %%mm3,%%mm2\n" "paddusb %%mm6,%%mm0\n" /* Add 1 to results */ "paddusb %%mm6,%%mm2\n" "movq %%mm0,(%2)\n" "addl %3,%1\n" "movq %%mm2, 8(%2)\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); #endif } static inline void recac_mmx(unsigned char *s, unsigned char *d, int lx2, int h) { #ifdef HAVE_3Dnow __asm__ ( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq (%2), %%mm2\n" /* 8 d */ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "movq %%mm0, (%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); #else /* No 3dnow */ __asm__ ( "movq _MASK_AND, %%mm5\n" "movq _ADD_1, %%mm6\n" "1:\t" "movq (%1),%%mm0\n" "movq (%2),%%mm1\n" "psrlw $1,%%mm0\n" "psrlw $1,%%mm1\n" "pand %%mm5,%%mm0\n" "pand %%mm5,%%mm1\n" "paddusb %%mm1,%%mm0\n" "paddusb %%mm6,%%mm0\n" "addl %3,%1\n" "movq %%mm0,(%2)\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2) ); #endif } static inline void recv_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { #ifdef HAVE_3Dnow __asm__( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq (%4), %%mm2\n" /* 8 s +lx */ "movq 8(%1), %%mm1\n" /* 8 s */ "movq 8(%4), %%mm3\n" /* 8 s +lx **/ "pavgusb %%mm2, %%mm0\n" "addl %3, %1\n" "pavgusb %%mm3, %%mm1\n" "movq %%mm0, (%2)\n" "addl %3, %4\n" "movq %%mm1, 8(%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); #else __asm__ ( "movq _MASK_AND, %%mm5\n" "movq _ADD_1, %%mm6\n" "1:\t" "movq (%1), %%mm0\n" /* 8 s */ "movq (%4), %%mm1\n" /* 8 s +lx */ "movq 8(%1), %%mm2\n" /* 8 s */ "movq 8(%4), %%mm3\n" /* 8 s +lx **/ "psrlw $1,%%mm0\n" "psrlw $1,%%mm1\n" "pand %%mm5,%%mm0\n" "psrlw $1,%%mm2\n" "pand %%mm5,%%mm1\n" "psrlw $1,%%mm3\n" "pand %%mm5,%%mm2\n" "paddusb %%mm1,%%mm0\n" "pand %%mm5,%%mm3\n" "paddusb %%mm3,%%mm2\n" "paddusb %%mm6,%%mm0\n" "paddusb %%mm6,%%mm2\n" "movq %%mm0,(%2)\n" "addl %3,%1\n" "movq %%mm2, 8(%2)\n" "addl %3,%4\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); #endif } static inline void recvc_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { #ifdef HAVE_3Dnow __asm__( ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 s */ "movq (%4), %%mm2\n" /* 8 s +lx */ "addl %3, %1\n" "pavgusb %%mm2, %%mm0\n" "addl %3, %4\n" "movq %%mm0, (%2)\n" "addl %3, %2\n" "loop 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); #else __asm__ ( "movq _MASK_AND, %%mm5\n" "movq _ADD_1, %%mm6\n" "1:\t" "movq (%1), %%mm0\n" /* 8 s */ "movq (%4), %%mm1\n" /* 8 s +lx */ "psrlw $1,%%mm0\n" "psrlw $1,%%mm1\n" "pand %%mm5,%%mm0\n" "pand %%mm5,%%mm1\n" "paddusb %%mm1,%%mm0\n" "addl %3,%1\n" "paddusb %%mm6,%%mm0\n" "addl %3,%4\n" "movq %%mm0,(%2)\n" "decl %0\n" "leal (%2, %3), %2\n" "jnz 1b\n" : : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) ); #endif } #endif // HAVE_MMX static inline void rec(unsigned char *s, unsigned char *d, int lx2, int h) { int j; # ifdef __POWERPC__ unsigned long t1,t2,t3,t4; #endif for(j = 0; j < h; j++, s += lx2, d += lx2) { # ifdef __POWERPC__ t1 = *(unsigned long *) s; t2 = *(((unsigned long *) s)+1); t3 = *(((unsigned long *) s)+2); t4 = *(((unsigned long *) s)+3); *(unsigned long *) d = t1; *(((unsigned long *) d)+1) = t2; *(((unsigned long *) d)+2) = t3; *(((unsigned long *) d)+3) = t4; #else d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; d[8] = s[8]; d[9] = s[9]; d[10] = s[10]; d[11] = s[11]; d[12] = s[12]; d[13] = s[13]; d[14] = s[14]; d[15] = s[15]; #endif } } static inline void recc(unsigned char *s, unsigned char *d, int lx2, int h) { int j; # ifdef __POWERPC__ long t1,t2; #endif for(j = 0; j < h; j++, s += lx2, d += lx2) { # ifdef __POWERPC__ t1 = *(long *) s; t2 = *(((long *) s)+1); *(long *) d = t1; *(((long *) d)+1) = t2; #else d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; #endif } } static inline void reca(unsigned char *s, unsigned char *d, int lx2, int h) { int j; for(j = 0; j < h; j++, s +=lx2, d +=lx2) { d[0] = (unsigned int)(d[0] + s[0] + 1) >> 1; d[1] = (unsigned int)(d[1] + s[1] + 1) >> 1; d[2] = (unsigned int)(d[2] + s[2] + 1) >> 1; d[3] = (unsigned int)(d[3] + s[3] + 1) >> 1; d[4] = (unsigned int)(d[4] + s[4] + 1) >> 1; d[5] = (unsigned int)(d[5] + s[5] + 1) >> 1; d[6] = (unsigned int)(d[6] + s[6] + 1) >> 1; d[7] = (unsigned int)(d[7] + s[7] + 1) >> 1; d[8] = (unsigned int)(d[8] + s[8] + 1) >> 1; d[9] = (unsigned int)(d[9] + s[9] + 1) >> 1; d[10] = (unsigned int)(d[10] + s[10] + 1) >> 1; d[11] = (unsigned int)(d[11] + s[11] + 1) >> 1; d[12] = (unsigned int)(d[12] + s[12] + 1) >> 1; d[13] = (unsigned int)(d[13] + s[13] + 1) >> 1; d[14] = (unsigned int)(d[14] + s[14] + 1) >> 1; d[15] = (unsigned int)(d[15] + s[15] + 1) >> 1; } } static inline void recac(unsigned char *s, unsigned char *d, int lx2, int h) { int j; for(j = 0; j < h; j++, s += lx2, d += lx2) { d[0] = (unsigned int)(d[0] + s[0] + 1)>>1; d[1] = (unsigned int)(d[1] + s[1] + 1)>>1; d[2] = (unsigned int)(d[2] + s[2] + 1)>>1; d[3] = (unsigned int)(d[3] + s[3] + 1)>>1; d[4] = (unsigned int)(d[4] + s[4] + 1)>>1; d[5] = (unsigned int)(d[5] + s[5] + 1)>>1; d[6] = (unsigned int)(d[6] + s[6] + 1)>>1; d[7] = (unsigned int)(d[7] + s[7] + 1)>>1; } } static inline void recv(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { unsigned char *dp,*sp,*sp2; int j; sp = s; sp2 = s + lx; dp = d; for(j = 0; j < h; j++) { dp[0] = (unsigned int)(sp[0] + sp2[0] + 1) >> 1; dp[1] = (unsigned int)(sp[1] + sp2[1] + 1) >> 1; dp[2] = (unsigned int)(sp[2] + sp2[2] + 1) >> 1; dp[3] = (unsigned int)(sp[3] + sp2[3] + 1) >> 1; dp[4] = (unsigned int)(sp[4] + sp2[4] + 1) >> 1; dp[5] = (unsigned int)(sp[5] + sp2[5] + 1) >> 1; dp[6] = (unsigned int)(sp[6] + sp2[6] + 1) >> 1; dp[7] = (unsigned int)(sp[7] + sp2[7] + 1) >> 1; dp[8] = (unsigned int)(sp[8] + sp2[8] + 1) >> 1; dp[9] = (unsigned int)(sp[9] + sp2[9] + 1) >> 1; dp[10] = (unsigned int)(sp[10] + sp2[10] + 1) >> 1; dp[11] = (unsigned int)(sp[11] + sp2[11] + 1) >> 1; dp[12] = (unsigned int)(sp[12] + sp2[12] + 1) >> 1; dp[13] = (unsigned int)(sp[13] + sp2[13] + 1) >> 1; dp[14] = (unsigned int)(sp[14] + sp2[14] + 1) >> 1; dp[15] = (unsigned int)(sp[15] + sp2[15] + 1) >> 1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void recvc(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { unsigned char *dp,*sp,*sp2; int j; sp = s; sp2 = s+lx; dp = d; for(j = 0; j < h; j++) { dp[0] = (unsigned int)(sp[0]+sp2[0]+1)>>1; dp[1] = (unsigned int)(sp[1]+sp2[1]+1)>>1; dp[2] = (unsigned int)(sp[2]+sp2[2]+1)>>1; dp[3] = (unsigned int)(sp[3]+sp2[3]+1)>>1; dp[4] = (unsigned int)(sp[4]+sp2[4]+1)>>1; dp[5] = (unsigned int)(sp[5]+sp2[5]+1)>>1; dp[6] = (unsigned int)(sp[6]+sp2[6]+1)>>1; dp[7] = (unsigned int)(sp[7]+sp2[7]+1)>>1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void recva(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { unsigned char *dp,*sp,*sp2; int j; sp = s; sp2 = s+lx; dp = d; for (j=0; j>1) + 1)>>1; dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; dp[8] = (dp[8] + ((unsigned int)(sp[8]+sp2[8]+1)>>1) + 1)>>1; dp[9] = (dp[9] + ((unsigned int)(sp[9]+sp2[9]+1)>>1) + 1)>>1; dp[10] = (dp[10] + ((unsigned int)(sp[10]+sp2[10]+1)>>1) + 1)>>1; dp[11] = (dp[11] + ((unsigned int)(sp[11]+sp2[11]+1)>>1) + 1)>>1; dp[12] = (dp[12] + ((unsigned int)(sp[12]+sp2[12]+1)>>1) + 1)>>1; dp[13] = (dp[13] + ((unsigned int)(sp[13]+sp2[13]+1)>>1) + 1)>>1; dp[14] = (dp[14] + ((unsigned int)(sp[14]+sp2[14]+1)>>1) + 1)>>1; dp[15] = (dp[15] + ((unsigned int)(sp[15]+sp2[15]+1)>>1) + 1)>>1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void recvac(unsigned char *s, unsigned char *d, int lx,int lx2, int h){ unsigned char *dp,*sp,*sp2; int j; sp = s; sp2 = s+lx; dp = d; for (j=0; j>1) + 1)>>1; dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void rech(unsigned char *s, unsigned char *d, int lx2, int h){ unsigned char *dp,*sp; unsigned int s1,s2; int j; sp = s; dp = d; for (j=0; j>1; dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; dp[7] = (unsigned int)(s2+(s1=sp[8])+1)>>1; dp[8] = (unsigned int)(s1+(s2=sp[9])+1)>>1; dp[9] = (unsigned int)(s2+(s1=sp[10])+1)>>1; dp[10] = (unsigned int)(s1+(s2=sp[11])+1)>>1; dp[11] = (unsigned int)(s2+(s1=sp[12])+1)>>1; dp[12] = (unsigned int)(s1+(s2=sp[13])+1)>>1; dp[13] = (unsigned int)(s2+(s1=sp[14])+1)>>1; dp[14] = (unsigned int)(s1+(s2=sp[15])+1)>>1; dp[15] = (unsigned int)(s2+sp[16]+1)>>1; sp+= lx2; dp+= lx2; } } static inline void rechc(unsigned char *s,unsigned char *d, int lx2, int h){ unsigned char *dp,*sp; unsigned int s1,s2; int j; sp = s; dp = d; for (j=0; j>1; dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; dp[7] = (unsigned int)(s2+sp[8]+1)>>1; sp+= lx2; dp+= lx2; } } static inline void recha(unsigned char *s, unsigned char *d,int lx2, int h) { unsigned char *dp,*sp; unsigned int s1,s2; int j; sp = s; dp = d; for (j = 0; j < h; j++) { s1 = sp[0]; dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; dp[7] = (dp[7] + ((unsigned int)(s2 + (s1 = sp[8]) + 1) >> 1) + 1) >> 1; dp[8] = (dp[8] + ((unsigned int)(s1 + (s2 = sp[9]) + 1) >> 1) + 1) >> 1; dp[9] = (dp[9] + ((unsigned int)(s2 + (s1 = sp[10]) + 1) >> 1) + 1) >> 1; dp[10] = (dp[10] + ((unsigned int)(s1 + (s2 = sp[11]) + 1) >> 1) + 1) >> 1; dp[11] = (dp[11] + ((unsigned int)(s2 + (s1 = sp[12]) + 1) >> 1) + 1) >> 1; dp[12] = (dp[12] + ((unsigned int)(s1 + (s2 = sp[13]) + 1) >> 1) + 1) >> 1; dp[13] = (dp[13] + ((unsigned int)(s2 + (s1 = sp[14]) + 1) >> 1) + 1) >> 1; dp[14] = (dp[14] + ((unsigned int)(s1 + (s2 = sp[15]) + 1) >> 1) + 1) >> 1; dp[15] = (dp[15] + ((unsigned int)(s2 + sp[16] + 1) >> 1) + 1) >> 1; sp += lx2; dp += lx2; } } static inline void rechac(unsigned char *s,unsigned char *d, int lx2, int h) { unsigned char *dp,*sp; unsigned int s1,s2; int j; sp = s; dp = d; for(j = 0; j < h; j++) { s1 = sp[0]; dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; dp[7] = (dp[7] + ((unsigned int)(s2 + sp[8] + 1) >> 1) + 1) >> 1; sp += lx2; dp += lx2; } } static inline void rec4(unsigned char *s, unsigned char *d, int lx, int lx2, int h) { unsigned char *dp,*sp,*sp2; unsigned int s1,s2,s3,s4; int j; sp = s; sp2 = s+lx; dp = d; for (j=0; j>2; dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; dp[7] = (unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2; dp[8] = (unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2; dp[9] = (unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2; dp[10] = (unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2; dp[11] = (unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2; dp[12] = (unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2; dp[13] = (unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2; dp[14] = (unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2; dp[15] = (unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void rec4c(unsigned char *s,unsigned char *d, int lx, int lx2, int h) { unsigned char *dp,*sp,*sp2; unsigned int s1,s2,s3,s4; int j; sp = s; sp2 = s+lx; dp = d; for (j=0; j>2; dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; dp[7] = (unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void rec4a(unsigned char *s,unsigned char *d, int lx, int lx2, int h) { unsigned char *dp=d, *sp=s, *sp2=s+lx; unsigned int s1, s2, s3, s4; int j; /* sp = s; sp2 = s+lx; dp = d; */ for (j=0; j>2) + 1)>>1; dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; dp[7] = (dp[7] + ((unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2) + 1)>>1; dp[8] = (dp[8] + ((unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2) + 1)>>1; dp[9] = (dp[9] + ((unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2) + 1)>>1; dp[10] = (dp[10] + ((unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2) + 1)>>1; dp[11] = (dp[11] + ((unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2) + 1)>>1; dp[12] = (dp[12] + ((unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2) + 1)>>1; dp[13] = (dp[13] + ((unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2) + 1)>>1; dp[14] = (dp[14] + ((unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2) + 1)>>1; dp[15] = (dp[15] + ((unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2) + 1)>>1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void rec4ac(unsigned char *s,unsigned char *d, int lx, int lx2, int h) { unsigned char *dp=d, *sp=s, *sp2=s+lx; unsigned int s1,s2,s3,s4; int j; /* sp = s; sp2 = s+lx; dp = d; */ for (j=0; j>2) + 1)>>1; dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; dp[7] = (dp[7] + ((unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2) + 1)>>1; sp+= lx2; sp2+= lx2; dp+= lx2; } } static inline void recon_comp(mpeg3video_t *video, unsigned char *src, unsigned char *dst, int lx, int lx2, int w, int h, int x, int y, int dx, int dy, int addflag) { int switcher; unsigned char *s, *d; /* half pel scaling */ switcher = (dx & 1) << 3 | (dy & 1) << 2 | w; if(addflag) switcher |= 2; /* origins */ s = src + lx * (y + (dy >> 1)) + x + (dx >> 1); d = dst + lx * y + x; // Accelerated functions #ifdef HAVE_MMX if(video->have_mmx) { switch(switcher) { case 0x3: reca_mmx(s, d, lx2, h); break; case 0x2: recac_mmx(s, d, lx2, h); break; case 0x1: rec_mmx(s, d, lx2, h); break; case 0x0: recc_mmx(s, d, lx2, h); break; case 0x7: recva(s, d, lx, lx2, h); break; case 0x6: recvac(s, d, lx, lx2, h); break; case 0x5: recv_mmx(s, d, lx, lx2, h); break; case 0x4: recvc_mmx(s, d, lx, lx2, h); break; case 0x9: rech(s, d, lx2, h); break; case 0x8: rechc(s, d, lx2, h); break; } } else #endif { switch(switcher) { case 0x3: reca(s, d, lx2, h); break; case 0x2: recac(s, d, lx2, h); break; case 0x1: rec(s, d, lx2, h); break; case 0x0: recc(s, d, lx2, h); break; case 0x7: recva(s, d, lx, lx2, h); break; case 0x6: recvac(s, d, lx, lx2, h); break; case 0x5: recv(s, d, lx, lx2, h); break; case 0x4: recvc(s, d, lx, lx2, h); break; case 0x9: rech(s, d, lx2, h); break; case 0x8: rechc(s, d, lx2, h); break; } } // Unaccelerated functions switch(switcher) { case 0xb: recha(s, d, lx2, h); break; case 0xa: rechac(s, d, lx2, h); break; case 0xf: rec4a(s, d, lx, lx2, h); break; case 0xe: rec4ac(s, d, lx, lx2, h); break; case 0xd: rec4(s, d, lx, lx2, h); break; case 0xc: rec4c(s, d, lx, lx2, h); break; } } /* unsigned char *src[]; * prediction source buffer * int sfield; * prediction source field number (0 or 1) * unsigned char *dst[]; * prediction destination buffer * int dfield; * prediction destination field number (0 or 1)* int lx,lx2; * horizontal offsets * int w,h; * prediction block/sub-block width, height * int x,y; * pixel co-ordinates of top-left sample in current MB * int dx,dy; * horizontal, vertical motion vector * int addflag; * add prediction error to prediction ? * */ static void recon(mpeg3video_t *video, unsigned char *src[], int sfield, unsigned char *dst[], int dfield, int lx, int lx2, int w, int h, int x, int y, int dx, int dy, int addflag) { /* Y */ recon_comp(video, (src[0] + (sfield ? (lx2 >> 1) : 0)), dst[0] + (dfield ? (lx2 >> 1) : 0), lx, lx2, w, h, x, y, dx, dy, addflag); if(video->chroma_format != CHROMA444) { lx >>= 1; dx /= 2; lx2 >>= 1; w = 0; x >>= 1; } if(video->chroma_format == CHROMA420) { h >>= 1; dy /= 2; y >>= 1; } /* Cb */ recon_comp(video, (src[1] + (sfield ? (lx2 >> 1) : 0)), dst[1] + (dfield ? (lx2 >> 1) : 0), lx, lx2, w, h, x, y, dx, dy, addflag); /* Cr */ recon_comp(video, (src[2] + (sfield ? (lx2 >> 1) : 0)), dst[2] + (dfield ? (lx2 >> 1) : 0), lx, lx2, w, h, x, y, dx, dy, addflag); } #define WIDTH 1 int mpeg3video_reconstruct(mpeg3video_t *video, int bx, int by, int mb_type, int motion_type, int PMV[2][2][2], int mv_field_sel[2][2], int dmvector[2], int stwtype) { int currentfield; unsigned char **predframe; int DMV[2][2]; int stwtop, stwbot; stwtop = stwtype % 3; /* 0:temporal, 1 : (spat+temp) / 2, 2 : spatial */ stwbot = stwtype / 3; if((mb_type & MB_FORWARD) || (video->pict_type == P_TYPE)) { if(video->pict_struct == FRAME_PICTURE) { if((motion_type == MC_FRAME) || !(mb_type & MB_FORWARD)) { /* frame-based prediction */ { if(stwtop < 2) recon(video, video->oldrefframe, 0, video->newframe, 0, video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][0][0], PMV[0][0][1], stwtop); if(stwbot < 2) recon(video, video->oldrefframe, 1, video->newframe, 1, video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][0][0], PMV[0][0][1], stwbot); } } else if(motion_type == MC_FIELD) /* field-based prediction */ { /* top field prediction */ if(stwtop < 2) recon(video, video->oldrefframe, mv_field_sel[0][0], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, PMV[0][0][0], PMV[0][0][1] >> 1, stwtop); /* bottom field prediction */ if(stwbot < 2) recon(video, video->oldrefframe, mv_field_sel[1][0], video->newframe, 1, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, PMV[1][0][0], PMV[1][0][1] >> 1, stwbot); } else if(motion_type == MC_DMV) { /* dual prime prediction */ /* calculate derived motion vectors */ mpeg3video_calc_dmv(video, DMV, dmvector, PMV[0][0][0], PMV[0][0][1] >> 1); if(stwtop < 2) { /* predict top field from top field */ recon(video, video->oldrefframe, 0, video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, PMV[0][0][0], PMV[0][0][1] >> 1, 0); /* predict and add to top field from bottom field */ recon(video, video->oldrefframe, 1, video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, DMV[0][0], DMV[0][1], 1); } if(stwbot < 2) { /* predict bottom field from bottom field */ recon(video, video->oldrefframe, 1, video->newframe, 1, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, PMV[0][0][0], PMV[0][0][1]>>1, 0); /* predict and add to bottom field from top field */ recon(video, video->oldrefframe, 0, video->newframe, 1, video->coded_picture_width << 1, video->coded_picture_width<<1, WIDTH, 8, bx, by>>1, DMV[1][0], DMV[1][1], 1); } } else /* invalid motion_type */ /* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ ; } else { /* TOP_FIELD or BOTTOM_FIELD */ /* field picture */ currentfield = (video->pict_struct == BOTTOM_FIELD); /* determine which frame to use for prediction */ if((video->pict_type == P_TYPE) && video->secondfield && (currentfield != mv_field_sel[0][0])) predframe = video->refframe; /* same frame */ else predframe = video->oldrefframe; /* previous frame */ if((motion_type == MC_FIELD) || !(mb_type & MB_FORWARD)) { /* field-based prediction */ if(stwtop < 2) recon(video, predframe,mv_field_sel[0][0],video->newframe,0, video->coded_picture_width << 1,video->coded_picture_width << 1,WIDTH,16,bx,by, PMV[0][0][0],PMV[0][0][1],stwtop); } else if(motion_type == MC_16X8) { if(stwtop < 2) { recon(video, predframe, mv_field_sel[0][0], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][0][0], PMV[0][0][1], stwtop); /* determine which frame to use for lower half prediction */ if((video->pict_type==P_TYPE) && video->secondfield && (currentfield!=mv_field_sel[1][0])) predframe = video->refframe; /* same frame */ else predframe = video->oldrefframe; /* previous frame */ recon(video, predframe, mv_field_sel[1][0], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, PMV[1][0][0], PMV[1][0][1], stwtop); } } else if(motion_type == MC_DMV) /* dual prime prediction */ { if(video->secondfield) predframe = video->refframe; /* same frame */ else predframe = video->oldrefframe; /* previous frame */ /* calculate derived motion vectors */ mpeg3video_calc_dmv(video, DMV, dmvector, PMV[0][0][0], PMV[0][0][1]); /* predict from field of same parity */ recon(video, video->oldrefframe, currentfield, video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, PMV[0][0][0], PMV[0][0][1], 0); /* predict from field of opposite parity */ recon(video, predframe, !currentfield, video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, DMV[0][0], DMV[0][1], 1); } else /* invalid motion_type */ /* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ ; } stwtop = stwbot = 1; } if(mb_type & MB_BACKWARD) { if(video->pict_struct == FRAME_PICTURE) { if(motion_type == MC_FRAME) { /* frame-based prediction */ if(stwtop < 2) recon(video, video->refframe, 0, video->newframe, 0, video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][1][0], PMV[0][1][1], stwtop); if(stwbot < 2) recon(video, video->refframe, 1, video->newframe, 1, video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][1][0], PMV[0][1][1], stwbot); } else { /* field-based prediction */ /* top field prediction */ if(stwtop < 2) { recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, (video->coded_picture_width << 1), (video->coded_picture_width<<1), WIDTH, 8, bx, (by >> 1), PMV[0][1][0], (PMV[0][1][1] >> 1), stwtop); } /* bottom field prediction */ if(stwbot < 2) { recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 1, (video->coded_picture_width << 1), (video->coded_picture_width << 1), WIDTH, 8, bx, (by>>1), PMV[1][1][0], (PMV[1][1][1]>>1), stwbot); } } } else { /* TOP_FIELD or BOTTOM_FIELD */ /* field picture */ if(motion_type == MC_FIELD) { /* field-based prediction */ recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, PMV[0][1][0], PMV[0][1][1], stwtop); } else if(motion_type==MC_16X8) { recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, PMV[0][1][0], PMV[0][1][1], stwtop); recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 0, video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, PMV[1][1][0], PMV[1][1][1], stwtop); } else /* invalid motion_type */ /* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ ; } } /* mb_type & MB_BACKWARD */ return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/seek.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3protos.h" #include "mpeg3video.h" #include #include unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream) { /* Perform forwards search */ mpeg3bits_byte_align(stream); /* Perform search */ while((mpeg3bits_showbits32_noptr(stream) >> 8) != MPEG3_PACKET_START_CODE_PREFIX && !mpeg3bits_eof(stream)) { mpeg3bits_getbyte_noptr(stream); } return mpeg3bits_showbits32_noptr(stream); } /* Line up on the beginning of the next code. */ int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code) { while(!mpeg3bits_eof(stream) && mpeg3bits_showbits32_noptr(stream) != code) { mpeg3bits_getbyte_noptr(stream); } return mpeg3bits_eof(stream); } /* Line up on the beginning of the previous code. */ int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code) { while(!mpeg3bits_bof(stream) && mpeg3bits_showbits_reverse(stream, 32) != code) { mpeg3bits_getbits_reverse(stream, 8); } return mpeg3bits_bof(stream); } long mpeg3video_goptimecode_to_frame(mpeg3video_t *video) { /* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */ /* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */ return (long)(video->gop_timecode.hour * 3600 * video->frame_rate + video->gop_timecode.minute * 60 * video->frame_rate + video->gop_timecode.second * video->frame_rate + video->gop_timecode.frame) - 1 - video->first_frame; } int mpeg3video_match_refframes(mpeg3video_t *video) { unsigned char *dst, *src; int i, j, size; for(i = 0; i < 3; i++) { if(video->newframe[i]) { if(video->newframe[i] == video->refframe[i]) { src = video->refframe[i]; dst = video->oldrefframe[i]; } else { src = video->oldrefframe[i]; dst = video->refframe[i]; } if(i == 0) size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width; else size = video->chrom_width * video->chrom_height + 32 * video->chrom_width; memcpy(dst, src, size); } } return 0; } int mpeg3video_seek(mpeg3video_t *video) { long this_gop_start; int result = 0; int back_step; int attempts; mpeg3_t *file = (mpeg3_t *) video->file; mpeg3_bits_t *vstream = video->vstream; double percentage; long frame_number; int match_refframes = 1; /* Seek to a percentage */ if(video->percentage_seek >= 0) { percentage = video->percentage_seek; video->percentage_seek = -1; mpeg3bits_seek_percentage(vstream, percentage); // Go to previous I-frame mpeg3bits_start_reverse(vstream); result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); if(!result) mpeg3bits_getbits_reverse(vstream, 32); mpeg3bits_start_forward(vstream); if(mpeg3bits_tell_percentage(vstream) < 0) mpeg3bits_seek_percentage(vstream, 0); // Read up to the correct percentage result = 0; while(!result && mpeg3bits_tell_percentage(vstream) < percentage) { result = mpeg3video_read_frame_backend(video, 0); if(match_refframes) mpeg3video_match_refframes(video); match_refframes = 0; } } else /* Seek to a frame */ if(video->frame_seek >= 0) { frame_number = video->frame_seek; video->frame_seek = -1; if(frame_number < 0) frame_number = 0; if(frame_number > video->maxframe) frame_number = video->maxframe; /* Seek to start of file */ if(frame_number < 16) { video->repeat_count = video->current_repeat = 0; mpeg3bits_seek_start(vstream); video->framenum = 0; result = mpeg3video_drop_frames(video, frame_number - video->framenum); } else { /* Seek to an I frame. */ if((frame_number < video->framenum || frame_number - video->framenum > MPEG3_SEEK_THRESHOLD)) { /* Elementary stream */ if(file->is_video_stream) { mpeg3_t *file = (mpeg3_t *) video->file; mpeg3_vtrack_t *track = (mpeg3_vtrack_t *) video->track; long byte = (long)((float)(mpeg3demuxer_total_bytes(vstream->demuxer) / track->total_frames) * frame_number); long minimum = 65535; int done = 0; //printf("seek elementary %d\n", frame_number); /* Get GOP just before frame */ do { result = mpeg3bits_seek_byte(vstream, byte); mpeg3bits_start_reverse(vstream); if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); mpeg3bits_start_forward(vstream); mpeg3bits_getbits(vstream, 8); if(!result) result = mpeg3video_getgophdr(video); this_gop_start = mpeg3video_goptimecode_to_frame(video); //printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result); if(labs(this_gop_start - frame_number) >= labs(minimum)) done = 1; else { minimum = this_gop_start - frame_number; byte += (long)((float)(frame_number - this_gop_start) * (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / track->total_frames)); if(byte < 0) byte = 0; } }while(!result && !done); //printf("wanted %d guessed %d\n", frame_number, this_gop_start); if(!result) { video->framenum = this_gop_start; result = mpeg3video_drop_frames(video, frame_number - video->framenum); } } else /* System stream */ { mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate); percentage = mpeg3bits_tell_percentage(vstream); //printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream)); mpeg3bits_start_reverse(vstream); mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); mpeg3bits_getbits_reverse(vstream, 32); mpeg3bits_start_forward(vstream); //printf("seek system 1 %f\n", (double)frame_number / video->frame_rate); while(!result && mpeg3bits_tell_percentage(vstream) < percentage) { result = mpeg3video_read_frame_backend(video, 0); if(match_refframes) mpeg3video_match_refframes(video); //printf("seek system 2 %f %f\n", mpeg3bits_tell_percentage(vstream) / percentage); match_refframes = 0; } //printf("seek system 3 %f\n", (double)frame_number / video->frame_rate); } video->framenum = frame_number; } else // Drop frames { mpeg3video_drop_frames(video, frame_number - video->framenum); } } } return result; } int mpeg3video_drop_frames(mpeg3video_t *video, long frames) { int result = 0; long frame_number = video->framenum + frames; /* Read the selected number of frames and skip b-frames */ while(!result && frame_number > video->framenum) { result = mpeg3video_read_frame_backend(video, frame_number - video->framenum); } return result; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3video.h" #include "mpeg3videoprotos.h" #include "slice.h" #include #ifdef HAVE_MMX static unsigned long long MMX_128 = 0x80008000800080LL; #endif int mpeg3_new_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) { #ifdef USE_PTHREADS pthread_mutexattr_t mutex_attr; #endif slice_buffer->data = (unsigned char *) memoryAllocate(1,1024); slice_buffer->buffer_size = 0; slice_buffer->buffer_allocation = 1024; slice_buffer->current_position = 0; slice_buffer->bits_size = 0; slice_buffer->bits = 0; slice_buffer->done = 0; #ifdef USE_PTHREADS pthread_mutexattr_init(&mutex_attr); pthread_mutex_init(&(slice_buffer->completion_lock), &mutex_attr); #endif return 0; } int mpeg3_delete_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) { memoryFree(slice_buffer->data); #ifdef USE_PTHREADS pthread_mutex_destroy(&(slice_buffer->completion_lock)); #endif return 0; } int mpeg3_expand_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) { int i; unsigned char *new_buffer = (unsigned char *) memoryAllocate(1,slice_buffer->buffer_allocation * 2); for(i = 0; i < slice_buffer->buffer_size; i++) new_buffer[i] = slice_buffer->data[i]; memoryFree(slice_buffer->data); slice_buffer->data = new_buffer; slice_buffer->buffer_allocation *= 2; return 0; } /* limit coefficients to -2048..2047 */ /* move/add 8x8-Block from block[comp] to refframe */ static inline int mpeg3video_addblock(mpeg3_slice_t *slice, mpeg3video_t *video, int comp, int bx, int by, int dct_type, int addflag) { int cc, i, iincr; unsigned char *rfp; short *bp; int spar = slice->sparse[comp]; /* color component index */ cc = (comp < 4) ? 0 : (comp & 1) + 1; if(cc == 0) { /* luminance */ if(video->pict_struct == FRAME_PICTURE) { if(dct_type) { /* field DCT coding */ rfp = video->newframe[0] + video->coded_picture_width * (by + ((comp & 2) >> 1)) + bx + ((comp & 1) << 3); iincr = (video->coded_picture_width << 1); } else { /* frame DCT coding */ rfp = video->newframe[0] + video->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = video->coded_picture_width; } } else { /* field picture */ rfp = video->newframe[0] + (video->coded_picture_width << 1) * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = (video->coded_picture_width << 1); } } else { /* chrominance */ /* scale coordinates */ if(video->chroma_format != CHROMA444) bx >>= 1; if(video->chroma_format == CHROMA420) by >>= 1; if(video->pict_struct == FRAME_PICTURE) { if(dct_type && (video->chroma_format != CHROMA420)) { /* field DCT coding */ rfp = video->newframe[cc] + video->chrom_width * (by + ((comp & 2) >> 1)) + bx + (comp & 8); iincr = (video->chrom_width << 1); } else { /* frame DCT coding */ rfp = video->newframe[cc] + video->chrom_width * (by + ((comp & 2) << 2)) + bx + (comp & 8); iincr = video->chrom_width; } } else { /* field picture */ rfp = video->newframe[cc] + (video->chrom_width << 1) * (by + ((comp & 2) << 2)) + bx + (comp & 8); iincr = (video->chrom_width << 1); } } bp = slice->block[comp]; if(addflag) { #ifdef HAVE_MMX if(video->have_mmx) { if(spar) { __asm__ __volatile__( "movq (%2), %%mm6\n" /* 4 blockvals */ "pxor %%mm4, %%mm4\n" "punpcklwd %%mm6, %%mm6\n" "punpcklwd %%mm6, %%mm6\n" ".align 8\n" "1:" "movq (%1), %%mm0\n" /* 8 rindex1 */ "movq %%mm0, %%mm2\n" "punpcklbw %%mm4, %%mm0\n" "punpckhbw %%mm4, %%mm2\n" "paddw %%mm6, %%mm0\n" "paddw %%mm6, %%mm2\n" "packuswb %%mm2, %%mm0\n" "movq %%mm0, (%1)\n" "leal (%1, %3), %1\n" "loop 1b\n" : /* scr dest */ : "c" (8),"r" (rfp), "r" (bp), "r" (iincr) ); } else { __asm__ __volatile__( "pxor %%mm4, %%mm4\n" ".align 8\n" "1:" "movq (%2), %%mm0\n" /* 8 rfp 0 1 2 3 4 5 6 7*/ "movq (%1), %%mm6\n" /* 4 blockvals 0 1 2 3 */ "movq %%mm0, %%mm2\n" "movq 8(%1), %%mm5\n" /* 4 blockvals 0 1 2 3 */ "punpcklbw %%mm4, %%mm0\n" /* 0 2 4 6 */ "punpckhbw %%mm4, %%mm2\n" /* 1 3 5 7 */ "paddw %%mm6, %%mm0\n" "paddw %%mm5, %%mm2\n" "packuswb %%mm2, %%mm0\n" "addl $16, %1\n" "movq %%mm0, (%2)\n" "leal (%2,%3), %2\n" "loop 1b\n" : /* scr dest */ : "c" (8),"r" (bp), "r" (rfp), "r" (iincr) ); } } else #endif for(i = 0; i < 8; i++) { rfp[0] = CLIP(bp[0] + rfp[0]); rfp[1] = CLIP(bp[1] + rfp[1]); rfp[2] = CLIP(bp[2] + rfp[2]); rfp[3] = CLIP(bp[3] + rfp[3]); rfp[4] = CLIP(bp[4] + rfp[4]); rfp[5] = CLIP(bp[5] + rfp[5]); rfp[6] = CLIP(bp[6] + rfp[6]); rfp[7] = CLIP(bp[7] + rfp[7]); rfp += iincr; bp += 8; } } else { #ifdef HAVE_MMX if(video->have_mmx) { if(spar) { __asm__ __volatile__( "movd (%2), %%mm0\n" /* " 0 0 0 v1" */ "punpcklwd %%mm0, %%mm0\n" /* " 0 0 v1 v1" */ "punpcklwd %%mm0, %%mm0\n" "paddw _MMX_128, %%mm0\n" "packuswb %%mm0, %%mm0\n" "leal (%0,%1,2), %%eax\n" "movq %%mm0, (%0, %1)\n" "movq %%mm0, (%%eax)\n" "leal (%%eax,%1,2), %0\n" "movq %%mm0, (%%eax, %1)\n" "movq %%mm0, (%0)\n" "leal (%0,%1,2), %%eax\n" "movq %%mm0, (%0, %1)\n" "movq %%mm0, (%%eax)\n" "movq %%mm0, (%%eax, %1)\n" : : "D" (rfp), "c" (iincr), "b" (bp) : "eax"); } else { __asm__ __volatile__( "movq _MMX_128,%%mm4\n" ".align 8\n" "1:" "movq (%1), %%mm0\n" "movq 8(%1), %%mm1\n" "paddw %%mm4, %%mm0\n" "movq 16(%1), %%mm2\n" "paddw %%mm4, %%mm1\n" "movq 24(%1), %%mm3\n" "paddw %%mm4, %%mm2\n" "packuswb %%mm1, %%mm0\n" "paddw %%mm4, %%mm3\n" "addl $32, %1\n" "packuswb %%mm3, %%mm2\n" "movq %%mm0, (%2)\n" "movq %%mm2, (%2,%3)\n" "leal (%2,%3,2), %2\n" "loop 1b\n" : : "c" (4), "r" (bp), "r" (rfp), "r" (iincr) ); } } else #endif for(i = 0; i < 8; i++) { rfp[0] = CLIP(bp[0] + 128); rfp[1] = CLIP(bp[1] + 128); rfp[2] = CLIP(bp[2] + 128); rfp[3] = CLIP(bp[3] + 128); rfp[4] = CLIP(bp[4] + 128); rfp[5] = CLIP(bp[5] + 128); rfp[6] = CLIP(bp[6] + 128); rfp[7] = CLIP(bp[7] + 128); rfp+= iincr; bp += 8; } } return 0; } int mpeg3_decode_slice(mpeg3_slice_t *slice) { mpeg3video_t *video = (mpeg3video_t *) slice->video; int comp; int mb_type, cbp, motion_type = 0, dct_type; int macroblock_address, mba_inc, mba_max; int slice_vert_pos_ext; unsigned int code; int bx, by; int dc_dct_pred[3]; int mv_count, mv_format, mvscale; int pmv[2][2][2], mv_field_sel[2][2]; int dmv, dmvector[2]; int qs; int stwtype, stwclass; int snr_cbp; int i; mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; /* number of macroblocks per picture */ mba_max = video->mb_width * video->mb_height; /* field picture has half as many macroblocks as frame */ if(video->pict_struct != FRAME_PICTURE) mba_max >>= 1; /* macroblock address */ macroblock_address = 0; /* first macroblock in slice is not skipped */ mba_inc = 0; slice->fault = 0; code = mpeg3slice_getbits(slice_buffer, 32); /* decode slice header (may change quant_scale) */ slice_vert_pos_ext = mpeg3video_getslicehdr(slice, video); /* reset all DC coefficient and motion vector predictors */ dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; for(i = 0; slice_buffer->current_position < slice_buffer->buffer_size; i++) { if(mba_inc == 0) { /* Done */ if(!mpeg3slice_showbits(slice_buffer, 23)) return 0; /* decode macroblock address increment */ mba_inc = mpeg3video_get_macroblock_address(slice); if(slice->fault) return 1; if(i == 0) { /* Get the macroblock_address */ macroblock_address = ((slice_vert_pos_ext << 7) + (code & 255) - 1) * video->mb_width + mba_inc - 1; /* first macroblock in slice: not skipped */ mba_inc = 1; } } if(slice->fault) return 1; if(macroblock_address >= mba_max) { /* mba_inc points beyond picture dimensions */ /*fprintf(stderr, "mpeg3_decode_slice: too many macroblocks in picture\n"); */ return 1; } /* not skipped */ if(mba_inc == 1) { mpeg3video_macroblock_modes(slice, video, &mb_type, &stwtype, &stwclass, &motion_type, &mv_count, &mv_format, &dmv, &mvscale, &dct_type); if(slice->fault) return 1; if(mb_type & MB_QUANT) { qs = mpeg3slice_getbits(slice_buffer, 5); if(video->mpeg2) slice->quant_scale = video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1); else slice->quant_scale = qs; if(video->scalable_mode == SC_DP) /* make sure quant_scale is valid */ slice->quant_scale = slice->quant_scale; } /* motion vectors */ /* decode forward motion vectors */ if((mb_type & MB_FORWARD) || ((mb_type & MB_INTRA) && video->conceal_mv)) { if(video->mpeg2) mpeg3video_motion_vectors(slice, video, pmv, dmvector, mv_field_sel, 0, mv_count, mv_format, video->h_forw_r_size, video->v_forw_r_size, dmv, mvscale); else mpeg3video_motion_vector(slice, video, pmv[0][0], dmvector, video->forw_r_size, video->forw_r_size, 0, 0, video->full_forw); } if(slice->fault) return 1; /* decode backward motion vectors */ if(mb_type & MB_BACKWARD) { if(video->mpeg2) mpeg3video_motion_vectors(slice, video, pmv, dmvector, mv_field_sel, 1, mv_count, mv_format, video->h_back_r_size, video->v_back_r_size, 0, mvscale); else mpeg3video_motion_vector(slice, video, pmv[0][1], dmvector, video->back_r_size, video->back_r_size, 0, 0, video->full_back); } if(slice->fault) return 1; /* remove marker_bit */ if((mb_type & MB_INTRA) && video->conceal_mv) mpeg3slice_flushbit(slice_buffer); /* macroblock_pattern */ if(mb_type & MB_PATTERN) { cbp = mpeg3video_get_cbp(slice); if(video->chroma_format == CHROMA422) { /* coded_block_pattern_1 */ cbp = (cbp << 2) | mpeg3slice_getbits2(slice_buffer); } else if(video->chroma_format == CHROMA444) { /* coded_block_pattern_2 */ cbp = (cbp << 6) | mpeg3slice_getbits(slice_buffer, 6); } } else cbp = (mb_type & MB_INTRA) ? ((1 << video->blk_cnt) - 1) : 0; if(slice->fault) return 1; /* decode blocks */ mpeg3video_clearblock(slice, 0, video->blk_cnt); for(comp = 0; comp < video->blk_cnt; comp++) { if(cbp & (1 << (video->blk_cnt - comp - 1))) { if(mb_type & MB_INTRA) { if(video->mpeg2) mpeg3video_getmpg2intrablock(slice, video, comp, dc_dct_pred); else mpeg3video_getintrablock(slice, video, comp, dc_dct_pred); } else { if(video->mpeg2) mpeg3video_getmpg2interblock(slice, video, comp); else mpeg3video_getinterblock(slice, video, comp); } if(slice->fault) return 1; } } /* reset intra_dc predictors */ if(!(mb_type & MB_INTRA)) dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; /* reset motion vector predictors */ if((mb_type & MB_INTRA) && !video->conceal_mv) { /* intra mb without concealment motion vectors */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; } if((video->pict_type == P_TYPE) && !(mb_type & (MB_FORWARD | MB_INTRA))) { /* non-intra mb without forward mv in a P picture */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; /* derive motion_type */ if(video->pict_struct == FRAME_PICTURE) motion_type = MC_FRAME; else { motion_type = MC_FIELD; /* predict from field of same parity */ mv_field_sel[0][0] = (video->pict_struct == BOTTOM_FIELD); } } if(stwclass == 4) { /* purely spatially predicted macroblock */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; } } else { /* mba_inc!=1: skipped macroblock */ mpeg3video_clearblock(slice, 0, video->blk_cnt); /* reset intra_dc predictors */ dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; /* reset motion vector predictors */ if(video->pict_type == P_TYPE) pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; /* derive motion_type */ if(video->pict_struct == FRAME_PICTURE) motion_type = MC_FRAME; else { motion_type = MC_FIELD; /* predict from field of same parity */ mv_field_sel[0][0] = mv_field_sel[0][1] = (video->pict_struct == BOTTOM_FIELD); } /* skipped I are spatial-only predicted, */ /* skipped P and B are temporal-only predicted */ stwtype = (video->pict_type == I_TYPE) ? 8 : 0; /* clear MB_INTRA */ mb_type &= ~MB_INTRA; /* no block data */ cbp = 0; } snr_cbp = 0; /* pixel coordinates of top left corner of current macroblock */ bx = 16 * (macroblock_address % video->mb_width); by = 16 * (macroblock_address / video->mb_width); /* motion compensation */ if(!(mb_type & MB_INTRA)) mpeg3video_reconstruct(video, bx, by, mb_type, motion_type, pmv, mv_field_sel, dmvector, stwtype); /* copy or add block data into picture */ for(comp = 0; comp < video->blk_cnt; comp++) { if((cbp | snr_cbp) & (1 << (video->blk_cnt - 1 - comp))) { #ifdef HAVE_MMX if(video->have_mmx) IDCT_mmx(slice->block[comp]); else #endif mpeg3video_idct_conversion(slice->block[comp]); mpeg3video_addblock(slice, video, comp, bx, by, dct_type, (mb_type & MB_INTRA) == 0); } } /* advance to next macroblock */ macroblock_address++; mba_inc--; } return 0; } void mpeg3_slice_loop(mpeg3_slice_t *slice) { mpeg3video_t *video = (mpeg3video_t *) slice->video; int result = 1; while(!slice->done) { #ifdef USE_PTHREADS pthread_mutex_lock(&(slice->input_lock)); #endif if(!slice->done) { /* Get a buffer to decode */ result = 1; #ifdef USE_PTHREADS pthread_mutex_lock(&(video->slice_lock)); #endif if(slice->buffer_step > 0) { while(slice->current_buffer <= slice->last_buffer) { if(!video->slice_buffers[slice->current_buffer].done && slice->current_buffer <= slice->last_buffer) { result = 0; break; } slice->current_buffer += slice->buffer_step; } } else { while(slice->current_buffer >= slice->last_buffer) { if(!video->slice_buffers[slice->current_buffer].done && slice->current_buffer >= slice->last_buffer) { result = 0; break; } slice->current_buffer += slice->buffer_step; } } /* Got one */ if(!result && slice->current_buffer >= 0 && slice->current_buffer < video->total_slice_buffers) { slice->slice_buffer = &(video->slice_buffers[slice->current_buffer]); slice->slice_buffer->done = 1; #ifdef USE_PTHREADS pthread_mutex_unlock(&(video->slice_lock)); pthread_mutex_unlock(&(slice->input_lock)); #endif mpeg3_decode_slice(slice); #ifdef USE_PTHREADS pthread_mutex_unlock(&(slice->slice_buffer->completion_lock)); #endif } else { #ifdef USE_PTHREADS pthread_mutex_unlock(&(video->slice_lock)); #endif } } #ifdef USE_PTHREADS pthread_mutex_unlock(&(slice->output_lock)); #else if ((slice->current_buffer > slice->last_buffer) || (slice->last_buffer == 0)) break; #endif } } int mpeg3_new_slice_decoder(void *video, mpeg3_slice_t *slice) { #ifdef USE_PTHREADS pthread_attr_t attr; struct sched_param param; pthread_mutexattr_t mutex_attr; #endif slice->video = video; slice->done = 0; #ifdef USE_PTHREADS pthread_mutexattr_init(&mutex_attr); pthread_mutex_init(&(slice->input_lock), &mutex_attr); pthread_mutex_lock(&(slice->input_lock)); pthread_mutex_init(&(slice->output_lock), &mutex_attr); pthread_mutex_lock(&(slice->output_lock)); pthread_attr_init(&attr); pthread_create(&(slice->tid), &attr, (void*)mpeg3_slice_loop, slice); #endif return 0; } int mpeg3_delete_slice_decoder(mpeg3_slice_t *slice) { slice->done = 1; #ifdef USE_PTHREADS pthread_mutex_unlock(&(slice->input_lock)); pthread_join(slice->tid, 0); pthread_mutex_destroy(&(slice->input_lock)); pthread_mutex_destroy(&(slice->output_lock)); #endif return 0; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef SLICE_H #define SLICE_H #ifdef USE_PTHREADS #include #endif /* Array of these feeds the slice decoders */ typedef struct { unsigned char *data; /* Buffer for holding the slice data */ int buffer_size; /* Size of buffer */ int buffer_allocation; /* Space allocated for buffer */ int current_position; /* Position in buffer */ unsigned MPEG3_INT32 bits; int bits_size; #ifdef USE_PTHREADS pthread_mutex_t completion_lock; /* Lock slice until completion */ #endif int done; /* Signal for slice decoder to skip */ } mpeg3_slice_buffer_t; /* Each slice decoder */ typedef struct { void *video; /* mpeg3video_t */ mpeg3_slice_buffer_t *slice_buffer; int thread_number; /* Number of this thread */ int current_buffer; /* Buffer this slice decoder is on */ int buffer_step; /* Number of buffers to skip */ int last_buffer; /* Last buffer this decoder should process */ int fault; int done; int quant_scale; int pri_brk; /* slice/macroblock */ short block[12][64]; int sparse[12]; #ifdef USE_PTHREADS pthread_t tid; /* ID of thread */ pthread_mutex_t input_lock, output_lock; #endif } mpeg3_slice_t; #define mpeg3slice_fillbits(buffer, nbits) \ while(((mpeg3_slice_buffer_t*)(buffer))->bits_size < (nbits)) \ { \ if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ { \ ((mpeg3_slice_buffer_t*)(buffer))->bits <<= 8; \ ((mpeg3_slice_buffer_t*)(buffer))->bits |= ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ } \ ((mpeg3_slice_buffer_t*)(buffer))->bits_size += 8; \ } #define mpeg3slice_flushbits(buffer, nbits) \ { \ mpeg3slice_fillbits((buffer), (nbits)); \ ((mpeg3_slice_buffer_t*)(buffer))->bits_size -= (nbits); \ } #define mpeg3slice_flushbit(buffer) \ { \ if(((mpeg3_slice_buffer_t*)(buffer))->bits_size) \ ((mpeg3_slice_buffer_t*)(buffer))->bits_size--; \ else \ if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ { \ ((mpeg3_slice_buffer_t*)(buffer))->bits = \ ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ ((mpeg3_slice_buffer_t*)(buffer))->bits_size = 7; \ } \ } static inline unsigned int mpeg3slice_getbit(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size) return (buffer->bits >> (--buffer->bits_size)) & 0x1; else if(buffer->current_position < buffer->buffer_size) { buffer->bits = buffer->data[buffer->current_position++]; buffer->bits_size = 7; return (buffer->bits >> 7) & 0x1; } } static inline unsigned int mpeg3slice_getbits2(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size >= 2) return (buffer->bits >> (buffer->bits_size -= 2)) & 0x3; else if(buffer->current_position < buffer->buffer_size) { buffer->bits <<= 8; buffer->bits |= buffer->data[buffer->current_position++]; buffer->bits_size += 6; return (buffer->bits >> buffer->bits_size) & 0x3; } } static inline unsigned int mpeg3slice_getbyte(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size >= 8) return (buffer->bits >> (buffer->bits_size -= 8)) & 0xff; else if(buffer->current_position < buffer->buffer_size) { buffer->bits <<= 8; buffer->bits |= buffer->data[buffer->current_position++]; return (buffer->bits >> buffer->bits_size) & 0xff; } } static inline unsigned int mpeg3slice_getbits(mpeg3_slice_buffer_t *slice_buffer, int bits) { if(bits == 1) return mpeg3slice_getbit(slice_buffer); mpeg3slice_fillbits(slice_buffer, bits); return (slice_buffer->bits >> (slice_buffer->bits_size -= bits)) & (0xffffffff >> (32 - bits)); } static inline unsigned int mpeg3slice_showbits16(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size >= 16) return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; else if(buffer->current_position < buffer->buffer_size) { buffer->bits <<= 16; buffer->bits_size += 16; buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; buffer->bits |= buffer->data[buffer->current_position++]; return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; } } static inline unsigned int mpeg3slice_showbits9(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size >= 9) return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; else if(buffer->current_position < buffer->buffer_size) { buffer->bits <<= 16; buffer->bits_size += 16; buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; buffer->bits |= buffer->data[buffer->current_position++]; return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; } } static inline unsigned int mpeg3slice_showbits5(mpeg3_slice_buffer_t *buffer) { if(buffer->bits_size >= 5) return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; else if(buffer->current_position < buffer->buffer_size) { buffer->bits <<= 8; buffer->bits_size += 8; buffer->bits |= buffer->data[buffer->current_position++]; return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; } } static inline unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits) { mpeg3slice_fillbits(slice_buffer, bits); return (slice_buffer->bits >> (slice_buffer->bits_size - bits)) & (0xffffffff >> (32 - bits)); } #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/vlc.c ================================================ /* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ #include "mpeg3video.h" #include "vlc.h" /* variable length code tables */ /* Table B-3, mb_type in P-pictures, codes 001..1xx */ mpeg3_VLCtab_t mpeg3_PMBtab0[8] = { {MPERROR,0}, {MB_FORWARD,3}, {MB_PATTERN,2}, {MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1} }; /* Table B-3, mb_type in P-pictures, codes 000001..00011x */ mpeg3_VLCtab_t mpeg3_PMBtab1[8] = { {MPERROR,0}, {MB_QUANT|MB_INTRA,6}, {MB_QUANT|MB_PATTERN,5}, {MB_QUANT|MB_PATTERN,5}, {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, {MB_INTRA,5}, {MB_INTRA,5} }; /* Table B-4, mb_type in B-pictures, codes 0010..11xx */ mpeg3_VLCtab_t mpeg3_BMBtab0[16] = { {MPERROR,0}, {MPERROR,0}, {MB_FORWARD,4}, {MB_FORWARD|MB_PATTERN,4}, {MB_BACKWARD,3}, {MB_BACKWARD,3}, {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} }; /* Table B-4, mb_type in B-pictures, codes 000001..00011x */ mpeg3_VLCtab_t mpeg3_BMBtab1[8] = { {MPERROR,0}, {MB_QUANT|MB_INTRA,6}, {MB_QUANT|MB_BACKWARD|MB_PATTERN,6}, {MB_QUANT|MB_FORWARD|MB_PATTERN,6}, {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, {MB_INTRA,5}, {MB_INTRA,5} }; /* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ mpeg3_VLCtab_t mpeg3_spIMBtab[16] = { {MPERROR,0}, {MB_CLASS4,4}, {MB_QUANT|MB_INTRA,4}, {MB_INTRA,4}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1} }; /* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ mpeg3_VLCtab_t mpeg3_spPMBtab0[16] = { {MPERROR,0},{MPERROR,0}, {MB_FORWARD,4}, {MB_WEIGHT|MB_FORWARD,4}, {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2} }; /* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ mpeg3_VLCtab_t mpeg3_spPMBtab1[16] = { {MPERROR,0},{MPERROR,0}, {MB_CLASS4|MB_QUANT|MB_PATTERN,7}, {MB_CLASS4,7}, {MB_PATTERN,7}, {MB_CLASS4|MB_PATTERN,7}, {MB_QUANT|MB_INTRA,7}, {MB_INTRA,7}, {MB_QUANT|MB_PATTERN,6}, {MB_QUANT|MB_PATTERN,6}, {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, {MB_WEIGHT,6}, {MB_WEIGHT,6}, {MB_WEIGHT|MB_PATTERN,6}, {MB_WEIGHT|MB_PATTERN,6} }; /* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ mpeg3_VLCtab_t mpeg3_spBMBtab0[14] = { {MB_FORWARD,4}, {MB_FORWARD|MB_PATTERN,4}, {MB_BACKWARD,3}, {MB_BACKWARD,3}, {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} }; /* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ mpeg3_VLCtab_t mpeg3_spBMBtab1[12] = { {MB_QUANT|MB_FORWARD|MB_PATTERN,7}, {MB_QUANT|MB_BACKWARD|MB_PATTERN,7}, {MB_INTRA,7}, {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,7}, {MB_WEIGHT|MB_FORWARD,6}, {MB_WEIGHT|MB_FORWARD,6}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_BACKWARD,6}, {MB_WEIGHT|MB_BACKWARD,6}, {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6} }; /* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ mpeg3_VLCtab_t mpeg3_spBMBtab2[8] = { {MB_QUANT|MB_INTRA,8}, {MB_QUANT|MB_INTRA,8}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, {MB_WEIGHT|MB_QUANT|MB_BACKWARD|MB_PATTERN,9}, {MB_CLASS4|MB_QUANT|MB_PATTERN,9}, {MB_CLASS4,9}, {MB_CLASS4|MB_PATTERN,9} }; /* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ mpeg3_VLCtab_t mpeg3_SNRMBtab[8] = { {MPERROR,0}, {0,3}, {MB_QUANT|MB_PATTERN,2}, {MB_QUANT|MB_PATTERN,2}, {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1} }; /* Table B-10, motion_code, codes 0001 ... 01xx */ mpeg3_VLCtab_t mpeg3_MVtab0[8] = { {MPERROR,0}, {3,3}, {2,2}, {2,2}, {1,1}, {1,1}, {1,1}, {1,1} }; /* Table B-10, motion_code, codes 0000011 ... 000011x */ mpeg3_VLCtab_t mpeg3_MVtab1[8] = { {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {7,6}, {6,6}, {5,6}, {4,5}, {4,5} }; /* Table B-10, motion_code, codes 0000001100 ... 000001011x */ mpeg3_VLCtab_t mpeg3_MVtab2[12] = { {16,9}, {15,9}, {14,9}, {13,9}, {12,9}, {11,9}, {10,8}, {10,8}, {9,8}, {9,8}, {8,8}, {8,8} }; /* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ mpeg3_VLCtab_t mpeg3_CBPtab0[32] = { {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {62,5}, {2,5}, {61,5}, {1,5}, {56,5}, {52,5}, {44,5}, {28,5}, {40,5}, {20,5}, {48,5}, {12,5}, {32,4}, {32,4}, {16,4}, {16,4}, {8,4}, {8,4}, {4,4}, {4,4}, {60,3}, {60,3}, {60,3}, {60,3} }; /* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ mpeg3_VLCtab_t mpeg3_CBPtab1[64] = { {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {MPERROR,0}, {58,8}, {54,8}, {46,8}, {30,8}, {57,8}, {53,8}, {45,8}, {29,8}, {38,8}, {26,8}, {37,8}, {25,8}, {43,8}, {23,8}, {51,8}, {15,8}, {42,8}, {22,8}, {50,8}, {14,8}, {41,8}, {21,8}, {49,8}, {13,8}, {35,8}, {19,8}, {11,8}, {7,8}, {34,7}, {34,7}, {18,7}, {18,7}, {10,7}, {10,7}, {6,7}, {6,7}, {33,7}, {33,7}, {17,7}, {17,7}, {9,7}, {9,7}, {5,7}, {5,7}, {63,6}, {63,6}, {63,6}, {63,6}, {3,6}, {3,6}, {3,6}, {3,6}, {36,6}, {36,6}, {36,6}, {36,6}, {24,6}, {24,6}, {24,6}, {24,6} }; /* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ mpeg3_VLCtab_t mpeg3_CBPtab2[8] = { {MPERROR,0}, {0,9}, {39,9}, {27,9}, {59,9}, {55,9}, {47,9}, {31,9} }; /* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ mpeg3_VLCtab_t mpeg3_MBAtab1[16] = { {MPERROR,0}, {MPERROR,0}, {7,5}, {6,5}, {5,4}, {5,4}, {4,4}, {4,4}, {3,3}, {3,3}, {3,3}, {3,3}, {2,3}, {2,3}, {2,3}, {2,3} }; /* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ mpeg3_VLCtab_t mpeg3_MBAtab2[104] = { {33,11}, {32,11}, {31,11}, {30,11}, {29,11}, {28,11}, {27,11}, {26,11}, {25,11}, {24,11}, {23,11}, {22,11}, {21,10}, {21,10}, {20,10}, {20,10}, {19,10}, {19,10}, {18,10}, {18,10}, {17,10}, {17,10}, {16,10}, {16,10}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7} }; /* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ mpeg3_VLCtab_t mpeg3_DClumtab0[32] = { {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}, {MPERROR, 0} }; /* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ mpeg3_VLCtab_t mpeg3_DClumtab1[16] = { {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10,9}, {11,9} }; /* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ mpeg3_VLCtab_t mpeg3_DCchromtab0[32] = { {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}, {MPERROR, 0} }; /* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ mpeg3_VLCtab_t mpeg3_DCchromtab1[32] = { {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {9, 9}, {9, 9}, {10,10}, {11,10} }; /* Table B-14, DCT coefficients table zero, * codes 0100 ... 1xxx (used for first (DC) coefficient) */ mpeg3_DCTtab_t mpeg3_DCTtabfirst[12] = { {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1} }; /* Table B-14, DCT coefficients table zero, * codes 0100 ... 1xxx (used for all other coefficients) */ mpeg3_DCTtab_t mpeg3_DCTtabnext[12] = { {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, {64,0,2}, {64,0,2}, {64,0,2}, {64,0,2}, /* EOB */ {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2} }; /* Table B-14, DCT coefficients table zero, * codes 000001xx ... 00111xxx */ mpeg3_DCTtab_t mpeg3_DCTtab0[60] = { {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ {2,2,7}, {2,2,7}, {9,1,7}, {9,1,7}, {0,4,7}, {0,4,7}, {8,1,7}, {8,1,7}, {7,1,6}, {7,1,6}, {7,1,6}, {7,1,6}, {6,1,6}, {6,1,6}, {6,1,6}, {6,1,6}, {1,2,6}, {1,2,6}, {1,2,6}, {1,2,6}, {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, {13,1,8}, {0,6,8}, {12,1,8}, {11,1,8}, {3,2,8}, {1,3,8}, {0,5,8}, {10,1,8}, {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5} }; /* Table B-15, DCT coefficients table one, * codes 000001xx ... 11111111 */ mpeg3_DCTtab_t mpeg3_DCTtab0a[252] = { {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ {7,1,7}, {7,1,7}, {8,1,7}, {8,1,7}, {6,1,7}, {6,1,7}, {2,2,7}, {2,2,7}, {0,7,6}, {0,7,6}, {0,7,6}, {0,7,6}, {0,6,6}, {0,6,6}, {0,6,6}, {0,6,6}, {4,1,6}, {4,1,6}, {4,1,6}, {4,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, {1,5,8}, {11,1,8}, {0,11,8}, {0,10,8}, {13,1,8}, {12,1,8}, {3,2,8}, {1,4,8}, {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, /* EOB */ {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, {9,1,7}, {9,1,7}, {1,3,7}, {1,3,7}, {10,1,7}, {10,1,7}, {0,8,7}, {0,8,7}, {0,9,7}, {0,9,7}, {0,12,8}, {0,13,8}, {2,3,8}, {4,2,8}, {0,14,8}, {0,15,8} }; /* Table B-14, DCT coefficients table zero, * codes 0000001000 ... 0000001111 */ mpeg3_DCTtab_t mpeg3_DCTtab1[8] = { {16,1,10}, {5,2,10}, {0,7,10}, {2,3,10}, {1,4,10}, {15,1,10}, {14,1,10}, {4,2,10} }; /* Table B-15, DCT coefficients table one, * codes 000000100x ... 000000111x */ mpeg3_DCTtab_t mpeg3_DCTtab1a[8] = { {5,2,9}, {5,2,9}, {14,1,9}, {14,1,9}, {2,4,10}, {16,1,10}, {15,1,9}, {15,1,9} }; /* Table B-14/15, DCT coefficients table zero / one, * codes 000000010000 ... 000000011111 */ mpeg3_DCTtab_t mpeg3_DCTtab2[16] = { {0,11,12}, {8,2,12}, {4,3,12}, {0,10,12}, {2,4,12}, {7,2,12}, {21,1,12}, {20,1,12}, {0,9,12}, {19,1,12}, {18,1,12}, {1,5,12}, {3,3,12}, {0,8,12}, {6,2,12}, {17,1,12} }; /* Table B-14/15, DCT coefficients table zero / one, * codes 0000000010000 ... 0000000011111 */ mpeg3_DCTtab_t mpeg3_DCTtab3[16] = { {10,2,13}, {9,2,13}, {5,3,13}, {3,4,13}, {2,5,13}, {1,7,13}, {1,6,13}, {0,15,13}, {0,14,13}, {0,13,13}, {0,12,13}, {26,1,13}, {25,1,13}, {24,1,13}, {23,1,13}, {22,1,13} }; /* Table B-14/15, DCT coefficients table zero / one, * codes 00000000010000 ... 00000000011111 */ mpeg3_DCTtab_t mpeg3_DCTtab4[16] = { {0,31,14}, {0,30,14}, {0,29,14}, {0,28,14}, {0,27,14}, {0,26,14}, {0,25,14}, {0,24,14}, {0,23,14}, {0,22,14}, {0,21,14}, {0,20,14}, {0,19,14}, {0,18,14}, {0,17,14}, {0,16,14} }; /* Table B-14/15, DCT coefficients table zero / one, * codes 000000000010000 ... 000000000011111 */ mpeg3_DCTtab_t mpeg3_DCTtab5[16] = { {0,40,15}, {0,39,15}, {0,38,15}, {0,37,15}, {0,36,15}, {0,35,15}, {0,34,15}, {0,33,15}, {0,32,15}, {1,14,15}, {1,13,15}, {1,12,15}, {1,11,15}, {1,10,15}, {1,9,15}, {1,8,15} }; /* Table B-14/15, DCT coefficients table zero / one, * codes 0000000000010000 ... 0000000000011111 */ mpeg3_DCTtab_t mpeg3_DCTtab6[16] = { {1,18,16}, {1,17,16}, {1,16,16}, {1,15,16}, {6,3,16}, {16,2,16}, {15,2,16}, {14,2,16}, {13,2,16}, {12,2,16}, {11,2,16}, {31,1,16}, {30,1,16}, {29,1,16}, {28,1,16}, {27,1,16} }; ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/vlc.h ================================================ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #ifndef VLC_H #define VLC_H /* variable length code tables */ typedef struct { char val, len; } mpeg3_VLCtab_t; typedef struct { char run, level, len; } mpeg3_DCTtab_t; /* Added 03/38/96 by Alex de Jong : avoid IRIX GNU warning */ //#ifdef ERROR //#undef ERROR //#define ERROR 99 //#endif /* Table B-3, mb_type in P-pictures, codes 001..1xx */ extern mpeg3_VLCtab_t mpeg3_PMBtab0[8]; /* Table B-3, mb_type in P-pictures, codes 000001..00011x */ extern mpeg3_VLCtab_t mpeg3_PMBtab1[8]; /* Table B-4, mb_type in B-pictures, codes 0010..11xx */ extern mpeg3_VLCtab_t mpeg3_BMBtab0[16]; /* Table B-4, mb_type in B-pictures, codes 000001..00011x */ extern mpeg3_VLCtab_t mpeg3_BMBtab1[8]; /* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ extern mpeg3_VLCtab_t mpeg3_spIMBtab[16]; /* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ extern mpeg3_VLCtab_t mpeg3_spPMBtab0[16]; /* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ extern mpeg3_VLCtab_t mpeg3_spPMBtab1[16]; /* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ extern mpeg3_VLCtab_t mpeg3_spBMBtab0[14]; /* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ extern mpeg3_VLCtab_t mpeg3_spBMBtab1[12]; /* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ extern mpeg3_VLCtab_t mpeg3_spBMBtab2[8]; /* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ extern mpeg3_VLCtab_t mpeg3_SNRMBtab[8]; /* Table B-10, motion_code, codes 0001 ... 01xx */ extern mpeg3_VLCtab_t mpeg3_MVtab0[8]; /* Table B-10, motion_code, codes 0000011 ... 000011x */ extern mpeg3_VLCtab_t mpeg3_MVtab1[8]; /* Table B-10, motion_code, codes 0000001100 ... 000001011x */ extern mpeg3_VLCtab_t mpeg3_MVtab2[12]; /* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ extern mpeg3_VLCtab_t mpeg3_CBPtab0[32]; /* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ extern mpeg3_VLCtab_t mpeg3_CBPtab1[64]; /* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ extern mpeg3_VLCtab_t mpeg3_CBPtab2[8]; /* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ extern mpeg3_VLCtab_t mpeg3_MBAtab1[16]; /* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ extern mpeg3_VLCtab_t mpeg3_MBAtab2[104]; /* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ extern mpeg3_VLCtab_t mpeg3_DClumtab0[32]; /* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ extern mpeg3_VLCtab_t mpeg3_DClumtab1[16]; /* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ extern mpeg3_VLCtab_t mpeg3_DCchromtab0[32]; /* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ extern mpeg3_VLCtab_t mpeg3_DCchromtab1[32]; /* Table B-14, DCT coefficients table zero, * codes 0100 ... 1xxx (used for first (DC) coefficient) */ extern mpeg3_DCTtab_t mpeg3_DCTtabfirst[12]; /* Table B-14, DCT coefficients table zero, * codes 0100 ... 1xxx (used for all other coefficients) */ extern mpeg3_DCTtab_t mpeg3_DCTtabnext[12]; /* Table B-14, DCT coefficients table zero, * codes 000001xx ... 00111xxx */ extern mpeg3_DCTtab_t mpeg3_DCTtab0[60]; /* Table B-15, DCT coefficients table one, * codes 000001xx ... 11111111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab0a[252]; /* Table B-14, DCT coefficients table zero, * codes 0000001000 ... 0000001111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab1[8]; /* Table B-15, DCT coefficients table one, * codes 000000100x ... 000000111x */ extern mpeg3_DCTtab_t mpeg3_DCTtab1a[8]; /* Table B-14/15, DCT coefficients table zero / one, * codes 000000010000 ... 000000011111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab2[16]; /* Table B-14/15, DCT coefficients table zero / one, * codes 0000000010000 ... 0000000011111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab3[16]; /* Table B-14/15, DCT coefficients table zero / one, * codes 00000000010000 ... 00000000011111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab4[16]; /* Table B-14/15, DCT coefficients table zero / one, * codes 000000000010000 ... 000000000011111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab5[16]; /* Table B-14/15, DCT coefficients table zero / one, * codes 0000000000010000 ... 0000000000011111 */ extern mpeg3_DCTtab_t mpeg3_DCTtab6[16]; #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Mpeg3Plugin/libmpeg/video/worksheet.c ================================================ #include #include #include static long long mpeg3_MMX_601_Y_COEF = 0x0000004000400040; inline void mpeg3_601_mmx(unsigned long y, unsigned long *output) { __asm { /* Output will be 0x00rrggbb */ movd (y), %%mm0; /* Load y 0x00000000000000yy */ /* pmullw mpeg3_MMX_601_Y_COEF, %%mm0; // Scale y 0x00000000000000yy */ psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ movd %%mm0, (output); /* Store output */ } } int main(int argc, char *argv[]) { unsigned char output[1024]; memset(output, 0, 1024); mpeg3_601_mmx(1, (unsigned long*)output); printf("%02x%02x\n", *(unsigned char*)&output[1], *(unsigned char*)&output[0]); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/PrintJobPlugin/PrintJobPlugin.h ================================================ #if defined(macintoshSqueak) #include "sqMacPrinting.h" #else #include "sqPrinting.h" #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/PseudoTTYPlugin/PseudoTTYPlugin.h ================================================ #include "../AsynchFilePlugin/AsynchFilePlugin.h" ================================================ FILE: vm/src/from_squeak/Cross/plugins/QuicktimePlugin/QuicktimePlugin.h ================================================ /* * QuicktimePlugin.h * SqueakQuicktime * * Created by John M McIntosh on 17/01/06. * Copyright 2006 Corporate Smalltalk Consulting ltd. All rights reserved, published under the Squeak-L licence * */ void SetupSurface(); int sqQuicktimeInitialize(); int sqQuicktimeShutdown(); long stQuicktimeSetSurfacewidthheightrowBytesdepthmovie(char * buffer, int width, int height, int rowBytes, int depth, void *movie); int stQuicktimeDestroy(int sqHandle); int stQuicktimeSetSemaphorefor(int index, int sqHandle); int stQuicktimeClearSemaphore(int sqHandle); ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/RePlugin3-Fixes.1.cs ================================================ 'From Squeak 3.2 of 11 July 2002 [latest update: #4917] on 17 August 2002 at 6:10:11 pm'! "Change Set: RePlugin3-Fixes Date: 17 August 2002 Author: tim@sumeru.stanford.edu Some small fixes to RePlugin3 to allow compiling on Acorn"! !RePlugin methodsFor: 're primitives' stamp: 'tpr 8/17/2002 18:00'! primPCREExec ", where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in and , generated from calls to primPCRECompile), to smalltalk String searchObject using . If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match." | searchObject searchBuffer length result matchSpacePtr matchSpaceSize | self export: true. self var:#searchBuffer declareC: 'char *searchBuffer'. self var:#matchSpacePtr declareC: 'int *matchSpacePtr'. self var:#result declareC: 'int result'. "Load Parameters" searchObject _ interpreterProxy stackObjectValue: 0. searchBuffer _ interpreterProxy arrayValueOf: searchObject. length _ interpreterProxy byteSizeOf: searchObject. self loadRcvrFromStackAt: 1. "Load Instance Variables" pcrePtr _ self rcvrPCREBufferPtr. extraPtr _ self rcvrExtraPtr. matchFlags _ self rcvrMatchFlags. matchSpacePtr _ self rcvrMatchSpacePtr. matchSpaceSize _ self rcvrMatchSpaceSize. interpreterProxy failed ifTrue:[^ nil]. result _ self cCode: 'pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize)'. interpreterProxy pop: 2; pushInteger: result. "empty call so compiler doesn't bug me about variables not used" self touch: searchBuffer; touch: matchSpacePtr; touch: matchSpaceSize; touch: length ! ! !RePlugin methodsFor: 're primitives' stamp: 'tpr 8/17/2002 18:00'! primPCREExecfromto " from: fromInteger to: toInteger>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in and , generated from calls to primPCRECompile), to smalltalk String searchObject using , beginning at offset and continuing until offset . If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match." | searchObject searchBuffer length result matchSpacePtr matchSpaceSize fromInteger toInteger | self export: true. self var:#searchBuffer declareC: 'char *searchBuffer'. self var:#fromInteger declareC: 'int fromInteger'. self var:#toInteger declareC: 'int toInteger'. self var:#matchSpacePtr declareC: 'int *matchSpacePtr'. self var:#result declareC: 'int result'. "Load Parameters" toInteger _ interpreterProxy stackIntegerValue: 0. fromInteger _ interpreterProxy stackIntegerValue: 1. searchObject _ interpreterProxy stackObjectValue: 2. searchBuffer _ interpreterProxy arrayValueOf: searchObject. length _ interpreterProxy byteSizeOf: searchObject. self loadRcvrFromStackAt: 3. "Validate parameters" interpreterProxy success: (1 <= fromInteger). interpreterProxy success: (toInteger<=length). fromInteger _ fromInteger - 1. "Smalltalk offsets are 1-based" interpreterProxy success: (fromInteger<=toInteger). "adjust length, searchBuffer" length _ toInteger - fromInteger. searchBuffer _ searchBuffer + fromInteger. "Load Instance Variables" pcrePtr _ self rcvrPCREBufferPtr. extraPtr _ self rcvrExtraPtr. matchFlags _ self rcvrMatchFlags. matchSpacePtr _ self rcvrMatchSpacePtr. matchSpaceSize _ self rcvrMatchSpaceSize. interpreterProxy failed ifTrue:[^ nil]. result _ self cCode: 'pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize)'. interpreterProxy pop: 2; pushInteger: result. "empty call so compiler doesn't bug me about variables not used" self touch: searchBuffer; touch: matchSpacePtr; touch: matchSpaceSize; touch: length ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'tpr 8/17/2002 18:01'! allocateStringAndSetRcvrErrorStrFromCStr: aCStrBuffer |length errorStrObj errorStrObjPtr | self var: #aCStrBuffer declareC: 'const char *aCStrBuffer'. self var: #errorStrObjPtr declareC: 'void *errorStrObjPtr'. "Allocate errorStrObj" length _ self cCode: 'strlen(aCStrBuffer)'. errorStrObj _ interpreterProxy instantiateClass: (interpreterProxy classString) indexableSize: length. self loadRcvrFromStackAt: 0. "Assume garbage collection after instantiation" "Copy aCStrBuffer to errorStrObj's buffer" errorStrObjPtr _ interpreterProxy arrayValueOf: errorStrObj. self cCode:'memcpy(errorStrObjPtr,aCStrBuffer,length)'. self touch: errorStrObjPtr; touch: errorStrObj. "Set rcvrErrorStr from errorStrObj and Return" self rcvrErrorStrFrom: errorStrObj. ^errorStrObj.! ! !RePlugin class methodsFor: 'plugin code generation' stamp: 'tpr 8/17/2002 18:02'! declareCVarsIn: cg cg addHeaderFile:'"rePlugin.h"'. "Memory Managament Error Checking" cg var: 'netMemory' declareC: 'int netMemory = 0'. cg var: 'numAllocs' declareC: 'int numAllocs = 0'. cg var: 'numFrees' declareC: 'int numFrees = 0'. cg var: 'lastAlloc' declareC: 'int lastAlloc = 0'. "The receiver Object Pointer" cg var: 'rcvr' declareC: 'int rcvr'. "Instance Variables of Receiver Object" cg var: 'patternStr' declareC: 'int patternStr'. cg var: 'compileFlags' declareC: 'int compileFlags'. cg var: 'pcrePtr' declareC: 'int pcrePtr'. cg var: 'extraPtr' declareC: 'int extraPtr'. cg var: 'errorStr' declareC: 'int errorStr'. cg var: 'errorOffset' declareC: 'int errorOffset'. cg var: 'matchFlags' declareC: 'int matchFlags'. "Support Variables for Access to Receiver Instance Variables" cg var: 'patternStrPtr' declareC: 'const char * patternStrPtr'. cg var: 'errorStrBuffer' declareC: 'const char * errorStrBuffer'.! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/RePlugin3-Fixes2.1.cs ================================================ 'From Squeak3.2gamma of 15 January 2002 [latest update: #4881] on 21 August 2002 at 10:52:51 pm'! "Change Set: RePlugin3-Fixes2 Date: 21 August 2002 Author: ian.piumarta@inria.fr Adds a cast to one method in RePlugin to avoid a compiler warning."! !RePlugin methodsFor: 'rcvr linkage' stamp: 'ikp 8/21/2002 22:40'! rcvrExtraPtr |extraObj| self inline: true. extraObj _ interpreterProxy fetchPointer: 3 ofObject: rcvr. (extraObj = (interpreterProxy nilObject)) ifTrue: [^ self cCode: '(int) NULL']. ^self cCoerce:(interpreterProxy arrayValueOf: extraObj) to: 'int'.! ! ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/RePlugin3.3.1.cs ================================================ 'From Squeak3.3alpha of 12 January 2002 [latest update: #4934] on 16 August 2002 at 10:56:49 pm'! "Change Set: RePlugin3.3 Date: 16 August 2002 Author: acg Perl-Style Regular Expressions in Smalltalk by Andrew C. Greenberg Version 3.3beta I. Regular Expressions in General Regular expressions are a language for specifying text to ease the searching and manipulation of text. A complete discussion of regular expressions is beyond the scope of this document. See Jeffrey Friedl, Mastering Regular Expressions, by O'Reilly for a relatively complete. The regular expressions supported by this package are similar to those presently used in Perl 5.05 and Python, and are based upon Philip Hazel's excellent PCRE libraries (incorporated almost without change, subject to a free license described in Re aLicenseComment. Thanks are due to Markus Kohler and Stephen Pair for their assistance in the initial ports of early versions of the Plugin. An explanation of the expressions available in this package are summarized in Re aRegexComment, Re anOptionsComment and Re aGlobalSearchComment. A more detailed description of RePlugin is available downloading the file 'RePluginDoco,' which can be obtained from http://www.gate.net/~werdna/RePlugin.html, into your default directory, and then executing Utilities reconstructTextWindowsFromFileNamed: 'RePluginDoco' II. Overview of the 'Package.' The following new classes are provided: Class Description of Instances ---------------------- ------------------------------------------------------------------- Re A regular expression matching engine ReMatch Result of a search using Re RePattern Deprecated engine class from earlier plugin versions RePlugin The Plugin 'Glue' to the PCRE Library. String Various new messages were added to String, which are the principal means for users to access the package. PluginCodeGenerator has been deleted from the packgage. III. Some Examples. A. Simple Matching and Querying of Matches To search a string for matches in a regular expression, use String reMatch: 'just trying to catch some zzz''s before noon' matchRe: 'z+' which returns true if matched, and false otherwise. If more information from a positive search result is desired, the method reMatch will return a ReMatch object corresponding to the result. 'just trying to catch some zzz''s before noon' reMatch: 'z+' The match object can be queried in various ways. For example, to obtain details when parenthetical phrases of a regular expression are captured: |m| m _ 'Andy was born on 10/02/1957, and not soon enough!!' reMatch: '(\d\d)/(\d\d)/((19|20)?\d\d)'. m matches answers with: ('10' '02' '1957' '19' ) The first message answers a ReMatch m representing the result of a search of the string for matches of re (nil would be returned if no match was found). The third message answered a collection of the parenthetical subgroups matched, each showing the day, month and year as extracted from the string. B. Global Matching and String Substitutions You can perform global searches to repeatedly search a string for non-overlapping occurrences of a pattern by using reMatch:collect: For example, 'this is a test' collectRe: '\w+' can be used to gather a collection of all words in the search string, answering: OrderedCollection ('this' 'is' 'a' 'test' ) For slightly more complex collections, you can use #reMatch:andCollect: Additionally, you can perform global searches with text substitutions using reMatch:sub: For example, 'this is a test' reMatch: '\w+' andReplace: [:m | '<', (m match), '>'] can be used to replace every word in the search string with the word enclosed by matching brackets, answering: ' ' Further examples and documentation can be found in the references above, and in the comments and definitions set forth in ReMatch, RePattern and String. "! Object subclass: #Re instanceVariableNames: 'pattern compiledPattern isAnchored isCaseSensitive isDollarEndOnly isDotIncludesNewline isExtended isExtra isMultiline isBeginningOfLine isEndOfLine isGreedy ' classVariableNames: '' module: #(Werdna Re)! !Re commentStamp: '' prior: 0! Perl-Style Regular Expressions in Smalltalk Documentation The documentation category of this method contains substantial documentation on the operation of this Class. Re aGeneralComment Re aGlobalSearchComment Re aRegexComment Re aRegexGoryDetailsComment Re aVersionsComment Re anReComment Re anReOverviewComment Re aLicenseComment Examples: (Re on: 'a.*y') search: 'Candy is dandy.' 'a.*y' asRe search: 'Candy is dandy.' 'Candy is dandy' reMatch: 'a.*y' (Re on: '\w+') searchAndCollect: 'Candy is dandy.' '\w+' asRe searchAndCollect: 'Candy is dandy.' 'Candy is dandy.' reMatch: '\w+' andCollect: [:m | m match] Structure: pattern String -- the string with the regular expression source code compiledPattern RePlugin representing a compiled pattern isAnchored Boolean -- representing an option setting is ... Booleans -- for the other options below List ofcommon public methods: #opt: sets options using Perl-style string #beAnchored #beNotAnchored #isAnchored #isAnchored: #beBeginningOfLine #beNotBeginningOfLine #isBeginningOfLine #isBeginningOfLine: #beCaseSensitive #beNotCaseSensitive #isCaseSensitive #isCaseSensitive: #beDollarEndOnly #beNotDollarEndOnly #isDollarEndOnly #isDollarEndOnly: #beDotIncludesNewline #beNotDotIncludesNewline #isDotIncludesNewLine #isDotIncludesNewline: #beEndOfLine #beNotEndOfLine #isEndOfLine #isEndOfLine: #beExtended #beNotExtended #isExtended #isExtended: #beExtra #beNotExtra #isExtra #isNotExtra: #beGreedy #beNotGreedy #isGreedy #isGreedy: #beMultiline #beNotMultiline #isMultiline #isMultiline: Getters and setters for options in traditional Smalltalk style search: aTargetString search aTargetString from: startInteger to: endInteger Compiling the pattern, if necessary, search a string (or substring) using the pattern. Answers nil if no match. searchAndCollect: aTargetString search: aTargetString andCollect: aBlock search: aTargetString andCollect: aBlock matchCount: anInteger Compiling the pattern, if necessary, gather all (or, if specified, the first anInteger) non-overlapping matches to me in aTargetString. Answer a collection of the results of applying aBlock to each ReMatch result. search: aTargetString andReplace: aBlock search: aTargetString andReplace: aBlock matchCount: anInteger Compiling the pattern, if necessary, find all (or, if specified, the first anInteger) non-overlapping matches to me in aTargetString. Answer a new string, created by substituting the results of applying aBlock to each ReMatch result for the matched substring. ! ]style[(44 16 109 1 1 18 2 23 2 16 2 27 2 19 2 14 2 22 3 1 19 1 12 280 11 236 30 1 6 40 687 66 8 13 8 13 7 12 5 10 1 118 18 13 9 13 13 6 9 13 13 6 13 9 1 217 8 13 13 6 9 13 13 6 13 9 1 266)bf3,bf1,f1,bf1,f1,f1LRe aGeneralComment;,f1,f1LRe aGlobalSearchComment;,f1,f1LRe aRegexComment;,f1,f1LRe aRegexGoryDetailsComment;,f1,f1LRe aVersionsComment;,f1,f1LRe anReComment;,f1,f1LRe anReOverviewComment;,bf1,f1,f1LRe aLicenseComment;,f1,bf1,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1! Re class instanceVariableNames: ''! Object subclass: #ReMatch instanceVariableNames: 'matchArray re searchString pos endpos ' classVariableNames: '' module: #(Werdna Re)! !ReMatch commentStamp: '' prior: 0! ReMatch: Perl-Style Regular Expression Search Results I. Introduction This Class is part of a package of classes providing a Smalltalk wrapper to Philip Hazel's excellent PCRE library. The Plugin interface and Smalltalk wrapper was written by Andrew C. Greenberg. As discussed in RePattern aGeneralComment, the functionality is essentially embodied in this class, Class RePattern and certain new messages in Class String. A summary of the regular expression syntax can be found in RePattern aRegexComment and a summary of the compile option codes available can be found in RePattern anOptionsComment. A more detailed description of RePlugin is available downloading the file 'RePluginDoco,' which can be obtained from http://www.gate.net/~werdna/RePlugin.html, into your default directory, and then executing Utilities reconstructTextWindowsFromFileNamed: 'RePluginDoco' II. Principal Match Results The substring of searchString matched by re is given by: m match which can be derived from searchString as follows: m searchString copyFrom: (m from) to: (m to) III. Captured Groups (and Collections of Captured Groups) The number of substrings capturable by a parenthetical grouping in an re (regardless of the number actually matched to create m) is given by: m numGroups The string captured by parenthetical grouping i, where 1<=i<=(m numGroups) is given by m matchAt: i and this can be generated as follows: m searchString copyFrom: (m fromAt: i) to: (m toAt: i) And an array of size (m numGroups) can be generated from strings and indices accordingly: m matches m froms m tos ! ]style[(53 2 15 214 25 65 9 103 23 69 26 120 41 53 61 2 27 177 57 488)bf3,f1,bf2,f1,f1LRePattern aGeneralComment;,f1,f1LRePattern Comment;,f1,f1LRePattern aRegexComment;,f1,f1LRePattern anOptionsComment;,f1,f1Rhttp://www.gate.net/~werdna/RePlugin.html;,f1,f1dUtilities reconstructTextWindowsFromFileNamed: 'RePluginDoco';;,f1,bf2,f1,bf2,f1! ReMatch class instanceVariableNames: ''! Object subclass: #RePattern instanceVariableNames: 'pattern compileOptions pcrePointer extraPointer errorString offset matchOptions matchSpace lastMatchResult ' classVariableNames: '' module: #(Werdna Re)! !RePattern commentStamp: '' prior: 0! RePattern: Compiled Perl-Style Regular Expressions I. Introduction. This Smalltalk implementation of modern Perl-Style regular expressions was compiled by Andrew Greenberg and contributors, based upon the excellent PCRE library by Philip Hazel. As discussed in RePattern aGeneralComment, the functionality is essentially embodied in this class, Class ReMatch and certain new messages in Class String. A summary of the regular expression syntax can be found in RePattern aRegexComment and a summary of the compile option codes available can be found in RePattern anOptionsComment. A substantially more detailed description of RePlugin is available downloading the file "RePluginDoco," which can be obtained from http://www.gate.net/~werdna/RePlugin.html, into your default directory, and then executing Utilities reconstructTextWindowsFromFileNamed: 'RePluginDoco' II. To Search a String or Substring For Pattern Matches (Once Only): Examples: 'Squeak or Squawk!!' reMatch: '^Squ(ea|aw)k' 'Squeak or Squawk!!' reMatch: '^Squ(ea|aw)k' opt: 'imsxABEXZ' 'Squeak or Squawk!!' reMatch: '^Squ(ea|aw)k!!' from: 11 more generally, srchStr reMatch: patStr [opt: oStr] [from: start] [to: stop] For a one-time search of a string (or substring) for occurences of a match pattern. The message will be answered with nil (if there is no match) or an instance of ReMatch, which can then be queried for further details about the match. III. Global Searching and Replacing The re package provides rudimentary facilities for global searches and replacements on a string. The following expressions '\w+' reMatch: 'this is a test' collect: [:m | m] (RePattern on: '\w+') search: 'this is a test' collect: [:m | m] return an ordered collection of the results of repeated non-overlapping applications of the pattern to the string, or nil if there are no matches in the string. To produce a list of matched strings, you can for example execute the following: '\w+' reMatch: 'this is a test' collect: [:m| m match] (RePattern on: '\w+') search: 'this is a test' collect: [:m | m match] You can also perform global search and string replacements, where the answer is a string with unmatched text left alone, and matched text replaced by the result of a call to a Block passed the ReMatch object as a single parameter. For example, ('\w+' reMatch: 'this is a test' sub: [:m| '<', (m match), '>'] and (RePattern on: '\w+') search: 'this is a test' sub: [:m| '<', (m match), '>'] return a string with each nonblank word surrounded by angle brackets. For more details, see RePattern aGlobalSearchComment. IV. To Create Compiled Regular Expression Objects (For Repeated Matching): '^Squ(ea|aw)k!!$' asRePattern '^Squ(ea|aw)k!!$' asRePatternOpt: 'imsxAEX' '^Squ(ea|aw)k!!$' asRePatternOpt: 'imsxAEX' onErrorRun: aBlock RePattern on: '^Squ(ea|aw)k!!$' RePattern on: '^Squ(ea|aw)k!!$' opt: 'imsxAEX' RePattern on: '^Squ(ea|aw)k!!$' opt: 'imsxAEX' onErrorRun: [:pat :offset :message | "your code here" ] Each of the preceding expressions returns an instance of RePattern, compiled for efficient matching when the pattern is repeatedly searched against different strings. RePattern ordinarily caches a dozen or so of the most recently compiled patterns, but nevertheless invokes a cost for the table lookup. To avoid compile and lookup costs, use the above messages. To perform a one-time search, see above. V. To Search a Compiled Regexp Against A String or Substring for Matches: searchString reMatch: re [from: from] [to: to] [opt: optStr] or re search: searchString [from: from] [to: to] [opt: optStr] Examples: 'Squeak or Squawk' reMatch: re. re search: 'Squeak or Squawk!!'. re search: 'Squeak or Squawk!!' opt: 'ABZ'. If no match is found, these messages answer nil. Otherwise, they answer with a corresponding instance of ReMatch.! ]style[(50 1 1 17 2 211 25 65 7 103 23 69 26 1 2 131 41 53 61 2 69 499 36 2 1110 30 3 75 749 73 362 7 1)bf3,f3,f1b,bf2,f1b,f1,f1LRePattern aGeneralComment;,f1,f1LReMatch Comment;,f1,f1LRePattern aRegexComment;,f1,f1LRePattern anOptionsComment;,f1,f1b,f1,f1Rhttp://www.gate.net/~werdna/RePlugin.html;,f1,f1dUtilities reconstructTextWindowsFromFileNamed: 'RePluginDoco';;,f1,bf2,f1,bf2,bf1,f1,f1LRePattern aGlobalSearchComment;,f1,f1b,f1,f1b,f1,f1LReMatch Comment;,f1! RePattern class instanceVariableNames: 'Patterns Options CompileObjects Front '! TestInterpreterPlugin subclass: #RePlugin instanceVariableNames: 'netMemory numAllocs numFrees lastAlloc patternStr rcvr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags patternStrPtr errorStrBuffer ' classVariableNames: '' module: #(Werdna Re)! !RePlugin commentStamp: '' prior: 0! /* Regular Expression Plugin (This class comment becomes part of rePlugin.c) RePlugin translate: 'RePlugin.c' doInlining: true. See documentation and source code for the PCRE C Library Code. This plugin is designed to serve an object such as RePattern: patternStr A 0-terminated string comprising the pattern to be compiled. compileFlags An Integer representing re compiler options PCREBuffer A ByteArray of regular expression bytecodes extraPtr A ByteArray of match optimization data (or nil) errorString A String Object For Holding an Error Message (when compile failed) errorOffset The index in patternStr (0-based) where the error ocurred (when compile failed) matchFlags An Integer representing re matcher options matchSpaceObj An Integer array for match results and workspace during matching. The instance variables must appear in the preceding order. MatchSpaceObj must be allocated by the calling routine and contain at least 6*(numGroups+1) bytes. */ #include "pcre.h" #include "internal.h" /* Slight machine-specific hack for MacOS Memory Management */ #ifdef TARGET_OS_MAC #define malloc(ptr) NewPtr(ptr) #define free(ptr) DisposePtr(aPointer) #endif /* Adjust malloc and free routines as used by PCRE */ void rePluginFree(void * aPointer); void * rePluginMalloc(size_t anInteger); void *(*pcre_malloc)(size_t) = rePluginMalloc; void (*pcre_free)(void *) = rePluginFree; ! RePlugin class instanceVariableNames: ''! TestCase subclass: #ReTest instanceVariableNames: '' classVariableNames: '' module: #(Werdna Re)! ReTest class instanceVariableNames: ''! !Re methodsFor: 'documentation' stamp: 'acg 8/3/2002 22:57'! aGeneralComment " Perl-Style Regular Expressions in Smalltalk by Andrew C. Greenberg I. Regular Expressions in General Regular expressions are a language for specifying text to ease the searching and manipulation of text. A complete discussion of regular expressions is beyond the scope of this document. See Jeffrey Friedl, Mastering Regular Expressions, by O'Reilly for a relatively complete. The regular expressions supported by this package are similar to those presently used in Perl 5.05 and Python, and are based upon Philip Hazel's excellent PCRE libraries (incorporated almost without change, subject to a free license described in Re aLicenseComment. Thanks are due to Markus Kohler and Stephen Pair for their assistance in the initial ports of early versions of the Plugin. An explanation of the expressions available in this package are summarized in Re aRegexComment, Re anOptionsComment and Re aGlobalSearchComment. A more detailed description of RePlugin is available downloading the file 'RePluginDoco,' which can be obtained from http://www.gate.net/~werdna/RePlugin.html, into your default directory, and then executing Utilities reconstructTextWindowsFromFileNamed: 'RePluginDoco' II. Overview of the 'Package.' The following new classes are provided: Class Description of Instances ---------------------- ------------------------------------------------------------------- Re A regular expression matching engine ReMatch Result of a search using Re RePattern Deprecated engine class from earlier plugin versions RePlugin The Plugin 'Glue' to the PCRE Library. String Various new messages were added to String, which are the principal means for users to access the package. PluginCodeGenerator has been deleted from the packgage. III. Some Examples. A. Simple Matching and Querying of Matches To search a string for matches in a regular expression, use String reMatch: 'just trying to catch some zzz''s before noon' matchRe: 'z+' which returns true if matched, and false otherwise. If more information from a positive search result is desired, the method reMatch will return a ReMatch object corresponding to the result. 'just trying to catch some zzz''s before noon' reMatch: 'z+' The match object can be queried in various ways. For example, to obtain details when parenthetical phrases of a regular expression are captured: |m| m _ 'Andy was born on 10/02/1957, and not soon enough!!' reMatch: '(\d\d)/(\d\d)/((19|20)?\d\d)'. m matches answers with: ('10' '02' '1957' '19' ) The first message answers a ReMatch m representing the result of a search of the string for matches of re (nil would be returned if no match was found). The third message answered a collection of the parenthetical subgroups matched, each showing the day, month and year as extracted from the string. B. Global Matching and String Substitutions You can perform global searches to repeatedly search a string for non-overlapping occurrences of a pattern by using reMatch:collect: For example, 'this is a test' collectRe: '\w+' can be used to gather a collection of all words in the search string, answering: OrderedCollection ('this' 'is' 'a' 'test' ) For slightly more complex collections, you can use #reMatch:andCollect: Additionally, you can perform global searches with text substitutions using reMatch:sub: For example, 'this is a test' reMatch: '\w+' andReplace: [:m | '<', (m match), '>'] can be used to replace every word in the search string with the word enclosed by matching brackets, answering: ' ' Further examples and documentation can be found in the references above, and in the comments and definitions set forth in ReMatch, RePattern and String. "! ]style[(19 44 24 34 211 29 289 18 206 16 2 19 5 24 119 41 53 61 2 30 224 7 34 9 59 8 46 6 179 65 291 7 442 7 268 43 832 7 2 9 5 7 2)f1b,bf3,bf2,bf1,f1,f1i,f1,f1LRe aLicenseComment;,f1,f1LRe aRegexComment;,f1,f1LRe anOptionsComment;,f1,f1LRe aGlobalSearchComment;,f1,f1Rhttp://www.gate.net/~werdna/RePlugin.html;,f1,f1dUtilities reconstructTextWindowsFromFileNamed: 'RePluginDoco';;,f1,f1b,f1,f1LReMatch Comment;,f1,f1LRePattern Comment;,f1,f1LRePlugin Comment;,f1,f1LString Comment;,f1,f1b,f1,f1LReMatch Comment;,f1,f1LReMatch Comment;,f1,f1b,f1,f1LReMatch Comment;,f1,f1LRePattern Comment;,f1,f1LString Comment;,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/3/2002 23:06'! aGlobalSearchComment " Global Searching Introduction RePattern provides facilities to support global searching and global searching and replacement of search strings with semantics quite similar to that of Perl 5.004. Global searching means that the search string is repeatedly searched for matches, beginning at the beginning of the string, and subsequently beginning the next match immediately after the preceding match terminated. For example, if we wanted to find all words in the subject string, we could execute: 'this is a test' reMatch: '\w+' collect: [:m | m match] which returns OrderedCollection ('this' 'is' 'a' 'test' ). The collect: keyword directs PCRE to repeat the search for '\w+', and to return a collection of the result of applying each ReMatch to the block. (In this case, the block simply returns the string that was matched.) To do global searching and string substitution, we could execute: 'this is a test' reMatch: '\w+' sub: [:m | '<', m match, '>'] which return ' ' The sub: keyword directs PCRE to repeat the search, and to return the original string, but with each matched substring replaced by the result of applying the block to the corresponding ReMatch object. Global Matching Functions RePattern convenience functions provide the following general global functions: searchString reMatch: pattern [opt: oStr] collect: aBlock [num: anInteger] searchString reMatch: pattern [opt: oStr] sub: aBlock [num: anInteger] Optionally, you may specify search and compile options with oStr, and you may specify a maximum number of searches performed in the global search with anInteger. If anInteger is less than 0, then as many searches as can be performed, will be performed. Special Case of the Empty Match Finally, the definition given above would infinite loop if the pattern matches an empty string. For example: 'abcdef' reMatch: 'x*' sub: [:m| '<', m match, '>'] will actually match the empty string just before and after each letter of the string, even though there is no x there. ('x+' would return nil). Since the string ends where it begins, at the beginning of the string, repeating the search from that point would simply infinite loop. Accordingly, RePattern gives the pattern a one-character 'bump' after matching an empty string, at which point the block is applied. For example, the preceding would answer '<>a<>b<>c<>d<>e<>f<>' In the case of global searching (but not replacement), an empty string will not result in the ReMatch being applied to the block if the empty match immediately follows a match that has already been made. Accordingly, '123' reMatch: '\d*' collect: [:m| m match] answers OrderedCollection ('123' ) and not OrderedCollection ('123' '') However, this last caveat does not apply to substitutions, so '123' reMatch: '\d*' sub: [:m| '<', m match, '>'] answers '<123><>' "! ]style[(21 3 18 12 1 2 9 460 1 243 7 154 1 290 7 10 25 487 31 1138 1 1)f1b,f1,bf3,bf2,bf3,bf2,f1LRePattern Comment;,f1,f1u,f1,f1LReMatch Comment;,f1,f1u,f1,f1LReMatch Comment;,f1,bf2,f1,bf2,f1,bf2,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/3/2002 23:01'! aLicenseComment " RePlugin is Open Source Software As noted earlier, the non-Smalltalk code on which these classes are based is Philip Hazel's excellent PCRE Package, which is distributed subject to the following license. The Smalltalk wrapper and plugin interface is written by Andrew C. Greenberg and other contributors, and is distributed subject to the same terms. PCRE LICENCE ------------ PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by: Philip Hazel University of Cambridge Computing Service, Cambridge, England. Phone: +44 1223 334714. Copyright (c) 1997-1999 University of Cambridge Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. "! ]style[(16 3 32 340 12 1127)f1b,f1,bf3,f1,bf2,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/3/2002 23:01'! aRegexComment " Regular Expressions A more detailed description of RePlugin is available downloading the file 'RePluginDoco,' which can be obtained from http://www.gate.net/~werdna/RePlugin.html, into your default directory, and then executing Utilities reconstructTextWindowsFromFileNamed: 'RePluginDoco' Basic MetaCharacters The regular expressions recognized in this package generally track those of Perl 5.05, and are set forth in greater detail in the PCRE documentation accompanying the package. A summary follows: \ General escape character with several uses ^ Assert start of subjct (or line, in multiline mode) Also used to negate class definitions $ Assert end of subject (or line, in multiline mode) . match any character but newline (by default) [] class definitions | start of alternative branch () subpattern ? extends the meaning of '(' (see below) quantifies previous extension (1 or 0 occurrences) (e.g. a?) minimizes previous quantifier (e.g. a*?) * 0 or more quantifier + 1 or more quantifier {} Min/Max Quantifier {3} {3,} {3,5} Inside Character Classes \ general escape character ^ negates the class, if the first character - indicates character range, if not escaped or the last character Special Escape Sequences \a alarm (hex 7) \cx control-x, where x is any character \e escape (hex 1b) \f formfeed (hex 0c) \n newline \r carriage return \t tab \xhh Character with hexcode hh \ddd Character with octal code ddd, or a backreference \d matches decimal digit \D non-decimal digit \s whitespace \S non-whitespace \w any 'word' character \W any non-word character \b asserts a word boundary \B asserts not a non-word boundary \A asserts start of subject (regardless of mode) \Z asserts end of subject (regardless of mode) Internal Option Setting Letters enclosed within a pattern and appearing between '(?' and ')' can be used to change the imsx options. For example. (?im-sx) sets caseless and multiline modes, and unsets dotall and extended modes. See the PCRE documentation for further details. Non-Grouping Subpatterns Groupings can be enclosed by parentheses without text being captured by following the leading parenthesis with a question mark and colon. for example: 'abc(?:def)*' repeats the 'def', but does not capture matches in a grouping. Assertions An assertion is a test on characters that does not actually consume any characters. There are two kinds, those that look ahead of the current position, and those that look behind. Consider the following example: \w+(?=;) which matches a word followed by a semicolon, but doesn't include the semicolon in the match. Another example: (?\d+)bar Once only subpatterns 'lock up' after finding a match, to prevent backtracking in various cases. Essentially, a subpattern ofthis type matches the string that an identical standalone pattern would match if anchored at the current point in the subject string first encountering the expression. Conditional Subpatterns (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) These permit one of two subpatterns to be matched, depending upon a preceding condition. There are two kinds of conditions: (1) a sequence of digits, specifying that a numbered subpattern has been matched; and (2) an assertion, either positive, negative, lookahead or lookbehind. Comments (?# This is a comment) Also, in extended mode, comments may be inserted between a '#' and a newline. "! ]style[(17 21 117 41 53 61 2 1 20 1 1 194 2 547 28 139 29 528 26 255 27 230 13 353 1 170 38 293 94 280 36 78 3)f1b,bf3,f1,f1Rhttp://www.gate.net/~werdna/RePlugin.html;,f1,f1dUtilities reconstructTextWindowsFromFileNamed: 'RePluginDoco';;,f1,bf3,bf2,bf3,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b! ! !Re methodsFor: 'documentation' stamp: 'acg 8/4/2002 11:13'! aRegexGoryDetailsComment " Regular Expression Syntax -- the Gory Details Introduction RePlugin is a Squeak Plugin providing modern regular expression matching operations similar to those found in Perl. It was written by Andrew C. Greenberg (werdna@gate.net), with contributions by Markus Kohler, Stephen Pair and others. RePlugin 2.3b (and 'the Gory Details' portion of this document) is directly taken from Version 2.04 of the excellent PCRE library by Philip Hazel with only minor modifications. The syntax and semantics of the regular expressions supported by PCRE are described below. Regular expressions are also described in the Perl documentation and in a number of other books, some of which have copious examples. Jeffrey Friedl's 'Mastering Regular Expressions', published by O'Reilly (ISBN 1-56592-257-3), covers them in great detail. The description here is intended as reference documentation. Regular Expressions A regular expression is a pattern that is matched against a subject string from left to right. Most characters stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern The quick brown fox matches a portion of a subject string that is identical to itself. The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of meta-characters, which do not stand for themselves but instead are interpreted in some special way. There are two different sets of meta-characters: those that are recognized anywhere in the pattern except within square brackets, and those that are recognized in square brackets. Outside square brackets, the meta-characters are as follows: \ general escape character with several uses ^ assert start of subject (or line, in multiline mode) $ assert end of subject (or line, in multiline mode) . match any character except newline (by default) [ start character class definition | start of alternative branch ( start subpattern ) end subpattern ? extends the meaning of ( also 0 or 1 quantifier also quantifier minimizer * 0 or more quantifier + 1 or more quantifier { start min/max quantifier Part of a pattern that is in square brackets is called a 'character class'. In a character class the only meta-characters are: \ general escape character ^ negate the class, but only if the first character - indicates character range ] terminates the character class The following sections describe the use of each of the meta-characters. BACKSLASH The backslash character has several uses. Firstly, if it is followed by a non-alphameric character, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes. For example, if you want to match a '*' character, you write '\*' in the pattern. This applies whether or not the following character would otherwise be interpreted as a meta-character, so it is always safe to precede a non-alphameric with '\' to specify that it stands for itself. In particular, if you want to match a backslash, you write '\\'. If a pattern is compiled with the 'x' (beExtended) option, whitespace in the pattern (other than in a character class) and characters between a '#' outside a character class and the next newline character are ignored. An escaping backslash can be used to include a whitespace or '#' character as part of the pattern. A second use of backslash provides a way of encoding non-printing characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters, apart from the binary zero that terminates a pattern, but when a pattern is being prepared by text editing, it is usually easier to use one of the following escape sequences than the binary character it represents: \a alarm, that is, the BEL character (hex 07) \cx 'control-x', where x is any character \e escape (hex 1B) \f formfeed (hex 0C) \n newline (hex 0A) \r carriage return (hex 0D) \t tab (hex 09) \xhh character with hex code hh \ddd character with octal code ddd, or backreference The precise effect of '\cx' is as follows: if 'x' is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus '\cz' becomes hex 1A, but '\c{' becomes hex 3B, while '\c;' becomes hex 7B. After '\x', up to two hexadecimal digits are read (letters can be in upper or lower case). After '\0' up to two further octal digits are read. In both cases, if there are fewer than two digits, just those that are present are used. Thus the sequence '\0\x\07' specifies two binary zeros followed by a BEL character. Make sure you supply two digits after the initial zero if the character that follows is itself an octal digit. The handling of a backslash followed by a digit other than 0 is complicated. Outside a character class, PCRE reads it and any following digits as a decimal number. If the number is less than 10, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a back reference. A description of how this works is given later, following the discussion of parenthesized subpatterns. Inside a character class, or if the decimal number is greater than 9 and there have not been that many capturing subpatterns, PCRE re-reads up to three octal digits following the backslash, and generates a single byte from the least significant 8 bits of the value. Any subsequent digits stand for themselves. For example: \040 is another way of writing a space \40 is the same, provided there are fewer than 40 previous capturing subpatterns \7 is always a back reference \11 might be a back reference, or another way of writing a tab \011 is always a tab \0113 is a tab followed by the character '3' \113 is the character with octal code 113 (since there can be no more than 99 back references) \377 is a byte consisting entirely of 1 bits \81 is either a back reference, or a binary zero followed by the two characters '8' and '1' Note that octal values of 100 or greater must not be introduced by a leading zero, because no more than three octal digits are ever read. All the sequences that define a single byte value can be used both inside and outside character classes. In addition, inside a character class, the sequence '\b' is interpreted as the backspace character (hex 08). Outside a character class it has a different meaning (see below). The third use of backslash is for specifying generic character types: \d any decimal digit \D any character that is not a decimal digit \s any whitespace character \S any character that is not a whitespace character \w any 'word' character \W any 'non-word' character Each pair of escape sequences partitions the complete set of characters into two disjoint sets. Any given character matches one, and only one, of each pair. A 'word' character is any letter or digit or the underscore character, that is, any character which can be part of a Perl 'word'. The definition of letters and digits is controlled by PCRE's character tables, and may vary if locale- specific matching is taking place (see 'Locale support' above). For example, in the 'fr' (French) locale, some character codes greater than 128 are used for accented letters, and these are matched by \w. These character type sequences can appear both inside and outside character classes. They each match one character of the appropriate type. If the current matching point is at the end of the subject string, all of them fail, since there is no character to match. The fourth use of backslash is for certain simple assertions. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The backslashed assertions are \b word boundary \B not a word boundary \A start of subject (independent of multiline mode) \Z end of subject or newline at end (independent of multiline mode) \z end of subject (independent of multiline mode) These assertions may not appear in character classes (but note that '\b' has a different meaning, namely the backspace character, inside a character class). A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively. The \A, \Z, and \z assertions differ from the traditional circumflex and dollar (described below) in that they only ever match at the very start and end of the subject string, whatever options are set. They are not affected by the 'B' (beNotBeginningOfLine) or 'Z' (beNotEndOfLine) options. The difference between \Z and \z is that \Z matches before a newline that is the last character of the string as well as at the end of the string, whereas \z matches only at the end. CIRCUMFLEX AND DOLLAR Outside a character class, in the default matching mode, the circumflex character is an assertion which is true only if the current matching point is at the start of the subject string. Inside a character class, circumflex has an entirely different meaning (see below). Circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives start with a circumflex, that is, if the pattern is constrained to match only at the start of the subject, it is said to be an 'anchored' pattern. (There are also other constructs that can cause a pattern to be anchored.) A dollar character is an assertion which is true only if the current matching point is at the end of the subject string, or immediately before a newline character that is the last character in the string (by default). Dollar need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. Dollar has no special meaning in a character class. The meaning of dollar can be changed so that it matches only at the very end of the string, by setting the 'E' ('beDollarEndOnly') option at compile or matching time. This does not affect the \Z assertion. The meanings of the circumflex and dollar characters are changed if the 'm' (beMultiline) option is set. When this is the case, they match immediately after and immediately before an internal '\n' character, respectively, in addition to matching at the start and end of the subject string. For example, the pattern /^abc$/ matches the subject string 'def\nabc' in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with '^' are not anchored in multiline mode. The 'E' (beExtended) option is ignored if 's' is set. Note that the sequences \A, \Z, and \z can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with \A is it always anchored, whether 's' (beDotIncludesNewline) is set or not. PERIOD, DOT Outside a character class, a dot in the pattern matches any one character in the subject, including a non-printing character, but not (by default) newline. If the 's' (beDotIncludesNewline) option is set, then dots match newlines as well. The handling of dot is entirely independent of the handling of circumflex and dollar, the only relationship being that they both involve newline characters. Dot has no special meaning in a character class. SQUARE BRACKETS An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not special. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash. A character class matches a single character in the subject; the character must be in the set of characters defined by the class, unless the first character in the class is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the characters which are in the class by enumerating those that are not. It is not an assertion: it still consumes a character from the subject string, and fails if the current pointer is at the end of the string. When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless [aeiou] matches 'A' as well as 'a', and a caseless [^aeiou] does not match 'A', whereas a caseful version would. The newline character is never treated in any special way in character classes, whatever the setting of the 's' (beDotIncludesNewline) or 'm' (beMultiline) options is. A class such as [^a] will always match a newline. The minus (hyphen) character can be used to specify a range of characters in a character class. For example, [d-m] matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class. It is not possible to have the literal character ']' as the end character of a range. A pattern such as [W-]46] is interpreted as a class of two characters ('W' and '-') followed by a literal string '46]', so it would match 'W46]' or '-46]'. However, if the ']' is escaped with a backslash it is interpreted as the end of range, so [W-\]46] is interpreted as a single class containing a range followed by two separate characters. The octal or hexadecimal representation of ']' can also be used to end a range. Ranges operate in ASCII collating sequence. They can also be used for characters specified numerically, for example [\000-\037]. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent to [][\^_`wxyzabc], matched caselessly, and if character tables for the 'fr' locale are in use, [\xc8-\xcb] matches accented E characters in both cases. The character types \d, \D, \s, \S, \w, and \W may also appear in a character class, and add the characters that they match to the class. For example, [\dABCDEF] matches any hexadecimal digit. A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class [^\W_] matches any letter or digit, but not underscore. All non-alphameric characters other than \, -, ^ (at the start) and the terminating ] are non-special in character classes, but it does no harm if they are escaped. VERTICAL BAR Vertical bar characters are used to separate alternative patterns. For example, the pattern gilbert|sullivan matches either 'gilbert' or 'sullivan'. Any number of alternatives may appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. If the alternatives are within a subpattern (defined below), 'succeeds' means matching the rest of the main pattern as well as the alternative in the subpattern. INTERNAL OPTION SETTING The settings of caseless, multiline, dotall and extended options can be changed from within the pattern by a sequence of Perl option letters enclosed between '(?' and ')'. The option letters are i for Caseless Matching Mode m for Multiline Mode s for Dotall Mode (Dot matches newlines) x for Extended Mode (whitespace not meaningful, comments permitted) For example, (?im) sets caseless, multiline matching. It is also possible to unset these options by preceding the letter with a hyphen, and a combined setting and unsetting such as (?im-sx), which sets caseless and multiline while unsetting dotall and extended, is also permitted. If a letter appears both before and after the hyphen, the option is unset. The scope of these option changes depends on where in the pattern the setting occurs. For settings that are outside any subpattern (defined below), the effect is the same as if the options were set or unset at the start of matching. The following patterns all behave in exactly the same way: (?i)abc a(?i)bc ab(?i)c abc(?i) which in turn is the same as compiling the pattern abc with 'i' set. In other words, such 'top level' settings apply to the whole pattern (unless there are other changes inside subpatterns). If there is more than one setting of the same option at top level, the rightmost setting is used. If an option change occurs inside a subpattern, the effect is different. This is a change of behaviour in Perl 5.005. An option change inside a subpattern affects only that part of the subpattern that follows it, so (a(?i)b)c matches abc and aBc and no other strings (assuming 'i' is not used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example, (a(?i)b|c) matches 'ab', 'aB', 'c', and 'C', even though when matching 'C' the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. The PCRE-specific options 'U' and 'X' can be changed in the same way as the Perl-compatible options. The (?X) flag setting is special in that it must always occur earlier in the pattern than any of the additional features it turns on, even when it is at top level. It is best put at the start. SUBPATTERNS Subpatterns are delimited by parentheses (round brackets), which can be nested. Marking part of a pattern as a subpattern does two things: 1. It localizes a set of alternatives. For example, the pattern cat(aract|erpillar|) matches one of the words 'cat', 'cataract', or 'caterpillar'. Without the parentheses, it would match 'cataract', 'erpillar' or the empty string. 2. It sets up the subpattern as a capturing subpattern (as defined above). When the whole pattern matches, that portion of the subject string that matchedOpening parentheses are counted from left to right (starting from 1) to obtain the numbers of the capturing subpatterns. For example, if the string 'the red king' is matched against the pattern the ((red|white) (king|queen)) the captured substrings are 'red king', 'red', and 'king', and are numbered 1, 2, and 3. The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by '?:', the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string 'the white queen' is matched against the pattern the ((?:red|white) (king|queen)) the captured substrings are 'white queen' and 'queen', and are numbered 1 and 2. The maximum number of captured substrings is 99, and the maximum number of all subpatterns, both capturing and non-capturing, is 200. As a convenient shorthand, if any option settings are required at the start of a non-capturing subpattern, the option letters may appear between the '?' and the ':'. Thus the two patterns (?i:saturday|sunday) (?:(?i)saturday|sunday) match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match 'SUNDAY' as well as 'Saturday'. REPETITION Repetition is specified by quantifiers, which can follow any of the following items: a single character, possibly escaped the . metacharacter a character class a back reference (see next section) a parenthesized subpattern (unless it is an assertion - see below) The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: z{2,4} matches 'zz', 'zzz', or 'zzzz'. A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus [aeiou]{3,} matches at least 3 successive vowels, but may match many more, while \d{8} matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, {,6} is not a quantifier, but a literal string of four characters. The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. For convenience (and historical compatibility) the three most common quantifiers have single-character abbreviations: * is equivalent to {0,} + is equivalent to {1,} ? is equivalent to {0,1} It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: (a?)* Earlier versions of Perl and PCRE used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken. By default, the quantifiers are 'greedy', that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between the sequences /* and */ and within the sequence, individual * and / characters may appear. An attempt to match C comments by applying the pattern /\*.*\*/ to the string /* first command */ not comment /* second comment */ fails, because it matches the entire string due to the greediness of the .* item. However, if a quantifier is followed by a question mark, then it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. If the 'U' option is set (an option which is not available in Perl) then the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more store is required for the compiled pattern, in proportion to the size of the minimum or maximum. If a pattern starts with .* then it is implicitly anchored, since whatever follows will be tried against every character position in the subject string. PCRE treats this as though it were preceded by \A. When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after (tweedle[dume]{3}\s*)+ has matched 'tweedledum tweedledee' the value of the captured substring is 'tweedledee'. However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after /(a|(b))+/ matches 'aba' the value of the second captured substring is 'b'. BACK REFERENCES Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (i.e. to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. See the section entitled 'Backslash' above for further details of the handling of digits following a backslash. A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself. So the pattern (sens|respons)e and \1ibility matches 'sense and sensibility' and 'response and responsibility', but not 'sense and responsibility'. If caseful matching is in force at the time of the back reference, then the case of letters is relevant. For example, ((?i)rah)\s+\1 matches 'rah rah' and 'RAH RAH', but not 'RAH rah', even though the original capturing subpattern is matched caselessly. There may be more than one back reference to the same subpattern. If a subpattern has not actually been used in a particular match, then any back references to it always fail. For example, the pattern (a|(bc))\2 always fails if it starts to match 'a' rather than 'bc'. Because there may be up to 99 back references, all digits following the backslash are taken as part of a potential back reference number. If the pattern continues with a digit character, then some delimiter must be used to terminate the back reference. If the 'x' (beExteded) option is set, this can be whitespace. Otherwise an empty comment can be used. A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\1) never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern (a|b\1)+ matches any number of 'a's and also 'aba', 'ababaa' etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. ASSERTIONS An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \b, \B, \A, \Z, \z, ^ and $ are described above. More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. Lookahead assertions start with (?= for positive assertions and (?!! for negative assertions. For example, \w+(?=;) matches a word followed by a semicolon, but does not include the semicolon in the match, and foo(?!!bar) matches any occurrence of 'foo' that is not followed by 'bar'. Note that the apparently similar pattern (?!!foo)bar does not find an occurrence of 'bar' that is preceded by something other than 'foo'; it finds any occurrence of 'bar' whatsoever, because the assertion (?!!foo) is always true when the next three characters are 'bar'. A lookbehind assertion is needed to achieve this effect. Lookbehind assertions start with (?<= for positive assertions and (?<!! for negative assertions. For example, (? as in this example: (?>\d+)bar This kind of parenthesis 'locks up' the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. An alternative description is that a subpattern of this type matches the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string. Once-only subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \d+ and \d+? are prepared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits. This construction can of course contain arbitrarily complicated subpatterns, and it can be nested. Once-only subpatterns can be used in conjunction with lookbehind assertions to specify efficient matching at the end of the subject string. Consider a simple pattern such as abcd$ when applied to a long string which does not match it. Because matching proceeds from left to right, PCRE will look for each 'a' in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as .*abcd$ then the initial .* matches the entire string at first, but when this fails, it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for 'a' covers the entire string, from right to left, so we are no better off. However, if the pattern is written as (?>.*)(?=abcd) then there can be no backtracking for the .* item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time. CONDITIONAL SUBPATTERNS It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a previous capturing subpattern matched or not. The two possible forms of conditional subpattern are (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs. There are two kinds of condition. If the text between the parentheses consists of a sequence of digits, then the condition is satisfied if the capturing subpattern of that number has previously matched. Consider the following pattern, which contains non-significant white space to make it more readable (assume the 'x' (beExtended) option) and to divide it into three parts for ease of discussion: ( \( )? [^()]+ (?(1) \) ) The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether the first set of parentheses matched or not. If they did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses. If the condition is not a sequence of digits, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: (?(?=[^a-z]*[a-z]) \d{2}[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits. COMMENTS The sequence (?# marks the start of a comment which continues up to the next closing parenthesis. Nested parentheses are not permitted. The characters that make up a comment play no part in the pattern matching at all. If the 'x' (beExtended) option is set, an unescaped # character outside a character class introduces a comment that continues up to the next newline character in the pattern."! ]style[(24 4 45 2 12 827 19 1761 9 6751 21 2205 11 450 15 3555 12 541 23 2425 11 2069 10 4396 15 2588 10 3372 21 3022 23 2413 8 398)f1b,f1,f3b,f1,f2b,f1,f2b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1,f1b,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/3/2002 23:04'! aVersionsComment " RePlugin Change History and Compatibility Version 3.2 -- Make compatible with Squeak version 3.X Further revisions to front end. Many bug fixes. Version 2.3b -- Substantially revise String convenience functions to serve as primary user interface to RePlugin. Implement pattern compile caching. Implement pattern match default caching. Order of magnitude performance improvement in global substitution routines. Implement modern Perl5 semantics for global matching and replacement. Minor bug fixes. Permit use of compiled patterns as reMatch: parameter. Plugin code changed so that semantics for '\n' and '\r' are hard-coded across all plugins to conform to Squeak standards regardless of variations in local hardware c libraries. Plugin code memory management scheme modified to permit compilation on most non-Macintosh systems. Plugin code changed to automatically incorporate RePlugin class comment in the generated plugin header. Release Wintel Plugin Release HP-UX Plugin Version 2.3a -- Release MacPPC Plugin. Limitations There are some size limitations in PCRE but it is hoped that they will never in practice be relevant. maximum length of a compiled pattern is 65539 (sic) bytes. All values in repeating quantifiers must be less than 65536. The maximum number of capturing subpatterns is 99. The maximum number of all parenthesized subpatterns, including capturing subpatterns, assertions, and other types of subpattern, is 200. The maximum length of a subject string is the largest positive number that an integer variable can hold. However, PCRE uses recursion to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of a subject string that can be processed by certain patterns. Differences From Perl The differences described here are with respect to Perl 5.005. 1. By default, a whitespace character is any character that the C library function isspace() recognizes, though it is possible to compile PCRE with alternative character type tables. Normally \fBisspace()\fR matches space, formfeed, newline, carriage return, horizontal tab, and vertical tab. Perl 5 no longer includes vertical tab in its set of whitespace characters. The \v escape that was in the Perl documentation for a long time was never in fact recognized. However, the character itself was treated as whitespace at least up to 5.002. In 5.004 and 5.005 it does not match \s. 2. PCRE does not allow repeat quantifiers on lookahead assertions. Perl permits them, but they do not mean what you might think. For example, (?!!a){3} does not assert that the next three characters are not 'a'. It just asserts that the next character is not 'a' three times. 3. Capturing subpatterns that occur inside negative lookahead assertions are counted, but their entries in the offsets vector are never set. Perl sets its numerical variables from any such patterns that are matched before the assertion fails to match something (thereby succeeding), but only if the negative lookahead assertion contains just one branch. 4. Though binary zero characters are supported in the subject string, they are not allowed in a pattern string because it is passed as a normal C string, terminated by zero. The escape sequence '\0' can be used in the pattern to represent a binary zero. 5. The following Perl escape sequences are not supported: \l, \u, \L, \U, \E, \Q. In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. 6. The Perl \G assertion is not supported as it is not relevant to single pattern matches. 7. Fairly obviously, PCRE does not support the (?{code}) construction. 8. There are at the time of writing some oddities in Perl 5.005_02 concerned with the settings of captured strings when part of a pattern is repeated. For example, matching 'aba' against the pattern /^(a(b)?)+$/ sets $2 to the value 'b', but matching 'aabbaa' against /^(aa(bb)?)+$/ leaves $2 unset. However, if the pattern is changed to /^(aa(b(b))?)+$/ then $2 (and $3) get set. In Perl 5.004 $2 is set in both cases, and that is also true of PCRE. If in the future Perl changes to a consistent state that is different, PCRE may change to follow. 9. Another as yet unresolved discrepancy is that in Perl 5.005_02 the pattern /^(a)?(?(1)a|b)+$/ matches the string 'a', whereas in PCRE it does not. However, in both Perl and PCRE /^(a)?a/ matched against 'a' leaves $1 unset. 10. PCRE provides some extensions to the Perl regular expression facilities: (a) Although lookbehind assertions must match fixed length strings, each alternative branch of a lookbehind assertion can match a different length of string. Perl 5.005 requires them all to have the same length. (b) If 'E' is set and 's' is not set, the $ meta- character matches only at the very end of the string. (c) If 'X' is set, a backslash followed by a letter with no special meaning is faulted. (d) If 'U' is set, the greediness of the repetition quantifiers is inverted, that is, by default they are not greedy, but if followed by a question mark they are. "! ]style[(16 4 41 4 14 91 15 828 12 30 11 727 21 3340)f1b,f1,bf3,f1,f2b,f1,f2b,f1,f2b,f1,f2b,f1,bf3,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/4/2002 12:56'! anOptionsComment " Compilation and Matching Options Message Name Code Explanation beCaseSensitive -i Case sensitive matching beNotCaseSensitive i Ignore case during matching beNotMultiline -m Anchor chars don't match line ending beMultiline m Anchor chars match on line ending beNotDotIncludesNewline -s '.' does not match line ending beDotIncludesNewline s '.' matches line endings beNotExtended -x extended mode off (see below) beExtended x extended mode on (see below) beNotDollarEndOnly -E $ matches \n before end of line beDollarEndOnly E $ does not match \n before end of line beGreedy -U quantifiers have ordinary meaning beNotGreedy U reverses meaning of * and :*, also + and :+ beNotExtra -X PCRE Extra mode off (see below) beExtra X PCRE Extra mode on (see below) beNotAnchored -A Matches may begin anywhere beAnchored A Matches must start with first character beBeginningOfLine -B subject starts at beginning of a line beNotBeginningOfLine B subject start not at beginning of a line beEndOfLine -Z subject end may be at end of line beNotEndOfLine Z subject end may not be at end of a line In extended mode (beExtended), whitespace are ignored unless escaped, and # precedes comment to next newline. PCRE Extra mode is described in detail in the accompanying documention. Options may be changed at any time, but a pattern recompile occurs after changing the value any option other than anchored (A), beginning of line (B) or end of line (Z). Options may be specified using messages or by Perl-style option codes: 'a.*y' asRe beNotCaseSensitive; beDotIncludesNewline; search: 'CANDY IS ', Character cr asString, 'DANDY, BUT LIQUOR IS QUICKER' 'a.*y' asRe opt: 'is'; search: 'CANDY IS ', Character cr asString, 'DANDY, BUT LIQUOR IS QUICKER' "! ]style[(17 1 1 1 33 1 33 15 82 14 96 23 85 13 83 18 98 8 104 14 36 1 47 17 87 20 106 15 761)f1b,f1,f1b,f1,bf3,bf1,bf2u,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1,bf1,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/4/2002 13:35'! anReComment " Re -- The RePlugin Pattern Matching Engine I. Introduction RePlugin is a Squeak Plugin providing modern regular expression matching operations similar to those found in Perl. It was written by Andrew C. Greenberg (werdna@gate.net), with contributions by Markus Kohler, Stephen Pair and others. RePlugin 3.2 (and 'the Gory Details' portion of this document) is directly taken from Version 2.04 of the excellent PCRE library by Philip Hazel with only minor modifications. A table of Re public methods and String convenience methods is available in Re anReMethodsComment. II. Creating a Pattern Matching Engine Object A pattern matcher for a pattern string may be created as follows: Re on: '\w+' or by using the convenient String conversion method: '\w+' asRe III. Using the Pattern Matching Engine Object A. Simple Searching. A number of methods are provided for evaluating a target string with an engine. To search a string: '\w+' asRe search: 'this will select the first word from me'. which will return nil if not matched, or a ReMatch object corresponding to the match result information. A substring can be searched with the following message: '\w+' asRe search: 'this will select the second word' from: 5 to: 10 B. Global Searching. Methods are provided for collecting non-overlapping matches in a string. '\w+' asRe searchAndCollect: 'this will give a collection of my words' or for doing a global search with more complex matching '\w+' asRe search: 'makes a list of words in brackets' andCollect: [:m | '<', m match, '>'] C. Global Replacement. Methods are provided to globally search and substitute into a string. '\w+' asRe search: 'makes a string with words in brackets' andReplace: [:m | '<', m match, '>'] There is a special case in the instance where the empty string is matched, because the 'next' match would begin in the same place, thereby creating an infinite loop. This case is handled as in Perl 5.004, where an empty string is replaced with the result of calling the block, and the next search begins after 'bumping' the string to the next character. Accordingly, 'Thanks Markus and Steve for all your help' reMatch: 'x*' andReplace: [:m | '!!' ]. will answer: '!!T!!h!!a!!n!!k!!s!! !!M!!a!!r!!k!!u!!s!! !!a!!n!!d!! !!S!!t!!e!!v!!e!! !!f!!o!!r!! !!a!!l!!l!! !!y!!o!!u!!r!! !!h!!e!!l!!p!!' IV. Search Engine Options The pattern matching engine can be modified to match in a variety of different ways. Re anOptionsComment describes those options in greater detail. Options may be set or reset using #be... and #beNot... messages. 'a.*y' asRe beNotCaseSensitive; beDotIncludesNewline; search: 'CANDY IS ', Character cr asString, 'DANDY, BUT LIQUOR IS QUICKER' or by using Perl-style option characters 'a.*y' asRe opt: 'is'; search: 'CANDY IS ', Character cr asString, 'DANDY, BUT LIQUOR IS QUICKER' "! ]style[(11 4 42 2 15 490 22 2 47 149 48 19 413 22 304 25 732 26 1 86 19 402)f1b,f1,f3b,f1,bf2,f1,f1LRe anReMethodsComment;,f1,f2b,f1,bf2,bf1,f1,f1b,f1,f1b,f1,bf2,f2b,f1,f1LRe anOptionsComment;,f1! ! !Re methodsFor: 'documentation' stamp: 'acg 8/4/2002 11:35'! anReOverviewComment " RePlugin -- A Regular Expressions Plugin for Squeak Introduction RePlugin is a Squeak Plugin providing modern regular expression matching operations similar to those found in Perl. It was written by Andrew C. Greenberg (werdna@gate.net), with contributions by Markus Kohler, Stephen Pair and others. RePlugin 3.2 (and 'the Gory Details' portion of this document) is directly taken from Version 2.04 of the excellent PCRE library by Philip Hazel with only minor modifications. RePlugin, an Overview While the primary functionality (and documentation) for RePlugin is found in new classes RePattern and ReMatch and the operations set forth therein, a comprehensive set of convenience functions are provided in the String class for ease of use. A Simple Example to Get You Started After installing RePlugin, you can execute the following in a workspace: 'Candy is dandy, but liquor is quicker.' reMatch: 'a.*y' This reMatch: message directs RePlugin to search the longer string for the leftmost occurrence of the letter 'a', followed by the longest string that can be collected thereafter comprising any characters, but ending in a 'y.' The message answers: a ReMatch('andy is dandy') (*blush*) which is an object of type ReMatch. As you shall see later, ReMatch objects can be saved to obtain a wide range of information about the match result. When printed, as here, it conveniently identifies the substring that was actually matched, which can also be obtained from the ReMatch instance by sending it the message match. (Note that the longer string 'andy is dandy' was matched, and not the shorter 'andy'.) If there was no match of the string, for example if the subject string were 'You got 'y', but only after the 'a'' then the message would answer nil. A common use of regular expression matching is simply to determine as a boolean result whether the pattern has been matched (similar to the #match method). Accordingly, a convenience function is provided: ('Candy is dandy, but liquor is quicker.' matchRe: 'a.*y') ifTrue: ['matched'] ifFalse: ['not matched'] Global Searching and Replacing It is sometimes convenient to ask ReMatch to repeatedly search for non-overlapping matches of a regular expression, and to report a collection of information with respect to each of the matches found. For example, the message: 'Stupid is as stupid does.' reMatch: 'stupid' andCollect: [:m | m match ]. This message looks for occurrences of the regular expression 'stupid' in the subject string. Each time a match is found, the corresponding match object is passed to the block associated with the collect: keyword, and the results of those computations are returned in an OrderedCollection. Since the first occurrence begins with a capital, only one match is found. (You could collect all occurrences either by using a character class or the i modifier, for example, using the reMatch:opt:collect: message.) In this case, however, the answer will be: OrderedCollection ('stupid' ) As a somewhat more useful example, 'Stupid is as stupid does.' reMatch: '\w+' andCollect: [:m | m match ]. can be used to collect an ordered collection of all non-whitespace phrases in the string, in this case: OrderedCollection ('Stupid' 'is' 'as' 'stupid' 'does' ) This particular form (collecting matches) is used with such frequency that a convenience function is provided: 'Stupid is as stupid does.' collectRe: '\w+' Sometimes you will want to substitute text for the matched text, which you can accomplish with the reMatch:collect: message and some fancy footwork, or which you can do quite easily, for example, as follows: 'Stupid is as stupid does.' reMatch: 'stupid' opt: 'i' sub: [:m | 'Andy' ]. which answers a string replacing all occurrences of stupid (because of the opt: 'i', the search is done without regard to case) with 'Andy', yielding: 'Andy is as Andy does.' You can also 'capture' text by surrounding regular expression subexpressions with parentheses. For example, consider the following expression: ' line has leading spaces' reMatch: '^\W+(.*)' which answers a ReMatch(' line has leading spaces') This would have little utility, since it merely copies the line of text entirely. But since RePlugin keeps track of which text is 'captured' by which parenthetical group, which is numbered in the order the left parenthesis appears in the string. These group matches can be seperately obtained by sending the resulting match object the message 'matchAt:,' for example: (' line has leading spaces' reMatch: '^\W+(.*)') matchAt: 1 which answers 'line has leading spaces' That is, the line without the leading white space. Indeed, RePlugin remembers these parenthetical captures during the match, so that you can check for double words as follows: 'this line has has a double word' reMatch: '(\w+)\W+\1' which matches a ReMatch('has has') These and other regular expression operations are discussed in substantially greater detail below. Matching With RePlugin The Principal Messages You may call RePlugin in any of the following ways: subjectString reMatch: pattern [from: from] [to: to] [opt: optionString] subjectString reMatch: [opt: optionString] sub: aBlock [num: maxMatches] subjectString reMatch: [opt: optionString] collect: aBlock [num: maxMatches] The keywords in square brackets are optional, in the sense that messages are available with every combination of keywords shown, with and without the optional keywords. The first message performs a single search on the substring of subjectString from from to to, using the modifiers set forth in optionString. If from: is not specified, then 1 is used, if to: is not specified, then subjectString size is used, and if opt: is not specified, then the empty string is used. It should be noted that everywhere a pattern is permitted in these operations, either a string or compiled pattern object (an Re) may be used. If a string is used, then RePlugin will first search to see if the object was recently compiled, and if so, use that object, or if not, compiles the expression and remembers it for later reuse. If a compiled pattern object (an Re) is used, then that compiled object will be used, thereby avoiding recompilations and table lookups. The second message performs repeated searches of subjectString for nonoverlapping matches of pattern, using compile and matching options optionString until no more matches are present or maxMatches have been found. (If maxMatches is less than zero, the number of matches will be limited only by the number of matches in the string.) Then, for each match found, replace the matched substring with the result of applying the corresponding match object to aBlock. If opt: is not specified, then the empty string is used, and if num: is not specified, then the equivalent of -1 is used. There is a special case in the instance where the empty string is matched, because the 'next' match would begin in the same place, thereby creating an infinite loop. This case is handled as in Perl 5.004, where an empty string is replaced with the result of calling the block, and the next search begins after 'bumping' the string to the next character. Accordingly, 'Thanks Markus and Steve for all your help' reMatch: 'x*' sub: [:m | '!!' ]. will answer: '!!T!!h!!a!!n!!k!!s!! !!M!!a!!r!!k!!u!!s!! !!a!!n!!d!! !!S!!t!!e!!v!!e!! !!f!!o!!r!! !!a!!l!!l!! !!y!!o!!u!!r!! !!h!!e!!l!!p!!' Finally, the third message performs repeated searches of subjectString for nonoverlapping matches of pattern, using compile and matching options optionString until no more matches are present or maxMatches have been found. (If maxMatches is less than zero, the number of matches will be limited only by the number of matches in the string.) Then, for each match found, evalute aBlock with the corresponding matchObject, and maintain and then answer an ordered collection of the results in the order they were computed. If opt: is not specified, then the empty string is used, and if num: is not specified, then the equivalent of -1 is used. reMatch:collect: handles empty string in the same manner as reMatch:sub:, with the added proviso that an empty match will not be counted if it immediately follows a non-empty match. Accordingly '123' reMatch: '\d*' collect: [:m | m match] answers OrderedCollection ('123' ) and not 'OrderedCollection ('123' ''),' although '123' reMatch: '\d*' sub: [:m | '<', m match, '>'] will answer '<123><>' These null match rules mirror the semantics of Perl 5's m/.../g and s/.../g operators. Using ReMatch to Obtain Principal Match Information The substring of the substring matched by re is given by: m match The beginning and end of the substring in searchString is given by the messages from and to, respectively, so that the substring matched (the result of m match could be obtained with: m searchString copyFrom: (m from) to: (m to) Using ReMatch to Obtain Captured Groups (and Collections of Captured Groups) The number of substrings capturable by a parenthetical grouping in an re (regardless of the number actually matched to create m) is given by: m numGroups The string captured by parenthetical grouping i, where 1<=i<=(m numGroups) is given by m matchAt: i and this can be generated as follows: m searchString copyFrom: (m fromAt: i) to: (m toAt: i) And an array of size (m numGroups) can be generated from strings and indices accordingly: m matches m froms m tos Efficient Regular Expression Matching RePattern tests for regular expression matching in three stages: 1. Compiles the regular expression into a convenient internal form. 2. Searches an object string or substring for matches. 3. Produces results of queries on a match object. If you intend to repeatedly matching a single regular expression against many different strings, for example each line of a file or element of a collection, then repeating Step 1, the compilation, would be wasteful and inefficient. RePattern avoids recompilation by keeping track of the last dozen or so compiled regular expressions, avoiding the costly process of recompilation. Unfortunately, this adds the (less inefficient) cost of a table lookup with each regular expression match. Accordingly, RePattern permits you to generate and keep 'compiled pattern objects,' for repeated matching against subsequent strings without recompiling or searching the compilation cache. You can create an compiled pattern object with the asRePattern message: '\w+' asRePattern which answers an Re('\w+') and the resulting pattern can be used wherever a pattern string can be used, except that no recompilation or table lookup occurs. The following: re := '\w+' asRePattern myCollection do: [:i| Transcript show: ((i reMatch: re) match); cr] will be substantially faster than myCollection do: [:i| Transcript show: ((i reMatch: '\w+') match); cr] Regular Expression Syntax Summary A regular expression (or regexp) specifies a set of strings that matches it. Regular expressions can be concatenated to form new regular expressions; if A and B are both regular expressions, then AB is also an regular expression. If a string p matches A and another string q matches B, the string pq will match AB. Thus, complex expressions are easily constructed from simpler primitive expressions. Regular expressions can contain both special and ordinary characters. Most ordinary characters, like 'A', 'a', or '0', are the simplest regular expressions; they simply match themselves. You can concatenate ordinary characters, so last matches the string 'last'. Some characters, like '|' or '(', are special. Special characters either stand for classes of ordinary characters, or affect how the regular expressions around them are interpreted. The special characters are: '.' (Dot.) In the default mode, this matches any character except a newline. If the 's' option has been specified, dot matches any character at all, including a newline. '^' (Caret.) Matches the start of the string, and if the 'm' option has been specified, then this also matches immediately after each newline. '$' Matches the end of the string, and if the 'm' option has been specified, then this also matches before a newline. foo matches both 'foo' and 'foobar', while the regular expression foo$ matches only 'foo'. '*' Causes the resulting regexp to match 0 or more repetitions of the preceding regexp, as many repetitions as are possible. ab* will match 'a', 'ab', or 'a' followed by any number of 'b's. '+' Causes the resulting regexp to match 1 or more repetitions of the preceding regexp. ab+ will match 'a' followed by any non-zero number of 'b's; it will not match just 'a'. '?' Causes the resulting regexp to match 0 or 1 repetitions of the preceding regexp. ab? will match either 'a' or 'ab'. *?, +?, ?? The '*', '+', and '?' qualifiers are all greedy; they match as much text as possible. Sometimes this behaviour isn't desired; if the regexp <.*> is matched against '

title

', it will match the entire string, and not just '

'. Adding '?' after the qualifier makes it perform the match in non-greedy or minimal fashion; as few characters as possible will be matched. Using .*? in the previous expression will match only '

'. {m,n} Causes the resulting regexp to match from m to n repetitions of the preceding regexp, attempting to match as many repetitions as possible. For example, a{3,5} will match from 3 to 5 'a' characters. Omitting n specifies an infinite upper bound; you can't omit m. {m,n}? Causes the resulting regexp to match from m to n repetitions of the preceding regexp, attempting to match as few repetitions as possible. This is the non-greedy version of the previous qualifier. For example, on the 6-character string 'aaaaaa', a{3,5} will match 5 'a' characters, while a{3,5}? will only match 3 characters. '\' Either escapes special characters (permitting you to match characters like '*', '?', and so forth), or signals a special sequence; special sequences are discussed below. [] Used to indicate a set of characters. Characters can be listed individually, or a range of characters can be indicated by giving two characters and separating them by a '-'. Special characters are not active inside sets. For example, [akm$] will match any of the characters 'a', 'k', 'm', or '$'; [a-z] will match any lowercase letter, and [a-zA-Z0-9] matches any letter or digit. Character classes such as \w or \S(defined below) are also acceptable inside a range. If you want to include a ']' or a '-' inside a set, precede it with a backslash, or place it as the first character. The pattern []] will match ']', for example. You can match the characters not within a range by complementing the set. This is indicated by including a '^' as the first character of the set; '^' elsewhere will simply match the '^' character. For example, [^5] will match any character except '5'. '|' A|B, where A and B can be arbitrary regexps, creates a regular expression that will match either A or B. This can be used inside groups (see below) as well. To match a literal '|', use \|, or enclose it inside a character class, as in [|]. (...) Matches whatever regular expression is inside the parentheses, and indicates the start and end of a group; the contents of a group can be retrieved after a match has been performed, and can be matched later in the string with the \number special sequence, described below. To match the literals '(' or '')', use \( or \), or enclose them inside a character class: [(] [)]. (?...) This is an extension notation (a '?' following a '(' is not meaningful otherwise). The first character after the '?' determines what the meaning and further syntax of the construct is. Following are the currently supported extensions: (?imsx[-imsx]) (One or more letters from the set 'i', 'm', 's', 'x'.) The group matches the empty string and set (or unset if the letters follow a '-') corresponding options for the regular expression or subexpression in which it is contained. (?:...) A non-grouping version of regular parentheses. Matches whatever regular expression is inside the parentheses, but the substring matched by the group cannot be retrieved after performing a match or referenced later in the pattern. (?#...) A comment; the contents of the parentheses are simply ignored. (?=...) Matches if ... matches next, but doesn't consume any of the string. This is called a lookahead assertion. For example, Isaac (?=Asimov) will match 'Isaac' only if it's followed by 'Asimov'. (?!!...) Matches if ... doesn't match next. This is a negative lookahead assertion. For example, Isaac (?!!Asimov) will match 'Isaac' only if it's not followed by 'Asimov'. (?<=...) Matches if ... matches, but doesn't consume any of the string. This is called a lookbehind assertion. For example, (?<=foo|fooey)bar will match 'bar' only if it's preceded by 'foo' or 'fooey'. All lookbehinds must have some fixed length, although alternatives need not be of the same length, as in the example. (? start) ifTrue: [ result nextPutAll: (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [ result nextPutAll: (aBlock value: m). ^result contents]. result nextPutAll: (aBlock value: m); nextPut: (aString at: start). start _ start + 1] ifFalse: [ result nextPutAll: (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start opt: optString]. (start <= (aString size)) ifTrue: [result nextPutAll: (aString copyFrom: start to: (aString size))]. ^(result contents) ! ! !RePattern methodsFor: 'global searching' stamp: 'acg 3/14/1999 21:51'! search: aString opt: optString sub: aBlock num: limitInteger |start m result numMatchesSoFar | start _ 1. numMatchesSoFar _ 0. ((limitInteger isNil) or: [limitInteger < 0]) ifTrue: [^self gsearch: aString opt: optString]. m _ self search: aString from: start opt: optString. result _ WriteStream on: (String new). [(m isNil) or: [numMatchesSoFar >= limitInteger]] whileFalse: [ numMatchesSoFar _ numMatchesSoFar + 1. ((m from) > start) ifTrue: [ result _ result , (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [ result nextPutAll: (aBlock value: m). ^result contents]. result nextPutAll: (aBlock value: m); nextPut: (aString at: start). start _ start + 1] ifFalse: [ result nextPutAll: (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start opt: optString]. (start <= (aString size)) ifTrue: [result nextPutAll: (aString copyFrom: start to: (aString size))]. ^(result contents)! ! !RePattern methodsFor: 'global searching' stamp: 'acg 3/7/1999 16:28'! search: aString sub: aBlock ^self search: aString opt: '' sub: aBlock! ! !RePattern methodsFor: 'global searching' stamp: 'acg 3/7/1999 16:28'! search: aString sub: aBlock num: limitInteger ^self search: aString opt: '' sub: aBlock num: limitInteger! ! !RePattern methodsFor: 'methods for RE' stamp: 'acg 7/30/2002 11:51'! search: aString from: posInteger to: endposInteger optCode: matchOptionsInteger "Answer nil if I don't match the substring of srchString beginning at posInteger and ending at endposInteger using options specified by optString. Otherwise return an appropriate ReMatch." matchOptions _ matchOptionsInteger. lastMatchResult _ self primPCREExec: aString from: posInteger to: endposInteger. (lastMatchResult < 0) ifTrue: [^nil]. ^ReMatch matchArray: matchSpace forRe: self onString: aString from: posInteger to: endposInteger ! ! !RePattern methodsFor: 'methods for RE' stamp: 'acg 7/30/2002 17:31'! search: aString optCode: anInteger collect: aBlock "Sequentially search aString until no more matches are found. Begin a subsequent search immediately where the preceding search ends, but handle empty matches specially as described below. Answer an OrderedCollection of the result of applying aBlock to each match, or nil if no matches were found. For example: (RePattern on: 'x+') gsearch: 'x xx xxx xxxxx xxxxxx' opt: '' collect: [:m | m match] Answers: OrderedCollection ('x' 'xx' 'xxx' 'xxxxx' 'xxxxxx' ) After an empty string is matched, a subsequent search would attain the same result. Accordingly, we simply bump the search one character in such cases. Additionally, we do not count as a match empty matches which are adjacent to a preceding match." | from to m results lastMatchFrom matchesSoFar | aString ifNil: [^nil]. from _ 1. to _ aString size. lastMatchFrom _ -1. matchesSoFar _ 0. results _ OrderedCollection new. [from <= (to+1)] whileTrue: [ (m _ self search: aString from: from to: to optCode: anInteger) ifNil: [ (0 = results size) ifTrue: [^nil]. ^results] ifNotNil: [ matchesSoFar _ matchesSoFar + 1. from _ (m to) + 1. (0 = m match size) ifTrue: [ "Handle an empty match" from _ from + 1. (lastMatchFrom = m from) ifFalse: [results add:(aBlock value: m)]] ifFalse: [ "Handle a non-empty match" lastMatchFrom _ from. results add:(aBlock value: m)]]]. ^results! ! !RePattern methodsFor: 'methods for RE' stamp: 'acg 7/30/2002 17:33'! search: aString optCode: optInteger collect: aBlock num: limitInteger "Sequentially search aString until no more matches are found, or limitInteger matches are found, whichever occurs first. Begin a subsequent searche immediately where the preceding search ended, but handle empty specially as described below. Answer an OrderedCollection of the result of applying aBlock to each match, or nil if no matches were found. For example: (RePattern on: 'x+') gsearch: 'x xx xxx xxxxx xxxxxx' opt: '' collect: [:m | m match] num: 3 Answers: OrderedCollection ('x' 'xx' 'xxx' ) After an empty string is matched, a subsequent search would attain the same result. Accordingly, we simply bump the search one character in such cases. Additionally, we do not count as a match empty matches which are adjacent to a preceding match." | from to m results lastMatchFrom matchesSoFar | aString ifNil: [^nil]. ((limitInteger isNil) or: [limitInteger < 0]) ifTrue: [^self search: aString optCode: optInteger collect: aBlock]. from _ 1. to _ aString size. lastMatchFrom _ -1. matchesSoFar _ 0. results _ OrderedCollection new. [(from <= (to+1)) and: [matchesSoFar < limitInteger]] whileTrue: [ (m _ self search: aString from: from to: to optCode: optInteger) ifNil: [ (0 = results size) ifTrue: [^nil]. ^results] ifNotNil: [ from _ (m to) + 1. (0 = m match size) ifTrue: [ "Handle an empty match" from _ from + 1. (lastMatchFrom = m from) ifFalse: [ "empty match not adjacent preceding match" matchesSoFar _ matchesSoFar + 1. results add:(aBlock value: m)]] ifFalse: [ "Handle a non-empty match" matchesSoFar _ matchesSoFar + 1. lastMatchFrom _ from. results add:(aBlock value: m)]]]. (0 = results size) ifTrue: [^nil]. ^results! ! !RePattern methodsFor: 'methods for RE' stamp: 'acg 7/30/2002 21:01'! search: aString optCode: anInteger sub: aBlock |start m result | start _ 1. m _ self search: aString from: 1 to: aString size optCode: anInteger. result _ WriteStream on: (String new). [m isNil] whileFalse: [ ((m from) > start) ifTrue: [ result nextPutAll: (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [ result nextPutAll: (aBlock value: m). ^result contents]. result nextPutAll: (aBlock value: m); nextPut: (aString at: start). start _ start + 1] ifFalse: [ result nextPutAll: (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start to: aString size optCode: anInteger]. (start <= (aString size)) ifTrue: [result nextPutAll: (aString copyFrom: start to: (aString size))]. ^(result contents) ! ! !RePattern methodsFor: 'methods for RE' stamp: 'acg 7/30/2002 21:19'! search: aString optCode: anInteger sub: aBlock num: limitInteger |start m result numMatchesSoFar | start _ 1. numMatchesSoFar _ 0. ((limitInteger isNil) or: [limitInteger < 0]) ifTrue: [^self search: aString optCode: anInteger sub: aBlock]. m _ self search: aString from: start to: aString size optCode: anInteger. result _ WriteStream on: (String new). [(m isNil) or: [numMatchesSoFar >= limitInteger]] whileFalse: [ numMatchesSoFar _ numMatchesSoFar + 1. ((m from) > start) ifTrue: [ result nextPutAll: (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [ result nextPutAll: (aBlock value: m). ^result contents]. result nextPutAll: (aBlock value: m); nextPut: (aString at: start). start _ start + 1] ifFalse: [ result nextPutAll: (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start to: aString size optCode: anInteger]. (start <= (aString size)) ifTrue: [result nextPutAll: (aString copyFrom: start to: (aString size))]. ^(result contents)! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 01:00'! PCREANCHORED ^16! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 00:59'! PCRECASELESS ^1 ! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 01:00'! PCREDOLLARENDONLY ^32 ! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 00:59'! PCREDOTALL ^4! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 00:59'! PCREEXTENDED ^8! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/28/1999 04:35'! PCREEXTRA ^64 ! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/24/1999 00:59'! PCREMULTILINE ^2! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/28/1999 04:36'! PCRENOTBOL ^128! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/28/1999 04:36'! PCRENOTEOL ^256! ! !RePattern methodsFor: 'constants' stamp: 'acg 2/28/1999 04:36'! PCREUNGREEDY ^512! ! !RePattern methodsFor: 'primitives' stamp: 'acg 8/11/2002 23:42'! primGetModuleName ^nil! ! !RePattern methodsFor: 'primitives' stamp: 'acg 2/24/1999 23:48'! primPCRECompile ^RePlugin doPrimitive: 'primPCRECompile'! ! !RePattern methodsFor: 'primitives' stamp: 'acg 2/24/1999 23:10'! primPCREExec: aCharBufferObject ^RePlugin doPrimitive: 'primPCREExec' ! ! !RePattern methodsFor: 'primitives' stamp: 'acg 2/26/1999 20:58'! primPCREExec: aCharBufferObject from: fromInteger to: toInteger ^RePlugin doPrimitive: 'primPCREExecfromto' ! ! !RePattern methodsFor: 'primitives' stamp: 'acg 2/25/1999 00:05'! primPCRENumSubPatterns ^RePlugin doPrimitive: 'primPCRENumSubPatterns' ! ! !RePattern methodsFor: 'private' stamp: 'acg 2/28/1999 01:41'! compile: aString "Initialize me so I can match aString using standard options. If the compile fails, display an appropriate notifier and answer nil. Otherwise answer self." ^self compile: aString opt: ''.! ! !RePattern methodsFor: 'private' stamp: 'acg 2/28/1999 01:40'! compile: aString opt: optString "Initialize me so I can match aString using options specified in optString. If the compile fails, display an appropriate notifier and answer nil. Otherwise answer self." ^self compile: aString opt: optString onErrorRun: [:pat :off :err | self error: err. ^nil].! ! !RePattern methodsFor: 'private' stamp: 'acg 7/28/2002 23:27'! compile: aString opt: optString onErrorRun: aBlock "Initialize me so I can match aString using options specified in optString. If the compile of aString fails, send aBlock the following message: aBlock value: aString value: anInteger value: anErrorString where, anInteger is the offset in aString where the error was identified, and anErrorString is a descriptive error message. Answer nil if compiles fails, otherwise self." pattern _ (aString, (Character characterTable at: 1) asString). "Must be Zero-Terminated" compileOptions _ self evalCompileString: optString onErrorRun: aBlock. pcrePointer _ extraPointer _ errorString _ offset _ nil. matchOptions _ 0. (self primPCRECompile) ifNotNil: [aBlock value: pattern value: offset value: errorString]. matchSpace _ IntegerArray new: 3 * ( 1 + (self primPCRENumSubPatterns)). ^ self.! ! !RePattern methodsFor: 'private' stamp: 'acg 7/30/2002 11:52'! compile: aString optCode: anInteger onErrorRun: aBlock "Initialize me so I can match aString using options specified in optString. If the compile of aString fails, send aBlock the following message: aBlock value: aString value: anInteger value: anErrorString where, anInteger is the offset in aString where the error was identified, and anErrorString is a descriptive error message. Answer nil if compiles fails, otherwise self." pattern _ (aString, (Character characterTable at: 1) asString). "Must be Zero-Terminated" compileOptions _ anInteger. pcrePointer _ extraPointer _ errorString _ offset _ nil. matchOptions _ 0. (self primPCRECompile) ifNotNil: [aBlock value: pattern value: offset value: errorString]. matchSpace _ IntegerArray new: 3 * ( 1 + (self primPCRENumSubPatterns)). ^ self.! ! !RePattern methodsFor: 'private' stamp: 'acg 3/12/1999 22:18'! evalCompileString: aString onErrorRun: aBlock "Answer an integer recognized by PCRE, and representing the compile time codes indicated in aString. For details about the codes, see the comments for the corresponding constant function. If aString contains unrecognized options, sent a message to aBlock" |result| result _ 0. aString doWithIndex: [:ch :index| "Traditional Perl Options" (ch == $i) ifTrue: [result _ result bitOr: (self PCRECASELESS)]. (ch == $m) ifTrue: [result _ result bitOr: (self PCREMULTILINE)]. (ch == $s) ifTrue: [result _ result bitOr: (self PCREDOTALL)]. (ch == $x) ifTrue: [result _ result bitOr: (self PCREEXTENDED)]. "PCRE Extensions" (ch == $A) ifTrue: [result _ result bitOr: (self PCREANCHORED)]. (ch == $E) ifTrue: [result _ result bitOr: (self PCREDOLLARENDONLY)]. (ch == $U) ifTrue: [result _ result bitOr: (self PCREUNGREEDY)]. (ch == $X) ifTrue: [result _ result bitOr: (self PCREEXTRA)]. ('imsxABEUXZ' includes: ch) ifFalse: [ aBlock value: aString value: index value: ('Invalid RE Compile Option: ', ch asString)]]. ^result! ! !RePattern methodsFor: 'private' stamp: 'acg 2/28/1999 00:56'! evalMatchString: aString "Answer an integer recognized by PCRE, and representing the match time codes indicated in aString. For details about the codes, see the comments for the corresponding constant function. If aString contains unrecognized options, display a notifier" ^self evalMatchString: aString onErrorRun: [:source :index :message | self error: message]! ! !RePattern methodsFor: 'private' stamp: 'acg 3/12/1999 22:18'! evalMatchString: aString onErrorRun: aBlock "Answer an integer recognized by PCRE, and representing the match time codes indicated in aString. For details about the codes, see the comments for the corresponding constant function. If aString contains unrecognized options, sent a message to aBlock" |result| result _ 0. aString doWithIndex: [:ch :index | (ch == $A) ifTrue: [result _ result bitOr: (self PCREANCHORED)]. (ch == $B) ifTrue: [result _ result bitOr: (self PCRENOTBOL)]. (ch == $Z) ifTrue: [result _ result bitOr: (self PCRENOTEOL)]. ('imsxABEUXZ' includes: ch) ifFalse: [ aBlock value: aString value: index value: ('Invalid RE Match Option: ', ch asString)]]. ^result! ! !RePattern methodsFor: 'private' stamp: 'acg 2/27/1999 22:24'! memoryState "Answer a report of the malloc:/free: engine (for tracking memory leaks)" ^String cr, ((self primNumAllocs) asString), ' Allocations', String cr, ((self primNumFrees) asString), ' Frees', String cr, ((self primNetMemory) asString), ' Net Memory Taken', String cr! ! !RePattern methodsFor: 'private' stamp: 'acg 2/25/1999 08:37'! primLastAlloc ^RePlugin doPrimitive: 'primLastAlloc' ! ! !RePattern methodsFor: 'private' stamp: 'acg 2/21/1999 23:15'! primNetMemory ^RePlugin doPrimitive: 'primNetMemory' ! ! !RePattern methodsFor: 'private' stamp: 'acg 2/21/1999 23:15'! primNumAllocs ^RePlugin doPrimitive: 'primNumAllocs' ! ! !RePattern methodsFor: 'private' stamp: 'acg 2/21/1999 23:15'! primNumFrees ^RePlugin doPrimitive: 'primNumFrees' ! ! !RePattern methodsFor: 'printing' stamp: 'acg 3/7/1999 08:04'! printOn: aStream aStream nextPutAll: 'a '. (self species) printOn: aStream. aStream nextPut: $(. (self pattern) printOn: aStream. aStream nextPut: $).! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/2/1999 07:58'! gsearch: aString ^self gsearch: aString opt: ''.! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/1/1999 08:33'! gsearch: aString collect: aBlock | collection | collection _ self gsearch: aString. ^collection ifNil: [nil] ifNotNil: [collection collect: aBlock] ! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/2/1999 09:47'! gsearch: aString opt: optString "Answer Collection of MatchObjects resulting sequential searches of aString for matches to me, or nil if there are no matches. Do not include empty matches that are adjacent to a previous match." | from to m results lastMatchFrom | aString ifNil: [^nil]. from _ 1. to _ aString size. lastMatchFrom _ -1. results _ OrderedCollection new. [from <= (to+1)] whileTrue: [ (m _ self search: aString from: from to: to opt: optString) ifNil: [ (0 = results size) ifTrue: [^nil]. ^results] ifNotNil: [ from _ (m to) + 1. (0 = m match size) ifTrue: [ from _ from + 1. (lastMatchFrom = m from) ifFalse: [results add:m]] ifFalse: [lastMatchFrom _ from. results add:m]]]. ^results! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/7/1999 15:41'! gsearch: aString opt: optString num: limitInteger "Answer Collection of MatchObjects resulting sequential searches of aString for up to limitInteger matches to me, or nil if there are no matches at all. Do not include empty matches that are adjacent to a previous match." | from to m results lastMatchFrom matchesSoFar | aString ifNil: [^nil]. ((limitInteger isNil) or: [limitInteger < 0]) ifTrue: [^self gsearch: aString opt: optString]. from _ 1. to _ aString size. lastMatchFrom _ -1. matchesSoFar _ 0. results _ OrderedCollection new. [(from <= (to+1)) and: [matchesSoFar < limitInteger]] whileTrue: [ (m _ self search: aString from: from to: to opt: optString) ifNil: [ (0 = results size) ifTrue: [^nil]. ^results] ifNotNil: [ from _ (m to) + 1. (0 = m match size) ifTrue: [ from _ from + 1. (lastMatchFrom = m from) ifFalse: [results add:m]] ifFalse: [lastMatchFrom _ from. results add:m]]]. ^results! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 2/28/1999 05:21'! gsearch: aString sub: aBlock ^self gsearch: aString sub: aBlock opt: ''! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/2/1999 00:55'! gsearch: aString sub: aBlock opt: optString |start m result | start _ 1. m _ self search: aString from: start opt: optString. result _ ''. [m isNil] whileFalse: [ ((m from) > start) ifTrue: [ result _ result , (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [^ result]. result _ result , (aString at: start) asString. start _ start + 1] ifFalse: [ result _ result , (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start opt: optString]. (start <= (aString size)) ifTrue: [result _ result, (aString copyFrom: start)]. ^result ! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 3/7/1999 16:21'! gsearch: aString sub: aBlock opt: optString num: limitInteger |start m result | start _ 1. m _ self search: aString from: start opt: optString. result _ ''. [m isNil] whileFalse: [ ((m from) > start) ifTrue: [ result _ result , (aString copyFrom: start to: ((m from) - 1))]. 0 = m match size ifTrue: [ start > aString size ifTrue: [^ result]. result _ result , (aString at: start) asString. start _ start + 1] ifFalse: [ result _ result , (aBlock value: m). start _ (m to) + 1]. m _ self search: aString from: start opt: optString]. (start <= (aString size)) ifTrue: [result _ result, (aString copyFrom: start)]. ^result ! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 2/27/1999 22:22'! initialize: aString "Initialize me so I can match aString using standard options. If the compile fails, display an appropriate notifier and answer nil. Otherwise answer self." ^self initialize: aString opt: ''.! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 2/27/1999 22:22'! initialize: aString opt: optString "Initialize me so I can match aString using options specified in optString. If the compile fails, display an appropriate notifier and answer nil. Otherwise answer self." ^self initialize: aString opt: optString onErrorRun: [:pat :off :err | self error: err. ^nil].! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 2/27/1999 22:21'! initialize: aString opt: optString onErrorRun: aBlock "Initialize me so I can match aString using options specified in optString. If the compile of aString fails, send aBlock the following message: aBlock value: aString value: anInteger value: anErrorString where, anInteger is the offset in aString where the error was identified, and anErrorString is a descriptive error message. Answer nil if compiles fails, otherwise self." pattern _ (aString, (Character characterTable at: 1) asString). "Must be Zero-Terminated" compileOptions _ self evalCompileString: optString onErrorRun: aBlock. pcrePointer _ extraPointer _ errorString _ offset _ nil. matchOptions _ 0. (self primPCRECompile) ifNotNil: [aBlock value: pattern value: offset value: errorString]. matchSpace _ IntegerArray new: 3 * ( 1 + (self primPCRENumSubPatterns)). ^ self.! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 2/27/1999 00:34'! initializePattern: aPatString ^self initializePattern: aPatString onErrorRun: [:pat :off :err | self error: err. ^nil].! ! !RePattern methodsFor: 'deprecated' stamp: 'acg 7/21/2002 17:26'! initializePattern: aPatString onErrorRun: aBlock |pstr delimiter patStream optionString optionCode | pstr _ ReadStream on: aPatString. "Get and check the delimiter" delimiter _ pstr next. ('!!@#$%^&*()_+-=[]{}|;:''"/?,.<>`~' includes: delimiter) ifFalse: [ self error: ( 'rePattern: improper delimiter ', (delimiter asString), ' in pattern ', aPatString)]. "Get the pattern string, permit delimiter to be escaped with $\" patStream _ ReadWriteStream on: (String new: (aPatString size)). patStream nextPutAll: (pstr upTo: delimiter). [$\ = (pstr last)] whileTrue: [ patStream nextPut: delimiter. patStream nextPutAll:(pstr upTo: delimiter)]. "Get and verify the option string" optionString _ pstr upToEnd. optionCode _ 0. optionString do: [:ch | (ch = 'i') ifTrue: [optionCode _ optionCode bitOr: (self PCRECASELESS)]. (ch = 'm') ifTrue: [optionCode _ optionCode bitOr: (self PCREMULTILINE)]. (ch = 's') ifTrue: [optionCode _ optionCode bitOr: (self PCREDOTALL)]. (ch = 'x') ifTrue: [optionCode _ optionCode bitOr: (self PCREEXTENDED)]. ('imsx' includes: ch) ifFalse: [ self error: ( 'rePattern: improper option ', (ch asString) , ' in pattern ', optionString)].]. ^self initialize: patStream contents opt: optionCode onErrorRun: aBlock.! ! !RePattern class methodsFor: 'instance creation' stamp: 'acg 3/7/1999 08:00'! on: aString "Answer an instance of a compiled re for matching aString under Standard options. If compile fails, display an appropriate notifier." ^self search: aString opt: '' ifAbsentAdd:[self new compile: aString].! ! !RePattern class methodsFor: 'instance creation' stamp: 'acg 3/6/1999 11:43'! on: aString opt: optString "Answer an instance of a compiled re for matching aString under the options specified by optString. If compile fails, display an appropriate notifier." ^ self search: aString opt: optString ifAbsentAdd: [self new compile: aString opt: optString]! ! !RePattern class methodsFor: 'instance creation' stamp: 'acg 3/7/1999 08:00'! on: aString opt: optString onErrorRun: aBlock "Answer an instance of a compiled re for matching aString under the options specified by optString. If compile fails, send aBlock the following message: aBlock value: aString value: anInteger value: anErrorString where, anInteger is the offset in aString where the error was identified, and anErrorString is a descriptive error message. " ^self search: aString opt: optString ifAbsentAdd:[self new compile: aString opt: optString onErrorRun: aBlock]! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 3/6/1999 11:52'! debugReport ^ String cr, 'Front: ', (Front asString), String cr, 'Patterns: ', (Patterns asString), String cr, 'Options: ', (Options asString), String cr, 'CompileObjects: ', (CompileObjects asString), String cr.! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 8/11/2002 14:36'! initialize self initializeCache ! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 3/6/1999 21:18'! initializeCache |size | size _ self queueSize. Patterns _ Array new: size. Options _ Array new: size. CompileObjects _ Array new: size. Front _ size. ! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 3/6/1999 16:52'! primCacheSearch: pStr opt: oStr ^RePlugin doPrimitive: 'primCacheSearch' ! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 3/6/1999 12:11'! queueSize ^10! ! !RePattern class methodsFor: 'pattern caching' stamp: 'acg 3/7/1999 08:03'! search: pStr opt: oStr ifAbsentAdd: aBlock |result | pStr ifNil: [^nil]. Patterns withIndexDo: [:p :i | ((p = pStr) and: [(Options at: i) = oStr]) ifTrue:[^CompileObjects at: i]]. result _ aBlock value. (Front == (self queueSize)) ifTrue: [Front _ 1] ifFalse: [Front _ Front + 1]. Patterns at: Front put: pStr. Options at: Front put: oStr. CompileObjects at: Front put: result. ^result! ! !RePlugin methodsFor: 're primitives' stamp: 'acg 3/12/1999 23:36'! primPCRECompile ", where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Compile the regular expression in patternStr, and if the compilation is successful, attempt to optimize the compiled expression. Store the results in and , or fill errorStr with a meaningful errorString and errorOffset with an indicator where the error was found, applying compileFlags throughout. Answer nil with a clean compile (regardless of whether an optimization is possible, and answer with the string otherwise." self export: true. self loadRcvrFromStackAt: 0. patternStrPtr _ self rcvrPatternStrPtr. compileFlags _ self rcvrCompileFlags. interpreterProxy failed ifTrue:[^ nil]. pcrePtr _ self cCode: '(int) pcre_compile(patternStrPtr, compileFlags, &errorStrBuffer, &errorOffset, NULL)'. pcrePtr ifTrue: [ self allocateByteArrayAndSetRcvrPCREPtrFromPCRE: pcrePtr. extraPtr _ self cCode: '(int) pcre_study((pcre *)pcrePtr, compileFlags, &errorStrBuffer)'. self allocateByteArrayAndSetRcvrExtraPtrFrom: extraPtr. self rePluginFree: (self cCoerce: pcrePtr to: 'void *'). extraPtr ifTrue: [self rePluginFree: (self cCoerce: extraPtr to: 'void *')]. interpreterProxy failed ifTrue:[^ nil]. interpreterProxy pop: 1 thenPush: interpreterProxy nilObject] ifFalse: [ errorStr _ self allocateStringAndSetRcvrErrorStrFromCStr: errorStrBuffer. self rcvrErrorOffsetFrom: errorOffset. interpreterProxy failed ifTrue:[^ nil]. interpreterProxy pop: 1 thenPush: errorStr].! ! !RePlugin methodsFor: 're primitives' stamp: 'acg 2/27/1999 01:08'! primPCREExec ", where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in and , generated from calls to primPCRECompile), to smalltalk String searchObject using . If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match." | searchObject searchBuffer length result matchSpacePtr matchSpaceSize | self export: true. self var:#searchBuffer declareC: 'char *searchBuffer'. self var:#matchSpacePtr declareC: 'int *matchSpacePtr'. self var:#result declareC: 'int result'. "Load Parameters" searchObject _ interpreterProxy stackObjectValue: 0. searchBuffer _ interpreterProxy arrayValueOf: searchObject. length _ interpreterProxy byteSizeOf: searchObject. self loadRcvrFromStackAt: 1. "Load Instance Variables" pcrePtr _ self rcvrPCREBufferPtr. extraPtr _ self rcvrExtraPtr. matchFlags _ self rcvrMatchFlags. matchSpacePtr _ self rcvrMatchSpacePtr. matchSpaceSize _ self rcvrMatchSpaceSize. interpreterProxy failed ifTrue:[^ nil]. result _ self cCode: 'pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, matchFlags, matchSpacePtr, matchSpaceSize)'. interpreterProxy pop: 2; pushInteger: result. "empty call so compiler doesn't bug me about variables not used" self touch: searchBuffer; touch: matchSpacePtr; touch: matchSpaceSize; touch: length ! ! !RePlugin methodsFor: 're primitives' stamp: 'acg 2/26/1999 21:01'! primPCREExecfromto " from: fromInteger to: toInteger>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in and , generated from calls to primPCRECompile), to smalltalk String searchObject using , beginning at offset and continuing until offset . If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match." | searchObject searchBuffer length result matchSpacePtr matchSpaceSize fromInteger toInteger | self export: true. self var:#searchBuffer declareC: 'char *searchBuffer'. self var:#fromInteger declareC: 'int fromInteger'. self var:#toInteger declareC: 'int toInteger'. self var:#matchSpacePtr declareC: 'int *matchSpacePtr'. self var:#result declareC: 'int result'. "Load Parameters" toInteger _ interpreterProxy stackIntegerValue: 0. fromInteger _ interpreterProxy stackIntegerValue: 1. searchObject _ interpreterProxy stackObjectValue: 2. searchBuffer _ interpreterProxy arrayValueOf: searchObject. length _ interpreterProxy byteSizeOf: searchObject. self loadRcvrFromStackAt: 3. "Validate parameters" interpreterProxy success: (1 <= fromInteger). interpreterProxy success: (toInteger<=length). fromInteger _ fromInteger - 1. "Smalltalk offsets are 1-based" interpreterProxy success: (fromInteger<=toInteger). "adjust length, searchBuffer" length _ toInteger - fromInteger. searchBuffer _ searchBuffer + fromInteger. "Load Instance Variables" pcrePtr _ self rcvrPCREBufferPtr. extraPtr _ self rcvrExtraPtr. matchFlags _ self rcvrMatchFlags. matchSpacePtr _ self rcvrMatchSpacePtr. matchSpaceSize _ self rcvrMatchSpaceSize. interpreterProxy failed ifTrue:[^ nil]. result _ self cCode: 'pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, matchFlags, matchSpacePtr, matchSpaceSize)'. interpreterProxy pop: 2; pushInteger: result. "empty call so compiler doesn't bug me about variables not used" self touch: searchBuffer; touch: matchSpacePtr; touch: matchSpaceSize; touch: length ! ! !RePlugin methodsFor: 're primitives' stamp: 'acg 3/12/1999 23:32'! primPCRENumSubPatterns ", where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Return the number of subpatterns captured by the compiled pattern." self export: true. "Load Parameters" self loadRcvrFromStackAt: 0. "Load Instance Variables" pcrePtr _ self rcvrPCREBufferPtr. interpreterProxy pop: 1; pushInteger: (self cCode: 'pcre_info((pcre *)pcrePtr, NULL, NULL)'). ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 2/25/1999 08:36'! primLastAlloc self export: true. interpreterProxy pop:1; pushInteger: lastAlloc ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 2/21/1999 23:20'! primNetMemory self export: true. interpreterProxy pop:1; pushInteger: netMemory ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 2/21/1999 23:20'! primNumAllocs self export: true. interpreterProxy pop:1; pushInteger: numAllocs ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 2/21/1999 23:20'! primNumFrees self export: true. interpreterProxy pop:1; pushInteger: numFrees ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 3/5/1999 09:18'! rePluginFree: aPointer "Free a block of fixed memory allocated with rePluginMalloc. Instrumented version of C free() to facilitate leak analysis from Smalltalk. OS-specific variations on malloc/free, such as with MacOS, are handled by adding a C macro to the header file redefining malloc/free -- see the class comment" self inline: true. self var: #aPointer declareC: 'void * aPointer'. self returnTypeC: 'void'. numFrees _ numFrees + 1. (aPointer) ifTrue: [self cCode: 'free(aPointer)'] ! ! !RePlugin methodsFor: 'memory management' stamp: 'acg 3/5/1999 09:19'! rePluginMalloc: anInteger "Allocate a block of fixed memory using C calls to malloc(). Instrumented to facilitate leak analysis from Smalltalk. Set global lastAlloc to anInteger. OS-specific variations on malloc/free, such as with MacOS, are handled by adding a C macro to the header file redefining malloc/free -- see the class comment" | aPointer | self inline: true. self var: #anInteger declareC: 'size_t anInteger'. self var: #aPointer declareC: 'void *aPointer'. self returnTypeC: 'void *'. numAllocs _ numAllocs + 1. (aPointer _ self cCode: 'malloc(anInteger)') ifTrue: [lastAlloc _ anInteger]. ^aPointer ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/27/1999 23:22'! allocateByteArrayAndSetRcvrExtraPtrFrom: anExtraPtr | extraObject extraByteArrayPtr | self var: #extraByteArrayPtr declareC: 'void *extraByteArrayPtr'. anExtraPtr ifFalse: [extraObject _ interpreterProxy nilObject] ifTrue: [ "Allocate a Smalltalk ByteArray -- lastAlloc contains the length" extraObject _ interpreterProxy instantiateClass: (interpreterProxy classByteArray) indexableSize: (self cCode: 'sizeof(real_pcre_extra)'). self loadRcvrFromStackAt: 0. "Assume garbage collection after instantiation" "Copy from the C bytecode buffer to the Smalltalk ByteArray" extraByteArrayPtr _ interpreterProxy arrayValueOf: extraObject. self cCode:'memcpy(extraByteArrayPtr, (void *) anExtraPtr, sizeof(real_pcre_extra))']. "Set rcvrErrorStr from errorStr and Return" self rcvrExtraPtrFrom: extraObject. self touch: extraByteArrayPtr. ^extraObject. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/27/1999 22:57'! allocateByteArrayAndSetRcvrPCREPtrFromPCRE: aPCREPtr | patObject patByteArrayPtr | self var: #patByteArrayPtr declareC: 'void *patByteArrayPtr'. "Allocate a Smalltalk ByteArray -- lastAlloc contains the length" patObject _ interpreterProxy instantiateClass: (interpreterProxy classByteArray) indexableSize: lastAlloc. self loadRcvrFromStackAt: 0. "Assume garbage collection after instantiation" "Copy from the C bytecode buffer to the Smalltalk ByteArray" patByteArrayPtr _ interpreterProxy arrayValueOf: patObject. self cCode:'memcpy(patByteArrayPtr, (void *) aPCREPtr, lastAlloc)'. "Set rcvrErrorStr from errorStr and Return" self rcvrPCREBufferFrom: patObject. self touch: patByteArrayPtr. ^patObject. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/28/1999 16:39'! allocateStringAndSetRcvrErrorStrFromCStr: aCStrBuffer |length errorStrObj errorStrObjPtr | self var: #aCStrBuffer declareC: 'char *aCStrBuffer'. self var: #errorStrObjPtr declareC: 'void *errorStrObjPtr'. "Allocate errorStrObj" length _ self cCode: 'strlen(aCStrBuffer)'. errorStrObj _ interpreterProxy instantiateClass: (interpreterProxy classString) indexableSize: length. self loadRcvrFromStackAt: 0. "Assume garbage collection after instantiation" "Copy aCStrBuffer to errorStrObj's buffer" errorStrObjPtr _ interpreterProxy arrayValueOf: errorStrObj. self cCode:'memcpy(errorStrObjPtr,aCStrBuffer,length)'. self touch: errorStrObjPtr; touch: errorStrObj. "Set rcvrErrorStr from errorStrObj and Return" self rcvrErrorStrFrom: errorStrObj. ^errorStrObj.! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/21/1999 22:58'! loadRcvrFromStackAt: stackInteger self inline:true. rcvr _ interpreterProxy stackObjectValue: stackInteger. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/21/1999 21:20'! rcvrCompileFlags self inline:true. ^interpreterProxy fetchInteger: 1 ofObject: rcvr. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/21/1999 22:46'! rcvrErrorOffsetFrom: anInteger self inline: true. interpreterProxy storeInteger: 5 ofObject: rcvr withValue: anInteger. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/24/1999 20:53'! rcvrErrorStrFrom: aString self inline: true. interpreterProxy storePointer: 4 ofObject: rcvr withValue: aString. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/27/1999 23:20'! rcvrExtraPtr |extraObj| self inline: true. extraObj _ interpreterProxy fetchPointer: 3 ofObject: rcvr. (extraObj = (interpreterProxy nilObject)) ifTrue: [^ self cCode: 'NULL']. ^self cCoerce:(interpreterProxy arrayValueOf: extraObj) to: 'int'.! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/27/1999 23:42'! rcvrExtraPtrFrom: aByteArrayOrNilObject self inline: true. interpreterProxy storePointer: 3 ofObject: rcvr withValue: aByteArrayOrNilObject! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/21/1999 21:19'! rcvrMatchFlags self inline: true. ^interpreterProxy fetchInteger: 6 ofObject: rcvr. ! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/25/1999 00:49'! rcvrMatchSpacePtr self inline: true. self returnTypeC: 'int *'. ^self cCoerce: (interpreterProxy fetchArray: 7 ofObject: rcvr) to: 'int *'.! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/25/1999 00:52'! rcvrMatchSpaceSize self inline: true. ^(interpreterProxy byteSizeOf: (interpreterProxy fetchPointer: 7 ofObject: rcvr))//4.! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/24/1999 21:33'! rcvrPCREBufferFrom: aByteArray self inline: true. interpreterProxy storePointer: 2 ofObject: rcvr withValue: aByteArray! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/24/1999 21:33'! rcvrPCREBufferPtr self inline: true. ^self cCoerce: (interpreterProxy fetchArray: 2 ofObject: rcvr) to: 'int'.! ! !RePlugin methodsFor: 'rcvr linkage' stamp: 'acg 2/24/1999 21:34'! rcvrPatternStrPtr self inline: true. self returnTypeC: 'char *'. ^self cCoerce: (interpreterProxy fetchArray: 0 ofObject: rcvr) to: 'char *'.! ! !RePlugin methodsFor: 'private' stamp: 'acg 3/12/1999 23:32'! touch: anOop "Do nothing but fool the compiler into thinking my parameter was used. Since I am inlined, I add no overhead whatsoever." self inline: true.! ! !RePlugin class methodsFor: 'plugin code generation' stamp: 'acg 7/27/2002 20:56'! declareCVarsIn: cg cg addHeaderFile:'"rePlugin.h"'. "Memory Managament Error Checking" cg var: 'netMemory' declareC: 'int netMemory = 0'. cg var: 'numAllocs' declareC: 'int numAllocs = 0'. cg var: 'numFrees' declareC: 'int numFrees = 0'. cg var: 'lastAlloc' declareC: 'int lastAlloc = 0'. "The receiver Object Pointer" cg var: 'rcvr' declareC: 'int rcvr'. "Instance Variables of Receiver Object" cg var: 'patternStr' declareC: 'int patternStr'. cg var: 'compileFlags' declareC: 'int compileFlags'. cg var: 'pcrePtr' declareC: 'int pcrePtr'. cg var: 'extraPtr' declareC: 'int extraPtr'. cg var: 'errorStr' declareC: 'int errorStr'. cg var: 'errorOffset' declareC: 'int errorOffset'. cg var: 'matchFlags' declareC: 'int matchFlags'. "Support Variables for Access to Receiver Instance Variables" cg var: 'patternStrPtr' declareC: 'char * patternStrPtr'. cg var: 'errorStrBuffer' declareC: 'char * errorStrBuffer'.! ! !RePlugin class methodsFor: 'plugin code generation' stamp: 'acg 8/16/2002 22:51'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !RePlugin class methodsFor: 'plugin code generation' stamp: 'acg 7/27/2002 21:48'! moduleName ^'rePlugin'! ! !RePlugin class methodsFor: 'plugin code generation' stamp: 'acg 7/27/2002 20:09'! requiresCrossPlatformFiles "default is ok for most, any plugin needing cross platform files must say so" ^true! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:36'! testNewSuite1test1 | re | re _ Re on: 'the quick brown fox'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'The quick brown FOX') isNil. self assert: (re search: 'What do you know about the quick brown fox?') isNil not. self assert: (re search: 'What do you know about THE QUICK BROWN FOX?') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test10 | re re2 | re _ Re on: '^(ba|b*){1,2}?bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'babc') isNil not. self assert: (re search: 'bbabc') isNil not. self assert: (re search: 'bababc') isNil not. self assert: (re search: 'bababbc') isNil. self assert: (re search: 'babababc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test100 | re re2 | re _ Re on: '[az-]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'za-') isNil not. self assert: (re search: 'b') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test101 | re re2 | re _ Re on: '[a\-z]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-z') isNil not. self assert: (re search: 'b') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test102 | re re2 | re _ Re on: '[a-z]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdxyz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test103 | re re2 | re _ Re on: '[\d-]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '12-34') isNil not. self assert: (re search: 'aaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test104 | re re2 | re _ Re on: '[\d-z]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '12-34z') isNil not. self assert: (re search: 'aaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:39'! testNewSuite1test105 | re | re _ Re on: '\x5c'. self shouldnt: [re compile] raise: Error. self assert: (re search: '\') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test106 | re re2 | re _ Re on: '\x20Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the Zoo') isNil not. self assert: (re search: 'Zulu') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test107 | re re2 | re _ Re on: '(abc)\1'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabc') isNil not. self assert: (re search: 'ABCabc') isNil not. self assert: (re search: 'abcABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test108 | re re2 | re _ Re on: 'ab{3cd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab{3cd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test109 | re re2 | re _ Re on: 'ab{3,cd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab{3,cd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test11 | re re2 | re _ Re on: '^\ca\cA\c[\c{\c:'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPut: 16r01 asCharacter; nextPut: 16r01 asCharacter; nextPut: Character escape; nextPutAll: ';z'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test110 | re re2 | re _ Re on: 'ab{3,4a}cd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab{3,4a}cd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test111 | re re2 | re _ Re on: '{4,5a}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: '{4,5a}bc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test112 | re re2 | re _ Re on: '^a.b'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character linefeed; nextPutAll: 'b'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test113 | re re2 | re _ Re on: 'abc$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'def'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test114 | re re2 | re _ Re on: '(abc)\123'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r53 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test115 | re re2 | re _ Re on: '(abc)\223'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r93 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test116 | re re2 | re _ Re on: '(abc)\323'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16rD3 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test117 | re re2 | re _ Re on: '(abc)\500'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r40 asCharacter])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r100 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test118 | re re2 | re _ Re on: '(abc)\5000'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r40 asCharacter; nextPutAll: '0'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r40 asCharacter; nextPut: 16r30 asCharacter])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r100 asCharacter; nextPutAll: '0'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r100 asCharacter; nextPut: 16r30 asCharacter])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r100 asCharacter; nextPut: 8r060 asCharacter])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r100 asCharacter; nextPut: 8r60 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test119 | re re2 | re _ Re on: 'abc\81'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r0 asCharacter; nextPutAll: '81'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r0 asCharacter; nextPut: 16r38 asCharacter; nextPut: 16r31 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test12 | re re2 | re _ Re on: '^[ab\]cde]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'athing') isNil not. self assert: (re search: 'bthing') isNil not. self assert: (re search: ']thing') isNil not. self assert: (re search: 'cthing') isNil not. self assert: (re search: 'dthing') isNil not. self assert: (re search: 'ething') isNil not. self assert: (re search: 'fthing') isNil. self assert: (re search: '[thing') isNil. self assert: (re search: '\\thing') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test120 | re re2 | re _ Re on: 'abc\91'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r0 asCharacter; nextPutAll: '91'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r0 asCharacter; nextPut: 16r39 asCharacter; nextPut: 16r31 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test121 | re re2 | re _ Re on: '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\12\123'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdefghijkllS') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test122 | re re2 | re _ Re on: '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\123'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcdefghijk'; nextPut: 8r12 asCharacter; nextPutAll: 'S'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test123 | re re2 | re _ Re on: 'ab\gdef'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abgdef') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test124 | re re2 | re _ Re on: 'a{0}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test125 | re re2 | re _ Re on: '(a|(bc)){0,0}?xyz'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xyz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test126 | re re2 | re _ Re on: 'abc[\10]de'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r010 asCharacter; nextPutAll: 'de'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test127 | re re2 | re _ Re on: 'abc[\1]de'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r1 asCharacter; nextPutAll: 'de'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test128 | re re2 | re _ Re on: '(abc)[\1]de'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r1 asCharacter; nextPutAll: 'de'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test129 | re re2 | re _ Re on: 'a.b(?s)'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test13 | re re2 | re _ Re on: '^[]cde]'. self shouldnt: [re compile] raise: Error. self assert: (re search: ']thing') isNil not. self assert: (re search: 'cthing') isNil not. self assert: (re search: 'dthing') isNil not. self assert: (re search: 'ething') isNil not. self assert: (re search: 'athing') isNil. self assert: (re search: 'fthing') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test130 | re re2 | re _ Re on: '^([^a])([^\b])([^c]*)([^d]{3,4})'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'baNOTccccd') isNil not. self assert: (re search: 'baNOTcccd') isNil not. self assert: (re search: 'baNOTccd') isNil not. self assert: (re search: 'bacccd') isNil not. self assert: (re search: 'anything') isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'b'; nextPut: Character backspace; nextPutAll: 'c'])) isNil. self assert: (re search: 'baccd') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test131 | re re2 | re _ Re on: '[^a]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'Abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test132 | re re2 | re _ Re on: '[^a]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'Abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test133 | re re2 | re _ Re on: '[^a]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'AAAaAbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test134 | re re2 | re _ Re on: '[^a]+'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'AAAaAbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test135 | re re2 | re _ Re on: '[^a]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'bbb'; nextPut: Character cr; nextPutAll: 'ccc'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test136 | re re2 | re _ Re on: '[^k]$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'abk') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test137 | re re2 | re _ Re on: '[^k]{2,3}$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'kbc') isNil not. self assert: (re search: 'kabc') isNil not. self assert: (re search: 'abk') isNil. self assert: (re search: 'akb') isNil. self assert: (re search: 'akk') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:40'! testNewSuite1test138 | re | re _ Re on: '^\d{8,}\@.+[^k]$'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: '12345678@a.b.c.d'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: '123456789@x.y.z'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: '12345678@x.y.uk'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: '1234567@a.b.c.d'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test139 | re re2 | re _ Re on: '(a)\1{8,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaaaaaaa') isNil not. self assert: (re search: 'aaaaaaaaaa') isNil not. self assert: (re search: 'aaaaaaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test14 | re re2 | re _ Re on: '^[^ab\]cde]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'fthing') isNil not. self assert: (re search: '[thing') isNil not. self assert: (re search: '\\thing') isNil not. self assert: (re search: 'athing') isNil. self assert: (re search: 'bthing') isNil. self assert: (re search: ']thing') isNil. self assert: (re search: 'cthing') isNil. self assert: (re search: 'dthing') isNil. self assert: (re search: 'ething') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test140 | re re2 | re _ Re on: '[^a]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaabcd') isNil not. self assert: (re search: 'aaAabcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test141 | re re2 | re _ Re on: '[^a]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaabcd') isNil not. self assert: (re search: 'aaAabcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test142 | re re2 | re _ Re on: '[^az]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaabcd') isNil not. self assert: (re search: 'aaAabcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test143 | re re2 | re _ Re on: '[^az]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaabcd') isNil not. self assert: (re search: 'aaAabcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:41'! testNewSuite1test144 | re | re _ Re on: '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | 0 to: 255 do: [:each | s nextPut: each asCharacter]])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test145 | re re2 | re _ Re on: 'P[^*]TAIRE[^*]{1,6}?LL'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xxxxxxxxxxxPSTAIREISLLxxxxxxxxx') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test146 | re re2 | re _ Re on: 'P[^*]TAIRE[^*]{1,}?LL'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xxxxxxxxxxxPSTAIREISLLxxxxxxxxx') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test147 | re re2 | re _ Re on: '(\.\d\d[1-9]?)\d+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1.230003938') isNil not. self assert: (re search: '1.875000282') isNil not. self assert: (re search: '1.235') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test148 | re re2 | re _ Re on: '(\.\d\d((?=0)|\d(?=\d)))'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1.230003938') isNil not. self assert: (re search: '1.875000282') isNil not. self assert: (re search: '1.235') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test149 | re re2 | re _ Re on: 'a(?)b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test15 | re re2 | re _ Re on: '^[^]cde]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'athing') isNil not. self assert: (re search: 'fthing') isNil not. self assert: (re search: ']thing') isNil. self assert: (re search: 'cthing') isNil. self assert: (re search: 'dthing') isNil. self assert: (re search: 'ething') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test150 | re re2 | re _ Re on: '\b(foo)\s+(\w+)'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'Food is on the foo table') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test151 | re re2 | re _ Re on: 'foo(.*)bar'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'The food is under the bar in the barn.') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test152 | re re2 | re _ Re on: 'foo(.*?)bar'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'The food is under the bar in the barn.') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test153 | re re2 | re _ Re on: '(.*)(\d*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test154 | re re2 | re _ Re on: '(.*)(\d+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test155 | re re2 | re _ Re on: '(.*?)(\d*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test156 | re re2 | re _ Re on: '(.*?)(\d+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test157 | re re2 | re _ Re on: '(.*)(\d+)$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test158 | re re2 | re _ Re on: '(.*?)(\d+)$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test159 | re re2 | re _ Re on: '(.*)\b(\d+)$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test16 | re re2 | re _ Re on: '^\'. self shouldnt: [re compile] raise: Error. self assert: (re search: '') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test160 | re re2 | re _ Re on: '(.*\D)(\d+)$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'I have 2 numbers: 53147') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test161 | re re2 | re _ Re on: '^\D*(?!!123)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC123') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test162 | re re2 | re _ Re on: '^(\D*)(?=\d)(?!!123)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC445') isNil not. self assert: (re search: 'ABC123') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test163 | re re2 | re _ Re on: '^[W-]46]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'W46]789') isNil not. self assert: (re search: '-46]789') isNil not. self assert: (re search: 'Wall') isNil. self assert: (re search: 'Zebra') isNil. self assert: (re search: '42') isNil. self assert: (re search: '[abcd]') isNil. self assert: (re search: ']abcd[') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test164 | re re2 | re _ Re on: '^[W-\]46]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'W46]789') isNil not. self assert: (re search: 'Wall') isNil not. self assert: (re search: 'Zebra') isNil not. self assert: (re search: 'Xylophone') isNil not. self assert: (re search: '42') isNil not. self assert: (re search: '[abcd]') isNil not. self assert: (re search: ']abcd[') isNil not. self assert: (re search: '\\backslash') isNil not. self assert: (re search: '-46]789') isNil. self assert: (re search: 'well') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test165 | re re2 | re _ Re on: '\d\d/\d\d\/\d\d\d\d'. self shouldnt: [re compile] raise: Error. self assert: (re search: '01/01/2000') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:43'! testNewSuite1test166 | re | re _ Re on: 'word (?:[a-zA-Z0-9]+ ){0,10}otherword'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark otherword') isNil not. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:34'! testNewSuite1test167 | re | re _ Re on: 'word (?:[a-zA-Z0-9]+ ){0,300}otherword'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope otherword') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test168 | re re2 | re _ Re on: '^(a){0,0}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test169 | re re2 | re _ Re on: '^(a){0,1}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test17 | re re2 | re _ Re on: '^'. self shouldnt: [re compile] raise: Error. self assert: (re search: '') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test170 | re re2 | re _ Re on: '^(a){0,2}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test171 | re re2 | re _ Re on: '^(a){0,3}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. self assert: (re search: 'aaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test172 | re re2 | re _ Re on: '^(a){0,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. self assert: (re search: 'aaa') isNil not. self assert: (re search: 'aaaaaaaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:43'! testNewSuite1test173 | re | re _ Re on: '^(a){1,1}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:35'! testNewSuite1test174 | re | re _ Re on: '^(a){1,2}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:43'! testNewSuite1test175 | re | re _ Re on: '^(a){1,3}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. self assert: (re search: 'aaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:44'! testNewSuite1test176 | re | re _ Re on: '^(a){1,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bcd') isNil. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aab') isNil not. self assert: (re search: 'aaa') isNil not. self assert: (re search: 'aaaaaaaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test177 | re re2 | re _ Re on: '.*\.gif'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test178 | re re2 | re _ Re on: '.{0,}\.gif'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test179 | re re2 | re _ Re on: '.*\.gif'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test18 | re re2 | re _ Re on: '^[0-9]+$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '0') isNil not. self assert: (re search: '1') isNil not. self assert: (re search: '2') isNil not. self assert: (re search: '3') isNil not. self assert: (re search: '4') isNil not. self assert: (re search: '5') isNil not. self assert: (re search: '6') isNil not. self assert: (re search: '7') isNil not. self assert: (re search: '8') isNil not. self assert: (re search: '9') isNil not. self assert: (re search: '10') isNil not. self assert: (re search: '100') isNil not. self assert: (re search: 'abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test180 | re re2 | re _ Re on: '.*\.gif'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test181 | re re2 | re _ Re on: '.*\.gif'. re beMultiline; beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test182 | re re2 | re _ Re on: '.*$'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test183 | re re2 | re _ Re on: '.*$'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test184 | re re2 | re _ Re on: '.*$'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test185 | re re2 | re _ Re on: '.*$'. re beMultiline; beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test186 | re re2 | re _ Re on: '.*$'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test187 | re re2 | re _ Re on: '.*$'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test188 | re re2 | re _ Re on: '.*$'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test189 | re re2 | re _ Re on: '.*$'. re beMultiline; beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'borfle'; nextPut: Character cr; nextPutAll: 'bib.gif'; nextPut: Character cr; nextPutAll: 'no'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test19 | re re2 | re _ Re on: '^.*nter'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'enter') isNil not. self assert: (re search: 'inter') isNil not. self assert: (re search: 'uponter') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test190 | re re2 | re _ Re on: '(.*X|^B)'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test191 | re re2 | re _ Re on: '(.*X|^B)'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test192 | re re2 | re _ Re on: '(.*X|^B)'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test193 | re re2 | re _ Re on: '(.*X|^B)'. re beMultiline; beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test194 | re re2 | re _ Re on: '(?s)(.*X|^B)'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test195 | re re2 | re _ Re on: '(?s:.*X|^B)'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: '1234Xyz'])) isNil not. self assert: (re search: 'BarFoo') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcde'; nextPut: Character cr; nextPutAll: 'Bar'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test196 | re re2 | re _ Re on: '^.*B'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'B'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test197 | re re2 | re _ Re on: '(?s)^.*B'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'B'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test198 | re re2 | re _ Re on: '(?m)^.*B'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'B'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test199 | re re2 | re _ Re on: '(?ms)^.*B'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'B'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test2 | re re2 | re _ Re on: 'The quick brown fox'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'The quick brown FOX') isNil not. self assert: (re search: 'What do you know about the quick brown fox?') isNil not. self assert: (re search: 'What do you know about THE QUICK BROWN FOX?') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test20 | re re2 | re _ Re on: '^xxx[0-9]+$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xxx0') isNil not. self assert: (re search: 'xxx1234') isNil not. self assert: (re search: 'xxx') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test200 | re re2 | re _ Re on: '(?ms)^B'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'B'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test201 | re re2 | re _ Re on: '(?s)B$'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'B'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test202 | re re2 | re _ Re on: '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'. self shouldnt: [re compile] raise: Error. self assert: (re search: '123456654321') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test203 | re re2 | re _ Re on: '^\d\d\d\d\d\d\d\d\d\d\d\d'. self shouldnt: [re compile] raise: Error. self assert: (re search: '123456654321') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test204 | re re2 | re _ Re on: '^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]'. self shouldnt: [re compile] raise: Error. self assert: (re search: '123456654321') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test205 | re re2 | re _ Re on: '^[abc]{12}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabcabcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test206 | re re2 | re _ Re on: '^[a-c]{12}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabcabcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test207 | re re2 | re _ Re on: '^(a|b|c){12}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabcabcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test208 | re re2 | re _ Re on: '^[abcdefghijklmnopqrstuvwxy0123456789]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'n') isNil not. self assert: (re search: 'z') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test209 | re re2 | re _ Re on: 'abcde{0,0}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. self assert: (re search: 'abce') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 14:10'! testNewSuite1test21 | re | re _ Re on: '^.+[0-9][0-9][0-9]$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'x123') isNil not. self assert: (re search: 'xx123') isNil not. self assert: (re search: '123456') isNil not. self assert: (re search: '123') isNil. self assert: (re search: 'x1234') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test210 | re re2 | re _ Re on: 'ab[cd]{0,0}e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abe') isNil not. self assert: (re search: 'abcde') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test211 | re re2 | re _ Re on: 'ab(c){0,0}d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abd') isNil not. self assert: (re search: 'abcd') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test212 | re re2 | re _ Re on: 'a(b*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'ab') isNil not. self assert: (re search: 'abbbb') isNil not. self assert: (re search: 'bbbbb') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test213 | re re2 | re _ Re on: 'ab\d{0}e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abe') isNil not. self assert: (re search: 'ab1e') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:48'! testNewSuite1test214 | re | re _ Re on: '"([^\\"]+|\\.)*"'. self shouldnt: [re compile] raise: Error. self assert: ('the \"quick\" brown fox') isNil not. self assert: ('\"the \\\"quick\\\" brown fox\"') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test215 | re re2 | re _ Re on: '.*?'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test216 | re re2 | re _ Re on: '\b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test217 | re re2 | re _ Re on: '\b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test218 | re re2 | re _ Re on: ''. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test219 | re re2 | re _ Re on: ']{0,})>]{0,})>([\d]{0,}\.)(.*)((
([\w\W\s\d][^<>]{0,})|[\s]{0,}))
]{0,})>([\w\W\s\d][^<>]{0,})]{0,})>([\w\W\s\d][^<>]{0,})'. re beNotCaseSensitive; beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: '43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 14:11'! testNewSuite1test22 | re | re _ Re on: '^.+?[0-9][0-9][0-9]$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'x123') isNil not. self assert: (re search: 'xx123') isNil not. self assert: (re search: '123456') isNil not. self assert: (re search: '123') isNil. self assert: (re search: 'x1234') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test220 | re re2 | re _ Re on: 'a[^a]b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acb') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test221 | re re2 | re _ Re on: 'a.b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acb') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test222 | re re2 | re _ Re on: 'a[^a]b'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acb') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test223 | re re2 | re _ Re on: 'a.b'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acb') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test224 | re re2 | re _ Re on: '^(b+?|a){1,2}?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bac') isNil not. self assert: (re search: 'bbac') isNil not. self assert: (re search: 'bbbac') isNil not. self assert: (re search: 'bbbbac') isNil not. self assert: (re search: 'bbbbbac') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test225 | re re2 | re _ Re on: '^(b+|a){1,2}?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bac') isNil not. self assert: (re search: 'bbac') isNil not. self assert: (re search: 'bbbac') isNil not. self assert: (re search: 'bbbbac') isNil not. self assert: (re search: 'bbbbbac') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 14:12'! testNewSuite1test226 | re | re _ Re on: '(?!!\A)x'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'x'; nextPut: Character cr; nextPutAll: 'b'; nextPut: Character cr])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character backspace; nextPutAll: 'x'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test227 | re re2 | re _ Re on: '\x0{ab}'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPut: 8r0 asCharacter; nextPutAll: '{ab}'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test228 | re re2 | re _ Re on: '(A|B)*?CD'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'CD') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test229 | re re2 | re _ Re on: '(A|B)*CD'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'CD') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test23 | re re2 | re _ Re on: '^([^!!]+)!!(.+)=apquxz\.ixr\.zzz\.ac\.uk$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc!!pqr=apquxz.ixr.zzz.ac.uk') isNil not. self assert: (re search: '!!pqr=apquxz.ixr.zzz.ac.uk') isNil. self assert: (re search: 'abc!!=apquxz.ixr.zzz.ac.uk') isNil. self assert: (re search: 'abc!!pqr=apquxz:ixr.zzz.ac.uk') isNil. self assert: (re search: 'abc!!pqr=apquxz.ixr.zzz.ac.ukk') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test230 | re re2 | re _ Re on: '(AB)*?\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABABAB') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test231 | re re2 | re _ Re on: '(AB)*\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABABAB') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test232 | re re2 | re _ Re on: ' End of testinput1 '. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test24 | re re2 | re _ Re on: ':'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'Well, we need a colon: somewhere') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test25 | re re2 | re _ Re on: '([\da-f:]+)$'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: '0abc') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'fed') isNil not. self assert: (re search: 'E') isNil not. self assert: (re search: '::') isNil not. self assert: (re search: '5f03:12C0::932e') isNil not. self assert: (re search: 'fed def') isNil not. self assert: (re search: 'Any old stuff') isNil not. self assert: (re search: '0zzz') isNil. self assert: (re search: 'gzzz') isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'fed'; nextPut: 16r20 asCharacter])) isNil. self assert: (re search: 'Any old rubbish') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test26 | re re2 | re _ Re on: '^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '.1.2.3') isNil not. self assert: (re search: 'A.12.123.0') isNil not. self assert: (re search: '.1.2.3333') isNil. self assert: (re search: '1.2.3') isNil. self assert: (re search: '1234.2.3') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test27 | re re2 | re _ Re on: '^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1 IN SOA non-sp1 non-sp2(') isNil not. self assert: (re search: '1 IN SOA non-sp1 non-sp2 (') isNil not. self assert: (re search: '1IN SOA non-sp1 non-sp2(') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test28 | re re2 | re _ Re on: '^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a.') isNil not. self assert: (re search: 'Z.') isNil not. self assert: (re search: '2.') isNil not. self assert: (re search: 'ab-c.pq-r.') isNil not. self assert: (re search: 'sxk.zzz.ac.uk.') isNil not. self assert: (re search: 'x-.y-.') isNil not. self assert: (re search: '-abc.peq.') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test29 | re re2 | re _ Re on: '^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '*.a') isNil not. self assert: (re search: '*.b0-a') isNil not. self assert: (re search: '*.c3-b.c') isNil not. self assert: (re search: '*.c-a.b-c') isNil not. self assert: (re search: '*.0') isNil. self assert: (re search: '*.a-') isNil. self assert: (re search: '*.a-b.c-') isNil. self assert: (re search: '*.c-a.0-c') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:54'! testNewSuite1test3 | re | re _ Re on: 'abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abcd'; nextPut: Character tab; nextPut: Character cr; nextPut: Character cr; nextPut: Character newPage; nextPut: 7 asCharacter; nextPut: Character escape; nextPut: 8r071 asCharacter; nextPut: 16r3B asCharacter; nextPutAll: '$\?caxyz'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test30 | re re2 | re _ Re on: '^(?=ab(de))(abd)(e)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test31 | re re2 | re _ Re on: '^(?!!(ab)de|x)(abd)(f)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abdf') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test32 | re re2 | re _ Re on: '^(?=(ab(cd)))(ab)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test33 | re re2 | re _ Re on: '^[\da-f](\.[\da-f])*$'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a.b.c.d') isNil not. self assert: (re search: 'A.B.C.D') isNil not. self assert: (re search: 'a.b.c.1.2.3.C') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 14:16'! testNewSuite1test34 | re | re _ Re on: '^\".*\"\s*(;.*)?$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '"1234"') isNil not. self assert: (re search: '"abcd" ;') isNil not. self assert: (re search: '"" ; rhubarb') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: '1234'; nextPutAll: ' : things'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test35 | re re2 | re _ Re on: '^$'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test36 | re re2 | re _ Re on: ' ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)'. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab c') isNil not. self assert: (re search: 'abc') isNil. self assert: (re search: 'ab cde') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test37 | re re2 | re _ Re on: '(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab c') isNil not. self assert: (re search: 'abc') isNil. self assert: (re search: 'ab cde') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test38 | re re2 | re _ Re on: '^ a\ b[c ]d $'. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a bcd') isNil not. self assert: (re search: 'a b d') isNil not. self assert: (re search: 'abcd') isNil. self assert: (re search: 'ab d') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test39 | re re2 | re _ Re on: '^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdefhijklm') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test4 | re re2 | re _ Re on: 'a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'abxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aabxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaabxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaaabxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'abcxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aabcxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqqqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqqqqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqqqqqAzz') isNil not. self assert: (re search: 'aaaabcxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'abxyzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aabxyzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaabxyzzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaaabxyzzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'abcxyzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aabcxyzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaabcxyzzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaaabcxyzzzzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'aaaabcxyzzzzpqrrrabbbxyyyypqAzz') isNil not. self assert: (re search: 'aaaabcxyzzzzpqrrrabbbxyyyyypqAzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypABzz') isNil not. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypABBzz') isNil not. self assert: (re search: '>>>aaabxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: '>aaaabxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: '>>>>abcxyzpqrrrabbxyyyypqAzz') isNil not. self assert: (re search: 'abxyzpqrrabbxyyyypqAzz') isNil. self assert: (re search: 'abxyzpqrrrrabbxyyyypqAzz') isNil. self assert: (re search: 'abxyzpqrrrabxyyyypqAzz') isNil. self assert: (re search: 'aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz') isNil. self assert: (re search: 'aaaabcxyzzzzpqrrrabbbxyyypqAzz') isNil. self assert: (re search: 'aaabcxyzpqrrrabbxyyyypqqqqqqqAzz') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test40 | re re2 | re _ Re on: '^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdefhijklm') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test41 | re re2 | re _ Re on: '^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a+ Z0+'; nextPut: 16r08 asCharacter; nextPut: Character cr; nextPut: 16r1D asCharacter; nextPut: 16r12 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test42 | re re2 | re _ Re on: '^[.^$|()*+?{,}]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: '.^'; nextPutAll: '(*+)|{?,?}'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test43 | re re2 | re _ Re on: '^a*\w'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'z') isNil not. self assert: (re search: 'az') isNil not. self assert: (re search: 'aaaz') isNil not. self assert: (re search: 'a') isNil not. self assert: (re search: 'aa') isNil not. self assert: (re search: 'aaaa') isNil not. self assert: (re search: 'a+') isNil not. self assert: (re search: 'aa+') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test44 | re re2 | re _ Re on: '^a*?\w'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'z') isNil not. self assert: (re search: 'az') isNil not. self assert: (re search: 'aaaz') isNil not. self assert: (re search: 'a') isNil not. self assert: (re search: 'aa') isNil not. self assert: (re search: 'aaaa') isNil not. self assert: (re search: 'a+') isNil not. self assert: (re search: 'aa+') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test45 | re re2 | re _ Re on: '^a+\w'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'az') isNil not. self assert: (re search: 'aaaz') isNil not. self assert: (re search: 'aa') isNil not. self assert: (re search: 'aaaa') isNil not. self assert: (re search: 'aa+') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test46 | re re2 | re _ Re on: '^a+?\w'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'az') isNil not. self assert: (re search: 'aaaz') isNil not. self assert: (re search: 'aa') isNil not. self assert: (re search: 'aaaa') isNil not. self assert: (re search: 'aa+') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test47 | re re2 | re _ Re on: '^\d{8}\w{2,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1234567890') isNil not. self assert: (re search: '12345678ab') isNil not. self assert: (re search: '12345678__') isNil not. self assert: (re search: '1234567') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test48 | re re2 | re _ Re on: '^[aeiou\d]{4,5}$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'uoie') isNil not. self assert: (re search: '1234') isNil not. self assert: (re search: '12345') isNil not. self assert: (re search: 'aaaaa') isNil not. self assert: (re search: '123456') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test49 | re re2 | re _ Re on: '^[aeiou\d]{4,5}?'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'uoie') isNil not. self assert: (re search: '1234') isNil not. self assert: (re search: '12345') isNil not. self assert: (re search: 'aaaaa') isNil not. self assert: (re search: '123456') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test5 | re re2 | re _ Re on: '^(abc){1,2}zz'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abczz') isNil not. self assert: (re search: 'abcabczz') isNil not. self assert: (re search: 'zz') isNil. self assert: (re search: 'abcabcabczz') isNil. self assert: (re search: '>>abczz') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test50 | re re2 | re _ Re on: '\A(abc|def)=(\1){2,3}\Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc=abcabc') isNil not. self assert: (re search: 'def=defdefdef') isNil not. self assert: (re search: 'abc=defdef') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test51 | re re2 | re _ Re on: '^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?#)2$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdefghijkcda2') isNil not. self assert: (re search: 'abcdefghijkkkkcda2') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test52 | re re2 | re _ Re on: '(cat(a(ract|tonic)|erpillar)) \1()2(3)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cataract cataract23') isNil not. self assert: (re search: 'catatonic catatonic23') isNil not. self assert: (re search: 'caterpillar caterpillar23') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test54 | re re2 | re _ Re on: '^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'From abcd Mon Sep 01 12:33:02 1997') isNil not. self assert: (re search: 'From abcd Mon Sep 1 12:33:02 1997') isNil not. self assert: (re search: 'From abcd Sep 01 12:33:02 1997') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test55 | re re2 | re _ Re on: '^12.34'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: '12'; nextPut: Character cr; nextPutAll: '34'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: '12'; nextPut: Character linefeed; nextPutAll: '34'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test56 | re re2 | re _ Re on: '\w+(?=\t)'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'the quick brown'; nextPut: Character tab; nextPutAll: ' fox'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test57 | re re2 | re _ Re on: 'foo(?!!bar)(.*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'foobar is foolish see?') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test58 | re re2 | re _ Re on: '(?:(?!!foo)...|^.{0,2})bar(.*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'foobar crowbar etc') isNil not. self assert: (re search: 'barrel') isNil not. self assert: (re search: '2barrel') isNil not. self assert: (re search: 'A barrel') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test59 | re re2 | re _ Re on: '^(\D*)(?=\d)(?!!123)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc456') isNil not. self assert: (re search: 'abc123') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test6 | re re2 | re _ Re on: '^(b+?|a){1,2}?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bc') isNil not. self assert: (re search: 'bbc') isNil not. self assert: (re search: 'bbbc') isNil not. self assert: (re search: 'bac') isNil not. self assert: (re search: 'bbac') isNil not. self assert: (re search: 'aac') isNil not. self assert: (re search: 'abbbbbbbbbbbc') isNil not. self assert: (re search: 'bbbbbbbbbbbac') isNil not. self assert: (re search: 'aaac') isNil. self assert: (re search: 'abbbbbbbbbbbac') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test60 | re re2 | re _ Re on: '^1234(?# test newlines inside)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1234') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test61 | re re2 | re _ Re on: '^1234 #comment in extended re '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '1234') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test62 | re re2 | re _ Re on: '#rhubarb abcd'. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test63 | re re2 | re _ Re on: '^abcd#rhubarb'. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test64 | re re2 | re _ Re on: '^(a)\1{2,3}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. self assert: (re search: 'aaaab') isNil not. self assert: (re search: 'aaaaab') isNil not. self assert: (re search: 'aaaaaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test65 | re re2 | re _ Re on: '(?!!^)abc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the abc') isNil not. self assert: (re search: 'abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test66 | re re2 | re _ Re on: '(?=^)abc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'the abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test67 | re re2 | re _ Re on: '^[ab]{1,3}(ab*|b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbbbb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test68 | re re2 | re _ Re on: '^[ab]{1,3}?(ab*|b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbbbb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test69 | re re2 | re _ Re on: '^[ab]{1,3}?(ab*?|b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbbbb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test7 | re re2 | re _ Re on: '^(b+|a){1,2}c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bc') isNil not. self assert: (re search: 'bbc') isNil not. self assert: (re search: 'bbbc') isNil not. self assert: (re search: 'bac') isNil not. self assert: (re search: 'bbac') isNil not. self assert: (re search: 'aac') isNil not. self assert: (re search: 'abbbbbbbbbbbc') isNil not. self assert: (re search: 'bbbbbbbbbbbac') isNil not. self assert: (re search: 'aaac') isNil. self assert: (re search: 'abbbbbbbbbbbac') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test70 | re re2 | re _ Re on: '^[ab]{1,3}(ab*?|b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbbbb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test73 | re re2 | re _ Re on: 'abc\0def\00pqr\000xyz\0000AB'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 8r0 asCharacter; nextPutAll: 'def'; nextPut: 8r00 asCharacter; nextPutAll: 'pqr'; nextPut: 8r000 asCharacter; nextPutAll: 'xyz'; nextPut: 8r000 asCharacter; nextPutAll: '0AB'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc456 abc'; nextPut: 8r0 asCharacter; nextPutAll: 'def'; nextPut: 8r00 asCharacter; nextPutAll: 'pqr'; nextPut: 8r000 asCharacter; nextPutAll: 'xyz'; nextPut: 8r000 asCharacter; nextPutAll: '0ABCDE'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test74 | re re2 | re _ Re on: 'abc\x0def\x00pqr\x000xyz\x0000AB'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: 16r0D asCharacter; nextPutAll: 'ef'; nextPut: 16r00 asCharacter; nextPutAll: 'pqr'; nextPut: 16r00 asCharacter; nextPutAll: '0xyz'; nextPut: 16r00 asCharacter; nextPutAll: '00AB'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc456 abc'; nextPut: 16r0D asCharacter; nextPutAll: 'ef'; nextPut: 16r00 asCharacter; nextPutAll: 'pqr'; nextPut: 16r00 asCharacter; nextPutAll: '0xyz'; nextPut: 16r00 asCharacter; nextPutAll: '00ABCDE'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test75 | re re2 | re _ Re on: '^[\000-\037]'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPut: 8r0 asCharacter; nextPutAll: 'A'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: 8r01 asCharacter; nextPutAll: 'B'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: 8r037 asCharacter; nextPutAll: 'C'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test76 | re re2 | re _ Re on: '\0*'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPut: 8r0 asCharacter; nextPut: 8r0 asCharacter; nextPut: 8r0 asCharacter; nextPut: 8r0 asCharacter])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test77 | re re2 | re _ Re on: 'A\x0{2,3}Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'The A'; nextPut: 16r0 asCharacter; nextPut: 16r0 asCharacter; nextPutAll: 'Z'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'An A'; nextPut: 8r0 asCharacter; nextPut: 16r0 asCharacter; nextPut: 8r0 asCharacter; nextPutAll: 'Z'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'A'; nextPut: 8r0 asCharacter; nextPutAll: 'Z'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'A'; nextPut: 8r0 asCharacter; nextPut: 16r0 asCharacter; nextPut: 8r0 asCharacter; nextPut: 16r0 asCharacter; nextPutAll: 'Z'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test78 | re re2 | re _ Re on: '^(cow|)\1(bell)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cowcowbell') isNil not. self assert: (re search: 'bell') isNil not. self assert: (re search: 'cowbell') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test79 | re re2 | re _ Re on: '^\s'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPut: 8r040 asCharacter; nextPutAll: 'abc'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: 16r0C asCharacter; nextPutAll: 'abc'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: Character cr; nextPutAll: 'abc'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: Character linefeed; nextPutAll: 'abc'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPut: Character tab; nextPutAll: 'abc'])) isNil not. self assert: (re search: 'abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test8 | re re2 | re _ Re on: '^(b+|a){1,2}?bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test80 | re re2 | re _ Re on: '^a b c'. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test81 | re re2 | re _ Re on: '^(a|)\1*b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'aaaab') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'acb') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test82 | re re2 | re _ Re on: '^(a|)\1+b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aab') isNil not. self assert: (re search: 'aaaab') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'ab') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test83 | re re2 | re _ Re on: '^(a|)\1?b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'aab') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'acb') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test84 | re re2 | re _ Re on: '^(a|)\1{2}b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'ab') isNil. self assert: (re search: 'aab') isNil. self assert: (re search: 'aaaab') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test85 | re re2 | re _ Re on: '^(a|)\1{2,3}b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. self assert: (re search: 'aaaab') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'ab') isNil. self assert: (re search: 'aab') isNil. self assert: (re search: 'aaaaab') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test86 | re re2 | re _ Re on: 'ab{1,3}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. self assert: (re search: 'abbbc') isNil not. self assert: (re search: 'abbc') isNil not. self assert: (re search: 'abc') isNil. self assert: (re search: 'abbbbbc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test87 | re re2 | re _ Re on: '([^.]*)\.([^:]*):[T ]+(.*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'track1.title:TBlah blah blah') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test88 | re re2 | re _ Re on: '([^.]*)\.([^:]*):[T ]+(.*)'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'track1.title:TBlah blah blah') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test89 | re re2 | re _ Re on: '([^.]*)\.([^:]*):[t ]+(.*)'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'track1.title:TBlah blah blah') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test9 | re re2 | re _ Re on: '^(b*|ba){1,2}?bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'babc') isNil not. self assert: (re search: 'bbabc') isNil not. self assert: (re search: 'bababc') isNil not. self assert: (re search: 'bababbc') isNil. self assert: (re search: 'babababc') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test90 | re re2 | re _ Re on: '^[W-c]+$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'WXY_^abc') isNil not. self assert: (re search: 'wxy') isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test91 | re re2 | re _ Re on: '^[W-c]+$'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'WXY_^abc') isNil not. self assert: (re search: 'wxy_^ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test92 | re re2 | re _ Re on: '^[\x3f-\x5F]+$'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'WXY_^abc') isNil not. self assert: (re search: 'wxy_^ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test93 | re re2 | re _ Re on: '^abc$'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test94 | re re2 | re _ Re on: '^abc$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test95 | re re2 | re _ Re on: '\Aabc\Z'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr])) isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test96 | re re2 | re _ Re on: '\A(.)*\Z'. re beDotIncludesNewline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'def'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test97 | re re2 | re _ Re on: '\A(.)*\Z'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'def'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test98 | re re2 | re _ Re on: '(?:b)|(?::+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'b::c') isNil not. self assert: (re search: 'c::b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite1' stamp: 'acg 8/11/2002 12:30'! testNewSuite1test99 | re re2 | re _ Re on: '[-az]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'az-') isNil not. self assert: (re search: 'b') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test1 | re re2 | re _ Re on: '(a)b|'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:57'! testNewSuite2test10 | re | re _ Re on: '(?X)ab\gdef'. re beExtra. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test100 | re re2 | re _ Re on: '(?[^()]+) # Either a sequence of non-brackets (no backtracking) | # Or (?R) # Recurse - i.e. nested bracketed string )* # Zero or more contents \) # Closing ) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(abcd)') isNil not. self assert: (re search: '(abcd)xyz') isNil not. self assert: (re search: 'xyz(abcd)') isNil not. self assert: (re search: '(ab(xy)cd)pqr') isNil not. self assert: (re search: '(ab(xycd)pqr') isNil not. self assert: (re search: '() abc ()') isNil not. self assert: (re search: '12(abcde(fsh)xyz(foo(bar))lmno)89') isNil not. self assert: (re search: 'abcd') isNil. self assert: (re search: 'abcd)') isNil. self assert: (re search: '(abcd') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test211 | re re2 | re _ Re on: '\( ( (?>[^()]+) | (?R) )* \) '. re beExtended; beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)pqr') isNil not. self assert: (re search: '1(abcd)(x(y)z)pqr') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test212 | re re2 | re _ Re on: '\( (?: (?>[^()]+) | (?R) ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(abcd)') isNil not. self assert: (re search: '(ab(xy)cd)') isNil not. self assert: (re search: '(a(b(c)d)e)') isNil not. self assert: (re search: '((ab))') isNil not. self assert: (re search: '()') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test213 | re re2 | re _ Re on: '\( (?: (?>[^()]+) | (?R) )? \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '()') isNil not. self assert: (re search: '12(abcde(fsh)xyz(foo(bar))lmno)89') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test214 | re re2 | re _ Re on: '\( ( (?>[^()]+) | (?R) )* \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test215 | re re2 | re _ Re on: '\( ( ( (?>[^()]+) | (?R) )* ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test216 | re re2 | re _ Re on: '\( (123)? ( ( (?>[^()]+) | (?R) )* ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)') isNil not. self assert: (re search: '(123ab(xy)cd)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test217 | re re2 | re _ Re on: '\( ( (123)? ( (?>[^()]+) | (?R) )* ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)') isNil not. self assert: (re search: '(123ab(xy)cd)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test218 | re re2 | re _ Re on: '\( (((((((((( ( (?>[^()]+) | (?R) )* )))))))))) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(xy)cd)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test219 | re re2 | re _ Re on: '\( ( ( (?>[^()<>]+) | ((?>[^()]+)) | (?R) )* ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(abcd(xyz

qrs)123)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test22 | re re2 | re _ Re on: 'cat|dog|elephant'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'this sentence eventually mentions a cat') isNil not. self assert: (re search: 'this sentences rambles on and on for a while and then reaches elephant') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test220 | re re2 | re _ Re on: '\( ( ( (?>[^()]+) | ((?R)) )* ) \) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '(ab(cd)ef)') isNil not. self assert: (re search: '(ab(cd(ef)gh)ij)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test221 | re re2 | re _ Re on: '^[[:alnum:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test222 | re re2 | re _ Re on: '^[[:alpha:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test223 | re re2 | re _ Re on: '^[[:ascii:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test224 | re re2 | re _ Re on: '^[[:cntrl:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test225 | re re2 | re _ Re on: '^[[:digit:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test226 | re re2 | re _ Re on: '^[[:graph:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test227 | re re2 | re _ Re on: '^[[:lower:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test228 | re re2 | re _ Re on: '^[[:print:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test229 | re re2 | re _ Re on: '^[[:punct:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test23 | re re2 | re _ Re on: 'cat|dog|elephant'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'this sentence eventually mentions a cat') isNil not. self assert: (re search: 'this sentences rambles on and on for a while and then reaches elephant') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test230 | re re2 | re _ Re on: '^[[:space:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test231 | re re2 | re _ Re on: '^[[:upper:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test232 | re re2 | re _ Re on: '^[[:xdigit:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test233 | re re2 | re _ Re on: '^[[:word:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test234 | re re2 | re _ Re on: '^[[:^cntrl:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test235 | re re2 | re _ Re on: '^[12[:^digit:]]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test236 | re re2 | re _ Re on: '[01[:alpha:]%]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:30'! testNewSuite2test237 | re | re _ Re on: '[[.ch.]]'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:30'! testNewSuite2test238 | re | re _ Re on: '[[=ch=]]'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:30'! testNewSuite2test239 | re | re _ Re on: '[[:rhubarb:]]'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test24 | re re2 | re _ Re on: 'cat|dog|elephant'. re beNotCaseSensitive; beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'this sentence eventually mentions a CAT cat') isNil not. self assert: (re search: 'this sentences rambles on and on for a while to elephant ElePhant') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test240 | re re2 | re _ Re on: '[[:upper:]]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'A') isNil not. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test241 | re re2 | re _ Re on: '[[:lower:]]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'A') isNil not. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test242 | re re2 | re _ Re on: '((?-i)[[:lower:]])[[:lower:]]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'aB') isNil not. self assert: (re search: 'Ab') isNil. self assert: (re search: 'AB') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:31'! testNewSuite2test243 | re | re _ Re on: '[\200-\410]'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:32'! testNewSuite2test244 | re | re _ Re on: '^(?(0)f|b)oo'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test245 | re re2 | re _ Re on: '(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '\O900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test246 | re re2 | re _ Re on: '(main(O)?)+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'mainmain') isNil not. self assert: (re search: 'mainOmain') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:31'! testNewSuite2test247 | re re2 | re _ Re on: ' End of testinput2 '. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 00:28'! testNewSuite2test248 | re | re _ Re on: 'This one''s here because of the large output vector needed.'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 00:28'! testNewSuite2test249 | re | re _ Re on: '(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '\O900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test25 | re re2 | re _ Re on: 'a|[bcd]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 00:28'! testNewSuite2test250 | re | re _ Re on: 'This one''s here because Perl does this differently and PCRE can''t at present'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 00:28'! testNewSuite2test251 | re | re _ Re on: '(main(O)?)+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'mainmain') isNil not. self assert: (re search: 'mainOmain') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 00:28'! testNewSuite2test252 | re | re _ Re on: ' End of testinput2 '. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test26 | re re2 | re _ Re on: '(a|[^\dZ])'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test27 | re re2 | re _ Re on: '(a|b)*[\s]'. re beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:32'! testNewSuite2test28 | re | re _ Re on: '(ab\2)'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:34'! testNewSuite2test29 | re | re _ Re on: '{4,5}abc'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test3 | re re2 | re _ Re on: '^abc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. re2 _ re copy beAnchored. self assert: (re2 search: 'abc') isNil not. self assert: (re search: 'defabc') isNil. re2 _ re copy beAnchored. self assert: (re2 search: 'defabc') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test30 | re re2 | re _ Re on: '(a)(b)(c)\2'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcb') isNil not. self assert: (re search: '\O0abcb') isNil not. self assert: (re search: '\O3abcb') isNil not. self assert: (re search: '\O6abcb') isNil not. self assert: (re search: '\O9abcb') isNil not. self assert: (re search: '\O12abcb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test31 | re re2 | re _ Re on: '(a)bc|(a)(b)\2'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: '\O0abc') isNil not. self assert: (re search: '\O3abc') isNil not. self assert: (re search: '\O6abc') isNil not. self assert: (re search: 'aba') isNil not. self assert: (re search: '\O0aba') isNil not. self assert: (re search: '\O3aba') isNil not. self assert: (re search: '\O6aba') isNil not. self assert: (re search: '\O9aba') isNil not. self assert: (re search: '\O12aba') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test32 | re re2 | re _ Re on: 'abc$'. re beDollarEndOnly. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'def'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:34'! testNewSuite2test33 | re | re _ Re on: '(a)(b)(c)(d)(e)\6'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test34 | re re2 | re _ Re on: 'the quick brown fox'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'this is a line with the quick brown fox') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test35 | re re2 | re _ Re on: 'the quick brown fox'. re beAnchored. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'this is a line with the quick brown fox') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:36'! testNewSuite2test36 | re | re _ Re on: 'ab(?z)cd'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test37 | re re2 | re _ Re on: '^abc|def'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdef') isNil not. re2 _ re copy beNotBeginningOfLine. self assert: (re2 search: 'abcdef') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test38 | re re2 | re _ Re on: '.*((abc)$|(def))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'defabc') isNil not. re2 _ re copy beNotEndOfLine. self assert: (re2 search: 'defabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test39 | re re2 | re _ Re on: 'abc'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test4 | re re2 | re _ Re on: 'a+bc'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test40 | re re2 | re _ Re on: '^abc|def'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdef') isNil not. re2 _ re copy beNotBeginningOfLine. self assert: (re2 search: 'abcdef') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test41 | re re2 | re _ Re on: '.*((abc)$|(def))'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'defabc') isNil not. re2 _ re copy beNotEndOfLine. self assert: (re2 search: 'defabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test42 | re re2 | re _ Re on: 'the quick brown fox'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'The Quick Brown Fox') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test43 | re re2 | re _ Re on: 'the quick brown fox'. re beStrangeOption; beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the quick brown fox') isNil not. self assert: (re search: 'The Quick Brown Fox') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test44 | re re2 | re _ Re on: 'abc.def'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'def'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test45 | re re2 | re _ Re on: 'abc$'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:36'! testNewSuite2test46 | re | re _ Re on: '(abc)\2'. re beStrangeOption. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 14:28'! testNewSuite2test47 | re | re _ Re on: '(abc\1)'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:37'! testNewSuite2test48 | re | re _ Re on: ')'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:37'! testNewSuite2test49 | re | re _ Re on: 'a[]b'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test5 | re re2 | re _ Re on: 'a*bc'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test50 | re re2 | re _ Re on: '[^aeiou ]{3,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'co-processors, and for') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test51 | re re2 | re _ Re on: '<.*>'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcghinop') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test52 | re re2 | re _ Re on: '<.*?>'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcghinop') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test53 | re re2 | re _ Re on: '<.*>'. re beNotGreedy. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcghinop') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test54 | re re2 | re _ Re on: '<.*>(?U)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcghinop') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test55 | re re2 | re _ Re on: '<.*?>'. re beNotGreedy. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcghinop') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test56 | re re2 | re _ Re on: '={3,}'. re beNotGreedy. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc========def') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test57 | re re2 | re _ Re on: '(?U)={3,}?'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc========def') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test58 | re re2 | re _ Re on: '(?^abc)'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'def'; nextPut: Character cr; nextPutAll: 'abc'])) isNil not. self assert: (re search: 'defabc') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:41'! testNewSuite2test92 | re | re _ Re on: '(?<=ab(c+)d)ef'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:41'! testNewSuite2test93 | re | re _ Re on: '(?<=ab(?<=c+)d)ef'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 13:41'! testNewSuite2test94 | re | re _ Re on: '(?<=ab(c|de)f)g'. self should: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test95 | re re2 | re _ Re on: 'The next three are in testinput2 because they have variable length branches'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test96 | re re2 | re _ Re on: '(?<=bullock|donkey)-cart'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'the bullock-cart') isNil not. self assert: (re search: 'a donkey-cart race') isNil not. self assert: (re search: 'cart') isNil. self assert: (re search: 'horse-and-cart') isNil. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test97 | re re2 | re _ Re on: '(?<=ab(?i)x|y|z)'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test98 | re re2 | re _ Re on: '(?>.*)(?<=(abcd)|(xyz))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'alphabetabcd') isNil not. self assert: (re search: 'endingxyz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite2' stamp: 'acg 8/11/2002 12:30'! testNewSuite2test99 | re re2 | re _ Re on: '(?<=ab(?i)x(?-i)y|(?i)z|b)ZZ'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abxyZZ') isNil not. self assert: (re search: 'abXyZZ') isNil not. self assert: (re search: 'ZZZ') isNil not. self assert: (re search: 'zZZ') isNil not. self assert: (re search: 'bZZ') isNil not. self assert: (re search: 'BZZ') isNil not. self assert: (re search: 'ZZ') isNil. self assert: (re search: 'abXYZZ') isNil. self assert: (re search: 'zzz') isNil. self assert: (re search: 'bzz') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test1 | re re2 | re _ Re on: '(?\d+))(\w)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '12345a') isNil not. self assert: (re search: '12345+') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test100 | re re2 | re _ Re on: 'a[^-b]c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'adc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:43'! testNewSuite3test101 | re | re _ Re on: 'a[^]b]c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'adc') isNil not. self assert: (re search: 'a-c') isNil not. self assert: (re search: 'a]c') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test102 | re re2 | re _ Re on: '\ba\b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-') isNil not. self assert: (re search: '-a') isNil not. self assert: (re search: '-a-') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test103 | re re2 | re _ Re on: '\by\b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xy') isNil. self assert: (re search: 'yz') isNil. self assert: (re search: 'xyz') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test104 | re re2 | re _ Re on: '\Ba\B'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-') isNil. self assert: (re search: '-a') isNil. self assert: (re search: '-a-') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test105 | re re2 | re _ Re on: '\By\b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xy') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test106 | re re2 | re _ Re on: '\by\B'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'yz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test107 | re re2 | re _ Re on: '\By\B'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xyz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test108 | re re2 | re _ Re on: '\w'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:45'! testNewSuite3test109 | re | re _ Re on: '\W'. self shouldnt: [re compile] raise: Error. self assert: (re search: '-') isNil not. self assert: (re search: 'a') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test11 | re re2 | re _ Re on: '(?>a+)b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test110 | re re2 | re _ Re on: 'a\sb'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 14:29'! testNewSuite3test111 | re | re _ Re on: 'a\Sb'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-b') isNil not. self assert: (re search: 'a b') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test112 | re re2 | re _ Re on: '\d'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:46'! testNewSuite3test113 | re | re _ Re on: '\D'. self shouldnt: [re compile] raise: Error. self assert: (re search: '-') isNil not. self assert: (re search: '1') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test114 | re re2 | re _ Re on: '[\w]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:46'! testNewSuite3test115 | re | re _ Re on: '[\W]'. self shouldnt: [re compile] raise: Error. self assert: (re search: '-') isNil not. self assert: (re search: 'a') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test116 | re re2 | re _ Re on: 'a[\s]b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:46'! testNewSuite3test117 | re | re _ Re on: 'a[\S]b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-b') isNil not. self assert: (re search: 'a b') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test118 | re re2 | re _ Re on: '[\d]'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:46'! testNewSuite3test119 | re | re _ Re on: '[\D]'. self shouldnt: [re compile] raise: Error. self assert: (re search: '-') isNil not. self assert: (re search: '1') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test12 | re re2 | re _ Re on: '((?>a+)b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test120 | re re2 | re _ Re on: 'ab|cd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test121 | re re2 | re _ Re on: '()ef'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'def') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test122 | re re2 | re _ Re on: '$b'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test123 | re re2 | re _ Re on: 'a\(b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a(b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test124 | re re2 | re _ Re on: 'a\(*b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'a((b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:47'! testNewSuite3test125 | re | re _ Re on: 'a\\b'. self shouldnt: [re compile] raise: Error. self assert: ('a\b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test126 | re re2 | re _ Re on: '((a))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test127 | re re2 | re _ Re on: '(a)b(c)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test128 | re re2 | re _ Re on: 'a+b+c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test129 | re re2 | re _ Re on: 'a{1,}b{1,}c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabbabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test13 | re re2 | re _ Re on: '(?>(a+))b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test130 | re re2 | re _ Re on: 'a.+?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test131 | re re2 | re _ Re on: '(a+|b)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test132 | re re2 | re _ Re on: '(a+|b){0,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test133 | re re2 | re _ Re on: '(a+|b)+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test134 | re re2 | re _ Re on: '(a+|b){1,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test135 | re re2 | re _ Re on: '(a+|b)?'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test136 | re re2 | re _ Re on: '(a+|b){0,1}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test137 | re re2 | re _ Re on: '[^ab]*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test138 | re re2 | re _ Re on: 'abc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'b') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test139 | re re2 | re _ Re on: '/a*/'. re beStrangeOption; beStrangeOption; beStrangeOption; beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test14 | re re2 | re _ Re on: '(?>b)+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaabbbccc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test140 | re re2 | re _ Re on: '([abc])*d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test141 | re re2 | re _ Re on: '([abc])*bcd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test142 | re re2 | re _ Re on: 'a|b|c|d|e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'e') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test143 | re re2 | re _ Re on: '(a|b|c|d|e)f'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ef') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test144 | re re2 | re _ Re on: 'abcd*efg'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdefg') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test145 | re re2 | re _ Re on: 'ab*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'xabyabbbz') isNil not. self assert: (re search: 'xayabbbz') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test146 | re re2 | re _ Re on: '(ab|cd)e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test147 | re re2 | re _ Re on: '[abhgefdc]ij'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'hij') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test148 | re re2 | re _ Re on: '^(ab|cd)e'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test149 | re re2 | re _ Re on: '(abc|)ef'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcdef') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test15 | re re2 | re _ Re on: '(?>a+|b+|c+)*c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaabbbbccccd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test150 | re re2 | re _ Re on: '(a|b)c*d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test151 | re re2 | re _ Re on: '(ab|ab*)bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test152 | re re2 | re _ Re on: 'a([bc]*)c*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test153 | re re2 | re _ Re on: 'a([bc]*)(c*d)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test154 | re re2 | re _ Re on: 'a([bc]+)(c*d)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test155 | re re2 | re _ Re on: 'a([bc]*)(c+d)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test156 | re re2 | re _ Re on: 'a[bcd]*dcdcde'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'adcdcde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test157 | re re2 | re _ Re on: 'a[bcd]+dcdcde'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcde') isNil. self assert: (re search: 'adcdcde') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test158 | re re2 | re _ Re on: '(ab|a)b*c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test159 | re re2 | re _ Re on: '((a)(b)c)(d)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test16 | re re2 | re _ Re on: '((?>[^()]+)|\([^()]*\))+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '((abc(ade)ufh()()x') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test160 | re re2 | re _ Re on: '[a-zA-Z_][a-zA-Z0-9_]*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'alpha') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test161 | re re2 | re _ Re on: '^a(bc+|b[eh])g|.h$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abh') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test162 | re re2 | re _ Re on: '(bc+d$|ef*g.|h?i(j|k))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'effgz') isNil not. self assert: (re search: 'ij') isNil not. self assert: (re search: 'reffgz') isNil not. self assert: (re search: 'effg') isNil. self assert: (re search: 'bcdd') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test163 | re re2 | re _ Re on: '((((((((((a))))))))))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test164 | re re2 | re _ Re on: '((((((((((a))))))))))\10'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test165 | re re2 | re _ Re on: '(((((((((a)))))))))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test166 | re re2 | re _ Re on: 'multiple words of text'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aa') isNil. self assert: (re search: 'uh-uh') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test167 | re re2 | re _ Re on: 'multiple words'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'multiple words, yeah') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test168 | re re2 | re _ Re on: '(.*)c(.*)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test169 | re re2 | re _ Re on: '\((.*), (.*)\)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '(a, b)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test17 | re re2 | re _ Re on: '\(((?>[^()]+)|\([^()]+\))+\)'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: '(abc)') isNil not. self assert: (re search: '(abc(def)xyz)') isNil not. self assert: (re search: '((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test170 | re re2 | re _ Re on: '[k]'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test171 | re re2 | re _ Re on: 'abcd'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test172 | re re2 | re _ Re on: 'a(bc)d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcd') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test173 | re re2 | re _ Re on: 'a[-]?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ac') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test174 | re re2 | re _ Re on: '(abc)\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test175 | re re2 | re _ Re on: '([a-c]*)\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcabc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:49'! testNewSuite3test176 | re | re _ Re on: '(a)|\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'ab') isNil not. self assert: (re search: 'x') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test177 | re re2 | re _ Re on: '(([a-c])b*?\2)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ababbbcbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test178 | re re2 | re _ Re on: '(([a-c])b*?\2){3}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ababbbcbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test179 | re re2 | re _ Re on: '((\3|b)\2(a)x)+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaxabaxbaaxbbax') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test18 | re re2 | re _ Re on: 'a(?-i)b'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'Ab') isNil. self assert: (re search: 'aB') isNil. self assert: (re search: 'AB') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test180 | re re2 | re _ Re on: '((\3|b)\2(a)){2,}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'bbaababbabaaaaabbaaaabba') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test181 | re re2 | re _ Re on: 'abc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. self assert: (re search: 'XABCY') isNil not. self assert: (re search: 'ABABC') isNil not. self assert: (re search: 'aaxabxbaxbbx') isNil. self assert: (re search: 'XBC') isNil. self assert: (re search: 'AXC') isNil. self assert: (re search: 'ABX') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test182 | re re2 | re _ Re on: 'ab*c'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test183 | re re2 | re _ Re on: 'ab*bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. self assert: (re search: 'ABBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test184 | re re2 | re _ Re on: 'ab*?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test185 | re re2 | re _ Re on: 'ab{0,}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test186 | re re2 | re _ Re on: 'ab+?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test187 | re re2 | re _ Re on: 'ab+bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil. self assert: (re search: 'ABQ') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test188 | re re2 | re _ Re on: 'ab{1,}bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test189 | re re2 | re _ Re on: 'ab+bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test19 | re re2 | re _ Re on: '(a (?x)b c)d e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a bcd e') isNil not. self assert: (re search: 'a b cd e') isNil. self assert: (re search: 'abcd e') isNil. self assert: (re search: 'a bcde') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test190 | re re2 | re _ Re on: 'ab{1,}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test191 | re re2 | re _ Re on: 'ab{1,3}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test192 | re re2 | re _ Re on: 'ab{3,4}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBBBC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test193 | re re2 | re _ Re on: 'ab{4,5}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABQ') isNil. self assert: (re search: 'ABBBBC') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test194 | re re2 | re _ Re on: 'ab??bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABBC') isNil not. self assert: (re search: 'ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test195 | re re2 | re _ Re on: 'ab{0,1}?bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test196 | re re2 | re _ Re on: 'ab??bc'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test197 | re re2 | re _ Re on: 'ab??c'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test198 | re re2 | re _ Re on: 'ab{0,1}?c'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test199 | re re2 | re _ Re on: '^abc$'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABC') isNil not. self assert: (re search: 'ABBBBC') isNil. self assert: (re search: 'ABCC') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test2 | re re2 | re _ Re on: '\w{3}(?a(?i)b+)+c'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aBbc') isNil not. self assert: (re search: 'aBBc') isNil not. self assert: (re search: 'Abc') isNil. self assert: (re search: 'abAb') isNil. self assert: (re search: 'abbC') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test270 | re re2 | re _ Re on: 'multiple words'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'MULTIPLE WORDS, YEAH') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test271 | re re2 | re _ Re on: '(.*)c(.*)'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABCDE') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test272 | re re2 | re _ Re on: '\((.*), (.*)\)'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: '(A, B)') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test273 | re re2 | re _ Re on: '[k]'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test274 | re re2 | re _ Re on: 'abcd'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABCD') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test275 | re re2 | re _ Re on: 'a(bc)d'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABCD') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test276 | re re2 | re _ Re on: 'a[-]?c'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'AC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test277 | re re2 | re _ Re on: '(abc)\1'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABCABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test278 | re re2 | re _ Re on: '([a-c]*)\1'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ABCABC') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test279 | re re2 | re _ Re on: 'a(?!!b).'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abad') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test28 | re re2 | re _ Re on: '(?=a(?i)b)\w\wc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'aBc') isNil not. self assert: (re search: 'Ab') isNil. self assert: (re search: 'abC') isNil. self assert: (re search: 'aBC') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test280 | re re2 | re _ Re on: 'a(?=d).'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abad') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test281 | re re2 | re _ Re on: 'a(?=c|d).'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abad') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test282 | re re2 | re _ Re on: 'a(?:b|c|d)(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ace') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test283 | re re2 | re _ Re on: 'a(?:b|c|d)*(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ace') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test284 | re re2 | re _ Re on: 'a(?:b|c|d)+?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ace') isNil not. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test285 | re re2 | re _ Re on: 'a(?:b|c|d)+(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test286 | re re2 | re _ Re on: 'a(?:b|c|d){2}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test287 | re re2 | re _ Re on: 'a(?:b|c|d){4,5}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test288 | re re2 | re _ Re on: 'a(?:b|c|d){4,5}?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test289 | re re2 | re _ Re on: '((foo)|(bar))*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'foobar') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test29 | re re2 | re _ Re on: '(?<=a(?i)b)(\w\w)c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abxxc') isNil not. self assert: (re search: 'aBxxc') isNil not. self assert: (re search: 'Abxxc') isNil. self assert: (re search: 'ABxxc') isNil. self assert: (re search: 'abxxC') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test290 | re re2 | re _ Re on: 'a(?:b|c|d){6,7}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test291 | re re2 | re _ Re on: 'a(?:b|c|d){6,7}?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test292 | re re2 | re _ Re on: 'a(?:b|c|d){5,6}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test293 | re re2 | re _ Re on: 'a(?:b|c|d){5,6}?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test294 | re re2 | re _ Re on: 'a(?:b|c|d){5,7}(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test295 | re re2 | re _ Re on: 'a(?:b|c|d){5,7}?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'acdbcdbe') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test296 | re re2 | re _ Re on: 'a(?:b|(c|e){1,2}?|d)+?(.)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ace') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test297 | re re2 | re _ Re on: '^(.+)?B'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'AB') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test298 | re re2 | re _ Re on: '^([^a-z])|(\^)$'. self shouldnt: [re compile] raise: Error. self assert: (re search: '.') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test299 | re re2 | re _ Re on: '^[<>]&'. self shouldnt: [re compile] raise: Error. self assert: (re search: '<&OUT') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test3 | re re2 | re _ Re on: '(?<=(foo)a)bar'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'fooabar') isNil not. self assert: (re search: 'bar') isNil. self assert: (re search: 'foobbar') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test30 | re re2 | re _ Re on: '(?:(a)|b)(?(1)A|B)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aA') isNil not. self assert: (re search: 'bB') isNil not. self assert: (re search: 'aB') isNil. self assert: (re search: 'bA') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test300 | re re2 | re _ Re on: '^(a\1?){4}$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaaaaaaaa') isNil not. self assert: (re search: 'AB') isNil. self assert: (re search: 'aaaaaaaaa') isNil. self assert: (re search: 'aaaaaaaaaaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test301 | re re2 | re _ Re on: '^(a(?(1)\1)){4}$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaaaaaaaa') isNil not. self assert: (re search: 'aaaaaaaaa') isNil. self assert: (re search: 'aaaaaaaaaaa') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test302 | re re2 | re _ Re on: '(?:(f)(o)(o)|(b)(a)(r))*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'foobar') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test303 | re re2 | re _ Re on: '(?<=a)b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'cb') isNil. self assert: (re search: 'b') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test304 | re re2 | re _ Re on: '(?a+)ab'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test397 | re re2 | re _ Re on: '(?>a+)b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test398 | re re2 | re _ Re on: '([[:]+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a:[b]:') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test399 | re re2 | re _ Re on: '([[=]+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a=[b]=') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test4 | re re2 | re _ Re on: '\Aabc\z'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'qqq'; nextPut: Character cr; nextPutAll: 'abc'; nextPut: Character cr; nextPutAll: 'zzz'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test40 | re re2 | re _ Re on: '((?i)blah)\s+(?i:\1)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'blah blah') isNil not. self assert: (re search: 'BLAH BLAH') isNil not. self assert: (re search: 'Blah Blah') isNil not. self assert: (re search: 'blaH blaH') isNil not. self assert: (re search: 'blah BLAH') isNil not. self assert: (re search: 'Blah blah') isNil not. self assert: (re search: 'blaH blah') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test400 | re re2 | re _ Re on: '([[.]+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a.[b].') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test401 | re re2 | re _ Re on: '((?>a+)b)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test402 | re re2 | re _ Re on: '(?>(a+))b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test403 | re re2 | re _ Re on: '((?>[^()]+)|\([^()]*\))+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '((abc(ade)ufh()()x') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test404 | re re2 | re _ Re on: 'a\Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaab') isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'; nextPut: Character cr])) isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test405 | re re2 | re _ Re on: 'b\Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'; nextPut: Character cr])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test406 | re re2 | re _ Re on: 'b\z'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test407 | re re2 | re _ Re on: 'b\Z'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test408 | re re2 | re _ Re on: 'b\z'. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'a'; nextPut: Character cr; nextPutAll: 'b'])) isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test409 | re re2 | re _ Re on: '^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'abc') isNil not. self assert: (re search: 'a-b') isNil not. self assert: (re search: '0-9') isNil not. self assert: (re search: 'a.b') isNil not. self assert: (re search: '5.6.7') isNil not. self assert: (re search: 'the.quick.brown.fox') isNil not. self assert: (re search: 'a100.b200.300c') isNil not. self assert: (re search: '12-ab.1245') isNil not. self assert: (re search: (String streamContents: [:s | s])) isNil. self assert: (re search: '.a') isNil. self assert: (re search: '-a') isNil. self assert: (re search: 'a-') isNil. self assert: (re search: 'a.') isNil. self assert: (re search: 'a_b') isNil. self assert: (re search: 'a.-') isNil. self assert: (re search: 'a..') isNil. self assert: (re search: 'ab..bc') isNil. self assert: (re search: 'the.quick.brown.fox-') isNil. self assert: (re search: 'the.quick.brown.fox.') isNil. self assert: (re search: 'the.quick.brown.fox_') isNil. self assert: (re search: 'the.quick.brown.fox+') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test41 | re re2 | re _ Re on: '(?>a*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'aa') isNil not. self assert: (re search: 'aaaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test410 | re re2 | re _ Re on: '(?>.*)(?<=(abcd|wxyz))'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'alphabetabcd') isNil not. self assert: (re search: 'endingwxyz') isNil not. self assert: (re search: 'a rather long string that doesn''t end with one of them') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:53'! testNewSuite3test411 | re | re _ Re on: 'word (?>(?:(?!!otherword)[a-zA-Z0-9]+ ){0,30})otherword'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark otherword') isNil not. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:54'! testNewSuite3test412 | re | re _ Re on: 'word (?>[a-zA-Z0-9]+ ){0,30}otherword'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope otherword') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test413 | re re2 | re _ Re on: '(?<=\d{3}(?!!999))foo'. self shouldnt: [re compile] raise: Error. self assert: (re search: '999foo') isNil not. self assert: (re search: '123999foo') isNil not. self assert: (re search: '123abcfoo') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test414 | re re2 | re _ Re on: '(?<=(?!!...999)\d{3})foo'. self shouldnt: [re compile] raise: Error. self assert: (re search: '999foo') isNil not. self assert: (re search: '123999foo') isNil not. self assert: (re search: '123abcfoo') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test415 | re re2 | re _ Re on: '(?<=\d{3}(?!!999)...)foo'. self shouldnt: [re compile] raise: Error. self assert: (re search: '123abcfoo') isNil not. self assert: (re search: '123456foo') isNil not. self assert: (re search: '123999foo') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test416 | re re2 | re _ Re on: '(?<=\d{3}...)(?\s*)=(?>\s*) # find Z)+|A)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ZABCDEFG') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test424 | re re2 | re _ Re on: '((?>)+|A)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ZABCDEFG') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test425 | re re2 | re _ Re on: 'a*'. re beStrangeOption. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test426 | re re2 | re _ Re on: '^[a-\d]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcde') isNil not. self assert: (re search: '-things') isNil not. self assert: (re search: '0digit') isNil not. self assert: (re search: 'bcdef') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test427 | re re2 | re _ Re on: '^[\d-a]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcde') isNil not. self assert: (re search: '-things') isNil not. self assert: (re search: '0digit') isNil not. self assert: (re search: 'bcdef') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:32'! testNewSuite3test428 | re re2 | re _ Re on: ' End of testinput3 '. re beStrangeOption; beStrangeOption; beStrangeOption; beStrangeOption; beStrangeOption; beStrangeOption; beStrangeOption. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test43 | re re2 | re _ Re on: '([a]*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'aaaaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test44 | re re2 | re _ Re on: '([ab]*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'ababab') isNil not. self assert: (re search: 'aaaabcde') isNil not. self assert: (re search: 'bbbb') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test45 | re re2 | re _ Re on: '([^a]*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'b') isNil not. self assert: (re search: 'bbbb') isNil not. self assert: (re search: 'aaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test46 | re re2 | re _ Re on: '([^ab]*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cccc') isNil not. self assert: (re search: 'abab') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test47 | re re2 | re _ Re on: '([a]*?)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'aaaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test48 | re re2 | re _ Re on: '([ab]*?)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'b') isNil not. self assert: (re search: 'abab') isNil not. self assert: (re search: 'baba') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test49 | re re2 | re _ Re on: '([^a]*?)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'b') isNil not. self assert: (re search: 'bbbb') isNil not. self assert: (re search: 'aaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 13:54'! testNewSuite3test5 | re | re _ Re on: '(?>.*/)foo'. self shouldnt: [re compile] raise: Error. self assert: (re search: '/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/foo') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test50 | re re2 | re _ Re on: '([^ab]*?)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'c') isNil not. self assert: (re search: 'cccc') isNil not. self assert: (re search: 'baba') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test51 | re re2 | re _ Re on: '(?>a*)*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a') isNil not. self assert: (re search: 'aaabcde') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test52 | re re2 | re _ Re on: '((?>a*))*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaaa') isNil not. self assert: (re search: 'aabbaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test53 | re re2 | re _ Re on: '((?>a*?))*'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aaaaa') isNil not. self assert: (re search: 'aabbaa') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test54 | re re2 | re _ Re on: '(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) '. re beExtended. self shouldnt: [re compile] raise: Error. self assert: (re search: '12-sep-98') isNil not. self assert: (re search: '12-09-98') isNil not. self assert: (re search: 'sep-12-98') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test55 | re re2 | re _ Re on: '(?<=(foo))bar\1'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'foobarfoo') isNil not. self assert: (re search: 'foobarfootling') isNil not. self assert: (re search: 'foobar') isNil. self assert: (re search: 'barfoo') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test56 | re re2 | re _ Re on: '(?i:saturday|sunday)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'saturday') isNil not. self assert: (re search: 'sunday') isNil not. self assert: (re search: 'Saturday') isNil not. self assert: (re search: 'Sunday') isNil not. self assert: (re search: 'SATURDAY') isNil not. self assert: (re search: 'SUNDAY') isNil not. self assert: (re search: 'SunDay') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test57 | re re2 | re _ Re on: '(a(?i)bc|BB)x'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcx') isNil not. self assert: (re search: 'aBCx') isNil not. self assert: (re search: 'bbx') isNil not. self assert: (re search: 'BBx') isNil not. self assert: (re search: 'abcX') isNil. self assert: (re search: 'aBCX') isNil. self assert: (re search: 'bbX') isNil. self assert: (re search: 'BBX') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test58 | re re2 | re _ Re on: '^([ab](?i)[cd]|[ef])'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ac') isNil not. self assert: (re search: 'aC') isNil not. self assert: (re search: 'bD') isNil not. self assert: (re search: 'elephant') isNil not. self assert: (re search: 'Europe') isNil not. self assert: (re search: 'frog') isNil not. self assert: (re search: 'France') isNil not. self assert: (re search: 'Africa') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test59 | re re2 | re _ Re on: '^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ab') isNil not. self assert: (re search: 'aBd') isNil not. self assert: (re search: 'xy') isNil not. self assert: (re search: 'xY') isNil not. self assert: (re search: 'zebra') isNil not. self assert: (re search: 'Zambesi') isNil not. self assert: (re search: 'aCD') isNil. self assert: (re search: 'XY') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test6 | re re2 | re _ Re on: '(?>.*/)foo'. self shouldnt: [re compile] raise: Error. self assert: (re search: '/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test60 | re re2 | re _ Re on: '(?<=foo\n)^bar'. re beMultiline. self shouldnt: [re compile] raise: Error. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'foo'; nextPut: Character cr; nextPutAll: 'bar'])) isNil not. self assert: (re search: 'bar') isNil. self assert: (re search: (String streamContents: [:s | s nextPutAll: 'baz'; nextPut: Character cr; nextPutAll: 'bar'])) isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test61 | re re2 | re _ Re on: '(?<=(?(\.\d\d[1-9]?))\d+'. self shouldnt: [re compile] raise: Error. self assert: (re search: '1.230003938') isNil not. self assert: (re search: '1.875000282') isNil not. self assert: (re search: '1.235') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test70 | re re2 | re _ Re on: '.{3,4}'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test71 | re re2 | re _ Re on: 'ab{0,}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test72 | re re2 | re _ Re on: 'ab+bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbc') isNil not. self assert: (re search: 'abc') isNil. self assert: (re search: 'abq') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test73 | re re2 | re _ Re on: 'ab{1,}bc'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test74 | re re2 | re _ Re on: 'ab+bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test75 | re re2 | re _ Re on: 'ab{1,}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test76 | re re2 | re _ Re on: 'ab{1,3}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test77 | re re2 | re _ Re on: 'ab{3,4}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbbbc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test78 | re re2 | re _ Re on: 'ab{4,5}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abq') isNil. self assert: (re search: 'abbbbc') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test79 | re re2 | re _ Re on: 'ab?bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abbc') isNil not. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test8 | re re2 | re _ Re on: '^((?>\w+)|(?>\s+))*$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'now is the time for all good men to come to the aid of the party') isNil not. self assert: (re search: 'this is not a line with only words and spaces!!') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test80 | re re2 | re _ Re on: 'ab{0,1}bc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test81 | re re2 | re _ Re on: 'ab?bc'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test82 | re re2 | re _ Re on: 'ab?c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test83 | re re2 | re _ Re on: 'ab{0,1}c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test84 | re re2 | re _ Re on: '^abc$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'abbbbc') isNil. self assert: (re search: 'abcc') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test85 | re re2 | re _ Re on: '^abc'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abcc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test86 | re re2 | re _ Re on: '^abc$'. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 14:02'! testNewSuite3test87 | re | re _ Re on: 'abc$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aabc') isNil not. self assert: (re search: 'aabc') isNil not. self assert: (re search: 'aabcd') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test88 | re re2 | re _ Re on: '^'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test89 | re re2 | re _ Re on: '$'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test9 | re re2 | re _ Re on: '(\d+)(\w)'. self shouldnt: [re compile] raise: Error. self assert: (re search: '12345a') isNil not. self assert: (re search: '12345+') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test90 | re re2 | re _ Re on: 'a.c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abc') isNil not. self assert: (re search: 'axc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test91 | re re2 | re _ Re on: 'a.*c'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'axyzc') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test92 | re re2 | re _ Re on: 'a[bc]d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'abd') isNil not. self assert: (re search: 'axyzd') isNil. self assert: (re search: 'abc') isNil. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test93 | re re2 | re _ Re on: 'a[b-d]e'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'ace') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test94 | re re2 | re _ Re on: 'a[b-d]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aac') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test95 | re re2 | re _ Re on: 'a[-b]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test96 | re re2 | re _ Re on: 'a[b-]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a-') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test97 | re re2 | re _ Re on: 'a]'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a]') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test98 | re re2 | re _ Re on: 'a[]]b'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'a]b') isNil not. ! ! !ReTest methodsFor: 'newTestSuite3' stamp: 'acg 8/11/2002 12:31'! testNewSuite3test99 | re re2 | re _ Re on: 'a[^bc]d'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'aed') isNil not. self assert: (re search: 'abd') isNil. self assert: (re search: 'abd') isNil. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test1 | re re2 | re _ Re on: '^[\w]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test10 | re re2 | re _ Re on: '(.+)\b(.+)'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil not. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test12 | re re2 | re _ Re on: 'cole'. re beNotCaseSensitive. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil not. self assert: (re search: 'cole') isNil. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test18 | re re2 | re _ Re on: ' End of testinput4 '. self shouldnt: [re compile] raise: Error. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test3 | re re2 | re _ Re on: '^[\w]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test4 | re re2 | re _ Re on: '^[\W]+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil not. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 14:08'! testNewSuit4test6 | re | re _ Re on: '[\b]'. self shouldnt: [re compile] raise: Error. self assert: (16r08 asCharacter asString) isNil not. self assert: (re search: 'a') isNil. ! ! !ReTest methodsFor: 'newTestSuite4' stamp: 'acg 8/11/2002 12:37'! testNewSuit4test8 | re re2 | re _ Re on: '^\w+'. self shouldnt: [re compile] raise: Error. self assert: (re search: 'cole') isNil. ! ! !String methodsFor: 'converting' stamp: 'acg 8/16/2002 22:48'! asRe ^Re on: self! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/3/2002 17:23'! asReDo: aBlock ^aBlock value: self asRe! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:34'! collectRe: aString "Answer the collection of my substrings matching aString" ^aString asRe collectFrom: self! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:34'! matchRe: aString "Answer whether the string is matched by the regular expression" ^(aString asRe search: self) isNil not! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:32'! reMatch: aString ^aString asRe search: self! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:32'! reMatch: aString andCollect: aBlock "Answer the collection of my substrings matching aString" ^aString asRe search: self andCollect: aBlock! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:33'! reMatch: aString andReplace: aBlock "Answer the collection of my substrings matching aString" ^aString asRe search: self andReplace: aBlock! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:33'! reMatch: aString from: fromInteger to: toInteger ^aString asRe search: self from: fromInteger to: toInteger! ! !String methodsFor: 'regular expressions' stamp: 'acg 8/4/2002 10:33'! reMatch: aString replace: aBlock "Answer the collection of my substrings matching aString" ^aString asRe search: aString andReplace: aBlock! ! ReTest class removeSelector: #buildTestNamed:from:! ReTest class removeSelector: #expandDataString:! ReTest class removeSelector: #expandParmList:! ReTest class removeSelector: #getDataFrom:! ReTest class removeSelector: #hasFailers:! ReTest class removeSelector: #install! ReTest class removeSelector: #install1! ReTest class removeSelector: #install2! ReTest class removeSelector: #install3! ReTest class removeSelector: #installNew1! ReTest class removeSelector: #installNew2! ReTest class removeSelector: #installNew3! ReTest class removeSelector: #installNew4! ReTest class removeSelector: #installNew5! ReTest class removeSelector: #installNew6! ReTest class removeSelector: #installTestNamed:in:from:! ReTest class removeSelector: #optionFor:! ReTest class removeSelector: #printDataArray:to:! ReTest class removeSelector: #testData2From:! ReTest class removeSelector: #testDataChunkFromFileStream:! ReTest class removeSelector: #testDataFrom:! ReTest class removeSelector: #testDataFromFileNamed:! RePattern initialize! ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/chartables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This file is automatically written by the dftables auxiliary program. If you edit it by hand, you might like to edit the Makefile to prevent its ever being regenerated. This file is #included in the compilation of pcre.c to build the default character tables which are used when no tables are passed to the compile function. */ static unsigned char pcre_default_tables[] = { /* This table is a lower casing table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table is a case flipping table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table contains bit maps for various character classes. Each map is 32 bytes long and the bits run from the least significant end of each byte. The classes that have their own maps are: space, xdigit, digit, upper, lower, word, graph print, punct, and cntrl. Other classes are built from combinations. */ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* This table identifies various classes of character by individual bits: 0x01 white space character 0x02 letter 0x04 decimal digit 0x08 hexadecimal digit 0x10 alphanumeric or '_' 0x80 regular expression metacharacter or binary zero */ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ 0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /* X - _ */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ /* End of chartables.c */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/config.h ================================================ /* config.h. Generated automatically by configure. */ /* On Unix systems config.in is converted by configure into config.h. PCRE is written in Standard C, but there are a few non-standard things it can cope with, allowing it to run on SunOS4 and other "close to standard" systems. On a non-Unix system you should just copy this file into config.h, and set up the macros the way you need them. You should normally change the definitions of HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because of the way autoconf works, these cannot be made the defaults. If your system has bcopy() and not memmove(), change the definition of HAVE_BCOPY instead of HAVE_MEMMOVE. If your system has neither bcopy() nor memmove(), leave them both as 0; an emulation function will be used. */ /* Define to empty if the keyword does not work. */ /* #undef const */ /* Define to `unsigned' if doesn't define size_t. */ /* #undef size_t */ /* The following two definitions are mainly for the benefit of SunOS4, which doesn't have the strerror() or memmove() functions that should be present in all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should normally be defined with the value 1 for other systems, but unfortunately we can't make this the default because "configure" files generated by autoconf will only change 0 to 1; they won't change 1 to 0 if the functions are not found. */ #define HAVE_STRERROR 1 #define HAVE_MEMMOVE 1 /* There are some non-Unix systems that don't even have bcopy(). If this macro is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of HAVE_BCOPY is not relevant. */ #define HAVE_BCOPY 1 /* The value of NEWLINE determines the newline character. The default is to leave it up to the compiler, but some sites want to force a particular value. On Unix systems, "configure" can be used to override this default. */ #ifndef NEWLINE #define NEWLINE '\n' #endif /* End */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/get.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See the file Tech.Notes for some information on the internals. Written by: Philip Hazel Copyright (c) 1997-2001 University of Cambridge ----------------------------------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. ----------------------------------------------------------------------------- */ /* This module contains some convenience functions for extracting substrings from the subject string after a regex match has succeeded. The original idea for these functions came from Scott Wimer . */ /* Include the internals header, which itself includes Standard C headers plus the external pcre header. */ #include "internal.h" /************************************************* * Copy captured string to given buffer * *************************************************/ /* This function copies a single captured substring into a given buffer. Note that we use memcpy() rather than strncpy() in case there are binary zeros in the string. Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringnumber the number of the required substring buffer where to put the substring size the size of the buffer Returns: if successful: the length of the copied string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) buffer too small PCRE_ERROR_NOSUBSTRING (-7) no such captured substring */ int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int size) { int yield; if (stringnumber < 0 || stringnumber >= stringcount) return PCRE_ERROR_NOSUBSTRING; stringnumber *= 2; yield = ovector[stringnumber+1] - ovector[stringnumber]; if (size < yield + 1) return PCRE_ERROR_NOMEMORY; memcpy(buffer, subject + ovector[stringnumber], yield); buffer[yield] = 0; return yield; } /************************************************* * Copy all captured strings to new store * *************************************************/ /* This function gets one chunk of store and builds a list of pointers and all of the captured substrings in it. A NULL pointer is put on the end of the list. Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) listptr set to point to the list of pointers Returns: if successful: 0 if not successful: PCRE_ERROR_NOMEMORY (-6) failed to get store */ int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr) { int i; int size = sizeof(char *); int double_count = stringcount * 2; char **stringlist; char *p; for (i = 0; i < double_count; i += 2) size += sizeof(char *) + ovector[i+1] - ovector[i] + 1; stringlist = (char **)(pcre_malloc)(size); if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; *listptr = (const char **)stringlist; p = (char *)(stringlist + stringcount + 1); for (i = 0; i < double_count; i += 2) { int len = ovector[i+1] - ovector[i]; memcpy(p, subject + ovector[i], len); *stringlist++ = p; p += len; *p++ = 0; } *stringlist = NULL; return 0; } /************************************************* * Free store obtained by get_substring_list * *************************************************/ /* This function exists for the benefit of people calling PCRE from non-C programs that can call its functions, but not free() or (pcre_free)() directly. Argument: the result of a previous pcre_get_substring_list() Returns: nothing */ void pcre_free_substring_list(const char **pointer) { (pcre_free)((void *)pointer); } /************************************************* * Copy captured string to new store * *************************************************/ /* This function copies a single captured substring into a piece of new store Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringnumber the number of the required substring stringptr where to put a pointer to the substring Returns: if successful: the length of the string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) failed to get store PCRE_ERROR_NOSUBSTRING (-7) substring not present */ int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr) { int yield; char *substring; if (stringnumber < 0 || stringnumber >= stringcount) return PCRE_ERROR_NOSUBSTRING; stringnumber *= 2; yield = ovector[stringnumber+1] - ovector[stringnumber]; substring = (char *)(pcre_malloc)(yield + 1); if (substring == NULL) return PCRE_ERROR_NOMEMORY; memcpy(substring, subject + ovector[stringnumber], yield); substring[yield] = 0; *stringptr = substring; return yield; } /************************************************* * Free store obtained by get_substring * *************************************************/ /* This function exists for the benefit of people calling PCRE from non-C programs that can call its functions, but not free() or (pcre_free)() directly. Argument: the result of a previous pcre_get_substring() Returns: nothing */ void pcre_free_substring(const char *pointer) { (pcre_free)((void *)pointer); } /* End of get.c */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/internal.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See the file Tech.Notes for some information on the internals. Written by: Philip Hazel Copyright (c) 1997-2001 University of Cambridge ----------------------------------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. ----------------------------------------------------------------------------- */ /* This header contains definitions that are shared between the different modules, but which are not relevant to the outside. */ /* Get the definitions provided by running "configure" */ #define NEWLINE '\r' #define SQUEAK_PLUGIN #include "config.h" /* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY is set. Otherwise, include an emulating function for those systems that have neither (there some non-Unix environments where this is the case). This assumes that all calls to memmove are moving strings upwards in store, which is the case in PCRE. */ #if ! HAVE_MEMMOVE #undef memmove /* some systems may have a macro */ #if HAVE_BCOPY #define memmove(a, b, c) bcopy(b, a, c) #else void * pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) { int i; dest += n; src += n; for (i = 0; i < n; ++i) *(--dest) = *(--src); } #define memmove(a, b, c) pcre_memmove(a, b, c) #endif #endif /* Standard C headers plus the external interface definition */ #include #include #include #include #include #include #include "pcre.h" /* In case there is no definition of offsetof() provided - though any proper Standard C system should have one. */ #ifndef offsetof #define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) #endif /* These are the public options that can change during matching. */ #define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) /* Private options flags start at the most significant end of the four bytes, but skip the top bit so we can use ints for convenience without getting tangled with negative values. The public options defined in pcre.h start at the least significant end. Make sure they don't overlap, though now that we have expanded to four bytes there is plenty of space. */ #define PCRE_FIRSTSET 0x40000000 /* first_char is set */ #define PCRE_REQCHSET 0x20000000 /* req_char is set */ #define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ #define PCRE_INGROUP 0x08000000 /* compiling inside a group */ #define PCRE_ICHANGED 0x04000000 /* i option changes within regex */ /* Options for the "extra" block produced by pcre_study(). */ #define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ /* Masks for identifying the public options which are permitted at compile time, run time or study time, respectively. */ #define PUBLIC_OPTIONS \ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8) #define PUBLIC_EXEC_OPTIONS \ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY) #define PUBLIC_STUDY_OPTIONS 0 /* None defined */ /* Magic number to provide a small check against being handed junk. */ #define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ /* Miscellaneous definitions */ typedef int BOOL; /* tpr - needed to avoid clash with prevous defn in system headers */ #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif /* Escape items that are just an encoding of a particular data value. Note that ESC_N is defined as yet another macro, which is set in config.h to either \n (the default) or \r (which some people want). */ #ifndef ESC_E #define ESC_E 27 #endif #ifndef ESC_F #define ESC_F '\f' #endif #ifndef ESC_N #define ESC_N NEWLINE #endif #ifndef ESC_R #define ESC_R '\r' #endif #ifndef ESC_T #define ESC_T '\t' #endif /* These are escaped items that aren't just an encoding of a particular data value such as \n. They must have non-zero values, as check_escape() returns their negation. Also, they must appear in the same order as in the opcode definitions below, up to ESC_z. The final one must be ESC_REF as subsequent values are used for \1, \2, \3, etc. There is a test in the code for an escape greater than ESC_b and less than ESC_Z to detect the types that may be repeated. If any new escapes are put in-between that don't consume a character, that code will have to change. */ enum { ESC_A = 1, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_Z, ESC_z, ESC_REF }; /* Opcode table: OP_BRA must be last, as all values >= it are used for brackets that extract substrings. Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in order to the list of escapes immediately above. */ enum { OP_END, /* End of pattern */ /* Values corresponding to backslashed metacharacters */ OP_SOD, /* Start of data: \A */ OP_NOT_WORD_BOUNDARY, /* \B */ OP_WORD_BOUNDARY, /* \b */ OP_NOT_DIGIT, /* \D */ OP_DIGIT, /* \d */ OP_NOT_WHITESPACE, /* \S */ OP_WHITESPACE, /* \s */ OP_NOT_WORDCHAR, /* \W */ OP_WORDCHAR, /* \w */ OP_EODN, /* End of data or \n at end of data: \Z. */ OP_EOD, /* End of data: \z */ OP_OPT, /* Set runtime options */ OP_CIRC, /* Start of line - varies with multiline switch */ OP_DOLL, /* End of line - varies with multiline switch */ OP_ANY, /* Match any character */ OP_CHARS, /* Match string of characters */ OP_NOT, /* Match anything but the following char */ OP_STAR, /* The maximizing and minimizing versions of */ OP_MINSTAR, /* all these opcodes must come in pairs, with */ OP_PLUS, /* the minimizing one second. */ OP_MINPLUS, /* This first set applies to single characters */ OP_QUERY, OP_MINQUERY, OP_UPTO, /* From 0 to n matches */ OP_MINUPTO, OP_EXACT, /* Exactly n matches */ OP_NOTSTAR, /* The maximizing and minimizing versions of */ OP_NOTMINSTAR, /* all these opcodes must come in pairs, with */ OP_NOTPLUS, /* the minimizing one second. */ OP_NOTMINPLUS, /* This first set applies to "not" single characters */ OP_NOTQUERY, OP_NOTMINQUERY, OP_NOTUPTO, /* From 0 to n matches */ OP_NOTMINUPTO, OP_NOTEXACT, /* Exactly n matches */ OP_TYPESTAR, /* The maximizing and minimizing versions of */ OP_TYPEMINSTAR, /* all these opcodes must come in pairs, with */ OP_TYPEPLUS, /* the minimizing one second. These codes must */ OP_TYPEMINPLUS, /* be in exactly the same order as those above. */ OP_TYPEQUERY, /* This set applies to character types such as \d */ OP_TYPEMINQUERY, OP_TYPEUPTO, /* From 0 to n matches */ OP_TYPEMINUPTO, OP_TYPEEXACT, /* Exactly n matches */ OP_CRSTAR, /* The maximizing and minimizing versions of */ OP_CRMINSTAR, /* all these opcodes must come in pairs, with */ OP_CRPLUS, /* the minimizing one second. These codes must */ OP_CRMINPLUS, /* be in exactly the same order as those above. */ OP_CRQUERY, /* These are for character classes and back refs */ OP_CRMINQUERY, OP_CRRANGE, /* These are different to the three seta above. */ OP_CRMINRANGE, OP_CLASS, /* Match a character class */ OP_REF, /* Match a back reference */ OP_RECURSE, /* Match this pattern recursively */ OP_ALT, /* Start of alternation */ OP_KET, /* End of group that doesn't have an unbounded repeat */ OP_KETRMAX, /* These two must remain together and in this */ OP_KETRMIN, /* order. They are for groups the repeat for ever. */ /* The assertions must come before ONCE and COND */ OP_ASSERT, /* Positive lookahead */ OP_ASSERT_NOT, /* Negative lookahead */ OP_ASSERTBACK, /* Positive lookbehind */ OP_ASSERTBACK_NOT, /* Negative lookbehind */ OP_REVERSE, /* Move pointer back - used in lookbehind assertions */ /* ONCE and COND must come after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. */ OP_ONCE, /* Once matched, don't back up into the subpattern */ OP_COND, /* Conditional group */ OP_CREF, /* Used to hold an extraction string number (cond ref) */ OP_BRAZERO, /* These two must remain together and in this */ OP_BRAMINZERO, /* order. */ OP_BRANUMBER, /* Used for extracting brackets whose number is greater than can fit into an opcode. */ OP_BRA /* This and greater values are used for brackets that extract substrings up to a basic limit. After that, use is made of OP_BRANUMBER. */ }; /* The highest extraction number before we have to start using additional bytes. (Originally PCRE didn't have support for extraction counts highter than this number.) The value is limited by the number of opcodes left after OP_BRA, i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional opcodes. */ #define EXTRACT_BASIC_MAX 150 /* The texts of compile-time error messages are defined as macros here so that they can be accessed by the POSIX wrapper and converted into error codes. Yes, I could have used error codes in the first place, but didn't feel like changing just to accommodate the POSIX wrapper. */ #define ERR1 "\\ at end of pattern" #define ERR2 "\\c at end of pattern" #define ERR3 "unrecognized character follows \\" #define ERR4 "numbers out of order in {} quantifier" #define ERR5 "number too big in {} quantifier" #define ERR6 "missing terminating ] for character class" #define ERR7 "invalid escape sequence in character class" #define ERR8 "range out of order in character class" #define ERR9 "nothing to repeat" #define ERR10 "operand of unlimited repeat could match the empty string" #define ERR11 "internal error: unexpected repeat" #define ERR12 "unrecognized character after (?" #define ERR13 "unused error" #define ERR14 "missing )" #define ERR15 "back reference to non-existent subpattern" #define ERR16 "erroffset passed as NULL" #define ERR17 "unknown option bit(s) set" #define ERR18 "missing ) after comment" #define ERR19 "parentheses nested too deeply" #define ERR20 "regular expression too large" #define ERR21 "failed to get memory" #define ERR22 "unmatched parentheses" #define ERR23 "internal error: code overflow" #define ERR24 "unrecognized character after (?<" #define ERR25 "lookbehind assertion is not fixed length" #define ERR26 "malformed number after (?(" #define ERR27 "conditional group contains more than two branches" #define ERR28 "assertion expected after (?(" #define ERR29 "(?p must be followed by )" #define ERR30 "unknown POSIX class name" #define ERR31 "POSIX collating elements are not supported" #define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support" #define ERR33 "characters with values > 255 are not yet supported in classes" #define ERR34 "character value in \\x{...} sequence is too large" #define ERR35 "invalid condition (?(0)" /* All character handling must be done as unsigned characters. Otherwise there are problems with top-bit-set characters and functions such as isspace(). However, we leave the interface to the outside world as char *, because that should make things easier for callers. We define a short type for unsigned char to save lots of typing. I tried "uchar", but it causes problems on Digital Unix, where it is defined in sys/types, so use "uschar" instead. */ typedef unsigned char uschar; /* The real format of the start of the pcre block; the actual code vector runs on as long as necessary after the end. */ typedef struct real_pcre { unsigned long int magic_number; size_t size; const unsigned char *tables; unsigned long int options; unsigned short int top_bracket; unsigned short int top_backref; uschar first_char; uschar req_char; uschar code[1]; } real_pcre; /* The real format of the extra block returned by pcre_study(). */ typedef struct real_pcre_extra { uschar options; uschar start_bits[32]; } real_pcre_extra; /* Structure for passing "static" information around between the functions doing the compiling, so that they are thread-safe. */ typedef struct compile_data { const uschar *lcc; /* Points to lower casing table */ const uschar *fcc; /* Points to case-flipping table */ const uschar *cbits; /* Points to character type table */ const uschar *ctypes; /* Points to table of type maps */ } compile_data; /* Structure for passing "static" information around between the functions doing the matching, so that they are thread-safe. */ typedef struct match_data { int errorcode; /* As it says */ int *offset_vector; /* Offset vector */ int offset_end; /* One past the end */ int offset_max; /* The maximum usable for return data */ const uschar *lcc; /* Points to lower casing table */ const uschar *ctypes; /* Points to table of type maps */ BOOL offset_overflow; /* Set if too many extractions */ BOOL notbol; /* NOTBOL flag */ BOOL noteol; /* NOTEOL flag */ BOOL utf8; /* UTF8 flag */ BOOL endonly; /* Dollar not before final \n */ BOOL notempty; /* Empty string match not wanted */ const uschar *start_pattern; /* For use when recursing */ const uschar *start_subject; /* Start of the subject string */ const uschar *end_subject; /* End of the subject string */ const uschar *start_match; /* Start of this match attempt */ const uschar *end_match_ptr; /* Subject position at end match */ int end_offset_top; /* Highwater mark at end of match */ } match_data; /* Bit definitions for entries in the pcre_ctypes table. */ #define ctype_space 0x01 #define ctype_letter 0x02 #define ctype_digit 0x04 #define ctype_xdigit 0x08 #define ctype_word 0x10 /* alphameric or '_' */ #define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ /* Offsets for the bitmap tables in pcre_cbits. Each table contains a set of bits for a class map. Some classes are built by combining these tables. */ #define cbit_space 0 /* [:space:] or \s */ #define cbit_xdigit 32 /* [:xdigit:] */ #define cbit_digit 64 /* [:digit:] or \d */ #define cbit_upper 96 /* [:upper:] */ #define cbit_lower 128 /* [:lower:] */ #define cbit_word 160 /* [:word:] or \w */ #define cbit_graph 192 /* [:graph:] */ #define cbit_print 224 /* [:print:] */ #define cbit_punct 256 /* [:punct:] */ #define cbit_cntrl 288 /* [:cntrl:] */ #define cbit_length 320 /* Length of the cbits table */ /* Offsets of the various tables from the base tables pointer, and total length. */ #define lcc_offset 0 #define fcc_offset 256 #define cbits_offset 512 #define ctypes_offset (cbits_offset + cbit_length) #define tables_length (ctypes_offset + 256) /* End of internal.h */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/oldInternal.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See the file Tech.Notes for some information on the internals. Written by: Philip Hazel Copyright (c) 1997-2001 University of Cambridge ----------------------------------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. ----------------------------------------------------------------------------- */ /* This header contains definitions that are shared between the different modules, but which are not relevant to the outside. */ /* Get the definitions provided by running "configure" */ #define NEWLINE '\r' #define SQUEAK_PLUGIN #include "config.h" /* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY is set. Otherwise, include an emulating function for those systems that have neither (there some non-Unix environments where this is the case). This assumes that all calls to memmove are moving strings upwards in store, which is the case in PCRE. */ #if ! HAVE_MEMMOVE #undef memmove /* some systems may have a macro */ #if HAVE_BCOPY #define memmove(a, b, c) bcopy(b, a, c) #else void * pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) { int i; dest += n; src += n; for (i = 0; i < n; ++i) *(--dest) = *(--src); } #define memmove(a, b, c) pcre_memmove(a, b, c) #endif #endif /* Standard C headers plus the external interface definition */ #include #include #include #include #include #include #include "pcre.h" /* In case there is no definition of offsetof() provided - though any proper Standard C system should have one. */ #ifndef offsetof #define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) #endif /* These are the public options that can change during matching. */ #define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) /* Private options flags start at the most significant end of the four bytes, but skip the top bit so we can use ints for convenience without getting tangled with negative values. The public options defined in pcre.h start at the least significant end. Make sure they don't overlap, though now that we have expanded to four bytes there is plenty of space. */ #define PCRE_FIRSTSET 0x40000000 /* first_char is set */ #define PCRE_REQCHSET 0x20000000 /* req_char is set */ #define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ #define PCRE_INGROUP 0x08000000 /* compiling inside a group */ #define PCRE_ICHANGED 0x04000000 /* i option changes within regex */ /* Options for the "extra" block produced by pcre_study(). */ #define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ /* Masks for identifying the public options which are permitted at compile time, run time or study time, respectively. */ #define PUBLIC_OPTIONS \ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8) #define PUBLIC_EXEC_OPTIONS \ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY) #define PUBLIC_STUDY_OPTIONS 0 /* None defined */ /* Magic number to provide a small check against being handed junk. */ #define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ /* Miscellaneous definitions */ typedef int BOOL; #define FALSE 0 #define TRUE 1 /* Escape items that are just an encoding of a particular data value. Note that ESC_N is defined as yet another macro, which is set in config.h to either \n (the default) or \r (which some people want). */ #ifndef ESC_E #define ESC_E 27 #endif #ifndef ESC_F #define ESC_F '\f' #endif #ifndef ESC_N #define ESC_N NEWLINE #endif #ifndef ESC_R #define ESC_R '\r' #endif #ifndef ESC_T #define ESC_T '\t' #endif /* These are escaped items that aren't just an encoding of a particular data value such as \n. They must have non-zero values, as check_escape() returns their negation. Also, they must appear in the same order as in the opcode definitions below, up to ESC_z. The final one must be ESC_REF as subsequent values are used for \1, \2, \3, etc. There is a test in the code for an escape greater than ESC_b and less than ESC_Z to detect the types that may be repeated. If any new escapes are put in-between that don't consume a character, that code will have to change. */ enum { ESC_A = 1, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_Z, ESC_z, ESC_REF }; /* Opcode table: OP_BRA must be last, as all values >= it are used for brackets that extract substrings. Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in order to the list of escapes immediately above. */ enum { OP_END, /* End of pattern */ /* Values corresponding to backslashed metacharacters */ OP_SOD, /* Start of data: \A */ OP_NOT_WORD_BOUNDARY, /* \B */ OP_WORD_BOUNDARY, /* \b */ OP_NOT_DIGIT, /* \D */ OP_DIGIT, /* \d */ OP_NOT_WHITESPACE, /* \S */ OP_WHITESPACE, /* \s */ OP_NOT_WORDCHAR, /* \W */ OP_WORDCHAR, /* \w */ OP_EODN, /* End of data or \n at end of data: \Z. */ OP_EOD, /* End of data: \z */ OP_OPT, /* Set runtime options */ OP_CIRC, /* Start of line - varies with multiline switch */ OP_DOLL, /* End of line - varies with multiline switch */ OP_ANY, /* Match any character */ OP_CHARS, /* Match string of characters */ OP_NOT, /* Match anything but the following char */ OP_STAR, /* The maximizing and minimizing versions of */ OP_MINSTAR, /* all these opcodes must come in pairs, with */ OP_PLUS, /* the minimizing one second. */ OP_MINPLUS, /* This first set applies to single characters */ OP_QUERY, OP_MINQUERY, OP_UPTO, /* From 0 to n matches */ OP_MINUPTO, OP_EXACT, /* Exactly n matches */ OP_NOTSTAR, /* The maximizing and minimizing versions of */ OP_NOTMINSTAR, /* all these opcodes must come in pairs, with */ OP_NOTPLUS, /* the minimizing one second. */ OP_NOTMINPLUS, /* This first set applies to "not" single characters */ OP_NOTQUERY, OP_NOTMINQUERY, OP_NOTUPTO, /* From 0 to n matches */ OP_NOTMINUPTO, OP_NOTEXACT, /* Exactly n matches */ OP_TYPESTAR, /* The maximizing and minimizing versions of */ OP_TYPEMINSTAR, /* all these opcodes must come in pairs, with */ OP_TYPEPLUS, /* the minimizing one second. These codes must */ OP_TYPEMINPLUS, /* be in exactly the same order as those above. */ OP_TYPEQUERY, /* This set applies to character types such as \d */ OP_TYPEMINQUERY, OP_TYPEUPTO, /* From 0 to n matches */ OP_TYPEMINUPTO, OP_TYPEEXACT, /* Exactly n matches */ OP_CRSTAR, /* The maximizing and minimizing versions of */ OP_CRMINSTAR, /* all these opcodes must come in pairs, with */ OP_CRPLUS, /* the minimizing one second. These codes must */ OP_CRMINPLUS, /* be in exactly the same order as those above. */ OP_CRQUERY, /* These are for character classes and back refs */ OP_CRMINQUERY, OP_CRRANGE, /* These are different to the three seta above. */ OP_CRMINRANGE, OP_CLASS, /* Match a character class */ OP_REF, /* Match a back reference */ OP_RECURSE, /* Match this pattern recursively */ OP_ALT, /* Start of alternation */ OP_KET, /* End of group that doesn't have an unbounded repeat */ OP_KETRMAX, /* These two must remain together and in this */ OP_KETRMIN, /* order. They are for groups the repeat for ever. */ /* The assertions must come before ONCE and COND */ OP_ASSERT, /* Positive lookahead */ OP_ASSERT_NOT, /* Negative lookahead */ OP_ASSERTBACK, /* Positive lookbehind */ OP_ASSERTBACK_NOT, /* Negative lookbehind */ OP_REVERSE, /* Move pointer back - used in lookbehind assertions */ /* ONCE and COND must come after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. */ OP_ONCE, /* Once matched, don't back up into the subpattern */ OP_COND, /* Conditional group */ OP_CREF, /* Used to hold an extraction string number (cond ref) */ OP_BRAZERO, /* These two must remain together and in this */ OP_BRAMINZERO, /* order. */ OP_BRANUMBER, /* Used for extracting brackets whose number is greater than can fit into an opcode. */ OP_BRA /* This and greater values are used for brackets that extract substrings up to a basic limit. After that, use is made of OP_BRANUMBER. */ }; /* The highest extraction number before we have to start using additional bytes. (Originally PCRE didn't have support for extraction counts highter than this number.) The value is limited by the number of opcodes left after OP_BRA, i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional opcodes. */ #define EXTRACT_BASIC_MAX 150 /* The texts of compile-time error messages are defined as macros here so that they can be accessed by the POSIX wrapper and converted into error codes. Yes, I could have used error codes in the first place, but didn't feel like changing just to accommodate the POSIX wrapper. */ #define ERR1 "\\ at end of pattern" #define ERR2 "\\c at end of pattern" #define ERR3 "unrecognized character follows \\" #define ERR4 "numbers out of order in {} quantifier" #define ERR5 "number too big in {} quantifier" #define ERR6 "missing terminating ] for character class" #define ERR7 "invalid escape sequence in character class" #define ERR8 "range out of order in character class" #define ERR9 "nothing to repeat" #define ERR10 "operand of unlimited repeat could match the empty string" #define ERR11 "internal error: unexpected repeat" #define ERR12 "unrecognized character after (?" #define ERR13 "unused error" #define ERR14 "missing )" #define ERR15 "back reference to non-existent subpattern" #define ERR16 "erroffset passed as NULL" #define ERR17 "unknown option bit(s) set" #define ERR18 "missing ) after comment" #define ERR19 "parentheses nested too deeply" #define ERR20 "regular expression too large" #define ERR21 "failed to get memory" #define ERR22 "unmatched parentheses" #define ERR23 "internal error: code overflow" #define ERR24 "unrecognized character after (?<" #define ERR25 "lookbehind assertion is not fixed length" #define ERR26 "malformed number after (?(" #define ERR27 "conditional group contains more than two branches" #define ERR28 "assertion expected after (?(" #define ERR29 "(?p must be followed by )" #define ERR30 "unknown POSIX class name" #define ERR31 "POSIX collating elements are not supported" #define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support" #define ERR33 "characters with values > 255 are not yet supported in classes" #define ERR34 "character value in \\x{...} sequence is too large" #define ERR35 "invalid condition (?(0)" /* All character handling must be done as unsigned characters. Otherwise there are problems with top-bit-set characters and functions such as isspace(). However, we leave the interface to the outside world as char *, because that should make things easier for callers. We define a short type for unsigned char to save lots of typing. I tried "uchar", but it causes problems on Digital Unix, where it is defined in sys/types, so use "uschar" instead. */ typedef unsigned char uschar; /* The real format of the start of the pcre block; the actual code vector runs on as long as necessary after the end. */ typedef struct real_pcre { unsigned long int magic_number; size_t size; const unsigned char *tables; unsigned long int options; unsigned short int top_bracket; unsigned short int top_backref; uschar first_char; uschar req_char; uschar code[1]; } real_pcre; /* The real format of the extra block returned by pcre_study(). */ typedef struct real_pcre_extra { uschar options; uschar start_bits[32]; } real_pcre_extra; /* Structure for passing "static" information around between the functions doing the compiling, so that they are thread-safe. */ typedef struct compile_data { const uschar *lcc; /* Points to lower casing table */ const uschar *fcc; /* Points to case-flipping table */ const uschar *cbits; /* Points to character type table */ const uschar *ctypes; /* Points to table of type maps */ } compile_data; /* Structure for passing "static" information around between the functions doing the matching, so that they are thread-safe. */ typedef struct match_data { int errorcode; /* As it says */ int *offset_vector; /* Offset vector */ int offset_end; /* One past the end */ int offset_max; /* The maximum usable for return data */ const uschar *lcc; /* Points to lower casing table */ const uschar *ctypes; /* Points to table of type maps */ BOOL offset_overflow; /* Set if too many extractions */ BOOL notbol; /* NOTBOL flag */ BOOL noteol; /* NOTEOL flag */ BOOL utf8; /* UTF8 flag */ BOOL endonly; /* Dollar not before final \n */ BOOL notempty; /* Empty string match not wanted */ const uschar *start_pattern; /* For use when recursing */ const uschar *start_subject; /* Start of the subject string */ const uschar *end_subject; /* End of the subject string */ const uschar *start_match; /* Start of this match attempt */ const uschar *end_match_ptr; /* Subject position at end match */ int end_offset_top; /* Highwater mark at end of match */ } match_data; /* Bit definitions for entries in the pcre_ctypes table. */ #define ctype_space 0x01 #define ctype_letter 0x02 #define ctype_digit 0x04 #define ctype_xdigit 0x08 #define ctype_word 0x10 /* alphameric or '_' */ #define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ /* Offsets for the bitmap tables in pcre_cbits. Each table contains a set of bits for a class map. Some classes are built by combining these tables. */ #define cbit_space 0 /* [:space:] or \s */ #define cbit_xdigit 32 /* [:xdigit:] */ #define cbit_digit 64 /* [:digit:] or \d */ #define cbit_upper 96 /* [:upper:] */ #define cbit_lower 128 /* [:lower:] */ #define cbit_word 160 /* [:word:] or \w */ #define cbit_graph 192 /* [:graph:] */ #define cbit_print 224 /* [:print:] */ #define cbit_punct 256 /* [:punct:] */ #define cbit_cntrl 288 /* [:cntrl:] */ #define cbit_length 320 /* Length of the cbits table */ /* Offsets of the various tables from the base tables pointer, and total length. */ #define lcc_offset 0 #define fcc_offset 256 #define cbits_offset 512 #define ctypes_offset (cbits_offset + cbit_length) #define tables_length (ctypes_offset + 256) /* End of internal.h */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/pcre.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See the file Tech.Notes for some information on the internals. Written by: Philip Hazel Copyright (c) 1997-2001 University of Cambridge ----------------------------------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. ----------------------------------------------------------------------------- */ /* Define DEBUG to get debugging output on stdout. */ /* #define DEBUG */ /* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef inline, and there are *still* stupid compilers about that don't like indented pre-processor statements. I suppose it's only been 10 years... */ #ifdef DEBUG #define DPRINTF(p) printf p #else #define DPRINTF(p) /*nothing*/ #endif /* Include the internals header, which itself includes Standard C headers plus the external pcre header. */ #include "internal.h" /* Allow compilation as C++ source code, should anybody want to do that. */ #ifdef __cplusplus #define class pcre_class #endif /* Maximum number of items on the nested bracket stacks at compile time. This applies to the nesting of all kinds of parentheses. It does not limit un-nested, non-capturing parentheses. This number can be made bigger if necessary - it is used to dimension one int and one unsigned char vector at compile time. */ #define BRASTACK_SIZE 200 /* The number of bytes in a literal character string above which we can't add any more is different when UTF-8 characters may be encountered. */ #ifdef SUPPORT_UTF8 #define MAXLIT 250 #else #define MAXLIT 255 #endif /* Min and max values for the common repeats; for the maxima, 0 => infinity */ static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; /* Text forms of OP_ values and things, for debugging (not all used) */ #ifdef DEBUG static const char *OP_names[] = { "End", "\\A", "\\B", "\\b", "\\D", "\\d", "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z", "Opt", "^", "$", "Any", "chars", "not", "*", "*?", "+", "+?", "?", "??", "{", "{", "{", "*", "*?", "+", "+?", "?", "??", "{", "{", "{", "*", "*?", "+", "+?", "?", "??", "{", "{", "{", "*", "*?", "+", "+?", "?", "??", "{", "{", "class", "Ref", "Recurse", "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref", "Brazero", "Braminzero", "Branumber", "Bra" }; #endif /* Table for handling escaped characters in the range '0'-'z'. Positive returns are simple data values; negative values are for special things like \d and so on. Zero means further processing is needed (for things like \x), or the escape is invalid. */ static const short int escapes[] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ '@', -ESC_A, -ESC_B, 0, -ESC_D, 0, 0, 0, /* @ - G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 0, 0, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ '`', 7, -ESC_b, 0, -ESC_d, ESC_E, ESC_F, 0, /* ` - g */ 0, 0, 0, 0, 0, 0, ESC_N, 0, /* h - o */ 0, 0, ESC_R, -ESC_s, ESC_T, 0, 0, -ESC_w, /* p - w */ 0, 0, -ESC_z /* x - z */ }; /* Tables of names of POSIX character classes and their lengths. The list is terminated by a zero length entry. The first three must be alpha, upper, lower, as this is assumed for handling case independence. */ static const char *posix_names[] = { "alpha", "lower", "upper", "alnum", "ascii", "cntrl", "digit", "graph", "print", "punct", "space", "word", "xdigit" }; static const uschar posix_name_lengths[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; /* Table of class bit maps for each POSIX class; up to three may be combined to form the class. */ static const int posix_class_maps[] = { cbit_lower, cbit_upper, -1, /* alpha */ cbit_lower, -1, -1, /* lower */ cbit_upper, -1, -1, /* upper */ cbit_digit, cbit_lower, cbit_upper, /* alnum */ cbit_print, cbit_cntrl, -1, /* ascii */ cbit_cntrl, -1, -1, /* cntrl */ cbit_digit, -1, -1, /* digit */ cbit_graph, -1, -1, /* graph */ cbit_print, -1, -1, /* print */ cbit_punct, -1, -1, /* punct */ cbit_space, -1, -1, /* space */ cbit_word, -1, -1, /* word */ cbit_xdigit,-1, -1 /* xdigit */ }; /* Definition to allow mutual recursion */ static BOOL compile_regex(int, int, int *, uschar **, const uschar **, const char **, BOOL, int, int *, int *, compile_data *); /* Structure for building a chain of data that actually lives on the stack, for holding the values of the subject pointer at the start of each subpattern, so as to detect when an empty string has been matched by a subpattern - to break infinite loops. */ typedef struct eptrblock { struct eptrblock *prev; const uschar *saved_eptr; } eptrblock; /* Flag bits for the match() function */ #define match_condassert 0x01 /* Called to check a condition assertion */ #define match_isgroup 0x02 /* Set if start of bracketed group */ /************************************************* * Global variables * *************************************************/ /* PCRE is thread-clean and doesn't use any global variables in the normal sense. However, it calls memory allocation and free functions via the two indirections below, which are can be changed by the caller, but are shared between all threads. */ #ifndef SQUEAK_PLUGIN void *(*pcre_malloc)(size_t) = malloc; void (*pcre_free)(void *) = free; #endif /************************************************* * Macros and tables for character handling * *************************************************/ /* When UTF-8 encoding is being used, a character is no longer just a single byte. The macros for character handling generate simple sequences when used in byte-mode, and more complicated ones for UTF-8 characters. */ #ifndef SUPPORT_UTF8 #define GETCHARINC(c, eptr) c = *eptr++; #define GETCHARLEN(c, eptr, len) c = *eptr; #define BACKCHAR(eptr) #else /* SUPPORT_UTF8 */ /* Get the next UTF-8 character, advancing the pointer */ #define GETCHARINC(c, eptr) \ c = *eptr++; \ if (md->utf8 && (c & 0xc0) == 0xc0) \ { \ int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ int s = 6*a; \ c = (c & utf8_table3[a]) << s; \ while (a-- > 0) \ { \ s -= 6; \ c |= (*eptr++ & 0x3f) << s; \ } \ } /* Get the next UTF-8 character, not advancing the pointer, setting length */ #define GETCHARLEN(c, eptr, len) \ c = *eptr; \ len = 1; \ if (md->utf8 && (c & 0xc0) == 0xc0) \ { \ int i; \ int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ int s = 6*a; \ c = (c & utf8_table3[a]) << s; \ for (i = 1; i <= a; i++) \ { \ s -= 6; \ c |= (eptr[i] & 0x3f) << s; \ } \ len += a; \ } /* If the pointer is not at the start of a character, move it back until it is. */ #define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--; #endif /************************************************* * Default character tables * *************************************************/ /* A default set of character tables is included in the PCRE binary. Its source is built by the maketables auxiliary program, which uses the default C ctypes functions, and put in the file chartables.c. These tables are used by PCRE whenever the caller of pcre_compile() does not provide an alternate set of tables. */ #include "chartables.c" #ifdef SUPPORT_UTF8 /************************************************* * Tables for UTF-8 support * *************************************************/ /* These are the breakpoints for different numbers of bytes in a UTF-8 character. */ static int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; /* These are the indicator bits and the mask for the data bits to set in the first byte of a character, indexed by the number of additional bytes. */ static int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; /* Table of the number of extra characters, indexed by the first character masked with 0x3f. The highest number for a valid UTF-8 character is in fact 0x3d. */ static uschar utf8_table4[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; /************************************************* * Convert character value to UTF-8 * *************************************************/ /* This function takes an integer value in the range 0 - 0x7fffffff and encodes it as a UTF-8 character in 0 to 6 bytes. Arguments: cvalue the character value buffer pointer to buffer for result - at least 6 bytes long Returns: number of characters placed in the buffer */ static int ord2utf8(int cvalue, uschar *buffer) { register int i, j; for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) if (cvalue <= utf8_table1[i]) break; buffer += i; for (j = i; j > 0; j--) { *buffer-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; } *buffer = utf8_table2[i] | cvalue; return i + 1; } #endif /************************************************* * Return version string * *************************************************/ #define STRING(a) # a #define XSTRING(s) STRING(s) const char * pcre_version(void) { return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE); } /************************************************* * (Obsolete) Return info about compiled pattern * *************************************************/ /* This is the original "info" function. It picks potentially useful data out of the private structure, but its interface was too rigid. It remains for backwards compatibility. The public options are passed back in an int - though the re->options field has been expanded to a long int, all the public options at the low end of it, and so even on 16-bit systems this will still be OK. Therefore, I haven't changed the API for pcre_info(). Arguments: external_re points to compiled code optptr where to pass back the options first_char where to pass back the first character, or -1 if multiline and all branches start ^, or -2 otherwise Returns: number of capturing subpatterns or negative values on error */ int pcre_info(const pcre *external_re, int *optptr, int *first_char) { const real_pcre *re = (const real_pcre *)external_re; if (re == NULL) return PCRE_ERROR_NULL; if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS); if (first_char != NULL) *first_char = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char : ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; return re->top_bracket; } /************************************************* * Return info about compiled pattern * *************************************************/ /* This is a newer "info" function which has an extensible interface so that additional items can be added compatibly. Arguments: external_re points to compiled code external_study points to study data, or NULL what what information is required where where to put the information Returns: 0 if data returned, negative on error */ int pcre_fullinfo(const pcre *external_re, const pcre_extra *study_data, int what, void *where) { const real_pcre *re = (const real_pcre *)external_re; const real_pcre_extra *study = (const real_pcre_extra *)study_data; if (re == NULL || where == NULL) return PCRE_ERROR_NULL; if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; switch (what) { case PCRE_INFO_OPTIONS: *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS; break; case PCRE_INFO_SIZE: *((size_t *)where) = re->size; break; case PCRE_INFO_CAPTURECOUNT: *((int *)where) = re->top_bracket; break; case PCRE_INFO_BACKREFMAX: *((int *)where) = re->top_backref; break; case PCRE_INFO_FIRSTCHAR: *((int *)where) = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char : ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; break; case PCRE_INFO_FIRSTTABLE: *((const uschar **)where) = (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)? study->start_bits : NULL; break; case PCRE_INFO_LASTLITERAL: *((int *)where) = ((re->options & PCRE_REQCHSET) != 0)? re->req_char : -1; break; default: return PCRE_ERROR_BADOPTION; } return 0; } #ifdef DEBUG /************************************************* * Debugging function to print chars * *************************************************/ /* Print a sequence of chars in printable format, stopping at the end of the subject if the requested. Arguments: p points to characters length number to print is_subject TRUE if printing from within md->start_subject md pointer to matching data block, if is_subject is TRUE Returns: nothing */ static void pchars(const uschar *p, int length, BOOL is_subject, match_data *md) { int c; if (is_subject && length > md->end_subject - p) length = md->end_subject - p; while (length-- > 0) if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); } #endif /************************************************* * Handle escapes * *************************************************/ /* This function is called when a \ has been encountered. It either returns a positive value for a simple escape such as \n, or a negative value which encodes one of the more complicated things such as \d. When UTF-8 is enabled, a positive value greater than 255 may be returned. On entry, ptr is pointing at the \. On exit, it is on the final character of the escape sequence. Arguments: ptrptr points to the pattern position pointer errorptr points to the pointer to the error message bracount number of previous extracting brackets options the options bits isclass TRUE if inside a character class cd pointer to char tables block Returns: zero or positive => a data character negative => a special escape sequence on error, errorptr is set */ static int check_escape(const uschar **ptrptr, const char **errorptr, int bracount, int options, BOOL isclass, compile_data *cd) { const uschar *ptr = *ptrptr; int c, i; /* If backslash is at the end of the pattern, it's an error. */ c = *(++ptr); if (c == 0) *errorptr = ERR1; /* Digits or letters may have special meaning; all others are literals. */ else if (c < '0' || c > 'z') {} /* Do an initial lookup in a table. A non-zero result is something that can be returned immediately. Otherwise further processing may be required. */ else if ((i = escapes[c - '0']) != 0) c = i; /* Escapes that need further processing, or are illegal. */ else { const uschar *oldptr; switch (c) { /* The handling of escape sequences consisting of a string of digits starting with one that is not zero is not straightforward. By experiment, the way Perl works seems to be as follows: Outside a character class, the digits are read as a decimal number. If the number is less than 10, or if there are that many previous extracting left brackets, then it is a back reference. Otherwise, up to three octal digits are read to form an escaped byte. Thus \123 is likely to be octal 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal value is greater than 377, the least significant 8 bits are taken. Inside a character class, \ followed by a digit is always an octal number. */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!isclass) { oldptr = ptr; c -= '0'; while ((cd->ctypes[ptr[1]] & ctype_digit) != 0) c = c * 10 + *(++ptr) - '0'; if (c < 10 || c <= bracount) { c = -(ESC_REF + c); break; } ptr = oldptr; /* Put the pointer back and fall through */ } /* Handle an octal number following \. If the first digit is 8 or 9, Perl generates a binary zero byte and treats the digit as a following literal. Thus we have to pull back the pointer by one. */ if ((c = *ptr) >= '8') { ptr--; c = 0; break; } /* \0 always starts an octal number, but we may drop through to here with a larger first octal digit. */ case '0': c -= '0'; while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 && ptr[1] != '8' && ptr[1] != '9') c = c * 8 + *(++ptr) - '0'; c &= 255; /* Take least significant 8 bits */ break; /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number which can be greater than 0xff, but only if the ddd are hex digits. */ case 'x': #ifdef SUPPORT_UTF8 if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) { const uschar *pt = ptr + 2; register int count = 0; c = 0; while ((cd->ctypes[*pt] & ctype_xdigit) != 0) { count++; c = c * 16 + cd->lcc[*pt] - (((cd->ctypes[*pt] & ctype_digit) != 0)? '0' : 'W'); pt++; } if (*pt == '}') { if (c < 0 || count > 8) *errorptr = ERR34; ptr = pt; break; } /* If the sequence of hex digits does not end with '}', then we don't recognize this construct; fall through to the normal \x handling. */ } #endif /* Read just a single hex char */ c = 0; while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0) { ptr++; c = c * 16 + cd->lcc[*ptr] - (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W'); } break; /* Other special escapes not starting with a digit are straightforward */ case 'c': c = *(++ptr); if (c == 0) { *errorptr = ERR2; return 0; } /* A letter is upper-cased; then the 0x40 bit is flipped */ if (c >= 'a' && c <= 'z') c = cd->fcc[c]; c ^= 0x40; break; /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any other alphameric following \ is an error if PCRE_EXTRA was set; otherwise, for Perl compatibility, it is a literal. This code looks a bit odd, but there used to be some cases other than the default, and there may be again in future, so I haven't "optimized" it. */ default: if ((options & PCRE_EXTRA) != 0) switch(c) { default: *errorptr = ERR3; break; } break; } } *ptrptr = ptr; return c; } /************************************************* * Check for counted repeat * *************************************************/ /* This function is called when a '{' is encountered in a place where it might start a quantifier. It looks ahead to see if it really is a quantifier or not. It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} where the ddds are digits. Arguments: p pointer to the first char after '{' cd pointer to char tables block Returns: TRUE or FALSE */ static BOOL is_counted_repeat(const uschar *p, compile_data *cd) { if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE; while ((cd->ctypes[*p] & ctype_digit) != 0) p++; if (*p == '}') return TRUE; if (*p++ != ',') return FALSE; if (*p == '}') return TRUE; if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE; while ((cd->ctypes[*p] & ctype_digit) != 0) p++; return (*p == '}'); } /************************************************* * Read repeat counts * *************************************************/ /* Read an item of the form {n,m} and return the values. This is called only after is_counted_repeat() has confirmed that a repeat-count quantifier exists, so the syntax is guaranteed to be correct, but we need to check the values. Arguments: p pointer to first char after '{' minp pointer to int for min maxp pointer to int for max returned as -1 if no max errorptr points to pointer to error message cd pointer to character tables clock Returns: pointer to '}' on success; current ptr on error, with errorptr set */ static const uschar * read_repeat_counts(const uschar *p, int *minp, int *maxp, const char **errorptr, compile_data *cd) { int min = 0; int max = -1; while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0'; if (*p == '}') max = min; else { if (*(++p) != '}') { max = 0; while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0'; if (max < min) { *errorptr = ERR4; return p; } } } /* Do paranoid checks, then fill in the required variables, and pass back the pointer to the terminating '}'. */ if (min > 65535 || max > 65535) *errorptr = ERR5; else { *minp = min; *maxp = max; } return p; } /************************************************* * Find the fixed length of a pattern * *************************************************/ /* Scan a pattern and compute the fixed length of subject that will match it, if the length is fixed. This is needed for dealing with backward assertions. Arguments: code points to the start of the pattern (the bracket) options the compiling options Returns: the fixed length, or -1 if there is no fixed length */ static int find_fixedlength(uschar *code, int options) { int length = -1; register int branchlength = 0; register uschar *cc = code + 3; /* Scan along the opcodes for this branch. If we get to the end of the branch, check the length against that of the other branches. */ for (;;) { int d; register int op = *cc; if (op >= OP_BRA) op = OP_BRA; switch (op) { case OP_BRA: case OP_ONCE: case OP_COND: d = find_fixedlength(cc, options); if (d < 0) return -1; branchlength += d; do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT); cc += 3; break; /* Reached end of a branch; if it's a ket it is the end of a nested call. If it's ALT it is an alternation in a nested call. If it is END it's the end of the outer call. All can be handled by the same code. */ case OP_ALT: case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_END: if (length < 0) length = branchlength; else if (length != branchlength) return -1; if (*cc != OP_ALT) return length; cc += 3; branchlength = 0; break; /* Skip over assertive subpatterns */ case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT); cc += 3; break; /* Skip over things that don't match chars */ case OP_REVERSE: case OP_BRANUMBER: case OP_CREF: cc++; /* Fall through */ case OP_OPT: cc++; /* Fall through */ case OP_SOD: case OP_EOD: case OP_EODN: case OP_CIRC: case OP_DOLL: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: cc++; break; /* Handle char strings. In UTF-8 mode we must count characters, not bytes. This requires a scan of the string, unfortunately. We assume valid UTF-8 strings, so all we do is reduce the length by one for byte whose bits are 10xxxxxx. */ case OP_CHARS: branchlength += *(++cc); #ifdef SUPPORT_UTF8 for (d = 1; d <= *cc; d++) if ((cc[d] & 0xc0) == 0x80) branchlength--; #endif cc += *cc + 1; break; /* Handle exact repetitions */ case OP_EXACT: case OP_TYPEEXACT: branchlength += (cc[1] << 8) + cc[2]; cc += 4; break; /* Handle single-char matchers */ case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: branchlength++; cc++; break; /* Check a class for variable quantification */ case OP_CLASS: cc += 33; switch (*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: return -1; case OP_CRRANGE: case OP_CRMINRANGE: if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1; branchlength += (cc[1] << 8) + cc[2]; cc += 5; break; default: branchlength++; } break; /* Anything else is variable length */ default: return -1; } } /* Control never gets here */ } /************************************************* * Check for POSIX class syntax * *************************************************/ /* This function is called when the sequence "[:" or "[." or "[=" is encountered in a character class. It checks whether this is followed by an optional ^ and then a sequence of letters, terminated by a matching ":]" or ".]" or "=]". Argument: ptr pointer to the initial [ endptr where to return the end pointer cd pointer to compile data Returns: TRUE or FALSE */ static BOOL check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd) { int terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ if (*(++ptr) == '^') ptr++; while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; if (*ptr == terminator && ptr[1] == ']') { *endptr = ptr; return TRUE; } return FALSE; } /************************************************* * Check POSIX class name * *************************************************/ /* This function is called to check the name given in a POSIX-style class entry such as [:alnum:]. Arguments: ptr points to the first letter len the length of the name Returns: a value representing the name, or -1 if unknown */ static int check_posix_name(const uschar *ptr, int len) { register int yield = 0; while (posix_name_lengths[yield] != 0) { if (len == posix_name_lengths[yield] && strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield; yield++; } return -1; } /************************************************* * Compile one branch * *************************************************/ /* Scan the pattern, compiling it into the code vector. Arguments: options the option bits brackets points to number of extracting brackets used code points to the pointer to the current code point ptrptr points to the current pattern pointer errorptr points to pointer to error message optchanged set to the value of the last OP_OPT item compiled reqchar set to the last literal character required, else -1 countlits set to count of mandatory literal characters cd contains pointers to tables Returns: TRUE on success FALSE, with *errorptr set on error */ static BOOL compile_branch(int options, int *brackets, uschar **codeptr, const uschar **ptrptr, const char **errorptr, int *optchanged, int *reqchar, int *countlits, compile_data *cd) { int repeat_type, op_type; int repeat_min, repeat_max; int bravalue, length; int greedy_default, greedy_non_default; int prevreqchar; int condcount = 0; int subcountlits = 0; register int c; register uschar *code = *codeptr; uschar *tempcode; const uschar *ptr = *ptrptr; const uschar *tempptr; uschar *previous = NULL; uschar class[32]; /* Set up the default and non-default settings for greediness */ greedy_default = ((options & PCRE_UNGREEDY) != 0); greedy_non_default = greedy_default ^ 1; /* Initialize no required char, and count of literals */ *reqchar = prevreqchar = -1; *countlits = 0; /* Switch on next character until the end of the branch */ for (;; ptr++) { BOOL negate_class; int class_charcount; int class_lastchar; int newoptions; int skipbytes; int subreqchar; c = *ptr; if ((options & PCRE_EXTENDED) != 0) { if ((cd->ctypes[c] & ctype_space) != 0) continue; if (c == '#') { /* The space before the ; is to avoid a warning on a silly compiler on the Macintosh. */ while ((c = *(++ptr)) != 0 && c != NEWLINE) ; continue; } } switch(c) { /* The branch terminates at end of string, |, or ). */ case 0: case '|': case ')': *codeptr = code; *ptrptr = ptr; return TRUE; /* Handle single-character metacharacters */ case '^': previous = NULL; *code++ = OP_CIRC; break; case '$': previous = NULL; *code++ = OP_DOLL; break; case '.': previous = code; *code++ = OP_ANY; break; /* Character classes. These always build a 32-byte bitmap of the permitted characters, except in the special case where there is only one character. For negated classes, we build the map as usual, then invert it at the end. */ case '[': previous = code; *code++ = OP_CLASS; /* If the first character is '^', set the negation flag and skip it. */ if ((c = *(++ptr)) == '^') { negate_class = TRUE; c = *(++ptr); } else negate_class = FALSE; /* Keep a count of chars so that we can optimize the case of just a single character. */ class_charcount = 0; class_lastchar = -1; /* Initialize the 32-char bit map to all zeros. We have to build the map in a temporary bit of store, in case the class contains only 1 character, because in that case the compiled code doesn't use the bit map. */ memset(class, 0, 32 * sizeof(uschar)); /* Process characters until ] is reached. By writing this as a "do" it means that an initial ] is taken as a data character. */ do { if (c == 0) { *errorptr = ERR6; goto FAILED; } /* Handle POSIX class names. Perl allows a negation extension of the form [:^name]. A square bracket that doesn't match the syntax is treated as a literal. We also recognize the POSIX constructions [.ch.] and [=ch=] ("collating elements") and fault them, as Perl 5.6 does. */ if (c == '[' && (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && check_posix_syntax(ptr, &tempptr, cd)) { BOOL local_negate = FALSE; int posix_class, i; register const uschar *cbits = cd->cbits; if (ptr[1] != ':') { *errorptr = ERR31; goto FAILED; } ptr += 2; if (*ptr == '^') { local_negate = TRUE; ptr++; } posix_class = check_posix_name(ptr, tempptr - ptr); if (posix_class < 0) { *errorptr = ERR30; goto FAILED; } /* If matching is caseless, upper and lower are converted to alpha. This relies on the fact that the class table starts with alpha, lower, upper as the first 3 entries. */ if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) posix_class = 0; /* Or into the map we are building up to 3 of the static class tables, or their negations. */ posix_class *= 3; for (i = 0; i < 3; i++) { int taboffset = posix_class_maps[posix_class + i]; if (taboffset < 0) break; if (local_negate) for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset]; else for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset]; } ptr = tempptr + 1; class_charcount = 10; /* Set > 1; assumes more than 1 per class */ continue; } /* Backslash may introduce a single character, or it may introduce one of the specials, which just set a flag. Escaped items are checked for validity in the pre-compiling pass. The sequence \b is a special case. Inside a class (and only there) it is treated as backspace. Elsewhere it marks a word boundary. Other escapes have preset maps ready to or into the one we are building. We assume they have more than one character in them, so set class_count bigger than one. */ if (c == '\\') { c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd); if (-c == ESC_b) c = '\b'; else if (c < 0) { register const uschar *cbits = cd->cbits; class_charcount = 10; switch (-c) { case ESC_d: for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit]; continue; case ESC_D: for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit]; continue; case ESC_w: for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word]; continue; case ESC_W: for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word]; continue; case ESC_s: for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space]; continue; case ESC_S: for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space]; continue; default: *errorptr = ERR7; goto FAILED; } } /* Fall through if single character, but don't at present allow chars > 255 in UTF-8 mode. */ #ifdef SUPPORT_UTF8 if (c > 255) { *errorptr = ERR33; goto FAILED; } #endif } /* A single character may be followed by '-' to form a range. However, Perl does not permit ']' to be the end of the range. A '-' character here is treated as a literal. */ if (ptr[1] == '-' && ptr[2] != ']') { int d; ptr += 2; d = *ptr; if (d == 0) { *errorptr = ERR6; goto FAILED; } /* The second part of a range can be a single-character escape, but not any of the other escapes. Perl 5.6 treats a hyphen as a literal in such circumstances. */ if (d == '\\') { const uschar *oldptr = ptr; d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd); #ifdef SUPPORT_UTF8 if (d > 255) { *errorptr = ERR33; goto FAILED; } #endif /* \b is backslash; any other special means the '-' was literal */ if (d < 0) { if (d == -ESC_b) d = '\b'; else { ptr = oldptr - 2; goto SINGLE_CHARACTER; /* A few lines below */ } } } if (d < c) { *errorptr = ERR8; goto FAILED; } for (; c <= d; c++) { class[c/8] |= (1 << (c&7)); if ((options & PCRE_CASELESS) != 0) { int uc = cd->fcc[c]; /* flip case */ class[uc/8] |= (1 << (uc&7)); } class_charcount++; /* in case a one-char range */ class_lastchar = c; } continue; /* Go get the next char in the class */ } /* Handle a lone single character - we can get here for a normal non-escape char, or after \ that introduces a single character. */ SINGLE_CHARACTER: class [c/8] |= (1 << (c&7)); if ((options & PCRE_CASELESS) != 0) { c = cd->fcc[c]; /* flip case */ class[c/8] |= (1 << (c&7)); } class_charcount++; class_lastchar = c; } /* Loop until ']' reached; the check for end of string happens inside the loop. This "while" is the end of the "do" above. */ while ((c = *(++ptr)) != ']'); /* If class_charcount is 1 and class_lastchar is not negative, we saw precisely one character. This doesn't need the whole 32-byte bit map. We turn it into a 1-character OP_CHAR if it's positive, or OP_NOT if it's negative. */ if (class_charcount == 1 && class_lastchar >= 0) { if (negate_class) { code[-1] = OP_NOT; } else { code[-1] = OP_CHARS; *code++ = 1; } *code++ = class_lastchar; } /* Otherwise, negate the 32-byte map if necessary, and copy it into the code vector. */ else { if (negate_class) for (c = 0; c < 32; c++) code[c] = ~class[c]; else memcpy(code, class, 32); code += 32; } break; /* Various kinds of repeat */ case '{': if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR; ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd); if (*errorptr != NULL) goto FAILED; goto REPEAT; case '*': repeat_min = 0; repeat_max = -1; goto REPEAT; case '+': repeat_min = 1; repeat_max = -1; goto REPEAT; case '?': repeat_min = 0; repeat_max = 1; REPEAT: if (previous == NULL) { *errorptr = ERR9; goto FAILED; } /* If the next character is '?' this is a minimizing repeat, by default, but if PCRE_UNGREEDY is set, it works the other way round. Advance to the next character. */ if (ptr[1] == '?') { repeat_type = greedy_non_default; ptr++; } else repeat_type = greedy_default; /* If previous was a string of characters, chop off the last one and use it as the subject of the repeat. If there was only one character, we can abolish the previous item altogether. A repeat with a zero minimum wipes out any reqchar setting, backing up to the previous value. We must also adjust the countlits value. */ if (*previous == OP_CHARS) { int len = previous[1]; if (repeat_min == 0) *reqchar = prevreqchar; *countlits += repeat_min - 1; if (len == 1) { c = previous[2]; code = previous; } else { c = previous[len+1]; previous[1]--; code--; } op_type = 0; /* Use single-char op codes */ goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ } /* If previous was a single negated character ([^a] or similar), we use one of the special opcodes, replacing it. The code is shared with single- character repeats by adding a suitable offset into repeat_type. */ else if ((int)*previous == OP_NOT) { op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ c = previous[1]; code = previous; goto OUTPUT_SINGLE_REPEAT; } /* If previous was a character type match (\d or similar), abolish it and create a suitable repeat item. The code is shared with single-character repeats by adding a suitable offset into repeat_type. */ else if ((int)*previous < OP_EODN || *previous == OP_ANY) { op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ c = *previous; code = previous; OUTPUT_SINGLE_REPEAT: /* If the maximum is zero then the minimum must also be zero; Perl allows this case, so we do too - by simply omitting the item altogether. */ if (repeat_max == 0) goto END_REPEAT; /* Combine the op_type with the repeat_type */ repeat_type += op_type; /* A minimum of zero is handled either as the special case * or ?, or as an UPTO, with the maximum given. */ if (repeat_min == 0) { if (repeat_max == -1) *code++ = OP_STAR + repeat_type; else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; else { *code++ = OP_UPTO + repeat_type; *code++ = repeat_max >> 8; *code++ = (repeat_max & 255); } } /* The case {1,} is handled as the special case + */ else if (repeat_min == 1 && repeat_max == -1) *code++ = OP_PLUS + repeat_type; /* The case {n,n} is just an EXACT, while the general case {n,m} is handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */ else { if (repeat_min != 1) { *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ *code++ = repeat_min >> 8; *code++ = (repeat_min & 255); } /* If the mininum is 1 and the previous item was a character string, we either have to put back the item that got cancelled if the string length was 1, or add the character back onto the end of a longer string. For a character type nothing need be done; it will just get put back naturally. Note that the final character is always going to get added below. */ else if (*previous == OP_CHARS) { if (code == previous) code += 2; else previous[1]++; } /* For a single negated character we also have to put back the item that got cancelled. */ else if (*previous == OP_NOT) code++; /* If the maximum is unlimited, insert an OP_STAR. */ if (repeat_max < 0) { *code++ = c; *code++ = OP_STAR + repeat_type; } /* Else insert an UPTO if the max is greater than the min. */ else if (repeat_max != repeat_min) { *code++ = c; repeat_max -= repeat_min; *code++ = OP_UPTO + repeat_type; *code++ = repeat_max >> 8; *code++ = (repeat_max & 255); } } /* The character or character type itself comes last in all cases. */ *code++ = c; } /* If previous was a character class or a back reference, we put the repeat stuff after it, but just skip the item if the repeat was {0,0}. */ else if (*previous == OP_CLASS || *previous == OP_REF) { if (repeat_max == 0) { code = previous; goto END_REPEAT; } if (repeat_min == 0 && repeat_max == -1) *code++ = OP_CRSTAR + repeat_type; else if (repeat_min == 1 && repeat_max == -1) *code++ = OP_CRPLUS + repeat_type; else if (repeat_min == 0 && repeat_max == 1) *code++ = OP_CRQUERY + repeat_type; else { *code++ = OP_CRRANGE + repeat_type; *code++ = repeat_min >> 8; *code++ = repeat_min & 255; if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ *code++ = repeat_max >> 8; *code++ = repeat_max & 255; } } /* If previous was a bracket group, we may have to replicate it in certain cases. */ else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE || (int)*previous == OP_COND) { register int i; int ketoffset = 0; int len = code - previous; uschar *bralink = NULL; /* If the maximum repeat count is unlimited, find the end of the bracket by scanning through from the start, and compute the offset back to it from the current code pointer. There may be an OP_OPT setting following the final KET, so we can't find the end just by going back from the code pointer. */ if (repeat_max == -1) { register uschar *ket = previous; do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET); ketoffset = code - ket; } /* The case of a zero minimum is special because of the need to stick OP_BRAZERO in front of it, and because the group appears once in the data, whereas in other cases it appears the minimum number of times. For this reason, it is simplest to treat this case separately, as otherwise the code gets far too messy. There are several special subcases when the minimum is zero. */ if (repeat_min == 0) { /* If we set up a required char from the bracket, we must back off to the previous value and reset the countlits value too. */ if (subcountlits > 0) { *reqchar = prevreqchar; *countlits -= subcountlits; } /* If the maximum is also zero, we just omit the group from the output altogether. */ if (repeat_max == 0) { code = previous; goto END_REPEAT; } /* If the maximum is 1 or unlimited, we just have to stick in the BRAZERO and do no more at this point. */ if (repeat_max <= 1) { memmove(previous+1, previous, len); code++; *previous++ = OP_BRAZERO + repeat_type; } /* If the maximum is greater than 1 and limited, we have to replicate in a nested fashion, sticking OP_BRAZERO before each set of brackets. The first one has to be handled carefully because it's the original copy, which has to be moved up. The remainder can be handled by code that is common with the non-zero minimum case below. We just have to adjust the value or repeat_max, since one less copy is required. */ else { int offset; memmove(previous+4, previous, len); code += 4; *previous++ = OP_BRAZERO + repeat_type; *previous++ = OP_BRA; /* We chain together the bracket offset fields that have to be filled in later when the ends of the brackets are reached. */ offset = (bralink == NULL)? 0 : previous - bralink; bralink = previous; *previous++ = offset >> 8; *previous++ = offset & 255; } repeat_max--; } /* If the minimum is greater than zero, replicate the group as many times as necessary, and adjust the maximum to the number of subsequent copies that we need. */ else { for (i = 1; i < repeat_min; i++) { memcpy(code, previous, len); code += len; } if (repeat_max > 0) repeat_max -= repeat_min; } /* This code is common to both the zero and non-zero minimum cases. If the maximum is limited, it replicates the group in a nested fashion, remembering the bracket starts on a stack. In the case of a zero minimum, the first one was set up above. In all cases the repeat_max now specifies the number of additional copies needed. */ if (repeat_max >= 0) { for (i = repeat_max - 1; i >= 0; i--) { *code++ = OP_BRAZERO + repeat_type; /* All but the final copy start a new nesting, maintaining the chain of brackets outstanding. */ if (i != 0) { int offset; *code++ = OP_BRA; offset = (bralink == NULL)? 0 : code - bralink; bralink = code; *code++ = offset >> 8; *code++ = offset & 255; } memcpy(code, previous, len); code += len; } /* Now chain through the pending brackets, and fill in their length fields (which are holding the chain links pro tem). */ while (bralink != NULL) { int oldlinkoffset; int offset = code - bralink + 1; uschar *bra = code - offset; oldlinkoffset = (bra[1] << 8) + bra[2]; bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; *code++ = OP_KET; *code++ = bra[1] = offset >> 8; *code++ = bra[2] = (offset & 255); } } /* If the maximum is unlimited, set a repeater in the final copy. We can't just offset backwards from the current code point, because we don't know if there's been an options resetting after the ket. The correct offset was computed above. */ else code[-ketoffset] = OP_KETRMAX + repeat_type; } /* Else there's some kind of shambles */ else { *errorptr = ERR11; goto FAILED; } /* In all case we no longer have a previous item. */ END_REPEAT: previous = NULL; break; /* Start of nested bracket sub-expression, or comment or lookahead or lookbehind or option setting or condition. First deal with special things that can come after a bracket; all are introduced by ?, and the appearance of any of them means that this is not a referencing group. They were checked for validity in the first pass over the string, so we don't have to check for syntax errors here. */ case '(': newoptions = options; skipbytes = 0; if (*(++ptr) == '?') { int set, unset; int *optset; switch (*(++ptr)) { case '#': /* Comment; skip to ket */ ptr++; while (*ptr != ')') ptr++; continue; case ':': /* Non-extracting bracket */ bravalue = OP_BRA; ptr++; break; case '(': bravalue = OP_COND; /* Conditional group */ if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0) { int condref = *ptr - '0'; while (*(++ptr) != ')') condref = condref*10 + *ptr - '0'; if (condref == 0) { *errorptr = ERR35; goto FAILED; } ptr++; code[3] = OP_CREF; code[4] = condref >> 8; code[5] = condref & 255; skipbytes = 3; } else ptr--; break; case '=': /* Positive lookahead */ bravalue = OP_ASSERT; ptr++; break; case '!': /* Negative lookahead */ bravalue = OP_ASSERT_NOT; ptr++; break; case '<': /* Lookbehinds */ switch (*(++ptr)) { case '=': /* Positive lookbehind */ bravalue = OP_ASSERTBACK; ptr++; break; case '!': /* Negative lookbehind */ bravalue = OP_ASSERTBACK_NOT; ptr++; break; default: /* Syntax error */ *errorptr = ERR24; goto FAILED; } break; case '>': /* One-time brackets */ bravalue = OP_ONCE; ptr++; break; case 'R': /* Pattern recursion */ *code++ = OP_RECURSE; ptr++; continue; default: /* Option setting */ set = unset = 0; optset = &set; while (*ptr != ')' && *ptr != ':') { switch (*ptr++) { case '-': optset = &unset; break; case 'i': *optset |= PCRE_CASELESS; break; case 'm': *optset |= PCRE_MULTILINE; break; case 's': *optset |= PCRE_DOTALL; break; case 'x': *optset |= PCRE_EXTENDED; break; case 'U': *optset |= PCRE_UNGREEDY; break; case 'X': *optset |= PCRE_EXTRA; break; default: *errorptr = ERR12; goto FAILED; } } /* Set up the changed option bits, but don't change anything yet. */ newoptions = (options | set) & (~unset); /* If the options ended with ')' this is not the start of a nested group with option changes, so the options change at this level. At top level there is nothing else to be done (the options will in fact have been set from the start of compiling as a result of the first pass) but at an inner level we must compile code to change the ims options if necessary, and pass the new setting back so that it can be put at the start of any following branches, and when this group ends, a resetting item can be compiled. */ if (*ptr == ')') { if ((options & PCRE_INGROUP) != 0 && (options & PCRE_IMS) != (newoptions & PCRE_IMS)) { *code++ = OP_OPT; *code++ = *optchanged = newoptions & PCRE_IMS; } options = newoptions; /* Change options at this level */ previous = NULL; /* This item can't be repeated */ continue; /* It is complete */ } /* If the options ended with ':' we are heading into a nested group with possible change of options. Such groups are non-capturing and are not assertions of any kind. All we need to do is skip over the ':'; the newoptions value is handled below. */ bravalue = OP_BRA; ptr++; } } /* Else we have a referencing group; adjust the opcode. If the bracket number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and arrange for the true number to follow later, in an OP_BRANUMBER item. */ else { if (++(*brackets) > EXTRACT_BASIC_MAX) { bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1; code[3] = OP_BRANUMBER; code[4] = *brackets >> 8; code[5] = *brackets & 255; skipbytes = 3; } else bravalue = OP_BRA + *brackets; } /* Process nested bracketed re. Assertions may not be repeated, but other kinds can be. We copy code into a non-register variable in order to be able to pass its address because some compilers complain otherwise. Pass in a new setting for the ims options if they have changed. */ previous = (bravalue >= OP_ONCE)? code : NULL; *code = bravalue; tempcode = code; if (!compile_regex( options | PCRE_INGROUP, /* Set for all nested groups */ ((options & PCRE_IMS) != (newoptions & PCRE_IMS))? newoptions & PCRE_IMS : -1, /* Pass ims options if changed */ brackets, /* Extracting bracket count */ &tempcode, /* Where to put code (updated) */ &ptr, /* Input pointer (updated) */ errorptr, /* Where to put an error message */ (bravalue == OP_ASSERTBACK || bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ skipbytes, /* Skip over OP_COND/OP_BRANUMBER */ &subreqchar, /* For possible last char */ &subcountlits, /* For literal count */ cd)) /* Tables block */ goto FAILED; /* At the end of compiling, code is still pointing to the start of the group, while tempcode has been updated to point past the end of the group and any option resetting that may follow it. The pattern pointer (ptr) is on the bracket. */ /* If this is a conditional bracket, check that there are no more than two branches in the group. */ else if (bravalue == OP_COND) { uschar *tc = code; condcount = 0; do { condcount++; tc += (tc[1] << 8) | tc[2]; } while (*tc != OP_KET); if (condcount > 2) { *errorptr = ERR27; goto FAILED; } } /* Handle updating of the required character. If the subpattern didn't set one, leave it as it was. Otherwise, update it for normal brackets of all kinds, forward assertions, and conditions with two branches. Don't update the literal count for forward assertions, however. If the bracket is followed by a quantifier with zero repeat, we have to back off. Hence the definition of prevreqchar and subcountlits outside the main loop so that they can be accessed for the back off. */ if (subreqchar > 0 && (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT || (bravalue == OP_COND && condcount == 2))) { prevreqchar = *reqchar; *reqchar = subreqchar; if (bravalue != OP_ASSERT) *countlits += subcountlits; } /* Now update the main code pointer to the end of the group. */ code = tempcode; /* Error if hit end of pattern */ if (*ptr != ')') { *errorptr = ERR14; goto FAILED; } break; /* Check \ for being a real metacharacter; if not, fall through and handle it as a data character at the start of a string. Escape items are checked for validity in the pre-compiling pass. */ case '\\': tempptr = ptr; c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd); /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values are arranged to be the negation of the corresponding OP_values. For the back references, the values are ESC_REF plus the reference number. Only back references and those types that consume a character may be repeated. We can test for values between ESC_b and ESC_Z for the latter; this may have to change if any new ones are ever created. */ if (c < 0) { if (-c >= ESC_REF) { int number = -c - ESC_REF; previous = code; *code++ = OP_REF; *code++ = number >> 8; *code++ = number & 255; } else { previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; *code++ = -c; } continue; } /* Data character: reset and fall through */ ptr = tempptr; c = '\\'; /* Handle a run of data characters until a metacharacter is encountered. The first character is guaranteed not to be whitespace or # when the extended flag is set. */ NORMAL_CHAR: default: previous = code; *code = OP_CHARS; code += 2; length = 0; do { if ((options & PCRE_EXTENDED) != 0) { if ((cd->ctypes[c] & ctype_space) != 0) continue; if (c == '#') { /* The space before the ; is to avoid a warning on a silly compiler on the Macintosh. */ while ((c = *(++ptr)) != 0 && c != NEWLINE) ; if (c == 0) break; continue; } } /* Backslash may introduce a data char or a metacharacter. Escaped items are checked for validity in the pre-compiling pass. Stop the string before a metaitem. */ if (c == '\\') { tempptr = ptr; c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd); if (c < 0) { ptr = tempptr; break; } /* If a character is > 127 in UTF-8 mode, we have to turn it into two or more characters in the UTF-8 encoding. */ #ifdef SUPPORT_UTF8 if (c > 127 && (options & PCRE_UTF8) != 0) { uschar buffer[8]; int len = ord2utf8(c, buffer); for (c = 0; c < len; c++) *code++ = buffer[c]; length += len; continue; } #endif } /* Ordinary character or single-char escape */ *code++ = c; length++; } /* This "while" is the end of the "do" above. */ while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0); /* Update the last character and the count of literals */ prevreqchar = (length > 1)? code[-2] : *reqchar; *reqchar = code[-1]; *countlits += length; /* Compute the length and set it in the data vector, and advance to the next state. */ previous[1] = length; if (length < MAXLIT) ptr--; break; } } /* end of big loop */ /* Control never reaches here by falling through, only by a goto for all the error states. Pass back the position in the pattern so that it can be displayed to the user for diagnosing the error. */ FAILED: *ptrptr = ptr; return FALSE; } /************************************************* * Compile sequence of alternatives * *************************************************/ /* On entry, ptr is pointing past the bracket character, but on return it points to the closing bracket, or vertical bar, or end of string. The code variable is pointing at the byte into which the BRA operator has been stored. If the ims options are changed at the start (for a (?ims: group) or during any branch, we need to insert an OP_OPT item at the start of every following branch to ensure they get set correctly at run time, and also pass the new options into every subsequent branch compile. Argument: options the option bits optchanged new ims options to set as if (?ims) were at the start, or -1 for no change brackets -> int containing the number of extracting brackets used codeptr -> the address of the current code pointer ptrptr -> the address of the current pattern pointer errorptr -> pointer to error message lookbehind TRUE if this is a lookbehind assertion skipbytes skip this many bytes at start (for OP_COND, OP_BRANUMBER) reqchar -> place to put the last required character, or a negative number countlits -> place to put the shortest literal count of any branch cd points to the data block with tables pointers Returns: TRUE on success */ static BOOL compile_regex(int options, int optchanged, int *brackets, uschar **codeptr, const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes, int *reqchar, int *countlits, compile_data *cd) { const uschar *ptr = *ptrptr; uschar *code = *codeptr; uschar *last_branch = code; uschar *start_bracket = code; uschar *reverse_count = NULL; int oldoptions = options & PCRE_IMS; int branchreqchar, branchcountlits; *reqchar = -1; *countlits = INT_MAX; code += 3 + skipbytes; /* Loop for each alternative branch */ for (;;) { int length; /* Handle change of options */ if (optchanged >= 0) { *code++ = OP_OPT; *code++ = optchanged; options = (options & ~PCRE_IMS) | optchanged; } /* Set up dummy OP_REVERSE if lookbehind assertion */ if (lookbehind) { *code++ = OP_REVERSE; reverse_count = code; *code++ = 0; *code++ = 0; } /* Now compile the branch */ if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged, &branchreqchar, &branchcountlits, cd)) { *ptrptr = ptr; return FALSE; } /* Fill in the length of the last branch */ length = code - last_branch; last_branch[1] = length >> 8; last_branch[2] = length & 255; /* Save the last required character if all branches have the same; a current value of -1 means unset, while -2 means "previous branch had no last required char". */ if (*reqchar != -2) { if (branchreqchar >= 0) { if (*reqchar == -1) *reqchar = branchreqchar; else if (*reqchar != branchreqchar) *reqchar = -2; } else *reqchar = -2; } /* Keep the shortest literal count */ if (branchcountlits < *countlits) *countlits = branchcountlits; DPRINTF(("literal count = %d min=%d\n", branchcountlits, *countlits)); /* If lookbehind, check that this branch matches a fixed-length string, and put the length into the OP_REVERSE item. Temporarily mark the end of the branch with OP_END. */ if (lookbehind) { *code = OP_END; length = find_fixedlength(last_branch, options); DPRINTF(("fixed length = %d\n", length)); if (length < 0) { *errorptr = ERR25; *ptrptr = ptr; return FALSE; } reverse_count[0] = (length >> 8); reverse_count[1] = length & 255; } /* Reached end of expression, either ')' or end of pattern. Insert a terminating ket and the length of the whole bracketed item, and return, leaving the pointer at the terminating char. If any of the ims options were changed inside the group, compile a resetting op-code following. */ if (*ptr != '|') { length = code - start_bracket; *code++ = OP_KET; *code++ = length >> 8; *code++ = length & 255; if (optchanged >= 0) { *code++ = OP_OPT; *code++ = oldoptions; } *codeptr = code; *ptrptr = ptr; return TRUE; } /* Another branch follows; insert an "or" node and advance the pointer. */ *code = OP_ALT; last_branch = code; code += 3; ptr++; } /* Control never reaches here */ } /************************************************* * Find first significant op code * *************************************************/ /* This is called by several functions that scan a compiled expression looking for a fixed first character, or an anchoring op code etc. It skips over things that do not influence this. For one application, a change of caseless option is important. Arguments: code pointer to the start of the group options pointer to external options optbit the option bit whose changing is significant, or zero if none are optstop TRUE to return on option change, otherwise change the options value and continue Returns: pointer to the first significant opcode */ static const uschar* first_significant_code(const uschar *code, int *options, int optbit, BOOL optstop) { for (;;) { switch ((int)*code) { case OP_OPT: if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) { if (optstop) return code; *options = (int)code[1]; } code += 2; break; case OP_CREF: case OP_BRANUMBER: code += 3; break; case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY: code++; break; case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do code += (code[1] << 8) + code[2]; while (*code == OP_ALT); code += 3; break; default: return code; } } /* Control never reaches here */ } /************************************************* * Check for anchored expression * *************************************************/ /* Try to find out if this is an anchored regular expression. Consider each alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then it's anchored. However, if this is a multiline pattern, then only OP_SOD counts, since OP_CIRC can match in the middle. A branch is also implicitly anchored if it starts with .* and DOTALL is set, because that will try the rest of the pattern at all possible matching points, so there is no point trying them again. Arguments: code points to start of expression (the bracket) options points to the options setting Returns: TRUE or FALSE */ static BOOL is_anchored(register const uschar *code, int *options) { do { const uschar *scode = first_significant_code(code + 3, options, PCRE_MULTILINE, FALSE); register int op = *scode; if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) { if (!is_anchored(scode, options)) return FALSE; } else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) && (*options & PCRE_DOTALL) != 0) { if (scode[1] != OP_ANY) return FALSE; } else if (op != OP_SOD && ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC)) return FALSE; code += (code[1] << 8) + code[2]; } while (*code == OP_ALT); return TRUE; } /************************************************* * Check for starting with ^ or .* * *************************************************/ /* This is called to find out if every branch starts with ^ or .* so that "first char" processing can be done to speed things up in multiline matching and for non-DOTALL patterns that start with .* (which must start at the beginning or after \n). Argument: points to start of expression (the bracket) Returns: TRUE or FALSE */ static BOOL is_startline(const uschar *code) { do { const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE); register int op = *scode; if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) { if (!is_startline(scode)) return FALSE; } else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) { if (scode[1] != OP_ANY) return FALSE; } else if (op != OP_CIRC) return FALSE; code += (code[1] << 8) + code[2]; } while (*code == OP_ALT); return TRUE; } /************************************************* * Check for fixed first char * *************************************************/ /* Try to find out if there is a fixed first character. This is called for unanchored expressions, as it speeds up their processing quite considerably. Consider each alternative branch. If they all start with the same char, or with a bracket all of whose alternatives start with the same char (recurse ad lib), then we return that char, otherwise -1. Arguments: code points to start of expression (the bracket) options pointer to the options (used to check casing changes) Returns: -1 or the fixed first char */ static int find_firstchar(const uschar *code, int *options) { register int c = -1; do { int d; const uschar *scode = first_significant_code(code + 3, options, PCRE_CASELESS, TRUE); register int op = *scode; if (op >= OP_BRA) op = OP_BRA; switch(op) { default: return -1; case OP_BRA: case OP_ASSERT: case OP_ONCE: case OP_COND: if ((d = find_firstchar(scode, options)) < 0) return -1; if (c < 0) c = d; else if (c != d) return -1; break; case OP_EXACT: /* Fall through */ scode++; case OP_CHARS: /* Fall through */ scode++; case OP_PLUS: case OP_MINPLUS: if (c < 0) c = scode[1]; else if (c != scode[1]) return -1; break; } code += (code[1] << 8) + code[2]; } while (*code == OP_ALT); return c; } /************************************************* * Compile a Regular Expression * *************************************************/ /* This function takes a string and returns a pointer to a block of store holding a compiled version of the expression. Arguments: pattern the regular expression options various option bits errorptr pointer to pointer to error text erroroffset ptr offset in pattern where error was detected tables pointer to character tables or NULL Returns: pointer to compiled data block, or NULL on error, with errorptr and erroroffset set */ pcre * pcre_compile(const char *pattern, int options, const char **errorptr, int *erroroffset, const unsigned char *tables) { real_pcre *re; int length = 3; /* For initial BRA plus length */ int runlength; int c, reqchar, countlits; int bracount = 0; int top_backref = 0; int branch_extra = 0; int branch_newextra; unsigned int brastackptr = 0; size_t size; uschar *code; const uschar *ptr; compile_data compile_block; int brastack[BRASTACK_SIZE]; uschar bralenstack[BRASTACK_SIZE]; #ifdef DEBUG uschar *code_base, *code_end; #endif /* Can't support UTF8 unless PCRE has been compiled to include the code. */ #ifndef SUPPORT_UTF8 if ((options & PCRE_UTF8) != 0) { *errorptr = ERR32; return NULL; } #endif /* We can't pass back an error message if errorptr is NULL; I guess the best we can do is just return NULL. */ if (errorptr == NULL) return NULL; *errorptr = NULL; /* However, we can give a message for this error */ if (erroroffset == NULL) { *errorptr = ERR16; return NULL; } *erroroffset = 0; if ((options & ~PUBLIC_OPTIONS) != 0) { *errorptr = ERR17; return NULL; } /* Set up pointers to the individual character tables */ if (tables == NULL) tables = pcre_default_tables; compile_block.lcc = tables + lcc_offset; compile_block.fcc = tables + fcc_offset; compile_block.cbits = tables + cbits_offset; compile_block.ctypes = tables + ctypes_offset; /* Reflect pattern for debugging output */ DPRINTF(("------------------------------------------------------------------\n")); DPRINTF(("%s\n", pattern)); /* The first thing to do is to make a pass over the pattern to compute the amount of store required to hold the compiled code. This does not have to be perfect as long as errors are overestimates. At the same time we can detect any internal flag settings. Make an attempt to correct for any counted white space if an "extended" flag setting appears late in the pattern. We can't be so clever for #-comments. */ ptr = (const uschar *)(pattern - 1); while ((c = *(++ptr)) != 0) { int min, max; int class_charcount; int bracket_length; if ((options & PCRE_EXTENDED) != 0) { if ((compile_block.ctypes[c] & ctype_space) != 0) continue; if (c == '#') { /* The space before the ; is to avoid a warning on a silly compiler on the Macintosh. */ while ((c = *(++ptr)) != 0 && c != NEWLINE) ; continue; } } switch(c) { /* A backslashed item may be an escaped "normal" character or a character type. For a "normal" character, put the pointers and character back so that tests for whitespace etc. in the input are done correctly. */ case '\\': { const uschar *save_ptr = ptr; c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (c >= 0) { ptr = save_ptr; c = '\\'; goto NORMAL_CHAR; } } length++; /* A back reference needs an additional 2 bytes, plus either one or 5 bytes for a repeat. We also need to keep the value of the highest back reference. */ if (c <= -ESC_REF) { int refnum = -c - ESC_REF; if (refnum > top_backref) top_backref = refnum; length += 2; /* For single back reference */ if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block)) { ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if ((min == 0 && (max == 1 || max == -1)) || (min == 1 && max == -1)) length++; else length += 5; if (ptr[1] == '?') ptr++; } } continue; case '^': case '.': case '$': case '*': /* These repeats won't be after brackets; */ case '+': /* those are handled separately */ case '?': length++; continue; /* This covers the cases of repeats after a single char, metachar, class, or back reference. */ case '{': if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR; ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if ((min == 0 && (max == 1 || max == -1)) || (min == 1 && max == -1)) length++; else { length--; /* Uncount the original char or metachar */ if (min == 1) length++; else if (min > 0) length += 4; if (max > 0) length += 4; else length += 2; } if (ptr[1] == '?') ptr++; continue; /* An alternation contains an offset to the next branch or ket. If any ims options changed in the previous branch(es), and/or if we are in a lookbehind assertion, extra space will be needed at the start of the branch. This is handled by branch_extra. */ case '|': length += 3 + branch_extra; continue; /* A character class uses 33 characters. Don't worry about character types that aren't allowed in classes - they'll get picked up during the compile. A character class that contains only one character uses 2 or 3 bytes, depending on whether it is negated or not. Notice this where we can. */ case '[': class_charcount = 0; if (*(++ptr) == '^') ptr++; do { if (*ptr == '\\') { int ch = check_escape(&ptr, errorptr, bracount, options, TRUE, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (-ch == ESC_b) class_charcount++; else class_charcount = 10; } else class_charcount++; ptr++; } while (*ptr != 0 && *ptr != ']'); /* Repeats for negated single chars are handled by the general code */ if (class_charcount == 1) length += 3; else { length += 33; /* A repeat needs either 1 or 5 bytes. */ if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block)) { ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if ((min == 0 && (max == 1 || max == -1)) || (min == 1 && max == -1)) length++; else length += 5; if (ptr[1] == '?') ptr++; } } continue; /* Brackets may be genuine groups or special things */ case '(': branch_newextra = 0; bracket_length = 3; /* Handle special forms of bracket, which all start (? */ if (ptr[1] == '?') { int set, unset; int *optset; switch (c = ptr[2]) { /* Skip over comments entirely */ case '#': ptr += 3; while (*ptr != 0 && *ptr != ')') ptr++; if (*ptr == 0) { *errorptr = ERR18; goto PCRE_ERROR_RETURN; } continue; /* Non-referencing groups and lookaheads just move the pointer on, and then behave like a non-special bracket, except that they don't increment the count of extracting brackets. Ditto for the "once only" bracket, which is in Perl from version 5.005. */ case ':': case '=': case '!': case '>': ptr += 2; break; /* A recursive call to the regex is an extension, to provide the facility which can be obtained by $(?p{perl-code}) in Perl 5.6. */ case 'R': if (ptr[3] != ')') { *errorptr = ERR29; goto PCRE_ERROR_RETURN; } ptr += 3; length += 1; break; /* Lookbehinds are in Perl from version 5.005 */ case '<': if (ptr[3] == '=' || ptr[3] == '!') { ptr += 3; branch_newextra = 3; length += 3; /* For the first branch */ break; } *errorptr = ERR24; goto PCRE_ERROR_RETURN; /* Conditionals are in Perl from version 5.005. The bracket must either be followed by a number (for bracket reference) or by an assertion group. */ case '(': if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0) { ptr += 4; length += 3; while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++; if (*ptr != ')') { *errorptr = ERR26; goto PCRE_ERROR_RETURN; } } else /* An assertion must follow */ { ptr++; /* Can treat like ':' as far as spacing is concerned */ if (ptr[2] != '?' || (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') ) { ptr += 2; /* To get right offset in message */ *errorptr = ERR28; goto PCRE_ERROR_RETURN; } } break; /* Else loop checking valid options until ) is met. Anything else is an error. If we are without any brackets, i.e. at top level, the settings act as if specified in the options, so massage the options immediately. This is for backward compatibility with Perl 5.004. */ default: set = unset = 0; optset = &set; ptr += 2; for (;; ptr++) { c = *ptr; switch (c) { case 'i': *optset |= PCRE_CASELESS; continue; case 'm': *optset |= PCRE_MULTILINE; continue; case 's': *optset |= PCRE_DOTALL; continue; case 'x': *optset |= PCRE_EXTENDED; continue; case 'X': *optset |= PCRE_EXTRA; continue; case 'U': *optset |= PCRE_UNGREEDY; continue; case '-': optset = &unset; continue; /* A termination by ')' indicates an options-setting-only item; this is global at top level; otherwise nothing is done here and it is handled during the compiling process on a per-bracket-group basis. */ case ')': if (brastackptr == 0) { options = (options | set) & (~unset); set = unset = 0; /* To save length */ } /* Fall through */ /* A termination by ':' indicates the start of a nested group with the given options set. This is again handled at compile time, but we must allow for compiled space if any of the ims options are set. We also have to allow for resetting space at the end of the group, which is why 4 is added to the length and not just 2. If there are several changes of options within the same group, this will lead to an over-estimate on the length, but this shouldn't matter very much. We also have to allow for resetting options at the start of any alternations, which we do by setting branch_newextra to 2. Finally, we record whether the case-dependent flag ever changes within the regex. This is used by the "required character" code. */ case ':': if (((set|unset) & PCRE_IMS) != 0) { length += 4; branch_newextra = 2; if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED; } goto END_OPTIONS; /* Unrecognized option character */ default: *errorptr = ERR12; goto PCRE_ERROR_RETURN; } } /* If we hit a closing bracket, that's it - this is a freestanding option-setting. We need to ensure that branch_extra is updated if necessary. The only values branch_newextra can have here are 0 or 2. If the value is 2, then branch_extra must either be 2 or 5, depending on whether this is a lookbehind group or not. */ END_OPTIONS: if (c == ')') { if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3)) branch_extra += branch_newextra; continue; } /* If options were terminated by ':' control comes here. Fall through to handle the group below. */ } } /* Extracting brackets must be counted so we can process escapes in a Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to need an additional 3 bytes of store per extracting bracket. */ else { bracount++; if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3; } /* Save length for computing whole length at end if there's a repeat that requires duplication of the group. Also save the current value of branch_extra, and start the new group with the new value. If non-zero, this will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */ if (brastackptr >= sizeof(brastack)/sizeof(int)) { *errorptr = ERR19; goto PCRE_ERROR_RETURN; } bralenstack[brastackptr] = branch_extra; branch_extra = branch_newextra; brastack[brastackptr++] = length; length += bracket_length; continue; /* Handle ket. Look for subsequent max/min; for certain sets of values we have to replicate this bracket up to that many times. If brastackptr is 0 this is an unmatched bracket which will generate an error, but take care not to try to access brastack[-1] when computing the length and restoring the branch_extra value. */ case ')': length += 3; { int minval = 1; int maxval = 1; int duplength; if (brastackptr > 0) { duplength = length - brastack[--brastackptr]; branch_extra = bralenstack[brastackptr]; } else duplength = 0; /* Leave ptr at the final char; for read_repeat_counts this happens automatically; for the others we need an increment. */ if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block)) { ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; } else if (c == '*') { minval = 0; maxval = -1; ptr++; } else if (c == '+') { maxval = -1; ptr++; } else if (c == '?') { minval = 0; ptr++; } /* If the minimum is zero, we have to allow for an OP_BRAZERO before the group, and if the maximum is greater than zero, we have to replicate maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting bracket set - hence the 7. */ if (minval == 0) { length++; if (maxval > 0) length += (maxval - 1) * (duplength + 7); } /* When the minimum is greater than zero, 1 we have to replicate up to minval-1 times, with no additions required in the copies. Then, if there is a limited maximum we have to replicate up to maxval-1 times allowing for a BRAZERO item before each optional copy and nesting brackets for all but one of the optional copies. */ else { length += (minval - 1) * duplength; if (maxval > minval) /* Need this test as maxval=-1 means no limit */ length += (maxval - minval) * (duplength + 7) - 6; } } continue; /* Non-special character. For a run of such characters the length required is the number of characters + 2, except that the maximum run length is 255. We won't get a skipped space or a non-data escape or the start of a # comment as the first character, so the length can't be zero. */ NORMAL_CHAR: default: length += 2; runlength = 0; do { if ((options & PCRE_EXTENDED) != 0) { if ((compile_block.ctypes[c] & ctype_space) != 0) continue; if (c == '#') { /* The space before the ; is to avoid a warning on a silly compiler on the Macintosh. */ while ((c = *(++ptr)) != 0 && c != NEWLINE) ; continue; } } /* Backslash may introduce a data char or a metacharacter; stop the string before the latter. */ if (c == '\\') { const uschar *saveptr = ptr; c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block); if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (c < 0) { ptr = saveptr; break; } #ifdef SUPPORT_UTF8 if (c > 127 && (options & PCRE_UTF8) != 0) { int i; for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) if (c <= utf8_table1[i]) break; runlength += i; } #endif } /* Ordinary character or single-char escape */ runlength++; } /* This "while" is the end of the "do" above. */ while (runlength < MAXLIT && (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0); ptr--; length += runlength; continue; } } length += 4; /* For final KET and END */ if (length > 65539) { *errorptr = ERR20; return NULL; } /* Compute the size of data block needed and get it, either from malloc or externally provided function. We specify "code[0]" in the offsetof() expression rather than just "code", because it has been reported that one broken compiler fails on "code" because it is also an independent variable. It should make no difference to the value of the offsetof(). */ size = length + offsetof(real_pcre, code[0]); re = (real_pcre *)(pcre_malloc)(size); if (re == NULL) { *errorptr = ERR21; return NULL; } /* Put in the magic number, and save the size, options, and table pointer */ re->magic_number = MAGIC_NUMBER; re->size = size; re->options = options; re->tables = tables; /* Set up a starting, non-extracting bracket, then compile the expression. On error, *errorptr will be set non-NULL, so we don't need to look at the result of the function here. */ ptr = (const uschar *)pattern; code = re->code; *code = OP_BRA; bracount = 0; (void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, 0, &reqchar, &countlits, &compile_block); re->top_bracket = bracount; re->top_backref = top_backref; /* If not reached end of pattern on success, there's an excess bracket. */ if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22; /* Fill in the terminating state and check for disastrous overflow, but if debugging, leave the test till after things are printed out. */ *code++ = OP_END; #ifndef DEBUG if (code - re->code > length) *errorptr = ERR23; #endif /* Give an error if there's back reference to a non-existent capturing subpattern. */ if (top_backref > re->top_bracket) *errorptr = ERR15; /* Failed to compile */ if (*errorptr != NULL) { (pcre_free)(re); PCRE_ERROR_RETURN: *erroroffset = ptr - (const uschar *)pattern; return NULL; } /* If the anchored option was not passed, set flag if we can determine that the pattern is anchored by virtue of ^ characters or \A or anything else (such as starting with .* when DOTALL is set). Otherwise, see if we can determine what the first character has to be, because that speeds up unanchored matches no end. If not, see if we can set the PCRE_STARTLINE flag. This is helpful for multiline matches when all branches start with ^. and also when all branches start with .* for non-DOTALL matches. */ if ((options & PCRE_ANCHORED) == 0) { int temp_options = options; if (is_anchored(re->code, &temp_options)) re->options |= PCRE_ANCHORED; else { int ch = find_firstchar(re->code, &temp_options); if (ch >= 0) { re->first_char = ch; re->options |= PCRE_FIRSTSET; } else if (is_startline(re->code)) re->options |= PCRE_STARTLINE; } } /* Save the last required character if there are at least two literal characters on all paths, or if there is no first character setting. */ if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0)) { re->req_char = reqchar; re->options |= PCRE_REQCHSET; } /* Print out the compiled data for debugging */ #ifdef DEBUG printf("Length = %d top_bracket = %d top_backref = %d\n", length, re->top_bracket, re->top_backref); if (re->options != 0) { printf("%s%s%s%s%s%s%s%s%s\n", ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "", ((re->options & PCRE_CASELESS) != 0)? "caseless " : "", ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "", ((re->options & PCRE_EXTENDED) != 0)? "extended " : "", ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "", ((re->options & PCRE_DOTALL) != 0)? "dotall " : "", ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "", ((re->options & PCRE_EXTRA) != 0)? "extra " : "", ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : ""); } if ((re->options & PCRE_FIRSTSET) != 0) { if (isprint(re->first_char)) printf("First char = %c\n", re->first_char); else printf("First char = \\x%02x\n", re->first_char); } if ((re->options & PCRE_REQCHSET) != 0) { if (isprint(re->req_char)) printf("Req char = %c\n", re->req_char); else printf("Req char = \\x%02x\n", re->req_char); } code_end = code; code_base = code = re->code; while (code < code_end) { int charlength; printf("%3d ", code - code_base); if (*code >= OP_BRA) { if (*code - OP_BRA > EXTRACT_BASIC_MAX) printf("%3d Bra extra", (code[1] << 8) + code[2]); else printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA); code += 2; } else switch(*code) { case OP_OPT: printf(" %.2x %s", code[1], OP_names[*code]); code++; break; case OP_CHARS: charlength = *(++code); printf("%3d ", charlength); while (charlength-- > 0) if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c); break; case OP_KETRMAX: case OP_KETRMIN: case OP_ALT: case OP_KET: case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_REVERSE: case OP_BRANUMBER: case OP_COND: case OP_CREF: printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]); code += 2; break; case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: if (*code >= OP_TYPESTAR) printf(" %s", OP_names[code[1]]); else if (isprint(c = code[1])) printf(" %c", c); else printf(" \\x%02x", c); printf("%s", OP_names[*code++]); break; case OP_EXACT: case OP_UPTO: case OP_MINUPTO: if (isprint(c = code[3])) printf(" %c{", c); else printf(" \\x%02x{", c); if (*code != OP_EXACT) printf("0,"); printf("%d}", (code[1] << 8) + code[2]); if (*code == OP_MINUPTO) printf("?"); code += 3; break; case OP_TYPEEXACT: case OP_TYPEUPTO: case OP_TYPEMINUPTO: printf(" %s{", OP_names[code[3]]); if (*code != OP_TYPEEXACT) printf(","); printf("%d}", (code[1] << 8) + code[2]); if (*code == OP_TYPEMINUPTO) printf("?"); code += 3; break; case OP_NOT: if (isprint(c = *(++code))) printf(" [^%c]", c); else printf(" [^\\x%02x]", c); break; case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: if (isprint(c = code[1])) printf(" [^%c]", c); else printf(" [^\\x%02x]", c); printf("%s", OP_names[*code++]); break; case OP_NOTEXACT: case OP_NOTUPTO: case OP_NOTMINUPTO: if (isprint(c = code[3])) printf(" [^%c]{", c); else printf(" [^\\x%02x]{", c); if (*code != OP_NOTEXACT) printf(","); printf("%d}", (code[1] << 8) + code[2]); if (*code == OP_NOTMINUPTO) printf("?"); code += 3; break; case OP_REF: printf(" \\%d", (code[1] << 8) | code[2]); code += 3; goto CLASS_REF_REPEAT; case OP_CLASS: { int i, min, max; code++; printf(" ["); for (i = 0; i < 256; i++) { if ((code[i/8] & (1 << (i&7))) != 0) { int j; for (j = i+1; j < 256; j++) if ((code[j/8] & (1 << (j&7))) == 0) break; if (i == '-' || i == ']') printf("\\"); if (isprint(i)) printf("%c", i); else printf("\\x%02x", i); if (--j > i) { printf("-"); if (j == '-' || j == ']') printf("\\"); if (isprint(j)) printf("%c", j); else printf("\\x%02x", j); } i = j; } } printf("]"); code += 32; CLASS_REF_REPEAT: switch(*code) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: printf("%s", OP_names[*code]); break; case OP_CRRANGE: case OP_CRMINRANGE: min = (code[1] << 8) + code[2]; max = (code[3] << 8) + code[4]; if (max == 0) printf("{%d,}", min); else printf("{%d,%d}", min, max); if (*code == OP_CRMINRANGE) printf("?"); code += 4; break; default: code--; } } break; /* Anything else is just a one-node item */ default: printf(" %s", OP_names[*code]); break; } code++; printf("\n"); } printf("------------------------------------------------------------------\n"); /* This check is done here in the debugging case so that the code that was compiled can be seen. */ if (code - re->code > length) { *errorptr = ERR23; (pcre_free)(re); *erroroffset = ptr - (uschar *)pattern; return NULL; } #endif return (pcre *)re; } /************************************************* * Match a back-reference * *************************************************/ /* If a back reference hasn't been set, the length that is passed is greater than the number of characters left in the string, so the match fails. Arguments: offset index into the offset vector eptr points into the subject length length to be matched md points to match data block ims the ims flags Returns: TRUE if matched */ static BOOL match_ref(int offset, register const uschar *eptr, int length, match_data *md, unsigned long int ims) { const uschar *p = md->start_subject + md->offset_vector[offset]; #ifdef DEBUG if (eptr >= md->end_subject) printf("matching subject "); else { printf("matching subject "); pchars(eptr, length, TRUE, md); } printf(" against backref "); pchars(p, length, FALSE, md); printf("\n"); #endif /* Always fail if not enough characters left */ if (length > md->end_subject - eptr) return FALSE; /* Separate the caselesss case for speed */ if ((ims & PCRE_CASELESS) != 0) { while (length-- > 0) if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; } else { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } return TRUE; } /************************************************* * Match from current position * *************************************************/ /* On entry ecode points to the first opcode, and eptr to the first character in the subject string, while eptrb holds the value of eptr at the start of the last bracketed group - used for breaking infinite loops matching zero-length strings. Arguments: eptr pointer in subject ecode position in code offset_top current top pointer md pointer to "static" info for the match ims current /i, /m, and /s options eptrb pointer to chain of blocks containing eptr at start of brackets - for testing for empty matches flags can contain match_condassert - this is an assertion condition match_isgroup - this is the start of a bracketed group Returns: TRUE if matched */ static BOOL match(register const uschar *eptr, register const uschar *ecode, int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, int flags) { unsigned long int original_ims = ims; /* Save for resetting on ')' */ eptrblock newptrb; /* At the start of a bracketed group, add the current subject pointer to the stack of such pointers, to be re-instated at the end of the group when we hit the closing ket. When match() is called in other circumstances, we don't add to the stack. */ if ((flags & match_isgroup) != 0) { newptrb.prev = eptrb; newptrb.saved_eptr = eptr; eptrb = &newptrb; } /* Now start processing the operations. */ for (;;) { int op = (int)*ecode; int min, max, ctype; register int i; register int c; BOOL minimize = FALSE; /* Opening capturing bracket. If there is space in the offset vector, save the current subject position in the working slot at the top of the vector. We mustn't change the current values of the data slot, because they may be set from a previous iteration of this group, and be referred to by a reference inside the group. If the bracket fails to match, we need to restore this value and also the values of the final offsets, in case they were set by a previous iteration of the same bracket. If there isn't enough space in the offset vector, treat this as if it were a non-capturing bracket. Don't worry about setting the flag for the error case here; that is handled in the code for KET. */ if (op > OP_BRA) { int offset; int number = op - OP_BRA; /* For extended extraction brackets (large number), we have to fish out the number from a dummy opcode at the start. */ if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5]; offset = number << 1; #ifdef DEBUG printf("start bracket %d subject=", number); pchars(eptr, 16, TRUE, md); printf("\n"); #endif if (offset < md->offset_max) { int save_offset1 = md->offset_vector[offset]; int save_offset2 = md->offset_vector[offset+1]; int save_offset3 = md->offset_vector[md->offset_end - number]; DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); md->offset_vector[md->offset_end - number] = eptr - md->start_subject; do { if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; ecode += (ecode[1] << 8) + ecode[2]; } while (*ecode == OP_ALT); DPRINTF(("bracket %d failed\n", number)); md->offset_vector[offset] = save_offset1; md->offset_vector[offset+1] = save_offset2; md->offset_vector[md->offset_end - number] = save_offset3; return FALSE; } /* Insufficient room for saving captured contents */ else op = OP_BRA; } /* Other types of node can be handled by a switch */ switch(op) { case OP_BRA: /* Non-capturing bracket: optimized */ DPRINTF(("start bracket 0\n")); do { if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; ecode += (ecode[1] << 8) + ecode[2]; } while (*ecode == OP_ALT); DPRINTF(("bracket 0 failed\n")); return FALSE; /* Conditional group: compilation checked that there are no more than two branches. If the condition is false, skipping the first branch takes us past the end if there is only one branch, but that's OK because that is exactly what going to the ket would do. */ case OP_COND: if (ecode[3] == OP_CREF) /* Condition is extraction test */ { int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */ return match(eptr, ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)? 6 : 3 + (ecode[1] << 8) + ecode[2]), offset_top, md, ims, eptrb, match_isgroup); } /* The condition is an assertion. Call match() to evaluate it - setting the final argument TRUE causes it to stop at the end of an assertion. */ else { if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_condassert | match_isgroup)) { ecode += 3 + (ecode[4] << 8) + ecode[5]; while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2]; } else ecode += (ecode[1] << 8) + ecode[2]; return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup); } /* Control never reaches here */ /* Skip over conditional reference or large extraction number data if encountered. */ case OP_CREF: case OP_BRANUMBER: ecode += 3; break; /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched an empty string - recursion will then try other alternatives, if any. */ case OP_END: if (md->notempty && eptr == md->start_match) return FALSE; md->end_match_ptr = eptr; /* Record where we ended */ md->end_offset_top = offset_top; /* and how many extracts were taken */ return TRUE; /* Change option settings */ case OP_OPT: ims = ecode[1]; ecode += 2; DPRINTF(("ims set to %02lx\n", ims)); break; /* Assertion brackets. Check the alternative branches in turn - the matching won't pass the KET for an assertion. If any one branch matches, the assertion is true. Lookbehind assertions have an OP_REVERSE item at the start of each branch to move the current point backwards, so the code at this level is identical to the lookahead case. */ case OP_ASSERT: case OP_ASSERTBACK: do { if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break; ecode += (ecode[1] << 8) + ecode[2]; } while (*ecode == OP_ALT); if (*ecode == OP_KET) return FALSE; /* If checking an assertion for a condition, return TRUE. */ if ((flags & match_condassert) != 0) return TRUE; /* Continue from after the assertion, updating the offsets high water mark, since extracts may have been taken during the assertion. */ do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT); ecode += 3; offset_top = md->end_offset_top; continue; /* Negative assertion: all branches must fail to match */ case OP_ASSERT_NOT: case OP_ASSERTBACK_NOT: do { if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) return FALSE; ecode += (ecode[1] << 8) + ecode[2]; } while (*ecode == OP_ALT); if ((flags & match_condassert) != 0) return TRUE; ecode += 3; continue; /* Move the subject pointer back. This occurs only at the start of each branch of a lookbehind assertion. If we are too close to the start to move back, this match function fails. When working with UTF-8 we move back a number of characters, not bytes. */ case OP_REVERSE: #ifdef SUPPORT_UTF8 c = (ecode[1] << 8) + ecode[2]; for (i = 0; i < c; i++) { eptr--; BACKCHAR(eptr) } #else eptr -= (ecode[1] << 8) + ecode[2]; #endif if (eptr < md->start_subject) return FALSE; ecode += 3; break; /* Recursion matches the current regex, nested. If there are any capturing brackets started but not finished, we have to save their starting points and reinstate them after the recursion. However, we don't know how many such there are (offset_top records the completed total) so we just have to save all the potential data. There may be up to 99 such values, which is a bit large to put on the stack, but using malloc for small numbers seems expensive. As a compromise, the stack is used when there are fewer than 16 values to store; otherwise malloc is used. A problem is what to do if the malloc fails ... there is no way of returning to the top level with an error. Save the top 15 values on the stack, and accept that the rest may be wrong. */ case OP_RECURSE: { BOOL rc; int *save; int stacksave[15]; c = md->offset_max; if (c < 16) save = stacksave; else { save = (int *)(pcre_malloc)((c+1) * sizeof(int)); if (save == NULL) { save = stacksave; c = 15; } } for (i = 1; i <= c; i++) save[i] = md->offset_vector[md->offset_end - i]; rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb, match_isgroup); for (i = 1; i <= c; i++) md->offset_vector[md->offset_end - i] = save[i]; if (save != stacksave) (pcre_free)(save); if (!rc) return FALSE; /* In case the recursion has set more capturing values, save the final number, then move along the subject till after the recursive match, and advance one byte in the pattern code. */ offset_top = md->end_offset_top; eptr = md->end_match_ptr; ecode++; } break; /* "Once" brackets are like assertion brackets except that after a match, the point in the subject string is not moved back. Thus there can never be a move back into the brackets. Check the alternative branches in turn - the matching won't pass the KET for this kind of subpattern. If any one branch matches, we carry on as at the end of a normal bracket, leaving the subject pointer. */ case OP_ONCE: { const uschar *prev = ecode; const uschar *saved_eptr = eptr; do { if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup)) break; ecode += (ecode[1] << 8) + ecode[2]; } while (*ecode == OP_ALT); /* If hit the end of the group (which could be repeated), fail */ if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE; /* Continue as from after the assertion, updating the offsets high water mark, since extracts may have been taken. */ do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT); offset_top = md->end_offset_top; eptr = md->end_match_ptr; /* For a non-repeating ket, just continue at this level. This also happens for a repeating ket if no characters were matched in the group. This is the forcible breaking of infinite loops as implemented in Perl 5.005. If there is an options reset, it will get obeyed in the normal course of events. */ if (*ecode == OP_KET || eptr == saved_eptr) { ecode += 3; break; } /* The repeating kets try the rest of the pattern or restart from the preceding bracket, in the appropriate order. We need to reset any options that changed within the bracket before re-running it, so check the next opcode. */ if (ecode[3] == OP_OPT) { ims = (ims & ~PCRE_IMS) | ecode[4]; DPRINTF(("ims set to %02lx at group repeat\n", ims)); } if (*ecode == OP_KETRMIN) { if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) || match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; } else /* OP_KETRMAX */ { if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) || match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE; } } return FALSE; /* An alternation is the end of a branch; scan along to find the end of the bracketed group and go to there. */ case OP_ALT: do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT); break; /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating that it may occur zero times. It may repeat infinitely, or not at all - i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper repeat limits are compiled as a number of copies, with the optional ones preceded by BRAZERO or BRAMINZERO. */ case OP_BRAZERO: { const uschar *next = ecode+1; if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; do next += (next[1] << 8) + next[2]; while (*next == OP_ALT); ecode = next + 3; } break; case OP_BRAMINZERO: { const uschar *next = ecode+1; do next += (next[1] << 8) + next[2]; while (*next == OP_ALT); if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; ecode++; } break; /* End of a group, repeated or non-repeating. If we are at the end of an assertion "group", stop matching and return TRUE, but record the current high water mark for use by positive assertions. Do this also for the "once" (not-backup up) groups. */ case OP_KET: case OP_KETRMIN: case OP_KETRMAX: { const uschar *prev = ecode - (ecode[1] << 8) - ecode[2]; const uschar *saved_eptr = eptrb->saved_eptr; eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */ if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || *prev == OP_ONCE) { md->end_match_ptr = eptr; /* For ONCE */ md->end_offset_top = offset_top; return TRUE; } /* In all other cases except a conditional group we have to check the group number back at the start and if necessary complete handling an extraction by setting the offsets and bumping the high water mark. */ if (*prev != OP_COND) { int offset; int number = *prev - OP_BRA; /* For extended extraction brackets (large number), we have to fish out the number from a dummy opcode at the start. */ if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5]; offset = number << 1; #ifdef DEBUG printf("end bracket %d", number); printf("\n"); #endif if (number > 0) { if (offset >= md->offset_max) md->offset_overflow = TRUE; else { md->offset_vector[offset] = md->offset_vector[md->offset_end - number]; md->offset_vector[offset+1] = eptr - md->start_subject; if (offset_top <= offset) offset_top = offset + 2; } } } /* Reset the value of the ims flags, in case they got changed during the group. */ ims = original_ims; DPRINTF(("ims reset to %02lx\n", ims)); /* For a non-repeating ket, just continue at this level. This also happens for a repeating ket if no characters were matched in the group. This is the forcible breaking of infinite loops as implemented in Perl 5.005. If there is an options reset, it will get obeyed in the normal course of events. */ if (*ecode == OP_KET || eptr == saved_eptr) { ecode += 3; break; } /* The repeating kets try the rest of the pattern or restart from the preceding bracket, in the appropriate order. */ if (*ecode == OP_KETRMIN) { if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) || match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup)) return TRUE; } else /* OP_KETRMAX */ { if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) || match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE; } } return FALSE; /* Start of subject unless notbol, or after internal newline if multiline */ case OP_CIRC: if (md->notbol && eptr == md->start_subject) return FALSE; if ((ims & PCRE_MULTILINE) != 0) { if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE; ecode++; break; } /* ... else fall through */ /* Start of subject assertion */ case OP_SOD: if (eptr != md->start_subject) return FALSE; ecode++; break; /* Assert before internal newline if multiline, or before a terminating newline unless endonly is set, else end of subject unless noteol is set. */ case OP_DOLL: if ((ims & PCRE_MULTILINE) != 0) { if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; } else { if (md->noteol) return FALSE; } ecode++; break; } else { if (md->noteol) return FALSE; if (!md->endonly) { if (eptr < md->end_subject - 1 || (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE; ecode++; break; } } /* ... else fall through */ /* End of subject assertion (\z) */ case OP_EOD: if (eptr < md->end_subject) return FALSE; ecode++; break; /* End of subject or ending \n assertion (\Z) */ case OP_EODN: if (eptr < md->end_subject - 1 || (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE; ecode++; break; /* Word boundary assertions */ case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: { BOOL prev_is_word = (eptr != md->start_subject) && ((md->ctypes[eptr[-1]] & ctype_word) != 0); BOOL cur_is_word = (eptr < md->end_subject) && ((md->ctypes[*eptr] & ctype_word) != 0); if ((*ecode++ == OP_WORD_BOUNDARY)? cur_is_word == prev_is_word : cur_is_word != prev_is_word) return FALSE; } break; /* Match a single character type; inline for speed */ case OP_ANY: if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE) return FALSE; if (eptr++ >= md->end_subject) return FALSE; #ifdef SUPPORT_UTF8 if (md->utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; #endif ecode++; break; case OP_NOT_DIGIT: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE; ecode++; break; case OP_DIGIT: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE; ecode++; break; case OP_NOT_WHITESPACE: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_space) != 0) return FALSE; ecode++; break; case OP_WHITESPACE: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_space) == 0) return FALSE; ecode++; break; case OP_NOT_WORDCHAR: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_word) != 0) return FALSE; ecode++; break; case OP_WORDCHAR: if (eptr >= md->end_subject || (md->ctypes[*eptr++] & ctype_word) == 0) return FALSE; ecode++; break; /* Match a back reference, possibly repeatedly. Look past the end of the item to see if there is repeat information following. The code is similar to that for character classes, but repeated for efficiency. Then obey similar code to character type repeats - written out again for speed. However, if the referenced string is the empty string, always treat it as matched, any number of times (otherwise there could be infinite loops). */ case OP_REF: { int length; int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */ ecode += 3; /* Advance past item */ /* If the reference is unset, set the length to be longer than the amount of subject left; this ensures that every attempt at a match fails. We can't just fail here, because of the possibility of quantifiers with zero minima. */ length = (offset >= offset_top || md->offset_vector[offset] < 0)? md->end_subject - eptr + 1 : md->offset_vector[offset+1] - md->offset_vector[offset]; /* Set up for repetition, or handle the non-repeated case */ switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: c = *ecode++ - OP_CRSTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; break; case OP_CRRANGE: case OP_CRMINRANGE: minimize = (*ecode == OP_CRMINRANGE); min = (ecode[1] << 8) + ecode[2]; max = (ecode[3] << 8) + ecode[4]; if (max == 0) max = INT_MAX; ecode += 5; break; default: /* No repeat follows */ if (!match_ref(offset, eptr, length, md, ims)) return FALSE; eptr += length; continue; /* With the main loop */ } /* If the length of the reference is zero, just continue with the main loop. */ if (length == 0) continue; /* First, ensure the minimum number of matches are present. We get back the length of the reference string explicitly rather than passing the address of eptr, so that eptr can be a register variable. */ for (i = 1; i <= min; i++) { if (!match_ref(offset, eptr, length, md, ims)) return FALSE; eptr += length; } /* If min = max, continue at the same level without recursion. They are not both allowed to be zero. */ if (min == max) continue; /* If minimizing, keep trying and advancing the pointer */ if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || !match_ref(offset, eptr, length, md, ims)) return FALSE; eptr += length; } /* Control never gets here */ } /* If maximizing, find the longest string and work backwards */ else { const uschar *pp = eptr; for (i = min; i < max; i++) { if (!match_ref(offset, eptr, length, md, ims)) break; eptr += length; } while (eptr >= pp) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; eptr -= length; } return FALSE; } } /* Control never gets here */ /* Match a character class, possibly repeatedly. Look past the end of the item to see if there is repeat information following. Then obey similar code to character type repeats - written out again for speed. */ case OP_CLASS: { const uschar *data = ecode + 1; /* Save for matching */ ecode += 33; /* Advance past the item */ switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: c = *ecode++ - OP_CRSTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; break; case OP_CRRANGE: case OP_CRMINRANGE: minimize = (*ecode == OP_CRMINRANGE); min = (ecode[1] << 8) + ecode[2]; max = (ecode[3] << 8) + ecode[4]; if (max == 0) max = INT_MAX; ecode += 5; break; default: /* No repeat follows */ min = max = 1; break; } /* First, ensure the minimum number of matches are present. */ for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) return FALSE; GETCHARINC(c, eptr) /* Get character; increment eptr */ #ifdef SUPPORT_UTF8 /* We do not yet support class members > 255 */ if (c > 255) return FALSE; #endif if ((data[c/8] & (1 << (c&7))) != 0) continue; return FALSE; } /* If max == min we can continue with the main loop without the need to recurse. */ if (min == max) continue; /* If minimizing, keep testing the rest of the expression and advancing the pointer while it matches the class. */ if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject) return FALSE; GETCHARINC(c, eptr) /* Get character; increment eptr */ #ifdef SUPPORT_UTF8 /* We do not yet support class members > 255 */ if (c > 255) return FALSE; #endif if ((data[c/8] & (1 << (c&7))) != 0) continue; return FALSE; } /* Control never gets here */ } /* If maximizing, find the longest possible run, then work backwards. */ else { const uschar *pp = eptr; int len = 1; for (i = min; i < max; i++) { if (eptr >= md->end_subject) break; GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */ #ifdef SUPPORT_UTF8 /* We do not yet support class members > 255 */ if (c > 255) break; #endif if ((data[c/8] & (1 << (c&7))) == 0) break; eptr += len; } while (eptr >= pp) { if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; #ifdef SUPPORT_UTF8 BACKCHAR(eptr) #endif } return FALSE; } } /* Control never gets here */ /* Match a run of characters */ case OP_CHARS: { register int length = ecode[1]; ecode += 2; #ifdef DEBUG /* Sigh. Some compilers never learn. */ if (eptr >= md->end_subject) printf("matching subject against pattern "); else { printf("matching subject "); pchars(eptr, length, TRUE, md); printf(" against pattern "); } pchars(ecode, length, FALSE, md); printf("\n"); #endif if (length > md->end_subject - eptr) return FALSE; if ((ims & PCRE_CASELESS) != 0) { while (length-- > 0) if (md->lcc[*ecode++] != md->lcc[*eptr++]) return FALSE; } else { while (length-- > 0) if (*ecode++ != *eptr++) return FALSE; } } break; /* Match a single character repeatedly; different opcodes share code. */ case OP_EXACT: min = max = (ecode[1] << 8) + ecode[2]; ecode += 3; goto REPEATCHAR; case OP_UPTO: case OP_MINUPTO: min = 0; max = (ecode[1] << 8) + ecode[2]; minimize = *ecode == OP_MINUPTO; ecode += 3; goto REPEATCHAR; case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: c = *ecode++ - OP_STAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single-character matches. We can give up quickly if there are fewer than the minimum number of characters left in the subject. */ REPEATCHAR: if (min > md->end_subject - eptr) return FALSE; c = *ecode++; /* The code is duplicated for the caseless and caseful cases, for speed, since matching characters is likely to be quite common. First, ensure the minimum number of matches are present. If min = max, continue at the same level without recursing. Otherwise, if minimizing, keep trying the rest of the expression and advancing one matching character if failing, up to the maximum. Alternatively, if maximizing, find the maximum number of characters and work backwards. */ DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max, max, eptr)); if ((ims & PCRE_CASELESS) != 0) { c = md->lcc[c]; for (i = 1; i <= min; i++) if (c != md->lcc[*eptr++]) return FALSE; if (min == max) continue; if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject || c != md->lcc[*eptr++]) return FALSE; } /* Control never gets here */ } else { const uschar *pp = eptr; for (i = min; i < max; i++) { if (eptr >= md->end_subject || c != md->lcc[*eptr]) break; eptr++; } while (eptr >= pp) if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; return FALSE; } /* Control never gets here */ } /* Caseful comparisons */ else { for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE; if (min == max) continue; if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE; } /* Control never gets here */ } else { const uschar *pp = eptr; for (i = min; i < max; i++) { if (eptr >= md->end_subject || c != *eptr) break; eptr++; } while (eptr >= pp) if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; return FALSE; } } /* Control never gets here */ /* Match a negated single character */ case OP_NOT: if (eptr >= md->end_subject) return FALSE; ecode++; if ((ims & PCRE_CASELESS) != 0) { if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE; } else { if (*ecode++ == *eptr++) return FALSE; } break; /* Match a negated single character repeatedly. This is almost a repeat of the code for a repeated single character, but I haven't found a nice way of commoning these up that doesn't require a test of the positive/negative option for each character match. Maybe that wouldn't add very much to the time taken, but character matching *is* what this is all about... */ case OP_NOTEXACT: min = max = (ecode[1] << 8) + ecode[2]; ecode += 3; goto REPEATNOTCHAR; case OP_NOTUPTO: case OP_NOTMINUPTO: min = 0; max = (ecode[1] << 8) + ecode[2]; minimize = *ecode == OP_NOTMINUPTO; ecode += 3; goto REPEATNOTCHAR; case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: c = *ecode++ - OP_NOTSTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single-character matches. We can give up quickly if there are fewer than the minimum number of characters left in the subject. */ REPEATNOTCHAR: if (min > md->end_subject - eptr) return FALSE; c = *ecode++; /* The code is duplicated for the caseless and caseful cases, for speed, since matching characters is likely to be quite common. First, ensure the minimum number of matches are present. If min = max, continue at the same level without recursing. Otherwise, if minimizing, keep trying the rest of the expression and advancing one matching character if failing, up to the maximum. Alternatively, if maximizing, find the maximum number of characters and work backwards. */ DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max, max, eptr)); if ((ims & PCRE_CASELESS) != 0) { c = md->lcc[c]; for (i = 1; i <= min; i++) if (c == md->lcc[*eptr++]) return FALSE; if (min == max) continue; if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject || c == md->lcc[*eptr++]) return FALSE; } /* Control never gets here */ } else { const uschar *pp = eptr; for (i = min; i < max; i++) { if (eptr >= md->end_subject || c == md->lcc[*eptr]) break; eptr++; } while (eptr >= pp) if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; return FALSE; } /* Control never gets here */ } /* Caseful comparisons */ else { for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE; if (min == max) continue; if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE; } /* Control never gets here */ } else { const uschar *pp = eptr; for (i = min; i < max; i++) { if (eptr >= md->end_subject || c == *eptr) break; eptr++; } while (eptr >= pp) if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; return FALSE; } } /* Control never gets here */ /* Match a single character type repeatedly; several different opcodes share code. This is very similar to the code for single characters, but we repeat it in the interests of efficiency. */ case OP_TYPEEXACT: min = max = (ecode[1] << 8) + ecode[2]; minimize = TRUE; ecode += 3; goto REPEATTYPE; case OP_TYPEUPTO: case OP_TYPEMINUPTO: min = 0; max = (ecode[1] << 8) + ecode[2]; minimize = *ecode == OP_TYPEMINUPTO; ecode += 3; goto REPEATTYPE; case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: c = *ecode++ - OP_TYPESTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single character type matches */ REPEATTYPE: ctype = *ecode++; /* Code for the character type */ /* First, ensure the minimum number of matches are present. Use inline code for maximizing the speed, and do the type test once at the start (i.e. keep it out of the loop). Also we can test that there are at least the minimum number of bytes before we start, except when doing '.' in UTF8 mode. Leave the test in in all cases; in the special case we have to test after each character. */ if (min > md->end_subject - eptr) return FALSE; if (min > 0) switch(ctype) { case OP_ANY: #ifdef SUPPORT_UTF8 if (md->utf8) { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject || (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0)) return FALSE; while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; } break; } #endif /* Non-UTF8 can be faster */ if ((ims & PCRE_DOTALL) == 0) { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; } else eptr += min; break; case OP_NOT_DIGIT: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE; break; case OP_DIGIT: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE; break; case OP_NOT_WHITESPACE: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE; break; case OP_WHITESPACE: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE; break; case OP_NOT_WORDCHAR: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_word) != 0) return FALSE; break; case OP_WORDCHAR: for (i = 1; i <= min; i++) if ((md->ctypes[*eptr++] & ctype_word) == 0) return FALSE; break; } /* If min = max, continue at the same level without recursing */ if (min == max) continue; /* If minimizing, we have to test the rest of the pattern before each subsequent match. */ if (minimize) { for (i = min;; i++) { if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; if (i >= max || eptr >= md->end_subject) return FALSE; c = *eptr++; switch(ctype) { case OP_ANY: if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE; #ifdef SUPPORT_UTF8 if (md->utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; #endif break; case OP_NOT_DIGIT: if ((md->ctypes[c] & ctype_digit) != 0) return FALSE; break; case OP_DIGIT: if ((md->ctypes[c] & ctype_digit) == 0) return FALSE; break; case OP_NOT_WHITESPACE: if ((md->ctypes[c] & ctype_space) != 0) return FALSE; break; case OP_WHITESPACE: if ((md->ctypes[c] & ctype_space) == 0) return FALSE; break; case OP_NOT_WORDCHAR: if ((md->ctypes[c] & ctype_word) != 0) return FALSE; break; case OP_WORDCHAR: if ((md->ctypes[c] & ctype_word) == 0) return FALSE; break; } } /* Control never gets here */ } /* If maximizing it is worth using inline code for speed, doing the type test once at the start (i.e. keep it out of the loop). */ else { const uschar *pp = eptr; switch(ctype) { case OP_ANY: /* Special code is required for UTF8, but when the maximum is unlimited we don't need it. */ #ifdef SUPPORT_UTF8 if (md->utf8 && max < INT_MAX) { if ((ims & PCRE_DOTALL) == 0) { for (i = min; i < max; i++) { if (eptr >= md->end_subject || *eptr++ == NEWLINE) break; while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; } } else { for (i = min; i < max; i++) { eptr++; while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; } } break; } #endif /* Non-UTF8 can be faster */ if ((ims & PCRE_DOTALL) == 0) { for (i = min; i < max; i++) { if (eptr >= md->end_subject || *eptr == NEWLINE) break; eptr++; } } else { c = max - min; if (c > md->end_subject - eptr) c = md->end_subject - eptr; eptr += c; } break; case OP_NOT_DIGIT: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) break; eptr++; } break; case OP_DIGIT: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) break; eptr++; } break; case OP_NOT_WHITESPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) break; eptr++; } break; case OP_WHITESPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) break; eptr++; } break; case OP_NOT_WORDCHAR: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) break; eptr++; } break; case OP_WORDCHAR: for (i = min; i < max; i++) { if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) break; eptr++; } break; } while (eptr >= pp) { if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) return TRUE; #ifdef SUPPORT_UTF8 if (md->utf8) while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--; #endif } return FALSE; } /* Control never gets here */ /* There's been some horrible disaster. */ default: DPRINTF(("Unknown opcode %d\n", *ecode)); md->errorcode = PCRE_ERROR_UNKNOWN_NODE; return FALSE; } /* Do not stick any code in here without much thought; it is assumed that "continue" in the code above comes out to here to repeat the main loop. */ } /* End of main loop */ /* Control never reaches here */ } /************************************************* * Execute a Regular Expression * *************************************************/ /* This function applies a compiled re to a subject string and picks out portions of the string if it matches. Two elements in the vector are set for each substring: the offsets to the start and end of the substring. Arguments: external_re points to the compiled expression external_extra points to "hints" from pcre_study() or is NULL subject points to the subject string length length of subject string (may contain binary zeros) start_offset where to start in the subject string options option bits offsets points to a vector of ints to be filled in with offsets offsetcount the number of elements in the vector Returns: > 0 => success; value is the number of elements filled in = 0 => success, but offsets is not big enough -1 => failed to match < -1 => some kind of unexpected problem */ int pcre_exec(const pcre *external_re, const pcre_extra *external_extra, const char *subject, int length, int start_offset, int options, int *offsets, int offsetcount) { int resetcount, ocount; int first_char = -1; int req_char = -1; int req_char2 = -1; unsigned long int ims = 0; match_data match_block; const uschar *start_bits = NULL; const uschar *start_match = (const uschar *)subject + start_offset; const uschar *end_subject; const uschar *req_char_ptr = start_match - 1; const real_pcre *re = (const real_pcre *)external_re; const real_pcre_extra *extra = (const real_pcre_extra *)external_extra; BOOL using_temporary_offsets = FALSE; BOOL anchored; BOOL startline; if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; anchored = ((re->options | options) & PCRE_ANCHORED) != 0; startline = (re->options & PCRE_STARTLINE) != 0; match_block.start_pattern = re->code; match_block.start_subject = (const uschar *)subject; match_block.end_subject = match_block.start_subject + length; end_subject = match_block.end_subject; match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; match_block.utf8 = (re->options & PCRE_UTF8) != 0; match_block.notbol = (options & PCRE_NOTBOL) != 0; match_block.noteol = (options & PCRE_NOTEOL) != 0; match_block.notempty = (options & PCRE_NOTEMPTY) != 0; match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */ match_block.lcc = re->tables + lcc_offset; match_block.ctypes = re->tables + ctypes_offset; /* The ims options can vary during the matching as a result of the presence of (?ims) items in the pattern. They are kept in a local variable so that restoring at the exit of a group is easy. */ ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); /* If the expression has got more back references than the offsets supplied can hold, we get a temporary bit of working store to use during the matching. Otherwise, we can use the vector supplied, rounding down its size to a multiple of 3. */ ocount = offsetcount - (offsetcount % 3); if (re->top_backref > 0 && re->top_backref >= ocount/3) { ocount = re->top_backref * 3 + 3; match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int)); if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; using_temporary_offsets = TRUE; DPRINTF(("Got memory to hold back references\n")); } else match_block.offset_vector = offsets; match_block.offset_end = ocount; match_block.offset_max = (2*ocount)/3; match_block.offset_overflow = FALSE; /* Compute the minimum number of offsets that we need to reset each time. Doing this makes a huge difference to execution time when there aren't many brackets in the pattern. */ resetcount = 2 + re->top_bracket * 2; if (resetcount > offsetcount) resetcount = ocount; /* Reset the working variable associated with each extraction. These should never be used unless previously set, but they get saved and restored, and so we initialize them to avoid reading uninitialized locations. */ if (match_block.offset_vector != NULL) { register int *iptr = match_block.offset_vector + ocount; register int *iend = iptr - resetcount/2 + 1; while (--iptr >= iend) *iptr = -1; } /* Set up the first character to match, if available. The first_char value is never set for an anchored regular expression, but the anchoring may be forced at run time, so we have to test for anchoring. The first char may be unset for an unanchored pattern, of course. If there's no first char and the pattern was studied, there may be a bitmap of possible first characters. */ if (!anchored) { if ((re->options & PCRE_FIRSTSET) != 0) { first_char = re->first_char; if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char]; } else if (!startline && extra != NULL && (extra->options & PCRE_STUDY_MAPPED) != 0) start_bits = extra->start_bits; } /* For anchored or unanchored matches, there may be a "last known required character" set. If the PCRE_CASELESS is set, implying that the match starts caselessly, or if there are any changes of this flag within the regex, set up both cases of the character. Otherwise set the two values the same, which will avoid duplicate testing (which takes significant time). This covers the vast majority of cases. It will be suboptimal when the case flag changes in a regex and the required character in fact is caseful. */ if ((re->options & PCRE_REQCHSET) != 0) { req_char = re->req_char; req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)? (re->tables + fcc_offset)[req_char] : req_char; } /* Loop for handling unanchored repeated matching attempts; for anchored regexs the loop runs just once. */ do { int rc; register int *iptr = match_block.offset_vector; register int *iend = iptr + resetcount; /* Reset the maximum number of extractions we might see. */ while (iptr < iend) *iptr++ = -1; /* Advance to a unique first char if possible */ if (first_char >= 0) { if ((ims & PCRE_CASELESS) != 0) while (start_match < end_subject && match_block.lcc[*start_match] != first_char) start_match++; else while (start_match < end_subject && *start_match != first_char) start_match++; } /* Or to just after \n for a multiline match if possible */ else if (startline) { if (start_match > match_block.start_subject + start_offset) { while (start_match < end_subject && start_match[-1] != NEWLINE) start_match++; } } /* Or to a non-unique first char after study */ else if (start_bits != NULL) { while (start_match < end_subject) { register int c = *start_match; if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break; } } #ifdef DEBUG /* Sigh. Some compilers never learn. */ printf(">>>> Match against: "); pchars(start_match, end_subject - start_match, TRUE, &match_block); printf("\n"); #endif /* If req_char is set, we know that that character must appear in the subject for the match to succeed. If the first character is set, req_char must be later in the subject; otherwise the test starts at the match point. This optimization can save a huge amount of backtracking in patterns with nested unlimited repeats that aren't going to match. We don't know what the state of case matching may be when this character is hit, so test for it in both its cases if necessary. However, the different cased versions will not be set up unless PCRE_CASELESS was given or the casing state changes within the regex. Writing separate code makes it go faster, as does using an autoincrement and backing off on a match. */ if (req_char >= 0) { register const uschar *p = start_match + ((first_char >= 0)? 1 : 0); /* We don't need to repeat the search if we haven't yet reached the place we found it at last time. */ if (p > req_char_ptr) { /* Do a single test if no case difference is set up */ if (req_char == req_char2) { while (p < end_subject) { if (*p++ == req_char) { p--; break; } } } /* Otherwise test for either case */ else { while (p < end_subject) { register int pp = *p++; if (pp == req_char || pp == req_char2) { p--; break; } } } /* If we can't find the required character, break the matching loop */ if (p >= end_subject) break; /* If we have found the required character, save the point where we found it, so that we don't search again next time round the loop if the start hasn't passed this character yet. */ req_char_ptr = p; } } /* When a match occurs, substrings will be set for all internal extractions; we just need to set up the whole thing as substring 0 before returning. If there were too many extractions, set the return code to zero. In the case where we had to get some local store to hold offsets for backreferences, copy those back references that we can. In this case there need not be overflow if certain parts of the pattern were not used. */ match_block.start_match = start_match; if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup)) continue; /* Copy the offset information from temporary store if necessary */ if (using_temporary_offsets) { if (offsetcount >= 4) { memcpy(offsets + 2, match_block.offset_vector + 2, (offsetcount - 2) * sizeof(int)); DPRINTF(("Copied offsets from temporary memory\n")); } if (match_block.end_offset_top > offsetcount) match_block.offset_overflow = TRUE; DPRINTF(("Freeing temporary memory\n")); (pcre_free)(match_block.offset_vector); } rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2; if (offsetcount < 2) rc = 0; else { offsets[0] = start_match - match_block.start_subject; offsets[1] = match_block.end_match_ptr - match_block.start_subject; } DPRINTF((">>>> returning %d\n", rc)); return rc; } /* This "while" is the end of the "do" above */ while (!anchored && match_block.errorcode == PCRE_ERROR_NOMATCH && start_match++ < end_subject); if (using_temporary_offsets) { DPRINTF(("Freeing temporary memory\n")); (pcre_free)(match_block.offset_vector); } DPRINTF((">>>> returning %d\n", match_block.errorcode)); return match_block.errorcode; } /* End of pcre.c */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/pcre.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* Copyright (c) 1997-2001 University of Cambridge */ #ifndef _PCRE_H #define _PCRE_H /* The file pcre.h is build by "configure". Do not edit it; instead make changes to pcre.in. */ #define PCRE_MAJOR 3 #define PCRE_MINOR 9 #define PCRE_DATE 02-Jan-2002 /* Win32 uses DLL by default */ #ifdef _WIN32 #define STATIC # ifdef STATIC # define PCRE_DL_IMPORT # else # define PCRE_DL_IMPORT __declspec(dllimport) # endif #else # define PCRE_DL_IMPORT #endif /* Have to include stdlib.h in order to ensure that size_t is defined; it is needed here for malloc. */ #include /* Allow for C++ users */ #ifdef __cplusplus extern "C" { #endif /* Options */ #define PCRE_CASELESS 0x0001 #define PCRE_MULTILINE 0x0002 #define PCRE_DOTALL 0x0004 #define PCRE_EXTENDED 0x0008 #define PCRE_ANCHORED 0x0010 #define PCRE_DOLLAR_ENDONLY 0x0020 #define PCRE_EXTRA 0x0040 #define PCRE_NOTBOL 0x0080 #define PCRE_NOTEOL 0x0100 #define PCRE_UNGREEDY 0x0200 #define PCRE_NOTEMPTY 0x0400 #define PCRE_UTF8 0x0800 /* Exec-time and get-time error codes */ #define PCRE_ERROR_NOMATCH (-1) #define PCRE_ERROR_NULL (-2) #define PCRE_ERROR_BADOPTION (-3) #define PCRE_ERROR_BADMAGIC (-4) #define PCRE_ERROR_UNKNOWN_NODE (-5) #define PCRE_ERROR_NOMEMORY (-6) #define PCRE_ERROR_NOSUBSTRING (-7) /* Request types for pcre_fullinfo() */ #define PCRE_INFO_OPTIONS 0 #define PCRE_INFO_SIZE 1 #define PCRE_INFO_CAPTURECOUNT 2 #define PCRE_INFO_BACKREFMAX 3 #define PCRE_INFO_FIRSTCHAR 4 #define PCRE_INFO_FIRSTTABLE 5 #define PCRE_INFO_LASTLITERAL 6 /* Types */ struct real_pcre; /* declaration; the definition is private */ struct real_pcre_extra; /* declaration; the definition is private */ typedef struct real_pcre pcre; typedef struct real_pcre_extra pcre_extra; /* Store get and free functions. These can be set to alternative malloc/free functions if required. Some magic is required for Win32 DLL; it is null on other OS. */ PCRE_DL_IMPORT extern void *(*pcre_malloc)(size_t); PCRE_DL_IMPORT extern void (*pcre_free)(void *); #undef PCRE_DL_IMPORT /* Functions */ extern pcre *pcre_compile(const char *, int, const char **, int *, const unsigned char *); extern int pcre_copy_substring(const char *, int *, int, int, char *, int); extern int pcre_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int); extern void pcre_free_substring(const char *); extern void pcre_free_substring_list(const char **); extern int pcre_get_substring(const char *, int *, int, int, const char **); extern int pcre_get_substring_list(const char *, int *, int, const char ***); extern int pcre_info(const pcre *, int *, int *); extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *); extern const unsigned char *pcre_maketables(void); extern pcre_extra *pcre_study(const pcre *, int, const char **); extern const char *pcre_version(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* End of pcre.h */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/rePlugin.h ================================================ /* Regular Expression Plugin (This class comment becomes part of rePlugin.c) RePlugin translate: 'RePlugin.c' doInlining: true. See documentation and source code for the PCRE C Library Code. This plugin is designed to serve an object such as RePattern: patternStr A 0-terminated string comprising the pattern to be compiled. compileFlags An Integer representing re compiler options PCREBuffer A ByteArray of regular expression bytecodes extraPtr A ByteArray of match optimization data (or nil) errorString A String Object For Holding an Error Message (when compile failed) errorOffset The index in patternStr (0-based) where the error ocurred (when compile failed) matchFlags An Integer representing re matcher options matchSpaceObj An Integer array for match results and workspace during matching. The instance variables must appear in the preceding order. MatchSpaceObj must be allocated by the calling routine and contain at least 6*(numGroups+1) bytes. */ #include "pcre.h" #include "internal.h" /* Adjust malloc and free routines as used by PCRE */ static void rePluginFree(void * aPointer); static void * rePluginMalloc(size_t anInteger); void *(*pcre_malloc)(size_t) = rePluginMalloc; void (*pcre_free)(void *) = rePluginFree; ================================================ FILE: vm/src/from_squeak/Cross/plugins/RePlugin/study.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See the file Tech.Notes for some information on the internals. Written by: Philip Hazel Copyright (c) 1997-2001 University of Cambridge ----------------------------------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. If PCRE is embedded in any software that is released under the GNU General Purpose Licence (GPL), then the terms of that licence shall supersede any condition above with which it is incompatible. ----------------------------------------------------------------------------- */ /* Include the internals header, which itself includes Standard C headers plus the external pcre header. */ #include "internal.h" /************************************************* * Set a bit and maybe its alternate case * *************************************************/ /* Given a character, set its bit in the table, and also the bit for the other version of a letter if we are caseless. Arguments: start_bits points to the bit map c is the character caseless the caseless flag cd the block with char table pointers Returns: nothing */ static void set_bit(uschar *start_bits, int c, BOOL caseless, compile_data *cd) { start_bits[c/8] |= (1 << (c&7)); if (caseless && (cd->ctypes[c] & ctype_letter) != 0) start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7)); } /************************************************* * Create bitmap of starting chars * *************************************************/ /* This function scans a compiled unanchored expression and attempts to build a bitmap of the set of initial characters. If it can't, it returns FALSE. As time goes by, we may be able to get more clever at doing this. Arguments: code points to an expression start_bits points to a 32-byte table, initialized to 0 caseless the current state of the caseless flag cd the block with char table pointers Returns: TRUE if table built, FALSE otherwise */ static BOOL set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless, compile_data *cd) { register int c; /* This next statement and the later reference to dummy are here in order to trick the optimizer of the IBM C compiler for OS/2 into generating correct code. Apparently IBM isn't going to fix the problem, and we would rather not disable optimization (in this module it actually makes a big difference, and the pcre module can use all the optimization it can get). */ volatile int dummy; do { const uschar *tcode = code + 3; BOOL try_next = TRUE; while (try_next) { /* If a branch starts with a bracket or a positive lookahead assertion, recurse to set bits from within them. That's all for this branch. */ if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT) { if (!set_start_bits(tcode, start_bits, caseless, cd)) return FALSE; try_next = FALSE; } else switch(*tcode) { default: return FALSE; /* Skip over extended extraction bracket number */ case OP_BRANUMBER: tcode += 3; break; /* Skip over lookbehind and negative lookahead assertions */ case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT); tcode += 3; break; /* Skip over an option setting, changing the caseless flag */ case OP_OPT: caseless = (tcode[1] & PCRE_CASELESS) != 0; tcode += 2; break; /* BRAZERO does the bracket, but carries on. */ case OP_BRAZERO: case OP_BRAMINZERO: if (!set_start_bits(++tcode, start_bits, caseless, cd)) return FALSE; dummy = 1; do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT); tcode += 3; break; /* Single-char * or ? sets the bit and tries the next item */ case OP_STAR: case OP_MINSTAR: case OP_QUERY: case OP_MINQUERY: set_bit(start_bits, tcode[1], caseless, cd); tcode += 2; break; /* Single-char upto sets the bit and tries the next */ case OP_UPTO: case OP_MINUPTO: set_bit(start_bits, tcode[3], caseless, cd); tcode += 4; break; /* At least one single char sets the bit and stops */ case OP_EXACT: /* Fall through */ tcode++; case OP_CHARS: /* Fall through */ tcode++; case OP_PLUS: case OP_MINPLUS: set_bit(start_bits, tcode[1], caseless, cd); try_next = FALSE; break; /* Single character type sets the bits and stops */ case OP_NOT_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_digit]; try_next = FALSE; break; case OP_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_digit]; try_next = FALSE; break; case OP_NOT_WHITESPACE: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_space]; try_next = FALSE; break; case OP_WHITESPACE: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_space]; try_next = FALSE; break; case OP_NOT_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_word]; try_next = FALSE; break; case OP_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_word]; try_next = FALSE; break; /* One or more character type fudges the pointer and restarts, knowing it will hit a single character type and stop there. */ case OP_TYPEPLUS: case OP_TYPEMINPLUS: tcode++; break; case OP_TYPEEXACT: tcode += 3; break; /* Zero or more repeats of character types set the bits and then try again. */ case OP_TYPEUPTO: case OP_TYPEMINUPTO: tcode += 2; /* Fall through */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEQUERY: case OP_TYPEMINQUERY: switch(tcode[1]) { case OP_NOT_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_digit]; break; case OP_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_digit]; break; case OP_NOT_WHITESPACE: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_space]; break; case OP_WHITESPACE: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_space]; break; case OP_NOT_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_word]; break; case OP_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_word]; break; } tcode += 2; break; /* Character class: set the bits and either carry on or not, according to the repeat count. */ case OP_CLASS: { tcode++; for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; tcode += 32; switch (*tcode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: tcode++; break; case OP_CRRANGE: case OP_CRMINRANGE: if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5; else try_next = FALSE; break; default: try_next = FALSE; break; } } break; /* End of class handling */ } /* End of switch */ } /* End of try_next loop */ code += (code[1] << 8) + code[2]; /* Advance to next branch */ } while (*code == OP_ALT); return TRUE; } /************************************************* * Study a compiled expression * *************************************************/ /* This function is handed a compiled expression that it must study to produce information that will speed up the matching. It returns a pcre_extra block which then gets handed back to pcre_exec(). Arguments: re points to the compiled expression options contains option bits errorptr points to where to place error messages; set NULL unless error Returns: pointer to a pcre_extra block, NULL on error or if no optimization possible */ pcre_extra * pcre_study(const pcre *external_re, int options, const char **errorptr) { uschar start_bits[32]; real_pcre_extra *extra; const real_pcre *re = (const real_pcre *)external_re; compile_data compile_block; *errorptr = NULL; if (re == NULL || re->magic_number != MAGIC_NUMBER) { *errorptr = "argument is not a compiled regular expression"; return NULL; } if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) { *errorptr = "unknown or incorrect option bit(s) set"; return NULL; } /* For an anchored pattern, or an unchored pattern that has a first char, or a multiline pattern that matches only at "line starts", no further processing at present. */ if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0) return NULL; /* Set the character tables in the block which is passed around */ compile_block.lcc = re->tables + lcc_offset; compile_block.fcc = re->tables + fcc_offset; compile_block.cbits = re->tables + cbits_offset; compile_block.ctypes = re->tables + ctypes_offset; /* See if we can find a fixed set of initial characters for the pattern. */ memset(start_bits, 0, 32 * sizeof(uschar)); if (!set_start_bits(re->code, start_bits, (re->options & PCRE_CASELESS) != 0, &compile_block)) return NULL; /* Get an "extra" block and put the information therein. */ extra = (real_pcre_extra *)(pcre_malloc)(sizeof(real_pcre_extra)); if (extra == NULL) { *errorptr = "failed to get memory"; return NULL; } extra->options = PCRE_STUDY_MAPPED; memcpy(extra->start_bits, start_bits, sizeof(start_bits)); return (pcre_extra *)extra; } /* End of study.c */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/SecurityPlugin/SecurityPlugin.h ================================================ /* security plugin header file */ /* image writing */ int ioDisableImageWrite(void); int ioCanWriteImage(void); /* untrusted and secure directory locations */ char *ioGetSecureUserDirectory(void); char *ioGetUntrustedUserDirectory(void); /* following must be called by the VM before interpret() */ int ioInitSecurity(void); int ioCanListenOnPort(int s, int port); int ioCanConnectToPort(int netAddr, int port); int ioCanCreateSocketOfType(int netType, int socketType); int ioCanCreateSocketOfType(int netType, int socketType); int ioCanConnectToPort(int netAddr, int port); int ioDisableSocketAccess(); int ioHasSocketAccess(); int ioCanCreatePathOfSize(char* pathString, int pathStringLength); int ioCanDeleteFileOfSize(char* pathString, int pathStringLength); int ioCanDeletePathOfSize(char* pathString, int pathStringLength); int ioCanGetFileTypeOfSize(char* pathString, int pathStringLength); int ioCanListPathOfSize(char* pathString, int pathStringLength); int ioCanOpenAsyncFileOfSizeWritable(char* pathString, int pathStringLength, int writeFlag); int ioCanOpenFileOfSizeWritable(char* pathString, int pathStringLength, int writeFlag); int ioCanRenameFileOfSize(char* pathString, int pathStringLength); int ioCanRenameImage(void); int ioCanSetFileTypeOfSize(char* pathString, int pathStringLength); int ioDisableFileAccess(void); int ioHasFileAccess(void); ================================================ FILE: vm/src/from_squeak/Cross/plugins/SerialPlugin/SerialPlugin.h ================================================ /* serial port primitives */ /* module initialization/shutdown */ int serialPortInit(void); int serialPortShutdown(void); #pragma export on int serialPortClose(int portNum); int serialPortCount(void); int serialPortOpen( int portNum, int baudRate, int stopBitsType, int parityType, int dataBits, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); int serialPortReadInto(int portNum, int count, int bufferPtr); int serialPortWriteFrom(int portNum, int count, int bufferPtr); #pragma export off ================================================ FILE: vm/src/from_squeak/Cross/plugins/SocketPlugin/SocketPlugin.h ================================================ /* squeak socket support header file */ /* module initialization/shutdown */ sqInt socketInit(void); sqInt socketShutdown(void); typedef struct { int sessionID; int socketType; /* 0 = TCP, 1 = UDP */ void *privateSocketPtr; } SQSocket, *SocketPtr; /* networking primitives */ sqInt sqNetworkInit(sqInt resolverSemaIndex); void sqNetworkShutdown(void); void sqResolverAbort(void); void sqResolverAddrLookupResult(char *nameForAddress, sqInt nameSize); sqInt sqResolverAddrLookupResultSize(void); sqInt sqResolverError(void); sqInt sqResolverLocalAddress(void); sqInt sqResolverNameLookupResult(void); void sqResolverStartAddrLookup(sqInt address); void sqResolverStartNameLookup(char *hostName, sqInt nameSize); sqInt sqResolverStatus(void); void sqSocketAbortConnection(SocketPtr s); void sqSocketCloseConnection(SocketPtr s); sqInt sqSocketConnectionStatus(SocketPtr s); void sqSocketConnectToPort(SocketPtr s, sqInt addr, sqInt port); void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID(SocketPtr s, sqInt netType, sqInt socketType, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex); void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, sqInt netType, sqInt socketType, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex, sqInt readSemaIndex, sqInt writeSemaIndex); void sqSocketDestroy(SocketPtr s); sqInt sqSocketError(SocketPtr s); void sqSocketListenOnPort(SocketPtr s, sqInt port); sqInt sqSocketLocalAddress(SocketPtr s); sqInt sqSocketLocalPort(SocketPtr s); sqInt sqSocketReceiveDataAvailable(SocketPtr s); sqInt sqSocketReceiveDataBufCount(SocketPtr s, char *buf, sqInt bufSize); sqInt sqSocketRemoteAddress(SocketPtr s); sqInt sqSocketRemotePort(SocketPtr s); sqInt sqSocketSendDataBufCount(SocketPtr s, char *buf, sqInt bufSize); sqInt sqSocketSendDone(SocketPtr s); /* ar 7/16/1999: New primitives for accept(). Note: If accept() calls are not supported simply make the calls fail and the old connection style will be used. */ void sqSocketListenOnPortBacklogSize(SocketPtr s, sqInt port, sqInt backlogSize); void sqSocketListenOnPortBacklogSizeInterface(SocketPtr s, sqInt port, sqInt backlogSize, sqInt addr); void sqSocketAcceptFromRecvBytesSendBytesSemaID(SocketPtr s, SocketPtr serverSocket, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex); void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, SocketPtr serverSocket, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex, sqInt readSemaIndex, sqInt writeSemaIndex); sqInt sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, char *buf, sqInt bufSize, sqInt *address, sqInt *port, sqInt *moreFlag); sqInt sqSockettoHostportSendDataBufCount(SocketPtr s, sqInt address, sqInt port, char *buf, sqInt bufSize); sqInt sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(SocketPtr s, char *optionName, sqInt optionNameSize, char *optionValue, sqInt optionValueSize, sqInt *result); sqInt sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(SocketPtr s, char *optionName, sqInt optionNameSize, sqInt *result); /* tpr 4/12/06 add declarations for two new socket routines */ void sqSocketBindToPort(SocketPtr s, int addr, int port); void sqSocketSetReusable(SocketPtr s); ================================================ FILE: vm/src/from_squeak/Cross/plugins/SoundCodecPrims/SoundCodecPrims.h ================================================ /* SoundCodec Plugin */ /* prototypes */ void gsmEncode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta); void gsmDecode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta); void gsmInitState(int state); int gsmStateBytes(void); ================================================ FILE: vm/src/from_squeak/Cross/plugins/SoundCodecPrims/sqSoundCodecPluginBasicPrims.c ================================================ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* This file was created by concatenating a number of separate header and source files from Jutta Degener and Carsten Bormann implementation, patch level 10. This was done to simplify Squeak source code maintenance. */ #include #include #include /****** begin "gsm.h" *****/ #ifdef __cplusplus # define NeedFunctionPrototypes 1 #endif #if __STDC__ # define NeedFunctionPrototypes 1 #endif #ifdef _NO_PROTO # undef NeedFunctionPrototypes #endif #ifdef NeedFunctionPrototypes # include /* for FILE * */ #endif #undef GSM_P #if NeedFunctionPrototypes # define GSM_P( protos ) protos #else # define GSM_P( protos ) ( /* protos */ ) #endif /* * Interface */ typedef struct gsm_state * gsm; typedef short gsm_signal; /* signed 16 bit */ typedef unsigned char gsm_byte; typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ #define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ #define GSM_PATCHLEVEL 10 #define GSM_MINOR 0 #define GSM_MAJOR 1 #define GSM_OPT_VERBOSE 1 #define GSM_OPT_FAST 2 #define GSM_OPT_LTP_CUT 3 #define GSM_OPT_WAV49 4 #define GSM_OPT_FRAME_INDEX 5 #define GSM_OPT_FRAME_CHAIN 6 extern gsm gsm_create GSM_P((void)); extern void gsm_destroy GSM_P((gsm)); extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *)); extern int gsm_option GSM_P((gsm, int, int *)); extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *)); extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *)); extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *)); extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *)); /****** begin "proto.h" *****/ #if __cplusplus # define NeedFunctionPrototypes 1 #endif #if __STDC__ # define NeedFunctionPrototypes 1 #endif #ifdef _NO_PROTO # undef NeedFunctionPrototypes #endif #undef P /* gnu stdio.h actually defines this... */ #undef P0 #undef P1 #undef P2 #undef P3 #undef P4 #undef P5 #undef P6 #undef P7 #undef P8 #if NeedFunctionPrototypes # define P( protos ) protos # define P0() (void) # define P1(x, a) (a) # define P2(x, a, b) (a, b) # define P3(x, a, b, c) (a, b, c) # define P4(x, a, b, c, d) (a, b, c, d) # define P5(x, a, b, c, d, e) (a, b, c, d, e) # define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f) # define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g) # define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h) #else /* !NeedFunctionPrototypes */ # define P( protos ) ( /* protos */ ) # define P0() () # define P1(x, a) x a; # define P2(x, a, b) x a; b; # define P3(x, a, b, c) x a; b; c; # define P4(x, a, b, c, d) x a; b; c; d; # define P5(x, a, b, c, d, e) x a; b; c; d; e; # define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f; # define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g; # define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h; #endif /* !NeedFunctionPrototypes */ /****** begin "private.h" *****/ typedef short word; /* 16 bit signed int */ typedef long longword; /* 32 bit signed int */ typedef unsigned short uword; /* unsigned word */ typedef unsigned long ulongword; /* unsigned longword */ struct gsm_state { word dp0[ 280 ]; word z1; /* preprocessing.c, Offset_com. */ longword L_z2; /* Offset_com. */ int mp; /* Preemphasis */ word u[8]; /* short_term_aly_filter.c */ word LARpp[2][8]; /* */ word j; /* */ word ltp_cut; /* long_term.c, LTP crosscorr. */ word nrp; /* 40 */ /* long_term.c, synthesis */ word v[9]; /* short_term.c, synthesis */ word msr; /* decoder.c, Postprocessing */ char verbose; /* only used if !NDEBUG */ char fast; /* only used if FAST */ char wav_fmt; /* only used if WAV49 defined */ unsigned char frame_index; /* odd/even chaining */ unsigned char frame_chain; /* half-byte to carry forward */ }; #define MIN_WORD (-32767 - 1) #define MAX_WORD 32767 #define MIN_LONGWORD (-2147483647 - 1) #define MAX_LONGWORD 2147483647 #ifdef SASR /* flag: >> is a signed arithmetic shift right */ #undef SASR #define SASR(x, by) ((x) >> (by)) #else #define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by)))) #endif /* SASR */ //#include "proto.h" /* * Prototypes from add.c */ extern word gsm_mult P((word a, word b)); extern longword gsm_L_mult P((word a, word b)); extern word gsm_mult_r P((word a, word b)); extern word gsm_div P((word num, word denum)); extern word gsm_add P(( word a, word b )); extern longword gsm_L_add P(( longword a, longword b )); extern word gsm_sub P((word a, word b)); extern longword gsm_L_sub P((longword a, longword b)); extern word gsm_abs P((word a)); extern word gsm_norm P(( longword a )); extern longword gsm_L_asl P((longword a, int n)); extern word gsm_asl P((word a, int n)); extern longword gsm_L_asr P((longword a, int n)); extern word gsm_asr P((word a, int n)); /* * Inlined functions from add.h */ /* * #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \ * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) */ #define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \ (SASR( ((longword)(a) * (longword)(b) + 16384), 15 )) # define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \ (SASR( ((longword)(a) * (longword)(b)), 15 )) # define GSM_L_MULT(a, b) /* word a, word b */ \ (((longword)(a) * (longword)(b)) << 1) # define GSM_L_ADD(a, b) \ ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ : ((b) <= 0 ? (a) + (b) \ : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ ? MAX_LONGWORD : utmp)) /* * # define GSM_ADD(a, b) \ * ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \ * ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) */ /* Nonportable, but faster: */ #define GSM_ADD(a, b) \ ((ulongword)((ltmp = (longword)(a) + (longword)(b)) - MIN_WORD) > \ MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp) # define GSM_SUB(a, b) \ ((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \ ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) # define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) /* Use these if necessary: # define GSM_MULT_R(a, b) gsm_mult_r(a, b) # define GSM_MULT(a, b) gsm_mult(a, b) # define GSM_L_MULT(a, b) gsm_L_mult(a, b) # define GSM_L_ADD(a, b) gsm_L_add(a, b) # define GSM_ADD(a, b) gsm_add(a, b) # define GSM_SUB(a, b) gsm_sub(a, b) # define GSM_ABS(a) gsm_abs(a) */ /* * More prototypes from implementations.. */ extern void Gsm_Coder P(( struct gsm_state * S, word * s, /* [0..159] samples IN */ word * LARc, /* [0..7] LAR coefficients OUT */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc /* [13*4] normalized RPE samples OUT */)); extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d' IN */ word * e, /* [0..40] OUT */ word * dpp, /* [0..40] OUT */ word * Nc, /* correlation lag OUT */ word * bc /* gain factor OUT */)); extern void Gsm_LPC_Analysis P(( struct gsm_state * S, word * s, /* 0..159 signals IN/OUT */ word * LARc)); /* 0..7 LARc's OUT */ extern void Gsm_Preprocess P(( struct gsm_state * S, word * s, word * so)); extern void Gsm_Encoding P(( struct gsm_state * S, word * e, word * ep, word * xmaxc, word * Mc, word * xMc)); extern void Gsm_Short_Term_Analysis_Filter P(( struct gsm_state * S, word * LARc, /* coded log area ratio [0..7] IN */ word * d /* st res. signal [0..159] IN/OUT */)); extern void Gsm_Decoder P(( struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s)); /* [0..159] OUT */ extern void Gsm_Decoding P(( struct gsm_state * S, word xmaxcr, word Mcr, word * xMcr, /* [0..12] IN */ word * erp)); /* [0..39] OUT */ extern void Gsm_Long_Term_Synthesis_Filtering P(( struct gsm_state* S, word Ncr, word bcr, word * erp, /* [0..39] IN */ word * drp)); /* [-120..-1] IN, [0..40] OUT */ void Gsm_RPE_Decoding P(( struct gsm_state *S, word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */ word * erp)); /* [0..39] OUT */ void Gsm_RPE_Encoding P(( struct gsm_state * S, word * e, /* -5..-1][0..39][40..44 IN/OUT */ word * xmaxc, /* OUT */ word * Mc, /* OUT */ word * xMc)); /* [0..12] OUT */ extern void Gsm_Short_Term_Synthesis_Filter P(( struct gsm_state * S, word * LARcr, /* log area ratios [0..7] IN */ word * drp, /* received d [0...39] IN */ word * s)); /* signal s [0..159] OUT */ extern void Gsm_Update_of_reconstructed_short_time_residual_signal P(( word * dpp, /* [0...39] IN */ word * ep, /* [0...39] IN */ word * dp)); /* [-120...-1] IN/OUT */ /* * Tables from table.c */ #ifndef GSM_TABLE_C extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; extern word gsm_INVA[8]; extern word gsm_DLB[4], gsm_QLB[4]; extern word gsm_H[11]; extern word gsm_NRFAC[8]; extern word gsm_FAC[8]; #endif /* GSM_TABLE_C */ /* * Debugging */ #ifdef NDEBUG # define gsm_debug_words(a, b, c, d) /* nil */ # define gsm_debug_longwords(a, b, c, d) /* nil */ # define gsm_debug_word(a, b) /* nil */ # define gsm_debug_longword(a, b) /* nil */ #else /* !NDEBUG => DEBUG */ extern void gsm_debug_words P((char * name, int, int, word *)); extern void gsm_debug_longwords P((char * name, int, int, longword *)); extern void gsm_debug_longword P((char * name, longword)); extern void gsm_debug_word P((char * name, word)); #endif /* !NDEBUG */ /****** begin "add.c" *****/ #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) word gsm_add P2((a,b), word a, word b) { longword sum = (longword)a + (longword)b; return saturate(sum); } word gsm_sub P2((a,b), word a, word b) { longword diff = (longword)a - (longword)b; return saturate(diff); } word gsm_mult P2((a,b), word a, word b) { if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; else return SASR( (longword)a * (longword)b, 15 ); } word gsm_mult_r P2((a,b), word a, word b) { if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; else { longword prod = (longword)a * (longword)b + 16384; prod >>= 15; return prod & 0xFFFF; } } word gsm_abs P1((a), word a) { return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; } longword gsm_L_mult P2((a,b),word a, word b) { assert( a != MIN_WORD || b != MIN_WORD ); return ((longword)a * (longword)b) << 1; } longword gsm_L_add P2((a,b), longword a, longword b) { if (a < 0) { if (b >= 0) return a + b; else { ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; } } else if (b <= 0) return a + b; else { ulongword A = (ulongword)a + (ulongword)b; return A > MAX_LONGWORD ? MAX_LONGWORD : A; } } longword gsm_L_sub P2((a,b), longword a, longword b) { if (a >= 0) { if (b >= 0) return a - b; else { /* a>=0, b<0 */ ulongword A = (ulongword)a + -(b + 1); return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); } } else if (b <= 0) return a - b; else { /* a<0, b>0 */ ulongword A = (ulongword)-(a + 1) + b; return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; } } static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; word gsm_norm P1((a), longword a ) /* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 ( -1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); * * (That's 'ffs', only from the left, not the right..) */ { assert(a != 0); if (a < 0) { if (a <= -1073741824) return 0; a = ~a; } return a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] ); } longword gsm_L_asl P2((a,n), longword a, int n) { if (n >= 32) return 0; if (n <= -32) return -(a < 0); if (n < 0) return gsm_L_asr(a, -n); return a << n; } word gsm_asl P2((a,n), word a, int n) { if (n >= 16) return 0; if (n <= -16) return -(a < 0); if (n < 0) return gsm_asr(a, -n); return a << n; } longword gsm_L_asr P2((a,n), longword a, int n) { if (n >= 32) return -(a < 0); if (n <= -32) return 0; if (n < 0) return a << -n; # ifdef SASR return a >> n; # else if (a >= 0) return a >> n; else return -(longword)( -(ulongword)a >> n ); # endif } word gsm_asr P2((a,n), word a, int n) { if (n >= 16) return -(a < 0); if (n <= -16) return 0; if (n < 0) return a << -n; # ifdef SASR return a >> n; # else if (a >= 0) return a >> n; else return -(word)( -(uword)a >> n ); # endif } /* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div(num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ word gsm_div P2((num,denum), word num, word denum) { longword L_num = num; longword L_denum = denum; word div = 0; volatile int k = 15; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert(num != 0); */ assert(num >= 0 && denum >= num); if (num == 0) return 0; while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_denum) { L_num -= L_denum; div++; } } return div; } /****** begin "code.c" *****/ /* * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER */ void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc), struct gsm_state * S, word * s, /* [0..159] samples IN */ /* * The RPE-LTD coder works on a frame by frame basis. The length of * the frame is equal to 160 samples. Some computations are done * once per frame to produce at the output of the coder the * LARc[1..8] parameters which are the coded LAR coefficients and * also to realize the inverse filtering operation for the entire * frame (160 samples of signal d[0..159]). These parts produce at * the output of the coder: */ word * LARc, /* [0..7] LAR coefficients OUT */ /* * Procedure 4.2.11 to 4.2.18 are to be executed four times per * frame. That means once for each sub-segment RPE-LTP analysis of * 40 samples. These parts produce at the output of the coder: */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc /* [13*4] normalized RPE samples OUT */ ) { int k; word * dp = S->dp0 + 120; /* [ -120...-1 ] */ word * dpp = dp; /* [ 0...39 ] */ static word e[50]; word so[160]; Gsm_Preprocess (S, s, so); Gsm_LPC_Analysis (S, so, LARc); Gsm_Short_Term_Analysis_Filter (S, LARc, so); for (k = 0; k <= 3; k++, xMc += 13) { Gsm_Long_Term_Predictor ( S, so+k*40, /* d [0..39] IN */ dp, /* dp [-120..-1] IN */ e + 5, /* e [0..39] OUT */ dpp, /* dpp [0..39] OUT */ Nc++, bc++); Gsm_RPE_Encoding ( S, e + 5, /* e ][0..39][ IN/OUT */ xmaxc++, Mc++, xMc ); /* * Gsm_Update_of_reconstructed_short_time_residual_signal * ( dpp, e + 5, dp ); */ { register int i; register longword ltmp; for (i = 0; i <= 39; i++) dp[ i ] = GSM_ADD( e[5 + i], dpp[i] ); } dp += 40; dpp += 40; } (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), 120 * sizeof(*S->dp0) ); } /****** begin "decode.c" *****/ /* * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER */ static void Postprocessing P2((S,s), struct gsm_state * S, register word * s) { register int k; register word msr = S->msr; register longword ltmp; /* for GSM_ADD */ register word tmp; for (k = 160; k--; s++) { tmp = GSM_MULT_R( msr, 28180 ); msr = GSM_ADD(*s, tmp); /* Deemphasis */ *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ } S->msr = msr; } void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s), struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s) /* [0..159] OUT */ { int j, k; word erp[40], wt[160]; word * drp = S->dp0 + 120; for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp ); Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; } Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); Postprocessing(S, s); } /****** begin "gsm_decode.c" *****/ int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; #ifdef WAV49 if (s->wav_fmt) { uword sr = 0; s->frame_index = !s->frame_index; if (s->frame_index) { sr = *c++; LARc[0] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 2; LARc[1] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 4; LARc[2] = sr & 0x1f; sr >>= 5; LARc[3] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 2; LARc[4] = sr & 0xf; sr >>= 4; LARc[5] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; /* 5 */ LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[0] = sr & 0x7f; sr >>= 7; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; sr = *c++; xmc[1] = sr & 0x7; sr >>= 3; xmc[2] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; xmc[5] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 10 */ xmc[6] = sr & 0x7; sr >>= 3; xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; sr = *c++; xmc[9] = sr & 0x7; sr >>= 3; xmc[10] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[1] = sr & 0x7f; sr >>= 7; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; sr = *c++; /* 15 */ xmc[14] = sr & 0x7; sr >>= 3; xmc[15] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; xmc[18] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[19] = sr & 0x7; sr >>= 3; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; sr = *c++; xmc[22] = sr & 0x7; sr >>= 3; xmc[23] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; /* 20 */ Nc[2] = sr & 0x7f; sr >>= 7; bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; sr = *c++; xmc[27] = sr & 0x7; sr >>= 3; xmc[28] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; xmc[31] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[32] = sr & 0x7; sr >>= 3; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; sr = *c++; /* 25 */ xmc[35] = sr & 0x7; sr >>= 3; xmc[36] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[3] = sr & 0x7f; sr >>= 7; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; sr = *c++; xmc[40] = sr & 0x7; sr >>= 3; xmc[41] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 30 */ xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; xmc[44] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[45] = sr & 0x7; sr >>= 3; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; sr = *c++; xmc[48] = sr & 0x7; sr >>= 3; xmc[49] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; s->frame_chain = sr & 0xf; } else { sr = s->frame_chain; sr |= (uword)*c++ << 4; /* 1 */ LARc[0] = sr & 0x3f; sr >>= 6; LARc[1] = sr & 0x3f; sr >>= 6; sr = *c++; LARc[2] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 3; LARc[3] = sr & 0x1f; sr >>= 5; LARc[4] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; LARc[5] = sr & 0xf; sr >>= 4; LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr = *c++; /* 5 */ Nc[0] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; xmc[1] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[2] = sr & 0x7; sr >>= 3; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; sr = *c++; xmc[5] = sr & 0x7; sr >>= 3; xmc[6] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 10 */ xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; xmc[9] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[10] = sr & 0x7; sr >>= 3; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr = *c++; Nc[1] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; xmc[14] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 15 */ xmc[15] = sr & 0x7; sr >>= 3; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; sr = *c++; xmc[18] = sr & 0x7; sr >>= 3; xmc[19] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; xmc[22] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[23] = sr & 0x7; sr >>= 3; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr = *c++; Nc[2] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; /* 20 */ bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; xmc[27] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[28] = sr & 0x7; sr >>= 3; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; sr = *c++; xmc[31] = sr & 0x7; sr >>= 3; xmc[32] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; xmc[35] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 25 */ xmc[36] = sr & 0x7; sr >>= 3; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr = *c++; Nc[3] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; xmc[40] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[41] = sr & 0x7; sr >>= 3; xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; sr = *c++; /* 30 */ xmc[44] = sr & 0x7; sr >>= 3; xmc[45] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; xmc[48] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[49] = sr & 0x7; sr >>= 3; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; } } else #endif { /* GSM_MAGIC = (*c >> 4) & 0xF; */ if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; LARc[0] = (*c++ & 0xF) << 2; /* 1 */ LARc[0] |= (*c >> 6) & 0x3; LARc[1] = *c++ & 0x3F; LARc[2] = (*c >> 3) & 0x1F; LARc[3] = (*c++ & 0x7) << 2; LARc[3] |= (*c >> 6) & 0x3; LARc[4] = (*c >> 2) & 0xF; LARc[5] = (*c++ & 0x3) << 2; LARc[5] |= (*c >> 6) & 0x3; LARc[6] = (*c >> 3) & 0x7; LARc[7] = *c++ & 0x7; Nc[0] = (*c >> 1) & 0x7F; bc[0] = (*c++ & 0x1) << 1; bc[0] |= (*c >> 7) & 0x1; Mc[0] = (*c >> 5) & 0x3; xmaxc[0] = (*c++ & 0x1F) << 1; xmaxc[0] |= (*c >> 7) & 0x1; xmc[0] = (*c >> 4) & 0x7; xmc[1] = (*c >> 1) & 0x7; xmc[2] = (*c++ & 0x1) << 2; xmc[2] |= (*c >> 6) & 0x3; xmc[3] = (*c >> 3) & 0x7; xmc[4] = *c++ & 0x7; xmc[5] = (*c >> 5) & 0x7; xmc[6] = (*c >> 2) & 0x7; xmc[7] = (*c++ & 0x3) << 1; /* 10 */ xmc[7] |= (*c >> 7) & 0x1; xmc[8] = (*c >> 4) & 0x7; xmc[9] = (*c >> 1) & 0x7; xmc[10] = (*c++ & 0x1) << 2; xmc[10] |= (*c >> 6) & 0x3; xmc[11] = (*c >> 3) & 0x7; xmc[12] = *c++ & 0x7; Nc[1] = (*c >> 1) & 0x7F; bc[1] = (*c++ & 0x1) << 1; bc[1] |= (*c >> 7) & 0x1; Mc[1] = (*c >> 5) & 0x3; xmaxc[1] = (*c++ & 0x1F) << 1; xmaxc[1] |= (*c >> 7) & 0x1; xmc[13] = (*c >> 4) & 0x7; xmc[14] = (*c >> 1) & 0x7; xmc[15] = (*c++ & 0x1) << 2; xmc[15] |= (*c >> 6) & 0x3; xmc[16] = (*c >> 3) & 0x7; xmc[17] = *c++ & 0x7; xmc[18] = (*c >> 5) & 0x7; xmc[19] = (*c >> 2) & 0x7; xmc[20] = (*c++ & 0x3) << 1; xmc[20] |= (*c >> 7) & 0x1; xmc[21] = (*c >> 4) & 0x7; xmc[22] = (*c >> 1) & 0x7; xmc[23] = (*c++ & 0x1) << 2; xmc[23] |= (*c >> 6) & 0x3; xmc[24] = (*c >> 3) & 0x7; xmc[25] = *c++ & 0x7; Nc[2] = (*c >> 1) & 0x7F; bc[2] = (*c++ & 0x1) << 1; /* 20 */ bc[2] |= (*c >> 7) & 0x1; Mc[2] = (*c >> 5) & 0x3; xmaxc[2] = (*c++ & 0x1F) << 1; xmaxc[2] |= (*c >> 7) & 0x1; xmc[26] = (*c >> 4) & 0x7; xmc[27] = (*c >> 1) & 0x7; xmc[28] = (*c++ & 0x1) << 2; xmc[28] |= (*c >> 6) & 0x3; xmc[29] = (*c >> 3) & 0x7; xmc[30] = *c++ & 0x7; xmc[31] = (*c >> 5) & 0x7; xmc[32] = (*c >> 2) & 0x7; xmc[33] = (*c++ & 0x3) << 1; xmc[33] |= (*c >> 7) & 0x1; xmc[34] = (*c >> 4) & 0x7; xmc[35] = (*c >> 1) & 0x7; xmc[36] = (*c++ & 0x1) << 2; xmc[36] |= (*c >> 6) & 0x3; xmc[37] = (*c >> 3) & 0x7; xmc[38] = *c++ & 0x7; Nc[3] = (*c >> 1) & 0x7F; bc[3] = (*c++ & 0x1) << 1; bc[3] |= (*c >> 7) & 0x1; Mc[3] = (*c >> 5) & 0x3; xmaxc[3] = (*c++ & 0x1F) << 1; xmaxc[3] |= (*c >> 7) & 0x1; xmc[39] = (*c >> 4) & 0x7; xmc[40] = (*c >> 1) & 0x7; xmc[41] = (*c++ & 0x1) << 2; xmc[41] |= (*c >> 6) & 0x3; xmc[42] = (*c >> 3) & 0x7; xmc[43] = *c++ & 0x7; /* 30 */ xmc[44] = (*c >> 5) & 0x7; xmc[45] = (*c >> 2) & 0x7; xmc[46] = (*c++ & 0x3) << 1; xmc[46] |= (*c >> 7) & 0x1; xmc[47] = (*c >> 4) & 0x7; xmc[48] = (*c >> 1) & 0x7; xmc[49] = (*c++ & 0x1) << 2; xmc[49] |= (*c >> 6) & 0x3; xmc[50] = (*c >> 3) & 0x7; xmc[51] = *c & 0x7; /* 33 */ } Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); return 0; } /****** begin "gsm_encode.c" *****/ void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); /* variable size GSM_MAGIC 4 LARc[0] 6 LARc[1] 6 LARc[2] 5 LARc[3] 5 LARc[4] 4 LARc[5] 4 LARc[6] 3 LARc[7] 3 Nc[0] 7 bc[0] 2 Mc[0] 2 xmaxc[0] 6 xmc[0] 3 xmc[1] 3 xmc[2] 3 xmc[3] 3 xmc[4] 3 xmc[5] 3 xmc[6] 3 xmc[7] 3 xmc[8] 3 xmc[9] 3 xmc[10] 3 xmc[11] 3 xmc[12] 3 Nc[1] 7 bc[1] 2 Mc[1] 2 xmaxc[1] 6 xmc[13] 3 xmc[14] 3 xmc[15] 3 xmc[16] 3 xmc[17] 3 xmc[18] 3 xmc[19] 3 xmc[20] 3 xmc[21] 3 xmc[22] 3 xmc[23] 3 xmc[24] 3 xmc[25] 3 Nc[2] 7 bc[2] 2 Mc[2] 2 xmaxc[2] 6 xmc[26] 3 xmc[27] 3 xmc[28] 3 xmc[29] 3 xmc[30] 3 xmc[31] 3 xmc[32] 3 xmc[33] 3 xmc[34] 3 xmc[35] 3 xmc[36] 3 xmc[37] 3 xmc[38] 3 Nc[3] 7 bc[3] 2 Mc[3] 2 xmaxc[3] 6 xmc[39] 3 xmc[40] 3 xmc[41] 3 xmc[42] 3 xmc[43] 3 xmc[44] 3 xmc[45] 3 xmc[46] 3 xmc[47] 3 xmc[48] 3 xmc[49] 3 xmc[50] 3 xmc[51] 3 */ #ifdef WAV49 if (s->wav_fmt) { s->frame_index = !s->frame_index; if (s->frame_index) { uword sr; sr = 0; sr = sr >> 6 | LARc[0] << 10; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 4; sr = sr >> 5 | LARc[2] << 11; *c++ = sr >> 7; sr = sr >> 5 | LARc[3] << 11; sr = sr >> 4 | LARc[4] << 12; *c++ = sr >> 6; sr = sr >> 4 | LARc[5] << 12; sr = sr >> 3 | LARc[6] << 13; *c++ = sr >> 7; sr = sr >> 3 | LARc[7] << 13; sr = sr >> 7 | Nc[0] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[0] << 14; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[0] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; sr = sr >> 3 | xmc[3] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[4] << 13; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[7] << 13; sr = sr >> 3 | xmc[8] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; sr = sr >> 3 | xmc[11] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[12] << 13; sr = sr >> 7 | Nc[1] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[1] << 14; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[13] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; sr = sr >> 3 | xmc[16] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[17] << 13; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[20] << 13; sr = sr >> 3 | xmc[21] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; sr = sr >> 3 | xmc[24] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[25] << 13; sr = sr >> 7 | Nc[2] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[2] << 14; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[26] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; sr = sr >> 3 | xmc[29] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[30] << 13; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[33] << 13; sr = sr >> 3 | xmc[34] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; sr = sr >> 3 | xmc[37] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[38] << 13; sr = sr >> 7 | Nc[3] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[3] << 14; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[39] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; sr = sr >> 3 | xmc[42] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[43] << 13; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[46] << 13; sr = sr >> 3 | xmc[47] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; sr = sr >> 3 | xmc[50] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[51] << 13; sr = sr >> 4; *c = sr >> 8; s->frame_chain = *c; } else { uword sr; sr = 0; sr = sr >> 4 | s->frame_chain << 12; sr = sr >> 6 | LARc[0] << 10; *c++ = sr >> 6; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 8; sr = sr >> 5 | LARc[2] << 11; sr = sr >> 5 | LARc[3] << 11; *c++ = sr >> 6; sr = sr >> 4 | LARc[4] << 12; sr = sr >> 4 | LARc[5] << 12; *c++ = sr >> 6; sr = sr >> 3 | LARc[6] << 13; sr = sr >> 3 | LARc[7] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[0] << 9; sr = sr >> 2 | bc[0] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[0] << 13; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[3] << 13; sr = sr >> 3 | xmc[4] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; sr = sr >> 3 | xmc[7] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[8] << 13; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[11] << 13; sr = sr >> 3 | xmc[12] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[1] << 9; sr = sr >> 2 | bc[1] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[13] << 13; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[16] << 13; sr = sr >> 3 | xmc[17] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; sr = sr >> 3 | xmc[20] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[21] << 13; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[24] << 13; sr = sr >> 3 | xmc[25] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[2] << 9; sr = sr >> 2 | bc[2] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[26] << 13; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[29] << 13; sr = sr >> 3 | xmc[30] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; sr = sr >> 3 | xmc[33] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[34] << 13; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[37] << 13; sr = sr >> 3 | xmc[38] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[3] << 9; sr = sr >> 2 | bc[3] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[39] << 13; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[42] << 13; sr = sr >> 3 | xmc[43] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; sr = sr >> 3 | xmc[46] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[47] << 13; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[50] << 13; sr = sr >> 3 | xmc[51] << 13; *c++ = sr >> 8; } } else #endif /* WAV49 */ { *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ | ((LARc[0] >> 2) & 0xF); *c++ = ((LARc[0] & 0x3) << 6) | (LARc[1] & 0x3F); *c++ = ((LARc[2] & 0x1F) << 3) | ((LARc[3] >> 2) & 0x7); *c++ = ((LARc[3] & 0x3) << 6) | ((LARc[4] & 0xF) << 2) | ((LARc[5] >> 2) & 0x3); *c++ = ((LARc[5] & 0x3) << 6) | ((LARc[6] & 0x7) << 3) | (LARc[7] & 0x7); *c++ = ((Nc[0] & 0x7F) << 1) | ((bc[0] >> 1) & 0x1); *c++ = ((bc[0] & 0x1) << 7) | ((Mc[0] & 0x3) << 5) | ((xmaxc[0] >> 1) & 0x1F); *c++ = ((xmaxc[0] & 0x1) << 7) | ((xmc[0] & 0x7) << 4) | ((xmc[1] & 0x7) << 1) | ((xmc[2] >> 2) & 0x1); *c++ = ((xmc[2] & 0x3) << 6) | ((xmc[3] & 0x7) << 3) | (xmc[4] & 0x7); *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ | ((xmc[6] & 0x7) << 2) | ((xmc[7] >> 1) & 0x3); *c++ = ((xmc[7] & 0x1) << 7) | ((xmc[8] & 0x7) << 4) | ((xmc[9] & 0x7) << 1) | ((xmc[10] >> 2) & 0x1); *c++ = ((xmc[10] & 0x3) << 6) | ((xmc[11] & 0x7) << 3) | (xmc[12] & 0x7); *c++ = ((Nc[1] & 0x7F) << 1) | ((bc[1] >> 1) & 0x1); *c++ = ((bc[1] & 0x1) << 7) | ((Mc[1] & 0x3) << 5) | ((xmaxc[1] >> 1) & 0x1F); *c++ = ((xmaxc[1] & 0x1) << 7) | ((xmc[13] & 0x7) << 4) | ((xmc[14] & 0x7) << 1) | ((xmc[15] >> 2) & 0x1); *c++ = ((xmc[15] & 0x3) << 6) | ((xmc[16] & 0x7) << 3) | (xmc[17] & 0x7); *c++ = ((xmc[18] & 0x7) << 5) | ((xmc[19] & 0x7) << 2) | ((xmc[20] >> 1) & 0x3); *c++ = ((xmc[20] & 0x1) << 7) | ((xmc[21] & 0x7) << 4) | ((xmc[22] & 0x7) << 1) | ((xmc[23] >> 2) & 0x1); *c++ = ((xmc[23] & 0x3) << 6) | ((xmc[24] & 0x7) << 3) | (xmc[25] & 0x7); *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ | ((bc[2] >> 1) & 0x1); *c++ = ((bc[2] & 0x1) << 7) | ((Mc[2] & 0x3) << 5) | ((xmaxc[2] >> 1) & 0x1F); *c++ = ((xmaxc[2] & 0x1) << 7) | ((xmc[26] & 0x7) << 4) | ((xmc[27] & 0x7) << 1) | ((xmc[28] >> 2) & 0x1); *c++ = ((xmc[28] & 0x3) << 6) | ((xmc[29] & 0x7) << 3) | (xmc[30] & 0x7); *c++ = ((xmc[31] & 0x7) << 5) | ((xmc[32] & 0x7) << 2) | ((xmc[33] >> 1) & 0x3); *c++ = ((xmc[33] & 0x1) << 7) | ((xmc[34] & 0x7) << 4) | ((xmc[35] & 0x7) << 1) | ((xmc[36] >> 2) & 0x1); *c++ = ((xmc[36] & 0x3) << 6) | ((xmc[37] & 0x7) << 3) | (xmc[38] & 0x7); *c++ = ((Nc[3] & 0x7F) << 1) | ((bc[3] >> 1) & 0x1); *c++ = ((bc[3] & 0x1) << 7) | ((Mc[3] & 0x3) << 5) | ((xmaxc[3] >> 1) & 0x1F); *c++ = ((xmaxc[3] & 0x1) << 7) | ((xmc[39] & 0x7) << 4) | ((xmc[40] & 0x7) << 1) | ((xmc[41] >> 2) & 0x1); *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ | ((xmc[42] & 0x7) << 3) | (xmc[43] & 0x7); *c++ = ((xmc[44] & 0x7) << 5) | ((xmc[45] & 0x7) << 2) | ((xmc[46] >> 1) & 0x3); *c++ = ((xmc[46] & 0x1) << 7) | ((xmc[47] & 0x7) << 4) | ((xmc[48] & 0x7) << 1) | ((xmc[49] >> 2) & 0x1); *c++ = ((xmc[49] & 0x3) << 6) | ((xmc[50] & 0x7) << 3) | (xmc[51] & 0x7); } } /****** begin "long_term.c" *****/ /* * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION */ /* * This module computes the LTP gain (bc) and the LTP lag (Nc) * for the long term analysis filter. This is done by calculating a * maximum of the cross-correlation function between the current * sub-segment short term residual signal d[0..39] (output of * the short term analysis filter; for simplification the index * of this array begins at 0 and ends at 39 for each sub-segment of the * RPE-LTP analysis) and the previous reconstructed short term * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be * performed to avoid overflow. */ /* The next procedure exists in six versions. First two integer * version (if USE_FLOAT_MUL is not defined); then four floating * point versions, twice with proper scaling (USE_FLOAT_MUL defined), * once without (USE_FLOAT_MUL and FAST defined, and fast run-time * option used). Every pair has first a Cut version (see the -C * option to toast or the LTP_CUT option to gsm_option()), then the * uncut one. (For a detailed explanation of why this is altogether * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered * Harmful''.) */ #ifndef USE_FLOAT_MUL #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_result; longword L_max, L_power; word R, S, dmax, scal, best_k; word ltp_cut; register word temp, wt_k; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) { dmax = temp; best_k = k; } } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ wt_k = SASR(d[best_k], scal); for (lambda = 40; lambda <= 120; lambda++) { L_result = (longword)wt_k * dp[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal ); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { # undef STEP # define STEP(k) (longword)wt[k] * dp[k - lambda] register longword L_result; L_result = STEP(0) ; L_result += STEP(1) ; L_result += STEP(2) ; L_result += STEP(3) ; L_result += STEP(4) ; L_result += STEP(5) ; L_result += STEP(6) ; L_result += STEP(7) ; L_result += STEP(8) ; L_result += STEP(9) ; L_result += STEP(10) ; L_result += STEP(11) ; L_result += STEP(12) ; L_result += STEP(13) ; L_result += STEP(14) ; L_result += STEP(15) ; L_result += STEP(16) ; L_result += STEP(17) ; L_result += STEP(18) ; L_result += STEP(19) ; L_result += STEP(20) ; L_result += STEP(21) ; L_result += STEP(22) ; L_result += STEP(23) ; L_result += STEP(24) ; L_result += STEP(25) ; L_result += STEP(26) ; L_result += STEP(27) ; L_result += STEP(28) ; L_result += STEP(29) ; L_result += STEP(30) ; L_result += STEP(31) ; L_result += STEP(32) ; L_result += STEP(33) ; L_result += STEP(34) ; L_result += STEP(35) ; L_result += STEP(36) ; L_result += STEP(37) ; L_result += STEP(38) ; L_result += STEP(39) ; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #else /* USE_FLOAT_MUL */ #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word ltp_cut; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100; /* Initialization of a working array wt */ for (k = 0; k < 40; k++) { register word w = SASR( d[k], scal ); if (w < 0 ? w > -ltp_cut : w < ltp_cut) { wt_float[k] = 0.0; } else { wt_float[k] = w; } } for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ if ((W = wt_float[K]) != 0.0) { \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E; } else (a = lp[K]) # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal ); for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #ifdef FAST #ifdef LTP_CUT static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; register float wt_float; word Nc, bc; word wt_max, best_k, ltp_cut; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_result, L_max, L_power; wt_max = 0; for (k = 0; k < 40; ++k) { if ( d[k] > wt_max) wt_max = d[best_k = k]; else if (-d[k] > wt_max) wt_max = -d[best_k = k]; } assert(wt_max >= 0); wt_float = (float)wt_max; for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { L_result = wt_float * dp_float[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_max, L_power; for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k]; for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* FAST */ #endif /* USE_FLOAT_MUL */ /* 4.2.12 */ static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e), word bc, /* IN */ word Nc, /* IN */ register word * dp, /* previous d [-120..-1] IN */ register word * d, /* d [0..39] IN */ register word * dpp, /* estimate [0..39] OUT */ register word * e /* long term res. signal [0..39] OUT */ ) /* * In this part, we have to decode the bc parameter to compute * the samples of the estimate dpp[0..39]. The decoding of bc needs the * use of table 4.3b. The long term residual signal e[0..39] * is then calculated to be fed to the RPE encoding section. */ { register int k; register longword ltmp; # undef STEP # define STEP(BP) \ for (k = 0; k <= 39; k++) { \ dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ e[k] = GSM_SUB( d[k], dpp[k] ); \ } switch (bc) { case 0: STEP( 3277 ); break; case 1: STEP( 11469 ); break; case 2: STEP( 21299 ); break; case 3: STEP( 32767 ); break; } } void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d' IN */ word * e, /* [0..39] OUT */ word * dpp, /* [0..39] OUT */ word * Nc, /* correlation lag OUT */ word * bc /* gain factor OUT */ ) { assert( d ); assert( dp ); assert( e ); assert( dpp); assert( Nc ); assert( bc ); #if defined(FAST) && defined(USE_FLOAT_MUL) if (S->fast) #if defined (LTP_CUT) if (S->ltp_cut) Cut_Fast_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif /* LTP_CUT */ Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); else #endif /* FAST & USE_FLOAT_MUL */ #ifdef LTP_CUT if (S->ltp_cut) Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif Calculation_of_the_LTP_parameters(d, dp, bc, Nc); Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); } /* 4.3.2 */ void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp), struct gsm_state * S, word Ncr, word bcr, register word * erp, /* [0..39] IN */ register word * drp /* [-120..-1] IN, [-120..40] OUT */ ) /* * This procedure uses the bcr and Ncr parameter to realize the * long term synthesis filtering. The decoding of bcr needs * table 4.3b. */ { register longword ltmp; /* for ADD */ register int k; word brp, drpp, Nr; /* Check the limits of Nr. */ Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; S->nrp = Nr; assert(Nr >= 40 && Nr <= 120); /* Decoding of the LTP gain bcr */ brp = gsm_QLB[ bcr ]; /* Computation of the reconstructed short term residual * signal drp[0..39] */ assert(brp != MIN_WORD); for (k = 0; k <= 39; k++) { drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); drp[k] = GSM_ADD( erp[k], drpp ); } /* * Update of the reconstructed short term residual signal * drp[ -1..-120 ] */ for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; } /****** begin "lpc.c" *****/ #undef STEP #undef P /* * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION */ /* 4.2.4 */ static void Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */ longword * L_ACF) /* [0..8] OUT */ /* * The goal is to compute the array L_ACF[k]. The signal s[i] must * be scaled in order to avoid an overflow situation. */ { register int k, i; word temp, smax, scalauto; #ifdef USE_FLOAT_MUL float float_s[160]; #endif /* Dynamic scaling of the array s[0..159] */ /* Search for the maximum. */ smax = 0; for (k = 0; k <= 159; k++) { temp = GSM_ABS( s[k] ); if (temp > smax) smax = temp; } /* Computation of the scaling factor. */ if (smax == 0) scalauto = 0; else { assert(smax > 0); scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ } /* Scaling of the array s[0...159] */ if (scalauto > 0) { # ifdef USE_FLOAT_MUL # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ float_s[k] = (float) \ (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ break; # else # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ break; # endif /* USE_FLOAT_MUL */ switch (scalauto) { SCALE(1) SCALE(2) SCALE(3) SCALE(4) } # undef SCALE } # ifdef USE_FLOAT_MUL else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; # endif /* Compute the L_ACF[..]. */ { # ifdef USE_FLOAT_MUL register float * sp = float_s; register float sl = *sp; # define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); # else word * sp = s; word sl = *sp; # define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); # endif # define NEXTI sl = *++sp for (k = 9; k--; L_ACF[k] = 0) ; STEP (0); NEXTI; STEP(0); STEP(1); NEXTI; STEP(0); STEP(1); STEP(2); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); for (i = 8; i <= 159; i++) { NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); STEP(8); } for (k = 9; k--; L_ACF[k] <<= 1) ; } /* Rescaling of the array s[0..159] */ if (scalauto > 0) { assert(scalauto <= 4); for (k = 160; k--; *s++ <<= scalauto) ; } } #if defined(USE_FLOAT_MUL) && defined(FAST) static void Fast_Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */ longword * L_ACF) /* [0..8] OUT */ { register int k, i; float f_L_ACF[9]; float scale; float s_f[160]; register float *sf = s_f; for (i = 0; i < 160; ++i) sf[i] = s[i]; for (k = 0; k <= 8; k++) { register float L_temp2 = 0; register float *sfl = sf - k; for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; f_L_ACF[k] = L_temp2; } scale = MAX_LONGWORD / f_L_ACF[0]; for (k = 0; k <= 8; k++) { L_ACF[k] = f_L_ACF[k] * scale; } } #endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ /* 4.2.5 */ static void Reflection_coefficients P2( (L_ACF, r), longword * L_ACF, /* 0...8 IN */ register word * r /* 0...7 OUT */ ) { register int i, m, n; register word temp; register longword ltmp; word ACF[9]; /* 0..8 */ word P[ 9]; /* 0..8 */ word K[ 9]; /* 2..8 */ /* Schur recursion with 16 bits arithmetic. */ if (L_ACF[0] == 0) { for (i = 8; i--; *r++ = 0) ; return; } assert( L_ACF[0] != 0 ); temp = gsm_norm( L_ACF[0] ); assert(temp >= 0 && temp < 32); /* ? overflow ? */ for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 ); /* Initialize array P[..] and K[..] for the recursion. */ for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; /* Compute reflection coefficients */ for (n = 1; n <= 8; n++, r++) { temp = P[1]; temp = GSM_ABS(temp); if (P[0] < temp) { for (i = n; i <= 8; i++) *r++ = 0; return; } *r = gsm_div( temp, P[0] ); assert(*r >= 0); if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ assert (*r != MIN_WORD); if (n == 8) return; /* Schur recursion */ temp = GSM_MULT_R( P[1], *r ); P[0] = GSM_ADD( P[0], temp ); for (m = 1; m <= 8 - n; m++) { temp = GSM_MULT_R( K[ m ], *r ); P[m] = GSM_ADD( P[ m+1 ], temp ); temp = GSM_MULT_R( P[ m+1 ], *r ); K[m] = GSM_ADD( K[ m ], temp ); } } } /* 4.2.6 */ static void Transformation_to_Log_Area_Ratios P1((r), register word * r /* 0..7 IN/OUT */ ) /* * The following scaling for r[..] and LAR[..] has been used: * * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. * LAR[..] = integer( real_LAR[..] * 16384 ); * with -1.625 <= real_LAR <= 1.625 */ { register word temp; register int i; /* Computation of the LAR[0..7] from the r[0..7] */ for (i = 1; i <= 8; i++, r++) { temp = *r; temp = GSM_ABS(temp); assert(temp >= 0); if (temp < 22118) { temp >>= 1; } else if (temp < 31130) { assert( temp >= 11059 ); temp -= 11059; } else { assert( temp >= 26112 ); temp -= 26112; temp <<= 2; } *r = *r < 0 ? -temp : temp; assert( *r != MIN_WORD ); } } /* 4.2.7 */ static void Quantization_and_coding P1((LAR), register word * LAR /* [0..7] IN/OUT */ ) { register word temp; longword ltmp; /* This procedure needs four tables; the following equations * give the optimum scaling for the constants: * * A[0..7] = integer( real_A[0..7] * 1024 ) * B[0..7] = integer( real_B[0..7] * 512 ) * MAC[0..7] = maximum of the LARc[0..7] * MIC[0..7] = minimum of the LARc[0..7] */ # undef STEP # define STEP( A, B, MAC, MIC ) \ temp = GSM_MULT( A, *LAR ); \ temp = GSM_ADD( temp, B ); \ temp = GSM_ADD( temp, 256 ); \ temp = SASR( temp, 9 ); \ *LAR = temp>MAC ? MAC - MIC : (tempfast) Fast_Autocorrelation (s, L_ACF ); else #endif Autocorrelation (s, L_ACF ); Reflection_coefficients (L_ACF, LARc ); Transformation_to_Log_Area_Ratios (LARc); Quantization_and_coding (LARc); } /****** begin "preprocess.c" *****/ /* 4.2.0 .. 4.2.3 PREPROCESSING SECTION * * After A-law to linear conversion (or directly from the * Ato D converter) the following scaling is assumed for * input to the RPE-LTP algorithm: * * in: 0.1.....................12 * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* * * Where S is the sign bit, v a valid bit, and * a "don't care" bit. * The original signal is called sop[..] * * out: 0.1................... 12 * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 */ void Gsm_Preprocess P3((S, s, so), struct gsm_state * S, word * s, word * so ) /* [0..159] IN/OUT */ { word z1 = S->z1; longword L_z2 = S->L_z2; word mp = S->mp; word s1; longword L_s2; longword L_temp; word msp, lsp; word SO; longword ltmp; /* for ADD */ ulongword utmp; /* for L_ADD */ volatile int k = 160; while (k--) { /* 4.2.1 Downscaling of the input signal */ SO = SASR( *s, 3 ) << 2; s++; assert (SO >= -0x4000); /* downscaled by */ assert (SO <= 0x3FFC); /* previous routine. */ /* 4.2.2 Offset compensation * * This part implements a high-pass filter and requires extended * arithmetic precision for the recursive part of this filter. * The input of this procedure is the array so[0...159] and the * output the array sof[ 0...159 ]. */ /* Compute the non-recursive part */ s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ z1 = SO; assert(s1 != MIN_WORD); /* Compute the recursive part */ L_s2 = s1; L_s2 <<= 15; /* Execution of a 31 bv 16 bits multiplication */ msp = SASR( L_z2, 15 ); lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */ L_s2 += GSM_MULT_R( lsp, 32735 ); L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ L_z2 = GSM_L_ADD( L_temp, L_s2 ); /* Compute sof[k] with rounding */ L_temp = GSM_L_ADD( L_z2, 16384 ); /* 4.2.3 Preemphasis */ msp = GSM_MULT_R( mp, -28180 ); mp = SASR( L_temp, 15 ); *so++ = GSM_ADD( mp, msp ); } S->z1 = z1; S->L_z2 = L_z2; S->mp = mp; } /****** begin "rpe.c" *****/ /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION */ /* 4.2.13 */ static void Weighting_filter P2((e, x), register word * e, /* signal [-5..0.39.44] IN */ word * x /* signal [0..39] OUT */ ) /* * The coefficients of the weighting filter are stored in a table * (see table 4.4). The following scaling is used: * * H[0..10] = integer( real_H[ 0..10] * 8192 ); */ { /* word wt[ 50 ]; */ register longword L_result; register int k /* , i */ ; /* Initialization of a temporary working array wt[0...49] */ /* for (k = 0; k <= 4; k++) wt[k] = 0; * for (k = 5; k <= 44; k++) wt[k] = *e++; * for (k = 45; k <= 49; k++) wt[k] = 0; * * (e[-5..-1] and e[40..44] are allocated by the caller, * are initially zero and are not written anywhere.) */ e -= 5; /* Compute the signal x[0..39] */ for (k = 0; k <= 39; k++) { L_result = 8192 >> 1; /* for (i = 0; i <= 10; i++) { * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); * L_result = GSM_L_ADD( L_result, L_temp ); * } */ #undef STEP #define STEP( i, H ) (e[ k + i ] * (longword)H) /* Every one of these multiplications is done twice -- * but I don't see an elegant way to optimize this. * Do you? */ #ifdef STUPID_COMPILER L_result += STEP( 0, -134 ) ; L_result += STEP( 1, -374 ) ; /* + STEP( 2, 0 ) */ L_result += STEP( 3, 2054 ) ; L_result += STEP( 4, 5741 ) ; L_result += STEP( 5, 8192 ) ; L_result += STEP( 6, 5741 ) ; L_result += STEP( 7, 2054 ) ; /* + STEP( 8, 0 ) */ L_result += STEP( 9, -374 ) ; L_result += STEP( 10, -134 ) ; #else L_result += STEP( 0, -134 ) + STEP( 1, -374 ) /* + STEP( 2, 0 ) */ + STEP( 3, 2054 ) + STEP( 4, 5741 ) + STEP( 5, 8192 ) + STEP( 6, 5741 ) + STEP( 7, 2054 ) /* + STEP( 8, 0 ) */ + STEP( 9, -374 ) + STEP(10, -134 ) ; #endif /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) * * x[k] = SASR( L_result, 16 ); */ /* 2 adds vs. >>16 => 14, minus one shift to compensate for * those we lost when replacing L_MULT by '*'. */ L_result = SASR( L_result, 13 ); x[k] = ( L_result < MIN_WORD ? MIN_WORD : (L_result > MAX_WORD ? MAX_WORD : L_result )); } } /* 4.2.14 */ static void RPE_grid_selection P3((x,xM,Mc_out), word * x, /* [0..39] IN */ word * xM, /* [0..12] OUT */ word * Mc_out /* OUT */ ) /* * The signal x[0..39] is used to select the RPE grid which is * represented by Mc. */ { /* register word temp1; */ register int /* m, */ i; register longword L_result, L_temp; longword EM; /* xxx should be L_EM? */ word Mc; longword L_common_0_3; EM = 0; Mc = 0; /* for (m = 0; m <= 3; m++) { * L_result = 0; * * * for (i = 0; i <= 12; i++) { * * temp1 = SASR( x[m + 3*i], 2 ); * * assert(temp1 != MIN_WORD); * * L_temp = GSM_L_MULT( temp1, temp1 ); * L_result = GSM_L_ADD( L_temp, L_result ); * } * * if (L_result > EM) { * Mc = m; * EM = L_result; * } * } */ #undef STEP #define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \ L_result += L_temp * L_temp; /* common part of 0 and 3 */ L_result = 0; STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 ); STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 ); STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12); L_common_0_3 = L_result; /* i = 0 */ STEP( 0, 0 ); L_result <<= 1; /* implicit in L_MULT */ EM = L_result; /* i = 1 */ L_result = 0; STEP( 1, 0 ); STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 ); STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 ); STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12); L_result <<= 1; if (L_result > EM) { Mc = 1; EM = L_result; } /* i = 2 */ L_result = 0; STEP( 2, 0 ); STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); L_result <<= 1; if (L_result > EM) { Mc = 2; EM = L_result; } /* i = 3 */ L_result = L_common_0_3; STEP( 3, 12 ); L_result <<= 1; if (L_result > EM) { Mc = 3; EM = L_result; } /**/ /* Down-sampling by a factor 3 to get the selected xM[0..12] * RPE sequence. */ for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; *Mc_out = Mc; } /* 4.12.15 */ static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc,exp_out,mant_out), word xmaxc, /* IN */ word * exp_out, /* OUT */ word * mant_out ) /* OUT */ { word exp, mant; /* Compute exponent and mantissa of the decoded version of xmaxc */ exp = 0; if (xmaxc > 15) exp = SASR(xmaxc, 3) - 1; mant = xmaxc - (exp << 3); if (mant == 0) { exp = -4; mant = 7; } else { while (mant <= 7) { mant = mant << 1 | 1; exp--; } mant -= 8; } assert( exp >= -4 && exp <= 6 ); assert( mant >= 0 && mant <= 7 ); *exp_out = exp; *mant_out = mant; } static void APCM_quantization P5((xM,xMc,mant_out,exp_out,xmaxc_out), word * xM, /* [0..12] IN */ word * xMc, /* [0..12] OUT */ word * mant_out, /* OUT */ word * exp_out, /* OUT */ word * xmaxc_out /* OUT */ ) { int i, itest; word xmax, xmaxc, temp, temp1, temp2; word exp, mant; /* Find the maximum absolute value xmax of xM[0..12]. */ xmax = 0; for (i = 0; i <= 12; i++) { temp = xM[i]; temp = GSM_ABS(temp); if (temp > xmax) xmax = temp; } /* Qantizing and coding of xmax to get xmaxc. */ exp = 0; temp = SASR( xmax, 9 ); itest = 0; for (i = 0; i <= 5; i++) { itest |= (temp <= 0); temp = SASR( temp, 1 ); assert(exp <= 5); if (itest == 0) exp++; /* exp = add (exp, 1) */ } assert(exp <= 6 && exp >= 0); temp = exp + 5; assert(temp <= 11 && temp >= 0); xmaxc = gsm_add( SASR(xmax, temp), exp << 3 ); /* Quantizing and coding of the xM[0..12] RPE sequence * to get the xMc[0..12] */ APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant ); /* This computation uses the fact that the decoded version of xmaxc * can be calculated by using the exponent and the mantissa part of * xmaxc (logarithmic table). * So, this method avoids any division and uses only a scaling * of the RPE samples by a function of the exponent. A direct * multiplication by the inverse of the mantissa (NRFAC[0..7] * found in table 4.5) gives the 3 bit coded version xMc[0..12] * of the RPE samples. */ /* Direct computation of xMc[0..12] using table 4.5 */ assert( exp <= 4096 && exp >= -4096); assert( mant >= 0 && mant <= 7 ); temp1 = 6 - exp; /* normalization by the exponent */ temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ for (i = 0; i <= 12; i++) { assert(temp1 >= 0 && temp1 < 16); temp = xM[i] << temp1; temp = GSM_MULT( temp, temp2 ); temp = SASR(temp, 12); xMc[i] = temp + 4; /* see note below */ } /* NOTE: This equation is used to make all the xMc[i] positive. */ *mant_out = mant; *exp_out = exp; *xmaxc_out = xmaxc; } /* 4.2.16 */ static void APCM_inverse_quantization P4((xMc,mant,exp,xMp), register word * xMc, /* [0..12] IN */ word mant, word exp, register word * xMp) /* [0..12] OUT */ /* * This part is for decoding the RPE sequence of coded xMc[0..12] * samples to obtain the xMp[0..12] array. Table 4.6 is used to get * the mantissa of xmaxc (FAC[0..7]). */ { int i; word temp, temp1, temp2, temp3; longword ltmp; assert( mant >= 0 && mant <= 7 ); temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ temp2 = gsm_sub( 6, exp ); /* see 4.2-15 for exp */ temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); for (i = 13; i--;) { assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ /* temp = gsm_sub( *xMc++ << 1, 7 ); */ temp = (*xMc++ << 1) - 7; /* restore sign */ assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ temp <<= 12; /* 16 bit signed */ temp = GSM_MULT_R( temp1, temp ); temp = GSM_ADD( temp, temp3 ); *xMp++ = gsm_asr( temp, temp2 ); } } /* 4.2.17 */ static void RPE_grid_positioning P3((Mc,xMp,ep), word Mc, /* grid position IN */ register word * xMp, /* [0..12] IN */ register word * ep /* [0..39] OUT */ ) /* * This procedure computes the reconstructed long term residual signal * ep[0..39] for the LTP analysis filter. The inputs are the Mc * which is the grid position selection and the xMp[0..12] decoded * RPE samples which are upsampled by a factor of 3 by inserting zero * values. */ { volatile int i = 13; assert(0 <= Mc && Mc <= 3); switch (Mc) { case 3: *ep++ = 0; case 2: do { *ep++ = 0; case 1: *ep++ = 0; case 0: *ep++ = *xMp++; } while (--i); } while (++Mc < 4) *ep++ = 0; /* int i, k; for (k = 0; k <= 39; k++) ep[k] = 0; for (i = 0; i <= 12; i++) { ep[ Mc + (3*i) ] = xMp[i]; } */ } /* 4.2.18 */ /* This procedure adds the reconstructed long term residual signal * ep[0..39] to the estimated signal dpp[0..39] from the long term * analysis filter to compute the reconstructed short term residual * signal dp[-40..-1]; also the reconstructed short term residual * array dp[-120..-41] is updated. */ #if 0 /* Has been inlined in code.c */ void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp), word * dpp, /* [0...39] IN */ word * ep, /* [0...39] IN */ word * dp) /* [-120...-1] IN/OUT */ { int k; for (k = 0; k <= 79; k++) dp[ -120 + k ] = dp[ -80 + k ]; for (k = 0; k <= 39; k++) dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); } #endif /* Has been inlined in code.c */ void Gsm_RPE_Encoding P5((S,e,xmaxc,Mc,xMc), struct gsm_state * S, word * e, /* -5..-1][0..39][40..44 IN/OUT */ word * xmaxc, /* OUT */ word * Mc, /* OUT */ word * xMc) /* [0..12] OUT */ { word x[40]; word xM[13], xMp[13]; word mant, exp; Weighting_filter(e, x); RPE_grid_selection(x, xM, Mc); APCM_quantization( xM, xMc, &mant, &exp, xmaxc); APCM_inverse_quantization( xMc, mant, exp, xMp); RPE_grid_positioning( *Mc, xMp, e ); } void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp), struct gsm_state * S, word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */ word * erp /* [0..39] OUT */ ) { word exp, mant; word xMp[ 13 ]; APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant ); APCM_inverse_quantization( xMcr, mant, exp, xMp ); RPE_grid_positioning( Mcr, xMp, erp ); } /****** begin "short_term.c" *****/ /* * SHORT TERM ANALYSIS FILTERING SECTION */ /* 4.2.8 */ static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp), word * LARc, /* coded log area ratio [0..7] IN */ word * LARpp) /* out: decoded .. */ { register word temp1 /* , temp2 */; register long ltmp; /* for GSM_ADD */ /* This procedure requires for efficient implementation * two tables. * * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) * MIC[1..8] = minimum value of the LARc[1..8] */ /* Compute the LARpp[1..8] */ /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { * * temp1 = GSM_ADD( *LARc, *MIC ) << 10; * temp2 = *B << 1; * temp1 = GSM_SUB( temp1, temp2 ); * * assert(*INVA != MIN_WORD); * * temp1 = GSM_MULT_R( *INVA, temp1 ); * *LARpp = GSM_ADD( temp1, temp1 ); * } */ #undef STEP #define STEP( B, MIC, INVA ) \ temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ temp1 = GSM_SUB( temp1, B << 1 ); \ temp1 = GSM_MULT_R( INVA, temp1 ); \ *LARpp++ = GSM_ADD( temp1, temp1 ); STEP( 0, -32, 13107 ); STEP( 0, -32, 13107 ); STEP( 2048, -16, 13107 ); STEP( -2560, -16, 13107 ); STEP( 94, -8, 19223 ); STEP( -1792, -8, 17476 ); STEP( -341, -4, 31454 ); STEP( -1144, -4, 29708 ); /* NOTE: the addition of *MIC is used to restore * the sign of *LARc. */ } /* 4.2.9 */ /* Computation of the quantized reflection coefficients */ /* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] */ /* * Within each frame of 160 analyzed speech samples the short term * analysis and synthesis filters operate with four different sets of * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) * and the actual set of decoded LARs (LARpp(j)) * * (Initial value: LARpp(j-1)[1..8] = 0.) */ static void Coefficients_0_12 P3((LARpp_j_1, LARpp_j, LARp), register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; register longword ltmp; for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); *LARp = GSM_ADD( *LARp, SASR( *LARpp_j_1, 1)); } } static void Coefficients_13_26 P3((LARpp_j_1, LARpp_j, LARp), register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; register longword ltmp; for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { *LARp = GSM_ADD( SASR( *LARpp_j_1, 1), SASR( *LARpp_j, 1 )); } } static void Coefficients_27_39 P3((LARpp_j_1, LARpp_j, LARp), register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; register longword ltmp; for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); *LARp = GSM_ADD( *LARp, SASR( *LARpp_j, 1 )); } } static void Coefficients_40_159 P2((LARpp_j, LARp), register word * LARpp_j, register word * LARp) { register int i; for (i = 1; i <= 8; i++, LARp++, LARpp_j++) *LARp = *LARpp_j; } /* 4.2.9.2 */ static void LARp_to_rp P1((LARp), register word * LARp) /* [0..7] IN/OUT */ /* * The input of this procedure is the interpolated LARp[0..7] array. * The reflection coefficients, rp[i], are used in the analysis * filter and in the synthesis filter. */ { register int i; register word temp; register longword ltmp; for (i = 1; i <= 8; i++, LARp++) { /* temp = GSM_ABS( *LARp ); * * if (temp < 11059) temp <<= 1; * else if (temp < 20070) temp += 11059; * else temp = GSM_ADD( temp >> 2, 26112 ); * * *LARp = *LARp < 0 ? -temp : temp; */ if (*LARp < 0) { temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); *LARp = - ((temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 : GSM_ADD( temp >> 2, 26112 ))); } else { temp = *LARp; *LARp = (temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 : GSM_ADD( temp >> 2, 26112 )); } } } /* 4.2.10 */ static void Short_term_analysis_filtering P4((S,rp,k_n,s), struct gsm_state * S, register word * rp, /* [0..7] IN */ register int k_n, /* k_end - k_start */ register word * s /* [0..n-1] IN/OUT */ ) /* * This procedure computes the short term residual signal d[..] to be fed * to the RPE-LTP loop from the s[..] signal and from the local rp[..] * array (quantized reflection coefficients). As the call of this * procedure can be done in many ways (see the interpolation of the LAR * coefficient), it is assumed that the computation begins with index * k_start (for arrays d[..] and s[..]) and stops with index k_end * (k_start and k_end are defined in 4.2.9.1). This procedure also * needs to keep the array u[0..7] in memory for each call. */ { register word * u = S->u; register int i; register word di, zzz, ui, sav, rpi; register longword ltmp; for (; k_n--; s++) { di = sav = *s; for (i = 0; i < 8; i++) { /* YYY */ ui = u[i]; rpi = rp[i]; u[i] = sav; zzz = GSM_MULT_R(rpi, di); sav = GSM_ADD( ui, zzz); zzz = GSM_MULT_R(rpi, ui); di = GSM_ADD( di, zzz ); } *s = di; } } #if defined(USE_FLOAT_MUL) && defined(FAST) static void Fast_Short_term_analysis_filtering P4((S,rp,k_n,s), struct gsm_state * S, register word * rp, /* [0..7] IN */ register int k_n, /* k_end - k_start */ register word * s /* [0..n-1] IN/OUT */ ) { register word * u = S->u; register int i; float uf[8], rpf[8]; register float scalef = 3.0517578125e-5; register float sav, di, temp; for (i = 0; i < 8; ++i) { uf[i] = u[i]; rpf[i] = rp[i] * scalef; } for (; k_n--; s++) { sav = di = *s; for (i = 0; i < 8; ++i) { register float rpfi = rpf[i]; register float ufi = uf[i]; uf[i] = sav; temp = rpfi * di + ufi; di += rpfi * ufi; sav = temp; } *s = di; } for (i = 0; i < 8; ++i) u[i] = uf[i]; } #endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */ static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), struct gsm_state * S, register word * rrp, /* [0..7] IN */ register int k, /* k_end - k_start */ register word * wt, /* [0..k-1] IN */ register word * sr /* [0..k-1] OUT */ ) { register word * v = S->v; register int i; register word sri, tmp1, tmp2; register longword ltmp; /* for GSM_ADD & GSM_SUB */ while (k--) { sri = *wt++; for (i = 8; i--;) { /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); */ tmp1 = rrp[i]; tmp2 = v[i]; tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD ? MAX_WORD : 0x0FFFF & (( (longword)tmp1 * (longword)tmp2 + 16384) >> 15)) ; sri = GSM_SUB( sri, tmp2 ); /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); */ tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD ? MAX_WORD : 0x0FFFF & (( (longword)tmp1 * (longword)sri + 16384) >> 15)) ; v[i+1] = GSM_ADD( v[i], tmp1); } *sr++ = v[0] = sri; } } #if defined(FAST) && defined(USE_FLOAT_MUL) static void Fast_Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), struct gsm_state * S, register word * rrp, /* [0..7] IN */ register int k, /* k_end - k_start */ register word * wt, /* [0..k-1] IN */ register word * sr /* [0..k-1] OUT */ ) { register word * v = S->v; register int i; float va[9], rrpa[8]; register float scalef = 3.0517578125e-5, temp; for (i = 0; i < 8; ++i) { va[i] = v[i]; rrpa[i] = (float)rrp[i] * scalef; } while (k--) { register float sri = *wt++; for (i = 8; i--;) { sri -= rrpa[i] * va[i]; if (sri < -32768.) sri = -32768.; else if (sri > 32767.) sri = 32767.; temp = va[i] + rrpa[i] * sri; if (temp < -32768.) temp = -32768.; else if (temp > 32767.) temp = 32767.; va[i+1] = temp; } *sr++ = va[0] = sri; } for (i = 0; i < 9; ++i) v[i] = va[i]; } #endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s), struct gsm_state * S, word * LARc, /* coded log area ratio [0..7] IN */ word * s /* signal [0..159] IN/OUT */ ) { word * LARpp_j = S->LARpp[ S->j ]; word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; word LARp[8]; #undef FILTER #if defined(FAST) && defined(USE_FLOAT_MUL) # define FILTER (* (S->fast \ ? Fast_Short_term_analysis_filtering \ : Short_term_analysis_filtering )) #else # define FILTER Short_term_analysis_filtering #endif Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER( S, LARp, 13, s); Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 14, s + 13); Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 13, s + 27); Coefficients_40_159( LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 120, s + 40); } void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s), struct gsm_state * S, word * LARcr, /* received log area ratios [0..7] IN */ word * wt, /* received d [0..159] IN */ word * s /* signal s [0..159] OUT */ ) { word * LARpp_j = S->LARpp[ S->j ]; word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; word LARp[8]; #undef FILTER #if defined(FAST) && defined(USE_FLOAT_MUL) # define FILTER (* (S->fast \ ? Fast_Short_term_synthesis_filtering \ : Short_term_synthesis_filtering )) #else # define FILTER Short_term_synthesis_filtering #endif Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER( S, LARp, 13, wt, s ); Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 14, wt + 13, s + 13 ); Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 13, wt + 27, s + 27 ); Coefficients_40_159( LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER(S, LARp, 120, wt + 40, s + 40); } /****** begin "table.c" *****/ /* Most of these tables are inlined at their point of use. */ /* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP * CODER AND DECODER * * (Most of them inlined, so watch out.) */ /* Table 4.1 Quantization of the Log.-Area Ratios */ /* i 1 2 3 4 5 6 7 8 */ word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; /* Table 4.2 Tabulation of 1/A[1..8] */ word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; /* Table 4.3a Decision level of the LTP gain quantizer */ /* bc 0 1 2 3 */ word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; /* Table 4.3b Quantization levels of the LTP gain quantizer */ /* bc 0 1 2 3 */ word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; /* Table 4.4 Coefficients of the weighting filter */ /* i 0 1 2 3 4 5 6 7 8 9 10 */ word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; /* Table 4.5 Normalized inverse mantissa used to compute xM/xmax */ /* i 0 1 2 3 4 5 6 7 */ word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; /* Table 4.6 Normalized direct mantissa used to compute xM/xmax */ /* i 0 1 2 3 4 5 6 7 */ word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; /***** Squeak Interface Code Starts Here *****/ /* prototypes */ void gsmEncode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta); void gsmDecode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta); void gsmInitState(int state); int gsmStateBytes(void); /* glue functions */ void gsmEncode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta) { int maxSrcFrames, maxDstFrames, srcPtr, dstPtr, i; maxSrcFrames = (srcSize + 1 - srcIndex) / 160; maxDstFrames = (dstSize + 1 - dstIndex) / 33; if (frameCount > maxSrcFrames) frameCount = maxSrcFrames; if (frameCount > maxDstFrames) frameCount = maxDstFrames; srcPtr = src + 4 + ((srcIndex - 1) * 2); dstPtr = dst + 4 + (dstIndex - 1); for (i = 1; i <= frameCount; i++) { gsm_encode((gsm) state, (short *) srcPtr, (unsigned char *) dstPtr); srcPtr += 160 * 2; dstPtr += 33; } *srcDelta = frameCount * 160; *dstDelta = frameCount * 33; } void gsmDecode( int state, int frameCount, int src, int srcIndex, int srcSize, int dst, int dstIndex, int dstSize, int *srcDelta, int *dstDelta) { int maxSrcFrames, maxDstFrames, srcPtr, dstPtr, i; maxSrcFrames = (srcSize + 1 - srcIndex) / 33; maxDstFrames = (dstSize + 1 - dstIndex) / 160; if (frameCount > maxSrcFrames) frameCount = maxSrcFrames; if (frameCount > maxDstFrames) frameCount = maxDstFrames; srcPtr = src + 4 + (srcIndex - 1); dstPtr = dst + 4 + ((dstIndex - 1) * 2); for (i = 1; i <= frameCount; i++) { gsm_decode((gsm) state, (unsigned char *) srcPtr, (short *) dstPtr); srcPtr += 33; dstPtr += 160 * 2; } *srcDelta = frameCount * 33; *dstDelta = frameCount * 160; } void gsmInitState(int state) { /* Initialize the given GSM state record. */ memset((char *) state, 0, sizeof(struct gsm_state)); ((gsm) state)->nrp = 40; } int gsmStateBytes(void) { /* Return the size of a GSM state record in bytes. */ return sizeof(struct gsm_state); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/SoundGenerationPlugin/SoundGenerationPlugin.h ================================================ /* obsolete primitives for backward compatibility */ int primFMSoundmixSampleCountintostartingAtpan(void); int oldprimSampledSoundmixSampleCountintostartingAtleftVolrightVol(void); int primPluckedSoundmixSampleCountintostartingAtpan(void); int primSampledSoundmixSampleCountintostartingAtpan(void); int primWaveTableSoundmixSampleCountintostartingAtpan(void); ================================================ FILE: vm/src/from_squeak/Cross/plugins/SoundGenerationPlugin/sqOldSoundPrims.c ================================================ /* Automatically generated from Squeak on (4 January 1998 3:05:25 am ) */ #include "sq.h" /* Memory Access Macros */ #define byteAt(i) (*((unsigned char *) (i))) #define byteAtput(i, val) (*((unsigned char *) (i)) = val) #define longAt(i) (*((int *) (i))) #define longAtput(i, val) (*((int *) (i)) = val) /*** Imported Functions/Variables ***/ extern int stackValue(int); extern int successFlag; /*** Variables ***/ /*** Function Prototypes ***/ int primFMSoundmixSampleCountintostartingAtpan(void); int primPluckedSoundmixSampleCountintostartingAtpan(void); int primSampledSoundmixSampleCountintostartingAtpan(void); int primWaveTableSoundmixSampleCountintostartingAtpan(void); int oldprimSampledSoundmixSampleCountintostartingAtleftVolrightVol(void); int primFMSoundmixSampleCountintostartingAtpan(void) { int rcvr; int n; short int *aSoundBuffer; int startIndex; int pan; int mySample; int sample; int lastIndex; int channelIndex; int i; short int *waveTable; int waveTableSize; int count; int amplitude; int increment; int index; int modulation; int offsetIncrement; int offsetIndex; rcvr = stackValue(4); n = checkedIntegerValueOf(stackValue(3)); aSoundBuffer = arrayValueOf(stackValue(2)); startIndex = checkedIntegerValueOf(stackValue(1)); pan = checkedIntegerValueOf(stackValue(0)); waveTable = fetchArrayofObject(1, rcvr); waveTableSize = fetchIntegerofObject(2, rcvr); count = fetchIntegerofObject(4, rcvr); amplitude = fetchIntegerofObject(6, rcvr); increment = fetchIntegerofObject(8, rcvr); index = fetchIntegerofObject(9, rcvr); modulation = fetchIntegerofObject(11, rcvr); offsetIncrement = fetchIntegerofObject(14, rcvr); offsetIndex = fetchIntegerofObject(15, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; for (i = startIndex; i <= lastIndex; i += 1) { mySample = (amplitude * (waveTable[index - 1])) / 1000; if (pan > 0) { channelIndex = 2 * i; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * pan) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } if (pan < 1000) { channelIndex = (2 * i) - 1; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * (1000 - pan)) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } index = (index + increment) + ((modulation * (waveTable[offsetIndex - 1])) / 1000000); if (index > waveTableSize) { index -= waveTableSize; } if (index < 1) { index += waveTableSize; } offsetIndex += offsetIncrement; if (offsetIndex > waveTableSize) { offsetIndex -= waveTableSize; } } count -= n; storeIntegerofObjectwithValue(4, rcvr, count); storeIntegerofObjectwithValue(9, rcvr, index); storeIntegerofObjectwithValue(15, rcvr, offsetIndex); pop(4); } int primPluckedSoundmixSampleCountintostartingAtpan(void) { int rcvr; int n; short int *aSoundBuffer; int startIndex; int pan; int lastIndex; int channelIndex; int i; int sample; int mySample; int thisIndex; int nextIndex; int count; short int *ring; int ringSize; int ringIndx; rcvr = stackValue(4); n = checkedIntegerValueOf(stackValue(3)); aSoundBuffer = arrayValueOf(stackValue(2)); startIndex = checkedIntegerValueOf(stackValue(1)); pan = checkedIntegerValueOf(stackValue(0)); count = fetchIntegerofObject(2, rcvr); ring = fetchArrayofObject(4, rcvr); ringSize = fetchIntegerofObject(5, rcvr); ringIndx = fetchIntegerofObject(6, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; thisIndex = ringIndx; for (i = startIndex; i <= lastIndex; i += 1) { nextIndex = (thisIndex % ringSize) + 1; mySample = ((ring[thisIndex - 1]) + (ring[nextIndex - 1])) / 2; ring[thisIndex - 1] = mySample; thisIndex = nextIndex; if (pan > 0) { channelIndex = 2 * i; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * pan) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } if (pan < 1000) { channelIndex = (2 * i) - 1; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * (1000 - pan)) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } } ringIndx = nextIndex; count -= n; storeIntegerofObjectwithValue(2, rcvr, count); storeIntegerofObjectwithValue(6, rcvr, ringIndx); pop(4); } int primSampledSoundmixSampleCountintostartingAtpan(void) { int rcvr; int n; short int *aSoundBuffer; int startIndex; int pan; int lastIndex; int i; int channelIndex; int sample; int sampleIndex; int thisSample; short int *samples; int samplesSize; int incrementTimes1000; int count; int indexTimes1000; rcvr = stackValue(4); n = checkedIntegerValueOf(stackValue(3)); aSoundBuffer = arrayValueOf(stackValue(2)); startIndex = checkedIntegerValueOf(stackValue(1)); pan = checkedIntegerValueOf(stackValue(0)); samples = fetchArrayofObject(1, rcvr); samplesSize = fetchIntegerofObject(2, rcvr); incrementTimes1000 = fetchIntegerofObject(3, rcvr); count = fetchIntegerofObject(5, rcvr); indexTimes1000 = fetchIntegerofObject(6, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; i = startIndex; sampleIndex = indexTimes1000 / 1000; while ((sampleIndex <= samplesSize) && (i <= lastIndex)) { thisSample = samples[sampleIndex - 1]; if (pan > 0) { channelIndex = 2 * i; sample = (aSoundBuffer[channelIndex - 1]) + ((thisSample * pan) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } if (pan < 1000) { channelIndex = (2 * i) - 1; sample = (aSoundBuffer[channelIndex - 1]) + ((thisSample * (1000 - pan)) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } indexTimes1000 += incrementTimes1000; sampleIndex = indexTimes1000 / 1000; i += 1; } count -= n; storeIntegerofObjectwithValue(5, rcvr, count); storeIntegerofObjectwithValue(6, rcvr, indexTimes1000); pop(4); } int primWaveTableSoundmixSampleCountintostartingAtpan(void) { int rcvr; int n; short int *aSoundBuffer; int startIndex; int pan; int lastIndex; int channelIndex; int i; int mySample; int sample; short int *waveTable; int waveTableSize; int count; int amplitude; int increment; int index; rcvr = stackValue(4); n = checkedIntegerValueOf(stackValue(3)); aSoundBuffer = arrayValueOf(stackValue(2)); startIndex = checkedIntegerValueOf(stackValue(1)); pan = checkedIntegerValueOf(stackValue(0)); waveTable = fetchArrayofObject(1, rcvr); waveTableSize = fetchIntegerofObject(2, rcvr); count = fetchIntegerofObject(4, rcvr); amplitude = fetchIntegerofObject(6, rcvr); increment = fetchIntegerofObject(8, rcvr); index = fetchIntegerofObject(9, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; for (i = startIndex; i <= lastIndex; i += 1) { mySample = (amplitude * (waveTable[index - 1])) / 1000; if (pan > 0) { channelIndex = 2 * i; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * pan) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } if (pan < 1000) { channelIndex = (2 * i) - 1; sample = (aSoundBuffer[channelIndex - 1]) + ((mySample * (1000 - pan)) / 1000); if (sample > 32767) { sample = 32767; } if (sample < -32767) { sample = -32767; } aSoundBuffer[channelIndex - 1] = sample; } index += increment; if (index > waveTableSize) { index -= waveTableSize; } } count -= n; storeIntegerofObjectwithValue(4, rcvr, count); storeIntegerofObjectwithValue(9, rcvr, index); pop(4); } int oldprimSampledSoundmixSampleCountintostartingAtleftVolrightVol(void) { int rcvr; int n; short int *aSoundBuffer; int startIndex; int leftVol; int rightVol; int sliceIndex; int sampleIndex; int sample; int s; int lastIndex; int i; int scaledVol; int scaledVolIncr; int scaledVolLimit; int count; short int *samples; int samplesSize; int incrementTimes1000; int indexTimes1000; rcvr = stackValue(5); n = checkedIntegerValueOf(stackValue(4)); aSoundBuffer = arrayValueOf(stackValue(3)); aSoundBuffer -= 1; startIndex = checkedIntegerValueOf(stackValue(2)); leftVol = checkedIntegerValueOf(stackValue(1)); rightVol = checkedIntegerValueOf(stackValue(0)); scaledVol = fetchIntegerofObject(3, rcvr); scaledVolIncr = fetchIntegerofObject(4, rcvr); scaledVolLimit = fetchIntegerofObject(5, rcvr); count = fetchIntegerofObject(7, rcvr); samples = fetchArrayofObject(8, rcvr); samples -= 1; samplesSize = fetchIntegerofObject(10, rcvr); incrementTimes1000 = fetchIntegerofObject(11, rcvr); indexTimes1000 = fetchIntegerofObject(12, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; sliceIndex = startIndex; sampleIndex = indexTimes1000 / 1000; while ((sampleIndex <= samplesSize) && (sliceIndex <= lastIndex)) { sample = ((int) ((samples[sampleIndex]) * scaledVol) >> 15); if (leftVol > 0) { i = (2 * sliceIndex) - 1; s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (rightVol > 0) { i = 2 * sliceIndex; s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (scaledVolIncr != 0) { scaledVol += scaledVolIncr; if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) { scaledVol = scaledVolLimit; scaledVolIncr = 0; } } indexTimes1000 += incrementTimes1000; sampleIndex = indexTimes1000 / 1000; sliceIndex += 1; } count -= n; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(12, rcvr, indexTimes1000); pop(5); } ================================================ FILE: vm/src/from_squeak/Cross/plugins/SoundPlugin/SoundPlugin.h ================================================ /* SoundPlugin.h - header for Sound Plugins :-) tim@sumeru.stanford.edu */ /* module initialization/shutdown */ sqInt soundInit(void); sqInt soundShutdown(void); /* sound output */ sqInt snd_AvailableSpace(void); sqInt snd_InsertSamplesFromLeadTime(sqInt frameCount, void *srcBufPtr, sqInt samplesOfLeadTime); sqInt snd_PlaySamplesFromAtLength(sqInt frameCount, void *srcBufPtr, sqInt startIndex); sqInt snd_PlaySilence(void); sqInt snd_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex); sqInt snd_Stop(void); /* sound input */ int snd_SetRecordLevel(sqInt level); sqInt snd_StartRecording(sqInt desiredSamplesPerSec, sqInt stereo, sqInt semaIndex); sqInt snd_StopRecording(void); double snd_GetRecordingSampleRate(void); sqInt snd_RecordSamplesIntoAtLength(void *buf, sqInt startSliceIndex, sqInt bufferSizeInBytes); void snd_Volume(double *left, double *right); /* johnmci@smalltalkconsulting.com Nov 6th 2000 */ void snd_SetVolume(double left, double right); /* johnmci@smalltalkconsulting.com Nov 6th 2000 */ /* mixer interface */ sqInt snd_GetSwitch(sqInt identifier, sqInt captureFlag, sqInt channel); sqInt snd_SetSwitch(sqInt identifier, sqInt captureFlag, sqInt parameter); sqInt snd_SetDevice(sqInt identifier, char *name); ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3d.h ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3d.h * CONTENT: Main include file * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3d.h 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #ifndef __B3D_H #define __B3D_H #ifdef DEBUG #define b3dDebug 1 #else #define b3dDebug 0 #endif #define b3dDoStats 1 /* primary include file */ #include "b3dTypes.h" #include "b3dAlloc.h" typedef int (*b3dDrawBufferFunction) (int leftX, int rightX, int yValue); typedef struct B3DRasterizerState { /* The three sources for allocating temporary rasterizer objects */ B3DFaceAllocList *faceAlloc; B3DEdgeAllocList *edgeAlloc; B3DAttrAllocList *attrAlloc; /* The active edge table */ B3DActiveEdgeTable *aet; /* The list for newly added edges */ B3DPrimitiveEdgeList *addedEdges; /* The fill list */ B3DFillList *fillList; /* The input objects for the rasterizer */ int nObjects; B3DPrimitiveObject **objects; /* The input textures for the rasterizer */ int nTextures; B3DTexture *textures; /* Length and location of span buffer to use */ int spanSize; unsigned int *spanBuffer; /* Function to call on drawing the output buffer */ b3dDrawBufferFunction spanDrawer; } B3DRasterizerState; extern B3DRasterizerState *currentState; /* from b3dInit.c */ int b3dInitializeEdgeAllocator(void* base, int length); int b3dInitializeFaceAllocator(void* base, int length); int b3dInitializeAttrAllocator(void* base, int length); int b3dInitializeAET(void* base, int length); int b3dInitializeEdgeList(void* base, int length); int b3dInitializeFillList(void* base, int length); int b3dSetupObjects(B3DRasterizerState *state); int b3dAddPolygonObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DPrimitiveViewport *vp); int b3dAddIndexedQuadObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DInputQuad *quadPtr, int nQuads, B3DPrimitiveViewport *vp); int b3dAddIndexedTriangleObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DInputFace *facePtr, int nFaces, B3DPrimitiveViewport *vp); int b3dLoadTexture(B3DTexture *texture, int width, int height, int depth, unsigned int *bits, int cmSize, unsigned int *colormap); /* from b3dRemap.c */ int b3dValidateAndRemapState(B3DRasterizerState *state); /* from b3dDraw.c */ typedef void (*b3dPixelDrawer) (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); extern b3dPixelDrawer B3D_FILL_FUNCTIONS[]; /* from b3dMain.c */ void b3dAbort(char *msg); int b3dMainLoop(B3DRasterizerState *state, int stopReason); #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dAlloc.c ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dAlloc.c * CONTENT: Memory allocation for the Balloon 3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dAlloc.c 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #include #include "b3d.h" #ifdef DEBUG_ALLOC /* DEBUG versions of allocators */ B3DPrimitiveFace *dbg_b3dAllocFace(B3DFaceAllocList *list) { B3DPrimitiveFace *result; if(list->firstFree) { result = list->firstFree; list->firstFree = list->firstFree->nextFree; if(result->flags & B3D_ALLOC_FLAG) b3dAbort("list->firstFree has allocation bit set"); } else { if(list->size < list->max) { result = list->data + list->size; list->size++; } else return NULL; } result->nextFree = NULL; result->flags = B3D_ALLOC_FLAG; list->nFree--; return result; } B3DPrimitiveEdge *dbg_b3dAllocEdge(B3DEdgeAllocList *list) { B3DPrimitiveEdge *result; if(list->firstFree) { result = list->firstFree; list->firstFree = list->firstFree->nextFree; if(result->flags & B3D_ALLOC_FLAG) b3dAbort("list->firstFree has allocation bit set"); } else { if(list->size < list->max) { result = list->data + list->size; list->size++; } else return NULL; } result->nextFree = NULL; result->flags = B3D_ALLOC_FLAG; list->nFree--; return result; } void dbg_b3dFreeFace(B3DFaceAllocList *list, B3DPrimitiveFace *face) { if(face < list->data || face >= (list->data + list->size)) b3dAbort("face to free is not in list"); if( ! (face->flags & B3D_ALLOC_FLAG) ) b3dAbort("face to free has no allocation flag set"); face->flags = 0; face->nextFree = list->firstFree; list->firstFree = face; list->nFree++; } void dbg_b3dFreeEdge(B3DEdgeAllocList *list, B3DPrimitiveEdge *edge) { if(edge < list->data || edge >= (list->data + list->size)) b3dAbort("edge to free is not in list"); if( ! (edge->flags & B3D_ALLOC_FLAG) ) b3dAbort("edge to free has no allocation flag set"); edge->flags = 0; edge->nextFree = list->firstFree; list->firstFree = edge; list->nFree++; } B3DPrimitiveAttribute *dbg_b3dAllocSingleAttr(B3DAttrAllocList *list) { B3DPrimitiveAttribute *result; if(list->firstFree) { result = list->firstFree; list->firstFree = list->firstFree->next; } else { if(list->size < list->max) { result = list->data + list->size; list->size++; } else return NULL; } list->nFree--; return result; } int dbg_b3dAllocAttrib(B3DAttrAllocList *attrList, B3DPrimitiveFace *face) { B3DPrimitiveAttribute *firstAttr, *nextAttr; int i, nAttrs = 0; assert(face->attributes == NULL); if(face->flags & B3D_FACE_RGB) nAttrs += 3; if(face->flags & B3D_FACE_ALPHA) nAttrs += 1; if(face->flags & B3D_FACE_STW) nAttrs += 3; if(!nAttrs) return 1; firstAttr = nextAttr = NULL; for(i=0;inext = firstAttr; firstAttr = nextAttr; } face->attributes = firstAttr; return 1; } void dbg_b3dFreeAttrib(B3DAttrAllocList *list, B3DPrimitiveFace *face) { B3DPrimitiveAttribute *attr, *nextAttr = face->attributes; while(nextAttr) { attr = nextAttr; nextAttr = attr->next; if(attr < list->data || attr >= (list->data + list->size)) b3dAbort("attributes to free are not in list"); attr->next = list->firstFree; list->firstFree = attr; list->nFree++; } } #endif /* DEBUG */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dAlloc.h ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dAlloc.h * CONTENT: Memory allocation for the Balloon 3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dAlloc.h 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #ifndef B3D_ALLOC_H #define B3D_ALLOC_H #include "b3dTypes.h" /************************ Allocator definitions ************************/ #define B3D_EDGE_ALLOC_MAGIC 0x45443341 typedef struct B3DEdgeAllocList { int magic; void *This; int max; /* Note: size is ALWAYS less than max */ int size; int nFree; B3DPrimitiveEdge *firstFree; /* pointer to the first free edge (< max) */ B3DPrimitiveEdge data[1]; } B3DEdgeAllocList; #define B3D_FACE_ALLOC_MAGIC 0x46443341 typedef struct B3DFaceAllocList { int magic; void *This; int max; /* Note: size is ALWAYS less than max */ int size; int nFree; B3DPrimitiveFace *firstFree; /* pointer to the first free face (< max) */ B3DPrimitiveFace data[1]; } B3DFaceAllocList; #define B3D_ATTR_ALLOC_MAGIC 0x41443341 typedef struct B3DAttrAllocList { int magic; void *This; int max; /* Note: size is ALWAYS less than max */ int size; int nFree; B3DPrimitiveAttribute *firstFree; /* pointer to the first free attribute (< max) */ B3DPrimitiveAttribute data[1]; } B3DAttrAllocList; /* The mapping from face flags to the number of attributes needed */ extern int B3D_ATTRIBUTE_SIZES[B3D_MAX_ATTRIBUTES]; #define B3D_FACE_ATTRIB_SIZE(face) (B3D_ATTRIBUTE_SIZES[(face->flags >> B3D_ATTR_SHIFT) & B3D_ATTR_MASK]) #ifdef DEBUG_ALLOC B3DPrimitiveFace *dbg_b3dAllocFace(B3DFaceAllocList *list); B3DPrimitiveEdge *dbg_b3dAllocEdge(B3DEdgeAllocList *list); int dbg_b3dAllocAttrib(B3DAttrAllocList *attrList, B3DPrimitiveFace *face); void dbg_b3dFreeFace(B3DFaceAllocList *list, B3DPrimitiveFace *face); void dbg_b3dFreeEdge(B3DEdgeAllocList *list, B3DPrimitiveEdge *edge); void dbg_b3dFreeAttrib(B3DAttrAllocList *list, B3DPrimitiveFace *face); #define b3dAllocFace(list, face) face = dbg_b3dAllocFace(list); #define b3dAllocEdge(list, edge) edge = dbg_b3dAllocEdge(list); #define b3dAllocAttrib(attrList, face, result) result = dbg_b3dAllocAttrib(attrList, face); #define b3dFreeFace(list, face) dbg_b3dFreeFace(list, face); #define b3dFreeEdge(list, edge) dbg_b3dFreeEdge(list, edge); #define b3dFreeAttrib(list, face) dbg_b3dFreeAttrib(list, face); #else /* RELEASE */ #define b3dAlloc(list,object) \ {\ if(list->firstFree) { \ object = list->firstFree; \ list->firstFree = object->nextFree; \ object->flags = B3D_ALLOC_FLAG; \ list->nFree--;\ } else { \ if(list->size < list->max) { \ object = list->data + list->size; \ list->size++;\ object->flags = B3D_ALLOC_FLAG;\ list->nFree--;\ } else object = NULL;\ }\ } #define b3dFree(list, object) \ {\ object->flags = 0;\ object->nextFree = list->firstFree; \ list->firstFree = object;\ list->nFree++;\ } #define b3dAllocFace(list, face) b3dAlloc(list,face) #define b3dAllocEdge(list, edge) b3dAlloc(list, edge) #define b3dFreeFace(list, face) b3dFree(list, face) #define b3dFreeEdge(list, edge) b3dFree(list, edge) #define b3dAllocSingleAttr(list,object) \ {\ if(list->firstFree) { \ object = list->firstFree; \ list->firstFree = object->next; \ list->nFree--;\ } else { \ if(list->size < list->max) { \ object = list->data + list->size; \ list->size++;\ list->nFree--;\ } else object = NULL;\ }\ } #define b3dAllocAttrib(attrList,face, result) \ {\ B3DPrimitiveAttribute *firstAttr, *nextAttr;\ int nAttrs = 0;\ \ if(face->flags & B3D_FACE_RGB) nAttrs += 3;\ if(face->flags & B3D_FACE_ALPHA) nAttrs += 1;\ if(face->flags & B3D_FACE_STW) nAttrs += 3;\ firstAttr = nextAttr = NULL;\ while(nAttrs--) {\ b3dAllocSingleAttr(attrList, nextAttr);\ if(!nextAttr) break;\ nextAttr->next = firstAttr;\ firstAttr = nextAttr;\ };\ face->attributes = firstAttr;\ result = nextAttr != NULL;\ } #define b3dFreeAttrib(list, face) \ {\ B3DPrimitiveAttribute *attr, *nextAttr = face->attributes;\ while(nextAttr) {\ attr = nextAttr;\ nextAttr = attr->next;\ attr->next = list->firstFree;\ list->firstFree = attr;\ list->nFree++;\ }\ } #endif #endif /* ifndef B3D_ALLOC_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dDraw.c ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dDraw.c * CONTENT: Pixel drawing functions for the B3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dDraw.c 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: LOTS of stuff missing here... * * - A note on RGBA interpolation: * For low polygon models it makes sense to compute both, the left and * the right attribute value if there might be any overflow at all. * Since we're usually drawing many pixels in a row we can clamp the * left and right value and thus be safe during the interpolation stage. * *****************************************************************************/ #include "b3d.h" #define rasterPosX rasterPos[0] #define rasterPosY rasterPos[1] #define redValue color[RED_INDEX] #define greenValue color[GREEN_INDEX] #define blueValue color[BLUE_INDEX] #define alphaValue color[ALPHA_INDEX] /* The following defines the maximum number of pixels we treat in one loop. This value should be carefully chosen: Setting it high will increase speed for larger polygons but reduce speed for smaller ones. Setting it low will do the opposite. Also, since I'm assuming a smart compiler, the code size will probably increase with this number (if loops are unrolled by the compiler). The current value of 5 should be a good median (32 pixels are processed at most and we'll have the overhead of 5 tests for a one-pixel polygon). */ #define MAX_PIXEL_SHIFT 5 /* USE_MULTBL: Replace up a couple of multiplications by table lookups. On PowerPC, the lookup seems to be slightly slower. On Intel, the lookup is way faster. */ #ifndef USE_MULTBL # ifdef __POWERPC__ # define USE_MULTBL 0 # else # define USE_MULTBL 1 # endif #endif /* Clamp the given value */ #define CLAMP(value, min, max)\ if((value) < (min)) (value) = (min); \ else if((value) > (max)) (value) = (max); /* Clamp a set of fixed point RGB values */ #define CLAMP_RGB(r,g,b) \ CLAMP(r,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf)\ CLAMP(g,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf)\ CLAMP(b,B3D_FixedHalf, (255 << B3D_IntToFixedShift) + B3D_FixedHalf) #ifdef DEBUG_ATTR double attrValueAt(B3DPrimitiveFace *face, B3DPrimitiveAttribute *attr, double xValue, double yValue) { return (attr->value + ((xValue - face->v0->rasterPosX) * attr->dvdx) + ((yValue - face->v0->rasterPosY) * attr->dvdy)); } #else #define attrValueAt(face,attr,xValue,yValue) \ ((attr)->value + \ (((double)(xValue) - (face)->v0->rasterPosX) * (attr)->dvdx) + \ (((double)(yValue) - (face)->v0->rasterPosY) * (attr)->dvdy)) #endif #define SETUP_RGB \ rValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed); \ deltaR = (int) (attr->dvdx * B3D_FloatToFixed); \ attr = attr->next; \ gValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed);\ deltaG = (int) (attr->dvdx * B3D_FloatToFixed); \ attr = attr->next; \ bValue = (int)(attrValueAt(face, attr, floatX, floatY) * B3D_FloatToFixed); \ deltaB = (int) (attr->dvdx * B3D_FloatToFixed); \ attr = attr->next;\ CLAMP_RGB(rValue, gValue, bValue); #define SETUP_STW \ wValue = attrValueAt(face, attr, floatX, floatY); \ wDelta = attr->dvdx; \ attr = attr->next; \ sValue = attrValueAt(face, attr, floatX, floatY); \ sDelta = attr->dvdx; \ attr = attr->next; \ tValue = attrValueAt(face, attr, floatX, floatY); \ tDelta = attr->dvdx; \ attr = attr->next; #define STEP_STW \ sValue += sDelta;\ tValue += tDelta;\ wValue += wDelta; /* Load the four neighbouring texels into tex00, tex01, tex10, and tex11 */ #define LOAD_4_RGB_TEXEL_32(fixedS, fixedT, texture) \ {\ int sIndex, tIndex;\ \ if(texture->sMask) {\ sIndex = (fixedS >> B3D_FixedToIntShift) & texture->sMask;\ } else {\ sIndex = (fixedS >> B3D_FixedToIntShift) % texture->width;\ }\ if(texture->tMask) {\ tIndex = (fixedT >> B3D_FixedToIntShift) & texture->tMask;\ } else {\ tIndex = (fixedT >> B3D_FixedToIntShift) % texture->height;\ }\ /* Load the 4 texels, wrapping if necessary */\ tex00 = (struct b3dPixelColor *) texture->data + (tIndex * texture->width) + sIndex;\ tex01 = tex00 + 1;\ tex10 = tex00 + texture->width;\ tex11 = tex10 + 1;\ if(sIndex+1 == texture->width) {\ tex01 -= texture->width;\ tex11 -= texture->width;\ }\ if(tIndex+1 == texture->height) {\ int tsize = texture->height * texture->width;\ tex10 -= tsize;\ tex11 -= tsize;\ }\ } #if USE_MULTBL /* Use a 16x256 table for lookups */ unsigned short MULTBL[17][256]; static int multblInit = 0; static void MULTBL_Init(void) { int i,j; for(i=0;i<17;i++) for(j=0; j<256; j++) MULTBL[i][j] = (i*j) >> 4; multblInit = 1; } #define INIT_MULTBL { if (!multblInit) MULTBL_Init(); } #define DO_RGB_INTERPOLATION(sf, si, tf, ti) \ tr = (MULTBL[ti][(MULTBL[si][tex00->redValue] + MULTBL[sf][tex01->redValue])] + \ MULTBL[tf][(MULTBL[si][tex10->redValue] + MULTBL[sf][tex11->redValue])]);\ tg = (MULTBL[ti][(MULTBL[si][tex00->greenValue] + MULTBL[sf][tex01->greenValue])] + \ MULTBL[tf][(MULTBL[si][tex10->greenValue] + MULTBL[sf][tex11->greenValue])]);\ tb = (MULTBL[ti][(MULTBL[si][tex00->blueValue] + MULTBL[sf][tex01->blueValue])] + \ MULTBL[tf][(MULTBL[si][tex10->blueValue] + MULTBL[sf][tex11->blueValue])]); #define DO_RGBA_INTERPOLATION(sf, si, tf, ti)\ tr = (MULTBL[ti][(MULTBL[si][tex00->redValue] + MULTBL[sf][tex01->redValue])] + \ MULTBL[tf][(MULTBL[si][tex10->redValue] + MULTBL[sf][tex11->redValue])]);\ tg = (MULTBL[ti][(MULTBL[si][tex00->greenValue] + MULTBL[sf][tex01->greenValue])] + \ MULTBL[tf][(MULTBL[si][tex10->greenValue] + MULTBL[sf][tex11->greenValue])]);\ tb = (MULTBL[ti][(MULTBL[si][tex00->blueValue] + MULTBL[sf][tex01->blueValue])] + \ MULTBL[tf][(MULTBL[si][tex10->blueValue] + MULTBL[sf][tex11->blueValue])]); \ ta = (MULTBL[ti][(MULTBL[si][tex00->alphaValue] + MULTBL[sf][tex01->alphaValue])] + \ MULTBL[tf][(MULTBL[si][tex10->alphaValue] + MULTBL[sf][tex11->alphaValue])]); #else #define INIT_MULTBL #define DO_RGB_INTERPOLATION(sf, si, tf, ti) \ tr = (ti * (si * tex00->redValue + sf * tex01->redValue) +\ tf * (si * tex10->redValue + sf * tex11->redValue)) >> 8;\ tg = (ti * (si * tex00->greenValue + sf * tex01->greenValue) +\ tf * (si * tex10->greenValue + sf * tex11->greenValue)) >> 8;\ tb = (ti * (si * tex00->blueValue + sf * tex01->blueValue) +\ tf * (si * tex10->blueValue + sf * tex11->blueValue)) >> 8;\ #define DO_RGBA_INTERPOLATION(sf, si, tf, ti) \ tr = (ti * (si * tex00->redValue + sf * tex01->redValue) +\ tf * (si * tex10->redValue + sf * tex11->redValue)) >> 8;\ tg = (ti * (si * tex00->greenValue + sf * tex01->greenValue) +\ tf * (si * tex10->greenValue + sf * tex11->greenValue)) >> 8;\ tb = (ti * (si * tex00->blueValue + sf * tex01->blueValue) +\ tf * (si * tex10->blueValue + sf * tex11->blueValue)) >> 8;\ ta = (ti * (si * tex00->alphaValue + sf * tex01->alphaValue) +\ tf * (si * tex10->alphaValue + sf * tex11->alphaValue)) >> 8; #endif /* No MULTBL */ #define INTERPOLATE_RGB_TEXEL(fixedS, fixedT)\ { int sf, si, tf, ti;\ sf = (fixedS >> (B3D_FixedToIntShift - 4)) & 15; si = 16 - sf;\ tf = (fixedT >> (B3D_FixedToIntShift - 4)) & 15; ti = 16 - tf;\ DO_RGB_INTERPOLATION(sf, si, tf, ti)\ } void b3dNoDraw (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawRGB (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawRGBA (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawSTW (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawSTWA (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawSTWRGB (int leftX, int rightX, int yValue, B3DPrimitiveFace *face); void b3dDrawSTWARGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face); b3dPixelDrawer B3D_FILL_FUNCTIONS[B3D_MAX_ATTRIBUTES] = { b3dNoDraw, /* No attributes */ b3dDrawRGB, /* B3D_FACE_RGB */ b3dNoDraw, /* B3D_FACE_ALPHA -- IGNORED!!! */ b3dDrawRGBA, /* B3D_FACE_RGB | B3D_FACE_ALPHA */ b3dDrawSTW, /* B3D_FACE_STW */ b3dDrawSTWRGB, /* B3D_FACE_STW | B3D_FACE_RGB */ b3dDrawSTWA, /* B3D_FACE_STW | B3D_FACE_ALPHA */ b3dDrawSTWARGB /* B3D_FACE_STW | B3D_FACE_RGB | B3D_FACE_ALPHA */ }; void b3dNoDraw(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { if(b3dDebug) b3dAbort("b3dNoDraw called!"); } void b3dDrawRGBFlat(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits; int rValue, gValue, bValue; int deltaR, deltaG, deltaB; { B3DPrimitiveAttribute *attr = face->attributes; /* Ughh ... I'm having a sampling problem somewhere. In theory, the faces should be sampled *exactly* at integer values (the necessary offset should be done before) so that we always sample inside the triangle. For some reason that doesn't quite work yet and that's why here is the strange 0.5 offset and the awful lot of tests. At some time I'll review this but for now I have more important things to do. */ double floatX = leftX; double floatY = yValue+0.5; if(b3dDebug) if(!attr) b3dAbort("face has no RGB attributes"); SETUP_RGB; } bits = (struct b3dPixelColor *) currentState->spanBuffer; pv.redValue = (unsigned char) (rValue >> B3D_FixedToIntShift); pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift); pv.blueValue = (unsigned char) (bValue >> B3D_FixedToIntShift); pv.alphaValue = 255; while(leftX <= rightX) { bits[leftX++] = pv; } } void b3dDrawRGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits; int rValue, gValue, bValue; int deltaR, deltaG, deltaB; int deltaX, pixelShift; { B3DPrimitiveAttribute *attr = face->attributes; /* Ughh ... I'm having a sampling problem somewhere. In theory, the faces should be sampled *exactly* at integer values (the necessary offset should be done before) so that we always sample inside the triangle. For some reason that doesn't quite work yet and that's why here is the strange 0.5 offset and the awful lot of tests. At some time I'll review this but for now I have more important things to do. */ double floatX = leftX; double floatY = yValue+0.5; if(b3dDebug) if(!attr) b3dAbort("face has no RGB attributes"); SETUP_RGB; } bits = (struct b3dPixelColor *) currentState->spanBuffer; pv.alphaValue = 255; /* Reduce the overhead of clamping by precomputing the deltas for each power of two step. A good question here is whether or not it is a good idea to do 2 pixels by this... */ deltaX = rightX - leftX + 1; /* Now do all the powers of two except the last one pixel */ /* Note: A smart compiler (== gcc) should unroll the following loop */ for(pixelShift= MAX_PIXEL_SHIFT; pixelShift> 0; pixelShift--) { int nPixels = 1 << pixelShift; /* Note: The 'if' here is possible since we have dealt with huge polys above */ while(deltaX >= nPixels) { { /* Compute right most values of color interpolation */ int maxR = rValue + (deltaR << pixelShift); int maxG = gValue + (deltaG << pixelShift); int maxB = bValue + (deltaB << pixelShift); /* Clamp those guys */ CLAMP_RGB(maxR, maxG, maxB); /* And compute the actual delta */ deltaR = (maxR - rValue) >> pixelShift; deltaG = (maxG - gValue) >> pixelShift; deltaB = (maxB - bValue) >> pixelShift; } /* Do the inner loop */ { int n = nPixels; while(n--) { pv.redValue = (unsigned char) (rValue >> B3D_FixedToIntShift); pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift); pv.blueValue = (unsigned char) (bValue >> B3D_FixedToIntShift); bits[leftX++] = pv; rValue += deltaR; gValue += deltaG; bValue += deltaB; } } /* Finally, adjust the number of pixels left */ deltaX -= nPixels; } } /* The last pixel is done separately */ if(deltaX) { pv.redValue = (unsigned char) (rValue >> B3D_FixedToIntShift); pv.greenValue = (unsigned char) (gValue >> B3D_FixedToIntShift); pv.blueValue = (unsigned char) (bValue >> B3D_FixedToIntShift); bits[leftX++] = pv; } } void b3dDrawSTWRGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { struct b3dPixelColor { B3DPrimitiveColor color; } pv, *bits, *tex00, *tex10, *tex01, *tex11; double sValue, tValue, wValue, sDelta, tDelta, wDelta, oneOverW; int rValue, gValue, bValue; int deltaR, deltaG, deltaB; int tr, tg, tb, ta; int fixedLeftS, fixedRightS, fixedLeftT, fixedRightT, fixedDeltaS, fixedDeltaT; int deltaX, pixelShift; B3DTexture *texture = face->texture; INIT_MULTBL; if(!texture || 0) { /* If no texture simply draw RGB */ b3dDrawRGB(leftX, rightX, yValue, face); return; } if(texture->depth < 16 && (texture->cmSize < (1 << texture->depth))) return; /* Colormap not installed */ { B3DPrimitiveAttribute *attr = face->attributes; /* See above */ double floatX = leftX; double floatY = yValue+0.5; if(b3dDebug) if(!attr) b3dAbort("face has no RGB attributes"); SETUP_RGB; SETUP_STW; } tr = tg = tb = ta = 255; bits = (struct b3dPixelColor *) currentState->spanBuffer; pv.alphaValue = 255; /* VERY Experimental: Reduce the overhead of clamping as well as division by W by precomputing the deltas for each power of two step */ deltaX = rightX - leftX + 1; if(wValue) oneOverW = 1.0 / wValue; else oneOverW = 0.0; fixedLeftS = (int) (sValue * oneOverW * (texture->width << B3D_IntToFixedShift)); fixedLeftT = (int) (tValue * oneOverW * (texture->height << B3D_IntToFixedShift)); for(pixelShift = MAX_PIXEL_SHIFT; pixelShift > 0; pixelShift--) { int nPixels = 1 << pixelShift; while(deltaX >= nPixels) { { /* Compute right most values of color interpolation */ int maxR = rValue + (deltaR << pixelShift); int maxG = gValue + (deltaG << pixelShift); int maxB = bValue + (deltaB << pixelShift); /* Clamp those guys */ CLAMP_RGB(maxR, maxG, maxB); /* And compute the actual delta */ deltaR = (maxR - rValue) >> pixelShift; deltaG = (maxG - gValue) >> pixelShift; deltaB = (maxB - bValue) >> pixelShift; } /* Compute the RIGHT s/t values (the left ones are kept from the last loop) */ wValue += wDelta * nPixels; sValue += sDelta * nPixels; tValue += tDelta * nPixels; if(wValue) oneOverW = 1.0 / wValue; else oneOverW = 0.0; fixedRightS = (int) (sValue * oneOverW * (texture->width << B3D_IntToFixedShift)); fixedDeltaS = (fixedRightS - fixedLeftS) >> pixelShift; fixedRightT = (int) (tValue * oneOverW * (texture->height << B3D_IntToFixedShift)); fixedDeltaT = (fixedRightT - fixedLeftT) >> pixelShift; /* Do the inner loop */ { int n = nPixels; while(n--) { /* Do the texture load ... hmm ... there should be a way to avoid loading the texture on each pixel... On the other hand, the texture load does not seem too expensive if compared with the texture interpolation. */ LOAD_4_RGB_TEXEL_32(fixedLeftS, fixedLeftT, texture); /* Do the interpolation based on tex00, tex01, tex10, tex11. THIS seems to be one of the real bottlenecks here... */ INTERPOLATE_RGB_TEXEL(fixedLeftS, fixedLeftT); #if USE_MULTBL pv.redValue = (unsigned char) (MULTBL[rValue >> (B3D_FixedToIntShift+4)][tr]); pv.greenValue = (unsigned char) (MULTBL[gValue >> (B3D_FixedToIntShift+4)][tg]); pv.blueValue = (unsigned char) (MULTBL[bValue >> (B3D_FixedToIntShift+4)][tb]); #else pv.redValue = (unsigned char) ((tr * rValue) >> (B3D_FixedToIntShift + 8)); pv.greenValue = (unsigned char) ((tg * gValue) >> (B3D_FixedToIntShift + 8)); pv.blueValue = (unsigned char) ((tb * bValue) >> (B3D_FixedToIntShift + 8)); #endif bits[leftX++] = pv; rValue += deltaR; gValue += deltaG; bValue += deltaB; fixedLeftS += fixedDeltaS; fixedLeftT += fixedDeltaT; } } /* Finally, adjust the number of pixels left and update s/t */ deltaX -= nPixels; fixedLeftS = fixedRightS; fixedLeftT = fixedRightT; } } /* The last pixel is done separately */ if(deltaX) { /* Do the texture load */ LOAD_4_RGB_TEXEL_32(fixedLeftS, fixedLeftT, texture); /* Do the interpolation */ INTERPOLATE_RGB_TEXEL(fixedLeftS, fixedLeftT); #if USE_MULTBL pv.redValue = (unsigned char) (MULTBL[rValue >> (B3D_FixedToIntShift+4)][tr]); pv.greenValue = (unsigned char) (MULTBL[gValue >> (B3D_FixedToIntShift+4)][tg]); pv.blueValue = (unsigned char) (MULTBL[bValue >> (B3D_FixedToIntShift+4)][tb]); #else pv.redValue = (unsigned char) ((tr * rValue) >> (B3D_FixedToIntShift + 8)); pv.greenValue = (unsigned char) ((tg * gValue) >> (B3D_FixedToIntShift + 8)); pv.blueValue = (unsigned char) ((tb * bValue) >> (B3D_FixedToIntShift + 8)); #endif bits[leftX++] = pv; } } void b3dDrawSTWARGB(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { /* not yet implemented */ } void b3dDrawRGBA(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { /* not yet implemented */ } void b3dDrawSTW(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { /* not yet implemented */ } void b3dDrawSTWA(int leftX, int rightX, int yValue, B3DPrimitiveFace *face) { /* not yet implemented */ } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dInit.c ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dInit.c * CONTENT: Initialization functions for the B3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dInit.c 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #include #include #include "b3d.h" #define b3dCompensateWindowPos 1 /* helpers */ #define rasterPosX rasterPos[0] #define rasterPosY rasterPos[1] #define rasterPosZ rasterPos[2] #define rasterPosW rasterPos[3] #define windowPosX windowPos[0] #define windowPosY windowPos[1] #define texCoordS texCoord[0] #define texCoordT texCoord[1] /*************************************************************/ /*************************************************************/ /*************************************************************/ int b3dInitializeEdgeAllocator(void* base, int length) { B3DEdgeAllocList *list = (B3DEdgeAllocList*) base; if(length < sizeof(B3DEdgeAllocList)) return B3D_GENERIC_ERROR; list->magic = B3D_EDGE_ALLOC_MAGIC; list->This = base; list->max = (length - sizeof(B3DEdgeAllocList)) / sizeof(B3DPrimitiveEdge) + 1; list->size = 0; list->nFree = list->max; list->firstFree = NULL; return B3D_NO_ERROR; } int b3dInitializeFaceAllocator(void* base, int length) { B3DFaceAllocList *list = (B3DFaceAllocList*) base; if(length < sizeof(B3DFaceAllocList)) return B3D_GENERIC_ERROR; list->magic = B3D_FACE_ALLOC_MAGIC; list->This = base; list->max = (length - sizeof(B3DFaceAllocList)) / sizeof(B3DPrimitiveFace) + 1; list->size = 0; list->nFree = list->max; list->firstFree = NULL; return B3D_NO_ERROR; } int b3dInitializeAttrAllocator(void* base, int length) { B3DAttrAllocList *list = (B3DAttrAllocList*) base; if(length < sizeof(B3DAttrAllocList)) return B3D_GENERIC_ERROR; list->magic = B3D_ATTR_ALLOC_MAGIC; list->This = base; list->max = (length - sizeof(B3DAttrAllocList)) / sizeof(B3DPrimitiveAttribute) + 1; list->size = 0; list->nFree = list->max; list->firstFree = NULL; return B3D_NO_ERROR; } int b3dInitializeEdgeList(void* base, int length) { B3DPrimitiveEdgeList *list = (B3DPrimitiveEdgeList*) base; if(length < sizeof(B3DPrimitiveEdgeList)) return B3D_GENERIC_ERROR; list->magic = B3D_EDGE_LIST_MAGIC; list->This = base; list->max = (length - sizeof(B3DPrimitiveEdgeList)) / sizeof(B3DPrimitiveEdge*) + 1; list->size = 0; return B3D_NO_ERROR; } int b3dInitializeAET(void* base, int length) { B3DActiveEdgeTable *aet = (B3DActiveEdgeTable *) base; if(length < sizeof(B3DActiveEdgeTable)) return B3D_GENERIC_ERROR; aet->magic = B3D_AET_MAGIC; aet->This = base; aet->max = (length - sizeof(B3DActiveEdgeTable)) / sizeof(B3DPrimitiveEdge*) + 1; aet->size = 0; aet->leftEdge = aet->rightEdge = NULL; aet->lastIntersection = &aet->tempEdge0; aet->nextIntersection = &aet->tempEdge1; return B3D_NO_ERROR; } int b3dInitializeFillList(void* base, int length) { B3DFillList *list = (B3DFillList*) base; if(length < sizeof(B3DFillList)) return B3D_GENERIC_ERROR; list->magic = B3D_FILL_LIST_MAGIC; list->This = base; list->firstFace = list->lastFace = NULL; return B3D_NO_ERROR; } /*************************************************************/ /*************************************************************/ /*************************************************************/ /* b3dMapObjectVertices: Map all the vertices of the given object into the designated viewport. */ void b3dMapObjectVertices(B3DPrimitiveObject *obj, B3DPrimitiveViewport *vp) { double xScale, yScale, xOfs, yOfs; int minX, minY, maxX, maxY; double minZ, maxZ; B3DPrimitiveVertex *vtx; int i; xOfs = (vp->x0 + vp->x1) * 0.5 - 0.5; yOfs = (vp->y0 + vp->y1) * 0.5 - 0.5; xScale = (vp->x1 - vp->x0) * 0.5; yScale = (vp->y1 - vp->y0) * -0.5; minX = minY = maxX = maxY = 0x7FFFFFFF; minZ = maxZ = 0.0; vtx = obj->vertices + 1; for(i=1; i < obj->nVertices; i++, vtx++) { double x,y,z,w; int scaledX, scaledY; w = vtx->rasterPosW; if(w) w = 1.0 / w; x = vtx->rasterPosX * w * xScale + xOfs; y = vtx->rasterPosY * w * yScale + yOfs; z = vtx->rasterPosZ * w; if(!b3dCompensateWindowPos) { vtx->rasterPosX = (float)x; vtx->rasterPosY = (float)y; } vtx->rasterPosZ = (float)z; vtx->rasterPosW = (float)w; scaledX = (int) (x * B3D_FloatToFixed); scaledY = (int) (y * B3D_FloatToFixed); vtx->windowPosX = scaledX; vtx->windowPosY = scaledY; if(b3dCompensateWindowPos) { vtx->rasterPosX = (float) (scaledX * B3D_FixedToFloat); vtx->rasterPosY = (float) (scaledY * B3D_FixedToFloat); } /* Update min/max */ if(i == 1) { minX = maxX = scaledX; minY = maxY = scaledY; minZ = maxZ = z; } else { if(scaledX < minX) minX = scaledX; else if(scaledX > maxX) maxX = scaledX; if(scaledY < minY) minY = scaledY; else if(scaledY > maxY) maxY = scaledY; if(z < minZ) minZ = z; else if(z > maxZ) maxZ = z; } } obj->minX = minX >> B3D_FixedToIntShift; obj->maxX = maxX >> B3D_FixedToIntShift; obj->minY = minY >> B3D_FixedToIntShift; obj->maxY = maxY >> B3D_FixedToIntShift; obj->minZ = (float)minZ; obj->maxZ = (float)maxZ; } /* b3dSetupVertexOrder: Setup the ordering of the vertices in each face so that v0 sorts before v1 sorts before v2. Gather some stats on how much locally sorted and invalid faces the object includes. */ void b3dSetupVertexOrder(B3DPrimitiveObject *obj) { B3DInputFace *face; int i, nSorted, nInvalid; B3DPrimitiveVertex *vtx, *lastTopVtx, *newTopVtx; face = obj->faces; vtx = obj->vertices; nSorted = nInvalid = 0; lastTopVtx = NULL; for(i=0;inFaces; i++,face++) { B3DPrimitiveVertex *vtx0, *vtx1, *vtx2; int idx0, idx1, idx2; idx0 = face->i0; idx1 = face->i1; idx2 = face->i2; if(0 == (idx0 && idx1 && idx2)) { nInvalid++; continue; } vtx0 = vtx + idx0; vtx1 = vtx + idx1; vtx2 = vtx + idx2; if(vtxSortsBefore(vtx0,vtx1)) { if(vtxSortsBefore(vtx1,vtx2)) { face->i0 = idx0; face->i1 = idx1; face->i2 = idx2; } else if(vtxSortsBefore(vtx0,vtx2)) { face->i0 = idx0; face->i1 = idx2; face->i2 = idx1; } else { face->i0 = idx2; face->i1 = idx0; face->i2 = idx1; } } else if(vtxSortsBefore(vtx0, vtx2)) { face->i0 = idx1; face->i1 = idx0; face->i2 = idx2; } else if(vtxSortsBefore(vtx1, vtx2)) { face->i0 = idx1; face->i1 = idx2; face->i2 = idx0; } else { face->i0 = idx2; face->i1 = idx1; face->i2 = idx0; } if(b3dDebug) { vtx0 = vtx + face->i0; vtx1 = vtx + face->i1; vtx2 = vtx + face->i2; if( !vtxSortsBefore(vtx0, vtx1) || !vtxSortsBefore(vtx0, vtx2) || !vtxSortsBefore(vtx1, vtx2)) b3dAbort("Vertex order problem"); } /* Experimental: Try to estimate how many faces are already sorted. */ newTopVtx = vtx + face->i0; if(lastTopVtx) if(vtxSortsBefore(lastTopVtx, newTopVtx)) nSorted++; lastTopVtx = newTopVtx; } obj->nSortedFaces = nSorted; obj->nInvalidFaces = nInvalid; } /*************************************************************/ /*************************************************************/ /*************************************************************/ typedef struct stackEntry { int i, j; } stackEntry; static stackEntry *stack = NULL; static int stackPointer = 0; static int stackSize = 0; #define PUSH(v1, v2) {\ stack[stackPointer].i = v1;\ stack[stackPointer].j = v2;\ stackPointer++;\ } #define POP(v1, v2) { \ stackPointer--; \ v1 = stack[stackPointer].i; \ v2 = stack[stackPointer].j; \ } #define INIT(k) { \ if(stackSize < (k)) { \ stackSize = k; \ if(stack) free(stack); \ stack = calloc(stackSize, sizeof(stackEntry)); \ if(!stack) { \ stackSize = 0; \ return B3D_GENERIC_ERROR; \ }\ } \ stackPointer = 0; \ } /* b3dSortInitialFaces: Sort the faces of the given object according to the given sort order. Note: It is assumed that the vertex order of the faces has been setup before. */ int b3dQuickSortInitialFaces(B3DPrimitiveObject *obj, int i, int j) { B3DInputFace tmp, *faces = obj->faces; int ij, k, l, n; B3DPrimitiveVertex *di, *dj, *dij, *tt, *vtx = obj->vertices; /* Keep us enough headroom */ INIT((j-i)*2); PUSH(i,j); while(stackPointer > 0) { POP(i, j); n = j + 1 - i; if(n <= 1) continue; /* Sort di,dj. */ di = vtx + faces[i].i0; dj = vtx + faces[j].i0; if(!vtxSortsBefore(di,dj)) { tmp = faces[i]; faces[i] = faces[j]; faces[j] = tmp; tt = di; di = dj; dj = tt; } if(n <= 2) continue; /* More than two elements. */ ij = (i+j) >> 1; /* ij is the midpoint of i and j. */ dij = vtx + faces[ij].i0; /* Sort di,dij,dj. Make dij be their median. */ if(vtxSortsBefore(di, dij)) {/* i.e. should di precede dij? */ if(!vtxSortsBefore(dij, dj)) {/* i.e., should dij precede dj?*/ tmp = faces[j]; faces[j] = faces[ij]; faces[ij] = tmp; dij = dj; } } else { /* i.e. di should come after dij */ tmp = faces[i]; faces[i] = faces[ij]; faces[ij] = tmp; dij = di; } if(n <= 3) continue; /* More than three elements. Find k>i and l 0) { POP(i, j); n = j + 1 - i; if(n <= 1) continue; /* Sort di,dj. */ di = array[i]; dj = array[j]; if(!objSortsBefore(di,dj)) { tmp = array[i]; array[i] = array[j]; array[j] = tmp; tmp = di; di = dj; dj = tmp; } if(n <= 2) continue; /* More than two elements. */ ij = (i+j) >> 1; /* ij is the midpoint of i and j. */ dij = array[ij]; /* Sort di,dij,dj. Make dij be their median. */ if(objSortsBefore(di, dij)) {/* i.e. should di precede dij? */ if(!objSortsBefore(dij, dj)) {/* i.e., should dij precede dj?*/ tmp = array[j]; array[j] = array[ij]; array[ij] = tmp; dij = dj; } } else { /* i.e. di should come after dij */ tmp = array[i]; array[i] = array[ij]; array[ij] = tmp; dij = di; } if(n <= 3) continue; /* More than three elements. Find k>i and lfaces; nextFace = face + 1; for(i=1; i < obj->nFaces; i++, face++, nextFace++) { if(!vtxSortsBefore(obj->vertices + face->i0, obj->vertices + nextFace->i0)) b3dAbort("Face sorting problem"); } } #define InitObject(obj, objBase, objFlags, textureIndex) \ obj = (B3DPrimitiveObject*) objBase; \ obj->magic = B3D_PRIMITIVE_OBJECT_MAGIC; \ obj->This = objBase; \ obj->start = 0; \ obj->next = NULL; \ obj->flags = objFlags; \ obj->textureIndex = textureIndex; \ obj->texture = NULL; #define InitVertex(vtx) \ (vtx)->rasterPosX = \ (vtx)->rasterPosY = \ (vtx)->rasterPosZ = \ (vtx)->rasterPosW = \ (vtx)->texCoordS = \ (vtx)->texCoordT = (float) 0.0;\ (vtx)->windowPosX = \ (vtx)->windowPosY = 0x7FFFFFFF; \ (vtx)->cc.pixelValue32 = 0; /* b3dAddIndexedTriangleObject: Create a new primitive object. */ int b3dAddIndexedTriangleObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DInputFace *facePtr, int nFaces, B3DPrimitiveViewport *vp) { B3DPrimitiveObject *obj; int sizeNeeded; sizeNeeded = sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex) * (nVertices+1) + sizeof(B3DInputFace) * nFaces; if(!objBase || objLength < sizeNeeded) return B3D_GENERIC_ERROR; InitObject(obj, objBase, objFlags, textureIndex); /* copy in the primitive vertices (starting immediately after the prim object) */ obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */ obj->vertices = (B3DPrimitiveVertex*) (obj + 1); memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex)); /* copy in the input faces (starting after the vertices) */ obj->nFaces = nFaces; obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices); memcpy(obj->faces, facePtr, nFaces * sizeof(B3DInputFace)); /* Initialize the first vertex with something useful */ InitVertex(obj->vertices); b3dMapObjectVertices(obj, vp); b3dSetupVertexOrder(obj); if(b3dQuickSortInitialFaces(obj,0,obj->nFaces-1) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; if(b3dDebug) b3dValidateObjectFaces(obj); return B3D_NO_ERROR; } /* b3dAddIndexedQuadObject: Create a new primitive object. */ int b3dAddIndexedQuadObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DInputQuad *quadPtr, int nQuads, B3DPrimitiveViewport *vp) { B3DPrimitiveObject *obj; int sizeNeeded; sizeNeeded = sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex) * (nVertices+1) + sizeof(B3DInputFace) * nQuads * 2; if(!objBase || objLength < sizeNeeded) return B3D_GENERIC_ERROR; InitObject(obj, objBase, objFlags, textureIndex); /* copy in the primitive vertices (starting immediately after the prim object) */ obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */ obj->vertices = (B3DPrimitiveVertex*) (obj + 1); memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex)); /* copy in the input faces (starting after the vertices) */ obj->nFaces = nQuads * 2; obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices); { int i, nFaces = obj->nFaces; B3DInputQuad *src = quadPtr; B3DInputFace *dst = obj->faces; for(i=0; i < nQuads; i++, src++) { dst->i0 = src->i0; dst->i1 = src->i1; dst->i2 = src->i2; dst++; dst->i0 = src->i2; dst->i1 = src->i3; dst->i2 = src->i0; dst++; } } /* Initialize the first vertex with something useful */ InitVertex(obj->vertices); b3dMapObjectVertices(obj, vp); b3dSetupVertexOrder(obj); if(b3dQuickSortInitialFaces(obj,0,obj->nFaces-1) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; if(b3dDebug) b3dValidateObjectFaces(obj); return B3D_NO_ERROR; } /* b3dAddPolygonObject: Create a new primitive object. */ int b3dAddPolygonObject(void *objBase, int objLength, int objFlags, int textureIndex, B3DPrimitiveVertex *vtxPointer, int nVertices, B3DPrimitiveViewport *vp) { B3DPrimitiveObject *obj; int sizeNeeded; sizeNeeded = sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex) * (nVertices+1) + sizeof(B3DInputFace) * (nVertices - 2); if(!objBase || objLength < sizeNeeded) return B3D_GENERIC_ERROR; InitObject(obj, objBase, objFlags, textureIndex); /* copy in the primitive vertices (starting immediately after the prim object) */ obj->nVertices = nVertices+1; /* For one-based indexing leave one more entry */ obj->vertices = (B3DPrimitiveVertex*) (obj + 1); memcpy(obj->vertices+1, vtxPointer, nVertices * sizeof(B3DPrimitiveVertex)); /* copy in the input faces (starting after the vertices) */ obj->nFaces = nVertices - 2; obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices); { B3DInputFace *dst = obj->faces; int i, nFaces = obj->nFaces; for(i=0; i < nFaces; i++, dst++) { dst->i0 = 1; dst->i1 = 2+i; dst->i2 = 3+i; } } /* Initialize the first vertex with something useful */ InitVertex(obj->vertices); b3dMapObjectVertices(obj, vp); b3dSetupVertexOrder(obj); if(b3dQuickSortInitialFaces(obj,0,obj->nFaces-1) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; if(b3dDebug) b3dValidateObjectFaces(obj); return B3D_NO_ERROR; } /*************************************************************/ /*************************************************************/ /*************************************************************/ int b3dLoadTexture(B3DTexture *texture, int width, int height, int depth, unsigned int *bits, int cmSize, unsigned int *colormap) { int nBits; if(width < 1 || height < 1) return B3D_GENERIC_ERROR; if(depth != 32) return B3D_GENERIC_ERROR; if(depth != 8 && depth != 16 && depth != 32) return B3D_GENERIC_ERROR; if(depth == 8 && cmSize < 256) return B3D_GENERIC_ERROR; texture->width = width; texture->height = height; texture->depth = depth; texture->data = bits; texture->cmSize = cmSize; texture->colormap = colormap; texture->rowLength = width; nBits = 1; while((1 << nBits) < width) nBits++; if((1<sMask = (1<sShift = nBits; } else { texture->sMask = texture->sShift = 0; } while((1 << nBits) < height) nBits++; if((1<tMask = (1<tShift = nBits; } else { texture->tMask = texture->tShift = 0; } return B3D_NO_ERROR; } /*************************************************************/ /*************************************************************/ /*************************************************************/ /* b3dSetupObjects: Sort the objects and create a linked list between the objects. */ int b3dSetupObjects(B3DRasterizerState *state) { int i, textureIndex, nTextures = state->nTextures, nObjects = state->nObjects; B3DPrimitiveObject *obj, **objects = state->objects; B3DTexture *textures = state->textures; if(b3dQuickSortObjects(objects, 0, nObjects-1) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; for(i=0; iflags &= ~(B3D_OBJECT_ACTIVE | B3D_OBJECT_DONE); obj->start = 0; /*-- Note: The following is important --*/ obj->nFaces -= obj->nInvalidFaces; obj->nInvalidFaces = 0; if(!obj->nFaces) break; /*-- End --*/ textureIndex = obj->textureIndex - 1; if(textureIndex >= 0 && textureIndex < nTextures) { obj->texture = textures + textureIndex; obj->flags |= B3D_FACE_STW; } else obj->texture = NULL; obj->next = NULL; if(i) { objects[i-1]->next = obj; obj->prev = objects[i-1]; } } return B3D_NO_ERROR; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dMain.c ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dMain.c * CONTENT: Main rasterizer body * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dMain.c 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #include /* printf() */ #include /* exit() */ #include /* assert() */ #include "b3d.h" #ifndef NULL #define NULL ((void*)0) #endif #ifdef B3D_PROFILE unsigned int b3dObjSetupTime; unsigned int b3dMapObjectTime; unsigned int b3dVertexOrderTime; unsigned int b3dSortFaceTime; #endif /* helpers */ #define rasterPosX rasterPos[0] #define rasterPosY rasterPos[1] #define rasterPosZ rasterPos[2] #define rasterPosW rasterPos[3] #define windowPosX windowPos[0] #define windowPosY windowPos[1] #define texCoordS texCoord[0] #define texCoordT texCoord[1] #define redValue cc.color[RED_INDEX] #define greenValue cc.color[GREEN_INDEX] #define blueValue cc.color[BLUE_INDEX] #define alphaValue cc.color[ALPHA_INDEX] /* globals */ B3DRasterizerState *currentState; B3DActiveEdgeTable *aet; B3DPrimitiveEdgeList *addedEdges; B3DEdgeAllocList *edgeAlloc; B3DFaceAllocList *faceAlloc; B3DAttrAllocList *attrAlloc; int nFaces = 0; int maxFaces = 0; int maxEdges = 0; /*************************************************************/ /*************************************************************/ /*************************************************************/ void b3dAbort(char *msg){ printf(msg); exit(-1); } void b3dValidateEdgeOrder(B3DPrimitiveEdgeList *list) { int i; if(list->size) if(list->data[0]->leftFace == list->data[0]->rightFace) { b3dAbort("Left face == right face"); } for(i=1; isize; i++) { if(list->data[i-1]->xValue > list->data[i]->xValue) { b3dAbort("Edge list is broken"); } if(list->data[i]->leftFace == list->data[i]->rightFace) { b3dAbort("Left face == right face"); } } } void b3dValidateAETOrder(B3DActiveEdgeTable *list) { int i; if(list->size) if(list->data[0]->leftFace == list->data[0]->rightFace) { b3dAbort("Left face == right face"); } for(i=1; isize; i++) { if(list->data[i-1]->xValue > list->data[i]->xValue) { b3dAbort("Edge list is broken"); } if(list->data[i]->leftFace == list->data[i]->rightFace) { b3dAbort("Left face == right face"); } } } /*************************************************************/ /*************************************************************/ /*************************************************************/ /* b3dInitializeFace: Allocate a new primitive face based on the given vertices. Do the necessary initial setup, but don't set up any drawing attributes yet. Return the newly created face. NOTE: May cause allocation of one face! */ B3DPrimitiveFace *b3dInitializeFace(B3DPrimitiveVertex *v0, B3DPrimitiveVertex *v1, B3DPrimitiveVertex *v2, B3DTexture *texture, int attrFlags) { B3DPrimitiveFace *face; /* Compute major and minor reference edges */ { float majorDx = v2->rasterPosX - v0->rasterPosX; float majorDy = v2->rasterPosY - v0->rasterPosY; float minorDx = v1->rasterPosX - v0->rasterPosX; float minorDy = v1->rasterPosY - v0->rasterPosY; float area = (majorDx * minorDy) - (minorDx * majorDy); if(area > -0.001 && area < 0.001) return NULL; /* Now that we know the face is valid, do the actual allocation */ b3dAllocFace(faceAlloc, face); if(b3dDebug) if(!face) b3dAbort("Face allocation failed"); face->v0 = v0; face->v1 = v1; face->v2 = v2; face->leftEdge = NULL; face->rightEdge = NULL; face->attributes = NULL; face->oneOverArea = (float) (1.0 / area); face->majorDx = majorDx; face->majorDy = majorDy; face->minorDx = minorDx; face->minorDy = minorDy; face->texture = texture; face->flags |= attrFlags & (B3D_ATTR_MASK << B3D_ATTR_SHIFT); { /* Compute dzdx and dzdy */ float majorDz = v2->rasterPosZ - v0->rasterPosZ; float minorDz = v1->rasterPosZ - v0->rasterPosZ; face->dzdx = face->oneOverArea * ((majorDz * minorDy) - (minorDz * majorDy)); face->dzdy = face->oneOverArea * ((majorDx * minorDz) - (minorDx * majorDz)); } } {/* Compute minZ/maxZ */ float z0 = v0->rasterPosZ; float z1 = v1->rasterPosZ; float z2 = v2->rasterPosZ; if(z0 <= z1) { if(z1 <= z2) { face->minZ = z0; face->maxZ = z2; } else if(z0 <= z2) { face->minZ = z0; face->maxZ = z1; } else { face->minZ = z2; face->maxZ = z1; } } else if(z2 <= z1) { face->minZ = z2; face->maxZ = z0; } else if(z0 <= z2) { face->minZ = z1; face->maxZ = z0; } else { face->minZ = z1; face->maxZ = z0; } } /* End of minZ/maxZ */ return face; } /* b3dInitializePass2: Do a second initialization pass if the face is known to be visible. */ int b3dInitializePass2(B3DPrimitiveFace *face) { double majorDv, minorDv, baseValue; double dvdx, dvdy; B3DPrimitiveAttribute *attr; B3DPrimitiveVertex *v0 = face->v0; B3DPrimitiveVertex *v1 = face->v1; B3DPrimitiveVertex *v2 = face->v2; { int ok; b3dAllocAttrib(attrAlloc, face, ok); if(!ok) return 0; /* NOT initalized */ } attr = face->attributes; assert(attr); if(face->flags & B3D_FACE_RGB) { /* Setup RGB interpolation */ majorDv = v2->redValue - v0->redValue; minorDv = v1->redValue - v0->redValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) v0->redValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; majorDv = v2->greenValue - v0->greenValue; minorDv = v1->greenValue - v0->greenValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) v0->greenValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; majorDv = v2->blueValue - v0->blueValue; minorDv = v1->blueValue - v0->blueValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) v0->blueValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; } if(face->flags & B3D_FACE_ALPHA) { /* Setup alpha interpolation */ majorDv = v2->alphaValue - v0->alphaValue; minorDv = v1->alphaValue - v0->alphaValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) v0->alphaValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; } if(face->flags & B3D_FACE_STW) { /* Setup texture coordinate interpolation */ double w0 = v0->rasterPosW; double w1 = v1->rasterPosW; double w2 = v2->rasterPosW; majorDv = w2 - w0; minorDv = w1 - w0; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) w0; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; baseValue = v0->texCoordS * w0; majorDv = (v2->texCoordS * w2) - baseValue; minorDv = (v1->texCoordS * w1) - baseValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) baseValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; baseValue = v0->texCoordT * w0; majorDv = (v2->texCoordT * w2) - baseValue; minorDv = (v1->texCoordT * w1) - baseValue; dvdx = face->oneOverArea * ((majorDv * face->minorDy) - (minorDv * face->majorDy)); dvdy = face->oneOverArea * ((minorDv * face->majorDx) - (majorDv * face->minorDx)); attr->value = (float) baseValue; attr->dvdx = (float) dvdx; attr->dvdy = (float) dvdy; attr = attr->next; } face->flags |= B3D_FACE_INITIALIZED; return 1; } /* b3dInitializeEdge: Initialize the incremental values of the given edge. */ /* INLINE b3dInitializeEdge(edge) */ void b3dInitializeEdge(B3DPrimitiveEdge *edge) { assert(edge); assert(edge->nLines); edge->xValue = edge->v0->windowPosX; edge->zValue = edge->v0->rasterPosZ; if(edge->nLines > 1) { edge->xIncrement = (edge->v1->windowPosX - edge->v0->windowPosX) / edge->nLines; edge->zIncrement = (edge->v1->rasterPosZ - edge->v0->rasterPosZ) / (float) edge->nLines; } else { edge->xIncrement = (edge->v1->windowPosX - edge->v0->windowPosX); edge->zIncrement = (edge->v1->rasterPosZ - edge->v0->rasterPosZ); } } /* --INLINE-- */ /*************************************************************/ /*************************************************************/ /*************************************************************/ /* b3dFirstIndexForInserting: Return the first possible index for inserting an edge with the given x value. */ int b3dFirstIndexForInserting(B3DPrimitiveEdgeList *list, int xValue) { int low, high, index; low = 0; high = list->size-1; while(low <= high) { index = (low + high) >> 1; if(list->data[index]->xValue <= xValue) low = index+1; else high = index-1; } index = low; while(index > 0 && (list->data[index-1]->xValue) == xValue) index--; return index; } /* b3dAddEdgeBeforeIndex: Insert the edge to the list before the given index. */ /* INLINE b3dAddEdgeBeforeIndex(list, edge, index) */ void b3dAddEdgeBeforeIndex(B3DPrimitiveEdgeList *list, B3DPrimitiveEdge *edge, int index) { int i; if(b3dDebug) if(list->size == list->max) b3dAbort("No more space for adding edges"); assert( (list->size == index) || (list->data[index]->xValue >= edge->xValue)); for(i=list->size-1; i >= index; i--) list->data[i+1] = list->data[i]; list->data[index] = edge; list->size++; } /* --INLINE-- */ /* b3d2AddEdgesBeforeIndex: Insert the two edge to the list before the given index. */ /* INLINE b3dAdd2EdgesBeforeIndex(list, edge1, edge2, index) */ void b3dAdd2EdgesBeforeIndex(B3DPrimitiveEdgeList *list, B3DPrimitiveEdge *edge1, B3DPrimitiveEdge *edge2, int index) { int i; if(b3dDebug) if(list->size+1 >= list->max) b3dAbort("No more space for adding edges"); assert( edge1->xValue == edge2->xValue); assert( (list->size == index) || (list->data[index]->xValue >= edge1->xValue)); for(i=list->size-1; i >= index; i--) list->data[i+2] = list->data[i]; list->data[index] = edge1; list->data[index+1] = edge2; list->size += 2; } /* --INLINE-- */ /* b3dAdjustFaceEdges: Assign left and right edges to the given face. */ /* INLINE b3dAdjustFaceEdges(face, edge1, edge2) */ void b3dAdjustFaceEdges(B3DPrimitiveFace *face, B3DPrimitiveEdge *edge1, B3DPrimitiveEdge *edge2) { assert(face); assert(edge1); assert(edge2); if(edge1->xValue == edge2->xValue) { if(edge1->xIncrement <= edge2->xIncrement) { face->leftEdge = edge1; face->rightEdge = edge2; } else { face->leftEdge = edge2; face->rightEdge = edge1; } } else { if(edge1->xValue <= edge2->xValue) { face->leftEdge = edge1; face->rightEdge = edge2; } else { face->leftEdge = edge2; face->rightEdge = edge1; } } } /* --INLINE-- */ /* b3dAddLowerEdgeFromFace: Add a new lower edge from the given face. NOTE: oldEdge may be NULL! NOTE: May cause allocation of one edge! */ B3DPrimitiveEdge *b3dAddLowerEdgeFromFace(B3DPrimitiveFace *face, B3DPrimitiveEdge *oldEdge) { B3DPrimitiveVertex *v0 = face->v0; B3DPrimitiveVertex *v1 = face->v1; B3DPrimitiveVertex *v2 = face->v2; int xValue = v1->windowPosX; int index; /* Search the list of added edges to merge the edges from the face */ index = b3dFirstIndexForInserting(addedEdges, xValue); for(;indexsize; index++) { B3DPrimitiveEdge *edge = addedEdges->data[index]; if(edge->xValue != xValue) break; if(edge->rightFace) continue; if((edge->v0 == v1 && edge->v1 == v2) || /* The simple test*/ /* The complex test */ (edge->v0->windowPosX == v1->windowPosX && edge->v0->windowPosY == v1->windowPosY && edge->v0->rasterPosZ == v1->rasterPosZ && edge->v1->windowPosX == v2->windowPosX && edge->v1->windowPosY == v2->windowPosY && edge->v1->rasterPosZ == v2->rasterPosZ)) { /* Found the edge */ if(face->leftEdge == oldEdge) face->leftEdge = edge; else face->rightEdge = edge; edge->rightFace = face; return edge; } } /* Need to create a new edge. NOTE: Index already points to the right insertion point. */ { B3DPrimitiveEdge *minorEdge; int nLines = (v2->windowPosY >> B3D_FixedToIntShift) - (v1->windowPosY >> B3D_FixedToIntShift); if(!nLines) return NULL; /* Edge is horizontal */ b3dAllocEdge(edgeAlloc, minorEdge); if(b3dDebug) if(!minorEdge) b3dAbort("Edge allocation failed"); minorEdge->v0 = v1; minorEdge->v1 = v2; minorEdge->nLines = nLines; minorEdge->leftFace = face; minorEdge->rightFace = NULL; if(face->leftEdge == oldEdge) face->leftEdge = minorEdge; else face->rightEdge = minorEdge; b3dInitializeEdge(minorEdge); b3dAddEdgeBeforeIndex(addedEdges, minorEdge, index); return minorEdge; } /* NOT REACHED */ } /* b3dAddEdgesFromFace: Add the two new edges from the given primitive face. NOTE: May cause allocation of two edges (but not three)! */ void b3dAddEdgesFromFace(B3DPrimitiveFace *face, int yValue) { int needMajor = 1; int needMinor = 1; B3DPrimitiveEdge *majorEdge = NULL; B3DPrimitiveEdge *minorEdge = NULL; B3DPrimitiveVertex *v0 = face->v0; B3DPrimitiveVertex *v1 = face->v1; B3DPrimitiveVertex *v2 = face->v2; int xValue = v0->windowPosX; int index; /* Search the list of added edges to merge the edges from the face */ index = b3dFirstIndexForInserting(addedEdges, xValue); for(;indexsize; index++) { B3DPrimitiveEdge *edge = addedEdges->data[index]; if(edge->xValue != xValue) break; if(edge->rightFace) continue; if(edge->v0 != v0 && (edge->v0->windowPosY != v0->windowPosY || edge->v0->rasterPosZ != v0->rasterPosZ)) continue; /* If we come to this point the edge might be usable for merging the face */ if(needMajor && /* Test only if major edge is needed */ (edge->v1 == v2 || /* Simple test */ /* A more complex test */ (edge->v1->windowPosX == v2->windowPosX && edge->v1->windowPosY == v2->windowPosY && edge->v1->rasterPosZ == v2->rasterPosZ))) { /* Yepp. That's the new major */ majorEdge = edge; majorEdge->rightFace = face; majorEdge->flags |= B3D_EDGE_RIGHT_MAJOR; if(b3dDoStats) nFaces++; if(!needMinor) { b3dAdjustFaceEdges(face, majorEdge, minorEdge); return; /* done */ } needMajor = 0; } else if(needMinor && /* Test only if minor edge is needed */ (edge->v1 == v1 || /* Simple test */ /* A more complex test */ (edge->v1->windowPosX == v1->windowPosX && edge->v1->windowPosY == v1->windowPosY && edge->v1->rasterPosZ == v1->rasterPosZ))) { /* Yepp. That's the new minor */ minorEdge = edge; minorEdge->rightFace = face; minorEdge->flags |= B3D_EDGE_CONTINUE_RIGHT; if(!needMajor) { b3dAdjustFaceEdges(face, majorEdge, minorEdge); return; /* done */ } needMinor = 0; } } /* Need to create new edges. Note: index already points to the right insertion point in addedEdges */ if(needMajor) { int nLines = (v2->windowPosY >> B3D_FixedToIntShift) - (v0->windowPosY >> B3D_FixedToIntShift); if(!nLines) { /* The major edge is horizontal. */ b3dFreeFace(faceAlloc, face); return; } b3dAllocEdge(edgeAlloc, majorEdge); if(b3dDebug) if(!majorEdge) b3dAbort("Edge allocation failed"); majorEdge->v0 = v0; majorEdge->v1 = v2; majorEdge->nLines = nLines; majorEdge->leftFace = face; majorEdge->rightFace = NULL; majorEdge->flags |= B3D_EDGE_LEFT_MAJOR; b3dInitializeEdge(majorEdge); if(b3dDoStats) nFaces++; } if(needMinor) { int nLines = (v1->windowPosY >> B3D_FixedToIntShift) - (v0->windowPosY >> B3D_FixedToIntShift); if(!nLines) { /* Note: If the (upper) minor edge is horizontal, use the lower one. Note: The lower edge cannot be horizontal if the major edge isn't */ if(needMajor) { b3dAddEdgeBeforeIndex(addedEdges, majorEdge, index); } minorEdge = b3dAddLowerEdgeFromFace(face,NULL); if(b3dDebug) if(!minorEdge || minorEdge->nLines == 0) b3dAbort("minor edge is horizontal"); b3dAdjustFaceEdges(face, majorEdge, minorEdge); return; } b3dAllocEdge(edgeAlloc, minorEdge); if(b3dDebug) if(!minorEdge) b3dAbort("Edge allocation failed"); minorEdge->v0 = v0; minorEdge->v1 = v1; minorEdge->nLines = nLines; minorEdge->leftFace = face; minorEdge->rightFace = NULL; minorEdge->flags |= B3D_EDGE_CONTINUE_LEFT; b3dInitializeEdge(minorEdge); } /* Add the newly created edges to addedEdges */ if(needMinor && needMajor) { b3dAdd2EdgesBeforeIndex(addedEdges, majorEdge, minorEdge, index); } else if(needMajor) { b3dAddEdgeBeforeIndex(addedEdges, majorEdge, index); } else { b3dAddEdgeBeforeIndex(addedEdges, minorEdge, index); } b3dAdjustFaceEdges(face, majorEdge, minorEdge); } /* b3dRemoveAETEdge: Remove the given edge from the AET. NOTE: May cause allocation of two edges! */ /* INLINE b3dRemoveAETEdge(aet, edge, yValue, aetPos) */ void b3dRemoveAETEdge(B3DActiveEdgeTable *aet, B3DPrimitiveEdge *edge, int yValue, int aetPos) { /* Remove edge and add lower edges if necessary */ int j; B3DPrimitiveEdge **aetData = aet->data; assert(aetData[aetPos] == edge); if(b3dDebug) if( (edge->v1->windowPosY >> B3D_FixedToIntShift) != yValue ) b3dAbort("Edge exceeds range"); /* Remove the edge and adjust the stuff */ for(j=aetPos+1; j < aet->size; j++) aetData[j-1] = aetData[j]; aet->size--; /* Add new lower edges */ if(edge->flags & B3D_EDGE_CONTINUE_LEFT) { b3dAddLowerEdgeFromFace(edge->leftFace, edge); } if(edge->flags & B3D_EDGE_CONTINUE_RIGHT) { b3dAddLowerEdgeFromFace(edge->rightFace, edge); } if(edge->flags & B3D_EDGE_LEFT_MAJOR) { /* Free left face */ b3dFreeAttrib(attrAlloc, edge->leftFace); b3dFreeFace(faceAlloc, edge->leftFace); if(b3dDoStats) nFaces--; } if(edge->flags & B3D_EDGE_RIGHT_MAJOR) { /* Free right face */ b3dFreeAttrib(attrAlloc, edge->rightFace); b3dFreeFace(faceAlloc, edge->rightFace); if(b3dDoStats) nFaces--; } /* And free old edge */ b3dFreeEdge(edgeAlloc, edge); } /* --INLINE-- */ /* b3dMergeAETEdgesFrom: Merge the edges from the given source into the AET. */ void b3dMergeAETEdgesFrom(B3DActiveEdgeTable *aet, B3DPrimitiveEdgeList *src) { int srcIndex, aetIndex, outIndex, i; B3DPrimitiveEdge *srcEdge, *aetEdge; assert(aet); assert(src); assert(src->size); assert(aet->size + src->size <= aet->max); if(!aet->size) { for(i=0; isize; i++) aet->data[i] = src->data[i]; aet->size += src->size; return; } /* Merge the input by stepping backwards through the aet and checking each edge */ outIndex = aet->size + src->size - 1; srcIndex = src->size-1; aetIndex = aet->size-1; srcEdge = src->data[srcIndex]; aetEdge = aet->data[aetIndex]; aet->size += src->size; while(1) { if(srcEdge->xValue >= aetEdge->xValue) { /* output srcEdge */ aet->data[outIndex--] = srcEdge; if(!srcIndex--) return; srcEdge = src->data[srcIndex]; } else { /* output aetEdge */ aet->data[outIndex--] = aetEdge; if(!aetIndex--) { for(i=0; i <= srcIndex; i++) aet->data[i] = src->data[i]; return; } aetEdge = aet->data[aetIndex]; } } } /* INLINE b3dAdvanceAETEdge(edge, aetData, aetStart) */ void b3dAdvanceAETEdge(B3DPrimitiveEdge *edge, B3DPrimitiveEdge **aetData, int aetStart) { /* Advance to next scan line */ edge->zValue += edge->zIncrement; edge->xValue += edge->xIncrement; /* Check if AET sort order is okay */ if(aetStart && aetData[aetStart-1]->xValue > edge->xValue) { /* Must resort rightEdge */ int xValue = edge->xValue; int j = aetStart; /* Move the edge left */ while(j>0 && aetData[j-1]->xValue > xValue) { aetData[j] = aetData[j-1]; j--; } aetData[j] = edge; } } /* --INLINE-- */ /*************************************************************/ /*************************************************************/ /*************************************************************/ #ifdef DEBUG double zValueAt(B3DPrimitiveFace *face, double xValue, double yValue) { return (face->v0->rasterPosZ + (((double)xValue - face->v0->rasterPosX) * face->dzdx) + (((double)yValue - face->v0->rasterPosY) * face->dzdy)); } #else #define zValueAt(face, xValue, yValue) \ ((face)->v0->rasterPosZ + \ (((double)(xValue) - (face)->v0->rasterPosX) * (face)->dzdx) +\ (((double)(yValue) - (face)->v0->rasterPosY) * (face)->dzdy)) #endif /*************************************************************/ /*************************************************************/ /*************************************************************/ int b3dComputeIntersection(B3DPrimitiveFace *frontFace, B3DPrimitiveFace *backFace, int yValue, int errorValue) { double dx1 = frontFace->rightEdge->xValue - frontFace->leftEdge->xValue; double dz1 = frontFace->rightEdge->zValue - frontFace->leftEdge->zValue; double dx2 = backFace->rightEdge->xValue - backFace->leftEdge->xValue; double dz2 = backFace->rightEdge->zValue - backFace->leftEdge->zValue; double px = backFace->leftEdge->xValue - frontFace->leftEdge->xValue; double pz = backFace->leftEdge->zValue - frontFace->leftEdge->zValue; double det = (dx1 * dz2) - (dx2 * dz1); if(det == 0.0) return errorValue; { double det2 = ((px * dz2) - (pz * dx2)) / det; return frontFace->leftEdge->xValue + (int)(dx1 * det2); } /* not reached */ } /* b3dCheckIntersectionOfFaces: Compute the possible intersection of frontFace and backFace. Store the result in nextIntersection if it is before any other intersection. Return true if other intersections tests should be performed, false otherwise. */ int b3dCheckIntersectionOfFaces(B3DPrimitiveFace *frontFace, B3DPrimitiveFace *backFace, int yValue, B3DPrimitiveEdge *leftEdge, B3DPrimitiveEdge *nextIntersection) { double frontZ, backZ; int xValue, rightX; /* Check if the backFace is completely behind the front face */ if(backFace->minZ >= frontFace->maxZ) return 0; /* abort */ /* Check if front and back face share any edges */ if(frontFace->leftEdge == backFace->leftEdge) return 1; /* proceed */ if(frontFace->rightEdge == backFace->rightEdge) return 1; /* proceed */ /* Check if either front or back face are less than 1 pixel wide */ if( (frontFace->leftEdge->xValue >> B3D_FixedToIntShift) == (frontFace->rightEdge->xValue >> B3D_FixedToIntShift)) return 0; /* abort */ if( (backFace->leftEdge->xValue >> B3D_FixedToIntShift) == (backFace->rightEdge->xValue >> B3D_FixedToIntShift)) return 1; /* proceed */ /* Choose the right x value of either front or back face, whichever is less (this is so we sample inside both faces) */ if(frontFace->rightEdge->xValue <= backFace->rightEdge->xValue) { rightX = frontFace->rightEdge->xValue; frontZ = frontFace->rightEdge->zValue; backZ = zValueAt(backFace, rightX * B3D_FixedToFloat, yValue); } else { rightX = backFace->rightEdge->xValue; backZ = backFace->rightEdge->zValue; frontZ = zValueAt(frontFace, rightX * B3D_FixedToFloat, yValue); } if(backZ < frontZ) { /* possible intersection found */ xValue = b3dComputeIntersection(frontFace, backFace, yValue, leftEdge->xValue); if(xValue > rightX) xValue = rightX; /* Ignore intersections at or before the leftEdge's x value. Important. */ if((xValue >> B3D_FixedToIntShift) <= (leftEdge->xValue >> B3D_FixedToIntShift)) xValue = ((leftEdge->xValue >> B3D_FixedToIntShift) + 1) << B3D_IntToFixedShift; if(xValue < nextIntersection->xValue) { nextIntersection->xValue = xValue; nextIntersection->leftFace = frontFace; nextIntersection->rightFace = backFace; } } return 1; } /* b3dAdjustIntersections: Compute the possible intersections of the current front face with all active faces. Store the next intersection if any. */ /* INLINE b3dAdjustIntersections(fillList, yValue, topEdge, nextIntersection) */ void b3dAdjustIntersections(B3DFillList *fillList, int yValue, B3DPrimitiveEdge *topEdge, B3DPrimitiveEdge *nextIntersection) { B3DPrimitiveFace *frontFace = fillList->firstFace; if(frontFace) { B3DPrimitiveFace *backFace = frontFace->nextFace; int proceed = 1; while(backFace && proceed) { proceed = b3dCheckIntersectionOfFaces(frontFace, backFace, yValue, topEdge, nextIntersection); backFace = backFace->nextFace; } } } /* --INLINE-- */ /*************************************************************/ /*************************************************************/ /*************************************************************/ void b3dValidateFillList(B3DFillList *list) { B3DPrimitiveFace *firstFace = list->firstFace; B3DPrimitiveFace *lastFace = list->lastFace; B3DPrimitiveFace *face; if(!firstFace && !lastFace) return; if(firstFace->prevFace) b3dAbort("Bad fill list"); if(lastFace->nextFace) b3dAbort("Bad fill list"); face = firstFace; while(face != lastFace) face = face->nextFace; /* Validate sort order */ if(firstFace == lastFace) return; /* 0 or 1 element */ face = firstFace->nextFace; while(face->nextFace) { if(face->minZ > face->nextFace->minZ) b3dAbort("Fill list sorting problem"); face = face->nextFace; } } /* INLINE b3dAddFirstFill(fillList, aFace) */ void b3dAddFirstFill(B3DFillList *fillList, B3DPrimitiveFace *aFace) { B3DPrimitiveFace *firstFace = fillList->firstFace; if(firstFace) firstFace->prevFace = aFace; else fillList->lastFace = aFace; aFace->nextFace = firstFace; aFace->prevFace = NULL; fillList->firstFace = aFace; if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dAddLastFill(fillList, aFace) */ void b3dAddLastFill(B3DFillList *fillList, B3DPrimitiveFace *aFace) { B3DPrimitiveFace *lastFace = fillList->lastFace; if(lastFace) lastFace->nextFace = aFace; else fillList->firstFace = aFace; aFace->prevFace = lastFace; aFace->nextFace = NULL; fillList->lastFace = aFace; if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dRemoveFill(fillList, aFace) */ void b3dRemoveFill(B3DFillList *fillList, B3DPrimitiveFace *aFace) { if(b3dDebug) b3dValidateFillList(fillList); if(aFace->prevFace) aFace->prevFace->nextFace = aFace->nextFace; else fillList->firstFace = aFace->nextFace; if(aFace->nextFace) aFace->nextFace->prevFace = aFace->prevFace; else fillList->lastFace = aFace->prevFace; } /* --INLINE-- */ /* INLINE b3dInsertBeforeFill(fillList, aFace, otherFace) */ void b3dInsertBeforeFill(B3DFillList *fillList, B3DPrimitiveFace *aFace, B3DPrimitiveFace *otherFace) { assert(otherFace != fillList->firstFace); aFace->nextFace = otherFace; aFace->prevFace = otherFace->prevFace; aFace->prevFace->nextFace = aFace; otherFace->prevFace = aFace; if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dAddFrontFill(fillList, aFace) */ void b3dAddFrontFill(B3DFillList *fillList, B3DPrimitiveFace *aFace) { B3DPrimitiveFace *firstFace = fillList->firstFace; if(firstFace != fillList->lastFace) { /* Meaning that we must find the new position for the old front face */ B3DPrimitiveFace *backFace = firstFace->nextFace; float minZ = firstFace->minZ; while(backFace && backFace->minZ < minZ) backFace = backFace->nextFace; /* Insert firstFace before backFace */ if(firstFace->nextFace != backFace) { B3DPrimitiveFace *tempFace = firstFace; b3dRemoveFill(fillList, tempFace); if(backFace) { b3dInsertBeforeFill(fillList, tempFace, backFace); } else { b3dAddLastFill(fillList, tempFace); } } } b3dAddFirstFill(fillList, aFace); if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dAddBackFill(fillList, aFace) */ void b3dAddBackFill(B3DFillList *fillList, B3DPrimitiveFace *aFace) { B3DPrimitiveFace *firstFace = fillList->firstFace; B3DPrimitiveFace *lastFace = fillList->lastFace; B3DPrimitiveFace *face; float minZ = aFace->minZ; assert(firstFace); if(firstFace == lastFace || minZ >= lastFace->minZ) { b3dAddLastFill(fillList, aFace); } else { /* Try an estimation on how to search */ if(minZ <= (firstFace->minZ + lastFace->minZ) * 0.5) { /* search front to back */ face = firstFace->nextFace; while(face->minZ < minZ) face = face->nextFace; } else { /* search back to front */ face = lastFace->prevFace; /* already checked if lastFace->minZ <= minZ */ while(face->minZ > minZ) face = face->prevFace; face = face->nextFace; } b3dInsertBeforeFill(fillList, aFace, face); } if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dCleanupFill(fillList) */ void b3dCleanupFill(B3DFillList *fillList) { B3DPrimitiveFace *firstFace = fillList->firstFace; while(firstFace) { firstFace->flags ^= B3D_FACE_ACTIVE; firstFace = firstFace->nextFace; } fillList->firstFace = fillList->lastFace = NULL; } /* --INLINE-- */ void b3dSearchForNewTopFill(B3DFillList *fillList, int scaledX, int yValue) { B3DPrimitiveFace *topFace = fillList->firstFace; if(b3dDebug) b3dValidateFillList(fillList); if(topFace) { /* only if there is any */ B3DPrimitiveFace *face = topFace->nextFace; double xValue = scaledX * B3D_FixedToFloat; double topZ = zValueAt(topFace, xValue, yValue); /* Note: since the list is ordered we need only to search until face->minZ >= topZ */ while(face && face->minZ <= topZ) { double faceZ = zValueAt(face, xValue, yValue); if(faceZ < topZ) { topZ = faceZ; topFace = face; } face = face->nextFace; } /* and move the guy to front */ b3dRemoveFill(fillList, topFace); b3dAddFrontFill(fillList, topFace); } } /* INLINE b3dToggleTopFills(fillList, edge, yValue) */ void b3dToggleTopFills(B3DFillList *fillList, B3DPrimitiveEdge *edge, int yValue) { B3DPrimitiveFace *leftFace = edge->leftFace; B3DPrimitiveFace *rightFace = edge->rightFace; if(b3dDebug) b3dValidateFillList(fillList); assert(leftFace != rightFace); if(rightFace) { int xorMask = leftFace->flags ^ rightFace->flags; if(xorMask & B3D_FACE_ACTIVE) { if(leftFace->flags & B3D_FACE_ACTIVE) { b3dRemoveFill(fillList, leftFace); b3dAddFrontFill(fillList, rightFace); } else { b3dRemoveFill(fillList, rightFace); b3dAddFrontFill(fillList, leftFace); } } else { if(leftFace->flags & B3D_FACE_ACTIVE) { b3dRemoveFill(fillList, leftFace); b3dRemoveFill(fillList, rightFace); b3dSearchForNewTopFill(fillList, edge->xValue, yValue); } else { if(leftFace->dzdx <= rightFace->dzdx) { b3dAddFrontFill(fillList, leftFace); b3dAddBackFill(fillList, rightFace); } else { b3dAddFrontFill(fillList, rightFace); b3dAddBackFill(fillList, leftFace); } } } leftFace->flags ^= B3D_FACE_ACTIVE; rightFace->flags ^= B3D_FACE_ACTIVE; } else { if(leftFace->flags & B3D_FACE_ACTIVE) { b3dRemoveFill(fillList, leftFace); b3dSearchForNewTopFill(fillList, edge->xValue, yValue); } else { b3dAddFrontFill(fillList, leftFace); } leftFace->flags ^= B3D_FACE_ACTIVE; } if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /* INLINE b3dToggleBackFills(fillList, edge, yValue, nextIntersection) */ void b3dToggleBackFills(B3DFillList *fillList, B3DPrimitiveEdge *edge, int yValue, B3DPrimitiveEdge *nextIntersection) { B3DPrimitiveFace *face = edge->leftFace; if(b3dDebug) b3dValidateFillList(fillList); if(face->flags & B3D_FACE_ACTIVE) { b3dRemoveFill(fillList, face); } else { b3dAddBackFill(fillList, face); b3dCheckIntersectionOfFaces(fillList->firstFace, face, yValue, edge, nextIntersection); } face->flags ^= B3D_FACE_ACTIVE; face = edge->rightFace; if(face) { if(face->flags & B3D_FACE_ACTIVE) { b3dRemoveFill(fillList, face); } else { b3dAddBackFill(fillList, face); b3dCheckIntersectionOfFaces(fillList->firstFace, face, yValue, edge, nextIntersection); } face->flags ^= B3D_FACE_ACTIVE; } if(b3dDebug) b3dValidateFillList(fillList); } /* --INLINE-- */ /*************************************************************/ /*************************************************************/ /*************************************************************/ /* INLINE b3dClearSpanBuffer(aet) */ void b3dClearSpanBuffer(B3DActiveEdgeTable *aet) { int i, leftX, rightX; unsigned int *buffer = currentState->spanBuffer; if(aet->size && buffer) { leftX = aet->data[0]->xValue >> B3D_FixedToIntShift; rightX = aet->data[aet->size-1]->xValue >> B3D_FixedToIntShift; if(leftX < 0) leftX = 0; if(rightX >= currentState->spanSize) rightX = currentState->spanSize-1; for(i=leftX;i<=rightX;i++) buffer[i] = 0; } } /* --INLINE-- */ /* INLINE b3dDrawSpanBuffer(aet, yValue) */ void b3dDrawSpanBuffer(B3DActiveEdgeTable *aet, int yValue) { int leftX, rightX; if(aet->size && currentState->spanDrawer) { leftX = aet->data[0]->xValue >> B3D_FixedToIntShift; rightX = aet->data[aet->size-1]->xValue >> B3D_FixedToIntShift; if(leftX < 0) leftX = 0; if(rightX > currentState->spanSize) rightX = currentState->spanSize; currentState->spanDrawer(leftX, rightX, yValue); } } /* --INLINE-- */ /*************************************************************/ /*************************************************************/ /*************************************************************/ /* General failure */ #define FAIL(reason,resume) { aet->yValue = yValue; return reason | resume; } #define PROCEED { yValue = aet->yValue; } /* Failure adding objects */ #define FAIL_ADDING(reason) { obj->start = objStart; FAIL(reason, B3D_RESUME_ADDING) } #define PROCEED_ADDING { objStart = obj->start; PROCEED } /* Failure merging objects */ #define FAIL_MERGING(reason) { FAIL(reason, B3D_RESUME_MERGING); } #define PROCEED_MERGING { PROCEED } /* Failure during paint */ #define FAIL_PAINTING(reason) { aet->start = aetStart; aet->leftEdge = leftEdge; aet->rightEdge = rightEdge; FAIL(reason, B3D_RESUME_PAINTING) } #define PROCEED_PAINTING(reason) { aetStart = aet->start; leftEdge = aet->leftEdge; rightEdge = aet->rightEdge; PROCEED } #define FAIL_UPDATING(reason) int b3dMainLoop(B3DRasterizerState *state, int stopReason) { B3DPrimitiveObject *activeStart, *passiveStart; int yValue, nextObjY, nextEdgeY; B3DFillList *fillList; B3DPrimitiveEdge *lastIntersection, *nextIntersection; if(!state) return B3D_GENERIC_ERROR; if(!state->nObjects) return B3D_NO_ERROR; if(b3dValidateAndRemapState(state) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; if(stopReason == B3D_NO_ERROR) if(b3dSetupObjects(state) != B3D_NO_ERROR) return B3D_GENERIC_ERROR; if(b3dDebug) { /* check the sort order of objects */ int i; for(i=2; inObjects;i++) if(!objSortsBefore(state->objects[i-1], state->objects[i])) b3dAbort("Objects not sorted"); } currentState = state; faceAlloc = state->faceAlloc; edgeAlloc = state->edgeAlloc; attrAlloc = state->attrAlloc; addedEdges = state->addedEdges; fillList = state->fillList; aet = state->aet; nextIntersection = aet->nextIntersection; lastIntersection = aet->lastIntersection; if(b3dDoStats) nFaces = 0; if(stopReason == B3D_NO_ERROR) { activeStart = passiveStart = state->objects[0]; yValue = nextEdgeY = nextObjY = passiveStart->minY; } else { int resumeCode; resumeCode = stopReason & B3D_RESUME_MASK; if(resumeCode == B3D_RESUME_ADDING ) goto RESUME_ADDING; if(resumeCode == B3D_RESUME_MERGING ) goto RESUME_MERGING; if(resumeCode == B3D_RESUME_PAINTING) goto RESUME_PAINTING; if(resumeCode == B3D_RESUME_UPDATING) goto RESUME_UPDATING; return B3D_GENERIC_ERROR; } /**** BEGIN MAINLOOP ****/ while(activeStart || passiveStart || aet->size) { RESUME_ADDING: /* STEP 1: Add new objects if necessary */ if(yValue == nextObjY) { nextEdgeY = nextObjY; while(passiveStart && passiveStart->minY == nextObjY) { passiveStart->flags |= B3D_OBJECT_ACTIVE; passiveStart = passiveStart->next; } if(passiveStart) nextObjY = passiveStart->minY; else nextObjY = 99999; } /* End of adding objects */ /* STEP 2: Add new edges if necessary */ if(yValue == nextEdgeY) { B3DPrimitiveObject *obj = activeStart; int scaledY = (yValue+1) << B3D_IntToFixedShift; nextEdgeY = nextObjY << B3D_IntToFixedShift; while(obj != passiveStart) { B3DInputFace *objFaces = obj->faces; B3DPrimitiveVertex *objVtx = obj->vertices; int objStart = obj->start; int objSize = obj->nFaces; int tempY; assert(obj->flags & B3D_OBJECT_ACTIVE); while(objStart < objSize && ((tempY = objVtx[objFaces[objStart].i0].windowPosY) < scaledY)) { /* add edges from face at objFaces[objStart] */ B3DInputFace *inputFace = objFaces + objStart; B3DPrimitiveFace *face; /* NOTE: If any of the following fails, we can re-enter the main loop later on. */ if(faceAlloc->nFree == 0) FAIL_ADDING(B3D_NO_MORE_FACES); if(edgeAlloc->nFree < 2) FAIL_ADDING(B3D_NO_MORE_EDGES); if(addedEdges->size+2 > addedEdges->max) FAIL_ADDING(B3D_NO_MORE_ADDED); /* Allocate a new face and do the initial setup */ face = b3dInitializeFace(objVtx + inputFace->i0, objVtx + inputFace->i1, objVtx + inputFace->i2, obj->texture, obj->flags); if(face) { b3dAddEdgesFromFace(face, yValue); } objStart++; } obj->start = objStart; if(objStart != objSize) { if(tempY < nextEdgeY) nextEdgeY = tempY; } else { /* Unlink obj from activeStart list */ obj->flags |= B3D_OBJECT_DONE; if(obj == activeStart) { activeStart = obj->next; } else { obj->prev->next = obj->next; } } obj = obj->next; } nextEdgeY >>= B3D_FixedToIntShift; } /* End of adding edges */ /* STEP 3: Merge all newly added edges from addedList into the AET */ if(addedEdges->size) { RESUME_MERGING: if(b3dDebug) b3dValidateEdgeOrder(addedEdges); /* NOTE: If the following fails, we can re-enter the main loop later on. */ if(aet->size + addedEdges->size > aet->max) FAIL_MERGING(B3D_NO_MORE_AET); b3dMergeAETEdgesFrom(aet, addedEdges); if(b3dDebug) { b3dValidateAETOrder(aet); } addedEdges->size = 0; /* reset added */ } /* End of merging edges */ /********** THIS IS THE CORE LOOP ********/ /* while(yValue < nextEdgeY && !addedEdges->size && aet->size) { */ if(b3dDoStats) { /* Gather stats */ if(aet->size > maxEdges) maxEdges = aet->size; if(nFaces > maxFaces) maxFaces = nFaces; } /* STEP 4: Draw the current span */ /* STEP 4a: Clear the span buffer */ b3dClearSpanBuffer(aet); /* STEP 4b: Scan out the AET */ if(aet->size) { B3DPrimitiveEdge *leftEdge; B3DPrimitiveEdge *rightEdge; B3DPrimitiveEdge **aetData = aet->data; int aetStart = 1; int aetSize = aet->size; /* clean up old fills if any */ b3dCleanupFill(fillList); nextIntersection->xValue = B3D_MAX_X; leftEdge = aetData[0]; while(aetStart < aetSize) { /*-- Toggle the faces of the top edge (the left edge is always on top) --*/ if(leftEdge == lastIntersection) { /* Special case if this is a intersection edge */ assert(fillList->firstFace == leftEdge->leftFace); b3dRemoveFill(fillList, leftEdge->rightFace); b3dAddFrontFill(fillList, leftEdge->rightFace); } else { b3dToggleTopFills(fillList, leftEdge, yValue); } /*-- end of toggling top edge faces --*/ /* after getting a new top fill we must adjust intersections */ b3dAdjustIntersections(fillList, yValue, leftEdge, nextIntersection); /*-- search for the next top edge which will be the right edge --*/ assert(aetStart < aetSize); if(!fillList->firstFace) rightEdge = aetData[aetStart++]; /* If no current top fill just use the next edge */ else while(aetStart < aetSize) { /* Search for the next top edge in the AET */ rightEdge = aetData[aetStart]; /* If we have an intersection use the intersection edge */ if(nextIntersection->xValue <= rightEdge->xValue) { rightEdge = nextIntersection; break; } aetStart++; /* Check if this edge is on top */ assert(fillList->firstFace); { double xValue = rightEdge->xValue * B3D_FixedToFloat; B3DPrimitiveFace *topFace = fillList->firstFace; if( rightEdge->leftFace == topFace || rightEdge->rightFace == topFace || rightEdge->zValue < zValueAt(topFace, xValue, yValue)) break; /* rightEdge is on top */ } /* If the edge is not on top toggle its (back) fills */ b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection); rightEdge = NULL; } /*-- end of search for next top edge --*/ /*-- Now do the drawing from leftEdge to rightEdge --*/ assert(rightEdge); if(fillList->firstFace) { /* Note: We fill *including* leftX and rightX */ int leftX = (leftEdge->xValue >> B3D_FixedToIntShift) + 1; int rightX = (rightEdge->xValue >> B3D_FixedToIntShift); B3DPrimitiveFace *topFace = fillList->firstFace; if(leftX < 0) leftX = 0; if(rightX >= currentState->spanSize) rightX = currentState->spanSize-1; if(leftX <= rightX) { /* Since we know now that some serious filling operation will happen, initialize the attributes of the face if this hasn't been done before. */ RESUME_PAINTING: if( (topFace->flags & B3D_FACE_INITIALIZED) == 0) { assert(topFace->attributes == NULL); if(!b3dInitializePass2(topFace)) FAIL_PAINTING(B3D_NO_MORE_ATTRS); } /* And dispatch on the actual pixel drawers */ (*B3D_FILL_FUNCTIONS[(topFace->flags >> B3D_ATTR_SHIFT) & B3D_ATTR_MASK]) (leftX, rightX, yValue, topFace); } } /*-- End of drawing -- */ /* prepare for new top edge */ leftEdge = rightEdge; /* use a new intersection if necessary */ if(leftEdge == nextIntersection) { nextIntersection = lastIntersection; lastIntersection = leftEdge; } nextIntersection->xValue = B3D_MAX_X; } /* clean up old fills if any */ b3dCleanupFill(fillList); } /* STEP 4c: Display the pixels from the span buffer */ b3dDrawSpanBuffer(aet, yValue); /* STEP 5: Go to next y value and update AET entries */ yValue++; if(aet->size) { int aetStart = 0; int aetSize = aet->size; B3DPrimitiveEdge **aetData = aet->data; aetStart = 0; while(aetStart < aetSize) { B3DPrimitiveEdge *edge = aetData[aetStart]; if(--(edge->nLines)) { /* Advance to next scan line and resort edge */ b3dAdvanceAETEdge(edge, aetData, aetStart); aetStart++; } else { /* Remove edge and add lower edges if necessary */ RESUME_UPDATING: if(edgeAlloc->nFree < 2) FAIL_UPDATING(B3D_NO_MORE_EDGES); if(addedEdges->size + 2 > addedEdges->max) FAIL_UPDATING(B3D_NO_MORE_ADDED); b3dRemoveAETEdge(aet, edge, yValue, aetStart); aetSize = aet->size; /* Do NOT advance aetStart here */ } } } /* End of AET update */ if(b3dDebug) { b3dValidateAETOrder(aet); } /*}*/ /******** END OF CORE LOOP ********/ } /**** END MAINLOOP ****/ return B3D_NO_ERROR; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dRemap.c ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dRemap.c * CONTENT: Remapping functions for the B3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dRemap.c 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #include "b3d.h" /* b3dRemapFaces: Remap all allocated faces using the given offsets */ /* INLINE b3dRemapFaces(list, attrOffset, edgeOffset) */ void b3dRemapFaces(B3DFaceAllocList *list, int attrOffset, int edgeOffset) { int i; for(i=0; isize;i++) { B3DPrimitiveFace *face = list->data + i; if(face->flags & B3D_ALLOC_FLAG) { if(face->attributes) face->attributes = (B3DPrimitiveAttribute*)((char*)face->attributes + attrOffset); if(face->leftEdge) face->leftEdge = (B3DPrimitiveEdge*)((char*)face->leftEdge + edgeOffset); if(face->rightEdge) face->rightEdge = (B3DPrimitiveEdge*)((char*)face->rightEdge + edgeOffset); } } } /* --INLINE-- */ /* b3dRemapEdges: Remap all allocated edges using the given offset */ /* INLINE b3dRemapEdges(list, faceOffset) */ void b3dRemapEdges(B3DEdgeAllocList *list, int faceOffset) { int i; for(i=0; isize;i++) { B3DPrimitiveEdge *edge = list->data + i; if(edge->flags & B3D_ALLOC_FLAG) { if(edge->leftFace) edge->leftFace = (B3DPrimitiveFace*)((char*)edge->leftFace + faceOffset); if(edge->rightFace) edge->rightFace = (B3DPrimitiveFace*)((char*)edge->rightFace + faceOffset); } } } /* --INLINE-- */ /* b3dRemapFills: Remap the fill list using the given offset */ /* INLINE b3dRemapFills(fillList, offset) */ void b3dRemapFills(B3DFillList *fillList, int offset) { B3DPrimitiveFace *temp; if(fillList->firstFace) fillList->firstFace = (B3DPrimitiveFace *)((char*)fillList->firstFace + offset); if(fillList->lastFace) fillList->lastFace = (B3DPrimitiveFace *)((char*)fillList->lastFace + offset); temp = fillList->firstFace; while(temp) { if(temp->nextFace) temp->nextFace = (B3DPrimitiveFace *)((char*)temp->nextFace + offset); if(temp->prevFace) temp->prevFace = (B3DPrimitiveFace *)((char*)temp->prevFace + offset); temp = temp->nextFace; } } /* --INLINE-- */ /* b3dRemapEdgeList: Remap all edge pointers using the given offset */ /* INLINE b3dRemapEdgeList(list, edgeOffset) */ void b3dRemapEdgeList(B3DPrimitiveEdgeList *list, int edgeOffset) { int i; for(i=0; isize;i++) { list->data[i] = (B3DPrimitiveEdge *)((char*) list->data[i] + edgeOffset); } } /* --INLINE-- */ /* b3dRemapAET: Remap all edge pointers using the given offset */ /* INLINE b3dRemapAET(list, edgeOffset, aetOffset, firstEdge, lastEdge) */ void b3dRemapAET(B3DActiveEdgeTable *list, int edgeOffset, int aetOffset, void *firstEdge, void *lastEdge) { int i; if(edgeOffset) for(i=0; isize;i++) list->data[i] = (B3DPrimitiveEdge *)((char*) list->data[i] + edgeOffset); if((void*)list->leftEdge >= firstEdge && (void*)list->leftEdge < lastEdge) list->leftEdge = (B3DPrimitiveEdge *)((char*) list->leftEdge + edgeOffset); else if(list->leftEdge) list->leftEdge = (B3DPrimitiveEdge *)((char*) list->leftEdge + aetOffset); if((void*)list->rightEdge >= firstEdge && (void*)list->rightEdge < lastEdge) list->rightEdge = (B3DPrimitiveEdge *)((char*) list->rightEdge + edgeOffset); else if(list->rightEdge) list->rightEdge = (B3DPrimitiveEdge *)((char*) list->rightEdge + aetOffset); if(aetOffset) { list->nextIntersection = (B3DPrimitiveEdge *)((char*) list->nextIntersection + aetOffset); list->lastIntersection = (B3DPrimitiveEdge *)((char*) list->lastIntersection + aetOffset); } } /* --INLINE-- */ /* b3dRemapEdgeVertices: Remap all vertices in the specified range using the given offset */ /* INLINE b3dRemapEdgeVertices(list, vtxOffset, firstVtx, lastVtx) */ void b3dRemapEdgeVertices(B3DEdgeAllocList *list, int vtxOffset, void *firstVtx, void *lastVtx) { int i; for(i=0; isize; i++) { B3DPrimitiveEdge *edge = list->data + i; if((edge->flags & B3D_ALLOC_FLAG) && ((void*)edge->v0 >= (void*)firstVtx) && ((void*)edge->v0 < (void*)lastVtx)) { edge->v0 = (B3DPrimitiveVertex *)((char*) edge->v0 + vtxOffset); edge->v1 = (B3DPrimitiveVertex *)((char*) edge->v1 + vtxOffset); } } } /* --INLINE-- */ /* b3dRemapFaceVertices: Remap all vertices in the specified range using the given offset */ /* INLINE b3dRemapFaceVertices(list, vtxOffset, firstVtx, lastVtx) */ void b3dRemapFaceVertices(B3DFaceAllocList *list, int vtxOffset, void *firstVtx, void *lastVtx) { int i; for(i=0; isize; i++) { B3DPrimitiveFace *face = list->data + i; if((face->flags & B3D_ALLOC_FLAG) && ((void*)face->v0 >= (void*)firstVtx) && ((void*)face->v0 < (void*)lastVtx)) { face->v0 = (B3DPrimitiveVertex *)((char*) face->v0 + vtxOffset); face->v1 = (B3DPrimitiveVertex *)((char*) face->v1 + vtxOffset); face->v2 = (B3DPrimitiveVertex *)((char*) face->v2 + vtxOffset); } } } /* --INLINE-- */ /* b3dRemapFaceFree: Remap all free faces using the given offset */ /* INLINE b3dRemapFaceFree(list, faceOffset) */ void b3dRemapFaceFree(B3DFaceAllocList *list, int faceOffset) { B3DPrimitiveFace *freeObj; if(list->firstFree) { list->firstFree = (B3DPrimitiveFace *)((char*)list->firstFree + faceOffset); freeObj = list->firstFree; while(freeObj->nextFree) { freeObj->nextFree= (B3DPrimitiveFace *)((char*) freeObj->nextFree + faceOffset); freeObj = freeObj->nextFree; } } } /* --INLINE-- */ /* b3dRemapEdgeFree: Remap all free edges using the given offset */ /* INLINE b3dRemapEdgeFree(list, edgeOffset) */ void b3dRemapEdgeFree(B3DEdgeAllocList *list, int edgeOffset) { B3DPrimitiveEdge *freeObj; if(list->firstFree) { list->firstFree = (B3DPrimitiveEdge *)((char*)list->firstFree + edgeOffset); freeObj = list->firstFree; while(freeObj->nextFree) { freeObj->nextFree = (B3DPrimitiveEdge *)((char*) freeObj->nextFree + edgeOffset); freeObj = freeObj->nextFree; } } } /* --INLINE-- */ /* b3dRemapAttrFree: Remap all free attributes using the given offset */ /* INLINE b3dRemapAttrFree(list, attrOffset) */ void b3dRemapAttributes(B3DAttrAllocList *list, int attrOffset) { int i; for(i=0; i < list->size; i++) { B3DPrimitiveAttribute *attr = list->data + i; if(attr->next) attr->next = (B3DPrimitiveAttribute *)((char*) attr->next + attrOffset); } } /* --INLINE-- */ /* b3dValidateAndRemapState: Validate the rasterizer state and remap the objects if necessary. */ int b3dValidateAndRemapState(B3DRasterizerState *state) { int faceOffset, edgeOffset, attrOffset, aetOffset, objOffset, i; B3DPrimitiveObject *obj; if(!state) return B3D_GENERIC_ERROR; /* Check the magic numbers */ if(state->faceAlloc->magic != B3D_FACE_ALLOC_MAGIC) return B3D_MAGIC_ERROR; if(state->edgeAlloc->magic != B3D_EDGE_ALLOC_MAGIC) return B3D_MAGIC_ERROR; if(state->attrAlloc->magic != B3D_ATTR_ALLOC_MAGIC) return B3D_MAGIC_ERROR; if(state->aet->magic != B3D_AET_MAGIC) return B3D_MAGIC_ERROR; if(state->addedEdges->magic != B3D_EDGE_LIST_MAGIC) return B3D_MAGIC_ERROR; if(state->fillList->magic != B3D_FILL_LIST_MAGIC) return B3D_MAGIC_ERROR; /* Check if we need to relocate objects */ faceOffset = (int)state->faceAlloc - (int)state->faceAlloc->This; edgeOffset = (int)state->edgeAlloc - (int)state->edgeAlloc->This; attrOffset = (int)state->attrAlloc - (int)state->attrAlloc->This; aetOffset = (int)state->aet - (int)state->aet->This; /* remap faces */ if(attrOffset || edgeOffset) b3dRemapFaces(state->faceAlloc, attrOffset, edgeOffset); /* remap fills and edges */ if(faceOffset) { b3dRemapFills(state->fillList, faceOffset); b3dRemapEdges(state->edgeAlloc, faceOffset); b3dRemapFaceFree(state->faceAlloc, faceOffset); } /* Remap AET */ if(edgeOffset || aetOffset) { void *firstEdge = state->edgeAlloc->data; void *lastEdge = state->edgeAlloc->data + state->edgeAlloc->size; b3dRemapAET(state->aet, edgeOffset, aetOffset, firstEdge, lastEdge); } /* Remap addedEdges and edge free list*/ if(edgeOffset) { b3dRemapEdgeList(state->addedEdges, edgeOffset); b3dRemapEdgeFree(state->edgeAlloc, edgeOffset); } if(attrOffset) b3dRemapAttributes(state->attrAlloc, attrOffset); state->faceAlloc->This = (void*) state->faceAlloc; state->edgeAlloc->This = (void*) state->edgeAlloc; state->attrAlloc->This = (void*) state->attrAlloc; state->aet->This = (void*) state->aet; /* Remap any vertex pointers */ for(i=0; inObjects; i++) { obj = state->objects[i]; if(obj->magic != B3D_PRIMITIVE_OBJECT_MAGIC) return B3D_MAGIC_ERROR; objOffset = (int)obj - (int)obj->This; if(objOffset) { if((obj->flags & B3D_OBJECT_ACTIVE)) { B3DPrimitiveVertex *firstVtx = obj->vertices; B3DPrimitiveVertex *lastVtx = obj->vertices + obj->nVertices; b3dRemapFaceVertices(state->faceAlloc, objOffset, firstVtx, lastVtx); b3dRemapEdgeVertices(state->edgeAlloc, objOffset, firstVtx, lastVtx); } obj->vertices = (B3DPrimitiveVertex*) (obj + 1); obj->faces = (B3DInputFace*) (obj->vertices + obj->nVertices); } obj->This = (void*) obj; } return B3D_NO_ERROR; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/Squeak3D/b3dTypes.h ================================================ /**************************************************************************** * PROJECT: Balloon 3D Graphics Subsystem for Squeak * FILE: b3dTypes.h * CONTENT: Type declarations for the B3D rasterizer * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: b3dTypes.h 2 2001-10-24 23:11:49Z rowledge $ * * NOTES: * * *****************************************************************************/ #ifndef B3D_TYPES_H #define B3D_TYPES_H #ifndef NULL #define NULL ((void*)0) #endif /* Error constants */ #define B3D_NO_ERROR 0 /* Generic error */ #define B3D_GENERIC_ERROR -1 /* Bad magic number */ #define B3D_MAGIC_ERROR -2 /* Note: The error codes that allow resuming must be positive. They'll be combined with the resume codes */ /* no more space in edge allocation list */ #define B3D_NO_MORE_EDGES 1 /* no more space in face allocation list */ #define B3D_NO_MORE_FACES 2 /* no more space in attribute allocation list */ #define B3D_NO_MORE_ATTRS 3 /* no more space in active edge table */ #define B3D_NO_MORE_AET 4 /* no more space for added edges */ #define B3D_NO_MORE_ADDED 5 /* Resume codes */ #define B3D_RESUME_MASK 0xF0000 /* Resume adding objects/edges */ #define B3D_RESUME_ADDING 0x10000 /* Resume merging added edges */ #define B3D_RESUME_MERGING 0x20000 /* Resume painting faces */ #define B3D_RESUME_PAINTING 0x40000 /* Resume updating the AET */ #define B3D_RESUME_UPDATING 0x80000 /* Factor to convert from float to fixed pt */ #define B3D_FloatToFixed 4096.0 /* Factor to convert from fixed pt to float */ #define B3D_FixedToFloat 0.000244140625 /* Shift value to convert from integer to fixed pt */ #define B3D_IntToFixedShift 12 #define B3D_FixedToIntShift 12 /* 0.5 in fixed pt representation */ #define B3D_FixedHalf 2048 /* Max. possible x value */ #define B3D_MAX_X 0x7FFFFFFF /* Allocation flag: If this flag is not set then the nextFree pointer is valid */ #define B3D_ALLOC_FLAG 1 /************************ PrimitiveColor definition ************************/ typedef unsigned char B3DPrimitiveColor[4]; /* An ugly hack but I can't find the global defs in CodeWarrior on the Mac */ #ifndef LSB_FIRST #define MSB_FIRST #endif #ifndef MSB_FIRST #define RED_INDEX 0 #define GREEN_INDEX 1 #define BLUE_INDEX 2 #define ALPHA_INDEX 3 #else #define ALPHA_INDEX 0 #define BLUE_INDEX 1 #define GREEN_INDEX 2 #define RED_INDEX 3 #endif /************************ PrimitiveVertex definition ************************/ typedef struct B3DPrimitiveVertex { float position[3]; float normal[3]; float texCoord[2]; float rasterPos[4]; union { int pixelValue32; B3DPrimitiveColor color; } cc; int clipFlags; int windowPos[2]; } B3DPrimitiveVertex; /* sort order for primitive vertices */ #define vtxSortsBefore(vtx1, vtx2) ( (vtx1)->windowPosY == (vtx2)->windowPosY ? (vtx1)->windowPosX <= (vtx2)->windowPosX : (vtx1)->windowPosY <= (vtx2)->windowPosY) /************************ InputFace definition ************************/ /* Note: The following is mainly so that we don't need these weird int[3] declarations. */ typedef struct B3DInputFace { int i0; int i1; int i2; } B3DInputFace; typedef struct B3DInputQuad { int i0; int i1; int i2; int i3; } B3DInputQuad; /************************ PrimitiveEdge definition ************************/ /* Edge flags: B3D_EDGE_CONTINUE_LEFT - continue with the lower edge of the left face B3D_EDGE_CONTINUE_RIGHT - continue with the lower edge of the right face B3D_EDGE_LEFT_MAJOR - edge is major edge for left face B3D_EDGE_RIGHT_MAJOR - edge is major edge for right face */ #define B3D_EDGE_CONTINUE_LEFT 0x10 #define B3D_EDGE_CONTINUE_RIGHT 0x20 #define B3D_EDGE_LEFT_MAJOR 0x40 #define B3D_EDGE_RIGHT_MAJOR 0x80 typedef struct B3DPrimitiveEdge { int flags; struct B3DPrimitiveEdge *nextFree; /* start/end of edge */ struct B3DPrimitiveVertex *v0; struct B3DPrimitiveVertex *v1; /* left/right face of edge (NOT meant literally) */ struct B3DPrimitiveFace *leftFace; struct B3DPrimitiveFace *rightFace; /* current x/z value */ int xValue; float zValue; /* x/z increment per scan line */ int xIncrement; float zIncrement; /* number of remaining scan lines */ int nLines; } B3DPrimitiveEdge; /* B3DPrimitiveEdgeList: A list of pointers to primitive edges */ #define B3D_EDGE_LIST_MAGIC 0x45553342 typedef struct B3DPrimitiveEdgeList { int magic; void *This; int start; int size; int max; B3DPrimitiveEdge *data[1]; } B3DPrimitiveEdgeList; /* B3DActiveEdgeTable: The active edge table (basically a primitive edge table with few additional entries) */ #define B3D_AET_MAGIC 0x41455420 typedef struct B3DActiveEdgeTable { int magic; void *This; int start; int size; int max; /* Backups for proceeding after failure */ int yValue; B3DPrimitiveEdge *leftEdge; B3DPrimitiveEdge *rightEdge; B3DPrimitiveEdge *lastIntersection; B3DPrimitiveEdge *nextIntersection; /* That's where lastIntersection and nextIntersection point to */ B3DPrimitiveEdge tempEdge0; B3DPrimitiveEdge tempEdge1; /* Actual data */ B3DPrimitiveEdge *data[1]; } B3DActiveEdgeTable ; /************************ PrimitiveFace definition ************************/ /* Face flags: B3D_FACE_INITIALIZED - have the face attributes been initialized?! B3D_FACE_ACTIVE - is the face currently in the fill list?! B3D_FACE_HAS_ALPHA - can the face eventually be transparent?! B3D_FACE_RGB - R,G,B interpolation values B3D_FACE_ALPHA - Alpha interpolation values B3D_FACE_STW - S,T,W interpolation values */ #define B3D_FACE_INITIALIZED 0x10 #define B3D_FACE_ACTIVE 0x20 #define B3D_FACE_HAS_ALPHA 0x40 #define B3D_FACE_RGB 0x100 #define B3D_FACE_ALPHA 0x200 #define B3D_FACE_STW 0x400 /* # of possible combinations AND maximum (e.g., R+G+B+A+S+T+W) of attribs */ /* NOTE: This is a really ugly hack - I'll have to fix that */ #define B3D_MAX_ATTRIBUTES 8 /* mask out the face attributes */ #define B3D_ATTR_MASK 0x7 /* shift for getting the attributes */ #define B3D_ATTR_SHIFT 8 typedef struct B3DPrimitiveFace { int flags; struct B3DPrimitiveFace *nextFree; /* The three vertices of the face */ struct B3DPrimitiveVertex *v0; struct B3DPrimitiveVertex *v1; struct B3DPrimitiveVertex *v2; /* The links for the (depth sorted) list of fills */ struct B3DPrimitiveFace *prevFace; struct B3DPrimitiveFace *nextFace; /* The left and right edge of the face (not taken too literally) */ struct B3DPrimitiveEdge *leftEdge; struct B3DPrimitiveEdge *rightEdge; /* The deltas for the major (e.g., v0-v2) and the first minor (e.g., v0-v1) edge */ float majorDx, majorDy; float minorDx, minorDy; /* The inverse area covered by (twice) the triangle */ float oneOverArea; /* Depth attributes are kept here since we almost always need 'em */ float minZ, maxZ; float dzdx, dzdy; /* The pointer to the texture */ struct B3DTexture *texture; /* The pointer to the extended (per face) interpolation values */ struct B3DPrimitiveAttribute *attributes; } B3DPrimitiveFace; /* B3DFillList: A (depth-sorted) list of primitive faces */ #define B3D_FILL_LIST_MAGIC 0x46443342 typedef struct B3DFillList { int magic; void *This; B3DPrimitiveFace *firstFace; B3DPrimitiveFace *lastFace; } B3DFillList; /************************ PrimitiveAttribute definition ************************/ typedef struct B3DPrimitiveAttribute { /* Note: next is either nextFree or or nextUsed */ struct B3DPrimitiveAttribute *next; /* value at the face->v0 */ float value; /* value / dx derivative for face */ float dvdx; /* value / dy derivative for face */ float dvdy; } B3DPrimitiveAttribute; /************************ Texture definition ************************/ #define B3D_TEXTURE_POWER_OF_2 0x10 typedef struct B3DTexture { int width; int height; int depth; int rowLength; /* 32bit words per scan line */ int sMask; /* Nonzero for power of two width */ int sShift; int tMask; /* Nonzero for power of two height */ int tShift; int cmSize; /* length of color map */ unsigned int *colormap; unsigned int *data; } B3DTexture; /************************ PrimitiveViewport definition ************************/ typedef struct B3DPrimitiveViewport { int x0, y0, x1, y1; } B3DPrimitiveViewport; /************************ PrimitiveObject definition ************************/ #define B3D_OBJECT_ACTIVE 0x10 #define B3D_OBJECT_DONE 0x20 #define B3D_PRIMITIVE_OBJECT_MAGIC 0x4F443342 typedef struct B3DPrimitiveObject { int magic; void *This; int __oop__; /* actual ST oop */ struct B3DPrimitiveObject *next; struct B3DPrimitiveObject *prev; int flags; int textureIndex; struct B3DTexture *texture; int minX, maxX, minY, maxY; float minZ, maxZ; int nSortedFaces; int nInvalidFaces; int start; int nFaces; B3DInputFace *faces; int nVertices; B3DPrimitiveVertex *vertices; } B3DPrimitiveObject; /* sort order for primitive objects */ #define objSortsBefore(obj1, obj2) ( (obj1)->minY == (obj2)->minY ? (obj1)->minX <= (obj2)->minX : (obj1)->minY <= (obj2)->minY) #endif /* ifndef B3D_TYPES_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/SqueakFFIPrims/sqFFI.h ================================================ /**************************************************************************** * PROJECT: Squeak foreign function interface support routines * FILE: sqFFI.h * CONTENT: Declarations for the foreign function interface support routines * * AUTHORS: Andreas Raab (ar), Eliot Miranda (eem), Josh Gargus (jcg) * ADDRESS: Teleplace, Inc. * EMAIL: {andreas.raab,eliot,josh}@teleplace.com * *****************************************************************************/ #ifndef SQ_FFI_H #define SQ_FFI_H /* Set the log file name for logging call-outs */ int ffiLogFileNameOfLength(void *nameIndex, int nameLength); int ffiLogCallOfLength(void *nameIndex, int nameLength); /* The following are for creating, manipulating, and destroying "manual surfaces". These are surfaces that are managed by Squeak code, which has manual control over the memory location where the image data is stored (the pointer used may be obtained via FFI calls, or other means). Upon creation, no memory is allocated for the surface. Squeak code is responsible for passing in a pointer to the memory to use. It is OK to set the pointer to different values, or to NULL. If the pointer is NULL, then BitBlt calls to ioLockSurface() will fail. createManualFunction() returns a non-negative surface ID if successful, and -1 otherwise. The other return true for success, and false for failure. */ #include "../SurfacePlugin/SurfacePlugin.h" void initManualSurfaceFunctionPointers(fn_ioRegisterSurface reg, fn_ioUnregisterSurface unreg, fn_ioFindSurface find); int createManualSurface(int width, int height, int rowPitch, int depth, int isMSB); int destroyManualSurface(int surfaceID); int setManualSurfacePointer(int surfaceID, void* ptr); #endif /* SQ_FFI_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/SqueakFFIPrims/sqFFIPlugin.c ================================================ /**************************************************************************** * PROJECT: Squeak threaded foreign function interface * FILE: sqFFIPlugin.c * CONTENT: C support code for the threaded FFIPlugin * * AUTHOR: Eliot Miranda * ADDRESS: Teleplace, Inc. * * *****************************************************************************/ #include #if !WIN32 && !__FreeBSD__ # include #endif #include #ifdef _MSC_VER # define alloca _alloca #endif /* this is a stub through which floating-point register arguments can be loaded * prior to an FFI call proper. e.g. on the PowerPC this would be declared as * extern void loadFloatRegs(double, double, double, double, * double, double, double, double); * and called with the appropriate values necessary to load the floating-point * argument registers. Immediately after the actual call is made, using the * undisturbed register contents created by the call of loadFloatRegs. */ void loadFloatRegs(void) { return; } static FILE *ffiLogFile = NULL; int ffiLogFileNameOfLength(void *nameIndex, int nameLength) { if (nameIndex && nameLength) { char *fileName; FILE *fp; if (!(fileName = alloca(nameLength+1))) return 0; strncpy(fileName, nameIndex, nameLength); fileName[nameLength] = 0; /* attempt to open the file and if we can't, fail */ if (!(fp = fopen(fileName, "at"))) return 0; /* close the old log file if needed and use the new one */ if (ffiLogFile) fclose(ffiLogFile); ffiLogFile = fp; fprintf(ffiLogFile, "------- Log started -------\n"); fflush(fp); } else { if (ffiLogFile) fclose(ffiLogFile); ffiLogFile = NULL; } return 1; } int ffiLogCallOfLength(void *nameIndex, int nameLength) { if (!ffiLogFile) return 0; fprintf(ffiLogFile, "%.*s\n", nameLength, (char *)nameIndex); fflush(ffiLogFile); return 1; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/SqueakFFIPrims/sqFFITestFuncs.c ================================================ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /************ Test functions for the foreign function interface **************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ #ifndef NO_FFI_TEST # include "sq.h" # define LONGLONG sqLong /* should be 64 bits */ typedef struct ffiTestPoint2 { int x; int y; } ffiTestPoint2; typedef struct ffiTestPoint4 { int x; int y; int z; int w; } ffiTestPoint4; #pragma export on EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4); EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4); EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4); EXPORT(int) ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8); EXPORT(float) ffiTestFloats(float f1, float f2); EXPORT(float) ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7); EXPORT(float) ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13); EXPORT(float) ffiTestFloats14(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14); EXPORT(double) ffiTestDoubles14(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14); EXPORT(double) ffiTestDoubles(double d1, double d2); EXPORT(char *) ffiPrintString(char *string); EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2); EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2); EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2); EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8a1(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8a2(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLonga1(char c1, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLonga2(char c1, char c2, LONGLONG i1, LONGLONG i2); #pragma export off /* test passing characters */ EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4) { printf("4 characters came in as\nc1 = %c (%x)\nc2 = %c (%x)\nc3 = %c (%x)\nc4 = %c (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } /* test passing shorts */ EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4) { printf("4 shorts came in as\ns1 = %d (%x)\ns2 = %d (%x)\ns3 = %d (%x)\ns4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } /* test passing ints */ EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4) { printf("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } EXPORT(int) ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8) { printf("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\ni5 = %d (%x)\ni6 = %d (%x)\ni7 = %d (%x)\ni8 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4, c5, c5, c6, c6, c7, c7, c8, c8); return 42; } /* test passing and returning floats */ EXPORT(float) ffiTestFloats(float f1, float f2) { printf("The two floats are %f and %f\n", f1, f2); return (float) (f1 + f2); } EXPORT(float) ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7) { printf("The 7 floats are %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7); } EXPORT(float) ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13) { printf("The 13 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13); } EXPORT(float) ffiTestFloats14(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14) { printf("The 14 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14); } EXPORT(double) ffiTestDoubles14(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14) { printf("The 14 double are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (double) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14); } /* test passing and returning doubles */ EXPORT(double) ffiTestDoubles(double d1, double d2) { printf("The two floats are %f and %f\n", (float)d1, (float)d2); return d1+d2; } /* test passing and returning strings */ EXPORT(char*) ffiPrintString(char *string) { printf("%s\n", string); return string; } /* test passing and returning 64bit structures */ EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2) { ffiTestPoint2 result; printf("pt1.x = %d\npt1.y = %d\npt2.x = %d\npt2.y = %d\n", pt1.x, pt1.y, pt2.x, pt2.y); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; return result; } /* test passing and returning large structures */ EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2) { ffiTestPoint4 result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1.x, pt1.y, pt1.z, pt1.w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2.x, pt2.y, pt2.z, pt2.w); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; result.z = pt1.z + pt2.z; result.w = pt1.w + pt2.w; return result; } /* test passing and returning pointers */ EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2) { ffiTestPoint4 *result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1->x, pt1->y, pt1->z, pt1->w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2->x, pt2->y, pt2->z, pt2->w); result = (ffiTestPoint4*) malloc(sizeof(ffiTestPoint4)); result->x = pt1->x + pt2->x; result->y = pt1->y + pt2->y; result->z = pt1->z + pt2->z; result->w = pt1->w + pt2->w; return result; } /* test passing and returning longlongs */ EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2) { return i1 + i2; } EXPORT(LONGLONG) ffiTestLongLonga1(char c1, LONGLONG i1, LONGLONG i2) { return c1 + i1 + i2; } EXPORT(LONGLONG) ffiTestLongLonga2(char c1, char c2, LONGLONG i1, LONGLONG i2) { return c1 + c2 + i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8a1(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+c9+i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8a2(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+c9+c10+i1 + i2; } #endif /* NO_FFI_TEST */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/SqueakFFIPrims/sqManualSurface.c ================================================ #include "sqFFI.h" #include "sq.h" #include "sqVirtualMachine.h" extern struct VirtualMachine* interpreterProxy; /* Need separate cases for GNU C and MSVC. */ #ifdef DEBUG #warning "DEBUG printing enabled" #define DPRINTF(x) warnPrintf x #elif defined(_DEBUG) #pragma message ( "DEBUG printing enabled" ) #define DPRINTF(x) warnPrintf x #else #define DPRINTF(x) #endif #ifndef NULL #define NULL 0 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* Don't want to mess with EXPORT status of functions in SurfacePlugin.c, we use function-pointers here. */ static fn_ioRegisterSurface registerSurface = NULL; static fn_ioUnregisterSurface unregisterSurface = NULL; static fn_ioFindSurface findSurface = NULL; void initSurfacePluginFunctionPointers() { registerSurface = (fn_ioRegisterSurface) interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface","SurfacePlugin"); unregisterSurface = (fn_ioUnregisterSurface) interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface","SurfacePlugin"); findSurface = (fn_ioFindSurface) interpreterProxy->ioLoadFunctionFrom("ioFindSurface","SurfacePlugin"); } /* This is the structure that represents a "manual surface". These are created/destroyed by new primitives in this plugin. During it's life-time, it may be touched directly from Squeak code to set/clear "ptr", and also treated as a generic surface via BitBlt's use of the SurfacePlugin. */ typedef struct { int width; int height; int rowPitch; int depth; int isMSB; void* ptr; int isLocked; } ManualSurface; /* Create the dispatch-table that SurfacePlugin will use to interact with instances of "struct ManualSurface" */ static int manualSurfaceGetFormat(ManualSurface* surface, int* width, int* height, int* depth, int* isMSB); static void* manualSurfaceLock(ManualSurface* surface, int *pitch, int x, int y, int w, int h); static int manualSurfaceUnlock(ManualSurface* surface, int x, int y, int w, int h); static int manualSurfaceShow(ManualSurface* surface, int x, int y, int w, int h); static sqSurfaceDispatch manualSurfaceDispatch = { 1, 0, (fn_getSurfaceFormat) manualSurfaceGetFormat, (fn_lockSurface) manualSurfaceLock, (fn_unlockSurface) manualSurfaceUnlock, (fn_showSurface) manualSurfaceShow }; /* sqSurfaceDispatch functions *****************************************************************************/ int manualSurfaceGetFormat(ManualSurface* surface, int* width, int* height, int* depth, int* isMSB) { *width = surface->width; *height = surface->height; *depth = surface->depth; *isMSB = surface->isMSB; DPRINTF(("Getting Surface Format: %lx %d %d %d %d\n", ((int) surface), *width, *height, *depth, *isMSB)); return 1; } void* manualSurfaceLock(ManualSurface* surface, int *pitch, int x, int y, int w, int h) { /* Ideally, would be atomic. But it doens't matter for the forseeable future, since it is only called via BitBlt primitives. */ int wasLocked = surface->isLocked; surface->isLocked = 1; /* Can't lock if it was already locked. */ if (wasLocked) return NULL; /* If there is no pointer, the lock-attempt fails. */ if (!surface->ptr) { surface->isLocked = 0; return NULL; } /* Success! Return the pointer. */ *pitch = surface->rowPitch; DPRINTF(("Locked Surface: %lx Input Rect: %d %d %d %d Row Pitch: %d\n", ((int) surface), x, y, w, h, *pitch)); return surface->ptr; } int manualSurfaceUnlock(ManualSurface* surface, int x, int y, int w, int h) { surface->isLocked = 0; DPRINTF(("Unlocked Surface: %lx Rect: %d %d %d %d\n", ((int) surface), x, y, w, h)); return 1; } int manualSurfaceShow(ManualSurface* surface, int x, int y, int w, int h) { /* Unsupported */ return 0; } /* primitive interface functions (i.e. called from Squeak) *********************************************/ /* Answer non-negative surfaceID if successful, and -1 for failure. */ int createManualSurface(int width, int height, int rowPitch, int depth, int isMSB) { ManualSurface* newSurface; int surfaceID; int result; if (width < 0) return -1; if (height < 0) return -1; if (rowPitch < (width*depth)/8) return -1; if (depth < 1 || depth > 32) return -1; if (!registerSurface) return -1; /* failure... couldn't init function-pointer */ newSurface = (ManualSurface*)malloc(sizeof(ManualSurface)); if (!newSurface) return -1; newSurface->width = width; newSurface->height = height; newSurface->rowPitch = rowPitch; newSurface->depth = depth; newSurface->isMSB = isMSB; newSurface->ptr = NULL; newSurface->isLocked = FALSE; result = registerSurface((int)newSurface, &manualSurfaceDispatch, &surfaceID); if (!result) { /* Failed to register surface. */ free(newSurface); return -1; } else { return surfaceID; } } int destroyManualSurface(int surfaceID) { if (!unregisterSurface) return 0; /* failure... couldn't init function-pointer */ else return unregisterSurface(surfaceID); } int setManualSurfacePointer(int surfaceID, void* ptr) { int surfaceHandle; ManualSurface *surface; int result; if (!findSurface) return FALSE; /* failure... couldn't init function-pointer */ result = findSurface(surfaceID, NULL, &surfaceHandle); if (!result) return FALSE; /* failed to find surface */ surface = (ManualSurface*)surfaceHandle; if (surface->isLocked) return FALSE; /* can't set pointer while surface is locked */ surface->ptr = ptr; DPRINTF(("Set Surface: %lx Pointer: %lx\n", surfaceID, ((int)ptr) )); return TRUE; } ================================================ FILE: vm/src/from_squeak/Cross/plugins/SqueakSSL/SqueakSSL.h ================================================ #ifndef SqueakSSL_H #define SqueakSSL_H /*************************/ /* SSL connection states */ /*************************/ #define SQSSL_UNUSED 0 #define SQSSL_ACCEPTING 1 #define SQSSL_CONNECTING 2 #define SQSSL_CONNECTED 3 /********************************************/ /* Return codes from the core SSL functions */ /********************************************/ #define SQSSL_OK 0 #define SQSSL_NEED_MORE_DATA -1 #define SQSSL_INVALID_STATE -2 #define SQSSL_BUFFER_TOO_SMALL -3 #define SQSSL_INPUT_TOO_LARGE -4 #define SQSSL_GENERIC_ERROR -5 #define SQSSL_OUT_OF_MEMORY -6 /**************************************/ /* SqueakSSL certificate status bits. */ /**************************************/ #define SQSSL_NO_CERTIFICATE -1 #define SQSSL_OTHER_ISSUE 0x0001 #define SQSSL_UNTRUSTED_ROOT 0x0002 #define SQSSL_CERT_EXPIRED 0x0004 #define SQSSL_WRONG_USAGE 0x0008 #define SQSSL_INVALID_CN 0x0010 #define SQSSL_CERT_REVOKED 0x0020 /****************************************/ /* SqueakSSL getInt/setInt property IDs */ /****************************************/ #define SQSSL_PROP_VERSION 0 #define SQSSL_PROP_LOGLEVEL 1 #define SQSSL_PROP_SSLSTATE 2 #define SQSSL_PROP_CERTSTATE 3 /**********************************************/ /* SqueakSSL getString/setString property IDs */ /**********************************************/ #define SQSSL_PROP_PEERNAME 0 #define SQSSL_PROP_CERTNAME 1 /* sqCreateSSL: Creates a new SSL instance. Arguments: None. Returns: SSL handle. */ sqInt sqCreateSSL(void); /* sqDestroySSL: Destroys an SSL instance. Arguments: handle - the SSL handle Returns: Non-zero if successful. */ sqInt sqDestroySSL(sqInt handle); /* sqAcceptSSL: Start/continue an SSL server handshake. Arguments: handle - the SSL handle srcBuf - the input token sent by the remote peer srcLen - the size of the input token dstBuf - the output buffer for a new token dstLen - the size of the output buffer Returns: The size of the output token or an error code. */ sqInt sqAcceptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen); /* sqConnectSSL: Start/continue an SSL client handshake. Arguments: handle - the SSL handle srcBuf - the input token sent by the remote peer srcLen - the size of the input token dstBuf - the output buffer for a new token dstLen - the size of the output buffer Returns: The size of the output token or an error code. */ sqInt sqConnectSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen); /* sqEncryptSSL: Encrypt data for SSL transmission. Arguments: handle - the SSL handle srcBuf - the unencrypted input data srcLen - the size of the input data dstBuf - the output buffer for the encrypted contents dstLen - the size of the output buffer Returns: The size of the output generated or an error code. */ sqInt sqEncryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen); /* sqDecryptSSL: Decrypt data for SSL transmission. Arguments: handle - the SSL handle srcBuf - the encrypted input data srcLen - the size of the input data dstBuf - the output buffer for the decrypted contents dstLen - the size of the output buffer Returns: The size of the output generated or an error code. */ sqInt sqDecryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen); /* sqGetStringPropertySSL: Retrieve a string property from SSL. Arguments: handle - the ssl handle propID - the property id to retrieve Returns: The string value of the property. */ char* sqGetStringPropertySSL(sqInt handle, int propID); /* sqSetStringPropertySSL: Set a string property in SSL. Arguments: handle - the ssl handle propID - the property id to retrieve propName - the property string propLen - the length of the property string Returns: Non-zero if successful. */ sqInt sqSetStringPropertySSL(sqInt handle, int propID, char *propName, sqInt propLen); /* sqGetIntPropertySSL: Retrieve an integer property from SSL. Arguments: handle - the ssl handle propID - the property id to retrieve Returns: The integer value of the property. */ sqInt sqGetIntPropertySSL(sqInt handle, sqInt propID); /* sqSetIntPropertySSL: Set an integer property in SSL. Arguments: handle - the ssl handle propID - the property id to retrieve propValue - the property value Returns: Non-zero if successful. */ sqInt sqSetIntPropertySSL(sqInt handle, sqInt propID, sqInt propValue); #endif ================================================ FILE: vm/src/from_squeak/Cross/plugins/SurfacePlugin/SurfacePlugin.c ================================================ /* This file contains the low-level support code for OS surfaces. Since FXBlt may operate on any of these some functions must be provided by the client. It is crucial that every client creating surfaces for use by Squeak registers the surfaces using the functions provided here. Other concrete primitives (such as creation or destroy) of surfaces can be handled by additional support code, querying the surface handle from ioFindSurface but the functions provided below are critical for any BitBlt operations. */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType #include "sqVirtualMachine.h" #include "sqConfig.h" #include "sqPlatformSpecific.h" #include "SurfacePlugin.h" /* internal plugin support */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT #define EXPORT(returnType) static returnType #endif typedef struct SqueakSurface { int handle; /* client supplied handle */ sqSurfaceDispatch *dispatch; } SqueakSurface; static SqueakSurface *surfaceArray = NULL; static int numSurfaces = 0; static int maxSurfaces = 0; #ifdef SQUEAK_BUILTIN_PLUGIN static const char *moduleName = "SurfacePlugin "__DATE__" (i)"; #else static const char *moduleName = "SurfacePlugin "__DATE__" (e)"; #endif static VirtualMachine *interpreterProxy; #define FAIL { interpreterProxy->primitiveFail(); return 0; } #pragma export on /* module initialization/shutdown */ EXPORT(int) setInterpreter(struct VirtualMachine *interpreterProxy); EXPORT(const char*) getModuleName(void); EXPORT(int) initialiseModule(void); EXPORT(int) shutdownModule(void); /* critical FXBlt entry points */ EXPORT(int) ioGetSurfaceFormat (int surfaceID, int* width, int* height, int* depth, int* isMSB); EXPORT(int) ioLockSurface (int surfaceID, int *pitch, int x, int y, int w, int h); EXPORT(int) ioUnlockSurface(int surfaceID, int x, int y, int w, int h); /* interpreter entry point */ EXPORT(int) ioShowSurface(int surfaceID, int x, int y, int w, int h); /* client entry points */ EXPORT(int) ioRegisterSurface(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID); EXPORT(int) ioUnregisterSurface(int surfaceID); EXPORT(int) ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle); #pragma export off /* ioGetSurfaceFormat: Return information describing the given surface. Return true if successful, false otherwise. */ EXPORT(int) ioGetSurfaceFormat (int surfaceID, int* width, int* height, int* depth, int* isMSB) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->getSurfaceFormat) FAIL; return surface->dispatch->getSurfaceFormat(surface->handle, width, height, depth, isMSB); } /* ioLockSurface: Lock the bits of the surface. Return a pointer to the actual surface bits, or NULL on failure. */ EXPORT(int) ioLockSurface (int surfaceID, int *pitch, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->lockSurface) FAIL; return surface->dispatch->lockSurface(surface->handle, pitch, x, y, w, h); } /* ioUnlockSurface: Unlock the bits of the surface. The return value is ignored. */ EXPORT(int) ioUnlockSurface(int surfaceID, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->unlockSurface) FAIL; return surface->dispatch->unlockSurface(surface->handle, x, y, w, h); } /* ioShowSurface: Transfer the bits of a surface to the screen. */ EXPORT(int) ioShowSurface(int surfaceID, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->showSurface) FAIL; return surface->dispatch->showSurface(surface->handle, x, y, w, h); } /* ioRegisterSurface: Register a new surface with the given handle and the set of surface functions. The new ID is returned in surfaceID. Returns true if successful, false otherwise. */ EXPORT(int) ioRegisterSurface(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID) { int index; if(!fn) return 0; if(fn->majorVersion != 1 && fn->minorVersion != 0) return 0; if(numSurfaces == maxSurfaces) { maxSurfaces = maxSurfaces * 2 + 10; surfaceArray = realloc(surfaceArray, sizeof(SqueakSurface) * maxSurfaces); for(index = numSurfaces; index < maxSurfaces; index++){ surfaceArray[index].handle = 0; surfaceArray[index].dispatch = NULL; } index = numSurfaces; } else { for(index = 0; index < maxSurfaces; index++) if(surfaceArray[index].dispatch == NULL) break; } if(index >= maxSurfaces) return 0; /* should not happen */ surfaceArray[index].handle = surfaceHandle; surfaceArray[index].dispatch = fn; *surfaceID = index; numSurfaces++; return 1; } /* ioUnregisterSurface: Unregister the surface with the given handle. Returns true if successful, false otherwise. */ EXPORT(int) ioUnregisterSurface(int surfaceID) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) return 0; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) return 0; surface->handle = 0; surface->dispatch = NULL; numSurfaces--; return 1; } /* ioFindSurface: Find the surface with the given ID, and, optionally, the given set of surface functions. The registered handle is returned in surfaceHandle. Return true if successful (e.g., the surface has been found), false otherwise. */ EXPORT(int) ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) return 0; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) return 0; if(fn && fn != surface->dispatch) return 0; *surfaceHandle = surface->handle; return 1; } EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter) { int ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(const char*) getModuleName(void) { return moduleName; } EXPORT(int) initialiseModule() { surfaceArray = NULL; numSurfaces = 0; maxSurfaces = 0; return 1; } EXPORT(int) shutdownModule() { /* This module can only be shut down if no surfaces are registered */ if(numSurfaces != 0) return 0; free(surfaceArray); return 1; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SurfacePlugin_exports[][3] = { {"SurfacePlugin", "setInterpreter", (void*)setInterpreter}, {"SurfacePlugin", "getModuleName", (void*)getModuleName}, {"SurfacePlugin", "initialiseModule", (void*)initialiseModule}, {"SurfacePlugin", "shutdownModule", (void*)shutdownModule}, {"SurfacePlugin", "ioGetSurfaceFormat", (void*)ioGetSurfaceFormat}, {"SurfacePlugin", "ioLockSurface", (void*)ioLockSurface}, {"SurfacePlugin", "ioUnlockSurface", (void*)ioUnlockSurface}, {"SurfacePlugin", "ioShowSurface", (void*)ioShowSurface}, {"SurfacePlugin", "ioRegisterSurface", (void*)ioRegisterSurface}, {"SurfacePlugin", "ioUnregisterSurface", (void*)ioUnregisterSurface}, {"SurfacePlugin", "ioFindSurface", (void*)ioFindSurface}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/SurfacePlugin/SurfacePlugin.h ================================================ #ifndef __SQ_DRAW_SURFACE_H #define __SQ_DRAW_SURFACE_H /* v1.0 */ #define SQ_SURFACE_MAJOR 1 #define SQ_SURFACE_MINOR 0 /* Plugins creating their own surfaces must register these using the following set of functions. The typedefs are for easier casts. */ typedef int (*fn_getSurfaceFormat)(int surfaceHandle, int* width, int* height, int* depth, int* isMSB); typedef int (*fn_lockSurface)(int surfaceHandle, int *pitch, int x, int y, int w, int h); typedef int (*fn_unlockSurface)(int surfaceHandle, int x, int y, int w, int h); typedef int (*fn_showSurface)(int surfaceHandle, int x, int y, int w, int h); typedef struct sqSurfaceDispatch { /* Version information. Must be provided by the client so the surface manager can check if certain operations are supported. */ int majorVersion; int minorVersion; /* Version 1.0 */ fn_getSurfaceFormat getSurfaceFormat; fn_lockSurface lockSurface; fn_unlockSurface unlockSurface; fn_showSurface showSurface; } sqSurfaceDispatch; /* The functions for sqSurfaceDispatch are: int getSurfaceFormat(int handle, int* width, int* height, int* depth, int* isMSB); Return general information about the OS drawing surface. Return true if successful, false otherwise. The returned values describe the basic properties such as width, height, depth and LSB vs. MSB pixels. int lockSurface(int handle, int *pitch, int x, int y, int w, int h); Lock the bits of the surface. Return a pointer to the actual surface bits, or NULL on failure. If successful, store the pitch of the surface (e.g., the bytes per scan line). For equal source/dest handles only one locking operation is performed. This is to prevent locking of overlapping areas which does not work with certain APIs (e.g., DirectDraw prevents locking of overlapping areas). A special case for non-overlapping but equal source/dest handle would be possible but we would have to transfer this information over to unlockSurfaces somehow (currently, only one unlock operation is performed for equal source and dest handles). Also, this would require a change in the notion of ioLockSurface() which is right now interpreted as a hint and not as a requirement to lock only the specific portion of the surface. The arguments in ioLockSurface() provide the implementation with an explicit hint what area is affected. It can be very useful to know the max. affected area beforehand if getting the bits requires expensive copy operations (e.g., like a roundtrip to the X server or a glReadPixel op). However, the returned pointer *MUST* point to the virtual origin of the surface and not to the beginning of the rectangle. The promise made by BitBlt is to never access data outside the given rectangle (aligned to 4byte boundaries!) so it is okay to return a pointer to the virtual origin that is actually outside the valid memory area. The area provided in ioLockSurface() is already clipped (e.g., it will always be inside the source and dest boundingBox) but it is not aligned to word boundaries yet. It is up to the support code to compute accurate alignment if necessary. int unlockSurface(int handle, int x, int y, int w, int h); Unlock the bits of a (possibly modified) surface after BitBlt completed. The return value is ignored. The arguments provided specify the dirty region of the surface. If the surface is unmodified all arguments are set to zero. int showSurface(int handle, int x, int y, int w, int h); Display the contents of the surface on the actual screen. If ioShowSurface() is called the surface in question represents a Squeak DisplayScreen. FXBlt uses a variant of the above functions which are exported from the surface plugin: int ioGetSurfaceFormat(int surfaceID, int* width, int* height, int* depth, int* isMSB); int ioLockSurface(int surfaceID, int *pitch, int x, int y, int w, int h); int ioUnlockSurface(int surfaceID, int x, int y, int w, int h); These functions are looked up in the registered surfaces and invoked as appropriate. The meaning of all values is exactly the same as for the functions specified in sqSurfaceDispatch with the exception that the surfaceID represents the 'bits' handle of the Form that is used within FXBlt. Interpreter itself uses a separate entry point for updating the display int ioShowSurface(int surfaceID, int x, int y, int w, int h); since the management of deferred updates is currently an intrinsic property of the VM (which is bad - deferred updates should be a property of the DisplayScreen in question and not of the VM but that's the way it is...). */ /* The following are the entry points for the surface manager: int ioRegisterSurface(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID); Register a new surface with the given handle and the set of surface functions. The new ID is returned in surfaceID. Returns true if successful, false otherwise. int ioUnregisterSurface(int surfaceID); Unregister the surface with the given handle. Returns true if successful, false otherwise. int ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle); Find the surface with the given ID, and, optionally, the given set of surface functions. The registered handle is returned in surfaceHandle. Return true if successful (e.g., the surface has been found), false otherwise. The above entry points can be looked up through the interpreter, e.g., using interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface","SurfacePlugin"); The typedefs below are for easier casts. */ typedef int (*fn_ioRegisterSurface)(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID); typedef int (*fn_ioUnregisterSurface)(int surfaceID); typedef int (*fn_ioFindSurface)(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle); #endif /* __SQ_DRAW_SURFACE_H */ ================================================ FILE: vm/src/from_squeak/Cross/plugins/UUIDPlugin/UUIDPlugin.h ================================================ /* UUID generation. Note that we typedef sqUUID as a generic 128 bit value so that platform specific code can coerce appropriately. */ typedef char sqUUID[16]; int MakeUUID(sqUUID location); int sqUUIDInit(); int sqUUIDShutdown(); ================================================ FILE: vm/src/from_squeak/Cross/vm/dispdbg.h ================================================ /* * Break-pointer debugging facilities for the StackInterpreter VM. * Edit this to install various debugging traps. In a production * VM this header should define only the assert macros and empty * sendBreakpointreceiver and bytecodeDispatchDebugHook macros. */ #include "sqAssert.h" #if !defined(VMBIGENDIAN) # error "sqConfig.h does not define VMBIGENDIAN" #elif !((VMBIGENDIAN == 1) || (VMBIGENDIAN == 0)) # error "sqConfig.h does not define VMBIGENDIAN as either 1 or 0" #endif /* * various definitions of the sendBreakpointreceiver macro for break-pointing at * specific sends. */ #if PRODUCTION /* default for no send breakpoint. */ # define sendBreakpointreceiver(sel, len, rcvr) 0 #elif 0 /* send tracing. */ # define sendBreakpointreceiver(sel, len, rcvr) do { \ if (sendTrace) \ printf("%.*s\n", len, (char *)(sel)); \ } while (0) #elif 0 /* send trace/byte count. */ # define sendBreakpointreceiver(sel, len, rcvr) do { \ if (sendTrace) \ printf("%u %.*s\n", GIV(byteCount), len, (char *)(sel)); \ } while (0) #elif 1 /* breakpoint without byteCount. */ # define sendBreakpointreceiver(sel, len, rcvr) do { \ if ((len) == breakSelectorLength \ && !strncmp((char *)(sel), breakSelector, breakSelectorLength)) { \ suppressHeartbeatFlag = 1; \ warning("send breakpoint (heartbeat suppressed)"); \ if (0) sendTrace = 1; \ } \ if (sendTrace) { \ printf("%.*s\n", len, (char *)(sel)); \ if (0 && !checkHeapIntegrity()) error("object leak"); \ } \ } while (0) #elif 0 /* breakpoint with byteCount. */ # define sendBreakpointreceiver(sel, len, rcvr) do { \ if ((len) == breakSelectorLength \ && !strncmp((char *)(sel), breakSelector, breakSelectorLength)) { \ suppressHeartbeatFlag = 1; \ warning("send breakpoint (heartbeat suppressed)"); \ if (0) sendTrace = 1; \ } \ if (sendTrace) \ printf("%u %.*s\n", GIV(byteCount), len, (char *)(sel)); \ } while (0) #endif /* * various definitions of the bytecodeDispatchDebugHook macro for * debugging code at the bytecode dispatch switch. */ #if PRODUCTION # define bytecodeDispatchDebugHook() 0 #elif 1 /* check for valid instruction pointer */ # define bytecodeDispatchDebugHook() do { \ if (!validInstructionPointerinMethodframePointer((usqInt)localIP, GIV(method), localFP)) \ warning("invalidInstructionPointerinMethod"); \ } while (0) #elif 0 /* check for valid stack-related pointers */ # define DEBUG_DISABLE_HEARTBEAT 1 # define bytecodeDispatchDebugHook() do { \ if (++GIV(byteCount) % 100000 == 0) \ forceInterruptCheck(); \ assertValidExecutionPointersimbar(localIP,localFP,localSP,1); \ } while (0) #elif 0 /* maintain byteCount & break-point & heart-beat every 100k bytecodes */ # define DEBUG_DISABLE_HEARTBEAT 1 # define bytecodeDispatchDebugHook() do { \ if (++GIV(byteCount) % 100000 == 0) \ forceInterruptCheck(); \ if (GIV(byteCount) == -1 /*256696UL*/) { \ sendTrace = 1; \ warning("break byteCount reached\n"); \ } \ if (!((localFP < ((GIV(stackPage->baseAddress)))) \ && (localFP > (((GIV(stackPage->realStackLimit))) - (((sqInt) LargeContextSize >> 1)))))) { \ warning("invalidLocalFPInPage"); \ sendTrace = 1; \ } \ if (GIV(stackLimit) != (char *)-1 && GIV(stackLimit) != GIV(stackPage->realStackLimit)) { \ warning("invalidStackLimitInPage"); \ sendTrace = 1; \ } \ } while (0) #elif 0 /* maintain byteCount & check for valid instruction pointer */ # define bytecodeDispatchDebugHook() do { \ if (++GIV(byteCount) == 175779UL) \ warning("break byteCount reached\n"); \ if (!validInstructionPointerinMethodframePointer((usqInt)localIP, GIV(method), localFP)) \ warning("invalidInstructionPointerinMethod"); \ } while (0) #elif 0 /* maintain byteCount & check for valid instruction pointer */ # define bytecodeDispatchDebugHook() do { \ printf("%ld: %x %d\n", ++GIV(byteCount), localIP-GIV(method)-3, currentBytecode); \ if (!validInstructionPointerinMethodframePointer((usqInt)localIP, GIV(method), localFP)) \ warning("invalidInstructionPointerinMethod"); \ if (sendTrace) printCallStack(); \ } while (0) #elif 0 /* print current frame & instruction pointer on every bytecode. */ # define bytecodeDispatchDebugHook() do { \ printFrameWithSP(localFP,localSP); \ printf("%d %x\n", localIP - GIV(method) - 3, currentBytecode); \ } while (0) #elif 0 /* print current frame & pc on every bytecode if sendTrace/hit break. */ # define bytecodeDispatchDebugHook() do { \ if (sendTrace) { \ printFrameWithSP(localFP,localSP); \ printf("%d %x\n", localIP - GIV(method) - 3, currentBytecode); \ } \ } while (0) #endif ================================================ FILE: vm/src/from_squeak/Cross/vm/sq.h ================================================ /**************************************************************************** * PROJECT: Common include * FILE: sq.h * CONTENT: * * AUTHOR: * ADDRESS: * EMAIL: * RCSID: $Id: sq.h 1283 2005-12-31 00:51:12Z rowledge $ * */ #include #include #include #include #include # include "squeak_adapters.h" #include "sqConfig.h" #include "sqMemoryAccess.h" #include "sqVirtualMachine.h" #define true 1 #define false 0 #define null 0 /* using "null" because nil is predefined in Think C */ /* Pluggable primitives macros. */ /* Note: All pluggable primitives are defined as EXPORT(int) somePrimitive(void) If the platform requires special declaration modifiers, the EXPORT macro can be redefined. */ #define EXPORT(returnType) returnType /* Image save/restore macros. */ /* Note: The image file save and restore code uses these macros; they can be redefined in sqPlatformSpecific.h if desired. These default versions are defined in terms of the ANSI Standard C libraries. */ #define sqImageFile FILE * #define sqImageFileClose(f) fclose(f) #define sqImageFileOpen(fileName, mode) fopen(fileName, mode) #define sqImageFilePosition(f) ftell(f) #define sqImageFileRead(ptr, sz, count, f) fread(ptr, sz, count, f) #define sqImageFileSeek(f, pos) fseek(f, pos, SEEK_SET) #define sqImageFileWrite(ptr, sz, count, f) fwrite(ptr, sz, count, f) #define sqImageFileStartLocation(fileRef, fileName, size) 0 /* Platform-dependent macros for handling object memory. */ /* Note: The grow/shrink macros assume that the object memory can be extended continuously at its prior end. The garbage collector cannot deal with 'holes' in the object memory so the support code needs to reserve the virtual maximum of pages that can be allocated beforehand. The amount of 'extra' memory should describe the amount of memory that can be allocated from the OS (including swap space if the flag is set to true) and must not exceed the prior reserved memory. In other words: don't you dare to report more free space then you can actually allocate. The default implementation assumes a fixed size memory allocated at startup. */ #define sqAllocateMemory(minHeapSize, desiredHeapSize) malloc(desiredHeapSize) #define sqGrowMemoryBy(oldLimit, delta) oldLimit #define sqShrinkMemoryBy(oldLimit, delta) oldLimit #define sqMemoryExtraBytesLeft(includingSwap) 0 /* Platform-dependent memory size adjustment macro. */ /* Note: This macro can be redefined to allows platforms with a fixed application memory partition (notably, the Macintosh) to reserve extra C heap memory for special applications that need it (e.g., for a 3D graphics library). Since most platforms can extend their application memory partition at run time if needed, this macro is defined as a noop here and redefined if necessary in sqPlatformSpecific.h. */ #define reserveExtraCHeapBytes(origHeapSize, bytesToReserve) origHeapSize /* Platform-dependent millisecond clock macros. */ /* Note: The Squeak VM uses two different clock functions for timing, and the Cog VMs provide a third. The primary one, ioMSecs(), is used to implement Delay and Time millisecondClockValue. The resolution of this clock determines the resolution of these basic timing functions. For doing real-time control of music and MIDI, a clock with resolution down to one millisecond is preferred, but a coarser clock (say, 1/60th second) can be used in a pinch. The function ioMicroMSecs() is used only to collect timing statistics for the garbage collector and other VM facilities. (The function name is meant to suggest that the function is based on a clock with microsecond accuracy, even though the times it returns are in units of milliseconds.) This clock must have enough precision to provide accurate timings, and normally isn't called frequently enough to slow down the VM. Thus, it can use a more expensive clock than ioMSecs(). This function is listed in the sqVirtualMachine plugin support mechanism and thus needs to be a real function, even if a macro is use to point to it. There was a third form that used to be used for quickly timing primitives in order to try to keep millisecond delays up to date. That is no longer used. By default, the basic ioMSec() clock function is defined here as a macro based on the standard C library function clock(). Any of this can be overridden in sqPlatformSpecific.h. The wall clock is answered by ioSeconds, which answers the number of seconds since the start of the 20th century (12pm Dec 31, 1900). The Cog VMs depend on a heartbeat to cause the VM to check for interrupts at regular intervals (of the order of ever milisecond). The heartbeat on these VMs is responsible for updating a 64-bit microsecond clock with the number of microseconds since the start of the 20th century (12pm Dec 31, 1900) available via ioUTCMicroseconds() and ioLocalMicroseconds(). For cases where exact time is required we provide ioUTCMicrosecondsNow that updates the clock to return the time right now, rather than of the last heartbeat. */ sqInt ioMSecs(void); /* deprecated out of existence sqInt ioLowResMSecs(void); */ sqInt ioMicroMSecs(void); /* duplicate the generated definition in the interpreter. If they differ the * compiler will complain and catch it for us. We use 0x1FFFFFFF instead of * 0x3FFFFFFF so that twice the maximum clock value remains in the positive * SmallInteger range. This assumes 31 bit SmallIntegers; 0x3FFFFFFF is * SmallInteger maxVal. */ #define MillisecondClockMask 0x1FFFFFFF #if STACKVM usqLong ioUTCMicrosecondsNow(); usqLong ioUTCMicroseconds(); usqLong ioLocalMicroseconds(); void ioUpdateVMTimezone(); void ioSynchronousCheckForEvents(); void checkHighPriorityTickees(usqLong); # if ITIMER_HEARTBEAT /* Hack; allow heartbeat to avoid */ extern int numAsyncTickees; /* prodHighPriorityThread unless necessary */ # endif /* see platforms/unix/vm/sqUnixHeartbeat.c */ void ioGetClockLogSizeUsecsIdxMsecsIdx(sqInt*,void**,sqInt*,void**,sqInt*); #endif /* this function should return the value of the high performance counter if there is such a thing on this platform (otherwise return 0) */ sqLong ioHighResClock(void); /* New filename converting function; used by the interpreterProxy function ioFilenamefromStringofLengthresolveAliases. Most platforms can ignore the resolveAlias boolean - it seems to only be of use by OSX but is crucial there. */ sqInt sqGetFilenameFromString(char * aCharBuffer, char * aFilenameString, sqInt filenameLength, sqInt aBoolean); /* Macro to provide default null behaviour for ftruncate - a non-ansi call used in FilePlugin. Override in sqPlatformSpecific.h for each platform that implements a file truncate, or consider replacing the ../Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c file with a platform specific version as Win32 and RISC OS do. */ #define sqFTruncate(filenum, fileoffset) true /* Macros to support Mac browser plugin without ugly code in Interpreter. */ #define insufficientMemorySpecifiedError() error("Insufficient memory for this image") #define insufficientMemoryAvailableError() error("Failed to allocate memory for the heap") #define unableToReadImageError() error("Read failed or premature end of image file") #define browserPluginReturnIfNeeded() #define browserPluginInitialiseIfNeeded() /* Platform-specific header file may redefine earlier definitions and macros. */ #include "sqPlatformSpecific.h" /* Interpreter entry points. */ /* Disable Intel compiler inlining of error which is used for breakpoints */ #pragma auto_inline off void error(char *s); #pragma auto_inline on sqInt checkedByteAt(sqInt byteAddress); sqInt checkedByteAtput(sqInt byteAddress, sqInt byte); sqInt checkedLongAt(sqInt byteAddress); sqInt checkedLongAtput(sqInt byteAddress, sqInt a32BitInteger); sqInt fullDisplayUpdate(void); sqInt interpret(void); sqInt primitiveFail(void); sqInt signalSemaphoreWithIndex(sqInt semaIndex); sqInt success(sqInt); /* Display, mouse, keyboard, time. */ sqInt ioBeep(void); sqInt ioExit(void); sqInt ioExitWithErrorCode(int); sqInt ioForceDisplayUpdate(void); sqInt ioFormPrint(sqInt bitsAddr, sqInt width, sqInt height, sqInt depth, double hScale, double vScale, sqInt landscapeFlag); sqInt ioSetFullScreen(sqInt fullScreen); sqInt ioRelinquishProcessorForMicroseconds(sqInt microSeconds); sqInt ioScreenSize(void); sqInt ioScreenDepth(void); sqInt ioSeconds(void); sqInt ioSetCursor(sqInt cursorBitsIndex, sqInt offsetX, sqInt offsetY); sqInt ioSetCursorWithMask(sqInt cursorBitsIndex, sqInt cursorMaskIndex, sqInt offsetX, sqInt offsetY); sqInt ioShowDisplay(sqInt dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB); sqInt ioHasDisplayDepth(sqInt depth); sqInt ioSetDisplayMode(sqInt width, sqInt height, sqInt depth, sqInt fullscreenFlag); #if STACKVM /* thread subsystem support for e.g. sqExternalSemaphores.c */ void ioInitThreads(); /* Event polling via periodic heartbeat thread. */ void ioInitHeartbeat(void); int ioHeartbeatMilliseconds(void); void ioSetHeartbeatMilliseconds(int); unsigned long ioHeartbeatFrequency(int); /* Management of the external semaphore table (max size set at startup) */ #if !defined(INITIAL_EXT_SEM_TABLE_SIZE) # define INITIAL_EXT_SEM_TABLE_SIZE 256 #endif int ioGetMaxExtSemTableSize(void); void ioSetMaxExtSemTableSize(int); /* these are used both in the STACKVM & the COGMTVM */ # if !defined(ioCurrentOSThread) sqOSThread ioCurrentOSThread(void); # endif # if !defined(ioOSThreadsEqual) int ioOSThreadsEqual(sqOSThread,sqOSThread); # endif # if !COGMTVM extern sqOSThread ioVMThread; # define getVMOSThread() ioVMThread # endif #endif /* STACKVM */ #if COGMTVM #define THRLOGSZ 256 extern int thrlogidx; extern char *thrlog[]; /* Debug logging that defers printing. Use like printf, e.g. * TLOG("tryLockVMToIndex vmOwner = %d\n", vmOwner); * Requires #include "sqAtomicOps.h" * N.B. The following still isn't safe. If enough log entries are made by other * threads after myindex is obtained but before asprintf completes we can get * two threads using the same entry. But this is good enough for now. */ #define THRLOG(...) do { int myidx, oldidx; \ do { myidx = thrlogidx; \ sqCompareAndSwapRes(thrlogidx,myidx,(myidx+1)&(THRLOGSZ-1),oldidx); \ } while (myidx != oldidx); \ if (thrlog[myidx]) free(thrlog[myidx]); \ asprintf(thrlog + myidx, __VA_ARGS__); \ } while (0) extern sqOSThread getVMOSThread(); /* Please read the comment for CogThreadManager in the VMMaker package for * documentation of this API. N.B. code is included from sqPlatformSpecific.h * before the code here. e.g. * # include * # define sqOSThread pthread_t * # define sqOSSemaphore pthread_cond_t * # define ioOSThreadsEqual(a,b) pthread_equal(a,b) */ # if !defined(ioGetThreadLocalThreadIndex) long ioGetThreadLocalThreadIndex(void); # endif # if !defined(ioSetThreadLocalThreadIndex) void ioSetThreadLocalThreadIndex(long); # endif # if !defined(ioNewOSThread) int ioNewOSThread(void (*func)(void *), void *); # endif # if !defined(ioExitOSThread) void ioExitOSThread(sqOSThread thread); # endif # if !defined(ioReleaseOSThreadState) void ioReleaseOSThreadState(sqOSThread thread); # endif # if !defined(ioOSThreadIsAlive) int ioOSThreadIsAlive(sqOSThread); # endif int ioNewOSSemaphore(sqOSSemaphore *); # if !defined(ioDestroyOSSemaphore) void ioDestroyOSSemaphore(sqOSSemaphore *); # endif void ioSignalOSSemaphore(sqOSSemaphore *); void ioWaitOnOSSemaphore(sqOSSemaphore *); int ioNumProcessors(void); # if !defined(ioTransferTimeslice) void ioTransferTimeslice(void); # endif #endif /* COGMTVM */ /* Profiling. */ void ioProfileStatus(sqInt *running, void **exestartpc, void **exelimitpc, void **vmhst, long *nvmhbin, void **eahst, long *neahbin); void ioControlProfile(int on, void **vhp, long *nvb, void **ehp, long *neb); long ioControlNewProfile(int on, unsigned long buffer_size); void ioNewProfileStatus(sqInt *running, long *buffersize); long ioNewProfileSamplesInto(void *sampleBuffer); void ioClearProfile(void); /* Power management. */ sqInt ioDisablePowerManager(sqInt disableIfNonZero); /* User input recording I: In general, either set of input function can be supported, depending on the platform. This (first) set is state based and should be supported even on platforms that make use of the newer event driven API to support older images without event support. */ sqInt ioGetButtonState(void); sqInt ioGetKeystroke(void); sqInt ioMousePoint(void); sqInt ioPeekKeystroke(void); /* Note: In an event driven architecture, ioProcessEvents is obsolete. It can be implemented as a no-op since the image will check for events in regular intervals. */ sqInt ioProcessEvents(void); /* User input recording II: The following functions and definition can be used on platform supporting events directly. */ /* Event types. */ #define EventTypeNone 0 #define EventTypeMouse 1 #define EventTypeKeyboard 2 #define EventTypeDragDropFiles 3 #define EventTypeMenu 4 #define EventTypeWindow 5 #define EventTypeComplex 6 /* Keypress state for keyboard events. */ #define EventKeyChar 0 #define EventKeyDown 1 #define EventKeyUp 2 /* Button definitions. */ #define RedButtonBit 4 #define YellowButtonBit 2 #define BlueButtonBit 1 /* Modifier definitions. */ #define ShiftKeyBit 1 #define CtrlKeyBit 2 #define OptionKeyBit 4 #define CommandKeyBit 8 /* generic input event */ typedef struct sqInputEvent { int type; /* type of event; either one of EventTypeXXX */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int unused1; int unused2; int unused3; int unused4; int unused5; int windowIndex; /* SmallInteger used in image to identify a host window structure */ } sqInputEvent; /* mouse input event */ typedef struct sqMouseEvent { int type; /* EventTypeMouse */ unsigned int timeStamp; /* time stamp */ int x; /* mouse position x */ int y; /* mouse position y */ int buttons; /* combination of xxxButtonBit */ int modifiers; /* combination of xxxKeyBit */ int nrClicks; /* number of clicks in button downs - was reserved1 */ int windowIndex; /* host window structure */ } sqMouseEvent; /* keyboard input event */ typedef struct sqKeyboardEvent { int type; /* EventTypeKeyboard */ unsigned int timeStamp; /* time stamp */ int charCode; /* character code in Mac Roman encoding */ int pressCode; /* press code; any of EventKeyXXX */ int modifiers; /* combination of xxxKeyBit */ int utf32Code; /* UTF-32 unicode value */ int reserved1; /* reserved for future use */ int windowIndex; /* host window structure */ } sqKeyboardEvent; /* drop files event */ typedef struct sqDragDropFilesEvent { int type; /* EventTypeDropFiles */ unsigned int timeStamp; /* time stamp */ int dragType; /* one of DragXXX (see below) */ int x; /* mouse position x */ int y; /* mouse position y */ int modifiers; /* combination of xxxKeyBit */ int numFiles; /* number of files in transaction */ int windowIndex; /* host window structure */ } sqDragDropFilesEvent; #define DragEnter 1 /* drag operation from OS entered Squeak window */ #define DragMove 2 /* drag operation from OS moved within Squeak window */ #define DragLeave 3 /* drag operation from OS left Squeak window */ #define DragDrop 4 /* drag operation dropped contents onto Squeak. */ #define DragRequest 5 /* data request from other app. */ /* menu event */ typedef struct sqMenuEvent { int type; /* type of event; EventTypeMenu */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int menu; /* platform-dependent to indicate which menu was picked */ int menuItem; /* given a menu having 1 to N items this maps to the menu item number */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ int reserved3; /* reserved for future use */ int windowIndex; /* host window structure */ } sqMenuEvent; /* window action event */ typedef struct sqWindowEvent { int type; /* type of event; EventTypeWindow */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int action; /* one of WindowEventXXX (see below) */ int value1; /* used for rectangle edges */ int value2; /* used for rectangle edges */ int value3; /* used for rectangle edges */ int value4; /* used for rectangle edges */ int windowIndex; /* host window structure */ } sqWindowEvent; #define WindowEventMetricChange 1 /* size or position of window changed - value1-4 are left/top/right/bottom values */ #define WindowEventClose 2 /* window close icon pressed */ #define WindowEventIconise 3 /* window iconised or hidden etc */ #define WindowEventActivated 4 /* window made active - some platforms only - do not rely upon this */ #define WindowEventPaint 5 /* window area (in value1-4) needs updating. Some platforms do not need to send this, do not rely on it in image */ #define WindowEventStinks 6 /* this window stinks (just to see if people read this stuff) */ typedef struct sqComplexEvent { int type; /* type of event; EventTypeComplex */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int action; /* one of ComplexEventXXX (see below) */ usqInt objectPointer; /* used to point to object */ int unused1; /* */ int unused2; /* */ int unused3; /* */ int windowIndex; /* host window structure */ } sqComplexEvent; #define ComplexEventTypeTouchsDown 1 /* */ #define ComplexEventTypeTouchsUp 2 /* */ #define ComplexEventTypeTouchsMoved 3 /* */ #define ComplexEventTypeTouchsStationary 4 /* */ #define ComplexEventTypeTouchsCancelled 5 /* */ #define ComplexEventTypeAccelerationData 6 /* */ #define ComplexEventTypeLocationData 7 /* */ #define ComplexEventTypeApplicationData 8 /* */ /* Set an asynchronous input semaphore index for events. */ sqInt ioSetInputSemaphore(sqInt semaIndex); /* Retrieve the next input event from the OS. */ sqInt ioGetNextEvent(sqInputEvent *evt); /* Image file and VM path names. */ extern char imageName[]; char *getImageName(void); sqInt imageNameGetLength(sqInt sqImageNameIndex, sqInt length); sqInt imageNamePutLength(sqInt sqImageNameIndex, sqInt length); sqInt imageNameSize(void); sqInt vmPathSize(void); sqInt vmPathGetLength(sqInt sqVMPathIndex, sqInt length); char* ioGetLogDirectory(void); char* ioGetWindowLabel(void); /* Image security traps. */ sqInt ioCanRenameImage(void); sqInt ioCanWriteImage(void); sqInt ioDisableImageWrite(void); /* Save/restore. */ /* Read the image from the given file starting at the given image offset */ sqInt readImageFromFileHeapSizeStartingAt(sqImageFile f, usqInt desiredHeapSize, squeakFileOffsetType imageOffset); /* Clipboard (cut/copy/paste). */ sqInt clipboardSize(void); sqInt clipboardReadIntoAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex); sqInt clipboardWriteFromAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex); /* Interpreter entry points needed by compiled primitives. */ void *arrayValueOf(sqInt arrayOop); sqInt checkedIntegerValueOf(sqInt intOop); void *fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer); double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer); double floatValueOf(sqInt floatOop); sqInt pop(sqInt nItems); sqInt pushInteger(sqInt integerValue); sqInt sizeOfSTArrayFromCPrimitive(void *cPtr); sqInt storeIntegerofObjectwithValue(sqInt fieldIndex, sqInt objectPointer, sqInt integerValue); /* System attributes. */ sqInt attributeSize(sqInt indexNumber); sqInt getAttributeIntoLength(sqInt indexNumber, sqInt byteArrayIndex, sqInt length); /*** Pluggable primitive support. ***/ /* NOTE: The following functions are those implemented by sqNamedPrims.c */ void *ioLoadExternalFunctionOfLengthFromModuleOfLength(sqInt functionNameIndex, sqInt functionNameLength, sqInt moduleNameIndex, sqInt moduleNameLength); sqInt ioUnloadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength); void *ioLoadFunctionFrom(const char *functionName, const char *pluginName); sqInt ioShutdownAllModules(void); sqInt ioUnloadModule(const char *moduleName); sqInt ioUnloadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength); char *ioListBuiltinModule(sqInt moduleIndex); char *ioListLoadedModule(sqInt moduleIndex); /* The next two are FFI entries! (implemented in sqNamedPrims.c as well) */ void *ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength); void *ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionNameLength, void *moduleHandle); /* The next three functions must be implemented by sqXYZExternalPrims.c */ /* ioLoadModule: Load a module from disk. WARNING: this always loads a *new* module. Don't even attempt to find a loaded one. WARNING: never primitiveFail() within, just return 0 */ void *ioLoadModule(const char *pluginName); /* ioFindExternalFunctionIn: Find the function with the given name in the moduleHandle. WARNING: never primitiveFail() within, just return 0. */ void *ioFindExternalFunctionIn(const char *lookupName, void *moduleHandle); /* ioFreeModule: Free the module with the associated handle. WARNING: never primitiveFail() within, just return 0. */ sqInt ioFreeModule(void *moduleHandle); /* The Squeak version from which this interpreter was generated. */ extern const char *interpreterVersion; ================================================ FILE: vm/src/from_squeak/Cross/vm/sqAssert.h ================================================ /* * An informative assert definition that prints expression and line number. * * assert's expression is evaluated only if NDEBUG is not defined and printed * along with its the line number if it is false. * * asserta's expression is always evaluated but only printed if it is false and * NDEBUG is not defined. (asserta => assert always) * * assertf's message is printed along with its line number if NDEBUG is not * defined. (assertfd => assert fail) */ extern void warning(char *); #ifdef NDEBUG /* compatible with Mac OS X (FreeBSD) /usr/include/assert.h */ # undef assert # define assert(expr) 0 /* hack disabling of asserts. Better in makefile? */ # define asserta(expr) (expr) # define assertf(msg) 0 # define PRODUCTION 1 #elif 1 # undef assert # define __stringify(foo) #foo # define __stringifyNum(n) __stringify(n) # define assert(expr) ((expr)||(warning(#expr " " __stringifyNum(__LINE__)),0)) # define asserta(expr) ((expr)||(warning(#expr " " __stringifyNum(__LINE__)),0)) # define assertf(msg) (warning(#msg " " __stringifyNum(__LINE__)),0) # define PRODUCTION 0 #endif #define halt() warning("halt") ================================================ FILE: vm/src/from_squeak/Cross/vm/sqAtomicOps.h ================================================ /**************************************************************************** * PROJECT: Atomic operations for multi-threading. * Atomic reads and writes of 64-bit values (e.g. for 64-bit clock). * Atomic 32-bit increment (e.g. for signalSemaphoreWithIndex:). * get64(sqLong variable) * set64(sqLong variable, sqLong value) * sqAtomicAddConst(var,n) * sqCompareAndSwap(var,old,new) * FILE: sqAtomicOps.h * * AUTHOR: Eliot Miranda * EMAIL: eliot@teleplace.com * *****************************************************************************/ /* Atomic access to 64-bit values allows variables to be updated safely by * interrupts on 32-bit systems without using locks. This is used e.g. by * the heartbeat as it updates the 64-bit microsecond clocks. * * Re LP32 ILP32 LP64 ILP64 & LLP64 * These are convenient names for different C programming models. See e.g. * http://www.unix.org/version2/whatsnew/lp64_wp.html. LP32 et al are models in * which the basic word size is 32-bits and LP64 et al are models in which the * basic word size is 64-bits. gcc defines these. Other compilers may not. * Here we assume that if either LP32 or ILP32 are defined as 1 then special * effort is required to access a 64-bit datum atomically. * * Only some compilers define LP32 et al. If not, and __LONG_MAX__ is defined * we can make a good guess that __LONG_MAX__ implies 32-bits or 64-bits. */ #if defined(__LONG_MAX__) && !defined(LP32) && !defined(ILP32) \ && !defined(LP64) && !defined(ILP64) && !defined(LLP64) # if __LONG_MAX__ > 0xFFFFFFFF # define LP64 1 # else # define LP32 1 # endif #endif #if LP64 || ILP64 || LLP64 /* On 64-bit systems 64-bit access is automatic by default. */ # define get64(variable) variable # define set64(variable,value) (variable = value) #elif LP32 || ILP32 # if TARGET_OS_IS_IPHONE static inline void AtomicSet(uint64_t *target, uint64_t new_value) { while (true) { uint64_t old_value = *target; if (OSAtomicCompareAndSwap64Barrier(old_value, new_value, target)) return; } } static inline uint64_t AtomicGet(uint64_t *target) { while (true) { int64 value = *target; if (OSAtomicCompareAndSwap64Barrier(value, value, target)) return value; } } # define get64(variable) AtomicGet(&(variable)) # define set64(variable,value) AtomicSet(&(variable),value) /* Currently we provide definitions for x86 and GCC only. But see below. */ # elif defined(__GNUC__) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_)) /* atomic read & write of 64-bit values using SSE2 movq to/from sse register. * 64-bit reads & writes are only guaranteed to be atomic if aligned on a 64-bit * boundary. Since 64-bit globals are so aligned a global access is atomic. */ # if __SSE2__ /* atomic read & write of 64-bit values using sse instructions. */ # define get64(variable) \ ({ long long result; \ asm volatile ("movq %1, %%xmm7; movq %%xmm7, %0"\ : "=m" (result) \ : "m" (variable) \ : "memory", "%xmm7"); \ result;}) # define set64(variable,value) \ asm volatile ("movq %1, %%xmm7; movq %%xmm7, %0"\ : "=m" (variable) \ : "m" (value) \ : "memory", "%xmm7") # else /* __SSE2__ */ /* atomic read & write of 64-bit values using the CMPXCHG8B instruction. * CMPXCHG8B m64 compares EDX:EAX with m64 and if equal loads ECX:EBX into m64. * If different it loads m64 into EDX:EAX. * Thanks to Frank http://www.exit.com/blog/archives/000361.html. * * Note that we could simply use movq which is guaranteed to provide atomic * reading or writing of 64-bit values aligned on a 64-bit boundary. But we * can only depend on global variables being correctly aligned on systems * such as Mac OS X, which aligns the stack on a 128-bit boundary. */ # include "sqAssert.h" # define lo32(x) (*(((unsigned long *)&(x))+0)) # define hi32(x) (*(((unsigned long *)&(x))+1)) # define get64(variable) \ ({ long long result; \ assert((variable) != 0); \ asm volatile ( "xorl %%eax, %%eax\n\t" \ "xorl %%edx, %%edx\n\t" \ "xorl %%ebx, %%ebx\n\t" \ "xorl %%ecx, %%ecx\n\t" \ "lock cmpxchg8b %2\n\t" \ "movl %%eax, %0\n\t" \ "movl %%edx, %1" \ : "=m" (lo32(result)), "=m" (hi32(result)) \ : "o" (variable) \ : "memory", "eax", "ebx", "ecx", "edx", "cc"); \ result;}) # define set64(variable,value) \ asm volatile ( "movl %0, %%eax\n\t" \ "movl %1, %%edx\n\t" \ "movl %2, %%ebx\n\t" \ "movl %3, %%ecx\n\t" \ "lock cmpxchg8b %0" \ : "+m" (lo32(variable)), "+m" (hi32(variable)) \ : "m" (lo32(value)), "m" (hi32(value)) \ : "memory", "eax", "ebx", "ecx", "edx", "cc") # endif /* __SSE2__ */ # else /* TARGET_OS_IS_IPHONE elif x86 variants etc */ /* Dear implementor, you have choices. For example consider defining get64 & * set64 thusly * #define get64(var) read64(&(var)) * #define set64(var,val) write64(&(var),val) * and get the JIT to generate read64 & write64 above atomic 64-bit read/write. */ # error atomic access of 64-bit variables not yet defined for this platform # endif #else /* LP32 || ILP32 else LP64 || ILP64 || LLP64 */ # error shurly shome mishtake; too drunk to shpot the programming muddle. hic. #endif /* Atomic increment of 32-bit values allows a lock-free implementation of the * request side of signalSemaphoreWithIndex: */ /* Currently we provide definitions for x86 and GCC only. */ #if defined(__GNUC__) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_)) #ifdef TARGET_OS_IS_IPHONE #define sqAtomicAddConst(var,n) OSAtomicAdd32(n,&var) #else # define sqAtomicAddConst(var,n) \ asm volatile ("lock addl %1, %0" : "=m" (var) : "i" (n), "m" (var)) #endif #else #ifdef TARGET_OS_IS_IPHONE #define sqAtomicAddConst(var,n) OSAtomicAdd32(n,&var) #endif /* Dear implementor, you have choices. Google atomic increment and you will * find a number of implementations for other architectures. */ #endif /* Atomic compare and swap of 32-bit values allows a lock-free implementation of * the request side of signalSemaphoreWithIndex: using tides to limit the range * of indices examined. * * sqCompareAndSwap(var,old,new) arranges atomically that if var's value is * equal to old, then var's is set to new. * * sqCompareAndSwapRes(var,old,new,res) arranges atomically that if var's value * is equal to old, then var's value is set to new, and that in any case, res * is set to the previous value of var. */ /* Currently we provide definitions for x86 and GCC only. */ #if defined(__GNUC__) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_)) #ifdef TARGET_OS_IS_IPHONE # define sqCompareAndSwap(var,old,new) OSAtomicCompareAndSwap32(old, new, &var) # define sqCompareAndSwapRes(var,old,new,res) res = var; OSAtomicCompareAndSwap32(old, new, &var) #else # define sqCompareAndSwap(var,old,new) \ asm volatile ("movl %1, %%eax; lock cmpxchg %2, %0" \ : "=m"(var) \ : "g"(old), "r"(new), "m"(var)\ : "memory", "%eax") # define sqCompareAndSwapRes(var,old,new,res) \ asm volatile ("movl %2, %%eax; lock cmpxchg %3, %0; movl %%eax, %1" \ : "=m"(var), "=g"(res) \ : "g"(old), "r"(new), "m"(var) \ : "memory", "%eax") #endif #else #if TARGET_OS_IS_IPHONE # define sqCompareAndSwap(var,old,new) OSAtomicCompareAndSwap32(old, new, &var) # define sqCompareAndSwapRes(var,old,new,res) res = var; OSAtomicCompareAndSwap32(old, new, &var) #endif /* Dear implementor, you have choices. Google atomic increment and you will * find a number of implementations for other architectures. */ #endif ================================================ FILE: vm/src/from_squeak/Cross/vm/sqCogStackAlignment.h ================================================ /**************************************************************************** * FILE: sqCogUnixStackAlignment.h * CONTENT: Answer & check stack alignment for current plaform * * AUTHOR: Eliot Miranda * DATE: February 2009 * * Changes: eem Wed Jul 14 17:11:01 PDT 2010 * make 16 bytes the default alignment for all x86. */ /* 16-byte stack alignment on x86 is required for SSE instructions which * insist on aligned addresses for accessing 64 or 128 bit values in memory. */ #if __i386__ && (__SSE2__ || __APPLE__ && __MACH__ || __linux__) # define STACK_ALIGN_BYTES 16 # define LEAF_CALL_STACK_ALIGN_BYTES 12 # define STACK_FP_ALIGN_BYTES 8 #endif #if defined(STACK_ALIGN_BYTES) # if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) # if __GNUC__ # define getfp() ({ register unsigned long fp; \ asm volatile ("movl %%ebp,%0" : "=r"(fp) : ); \ fp; }) # else extern unsigned long getfp(); # endif # else # error define code for your processor here # endif extern unsigned long (*ceGetSP)(); /* provided by Cogit */ # define STACK_ALIGN_MASK (STACK_ALIGN_BYTES-1) # define assertCStackWellAligned() do { \ extern sqInt cFramePointerInUse; \ if (cFramePointerInUse) \ assert((getfp() & STACK_ALIGN_MASK) == STACK_FP_ALIGN_BYTES); \ assert((ceGetSP() & STACK_ALIGN_MASK) == LEAF_CALL_STACK_ALIGN_BYTES); \ } while (0) #else /* defined(STACK_ALIGN_BYTES) */ # define STACK_ALIGN_BYTES 4 # define assertCStackWellAligned() 0 #endif /* defined(STACK_ALIGN_BYTES) */ ================================================ FILE: vm/src/from_squeak/Cross/vm/sqExternalSemaphores.c ================================================ /* sqExternalSemaphores.c * Cross-platform thread-safe external semaphore signalling. * * Authors: Eliot Miranda & Brad Fowlow * * Copyright (C) 2009 by Teleplace, Inc. * * All rights reserved. * * This file is part of Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "sq.h" #include "sqAssert.h" #include "sqAtomicOps.h" #include "sqMemoryFence.h" /* This implements "lock-free" signalling of external semaphores where there is * no lock between the signal responder (the VM) and signal requestors, but * there may be spin-locking between signal requestors, depending on the implem- * entation of atomicAddConst. * * Freedom from locks is very helpful in making the QAudioPlugin function on * linux, where the absence of thread priorities for non-setuid programs means * we cannot run the QAudioPlugin's ticker in a separate thread and must instead * derive it from the interval-timer based signal-driven (software interrupt) * heartbeat. If the external semaphore state is locked while the VM is * responding to external semaphore signal requests and the heartbeat interrupts * causing a locking request for an external semaphore signal request then the * system will deadlock, since the interrupt occurs in the VM thread. * * Lock freedom is achieved by having an array of request counters, and an array * of response counters, one per external semaphore index. To request a signal * the requests are locked and the relevant request is incremented. To respond * to a request the VM increments the corresponding response until it matches * the request, signalling the associated semaphore on each increment. */ #if !COGMTVM sqOSThread ioVMThread; /* initialized in the various /vm/sqFooMain.c */ #endif extern void forceInterruptCheck(void); extern sqInt doSignalSemaphoreWithIndex(sqInt semaIndex); typedef struct { #if !defined(TARGET_OS_IS_IPHONE) && (x86 || x86-64) /* etc etc x86 allows atomic update of 16 bit values */ short requests; short responses; #else long requests; long responses; #endif } SignalRequest; static SignalRequest *signalRequests = 0; static int numSignalRequests = 0; static volatile sqInt checkSignalRequests; /* The tides define the minimum range of indices into signalRequests that the * VM needs to scan. With potentially thousands of indices to scan this can * save significant lengths of time. */ static volatile int tideLock = 0; static volatile int useTideA = 1; static volatile sqInt lowTideA = (unsigned long)-1 >> 1, highTideA = -1; static volatile sqInt lowTideB = (unsigned long)-1 >> 1, highTideB = -1; int ioGetMaxExtSemTableSize(void) { return numSignalRequests; } /* Setting this at any time other than start-up can potentially lose requests. * i.e. during the realloc new storage is allocated, the old contents are copied * and then pointersd are switched. Requests occurring during copying won't * be seen if they occur to indices already copied. * We could make this safer in the linux case by disabling interrupts, but * there is little point. The intended use is to set the table to some adequate * maximum at start-up and avoid locking altogether. */ void ioSetMaxExtSemTableSize(int n) { #if COGMTVM if (getVMOSThread()) /* initialization is a little different in MT. Hack around for now */ #endif assert(ioOSThreadsEqual(ioCurrentOSThread(),getVMOSThread())); if (numSignalRequests < n) { extern sqInt highBit(sqInt); int sz = 1 << highBit(n); signalRequests = realloc(signalRequests, sz * sizeof(SignalRequest)); memset(signalRequests + numSignalRequests, 0, (sz - numSignalRequests) * sizeof(SignalRequest)); numSignalRequests = sz; } } void ioInitExternalSemaphores(void) { ioSetMaxExtSemTableSize(INITIAL_EXT_SEM_TABLE_SIZE); } /* Signal the external semaphore with the given index. Answer non-zero on * success, zero otherwise. This function is (should be) thread-safe; * multiple threads may attempt to signal the same semaphore without error. * An index of zero should be and is silently ignored. */ sqInt signalSemaphoreWithIndex(sqInt index) { int i = index - 1; int v; /* An index of zero should be and is silently ignored. */ assert(index >= 0 && index <= numSignalRequests); if ((unsigned)i >= numSignalRequests) return 0; sqLowLevelMFence(); sqAtomicAddConst(signalRequests[i].requests,1); if (useTideA) { /* atomic if (lowTideA > i) lowTideA = i; */ while ((v = lowTideA) > i) { sqLowLevelMFence(); sqCompareAndSwap(lowTideA, v, i); } /* atomic if (highTideA < i) highTideA = i; */ while ((v = highTideA) < i) { sqLowLevelMFence(); sqCompareAndSwap(highTideA, v, i); } } else { /* atomic if (lowTideB > i) lowTideB = i; */ while ((v = lowTideB) > i) { sqLowLevelMFence(); sqCompareAndSwap(lowTideB, v, i); } /* atomic if (highTideB < i) highTideB = i; */ while ((v = highTideB) < i) { sqLowLevelMFence(); sqCompareAndSwap(highTideB, v, i); } } checkSignalRequests = 1; forceInterruptCheck(); return 1; } /* Signal any external semaphores for which signal requests exist. * Answer whether a context switch occurred. * Note we no longer ensure the lock table has at least minTableSize elements. * Instead its size is settable at startup from a value in the image header via * ioSetMaxExtSemTableSize. This avoids locks on the table while it grows * (although a lock-free implementation is possible, if tricky). So for the * moment externalSemaphoreTableSize is not used. */ sqInt doSignalExternalSemaphores(int externalSemaphoreTableSize) { int i, switched; if (!checkSignalRequests) return 0; switched = 0; checkSignalRequests = 0; if (useTideA) { useTideA = 0; sqLowLevelMFence(); /* doing this here saves a bounds check in doSignalSemaphoreWithIndex */ if (highTideA >= externalSemaphoreTableSize) highTideA = externalSemaphoreTableSize - 1; for (i = lowTideA; i <= highTideA; i++) while (signalRequests[i].responses != signalRequests[i].requests) { if (doSignalSemaphoreWithIndex(i+1)) switched = 1; ++signalRequests[i].responses; } lowTideA = (unsigned long)-1 >> 1, highTideA = -1; } else { useTideA = 1; sqLowLevelMFence(); /* doing this here saves a bounds check in doSignalSemaphoreWithIndex */ if (highTideB >= externalSemaphoreTableSize) highTideB = externalSemaphoreTableSize - 1; for (i = lowTideB; i <= highTideB; i++) while (signalRequests[i].responses != signalRequests[i].requests) { if (doSignalSemaphoreWithIndex(i+1)) switched = 1; ++signalRequests[i].responses; } lowTideB = (unsigned long)-1 >> 1, highTideB = -1; } /* If a signal came in while processing, check for signals again soon. */ sqLowLevelMFence(); if (checkSignalRequests) forceInterruptCheck(); return switched; } #if FOR_SQUEAK_VM_TESTS /* see e.g. tests/sqExternalSemaphores/unixmain.c */ int allRequestsAreAnswered(int externalSemaphoreTableSize) { long i; for (i = 1; i < externalSemaphoreTableSize; i++) if (signalRequests[i].responses != signalRequests[i].requests) { printf("signalRequests[%ld] requests %d responses %d\n", i, signalRequests[i].requests, signalRequests[i].responses); return 0; } return 1; } #endif /* FOR_SQUEAK_VM_TESTS */ ================================================ FILE: vm/src/from_squeak/Cross/vm/sqHeapMap.c ================================================ /**************************************************************************** * PROJECT: Maintain a heap map for heap debugging, 1 bit per 32-bit word * The space overhead is a maximum of 1/32 of the address space. * FILE: sqHeapMap.c * CONTENT: * * AUTHOR: Eliot Miranda * ADDRESS: * EMAIL: eliot.miranda@gmail.com * * NOTES: The idea is to check for heap pointer integrity. We scan the heap * setting a bit in the map for each object's base header. We then * scan the heap checking that each pointer points to a base header by * checking for a 1 in the heap map. * * We can also check for leaks by scanning a third time and clearing * the header bit. Any remaining set bits indicate an unreferenced * object that should have been collected. * ****************************************************************************/ #include "sqMemoryAccess.h" #include #define ulong unsigned long #define uchar unsigned char #if SQ_IMAGE32 /* * 32-bit address space = 2^32 bytes = 2^30 words. If we have 256 root pages * then each page needs to cover 2^30 / 256 words = 4 megawords. Each 8-bit * byte in the leak map covers 8 words. So each page needs to be 4M / 8 bytes * = 512k bytes per page. */ #define NUMPAGES 256 static uchar *mapPages[256] = { 0, }; #define PAGESIZE (512*1024) #define PAGESHIFT 24 #define PAGEMASK 0xFFFFFF #define LOGWORDSIZE 2 #define LOGBITSPERBYTE 3 #define PAGEINDEX(a) ((a) >> PAGESHIFT) #define BYTEINDEX(a) (((a) & PAGEMASK) >> (LOGWORDSIZE + LOGBITSPERBYTE)) #define BITINDEX(a) (((a) >> LOGWORDSIZE) & ((1< #if defined(HAVE_INTERP_H) # include "interp.h" #else # define SQ_VI_BYTES_PER_WORD 4 /* build a 32-bit VM */ # warning # warning *************************************************** # warning * # warning * interp.h not found -- defaulting to a 32-bit VM # warning * # warning * update your image-side VM sources to the latest # warning * version to avoid this message # warning * # warning *************************************************** # warning #endif #if (SQ_VI_BYTES_PER_WORD == 4) # define SQ_IMAGE32 1 #else # define SQ_IMAGE64 1 #endif #if (SIZEOF_VOID_P == 4) # define SQ_HOST32 1 #elif (SIZEOF_VOID_P == 8) # define SQ_HOST64 1 #else # error host is neither 32- nor 64-bit? #endif #if defined(SQ_IMAGE32) typedef int sqInt; typedef unsigned int usqInt; #elif defined(SQ_HOST64) typedef long sqInt; typedef unsigned long usqInt; #else # if (SIZEOF_LONG_LONG != 8) # error long long integers are not 64-bits wide? # endif typedef long long sqInt; typedef unsigned long long usqInt; #endif #if defined(SQ_HOST64) && defined(SQ_IMAGE32) extern char *sqMemoryBase; # define SQ_FAKE_MEMORY_OFFSET 16 // (1*1024*1024) /* nonzero to debug addr xlation */ #else # define sqMemoryBase 0 #endif #ifdef USE_INLINE_MEMORY_ACCESSORS /* Use static inline functions when the compiler produces efficient code for small accessors. These are preferred because static type checking will prevent inadvertent confusion of pointers and oops. */ static inline sqInt byteAtPointer(char *ptr) { return (sqInt)(*((unsigned char *)ptr)); } static inline sqInt byteAtPointerput(char *ptr, int val) { return (sqInt)(*((unsigned char *)ptr)= (unsigned char)val); } static inline sqInt shortAtPointer(char *ptr) { return (sqInt)(*((short *)ptr)); } static inline sqInt shortAtPointerput(char *ptr, int val) { return (sqInt)(*((short *)ptr)= (short)val); } static inline sqInt intAtPointer(char *ptr) { return (sqInt)(*((unsigned int *)ptr)); } static inline sqInt intAtPointerput(char *ptr, int val) { return (sqInt)(*((unsigned int *)ptr)= (int)val); } static inline sqInt longAtPointer(char *ptr) { return *(sqInt *)ptr; } static inline sqInt longAtPointerput(char *ptr, sqInt val) { return *(sqInt *)ptr= (sqInt)val; } static inline sqInt oopAtPointer(char *ptr) { return *(sqInt *)ptr; } static inline sqInt oopAtPointerput(char *ptr, sqInt val) { return (sqInt)(*(sqInt *)ptr= (sqInt)val); } # ifdef ROAR_VM extern char *pointerForOop(sqInt oop); // xxx_dmu Renaissance extern sqInt oopForPointer(void *ptr); // xxx_dmu Renaissance # else # if defined(sqMemoryBase) && !sqMemoryBase static inline char *pointerForOop(usqInt oop) { return (char *)oop; } static inline sqInt oopForPointer(char *ptr) { return (sqInt)ptr; } # else static inline char *pointerForOop(usqInt oop) { return sqMemoryBase + oop; } static inline sqInt oopForPointer(char *ptr) { return (sqInt)(ptr - sqMemoryBase); } # endif # endif // ROAR_VM static inline sqInt byteAt(sqInt oop) { return byteAtPointer(pointerForOop(oop)); } static inline sqInt byteAtput(sqInt oop, int val) { return byteAtPointerput(pointerForOop(oop), val); } static inline sqInt shortAt(sqInt oop) { return shortAtPointer(pointerForOop(oop)); } static inline sqInt shortAtput(sqInt oop, int val) { return shortAtPointerput(pointerForOop(oop), val); } static inline sqInt intAt(sqInt oop) { return intAtPointer(pointerForOop(oop)); } static inline sqInt intAtput(sqInt oop, int val) { return intAtPointerput(pointerForOop(oop), val); } static inline sqInt longAt(sqInt oop) { return longAtPointer(pointerForOop(oop)); } static inline sqInt longAtput(sqInt oop, sqInt val) { return longAtPointerput(pointerForOop(oop), val); } static inline sqInt oopAt(sqInt oop) { return oopAtPointer(pointerForOop(oop)); } static inline sqInt oopAtput(sqInt oop, sqInt val) { return oopAtPointerput(pointerForOop(oop), val); } #else # ifdef ROAR_VM # error Use the other ones for the RVM/RoarVM # endif /* Use macros when static inline functions aren't efficient. */ # define byteAtPointer(ptr) ((sqInt)(*((unsigned char *)(ptr)))) # define byteAtPointerput(ptr, val) ((sqInt)(*((unsigned char *)(ptr))= (unsigned char)(val))) # define shortAtPointer(ptr) ((sqInt)(*((short *)(ptr)))) # define shortAtPointerput(ptr, val) ((sqInt)(*((short *)(ptr))= (short)(val))) # define intAtPointer(ptr) ((sqInt)(*((int *)(ptr)))) # define intAtPointerput(ptr, val) ((sqInt)(*((int *)(ptr))= (int)(val))) # define longAtPointer(ptr) (*(sqInt *)(ptr)) # define longAtPointerput(ptr, val) (*(sqInt *)(ptr)= (sqInt)(val)) # define oopAtPointer(ptr) (*(sqInt *)(ptr)) # define oopAtPointerput(ptr, val) (*(sqInt *)(ptr)= (sqInt)(val)) # if defined(sqMemoryBase) && !sqMemoryBase # define pointerForOop(oop) ((char *)(oop)) # define oopForPointer(ptr) ((sqInt)(ptr)) # else # define pointerForOop(oop) ((char *)(sqMemoryBase + ((usqInt)(oop)))) # define oopForPointer(ptr) ((sqInt)(((char *)(ptr)) - (sqMemoryBase))) # endif # define byteAt(oop) byteAtPointer(pointerForOop(oop)) # define byteAtput(oop, val) byteAtPointerput(pointerForOop(oop), (val)) # define shortAt(oop) shortAtPointer(pointerForOop(oop)) # define shortAtput(oop, val) shortAtPointerput(pointerForOop(oop), (val)) # define longAt(oop) longAtPointer(pointerForOop(oop)) # define longAtput(oop, val) longAtPointerput(pointerForOop(oop), (val)) # define intAt(oop) intAtPointer(pointerForOop(oop)) # define intAtput(oop, val) intAtPointerput(pointerForOop(oop), (val)) # define oopAt(oop) oopAtPointer(pointerForOop(oop)) # define oopAtput(oop, val) oopAtPointerput(pointerForOop(oop), (val)) #endif #define long32At intAt #define long32Atput intAtput # ifdef ROAR_VM #define long32AtPointer intAtPointer // xxx_dmu #define long32AtPointerput intAtPointerput // xxx_dmu # endif // ROAR_VM /* platform-dependent float conversion macros */ /* Note: Second argument must be a variable name, not an expression! */ #if defined(DOUBLE_WORD_ALIGNMENT) /* this is to allow strict aliasing assumption in the optimizer */ typedef union { double d; int i[sizeof(double) / sizeof(int)]; } _aligner; /* word-based copy for machines with alignment restrictions */ # define storeFloatAtPointerfrom(intPointerToFloat, doubleVar) do { \ *((int *)(intPointerToFloat) + 0) = ((_aligner *)(&doubleVar))->i[0]; \ *((int *)(intPointerToFloat) + 1) = ((_aligner *)(&doubleVar))->i[1]; \ } while (0) # define fetchFloatAtPointerinto(intPointerToFloat, doubleVar) do { \ ((_aligner *)(&doubleVar))->i[0] = *((int *)(intPointerToFloat) + 0); \ ((_aligner *)(&doubleVar))->i[1] = *((int *)(intPointerToFloat) + 1); \ } while (0) #else /* !DOUBLE_WORD_ALIGNMENT */ /* for machines that allow doubles to be on any word boundary */ # define storeFloatAtPointerfrom(i, doubleVar) (*((double *) (i)) = (doubleVar)) # define fetchFloatAtPointerinto(i, doubleVar) ((doubleVar) = *((double *) (i))) #endif #define storeFloatAtfrom(i, doubleVar) storeFloatAtPointerfrom(pointerForOop(i), doubleVar) #define fetchFloatAtinto(i, doubleVar) fetchFloatAtPointerinto(pointerForOop(i), doubleVar) # define storeSingleFloatAtPointerfrom(i, floatVar) (*((float *) (i)) = (float)(floatVar)) # define fetchSingleFloatAtPointerinto(i, floatVar) ((floatVar) = *((float *) (i))) #define storeSingleFloatAtfrom(i, floatVar) storeSingleFloatAtPointerfrom(pointerForOop(i), floatVar) #define fetchSingleFloatAtinto(i, floatVar) fetchSingleFloatAtPointerinto(pointerForOop(i), floatVar) /* This doesn't belong here, but neither do 'self flag: ...'s belong in the image. */ #ifdef _MSC_VER static void flag(char *ignored) {} #else static inline void flag(char *ignored) {} #endif /* heap debugging facilities in sqHeapMap.c */ extern void clearHeapMap(void); extern int heapMapAtWord(void *wordPointer); extern void heapMapAtWordPut(void *wordPointer, int bit); #endif /* __sqMemoryAccess_h */ ================================================ FILE: vm/src/from_squeak/Cross/vm/sqMemoryFence.h ================================================ /* sqMemoryFence.h * Support for synchronisation above weakly-ordered memory models. * * Author: Eliot Miranda * * Copyright (C) 2010 by Teleplace, Inc. * * All rights reserved. * * This file is part of Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* sqLowLevelMFence is required to ensure that after completion any stores made * by other threads before a fence will be visible to the calling thread, and * vice versa. Writers follow a write with a fence. Readers use a fence before * reading. See e.g. http://en.wikipedia.org/wiki/Memory_barrier * * The only implementation directly uses mfence on x86. * Please add implementations for other ISAs as required. */ #if defined(__GNUC__) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_)) # if defined(__MINGW32__) && !__SSE2__ /* Andreas is fond of the gcc 2.95 MINGW but it lacks sse2 support */ # define sqLowLevelMFence() asm volatile (".byte 0x0f;.byte 0xae;.byte 0xf0") # elif defined(TARGET_OS_IS_IPHONE) # define sqLowLevelMFence() __sync_synchronize() # else # define sqLowLevelMFence() asm volatile ("mfence") # endif #else # if defined(TARGET_OS_IS_IPHONE) # define sqLowLevelMFence() __sync_synchronize() # elif !defined(sqLowLevelMFence) extern void sqLowLevelMFence(void); # endif #endif ================================================ FILE: vm/src/from_squeak/Cross/vm/sqNamedPrims.c ================================================ /**************************************************************************** * PROJECT: Squeak * FILE: sqNamedPrims.c * CONTENT: Generic (cross platform) named primitive support * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: Andreas.Raab@disney.com * RCSID: $Id: sqNamedPrims.c 2158 2010-03-29 01:16:36Z johnmci $ * * NOTES: * *****************************************************************************/ #include "sq.h" typedef struct { char *pluginName; char *primitiveName; void *primitiveAddress; } sqExport; #include "sqNamedPrims.h" #undef DEBUG #undef DPRINTF #ifdef DEBUG #define DPRINTF(what) printf what #else #define DPRINTF(what) #endif typedef struct ModuleEntry { struct ModuleEntry *next; void *handle; sqInt ffiLoaded; char name[1]; } ModuleEntry; static ModuleEntry *squeakModule = NULL; static ModuleEntry *firstModule = NULL; struct VirtualMachine *sqGetInterpreterProxy(void); static void *findLoadedModule(const char *pluginName) { ModuleEntry *module; if(!pluginName || !pluginName[0]) return squeakModule; module = firstModule; while(module) { if(strcmp(module->name, pluginName) == 0) return module; module = module->next; } return NULL; } static ModuleEntry *addToModuleList(const char *pluginName, void* handle, sqInt ffiFlag) { ModuleEntry *module; module = (ModuleEntry*) calloc(1, sizeof(ModuleEntry) + strlen(pluginName)); strcpy(module->name, pluginName); module->handle = handle; module->ffiLoaded = ffiFlag; module->next = firstModule; firstModule = module; return firstModule; } /* removeFromList: Remove the given entry from the list of loaded modules. Do NOT free it yet. */ static sqInt removeFromList(ModuleEntry *entry) { ModuleEntry *prevModule; /* Unlink the entry from the module chain */ if(entry == firstModule) { firstModule = entry->next; } else { prevModule = firstModule; while(prevModule->next != entry) prevModule = prevModule->next; prevModule->next = entry->next; } return 1; } /* findExternalFunctionIn: Look up "pluginName_functionName" in the specified module through the OS dependent call. NEVER used to search through the internal primitive table. */ static void *findExternalFunctionIn(const char *functionName, ModuleEntry *module) { void *result; DPRINTF(("Looking (externally) for %s in %s... ", functionName,module->name)); if(module->handle) result = ioFindExternalFunctionIn(functionName, module->handle); else result = NULL; DPRINTF(("%s\n", result ? "found" : "not found")); return result; } /* findInternalFunctionIn: Lookup the given "pluginName_functionName" in the internal primitive table. If it can not be found try to look it up by using the OS dependent mechanism (see comment below). */ static void *findInternalFunctionIn(const char *functionName, const char *pluginName) { char *function, *plugin; sqInt listIndex, index; sqExport *exports; DPRINTF(("Looking (internally) for %s in %s ... ", functionName, (pluginName ? pluginName : ""))); /* canonicalize functionName and pluginName to be NULL if not specified */ if(functionName && !functionName[0]) functionName = NULL; if(pluginName && !pluginName[0]) pluginName = NULL; for(listIndex=0;; listIndex++) { exports = pluginExports[listIndex]; if(!exports) break; for(index=0;; index++) { plugin = exports[index].pluginName; function = exports[index].primitiveName; /* canonicalize plugin and function to be NULL if not specified */ if(plugin && !plugin[0]) plugin = NULL; if(function && !function[0]) function = NULL; if(!plugin && !function) break; /* At end of table. */ /* check for module name match */ if((pluginName == NULL) != (plugin == NULL)) continue; /* one is missing */ if(plugin && strcmp(pluginName, plugin)) continue; /* name mismatch */ /* check for function name match */ if((functionName == NULL) != (function == NULL)) continue; /* one is missing */ if(function && strcmp(functionName, function)) continue; /* name mismatch */ /* match */ DPRINTF(("found\n")); return exports[index].primitiveAddress; } } DPRINTF(("not found\n")); return NULL; } static void *findFunctionIn(const char *functionName, ModuleEntry *module) { if(module->handle == squeakModule->handle) return findInternalFunctionIn(functionName, module->name); else return findExternalFunctionIn(functionName, module); } /* callInitializersIn: Call the required initializers in the given module. The module has been loaded before so the task is to call a) setInterpreter() and check it's return, and b) initialiseModule (if defined) and check it's return as well. */ static sqInt callInitializersIn(ModuleEntry *module) { void *init0; void *init1; void *init2; char *moduleName; sqInt okay; init0 = findFunctionIn("getModuleName", module); init1 = findFunctionIn("setInterpreter", module); init2 = findFunctionIn("initialiseModule", module); if(init0) { /* Check the compiled name of the module */ moduleName = ((char* (*) (void))init0)(); if(!moduleName) { DPRINTF(("ERROR: getModuleName() returned NULL\n")); return 0; } if(strncmp(moduleName, module->name, strlen(module->name)) != 0) { DPRINTF(("ERROR: getModuleName returned %s (expected: %s)\n", moduleName, module->name)); return 0; } } else { /* Note: older plugins may not export the compiled module name */ DPRINTF(("WARNING: getModuleName() not found in %s\n", module->name)); } if(!init1) { DPRINTF(("ERROR: setInterpreter() not found\n")); return 0; } /* call setInterpreter */ okay = ((sqInt (*) (struct VirtualMachine*))init1)(sqGetInterpreterProxy()); if(!okay) { DPRINTF(("ERROR: setInterpreter() returned false\n")); return 0; } if(init2) { okay = ((sqInt (*) (void)) init2)(); if(!okay) { DPRINTF(("ERROR: initialiseModule() returned false\n")); return 0; } } DPRINTF(("SUCCESS: Module %s is now initialized\n", module->name)); return 1; } /* findAndLoadModule: Find the module with the given name by, * first looking it up in some (external) shared library * then, by trying to find pluginName_setInterpreter. If the module is found and the initialisers work, add it to the list of loaded modules and return the new module. If anything goes wrong make sure the module is unloaded (WITHOUT calling shutdownModule()) and return NULL. */ static int moduleLoadingEnabled = 1; /* Disable module loading mechanism for the rest of current session. This operation should be not reversable! */ void ioDisableModuleLoading() { moduleLoadingEnabled = 0; } static ModuleEntry *findAndLoadModule(const char *pluginName, sqInt ffiLoad) { void *handle; ModuleEntry *module; if (!moduleLoadingEnabled) return NULL; DPRINTF(("Looking for plugin %s\n", (pluginName ? pluginName : ""))); /* Try to load the module externally */ handle = ioLoadModule(pluginName); if(ffiLoad) { /* When dealing with the FFI, don't attempt to mess around internally */ if(!handle) return NULL; return addToModuleList(pluginName, handle, ffiLoad); } /* NOT ffiLoad */ if(!handle) { /* might be internal, so go looking for setInterpreter() */ if(findInternalFunctionIn("setInterpreter", pluginName)) handle = squeakModule->handle; else return NULL; /* PluginName_setInterpreter() not found */ } module = addToModuleList(pluginName, handle, ffiLoad); if(!callInitializersIn(module)) { /* Initializers failed */ if(handle != squeakModule->handle) { /* physically unload module */ ioFreeModule(handle); } removeFromList(module); /* remove list entry */ free(module); /* give back space */ module = NULL; } return module; } /* findOrLoadModule: Look if the given module is already loaded. If so, return it's handle, otherwise try to load it. */ static ModuleEntry *findOrLoadModule(const char *pluginName, sqInt ffiLoad) { ModuleEntry *module; if(!squeakModule) { /* Load intrinsics (if possible) */ squeakModule = addToModuleList("", NULL, 1); firstModule = NULL; /* drop off module list - will never be unloaded */ } /* see if the module was already loaded */ module = findLoadedModule(pluginName); if(!module) { /* if not try loading it */ module = findAndLoadModule(pluginName, ffiLoad); } return module; /* module not found */ } /* ioLoadFunctionFrom: Load and return the given function from the specified plugin. Return the function address if successful, otherwise 0. This entry point is called from the interpreter proxy. */ void *ioLoadFunctionFrom(const char *functionName, const char *pluginName) { ModuleEntry *module; module = findOrLoadModule(pluginName, 0); if(!module) { /* no module */ DPRINTF(("Failed to find %s (module %s was not loaded)\n", functionName, pluginName)); return 0; } if(!functionName) { /* only the module was requested but not any specific function */ return (void *)1; } /* and load the actual function */ return findFunctionIn(functionName, module); } /* ioLoadExternalFunctionOfLengthFromModuleOfLength Entry point for functions looked up through the VM. */ void *ioLoadExternalFunctionOfLengthFromModuleOfLength(sqInt functionNameIndex, sqInt functionNameLength, sqInt moduleNameIndex, sqInt moduleNameLength) { char *functionNamePointer= pointerForIndex_xxx_dmu((usqInt)functionNameIndex); char *moduleNamePointer= pointerForIndex_xxx_dmu((usqInt)moduleNameIndex); char functionName[256]; char moduleName[256]; sqInt i; if(functionNameLength > 255 || moduleNameLength > 255) return 0; /* can't cope with those */ for(i=0; i< functionNameLength; i++) functionName[i] = functionNamePointer[i]; functionName[functionNameLength] = 0; for(i=0; i< moduleNameLength; i++) moduleName[i] = moduleNamePointer[i]; moduleName[moduleNameLength] = 0; return ioLoadFunctionFrom(functionName, moduleName); } /* ioLoadSymbolOfLengthFromModule This entry point is exclusively for the FFI. */ void *ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionNameLength, void *moduleHandle) { char *functionNamePointer= pointerForIndex_xxx_dmu((usqInt)functionNameIndex); char functionName[256]; sqInt i; if(functionNameLength > 255) return 0; /* can't cope with those */ for(i=0; i< functionNameLength; i++) functionName[i] = functionNamePointer[i]; functionName[functionNameLength] = 0; if(moduleHandle) return ioFindExternalFunctionIn(functionName, moduleHandle); else return 0; } /* ioLoadModuleOfLength This entry point is exclusively for the FFI. It does *NOT* call any of the initializers nor does it attempt to lookup stuff internally. */ void *ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength) { ModuleEntry *module; char *moduleNamePointer= pointerForIndex_xxx_dmu((usqInt)moduleNameIndex); char moduleName[256]; sqInt i; if(moduleNameLength > 255) return 0; /* can't cope with those */ for(i=0; i< moduleNameLength; i++) moduleName[i] = moduleNamePointer[i]; moduleName[moduleNameLength] = 0; module = findOrLoadModule(moduleName, 1); if(module) return module->handle; return 0; } /* shutdownModule: Call the shutdown mechanism from the specified module. */ static sqInt shutdownModule(ModuleEntry *module) { void* fn; if(module->ffiLoaded) return 1; /* don't even attempt for ffi loaded modules */ /* load the actual function */ fn = findFunctionIn("shutdownModule", module); if(fn) return ((sqInt (*) (void)) fn) (); return 1; } /* ioShutdownAllModules: Call the shutdown mechanism for all loaded modules. */ sqInt ioShutdownAllModules(void) { ModuleEntry *entry; entry = firstModule; while(entry) { shutdownModule(entry); entry = entry->next; } return 1; } /* ioUnloadModule: Unload the module with the given name. */ sqInt ioUnloadModule(const char *moduleName) { ModuleEntry *entry, *temp; if(!squeakModule) return 0; /* Nothing has been loaded */ if(!moduleName || !moduleName[0]) return 0; /* nope */ entry = findLoadedModule(moduleName); if(!entry) return 1; /* module was never loaded */ /* Try to shutdown the module */ if(!shutdownModule(entry)) { /* Could not shut down the module. Bail out. */ return 0; } /* Notify all interested parties about the fact */ temp = firstModule; while(temp) { if(temp != entry) { /* Lookup moduleUnloaded: from the plugin */ void *fn = findFunctionIn("moduleUnloaded", temp); if(fn) { /* call it */ ((sqInt (*) (char *))fn)(entry->name); } } temp = temp->next; } /* And actually unload it if it isn't just the VM... */ if(entry->handle != squeakModule->handle) ioFreeModule(entry->handle); removeFromList(entry); free(entry); /* give back space */ return 1; } /* ioUnloadModuleOfLength: Entry point for the interpreter. */ sqInt ioUnloadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength) { char *moduleNamePointer= pointerForIndex_xxx_dmu((usqInt) moduleNameIndex); char moduleName[256]; sqInt i; if(moduleNameLength > 255) return 0; /* can't cope with those */ for(i=0; i< moduleNameLength; i++) moduleName[i] = moduleNamePointer[i]; moduleName[moduleNameLength] = 0; return ioUnloadModule(moduleName); } /* ioListBuiltinModule: Return the name of the n-th builtin module. */ char *ioListBuiltinModule(sqInt moduleIndex) { sqInt index, listIndex; char *function; char *plugin; sqExport *exports; for(listIndex=0;; listIndex++) { exports = pluginExports[listIndex]; if(!exports) break; for(index=0;; index++) { plugin = exports[index].pluginName; function = exports[index].primitiveName; if(!function && !plugin) break; /* no more plugins */ if(strcmp(function,"setInterpreter") == 0) { /* new module */ if(--moduleIndex == 0) { char *moduleName; void * init0; init0 = findInternalFunctionIn("getModuleName", plugin); if(init0) { /* Check the compiled name of the module */ moduleName = ((char* (*) (void))init0)(); if(moduleName) { return moduleName;} } return plugin; } } } } return NULL; } char *ioListLoadedModule(sqInt moduleIndex) { sqInt index = 1; ModuleEntry *entry; entry = firstModule; if ( moduleIndex < 1) return (char*)NULL; while(entry && index < moduleIndex) { entry = entry->next; index = index + 1; } if ( entry ) { char *moduleName; void * init0; init0 = findFunctionIn("getModuleName", entry); if(init0) { /* Check the compiled name of the module */ moduleName = ((char* (*) (void))init0)(); if(moduleName) { return moduleName;} } return entry->name; } else return (char*)NULL; } void rvm_callInitializersInAllModules() { findOrLoadModule("BitBltPlugin", 0); // xxxxxx Which other modules? } ================================================ FILE: vm/src/from_squeak/Cross/vm/sqTicker.c ================================================ /* sqTicker.c * Core cross-platform tickers. tick.er (n): one who ticks a tickee * * Authors: Eliot Miranda & Josh Gargus * * Copyright (C) 2010 by Teleplace, Inc. * * All rights reserved. * * This file is part of Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* High-priority and synchronous tickee function support. * * Tickers provide the ability to register a tickee function that will be * called at a regular interval. There are two sets of tickers. The high- * priority ticker is asynchronous and if possible, runs in a high-priority * thread or if not, from an interrupt. Running from an interrupt is undesir- * able because it is much easier to create deadlock, for example by interrupt- * ing the VM when it has acquired some lock, and a tickee tries to acquire * the same lock. But the use of an interrupt is forced on linux because as * of 2006 and the 2.6.x kernel there is no way for a non-root process to * create threads of different priorities. * * The synchronous ticker runs in the VM thread at the earliest opportunity once * the tick has occurred. The VM calls the ticker from its event check. * * This file implements the cross-platform components, registering tickers and * calling tickers if deadlines have been reached. The platform-specific heart- * beats implement the threads or interrupts and the clocks. * * For the moment the number of asynchronous and synchronous tickees is * hard-wired, but they could easily be defined by a command-line argument etc. */ #include "sq.h" #include "sqAssert.h" #include "sqAtomicOps.h" #include "sqMemoryFence.h" #define NUM_ASYNCHRONOUS_TICKEES 4 #define NUM_SYNCHRONOUS_TICKEES 4 #define MicrosecondsPerMillisecond 1000 typedef struct { void (*tickee)(void); long inProgress; /* used only in high-priority ticker */ usqLong tickeeDeadlineUsecs; usqLong tickeePeriodUsecs; } Tickee; static int numSyncTickees = 0; static Tickee synch[NUM_SYNCHRONOUS_TICKEES]; #if ITIMER_HEARTBEAT /* See platforms/unix/vm/sqUnixHeartbeat.c */ static volatile int shouldYieldToHighPriorityTickerThread; #endif /* Add or remove a synchronous tickee. If periodms is non zero add the tickee * calling it every periodms, aligned to roundms, if non-zero. If periodms is * zero, remove tickee. */ void addSynchronousTickee(void (*tickee)(void), unsigned periodms, unsigned roundms) { int i; if (!periodms) { for (i = 0; i < numSyncTickees; i++) if (synch[i].tickee == tickee) { --numSyncTickees; if (i < numSyncTickees) memmove(synch + i, synch + i + 1, sizeof(synch[i]) * (numSyncTickees - i)); return; } return; } for (i = 0; i < NUM_SYNCHRONOUS_TICKEES; i++) if (i >= numSyncTickees || !synch[i].tickee || synch[i].tickee == tickee) { synch[i].tickee = tickee; synch[i].tickeePeriodUsecs = periodms * MicrosecondsPerMillisecond; synch[i].tickeeDeadlineUsecs = synch[i].tickeePeriodUsecs + ioUTCMicroseconds(); if (roundms) { synch[i].tickeeDeadlineUsecs -= synch[i].tickeeDeadlineUsecs % (roundms * MicrosecondsPerMillisecond); if (synch[i].tickeeDeadlineUsecs < ioUTCMicroseconds()) synch[i].tickeeDeadlineUsecs += synch[i].tickeePeriodUsecs; } if (i >= numSyncTickees) ++numSyncTickees; return; } error("ran out of synchronous tickee slots"); } void ioSynchronousCheckForEvents() { int i; #if ITIMER_HEARTBEAT extern void yieldToHighPriorityTickerThread(void); sqLowLevelMFence(); if (shouldYieldToHighPriorityTickerThread) yieldToHighPriorityTickerThread(); #endif for (i = 0; i < numSyncTickees; i++) if (synch[i].tickee && ioUTCMicroseconds() >= synch[i].tickeeDeadlineUsecs) { synch[i].tickeeDeadlineUsecs += synch[i].tickeePeriodUsecs; synch[i].tickee(); } } #if !ITIMER_HEARTBEAT /* Hack; allow heartbeat to avoid */ static /* prodHighPriorityThread unless necessary */ # endif /* see platforms/unix/vm/sqUnixHeartbeat.c */ int numAsyncTickees = 0; static Tickee async[NUM_ASYNCHRONOUS_TICKEES]; /* Add or remove an asynchronous tickee. If periodms is non zero add the * tickee, calling it every periodms. * * N.B. addHighPriorityTickee is called from the VM thread, whereas * checkHighPriorityTickees is called from the high-priority heartbeat thread * (or an interrupt). The above 64-bit variables must therefore be read and * written atomically to avoid either thread reading or writing a modified * half of the variable while the other half has yet to be updated. */ void addHighPriorityTickee(void (*tickee)(void), unsigned periodms) { int i; if (!periodms) { for (i = 0; i < numAsyncTickees; i++) /* We cannot safely copy the data to keep used tickees contiguous * because checkHighPriorityTickees could be called during the move. * This implies first checking for an existing tickee below before * using an empty slot because an empty slot can be created before * a used (and subsequently modified) tickee. */ if (async[i].tickee == tickee) { async[i].tickee = 0; sqLowLevelMFence(); return; } return; } for (i = 0; i < numAsyncTickees; i++) if (async[i].tickee == tickee) break; if (i >= numAsyncTickees) for (i = 0; i < NUM_ASYNCHRONOUS_TICKEES; i++) if (i >= numAsyncTickees || !async[i].tickee) break; if (i >= NUM_ASYNCHRONOUS_TICKEES) error("ran out of asyncronous tickee slots"); /* first disable the tickee while updating the entry. */ async[i].tickee = 0; sqLowLevelMFence(); async[i].tickeePeriodUsecs = periodms * MicrosecondsPerMillisecond; async[i].tickeeDeadlineUsecs = async[i].tickeePeriodUsecs + ioUTCMicroseconds(); async[i].inProgress = 0; async[i].tickee = tickee; if (i >= numAsyncTickees) ++numAsyncTickees; sqLowLevelMFence(); } /* If the heartbeat fails to invoke checkHighPriorityTickees in a timely manner * for wahtever reason (e.g. the user has put the machine to sleep) we need to * readjust the deadline, moving it forward to a delta from the current time. * If we don't then the heartbeat will spin calling checkHighPriorityTickees as * it inches forward at tickeePeriodUsecs. But if we always base the deadline * on the current time and for whatever reason there is a slight hiccup then all * subsequent deadlines will be pushed into the future. The HiccupThreshold of * 10 seconds distinguishes between the two cases; longer than 10 seconds and we * assume the system has slept. */ #define HiccupThreshold 10000000ULL /* 10 seconds */ void checkHighPriorityTickees(usqLong utcMicrosecondClock) { int i; #if ITIMER_HEARTBEAT extern void unblockVMThreadAfterYieldToHighPriorityTickerThread(void); shouldYieldToHighPriorityTickerThread = 1; #endif /* Since this runs either in a high-priority thread or in an interrupt only * one fence is needed. Since the VM thread will not disturb any non-zero * entry (except for changing the period) we can read the entry without * locking. But we need to lock the attempt to run the tickee in case for * any reason checkHighPriorityTickees is miscalled reentrantly. */ sqLowLevelMFence(); for (i = 0; i < numAsyncTickees; i++) if (async[i].tickee && !async[i].inProgress && utcMicrosecondClock >= async[i].tickeeDeadlineUsecs) { int previousInProgress; sqCompareAndSwapRes(async[i].inProgress,0,1,previousInProgress); if (previousInProgress == 0) { assert(async[i].inProgress); if (async[i].tickeeDeadlineUsecs + HiccupThreshold < utcMicrosecondClock) async[i].tickeeDeadlineUsecs = utcMicrosecondClock + async[i].tickeePeriodUsecs; else async[i].tickeeDeadlineUsecs += async[i].tickeePeriodUsecs; async[i].tickee(); async[i].inProgress = 0; } } #if ITIMER_HEARTBEAT shouldYieldToHighPriorityTickerThread = 0; sqLowLevelMFence(); unblockVMThreadAfterYieldToHighPriorityTickerThread(); #endif } ================================================ FILE: vm/src/from_squeak/Cross/vm/sqVirtualMachine.c ================================================ #include #include #include #include #include #include #include "squeak_adapters.h" #include "sqVirtualMachine.h" /*** Function prototypes ***/ /* InterpreterProxy methodsFor: 'stack access' */ sqInt pop(sqInt nItems); sqInt popthenPush(sqInt nItems, sqInt oop); sqInt push(sqInt object); sqInt pushBool(sqInt trueOrFalse); sqInt pushFloat(double f); sqInt pushInteger(sqInt integerValue); double stackFloatValue(sqInt offset); sqInt stackIntegerValue(sqInt offset); sqInt stackObjectValue(sqInt offset); sqInt stackValue(sqInt offset); /*** variables ***/ /* InterpreterProxy methodsFor: 'object access' */ sqInt argumentCountOf(sqInt methodPointer); void *arrayValueOf(sqInt oop); sqInt byteSizeOf(sqInt oop); void *fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchClassOf(sqInt oop); double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchPointerofObject(sqInt index, sqInt oop); /* sqInt fetchWordofObject(sqInt fieldIndex, sqInt oop); * * has been rescinded as of VMMaker 3.8 and the 64bitclean VM * * work. To support old plugins we keep a valid function in * * the same location in the VM struct but rename it to * * something utterly horrible to scare off the natives. A new * * equivalent but 64 bit valid function is added as * * 'fetchLong32OfObject' */ sqInt obsoleteDontUseThisFetchWordofObject(sqInt index, sqInt oop); sqInt fetchLong32ofObject(sqInt index, sqInt oop); void *firstFixedField(sqInt oop); void *firstIndexableField(sqInt oop); sqInt literalofMethod(sqInt offset, sqInt methodPointer); sqInt literalCountOf(sqInt methodPointer); sqInt methodArgumentCount(void); sqInt methodPrimitiveIndex(void); sqInt primitiveMethod(void); sqInt primitiveIndexOf(sqInt methodPointer); sqInt sizeOfSTArrayFromCPrimitive(void *cPtr); sqInt slotSizeOf(sqInt oop); sqInt stObjectat(sqInt array, sqInt index); sqInt stObjectatput(sqInt array, sqInt index, sqInt value); sqInt stSizeOf(sqInt oop); sqInt storeIntegerofObjectwithValue(sqInt index, sqInt oop, sqInt integer); sqInt storePointerofObjectwithValue(sqInt index, sqInt oop, sqInt valuePointer); /* InterpreterProxy methodsFor: 'testing' */ sqInt isKindOf(sqInt oop, char *aString); sqInt isMemberOf(sqInt oop, char *aString); sqInt isBytes(sqInt oop); sqInt isFloatObject(sqInt oop); sqInt isIndexable(sqInt oop); sqInt isIntegerObject(sqInt objectPointer); sqInt isIntegerValue(sqInt intValue); sqInt isPointers(sqInt oop); sqInt isWeak(sqInt oop); sqInt isWords(sqInt oop); sqInt isWordsOrBytes(sqInt oop); sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperClass); #if VM_PROXY_MINOR > 10 sqInt primitiveErrorTable(void); #endif #if VM_PROXY_MINOR > 10 || defined(ROAR_VM) sqInt primitiveFailureCode(void); sqInt tenuringIncrementalGC(void); sqInt isKindOfClass(sqInt oop, sqInt aClass); sqInt instanceSizeOf(sqInt aClass); #endif sqInt isArray(sqInt oop); #if IMMUTABILITY sqInt internalIsMutable(sqInt oop); sqInt internalIsImmutable(sqInt oop); #endif /* InterpreterProxy methodsFor: 'converting' */ sqInt booleanValueOf(sqInt obj); sqInt checkedIntegerValueOf(sqInt intOop); sqInt floatObjectOf(double aFloat); double floatValueOf(sqInt oop); sqInt integerObjectOf(sqInt value); sqInt integerValueOf(sqInt oop); sqInt positive32BitIntegerFor(sqInt integerValue); sqInt positive32BitValueOf(sqInt oop); sqInt signed32BitIntegerFor(sqInt integerValue); sqInt signed32BitValueOf(sqInt oop); sqInt positive64BitIntegerFor(sqLong integerValue); sqLong positive64BitValueOf(sqInt oop); sqInt signed64BitIntegerFor(sqLong integerValue); sqLong signed64BitValueOf(sqInt oop); long signedMachineIntegerValueOf(sqInt); long stackSignedMachineIntegerValue(sqInt); unsigned long positiveMachineIntegerValueOf(sqInt); unsigned long stackPositiveMachineIntegerValue(sqInt); /* InterpreterProxy methodsFor: 'special objects' */ sqInt characterTable(void); sqInt displayObject(void); sqInt falseObject(void); sqInt nilObject(void); sqInt trueObject(void); /* InterpreterProxy methodsFor: 'special classes' */ sqInt classArray(void); sqInt classBitmap(void); sqInt classByteArray(void); sqInt classCharacter(void); sqInt classFloat(void); sqInt classLargePositiveInteger(void); sqInt classLargeNegativeInteger(void); sqInt classPoint(void); sqInt classSemaphore(void); sqInt classSmallInteger(void); sqInt classString(void); /* InterpreterProxy methodsFor: 'instance creation' */ # ifdef ROAR_VM sqInt sqr_clone(sqInt oop); # else sqInt clone(sqInt oop); # endif // ROAR_VM sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size); sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue); sqInt popRemappableOop(void); sqInt pushRemappableOop(sqInt oop); /* InterpreterProxy methodsFor: 'other' */ sqInt becomewith(sqInt array1, sqInt array2); sqInt byteSwapped(sqInt w); sqInt failed(void); sqInt fullDisplayUpdate(void); sqInt fullGC(void); sqInt incrementalGC(void); sqInt primitiveFail(void); sqInt primitiveFailFor(sqInt reasonCode); sqInt showDisplayBitsLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt signalSemaphoreWithIndex(sqInt semaIndex); sqInt success(sqInt aBoolean); sqInt superclassOf(sqInt classPointer); sqInt ioMicroMSecs(void); usqLong ioUTCMicroseconds(void); sqInt forceInterruptCheck(void); sqInt getThisSessionID(void); sqInt ioFilenamefromStringofLengthresolveAliases(char* aCharBuffer, char* filenameIndex, sqInt filenameLength, sqInt resolveFlag); sqInt vmEndianness(void); sqInt getInterruptPending(void); /* InterpreterProxy methodsFor: 'BitBlt support' */ sqInt loadBitBltFrom(sqInt bbOop); sqInt copyBits(void); sqInt copyBitsFromtoat(sqInt leftX, sqInt rightX, sqInt yValue); /* InterpreterProxy methodsFor: 'FFI support' */ sqInt classExternalAddress(void); /* Old Squeak FFI */ sqInt classExternalData(void); sqInt classExternalFunction(void); sqInt classExternalLibrary(void); sqInt classExternalStructure(void); sqInt ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength); sqInt ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionNameLength, sqInt moduleHandle); sqInt isInMemory(sqInt address); # if VM_PROXY_MINOR > 7 sqInt classUnsafeAlien(void); /* Alien FFI */ void *startOfAlienData(sqInt); usqInt sizeOfAlienData(sqInt); sqInt getStackPointer(void); /* Alien FFI */ sqInt sendInvokeCallbackStackRegistersJmpbuf(sqInt thunkPtrAsInt, sqInt stackPtrAsInt, sqInt regsPtrAsInt, sqInt jmpBufPtrAsInt); /* Alien FFI */ sqInt reestablishContextPriorToCallback(sqInt callbackContext); /* Alien FFI */ sqInt sendInvokeCallbackContext(VMCallbackContext *); sqInt returnAsThroughCallbackContext(int, VMCallbackContext *, sqInt); char *cStringOrNullFor(sqInt); # endif #if VM_PROXY_MINOR > 8 || defined(ROAR_VM) sqInt classAlien(void); /* Alien FFI */ #endif void *ioLoadFunctionFrom(const char *fnName, const char *modName); # if VM_PROXY_MINOR > 7 /* Proxy declarations for v1.8 */ sqInt callbackEnter(sqInt *callbackID); sqInt callbackLeave(sqInt callbackID); sqInt addGCRoot(sqInt *varLoc); sqInt removeGCRoot(sqInt *varLoc); /* Proxy declarations for v1.10 */ sqInt methodArg(sqInt index); sqInt objectArg(sqInt index); sqInt integerArg(sqInt index); double floatArg(sqInt index); # endif // VM_PROXY_MINOR #if VM_PROXY_MINOR > 9 || defined(ROAR_VM) sqInt topRemappableOop(void); sqInt methodReturnValue(sqInt oop); #endif struct VirtualMachine *VM = NULL; static sqInt majorVersion(void) { return VM_PROXY_MAJOR; } static sqInt minorVersion(void) { return VM_PROXY_MINOR; } #if !IMMUTABILITY static sqInt isNonIntegerObject(sqInt objectPointer) { return !isIntegerObject(objectPointer); } #endif #if STACKVM void (*setInterruptCheckChain(void (*aFunction)(void)))(); #else void (*setInterruptCheckChain(void (*aFunction)(void)))() { return 0; } #endif # if VM_PROXY_MINOR > 7 #if COGMTVM sqInt disownVM(sqInt flags); sqInt ownVM(sqInt threadIdAndFlags); #else sqInt disownVM(sqInt flags) { return 1; } sqInt ownVM(sqInt threadIdAndFlags) { extern sqInt amInVMThread(void); return amInVMThread() ? 0 : -1; } #endif # endif // VM_PROXY_MINOR extern sqInt isYoung(sqInt); /* High-priority and synchronous ticker function support. */ void addHighPriorityTickee(void (*ticker)(void), unsigned periodms); void addSynchronousTickee(void (*ticker)(void), unsigned periodms, unsigned roundms); struct VirtualMachine* sqGetInterpreterProxy(void) { if(VM) return VM; VM = (struct VirtualMachine *)calloc(1, sizeof(VirtualMachine)); /* Initialize Function pointers */ VM->majorVersion = majorVersion; VM->minorVersion = minorVersion; /* InterpreterProxy methodsFor: 'stack access' */ VM->pop = pop; VM->popthenPush = popthenPush; VM->push = push; VM->pushBool = pushBool; VM->pushFloat = pushFloat; VM->pushInteger = pushInteger; VM->stackFloatValue = stackFloatValue; VM->stackIntegerValue = stackIntegerValue; VM->stackObjectValue = stackObjectValue; VM->stackValue = stackValue; /* InterpreterProxy methodsFor: 'object access' */ VM->argumentCountOf = argumentCountOf; VM->arrayValueOf = arrayValueOf; VM->byteSizeOf = byteSizeOf; VM->fetchArrayofObject = fetchArrayofObject; VM->fetchClassOf = fetchClassOf; VM->fetchFloatofObject = fetchFloatofObject; VM->fetchIntegerofObject = fetchIntegerofObject; VM->fetchPointerofObject = fetchPointerofObject; VM->obsoleteDontUseThisFetchWordofObject = obsoleteDontUseThisFetchWordofObject; VM->firstFixedField = firstFixedField; VM->firstIndexableField = firstIndexableField; VM->literalofMethod = literalofMethod; VM->literalCountOf = literalCountOf; VM->methodArgumentCount = methodArgumentCount; VM->methodPrimitiveIndex = methodPrimitiveIndex; VM->primitiveIndexOf = primitiveIndexOf; VM->primitiveMethod = primitiveMethod; VM->sizeOfSTArrayFromCPrimitive = sizeOfSTArrayFromCPrimitive; VM->slotSizeOf = slotSizeOf; VM->stObjectat = stObjectat; VM->stObjectatput = stObjectatput; VM->stSizeOf = stSizeOf; VM->storeIntegerofObjectwithValue = storeIntegerofObjectwithValue; VM->storePointerofObjectwithValue = storePointerofObjectwithValue; /* InterpreterProxy methodsFor: 'testing' */ VM->isKindOf = isKindOf; VM->isMemberOf = isMemberOf; VM->isBytes = isBytes; VM->isFloatObject = isFloatObject; VM->isIndexable = isIndexable; VM->isIntegerObject = isIntegerObject; VM->isIntegerValue = isIntegerValue; VM->isPointers = isPointers; VM->isWeak = isWeak; VM->isWords = isWords; VM->isWordsOrBytes = isWordsOrBytes; /* InterpreterProxy methodsFor: 'converting' */ VM->booleanValueOf = booleanValueOf; VM->checkedIntegerValueOf = checkedIntegerValueOf; VM->floatObjectOf = floatObjectOf; VM->floatValueOf = floatValueOf; VM->integerObjectOf = integerObjectOf; VM->integerValueOf = integerValueOf; VM->positive32BitIntegerFor = positive32BitIntegerFor; VM->positive32BitValueOf = positive32BitValueOf; /* InterpreterProxy methodsFor: 'special objects' */ VM->characterTable = characterTable; VM->displayObject = displayObject; VM->falseObject = falseObject; VM->nilObject = nilObject; VM->trueObject = trueObject; /* InterpreterProxy methodsFor: 'special classes' */ VM->classArray = classArray; VM->classBitmap = classBitmap; VM->classByteArray = classByteArray; VM->classCharacter = classCharacter; VM->classFloat = classFloat; VM->classLargePositiveInteger = classLargePositiveInteger; VM->classPoint = classPoint; VM->classSemaphore = classSemaphore; VM->classSmallInteger = classSmallInteger; VM->classString = classString; /* InterpreterProxy methodsFor: 'instance creation' */ # ifdef ROAR_VM VM->clone = sqr_clone; # else VM->clone = clone; # endif VM->instantiateClassindexableSize = instantiateClassindexableSize; VM->makePointwithxValueyValue = makePointwithxValueyValue; VM->popRemappableOop = popRemappableOop; VM->pushRemappableOop = pushRemappableOop; /* InterpreterProxy methodsFor: 'other' */ VM->becomewith = becomewith; VM->byteSwapped = byteSwapped; VM->failed = failed; VM->fullDisplayUpdate = fullDisplayUpdate; VM->fullGC = fullGC; VM->incrementalGC = incrementalGC; VM->primitiveFail = primitiveFail; VM->showDisplayBitsLeftTopRightBottom = showDisplayBitsLeftTopRightBottom; VM->signalSemaphoreWithIndex = signalSemaphoreWithIndex; VM->success = success; VM->superclassOf = superclassOf; VM->compilerHookVector= 0; VM->setCompilerInitialized= 0; #if VM_PROXY_MINOR > 1 /* InterpreterProxy methodsFor: 'BitBlt support' */ VM->loadBitBltFrom = loadBitBltFrom; VM->copyBits = copyBits; VM->copyBitsFromtoat = copyBitsFromtoat; #endif #if VM_PROXY_MINOR > 2 /* InterpreterProxy methodsFor: 'FFI support' */ VM->classExternalAddress = classExternalAddress; VM->classExternalData = classExternalData; VM->classExternalFunction = classExternalFunction; VM->classExternalLibrary = classExternalLibrary; VM->classExternalStructure = classExternalStructure; VM->ioLoadModuleOfLength = ioLoadModuleOfLength; VM->ioLoadSymbolOfLengthFromModule = ioLoadSymbolOfLengthFromModule; VM->isInMemory = isInMemory; VM->signed32BitIntegerFor = signed32BitIntegerFor; VM->signed32BitValueOf = signed32BitValueOf; VM->includesBehaviorThatOf = includesBehaviorThatOf; VM->classLargeNegativeInteger = classLargeNegativeInteger; #endif #if VM_PROXY_MINOR > 3 VM->ioLoadFunctionFrom = ioLoadFunctionFrom; VM->ioMicroMSecs = ioMicroMSecs; #endif #if VM_PROXY_MINOR > 4 VM->positive64BitIntegerFor = positive64BitIntegerFor; VM->positive64BitValueOf = positive64BitValueOf; VM->signed64BitIntegerFor = signed64BitIntegerFor; VM->signed64BitValueOf = signed64BitValueOf; #endif #if VM_PROXY_MINOR > 5 VM->isArray = isArray; VM->forceInterruptCheck = forceInterruptCheck; #endif #if VM_PROXY_MINOR > 6 VM->fetchLong32ofObject = fetchLong32ofObject; VM->getThisSessionID = getThisSessionID; VM->ioFilenamefromStringofLengthresolveAliases = ioFilenamefromStringofLengthresolveAliases; VM->vmEndianness = vmEndianness; #endif #if VM_PROXY_MINOR > 7 VM->callbackEnter = callbackEnter; VM->callbackLeave = callbackLeave; VM->addGCRoot = addGCRoot; VM->removeGCRoot = removeGCRoot; #endif #if VM_PROXY_MINOR > 8 VM->setInterruptCheckChain = setInterruptCheckChain; VM->classUnsafeAlien = classUnsafeAlien; VM->sendInvokeCallbackStackRegistersJmpbuf = sendInvokeCallbackStackRegistersJmpbuf; VM->reestablishContextPriorToCallback = reestablishContextPriorToCallback; # if ALIEN_FFI VM->getStackPointer = 0; # endif # if IMMUTABILITY VM->internalIsImmutable = internalIsImmutable; VM->internalIsMutable = internalIsMutable; # else VM->internalIsImmutable = isIntegerObject; VM->internalIsMutable = isNonIntegerObject; # endif #endif #if VM_PROXY_MINOR > 8 || defined(ROAR_VM) VM->classAlien = classAlien; VM->primitiveFailFor = primitiveFailFor; #endif #if VM_PROXY_MINOR > 9 VM->methodArg = methodArg; VM->objectArg = objectArg; VM->integerArg = integerArg; VM->floatArg = floatArg; #endif #if VM_PROXY_MINOR > 9 || defined(ROAR_VM) VM->topRemappableOop = topRemappableOop; VM->methodReturnValue = methodReturnValue; #endif #if VM_PROXY_MINOR > 10 VM->disownVM = disownVM; VM->ownVM = ownVM; VM->addHighPriorityTickee = addHighPriorityTickee; VM->addSynchronousTickee = addSynchronousTickee; VM->utcMicroseconds = ioUTCMicroseconds; VM->isYoung = isYoung; VM->primitiveErrorTable = primitiveErrorTable; #endif #if VM_PROXY_MINOR > 10 || defined(ROAR_VM) VM->tenuringIncrementalGC = tenuringIncrementalGC; VM->primitiveFailureCode = primitiveFailureCode; VM->isKindOfClass = isKindOfClass; VM->instanceSizeOf = instanceSizeOf; #endif #if VM_PROXY_MINOR > 11 VM->sendInvokeCallbackContext = sendInvokeCallbackContext; VM->returnAsThroughCallbackContext = returnAsThroughCallbackContext; VM->signedMachineIntegerValueOf = signedMachineIntegerValueOf; VM->stackSignedMachineIntegerValue = stackSignedMachineIntegerValue; VM->positiveMachineIntegerValueOf = positiveMachineIntegerValueOf; VM->stackPositiveMachineIntegerValue = stackPositiveMachineIntegerValue; VM->getInterruptPending = getInterruptPending; VM->cStringOrNullFor = cStringOrNullFor; VM->startOfAlienData = startOfAlienData; VM->sizeOfAlienData = sizeOfAlienData; #endif return VM; } /* This lives here for now but belongs somewhere else. * platforms/Cross/vm/sqStuff.c?? */ #define STDOUT_STACK_SZ 5 static int stdoutStackIdx = -1; static FILE stdoutStack[STDOUT_STACK_SZ]; /* N.B. As of cygwin 1.5.25 fopen("crash.dmp","a") DOES NOT WORK! crash.dmp * contains garbled output as if the file pointer gets set to the start of the * file, not the end. So we synthesize our own append mode. */ #if __MINGW32__ # include static FILE * fopen_for_append(char *filename) { FILE *f = !access(filename, F_OK) /* access is bass ackwards */ ? fopen(filename,"r+") : fopen(filename,"w+"); if (f) fseek(f,0,SEEK_END); return f; } #elif defined(WIN32) # define fopen_for_append(filename) fopen(filename,"a+t") #else # define fopen_for_append(filename) fopen(filename,"a+") #endif void pushOutputFile(char *filenameOrStdioIndex) { #ifndef STDOUT_FILENO # define STDOUT_FILENO 1 # define STDERR_FILENO 2 #endif FILE *output; if (stdoutStackIdx + 2 >= STDOUT_STACK_SZ) { fprintf(stderr,"output file stack is full.\n"); return; } switch ((unsigned)filenameOrStdioIndex) { case STDOUT_FILENO: output = stdout; break; case STDERR_FILENO: output = stderr; break; default: if (!(output = fopen_for_append(filenameOrStdioIndex))) { fprintf(stderr, "could not open \"%s\" for writing.\n", filenameOrStdioIndex); return; } } stdoutStack[++stdoutStackIdx] = *stdout; *stdout = *output; } void popOutputFile() { if (stdoutStackIdx < 0) { fprintf(stderr,"output file stack is empty.\n"); return; } fflush(stdout); if (fileno(stdout) > STDERR_FILENO) { /* as of Feb 2011 with fclose@@GLIBC_2.1 under e.g. CentOS 5.3, fclose * hangs in _IO_un_link_internal. This hack avoids that. */ #if __linux__ close(fileno(stdout)); #else fclose(stdout); #endif } *stdout = stdoutStack[stdoutStackIdx--]; } ================================================ FILE: vm/src/from_squeak/Cross/vm/sqVirtualMachine.h ================================================ #ifndef _SqueakVM_H #define _SqueakVM_H # include "squeak_adapters.h" /* Increment the following number if you change the order of functions listed or if you remove functions */ #define VM_PROXY_MAJOR 1 /* Note: You can define a different VM_PROXY_MINOR if the plugin should work with older VMs. */ #ifndef VM_PROXY_MINOR /* Increment the following number if you add functions at the end */ # error The macro VM_PROXY_MINOR was not defined, it should be 7 as far as I can tell /* Increment the following number if you add functions at the end */ # define VM_PROXY_MINOR 12 #endif #include "sqMemoryAccess.h" #if VM_PROXY_MINOR > 8 # define PrimNoErr 0 # define PrimErrGenericFailure 1 # define PrimErrBadReceiver 2 # define PrimErrBadArgument 3 # define PrimErrBadIndex 4 # define PrimErrBadNumArgs 5 # define PrimErrInappropriate 6 # define PrimErrUnsupported 7 # define PrimErrNoModification 8 # define PrimErrNoMemory 9 # define PrimErrNoCMemory 10 # define PrimErrNotFound 11 # define PrimErrBadMethod 12 # define PrimErrNamedInternal 13 # define PrimErrObjectMayMove 14 /* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ typedef struct _VMCallbackContext *vmccp; #endif typedef sqInt (*CompilerHook)(); struct VirtualMachine* sqGetInterpreterProxy(void); typedef struct VirtualMachine { sqInt (*minorVersion)(void); sqInt (*majorVersion)(void); /* InterpreterProxy methodsFor: 'stack access' */ sqInt (*pop)(sqInt nItems); sqInt (*popthenPush)(sqInt nItems, sqInt oop); sqInt (*push)(sqInt object); sqInt (*pushBool)(sqInt trueOrFalse); sqInt (*pushFloat)(double f); sqInt (*pushInteger)(sqInt integerValue); double (*stackFloatValue)(sqInt offset); sqInt (*stackIntegerValue)(sqInt offset); sqInt (*stackObjectValue)(sqInt offset); sqInt (*stackValue)(sqInt offset); /* InterpreterProxy methodsFor: 'object access' */ sqInt (*argumentCountOf)(sqInt methodPointer); void *(*arrayValueOf)(sqInt oop); sqInt (*byteSizeOf)(sqInt oop); void *(*fetchArrayofObject)(sqInt fieldIndex, sqInt objectPointer); sqInt (*fetchClassOf)(sqInt oop); double (*fetchFloatofObject)(sqInt fieldIndex, sqInt objectPointer); sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer); sqInt (*fetchPointerofObject)(sqInt fieldIndex, sqInt oop); /* sqInt (*fetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); * * has been rescinded as of VMMaker 3.8 and the 64bitclean VM * * work. To support old plugins we keep a valid function in * * the same location in the VM struct but rename it to * * something utterly horrible to scare off the natives. A new * * equivalent but 64 bit valid function is added as * * 'fetchLong32OfObject' */ sqInt (*obsoleteDontUseThisFetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); void *(*firstFixedField)(sqInt oop); void *(*firstIndexableField)(sqInt oop); sqInt (*literalofMethod)(sqInt offset, sqInt methodPointer); sqInt (*literalCountOf)(sqInt methodPointer); sqInt (*methodArgumentCount)(void); sqInt (*methodPrimitiveIndex)(void); sqInt (*primitiveIndexOf)(sqInt methodPointer); sqInt (*sizeOfSTArrayFromCPrimitive)(void *cPtr); sqInt (*slotSizeOf)(sqInt oop); sqInt (*stObjectat)(sqInt array, sqInt fieldIndex); sqInt (*stObjectatput)(sqInt array, sqInt fieldIndex, sqInt value); sqInt (*stSizeOf)(sqInt oop); sqInt (*storeIntegerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt integer); sqInt (*storePointerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt valuePointer); /* InterpreterProxy methodsFor: 'testing' */ sqInt (*isKindOf)(sqInt oop, char *aString); sqInt (*isMemberOf)(sqInt oop, char *aString); sqInt (*isBytes)(sqInt oop); sqInt (*isFloatObject)(sqInt oop); sqInt (*isIndexable)(sqInt oop); sqInt (*isIntegerObject)(sqInt objectPointer); sqInt (*isIntegerValue)(sqInt intValue); sqInt (*isPointers)(sqInt oop); sqInt (*isWeak)(sqInt oop); sqInt (*isWords)(sqInt oop); sqInt (*isWordsOrBytes)(sqInt oop); /* InterpreterProxy methodsFor: 'converting' */ sqInt (*booleanValueOf)(sqInt obj); sqInt (*checkedIntegerValueOf)(sqInt intOop); sqInt (*floatObjectOf)(double aFloat); double (*floatValueOf)(sqInt oop); sqInt (*integerObjectOf)(sqInt value); sqInt (*integerValueOf)(sqInt oop); sqInt (*positive32BitIntegerFor)(sqInt integerValue); sqInt (*positive32BitValueOf)(sqInt oop); /* InterpreterProxy methodsFor: 'special objects' */ sqInt (*characterTable)(void); sqInt (*displayObject)(void); sqInt (*falseObject)(void); sqInt (*nilObject)(void); sqInt (*trueObject)(void); /* InterpreterProxy methodsFor: 'special classes' */ sqInt (*classArray)(void); sqInt (*classBitmap)(void); sqInt (*classByteArray)(void); sqInt (*classCharacter)(void); sqInt (*classFloat)(void); sqInt (*classLargePositiveInteger)(void); sqInt (*classPoint)(void); sqInt (*classSemaphore)(void); sqInt (*classSmallInteger)(void); sqInt (*classString)(void); /* InterpreterProxy methodsFor: 'instance creation' */ sqInt (*clone)(sqInt oop); sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size); sqInt (*makePointwithxValueyValue)(sqInt xValue, sqInt yValue); sqInt (*popRemappableOop)(void); sqInt (*pushRemappableOop)(sqInt oop); /* InterpreterProxy methodsFor: 'other' */ sqInt (*becomewith)(sqInt array1, sqInt array2); sqInt (*byteSwapped)(sqInt w); sqInt (*failed)(void); sqInt (*fullDisplayUpdate)(void); sqInt (*fullGC)(void); sqInt (*incrementalGC)(void); sqInt (*primitiveFail)(void); sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt (*signalSemaphoreWithIndex)(sqInt semaIndex); sqInt (*success)(sqInt aBoolean); sqInt (*superclassOf)(sqInt classPointer); /* InterpreterProxy methodsFor: 'compiler' */ CompilerHook *(*compilerHookVector)(void); sqInt (*setCompilerInitialized)(sqInt initFlag); #if VM_PROXY_MINOR > 1 /* InterpreterProxy methodsFor: 'BitBlt support' */ sqInt (*loadBitBltFrom)(sqInt bbOop); sqInt (*copyBits)(void); sqInt (*copyBitsFromtoat)(sqInt leftX, sqInt rightX, sqInt yValue); #endif #if VM_PROXY_MINOR > 2 sqInt (*classLargeNegativeInteger)(void); sqInt (*signed32BitIntegerFor)(sqInt integerValue); sqInt (*signed32BitValueOf)(sqInt oop); sqInt (*includesBehaviorThatOf)(sqInt aClass, sqInt aSuperClass); sqInt (*primitiveMethod)(void); /* InterpreterProxy methodsFor: 'FFI support' */ sqInt (*classExternalAddress)(void); sqInt (*classExternalData)(void); sqInt (*classExternalFunction)(void); sqInt (*classExternalLibrary)(void); sqInt (*classExternalStructure)(void); sqInt (*ioLoadModuleOfLength)(sqInt modIndex, sqInt modLength); sqInt (*ioLoadSymbolOfLengthFromModule)(sqInt fnIndex, sqInt fnLength, sqInt handle); sqInt (*isInMemory)(sqInt address); #endif #if VM_PROXY_MINOR > 3 void *(*ioLoadFunctionFrom)(const char *fnName, const char *modName); sqInt (*ioMicroMSecs)(void); #endif #if VM_PROXY_MINOR > 4 # if !defined(sqLong) # if _MSC_VER # define sqLong __int64 # define usqLong unsigned __int64 # else # define sqLong long long # define usqLong unsigned long long # endif # endif sqInt (*positive64BitIntegerFor)(sqLong integerValue); sqLong (*positive64BitValueOf)(sqInt oop); sqInt (*signed64BitIntegerFor)(sqLong integerValue); sqLong (*signed64BitValueOf)(sqInt oop); #endif #if VM_PROXY_MINOR > 5 sqInt (*isArray)(sqInt oop); sqInt (*forceInterruptCheck)(void); #endif #if VM_PROXY_MINOR > 6 sqInt (*fetchLong32ofObject)(sqInt fieldFieldIndex, sqInt oop); sqInt (*getThisSessionID)(void); sqInt (*ioFilenamefromStringofLengthresolveAliases)(char* aCharBuffer, char* filenameIndex, sqInt filenameLength, sqInt resolveFlag); sqInt (*vmEndianness)(void); #endif #if VM_PROXY_MINOR > 7 /* New methods for proxy version 1.8 */ /* callbackEnter: Re-enter the interpreter loop for a callback. Arguments: callbackID: Pointer to a location receiving the callback ID used in callbackLeave Returns: True if successful, false otherwise */ sqInt (*callbackEnter)(sqInt *callbackID); /* callbackLeave: Leave the interpreter from a previous callback Arguments: callbackID: The ID of the callback received from callbackEnter() Returns: True if succcessful, false otherwise. */ sqInt (*callbackLeave)(sqInt callbackID); /* addGCRoot: Add a variable location to the garbage collector. The contents of the variable location will be updated accordingly. Arguments: varLoc: Pointer to the variable location Returns: True if successful, false otherwise. */ sqInt (*addGCRoot)(sqInt *varLoc); /* removeGCRoot: Remove a variable location from the garbage collector. Arguments: varLoc: Pointer to the variable location Returns: True if successful, false otherwise. */ sqInt (*removeGCRoot)(sqInt *varLoc); #endif #if VM_PROXY_MINOR > 8 /* See interp.h and above for standard error codes. */ void (*(*setInterruptCheckChain)(void (*aFunction)(void)))(); sqInt (*classUnsafeAlien)(void); sqInt (*sendInvokeCallbackStackRegistersJmpbuf)(sqInt thunkPtrAsInt, sqInt stackPtrAsInt, sqInt regsPtrAsInt, sqInt jmpBufPtrAsInt); sqInt (*reestablishContextPriorToCallback)(sqInt callbackContext); sqInt *(*getStackPointer)(void); sqInt (*internalIsImmutable)(sqInt oop); sqInt (*internalIsMutable)(sqInt oop); #endif #if VM_PROXY_MINOR > 8 || defined(ROAR_VM) sqInt (*classAlien)(void); sqInt (*primitiveFailFor)(sqInt code); #endif #if VM_PROXY_MINOR > 9 sqInt (*methodArg) (sqInt index); sqInt (*objectArg) (sqInt index); sqInt (*integerArg) (sqInt index); double (*floatArg) (sqInt index); #endif #if VM_PROXY_MINOR > 9 || defined(ROAR_VM) // some primitives need those sqInt (*topRemappableOop) (void); sqInt (*methodReturnValue) (sqInt oop); #endif #if VM_PROXY_MINOR > 10 # define DisownVMLockOutFullGC 1 sqInt (*disownVM)(sqInt flags); sqInt (*ownVM) (sqInt threadIdAndFlags); void (*addHighPriorityTickee)(void (*ticker)(void), unsigned periodms); void (*addSynchronousTickee)(void (*ticker)(void), unsigned periodms, unsigned roundms); usqLong (*utcMicroseconds)(void); sqInt (*isYoung) (sqInt anOop); sqInt (*primitiveErrorTable)(void); #endif #if VM_PROXY_MINOR > 10 || defined(ROAR_VM) // some primitives need those sqInt (*tenuringIncrementalGC)(void); sqInt (*primitiveFailureCode)(void); sqInt (*isKindOfClass)(sqInt oop, sqInt aClass); sqInt (*instanceSizeOf)(sqInt aClass); #endif #if VM_PROXY_MINOR > 11 /* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ sqInt (*sendInvokeCallbackContext)(vmccp); sqInt (*returnAsThroughCallbackContext)(int, vmccp, sqInt); long (*signedMachineIntegerValueOf)(sqInt); long (*stackSignedMachineIntegerValue)(sqInt); unsigned long (*positiveMachineIntegerValueOf)(sqInt); unsigned long (*stackPositiveMachineIntegerValue)(sqInt); sqInt (*getInterruptPending)(void); char *(*cStringOrNullFor)(sqInt); void *(*startOfAlienData)(sqInt); usqInt (*sizeOfAlienData)(sqInt); #endif } VirtualMachine; #endif /* _SqueakVM_H */ ================================================ FILE: vm/src/from_squeak/LICENSE ================================================ All contributions from Teleplace in this release are Copyright (c) 2010 Teleplace, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/AsynchFilePlugin/sqMacAsyncFilePrims.c ================================================ #include "sq.h" #include "AsynchFilePlugin.h" #include "sqMacFileLogic.h" #if TARGET_API_MAC_CARBON #include #else #include #include #include #include #include #endif extern struct VirtualMachine* interpreterProxy; #define success(bool) (interpreterProxy->success(bool)) #if !TARGET_API_MAC_CARBON #define DisposeIOCompletionUPP(userUPP) DisposeRoutineDescriptor(userUPP) #else IOCompletionUPP NewIOCompletionUPP(IOCompletionProcPtr userRoutine); void DisposeIOCompletionUPP(IOCompletionUPP userUPP); #endif /* initialize/shutdown */ int asyncFileInit() { return true; } int asyncFileShutdown() {return true;} /* End of adjustments for pluginized VM */ /* Experimental support for asynchronous file reading and writing. When a read or write operation is initiated, control is returned to Squeak immediately. A semaphore is signaled when the operation completes, at which time the client can find out how many bytes were actually read or written and copy the results of the read operation from the file buffer into a Squeak buffer. Only one operation may be in progress on a given file at a given time, but operations on different files may be done in parallel. The semaphore is signalled once for each transfer operation that is successfully started, even if that operation later fails. Write operations always write their entire buffer if they succeed, but read operations may transfer less than their buffer size if they are started less than a buffer's size from the end of the file. The state of a file is kept in the following structure, which is stored directly in a Squeak ByteArray object: typedef struct { int sessionID; AsyncFileState *state; } AsyncFile; The session ID is used to detect stale files--files that were open when the image was saved. The state pointer of such files is meaningless. Async file handles use the same session ID as ordinary file handles. Note: These primitives are experimental! They need not be implemented on every platform, and they may be withdrawn or replaced in a future release. */ /* Async file handle (defined in header file): */ typedef struct { ParamBlockRec pb; /* must be first */ long refNum; int writable; int semaIndex; int status; int bytesTransferred; int bufferSize; char *bufferPtr; } AsyncFileState; /*** Status Values ***/ #define IDLE 0 #define LAST_OP_FAILED 1 #define BUSY 2 /*** Local Vaiables ***/ IOCompletionUPP asyncFileCompletionProc = nil; /*** Exported Functions ***/ int asyncFileClose(AsyncFile *f); int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex); int asyncFileRecordSize(); int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize); int asyncFileReadStart(AsyncFile *f, int fPosition, int count); int asyncFileWriteResult(AsyncFile *f); int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize); /*** Local Functions ***/ void asyncFileAllocateBuffer(AsyncFileState *state, int byteCount); pascal void asyncFileCompletionRoutine(AsyncFileState *state); void asyncFileInitPB(AsyncFileState *state, int fPosition); int asyncFileValid(AsyncFile *f); void asyncFileAllocateBuffer(AsyncFileState *state, int byteCount) { /* Allocate a new buffer of the given size if necessary. If the current buffer is already allocated and of the desired size, do nothing. */ if ((state->bufferPtr != nil) && (state->bufferSize == byteCount)) { return; /* buffer is already allocated and of the desired size */ } /* free old buffer, if any */ if (state->bufferPtr != nil) { DisposePtr(state->bufferPtr); state->bufferSize = 0; state->bufferPtr = nil; } /* allocate new buffer */ state->bufferPtr = NewPtr(byteCount); if (state->bufferPtr == nil) { state->bufferSize = 0; success(false); /* could not allocate a buffer of size count */ return; } state->bufferSize = byteCount; } pascal void asyncFileCompletionRoutine(AsyncFileState *state) { /* Called when an I/O request completes. Decides what to do based on the given state. Note that the first part of the state record is the I/O parameter block. */ OSErr err; err = state->pb.ioParam.ioResult; if ((err != noErr) && (err != eofErr)) { /* Note: eofErr indicates that fewer than the count bytes were transfered when reading because the end-of-file was encountered first; it isn't a real error. */ state->status = LAST_OP_FAILED; state->bytesTransferred = 0; interpreterProxy->signalSemaphoreWithIndex(state->semaIndex); return; } state->bytesTransferred = state->pb.ioParam.ioActCount; state->status = IDLE; interpreterProxy->signalSemaphoreWithIndex(state->semaIndex); } void asyncFileInitPB(AsyncFileState *state, int fPosition) { memset(&state->pb, 0, sizeof(ParamBlockRec)); state->pb.ioParam.ioCompletion = asyncFileCompletionProc; state->pb.ioParam.ioRefNum = state->refNum; state->pb.ioParam.ioBuffer = state->bufferPtr; state->pb.ioParam.ioReqCount = state->bufferSize; state->pb.ioParam.ioPosMode = fsFromStart; state->pb.ioParam.ioPosOffset = (fPosition < 0) ? 0 : fPosition; state->status = BUSY; state->bytesTransferred = 0; } int asyncFileValid(AsyncFile *f) { void* ithisSessionfn; int thisSession; ithisSessionfn = interpreterProxy->ioLoadFunctionFrom("getThisSession", "FilePlugin"); if (ithisSessionfn != 0) thisSession = ((int (*) (void)) ithisSessionfn)(); else thisSession = 0; return ( (f != NULL) && (f->sessionID == thisSession) && (f->state != NULL) && (((AsyncFileState *) f->state)->refNum != 0)); } /*** Exported Functions ***/ int asyncFileClose(AsyncFile *f) { /* Close the given asynchronous file. */ AsyncFileState *state; short int volRefNum; OSErr err; if (!asyncFileValid(f)) return 0; /* already closed */ state = f->state; err = GetVRefNum(state->refNum, &volRefNum); success(err == noErr); err = FSClose(state->refNum); success(err == noErr); if (!interpreterProxy->failed()) err = FlushVol(NULL, volRefNum); success(err == noErr); if (asyncFileCompletionProc != nil) DisposeIOCompletionUPP(asyncFileCompletionProc); asyncFileCompletionProc = nil; if (state->bufferPtr != nil) DisposePtr(state->bufferPtr); DisposePtr((void *) f->state); f->state = nil; f->sessionID = 0; return 0; } int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex) { /* Opens the given file using the supplied AsyncFile structure to record its state. Fails with no side effects if f is already open. Files are always opened in binary mode. */ short int fileRefNum; AsyncFileState *state; OSErr err; void * ithisSessionfn; int thisSession; FSSpec theSpec; /* don't open an already open file */ if (asyncFileValid(f)) return success(false); /* build complete routine descriptor, if necessary */ if (asyncFileCompletionProc == nil) { #if TARGET_API_MAC_CARBON asyncFileCompletionProc = NewIOCompletionUPP((pascal void (*) (union ParamBlockRec *) )asyncFileCompletionRoutine); #else asyncFileCompletionProc = NewIOCompletionProc((pascal void (*) (union ParamBlockRec *) )asyncFileCompletionRoutine); #endif } /* copy the file name into a null-terminated C string */ if (fileNameSize > 1000) return success(false); makeFSSpec((char*) fileNamePtr, fileNameSize,&theSpec); f->sessionID = 0; if (writeFlag) { /* first try to open an existing file read/write: */ err = FSpOpenDF(&theSpec,fsRdWrPerm, &fileRefNum); if (err != noErr) { /* file does not exist; must create it. */ err = FSpCreate(&theSpec,'R*ch','TEXT',smSystemScript); if (err != noErr) return success(false); err = FSpOpenDF(&theSpec,fsRdWrPerm, &fileRefNum); if (err != noErr) return success(false); } } else { /* open the file read-only */ err = FSpOpenDF(&theSpec,fsRdPerm, &fileRefNum); if (err != noErr) return success(false); } f->state = (AsyncFileState *) NewPtr(sizeof(AsyncFileState)); /* allocate state record */ if (f->state == nil) { FSClose(fileRefNum); return success(false); } ithisSessionfn = interpreterProxy->ioLoadFunctionFrom("getThisSession", "FilePlugin"); if (ithisSessionfn != 0) thisSession = ((int (*) (void)) ithisSessionfn)(); else thisSession = 0; f->sessionID = thisSession; state = (AsyncFileState *) f->state; state->refNum = fileRefNum; state->writable = writeFlag; state->semaIndex = semaIndex; state->status = IDLE; state->bytesTransferred = 0; state->bufferSize = 0; state->bufferPtr = nil; return 0; } int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize) { /* Copy up to bufferSize bytes from the buffer of the last read operation into the given Squeak buffer, and return the number of bytes copied. Negative values indicate: -1 -- busy; the last operation has not finished yet -2 -- error; the last operation failed Note that a read operation may read fewer bytes than requested if, for example, there are fewer than the requested number of bytes between the starting file position of the read operation and the end-of-file. */ AsyncFileState *state; int bytesRead; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return -1; if (state->status == LAST_OP_FAILED) return -2; /* copy the file buffer into the squeak buffer */ bytesRead = (bufferSize < state->bytesTransferred) ? bufferSize : state->bytesTransferred; memcpy((char *) bufferPtr, state->bufferPtr, bytesRead); return bytesRead; } int asyncFileReadStart(AsyncFile *f, int fPosition, int count) { /* Start an asynchronous operation to read count bytes from the given file starting at the given file position. The file's semaphore will be signalled when the operation is complete. The client may then use asyncFileReadResult() to find out if the operation succeeded and to get the data that was read. */ AsyncFileState *state; OSErr err; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return success(false); /* operation in progress */ /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, count); if (state->bufferPtr == nil) return success(false); /* could not allocate buffer */ asyncFileInitPB(state, fPosition); err = PBReadAsync(&state->pb); if (err != noErr) { state->status = IDLE; success(false); return 0; } return 0; } int asyncFileRecordSize() { return sizeof(AsyncFile); } int asyncFileWriteResult(AsyncFile *f) { /* Return the number of bytes copied by the last write operation. Negative values indicate: -1 -- busy; the last operation has not finished yet -2 -- error; the last operation failed */ AsyncFileState *state; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return -1; if (state->status == LAST_OP_FAILED) return -2; return state->bytesTransferred; } int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int bufferSize) { /* Start an asynchronous operation to write bufferSize bytes to the given file starting at the given file position. The file's semaphore will be signalled when the operation is complete. The client may then use asyncFileWriteResult() to find out if the operation succeeded and how many bytes were actually written. */ AsyncFileState *state; OSErr err; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return success(false); /* operation in progress */ if (!state->writable) return success(false); /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, bufferSize); if (state->bufferPtr == nil) return success(false); /* could not allocate buffer */ /* copy the squeak buffer into the file buffer */ memcpy(state->bufferPtr, (char *) bufferPtr, bufferSize); asyncFileInitPB(state, fPosition); err = PBWriteAsync(&state->pb); if (err != noErr) { state->status = IDLE; return success(false); } return 0; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/B3DAcceleratorPlugin/sqMacOpenGL.c ================================================ /**************************************************************************** * PROJECT: Squeak 3D accelerator * FILE: sqMacOpenGL.c * CONTENT: MacOS specific bindings for OpenGL * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: Andreas.Raab@disney.com * RCSID: $Id: sqMacOpenGL.c 1367 2006-03-21 06:49:10Z johnmci $ * * NOTES: * * Changes May 14th 2001 John M McIntosh Carbon support * Changes Jun 2001 JMM browser internal plugin support * Changes Jan 2002 JMM carbon cleanup * Feb 26th, 2002, JMM - use carbon get dominate device * Apr 3rd, 2003, JMM - use BROWSERPLUGIN * *****************************************************************************/ #include #include #include #include #include #include #include /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #include "sqMacUIConstants.h" #include "B3DAcceleratorPlugin.h" #include "sqMacOpenGL.h" #include "sqOpenGLRenderer.h" #define INTERNAL #ifdef BROWSERPLUGIN #include "npapi.h" #endif int printRendererInfo(void); int printFormatInfo(AGLPixelFormat info); static glRenderer *current = NULL; static glRenderer allRenderer[MAX_RENDERER]; typedef int (*eventMessageHook)(EventRecord* event); #ifdef INTERNAL #ifdef BROWSERPLUGIN int gPortX,gPortY; extern NP_Port *getNP_Port(void); #endif void StartDraw(void); void EndDraw(void); extern WindowPtr getSTWindow(void); extern int setMessageHook(eventMessageHook theHook); extern int setPostMessageHook(eventMessageHook theHook); extern GDHandle getDominateDevice(WindowPtr theWindow,Rect *windRect); #else typedef WindowPtr (*getSTWindowFn)(void); getSTWindowFn getSTWindow = 0; eventMessageHook setMessageHook = 0; #endif /* Verbose level for debugging purposes: 0 - print NO information ever 1 - print critical debug errors 2 - print debug warnings 3 - print extra information 4 - print extra warnings 5 - print information about primitive execution 10 - print information about each vertex and face */ extern int verboseLevel; /* define forceFlush if we should fflush() before closing file */ #define forceFlush 1 #include "sqMacFileLogic.h" /* Note: Print this stuff into a file in case we lock up*/ #undef DPRINTF3D # define DPRINTF3D(vLevel, args) if(vLevel <= verboseLevel) {\ char fileName[DOCUMENT_NAME_SIZE+1]; \ sqFilenameFromStringOpen(fileName,(sqInt) &"Squeak3D.log", strlen("Squeak3D.log")); \ FILE *fp = fopen(fileName, "at");\ if(fp) { fprintf args; if(forceFlush) fflush(fp); fclose(fp); }} /* Plugin refs */ extern struct VirtualMachine *interpreterProxy; static float blackLight[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; /*****************************************************************************/ /*****************************************************************************/ /* Mac event hook */ /*****************************************************************************/ /*****************************************************************************/ static int macEventHook(EventRecord *event) { AGLDrawable win; int result; int i,windowCode; Boolean windowHasChanged=false; WindowPtr checkMouseDown,checkMouseUp; static WindowPtr oldWindow = NULL; #ifdef BROWSERPLUGIN NP_Port *anNPPort; #endif if (oldWindow == NULL) oldWindow = getSTWindow(); result = 0; switch(event->what) { case osEvt: if (((event->message>>24)& 0xFF) != suspendResumeMessage) return 0; DPRINTF3D(5, (fp, "\n")); break; case activateEvt: DPRINTF3D(5, (fp, "\n")); break; case updateEvt: DPRINTF3D(5, (fp, "\n")); break; case mouseDown: DPRINTF3D(5, (fp, "\n")); windowCode = FindWindow(event->where, &checkMouseDown); if (windowCode == inContent) return 0; break; case mouseUp: DPRINTF3D(5, (fp, "\n")); windowCode = FindWindow(event->where, &checkMouseUp); if (windowCode == inContent) return 0; break; default: #ifdef BROWSERPLUGIN if (oldWindow != getSTWindow()) { windowHasChanged = true; } anNPPort = getNP_Port(); if (!(anNPPort->portx == gPortX && anNPPort->porty == gPortY)) { windowHasChanged = true; } if (windowHasChanged) break; #endif return 0; } win = (AGLDrawable) getSTWindow(); if(!win) return 0; for(i=0; i< MAX_RENDERER; i++) { glRenderer *renderer = allRenderer+i; if(renderer->used) { if (renderer->drawable == win || (WindowPtr) renderer->drawable == oldWindow) { int x,y,w,h; Rect portRect; GLint bufferRect[4]; CGrafPtr windowPort; #ifdef BROWSERPLUGIN StartDraw(); anNPPort = getNP_Port(); gPortX = anNPPort->portx; gPortY = anNPPort->porty; x = renderer->bufferRect[0] - gPortX; y = renderer->bufferRect[1] - gPortY; #else x = renderer->bufferRect[0]; y = renderer->bufferRect[1]; #endif w = renderer->bufferRect[2]; h = renderer->bufferRect[3]; windowPort = GetWindowPort((WindowPtr)win); GetPortBounds(windowPort,&portRect); bufferRect[0] = x; bufferRect[1] = portRect.bottom - portRect.top - (y+h); bufferRect[2] = w; bufferRect[3] = h; // aglSetDrawable(renderer->context,nil); renderer->drawable = (AGLDrawable) win; aglSetDrawable(renderer->context,windowPort); aglSetInteger(renderer->context, AGL_BUFFER_RECT, bufferRect); aglUpdateContext(renderer->context); windowHasChanged = false; #ifdef BROWSERPLUGIN EndDraw(); #endif } } } oldWindow = getSTWindow(); return result; } /*****************************************************************************/ /*****************************************************************************/ /* Renderer creation primitives */ /*****************************************************************************/ /*****************************************************************************/ int glDestroyRenderer(int handle) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer) return 1; /* already destroyed */ /* Now really destroy the renderer */ if(renderer->drawable) { /* was a direct drawable */ aglSetDrawable(renderer->context, NULL); } if(renderer == current) glMakeCurrentRenderer(NULL); aglDestroyContext(renderer->context); if(renderer->gWorld) { UnlockPixels(renderer->pixMap); DisposeGWorld(renderer->gWorld); } renderer->context = (AGLContext) NULL; renderer->drawable = (AGLDrawable) NULL; renderer->gWorld = NULL; renderer->used = 0; return 1; } /* * Is ARB_Multisample supported? */ static int glHasARBMultisampling () { /* We need an open gl connection in which to test for extensions, * so we setup a throwaway context. */ GLint attrib[] = { AGL_RGBA, AGL_NONE}; AGLContext ctx; AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, attrib); if (! fmt) { return 0; } ctx = aglCreateContext(fmt, NULL); aglDestroyPixelFormat(fmt); if (! ctx) { return 0; } aglSetCurrentContext(ctx); int result = gluCheckExtension((const GLubyte*) "GL_ARB_multisample", glGetString(GL_EXTENSIONS)); aglDestroyContext(ctx); return result; } int glCreateRendererFlags(int x, int y, int w, int h, int flags) { int index, i, allowSoftware, allowHardware; GLint hwAttrib[] = { AGL_STENCIL_SIZE, 0, AGL_RGBA, AGL_DOUBLEBUFFER, AGL_ACCELERATED, AGL_DEPTH_SIZE, 16, AGL_SAMPLE_BUFFERS_ARB, 1, AGL_SAMPLES_ARB, 4, AGL_MULTISAMPLE, AGL_NO_RECOVERY, AGL_NONE}; /* Note - we honor antialiasing requests only for hardware renderers. */ GLint swAttrib[] = { AGL_STENCIL_SIZE, 0, AGL_RGBA, AGL_PIXEL_SIZE, 0, AGL_OFFSCREEN, AGL_DEPTH_SIZE, 16, AGL_NONE }; AGLPixelFormat fmt; AGLContext ctx; GLboolean ok; GLenum err; AGLDrawable win; glRenderer *renderer; char *string; GDHandle tempGDH; Rect ignore; long swapInterval = 0; #define SUPPORTED_FLAGS (B3D_HARDWARE_RENDERER | B3D_SOFTWARE_RENDERER | B3D_STENCIL_BUFFER | B3D_ANTIALIASING | B3D_STEREO | B3D_SYNCVBL) if(flags & ~SUPPORTED_FLAGS) { DPRINTF3D(1, (fp, "ERROR: Unsupported renderer flags (%d)\n", flags)); return -1; } #undef SUPPORTED_FLAGS /* interpret renderer flags */ allowSoftware = (flags & B3D_SOFTWARE_RENDERER) != 0; allowHardware = (flags & B3D_HARDWARE_RENDERER) != 0; if(flags & B3D_STENCIL_BUFFER) { hwAttrib[1] = 1; swAttrib[1] = 1; } /* enable/disable stereo requests */ if(flags & B3D_STEREO) { return -1; /* not supported for now */ } /* Suppress the multisampling flags if antialiasing is not requested (or not supported.) */ if (! ((flags & B3D_ANTIALIASING) && glHasARBMultisampling())) { hwAttrib[7] = AGL_NONE; } for(index=0; index < MAX_RENDERER; index++) { if(allRenderer[index].used == 0) break; } if(index >= MAX_RENDERER) { DPRINTF3D(1, (fp, "ERROR: Maximum number of renderers (%d) exceeded\n", MAX_RENDERER)); return 0; } renderer = allRenderer+index; renderer->used = 0; renderer->finished = 0; renderer->context = NULL; renderer->drawable = NULL; renderer->gWorld = NULL; #ifdef INTERNAL if (! getSTWindow()) { return 0; } GetWindowGreatestAreaDevice(getSTWindow(),kWindowContentRgn,&tempGDH,&ignore); if (tempGDH == nil) return -1; swAttrib[2] = (*(*tempGDH)->gdPMap)->pixelSize; #else swAttrib[2] = (*(*GetMainDevice())->gdPMap)->pixelSize; #endif if(swAttrib[2] < 16) swAttrib[2] = 16; /* Choose an rgb pixel format */ for(i = 0; i<2; i++) { if( (i == 0) && !allowHardware) continue; if( (i == 1) && !allowSoftware) continue; ctx = 0; if(i == 0) { DPRINTF3D(3, (fp, "### Attempting to find hardware renderer\n")); win = (AGLDrawable) getSTWindow(); if(!win) { DPRINTF3D(1, (fp, "ERROR: stWindow is invalid (NULL)\n")); goto FAILED; } fmt = aglChoosePixelFormat(NULL, 0, hwAttrib); } else { DPRINTF3D(3, (fp, "### Attempting to find software renderer\n")); win = NULL; fmt = aglChoosePixelFormat(NULL, 0, swAttrib); } DPRINTF3D(3, (fp,"\tx: %d\n\ty: %d\n\tw: %d\n\th: %d\n", x, y, w, h)); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglGetError - %s\n", aglErrorString(err))); if(fmt == NULL) { DPRINTF3D(1, (fp, "ERROR: aglChoosePixelFormat failed\n")); goto FAILED; } printFormatInfo(fmt); /* Create an AGL context */ ctx = aglCreateContext(fmt, NULL); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglGetError - %s\n", aglErrorString(err))); /* The pixel format is no longer needed */ aglDestroyPixelFormat(fmt); if(ctx == NULL) { DPRINTF3D(1, (fp, "ERROR: aglCreateContext failed\n")); goto FAILED; } if(i == 0) { GLint bufferRect[4]; Rect portRect; #ifdef BROWSERPLUGIN NP_Port *anNPPort; StartDraw(); win = (AGLDrawable) getSTWindow(); anNPPort = getNP_Port(); GetPortBounds(GetWindowPort((WindowPtr)win),&portRect); bufferRect[0] = x - anNPPort->portx; bufferRect[1] = portRect.bottom - portRect.top - (y+h) + anNPPort->porty; bufferRect[2] = w; bufferRect[3] = h; EndDraw(); #else GetPortBounds(GetWindowPort((WindowPtr)win),&portRect); bufferRect[0] = x; bufferRect[1] = portRect.bottom - portRect.top - (y+h); bufferRect[2] = w; bufferRect[3] = h; #endif /* hardware renderer; attach buffer rect and window */ ok = aglEnable(ctx, AGL_BUFFER_RECT); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglEnable(AGL_BUFFER_RECT) failed: aglGetError - %s\n", aglErrorString(err))); if(!ok) goto FAILED; ok = aglSetInteger(ctx, AGL_BUFFER_RECT, bufferRect); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglSetInteger(AGL_BUFFER_RECT) failed: aglGetError - %s\n", aglErrorString(err))); if(!ok) goto FAILED; /* Attach the context to the target */ ok = aglSetDrawable(ctx,GetWindowPort( (WindowPtr)win)); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglSetDrawable() failed: aglGetError - %s\n", aglErrorString(err))); if(!ok) goto FAILED; renderer->drawable = (AGLDrawable) win; /* Set VBL SYNC if requested */ if(flags & B3D_SYNCVBL) swapInterval = 1; aglSetInteger(ctx, AGL_SWAP_INTERVAL, &swapInterval); } else { /* software renderer; attach offscreen buffer to context */ Rect rect; QDErr qdErr; renderer->depth = swAttrib[2]; /* Create the offscreen gworld */ SetRect(&rect, 0, 0, w, h); qdErr = NewGWorld(&renderer->gWorld, (short) renderer->depth, &rect, NULL, NULL, useTempMem); if(qdErr || !renderer->gWorld) { DPRINTF3D(1,(fp,"ERROR: Failed to create new GWorld\n")); renderer->gWorld = NULL; goto FAILED; } renderer->pixMap = GetGWorldPixMap(renderer->gWorld); LockPixels(renderer->pixMap); renderer->pitch = (**(renderer->pixMap)).rowBytes & 0x7FFF; renderer->bits = (unsigned char*) GetPixBaseAddr(renderer->pixMap); ok = aglSetOffScreen(ctx, w, h, renderer->pitch, renderer->bits); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglGetError - %s\n", aglErrorString(err))); if(!ok) { DPRINTF3D(1, (fp, "ERROR: aglSetOffScreen failed\n")); goto FAILED; } } renderer->context = ctx; renderer->used = 1; renderer->finished = 0; renderer->bufferRect[0] = x; renderer->bufferRect[1] = y; renderer->bufferRect[2] = w; renderer->bufferRect[3] = h; /* Make the context the current context */ glMakeCurrentRenderer(renderer); /* finally, try to enable multithreaded OpenGL */ if (0) /* disable it, because it's broken */ { CGLContextObj cglContext = CGLGetCurrentContext(); CGLError cglErr = CGLEnable( cglContext, kCGLCEMPEngine); if (cglErr != kCGLNoError ) { DPRINTF3D(3,(fp,"CGLEnable(kCGLCEMPEngine) failed: cannot set multithreaded OpenGL\n")); exit(0); } } /* print some information about the context */ string = (char*) glGetString(GL_VENDOR); DPRINTF3D(3,(fp, "\nOpenGL vendor: %s\n", string)); string = (char*) glGetString(GL_RENDERER); DPRINTF3D(3,(fp, "OpenGL renderer: %s\n", string)); string = (char*) glGetString(GL_VERSION); DPRINTF3D(3,(fp, "OpenGL version: %s\n", string)); string = (char*) glGetString(GL_EXTENSIONS); DPRINTF3D(3,(fp, "OpenGL extensions: %s\n", string)); ERROR_CHECK; DPRINTF3D(3, (fp,"### Renderer created! (id = %d)\n", index)); /* setup user context */ glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_DITHER); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glDepthFunc(GL_LEQUAL); glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glShadeModel(GL_SMOOTH); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, blackLight); ERROR_CHECK; return index; FAILED: if(ctx) aglDestroyContext(ctx); if(renderer->gWorld) DisposeGWorld(renderer->gWorld); } return -1; } /*****************************************************************************/ /*****************************************************************************/ int glGetIntPropertyOS(int handle, int prop) { GLint v; glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; switch(prop) { case -1: /* vertical blank synchronization */ aglGetInteger(renderer->context, AGL_SWAP_INTERVAL, &v); return v; } return 0; } int glSetIntPropertyOS(int handle, int prop, int value) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; switch(prop) { case -1: /* vertical blank synchronization */ aglSetInteger(renderer->context, AGL_SWAP_INTERVAL, (GLint*) &value); return 1; } return 0; } glRenderer *glRendererFromHandle(int handle) { DPRINTF3D(7, (fp, "Looking for renderer id: %d\n", handle)); if(handle < 0 || handle >= MAX_RENDERER) return NULL; if(allRenderer[handle].used) return allRenderer+handle; return NULL; } int glSwapBuffers(glRenderer *renderer) { GLint err; if(!renderer) return 0; if(!renderer->used || !renderer->context) return 0; if(renderer->drawable) { #ifdef BROWSERPLUGIN NP_Port *anNPPort; anNPPort = getNP_Port(); if (!(anNPPort->portx == gPortX && anNPPort->porty == gPortY)) { return 0; } #endif aglSwapBuffers(renderer->context); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"ERROR (glSwapBuffers): aglGetError - %s\n", aglErrorString(err))); ERROR_CHECK; } else { WindowPtr win; Rect src, dst, portBounds; GrafPtr oldPort,winPort; Boolean portChanged; /* ensure execution for offscreen contexts */ glFinish(); ERROR_CHECK; /* Copy the image to the window */ win = getSTWindow(); if(!win) return 0; winPort = (GrafPtr) GetWindowPort((WindowRef) win); #ifdef BROWSERPLUGIN StartDraw(); #else portChanged = QDSwapPort(winPort, &oldPort); GetPortBounds((CGrafPtr) winPort,&portBounds); // Draw into the new port here #endif SetRect(&src, 0, 0, renderer->bufferRect[2], renderer->bufferRect[3]); SetRect(&dst, renderer->bufferRect[0], renderer->bufferRect[1], renderer->bufferRect[0] + renderer->bufferRect[2], renderer->bufferRect[1] + renderer->bufferRect[3]); CopyBits(GetPortBitMapForCopyBits(renderer->gWorld), GetPortBitMapForCopyBits((CGrafPtr) winPort), &src, &dst, srcCopy, NULL); #ifdef BROWSERPLUGIN EndDraw(); #else if (portChanged) QDSwapPort(oldPort, NULL); #endif } return 1; } int glMakeCurrentRenderer(glRenderer *renderer) { GLboolean ok; GLint err; if(current == renderer) return 1; if(renderer) if(!renderer->used || !renderer->context) return 0; // ERROR_CHECK; ok = aglSetCurrentContext(renderer ? renderer->context : NULL); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"ERROR (glMakeCurrentRenderer): aglGetError - %s\n", aglErrorString(err))); if(!ok) { DPRINTF3D(1, (fp, "ERROR (glMakeCurrentRenderer): aglSetCurrentContext failed\n")); return 0; } // ERROR_CHECK; current = renderer; return 1; } int glSetBufferRect(int handle, int x, int y, int w, int h) { glRenderer *renderer = glRendererFromHandle(handle); if(!renderer || !glMakeCurrentRenderer(renderer)) return 0; if(renderer->drawable) { /* hardware renderer */ GLboolean ok; GLenum err; GLint bufferRect[4]; Rect portRect; #ifdef BROWSERPLUGIN AGLDrawable win; NP_Port *anNPPort; StartDraw(); win = (AGLDrawable) getSTWindow(); anNPPort = getNP_Port(); GetPortBounds(GetWindowPort((WindowPtr)win),&portRect); bufferRect[0] = x - anNPPort->portx; bufferRect[1] = portRect.bottom - portRect.top - (y+h) + anNPPort->porty; bufferRect[2] = w; bufferRect[3] = h; EndDraw(); #else GetPortBounds(GetWindowPort((WindowPtr) renderer->drawable),&portRect); bufferRect[0] = x; bufferRect[1] = portRect.bottom - portRect.top - (y+h); bufferRect[2] = w; bufferRect[3] = h; #endif ok = aglSetInteger(renderer->context, AGL_BUFFER_RECT, bufferRect); if((err = aglGetError()) != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglSetInteger(AGL_BUFFER_RECT) failed: aglGetError - %s\n", aglErrorString(err))); if(!ok) return 0; } else { /* software renderer */ if(renderer->bufferRect[2] != w && renderer->bufferRect[3] != h) { /* do not allow resizing the software renderer */ return 0; } } renderer->bufferRect[0] = x; renderer->bufferRect[1] = y; renderer->bufferRect[2] = w; renderer->bufferRect[3] = h; return 1; } int glSetVerboseLevel(int level) { verboseLevel = level; return 1; } int glIsOverlayRenderer(int handle) { #pragma unused(handle) /* we never use overlay renderers */ return 0; } /*************************************************************************** *************************************************************************** Module initializers *************************************************************************** ***************************************************************************/ int glInitialize(void) { int i; for(i = 0; i < MAX_RENDERER; i++) { allRenderer[i].used = 0; } #ifdef INTERNAL setPostMessageHook(macEventHook); #else getSTWindow = (getSTWindowFn) interpreterProxy->ioLoadFunctionFrom("getSTWindow", ""); if(!getSTWindow) { DPRINTF3D(1,(fp,"ERROR: Failed to look up getSTWindow()\n")); return 0; } setMessageHook = (eventMessageHook) interpreterProxy->ioLoadFunctionFrom("setPostMessageHook", ""); if(!setMessageHook) { DPRINTF3D(1, (fp, "ERROR: Failed to look up setMessageHook()\n")); return 0; } ((void (*)(void*))setMessageHook)(macEventHook); #endif return 1; } int glShutdown(void) { int i; for(i=0; i< MAX_RENDERER; i++) { if(allRenderer[i].used) glDestroyRenderer(i); } return 1; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/B3DAcceleratorPlugin/sqMacOpenGL.h ================================================ #ifndef SQ_MAC_OPENGL_H #define SQ_MAC_OPENGL_H #define MAX_RENDERER 16 #if defined(__MWERKS__) #include #include #else #include #include #endif typedef struct glRenderer { GLint bufferRect[4]; GLint viewport[4]; int used; int finished; AGLContext context; /* hardware attributes */ AGLDrawable drawable; /* software attributes */ GWorldPtr gWorld; PixMapHandle pixMap; int depth; int pitch; unsigned char *bits; } glRenderer; #define GL_RENDERER_DEFINED 1 #endif /* SQ_MAC_OPENGL_H */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/B3DAcceleratorPlugin/sqMacOpenGLInfo.c ================================================ /**************************************************************************** * PROJECT: Squeak 3D accelerator * FILE: sqMacOpenGLInfo.c * CONTENT: MacOS specific bindings for OpenGL * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: Andreas.Raab@disney.com * RCSID: $Id: sqMacOpenGLInfo.c 1708 2007-06-10 00:40:04Z johnmci $ * * NOTES: * *****************************************************************************/ #include #include #include #include #include #include "sq.h" #include "sqVirtualMachine.h" #include "sqMacUIConstants.h" int printRendererInfo(void); int printFormatInfo(AGLPixelFormat info); /* Verbose level for debugging purposes: 0 - print NO information ever 1 - print critical debug errors 2 - print debug warnings 3 - print extra information 4 - print extra warnings 5 - print information about primitive execution 10 - print information about each vertex and face */ int verboseLevel = 3; /* define forceFlush if we should fflush() before closing file */ #define forceFlush 1 #include "sqMacFileLogic.h" /* Note: Print this stuff into a file in case we lock up*/ /* Note: Print this stuff into a file in case we lock up*/ #undef DPRINTF3D # define DPRINTF3D(vLevel, args) if(vLevel <= verboseLevel) {\ char fileName[DOCUMENT_NAME_SIZE+1]; \ sqFilenameFromStringOpen(fileName,(sqInt) &"Squeak3D.log", strlen("Squeak3D.log")); \ FILE *fp = fopen(fileName, "at");\ if(fp) { fprintf args; if(forceFlush) fflush(fp); fclose(fp); }} /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ static void PrintBufferModes(GLint v) { if(v & AGL_MONOSCOPIC_BIT) DPRINTF3D(3,(fp," AGL_MONOSCOPIC_BIT\n")); if(v & AGL_STEREOSCOPIC_BIT) DPRINTF3D(3,(fp," AGL_STEREOSCOPIC_BIT\n")); if(v & AGL_SINGLEBUFFER_BIT) DPRINTF3D(3,(fp," AGL_SINGLEBUFFER_BIT\n")); if(v & AGL_DOUBLEBUFFER_BIT) DPRINTF3D(3,(fp," AGL_DOUBLEBUFFER_BIT\n")); } static void PrintColorModes(GLint v) { if(v & AGL_RGB8_BIT) DPRINTF3D(3,(fp," AGL_RGB8_BIT\n")); if(v & AGL_RGB8_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB8_A8_BIT\n")); if(v & AGL_BGR233_BIT) DPRINTF3D(3,(fp," AGL_BGR233_BIT\n")); if(v & AGL_BGR233_A8_BIT) DPRINTF3D(3,(fp," AGL_BGR233_A8_BIT\n")); if(v & AGL_RGB332_BIT) DPRINTF3D(3,(fp," AGL_RGB332_BIT\n")); if(v & AGL_RGB332_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB332_A8_BIT\n")); if(v & AGL_RGB444_BIT) DPRINTF3D(3,(fp," AGL_RGB444_BIT\n")); if(v & AGL_ARGB4444_BIT) DPRINTF3D(3,(fp," AGL_ARGB4444_BIT\n")); if(v & AGL_RGB444_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB444_A8_BIT\n")); if(v & AGL_RGB555_BIT) DPRINTF3D(3,(fp," AGL_RGB555_BIT\n")); if(v & AGL_ARGB1555_BIT) DPRINTF3D(3,(fp," AGL_ARGB1555_BIT\n")); if(v & AGL_RGB555_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB555_A8_BIT\n")); if(v & AGL_RGB565_BIT) DPRINTF3D(3,(fp," AGL_RGB565_BIT\n")); if(v & AGL_RGB565_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB565_A8_BIT\n")); if(v & AGL_RGB888_BIT) DPRINTF3D(3,(fp," AGL_RGB888_BIT\n")); if(v & AGL_ARGB8888_BIT) DPRINTF3D(3,(fp," AGL_ARGB8888_BIT\n")); if(v & AGL_RGB888_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB888_A8_BIT\n")); if(v & AGL_RGB101010_BIT) DPRINTF3D(3,(fp," AGL_RGB101010_BIT\n")); if(v & AGL_ARGB2101010_BIT) DPRINTF3D(3,(fp," AGL_ARGB2101010_BIT\n")); if(v & AGL_RGB101010_A8_BIT) DPRINTF3D(3,(fp," AGL_RGB101010_A8_BIT\n")); if(v & AGL_RGB121212_BIT) DPRINTF3D(3,(fp," AGL_RGB121212_BIT\n")); if(v & AGL_ARGB12121212_BIT) DPRINTF3D(3,(fp," AGL_ARGB12121212_BIT\n")); if(v & AGL_RGB161616_BIT) DPRINTF3D(3,(fp," AGL_RGB161616_BIT\n")); if(v & AGL_ARGB16161616_BIT) DPRINTF3D(3,(fp," AGL_ARGB16161616_BIT\n")); if(v & AGL_INDEX8_BIT) DPRINTF3D(3,(fp," AGL_INDEX8_BIT\n")); if(v & AGL_INDEX16_BIT) DPRINTF3D(3,(fp," AGL_INDEX16_BIT\n")); } static void PrintBitModes(GLint v) { if(v & AGL_0_BIT) DPRINTF3D(3,(fp," AGL_0_BIT\n")); if(v & AGL_1_BIT) DPRINTF3D(3,(fp," AGL_1_BIT\n")); if(v & AGL_2_BIT) DPRINTF3D(3,(fp," AGL_2_BIT\n")); if(v & AGL_3_BIT) DPRINTF3D(3,(fp," AGL_3_BIT\n")); if(v & AGL_4_BIT) DPRINTF3D(3,(fp," AGL_4_BIT\n")); if(v & AGL_5_BIT) DPRINTF3D(3,(fp," AGL_5_BIT\n")); if(v & AGL_6_BIT) DPRINTF3D(3,(fp," AGL_6_BIT\n")); if(v & AGL_8_BIT) DPRINTF3D(3,(fp," AGL_8_BIT\n")); if(v & AGL_10_BIT) DPRINTF3D(3,(fp," AGL_10_BIT\n")); if(v & AGL_12_BIT) DPRINTF3D(3,(fp," AGL_12_BIT\n")); if(v & AGL_16_BIT) DPRINTF3D(3,(fp," AGL_16_BIT\n")); if(v & AGL_24_BIT) DPRINTF3D(3,(fp," AGL_24_BIT\n")); if(v & AGL_32_BIT) DPRINTF3D(3,(fp," AGL_32_BIT\n")); if(v & AGL_48_BIT) DPRINTF3D(3,(fp," AGL_48_BIT\n")); if(v & AGL_64_BIT) DPRINTF3D(3,(fp," AGL_64_BIT\n")); if(v & AGL_96_BIT) DPRINTF3D(3,(fp," AGL_96_BIT\n")); if(v & AGL_128_BIT) DPRINTF3D(3,(fp," AGL_128_BIT\n")); } static void PrintInfoStats(AGLRendererInfo info) { GLint rv; aglDescribeRenderer(info, AGL_RENDERER_ID, &rv); DPRINTF3D(3,(fp," AGL_RENDERER_ID : 0x%X\n", rv)); aglDescribeRenderer(info, AGL_OFFSCREEN, &rv); DPRINTF3D(3,(fp," AGL_OFFSCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_FULLSCREEN, &rv); DPRINTF3D(3,(fp," AGL_FULLSCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_WINDOW, &rv); DPRINTF3D(3,(fp," AGL_WINDOW : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_ACCELERATED, &rv); DPRINTF3D(3,(fp," AGL_ACCELERATED : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_ROBUST, &rv); DPRINTF3D(3,(fp," AGL_ROBUST : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_BACKING_STORE, &rv); DPRINTF3D(3,(fp," AGL_BACKING_STORE : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_MP_SAFE, &rv); DPRINTF3D(3,(fp," AGL_MP_SAFE : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_COMPLIANT, &rv); DPRINTF3D(3,(fp," AGL_COMPLIANT : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_MULTISCREEN, &rv); DPRINTF3D(3,(fp," AGL_MULTISCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribeRenderer(info, AGL_BUFFER_MODES, &rv); DPRINTF3D(3,(fp," AGL_BUFFER_MODES : 0x%X\n", rv)); PrintBufferModes(rv); aglDescribeRenderer(info, AGL_MIN_LEVEL, &rv); DPRINTF3D(3,(fp," AGL_MIN_LEVEL : %d\n", rv)); aglDescribeRenderer(info, AGL_MAX_LEVEL, &rv); DPRINTF3D(3,(fp," AGL_MAX_LEVEL : %d\n", rv)); aglDescribeRenderer(info, AGL_COLOR_MODES, &rv); DPRINTF3D(3,(fp," AGL_COLOR_MODES : 0x%X\n", rv)); PrintColorModes(rv); aglDescribeRenderer(info, AGL_ACCUM_MODES, &rv); DPRINTF3D(3,(fp," AGL_ACCUM_MODES : 0x%X\n", rv)); PrintColorModes(rv); aglDescribeRenderer(info, AGL_DEPTH_MODES, &rv); DPRINTF3D(3,(fp," AGL_DEPTH_MODES : 0x%X\n", rv)); PrintBitModes(rv); aglDescribeRenderer(info, AGL_STENCIL_MODES, &rv); DPRINTF3D(3,(fp," AGL_STENCIL_MODES : 0x%X\n", rv)); PrintBitModes(rv); aglDescribeRenderer(info, AGL_MAX_AUX_BUFFERS, &rv); DPRINTF3D(3,(fp," AGL_MAX_AUX_BUFFERS : %d\n", rv)); aglDescribeRenderer(info, AGL_VIDEO_MEMORY, &rv); DPRINTF3D(3,(fp," AGL_VIDEO_MEMORY : %d\n", rv)); aglDescribeRenderer(info, AGL_TEXTURE_MEMORY, &rv); DPRINTF3D(3,(fp," AGL_TEXTURE_MEMORY : %d\n", rv)); } static void CheckGetRendererInfo(GDHandle device) { AGLRendererInfo info, head_info; GLint inum; head_info = aglQueryRendererInfo(&device, 1); if(!head_info) { DPRINTF3D(3,(fp,"aglQueryRendererInfo : Info Error\n")); return; } info = head_info; inum = 0; while(info) { DPRINTF3D(3,(fp,"\n Renderer : %d\n", inum)); PrintInfoStats(info); info = aglNextRendererInfo(info); inum++; } aglDestroyRendererInfo(head_info); } int printRendererInfo(void) { GLenum err; GDHandle device; GLuint dnum = 0; device = GetDeviceList(); while(device) { DPRINTF3D(3,(fp,"\nDevice : %d\n", dnum)); CheckGetRendererInfo(device); device = GetNextDevice(device); dnum++; } err = aglGetError(); if(err != AGL_NO_ERROR) DPRINTF3D(3,(fp,"aglGetError - %s\n", aglErrorString(err))); return 1; } int printFormatInfo(AGLPixelFormat info) { GLint rv; DPRINTF3D(3, (fp, "\n\nSelected pixel format:\n")); aglDescribePixelFormat(info, AGL_RENDERER_ID, &rv); DPRINTF3D(3,(fp," AGL_RENDERER_ID : 0x%X\n", rv)); aglDescribePixelFormat(info, AGL_OFFSCREEN, &rv); DPRINTF3D(3,(fp," AGL_OFFSCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_FULLSCREEN, &rv); DPRINTF3D(3,(fp," AGL_FULLSCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_WINDOW, &rv); DPRINTF3D(3,(fp," AGL_WINDOW : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_ACCELERATED, &rv); DPRINTF3D(3,(fp," AGL_ACCELERATED : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_ROBUST, &rv); DPRINTF3D(3,(fp," AGL_ROBUST : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_BACKING_STORE, &rv); DPRINTF3D(3,(fp," AGL_BACKING_STORE : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_MP_SAFE, &rv); DPRINTF3D(3,(fp," AGL_MP_SAFE : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_COMPLIANT, &rv); DPRINTF3D(3,(fp," AGL_COMPLIANT : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_MULTISCREEN, &rv); DPRINTF3D(3,(fp," AGL_MULTISCREEN : %s\n", (rv ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(info, AGL_BUFFER_SIZE, &rv); DPRINTF3D(3,(fp," AGL_BUFFER_SIZE : %d\n", rv)); aglDescribePixelFormat(info, AGL_LEVEL, &rv); DPRINTF3D(3,(fp," AGL_LEVEL : %d\n", rv)); aglDescribePixelFormat(info, AGL_PIXEL_SIZE, &rv); DPRINTF3D(3,(fp," AGL_PIXEL_SIZE : %d\n", rv)); #if 0 aglDescribePixelFormat(info, AGL_ACCUM_MODES, &rv); DPRINTF3D(3,(fp," AGL_ACCUM_MODES : 0x%X\n", rv)); PrintColorModes(rv); #endif aglDescribePixelFormat(info, AGL_DEPTH_SIZE, &rv); DPRINTF3D(3,(fp," AGL_DEPTH_SIZE : %d\n", rv)); aglDescribePixelFormat(info, AGL_STENCIL_SIZE, &rv); DPRINTF3D(3,(fp," AGL_STENCIL_SIZE : %d\n", rv)); PrintBitModes(rv); aglDescribePixelFormat(info, AGL_AUX_BUFFERS, &rv); DPRINTF3D(3,(fp," AGL_AUX_BUFFERS : %d\n", rv)); #if 0 aglDescribePixelFormat(info, AGL_VIDEO_MEMORY, &rv); DPRINTF3D(3,(fp," AGL_VIDEO_MEMORY : %d\n", rv)); aglDescribePixelFormat(info, AGL_TEXTURE_MEMORY, &rv); DPRINTF3D(3,(fp," AGL_TEXTURE_MEMORY : %d\n", rv)); #endif #if 0 aglDescribePixelFormat(pix, AGL_BUFFER_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_BUFFER_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_LEVEL, &rv); DPRINTF3D(3, (fp, "\tAGL_LEVEL: %d\n", rv)); aglDescribePixelFormat(pix, AGL_RGBA, &rv); DPRINTF3D(3, (fp, "\tAGL_RGBA: %s\n", (rv == GL_TRUE ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(pix, AGL_DOUBLEBUFFER, &rv); DPRINTF3D(3, (fp, "\tAGL_DOUBLEBUFFER: %s\n", (rv == GL_TRUE ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(pix, AGL_STEREO, &rv); DPRINTF3D(3, (fp, "\tAGL_STEREO: %s\n", (rv == GL_TRUE ? "GL_TRUE" : "GL_FALSE"))); aglDescribePixelFormat(pix, AGL_AUX_BUFFERS, &rv); DPRINTF3D(3, (fp, "\tAGL_AUX_BUFFERS: %d\n", rv)); aglDescribePixelFormat(pix, AGL_PIXEL_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_PIXEL_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_RED_SIZE, &rv); DPRINTF3D(3, (fp, "\n\tAGL_RED_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_GREEN_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_GREEN_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_BLUE_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_BLUE_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_ALPHA_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_ALPHA_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_DEPTH_SIZE, &rv); DPRINTF3D(3, (fp, "\n\tAGL_DEPTH_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_STENCIL_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_STENCIL_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_ACCUM_RED_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_ACCUM_RED_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_ACCUM_GREEN_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_ACCUM_GREEN_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_ACCUM_BLUE_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_ACCUM_BLUE_SIZE: %d\n", rv)); aglDescribePixelFormat(pix, AGL_ACCUM_ALPHA_SIZE, &rv); DPRINTF3D(3, (fp, "\tAGL_ACCUM_ALPHA_SIZE: %d\n", rv)); #endif return 1; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/ClipboardExtendedPlugin.c ================================================ /* Automatically generated from Squeak on #(9 May 2006 1:40:04 am) */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) ioAddClipboardData(void); EXPORT(sqInt) ioClearClipboard(void); EXPORT(sqInt) ioCreateClipboard(void); EXPORT(sqInt) ioGetClipboardFormat(void); EXPORT(sqInt) ioReadClipboardData(void); #pragma export off static sqInt msg(char * s); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "ClipboardExtendedPlugin 9 May 2006 (i)" #else "ClipboardExtendedPlugin 9 May 2006 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) ioAddClipboardData(void) { sqInt clipboardAddress; sqInt dataLength; sqInt formatLength; sqInt clipboard; char *data; char *aFormat; clipboard = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); data = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aFormat = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); dataLength = interpreterProxy->slotSizeOf(((sqInt)(long)(data) - 4)); formatLength = interpreterProxy->slotSizeOf(((sqInt)(long)(aFormat) - 4)); sqPasteboardPutItemFlavordatalengthformatTypeformatLength(clipboardAddress, data, dataLength, aFormat, formatLength); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) ioClearClipboard(void) { sqInt clipboardAddress; sqInt clipboard; clipboard = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); sqPasteboardClear(clipboardAddress); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) ioCreateClipboard(void) { sqInt clipboardAddress; clipboardAddress = interpreterProxy->positive32BitIntegerFor(sqCreateClipboard()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, clipboardAddress); return null; } EXPORT(sqInt) ioGetClipboardFormat(void) { sqInt itemCount; sqInt clipboardAddress; sqInt clipboard; sqInt formatNumber; sqInt _return_value; clipboard = interpreterProxy->stackValue(1); formatNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); itemCount = sqPasteboardGetItemCount(clipboardAddress); if (itemCount > 0) { _return_value = sqPasteboardCopyItemFlavorsitemNumber(clipboardAddress, formatNumber); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) ioReadClipboardData(void) { sqInt formatLength; sqInt clipboardAddress; sqInt clipboard; char *format; sqInt _return_value; clipboard = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); format = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); formatLength = interpreterProxy->slotSizeOf(((sqInt)(long)(format) - 4)); _return_value = sqPasteboardCopyItemFlavorDataformatformatLength(clipboardAddress, format, formatLength); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } static sqInt msg(char * s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* ClipboardExtendedPlugin_exports[][3] = { {"ClipboardExtendedPlugin", "ioClearClipboard", (void*)ioClearClipboard}, {"ClipboardExtendedPlugin", "ioReadClipboardData", (void*)ioReadClipboardData}, {"ClipboardExtendedPlugin", "ioCreateClipboard", (void*)ioCreateClipboard}, {"ClipboardExtendedPlugin", "ioAddClipboardData", (void*)ioAddClipboardData}, {"ClipboardExtendedPlugin", "getModuleName", (void*)getModuleName}, {"ClipboardExtendedPlugin", "ioGetClipboardFormat", (void*)ioGetClipboardFormat}, {"ClipboardExtendedPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable ClipboardExtendedPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.ClipboardExtendedPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.0b2 CFBundleSignature FAST CFBundleVersion 1.0.0b2 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/JMMExtendedClipBoardPlugin.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 22 May 2007 at 7:28:42 am'! SmartSyntaxInterpreterPlugin subclass: #ClipboardExtendedPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !ClipboardExtendedPlugin methodsFor: 'io' stamp: 'JSM 5/8/2006 23:39'! ioAddClipboardData: clipboard data: data dataFormat: aFormat | clipboardAddress formatLength dataLength | self primitive: 'ioAddClipboardData' parameters: #(Oop ByteArray String). clipboardAddress := interpreterProxy positive32BitValueOf: clipboard. dataLength := interpreterProxy slotSizeOf: data cPtrAsOop. formatLength := interpreterProxy slotSizeOf: aFormat cPtrAsOop. self sqPasteboardPutItemFlavor: clipboardAddress data: data length: dataLength formatType: aFormat formatLength: formatLength. ! ! !ClipboardExtendedPlugin methodsFor: 'io' stamp: 'JSM 5/6/2006 18:59'! ioClearClipboard: clipboard | clipboardAddress | self primitive: 'ioClearClipboard' parameters: #(Oop). clipboardAddress := interpreterProxy positive32BitValueOf: clipboard. self sqPasteboardClear: clipboardAddress.! ! !ClipboardExtendedPlugin methodsFor: 'io' stamp: 'JSM 5/6/2006 19:23'! ioCreateClipboard | clipboardAddress | self primitive: 'ioCreateClipboard' parameters: #(). clipboardAddress := interpreterProxy positive32BitIntegerFor: self sqCreateClipboard. ^ clipboardAddress.! ! !ClipboardExtendedPlugin methodsFor: 'io' stamp: 'JSM 5/9/2006 01:39'! ioGetClipboardFormat: clipboard formatNumber: formatNumber | clipboardAddress itemCount | self primitive: 'ioGetClipboardFormat' parameters: #(#Oop #SmallInteger ). clipboardAddress := interpreterProxy positive32BitValueOf: clipboard. itemCount := self sqPasteboardGetItemCount: clipboardAddress. itemCount > 0 ifTrue: [^ self sqPasteboardCopyItemFlavors: clipboardAddress itemNumber: formatNumber]. ^ interpreterProxy nilObject! ! !ClipboardExtendedPlugin methodsFor: 'io' stamp: 'JSM 5/7/2006 13:07'! ioReadClipboardData: clipboard format: format | clipboardAddress formatLength | self primitive: 'ioReadClipboardData' parameters: #(Oop String). clipboardAddress := interpreterProxy positive32BitValueOf: clipboard. formatLength := interpreterProxy slotSizeOf: format cPtrAsOop. ^ self sqPasteboardCopyItemFlavorData: clipboardAddress format: format formatLength: formatLength. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/Sophie-Clipboard.st ================================================ Object subclass: #ExtendedClipboardInterface instanceVariableNames: 'clipboard' classVariableNames: 'Current MacServicesProcess' poolDictionaries: '' category: 'Sophie-Clipboard'! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:44'! addClipboardData: data dataFormat: aFormat ^ self primAddClipboardData: clipboard data: data dataFormat: aFormat.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:37'! clearClipboard ^ self primClearClipboard: clipboard.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:28'! createClipboard ^ self primCreateClipboard.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:38'! getClipboardFormat: formatNumber ^ self primGetClipboardFormat: clipboard formatNumber: formatNumber.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:35'! initialize clipboard := self createClipboard.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 16:32'! primAddClipboardData: clipboard data: data dataFormat: aFormat ^ self primitiveFailed.! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 16:32'! primClearClipboard: clipboard ^ self primitiveFailed. ! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 18:53'! primCreateClipboard ^ self primitiveFailed. ! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 16:33'! primGetClipboardFormat: clipboard formatNumber: formatNumber ^ self primitiveFailed. ! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 16:33'! primReadClipboardData: clipboard format: format . ^ self primitiveFailed. ! ! !ExtendedClipboardInterface methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:38'! readClipboardData: format ^ self primReadClipboardData: clipboard format: format.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ExtendedClipboardInterface class instanceVariableNames: ''! !ExtendedClipboardInterface class methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:32'! current Current ifNil: [Current := self new]. ^Current! ! !ExtendedClipboardInterface class methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 18:14'! initialize "ExtendedClipboardInterface initialize" Current := nil. Smalltalk addToStartUpList: self after: nil. Smalltalk addToShutDownList: self after: nil.! ! !ExtendedClipboardInterface class methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:33'! shutDown: quitting ! ! !ExtendedClipboardInterface class methodsFor: 'as yet unclassified' stamp: 'JSM 5/6/2006 15:33'! startUp: resuming "The image is either being newly started (resuming is true), or it's just been snapshotted" Current := nil. self current.! ! ExtendedClipboardInterface initialize! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/SophieSUnitClipboard.st ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 9 May 2006 at 1:45:40 am'! TestCase subclass: #ExtendedClipboardSunit instanceVariableNames: 'interface' classVariableNames: '' poolDictionaries: '' category: 'System-Clipboard-Extended'! !ExtendedClipboardSunit methodsFor: 'testing' stamp: 'JSM 5/9/2006 00:43'! testAddClipboardData | data | interface clearClipboard. interface addClipboardData:'hello' dataFormat: 'text'. interface addClipboardData:'bye' dataFormat: 'txt'. data := interface readClipboardData: 'text'. self should: data asString = 'hello'. data := interface readClipboardData: 'txt'. self should: data asString = 'bye'. interface clearClipboard. data := interface readClipboardData: 'text'. self should: data = nil. ! ! !ExtendedClipboardSunit methodsFor: 'testing' stamp: 'JSM 5/9/2006 01:43'! testClearClipboard | data | interface clearClipboard. data := interface readClipboardData: 'txt'. self assert: data = nil! ! !ExtendedClipboardSunit methodsFor: 'testing' stamp: 'JSM 5/9/2006 01:43'! testGetClipboardFormat | data | interface clearClipboard. data := interface getClipboardFormat: 1. self assert: data = nil. interface clearClipboard. interface addClipboardData: 'hello' dataFormat: 'com.apple.traditional-mac-plain-text'. interface addClipboardData: 'bye' dataFormat: 'public.utf8-plain-text'. data := interface getClipboardFormat: 1. self should: data asText = 'public.utf8-plain-text'. data := interface getClipboardFormat: 0. self should: data asText = 'com.apple.traditional-mac-plain-text'! ! !ExtendedClipboardSunit methodsFor: 'initialize-release' stamp: 'JSM 5/6/2006 15:54'! setUp interface _ ExtendedClipboardInterface current. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/sqMacExtendedClipboard.c ================================================ /* * sqMacExtendedClipboard.c * SqueakClipboardExtendedxcodeproj * * Created by John Sterling Mcintosh on 4/21/06. * Copyright 2006 Corporate Smalltalk Consulting ltd. All rights reserved. * Licenced under the squeak-l NSImage * */ #include #include "sqMacExtendedClipboard.h" /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" extern struct VirtualMachine* interpreterProxy; void sqPasteboardClear( PasteboardRef inPasteboard ) { PasteboardClear( inPasteboard ); } int sqPasteboardGetItemCount ( PasteboardRef inPasteboard ) { ItemCount itemCount; PasteboardSynchronize ( inPasteboard ); PasteboardGetItemCount ( inPasteboard, &itemCount); return itemCount; } int sqPasteboardCopyItemFlavorsitemNumber ( PasteboardRef inPasteboard, int formatNumber ) { CFArrayRef flavorTypeArray; CFStringRef formatType; int formatTypeLength; PasteboardItemID itemID; OSStatus err; int flavorCount; PasteboardSynchronize ( inPasteboard ); err = PasteboardGetItemIdentifier (inPasteboard,1,&itemID); if (err) { return interpreterProxy->nilObject(); } err = PasteboardCopyItemFlavors( inPasteboard, itemID, &flavorTypeArray ); if (err) { return interpreterProxy->nilObject(); } flavorCount = CFArrayGetCount( flavorTypeArray ); if (formatNumber > flavorCount) { CFRelease(flavorTypeArray); return interpreterProxy->nilObject(); } formatType = (CFStringRef) CFArrayGetValueAtIndex ( flavorTypeArray, formatNumber-1); formatTypeLength = CFStringGetLength (formatType); int outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), formatTypeLength); unsigned char* formatConverted = interpreterProxy->firstIndexableField(outData); CFStringGetBytes ( formatType, CFRangeMake(0,formatTypeLength), kCFStringEncodingMacRoman, 0, false, formatConverted,formatTypeLength, NULL); CFRelease (flavorTypeArray); return outData; } PasteboardRef sqCreateClipboard( void ) { static PasteboardRef sPasteboard = NULL; if ( sPasteboard == NULL ) { PasteboardCreate( kPasteboardClipboard, &sPasteboard ); } return sPasteboard; } void sqPasteboardPutItemFlavordatalengthformatTypeformatLength ( PasteboardRef inPasteboard, char* inData, int dataLength, char* format, int formatLength) { OSStatus err; CFStringRef formatType = CFStringCreateWithBytes ( kCFAllocatorDefault, format, formatLength, kCFStringEncodingMacRoman, false); CFDataRef convertedData = CFDataCreate(NULL, inData, dataLength); err = PasteboardPutItemFlavor ( inPasteboard, 1, formatType, convertedData, kPasteboardFlavorNoFlags); CFRelease (convertedData); CFRelease (formatType); if (err) { interpreterProxy->success(0); } } int sqPasteboardCopyItemFlavorDataformatformatLength ( PasteboardRef inPasteboard, char* format, int formatLength) { CFDataRef dataBuffer; PasteboardItemID itemID; OSStatus err; CFStringRef formatType = CFStringCreateWithBytes ( kCFAllocatorDefault, format, formatLength, kCFStringEncodingMacRoman, false); PasteboardSynchronize ( inPasteboard ); err = PasteboardGetItemIdentifier (inPasteboard,1,&itemID); if (err) { return interpreterProxy->nilObject(); } err = PasteboardCopyItemFlavorData ( inPasteboard, itemID, formatType, &dataBuffer); if (err) { CFRelease(formatType); return interpreterProxy->nilObject(); } int dataLength = CFDataGetLength(dataBuffer); int outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), dataLength ); unsigned char* flavorData = interpreterProxy->firstIndexableField(outData); CFDataGetBytes (dataBuffer, CFRangeMake(0,dataLength), flavorData); CFRelease(formatType); CFRelease(dataBuffer); return outData; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ClipboardExtended/sqMacExtendedClipboard.h ================================================ /* * sqMacExtendedClipboard.h * SqueakClipboardExtendedxcodeproj * * Created by John Sterling Mcintosh on 4/21/06. * Copyright 2006 Corporate Smalltalk Consulting ltd. All rights reserved. * Licenced under the squeak-l * */ #include ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/CroquetPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable CroquetPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.CroquetPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.0b2 CFBundleSignature FAST CFBundleVersion 1.0.0b2 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/CroquetPlugin/sqMacCroquet.c ================================================ /* * sqMacCroquet.c * SqueakCroquet * * Created by John M McIntosh on 04/04/06. * Copyright 2006 Corporate Smalltalk Consulting Ltd. All rights reserved. * Licenced under the Squeak-L * taken from Ian's unix example * */ #include "sqMacCroquet.h" #include "sqMemoryAccess.h" #include #include #include sqInt ioGatherEntropy(char *buffer, sqInt bufSize) { int fd, count= 0; if ((fd= open("/dev/urandom", O_RDONLY)) < 0) return 0; while (count < bufSize) { int n; if ((n= read(fd, buffer + count, bufSize)) < 1) break; count += n; } close(fd); return count == bufSize; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/CroquetPlugin/sqMacCroquet.h ================================================ /* * sqMacCroquet.h * SqueakCroquet * * Created by John M McIntosh on 04/04/06. * Copyright 2006 Corporate Smalltalk Consulting Ltd. All rights reserved. * Licenced under the Squeak-L * */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/CurlPlugin/Info-CURLPlugin.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable CurlPlugin CFBundleGetInfoString CurlPlugin V2.0.0 for Squeak CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.CurlPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName CurlPlugin V2.0.0 for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 2.0.0 CFBundleSignature FAST CFBundleVersion 2.0.0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/DropPlugin/sqMacDragDrop.c ================================================ /**************************************************************************** * PROJECT: Mac window, memory, keyboard interface. * FILE: sqMacDragDrop.c * CONTENT: * * AUTHOR: John McIntosh, and others. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacDragDrop.c 1708 2007-06-10 00:40:04Z johnmci $ * * NOTES: See change log below. * 1/4/2002 JMM Carbon cleanup * *****************************************************************************/ /* Drag and drop support for Squeak John M McIntosh of Corporate Smalltalk Consulting Ltd johnmci@smalltalkconsulting.com http://www.smalltalkconsulting.com In Jan of 2001 under contract to Disney Dragging is only for objects into Squeak, not from Squeak outwards. V1.0 Jan 24th 2001, JMM V3.0.19 Aug 2001, JMM make a proper plugin Some of this code comes from Author: John Montbriand Some techniques borrowed from Pete Gontier's original FinderDragPro. Copyright: Copyright: 1999 by Apple Computer, Inc. all rights reserved. Disclaimer: You may incorporate this sample code into your applications without restriction, though the sample code has been provided "AS IS" and the responsibility for its operation is 100% yours. However, what you are not permitted to do is to redistribute the source as "DSC Sample Code" after having made changes. If you're going to re-distribute the source, we require that you make it clear in the source that the code was descended from Apple Sample Code, but that you've made changes. Change History (most recent first): 9/9/99 by John Montbriand May 8th,2002,JMM - Bert Freudenberg published some changes to make file opening easier without security July 28th, 2003, JMM - fix issue with race on open doc events and squeak VM Thread. * 3.7.0bx Nov 24th, 2003 JMM gCurrentVMEncoding */ /* need get filetype/creator need DropPlugin_shutdownModule & dropShutdown */ #include "sq.h" #include #include #include #include #include "sqVirtualMachine.h" #include "sqMacFileLogic.h" #include "sqMacUIConstants.h" #include "DropPlugin.h" /* promise flavor types */ enum { kPromisedFlavor = 'fssP', /* default promise */ kPromisedFlavorFindFile = 'rWm1' /* Find File promise -- special case */ }; struct HFSFlavorSqueak { OSType fileType; /* file type */ OSType fileCreator; /* file creator */ UInt16 fdFlags; /* Finder flags */ FSRef theFSRef; /* file system Ref */ }; typedef struct HFSFlavorSqueak HFSFlavorSqueak; volatile static Boolean gDragDropThrottleSpinLock = false; /* true if waiting for Squeak to process D&D */ static DragReceiveHandlerUPP gMainReceiveHandler = NULL; /* receive handler for the main dialog */ static DragTrackingHandlerUPP gMainTrackingHandler = NULL; /* tracking handler for the main dialog */ static WindowPtr gWindowPtr; volatile static UInt16 gNumDropFiles=0; static HFSFlavorSqueak *dropFiles; static char tempName[DOCUMENT_NAME_SIZE + 1]; /* these routines are used both in the receive handler and inside of the tracking handler. The following variables are shared between MyDragTrackingHandler and MyDragReceiveHandler. */ static Boolean gApprovedDrag = false; /* set to true if the drag is approved */ static Boolean gInIconBox = false; /* set true if the drag is inside our drop box */ extern struct VirtualMachine *interpreterProxy; pascal OSErr MyDragTrackingHandler(DragTrackingMessage message, WindowPtr theWindow, void *refCon, DragReference theDragRef); pascal OSErr MyDragReceiveHandler(WindowPtr theWindow, void *refcon, DragReference theDragRef); // Startup logic int dropInit(void) { void *fn; Boolean installedReceiver=false, installedTracker=false; OSErr err; /* check for the drag manager & translucent feature??? */ if (gMainReceiveHandler != NULL) return 1; fn = interpreterProxy->ioLoadFunctionFrom("getSTWindow", ""); if (fn == 0) { goto bail; } gWindowPtr = (WindowPtr) ((int (*) ()) fn)(); gMainTrackingHandler = NewDragTrackingHandlerUPP(MyDragTrackingHandler); if (gMainTrackingHandler == NULL) return 0; gMainReceiveHandler = NewDragReceiveHandlerUPP(MyDragReceiveHandler); if (gMainReceiveHandler == NULL) return 0; /* install the drag handlers, don't forget to dispose of them later */ if (!gWindowPtr) goto bail; err = InstallTrackingHandler(gMainTrackingHandler, gWindowPtr, NULL); if (err != noErr) { err = memFullErr; goto bail; } installedTracker = true; err = InstallReceiveHandler(gMainReceiveHandler, gWindowPtr, NULL); if (err != noErr) { err = memFullErr; goto bail; } installedReceiver = true; return 1; bail: if (installedReceiver) RemoveReceiveHandler(gMainReceiveHandler, gWindowPtr); if (installedTracker) RemoveTrackingHandler(gMainTrackingHandler, gWindowPtr); gMainTrackingHandler = NULL; gMainReceiveHandler = NULL; return 0; } // Shutdown logic int dropShutdown() { if (gMainReceiveHandler != NULL) RemoveReceiveHandler(gMainReceiveHandler, gWindowPtr); if (gMainTrackingHandler != NULL) RemoveTrackingHandler(gMainTrackingHandler, gWindowPtr); if (gNumDropFiles != 0 ) { DisposePtr((char *) dropFiles); gNumDropFiles = 0; } gMainTrackingHandler = NULL; gMainReceiveHandler = NULL; gDragDropThrottleSpinLock = false; return 1; } int sqSecFileAccessCallback(void *function) { #pragma unused(function) return 0; } //Primitive to get file name char *dropRequestFileName(int dropIndex) { if(dropIndex < 1 || dropIndex > gNumDropFiles) return NULL; PathToFileViaFSRef(tempName, DOCUMENT_NAME_SIZE, &dropFiles[dropIndex-1].theFSRef,gCurrentVMEncoding); if (dropIndex == gNumDropFiles) gDragDropThrottleSpinLock = false; return tempName; } //Primitive to get file stream handle. int dropRequestFileHandle(int dropIndex) { sqInt fileOop; void *fn; char *dropName = dropRequestFileName(dropIndex); if(!dropName) return interpreterProxy->nilObject(); fn = interpreterProxy->ioLoadFunctionFrom("fileOpenNamesizewritesecure", "FilePlugin"); if (fn == 0) { /* begin primitiveFail */ interpreterProxy->success(false); return null; } fileOop = ((sqInt (*) (int, int, int, int)) fn)((int)dropName, strlen(dropName), 0,0); return fileOop; } /* RECEIVING DRAGS ------------------------------------------------ */ /* ApproveDragReference is called by the drag tracking handler to determine if the contents of the drag can be handled by our receive handler. Note that if a flavor can't be found, it's not really an error; it only means the flavor wasn't there and we should not accept the drag. Therefore, we translate 'badDragFlavorErr' into a 'false' value for '*approved'. */ static pascal OSErr ApproveDragReference(DragReference theDragRef, Boolean *approved) { OSErr err; DragAttributes dragAttrs; FlavorFlags flavorFlags; ItemReference theItem; /* we cannot drag to our own window */ if ((err = GetDragAttributes(theDragRef, &dragAttrs)) != noErr) goto bail; if ((dragAttrs & kDragInsideSenderWindow) != 0) { err = userCanceledErr; goto bail; } /* gather information about the drag & a reference to item one. */ if ((err = GetDragItemReferenceNumber(theDragRef, 1, &theItem)) != noErr) goto bail; /* check for flavorTypeHFS */ err = GetFlavorFlags(theDragRef, theItem, flavorTypeHFS, &flavorFlags); if (err == noErr) { *approved = true; return noErr; } else if (err != badDragFlavorErr) goto bail; /* check for flavorTypePromiseHFS */ err = GetFlavorFlags(theDragRef, theItem, flavorTypePromiseHFS, &flavorFlags); if (err == noErr) { *approved = true; return noErr; } else if (err != badDragFlavorErr) goto bail; /* none of our flavors were found */ *approved = false; return noErr; bail: /* an error occured, clean up. set result to false. */ *approved = false; return err; } /* MyDragTrackingHandler is called for tracking the mouse while a drag is passing over our window. if the drag is approved, then the drop box will be hilitied appropriately as the mouse passes over it. */ pascal OSErr MyDragTrackingHandler(DragTrackingMessage message, WindowPtr theWindow, void *refCon, DragReference theDragRef) { #pragma unused(refCon) /* we're drawing into the image well if we hilite... */ EventRecord theEvent; void * fn; Point mouse; switch (message) { case kDragTrackingEnterWindow: { DragAttributes currDragFlags; gApprovedDrag = false; if (theWindow == gWindowPtr) { if (ApproveDragReference(theDragRef, &gApprovedDrag) != noErr) break; if ( ! gApprovedDrag ) break; GetDragAttributes(theDragRef,&currDragFlags); if (currDragFlags) { // if we're in the box, hilite... gInIconBox = true; /* queue up an event */ GetDragMouse (theDragRef,&mouse,NULL); theEvent.what = 0; theEvent.message = 0; theEvent.modifiers = 0; theEvent.when = 0; theEvent.where = mouse; fn = interpreterProxy->ioLoadFunctionFrom("recordDragDropEvent", ""); if (fn != 0) { ((int (*) (EventRecord *theEvent, int numberOfItems, int dragType)) fn)(&theEvent, gNumDropFiles,DragEnter); } } } } break; case kDragTrackingInWindow: if (gApprovedDrag) { GetDragMouse (theDragRef,&mouse,NULL); theEvent.what = 0; theEvent.message = 0; theEvent.modifiers = 0; theEvent.when = 0; theEvent.where = mouse; fn = interpreterProxy->ioLoadFunctionFrom("recordDragDropEvent", ""); if (fn != 0) { ((int (*) (EventRecord *theEvent, int numberOfItems, int dragType)) fn)(&theEvent,gNumDropFiles,DragMove); } } break; case kDragTrackingLeaveWindow: if (gApprovedDrag && gInIconBox) { /* queue up an event */ GetDragMouse (theDragRef,&mouse,NULL); theEvent.what = 0; theEvent.message = 0; theEvent.modifiers = 0; theEvent.when = 0; theEvent.where = mouse; fn = interpreterProxy->ioLoadFunctionFrom("recordDragDropEvent", ""); if (fn != 0) { ((int (*) (EventRecord *theEvent, int numberOfItems, int dragType)) fn)(&theEvent, gNumDropFiles,DragLeave); } } gApprovedDrag = gInIconBox = false; break; } return noErr; // there's no point in confusing Drag Manager or its caller } static pascal OSErr SetDropFolder (DragReference dragRef, FSRef *folder) { OSErr err = noErr; AliasHandle aliasH; if (!(err = FSNewAliasMinimal (folder,&aliasH))) { HLockHi ((Handle) aliasH); if (!(err = MemError ( ))) { Size size = GetHandleSize ((Handle) aliasH); if (!(err = MemError ( ))) { AEDesc dropLoc; if (!(err = AECreateDesc (typeAlias,*aliasH,size,&dropLoc))) { OSErr err2; err = SetDropLocation (dragRef,&dropLoc); err2 = AEDisposeDesc (&dropLoc); if (!err) err = err2; } } } DisposeHandle ((Handle) aliasH); if (!err) err = MemError ( ); } return err; } /* MyDragReceiveHandler is the receive handler for the main window. It is called when a file or folder (or a promised file or folder) is dropped into the drop box in the main window. Here, if the drag reference has been approved in the track drag call, we handle three different cases: 1. standard hfs flavors, 2. promised flavors provided by find file, mmmm This may be a pre sherlock issue 3. promised flavors provided by other applications. */ pascal OSErr MyDragReceiveHandler(WindowPtr theWindow, void *refcon, DragReference theDragRef) { #pragma unused(refcon) #pragma unused(theWindow) ItemReference theItem; PromiseHFSFlavor targetPromise; Size theSize; OSErr err; EventRecord theEvent; long i,countActualItems; void * fn; FInfo finderInfo; HFSFlavor targetHFSFlavor; /* validate the drag. Recall the receive handler will only be called after the tracking handler has received a kDragTrackingInWindow event. As a result, the gApprovedDrag and gInIconBox will be defined when we arrive here. Hence, there is no need to spend extra time validating the drag at this point. */ if ( ! (gApprovedDrag && gInIconBox) ) return userCanceledErr; if (gNumDropFiles !=0 ) DisposePtr((char *) dropFiles); if ((err = CountDragItems(theDragRef, (UInt16 *) &gNumDropFiles)) != noErr) return paramErr; dropFiles = (HFSFlavorSqueak *) NewPtr(sizeof(HFSFlavorSqueak)*gNumDropFiles); if (dropFiles == null) { gNumDropFiles = 0; return userCanceledErr; } countActualItems = 0; for(i=1;i<=gNumDropFiles;i++) { /* get the first item reference */ if ((err = GetDragItemReferenceNumber(theDragRef, i, &theItem)) != noErr) continue; /* try to get a HFSFlavor*/ theSize = sizeof(HFSFlavor); err = GetFlavorData(theDragRef, theItem, flavorTypeHFS, &targetHFSFlavor, &theSize, 0); if (err == noErr) { dropFiles[countActualItems].fileType = targetHFSFlavor.fileType; dropFiles[countActualItems].fileCreator = targetHFSFlavor.fileCreator; dropFiles[countActualItems].fdFlags = targetHFSFlavor.fdFlags; FSpMakeFSRef(&targetHFSFlavor.fileSpec, &dropFiles[countActualItems].theFSRef); countActualItems++; continue; } else if (err != badDragFlavorErr) continue; /* try to get a promised HFSFlavor*/ theSize = sizeof(PromiseHFSFlavor); err = GetFlavorData(theDragRef, theItem, flavorTypePromiseHFS, &targetPromise, &theSize, 0); if (err != noErr) continue; /* check for a drop from find file */ if (targetPromise.promisedFlavor == kPromisedFlavorFindFile) { /* from find file, no need to set the file location... */ if (err != noErr) continue; } else { FSRef targetFolder; err = FSFindFolder(kLocalDomain, kTemporaryFolderType, kDontCreateFolder, &targetFolder); if (err != noErr) continue; err = SetDropFolder(theDragRef, &targetFolder); if (err != noErr) continue; } FSSpec aFSSpec; theSize = sizeof(FSSpec); err = GetFlavorData(theDragRef, theItem, targetPromise.promisedFlavor, &aFSSpec, &theSize, 0); if (err != noErr) continue; FSpMakeFSRef(&aFSSpec, &dropFiles[countActualItems].theFSRef); err = getFInfoViaFSRef(&dropFiles[countActualItems].theFSRef,&finderInfo); if (err != noErr) continue; dropFiles[countActualItems].fileType = finderInfo.fdType; dropFiles[countActualItems].fileCreator = finderInfo.fdCreator; dropFiles[countActualItems].fdFlags = finderInfo.fdFlags; countActualItems++; } gNumDropFiles = countActualItems; if (gNumDropFiles == 0) { DisposePtr((char *) dropFiles); return noErr; } /* queue up an event */ Point mouse; GetDragMouse (theDragRef,&mouse,NULL); theEvent.what = 0; theEvent.message = 0; theEvent.modifiers = 0; theEvent.when = 0; theEvent.where = mouse; fn = interpreterProxy->ioLoadFunctionFrom("recordDragDropEvent", ""); if (fn != 0) { ((int (*) (EventRecord *theEvent, int numberOfItems, int dragType)) fn)(&theEvent, gNumDropFiles,DragDrop); } return noErr; } void sqSetNumberOfDropFiles(int numberOfFiles) { while (gDragDropThrottleSpinLock); gDragDropThrottleSpinLock = true; if (gNumDropFiles != 0 ) { DisposePtr((char *) dropFiles); gNumDropFiles = 0; } gNumDropFiles = numberOfFiles; dropFiles = (HFSFlavorSqueak *) NewPtr(sizeof(HFSFlavorSqueak)*gNumDropFiles); if (dropFiles == null) { gNumDropFiles = 0; } return; } void sqSetFileInformation(int dropIndex, void *dropFile) { if(dropIndex < 1 || dropIndex > gNumDropFiles) return; memcpy(&dropFiles[dropIndex-1],(char *) dropFile,sizeof(HFSFlavorSqueak)); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ExuperyPlugin/sqOSXExuperyPlugin.c ================================================ #include #include #include "ExuperyPlugin.h" #include #include int ioMapCodeCache(int size) { void *value; long error; extern int errno; value = (void*) mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_SHARED,-1,0); if ((int) value == -1) { error = errno; fprintf(stderr,"ioMapCodeCache failed %i\n",error); exit(-1); } } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/FileCopy.xml ================================================ ]> FileCopyPlugin UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::Squeak:Carbon:Stub: PathFormatMacOS PathRootSystem Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:Squeak3.0 Folder:Squeak 3.0.19: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameFileCopyPlugin OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E30416C70686131384D5400000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic1 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources  MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileFileCopyPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name myMacHeaders.pch MacOS Text Debug Name FileCopyPlugin.c MacOS Text Debug Name sqMacFileCopy.c MacOS Text Debug Name FileCopy.c MacOS Text Debug Name DirectoryCopy.c MacOS Text Debug Name FSpCompat.c MacOS Text Debug Name FullPath.c MacOS Text Debug Name IterateDirectory.c MacOS Text Debug Name MoreDesktopMgr.c MacOS Text Debug Name MoreFiles.c MacOS Text Debug Name MoreFilesExtras.c MacOS Text Debug Name Search.c MacOS Text Debug Name CarbonAccessors.o MacOS Library Name DirectoryCopy.c MacOS Name FileCopyPlugin.c MacOS Name FileCopy.c MacOS Name FSpCompat.c MacOS Name FullPath.c MacOS Name IterateDirectory.c MacOS Name MoreDesktopMgr.c MacOS Name MoreFiles.c MacOS Name MoreFilesExtras.c MacOS Name Search.c MacOS Name sqMacFileCopy.c MacOS Name myMacHeaders.pch MacOS Name CarbonAccessors.o MacOS Name InterfaceLib MacOS Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name MathLib MacOS FileCopyPlugin Opt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::Squeak:Carbon:Stub: PathFormatMacOS PathRootSystem Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:Squeak3.0 Folder:Squeak 3.0.19: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameFileCopyPlugin Opt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E30416C70686131384D5400000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic1 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources  MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileFileCopyPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name myMacHeaders.pch MacOS Text Name FileCopyPlugin.c MacOS Text Name sqMacFileCopy.c MacOS Text Name FileCopy.c MacOS Text Name DirectoryCopy.c MacOS Text Name FSpCompat.c MacOS Text Name FullPath.c MacOS Text Name IterateDirectory.c MacOS Text Name MoreDesktopMgr.c MacOS Text Name MoreFiles.c MacOS Text Name MoreFilesExtras.c MacOS Text Name Search.c MacOS Text Name CarbonAccessors.o MacOS Library Name DirectoryCopy.c MacOS Name FileCopyPlugin.c MacOS Name FileCopy.c MacOS Name FSpCompat.c MacOS Name FullPath.c MacOS Name IterateDirectory.c MacOS Name MoreDesktopMgr.c MacOS Name MoreFiles.c MacOS Name MoreFilesExtras.c MacOS Name Search.c MacOS Name sqMacFileCopy.c MacOS Name myMacHeaders.pch MacOS Name CarbonAccessors.o MacOS Name InterfaceLib MacOS Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name MathLib MacOS FileCopyPlugin FileCopyPlugin Opt Group 1 FileCopyPlugin Name FileCopyPlugin.c MacOS FileCopyPlugin Name sqMacFileCopy.c MacOS FileCopyPlugin Name DirectoryCopy.c MacOS FileCopyPlugin Name FSpCompat.c MacOS FileCopyPlugin Name FullPath.c MacOS FileCopyPlugin Name IterateDirectory.c MacOS FileCopyPlugin Name MoreDesktopMgr.c MacOS FileCopyPlugin Name MoreFiles.c MacOS FileCopyPlugin Name MoreFilesExtras.c MacOS FileCopyPlugin Name Search.c MacOS FileCopyPlugin Name FileCopy.c MacOS FileCopyPlugin Name MSL C.PPC.Lib MacOS FileCopyPlugin Name MSL RuntimePPC.Lib MacOS FileCopyPlugin Name InterfaceLib MacOS FileCopyPlugin Name MathLib MacOS FileCopyPlugin Name CarbonAccessors.o MacOS FileCopyPlugin Name myMacHeaders.pch MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/DirectoryCopy.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** DirectoryCopy: A robust, general purpose directory copy routine. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: DirectoryCopy.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __DIRECTORYCOPY__ #define __DIRECTORYCOPY__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ enum { getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */ copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */ copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */ copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */ dirCreateOp = 5, /* couldn't create destination directory */ fileCopyOp = 6 /* couldn't copy file */ }; /*****************************************************************************/ typedef pascal Boolean (*CopyErrProcPtr) (OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName); /* Prototype for the CopyErrProc function DirectoryCopy calls. This is the prototype for the CopyErrProc function DirectoryCopy calls if an error condition is detected sometime during the copy. If CopyErrProc returns false, then DirectoryCopy attempts to continue with the directory copy operation. If CopyErrProc returns true, then DirectoryCopy stops the directory copy operation. error input: The error result code that caused CopyErrProc to be called. failedOperation input: The operation that returned an error to DirectoryCopy. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Source file or directory name, or nil if srcDirID specifies the directory. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Destination file or directory name, or nil if dstDirID specifies the directory. __________ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy */ #define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \ (*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName)) /*****************************************************************************/ typedef pascal Boolean (*CopyFilterProcPtr) (const CInfoPBRec * const cpbPtr); /* Prototype for the CopyFilterProc function. This is the prototype for the CopyFilterProc function called by FilteredDirectoryCopy and GetLevelSize. If true is returned, the file/folder is included in the copy, otherwise it is excluded. pb input: Points to the CInfoPBRec for the item under consideration. __________ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy */ #define CallCopyFilterProc(userRoutine, cpbPtr) (*(userRoutine))((cpbPtr)) /*****************************************************************************/ pascal OSErr FilteredDirectoryCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler, CopyFilterProcPtr copyFilterProc); /* Make a copy of a directory structure in a new location with item filtering. The FilteredDirectoryCopy function makes a copy of a directory structure in a new location. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy files data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. The optional copyFilterProc parameter lets a routine you define decide what files or directories are copied to the destination. FilteredDirectoryCopy normally creates a new directory *in* the specified destination directory and copies the source directory's content into the new directory. However, if root parent directory (fsRtParID) is passed as the dstDirID parameter and NULL is passed as the dstName parameter, DirectoryCopy renames the destination volume to the source directory's name (truncating if the name is longer than 27 characters) and copies the source directory's content into the destination volume's root directory. This special case is supported by FilteredDirectoryCopy, but not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy, the dstName parameter can not be NULL. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Source directory name, or nil if srcDirID specifies the directory. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Destination directory name, or nil if dstDirID specifies the directory. copyName input: Points to the new directory name if the directory is to be renamed or nil if the directory isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want DirectoryCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, DirectoryCopy makes sure there are enough allocation blocks on the destination volume to hold the directory's files before starting the copy. copyErrHandler input: A pointer to the routine you want called if an error condition is detected during the copy, or nil if you don't want to handle error conditions. If you don't handle error conditions, the first error will cause the copy to quit and DirectoryCopy will return the error. Error handling is recommended... copyFilterProc input: A pointer to the filter routine you want called for each item in the source directory, or NULL if you don't want to filter. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy */ /*****************************************************************************/ pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler, CopyFilterProcPtr copyFilterProc); /* Make a copy of a directory structure in a new location with item filtering. The FSpFilteredDirectoryCopy function makes a copy of a directory structure in a new location. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy files data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. The optional copyFilterProc parameter lets a routine you define decide what files or directories are copied to the destination. srcSpec input: An FSSpec record specifying the directory to copy. dstSpec input: An FSSpec record specifying destination directory of the copy. copyName input: Points to the new directory name if the directory is to be renamed or nil if the directory isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want DirectoryCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, FSpDirectoryCopy makes sure there are enough allocation blocks on the destination volume to hold the directory's files before starting the copy. copyErrHandler input: A pointer to the routine you want called if an error condition is detected during the copy, or nil if you don't want to handle error conditions. If you don't handle error conditions, the first error will cause the copy to quit and DirectoryCopy will return the error. Error handling is recommended... copyFilterProc input: A pointer to the filter routine you want called for each item in the source directory, or NULL if you don't want to filter. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: CopyErrProcPtr, CopyFilterProcPtr, FilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy */ /*****************************************************************************/ pascal OSErr DirectoryCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler); /* Make a copy of a directory structure in a new location. The DirectoryCopy function makes a copy of a directory structure in a new location. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy files data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. DirectoryCopy normally creates a new directory *in* the specified destination directory and copies the source directory's content into the new directory. However, if root parent directory (fsRtParID) is passed as the dstDirID parameter and NULL is passed as the dstName parameter, DirectoryCopy renames the destination volume to the source directory's name (truncating if the name is longer than 27 characters) and copies the source directory's content into the destination volume's root directory. This special case is supported by DirectoryCopy, but not by FSpDirectoryCopy since with FSpDirectoryCopy, the dstName parameter can not be NULL. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Source directory name, or nil if srcDirID specifies the directory. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Destination directory name, or nil if dstDirID specifies the directory. copyName input: Points to the new directory name if the directory is to be renamed or nil if the directory isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want DirectoryCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, DirectoryCopy makes sure there are enough allocation blocks on the destination volume to hold the directory's files before starting the copy. copyErrHandler input: A pointer to the routine you want called if an error condition is detected during the copy, or nil if you don't want to handle error conditions. If you don't handle error conditions, the first error will cause the copy to quit and DirectoryCopy will return the error. Error handling is recommended... Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: CopyErrProcPtr, FSpDirectoryCopy, FilteredDirectoryCopy, FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy */ /*****************************************************************************/ pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler); /* Make a copy of a directory structure in a new location. The FSpDirectoryCopy function makes a copy of a directory structure in a new location. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy files data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. srcSpec input: An FSSpec record specifying the directory to copy. dstSpec input: An FSSpec record specifying destination directory of the copy. copyName input: Points to the new directory name if the directory is to be renamed or nil if the directory isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want DirectoryCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, FSpDirectoryCopy makes sure there are enough allocation blocks on the destination volume to hold the directory's files before starting the copy. copyErrHandler input: A pointer to the routine you want called if an error condition is detected during the copy, or nil if you don't want to handle error conditions. If you don't handle error conditions, the first error will cause the copy to quit and DirectoryCopy will return the error. Error handling is recommended... Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy, FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __DIRECTORYCOPY__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/FSpCompat.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** FSSpec compatibility functions. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FSpCompat.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __FSPCOMPAT__ #define __FSPCOMPAT__ #if 0 #include #include #include "Optimization.h" #endif 0 #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ pascal OSErr FSMakeFSSpecCompat(short vRefNum, long dirID, ConstStr255Param fileName, FSSpec *spec); /* Initialize a FSSpec record. The FSMakeFSSpecCompat function fills in the fields of an FSSpec record. If the file system can't create the FSSpec, then the compatibility code creates a FSSpec that is exactly like an FSSpec except that spec.name for a file may not have the same capitalization as the file's catalog entry on the disk volume. That is because fileName is parsed to get the name instead of getting the name back from the file system. This works fine with System 6 where FSMakeSpec isn't available. vRefNum input: Volume specification. dirID input: Directory ID. fileName input: Pointer to object name, or nil when dirID specifies a directory that's the object. spec output: A file system specification to be filled in by FSMakeFSSpecCompat. Result Codes noErr 0 No error nsvErr -35 Volume doesnt exist fnfErr -43 File or directory does not exist (FSSpec is still valid) */ /*****************************************************************************/ pascal OSErr FSpOpenDFCompat(const FSSpec *spec, char permission, short *refNum); /* Open a file's data fork. The FSpOpenDFCompat function opens the data fork of the file specified by spec. Differences from FSpOpenDF: If FSpOpenDF isn't available, FSpOpenDFCompat uses PHBOpen because System 6 doesn't support PBHOpenDF. This means FSpOpenDFCompat could accidentally open a driver if the spec->name begins with a period. spec input: An FSSpec record specifying the file whose data fork is to be opened. permission input: A constant indicating the desired file access permissions. refNum output: A reference number of an access path to the file's data fork. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 File not found opWrErr -49 File already open for writing permErr -54 Attempt to open locked file for writing dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access to the file __________ See also: FSpOpenAware */ /*****************************************************************************/ pascal OSErr FSpOpenRFCompat(const FSSpec *spec, char permission, short *refNum); /* Open a file's resource fork. The FSpOpenRFCompat function opens the resource fork of the file specified by spec. spec input: An FSSpec record specifying the file whose resource fork is to be opened. permission input: A constant indicating the desired file access permissions. refNum output: A reference number of an access path to the file's resource fork. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 File not found opWrErr -49 File already open for writing permErr -54 Attempt to open locked file for writing dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access to the file __________ See also: FSpOpenRFAware */ /*****************************************************************************/ pascal OSErr FSpCreateCompat(const FSSpec *spec, OSType creator, OSType fileType, ScriptCode scriptTag); /* Create a new file. The FSpCreateCompat function creates a new file with the specified type, creator, and script code. Differences from FSpCreate: FSpCreateCompat correctly sets the fdScript in the file's FXInfo record to scriptTag if the problem isn't fixed in the File Manager code. spec input: An FSSpec record specifying the file to create. creator input: The creator of the new file. fileType input The file type of the new file. scriptCode input: The code of the script system in which the file name is to be displayed. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 Directory not found or incomplete pathname wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 A directory exists with that name */ /*****************************************************************************/ pascal OSErr FSpDirCreateCompat(const FSSpec *spec, ScriptCode scriptTag, long *createdDirID); /* Create a new directory. The FSpDirCreateCompat function creates a new directory and returns the directory ID of the newDirectory. spec input: An FSSpec record specifying the directory to create. scriptCode input: The code of the script system in which the directory name is to be displayed. createdDirID output: The directory ID of the directory that was created. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 Directory not found or incomplete pathname wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version dirNFErrdirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Not an HFS volume afpAccessDenied -5000 User does not have the correct access */ /*****************************************************************************/ pascal OSErr FSpDeleteCompat(const FSSpec *spec); /* Delete a file or directory. The FSpDeleteCompat function deletes a file or directory. spec input: An FSSpec record specifying the file or directory to delete. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock fBsyErr -47 File busy, directory not empty, or working directory control block open dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access */ /*****************************************************************************/ pascal OSErr FSpGetFInfoCompat(const FSSpec *spec, FInfo *fndrInfo); /* Get the finder information for a file. The FSpGetFInfoCompat function gets the finder information for a file. spec input: An FSSpec record specifying the file. fndrInfo output: If the object is a file, then its FInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpGetDInfo */ /*****************************************************************************/ pascal OSErr FSpSetFInfoCompat(const FSSpec *spec, const FInfo *fndrInfo); /* Set the finder information for a file. The FSpSetFInfoCompat function sets the finder information for a file. spec input: An FSSpec record specifying the file. fndrInfo input: The FInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Object was a directory __________ Also see: FSpSetDInfo */ /*****************************************************************************/ pascal OSErr FSpSetFLockCompat(const FSSpec *spec); /* Lock a file. The FSpSetFLockCompat function locks a file. spec input: An FSSpec record specifying the file. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error fnfErr -43 File not found wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access to the file afpObjectTypeErr -5025 Folder locking not supported by volume */ /*****************************************************************************/ pascal OSErr FSpRstFLockCompat(const FSSpec *spec); /* Unlock a file. The FSpRstFLockCompat function unlocks a file. spec input: An FSSpec record specifying the file. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error fnfErr -43 File not found wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access to the file afpObjectTypeErr -5025 Folder locking not supported by volume */ /*****************************************************************************/ pascal OSErr FSpRenameCompat(const FSSpec *spec, ConstStr255Param newName); /* Rename a file or directory. The FSpRenameCompat function renames a file or directory. spec input: An FSSpec record specifying the file. newName input: The new name of the file or directory. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version paramErr -50 No default volume fsRnErr -59 Problem during rename dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access to the file */ /*****************************************************************************/ pascal OSErr FSpCatMoveCompat(const FSSpec *source, const FSSpec *dest); /* Move a file or directory to a different location on on the same volume. The FSpCatMoveCompat function moves a file or directory to a different location on on the same volume. source input: An FSSpec record specifying the file or directory. dest input: An FSSpec record specifying the name and location of the directory into which the source file or directory is to be moved. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename or attempt to move into a file fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 Target directory is locked vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version paramErr -50 No default volume badMovErr -122 Attempt to move into offspring wrgVolTypErr -123 Not an HFS volume afpAccessDenied -5000 User does not have the correct access to the file */ /*****************************************************************************/ pascal OSErr FSpExchangeFilesCompat(const FSSpec *source, const FSSpec *dest); /* Exchange the data stored in two files on the same volume. The FSpExchangeFilesCompat function swaps the data in two files by changing the information in the volume's catalog and, if the files are open, in the file control blocks. Differences from FSpExchangeFiles: Correctly exchanges files on volumes that don't support PBExchangeFiles. FSpExchangeFiles attempts to support volumes that don't support PBExchangeFiles, but in System 7, 7.0.1, 7.1, and 7 Pro, the compatibility code just doesn't work on volumes that don't support PBExchangeFiles (even though you may get a noErr result). System Update 3.0 and System 7.5 and later have the problems in FSpExchangeFiles corrected. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline wrgVolTypErr -123 Not an HFS volume diffVolErr -1303 Files on different volumes afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Object is a directory, not a file afpSameObjectErr -5038 Source and destination files are the same */ /*****************************************************************************/ pascal short FSpOpenResFileCompat(const FSSpec *spec, SignedByte permission); /* Open a file's resource file. The FSpOpenResFileCompat function opens the resource file specified by spec. spec input: An FSSpec record specifying the file whose resource file is to be opened. permission input: A constant indicating the desired file access permissions. function result output: A resource file reference number, or if there's an error -1. Result Codes noErr 0 No error nsvErr 35 No such volume ioErr 36 I/O error bdNamErr 37 Bad filename or volume name (perhaps zero length) eofErr 39 End of file tmfoErr 42 Too many files open fnfErr 43 File not found opWrErr 49 File already open with write permission permErr 54 Permissions error (on file open) extFSErr 58 Volume belongs to an external file system memFullErr 108 Not enough room in heap zone dirNFErr 120 Directory not found mapReadErr 199 Map inconsistent with operation */ /*****************************************************************************/ pascal void FSpCreateResFileCompat(const FSSpec *spec, OSType creator, OSType fileType, ScriptCode scriptTag); /* Create a resource file. The FSpCreateResFileCompat function creates a new resource file with the specified type, creator, and script code. Differences from FSpCreateResFile: FSpCreateResFileCompat correctly sets the fdScript in the file's FXInfo record to scriptTag if the problem isn't fixed in the File Manager code. spec input: An FSSpec record specifying the resource file to create. creator input: The creator of the new file. fileType input The file type of the new file. scriptCode input: The code of the script system in which the file name is to be displayed. Result Codes noErr 0 No error dirFulErr 33 Directory full dskFulErr 34 Disk full nsvErr 35 No such volume ioErr 36 I/O error bdNamErr 37 Bad filename or volume name (perhaps zero length) tmfoErr 42 Too many files open wPrErrw 44 Disk is write-protected fLckdErr 45 File is locked */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __FSPCOMPAT__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/FileCopy.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** FileCopy: A robust, general purpose file copy routine. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FileCopy.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __FILECOPY__ #define __FILECOPY__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ pascal OSErr FileCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstPathname, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight); /* Duplicate a file and optionally rename it. The FileCopy function duplicates a file and optionally renames it. Since the PBHCopyFile routine is only available on some AFP server volumes under specific conditions, this routine either uses PBHCopyFile, or does all of the work PBHCopyFile does. The srcVRefNum, srcDirID and srcName are used to determine the location of the file to copy. The dstVRefNum dstDirID and dstPathname are used to determine the location of the destination directory. If copyName <> NIL, then it points to the name of the new file. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy the file's data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Source file name. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstPathname input: Pointer to destination directory name, or nil when dstDirID specifies a directory. copyName input: Points to the new file name if the file is to be renamed or nil if the file isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want FileCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, FileCopy makes sure there are enough allocation blocks on the destination volume to hold both the data and resource forks before starting the copy. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: FSpFileCopy, DirectoryCopy, FSpDirectoryCopy */ /*****************************************************************************/ pascal OSErr FSpFileCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight); /* Duplicate a file and optionally rename it. The FSpFileCopy function duplicates a file and optionally renames it. Since the PBHCopyFile routine is only available on some AFP server volumes under specific conditions, this routine either uses PBHCopyFile, or does all of the work PBHCopyFile does. The srcSpec is used to determine the location of the file to copy. The dstSpec is used to determine the location of the destination directory. If copyName <> NIL, then it points to the name of the new file. If copyBufferPtr <> NIL, it points to a buffer of copyBufferSize that is used to copy the file's data. The larger the supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this routine allocates a buffer in the application heap. If you pass a copy buffer to this routine, make its size a multiple of 512 ($200) bytes for optimum performance. srcSpec input: An FSSpec record specifying the source file. dstSpec input: An FSSpec record specifying the destination directory. copyName input: Points to the new file name if the file is to be renamed or nil if the file isn't to be renamed. copyBufferPtr input: Points to a buffer of copyBufferSize that is used the i/o buffer for the copy or nil if you want FileCopy to allocate its own buffer in the application heap. copyBufferSize input: The size of the buffer pointed to by copyBufferPtr. preflight input: If true, FSpFileCopy makes sure there are enough allocation blocks on the destination volume to hold both the data and resource forks before starting the copy. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Destination volume is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename tmfoErr -42 Too many files open fnfErr -43 Source file not found, or destination directory does not exist wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists opWrErr -49 File already open for writing paramErr -50 No default volume or function not supported by volume permErr -54 File is already open and cannot be opened using specified deny modes memFullErr -108 Copy buffer could not be allocated dirNFErr -120 Directory not found or incomplete pathname wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 User does not have the correct access afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory, directory not found or incomplete pathname __________ Also see: FileCopy, DirectoryCopy, FSpDirectoryCopy */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __FILECOPY__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/FullPath.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** Routines for dealing with full pathnames... if you really must. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FullPath.h ** ** Copyright 1995-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __FULLPATH__ #define __FULLPATH__ #if 0 #include #include #include "Optimization.h" #endif 0 #ifdef __cplusplus extern "C" { #endif /* IMPORTANT NOTE: The use of full pathnames is strongly discouraged. Full pathnames are particularly unreliable as a means of identifying files, directories or volumes within your application, for two primary reasons: The user can change the name of any element in the path at virtually any time. Volume names on the Macintosh are *not* unique. Multiple mounted volumes can have the same name. For this reason, the use of a full pathname to identify a specific volume may not produce the results you expect. If more than one volume has the same name and a full pathname is used, the File Manager currently uses the first mounted volume it finds with a matching name in the volume queue. In general, you should use a files name, parent directory ID, and volume reference number to identify a file you want to open, delete, or otherwise manipulate. If you need to remember the location of a particular file across subsequent system boots, use the Alias Manager to create an alias record describing the file. If the Alias Manager is not available, you can save the files name, its parent directory ID, and the name of the volume on which its located. Although none of these methods is foolproof, they are much more reliable than using full pathnames to identify files. Nonetheless, it is sometimes useful to display a files full pathname to the user. For example, a backup utility might display a list of full pathnames of files as it copies them onto the backup medium. Or, a utility might want to display a dialog box showing the full pathname of a file when it needs the users confirmation to delete the file. No matter how unreliable full pathnames may be from a file-specification viewpoint, users understand them more readily than volume reference numbers or directory IDs. (Hint: Use the TruncString function from TextUtils.h with truncMiddle as the truncWhere argument to shorten full pathnames to a displayable length.) The following technique for constructing the full pathname of a file is intended for display purposes only. Applications that depend on any particular structure of a full pathname are likely to fail on alternate foreign file systems or under future system software versions. */ /*****************************************************************************/ pascal OSErr GetFullPath(short vRefNum, long dirID, ConstStr255Param name, short *fullPathLength, Handle *fullPath); /* Get a full pathname to a volume, directory or file. The GetFullPath function builds a full pathname to the specified object. The full pathname is returned in the newly created handle fullPath and the length of the full pathname is returned in fullPathLength. Your program is responsible for disposing of the fullPath handle. Note that a full pathname can be made to a file/directory that does not yet exist if all directories up to that file/directory exist. In this case, GetFullPath will return a fnfErr. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. fullPathLength output: The number of characters in the full pathname. If the function fails to create a full pathname, it sets fullPathLength to 0. fullPath output: A handle to the newly created full pathname buffer. If the function fails to create a full pathname, it sets fullPath to NULL. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File or directory does not exist (fullPath and fullPathLength are still valid) paramErr -50 No default volume memFullErr -108 Not enough memory dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpGetFullPath */ /*****************************************************************************/ pascal OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath); /* Get a full pathname to a volume, directory or file. The GetFullPath function builds a full pathname to the specified object. The full pathname is returned in the newly created handle fullPath and the length of the full pathname is returned in fullPathLength. Your program is responsible for disposing of the fullPath handle. Note that a full pathname can be made to a file/directory that does not yet exist if all directories up to that file/directory exist. In this case, FSpGetFullPath will return a fnfErr. spec input: An FSSpec record specifying the object. fullPathLength output: The number of characters in the full pathname. If the function fails to create a full pathname, it sets fullPathLength to 0. fullPath output: A handle to the newly created full pathname buffer. If the function fails to create a full pathname, it sets fullPath to NULL. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File or directory does not exist (fullPath and fullPathLength are still valid) paramErr -50 No default volume memFullErr -108 Not enough memory dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: GetFullPath */ /*****************************************************************************/ pascal OSErr FSpLocationFromFullPath(short fullPathLength, const void *fullPath, FSSpec *spec); /* Get a FSSpec from a full pathname. The FSpLocationFromFullPath function returns a FSSpec to the object specified by full pathname. This function requires the Alias Manager. fullPathLength input: The number of characters in the full pathname of the target. fullPath input: A pointer to a buffer that contains the full pathname of the target. The full pathname starts with the name of the volume, includes all of the directory names in the path to the target, and ends with the target name. spec output: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 The volume is not mounted fnfErr -43 Target not found, but volume and parent directory found paramErr -50 Parameter error usrCanceledErr -128 The user canceled the operation __________ See also: LocationFromFullPath */ /*****************************************************************************/ pascal OSErr LocationFromFullPath(short fullPathLength, const void *fullPath, short *vRefNum, long *parID, Str31 name); /* Get an object's location from a full pathname. The LocationFromFullPath function returns the volume reference number, parent directory ID and name of the object specified by full pathname. This function requires the Alias Manager. fullPathLength input: The number of characters in the full pathname of the target. fullPath input: A pointer to a buffer that contains the full pathname of the target. The full pathname starts with the name of the volume, includes all of the directory names in the path to the target, and ends with the target name. vRefNum output: The volume reference number. parID output: The parent directory ID of the specified object. name output: The name of the specified object. Result Codes noErr 0 No error nsvErr -35 The volume is not mounted fnfErr -43 Target not found, but volume and parent directory found paramErr -50 Parameter error usrCanceledErr -128 The user canceled the operation __________ See also: FSpLocationFromFullPath */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __FULLPATH__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/IterateDirectory.h ================================================ /* ** IterateDirectory: File Manager directory iterator routines. ** ** by Jim Luther ** ** File: IterateDirectory.h ** ** Copyright 1995-1999 Jim Luther and Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. ** ** IterateDirectory is designed to drop into the MoreFiles sample code ** library I wrote while in Apple Developer Technical Support */ #ifndef __ITERATEDIRECTORY__ #define __ITERATEDIRECTORY__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ typedef pascal void (*IterateFilterProcPtr) (const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void *yourDataPtr); /* Prototype for the IterateFilterProc function IterateDirectory calls. This is the prototype for the IterateFilterProc function which is called once for each file and directory found by IterateDirectory. The IterateFilterProc gets a pointer to the CInfoPBRec that IterateDirectory used to call PBGetCatInfo. The IterateFilterProc can use the read-only data in the CInfoPBRec for whatever it wants. If the IterateFilterProc wants to stop IterateDirectory, it can set quitFlag to true (quitFlag will be passed to the IterateFilterProc false). The yourDataPtr parameter can point to whatever data structure you might want to access from within the IterateFilterProc. cpbPtr input: A pointer to the CInfoPBRec that IterateDirectory used to call PBGetCatInfo. The CInfoPBRec and the data it points to must not be changed by your IterateFilterProc. quitFlag output: Your IterateFilterProc can set quitFlag to true if it wants to stop IterateDirectory. yourDataPtr input: A pointer to whatever data structure you might want to access from within the IterateFilterProc. __________ Also see: IterateDirectory, FSpIterateDirectory */ #define CallIterateFilterProc(userRoutine, cpbPtr, quitFlag, yourDataPtr) \ (*(userRoutine))((cpbPtr), (quitFlag), (yourDataPtr)) /*****************************************************************************/ pascal OSErr IterateDirectory(short vRefNum, long dirID, ConstStr255Param name, unsigned short maxLevels, IterateFilterProcPtr iterateFilter, void *yourDataPtr); /* Iterate (scan) through a directory's content. The IterateDirectory function performs a recursive iteration (scan) of the specified directory and calls your IterateFilterProc function once for each file and directory found. The maxLevels parameter lets you control how deep the recursion goes. If maxLevels is 1, IterateDirectory only scans the specified directory; if maxLevels is 2, IterateDirectory scans the specified directory and one subdirectory below the specified directory; etc. Set maxLevels to zero to scan all levels. The yourDataPtr parameter can point to whatever data structure you might want to access from within the IterateFilterProc. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. maxLevels input: Maximum number of directory levels to scan or zero to scan all directory levels. iterateFilter input: A pointer to the routine you want called once for each file and directory found by IterateDirectory. yourDataPtr input: A pointer to whatever data structure you might want to access from within the IterateFilterProc. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume or iterateFilter was NULL dirNFErr -120 Directory not found or incomplete pathname or a file was passed instead of a directory afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: IterateFilterProcPtr, FSpIterateDirectory */ /*****************************************************************************/ pascal OSErr FSpIterateDirectory(const FSSpec *spec, unsigned short maxLevels, IterateFilterProcPtr iterateFilter, void *yourDataPtr); /* Iterate (scan) through a directory's content. The FSpIterateDirectory function performs a recursive iteration (scan) of the specified directory and calls your IterateFilterProc function once for each file and directory found. The maxLevels parameter lets you control how deep the recursion goes. If maxLevels is 1, FSpIterateDirectory only scans the specified directory; if maxLevels is 2, FSpIterateDirectory scans the specified directory and one subdirectory below the specified directory; etc. Set maxLevels to zero to scan all levels. The yourDataPtr parameter can point to whatever data structure you might want to access from within the IterateFilterProc. spec input: An FSSpec record specifying the directory to scan. maxLevels input: Maximum number of directory levels to scan or zero to scan all directory levels. iterateFilter input: A pointer to the routine you want called once for each file and directory found by FSpIterateDirectory. yourDataPtr input: A pointer to whatever data structure you might want to access from within the IterateFilterProc. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume or iterateFilter was NULL dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: IterateFilterProcPtr, IterateDirectory */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __ITERATEDIRECTORY__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/MoreDesktopMgr.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** A collection of useful high-level Desktop Manager routines. ** If the Desktop Manager isn't available, use the Desktop file ** for 'read' operations. ** ** We do more because we can... ** ** by Jim Luther and Nitin Ganatra, Apple Developer Technical Support Emeriti ** ** File: MoreDesktopMgr.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __MOREDESKTOPMGR__ #define __MOREDESKTOPMGR__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ pascal OSErr DTOpen(ConstStr255Param volName, short vRefNum, short *dtRefNum, Boolean *newDTDatabase); /* Open a volume's desktop database and return the desktop database refNum. The DTOpen function opens a volume's desktop database. It returns the reference number of the desktop database and indicates if the desktop database was created as a result of this call (if it was created, then it is empty). volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. dtRefNum output: The reference number of Desktop Manager's desktop database on the specified volume. newDTDatabase output: true if the desktop database was created as a result of this call and thus empty. false if the desktop database was already created, or if it could not be determined if it was already created. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 Volume doesn't support this function extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete */ /*****************************************************************************/ pascal OSErr DTXGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, Boolean searchCatalog, short *applVRefNum, long *applParID, Str255 applName); /* Find an application on a volume that can open a file with a given creator. The DTXGetAPPL function finds an application (file type 'APPL') with the specified creator on the specified volume. It first tries to get the application mapping from the desktop database. If that fails, then it tries to find an application in the Desktop file. If that fails and searchCatalog is true, then it tries to find an application with the specified creator using the File Manager's CatSearch routine. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. creator input: The file's creator type. searchCatalog input: If true, search the catalog for the application if it isn't found in the desktop database. applVRefNum output: The volume reference number of the volume the application is on. applParID output: The parent directory ID of the application. applName output: The name of the application. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 No default volume rfNumErr -51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: FSpDTGetAPPL */ /*****************************************************************************/ pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, Boolean searchCatalog, FSSpec *spec); /* Find an application on a volume that can open a file with a given creator. The FSpDTXGetAPPL function finds an application (file type 'APPL') with the specified creator on the specified volume. It first tries to get the application mapping from the desktop database. If that fails, then it tries to find an application in the Desktop file. If that fails and searchCatalog is true, then it tries to find an application with the specified creator using the File Manager's CatSearch routine. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. creator input: The file's creator type. searchCatalog input: If true, search the catalog for the application if it isn't found in the desktop database. spec output: FSSpec record containing the application name and location. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 No default volume rfNumErr -51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: FSpDTGetAPPL */ /*****************************************************************************/ pascal OSErr DTGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, short *applVRefNum, long *applParID, Str255 applName); /* Find an application on a volume that can open a file with a given creator. The DTGetAPPL function finds an application (file type 'APPL') with the specified creator on the specified volume. It first tries to get the application mapping from the desktop database. If that fails, then it tries to find an application in the Desktop file. If that fails, then it tries to find an application with the specified creator using the File Manager's CatSearch routine. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. creator input: The file's creator type. applVRefNum output: The volume reference number of the volume the application is on. applParID output: The parent directory ID of the application. applName output: The name of the application. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 No default volume rfNumErr -51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: FSpDTGetAPPL */ /*****************************************************************************/ pascal OSErr FSpDTGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, FSSpec *spec); /* Find an application on a volume that can open a file with a given creator. The FSpDTGetAPPL function finds an application (file type 'APPL') with the specified creator on the specified volume. It first tries to get the application mapping from the desktop database. If that fails, then it tries to find an application in the Desktop file. If that fails, then it tries to find an application with the specified creator using the File Manager's CatSearch routine. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. creator input: The file's creator type. spec output: FSSpec record containing the application name and location. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 No default volume rfNumErr -51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: DTGetAPPL */ /*****************************************************************************/ pascal OSErr DTGetIcon(ConstStr255Param volName, short vRefNum, short iconType, OSType fileCreator, OSType fileType, Handle *iconHandle); /* Get an icon from the desktop database or Desktop file. The DTGetIcon function retrieves the specified icon and returns it in a newly created handle. The icon is retrieves from the Desktop Manager or if the Desktop Manager is not available, from the Finder's Desktop file. Your program is responsible for disposing of the handle when it is done using the icon. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. iconType input: The icon type as defined in Files.h. Valid values are: kLargeIcon kLarge4BitIcon kLarge8BitIcon kSmallIcon kSmall4BitIcon kSmall8BitIcon fileCreator input: The icon's creator type. fileType input: The icon's file type. iconHandle output: A Handle containing the newly created icon. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error paramErr -50 Volume doesn't support this function rfNumErr -51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call memFullErr -108 iconHandle could not be allocated desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found */ /*****************************************************************************/ pascal OSErr DTSetComment(short vRefNum, long dirID, ConstStr255Param name, ConstStr255Param comment); /* Set a file or directory's Finder comment field. The DTSetComment function sets a file or directory's Finder comment field. The volume must support the Desktop Manager because you only have read access to the Desktop file. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. comment input: The comment to add. Comments are limited to 200 characters; longer comments are truncated. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr 43 File or directory doesnt exist paramErr -50 Volume doesn't support this function wPrErr 44 Volume is locked through hardware vLckdErr 46 Volume is locked through software rfNumErr 51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete __________ Also see: DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment, FSpDTGetComment */ /*****************************************************************************/ pascal OSErr FSpDTSetComment(const FSSpec *spec, ConstStr255Param comment); /* Set a file or directory's Finder comment field. The FSpDTSetComment function sets a file or directory's Finder comment field. The volume must support the Desktop Manager because you only have read access to the Desktop file. spec input: An FSSpec record specifying the file or directory. comment input: The comment to add. Comments are limited to 200 characters; longer comments are truncated. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr 43 File or directory doesnt exist wPrErr 44 Volume is locked through hardware vLckdErr 46 Volume is locked through software rfNumErr 51 Reference number invalid paramErr -50 Volume doesn't support this function extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete __________ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment, FSpDTGetComment */ /*****************************************************************************/ pascal OSErr DTGetComment(short vRefNum, long dirID, ConstStr255Param name, Str255 comment); /* Get a file or directory's Finder comment field (if any). The DTGetComment function gets a file or directory's Finder comment field (if any) from the Desktop Manager or if the Desktop Manager is not available, from the Finder's Desktop file. IMPORTANT NOTE: Inside Macintosh says that comments are up to 200 characters. While that may be correct for the HFS file system's Desktop Manager, other file systems (such as Apple Photo Access) return up to 255 characters. Make sure the comment buffer is a Str255 or you'll regret it. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. comment output: A Str255 where the comment is to be returned. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found paramErr -50 Volume doesn't support this function rfNumErr 51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment, FSpDTGetComment */ /*****************************************************************************/ pascal OSErr FSpDTGetComment(const FSSpec *spec, Str255 comment); /* Get a file or directory's Finder comment field (if any). The FSpDTGetComment function gets a file or directory's Finder comment field (if any) from the Desktop Manager or if the Desktop Manager is not available, from the Finder's Desktop file. IMPORTANT NOTE: Inside Macintosh says that comments are up to 200 characters. While that may be correct for the HFS file system's Desktop Manager, other file systems (such as Apple Photo Access) return up to 255 characters. Make sure the comment buffer is a Str255 or you'll regret it. spec input: An FSSpec record specifying the file or directory. comment output: A Str255 where the comment is to be returned. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found paramErr -50 Volume doesn't support this function rfNumErr 51 Reference number invalid extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment */ /*****************************************************************************/ pascal OSErr DTCopyComment(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName); /* Copy the file or folder comment from the source to the destination object. The DTCopyComment function copies the file or folder comment from the source to the destination object. The destination volume must support the Desktop Manager because you only have read access to the Desktop file. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Pointer to source object name, or nil when srcDirID specifies a directory that's the object. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Pointer to destination object name, or nil when dstDirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr 43 File or directory doesnt exist wPrErr 44 Volume is locked through hardware vLckdErr 46 Volume is locked through software paramErr -50 Volume doesn't support this function rfNumErr 51 Reference number invalid paramErr -50 Volume doesn't support this function extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: FSpDTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment, FSpDTGetComment */ /*****************************************************************************/ pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec, const FSSpec *dstSpec); /* Copy the desktop database comment from the source to the destination object. The FSpDTCopyComment function copies the desktop database comment from the source to the destination object. Both the source and the destination volumes must support the Desktop Manager. srcSpec input: An FSSpec record specifying the source object. dstSpec input: An FSSpec record specifying the destination object. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr 43 File or directory doesnt exist wPrErr 44 Volume is locked through hardware vLckdErr 46 Volume is locked through software paramErr -50 Volume doesn't support this function rfNumErr 51 Reference number invalid paramErr -50 Volume doesn't support this function extFSErr -58 External file system error - no file system claimed this call. desktopDamagedErr -1305 The desktop database has become corrupted - the Finder will fix this, but if your application is not running with the Finder, use PBDTReset or PBDTDelete afpItemNotFound -5012 Information not found __________ Also see: DTCopyComment, DTSetComment, FSpDTSetComment, DTGetComment, FSpDTGetComment */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __MOREDESKTOPMGR__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/MoreFiles.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** The long lost high-level and FSSpec File Manager functions. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: MoreFiles.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __MOREFILES__ #define __MOREFILES__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ pascal OSErr HGetVolParms(ConstStr255Param volName, short vRefNum, GetVolParmsInfoBuffer *volParmsInfo, long *infoSize); /* Determine the characteristics of a volume. The HGetVolParms function returns information about the characteristics of a volume. A result of paramErr usually just means the volume doesn't support PBHGetVolParms and the feature you were going to check for isn't available. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. volParmsInfo input: Pointer to GetVolParmsInfoBuffer where the volume attributes information is returned. output: Atributes information. infoSize input: Size of buffer pointed to by volParmsInfo. output: Size of data actually returned. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Volume doesn't support this function __________ Also see the macros for checking attribute bits in MoreFilesExtras.h */ /*****************************************************************************/ pascal OSErr HCreateMinimum(short vRefNum, long dirID, ConstStr255Param fileName); /* Create a new file with no creator or file type. The HCreateMinimum function creates a new file without attempting to set the creator and file type of the new file. This function is needed to create a file in an AppleShare "drop box" where the user can make changes, but cannot see folder or files. vRefNum input: Volume specification. dirID input: Directory ID. fileName input: The name of the new file. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 Directory not found or incomplete pathname wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 A directory exists with that name __________ Also see: FSpCreateMinimum */ /*****************************************************************************/ pascal OSErr FSpCreateMinimum(const FSSpec *spec); /* Create a new file with no creator or file type. The FSpCreateMinimum function creates a new file without attempting to set the the creator and file type of the new file. This function is needed to create a file in an AppleShare "dropbox" where the user can make changes, but cannot see folder or files. spec input: An FSSpec record specifying the file to create. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 Directory not found or incomplete pathname wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock dupFNErr -48 Duplicate filename and version dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 A directory exists with that name __________ Also see: HCreateMinimum */ /*****************************************************************************/ pascal OSErr ExchangeFiles(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstName); /* Exchange the data stored in two files on the same volume. The ExchangeFiles function swaps the data in two files on the same volume by changing some of the information in the volume catalog and, if the files are open, in the file control blocks. vRefNum input: Volume specification. srcDirID input: Source directory ID. srcName input: Source file name. dstDirID input: Destination directory ID. dstName input: Destination file name. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline wrgVolTypErr -123 Not an HFS volume diffVolErr -1303 Files on different volumes afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Object is a directory, not a file afpSameObjectErr -5038 Source and destination are the same __________ Also see: FSpExchangeFilesCompat */ /*****************************************************************************/ pascal OSErr ResolveFileIDRef(ConstStr255Param volName, short vRefNum, long fileID, long *parID, StringPtr fileName); /* Retrieve the location of the file with the specified file ID reference. The ResolveFileIDRef function returns the filename and parent directory ID of the file with the specified file ID reference. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. fileID input: The file ID reference. parID output: The parent directory ID of the file. name input: Points to a buffer (minimum Str63) where the filename is to be returned or must be nil. output: The filename. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline extFSErr -58 External file system error - no file system claimed this call. wrgVolTypErr -123 Not an HFS volume fidNotFoundErr -1300 File ID reference not found notAFileErr -1302 Specified file is a directory afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Specified file is a directory afpIDNotFound -5034 File ID reference not found afpBadIDErr -5039 File ID reference not found __________ Also see: FSpResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, DeleteFileIDRef */ /*****************************************************************************/ pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName, short vRefNum, long fileID, FSSpecPtr spec); /* Retrieve the location of the file with the specified file ID reference. The FSpResolveFileIDRef function fills in an FSSpec with the location of the file with the specified file ID reference. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. fileID input: The file ID reference. spec input: A pointer to a FSSpec record. output: A file system specification to be filled in by FSpResolveFileIDRef. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found paramErr -50 Function not supported by volume or no default volume volOfflinErr -53 Volume is offline extFSErr -58 External file system error - no file system claimed this call. wrgVolTypErr -123 Not an HFS volume fidNotFoundErr -1300 File ID reference not found notAFileErr -1302 Specified file is a directory afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Specified file is a directory afpIDNotFound -5034 File ID reference not found afpBadIDErr -5039 File ID reference not found __________ Also see: ResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef, DeleteFileIDRef */ /*****************************************************************************/ pascal OSErr CreateFileIDRef(short vRefNum, long parID, ConstStr255Param fileName, long *fileID); /* Establish a file ID reference for a file. The CreateFileIDRef function creates a file ID reference for the specified file, or if a file ID reference already exists, supplies the file ID reference and returns the result code fidExists or afpIDExists. vRefNum input: Volume specification. parID input: Directory ID. fileName input: The name of the file. fileID output: The file ID reference (if result is noErr, fidExists, or afpIDExists). Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline extFSErr -58 External file system error - no file system claimed this call. wrgVolTypErr -123 Not an HFS volume fidExists -1301 File ID reference already exists notAFileErrn -1302 Specified file is a directory afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Specified file is a directory afpIDExists -5035 File ID reference already exists __________ Also see: FSpResolveFileIDRef, ResolveFileIDRef, FSpCreateFileIDRef, DeleteFileIDRef */ /*****************************************************************************/ pascal OSErr FSpCreateFileIDRef(const FSSpec *spec, long *fileID); /* Establish a file ID reference for a file. The FSpCreateFileIDRef function creates a file ID reference for the specified file, or if a file ID reference already exists, supplies the file ID reference and returns the result code fidExists or afpIDExists. spec input: An FSSpec record specifying the file. fileID output: The file ID reference (if result is noErr, fidExists, or afpIDExists). Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline extFSErr -58 External file system error - no file system claimed this call. wrgVolTypErr -123 Not an HFS volume fidExists -1301 File ID reference already exists notAFileErrn -1302 Specified file is a directory afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Specified file is a directory afpIDExists -5035 File ID reference already exists __________ Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, DeleteFileIDRef */ /*****************************************************************************/ pascal OSErr DeleteFileIDRef(ConstStr255Param volName, short vRefNum, long fileID); /* Delete a file ID reference. The DeleteFileIDRef function deletes a file ID reference. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. fileID input: The file ID reference. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnfErr -43 File not found wPrErr -44 Hardware volume lock vLckdErr -46 Software volume lock paramErr -50 Function not supported by volume volOfflinErr -53 Volume is offline extFSErr -58 External file system error - no file system claimed this call. wrgVolTypErr -123 Function is not supported by volume fidNotFoundErr -1300 File ID reference not found afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Specified file is a directory afpIDNotFound -5034 File ID reference not found __________ Also see: FSpResolveFileIDRef, ResolveFileIDRef, CreateFileIDRef, FSpCreateFileIDRef */ /*****************************************************************************/ pascal OSErr FlushFile(short refNum); /* Write the contents of a file's access path buffer (the fork data). The FlushFile function writes the contents of a file's access path buffer (the fork data) to the volume. Note: some of the file's catalog information stored on the volume may not be correct until FlushVol is called. refNum input: The file reference number of an open file. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error fnOpnErr -38 File not open fnfErr -43 File not found rfNumErr -51 Bad reference number extFSErr -58 External file system error - no file system claimed this call. */ /*****************************************************************************/ pascal OSErr LockRange(short refNum, long rangeLength, long rangeStart); /* Lock a portion of a file. The LockRange function locks (denies access to) a portion of a file that was opened with shared read/write permission. refNum input: The file reference number of an open file. rangeLength input: The number of bytes in the range. rangeStart input: The starting byte in the range to lock. Result Codes noErr 0 No error ioErr -36 I/O error fnOpnErr -38 File not open eofErr -39 Logical end-of-file reached fLckdErr -45 File is locked by another user paramErr -50 Negative ioReqCount rfNumErr -51 Bad reference number extFSErr -58 External file system error - no file system claimed this call. volGoneErr -124 Server volume has been disconnected afpNoMoreLocks -5015 No more ranges can be locked afpRangeOverlap -5021 Part of range is already locked __________ Also see: UnlockRange */ /*****************************************************************************/ pascal OSErr UnlockRange(short refNum, long rangeLength, long rangeStart); /* Unlock a previously locked range. The UnlockRange function unlocks (allows access to) a previously locked portion of a file that was opened with shared read/write permission. refNum input: The file reference number of an open file. rangeLength input: The number of bytes in the range. rangeStart input: The starting byte in the range to unlock. Result Codes noErr 0 No error ioErr -36 I/O error fnOpnErr -38 File not open eofErr -39 Logical end-of-file reached paramErr -50 Negative ioReqCount rfNumErr -51 Bad reference number extFSErr -58 External file system error - no file system claimed this call. volGoneErr -124 Server volume has been disconnected afpRangeNotLocked -5020 Specified range was not locked __________ Also see: LockRange */ /*****************************************************************************/ pascal OSErr GetForeignPrivs(short vRefNum, long dirID, ConstStr255Param name, void *foreignPrivBuffer, long *foreignPrivSize, long *foreignPrivInfo1, long *foreignPrivInfo2, long *foreignPrivInfo3, long *foreignPrivInfo4); /* Retrieve the native access-control information. The GetForeignPrivs function retrieves the native access-control information for a file or directory stored on a volume managed by a foreign file system. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. foreignPrivBuffer input: Pointer to buffer where the privilege information is returned. output: Privilege information. foreignPrivSize input: Size of buffer pointed to by foreignPrivBuffer. output: Amount of buffer actually used. foreignPrivInfo1 output: Information specific to privilege model. foreignPrivInfo2 output: Information specific to privilege model. foreignPrivInfo3 output: Information specific to privilege model. foreignPrivInfo4 output: Information specific to privilege model. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Volume is HFS or MFS (that is, it has no foreign privilege model), or foreign volume does not support these calls __________ Also see: FSpGetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs */ /*****************************************************************************/ pascal OSErr FSpGetForeignPrivs(const FSSpec *spec, void *foreignPrivBuffer, long *foreignPrivSize, long *foreignPrivInfo1, long *foreignPrivInfo2, long *foreignPrivInfo3, long *foreignPrivInfo4); /* Retrieve the native access-control information. The FSpGetForeignPrivs function retrieves the native access-control information for a file or directory stored on a volume managed by a foreign file system. spec input: An FSSpec record specifying the object. foreignPrivBuffer input: Pointer to buffer where the privilege information is returned. output: Privilege information. foreignPrivSize input: Size of buffer pointed to by foreignPrivBuffer. output: Amount of buffer actually used. foreignPrivInfo1 output: Information specific to privilege model. foreignPrivInfo2 output: Information specific to privilege model. foreignPrivInfo3 output: Information specific to privilege model. foreignPrivInfo4 output: Information specific to privilege model. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Volume is HFS or MFS (that is, it has no foreign privilege model), or foreign volume does not support these calls __________ Also see: GetForeignPrivs, SetForeignPrivs, FSpSetForeignPrivs */ /*****************************************************************************/ pascal OSErr SetForeignPrivs(short vRefNum, long dirID, ConstStr255Param name, const void *foreignPrivBuffer, long *foreignPrivSize, long foreignPrivInfo1, long foreignPrivInfo2, long foreignPrivInfo3, long foreignPrivInfo4); /* Change the native access-control information. The SetForeignPrivs function changes the native access-control information for a file or directory stored on a volume managed by a foreign file system. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. foreignPrivBuffer input: Pointer to privilege information buffer. foreignPrivSize input: Size of buffer pointed to by foreignPrivBuffer. output: Amount of buffer actually used. foreignPrivInfo1 input: Information specific to privilege model. foreignPrivInfo2 input: Information specific to privilege model. foreignPrivInfo3 input: Information specific to privilege model. foreignPrivInfo4 input: Information specific to privilege model. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Volume is HFS or MFS (that is, it has no foreign privilege model), or foreign volume does not support these calls __________ Also see: GetForeignPrivs, FSpGetForeignPrivs, FSpSetForeignPrivs */ /*****************************************************************************/ pascal OSErr FSpSetForeignPrivs(const FSSpec *spec, const void *foreignPrivBuffer, long *foreignPrivSize, long foreignPrivInfo1, long foreignPrivInfo2, long foreignPrivInfo3, long foreignPrivInfo4); /* Change the native access-control information. The FSpSetForeignPrivs function changes the native access-control information for a file or directory stored on a volume managed by a foreign file system. spec input: An FSSpec record specifying the object. foreignPrivBuffer input: Pointer to privilege information buffer. foreignPrivSize input: Size of buffer pointed to by foreignPrivBuffer. output: Amount of buffer actually used. foreignPrivInfo1 input: Information specific to privilege model. foreignPrivInfo2 input: Information specific to privilege model. foreignPrivInfo3 input: Information specific to privilege model. foreignPrivInfo4 input: Information specific to privilege model. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Volume is HFS or MFS (that is, it has no foreign privilege model), or foreign volume does not support these calls __________ Also see: GetForeignPrivs, FSpGetForeignPrivs, SetForeignPrivs */ /*****************************************************************************/ pascal OSErr HGetLogInInfo(ConstStr255Param volName, short vRefNum, short *loginMethod, StringPtr userName); /* Get the login method and user name used to log on to a shared volume. The HGetLogInInfo function retrieves the login method and user name used to log on to a particular shared volume. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: The volume reference number. loginMethod output: The login method used (kNoUserAuthentication, kPassword, kEncryptPassword, or kTwoWayEncryptPassword). userName input: Points to a buffer (minimum Str31) where the user name is to be returned or must be nil. output: The user name. Result Codes noErr 0 No error nsvErr -35 Specified volume doesnt exist paramErr -50 Function not supported by volume __________ Also see: HGetDirAccess, FSpGetDirAccess, HSetDirAccess, FSpSetDirAccess, HMapName, HMapID */ /*****************************************************************************/ pascal OSErr HGetDirAccess(short vRefNum, long dirID, ConstStr255Param name, long *ownerID, long *groupID, long *accessRights); /* Get a directory's access control information on a shared volume. The HGetDirAccess function retrieves the directory access control information for a directory on a shared volume. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil if dirID specifies the directory. ownerID output: The directory's owner ID. groupID output: The directory's group ID or 0 if no group affiliation. accessRights output: The directory's access rights. Result Codes noErr 0 No error fnfErr -43 Directory not found paramErr -50 Function not supported by volume afpAccessDenied -5000 User does not have the correct access to the directory __________ Also see: HGetLogInInfo, FSpGetDirAccess, HSetDirAccess, FSpSetDirAccess, HMapName, HMapID */ /*****************************************************************************/ pascal OSErr FSpGetDirAccess(const FSSpec *spec, long *ownerID, long *groupID, long *accessRights); /* Get a directory's access control information on a shared volume. The FSpGetDirAccess function retrieves the directory access control information for a directory on a shared volume. spec input: An FSSpec record specifying the directory. ownerID output: The directory's owner ID. groupID output: The directory's group ID or 0 if no group affiliation. accessRights output: The directory's access rights. Result Codes noErr 0 No error fnfErr -43 Directory not found paramErr -50 Function not supported by volume afpAccessDenied -5000 User does not have the correct access to the directory __________ Also see: HGetLogInInfo, HGetDirAccess, HSetDirAccess, FSpSetDirAccess, HMapName, HMapID */ /*****************************************************************************/ pascal OSErr HSetDirAccess(short vRefNum, long dirID, ConstStr255Param name, long ownerID, long groupID, long accessRights); /* Set a directory's access control information on a shared volume. The HSetDirAccess function changes the directory access control information for a directory on a shared volume. You must own a directory to change its access control information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil if dirID specifies the directory. ownerID input: The directory's owner ID. groupID input: The directory's group ID or 0 if no group affiliation. accessRights input: The directory's access rights. Result Codes noErr 0 No error fnfErr -43 Directory not found vLckdErr -46 Volume is locked or read-only paramErr -50 Parameter error afpAccessDenied -5000 User does not have the correct access to the directory afpObjectTypeErr -5025 Object is a file, not a directory __________ Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, FSpSetDirAccess, HMapName, HMapID */ /*****************************************************************************/ pascal OSErr FSpSetDirAccess(const FSSpec *spec, long ownerID, long groupID, long accessRights); /* Set a directory's access control information on a shared volume. The FSpSetDirAccess function changes the directory access control information for a directory on a shared volume. You must own a directory to change its access control information. spec input: An FSSpec record specifying the directory. ownerID input: The directory's owner ID. groupID input: The directory's group ID or 0 if no group affiliation. accessRights input: The directory's access rights. Result Codes noErr 0 No error fnfErr -43 Directory not found vLckdErr -46 Volume is locked or read-only paramErr -50 Parameter error afpAccessDenied -5000 User does not have the correct access to the directory afpObjectTypeErr -5025 Object is a file, not a directory __________ Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, HMapName, HMapID */ /*****************************************************************************/ pascal OSErr HMapID(ConstStr255Param volName, short vRefNum, long ugID, short objType, StringPtr name); /* Map a user or group ID to a user or group name. The HMapID function determines the name of a user or group if you know the user or group ID. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. objType input: The mapping function code: 1 if you're mapping a user ID to a user name or 2 if you're mapping a group ID to a group name. name input: Points to a buffer (minimum Str31) where the user or group name is to be returned or must be nil. output: The user or group name. Result Codes noErr 0 No error fnfErr -43 Unrecognizable owner or group name paramErr -50 Function not supported by volume __________ Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, FSpSetDirAccess, HMapName */ /*****************************************************************************/ pascal OSErr HMapName(ConstStr255Param volName, short vRefNum, ConstStr255Param name, short objType, long *ugID); /* Map a user or group name to a user or group ID. The HMapName function determines the user or group ID if you know the user or group name. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. name input: The user or group name. objType input: The mapping function code: 3 if you're mapping a user name to a user ID or 4 if you're mapping a group name to a group ID. ugID output: The user or group ID. Result Codes noErr 0 No error fnfErr -43 Unrecognizable owner or group name paramErr -50 Function not supported by volume __________ Also see: HGetLogInInfo, HGetDirAccess, FSpGetDirAccess, HSetDirAccess, FSpSetDirAccess, HMapID */ /*****************************************************************************/ pascal OSErr HCopyFile(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstPathname, ConstStr255Param copyName); /* Duplicate a file on a file server and optionally to rename it. The HCopyFile function duplicates a file and optionally to renames it. The source and destination volumes must be on the same file server. This function instructs the server to copy the file. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Source file name. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstPathname input: Pointer to destination directory name, or nil when dstDirID specifies a directory. copyName input: Points to the new file name if the file is to be renamed or nil if the file isn't to be renamed. Result Codes noErr 0 No error dskFulErr -34 Destination volume is full fnfErr -43 Source file not found, or destination directory does not exist vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists paramErr -50 Function not supported by volume wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 The user does not have the right to read the source or write to the destination afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory __________ Also see: FSpCopyFile, FileCopy, FSpFileCopy */ /*****************************************************************************/ pascal OSErr FSpCopyFile(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName); /* Duplicate a file on a file server and optionally to rename it. The FSpCopyFile function duplicates a file and optionally to renames it. The source and destination volumes must be on the same file server. This function instructs the server to copy the file. srcSpec input: An FSSpec record specifying the source file. dstSpec input: An FSSpec record specifying the destination directory. copyName input: Points to the new file name if the file is to be renamed or nil if the file isn't to be renamed. Result Codes noErr 0 No error dskFulErr -34 Destination volume is full fnfErr -43 Source file not found, or destination directory does not exist vLckdErr -46 Destination volume is read-only fBsyErr -47 The source or destination file could not be opened with the correct access modes dupFNErr -48 Destination file already exists paramErr -50 Function not supported by volume wrgVolTypErr -123 Function not supported by volume afpAccessDenied -5000 The user does not have the right to read the source or write to the destination afpDenyConflict -5006 The source or destination file could not be opened with the correct access modes afpObjectTypeErr -5025 Source is a directory __________ Also see: HCopyFile, FileCopy, FSpFileCopy */ /*****************************************************************************/ pascal OSErr HMoveRename(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstpathName, ConstStr255Param copyName); /* Move a file or directory on a file server and optionally to rename it. The HMoveRename function moves a file or directory and optionally renames it. The source and destination locations must be on the same shared volume. vRefNum input: Volume specification. srcDirID input: Source directory ID. srcName input: The source object name. dstDirID input: Destination directory ID. dstName input: Pointer to destination directory name, or nil when dstDirID specifies a directory. copyName input: Points to the new name if the object is to be renamed or nil if the object isn't to be renamed. Result Codes noErr 0 No error fnfErr -43 Source file or directory not found fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only dupFNErr -48 Destination already exists paramErr -50 Function not supported by volume badMovErr -122 Attempted to move directory into offspring afpAccessDenied -5000 The user does not have the right to move the file or directory __________ Also see: FSpMoveRename, HMoveRenameCompat, FSpMoveRenameCompat */ /*****************************************************************************/ pascal OSErr FSpMoveRename(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName); /* Move a file or directory on a file server and optionally to rename it. The FSpMoveRename function moves a file or directory and optionally renames it. The source and destination locations must be on the same shared volume. srcSpec input: An FSSpec record specifying the source object. dstSpec input: An FSSpec record specifying the destination directory. copyName input: Points to the new name if the object is to be renamed or nil if the object isn't to be renamed. Result Codes noErr 0 No error fnfErr -43 Source file or directory not found fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only dupFNErr -48 Destination already exists paramErr -50 Function not supported by volume badMovErr -122 Attempted to move directory into offspring afpAccessDenied -5000 The user does not have the right to move the file or directory __________ Also see: HMoveRename, HMoveRenameCompat, FSpMoveRenameCompat */ /*****************************************************************************/ pascal OSErr GetVolMountInfoSize(ConstStr255Param volName, short vRefNum, short *size); /* Get the size of a volume mounting information record. The GetVolMountInfoSize function determines the how much space the program needs to allocate for a volume mounting information record. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. size output: The space needed (in bytes) of the volume mounting information record. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Parameter error extFSErr -58 External file system error - no file system claimed this call. __________ Also see: GetVolMountInfo, VolumeMount BuildAFPVolMountInfo, RetrieveAFPVolMountInfo */ /*****************************************************************************/ pascal OSErr GetVolMountInfo(ConstStr255Param volName, short vRefNum, void *volMountInfo); /* Retrieve a volume mounting information record. The GetVolMountInfo function retrieves a volume mounting information record containing all the information needed to mount the volume, except for passwords. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. volMountInfo output: Points to a volume mounting information record where the mounting information is to be returned. Result Codes noErr 0 No error nsvErr -35 Volume not found paramErr -50 Parameter error extFSErr -58 External file system error - no file system claimed this call. __________ Also see: GetVolMountInfoSize, VolumeMount, BuildAFPVolMountInfo, RetrieveAFPVolMountInfo */ /*****************************************************************************/ pascal OSErr VolumeMount(const void *volMountInfo, short *vRefNum); /* Mount a volume using a volume mounting information record. The VolumeMount function mounts a volume using a volume mounting information record. volMountInfo input: Points to a volume mounting information record. vRefNum output: A volume reference number. Result Codes noErr 0 No error notOpenErr -28 AppleTalk is not open nsvErr -35 Volume not found paramErr -50 Parameter error; typically, zone, server, and volume name combination is not valid or not complete, or the user name is not recognized extFSErr -58 External file system error - no file system claimed this call. memFullErr -108 Not enough memory to create a new volume control block for mounting the volume afpBadUAM -5002 User authentication method is unknown afpBadVersNum -5003 Workstation is using an AFP version that the server doesnt recognize afpNoServer -5016 Server is not responding afpUserNotAuth -5023 User authentication failed (usually, password is not correct) afpPwdExpired -5042 Password has expired on server afpBadDirIDType -5060 Not a fixed directory ID volume afpCantMountMoreSrvrs -5061 Maximum number of volumes has been mounted afpAlreadyMounted -5062 Volume already mounted afpSameNodeErr -5063 Attempt to log on to a server running on the same machine __________ Also see: GetVolMountInfoSize, GetVolMountInfo, BuildAFPVolMountInfo, RetrieveAFPVolMountInfo */ /*****************************************************************************/ pascal OSErr Share(short vRefNum, long dirID, ConstStr255Param name); /* Establish a local volume or directory as a share point. The Share function establishes a local volume or directory as a share point. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil if dirID specifies the directory. Result Codes noErr 0 No error tmfoErr -42 Too many share points fnfErr -43 File not found dupFNErr -48 Already a share point with this name paramErr -50 Function not supported by volume dirNFErrdirNFErr -120 Directory not found afpAccessDenied -5000 This directory cannot be shared afpObjectTypeErr -5025 Object was a file, not a directory afpContainsSharedErr -5033 The directory contains a share point afpInsideSharedErr -5043 The directory is inside a shared directory __________ Also see: FSpShare, Unshare, FSpUnshare */ /*****************************************************************************/ pascal OSErr FSpShare(const FSSpec *spec); /* Establish a local volume or directory as a share point. The FSpShare function establishes a local volume or directory as a share point. spec input: An FSSpec record specifying the share point. Result Codes noErr 0 No error tmfoErr -42 Too many share points fnfErr -43 File not found dupFNErr -48 Already a share point with this name paramErr -50 Function not supported by volume dirNFErrdirNFErr -120 Directory not found afpAccessDenied -5000 This directory cannot be shared afpObjectTypeErr -5025 Object was a file, not a directory afpContainsSharedErr -5033 The directory contains a share point afpInsideSharedErr -5043 The directory is inside a shared directory __________ Also see: Share, Unshare, FSpUnshare */ /*****************************************************************************/ pascal OSErr Unshare(short vRefNum, long dirID, ConstStr255Param name); /* Remove a share point. The Unshare function removes a share point. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil if dirID specifies the directory. Result Codes noErr 0 No error fnfErr -43 File not found paramErr -50 Function not supported by volume dirNFErrdirNFErr -120 Directory not found afpObjectTypeErr -5025 Object was a file, not a directory; or, this directory is not a share point __________ Also see: Share, FSpShare, FSpUnshare */ /*****************************************************************************/ pascal OSErr FSpUnshare(const FSSpec *spec); /* Remove a share point. The FSpUnshare function removes a share point. spec input: An FSSpec record specifying the share point. Result Codes noErr 0 No error fnfErr -43 File not found paramErr -50 Function not supported by volume dirNFErrdirNFErr -120 Directory not found afpObjectTypeErr -5025 Object was a file, not a directory; or, this directory is not a share point __________ Also see: Share, FSpShare, Unshare */ /*****************************************************************************/ pascal OSErr GetUGEntry(short objType, StringPtr objName, long *objID); /* Retrieve a user or group entry from the local file server. The GetUGEntry function retrieves user or group entries from the local file server. objType input: The object type: -1 = group; 0 = user objName input: Points to a buffer (minimum Str31) where the user or group name is to be returned or must be nil. output: The user or group name. objID input: O to get the first user or group. If the entry objID last returned by GetUGEntry is passed, then user or group whose alphabetically next in the list of entries is returned. output: The user or group ID. Result Codes noErr 0 No error fnfErr -43 No more users or groups paramErr -50 Function not supported; or, ioObjID is negative __________ Also see: GetUGEntries */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __MOREFILES__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/MoreFilesExtras.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** A collection of useful high-level File Manager routines. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: MoreFilesExtras.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __MOREFILESEXTRAS__ #define __MOREFILESEXTRAS__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* ** Macros to get information out of GetVolParmsInfoBuffer */ /* version 1 field getters */ #define GetVolParmsInfoVersion(volParms) \ ((volParms).vMVersion) #define GetVolParmsInfoAttrib(volParms) \ ((volParms).vMAttrib) #define GetVolParmsInfoLocalHand(volParms) \ ((volParms).vMLocalHand) #define GetVolParmsInfoServerAdr(volParms) \ ((volParms).vMServerAdr) /* version 2 field getters (assume zero result if not version >= 2) */ #define GetVolParmsInfoVolumeGrade(volParms) \ (((volParms).vMVersion >= 2) ? (volParms).vMVolumeGrade : 0) #define GetVolParmsInfoForeignPrivID(volParms) \ (((volParms).vMVersion >= 2) ? (volParms).vMForeignPrivID : 0) /* version 3 field getters (assume zero result if not version >= 3) */ #define GetVolParmsInfoExtendedAttributes(volParms) \ (((volParms).vMVersion >= 3) ? (volParms).vMExtendedAttributes : 0) /* attribute bits supported by all versions of GetVolParmsInfoBuffer */ #define isNetworkVolume(volParms) ((volParms).vMServerAdr != 0) #define hasLimitFCBs(volParms) (((volParms).vMAttrib & (1L << bLimitFCBs)) != 0) #define hasLocalWList(volParms) (((volParms).vMAttrib & (1L << bLocalWList)) != 0) #define hasNoMiniFndr(volParms) (((volParms).vMAttrib & (1L << bNoMiniFndr)) != 0) #define hasNoVNEdit(volParms) (((volParms).vMAttrib & (1L << bNoVNEdit)) != 0) #define hasNoLclSync(volParms) (((volParms).vMAttrib & (1L << bNoLclSync)) != 0) #define hasTrshOffLine(volParms) (((volParms).vMAttrib & (1L << bTrshOffLine)) != 0) #define hasNoSwitchTo(volParms) (((volParms).vMAttrib & (1L << bNoSwitchTo)) != 0) #define hasNoDeskItems(volParms) (((volParms).vMAttrib & (1L << bNoDeskItems)) != 0) #define hasNoBootBlks(volParms) (((volParms).vMAttrib & (1L << bNoBootBlks)) != 0) #define hasAccessCntl(volParms) (((volParms).vMAttrib & (1L << bAccessCntl)) != 0) #define hasNoSysDir(volParms) (((volParms).vMAttrib & (1L << bNoSysDir)) != 0) #define hasExtFSVol(volParms) (((volParms).vMAttrib & (1L << bHasExtFSVol)) != 0) #define hasOpenDeny(volParms) (((volParms).vMAttrib & (1L << bHasOpenDeny)) != 0) #define hasCopyFile(volParms) (((volParms).vMAttrib & (1L << bHasCopyFile)) != 0) #define hasMoveRename(volParms) (((volParms).vMAttrib & (1L << bHasMoveRename)) != 0) #define hasDesktopMgr(volParms) (((volParms).vMAttrib & (1L << bHasDesktopMgr)) != 0) #define hasShortName(volParms) (((volParms).vMAttrib & (1L << bHasShortName)) != 0) #define hasFolderLock(volParms) (((volParms).vMAttrib & (1L << bHasFolderLock)) != 0) #define hasPersonalAccessPrivileges(volParms) \ (((volParms).vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0) #define hasUserGroupList(volParms) (((volParms).vMAttrib & (1L << bHasUserGroupList)) != 0) #define hasCatSearch(volParms) (((volParms).vMAttrib & (1L << bHasCatSearch)) != 0) #define hasFileIDs(volParms) (((volParms).vMAttrib & (1L << bHasFileIDs)) != 0) #define hasBTreeMgr(volParms) (((volParms).vMAttrib & (1L << bHasBTreeMgr)) != 0) #define hasBlankAccessPrivileges(volParms) \ (((volParms).vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0) #define supportsAsyncRequests(volParms) \ (((volParms).vMAttrib & (1L << bSupportsAsyncRequests)) != 0) #define supportsTrashVolumeCache(volParms) \ (((volParms).vMAttrib & (1L << bSupportsTrashVolumeCache)) != 0) /* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */ #define volIsEjectable(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsEjectable)) != 0) #define volSupportsHFSPlusAPIs(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsHFSPlusAPIs)) != 0) #define volSupportsFSCatalogSearch(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSCatalogSearch)) != 0) #define volSupportsFSExchangeObjects(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSExchangeObjects)) != 0) #define volSupports2TBFiles(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupports2TBFiles)) != 0) #define volSupportsLongNames(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsLongNames)) != 0) #define volSupportsMultiScriptNames(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsMultiScriptNames)) != 0) #define volSupportsNamedForks(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsNamedForks)) != 0) #define volSupportsSubtreeIterators(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSubtreeIterators)) != 0) #define volL2PCanMapFileBlocks(volParms) \ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bL2PCanMapFileBlocks)) != 0) /*****************************************************************************/ /* ** Bit masks and macros to get common information out of ioACUser returned ** by PBGetCatInfo (remember to clear ioACUser before calling PBGetCatInfo ** since some file systems don't bother to set this field). ** ** Use the GetDirAccessRestrictions or FSpGetDirAccessRestrictions ** functions to retrieve the ioACUser access restrictions byte for ** a folder. ** ** Note: The access restriction byte returned by PBGetCatInfo is the ** 2's complement of the user's privileges byte returned in ** ioACAccess by PBHGetDirAccess. */ enum { /* mask for just the access restriction bits */ acUserAccessMask = (kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask + kioACUserNoMakeChangesMask), /* common access privilege settings */ acUserFull = 0x00, /* no access restiction bits on */ acUserNone = acUserAccessMask, /* all access restiction bits on */ acUserDropBox = kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask, /* make changes, but not see files or folders */ acUserBulletinBoard = kioACUserNoMakeChangesMask /* see files and folders, but not make changes */ }; /* Macros for testing ioACUser bits */ #define userIsOwner(ioACUser) \ (((ioACUser) & kioACUserNotOwnerMask) == 0) #define userHasFullAccess(ioACUser) \ (((ioACUser) & (acUserAccessMask)) == acUserFull) #define userHasDropBoxAccess(ioACUser) \ (((ioACUser) & acUserAccessMask) == acUserDropBox) #define userHasBulletinBoard(ioACUser) \ (((ioACUser) & acUserAccessMask) == acUserBulletinBoard) #define userHasNoAccess(ioACUser) \ (((ioACUser) & acUserAccessMask) == acUserNone) /*****************************************************************************/ /* ** Deny mode permissions for use with the HOpenAware, HOpenRFAware, ** FSpOpenAware, and FSpOpenRFAware functions. ** Note: Common settings are the ones with comments. */ enum { dmNone = 0x0000, dmNoneDenyRd = fsRdDenyPerm, dmNoneDenyWr = fsWrDenyPerm, dmNoneDenyRdWr = (fsRdDenyPerm + fsWrDenyPerm), dmRd = fsRdPerm, /* Single writer, multiple readers; the readers */ dmRdDenyRd = (fsRdPerm + fsRdDenyPerm), dmRdDenyWr = (fsRdPerm + fsWrDenyPerm), /* Browsing - equivalent to fsRdPerm */ dmRdDenyRdWr = (fsRdPerm + fsRdDenyPerm + fsWrDenyPerm), dmWr = fsWrPerm, dmWrDenyRd = (fsWrPerm + fsRdDenyPerm), dmWrDenyWr = (fsWrPerm + fsWrDenyPerm), dmWrDenyRdWr = (fsWrPerm + fsRdDenyPerm + fsWrDenyPerm), dmRdWr = fsRdWrPerm, /* Shared access - equivalent to fsRdWrShPerm */ dmRdWrDenyRd = (fsRdWrPerm + fsRdDenyPerm), dmRdWrDenyWr = (fsRdWrPerm + fsWrDenyPerm), /* Single writer, multiple readers; the writer */ dmRdWrDenyRdWr = (fsRdWrPerm + fsRdDenyPerm + fsWrDenyPerm) /* Exclusive access - equivalent to fsRdWrPerm */ }; /*****************************************************************************/ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif /* ** For those times where you need to use more than one kind of File Manager parameter ** block but don't feel like wasting stack space, here's a parameter block you can reuse. */ union UniversalFMPB { ParamBlockRec PB; CInfoPBRec ciPB; DTPBRec dtPB; HParamBlockRec hPB; CMovePBRec cmPB; WDPBRec wdPB; FCBPBRec fcbPB; XVolumeParam xPB; }; typedef union UniversalFMPB UniversalFMPB; typedef UniversalFMPB *UniversalFMPBPtr, **UniversalFMPBHandle; /* ** Used by GetUGEntries to return user or group lists */ struct UGEntry { short objType; /* object type: -1 = group; 0 = user */ long objID; /* the user or group ID */ Str31 name; /* the user or group name */ }; typedef struct UGEntry UGEntry; typedef UGEntry *UGEntryPtr, **UGEntryHandle; typedef unsigned char Str8[9]; /* ** I use the following records instead of the AFPVolMountInfo and AFPXVolMountInfo structures in Files.h */ struct MyAFPVolMountInfo { short length; /* length of this record */ VolumeType media; /* type of media, always AppleShareMediaType */ short flags; /* 0 = normal mount; set bit 0 to inhibit greeting messages */ char nbpInterval; /* NBP interval parameter; 7 is a good choice */ char nbpCount; /* NBP count parameter; 5 is a good choice */ short uamType; /* User Authentication Method */ short zoneNameOffset; /* offset from start of record to zoneName */ short serverNameOffset; /* offset from start of record to serverName */ short volNameOffset; /* offset from start of record to volName */ short userNameOffset; /* offset from start of record to userName */ short userPasswordOffset; /* offset from start of record to userPassword */ short volPasswordOffset; /* offset from start of record to volPassword */ Str32 zoneName; /* server's AppleTalk zone name */ char filler1; /* to word align volPassword */ Str32 serverName; /* server name */ char filler2; /* to word align volPassword */ Str27 volName; /* volume name */ Str31 userName; /* user name (zero length Pascal string for guest) */ Str8 userPassword; /* user password (zero length Pascal string if no user password) */ char filler3; /* to word align volPassword */ Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ char filler4; /* to end record on word boundry */ }; typedef struct MyAFPVolMountInfo MyAFPVolMountInfo; typedef MyAFPVolMountInfo *MyAFPVolMountInfoPtr, **MyAFPVolMountInfoHandle; struct MyAFPXVolMountInfo { short length; /* length of this record */ VolumeType media; /* type of media, always AppleShareMediaType */ short flags; /* bits for no messages, no reconnect, etc */ char nbpInterval; /* NBP interval parameter; 7 is a good choice */ char nbpCount; /* NBP count parameter; 5 is a good choice */ short uamType; /* User Authentication Method */ short zoneNameOffset; /* offset from start of record to zoneName */ short serverNameOffset; /* offset from start of record to serverName */ short volNameOffset; /* offset from start of record to volName */ short userNameOffset; /* offset from start of record to userName */ short userPasswordOffset; /* offset from start of record to userPassword */ short volPasswordOffset; /* offset from start of record to volPassword */ short extendedFlags; /* extended flags word */ short uamNameOffset; /* offset to a pascal UAM name string */ short alternateAddressOffset; /* offset to Alternate Addresses in tagged format */ Str32 zoneName; /* server's AppleTalk zone name */ char filler1; /* to word align volPassword */ Str32 serverName; /* server name */ char filler2; /* to word align volPassword */ Str27 volName; /* volume name */ Str31 userName; /* user name (zero length Pascal string for guest) */ Str8 userPassword; /* user password (zero length Pascal string if no user password) */ char filler3; /* to word align volPassword */ Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */ char filler4; /* to word align uamNameOffset */ Str32 uamName; /* UAM name */ char filler5; /* to word align alternateAddress */ char alternateAddress[kVariableLengthArray]; /* AFPAlternateAddress */ }; typedef struct MyAFPXVolMountInfo MyAFPXVolMountInfo; typedef MyAFPXVolMountInfo *MyAFPXVolMountInfoPtr, **MyAFPXVolMountInfoHandle; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif /*****************************************************************************/ pascal void TruncPString(StringPtr destination, ConstStr255Param source, short maxLength); /* International friendly string truncate routine. The TruncPString function copies up to maxLength characters from the source Pascal string to the destination Pascal string. TruncPString ensures that the truncated string ends on a single-byte character, or on the last byte of a multi-byte character. destination output: destination Pascal string. source input: source Pascal string. maxLength output: The maximum allowable length of the destination string. */ /*****************************************************************************/ pascal Ptr GetTempBuffer(long buffReqSize, long *buffActSize); /* Allocate a temporary copy or search buffer. The GetTempBuffer function allocates a temporary buffer for file system operations which is at least 1024 bytes (1K) and a multiple of 1024 bytes. buffReqSize input: Size you'd like the buffer to be. buffActSize output: Size of buffer allocated. function result output: Pointer to memory allocated or nil if no memory was available. The caller is responsible for disposing of this buffer with DisposePtr. */ /*****************************************************************************/ pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, short vRefNum, HParmBlkPtr pb); /* Call PBHGetVInfoSync ignoring returned name. GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync in cases where the returned volume name is not needed by the caller. The pathname and vRefNum parameters are not touched, and the pb parameter is initialized by PBHGetVInfoSync except that ioNamePtr in the parameter block is always returned as NULL (since it might point to GetVolumeInfoNoName's local variable tempPathname). I noticed using this code in several places, so here it is once. This reduces the code size of MoreFiles. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). pb input: A pointer to HParamBlockRec. output: The parameter block as filled in by PBHGetVInfoSync except that ioNamePtr will always be NULL. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume, or pb was NULL */ /*****************************************************************************/ pascal OSErr XGetVolumeInfoNoName(ConstStr255Param pathname, short vRefNum, XVolumeParamPtr pb); /* Call PBXGetVolInfoSync ignoring returned name. XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync in cases where the returned volume name is not needed by the caller. The pathname and vRefNum parameters are not touched, and the pb parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in the parameter block is always returned as NULL (since it might point to XGetVolumeInfoNoName's local variable tempPathname). pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). pb input: A pointer to HParamBlockRec. output: The parameter block as filled in by PBXGetVolInfoSync except that ioNamePtr will always be NULL. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume, or pb was NULL */ /*****************************************************************************/ pascal OSErr GetCatInfoNoName(short vRefNum, long dirID, ConstStr255Param name, CInfoPBPtr pb); /* Call PBGetCatInfoSync ignoring returned name. GetCatInfoNoName uses vRefNum, dirID and name to call PBGetCatInfoSync in cases where the returned object is not needed by the caller. The vRefNum, dirID and name parameters are not touched, and the pb parameter is initialized by PBGetCatInfoSync except that ioNamePtr in the parameter block is always returned as NULL (since it might point to GetCatInfoNoName's local variable tempName). I noticed using this code in several places, so here it is once. This reduces the code size of MoreFiles. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. pb input: A pointer to CInfoPBRec. output: The parameter block as filled in by PBGetCatInfoSync except that ioNamePtr will always be NULL. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr DetermineVRefNum(ConstStr255Param pathname, short vRefNum, short *realVRefNum); /* Determine the real volume reference number. The DetermineVRefNum function determines the volume reference number of a volume from a pathname, a volume specification, or a combination of the two. WARNING: Volume names on the Macintosh are *not* unique -- Multiple mounted volumes can have the same name. For this reason, the use of a volume name or full pathname to identify a specific volume may not produce the results you expect. If more than one volume has the same name and a volume name or full pathname is used, the File Manager currently uses the first volume it finds with a matching name in the volume queue. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). realVRefNum output: The real volume reference number. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume */ /*****************************************************************************/ pascal OSErr HGetVInfo(short volReference, StringPtr volName, short *vRefNum, unsigned long *freeBytes, unsigned long *totalBytes); /* Get information about a mounted volume. The HGetVInfo function returns the name, volume reference number, available space (in bytes), and total space (in bytes) for the specified volume. You can specify the volume by providing its drive number, volume reference number, or 0 for the default volume. This routine is compatible with volumes up to 4 gigabytes. volReference input: The drive number, volume reference number, or 0 for the default volume. volName input: A pointer to a buffer (minimum Str27) where the volume name is to be returned or must be nil. output: The volume name. vRefNum output: The volume reference number. freeBytes output: The number of free bytes on the volume. freeBytes is an unsigned long value. totalBytes output: The total number of bytes on the volume. totalBytes is an unsigned long value. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume __________ Also see: XGetVInfo */ /*****************************************************************************/ pascal OSErr XGetVInfo(short volReference, StringPtr volName, short *vRefNum, UInt64 *freeBytes, UInt64 *totalBytes); /* Get extended information about a mounted volume. The XGetVInfo function returns the name, volume reference number, available space (in bytes), and total space (in bytes) for the specified volume. You can specify the volume by providing its drive number, volume reference number, or 0 for the default volume. This routine is compatible with volumes up to 2 terabytes. volReference input: The drive number, volume reference number, or 0 for the default volume. volName input: A pointer to a buffer (minimum Str27) where the volume name is to be returned or must be nil. output: The volume name. vRefNum output: The volume reference number. freeBytes output: The number of free bytes on the volume. freeBytes is an UnsignedWide value. totalBytes output: The total number of bytes on the volume. totalBytes is an UnsignedWide value. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume __________ Also see: HGetVInfo */ /*****************************************************************************/ pascal OSErr CheckVolLock(ConstStr255Param pathname, short vRefNum); /* Determine if a volume is locked. The CheckVolLock function determines if a volume is locked - either by hardware or by software. If CheckVolLock returns noErr, then the volume is not locked. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). Result Codes noErr 0 No error - volume not locked nsvErr -35 No such volume wPrErr -44 Volume locked by hardware vLckdErr -46 Volume locked by software paramErr -50 No default volume */ /*****************************************************************************/ // // The following routines call Mac OS routines that are not supported by // Carbon: // // GetDriverName // FindDrive // GetDiskBlocks // GetVolState #if !TARGET_API_MAC_CARBON // { /*****************************************************************************/ pascal OSErr GetDriverName(short driverRefNum, Str255 driverName); /* Get a device driver's name. The GetDriverName function returns a device driver's name. driverRefNum input: The driver reference number. driverName output: The driver's name. Result Codes noErr 0 No error badUnitErr -21 Bad driver reference number */ /*****************************************************************************/ pascal OSErr FindDrive(ConstStr255Param pathname, short vRefNum, DrvQElPtr *driveQElementPtr); /* Find a volume's drive queue element in the drive queue. The FindDrive function returns a pointer to a mounted volume's drive queue element. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). driveQElementPtr output: Pointer to a volume's drive queue element in the drive queue. DO NOT change the DrvQEl. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume nsDrvErr -56 No such drive */ /*****************************************************************************/ pascal OSErr GetDiskBlocks(ConstStr255Param pathname, short vRefNum, unsigned long *numBlocks); /* Return the number of physical disk blocks on a disk drive. The GetDiskBlocks function returns the number of physical disk blocks on a disk drive. NOTE: This is not the same as volume allocation blocks! pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). numBlocks output: The number of physical disk blocks on the disk drive. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume, driver reference number is zero, ReturnFormatList returned zero blocks, DriveStatus returned an unknown value, or driveQElementPtr->qType is unknown nsDrvErr -56 No such drive statusErr 18 Driver does not respond to this status request badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open */ /*****************************************************************************/ pascal OSErr GetVolState(ConstStr255Param pathname, short vRefNum, Boolean *volumeOnline, Boolean *volumeEjected, Boolean *driveEjectable, Boolean *driverWantsEject); /* Returns a volume's online and eject information. The GetVolState function determines if a volume is online or offline, if an offline volume is ejected, and if the volume's driver is ejectable or wants eject calls. pathName input: Pointer to a full pathname or nil. vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). volumeOnline output: True if the volume is online; False if the volume is offline. volumeEjected output: True if the volume is ejected (ejected volumes are always offline); False if the volume is not ejected. driveEjectable output: True if the volume's drive is ejectable; False if the volume's drive is not ejectable. driverWantsEject output: True if the volume's driver wants an Eject request after unmount (even if the drive is not ejectable); False if the volume's driver does not need an eject request. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume, or pb was NULL */ /*****************************************************************************/ #endif // } !TARGET_API_MAC_CARBON /*****************************************************************************/ pascal OSErr GetVolFileSystemID(ConstStr255Param pathname, short vRefNum, short *fileSystemID); /* Get a volume's file system ID. The GetVolFileSystemID function returned the file system ID of a mounted volume. The file system ID identifies the file system that handles requests to a particular volume. Here's a partial list of file system ID numbers (only Apple's file systems are listed): FSID File System ----- ----------------------------------------------------- $0000 Macintosh HFS or MFS $0100 ProDOS File System $0101 PowerTalk Mail Enclosures $4147 ISO 9660 File Access (through Foreign File Access) $4242 High Sierra File Access (through Foreign File Access) $464D QuickTake File System (through Foreign File Access) $4953 Macintosh PC Exchange (MS-DOS) $4A48 Audio CD Access (through Foreign File Access) $4D4B Apple Photo Access (through Foreign File Access) See the Technical Note "FL 35 - Determining Which File System Is Active" and the "Guide to the File System Manager" for more information. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must contain at least one colon character (:) and must not start with a colon character. vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). fileSystemID output: The volume's file system ID. Result Codes noErr 0 No error nsvErr -35 No such volume paramErr -50 No default volume, or pb was NULL */ /*****************************************************************************/ pascal OSErr UnmountAndEject(ConstStr255Param pathname, short vRefNum); /* Unmount and eject a volume. The UnmountAndEject function unmounts and ejects a volume. The volume is ejected only if it is ejectable and not already ejected. pathName input: Pointer to a full pathname or nil. If you pass in a partial pathname, it is ignored. A full pathname to a volume must end with a colon character (:). vRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0). Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad volume name fBsyErr -47 One or more files are open paramErr -50 No default volume nsDrvErr -56 No such drive extFSErr -58 External file system error - no file system claimed this call. */ /*****************************************************************************/ pascal OSErr OnLine(FSSpecPtr volumes, short reqVolCount, short *actVolCount, short *volIndex); /* Return the list of volumes currently mounted. The OnLine function returns the list of volumes currently mounted in an array of FSSpec records. A noErr result indicates that the volumes array was filled (actVolCount == reqVolCount) and there may be additional volumes mounted. A nsvErr result indicates that the end of the volume list was found and actVolCount volumes were actually found this time. volumes input: Pointer to array of FSSpec where the volume list is returned. reqVolCount input: Maximum number of volumes to return (the number of elements in the volumes array). actVolCount output: The number of volumes actually returned. volIndex input: The current volume index position. Set to 1 to start with the first volume. output: The volume index position to get the next volume. Pass this value the next time you call OnLine to start where you left off. Result Codes noErr 0 No error, but there are more volumes to list nsvErr -35 No more volumes to be listed paramErr -50 volIndex was <= 0 */ /*****************************************************************************/ pascal OSErr SetDefault(short newVRefNum, long newDirID, short *oldVRefNum, long *oldDirID); /* Set the default volume before making Standard I/O requests. The SetDefault function sets the default volume and directory to the volume specified by newVRefNum and the directory specified by newDirID. The current default volume reference number and directory ID are returned in oldVRefNum and oldDir and must be used to restore the default volume and directory to their previous state *as soon as possible* with the RestoreDefault function. These two functions are designed to be used as a wrapper around Standard I/O routines where the location of the file is implied to be the default volume and directory. In other words, this is how you should use these functions: error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); if ( error == noErr ) { // call the Stdio functions like remove, rename, tmpfile, // fopen, freopen, etc. or non-ANSI extensions like // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! error = RestoreDefault(oldVRefNum, oldDirID); } By using these functions as a wrapper, you won't need to open a working directory (because SetDefault and RestoreDefault use HSetVol) and you won't have to worry about the effects of using HSetVol (documented in Technical Note "FL 11 - PBHSetVol is Dangerous" and in the Inside Macintosh: Files book in the description of the HSetVol and PBHSetVol functions) because the default volume/directory is restored before giving up control to code that might be affected by HSetVol. newVRefNum input: Volume specification (volume reference number, working directory number, drive number, or 0) of the new default volume. newDirID input: Directory ID of the new default directory. oldVRefNum output: The volume specification to save for use with RestoreDefault. oldDirID output: The directory ID to save for use with RestoreDefault. Result Codes noErr 0 No error nsvErr -35 No such volume bdNamErr -37 Bad volume name fnfErr -43 Directory not found paramErr -50 No default volume afpAccessDenied -5000 User does not have access to the directory __________ Also see: RestoreDefault */ /*****************************************************************************/ pascal OSErr RestoreDefault(short oldVRefNum, long oldDirID); /* Restore the default volume after making Standard C I/O requests. The RestoreDefault function restores the default volume and directory to the volume specified by oldVRefNum and the directory specified by oldDirID. The oldVRefNum and oldDirID parameters were previously obtained from the SetDefault function. These two functions are designed to be used as a wrapper around Standard C I/O routines where the location of the file is implied to be the default volume and directory. In other words, this is how you should use these functions: error = SetDefault(newVRefNum, newDirID, &oldVRefNum, &oldDirID); if ( error == noErr ) { // call the Stdio functions like remove, rename, tmpfile, // fopen, freopen, etc. or non-ANSI extensions like // fdopen,fsetfileinfo, -- create, open, unlink, etc. here! error = RestoreDefault(oldVRefNum, oldDirID); } By using these functions as a wrapper, you won't need to open a working directory (because SetDefault and RestoreDefault use HSetVol) and you won't have to worry about the effects of using HSetVol (documented in Technical Note "FL 11 - PBHSetVol is Dangerous" and in the Inside Macintosh: Files book in the description of the HSetVol and PBHSetVol functions) because the default volume/directory is restored before giving up control to code that might be affected by HSetVol. oldVRefNum input: The volume specification to restore. oldDirID input: The directory ID to restore. Result Codes noErr 0 No error nsvErr -35 No such volume bdNamErr -37 Bad volume name fnfErr -43 Directory not found paramErr -50 No default volume rfNumErr -51 Bad working directory reference number afpAccessDenied -5000 User does not have access to the directory __________ Also see: SetDefault */ /*****************************************************************************/ pascal OSErr GetDInfo(short vRefNum, long dirID, ConstStr255Param name, DInfo *fndrInfo); /* Get the finder information for a directory. The GetDInfo function gets the finder information for a directory. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. fndrInfo output: If the object is a directory, then its DInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpGetDInfo, FSpGetFInfoCompat */ /*****************************************************************************/ pascal OSErr FSpGetDInfo(const FSSpec *spec, DInfo *fndrInfo); /* Get the finder information for a directory. The FSpGetDInfo function gets the finder information for a directory. spec input: An FSSpec record specifying the directory. fndrInfo output: If the object is a directory, then its DInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpGetFInfoCompat, GetDInfo */ /*****************************************************************************/ pascal OSErr SetDInfo(short vRefNum, long dirID, ConstStr255Param name, const DInfo *fndrInfo); /* Set the finder information for a directory. The SetDInfo function sets the finder information for a directory. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. fndrInfo input: The DInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpSetDInfo, FSpSetFInfoCompat */ /*****************************************************************************/ pascal OSErr FSpSetDInfo(const FSSpec *spec, const DInfo *fndrInfo); /* Set the finder information for a directory. The FSpSetDInfo function sets the finder information for a directory. spec input: An FSSpec record specifying the directory. fndrInfo input: The DInfo. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpSetFInfoCompat, SetDInfo */ /*****************************************************************************/ #if OLDROUTINENAMES #define GetDirID(vRefNum, dirID, name, theDirID, isDirectory) \ GetDirectoryID(vRefNum, dirID, name, theDirID, isDirectory) #endif pascal OSErr GetDirectoryID(short vRefNum, long dirID, ConstStr255Param name, long *theDirID, Boolean *isDirectory); /* Get the directory ID number of the directory specified. The GetDirectoryID function gets the directory ID number of the directory specified. If a file is specified, then the parent directory of the file is returned and isDirectory is false. If a directory is specified, then that directory's ID number is returned and isDirectory is true. WARNING: Volume names on the Macintosh are *not* unique -- Multiple mounted volumes can have the same name. For this reason, the use of a volume name or full pathname to identify a specific volume may not produce the results you expect. If more than one volume has the same name and a volume name or full pathname is used, the File Manager currently uses the first volume it finds with a matching name in the volume queue. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. theDirID output: If the object is a file, then its parent directory ID. If the object is a directory, then its ID. isDirectory output: True if object is a directory; false if object is a file. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ #if OLDROUTINENAMES #define DirIDFromFSSpec(spec, theDirID, isDirectory) \ FSpGetDirectoryID(spec, theDirID, isDirectory) #endif pascal OSErr FSpGetDirectoryID(const FSSpec *spec, long *theDirID, Boolean *isDirectory); /* Get the directory ID number of a directory. The FSpGetDirectoryID function gets the directory ID number of the directory specified by spec. If spec is to a file, then the parent directory of the file is returned and isDirectory is false. If spec is to a directory, then that directory's ID number is returned and isDirectory is true. spec input: An FSSpec record specifying the directory. theDirID output: The directory ID. isDirectory output: True if object is a directory; false if object is a file. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr GetDirName(short vRefNum, long dirID, Str31 name); /* Get the name of a directory from its directory ID. The GetDirName function gets the name of a directory from its directory ID. vRefNum input: Volume specification. dirID input: Directory ID. name output: Points to a Str31 where the directory name is to be returned. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume or name parameter was NULL dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr GetIOACUser(short vRefNum, long dirID, ConstStr255Param name, SInt8 *ioACUser); /* Get a directory's access restrictions byte. GetIOACUser returns a directory's access restrictions byte. Use the masks and macro defined in MoreFilesExtras to check for specific access priviledges. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. ioACUser output: The access restriction byte Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr FSpGetIOACUser(const FSSpec *spec, SInt8 *ioACUser); /* Get a directory's access restrictions byte. FSpGetIOACUser returns a directory's access restrictions byte. Use the masks and macro defined in MoreFilesExtras to check for specific access priviledges. spec input: An FSSpec record specifying the directory. ioACUser output: The access restriction byte Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr GetParentID(short vRefNum, long dirID, ConstStr255Param name, long *parID); /* Get the parent directory ID number of the specified object. The GetParentID function gets the parent directory ID number of the specified object. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. parID output: The parent directory ID of the specified object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname, Str255 filename); /* Get the object name from the end of a full or partial pathname. The GetFilenameFromPathname function gets the file (or directory) name from the end of a full or partial pathname. Returns notAFileErr if the pathname is nil, the pathname is empty, or the pathname cannot refer to a filename (with a noErr result, the pathname could still refer to a directory). pathname input: A full or partial pathname. filename output: The file (or directory) name. Result Codes noErr 0 No error notAFileErr -1302 The pathname is nil, the pathname is empty, or the pathname cannot refer to a filename __________ See also: GetObjectLocation. */ /*****************************************************************************/ pascal OSErr GetObjectLocation(short vRefNum, long dirID, ConstStr255Param pathname, short *realVRefNum, long *realParID, Str255 realName, Boolean *isDirectory); /* Get a file system object's location. The GetObjectLocation function gets a file system object's location - that is, its real volume reference number, real parent directory ID, and name. While we're at it, determine if the object is a file or directory. If GetObjectLocation returns fnfErr, then the location information returned is valid, but it describes an object that doesn't exist. You can use the location information for another operation, such as creating a file or directory. vRefNum input: Volume specification. dirID input: Directory ID. pathname input: Pointer to object name, or nil when dirID specifies a directory that's the object. realVRefNum output: The real volume reference number. realParID output: The parent directory ID of the specified object. realName output: The name of the specified object (the case of the object name may not be the same as the object's catalog entry on disk - since the Macintosh file system is not case sensitive, it shouldn't matter). isDirectory output: True if object is a directory; false if object is a file. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname notAFileErr -1302 The pathname is nil, the pathname is empty, or the pathname cannot refer to a filename afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSMakeFSSpecCompat */ /*****************************************************************************/ pascal OSErr GetDirItems(short vRefNum, long dirID, ConstStr255Param name, Boolean getFiles, Boolean getDirectories, FSSpecPtr items, short reqItemCount, short *actItemCount, short *itemIndex); /* Return a list of items in a directory. The GetDirItems function returns a list of items in the specified directory in an array of FSSpec records. File, subdirectories, or both can be returned in the list. A noErr result indicates that the items array was filled (actItemCount == reqItemCount) and there may be additional items left in the directory. A fnfErr result indicates that the end of the directory list was found and actItemCount items were actually found this time. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. getFiles input: Pass true to have files added to the items list. getDirectories input: Pass true to have directories added to the items list. items input: Pointer to array of FSSpec where the item list is returned. reqItemCount input: Maximum number of items to return (the number of elements in the items array). actItemCount output: The number of items actually returned. itemIndex input: The current item index position. Set to 1 to start with the first item in the directory. output: The item index position to get the next item. Pass this value the next time you call GetDirItems to start where you left off. Result Codes noErr 0 No error, but there are more items to list nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found, there are no more items to be listed. paramErr -50 No default volume or itemIndex was <= 0 dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname */ /*****************************************************************************/ pascal OSErr DeleteDirectoryContents(short vRefNum, long dirID, ConstStr255Param name); /* Delete the contents of a directory. The DeleteDirectoryContents function deletes the contents of a directory. All files and subdirectories in the specified directory are deleted. If a locked file or directory is encountered, it is unlocked and then deleted. If any unexpected errors are encountered, DeleteDirectoryContents quits and returns to the caller. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock fBsyErr -47 File busy, directory not empty, or working directory control block open paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: DeleteDirectory */ /*****************************************************************************/ pascal OSErr DeleteDirectory(short vRefNum, long dirID, ConstStr255Param name); /* Delete a directory and its contents. The DeleteDirectory function deletes a directory and its contents. All files and subdirectories in the specified directory are deleted. If a locked file or directory is encountered, it is unlocked and then deleted. After deleting the directories contents, the directory is deleted. If any unexpected errors are encountered, DeleteDirectory quits and returns to the caller. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to directory name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock fBsyErr -47 File busy, directory not empty, or working directory control block open paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: DeleteDirectoryContents */ /*****************************************************************************/ pascal OSErr CheckObjectLock(short vRefNum, long dirID, ConstStr255Param name); /* Determine if a file or directory is locked. The CheckObjectLock function determines if a file or directory is locked. If CheckObjectLock returns noErr, then the file or directory is not locked. If CheckObjectLock returns fLckdErr, the it is locked. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: FSpCheckObjectLock */ /*****************************************************************************/ pascal OSErr FSpCheckObjectLock(const FSSpec *spec); /* Determine if a file or directory is locked. The FSpCheckObjectLock function determines if a file or directory is locked. If FSpCheckObjectLock returns noErr, then the file or directory is not locked. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ Also see: CheckObjectLock */ /*****************************************************************************/ pascal OSErr GetFileSize(short vRefNum, long dirID, ConstStr255Param fileName, long *dataSize, long *rsrcSize); /* Get the logical sizes of a file's forks. The GetFileSize function returns the logical size of a file's data and resource fork. vRefNum input: Volume specification. dirID input: Directory ID. name input: The name of the file. dataSize output: The number of bytes in the file's data fork. rsrcSize output: The number of bytes in the file's resource fork. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpGetFileSize */ /*****************************************************************************/ pascal OSErr FSpGetFileSize(const FSSpec *spec, long *dataSize, long *rsrcSize); /* Get the logical sizes of a file's forks. The FSpGetFileSize function returns the logical size of a file's data and resource fork. spec input: An FSSpec record specifying the file. dataSize output: The number of bytes in the file's data fork. rsrcSize output: The number of bytes in the file's resource fork. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found paramErr -50 No default volume dirNFErrdirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: GetFileSize */ /*****************************************************************************/ pascal OSErr BumpDate(short vRefNum, long dirID, ConstStr255Param name); /* Update the modification date of a file or directory. The BumpDate function changes the modification date of a file or directory to the current date/time. If the modification date is already equal to the current date/time, then add one second to the modification date. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpBumpDate */ /*****************************************************************************/ pascal OSErr FSpBumpDate(const FSSpec *spec); /* Update the modification date of a file or directory. The FSpBumpDate function changes the modification date of a file or directory to the current date/time. If the modification date is already equal to the current date/time, then add one second to the modification date. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: BumpDate */ /*****************************************************************************/ pascal OSErr ChangeCreatorType(short vRefNum, long dirID, ConstStr255Param name, OSType creator, OSType fileType); /* Change the creator or file type of a file. The ChangeCreatorType function changes the creator or file type of a file. vRefNum input: Volume specification. dirID input: Directory ID. name input: The name of the file. creator input: The new creator type or 0x00000000 to leave the creator type alone. fileType input: The new file type or 0x00000000 to leave the file type alone. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname notAFileErr -1302 Name was not a file afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpChangeCreatorType */ /*****************************************************************************/ pascal OSErr FSpChangeCreatorType(const FSSpec *spec, OSType creator, OSType fileType); /* Change the creator or file type of a file. The FSpChangeCreatorType function changes the creator or file type of a file. spec input: An FSSpec record specifying the file. creator input: The new creator type or 0x00000000 to leave the creator type alone. fileType input: The new file type or 0x00000000 to leave the file type alone. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname notAFileErr -1302 Name was not a file afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: ChangeCreatorType */ /*****************************************************************************/ pascal OSErr ChangeFDFlags(short vRefNum, long dirID, ConstStr255Param name, Boolean setBits, unsigned short flagBits); /* Set or clear Finder Flag bits. The ChangeFDFlags function sets or clears Finder Flag bits in the fdFlags field of a file or directory's FInfo record. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. setBits input: If true, then set the bits specified in flagBits. If false, then clear the bits specified in flagBits. flagBits input: The flagBits parameter specifies which Finder Flag bits to set or clear. If a bit in flagBits is set, then the same bit in fdFlags is either set or cleared depending on the state of the setBits parameter. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpChangeFDFlags */ /*****************************************************************************/ pascal OSErr FSpChangeFDFlags(const FSSpec *spec, Boolean setBits, unsigned short flagBits); /* Set or clear Finder Flag bits. The FSpChangeFDFlags function sets or clears Finder Flag bits in the fdFlags field of a file or directory's FInfo record. spec input: An FSSpec record specifying the object. setBits input: If true, then set the bits specified in flagBits. If false, then clear the bits specified in flagBits. flagBits input: The flagBits parameter specifies which Finder Flag bits to set or clear. If a bit in flagBits is set, then the same bit in fdFlags is either set or cleared depending on the state of the setBits parameter. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: ChangeFDFlags */ /*****************************************************************************/ pascal OSErr SetIsInvisible(short vRefNum, long dirID, ConstStr255Param name); /* Set the invisible Finder Flag bit. The SetIsInvisible function sets the invisible bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpSetIsInvisible, ClearIsInvisible, FSpClearIsInvisible */ /*****************************************************************************/ pascal OSErr FSpSetIsInvisible(const FSSpec *spec); /* Set the invisible Finder Flag bit. The FSpSetIsInvisible function sets the invisible bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsInvisible, ClearIsInvisible, FSpClearIsInvisible */ /*****************************************************************************/ pascal OSErr ClearIsInvisible(short vRefNum, long dirID, ConstStr255Param name); /* Clear the invisible Finder Flag bit. The ClearIsInvisible function clears the invisible bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsInvisible, FSpSetIsInvisible, FSpClearIsInvisible */ /*****************************************************************************/ pascal OSErr FSpClearIsInvisible(const FSSpec *spec); /* Clear the invisible Finder Flag bit. The FSpClearIsInvisible function clears the invisible bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsInvisible, FSpSetIsInvisible, ClearIsInvisible */ /*****************************************************************************/ pascal OSErr SetNameLocked(short vRefNum, long dirID, ConstStr255Param name); /* Set the nameLocked Finder Flag bit. The SetNameLocked function sets the nameLocked bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpSetNameLocked, ClearNameLocked, FSpClearNameLocked */ /*****************************************************************************/ pascal OSErr FSpSetNameLocked(const FSSpec *spec); /* Set the nameLocked Finder Flag bit. The FSpSetNameLocked function sets the nameLocked bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetNameLocked, ClearNameLocked, FSpClearNameLocked */ /*****************************************************************************/ pascal OSErr ClearNameLocked(short vRefNum, long dirID, ConstStr255Param name); /* Clear the nameLocked Finder Flag bit. The ClearNameLocked function clears the nameLocked bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetNameLocked, FSpSetNameLocked, FSpClearNameLocked */ /*****************************************************************************/ pascal OSErr FSpClearNameLocked(const FSSpec *spec); /* Clear the nameLocked Finder Flag bit. The FSpClearNameLocked function clears the nameLocked bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetNameLocked, FSpSetNameLocked, ClearNameLocked */ /*****************************************************************************/ pascal OSErr SetIsStationery(short vRefNum, long dirID, ConstStr255Param name); /* Set the isStationery Finder Flag bit. The SetIsStationery function sets the isStationery bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpSetIsStationery, ClearIsStationery, FSpClearIsStationery */ /*****************************************************************************/ pascal OSErr FSpSetIsStationery(const FSSpec *spec); /* Set the isStationery Finder Flag bit. The FSpSetIsStationery function sets the isStationery bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsStationery, ClearIsStationery, FSpClearIsStationery */ /*****************************************************************************/ pascal OSErr ClearIsStationery(short vRefNum, long dirID, ConstStr255Param name); /* Clear the isStationery Finder Flag bit. The ClearIsStationery function clears the isStationery bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsStationery, FSpSetIsStationery, FSpClearIsStationery */ /*****************************************************************************/ pascal OSErr FSpClearIsStationery(const FSSpec *spec); /* Clear the isStationery Finder Flag bit. The FSpClearIsStationery function clears the isStationery bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetIsStationery, FSpSetIsStationery, ClearIsStationery */ /*****************************************************************************/ pascal OSErr SetHasCustomIcon(short vRefNum, long dirID, ConstStr255Param name); /* Set the hasCustomIcon Finder Flag bit. The SetHasCustomIcon function sets the hasCustomIcon bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpSetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon */ /*****************************************************************************/ pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec); /* Set the hasCustomIcon Finder Flag bit. The FSpSetHasCustomIcon function sets the hasCustomIcon bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetHasCustomIcon, ClearHasCustomIcon, FSpClearHasCustomIcon */ /*****************************************************************************/ pascal OSErr ClearHasCustomIcon(short vRefNum, long dirID, ConstStr255Param name); /* Clear the hasCustomIcon Finder Flag bit. The ClearHasCustomIcon function clears the hasCustomIcon bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetHasCustomIcon, FSpSetHasCustomIcon, FSpClearHasCustomIcon */ /*****************************************************************************/ pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec); /* Clear the hasCustomIcon Finder Flag bit. The FSpClearHasCustomIcon function clears the hasCustomIcon bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: SetHasCustomIcon, FSpSetHasCustomIcon, ClearHasCustomIcon */ /*****************************************************************************/ pascal OSErr ClearHasBeenInited(short vRefNum, long dirID, ConstStr255Param name); /* Clear the hasBeenInited Finder Flag bit. The ClearHasBeenInited function clears the hasBeenInited bit in the fdFlags word of the specified file or directory's finder information. vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpClearHasBeenInited */ /*****************************************************************************/ pascal OSErr FSpClearHasBeenInited(const FSSpec *spec); /* Clear the hasBeenInited Finder Flag bit. The FSpClearHasBeenInited function clears the hasBeenInited bit in the fdFlags word of the specified file or directory's finder information. spec input: An FSSpec record specifying the object. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: ClearHasBeenInited */ /*****************************************************************************/ pascal OSErr CopyFileMgrAttributes(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, Boolean copyLockBit); /* Copy all File Manager attributes from the source to the destination. The CopyFileMgrAttributes function copies all File Manager attributes from the source file or directory to the destination file or directory. If copyLockBit is true, then set the locked state of the destination to match the source. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Pointer to source object name, or nil when srcDirID specifies a directory that's the object. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Pointer to destination object name, or nil when dstDirID specifies a directory that's the object. copyLockBit input: If true, set the locked state of the destination to match the source. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: FSpCopyFileMgrAttributes */ /*****************************************************************************/ pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec, const FSSpec *dstSpec, Boolean copyLockBit); /* Copy all File Manager attributes from the source to the destination. The FSpCopyFileMgrAttributes function copies all File Manager attributes from the source file or directory to the destination file or directory. If copyLockBit is true, then set the locked state of the destination to match the source. srcSpec input: An FSSpec record specifying the source object. dstSpec input: An FSSpec record specifying the destination object. copyLockBit input: If true, set the locked state of the destination to match the source. Result Codes noErr 0 No error nsvErr -35 No such volume ioErr -36 I/O error bdNamErr -37 Bad filename fnfErr -43 File not found fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only paramErr -50 No default volume dirNFErr -120 Directory not found or incomplete pathname afpAccessDenied -5000 User does not have the correct access afpObjectTypeErr -5025 Directory not found or incomplete pathname __________ See also: CopyFileMgrAttributes */ /*****************************************************************************/ pascal OSErr HOpenAware(short vRefNum, long dirID, ConstStr255Param fileName, short denyModes, short *refNum); /* Open the data fork of a file using deny mode permissions. The HOpenAware function opens the data fork of a file using deny mode permissions instead the normal File Manager permissions. If OpenDeny is not available, then HOpenAware translates the deny modes to the closest File Manager permissions and tries to open the file with OpenDF first, and then Open if OpenDF isn't available. By using HOpenAware with deny mode permissions, a program can be "AppleShare aware" and fall back on the standard File Manager open calls automatically. vRefNum input: Volume specification. dirID input: Directory ID. fileName input: The name of the file. denyModes input: The deny modes access under which to open the file. refNum output: The file reference number of the opened file. Result Codes noErr 0 No error nsvErr -35 No such volume tmfoErr -42 Too many files open fnfErr -43 File not found wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only opWrErr -49 File already open for writing paramErr -50 No default volume permErr -54 File is already open and cannot be opened using specified deny modes afpAccessDenied -5000 User does not have the correct access to the file afpDenyConflict -5006 Requested access permission not possible __________ See also: FSpOpenAware, HOpenRFAware, FSpOpenRFAware */ /*****************************************************************************/ pascal OSErr FSpOpenAware(const FSSpec *spec, short denyModes, short *refNum); /* Open the data fork of a file using deny mode permissions. The FSpOpenAware function opens the data fork of a file using deny mode permissions instead the normal File Manager permissions. If OpenDeny is not available, then FSpOpenAware translates the deny modes to the closest File Manager permissions and tries to open the file with OpenDF first, and then Open if OpenDF isn't available. By using FSpOpenAware with deny mode permissions, a program can be "AppleShare aware" and fall back on the standard File Manager open calls automatically. spec input: An FSSpec record specifying the file. denyModes input: The deny modes access under which to open the file. refNum output: The file reference number of the opened file. Result Codes noErr 0 No error nsvErr -35 No such volume tmfoErr -42 Too many files open fnfErr -43 File not found wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only opWrErr -49 File already open for writing paramErr -50 No default volume permErr -54 File is already open and cannot be opened using specified deny modes afpAccessDenied -5000 User does not have the correct access to the file afpDenyConflict -5006 Requested access permission not possible __________ See also: HOpenAware, HOpenRFAware, FSpOpenRFAware */ /*****************************************************************************/ pascal OSErr HOpenRFAware(short vRefNum, long dirID, ConstStr255Param fileName, short denyModes, short *refNum); /* Open the resource fork of a file using deny mode permissions. The HOpenRFAware function opens the resource fork of a file using deny mode permissions instead the normal File Manager permissions. If OpenRFDeny is not available, then HOpenRFAware translates the deny modes to the closest File Manager permissions and tries to open the file with OpenRF. By using HOpenRFAware with deny mode permissions, a program can be "AppleShare aware" and fall back on the standard File Manager open calls automatically. vRefNum input: Volume specification. dirID input: Directory ID. fileName input: The name of the file. denyModes input: The deny modes access under which to open the file. refNum output: The file reference number of the opened file. Result Codes noErr 0 No error nsvErr -35 No such volume tmfoErr -42 Too many files open fnfErr -43 File not found wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only opWrErr -49 File already open for writing paramErr -50 No default volume permErr -54 File is already open and cannot be opened using specified deny modes afpAccessDenied -5000 User does not have the correct access to the file afpDenyConflict -5006 Requested access permission not possible __________ See also: HOpenAware, FSpOpenAware, FSpOpenRFAware */ /*****************************************************************************/ pascal OSErr FSpOpenRFAware(const FSSpec *spec, short denyModes, short *refNum); /* Open the resource fork of a file using deny mode permissions. The FSpOpenRFAware function opens the resource fork of a file using deny mode permissions instead the normal File Manager permissions. If OpenRFDeny is not available, then FSpOpenRFAware translates the deny modes to the closest File Manager permissions and tries to open the file with OpenRF. By using FSpOpenRFAware with deny mode permissions, a program can be "AppleShare aware" and fall back on the standard File Manager open calls automatically. spec input: An FSSpec record specifying the file. denyModes input: The deny modes access under which to open the file. refNum output: The file reference number of the opened file. Result Codes noErr 0 No error nsvErr -35 No such volume tmfoErr -42 Too many files open fnfErr -43 File not found wPrErr -44 Volume locked by hardware fLckdErr -45 File is locked vLckdErr -46 Volume is locked or read-only opWrErr -49 File already open for writing paramErr -50 No default volume permErr -54 File is already open and cannot be opened using specified deny modes afpAccessDenied -5000 User does not have the correct access to the file afpDenyConflict -5006 Requested access permission not possible __________ See also: HOpenAware, FSpOpenAware, HOpenRFAware */ /*****************************************************************************/ pascal OSErr FSReadNoCache(short refNum, long *count, void *buffPtr); /* Read any number of bytes from an open file requesting no caching. The FSReadNoCache function reads any number of bytes from an open file while asking the file system to bypass its cache mechanism. refNum input: The file reference number of an open file. count input: The number of bytes to read. output: The number of bytes actually read. buffPtr input: A pointer to the data buffer into which the bytes are to be read. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open ioErr 36 Data does not match in read-verify mode fnOpnErr -38 File not open rfNumErr -51 Bad reference number afpAccessDenied -5000 User does not have the correct access to the file __________ See also: FSWriteNoCache */ /*****************************************************************************/ pascal OSErr FSWriteNoCache(short refNum, long *count, const void *buffPtr); /* Write any number of bytes to an open file requesting no caching. The FSReadNoCache function writes any number of bytes to an open file while asking the file system to bypass its cache mechanism. refNum input: The file reference number of an open file. count input: The number of bytes to write to the file. output: The number of bytes actually written. buffPtr input: A pointer to the data buffer from which the bytes are to be written. Result Codes noErr 0 No error writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Disk full ioErr 36 Data does not match in read-verify mode fnOpnErr -38 File not open wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock rfNumErr -51 Bad reference number wrPermErr -61 Read/write permission doesnt allow writing afpAccessDenied -5000 User does not have the correct access to the file __________ See also: FSReadNoCache */ /*****************************************************************************/ pascal OSErr FSWriteVerify(short refNum, long *count, const void *buffPtr); /* Write any number of bytes to an open file and then verify the data was written. The FSWriteVerify function writes any number of bytes to an open file and then verifies that the data was actually written to the device. refNum input: The file reference number of an open file. count input: The number of bytes to write to the file. output: The number of bytes actually written and verified. buffPtr input: A pointer to the data buffer from which the bytes are to be written. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Disk full ioErr 36 Data does not match in read-verify mode fnOpnErr -38 File not open eofErr -39 Logical end-of-file reached posErr -40 Attempt to position mark before start of file wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock rfNumErr -51 Bad reference number gfpErr -52 Error during GetFPos wrPermErr -61 Read/write permission doesnt allow writing memFullErr -108 Not enough room in heap zone to allocate verify buffer afpAccessDenied -5000 User does not have the correct access to the file */ /*****************************************************************************/ pascal OSErr CopyFork(short srcRefNum, short dstRefNum, void *copyBufferPtr, long copyBufferSize); /* Copy all data from the source fork to the destination fork of open file forks. The CopyFork function copies all data from the source fork to the destination fork of open file forks and makes sure the destination EOF is equal to the source EOF. srcRefNum input: The source file reference number. dstRefNum input: The destination file reference number. copyBufferPtr input: Pointer to buffer to use during copy. The buffer should be at least 512-bytes minimum. The larger the buffer, the faster the copy. copyBufferSize input: The size of the copy buffer. Result Codes noErr 0 No error readErr 19 Driver does not respond to read requests writErr 20 Driver does not respond to write requests badUnitErr 21 Driver reference number does not match unit table unitEmptyErr 22 Driver reference number specifies a nil handle in unit table abortErr 27 Request aborted by KillIO notOpenErr 28 Driver not open dskFulErr -34 Disk full ioErr 36 Data does not match in read-verify mode fnOpnErr -38 File not open wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Software volume lock rfNumErr -51 Bad reference number wrPermErr -61 Read/write permission doesnt allow writing afpAccessDenied -5000 User does not have the correct access to the file */ /*****************************************************************************/ pascal OSErr GetFileLocation(short refNum, short *vRefNum, long *dirID, StringPtr fileName); /* Get the location of an open file. The GetFileLocation function gets the location (volume reference number, directory ID, and fileName) of an open file. refNum input: The file reference number of an open file. vRefNum output: The volume reference number. dirID output: The parent directory ID. fileName input: Points to a buffer (minimum Str63) where the filename is to be returned or must be nil. output: The filename. Result Codes noErr 0 No error nsvErr -35 Specified volume doesnt exist fnOpnErr -38 File not open rfNumErr -51 Reference number specifies nonexistent access path __________ See also: FSpGetFileLocation */ /*****************************************************************************/ pascal OSErr FSpGetFileLocation(short refNum, FSSpec *spec); /* Get the location of an open file in an FSSpec record. The FSpGetFileLocation function gets the location of an open file in an FSSpec record. refNum input: The file reference number of an open file. spec output: FSSpec record containing the file name and location. Result Codes noErr 0 No error nsvErr -35 Specified volume doesnt exist fnOpnErr -38 File not open rfNumErr -51 Reference number specifies nonexistent access path __________ See also: GetFileLocation */ /*****************************************************************************/ pascal OSErr CopyDirectoryAccess(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName); /* Copy the AFP directory access privileges. The CopyDirectoryAccess function copies the AFP directory access privileges from one directory to another. Both directories must be on the same file server, but not necessarily on the same server volume. srcVRefNum input: Source volume specification. srcDirID input: Source directory ID. srcName input: Pointer to source directory name, or nil when srcDirID specifies the directory. dstVRefNum input: Destination volume specification. dstDirID input: Destination directory ID. dstName input: Pointer to destination directory name, or nil when dstDirID specifies the directory. Result Codes noErr 0 No error nsvErr -35 Volume not found fnfErr -43 Directory not found vLckdErr -46 Volume is locked or read-only paramErr -50 Volume doesn't support this function afpAccessDenied -5000 User does not have the correct access to the directory afpObjectTypeErr -5025 Object is a file, not a directory __________ See also: FSpCopyDirectoryAccess */ /*****************************************************************************/ pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec, const FSSpec *dstSpec); /* Copy the AFP directory access privileges. The FSpCopyDirectoryAccess function copies the AFP directory access privileges from one directory to another. Both directories must be on the same file server, but not necessarily on the same server volume. srcSpec input: An FSSpec record specifying the source directory. dstSpec input: An FSSpec record specifying the destination directory. Result Codes noErr 0 No error nsvErr -35 Volume not found fnfErr -43 Directory not found vLckdErr -46 Volume is locked or read-only paramErr -50 Volume doesn't support this function afpAccessDenied -5000 User does not have the correct access to the directory afpObjectTypeErr -5025 Object is a file, not a directory __________ See also: CopyDirectoryAccess */ /*****************************************************************************/ pascal OSErr HMoveRenameCompat(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstpathName, ConstStr255Param copyName); /* Move a file or directory and optionally rename it. The HMoveRenameCompat function moves a file or directory and optionally renames it. The source and destination locations must be on the same volume. This routine works even if the volume doesn't support MoveRename. vRefNum input: Volume specification. srcDirID input: Source directory ID. srcName input: The source object name. dstDirID input: Destination directory ID. dstName input: Pointer to destination directory name, or nil when dstDirID specifies a directory. copyName input: Points to the new name if the object is to be renamed or nil if the object isn't to be renamed. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 Volume not found ioErr -36 I/O error bdNamErr -37 Bad filename or attempt to move into a file fnfErr -43 Source file or directory not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 File busy, directory not empty, or working directory control block open dupFNErr -48 Destination already exists paramErr -50 Volume doesn't support this function, no default volume, or source and volOfflinErr -53 Volume is offline fsRnErr -59 Problem during rename dirNFErr -120 Directory not found or incomplete pathname badMovErr -122 Attempted to move directory into offspring wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) notAFileErr -1302 The pathname is nil, the pathname is empty, or the pathname cannot refer to a filename diffVolErr -1303 Files on different volumes afpAccessDenied -5000 The user does not have the right to move the file or directory afpObjectTypeErr -5025 Directory not found or incomplete pathname afpSameObjectErr -5038 Source and destination files are the same __________ See also: FSpMoveRenameCompat */ /*****************************************************************************/ pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName); /* Move a file or directory and optionally rename it. The FSpMoveRenameCompat function moves a file or directory and optionally renames it. The source and destination locations must be on the same volume. This routine works even if the volume doesn't support MoveRename. srcSpec input: An FSSpec record specifying the source object. dstSpec input: An FSSpec record specifying the destination directory. copyName input: Points to the new name if the object is to be renamed or nil if the object isn't to be renamed. Result Codes noErr 0 No error dirFulErr -33 File directory full dskFulErr -34 Disk is full nsvErr -35 Volume not found ioErr -36 I/O error bdNamErr -37 Bad filename or attempt to move into a file fnfErr -43 Source file or directory not found wPrErr -44 Hardware volume lock fLckdErr -45 File is locked vLckdErr -46 Destination volume is read-only fBsyErr -47 File busy, directory not empty, or working directory control block open dupFNErr -48 Destination already exists paramErr -50 Volume doesn't support this function, no default volume, or source and volOfflinErr -53 Volume is offline fsRnErr -59 Problem during rename dirNFErr -120 Directory not found or incomplete pathname badMovErr -122 Attempted to move directory into offspring wrgVolTypErr -123 Not an HFS volume (it's a MFS volume) notAFileErr -1302 The pathname is nil, the pathname is empty, or the pathname cannot refer to a filename diffVolErr -1303 Files on different volumes afpAccessDenied -5000 The user does not have the right to move the file or directory afpObjectTypeErr -5025 Directory not found or incomplete pathname afpSameObjectErr -5038 Source and destination files are the same __________ See also: HMoveRenameCompat */ /*****************************************************************************/ pascal OSErr BuildAFPVolMountInfo(short flags, char nbpInterval, char nbpCount, short uamType, Str32 zoneName, Str31 serverName, Str27 volName, Str31 userName, Str8 userPassword, Str8 volPassword, AFPVolMountInfoPtr *afpInfoPtr); /* Allocate and initializes the fields of an AFPVolMountInfo record. The BuildAFPVolMountInfo function allocates and initializes the fields of an AFPVolMountInfo record before using that record to call the VolumeMount function. flags input: The AFP mounting flags. 0 = normal mount; set bit 0 to inhibit greeting messages. nbpInterval input: The interval used for VolumeMount's NBP Lookup call. 7 is a good choice. nbpCount input: The retry count used for VolumeMount's NBP Lookup call. 5 is a good choice. uamType input: The user authentication method to use. zoneName input: The AppleTalk zone name of the server. serverName input: The AFP server name. volName input: The AFP volume name. userName input: The user name (zero length Pascal string for guest). userPassWord input: The user password (zero length Pascal string if no user password) volPassWord input: The volume password (zero length Pascal string if no volume password) afpInfoPtr output: A pointer to the newly created and initialized AFPVolMountInfo record. If the function fails to create an AFPVolMountInfo record, it sets afpInfoPtr to NULL and the function result is memFullErr. Your program is responsible for disposing of this pointer when it is finished with it. Result Codes noErr 0 No error memFullErr -108 memory full error __________ Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, RetrieveAFPVolMountInfo, BuildAFPXVolMountInfo, RetrieveAFPXVolMountInfo */ /*****************************************************************************/ pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr afpInfoPtr, short *flags, short *uamType, StringPtr zoneName, StringPtr serverName, StringPtr volName, StringPtr userName); /* Retrieve the AFP mounting information from an AFPVolMountInfo record. The RetrieveAFPVolMountInfo function retrieves the AFP mounting information returned in an AFPVolMountInfo record by the GetVolMountInfo function. afpInfoPtr input: Pointer to AFPVolMountInfo record that contains the AFP mounting information. flags output: The AFP mounting flags. uamType output: The user authentication method used. zoneName output: The AppleTalk zone name of the server. serverName output: The AFP server name. volName output: The AFP volume name. userName output: The user name (zero length Pascal string for guest). Result Codes noErr 0 No error paramErr -50 media field in AFP mounting information was not AppleShareMediaType __________ Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, BuildAFPVolMountInfo, BuildAFPXVolMountInfo, RetrieveAFPXVolMountInfo */ /*****************************************************************************/ pascal OSErr BuildAFPXVolMountInfo(short flags, char nbpInterval, char nbpCount, short uamType, Str32 zoneName, Str31 serverName, Str27 volName, Str31 userName, Str8 userPassword, Str8 volPassword, Str32 uamName, unsigned long alternateAddressLength, void *alternateAddress, AFPXVolMountInfoPtr *afpXInfoPtr); /* Allocate and initializes the fields of an AFPXVolMountInfo record. The BuildAFPXVolMountInfo function allocates and initializes the fields of an AFPXVolMountInfo record before using that record to call the VolumeMount function. flags input: The AFP mounting flags. nbpInterval input: The interval used for VolumeMount's NBP Lookup call. 7 is a good choice. nbpCount input: The retry count used for VolumeMount's NBP Lookup call. 5 is a good choice. uamType input: The user authentication method to use. zoneName input: The AppleTalk zone name of the server. serverName input: The AFP server name. volName input: The AFP volume name. userName input: The user name (zero length Pascal string for guest). userPassWord input: The user password (zero length Pascal string if no user password) volPassWord input: The volume password (zero length Pascal string if no volume password) uamName input: The User Authentication Method name. alternateAddressLength input: Length of alternateAddress data. alternateAddress input The AFPAlternateAddress (variable length) afpXInfoPtr output: A pointer to the newly created and initialized AFPVolMountInfo record. If the function fails to create an AFPVolMountInfo record, it sets afpInfoPtr to NULL and the function result is memFullErr. Your program is responsible for disposing of this pointer when it is finished with it. Result Codes noErr 0 No error memFullErr -108 memory full error __________ Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, BuildAFPVolMountInfo, RetrieveAFPVolMountInfo, RetrieveAFPXVolMountInfo */ /*****************************************************************************/ pascal OSErr RetrieveAFPXVolMountInfo(AFPXVolMountInfoPtr afpXInfoPtr, short *flags, short *uamType, StringPtr zoneName, StringPtr serverName, StringPtr volName, StringPtr userName, StringPtr uamName, unsigned long *alternateAddressLength, AFPAlternateAddress **alternateAddress); /* Retrieve the AFP mounting information from an AFPXVolMountInfo record. The RetrieveAFPXVolMountInfo function retrieves the AFP mounting information returned in an AFPXVolMountInfo record by the GetVolMountInfo function. afpXInfoPtr input: Pointer to AFPXVolMountInfo record that contains the AFP mounting information. flags output: The AFP mounting flags. uamType output: The user authentication method used. zoneName output: The AppleTalk zone name of the server. serverName output: The AFP server name. volName output: The AFP volume name. userName output: The user name (zero length Pascal string for guest). uamName output: The User Authentication Method name. alternateAddressLength output: Length of alternateAddress data returned. alternateAddress: output: A pointer to the newly created and AFPAlternateAddress record (a variable length record). If the function fails to create an AFPAlternateAddress record, it sets alternateAddress to NULL and the function result is memFullErr. Your program is responsible for disposing of this pointer when it is finished with it. Result Codes noErr 0 No error paramErr -50 media field in AFP mounting information was not AppleShareMediaType memFullErr -108 memory full error __________ Also see: GetVolMountInfoSize, GetVolMountInfo, VolumeMount, BuildAFPVolMountInfo, RetrieveAFXVolMountInfo, BuildAFPXVolMountInfo */ /*****************************************************************************/ pascal OSErr GetUGEntries(short objType, UGEntryPtr entries, long reqEntryCount, long *actEntryCount, long *objID); /* Retrieve a list of user or group entries from the local file server. The GetUGEntries functions retrieves a list of user or group entries from the local file server. objType input: The object type: -1 = group; 0 = user UGEntries input: Pointer to array of UGEntry records where the list is returned. reqEntryCount input: The number of elements in the UGEntries array. actEntryCount output: The number of entries returned. objID input: The current index position. Set to 0 to start with the first entry. output: The index position to get the next entry. Pass this value the next time you call GetUGEntries to start where you left off. Result Codes noErr 0 No error fnfErr -43 No more users or groups paramErr -50 Function not supported; or, ioObjID is negative __________ Also see: GetUGEntry */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __MOREFILESEXTRAS__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/Optimization.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** DirectoryCopy: #defines that let you make MoreFiles code more efficient. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: Optimization.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. ** ** The Optimization changes to MoreFiles source and header files, along with ** this file and OptimizationEnd.h, let you optimize the code produced ** by MoreFiles in several ways. ** ** 1 -- MoreFiles contains extra code so that many routines can run under ** Mac OS systems back to System 6. If your program requires a specific ** version of Mac OS and your program checks for that version before ** calling MoreFiles routines, then you can remove a lot of compatibility ** code by defining one of the following to 1: ** ** __MACOSSEVENFIVEONEORLATER // assume Mac OS 7.5.1 or later ** __MACOSSEVENFIVEORLATER // assume Mac OS 7.5 or later ** __MACOSSEVENORLATER // assume Mac OS 7.0 or later ** ** If you're compiling 68K code, the default is to include all compatibility code. ** If you're compiling PowerPC code (TARGET_RT_MAC_CFM), the default is __MACOSSEVENORLATER ** If you're compiling for Carbon code (TARGET_API_MAC_CARBON), the default is __MACOSSEVENFIVEONEORLATER ** ** 2 -- You may disable Pascal calling conventions in all MoreFiles routines ** except for system callbacks that require Pascal calling conventions. ** This will make 68K C programs both smaller and faster. ** (PowerPC compilers ignore pascal calling conventions.) ** Just define __WANTPASCALELIMINATION to be 1 to turn this optimization on ** when building MoreFiles for use from C programs (you'll need to keep ** Pascal calling conventions when linking MoreFiles routines with Pascal ** programs). ** ** 3 -- If Metrowerks compiler is used, "#pragma internal on" may help produce ** better code. However, this option can also cause problems if you're ** trying to build MoreFiles as a shared library, so it is by default not used. ** Just define __USEPRAGMAINTERNAL to be 1 to turn this optimization on. ** ** Original changes supplied by Fabrizio Oddone ** ** File: Optimization.h */ #include // if we're compiling for Carbon, then we're running on Mac OS 8.1 or later #ifndef __MACOSSEVENFIVEONEORLATER #define __MACOSSEVENFIVEONEORLATER TARGET_API_MAC_CARBON #endif #ifndef __MACOSSEVENFIVEORLATER #define __MACOSSEVENFIVEORLATER __MACOSSEVENFIVEONEORLATER #endif #ifndef __MACOSSEVENORLATER #if TARGET_RT_MAC_CFM #define __MACOSSEVENORLATER 1 #else #define __MACOSSEVENORLATER __MACOSSEVENFIVEORLATER #endif #endif #ifndef __WANTPASCALELIMINATION #define __WANTPASCALELIMINATION 0 #endif #if __WANTPASCALELIMINATION #define pascal #endif #ifndef __USEPRAGMAINTERNAL #define __USEPRAGMAINTERNAL 0 #endif #if __USEPRAGMAINTERNAL #if defined(__MWERKS__) #pragma internal on #endif #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/OptimizationEnd.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** DirectoryCopy: #defines that let you make MoreFiles code more efficient. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: OptimizationEnd.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. ** ** The Optimization changes to MoreFiles source and header files, along with ** this file and Optimization.h, let you optimize the code produced by MoreFiles ** in several ways. ** ** Original changes supplied by Fabrizio Oddone */ #if __USEPRAGMAINTERNAL #if defined(__MWERKS__) #pragma internal reset #endif #endif #if __WANTPASCALELIMINATION #ifndef __COMPILINGMOREFILES #undef pascal #endif #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/C Headers/Search.h ================================================ /* ** Apple Macintosh Developer Technical Support ** ** IndexedSearch and the PBCatSearch compatibility function. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: Search.h ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #ifndef __SEARCH__ #define __SEARCH__ #include #include #include "Optimization.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ pascal OSErr IndexedSearch(CSParamPtr pb, long dirID); /* Search in and below a directory. The IndexedSearch function performs an indexed search in and below the specified directory using the same parameters (in pb) as is passed to PBCatSearch. See Inside Macintosh: Files for a description of the parameter block. pb input: A CSParamPtr record specifying the volume to search and the search criteria. output: Fields in the parameter block are returned indicating the number of matches found, the matches, and if the search ended with noErr, the CatPosition record that lets you resume a search where the last search left off. dirID input: The directory to search. If fsRtDirID is passed, the entire volume is searched. Note: If you use a high-level debugger and use ioSearchTime to limit the length of time to run the search, you'll want to step over calls to IndexedSearch because it installs a Time Manager task. Most high-level debuggers don't deal gracefully with interrupt driven code. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error eofErr -39 End of catalog found (this is normal!) paramErr -50 Parameter block has invalid parameters (see source for VerifyUserPB) or invalid catPosition record was passed extFSErr -58 External file system error - no file system claimed this call. memFullErr -108 Memory could not be allocated in heap catChangedErr -1304 Catalog has changed and catalog position record may be invalid __________ See also: PBCatSearch, PBCatSearchSyncCompat */ /*****************************************************************************/ pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock); /* Search a volume using PBCatSearch or IndexedSearch. The PBCatSearchSyncCompat function uses PBCatSearch (if available) or IndexedSearch (if PBCatSearch is not available) to search a volume using a set of search criteria that you specify. It builds a list of all files or directories that meet your specifications. pb input: A CSParamPtr record specifying the volume to search and the search criteria. output: Fields in the parameter block are returned indicating the number of matches found, the matches, and if the search ended with noErr, the CatPosition record that lets you resume a search where the last search left off. Note: If you use a high-level debugger and use ioSearchTime to limit the length of time to run the search, you'll want to step over calls to PBCatSearchSyncCompat because it calls IndexedSearch which installs a Time Manager task. Most high-level debuggers don't deal gracefully with interrupt driven code. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error eofErr -39 End of catalog found (this is normal!) paramErr -50 Parameter block has invalid parameters (see source for VerifyUserPB) or invalid catPosition record was passed extFSErr -58 External file system error - no file system claimed this call. memFullErr -108 Memory could not be allocated in heap catChangedErr -1304 Catalog has changed and catalog position record may be invalid afpCatalogChanged -5037 Catalog has changed and search cannot be resumed __________ See also: PBCatSearch, IndexedSearch */ /*****************************************************************************/ pascal OSErr NameFileSearch(ConstStr255Param volName, short vRefNum, ConstStr255Param fileName, FSSpecPtr matches, long reqMatchCount, long *actMatchCount, Boolean newSearch, Boolean partial); /* Search for files by file name with PBCatSearch. The NameFileSearch function searches for files with a specific file name on a volume that supports PBCatSearch. Note: A result of catChangedErr means the catalog has changed between searches, but the search can be continued with the possiblity that you may miss some matches or get duplicate matches. For all other results (except for noErr), the search cannot be continued. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. fileName input: The name of the file to search for. matches input: Pointer to array of FSSpec where the match list is returned. reqMatchCount input: Maximum number of matches to return (the number of elements in the matches array). actMatchCount output: The number of matches actually returned. newSearch input: If true, start a new search. If false and if vRefNum is the same as the last call to NameFileSearch, then start searching at the position where the last search left off. partial input: If the partial parameter is false, then only files that exactly match fileName will be found. If the partial parameter is true, then all file names that contain fileName will be found. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error eofErr -39 End of catalog found (this is normal!) paramErr -50 Parameter block has invalid parameters (see source for VerifyUserPB) or invalid catPosition record was passed extFSErr -58 External file system error - no file system claimed this call. memFullErr -108 Memory could not be allocated in heap catChangedErr -1304 Catalog has changed and catalog position record may be invalid afpCatalogChanged -5037 Catalog has changed and search cannot be resumed __________ Also see: CreatorTypeFileSearch */ /*****************************************************************************/ pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName, short vRefNum, OSType creator, OSType fileType, FSSpecPtr matches, long reqMatchCount, long *actMatchCount, Boolean newSearch); /* Search for files by creator/fileType with PBCatSearch. The CreatorTypeFileSearch function searches for files with a specific creator or fileType on a volume that supports PBCatSearch. Note: A result of catChangedErr means the catalog has changed between searches, but the search can be continued with the possiblity that you may miss some matches or get duplicate matches. For all other results (except for noErr), the search cannot be continued. volName input: A pointer to the name of a mounted volume or nil. vRefNum input: Volume specification. creator input: The creator type of the file to search for. To ignore the creator type, pass 0x00000000 in this field. fileType input: The file type of the file to search for. To ignore the file type, pass 0x00000000 in this field. matches input: Pointer to array of FSSpec where the match list is returned. reqMatchCount input: Maximum number of matches to return (the number of elements in the matches array). actMatchCount output: The number of matches actually returned. newSearch input: If true, start a new search. If false and if vRefNum is the same as the last call to CreatorTypeFileSearch, then start searching at the position where the last search left off. Result Codes noErr 0 No error nsvErr -35 Volume not found ioErr -36 I/O error eofErr -39 End of catalog found (this is normal!) paramErr -50 Parameter block has invalid parameters (see source for VerifyUserPB) or invalid catPosition record was passed extFSErr -58 External file system error - no file system claimed this call. memFullErr -108 Memory could not be allocated in heap catChangedErr -1304 Catalog has changed and catalog position record may be invalid afpCatalogChanged -5037 Catalog has changed and search cannot be resumed __________ Also see: NameFileSearch */ /*****************************************************************************/ #ifdef __cplusplus } #endif #include "OptimizationEnd.h" #endif /* __SEARCH__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/MoreFilesReadMe ================================================ MoreFiles A collection of File Manager and related routines by Jim Luther (Apple Macintosh Developer Technical Support Emeritus) with significant code contributions by Nitin Ganatra (Apple Macintosh Developer Technical Support Emeritus) Copyright 1992-1999 Apple Computer, Inc. Portions copyright 1995 Jim Luther All rights reserved. You may incorporate this sample code into your applications without restriction, though the sample code has been provided "AS IS" and the responsibility for its operation is 100% yours. However, what you are not permitted to do is to redistribute the source as "DSC Sample Code" after having made changes. If you're going to redistribute the source, we require that you make it clear in the source that the code was descended from Apple Sample Code, but that you've made changes. What is MoreFiles? MoreFiles is a collection of high-level routines written over the years to answer File Manager questions developers have sent to Apple Developer Technical Support, and to answer questions on various online services and the internet. The routines have been tested (but not stress-tested), documented, code-reviewed, and used in both my own programs, the Macintosh OS, and in many commercial products. Important Note These routines are meant to be used from an application environment. In particular, some routines use static variables which require an A5 world (if youre building 68K code) and almost all routines make calls that are unsafe at interrupt time (i.e., synchronous File Manager calls and Memory Manager calls). If you plan to use these routines from stand-alone 68K code modules, you may need to make some modifications to the code that uses static variables. Don't even think about using most of these routines from code that executes at interrupt time. Note: If you need to use the routines in FSpCompat in stand-alone 68K code, set GENERATENODATA to 1 in FSpCompat.c (or pass it in) so globals (static variables) are not used. Some routines in Search.c also use static variables. Build Environments MoreFiles is built using the latest development environments I have access to and Universal Interfaces v3.3. You might have to make some minor changes to compile or link with MoreFiles. The Pascal interfaces to MoreFiles are maintained, but have not been tested with all available Pascal development environments. Notes: Starting with MoreFiles 1.5, IDE project files and MPW make/build files are not included because: (a) many developers do not have the latest development environments, (b) IDE project files are often not comaptible with newer or older versions of IDEs. Starting with MoreFiles 1.5, you may need to link 68K programs with Math64Lib.o if your development environment doesn't support long long variables. Files in the MoreFiles Package MoreFiles.c - the glue code for high-level and FSSpec style routines that were never implemented or added to the standard interface for one reason or another. If you're uncomfortable filling in parameter blocks, you'll find the code in this file very useful. MoreFiles.h and MoreFiles.p - the documentation and header files for calling the routines included in MoreFiles.c. MoreFilesExtras.c - a collection of useful File Manager utility routines. MoreFilesExtras.h and MoreFilesExtras.p - the documentation and header files for calling the routines included in MoreFilesExtras.c. I recommend that you browse through the header files - you'll probably find a routine that you've always wanted. MoreDesktopMgr.c - a collection of useful high-level Desktop Manager routines. If the Desktop Manager isn't available, the "Desktop" file is used for 'read' operations. MoreDesktopMgr.h and MoreDesktopMgr.p - the documentation and header files for calling the routines included in MoreDesktopMgr.c. FileCopy.c - a robust, general purpose file copy routine that does everything the right way. Copying a file on the Macintosh isn't as simple as you'd think if you want to handle all cases (i.e., file server drop boxes, preflighting disk space, etc.). This routine does it all and is fast, too. FileCopy.h and FileCopy.p - the documentation and header files for calling the routines included in FileCopy.c. DirectoryCopy.c - a general purpose recursive directory copy routine with a hook for your error handling routine and a hook for filtering what you want or don't want copied. DirectoryCopy.h and DirectoryCopy.p - the documentation and header files for calling the routines included in DirectoryCopy.c. FSpCompat.c - the glue code for FSSpec style routines that will work under System 6 as much as possible. If you still need to support System 6, you'll find the code in this file very useful. FSpCompat.h and FSpCompat.p - the documentation and header files for calling the routines included in FSpCompat.c. Search.c - IndexedSearch and PBCatSearchSyncCompat. IndexedSearch performs an indexed search in and below the specified directory using the same parameters as is passed to PBCatSearch. PBCatSearchSyncCompat uses PBCatSearch (if available) or IndexedSearch (if PBCatSearch is not available) to search a volume. Also included are a couple of examples of how to call PBCatSearch: one that searches by creator and file type, and one that searches by file name. Search.h and Search.p - the documentation and header files for calling the routines included in Search.c. FullPath.c - Routines for dealing with full pathnames if you really must use them. Read the warning at the top of the interface files for reasons why you shouldn't use them most of the time. FullPath.h and FullPath.p - the documentation and header files for calling the routines included in FullPath.c. IterateDirectory.c - Routines that perform a recursive iteration (scan) of a specified directory and call your IterateFilterProc function once for each file and directory found. IterateDirectory lets you decide how deep you want the function to dive into the directory tree - anything from 1 level or all levels. This routine is very useful when you want to do something to each item in a directory. IterateDirectory.h and IterateDirectory.p - the documentation and header files for calling the routines included in IterateDirectory.c. Optimization.h and OptimizationEnd.h - Used to provide code opimizations to the code generated from MoreFiles sources. Notes: If you're compiling 68K code, __MACOSSEVENFIVEONEORLATER, __MACOSSEVENFIVEORLATER, and __MACOSSEVENORLATER are by default defined to 0 so all compatibility code is included by default. If you're compiling PowerPC code (TARGET_RT_MAC_CFM), the default is __MACOSSEVENORLATER. If you're compiling for Carbon code (TARGET_API_MAC_CARBON), the default is __MACOSSEVENFIVEONEORLATER. How to use MoreFiles You can compile the code and link it into your programs. You can cut and paste portions of it into your programs. You can use it as example code (as sample code, many routines in MoreFiles should be modified by you to do what you want them to do). Feel free to rip MoreFiles off and modify it's code in whatever ways you find work best for you. All exported routines use Pascal calling conventions so this code can be used from either C or Pascal and with 68K or PowerPC compliers. (Note: Pascal calling conventions can be turned off starting with MoreFiles 1.4.2. BE CAREFUL WITH THE CALLBACKS if you use this option!) You'll also notice that all routines that make other File Manager calls return an OSErr result. I always check for error results and you should too. (Well, there's a few places where I purposely ignore errors, but they're commented in the source.) Documentation The documentation for the routines can be found in the C header files. There, you'll find a short description of each call and a complete listing of all input and output parameters. I've also included a list of possible result codes for each routine. For example, here's the documentation for one of the routines, GetFileLocation. /*****************************************************************************/ pascal OSErr GetFileLocation(short refNum, short *vRefNum, long *dirID, StringPtr fileName); /* Get the location of an open file. The GetFileLocation function gets the location (volume reference number, directory ID, and fileName) of an open file. refNum input: The file reference number of an open file. vRefNum output: The volume reference number. dirID output: The parent directory ID. fileName input: Points to a buffer (minimum Str63) where the filename is to be returned or must be nil. output: The filename. Result Codes noErr 0 No error nsvErr -35 Specified volume doesnt exist fnOpnErr -38 File not open rfNumErr -51 Reference number specifies nonexistent access path __________ See also: FSpGetFileLocation */ /*****************************************************************************/ Some routines have very few comments in their code because they simply make a single File Manager call. For those routines, the routine description is the comment. However, you'll find that more complicated routines have plenty of comments to clarify what and why the code is doing something. If something isn't clear, take a look at "Inside Macintosh: Files" and the TechNote "Inside Macintosh: Files - Errata" for further reference. Release Notes v1.0 09/14/93 v1.1 01/22/94 v1.1.1 02/01/94 v1.2 07/20/94 v1.2.1 08/09/94 v1.2.2 11/01/94 v1.3 04/17/95 v1.3.1 06/17/95 ________________________________________ v1.4 12/21/95 New Routines: Added directory scanning functions, IterateDirectory and FSpIterateDirectory in a new files IterateDirectory.c, IterateDirectory.h and IterateDirectory.p. Check these routines out. I think you'll find them useful. Added SetDefault and RestoreDefault to MoreFileExtras. These routines let you set the default directory for those times when you're stuck calling standard C I/O or a library that takes only a filename. Added XGetVInfo to MoreFilesExtras. Like GetVInfo, this routine returns the volume name, volume reference number, and free bytes on the volume; like HGetVInfo, XGetVInfo also returns the total number of bytes on the volume. Both freeBytes and totalBytes are UnsignedWide values so this routine can report volume size information for volumes up to 2 terabytes. XGetVInfo's glue code calls through to HGetVInfo if needed to provide backwards compatibility. Bugs fixed: Fixed bug where FileCopy could pass NULL to CopyFileMgrAttributes if PBHCopyFile was used. Added 68K alignment to MoreDesktopMgr.c structs. Added 68K alignment to MoreFilesExtras.p records. Other changes: Conditionalized FSpCompat.c with SystemSevenOrLater and SystemSevenFiveOrLater so the FSSpec compatibility code is only included when needed. It makes the code a little harder to read, but it removes 2K-3K of code and the overhead of additional calls when SystemSevenOrLater and SystemSevenFiveOrLater are true. See ConditionalMacros.h for an explanation of SystemSevenOrLater and SystemSevenFiveOrLater. Moved the code to create a full pathname from GetFullPath to FSpGetFullPath. This accomplished two goals: (1) when FSpGetFullPath is used, the input FSSpec isn't passed to FSMakeFSSpecCompat (it was already an FSSpec) and (2) the code is now smaller. While I was in the code, I changed a couple of calls from Munger to PtrToHand. Changed GetDirID to GetDirectoryID so that MoreFiles could be used by MacApp programs (There's a MacApp method named GetDirID). Changed DirIDFromFSSpec to FSpGetDirectoryID to be consistent in naming conventions. Added macros wrapped with "#if OLDROUTINENAMES #endif" so GetDirID and DirIDFromFSSpec will still work with your old code. Changed alignment #if's to use PRAGMA_ALIGN_SUPPORTED instead of GENERATINGPOWERPC (will they ever stop changing?). Changed all occurances of filler2 to ioACUser to match the change in Universal Interfaces 2.1. Added type-casts from "void *" to "Ptr" in various places to get rid of compiler warnings. Added CallCopyErrProc to DirectoryCopy.h and DirectoryCopy.c (it just looks better that way). Added the "__cplusplus" conditional code around all .h header files so they'll work with C++. Built libraries with Metrowerks, THINK C, and MPW so everyone can link. ________________________________________ v1.4.1 1/6/96 Bugs fixed: Fixed the conditionalized code FSpCreateCompat. Fixed the conditionalized code FSpExchangeFilesCompat. Fixed the conditionalized code FSpCreateResFileCompat. Other changes: Changed PBStatus(&pb, false) to PBStatusSync(&pb) in GetDiskBlocks. ________________________________________ v1.4.2 3/25/96 New Routines: Added FSpResolveFileIDRef to MoreFiles. Added GetIOACUser and FSpGetIOACUser to MoreFilesExtras. These routines let you get a directory's access privileges for the current user. Added bit masks, macros, and function for testing ioACUser values to MoreFilesExtras.h and MoreFilesExtras.p. Added GetVolumeInfoNoName to MoreFilesExtras to put common calls to PBHGetVInfo in one place. Functions that call GetVolumeInfoNoName are: (in DirectoryCopy.c) PreflightDirectoryCopySpace, (in FileCopy.c) PreflightFileCopySpace, (in MoreFilesExtras.c) DetermineVRefNum, CheckVolLock, FindDrive, UnmountAndEject, (in Search.c) CheckVol. Added GetCatInfoNoName to MoreFilesExtras to put common calls to PBGetCatInfo in one place. Functions that call GetCatInfoNoName are: (in FileCopy.c) GetDestinationDirInfo, (in MoreDesktopMgr.c) GetCommentID, (in MoreFilesExtras.c) GetDInfo, GetDirectoryID, CheckObjectLock. Added TruncPString to MoreFilesExtras. This lets you shorten a Pascal string without breaking the string in the middle of a multi-byte character. Added FilteredDirectoryCopy and FSpFilteredDirectoryCopy to DirectoryCopy. FilteredDirectoryCopy and FSpFilteredDirectoryCopy work just like DirectoryCopy and FSpDirectoryCopy only they both take an optional CopyFilterProc parameter which can point to routine you supply. The CopyFilterProc lets your code decide what files or directories are copied to the destination. DirectoryCopy and FSpDirectoryCopy now call through to FilteredDirectoryCopy with a NULL CopyFilterProc. Bugs fixed: Fixed minor bug in GetDiskBlocks where driveQElementPtr->dQRefNum was checked when driveQElementPtr could be NULL. DirectoryCopy didn't handle error conditions correctly. In some cases, DirectoryCopy would return noErr when there was a problem and in other cases, the CopyErrProc wasn't called and the function immediately failed. The result of DirectoryCopy's CopyErrProc was documented incorrectly. Other changes and improvements: Added result codes to function descriptions in the C header files (these probably aren't a perfect list of possible errors, but they should catch most of the results you'll ever see). Removed most of the function descriptions in Pascal interface files since they haven't been completely in sync with the C headers for some time and I don't have time to keep the documentation in both places up to date. Rewrote HMoveRenameCompat so it doesn't use the Temporary Items folder. Added parameter checking to OnLine so that it doesn't allow the volIndex parameter to be less than or equal to 0. Added parameter checking to GetDirItems so that it doesn't allow the itemIndex parameter to be less than or equal to 0. FSpExchangeFilesCompat now returns diffVolErr (instead of paramErr) if the source and the destination are on different volumes. Changed GetDirName's name parameter to Str31 and added parameter checking so that it doesn't allow a NULL name parameter. Forced errors returned by MoreDesktopMgr routines to be closer to what would be expected if the low-level Desktop Manager calls were used. Added conditionalized changes from Fabrizio Oddone so that Pascal calling conventions can be easily disabled. Disabling Pascal calling conventions reduces the code size slightly and allows C compilers to optimize parameter passing. NOTE: If you disable Pascal calling conventions, you'll have to remove the "pascal" keyword from all of the MoreFiles callbacks you've defined in your code. Changed DirectoryCopy so that you can copy the source directory's content to a disk's root directory. Added a build script and a make file for MPW libraries. Added a build script for Metrowerks CodeWarrior libraries. Added a build script for Symantec THINK Project Manager and Symantec Project Manager libraries. Renamed the Symantec and Metrowerks project files. Changed MoreFiles directory structure so that C headers, Pascal interfaces, and the source code aren't in the main directory. Thanks to Fabrizio Oddone for supplying the conditionalized changes that optionally remove Pascal calling conventions. Thanks to Byron Han for beating the bugs out of DirectoryCopy and for suggesting and prototyping the changes needed for the "copy to root directory" option and the FilteredDirectoryCopy routine in DirectoryCopy. ________________________________________ v1.4.3 8/24/96 Bugs fixed: Fixed bug in GetDriverName where dctlDriver is a handle. It was not dereferenced correctly. Fixed the MPW build file, BuildMoreFiles, so it would correctly pass options to MoreFilesLib.make. GetFullPath now returns fullPathLength = 0 and fullPath = NULL as documented. Other changes and improvements: Added PBXGetVolInfoSync glue code to MoreFilesExtras.c when GENERATINGCFM is true. This allows building with no link errors where PBXGetVolInfoSync isn't included in your development system's standard libraries. This routine shouldn't be needed in MoreFiles at some point in the future after it has been added to your development system's standard libraries. Changed BuildMoreFiles and MoreFilesLib.make to use the MrC compiler instead of the PPCC compiler. Removed BuildMoreFiles Symantec because it's much simpler to include MoreFiles as a subproject in your Symantec project instead of building a library and then including it. Removed non-strict ANSI comment from PascalElim.h and used conditional code instead. GetFullPath and FSpGetFullPath return full pathname to directories with a trailing colon character. For example, they now return "MyVolume:MyDirectory:" instead of "MyVolume:MyDirectory". Changed the MoreFiles feedback email address (below) in this Read Me file. ________________________________________ v1.4.4 12/18/96 Bugs fixed: Added "| REGISTER_RESULT_LOCATION(kRegisterD0)" to uppFSDispatchProcInfo in PBXGetVolInfoSync. (the code produced is the same since REGISTER_RESULT_LOCATION(kRegisterD0) happens to be 0). Initialized ioDTReqCount before calling PBDTGetComment. See the comment in DTGetComment in MoreDesktopMgr.c for the reasons why. Fixed paramErr check in GetDirName in MoreFilesExtras.c so it actually works. Rewrote CopyDirectoryAccess in MoreFilesExtras.c for better error handling. Fixed error handling in GetAPPLFromDesktopFile in MoreDesktopMgr.c. Fixed off by one errors in GetLocalIDFromFREF and GetIconRsrcIDFromLocalID in MoreDesktopMgr.c. Changed IterateDirectoryLevel so that it continues iterating when it finds a directory that cannot be accessed due to an afpAccessDenied error. Other changes and improvements: Added const type qualifier to input-only pointer parameters. That includes changing many StringPtr parameters to ConstStr255Param (thanks to Stephen C. Gilardi for starting this project). General cleanup to improve readability and code generation. Added DTXGetAPPL to MoreDesktopMgr. DTXGetAPPL works like DTGetAPPL only it has an additional input parameter, searchCatalog. If searchCatalog is set to false, the catalog search is skipped if the application isn't found in the desktop database or desktop file. This is useful if you need to find the application quickly (the catalog search can be quite time consuming). Removed "BuildMoreFiles Metrowerks" script. I've decided that it's too hard to keep the scripts working with current IDEs. Removed pre-v1.4 release notes from this file because it was too big for SimpleText. ________________________________________ v1.4.5 12/20/96 Bugs fixed: Fixed logic bug in HOpenAware and HOpenRFAware. Those two functions and FileCopy (which calls them) DO NOT work in MoreFiles version 1.4.4. ________________________________________ v1.4.6 2/15/97 Bugs fixed: Fixed bug in PreflightFileCopySpace (FileCopy.c) introduced in MoreFiles version 1.4.4. Fixed problem between PBXGetVolInfoSync and __WANTPASCALELIMINATION conditional. HMoveRenameCompat from v1.4.2 through v1.4.5 worked with files but not folders, and comments were not being moved along with the file. Reverted HMoveRenameCompat to the v1.4.1 source and then fixed the possible collision in the Temporary Items folder by creating a new uniquely named subfolder in the Temporary Items folder. Other changes and improvements: Added GetVolState function to MoreFilesExtras. Use GetVolState to determine a volumes online and eject state and the volume drivers need for eject requests. Added GetVolFileSystemID function to MoreFilesExtras. Renamed PascalElim.h to Optimization.h since it now contains additional optimization directives. Added OptimizationEnd.h. Checks for __WANTPASCALELIMINATION now use #if instead of #ifdef to be consistent with other conditionals in MoreFiles and in Apple interfaces. Added #pragma internal on if __MWERKS__ is defined to Optimization.h and OptimizationEnd.h to produce better code under Metrowerks compilers. In Optimization.h, define __WANTPASCALELIMINATION to 0 if not already defined so __WANTPASCALELIMINATION can be passed in from the command line. In FSpCompat.c, define GENERATENODATA to 0 if not already defined so GENERATENODATA can be passed in from the command line. Added FSpDTXGetAPPL to MoreDesktopMgr. Added echo lines to MoreFilesLib.make so the build process can be monitored. ________________________________________ v1.4.7 3/1/98 Bugs fixed: Fixed DirectoryCopy.p header (FSpFilteredDirectoryCopy wasn't there; FSpDirectoryCopy was there twice). PreflightFileCopySpace, PreflightGlobals, and PreflightDirectoryCopySpace now use unsigned long values for block counts to support Mac OS Enhanced volumes which can have more than 64K of allocation blocks, and to fix problems with large files. Other changes and improvements: __USEPRAGMAINTERNAL is now used to control the "#pragma internal on" optimization and it defaults to off in Optimization.h. In most cases, output parameters are not changed if error occurs (for example, see ResolveFileIDRef). Added __MACOSSEVENFIVEONEORLATER, __MACOSSEVENFIVEORLATER, and __MACOSSEVENORLATER defines so that compatibility and bug fix code can be removed when specific versions of Mac OS are required. (FSpCompat.c is affected the most.) Reconditionalized FSpCompat.c so that more compatibility code can be stripped. Added XGetVolumeInfoNoName to MoreFilesExtras.c. GetFullPath and FSpGetFullPath now allow creation of full pathnames to files or directories that don't exist (all directories up to that file/directory must exist). Added BuildAFPXVolMountInfo and RetrieveAFPXVolMountInfo to work with new AppleShare IP clients (AppleShare client versions 3.7 and later). Changed API of BuildAFPVolMountInfo to closely match BuildAFPXVolMountInfo. It now allocates the space for the AFPVolMountInfo record. RetrieveAFPVolMountInfo now checks offsets and doesn't use them if they are zero. Conditionally added volume mount constants and structures (from Files.h in Universal Interfaces 3.0.1 and later) to MoreFilesExtras.h and .p. Added XVolumeParam to UniversalFMPB. Changed zoneName and serverName fields in MyAFPVolMountInfo to Str32 since AppleTalk names can be 32 characters. Added MyAFPXVolMountInfo to MoreFilesExtras.h. Added XGetVolumeInfoNoName to MoreFilesExtras.h. Removed Sharing.h, Sharing.p, and UpperString.p. The routines defined by these files have been defined for several years, so it's time for them to go. Removed FindFolderGlue.o library. The code in the FindFolderGlue.o library is supplied by all recent development environments, so it's time for it to go. ________________________________________ v1.4.8 3/24/98 Bugs fixed: Fixed conditional errors introduced in v1.4.7 in FSpCompat.c. Initialized realResult to noErr in FSpGetFullPath. Changed comment in IterateDirectory.p for MyIterateFilterProc - the CInfoPBRec parameter should be {CONST} VAR. ________________________________________ v1.4.9 9/2/98 Bugs fixed: Changed parameter order in PBXGetVolInfoSync to match that in InterfaceLib. CreateFileIDRef and FSpCreateFileIDRef now return the file ID when it already exists and PBCreateFileID has returned fidExists or afpIDExists. In other words, you can use the file ID if either function returns noErr, fidExists, or afpIDExists. ________________________________________ v1.5 12/6/99 Bugs fixed: Fixed off-by-one bug in TruncPString. Other changes and improvements: Updated sources for Universal Interfaces 3.3. This includes changes where the code uses UInt64 variables, removing all bit and mask definitions in MoreFilesExtras.h if they are already defined in Files.h, using the latest names for bits and masks, and making sure only symbols available to Carbon are used (except where the code is conditionalized for Carbon). Conditionalized code and headers for Carbon. If __MACOSSEVENFIVEONEORLATER is undefined, set it to TARGET_API_MAC_CARBON in Optimization.h. Renamed PBXGetVolInfoSync PowerPC glue code to CallPBXGetVolInfoSync, and changed it to call the real PBXGetVolInfoSync code in InterfaceLib if possible. This code is conditionalized for Carbon and 68K where PBXGetVolInfoSync is always available. HGetVInfo now calls through to XGetVInfo to get the best results. Added work-around for Alias Manager sloppy volume matching problem in FSpLocationFromFullPath. Added work-around for Navigation Services invalid FSSpec problem in FSpGetFullPath. Added copyName parameter to all DirectoryCopy routines so that the source directory's name can be changed at the destination. Updated GetVolParmsInfoBuffer macros in MoreFilesExtras.h. Conditionalized PBCatSearchSyncCompat for System 7.0 or later (hasFullExtFSDispatching is always true with Systme 7.0 and later). ________________________________________ Thanks again (you know who you are) for the bug reports and suggestions that helped improve MoreFiles since the last version(s). To file bug reports and enhancement requests, please go to http://developer.apple.com/bugreporter/ and include "MoreFiles Sample Code" in the title of your message. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/DirectoryCopy.p ================================================ UNIT DirectoryCopy; { Apple Macintosh Developer Technical Support } { } { DirectoryCopy: A robust, general purpose directory copy routine. } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: DirectoryCopy.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files; {***************************************************************************} { DirectoryCopy failedOperation codes. } CONST getNextItemOp = 1; { couldn't access items in this } { directory - no access privileges } copyDirCommentOp = 2; { couldn't copy directory's Finder } { comment } copyDirAccessPrivsOp = 3; { couldn't copy directory's AFP access } { privileges } copyDirFMAttributesOp = 4; { couldn't copy directory's File } { Manager attributes } dirCreateOp = 5; { couldn't create destination directory } fileCopyOp = 6; { couldn't copy file } {***************************************************************************} TYPE CopyErrProcPtr = ProcPtr; { A DirectoryCopy CopyErrProc function should have the following form: } { } { FUNCTION MyCopyErrProc (error: OSErr; } { failedOperation: Integer; } { srcVRefNum: Integer; } { srcDirID: LongInt; } { srcName: StringPtr; } { dstVRefNum: Integer; } { dstDirID: LongInt; } { dstName: StringPtr): Boolean; } CopyFilterProcPtr = ProcPtr; { A DirectoryCopy CopyFilterProc function should have the following form: } { } { FUNCTION MyCopyFilterProc (cpbPtr: CInfoPBPtr): Boolean; } {***************************************************************************} FUNCTION FilteredDirectoryCopy (srcVRefNum: Integer; srcDirID: LongInt; srcName: StringPtr; dstVRefNum: Integer; dstDirID: LongInt; dstName: StringPtr; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean; copyErrHandler: CopyErrProcPtr; copyFilterProc: CopyFilterProcPtr): OSErr; FUNCTION FSpFilteredDirectoryCopy ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean; copyErrHandler: CopyErrProcPtr; copyFilterProc: CopyFilterProcPtr): OSErr; FUNCTION DirectoryCopy (srcVRefNum: Integer; srcDirID: LongInt; srcName: StringPtr; dstVRefNum: Integer; dstDirID: LongInt; dstName: StringPtr; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean; copyErrHandler: CopyErrProcPtr): OSErr; FUNCTION FSpDirectoryCopy ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean; copyErrHandler: CopyErrProcPtr): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/FSpCompat.p ================================================ UNIT FSpCompat; { Apple Macintosh Developer Technical Support } { } { FSSpec compatibility functions } { } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: FSpCompat.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files, Finder; {***************************************************************************} FUNCTION FSMakeFSSpecCompat (vRefNum: INTEGER; dirID: LONGINT; fileName: Str255; VAR spec: FSSpec): OSErr; FUNCTION FSpOpenDFCompat ({CONST} VAR spec: FSSpec; permission: SignedByte; VAR refNum: INTEGER): OSErr; FUNCTION FSpOpenRFCompat ({CONST} VAR spec: FSSpec; permission: SignedByte; VAR refNum: INTEGER): OSErr; FUNCTION FSpCreateCompat ({CONST} VAR spec: FSSpec; creator: OSType; fileType: OSType; scriptTag: ScriptCode): OSErr; FUNCTION FSpDirCreateCompat ({CONST} VAR spec: FSSpec; scriptTag: ScriptCode; VAR createdDirID: LONGINT): OSErr; FUNCTION FSpDeleteCompat ({CONST} VAR spec: FSSpec): OSErr; FUNCTION FSpGetFInfoCompat ({CONST} VAR spec: FSSpec; VAR fndrInfo: FInfo): OSErr; FUNCTION FSpSetFInfoCompat ({CONST} VAR spec: FSSpec; fndrInfo: FInfo): OSErr; FUNCTION FSpSetFLockCompat ({CONST} VAR spec: FSSpec): OSErr; FUNCTION FSpRstFLockCompat ({CONST} VAR spec: FSSpec): OSErr; FUNCTION FSpRenameCompat ({CONST} VAR spec: FSSpec; newName: Str255): OSErr; FUNCTION FSpCatMoveCompat ({CONST} VAR source: FSSpec; {CONST} VAR dest: FSSpec): OSErr; FUNCTION FSpExchangeFilesCompat ({CONST} VAR source: FSSpec; {CONST} VAR dest: FSSpec): OSErr; FUNCTION FSpOpenResFileCompat ({CONST} VAR spec: FSSpec; permission: SignedByte): INTEGER; PROCEDURE FSpCreateResFileCompat ({CONST} VAR spec: FSSpec; creator: OSType; fileType: OSType; scriptTag: ScriptCode); {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/FileCopy.p ================================================ UNIT FileCopy; { Apple Macintosh Developer Technical Support } { } { FileCopy: A robust, general purpose file copy routine. } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: FileCopy.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files; {***************************************************************************} FUNCTION FileCopy (srcVRefNum: Integer; srcDirID: LongInt; srcName: Str255; dstVRefNum: Integer; dstDirID: LongInt; dstPathname: StringPtr; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean): OSErr; FUNCTION FSpFileCopy ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr; copyBufferPtr: Ptr; copyBufferSize: LongInt; preflight: Boolean): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/FullPath.p ================================================ UNIT FullPath; { Apple Macintosh Developer Technical Support } { } { Routines for dealing with full pathnames... if you really must. } { } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: FullPath.p } { } { Copyright 1995-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } { IMPORTANT NOTE: } { } { The use of full pathnames is strongly discouraged. Full pathnames are } { particularly unreliable as a means of identifying files, directories } { or volumes within your application, for two primary reasons: } { } { The user can change the name of any element in the path at } { virtually any time. } { Volume names on the Macintosh are *not* unique. Multiple } { mounted volumes can have the same name. For this reason, the use of } { a full pathname to identify a specific volume may not produce the } { results you expect. If more than one volume has the same name and } { a full pathname is used, the File Manager currently uses the first } { mounted volume it finds with a matching name in the volume queue. } { } { In general, you should use a files name, parent directory ID, and } { volume reference number to identify a file you want to open, delete, } { or otherwise manipulate. } { } { If you need to remember the location of a particular file across } { subsequent system boots, use the Alias Manager to create an alias } { record describing the file. If the Alias Manager is not available, you } { can save the files name, its parent directory ID, and the name of the } { volume on which its located. Although none of these methods is } { foolproof, they are much more reliable than using full pathnames to } { identify files. } { } { Nonetheless, it is sometimes useful to display a files full pathname } { to the user. For example, a backup utility might display a list of full } { pathnames of files as it copies them onto the backup medium. Or, a } { utility might want to display a dialog box showing the full pathname of } { a file when it needs the users confirmation to delete the file. No } { matter how unreliable full pathnames may be from a file-specification } { viewpoint, users understand them more readily than volume reference } { numbers or directory IDs. } { } { The following technique for constructing the full pathname of a file is } { intended for display purposes only. Applications that depend on any } { particular structure of a full pathname are likely to fail on alternate } { foreign file systems or under future system software versions. } INTERFACE USES Types, Files; {***************************************************************************} FUNCTION GetFullPath (vRefNum: INTEGER; dirID: LONGINT; name: StringPtr; VAR fullPathLength: INTEGER; VAR fullPath: Handle): OSErr; FUNCTION FSpGetFullPath ({CONST} VAR spec: FSSpec; VAR fullPathLength: INTEGER; VAR fullPath: Handle): OSErr; FUNCTION FSpLocationFromFullPath (fullPathLength: INTEGER; fullPath: Ptr; VAR spec: FSSpec): OSErr; FUNCTION LocationFromFullPath (fullPathLength: INTEGER; fullPath: Ptr; VAR vRefNum: INTEGER; VAR parID: LONGINT; VAR name: Str31): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/IterateDirectory.p ================================================ UNIT IterateDirectory; { IterateDirectory: File Manager directory iterator routines. } { } { by Jim Luther } { } { File: IterateDirectory.p } { } { Copyright 1996-1999 Jim Luther and Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. } { } { IterateDirectory is designed to drop into the MoreFiles sample code } { library I wrote while in Apple Developer Technical Support } INTERFACE USES Types, Files; {***************************************************************************} TYPE IterateFilterProcPtr = ProcPtr; { A IterateDirectory IterateFilterProc procedure should have the } { following form where the CInfoPBRec should be considered a CONST } { (do not change it): } { } { PROCEDURE MyIterateFilterProcPtr (VAR cpbPtr: CInfoPBRec; } { VAR quitFlag: Boolean; } { yourDataPtr: Ptr); } {***************************************************************************} FUNCTION IterateDirectory (vRefNum: Integer; dirID: LongInt; name: StringPtr; maxLevels: Integer; iterateFilter: IterateFilterProcPtr; yourDataPtr: Ptr): OSErr; FUNCTION FSpIterateDirectory ({CONST} VAR spec: FSSpec; maxLevels: Integer; iterateFilter: IterateFilterProcPtr; yourDataPtr: Ptr): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/MoreDesktopMgr.p ================================================ UNIT MoreDesktopMgr; { Apple Macintosh Developer Technical Support } { } { A collection of useful high-level Desktop Manager routines. } { If the Desktop Manager isn't available, use the Desktop file } { for 'read' operations. } { } { We do more because we can... } { } { by Jim Luther and Nitin Ganatra, } { Apple Developer Technical Support Emeriti } { } { File: MoreDesktopMgr.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files; {***************************************************************************} FUNCTION DTOpen (volName: StringPtr; vRefNum: Integer; VAR dtRefNum: Integer; VAR newDTDatabase: Boolean): OSErr; FUNCTION DTXGetAPPL (volName: StringPtr; vRefNum: Integer; creator: OSType; searchCatalog: Boolean; VAR applVRefNum: Integer; VAR applParID: LongInt; VAR applName: Str255): OSErr; FUNCTION FSpDTXGetAPPL (volName: StringPtr; vRefNum: Integer; creator: OSType; searchCatalog: Boolean; VAR spec: FSSpec): OSErr; FUNCTION DTGetAPPL (volName: StringPtr; vRefNum: Integer; creator: OSType; VAR applVRefNum: Integer; VAR applParID: LongInt; VAR applName: Str255): OSErr; FUNCTION FSpDTGetAPPL (volName: StringPtr; vRefNum: Integer; creator: OSType; VAR spec: FSSpec): OSErr; FUNCTION DTGetIcon (volName: StringPtr; vRefNum: Integer; iconType: Integer; fileCreator: OSType; fileType: OSType; VAR iconHandle: Handle): OSErr; FUNCTION DTSetComment (vRefNum: Integer; dirID: LongInt; name: StringPtr; comment: Str255): OSErr; FUNCTION FSpDTSetComment ({CONST} VAR spec: FSSpec; comment: Str255): OSErr; FUNCTION DTGetComment (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR comment: Str255): OSErr; FUNCTION FSpDTGetComment ({CONST} VAR spec: FSSpec; VAR comment: Str255): OSErr; FUNCTION DTCopyComment (srcVRefNum: Integer; srcDirID: LongInt; srcName: StringPtr; dstVRefNum: Integer; dstDirID: LongInt; dstName: StringPtr): OSErr; FUNCTION FSpDTCopyComment ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/MoreFiles.p ================================================ UNIT MoreFiles; { Apple Macintosh Developer Technical Support } { } { The long lost high-level and FSSpec File Manager functions. } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: MoreFiles.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files; {***************************************************************************} FUNCTION HGetVolParms (volName: StringPtr; vRefNum: Integer; VAR volParmsInfo: GetVolParmsInfoBuffer; VAR infoSize: LongInt): OSErr; FUNCTION HCreateMinimum (vRefNum: Integer; dirID: LongInt; fileName: Str255): OSErr; FUNCTION FSpCreateMinimum ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ExchangeFiles (vRefNum: Integer; srcDirID: LongInt; srcName: Str255; dstDirID: LongInt; dstName: Str255): OSErr; FUNCTION ResolveFileIDRef (volName: StringPtr; vRefNum: Integer; fileID: LongInt; VAR parID: LongInt; fileName: StringPtr): OSErr; FUNCTION FSpResolveFileIDRef (volName: StringPtr; vRefNum: Integer; fileID: LongInt; VAR spec: FSSpec): OSErr; FUNCTION CreateFileIDRef (vRefNum: Integer; parID: LongInt; fileName: Str255; VAR fileID: LongInt): OSErr; FUNCTION FSpCreateFileIDRef ({CONST} VAR spec: FSSpec; VAR fileID: LongInt): OSErr; FUNCTION DeleteFileIDRef (volName: StringPtr; vRefNum: Integer; fileID: LongInt): OSErr; FUNCTION FlushFile (refNum: Integer): OSErr; FUNCTION LockRange (refNum: Integer; rangeLength: LongInt; rangeStart: LongInt): OSErr; FUNCTION UnlockRange (refNum: Integer; rangeLength: LongInt; rangeStart: LongInt): OSErr; FUNCTION GetForeignPrivs (vRefNum: Integer; dirID: LongInt; name: StringPtr; foreignPrivBuffer: Ptr; VAR foreignPrivSize: LongInt; VAR foreignPrivInfo1: LongInt; VAR foreignPrivInfo2: LongInt; VAR foreignPrivInfo3: LongInt; VAR foreignPrivInfo4: LongInt): OSErr; FUNCTION FSpGetForeignPrivs ({CONST} VAR spec: FSSpec; foreignPrivBuffer: Ptr; VAR foreignPrivSize: LongInt; VAR foreignPrivInfo1: LongInt; VAR foreignPrivInfo2: LongInt; VAR foreignPrivInfo3: LongInt; VAR foreignPrivInfo4: LongInt): OSErr; FUNCTION SetForeignPrivs (vRefNum: Integer; dirID: LongInt; name: StringPtr; foreignPrivBuffer: Ptr; VAR foreignPrivSize: LongInt; foreignPrivInfo1: LongInt; foreignPrivInfo2: LongInt; foreignPrivInfo3: LongInt; foreignPrivInfo4: LongInt): OSErr; FUNCTION FSpSetForeignPrivs ({CONST} VAR spec: FSSpec; foreignPrivBuffer: Ptr; VAR foreignPrivSize: LongInt; foreignPrivInfo1: LongInt; foreignPrivInfo2: LongInt; foreignPrivInfo3: LongInt; foreignPrivInfo4: LongInt): OSErr; FUNCTION HGetLogInInfo (volName: StringPtr; vRefNum: Integer; VAR loginMethod: Integer; userName: StringPtr): OSErr; FUNCTION HGetDirAccess (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR ownerID: LongInt; VAR groupID: LongInt; VAR accessRights: LongInt): OSErr; FUNCTION FSpGetDirAccess ({CONST} VAR spec: FSSpec; VAR ownerID: LongInt; VAR groupID: LongInt; VAR accessRights: LongInt): OSErr; FUNCTION HSetDirAccess (vRefNum: Integer; dirID: LongInt; name: StringPtr; ownerID: LongInt; groupID: LongInt; accessRights: LongInt): OSErr; FUNCTION FSpSetDirAccess ({CONST} VAR spec: FSSpec; ownerID: LongInt; groupID: LongInt; accessRights: LongInt): OSErr; FUNCTION HMapID (volName: StringPtr; vRefNum: Integer; ugID: LongInt; objType: Integer; name: StringPtr): OSErr; FUNCTION HMapName (volName: StringPtr; vRefNum: Integer; name: Str255; objType: Integer; VAR ugID: LongInt): OSErr; FUNCTION HCopyFile (srcVRefNum: Integer; srcDirID: LongInt; srcName: Str255; dstVRefNum: Integer; dstDirID: LongInt; dstPathname: StringPtr; copyName: StringPtr): OSErr; FUNCTION FSpCopyFile ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr): OSErr; FUNCTION HMoveRename (vRefNum: Integer; srcDirID: LongInt; srcName: Str255; dstDirID: LongInt; dstpathName: StringPtr; copyName: StringPtr): OSErr; FUNCTION FSpMoveRename ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr): OSErr; FUNCTION GetVolMountInfoSize (volName: StringPtr; vRefNum: Integer; VAR size: Integer): OSErr; FUNCTION GetVolMountInfo (volName: StringPtr; vRefNum: Integer; volMountInfo: Ptr): OSErr; FUNCTION VolumeMount (volMountInfo: Ptr; VAR vRefNum: Integer): OSErr; FUNCTION Share (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpShare ({CONST} VAR spec: FSSpec): OSErr; FUNCTION Unshare (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpUnshare ({CONST} VAR spec: FSSpec): OSErr; FUNCTION GetUGEntry (objType: Integer; objName: StringPtr; VAR objID: LongInt): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/MoreFilesExtras.p ================================================ UNIT MoreFilesExtras; { Apple Macintosh Developer Technical Support } { } { A collection of useful high-level File Manager routines. } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: MoreFilesExtras.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files, Finder; {***************************************************************************} CONST { Deny mode permissions for use with the HOpenAware, HOpenRFAware, } { FSpOpenAware, and FSpOpenRFAware functions. } { Note: Common settings are the ones with comments. } dmNone = $0000; dmNoneDenyRd = fsRdDenyPerm; dmNoneDenyWr = fsWrDenyPerm; dmNoneDenyRdWr = fsRdDenyPerm + fsWrDenyPerm; dmRd = fsRdPerm; { Single writer, multiple readers; the readers } dmRdDenyRd = fsRdPerm + fsRdDenyPerm; dmRdDenyWr = fsRdPerm + fsWrDenyPerm; { Browsing - equivalent to fsRdPerm } dmRdDenyRdWr = fsRdPerm + fsRdDenyPerm + fsWrDenyPerm; dmWr = fsWrPerm; dmWrDenyRd = fsWrPerm + fsRdDenyPerm; dmWrDenyWr = fsWrPerm + fsWrDenyPerm; dmWrDenyRdWr = fsWrPerm + fsRdDenyPerm + fsWrDenyPerm; dmRdWr = fsRdWrPerm; { Shared access - equivalent to fsRdWrShPerm } dmRdWrDenyRd = fsRdWrPerm + fsRdDenyPerm; dmRdWrDenyWr = fsRdWrPerm + fsWrDenyPerm; { Single writer, multiple readers; the writer } dmRdWrDenyRdWr = fsRdWrPerm + fsRdDenyPerm + fsWrDenyPerm; { Exclusive access - equivalent to fsRdWrPerm } { Bit masks to get common information out of ioACUser returned by } { PBGetCatInfo (remember to clear ioACUser before calling PBGetCatInfo } { since some file systems don't bother to set this field). } { } { Use the GetDirAccessRestrictions or FSpGetDirAccessRestrictions } { functions to retrieve the ioACUser access restrictions byte for } { a folder. } { } { Note: The access restriction byte returned by PBGetCatInfo is the } { 2's complement of the user's privileges byte returned in } { ioACAccess by PBHGetDirAccess. } { mask for just the access restriction bits } acUserAccessMask = kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask + kioACUserNoMakeChangesMask; { common access privilege settings } acUserFull = $00; { no access restiction bits on } acUserNone = acUserAccessMask; { all access restiction bits on } acUserDropBox = kioACUserNoSeeFolderMask + kioACUserNoSeeFilesMask; { make changes, but not see files or folders } acUserBulletinBoard = kioACUserNoMakeChangesMask; { see files and folders, but not make changes } { For those times where you need to use more than one kind of } { File Manager parameter block but don't feel like wasting stack space, } { here's a parameter block you can reuse. } {$PUSH} {$ALIGN MAC68K} TYPE UniversalFMPBHandle = ^UniversalFMPBPtr; UniversalFMPBPtr = ^UniversalFMPB; UniversalFMPB = RECORD CASE Integer OF 1: ( PB: ParamBlockRec ); 2: ( ciPB: CInfoPBRec ); 3: ( dtPB: DTPBRec ); 4: ( hPB: HParamBlockRec ); 5: ( cmPB: CMovePBRec ); 6: ( wdPB: WDPBRec ); 7: ( fcbPB: FCBPBRec ); 8: ( xPB: XVolumeParam ); END; { Used by GetUGEntries to return user or group lists. } UGEntryHandle = ^UGEntryPtr; UGEntryPtr = ^UGEntry; UGEntry = RECORD objType: Integer; objID: LongInt; name: Str31; END; { I use the following records instead of the AFPVolMountInfo and } { AFPXVolMountInfo structures in Files.p } Str8 = STRING[8]; MyAFPVolMountInfoHandle = ^MyAFPVolMountInfoPtr; MyAFPVolMountInfoPtr = ^MyAFPVolMountInfo; MyAFPVolMountInfo = RECORD length: Integer; { length of this record } media: VolumeType; { type of media, always AppleShareMediaType } flags: Integer; { 0 = normal mount; set bit 0 to inhibit greeting messages } nbpInterval: SignedByte; { NBP interval parameter; 7 is a good choice } nbpCount: SignedByte; { NBP count parameter; 5 is a good choice } uamType: Integer; { User Authentication Method } zoneNameOffset: Integer; { offset from start of record to zoneName } serverNameOffset: Integer; { offset from start of record to serverName } volNameOffset: Integer; { offset from start of record to volName } userNameOffset: Integer; { offset from start of record to userName } userPasswordOffset: Integer; { offset from start of record to userPassword } volPasswordOffset: Integer; { offset from start of record to volPassword } zoneName: Str32; { server's AppleTalk zone name } serverName: Str32; { server name } volName: Str27; { volume name } userName: Str31; { user name (zero length Pascal string for guest) } userPassword: Str8; { user password (zero length Pascal string if no user password) } volPassword: Str8; { volume password (zero length Pascal string if no volume password) } END; MyAFPXVolMountInfo = RECORD length: Integer; { length of this record } media: VolumeType; { type of media, always AppleShareMediaType } flags: Integer; { 0 = normal mount; set bit 0 to inhibit greeting messages } nbpInterval: SignedByte; { NBP interval parameter; 7 is a good choice } nbpCount: SignedByte; { NBP count parameter; 5 is a good choice } uamType: Integer; { User Authentication Method } zoneNameOffset: Integer; { offset from start of record to zoneName } serverNameOffset: Integer; { offset from start of record to serverName } volNameOffset: Integer; { offset from start of record to volName } userNameOffset: Integer; { offset from start of record to userName } userPasswordOffset: Integer; { offset from start of record to userPassword } volPasswordOffset: Integer; { offset from start of record to volPassword } extendedFlags: Integer; { extended flags word } uamNameOffset: Integer; { offset to a pascal UAM name string } alternateAddressOffset: Integer; { offset to Alternate Addresses in tagged format } zoneName: Str32; { server's AppleTalk zone name } serverName: Str32; { server name } volName: Str27; { volume name } userName: Str31; { user name (zero length Pascal string for guest) } userPassword: Str8; { user password (zero length Pascal string if no user password) } volPassword: Str8; { volume password (zero length Pascal string if no volume password) } uamName: Str32; { UAM name } alternateAddress: Packed Array [0..0] OF Char; { variable length data } END; {$ALIGN RESET} {$POP} {***************************************************************************} { Functions to get information out of GetVolParmsInfoBuffer. } { (implemented in this Unit). } { version 1 field getters } FUNCTION GetVolParmsInfoVersion(VAR volParms: GetVolParmsInfoBuffer): INTEGER; FUNCTION GetVolParmsInfoAttrib(VAR volParms: GetVolParmsInfoBuffer): LONGINT; FUNCTION GetVolParmsInfoLocalHand(VAR volParms: GetVolParmsInfoBuffer): Handle; FUNCTION GetVolParmsInfoServerAdr(VAR volParms: GetVolParmsInfoBuffer): LONGINT; { version 2 field getters (assume zero result if not version >= 2) } FUNCTION GetVolParmsInfoVolumeGrade(VAR volParms: GetVolParmsInfoBuffer): LONGINT; FUNCTION GetVolParmsInfoForeignPrivID(VAR volParms: GetVolParmsInfoBuffer): INTEGER; { version 3 field getters (assume zero result if not version >= 3) } FUNCTION GetVolParmsInfoExtendedAttributes(VAR volParms: GetVolParmsInfoBuffer): LONGINT; { attribute bits supported by all versions of GetVolParmsInfoBuffer } FUNCTION isNetworkVolume (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasLimitFCBs (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasLocalWList (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoMiniFndr (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoVNEdit (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoLclSync (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasTrshOffLine (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoSwitchTo (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoDeskItems (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoBootBlks (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasAccessCntl (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasNoSysDir (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasExtFSVol (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasOpenDeny (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasCopyFile (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasMoveRename (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasDesktopMgr (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasShortName (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasFolderLock (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasPersonalAccessPrivileges (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasUserGroupList (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasCatSearch (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasFileIDs (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasBTreeMgr (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION hasBlankAccessPrivileges (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION supportsAsyncRequests (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION supportsTrashVolumeCache (VAR volParms: GetVolParmsInfoBuffer): Boolean; { attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer } FUNCTION volIsEjectable (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsHFSPlusAPIs (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsFSCatalogSearch (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsFSExchangeObjects (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupports2TBFiles (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsLongNames (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsMultiScriptNames (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsNamedForks (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volSupportsSubtreeIterators (VAR volParms: GetVolParmsInfoBuffer): Boolean; FUNCTION volL2PCanMapFileBlocks (VAR volParms: GetVolParmsInfoBuffer): Boolean; { Functions to get common information out of ioACUser. } { (implemented in this Unit). } FUNCTION userIsOwner (ioACUser: SInt8): Boolean; FUNCTION userHasFullAccess (ioACUser: SInt8): Boolean; FUNCTION userHasDropBoxAccess (ioACUser: SInt8): Boolean; FUNCTION userHasBulletinBoard (ioACUser: SInt8): Boolean; FUNCTION userHasNoAccess (ioACUser: SInt8): Boolean; {***************************************************************************} PROCEDURE TruncPString (destination: StringPtr; source: StringPtr; maxLength: Integer); FUNCTION GetTempBuffer (buffReqSize: LONGINT; VAR buffActSize: LONGINT): Ptr; FUNCTION GetVolumeInfoNoName (pathname: StringPtr; vRefNum: Integer; VAR pb: HParamBlockRec): OSErr; FUNCTION XGetVolumeInfoNoName(pathname: StringPtr; vRefNum: Integer; VAR pb: XVolumeParam): OSErr; FUNCTION GetCatInfoNoName (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR pb: CInfoPBRec): OSErr; FUNCTION DetermineVRefNum (pathname: StringPtr; vRefNum: Integer; VAR realVRefNum: Integer): OSErr; FUNCTION HGetVInfo (volReference: Integer; volName: StringPtr; VAR vRefNum: Integer; VAR freeBytes: LongInt; VAR totalBytes: LongInt): OSErr; FUNCTION XGetVInfo (volReference: Integer; volName: StringPtr; VAR vRefNum: Integer; VAR freeBytes: UnsignedWide; VAR totalBytes: UnsignedWide): OSErr; FUNCTION CheckVolLock (pathname: StringPtr; vRefNum: Integer): OSErr; FUNCTION GetDriverName (driverRefNum: Integer; VAR driverName: Str255): OSErr; FUNCTION FindDrive (pathname: StringPtr; vRefNum: Integer; VAR driveQElementPtr: DrvQElPtr): OSErr; FUNCTION GetVolFileSystemID (pathname: StringPtr; vRefNum: Integer; VAR fileSystemID: Integer): OSErr; FUNCTION GetVolState (pathname: StringPtr; vRefNum: Integer; VAR volumeOnline: Boolean; VAR volumeEjected: Boolean; VAR driveEjectable: Boolean; VAR driverWantsEject: Boolean): OSErr; FUNCTION UnmountAndEject (pathname: StringPtr; vRefNum: Integer): OSErr; FUNCTION OnLine (volumes: FSSpecPtr; reqVolCount: Integer; VAR actVolCount: Integer; VAR volIndex: Integer): OSErr; FUNCTION SetDefault (newVRefNum: Integer; newDirID: LongInt; VAR oldVRefNum: Integer; VAR oldDirID: LongInt): OSErr; FUNCTION RestoreDefault (oldVRefNum: Integer; oldDirID: LongInt): OSErr; FUNCTION GetDInfo (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR fndrInfo: DInfo): OSErr; FUNCTION FSpGetDInfo ({CONST} VAR spec: FSSpec; VAR fndrInfo: DInfo): OSErr; FUNCTION SetDInfo (vRefNum: Integer; dirID: LongInt; name: StringPtr; fndrInfo: DInfo): OSErr; FUNCTION FSpSetDInfo ({CONST} VAR spec: FSSpec; fndrInfo: DInfo): OSErr; FUNCTION GetDirectoryID (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR theDirID: LongInt; VAR isDirectory: Boolean): OSErr; FUNCTION FSpGetDirectoryID ({CONST} VAR spec: FSSpec; VAR theDirID: LongInt; VAR isDirectory: Boolean): OSErr; FUNCTION GetDirName (vRefNum: Integer; dirID: LongInt; VAR name: Str31): OSErr; FUNCTION GetIOACUser (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR ioACUser: SInt8): OSErr; FUNCTION FSpGetIOACUser (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR ioACUser: SInt8): OSErr; FUNCTION GetParentID (vRefNum: Integer; dirID: LongInt; name: StringPtr; VAR parID: LongInt): OSErr; FUNCTION GetFilenameFromPathname (pathname: Str255; VAR filename: Str255): OSErr; FUNCTION GetObjectLocation (vRefNum: Integer; dirID: LongInt; pathname: StringPtr; VAR realVRefNum: Integer; VAR realParID: LongInt; VAR realName: Str255; VAR isDirectory: Boolean): OSErr; FUNCTION GetDirItems (vRefNum: Integer; dirID: LongInt; name: StringPtr; getFiles: Boolean; getDirectories: Boolean; items: FSSpecPtr; reqItemCount: Integer; VAR actItemCount: Integer; VAR itemIndex: Integer): OSErr; FUNCTION DeleteDirectoryContents (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION DeleteDirectory (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION CheckObjectLock (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpCheckObjectLock ({CONST} VAR spec: FSSpec): OSErr; FUNCTION GetFileSize (vRefNum: Integer; dirID: LongInt; fileName: Str255; VAR dataSize: LONGINT; VAR rsrcSize: LONGINT): OSErr; FUNCTION FSpGetFileSize ({CONST} VAR spec: FSSpec; VAR dataSize: LONGINT; VAR rsrcSize: LONGINT): OSErr; FUNCTION BumpDate (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpBumpDate ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ChangeCreatorType (vRefNum: Integer; dirID: LongInt; name: Str255; creator: OSType; fileType: OSType): OSErr; FUNCTION FSpChangeCreatorType ({CONST} VAR spec: FSSpec; creator: OSType; fileType: OSType): OSErr; FUNCTION ChangeFDFlags (vRefNum: Integer; dirID: LongInt; name: StringPtr; setBits: Boolean; flagBits: Integer): OSErr; FUNCTION FSpChangeFDFlags ({CONST} VAR spec: FSSpec; setBits: Boolean; flagBits: Integer): OSErr; FUNCTION SetIsInvisible (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpSetIsInvisible ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ClearIsInvisible (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpClearIsInvisible ({CONST} VAR spec: FSSpec): OSErr; FUNCTION SetNameLocked (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpSetNameLocked ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ClearNameLocked (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpClearNameLocked ({CONST} VAR spec: FSSpec): OSErr; FUNCTION SetIsStationery (vRefNum: Integer; dirID: LongInt; name: Str255): OSErr; FUNCTION FSpSetIsStationery ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ClearIsStationery (vRefNum: Integer; dirID: LongInt; name: Str255): OSErr; FUNCTION FSpClearIsStationery ({CONST} VAR spec: FSSpec): OSErr; FUNCTION SetHasCustomIcon (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpSetHasCustomIcon ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ClearHasCustomIcon (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpClearHasCustomIcon ({CONST} VAR spec: FSSpec): OSErr; FUNCTION ClearHasBeenInited (vRefNum: Integer; dirID: LongInt; name: StringPtr): OSErr; FUNCTION FSpClearHasBeenInited ({CONST} VAR spec: FSSpec): OSErr; FUNCTION CopyFileMgrAttributes (srcVRefNum: Integer; srcDirID: LongInt; srcName: StringPtr; dstVRefNum: Integer; dstDirID: LongInt; dstName: StringPtr; copyLockBit: Boolean): OSErr; FUNCTION FSpCopyFileMgrAttributes ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyLockBit: Boolean): OSErr; FUNCTION HOpenAware (vRefNum: Integer; dirID: LongInt; fileName: Str255; denyModes: Integer; VAR refNum: Integer): OSErr; FUNCTION FSpOpenAware ({CONST} VAR spec: FSSpec; denyModes: Integer; VAR refNum: Integer): OSErr; FUNCTION HOpenRFAware (vRefNum: Integer; dirID: LongInt; fileName: Str255; denyModes: Integer; VAR refNum: Integer): OSErr; FUNCTION FSpOpenRFAware ({CONST} VAR spec: FSSpec; denyModes: Integer; VAR refNum: Integer): OSErr; FUNCTION FSReadNoCache (refNum: Integer; VAR count: LongInt; buffPtr: Ptr): OSErr; FUNCTION FSWriteNoCache (refNum: Integer; VAR count: LongInt; buffPtr: Ptr): OSErr; FUNCTION FSWriteVerify (refNum: Integer; VAR count: LongInt; buffPtr: Ptr): OSErr; FUNCTION CopyFork (srcRefNum: Integer; dstRefNum: Integer; copyBufferPtr: Ptr; copyBufferSize: LongInt): OSErr; FUNCTION GetFileLocation (refNum: Integer; VAR vRefNum: Integer; VAR dirID: LongInt; fileName: StringPtr): OSErr; FUNCTION FSpGetFileLocation (refNum: Integer; VAR spec: FSSpec): OSErr; FUNCTION CopyDirectoryAccess (srcVRefNum: Integer; srcDirID: LongInt; srcName: StringPtr; dstVRefNum: Integer; dstDirID: LongInt; dstName: StringPtr): OSErr; FUNCTION FSpCopyDirectoryAccess ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec): OSErr; FUNCTION HMoveRenameCompat (vRefNum: Integer; srcDirID: LongInt; srcName: Str255; dstDirID: LongInt; dstpathName: StringPtr; copyName: StringPtr): OSErr; FUNCTION FSpMoveRenameCompat ({CONST} VAR srcSpec: FSSpec; {CONST} VAR dstSpec: FSSpec; copyName: StringPtr): OSErr; FUNCTION BuildAFPVolMountInfo (flags: Integer; nbpInterval: SignedByte; nbpCount: SignedByte; uamType: Integer; zoneName: Str32; serverName: Str32; volName: Str27; userName: Str31; userPassword: Str8; volPassword: Str8; VAR afpInfoPtr: MyAFPVolMountInfoPtr): OSErr; FUNCTION RetrieveAFPVolMountInfo (afpInfoPtr: AFPVolMountInfoPtr; VAR flags: Integer; VAR uamType: Integer; zoneName: StringPtr; serverName: StringPtr; volName: StringPtr; userName: StringPtr): OSErr; FUNCTION BuildAFPXVolMountInfo (flags: Integer; nbpInterval: SignedByte; nbpCount: SignedByte; uamType: Integer; zoneName: Str32; serverName: Str32; volName: Str27; userName: Str31; userPassword: Str8; volPassword: Str8; uamName: Str32; alternateAddressLength: LongInt; alternateAddress: Ptr; VAR afpXInfoPtr: AFPXVolMountInfoPtr): OSErr; FUNCTION RetrieveAFPXVolMountInfo(afpXInfoPtr: AFPXVolMountInfoPtr; VAR flags: Integer; VAR uamType: Integer; zoneName: StringPtr; serverName: StringPtr; volName: StringPtr; userName: StringPtr; uamName: StringPtr; VAR alternateAddressLength: LongInt; VAR alternateAddress: AFPAlternateAddressPtr): OSErr; FUNCTION GetUGEntries (objType: Integer; entries: UGEntryPtr; reqEntryCount: LongInt; VAR actEntryCount: LongInt; VAR objID: LongInt): OSErr; {***************************************************************************} IMPLEMENTATION { Functions to get information out of GetVolParmsInfoBuffer. } FUNCTION GetVolParmsInfoVersion(VAR volParms: GetVolParmsInfoBuffer): INTEGER; BEGIN GetVolParmsInfoVersion := volParms.vMVersion; END; FUNCTION GetVolParmsInfoAttrib(VAR volParms: GetVolParmsInfoBuffer): LONGINT; BEGIN GetVolParmsInfoAttrib := volParms.vMAttrib; END; FUNCTION GetVolParmsInfoLocalHand(VAR volParms: GetVolParmsInfoBuffer): Handle; BEGIN GetVolParmsInfoLocalHand := volParms.vMLocalHand; END; FUNCTION GetVolParmsInfoServerAdr(VAR volParms: GetVolParmsInfoBuffer): LONGINT; BEGIN GetVolParmsInfoServerAdr := volParms.vMServerAdr; END; FUNCTION GetVolParmsInfoVolumeGrade(VAR volParms: GetVolParmsInfoBuffer): LONGINT; BEGIN IF volParms.vMVersion >= 2 THEN GetVolParmsInfoVolumeGrade := volParms.vMVolumeGrade ELSE GetVolParmsInfoVolumeGrade := 0; END; FUNCTION GetVolParmsInfoForeignPrivID(VAR volParms: GetVolParmsInfoBuffer): INTEGER; BEGIN IF volParms.vMVersion >= 2 THEN GetVolParmsInfoForeignPrivID := volParms.vMForeignPrivID ELSE GetVolParmsInfoForeignPrivID := 0; END; FUNCTION GetVolParmsInfoExtendedAttributes(VAR volParms: GetVolParmsInfoBuffer): LONGINT; BEGIN IF volParms.vMVersion >= 3 THEN GetVolParmsInfoExtendedAttributes := volParms.vMExtendedAttributes ELSE GetVolParmsInfoExtendedAttributes := 0; END; FUNCTION isNetworkVolume (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN isNetworkVolume := (volParms.vMServerAdr <> 0); END; FUNCTION hasLimitFCBs (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasLimitFCBs := BTST(volParms.vMAttrib, bLimitFCBs); END; FUNCTION hasLocalWList (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasLocalWList := BTST(volParms.vMAttrib, bLocalWList); END; FUNCTION hasNoMiniFndr (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoMiniFndr := BTST(volParms.vMAttrib, bNoMiniFndr); END; FUNCTION hasNoVNEdit (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoVNEdit := BTST(volParms.vMAttrib, bNoVNEdit); END; FUNCTION hasNoLclSync (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoLclSync := BTST(volParms.vMAttrib, bNoLclSync); END; FUNCTION hasTrshOffLine (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasTrshOffLine := BTST(volParms.vMAttrib, bTrshOffLine); END; FUNCTION hasNoSwitchTo (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoSwitchTo := BTST(volParms.vMAttrib, bNoSwitchTo); END; FUNCTION hasNoDeskItems (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoDeskItems := BTST(volParms.vMAttrib, bNoDeskItems); END; FUNCTION hasNoBootBlks (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoBootBlks := BTST(volParms.vMAttrib, bNoBootBlks); END; FUNCTION hasAccessCntl (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasAccessCntl := BTST(volParms.vMAttrib, bAccessCntl); END; FUNCTION hasNoSysDir (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasNoSysDir := BTST(volParms.vMAttrib, bNoSysDir); END; FUNCTION hasExtFSVol (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasExtFSVol := BTST(volParms.vMAttrib, bHasExtFSVol); END; FUNCTION hasOpenDeny (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasOpenDeny := BTST(volParms.vMAttrib, bHasOpenDeny); END; FUNCTION hasCopyFile (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasCopyFile := BTST(volParms.vMAttrib, bHasCopyFile); END; FUNCTION hasMoveRename (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasMoveRename := BTST(volParms.vMAttrib, bHasMoveRename); END; FUNCTION hasDesktopMgr (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasDesktopMgr := BTST(volParms.vMAttrib, bHasDesktopMgr); END; FUNCTION hasShortName (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasShortName := BTST(volParms.vMAttrib, bHasShortName); END; FUNCTION hasFolderLock (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasFolderLock := BTST(volParms.vMAttrib, bHasFolderLock); END; FUNCTION hasPersonalAccessPrivileges (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasPersonalAccessPrivileges := BTST(volParms.vMAttrib, bHasPersonalAccessPrivileges); END; FUNCTION hasUserGroupList (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasUserGroupList := BTST(volParms.vMAttrib, bHasUserGroupList); END; FUNCTION hasCatSearch (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasCatSearch := BTST(volParms.vMAttrib, bHasCatSearch); END; FUNCTION hasFileIDs (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasFileIDs := BTST(volParms.vMAttrib, bHasFileIDs); END; FUNCTION hasBTreeMgr (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasBTreeMgr := BTST(volParms.vMAttrib, bHasBTreeMgr); END; FUNCTION hasBlankAccessPrivileges (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN hasBlankAccessPrivileges := BTST(volParms.vMAttrib, bHasBlankAccessPrivileges); END; FUNCTION supportsAsyncRequests (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN supportsAsyncRequests := BTST(volParms.vMAttrib, bSupportsAsyncRequests); END; FUNCTION supportsTrashVolumeCache (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN supportsTrashVolumeCache := BTST(volParms.vMAttrib, bSupportsTrashVolumeCache); END; FUNCTION volIsEjectable (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volIsEjectable := BTST(GetVolParmsInfoExtendedAttributes(volParms), bIsEjectable); END; FUNCTION volSupportsHFSPlusAPIs (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsHFSPlusAPIs := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsHFSPlusAPIs); END; FUNCTION volSupportsFSCatalogSearch (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsFSCatalogSearch := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsFSCatalogSearch); END; FUNCTION volSupportsFSExchangeObjects (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsFSExchangeObjects := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsFSExchangeObjects); END; FUNCTION volSupports2TBFiles (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupports2TBFiles := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupports2TBFiles); END; FUNCTION volSupportsLongNames (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsLongNames := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsLongNames); END; FUNCTION volSupportsMultiScriptNames (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsMultiScriptNames := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsMultiScriptNames); END; FUNCTION volSupportsNamedForks (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsNamedForks := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsNamedForks); END; FUNCTION volSupportsSubtreeIterators (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volSupportsSubtreeIterators := BTST(GetVolParmsInfoExtendedAttributes(volParms), bSupportsSubtreeIterators); END; FUNCTION volL2PCanMapFileBlocks (VAR volParms: GetVolParmsInfoBuffer): Boolean; BEGIN volL2PCanMapFileBlocks := BTST(GetVolParmsInfoExtendedAttributes(volParms), bL2PCanMapFileBlocks); END; { Functions for testing ioACUser bits. } FUNCTION userIsOwner (ioACUser: SInt8): Boolean; BEGIN userIsOwner := NOT (BTST(ioACUser, kioACUserNotOwnerMask)); END; FUNCTION userHasFullAccess (ioACUser: SInt8): Boolean; BEGIN userHasFullAccess := BAND(ioACUser, acUserAccessMask) = acUserFull; END; FUNCTION userHasDropBoxAccess (ioACUser: SInt8): Boolean; BEGIN userHasDropBoxAccess := BAND(ioACUser, acUserAccessMask) = acUserDropBox; END; FUNCTION userHasBulletinBoard (ioACUser: SInt8): Boolean; BEGIN userHasBulletinBoard := BAND(ioACUser, acUserAccessMask) = acUserBulletinBoard; END; FUNCTION userHasNoAccess (ioACUser: SInt8): Boolean; BEGIN userHasNoAccess := BAND(ioACUser, acUserAccessMask) = acUserNone; END; END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/PascalInterfaces/Search.p ================================================ UNIT Search; { Apple Macintosh Developer Technical Support } { } { IndexedSearch and the PBCatSearch compatibility function. } { by Jim Luther, Apple Developer Technical Support Emeritus } { } { File: Search.p } { } { Copyright 1992-1999 Apple Computer, Inc. } { All rights reserved. } { } { You may incorporate this sample code into your applications without } { restriction, though the sample code has been provided "AS IS" and the } { responsibility for its operation is 100% yours. However, what you are } { not permitted to do is to redistribute the source as "DSC Sample Code" } { after having made changes. If you're going to re-distribute the source, } { we require that you make it clear in the source that the code was } { descended from Apple Sample Code, but that you've made changes. } INTERFACE USES Types, Files; {***************************************************************************} FUNCTION IndexedSearch (pb: HParmBlkPtr; dirID: LongInt): OSErr; FUNCTION PBCatSearchSyncCompat (paramBlock: HParmBlkPtr): OSErr; FUNCTION NameFileSearch (volName: StringPtr; vRefNum: Integer; fileName: Str255; matches: FSSpecPtr; reqMatchCount: LongInt; VAR actMatchCount: LongInt; newSearch: Boolean; partial: Boolean): OSErr; FUNCTION CreatorTypeFileSearch (volName: StringPtr; vRefNum: Integer; creator: OSType; fileType: OSType; matches: FSSpecPtr; reqMatchCount: LongInt; VAR actMatchCount: LongInt; newSearch: Boolean): OSErr; {***************************************************************************} IMPLEMENTATION END. ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/DirectoryCopy.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** DirectoryCopy: A robust, general purpose directory copy routine. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: DirectoryCopy.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "MoreDesktopMgr.h" #include "FileCopy.h" #include "DirectoryCopy.h" /*****************************************************************************/ /* local constants */ enum { dirCopyBigCopyBuffSize = 0x00004000, dirCopyMinCopyBuffSize = 0x00000200 }; /*****************************************************************************/ /* local data structures */ /* The EnumerateGlobals structure is used to minimize the amount of ** stack space used when recursively calling CopyLevel and to hold ** global information that might be needed at any time. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct EnumerateGlobals { Ptr copyBuffer; /* pointer to buffer used for file copy operations */ long bufferSize; /* the size of the copy buffer */ CopyErrProcPtr errorHandler; /* pointer to error handling function */ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */ OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */ Boolean bailout; /* set to true to by error handling function if fatal error */ short destinationVRefNum; /* the destination vRefNum */ Str63 itemName; /* the name of the current item */ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif typedef struct EnumerateGlobals EnumerateGlobals; typedef EnumerateGlobals *EnumerateGlobalsPtr; /* The PreflightGlobals structure is used to minimize the amount of ** stack space used when recursively calling GetLevelSize and to hold ** global information that might be needed at any time. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct PreflightGlobals { OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */ Str63 itemName; /* the name of the current item */ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */ unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */ unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */ unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif typedef struct PreflightGlobals PreflightGlobals; typedef PreflightGlobals *PreflightGlobalsPtr; /*****************************************************************************/ /* static prototypes */ static void GetLevelSize(long currentDirID, PreflightGlobals *theGlobals); static OSErr PreflightDirectoryCopySpace(short srcVRefNum, long srcDirID, short dstVRefNum, CopyFilterProcPtr copyFilterProc, Boolean *spaceOK); static void CopyLevel(long sourceDirID, long dstDirID, EnumerateGlobals *theGlobals); /*****************************************************************************/ static void GetLevelSize(long currentDirID, PreflightGlobals *theGlobals) { short index = 1; do { theGlobals->myCPB.dirInfo.ioFDirIndex = index; theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */ /* through, since GetCatInfo */ /* returns ioFlNum in this field */ theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB); if ( theGlobals->result == noErr ) { if ( (theGlobals->copyFilterProc == NULL) || CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */ { /* Either there's no filter proc OR the filter proc says to use this item */ if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* we have a directory */ GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */ theGlobals->result = noErr; /* clear error return on way back */ } else { /* We have a file - add its allocation blocks to allocBlksNeeded. */ /* Since space on Mac OS disks is always allocated in allocation blocks, */ /* this takes into account rounding up to the end of an allocation block. */ /* get number of 512-byte blocks needed for data fork */ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 ) { theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1; } else { theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9; } /* now, calculate number of new allocation blocks needed for the data fork and add it to the total */ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk ) { theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1; } else { theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk; } /* get number of 512-byte blocks needed for resource fork */ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 ) { theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1; } else { theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9; } /* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk ) { theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1; } else { theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk; } } } } ++index; } while ( theGlobals->result == noErr ); } /*****************************************************************************/ static OSErr PreflightDirectoryCopySpace(short srcVRefNum, long srcDirID, short dstVRefNum, CopyFilterProcPtr copyFilterProc, Boolean *spaceOK) { XVolumeParam pb; OSErr error; unsigned long dstFreeBlocks; PreflightGlobals theGlobals; error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb); if ( error == noErr ) { /* Convert freeBytes to free disk blocks (512-byte blocks) */ dstFreeBlocks = U32SetU(U64ShiftRight(pb.ioVFreeBytes, 9)); /* get allocation block size (always multiple of 512) and divide by 512 to get number of 512-byte blocks per allocation block */ theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9); theGlobals.allocBlksNeeded = 0; theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName; theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum; theGlobals.copyFilterProc = copyFilterProc; GetLevelSize(srcDirID, &theGlobals); /* Is there enough room on the destination volume for the source file? */ /* Note: This will work because the largest number of disk blocks supported */ /* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */ /* will always be less than 0xffffffff. */ *spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks); } return ( error ); } /*****************************************************************************/ static void CopyLevel(long sourceDirID, long dstDirID, EnumerateGlobals *theGlobals) { long currentSrcDirID; long newDirID; short index = 1; do { /* Get next source item at the current directory level */ theGlobals->myCPB.dirInfo.ioFDirIndex = index; theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID; theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB); if ( theGlobals->error == noErr ) { if ( (theGlobals->copyFilterProc == NULL) || CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */ { /* Either there's no filter proc OR the filter proc says to use this item */ /* We have an item. Is it a file or directory? */ if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* We have a directory */ /* Create a new directory at the destination. No errors allowed! */ theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID); if ( theGlobals->error == noErr ) { /* Save the current source directory ID where we can get it when we come back ** from recursion land. */ currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID; /* Dive again (copy the directory level we just found below this one) */ CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals); if ( !theGlobals->bailout ) { /* Copy comment from old to new directory. */ /* Ignore the result because we really don't care if it worked or not. */ (void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL); /* Copy directory attributes (dates, etc.) to newDirID. */ /* No errors allowed */ theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true); /* handle any errors from CopyFileMgrAttributes */ if ( theGlobals->error != noErr ) { if ( theGlobals->errorHandler != NULL ) { theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp, theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL); } else { /* If you don't handle the errors with an error handler, */ /* then the copy stops here. */ theGlobals->bailout = true; } } } } else /* error handling for DirCreate */ { if ( theGlobals->errorHandler != NULL ) { theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp, theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName); } else { /* If you don't handle the errors with an error handler, */ /* then the copy stops here. */ theGlobals->bailout = true; } } if ( !theGlobals->bailout ) { /* clear error return on way back if we aren't bailing out */ theGlobals->error = noErr; } } else { /* We have a file, so copy it */ theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName, theGlobals->destinationVRefNum, dstDirID, NULL, NULL, theGlobals->copyBuffer, theGlobals->bufferSize, false); /* handle any errors from FileCopy */ if ( theGlobals->error != noErr ) { if ( theGlobals->errorHandler != NULL ) { theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp, theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName, theGlobals->destinationVRefNum, dstDirID, NULL); if ( !theGlobals->bailout ) { /* If the CopyErrProc handled the problem, clear the error here */ theGlobals->error = noErr; } } else { /* If you don't handle the errors with an error handler, */ /* then the copy stops here. */ theGlobals->bailout = true; } } } } } else { /* error handling for PBGetCatInfo */ /* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */ if ( theGlobals->error != fnfErr ) { if ( theGlobals->errorHandler != NULL ) { theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp, theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL); if ( !theGlobals->bailout ) { /* If the CopyErrProc handled the problem, clear the error here */ theGlobals->error = noErr; } } else { /* If you don't handle the errors with an error handler, */ /* then the copy stops here. */ theGlobals->bailout = true; } } } ++index; /* prepare to get next item */ } while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */ } /*****************************************************************************/ pascal OSErr FilteredDirectoryCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler, CopyFilterProcPtr copyFilterProc) { EnumerateGlobals theGlobals; Boolean isDirectory; OSErr error; Boolean ourCopyBuffer = false; Str63 srcDirName, oldDiskName; Boolean spaceOK; /* Make sure a copy buffer is allocated. */ if ( copyBufferPtr == NULL ) { /* The caller didn't supply a copy buffer so grab one from the application heap. ** Try to get a big copy buffer, if we can't, try for a 512-byte buffer. ** If 512 bytes aren't available, we're in trouble. */ copyBufferSize = dirCopyBigCopyBuffSize; copyBufferPtr = NewPtr(copyBufferSize); if ( copyBufferPtr == NULL ) { copyBufferSize = dirCopyMinCopyBuffSize; copyBufferPtr = NewPtr(copyBufferSize); if ( copyBufferPtr == NULL ) { return ( memFullErr ); } } ourCopyBuffer = true; } /* Get the real dirID where we're copying from and make sure it is a directory. */ error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory); if ( error != noErr ) { goto ErrorExit; } if ( !isDirectory ) { error = dirNFErr; goto ErrorExit; } /* Special case destination if it is the root parent directory. */ /* Since you can't create the root directory, this is needed if */ /* you want to copy a directory's content to a disk's root directory. */ if ( (dstDirID == fsRtParID) && (dstName == NULL) ) { dstDirID = fsRtParID; isDirectory = true; error = noErr; } else { /* Get the real dirID where we're going to put the copy and make sure it is a directory. */ error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory); if ( error != noErr ) { goto ErrorExit; } if ( !isDirectory ) { error = dirNFErr; goto ErrorExit; } } /* Get the real vRefNum of both the source and destination */ error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum); if ( error != noErr ) { goto ErrorExit; } error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum); if ( error != noErr ) { goto ErrorExit; } if ( preflight ) { error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK); if ( error != noErr ) { goto ErrorExit; } if ( !spaceOK ) { error = dskFulErr; /* not enough room on destination */ goto ErrorExit; } } /* Create the new directory in the destination directory with the */ /* same name as the source directory. */ error = GetDirName(srcVRefNum, srcDirID, srcDirName); if ( error != noErr ) { goto ErrorExit; } /* Again, special case destination if the destination is the */ /* root parent directory. This time, we'll rename the disk to */ /* the source directory name. */ if ( dstDirID == fsRtParID ) { /* Get the current name of the destination disk */ error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName); if ( error == noErr ) { /* use the copyName as srcDirName if supplied */ if ( copyName != NULL ) { /* make a copy since copyName is a const input */ BlockMoveData(copyName, srcDirName, sizeof(Str31)); } /* Shorten the name if it's too long to be the volume name */ TruncPString(srcDirName, srcDirName, 27); /* Rename the disk */ error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName); /* and copy to the root directory */ dstDirID = fsRtDirID; } } else { /* use the copyName as srcDirName if supplied */ error = DirCreate(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : srcDirName), &dstDirID); } if ( error != noErr ) { /* handle any errors from DirCreate */ if ( copyErrHandler != NULL ) { if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp, srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, srcDirName) ) { goto ErrorExit; } else { Boolean isDirectory;// JMM for Squeak /* If the CopyErrProc handled the problem, clear the error here */ /* and continue */ GetDirectoryID(dstVRefNum, dstDirID, ((copyName != NULL) ? copyName : srcDirName), &dstDirID, &isDirectory); error = noErr; } } else { /* If you don't handle the errors with an error handler, */ /* then the copy stops here. */ goto ErrorExit; } } /* dstDirID is now the newly created directory! */ /* Set up the globals we need to access from the recursive routine. */ theGlobals.copyBuffer = (Ptr)copyBufferPtr; theGlobals.bufferSize = copyBufferSize; theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */ theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName; theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum; theGlobals.errorHandler = copyErrHandler; theGlobals.bailout = false; theGlobals.copyFilterProc = copyFilterProc; /* Here we go into recursion land... */ CopyLevel(srcDirID, dstDirID, &theGlobals); error = theGlobals.error; /* get the result */ if ( !theGlobals.bailout ) { /* Copy comment from source to destination directory. */ /* Ignore the result because we really don't care if it worked or not. */ (void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL); /* Copy the File Manager attributes */ error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL, true); /* handle any errors from CopyFileMgrAttributes */ if ( (error != noErr) && (copyErrHandler != NULL) ) { theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp, srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL); } } ErrorExit: /* Get rid of the copy buffer if we allocated it. */ if ( ourCopyBuffer ) { DisposePtr((Ptr)copyBufferPtr); } return ( error ); } /*****************************************************************************/ pascal OSErr DirectoryCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler) { return ( FilteredDirectoryCopy(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName, copyName, copyBufferPtr, copyBufferSize, preflight, copyErrHandler, NULL) ); } /*****************************************************************************/ pascal OSErr FSpFilteredDirectoryCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler, CopyFilterProcPtr copyFilterProc) { return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name, copyName, copyBufferPtr, copyBufferSize, preflight, copyErrHandler, copyFilterProc) ); } /*****************************************************************************/ pascal OSErr FSpDirectoryCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight, CopyErrProcPtr copyErrHandler) { return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name, copyName, copyBufferPtr, copyBufferSize, preflight, copyErrHandler, NULL) ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/FSpCompat.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** FSSpec compatibility functions. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FSpCompat.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ /* ** If building application 68K code, set GENERATENODATA to 0 for faster code. ** If building stand-alone 68K code, set GENERATENODATA to 1 so globals ** (static variables) are not used. */ #ifndef GENERATENODATA #define GENERATENODATA 0 #endif #if 0 #include #include #include #include #include #include #endif 0 #define __COMPILINGMOREFILES #include "MoreFilesExtras.h" #include "FSpCompat.h" /*****************************************************************************/ /* local constants */ enum { gestaltBugFixAttrsTwo = 'bugy', gestaltFSpExchangeFilesCompatibilityFix = 26, gestaltBugFixAttrsThree = 'bugx', gestaltFSpCreateScriptSupportFix = 1 }; /*****************************************************************************/ /* static prototypes */ #if !__MACOSSEVENORLATER static Boolean FSHasFSSpecCalls(void); static Boolean QTHasFSSpecCalls(void); #endif /* !__MACOSSEVENORLATER */ #if !__MACOSSEVENFIVEORLATER static Boolean HasFSpExchangeFilesCompatibilityFix(void); static OSErr GenerateUniqueName(short volume, long *startSeed, long dir1, long dir2, StringPtr uniqueName); #endif /* !__MACOSSEVENFIVEORLATER */ #if !__MACOSSEVENFIVEONEORLATER static Boolean HasFSpCreateScriptSupportFix(void); #endif /* !__MACOSSEVENFIVEONEORLATER */ /*****************************************************************************/ /* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */ #if !__MACOSSEVENORLATER static Boolean FSHasFSSpecCalls(void) { long response; #if !GENERATENODATA static Boolean tested = false; static Boolean result = false; #else Boolean result = false; #endif #if !GENERATENODATA if ( !tested ) { tested = true; #endif if ( Gestalt(gestaltFSAttr, &response) == noErr ) { result = ((response & (1L << gestaltHasFSSpecCalls)) != 0); } #if !GENERATENODATA } #endif return ( result ); } #endif /* !__MACOSSEVENORLATER */ /*****************************************************************************/ /* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */ /* except for FSpExchangeFiles. */ #if !__MACOSSEVENORLATER static Boolean QTHasFSSpecCalls(void) { long response; #if !GENERATENODATA static Boolean tested = false; static Boolean result = false; #else Boolean result = false; #endif #if !GENERATENODATA if ( !tested ) { tested = true; #endif result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr); #if !GENERATENODATA } #endif return ( result ); } #endif /* !__MACOSSEVENORLATER */ /*****************************************************************************/ /* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */ /* compatibility code has been fixed in system software. */ /* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */ /* is true, then we know the fix is in. */ #if !__MACOSSEVENFIVEORLATER static Boolean HasFSpExchangeFilesCompatibilityFix(void) { long response; #if !GENERATENODATA static Boolean tested = false; static Boolean result = false; #else /* !GENERATENODATA */ Boolean result = false; #endif /* !GENERATENODATA */ #if !GENERATENODATA if ( !tested ) { tested = true; #endif /* !GENERATENODATA */ if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr ) { result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0); } #if !GENERATENODATA } #endif /* !GENERATENODATA */ return ( result ); } #endif /* !__MACOSSEVENFIVEORLATER */ /*****************************************************************************/ /* HasFSpCreateScriptSupportFix returns true if FSpCreate and */ /* FSpCreateResFile have been fixed in system software to correctly set */ /* the scriptCode in the volume's catalog. */ /* This was fixed by System 7.5 Update 1.0 */ #if !__MACOSSEVENFIVEONEORLATER static Boolean HasFSpCreateScriptSupportFix(void) { long response; #if !GENERATENODATA static Boolean tested = false; static Boolean result = false; #else Boolean result = false; #endif /* !GENERATENODATA */ #if !GENERATENODATA if ( !tested ) { tested = true; #endif /* !GENERATENODATA */ if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr ) { result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0); } #if !GENERATENODATA } #endif /* !GENERATENODATA */ return ( result ); } #endif /* !__MACOSSEVENFIVEONEORLATER */ /*****************************************************************************/ /* ** File Manager FSp calls */ /*****************************************************************************/ pascal OSErr FSMakeFSSpecCompat(short vRefNum, long dirID, ConstStr255Param fileName, FSSpec *spec) { OSErr result; #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { Boolean isDirectory; result = GetObjectLocation(vRefNum, dirID, fileName, &(spec->vRefNum), &(spec->parID), spec->name, &isDirectory); } else #endif /* !__MACOSSEVENORLATER */ { /* Let the file system create the FSSpec if it can since it does the job */ /* much more efficiently than I can. */ result = FSMakeFSSpec(vRefNum, dirID, fileName, spec); /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */ /* returned in the parID field when making an FSSpec to the volume's */ /* root directory by passing a full pathname in MakeFSSpec's */ /* fileName parameter. Fixed in Mac OS 8.1 */ if ( (result == noErr) && (spec->parID == 0) ) spec->parID = fsRtParID; } return ( result ); } /*****************************************************************************/ pascal OSErr FSpOpenDFCompat(const FSSpec *spec, char permission, short *refNum) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { OSErr result; HParamBlockRec pb; pb.ioParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); pb.ioParam.ioVersNum = 0; pb.ioParam.ioPermssn = permission; pb.ioParam.ioMisc = NULL; result = PBHOpenSync(&pb); /* OpenDF not supported by System 6, so use Open */ *refNum = pb.ioParam.ioRefNum; return ( result ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpOpenDF(spec, permission, refNum) ); } } /*****************************************************************************/ pascal OSErr FSpOpenRFCompat(const FSSpec *spec, char permission, short *refNum) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { OSErr result; HParamBlockRec pb; pb.ioParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); pb.ioParam.ioVersNum = 0; pb.ioParam.ioPermssn = permission; pb.ioParam.ioMisc = NULL; result = PBHOpenRFSync(&pb); *refNum = pb.ioParam.ioRefNum; return ( result ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpOpenRF(spec, permission, refNum) ); } } /*****************************************************************************/ pascal OSErr FSpCreateCompat(const FSSpec *spec, OSType creator, OSType fileType, ScriptCode scriptTag) { #if !__MACOSSEVENFIVEONEORLATER OSErr result; UniversalFMPB pb; if ( #if !__MACOSSEVENORLATER (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) || #endif /* !__MACOSSEVENORLATER */ !HasFSpCreateScriptSupportFix() ) { /* If FSpCreate isn't called, this code will be executed */ pb.hPB.fileParam.ioVRefNum = spec->vRefNum; pb.hPB.fileParam.ioDirID = spec->parID; pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name); pb.hPB.fileParam.ioFVersNum = 0; result = PBHCreateSync(&(pb.hPB)); if ( result == noErr ) { /* get info on created item */ pb.ciPB.hFileInfo.ioFDirIndex = 0; result = PBGetCatInfoSync(&(pb.ciPB)); if ( result == noErr ) { /* Set fdScript in FXInfo */ /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */ pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ? ((char)scriptTag | (char)0x80) : (smRoman); /* Set creator/fileType */ pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator; pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType; /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ pb.ciPB.hFileInfo.ioDirID = spec->parID; result = PBSetCatInfoSync(&(pb.ciPB)); } } return ( result ); } else #endif /* !__MACOSSEVENFIVEONEORLATER */ { return ( FSpCreate(spec, creator, fileType, scriptTag) ); } } /*****************************************************************************/ pascal OSErr FSpDirCreateCompat(const FSSpec *spec, ScriptCode scriptTag, long *createdDirID) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { OSErr result; UniversalFMPB pb; pb.hPB.fileParam.ioVRefNum = spec->vRefNum; pb.hPB.fileParam.ioDirID = spec->parID; pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name); result = PBDirCreateSync(&(pb.hPB)); *createdDirID = pb.hPB.fileParam.ioDirID; if ( result == noErr ) { /* get info on created item */ pb.ciPB.dirInfo.ioFDirIndex = 0; pb.ciPB.dirInfo.ioDrDirID = spec->parID; result = PBGetCatInfoSync(&(pb.ciPB)); if ( result == noErr ) { /* Set frScript in DXInfo */ /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ /* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */ pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ? ((char)scriptTag | (char)0x80) : (smRoman); /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ pb.ciPB.dirInfo.ioDrDirID = spec->parID; result = PBSetCatInfoSync(&(pb.ciPB)); } } return ( result ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpDirCreate(spec, scriptTag, createdDirID) ); } } /*****************************************************************************/ pascal OSErr FSpDeleteCompat(const FSSpec *spec) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { HParamBlockRec pb; pb.ioParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); pb.ioParam.ioVersNum = 0; return ( PBHDeleteSync(&pb) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpDelete(spec) ); } } /*****************************************************************************/ pascal OSErr FSpGetFInfoCompat(const FSSpec *spec, FInfo *fndrInfo) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { OSErr result; HParamBlockRec pb; pb.fileParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); pb.fileParam.ioFVersNum = 0; pb.fileParam.ioFDirIndex = 0; result = PBHGetFInfoSync(&pb); *fndrInfo = pb.fileParam.ioFlFndrInfo; return ( result ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpGetFInfo(spec, fndrInfo) ); } } /*****************************************************************************/ pascal OSErr FSpSetFInfoCompat(const FSSpec *spec, const FInfo *fndrInfo) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { OSErr result; HParamBlockRec pb; pb.fileParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); pb.fileParam.ioFVersNum = 0; pb.fileParam.ioFDirIndex = 0; result = PBHGetFInfoSync(&pb); if ( result == noErr ) { pb.fileParam.ioFlFndrInfo = *fndrInfo; pb.fileParam.ioDirID = spec->parID; result = PBHSetFInfoSync(&pb); } return ( result ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpSetFInfo(spec, fndrInfo) ); } } /*****************************************************************************/ pascal OSErr FSpSetFLockCompat(const FSSpec *spec) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { HParamBlockRec pb; pb.fileParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); pb.fileParam.ioFVersNum = 0; return ( PBHSetFLockSync(&pb) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpSetFLock(spec) ); } } /*****************************************************************************/ pascal OSErr FSpRstFLockCompat(const FSSpec *spec) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { HParamBlockRec pb; pb.fileParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.fileParam.ioNamePtr = (StringPtr) &(spec->name); pb.fileParam.ioFVersNum = 0; return ( PBHRstFLockSync(&pb) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpRstFLock(spec) ); } } /*****************************************************************************/ pascal OSErr FSpRenameCompat(const FSSpec *spec, ConstStr255Param newName) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { HParamBlockRec pb; pb.ioParam.ioVRefNum = spec->vRefNum; pb.fileParam.ioDirID = spec->parID; pb.ioParam.ioNamePtr = (StringPtr) &(spec->name); pb.ioParam.ioVersNum = 0; pb.ioParam.ioMisc = (Ptr) newName; return ( PBHRenameSync(&pb) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpRename(spec, newName) ); } } /*****************************************************************************/ pascal OSErr FSpCatMoveCompat(const FSSpec *source, const FSSpec *dest) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { CMovePBRec pb; /* source and destination volume must be the same */ if ( source->vRefNum != dest->vRefNum ) return ( paramErr ); pb.ioNamePtr = (StringPtr) &(source->name); pb.ioVRefNum = source->vRefNum; pb.ioDirID = source->parID; pb.ioNewDirID = dest->parID; pb.ioNewName = (StringPtr) &(dest->name); return ( PBCatMoveSync(&pb) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpCatMove(source, dest) ); } } /*****************************************************************************/ /* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */ /* on the specified volume. Ripped off from Feldman's code. */ #if !__MACOSSEVENFIVEORLATER static OSErr GenerateUniqueName(short volume, long *startSeed, long dir1, long dir2, StringPtr uniqueName) { OSErr error = noErr; long i; CInfoPBRec cinfo; unsigned char hexStr[16]; for ( i = 0; i < 16; ++i ) { if ( i < 10 ) { hexStr[i] = 0x30 + i; } else { hexStr[i] = 0x37 + i; } } cinfo.hFileInfo.ioVRefNum = volume; cinfo.hFileInfo.ioFDirIndex = 0; cinfo.hFileInfo.ioNamePtr = uniqueName; while ( error != fnfErr ) { (*startSeed)++; cinfo.hFileInfo.ioNamePtr[0] = 8; for ( i = 1; i <= 8; i++ ) { cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)]; } cinfo.hFileInfo.ioDirID = dir1; error = fnfErr; for ( i = 1; i <= 2; i++ ) { error = error & PBGetCatInfoSync(&cinfo); cinfo.hFileInfo.ioDirID = dir2; if ( (error != fnfErr) && (error != noErr) ) { return ( error ); } } } return ( noErr ); } #endif /* !__MACOSSEVENFIVEORLATER */ /*****************************************************************************/ pascal OSErr FSpExchangeFilesCompat(const FSSpec *source, const FSSpec *dest) { #if !__MACOSSEVENFIVEORLATER if ( #if !__MACOSSEVENORLATER !FSHasFSSpecCalls() || #endif /* !__MACOSSEVENORLATER */ !HasFSpExchangeFilesCompatibilityFix() ) { HParamBlockRec pb; CInfoPBRec catInfoSource, catInfoDest; OSErr result, result2; Str31 unique1, unique2; StringPtr unique1Ptr, unique2Ptr, swapola; GetVolParmsInfoBuffer volInfo; long theSeed, temp; /* Make sure the source and destination are on the same volume */ if ( source->vRefNum != dest->vRefNum ) { result = diffVolErr; goto errorExit3; } /* Try PBExchangeFiles first since it preserves the file ID reference */ pb.fidParam.ioNamePtr = (StringPtr) &(source->name); pb.fidParam.ioVRefNum = source->vRefNum; pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name); pb.fidParam.ioDestDirID = dest->parID; pb.fidParam.ioSrcDirID = source->parID; result = PBExchangeFilesSync(&pb); /* Note: The compatibility case won't work for files with *Btree control blocks. */ /* Right now the only *Btree files are created by the system. */ if ( result != noErr ) { pb.ioParam.ioNamePtr = NULL; pb.ioParam.ioBuffer = (Ptr) &volInfo; pb.ioParam.ioReqCount = sizeof(volInfo); result2 = PBHGetVolParmsSync(&pb); /* continue if volume has no fileID support (or no GetVolParms support) */ if ( (result2 == noErr) && hasFileIDs(volInfo) ) { goto errorExit3; } /* Get the catalog information for each file */ /* and make sure both files are *really* files */ catInfoSource.hFileInfo.ioVRefNum = source->vRefNum; catInfoSource.hFileInfo.ioFDirIndex = 0; catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name); catInfoSource.hFileInfo.ioDirID = source->parID; catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */ result = PBGetCatInfoSync(&catInfoSource); if ( result != noErr ) { goto errorExit3; } if ( (catInfoSource.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { result = notAFileErr; goto errorExit3; } catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum; catInfoDest.hFileInfo.ioFDirIndex = 0; catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name); catInfoDest.hFileInfo.ioDirID = dest->parID; catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */ result = PBGetCatInfoSync(&catInfoDest); if ( result != noErr ) { goto errorExit3; } if ( (catInfoDest.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { result = notAFileErr; goto errorExit3; } /* generate 2 filenames that are unique in both directories */ theSeed = 0x64666A6C; /* a fine unlikely filename */ unique1Ptr = (StringPtr)&unique1; unique2Ptr = (StringPtr)&unique2; result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr); if ( result != noErr ) { goto errorExit3; } GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr); if ( result != noErr ) { goto errorExit3; } /* rename source to unique1 */ pb.fileParam.ioNamePtr = (StringPtr) &(source->name); pb.ioParam.ioMisc = (Ptr) unique1Ptr; pb.ioParam.ioVersNum = 0; result = PBHRenameSync(&pb); if ( result != noErr ) { goto errorExit3; } /* rename dest to unique2 */ pb.ioParam.ioMisc = (Ptr) unique2Ptr; pb.ioParam.ioVersNum = 0; pb.fileParam.ioNamePtr = (StringPtr) &(dest->name); pb.fileParam.ioDirID = dest->parID; result = PBHRenameSync(&pb); if ( result != noErr ) { goto errorExit2; /* back out gracefully by renaming unique1 back to source */ } /* If files are not in same directory, swap their locations */ if ( source->parID != dest->parID ) { /* move source file to dest directory */ pb.copyParam.ioNamePtr = unique1Ptr; pb.copyParam.ioNewName = NULL; pb.copyParam.ioNewDirID = dest->parID; pb.copyParam.ioDirID = source->parID; result = PBCatMoveSync((CMovePBPtr) &pb); if ( result != noErr ) { goto errorExit1; /* back out gracefully by renaming both files to original names */ } /* move dest file to source directory */ pb.copyParam.ioNamePtr = unique2Ptr; pb.copyParam.ioNewDirID = source->parID; pb.copyParam.ioDirID = dest->parID; result = PBCatMoveSync((CMovePBPtr) &pb); if ( result != noErr) { /* life is very bad. We'll at least try to move source back */ pb.copyParam.ioNamePtr = unique1Ptr; pb.copyParam.ioNewName = NULL; pb.copyParam.ioNewDirID = source->parID; pb.copyParam.ioDirID = dest->parID; (void) PBCatMoveSync((CMovePBPtr) &pb); /* ignore errors */ goto errorExit1; /* back out gracefully by renaming both files to original names */ } } /* Make unique1Ptr point to file in source->parID */ /* and unique2Ptr point to file in dest->parID */ /* This lets us fall through to the rename code below */ swapola = unique1Ptr; unique1Ptr = unique2Ptr; unique2Ptr = swapola; /* At this point, the files are in their new locations (if they were moved) */ /* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */ /* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */ /* Need to swap attributes except mod date and swap names */ /* swap the catalog info by re-aiming the CInfoPB's */ catInfoSource.hFileInfo.ioNamePtr = unique1Ptr; catInfoDest.hFileInfo.ioNamePtr = unique2Ptr; catInfoSource.hFileInfo.ioDirID = source->parID; catInfoDest.hFileInfo.ioDirID = dest->parID; /* Swap the original mod dates with each file */ temp = catInfoSource.hFileInfo.ioFlMdDat; catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat; catInfoDest.hFileInfo.ioFlMdDat = temp; /* Here's the swap (ignore errors) */ (void) PBSetCatInfoSync(&catInfoSource); (void) PBSetCatInfoSync(&catInfoDest); /* rename unique2 back to dest */ errorExit1: pb.ioParam.ioMisc = (Ptr) &(dest->name); pb.ioParam.ioVersNum = 0; pb.fileParam.ioNamePtr = unique2Ptr; pb.fileParam.ioDirID = dest->parID; (void) PBHRenameSync(&pb); /* ignore errors */ /* rename unique1 back to source */ errorExit2: pb.ioParam.ioMisc = (Ptr) &(source->name); pb.ioParam.ioVersNum = 0; pb.fileParam.ioNamePtr = unique1Ptr; pb.fileParam.ioDirID = source->parID; (void) PBHRenameSync(&pb); /* ignore errors */ } errorExit3: { /* null statement */ } return ( result ); } else #endif /* !__MACOSSEVENFIVEORLATER */ { return ( FSpExchangeFiles(source, dest) ); } } /*****************************************************************************/ /* ** Resource Manager FSp calls */ /*****************************************************************************/ pascal short FSpOpenResFileCompat(const FSSpec *spec, SignedByte permission) { #if !__MACOSSEVENORLATER if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() ) { return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) ); } else #endif /* !__MACOSSEVENORLATER */ { return ( FSpOpenResFile(spec, permission) ); } } /*****************************************************************************/ pascal void FSpCreateResFileCompat(const FSSpec *spec, OSType creator, OSType fileType, ScriptCode scriptTag) { #if !__MACOSSEVENFIVEONEORLATER if ( #if !__MACOSSEVENORLATER (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) || #endif /* !__MACOSSEVENORLATER */ !HasFSpCreateScriptSupportFix() ) { OSErr result; CInfoPBRec pb; HCreateResFile(spec->vRefNum, spec->parID, spec->name); if ( ResError() == noErr ) { /* get info on created item */ pb.hFileInfo.ioVRefNum = spec->vRefNum; pb.hFileInfo.ioDirID = spec->parID; pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name); pb.hFileInfo.ioFDirIndex = 0; result = PBGetCatInfoSync(&pb); if ( result == noErr ) { /* Set fdScript in FXInfo */ /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */ /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */ /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */ pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ? ((char)scriptTag | (char)0x80) : (smRoman); /* Set creator/fileType */ pb.hFileInfo.ioFlFndrInfo.fdCreator = creator; pb.hFileInfo.ioFlFndrInfo.fdType = fileType; /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ pb.hFileInfo.ioDirID = spec->parID; result = PBSetCatInfoSync(&pb); } /* Set ResErr low memory global to result */ LMSetResErr(result); } return; } else #endif /* !__MACOSSEVENFIVEONEORLATER */ { FSpCreateResFile(spec, creator, fileType, scriptTag); return; } } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/FileCopy.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** FileCopy: A robust, general purpose file copy routine. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FileCopy.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "MoreDesktopMgr.h" #include "FileCopy.h" /*****************************************************************************/ /* local constants */ /* The deny-mode privileges to use when opening the source and destination files. */ enum { srcCopyMode = dmRdDenyWr, dstCopyMode = dmWrDenyRdWr }; /* The largest (16K) and smallest (.5K) copy buffer to use if the caller doesn't supply ** their own copy buffer. */ enum { bigCopyBuffSize = 0x00004000, minCopyBuffSize = 0x00000200 }; /*****************************************************************************/ /* static prototypes */ static OSErr GetDestinationDirInfo(short vRefNum, long dirID, ConstStr255Param name, long *theDirID, Boolean *isDirectory, Boolean *isDropBox); /* GetDestinationDirInfo tells us if the destination is a directory, it's directory ID, and if it's an AppleShare drop box (write privileges only -- no read or search privileges). vRefNum input: Volume specification. dirID input: Directory ID. name input: Pointer to object name, or nil when dirID specifies a directory that's the object. theDirID output: If the object is a file, then its parent directory ID. If the object is a directory, then its ID. isDirectory output: True if object is a directory; false if object is a file. isDropBox output: True if directory is an AppleShare drop box. */ static OSErr CheckForForks(short vRefNum, long dirID, ConstStr255Param name, Boolean *hasDataFork, Boolean *hasResourceFork); /* CheckForForks tells us if there is a data or resource fork to copy. vRefNum input: Volume specification of the file's current location. dirID input: Directory ID of the file's current location. name input: The name of the file. */ static OSErr PreflightFileCopySpace(short srcVRefNum, long srcDirID, ConstStr255Param srcName, ConstStr255Param dstVolName, short dstVRefNum, Boolean *spaceOK); /* PreflightFileCopySpace determines if there's enough space on a volume to copy the specified file to that volume. Note: The results of this routine are not perfect. For example if the volume's catalog or extents overflow file grows when the new file is created, more allocation blocks may be needed beyond those needed for the file's data and resource forks. srcVRefNum input: Volume specification of the file's current location. srcDirID input: Directory ID of the file's current location. srcName input: The name of the file. dstVolName input: A pointer to the name of the volume where the file will be copied or NULL. dstVRefNum input: Volume specification indicating the volume where the file will be copied. spaceOK output: true if there's enough space on the volume for the file's data and resource forks. */ /*****************************************************************************/ static OSErr GetDestinationDirInfo(short vRefNum, long dirID, ConstStr255Param name, long *theDirID, Boolean *isDirectory, Boolean *isDropBox) { CInfoPBRec pb; OSErr error; pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2, clear it before calling GetCatInfo */ error = GetCatInfoNoName(vRefNum, dirID, name, &pb); *theDirID = pb.dirInfo.ioDrDirID; *isDirectory = (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0; /* see if access priviledges are make changes, not see folder, and not see files (drop box) */ *isDropBox = userHasDropBoxAccess(pb.dirInfo.ioACUser); return ( error ); } /*****************************************************************************/ static OSErr CheckForForks(short vRefNum, long dirID, ConstStr255Param name, Boolean *hasDataFork, Boolean *hasResourceFork) { HParamBlockRec pb; OSErr error; pb.fileParam.ioNamePtr = (StringPtr)name; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioDirID = dirID; pb.fileParam.ioFDirIndex = 0; error = PBHGetFInfoSync(&pb); *hasDataFork = (pb.fileParam.ioFlLgLen != 0); *hasResourceFork = (pb.fileParam.ioFlRLgLen != 0); return ( error ); } /*****************************************************************************/ static OSErr PreflightFileCopySpace(short srcVRefNum, long srcDirID, ConstStr255Param srcName, ConstStr255Param dstVolName, short dstVRefNum, Boolean *spaceOK) { UniversalFMPB pb; OSErr error; unsigned long dstFreeBlocks; unsigned long dstBlksPerAllocBlk; unsigned long srcDataBlks; unsigned long srcResourceBlks; error = XGetVolumeInfoNoName(dstVolName, dstVRefNum, &pb.xPB); if ( error == noErr ) { /* get allocation block size (always multiple of 512) and divide by 512 to get number of 512-byte blocks per allocation block */ dstBlksPerAllocBlk = ((unsigned long)pb.xPB.ioVAlBlkSiz >> 9); /* Convert freeBytes to free disk blocks (512-byte blocks) */ dstFreeBlocks = U32SetU(U64ShiftRight(pb.xPB.ioVFreeBytes, 9)); /* Now, get the size of the file's data resource forks */ pb.hPB.fileParam.ioNamePtr = (StringPtr)srcName; pb.hPB.fileParam.ioVRefNum = srcVRefNum; pb.hPB.fileParam.ioFVersNum = 0; pb.hPB.fileParam.ioDirID = srcDirID; pb.hPB.fileParam.ioFDirIndex = 0; error = PBHGetFInfoSync(&pb.hPB); if ( error == noErr ) { /* Since space on Mac OS disks is always allocated in allocation blocks, */ /* this code takes into account rounding up to the end of an allocation block. */ /* get number of 512-byte blocks needed for data fork */ if ( ((unsigned long)pb.hPB.fileParam.ioFlLgLen & 0x000001ff) != 0 ) { srcDataBlks = ((unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9) + 1; } else { srcDataBlks = (unsigned long)pb.hPB.fileParam.ioFlLgLen >> 9; } /* now, calculate number of new allocation blocks needed */ if ( srcDataBlks % dstBlksPerAllocBlk ) { srcDataBlks = (srcDataBlks / dstBlksPerAllocBlk) + 1; } else { srcDataBlks /= dstBlksPerAllocBlk; } /* get number of 512-byte blocks needed for resource fork */ if ( ((unsigned long)pb.hPB.fileParam.ioFlRLgLen & 0x000001ff) != 0 ) { srcResourceBlks = ((unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9) + 1; } else { srcResourceBlks = (unsigned long)pb.hPB.fileParam.ioFlRLgLen >> 9; } /* now, calculate number of new allocation blocks needed */ if ( srcResourceBlks % dstBlksPerAllocBlk ) { srcResourceBlks = (srcResourceBlks / dstBlksPerAllocBlk) + 1; } else { srcResourceBlks /= dstBlksPerAllocBlk; } /* Is there enough room on the destination volume for the source file? */ *spaceOK = ( ((srcDataBlks + srcResourceBlks) * dstBlksPerAllocBlk) <= dstFreeBlocks ); } } return ( error ); } /*****************************************************************************/ pascal OSErr FileCopy(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstPathname, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight) { OSErr err; short srcRefNum = 0, /* 0 when source data and resource fork are closed */ dstDataRefNum = 0, /* 0 when destination data fork is closed */ dstRsrcRefNum = 0; /* 0 when destination resource fork is closed */ Str63 dstName; /* The filename of the destination. It might be the ** source filename, it might be a new name... */ GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */ long srcServerAdr; /* AppleTalk server address of source (if any) */ Boolean dstCreated = false, /* true when destination file has been created */ ourCopyBuffer = false, /* true if we had to allocate the copy buffer */ isDirectory, /* true if destination is really a directory */ isDropBox; /* true if destination is an AppleShare drop box */ long tempLong; short tempInt; Boolean spaceOK; /* true if there's enough room to copy the file to the destination volume */ Boolean hasDataFork; Boolean hasResourceFork; /* Preflight for size */ if ( preflight ) { err = PreflightFileCopySpace(srcVRefNum, srcDirID, srcName, dstPathname, dstVRefNum, &spaceOK); if ( err != noErr ) { return ( err ); } if ( !spaceOK ) { return ( dskFulErr ); } } /* get the destination's real dirID and make sure it really is a directory */ err = GetDestinationDirInfo(dstVRefNum, dstDirID, dstPathname, &dstDirID, &isDirectory, &isDropBox); if ( err != noErr ) { goto ErrorExit; } if ( !isDirectory ) { return ( dirNFErr ); } /* get the destination's real vRefNum */ err = DetermineVRefNum(dstPathname, dstVRefNum, &dstVRefNum); if ( err != noErr ) { goto ErrorExit; } /* See if PBHCopyFile can be used. Using PBHCopyFile saves time by letting the file server ** copy the file if the source and destination locations are on the same file server. */ tempLong = sizeof(infoBuffer); err = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong); if ( (err != noErr) && (err != paramErr) ) { return ( err ); } if ( (err != paramErr) && hasCopyFile(infoBuffer) ) { /* The source volume supports PBHCopyFile. */ srcServerAdr = infoBuffer.vMServerAdr; /* Now, see if the destination volume is on the same file server. */ tempLong = sizeof(infoBuffer); err = HGetVolParms(NULL, dstVRefNum, &infoBuffer, &tempLong); if ( (err != noErr) && (err != paramErr) ) { return ( err ); } if ( (err != paramErr) && (srcServerAdr == infoBuffer.vMServerAdr) ) { /* Source and Dest are on same server and PBHCopyFile is supported. Copy with CopyFile. */ err = HCopyFile(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, NULL, copyName); if ( err != noErr ) { return ( err ); } /* AppleShare's CopyFile clears the isAlias bit, so I still need to attempt to copy the File's attributes to attempt to get things right. */ if ( copyName != NULL ) /* Did caller supply copy file name? */ { /* Yes, use the caller supplied copy file name. */ (void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, copyName, true); } else { /* They didn't, so get the source file name and use it. */ if ( GetFilenameFromPathname(srcName, dstName) == noErr ) { /* */ (void) CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName, true); } } return ( err ); } } /* If we're here, then PBHCopyFile couldn't be used so we have to copy the file by hand. */ /* Make sure a copy buffer is allocated. */ if ( copyBufferPtr == NULL ) { /* The caller didn't supply a copy buffer so grab one from the application heap. ** Try to get a big copy buffer, if we can't, try for a 512-byte buffer. ** If 512 bytes aren't available, we're in trouble. */ copyBufferSize = bigCopyBuffSize; copyBufferPtr = NewPtr(copyBufferSize); if ( copyBufferPtr == NULL ) { copyBufferSize = minCopyBuffSize; copyBufferPtr = NewPtr(copyBufferSize); if ( copyBufferPtr == NULL ) { return ( memFullErr ); } } ourCopyBuffer = true; } /* Open the source data fork. */ err = HOpenAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum); if ( err != noErr ) return ( err ); /* Once a file is opened, we have to exit via ErrorExit to make sure things are cleaned up */ /* See if the copy will be renamed. */ if ( copyName != NULL ) /* Did caller supply copy file name? */ BlockMoveData(copyName, dstName, copyName[0] + 1); /* Yes, use the caller supplied copy file name. */ else { /* They didn't, so get the source file name and use it. */ err = GetFileLocation(srcRefNum, &tempInt, &tempLong, dstName); if ( err != noErr ) { goto ErrorExit; } } /* Create the destination file. */ err = HCreateMinimum(dstVRefNum, dstDirID, dstName); if ( err != noErr ) { goto ErrorExit; } dstCreated = true; /* After creating the destination file, any ** error conditions should delete the destination file */ /* An AppleShare dropbox folder is a folder for which the user has the Make Changes ** privilege (write access), but not See Files (read access) and See Folders (search access). ** Copying a file into an AppleShare dropbox presents some special problems. Here are the ** rules we have to follow to copy a file into a dropbox: ** File attributes can be changed only when both forks of a file are empty. ** DeskTop Manager comments can be added to a file only when both forks of a file ** are empty. ** A fork can be opened for write access only when both forks of a file are empty. ** So, with those rules to live with, we'll do those operations now while both forks ** are empty. */ if ( isDropBox ) { /* We only set the file attributes now if the file is being copied into a ** drop box. In all other cases, it is better to set the attributes last ** so that if FileCopy is modified to give up time to other processes ** periodicly, the Finder won't try to read any bundle information (because ** the bundle-bit will still be clear) from a partially copied file. If the ** copy is into a drop box, we have to set the attributes now, but since the ** destination forks are opened with write/deny-read/deny-write permissions, ** any Finder that might see the file in the drop box won't be able to open ** its resource fork until the resource fork is closed. ** ** Note: if you do modify FileCopy to give up time to other processes, don't ** give up time between the time the destination file is created (above) and ** the time both forks are opened (below). That way, you stand the best chance ** of making sure the Finder doesn't read a partially copied resource fork. */ /* Copy attributes but don't lock the destination. */ err = CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName, false); if ( err != noErr ) { goto ErrorExit; } } /* Attempt to copy the comments while both forks are empty. ** Ignore the result because we really don't care if it worked or not. */ (void) DTCopyComment(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName); /* See which forks we need to copy. By doing this, we won't create a data or resource fork ** for the destination unless it's really needed (some foreign file systems such as ** the ProDOS File System and Macintosh PC Exchange have to create additional disk ** structures to support resource forks). */ err = CheckForForks(srcVRefNum, srcDirID, srcName, &hasDataFork, &hasResourceFork); if ( err != noErr ) { goto ErrorExit; } if ( hasDataFork ) { /* Open the destination data fork. */ err = HOpenAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstDataRefNum); if ( err != noErr ) { goto ErrorExit; } } if ( hasResourceFork ) { /* Open the destination resource fork. */ err = HOpenRFAware(dstVRefNum, dstDirID, dstName, dstCopyMode, &dstRsrcRefNum); if ( err != noErr ) { goto ErrorExit; } } if ( hasDataFork ) { /* Copy the data fork. */ err = CopyFork(srcRefNum, dstDataRefNum, copyBufferPtr, copyBufferSize); if ( err != noErr ) { goto ErrorExit; } /* Close both data forks and clear reference numbers. */ (void) FSClose(srcRefNum); (void) FSClose(dstDataRefNum); srcRefNum = dstDataRefNum = 0; } else { /* Close the source data fork since it was opened earlier */ (void) FSClose(srcRefNum); srcRefNum = 0; } if ( hasResourceFork ) { /* Open the source resource fork. */ err = HOpenRFAware(srcVRefNum, srcDirID, srcName, srcCopyMode, &srcRefNum); if ( err != noErr ) { goto ErrorExit; } /* Copy the resource fork. */ err = CopyFork(srcRefNum, dstRsrcRefNum, copyBufferPtr, copyBufferSize); if ( err != noErr ) { goto ErrorExit; } /* Close both resource forks and clear reference numbers. */ (void) FSClose(srcRefNum); (void) FSClose(dstRsrcRefNum); srcRefNum = dstRsrcRefNum = 0; } /* Get rid of the copy buffer if we allocated it. */ if ( ourCopyBuffer ) { DisposePtr((Ptr)copyBufferPtr); } /* Attempt to copy attributes again to set mod date. Copy lock condition this time ** since we're done with the copy operation. This operation will fail if we're copying ** into an AppleShare dropbox, so we don't check for error conditions. */ CopyFileMgrAttributes(srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName, true); /* Hey, we did it! */ return ( noErr ); ErrorExit: if ( srcRefNum != 0 ) { (void) FSClose(srcRefNum); /* Close the source file */ } if ( dstDataRefNum != 0 ) { (void) FSClose(dstDataRefNum); /* Close the destination file data fork */ } if ( dstRsrcRefNum != 0 ) { (void) FSClose(dstRsrcRefNum); /* Close the destination file resource fork */ } if ( dstCreated ) { (void) HDelete(dstVRefNum, dstDirID, dstName); /* Delete dest file. This may fail if the file is in a "drop folder" */ } if ( ourCopyBuffer ) /* dispose of any memory we allocated */ { DisposePtr((Ptr)copyBufferPtr); } return ( err ); } /*****************************************************************************/ pascal OSErr FSpFileCopy(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName, void *copyBufferPtr, long copyBufferSize, Boolean preflight) { return ( FileCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name, copyName, copyBufferPtr, copyBufferSize, preflight) ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/FullPath.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** Routines for dealing with full pathnames... if you really must. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: FullPath.c ** ** Copyright 1995-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #if 0 #include #include #include #include #include #include #endif 0 #define __COMPILINGMOREFILES #include "FSpCompat.h" #include "FullPath.h" /* IMPORTANT NOTE: The use of full pathnames is strongly discouraged. Full pathnames are particularly unreliable as a means of identifying files, directories or volumes within your application, for two primary reasons: The user can change the name of any element in the path at virtually any time. Volume names on the Macintosh are *not* unique. Multiple mounted volumes can have the same name. For this reason, the use of a full pathname to identify a specific volume may not produce the results you expect. If more than one volume has the same name and a full pathname is used, the File Manager currently uses the first mounted volume it finds with a matching name in the volume queue. In general, you should use a files name, parent directory ID, and volume reference number to identify a file you want to open, delete, or otherwise manipulate. If you need to remember the location of a particular file across subsequent system boots, use the Alias Manager to create an alias record describing the file. If the Alias Manager is not available, you can save the files name, its parent directory ID, and the name of the volume on which its located. Although none of these methods is foolproof, they are much more reliable than using full pathnames to identify files. Nonetheless, it is sometimes useful to display a files full pathname to the user. For example, a backup utility might display a list of full pathnames of files as it copies them onto the backup medium. Or, a utility might want to display a dialog box showing the full pathname of a file when it needs the users confirmation to delete the file. No matter how unreliable full pathnames may be from a file-specification viewpoint, users understand them more readily than volume reference numbers or directory IDs. (Hint: Use the TruncString function from TextUtils.h with truncMiddle as the truncWhere argument to shorten full pathnames to a displayable length.) The following technique for constructing the full pathname of a file is intended for display purposes only. Applications that depend on any particular structure of a full pathname are likely to fail on alternate foreign file systems or under future system software versions. */ /*****************************************************************************/ pascal OSErr GetFullPath(short vRefNum, long dirID, ConstStr255Param name, short *fullPathLength, Handle *fullPath) { OSErr result; FSSpec spec; *fullPathLength = 0; *fullPath = NULL; result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec); if ( (result == noErr) || (result == fnfErr) ) { result = FSpGetFullPath(&spec, fullPathLength, fullPath); } return ( result ); } /*****************************************************************************/ pascal OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath) { OSErr result; OSErr realResult; FSSpec tempSpec; CInfoPBRec pb; *fullPathLength = 0; *fullPath = NULL; /* Default to noErr */ realResult = result = noErr; #if 0 //The following code doesn't seem to work in OS X, the BloackMoveData crashes the // machine, the the FSMakeFSSpecCompat works, so go figure... KG 4/1/01 /* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */ if ( spec->name[0] == 0 ) { result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec); } else { /* Make a copy of the input FSSpec that can be modified */ BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); } #endif 0 result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec); if ( result == noErr ) { if ( tempSpec.parID == fsRtParID ) { /* The object is a volume */ /* Add a colon to make it a full pathname */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* We're done */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); *fullPathLength = tempSpec.name[0]; } else { /* The object isn't a volume */ /* Is the object a file or a directory? */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrDirID = tempSpec.parID; pb.dirInfo.ioFDirIndex = 0; result = PBGetCatInfoSync(&pb); // Allow file/directory name at end of path to not exist. realResult = result; if ( (result == noErr) || (result == fnfErr) ) { /* if the object is a directory, append a colon so full pathname ends with colon */ if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; } /* Put the object name in first */ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); *fullPathLength = tempSpec.name[0]; if ( result == noErr ) { /* Get the ancestor directory names */ pb.dirInfo.ioNamePtr = tempSpec.name; pb.dirInfo.ioVRefNum = tempSpec.vRefNum; pb.dirInfo.ioDrParID = tempSpec.parID; do /* loop until we have an error or find the root directory */ { pb.dirInfo.ioFDirIndex = -1; pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; result = PBGetCatInfoSync(&pb); if ( result == noErr ) { /* Append colon to directory name */ ++tempSpec.name[0]; tempSpec.name[tempSpec.name[0]] = ':'; /* Add directory name to beginning of fullPath */ (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); *fullPathLength += tempSpec.name[0]; result = MemError(); } } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) ); } } } } if ( result == noErr ) { /* Return the length */ /// *fullPathLength = GetHandleSize(*fullPath); result = realResult; // return realResult in case it was fnfErr } else { /* Dispose of the handle and return NULL and zero length */ if ( *fullPath != NULL ) { DisposeHandle(*fullPath); } *fullPath = NULL; *fullPathLength = 0; } return ( result ); } /*****************************************************************************/ pascal OSErr FSpLocationFromFullPath(short fullPathLength, const void *fullPath, FSSpec *spec) { AliasHandle alias; OSErr result; Boolean wasChanged; Str32 nullString; /* Create a minimal alias from the full pathname */ nullString[0] = 0; /* null string to indicate no zone or server name */ result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias); if ( result == noErr ) { /* Let the Alias Manager resolve the alias. */ result = ResolveAlias(NULL, alias, spec, &wasChanged); /* work around Alias Mgr sloppy volume matching bug */ if ( spec->vRefNum == 0 ) { /* invalidate wrong FSSpec */ spec->parID = 0; spec->name[0] = 0; result = nsvErr; } DisposeHandle((Handle)alias); /* Free up memory used */ } return ( result ); } /*****************************************************************************/ pascal OSErr LocationFromFullPath(short fullPathLength, const void *fullPath, short *vRefNum, long *parID, Str31 name) { OSErr result; FSSpec spec; result = FSpLocationFromFullPath(fullPathLength, fullPath, &spec); if ( result == noErr ) { *vRefNum = spec.vRefNum; *parID = spec.parID; BlockMoveData(&spec.name[0], &name[0], spec.name[0] + 1); } return ( result ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/IterateDirectory.c ================================================ /* ** IterateDirectory: File Manager directory iterator routines. ** ** by Jim Luther ** ** File: IterateDirectory.c ** ** Copyright 1995-1999 Jim Luther and Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. ** ** IterateDirectory is designed to drop into the MoreFiles sample code ** library I wrote while in Apple Developer Technical Support */ #include #include #include #define __COMPILINGMOREFILES #include "MoreFilesExtras.h" #include "IterateDirectory.h" /* ** Type definitions */ /* The IterateGlobals structure is used to minimize the amount of ** stack space used when recursively calling IterateDirectoryLevel ** and to hold global information that might be needed at any time. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct IterateGlobals { IterateFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */ CInfoPBRec cPB; /* the parameter block used for PBGetCatInfo calls */ Str63 itemName; /* the name of the current item */ OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */ Boolean quitFlag; /* set to true if filter wants to kill interation */ unsigned short maxLevels; /* Maximum levels to iterate through */ unsigned short currentLevel; /* The current level IterateLevel is on */ void *yourDataPtr; /* A pointer to caller data the filter may need to access */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif typedef struct IterateGlobals IterateGlobals; typedef IterateGlobals *IterateGlobalsPtr; /*****************************************************************************/ /* Static Prototype */ static void IterateDirectoryLevel(long dirID, IterateGlobals *theGlobals); /*****************************************************************************/ /* ** Functions */ static void IterateDirectoryLevel(long dirID, IterateGlobals *theGlobals) { if ( (theGlobals->maxLevels == 0) || /* if maxLevels is zero, we aren't checking levels */ (theGlobals->currentLevel < theGlobals->maxLevels) ) /* if currentLevel < maxLevels, look at this level */ { short index = 1; ++theGlobals->currentLevel; /* go to next level */ do { /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */ /* Get next source item at the current directory level */ theGlobals->cPB.dirInfo.ioFDirIndex = index; theGlobals->cPB.dirInfo.ioDrDirID = dirID; theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB); if ( theGlobals->result == noErr ) { /* Call the IterateFilterProc */ CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr); /* Is it a directory? */ if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* We have a directory */ if ( !theGlobals->quitFlag ) { /* Dive again if the IterateFilterProc didn't say "quit" */ IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals); } } } ++index; /* prepare to get next item */ } while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */ if ( (theGlobals->result == fnfErr) || /* fnfErr is OK - it only means we hit the end of this level */ (theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */ { theGlobals->result = noErr; } --theGlobals->currentLevel; /* return to previous level as we leave */ } } /*****************************************************************************/ pascal OSErr IterateDirectory(short vRefNum, long dirID, ConstStr255Param name, unsigned short maxLevels, IterateFilterProcPtr iterateFilter, void *yourDataPtr) { IterateGlobals theGlobals; OSErr result; long theDirID; short theVRefNum; Boolean isDirectory; /* Make sure there is a IterateFilter */ if ( iterateFilter != NULL ) { /* Get the real directory ID and make sure it is a directory */ result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory); if ( result == noErr ) { if ( isDirectory == true ) { /* Get the real vRefNum */ result = DetermineVRefNum(name, vRefNum, &theVRefNum); if ( result == noErr ) { /* Set up the globals we need to access from the recursive routine. */ theGlobals.iterateFilter = iterateFilter; theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName; theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum; theGlobals.itemName[0] = 0; theGlobals.result = noErr; theGlobals.quitFlag = false; theGlobals.maxLevels = maxLevels; theGlobals.currentLevel = 0; /* start at level 0 */ theGlobals.yourDataPtr = yourDataPtr; /* Here we go into recursion land... */ IterateDirectoryLevel(theDirID, &theGlobals); result = theGlobals.result; /* set the result */ } } else { result = dirNFErr; /* a file was passed instead of a directory */ } } } else { result = paramErr; /* iterateFilter was NULL */ } return ( result ); } /*****************************************************************************/ pascal OSErr FSpIterateDirectory(const FSSpec *spec, unsigned short maxLevels, IterateFilterProcPtr iterateFilter, void *yourDataPtr) { return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name, maxLevels, iterateFilter, yourDataPtr) ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/MoreDesktopMgr.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** A collection of useful high-level Desktop Manager routines. ** If the Desktop Manager isn't available, use the Desktop file ** for 'read' operations. ** ** We do more because we can... ** ** by Jim Luther and Nitin Ganatra, Apple Developer Technical Support Emeriti ** ** File: MoreDesktopMgr.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "Search.h" #include "MoreDesktopMgr.h" /*****************************************************************************/ /* Desktop file notes: ** ** The Desktop file is owned by the Finder and is normally open by the ** Finder. That means that we only have read-only access to the Desktop ** file. ** Since the Resource Manager doesn't support shared access to resource ** files and we're using read-only access, we don't ever leave the ** Desktop file open. We open a path to it, get the data we want out ** of it, and then close the open path. This is the only safe way to ** open a resource file with read-only access since some other program ** could have it open with write access. ** The bundle related resources in the Desktop file are normally ** purgable, so when we're looking through them, we don't bother to ** release resources we're done looking at - closing the resource file ** (which we always do) will release them. ** Since we can't assume the Desktop file is named "Desktop" ** (it probably is everywhere but France), we get the Desktop ** file's name by searching the volume's root directory for a file ** with fileType == 'FNDR' and creator == 'ERIK'. The only problem with ** this scheme is that someone could create another file with that type ** and creator in the root directory and we'd find the wrong file. ** The chances of this are very slim. */ /*****************************************************************************/ /* local defines */ enum { kBNDLResType = 'BNDL', kFREFResType = 'FREF', kIconFamResType = 'ICN#', kFCMTResType = 'FCMT', kAPPLResType = 'APPL' }; /*****************************************************************************/ /* local data structures */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct IDRec { short localID; short rsrcID; }; typedef struct IDRec IDRec; typedef IDRec *IDRecPtr; struct BundleType { OSType type; /* 'ICN#' or 'FREF' */ short count; /* number of IDRecs - 1 */ IDRec idArray[1]; }; typedef struct BundleType BundleType; typedef BundleType *BundleTypePtr; struct BNDLRec { OSType signature; /* creator type signature */ short versionID; /* version - should always be 0 */ short numTypes; /* number of elements in typeArray - 1 */ BundleType typeArray[1]; }; typedef struct BNDLRec BNDLRec; typedef BNDLRec **BNDLRecHandle; struct FREFRec { OSType fileType; /* file type */ short iconID; /* icon local ID */ Str255 fileName; /* file name */ }; typedef struct FREFRec FREFRec; typedef FREFRec **FREFRecHandle; struct APPLRec { OSType creator; /* creator type signature */ long parID; /* parent directory ID */ Str255 applName; /* application name */ }; typedef struct APPLRec APPLRec; typedef APPLRec *APPLRecPtr; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif /*****************************************************************************/ /* static prototypes */ static OSErr GetDesktopFileName(short vRefNum, Str255 desktopName); static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, short vRefNum, OSType creator, short *applVRefNum, long *applParID, Str255 applName); static OSErr FindBundleGivenCreator(OSType creator, BNDLRecHandle *returnBndl); static OSErr FindTypeInBundle(OSType typeToFind, BNDLRecHandle theBndl, BundleTypePtr *returnBundleType); static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, OSType fileType, short *iconLocalID); static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, short iconLocalID, short *iconRsrcID); static OSType DTIconToResIcon(short iconType); static OSErr GetIconFromDesktopFile(ConstStr255Param volName, short vRefNum, short iconType, OSType fileCreator, OSType fileType, Handle *iconHandle); static OSErr GetCommentID(short vRefNum, long dirID, ConstStr255Param name, short *commentID); static OSErr GetCommentFromDesktopFile(short vRefNum, long dirID, ConstStr255Param name, Str255 comment); /*****************************************************************************/ /* ** GetDesktopFileName ** ** Get the name of the Desktop file. */ static OSErr GetDesktopFileName(short vRefNum, Str255 desktopName) { OSErr error; HParamBlockRec pb; short index; Boolean found; pb.fileParam.ioNamePtr = desktopName; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioFVersNum = 0; index = 1; found = false; do { pb.fileParam.ioDirID = fsRtDirID; pb.fileParam.ioFDirIndex = index; error = PBHGetFInfoSync(&pb); if ( error == noErr ) { if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') && (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') ) { found = true; } } ++index; } while ( (error == noErr) && !found ); return ( error ); } /*****************************************************************************/ pascal OSErr DTOpen(ConstStr255Param volName, short vRefNum, short *dtRefNum, Boolean *newDTDatabase) { OSErr error; GetVolParmsInfoBuffer volParmsInfo; long infoSize; DTPBRec pb; /* Check for volume Desktop Manager support before calling */ infoSize = sizeof(GetVolParmsInfoBuffer); error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize); if ( error == noErr ) { if ( hasDesktopMgr(volParmsInfo) ) { pb.ioNamePtr = (StringPtr)volName; pb.ioVRefNum = vRefNum; error = PBDTOpenInform(&pb); /* PBDTOpenInform informs us if the desktop was just created */ /* by leaving the low bit of ioTagInfo clear (0) */ *newDTDatabase = ((pb.ioTagInfo & 1L) == 0); if ( error == paramErr ) { error = PBDTGetPath(&pb); /* PBDTGetPath doesn't tell us if the database is new */ /* so assume it is not new */ *newDTDatabase = false; } *dtRefNum = pb.ioDTRefNum; } else { error = paramErr; } } return ( error ); } /*****************************************************************************/ /* ** GetAPPLFromDesktopFile ** ** Get a application's location from the ** Desktop file's 'APPL' resources. */ static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName, short vRefNum, OSType creator, short *applVRefNum, long *applParID, Str255 applName) { OSErr error; short realVRefNum; Str255 desktopName; short savedResFile; short dfRefNum; Handle applResHandle; Boolean foundCreator; Ptr applPtr; long applSize; error = DetermineVRefNum(volName, vRefNum, &realVRefNum); if ( error == noErr ) { error = GetDesktopFileName(realVRefNum, desktopName); if ( error == noErr ) { savedResFile = CurResFile(); /* ** Open the 'Desktop' file in the root directory. (because ** opening the resource file could preload unwanted resources, ** bracket the call with SetResLoad(s)) */ SetResLoad(false); dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); SetResLoad(true); if ( dfRefNum != -1) { /* Get 'APPL' resource ID 0 */ applResHandle = Get1Resource(kAPPLResType, 0); if ( applResHandle != NULL ) { applSize = GetHandleSize((Handle)applResHandle); if ( applSize != 0 ) /* make sure the APPL resource isn't empty */ { foundCreator = false; applPtr = *applResHandle; /* APPL's don't have a count so I have to use the size as the bounds */ while ( (foundCreator == false) && (applPtr < (*applResHandle + applSize)) ) { if ( ((APPLRecPtr)applPtr)->creator == creator ) { foundCreator = true; } else { /* fun with pointer math... */ applPtr += sizeof(OSType) + sizeof(long) + ((APPLRecPtr)applPtr)->applName[0] + 1; /* application mappings are word aligned within the resource */ if ( ((unsigned long)applPtr % 2) != 0 ) { applPtr += 1; } } } if ( foundCreator == true ) { *applVRefNum = realVRefNum; *applParID = ((APPLRecPtr)applPtr)->parID; BlockMoveData(((APPLRecPtr)applPtr)->applName, applName, ((APPLRecPtr)applPtr)->applName[0] + 1); /* error is already noErr */ } else { error = afpItemNotFound; /* didn't find a creator match */ } } else { error = afpItemNotFound; /* no APPL mapping available */ } } else { error = afpItemNotFound; /* no APPL mapping available */ } /* restore the resource chain and close the Desktop file */ UseResFile(savedResFile); CloseResFile(dfRefNum); } else { error = afpItemNotFound; } } } return ( error ); } /*****************************************************************************/ pascal OSErr DTXGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, Boolean searchCatalog, short *applVRefNum, long *applParID, Str255 applName) { OSErr error; UniversalFMPB pb; short dtRefNum; Boolean newDTDatabase; short realVRefNum; short index; Boolean applFound; FSSpec spec; long actMatchCount; /* get the real vRefNum */ error = DetermineVRefNum(volName, vRefNum, &realVRefNum); if ( error == noErr ) { error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); if ( error == noErr ) { if ( !newDTDatabase ) { index = 0; applFound = false; do { pb.dtPB.ioNamePtr = applName; pb.dtPB.ioDTRefNum = dtRefNum; pb.dtPB.ioIndex = index; pb.dtPB.ioFileCreator = creator; error = PBDTGetAPPLSync(&pb.dtPB); if ( error == noErr ) { /* got a match - see if it is valid */ *applVRefNum = realVRefNum; /* get the vRefNum now */ *applParID = pb.dtPB.ioAPPLParID; /* get the parent ID now */ /* pb.hPB.fileParam.ioNamePtr is already set */ pb.hPB.fileParam.ioVRefNum = realVRefNum; pb.hPB.fileParam.ioFVersNum = 0; pb.hPB.fileParam.ioDirID = *applParID; pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ if ( PBHGetFInfoSync(&pb.hPB) == noErr ) { if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator == creator) && (pb.hPB.fileParam.ioFlFndrInfo.fdType == 'APPL') ) { applFound = true; } } } ++index; } while ( (error == noErr) && !applFound ); if ( error != noErr ) { error = afpItemNotFound; } } else { /* Desktop database is empty (new), set error to try CatSearch */ error = afpItemNotFound; } } /* acceptable errors from Desktop Manager to continue are paramErr or afpItemNotFound */ if ( error == paramErr ) { /* if paramErr, the volume didn't support the Desktop Manager */ /* try the Desktop file */ error = GetAPPLFromDesktopFile(volName, vRefNum, creator, applVRefNum, applParID, applName); if ( error == noErr ) { /* got a match - see if it is valid */ pb.hPB.fileParam.ioNamePtr = applName; pb.hPB.fileParam.ioVRefNum = *applVRefNum; pb.hPB.fileParam.ioFVersNum = 0; pb.hPB.fileParam.ioDirID = *applParID; pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ if ( PBHGetFInfoSync(&pb.hPB) == noErr ) { if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator != creator) || (pb.hPB.fileParam.ioFlFndrInfo.fdType != 'APPL') ) { error = afpItemNotFound; } } else if ( error == fnfErr ) { error = afpItemNotFound; } } } /* acceptable error from DesktopFile code to continue is afpItemNotFound */ if ( (error == afpItemNotFound) && searchCatalog) { /* Couldn't be found in the Desktop file either, */ /* try searching with CatSearch if requested */ error = CreatorTypeFileSearch(NULL, realVRefNum, creator, kAPPLResType, &spec, 1, &actMatchCount, true); if ( (error == noErr) || (error == eofErr) ) { if ( actMatchCount > 0 ) { *applVRefNum = spec.vRefNum; *applParID = spec.parID; BlockMoveData(spec.name, applName, spec.name[0] + 1); } else { error = afpItemNotFound; } } } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, Boolean searchCatalog, FSSpec *spec) { return ( DTXGetAPPL(volName, vRefNum, creator, searchCatalog, &(spec->vRefNum), &(spec->parID), spec->name) ); } /*****************************************************************************/ pascal OSErr DTGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, short *applVRefNum, long *applParID, Str255 applName) { /* Call DTXGetAPPL with the "searchCatalog" parameter true */ return ( DTXGetAPPL(volName, vRefNum, creator, true, applVRefNum, applParID, applName) ); } /*****************************************************************************/ pascal OSErr FSpDTGetAPPL(ConstStr255Param volName, short vRefNum, OSType creator, FSSpec *spec) { /* Call DTXGetAPPL with the "searchCatalog" parameter true */ return ( DTXGetAPPL(volName, vRefNum, creator, true, &(spec->vRefNum), &(spec->parID), spec->name) ); } /*****************************************************************************/ /* ** FindBundleGivenCreator ** ** Search the current resource file for the 'BNDL' resource with the given ** creator and return a handle to it. */ static OSErr FindBundleGivenCreator(OSType creator, BNDLRecHandle *returnBndl) { OSErr error; short numOfBundles; short index; BNDLRecHandle theBndl; error = afpItemNotFound; /* default to not found */ /* Search each BNDL resource until we find the one with a matching creator. */ numOfBundles = Count1Resources(kBNDLResType); index = 1; *returnBndl = NULL; while ( (index <= numOfBundles) && (*returnBndl == NULL) ) { theBndl = (BNDLRecHandle)Get1IndResource(kBNDLResType, index); if ( theBndl != NULL ) { if ( (*theBndl)->signature == creator ) { /* numTypes and typeArray->count will always be the actual count minus 1, */ /* so 0 in both fields is valid. */ if ( ((*theBndl)->numTypes >= 0) && ((*theBndl)->typeArray->count >= 0) ) { /* got it */ *returnBndl = theBndl; error = noErr; } } } index ++; } return ( error ); } /*****************************************************************************/ /* ** FindTypeInBundle ** ** Given a Handle to a BNDL return a pointer to the desired type ** in it. If the type is not found, or if the type's count < 0, ** return afpItemNotFound. */ static OSErr FindTypeInBundle(OSType typeToFind, BNDLRecHandle theBndl, BundleTypePtr *returnBundleType) { OSErr error; short index; Ptr ptrIterator; /* use a Ptr so we can do ugly pointer math */ error = afpItemNotFound; /* default to not found */ ptrIterator = (Ptr)((*theBndl)->typeArray); index = 0; *returnBundleType = NULL; while ( (index < ((*theBndl)->numTypes + 1)) && (*returnBundleType == NULL) ) { if ( (((BundleTypePtr)ptrIterator)->type == typeToFind) && (((BundleTypePtr)ptrIterator)->count >= 0) ) { *returnBundleType = (BundleTypePtr)ptrIterator; error = noErr; } else { ptrIterator += ( sizeof(OSType) + sizeof(short) + ( sizeof(IDRec) * (((BundleTypePtr)ptrIterator)->count + 1) ) ); ++index; } } return ( error ); } /*****************************************************************************/ /* ** GetLocalIDFromFREF ** ** Given a pointer to a 'FREF' BundleType record, load each 'FREF' resource ** looking for a matching fileType. If a matching fileType is found, return ** its icon local ID. If no match is found, return afpItemNotFound as the ** function result. */ static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType, OSType fileType, short *iconLocalID) { OSErr error; short index; IDRecPtr idIterator; FREFRecHandle theFref; error = afpItemNotFound; /* default to not found */ /* For each localID in this type, get the FREF resource looking for fileType */ index = 0; idIterator = &theBundleType->idArray[0]; *iconLocalID = 0; while ( (index <= theBundleType->count) && (*iconLocalID == 0) ) { theFref = (FREFRecHandle)Get1Resource(kFREFResType, idIterator->rsrcID); if ( theFref != NULL ) { if ( (*theFref)->fileType == fileType ) { *iconLocalID = (*theFref)->iconID; error = noErr; } } ++idIterator; ++index; } return ( error ); } /*****************************************************************************/ /* ** GetIconRsrcIDFromLocalID ** ** Given a pointer to a 'ICN#' BundleType record, look for the IDRec with ** the localID that matches iconLocalID. If a matching IDRec is found, ** return the IDRec's rsrcID field value. If no match is found, return ** afpItemNotFound as the function result. */ static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType, short iconLocalID, short *iconRsrcID) { OSErr error; short index; IDRecPtr idIterator; error = afpItemNotFound; /* default to not found */ /* Find the rsrcID of the icon family type, given the localID */ index = 0; idIterator = &theBundleType->idArray[0]; *iconRsrcID = 0; while ( (index <= theBundleType->count) && (*iconRsrcID == 0) ) { if ( idIterator->localID == iconLocalID ) { *iconRsrcID = idIterator->rsrcID; error = noErr; } idIterator ++; index ++; } return ( error ); } /*****************************************************************************/ /* ** DTIconToResIcon ** ** Map a Desktop Manager icon type to the corresponding resource type. ** Return (OSType)0 if there is no corresponding resource type. */ static OSType DTIconToResIcon(short iconType) { OSType resType; switch ( iconType ) { case kLargeIcon: resType = large1BitMask; break; case kLarge4BitIcon: resType = large4BitData; break; case kLarge8BitIcon: resType = large8BitData; break; case kSmallIcon: resType = small1BitMask; break; case kSmall4BitIcon: resType = small4BitData; break; case kSmall8BitIcon: resType = small8BitData; break; default: resType = (OSType)0; break; } return ( resType ); } /*****************************************************************************/ /* ** GetIconFromDesktopFile ** ** INPUT a pointer to a non-existent Handle, because we'll allocate one ** ** search each BNDL resource for the right fileCreator and once we get it ** find the 'FREF' type in BNDL ** for each localID in the type, open the FREF resource ** if the FREF is the desired fileType ** get its icon localID ** get the ICN# type in BNDL ** get the icon resource number from the icon localID ** get the icon resource type from the desktop mgr's iconType ** get the icon of that type and number */ static OSErr GetIconFromDesktopFile(ConstStr255Param volName, short vRefNum, short iconType, OSType fileCreator, OSType fileType, Handle *iconHandle) { OSErr error; short realVRefNum; Str255 desktopName; short savedResFile; short dfRefNum; BNDLRecHandle theBndl = NULL; BundleTypePtr theBundleType; short iconLocalID; short iconRsrcID; OSType iconRsrcType; Handle returnIconHandle; char bndlState; *iconHandle = NULL; error = DetermineVRefNum(volName, vRefNum, &realVRefNum); if ( error == noErr ) { error = GetDesktopFileName(realVRefNum, desktopName); if ( error == noErr ) { savedResFile = CurResFile(); /* ** Open the 'Desktop' file in the root directory. (because ** opening the resource file could preload unwanted resources, ** bracket the call with SetResLoad(s)) */ SetResLoad(false); dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); SetResLoad(true); if ( dfRefNum != -1 ) { /* ** Find the BNDL resource with the specified creator. */ error = FindBundleGivenCreator(fileCreator, &theBndl); if ( error == noErr ) { /* Lock the BNDL resource so it won't be purged when other resources are loaded */ bndlState = HGetState((Handle)theBndl); HLock((Handle)theBndl); /* Find the 'FREF' BundleType record in the BNDL resource. */ error = FindTypeInBundle(kFREFResType, theBndl, &theBundleType); if ( error == noErr ) { /* Find the local ID in the 'FREF' resource with the specified fileType */ error = GetLocalIDFromFREF(theBundleType, fileType, &iconLocalID); if ( error == noErr ) { /* Find the 'ICN#' BundleType record in the BNDL resource. */ error = FindTypeInBundle(kIconFamResType, theBndl, &theBundleType); if ( error == noErr ) { /* Find the icon's resource ID in the 'ICN#' BundleType record */ error = GetIconRsrcIDFromLocalID(theBundleType, iconLocalID, &iconRsrcID); if ( error == noErr ) { /* Map Desktop Manager icon type to resource type */ iconRsrcType = DTIconToResIcon(iconType); if ( iconRsrcType != (OSType)0 ) { /* Load the icon */ returnIconHandle = Get1Resource(iconRsrcType, iconRsrcID); if ( returnIconHandle != NULL ) { /* Copy the resource handle, and return the copy */ HandToHand(&returnIconHandle); if ( MemError() == noErr ) { *iconHandle = returnIconHandle; } else { error = afpItemNotFound; } } else { error = afpItemNotFound; } } } } } } /* Restore the state of the BNDL resource */ HSetState((Handle)theBndl, bndlState); } /* Restore the resource chain and close the Desktop file */ UseResFile(savedResFile); CloseResFile(dfRefNum); } else { error = ResError(); /* could not open Desktop file */ } } if ( (error != noErr) && (error != memFullErr) ) { error = afpItemNotFound; /* force an error we should return */ } } return ( error ); } /*****************************************************************************/ pascal OSErr DTGetIcon(ConstStr255Param volName, short vRefNum, short iconType, OSType fileCreator, OSType fileType, Handle *iconHandle) { OSErr error; DTPBRec pb; short dtRefNum; Boolean newDTDatabase; Size bufferSize; *iconHandle = NULL; error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); if ( error == noErr ) { /* there was a desktop database and it's now open */ if ( !newDTDatabase ) /* don't bother to look in a new (empty) database */ { /* get the buffer size for the requested icon type */ switch ( iconType ) { case kLargeIcon: bufferSize = kLargeIconSize; break; case kLarge4BitIcon: bufferSize = kLarge4BitIconSize; break; case kLarge8BitIcon: bufferSize = kLarge8BitIconSize; break; case kSmallIcon: bufferSize = kSmallIconSize; break; case kSmall4BitIcon: bufferSize = kSmall4BitIconSize; break; case kSmall8BitIcon: bufferSize = kSmall8BitIconSize; break; default: iconType = 0; bufferSize = 0; break; } if ( bufferSize != 0 ) { *iconHandle = NewHandle(bufferSize); if ( *iconHandle != NULL ) { HLock(*iconHandle); pb.ioDTRefNum = dtRefNum; pb.ioTagInfo = 0; pb.ioDTBuffer = **iconHandle; pb.ioDTReqCount = bufferSize; pb.ioIconType = iconType; pb.ioFileCreator = fileCreator; pb.ioFileType = fileType; error = PBDTGetIconSync(&pb); HUnlock(*iconHandle); if ( error != noErr ) { DisposeHandle(*iconHandle); /* dispose of the allocated memory */ *iconHandle = NULL; } } else { error = memFullErr; /* handle could not be allocated */ } } else { error = paramErr; /* unknown icon type requested */ } } else { error = afpItemNotFound; /* the desktop database was empty - nothing to return */ } } else { /* There is no desktop database - try the Desktop file */ error = GetIconFromDesktopFile(volName, vRefNum, iconType, fileCreator, fileType, iconHandle); } return ( error ); } /*****************************************************************************/ pascal OSErr DTSetComment(short vRefNum, long dirID, ConstStr255Param name, ConstStr255Param comment) { DTPBRec pb; OSErr error; short dtRefNum; Boolean newDTDatabase; error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); if ( error == noErr ) { pb.ioDTRefNum = dtRefNum; pb.ioNamePtr = (StringPtr)name; pb.ioDirID = dirID; pb.ioDTBuffer = (Ptr)&comment[1]; /* Truncate the comment to 200 characters just in case */ /* some file system doesn't range check */ if ( comment[0] <= 200 ) { pb.ioDTReqCount = comment[0]; } else { pb.ioDTReqCount = 200; } error = PBDTSetCommentSync(&pb); } return (error); } /*****************************************************************************/ pascal OSErr FSpDTSetComment(const FSSpec *spec, ConstStr255Param comment) { return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment)); } /*****************************************************************************/ /* ** GetCommentID ** ** Get the comment ID number for the Desktop file's 'FCMT' resource ID from ** the file or folders fdComment (frComment) field. */ static OSErr GetCommentID(short vRefNum, long dirID, ConstStr255Param name, short *commentID) { CInfoPBRec pb; OSErr error; error = GetCatInfoNoName(vRefNum, dirID, name, &pb); *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment; return ( error ); } /*****************************************************************************/ /* ** GetCommentFromDesktopFile ** ** Get a file or directory's Finder comment field (if any) from the ** Desktop file's 'FCMT' resources. */ static OSErr GetCommentFromDesktopFile(short vRefNum, long dirID, ConstStr255Param name, Str255 comment) { OSErr error; short commentID; short realVRefNum; Str255 desktopName; short savedResFile; short dfRefNum; StringHandle commentHandle; /* Get the comment ID number */ error = GetCommentID(vRefNum, dirID, name, &commentID); if ( error == noErr ) { if ( commentID != 0 ) /* commentID == 0 means there's no comment */ { error = DetermineVRefNum(name, vRefNum, &realVRefNum); if ( error == noErr ) { error = GetDesktopFileName(realVRefNum, desktopName); if ( error == noErr ) { savedResFile = CurResFile(); /* ** Open the 'Desktop' file in the root directory. (because ** opening the resource file could preload unwanted resources, ** bracket the call with SetResLoad(s)) */ SetResLoad(false); dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm); SetResLoad(true); if ( dfRefNum != -1) { /* Get the comment resource */ commentHandle = (StringHandle)Get1Resource(kFCMTResType,commentID); if ( commentHandle != NULL ) { if ( GetHandleSize((Handle)commentHandle) > 0 ) { BlockMoveData(*commentHandle, comment, *commentHandle[0] + 1); } else { error = afpItemNotFound; /* no comment available */ } } else { error = afpItemNotFound; /* no comment available */ } /* restore the resource chain and close the Desktop file */ UseResFile(savedResFile); CloseResFile(dfRefNum); } else { error = afpItemNotFound; } } else { error = afpItemNotFound; } } } else { error = afpItemNotFound; /* no comment available */ } } return ( error ); } /*****************************************************************************/ pascal OSErr DTGetComment(short vRefNum, long dirID, ConstStr255Param name, Str255 comment) { DTPBRec pb; OSErr error; short dtRefNum; Boolean newDTDatabase; if (comment != NULL) { comment[0] = 0; /* return nothing by default */ /* attempt to open the desktop database */ error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase); if ( error == noErr ) { /* There was a desktop database and it's now open */ if ( !newDTDatabase ) { pb.ioDTRefNum = dtRefNum; pb.ioNamePtr = (StringPtr)name; pb.ioDirID = dirID; pb.ioDTBuffer = (Ptr)&comment[1]; /* ** IMPORTANT NOTE #1: Inside Macintosh says that comments ** are up to 200 characters. While that may be correct for ** the HFS file system's Desktop Manager, other file ** systems (such as Apple Photo Access) return up to ** 255 characters. Make sure the comment buffer is a Str255 ** or you'll regret it. ** ** IMPORTANT NOTE #2: Although Inside Macintosh doesn't ** mention it, ioDTReqCount is a input field to ** PBDTGetCommentSync. Some file systems (like HFS) ignore ** ioDTReqCount and always return the full comment -- ** others (like AppleShare) respect ioDTReqCount and only ** return up to ioDTReqCount characters of the comment. */ pb.ioDTReqCount = sizeof(Str255) - 1; error = PBDTGetCommentSync(&pb); if (error == noErr) { comment[0] = (unsigned char)pb.ioDTActCount; } } } else { /* There is no desktop database - try the Desktop file */ error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment); if ( error != noErr ) { error = afpItemNotFound; /* return an expected error */ } } } else { error = paramErr; } return (error); } /*****************************************************************************/ pascal OSErr FSpDTGetComment(const FSSpec *spec, Str255 comment) { return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment)); } /*****************************************************************************/ pascal OSErr DTCopyComment(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName) /* The destination volume must support the Desktop Manager for this to work */ { OSErr error; Str255 comment; error = DTGetComment(srcVRefNum, srcDirID, srcName, comment); if ( (error == noErr) && (comment[0] > 0) ) { error = DTSetComment(dstVRefNum, dstDirID, dstName, comment); } return (error); } /*****************************************************************************/ pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec, const FSSpec *dstSpec) /* The destination volume must support the Desktop Manager for this to work */ { return (DTCopyComment(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name)); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/MoreFiles.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** The long lost high-level and FSSpec File Manager functions. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: MoreFiles.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" /*****************************************************************************/ pascal OSErr HGetVolParms(ConstStr255Param volName, short vRefNum, GetVolParmsInfoBuffer *volParmsInfo, long *infoSize) { HParamBlockRec pb; OSErr error; pb.ioParam.ioNamePtr = (StringPtr)volName; pb.ioParam.ioVRefNum = vRefNum; pb.ioParam.ioBuffer = (Ptr)volParmsInfo; pb.ioParam.ioReqCount = *infoSize; error = PBHGetVolParmsSync(&pb); if ( error == noErr ) { *infoSize = pb.ioParam.ioActCount; } return ( error ); } /*****************************************************************************/ pascal OSErr HCreateMinimum(short vRefNum, long dirID, ConstStr255Param fileName) { HParamBlockRec pb; pb.fileParam.ioNamePtr = (StringPtr)fileName; pb.fileParam.ioVRefNum = vRefNum; pb.ioParam.ioVersNum = 0; pb.fileParam.ioDirID = dirID; return ( PBHCreateSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpCreateMinimum(const FSSpec *spec) { return ( HCreateMinimum(spec->vRefNum, spec->parID, spec->name) ); } /*****************************************************************************/ pascal OSErr ExchangeFiles(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstName) { HParamBlockRec pb; pb.fidParam.ioVRefNum = vRefNum; pb.fidParam.ioSrcDirID = srcDirID; pb.fidParam.ioNamePtr = (StringPtr)srcName; pb.fidParam.ioDestDirID = dstDirID; pb.fidParam.ioDestNamePtr = (StringPtr)dstName; return ( PBExchangeFilesSync(&pb) ); } /*****************************************************************************/ pascal OSErr ResolveFileIDRef(ConstStr255Param volName, short vRefNum, long fileID, long *parID, StringPtr fileName) { HParamBlockRec pb; OSErr error; Str255 tempStr; tempStr[0] = 0; if ( volName != NULL ) { BlockMoveData(volName, tempStr, volName[0] + 1); } pb.fidParam.ioNamePtr = (StringPtr)tempStr; pb.fidParam.ioVRefNum = vRefNum; pb.fidParam.ioFileID = fileID; error = PBResolveFileIDRefSync(&pb); if ( error == noErr ) { *parID = pb.fidParam.ioSrcDirID; if ( fileName != NULL ) { BlockMoveData(tempStr, fileName, tempStr[0] + 1); } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpResolveFileIDRef(ConstStr255Param volName, short vRefNum, long fileID, FSSpec *spec) { OSErr error; error = DetermineVRefNum(volName, vRefNum, &(spec->vRefNum)); if ( error == noErr ) { error = ResolveFileIDRef(volName, vRefNum, fileID, &(spec->parID), spec->name); } return ( error ); } /*****************************************************************************/ pascal OSErr CreateFileIDRef(short vRefNum, long parID, ConstStr255Param fileName, long *fileID) { HParamBlockRec pb; OSErr error; pb.fidParam.ioNamePtr = (StringPtr)fileName; pb.fidParam.ioVRefNum = vRefNum; pb.fidParam.ioSrcDirID = parID; error = PBCreateFileIDRefSync(&pb); if ( (error == noErr) || (error == fidExists) || (error == afpIDExists) ) { *fileID = pb.fidParam.ioFileID; } return ( error ); } /*****************************************************************************/ pascal OSErr FSpCreateFileIDRef(const FSSpec *spec, long *fileID) { return ( CreateFileIDRef(spec->vRefNum, spec->parID, spec->name, fileID) ); } /*****************************************************************************/ pascal OSErr DeleteFileIDRef(ConstStr255Param volName, short vRefNum, long fileID) { HParamBlockRec pb; pb.fidParam.ioNamePtr = (StringPtr)volName; pb.fidParam.ioVRefNum = vRefNum; pb.fidParam.ioFileID = fileID; return ( PBDeleteFileIDRefSync(&pb) ); } /*****************************************************************************/ pascal OSErr FlushFile(short refNum) { ParamBlockRec pb; pb.ioParam.ioRefNum = refNum; return ( PBFlushFileSync(&pb) ); } /*****************************************************************************/ pascal OSErr LockRange(short refNum, long rangeLength, long rangeStart) { ParamBlockRec pb; pb.ioParam.ioRefNum = refNum; pb.ioParam.ioReqCount = rangeLength; pb.ioParam.ioPosMode = fsFromStart; pb.ioParam.ioPosOffset = rangeStart; return ( PBLockRangeSync(&pb) ); } /*****************************************************************************/ pascal OSErr UnlockRange(short refNum, long rangeLength, long rangeStart) { ParamBlockRec pb; pb.ioParam.ioRefNum = refNum; pb.ioParam.ioReqCount = rangeLength; pb.ioParam.ioPosMode = fsFromStart; pb.ioParam.ioPosOffset = rangeStart; return ( PBUnlockRangeSync(&pb) ); } /*****************************************************************************/ pascal OSErr GetForeignPrivs(short vRefNum, long dirID, ConstStr255Param name, void *foreignPrivBuffer, long *foreignPrivSize, long *foreignPrivInfo1, long *foreignPrivInfo2, long *foreignPrivInfo3, long *foreignPrivInfo4) { HParamBlockRec pb; OSErr error; pb.foreignPrivParam.ioNamePtr = (StringPtr)name; pb.foreignPrivParam.ioVRefNum = vRefNum; pb.foreignPrivParam.ioForeignPrivDirID = dirID; pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer; pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize; error = PBGetForeignPrivsSync(&pb); *foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount; *foreignPrivInfo1 = pb.foreignPrivParam.ioForeignPrivInfo1; *foreignPrivInfo2 = pb.foreignPrivParam.ioForeignPrivInfo2; *foreignPrivInfo3 = pb.foreignPrivParam.ioForeignPrivInfo3; *foreignPrivInfo4 = pb.foreignPrivParam.ioForeignPrivInfo4; return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetForeignPrivs(const FSSpec *spec, void *foreignPrivBuffer, long *foreignPrivSize, long *foreignPrivInfo1, long *foreignPrivInfo2, long *foreignPrivInfo3, long *foreignPrivInfo4) { return ( GetForeignPrivs(spec->vRefNum, spec->parID, spec->name, foreignPrivBuffer, foreignPrivSize, foreignPrivInfo1, foreignPrivInfo2, foreignPrivInfo3, foreignPrivInfo4) ); } /*****************************************************************************/ pascal OSErr SetForeignPrivs(short vRefNum, long dirID, ConstStr255Param name, const void *foreignPrivBuffer, long *foreignPrivSize, long foreignPrivInfo1, long foreignPrivInfo2, long foreignPrivInfo3, long foreignPrivInfo4) { HParamBlockRec pb; OSErr error; pb.foreignPrivParam.ioNamePtr = (StringPtr)name; pb.foreignPrivParam.ioVRefNum = vRefNum; pb.foreignPrivParam.ioForeignPrivDirID = dirID; pb.foreignPrivParam.ioForeignPrivBuffer = (Ptr)foreignPrivBuffer; pb.foreignPrivParam.ioForeignPrivReqCount = *foreignPrivSize; pb.foreignPrivParam.ioForeignPrivInfo1 = foreignPrivInfo1; pb.foreignPrivParam.ioForeignPrivInfo2 = foreignPrivInfo2; pb.foreignPrivParam.ioForeignPrivInfo3 = foreignPrivInfo3; pb.foreignPrivParam.ioForeignPrivInfo4 = foreignPrivInfo4; error = PBSetForeignPrivsSync(&pb); if ( error == noErr ) { *foreignPrivSize = pb.foreignPrivParam.ioForeignPrivActCount; } return ( error ); } /*****************************************************************************/ pascal OSErr FSpSetForeignPrivs(const FSSpec *spec, const void *foreignPrivBuffer, long *foreignPrivSize, long foreignPrivInfo1, long foreignPrivInfo2, long foreignPrivInfo3, long foreignPrivInfo4) { return ( SetForeignPrivs(spec->vRefNum, spec->parID, spec->name, foreignPrivBuffer, foreignPrivSize, foreignPrivInfo1, foreignPrivInfo2, foreignPrivInfo3, foreignPrivInfo4) ); } /*****************************************************************************/ pascal OSErr HGetLogInInfo(ConstStr255Param volName, short vRefNum, short *loginMethod, StringPtr userName) { HParamBlockRec pb; OSErr error; pb.objParam.ioNamePtr = (StringPtr)volName; pb.objParam.ioVRefNum = vRefNum; pb.objParam.ioObjNamePtr = userName; error = PBHGetLogInInfoSync(&pb); if ( error == noErr ) { *loginMethod = pb.objParam.ioObjType; } return ( error ); } /*****************************************************************************/ pascal OSErr HGetDirAccess(short vRefNum, long dirID, ConstStr255Param name, long *ownerID, long *groupID, long *accessRights) { HParamBlockRec pb; OSErr error; pb.accessParam.ioNamePtr = (StringPtr)name; pb.accessParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; error = PBHGetDirAccessSync(&pb); if ( error == noErr ) { *ownerID = pb.accessParam.ioACOwnerID; *groupID = pb.accessParam.ioACGroupID; *accessRights = pb.accessParam.ioACAccess; } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetDirAccess(const FSSpec *spec, long *ownerID, long *groupID, long *accessRights) { return ( HGetDirAccess(spec->vRefNum, spec->parID, spec->name, ownerID, groupID, accessRights) ); } /*****************************************************************************/ pascal OSErr HSetDirAccess(short vRefNum, long dirID, ConstStr255Param name, long ownerID, long groupID, long accessRights) { HParamBlockRec pb; pb.accessParam.ioNamePtr = (StringPtr)name; pb.accessParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; pb.accessParam.ioACOwnerID = ownerID; pb.accessParam.ioACGroupID = groupID; pb.accessParam.ioACAccess = accessRights; return ( PBHSetDirAccessSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpSetDirAccess(const FSSpec *spec, long ownerID, long groupID, long accessRights) { return ( HSetDirAccess(spec->vRefNum, spec->parID, spec->name, ownerID, groupID, accessRights) ); } /*****************************************************************************/ pascal OSErr HMapID(ConstStr255Param volName, short vRefNum, long ugID, short objType, StringPtr name) { HParamBlockRec pb; pb.objParam.ioNamePtr = (StringPtr)volName; pb.objParam.ioVRefNum = vRefNum; pb.objParam.ioObjType = objType; pb.objParam.ioObjNamePtr = name; pb.objParam.ioObjID = ugID; return ( PBHMapIDSync(&pb) ); } /*****************************************************************************/ pascal OSErr HMapName(ConstStr255Param volName, short vRefNum, ConstStr255Param name, short objType, long *ugID) { HParamBlockRec pb; OSErr error; pb.objParam.ioNamePtr = (StringPtr)volName; pb.objParam.ioVRefNum = vRefNum; pb.objParam.ioObjType = objType; pb.objParam.ioObjNamePtr = (StringPtr)name; error = PBHMapNameSync(&pb); if ( error == noErr ) { *ugID = pb.objParam.ioObjID; } return ( error ); } /*****************************************************************************/ pascal OSErr HCopyFile(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstPathname, ConstStr255Param copyName) { HParamBlockRec pb; pb.copyParam.ioVRefNum = srcVRefNum; pb.copyParam.ioDirID = srcDirID; pb.copyParam.ioNamePtr = (StringPtr)srcName; pb.copyParam.ioDstVRefNum = dstVRefNum; pb.copyParam.ioNewDirID = dstDirID; pb.copyParam.ioNewName = (StringPtr)dstPathname; pb.copyParam.ioCopyName = (StringPtr)copyName; return ( PBHCopyFileSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpCopyFile(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName) { return ( HCopyFile(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name, copyName) ); } /*****************************************************************************/ pascal OSErr HMoveRename(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstpathName, ConstStr255Param copyName) { HParamBlockRec pb; pb.copyParam.ioVRefNum = vRefNum; pb.copyParam.ioDirID = srcDirID; pb.copyParam.ioNamePtr = (StringPtr)srcName; pb.copyParam.ioNewDirID = dstDirID; pb.copyParam.ioNewName = (StringPtr)dstpathName; pb.copyParam.ioCopyName = (StringPtr)copyName; return ( PBHMoveRenameSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpMoveRename(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName) { OSErr error; /* make sure the FSSpecs refer to the same volume */ if ( srcSpec->vRefNum != dstSpec->vRefNum ) { error = diffVolErr; } else { error = HMoveRename(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->parID, dstSpec->name, copyName); } return ( error ); } /*****************************************************************************/ pascal OSErr GetVolMountInfoSize(ConstStr255Param volName, short vRefNum, short *size) { ParamBlockRec pb; pb.ioParam.ioNamePtr = (StringPtr)volName; pb.ioParam.ioVRefNum = vRefNum; pb.ioParam.ioBuffer = (Ptr)size; return ( PBGetVolMountInfoSize(&pb) ); } /*****************************************************************************/ pascal OSErr GetVolMountInfo(ConstStr255Param volName, short vRefNum, void *volMountInfo) { ParamBlockRec pb; pb.ioParam.ioNamePtr = (StringPtr)volName; pb.ioParam.ioVRefNum = vRefNum; pb.ioParam.ioBuffer = (Ptr)volMountInfo; return ( PBGetVolMountInfo(&pb) ); } /*****************************************************************************/ pascal OSErr VolumeMount(const void *volMountInfo, short *vRefNum) { ParamBlockRec pb; OSErr error; pb.ioParam.ioBuffer = (Ptr)volMountInfo; error = PBVolumeMount(&pb); if ( error == noErr ) { *vRefNum = pb.ioParam.ioVRefNum; } return ( error ); } /*****************************************************************************/ pascal OSErr Share(short vRefNum, long dirID, ConstStr255Param name) { HParamBlockRec pb; pb.fileParam.ioNamePtr = (StringPtr)name; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; return ( PBShareSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpShare(const FSSpec *spec) { return ( Share(spec->vRefNum, spec->parID, spec->name) ); } /*****************************************************************************/ pascal OSErr Unshare(short vRefNum, long dirID, ConstStr255Param name) { HParamBlockRec pb; pb.fileParam.ioNamePtr = (StringPtr)name; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; return ( PBUnshareSync(&pb) ); } /*****************************************************************************/ pascal OSErr FSpUnshare(const FSSpec *spec) { return ( Unshare(spec->vRefNum, spec->parID, spec->name) ); } /*****************************************************************************/ pascal OSErr GetUGEntry(short objType, StringPtr objName, long *objID) { HParamBlockRec pb; OSErr error; pb.objParam.ioObjType = objType; pb.objParam.ioObjNamePtr = objName; pb.objParam.ioObjID = *objID; error = PBGetUGEntrySync(&pb); if ( error == noErr ) { *objID = pb.objParam.ioObjID; } return ( error ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/MoreFilesExtras.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** A collection of useful high-level File Manager routines. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: MoreFilesExtras.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "MoreDesktopMgr.h" #include "FSpCompat.h" /*****************************************************************************/ /* local data structures */ /* The DeleteEnumGlobals structure is used to minimize the amount of ** stack space used when recursively calling DeleteLevel and to hold ** global information that might be needed at any time. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif // PRAGMA_STRUCT_ALIGN struct DeleteEnumGlobals { OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */ Str63 itemName; /* the name of the current item */ UniversalFMPB myPB; /* the parameter block used for PBGetCatInfo calls */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif // PRAGMA_STRUCT_ALIGN typedef struct DeleteEnumGlobals DeleteEnumGlobals; typedef DeleteEnumGlobals *DeleteEnumGlobalsPtr; /*****************************************************************************/ /* ** CallPBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync ** File Manager requests from CFM-based programs. Apple added PBXGetVolInfoSync ** to InterfaceLib in Mac OS 8.5, so if __MACOSEIGHTFIVEORLATER is defined, ** CallPBXGetVolInfoSync is defined back to PBXGetVolInfoSync. ** ** Non-CFM 68K programs don't needs this glue (and won't get it) because ** they instead use the inline assembly glue found in the Files.h interface ** file. */ #if TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM // Carbon builds and 68K builds don't need this glue #define CallPBXGetVolInfoSync PBXGetVolInfoSync #else // TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM #if __WANTPASCALELIMINATION #undef pascal #endif // __WANTPASCALELIMINATION /* This is exactly like the simple mixed mode glue in InterfaceLib in Mac OS 8.5 and 8.6 */ static pascal OSErr PBXGetVolInfoSyncGlue(XVolumeParamPtr paramBlock) { enum { uppFSDispatchProcInfo = kRegisterBased | REGISTER_RESULT_LOCATION(kRegisterD0) | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(long))) /* selector */ | REGISTER_ROUTINE_PARAMETER(2, kRegisterD1, SIZE_CODE(sizeof(long))) /* trap word */ | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr))) }; static UniversalProcPtr fsDispatchTrapAddress = NULL; /* Is this the first time we've been called? */ if ( fsDispatchTrapAddress == NULL ) { /* Yes - Get the trap address of _FSDispatch */ fsDispatchTrapAddress = NGetTrapAddress(_FSDispatch, OSTrap); } return ( CallOSTrapUniversalProc(fsDispatchTrapAddress, uppFSDispatchProcInfo, kFSMXGetVolInfo, _FSDispatch, paramBlock) ); } /* ** PBXGetVolInfoSync was added to the File Manager in System software 7.5.2. ** However, PBXGetVolInfoSync wasn't added to InterfaceLib until Mac OS 8.5. ** This wrapper calls PBXGetVolInfoSync if it is found in InterfaceLib; ** otherwise, it calls PBXGetVolInfoSyncGlue. This ensures that your program ** is calling the latest implementation of PBXGetVolInfoSync. */ static pascal OSErr CallPBXGetVolInfoSync(XVolumeParamPtr paramBlock) { typedef pascal OSErr (*PBXGetVolInfoProcPtr) (XVolumeParamPtr paramBlock); OSErr result; CFragConnectionID connID; static PBXGetVolInfoProcPtr PBXGetVolInfoSyncPtr = NULL; //* Is this the first time we've been called? */ if ( PBXGetVolInfoSyncPtr == NULL ) { /* Yes - Get our connection ID to InterfaceLib */ result = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kLoadCFrag, &connID, NULL, NULL); if ( result == noErr ) { /* See if PBXGetVolInfoSync is in InterfaceLib */ if ( FindSymbol(connID, "\pPBXGetVolInfoSync", &(Ptr)PBXGetVolInfoSyncPtr, NULL) != noErr ) { /* Use glue code if symbol isn't found */ PBXGetVolInfoSyncPtr = PBXGetVolInfoSyncGlue; } } } /* Call PBXGetVolInfoSync if present; otherwise, call PBXGetVolInfoSyncGlue */ return ( (*PBXGetVolInfoSyncPtr)(paramBlock) ); } #if __WANTPASCALELIMINATION #define pascal #endif // __WANTPASCALELIMINATION #endif // TARGET_API_MAC_CARBON || !TARGET_RT_MAC_CFM /*****************************************************************************/ pascal void TruncPString(StringPtr destination, ConstStr255Param source, short maxLength) { short charType; if ( source != NULL && destination != NULL ) /* don't do anything stupid */ { if ( source[0] > maxLength ) { /* Make sure the string isn't truncated in the middle of */ /* a multi-byte character. */ while (maxLength != 0) { // Note: CharacterByteType's textOffset parameter is zero-based from the textPtr parameter charType = CharacterByteType((Ptr)&source[1], maxLength - 1, smSystemScript); if ( (charType == smSingleByte) || (charType == smLastByte) ) break; /* source[maxLength] is now a valid last character */ --maxLength; } } else { maxLength = source[0]; } /* Set the destination string length */ destination[0] = maxLength; /* and copy maxLength characters (if needed) */ if ( source != destination ) { while ( maxLength != 0 ) { destination[maxLength] = source[maxLength]; --maxLength; } } } } /*****************************************************************************/ pascal Ptr GetTempBuffer(long buffReqSize, long *buffActSize) { enum { kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */ }; Ptr tempPtr; /* Make request a multiple of 1024 bytes */ buffReqSize = buffReqSize & 0xfffffc00; if ( buffReqSize < 0x00000400 ) { /* Request was smaller than 1024 bytes - make it 1024 */ buffReqSize = 0x00000400; } /* Attempt to allocate the memory */ tempPtr = NewPtr(buffReqSize); /* If request failed, go to backup plan */ if ( (tempPtr == NULL) && (buffReqSize > 0x00000400) ) { /* ** Try to get largest 1024-byte block available ** leaving some slop for the toolbox if possible */ long freeMemory = (FreeMem() - kSlopMemory) & 0xfffffc00; buffReqSize = MaxBlock() & 0xfffffc00; if ( buffReqSize > freeMemory ) { buffReqSize = freeMemory; } if ( buffReqSize == 0 ) { buffReqSize = 0x00000400; } tempPtr = NewPtr(buffReqSize); } /* Return bytes allocated */ if ( tempPtr != NULL ) { *buffActSize = buffReqSize; } else { *buffActSize = 0; } return ( tempPtr ); } /*****************************************************************************/ /* ** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync ** in cases where the returned volume name is not needed by the caller. ** The pathname and vRefNum parameters are not touched, and the pb ** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in ** the parameter block is always returned as NULL (since it might point ** to the local tempPathname). ** ** I noticed using this code in several places, so here it is once. ** This reduces the code size of MoreFiles. */ pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, short vRefNum, HParmBlkPtr pb) { Str255 tempPathname; OSErr error; /* Make sure pb parameter is not NULL */ if ( pb != NULL ) { pb->volumeParam.ioVRefNum = vRefNum; if ( pathname == NULL ) { pb->volumeParam.ioNamePtr = NULL; pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */ } else { BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ } error = PBHGetVInfoSync(pb); pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ } else { error = paramErr; } return ( error ); } /*****************************************************************************/ /* ** XGetVolumeInfoNoName uses pathname and vRefNum to call PBXGetVolInfoSync ** in cases where the returned volume name is not needed by the caller. ** The pathname and vRefNum parameters are not touched, and the pb ** parameter is initialized by PBXGetVolInfoSync except that ioNamePtr in ** the parameter block is always returned as NULL (since it might point ** to the local tempPathname). */ pascal OSErr XGetVolumeInfoNoName(ConstStr255Param pathname, short vRefNum, XVolumeParamPtr pb) { Str255 tempPathname; OSErr error; /* Make sure pb parameter is not NULL */ if ( pb != NULL ) { pb->ioVRefNum = vRefNum; pb->ioXVersion = 0; /* this XVolumeParam version (0) */ if ( pathname == NULL ) { pb->ioNamePtr = NULL; pb->ioVolIndex = 0; /* use ioVRefNum only */ } else { BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ pb->ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ pb->ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ } { #if !TARGET_API_MAC_CARBON long response; /* Is PBXGetVolInfo available? */ if ( ( Gestalt(gestaltFSAttr, &response) != noErr ) || ((response & (1L << gestaltFSSupports2TBVols)) == 0) ) { /* No, fall back on PBHGetVInfo */ error = PBHGetVInfoSync((HParmBlkPtr)pb); if ( error == noErr ) { /* calculate the ioVTotalBytes and ioVFreeBytes fields */ pb->ioVTotalBytes = U64Multiply(U64SetU(pb->ioVNmAlBlks), U64SetU(pb->ioVAlBlkSiz)); pb->ioVFreeBytes = U64Multiply(U64SetU(pb->ioVFrBlk), U64SetU(pb->ioVAlBlkSiz)); } } else #endif { /* Yes, so use it */ error = CallPBXGetVolInfoSync(pb); } } pb->ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ } else { error = paramErr; } return ( error ); } /*****************************************************************************/ pascal OSErr GetCatInfoNoName(short vRefNum, long dirID, ConstStr255Param name, CInfoPBPtr pb) { Str31 tempName; OSErr error; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb->dirInfo.ioNamePtr = tempName; pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb->dirInfo.ioNamePtr = (StringPtr)name; pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb->dirInfo.ioVRefNum = vRefNum; pb->dirInfo.ioDrDirID = dirID; error = PBGetCatInfoSync(pb); pb->dirInfo.ioNamePtr = NULL; return ( error ); } /*****************************************************************************/ pascal OSErr DetermineVRefNum(ConstStr255Param pathname, short vRefNum, short *realVRefNum) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname,vRefNum, &pb); if ( error == noErr ) { *realVRefNum = pb.volumeParam.ioVRefNum; } return ( error ); } /*****************************************************************************/ pascal OSErr HGetVInfo(short volReference, StringPtr volName, short *vRefNum, unsigned long *freeBytes, unsigned long *totalBytes) { OSErr result; UInt64 freeBytes64; UInt64 totalBytes64; // get the best values possible from XGetVInfo result = XGetVInfo(volReference, volName, vRefNum, &freeBytes64, &totalBytes64); if ( result == noErr ) { // and pin those values if needed if ( UInt64ToUnsignedWide(freeBytes64).hi != 0 ) { // pin to maximum 512-byte block aligned value *freeBytes = 0xfffffe00; } else { *freeBytes = U32SetU(freeBytes64); } if ( UInt64ToUnsignedWide(totalBytes64).hi != 0 ) { // pin to maximum 512-byte block aligned value *totalBytes = 0xfffffe00; } else { *totalBytes = U32SetU(totalBytes64); } } return ( result ); } /*****************************************************************************/ pascal OSErr XGetVInfo(short volReference, StringPtr volName, short *vRefNum, UInt64 *freeBytes, UInt64 *totalBytes) { OSErr result; XVolumeParam pb; #if !TARGET_API_MAC_CARBON long response; #endif // !TARGET_API_MAC_CARBON pb.ioVRefNum = volReference; pb.ioNamePtr = volName; pb.ioXVersion = 0; /* this XVolumeParam version (0) */ pb.ioVolIndex = 0; /* use ioVRefNum only, return volume name */ #if !TARGET_API_MAC_CARBON /* See if large volume support is available */ if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) ) #endif // !TARGET_API_MAC_CARBON { /* Large volume support is available */ result = CallPBXGetVolInfoSync(&pb); if ( result == noErr ) { /* The volume name was returned in volName (if not NULL) and */ /* we have the volume's vRefNum and allocation block size */ *vRefNum = pb.ioVRefNum; /* return the freeBytes and totalBytes */ *totalBytes = pb.ioVTotalBytes; *freeBytes = pb.ioVFreeBytes; } } #if !TARGET_API_MAC_CARBON else { /* No large volume support */ /* Use PBHGetVInfoSync to get the results */ result = PBHGetVInfoSync((HParmBlkPtr)&pb); if ( result == noErr ) { VCB *theVCB; /* The volume name was returned in volName (if not NULL) and */ /* we have the volume's vRefNum */ *vRefNum = pb.ioVRefNum; /* System 7.5 (and beyond) pins the number of allocation blocks and */ /* the number of free allocation blocks returned by PBHGetVInfo to */ /* a value so that when multiplied by the allocation block size, */ /* the volume will look like it has $7fffffff bytes or less. This */ /* was done so older applications that use signed math or that use */ /* the GetVInfo function (which uses signed math) will continue to work. */ /* However, the unpinned numbers (which we want) are always available */ /* in the volume's VCB so we'll get those values from the VCB. */ /* Note: Carbon doesn't support the VCB queue, so this code cannot be */ /* used (and is conditionalized out) by Carbon applications. */ /* Find the volume's VCB */ theVCB = (VCB *)(GetVCBQHdr()->qHead); while ( theVCB != NULL ) { if ( theVCB->vcbVRefNum == *vRefNum ) { break; } theVCB = (VCB *)(theVCB->qLink); /* next VCB */ } if ( theVCB != NULL ) { /* Found a VCB we can use. Get the un-pinned number of allocation blocks */ /* and the number of free blocks from the VCB. */ *freeBytes = U64Multiply(U64SetU((unsigned short)theVCB->vcbFreeBks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); *totalBytes = U64Multiply(U64SetU((unsigned short)theVCB->vcbNmAlBlks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); } else { /* Didn't find a VCB we can use. Return the number of allocation blocks */ /* and the number of free blocks returned by PBHGetVInfoSync. */ *freeBytes = U64Multiply(U64SetU((unsigned short)pb.ioVFrBlk), U64SetU((unsigned long)pb.ioVAlBlkSiz)); *totalBytes = U64Multiply(U64SetU((unsigned short)pb.ioVNmAlBlks), U64SetU((unsigned long)pb.ioVAlBlkSiz)); } } } #endif // !TARGET_API_MAC_CARBON return ( result ); } /*****************************************************************************/ pascal OSErr CheckVolLock(ConstStr255Param pathname, short vRefNum) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname,vRefNum, &pb); if ( error == noErr ) { if ( (pb.volumeParam.ioVAtrb & kHFSVolumeHardwareLockMask) != 0 ) { error = wPrErr; /* volume locked by hardware */ } else if ( (pb.volumeParam.ioVAtrb & kHFSVolumeSoftwareLockMask) != 0 ) { error = vLckdErr; /* volume locked by software */ } } return ( error ); } /*****************************************************************************/ // // The following routines call Mac OS routines that are not supported by // Carbon: // // GetDriverName // FindDrive // GetDiskBlocks // GetVolState #if !TARGET_API_MAC_CARBON // { /*****************************************************************************/ pascal OSErr GetDriverName(short driverRefNum, Str255 driverName) { OSErr result; DCtlHandle theDctl; DRVRHeaderPtr dHeaderPtr; theDctl = GetDCtlEntry(driverRefNum); if ( theDctl != NULL ) { if ( (**theDctl).dCtlFlags & dRAMBasedMask ) { /* dctlDriver is handle - dereference */ dHeaderPtr = *((DRVRHeaderHandle)(**theDctl).dCtlDriver); } else { /* dctlDriver is pointer */ dHeaderPtr = (DRVRHeaderPtr)(**theDctl).dCtlDriver; } BlockMoveData((*dHeaderPtr).drvrName, driverName, (*dHeaderPtr).drvrName[0] + 1); result = noErr; } else { driverName[0] = 0; result = badUnitErr; /* bad reference number */ } return ( result ); } /*****************************************************************************/ pascal OSErr FindDrive(ConstStr255Param pathname, short vRefNum, DrvQElPtr *driveQElementPtr) { OSErr result; HParamBlockRec hPB; short driveNumber; *driveQElementPtr = NULL; /* First, use GetVolumeInfoNoName to determine the volume */ result = GetVolumeInfoNoName(pathname, vRefNum, &hPB); if ( result == noErr ) { /* ** The volume can be either online, offline, or ejected. What we find in ** ioVDrvInfo and ioVDRefNum will tell us which it is. ** See Inside Macintosh: Files page 2-80 and the Technical Note ** "FL 34 - VCBs and Drive Numbers : The Real Story" ** Where we get the drive number depends on the state of the volume. */ if ( hPB.volumeParam.ioVDrvInfo != 0 ) { /* The volume is online and not ejected */ /* Get the drive number */ driveNumber = hPB.volumeParam.ioVDrvInfo; } else { /* The volume's is either offline or ejected */ /* in either case, the volume is NOT online */ /* Is it ejected or just offline? */ if ( hPB.volumeParam.ioVDRefNum > 0 ) { /* It's ejected, the drive number is ioVDRefNum */ driveNumber = hPB.volumeParam.ioVDRefNum; } else { /* It's offline, the drive number is the negative of ioVDRefNum */ driveNumber = (short)-hPB.volumeParam.ioVDRefNum; } } /* Get pointer to first element in drive queue */ *driveQElementPtr = (DrvQElPtr)(GetDrvQHdr()->qHead); /* Search for a matching drive number */ while ( (*driveQElementPtr != NULL) && ((*driveQElementPtr)->dQDrive != driveNumber) ) { *driveQElementPtr = (DrvQElPtr)(*driveQElementPtr)->qLink; } if ( *driveQElementPtr == NULL ) { /* This should never happen since every volume must have a drive, but... */ result = nsDrvErr; } } return ( result ); } /*****************************************************************************/ pascal OSErr GetDiskBlocks(ConstStr255Param pathname, short vRefNum, unsigned long *numBlocks) { /* Various constants for GetDiskBlocks() */ enum { /* return format list status code */ kFmtLstCode = 6, /* reference number of .SONY driver */ kSonyRefNum = 0xfffb, /* values returned by DriveStatus in DrvSts.twoSideFmt */ kSingleSided = 0, kDoubleSided = -1, kSingleSidedSize = 800, /* 400K */ kDoubleSidedSize = 1600, /* 800K */ /* values in DrvQEl.qType */ kWordDrvSiz = 0, kLongDrvSiz = 1, /* more than enough formatListRecords */ kMaxFormatListRecs = 16 }; DrvQElPtr driveQElementPtr; unsigned long blocks; ParamBlockRec pb; FormatListRec formatListRecords[kMaxFormatListRecs]; DrvSts status; short formatListRecIndex; OSErr result; blocks = 0; /* Find the drive queue element for this volume */ result = FindDrive(pathname, vRefNum, &driveQElementPtr); /* ** Make sure this is a real driver (dQRefNum < 0). ** AOCE's Mail Enclosures volume uses 0 for dQRefNum which will cause ** problems if you try to use it as a driver refNum. */ if ( (result == noErr) && (driveQElementPtr->dQRefNum >= 0) ) { result = paramErr; } else { /* Attempt to get the drive's format list. */ /* (see the Technical Note "What Your Sony Drives For You") */ pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive; pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum; pb.cntrlParam.csCode = kFmtLstCode; pb.cntrlParam.csParam[0] = kMaxFormatListRecs; *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0]; result = PBStatusSync(&pb); if ( result == noErr ) { /* The drive supports ReturnFormatList status call. */ /* Get the current disk's size. */ for( formatListRecIndex = 0; formatListRecIndex < pb.cntrlParam.csParam[0]; ++formatListRecIndex ) { if ( (formatListRecords[formatListRecIndex].formatFlags & diCIFmtFlagsCurrentMask) != 0 ) { blocks = formatListRecords[formatListRecIndex].volSize; } } if ( blocks == 0 ) { /* This should never happen */ result = paramErr; } } else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum ) { /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */ result = DriveStatus(driveQElementPtr->dQDrive, &status); if ( result == noErr ) { switch ( status.twoSideFmt ) { case kSingleSided: blocks = kSingleSidedSize; break; case kDoubleSided: blocks = kDoubleSidedSize; break; default: /* This should never happen */ result = paramErr; break; } } } else { /* The drive is not a floppy and it doesn't support ReturnFormatList */ /* so use the dQDrvSz field(s) */ result = noErr; /* reset result */ switch ( driveQElementPtr->qType ) { case kWordDrvSiz: blocks = driveQElementPtr->dQDrvSz; break; case kLongDrvSiz: blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) + driveQElementPtr->dQDrvSz; break; default: /* This should never happen */ result = paramErr; break; } } } if ( result == noErr ) { *numBlocks = blocks; } return ( result ); } /*****************************************************************************/ pascal OSErr GetVolState(ConstStr255Param pathname, short vRefNum, Boolean *volumeOnline, Boolean *volumeEjected, Boolean *driveEjectable, Boolean *driverWantsEject) { HParamBlockRec pb; short driveNumber; OSErr error; error = GetVolumeInfoNoName(pathname,vRefNum, &pb); if ( error == noErr ) { if ( pb.volumeParam.ioVDrvInfo != 0 ) { /* the volume is online and not ejected */ *volumeOnline = true; *volumeEjected = false; /* Get the drive number */ driveNumber = pb.volumeParam.ioVDrvInfo; } else { /* the volume's is either offline or ejected */ /* in either case, the volume is NOT online */ *volumeOnline = false; /* Is it ejected? */ *volumeEjected = pb.volumeParam.ioVDRefNum > 0; if ( *volumeEjected ) { /* If ejected, the drive number is ioVDRefNum */ driveNumber = pb.volumeParam.ioVDRefNum; } else { /* If offline, the drive number is the negative of ioVDRefNum */ driveNumber = (short)-pb.volumeParam.ioVDRefNum; } } { DrvQElPtr drvQElem; /* Find the drive queue element by searching the drive queue */ drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNumber) ) { drvQElem = (DrvQElPtr)drvQElem->qLink; } if ( drvQElem != NULL ) { /* ** Each drive queue element is preceded by 4 flag bytes. ** Byte 1 (the second flag byte) has bits that tell us if a ** drive is ejectable and if its driver wants an eject call. ** See Inside Macintosh: Files, page 2-85. */ { Ptr flagBytePtr; /* point to byte 1 of the flag bytes */ flagBytePtr = (Ptr)drvQElem; flagBytePtr -= 3; /* ** The drive is ejectable if flag byte 1 does not contain ** 0x08 (nonejectable) or 0x48 (nonejectable, but wants eject call). */ *driveEjectable = (*flagBytePtr != 0x08) && (*flagBytePtr != 0x48); /* ** The driver wants an eject call if flag byte 1 does not contain ** 0x08 (nonejectable). This may seem like a minor point, but some ** disk drivers use the Eject request to flush their caches to disk ** and you wouldn't want to skip that step after unmounting a volume. */ *driverWantsEject = (*flagBytePtr != 0x08); } } else { /* Didn't find the drive (this should never happen) */ *driveEjectable = false; *driverWantsEject = false; } } } return ( error ); } /*****************************************************************************/ #endif // } !TARGET_API_MAC_CARBON /*****************************************************************************/ pascal OSErr GetVolFileSystemID(ConstStr255Param pathname, short vRefNum, short *fileSystemID) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname,vRefNum, &pb); if ( error == noErr ) { *fileSystemID = pb.volumeParam.ioVFSID; } return ( error ); } /*****************************************************************************/ // // Note: Under Carbon there are no drive numbers, so you cannot call // Eject with a drive number after unmounting a volume. // When a Carbon application calls UnmountVol, CarbonLib will make // sure ejectable media is ejected (leaving ejectable media in the // disk drive makes no sense to Carbon applications). // pascal OSErr UnmountAndEject(ConstStr255Param pathname, short vRefNum) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname, vRefNum, &pb); if ( error == noErr ) { #if !TARGET_API_MAC_CARBON short driveNum; Boolean ejected, wantsEject; DrvQElPtr drvQElem; if ( pb.volumeParam.ioVDrvInfo != 0 ) { /* the volume is online and not ejected */ ejected = false; /* Get the drive number */ driveNum = pb.volumeParam.ioVDrvInfo; } else { /* the volume is ejected or offline */ /* Is it ejected? */ ejected = pb.volumeParam.ioVDRefNum > 0; if ( ejected ) { /* If ejected, the drive number is ioVDRefNum */ driveNum = pb.volumeParam.ioVDRefNum; } else { /* If offline, the drive number is the negative of ioVDRefNum */ driveNum = (short)-pb.volumeParam.ioVDRefNum; } } /* find the drive queue element */ drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead); while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNum) ) { drvQElem = (DrvQElPtr)drvQElem->qLink; } if ( drvQElem != NULL ) { /* does the drive want an eject call */ wantsEject = (*((Ptr)((Ptr)drvQElem - 3)) != 8); } else { /* didn't find the drive!! */ wantsEject = false; } #endif // !TARGET_API_MAC_CARBON /* unmount the volume */ pb.volumeParam.ioNamePtr = NULL; /* ioVRefNum is already filled in from PBHGetVInfo */ error = PBUnmountVol((ParmBlkPtr)&pb); #if !TARGET_API_MAC_CARBON if ( error == noErr ) { if ( wantsEject && !ejected ) { /* eject the media from the drive if needed */ pb.volumeParam.ioVRefNum = driveNum; error = PBEject((ParmBlkPtr)&pb); } } #endif // !TARGET_API_MAC_CARBON } return ( error ); } /*****************************************************************************/ pascal OSErr OnLine(FSSpecPtr volumes, short reqVolCount, short *actVolCount, short *volIndex) { HParamBlockRec pb; OSErr error = noErr; FSSpec *endVolArray; if ( *volIndex > 0 ) { *actVolCount = 0; for ( endVolArray = volumes + reqVolCount; (volumes < endVolArray) && (error == noErr); ++volumes ) { pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name; pb.volumeParam.ioVolIndex = *volIndex; error = PBHGetVInfoSync(&pb); if ( error == noErr ) { volumes->parID = fsRtParID; /* the root directory's parent is 1 */ volumes->vRefNum = pb.volumeParam.ioVRefNum; ++*volIndex; ++*actVolCount; } } } else { error = paramErr; } return ( error ); } /*****************************************************************************/ pascal OSErr SetDefault(short newVRefNum, long newDirID, short *oldVRefNum, long *oldDirID) { OSErr error; /* Get the current default volume/directory. */ error = HGetVol(NULL, oldVRefNum, oldDirID); if ( error == noErr ) { /* Set the new default volume/directory */ error = HSetVol(NULL, newVRefNum, newDirID); } return ( error ); } /*****************************************************************************/ pascal OSErr RestoreDefault(short oldVRefNum, long oldDirID) { OSErr error; #if !TARGET_API_MAC_CARBON short defaultVRefNum; long defaultDirID; long defaultProcID; /* Determine if the default volume was a wdRefNum. */ error = GetWDInfo(oldVRefNum, &defaultVRefNum, &defaultDirID, &defaultProcID); if ( error == noErr ) { /* Restore the old default volume/directory, one way or the other. */ if ( defaultDirID != fsRtDirID ) { /* oldVRefNum was a wdRefNum - use SetVol */ error = SetVol(NULL, oldVRefNum); } else { #endif // !TARGET_API_MAC_CARBON /* oldVRefNum was a real vRefNum - use HSetVol */ error = HSetVol(NULL, oldVRefNum, oldDirID); #if !TARGET_API_MAC_CARBON } } #endif // !TARGET_API_MAC_CARBON return ( error ); } /*****************************************************************************/ pascal OSErr GetDInfo(short vRefNum, long dirID, ConstStr255Param name, DInfo *fndrInfo) { CInfoPBRec pb; OSErr error; error = GetCatInfoNoName(vRefNum, dirID, name, &pb); if ( error == noErr ) { if ( (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* it's a directory, return the DInfo */ *fndrInfo = pb.dirInfo.ioDrUsrWds; } else { /* oops, a file was passed */ error = dirNFErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetDInfo(const FSSpec *spec, DInfo *fndrInfo) { return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); } /*****************************************************************************/ pascal OSErr SetDInfo(short vRefNum, long dirID, ConstStr255Param name, const DInfo *fndrInfo) { CInfoPBRec pb; Str31 tempName; OSErr error; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb.dirInfo.ioNamePtr = tempName; pb.dirInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.dirInfo.ioNamePtr = (StringPtr)name; pb.dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb.dirInfo.ioVRefNum = vRefNum; pb.dirInfo.ioDrDirID = dirID; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { if ( (pb.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* it's a directory, set the DInfo */ if ( pb.dirInfo.ioNamePtr == tempName ) { pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; } else { pb.dirInfo.ioDrDirID = dirID; } pb.dirInfo.ioDrUsrWds = *fndrInfo; error = PBSetCatInfoSync(&pb); } else { /* oops, a file was passed */ error = dirNFErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpSetDInfo(const FSSpec *spec, const DInfo *fndrInfo) { return ( SetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) ); } /*****************************************************************************/ pascal OSErr GetDirectoryID(short vRefNum, long dirID, ConstStr255Param name, long *theDirID, Boolean *isDirectory) { CInfoPBRec pb; OSErr error; error = GetCatInfoNoName(vRefNum, dirID, name, &pb); if ( error == noErr ) { *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; if ( *isDirectory ) { *theDirID = pb.dirInfo.ioDrDirID; } else { *theDirID = pb.hFileInfo.ioFlParID; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetDirectoryID(const FSSpec *spec, long *theDirID, Boolean *isDirectory) { return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name, theDirID, isDirectory) ); } /*****************************************************************************/ pascal OSErr GetDirName(short vRefNum, long dirID, Str31 name) { CInfoPBRec pb; OSErr error; if ( name != NULL ) { pb.dirInfo.ioNamePtr = name; pb.dirInfo.ioVRefNum = vRefNum; pb.dirInfo.ioDrDirID = dirID; pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ error = PBGetCatInfoSync(&pb); } else { error = paramErr; } return ( error ); } /*****************************************************************************/ pascal OSErr GetIOACUser(short vRefNum, long dirID, ConstStr255Param name, SInt8 *ioACUser) { CInfoPBRec pb; OSErr error; /* Clear ioACUser before calling PBGetCatInfo since some file systems ** don't bother to set or clear this field. If ioACUser isn't set by the ** file system, then you'll get the zero value back (full access) which ** is the access you have on volumes that don't support ioACUser. */ pb.dirInfo.ioACUser = 0; /* ioACUser used to be filler2 */ error = GetCatInfoNoName(vRefNum, dirID, name, &pb); if ( error == noErr ) { if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) { /* oops, a file was passed */ error = dirNFErr; } else { *ioACUser = pb.dirInfo.ioACUser; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetIOACUser(const FSSpec *spec, SInt8 *ioACUser) { return ( GetIOACUser(spec->vRefNum, spec->parID, spec->name, ioACUser) ); } /*****************************************************************************/ pascal OSErr GetParentID(short vRefNum, long dirID, ConstStr255Param name, long *parID) { CInfoPBRec pb; Str31 tempName; OSErr error; short realVRefNum; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb.hFileInfo.ioNamePtr = tempName; pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.hFileInfo.ioNamePtr = (StringPtr)name; pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { /* ** There's a bug in HFS where the wrong parent dir ID can be ** returned if multiple separators are used at the end of a ** pathname. For example, if the pathname: ** 'volumeName:System Folder:Extensions::' ** is passed, the directory ID of the Extensions folder is ** returned in the ioFlParID field instead of fsRtDirID. Since ** multiple separators at the end of a pathname always specifies ** a directory, we only need to work-around cases where the ** object is a directory and there are multiple separators at ** the end of the name parameter. */ if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* Its a directory */ /* is there a pathname? */ if ( pb.hFileInfo.ioNamePtr == name ) { /* could it contain multiple separators? */ if ( name[0] >= 2 ) { /* does it contain multiple separators at the end? */ if ( (name[name[0]] == ':') && (name[name[0] - 1] == ':') ) { /* OK, then do the extra stuff to get the correct parID */ /* Get the real vRefNum (this should not fail) */ error = DetermineVRefNum(name, vRefNum, &realVRefNum); if ( error == noErr ) { /* we don't need the parent's name, but add protect against File Sharing problem */ tempName[0] = 0; pb.dirInfo.ioNamePtr = tempName; pb.dirInfo.ioVRefNum = realVRefNum; /* pb.dirInfo.ioDrDirID already contains the */ /* dirID of the directory object */ pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ error = PBGetCatInfoSync(&pb); /* now, pb.dirInfo.ioDrParID contains the correct parID */ } } } } } if ( error == noErr ) { /* if no errors, then pb.hFileInfo.ioFlParID (pb.dirInfo.ioDrParID) */ /* contains the parent ID */ *parID = pb.hFileInfo.ioFlParID; } } return ( error ); } /*****************************************************************************/ pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname, Str255 filename) { short index; short nameEnd; OSErr error; /* default to no filename */ filename[0] = 0; /* check for no pathname */ if ( pathname != NULL ) { /* get string length */ index = pathname[0]; /* check for empty string */ if ( index != 0 ) { /* skip over last trailing colon (if any) */ if ( pathname[index] == ':' ) { --index; } /* save the end of the string */ nameEnd = index; /* if pathname ends with multiple colons, then this pathname refers */ /* to a directory, not a file */ if ( pathname[index] != ':' ) { /* parse backwards until we find a colon or hit the beginning of the pathname */ while ( (index != 0) && (pathname[index] != ':') ) { --index; } /* if we parsed to the beginning of the pathname and the pathname ended */ /* with a colon, then pathname is a full pathname to a volume, not a file */ if ( (index != 0) || (pathname[pathname[0]] != ':') ) { /* get the filename and return noErr */ filename[0] = (char)(nameEnd - index); BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index); error = noErr; } else { /* pathname to a volume, not a file */ error = notAFileErr; } } else { /* directory, not a file */ error = notAFileErr; } } else { /* empty string isn't a file */ error = notAFileErr; } } else { /* NULL pathname isn't a file */ error = notAFileErr; } return ( error ); } /*****************************************************************************/ pascal OSErr GetObjectLocation(short vRefNum, long dirID, ConstStr255Param pathname, short *realVRefNum, long *realParID, Str255 realName, Boolean *isDirectory) { OSErr error; CInfoPBRec pb; Str255 tempPathname; /* clear results */ *realVRefNum = 0; *realParID = 0; realName[0] = 0; /* ** Get the real vRefNum */ error = DetermineVRefNum(pathname, vRefNum, realVRefNum); if ( error == noErr ) { /* ** Determine if the object already exists and if so, ** get the real parent directory ID if it's a file */ /* Protection against File Sharing problem */ if ( (pathname == NULL) || (pathname[0] == 0) ) { tempPathname[0] = 0; pb.hFileInfo.ioNamePtr = tempPathname; pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.hFileInfo.ioNamePtr = (StringPtr)pathname; pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { /* ** The file system object is present and we have the file's real parID */ /* Is it a directory or a file? */ *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; if ( *isDirectory ) { /* ** It's a directory, get its name and parent dirID, and then we're done */ pb.dirInfo.ioNamePtr = realName; pb.dirInfo.ioVRefNum = *realVRefNum; /* pb.dirInfo.ioDrDirID already contains the dirID of the directory object */ pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */ error = PBGetCatInfoSync(&pb); /* get the parent ID here, because the file system can return the */ /* wrong parent ID from the last call. */ *realParID = pb.dirInfo.ioDrParID; } else { /* ** It's a file - use the parent directory ID from the last call ** to GetCatInfoparse, get the file name, and then we're done */ *realParID = pb.hFileInfo.ioFlParID; error = GetFilenameFromPathname(pathname, realName); } } else if ( error == fnfErr ) { /* ** The file system object is not present - see if its parent is present */ /* ** Parse to get the object name from end of pathname */ error = GetFilenameFromPathname(pathname, realName); /* if we can't get the object name from the end, we can't continue */ if ( error == noErr ) { /* ** What we want now is the pathname minus the object name ** for example: ** if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:' ** if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:' ** if pathname is ':dir:file' tempPathname becomes ':dir:' ** if pathname is ':dir:file:' tempPathname becomes ':dir:' ** if pathname is ':file' tempPathname becomes ':' ** if pathname is 'file or file:' tempPathname becomes '' */ /* get a copy of the pathname */ BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* remove the object name */ tempPathname[0] -= realName[0]; /* and the trailing colon (if any) */ if ( pathname[pathname[0]] == ':' ) { --tempPathname[0]; } /* OK, now get the parent's directory ID */ /* Protection against File Sharing problem */ pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname; if ( tempPathname[0] != 0 ) { pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } else { pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; error = PBGetCatInfoSync(&pb); *realParID = pb.dirInfo.ioDrDirID; *isDirectory = false; /* we don't know what the object is really going to be */ } if ( error != noErr ) { error = dirNFErr; /* couldn't find parent directory */ } else { error = fnfErr; /* we found the parent, but not the file */ } } } return ( error ); } /*****************************************************************************/ pascal OSErr GetDirItems(short vRefNum, long dirID, ConstStr255Param name, Boolean getFiles, Boolean getDirectories, FSSpecPtr items, short reqItemCount, short *actItemCount, short *itemIndex) /* start with 1, then use what's returned */ { CInfoPBRec pb; OSErr error; long theDirID; Boolean isDirectory; FSSpec *endItemsArray; if ( *itemIndex > 0 ) { /* NOTE: If I could be sure that the caller passed a real vRefNum and real directory */ /* to this routine, I could rip out calls to DetermineVRefNum and GetDirectoryID and this */ /* routine would be much faster because of the overhead of DetermineVRefNum and */ /* GetDirectoryID and because GetDirectoryID blows away the directory index hint the Macintosh */ /* file system keeps for indexed calls. I can't be sure, so for maximum throughput, */ /* pass a big array of FSSpecs so you can get the directory's contents with few calls */ /* to this routine. */ /* get the real volume reference number */ error = DetermineVRefNum(name, vRefNum, &pb.hFileInfo.ioVRefNum); if ( error == noErr ) { /* and the real directory ID of this directory (and make sure it IS a directory) */ error = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory); if ( error == noErr ) { if ( isDirectory ) { *actItemCount = 0; endItemsArray = items + reqItemCount; while ( (items < endItemsArray) && (error == noErr) ) { pb.hFileInfo.ioNamePtr = (StringPtr) &items->name; pb.hFileInfo.ioDirID = theDirID; pb.hFileInfo.ioFDirIndex = *itemIndex; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { items->parID = pb.hFileInfo.ioFlParID; /* return item's parID */ items->vRefNum = pb.hFileInfo.ioVRefNum; /* return item's vRefNum */ ++*itemIndex; /* prepare to get next item in directory */ if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { if ( getDirectories ) { ++*actItemCount; /* keep this item */ ++items; /* point to next item */ } } else { if ( getFiles ) { ++*actItemCount; /* keep this item */ ++items; /* point to next item */ } } } } } else { /* it wasn't a directory */ error = dirNFErr; } } } } else { /* bad itemIndex */ error = paramErr; } return ( error ); } /*****************************************************************************/ static void DeleteLevel(long dirToDelete, DeleteEnumGlobalsPtr theGlobals) { long savedDir; do { /* prepare to delete directory */ theGlobals->myPB.ciPB.dirInfo.ioNamePtr = (StringPtr)&theGlobals->itemName; theGlobals->myPB.ciPB.dirInfo.ioFDirIndex = 1; /* get first item */ theGlobals->myPB.ciPB.dirInfo.ioDrDirID = dirToDelete; /* in this directory */ theGlobals->error = PBGetCatInfoSync(&(theGlobals->myPB.ciPB)); if ( theGlobals->error == noErr ) { savedDir = dirToDelete; /* We have an item. Is it a file or directory? */ if ( (theGlobals->myPB.ciPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* it's a directory */ savedDir = theGlobals->myPB.ciPB.dirInfo.ioDrDirID; /* save dirID of directory instead */ DeleteLevel(theGlobals->myPB.ciPB.dirInfo.ioDrDirID, theGlobals); /* Delete its contents */ theGlobals->myPB.ciPB.dirInfo.ioNamePtr = NULL; /* prepare to delete directory */ } if ( theGlobals->error == noErr ) { theGlobals->myPB.ciPB.dirInfo.ioDrDirID = savedDir; /* restore dirID */ theGlobals->myPB.hPB.fileParam.ioFVersNum = 0; /* just in case it's used on an MFS volume... */ theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* delete this item */ if ( theGlobals->error == fLckdErr ) { (void) PBHRstFLockSync(&(theGlobals->myPB.hPB)); /* unlock it */ theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* and try again */ } } } } while ( theGlobals->error == noErr ); if ( theGlobals->error == fnfErr ) { theGlobals->error = noErr; } } /*****************************************************************************/ pascal OSErr DeleteDirectoryContents(short vRefNum, long dirID, ConstStr255Param name) { DeleteEnumGlobals theGlobals; Boolean isDirectory; OSErr error; /* Get the real dirID and make sure it is a directory. */ error = GetDirectoryID(vRefNum, dirID, name, &dirID, &isDirectory); if ( error == noErr ) { if ( isDirectory ) { /* Get the real vRefNum */ error = DetermineVRefNum(name, vRefNum, &vRefNum); if ( error == noErr ) { /* Set up the globals we need to access from the recursive routine. */ theGlobals.myPB.ciPB.dirInfo.ioVRefNum = vRefNum; /* Here we go into recursion land... */ DeleteLevel(dirID, &theGlobals); error = theGlobals.error; } } else { error = dirNFErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr DeleteDirectory(short vRefNum, long dirID, ConstStr255Param name) { OSErr error; /* Make sure a directory was specified and then delete its contents */ error = DeleteDirectoryContents(vRefNum, dirID, name); if ( error == noErr ) { error = HDelete(vRefNum, dirID, name); if ( error == fLckdErr ) { (void) HRstFLock(vRefNum, dirID, name); /* unlock the directory locked by AppleShare */ error = HDelete(vRefNum, dirID, name); /* and try again */ } } return ( error ); } /*****************************************************************************/ pascal OSErr CheckObjectLock(short vRefNum, long dirID, ConstStr255Param name) { CInfoPBRec pb; OSErr error; error = GetCatInfoNoName(vRefNum, dirID, name, &pb); if ( error == noErr ) { /* check locked bit */ if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0 ) { error = fLckdErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpCheckObjectLock(const FSSpec *spec) { return ( CheckObjectLock(spec->vRefNum, spec->parID, spec->name) ); } /*****************************************************************************/ pascal OSErr GetFileSize(short vRefNum, long dirID, ConstStr255Param fileName, long *dataSize, long *rsrcSize) { HParamBlockRec pb; OSErr error; pb.fileParam.ioNamePtr = (StringPtr)fileName; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioDirID = dirID; pb.fileParam.ioFDirIndex = 0; error = PBHGetFInfoSync(&pb); if ( error == noErr ) { *dataSize = pb.fileParam.ioFlLgLen; *rsrcSize = pb.fileParam.ioFlRLgLen; } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetFileSize(const FSSpec *spec, long *dataSize, long *rsrcSize) { return ( GetFileSize(spec->vRefNum, spec->parID, spec->name, dataSize, rsrcSize) ); } /*****************************************************************************/ pascal OSErr BumpDate(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, change its modification date to the current date/time. */ { CInfoPBRec pb; Str31 tempName; OSErr error; unsigned long secs; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb.hFileInfo.ioNamePtr = tempName; pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.hFileInfo.ioNamePtr = (StringPtr)name; pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { GetDateTime(&secs); /* set mod date to current date, or one second into the future if mod date = current date */ pb.hFileInfo.ioFlMdDat = (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs); if ( pb.dirInfo.ioNamePtr == tempName ) { pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; } else { pb.hFileInfo.ioDirID = dirID; } error = PBSetCatInfoSync(&pb); } return ( error ); } /*****************************************************************************/ pascal OSErr FSpBumpDate(const FSSpec *spec) { return ( BumpDate(spec->vRefNum, spec->parID, spec->name) ); } /*****************************************************************************/ pascal OSErr ChangeCreatorType(short vRefNum, long dirID, ConstStr255Param name, OSType creator, OSType fileType) { CInfoPBRec pb; OSErr error; short realVRefNum; long parID; pb.hFileInfo.ioNamePtr = (StringPtr)name; pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ error = PBGetCatInfoSync(&pb); if ( error == noErr ) { if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) /* if file */ { parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ /* If creator not 0x00000000, change creator */ if ( creator != (OSType)0x00000000 ) { pb.hFileInfo.ioFlFndrInfo.fdCreator = creator; } /* If fileType not 0x00000000, change fileType */ if ( fileType != (OSType)0x00000000 ) { pb.hFileInfo.ioFlFndrInfo.fdType = fileType; } pb.hFileInfo.ioDirID = dirID; error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ { /* get the real vRefNum in case a full pathname was passed */ error = DetermineVRefNum(name, vRefNum, &realVRefNum); if ( error == noErr ) { error = BumpDate(realVRefNum, parID, NULL); /* and bump the parent directory's mod date to wake up the Finder */ /* to the change we just made */ } } } else { /* it was a directory, not a file */ error = notAFileErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpChangeCreatorType(const FSSpec *spec, OSType creator, OSType fileType) { return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name, creator, fileType) ); } /*****************************************************************************/ pascal OSErr ChangeFDFlags(short vRefNum, long dirID, ConstStr255Param name, Boolean setBits, unsigned short flagBits) { CInfoPBRec pb; Str31 tempName; OSErr error; short realVRefNum; long parID; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb.hFileInfo.ioNamePtr = tempName; pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.hFileInfo.ioNamePtr = (StringPtr)name; pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb.hFileInfo.ioVRefNum = vRefNum; pb.hFileInfo.ioDirID = dirID; error = PBGetCatInfoSync(&pb); if ( error == noErr ) { parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */ /* set or clear the appropriate bits in the Finder flags */ if ( setBits ) { /* OR in the bits */ pb.hFileInfo.ioFlFndrInfo.fdFlags |= flagBits; } else { /* AND out the bits */ pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~flagBits; } if ( pb.dirInfo.ioNamePtr == tempName ) { pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID; } else { pb.hFileInfo.ioDirID = dirID; } error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */ if ( (error == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */ { /* get the real vRefNum in case a full pathname was passed */ error = DetermineVRefNum(name, vRefNum, &realVRefNum); if ( error == noErr ) { error = BumpDate(realVRefNum, parID, NULL); /* and bump the parent directory's mod date to wake up the Finder */ /* to the change we just made */ } } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpChangeFDFlags(const FSSpec *spec, Boolean setBits, unsigned short flagBits) { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, setBits, flagBits) ); } /*****************************************************************************/ pascal OSErr SetIsInvisible(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, make it invisible. */ { return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsInvisible) ); } /*****************************************************************************/ pascal OSErr FSpSetIsInvisible(const FSSpec *spec) /* Given a file or directory, make it invisible. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsInvisible) ); } /*****************************************************************************/ pascal OSErr ClearIsInvisible(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, make it visible. */ { return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsInvisible) ); } /*****************************************************************************/ pascal OSErr FSpClearIsInvisible(const FSSpec *spec) /* Given a file or directory, make it visible. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsInvisible) ); } /*****************************************************************************/ pascal OSErr SetNameLocked(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, lock its name. */ { return ( ChangeFDFlags(vRefNum, dirID, name, true, kNameLocked) ); } /*****************************************************************************/ pascal OSErr FSpSetNameLocked(const FSSpec *spec) /* Given a file or directory, lock its name. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kNameLocked) ); } /*****************************************************************************/ pascal OSErr ClearNameLocked(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, unlock its name. */ { return ( ChangeFDFlags(vRefNum, dirID, name, false, kNameLocked) ); } /*****************************************************************************/ pascal OSErr FSpClearNameLocked(const FSSpec *spec) /* Given a file or directory, unlock its name. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kNameLocked) ); } /*****************************************************************************/ pascal OSErr SetIsStationery(short vRefNum, long dirID, ConstStr255Param name) /* Given a file, make it a stationery pad. */ { return ( ChangeFDFlags(vRefNum, dirID, name, true, kIsStationery) ); } /*****************************************************************************/ pascal OSErr FSpSetIsStationery(const FSSpec *spec) /* Given a file, make it a stationery pad. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kIsStationery) ); } /*****************************************************************************/ pascal OSErr ClearIsStationery(short vRefNum, long dirID, ConstStr255Param name) /* Given a file, clear the stationery bit. */ { return ( ChangeFDFlags(vRefNum, dirID, name, false, kIsStationery) ); } /*****************************************************************************/ pascal OSErr FSpClearIsStationery(const FSSpec *spec) /* Given a file, clear the stationery bit. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kIsStationery) ); } /*****************************************************************************/ pascal OSErr SetHasCustomIcon(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, indicate that it has a custom icon. */ { return ( ChangeFDFlags(vRefNum, dirID, name, true, kHasCustomIcon) ); } /*****************************************************************************/ pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec) /* Given a file or directory, indicate that it has a custom icon. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, true, kHasCustomIcon) ); } /*****************************************************************************/ pascal OSErr ClearHasCustomIcon(short vRefNum, long dirID, ConstStr255Param name) /* Given a file or directory, indicate that it does not have a custom icon. */ { return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasCustomIcon) ); } /*****************************************************************************/ pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec) /* Given a file or directory, indicate that it does not have a custom icon. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasCustomIcon) ); } /*****************************************************************************/ pascal OSErr ClearHasBeenInited(short vRefNum, long dirID, ConstStr255Param name) /* Given a file, clear its "has been inited" bit. */ { return ( ChangeFDFlags(vRefNum, dirID, name, false, kHasBeenInited) ); } /*****************************************************************************/ pascal OSErr FSpClearHasBeenInited(const FSSpec *spec) /* Given a file, clear its "has been inited" bit. */ { return ( ChangeFDFlags(spec->vRefNum, spec->parID, spec->name, false, kHasBeenInited) ); } /*****************************************************************************/ pascal OSErr CopyFileMgrAttributes(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName, Boolean copyLockBit) { UniversalFMPB pb; Str31 tempName; OSErr error; Boolean objectIsDirectory; pb.ciPB.hFileInfo.ioVRefNum = srcVRefNum; pb.ciPB.hFileInfo.ioDirID = srcDirID; /* Protection against File Sharing problem */ if ( (srcName == NULL) || (srcName[0] == 0) ) { tempName[0] = 0; pb.ciPB.hFileInfo.ioNamePtr = tempName; pb.ciPB.hFileInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)srcName; pb.ciPB.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } error = PBGetCatInfoSync(&pb.ciPB); if ( error == noErr ) { objectIsDirectory = ( (pb.ciPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ); pb.ciPB.hFileInfo.ioVRefNum = dstVRefNum; pb.ciPB.hFileInfo.ioDirID = dstDirID; if ( (dstName != NULL) && (dstName[0] == 0) ) { pb.ciPB.hFileInfo.ioNamePtr = NULL; } else { pb.ciPB.hFileInfo.ioNamePtr = (StringPtr)dstName; } /* don't copy the hasBeenInited bit */ pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags = ( pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags & ~kHasBeenInited ); error = PBSetCatInfoSync(&pb.ciPB); if ( (error == noErr) && (copyLockBit) && ((pb.ciPB.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0) ) { pb.hPB.fileParam.ioFVersNum = 0; error = PBHSetFLockSync(&pb.hPB); if ( (error != noErr) && (objectIsDirectory) ) { error = noErr; /* ignore lock errors if destination is directory */ } } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec, const FSSpec *dstSpec, Boolean copyLockBit) { return ( CopyFileMgrAttributes(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name, copyLockBit) ); } /*****************************************************************************/ pascal OSErr HOpenAware(short vRefNum, long dirID, ConstStr255Param fileName, short denyModes, short *refNum) { HParamBlockRec pb; OSErr error; GetVolParmsInfoBuffer volParmsInfo; long infoSize = sizeof(GetVolParmsInfoBuffer); pb.ioParam.ioMisc = NULL; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioNamePtr = (StringPtr)fileName; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; /* get volume attributes */ /* this preflighting is needed because Foreign File Access based file systems don't */ /* return the correct error result to the OpenDeny call */ error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); if ( (error == noErr) && hasOpenDeny(volParmsInfo) ) { /* if volume supports OpenDeny, use it and return */ pb.accessParam.ioDenyModes = denyModes; error = PBHOpenDenySync(&pb); *refNum = pb.ioParam.ioRefNum; } else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ { /* OpenDeny isn't supported, so try File Manager Open functions */ /* If request includes write permission, then see if the volume is */ /* locked by hardware or software. The HFS file system doesn't check */ /* for this when a file is opened - you only find out later when you */ /* try to write and the write fails with a wPrErr or a vLckdErr. */ if ( (denyModes & dmWr) != 0 ) { error = CheckVolLock(fileName, vRefNum); } else { error = noErr; } if ( error == noErr ) { /* Set File Manager permissions to closest thing possible */ if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) { pb.ioParam.ioPermssn = fsRdWrShPerm; } else { pb.ioParam.ioPermssn = denyModes % 4; } error = PBHOpenDFSync(&pb); /* Try OpenDF */ if ( error == paramErr ) { error = PBHOpenSync(&pb); /* OpenDF not supported, so try Open */ } *refNum = pb.ioParam.ioRefNum; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpOpenAware(const FSSpec *spec, short denyModes, short *refNum) { return ( HOpenAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); } /*****************************************************************************/ pascal OSErr HOpenRFAware(short vRefNum, long dirID, ConstStr255Param fileName, short denyModes, short *refNum) { HParamBlockRec pb; OSErr error; GetVolParmsInfoBuffer volParmsInfo; long infoSize = sizeof(GetVolParmsInfoBuffer); pb.ioParam.ioMisc = NULL; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioNamePtr = (StringPtr)fileName; pb.fileParam.ioVRefNum = vRefNum; pb.fileParam.ioDirID = dirID; /* get volume attributes */ /* this preflighting is needed because Foreign File Access based file systems don't */ /* return the correct error result to the OpenRFDeny call */ error = HGetVolParms(fileName, vRefNum, &volParmsInfo, &infoSize); if ( (error == noErr) && hasOpenDeny(volParmsInfo) ) { /* if volume supports OpenRFDeny, use it and return */ if ( hasOpenDeny(volParmsInfo) ) { pb.accessParam.ioDenyModes = denyModes; error = PBHOpenRFDenySync(&pb); *refNum = pb.ioParam.ioRefNum; } } else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ { /* OpenRFDeny isn't supported, so try File Manager OpenRF function */ /* If request includes write permission, then see if the volume is */ /* locked by hardware or software. The HFS file system doesn't check */ /* for this when a file is opened - you only find out later when you */ /* try to write and the write fails with a wPrErr or a vLckdErr. */ if ( (denyModes & dmWr) != 0 ) { error = CheckVolLock(fileName, vRefNum); } else { error = noErr; } if ( error == noErr ) { /* Set File Manager permissions to closest thing possible */ if ( (denyModes == dmWr) || (denyModes == dmRdWr) ) { pb.ioParam.ioPermssn = fsRdWrShPerm; } else { pb.ioParam.ioPermssn = denyModes % 4; } error = PBHOpenRFSync(&pb); *refNum = pb.ioParam.ioRefNum; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpOpenRFAware(const FSSpec *spec, short denyModes, short *refNum) { return ( HOpenRFAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum) ); } /*****************************************************************************/ pascal OSErr FSReadNoCache(short refNum, long *count, void *buffPtr) { ParamBlockRec pb; OSErr error; pb.ioParam.ioRefNum = refNum; pb.ioParam.ioBuffer = (Ptr)buffPtr; pb.ioParam.ioReqCount = *count; pb.ioParam.ioPosMode = fsAtMark + noCacheMask; /* fsAtMark + noCacheMask */ pb.ioParam.ioPosOffset = 0; error = PBReadSync(&pb); *count = pb.ioParam.ioActCount; /* always return count */ return ( error ); } /*****************************************************************************/ pascal OSErr FSWriteNoCache(short refNum, long *count, const void *buffPtr) { ParamBlockRec pb; OSErr error; pb.ioParam.ioRefNum = refNum; pb.ioParam.ioBuffer = (Ptr)buffPtr; pb.ioParam.ioReqCount = *count; pb.ioParam.ioPosMode = fsAtMark + noCacheMask; /* fsAtMark + noCacheMask */ pb.ioParam.ioPosOffset = 0; error = PBWriteSync(&pb); *count = pb.ioParam.ioActCount; /* always return count */ return ( error ); } /*****************************************************************************/ /* ** See if numBytes bytes of buffer1 are equal to buffer2. */ static Boolean EqualMemory(const void *buffer1, const void *buffer2, unsigned long numBytes) { register unsigned char *b1 = (unsigned char *)buffer1; register unsigned char *b2 = (unsigned char *)buffer2; if ( b1 != b2 ) /* if buffer pointers are same, then they are equal */ { while ( numBytes > 0 ) { /* compare the bytes and then increment the pointers */ if ( (*b1++ - *b2++) != 0 ) { return ( false ); } --numBytes; } } return ( true ); } /*****************************************************************************/ /* ** Read any number of bytes from an open file using read-verify mode. ** The FSReadVerify function reads any number of bytes from an open file ** and verifies them against the data in the buffer pointed to by buffPtr. ** ** Because of a bug in the HFS file system, only non-block aligned parts of ** the read are verified against the buffer data and the rest is *copied* ** into the buffer. Thus, you shouldn't verify against your original data; ** instead, you should verify against a copy of the original data and then ** compare the read-verified copy against the original data after calling ** FSReadVerify. That's why this function isn't exported - it needs the ** wrapper provided by FSWriteVerify. */ static OSErr FSReadVerify(short refNum, long *count, void *buffPtr) { ParamBlockRec pb; OSErr result; pb.ioParam.ioRefNum = refNum; pb.ioParam.ioBuffer = (Ptr)buffPtr; pb.ioParam.ioReqCount = *count; pb.ioParam.ioPosMode = fsAtMark + rdVerify; pb.ioParam.ioPosOffset = 0; result = PBReadSync(&pb); *count = pb.ioParam.ioActCount; /* always return count */ return ( result ); } /*****************************************************************************/ pascal OSErr FSWriteVerify(short refNum, long *count, const void *buffPtr) { Ptr verifyBuffer; long position; long bufferSize; long byteCount; long bytesVerified; Ptr startVerify; OSErr result; /* ** Allocate the verify buffer ** Try to get get a large enough buffer to verify in one pass. ** If that fails, use GetTempBuffer to get a buffer. */ bufferSize = *count; verifyBuffer = NewPtr(bufferSize); if ( verifyBuffer == NULL ) { verifyBuffer = GetTempBuffer(bufferSize, &bufferSize); } if ( verifyBuffer != NULL ) { /* Save the current position */ result = GetFPos(refNum, &position); if ( result == noErr ) { /* Write the data */ result = FSWrite(refNum, count, buffPtr); if ( result == noErr ) { /* Restore the original position */ result = SetFPos(refNum, fsFromStart, position); if ( result == noErr ) { /* ** *count = total number of bytes to verify ** bufferSize = the size of the verify buffer ** bytesVerified = number of bytes verified ** byteCount = number of bytes to verify this pass ** startVerify = position in buffPtr */ bytesVerified = 0; startVerify = (Ptr)buffPtr; while ( (bytesVerified < *count) && ( result == noErr ) ) { if ( (*count - bytesVerified) > bufferSize ) { byteCount = bufferSize; } else { byteCount = *count - bytesVerified; } /* ** Copy the write buffer into the verify buffer. ** This step is needed because the File Manager ** compares the data in any non-block aligned ** data at the beginning and end of the read-verify ** request back into the file system's cache ** to the data in verify Buffer. However, the ** File Manager does not compare any full blocks ** and instead copies them into the verify buffer ** so we still have to compare the buffers again ** after the read-verify request completes. */ BlockMoveData(startVerify, verifyBuffer, byteCount); /* Read-verify the data back into the verify buffer */ result = FSReadVerify(refNum, &byteCount, verifyBuffer); if ( result == noErr ) { /* See if the buffers are the same */ if ( !EqualMemory(verifyBuffer, startVerify, byteCount) ) { result = ioErr; } startVerify += byteCount; bytesVerified += byteCount; } } } } } DisposePtr(verifyBuffer); } else { result = memFullErr; } return ( result ); } /*****************************************************************************/ pascal OSErr CopyFork(short srcRefNum, short dstRefNum, void *copyBufferPtr, long copyBufferSize) { ParamBlockRec srcPB; ParamBlockRec dstPB; OSErr srcError; OSErr dstError; if ( (copyBufferPtr == NULL) || (copyBufferSize == 0) ) return ( paramErr ); srcPB.ioParam.ioRefNum = srcRefNum; dstPB.ioParam.ioRefNum = dstRefNum; /* preallocate the destination fork and */ /* ensure the destination fork's EOF is correct after the copy */ srcError = PBGetEOFSync(&srcPB); if ( srcError != noErr ) return ( srcError ); dstPB.ioParam.ioMisc = srcPB.ioParam.ioMisc; dstError = PBSetEOFSync(&dstPB); if ( dstError != noErr ) return ( dstError ); /* reset source fork's mark */ srcPB.ioParam.ioPosMode = fsFromStart; srcPB.ioParam.ioPosOffset = 0; srcError = PBSetFPosSync(&srcPB); if ( srcError != noErr ) return ( srcError ); /* reset destination fork's mark */ dstPB.ioParam.ioPosMode = fsFromStart; dstPB.ioParam.ioPosOffset = 0; dstError = PBSetFPosSync(&dstPB); if ( dstError != noErr ) return ( dstError ); /* set up fields that won't change in the loop */ srcPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; srcPB.ioParam.ioPosMode = fsAtMark + noCacheMask;/* fsAtMark + noCacheMask */ /* If copyBufferSize is greater than 512 bytes, make it a multiple of 512 bytes */ /* This will make writes on local volumes faster */ if ( (copyBufferSize >= 512) && ((copyBufferSize & 0x1ff) != 0) ) { srcPB.ioParam.ioReqCount = copyBufferSize & 0xfffffe00; } else { srcPB.ioParam.ioReqCount = copyBufferSize; } dstPB.ioParam.ioBuffer = (Ptr)copyBufferPtr; dstPB.ioParam.ioPosMode = fsAtMark + noCacheMask;/* fsAtMark + noCacheMask */ while ( (srcError == noErr) && (dstError == noErr) ) { srcError = PBReadSync(&srcPB); dstPB.ioParam.ioReqCount = srcPB.ioParam.ioActCount; dstError = PBWriteSync(&dstPB); } /* make sure there were no errors at the destination */ if ( dstError != noErr ) return ( dstError ); /* make sure the only error at the source was eofErr */ if ( srcError != eofErr ) return ( srcError ); return ( noErr ); } /*****************************************************************************/ pascal OSErr GetFileLocation(short refNum, short *vRefNum, long *dirID, StringPtr fileName) { FCBPBRec pb; OSErr error; pb.ioNamePtr = fileName; pb.ioVRefNum = 0; pb.ioRefNum = refNum; pb.ioFCBIndx = 0; error = PBGetFCBInfoSync(&pb); if ( error == noErr ) { *vRefNum = pb.ioFCBVRefNum; *dirID = pb.ioFCBParID; } return ( error ); } /*****************************************************************************/ pascal OSErr FSpGetFileLocation(short refNum, FSSpec *spec) { return ( GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name) ); } /*****************************************************************************/ pascal OSErr CopyDirectoryAccess(short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName) { OSErr error; GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */ long dstServerAdr; /* AppleTalk server address of destination (if any) */ long ownerID, groupID, accessRights; long tempLong; /* See if destination supports directory access control */ tempLong = sizeof(infoBuffer); error = HGetVolParms(dstName, dstVRefNum, &infoBuffer, &tempLong); if ( (error == noErr) && hasAccessCntl(infoBuffer) ) { if ( hasAccessCntl(infoBuffer) ) { dstServerAdr = infoBuffer.vMServerAdr; /* See if source supports directory access control and is on same server */ tempLong = sizeof(infoBuffer); error = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong); if ( error == noErr ) { if ( hasAccessCntl(infoBuffer) && (dstServerAdr == infoBuffer.vMServerAdr) ) { /* both volumes support directory access control and they are */ /* on same server, so copy the access information */ error = HGetDirAccess(srcVRefNum, srcDirID, srcName, &ownerID, &groupID, &accessRights); if ( error == noErr ) { error = HSetDirAccess(dstVRefNum, dstDirID, dstName, ownerID, groupID, accessRights); } } else { /* destination doesn't support directory access control or */ /* they volumes aren't on the same server */ error = paramErr; } } } else { /* destination doesn't support directory access control */ error = paramErr; } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec, const FSSpec *dstSpec) { return ( CopyDirectoryAccess(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->vRefNum, dstSpec->parID, dstSpec->name) ); } /*****************************************************************************/ pascal OSErr HMoveRenameCompat(short vRefNum, long srcDirID, ConstStr255Param srcName, long dstDirID, ConstStr255Param dstpathName, ConstStr255Param copyName) { OSErr error; GetVolParmsInfoBuffer volParmsInfo; long infoSize; short realVRefNum; long realParID; Str31 realName; Boolean isDirectory; long tempItemsDirID; long uniqueTempDirID; Str31 uniqueTempDirName; unsigned short uniqueNameoverflow; /* Get volume attributes */ infoSize = sizeof(GetVolParmsInfoBuffer); error = HGetVolParms((StringPtr)srcName, vRefNum, &volParmsInfo, &infoSize); if ( (error == noErr) && hasMoveRename(volParmsInfo) ) { /* If volume supports move and rename, so use it and return */ error = HMoveRename(vRefNum, srcDirID, srcName, dstDirID, dstpathName, copyName); } else if ( (error == noErr) || (error == paramErr) ) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ { /* MoveRename isn't supported by this volume, so do it by hand */ /* If copyName isn't supplied, we can simply CatMove and return */ if ( copyName == NULL ) { error = CatMove(vRefNum, srcDirID, srcName, dstDirID, dstpathName); } else { /* Renaming is required, so we have some work to do... */ /* Get the object's real name, real parent ID and real vRefNum */ error = GetObjectLocation(vRefNum, srcDirID, (StringPtr)srcName, &realVRefNum, &realParID, realName, &isDirectory); if ( error == noErr ) { /* Find the Temporary Items Folder on that volume */ error = FindFolder(realVRefNum, kTemporaryFolderType, kCreateFolder, &realVRefNum, &tempItemsDirID); if ( error == noErr ) { /* Create a new uniquely named folder in the temporary items folder. */ /* This is done to avoid the case where 'realName' or 'copyName' already */ /* exists in the temporary items folder. */ /* Start with current tick count as uniqueTempDirName */ NumToString(TickCount(), uniqueTempDirName); uniqueNameoverflow = 0; do { error = DirCreate(realVRefNum, tempItemsDirID, uniqueTempDirName, &uniqueTempDirID); if ( error == dupFNErr ) { /* Duplicate name - change the first character to the next ASCII character */ ++uniqueTempDirName[1]; /* Make sure it isn't a colon! */ if ( uniqueTempDirName[1] == ':' ) { ++uniqueTempDirName[1]; } /* Don't go too far... */ ++uniqueNameoverflow; } } while ( (error == dupFNErr) && (uniqueNameoverflow <= 64) ); /* 64 new files per 1/60th second - not likely! */ if ( error == noErr ) { /* Move the object to the folder with uniqueTempDirID for renaming */ error = CatMove(realVRefNum, realParID, realName, uniqueTempDirID, NULL); if ( error == noErr ) { /* Rename the object */ error = HRename(realVRefNum, uniqueTempDirID, realName, copyName); if ( error == noErr ) { /* Move object to its new home */ error = CatMove(realVRefNum, uniqueTempDirID, copyName, dstDirID, dstpathName); if ( error != noErr ) { /* Error handling: rename object back to original name - ignore errors */ (void) HRename(realVRefNum, uniqueTempDirID, copyName, realName); } } if ( error != noErr ) { /* Error handling: move object back to original location - ignore errors */ (void) CatMove(realVRefNum, uniqueTempDirID, realName, realParID, NULL); } } /* Done with ourTempDir, so delete it - ignore errors */ (void) HDelete(realVRefNum, uniqueTempDirID, NULL); } } } } } return ( error ); } /*****************************************************************************/ pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec, const FSSpec *dstSpec, ConstStr255Param copyName) { /* make sure the FSSpecs refer to the same volume */ if (srcSpec->vRefNum != dstSpec->vRefNum) return (diffVolErr); return ( HMoveRenameCompat(srcSpec->vRefNum, srcSpec->parID, srcSpec->name, dstSpec->parID, dstSpec->name, copyName) ); } /*****************************************************************************/ pascal OSErr BuildAFPVolMountInfo(short flags, char nbpInterval, char nbpCount, short uamType, Str32 zoneName, Str32 serverName, Str27 volName, Str31 userName, Str8 userPassword, Str8 volPassword, AFPVolMountInfoPtr *afpInfoPtr) { MyAFPVolMountInfoPtr infoPtr; OSErr error; /* Allocate the AFPXVolMountInfo record */ infoPtr = (MyAFPVolMountInfoPtr)NewPtrClear(sizeof(MyAFPVolMountInfo)); if ( infoPtr != NULL ) { /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */ infoPtr->length = sizeof(MyAFPVolMountInfo); infoPtr->media = AppleShareMediaType; infoPtr->flags = flags; infoPtr->nbpInterval = nbpInterval; infoPtr->nbpCount = nbpCount; infoPtr->uamType = uamType; infoPtr->zoneNameOffset = offsetof(MyAFPVolMountInfo, zoneName); infoPtr->serverNameOffset = offsetof(MyAFPVolMountInfo, serverName); infoPtr->volNameOffset = offsetof(MyAFPVolMountInfo, volName); infoPtr->userNameOffset = offsetof(MyAFPVolMountInfo, userName); infoPtr->userPasswordOffset = offsetof(MyAFPVolMountInfo, userPassword); infoPtr->volPasswordOffset = offsetof(MyAFPVolMountInfo, volPassword); BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); *afpInfoPtr = (AFPVolMountInfoPtr)infoPtr; error = noErr; } else { error = memFullErr; } return ( error ); } /*****************************************************************************/ pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr afpInfoPtr, short *flags, short *uamType, StringPtr zoneName, StringPtr serverName, StringPtr volName, StringPtr userName) { StringPtr tempPtr; OSErr error; /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ if ( afpInfoPtr->media == AppleShareMediaType ) { *flags = afpInfoPtr->flags; *uamType = afpInfoPtr->uamType; if ( afpInfoPtr->zoneNameOffset != 0) { tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->zoneNameOffset); BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); } if ( afpInfoPtr->serverNameOffset != 0) { tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->serverNameOffset); BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); } if ( afpInfoPtr->volNameOffset != 0) { tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->volNameOffset); BlockMoveData(tempPtr, volName, tempPtr[0] + 1); } if ( afpInfoPtr->userNameOffset != 0) { tempPtr = (StringPtr)((long)afpInfoPtr + afpInfoPtr->userNameOffset); BlockMoveData(tempPtr, userName, tempPtr[0] + 1); } error = noErr; } else { error = paramErr; } return ( error ); } /*****************************************************************************/ pascal OSErr BuildAFPXVolMountInfo(short flags, char nbpInterval, char nbpCount, short uamType, Str32 zoneName, Str32 serverName, Str27 volName, Str31 userName, Str8 userPassword, Str8 volPassword, Str32 uamName, unsigned long alternateAddressLength, void *alternateAddress, AFPXVolMountInfoPtr *afpXInfoPtr) { Size infoSize; MyAFPXVolMountInfoPtr infoPtr; OSErr error; /* Calculate the size of the AFPXVolMountInfo record */ infoSize = sizeof(MyAFPXVolMountInfo) + alternateAddressLength - 1; /* Allocate the AFPXVolMountInfo record */ infoPtr = (MyAFPXVolMountInfoPtr)NewPtrClear(infoSize); if ( infoPtr != NULL ) { /* Fill in an AFPXVolMountInfo record that can be passed to VolumeMount */ infoPtr->length = infoSize; infoPtr->media = AppleShareMediaType; infoPtr->flags = flags; if ( alternateAddressLength != 0 ) { /* make sure the volMountExtendedFlagsBit is set if there's extended address info */ infoPtr->flags |= volMountExtendedFlagsMask; /* and set the only extendedFlags bit we know about */ infoPtr->extendedFlags = kAFPExtendedFlagsAlternateAddressMask; } else { /* make sure the volMountExtendedFlagsBit is clear if there's no extended address info */ infoPtr->flags &= ~volMountExtendedFlagsMask; /* and clear the extendedFlags */ infoPtr->extendedFlags = 0; } infoPtr->nbpInterval = nbpInterval; infoPtr->nbpCount = nbpCount; infoPtr->uamType = uamType; infoPtr->zoneNameOffset = offsetof(MyAFPXVolMountInfo, zoneName); infoPtr->serverNameOffset = offsetof(MyAFPXVolMountInfo, serverName); infoPtr->volNameOffset = offsetof(MyAFPXVolMountInfo, volName); infoPtr->userNameOffset = offsetof(MyAFPXVolMountInfo, userName); infoPtr->userPasswordOffset = offsetof(MyAFPXVolMountInfo, userPassword); infoPtr->volPasswordOffset = offsetof(MyAFPXVolMountInfo, volPassword); infoPtr->uamNameOffset = offsetof(MyAFPXVolMountInfo, uamName); infoPtr->alternateAddressOffset = offsetof(MyAFPXVolMountInfo, alternateAddress); BlockMoveData(zoneName, infoPtr->zoneName, sizeof(Str32)); BlockMoveData(serverName, infoPtr->serverName, sizeof(Str32)); BlockMoveData(volName, infoPtr->volName, sizeof(Str27)); BlockMoveData(userName, infoPtr->userName, sizeof(Str31)); BlockMoveData(userPassword, infoPtr->userPassword, sizeof(Str8)); BlockMoveData(volPassword, infoPtr->volPassword, sizeof(Str8)); BlockMoveData(uamName, infoPtr->uamName, sizeof(Str32)); BlockMoveData(alternateAddress, infoPtr->alternateAddress, alternateAddressLength); *afpXInfoPtr = (AFPXVolMountInfoPtr)infoPtr; error = noErr; } else { error = memFullErr; } return ( error ); } /*****************************************************************************/ pascal OSErr RetrieveAFPXVolMountInfo(AFPXVolMountInfoPtr afpXInfoPtr, short *flags, short *uamType, StringPtr zoneName, StringPtr serverName, StringPtr volName, StringPtr userName, StringPtr uamName, unsigned long *alternateAddressLength, AFPAlternateAddress **alternateAddress) { StringPtr tempPtr; Ptr alternateAddressStart; Ptr alternateAddressEnd; Size alternateAddressDataSize; OSErr error; UInt8 addressCount; /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */ if ( afpXInfoPtr->media == AppleShareMediaType ) { /* default to noErr */ error = noErr; /* Is this an extended record? */ if ( (afpXInfoPtr->flags & volMountExtendedFlagsMask) != 0 ) { if ( ((afpXInfoPtr->extendedFlags & kAFPExtendedFlagsAlternateAddressMask) != 0) && (afpXInfoPtr->alternateAddressOffset != 0) ) { alternateAddressStart = (Ptr)((long)afpXInfoPtr + afpXInfoPtr->alternateAddressOffset); alternateAddressEnd = alternateAddressStart + 1; /* skip over alternate address version byte */ addressCount = *(UInt8*)alternateAddressEnd; /* get the address count */ ++alternateAddressEnd; /* skip over alternate address count byte */ /* alternateAddressEnd now equals &AFPAlternateAddress.fAddressList[0] */ while ( addressCount != 0 ) { /* parse the address list to find the end */ alternateAddressEnd += *(UInt8*)alternateAddressEnd; /* add length of each AFPTagData record */ --addressCount; } /* get the size of the alternateAddressData */ alternateAddressDataSize = alternateAddressEnd - alternateAddressStart; /* allocate memory for it */ *alternateAddress = (AFPAlternateAddress *)NewPtr(alternateAddressDataSize); if ( *alternateAddress != NULL ) { /* and return the data */ BlockMoveData(alternateAddressStart, *alternateAddress, alternateAddressDataSize); *alternateAddressLength = alternateAddressDataSize; } else { /* no memory - fail now */ error = memFullErr; } } if ( error == noErr ) /* fill in more output parameters if everything is OK */ { if ( afpXInfoPtr->uamNameOffset != 0 ) { tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->uamNameOffset); BlockMoveData(tempPtr, uamName, tempPtr[0] + 1); } } } if ( error == noErr ) /* fill in more output parameters if everything is OK */ { *flags = afpXInfoPtr->flags; *uamType = afpXInfoPtr->uamType; if ( afpXInfoPtr->zoneNameOffset != 0 ) { tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->zoneNameOffset); BlockMoveData(tempPtr, zoneName, tempPtr[0] + 1); } if ( afpXInfoPtr->serverNameOffset != 0 ) { tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->serverNameOffset); BlockMoveData(tempPtr, serverName, tempPtr[0] + 1); } if ( afpXInfoPtr->volNameOffset != 0 ) { tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->volNameOffset); BlockMoveData(tempPtr, volName, tempPtr[0] + 1); } if ( afpXInfoPtr->userNameOffset != 0 ) { tempPtr = (StringPtr)((long)afpXInfoPtr + afpXInfoPtr->userNameOffset); BlockMoveData(tempPtr, userName, tempPtr[0] + 1); } } } else { error = paramErr; } return ( error ); } /*****************************************************************************/ pascal OSErr GetUGEntries(short objType, UGEntryPtr entries, long reqEntryCount, long *actEntryCount, long *objID) { HParamBlockRec pb; OSErr error = noErr; UGEntry *endEntryArray; pb.objParam.ioObjType = objType; *actEntryCount = 0; for ( endEntryArray = entries + reqEntryCount; (entries < endEntryArray) && (error == noErr); ++entries ) { pb.objParam.ioObjNamePtr = (StringPtr)entries->name; pb.objParam.ioObjID = *objID; /* Files.h in the universal interfaces, PBGetUGEntrySync takes a CMovePBPtr */ /* as the parameter. Inside Macintosh and the original glue used HParmBlkPtr. */ /* A CMovePBPtr works OK, but this will be changed in the future back to */ /* HParmBlkPtr, so I'm just casting it here. */ error = PBGetUGEntrySync(&pb); if ( error == noErr ) { entries->objID = *objID = pb.objParam.ioObjID; entries->objType = objType; ++*actEntryCount; } } return ( error ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/MoreFiles 1.5/Sources/Search.c ================================================ /* ** Apple Macintosh Developer Technical Support ** ** IndexedSearch and the PBCatSearch compatibility function. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: Search.c ** ** Copyright 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #include #include #define __COMPILINGMOREFILES #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "Search.h" /*****************************************************************************/ enum { /* Number of LevelRecs to add each time the searchStack is grown */ /* 20 levels is probably more than reasonable for most volumes. */ /* If more are needed, they are allocated 20 levels at a time. */ kAdditionalLevelRecs = 20 }; /*****************************************************************************/ /* ** LevelRecs are used to store the directory ID and index whenever ** IndexedSearch needs to either scan a sub-directory, or return control ** to the caller because the call has timed out or the number of ** matches requested has been found. LevelRecs are stored in an array ** used as a stack. */ struct LevelRec { long dirModDate; /* for detecting most (but not all) catalog changes */ long dirID; short index; }; typedef struct LevelRec LevelRec; typedef LevelRec *LevelRecPtr, **LevelRecHandle; /* ** SearchPositionRec is my version of a CatPositionRec. It holds the ** information I need to resuming searching. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct SearchPositionRec { long initialize; /* Goofy checksum of volume information used to make */ /* sure we're resuming a search on the same volume. */ unsigned short stackDepth; /* Current depth on searchStack. */ short priv[11]; /* For future use... */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif typedef struct SearchPositionRec SearchPositionRec; typedef SearchPositionRec *SearchPositionRecPtr; /* ** ExtendedTMTask is a TMTask record extended to hold the timer flag. */ #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #endif struct ExtendedTMTask { TMTask theTask; Boolean stopSearch; /* the Time Mgr task will set stopSearch to */ /* true when the timer expires */ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #endif typedef struct ExtendedTMTask ExtendedTMTask; typedef ExtendedTMTask *ExtendedTMTaskPtr; /*****************************************************************************/ static OSErr CheckVol(ConstStr255Param pathname, short vRefNum, short *realVRefNum, long *volID); static OSErr CheckStack(unsigned short stackDepth, LevelRecHandle searchStack, Size *searchStackSize); static OSErr VerifyUserPB(CSParamPtr userPB, Boolean *includeFiles, Boolean *includeDirs, Boolean *includeNames); static Boolean IsSubString(ConstStr255Param aStringPtr, ConstStr255Param subStringPtr); static Boolean CompareMasked(const long *data1, const long *data2, const long *mask, short longsToCompare); static void CheckForMatches(CInfoPBPtr cPB, CSParamPtr userPB, const Str63 matchName, Boolean includeFiles, Boolean includeDirs); #if __WANTPASCALELIMINATION #undef pascal #endif #if TARGET_RT_MAC_CFM static pascal void TimeOutTask(TMTaskPtr tmTaskPtr); #else static pascal TMTaskPtr GetTMTaskPtr(void); static void TimeOutTask(void); #endif #if __WANTPASCALELIMINATION #define pascal #endif static long GetDirModDate(short vRefNum, long dirID); /*****************************************************************************/ /* ** CheckVol gets the volume's real vRefNum and builds a volID. The volID ** is used to help insure that calls to resume searching with IndexedSearch ** are to the same volume as the last call to IndexedSearch. */ static OSErr CheckVol(ConstStr255Param pathname, short vRefNum, short *realVRefNum, long *volID) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname, vRefNum, &pb); if ( error == noErr ) { /* Return the real vRefNum */ *realVRefNum = pb.volumeParam.ioVRefNum; /* Add together a bunch of things that aren't supposed to change on */ /* a mounted volume that's being searched and that should come up with */ /* a fairly unique number */ *volID = pb.volumeParam.ioVCrDate + pb.volumeParam.ioVRefNum + pb.volumeParam.ioVNmAlBlks + pb.volumeParam.ioVAlBlkSiz + pb.volumeParam.ioVFSID; } return ( error ); } /*****************************************************************************/ /* ** CheckStack checks the size of the search stack (array) to see if there's ** room to push another LevelRec. If not, CheckStack grows the stack by ** another kAdditionalLevelRecs elements. */ static OSErr CheckStack(unsigned short stackDepth, LevelRecHandle searchStack, Size *searchStackSize) { OSErr result; if ( (*searchStackSize / sizeof(LevelRec)) == (stackDepth + 1) ) { /* Time to grow stack */ SetHandleSize((Handle)searchStack, *searchStackSize + (kAdditionalLevelRecs * sizeof(LevelRec))); result = MemError(); /* should be noErr */ *searchStackSize = GetHandleSize((Handle)searchStack); } else { result = noErr; } return ( result ); } /*****************************************************************************/ /* ** VerifyUserPB makes sure the parameter block passed to IndexedSearch has ** valid parameters. By making this check once, we don't have to worry about ** things like NULL pointers, strings being too long, etc. ** VerifyUserPB also determines if the search includes files and/or ** directories, and determines if a full or partial name search was requested. */ static OSErr VerifyUserPB(CSParamPtr userPB, Boolean *includeFiles, Boolean *includeDirs, Boolean *includeNames) { CInfoPBPtr searchInfo1; CInfoPBPtr searchInfo2; searchInfo1 = userPB->ioSearchInfo1; searchInfo2 = userPB->ioSearchInfo2; /* ioMatchPtr cannot be NULL */ if ( userPB->ioMatchPtr == NULL ) { goto ParamErrExit; } /* ioSearchInfo1 cannot be NULL */ if ( searchInfo1 == NULL ) { goto ParamErrExit; } /* If any bits except partialName, fullName, or negate are set, then */ /* ioSearchInfo2 cannot be NULL because information in ioSearchInfo2 is required */ if ( ((userPB->ioSearchBits & ~(fsSBPartialName | fsSBFullName | fsSBNegate)) != 0) && ( searchInfo2 == NULL )) { goto ParamErrExit; } *includeFiles = false; *includeDirs = false; *includeNames = false; if ( (userPB->ioSearchBits & (fsSBPartialName | fsSBFullName)) != 0 ) { /* If any kind of name matching is requested, then ioNamePtr in */ /* ioSearchInfo1 cannot be NULL or a zero-length string */ if ( (searchInfo1->hFileInfo.ioNamePtr == NULL) || (searchInfo1->hFileInfo.ioNamePtr[0] == 0) || (searchInfo1->hFileInfo.ioNamePtr[0] > (sizeof(Str63) - 1)) ) { goto ParamErrExit; } *includeNames = true; } if ( (userPB->ioSearchBits & fsSBFlAttrib) != 0 ) { /* The only attributes you can search on are the directory flag */ /* and the locked flag. */ if ( (searchInfo2->hFileInfo.ioFlAttrib & ~(kioFlAttribDirMask | kioFlAttribLockedMask)) != 0 ) { goto ParamErrExit; } /* interested in the directory bit? */ if ( (searchInfo2->hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* yes, so do they want just directories or just files? */ if ( (searchInfo1->hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { *includeDirs = true; } else { *includeFiles = true; } } else { /* no interest in directory bit - get both files and directories */ *includeDirs = true; *includeFiles = true; } } else { /* no attribute checking - get both files and directories */ *includeDirs = true; *includeFiles = true; } /* If directories are included in the search, */ /* then the locked attribute cannot be requested. */ if ( *includeDirs && ((userPB->ioSearchBits & fsSBFlAttrib) != 0) && ((searchInfo2->hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0) ) { goto ParamErrExit; } /* If files are included in the search, then there cannot be */ /* a search on the number of files. */ if ( *includeFiles && ((userPB->ioSearchBits & fsSBDrNmFls) != 0) ) { goto ParamErrExit; } /* If directories are included in the search, then there cannot */ /* be a search on file lengths. */ if ( *includeDirs && ((userPB->ioSearchBits & (fsSBFlLgLen | fsSBFlPyLen | fsSBFlRLgLen | fsSBFlRPyLen)) != 0) ) { goto ParamErrExit; } return ( noErr ); ParamErrExit: return ( paramErr ); } /*****************************************************************************/ /* ** IsSubString checks to see if a string is a substring of another string. ** Both input strings have already been converted to all uppercase using ** UprString (the same non-international call the File Manager uses). */ static Boolean IsSubString(ConstStr255Param aStringPtr, ConstStr255Param subStringPtr) { short strLength; /* length of string */ short subStrLength; /* length of subString */ Boolean found; /* result of test */ short index; /* current index into string */ found = false; strLength = aStringPtr[0]; subStrLength = subStringPtr[0]; if ( subStrLength <= strLength) { register short count; /* search counter */ register short strIndex; /* running index into string */ register short subStrIndex; /* running index into subString */ /* start looking at first character */ index = 1; /* continue looking until remaining string is shorter than substring */ count = strLength - subStrLength + 1; do { strIndex = index; /* start string index at index */ subStrIndex = 1; /* start subString index at 1 */ while ( !found && (aStringPtr[strIndex] == subStringPtr[subStrIndex]) ) { if ( subStrIndex == subStrLength ) { /* all characters in subString were found */ found = true; } else { /* check next character of substring against next character of string */ ++subStrIndex; ++strIndex; } } if ( !found ) { /* start substring search again at next string character */ ++index; --count; } } while ( count != 0 && (!found) ); } return ( found ); } /*****************************************************************************/ /* ** CompareMasked does a bitwise comparison with mask on 1 or more longs. ** data1 and data2 are first exclusive-ORed together resulting with bits set ** where they are different. That value is then ANDed with the mask resulting ** with bits set if the test fails. true is returned if the tests pass. */ static Boolean CompareMasked(const long *data1, const long *data2, const long *mask, short longsToCompare) { Boolean result = true; while ( (longsToCompare != 0) && (result == true) ) { /* (*data1 ^ *data2) = bits that are different, so... */ /* ((*data1 ^ *data2) & *mask) = bits that are different that we're interested in */ if ( ((*data1 ^ *data2) & *mask) != 0 ) result = false; ++data1; ++data2; ++mask; --longsToCompare; } return ( result ); } /*****************************************************************************/ /* ** Check for matches compares the search criteria in userPB to the file ** system object in cPB. If there's a match, then the information in cPB is ** is added to the match array and the actual match count is incremented. */ static void CheckForMatches(CInfoPBPtr cPB, CSParamPtr userPB, const Str63 matchName, Boolean includeFiles, Boolean includeDirs) { long searchBits; CInfoPBPtr searchInfo1; CInfoPBPtr searchInfo2; Str63 itemName; /* copy of object's name for partial name matching */ Boolean foundMatch; foundMatch = false; /* default to no match */ searchBits = userPB->ioSearchBits; searchInfo1 = userPB->ioSearchInfo1; searchInfo2 = userPB->ioSearchInfo2; /* Into the if statements that go on forever... */ if ( (cPB->hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 ) { if (!includeFiles) { goto Failed; } } else { if (!includeDirs) { goto Failed; } } if ( (searchBits & fsSBPartialName) != 0 ) { if ( (cPB->hFileInfo.ioNamePtr[0] > 0) && (cPB->hFileInfo.ioNamePtr[0] <= (sizeof(Str63) - 1)) ) { /* Make uppercase copy of object name */ BlockMoveData(cPB->hFileInfo.ioNamePtr, itemName, cPB->hFileInfo.ioNamePtr[0] + 1); /* Use the same non-international call the File Manager uses */ UpperString(itemName, true); } else { goto Failed; } { if ( !IsSubString(itemName, matchName) ) { goto Failed; } else if ( searchBits == fsSBPartialName ) { /* optimize for name matching only since it is most common way to search */ goto Hit; } } } if ( (searchBits & fsSBFullName) != 0 ) { /* Use the same non-international call the File Manager uses */ if ( !EqualString(cPB->hFileInfo.ioNamePtr, matchName, false, true) ) { goto Failed; } else if ( searchBits == fsSBFullName ) { /* optimize for name matching only since it is most common way to search */ goto Hit; } } if ( (searchBits & fsSBFlParID) != 0 ) { if ( ((unsigned long)(cPB->hFileInfo.ioFlParID) < (unsigned long)(searchInfo1->hFileInfo.ioFlParID)) || ((unsigned long)(cPB->hFileInfo.ioFlParID) > (unsigned long)(searchInfo2->hFileInfo.ioFlParID)) ) { goto Failed; } } if ( (searchBits & fsSBFlAttrib) != 0 ) { if ( ((cPB->hFileInfo.ioFlAttrib ^ searchInfo1->hFileInfo.ioFlAttrib) & searchInfo2->hFileInfo.ioFlAttrib) != 0 ) { goto Failed; } } if ( (searchBits & fsSBDrNmFls) != 0 ) { if ( ((unsigned long)(cPB->dirInfo.ioDrNmFls) < (unsigned long)(searchInfo1->dirInfo.ioDrNmFls)) || ((unsigned long)(cPB->dirInfo.ioDrNmFls) > (unsigned long)(searchInfo2->dirInfo.ioDrNmFls)) ) { goto Failed; } } if ( (searchBits & fsSBFlFndrInfo) != 0 ) /* fsSBFlFndrInfo is same as fsSBDrUsrWds */ { if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlFndrInfo), (long *)&(searchInfo1->hFileInfo.ioFlFndrInfo), (long *)&(searchInfo2->hFileInfo.ioFlFndrInfo), sizeof(FInfo) / sizeof(long)) ) { goto Failed; } } if ( (searchBits & fsSBFlXFndrInfo) != 0 ) /* fsSBFlXFndrInfo is same as fsSBDrFndrInfo */ { if ( !CompareMasked((long *)&(cPB->hFileInfo.ioFlXFndrInfo), (long *)&(searchInfo1->hFileInfo.ioFlXFndrInfo), (long *)&(searchInfo2->hFileInfo.ioFlXFndrInfo), sizeof(FXInfo) / sizeof(long)) ) { goto Failed; } } if ( (searchBits & fsSBFlLgLen) != 0 ) { if ( ((unsigned long)(cPB->hFileInfo.ioFlLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlLgLen)) || ((unsigned long)(cPB->hFileInfo.ioFlLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlLgLen)) ) { goto Failed; } } if ( (searchBits & fsSBFlPyLen) != 0 ) { if ( ((unsigned long)(cPB->hFileInfo.ioFlPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlPyLen)) || ((unsigned long)(cPB->hFileInfo.ioFlPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlPyLen)) ) { goto Failed; } } if ( (searchBits & fsSBFlRLgLen) != 0 ) { if ( ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRLgLen)) || ((unsigned long)(cPB->hFileInfo.ioFlRLgLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRLgLen)) ) { goto Failed; } } if ( (searchBits & fsSBFlRPyLen) != 0 ) { if ( ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) < (unsigned long)(searchInfo1->hFileInfo.ioFlRPyLen)) || ((unsigned long)(cPB->hFileInfo.ioFlRPyLen) > (unsigned long)(searchInfo2->hFileInfo.ioFlRPyLen)) ) { goto Failed; } } if ( (searchBits & fsSBFlCrDat) != 0 ) /* fsSBFlCrDat is same as fsSBDrCrDat */ { if ( ((unsigned long)(cPB->hFileInfo.ioFlCrDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlCrDat)) || ((unsigned long)(cPB->hFileInfo.ioFlCrDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlCrDat)) ) { goto Failed; } } if ( (searchBits & fsSBFlMdDat) != 0 ) /* fsSBFlMdDat is same as fsSBDrMdDat */ { if ( ((unsigned long)(cPB->hFileInfo.ioFlMdDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlMdDat)) || ((unsigned long)(cPB->hFileInfo.ioFlMdDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlMdDat)) ) { goto Failed; } } if ( (searchBits & fsSBFlBkDat) != 0 ) /* fsSBFlBkDat is same as fsSBDrBkDat */ { if ( ((unsigned long)(cPB->hFileInfo.ioFlBkDat) < (unsigned long)(searchInfo1->hFileInfo.ioFlBkDat)) || ((unsigned long)(cPB->hFileInfo.ioFlBkDat) > (unsigned long)(searchInfo2->hFileInfo.ioFlBkDat)) ) { goto Failed; } } /* Hey, we passed all of the tests! */ Hit: foundMatch = true; /* foundMatch is false if code jumps to Failed */ Failed: /* Do we reverse our findings? */ if ( (searchBits & fsSBNegate) != 0 ) { foundMatch = !foundMatch; /* matches are not, not matches are */ } if ( foundMatch ) { /* Move the match into the match buffer */ userPB->ioMatchPtr[userPB->ioActMatchCount].vRefNum = cPB->hFileInfo.ioVRefNum; userPB->ioMatchPtr[userPB->ioActMatchCount].parID = cPB->hFileInfo.ioFlParID; if ( cPB->hFileInfo.ioNamePtr[0] > 63 ) { cPB->hFileInfo.ioNamePtr[0] = 63; } BlockMoveData(cPB->hFileInfo.ioNamePtr, userPB->ioMatchPtr[userPB->ioActMatchCount].name, cPB->hFileInfo.ioNamePtr[0] + 1); /* increment the actual count */ ++(userPB->ioActMatchCount); } } /*****************************************************************************/ /* ** TimeOutTask is executed when the timer goes off. It simply sets the ** stopSearch field to true. After each object is found and possibly added ** to the matches buffer, stopSearch is checked to see if the search should ** continue. */ #if __WANTPASCALELIMINATION #undef pascal #endif #if TARGET_RT_MAC_CFM static pascal void TimeOutTask(TMTaskPtr tmTaskPtr) { ((ExtendedTMTaskPtr)tmTaskPtr)->stopSearch = true; } #else static pascal TMTaskPtr GetTMTaskPtr(void) ONEWORDINLINE(0x2e89); /* MOVE.L A1,(SP) */ static void TimeOutTask(void) { ((ExtendedTMTaskPtr)GetTMTaskPtr())->stopSearch = true; } #endif #if __WANTPASCALELIMINATION #define pascal #endif /*****************************************************************************/ /* ** GetDirModDate returns the modification date of a directory. If there is ** an error getting the modification date, -1 is returned to indicate ** something went wrong. */ static long GetDirModDate(short vRefNum, long dirID) { CInfoPBRec pb; Str31 tempName; long modDate; /* Protection against File Sharing problem */ tempName[0] = 0; pb.dirInfo.ioNamePtr = tempName; pb.dirInfo.ioVRefNum = vRefNum; pb.dirInfo.ioDrDirID = dirID; pb.dirInfo.ioFDirIndex = -1; /* use ioDrDirID */ if ( PBGetCatInfoSync(&pb) == noErr ) { modDate = pb.dirInfo.ioDrMdDat; } else { modDate = -1; } return ( modDate ); } /*****************************************************************************/ pascal OSErr IndexedSearch(CSParamPtr pb, long dirID) { static LevelRecHandle searchStack = NULL; /* static handle to LevelRec stack */ static Size searchStackSize = 0; /* size of static handle */ SearchPositionRecPtr catPosition; long modDate; short index; ExtendedTMTask timerTask; OSErr result; short realVRefNum; Str63 itemName; CInfoPBRec cPB; long tempLong; Boolean includeFiles; Boolean includeDirs; Boolean includeNames; Str63 upperName; timerTask.stopSearch = false; /* don't stop yet! */ /* If request has a timeout, install a Time Manager task. */ if ( pb->ioSearchTime != 0 ) { /* Start timer */ timerTask.theTask.tmAddr = NewTimerUPP(TimeOutTask); InsTime((QElemPtr)&(timerTask.theTask)); PrimeTime((QElemPtr)&(timerTask.theTask), pb->ioSearchTime); } /* Check the parameter block passed for things that we don't want to assume */ /* are OK later in the code. For example, make sure pointers to data structures */ /* and buffers are not NULL. And while we're in there, see if the request */ /* specified searching for files, directories, or both, and see if the search */ /* was by full or partial name. */ result = VerifyUserPB(pb, &includeFiles, &includeDirs, &includeNames); if ( result == noErr ) { pb->ioActMatchCount = 0; /* no matches yet */ if ( includeNames ) { /* The search includes seach by full or partial name. */ /* Make an upper case copy of the match string to pass to */ /* CheckForMatches. */ BlockMoveData(pb->ioSearchInfo1->hFileInfo.ioNamePtr, upperName, pb->ioSearchInfo1->hFileInfo.ioNamePtr[0] + 1); /* Use the same non-international call the File Manager uses */ UpperString(upperName, true); } /* Prevent casting to my type throughout code */ catPosition = (SearchPositionRecPtr)&pb->ioCatPosition; /* Create searchStack first time called */ if ( searchStack == NULL ) { searchStack = (LevelRecHandle)NewHandle(kAdditionalLevelRecs * sizeof(LevelRec)); } /* Make sure searchStack really exists */ if ( searchStack != NULL ) { searchStackSize = GetHandleSize((Handle)searchStack); /* See if the search is a new search or a resumed search. */ if ( catPosition->initialize == 0 ) { /* New search. */ /* Get the real vRefNum and fill in catPosition->initialize. */ result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &catPosition->initialize); if ( result == noErr ) { /* clear searchStack */ catPosition->stackDepth = 0; /* use dirID parameter passed and... */ index = -1; /* start with the passed directory itself! */ } } else { /* We're resuming a search. */ /* Get the real vRefNum and make sure catPosition->initialize is valid. */ result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &tempLong); if ( result == noErr ) { /* Make sure the resumed search is to the same volume! */ if ( catPosition->initialize == tempLong ) { /* For resume, catPosition->stackDepth > 0 */ if ( catPosition->stackDepth > 0 ) { /* Position catPosition->stackDepth to access last saved level */ --(catPosition->stackDepth); /* Get the dirID and index for the next item */ dirID = (*searchStack)[catPosition->stackDepth].dirID; index = (*searchStack)[catPosition->stackDepth].index; /* Check the dir's mod date against the saved mode date on our "stack" */ modDate = GetDirModDate(realVRefNum, dirID); if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) { result = catChangedErr; } } else { /* Invalid catPosition record was passed */ result = paramErr; } } else { /* The volume is not the same */ result = catChangedErr; } } } if ( result == noErr ) { /* ioNamePtr and ioVRefNum only need to be set up once. */ cPB.hFileInfo.ioNamePtr = itemName; cPB.hFileInfo.ioVRefNum = realVRefNum; /* ** Here's the loop that: ** Finds the next item on the volume. ** If noErr, calls the code to check for matches and add matches ** to the match buffer. ** Sets up dirID and index for to find the next item on the volume. ** ** The looping ends when: ** (a) an unexpected error is returned by PBGetCatInfo. All that ** is expected is noErr and fnfErr (after the last item in a ** directory is found). ** (b) the caller specified a timeout and our Time Manager task ** has fired. ** (c) the number of matches requested by the caller has been found. ** (d) the last item on the volume was found. */ do { /* get the next item */ cPB.hFileInfo.ioFDirIndex = index; cPB.hFileInfo.ioDirID = dirID; result = PBGetCatInfoSync(&cPB); if ( index != -1 ) { if ( result == noErr ) { /* We found something */ CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); ++index; if ( (cPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* It's a directory */ result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); if ( result == noErr ) { /* Save the current state on the searchStack */ /* when we come back, this is where we'll start */ (*searchStack)[catPosition->stackDepth].dirID = dirID; (*searchStack)[catPosition->stackDepth].index = index; (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); /* position catPosition->stackDepth for next saved level */ ++(catPosition->stackDepth); /* The next item to get is the 1st item in the child directory */ dirID = cPB.dirInfo.ioDrDirID; index = 1; } } /* else do nothing for files */ } else { /* End of directory found (or we had some error and that */ /* means we have to drop out of this directory). */ /* Restore last thing put on stack and */ /* see if we need to continue or quit. */ if ( catPosition->stackDepth > 0 ) { /* position catPosition->stackDepth to access last saved level */ --(catPosition->stackDepth); dirID = (*searchStack)[catPosition->stackDepth].dirID; index = (*searchStack)[catPosition->stackDepth].index; /* Check the dir's mod date against the saved mode date on our "stack" */ modDate = GetDirModDate(realVRefNum, dirID); if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) { result = catChangedErr; } else { /* Going back to ancestor directory. */ /* Clear error so we can continue. */ result = noErr; } } else { /* We hit the bottom of the stack, so we'll let the */ /* the eofErr drop us out of the loop. */ result = eofErr; } } } else { /* Special case for index == -1; that means that we're starting */ /* a new search and so the first item to check is the directory */ /* passed to us. */ if ( result == noErr ) { /* We found something */ CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); /* Now, set the index to 1 and then we're ready to look inside */ /* the passed directory. */ index = 1; } } } while ( (!timerTask.stopSearch) && /* timer hasn't fired */ (result == noErr) && /* no unexpected errors */ (pb->ioReqMatchCount > pb->ioActMatchCount) ); /* we haven't found our limit */ /* Did we drop out of the loop because of timeout or */ /* ioReqMatchCount was found? */ if ( result == noErr ) { result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); if ( result == noErr ) { /* Either there was a timeout or ioReqMatchCount was reached. */ /* Save the dirID and index for the next time we're called. */ (*searchStack)[catPosition->stackDepth].dirID = dirID; (*searchStack)[catPosition->stackDepth].index = index; (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); /* position catPosition->stackDepth for next saved level */ ++(catPosition->stackDepth); } } } } else { /* searchStack Handle could not be allocated */ result = memFullErr; } } if ( pb->ioSearchTime != 0 ) { /* Stop Time Manager task here if it was installed */ RmvTime((QElemPtr)&(timerTask.theTask)); DisposeTimerUPP(timerTask.theTask.tmAddr); } return ( result ); } /*****************************************************************************/ pascal OSErr PBCatSearchSyncCompat(CSParamPtr paramBlock) { OSErr result; Boolean supportsCatSearch; GetVolParmsInfoBuffer volParmsInfo; long infoSize; #if !__MACOSSEVENORLATER static Boolean fullExtFSDispatchingtested = false; static Boolean hasFullExtFSDispatching = false; long response; #endif result = noErr; #if !__MACOSSEVENORLATER /* See if File Manager will pass CatSearch requests to external file systems */ /* we'll store the results in a static variable so we don't have to call Gestalt */ /* everytime we're called. (System 7.0 and later always do this) */ if ( !fullExtFSDispatchingtested ) { fullExtFSDispatchingtested = true; if ( Gestalt(gestaltFSAttr, &response) == noErr ) { hasFullExtFSDispatching = ((response & (1L << gestaltFullExtFSDispatching)) != 0); } } #endif /* CatSearch is a per volume attribute, so we have to check each time we're */ /* called to see if it is available on the volume specified. */ supportsCatSearch = false; #if !__MACOSSEVENORLATER if ( hasFullExtFSDispatching ) #endif { infoSize = sizeof(GetVolParmsInfoBuffer); result = HGetVolParms(paramBlock->ioNamePtr, paramBlock->ioVRefNum, &volParmsInfo, &infoSize); if ( result == noErr ) { supportsCatSearch = hasCatSearch(volParmsInfo); } } /* noErr or paramErr is OK here. */ /* paramErr just means that GetVolParms isn't supported by this volume */ if ( (result == noErr) || (result == paramErr) ) { if ( supportsCatSearch ) { /* Volume supports CatSearch so use it. */ /* CatSearch is faster than an indexed search. */ result = PBCatSearchSync(paramBlock); } else { /* Volume doesn't support CatSearch so */ /* search using IndexedSearch from root directory. */ result = IndexedSearch(paramBlock, fsRtDirID); } } return ( result ); } /*****************************************************************************/ pascal OSErr NameFileSearch(ConstStr255Param volName, short vRefNum, ConstStr255Param fileName, FSSpecPtr matches, long reqMatchCount, long *actMatchCount, Boolean newSearch, Boolean partial) { CInfoPBRec searchInfo1, searchInfo2; HParamBlockRec pb; OSErr error; static CatPositionRec catPosition; static short lastVRefNum = 0; /* get the real volume reference number */ error = DetermineVRefNum(volName, vRefNum, &vRefNum); if ( error != noErr ) return ( error ); pb.csParam.ioNamePtr = NULL; pb.csParam.ioVRefNum = vRefNum; pb.csParam.ioMatchPtr = matches; pb.csParam.ioReqMatchCount = reqMatchCount; if ( partial ) /* tell CatSearch what we're looking for: */ { pb.csParam.ioSearchBits = fsSBPartialName + fsSBFlAttrib; /* partial name file matches or */ } else { pb.csParam.ioSearchBits = fsSBFullName + fsSBFlAttrib; /* full name file matches */ } pb.csParam.ioSearchInfo1 = &searchInfo1; pb.csParam.ioSearchInfo2 = &searchInfo2; pb.csParam.ioSearchTime = 0; if ( (newSearch) || /* If caller specified new search */ (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ { catPosition.initialize = 0; /* then search from beginning of catalog */ } pb.csParam.ioCatPosition = catPosition; pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); /* search for fileName */ searchInfo1.hFileInfo.ioNamePtr = (StringPtr)fileName; searchInfo2.hFileInfo.ioNamePtr = NULL; /* only match files (not directories) */ searchInfo1.hFileInfo.ioFlAttrib = 0x00; searchInfo2.hFileInfo.ioFlAttrib = kioFlAttribDirMask; error = PBCatSearchSyncCompat((CSParamPtr)&pb); if ( (error == noErr) || /* If no errors or the end of catalog was */ (error == eofErr) ) /* found, then the call was successful so */ { *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ } else { *actMatchCount = 0; /* else no matches found */ } if ( (error == noErr) || /* If no errors */ (error == catChangedErr) ) /* or there was a change in the catalog */ { catPosition = pb.csParam.ioCatPosition; lastVRefNum = vRefNum; /* we can probably start the next search where we stopped this time */ } else { catPosition.initialize = 0; /* start the next search from beginning of catalog */ } if ( pb.csParam.ioOptBuffer != NULL ) { DisposePtr(pb.csParam.ioOptBuffer); } return ( error ); } /*****************************************************************************/ pascal OSErr CreatorTypeFileSearch(ConstStr255Param volName, short vRefNum, OSType creator, OSType fileType, FSSpecPtr matches, long reqMatchCount, long *actMatchCount, Boolean newSearch) { CInfoPBRec searchInfo1, searchInfo2; HParamBlockRec pb; OSErr error; static CatPositionRec catPosition; static short lastVRefNum = 0; /* get the real volume reference number */ error = DetermineVRefNum(volName, vRefNum, &vRefNum); if ( error != noErr ) return ( error ); pb.csParam.ioNamePtr = NULL; pb.csParam.ioVRefNum = vRefNum; pb.csParam.ioMatchPtr = matches; pb.csParam.ioReqMatchCount = reqMatchCount; pb.csParam.ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo; /* Looking for finder info file matches */ pb.csParam.ioSearchInfo1 = &searchInfo1; pb.csParam.ioSearchInfo2 = &searchInfo2; pb.csParam.ioSearchTime = 0; if ( (newSearch) || /* If caller specified new search */ (lastVRefNum != vRefNum) ) /* or if last search was to another volume, */ { catPosition.initialize = 0; /* then search from beginning of catalog */ } pb.csParam.ioCatPosition = catPosition; pb.csParam.ioOptBuffer = GetTempBuffer(0x00004000, &pb.csParam.ioOptBufSize); /* no fileName */ searchInfo1.hFileInfo.ioNamePtr = NULL; searchInfo2.hFileInfo.ioNamePtr = NULL; /* only match files (not directories) */ searchInfo1.hFileInfo.ioFlAttrib = 0x00; searchInfo2.hFileInfo.ioFlAttrib = kioFlAttribDirMask; /* search for creator; if creator = 0x00000000, ignore creator */ searchInfo1.hFileInfo.ioFlFndrInfo.fdCreator = creator; if ( creator == (OSType)0x00000000 ) { searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0x00000000; } else { searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (OSType)0xffffffff; } /* search for fileType; if fileType = 0x00000000, ignore fileType */ searchInfo1.hFileInfo.ioFlFndrInfo.fdType = fileType; if ( fileType == (OSType)0x00000000 ) { searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0x00000000; } else { searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (OSType)0xffffffff; } /* zero all other FInfo fields */ searchInfo1.hFileInfo.ioFlFndrInfo.fdFlags = 0; searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; searchInfo1.hFileInfo.ioFlFndrInfo.fdFldr = 0; searchInfo2.hFileInfo.ioFlFndrInfo.fdFlags = 0; searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0; searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0; searchInfo2.hFileInfo.ioFlFndrInfo.fdFldr = 0; error = PBCatSearchSyncCompat((CSParamPtr)&pb); if ( (error == noErr) || /* If no errors or the end of catalog was */ (error == eofErr) ) /* found, then the call was successful so */ { *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */ } else { *actMatchCount = 0; /* else no matches found */ } if ( (error == noErr) || /* If no errors */ (error == catChangedErr) ) /* or there was a change in the catalog */ { catPosition = pb.csParam.ioCatPosition; lastVRefNum = vRefNum; /* we can probably start the next search where we stopped this time */ } else { catPosition.initialize = 0; /* start the next search from beginning of catalog */ } if ( pb.csParam.ioOptBuffer != NULL ) { DisposePtr(pb.csParam.ioOptBuffer); } return ( error ); } /*****************************************************************************/ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/sqMacFileCopy.c ================================================ /* Use the extra files logic from Apple to copy a directory or file to another directory or file */ //John M McIntosh johnmci@smalltalkconsulting.com Aug 21 2001 Chunnel build #include #include "FileCopy.h" #include "FullPath.h" #include "DirectoryCopy.h" #include "MoreFilesExtras.h" #include "FSpCompat.h" #include "sqMacFileCopy.h" int sqCopyFilesizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize) { OSErr error; FSSpec srcSpec,dstFileSpec,dstSpec; char *pointer; const int desiredBufferSize = 64*1024; FSpLocationFromFullPath(srcNameSize,srcNameIndex,&srcSpec); FSpLocationFromFullPath(dstNameSize,dstNameIndex,&dstFileSpec); FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, "\p:", &dstSpec); #if TARGET_API_MAC_CARBON pointer = NewPtr(desiredBufferSize); #else pointer = NewPtr(desiredBufferSize); if (pointer == NULL) pointer = NewPtrSys(desiredBufferSize); if (pointer == NULL) return false; #endif error = FSpFileCopy(&srcSpec, &dstSpec, dstFileSpec.name, pointer, desiredBufferSize, false); DisposePtr((void *)pointer); return error; } int sqCopyDirectorysizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize) { OSErr error; FSSpec srcSpec,dstSpec,dstFolderSpec; char *pointer; const int desiredBufferSize = 64*1024; char name[256]; memmove(name,srcNameIndex,srcNameSize); memmove(name+srcNameSize,":",1); FSpLocationFromFullPath(srcNameSize+1,name,&srcSpec); memmove(name,dstNameIndex,dstNameSize); memmove(name+dstNameSize,":",1); FSpLocationFromFullPath(dstNameSize+1,name,&dstFolderSpec); FSMakeFSSpecCompat(dstFolderSpec.vRefNum, dstFolderSpec.parID, "\p:", &dstSpec); #if TARGET_API_MAC_CARBON pointer = NewPtr(desiredBufferSize); #else pointer = NewPtr(desiredBufferSize); if (pointer == NULL) pointer = NewPtrSys(desiredBufferSize); if (pointer == NULL) return false; #endif memmove(name,dstFolderSpec.name,sizeof(dstFolderSpec.name)); error = FSpDirectoryCopy(&srcSpec, &dstSpec, (ConstStr255Param) &name, pointer, desiredBufferSize, false, &handleDupError); DisposePtr((void *)pointer); return error; } pascal Boolean handleDupError(OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName) { if (error == dupFNErr ) return false; return true; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FileCopyPlugin/sqMacFileCopy.h ================================================ int sqCopyFilesizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize); int sqCopyDirectorysizetosize(char *srcNameIndex, int srcNameSize, char *dstNameIndex, int dstNameSize); pascal Boolean handleDupError(OSErr error, short failedOperation, short srcVRefNum, long srcDirID, ConstStr255Param srcName, short dstVRefNum, long dstDirID, ConstStr255Param dstName); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FilePlugin/sqMacDirectory.c ================================================ /**************************************************************************** * PROJECT: Mac directory logic * FILE: sqMacDirectory.c * CONTENT: * * AUTHOR: John McIntosh, and others. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacDirectory.c 1197 2005-05-31 05:51:16Z johnmci $ * * NOTES: See change log below. * Feb 2nd 2001, JMM rewrote, using more current file manager logic. 3.0.7 return correct response on findimage 3.0.10 Mimimal VM logic 3.0.11 April 4th fix bug in lookupPath (users never saw it) 3.0.14 May 2001 lookupPath needs to abort on :: can't do hardway lookup, too complicated 3.0.17 May 24th 2001 JMM add flush vol on flush file (needed according to apple tech notes) 3.0.19 Aug 2001 JMM make it a real plugin 3.2.1 Nov 2001 JMM build with Apple's project builder and convert to use StdCLib. 3.2.1B5 Dec 27,2001 JMM alter mkdir def to make cw pro 5 happy 3.2.1B6 Jan 2,2002 JMM make lookup faster 3.2.2B1 Jan 18th,2002 JMM check macroman, fix issues with squeak file offset 3.2.8b1 July 24th, 2002 JMM support for os-x plugin under IE 5.x 3.5.1b1 May 20th, 2003 JMM isDirectory ? ENTRY_FOUND versus always found because path could be a file. 3.7.0bx Nov 24th, 2003 JMM gCurrentVMEncoding */ #include "sq.h" #include "FilePlugin.h" #include "sqMacFileLogic.h" #if TARGET_API_MAC_CARBON #include #include #include extern CFStringEncoding gCurrentVMEncoding; #else #if defined(__MWERKS__) && !defined(__APPLE__) && !defined(__MACH__) #include int mkdir(const char *,int); int ftruncate(short int file,int offset); #endif #include #include #endif /*** The interface to the directory primitive is path based. That is, the client supplies a Squeak string describing the path to the directory on every call. To avoid traversing this path on every call, a cache is maintained of the last path seen, along with the Mac volume and folder reference numbers corresponding to that path. ***/ /*** Constants ***/ #define ENTRY_FOUND 0 #define NO_MORE_ENTRIES 1 #define BAD_PATH 2 #define DELIMITOR ':' #define MAX_PATH 2000 /*** Variables ***/ char lastPath[MAX_PATH + 1]; int lastPathValid = false; FSSpec lastSpec; /*** Functions ***/ int convertToSqueakTime(int macTime); int equalsLastPath(char *pathString, int pathStringLength); int recordPath(char *pathString, int pathStringLength, FSSpec *spec); OSErr getSpecAndFInfo(char *filename, int filenameSize,FSSpec *spec,FInfo *finderInfo); int convertToSqueakTime(int macTime) { /* Squeak epoch is Jan 1, 1901, 3 non-leap years earlier than Mac one */ return macTime + (3 * 365 * 24 * 60 * 60); } #if TARGET_API_MAC_CARBON int dir_Create(char *pathString, int pathStringLength) { /* Create a new directory with the given path. By default, this directory is created in the current directory. Use a full path name such as "MyDisk:Working:New Folder" to create folders elsewhere. */ char cFileName[1001]; if (pathStringLength >= 1000) { return false; } /* copy the file name into a null-terminated C string */ sqFilenameFromString((char *) cFileName, (int) pathString, pathStringLength); #if defined(__MWERKS__) { CFStringRef filePath,lastFilePath; CFURLRef sillyThing,sillyThing2; FSRef parentFSRef; UniChar buffer[1024]; long tokenLength; int err; filePath = CFStringCreateWithBytes(kCFAllocatorDefault,(UInt8 *)cFileName,strlen(cFileName),gCurrentVMEncoding,false); if (filePath == nil) return false; sillyThing = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,filePath,kCFURLHFSPathStyle,true); CFRelease(filePath); lastFilePath = CFURLCopyLastPathComponent(sillyThing); tokenLength = CFStringGetLength(lastFilePath); if (tokenLength > 1024) return false; CFStringGetCharacters(lastFilePath,CFRangeMake(0,tokenLength),buffer); CFRelease(lastFilePath); sillyThing2 = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault,sillyThing); err = CFURLGetFSRef(sillyThing2,&parentFSRef); CFRelease(sillyThing); CFRelease(sillyThing2); if (err == 0) { return false; } err = FSCreateDirectoryUnicode(&parentFSRef,tokenLength,buffer,kFSCatInfoNone,NULL,NULL,NULL,NULL); return (err == noErr ? 1 : 0); } #else return mkdir(cFileName, 0777) == 0; #endif } int dir_Delete(char *pathString, int pathStringLength) { /* Delete the existing directory with the given path. */ char cFileName[1000]; if (pathStringLength >= 1000) { return false; } if (equalsLastPath(pathString, pathStringLength)) lastPathValid = false; #if defined(__MWERKS__) { /* Delete the existing directory with the given path. */ FSSpec spec; OSErr err; if ((err = makeFSSpec(pathString, pathStringLength,&spec)) != noErr) return false; return FSpDelete(&spec) == noErr; } #else /* copy the file name into a null-terminated C string */ sqFilenameFromString(cFileName, (int) pathString, pathStringLength); return rmdir(cFileName) == 0; #endif } #else int dir_Create(char *pathString, int pathStringLength) { FSSpec spec; OSErr err; long createdDirID; if ((err = makeFSSpec(pathString, pathStringLength,&spec)) == -1) return false; return FSpDirCreate(&spec,smSystemScript,&createdDirID) == noErr; } int dir_Delete(char *pathString, int pathStringLength) { /* Delete the existing directory with the given path. */ FSSpec spec; OSErr err; if ((err = makeFSSpec(pathString, pathStringLength,&spec)) == -1) return false; return FSpDelete(&spec) == noErr; } #endif int dir_Delimitor(void) { return DELIMITOR; } #if TARGET_API_MAC_CARBON int dir_Lookup(char *pathString, int pathStringLength, int index, /* outputs: */ char *name, int *nameLength, int *creationDate, int *modificationDate, int *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries 2 if the given path has bad syntax or does not reach a directory */ int okay; FSSpec spec; long parentDirectory; OSErr err; Str255 longFileName; FSVolumeInfoParam fsVolumeParam; HFSUniStr255 uniStr; FSVolumeInfo volumeInfo; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) { /* get volume info */ fsVolumeParam.volumeName = &uniStr; fsVolumeParam.ioVRefNum = kFSInvalidVolumeRefNum; fsVolumeParam.volumeIndex = index; fsVolumeParam.whichInfo = 0; fsVolumeParam.volumeInfo = &volumeInfo; fsVolumeParam.ref = NULL; fsVolumeParam.whichInfo = kFSVolInfoCreateDate + kFSVolInfoModDate; okay = PBGetVolumeInfoSync( &fsVolumeParam) == noErr; /* FSGetVolumeInfo (kFSInvalidVolumeRefNum, index, NULL, ) */ if (okay) { CFStringRef strRef = CFStringCreateWithCharacters( kCFAllocatorDefault, uniStr.unicode, uniStr.length ); CFMutableStringRef mStr = CFStringCreateMutableCopy(NULL, 0, strRef); // HFS+ imposes Unicode2.1 decomposed UTF-8 encoding on all path elements if (gCurrentVMEncoding == kCFStringEncodingUTF8) CFStringNormalize(mStr, kCFStringNormalizationFormKC); // pre-combined Boolean result = CFStringGetCString(mStr, name, 256, gCurrentVMEncoding); // buffer size is to see primitiveDirectoryLookup CFRelease(strRef); CFRelease(mStr); if (result == true) { // strncpy(name, &(uniStr.unicode), uniStr.length); // *nameLength = uniStr.length; *nameLength = strlen(name); { LocalDateTime local; ConvertUTCToLocalDateTime(&fsVolumeParam.volumeInfo->createDate,&local); *creationDate = convertToSqueakTime(local.lowSeconds); } { LocalDateTime local; ConvertUTCToLocalDateTime(&fsVolumeParam.volumeInfo->modifyDate,&local); *modificationDate = convertToSqueakTime(local.lowSeconds); } *isDirectory = true; *sizeIfFile = 0; return ENTRY_FOUND; } else { return NO_MORE_ENTRIES; } } else { return NO_MORE_ENTRIES; } } else { /* get file or directory info */ if (!equalsLastPath(pathString, pathStringLength)) { /* lookup and cache the refNum for this path */ err = lookupPath(pathString, pathStringLength, &spec,false,true); if (err == noErr) recordPath(pathString, pathStringLength, &spec); else return BAD_PATH; } spec = lastSpec; *sizeIfFile = 0; okay = fetchFileInfo(index,&spec,(unsigned char *) name,true, &parentDirectory,isDirectory,creationDate, modificationDate,sizeIfFile,&longFileName); if (okay == noErr) { CFStringRef cfs= CFStringCreateWithPascalString(NULL, longFileName, gCurrentVMEncoding); CFMutableStringRef mStr= CFStringCreateMutableCopy(NULL, 0, cfs); CFRelease(cfs); // HFS+ imposes Unicode2.1 decomposed UTF-8 encoding on all path elements if (gCurrentVMEncoding == kCFStringEncodingUTF8) CFStringNormalize(mStr, kCFStringNormalizationFormKC); // pre-combined CFStringGetCString(mStr, name, 256, gCurrentVMEncoding); CFRelease(mStr); *nameLength = strlen(name); *creationDate = convertToSqueakTime(*creationDate); *modificationDate = convertToSqueakTime(*modificationDate); return ENTRY_FOUND; } else return okay == fnfErr ? NO_MORE_ENTRIES : BAD_PATH; } } #else int dir_Lookup(char *pathString, int pathStringLength, int index, /* outputs: */ char *name, int *nameLength, int *creationDate, int *modificationDate, int *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries 2 if the given path has bad syntax or does not reach a directory */ int okay; HVolumeParam volumeParams; FSSpec spec; long parentDirectory; OSErr err; Str255 longFileName; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) { /* get volume info */ volumeParams.ioNamePtr = (unsigned char *) name; volumeParams.ioVRefNum = 0; volumeParams.ioVolIndex = index; okay = PBHGetVInfoSync((HParmBlkPtr) &volumeParams) == noErr; if (okay) { CopyPascalStringToC((ConstStr255Param) name,name); *nameLength = strlen(name); *creationDate = convertToSqueakTime(volumeParams.ioVCrDate); *modificationDate = convertToSqueakTime(volumeParams.ioVLsMod); *isDirectory = true; *sizeIfFile = 0; return ENTRY_FOUND; } else { return NO_MORE_ENTRIES; } } else { /* get file or directory info */ if (!equalsLastPath(pathString, pathStringLength)) { /* lookup and cache the refNum for this path */ err = lookupPath(pathString, pathStringLength, &spec,false,true); if (err == noErr) recordPath(pathString, pathStringLength, &spec); else return BAD_PATH; } spec = lastSpec; *sizeIfFile = 0; okay = fetchFileInfo(index,&spec,(unsigned char *) name,true,&parentDirectory,isDirectory,creationDate,modificationDate,sizeIfFile,&longFileName); if (okay == noErr) { CopyPascalStringToC((ConstStr255Param) longFileName,name); *nameLength = strlen(name); *creationDate = convertToSqueakTime(*creationDate); *modificationDate = convertToSqueakTime(*modificationDate); return ENTRY_FOUND; } else return okay == fnfErr ? NO_MORE_ENTRIES : BAD_PATH; } } #endif OSErr getSpecAndFInfo(char *filename, int filenameSize,FSSpec *spec,FInfo *finderInfo) { OSErr err; if ((err = makeFSSpec(filename, filenameSize,spec)) != noErr) return err; if ((err= FSpGetFInfo(spec,finderInfo)) != noErr) return err; return noErr; } int dir_SetMacFileTypeAndCreator(char *filename, int filenameSize, char *fType, char *fCreator) { /* Set the Macintosh type and creator of the given file. */ /* Note: On other platforms, this is just a noop. */ FSSpec spec; FInfo finderInfo; if (getSpecAndFInfo(filename,filenameSize,&spec,&finderInfo) != noErr) return false; finderInfo.fdType = *((int *) fType); finderInfo.fdCreator = *((int *) fCreator); return FSpSetFInfo(&spec,&finderInfo) == noErr; } int dir_GetMacFileTypeAndCreator(char *filename, int filenameSize, char *fType, char *fCreator) { /* Get the Macintosh type and creator of the given file. */ /* Note: On other platforms, this is just a noop. */ FSSpec spec; FInfo finderInfo; if (getSpecAndFInfo(filename,filenameSize,&spec,&finderInfo) != noErr) return false; *((int *) fType) = finderInfo.fdType; *((int *) fCreator) = finderInfo.fdCreator; return true; } int equalsLastPath(char *pathString, int pathStringLength) { /* Return true if the lastPath cache is valid and the given Squeak string equals it. */ int i, ch; if (!lastPathValid || (pathStringLength > MAX_PATH)) { return false; } for (i = 0; i < pathStringLength; i++) { ch = lastPath[i]; if ((ch == 0) || (ch != pathString[i])) return false; } return lastPath[i] == 0; } int recordPath(char *pathString, int pathStringLength, FSSpec *spec) { /* Copy the given Squeak string into the lastPath cache. */ if (pathStringLength > MAX_PATH) { lastPath[0] = 0; /* set to empty string */ lastPathValid = false; lastSpec = *spec; return 0; } strncpy(lastPath,pathString,pathStringLength); lastPath[pathStringLength] = 0; /* string terminator */ lastPathValid = true; lastSpec = *spec; return 0; } #if defined(__MWERKS__) int ftruncate(short int file,int offset) { ParamBlockRec pb; OSErr error; //JMM Foo FSSetForkSize FSSetForkPosition FSGetForkPosition pb.ioParam.ioRefNum = file; pb.ioParam.ioMisc = (char *) offset; error = PBSetEOFSync(&pb); return error; } #endif #if defined(__MWERKS__) #include #include int fflush(FILE * file) { fpos_t position; /* mm 970708 */ ParamBlockRec pb; OSErr error; if (!file) return(__flush_all()); if (file->state.error || file->mode.file_kind == __closed_file) return(EOF); if (file->mode.io_mode == __read) /* mm 980430 */ return 0; /* mm 980430 */ if (file->state.io_state >= __rereading) file->state.io_state = __reading; if (file->state.io_state == __reading) file->buffer_len = 0; if (file->state.io_state != __writing) { file->state.io_state = __neutral; /* mm 970905 */ return(0); } #ifndef _No_Disk_File_OS_Support if (file->mode.file_kind != __disk_file || (position = ftello(file)) < 0) position = 0; #else position = 0; #endif if (__flush_buffer(file, NULL)) { set_error(file); return(EOF); } file->state.io_state = __neutral; file->position = position; file->buffer_len = 0; pb.ioParam.ioRefNum = file->handle; error = PBFlushFileSync(&pb); error = GetVRefNum(pb.ioParam.ioRefNum,&pb.volumeParam.ioVRefNum); pb.volumeParam.ioNamePtr = nil; error = PBFlushVolSync(&pb); return(0); } extern __system7present(); extern long __getcreator(long isbinary); extern long __gettype(long isbinary); static void set_file_type(FSSpec * spec, int binary_file) { CInfoPBRec pb; OSErr ioResult; pb.hFileInfo.ioNamePtr = spec->name; pb.hFileInfo.ioVRefNum = spec->vRefNum; pb.hFileInfo.ioFDirIndex = 0; pb.hFileInfo.ioDirID = spec->parID; if (!(ioResult = PBGetCatInfoSync(&pb))) { pb.hFileInfo.ioFlFndrInfo.fdType = __gettype(binary_file); /*mm-960729*/ pb.hFileInfo.ioFlFndrInfo.fdCreator = __getcreator(binary_file); /*mm-960729*/ pb.hFileInfo.ioDirID = spec->parID; ioResult = PBSetCatInfoSync(&pb); } } int __open_file (const char * name, __std(__file_modes) mode, __std(__file_handle) * handle); OSErr __path2fss(const char * pathName, FSSpecPtr spec); extern OSErr gSqueakFileLastError; int __open_file(const char * name, __file_modes mode, __file_handle * handle) { FSSpec spec; OSErr ioResult; HParamBlockRec pb; ioResult = __path2fss(name, &spec); if (ioResult) gSqueakFileLastError = ioResult; if (__system7present()) /* mm 980424 */ { /* mm 980424 */ Boolean targetIsFolder, wasAliased; /* mm 980424 */ ResolveAliasFile(&spec, true, &targetIsFolder, &wasAliased); /* mm 980424 */ } /* mm 980424 */ if (ioResult && (ioResult != fnfErr || mode.open_mode == __must_exist)) return(__io_error); #if TARGET_API_MAC_CARBON if (ioResult) { CFStringRef filePath; CFURLRef sillyThing, sillyThing2; FSRef parentFSRef; short int fileRefNum; OSErr err; UniChar buffer[1024]; long tokenLength; filePath = CFStringCreateWithBytes(kCFAllocatorDefault,(UInt8 *)name,strlen(name),gCurrentVMEncoding,false); if (filePath == nil) return __io_error; sillyThing = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,filePath,kCFURLHFSPathStyle,false); CFRelease(filePath); sillyThing2 = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault,sillyThing); err = CFURLGetFSRef(sillyThing2,&parentFSRef); if (err == 0) { CFRelease(sillyThing); CFRelease(sillyThing2); return fnfErr; } filePath = CFURLCopyLastPathComponent(sillyThing); tokenLength = CFStringGetLength(filePath); if (tokenLength > 1024) { CFRelease(filePath); CFRelease(sillyThing); CFRelease(sillyThing2); return(__io_error); } CFStringGetCharacters(filePath,CFRangeMake(0,tokenLength),buffer); CFRelease(filePath); CFRelease(sillyThing); CFRelease(sillyThing2); ioResult = FSCreateFileUnicode(&parentFSRef,tokenLength,buffer,kFSCatInfoNone,NULL,NULL,&spec); if (ioResult) gSqueakFileLastError = ioResult; if (ioResult) return(__io_error); pb.ioParam.ioNamePtr = spec.name; pb.ioParam.ioVRefNum = spec.vRefNum; pb.ioParam.ioPermssn = (mode.io_mode == __read) ? fsRdPerm : fsRdWrPerm; pb.ioParam.ioMisc = 0; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioDirID = spec.parID; set_file_type(&spec, mode.binary_io); ioResult = PBHOpenDFSync(&pb); /* HH 10/25/97 was PBHOpenSync */ if (ioResult) return(__io_error); *handle = pb.ioParam.ioRefNum; return(__no_io_error); } #endif pb.ioParam.ioNamePtr = spec.name; pb.ioParam.ioVRefNum = spec.vRefNum; pb.ioParam.ioPermssn = (mode.io_mode == __read) ? fsRdPerm : fsRdWrPerm; pb.ioParam.ioMisc = 0; pb.fileParam.ioFVersNum = 0; pb.fileParam.ioDirID = spec.parID; if (ioResult) { if (!(ioResult = PBHCreateSync(&pb))) { if (ioResult) gSqueakFileLastError = ioResult; set_file_type(&spec, mode.binary_io); ioResult = PBHOpenDFSync(&pb); /* HH 10/25/97 was PBHOpenSync */ if (ioResult) gSqueakFileLastError = ioResult; } } else { if (!(ioResult = PBHOpenDFSync(&pb)) && mode.open_mode == __create_or_truncate) /* HH 10/25/97 was PBHOpenSync */ { pb.ioParam.ioMisc = 0; ioResult = PBSetEOFSync((ParmBlkPtr) &pb); if (ioResult) gSqueakFileLastError = ioResult; if (ioResult) PBCloseSync((ParmBlkPtr) &pb); } else { if (ioResult) gSqueakFileLastError = ioResult; } } if (ioResult) return(__io_error); *handle = pb.ioParam.ioRefNum; return(__no_io_error); } #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FilePlugin/sqMacUnixFileInterface.c ================================================ /* * sqMacUnixFileInterface.c * SqueakVMUNIXPATHS * * Created by John M McIntosh on 31/01/06. * Copyright 2006 Corporate Smalltalk Consulting Ltd. All rights reserved, licensed under the Squeak-L license. * */ #include #include "sqMacUnixFileInterface.h" #include "sqMacUIConstants.h" #include "sqUnixCharConv.h" extern CFStringEncoding gCurrentVMEncoding; /* sqUnixFile.c -- directory operations for Unix * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.Fr * 3.8.15b3 Feb 19th, 2007 JMM fix bug with crash on bogus file path. 3.8.17b4 Apr 27th, 2007 JMM note from Tetsuya HAYASHI, tetha@st.rim.or.jp, tetha@mac.com I've found the latest mac vm (or recent version) fails to normalize UTF file name. It seems to be the function convertChars() of sqMacUnixFileInterface.c, which normalizes only decompose when converting squeak string to unix, but I think it needs pre-combined when unix string to squeak, and I noticed normalization form should be canonical (exactly should be kCFStringNormalizationFormC) for pre-combined. */ #include "sq.h" #include "FilePlugin.h" #include "sqUnixCharConv.h" #include "sqMacEncoding.h" #include "sqMacTime.h" #include "sqMacImageIO.h" #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif #ifdef HAVE_UNISTD_H # include # include #endif #include #include #include #include #include /*** The interface to the directory primitive is path based. That is, the client supplies a Squeak string describing the path to the directory on every call. To avoid traversing this path on every call, a cache is maintained of the last path seen, along with the Mac volume and folder reference numbers corresponding to that path. ***/ /*** Constants ***/ #define ENTRY_FOUND 0 #define NO_MORE_ENTRIES 1 #define BAD_PATH 2 /*** Variables ***/ static char lastPath[DOCUMENT_NAME_SIZE+1]; static int lastPathValid = false; static int lastIndex= -1; static DIR *openDir= 0; /*** Functions ***/ int convertChars(char *from, int fromLen, void *fromCode, char *to, int toLen, void *toCode, int norm, int term); sqInt ioFilenamefromStringofLengthresolveAliasesRetry(char* dst, char* src, sqInt num, sqInt resolveAlias, Boolean retry); static CFURLRef makeFileSystemURLFromString(char *pathString,int length,CFStringEncoding encoding); static OSErr getFInfo(char *filename,FSCatalogInfo *catInfo,CFStringEncoding encoding); OSStatus SetVMPathFromApplicationDirectory(); sqInt dir_Create(char *pathString, sqInt pathStringLength) { /* Create a new directory with the given path. By default, this directory is created relative to the cwd. */ char name[DOCUMENT_NAME_SIZE+1]; if (pathStringLength >= DOCUMENT_NAME_SIZE) return false; if (!ioFilenamefromStringofLengthresolveAliasesRetry(name,pathString, pathStringLength, false, true)) return false; return mkdir(name, 0777) == 0; /* rwxrwxrwx & ~umask */ } sqInt dir_Delete(char *pathString, sqInt pathStringLength) { /* Delete the existing directory with the given path. */ char name[DOCUMENT_NAME_SIZE+1]; if (pathStringLength >= DOCUMENT_NAME_SIZE) return false; if (!ioFilenamefromStringofLengthresolveAliasesRetry(name,pathString, pathStringLength, false, true)) return false; if (strcmp(lastPath, name) == 0) lastPath[0] = 0x00; return rmdir(name) == 0; } sqInt dir_Delimitor(void) { return DELIMITERInt; } static int maybeOpenDir(char *unixPath) { /* if the last opendir was to the same directory, re-use the directory pointer from last time. Otherwise close the previous directory, open the new one, and save its name. Return true if the operation was successful, false if not. */ if (!lastPathValid || strcmp(lastPath, unixPath)) { /* invalidate the old, open the new */ if (lastPathValid) closedir(openDir); lastPathValid= false; strcpy(lastPath, unixPath); if ((openDir= opendir(unixPath)) == 0) return false; lastPathValid= true; lastIndex= 0; /* first entry is index 1 */ } return true; } sqInt dir_Lookup(char *pathString, sqInt pathStringLength, sqInt index, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries 2 if the given path has bad syntax or does not reach a directory */ int i; int nameLen= 0; struct dirent *dirEntry= 0; char unixPath[DOCUMENT_NAME_SIZE+1]; struct stat statBuf; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) strcpy(unixPath, "."); else { if (!ioFilenamefromStringofLengthresolveAliasesRetry(unixPath, pathString,pathStringLength, true, true)) return BAD_PATH; } /* get file or directory info */ if (!maybeOpenDir(unixPath)) return BAD_PATH; if (++lastIndex == index) index= 1; /* fake that the dir is rewound and we want the first entry */ else { rewinddir(openDir); /* really rewind it, and read to the index */ lastIndex= index; } for (i= 0; i < index; i++) { nextEntry: do { errno= 0; dirEntry= readdir(openDir); } while ((dirEntry == 0) && (errno == EINTR)); if (!dirEntry) return NO_MORE_ENTRIES; nameLen= NAMLEN(dirEntry); /* ignore '.' and '..' (these are not *guaranteed* to be first) */ if (nameLen < 3 && dirEntry->d_name[0] == '.') if (nameLen == 1 || dirEntry->d_name[1] == '.') goto nextEntry; } *nameLength= ux2sqPath(dirEntry->d_name, nameLen, name, 256, 0); { char terminatedName[DOCUMENT_NAME_SIZE+1]; strncpy(terminatedName, dirEntry->d_name, nameLen); terminatedName[nameLen]= '\0'; strcat(unixPath, "/"); strcat(unixPath, terminatedName); if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) { /* We can't stat the entry, but failing here would invalidate the whole directory --bertf */ return ENTRY_FOUND; } } /* last change time */ *creationDate= convertToSqueakTime(statBuf.st_ctime); /* modification time */ *modificationDate= convertToSqueakTime(statBuf.st_mtime); { FSRef targetFSRef; Boolean targetIsFolder,wasAliased; OSErr err; err = getFSRef(unixPath,&targetFSRef,kCFStringEncodingUTF8); if (!err) { FSResolveAliasFileWithMountFlags(&targetFSRef,true,&targetIsFolder,&wasAliased,kResolveAliasFileNoUI); if (wasAliased && targetIsFolder) { *isDirectory= true; return ENTRY_FOUND; } } } if (S_ISDIR(statBuf.st_mode)) *isDirectory= true; else *sizeIfFile= statBuf.st_size; return ENTRY_FOUND; } sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char* nameString, sqInt nameStringLength, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the given name in the given directory, Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if there is no such entry in the directory 2 if the given path has bad syntax or does not reach a directory */ char unixPath[DOCUMENT_NAME_SIZE+1]; struct stat statBuf; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) strcpy(unixPath, "."); else { if (!ioFilenamefromStringofLengthresolveAliasesRetry(unixPath, pathString,pathStringLength, true, true)) return BAD_PATH; } char terminatedName[DOCUMENT_NAME_SIZE+1]; strncpy(terminatedName, nameString, nameStringLength); terminatedName[nameStringLength]= '\0'; strcat(unixPath, "/"); strcat(unixPath, terminatedName); if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) { return NO_MORE_ENTRIES; } /* To match the results of dir_Lookup, copy back the file name */ *nameLength = ux2sqPath(nameString, nameStringLength, name, 256, 0); /* last change time */ *creationDate= convertToSqueakTime(statBuf.st_ctime); /* modification time */ *modificationDate= convertToSqueakTime(statBuf.st_mtime); { FSRef targetFSRef; Boolean targetIsFolder,wasAliased; OSErr err; err = getFSRef(unixPath,&targetFSRef,kCFStringEncodingUTF8); if (!err) { FSResolveAliasFileWithMountFlags(&targetFSRef,true,&targetIsFolder,&wasAliased,kResolveAliasFileNoUI); if (wasAliased && targetIsFolder) { *isDirectory= true; return ENTRY_FOUND; } } } if (S_ISDIR(statBuf.st_mode)) *isDirectory= true; else *sizeIfFile= statBuf.st_size; return ENTRY_FOUND; } int wanderDownPath(char *src,int bytes,char *possiblePath, Boolean resolveLastAlias); sqInt sqGetFilenameFromString(char * aCharBuffer, char * aFilenameString, sqInt filenameLength, sqInt aBoolean){ ioFilenamefromStringofLengthresolveAliasesRetry(aCharBuffer,(char *) aFilenameString, filenameLength, aBoolean, true); return 0; } void sqFilenameFromStringOpen(char *buffer,sqInt fileIndex, long fileLength) { ioFilenamefromStringofLengthresolveAliasesRetry(buffer,(char *) fileIndex, fileLength, true, true); } void sqFilenameFromString(char *buffer,sqInt fileIndex, long fileLength) { ioFilenamefromStringofLengthresolveAliasesRetry(buffer,(char *) fileIndex, fileLength, false, true); } sqInt ioFilenamefromStringofLengthresolveAliasesRetry(char* dst, char* src, sqInt num, sqInt resolveAlias, Boolean retry) { int bytes; FSRef targetFSRef; OSStatus err; if (retry) bytes = sq2uxPath(src, num, dst, DOCUMENT_NAME_SIZE, 1); else { memcpy(dst,src,num); dst[num] = 0x00; bytes = num; } err = getFSRef(dst,&targetFSRef,kCFStringEncodingUTF8); if (retry) { if (err) { char possiblePath[DOCUMENT_NAME_SIZE+1]; bytes = wanderDownPath(dst,bytes,possiblePath,resolveAlias); if (bytes) strcpy(dst,possiblePath); return bytes; } } if (err == 0 && resolveAlias) { Boolean targetIsFolder,wasAliased; err = FSResolveAliasFileWithMountFlags(&targetFSRef,true,&targetIsFolder,&wasAliased,kResolveAliasFileNoUI); if (err || wasAliased == false) return bytes; PathToFileViaFSRef(dst, DOCUMENT_NAME_SIZE, &targetFSRef,kCFStringEncodingUTF8); bytes = strlen(dst); } return bytes; } static CFURLRef makeFileSystemURLFromString(char *pathString,int length, CFStringEncoding encoding) { CFStringRef tmpStrRef; CFMutableStringRef filePath; CFURLRef sillyThing; tmpStrRef = CFStringCreateWithBytes(kCFAllocatorDefault,(UInt8 *) pathString, length, encoding, true); if (tmpStrRef == nil) return null; filePath = CFStringCreateMutableCopy(NULL, 0, tmpStrRef); CFRelease(tmpStrRef); if (encoding == kCFStringEncodingUTF8) CFStringNormalize(filePath, kCFStringNormalizationFormD); sillyThing = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,filePath,kCFURLPOSIXPathStyle,false); CFRelease(filePath); return sillyThing; } OSErr getFSRef(char *pathString,FSRef *theFSRef,CFStringEncoding encoding) { CFURLRef sillyThing; sillyThing = makeFileSystemURLFromString(pathString,strlen(pathString),encoding); if (sillyThing == NULL) { return -2000; } if (CFURLGetFSRef(sillyThing,theFSRef) == false) { CFRelease(sillyThing); return -3000; } CFRelease(sillyThing); return 0; } /* Returns in gCurrentVMEncoding */ int getLastPathComponentInCurrentEncoding(char *pathString,char * lastPathPart,CFStringEncoding encoding) { CFURLRef sillyThing; CFStringRef tmpStrRef; sillyThing = makeFileSystemURLFromString(pathString,strlen(pathString),encoding); if (sillyThing == NULL) return -2000; tmpStrRef = CFURLCopyLastPathComponent(sillyThing); CFRelease(sillyThing); CFMutableStringRef mutableStr= CFStringCreateMutableCopy(NULL, 0, tmpStrRef); CFRelease(tmpStrRef); // HFS+ imposes Unicode2.1 decomposed UTF-8 encoding on all path elements if (gCurrentVMEncoding == kCFStringEncodingUTF8) CFStringNormalize(mutableStr, kCFStringNormalizationFormC); // pre-combined CFStringGetCString (mutableStr, lastPathPart,256, gCurrentVMEncoding); CFRelease(mutableStr); return 0; } void PathToFileViaFSRef(char *pathName, int pathNameMax, FSRef *theFSRef,CFStringEncoding encoding) { CFURLRef sillyThing; CFStringRef filePath; Boolean isDirectory; pathName[0]= 0x00; sillyThing = CFURLCreateFromFSRef (kCFAllocatorDefault, theFSRef); if (sillyThing == NULL) return; isDirectory = CFURLHasDirectoryPath(sillyThing); filePath = CFURLCopyFileSystemPath (sillyThing, kCFURLPOSIXPathStyle); CFRelease(sillyThing); CFMutableStringRef mutableStr= CFStringCreateMutableCopy(NULL, 0, filePath); CFRelease(filePath); // HFS+ imposes Unicode2.1 decomposed UTF-8 encoding on all path elements if (encoding == kCFStringEncodingUTF8) CFStringNormalize(mutableStr, kCFStringNormalizationFormC); // pre-combined CFStringGetCString (mutableStr, pathName,pathNameMax, encoding); CFRelease(mutableStr); if (isDirectory) strcat(pathName,"/"); } static OSErr getFInfo(char *filename,FSCatalogInfo *catInfo,CFStringEncoding encoding) { FSRef theFSRef; OSErr err; err = getFSRef(filename,&theFSRef,encoding); if (err != 0) return err; err = FSGetCatalogInfo (&theFSRef,kFSCatInfoFinderInfo,catInfo,nil,nil,nil); return noErr; } OSErr getFInfoViaFSRef(FSRef *theFSRef, FInfo *finderInfo) { OSErr err; FSCatalogInfo catInfo; err = FSGetCatalogInfo (theFSRef,kFSCatInfoFinderInfo,&catInfo,nil,nil,nil); memcpy(finderInfo,&catInfo.finderInfo,sizeof(FInfo)); return err; } int dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { /* Set the Macintosh type and creator of the given file. */ /* Note: On other platforms, this is just a noop. */ FSCatalogInfo catInfo; FInfo finderInfo; OSErr err; FSRef theFSRef; char fileNameBuffer[DOCUMENT_NAME_SIZE+1]; int bytes; bytes = ioFilenamefromStringofLengthresolveAliasesRetry(fileNameBuffer,filename, filenameSize, true, true); if (bytes == 0) return false; if (getFInfo(fileNameBuffer,&catInfo,kCFStringEncodingUTF8) != noErr) return false; memcpy(&finderInfo,&catInfo.finderInfo,16); finderInfo.fdType = CFSwapInt32HostToBig(*((int *) fType)); finderInfo.fdCreator = CFSwapInt32HostToBig(*((int *) fCreator)); memcpy(&catInfo.finderInfo,&finderInfo,16); err = getFSRef(fileNameBuffer,&theFSRef,kCFStringEncodingUTF8); if (err != 0) return err; err = FSSetCatalogInfo (&theFSRef,kFSCatInfoFinderInfo,&catInfo); return true; } int dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { /* Get the Macintosh type and creator of the given file. */ /* Note: On other platforms, this is just a noop. */ FSCatalogInfo catInfo; FInfo finderInfo; char fileNameBuffer[DOCUMENT_NAME_SIZE+1]; int bytes; bytes = ioFilenamefromStringofLengthresolveAliasesRetry(fileNameBuffer,filename, filenameSize, true, true); if (bytes == 0) return false; if (getFInfo(fileNameBuffer,&catInfo,kCFStringEncodingUTF8) != noErr) return false; memcpy(&finderInfo,&catInfo.finderInfo,16); *((int *) fType) = CFSwapInt32BigToHost(finderInfo.fdType); *((int *) fCreator) = CFSwapInt32BigToHost(finderInfo.fdCreator); return true; } OSStatus SetVMPathFromApplicationDirectory() { CFBundleRef mainBundle; CFURLRef bundleURL,bundleURLPrefix; CFStringRef filePath; CFMutableStringRef vmPathString; mainBundle = CFBundleGetMainBundle(); bundleURL = CFBundleCopyBundleURL(mainBundle); bundleURLPrefix = CFURLCreateCopyDeletingLastPathComponent(NULL,bundleURL); CFRelease(bundleURL); filePath = CFURLCopyFileSystemPath (bundleURLPrefix, kCFURLPOSIXPathStyle); CFRelease(bundleURLPrefix); vmPathString = CFStringCreateMutableCopy(NULL, 0, filePath); CFStringAppendCString(vmPathString, "/", kCFStringEncodingMacRoman); SetVMPathFromCFString(vmPathString); CFRelease(filePath); CFRelease(vmPathString); return 0; } pascal Boolean findImageFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode); OSErr squeakFindImage(char* pathName) { NavDialogCreationOptions dialogOptions; NavObjectFilterUPP filterProc = NewNavObjectFilterUPP(findImageFilterProc); OSErr anErr = noErr; NavDialogRef navDialog; FSRef fileAsFSRef; // Specify default options for dialog box anErr = NavGetDefaultDialogCreationOptions(&dialogOptions); if (anErr != noErr) return anErr; // Adjust the options to fit our needs // Set default location option dialogOptions.optionFlags |= kNavSelectDefaultLocation; dialogOptions.optionFlags |= kNavAllFilesInPopup; dialogOptions.optionFlags |= kNavSelectAllReadableItem; // Clear preview option dialogOptions.optionFlags ^= kNavAllowPreviews; // Call NavGetFile() with specified options and // declare our app-defined functions and type list NavCreateChooseFileDialog ( &dialogOptions, nil, nil, nil, filterProc, nil, &navDialog); anErr = NavDialogRun (navDialog); if (anErr != noErr ) return anErr; NavReplyRecord outReply; anErr = NavDialogGetReply (navDialog,&outReply); DisposeNavObjectFilterUPP(filterProc); NavDialogDispose(navDialog); if (anErr != noErr) return anErr; if (!outReply.validRecord) { anErr = NavDisposeReply(&outReply); return -1; } // Get the file anErr = AEGetNthPtr(&(outReply.selection), 1, typeFSRef, NULL, NULL, &fileAsFSRef, sizeof(FSRef), NULL); PathToFileViaFSRef(pathName,DOCUMENT_NAME_SIZE, &fileAsFSRef, gCurrentVMEncoding); // Dispose of NavReplyRecord, resources, descriptors anErr = NavDisposeReply(&outReply); return 0; } pascal Boolean findImageFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode) { #pragma unused(filterMode,callBackUD) NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; if (theItem->descriptorType == typeFSRef) { char checkSuffix[256],pathName[1024]; OSErr error; Boolean check; FSRef theFSRef; if (theInfo->isFolder) return true; if (theInfo->fileAndFolder.fileInfo.finderInfo.fdType == 'STim') return true; error = AEGetDescData(theItem,&theFSRef,sizeof(FSRef)); if (error != noErr) return true; PathToFileViaFSRef(pathName, 1024, &theFSRef,kCFStringEncodingUTF8); getLastPathComponentInCurrentEncoding(pathName,checkSuffix,kCFStringEncodingUTF8); check = IsImageName(checkSuffix); if (check) return true; else { return false; } } return true; } int wanderDownPath(char *src,int bytes,char *parts,Boolean resolveLastAlias) { char tokens[DOCUMENT_NAME_SIZE+1],results[DOCUMENT_NAME_SIZE+1]; Boolean firstTime = true; char *token,*nexttoken; int tokenLength,numberOfBytes; parts[0] = 0x00; memcpy(tokens,src,bytes); tokens[bytes] = 0x00; token = strtok((char*) tokens,"/"); if (token == 0) return 0; while (token) { tokenLength = strlen(token); if (firstTime) { firstTime = false; strcat(parts,"/"); strcat(parts,token); numberOfBytes = ioFilenamefromStringofLengthresolveAliasesRetry(results, parts, strlen(parts), true, false); strcat(parts,"/"); if (numberOfBytes) { strcpy(parts,results); } else { strcpy(parts,token); } token = strtok(nil,"/"); } else { if (parts[strlen(parts)-1] != '/') strcat(parts,"/"); strcat(parts,token); nexttoken = strtok(nil,"/"); if (nexttoken == nil) numberOfBytes = ioFilenamefromStringofLengthresolveAliasesRetry(results, parts, strlen(parts), resolveLastAlias, false); else numberOfBytes = ioFilenamefromStringofLengthresolveAliasesRetry(results, parts, strlen(parts), true, false); if (numberOfBytes) strcpy(parts,results); else strcpy(parts,token); token = nexttoken; } } return strlen(parts); } int sq2uxPath(char *from, int fromLen, char *to, int toLen, int term) { CFStringEncoding unixEncoding = kCFStringEncodingUTF8; int n= convertChars(from, fromLen, (char *) gCurrentVMEncoding, to, toLen,(char *) unixEncoding, true, term); return n; } int ux2sqPath(char *from, int fromLen, char *to, int toLen, int term) { CFStringEncoding unixEncoding = kCFStringEncodingUTF8; int n= convertChars(from, fromLen,(char *) unixEncoding, to, toLen, (char *) gCurrentVMEncoding, false, term); return n; } #define min(X, Y) ( ((X)>(Y)) ? (Y) : (X) ) static int convertCopy(char *from, int fromLen, char *to, int toLen, int term) { int len= min(toLen - term, fromLen); strncpy(to, from, len); if (term) to[len]= '\0'; return len; } int convertChars(char *from, int fromLen, void *fromCode, char *to, int toLen, void *toCode, int norm, int term) { CFStringRef cfs= CFStringCreateWithBytes(NULL, (UInt8 *) from, fromLen, (CFStringEncoding)fromCode, 0); if (cfs == NULL) { toLen = 0; to[toLen]= '\0'; return toLen; } CFMutableStringRef str= CFStringCreateMutableCopy(NULL, 0, cfs); CFRelease(cfs); if (norm) // HFS+ imposes Unicode2.1 decomposed UTF-8 encoding on all path elements CFStringNormalize(str, kCFStringNormalizationFormD); // canonical decomposition else CFStringNormalize(str, kCFStringNormalizationFormC); // pre-combined { CFRange rng= CFRangeMake(0, CFStringGetLength(str)); CFIndex len= 0; CFIndex num= CFStringGetBytes(str, rng, (CFStringEncoding)toCode, '?', 0, (UInt8 *)to, toLen - term, &len); CFRelease(str); if (!num) return convertCopy(from, fromLen, to, toLen, term); if (term) to[len]= '\0'; return len; } } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FilePlugin/sqMacUnixFileInterface.h ================================================ /* * sqMacUnixFileInterface.h * SqueakVMUNIXPATHS * * Created by John M McIntosh on 31/01/06. * Copyright 2006 Corporate Smalltalk Consulting Ltd. All rights reserved, released under the Squeak-L license. * */ #include "sqMacUIConstants.h" OSStatus SetVMPathFromApplicationDirectory(void); int getLastPathComponentInCurrentEncoding(char *pathString,char * lastPathPart,CFStringEncoding encoding); extern UInt32 gCurrentVMEncoding; OSErr squeakFindImage(char *pathName); OSErr getFSRef(char *pathString,FSRef *theFSRef,CFStringEncoding encoding); void PathToFileViaFSRef(char *pathName, int pathNameMax, FSRef *theFSRef,CFStringEncoding encoding); OSErr getFInfoViaFSRef(FSRef *theFSRef, FInfo *finderInfo); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/FloatMathPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable FloatMathPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.FloatMathPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.1b4 CFBundleSignature FAST CFBundleVersion 1.0.1b4 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/HostWindowPlugin/sqMacHostWindow.c ================================================ /* * sqMacHostWindow.c * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * July 15th 2005 add logic to flush QD buffers for os-x 10.4 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic 4.1.0b2 set window title via cfstring */ #include "sqVirtualMachine.h" #include "sqMacHostWindow.h" #include "sqMacWindow.h" extern struct VirtualMachine *interpreterProxy; int RemoveWindowBlock(windowDescriptorBlock * thisWindow); int createWindowWidthheightoriginXyattrlength(int w,int h,int x,int y, char * list, int listLength) { int index; long windowClass,windowAttributes; WindowPtr window; windowDescriptorBlock *windowBlock; if (listLength != 8) return -1; memmove(&windowClass, list, 4); memmove(&windowAttributes, list+4, 4); window = SetUpWindow(y,x,y+h,x+w,windowClass,windowAttributes); if (window == 0) return -1; windowBlock = AddWindowBlock(); windowBlock->handle = (wHandleType) window; index = windowBlock->windowIndex; windowBlock->isInvisible = !MacIsWindowVisible(window); SetUpCarbonEventForWindowIndex(index); QDBeginCGContext(GetWindowPort(windowBlock->handle),&windowBlock->context); // CreateCGContextForPort(GetWindowPort(windowBlock->handle),&windowBlock->context); windowBlock->width = w; windowBlock->height = h; sqShowWindow(index); return index; } void setWindowTrackingRgn(int windowIndex) { Rect rgnRect; RgnHandle rgn = NewRgn(); MouseTrackingRegionID id; windowDescriptorBlock *windowBlock = windowBlockFromIndex(windowIndex); if (!windowBlock) return; if (windowBlock->windowTrackingRef) { GetWindowBounds(windowBlock->handle, kWindowContentRgn, &rgnRect); SetRectRgn( rgn, rgnRect.left, rgnRect.top, rgnRect.right, rgnRect.bottom ); ChangeMouseTrackingRegion(windowBlock->windowTrackingRef,rgn, NULL); DisposeRgn( rgn ); return; } GetWindowBounds(windowBlock->handle, kWindowContentRgn, &rgnRect); SetRectRgn( rgn, rgnRect.left, rgnRect.top, rgnRect.right, rgnRect.bottom ); id.signature = 'FAST'; id.id = windowIndex; OSStatus err = CreateMouseTrackingRegion(windowBlock->handle, rgn, NULL, kMouseTrackingOptionsGlobalClip, id, NULL, NULL, &windowBlock->windowTrackingRef); if ( noErr == err ) { RetainMouseTrackingRegion( windowBlock->windowTrackingRef); err = SetMouseTrackingRegionEnabled( windowBlock->windowTrackingRef, TRUE ); } DisposeRgn( rgn ); } int closeWindow(int windowIndex) { wHandleType windowHandle; windowHandle = windowHandleFromIndex(windowIndex); if(windowHandle == NULL) return 0; if (windowBlockFromIndex(windowIndex)->context) QDEndCGContext(GetWindowPort(windowBlockFromIndex(windowIndex)->handle),&windowBlockFromIndex(windowIndex)->context); //CGContextRelease(windowBlockFromIndex(windowIndex)->context); if (windowBlockFromIndex(windowIndex)->windowTrackingRef) { ReleaseMouseTrackingRegion(windowBlockFromIndex(windowIndex)->windowTrackingRef ); windowBlockFromIndex(windowIndex)->windowTrackingRef = NULL; } windowBlockFromIndex(windowIndex)->context = NULL; RemoveWindowBlock(windowBlockFromIndex(windowIndex)); DisposeWindow(windowHandle); return 1; } int ioPositionOfWindow(wIndexType windowIndex) { Rect portRect; if (windowHandleFromIndex(windowIndex) == nil) return -1; GetPortBounds(GetWindowPort(windowHandleFromIndex(windowIndex)),&portRect); QDLocalToGlobalRect(GetWindowPort(windowHandleFromIndex(windowIndex)), &portRect); return (portRect.left << 16) | (portRect.top & 0xFFFF); /* left is high 16 bits; top is low 16 bits */ } int ioPositionOfWindowSetxy(wIndexType windowIndex, int x, int y) { void *giLocker; int return_value=0; if (windowHandleFromIndex(windowIndex) == nil) return -1; giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { sqInt *foo; foo = malloc(sizeof(sqInt)*7); foo[0] = 4; foo[1] = (sqInt) MoveWindow; foo[2] = (sqInt) windowHandleFromIndex(windowIndex); foo[3] = x; foo[4] = y; foo[5] = true; foo[6] = 0; ((sqInt (*) (void *)) giLocker)(foo); return_value = interpreterProxy->positive32BitIntegerFor(foo[6]); free(foo); } return ioPositionOfWindow(windowIndex); } int ioSizeOfWindow(wIndexType windowIndex) { Rect portRect; int w, h; if (windowHandleFromIndex(windowIndex) == nil) return -1; GetPortBounds(GetWindowPort(windowHandleFromIndex(windowIndex)),&portRect); w = portRect.right - portRect.left; h = portRect.bottom - portRect.top; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } int ioSizeOfWindowSetxy(wIndexType windowIndex, int x, int y) { void * giLocker; int return_value=0; if (windowHandleFromIndex(windowIndex) == nil) return -1; giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { sqInt *foo; foo = malloc(sizeof(sqInt)*7); foo[0] = 4; foo[1] = (sqInt) SizeWindow; foo[2] = (sqInt) windowHandleFromIndex(windowIndex); foo[3] = x; foo[4] = y; foo[5] = true; foo[6] = 0; ((sqInt (*) (void *)) giLocker)(foo); return_value = interpreterProxy->positive32BitIntegerFor(foo[6]); free(foo); } setWindowTrackingRgn(windowIndex); return ioSizeOfWindow(windowIndex); } int ioSetTitleOfWindow(int windowIndex, char * newTitle, int sizeOfTitle) { char string[256]; if (sizeOfTitle > 255) return -1; memcpy(string,newTitle,sizeOfTitle); string[sizeOfTitle] = 0x00; CFStringRef windowTitleCFString = CFStringCreateWithCString (nil,string,kCFStringEncodingUTF8); SetWindowTitleWithCFString (windowHandleFromIndex(windowIndex),windowTitleCFString); CFRelease(windowTitleCFString); return 1; } int ioCloseAllWindows(void) { return 1; } /* addendum to sqPlatformSpecific.h */ /* multiple host windows stuff */ static windowDescriptorBlock *windowListRoot = NULL; /* end addendum to sqPlatformSpecific.h */ /* simple linked list management code */ /* window list management */ windowDescriptorBlock *windowBlockFromIndex(int windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry; entry = entry->next; } return NULL; } windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry; entry = entry->next; } return NULL; } wHandleType windowHandleFromIndex(int windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry->handle; entry = entry->next; } return NULL; } int windowIndexFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry->windowIndex; entry = entry->next; } return 0; } int windowIndexFromBlock( windowDescriptorBlock * thisWindow) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry == thisWindow) return entry->windowIndex; entry = entry->next; } return 0; } static int nextIndex = 1; windowDescriptorBlock *AddWindowBlock(void) { /* create a new entry in the linkedlist of windows. * If the calloc fails, return NULL which will then go back to the * prim and fail it cleanly. * Initialize the block to a sensible state */ windowDescriptorBlock *thisWindow; thisWindow = (windowDescriptorBlock*) calloc(1, sizeof(windowDescriptorBlock)); if ( thisWindow == NULL) { return NULL; } thisWindow->next = windowListRoot; thisWindow->windowIndex = nextIndex++; thisWindow->handle = NULL; windowListRoot = thisWindow; return windowListRoot; } /* * RemoveWindowBlock: * Remove the given entry from the list of windows. * free it, if found. */ int RemoveWindowBlock(windowDescriptorBlock * thisWindow) { windowDescriptorBlock *prevEntry; /* Unlink the entry from the module chain */ if(thisWindow == windowListRoot) { windowListRoot = thisWindow->next; } else { prevEntry = windowListRoot; while(prevEntry->next != thisWindow) { prevEntry = prevEntry->next; if (prevEntry == NULL) { return 0; } } prevEntry->next = thisWindow->next; } free(thisWindow); return 1; } int getCurrentIndexInUse(void) { return nextIndex-1; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/HostWindowPlugin/sqMacHostWindow.h ================================================ /* * sqMacHostWindow.h * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic */ #include #include "HostWindowPlugin.h" /* window handle type */ #define wHandleType WindowPtr #define wIndexType int typedef struct windowDescriptorBlock { struct windowDescriptorBlock * next; wHandleType handle; wIndexType windowIndex; /* extra fields to support your platform needs */ CGContextRef context; MouseTrackingRef windowTrackingRef; int rememberTicker; int dirty; int sync; int locked; int width; int height; int isInvisible; } windowDescriptorBlock; windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle); int windowIndexFromBlock( windowDescriptorBlock * thisWindow); int windowIndexFromHandle(wHandleType windowHandle); wHandleType windowHandleFromIndex(wIndexType windowIndex); windowDescriptorBlock *AddWindowBlock(void); windowDescriptorBlock *windowBlockFromIndex(int windowIndex); int getCurrentIndexInUse(void); void SetUpCarbonEventForWindowIndex(int index); void setWindowTrackingRgn(int windowIndex); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/IA32ABI/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable IA32ABIPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.IA32ABIPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.1.0 CFBundleSignature FAST CFBundleVersion 1.1.0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/InternetConfigPlugin/InternetConfiguration.xml ================================================ ]> InternetConfigPlugin UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathMac OS X:Users:Shared:VMMaker-v2.2 Folder:src:vm: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameInternetConfigPlugin OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E31416C706861314D540000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources x MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract0 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileInternetConfigPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library WeakImport Name myMacHeaders.pch MacOS Text Debug Name InternetConfigPlugin.c MacOS Text Debug Name sqMacInternetConfiguration.c MacOS Text Debug Name InternetConfigLib MacOS Library Debug, WeakImport Name CarbonAccessors.o MacOS Library Debug Name sqMacFileLogic.c MacOS Text Debug Name sqMacFileLogic.h MacOS Text Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name myMacHeaders.pch MacOS Name InternetConfigPlugin.c MacOS Name sqMacInternetConfiguration.c MacOS Name InternetConfigLib MacOS Name CarbonAccessors.o MacOS Name sqMacFileLogic.c MacOS Name sqMacFileLogic.h MacOS InternetConfigPluginOpt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathMac OS X:Users:Shared:VMMaker-v2.2 Folder:src:vm: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameInternetConfigPluginOpt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E31416C706861314D540000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources x MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileInternetConfigPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library WeakImport Name myMacHeaders.pch MacOS Text Debug Name InternetConfigPlugin.c MacOS Text Debug Name sqMacInternetConfiguration.c MacOS Text Debug Name InternetConfigLib MacOS Library Debug, WeakImport Name CarbonAccessors.o MacOS Library Debug Name sqMacFileLogic.c MacOS Text Debug Name sqMacFileLogic.h MacOS Text Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name myMacHeaders.pch MacOS Name InternetConfigPlugin.c MacOS Name sqMacInternetConfiguration.c MacOS Name InternetConfigLib MacOS Name CarbonAccessors.o MacOS Name sqMacFileLogic.c MacOS Name sqMacFileLogic.h MacOS InternetConfigPlugin InternetConfigPluginOpt Group 1 InternetConfigPlugin Name sqMacInternetConfiguration.c MacOS InternetConfigPlugin Name sqMacFileLogic.c MacOS InternetConfigPlugin Name sqMacFileLogic.h MacOS InternetConfigPlugin Name InternetConfigPlugin.c MacOS InternetConfigPlugin Name MSL C.PPC.Lib MacOS InternetConfigPlugin Name MSL RuntimePPC.Lib MacOS InternetConfigPlugin Name InterfaceLib MacOS InternetConfigPlugin Name InternetConfigLib MacOS InternetConfigPlugin Name MathLib MacOS InternetConfigPlugin Name CarbonAccessors.o MacOS InternetConfigPlugin Name myMacHeaders.pch MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/InternetConfigPlugin/sqMacInternetConfiguration.c ================================================ /* Sep 26th 2001 Interface to the Internet Configuration toolkit John M McIntosh of Corporate Smalltalk Consulting Ltd johnmci@smalltalkconsulting.com http://www.smalltalkconsulting.com Nov 24th 2001 JMM fixed broken tempSpec code, was causing memory exception under os-x 3.7.0bx Nov 24th, 2003 JMM gCurrentVMEncoding 3.8.18b2 fix broken endian code in sqInternetGetMacintoshFileTypeAndCreatorFromkeySizeinto */ #include #include "sq.h" #include "InternetConfigPlugin.h" #include "sqMacFileLogic.h" #include "sqMacUIConstants.h" static OSType GetApplicationSignature(void); void convertPassword(unsigned char *buffer); static ICInstance gICInstance; static Boolean gInitializedOk=false; void convertPSTRToString(unsigned char*pstr,char *target); int sqInternetConfigurationInit(void) { OSStatus error; OSType signature; if (gInitializedOk) return 1; if ((Ptr)ICStart==(Ptr)kUnresolvedCFragSymbolAddress) return 0; signature = GetApplicationSignature(); error = ICStart(&gICInstance, signature); if (error != noErr) return 0; gInitializedOk = true; return 1; } int sqInternetConfigurationShutdown(void) { if (!gInitializedOk) return 1; ICStop(gICInstance); gInitializedOk = false; return 1; } int sqInternetConfigurationGetStringKeyedBykeySizeinto(char *aKey,int keyLength, char *aString) { ICAttr junkAttr; long size=0; OSStatus error; Str255 key; char convertedKey[256],buffer[DOCUMENT_NAME_SIZE+1]; ICFileSpec *tempICFileSpec; if (!gInitializedOk) return 0; if (keyLength+1 > (int) sizeof(convertedKey)) return 0; strncpy(convertedKey,aKey,keyLength); convertedKey[keyLength] = 0; CopyCStringToPascal(convertedKey,key); if (strcmp(convertedKey,"DownLoadPath") == 0) { size = sizeof(ICFileSpec); error = ICGetPref(gICInstance, "\pDownloadFolder", nil, &buffer, &size); if (error == noErr || error == icTruncatedErr) { FSRef theFSRef; tempICFileSpec = (ICFileSpec *) &buffer; error = FSpMakeFSRef (&tempICFileSpec->fss, &theFSRef); if(error) return 0; PathToFileViaFSRef(aString, DOCUMENT_NAME_SIZE, &theFSRef,gCurrentVMEncoding); size = strlen(aString); } else return 0; } else { size = 1024; error = ICGetPref(gICInstance, key, &junkAttr, &buffer, &size); if (error == noErr) { if (size == 0) return size; if ((strcmp(convertedKey,"FTPProxyPassword") == 0|| strcmp(convertedKey,"MailPassword") == 0 || strcmp(convertedKey,"NewsAuthPassword") == 0)) { convertPassword((unsigned char *)buffer); } if ((strcmp(convertedKey,"UseFTPProxy") == 0 || strcmp(convertedKey,"UseGopherProxy") == 0 || strcmp(convertedKey,"UseHTTPProxy") == 0 || strcmp(convertedKey,"UsePassiveFTP") == 0 || strcmp(convertedKey,"UseSocks") == 0)) { if (buffer[0] == 0x01) strcpy(aString,"1"); else strcpy(aString,"0"); size = 1; } else if (strcmp(convertedKey,"NoProxyDomains") == 0) { convertPSTRToString((unsigned char *)buffer,aString); return strlen(aString); } else { CopyPascalStringToC((unsigned char *)buffer,aString); size--; } } } return size; } void sqInternetGetMacintoshFileTypeAndCreatorFromkeySizeinto(char * aFileName, int keyLength, char * creator){ Str255 filename; char convertedKey[256]; ICMapEntry mapEntry; OSStatus error; if (!gInitializedOk) goto abort; if (keyLength+1 > (int) sizeof(convertedKey)) goto abort; strncpy(convertedKey,aFileName,keyLength); convertedKey[keyLength] = 0; CopyCStringToPascal(convertedKey,filename); error = ICMapFilename(gICInstance,filename,&mapEntry); if (error != noErr) goto abort; *((int *) creator) = CFSwapInt32BigToHost(mapEntry.fileType); *((int *) (creator+4)) = CFSwapInt32BigToHost(mapEntry.fileCreator); return; abort: strncpy(creator,"********",8); return; } static OSType GetApplicationSignature() { ProcessSerialNumber PSN; ProcessInfoRec pinfo; FSSpec pspec; OSStatus err; /* set up process serial number */ PSN.highLongOfPSN = 0; PSN.lowLongOfPSN = kCurrentProcess; /* set up info block */ pinfo.processInfoLength = sizeof(pinfo); pinfo.processName = NULL; pinfo.processAppSpec = &pspec; /* grab the vrefnum and directory */ err = GetProcessInformation(&PSN, &pinfo); if (err == noErr) { return pinfo.processSignature; } return 0; } void convertPassword(unsigned char *buffer) { int size,i; size = buffer[0]; for (i=0;i 1024) { target[totalSize] = 0x00; return; } memcpy(target+totalSize,(char *) arrayOfpstr+1,size); totalSize += size; target[totalSize++] = ','; arrayOfpstr += (size+1); } if (totalSize > 0) totalSize--; target[totalSize] = 0x00; return; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JPEGReadWriter2Plugin/JConfig.h ================================================ /* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define BMP_SUPPORTED /* BMP image file format */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ #define USE_MAC_MEMMGR ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Error_Handler.c ================================================ /* File: Error Handler.c Contains: Implementation of the HID utility error handlers for the HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if !defined (kBuildingLibrary) #define kVerboseErrors // system includes ---------------------------------------------------------- #ifdef kVerboseErrors #include #endif #endif // not kBuildingLibrary #include // project includes --------------------------------------------------------- #include "HID_Utilities_Internal.h" // globals (internal/private) ----------------------------------------------- // prototypes (internal/private) -------------------------------------------- // functions (internal/private) --------------------------------------------- #pragma mark - // ------------------------------------- // central error reporting void HIDReportErrorNum (char * strError, long numError) { char errMsgCStr [256]; sprintf (errMsgCStr, "%s #%ld (0x%lx)", strError, numError, numError); // out as debug string #ifdef kVerboseErrors { Str255 strErr = "\p"; CopyCStringToPascal (errMsgCStr, strErr); DebugStr (strErr); } #endif // kVerboseErrors } // ------------------------------------- void HIDReportError (char * strError) { char errMsgCStr [256]; sprintf (errMsgCStr, "%s", strError); // out as debug string #ifdef kVerboseErrors { Str255 strErr = "\p"; CopyCStringToPascal (errMsgCStr, strErr); DebugStr (strErr); } #endif // kVerboseErrors } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Error_Handler.h ================================================ /* File: HID_Error_Handler.h Contains: Definition of the interfaces to DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Usage notes: // include control -------------------------------------------------- #ifndef Error_Handler_h #define Error_Handler_h // includes --------------------------------------------------------- #ifdef __cplusplus extern "C" { #endif // structures (public) ----------------------------------------------- // public function declarations ------------------------------------- // Error reporter, can be set to report however the application desires extern void HIDReportError (char * strError); // Error with numeric code reporter, can be set to report however the application desires extern void HIDReportErrorNum (char * strError, long numError); #ifdef __cplusplus } #endif #endif // Error_Handler_h ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Name_Lookup.c ================================================ /* File: HID_Name_Lookup.c Contains: Implementation of the HID device name lookup functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HID_Utilities_Internal.h" #include "HID_Name_Lookup.h" #define FAKE_IT 1 // set true for debugging; returns the vendor, product & cookie (or usage info) as numbers. // --------------------------------- // Load the element strings from the given resource (XML) file into a CFPropertyListRef static CFPropertyListRef xml_load(const CFStringRef pResourceName,const CFStringRef pResourceExtension) { CFPropertyListRef tCFPropertyListRef = NULL; CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), pResourceName, pResourceExtension, NULL); if (NULL != resFileCFURLRef) { CFDataRef resCFDataRef; if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) { if (NULL != resCFDataRef) { CFStringRef errorString; tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); if (NULL == tCFPropertyListRef) CFShow(errorString); CFRelease(resCFDataRef); } } CFRelease(resFileCFURLRef); } return tCFPropertyListRef; } // --------------------------------- // Find an element string in the resource (XML) file static Boolean xml_search_cookie(const long pVendorID, const long pProductID, const long pCookie, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load(CFSTR("HID_cookie_strings"), CFSTR("plist")); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef vendorCFDictionaryRef; CFStringRef vendorKeyCFStringRef; vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) { CFDictionaryRef productCFDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef vendorCFStringRef; if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) { //CFShow(vendorCFStringRef); } productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) { CFStringRef fullCFStringRef = NULL; CFStringRef cookieKeyCFStringRef; CFStringRef productCFStringRef; CFStringRef cookieCFStringRef; if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) { //CFShow(productCFStringRef); } cookieKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pCookie); if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, cookieKeyCFStringRef, (const void**) &cookieCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, cookieCFStringRef); // CFShow(cookieCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), vendorCFStringRef, productCFStringRef, cookieKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(cookieKeyCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } // --------------------------------- // Find an element string in the resource (XML) file static Boolean xml_search_usage(const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load(CFSTR("HID_device_usage_strings"), CFSTR("plist")); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef vendorCFDictionaryRef; CFStringRef vendorKeyCFStringRef; vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) { CFDictionaryRef productCFDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef vendorCFStringRef; if (!CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) { vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("v: %ld"), pVendorID); //CFShow(vendorCFStringRef); } productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) { CFStringRef fullCFStringRef = NULL; CFStringRef usageKeyCFStringRef; CFStringRef productCFStringRef; CFStringRef usageCFStringRef; if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) { //CFShow(productCFStringRef); } usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), pUsagePage, pUsage); if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, usageCFStringRef); // CFShow(usageCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), vendorCFStringRef, productCFStringRef, usageKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(usageKeyCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } // --------------------------------- // set name from vendor id/product id look up Boolean HIDGetElementNameFromVendorProductCookie (const long pVendorID, const long pProductID, const long pCookie, char * pName) { Boolean result = false; *pName = 0; // clear name if (xml_search_cookie(pVendorID, pProductID, pCookie, pName)) return true; switch (pVendorID) { case kMacally: switch (pProductID) { case kiShock: result = true; switch (pCookie) { case 3: sprintf(pName, "D-Pad Up"); break; case 4: sprintf(pName, "D-Pad Down"); break; case 5: sprintf(pName, "D-Pad Left"); break; case 6: sprintf(pName, "D-Pad Right"); break; case 7: sprintf(pName, "Up Button"); break; case 8: sprintf(pName, "Right Button"); break; case 9: sprintf(pName, "Down Button"); break; case 10: sprintf(pName, "Left Button"); break; case 11: sprintf(pName, "C Button"); break; case 12: sprintf(pName, "B Button [Select]"); break; case 13: sprintf(pName, "A Button [Start]"); break; case 14: sprintf(pName, "F Button"); break; case 15: sprintf(pName, "R1 Trigger"); break; case 16: sprintf(pName, "R2 Trigger"); break; case 17: sprintf(pName, "L1 Trigger"); break; case 18: sprintf(pName, "L2 Trigger"); break; case 19: sprintf(pName, "Left Stick Button"); break; case 20: sprintf(pName, "Right Stick Button"); break; case 21: sprintf(pName, "D Button"); break; case 22: sprintf(pName, "E Button"); break; case 23: sprintf(pName, "Left Stick X-Axis"); break; case 24: sprintf(pName, "Left Stick Y-Axis"); break; case 25: sprintf(pName, "Right Stick X-Axis"); break; case 26: sprintf(pName, "Right Stick Y-Axis"); break; default: #if FAKE_IT sprintf(pName, "#{V:Macally, P:iShock, C:%ld}#", pCookie); #else result = false; #endif FAKE_IT break; } break; default: #if FAKE_IT sprintf(pName, "#{V:Macally, P:%ld, C:%ld}#", pProductID, pCookie); break; #else result = false; #endif FAKE_IT break; } break; case kMacsense: switch (pProductID) { case kFunPadF107: result = true; switch (pCookie) { case 3: sprintf(pName, "Button 1"); break; case 4: sprintf(pName, "Button 2"); break; case 5: sprintf(pName, "Button 3"); break; case 6: sprintf(pName, "Button 4"); break; case 7: sprintf(pName, "L1 Trigger"); break; case 8: sprintf(pName, "R1 Trigger"); break; case 9: sprintf(pName, "L2 Trigger"); break; case 10: sprintf(pName, "R2 Trigger"); break; case 11: sprintf(pName, "Right Stick X-Axis"); break; case 12: sprintf(pName, "Right Stick Y-Axis"); break; case 13: sprintf(pName, "Left Stick X-Axis"); break; case 14: sprintf(pName, "Left Stick Y-Axis"); break; case 15: sprintf(pName, "Hat Switch"); break; default: #if FAKE_IT sprintf(pName, "#{V:Macsense, P:FunPad F-107, C:%ld}#", pCookie); #else result = false; #endif FAKE_IT break; } default: #if FAKE_IT sprintf(pName, "#{V:Macsense, P:%ld, C:%ld}#", pProductID, pCookie); #else result = false; #endif FAKE_IT break; } break; default: #if FAKE_IT sprintf(pName, "#{V:%ld, P:%ld, C:%ld}#", pVendorID, pProductID, pCookie); #else result = false; #endif FAKE_IT break; } return result; } // --------------------------------- // set name from vendor id/product id & usage look up Boolean HIDGetElementNameFromVendorProductUsage (const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char * pName) { Boolean result = false; *pName = 0; // clear name if (xml_search_usage(pVendorID, pProductID, pUsagePage, pUsage, pName)) return true; #if FAKE_IT sprintf(pName, "#{V:%ld, P:%ld, U:%ld:%ld}#", pVendorID, pProductID, pUsagePage, pUsage); result = true; #endif return result; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Name_Lookup.h ================================================ /* File: HID_Name_Lookup.h Contains: Definition of the HID device name lookup functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Name_Lookup_h_ #define _HID_Name_Lookup_h_ #include "HID_Utilities.h" // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== // Note: Now that as the device data has now been moved into external .XML files these // constansts should no longer be used. They will eventually be eliminated from this header. #define kMicrosoft 1118 #define kSideWinderFFB2 27 #define kLogitech 1133 #define kWingManStrikeForce3D 49797 #define kMacally 8738 #define kiShock 16400 #define kiShockIIFFB 16416 #define kMacsense 1635 #define kFunPadF107 38916 // ================================== // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // ================================== #ifdef __cplusplus } #endif #endif // _HID_Name_Lookup_h_ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Queue_Utilities.c ================================================ /* File: HID_Queue_Utilities.c Contains: Implementation of the HID queue functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //#include #include "HID_Utilities_Internal.h" #include "HID_Utilities_External.h" // ================================== // compiler directives // ================================== #define USE_ASYNC_EVENTS TRUE #define REPORT_ERRORS FALSE // ================================== #if REPORT_ERRORS #define HIDREPORTERRORNUM(s,n) HIDReportErrorNum(s,n) #define HIDREPORTERROR(s) HIDReportError(s) #else #define HIDREPORTERRORNUM(s,n) do {} while (false) #define HIDREPORTERROR(s) do {} while (false) #endif // ================================== // private functions // ================================== // creates a queue for a device static IOReturn hid_CreateQueue (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL == pDevice->queue) // do we already have a queue { if (NULL != pDevice->interface) { pDevice->queue = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocQueue (pDevice->interface); // alloc queue if (pDevice->queue) { result = (*(IOHIDQueueInterface**) pDevice->queue)->create (pDevice->queue, 0, kDeviceQueueSize); // create actual queue if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_CreateQueue - Failed to create queue via create", result); } else { HIDREPORTERROR ("hid_CreateQueue - Failed to alloc IOHIDQueueInterface ** via allocQueue"); result = kIOReturnError; // synthesis error } } else HIDREPORTERRORNUM ("hid_CreateQueue - Device inteface does not exist for queue creation", result); } } else HIDREPORTERRORNUM ("hid_CreateQueue - Invalid Device", result); return result; } // --------------------------------- // returns true if queue is empty false otherwise // error if no device, empty if no queue static unsigned char hid_IsDeviceQueueEmpty (pRecDevice pDevice) { if (HIDIsValidDevice(pDevice)) // need valid device { if (pDevice->queue) // and queue { pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); while (pElement) { if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) return false; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } else HIDREPORTERROR ("hid_IsDeviceQueueEmpty - no queue."); } else HIDREPORTERROR ("hid_IsDeviceQueueEmpty - Invalid device."); return true; } // --------------------------------- // disposes and releases queue, sets queue to NULL,. // Note: will have no effect if device or queue do not exist static IOReturn hid_DisposeReleaseQueue (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) // need valid device { if (pDevice->queue) // and queue { // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to stop queue.", result); // dispose of queue result = (*(IOHIDQueueInterface**) pDevice->queue)->dispose (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to dipose queue.", result); // release the queue result = (*(IOHIDQueueInterface**) pDevice->queue)->Release (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to release queue.", result); pDevice->queue = NULL; } else HIDREPORTERROR ("hid_DisposeReleaseQueue - no queue."); } else HIDREPORTERROR ("hid_DisposeReleaseQueue - Invalid device."); return result; } // ================================== // public functions // --------------------------------- // queues specific element, performing any device queue set up required // queue is started and ready to return events on exit from this function unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice,pElement)) { if (NULL == pDevice->interface) // must have interface { HIDREPORTERROR ("HIDQueueElement - Device does not have interface."); return kIOReturnError; } if (NULL == pDevice->queue) // if no queue create queue result = hid_CreateQueue (pDevice); if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) { HIDREPORTERRORNUM ("HIDQueueElement - problem creating queue.", result); if (kIOReturnSuccess != result) return result; else return kIOReturnError; } // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to stop queue."); // queue element if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to add Element to queue."); } // restart queue result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to start queue."); } else { HIDREPORTERROR ("HIDQueueElement - Invalid Device and/or element."); return kIOReturnBadArgument; } return result; } // --------------------------------- // adds all elements to queue, performing any device queue set up required // queue is started and ready to return events on exit from this function unsigned long HIDQueueDevice (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) pRecElement pElement; if (HIDIsValidDevice(pDevice)) { // error checking if (NULL == pDevice) { HIDREPORTERROR ("HIDQueueDevice - Device does not exist."); return kIOReturnBadArgument; } if (NULL == pDevice->interface) // must have interface { HIDREPORTERROR ("HIDQueueDevice - Device does not have interface."); return kIOReturnError; } if (NULL == pDevice->queue) // if no queue create queue result = hid_CreateQueue (pDevice); if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) { HIDREPORTERRORNUM ("HIDQueueDevice - problem creating queue.", result); if (kIOReturnSuccess != result) return result; else return kIOReturnError; } // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to stop queue.", result); // queue element // pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput | kHIDElementTypeFeature); while (pElement) { if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to add element to queue.", result); } // pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput | kHIDElementTypeFeature); } // start queue result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to start queue.", result); } else HIDREPORTERROR ("HIDQueueDevice - Invalid device."); return result; } // --------------------------------- // removes element for queue, if last element in queue will release queue and closes device interface unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice,pElement)) { if (!pDevice || !pElement) result = kIOReturnBadArgument; else { if ((pDevice->interface) && (pDevice->queue)) { // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to stop queue.", result); if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) // if has element then remove { result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to add element to queue", result); } if (hid_IsDeviceQueueEmpty (pDevice)) // release device queue and close interface if queue empty { result = hid_DisposeReleaseQueue (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to dispose and release queue.", result); } else // not empty so restart queue { result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to start queue.", result); } } else { HIDREPORTERROR ("HIDDequeueElement - No device inteface or queue."); return kIOReturnError; } } } else HIDREPORTERROR ("HIDDequeueElement - Invalid device."); return result; } // --------------------------------- // completely removes all elements from queue and releases queue and closes device interface // does not release device interfaces, application must call HIDReleaseDeviceList on exit unsigned long HIDDequeueDevice (pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; if (HIDIsValidDevice(pDevice)) { if ((pDevice->interface) && (pDevice->queue)) { // iterate through elements and if queued, remove pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); while (pElement) { if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueDevice - Failed to remove element from queue.", result); } pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } // ensure queue is disposed and released // interface will be closed and released on call to HIDReleaseDeviceList result = hid_DisposeReleaseQueue (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("removeElement - Failed to dispose and release queue.", result); #if USE_ASYNC_EVENTS else if (NULL != pDevice->queueRunLoopSource) { if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); CFRelease(pDevice->queueRunLoopSource); pDevice->queueRunLoopSource = NULL; } #endif USE_ASYNC_EVENTS } else { HIDREPORTERROR ("HIDDequeueDevice - Invalid device."); result = kIOReturnBadArgument; } return result; } // --------------------------------- // releases all device queues for quit or rebuild (must be called) // does not release device interfaces, application must call HIDReleaseDeviceList on exit unsigned long HIDReleaseAllDeviceQueues (void) { IOReturn result = kIOReturnBadArgument; pRecDevice pDevice = HIDGetFirstDevice (); while (pDevice) { result = HIDDequeueDevice (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDReleaseAllDeviceQueues - Could not dequeue device.", result); pDevice = HIDGetNextDevice (pDevice); } return result; } // --------------------------------- // Closes and releases interface to device, should be done prior to exting application // Note: will have no affect if device or interface do not exist // application will "own" the device if interface is not closed // (device may have to be plug and re-plugged in different location to get it working again without a restart) unsigned long HIDCloseReleaseInterface (pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; if (HIDIsValidDevice(pDevice) && (NULL != pDevice->interface)) { // close the interface result = (*(IOHIDDeviceInterface**) pDevice->interface)->close (pDevice->interface); if (kIOReturnNotOpen == result) { // do nothing as device was not opened, thus can't be closed } else if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to close IOHIDDeviceInterface.", result); //release the interface result = (*(IOHIDDeviceInterface**) pDevice->interface)->Release (pDevice->interface); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to release interface.", result); pDevice->interface = NULL; } return result; } // --------------------------------- // Get the next event in the queue for a device // elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition // Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility) unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent) { IOReturn result = kIOReturnBadArgument; AbsoluteTime zeroTime = {0,0}; if (HIDIsValidDevice(pDevice)) { if (pDevice->queue) { result = (*(IOHIDQueueInterface**) pDevice->queue)->getNextEvent (pDevice->queue, (IOHIDEventStruct *)pHIDEvent, zeroTime, 0); if (kIOReturnUnderrun == result) return false; // no events in queue not an error per say else if (kIOReturnSuccess != result) // actual error versus just an empty queue HIDREPORTERRORNUM ("HIDGetEvent - Could not get HID event via getNextEvent.", result); else return true; } else HIDREPORTERROR ("HIDGetEvent - queue does not exist."); } else HIDREPORTERROR ("HIDGetEvent - invalid device."); return false; // did not get event } // --------------------------------- // returns current value for element, polling element // will return 0 on error conditions which should be accounted for by application long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnBadArgument; IOHIDEventStruct hidEvent; hidEvent.value = 0; hidEvent.longValueSize = 0; hidEvent.longValue = nil; if (HIDIsValidElement(pDevice, pElement)) { if (NULL != pDevice->interface) { // ++ NOTE: If the element type is feature then use queryElementValue instead of getElementValue if (kIOHIDElementTypeFeature == pElement->type) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->queryElementValue (pDevice->interface, pElement->cookie, &hidEvent,0,NULL,NULL,NULL); if (kIOReturnUnsupported == result) // unless it's unsuported. goto try_getElementValue; else if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via queryElementValue.", result); } else if (pElement->type <= kIOHIDElementTypeInput_ScanCodes) { try_getElementValue: result = (*(IOHIDDeviceInterface**) pDevice->interface)->getElementValue (pDevice->interface, pElement->cookie, &hidEvent); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via getElementValue.", result); } // on 10.0.x this returns the incorrect result for negative ranges, so fix it!!! // this is not required on Mac OS X 10.1+ if ((pElement->min < 0) && (hidEvent.value > pElement->max)) // assume range problem hidEvent.value = hidEvent.value + pElement->min - pElement->max - 1; } else HIDREPORTERROR ("HIDGetElementValue - no interface for device."); } else HIDREPORTERROR ("HIDGetElementValue - invalid device and/or element."); // record min and max for auto scale and auto ... if (hidEvent.value < pElement->calMin) pElement->calMin = hidEvent.value; if (hidEvent.value > pElement->calMax) pElement->calMax = hidEvent.value; // auto user scale return hidEvent.value; } // --------------------------------- // Set an elements value // NOTE: This should only be used when a single element of a report needs to be sent. // If multiple elements are to be send then transactions should be used. long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent) { IOHIDEventStruct* pMyIOHIDEvent = (IOHIDEventStruct*) pIOHIDEvent; IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice, pElement)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->setElementValue (pDevice->interface, pElement->cookie, pMyIOHIDEvent, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetElementValue - Could not set HID element value via setElementValue.", result); } else HIDREPORTERROR ("HIDSetElementValue - no interface for device."); } else HIDREPORTERROR ("HIDSetElementValue - invalid device and/or element."); return result; } // --------------------------------- // Set a callback to be called when a queue goes from empty to non-empty long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { #if USE_ASYNC_EVENTS // if we don't have a queue runloop source if (NULL == pDevice->queueRunLoopSource) { // then create one result = (*(IOHIDQueueInterface**) pDevice->queue)->createAsyncEventSource((void *) pDevice->queue, (CFRunLoopSourceRef*) &pDevice->queueRunLoopSource); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetQueueCallback - Failed to createAsyncEventSource error: ", result); } // if we have one now if (NULL != pDevice->queueRunLoopSource) { // and it's not already attached to our runloop if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) // then attach it now. CFRunLoopAddSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); } // now install our callback result = (*(IOHIDQueueInterface**) pDevice->queue)->setEventCallout(pDevice->queue, callback, pDevice, pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetQueueCallback - Could not set HID queue callback via setEventCallout.", result); #endif USE_ASYNC_EVENTS } else HIDREPORTERROR ("HIDSetQueueCallback - invalid device and/or element."); return result; } #if 1 // --------------------------------- // Get a report from a device long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize); long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->getReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetReport - Could not getReport, error: ", result); } else HIDREPORTERROR ("HIDGetReport - no interface for device."); } else HIDREPORTERROR ("HIDGetReport - invalid device."); return result; } // --------------------------------- // Send a report to a device long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize); long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->setReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetReport - Could not setReport; error: ", result); } else HIDREPORTERROR ("HIDGetReport - no interface for device."); } else HIDREPORTERROR ("HIDGetReport - invalid device."); return result; } #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Queue_Utilities.h ================================================ /* File: HID_Queue_Utilities.h Contains: Definition of the HID queue functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Queue_Utilities_h_ #define _HID_Queue_Utilities_h_ #include "HID_Utilities.h" // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== enum { kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate of // if states change quickly (updates are only posted on state changes) }; // ================================== // queues specific element, performing any device queue set up required extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); // adds all elements to queue, performing any device queue set up required extern unsigned long HIDQueueDevice (pRecDevice pDevice); // removes element for queue, if last element in queue will release queue and device extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); // completely removes all elements from queue and releases queue and device extern unsigned long HIDDequeueDevice (pRecDevice pDevice); // releases all device queues for quit or rebuild (must be called) extern unsigned long HIDReleaseAllDeviceQueues (void); // releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); // returns current value for element, creating device interface as required, polling element extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); // Set an elements value // NOTE: This should only be used when a single element report needs to be sent. // If multiple elements reports are to be send then transactions should be used. extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pIOHIDEvent); // Set a callback to be called when a queue goes from empty to non-empty extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); #if 0 // Get a report from a device extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize); // Send a report to a device extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize); #endif #ifdef __cplusplus } #endif #endif // _HID_Queue_Utilities_h_ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Utilities.c ================================================ /* File: HID_Utilities.c Contains: Implementation of HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HID_Utilities_Internal.h" #include "HID_Utilities_External.h" #include #include #include #include //================================================================================================ #define USE_NOTIFICATIONS 1 //================================================================================================ // local (static) functions //================================================================================================ static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection); static pRecDevice hid_DisposeDevice (pRecDevice ppDevice); //================================================================================================ // globals //================================================================================================ #if USE_NOTIFICATIONS static IONotificationPortRef gNotifyPort; static io_iterator_t gAddedIter; static CFRunLoopRef gRunLoop; #endif USE_NOTIFICATIONS // for element retrieval static pRecDevice gCurrentGetDevice = NULL; static Boolean gAddAsChild = false; static int gDepth = false; static pRecDevice gpDeviceList = NULL; static UInt32 gNumDevices = 0; #pragma mark private functions // ================================== // private functions static UInt32 hid_CountCurrentDevices (void); // extracts actual specific element information from each element CF dictionary entry static void hid_GetElementInfo (CFTypeRef refElement, pRecElement pElement) { long number; CFTypeRef refType; // type, usagePage, usage already stored refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->cookie = (IOHIDElementCookie) number; else pElement->cookie = (IOHIDElementCookie) 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->min = number; else pElement->min = 0; pElement->calMax = pElement->min; pElement->userMin = kDefaultUserMin; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->max = number; else pElement->max = 0; pElement->calMin = pElement->max; pElement->userMax = kDefaultUserMax; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMin = number; else pElement->scaledMin = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMax = number; else pElement->scaledMax = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->size = number; else pElement->size = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); if (refType) pElement->relative = CFBooleanGetValue (refType); else pElement->relative = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); if (refType) pElement->wrapping = CFBooleanGetValue (refType); else pElement->wrapping = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); if (refType) pElement->nonLinear = CFBooleanGetValue (refType); else pElement->wrapping = false; #ifdef kIOHIDElementHasPreferredStateKey refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferredStateKey)); #else // Mac OS X 10.0 has spelling error refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); #endif if (refType) pElement->preferredState = CFBooleanGetValue (refType); else pElement->preferredState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); if (refType) pElement->nullState = CFBooleanGetValue (refType); else pElement->nullState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->units = number; else pElement->units = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitExponentKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->unitExp = number; else pElement->unitExp = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementNameKey)); if (refType) if (!CFStringGetCString (refType, pElement->name, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pElement->name."); if (!*pElement->name) { // set name from vendor id, product id & usage info look up if (!HIDGetElementNameFromVendorProductUsage (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, pElement->usagePage, pElement->usage, pElement->name)) { // set name from vendor id/product id look up HIDGetElementNameFromVendorProductCookie (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, (long) pElement->cookie, pElement->name); if (!*pElement->name) { // if no name HIDGetUsageName (pElement->usagePage, pElement->usage, pElement->name); if (!*pElement->name) // if not usage sprintf (pElement->name, "Element"); } } } } // --------------------------------- // examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements // if element of interest allocate storage, add to list and retrieve element specific info // if collection then pass on to deconstruction collection into additional individual elements static void hid_AddElement (CFTypeRef refElement, pRecElement * ppElementCurrent) { pRecDevice pDevice = gCurrentGetDevice; pRecElement pElement = NULL; long elementType, usagePage, usage; CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); if (refElementType) CFNumberGetValue (refElementType, kCFNumberLongType, &elementType); if (refUsagePage) CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage); if (refUsage) CFNumberGetValue (refUsage, kCFNumberLongType, &usage); if (NULL == pDevice) return; if (elementType) { // look at types of interest if (elementType != kIOHIDElementTypeCollection) { if (usagePage && usage) // if valid usage and page { switch (usagePage) // only interested in kHIDPage_GenericDesktop and kHIDPage_Button { case kHIDPage_GenericDesktop: { switch (usage) // look at usage to determine function { case kHIDUsage_GD_X: case kHIDUsage_GD_Y: case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->axis++; break; case kHIDUsage_GD_Slider: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->sliders++; break; case kHIDUsage_GD_Dial: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->dials++; break; case kHIDUsage_GD_Wheel: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->wheels++; break; case kHIDUsage_GD_Hatswitch: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->hats++; break; default: pElement = (pRecElement) malloc (sizeof (recElement)); break; } } break; case kHIDPage_Button: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->buttons++; break; default: // just add a generic element pElement = (pRecElement) malloc (sizeof (recElement)); break; } } #if 0 else HIDReportError ("CFNumberGetValue error when getting value for refUsage or refUsagePage."); #endif 0 } else // collection pElement = (pRecElement) malloc (sizeof (recElement)); } else HIDReportError ("CFNumberGetValue error when getting value for refElementType."); if (pElement) // add to list { // this code builds a binary tree based on the collection hierarchy of inherent in the device element layout // it preserves the structure of the lements as collections have children and elements are siblings to each other // clear record bzero(pElement,sizeof(recElement)); // get element info pElement->type = elementType; pElement->usagePage = usagePage; pElement->usage = usage; pElement->depth = 0; // assume root object hid_GetElementInfo (refElement, pElement); // count elements pDevice->totalElements++; switch (pElement->type) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: pDevice->inputs++; break; case kIOHIDElementTypeOutput: pDevice->outputs++; break; case kIOHIDElementTypeFeature: pDevice->features++; break; case kIOHIDElementTypeCollection: pDevice->collections++; break; default: HIDReportErrorNum ("Unknown element type : ", pElement->type); } if (NULL == *ppElementCurrent) // if at list head { pDevice->pListElements = pElement; // add current element *ppElementCurrent = pElement; // set current element to element we just added } else // have exsiting structure { if (gAddAsChild) // if the previous element was a collection, let's add this as a child of the previous { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pChild) // step down tree until free child node found *ppElementCurrent = (*ppElementCurrent)->pChild; (*ppElementCurrent)->pChild = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth + 1; } else // add as sibling { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pSibling) // step down tree until free sibling node found *ppElementCurrent = (*ppElementCurrent)->pSibling; (*ppElementCurrent)->pSibling = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth; } pElement->pPrevious = *ppElementCurrent; // point to previous *ppElementCurrent = pElement; // set current to our collection } if (elementType == kIOHIDElementTypeCollection) // if this element is a collection of other elements { gAddAsChild = true; // add next set as children to this element gDepth++; hid_GetCollectionElements ((CFMutableDictionaryRef) refElement, &pElement); // recursively process the collection gDepth--; } gAddAsChild = false; // add next as this elements sibling (when return from a collection or with non-collections) } #if 0 else HIDReportError ("hid_AddElement - no element added."); #endif } // --------------------------------- // collects information from each array member in device element list (each array memeber = element) static void hid_GetElementsCFArrayHandler (const void * value, void * parameter) { if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) hid_AddElement ((CFTypeRef) value, (pRecElement *) parameter); } // --------------------------------- // handles retrieval of element information from arrays of elements in device IO registry information static void hid_GetElements (CFTypeRef refElementCurrent, pRecElement *ppCurrentElement) { CFTypeID type = CFGetTypeID (refElementCurrent); if (type == CFArrayGetTypeID()) // if element is an array { CFRange range = {0, CFArrayGetCount (refElementCurrent)}; // CountElementsCFArrayHandler called for each array member CFArrayApplyFunction (refElementCurrent, range, hid_GetElementsCFArrayHandler, ppCurrentElement); } } // --------------------------------- // handles extracting element information from element collection CF types // used from top level element decoding and hierarchy deconstruction to flatten device element list static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection) { CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); if (refElementTop) hid_GetElements (refElementTop, ppCurrentCollection); else HIDReportError ("hid_GetCollectionElements: CFDictionaryGetValue error when creating CFTypeRef for kIOHIDElementKey."); } // --------------------------------- // use top level element usage page and usage to discern device usage page and usage setting appropriate values in device record static void hid_TopLevelElementHandler (const void * value, void * parameter) { CFTypeRef refCF = 0; if ((NULL == value) || (NULL == parameter)) return; // (kIOReturnBadArgument) if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) return; // (kIOReturnBadArgument) refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); } // --------------------------------- // extracts device info from CF dictionary records in IO registry static void hid_GetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, pRecDevice pDevice) { CFMutableDictionaryRef usbProperties = 0; io_registry_entry_t parent1, parent2; // Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also // get dictionary for usb properties: step up two levels and get CF dictionary for USB properties if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) { if (usbProperties) { CFTypeRef refCF = 0; // get device info // try hid dictionary first, if fail then go to usb dictionary // get transport refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDTransportKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->transport, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->transport."); } // get vendorID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVendorIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idVendor")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->vendorID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->vendorID."); } // get product ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idProduct")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->productID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->productID."); } // get product version refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVersionNumberKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->version)) HIDReportError ("CFNumberGetValue error retrieving pDevice->version."); } // get manufacturer name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDManufacturerKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Vendor Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->manufacturer, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->manufacturer."); } // get product name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->product."); } // get serial refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDSerialNumberKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->serial, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->serial."); } // get location ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDLocationIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("locationID")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->locID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->locID."); } // get usage page and usage refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); if (refCF) if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); } if (NULL == refCF) // get top level element HID usage page or usage { // use top level element instead CFTypeRef refCFTopElement = 0; refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); { // refCFTopElement points to an array of element dictionaries CFRange range = {0, CFArrayGetCount (refCFTopElement)}; CFArrayApplyFunction (refCFTopElement, range, hid_TopLevelElementHandler, NULL); } } } else HIDReportError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); CFRelease (usbProperties); if (kIOReturnSuccess != IOObjectRelease (parent2)) HIDReportError ("IOObjectRelease error with parent2."); if (kIOReturnSuccess != IOObjectRelease (parent1)) HIDReportError ("IOObjectRelease error with parent1."); } } // --------------------------------- // adds device to linked list of devices passed in (handles NULL lists properly) // (returns where you just stored it) static pRecDevice* hid_AddDevice (pRecDevice *ppListDeviceHead, pRecDevice pNewDevice) { pRecDevice* result = NULL; if (NULL == *ppListDeviceHead) result = ppListDeviceHead; else { pRecDevice pDevicePrevious = NULL, pDevice = *ppListDeviceHead; while (pDevice) { pDevicePrevious = pDevice; pDevice = pDevicePrevious->pNext; } result = &pDevicePrevious->pNext; } pNewDevice->pNext = NULL; *result = pNewDevice; return result; } // --------------------------------- // given a IO device object build a flat device record including device info and elements static pRecDevice hid_BuildDevice (io_object_t hidDevice) { pRecDevice pDevice = (pRecDevice) malloc (sizeof (recDevice)); if (NULL != pDevice) { // get dictionary for HID properties CFMutableDictionaryRef hidProperties = 0; kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); // clear record bzero(pDevice, sizeof(recDevice)); if ((result == KERN_SUCCESS) && (NULL != hidProperties)) { pRecElement pCurrentElement = NULL; // create device interface result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); if (kIOReturnSuccess != result) HIDReportErrorNum ("HIDCreateOpenDeviceInterface failed.", result); hid_GetDeviceInfo (hidDevice, hidProperties, pDevice); // hidDevice used to find parents in registry tree // set current device for use in getting elements gCurrentGetDevice = pDevice; // Add all elements hid_GetCollectionElements (hidProperties, &pCurrentElement); gCurrentGetDevice = NULL; CFRelease (hidProperties); } else HIDReportErrorNum ("IORegistryEntryCreateCFProperties error when creating deviceProperties.", result); } else HIDReportError ("malloc error when allocating pRecDevice."); return pDevice; } #if USE_NOTIFICATIONS //================================================================================================ // // hid_DeviceNotification // // This routine will get called whenever any kIOGeneralInterest notification happens. We are // interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other // messages are defined in IOMessage.h. // //================================================================================================ // static void hid_DeviceNotification( void *refCon, io_service_t service, natural_t messageType, void *messageArgument ) { #pragma unused(messageArgument) pRecDevice pDevice = (pRecDevice) refCon; if (messageType == kIOMessageServiceIsTerminated) { printf("Device 0x%08x \"%s\"removed.\n", service, pDevice->product); // Free the data we're no longer using now that the device is going away hid_DisposeDevice (pDevice); } } #else static void hid_RemovalCallbackFunction(void * target, IOReturn result, void * refcon, void * sender) { hid_DisposeDevice ((pRecDevice) target); } #endif USE_NOTIFICATIONS //================================================================================================ // // hid_AddDevices // // This routine is the callback for our IOServiceAddMatchingNotification. When we get called // we will look at all the devices that were added and we will: // // 1. Create some private data to relate to each device. // 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, // using the refCon field to store a pointer to our data. When we get called with // this interest notification, we can grab the refCon and access our private data. // //================================================================================================ // // --------------------------------- // given a IO device iterator, iterate it and add all its devices static void hid_AddDevices (void *refCon, io_iterator_t iterator) { // NOTE: refcon passed in is used to point to the device list head pRecDevice* pListDeviceHead = (pRecDevice*) refCon; IOReturn result = kIOReturnSuccess; io_object_t ioHIDDeviceObject = 0; while ((ioHIDDeviceObject = IOIteratorNext (iterator))) { pRecDevice* pNewDeviceAt = NULL; pRecDevice pNewDevice = hid_BuildDevice (ioHIDDeviceObject); if (pNewDevice) { #if 0 // set true for verbose output printf("\nhid_AddDevices: pNewDevice = {t: \"%s\", v: %ld, p: %ld, v: %ld, m: \"%s\", " \ "p: \"%s\", l: %ld, u: %4.4lX:%4.4lX, #e: %ld, #f: %ld, #i: %ld, #o: %ld, " \ "#c: %ld, #a: %ld, #b: %ld, #h: %ld, #s: %ld, #d: %ld, #w: %ld}.", pNewDevice->transport, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->version, pNewDevice->manufacturer, pNewDevice->product, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage, pNewDevice->totalElements, pNewDevice->features, pNewDevice->inputs, pNewDevice->outputs, pNewDevice->collections, pNewDevice->axis, pNewDevice->buttons, pNewDevice->hats, pNewDevice->sliders, pNewDevice->dials, pNewDevice->wheels ); fflush(stdout); #elif 0 // otherwise output brief description printf("\nhid_AddDevices: pNewDevice = {m: \"%s\" p: \"%s\", vid: %ld, pid: %ld, loc: %8.8lX, usage: %4.4lX:%4.4lX}.", pNewDevice->manufacturer, pNewDevice->product, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage ); fflush(stdout); #endif pNewDeviceAt = hid_AddDevice (pListDeviceHead, pNewDevice); } #if USE_NOTIFICATIONS // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. result = IOServiceAddInterestNotification( gNotifyPort, // notifyPort ioHIDDeviceObject, // service kIOGeneralInterest, // interestType hid_DeviceNotification, // callback pNewDevice, // refCon (io_object_t*) &pNewDevice->notification); // notification if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOServiceAddInterestNotification error: x0%8.8lX.", result); #else result = (*(IOHIDDeviceInterface**)pNewDevice->interface)->setRemovalCallback (pNewDevice->interface, hid_RemovalCallbackFunction,pNewDeviceAt,0); #endif USE_NOTIFICATIONS // release the device object, it is no longer needed result = IOObjectRelease (ioHIDDeviceObject); if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOObjectRelease error with ioHIDDeviceObject.", result); } } // --------------------------------- // disposes of the element list associated with a device and the memory associated with the list // uses depthwise recursion to dispose both collections and elements. static void hid_DisposeDeviceElements (pRecElement pElement) { if (pElement) { if (pElement->pChild) hid_DisposeDeviceElements (pElement->pChild); if (pElement->pSibling) hid_DisposeDeviceElements (pElement->pSibling); free (pElement); } } // --------------------------------- // disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL // all your device no longer belong to us... (i.e., you do not 'own' the device anymore) static pRecDevice hid_DisposeDevice (pRecDevice pDevice) { kern_return_t result = KERN_SUCCESS; pRecDevice pDeviceNext = NULL; if (HIDIsValidDevice(pDevice)) { // save next device prior to disposing of this device pDeviceNext = pDevice->pNext; result = HIDDequeueDevice (pDevice); #if 0 if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: HIDDequeueDevice error: 0x%8.8X.", result); #endif 1 hid_DisposeDeviceElements (pDevice->pListElements); pDevice->pListElements = NULL; result = HIDCloseReleaseInterface (pDevice); // function sanity checks interface value (now application does not own device) if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: HIDCloseReleaseInterface error: 0x%8.8X.", result); #if USE_NOTIFICATIONS if (pDevice->interface) { // replace (*pDevice->interface)->Release(pDevice->interface); result = IODestroyPlugInInterface (pDevice->interface); if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: IODestroyPlugInInterface error: 0x%8.8X.", result); } if (pDevice->notification) { result = IOObjectRelease((io_object_t) pDevice->notification); if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: IOObjectRelease error: 0x%8.8X.", result); } #endif USE_NOTIFICATIONS // remove this device from the device list if (gpDeviceList == pDevice) // head of list? gpDeviceList = pDeviceNext; else { pRecDevice pDeviceTemp = pDeviceNext = gpDeviceList; // we're going to return this if we don't find ourselfs in the list while (pDeviceTemp) { if (pDeviceTemp->pNext == pDevice) // found us! { // take us out of linked list pDeviceTemp->pNext = pDeviceNext = pDevice->pNext; break; } pDeviceTemp = pDeviceTemp->pNext; } } free (pDevice); } // update device count gNumDevices = hid_CountCurrentDevices (); return pDeviceNext; } // --------------------------------- // count number of devices in global device list (gpDeviceList) static UInt32 hid_CountCurrentDevices (void) { pRecDevice pDevice = gpDeviceList; UInt32 devices = 0; while (pDevice) { devices++; pDevice = pDevice->pNext; } return devices; } // --------------------------------- // matches type masks passed in to actual element types (which are not set up to be used as a mask static Boolean hid_MatchElementTypeMask (IOHIDElementType type, HIDElementTypeMask typeMask) { if (typeMask & kHIDElementTypeInput) if ((type == kIOHIDElementTypeInput_Misc) || (type == kIOHIDElementTypeInput_Button) || (type == kIOHIDElementTypeInput_Axis) || (type == kIOHIDElementTypeInput_ScanCodes)) return true; if (typeMask & kHIDElementTypeOutput) if (type == kIOHIDElementTypeOutput) return true; if (typeMask & kHIDElementTypeFeature) if (type == kIOHIDElementTypeFeature) return true; if (typeMask & kHIDElementTypeCollection) if (type == kIOHIDElementTypeCollection) return true; return false; } // --------------------------------- static pRecElement hid_GetDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { // we are asking for this element if (NULL != pElement) { if (hid_MatchElementTypeMask (pElement->type, typeMask)) // if the type match what we are looking for return pElement; // return the element else return HIDGetNextDeviceElement (pElement, typeMask); // else get the next one } return NULL; } #define FAKE_IT 0 // set true for debugging; returns the usage & usage page as numbers // --------------------------------- // Load the usage strings from the resource (XML) file into a CFPropertyListRef static CFPropertyListRef xml_load_usage_strings(void) { CFPropertyListRef tCFPropertyListRef = NULL; CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("HID_usage_strings"), CFSTR("plist"), NULL); if (NULL != resFileCFURLRef) { CFDataRef resCFDataRef; if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) { if (NULL != resCFDataRef) { CFStringRef errorString; tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); if (NULL == tCFPropertyListRef) CFShow(errorString); CFRelease(resCFDataRef); } } CFRelease(resFileCFURLRef); } return tCFPropertyListRef; } // --------------------------------- // Find a usage string in the resource (XML) file static Boolean xml_GetUsageName(const long valueUsagePage, const long valueUsage, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load_usage_strings(); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef pageCFDictionaryRef; CFStringRef pageKeyCFStringRef; pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsagePage); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void**) &pageCFDictionaryRef)) { CFStringRef pageCFStringRef; if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, CFSTR("Name"), (const void**) &pageCFStringRef)) { //CFShow(pageCFStringRef); } { CFStringRef fullCFStringRef = NULL; CFStringRef usageKeyCFStringRef; CFStringRef usageCFStringRef; usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsage); if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), pageCFStringRef, usageCFStringRef); // CFShow(usageCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ #%@"), pageCFStringRef, usageKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(usageKeyCFStringRef); } } CFRelease(pageKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } #pragma mark public functions // ================================= // public functions // --------------------------------- // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; HRESULT plugInResult = S_OK; SInt32 score = 0; IOCFPlugInInterface ** ppPlugInInterface = NULL; if (NULL == pDevice->interface) { result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); if (kIOReturnSuccess == result) { // Call a method of the intermediate plug-in to create the device interface plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); if (S_OK != plugInResult) HIDReportErrorNum ("Couldnt query HID class device interface from plugInInterface", plugInResult); IODestroyPlugInInterface (ppPlugInInterface); // replace (*ppPlugInInterface)->Release (ppPlugInInterface) } else HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); } if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**)pDevice->interface)->open (pDevice->interface, 0); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); } return result; } // --------------------------------- // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, but not user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) // returns true if succesful Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage) { IOReturn result = kIOReturnSuccess; mach_port_t masterPort = 0; if (NULL != gpDeviceList) HIDReleaseDeviceList (); result = IOMasterPort (bootstrap_port, &masterPort); if (kIOReturnSuccess != result) HIDReportErrorNum ("IOMasterPort error with bootstrap_port.", result); else { CFMutableDictionaryRef hidMatchDictionary = NULL; // Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error. { CFNumberRef refUsage = NULL, refUsagePage = NULL; // Set up a matching dictionary to search I/O Registry by class name for all HID class devices. hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); if (NULL != hidMatchDictionary) { if (usagePage) { // Add key for device type (joystick, in this case) to refine the matching dictionary. refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usagePage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); CFRelease (refUsagePage); if (usage) { refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); CFRelease (refUsage); } } CFRetain(hidMatchDictionary); } else HIDReportError ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); } #if USE_NOTIFICATIONS // Create a notification port and add its run loop event source to our run loop // This is how async notifications get set up. { CFRunLoopSourceRef runLoopSource; gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. result = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType hidMatchDictionary, // matching hid_AddDevices, // callback &gpDeviceList, // refCon &gAddedIter // notification ); // call it now to add all existing devices hid_AddDevices(&gpDeviceList,gAddedIter); } #else { io_iterator_t hidObjectIterator = NULL; // Now search I/O Registry for matching devices. result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to create IO object iterator, error:", result); else if (NULL == hidObjectIterator) // likely no HID devices which matched selection criteria are connected HIDReportError ("Warning: Could not find any matching devices, thus iterator creation failed."); if (NULL != hidObjectIterator) { hid_AddDevices(&gpDeviceList,hidObjectIterator); result = IOObjectRelease (hidObjectIterator); // release the iterator if (kIOReturnSuccess != result) HIDReportErrorNum ("IOObjectRelease error with hidObjectIterator.", result); gNumDevices = hid_CountCurrentDevices (); return true; } } #endif USE_NOTIFICATIONS // IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. hidMatchDictionary = NULL; } return false; } // --------------------------------- // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain void HIDReleaseDeviceList (void) { while (NULL != gpDeviceList) gpDeviceList = hid_DisposeDevice (gpDeviceList); // dispose current device return next device will set gpDeviceList to NULL gNumDevices = 0; } // --------------------------------- // does a device list exist Boolean HIDHaveDeviceList (void) { if (NULL != gpDeviceList) return true; return false; } // --------------------------------- // how many HID devices have been found // returns 0 if no device list exist UInt32 HIDCountDevices (void) { gNumDevices = hid_CountCurrentDevices (); return gNumDevices; } // --------------------------------- // how many elements does a specific device have // returns 0 if device is invlaid or NULL UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask) { long count = 0; if (HIDIsValidDevice(pDevice)) { if (typeMask & kHIDElementTypeInput) count += pDevice->inputs; if (typeMask & kHIDElementTypeOutput) count += pDevice->outputs; if (typeMask & kHIDElementTypeFeature) count += pDevice->features; if (typeMask & kHIDElementTypeCollection) count += pDevice->collections; } return count; } // --------------------------------- // get the first device in the device list // returns NULL if no list exists pRecDevice HIDGetFirstDevice (void) { return gpDeviceList; } // --------------------------------- // get next device in list given current device as parameter // returns NULL if end of list pRecDevice HIDGetNextDevice (pRecDevice pDevice) { if (NULL != pDevice) return pDevice->pNext; else return NULL; } // --------------------------------- // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask) { if (HIDIsValidDevice(pDevice)) { if (hid_MatchElementTypeMask (pDevice->pListElements->type, typeMask)) // ensure first type matches return pDevice->pListElements; else return HIDGetNextDeviceElement (pDevice->pListElements, typeMask); } else return NULL; } // --------------------------------- // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { // should only have elements passed in (though someone could mix calls and pass us a collection) // collection means return the next child or sibling (in that order) // element means returnt he next sibling (as elements can't have children if (NULL != pElement) { if (pElement->pChild) { if (pElement->type != kIOHIDElementTypeCollection) HIDReportError ("Malformed element list: found child of element."); else return hid_GetDeviceElement (pElement->pChild, typeMask); // return the child of this element } else if (pElement->pSibling) { return hid_GetDeviceElement (pElement->pSibling, typeMask); //return the sibling of this element } else // at end back up correctly { pRecElement pPreviousElement = NULL; // malformed device ending in collection if (pElement->type == kIOHIDElementTypeCollection) HIDReportError ("Malformed device: found collection at end of element chain."); // walk back up tree to element prior to first collection ecountered and take next element while (NULL != pElement->pPrevious) { pPreviousElement = pElement; pElement = pElement->pPrevious; // look at previous element // if we have a collection and the previous element is the branch element (should have both a colection and next element attached to it) // if we found a collection, which we are not at the sibling level that actually does have siblings if (((pElement->type == kIOHIDElementTypeCollection) && (pPreviousElement != pElement->pSibling) && pElement->pSibling) || // or if we are at the top (NULL == pElement->pPrevious)) // at top of tree break; } if (NULL == pElement->pPrevious) return NULL; // got to top of list with only a collection as the first element // now we must have been down the child route so go down the sibling route pElement = pElement->pSibling; // element of interest return hid_GetDeviceElement (pElement, typeMask); // otherwise return this element } } return NULL; } // --------------------------------- // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { pRecElement pPreviousElement = pElement->pPrevious; // walk back up tree to element prior while (pPreviousElement && !hid_MatchElementTypeMask (pPreviousElement->type, typeMask)) { pElement = pPreviousElement; // look at previous element pPreviousElement = pElement->pPrevious; } return pPreviousElement; // return this element } // --------------------------------- // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns "Unknown Type" for invalid types void HIDGetTypeName (IOHIDElementType theType, char * cstrName) { switch (theType) { case kIOHIDElementTypeInput_Misc: sprintf(cstrName, "Miscellaneous Input"); break; case kIOHIDElementTypeInput_Button: sprintf(cstrName, "Button Input"); break; case kIOHIDElementTypeInput_Axis: sprintf(cstrName, "Axis Input"); break; case kIOHIDElementTypeInput_ScanCodes: sprintf(cstrName, "Scan Code Input"); break; case kIOHIDElementTypeOutput: sprintf(cstrName, "Output"); break; case kIOHIDElementTypeFeature: sprintf(cstrName, "Feature"); break; case kIOHIDElementTypeCollection: sprintf(cstrName, "Collection"); break; default: sprintf(cstrName, "Unknown Type"); break; } } // --------------------------------- // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values void HIDGetUsageName (const long valueUsagePage, const long valueUsage, char * cstrName) { if (xml_GetUsageName(valueUsagePage, valueUsage, cstrName)) return; switch (valueUsagePage) { case kHIDPage_Undefined: switch (valueUsage) { default: sprintf (cstrName, "Undefined Page, Usage 0x%lx", valueUsage); break; } break; case kHIDPage_GenericDesktop: switch (valueUsage) { case kHIDUsage_GD_Pointer: sprintf (cstrName, "Pointer"); break; case kHIDUsage_GD_Mouse: sprintf (cstrName, "Mouse"); break; case kHIDUsage_GD_Joystick: sprintf (cstrName, "Joystick"); break; case kHIDUsage_GD_GamePad: sprintf (cstrName, "GamePad"); break; case kHIDUsage_GD_Keyboard: sprintf (cstrName, "Keyboard"); break; case kHIDUsage_GD_Keypad: sprintf (cstrName, "Keypad"); break; case kHIDUsage_GD_MultiAxisController: sprintf (cstrName, "Multi-Axis Controller"); break; case kHIDUsage_GD_X: sprintf (cstrName, "X-Axis"); break; case kHIDUsage_GD_Y: sprintf (cstrName, "Y-Axis"); break; case kHIDUsage_GD_Z: sprintf (cstrName, "Z-Axis"); break; case kHIDUsage_GD_Rx: sprintf (cstrName, "X-Rotation"); break; case kHIDUsage_GD_Ry: sprintf (cstrName, "Y-Rotation"); break; case kHIDUsage_GD_Rz: sprintf (cstrName, "Z-Rotation"); break; case kHIDUsage_GD_Slider: sprintf (cstrName, "Slider"); break; case kHIDUsage_GD_Dial: sprintf (cstrName, "Dial"); break; case kHIDUsage_GD_Wheel: sprintf (cstrName, "Wheel"); break; case kHIDUsage_GD_Hatswitch: sprintf (cstrName, "Hatswitch"); break; case kHIDUsage_GD_CountedBuffer: sprintf (cstrName, "Counted Buffer"); break; case kHIDUsage_GD_ByteCount: sprintf (cstrName, "Byte Count"); break; case kHIDUsage_GD_MotionWakeup: sprintf (cstrName, "Motion Wakeup"); break; case kHIDUsage_GD_Start: sprintf (cstrName, "Start"); break; case kHIDUsage_GD_Select: sprintf (cstrName, "Select"); break; case kHIDUsage_GD_Vx: sprintf (cstrName, "X-Velocity"); break; case kHIDUsage_GD_Vy: sprintf (cstrName, "Y-Velocity"); break; case kHIDUsage_GD_Vz: sprintf (cstrName, "Z-Velocity"); break; case kHIDUsage_GD_Vbrx: sprintf (cstrName, "X-Rotation Velocity"); break; case kHIDUsage_GD_Vbry: sprintf (cstrName, "Y-Rotation Velocity"); break; case kHIDUsage_GD_Vbrz: sprintf (cstrName, "Z-Rotation Velocity"); break; case kHIDUsage_GD_Vno: sprintf (cstrName, "Vno"); break; case kHIDUsage_GD_SystemControl: sprintf (cstrName, "System Control"); break; case kHIDUsage_GD_SystemPowerDown: sprintf (cstrName, "System Power Down"); break; case kHIDUsage_GD_SystemSleep: sprintf (cstrName, "System Sleep"); break; case kHIDUsage_GD_SystemWakeUp: sprintf (cstrName, "System Wake Up"); break; case kHIDUsage_GD_SystemContextMenu: sprintf (cstrName, "System Context Menu"); break; case kHIDUsage_GD_SystemMainMenu: sprintf (cstrName, "System Main Menu"); break; case kHIDUsage_GD_SystemAppMenu: sprintf (cstrName, "System App Menu"); break; case kHIDUsage_GD_SystemMenuHelp: sprintf (cstrName, "System Menu Help"); break; case kHIDUsage_GD_SystemMenuExit: sprintf (cstrName, "System Menu Exit"); break; case kHIDUsage_GD_SystemMenu: sprintf (cstrName, "System Menu"); break; case kHIDUsage_GD_SystemMenuRight: sprintf (cstrName, "System Menu Right"); break; case kHIDUsage_GD_SystemMenuLeft: sprintf (cstrName, "System Menu Left"); break; case kHIDUsage_GD_SystemMenuUp: sprintf (cstrName, "System Menu Up"); break; case kHIDUsage_GD_SystemMenuDown: sprintf (cstrName, "System Menu Down"); break; case kHIDUsage_GD_DPadUp: sprintf (cstrName, "DPad Up"); break; case kHIDUsage_GD_DPadDown: sprintf (cstrName, "DPad Down"); break; case kHIDUsage_GD_DPadRight: sprintf (cstrName, "DPad Right"); break; case kHIDUsage_GD_DPadLeft: sprintf (cstrName, "DPad Left"); break; case kHIDUsage_GD_Reserved: sprintf (cstrName, "Reserved"); break; default: sprintf (cstrName, "Generic Desktop Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Simulation: switch (valueUsage) { default: sprintf (cstrName, "Simulation Usage 0x%lx", valueUsage); break; } break; case kHIDPage_VR: switch (valueUsage) { default: sprintf (cstrName, "VR Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Sport: switch (valueUsage) { default: sprintf (cstrName, "Sport Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Game: switch (valueUsage) { default: sprintf (cstrName, "Game Usage 0x%lx", valueUsage); break; } break; case kHIDPage_KeyboardOrKeypad: switch (valueUsage) { default: sprintf (cstrName, "Keyboard Usage 0x%lx", valueUsage); break; } break; case kHIDPage_LEDs: switch (valueUsage) { // some LED usages case kHIDUsage_LED_IndicatorRed: sprintf (cstrName, "Red LED"); break; case kHIDUsage_LED_IndicatorGreen: sprintf (cstrName, "Green LED"); break; case kHIDUsage_LED_IndicatorAmber: sprintf (cstrName, "Amber LED"); break; case kHIDUsage_LED_GenericIndicator: sprintf (cstrName, "Generic LED"); break; case kHIDUsage_LED_SystemSuspend: sprintf (cstrName, "System Suspend LED"); break; case kHIDUsage_LED_ExternalPowerConnected: sprintf (cstrName, "External Power LED"); break; default: sprintf (cstrName, "LED Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Button: switch (valueUsage) { default: sprintf (cstrName, "Button #%ld", valueUsage); break; } break; case kHIDPage_Ordinal: switch (valueUsage) { default: sprintf (cstrName, "Ordinal Instance %lx", valueUsage); break; } break; case kHIDPage_Telephony: switch (valueUsage) { default: sprintf (cstrName, "Telephony Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Consumer: switch (valueUsage) { default: sprintf (cstrName, "Consumer Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Digitizer: switch (valueUsage) { default: sprintf (cstrName, "Digitizer Usage 0x%lx", valueUsage); break; } break; case kHIDPage_PID: if (((valueUsage >= 0x02) && (valueUsage <= 0x1F)) || ((valueUsage >= 0x29) && (valueUsage <= 0x2F)) || ((valueUsage >= 0x35) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x44) && (valueUsage <= 0x4F)) || (valueUsage == 0x8A) || (valueUsage == 0x93) || ((valueUsage >= 0x9D) && (valueUsage <= 0x9E)) || ((valueUsage >= 0xA1) && (valueUsage <= 0xA3)) || ((valueUsage >= 0xAD) && (valueUsage <= 0xFFFF))) sprintf (cstrName, "PID Reserved"); else switch (valueUsage) { case 0x00: sprintf (cstrName, "PID Undefined Usage"); break; case kHIDUsage_PID_PhysicalInterfaceDevice: sprintf (cstrName, "Physical Interface Device"); break; case kHIDUsage_PID_Normal: sprintf (cstrName, "Normal Force"); break; case kHIDUsage_PID_SetEffectReport: sprintf (cstrName, "Set Effect Report"); break; case kHIDUsage_PID_EffectBlockIndex: sprintf (cstrName, "Effect Block Index"); break; case kHIDUsage_PID_ParamBlockOffset: sprintf (cstrName, "Parameter Block Offset"); break; case kHIDUsage_PID_ROM_Flag: sprintf (cstrName, "ROM Flag"); break; case kHIDUsage_PID_EffectType: sprintf (cstrName, "Effect Type"); break; case kHIDUsage_PID_ET_ConstantForce: sprintf (cstrName, "Effect Type Constant Force"); break; case kHIDUsage_PID_ET_Ramp: sprintf (cstrName, "Effect Type Ramp"); break; case kHIDUsage_PID_ET_CustomForceData: sprintf (cstrName, "Effect Type Custom Force Data"); break; case kHIDUsage_PID_ET_Square: sprintf (cstrName, "Effect Type Square"); break; case kHIDUsage_PID_ET_Sine: sprintf (cstrName, "Effect Type Sine"); break; case kHIDUsage_PID_ET_Triangle: sprintf (cstrName, "Effect Type Triangle"); break; case kHIDUsage_PID_ET_SawtoothUp: sprintf (cstrName, "Effect Type Sawtooth Up"); break; case kHIDUsage_PID_ET_SawtoothDown: sprintf (cstrName, "Effect Type Sawtooth Down"); break; case kHIDUsage_PID_ET_Spring: sprintf (cstrName, "Effect Type Spring"); break; case kHIDUsage_PID_ET_Damper: sprintf (cstrName, "Effect Type Damper"); break; case kHIDUsage_PID_ET_Inertia: sprintf (cstrName, "Effect Type Inertia"); break; case kHIDUsage_PID_ET_Friction: sprintf (cstrName, "Effect Type Friction"); break; case kHIDUsage_PID_Duration: sprintf (cstrName, "Effect Duration"); break; case kHIDUsage_PID_SamplePeriod: sprintf (cstrName, "Effect Sample Period"); break; case kHIDUsage_PID_Gain: sprintf (cstrName, "Effect Gain"); break; case kHIDUsage_PID_TriggerButton: sprintf (cstrName, "Effect Trigger Button"); break; case kHIDUsage_PID_TriggerRepeatInterval: sprintf (cstrName, "Effect Trigger Repeat Interval"); break; case kHIDUsage_PID_AxesEnable: sprintf (cstrName, "Axis Enable"); break; case kHIDUsage_PID_DirectionEnable: sprintf (cstrName, "Direction Enable"); break; case kHIDUsage_PID_Direction: sprintf (cstrName, "Direction"); break; case kHIDUsage_PID_TypeSpecificBlockOffset: sprintf (cstrName, "Type Specific Block Offset"); break; case kHIDUsage_PID_BlockType: sprintf (cstrName, "Block Type"); break; case kHIDUsage_PID_SetEnvelopeReport: sprintf (cstrName, "Set Envelope Report"); break; case kHIDUsage_PID_AttackLevel: sprintf (cstrName, "Envelope Attack Level"); break; case kHIDUsage_PID_AttackTime: sprintf (cstrName, "Envelope Attack Time"); break; case kHIDUsage_PID_FadeLevel: sprintf (cstrName, "Envelope Fade Level"); break; case kHIDUsage_PID_FadeTime: sprintf (cstrName, "Envelope Fade Time"); break; case kHIDUsage_PID_SetConditionReport: sprintf (cstrName, "Set Condition Report"); break; case kHIDUsage_PID_CP_Offset: sprintf (cstrName, "Condition CP Offset"); break; case kHIDUsage_PID_PositiveCoefficient: sprintf (cstrName, "Condition Positive Coefficient"); break; case kHIDUsage_PID_NegativeCoefficient: sprintf (cstrName, "Condition Negative Coefficient"); break; case kHIDUsage_PID_PositiveSaturation: sprintf (cstrName, "Condition Positive Saturation"); break; case kHIDUsage_PID_NegativeSaturation: sprintf (cstrName, "Condition Negative Saturation"); break; case kHIDUsage_PID_DeadBand: sprintf (cstrName, "Condition Dead Band"); break; case kHIDUsage_PID_DownloadForceSample: sprintf (cstrName, "Download Force Sample"); break; case kHIDUsage_PID_IsochCustomForceEnable: sprintf (cstrName, "Isoch Custom Force Enable"); break; case kHIDUsage_PID_CustomForceDataReport: sprintf (cstrName, "Custom Force Data Report"); break; case kHIDUsage_PID_CustomForceData: sprintf (cstrName, "Custom Force Data"); break; case kHIDUsage_PID_CustomForceVendorDefinedData: sprintf (cstrName, "Custom Force Vendor Defined Data"); break; case kHIDUsage_PID_SetCustomForceReport: sprintf (cstrName, "Set Custom Force Report"); break; case kHIDUsage_PID_CustomForceDataOffset: sprintf (cstrName, "Custom Force Data Offset"); break; case kHIDUsage_PID_SampleCount: sprintf (cstrName, "Custom Force Sample Count"); break; case kHIDUsage_PID_SetPeriodicReport: sprintf (cstrName, "Set Periodic Report"); break; case kHIDUsage_PID_Offset: sprintf (cstrName, "Periodic Offset"); break; case kHIDUsage_PID_Magnitude: sprintf (cstrName, "Periodic Magnitude"); break; case kHIDUsage_PID_Phase: sprintf (cstrName, "Periodic Phase"); break; case kHIDUsage_PID_Period: sprintf (cstrName, "Periodic Period"); break; case kHIDUsage_PID_SetConstantForceReport: sprintf (cstrName, "Set Constant Force Report"); break; case kHIDUsage_PID_SetRampForceReport: sprintf (cstrName, "Set Ramp Force Report"); break; case kHIDUsage_PID_RampStart: sprintf (cstrName, "Ramp Start"); break; case kHIDUsage_PID_RampEnd: sprintf (cstrName, "Ramp End"); break; case kHIDUsage_PID_EffectOperationReport: sprintf (cstrName, "Effect Operation Report"); break; case kHIDUsage_PID_EffectOperation: sprintf (cstrName, "Effect Operation"); break; case kHIDUsage_PID_OpEffectStart: sprintf (cstrName, "Op Effect Start"); break; case kHIDUsage_PID_OpEffectStartSolo: sprintf (cstrName, "Op Effect Start Solo"); break; case kHIDUsage_PID_OpEffectStop: sprintf (cstrName, "Op Effect Stop"); break; case kHIDUsage_PID_LoopCount: sprintf (cstrName, "Op Effect Loop Count"); break; case kHIDUsage_PID_DeviceGainReport: sprintf (cstrName, "Device Gain Report"); break; case kHIDUsage_PID_DeviceGain: sprintf (cstrName, "Device Gain"); break; case kHIDUsage_PID_PoolReport: sprintf (cstrName, "PID Pool Report"); break; case kHIDUsage_PID_RAM_PoolSize: sprintf (cstrName, "RAM Pool Size"); break; case kHIDUsage_PID_ROM_PoolSize: sprintf (cstrName, "ROM Pool Size"); break; case kHIDUsage_PID_ROM_EffectBlockCount: sprintf (cstrName, "ROM Effect Block Count"); break; case kHIDUsage_PID_SimultaneousEffectsMax: sprintf (cstrName, "Simultaneous Effects Max"); break; case kHIDUsage_PID_PoolAlignment: sprintf (cstrName, "Pool Alignment"); break; case kHIDUsage_PID_PoolMoveReport: sprintf (cstrName, "PID Pool Move Report"); break; case kHIDUsage_PID_MoveSource: sprintf (cstrName, "Move Source"); break; case kHIDUsage_PID_MoveDestination: sprintf (cstrName, "Move Destination"); break; case kHIDUsage_PID_MoveLength: sprintf (cstrName, "Move Length"); break; case kHIDUsage_PID_BlockLoadReport: sprintf (cstrName, "PID Block Load Report"); break; case kHIDUsage_PID_BlockLoadStatus: sprintf (cstrName, "Block Load Status"); break; case kHIDUsage_PID_BlockLoadSuccess: sprintf (cstrName, "Block Load Success"); break; case kHIDUsage_PID_BlockLoadFull: sprintf (cstrName, "Block Load Full"); break; case kHIDUsage_PID_BlockLoadError: sprintf (cstrName, "Block Load Error"); break; case kHIDUsage_PID_BlockHandle: sprintf (cstrName, "Block Handle"); break; case kHIDUsage_PID_BlockFreeReport: sprintf (cstrName, "PID Block Free Report"); break; case kHIDUsage_PID_TypeSpecificBlockHandle: sprintf (cstrName, "Type Specific Block Handle"); break; case kHIDUsage_PID_StateReport: sprintf (cstrName, "PID State Report"); break; case kHIDUsage_PID_EffectPlaying: sprintf (cstrName, "Effect Playing"); break; case kHIDUsage_PID_DeviceControlReport: sprintf (cstrName, "PID Device Control Report"); break; case kHIDUsage_PID_DeviceControl: sprintf (cstrName, "PID Device Control"); break; case kHIDUsage_PID_DC_EnableActuators: sprintf (cstrName, "Device Control Enable Actuators"); break; case kHIDUsage_PID_DC_DisableActuators: sprintf (cstrName, "Device Control Disable Actuators"); break; case kHIDUsage_PID_DC_StopAllEffects: sprintf (cstrName, "Device Control Stop All Effects"); break; case kHIDUsage_PID_DC_DeviceReset: sprintf (cstrName, "Device Control Reset"); break; case kHIDUsage_PID_DC_DevicePause: sprintf (cstrName, "Device Control Pause"); break; case kHIDUsage_PID_DC_DeviceContinue: sprintf (cstrName, "Device Control Continue"); break; case kHIDUsage_PID_DevicePaused: sprintf (cstrName, "Device Paused"); break; case kHIDUsage_PID_ActuatorsEnabled: sprintf (cstrName, "Actuators Enabled"); break; case kHIDUsage_PID_SafetySwitch: sprintf (cstrName, "Safety Switch"); break; case kHIDUsage_PID_ActuatorOverrideSwitch: sprintf (cstrName, "Actuator Override Switch"); break; case kHIDUsage_PID_ActuatorPower: sprintf (cstrName, "Actuator Power"); break; case kHIDUsage_PID_StartDelay: sprintf (cstrName, "Start Delay"); break; case kHIDUsage_PID_ParameterBlockSize: sprintf (cstrName, "Parameter Block Size"); break; case kHIDUsage_PID_DeviceManagedPool: sprintf (cstrName, "Device Managed Pool"); break; case kHIDUsage_PID_SharedParameterBlocks: sprintf (cstrName, "Shared Parameter Blocks"); break; case kHIDUsage_PID_CreateNewEffectReport: sprintf (cstrName, "Create New Effect Report"); break; case kHIDUsage_PID_RAM_PoolAvailable: sprintf (cstrName, "RAM Pool Available"); break; default: sprintf (cstrName, "PID Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Unicode: switch (valueUsage) { default: sprintf (cstrName, "Unicode Usage 0x%lx", valueUsage); break; } break; case kHIDPage_PowerDevice: if (((valueUsage >= 0x06) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x26) && (valueUsage <= 0x2F)) || ((valueUsage >= 0x39) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x48) && (valueUsage <= 0x4F)) || ((valueUsage >= 0x58) && (valueUsage <= 0x5F)) || (valueUsage == 0x6A) || ((valueUsage >= 0x74) && (valueUsage <= 0xFC))) sprintf (cstrName, "Power Device Reserved"); else switch (valueUsage) { case kHIDUsage_PD_Undefined: sprintf (cstrName, "Power Device Undefined Usage"); break; case kHIDUsage_PD_iName: sprintf (cstrName, "Power Device Name Index"); break; case kHIDUsage_PD_PresentStatus: sprintf (cstrName, "Power Device Present Status"); break; case kHIDUsage_PD_ChangedStatus: sprintf (cstrName, "Power Device Changed Status"); break; case kHIDUsage_PD_UPS: sprintf (cstrName, "Uninterruptible Power Supply"); break; case kHIDUsage_PD_PowerSupply: sprintf (cstrName, "Power Supply"); break; case kHIDUsage_PD_BatterySystem: sprintf (cstrName, "Battery System Power Module"); break; case kHIDUsage_PD_BatterySystemID: sprintf (cstrName, "Battery System ID"); break; case kHIDUsage_PD_Battery: sprintf (cstrName, "Battery"); break; case kHIDUsage_PD_BatteryID: sprintf (cstrName, "Battery ID"); break; case kHIDUsage_PD_Charger: sprintf (cstrName, "Charger"); break; case kHIDUsage_PD_ChargerID: sprintf (cstrName, "Charger ID"); break; case kHIDUsage_PD_PowerConverter: sprintf (cstrName, "Power Converter Power Module"); break; case kHIDUsage_PD_PowerConverterID: sprintf (cstrName, "Power Converter ID"); break; case kHIDUsage_PD_OutletSystem: sprintf (cstrName, "Outlet System power module"); break; case kHIDUsage_PD_OutletSystemID: sprintf (cstrName, "Outlet System ID"); break; case kHIDUsage_PD_Input: sprintf (cstrName, "Power Device Input"); break; case kHIDUsage_PD_InputID: sprintf (cstrName, "Power Device Input ID"); break; case kHIDUsage_PD_Output: sprintf (cstrName, "Power Device Output"); break; case kHIDUsage_PD_OutputID: sprintf (cstrName, "Power Device Output ID"); break; case kHIDUsage_PD_Flow: sprintf (cstrName, "Power Device Flow"); break; case kHIDUsage_PD_FlowID: sprintf (cstrName, "Power Device Flow ID"); break; case kHIDUsage_PD_Outlet: sprintf (cstrName, "Power Device Outlet"); break; case kHIDUsage_PD_OutletID: sprintf (cstrName, "Power Device Outlet ID"); break; case kHIDUsage_PD_Gang: sprintf (cstrName, "Power Device Gang"); break; case kHIDUsage_PD_GangID: sprintf (cstrName, "Power Device Gang ID"); break; case kHIDUsage_PD_PowerSummary: sprintf (cstrName, "Power Device Power Summary"); break; case kHIDUsage_PD_PowerSummaryID: sprintf (cstrName, "Power Device Power Summary ID"); break; case kHIDUsage_PD_Voltage: sprintf (cstrName, "Power Device Voltage"); break; case kHIDUsage_PD_Current: sprintf (cstrName, "Power Device Current"); break; case kHIDUsage_PD_Frequency: sprintf (cstrName, "Power Device Frequency"); break; case kHIDUsage_PD_ApparentPower: sprintf (cstrName, "Power Device Apparent Power"); break; case kHIDUsage_PD_ActivePower: sprintf (cstrName, "Power Device RMS Power"); break; case kHIDUsage_PD_PercentLoad: sprintf (cstrName, "Power Device Percent Load"); break; case kHIDUsage_PD_Temperature: sprintf (cstrName, "Power Device Temperature"); break; case kHIDUsage_PD_Humidity: sprintf (cstrName, "Power Device Humidity"); break; case kHIDUsage_PD_BadCount: sprintf (cstrName, "Power Device Bad Condition Count"); break; case kHIDUsage_PD_ConfigVoltage: sprintf (cstrName, "Power Device Nominal Voltage"); break; case kHIDUsage_PD_ConfigCurrent: sprintf (cstrName, "Power Device Nominal Current"); break; case kHIDUsage_PD_ConfigFrequency: sprintf (cstrName, "Power Device Nominal Frequency"); break; case kHIDUsage_PD_ConfigApparentPower: sprintf (cstrName, "Power Device Nominal Apparent Power"); break; case kHIDUsage_PD_ConfigActivePower: sprintf (cstrName, "Power Device Nominal RMS Power"); break; case kHIDUsage_PD_ConfigPercentLoad: sprintf (cstrName, "Power Device Nominal Percent Load"); break; case kHIDUsage_PD_ConfigTemperature: sprintf (cstrName, "Power Device Nominal Temperature"); break; case kHIDUsage_PD_ConfigHumidity: sprintf (cstrName, "Power Device Nominal Humidity"); break; case kHIDUsage_PD_SwitchOnControl: sprintf (cstrName, "Power Device Switch On Control"); break; case kHIDUsage_PD_SwitchOffControl: sprintf (cstrName, "Power Device Switch Off Control"); break; case kHIDUsage_PD_ToggleControl: sprintf (cstrName, "Power Device Toogle Sequence Control"); break; case kHIDUsage_PD_LowVoltageTransfer: sprintf (cstrName, "Power Device Min Transfer Voltage"); break; case kHIDUsage_PD_HighVoltageTransfer: sprintf (cstrName, "Power Device Max Transfer Voltage"); break; case kHIDUsage_PD_DelayBeforeReboot: sprintf (cstrName, "Power Device Delay Before Reboot"); break; case kHIDUsage_PD_DelayBeforeStartup: sprintf (cstrName, "Power Device Delay Before Startup"); break; case kHIDUsage_PD_DelayBeforeShutdown: sprintf (cstrName, "Power Device Delay Before Shutdown"); break; case kHIDUsage_PD_Test: sprintf (cstrName, "Power Device Test Request/Result"); break; case kHIDUsage_PD_ModuleReset: sprintf (cstrName, "Power Device Reset Request/Result"); break; case kHIDUsage_PD_AudibleAlarmControl: sprintf (cstrName, "Power Device Audible Alarm Control"); break; case kHIDUsage_PD_Present: sprintf (cstrName, "Power Device Present"); break; case kHIDUsage_PD_Good: sprintf (cstrName, "Power Device Good"); break; case kHIDUsage_PD_InternalFailure: sprintf (cstrName, "Power Device Internal Failure"); break; case kHIDUsage_PD_VoltageOutOfRange: sprintf (cstrName, "Power Device Voltage Out Of Range"); break; case kHIDUsage_PD_FrequencyOutOfRange: sprintf (cstrName, "Power Device Frequency Out Of Range"); break; case kHIDUsage_PD_Overload: sprintf (cstrName, "Power Device Overload"); break; case kHIDUsage_PD_OverCharged: sprintf (cstrName, "Power Device Over Charged"); break; case kHIDUsage_PD_OverTemperature: sprintf (cstrName, "Power Device Over Temperature"); break; case kHIDUsage_PD_ShutdownRequested: sprintf (cstrName, "Power Device Shutdown Requested"); break; case kHIDUsage_PD_ShutdownImminent: sprintf (cstrName, "Power Device Shutdown Imminent"); break; case kHIDUsage_PD_SwitchOnOff: sprintf (cstrName, "Power Device On/Off Switch Status"); break; case kHIDUsage_PD_Switchable: sprintf (cstrName, "Power Device Switchable"); break; case kHIDUsage_PD_Used: sprintf (cstrName, "Power Device Used"); break; case kHIDUsage_PD_Boost: sprintf (cstrName, "Power Device Boosted"); break; case kHIDUsage_PD_Buck: sprintf (cstrName, "Power Device Bucked"); break; case kHIDUsage_PD_Initialized: sprintf (cstrName, "Power Device Initialized"); break; case kHIDUsage_PD_Tested: sprintf (cstrName, "Power Device Tested"); break; case kHIDUsage_PD_AwaitingPower: sprintf (cstrName, "Power Device Awaiting Power"); break; case kHIDUsage_PD_CommunicationLost: sprintf (cstrName, "Power Device Communication Lost"); break; case kHIDUsage_PD_iManufacturer: sprintf (cstrName, "Power Device Manufacturer String Index"); break; case kHIDUsage_PD_iProduct: sprintf (cstrName, "Power Device Product String Index"); break; case kHIDUsage_PD_iserialNumber: sprintf (cstrName, "Power Device Serial Number String Index"); break; default: sprintf (cstrName, "Power Device Usage 0x%lx", valueUsage); break; } break; case kHIDPage_BatterySystem: if (((valueUsage >= 0x0A) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x1E) && (valueUsage <= 0x27)) || ((valueUsage >= 0x30) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x4C) && (valueUsage <= 0x5F)) || ((valueUsage >= 0x6C) && (valueUsage <= 0x7F)) || ((valueUsage >= 0x90) && (valueUsage <= 0xBF)) || ((valueUsage >= 0xC3) && (valueUsage <= 0xCF)) || ((valueUsage >= 0xDD) && (valueUsage <= 0xEF)) || ((valueUsage >= 0xF2) && (valueUsage <= 0xFF))) sprintf (cstrName, "Power Device Reserved"); else switch (valueUsage) { case kHIDUsage_BS_Undefined: sprintf (cstrName, "Battery System Undefined"); break; case kHIDUsage_BS_SMBBatteryMode: sprintf (cstrName, "SMB Mode"); break; case kHIDUsage_BS_SMBBatteryStatus: sprintf (cstrName, "SMB Status"); break; case kHIDUsage_BS_SMBAlarmWarning: sprintf (cstrName, "SMB Alarm Warning"); break; case kHIDUsage_BS_SMBChargerMode: sprintf (cstrName, "SMB Charger Mode"); break; case kHIDUsage_BS_SMBChargerStatus: sprintf (cstrName, "SMB Charger Status"); break; case kHIDUsage_BS_SMBChargerSpecInfo: sprintf (cstrName, "SMB Charger Extended Status"); break; case kHIDUsage_BS_SMBSelectorState: sprintf (cstrName, "SMB Selector State"); break; case kHIDUsage_BS_SMBSelectorPresets: sprintf (cstrName, "SMB Selector Presets"); break; case kHIDUsage_BS_SMBSelectorInfo: sprintf (cstrName, "SMB Selector Info"); break; case kHIDUsage_BS_OptionalMfgFunction1: sprintf (cstrName, "Battery System Optional SMB Mfg Function 1"); break; case kHIDUsage_BS_OptionalMfgFunction2: sprintf (cstrName, "Battery System Optional SMB Mfg Function 2"); break; case kHIDUsage_BS_OptionalMfgFunction3: sprintf (cstrName, "Battery System Optional SMB Mfg Function 3"); break; case kHIDUsage_BS_OptionalMfgFunction4: sprintf (cstrName, "Battery System Optional SMB Mfg Function 4"); break; case kHIDUsage_BS_OptionalMfgFunction5: sprintf (cstrName, "Battery System Optional SMB Mfg Function 5"); break; case kHIDUsage_BS_ConnectionToSMBus: sprintf (cstrName, "Battery System Connection To System Management Bus"); break; case kHIDUsage_BS_OutputConnection: sprintf (cstrName, "Battery System Output Connection Status"); break; case kHIDUsage_BS_ChargerConnection: sprintf (cstrName, "Battery System Charger Connection"); break; case kHIDUsage_BS_BatteryInsertion: sprintf (cstrName, "Battery System Battery Insertion"); break; case kHIDUsage_BS_Usenext: sprintf (cstrName, "Battery System Use Next"); break; case kHIDUsage_BS_OKToUse: sprintf (cstrName, "Battery System OK To Use"); break; case kHIDUsage_BS_BatterySupported: sprintf (cstrName, "Battery System Battery Supported"); break; case kHIDUsage_BS_SelectorRevision: sprintf (cstrName, "Battery System Selector Revision"); break; case kHIDUsage_BS_ChargingIndicator: sprintf (cstrName, "Battery System Charging Indicator"); break; case kHIDUsage_BS_ManufacturerAccess: sprintf (cstrName, "Battery System Manufacturer Access"); break; case kHIDUsage_BS_RemainingCapacityLimit: sprintf (cstrName, "Battery System Remaining Capacity Limit"); break; case kHIDUsage_BS_RemainingTimeLimit: sprintf (cstrName, "Battery System Remaining Time Limit"); break; case kHIDUsage_BS_AtRate: sprintf (cstrName, "Battery System At Rate..."); break; case kHIDUsage_BS_CapacityMode: sprintf (cstrName, "Battery System Capacity Mode"); break; case kHIDUsage_BS_BroadcastToCharger: sprintf (cstrName, "Battery System Broadcast To Charger"); break; case kHIDUsage_BS_PrimaryBattery: sprintf (cstrName, "Battery System Primary Battery"); break; case kHIDUsage_BS_ChargeController: sprintf (cstrName, "Battery System Charge Controller"); break; case kHIDUsage_BS_TerminateCharge: sprintf (cstrName, "Battery System Terminate Charge"); break; case kHIDUsage_BS_TerminateDischarge: sprintf (cstrName, "Battery System Terminate Discharge"); break; case kHIDUsage_BS_BelowRemainingCapacityLimit: sprintf (cstrName, "Battery System Below Remaining Capacity Limit"); break; case kHIDUsage_BS_RemainingTimeLimitExpired: sprintf (cstrName, "Battery System Remaining Time Limit Expired"); break; case kHIDUsage_BS_Charging: sprintf (cstrName, "Battery System Charging"); break; case kHIDUsage_BS_Discharging: sprintf (cstrName, "Battery System Discharging"); break; case kHIDUsage_BS_FullyCharged: sprintf (cstrName, "Battery System Fully Charged"); break; case kHIDUsage_BS_FullyDischarged: sprintf (cstrName, "Battery System Fully Discharged"); break; case kHIDUsage_BS_ConditioningFlag: sprintf (cstrName, "Battery System Conditioning Flag"); break; case kHIDUsage_BS_AtRateOK: sprintf (cstrName, "Battery System At Rate OK"); break; case kHIDUsage_BS_SMBErrorCode: sprintf (cstrName, "Battery System SMB Error Code"); break; case kHIDUsage_BS_NeedReplacement: sprintf (cstrName, "Battery System Need Replacement"); break; case kHIDUsage_BS_AtRateTimeToFull: sprintf (cstrName, "Battery System At Rate Time To Full"); break; case kHIDUsage_BS_AtRateTimeToEmpty: sprintf (cstrName, "Battery System At Rate Time To Empty"); break; case kHIDUsage_BS_AverageCurrent: sprintf (cstrName, "Battery System Average Current"); break; case kHIDUsage_BS_Maxerror: sprintf (cstrName, "Battery System Max Error"); break; case kHIDUsage_BS_RelativeStateOfCharge: sprintf (cstrName, "Battery System Relative State Of Charge"); break; case kHIDUsage_BS_AbsoluteStateOfCharge: sprintf (cstrName, "Battery System Absolute State Of Charge"); break; case kHIDUsage_BS_RemainingCapacity: sprintf (cstrName, "Battery System Remaining Capacity"); break; case kHIDUsage_BS_FullChargeCapacity: sprintf (cstrName, "Battery System Full Charge Capacity"); break; case kHIDUsage_BS_RunTimeToEmpty: sprintf (cstrName, "Battery System Run Time To Empty"); break; case kHIDUsage_BS_AverageTimeToEmpty: sprintf (cstrName, "Battery System Average Time To Empty"); break; case kHIDUsage_BS_AverageTimeToFull: sprintf (cstrName, "Battery System Average Time To Full"); break; case kHIDUsage_BS_CycleCount: sprintf (cstrName, "Battery System Cycle Count"); break; case kHIDUsage_BS_BattPackModelLevel: sprintf (cstrName, "Battery System Batt Pack Model Level"); break; case kHIDUsage_BS_InternalChargeController: sprintf (cstrName, "Battery System Internal Charge Controller"); break; case kHIDUsage_BS_PrimaryBatterySupport: sprintf (cstrName, "Battery System Primary Battery Support"); break; case kHIDUsage_BS_DesignCapacity: sprintf (cstrName, "Battery System Design Capacity"); break; case kHIDUsage_BS_SpecificationInfo: sprintf (cstrName, "Battery System Specification Info"); break; case kHIDUsage_BS_ManufacturerDate: sprintf (cstrName, "Battery System Manufacturer Date"); break; case kHIDUsage_BS_SerialNumber: sprintf (cstrName, "Battery System Serial Number"); break; case kHIDUsage_BS_iManufacturerName: sprintf (cstrName, "Battery System Manufacturer Name Index"); break; case kHIDUsage_BS_iDevicename: sprintf (cstrName, "Battery System Device Name Index"); break; case kHIDUsage_BS_iDeviceChemistry: sprintf (cstrName, "Battery System Device Chemistry Index"); break; case kHIDUsage_BS_ManufacturerData: sprintf (cstrName, "Battery System Manufacturer Data"); break; case kHIDUsage_BS_Rechargable: sprintf (cstrName, "Battery System Rechargable"); break; case kHIDUsage_BS_WarningCapacityLimit: sprintf (cstrName, "Battery System Warning Capacity Limit"); break; case kHIDUsage_BS_CapacityGranularity1: sprintf (cstrName, "Battery System Capacity Granularity 1"); break; case kHIDUsage_BS_CapacityGranularity2: sprintf (cstrName, "Battery System Capacity Granularity 2"); break; case kHIDUsage_BS_iOEMInformation: sprintf (cstrName, "Battery System OEM Information Index"); break; case kHIDUsage_BS_InhibitCharge: sprintf (cstrName, "Battery System Inhibit Charge"); break; case kHIDUsage_BS_EnablePolling: sprintf (cstrName, "Battery System Enable Polling"); break; case kHIDUsage_BS_ResetToZero: sprintf (cstrName, "Battery System Reset To Zero"); break; case kHIDUsage_BS_ACPresent: sprintf (cstrName, "Battery System AC Present"); break; case kHIDUsage_BS_BatteryPresent: sprintf (cstrName, "Battery System Battery Present"); break; case kHIDUsage_BS_PowerFail: sprintf (cstrName, "Battery System Power Fail"); break; case kHIDUsage_BS_AlarmInhibited: sprintf (cstrName, "Battery System Alarm Inhibited"); break; case kHIDUsage_BS_ThermistorUnderRange: sprintf (cstrName, "Battery System Thermistor Under Range"); break; case kHIDUsage_BS_ThermistorHot: sprintf (cstrName, "Battery System Thermistor Hot"); break; case kHIDUsage_BS_ThermistorCold: sprintf (cstrName, "Battery System Thermistor Cold"); break; case kHIDUsage_BS_ThermistorOverRange: sprintf (cstrName, "Battery System Thermistor Over Range"); break; case kHIDUsage_BS_VoltageOutOfRange: sprintf (cstrName, "Battery System Voltage Out Of Range"); break; case kHIDUsage_BS_CurrentOutOfRange: sprintf (cstrName, "Battery System Current Out Of Range"); break; case kHIDUsage_BS_CurrentNotRegulated: sprintf (cstrName, "Battery System Current Not Regulated"); break; case kHIDUsage_BS_VoltageNotRegulated: sprintf (cstrName, "Battery System Voltage Not Regulated"); break; case kHIDUsage_BS_MasterMode: sprintf (cstrName, "Battery System Master Mode"); break; case kHIDUsage_BS_ChargerSelectorSupport: sprintf (cstrName, "Battery System Charger Support Selector"); break; case kHIDUsage_BS_ChargerSpec: sprintf (cstrName, "attery System Charger Specification"); break; case kHIDUsage_BS_Level2: sprintf (cstrName, "Battery System Charger Level 2"); break; case kHIDUsage_BS_Level3: sprintf (cstrName, "Battery System Charger Level 3"); break; default: sprintf (cstrName, "Battery System Usage 0x%lx", valueUsage); break; } break; case kHIDPage_AlphanumericDisplay: switch (valueUsage) { default: sprintf (cstrName, "Alphanumeric Display Usage 0x%lx", valueUsage); break; } break; case kHIDPage_BarCodeScanner: switch (valueUsage) { default: sprintf (cstrName, "Bar Code Scanner Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Scale: switch (valueUsage) { default: sprintf (cstrName, "Scale Usage 0x%lx", valueUsage); break; } break; case kHIDPage_CameraControl: switch (valueUsage) { default: sprintf (cstrName, "Camera Control Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Arcade: switch (valueUsage) { default: sprintf (cstrName, "Arcade Usage 0x%lx", valueUsage); break; } break; default: if (valueUsagePage > kHIDPage_VendorDefinedStart) sprintf (cstrName, "Vendor Defined Usage 0x%lx", valueUsage); else sprintf (cstrName, "Page: 0x%lx, Usage: 0x%lx", valueUsagePage, valueUsage); break; } } // --------------------------------- // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement) { if (NULL != pElement) { float deviceScale = pElement->max - pElement->min; float readScale = pElement->calMax - pElement->calMin; if (readScale == 0) return value; // no scaling as else return ((value - pElement->calMin) * deviceScale / readScale) + pElement->min; } else return 0; // bad element passed in } // --------------------------------- // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values SInt32 HIDScaleValue (SInt32 value, pRecElement pElement) { float deviceScale = pElement->userMax - pElement->userMin; float readScale = pElement->max - pElement->min; if (readScale == 0) return value; else return (value - pElement->min) * deviceScale / readScale + pElement->userMin; } // --------------------------------- // convert an element type to a mask HIDElementTypeMask HIDConvertElementTypeToMask (const long type) { HIDElementTypeMask result = kHIDElementTypeAll; switch (type) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: result = kHIDElementTypeInput; break; case kIOHIDElementTypeOutput: result = kHIDElementTypeOutput; break; case kIOHIDElementTypeFeature: result = kHIDElementTypeFeature; break; case kIOHIDElementTypeCollection: result = kHIDElementTypeCollection; break; default: result = kHIDElementTypeAll; break; } return result; } Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice) { pRecDevice pDevice, pBestDevice = NULL; long bestScore = 0; // iterate over all devices pDevice = HIDGetFirstDevice(); while (pDevice) { long deviceScore = 1; if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) { deviceScore += 10; if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) deviceScore += 8; } if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) deviceScore += 9; if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) deviceScore += 5; if (deviceScore > bestScore) { pBestDevice = pDevice; bestScore = deviceScore; #if 0 // set true to output scoring informaton printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pDevice = HIDGetNextDevice(pDevice); } if (NULL != pBestDevice) { *ppFoundDevice = pBestDevice; #if 0 // set true to output scoring informaton printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); #endif return true; } else return false; } // --------------------------------- // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement) { pRecDevice pDevice, pBestDevice = NULL; pRecElement pElement, pBestElement = NULL; HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); long bestScore = 0; // iterate over all devices pDevice = HIDGetFirstDevice(); while (pDevice) { long deviceScore = 1; if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) { deviceScore += 10; if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) deviceScore += 8; } if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) deviceScore += 9; if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) deviceScore += 5; // iterate over all elements of this device pElement = HIDGetFirstDeviceElement(pDevice, hidMask); while (pElement) { long score = deviceScore; if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) { score += 5; if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) score += 4; } else score = 0; #if 0 // set true to output scoring informaton if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here { printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pElement); } #endif if (score > bestScore) { pBestDevice = pDevice; pBestElement = pElement; bestScore = score; #if 0 // set true to output scoring informaton printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pElement = HIDGetNextDeviceElement(pElement, hidMask); } pDevice = HIDGetNextDevice(pDevice); } if ((NULL != pBestDevice) || (NULL != pBestElement)) { *ppFoundDevice = pBestDevice; *ppFoundElement = pBestElement; #if 0 // set true to output scoring informaton printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); #endif return true; } else return false; } // --------------------------------- // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement) { pRecElement pElement, pBestElement = NULL; HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); long bestScore = 0; if ((NULL == pStartElement) || (NULL == pSearchElement) || (NULL == ppFoundElement)) return false; // iterate over all children of this element pElement = pStartElement->pChild; while (pElement) { long score = 0; #if 0 // set true to output searching informaton printf("\n-HIDFindSubElement, search = {t:%.2lX, u:%.4lX:%.4lX}, match = {t:%.2lX, u:%.4lX:%.4lX, s:\"%s\"}", pSearchElement->type, pSearchElement->usagePage, pSearchElement->usage, pElement->type, pElement->usagePage, pElement->usage, pElement->name); fflush(stdout); #endif if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) { score += 4; if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) score += 5; } #if 0 // set true to output searching informaton if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here { printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pElement); } #endif if (score > bestScore) { pBestElement = pElement; bestScore = score; #if 0 // set true to output searching informaton printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pElement = HIDGetNextDeviceElement(pElement, hidMask); } #if 0 // set true to output searching informaton if (pBestElement) { printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); } #endif *ppFoundElement = pBestElement; return (NULL != pBestElement); } // print out all of an elements information int HIDPrintElement(const pRecElement pElement) { int results; int count; printf("\n"); if (gDepth != pElement->depth) printf("%d",gDepth); for (count = 0;count < pElement->depth;count++) printf(" | "); #if 0 // this is verbose results = printf("-HIDPrintElement = {name: \"%s\", t: 0x%.2lX, u:%ld:%ld, c: %ld, min/max: %ld/%ld, scaled: %ld/%ld, size: %ld, rel: %s, wrap: %s, nonLinear: %s, preferred: %s, nullState: %s, units: %ld, exp: %ld, cal: %ld/%ld, user: %ld/%ld, depth: %ld}.", pElement->name, // name of element (c string) pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change pElement->min, // reported min value possible pElement->max, // reported max value possible pElement->scaledMin, // reported scaled min value possible pElement->scaledMax, // reported scaled max value possible pElement->size, // size in bits of data return from element pElement->relative ? "YES" : "NO", // are reports relative to last report (deltas) pElement->wrapping ? "YES" : "NO", // does element wrap around (one value higher than max is min) pElement->nonLinear ? "YES" : "NO", // are the values reported non-linear relative to element movement pElement->preferredState ? "YES" : "NO",// does element have a preferred state (such as a button) pElement->nullState ? "YES" : "NO", // does element have null state pElement->units, // units value is reported in (not used very often) pElement->unitExp, // exponent for units (also not used very often) pElement->calMin, // min returned value (for calibrate call) pElement->calMax, // max returned value pElement->userMin, // user set min to scale to (for scale call) pElement->userMax, // user set max pElement->depth ); #else // this is brief results = printf("-HIDPrintElement = {t: 0x%lX, u:%ld:%ld, c: %ld, name: \"%s\", d: %ld}.", pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change pElement->name, // name of element (c string) pElement->depth ); #endif fflush(stdout); return results; } // return true if this is a valid device pointer Boolean HIDIsValidDevice(const pRecDevice pSearchDevice) { pRecDevice pDevice = gpDeviceList; while (pDevice) { if (pDevice == pSearchDevice) return true; pDevice = pDevice->pNext; } return false; } // return true if this is a valid element pointer for this device Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement) { if (HIDIsValidDevice(pSearchDevice)) { pRecElement pRecElementTemp = HIDGetFirstDeviceElement(pSearchDevice,kHIDElementTypeAll); while (pRecElementTemp) { if (pRecElementTemp == pSearchElement) return true; pRecElementTemp = HIDGetNextDeviceElement(pRecElementTemp,kHIDElementTypeAll); } } return false; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Utilities.h ================================================ /* File: HID_Utilities.h Contains: External interface for HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_h_ #define _HID_Utilities_h_ #include #include // 10.0.x //#include // 10.1.x #include #include // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== enum { kDefaultUserMin = 0, // default user min and max used for scaling kDefaultUserMax = 255, }; typedef enum HIDElementTypeMask { kHIDElementTypeInput = 1 << 1, kHIDElementTypeOutput = 1 << 2, kHIDElementTypeFeature = 1 << 3, kHIDElementTypeCollection = 1 << 4, kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection }HIDElementTypeMask; struct recElement { IOHIDElementType type; // the type defined by IOHIDElementType in IOHIDKeys.h long usagePage; // usage page from IOUSBHIDParser.h which defines general usage long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage IOHIDElementCookie cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change long min; // reported min value possible long max; // reported max value possible long scaledMin; // reported scaled min value possible long scaledMax; // reported scaled max value possible long size; // size in bits of data return from element Boolean relative; // are reports relative to last report (deltas) Boolean wrapping; // does element wrap around (one value higher than max is min) Boolean nonLinear; // are the values reported non-linear relative to element movement Boolean preferredState; // does element have a preferred state (such as a button) Boolean nullState; // does element have null state long units; // units value is reported in (not used very often) long unitExp; // exponent for units (also not used very often) Str255 name; // name of element (not used often) // runtime variables long minReport; // min returned value long maxReport; // max returned value (calibrate call) long userMin; // user set value to scale to (scale call) long userMax; struct recElement * pPrevious; // previous element (NULL at list head) struct recElement * pChild; // next child (only of collections) struct recElement * pSibling; // next sibling (for elements and collections) }; typedef struct recElement recElement; typedef recElement* pRecElement; struct recDevice { IOHIDDeviceInterface ** interface; // interface to device, NULL = no interface IOHIDQueueInterface ** queue; // device queue, NULL = no queue CFRunLoopSourceRef queueRunLoopSource; // device queue run loop source, NULL == no source IOHIDOutputTransactionInterface ** transaction; // output transaction interface, NULL == no transaction io_object_t notification; // notifications Str255 transport; // device transport long vendorID; // id for device vendor, unique across all devices long productID; // id for particular product, unique across all of a vendors devices long version; // version of product Str255 manufacturer; // name of manufacturer Str255 product; // name of product Str255 serial; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine long usage; // usage page from IOUSBHID Parser.h which defines general usage long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) long features; // number of elements of type kIOHIDElementTypeFeature long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes long outputs; // number of elements of type kIOHIDElementTypeOutput long collections; // number of elements of type kIOHIDElementTypeCollection long axis; // number of axis (calculated, not reported by device) long buttons; // number of buttons (calculated, not reported by device) long hats; // number of hat switches (calculated, not reported by device) long sliders; // number of sliders (calculated, not reported by device) long dials; // number of dials (calculated, not reported by device) long wheels; // number of wheels (calculated, not reported by device) recElement* pListElements; // head of linked list of elements struct recDevice* pNext; // next device }; typedef struct recDevice recDevice; typedef recDevice* pRecDevice; // ================================== // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting extern IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, pRecDevice pDevice); // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, butnot user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain extern void HIDReleaseDeviceList (void); // does a device list exist extern Boolean HIDHaveDeviceList (void); // how many HID devices have been found // returns 0 if no device list exist extern UInt32 HIDCountDevices (void); // how many elements does a specific device have // returns 0 if device is invalid or NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); // get the first device in the device list // returns NULL if no list exists extern pRecDevice HIDGetFirstDevice (void); // get next device in list given current device as parameter // returns NULL if end of list extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns empty string for invlid types extern void HIDGetTypeName (IOHIDElementType type, char * cstrName); // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); // --------------------------------- // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); #ifdef __cplusplus } #endif #endif // _HID_Utilities_h_ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Utilities_External.h ================================================ /* File: HID_Utilities_External.h Contains: Definition of the HID Utilities exported functions DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_External_h_ #define _HID_Utilities_External_h_ // ================================== //includes #if TARGET_RT_MAC_CFM typedef void (*IOHIDCallbackFunction)(void * target, unsigned long result, void* refcon, void * sender); #else #include #endif TARGET_RT_MAC_CFM #include #if 0 #include #include "PID.h" // NOTE: These are now in #include "IOHIDPowerUsage.h" // NOTE: These are now in #endif // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== // Device and Element Interfaces typedef enum HIDElementTypeMask { kHIDElementTypeInput = 1 << 1, kHIDElementTypeOutput = 1 << 2, kHIDElementTypeFeature = 1 << 3, kHIDElementTypeCollection = 1 << 4, kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection }HIDElementTypeMask; struct recElement { unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h long usagePage; // usage page from IOUSBHIDParser.h which defines general usage long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change long min; // reported min value possible long max; // reported max value possible long scaledMin; // reported scaled min value possible long scaledMax; // reported scaled max value possible long size; // size in bits of data return from element unsigned char relative; // are reports relative to last report (deltas) unsigned char wrapping; // does element wrap around (one value higher than max is min) unsigned char nonLinear; // are the values reported non-linear relative to element movement unsigned char preferredState; // does element have a preferred state (such as a button) unsigned char nullState; // does element have null state long units; // units value is reported in (not used very often) long unitExp; // exponent for units (also not used very often) char name[256]; // name of element (c string) // runtime variables long calMin; // min returned value long calMax; // max returned value (calibrate call) long userMin; // user set value to scale to (scale call) long userMax; struct recElement * pPrevious; // previous element (NULL at list head) struct recElement * pChild; // next child (only of collections) struct recElement * pSibling; // next sibling (for elements and collections) long depth; }; typedef struct recElement recElement; typedef recElement* pRecElement; struct recDevice { void * interface; // interface to device, NULL = no interface void * queue; // device queue, NULL = no queue void * queueRunLoopSource; // device queue run loop source, NULL == no source void * transaction; // output transaction interface, NULL == no interface void * notification; // notifications char transport[256]; // device transport (c string) long vendorID; // id for device vendor, unique across all devices long productID; // id for particular product, unique across all of a vendors devices long version; // version of product char manufacturer[256]; // name of manufacturer char product[256]; // name of product char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine long usage; // usage page from IOUSBHID Parser.h which defines general usage long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) long features; // number of elements of type kIOHIDElementTypeFeature long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes long outputs; // number of elements of type kIOHIDElementTypeOutput long collections; // number of elements of type kIOHIDElementTypeCollection long axis; // number of axis (calculated, not reported by device) long buttons; // number of buttons (calculated, not reported by device) long hats; // number of hat switches (calculated, not reported by device) long sliders; // number of sliders (calculated, not reported by device) long dials; // number of dials (calculated, not reported by device) long wheels; // number of wheels (calculated, not reported by device) recElement* pListElements; // head of linked list of elements struct recDevice* pNext; // next device }; typedef struct recDevice recDevice; typedef recDevice* pRecDevice; // ================================== // HID Utilities interface // ================================== // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting extern unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice); // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, butnot user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain extern void HIDReleaseDeviceList (void); // does a device list exist extern Boolean HIDHaveDeviceList (void); // how many HID devices have been found // returns 0 if no device list exist extern UInt32 HIDCountDevices (void); // how many elements does a specific device have // returns 0 if device is invalid or NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); // get the first device in the device list // returns NULL if no list exists extern pRecDevice HIDGetFirstDevice (void); // get next device in list given current device as parameter // returns NULL if end of list extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns empty string for invlid types extern void HIDGetTypeName (IOHIDElementType theType, char * cstrName); // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); // --------------------------------- // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); // ================================== // Element Event Queue and Value Interfaces enum { kDefaultUserMin = 0, // default user min and max used for scaling kDefaultUserMax = 255 }; enum { kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate of // if states change quickly (updates are only posted on state changes) }; // ================================== // queues specific element, performing any device queue set up required extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); // adds all elements to queue, performing any device queue set up required extern unsigned long HIDQueueDevice (pRecDevice pDevice); // removes element for queue, if last element in queue will release queue and device extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); // completely removes all elements from queue and releases queue and device extern unsigned long HIDDequeueDevice (pRecDevice pDevice); // releases all device queues for quit or rebuild (must be called) extern unsigned long HIDReleaseAllDeviceQueues (void); // releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); // returns current value for element, creating device interface as required, polling element extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); // Set an elements value // NOTE: This should only be used when a single element report needs to be sent. // If multiple elements reports are to be send then transactions should be used. // pIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent); // Set a callback to be called when a queue goes from empty to non-empty extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); #if 0 // Get a report from a device extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize); // Send a report to a device extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize); #endif // ================================== // HUD utilities interfaces // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern long HIDCalibrateValue (long value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern long HIDScaleValue (long value, pRecElement pElement); // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); // ================================== // Name Lookup Interfaces // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // ================================== // Conguration and Save Interfaces enum { kPercentMove = 10 // precent of overall range a element must move to register }; typedef struct recSaveHID { long actionCookie; // device // need to add serial number when I have a test case long vendorID; long productID; long locID; long usage; long usagePage; // elements long usagePageE; long usageE; void * cookie; }recSaveHID,*pRecSaveHID; // polls all devices and elements for a change greater than kPercentMove. Times out after given time // returns true and pointer to device and element if found // returns false and NULL for both parameters if not found extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout); // take input records, save required info // assume file is open and at correct position. extern void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie); // take file, read one record (assume file position is correct and file is open) // search for matching device // return pDevice, pElement and cookie for action extern long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement); // Save the device & element values into the specified key in the specified applications preferences extern Boolean HIDSaveElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement); // Find the specified preference in the specified application // search for matching device and element // return pDevice, pElement that matches extern Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement); // ================================== // Output Transaction interface // Create and open an transaction interface to device, required prior to extracting values or building Transactions extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement); // removes an element from a Transaction extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement); // return true if this transaction contains this element extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement); /* This changes the default value of an element, when the values of the */ /* elements are cleared, on clear or commit, they are reset to the */ /* default value */ /* This call can be made on elements that are not in the transaction, but */ /* has undefined behavior if made on elements not in the transaction */ /* which are later added to the transaction. */ /* In other words, an element should be added before its default is */ /* set, for well defined behavior. */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Get the current setting of an element's default value */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Add a change to the transaction, by setting an element value */ /* The change is not actually made until it is commited */ /* The element must be part of the transaction or this call will fail */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Get the current setting of an element value */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Commit the transaction, or clear all the changes and start over */ /* timoutMS is the timeout in milliseconds, a zero timeout will cause */ /* this call to be non-blocking (returning queue empty) if there */ /* is a NULL callback, and blocking forever until the queue is */ /* non-empty if their is a valid callback */ /* callback, if non-NULL is a callback to be called when data is */ /* inserted to the queue */ /* callbackTarget and callbackRefcon are passed to the callback */ extern unsigned long HIDTransactionCommit(pRecDevice pDevice); /* Clear all the changes and start over */ extern unsigned long HIDTransactionClear(pRecDevice pDevice); // ================================== #ifdef __cplusplus } #endif #endif // _HID_Utilities_External_h_ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/HID_Utilities_Internal.h ================================================ /* File: HID_Utilities_Internal.h Contains: Definition of HID Utilities internal functions DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_Internal_h_ #define _HID_Utilities_Internal_h_ // Moved into specific "HID_xxx.h" files. #include "HID_Error_Handler.h" #endif // _HID_Utilities_Internal_h_ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/JoystickTabletPlugin/sqMacJoystickAndTablet.c ================================================ /* Adjustments for pluginized VM * * Note: The Mac support files have not yet been fully converted to * pluginization. For the time being, it is assumed that they are linked * with the VM. When conversion is complete, they will no longer import * "sq.h" and they will access all VM functions and variables through * the interpreterProxy mechanism. */ #include "sq.h" #include "JoystickTabletPlugin.h" /* End of adjustments for pluginized VM */ #pragma mark Joystick support for Mac OS X #include "HID_Utilities.h" long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); int joystickInit(void) { HIDBuildDeviceList(kHIDPage_GenericDesktop, 0); return true; } int joystickShutdown() { HIDReleaseDeviceList(); return true; } static pRecDevice getJoystickDevice(int stickIndex) { pRecDevice device = HIDGetFirstDevice(); int stickCount = 0; while (device) { if ( (device->usage == kHIDUsage_GD_Joystick) || (device->usage == kHIDUsage_GD_GamePad) ) { stickCount++; if (stickCount == stickIndex) return device; } device = HIDGetNextDevice(device); } return NULL; } static int getScaledAxisValue(pRecDevice device, pRecElement element, int userMin, int userMax) { SInt32 raw = HIDGetElementValue(device, element); element -> userMin = userMin; element -> userMax = userMax; return (int) HIDScaleValue(raw, element); } int joystickRead(int stickIndex) { /* Return input word for the joystick with the given index (starting at 1). This word is encoded as follows: The highest four bits of the input word are zero. If the onFlag bit is zero, there is no joystick at the given index. The x and y values are 11-bit signed values in the range [-1024..1023] representing the raw (unencoded) joystick position. */ int onFlag = 0; int buttons = 0; int xValue = 0; int yValue = 0; pRecDevice device = getJoystickDevice(stickIndex); if (device) { onFlag = 1; pRecElement element = HIDGetFirstDeviceElement(device, kHIDElementTypeAll); while (element) { switch (element->usagePage) { case kHIDPage_GenericDesktop: switch (element->usage) { case kHIDUsage_GD_X: xValue = getScaledAxisValue(device, element, -1024, 1023); break; case kHIDUsage_GD_Y: yValue = getScaledAxisValue(device, element, -1024, 1023); break; } break; case kHIDPage_Button: { int button = element->usage - kHIDUsage_Button_1; if ((button >= 0) && (button <= 4) ) buttons |= (HIDGetElementValue(device, element) << button); } break; } element = HIDGetNextDeviceElement(element, kHIDElementTypeAll); } } return (onFlag << 27) | (buttons << 22) | ((yValue + 1024) << 11) | (xValue + 1024); } #pragma mark Tablet support for older versions of Mac OS /* Tablet Record (see Apple Tech. Note 266, version 2) */ #define MAX_TRANSDUCERS 4 typedef struct { char DOFTrans; /* degrees of freedom and transducer type */ char orientFlag; /* type of orientation information */ short pressLevels; /* pressure support and number of levels */ unsigned short xScale; /* x scale factor for screen mapping */ short xTrans; /* x translation factor for screen */ unsigned short yScale; /* y scale factor for screen mapping */ short yTrans; /* y translation factor for screen */ unsigned char flags; /* proximity, update flag, and # buttons */ unsigned char pressThresh; /* pressure threshold - normally unused */ short buttonMask; /* button mask of driver-reserved buttons */ short errorFlag; /* error code generated */ short buttons; /* buttons pressed */ short tangPress; /* tangential pressure level */ short pressure; /* normal pressure level */ long timeStamp; /* ticks at latest update */ long xCoord; /* x coordinate in resolution units */ long yCoord; /* y coordinate in resolution units */ long zCoord; /* z coordinate in resolution units */ short xTilt; /* x tilt */ short yTilt; /* y tilt */ short unused[8]; /* remainder of unused attitude matrix */ } TransducerRec, *TransducerRecPtr; typedef struct { char version; /* version of this data format */ char semaphore; /* for future use -- tells if drvr is enabled */ char cursors; /* number of cursors with tablet */ char updateFlags; /* flags used when updating structure */ short angleRes; /* metric bit & angular resolution */ short spaceRes; /* spatial resolution of the tablet */ long xDimension; /* x dimension in resolution units */ long yDimension; /* y dimension in resolution units */ long zDimension; /* z dimension in resolution units */ long xDisplace; /* x displacement - minimum x value */ long yDisplace; /* y displacement - minimum y value */ long zDisplace; /* z displacement - minimum z value */ long reserved; /* reserved */ long tabletID; /* contains 'TBLT' identifying the device */ TransducerRec transducer[MAX_TRANSDUCERS]; } TabletRec, *TabletRecPtr; /*** Variables ***/ TabletRecPtr tablet = nil; /* pointer to a tablet record or nil */ int tabletInit(void); int tabletInit(void) { /* Open the tablet driver and initialize the global pointer to its status record. Return true if a tablet exists, false otherwise. */ return false; } int tabletGetParameters(int cursorIndex, int result[]) { /* Fill in the integer array 'result' with tablet parameter information. For cursor-specific parameters, such as the number of pressure levels, return the information for the cursor with the given index, an integer between 1 and tablet->cursors. */ TransducerRecPtr cursorPtr; int cursor; /* open tablet if necessary; return false if no tablet */ if (tablet == nil) { if (!tabletInit()) return false; } cursor = cursorIndex - 1; if ((cursor < 0) || (cursor >= tablet->cursors)) { return false; } cursorPtr = &tablet->transducer[cursor]; result[0] = tablet->xDimension; result[1] = tablet->yDimension; result[2] = tablet->spaceRes; result[3] = tablet->cursors; /* number of cursors */ result[4] = cursor + 1; result[5] = cursorPtr->xScale; result[6] = cursorPtr->xTrans; result[7] = cursorPtr->yScale; result[8] = cursorPtr->yTrans; result[9] = cursorPtr->pressLevels; result[10] = cursorPtr->pressThresh; if (tablet->angleRes == 0) { result[11] = 0; /* no pen tilt support */ } else { result[11] = tablet->angleRes >> 1; /* number of pen tilt levels */ } return true; } int tabletRead(int cursorIndex, int result[]) { /* Fill in the integer array 'result' with the current data the cursor with the given index, an integer between 1 and tablet->cursors. Note that the timestamp changes only when some new data has arrived from the tablet. */ TransducerRecPtr cursorPtr; int cursor; /* open tablet if necessary; return false if no tablet */ if (tablet == nil) { if (!tabletInit()) return false; } cursor = cursorIndex - 1; if ((cursor < 0) || (cursor >= tablet->cursors)) { return false; } cursorPtr = &tablet->transducer[cursor]; result[0] = cursor + 1; result[1] = cursorPtr->timeStamp; result[2] = cursorPtr->xCoord; result[3] = cursorPtr->yCoord; result[4] = cursorPtr->zCoord; result[5] = cursorPtr->xTilt; result[6] = cursorPtr->yTilt; result[7] = (cursorPtr->DOFTrans & 0x30) >> 4; /* cursor type; 1-pen, 2-puck, 3-eraser */ result[8] = cursorPtr->buttons; result[9] = cursorPtr->pressure; result[10] = cursorPtr->tangPress; result[11] = cursorPtr->flags; return true; } int tabletResultSize(void) { /* Return the size of the integer array required to hold the results of either a tabletGetParameters() or tabletRead() call. The VM allocates an array of this length and passes it as a parameter to be filled in. */ return 12; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ CFBundleName = "KedamaPlugin"; CFBundleShortVersionString = "KedamaPlugin version 1.1.0"; CFBundleGetInfoString = "KedamaPlugin version 1.1.0"; NSHumanReadableCopyright = "http://www.squeak.org"; ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin/Info-KedamaPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable KedamaPlugin CFBundleGetInfoString KedamaPlugin V1.1.0 for Squeak, see http://www.squeak.org CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.KedamaPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName KedamaPlugin V1.1.0 for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.1.0 CFBundleSignature FAST CFBundleVersion 1.1.0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin/KedamaPlugin.st ================================================ 'From Squeakland 3.8-05 of 7 September 2005 [latest update: #494] on 8 May 2007 at 9:50:13 am'! InterpreterPlugin subclass: #KedamaPlugin instanceVariableNames: 'kedamaRandomSeed randA randM randQ randR' classVariableNames: '' poolDictionaries: '' category: 'EToys-StarSqueak'! !KedamaPlugin commentStamp: '' prior: 0! KedamaPlugin is intended to be a subclass of InterpreterPlugin, which resides in the VMMaker package and hence is not in the base Vancouver image. Thus, most methods in KedamaPlugIn won't properly, owing to their reliance on the presence of an instance variable named interpreterProxy which is expected to be inherited from SqueakPlugIn. The code is included here anyway, just to keep all the Kedama code together, but for the KedamaPlugin code to be usable, one would first need to install the VMMaker package and then redeclare KedamaPlugIn to be a subclass of InterpreterPlugin.! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveAddArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) + (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) + (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveAddScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) + intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) + floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveDivArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) / (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) / (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveDivScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) // intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) / floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveMulArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) * (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) * (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:26'! primitiveMulScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) * intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) * floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:25'! primitiveSubArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) - (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) - (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'array arithmetic' stamp: 'yo 1/10/2005 21:25'! primitiveSubScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) - intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) - floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/30/2004 12:08'! degreesFromX: x y: y | tanVal theta | self inline: true. self returnTypeC: 'double'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'tanVal' declareC: 'double tanVal'. self var: 'theta' declareC: 'double theta'. x = 0.0 ifTrue: [ y >= 0.0 ifTrue: [^ 90.0] ifFalse: [^ 270.0]. ] ifFalse: [ tanVal _ y / x. theta _ self cCode: 'atan(tanVal)' inSmalltalk: [tanVal arcTan]. x >= 0.0 ifTrue: [ y >= 0.0 ifTrue: [^ theta / 0.0174532925199433] ifFalse: [^ 360.0 + (theta / 0.0174532925199433)] ] ifFalse: [ ^ 180.0 + (theta / 0.0174532925199433) ] ]. ^ 0.0. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:36'! degreesToRadians: degrees | headingRadians deg q | self inline: true. self returnTypeC: 'double'. self var: 'degrees' declareC: 'double degrees'. self var: 'deg' declareC: 'double deg'. self var: 'headingRadians' declareC: 'double headingRadians'. self var: 'q' declareC: 'int q'. deg _ 90.0 - degrees. q _ deg / 360.0. deg < 0.0 ifTrue: [q _ q - 1]. headingRadians _ (deg - (q * 360.0)) * 0.0174532925199433. ^ headingRadians. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/30/2004 11:07'! drawTurtlesInArray | visibleArray colorArray yArray xArray destHeight destWidth destBits size x y visible visibleOop colorOop yOop xOop destOop bitsIndex | self export: true. self inline: true. self var: 'destBits' declareC: 'unsigned int *destBits'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'colorArray' declareC: 'unsigned int *colorArray'. self var: 'visibleArray' declareC: 'unsigned char *visibleArray'. visibleOop _ interpreterProxy stackValue: 0. colorOop _ interpreterProxy stackValue: 1. yOop _ interpreterProxy stackValue: 2. xOop _ interpreterProxy stackValue: 3. destHeight _ interpreterProxy stackIntegerValue: 4. destWidth _ interpreterProxy stackIntegerValue: 5. destOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: destOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: colorOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isBytes: visibleOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (destHeight * destWidth) ~= (interpreterProxy slotSizeOf: destOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: colorOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: visibleOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. colorArray _ interpreterProxy firstIndexableField: colorOop. visibleArray _ interpreterProxy firstIndexableField: visibleOop. destBits _ interpreterProxy firstIndexableField: destOop. 0 to: size - 1 do: [:i | x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. visible _ (visibleArray at: i). ((visible ~= 0) and: [((x >= 0) and: [y >= 0]) and: [(x < destWidth) and: [y < destHeight]]]) ifTrue: [ bitsIndex _ ((y * destWidth) + x). destBits at: bitsIndex put: (colorArray at: i). ] ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:37'! getHeadingArrayInto | resultOop headingOop size headingArray resultArray heading | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'resultArray' declareC: 'float *resultArray'. self var: 'heading' declareC: 'double heading'. resultOop _ interpreterProxy stackValue: 0. headingOop _ interpreterProxy stackValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: headingOop. (interpreterProxy slotSizeOf: resultOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. resultArray _ interpreterProxy firstIndexableField: resultOop. 0 to: size - 1 do: [:i | heading _ headingArray at: i. heading _ heading / 0.0174532925199433. heading _ 90.0 - heading. heading > 0.0 ifFalse: [heading _ heading + 360.0]. resultArray at: i put: heading. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 2. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/11/2004 21:17'! getScalarHeading | headingOop headingArray heading index | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'heading' declareC: 'double heading'. headingOop _ interpreterProxy stackValue: 0. index _ interpreterProxy stackIntegerValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) < index ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. heading _ headingArray at: index - 1. heading _ self radiansToDegrees: heading. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 3. interpreterProxy pushFloat: heading. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:39'! initialiseModule self export: true. kedamaRandomSeed _ 17. randA := 16r000041A7. " magic constant = 16807 " randM := 16r7FFFFFFF. " magic constant = 2147483647 " randQ := randM // randA. randR := randM \\ randA. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:38'! kedamaRandom2: range | lo hi r v val | self inline: true. range < 0 ifTrue: [r _ 0 - range] ifFalse: [r _ range]. hi _ kedamaRandomSeed // randQ. lo _ kedamaRandomSeed \\ randQ. kedamaRandomSeed _ (randA * lo) - (randR * hi). v _ kedamaRandomSeed bitAnd: 65535. val _ (v * (r + 1)) >> 16. range < 0 ifTrue: [^ 0 - val] ifFalse: [^ val]. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:02'! kedamaRandom: range | r val | self inline: true. range < 0 ifTrue: [r _ 0 - range] ifFalse: [r _ range]. kedamaRandomSeed _ ((kedamaRandomSeed * 1309) + 13849) bitAnd: 65535. val _ (kedamaRandomSeed * (r + 1)) >> 16. range < 0 ifTrue: [^ 0 - val] ifFalse: [^ val]. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 13:26'! kedamaSetRandomSeed | seed | self inline: true. self export: true. seed _ interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue: [^ nil]. kedamaRandomSeed _ seed bitAnd: 65536. interpreterProxy pop: 1. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 6/7/2004 12:24'! makeMask | shiftAmount pixel maskBits dataBits dataSize maskSize dOrigin mOrigin data alpha highMask | self export: true. self inline: true. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. self var: 'mOrigin' declareC: 'unsigned int* mOrigin'. self var: 'highMask' declareC: 'unsigned int highMask'. self var: 'alpha' declareC: 'unsigned int alpha'. self var: 'pixel' declareC: 'unsigned int pixel'. shiftAmount _ interpreterProxy stackIntegerValue: 0. pixel _ interpreterProxy stackIntegerValue: 1. maskBits _ interpreterProxy stackValue: 2. dataBits _ interpreterProxy stackValue: 3. interpreterProxy failed ifTrue: [^ nil]. dataSize _ interpreterProxy slotSizeOf: dataBits. maskSize _ interpreterProxy slotSizeOf: maskBits. dataSize = maskSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. shiftAmount < -32 ifTrue: [interpreterProxy primitiveFail. ^ nil]. shiftAmount > 8 ifTrue: [interpreterProxy primitiveFail. ^ nil]. dOrigin _ interpreterProxy firstIndexableField: dataBits. mOrigin _ interpreterProxy firstIndexableField: maskBits. highMask _ 16rFF000000. 0 to: dataSize -1 do: [:i | data _ dOrigin at: i. alpha _ data bitShift: shiftAmount. (alpha > 255) ifTrue: [alpha _ 255]. (alpha < 0) ifTrue: [alpha _ 0]. mOrigin at: i put: (((alpha << 24) bitAnd: highMask) bitOr: pixel). ]. interpreterProxy pop: 4. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 6/15/2004 04:57'! makeMaskLog | max pixel maskBits dataBits dataSize maskSize dOrigin mOrigin data alpha highMask maxLog maxOop maxFirst | self export: true. self inline: true. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. self var: 'mOrigin' declareC: 'unsigned int* mOrigin'. self var: 'highMask' declareC: 'unsigned int highMask'. self var: 'maxFirst' declareC: 'unsigned int* maxFirst'. self var: 'max' declareC: 'unsigned int max'. self var: 'alpha' declareC: 'unsigned int alpha'. self var: 'pixel' declareC: 'unsigned int pixel'. self var: 'maxLog' declareC: 'double maxLog'. maxOop _ interpreterProxy stackValue: 0. pixel _ interpreterProxy stackIntegerValue: 1. maskBits _ interpreterProxy stackValue: 2. dataBits _ interpreterProxy stackValue: 3. interpreterProxy failed ifTrue: [^ nil]. maxFirst _ (interpreterProxy firstIndexableField: maxOop). max _ maxFirst at: 0. interpreterProxy failed ifTrue: [^ nil]. maxLog _ self cCode: 'log(max)' inSmalltalk: [max ln]. dataSize _ interpreterProxy slotSizeOf: dataBits. maskSize _ interpreterProxy slotSizeOf: maskBits. dataSize = maskSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. dOrigin _ interpreterProxy firstIndexableField: dataBits. mOrigin _ interpreterProxy firstIndexableField: maskBits. highMask _ 16rFF000000. 0 to: dataSize -1 do: [:i | data _ dOrigin at: i. data = 0 ifTrue: [alpha _ 0] ifFalse: [ alpha _ ((255.0 / maxLog) * (self cCode: 'log(data)' inSmalltalk: [data ln])) asInteger. ]. (alpha > 255) ifTrue: [alpha _ 255]. mOrigin at: i put: (((alpha << 24) bitAnd: highMask) bitOr: pixel). ]. interpreterProxy pop: 4. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/29/2004 17:27'! makeTurtlesMap | height width yOop xOop whoOop mapOop size xArray yArray whoArray map x y mapIndex | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'whoArray' declareC: 'unsigned int *whoArray'. self var: 'map' declareC: 'unsigned int *map'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. yOop _ interpreterProxy stackValue: 2. xOop _ interpreterProxy stackValue: 3. whoOop _ interpreterProxy stackValue: 4. mapOop _ interpreterProxy stackValue: 5. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: whoOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: mapOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: whoOop. (interpreterProxy slotSizeOf: xOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: mapOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. whoArray _ interpreterProxy firstIndexableField: whoOop. map _ interpreterProxy firstIndexableField: mapOop. 0 to: (height * width) - 1 do: [:index | map at: index put: 0. ]. 0 to: size - 1 do: [:index | x _ xArray at: index. y _ yArray at: index. mapIndex _ (width * y) + x. (mapIndex >= 0 and: [mapIndex < (height * width)]) ifTrue: [ map at: mapIndex put: (whoArray at: index). ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/29/2004 18:52'! primPixelAtXY | height width yPos xPos bitsOop x y bits index ret | self export: true. self inline: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xPos' declareC: 'double xPos'. self var: 'yPos' declareC: 'double yPos'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. yPos _ interpreterProxy stackFloatValue: 2. xPos _ interpreterProxy stackFloatValue: 3. bitsOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. x _ xPos. y _ yPos. bits _ interpreterProxy firstIndexableField: bitsOop. ((x >= 0) & (x < width) & (y >= 0) & (y < height)) ifTrue: [ index _ y * width + x. ret _ bits at: index. ] ifFalse: [ ret _ 0. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy pushInteger: ret. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/29/2004 18:50'! primPixelAtXYPut | height width value yPos xPos bitsOop x y v bits index | self export: true. self inline: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xPos' declareC: 'double xPos'. self var: 'yPos' declareC: 'double yPos'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. value _ interpreterProxy stackIntegerValue: 2. yPos _ interpreterProxy stackFloatValue: 3. xPos _ interpreterProxy stackFloatValue: 4. bitsOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. x _ xPos. y _ yPos. v _ value. v > 16r3FFFFFFF ifTrue: [ v _ 16r3FFFFFFF. ]. v < 0 ifTrue: [ v _ 0. ]. bits _ interpreterProxy firstIndexableField: bitsOop. ((x >= 0) & (x < width) & (y >= 0) & (y < height)) ifTrue: [ index _ y * width + x. bits at: index put: v. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/25/2004 16:42'! primPixelsAtXY | yArray xArray bitsHeight bitsWidth bitsOop bits size x y bitsIndex destWordsOop yArrayOop xArrayOop destWords | self export: true. self inline: true. self var: 'destWords' declareC: 'unsigned int *destWords'. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. destWordsOop _ interpreterProxy stackValue: 0. bitsHeight _ interpreterProxy stackIntegerValue: 1. bitsWidth _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. yArrayOop _ interpreterProxy stackValue: 4. xArrayOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: destWordsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (bitsHeight * bitsWidth) ~= (interpreterProxy slotSizeOf: bitsOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xArrayOop. (interpreterProxy slotSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: destWordsOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. destWords _ interpreterProxy firstIndexableField: destWordsOop. bits _ interpreterProxy firstIndexableField: bitsOop. 0 to: size - 1 do: [:i | x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. (((x >= 0) and: [y >= 0]) and: [(x < bitsWidth) and: [y < bitsHeight]]) ifTrue: [ bitsIndex _ ((y * bitsWidth) + x). destWords at: i put: (bits at: bitsIndex). ] ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:38'! primScalarForward | bottomEdgeMode topEdgeMode rightEdgeMode leftEdgeMode destHeight destWidth headingOop yOop xOop size xArray yArray headingArray val dist newX newY index i | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'dist' declareC: 'double dist'. self var: 'newX' declareC: 'double newX'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. rightEdgeMode _ interpreterProxy stackIntegerValue: 2. leftEdgeMode _ interpreterProxy stackIntegerValue: 3. destHeight _ interpreterProxy stackFloatValue: 4. destWidth _ interpreterProxy stackFloatValue: 5. val _ interpreterProxy stackFloatValue: 6. headingOop _ interpreterProxy stackValue: 7. yOop _ interpreterProxy stackValue: 8. xOop _ interpreterProxy stackValue: 9. index _ interpreterProxy stackIntegerValue: 10. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. dist _ val. i _ index - 1. newX _ (xArray at: i) + (dist * (headingArray at: i) cos). newY _ (yArray at: i) - (dist * (headingArray at: i) sin). self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 11. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/25/2004 17:06'! primSetPixelsAtXY | yArray xArray bitsHeight bitsWidth bitsOop bits size x y bitsIndex yArrayOop xArrayOop valueOop isValueInt intValue wordsValue value | self export: true. self inline: true. self var: 'intValue' declareC: 'unsigned int intValue'. self var: 'wordsValue' declareC: 'unsigned int *wordsValue'. self var: 'value' declareC: 'unsigned int value'. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. valueOop _ interpreterProxy stackValue: 0. bitsHeight _ interpreterProxy stackIntegerValue: 1. bitsWidth _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. yArrayOop _ interpreterProxy stackValue: 4. xArrayOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (bitsHeight * bitsWidth) ~= (interpreterProxy slotSizeOf: bitsOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xArrayOop. (interpreterProxy slotSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValueInt _ interpreterProxy isIntegerObject: valueOop. isValueInt ifTrue: [ intValue _ interpreterProxy integerValueOf: valueOop. ]. isValueInt ifFalse: [ (interpreterProxy is: valueOop MemberOf: 'WordArray') ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: valueOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isValueInt ifFalse: [ wordsValue _ interpreterProxy firstIndexableField: valueOop. ]. bits _ interpreterProxy firstIndexableField: bitsOop. isValueInt ifTrue: [ value _ intValue. ]. 0 to: size - 1 do: [:i | x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. (((x >= 0) and: [y >= 0]) and: [(x < bitsWidth) and: [y < bitsHeight]]) ifTrue: [ bitsIndex _ ((y * bitsWidth) + x). isValueInt ifFalse: [ value _ wordsValue at: i. ]. bits at: bitsIndex put: value. ] ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:39'! primTurtlesForward | bottomEdgeMode topEdgeMode rightEdgeMode leftEdgeMode destHeight destWidth valOop headingOop yOop xOop isValVector size xArray yArray headingArray valArray val dist newX newY | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'dist' declareC: 'double dist'. self var: 'newX' declareC: 'double newX'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. rightEdgeMode _ interpreterProxy stackIntegerValue: 2. leftEdgeMode _ interpreterProxy stackIntegerValue: 3. destHeight _ interpreterProxy stackFloatValue: 4. destWidth _ interpreterProxy stackFloatValue: 5. valOop _ interpreterProxy stackValue: 6. headingOop _ interpreterProxy stackValue: 7. yOop _ interpreterProxy stackValue: 8. xOop _ interpreterProxy stackValue: 9. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false. ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ valArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size -1 do: [:i | isValVector ifTrue: [ dist _ valArray at: i. ] ifFalse: [ dist _ val. ]. newX _ (xArray at: i) + (dist * (headingArray at: i) cos). newY _ (yArray at: i) - (dist * (headingArray at: i) sin). self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 10. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 9/30/2004 12:19'! primUpHill | sniffRange height width bitsOop tH tY tX bits turtleX turtleY startX endX startY endY maxVal maxValX rowOffset thisVal maxValY ret | self inline: true. self export: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'tX' declareC: 'double tX'. self var: 'tY' declareC: 'double tY'. self var: 'tH' declareC: 'double tH'. sniffRange _ interpreterProxy stackIntegerValue: 0. height _ interpreterProxy stackIntegerValue: 1. width _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. tH _ interpreterProxy stackFloatValue: 4. tY _ interpreterProxy stackFloatValue: 5. tX _ interpreterProxy stackFloatValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. bits _ interpreterProxy firstIndexableField: bitsOop. turtleX _ self cCode: 'tX' inSmalltalk: [tX asInteger]. turtleY _ self cCode: 'tY' inSmalltalk: [tY asInteger]. turtleX _ turtleX max: 0. turtleY _ turtleY max: 0. turtleX _ turtleX min: width - 1. turtleY _ turtleY min: height - 1. startX _ turtleX - sniffRange max: 0. endX _ (turtleX + sniffRange) min: (width - 1). startY _ (turtleY - sniffRange) max: 0. endY _ (turtleY + sniffRange) min: (height - 1). maxVal _ bits at: turtleY * width + turtleX. maxValX _ -1. startY to: endY do: [:y | rowOffset _ y * width. startX to: endX do: [:x | thisVal _ bits at: rowOffset + x. thisVal > maxVal ifTrue: [ maxValX _ x. maxValY _ y. maxVal _ thisVal ]. ]. ]. -1 = maxValX ifTrue: [ret _ self radiansToDegrees: tH] ifFalse: [ ret _ (self degreesFromX: (self cCoerce: maxValX - turtleX to: 'double') y: (self cCoerce: maxValY - turtleY to: 'double')) + 90.0. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 8. interpreterProxy pushFloat: ret. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/11/2004 12:43'! radiansToDegrees: radians | deg degrees | self inline: true. self returnTypeC: 'double'. self var: 'degrees' declareC: 'double degrees'. self var: 'deg' declareC: 'double deg'. self var: 'radians' declareC: 'double radians'. self var: 'headingRadians' declareC: 'double headingRadians'. degrees _ radians / 0.0174532925199433. deg _ 90.0 - degrees. deg > 0.0 ifFalse: [deg _ deg + 360.0]. ^ deg. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:43'! randomIntoFloatArray | range factor floatArrayOop to from size floatArray | self export: true. self inline: true. self var: 'factor' declareC: 'double factor'. self var: 'floatArray' declareC: 'float *floatArray'. factor _ interpreterProxy stackFloatValue: 0. floatArrayOop _ interpreterProxy stackValue: 1. to _ interpreterProxy stackIntegerValue: 2. from _ interpreterProxy stackIntegerValue: 3. range _ interpreterProxy stackIntegerValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: floatArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: floatArrayOop. (size >= to and: [from >= 1 and: [to >= from]]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. floatArray _ interpreterProxy firstIndexableField: floatArrayOop. interpreterProxy failed ifTrue: [^ nil]. from to: to do: [:index | floatArray at: index-1 put: (self cCoerce: (self kedamaRandom2: range) to: 'double') * factor. ]. interpreterProxy pop: 5. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:43'! randomIntoIntegerArray | range factor integerArrayOop to from size integerArray | self export: true. self inline: true. self var: 'factor' declareC: 'double factor'. self var: 'integerArray' declareC: 'unsigned int *integerArray'. factor _ interpreterProxy stackFloatValue: 0. integerArrayOop _ interpreterProxy stackValue: 1. to _ interpreterProxy stackIntegerValue: 2. from _ interpreterProxy stackIntegerValue: 3. range _ interpreterProxy stackIntegerValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: integerArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: integerArrayOop. (size >= to and: [from >= 1 and: [to >= from]]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. integerArray _ interpreterProxy firstIndexableField: integerArrayOop. interpreterProxy failed ifTrue: [^ nil]. from to: to do: [:index | integerArray at: index-1 put: (self cCoerce: ((self cCoerce: (self kedamaRandom2: range) to: 'double') * factor) to: 'int'). ]. interpreterProxy pop: 5. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 3/7/2005 14:43'! randomRange | range ret | self export: true. self inline: true. range _ interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue: [^ nil]. ret _ self kedamaRandom2: range. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 2. interpreterProxy pushInteger: ret. ^ self. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 22:23'! scalarGetAngleTo | fromY fromX toY toX x y r | self export: true. self inline: true. self var: 'toX' declareC: 'double toX'. self var: 'toY' declareC: 'double toY'. self var: 'fromX' declareC: 'double fromX'. self var: 'fromY' declareC: 'double fromY'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'r' declareC: 'double r'. fromY _ interpreterProxy stackFloatValue: 0. fromX _ interpreterProxy stackFloatValue: 1. toY _ interpreterProxy stackFloatValue: 2. toX _ interpreterProxy stackFloatValue: 3. interpreterProxy failed ifTrue: [^ nil]. x _ toX - fromX. y _ toY - fromY. r _ self degreesFromX: x y: y. r _ r + 90.0. r > 360.0 ifTrue: [r _ r - 360.0]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 5. interpreterProxy pushFloat: r. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/22/2004 15:35'! scalarGetDistanceTo | fromY fromX toY toX x y r | self export: true. self inline: true. self var: 'toX' declareC: 'double toX'. self var: 'toY' declareC: 'double toY'. self var: 'fromX' declareC: 'double fromX'. self var: 'fromY' declareC: 'double fromY'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'r' declareC: 'double r'. fromY _ interpreterProxy stackFloatValue: 0. fromX _ interpreterProxy stackFloatValue: 1. toY _ interpreterProxy stackFloatValue: 2. toX _ interpreterProxy stackFloatValue: 3. interpreterProxy failed ifTrue: [^ nil]. x _ fromX - toX. y _ fromY - toY. r _ ((x * x) + (y * y)) sqrt. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 5. interpreterProxy pushFloat: r. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:39'! scalarXAt: index xArray: xArray headingArray: headingArray value: val destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode | newX headingRadians | self inline: true. self var: 'xArray' declareC: 'float* xArray'. self var: 'headingArray' declareC: 'float* headingArray'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'val' declareC: 'double val'. self var: 'newX' declareC: 'double newX'. self var: 'headingRadians' declareC: 'double headingRadians'. newX _ val. newX < 0.0 ifTrue: [ leftEdgeMode = 1 ifTrue: [ "wrap" newX _ newX + destWidth. ]. leftEdgeMode = 2 ifTrue: [ "stick" newX _ 0.0. ]. leftEdgeMode = 3 ifTrue: [ "bounce" newX _ 0.0 - newX. headingRadians _ headingArray at: index. headingRadians < 3.141592653589793 ifTrue: [headingArray at: index put: 3.141592653589793 - headingRadians] ifFalse: [headingArray at: index put: 9.42477796076938 - headingRadians]. ]. ]. newX >= destWidth ifTrue: [ rightEdgeMode = 1 ifTrue: [ newX _ newX - destWidth. ]. rightEdgeMode = 2 ifTrue: [ newX _ destWidth - 0.000001. ]. rightEdgeMode = 3 ifTrue: [ newX _ (destWidth - 0.000001) - (newX - destWidth). headingRadians _ headingArray at: index. headingRadians < 3.141592653589793 ifTrue: [headingArray at: index put: (3.141592653589793 - headingRadians)] ifFalse: [headingArray at: index put: (9.42477796076938 - headingRadians)]. ] ]. xArray at: index put: newX. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:39'! scalarYAt: index yArray: yArray headingArray: headingArray value: val destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode | newY | self inline: true. self var: 'yArray' declareC: 'float* yArray'. self var: 'headingArray' declareC: 'float* headingArray'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'val' declareC: 'double val'. self var: 'newY' declareC: 'double newY'. newY _ val. newY < 0.0 ifTrue: [ topEdgeMode = 1 ifTrue: [ "wrap" newY _ newY + destHeight. ]. topEdgeMode = 2 ifTrue: [ "stick" newY _ 0.0. ]. topEdgeMode = 3 ifTrue: [ "bounce" newY _ 0.0 - newY. headingArray at: index put: (6.283185307179586 - (headingArray at: index)). ]. ]. newY >= destHeight ifTrue: [ bottomEdgeMode = 1 ifTrue: [ newY _ newY - destHeight. ]. bottomEdgeMode = 2 ifTrue: [ newY _ destHeight - 0.000001. ]. bottomEdgeMode = 3 ifTrue: [ newY _ (destHeight - 0.000001) - (newY - destHeight). headingArray at: index put: (6.283185307179586 - (headingArray at: index)). ] ]. yArray at: index put: newY. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:39'! setHeadingArrayFrom | resultOop headingOop size headingArray resultArray heading isValVector | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'resultArray' declareC: 'float *resultArray'. self var: 'heading' declareC: 'double heading'. resultOop _ interpreterProxy stackValue: 0. headingOop _ interpreterProxy stackValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: headingOop. (interpreterProxy isFloatObject: resultOop) ifTrue: [ isValVector _ false. ] ifFalse: [ (interpreterProxy isWords: resultOop) ifTrue: [ (interpreterProxy slotSizeOf: resultOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ resultArray _ interpreterProxy firstIndexableField: resultOop. ] ifFalse: [ heading _ interpreterProxy floatValueOf: resultOop. heading _ self degreesToRadians: heading. ]. 0 to: size - 1 do: [:i | isValVector ifTrue: [ heading _ resultArray at: i. heading _ self degreesToRadians: heading. ]. headingArray at: i put: heading. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 2. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/11/2004 14:10'! setScalarHeading | headingOop headingArray heading index | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'heading' declareC: 'double heading'. heading _ interpreterProxy stackFloatValue: 0. headingOop _ interpreterProxy stackValue: 1. index _ interpreterProxy stackIntegerValue: 2. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) < index ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. headingArray at: index - 1 put: (self degreesToRadians: heading). interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 3. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 1/24/2005 14:49'! shutdownModule self export: true. ^ true. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:39'! turtleScalarSetX | xArray headingArray val destWidth xOop headingOop leftEdgeMode rightEdgeMode xIndex size | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destWidth' declareC: 'double destWidth'. rightEdgeMode _ interpreterProxy stackIntegerValue: 0. leftEdgeMode _ interpreterProxy stackIntegerValue: 1. destWidth _ interpreterProxy stackFloatValue: 2. val _ interpreterProxy stackFloatValue: 3. headingOop _ interpreterProxy stackValue: 4. xIndex _ interpreterProxy stackIntegerValue: 5. xOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. headingArray _ interpreterProxy firstIndexableField: headingOop. self scalarXAt: xIndex - 1 xArray: xArray headingArray: headingArray value: val destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:40'! turtleScalarSetY | yArray headingArray val destHeight yOop headingOop size yIndex topEdgeMode bottomEdgeMode | self export: true. self inline: true. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. destHeight _ interpreterProxy stackFloatValue: 2. val _ interpreterProxy stackFloatValue: 3. headingOop _ interpreterProxy stackValue: 4. yIndex _ interpreterProxy stackIntegerValue: 5. yOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: yOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. self scalarYAt: yIndex - 1 yArray: yArray headingArray: headingArray value: val destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:40'! turtlesSetX | xArray headingArray valArray val destWidth xOop headingOop valOop leftEdgeMode rightEdgeMode isValVector size newX | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'val' declareC: 'double val'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'newX' declareC: 'double newX'. rightEdgeMode _ interpreterProxy stackIntegerValue: 0. leftEdgeMode _ interpreterProxy stackIntegerValue: 1. destWidth _ interpreterProxy stackFloatValue: 2. valOop _ interpreterProxy stackValue: 3. headingOop _ interpreterProxy stackValue: 4. xOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. xArray _ interpreterProxy firstIndexableField: xOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ valArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size - 1 do: [:i | isValVector ifTrue: [ newX _ valArray at: i. ] ifFalse: [ newX _ val. ]. self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:40'! turtlesSetY | yArray headingArray valArray val destHeight yOop headingOop valOop topEdgeMode bottomEdgeMode isValVector size newY | self export: true. self inline: true. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. destHeight _ interpreterProxy stackFloatValue: 2. valOop _ interpreterProxy stackValue: 3. headingOop _ interpreterProxy stackValue: 4. yOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: yOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ valArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size - 1 do: [:i | isValVector ifTrue: [ newY _ valArray at: i. ] ifFalse: [ newY _ val. ]. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 19:01'! vectorGetAngleTo | x y resultOop yArrayOop xArrayOop pYOop pXOop size isVector result xArray yArray pX pY ppx ppy r | self export: true. self inline: true. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'result' declareC: 'float *result'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'pX' declareC: 'float *pX'. self var: 'pY' declareC: 'float *pY'. self var: 'ppx' declareC: 'double ppx'. self var: 'ppy' declareC: 'double ppy'. resultOop _ interpreterProxy stackValue: 0. yArrayOop _ interpreterProxy stackValue: 1. xArrayOop _ interpreterProxy stackValue: 2. pYOop _ interpreterProxy stackValue: 3. pXOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: resultOop. size < 0 ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: xArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: pXOop) ifTrue: [ (interpreterProxy isFloatObject: pYOop) ifTrue: [isVector _ false] ifFalse: [interpreterProxy primitiveFail. ^ nil]. ] ifFalse: [ (interpreterProxy isFloatObject: pYOop) ifFalse: [isVector _ true] ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. isVector ifTrue: [ (interpreterProxy stSizeOf: pXOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: pYOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. result _ interpreterProxy firstIndexableField: resultOop. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isVector ifTrue: [ pX _ interpreterProxy firstIndexableField: pXOop. pY _ interpreterProxy firstIndexableField: pYOop. ]. isVector ifFalse: [ ppx _ interpreterProxy floatValueOf: pXOop. ppy _ interpreterProxy floatValueOf: pYOop. ]. 0 to: size - 1 do: [:index | isVector ifTrue: [ ppx _ pX at: index. ppy _ pY at: index. ]. x _ ppx - (xArray at: index). y _ ppy - (yArray at: index). r _ self degreesFromX: x y: y. r _ r + 90.0. r > 360.0 ifTrue: [r _ r - 360.0]. result at: index put: r. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 10/23/2004 18:20'! vectorGetDistanceTo | x y resultOop yArrayOop xArrayOop pYOop pXOop size isVector result xArray yArray pX pY ppx ppy | self export: true. self inline: true. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'result' declareC: 'float *result'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'pX' declareC: 'float *pX'. self var: 'pY' declareC: 'float *pY'. self var: 'ppx' declareC: 'double ppx'. self var: 'ppy' declareC: 'double ppy'. resultOop _ interpreterProxy stackValue: 0. yArrayOop _ interpreterProxy stackValue: 1. xArrayOop _ interpreterProxy stackValue: 2. pYOop _ interpreterProxy stackValue: 3. pXOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: resultOop. size < 0 ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: xArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: pXOop) ifTrue: [ (interpreterProxy isFloatObject: pYOop) ifTrue: [isVector _ false] ifFalse: [interpreterProxy primitiveFail. ^ nil]. ] ifFalse: [ (interpreterProxy isFloatObject: pYOop) ifFalse: [isVector _ true] ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. isVector ifTrue: [ (interpreterProxy stSizeOf: pXOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: pYOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. result _ interpreterProxy firstIndexableField: resultOop. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isVector ifTrue: [ pX _ interpreterProxy firstIndexableField: pXOop. pY _ interpreterProxy firstIndexableField: pYOop. ]. isVector ifFalse: [ ppx _ interpreterProxy floatValueOf: pXOop. ppy _ interpreterProxy floatValueOf: pYOop. ]. 0 to: size - 1 do: [:index | isVector ifTrue: [ ppx _ pX at: index. ppy _ pY at: index. ]. x _ ppx - (xArray at: index). y _ ppy - (yArray at: index). result at: index put: ((x * x) + (y * y)) sqrt. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy push: resultOop. ! ! !KedamaPlugin methodsFor: 'primitives' stamp: 'yo 6/7/2004 12:02'! zoomBitmap | yFactor xFactor sHeight sWidth dst src srcSize dstSize sOrigin dOrigin srcIndex bit dstIndex srcOrigin | self export: true. self inline: true. self var: 'sOrigin' declareC: 'unsigned int* sOrigin'. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. yFactor _ interpreterProxy stackIntegerValue: 0. xFactor _ interpreterProxy stackIntegerValue: 1. sHeight _ interpreterProxy stackIntegerValue: 2. sWidth _ interpreterProxy stackIntegerValue: 3. dst _ interpreterProxy stackValue: 4. src _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. srcSize _ interpreterProxy slotSizeOf: src. dstSize _ interpreterProxy slotSizeOf: dst. (sWidth * sHeight) = srcSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. (srcSize * xFactor * yFactor) = dstSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. sOrigin _ interpreterProxy firstIndexableField: src. dOrigin _ interpreterProxy firstIndexableField: dst. srcIndex _ 0. srcOrigin _ 0. dstIndex _ 0. 0 to: sHeight - 1 do: [:sy | 0 to: yFactor - 1 do: [:y | 0 to: sWidth - 1 do: [:sx | bit _ sOrigin at: srcIndex. srcIndex _ srcIndex + 1. 0 to: xFactor - 1 do: [:dummy | dOrigin at: dstIndex put: bit. dstIndex _ dstIndex + 1. ]. ]. srcIndex _ srcOrigin. ]. srcOrigin _ srcOrigin + sWidth. srcIndex _ srcOrigin. ]. interpreterProxy pop: 6. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! KedamaPlugin class instanceVariableNames: ''! !KedamaPlugin class methodsFor: 'as yet unclassified' stamp: 'yo 3/7/2005 14:30'! declareCVarsIn: cg cg var: #kedamaRandomSeed type: 'unsigned int'. cg var: #randA type: 'unsigned int'. cg var: #randM type: 'unsigned int'. cg var: #randQ type: 'unsigned int'. cg var: #randR type: 'unsigned int'. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin2/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ CFBundleName = "KedamaPlugin2"; CFBundleShortVersionString = "KedamaPlugin2 version 1.0.0"; CFBundleGetInfoString = "KedamaPlugin2 version 1.0.0"; NSHumanReadableCopyright = "http://www.squeak.org"; ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin2/Info-KedamaPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable KedamaPlugin2 CFBundleGetInfoString KedamaPlugin2 V1.0.0 for Squeak, see http://www.squeak.org CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.KedamaPlugin2 CFBundleInfoDictionaryVersion 6.0 CFBundleName KedamaPlugin2 V1.0.0 for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.0.0 CFBundleSignature FAST CFBundleVersion 1.0.0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/KedamaPlugin2/KedamaPlugin2.st ================================================ 'From Squeakland 3.8-05 of 7 September 2005 [latest update: #494] on 8 May 2007 at 9:50:18 am'! InterpreterPlugin subclass: #KedamaPlugin2 instanceVariableNames: 'kedamaRandomSeed randA randM randQ randR' classVariableNames: '' poolDictionaries: '' category: 'EToys-StarSqueak'! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 1/19/2006 16:16'! primitivePredicateAtAllPutBoolean | rcvrOop valOop val valuesOop values predicatesOop predicates | self export: true. self inline: true. self var: #values declareC: 'unsigned char *values'. self var: #predicates declareC: 'unsigned char *predicates'. valOop _ interpreterProxy stackValue: 0. rcvrOop _ interpreterProxy stackObjectValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isIntegerValue: valOop) ifTrue: [ val _ interpreterProxy integerValueOf: valOop. ] ifFalse: [ val _ interpreterProxy booleanValueOf: valOop. ]. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isBytes: valuesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. values _ interpreterProxy firstIndexableField: valuesOop. predicates _ interpreterProxy firstIndexableField: predicatesOop. 0 to: (interpreterProxy stSizeOf: valuesOop) - 1 do:[:i | (predicates at: i) = 1 ifTrue: [ values at: i put: val ]. ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 10/13/2005 23:35'! primitivePredicateAtAllPutColor | rcvrOop val valuesOop values predicatesOop predicates | self export: true. self inline: true. self var: #values declareC: 'unsigned int *values'. self var: #val declareC: 'unsigned int val'. self var: #predicates declareC: 'unsigned char *predicates'. val _ interpreterProxy stackIntegerValue: 0. rcvrOop _ interpreterProxy stackObjectValue: 1. interpreterProxy failed ifTrue: [^ nil]. val _ val bitOr: 16rFF000000. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: valuesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. values _ interpreterProxy firstIndexableField: valuesOop. predicates _ interpreterProxy firstIndexableField: predicatesOop. 0 to: (interpreterProxy stSizeOf: valuesOop) - 1 do:[:i | (predicates at: i) = 1 ifTrue: [ values at: i put: val ]. ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 10/13/2005 23:36'! primitivePredicateAtAllPutNumber | rcvrOop val valuesOop values predicatesOop predicates | self export: true. self inline: true. self var: #values declareC: 'float *values'. self var: #val declareC: 'float val'. self var: #predicates declareC: 'unsigned char *predicates'. val _ interpreterProxy stackFloatValue: 0. rcvrOop _ interpreterProxy stackObjectValue: 1. interpreterProxy failed ifTrue: [^ nil]. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: valuesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. values _ interpreterProxy firstIndexableField: valuesOop. predicates _ interpreterProxy firstIndexableField: predicatesOop. 0 to: (interpreterProxy stSizeOf: valuesOop) - 1 do:[:i | (predicates at: i) = 1 ifTrue: [ values at: i put: val ]. ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 10/13/2005 23:33'! primitivePredicateAtAllPutObject | rcvrOop valOop valuesOop values predicatesOop predicates | self export: true. self inline: true. self var: #values declareC: 'int *values'. self var: #predicates declareC: 'unsigned char *predicates'. valOop _ interpreterProxy stackValue: 0. rcvrOop _ interpreterProxy stackObjectValue: 1. interpreterProxy failed ifTrue: [^ nil]. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isPointers: valuesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. values _ interpreterProxy firstIndexableField: valuesOop. predicates _ interpreterProxy firstIndexableField: predicatesOop. 0 to: (interpreterProxy stSizeOf: valuesOop) - 1 do:[:i | (predicates at: i) = 1 ifTrue: [ values at: i put: valOop ]. ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 10/14/2005 00:02'! primitivePredicateReplaceBytes | rcvrOop valuesOop values predicatesOop predicates repStart repOop stop start replacement valuesSize predicatesSize replacementSize | self export: true. self inline: true. self var: #values declareC: 'unsigned char *values'. self var: #predicates declareC: 'unsigned char *predicates'. self var: #replacement declareC: 'unsigned char *replacement'. repStart _ interpreterProxy stackIntegerValue: 0. repOop _ interpreterProxy stackObjectValue: 1. stop _ interpreterProxy stackIntegerValue: 2. start _ interpreterProxy stackIntegerValue: 3. rcvrOop _ interpreterProxy stackObjectValue: 4. interpreterProxy failed ifTrue: [^ nil]. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. ((interpreterProxy isBytes: valuesOop) and: [interpreterProxy isBytes: repOop]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. values _ interpreterProxy firstIndexableField: valuesOop. predicates _ interpreterProxy firstIndexableField: predicatesOop. replacement _ interpreterProxy firstIndexableField: repOop. valuesSize _ interpreterProxy stSizeOf: valuesOop. predicatesSize _ interpreterProxy stSizeOf: predicatesOop. replacementSize _ interpreterProxy stSizeOf: repOop. start > stop ifTrue: [interpreterProxy primitiveFail. ^ nil]. start < 1 ifTrue: [interpreterProxy primitiveFail. ^ nil]. start > valuesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. start > predicatesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. stop > valuesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. stop > predicatesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. repStart < 1 ifTrue: [interpreterProxy primitiveFail. ^ nil]. repStart > replacementSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. (replacementSize - repStart + 1) < (stop - start + 1) ifTrue: [interpreterProxy primitiveFail. ^ nil]. start - 1 to: stop - 1 do: [:i | (predicates at: i) = 1 ifTrue: [ values at: i put: (replacement at: repStart + i - start). ]. ]. interpreterProxy pop: 4. ! ! !KedamaPlugin2 methodsFor: 'predicated array primitive' stamp: 'yo 1/20/2006 12:01'! primitivePredicateReplaceWords | rcvrOop valuesOop values predicatesOop predicates repStart repOop stop start replacement valuesSize predicatesSize replacementSize vIsFloat rIsFloat floatValues floatReplacement fv | self export: true. self inline: true. self var: #values declareC: 'unsigned int *values'. self var: #floatValues declareC: 'float *floatValues'. self var: #predicates declareC: 'unsigned char *predicates'. self var: #replacement declareC: 'unsigned int *replacement'. self var: #floatReplacement declareC: 'float *floatReplacement'. self var: #fv declareC: 'unsigned int fv'. repStart _ interpreterProxy stackIntegerValue: 0. repOop _ interpreterProxy stackObjectValue: 1. stop _ interpreterProxy stackIntegerValue: 2. start _ interpreterProxy stackIntegerValue: 3. rcvrOop _ interpreterProxy stackObjectValue: 4. interpreterProxy failed ifTrue: [^ nil]. valuesOop _ interpreterProxy fetchPointer: 1 ofObject: rcvrOop. predicatesOop _ interpreterProxy fetchPointer: 0 ofObject: rcvrOop. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: predicatesOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (((interpreterProxy isWords: valuesOop) and: [interpreterProxy isWords: repOop]) or: [ (interpreterProxy isPointers: valuesOop) and: [interpreterProxy isPointers: repOop]]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. predicates _ interpreterProxy firstIndexableField: predicatesOop. valuesSize _ interpreterProxy stSizeOf: valuesOop. predicatesSize _ interpreterProxy stSizeOf: predicatesOop. replacementSize _ interpreterProxy stSizeOf: repOop. start > stop ifTrue: [interpreterProxy primitiveFail. ^ nil]. start < 1 ifTrue: [interpreterProxy primitiveFail. ^ nil]. start > valuesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. start > predicatesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. stop > valuesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. stop > predicatesSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. repStart < 1 ifTrue: [interpreterProxy primitiveFail. ^ nil]. repStart > replacementSize ifTrue: [interpreterProxy primitiveFail. ^ nil]. (replacementSize - repStart + 1) < (stop - start + 1) ifTrue: [interpreterProxy primitiveFail. ^ nil]. vIsFloat _ interpreterProxy is: valuesOop MemberOf: 'KedamaFloatArray'. rIsFloat _ interpreterProxy is: repOop MemberOf: 'KedamaFloatArray'. (vIsFloat and: [rIsFloat]) ifTrue: [ floatValues _ interpreterProxy firstIndexableField: valuesOop. floatReplacement _ interpreterProxy firstIndexableField: repOop. start - 1 to: stop - 1 do: [:i | (predicates at: i) = 1 ifTrue: [ floatValues at: i put: (floatReplacement at: repStart + i - start). ]. ]. ]. (vIsFloat and: [rIsFloat not]) ifTrue: [ floatValues _ interpreterProxy firstIndexableField: valuesOop. replacement _ interpreterProxy firstIndexableField: repOop. start - 1 to: stop - 1 do: [:i | (predicates at: i) = 1 ifTrue: [ floatValues at: i put: (replacement at: repStart + i - start). ]. ]. ]. (vIsFloat not and: [rIsFloat]) ifTrue: [ values _ interpreterProxy firstIndexableField: valuesOop. floatReplacement _ interpreterProxy firstIndexableField: repOop. start - 1 to: stop - 1 do: [:i | (predicates at: i) = 1 ifTrue: [ fv _ self cCoerce: (floatReplacement at: repStart + i - start) to: 'unsigned int'. self cCode: '' inSmalltalk: [fv _ fv asInteger]. values at: i put: fv. ]. ]. ]. (vIsFloat not and: [rIsFloat not]) ifTrue: [ values _ interpreterProxy firstIndexableField: valuesOop. replacement _ interpreterProxy firstIndexableField: repOop. start - 1 to: stop - 1 do: [:i | (predicates at: i) = 1 ifTrue: [ values at: i put: (replacement at: repStart + i - start). ]. ]. ]. interpreterProxy pop: 4. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveAddArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) + (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) + (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveAddScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) + intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) + floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) + floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 1/19/2006 20:20'! primitiveAndByteArray | length rcvrOop otherOop otherArray rcvrArray length1 length2 | self export: true. self inline: true. self var: #rcvrArray declareC: 'unsigned char *rcvrArray'. self var: #otherArray declareC: 'unsigned char *otherArray'. otherOop _ interpreterProxy stackObjectValue: 0. rcvrOop _ interpreterProxy stackValue: 1. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isBytes: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: otherOop). interpreterProxy failed ifTrue:[^nil]. length1 _ interpreterProxy stSizeOf: rcvrOop. length2 _ interpreterProxy stSizeOf: otherOop. interpreterProxy failed ifTrue:[^nil]. length _ length1. length1 > length2 ifTrue: [ length _ length2. ]. otherArray _ interpreterProxy firstIndexableField: otherOop. rcvrArray _ interpreterProxy firstIndexableField: rcvrOop. 0 to: length-1 do:[:i| rcvrArray at: i put: (((rcvrArray at: i) + (otherArray at: i)) = 2). ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveDivArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) / (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) / (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveDivScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) // intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) / floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) / floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:58'! primitiveEQArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) = (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) = (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) = (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) = (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:58'! primitiveEQScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) = intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) = floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) = intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) = floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:05'! primitiveGEArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) >= (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) >= (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) >= (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) >= (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:06'! primitiveGEScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) >= intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) >= floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) >= intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) >= floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:05'! primitiveGTArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) > (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) > (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) > (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) > (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:04'! primitiveGTScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) > intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) > floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) > intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) > floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:49'! primitiveLEArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) <= (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) <= (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) <= (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) <= (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:49'! primitiveLEScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) <= intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) <= floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) <= intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) <= floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:42'! primitiveLTArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) < (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) < (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) < (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) < (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 20:41'! primitiveLTScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) < intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) < floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) < intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) < floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveMulArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) * (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) * (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveMulScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) * intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) * floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) * floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:11'! primitiveNEArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg floatsArg floatsRcvr bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) ~= (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) ~= (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) ~= (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) ~= (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 21:11'! primitiveNEScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr floatsRcvr isArgInt intArg floatArg bytesResult | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #bytesResult declareC: 'unsigned char *bytesResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) ~= intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (wordsRcvr at: i) ~= floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) ~= intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. bytesResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| bytesResult at: i put: (floatsRcvr at: i) ~= floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 17:49'! primitiveNotByteArray | length rcvrOop rcvrArray | self export: true. self inline: true. self var: #rcvrArray declareC: 'unsigned char *rcvrArray'. rcvrOop _ interpreterProxy stackValue: 0. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isBytes: rcvrOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy failed ifTrue:[^nil]. rcvrArray _ interpreterProxy firstIndexableField: rcvrOop. 0 to: length-1 do:[:i| (rcvrArray at: i) = 0 ifTrue: [ rcvrArray at: i put: 1 ] ifFalse: [ rcvrArray at: i put: 0 ]. ]. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 1/19/2006 20:17'! primitiveOrByteArray | length rcvrOop otherOop otherArray rcvrArray length1 length2 | self export: true. self inline: true. self var: #rcvrArray declareC: 'unsigned char *rcvrArray'. self var: #otherArray declareC: 'unsigned char *otherArray'. otherOop _ interpreterProxy stackObjectValue: 0. rcvrOop _ interpreterProxy stackValue: 1. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isBytes: rcvrOop). interpreterProxy success: (interpreterProxy isBytes: otherOop). interpreterProxy failed ifTrue:[^nil]. length1 _ interpreterProxy stSizeOf: rcvrOop. length2 _ interpreterProxy stSizeOf: otherOop. interpreterProxy failed ifTrue:[^nil]. length _ length1. length1 > length2 ifTrue: [ length _ length2. ]. otherArray _ interpreterProxy firstIndexableField: otherOop. rcvrArray _ interpreterProxy firstIndexableField: rcvrOop. 0 to: length-1 do:[:i| rcvrArray at: i put: (((rcvrArray at: i) + (otherArray at: i)) > 0). ]. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 1/21/2006 00:21'! primitiveRemArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr wordRcvr wordArg wordResult floatArg floatResult floatRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. self var: #floatResult declareC: 'double floatResult'. self var: #wordResult declareC: 'unsigned int wordResult'. self var: #floatRcvr declareC: 'double floatRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #wordRcvr declareC: 'unsigned int wordRcvr'. self var: #wordArg declareC: 'unsigned int wordArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordRcvr _ (wordsRcvr at: i). wordArg _ (wordsArg at: i). wordResult _ wordRcvr \\ wordArg. "In this primitive, words are supposed to be unsigned." wordsResult at: i put: wordResult. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordRcvr _ wordsRcvr at: i. floatArg _ floatsArg at: i. floatResult _ wordRcvr / floatArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: wordRcvr - (floatResult * floatArg). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatRcvr _ floatsRcvr at: i. wordArg _ wordsArg at: i. floatResult _ floatRcvr / wordArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: (floatRcvr - (floatResult * wordArg)). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatRcvr _ floatsRcvr at: i. floatArg _ floatsArg at: i. floatResult _ floatRcvr / floatArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: (floatRcvr - (floatResult * floatArg)). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 1/21/2006 00:21'! primitiveRemScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg wordRcvr floatResult floatRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. self var: #floatResult declareC: 'double floatResult'. self var: #wordResult declareC: 'unsigned int wordResult'. self var: #floatRcvr declareC: 'double floatRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #wordRcvr declareC: 'unsigned int wordRcvr'. self var: #wordArg declareC: 'unsigned int wordArg'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) \\ intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordRcvr _ wordsRcvr at: i. floatResult _ wordRcvr / floatArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: wordRcvr - (floatResult * floatArg). ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatRcvr _ floatsRcvr at: i. floatResult _ floatRcvr / intArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: floatRcvr - (floatResult * intArg). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatRcvr _ floatsRcvr at: i. floatResult _ floatRcvr / floatArg. floatResult _ self cCode: 'floor(floatResult)' inSmalltalk: [floatResult floor]. floatsResult at: i put: floatRcvr - (floatResult * floatArg). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveSubArrays | length resultOop argOop rcvrOop isArgWords isRcvrWords wordsRcvr wordsArg wordsResult floatsArg floatsResult floatsRcvr | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #wordsArg declareC: 'unsigned int *wordsArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatsArg declareC: 'float *floatsArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackObjectValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: argOop). interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: argOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgWords _ interpreterProxy is: argOop MemberOf: 'WordArray'. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgWords & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgWords ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) - (wordsArg at: i). ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) - (floatsArg at: i). ]. ]. ] ifFalse: [ isArgWords ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. wordsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - (wordsArg at: i). ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatsArg _ interpreterProxy firstIndexableField: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - (floatsArg at: i). ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'array arithmetic' stamp: 'yo 10/13/2005 01:28'! primitiveSubScalar | length resultOop argOop rcvrOop isRcvrWords wordsRcvr wordsResult floatsResult floatsRcvr isArgInt intArg floatArg | self export: true. self inline: true. self var: #wordsRcvr declareC: 'unsigned int *wordsRcvr'. self var: #intArg declareC: 'int intArg'. self var: #wordsResult declareC: 'unsigned int *wordsResult'. self var: #floatsRcvr declareC: 'float *floatsRcvr'. self var: #floatArg declareC: 'double floatArg'. self var: #floatsResult declareC: 'float *floatsResult'. resultOop _ interpreterProxy stackObjectValue: 0. argOop _ interpreterProxy stackValue: 1. rcvrOop _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvrOop). interpreterProxy success: (interpreterProxy isWords: resultOop). interpreterProxy failed ifTrue:[^nil]. length _ interpreterProxy stSizeOf: rcvrOop. interpreterProxy success: (length = (interpreterProxy stSizeOf: resultOop)). interpreterProxy failed ifTrue:[^nil]. isArgInt _ interpreterProxy isIntegerObject: argOop. isRcvrWords _ interpreterProxy is: rcvrOop MemberOf: 'WordArray'. isArgInt & isRcvrWords ifTrue: [ (interpreterProxy is: resultOop MemberOf: 'WordArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ] ifFalse: [ (interpreterProxy is: resultOop MemberOf: 'KedamaFloatArray') ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. isRcvrWords ifTrue: [ isArgInt ifTrue: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. wordsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| wordsResult at: i put: (wordsRcvr at: i) - intArg. ]. ] ifFalse: [ wordsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (wordsRcvr at: i) - floatArg. ]. ]. ] ifFalse: [ isArgInt ifTrue: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. intArg _ interpreterProxy integerValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - intArg. ]. ] ifFalse: [ floatsRcvr _ interpreterProxy firstIndexableField: rcvrOop. floatArg _ interpreterProxy floatValueOf: argOop. floatsResult _ interpreterProxy firstIndexableField: resultOop. 0 to: length-1 do:[:i| floatsResult at: i put: (floatsRcvr at: i) - floatArg. ]. ]. ]. interpreterProxy pop: 4. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! degreesFromX: x y: y | tanVal theta | self inline: true. self returnTypeC: 'double'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'tanVal' declareC: 'double tanVal'. self var: 'theta' declareC: 'double theta'. x = 0.0 ifTrue: [ y >= 0.0 ifTrue: [^ 90.0] ifFalse: [^ 270.0]. ] ifFalse: [ tanVal _ y / x. theta _ self cCode: 'atan(tanVal)' inSmalltalk: [tanVal arcTan]. x >= 0.0 ifTrue: [ y >= 0.0 ifTrue: [^ theta / 0.0174532925199433] ifFalse: [^ 360.0 + (theta / 0.0174532925199433)] ] ifFalse: [ ^ 180.0 + (theta / 0.0174532925199433) ] ]. ^ 0.0. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! degreesToRadians: degrees | headingRadians deg q | self inline: true. self returnTypeC: 'double'. self var: 'degrees' declareC: 'double degrees'. self var: 'deg' declareC: 'double deg'. self var: 'headingRadians' declareC: 'double headingRadians'. self var: 'q' declareC: 'int q'. deg _ 90.0 - degrees. q _ deg / 360.0. deg < 0.0 ifTrue: [q _ q - 1]. headingRadians _ (deg - (q * 360.0)) * 0.0174532925199433. ^ headingRadians. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! drawTurtlesInArray | visibleArray colorArray yArray xArray destHeight destWidth destBits size x y visible visibleOop colorOop yOop xOop destOop bitsIndex | self export: true. self inline: true. self var: 'destBits' declareC: 'unsigned int *destBits'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'colorArray' declareC: 'unsigned int *colorArray'. self var: 'visibleArray' declareC: 'unsigned char *visibleArray'. visibleOop _ interpreterProxy stackValue: 0. colorOop _ interpreterProxy stackValue: 1. yOop _ interpreterProxy stackValue: 2. xOop _ interpreterProxy stackValue: 3. destHeight _ interpreterProxy stackIntegerValue: 4. destWidth _ interpreterProxy stackIntegerValue: 5. destOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: destOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: colorOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isBytes: visibleOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (destHeight * destWidth) ~= (interpreterProxy slotSizeOf: destOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: colorOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: visibleOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. colorArray _ interpreterProxy firstIndexableField: colorOop. visibleArray _ interpreterProxy firstIndexableField: visibleOop. destBits _ interpreterProxy firstIndexableField: destOop. 0 to: size - 1 do: [:i | x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. visible _ (visibleArray at: i). ((visible ~= 0) and: [((x >= 0) and: [y >= 0]) and: [(x < destWidth) and: [y < destHeight]]]) ifTrue: [ bitsIndex _ ((y * destWidth) + x). destBits at: bitsIndex put: (colorArray at: i). ] ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! getHeadingArrayInto | resultOop headingOop size headingArray resultArray heading | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'resultArray' declareC: 'float *resultArray'. self var: 'heading' declareC: 'double heading'. resultOop _ interpreterProxy stackValue: 0. headingOop _ interpreterProxy stackValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: headingOop. (interpreterProxy slotSizeOf: resultOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. resultArray _ interpreterProxy firstIndexableField: resultOop. 0 to: size - 1 do: [:i | heading _ headingArray at: i. heading _ heading / 0.0174532925199433. heading _ 90.0 - heading. heading > 0.0 ifFalse: [heading _ heading + 360.0]. resultArray at: i put: heading. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 2. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! getScalarHeading | headingOop headingArray heading index | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'heading' declareC: 'double heading'. headingOop _ interpreterProxy stackValue: 0. index _ interpreterProxy stackIntegerValue: 1. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) < index ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. heading _ headingArray at: index - 1. heading _ self radiansToDegrees: heading. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 3. interpreterProxy pushFloat: heading. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! initialiseModule self export: true. kedamaRandomSeed _ 17. randA := 16r000041A7. " magic constant = 16807 " randM := 16r7FFFFFFF. " magic constant = 2147483647 " randQ := randM // randA. randR := randM \\ randA. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! kedamaRandom2: range | lo hi r v val | self inline: true. range < 0 ifTrue: [r _ 0 - range] ifFalse: [r _ range]. hi _ kedamaRandomSeed // randQ. lo _ kedamaRandomSeed \\ randQ. kedamaRandomSeed _ (randA * lo) - (randR * hi). v _ kedamaRandomSeed bitAnd: 65535. val _ (v * (r + 1)) >> 16. range < 0 ifTrue: [^ 0 - val] ifFalse: [^ val]. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! kedamaRandom: range | r val | self inline: true. range < 0 ifTrue: [r _ 0 - range] ifFalse: [r _ range]. kedamaRandomSeed _ ((kedamaRandomSeed * 1309) + 13849) bitAnd: 65535. val _ (kedamaRandomSeed * (r + 1)) >> 16. range < 0 ifTrue: [^ 0 - val] ifFalse: [^ val]. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! kedamaSetRandomSeed | seed | self inline: true. self export: true. seed _ interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue: [^ nil]. kedamaRandomSeed _ seed bitAnd: 65536. interpreterProxy pop: 1. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! makeMask | shiftAmount pixel maskBits dataBits dataSize maskSize dOrigin mOrigin data alpha highMask | self export: true. self inline: true. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. self var: 'mOrigin' declareC: 'unsigned int* mOrigin'. self var: 'highMask' declareC: 'unsigned int highMask'. self var: 'alpha' declareC: 'unsigned int alpha'. self var: 'pixel' declareC: 'unsigned int pixel'. shiftAmount _ interpreterProxy stackIntegerValue: 0. pixel _ interpreterProxy stackIntegerValue: 1. maskBits _ interpreterProxy stackValue: 2. dataBits _ interpreterProxy stackValue: 3. interpreterProxy failed ifTrue: [^ nil]. dataSize _ interpreterProxy slotSizeOf: dataBits. maskSize _ interpreterProxy slotSizeOf: maskBits. dataSize = maskSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. shiftAmount < -32 ifTrue: [interpreterProxy primitiveFail. ^ nil]. shiftAmount > 8 ifTrue: [interpreterProxy primitiveFail. ^ nil]. dOrigin _ interpreterProxy firstIndexableField: dataBits. mOrigin _ interpreterProxy firstIndexableField: maskBits. highMask _ 16rFF000000. 0 to: dataSize -1 do: [:i | data _ dOrigin at: i. alpha _ data bitShift: shiftAmount. (alpha > 255) ifTrue: [alpha _ 255]. (alpha < 0) ifTrue: [alpha _ 0]. mOrigin at: i put: (((alpha << 24) bitAnd: highMask) bitOr: pixel). ]. interpreterProxy pop: 4. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! makeMaskLog | max pixel maskBits dataBits dataSize maskSize dOrigin mOrigin data alpha highMask maxLog maxOop maxFirst | self export: true. self inline: true. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. self var: 'mOrigin' declareC: 'unsigned int* mOrigin'. self var: 'highMask' declareC: 'unsigned int highMask'. self var: 'maxFirst' declareC: 'unsigned int* maxFirst'. self var: 'max' declareC: 'unsigned int max'. self var: 'alpha' declareC: 'unsigned int alpha'. self var: 'pixel' declareC: 'unsigned int pixel'. self var: 'maxLog' declareC: 'double maxLog'. maxOop _ interpreterProxy stackValue: 0. pixel _ interpreterProxy stackIntegerValue: 1. maskBits _ interpreterProxy stackValue: 2. dataBits _ interpreterProxy stackValue: 3. interpreterProxy failed ifTrue: [^ nil]. maxFirst _ (interpreterProxy firstIndexableField: maxOop). max _ maxFirst at: 0. interpreterProxy failed ifTrue: [^ nil]. maxLog _ self cCode: 'log(max)' inSmalltalk: [max ln]. dataSize _ interpreterProxy slotSizeOf: dataBits. maskSize _ interpreterProxy slotSizeOf: maskBits. dataSize = maskSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. dOrigin _ interpreterProxy firstIndexableField: dataBits. mOrigin _ interpreterProxy firstIndexableField: maskBits. highMask _ 16rFF000000. 0 to: dataSize -1 do: [:i | data _ dOrigin at: i. data = 0 ifTrue: [alpha _ 0] ifFalse: [ alpha _ ((255.0 / maxLog) * (self cCode: 'log(data)' inSmalltalk: [data ln])) asInteger. ]. (alpha > 255) ifTrue: [alpha _ 255]. mOrigin at: i put: (((alpha << 24) bitAnd: highMask) bitOr: pixel). ]. interpreterProxy pop: 4. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! makeTurtlesMap | height width yOop xOop whoOop mapOop size xArray yArray whoArray map x y mapIndex | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'whoArray' declareC: 'unsigned int *whoArray'. self var: 'map' declareC: 'unsigned int *map'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. yOop _ interpreterProxy stackValue: 2. xOop _ interpreterProxy stackValue: 3. whoOop _ interpreterProxy stackValue: 4. mapOop _ interpreterProxy stackValue: 5. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: whoOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: mapOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: whoOop. (interpreterProxy slotSizeOf: xOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: mapOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. whoArray _ interpreterProxy firstIndexableField: whoOop. map _ interpreterProxy firstIndexableField: mapOop. 0 to: (height * width) - 1 do: [:index | map at: index put: 0. ]. 0 to: size - 1 do: [:index | x _ xArray at: index. y _ yArray at: index. mapIndex _ (width * y) + x. (mapIndex >= 0 and: [mapIndex < (height * width)]) ifTrue: [ map at: mapIndex put: (whoArray at: index). ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! primPixelAtXY | height width yPos xPos bitsOop x y bits index ret | self export: true. self inline: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xPos' declareC: 'double xPos'. self var: 'yPos' declareC: 'double yPos'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. yPos _ interpreterProxy stackFloatValue: 2. xPos _ interpreterProxy stackFloatValue: 3. bitsOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. x _ xPos. y _ yPos. bits _ interpreterProxy firstIndexableField: bitsOop. ((x >= 0) & (x < width) & (y >= 0) & (y < height)) ifTrue: [ index _ y * width + x. ret _ bits at: index. ] ifFalse: [ ret _ 0. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy pushInteger: ret. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! primPixelAtXYPut | height width value yPos xPos bitsOop x y v bits index | self export: true. self inline: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xPos' declareC: 'double xPos'. self var: 'yPos' declareC: 'double yPos'. height _ interpreterProxy stackIntegerValue: 0. width _ interpreterProxy stackIntegerValue: 1. value _ interpreterProxy stackIntegerValue: 2. yPos _ interpreterProxy stackFloatValue: 3. xPos _ interpreterProxy stackFloatValue: 4. bitsOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. x _ xPos. y _ yPos. v _ value. v > 16r3FFFFFFF ifTrue: [ v _ 16r3FFFFFFF. ]. v < 0 ifTrue: [ v _ 0. ]. bits _ interpreterProxy firstIndexableField: bitsOop. ((x >= 0) & (x < width) & (y >= 0) & (y < height)) ifTrue: [ index _ y * width + x. bits at: index put: v. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! primPixelsAtXY | yArray xArray bitsHeight bitsWidth bitsOop bits size x y bitsIndex destWordsOop yArrayOop xArrayOop destWords | self export: true. self inline: true. self var: 'destWords' declareC: 'unsigned int *destWords'. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. destWordsOop _ interpreterProxy stackValue: 0. bitsHeight _ interpreterProxy stackIntegerValue: 1. bitsWidth _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. yArrayOop _ interpreterProxy stackValue: 4. xArrayOop _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: destWordsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (bitsHeight * bitsWidth) ~= (interpreterProxy slotSizeOf: bitsOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xArrayOop. (interpreterProxy slotSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: destWordsOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. destWords _ interpreterProxy firstIndexableField: destWordsOop. bits _ interpreterProxy firstIndexableField: bitsOop. 0 to: size - 1 do: [:i | x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. (((x >= 0) and: [y >= 0]) and: [(x < bitsWidth) and: [y < bitsHeight]]) ifTrue: [ bitsIndex _ ((y * bitsWidth) + x). destWords at: i put: (bits at: bitsIndex). ] ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! primScalarForward | bottomEdgeMode topEdgeMode rightEdgeMode leftEdgeMode destHeight destWidth headingOop yOop xOop size xArray yArray headingArray val dist newX newY index i | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'dist' declareC: 'double dist'. self var: 'newX' declareC: 'double newX'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. rightEdgeMode _ interpreterProxy stackIntegerValue: 2. leftEdgeMode _ interpreterProxy stackIntegerValue: 3. destHeight _ interpreterProxy stackFloatValue: 4. destWidth _ interpreterProxy stackFloatValue: 5. val _ interpreterProxy stackFloatValue: 6. headingOop _ interpreterProxy stackValue: 7. yOop _ interpreterProxy stackValue: 8. xOop _ interpreterProxy stackValue: 9. index _ interpreterProxy stackIntegerValue: 10. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. dist _ val. i _ index - 1. newX _ (xArray at: i) + (dist * (headingArray at: i) cos). newY _ (yArray at: i) - (dist * (headingArray at: i) sin). self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 11. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 1/20/2006 14:02'! primSetPixelsAtXY | yArray xArray bitsHeight bitsWidth bitsOop bits size x y bitsIndex yArrayOop xArrayOop valueOop isValueInt isValueWordArray intValue wordsValue value pArrayOop pArray floatsValue fv | self export: true. self inline: true. self var: 'intValue' declareC: 'unsigned int intValue'. self var: 'wordsValue' declareC: 'unsigned int *wordsValue'. self var: 'floatsValue' declareC: 'float *floatsValue'. self var: 'value' declareC: 'unsigned int value'. self var: 'floatValue' declareC: 'float floatValue'. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'pArray' declareC: 'unsigned char *pArray'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. valueOop _ interpreterProxy stackValue: 0. bitsHeight _ interpreterProxy stackIntegerValue: 1. bitsWidth _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. yArrayOop _ interpreterProxy stackValue: 4. xArrayOop _ interpreterProxy stackValue: 5. pArrayOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: pArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (bitsHeight * bitsWidth) ~= (interpreterProxy slotSizeOf: bitsOop) ifTrue: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xArrayOop. (interpreterProxy slotSizeOf: pArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. pArray _ interpreterProxy firstIndexableField: pArrayOop. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isValueInt _ interpreterProxy isIntegerObject: valueOop. isValueInt ifTrue: [ intValue _ interpreterProxy integerValueOf: valueOop. value _ intValue. ] ifFalse: [ (interpreterProxy slotSizeOf: valueOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValueWordArray _ (interpreterProxy is: valueOop MemberOf: 'WordArray'). isValueWordArray ifTrue: [ wordsValue _ interpreterProxy firstIndexableField: valueOop. ] ifFalse: [ floatsValue _ interpreterProxy firstIndexableField: valueOop. ]. ]. bits _ interpreterProxy firstIndexableField: bitsOop. 0 to: size - 1 do: [:i | (pArray at: i) = 1 ifTrue: [ x _ self cCoerce: (xArray at: i) to: 'int'. self cCode: '' inSmalltalk: [x _ x asInteger]. y _ self cCoerce: (yArray at: i) to: 'int'. self cCode: '' inSmalltalk: [y _ y asInteger]. (((x >= 0) and: [y >= 0]) and: [(x < bitsWidth) and: [y < bitsHeight]]) ifTrue: [ bitsIndex _ ((y * bitsWidth) + x). isValueInt ifFalse: [ isValueWordArray ifTrue: [ bits at: bitsIndex put: (wordsValue at: i). ] ifFalse: [ fv _ floatsValue at: i. self cCode: '' inSmalltalk: [fv _ fv asInteger]. bits at: bitsIndex put: fv. ]. ] ifTrue: [ bits at: bitsIndex put: value. ]. ] ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 15:47'! primTurtlesForward | bottomEdgeMode topEdgeMode rightEdgeMode leftEdgeMode destHeight destWidth valOop headingOop yOop xOop isValVector size xArray yArray headingArray valArray val dist newX newY pOop pArray | self export: true. self inline: true. self var: 'pArray' declareC: 'unsigned char *pArray'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'dist' declareC: 'double dist'. self var: 'newX' declareC: 'double newX'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. rightEdgeMode _ interpreterProxy stackIntegerValue: 2. leftEdgeMode _ interpreterProxy stackIntegerValue: 3. destHeight _ interpreterProxy stackFloatValue: 4. destWidth _ interpreterProxy stackFloatValue: 5. valOop _ interpreterProxy stackValue: 6. headingOop _ interpreterProxy stackValue: 7. yOop _ interpreterProxy stackValue: 8. xOop _ interpreterProxy stackValue: 9. pOop _ interpreterProxy stackValue: 10. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: pOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false. ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: yOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: pOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. pArray _ interpreterProxy firstIndexableField: pOop. xArray _ interpreterProxy firstIndexableField: xOop. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ valArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size -1 do: [:i | (pArray at: i) = 1 ifTrue: [ isValVector ifTrue: [ dist _ valArray at: i. ] ifFalse: [ dist _ val. ]. newX _ (xArray at: i) + (dist * (headingArray at: i) cos). newY _ (yArray at: i) - (dist * (headingArray at: i) sin). self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 11. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! primUpHill | sniffRange height width bitsOop tH tY tX bits turtleX turtleY startX endX startY endY maxVal maxValX rowOffset thisVal maxValY ret | self inline: true. self export: true. self var: 'bits' declareC: 'unsigned int *bits'. self var: 'tX' declareC: 'double tX'. self var: 'tY' declareC: 'double tY'. self var: 'tH' declareC: 'double tH'. sniffRange _ interpreterProxy stackIntegerValue: 0. height _ interpreterProxy stackIntegerValue: 1. width _ interpreterProxy stackIntegerValue: 2. bitsOop _ interpreterProxy stackValue: 3. tH _ interpreterProxy stackFloatValue: 4. tY _ interpreterProxy stackFloatValue: 5. tX _ interpreterProxy stackFloatValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: bitsOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: bitsOop) ~= (height * width) ifTrue: [interpreterProxy primitiveFail. ^ nil]. bits _ interpreterProxy firstIndexableField: bitsOop. turtleX _ self cCode: 'tX' inSmalltalk: [tX asInteger]. turtleY _ self cCode: 'tY' inSmalltalk: [tY asInteger]. turtleX _ turtleX max: 0. turtleY _ turtleY max: 0. turtleX _ turtleX min: width - 1. turtleY _ turtleY min: height - 1. startX _ turtleX - sniffRange max: 0. endX _ (turtleX + sniffRange) min: (width - 1). startY _ (turtleY - sniffRange) max: 0. endY _ (turtleY + sniffRange) min: (height - 1). maxVal _ bits at: turtleY * width + turtleX. maxValX _ -1. startY to: endY do: [:y | rowOffset _ y * width. startX to: endX do: [:x | thisVal _ bits at: rowOffset + x. thisVal > maxVal ifTrue: [ maxValX _ x. maxValY _ y. maxVal _ thisVal ]. ]. ]. -1 = maxValX ifTrue: [ret _ self radiansToDegrees: tH] ifFalse: [ ret _ (self degreesFromX: (self cCoerce: maxValX - turtleX to: 'double') y: (self cCoerce: maxValY - turtleY to: 'double')) + 90.0. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 8. interpreterProxy pushFloat: ret. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! radiansToDegrees: radians | deg degrees | self inline: true. self returnTypeC: 'double'. self var: 'degrees' declareC: 'double degrees'. self var: 'deg' declareC: 'double deg'. self var: 'radians' declareC: 'double radians'. self var: 'headingRadians' declareC: 'double headingRadians'. degrees _ radians / 0.0174532925199433. deg _ 90.0 - degrees. deg > 0.0 ifFalse: [deg _ deg + 360.0]. ^ deg. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! randomIntoFloatArray | range factor floatArrayOop to from size floatArray | self export: true. self inline: true. self var: 'factor' declareC: 'double factor'. self var: 'floatArray' declareC: 'float *floatArray'. factor _ interpreterProxy stackFloatValue: 0. floatArrayOop _ interpreterProxy stackValue: 1. to _ interpreterProxy stackIntegerValue: 2. from _ interpreterProxy stackIntegerValue: 3. range _ interpreterProxy stackIntegerValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: floatArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: floatArrayOop. (size >= to and: [from >= 1 and: [to >= from]]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. floatArray _ interpreterProxy firstIndexableField: floatArrayOop. interpreterProxy failed ifTrue: [^ nil]. from to: to do: [:index | floatArray at: index-1 put: (self cCoerce: (self kedamaRandom2: range) to: 'double') * factor. ]. interpreterProxy pop: 5. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! randomIntoIntegerArray | range factor integerArrayOop to from size integerArray | self export: true. self inline: true. self var: 'factor' declareC: 'double factor'. self var: 'integerArray' declareC: 'unsigned int *integerArray'. factor _ interpreterProxy stackFloatValue: 0. integerArrayOop _ interpreterProxy stackValue: 1. to _ interpreterProxy stackIntegerValue: 2. from _ interpreterProxy stackIntegerValue: 3. range _ interpreterProxy stackIntegerValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: integerArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: integerArrayOop. (size >= to and: [from >= 1 and: [to >= from]]) ifFalse: [interpreterProxy primitiveFail. ^ nil]. integerArray _ interpreterProxy firstIndexableField: integerArrayOop. interpreterProxy failed ifTrue: [^ nil]. from to: to do: [:index | integerArray at: index-1 put: (self cCoerce: ((self cCoerce: (self kedamaRandom2: range) to: 'double') * factor) to: 'int'). ]. interpreterProxy pop: 5. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! randomRange | range ret | self export: true. self inline: true. range _ interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue: [^ nil]. ret _ self kedamaRandom2: range. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 2. interpreterProxy pushInteger: ret. ^ self. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! scalarGetAngleTo | fromY fromX toY toX x y r | self export: true. self inline: true. self var: 'toX' declareC: 'double toX'. self var: 'toY' declareC: 'double toY'. self var: 'fromX' declareC: 'double fromX'. self var: 'fromY' declareC: 'double fromY'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'r' declareC: 'double r'. fromY _ interpreterProxy stackFloatValue: 0. fromX _ interpreterProxy stackFloatValue: 1. toY _ interpreterProxy stackFloatValue: 2. toX _ interpreterProxy stackFloatValue: 3. interpreterProxy failed ifTrue: [^ nil]. x _ toX - fromX. y _ toY - fromY. r _ self degreesFromX: x y: y. r _ r + 90.0. r > 360.0 ifTrue: [r _ r - 360.0]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 5. interpreterProxy pushFloat: r. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! scalarGetDistanceTo | fromY fromX toY toX x y r | self export: true. self inline: true. self var: 'toX' declareC: 'double toX'. self var: 'toY' declareC: 'double toY'. self var: 'fromX' declareC: 'double fromX'. self var: 'fromY' declareC: 'double fromY'. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'r' declareC: 'double r'. fromY _ interpreterProxy stackFloatValue: 0. fromX _ interpreterProxy stackFloatValue: 1. toY _ interpreterProxy stackFloatValue: 2. toX _ interpreterProxy stackFloatValue: 3. interpreterProxy failed ifTrue: [^ nil]. x _ fromX - toX. y _ fromY - toY. r _ ((x * x) + (y * y)) sqrt. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 5. interpreterProxy pushFloat: r. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! scalarXAt: index xArray: xArray headingArray: headingArray value: val destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode | newX headingRadians | self inline: true. self var: 'xArray' declareC: 'float* xArray'. self var: 'headingArray' declareC: 'float* headingArray'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'val' declareC: 'double val'. self var: 'newX' declareC: 'double newX'. self var: 'headingRadians' declareC: 'double headingRadians'. newX _ val. newX < 0.0 ifTrue: [ leftEdgeMode = 1 ifTrue: [ "wrap" newX _ newX + destWidth. ]. leftEdgeMode = 2 ifTrue: [ "stick" newX _ 0.0. ]. leftEdgeMode = 3 ifTrue: [ "bounce" newX _ 0.0 - newX. headingRadians _ headingArray at: index. headingRadians < 3.141592653589793 ifTrue: [headingArray at: index put: 3.141592653589793 - headingRadians] ifFalse: [headingArray at: index put: 9.42477796076938 - headingRadians]. ]. ]. newX >= destWidth ifTrue: [ rightEdgeMode = 1 ifTrue: [ newX _ newX - destWidth. ]. rightEdgeMode = 2 ifTrue: [ newX _ destWidth - 0.000001. ]. rightEdgeMode = 3 ifTrue: [ newX _ (destWidth - 0.000001) - (newX - destWidth). headingRadians _ headingArray at: index. headingRadians < 3.141592653589793 ifTrue: [headingArray at: index put: (3.141592653589793 - headingRadians)] ifFalse: [headingArray at: index put: (9.42477796076938 - headingRadians)]. ] ]. xArray at: index put: newX. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! scalarYAt: index yArray: yArray headingArray: headingArray value: val destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode | newY | self inline: true. self var: 'yArray' declareC: 'float* yArray'. self var: 'headingArray' declareC: 'float* headingArray'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'val' declareC: 'double val'. self var: 'newY' declareC: 'double newY'. newY _ val. newY < 0.0 ifTrue: [ topEdgeMode = 1 ifTrue: [ "wrap" newY _ newY + destHeight. ]. topEdgeMode = 2 ifTrue: [ "stick" newY _ 0.0. ]. topEdgeMode = 3 ifTrue: [ "bounce" newY _ 0.0 - newY. headingArray at: index put: (6.283185307179586 - (headingArray at: index)). ]. ]. newY >= destHeight ifTrue: [ bottomEdgeMode = 1 ifTrue: [ newY _ newY - destHeight. ]. bottomEdgeMode = 2 ifTrue: [ newY _ destHeight - 0.000001. ]. bottomEdgeMode = 3 ifTrue: [ newY _ (destHeight - 0.000001) - (newY - destHeight). headingArray at: index put: (6.283185307179586 - (headingArray at: index)). ] ]. yArray at: index put: newY. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 15:03'! setHeadingArrayFrom | resultOop headingOop size headingArray resultArray heading isValVector pOop pArray | self export: true. self inline: true. self var: 'pArray' declareC: 'unsigned char *pArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'resultArray' declareC: 'float *resultArray'. self var: 'heading' declareC: 'double heading'. resultOop _ interpreterProxy stackValue: 0. headingOop _ interpreterProxy stackValue: 1. pOop _ interpreterProxy stackValue: 2. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: pOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: headingOop. (interpreterProxy isFloatObject: resultOop) ifTrue: [ isValVector _ false. ] ifFalse: [ (interpreterProxy isWords: resultOop) ifTrue: [ (interpreterProxy slotSizeOf: resultOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector _ true ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. pArray _ interpreterProxy firstIndexableField: pOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ resultArray _ interpreterProxy firstIndexableField: resultOop. ] ifFalse: [ heading _ interpreterProxy floatValueOf: resultOop. heading _ self degreesToRadians: heading. ]. 0 to: size - 1 do: [:i | (pArray at: i) = 1 ifTrue: [ isValVector ifTrue: [ heading _ resultArray at: i. heading _ self degreesToRadians: heading. ]. headingArray at: i put: heading. ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 3. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! setScalarHeading | headingOop headingArray heading index | self export: true. self inline: true. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'heading' declareC: 'double heading'. heading _ interpreterProxy stackFloatValue: 0. headingOop _ interpreterProxy stackValue: 1. index _ interpreterProxy stackIntegerValue: 2. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) < index ifTrue: [interpreterProxy primitiveFail. ^ nil]. headingArray _ interpreterProxy firstIndexableField: headingOop. headingArray at: index - 1 put: (self degreesToRadians: heading). interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 3. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! shutdownModule self export: true. ^ true. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! turtleScalarSetX | xArray headingArray val destWidth xOop headingOop leftEdgeMode rightEdgeMode xIndex size | self export: true. self inline: true. self var: 'xArray' declareC: 'float *xArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destWidth' declareC: 'double destWidth'. rightEdgeMode _ interpreterProxy stackIntegerValue: 0. leftEdgeMode _ interpreterProxy stackIntegerValue: 1. destWidth _ interpreterProxy stackFloatValue: 2. val _ interpreterProxy stackFloatValue: 3. headingOop _ interpreterProxy stackValue: 4. xIndex _ interpreterProxy stackIntegerValue: 5. xOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. xArray _ interpreterProxy firstIndexableField: xOop. headingArray _ interpreterProxy firstIndexableField: headingOop. self scalarXAt: xIndex - 1 xArray: xArray headingArray: headingArray value: val destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! turtleScalarSetY | yArray headingArray val destHeight yOop headingOop size yIndex topEdgeMode bottomEdgeMode | self export: true. self inline: true. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. destHeight _ interpreterProxy stackFloatValue: 2. val _ interpreterProxy stackFloatValue: 3. headingOop _ interpreterProxy stackValue: 4. yIndex _ interpreterProxy stackIntegerValue: 5. yOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy slotSizeOf: yOop. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. self scalarYAt: yIndex - 1 yArray: yArray headingArray: headingArray value: val destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 1/20/2006 22:05'! turtlesSetX | xArray headingArray valArray val destWidth xOop headingOop valOop leftEdgeMode rightEdgeMode isValVector size newX pOop pArray isWordVector wordValArray | self export: true. self inline: true. self var: 'pArray' declareC: 'unsigned char *pArray'. self var: 'xArray' declareC: 'float *xArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'wordValArray' declareC: 'unsigned int *wordValArray'. self var: 'val' declareC: 'double val'. self var: 'destWidth' declareC: 'double destWidth'. self var: 'newX' declareC: 'double newX'. rightEdgeMode _ interpreterProxy stackIntegerValue: 0. leftEdgeMode _ interpreterProxy stackIntegerValue: 1. destWidth _ interpreterProxy stackFloatValue: 2. valOop _ interpreterProxy stackValue: 3. headingOop _ interpreterProxy stackValue: 4. xOop _ interpreterProxy stackValue: 5. pOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: pOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true. isWordVector _ interpreterProxy is: valOop MemberOf: 'WordArray'. ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: xOop. (interpreterProxy slotSizeOf: pOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. pArray _ interpreterProxy firstIndexableField: pOop. xArray _ interpreterProxy firstIndexableField: xOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ isWordVector ifTrue: [ wordValArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ valArray _ interpreterProxy firstIndexableField: valOop. ]. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size - 1 do: [:i | (pArray at: i) = 1 ifTrue: [ isValVector ifTrue: [ isWordVector ifTrue: [ newX _ wordValArray at: i. self cCode: '' inSmalltalk: [newX _ newX asFloat]. ] ifFalse: [ newX _ valArray at: i. ]. ] ifFalse: [ newX _ val. ]. self scalarXAt: i xArray: xArray headingArray: headingArray value: newX destWidth: destWidth leftEdgeMode: leftEdgeMode rightEdgeMode: rightEdgeMode. ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 1/20/2006 22:03'! turtlesSetY | yArray headingArray valArray val destHeight yOop headingOop valOop topEdgeMode bottomEdgeMode isValVector size newY pOop pArray isWordVector wordValArray | self export: true. self inline: true. self var: 'pArray' declareC: 'unsigned char *pArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'headingArray' declareC: 'float *headingArray'. self var: 'valArray' declareC: 'float *valArray'. self var: 'wordValArray' declareC: 'unsigned int *wordValArray'. self var: 'val' declareC: 'double val'. self var: 'destHeight' declareC: 'double destHeight'. self var: 'newY' declareC: 'double newY'. bottomEdgeMode _ interpreterProxy stackIntegerValue: 0. topEdgeMode _ interpreterProxy stackIntegerValue: 1. destHeight _ interpreterProxy stackFloatValue: 2. valOop _ interpreterProxy stackValue: 3. headingOop _ interpreterProxy stackValue: 4. yOop _ interpreterProxy stackValue: 5. pOop _ interpreterProxy stackValue: 6. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isBytes: pOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: headingOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: valOop) ifTrue: [ isValVector _ false ] ifFalse: [ (interpreterProxy isWords: valOop) ifTrue: [ isValVector _ true. isWordVector _ interpreterProxy is: valOop MemberOf: 'WordArray'. ] ifFalse: [ interpreterProxy primitiveFail. ^ nil ]. ]. size _ interpreterProxy slotSizeOf: yOop. (interpreterProxy slotSizeOf: pOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy slotSizeOf: headingOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. isValVector ifTrue: [ (interpreterProxy slotSizeOf: valOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. pArray _ interpreterProxy firstIndexableField: pOop. yArray _ interpreterProxy firstIndexableField: yOop. headingArray _ interpreterProxy firstIndexableField: headingOop. isValVector ifTrue: [ isWordVector ifTrue: [ wordValArray _ interpreterProxy firstIndexableField: valOop. ] ifFalse: [ valArray _ interpreterProxy firstIndexableField: valOop. ]. ] ifFalse: [ val _ interpreterProxy floatValueOf: valOop ]. 0 to: size - 1 do: [:i | (pArray at: i) = 1 ifTrue: [ isValVector ifTrue: [ isWordVector ifTrue: [ newY _ wordValArray at: i. self cCode: '' inSmalltalk: [newY _ newY asFloat]. ] ifFalse: [ newY _ valArray at: i. ]. ] ifFalse: [ newY _ val. ]. self scalarYAt: i yArray: yArray headingArray: headingArray value: newY destHeight: destHeight topEdgeMode: topEdgeMode bottomEdgeMode: bottomEdgeMode. ]. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 7. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! vectorGetAngleTo | x y resultOop yArrayOop xArrayOop pYOop pXOop size isVector result xArray yArray pX pY ppx ppy r | self export: true. self inline: true. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'result' declareC: 'float *result'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'pX' declareC: 'float *pX'. self var: 'pY' declareC: 'float *pY'. self var: 'ppx' declareC: 'double ppx'. self var: 'ppy' declareC: 'double ppy'. resultOop _ interpreterProxy stackValue: 0. yArrayOop _ interpreterProxy stackValue: 1. xArrayOop _ interpreterProxy stackValue: 2. pYOop _ interpreterProxy stackValue: 3. pXOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: resultOop. size < 0 ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: xArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: pXOop) ifTrue: [ (interpreterProxy isFloatObject: pYOop) ifTrue: [isVector _ false] ifFalse: [interpreterProxy primitiveFail. ^ nil]. ] ifFalse: [ (interpreterProxy isFloatObject: pYOop) ifFalse: [isVector _ true] ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. isVector ifTrue: [ (interpreterProxy stSizeOf: pXOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: pYOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. result _ interpreterProxy firstIndexableField: resultOop. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isVector ifTrue: [ pX _ interpreterProxy firstIndexableField: pXOop. pY _ interpreterProxy firstIndexableField: pYOop. ]. isVector ifFalse: [ ppx _ interpreterProxy floatValueOf: pXOop. ppy _ interpreterProxy floatValueOf: pYOop. ]. 0 to: size - 1 do: [:index | isVector ifTrue: [ ppx _ pX at: index. ppy _ pY at: index. ]. x _ ppx - (xArray at: index). y _ ppy - (yArray at: index). r _ self degreesFromX: x y: y. r _ r + 90.0. r > 360.0 ifTrue: [r _ r - 360.0]. result at: index put: r. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! vectorGetDistanceTo | x y resultOop yArrayOop xArrayOop pYOop pXOop size isVector result xArray yArray pX pY ppx ppy | self export: true. self inline: true. self var: 'x' declareC: 'double x'. self var: 'y' declareC: 'double y'. self var: 'result' declareC: 'float *result'. self var: 'xArray' declareC: 'float *xArray'. self var: 'yArray' declareC: 'float *yArray'. self var: 'pX' declareC: 'float *pX'. self var: 'pY' declareC: 'float *pY'. self var: 'ppx' declareC: 'double ppx'. self var: 'ppy' declareC: 'double ppy'. resultOop _ interpreterProxy stackValue: 0. yArrayOop _ interpreterProxy stackValue: 1. xArrayOop _ interpreterProxy stackValue: 2. pYOop _ interpreterProxy stackValue: 3. pXOop _ interpreterProxy stackValue: 4. interpreterProxy failed ifTrue: [^ nil]. (interpreterProxy isWords: resultOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: xArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isWords: yArrayOop) ifFalse: [interpreterProxy primitiveFail. ^ nil]. size _ interpreterProxy stSizeOf: resultOop. size < 0 ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: xArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: yArrayOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy isFloatObject: pXOop) ifTrue: [ (interpreterProxy isFloatObject: pYOop) ifTrue: [isVector _ false] ifFalse: [interpreterProxy primitiveFail. ^ nil]. ] ifFalse: [ (interpreterProxy isFloatObject: pYOop) ifFalse: [isVector _ true] ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. isVector ifTrue: [ (interpreterProxy stSizeOf: pXOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. (interpreterProxy stSizeOf: pYOop) ~= size ifTrue: [interpreterProxy primitiveFail. ^ nil]. ]. result _ interpreterProxy firstIndexableField: resultOop. xArray _ interpreterProxy firstIndexableField: xArrayOop. yArray _ interpreterProxy firstIndexableField: yArrayOop. isVector ifTrue: [ pX _ interpreterProxy firstIndexableField: pXOop. pY _ interpreterProxy firstIndexableField: pYOop. ]. isVector ifFalse: [ ppx _ interpreterProxy floatValueOf: pXOop. ppy _ interpreterProxy floatValueOf: pYOop. ]. 0 to: size - 1 do: [:index | isVector ifTrue: [ ppx _ pX at: index. ppy _ pY at: index. ]. x _ ppx - (xArray at: index). y _ ppy - (yArray at: index). result at: index put: ((x * x) + (y * y)) sqrt. ]. interpreterProxy failed ifTrue: [^ nil]. interpreterProxy pop: 6. interpreterProxy push: resultOop. ! ! !KedamaPlugin2 methodsFor: 'primitives' stamp: 'yo 10/13/2005 01:28'! zoomBitmap | yFactor xFactor sHeight sWidth dst src srcSize dstSize sOrigin dOrigin srcIndex bit dstIndex srcOrigin | self export: true. self inline: true. self var: 'sOrigin' declareC: 'unsigned int* sOrigin'. self var: 'dOrigin' declareC: 'unsigned int* dOrigin'. yFactor _ interpreterProxy stackIntegerValue: 0. xFactor _ interpreterProxy stackIntegerValue: 1. sHeight _ interpreterProxy stackIntegerValue: 2. sWidth _ interpreterProxy stackIntegerValue: 3. dst _ interpreterProxy stackValue: 4. src _ interpreterProxy stackValue: 5. interpreterProxy failed ifTrue: [^ nil]. srcSize _ interpreterProxy slotSizeOf: src. dstSize _ interpreterProxy slotSizeOf: dst. (sWidth * sHeight) = srcSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. (srcSize * xFactor * yFactor) = dstSize ifFalse: [interpreterProxy primitiveFail. ^ nil]. sOrigin _ interpreterProxy firstIndexableField: src. dOrigin _ interpreterProxy firstIndexableField: dst. srcIndex _ 0. srcOrigin _ 0. dstIndex _ 0. 0 to: sHeight - 1 do: [:sy | 0 to: yFactor - 1 do: [:y | 0 to: sWidth - 1 do: [:sx | bit _ sOrigin at: srcIndex. srcIndex _ srcIndex + 1. 0 to: xFactor - 1 do: [:dummy | dOrigin at: dstIndex put: bit. dstIndex _ dstIndex + 1. ]. ]. srcIndex _ srcOrigin. ]. srcOrigin _ srcOrigin + sWidth. srcIndex _ srcOrigin. ]. interpreterProxy pop: 6. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! KedamaPlugin2 class instanceVariableNames: ''! !KedamaPlugin2 class methodsFor: 'as yet unclassified' stamp: 'yo 10/13/2005 01:29'! declareCVarsIn: cg cg var: #kedamaRandomSeed type: 'unsigned int'. cg var: #randA type: 'unsigned int'. cg var: #randM type: 'unsigned int'. cg var: #randQ type: 'unsigned int'. cg var: #randR type: 'unsigned int'. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/Info-SqueakLocalePlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable LocalePlugin CFBundleGetInfoString LocalePlugin for Squeak CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.LocalePlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName LocalePlugin for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.0.1b1 CFBundleSignature FAST CFBundleVersion 1.0.1b1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/LocalePlugin.proj.xml ================================================ ]> LocalePlugin UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::Squeak:SqueakAtSourceForge:squeak:platforms:Mac OS: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::Squeak:SqueakAtSourceForge:squeak:platforms: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameLocalePlugin OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000100013A53717565616B20332E382E38623220436C617373696300 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000010122D40100000000000010010123650 000200000000000000000000101227A000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileLocalePlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name InterfaceLib MacOS Library Debug Name MSL C.PPC.Lib MacOS Library Debug Name UTCUtils MacOS Library Debug Name LocalePlugin.c MacOS Text Debug Name sqMacLocaleOS9.c MacOS Text Debug Name sqMacLocaleOS9.h MacOS Text Name MSL RuntimePPC.Lib MacOS Library Debug Name MathLib MacOS Library Debug Name LocalesLib MacOS Library Debug Name InterfaceLib MacOS Name MSL C.PPC.Lib MacOS Name UTCUtils MacOS Name LocalePlugin.c MacOS Name sqMacLocaleOS9.c MacOS Name sqMacLocaleOS9.h MacOS Name MSL RuntimePPC.Lib MacOS Name MathLib MacOS Name LocalesLib MacOS LocalePlugin Source LocalePlugin Name MSL RuntimePPC.Lib MacOS LocalePlugin Name InterfaceLib MacOS LocalePlugin Name MSL C.PPC.Lib MacOS LocalePlugin Name UTCUtils MacOS LocalePlugin Name MathLib MacOS LocalePlugin Name LocalesLib MacOS LocalePlugin Name LocalePlugin.c MacOS LocalePlugin Name sqMacLocaleOS9.c MacOS LocalePlugin Name sqMacLocaleOS9.h MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/SqueakLocale.pbproj/johnmci.mode1 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID 94AF35A4084782DD00FA5ACB XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 66DF6BFE01D7DCEA00A80119 66B8BC570381F53800A8011A 66DF6BFF01D7DCEA00A80119 66DF6C4501D7DEEE00A80119 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 600}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 618}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 189 157 922 659 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 203pt Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel InfoPlist.strings PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel InfoPlist.strings _historyCapacity 0 bookmark 94405842085E5A7A004495D0 history 9479076E0859F8950068B3F8 94461695085E5999004F7BD5 94461696085E5999004F7BD5 944616B9085E59BC004F7BD5 94405840085E5A7A004495D0 prevStack 947907380858EDF80068B3F8 947907390858EDF80068B3F8 94461699085E5999004F7BD5 9446169B085E5999004F7BD5 SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {714, 429}} RubberWindowFrame 189 157 922 659 0 0 1440 878 Module PBXNavigatorGroup Proportion 429pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 434}, {714, 184}} RubberWindowFrame 189 157 922 659 0 0 1440 878 Module XCDetailModule Proportion 184pt Proportion 714pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 94405844085E5A7A004495D0 1CE0B1FE06471DED0097A5F4 94405845085E5A7A004495D0 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 140401172.60255501 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList /Users/johnmci/Documents/SqueakLocale/SqueakLocale.pbproj WindowString 189 157 922 659 0 0 1440 878 WindowTools FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {879, 513}} RubberWindowFrame 444 70 879 795 0 0 1440 878 Module PBXNavigatorGroup Proportion 513pt BecomeActive ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1012 GeometryConfiguration Frame {{0, 518}, {879, 236}} RubberWindowFrame 444 70 879 795 0 0 1440 878 Module PBXBuildResultsModule Proportion 236pt Proportion 754pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 9446168A085E5866004F7BD5 944616CB085E59D7004F7BD5 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 444 70 879 795 0 0 1440 878 WindowToolGUID 9446168A085E5866004F7BD5 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {287, 175}} {{287, 0}, {560, 175}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {847, 175}} {{0, 175}, {847, 352}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {847, 527}} RubberWindowFrame 459 148 847 568 0 0 1440 878 Module PBXDebugSessionModule Proportion 527pt Proportion 527pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 94461664085E51E6004F7BD5 1C162984064C10D400B95A72 94461665085E51E6004F7BD5 94461666085E51E6004F7BD5 94461667085E51E6004F7BD5 94461668085E51E6004F7BD5 94461669085E51E6004F7BD5 9446166A085E51E6004F7BD5 ToolbarConfiguration xcode.toolbar.config.debug WindowString 459 148 847 568 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel LocalePlugin.h StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {791, 416}} RubberWindowFrame 459 42 791 674 0 0 1440 878 Module PBXNavigatorGroup Proportion 791pt Proportion 416pt ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 421}, {791, 212}} RubberWindowFrame 459 42 791 674 0 0 1440 878 Module PBXProjectFindModule Proportion 212pt Proportion 633pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE 9446168F085E5866004F7BD5 94461690085E5866004F7BD5 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 459 42 791 674 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {686, 500}} RubberWindowFrame 759 114 686 541 0 0 1440 878 Module PBXDebugCLIModule Proportion 500pt Proportion 500pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 94ABA92F0858D3A300079BE1 9446166B085E51E6004F7BD5 1C78EAAC065D492600B07095 WindowString 759 114 686 541 0 0 1440 878 WindowToolGUID 94ABA92F0858D3A300079BE1 WindowToolIsVisible Identifier windowTool.run Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {493, 167}} {{0, 176}, {493, 267}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {405, 443}} {{414, 0}, {514, 443}} GeometryConfiguration Frame {{0, 0}, {460, 159}} RubberWindowFrame 316 696 459 200 0 0 1280 1002 Module PBXRunSessionModule Proportion 159pt Proportion 159pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible 1 TableOfContents 1C0AD2B3069F1EA900FABCE6 1C0AD2B4069F1EA900FABCE6 1CD0528B0623707200166675 1C0AD2B5069F1EA900FABCE6 ToolbarConfiguration xcode.toolbar.config.run WindowString 316 696 459 200 0 0 1280 1002 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible 0 Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.breakpoints IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD052930623707200166675 PBXProjectModuleLabel Breakpoints GeometryConfiguration BreakpointsTreeTableConfiguration enabledColumn 16 breakpointColumn 482 Frame {{0, 0}, {506, 360}} RubberWindowFrame 780 252 506 380 0 0 1440 878 Module PBXDebugBreakpointsModule Proportion 360pt Proportion 360pt Name Breakpoints ServiceClasses PBXDebugBreakpointsModule StatusbarIsVisible TableOfContents 1C0AD2AD069F1E9B00FABCE6 94ABA9B60858E18E00079BE1 1CD052930623707200166675 WindowString 780 252 506 380 0 0 1440 878 WindowToolGUID 1C0AD2AD069F1E9B00FABCE6 WindowToolIsVisible Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/SqueakLocale.pbproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66A53B2101DAF78500A80109 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {782, 373}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {711, 373}}"; sepNavWindowFrame = "{{61, 197}, {750, 502}}"; }; }; 66B8BC5C0381F66500A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 6117}}"; sepNavSelRange = "{16850, 24}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {750, 2814}}"; sepNavSelRange = "{1486, 20}"; sepNavVisRect = "{{0, 0}, {750, 384}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66DF6BFD01D7DCEA00A80119 = { activeBuildStyle = 66DF6C4401D7DCEA00A80119; activeExecutable = 94ABA91E0858D35E00079BE1; activeTarget = 94AF34E00846F91100FA5ACB; addToTargets = ( 94AF34E00846F91100FA5ACB, ); breakpoints = ( 94ABA9220858D37A00079BE1, 94ABA9240858D37B00079BE1, 947906FD0858E5030068B3F8, ); codeSenseManager = 9444E60E06E7B8740063F6CC; executables = ( 94ABA91E0858D35E00079BE1, ); expressions = ( buffer, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 303.5835, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 475, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 63, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 140401172; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 140401172; }; perUserProjectItems = { 94405840085E5A7A004495D0 = 94405840085E5A7A004495D0; 94405842085E5A7A004495D0 = 94405842085E5A7A004495D0; 94461695085E5999004F7BD5 = 94461695085E5999004F7BD5; 94461696085E5999004F7BD5 = 94461696085E5999004F7BD5; 94461699085E5999004F7BD5 = 94461699085E5999004F7BD5; 9446169B085E5999004F7BD5 = 9446169B085E5999004F7BD5; 944616B9085E59BC004F7BD5 = 944616B9085E59BC004F7BD5; 947907380858EDF80068B3F8 = 947907380858EDF80068B3F8; 947907390858EDF80068B3F8 = 947907390858EDF80068B3F8; 9479076E0859F8950068B3F8 = 9479076E0859F8950068B3F8; }; sourceControlManager = 9444E60D06E7B8740063F6CC; userBuildSettings = { }; }; 94405840085E5A7A004495D0 = { fRef = 94405841085E5A7A004495D0; isa = PBXTextBookmark; rLen = 0; rLoc = 2147483647; rType = 0; }; 94405841085E5A7A004495D0 = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakLocale/build/LocalePlugin.bundle/Contents/Resources/English.lproj/InfoPlist.strings; refType = 0; sourceTree = ""; }; 94405842085E5A7A004495D0 = { fRef = 94405843085E5A7A004495D0; isa = PBXTextBookmark; name = "(null): 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 263; vrLoc = 0; }; 94405843085E5A7A004495D0 = { isa = PBXFileReference; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakLocale/build/LocalePlugin.bundle/Contents/Resources/English.lproj/InfoPlist.strings; refType = 0; sourceTree = ""; }; 9444E60D06E7B8740063F6CC = { fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; isa = PBXSourceControlManager; scmConfiguration = { }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC = { indexTemplatePath = ""; isa = PBXCodeSenseManager; }; 94461695085E5999004F7BD5 = { fRef = 94ABA8900858C3F900079BE1; isa = PBXTextBookmark; name = "LocalePlugin.h: 79"; rLen = 0; rLoc = 2551; rType = 0; vrLen = 1509; vrLoc = 1658; }; 94461696085E5999004F7BD5 = { fRef = 94ABA89A0858C5FA00079BE1; isa = PBXTextBookmark; name = locale.h; rLen = 8; rLoc = 162; rType = 0; vrLen = 189; vrLoc = 0; }; 94461699085E5999004F7BD5 = { fRef = 94ABA89A0858C5FA00079BE1; isa = PBXTextBookmark; name = locale.h; rLen = 8; rLoc = 162; rType = 0; vrLen = 189; vrLoc = 0; }; 9446169B085E5999004F7BD5 = { fRef = 94ABA8900858C3F900079BE1; isa = PBXTextBookmark; name = "LocalePlugin.h: 79"; rLen = 0; rLoc = 2551; rType = 0; vrLen = 1509; vrLoc = 1658; }; 944616B9085E59BC004F7BD5 = { fRef = 94ABA89B0858C5FA00079BE1; isa = PBXTextBookmark; name = "sqMacLocaleCarbon.c: 186"; rLen = 0; rLoc = 5594; rType = 0; vrLen = 954; vrLoc = 4643; }; 947906FD0858E5030068B3F8 = { fileReference = 94ABA89B0858C5FA00079BE1; functionName = "sqLocMeasurementMetric()"; isa = PBXFileBreakpoint; lineNumber = 80; state = 1; }; 947907380858EDF80068B3F8 = { fRef = 94ABA89B0858C5FA00079BE1; isa = PBXTextBookmark; name = "sqMacLocaleCarbon.c: 80"; rLen = 0; rLoc = 2240; rType = 0; vrLen = 1096; vrLoc = 1817; }; 947907390858EDF80068B3F8 = { fRef = 94ABA8870858C2CB00079BE1; isa = PBXTextBookmark; name = sqLocMeasurementMetric; rLen = 22; rLoc = 6712; rType = 0; vrLen = 959; vrLoc = 6129; }; 9479076E0859F8950068B3F8 = { fRef = 94ABA8870858C2CB00079BE1; isa = PBXTextBookmark; name = instantiateClassindexableSize; rLen = 29; rLoc = 6270; rType = 0; vrLen = 1249; vrLoc = 4205; }; 94ABA8870858C2CB00079BE1 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1214, 4774}}"; sepNavSelRange = "{6497, 0}"; sepNavVisRect = "{{0, 3004}, {380, 320}}"; sepNavWindowFrame = "{{153, 28}, {962, 719}}"; }; }; 94ABA8900858C3F900079BE1 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {750, 1316}}"; sepNavSelRange = "{2873, 19}"; sepNavVisRect = "{{0, 932}, {750, 384}}"; }; }; 94ABA89A0858C5FA00079BE1 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 581}}"; sepNavSelRange = "{162, 8}"; sepNavVisRect = "{{0, 0}, {673, 581}}"; sepNavWindowFrame = "{{130, 49}, {962, 719}}"; }; }; 94ABA89B0858C5FA00079BE1 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2632}}"; sepNavSelRange = "{5594, 0}"; sepNavVisRect = "{{0, 2224}, {673, 397}}"; sepNavWindowFrame = "{{417, 3}, {962, 719}}"; }; }; 94ABA91E0858D35E00079BE1 = { activeArgIndex = 2147483647; activeArgIndices = ( ); argumentStrings = ( ); configStateDict = { }; cppStopOnCatchEnabled = 0; cppStopOnThrowEnabled = 0; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; isa = PBXExecutable; launchableReference = 94ABA91F0858D35E00079BE1; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; shlibInfoDictList_v2 = ( { level = 0; path = /usr/lib/system/libmathCommon.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libSystem.B.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libicucore.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libauto.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libobjc.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; whenToLoad = 0; }, { level = 0; path = /usr/lib/libz.1.2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Security.framework/Versions/A/Security; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/WebServicesCore.framework/Versions/A/WebServicesCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound; whenToLoad = 0; }, { level = 0; path = /usr/lib/libbsm.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcrypto.0.9.7.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcups.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/FindByContent.framework/Versions/A/FindByContent; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRaw.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libmx.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices; whenToLoad = 0; }, { level = 0; path = /usr/lib/libiconv.2.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libxml2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HTMLRendering.framework/Versions/A/HTMLRendering; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/NavigationServices.framework/Versions/A/NavigationServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AGL.framework/Versions/A/AGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/QuickTime.framework/Versions/A/QuickTime; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/ZeroLink.framework/Versions/A/ZeroLink; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app/Contents/MacOS/Squeak; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacEncoding.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/interp.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIMenuBar.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMain.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGATS.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCSync.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIClipBoard.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixCommandLineInterface.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIAppleEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacFileLogic.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacImageIO.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Components/DictionaryService.component/Contents/MacOS/DictionaryService; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMemory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacTime.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/UUIDPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SurfacePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/StarSqueakPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundGenerationPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundCodecPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SocketPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SerialPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SecurityPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MiscPrimitivePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Matrix2x3Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MIDIPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MacMenubarPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/LargeIntegers.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Klatt.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JoystickTabletPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReaderPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Error.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReadWriter2Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/InternetConfigPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/HostWindowPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/GeniePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FloatArrayPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FFTPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DropPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ZipPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DSAPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BitBltPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B2DPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BMPReadWriterPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Squeak3D.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B3DAcceleratorPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/AsynchFilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ADPCMCodecPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSerialPort.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/osExports.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqNamedPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqVirtualMachine.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/aio.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacExternalPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacHostWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSecurity.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqFilePluginBasicPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDirectory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDragDrop.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixInterfaceSound.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSoundMacOSXJMM.ob"; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/LocalePlugin.bundle/Contents/MacOS/LocalePlugin; whenToLoad = 0; }, { level = 0; path = /Developer/Applications/Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin/Contents/Resources/PBGDBIntrospectionSupport.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Library/Application Support/Apple/Developer Tools/CustomDataViews/CFDataFormatters.bundle/Contents/MacOS/CFDataFormatters"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSocket.ob"; whenToLoad = 0; }, ); sourceDirectories = ( ); }; 94ABA91F0858D35E00079BE1 = { isa = PBXFileReference; lastKnownFileType = wrapper.application; name = Squeak.app; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app; refType = 0; sourceTree = ""; }; 94ABA9220858D37A00079BE1 = { fileReference = 94ABA89B0858C5FA00079BE1; functionName = "sqLocGetCountryInto()"; isa = PBXFileBreakpoint; lineNumber = 25; state = 1; }; 94ABA9240858D37B00079BE1 = { fileReference = 94ABA89B0858C5FA00079BE1; functionName = "sqLocGetLanguageInto()"; isa = PBXFileBreakpoint; lineNumber = 41; state = 1; }; 94AF34E00846F91100FA5ACB = { activeExec = 0; }; 94AF34F10846F91100FA5ACB = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {923, 590}}"; sepNavSelRange = "{284, 6}"; sepNavVisRect = "{{0, 0}, {923, 590}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/SqueakLocale.pbproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 39; objects = { 66A53B2001DAF78500A80109 = { children = ( 66A53B2101DAF78500A80109, ); isa = PBXVariantGroup; name = InfoPlist.strings; path = ""; refType = 4; sourceTree = ""; }; 66A53B2101DAF78500A80109 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = resources/English.lproj/InfoPlist.strings; refType = 4; sourceTree = ""; }; 66B8BC570381F53800A8011A = { children = ( 94AF35040846F9AB00FA5ACB, 94AF35000846F98600FA5ACB, 66B8BC580381F61C00A8011A, 66B8BC5A0381F63A00A8011A, 66B8BC5C0381F66500A8011A, 66B8BC5E0381F69100A8011A, ); isa = PBXGroup; name = platforms; path = ../Squeak3.8.0/platforms; refType = 2; sourceTree = SOURCE_ROOT; }; 66B8BC580381F61C00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = "Mac OS/vm/sqConfig.h"; refType = 4; sourceTree = ""; }; 66B8BC5A0381F63A00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqPlatformSpecific.h"; refType = 0; sourceTree = ""; }; 66B8BC5C0381F66500A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sq.h; path = Cross/vm/sq.h; refType = 4; sourceTree = ""; }; 66B8BC5E0381F69100A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/Cross/vm/sqVirtualMachine.h; refType = 0; sourceTree = ""; }; 66C6C8E501DB1EC300A80109 = { isa = PBXFileReference; lastKnownFileType = image.icns; path = SqueakPlugin.icns; refType = 4; sourceTree = ""; }; 66DF6BFD01D7DCEA00A80119 = { buildSettings = { }; buildStyles = ( 66DF6C4301D7DCEA00A80119, 66DF6C4401D7DCEA00A80119, ); hasScannedForEncodings = 1; isa = PBXProject; mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119; projectDirPath = ""; targets = ( 94AF34E00846F91100FA5ACB, ); }; 66DF6BFE01D7DCEA00A80119 = { children = ( 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, 66DF6C3901D7DCEA00A80119, 66DF6C8201D7DF7E00A80119, 66DF6C4501D7DEEE00A80119, 94AF34F10846F91100FA5ACB, ); isa = PBXGroup; refType = 4; sourceTree = ""; }; 66DF6BFF01D7DCEA00A80119 = { children = ( 94ABA8920858C40D00079BE1, 94ABA8900858C3F900079BE1, 94ABA8870858C2CB00079BE1, 94ABA89A0858C5FA00079BE1, 94ABA89B0858C5FA00079BE1, ); isa = PBXGroup; name = Sources; refType = 4; sourceTree = ""; }; 66DF6C3901D7DCEA00A80119 = { children = ( 66A53B2001DAF78500A80109, 66C6C8E501DB1EC300A80109, ); isa = PBXGroup; name = resources; refType = 4; sourceTree = ""; }; 66DF6C4301D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Development; }; 66DF6C4401D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; OPTIMIZATION_CFLAGS = "-O3 -mcpu=750 -funroll-loops "; OTHER_CFLAGS = "-DTARGET_OS_MAC -DNOPTHREADS"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; }; 66DF6C4501D7DEEE00A80119 = { children = ( 94AF34F20846F91100FA5ACB, ); isa = PBXGroup; name = Products; refType = 4; sourceTree = ""; }; 66DF6C8201D7DF7E00A80119 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; refType = 0; sourceTree = ""; }; //660 //661 //662 //663 //664 //940 //941 //942 //943 //944 94ABA8870858C2CB00079BE1 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = LocalePlugin.c; refType = 4; sourceTree = ""; }; 94ABA8880858C2CB00079BE1 = { fileRef = 94ABA8870858C2CB00079BE1; isa = PBXBuildFile; settings = { }; }; 94ABA8900858C3F900079BE1 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LocalePlugin.h; path = ../Squeak3.8.0/platforms/Cross/plugins/LocalePlugin/LocalePlugin.h; refType = 2; sourceTree = SOURCE_ROOT; }; 94ABA8910858C3F900079BE1 = { fileRef = 94ABA8900858C3F900079BE1; isa = PBXBuildFile; settings = { }; }; 94ABA8920858C40D00079BE1 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = ../Squeak3.8.0/platforms/Cross/vm/sqMemoryAccess.h; refType = 2; sourceTree = SOURCE_ROOT; }; 94ABA8930858C40D00079BE1 = { fileRef = 94ABA8920858C40D00079BE1; isa = PBXBuildFile; settings = { }; }; 94ABA89A0858C5FA00079BE1 = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sqMacLocaleCarbon.h; refType = 4; sourceTree = ""; }; 94ABA89B0858C5FA00079BE1 = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sqMacLocaleCarbon.c; refType = 4; sourceTree = ""; }; 94ABA89C0858C5FA00079BE1 = { fileRef = 94ABA89A0858C5FA00079BE1; isa = PBXBuildFile; settings = { }; }; 94ABA89D0858C5FA00079BE1 = { fileRef = 94ABA89B0858C5FA00079BE1; isa = PBXBuildFile; settings = { }; }; 94AF34E00846F91100FA5ACB = { buildPhases = ( 94AF34E10846F91100FA5ACB, 94AF34E70846F91100FA5ACB, 94AF34EA0846F91100FA5ACB, 94AF34EE0846F91100FA5ACB, 94AF34F00846F91100FA5ACB, ); buildRules = ( 94AF34F70846F94F00FA5ACB, ); buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = "Info-SqueakLocalePlugin__Upgraded_.plist"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = LocalePlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = bundle; }; dependencies = ( ); isa = PBXNativeTarget; name = "SqueakLocalePlugin (Upgraded)"; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 94AF34F20846F91100FA5ACB; productType = "com.apple.product-type.bundle"; }; 94AF34E10846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E20846F91100FA5ACB, 94AF34E30846F91100FA5ACB, 94AF34E40846F91100FA5ACB, 94AF34E50846F91100FA5ACB, 94AF35010846F98600FA5ACB, 94AF35050846F9AB00FA5ACB, 94ABA8910858C3F900079BE1, 94ABA8930858C40D00079BE1, 94ABA89C0858C5FA00079BE1, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E20846F91100FA5ACB = { fileRef = 66B8BC580381F61C00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E30846F91100FA5ACB = { fileRef = 66B8BC5A0381F63A00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E40846F91100FA5ACB = { fileRef = 66B8BC5C0381F66500A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E50846F91100FA5ACB = { fileRef = 66B8BC5E0381F69100A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E70846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E80846F91100FA5ACB, 94AF34E90846F91100FA5ACB, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E80846F91100FA5ACB = { fileRef = 66C6C8E501DB1EC300A80109; isa = PBXBuildFile; settings = { }; }; 94AF34E90846F91100FA5ACB = { fileRef = 66A53B2001DAF78500A80109; isa = PBXBuildFile; settings = { }; }; 94AF34EA0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94ABA8880858C2CB00079BE1, 94ABA89D0858C5FA00079BE1, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EE0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34EF0846F91100FA5ACB, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EF0846F91100FA5ACB = { fileRef = 66DF6C8201D7DF7E00A80119; isa = PBXBuildFile; settings = { }; }; 94AF34F00846F91100FA5ACB = { buildActionMask = 2147483647; files = ( ); isa = PBXRezBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34F10846F91100FA5ACB = { isa = PBXFileReference; lastKnownFileType = text.xml; path = "Info-SqueakLocalePlugin__Upgraded_.plist"; refType = 4; sourceTree = ""; }; 94AF34F20846F91100FA5ACB = { explicitFileType = wrapper.cfbundle; includeInIndex = 0; isa = PBXFileReference; path = LocalePlugin.bundle; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; 94AF34F70846F94F00FA5ACB = { compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; isa = PBXBuildRule; outputFiles = ( ); }; 94AF35000846F98600FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = "Mac OS/vm/config.h"; refType = 4; sourceTree = ""; }; 94AF35010846F98600FA5ACB = { fileRef = 94AF35000846F98600FA5ACB; isa = PBXBuildFile; settings = { }; }; 94AF35040846F9AB00FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../Squeak3.8.0/src/vm/interp.h; refType = 2; sourceTree = SOURCE_ROOT; }; 94AF35050846F9AB00FA5ACB = { fileRef = 94AF35040846F9AB00FA5ACB; isa = PBXBuildFile; settings = { }; }; }; rootObject = 66DF6BFD01D7DCEA00A80119; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/sqMacLocaleCarbon.c ================================================ /* * sqMacLocaleCarbon.c * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include "sqMacLocaleCarbon.h" /* Locale support functions */ char * thisLocale; struct lconv * localeTable; sqInt sqLocInitialize(void) { thisLocale = setlocale(LC_ALL,""); localeTable = localeconv(); return true; } /************** Country and language ******************/ /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[4]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode); CFStringGetCString(stringRef, buffer, 4,kCFStringEncodingMacRoman); memcpy(str,buffer,3); CFRelease(userLocaleRef); } /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[4]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode); CFStringGetCString(stringRef, buffer, 4,kCFStringEncodingMacRoman); memcpy(str,buffer,3); CFRelease(userLocaleRef); } /***************** Currency ********************/ /* return 1 (true) if the currency symbol is to be placed in front of the *currency amount */ sqInt sqLocCurrencyNotation(void) { return localeTable->p_cs_precedes; } /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void) { return strlen(localeTable->currency_symbol); } /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str) { strcpy(str, localeTable->currency_symbol); } /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[7]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleMeasurementSystem); CFStringGetCString(stringRef, buffer, 7,kCFStringEncodingMacRoman); CFRelease(userLocaleRef); if (strcmp(buffer, "Metric") == 0) return 1; else return 0; } /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str) { strncpy(str, localeTable->thousands_sep, 1); } /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str) { strncpy(str, localeTable->decimal_point, 1); } /****************** time and date *********************/ sqInt sqLocGetVMOffsetToUTC(void) { /* return 0 for now */ return 0; } sqInt sqLocGetTimezoneOffset(void) { CFTimeZoneRef zoneRef = CFTimeZoneCopySystem (); CFAbsoluteTime timeIs = CFAbsoluteTimeGetCurrent(); CFTimeInterval interval; interval = CFTimeZoneGetSecondsFromGMT (zoneRef,timeIs); CFRelease(zoneRef); return ((sqInt) interval)/60; } /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void) { struct tm * timeBlock; time_t theTime; theTime = time((time_t)NULL); timeBlock = localtime(&theTime); return timeBlock->tm_isdst; } void dateFormatIs(char *buffer,CFDateFormatterStyle type ) { CFDateFormatterRef longFormatter = CFDateFormatterCreate(NULL, NULL, type, type); CFStringRef longStrRef = CFDateFormatterGetFormat(longFormatter); CFStringGetCString(longStrRef, buffer, 255,kCFStringEncodingMacRoman); CFRelease(longFormatter); } /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); return strlen(buffer); } /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); memcpy(str, buffer,strlen(buffer)); } /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterShortStyle); return strlen(buffer); } /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterShortStyle); memcpy(str, buffer,strlen(buffer)); } /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); return strlen(buffer); } /* write the string describing the time formatting into string ptr. * Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); memcpy(str, buffer,strlen(buffer)); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/sqMacLocaleCarbon.h ================================================ /* * sqMacLocaleCarbon.h * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include #include "sqMemoryAccess.h" #include #include "sq.h" ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/sqMacLocaleOS9.c ================================================ /* * sqMacLocaleOS9.c * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include "sqMacLocaleOS9.h" #include "script.h" #include /* Locale support functions */ Intl0Hndl itl0; Intl0Rec intMarksR; sqInt sqLocInitialize(void) { itl0 = (Intl0Hndl)GetIntlResource(0); intMarksR = **itl0; return true; } /************** Country and language ******************/ void getCountryOrLanguage(char *str,LocalePartMask which); void getCountryOrLanguage(char *str,LocalePartMask which){ RegionCode regionCode; LangCode languageCode; OSStatus err; char string[18]; LocaleRef locale=NULL; languageCode = GetScriptManagerVariable(smScriptLang); regionCode = GetScriptManagerVariable(smRegionCode); err = LocaleRefFromLangOrRegionCode (languageCode, regionCode, &locale); err = LocaleRefGetPartString (locale, which, 18, string); memcpy(str,string,3); } /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str) { getCountryOrLanguage(str,kLocaleRegionMask); } /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str) { getCountryOrLanguage(str,kLocaleLanguageMask); } /***************** Currency ********************/ /* return 1 (true) if the currency symbol is to be placed in front of the *currency amount */ sqInt sqLocCurrencyNotation(void) { return intMarksR.currFmt & currSymLead; } /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void) { char currencySymbol[4]; strncpy(currencySymbol, &intMarksR.currSym1, 3); currencySymbol[3] = 0x00; return strlen(currencySymbol); } /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str) { char currencySymbol[4]; strncpy(currencySymbol, &intMarksR.currSym1, 3); currencySymbol[3] = 0x00; strcpy(str, currencySymbol); } /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void) { return intMarksR.metricSys > 0; } /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str) { strncpy(str, &intMarksR.thousSep, 1); } /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str) { strncpy(str, &intMarksR.decimalPt, 1); } /****************** time and date *********************/ sqInt sqLocGetVMOffsetToUTC(void) { /* return 0 for now */ return 0; } sqInt sqLocGetTimezoneOffset(void) { unsigned long now,utc; GetDateTime(&now); ConvertLocalTimeToUTC(now,&utc); return ((sqInt) (now-utc)/60); } /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void) { struct tm * timeBlock; time_t theTime; theTime = time((time_t)NULL); timeBlock = localtime(&theTime); return timeBlock->tm_isdst; } void dateFormatIs(Str255 buffer,DateForm type ); void timeFormatIs(Str255 buffer,DateForm type ); void dateFormatIs(Str255 buffer,DateForm type ) { DateString (0+24*60*60+1,type,buffer,0); } void timeFormatIs(Str255 buffer,DateForm type ) { TimeString (0+24*60*60+1,true,buffer,0); } /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void) { Str255 buffer; dateFormatIs(buffer,longDate); return buffer[0]; } /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str) { Str255 buffer; dateFormatIs(buffer,longDate); p2cstr(buffer); memcpy(str, (char *) buffer,strlen((char*)buffer)); } /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(void) { Str255 buffer; dateFormatIs(buffer,shortDate); return buffer[0]; } /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str) { Str255 buffer; dateFormatIs(buffer,shortDate); p2cstr(buffer); memcpy(str,(char *) buffer,strlen((char*)buffer)); } /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void) { Str255 buffer; timeFormatIs(buffer,shortDate); return buffer[0]; } /* write the string describing the time formatting into string ptr. * Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str) { Str255 buffer; timeFormatIs(buffer,shortDate); p2cstr(buffer); memcpy(str, (char*) buffer,strlen((char*)buffer)); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/LocalePlugin/sqMacLocaleOS9.h ================================================ /* * sqMacLocaleOS9.h * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include "sqMemoryAccess.h" #include "sq.h" #include "LocalePlugin.h" ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/MIDIPlugin/sqMacMIDI.c ================================================ #include "sq.h" #include "MIDIPlugin.h" #include #include extern struct VirtualMachine *interpreterProxy; /* Quicktime MIDI note allocator and channels */ #define FIRST_DRUM_KIT 16385 void* portNamesFn; void* portIsOpenFn; void* portSetControlFn; void* serialPortOpenFn; void* serialPortCloseFn; void* serialPortCountFn; void* serialPortReadIntoFn; void* serialPortWriteFromFn; NoteAllocator na = nil; NoteChannel channel[16] = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}; /* Initial instruments: drums on channel 10, piano on all other channels */ int channelInstrument[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, FIRST_DRUM_KIT, 1, 1, 1, 1, 1, 1}; /* Quicktime MIDI parser state */ enum {idle, want1of2, want2of2, want1of1, sysExclusive}; int state = idle; int argByte1 = 0; int argByte2 = 0; int lastCmdByte = nil; /* number of argument bytes for each MIDI command */ char argumentBytes[128] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /*** Private Functions ***/ int setMidiClockRate(int portNum, int interfaceClockRate); int sqMIDIGetSerialPortCount(void); /*** Quicktime MIDI Support Functions ***/ void closeQuicktimeMIDIPort(void); void openQuicktimeMIDIPort(void); void performMIDICmd(int cmdByte, int arg1, int arg2); void processMIDIByte(int aByte); void startMIDICommand(int cmdByte); /* initialize/shutdown */ int midiInit() { portIsOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortIsOpen", "SerialPlugin"); if (portIsOpenFn == 0) { portIsOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortIsOpen", ""); if (portIsOpenFn == 0) return interpreterProxy->success(false); } portSetControlFn = interpreterProxy->ioLoadFunctionFrom("serialPortSetControl", "SerialPlugin"); if (portSetControlFn == 0) { portSetControlFn = interpreterProxy->ioLoadFunctionFrom("serialPortSetControl", ""); if (portSetControlFn == 0) return interpreterProxy->success(false); } serialPortCloseFn = interpreterProxy->ioLoadFunctionFrom("serialPortClose", "SerialPlugin"); if (serialPortCloseFn == 0) { serialPortCloseFn = interpreterProxy->ioLoadFunctionFrom("serialPortClose", ""); if (serialPortCloseFn == 0) return interpreterProxy->success(false); } serialPortCountFn = interpreterProxy->ioLoadFunctionFrom("serialPortCount", "SerialPlugin"); if (serialPortCountFn == 0) { serialPortCountFn = interpreterProxy->ioLoadFunctionFrom("serialPortCount", ""); if (serialPortCountFn == 0) return interpreterProxy->success(false); } portNamesFn = interpreterProxy->ioLoadFunctionFrom("serialPortNames", "SerialPlugin"); if (portNamesFn == 0) { portNamesFn = interpreterProxy->ioLoadFunctionFrom("serialPortNames", ""); if (portNamesFn == 0) return interpreterProxy->success(false); } serialPortOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortOpen", "SerialPlugin"); if (serialPortOpenFn == 0) { serialPortOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortOpen", ""); if (serialPortOpenFn == 0) return interpreterProxy->success(false); } serialPortReadIntoFn = interpreterProxy->ioLoadFunctionFrom("serialPortReadInto", "SerialPlugin"); if (serialPortReadIntoFn == 0) { serialPortReadIntoFn = interpreterProxy->ioLoadFunctionFrom("serialPortReadInto", ""); if (serialPortReadIntoFn == 0) return interpreterProxy->success(false); } serialPortWriteFromFn = interpreterProxy->ioLoadFunctionFrom("serialPortWriteFrom", "SerialPlugin"); if (serialPortWriteFromFn == 0) { serialPortWriteFromFn = interpreterProxy->ioLoadFunctionFrom("serialPortWriteFrom", ""); if (serialPortWriteFromFn == 0) return interpreterProxy->success(false); } return true; } int midiShutdown() { return 1; } /* helper function for MIDI module */ int sqMIDIParameter(int whichParameter, int modify, int newValue); int sqMIDIParameterSet(int whichParameter, int newValue) { sqMIDIParameter(whichParameter, true, newValue); return 0; } int sqMIDIParameterGet(int whichParameter) { sqMIDIParameter(whichParameter, false, 0); return 0; } int setMidiClockRate(int portNum, int interfaceClockRate) { #pragma unused(portNum, interfaceClockRate) /* Put the given port into MIDI mode, which uses a clock supplied by an external MIDI interface adaptor to determine the baud rate. Possible external clock rates: 31.25 KHz, 0.5 MHz, 1 MHz, or 2 MHz. */ return false; }/*** MIDI Parameters (used with sqMIDIParameter function) ***/ #define sqMIDIInstalled 1 /* Read-only. Return 1 if a MIDI driver is installed, 0 if not. On OMS-based MIDI drivers, this returns 1 only if the OMS system is properly installed and configured. */ #define sqMIDIVersion 2 /* Read-only. Return the integer version number of this MIDI driver. The version numbering sequence is relative to a particular driver. That is, version 3 of the Macintosh MIDI driver is not necessarily related to version 3 of the Win95 MIDI driver. */ #define sqMIDIHasBuffer 3 /* Read-only. Return 1 if this MIDI driver has a time-stamped output buffer, 0 otherwise. Such a buffer allows the client to schedule MIDI output packets to be sent later. This can allow more precise timing, since the driver uses timer interrupts to send the data at the right time even if the processor is in the midst of a long-running Squeak primitive or is running some other application or system task. */ #define sqMIDIHasDurs 4 /* Read-only. Return 1 if this MIDI driver supports an extended primitive for note-playing that includes the note duration and schedules both the note-on and the note-off messages in the driver. Otherwise, return 0. */ #define sqMIDICanSetClock 5 /* Read-only. Return 1 if this MIDI drivers clock can be set via an extended primitive, 0 if not. */ #define sqMIDICanUseSemaphore 6 /* Read-only. Return 1 if this MIDI driver can signal a semaphore when MIDI input arrives. Otherwise, return 0. If this driver supports controller caching and it is enabled, then incoming controller messages will not signal the semaphore. */ #define sqMIDIEchoOn 7 /* Read-write. If this flag is set to a non-zero value, and if the driver supports echoing, then incoming MIDI events will be echoed immediately. If this driver does not support echoing, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIUseControllerCache 8 /* Read-write. If this flag is set to a non-zero value, and if the driver supports a controller cache, then the driver will maintain a cache of the latest value seen for each MIDI controller, and control update messages will be filtered out of the incoming MIDI stream. An extended MIDI primitive allows the client to poll the driver for the current value of each controller. If this driver does not support a controller cache, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIEventsAvailable 9 /* Read-only. Return the number of MIDI packets in the input queue. */ #define sqMIDIFlushDriver 10 /* Write-only. Setting this parameter to any value forces the driver to flush its I/0 buffer, discarding all unprocessed data. Reading this parameter returns 0. Setting this parameter will do nothing if the driver does not support buffer flushing. */ #define sqMIDIClockTicksPerSec 11 /* Read-only. Return the MIDI clock rate in ticks per second. */ #define sqMIDIHasInputClock 12 /* Read-only. Return 1 if this MIDI driver timestamps incoming MIDI data with the current value of the MIDI clock, 0 otherwise. If the driver does not support such timestamping, then the client must read input data frequently and provide its own timestamping. */ /*** MIDI Functions ***/ int sqMIDIClosePort(int portNum) { /* Close the given MIDI port. Do nothing if the port is not open. Fail if there is no port of the given number.*/ int serialPorts; serialPorts = sqMIDIGetSerialPortCount(); if (portNum == serialPorts) { closeQuicktimeMIDIPort(); return 0; } else { if (serialPortCloseFn == 0) { return interpreterProxy->success(false); } return ((int (*) (int)) serialPortCloseFn)(portNum); } } int sqMIDIGetClock(void) { /* Return the current value of the clock used to schedule MIDI events. The MIDI clock is assumed to wrap at or before half the maximum positive SmallInteger value. This allows events to be scheduled into the future without overflowing into LargePositiveIntegers. This implementation does not support event scheduling, so it just returns the value of the Squeak millisecond clock. */ return interpreterProxy->ioMicroMSecs(); } int sqMIDIGetSerialPortCount(void) { /* Return the number of available hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ int serialPorts; if (serialPortCountFn == 0) { return 0; } serialPorts = ((int (*) (void)) serialPortCountFn)(); return serialPorts; /* serial ports */ } int sqMIDIGetPortCount(void) { /* Return the number of available MIDI interfaces, including both hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ return sqMIDIGetSerialPortCount() + 1; /* serial ports + QuickTime Synth */ } int sqMIDIGetPortDirectionality(int portNum) { /* Return an integer indicating the directionality of the given port where: 1 = input, 2 = output, 3 = bidirectional. Fail if there is no port of the given number. */ int serialPorts; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { return 2; } else { return 3; } } int sqMIDIGetPortName(int portNum, int namePtr, int length) { /* Copy the name of the given MIDI port into the string at the given address. Copy at most length characters, and return the number of characters copied. Fail if there is no port of the given number.*/ char userName[256], inName[256], outName[256]; int serialPorts, count; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { strcpy(userName, "QuickTime MIDI"); } else { if (portNamesFn == 0) { return 0; } ((int (*) (int , char *, char *, char *)) portNamesFn)(portNum, userName, inName, outName); } count = strlen(userName); if (count > length) count = length; memcpy((void *) namePtr, userName, count); return count; } int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate) { /* Open the given port, if possible. If non-zero, readSemaphoreIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Note that not all implementations support read semaphores (this one does not); see sqMIDICanUseSemaphore. The interfaceClockRate parameter specifies the clock speed for an external MIDI interface adaptor on platforms that use such adaptors (e.g., Macintosh). Fail if there is no port of the given number.*/ #pragma unused(readSemaIndex) int serialPorts; int err; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { openQuicktimeMIDIPort(); return 0; } if (serialPortOpenFn == 0) { return interpreterProxy->success(false); } err = ((int (*) (int , int , int , int , int , int , int , int , int ))serialPortOpenFn)(portNum, 9600, 1, 0, 8, 0, 0, 0, 0); if (!err) { err = setMidiClockRate(portNum, interfaceClockRate); if (err) { sqMIDIClosePort(portNum); } } return 0; } int sqMIDIParameter(int whichParameter, int modify, int newValue) { /* Read or write the given MIDI driver parameter. If modify is 0, then newValue is ignored and the current value of the specified parameter is returned. If modify is non-zero, then the specified parameter is set to newValue. Note that many MIDI driver parameters are read-only; attempting to set one of these parameters fails. For boolean parameters, true = 1, false = 0. */ #pragma unused(newValue) if (modify == 0) { switch(whichParameter) { case sqMIDIInstalled: return 1; break; case sqMIDIVersion: return 100; break; case sqMIDIHasBuffer: case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: case sqMIDIEchoOn: case sqMIDIUseControllerCache: return 0; break; case sqMIDIEventsAvailable: return 1; /* pretend that events are always available */ break; case sqMIDIFlushDriver: return 0; break; case sqMIDIClockTicksPerSec: return 1000; break; case sqMIDIHasInputClock: return 0; break; default: return interpreterProxy->success(false); } } else { switch(whichParameter) { case sqMIDIInstalled: case sqMIDIVersion: case sqMIDIHasBuffer: case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: return interpreterProxy->success(false); break; case sqMIDIEchoOn: /* noop; echoing not supported */ break; case sqMIDIUseControllerCache: /* noop; controller cache not supported */ break; case sqMIDIEventsAvailable: return interpreterProxy->success(false); break; case sqMIDIFlushDriver: /* noop; buffer flushing not supported */ break; case sqMIDIClockTicksPerSec: return interpreterProxy->success(false); break; default: return interpreterProxy->success(false); } } return 0; } int sqMIDIPortReadInto(int portNum, int count, int bufferPtr) { /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Copy up to (length - 4) bytes of incoming MIDI data into that buffer, preceded by a 4-byte timestamp in the units of the MIDI clock, most significant byte first. Implementations that do not support timestamping of incoming data as it arrives (see sqMIDIHasInputClock) simply set the timestamp to the value of the MIDI clock when this function is called. Return the total number of bytes read, including the timestamp bytes. Return zero if no data is available. Fail if the buffer is shorter than five bytes, since there must be enough room for the timestamp plus at least one data byte. */ int bytesRead; if (count < 5) return interpreterProxy->success(false); if (serialPortReadIntoFn == 0) { return interpreterProxy->success(false); } bytesRead = ((int (*) (int , int , int )) serialPortReadIntoFn)(portNum, count - 4, bufferPtr + 4); if (bytesRead == 0) return 0; *((int *) bufferPtr) = sqMIDIGetClock(); /* set timestamp */ return bytesRead + 4; } int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time) { /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Send its contents to the given port when the MIDI clock reaches the given time. If time equals zero, then send the data immediately. Implementations that do not support a timestamped output queue, such as this one, always send the data immediately; see sqMIDIHasBuffer. */ #pragma unused(time) int serialPorts, i; unsigned char *bytePtr; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { if (!na) return interpreterProxy->success(false); /* QuickTime port not open */ bytePtr = (unsigned char *) bufferPtr; for (i = 0; i < count; i++) { processMIDIByte(*bytePtr++); } return count; } if (serialPortWriteFromFn == 0) { return interpreterProxy->success(false); } return ((int (*) (int , int , int )) serialPortWriteFromFn)(portNum, count - 4, bufferPtr + 4); } /*** Quicktime MIDI Support Functions ***/ void closeQuicktimeMIDIPort(void) { int i; if (!na) return; for (i = 0; i < 16; i++) { /* dispose of note channels */ if (channel[i]) NADisposeNoteChannel(na, channel[i]); channel[i] = nil; } CloseComponent(na); /* close note allocator */ } void openQuicktimeMIDIPort(void) { ComponentResult err; NoteRequest nr; NoteChannel nc; int i; short shortpoly; Fixed fixedtypical; closeQuicktimeMIDIPort(); na = OpenDefaultComponent('nota', 0); if (!na) return; for (i = 0; i < 16; i++) { shortpoly = CFSwapInt16HostToBig(11); memcpy(&nr.info.polyphony,&shortpoly,2); /* max simultaneous tones */ fixedtypical = CFSwapInt32HostToBig(0x00010000); memcpy(&nr.info.typicalPolyphony,&fixedtypical,4); NAStuffToneDescription(na, 1, &nr.tone); err = NANewNoteChannel(na, &nr, &nc); if (err || !nc) { closeQuicktimeMIDIPort(); return; } NAResetNoteChannel(na, nc); NASetInstrumentNumber(na, nc, channelInstrument[i]); channel[i] = nc; } state = idle; argByte1 = 0; argByte2 = 0; lastCmdByte = nil; return; } void performMIDICmd(int cmdByte, int arg1, int arg2) { /* Perform the given MIDI command with the given arguments. */ int ch, cmd, val, instrument, bend; ch = cmdByte & 0x0F; cmd = cmdByte & 0xF0; if (cmd == 128) { /* note off */ NAPlayNote(na, channel[ch], arg1, 0); } if (cmd == 144) { /* note on */ NAPlayNote(na, channel[ch], arg1, arg2); } if (cmd == 176) { /* control change */ if ((arg1 >= 32) && (arg1 <= 63)) { val = arg2 << 1; /* LSB of controllers 0-31 */ } else { val = arg2 << 8; /* scale MSB to QT controller range */ } NASetController(na, channel[ch], arg1, val); } if (cmd == 192) { /* program change */ if (ch == 9) { instrument = FIRST_DRUM_KIT + arg1; /* if channel 10, select a drum set */ } else { instrument = arg1 + 1; } NASetInstrumentNumber(na, channel[ch], instrument); channelInstrument[ch] = instrument; } if (cmd == 224) { /* pitch bend */ bend = ((arg2 << 7) + arg1) - (64 << 7); bend = bend / 32; /* default sensitivity = +/- 2 semitones */ NASetController(na, channel[ch], kControllerPitchBend, bend); } } void processMIDIByte(int aByte) { /* Process the given incoming MIDI byte and perform any completed commands. */ if (aByte > 247) return; /* skip all real-time messages */ switch (state) { case idle: if (aByte >= 128) { /* start a new command using the action table */ startMIDICommand(aByte); } else { /* data byte arrived in idle state: use running status if possible */ if (lastCmdByte == nil) { return; /* last command byte is not defined; just skip this byte */ } else { /* process this data as if it had the last command byte in front of it */ startMIDICommand(lastCmdByte); /* the previous line put us into a new state; we now do a recursive call to process the data byte in this new state. */ processMIDIByte(aByte); return; } } break; case want1of2: argByte1 = aByte; state = want2of2; break; case want2of2: argByte2 = aByte; performMIDICmd(lastCmdByte, argByte1, argByte2); state = idle; break; case want1of1: argByte1 = aByte; performMIDICmd(lastCmdByte, argByte1, 0); state = idle; break; case sysExclusive: if (aByte < 128) { /* skip a system exclusive data byte */ } else { if (aByte < 248) { /* a system exclusive message can be terminated by any non-real-time command byte */ state = idle; if (aByte != 247) { processMIDIByte(aByte); /* if not endSysExclusive, byte is the start the next command */ } } } break; } } void startMIDICommand(int cmdByte) { /* Start processing a MIDI message beginning with the given command byte. */ int argCount; argCount = argumentBytes[cmdByte - 128]; switch (argCount) { case 0: /* start a zero argument command (e.g., a real-time message) */ /* Stay in the current state and don't change active status. Real-time messages may arrive between data bytes without disruption. */ performMIDICmd(cmdByte, 0, 0); break; case 1: /* start a one argument command */ lastCmdByte = cmdByte; state = want1of1; break; case 2: /* start a two argument command */ lastCmdByte = cmdByte; state = want1of2; break; case 3: /* start a variable length 'system exclusive' command */ /* a system exclusive command clears running status */ lastCmdByte = nil; state = sysExclusive; break; } } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/MacMenubarPlugin/MacMenubarPlugin.h ================================================ #include Boolean ioCheckMenuHandle(MenuHandle menuHandle); Boolean ioCheckMenuHandle(MenuHandle menuHandle) { int menuID; if (menuHandle == 0) return true; menuID = GetMenuID(menuHandle); if (menuID == 0) return false; return true; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:15 pm'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer ' classVariableNames: 'Registry ' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer ' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 18:12'! buffer ^buffer! ! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 23:15'! isBufferBased ^(buffer == nil) not ! ! !MPEGFile methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:11'! openBuffer: aByteArray pathToFile := nil. buffer _ aByteArray. fileBits := self primFileOpenABuffer: aByteArray size: aByteArray size. fileBits notNil ifTrue: [fileIndex := Smalltalk registerExternalObject: fileBits. self register.] ! ! !MPEGFile methodsFor: 'primitives' stamp: 'JMM 1/20/2006 17:52'! primFileOpenABuffer: buffer size: aSize "Open the file" self primitiveFailed! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:18'! openBuffer: aBuffer ^self new openBuffer: aBuffer! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 23:05'! openFileUseBuffer: aPath | bar bytes | bar _ StandardFileStream oldFileNamed: aPath. bar binary. bytes _ bar contents. ^self new openBuffer: bytes! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:10'! external [external hasVideo] on: Error do: [self isBuffer ifTrue: [external := MPEGFile openBuffer: external buffer] ifFalse: [(MPEGFile isFileValidMPEG: external fileName) ifFalse: [^self error: 'Mpeg File is invalid']. external := MPEGFile openFile: external fileName]]. ^external! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:05'! isBuffer ^isBuffer == true! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:17'! initializeWithBuffer: aBuffer form: aForm isBuffer := true. buffer := aBuffer. self initialize: aBuffer. self form: aForm. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:07'! initializeWithBuffer: aBuffer morph: aMorphic isBuffer _ true. buffer _ aBuffer. self initialize: aBuffer. self morph: aMorphic. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:54'! initialize: aPath self halt. self isBuffer ifTrue: [external := MPEGFile openBuffer: buffer] ifFalse: [(MPEGFile isFileValidMPEG: aPath) ifFalse: [^nil]. external := MPEGFile openFile: aPath.]. self playerProcessPriority: Processor userSchedulingPriority. self lastDelay: 10. volume := 1.0. errorForSoundStart := 500. semaphoreForSound := Semaphore new. self startTime: (Array new: self totalVideoStreams). self clockBias: (Array new: self totalVideoStreams withAll: 0).! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:16'! playBuffer: aBuffer onForm: aForm ^self new initializeWithBuffer: aBuffer morph: aForm! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:06'! playBuffer: aBuffer onMorph: aMorph ^self new initializeWithBuffer: aBuffer morph: aMorph! ! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer' classVariableNames: 'Registry' poolDictionaries: '' category: 'Movies-Kernel'! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegBufferTest.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:22 pm'! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! isThereAFile mpegFile isBufferBased ifTrue: [^true]. ^(FileStream isAFileNamed: mpegFile fileName)! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! moviePosition "Answer a number between 0.0 and 1.0 indicating the current position within the movie." mpegFile ifNil: [^ 0.0]. mpegFile fileHandle ifNil: [^ 0.0]. self isThereAFile ifFalse: [^0.0]. mpegFile hasVideo ifTrue: [^ ((mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0)) min: 1.0]. soundTrack ifNotNil: [^ soundTrack soundPosition]. ^ 0.0 ! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalFrames "Answer the total number of frames in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ mpegFile videoFrames: 0! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalSeconds "Answer the total number of seconds in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ self totalFrames asFloat / (mpegFile videoFrameRate: 0)! ! !MPEGDisplayMorph methodsFor: 'commands' stamp: 'JMM 1/20/2006 23:09'! startPlaying "Start playing the movie at the current position." | frameIndex | self stopPlaying. stopFrame := nil. self mpegFileIsOpen ifFalse: [^ self]. (mpegFile fileName notNil) ifTrue: [(FileStream isAFileNamed: mpegFile fileName) ifFalse: [ | newFileResult newFileName | self inform: 'Path changed. Enter new one for: ', (FileDirectory localNameFor: mpegFile fileName). newFileResult := StandardFileMenu oldFile. newFileName := newFileResult directory fullNameFor: newFileResult name. mpegFile openFile: newFileName]]. mpegFile hasAudio ifTrue: [mpegFile hasVideo ifTrue: ["set movie frame position from soundTrack position" soundTrack reset. "ensure file is open before positioning" soundTrack soundPosition: (mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0). "now set frame index from the soundtrack position for best sync" frameIndex := ((soundTrack millisecondsSinceStart * desiredFrameRate) // 1000). frameIndex := (frameIndex max: 0) min: ((mpegFile videoFrames: 0) - 3). mpegFile videoSetFrame: frameIndex stream: 0]. SoundPlayer stopReverb. soundTrack volume: volume. soundTrack repeat: repeat. soundTrack resumePlaying. startFrame := startMSecs := 0] ifFalse: [soundTrack := nil. startFrame := mpegFile videoGetFrame: 0. startMSecs := Time millisecondClockValue]. running := true! ! !MPEGDisplayMorph methodsFor: 'file open/close' stamp: 'JMM 1/20/2006 23:02'! openFileNamed: mpegFileName "Try to open the MPEG file with the given name. Answer true if successful." | e | self closeFile. (FileDirectory default fileExists: mpegFileName) ifFalse: [self inform: ('File not found: {1}' translated format: {mpegFileName}). ^ false]. (MPEGFile isFileValidMPEG: mpegFileName) ifTrue: [mpegFile := MPEGFile openFileUseBuffer: mpegFileName] ifFalse: [ (JPEGMovieFile isJPEGMovieFile: mpegFileName) ifTrue: [mpegFile := JPEGMovieFile new openFileNamed: mpegFileName] ifFalse: [self inform: ('Not an MPEG or JPEG movie file: {1}' translated format: {mpegFileName}). ^ false]]. mpegFile fileHandle ifNil: [^ false]. "initialize soundTrack" mpegFile hasAudio ifTrue: [soundTrack := mpegFile audioPlayerForChannel: 1] ifFalse: [soundTrack := nil]. mpegFile hasVideo ifTrue: [ "set screen size and display first frame" desiredFrameRate := mpegFile videoFrameRate: 0. soundTrack ifNotNil: [ "compute frame rate from length of audio track" desiredFrameRate := (mpegFile videoFrames: 0) / soundTrack duration]. e := (mpegFile videoFrameWidth: 0)@(mpegFile videoFrameHeight: 0). frameBuffer := Form extent: e depth: (Display depth max: 16). super extent: e. self nextFrame] ifFalse: [ "hide screen for audio-only files" super extent: 250@0]. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegPluginBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:10 pm'! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:07'! primitiveMPEG3CheckSig: path | result sz storage | "int mpeg3_check_sig(char *path)" self var: #storage declareC: 'char storage[1024] '. self primitive: 'primitiveMPEG3CheckSig' parameters: #(String). sz _ interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. self cCode: 'result = mpeg3_check_sig(storage)'. ^result asOop: Boolean ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 18:38'! primitiveMPEG3OpenABuffer: path size: size | mpeg3Oop index | self var: #index declareC: 'mpeg3_t ** index'. self primitive: 'primitiveMPEG3OpenABuffer' parameters: #(String SmallInteger). mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(path,size); makeFileEntry(*index)'. ^mpeg3Oop. ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:11'! primitiveMPEG3Open: path | mpeg3Oop index sz storage | "mpeg3_t* mpeg3_open(char *path)" self var: #index declareC: 'mpeg3_t ** index'. self var: #storage declareC: 'char storage[1024]'. self primitive: 'primitiveMPEG3Open' parameters: #(String). sz := interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(storage,0); makeFileEntry(*index)'. ^mpeg3Oop. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/mpeg3Plugin-Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable mpeg3Plugin CFBundleGetInfoString mpeg3Plugin for Squeak CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.mpeg3Plugin CFBundleInfoDictionaryVersion 6.0 CFBundleName mpeg3Plugin for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.6.0b1 CFBundleSignature FAST CFBundleVersion 1.6.0b1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/mpeglibAudioVideo.xml ================================================ ]> LibMPEG3ForSqueak UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:Squeak3.0 Folder:Squeak 3.1.1: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameLibMPEG3ForSqueak OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000100013A53717565616B20332E30416C70686131314D5400000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000B4F1AE010000000000001000B4F23F0 0002000000000000000000000B4F128000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel1 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileStd C Console 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos0 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameconditionalmacros.h MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline1 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix1 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap1 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsAll MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilempeg3Plugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name InterfaceLib MacOS Library Name MathLib MacOS Library Name dct.c MacOS Text Debug Name header.c MacOS Text Debug Name huffman.h MacOS Text Name layer1.c MacOS Text Debug Name layer2.c MacOS Text Debug Name layer3.c MacOS Text Debug Name mpeg3audio.c MacOS Text Debug Name mpeg3audio.h MacOS Text Name synthesizers.c MacOS Text Debug Name tables.c MacOS Text Debug Name tables.h MacOS Text Name mpeg3demux.c MacOS Text Debug Name bitstream.c MacOS Text Debug Name bitstream.h MacOS Text Name libmpeg3.c MacOS Text Debug Name libmpeg3.h MacOS Text Name mpeg3atrack.c MacOS Text Debug Name mpeg3atrack.h MacOS Text Name mpeg3io.c MacOS Text Debug Name mpeg3io.h MacOS Text Name mpeg3private.h MacOS Text Name mpeg3protos.h MacOS Text Name mpeg3title.c MacOS Text Debug Name mpeg3title.h MacOS Text Name mpeg3vtrack.c MacOS Text Debug Name mpeg3vtrack.h MacOS Text Name timecode.h MacOS Text Name changesForSqueak.c MacOS Text Debug Name mpeg3demux.h MacOS Text Name pcm.c MacOS Text Debug Name getpicture.c MacOS Text Debug Name headers.c MacOS Text Debug Name idct.c MacOS Text Debug Name idct.h MacOS Text Name layerdata.h MacOS Text Name macroblocks.c MacOS Text Debug Name mmxtest.c MacOS Text Debug Name motion.c MacOS Text Debug Name mpeg3video.c MacOS Text Debug Name mpeg3video.h MacOS Text Name mpeg3videoprotos.h MacOS Text Name output.c MacOS Text Debug Name reconstruct.c MacOS Text Debug Name seek.c MacOS Text Debug Name slice.c MacOS Text Debug Name slice.h MacOS Text Name vlc.c MacOS Text Debug Name vlc.h MacOS Text Name Mpeg3plugin.c MacOS Text Debug Name Mpeg3Plugin.h MacOS Text Name MSL RuntimePPC.Lib MacOS Library Debug Name MSL C.PPC.Lib MacOS Library Debug Name MSL SIOUX.PPC.Lib MacOS Library Debug Name ac3.h MacOS Text Name mpeg3css.h MacOS Text Name App.rsrc MacOS Resource Debug Name InterfaceLib MacOS Name MathLib MacOS Name dct.c MacOS Name header.c MacOS Name huffman.h MacOS Name layer1.c MacOS Name layer2.c MacOS Name layer3.c MacOS Name mpeg3audio.c MacOS Name mpeg3audio.h MacOS Name synthesizers.c MacOS Name tables.c MacOS Name tables.h MacOS Name mpeg3demux.c MacOS Name bitstream.c MacOS Name bitstream.h MacOS Name libmpeg3.c MacOS Name libmpeg3.h MacOS Name mpeg3atrack.c MacOS Name mpeg3atrack.h MacOS Name mpeg3io.c MacOS Name mpeg3io.h MacOS Name mpeg3private.h MacOS Name mpeg3protos.h MacOS Name mpeg3title.c MacOS Name mpeg3title.h MacOS Name mpeg3vtrack.c MacOS Name mpeg3vtrack.h MacOS Name timecode.h MacOS Name changesForSqueak.c MacOS Name mpeg3demux.h MacOS Name pcm.c MacOS Name getpicture.c MacOS Name headers.c MacOS Name idct.c MacOS Name idct.h MacOS Name layerdata.h MacOS Name macroblocks.c MacOS Name mmxtest.c MacOS Name motion.c MacOS Name mpeg3video.c MacOS Name mpeg3video.h MacOS Name mpeg3videoprotos.h MacOS Name output.c MacOS Name reconstruct.c MacOS Name seek.c MacOS Name slice.c MacOS Name slice.h MacOS Name vlc.c MacOS Name vlc.h MacOS Name Mpeg3plugin.c MacOS Name Mpeg3Plugin.h MacOS Name MSL RuntimePPC.Lib MacOS Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name ac3.h MacOS Name mpeg3css.h MacOS Name App.rsrc MacOS LibMPEG3ForSqueakOptimized UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:Squeak3.0 Folder:Squeak 3.1.1: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameLibMPEG3ForSqueakOptimized OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A6D7065672070726F647563 74696F6E3A53717565616B436F64653A53717565616B20332E30416C70686131 3000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000B4F1AE010000000000001000B4F23F0 0002000000000000000000000B4F128000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel1 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileStd C Console 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos0 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameconditionalmacros.h MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix1 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath0 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsAll MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilempeg3Plugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name InterfaceLib MacOS Library Name MathLib MacOS Library Name dct.c MacOS Text Name header.c MacOS Text Name huffman.h MacOS Text Name layer1.c MacOS Text Name layer2.c MacOS Text Name layer3.c MacOS Text Name mpeg3audio.c MacOS Text Name mpeg3audio.h MacOS Text Name synthesizers.c MacOS Text Name tables.c MacOS Text Name tables.h MacOS Text Name mpeg3demux.c MacOS Text Name bitstream.c MacOS Text Name bitstream.h MacOS Text Name libmpeg3.c MacOS Text Name libmpeg3.h MacOS Text Name mpeg3atrack.c MacOS Text Name mpeg3atrack.h MacOS Text Name mpeg3io.c MacOS Text Name mpeg3io.h MacOS Text Name mpeg3private.h MacOS Text Name mpeg3protos.h MacOS Text Name mpeg3title.c MacOS Text Name mpeg3title.h MacOS Text Name mpeg3vtrack.c MacOS Text Name mpeg3vtrack.h MacOS Text Name timecode.h MacOS Text Name changesForSqueak.c MacOS Text Name mpeg3demux.h MacOS Text Name pcm.c MacOS Text Name getpicture.c MacOS Text Name headers.c MacOS Text Name idct.c MacOS Text Name idct.h MacOS Text Name layerdata.h MacOS Text Name macroblocks.c MacOS Text Name mmxtest.c MacOS Text Name motion.c MacOS Text Name mpeg3video.c MacOS Text Name mpeg3video.h MacOS Text Name mpeg3videoprotos.h MacOS Text Name output.c MacOS Text Name reconstruct.c MacOS Text Name seek.c MacOS Text Name slice.c MacOS Text Name slice.h MacOS Text Name vlc.c MacOS Text Name vlc.h MacOS Text Name Mpeg3plugin.c MacOS Text Name Mpeg3Plugin.h MacOS Text Name MSL RuntimePPC.Lib MacOS Library Debug Name MSL C.PPC.Lib MacOS Library Debug Name MSL SIOUX.PPC.Lib MacOS Library Debug Name ac3.h MacOS Text Name mpeg3css.h MacOS Text Name App.rsrc MacOS Resource Name InterfaceLib MacOS Name MathLib MacOS Name dct.c MacOS Name header.c MacOS Name huffman.h MacOS Name layer1.c MacOS Name layer2.c MacOS Name layer3.c MacOS Name mpeg3audio.c MacOS Name mpeg3audio.h MacOS Name synthesizers.c MacOS Name tables.c MacOS Name tables.h MacOS Name mpeg3demux.c MacOS Name bitstream.c MacOS Name bitstream.h MacOS Name libmpeg3.c MacOS Name libmpeg3.h MacOS Name mpeg3atrack.c MacOS Name mpeg3atrack.h MacOS Name mpeg3io.c MacOS Name mpeg3io.h MacOS Name mpeg3private.h MacOS Name mpeg3protos.h MacOS Name mpeg3title.c MacOS Name mpeg3title.h MacOS Name mpeg3vtrack.c MacOS Name mpeg3vtrack.h MacOS Name timecode.h MacOS Name changesForSqueak.c MacOS Name mpeg3demux.h MacOS Name pcm.c MacOS Name getpicture.c MacOS Name headers.c MacOS Name idct.c MacOS Name idct.h MacOS Name layerdata.h MacOS Name macroblocks.c MacOS Name mmxtest.c MacOS Name motion.c MacOS Name mpeg3video.c MacOS Name mpeg3video.h MacOS Name mpeg3videoprotos.h MacOS Name output.c MacOS Name reconstruct.c MacOS Name seek.c MacOS Name slice.c MacOS Name slice.h MacOS Name vlc.c MacOS Name vlc.h MacOS Name Mpeg3plugin.c MacOS Name Mpeg3Plugin.h MacOS Name MSL RuntimePPC.Lib MacOS Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name ac3.h MacOS Name mpeg3css.h MacOS Name App.rsrc MacOS LibMpEG3 Carbon Opt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:Squeak3.0 Folder:Squeak 3.1.1: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameLibMpEG3 Carbon Opt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A6D7065672070726F647563 74696F6E3A53717565616B436F64653A53717565616B20332E30416C70686131 3000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000B4F1AE010000000000001000B4F23F0 0002000000000000000000000B4F128000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel1 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileStd C Console 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos0 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPCCarbon MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix1 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath0 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsAll MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilempeg3Plugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name dct.c MacOS Text Name header.c MacOS Text Name huffman.h MacOS Text Name layer1.c MacOS Text Name layer2.c MacOS Text Name layer3.c MacOS Text Name mpeg3audio.c MacOS Text Name mpeg3audio.h MacOS Text Name synthesizers.c MacOS Text Name tables.c MacOS Text Name tables.h MacOS Text Name mpeg3demux.c MacOS Text Name bitstream.c MacOS Text Name bitstream.h MacOS Text Name libmpeg3.c MacOS Text Name libmpeg3.h MacOS Text Name mpeg3atrack.c MacOS Text Name mpeg3atrack.h MacOS Text Name mpeg3io.c MacOS Text Name mpeg3io.h MacOS Text Name mpeg3private.h MacOS Text Name mpeg3protos.h MacOS Text Name mpeg3title.c MacOS Text Name mpeg3title.h MacOS Text Name mpeg3vtrack.c MacOS Text Name mpeg3vtrack.h MacOS Text Name timecode.h MacOS Text Name changesForSqueak.c MacOS Text Name mpeg3demux.h MacOS Text Name pcm.c MacOS Text Name getpicture.c MacOS Text Name headers.c MacOS Text Name idct.c MacOS Text Name idct.h MacOS Text Name layerdata.h MacOS Text Name macroblocks.c MacOS Text Name mmxtest.c MacOS Text Name motion.c MacOS Text Name mpeg3video.c MacOS Text Name mpeg3video.h MacOS Text Name mpeg3videoprotos.h MacOS Text Name output.c MacOS Text Name reconstruct.c MacOS Text Name seek.c MacOS Text Name slice.c MacOS Text Name slice.h MacOS Text Name vlc.c MacOS Text Name vlc.h MacOS Text Name Mpeg3plugin.c MacOS Text Name Mpeg3Plugin.h MacOS Text Name MSL RuntimePPC.Lib MacOS Library Debug Name ac3.h MacOS Text Name mpeg3css.h MacOS Text Name CarbonApp.rsrc MacOS Resource Name MSL C.CARBON.Lib MacOS Library Name MSL SIOUX.CARBON.Lib MacOS Library Name CarbonLib MacOS Library Name myMacHeadersCarbon.pch MacOS Text Name dct.c MacOS Name header.c MacOS Name huffman.h MacOS Name layer1.c MacOS Name layer2.c MacOS Name layer3.c MacOS Name mpeg3audio.c MacOS Name mpeg3audio.h MacOS Name synthesizers.c MacOS Name tables.c MacOS Name tables.h MacOS Name mpeg3demux.c MacOS Name bitstream.c MacOS Name bitstream.h MacOS Name libmpeg3.c MacOS Name libmpeg3.h MacOS Name mpeg3atrack.c MacOS Name mpeg3atrack.h MacOS Name mpeg3io.c MacOS Name mpeg3io.h MacOS Name mpeg3private.h MacOS Name mpeg3protos.h MacOS Name mpeg3title.c MacOS Name mpeg3title.h MacOS Name mpeg3vtrack.c MacOS Name mpeg3vtrack.h MacOS Name timecode.h MacOS Name changesForSqueak.c MacOS Name mpeg3demux.h MacOS Name pcm.c MacOS Name getpicture.c MacOS Name headers.c MacOS Name idct.c MacOS Name idct.h MacOS Name layerdata.h MacOS Name macroblocks.c MacOS Name mmxtest.c MacOS Name motion.c MacOS Name mpeg3video.c MacOS Name mpeg3video.h MacOS Name mpeg3videoprotos.h MacOS Name output.c MacOS Name reconstruct.c MacOS Name seek.c MacOS Name slice.c MacOS Name slice.h MacOS Name vlc.c MacOS Name vlc.h MacOS Name Mpeg3plugin.c MacOS Name Mpeg3Plugin.h MacOS Name MSL RuntimePPC.Lib MacOS Name ac3.h MacOS Name mpeg3css.h MacOS Name CarbonApp.rsrc MacOS Name MSL C.CARBON.Lib MacOS Name MSL SIOUX.CARBON.Lib MacOS Name CarbonLib MacOS Name myMacHeadersCarbon.pch MacOS LibMPEG3ForSqueak LibMPEG3ForSqueakOptimized LibMpEG3 Carbon Opt Sources Audio LibMPEG3ForSqueak Name ac3.h MacOS LibMPEG3ForSqueak Name dct.c MacOS LibMPEG3ForSqueak Name header.c MacOS LibMPEG3ForSqueak Name huffman.h MacOS LibMPEG3ForSqueak Name layer1.c MacOS LibMPEG3ForSqueak Name layer2.c MacOS LibMPEG3ForSqueak Name layer3.c MacOS LibMPEG3ForSqueak Name mpeg3audio.c MacOS LibMPEG3ForSqueak Name mpeg3audio.h MacOS LibMPEG3ForSqueak Name pcm.c MacOS LibMPEG3ForSqueak Name synthesizers.c MacOS LibMPEG3ForSqueak Name tables.c MacOS LibMPEG3ForSqueak Name tables.h MacOS Video LibMPEG3ForSqueak Name getpicture.c MacOS LibMPEG3ForSqueak Name headers.c MacOS LibMPEG3ForSqueak Name idct.c MacOS LibMPEG3ForSqueak Name idct.h MacOS LibMPEG3ForSqueak Name layerdata.h MacOS LibMPEG3ForSqueak Name macroblocks.c MacOS LibMPEG3ForSqueak Name mmxtest.c MacOS LibMPEG3ForSqueak Name motion.c MacOS LibMPEG3ForSqueak Name mpeg3video.c MacOS LibMPEG3ForSqueak Name mpeg3video.h MacOS LibMPEG3ForSqueak Name mpeg3videoprotos.h MacOS LibMPEG3ForSqueak Name output.c MacOS LibMPEG3ForSqueak Name reconstruct.c MacOS LibMPEG3ForSqueak Name seek.c MacOS LibMPEG3ForSqueak Name slice.c MacOS LibMPEG3ForSqueak Name slice.h MacOS LibMPEG3ForSqueak Name vlc.c MacOS LibMPEG3ForSqueak Name vlc.h MacOS LibMPEG3ForSqueak Name bitstream.c MacOS LibMPEG3ForSqueak Name bitstream.h MacOS LibMPEG3ForSqueak Name libmpeg3.c MacOS LibMPEG3ForSqueak Name libmpeg3.h MacOS LibMPEG3ForSqueak Name mpeg3atrack.c MacOS LibMPEG3ForSqueak Name mpeg3atrack.h MacOS LibMPEG3ForSqueak Name mpeg3css.h MacOS LibMPEG3ForSqueak Name mpeg3demux.c MacOS LibMPEG3ForSqueak Name mpeg3demux.h MacOS LibMPEG3ForSqueak Name mpeg3io.c MacOS LibMPEG3ForSqueak Name mpeg3io.h MacOS LibMPEG3ForSqueak Name mpeg3private.h MacOS LibMPEG3ForSqueak Name mpeg3protos.h MacOS LibMPEG3ForSqueak Name mpeg3title.c MacOS LibMPEG3ForSqueak Name mpeg3title.h MacOS LibMPEG3ForSqueak Name mpeg3vtrack.c MacOS LibMPEG3ForSqueak Name mpeg3vtrack.h MacOS LibMPEG3ForSqueak Name timecode.h MacOS LibMPEG3ForSqueak Name changesForSqueak.c MacOS LibMPEG3ForSqueak Name Mpeg3Plugin.h MacOS LibMPEG3ForSqueak Name Mpeg3plugin.c MacOS ANSI Libraries LibMPEG3ForSqueak Name MSL SIOUX.PPC.Lib MacOS LibMPEG3ForSqueak Name MSL C.PPC.Lib MacOS LibMPEG3ForSqueak Name MSL RuntimePPC.Lib MacOS resources LibMPEG3ForSqueak Name App.rsrc MacOS LibMpEG3 Carbon Opt Name CarbonApp.rsrc MacOS Mac Libraries LibMPEG3ForSqueak Name InterfaceLib MacOS LibMPEG3ForSqueak Name MathLib MacOS Carbon LibMpEG3 Carbon Opt Name myMacHeadersCarbon.pch MacOS LibMpEG3 Carbon Opt Name CarbonLib MacOS LibMpEG3 Carbon Opt Name MSL C.CARBON.Lib MacOS LibMpEG3 Carbon Opt Name MSL SIOUX.CARBON.Lib MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/myMacHeadersCarbon.pch ================================================ /* =========================================================================== MacHeaders.pch 1995-1999 Metrowerks Inc. All rights reserved. =========================================================================== Script to generate the 'MacHeaders' precompiled header for Metrowerks C. RA/8/19/98 Updated to Universal Headers 3.1 RA/7/14/99 Changed commenting style so you can built for ANSI Strict Support for automatically naming the C precompiled header file ... */ #if __POWERPC__ #pragma precompile_target "myMacHeadersPPCCarbon" #ifndef TARGET_API_MAC_CARBON #define TARGET_API_MAC_CARBON 1 #define ACCESSOR_CALLS_ARE_FUNCTIONS 1 #define OPAQUE_TOOLBOX_STRUCTS 1 #endif #elif __CFM68K__ #pragma precompile_target "myMacHeadersCFM68K" #else #pragma precompile_target "myMacHeaders68K" #endif /* Now just include the "MacHeaders.c" source file ... */ #pragma once on #include "myMacHeaders.c" ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/resources/App.rsrc ================================================ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/resources/CarbonApp.rsrc ================================================ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/sqMacFileBits.c ================================================ /* * sqMacFileBits.c * mpeglibAudioVideo * * Created by John M McIntosh on 15/02/06. * Copyright 2006 __MyCompanyName__. All rights reserved. * */ #include "sqMacFileBits.h" ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/Mpeg3Plugin/sqMacFileBits.h ================================================ /* * macFileNameBits.c * FT2Plugin support * * Created by John M McIntosh on 21/11/05. * Feb 15th, 2006, use sqFilenameFromString * */ #include "sqVirtualMachine.h" extern struct VirtualMachine * interpreterProxy; void sqFilenameFromStringOpen(char *buffer,long fileIndex, long fileLength, int flag) { interpreterProxy->ioFilenamefromStringofLengthresolveAliases(buffer,fileIndex, fileLength, flag); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/OpenALPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable CroquetPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.CroquetPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.0b1 CFBundleSignature FAST CFBundleVersion 1.0.0b1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/PrintJobPlugin/Info-PrintJobPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable PrintJobPlugin CFBundleGetInfoString PrintJobPlugin V1.2.0 for Squeak, see http://www.squeak.org CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.PrintJobPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName PrintJobPlugin V1.2.0 for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.2.0 CFBundleSignature FAST CFBundleVersion 1.2.1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/PrintJobPlugin/PrintJobPlugin.project.xml ================================================ ]> PrintJobPluginCarbon UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::::Carbon: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnamePrintJobPluginCarbon OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E30416C70686131384D54436172626F6E00 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPCCarbon MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilePrintJobPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name SqueakCarbonApp.rsrc MacOS Resource Name myMacHeadersCarbon.pch MacOS Text Debug Name MSL RuntimePPC.Lib MacOS Library Name PrintJobPlugin.c MacOS Text Debug Name PrintJobPlugin.h MacOS Text Name sqMacPrinting.c MacOS Text Debug Name sqMacPrinting.h MacOS Text Name MSL C.CARBON.Lib MacOS Library Name MSL SIOUX.CARBON.Lib MacOS Library Name CarbonLib MacOS Library Debug Name SqueakCarbonApp.rsrc MacOS Name myMacHeadersCarbon.pch MacOS Name MSL RuntimePPC.Lib MacOS Name PrintJobPlugin.c MacOS Name PrintJobPlugin.h MacOS Name sqMacPrinting.c MacOS Name sqMacPrinting.h MacOS Name MSL C.CARBON.Lib MacOS Name MSL SIOUX.CARBON.Lib MacOS Name CarbonLib MacOS PrintJobPluginCarbon Opt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::::Carbon: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnamePrintJobPluginCarbon Opt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E30416C70686131384D54436172626F6E00 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPCCarbon MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilePrintJobPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name SqueakCarbonApp.rsrc MacOS Resource Name myMacHeadersCarbon.pch MacOS Text Debug Name MSL RuntimePPC.Lib MacOS Library Name PrintJobPlugin.c MacOS Text Debug Name PrintJobPlugin.h MacOS Text Name sqMacPrinting.c MacOS Text Debug Name sqMacPrinting.h MacOS Text Name MSL C.CARBON.Lib MacOS Library Name MSL SIOUX.CARBON.Lib MacOS Library Name CarbonLib MacOS Library Debug Name SqueakCarbonApp.rsrc MacOS Name myMacHeadersCarbon.pch MacOS Name MSL RuntimePPC.Lib MacOS Name PrintJobPlugin.c MacOS Name PrintJobPlugin.h MacOS Name sqMacPrinting.c MacOS Name sqMacPrinting.h MacOS Name MSL C.CARBON.Lib MacOS Name MSL SIOUX.CARBON.Lib MacOS Name CarbonLib MacOS PrintJobPlugin Classic UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path::::Carbon: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:SqueakAtSourceForge:squeak:platforms: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnamePrintJobPlugin Classic OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A53717565616B3A53717565616B332E302046 6F6C6465723A53717565616B20332E302E31383A53717565616B20564D205050 4320446562756700000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000D06EEF010000000000001000D06F800 0002000000000000000000000D06D9E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline1 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ! MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfilePrintJobPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL RuntimePPC.Lib MacOS Library Name PrintJobPlugin.c MacOS Text Debug Name PrintJobPlugin.h MacOS Text Name sqMacPrinting.c MacOS Text Debug Name sqMacPrinting.h MacOS Text Name MSL C.PPC.Lib MacOS Library Debug Name InterfaceLib MacOS Library Debug Name myMacHeaders.pch MacOS Text Debug Name CarbonAccessors.o MacOS Library Debug Name MSL RuntimePPC.Lib MacOS Name PrintJobPlugin.c MacOS Name PrintJobPlugin.h MacOS Name sqMacPrinting.c MacOS Name sqMacPrinting.h MacOS Name MSL C.PPC.Lib MacOS Name InterfaceLib MacOS Name myMacHeaders.pch MacOS Name CarbonAccessors.o MacOS PrintJobPluginCarbon PrintJobPluginCarbon Opt PrintJobPlugin Classic Carbon PrintJobPluginCarbon Name MSL C.CARBON.Lib MacOS PrintJobPluginCarbon Name MSL SIOUX.CARBON.Lib MacOS PrintJobPluginCarbon Name CarbonLib MacOS PrintJobPluginCarbon Name SqueakCarbonApp.rsrc MacOS PrintJobPluginCarbon Name myMacHeadersCarbon.pch MacOS Classic PrintJobPlugin Classic Name MSL C.PPC.Lib MacOS PrintJobPlugin Classic Name InterfaceLib MacOS PrintJobPlugin Classic Name CarbonAccessors.o MacOS PrintJobPlugin Classic Name myMacHeaders.pch MacOS Group 1 PrintJobPluginCarbon Name MSL RuntimePPC.Lib MacOS PrintJobPluginCarbon Name PrintJobPlugin.c MacOS PrintJobPluginCarbon Name PrintJobPlugin.h MacOS PrintJobPluginCarbon Name sqMacPrinting.c MacOS PrintJobPluginCarbon Name sqMacPrinting.h MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/PrintJobPlugin/RealPrinting-JMM.7.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 18 January 2007 at 10:50:25 am'! Object subclass: #PrintJob instanceVariableNames: 'sessionBits sessionIndex pageRect' classVariableNames: 'Registry' poolDictionaries: '' category: 'Graphics-Text'! !PrintJob commentStamp: 'JMM 2/9/2002 00:47' prior: 0! A simple print interface by johnmci@smalltalkconsulting.com Originally written for macintosh carbon applications. Usually you invoke a utility method to print a set of forms, or postscript objects. Basically you invoke primPrintSetup to setup printing for a set of pages. printPreProcessing: totalPages to setup printing, which later must exit by calling printPostProcessing then you invoke pagePreProcessing to setup to print a page, which later must exit by calling pagePostProcessing Then you invoke setForm: or setPostscript: to image a form or postscript as many times as needed, then as mentioned pagePostProcessing to close the page, and finaly printPostProcessing to close the print job, with printCleanup to release all the resources. ! !PrintJob methodsFor: 'accessors' stamp: 'JMM 2/9/2002 13:50'! session sessionIndex isNil ifTrue:[^nil]. (Smalltalk externalObjects at: sessionIndex ifAbsent: [^nil]) == sessionBits ifTrue: [^sessionBits] ifFalse: [^nil]. ! ! !PrintJob methodsFor: 'initialize-release' stamp: 'pe 12/16/2006 16:52'! initialize pageRect := Rectangle origin: 0@0 corner: 0@0. paperRect := Rectangle origin: 0@0 corner: 0@0. dpi := (300@300). sessionBits _ self primPrintSetup. sessionBits notNil ifTrue: [sessionIndex _ Smalltalk registerExternalObject: sessionBits. self register] ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/8/2002 00:13'! pagePostProcessing ^self primPagePostProcessing: self session ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/8/2002 00:14'! pagePreProcessing ^self primPagePreProcessing: self session ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/9/2002 01:32'! printCleanup [self primPrintCleanup: self session] ensure: [self finalize]! ! !PrintJob methodsFor: 'logic' stamp: 'pe 12/16/2006 16:55'! printFullPageForm: aForm | status statusPostProcessing | self session isNil ifTrue: [self beep. ^-1]. [status _ self printPreProcessing: 1 dpi: dpi. "printPreProcessing: dpi: returns these values: Transcript show: 'pageRect: ', pageRect; cr. Transcript show: 'paperRect: ', paperRect; cr. Transcript show: 'dpi: ', dpi; cr. " self pagePreProcessing. status ~= 0 ifTrue: [^status]. self setFullPageForm: aForm] ensure: [ self pagePostProcessing. statusPostProcessing _ self printPostProcessing. self printCleanup]. status ~= 0 ifTrue: [^status]. ^statusPostProcessing.! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/9/2002 12:28'! printGetFirstPageNumber ^self primGetFirstPageNumber: self session ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/9/2002 12:28'! printGetLastPageNumber ^self primGetLastPageNumber: self session ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/7/2002 18:32'! printPostProcessing ^self primPrintPostProcessing: self session ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/7/2002 18:32'! printPreProcessing: aNumber ^self primPrintPreProcessing: self session pages: aNumber! ! !PrintJob methodsFor: 'logic' stamp: 'pe 12/16/2006 16:55'! printPreProcessing: aNumber dpi: dpiPoint ^self primPrintPreProcessing: self session pages: aNumber pageRectangle: pageRect paperRectangle: paperRect dpi: dpi! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/8/2002 21:07'! setForm: aForm ^self setForm: aForm scaleHeight: 1.0 scaleWidth: 1.0 ! ! !PrintJob methodsFor: 'logic' stamp: 'pe 12/12/2006 09:44'! setForm: aForm at: aSymbol "this is not yet generally working, for Plopp I needed just the #topCenter case. pe 12/12/2006 09:44" | formRatio printRatio printExtent inRect aPoint | formRatio := aForm width asFloat / aForm height asFloat. printRatio := pageRect width asFloat / pageRect height asFloat. printRatio <= formRatio ifTrue: [ printExtent := pageRect width @ (pageRect width asFloat / formRatio)] ifFalse: [ printExtent := (pageRect height * formRatio) @ pageRect height]. inRect := Rectangle origin: (0@0) extent: printExtent truncated. aPoint := (pageRect perform: aSymbol). inRect := inRect perform: (aSymbol, ':')asSymbol with: aPoint. inRect := Rectangle origin: inRect origin extent: printExtent truncated. ^self setForm: aForm in: inRect.! ! !PrintJob methodsFor: 'logic' stamp: 'pe 12/8/2006 20:02'! setForm: aForm in: inRect aForm unhibernate. ^self primPageSetForm: self session bits: aForm bits bitmapHeight: aForm height truncated bitmapWidth: aForm width truncated bitmapDepth: aForm depth truncated printHeight: inRect height truncated printWidth: inRect width truncated offsetH: inRect top truncated offsetW: inRect left truncated.! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/20/2002 11:56'! setForm: aForm scaleHeight: sh scaleWidth: sw ^self setForm: aForm scaleHeight: sh scaleWidth: sw offsetHeight: 0 offsetWidth: 0! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/20/2002 10:25'! setForm: aForm scaleHeight: sh scaleWidth: sw offsetHeight: oh offsetWidth: ow aForm unhibernate. ^self primPageSetForm: self session bits: aForm bits height: aForm height width: aForm width depth: aForm depth scaleH: sh scaleW: sw offsetH: oh offsetW: ow ! ! !PrintJob methodsFor: 'logic' stamp: 'pe 12/16/2006 16:56'! setFullPageForm: aForm | formRatio printRatio printExtent inRect | formRatio := aForm width asFloat / aForm height asFloat. printRatio := pageRect width asFloat / pageRect height asFloat. printRatio <= formRatio ifTrue: [ printExtent := pageRect width @ (pageRect width asFloat / formRatio)] ifFalse: [ printExtent := (pageRect height * formRatio) @ pageRect height]. inRect := (Rectangle center: pageRect center extent: printExtent truncated). ^self setForm: aForm in: inRect. ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/8/2002 01:20'! setPostscript: aText ^self primPageSetPostscript: self session postscript: aText! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/9/2002 13:49'! startJob: objects | status statusPostProcessing | self session isNil ifTrue: [^-1]. [status _ self printPreProcessing: objects size. status ~= 0 ifTrue: [^status]. self printGetFirstPageNumber to: self printGetLastPageNumber do: [:index | status _ self startPage: (objects at: index)]] ensure: [statusPostProcessing _ self printPostProcessing. self printCleanup]. status ~= 0 ifTrue: [^status]. ^statusPostProcessing ! ! !PrintJob methodsFor: 'logic' stamp: 'JMM 2/8/2002 22:48'! startPage: aObject | status | [status _ self pagePreProcessing. status ~= 0 ifTrue: [^status]. aObject isForm ifTrue: [status _ self setForm: aObject] ifFalse: [status _ self setPostscript: aObject]. status ~= 0 ifTrue: [^status]] ensure: [status _ self pagePostProcessing]. ^status ! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/9/2002 12:27'! primGetFirstPageNumber: aSession "get first page number" ^0! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/9/2002 12:27'! primGetLastPageNumber: aSession "get last page number" ^0! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/8/2002 00:41'! primPagePostProcessing: aSession "Page post processing" self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/8/2002 00:13'! primPagePreProcessing: aSession "Page preprocessing" self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'pe 12/8/2006 19:57'! primPageSetForm: aSessionHandle bits: aBitMap bitmapHeight: bh bitmapWidth: bw bitmapDepth: bd printHeight: ph printWidth: pw offsetH: oh offsetW: ow "setup form " ^nil. "self primitiveFailed"! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/20/2002 10:22'! primPageSetForm: aSessionHandle bits: aBitMap height: h width: w depth: d scaleH: sh scaleW: sw offsetH: oh offsetW: ow "setup form " self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/8/2002 00:11'! primPageSetPostscript: aSessionHandle postscript: aText "setup postscript " self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/9/2002 01:52'! primPrintCleanup: aSession "Print cleanup processing" ! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/9/2002 01:27'! primPrintPostProcessing: aSession "Print post processing" ! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/7/2002 18:32'! primPrintPreProcessing: aSession pages: aNumber "Printing preprocessing" self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'pe 12/16/2006 16:53'! primPrintPreProcessing: aSession pages: aNumber pageRectangle: pageRectangle paperRectangle: paperRectangle dpi: dpiPoint "Printing preprocessing" self primitiveFailed! ! !PrintJob methodsFor: 'system primitives' stamp: 'JMM 2/9/2002 13:25'! primPrintSetup "Setup printing" ^nil! ! !PrintJob methodsFor: 'system primitives' stamp: 'pe 12/16/2006 16:54'! primPrintSetupPage: pageRectangle paper: paperRectangle dpi: dpiPoint "Setup printing" self halt. ^nil. "If the user pressed cancel, we don't want a primitive failed. We do the checks using session bits"! ! !PrintJob methodsFor: 'system primitives' stamp: 'pe 12/8/2006 18:53'! primPrintSetupRect: aRectangle "Setup printing" ^nil. "If the user pressed cancel, we don't want a primitive failed. We do the checks using session bits"! ! !PrintJob methodsFor: 'utility' stamp: 'JMM 2/8/2002 21:28'! printForms: aCollectionOfForms ^self startJob: aCollectionOfForms ! ! !PrintJob methodsFor: 'utility' stamp: 'JMM 2/8/2002 21:10'! printForm: aForm ^self printForms: (Array with: aForm) ! ! !PrintJob methodsFor: 'utility' stamp: 'JMM 2/8/2002 21:30'! printPostscriptObjects: aCollection ^self startJob: aCollection ! ! !PrintJob methodsFor: 'utility' stamp: 'JMM 2/8/2002 22:49'! printPostscript: aText ^self printPostscriptObjects: (Array with: aText) ! ! !PrintJob methodsFor: 'private' stamp: 'JMM 2/9/2002 01:58'! finalize self session notNil ifTrue: [self primPrintCleanup: self session]. self session = sessionBits ifTrue: [Smalltalk unregisterExternalObject: sessionIndex]. self unregister. sessionBits _ nil. sessionIndex _ 0.! ! !PrintJob methodsFor: 'private' stamp: 'JMM 2/9/2002 01:29'! register ^self class register: self! ! !PrintJob methodsFor: 'private' stamp: 'JMM 2/9/2002 01:29'! unregister ^self class unregister: self! ! !PrintJob class methodsFor: 'utility' stamp: 'JMM 2/9/2002 00:19'! printForms: forms ^super new initialize printForms: forms! ! !PrintJob class methodsFor: 'utility' stamp: 'JMM 2/9/2002 00:12'! printForm: aForm ^self printForms: (Array with: aForm)! ! !PrintJob class methodsFor: 'utility' stamp: 'JMM 2/9/2002 00:48'! printPostscriptObjects: aCollection ^super new initialize printPostscriptObjects: aCollection! ! !PrintJob class methodsFor: 'utility' stamp: 'JMM 2/9/2002 00:49'! printPostscript: aString ^self printPostscriptObjects: (Array with: aString)! ! !PrintJob class methodsFor: 'registery' stamp: 'JMM 2/9/2002 01:21'! register: anObject WeakArray isFinalizationSupported ifFalse:[^anObject]. self registry add: anObject! ! !PrintJob class methodsFor: 'registery' stamp: 'JMM 2/9/2002 01:21'! registry WeakArray isFinalizationSupported ifFalse:[^nil]. ^Registry isNil ifTrue:[Registry := WeakRegistry new] ifFalse:[Registry].! ! !PrintJob class methodsFor: 'registery' stamp: 'JMM 2/9/2002 01:21'! unregister: anObject WeakArray isFinalizationSupported ifFalse:[^anObject]. self registry remove: anObject ifAbsent:[]! ! PrintJob class removeSelector: #new! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/PrintJobPlugin/sqMacPrinting.c ================================================ /**************************************************************************** * PROJECT: Mac printing * FILE: sqMacPrinting.c * CONTENT: * * AUTHOR: John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacPrinting.c 1206 2005-06-02 20:21:11Z johnmci $ * * NOTES: * Take carbon sample code, and alter it a bit * Feb 20th 2002, JMM - add offset logic, free printsession only if allocated (duh) * Jun 27th 2002, JMM - use UILock code to lock UI to prevent os-x seg fault * Aug 7th, 2002, JMM - fixes to build as internal * *****************************************************************************/ #include "sqVirtualMachine.h" #include "sqMacPrinting.h" /*------------------------------------------------------------------------------ This sample code is the Carbon equivalent of the classic print loop documented in Tech Note 1092 "A Print Loop That Cares ...". This code illustrates the use of functions defined in PMCore.h and PMApplication.h instead of Printing.h. You may incorporate this sample code into your applications without restriction, though the sample code has been provided "AS IS" and the responsibility for its operation is 100% yours. However, what you are not permitted to do is to redistribute the source as "Apple Sample Code" after having made changes. If you're going to re-distribute the source, we require that you make it clear in the source that the code was descended from Apple Sample Code, but that you've made changes. Version: 1.0.1 Technology: Carbon Printing for Mac OS 8, 9 & X Copyright 1998-2001 Apple Computer, Inc ., All Rights Reserved Change History: ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ Globals ------------------------------------------------------------------------------*/ static CTabHandle stColorTable = nil; static PixMapHandle stPixMap = nil; extern struct VirtualMachine *interpreterProxy; /*------------------------------------------------------------------------------ Prototypes ------------------------------------------------------------------------------*/ static void SetColorEntry(int index, int red, int green, int blue); static void SetUpPixmap(void); static void FreePixmap(void); static Boolean RunningOnCarbonX(void); OSStatus DoPrintLoop(PrintingLogicPtr printJob); OSStatus DrawPage(PrintingLogicPtr printJob); #if TARGET_API_MAC_CARBON OSStatus DoPageSetupDialog(PrintingLogicPtr printJob); OSStatus DoPrintDialog(PrintingLogicPtr printJob); OSStatus FlattenAndSavePageFormat(PrintingLogicPtr printJob); OSStatus LoadAndUnflattenPageFormat(PrintingLogicPtr printJob); OSStatus DetermineNumberOfPagesInDoc(UInt32 *numPages,PrintingLogicPtr printJob); Boolean IncludePostScriptInSpoolFile(PrintingLogicPtr printJob); /*------------------------------------------------------------------------------ Description: Uses PMCreateSession/PMRelease instead of PMBegin/PMEnd. Note that the two printing objects, PMPageSetup and PMPrintSettings are valid outside the printing session. This was not the case with PMBegin/PMEnd in the previous version of this sample code. Note also that no nesting of printing sessions is allowed for Carbon applications running under MacOS 8 or 9. ------------------------------------------------------------------------------*/ int ioPrintSetup(PrintingLogicPtr *token) { OSStatus status = noErr; PrintingLogicPtr printJob; printJob = *token = calloc(1,sizeof(PrintingLogic)); printJob->printSession = NULL; printJob->pageFormat = kPMNoPageFormat; printJob->printSettings = kPMNoPrintSettings; printJob->flatFormatHandle = NULL; printJob->numberOfPages = 0; // Initialize the printing manager and create a printing session. status = PMCreateSession(&printJob->printSession); if (status != noErr) return -1; // pointless to continue if PMCreateSession fails // Display the Page Setup dialog. if (status == noErr) { status = DoPageSetupDialog(printJob); } return status; } int ioPrintPreProcessing(PrintingLogicPtr printJob,int numberOfPages) { OSStatus status = noErr; UInt32 realNumberOfPagesinDoc; // Display the Print dialog. if (printJob->printSession == NULL) return -1; printJob->numberOfPages = numberOfPages; printJob->allowPostscript = false; status = DoPrintDialog(printJob); if (status == noErr) { //issues with os 9 don't do CFStringRef jobName = CFSTR("Squeak"); //issues with os 9 don't do status = PMSetJobNameCFString(printJob->printSettings, jobName); // Get the user's Print dialog selection for first and last pages to print. if (status == noErr) { status = PMGetFirstPage(printJob->printSettings, &printJob->firstPage); if (status == noErr) status = PMGetLastPage(printJob->printSettings, &printJob->lastPage); } // Check that the selected page range does not exceed the actual number of // pages in the document. if (status == noErr) { status = DetermineNumberOfPagesInDoc(&realNumberOfPagesinDoc,printJob); if (realNumberOfPagesinDoc < printJob->lastPage) printJob->lastPage = realNumberOfPagesinDoc; } // Before executing the print loop, tell the Carbon Printing Manager which pages // will be spooled so that the progress dialog can reflect an accurate page count. // This is recommended on Mac OS X. On Mac OS 8 and 9, we have no control over // what the printer driver displays. if (status == noErr) status = PMSetFirstPage(printJob->printSettings, printJob->firstPage, false); if (status == noErr) status = PMSetLastPage(printJob->printSettings, printJob->lastPage, false); if (status == noErr) status = PMSetPageRange(printJob->printSettings, 1, printJob->lastPage-printJob->firstPage+1); // Check if we can add PostScript to the spool file if (status == noErr) printJob->allowPostscript = IncludePostScriptInSpoolFile(printJob); // Begin a new print job. status = PMSessionBeginDocument(printJob->printSession, printJob->printSettings, printJob->pageFormat); } return status; } int ioPagePreProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; status = PMSessionBeginPage(printJob->printSession, printJob->pageFormat, NULL); return status; } int ioPrint(PrintingLogicPtr printJob) { OSStatus status = noErr; if (printJob->printSession == NULL) return -1; // Execute the print loop. if (status == noErr) status = DoPrintLoop(printJob); if(status == kPMCancel) status = noErr; return status; } int ioPagePostProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; // Close the page. status = PMSessionEndPage(printJob->printSession); return status; } int ioPrintPostProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; // Close the print job. This dismisses the progress dialog on Mac OS X. status = PMSessionEndDocument(printJob->printSession); return status; } int ioPrintGetFirstPageNumber(PrintingLogicPtr printJob){ if (printJob->printSession == NULL) return 0; return printJob->firstPage; } int ioPrintGetLastPageNumber(PrintingLogicPtr printJob){ if (printJob->printSession == NULL) return 0; return printJob->lastPage; } int ioPrintCleanup(PrintingLogicPtr *token) { PrintingLogicPtr printJob; // Release the PageFormat and PrintSettings objects. PMRelease decrements the // ref count of the allocated objects. We let the Printing Manager decide when // to release the allocated memory. printJob = *token; if (printJob == nil) return 0; if (printJob->pageFormat != kPMNoPageFormat) (void)PMRelease(printJob->pageFormat); if (printJob->printSettings != kPMNoPrintSettings) (void)PMRelease(printJob->printSettings); // Terminate the current printing session. if (printJob->printSession != NULL) (void)PMRelease(printJob->printSession); printJob->pageFormat = kPMNoPageFormat; printJob->printSettings = kPMNoPrintSettings; printJob->printSession = NULL; free(printJob); *token = nil; return 0; } /*------------------------------------------------------------------------------ Function: DoPageSetupDialog Parameters: Description: If the caller passes in an empty PageFormat object, DoPageSetupDialog creates a new one, otherwise it validates the one provided by the caller. It then invokes the Page Setup dialog and checks for Cancel. Finally it flattens the PageFormat object so it can be saved with the document. Note that the PageFormat object is modified by this function. ------------------------------------------------------------------------------*/ OSStatus DoPageSetupDialog(PrintingLogicPtr printJob) { OSStatus status = noErr; Boolean accepted; // Set up a valid PageFormat object. if (printJob->pageFormat == kPMNoPageFormat) { status = PMCreatePageFormat(&printJob->pageFormat); // Note that PMPageFormat is not session-specific, but calling // PMSessionDefaultPageFormat assigns values specific to the printer // associated with the current printing session. if ((status == noErr) && (printJob->pageFormat != kPMNoPageFormat)) status = PMSessionDefaultPageFormat(printJob->printSession, printJob->pageFormat); } else status = PMSessionValidatePageFormat(printJob->printSession, printJob->pageFormat, kPMDontWantBoolean); /* This is broken fn = interpreterProxy->ioLoadFunctionFrom("getSTWindow", ""); if (fn != 0) { WindowPtr windowRef; windowRef = (WindowPtr) ((int (*) ()) fn)(); PMSessionUseSheets(printJob->printSession,windowRef,NULL); } */ // Display the Page Setup dialog. if (status == noErr) { void * giLocker; giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*6); foo[0] = 3; foo[1] = (long) PMSessionPageSetupDialog; foo[2] = (long)printJob->printSession; foo[3] = (long)printJob->pageFormat; foo[4] = (long)&accepted; foo[5] = 0; ((int (*) (void *)) giLocker)(foo); status = foo[5]; free(foo); } else status = PMSessionPageSetupDialog(printJob->printSession, printJob->pageFormat, &accepted); if (status == noErr && !accepted) status = kPMCancel; // user clicked Cancel button } // If the user did not cancel, flatten and save the PageFormat object // with our document. if (status == noErr) status = FlattenAndSavePageFormat(printJob); return status; } // DoPageSetupDialog /*------------------------------------------------------------------------------ Function: DoPrintDialog Parameters: Description: If the caller passes an empty PrintSettings object, DoPrintDialog creates a new one, otherwise it validates the one provided by the caller. It then invokes the Print dialog and checks for Cancel. Note that the PrintSettings object is modified by this function. ------------------------------------------------------------------------------*/ OSStatus DoPrintDialog(PrintingLogicPtr printJob) { OSStatus status = noErr; Boolean accepted; UInt32 realNumberOfPagesinDoc; // In this sample code the caller provides a valid PageFormat reference but in // your application you may want to load and unflatten the PageFormat object // that was saved at PageSetup time. See LoadAndUnflattenPageFormat below. // Set up a valid PrintSettings object. if (printJob->printSettings == kPMNoPrintSettings) { status = PMCreatePrintSettings(&printJob->printSettings); // Note that PMPrintSettings is not session-specific, but calling // PMSessionDefaultPrintSettings assigns values specific to the printer // associated with the current printing session. if ((status == noErr) && (printJob->printSettings != kPMNoPrintSettings)) status = PMSessionDefaultPrintSettings(printJob->printSession, printJob->printSettings); } else status = PMSessionValidatePrintSettings(printJob->printSession, printJob->printSettings, kPMDontWantBoolean); // Before displaying the Print dialog, we calculate the number of pages in the // document. On Mac OS X this is useful because we can prime the Print dialog // with the actual page range of the document and prevent the user from entering // out-of-range numbers. This is not possible on Mac OS 8 and 9 because the driver, // not the printing manager, controls the page range fields in the Print dialog. // Calculate the number of pages required to print the entire document. if (status == noErr) status = DetermineNumberOfPagesInDoc(&realNumberOfPagesinDoc,printJob); // Set a valid page range before displaying the Print dialog if (status == noErr) status = PMSetPageRange(printJob->printSettings, 1, realNumberOfPagesinDoc); // Display the Print dialog. if (status == noErr) { void * giLocker; giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*7); foo[0] = 4; foo[1] = (long)PMSessionPrintDialog; foo[2] = (long)printJob->printSession; foo[3] = (long)printJob->printSettings; foo[4] = (long)printJob->pageFormat; foo[5] = (long)&accepted; foo[6] = 0; ((int (*) (void *)) giLocker)(foo); status = foo[6]; free(foo); } else status = PMSessionPrintDialog(printJob->printSession, printJob->printSettings, printJob->pageFormat, &accepted); if (status == noErr && !accepted) status = kPMCancel; // user clicked Cancel button } return status; } // DoPrintDialog /*------------------------------------------------------------------------------ Function: DoPrintLoop Parameters: Description: DoPrintLoop calculates which pages to print and executes the print loop, calling DrawPage for each page. ------------------------------------------------------------------------------*/ OSStatus DoPrintLoop(PrintingLogicPtr printJob) { OSStatus status = noErr, tempErr; GrafPtr currPort, printingPort; // Note, we don't have to worry about the number of copies. The printing // manager handles this. So we just iterate through the document from the // first page to be printed, to the last. // Note, we don't have to deal with the classic Printing Manager's // 128-page boundary limit. // Set up a page for printing. Under the classic Printing Manager, applications // could provide a page rect different from the one in the print record to achieve // scaling. This is no longer recommended and on Mac OS X, the PageRect argument // is ignored. // Save the current QD grafport. GetPort(&currPort); // Get the current graphics context, in this case a Quickdraw grafPort, // for drawing the page. status = PMSessionGetGraphicsContext(printJob->printSession, kPMGraphicsContextQuickdraw, (void**) &printingPort); if (status == noErr) { // Set the printing port before drawing the page. SetPort((GrafPtr) printingPort); // Draw the page. status = DrawPage(printJob); // Restore the QD grafport. SetPort(currPort); } // Only report a printing error once we have completed the print loop. This // ensures that every PMBeginXXX call that returns no error is followed by // a matching PMEndXXX call, so the Printing Manager can release all temporary // memory and close properly. tempErr = PMSessionError(printJob->printSession); if(status == noErr) status = tempErr; if (status == kPMCancel) status = noErr; return status; } // DoPrintLoop /*------------------------------------------------------------------------------ Function: FlattenAndSavePageFormat Parameters: pageFormat - a PageFormat object Description: Flattens a PageFormat object so it can be saved with the document. Assumes caller passes a validated PageFormat object. ------------------------------------------------------------------------------*/ OSStatus FlattenAndSavePageFormat(PrintingLogicPtr printJob) { OSStatus status; printJob->flatFormatHandle = NULL; // Flatten the PageFormat object to memory. status = PMFlattenPageFormat(printJob->pageFormat, &printJob->flatFormatHandle); return status; } // FlattenAndSavePageFormat /*------------------------------------------------------------------------------ Function: LoadAndUnflattenPageFormat Parameters: pageFormat - PageFormat object read from document file Description: Gets flattened PageFormat data from the document and returns a PageFormat object. The function is not called in this sample code but your application will need to retrieve PageFormat data saved with documents. ------------------------------------------------------------------------------*/ OSStatus LoadAndUnflattenPageFormat(PrintingLogicPtr printJob) { OSStatus status = noErr; if(printJob->flatFormatHandle){ // Convert the PageFormat flattened data into a PageFormat object. status = PMUnflattenPageFormat(printJob->flatFormatHandle,&printJob->pageFormat); }else{ printJob->pageFormat = kPMNoPageFormat; } return status; } // LoadAndUnflattenPageFormat /*------------------------------------------------------------------------------ Function: DetermineNumberOfPagesInDoc Parameters: pageFormat - a PageFormat object addr numPages - on return, the size of the document in pages Description: Calculates the number of pages needed to print the entire document. ------------------------------------------------------------------------------*/ OSStatus DetermineNumberOfPagesInDoc(UInt32 *numPages,PrintingLogicPtr printJob) { OSStatus status; PMRect pageRect; // PMGetAdjustedPageRect returns the page size taking into account rotation, // resolution and scaling settings. status = PMGetAdjustedPageRect(printJob->pageFormat, &pageRect); // In this sample code we simply return a hard coded number. In your application, // you will need to figure out how many page rects are needed to image the // current document. *numPages = printJob->numberOfPages; return status; } // DetermineNumberOfPagesinDoc /*------------------------------------------------------------------------------ Function: IncludePostScriptInSpoolFile Parameters: printSession - current printing session Description: Check if current printer driver supports embedding of PostScript in the spool file, and if it does, instruct the Carbon Printing Manager to generate a PICT w/ PS spool file. ------------------------------------------------------------------------------*/ Boolean IncludePostScriptInSpoolFile(PrintingLogicPtr printJob) { Boolean includePostScript = false; OSStatus status; CFArrayRef supportedFormats = NULL; SInt32 i, numSupportedFormats; // Get the list of spool file formats supported by the current driver. // PMSessionGetDocumentFormatGeneration returns the list of formats which can be generated // by the spooler (client-side) AND converted by the despooler (server-side). // PMSessionGetDocumentFormatSupported only returns the list of formats which can be converted // by the despooler. status = PMSessionGetDocumentFormatGeneration(printJob->printSession, &supportedFormats); if (status == noErr) { // Check if PICT w/ PS is in the list of supported formats. numSupportedFormats = CFArrayGetCount(supportedFormats); for (i=0; i < numSupportedFormats; i++) { /* if ( CFStringCompare(CFArrayGetValueAtIndex(supportedFormats, i), kPMDocumentFormatPDF, kCFCompareCaseInsensitive) == kCFCompareEqualTo ) return true; if ( CFStringCompare(CFArrayGetValueAtIndex(supportedFormats, i), kPMDocumentFormatPostScript, kCFCompareCaseInsensitive) == kCFCompareEqualTo ) return true;*/ if ( CFStringCompare(CFArrayGetValueAtIndex(supportedFormats, i), kPMDocumentFormatPICTPS, kCFCompareCaseInsensitive) == kCFCompareEqualTo ) { // PICT w/ PS is supported, so tell the Printing Mgr to generate a PICT w/ PS spool file // Build an array of graphics contexts containing just one type, Quickdraw, // meaning that we will be using a QD port to image our pages in the print loop. CFStringRef strings[1]; CFArrayRef arrayOfGraphicsContexts; strings[0] = kPMGraphicsContextQuickdraw; arrayOfGraphicsContexts = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, 1, &kCFTypeArrayCallBacks); if (arrayOfGraphicsContexts != NULL) { // Request a PICT w/ PS spool file status = PMSessionSetDocumentFormatGeneration(printJob->printSession, kPMDocumentFormatPICTPS, arrayOfGraphicsContexts, NULL); if (status == noErr) { includePostScript = true; // Enable use of PS PicComments in DrawPage. } // Deallocate the array used for the list of graphics contexts. CFRelease(arrayOfGraphicsContexts); } break; } } // Deallocate the array used for the list of supported spool file formats. CFRelease(supportedFormats); } return includePostScript; } // IncludePostScriptInSpoolFile #else int ioPrintSetup(PrintingLogicPtr *token) { OSStatus status = noErr; PrintingLogicPtr printJob; printJob = *token = (PrintingLogicPtr) NewPtrClear(sizeof(PrintingLogic)); printJob->thePrRecHdl = (THPrint) NewHandle (sizeof (TPrint)); status = MemError(); if (status != noErr) return -1; // pointless to continue if memory allocation fails // Initialize the printing manager and create a printing session. PrOpen(); //The PrOpen procedure prepares the current printer driver for use. status = PrError(); if (status != noErr) return status; PrintDefault(printJob->thePrRecHdl); status = PrError(); if (status != noErr) return status; PrValidate(printJob->thePrRecHdl); status = PrError(); if (status != noErr) return status; // Display the Page Setup dialog. if (! PrStlDialog(printJob->thePrRecHdl)) goto cleanup; // user cancelled return status; cleanup: DisposeHandle ((Handle) printJob->thePrRecHdl); printJob->thePrRecHdl = NULL; return -4; } int ioPrintPreProcessing(PrintingLogicPtr printJob,int numberOfPages) { OSStatus status = noErr; UInt32 realNumberOfPagesinDoc; if (printJob->thePrRecHdl == NULL) return -1; printJob->numberOfPages = numberOfPages; printJob->allowPostscript = false; if (!PrJobDialog(printJob->thePrRecHdl)) return -2; if (status == noErr) { // Get the user's Print dialog selection for first and last pages to print. if (status == noErr) { TPPrint foo = *printJob->thePrRecHdl; printJob->firstPage = foo->prJob.iFstPage; printJob->lastPage = foo->prJob.iLstPage; } // Check that the selected page range does not exceed the actual number of // pages in the document. if (status == noErr) { realNumberOfPagesinDoc = printJob->numberOfPages; if (realNumberOfPagesinDoc < printJob->lastPage) printJob->lastPage = realNumberOfPagesinDoc; } // Begin a new print job. printJob->thePrPort = PrOpenDoc(printJob->thePrRecHdl, nil, nil); status = PrError(); } return status; } int ioPagePreProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; PrOpenPage(printJob->thePrPort, nil); status = PrError(); return status; } int ioPrint(PrintingLogicPtr printJob) { OSStatus status = noErr; if (printJob->thePrRecHdl == NULL) return -1; // Execute the print loop. if (status == noErr) status = DoPrintLoop(printJob); if(status == kPMCancel) status = noErr; return status; } int ioPagePostProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; // Close the page. PrClosePage(printJob->thePrPort); status = PrError(); return status; } int ioPrintPostProcessing(PrintingLogicPtr printJob) { OSStatus status = noErr; // Close the print job. This dismisses the progress dialog on Mac OS X. PrCloseDoc(printJob->thePrPort); status = PrError(); return status; } int ioPrintGetFirstPageNumber(PrintingLogicPtr printJob){ if (printJob->thePrRecHdl == NULL) return 0; return printJob->firstPage; } int ioPrintGetLastPageNumber(PrintingLogicPtr printJob){ if (printJob->thePrRecHdl == NULL) return 0; return printJob->lastPage; } int ioPrintCleanup(PrintingLogicPtr *token) { PrintingLogicPtr printJob; // Release the PageFormat and PrintSettings objects. PMRelease decrements the // ref count of the allocated objects. We let the Printing Manager decide when // to release the allocated memory. printJob = *token; if (printJob == nil) return 0; // Terminate the current printing session. PrClose(); if(printJob->thePrRecHdl != NULL) DisposeHandle ((Handle) printJob->thePrRecHdl); printJob->thePrRecHdl = NULL; DisposePtr((char*)printJob); *token = nil; return 0; } OSStatus DoPrintLoop(PrintingLogicPtr printJob) { OSStatus status = noErr; GrafPtr currPort; // Save the current QD grafport. GetPort(&currPort); // Get the current graphics context, in this case a Quickdraw grafPort, // for drawing the page. status = printJob->thePrPort == NULL ? -3 : noErr; if (status == noErr) { // Set the printing port before drawing the page. SetPort((GrafPtr) printJob->thePrPort); // Draw the page. status = DrawPage(printJob); // Restore the QD grafport. SetPort(currPort); } return status; } // DoPrintLoop #endif int ioInitPrintJob() { SetUpPixmap(); return 1; } int ioShutdownPrintJob() { FreePixmap(); return 1; } static Boolean RunningOnCarbonX(void) { UInt32 response; return (Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x01000); } int ioPagePostscript(PrintingLogicPtr printJob,char *postscript,int postscriptLength) { printJob->postscript = postscript; printJob->postscriptLength = postscriptLength; printJob->formBitMap = NULL; return ioPrint(printJob); } int ioPageForm(PrintingLogicPtr printJob, char *aBitMap,int h,int w,int d,float sh,float sw,int oh, int ow) { printJob->formBitMap = aBitMap; printJob->width = w; printJob->height = h; printJob->depth = d; printJob->scaleH = sh; printJob->scaleW = sw; printJob->offsetHeight = oh; printJob->offsetWidth = ow; printJob->postscriptLength = 0; return ioPrint(printJob); } /*------------------------------------------------------------------------------ Function: DrawPage Parameters: Description: Draws the contents of a single page. If allowPostscript is true, DrawPage adds PostScript code into the spool file. See the Printing chapter in Inside Macintosh, Imaging with QuickDraw, for details about PostScript PicComments. ------------------------------------------------------------------------------*/ OSStatus DrawPage(PrintingLogicPtr printJob) { OSStatus status = noErr; CGrafPtr printerPort; Rect dstRect = { 0, 0, 0, 0 }; Rect srcRect = { 0, 0, 0, 0 }; if (printJob->formBitMap != nil) { dstRect.top = printJob->offsetHeight; dstRect.left = printJob->offsetWidth; dstRect.right = printJob->width*printJob->scaleW + printJob->offsetWidth; dstRect.bottom = printJob->height*printJob->scaleH + printJob->offsetHeight; srcRect.right = printJob->width; srcRect.bottom = printJob->height; HLock((Handle)stPixMap); (*stPixMap)->baseAddr = (void *) printJob->formBitMap; (*stPixMap)->rowBytes = (((((printJob->width * printJob->depth) + 31) / 32) * 4) & 0x1FFF) | 0x8000; (*stPixMap)->bounds = srcRect; (*stPixMap)->pixelSize = printJob->depth; if (printJob->depth<=8) { (*stPixMap)->cmpSize = printJob->depth; (*stPixMap)->cmpCount = 1; } else if (printJob->depth==16) { (*stPixMap)->cmpSize = 5; (*stPixMap)->cmpCount = 3; } else if (printJob->depth==32) { (*stPixMap)->cmpSize = 8; (*stPixMap)->cmpCount = 3; } GetPort((GrafPtr *) &printerPort); if (RunningOnCarbonX()) { CopyBits((BitMap *) *stPixMap, GetPortBitMapForCopyBits(printerPort), &srcRect, &dstRect, srcCopy, NULL); } else { GWorldPtr aGWorld; PixMapHandle thePix; NewGWorld(&aGWorld, printJob->depth, &srcRect, stColorTable, NULL, keepLocal+useTempMem); thePix = GetGWorldPixMap (aGWorld); LockPixels(thePix); CopyBits((BitMap *) *stPixMap, (BitMap *) *thePix, &srcRect, &srcRect, srcCopy, NULL); CopyBits((BitMap *) *thePix, GetPortBitMapForCopyBits(printerPort), &srcRect, &dstRect, srcCopy, NULL); UnlockPixels(thePix); DisposeGWorld(aGWorld); } HUnlock((Handle)stPixMap); } #if TARGET_API_MAC_CARBON // Conditionally insert PostScript into the spool file. if (printJob->allowPostscript && printJob->postscriptLength > 0) { status = PMSessionPostScriptBegin(printJob->printSession); if (status == noErr) { status = PMSessionPostScriptData(printJob->printSession, (char *)printJob->postscript,printJob->postscriptLength); status = PMSessionPostScriptEnd(printJob->printSession); } } #else return PrError(); #endif return status; } // DrawPage static void SetUpPixmap(void) { int i, r, g, b; stColorTable = (CTabHandle) NewHandle(sizeof(ColorTable) + (256 * sizeof(ColorSpec))); (*stColorTable)->ctSeed = GetCTSeed(); (*stColorTable)->ctFlags = 0; (*stColorTable)->ctSize = 255; /* 1-bit colors (monochrome) */ SetColorEntry(0, 65535, 65535, 65535); /* white or transparent */ SetColorEntry(1, 0, 0, 0); /* black */ /* additional colors for 2-bit color */ SetColorEntry(2, 65535, 65535, 65535); /* opaque white */ SetColorEntry(3, 32768, 32768, 32768); /* 1/2 gray */ /* additional colors for 4-bit color */ SetColorEntry( 4, 65535, 0, 0); /* red */ SetColorEntry( 5, 0, 65535, 0); /* green */ SetColorEntry( 6, 0, 0, 65535); /* blue */ SetColorEntry( 7, 0, 65535, 65535); /* cyan */ SetColorEntry( 8, 65535, 65535, 0); /* yellow */ SetColorEntry( 9, 65535, 0, 65535); /* magenta */ SetColorEntry(10, 8192, 8192, 8192); /* 1/8 gray */ SetColorEntry(11, 16384, 16384, 16384); /* 2/8 gray */ SetColorEntry(12, 24576, 24576, 24576); /* 3/8 gray */ SetColorEntry(13, 40959, 40959, 40959); /* 5/8 gray */ SetColorEntry(14, 49151, 49151, 49151); /* 6/8 gray */ SetColorEntry(15, 57343, 57343, 57343); /* 7/8 gray */ /* additional colors for 8-bit color */ /* 24 more shades of gray (does not repeat 1/8th increments) */ SetColorEntry(16, 2048, 2048, 2048); /* 1/32 gray */ SetColorEntry(17, 4096, 4096, 4096); /* 2/32 gray */ SetColorEntry(18, 6144, 6144, 6144); /* 3/32 gray */ SetColorEntry(19, 10240, 10240, 10240); /* 5/32 gray */ SetColorEntry(20, 12288, 12288, 12288); /* 6/32 gray */ SetColorEntry(21, 14336, 14336, 14336); /* 7/32 gray */ SetColorEntry(22, 18432, 18432, 18432); /* 9/32 gray */ SetColorEntry(23, 20480, 20480, 20480); /* 10/32 gray */ SetColorEntry(24, 22528, 22528, 22528); /* 11/32 gray */ SetColorEntry(25, 26624, 26624, 26624); /* 13/32 gray */ SetColorEntry(26, 28672, 28672, 28672); /* 14/32 gray */ SetColorEntry(27, 30720, 30720, 30720); /* 15/32 gray */ SetColorEntry(28, 34815, 34815, 34815); /* 17/32 gray */ SetColorEntry(29, 36863, 36863, 36863); /* 18/32 gray */ SetColorEntry(30, 38911, 38911, 38911); /* 19/32 gray */ SetColorEntry(31, 43007, 43007, 43007); /* 21/32 gray */ SetColorEntry(32, 45055, 45055, 45055); /* 22/32 gray */ SetColorEntry(33, 47103, 47103, 47103); /* 23/32 gray */ SetColorEntry(34, 51199, 51199, 51199); /* 25/32 gray */ SetColorEntry(35, 53247, 53247, 53247); /* 26/32 gray */ SetColorEntry(36, 55295, 55295, 55295); /* 27/32 gray */ SetColorEntry(37, 59391, 59391, 59391); /* 29/32 gray */ SetColorEntry(38, 61439, 61439, 61439); /* 30/32 gray */ SetColorEntry(39, 63487, 63487, 63487); /* 31/32 gray */ /* The remainder of color table defines a color cube with six steps for each primary color. Note that the corners of this cube repeat previous colors, but simplifies the mapping between RGB colors and color map indices. This color cube spans indices 40 through 255. */ for (r = 0; r < 6; r++) { for (g = 0; g < 6; g++) { for (b = 0; b < 6; b++) { i = 40 + ((36 * r) + (6 * b) + g); SetColorEntry(i, (r * 65535) / 5, (g * 65535) / 5, (b * 65535) / 5); } } } stPixMap = NewPixMap(); (*stPixMap)->pixelType = 0; /* chunky */ (*stPixMap)->cmpCount = 1; (*stPixMap)->pmTable = stColorTable; } static void SetColorEntry(int index, int red, int green, int blue) { (*stColorTable)->ctTable[index].value = index; (*stColorTable)->ctTable[index].rgb.red = red; (*stColorTable)->ctTable[index].rgb.green = green; (*stColorTable)->ctTable[index].rgb.blue = blue; } static void FreePixmap(void) { if (stPixMap != nil) { DisposePixMap(stPixMap); stPixMap = nil; } if (stColorTable != nil) { //JMM disposepixmap does this DisposeHandle((void *) stColorTable); stColorTable = nil; } } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/PrintJobPlugin/sqMacPrinting.h ================================================ /**************************************************************************** * PROJECT: Mac printing * FILE: sqMacPrinting.h * CONTENT: * * AUTHOR: John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacPrinting.h 210 2002-02-20 21:02:40Z johnmci $ * * NOTES: * *****************************************************************************/ #if defined(__MWERKS__) #include #else #if TARGET_API_MAC_CARBON #include #else #endif #endif typedef struct { UInt32 numberOfPages; UInt32 currentPage; UInt32 firstPage; UInt32 lastPage; Boolean allowPostscript; void *formBitMap; long width; long height; long depth; float scaleW; float scaleH; long offsetWidth; long offsetHeight; void *postscript; UInt32 postscriptLength; #if TARGET_API_MAC_CARBON Handle flatFormatHandle; PMPrintSession printSession; PMPageFormat pageFormat; PMPrintSettings printSettings; #else THPrint thePrRecHdl; TPPrPort thePrPort; #endif } PrintingLogic, *PrintingLogicPtr; int ioPrintSetup(PrintingLogicPtr *printJob); int ioPrintPreProcessing(PrintingLogicPtr printJob,int numberOfPages); int ioPrint(PrintingLogicPtr printJob); int ioPrintPostProcessing(PrintingLogicPtr printJob); int ioPrintCleanup(PrintingLogicPtr *printJob); int ioInitPrintJob(void); int ioShutdownPrintJob(void); int ioPagePreProcessing(PrintingLogicPtr printJob); int ioPagePostProcessing(PrintingLogicPtr printJob); int ioPagePostscript(PrintingLogicPtr printJob,char *postscript,int postscriptLength); int ioPageForm(PrintingLogicPtr printJob, char *aBitMap,int h,int w,int d,float sh,float sw,int oh,int ow); int ioPrintGetFirstPageNumber(PrintingLogicPtr printJob); int ioPrintGetLastPageNumber(PrintingLogicPtr printJob); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable QuicktimePlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.QuicktimePlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.1b1 CFBundleSignature FAST CFBundleVersion 1.0.1b1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/JMMMacQuicktimePlugin.3.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 16 March 2006 at 11:58:44 am'! Smalltalk renameClassNamed: #MacQuicktimePlugin as: #QuicktimePlugin! SmartSyntaxInterpreterPlugin subclass: #QuicktimePlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 1/17/2006 15:53'! initialiseModule self export: true. ^self sqQuicktimeInitialize ! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 1/17/2006 15:53'! moduleUnloaded: aModuleName "The module with the given name was just unloaded. Make sure we have no dangling references." self export: true. self var: #aModuleName type: 'char *'. (aModuleName strcmp: 'QuicktimePlugin') = 0 ifTrue: [self sqQuicktimeShutdown]! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 1/17/2006 23:05'! primitiveClearFrameCompletedSemaphore: data self primitive: 'primitiveClearFrameCompletedSemaphore' parameters: #(SmallInteger). self stQuicktimeClearSemaphore: data. ^nil! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 1/17/2006 23:05'! primitiveDestroyHandle: data self primitive: 'primitiveDestroyHandle' parameters: #(SmallInteger). self stQuicktimeDestroy: data. ^nil! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 3/16/2006 09:32'! primitiveDestroySurface: data self primitive: 'primitiveDestroySurface' parameters: #(SmallInteger). self stQuicktimeDestroySurface: data. ^nil! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 1/17/2006 23:06'! primitiveSetFrameCompletedSemaphore: semaIndex for: data self primitive: 'primitiveSetFrameCompletedSemaphore' parameters:#(SmallInteger SmallInteger). self stQuicktimeSetSemaphore: semaIndex for: data. ^nil! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 3/16/2006 11:30'! primitiveSetGWorldPtrOntoExistingSurface: surfaceID gWorld: bitMapPtr width: width height: height rowBytes: rowBytes depth: depth movie: moviePtr | buffer movie | self primitive: 'primitiveSetGWorldPtrOntoExistingSurface' parameters:#(SmallInteger Oop SmallInteger SmallInteger SmallInteger SmallInteger Oop). buffer := self cCoerce: (interpreterProxy positive32BitValueOf: bitMapPtr) to: 'char *'. movie := self cCoerce: (interpreterProxy positive32BitValueOf: moviePtr) to: 'long'. self stQuicktimeSetToExistingSurface: surfaceID gworld: buffer width: width height: height rowBytes: rowBytes depth: depth movie: movie. ! ! !QuicktimePlugin methodsFor: 'system primitives' stamp: 'JMM 3/16/2006 11:30'! primitiveSetGWorldPtrOntoSurface: bitMapPtr width: width height: height rowBytes: rowBytes depth: depth movie: moviePtr | buffer movie results | self primitive: 'primitiveSetGWorldPtrOntoSurface' parameters:#(Oop SmallInteger SmallInteger SmallInteger SmallInteger Oop). buffer := self cCoerce: (interpreterProxy positive32BitValueOf: bitMapPtr) to: 'char *'. movie := self cCoerce: (interpreterProxy positive32BitValueOf: moviePtr) to: 'long'. results := self stQuicktimeSetSurface: buffer width: width height: height rowBytes: rowBytes depth: depth movie: movie. ^results asOop: SmallInteger ! ! !QuicktimePlugin class methodsFor: 'translation' stamp: 'JMM 1/17/2006 20:24'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !QuicktimePlugin class methodsFor: 'translation' stamp: 'JMM 1/17/2006 20:24'! requiresCrossPlatformFiles "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !QuicktimePlugin class reorganize! ('translation' hasHeaderFile requiresCrossPlatformFiles) ! QuicktimePlugin removeSelector: #primitiveClearFrameCompletedSemaphore! QuicktimePlugin removeSelector: #primitiveDestoryHandle:! QuicktimePlugin removeSelector: #primitiveSetFrameCompletedSemaphore:! QuicktimePlugin removeSelector: #primitiveSetGWorldPtrOntoSurface:width:height:! QuicktimePlugin removeSelector: #primitiveSetGWorldPtrOntoSurface:width:height:rowBytes:! QuicktimePlugin removeSelector: #primitiveSetGWorldPtrOntoSurface:width:height:rowBytes:depth:! !QuicktimePlugin reorganize! ('system primitives' initialiseModule moduleUnloaded: primitiveClearFrameCompletedSemaphore: primitiveDestroyHandle: primitiveDestroySurface: primitiveSetFrameCompletedSemaphore:for: primitiveSetGWorldPtrOntoExistingSurface:gWorld:width:height:rowBytes:depth:movie: primitiveSetGWorldPtrOntoSurface:width:height:rowBytes:depth:movie:) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/PkgInfo ================================================ BNDLFAST ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/SqueakQuicktime.xcodeproj/johnmci.mode1 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID 94AF35A4084782DD00FA5ACB XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 OpenEditors Content PBXProjectModuleGUID 94ECA626097E2D7F00C2C7BA PBXProjectModuleLabel Movies.h PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 94ECA627097E2D7F00C2C7BA PBXProjectModuleLabel Movies.h _historyCapacity 0 bookmark 9491968C09804F6D000FC37A history 94ECA675097EC7CE00C2C7BA SplitCount 1 StatusBarVisibility Geometry Frame {{0, 20}, {1364, 623}} PBXModuleWindowStatusBarHidden2 RubberWindowFrame 15 209 1364 664 0 0 1440 878 PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout BecomeActive ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 339 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 66DF6BFE01D7DCEA00A80119 66B8BC570381F53800A8011A 66DF6BFF01D7DCEA00A80119 66DF6C3901D7DCEA00A80119 944D6212085F458100600D6E 944D6213085F458100600D6E 66DF6C4501D7DEEE00A80119 943173AF085CD38900DDDC64 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 1CC0EA4004350EF90044410B PBXSmartGroupTreeModuleOutlineStateSelectionKey 3 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {339, 671}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {356, 689}} GroupTreeTableConfiguration MainColumn 339 RubberWindowFrame 338 54 1011 730 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 356pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel QuicktimePlugin.h PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel QuicktimePlugin.h history 944D6240085F473000600D6E 94ECA500097E16B400C2C7BA 94ECA55F097E1D2B00C2C7BA prevStack 949CD5C5085CC32700EB8605 94ECA4AA097E137A00C2C7BA 94ECA566097E1D2B00C2C7BA SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {650, 626}} RubberWindowFrame 338 54 1011 730 0 0 1440 878 Module PBXNavigatorGroup Proportion 626pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 631}, {650, 58}} RubberWindowFrame 338 54 1011 730 0 0 1440 878 Module XCDetailModule Proportion 58pt Proportion 650pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 9491968A09804F6D000FC37A 1CE0B1FE06471DED0097A5F4 9491968B09804F6D000FC37A 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 159403871.59758699 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList 9491969409804F6D000FC37A 94ECA626097E2D7F00C2C7BA 1CD10A99069EF8BA00B06720 /Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/QuicktimePlugin/SqueakQuicktime.xcodeproj WindowString 338 54 1011 730 0 0 1440 878 WindowTools FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel sqMacQuicktimeInteface.c StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {879, 326}} RubberWindowFrame 91 68 879 795 0 0 1440 878 Module PBXNavigatorGroup Proportion 326pt BecomeActive ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1012 GeometryConfiguration Frame {{0, 331}, {879, 423}} RubberWindowFrame 91 68 879 795 0 0 1440 878 Module PBXBuildResultsModule Proportion 423pt Proportion 754pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 94E4F4CD08D0A1CA00B9E724 94ECA4AC097E137A00C2C7BA 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 91 68 879 795 0 0 1440 878 WindowToolGUID 94E4F4CD08D0A1CA00B9E724 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {296, 309}} {{0, 309}, {296, 395}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {296, 704}} {{296, 0}, {846, 704}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {1142, 704}} RubberWindowFrame 196 68 1142 745 0 0 1440 878 Module PBXDebugSessionModule Proportion 704pt Proportion 704pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 9491968E09804F6D000FC37A 1C162984064C10D400B95A72 9491968F09804F6D000FC37A 9491969009804F6D000FC37A 9491969109804F6D000FC37A 9491969209804F6D000FC37A 9491969309804F6D000FC37A 9491969409804F6D000FC37A ToolbarConfiguration xcode.toolbar.config.debug WindowString 196 68 1142 745 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel QuicktimePlugin.h StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {791, 416}} RubberWindowFrame 51 90 791 674 0 0 1440 878 Module PBXNavigatorGroup Proportion 791pt Proportion 416pt ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 421}, {791, 212}} RubberWindowFrame 51 90 791 674 0 0 1440 878 Module PBXProjectFindModule Proportion 212pt Proportion 633pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE 94ECA513097E178F00C2C7BA 94ECA514097E178F00C2C7BA 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 51 90 791 674 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {686, 500}} RubberWindowFrame 635 113 686 541 0 0 1440 878 Module PBXDebugCLIModule Proportion 500pt Proportion 500pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 94ABA92F0858D3A300079BE1 94ECA4B1097E13C500C2C7BA 1C78EAAC065D492600B07095 WindowString 635 113 686 541 0 0 1440 878 WindowToolGUID 94ABA92F0858D3A300079BE1 WindowToolIsVisible Identifier windowTool.run Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {493, 167}} {{0, 176}, {493, 267}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {405, 443}} {{414, 0}, {514, 443}} GeometryConfiguration Frame {{0, 0}, {460, 159}} RubberWindowFrame 316 696 459 200 0 0 1280 1002 Module PBXRunSessionModule Proportion 159pt Proportion 159pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible 1 TableOfContents 1C0AD2B3069F1EA900FABCE6 1C0AD2B4069F1EA900FABCE6 1CD0528B0623707200166675 1C0AD2B5069F1EA900FABCE6 ToolbarConfiguration xcode.toolbar.config.run WindowString 316 696 459 200 0 0 1280 1002 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible 0 Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints IsVertical Layout Dock BecomeActive ContentConfiguration PBXBottomSmartGroupGIDs 1C77FABC04509CD000000102 PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided no PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 168 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 1C77FABC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {168, 350}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch GeometryConfiguration Frame {{0, 0}, {185, 368}} GroupTreeTableConfiguration MainColumn 168 RubberWindowFrame 315 424 744 409 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 185pt ContentConfiguration PBXProjectModuleGUID 1CA1AED706398EBD00589147 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{190, 0}, {554, 368}} RubberWindowFrame 315 424 744 409 0 0 1440 878 Module XCDetailModule Proportion 554pt Proportion 368pt MajorVersion 2 MinorVersion 0 Name Breakpoints ServiceClasses PBXSmartGroupTreeModule XCDetailModule StatusbarIsVisible TableOfContents 1CDDB66807F98D9800BB5817 1CDDB66907F98D9800BB5817 1CE0B1FE06471DED0097A5F4 1CA1AED706398EBD00589147 ToolbarConfiguration xcode.toolbar.config.breakpoints WindowString 315 424 744 409 0 0 1440 878 WindowToolGUID 1CDDB66807F98D9800BB5817 WindowToolIsVisible Identifier windowTool.debugAnimator Layout Dock Module PBXNavigatorGroup Proportion 100% Proportion 100% Name Debug Visualizer ServiceClasses PBXNavigatorGroup StatusbarIsVisible ToolbarConfiguration xcode.toolbar.config.debugAnimator WindowString 100 100 700 500 0 0 1280 1002 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.classBrowser IsVertical Layout Dock BecomeActive ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {378, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 332}} MembersFrame {{0, 101}, {378, 231}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 101 PBXMemberBookColumnIdentifier 22 RubberWindowFrame 312 384 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible TableOfContents 1C0AD2AF069F1E9B00FABCE6 949CD652085CD34000EB8605 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 312 384 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/SqueakQuicktime.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1064, 2114}}"; sepNavSelRange = "{1454, 21}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; }; }; 66B8BC5C0381F66500A8011A /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 6117}}"; sepNavSelRange = "{16850, 24}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {866, 3010}}"; sepNavSelRange = "{518, 32}"; sepNavVisRect = "{{0, 73}, {711, 429}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */ = { uiCtxt = { sepNavWindowFrame = "{{15, 153}, {1364, 720}}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Development; activeBuildStyle = 66DF6C4301D7DCEA00A80119 /* Development */; activeExecutable = 94ABA91E0858D35E00079BE1 /* Squeak */; activeTarget = 94AF34E00846F91100FA5ACB /* QuicktimePlugin */; addToTargets = ( 94AF34E00846F91100FA5ACB /* QuicktimePlugin */, ); breakpoints = ( ); codeSenseManager = 9444E60E06E7B8740063F6CC /* Code sense */; executables = ( 94ABA91E0858D35E00079BE1 /* Squeak */, ); expressions = ( buffer, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 200, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 299, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 411, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 425.2085, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 63, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 159403871; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 159403871; }; perUserProjectItems = { 944D6240085F473000600D6E /* PBXTextBookmark */ = 944D6240085F473000600D6E /* PBXTextBookmark */; 9491968C09804F6D000FC37A /* PBXTextBookmark */ = 9491968C09804F6D000FC37A /* PBXTextBookmark */; 949CD5C5085CC32700EB8605 /* PBXTextBookmark */ = 949CD5C5085CC32700EB8605 /* PBXTextBookmark */; 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */ = 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */; 94ECA500097E16B400C2C7BA /* PBXTextBookmark */ = 94ECA500097E16B400C2C7BA /* PBXTextBookmark */; 94ECA55F097E1D2B00C2C7BA /* PBXTextBookmark */ = 94ECA55F097E1D2B00C2C7BA /* PBXTextBookmark */; 94ECA566097E1D2B00C2C7BA /* PBXTextBookmark */ = 94ECA566097E1D2B00C2C7BA /* PBXTextBookmark */; 94ECA675097EC7CE00C2C7BA /* PBXTextBookmark */ = 94ECA675097EC7CE00C2C7BA /* PBXTextBookmark */; }; sourceControlManager = 9444E60D06E7B8740063F6CC /* Source Control */; userBuildSettings = { }; }; 9444E60D06E7B8740063F6CC /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 944D6214085F458100600D6E /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {659, 617}}"; sepNavSelRange = "{177, 0}"; sepNavVisRect = "{{0, 0}, {659, 617}}"; sepNavWindowFrame = "{{176, 7}, {962, 719}}"; }; }; 944D6240085F473000600D6E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949CD57E085CBE5900EB8605 /* InfoPlist.strings */; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 9491968C09804F6D000FC37A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9491968D09804F6D000FC37A /* Movies.h */; name = "typedef CALLBACK_API( OSErr , MovieDrawingCompleteProcPtr )(Movie theMovie, long refCon);"; rLen = 90; rLoc = 60035; rType = 0; vrLen = 2155; vrLoc = 61915; }; 9491968D09804F6D000FC37A /* Movies.h */ = { isa = PBXFileReference; name = Movies.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/QuickTime.framework/Versions/A/Headers/Movies.h; sourceTree = ""; }; 949CD57E085CBE5900EB8605 /* InfoPlist.strings */ = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakSerialPortExtendedUnixPlugin/resources/English.lproj/InfoPlist.strings; sourceTree = ""; }; 949CD5C5085CC32700EB8605 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949CD57E085CBE5900EB8605 /* InfoPlist.strings */; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 94ABA91E0858D35E00079BE1 /* Squeak */ = { isa = PBXExecutable; activeArgIndex = 2147483647; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; launchableReference = 94ECA424097E0C2D00C2C7BA /* Squeak.app */; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; sourceDirectories = ( ); }; 94AF34E00846F91100FA5ACB /* QuicktimePlugin */ = { activeExec = 0; }; 94AF34F10846F91100FA5ACB /* Info.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {686, 594}}"; sepNavSelRange = "{284, 6}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; 94AF35000846F98600FA5ACB /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2590}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; 94ECA1F5097DC2F800C2C7BA /* QuicktimePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 2982}}"; sepNavSelRange = "{3982, 74}"; sepNavVisRect = "{{0, 2142}, {838, 294}}"; sepNavWindowFrame = "{{61, 111}, {1364, 720}}"; }; }; 94ECA424097E0C2D00C2C7BA /* Squeak.app */ = { isa = PBXFileReference; explicitFileType = wrapper.application; name = Squeak.app; path = /Users/johnmci/Documents/Squeak3.8.0/build/Development/Squeak.app; sourceTree = ""; }; 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info.plist */; name = Quickt; rLen = 6; rLoc = 284; rType = 0; vrLen = 758; vrLoc = 0; }; 94ECA4E7097E15F800C2C7BA /* PkgInfo */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {609, 594}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; }; }; 94ECA500097E16B400C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info.plist */; name = Quickt; rLen = 6; rLoc = 284; rType = 0; vrLen = 758; vrLoc = 0; }; 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {812, 594}}"; sepNavSelRange = "{467, 26}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; sepNavWindowFrame = "{{38, 132}, {1364, 720}}"; }; }; 94ECA546097E1BF300C2C7BA /* sqMacQuicktimeInteface.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 2338}}"; sepNavSelRange = "{4126, 0}"; sepNavVisRect = "{{0, 1652}, {838, 294}}"; sepNavWindowFrame = "{{38, 132}, {1364, 720}}"; }; }; 94ECA547097E1BF300C2C7BA /* sqMacQuicktimeInteface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {698, 594}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; }; }; 94ECA55F097E1D2B00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = SQUEAK_BUILTIN_PLUGIN; rLen = 21; rLoc = 1454; rType = 0; vrLen = 1759; vrLoc = 0; }; 94ECA566097E1D2B00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = SQUEAK_BUILTIN_PLUGIN; rLen = 21; rLoc = 1454; rType = 0; vrLen = 1759; vrLoc = 0; }; 94ECA629097E2D7F00C2C7BA /* Movies.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Movies.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/QuickTime.framework/Versions/A/Headers/Movies.h; sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1568, 251258}}"; sepNavSelRange = "{60035, 90}"; sepNavVisRect = "{{0, 19390}, {1325, 591}}"; sepNavWindowFrame = "{{15, 153}, {1364, 720}}"; }; }; 94ECA675097EC7CE00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ECA629097E2D7F00C2C7BA /* Movies.h */; name = "typedef CALLBACK_API( OSErr , MovieDrawingCompleteProcPtr )(Movie theMovie, long refCon);"; rLen = 90; rLoc = 60035; rType = 0; vrLen = 2155; vrLoc = 61915; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/SqueakQuicktime.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 42; objects = { /* Begin PBXBuildFile section */ 944D6215085F458100600D6E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 944D6213085F458100600D6E /* InfoPlist.strings */; }; 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; }; 94AF34E20846F91100FA5ACB /* sqConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC580381F61C00A8011A /* sqConfig.h */; }; 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; }; 94AF34E40846F91100FA5ACB /* sq.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5C0381F66500A8011A /* sq.h */; }; 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; }; 94AF34E80846F91100FA5ACB /* SqueakPlugin.icns in Resources */ = {isa = PBXBuildFile; fileRef = 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */; }; 94AF34EF0846F91100FA5ACB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66DF6C8201D7DF7E00A80119 /* Carbon.framework */; }; 94AF35010846F98600FA5ACB /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF35000846F98600FA5ACB /* config.h */; }; 94AF35050846F9AB00FA5ACB /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF35040846F9AB00FA5ACB /* interp.h */; }; 94ECA1F6097DC2F800C2C7BA /* QuicktimePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94ECA1F5097DC2F800C2C7BA /* QuicktimePlugin.c */; }; 94ECA269097DCD5100C2C7BA /* SurfacePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ECA268097DCD5100C2C7BA /* SurfacePlugin.h */; }; 94ECA38F097DF8A400C2C7BA /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94ECA38E097DF8A400C2C7BA /* QuickTime.framework */; }; 94ECA52D097E197400C2C7BA /* QuicktimePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */; }; 94ECA548097E1BF300C2C7BA /* sqMacQuicktimeInteface.c in Sources */ = {isa = PBXBuildFile; fileRef = 94ECA546097E1BF300C2C7BA /* sqMacQuicktimeInteface.c */; }; 94ECA549097E1BF300C2C7BA /* sqMacQuicktimeInteface.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ECA547097E1BF300C2C7BA /* sqMacQuicktimeInteface.h */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 94AF34F70846F94F00FA5ACB /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; outputFiles = ( ); }; /* End PBXBuildRule section */ /* Begin PBXBuildStyle section */ 66DF6C4301D7DCEA00A80119 /* Development */ = { isa = PBXBuildStyle; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = NO; }; name = Development; }; 66DF6C4401D7DCEA00A80119 /* Deployment */ = { isa = PBXBuildStyle; buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; OPTIMIZATION_CFLAGS = "-O3 -mcpu=750 -funroll-loops "; OTHER_CFLAGS = ( "-DTARGET_OS_MAC", "-DNOPTHREADS", ); ZERO_LINK = NO; }; name = Deployment; }; /* End PBXBuildStyle section */ /* Begin PBXFileReference section */ 66B8BC580381F61C00A8011A /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = "Mac OS/vm/sqConfig.h"; sourceTree = ""; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqPlatformSpecific.h"; sourceTree = ""; }; 66B8BC5C0381F66500A8011A /* sq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sq.h; path = Cross/vm/sq.h; sourceTree = ""; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/Cross/vm/sqVirtualMachine.h; sourceTree = ""; }; 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakPlugin.icns; path = ../SqueakPlugin.icns; sourceTree = ""; }; 66DF6C8201D7DF7E00A80119 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; 943173AF085CD38900DDDC64 /* QuicktimePlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuicktimePlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 944D6214085F458100600D6E /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = InfoPlist.strings; sourceTree = ""; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = Cross/vm/sqMemoryAccess.h; sourceTree = ""; }; 94AF34F10846F91100FA5ACB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; sourceTree = ""; }; 94AF35000846F98600FA5ACB /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = "Mac OS/vm/config.h"; sourceTree = ""; }; 94AF35040846F9AB00FA5ACB /* interp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../Squeak3.8.0/src/vm/interp.h; sourceTree = SOURCE_ROOT; }; 94ECA1F5097DC2F800C2C7BA /* QuicktimePlugin.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = QuicktimePlugin.c; sourceTree = ""; }; 94ECA268097DCD5100C2C7BA /* SurfacePlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SurfacePlugin.h; path = platforms/Cross/plugins/SurfacePlugin/SurfacePlugin.h; sourceTree = SOURCE_ROOT; }; 94ECA38E097DF8A400C2C7BA /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; 94ECA4E7097E15F800C2C7BA /* PkgInfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = PkgInfo; path = build/PkgInfo; sourceTree = ""; }; 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuicktimePlugin.h; path = platforms/Cross/plugins/QuicktimePlugin/QuicktimePlugin.h; sourceTree = ""; }; 94ECA546097E1BF300C2C7BA /* sqMacQuicktimeInteface.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sqMacQuicktimeInteface.c; path = "platforms/Mac OS/plugins/QuicktimePlugin/sqMacQuicktimeInteface.c"; sourceTree = ""; }; 94ECA547097E1BF300C2C7BA /* sqMacQuicktimeInteface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqMacQuicktimeInteface.h; path = "platforms/Mac OS/plugins/QuicktimePlugin/sqMacQuicktimeInteface.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 94AF34EE0846F91100FA5ACB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 94AF34EF0846F91100FA5ACB /* Carbon.framework in Frameworks */, 94ECA38F097DF8A400C2C7BA /* QuickTime.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 66B8BC570381F53800A8011A /* platforms */ = { isa = PBXGroup; children = ( 94ECA268097DCD5100C2C7BA /* SurfacePlugin.h */, 94AF35040846F9AB00FA5ACB /* interp.h */, 94AF35000846F98600FA5ACB /* config.h */, 66B8BC580381F61C00A8011A /* sqConfig.h */, 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */, 66B8BC5C0381F66500A8011A /* sq.h */, 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */, 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */, ); name = platforms; path = ../Squeak3.8.0/platforms; sourceTree = SOURCE_ROOT; }; 66DF6BFE01D7DCEA00A80119 = { isa = PBXGroup; children = ( 94ECA4E7097E15F800C2C7BA /* PkgInfo */, 94AF34F10846F91100FA5ACB /* Info.plist */, 66B8BC570381F53800A8011A /* platforms */, 66DF6BFF01D7DCEA00A80119 /* Sources */, 66DF6C3901D7DCEA00A80119 /* resources */, 66DF6C8201D7DF7E00A80119 /* Carbon.framework */, 94ECA38E097DF8A400C2C7BA /* QuickTime.framework */, 66DF6C4501D7DEEE00A80119 /* Products */, ); sourceTree = ""; }; 66DF6BFF01D7DCEA00A80119 /* Sources */ = { isa = PBXGroup; children = ( 94ECA546097E1BF300C2C7BA /* sqMacQuicktimeInteface.c */, 94ECA547097E1BF300C2C7BA /* sqMacQuicktimeInteface.h */, 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */, 94ECA1F5097DC2F800C2C7BA /* QuicktimePlugin.c */, ); name = Sources; sourceTree = ""; }; 66DF6C3901D7DCEA00A80119 /* resources */ = { isa = PBXGroup; children = ( 944D6212085F458100600D6E /* English.lproj */, 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */, ); name = resources; path = "platforms/Mac OS/plugins/QuicktimePlugin/resources"; sourceTree = ""; }; 66DF6C4501D7DEEE00A80119 /* Products */ = { isa = PBXGroup; children = ( 943173AF085CD38900DDDC64 /* QuicktimePlugin.bundle */, ); name = Products; sourceTree = ""; }; 944D6212085F458100600D6E /* English.lproj */ = { isa = PBXGroup; children = ( 944D6213085F458100600D6E /* InfoPlist.strings */, ); path = English.lproj; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 94AF34E10846F91100FA5ACB /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 94AF34E20846F91100FA5ACB /* sqConfig.h in Headers */, 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */, 94AF34E40846F91100FA5ACB /* sq.h in Headers */, 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */, 94AF35010846F98600FA5ACB /* config.h in Headers */, 94AF35050846F9AB00FA5ACB /* interp.h in Headers */, 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */, 94ECA269097DCD5100C2C7BA /* SurfacePlugin.h in Headers */, 94ECA52D097E197400C2C7BA /* QuicktimePlugin.h in Headers */, 94ECA549097E1BF300C2C7BA /* sqMacQuicktimeInteface.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 94AF34E00846F91100FA5ACB /* QuicktimePlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 94ECA1E7097DC27D00C2C7BA /* Build configuration list for PBXNativeTarget "QuicktimePlugin" */; buildPhases = ( 94AF34E10846F91100FA5ACB /* Headers */, 94AF34E70846F91100FA5ACB /* Resources */, 94AF34EA0846F91100FA5ACB /* Sources */, 94AF34EE0846F91100FA5ACB /* Frameworks */, 94AF34F00846F91100FA5ACB /* Rez */, ); buildRules = ( 94AF34F70846F94F00FA5ACB /* PBXBuildRule */, ); buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = ServicesPlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; dependencies = ( ); name = QuicktimePlugin; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 943173AF085CD38900DDDC64 /* QuicktimePlugin.bundle */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 66DF6BFD01D7DCEA00A80119 /* Project object */ = { isa = PBXProject; buildConfigurationList = 94ECA1EB097DC27D00C2C7BA /* Build configuration list for PBXProject "SqueakQuicktime" */; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; }; buildStyles = ( 66DF6C4301D7DCEA00A80119 /* Development */, 66DF6C4401D7DCEA00A80119 /* Deployment */, ); hasScannedForEncodings = 1; mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119 /* Products */; projectDirPath = ""; targets = ( 94AF34E00846F91100FA5ACB /* QuicktimePlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 94AF34E70846F91100FA5ACB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 94AF34E80846F91100FA5ACB /* SqueakPlugin.icns in Resources */, 944D6215085F458100600D6E /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ 94AF34F00846F91100FA5ACB /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 94AF34EA0846F91100FA5ACB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 94ECA1F6097DC2F800C2C7BA /* QuicktimePlugin.c in Sources */, 94ECA548097E1BF300C2C7BA /* sqMacQuicktimeInteface.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 944D6213085F458100600D6E /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 944D6214085F458100600D6E /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 94ECA1E8097DC27D00C2C7BA /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OPTIMIZATION_CFLAGS = "-O0"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = QuicktimePlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; ZERO_LINK = NO; }; name = Development; }; 94ECA1E9097DC27D00C2C7BA /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OPTIMIZATION_CFLAGS = "-O3 -mcpu=750 -funroll-loops "; OTHER_CFLAGS = ( "-DTARGET_OS_MAC", "-DNOPTHREADS", ); OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = QuicktimePlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; ZERO_LINK = NO; }; name = Deployment; }; 94ECA1EA097DC27D00C2C7BA /* Default */ = { isa = XCBuildConfiguration; buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = QuicktimePlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Default; }; 94ECA1EC097DC27D00C2C7BA /* Development */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; }; name = Development; }; 94ECA1ED097DC27D00C2C7BA /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; }; name = Deployment; }; 94ECA1EE097DC27D00C2C7BA /* Default */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 94ECA1E7097DC27D00C2C7BA /* Build configuration list for PBXNativeTarget "QuicktimePlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 94ECA1E8097DC27D00C2C7BA /* Development */, 94ECA1E9097DC27D00C2C7BA /* Deployment */, 94ECA1EA097DC27D00C2C7BA /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; 94ECA1EB097DC27D00C2C7BA /* Build configuration list for PBXProject "SqueakQuicktime" */ = { isa = XCConfigurationList; buildConfigurations = ( 94ECA1EC097DC27D00C2C7BA /* Development */, 94ECA1ED097DC27D00C2C7BA /* Deployment */, 94ECA1EE097DC27D00C2C7BA /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 66DF6BFD01D7DCEA00A80119 /* Project object */; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/resources/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ CFBundleName = "QuicktimePlugin"; CFBundleShortVersionString = "QuicktimePlugin version 1.0.1B1"; CFBundleGetInfoString = "QuicktimePlugin version 1.0.1B1"; NSHumanReadableCopyright = "http://www.squeak.org"; ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/sqMacQuicktimeInteface.c ================================================ /* * sqMacQuicktimeInteface.c * SqueakQuicktime * * Created by John M McIntosh on 17/01/06. * Copyright 2006 Corporate Smalltalk Consulting ltd. All rights reserved, published under the Squeak-L licence * */ #include #include "sqMacQuicktimeInteface.h" #include "SurfacePlugin.h" #include "sqMemoryAccess.h" #include "sqVirtualMachine.h" typedef struct QuickTimeBitMapForSqueak { int width, height, depth; /* width, height, and depth */ int rowBytes; /* how many bytes per scan line? */ MovieDrawingCompleteUPP myDrawCompleteProc; Movie movie; int semaIndex; void *bits; /* where are those bits? */ } QuickTimeBitMapForSqueak; static fn_ioRegisterSurface registerSurface = 0; static fn_ioUnregisterSurface unregisterSurface = 0; static fn_ioFindSurface findSurface = 0; int QuicktimeGetSurfaceFormat(QuickTimeBitMapForSqueak *handle, int* width, int* height, int* depth, int* isMSB); int QuicktimeLockSurface(QuickTimeBitMapForSqueak *handle, int *pitch, int x, int y, int w, int h); int QuicktimeUnlockSurface(QuickTimeBitMapForSqueak *handle, int x, int y, int w, int h); int QuicktimeShowSurface(QuickTimeBitMapForSqueak *handle, int x, int y, int w, int h); struct VirtualMachine *interpreterProxy; static sqSurfaceDispatch QuicktimeTargetDispatch = { 1, 0, (fn_getSurfaceFormat) QuicktimeGetSurfaceFormat, (fn_lockSurface) QuicktimeLockSurface, (fn_unlockSurface) QuicktimeUnlockSurface, (fn_showSurface) QuicktimeShowSurface }; static OSErr DrawCompleteProc(Movie theMovie, long refCon) { interpreterProxy->signalSemaphoreWithIndex(refCon); return noErr; } void SetupSurface() { registerSurface = (fn_ioRegisterSurface) interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface","SurfacePlugin"); unregisterSurface = (fn_ioUnregisterSurface) interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface","SurfacePlugin"); findSurface = (fn_ioFindSurface) interpreterProxy->ioLoadFunctionFrom("ioFindSurface","SurfacePlugin"); } sqInt sqQuicktimeInitialize() { SetupSurface(); return true; } sqInt sqQuicktimeShutdown() { return true; } long stQuicktimeSetSurfacewidthheightrowBytesdepthmovie(char * buffer, int width, int height, int rowBytes, int depth, void *movie) { QuickTimeBitMapForSqueak *bitMap; int sqHandle; bitMap = calloc(1, sizeof(QuickTimeBitMapForSqueak)); bitMap->width = width; bitMap->height = height; bitMap->depth = depth; bitMap->rowBytes = rowBytes; bitMap->bits = buffer; bitMap->movie = movie; (*registerSurface)((long) bitMap, &QuicktimeTargetDispatch, &sqHandle); return sqHandle; } long stQuicktimeSetToExistingSurfacegworldwidthheightrowBytesdepthmovie (int sqHandle, char * buffer, int width, int height, int rowBytes, int depth, void *movie) { QuickTimeBitMapForSqueak *bitMap; /* see if the handle really describes a MyBitmap surface */ if( ! (*findSurface)(sqHandle, &QuicktimeTargetDispatch, (int*) (&bitMap)) ) { /* i don't know what it is but certainly not MyBitmap */ return interpreterProxy->primitiveFail(); } bitMap->width = width; bitMap->height = height; bitMap->depth = depth; bitMap->rowBytes = rowBytes; bitMap->bits = buffer; bitMap->movie = movie; (*registerSurface)((long) bitMap, &QuicktimeTargetDispatch, &sqHandle); return sqHandle; } int stQuicktimeDestroySurface(int sqHandle) { QuickTimeBitMapForSqueak *myBM; /* see if the handle really describes a MyBitmap surface */ if( ! (*findSurface)(sqHandle, &QuicktimeTargetDispatch, (int*) (&myBM)) ) { /* i don't know what it is but certainly not MyBitmap */ return interpreterProxy->primitiveFail(); } /* unregister and destroy */ (*unregisterSurface)(sqHandle); free(myBM); } int stQuicktimeDestroy(int sqHandle) { QuickTimeBitMapForSqueak *myBM; /* see if the handle really describes a MyBitmap surface */ if( ! (*findSurface)(sqHandle, &QuicktimeTargetDispatch, (int*) (&myBM)) ) { /* i don't know what it is but certainly not MyBitmap */ return interpreterProxy->primitiveFail(); } /* unregister and destroy */ (*unregisterSurface)(sqHandle); if (myBM->semaIndex && !((myBM->movie == nil) || (*myBM->movie == 0xFFFFFFFFU))) { DisposeMovieDrawingCompleteUPP(myBM->myDrawCompleteProc); SetMovieDrawingCompleteProc (myBM->movie,0,0,0); } myBM->semaIndex = 0; free(myBM); return 1; } int stQuicktimeSetSemaphorefor(int index, int sqHandle) { // interpreterProxy->signalSemaphoreWithIndex(state->semaIndex); QuickTimeBitMapForSqueak *myBM; if( ! (*findSurface)(sqHandle, &QuicktimeTargetDispatch, (int*) (&myBM)) ) { /* i don't know what it is but certainly not MyBitmap */ return interpreterProxy->primitiveFail(); } if ((myBM->movie == nil) || (*myBM->movie == 0xFFFFFFFFU)) return interpreterProxy->primitiveFail(); myBM->myDrawCompleteProc = NewMovieDrawingCompleteUPP(DrawCompleteProc); SetMovieDrawingCompleteProc (myBM->movie,movieDrawingCallWhenChanged,myBM->myDrawCompleteProc,(long) index); myBM->semaIndex = index; return 0; } int stQuicktimeClearSemaphore(int sqHandle) { QuickTimeBitMapForSqueak *myBM; if( ! (*findSurface)(sqHandle, &QuicktimeTargetDispatch, (int*) (&myBM)) ) { /* i don't know what it is but certainly not MyBitmap */ return interpreterProxy->primitiveFail(); } if ((myBM->movie == nil) || (*myBM->movie == 0xFFFFFFFFU)) return interpreterProxy->primitiveFail(); if (myBM->semaIndex) { SetMovieDrawingCompleteProc (myBM->movie,0,0,0); } myBM->semaIndex = 0; return 1; } int QuicktimeGetSurfaceFormat(QuickTimeBitMapForSqueak *myBM, int *width, int *height, int *depth, int *isMSB) { /* fill in status information */ *width = myBM->width; *height = myBM->height; *depth = myBM->depth; *isMSB = 1; /* or zero depending on platform or choice */ #warning Endeness return 1; /* success - otherwise return zero */ } int QuicktimeLockSurface(QuickTimeBitMapForSqueak *myBM, int *pitch, int x, int y, int w, int h) { /* lock the region x,y - (x+w),(y+h) the area actually used is provided so that expensive operations (like a round trip to the X-Server) can be avoided. See SurfacePlugin.h */ /* for our simple example, only fill in the pitch. No locking is required. */ *pitch = myBM->rowBytes; return (long) myBM->bits; /* success */ } int QuicktimeUnlockSurface(QuickTimeBitMapForSqueak *myBM, int x, int y, int w, int h) { /* Unlock a previously locked portion of myBM. The area describes the 'dirty region' which might need to be written back/flushed whatever. */ /* for the simple example do nothing */ return 1; } int QuicktimeShowSurface(QuickTimeBitMapForSqueak *myBM, int x, int y, int w, int h) { /* the surface represents Display - update the portion described in x,y,w,h */ /* for our simple example we just ignore this */ return 0; /* e.g., fail */ } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/QuicktimePlugin/sqMacQuicktimeInteface.h ================================================ /* * sqMacQuicktimeInteface.h * SqueakQuicktime * * Created by John M McIntosh on 17/01/06. johnmci@smalltalkconsulting.com * Copyright 2006 Corporate Smalltalk Consulting ltd. All rights reserved, published under the Squeak-L licence * */ #include #include "QuicktimePlugin.h" ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SecurityPlugin/sqMacSecurity.c ================================================ //JMM 2/13/01 create docs folder if non-existant //JMM 4/4/01 look for documents/My Squeak folder versus just documents as secure location //JMM 5/3/01 path was wrong for unsecure folder which uncovered a bug in lookupPath //JMM 8/15/01 only allow call to ioInitSecurity Once, also return proper return code //JMM 9/5/01 make it as a plugin // 3.7.0bx Nov 24th, 2003 JMM gCurrentVMEncoding #include "sq.h" #include "sqMacFileLogic.h" #include "SecurityPlugin.h" #include "sqMacUIConstants.h" #include "FilePlugin.h" #include #if !defined(PATH_MAX) # include #endif extern struct VirtualMachine * interpreterProxy; #define fromSqueak(string,length) string void fixPath(char *path); int dir_CreateSecurity(char *pathString, int pathStringLength); int _ioSetFileAccess(int enable); static char secureUserDirectory[PATH_MAX]; static char untrustedUserDirectory[PATH_MAX]; static Boolean gInitialized = false; /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* file security */ static int allowFileAccess = 1; /* full access to files */ static int isAccessiblePathName(char *pathName) { unsigned int i; /* Check if the path/file name is subdirectory of the image path */ for(i=0; i0;i--) if(path[i-1]==DELIMITERInt) { path[i-1]=0x00; return; } } int dir_CreateSecurity(char *pathString, int pathStringLength) { /* Create a new directory with the given path. By default, this directory is created in the current directory. Use a full path name such as "MyDisk:Working:New Folder" to create folders elsewhere. */ //JMM tests create file in Vm directory, other place, other volume return dir_Create(pathString, pathStringLength); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SerialExtendedPlugin/Info-SerialExtendedUnixPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable SerialExtendedUnixPlugin CFBundleGetInfoString SerialExtendedUnixPlugin V1.0.3 for Squeak, see http://www.squeak.org CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.SerialExtendedUnixPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName SerialExtendedUnixPlugin V1.0.3 for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.0.3 CFBundleSignature FAST CFBundleVersion 1.0.3 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SerialExtendedPlugin/serialExtendedUnixPlugin.h ================================================ #include #include #include #include #include #include #include int serialPortFindNamesPlusKeysstorage(int aUpperNumber, char *aByteArray); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SerialExtendedPlugin/sqMacSerialExtended.c ================================================ #include "sq.h" #include #include #include #include #define MAXPATHLEN 256 extern struct VirtualMachine *interpreterProxy; static kern_return_t FindModems(io_iterator_t *matchingServices); static void GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize, char *key, CFIndex maxKeySize); int serialPortFindNamesPlusKeysstorage(int numberOf,int storage); int serialPortFindNamesPlusKeysstorage(int numberOf,int storage) { char *where; int i; io_iterator_t serialPortIterator; kern_return_t kernResult; char bsdPath[MAXPATHLEN], key[MAXPATHLEN]; where = (char *) storage; kernResult = FindModems(&serialPortIterator); if (kernResult != 0) return kernResult; for(i=0;i extern struct VirtualMachine *interpreterProxy; /*** Constants ***/ #define INPUT_BUF_SIZE 1000 /*** Serial Ports ***/ #define MAX_PORTS 16 static short outRefNum[MAX_PORTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /*** Private Functions ***/ int setHandshakeOptions(int portNum, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); int serialPortSetControl(int portNum,int control, char *data); int serialPortIsOpen(int portNum); int serialPortNames(int portNum, char *portName, char *inName, char *outName); /* initialize/shutdown */ int serialPortInit() { return true; } int serialPortShutdown() { int i; for(i=0;i= MAX_PORTS)) return false; return outRefNum[portNum] != 0; } int serialPortSetControl(int portNum,int control, char *data) { #pragma unused(portNum,control,data) return -1; } int serialPortNames(int portNum, char *portName, char *inName, char *outName) { /* Fill in the user name and input and output port names for the given port number. Note that ports are numbered starting with zero. */ #pragma unused(portNum,portName,inName,outName) return false; } int setHandshakeOptions( int portNum, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar) { /* Set the given port's handshaking parameters. */ #pragma unused(portNum,inFlowCtrl,outFlowCtrl,xOnChar,xOffChar) return false; } /*** Serial Port Functions ***/ EXPORT (int) serialPortClose(int portNum) { #pragma unused(portNum) return false; } EXPORT (int) serialPortOpen( int portNum, int baudRate, int stopBitsType, int parityType, int dataBits, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar) { /* Open the given serial port using the given settings. The baud rate can be any number between about 224 and 57600; the driver will pick a clock divisor that will generate the closest available baud rate. */ #pragma unused(portNum,baudRate,stopBitsType,parityType,dataBits,inFlowCtrl,outFlowCtrl,xOnChar,xOffChar) return false; } EXPORT (int) serialPortReadInto(int portNum, int count, int bufferPtr) { /* Read up to count bytes from the given serial port into the given byte array. Read only up to the number of bytes in the port's input buffer; if fewer bytes than count have been received, do not wait for additional data to arrive. Return zero if no data is available. */ #pragma unused(portNum,count,bufferPtr) return false; } EXPORT (int) serialPortWriteFrom(int portNum, int count, int bufferPtr) { /* Write count bytes from the given byte array to the given serial port's output buffer. Return the number of bytes written. This implementation is synchronous: it doesn't return until the data has been sent. However, other implementations may return before transmission is complete. */ long int byteCount = count; int osErr; if (!serialPortIsOpen(portNum)) { return interpreterProxy->success(false); } osErr = FSWrite(outRefNum[portNum], &byteCount, (char *) bufferPtr); if (osErr != noErr) { return interpreterProxy->success(false); } return byteCount; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable ServicesPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.ServicesPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.2b2 CFBundleSignature FAST CFBundleVersion 1.0.2b2 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/JMMMacServices.5.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 15 February 2006 at 3:39:39 pm'! "Change Set: JMMMacServices Date: 13 June 2005 Author: johnmci@smalltalkconsulting.com Mac Services, used by the Services logic to allow squeak to service requests from other application. The intial release executes the supplied UTF-8 string, then returns the result to the calling application"! Object subclass: #MacServicesInterface instanceVariableNames: 'servicesSemaphore servicesSemaIndex' classVariableNames: 'Current MacServicesProcess' poolDictionaries: '' category: 'Network-RemoteDirectory'! !MacServicesInterface commentStamp: '' prior: 0! Mac Services interface. uses ServicesPlugin by John M McIntosh johnmci@smalltalkconsulting.com June 15th 2005 ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 10:14'! getBytes ^self primGetBytes! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 6/12/2005 13:43'! getTextString ^self primGetTextString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 6/12/2005 14:24'! setBasicType self setDataTypes: 'TEXT'! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 10:14'! setBytes: aByteString self primSetBytes: aByteString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 10:16'! setCopyOSType: aString self primSetCopyOSTypeString: aString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 13:03'! setDataTypes: aDataTypeArray "Needs a string of OSTypes, ie TEXTTIFF" "Types could be: kScrapFlavorTypePicture = 'PICT', /* contents of a PicHandle*/ kScrapFlavorTypeText = 'TEXT', /* stream of characters*/ kScrapFlavorTypeTextStyle = 'styl', /* see TEGetStyleScrapHandle*/ kScrapFlavorTypeMovie = 'moov', /* reference to a movie*/ kScrapFlavorTypeSound = 'snd ', /* see SndRecord and SndPlay*/ kScrapFlavorTypeUnicode = 'utxt', /* stream of UTF16 characters*/ kScrapFlavorTypeUnicodeStyle = 'ustl' /* ATSUI defines; Textension uses*/ also other types like TIFF " self primSetDataTypes: aDataTypeArray! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 10:16'! setPasteOSType: aString self primSetPasteOSTypeString: aString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 10:16'! setPerformOSType: aString self primSetPerformOSTypeString: aString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 9/8/2005 13:42'! setReturnBytes: aString osType: aType self primSetReturnBytes: aString osType: aType! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 6/12/2005 15:14'! setReturnTextString: aString self primSetReturnTextString: aString! ! !MacServicesInterface methodsFor: 'accessing' stamp: 'JMM 6/12/2005 13:40'! setTextString: aString self primSetTextString: aString! ! !MacServicesInterface methodsFor: 'initialize-release' stamp: 'JMM 6/13/2005 21:31'! initialize self installSemaphore. self setBasicType. self installServicesProcess! ! !MacServicesInterface methodsFor: 'initialize-release' stamp: 'JMM 6/13/2005 21:44'! installSemaphore servicesSemaphore := Semaphore new. servicesSemaIndex := Smalltalk registerExternalObject: servicesSemaphore. self primSetSemaphore: servicesSemaIndex. ! ! !MacServicesInterface methodsFor: 'initialize-release' stamp: 'JMM 6/13/2005 21:27'! installServicesProcess MacServicesProcess ifNotNil: [MacServicesProcess terminate]. MacServicesProcess := [self macServicesProcessLogic] forkAt: Processor userBackgroundPriority. ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 10:10'! primGetBytes ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 6/12/2005 13:42'! primGetTextString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 10:11'! primSetBytes: aString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 10:12'! primSetCopyOSTypeString: aString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 6/12/2005 13:38'! primSetDataTypes: typeString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 10:12'! primSetPasteOSTypeString: aString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 10:13'! primSetPerformOSTypeString: aString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 9/8/2005 13:39'! primSetReturnBytes: aString osType: aType ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 6/12/2005 15:14'! primSetReturnTextString: aString ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 6/13/2005 21:39'! primSetSemaphore: aSemaIndex ! ! !MacServicesInterface methodsFor: 'system primitives' stamp: 'JMM 6/12/2005 14:30'! primSetTextString: aString ! ! !MacServicesInterface methodsFor: 'process' stamp: 'JMM 9/8/2005 13:43'! getDataExecuteAndReturn | string results resultsString | string := self getBytes. results := Compiler evaluate: string asString. resultsString := results printString. self setReturnBytes: resultsString asByteArray osType: 'TEXT'. ! ! !MacServicesInterface methodsFor: 'process' stamp: 'JMM 9/8/2005 13:43'! macServicesProcessLogic [servicesSemaphore wait. [self getDataExecuteAndReturn] on: Error do: [:ex | self setReturnBytes: String new osType: 'TEXT']. true ] whileTrue.! ! !MacServicesInterface class methodsFor: 'accessing' stamp: 'JMM 6/13/2005 21:21'! current Current ifNil: [Current := self new]. ^Current! ! !MacServicesInterface class methodsFor: 'initialize-release' stamp: 'JMM 6/13/2005 21:21'! shutDown: quitting ! ! !MacServicesInterface class methodsFor: 'initialize-release' stamp: 'JMM 6/13/2005 21:34'! startUp: resuming "The image is either being newly started (resuming is true), or it's just been snapshotted" Current := nil. self current.! ! !MacServicesInterface class methodsFor: 'class initialization' stamp: 'JMM 6/13/2005 21:19'! initialize "MacServicesInterface initialize" Smalltalk addToStartUpList: self after: nil. Smalltalk addToShutDownList: self after: nil.! ! MacServicesInterface initialize! !MacServicesInterface class reorganize! ('accessing' current) ('initialize-release' shutDown: startUp:) ('class initialization' initialize) ! !MacServicesInterface reorganize! ('accessing' getBytes getTextString setBasicType setBytes: setCopyOSType: setDataTypes: setPasteOSType: setPerformOSType: setReturnBytes:osType: setReturnTextString: setTextString:) ('initialize-release' initialize installSemaphore installServicesProcess) ('system primitives' primGetBytes primGetTextString primSetBytes: primSetCopyOSTypeString: primSetDataTypes: primSetPasteOSTypeString: primSetPerformOSTypeString: primSetReturnBytes:osType: primSetReturnTextString: primSetSemaphore: primSetTextString:) ('process' getDataExecuteAndReturn macServicesProcessLogic) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/JMMServicesPlugin.2.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 8 September 2005 at 3:07:58 pm'! SmartSyntaxInterpreterPlugin subclass: #ServicesPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 11:17'! initialiseModule self export: true. ^self sqServicesInitialize ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 11:17'! moduleUnloaded: aModuleName "The module with the given name was just unloaded. Make sure we have no dangling references." self export: true. self var: #aModuleName type: 'char *'. (aModuleName strcmp: 'ServicesPlugin') = 0 ifTrue: [self sqServicesShutdown]! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:21'! primitiveGetBytes "Setup bytes, could be text, could be TIFF" | length oop | self primitive: 'primitiveGetBytes'. length := self sqServicesGetTextStringLength. oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: length. self sqServicesGetTextStringInto: (interpreterProxy firstIndexableField: oop). ^oop ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 13:11'! primitiveGetTextString "Setup text string" | length oop | self primitive: 'primitiveGetTextString'. length := self sqServicesGetTextStringLength. oop := interpreterProxy instantiateClass: interpreterProxy classString indexableSize: length. self sqServicesGetTextStringInto: (interpreterProxy firstIndexableField: oop). ^oop ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:23'! primitiveSetBytes: aTextString "Setup text string" | dataTypesLength | self primitive: 'primitiveSetBytes' parameters: #(ByteArray). dataTypesLength := interpreterProxy slotSizeOf: aTextString cPtrAsOop. self sqServicesSetTextString: aTextString length: dataTypesLength. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:40'! primitiveSetCopyOSTypeString: aTextString "Setup copy ostype string" self primitive: 'primitiveSetCopyOSTypeString' parameters: #(String). self sqServicesSetCopyOSTypeString: aTextString. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 11:25'! primitiveSetDataTypes: dataTypes "OSType MyAppsDataTypes[] ='TEXT','PICT','MooV','AIFF','utxt'}; " | dataTypesLength | self primitive: 'primitiveSetDataTypes' parameters: #(String). dataTypesLength := interpreterProxy slotSizeOf: dataTypes cPtrAsOop. self sqServicesSetDataTypes: dataTypes length: dataTypesLength. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:40'! primitiveSetPasteOSTypeString: aTextString "Setup paste ostype string" self primitive: 'primitiveSetPasteOSTypeString' parameters: #(String). self sqServicesSetPasteOSTypeString: aTextString. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:41'! primitiveSetPerformOSTypeString: aTextString "Setup perform ostype string" self primitive: 'primitiveSetPerformOSTypeString' parameters: #(String). self sqServicesSetPerformOSTypeString: aTextString. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 9/8/2005 09:19'! primitiveSetReturnBytes: aByteArray osType: aOSType "Setup text string" | dataTypesLength | self primitive: 'primitiveSetReturnBytes' parameters: #(ByteArray String). dataTypesLength := interpreterProxy slotSizeOf: aByteArray cPtrAsOop. self sqServicesSetBytes: aByteArray length: dataTypesLength osType: aOSType. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 15:13'! primitiveSetReturnTextString: aTextString "Setup text string" | dataTypesLength | self primitive: 'primitiveSetReturnTextString' parameters: #(String). dataTypesLength := interpreterProxy slotSizeOf: aTextString cPtrAsOop. self sqServicesSetReturnTextString: aTextString length: dataTypesLength. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 11:33'! primitiveSetSemaphore: semi self primitive: 'primitiveSetSemaphore' parameters: #(SmallInteger). self sqServicesSetSemaphore: semi. ! ! !ServicesPlugin methodsFor: 'initialize' stamp: 'JMM 6/12/2005 11:44'! primitiveSetTextString: aTextString "Setup text string" | dataTypesLength | self primitive: 'primitiveSetTextString' parameters: #(String). dataTypesLength := interpreterProxy slotSizeOf: aTextString cPtrAsOop. self sqServicesSetTextString: aTextString length: dataTypesLength. ! ! !ServicesPlugin class methodsFor: 'translation' stamp: 'JMM 9/8/2005 09:48'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !ServicesPlugin class methodsFor: 'translation' stamp: 'JMM 9/8/2005 09:52'! requiresCrossPlatformFiles "default is ok for most, any plugin needing platform specific files must say so" ^false! ! !ServicesPlugin class methodsFor: 'translation' stamp: 'JMM 6/12/2005 13:12'! requiresPlatformFiles "this plugin requires platform specific files in order to work" ^true! ! !ServicesPlugin class reorganize! ('translation' hasHeaderFile requiresCrossPlatformFiles requiresPlatformFiles) ! !ServicesPlugin reorganize! ('initialize' initialiseModule moduleUnloaded: primitiveGetBytes primitiveGetTextString primitiveSetBytes: primitiveSetCopyOSTypeString: primitiveSetDataTypes: primitiveSetPasteOSTypeString: primitiveSetPerformOSTypeString: primitiveSetReturnBytes:osType: primitiveSetReturnTextString: primitiveSetSemaphore: primitiveSetTextString:) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/MacServicesReadMe.rtf ================================================ {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf110 {\fonttbl\f0\froman\fcharset77 TimesNewRomanPSMT;\f1\fnil\fcharset77 LucidaGrande;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww11420\viewh12140\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural \f0\fs28 \cf0 MacServices\ June 13th, 2005, Sept 9th, 2005\ John M McIntosh\ johnmci@smalltalkconsulting.com\ \ Visit my Idisk, \f1\fs24 experimental:MacServices directory \f0\fs28 \ \ This plugin and change set, along with a 3.8.8b3 (or higher) VM allow you to enter the world of OS-X services. With this change you can select text, give it to the plugin, then select from the Services menu, and have the service grab the text. Also you can from many applications select text, invoke Squeak DoIt from the services menu and get a result back from invoking Compile on the selected text. \ \ In the 1.0.1 plugin release and JMMMacServices.4.cs change set you can set the type of data to something other than TEXT, for example 16 bit unicode 'utxt' \ \ MacServicesInterface current setBytes:\ ('ackbar' convertToWithConverter: (TextConverter newForEncoding: 'utf-16')).\ \ To make this happen on your machine. \ \ Installl the Squeak 3.8.8beta3.app.zip (or higher) unzipped in your Application's directory and log off and back on your machine. This is the only way (unless someone discovers another way) to make os-x rebuild the list of available services, so that the Squeak DoIt item will appear in the menu. A quick check would be to check the Services menu once you sign back on to see if Squeak is there. \ \ Install the unzipped ServicesPlugin.bundle.zip in your plugins folder by the 3.8.8b3 VM\ \ File in the change set JMMMacServices.4.cs into a TEST image for testing. I'll note it installs a startup and shutdown method, so something bad could happen, and runs a process that is responsible for processing incoming Service requests. \ \ Launch Apple's textedit , type in 1000 factorial, select go to Services menu and pick \ "Squeak DoIt" \ \ What is pending:\ \ a) Right now to sent the text string you want to work with on the services menu you must invoke: MacServicesInterface current setTextString: Someone could change the logic such that selecting text, auto-runs MacServicesInterface current setTextString: I have not done that. Contributions are welcome!\ \ b) Ability to send text to a service and get the data back automatically. For now this requires you to invoke MacServicesInterface current getTextString. Later we may add a semaphore and loop to invoke a paste or something. Not quite sure if getting the data back works yet. \ \ \ c) MacServicesInterface >>macServicesProcessLogic & getDataExecuteAndReturn both set the return string to the results of the compile printString. However this might not be what we want, perhaps you return the original string, and the results? In Apple's TextEdit it acts as a cut/paste. \ \ d) I may make Squeak a sub menu to allow you to say DoIt, DoItPaste, DoItOriginalPaste or something\ \ In the 1.01 release I added the feature to allow you to pass bytes into and from the inteface via:\ \ getBytes\ setBytes: \ \ To specify the data types to the Services interface you can now set \ \ setCopyOSType:\ setPasteOSType:\ setPerformOSType:\ \ to use a different type from 'TEXT'\ So for example if you want to invoke GRAB to get a screen image you would do \ \ MacServicesInterface current setDataTypes: 'TEXTTIFFutxt'.\ MacServicesInterface current setPasteOSType: 'TIFF'\ Then invoke the Service>>Grab \ Then invoke \ \ MacServicesInterface current getBytes.\ \ Say you want to paste UTF-16 to TextEdit\ \ MacServicesInterface current setCopyOSType: 'utxt'\ MacServicesInterface current setBytes:\ ('ackbar' convertToWithConverter: (TextConverter newForEncoding: 'utf-16')).\ \ In order to use setPerformOSType: which will allow for incoming Squeak DoIt requests to another type than 'TEXT' you must alter:\ \ MacServicesInterface >>getDataExecuteAndReturn\ \ To change it from getBytes, to perhaps use a TextConverter to convert say utf-16 ('utxt') to a string so the Compiler evaluate: string will work as expected. \ \ Observations\ \ a) Invoking text as a SqueakDoIt Service causes Squeak to come to the foreground, then be hidden, yes it's annoying, but that is how the interface works. \ \ b) Not all systems work as you expect, composing in mail and invoking SqueakDoIt Service does not work as expected, not sure why. \ \ c) Invoking SqueakDoIt from an application if squeak is not running causes os-x to launch the Squeak VM that exists in your Applications folder. \ \ d) You must set the OSTYPE for cut/copy/paste between image startups to what you expect, the values default to 'TEXT'\ } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/SqueakServices.pbproj/johnmci.mode1 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID 94AF35A4084782DD00FA5ACB XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 66DF6BFE01D7DCEA00A80119 66B8BC570381F53800A8011A 66DF6BFF01D7DCEA00A80119 66DF6C3901D7DCEA00A80119 944D6212085F458100600D6E 944D6213085F458100600D6E 66DF6C8201D7DF7E00A80119 66DF6C4501D7DEEE00A80119 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 1CC0EA4004350EF90044410B PBXSmartGroupTreeModuleOutlineStateSelectionKey 9 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 693}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 711}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 429 90 908 752 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 203pt Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel sqMacServices.c PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel sqMacServices.c _historyCapacity 0 bookmark 94859C4308D0E67B0084EF9E history 949CD5C0085CC32700EB8605 944D6240085F473000600D6E 941022CE0867E11B00AEB432 94E4F4B608D0987B00B9E724 94E4F51908D0A7C500B9E724 94E4F51B08D0A7C500B9E724 94E0B9F008D0DA420031D5D3 94E0BA3008D0DDBE0031D5D3 prevStack 949CD574085CBE0300EB8605 949CD576085CBE0300EB8605 949CD577085CBE0300EB8605 949CD5C5085CC32700EB8605 949CD5C6085CC32700EB8605 944D621E085F45A500600D6E 94E4F4DC08D0A2D300B9E724 94E4F51E08D0A7C500B9E724 SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {700, 649}} RubberWindowFrame 429 90 908 752 0 0 1440 878 Module PBXNavigatorGroup Proportion 649pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 654}, {700, 58}} RubberWindowFrame 429 90 908 752 0 0 1440 878 Module XCDetailModule Proportion 58pt Proportion 700pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 94859C2208D0DE7C0084EF9E 1CE0B1FE06471DED0097A5F4 94859C2308D0DE7C0084EF9E 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 147908219.01835099 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList 94859C4508D0E67B0084EF9E 94859C4608D0E67B0084EF9E 94859C3008D0E1C20084EF9E 94859C3108D0E1C20084EF9E 94ABA92F0858D3A300079BE1 1CD10A99069EF8BA00B06720 94859C2A08D0DE7C0084EF9E /Users/johnmci/Documents/SqueakServicesPlugin/SqueakServices.pbproj 94E4F4CD08D0A1CA00B9E724 WindowString 429 90 908 752 0 0 1440 878 WindowTools FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {879, 326}} RubberWindowFrame 91 68 879 795 0 0 1440 878 Module PBXNavigatorGroup Proportion 326pt BecomeActive ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1012 GeometryConfiguration Frame {{0, 331}, {879, 423}} RubberWindowFrame 91 68 879 795 0 0 1440 878 Module PBXBuildResultsModule Proportion 423pt Proportion 754pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 94E4F4CD08D0A1CA00B9E724 94859C4408D0E67B0084EF9E 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 91 68 879 795 0 0 1440 878 WindowToolGUID 94E4F4CD08D0A1CA00B9E724 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {373, 325}} {{0, 325}, {373, 379}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {373, 704}} {{373, 0}, {769, 704}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {1142, 704}} RubberWindowFrame 196 68 1142 745 0 0 1440 878 Module PBXDebugSessionModule Proportion 704pt Proportion 704pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 94859C2408D0DE7C0084EF9E 1C162984064C10D400B95A72 94859C2508D0DE7C0084EF9E 94859C2608D0DE7C0084EF9E 94859C2708D0DE7C0084EF9E 94859C2808D0DE7C0084EF9E 94859C2908D0DE7C0084EF9E 94859C2A08D0DE7C0084EF9E ToolbarConfiguration xcode.toolbar.config.debug WindowString 196 68 1142 745 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel sqMacServices.h StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {791, 416}} RubberWindowFrame 51 90 791 674 0 0 1440 878 Module PBXNavigatorGroup Proportion 791pt Proportion 416pt ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 421}, {791, 212}} RubberWindowFrame 51 90 791 674 0 0 1440 878 Module PBXProjectFindModule Proportion 212pt Proportion 633pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE 94E4F4D608D0A1CA00B9E724 94E4F4D708D0A1CA00B9E724 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 51 90 791 674 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {686, 500}} RubberWindowFrame 759 114 686 541 0 0 1440 878 Module PBXDebugCLIModule Proportion 500pt Proportion 500pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 94ABA92F0858D3A300079BE1 94859C2E08D0E1C20084EF9E 1C78EAAC065D492600B07095 WindowString 759 114 686 541 0 0 1440 878 WindowToolGUID 94ABA92F0858D3A300079BE1 WindowToolIsVisible Identifier windowTool.run Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {493, 167}} {{0, 176}, {493, 267}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {405, 443}} {{414, 0}, {514, 443}} GeometryConfiguration Frame {{0, 0}, {460, 159}} RubberWindowFrame 316 696 459 200 0 0 1280 1002 Module PBXRunSessionModule Proportion 159pt Proportion 159pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible 1 TableOfContents 1C0AD2B3069F1EA900FABCE6 1C0AD2B4069F1EA900FABCE6 1CD0528B0623707200166675 1C0AD2B5069F1EA900FABCE6 ToolbarConfiguration xcode.toolbar.config.run WindowString 316 696 459 200 0 0 1280 1002 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible 0 Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.breakpoints IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD052930623707200166675 PBXProjectModuleLabel Breakpoints GeometryConfiguration BreakpointsTreeTableConfiguration enabledColumn 16 breakpointColumn 482 Frame {{0, 0}, {506, 360}} RubberWindowFrame 780 250 506 380 0 0 1440 878 Module PBXDebugBreakpointsModule Proportion 360pt Proportion 360pt Name Breakpoints ServiceClasses PBXDebugBreakpointsModule StatusbarIsVisible TableOfContents 1C0AD2AD069F1E9B00FABCE6 94F94C8F085D4373008ACC85 1CD052930623707200166675 WindowString 780 250 506 380 0 0 1440 878 WindowToolGUID 1C0AD2AD069F1E9B00FABCE6 WindowToolIsVisible Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.classBrowser IsVertical Layout Dock BecomeActive ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {378, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 332}} MembersFrame {{0, 101}, {378, 231}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 101 PBXMemberBookColumnIdentifier 22 RubberWindowFrame 312 384 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible TableOfContents 1C0AD2AF069F1E9B00FABCE6 949CD652085CD34000EB8605 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 312 384 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/SqueakServices.pbproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66B8BC5A0381F63A00A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1064, 2142}}"; sepNavSelRange = "{1454, 21}"; sepNavVisRect = "{{0, 0}, {659, 490}}"; }; }; 66B8BC5C0381F66500A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 6117}}"; sepNavSelRange = "{16850, 24}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2968}}"; sepNavSelRange = "{1486, 20}"; sepNavVisRect = "{{0, 9}, {673, 397}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66DF6BFD01D7DCEA00A80119 = { activeBuildStyle = 66DF6C4401D7DCEA00A80119; activeExecutable = 94ABA91E0858D35E00079BE1; activeTarget = 94AF34E00846F91100FA5ACB; addToTargets = ( 94AF34E00846F91100FA5ACB, ); breakpoints = ( 94E4F52F08D0B2D800B9E724, 94E4F55308D0CE0000B9E724, 94859C3B08D0E2FB0084EF9E, 94859C3E08D0E3370084EF9E, ); codeSenseManager = 9444E60E06E7B8740063F6CC; executables = ( 94ABA91E0858D35E00079BE1, ); expressions = ( buffer, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 200, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 348.5835, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 461, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 63, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 147906161; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 147906161; }; perUserProjectItems = { 941022CE0867E11B00AEB432 = 941022CE0867E11B00AEB432; 944D621E085F45A500600D6E = 944D621E085F45A500600D6E; 944D6240085F473000600D6E = 944D6240085F473000600D6E; 94859C4308D0E67B0084EF9E = 94859C4308D0E67B0084EF9E; 949CD574085CBE0300EB8605 = 949CD574085CBE0300EB8605; 949CD576085CBE0300EB8605 = 949CD576085CBE0300EB8605; 949CD577085CBE0300EB8605 = 949CD577085CBE0300EB8605; 949CD5C0085CC32700EB8605 = 949CD5C0085CC32700EB8605; 949CD5C5085CC32700EB8605 = 949CD5C5085CC32700EB8605; 949CD5C6085CC32700EB8605 = 949CD5C6085CC32700EB8605; 94E0B9F008D0DA420031D5D3 = 94E0B9F008D0DA420031D5D3; 94E0BA3008D0DDBE0031D5D3 = 94E0BA3008D0DDBE0031D5D3; 94E4F4B608D0987B00B9E724 = 94E4F4B608D0987B00B9E724; 94E4F4DC08D0A2D300B9E724 = 94E4F4DC08D0A2D300B9E724; 94E4F51908D0A7C500B9E724 = 94E4F51908D0A7C500B9E724; 94E4F51B08D0A7C500B9E724 = 94E4F51B08D0A7C500B9E724; 94E4F51E08D0A7C500B9E724 = 94E4F51E08D0A7C500B9E724; }; sourceControlManager = 9444E60D06E7B8740063F6CC; userBuildSettings = { }; }; 941022CE0867E11B00AEB432 = { fRef = 944D6214085F458100600D6E; isa = PBXTextBookmark; name = "English: 7"; rLen = 0; rLoc = 251; rType = 0; vrLen = 251; vrLoc = 0; }; 9444E60D06E7B8740063F6CC = { fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; isa = PBXSourceControlManager; scmConfiguration = { }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC = { indexTemplatePath = ""; isa = PBXCodeSenseManager; }; 944D6214085F458100600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {659, 490}}"; sepNavSelRange = "{0, 251}"; sepNavVisRect = "{{0, 0}, {659, 490}}"; sepNavWindowFrame = "{{176, 7}, {962, 719}}"; }; }; 944D621E085F45A500600D6E = { fRef = 944D6214085F458100600D6E; isa = PBXTextBookmark; name = "English: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 251; vrLoc = 0; }; 944D6240085F473000600D6E = { fRef = 949CD57E085CBE5900EB8605; isa = PBXTextBookmark; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 94859C3B08D0E2FB0084EF9E = { fileReference = 949CD547085CBD4100EB8605; functionName = "sqServicesSetByteslengthosType()"; isa = PBXFileBreakpoint; lineNumber = 116; state = 1; }; 94859C3E08D0E3370084EF9E = { fileReference = 949CD547085CBD4100EB8605; functionName = "sqServicesGetTextStringInto()"; isa = PBXFileBreakpoint; lineNumber = 142; state = 1; }; 94859C4308D0E67B0084EF9E = { fRef = 949CD547085CBD4100EB8605; isa = PBXTextBookmark; name = kEventServicePerform; rLen = 20; rLoc = 6667; rType = 0; vrLen = 1266; vrLoc = 5829; }; 949CD541085CBD1900EB8605 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {728, 5236}}"; sepNavSelRange = "{3298, 0}"; sepNavVisRect = "{{0, 1407}, {728, 672}}"; sepNavWindowFrame = "{{60, 112}, {962, 719}}"; }; }; 949CD546085CBD4100EB8605 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {750, 384}}"; sepNavSelRange = "{123, 0}"; sepNavVisRect = "{{0, 0}, {750, 384}}"; }; }; 949CD547085CBD4100EB8605 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {974, 5222}}"; sepNavSelRange = "{6667, 20}"; sepNavVisRect = "{{0, 2911}, {659, 617}}"; sepNavWindowFrame = "{{176, 7}, {962, 719}}"; }; }; 949CD574085CBE0300EB8605 = { fRef = 949CD546085CBD4100EB8605; isa = PBXTextBookmark; name = "sqMacServices.h: 6"; rLen = 0; rLoc = 89; rType = 0; vrLen = 125; vrLoc = 0; }; 949CD576085CBE0300EB8605 = { fRef = 94AF34F10846F91100FA5ACB; isa = PBXTextBookmark; name = "Info-SqueakServicesPlugin__Upgraded_.plist: 18"; rLen = 0; rLoc = 632; rType = 0; vrLen = 903; vrLoc = 0; }; 949CD577085CBE0300EB8605 = { fRef = 949CD541085CBD1900EB8605; isa = PBXTextBookmark; name = "ServicesPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 824; vrLoc = 0; }; 949CD57E085CBE5900EB8605 = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakSerialPortExtendedUnixPlugin/resources/English.lproj/InfoPlist.strings; refType = 0; sourceTree = ""; }; 949CD5C0085CC32700EB8605 = { fRef = 66C6C8E501DB1EC300A80109; isa = PBXBookmark; }; 949CD5C5085CC32700EB8605 = { fRef = 949CD57E085CBE5900EB8605; isa = PBXTextBookmark; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 949CD5C6085CC32700EB8605 = { fRef = 66C6C8E501DB1EC300A80109; isa = PBXBookmark; }; 94ABA91E0858D35E00079BE1 = { activeArgIndex = 2147483647; activeArgIndices = ( ); argumentStrings = ( ); configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; cppStopOnCatchEnabled = 0; cppStopOnThrowEnabled = 0; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; isa = PBXExecutable; launchableReference = 94E4F56108D0D68A00B9E724; libgmallocEnabled = 0; name = Squeak; savedGlobals = { /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/ServicesPlugin.bundle/Contents/MacOS/ServicesPlugin = ( { dataValue = " PBXGDB_VarObjDataValue2=0xa24e0c0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypes, value=[256]\n"; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypes; type = "char [256]"; value = "[256]"; varobj = var108; }, { dataValue = " PBXGDB_VarObjDataValue2=0x627dc00, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypes, value=[64] "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypes; type = "OSType [64]"; value = "[64]"; varobj = var7; }, { dataValue = " PBXGDB_VarObjDataValue2=0x621fe20, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myEventServicePasteOSType, value=utxt "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myEventServicePasteOSType; type = OSType; value = 1413830740; varobj = var8; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5c68510, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myEventServicePerformOSType, value=utxt "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myEventServicePerformOSType; type = OSType; value = 1413830740; varobj = var9; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5c8aab0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=1, childValidityStatus=Valid, numViewController=0, name=myTextStringIn, value=0x3637d0 PBXGDB_VarObjDataValue2=0x62ca470, rtnCnt=1, parent=0x5c8aab0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=*myTextStringIn, value=0 '\\0' "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringIn; type = "char *"; value = "0x3c87e0 \"1000 factorial\\r\\001CFRLCFRL\""; varobj = var10; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5ce75e0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypesSize, value=4 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypesSize; type = "long int"; value = 4; varobj = var12; }, { dataValue = " PBXGDB_VarObjDataValue2=0x133fed0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringInLength, value=30 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringInLength; type = "long int"; value = 15; varobj = var13; }, { dataValue = " PBXGDB_VarObjDataValue2=0x62f6370, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myEventServiceCopyOSType, value=utxt "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myEventServiceCopyOSType; type = OSType; value = 1413830740; varobj = var15; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5cd1790, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringOut, value=0x0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringOut; type = "char *"; value = 0x0; varobj = var16; }, { dataValue = " PBXGDB_VarObjDataValue2=0x13f62d0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=specificScrap, value=0x28000000 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = specificScrap; type = ScrapRef; value = 0x8000000; varobj = var17; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5c8a860, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringOutLength, value=0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringOutLength; type = "long int"; value = 0; varobj = var21; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5ca4ee0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=gWaiting, value=1 '\\001' "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = gWaiting; type = Boolean; value = "1 '\\001'"; varobj = var23; }, { dataValue = " PBXGDB_VarObjDataValue2=0x5c550d0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=ghideStupidApplicationNow, value=0 '\\0' "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = ghideStupidApplicationNow; type = Boolean; value = "0 '\\0'"; varobj = var24; }, ); }; shlibInfoDictList_v2 = ( { level = 0; path = /usr/lib/system/libmathCommon.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libSystem.B.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libicucore.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libauto.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libobjc.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; whenToLoad = 0; }, { level = 0; path = /usr/lib/libz.1.2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Security.framework/Versions/A/Security; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/WebServicesCore.framework/Versions/A/WebServicesCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound; whenToLoad = 0; }, { level = 0; path = /usr/lib/libbsm.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcrypto.0.9.7.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcups.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/FindByContent.framework/Versions/A/FindByContent; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRaw.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libmx.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices; whenToLoad = 0; }, { level = 0; path = /usr/lib/libiconv.2.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libxml2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HTMLRendering.framework/Versions/A/HTMLRendering; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/NavigationServices.framework/Versions/A/NavigationServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AGL.framework/Versions/A/AGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/QuickTime.framework/Versions/A/QuickTime; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/ZeroLink.framework/Versions/A/ZeroLink; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app/Contents/MacOS/Squeak; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacEncoding.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/interp.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIMenuBar.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMain.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGATS.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCSync.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIClipBoard.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixCommandLineInterface.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIAppleEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacFileLogic.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacImageIO.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Components/DictionaryService.component/Contents/MacOS/DictionaryService; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMemory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacTime.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/UUIDPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SurfacePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/StarSqueakPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundGenerationPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundCodecPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SocketPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SerialPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SecurityPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MiscPrimitivePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Matrix2x3Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MIDIPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MacMenubarPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/LargeIntegers.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Klatt.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JoystickTabletPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReaderPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Error.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReadWriter2Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/InternetConfigPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/HostWindowPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/GeniePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FloatArrayPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FFTPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DropPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ZipPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DSAPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BitBltPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B2DPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BMPReadWriterPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Squeak3D.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B3DAcceleratorPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/AsynchFilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ADPCMCodecPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSerialPort.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/osExports.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqNamedPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqVirtualMachine.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/aio.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacExternalPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacHostWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSecurity.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqFilePluginBasicPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDirectory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDragDrop.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixInterfaceSound.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSoundMacOSXJMM.ob"; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/LocalePlugin.bundle/Contents/MacOS/LocalePlugin; whenToLoad = 0; }, { level = 0; path = /Developer/Applications/Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin/Contents/Resources/PBGDBIntrospectionSupport.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Library/Application Support/Apple/Developer Tools/CustomDataViews/CFDataFormatters.bundle/Contents/MacOS/CFDataFormatters"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSocket.ob"; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/ServicesPlugin.bundle/Contents/MacOS/ServicesPlugin; whenToLoad = 0; }, { level = 0; path = /usr/lib/libgcc_s.1.0.dylib; whenToLoad = 0; }, { level = 0; path = "/usr/lib/libstdc++.6.0.3.dylib"; whenToLoad = 0; }, { level = 0; path = "/Library/Application Support/Apple/Developer Tools/CustomDataViews/CarbonDataFormatters.bundle/Contents/MacOS/CarbonDataFormatters"; whenToLoad = 0; }, { level = 0; path = /usr/lib/dyld; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/URLMount.framework/Versions/A/URLMount; whenToLoad = 0; }, { level = 0; path = /usr/lib/libz.1.2.3.dylib; whenToLoad = 0; }, ); sourceDirectories = ( ); }; 94AF34E00846F91100FA5ACB = { activeExec = 0; }; 94AF34F10846F91100FA5ACB = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {923, 590}}"; sepNavSelRange = "{284, 6}"; sepNavVisRect = "{{0, 0}, {923, 590}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; 94AF35000846F98600FA5ACB = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2590}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; 94E0B9F008D0DA420031D5D3 = { fRef = 949CD541085CBD1900EB8605; isa = PBXTextBookmark; name = SetReturnB; rLen = 10; rLoc = 6585; rType = 0; vrLen = 1653; vrLoc = 8597; }; 94E0BA3008D0DDBE0031D5D3 = { fRef = 949CD547085CBD4100EB8605; isa = PBXTextBookmark; name = kEventServicePerform; rLen = 20; rLoc = 6667; rType = 0; vrLen = 1266; vrLoc = 5829; }; 94E4F4B608D0987B00B9E724 = { fRef = 949CD546085CBD4100EB8605; isa = PBXTextBookmark; name = "sqMacServices.h: 6"; rLen = 0; rLoc = 89; rType = 0; vrLen = 125; vrLoc = 0; }; 94E4F4DC08D0A2D300B9E724 = { fRef = 949CD547085CBD4100EB8605; isa = PBXTextBookmark; name = sqServicesGetText; rLen = 17; rLoc = 3868; rType = 0; vrLen = 580; vrLoc = 2903; }; 94E4F4E808D0A44600B9E724 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {659, 280}}"; sepNavSelRange = "{7, 16}"; sepNavVisRect = "{{0, 3}, {659, 277}}"; sepNavWindowFrame = "{{84, 99}, {1310, 711}}"; }; }; 94E4F51908D0A7C500B9E724 = { fRef = 94E4F4E808D0A44600B9E724; isa = PBXTextBookmark; name = ServicesPlugin.h; rLen = 16; rLoc = 7; rType = 0; vrLen = 786; vrLoc = 0; }; 94E4F51B08D0A7C500B9E724 = { fRef = 94AF34F10846F91100FA5ACB; isa = PBXTextBookmark; name = "Info.plist: 29"; rLen = 0; rLoc = 903; rType = 0; vrLen = 903; vrLoc = 0; }; 94E4F51E08D0A7C500B9E724 = { fRef = 94E4F4E808D0A44600B9E724; isa = PBXTextBookmark; name = ServicesPlugin.h; rLen = 16; rLoc = 7; rType = 0; vrLen = 786; vrLoc = 0; }; 94E4F52F08D0B2D800B9E724 = { fileReference = 949CD547085CBD4100EB8605; functionName = "MyServicesEventHandler()"; isa = PBXFileBreakpoint; lineNumber = 194; state = 1; }; 94E4F55308D0CE0000B9E724 = { fileReference = 949CD547085CBD4100EB8605; functionName = "MyServicesEventHandler()"; isa = PBXFileBreakpoint; lineNumber = 217; state = 1; }; 94E4F56108D0D68A00B9E724 = { isa = PBXFileReference; lastKnownFileType = wrapper.application; name = Squeak.app; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app; refType = 0; sourceTree = ""; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/SqueakServices.pbproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 39; objects = { 66B8BC570381F53800A8011A = { children = ( 94AF35040846F9AB00FA5ACB, 94AF35000846F98600FA5ACB, 66B8BC580381F61C00A8011A, 66B8BC5A0381F63A00A8011A, 66B8BC5C0381F66500A8011A, 66B8BC5E0381F69100A8011A, 94ABA8920858C40D00079BE1, ); isa = PBXGroup; name = platforms; path = ../Squeak3.8.0/platforms; refType = 2; sourceTree = SOURCE_ROOT; }; 66B8BC580381F61C00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = "Mac OS/vm/sqConfig.h"; refType = 4; sourceTree = ""; }; 66B8BC5A0381F63A00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqPlatformSpecific.h"; refType = 0; sourceTree = ""; }; 66B8BC5C0381F66500A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sq.h; path = Cross/vm/sq.h; refType = 4; sourceTree = ""; }; 66B8BC5E0381F69100A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/Cross/vm/sqVirtualMachine.h; refType = 0; sourceTree = ""; }; 66C6C8E501DB1EC300A80109 = { isa = PBXFileReference; lastKnownFileType = image.icns; path = SqueakPlugin.icns; refType = 4; sourceTree = ""; }; 66DF6BFD01D7DCEA00A80119 = { buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; }; buildStyles = ( 66DF6C4301D7DCEA00A80119, 66DF6C4401D7DCEA00A80119, ); hasScannedForEncodings = 1; isa = PBXProject; mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119; projectDirPath = ""; targets = ( 94AF34E00846F91100FA5ACB, ); }; 66DF6BFE01D7DCEA00A80119 = { children = ( 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, 66DF6C3901D7DCEA00A80119, 66DF6C8201D7DF7E00A80119, 66DF6C4501D7DEEE00A80119, 94AF34F10846F91100FA5ACB, ); isa = PBXGroup; refType = 4; sourceTree = ""; }; 66DF6BFF01D7DCEA00A80119 = { children = ( 949CD541085CBD1900EB8605, 94E4F4E808D0A44600B9E724, 949CD547085CBD4100EB8605, 949CD546085CBD4100EB8605, ); isa = PBXGroup; name = Sources; refType = 4; sourceTree = ""; }; 66DF6C3901D7DCEA00A80119 = { children = ( 944D6212085F458100600D6E, 66C6C8E501DB1EC300A80109, ); isa = PBXGroup; name = resources; refType = 4; sourceTree = ""; }; 66DF6C4301D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Development; }; 66DF6C4401D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; OPTIMIZATION_CFLAGS = "-O3 -mcpu=750 -funroll-loops "; OTHER_CFLAGS = "-DTARGET_OS_MAC -DNOPTHREADS"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; }; 66DF6C4501D7DEEE00A80119 = { children = ( 943173AF085CD38900DDDC64, ); isa = PBXGroup; name = Products; refType = 4; sourceTree = ""; }; 66DF6C8201D7DF7E00A80119 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; refType = 0; sourceTree = ""; }; //660 //661 //662 //663 //664 //940 //941 //942 //943 //944 943173AF085CD38900DDDC64 = { explicitFileType = wrapper.cfbundle; includeInIndex = 0; isa = PBXFileReference; path = ServicesPlugin.bundle; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; 944D6212085F458100600D6E = { children = ( 944D6213085F458100600D6E, ); isa = PBXGroup; name = English.lproj; path = resources/English.lproj; refType = 4; sourceTree = ""; }; 944D6213085F458100600D6E = { children = ( 944D6214085F458100600D6E, ); isa = PBXVariantGroup; name = InfoPlist.strings; path = ""; refType = 4; sourceTree = ""; }; 944D6214085F458100600D6E = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = InfoPlist.strings; refType = 4; sourceTree = ""; }; 944D6215085F458100600D6E = { fileRef = 944D6213085F458100600D6E; isa = PBXBuildFile; settings = { }; }; 949CD541085CBD1900EB8605 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ServicesPlugin.c; refType = 4; sourceTree = ""; }; 949CD542085CBD1A00EB8605 = { fileRef = 949CD541085CBD1900EB8605; isa = PBXBuildFile; settings = { }; }; 949CD546085CBD4100EB8605 = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sqMacServices.h; refType = 4; sourceTree = ""; }; 949CD547085CBD4100EB8605 = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sqMacServices.c; refType = 4; sourceTree = ""; }; 949CD548085CBD4100EB8605 = { fileRef = 949CD546085CBD4100EB8605; isa = PBXBuildFile; settings = { }; }; 949CD549085CBD4100EB8605 = { fileRef = 949CD547085CBD4100EB8605; isa = PBXBuildFile; settings = { }; }; 94ABA8920858C40D00079BE1 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = Cross/vm/sqMemoryAccess.h; refType = 4; sourceTree = ""; }; 94ABA8930858C40D00079BE1 = { fileRef = 94ABA8920858C40D00079BE1; isa = PBXBuildFile; settings = { }; }; 94AF34E00846F91100FA5ACB = { buildPhases = ( 94AF34E10846F91100FA5ACB, 94AF34E70846F91100FA5ACB, 94AF34EA0846F91100FA5ACB, 94AF34EE0846F91100FA5ACB, 94AF34F00846F91100FA5ACB, ); buildRules = ( 94AF34F70846F94F00FA5ACB, ); buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = ServicesPlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = bundle; }; dependencies = ( ); isa = PBXNativeTarget; name = "SqueakServicesPlugin (Upgraded)"; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 943173AF085CD38900DDDC64; productType = "com.apple.product-type.bundle"; }; 94AF34E10846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E20846F91100FA5ACB, 94AF34E30846F91100FA5ACB, 94AF34E40846F91100FA5ACB, 94AF34E50846F91100FA5ACB, 94AF35010846F98600FA5ACB, 94AF35050846F9AB00FA5ACB, 94ABA8930858C40D00079BE1, 949CD548085CBD4100EB8605, 94E4F4E908D0A44600B9E724, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E20846F91100FA5ACB = { fileRef = 66B8BC580381F61C00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E30846F91100FA5ACB = { fileRef = 66B8BC5A0381F63A00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E40846F91100FA5ACB = { fileRef = 66B8BC5C0381F66500A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E50846F91100FA5ACB = { fileRef = 66B8BC5E0381F69100A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E70846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E80846F91100FA5ACB, 944D6215085F458100600D6E, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E80846F91100FA5ACB = { fileRef = 66C6C8E501DB1EC300A80109; isa = PBXBuildFile; settings = { }; }; 94AF34EA0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 949CD542085CBD1A00EB8605, 949CD549085CBD4100EB8605, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EE0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34EF0846F91100FA5ACB, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EF0846F91100FA5ACB = { fileRef = 66DF6C8201D7DF7E00A80119; isa = PBXBuildFile; settings = { }; }; 94AF34F00846F91100FA5ACB = { buildActionMask = 2147483647; files = ( ); isa = PBXRezBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34F10846F91100FA5ACB = { isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; refType = 4; sourceTree = ""; }; 94AF34F70846F94F00FA5ACB = { compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; isa = PBXBuildRule; outputFiles = ( ); }; 94AF35000846F98600FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = "Mac OS/vm/config.h"; refType = 4; sourceTree = ""; }; 94AF35010846F98600FA5ACB = { fileRef = 94AF35000846F98600FA5ACB; isa = PBXBuildFile; settings = { }; }; 94AF35040846F9AB00FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../Squeak3.8.0/src/vm/interp.h; refType = 2; sourceTree = SOURCE_ROOT; }; 94AF35050846F9AB00FA5ACB = { fileRef = 94AF35040846F9AB00FA5ACB; isa = PBXBuildFile; settings = { }; }; 94E4F4E808D0A44600B9E724 = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServicesPlugin.h; refType = 4; sourceTree = ""; }; 94E4F4E908D0A44600B9E724 = { fileRef = 94E4F4E808D0A44600B9E724; isa = PBXBuildFile; settings = { }; }; }; rootObject = 66DF6BFD01D7DCEA00A80119; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/resources/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ CFBundleName = "ServicesPlugin"; CFBundleShortVersionString = "ServicesPlugin version 1.0.0B2"; CFBundleGetInfoString = "ServicesPlugin version 1.0.0B2"; NSHumanReadableCopyright = "http://www.squeak.org"; ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/sqMacServices.c ================================================ /* * sqMacServices.c * SqueakServices * * Created by John M McIntosh on 12/06/05. * */ #include "sqMacServices.h" #include "ServicesPlugin.h" /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #include extern struct VirtualMachine *interpreterProxy; OSType MyAppsDataTypes[64]; long MyAppsDataTypesSize; OSType myEventServiceCopyOSType = kScrapFlavorTypeText; OSType myEventServicePasteOSType = kScrapFlavorTypeText; OSType myEventServicePerformOSType = kScrapFlavorTypeText; char * myTextStringOut=NULL; long myTextStringOutLength=0; char * myTextStringIn=NULL; long myTextStringInLength=0; ScrapRef specificScrap=NULL; long mySemaphore=0; Boolean gWaiting=false; EventHandlerRef myEventRef=NULL; EventTypeSpec serviceEventList[] = { { kEventClassService, kEventServiceGetTypes }, { kEventClassService, kEventServicePerform }, { kEventClassService, kEventServiceCopy }, { kEventClassService, kEventServicePaste } }; static pascal OSStatus MyServicesEventHandler (EventHandlerCallRef myHandlerChain,EventRef event, void* userData); void makeItHideLogic(); void waitAFewMilliseconds(); int sqServicesInitialize() { static Boolean initialized=false; if (initialized) return 1; else initialized = true; InstallApplicationEventHandler(NewEventHandlerUPP(MyServicesEventHandler), GetEventTypeCount(serviceEventList), serviceEventList, 0, &myEventRef); return 1; } int sqServicesShutdown() { if (myEventRef) RemoveEventHandler(myEventRef); myEventRef = NULL; myTextStringInLength = 0; myTextStringOutLength = 0; if (myTextStringIn) { free(myTextStringIn); myTextStringIn = NULL; } if (myTextStringOut) { free(myTextStringOut); myTextStringOut = NULL; } return 1; } void sqServicesSetDataTypeslength(char *dataTypes, long dataTypesLength) { if (dataTypesLength > 256) return; MyAppsDataTypesSize = dataTypesLength; memcpy(MyAppsDataTypes,dataTypes,MyAppsDataTypesSize); } void sqServicesSetSemaphore(int semi){ mySemaphore = semi; } void sqServicesSetTextStringlength(char *aTextString, int stringLength){ if (myTextStringOut != NULL) free(myTextStringOut); myTextStringOutLength = stringLength; myTextStringOut = malloc(myTextStringOutLength+1); memcpy(myTextStringOut,aTextString,myTextStringOutLength); myTextStringOut[myTextStringOutLength] = 0x00; } void sqServicesSetReturnTextStringlength(char *aTextString, int stringLength){ if(specificScrap == NULL) return; ClearScrap (&specificScrap); PutScrapFlavor (specificScrap, kScrapFlavorTypeText,kScrapFlavorMaskNone,stringLength,aTextString); gWaiting = false; specificScrap = NULL; } void sqServicesSetByteslengthosType(char *aByteArray, long dataTypesLength, char *aOSTypeString) { OSType typeToUse; if(specificScrap == NULL) return; typeToUse = CFSwapInt32HostToBig((int) *(int *) aOSTypeString); ClearScrap (&specificScrap); PutScrapFlavor (specificScrap, typeToUse ,kScrapFlavorMaskNone,dataTypesLength,aByteArray); gWaiting = false; specificScrap = NULL; } void sqServicesSetCopyOSTypeString(char *aOSTypeString) { myEventServiceCopyOSType = CFSwapInt32HostToBig((int) *(int *) aOSTypeString); } void sqServicesSetPasteOSTypeString(char *aOSTypeString) { myEventServicePasteOSType = CFSwapInt32HostToBig((int) *(int *) aOSTypeString); } void sqServicesSetPerformOSTypeString(char *aOSTypeString) { myEventServicePerformOSType = CFSwapInt32HostToBig((int) *(int *)aOSTypeString); } int sqServicesGetTextStringLength(void){ return myTextStringInLength; } void sqServicesGetTextStringInto(char *buffer) { memcpy(buffer,myTextStringIn,myTextStringInLength); } static pascal OSStatus MyServicesEventHandler (EventHandlerCallRef myHandlerChain, EventRef event, void* userData) { UInt32 whatHappened; OSStatus result = eventNotHandledErr; /* report failure by default */ whatHappened = GetEventKind(event); switch (whatHappened) { case kEventServiceGetTypes: { Boolean textSelection = true; CFMutableArrayRef copyTypes, pasteTypes; short index, count; if (textSelection) { GetEventParameter (event, kEventParamServiceCopyTypes, typeCFMutableArrayRef, NULL, sizeof (CFMutableArrayRef), NULL, ©Types); } GetEventParameter (event, kEventParamServicePasteTypes, typeCFMutableArrayRef, NULL, sizeof (CFMutableArrayRef), NULL, &pasteTypes); count = MyAppsDataTypesSize / sizeof (OSType); for ( index = 0; index < count; index++ ) { CFStringRef type = CreateTypeStringWithOSType (CFSwapInt32HostToBig(MyAppsDataTypes [index])); if (type) { if (textSelection) CFArrayAppendValue (copyTypes, type); CFArrayAppendValue (pasteTypes, type); CFRelease (type); } } result = noErr; } break; case kEventServiceCopy: { OSStatus status = noErr; ScrapRef scrap; status = GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL, sizeof (ScrapRef), NULL, &scrap ); if (status != noErr) return result; status = ClearScrap (&scrap); if (status != noErr) return result; status = PutScrapFlavor (scrap, myEventServiceCopyOSType, kScrapFlavorMaskNone, myTextStringOutLength, myTextStringOut); if (status != noErr) return result; result = status; } break; case kEventServicePaste: { OSStatus status = noErr; ScrapRef scrap; status = GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL, sizeof (ScrapRef), NULL, &scrap); if (status != noErr) return result; status = GetScrapFlavorSize (scrap, myEventServicePasteOSType, &myTextStringInLength); if (status != noErr) return result; if (myTextStringIn) free(myTextStringIn); myTextStringIn = malloc (myTextStringInLength); status = GetScrapFlavorData (scrap, myEventServicePasteOSType, &myTextStringInLength, myTextStringIn ); result = status; } break; case kEventServicePerform: { OSStatus status = noErr; CFStringRef message; status = GetEventParameter (event, kEventParamServiceMessageName, typeCFStringRef, NULL, sizeof (CFStringRef), NULL, &message); if (status != noErr) return result; status = GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL, sizeof (ScrapRef), NULL, &specificScrap); if (status != noErr) return result; status = GetScrapFlavorSize (specificScrap, myEventServicePerformOSType, &myTextStringInLength); if (status != noErr) return result; if (myTextStringIn) free(myTextStringIn); myTextStringIn = malloc (myTextStringInLength); status = GetScrapFlavorData (specificScrap, myEventServicePerformOSType, &myTextStringInLength, myTextStringIn ); if (status != noErr) return result; if (mySemaphore) interpreterProxy->signalSemaphoreWithIndex(mySemaphore); gWaiting = true; while(gWaiting) waitAFewMilliseconds(); makeItHideLogic(); result = status; } break; default: break; } return result; } EventLoopTimerRef ghideStupidApplication; Boolean ghideStupidApplicationNow=false; static pascal void hideStupidApplication (EventLoopTimerRef theTimer,void* userData); static pascal void hideStupidApplication (EventLoopTimerRef theTimer,void* userData) { if (ghideStupidApplicationNow ) { ProcessSerialNumber psn = { 0, kCurrentProcess }; if (IsProcessVisible(&psn)) ShowHideProcess( &psn, false ); ghideStupidApplicationNow = false; RemoveEventLoopTimer(ghideStupidApplication); } } void makeItHideLogic(int foo) { InstallEventLoopTimer (GetMainEventLoop(), 250*kEventDurationMillisecond, kEventDurationMillisecond, NewEventLoopTimerUPP(hideStupidApplication), NULL,&ghideStupidApplication); ghideStupidApplicationNow = true; } pthread_mutex_t sleepLock; pthread_cond_t sleepLockCondition; void waitAFewMilliseconds() { static Boolean doInitialization=true; const int realTimeToWait = 16; struct timespec tspec; int err; if (doInitialization) { doInitialization = false; pthread_mutex_init(&sleepLock, NULL); pthread_cond_init(&sleepLockCondition,NULL); } tspec.tv_sec= realTimeToWait / 1000; tspec.tv_nsec= (realTimeToWait % 1000)*1000000; err = pthread_mutex_lock(&sleepLock); err = pthread_cond_timedwait_relative_np(&sleepLockCondition,&sleepLock,&tspec); err = pthread_mutex_unlock(&sleepLock); } /* PasteboardRef pasteboard; PasteboardItemID item; CFDataRef sourceData; CFIndex sourceSize; CFMutableDataRef returnData = NULL; const UInt8* sourceBytes; UInt8* returnBytes; CFIndex i; status = GetEventParameter( event, kEventParamPasteboardRef, typePasteboardRef, NULL, sizeof( pasteboard ), NULL, &pasteboard ); if (status != noErr) return result; PasteboardSynchronize(pasteboard); status = PasteboardGetItemIdentifier( pasteboard, 1, &item ); status = PasteboardCopyItemFlavorData( pasteboard, item, CFSTR("com.apple.traditional-mac-plain-text"), &sourceData ); sourceSize = CFDataGetLength( sourceData ); // create the translation's return data storage returnData = CFDataCreateMutable( kCFAllocatorDefault, sourceSize ); sourceBytes = CFDataGetBytePtr( sourceData ); returnBytes = CFDataGetMutableBytePtr( returnData ); for(i = 0; i< sourceSize; i++ ) returnBytes[i] = ( UInt8 )toupper( sourceBytes[ i ] ); status = PasteboardClear( pasteboard ); status = PasteboardPutItemFlavor( pasteboard, item, CFSTR("com.apple.traditional-mac-plain-text"), returnData, kPasteboardFlavorNoFlags ); PasteboardSynchronize(pasteboard); */ /* status = GetScrapFlavorSize (specificScrap, kScrapFlavorTypeText, &myTextStringInLength); if (status != noErr) return result; if (myTextStringIn) free(myTextStringIn); myTextStringIn = malloc (myTextStringInLength); status = GetScrapFlavorData (specificScrap, kScrapFlavorTypeText, &myTextStringInLength, myTextStringIn ); if (status != noErr) return result; ClearScrap (&specificScrap); myTextStringIn[0] = '!'; status = PutScrapFlavor (specificScrap,kScrapFlavorTypeText,kScrapFlavorMaskNone,myTextStringInLength,myTextStringIn); */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/ServicesPlugin/sqMacServices.h ================================================ /* * sqMacServices.h * SqueakServices * * Created by John M McIntosh on 12/06/05. * */ #include ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SocketPlugin/68K/AddressXlation.h ================================================ /* File: AddressXlation.h Contains: TCP Manager interfaces for dnr.c Version: Use with MacTCP 2.0.6 and Universal Interfaces 2.1b1 in MPW Prerelease on ETO #17 Copyright: 1984-1995 by Apple Computer, Inc. All rights reserved. Bugs?: If you find a problem with this file, send the file and version information (from above) and the problem description to: Internet: apple.bugs@applelink.apple.com AppleLink: APPLE.BUGS */ #ifndef __ADDRESSXLATION__ #define __ADDRESSXLATION__ #ifndef __TYPES__ #include #endif /* #include */ #ifndef __MACTCP__ #include #endif /* #include */ /* #include */ /* #include */ /* #include */ #ifdef __cplusplus extern "C" { #endif #if STRUCTALIGNMENTSUPPORTED #pragma options align=mac68k #endif #if PRAGMA_IMPORT_SUPPORTED #pragma import on #endif /* Developer Notes: When the various calls are made to the dnr code, you must set up a NewRoutineDescriptor for every non-nil completion routine and/or notifyProc parameter. Otherwise, the 68K dnr code, will not correctly call your routine. 1. For the call to EnumCache, use NewEnumResultProc to set up a universal procptr to pass as the enumResultProc parameter. 2. For the calls to StrToAddr and AddrToName, use NewResultProc to set up a ResultUPP universal procptr to pass as the ResultProc parameter. 3. For the calls to HInfo and MXInfo, use NewResultProc2Proc to set up a ResultProc2UPP universal procptr to pass as the ResultProc parameter. 4. The DNR selector symbol HINFO has been changed to HXINFO due to conflict with the same symbol in the AddressXLation.h header */ enum { NUM_ALT_ADDRS = 4 }; struct hostInfo { long rtnCode; char cname[255]; SInt8 filler; /* Filler for proper byte alignment */ unsigned long addr[NUM_ALT_ADDRS]; }; typedef struct hostInfo hostInfo; enum { A = 1, NS = 2, CNAME = 5, HINFO = 13, MX = 15, lastClass = 32767 }; typedef unsigned short AddrClasses; /* Domain Name Resolver code selectors */ enum { OPENRESOLVER = 1, CLOSERESOLVER = 2, STRTOADDR = 3, ADDRTOSTR = 4, ENUMCACHE = 5, ADDRTONAME = 6, HXINFO = 7, /* changed from HINFO due to symbol conflict*/ MXINFO = 8 }; struct HInfoRec { char cpuType[30]; char osType[30]; }; typedef struct HInfoRec HInfoRec; struct MXRec { unsigned short preference; char exchange[255]; }; typedef struct MXRec MXRec; struct returnRec { long rtnCode; char cname[255]; SInt8 filler; /* Filler for proper byte alignment */ union { unsigned long addr[NUM_ALT_ADDRS]; struct HInfoRec hinfo; struct MXRec mx; } rdata; }; typedef struct returnRec returnRec; struct cacheEntryRecord { char *cname; unsigned short ctype; unsigned short cacheClass; unsigned long ttl; union { char *name; ip_addr addr; } rdata; }; typedef struct cacheEntryRecord cacheEntryRecord; typedef pascal void (*EnumResultProcPtr)(struct cacheEntryRecord *cacheEntryRecordPtr, Ptr userDataPtr); typedef pascal void (*ResultProcPtr)(struct hostInfo *hostInfoPtr, Ptr userDataPtr); typedef pascal void (*ResultProc2ProcPtr)(struct returnRec *returnRecPtr, Ptr userDataPtr); #if GENERATINGCFM typedef UniversalProcPtr EnumResultUPP; typedef UniversalProcPtr ResultUPP; typedef UniversalProcPtr ResultProc2UPP; #else typedef EnumResultProcPtr EnumResultUPP; typedef ResultProcPtr ResultUPP; typedef ResultProc2ProcPtr ResultProc2UPP; #endif enum { uppEnumResultProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct cacheEntryRecord*))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr))), uppResultProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct hostInfo*))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr))), uppResultProc2ProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct returnRec*))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr))) }; #if GENERATINGCFM #define NewEnumResultProc(userRoutine) \ (EnumResultUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppEnumResultProcInfo, GetCurrentArchitecture()) #define NewResultProc(userRoutine) \ (ResultUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppResultProcInfo, GetCurrentArchitecture()) #define NewResultProc2Proc(userRoutine) \ (ResultProc2UPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppResultProc2ProcInfo, GetCurrentArchitecture()) #else #define NewEnumResultProc(userRoutine) \ ((EnumResultUPP) (userRoutine)) #define NewResultProc(userRoutine) \ ((ResultUPP) (userRoutine)) #define NewResultProc2Proc(userRoutine) \ ((ResultProc2UPP) (userRoutine)) #endif #if GENERATINGCFM #define CallEnumResultProc(userRoutine, cacheEntryRecordPtr, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppEnumResultProcInfo, (cacheEntryRecordPtr), (userDataPtr)) #define CallResultProc(userRoutine, hostInfoPtr, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppResultProcInfo, (hostInfoPtr), (userDataPtr)) #define CallResultProc2Proc(userRoutine, returnRecPtr, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppResultProc2ProcInfo, (returnRecPtr), (userDataPtr)) #else #define CallEnumResultProc(userRoutine, cacheEntryRecordPtr, userDataPtr) \ (*(userRoutine))((cacheEntryRecordPtr), (userDataPtr)) #define CallResultProc(userRoutine, hostInfoPtr, userDataPtr) \ (*(userRoutine))((hostInfoPtr), (userDataPtr)) #define CallResultProc2Proc(userRoutine, returnRecPtr, userDataPtr) \ (*(userRoutine))((returnRecPtr), (userDataPtr)) #endif extern OSErr OpenResolver(char *fileName); extern OSErr StrToAddr(char *hostName, struct hostInfo *hostInfoPtr, ResultUPP ResultProc, char *userDataPtr); extern OSErr AddrToStr(unsigned long addr, char *addrStr); extern OSErr EnumCache(EnumResultUPP enumResultProc, Ptr userDataPtr); extern OSErr AddrToName(ip_addr addr, struct hostInfo *hostInfoPtr, ResultUPP ResultProc, Ptr userDataPtr); extern OSErr HInfo(char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr); extern OSErr MXInfo(char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr); extern OSErr CloseResolver(void); /* Universal ProcPtrs declaration for each of the dnr selector code calls. */ typedef OSErr (*OpenResolverProcPtr)(UInt32 selector, char *filename); typedef OSErr (*CloseResolverProcPtr)(UInt32 selector); typedef OSErr (*StrToAddrProcPtr)(UInt32 selector, char *hostName, struct hostInfo *rtnStruct, ResultUPP resultproc, Ptr userDataPtr); typedef OSErr (*AddrToStrProcPtr)(UInt32 selector, unsigned long addr, char *addrStr); typedef OSErr (*EnumCacheProcPtr)(UInt32 selector, EnumResultUPP resultproc, Ptr userDataPtr); typedef OSErr (*AddrToNameProcPtr)(UInt32 selector, UInt32 addr, struct hostInfo *rtnStruct, ResultUPP resultproc, Ptr userDataPtr); typedef OSErr (*HInfoProcPtr)(UInt32 selector, char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr); typedef OSErr (*MXInfoProcPtr)(UInt32 selector, char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr); #if GENERATINGCFM typedef UniversalProcPtr OpenResolverUPP; typedef UniversalProcPtr CloseResolverUPP; typedef UniversalProcPtr StrToAddrUPP; typedef UniversalProcPtr AddrToStrUPP; typedef UniversalProcPtr EnumCacheUPP; typedef UniversalProcPtr AddrToNameUPP; typedef UniversalProcPtr HInfoUPP; typedef UniversalProcPtr MXInfoUPP; #else typedef OpenResolverProcPtr OpenResolverUPP; typedef CloseResolverProcPtr CloseResolverUPP; typedef StrToAddrProcPtr StrToAddrUPP; typedef AddrToStrProcPtr AddrToStrUPP; typedef EnumCacheProcPtr EnumCacheUPP; typedef AddrToNameProcPtr AddrToNameUPP; typedef HInfoProcPtr HInfoUPP; typedef MXInfoProcPtr MXInfoUPP; #endif enum { uppOpenResolverProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*))), uppCloseResolverProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))), uppStrToAddrProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ResultUPP))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(Ptr))), uppAddrToStrProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char*))), uppEnumCacheProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(EnumResultUPP))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))), uppAddrToNameProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ResultUPP))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(Ptr))), uppHInfoProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ResultProc2UPP))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(Ptr))), uppMXInfoProcInfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UInt32))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ResultProc2UPP))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(Ptr))) }; #if GENERATINGCFM #define CallOpenResolverProc(userRoutine, selector, filename) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppOpenResolverProcInfo, (selector), (filename)) #define CallCloseResolverProc(userRoutine, selector) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppCloseResolverProcInfo, (selector)) #define CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultproc, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppStrToAddrProcInfo, (selector), (hostName), (rtnStruct), (resultproc), (userDataPtr)) #define CallAddrToStrProc(userRoutine, selector, addr, addrStr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppAddrToStrProcInfo, (selector), (addr), (addrStr)) #define CallEnumCacheProc(userRoutine, selector, resultproc, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppEnumCacheProcInfo, (selector), (resultproc), (userDataPtr)) #define CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultproc, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppAddrToNameProcInfo, (selector), (addr), (rtnStruct), (resultproc), (userDataPtr)) #define CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppHInfoProcInfo, (selector), (hostName), (returnRecPtr), (resultProc), (userDataPtr)) #define CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userDataPtr) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppMXInfoProcInfo, (selector), (hostName), (returnRecPtr), (resultProc), (userDataPtr)) #else #define CallOpenResolverProc(userRoutine, selector, filename) \ (*(userRoutine))((selector), (filename)) #define CallCloseResolverProc(userRoutine, selector) \ (*(userRoutine))((selector)) #define CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultproc, userDataPtr) \ (*(userRoutine))((selector), (hostName), (rtnStruct), (resultproc), (userDataPtr)) #define CallAddrToStrProc(userRoutine, selector, addr, addrStr) \ (*(userRoutine))((selector), (addr), (addrStr)) #define CallEnumCacheProc(userRoutine, selector, resultproc, userDataPtr) \ (*(userRoutine))((selector), (resultproc), (userDataPtr)) #define CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultproc, userDataPtr) \ (*(userRoutine))((selector), (addr), (rtnStruct), (resultproc), (userDataPtr)) #define CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userDataPtr) \ (*(userRoutine))((selector), (hostName), (returnRecPtr), (resultProc), (userDataPtr)) #define CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userDataPtr) \ (*(userRoutine))((selector), (hostName), (returnRecPtr), (resultProc), (userDataPtr)) #endif #if PRAGMA_IMPORT_SUPPORTED #pragma import off #endif #if STRUCTALIGNMENTSUPPORTED #pragma options align=reset #endif #ifdef __cplusplus } #endif #endif /* __ADDRESSXLATION__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SocketPlugin/68K/MacTCP.h ================================================ /* File: MacTCP.h Contains: TCP Manager Interfaces. Version: Technology: MacTCP 2.0.6 Package: Universal Interfaces 2.11 in MPW Prerelease on ETO #17 Copyright: 1984-1995 by Apple Computer, Inc. All rights reserved. Bugs?: If you find a problem with this file, use the Apple Bug Reporter stack. Include the file and version information (from above) in the problem description and send to: Internet: apple.bugs@applelink.apple.com AppleLink: APPLE.BUGS */ #ifndef __MACTCP__ #define __MACTCP__ #ifndef __TYPES__ #include #endif /* #include */ #ifndef __APPLETALK__ #include #endif /* #include */ /* #include */ /* #include */ #ifdef __cplusplus extern "C" { #endif #if PRAGMA_ALIGN_SUPPORTED #pragma options align=mac68k #endif #if PRAGMA_IMPORT_SUPPORTED #pragma import on #endif /* Developer Notes: 0. This MacTCP header replaces what used to be defined in the following header files MacTCPCommonTypes.h GetMyIPAddr.h MiscIPPB.h TCPPB.h UDPPB.h When the various control calls are made to the ip driver, you must set up a NewRoutineDescriptor for every non-nil completion routine and/or notifyProc parameter. Otherwise, the 68K driver code, will not correctly call your routine. 1. For ipctlGetAddr Control calls, use NewGetIPIOCompletionProc to set up a GetIPIOCompletionUPP universal procptr to pass as the ioCompletion parameter. 2. For the ipctlEchoICMP and ipctlLAPStats Control calls, use NewIPIOCompletion to set up a IPIOCompletionUPP universal procptr to pass in the ioCompletion field of the parameter block. 3. For TCPCreatePB Control calls, use NewTCPNotifyProc to set up a TCPNotifyUPP universal procptr to pass in the notifyProc field of the parameter block 4. For all of the TCP Control calls using the TCPiopb parameter block, use NewTCPIOCompletionProc to set up a TCPIOCompletionUPP universal procptr to pass in the ioCompletion field of the paramter block. 5. For UDBCreatePB Control calls, use NewUDPNotifyProc to set up a UDPNotifyUPP universal procptr to pass in the notifyProc field of the parameter block 6. For all of the UDP Control calls using the UDPiopb parameter block, use NewUDPIOCompletionProc to set up a UDPIOCompletionUPP universal procptr to pass in the ioCompletion field of the paramter block. 7. For all calls implementing a notifyProc or ioCompletion routine which was set up using a NewTCPRoutineProc call, do not call DisposeRoutineSDescriptor on the universal procptr until after the completion or notify proc has completed. */ /* MacTCP return Codes in the range -23000 through -23049 */ enum { inProgress = 1, /* I/O in progress */ ipBadLapErr = -23000, /* bad network configuration */ ipBadCnfgErr = -23001, /* bad IP configuration error */ ipNoCnfgErr = -23002, /* missing IP or LAP configuration error */ ipLoadErr = -23003, /* error in MacTCP load */ ipBadAddr = -23004, /* error in getting address */ connectionClosing = -23005, /* connection is closing */ invalidLength = -23006, connectionExists = -23007, /* request conflicts with existing connection */ connectionDoesntExist = -23008, /* connection does not exist */ insufficientResources = -23009, /* insufficient resources to perform request */ invalidStreamPtr = -23010, streamAlreadyOpen = -23011, connectionTerminated = -23012, invalidBufPtr = -23013, invalidRDS = -23014, invalidWDS = -23014, openFailed = -23015, commandTimeout = -23016, duplicateSocket = -23017 }; /* Error codes from internal IP functions */ enum { ipDontFragErr = -23032, /* Packet too large to send w/o fragmenting */ ipDestDeadErr = -23033, /* destination not responding */ icmpEchoTimeoutErr = -23035, /* ICMP echo timed-out */ ipNoFragMemErr = -23036, /* no memory to send fragmented pkt */ ipRouteErr = -23037, /* can't route packet off-net */ nameSyntaxErr = -23041, cacheFault = -23042, noResultProc = -23043, noNameServer = -23044, authNameErr = -23045, noAnsErr = -23046, dnrErr = -23047, outOfMemory = -23048 }; enum { BYTES_16WORD = 2, /* bytes per = 16, bit ip word */ BYTES_32WORD = 4, /* bytes per = 32, bit ip word */ BYTES_64WORD = 8 /* bytes per = 64, bit ip word */ }; /* 8-bit quantity */ typedef UInt8 b_8; /* 16-bit quantity */ typedef UInt16 b_16; /* 32-bit quantity */ typedef UInt32 b_32; /* IP address is 32-bits */ typedef b_32 ip_addr; struct ip_addrbytes { union { b_32 addr; UInt8 byte[4]; } a; }; typedef struct ip_addrbytes ip_addrbytes; struct wdsEntry { unsigned short length; /* length of buffer */ Ptr ptr; /* pointer to buffer */ }; typedef struct wdsEntry wdsEntry; struct rdsEntry { unsigned short length; /* length of buffer */ Ptr ptr; /* pointer to buffer */ }; typedef struct rdsEntry rdsEntry; typedef unsigned long BufferPtr; typedef unsigned long StreamPtr; enum { netUnreach = 0, hostUnreach = 1, protocolUnreach = 2, portUnreach = 3, fragReqd = 4, sourceRouteFailed = 5, timeExceeded = 6, parmProblem = 7, missingOption = 8, lastICMPMsgType = 32767 }; typedef unsigned short ICMPMsgType; typedef b_16 ip_port; struct ICMPReport { StreamPtr streamPtr; ip_addr localHost; ip_port localPort; ip_addr remoteHost; ip_port remotePort; short reportType; unsigned short optionalAddlInfo; unsigned long optionalAddlInfoPtr; }; typedef struct ICMPReport ICMPReport; /* csCode to get our IP address */ enum { ipctlGetAddr = 15 }; typedef void (*GetIPIOCompletionProcPtr)(struct GetAddrParamBlock *iopb); #if GENERATINGCFM typedef UniversalProcPtr GetIPIOCompletionUPP; #else typedef GetIPIOCompletionProcPtr GetIPIOCompletionUPP; #endif #define GetIPParamBlockHeader \ struct QElem* qLink; \ short qType; \ short ioTrap; \ Ptr ioCmdAddr; \ GetIPIOCompletionUPP ioCompletion; \ OSErr ioResult; \ StringPtr ioNamePtr; \ short ioVRefNum; \ short ioCRefNum; \ short csCode struct GetAddrParamBlock { struct QElem *qLink; short qType; short ioTrap; Ptr ioCmdAddr; GetIPIOCompletionUPP ioCompletion; OSErr ioResult; StringPtr ioNamePtr; short ioVRefNum; short ioCRefNum; short csCode; /* standard I/O header */ ip_addr ourAddress; /* our IP address */ long ourNetMask; /* our IP net mask */ }; typedef struct GetAddrParamBlock GetAddrParamBlock; /* control codes */ enum { ipctlEchoICMP = 17, /* send icmp echo */ ipctlLAPStats = 19 /* get lap stats */ }; typedef void (*IPIOCompletionProcPtr)(struct ICMPParamBlock *iopb); #if GENERATINGCFM typedef UniversalProcPtr IPIOCompletionUPP; #else typedef IPIOCompletionProcPtr IPIOCompletionUPP; #endif #define IPParamBlockHeader \ struct QElem* qLink; \ short qType; \ short ioTrap; \ Ptr ioCmdAddr; \ IPIOCompletionUPP ioCompletion; \ OSErr ioResult; \ StringPtr ioNamePtr; \ short ioVRefNum; \ short ioCRefNum; \ short csCode struct ICMPParamBlock { struct QElem *qLink; short qType; short ioTrap; Ptr ioCmdAddr; IPIOCompletionUPP ioCompletion; OSErr ioResult; StringPtr ioNamePtr; short ioVRefNum; short ioCRefNum; short csCode; /* standard I/O header */ short params[11]; struct { unsigned long echoRequestOut; /* time in ticks of when the echo request went out */ unsigned long echoReplyIn; /* time in ticks of when the reply was received */ struct rdsEntry echoedData; /* data received in responce */ Ptr options; unsigned long userDataPtr; } icmpEchoInfo; }; typedef pascal void (*ICMPEchoNotifyProcPtr)(struct ICMPParamBlock *iopb); #if GENERATINGCFM typedef UniversalProcPtr ICMPEchoNotifyUPP; #else typedef ICMPEchoNotifyProcPtr ICMPEchoNotifyUPP; #endif struct IPParamBlock { struct QElem *qLink; short qType; short ioTrap; Ptr ioCmdAddr; IPIOCompletionUPP ioCompletion; OSErr ioResult; StringPtr ioNamePtr; short ioVRefNum; short ioCRefNum; short csCode; /* standard I/O header */ union { struct { ip_addr dest; /* echo to IP address */ wdsEntry data; short timeout; Ptr options; unsigned short optLength; ICMPEchoNotifyUPP icmpCompletion; unsigned long userDataPtr; } IPEchoPB; struct { struct LAPStats *lapStatsPtr; } LAPStatsPB; } csParam; }; union LAPStatsAddrXlation { struct arp_entry *arp_table; struct nbp_entry *nbp_table; }; struct LAPStats { short ifType; char *ifString; short ifMaxMTU; long ifSpeed; short ifPhyAddrLength; char *ifPhysicalAddress; union LAPStatsAddrXlation AddrXlation; short slotNumber; }; typedef struct LAPStats LAPStats; struct nbp_entry { ip_addr ip_address; /* IP address */ AddrBlock at_address; /* matching AppleTalk address */ Boolean gateway; /* TRUE if entry for a gateway */ Boolean valid; /* TRUE if LAP address is valid */ Boolean probing; /* TRUE if NBP lookup pending */ SInt8 afiller; /* Filler for proper byte alignment */ long age; /* ticks since cache entry verified */ long access; /* ticks since last access */ SInt8 filler[116]; /* for internal use only !!! */ }; struct Enet_addr { b_16 en_hi; b_32 en_lo; }; typedef struct Enet_addr Enet_addr; struct arp_entry { short age; /* cache aging field */ b_16 protocol; /* Protocol type */ ip_addr ip_address; /* IP address */ Enet_addr en_address; /* matching Ethernet address */ }; typedef struct arp_entry arp_entry; /* number of ARP table entries */ enum { ARP_TABLE_SIZE = 20 }; enum { NBP_TABLE_SIZE = 20, /* number of NBP table entries */ NBP_MAX_NAME_SIZE = 16 + 10 + 2 }; /* Command codes */ enum { TCPCreate = 30, TCPPassiveOpen = 31, TCPActiveOpen = 32, TCPSend = 34, TCPNoCopyRcv = 35, TCPRcvBfrReturn = 36, TCPRcv = 37, TCPClose = 38, TCPAbort = 39, TCPStatus = 40, TCPExtendedStat = 41, TCPRelease = 42, TCPGlobalInfo = 43, TCPCtlMax = 49 }; enum { TCPClosing = 1, TCPULPTimeout = 2, TCPTerminate = 3, TCPDataArrival = 4, TCPUrgent = 5, TCPICMPReceived = 6, lastEvent = 32767 }; typedef unsigned short TCPEventCode; enum { TCPRemoteAbort = 2, TCPNetworkFailure = 3, TCPSecPrecMismatch = 4, TCPULPTimeoutTerminate = 5, TCPULPAbort = 6, TCPULPClose = 7, TCPServiceError = 8, lastReason = 32767 }; typedef unsigned short TCPTerminationReason; typedef pascal void (*TCPNotifyProcPtr)(StreamPtr tcpStream, unsigned short eventCode, Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg); #if GENERATINGCFM typedef UniversalProcPtr TCPNotifyUPP; #else typedef TCPNotifyProcPtr TCPNotifyUPP; #endif typedef unsigned short tcp_port; /* ValidityFlags */ enum { timeoutValue = 0x80, timeoutAction = 0x40, typeOfService = 0x20, precedence = 0x10 }; /* TOSFlags */ enum { lowDelay = 0x01, throughPut = 0x02, reliability = 0x04 }; struct TCPCreatePB { Ptr rcvBuff; unsigned long rcvBuffLen; TCPNotifyUPP notifyProc; Ptr userDataPtr; }; typedef struct TCPCreatePB TCPCreatePB; struct TCPOpenPB { SInt8 ulpTimeoutValue; SInt8 ulpTimeoutAction; SInt8 validityFlags; SInt8 commandTimeoutValue; ip_addr remoteHost; tcp_port remotePort; ip_addr localHost; tcp_port localPort; SInt8 tosFlags; SInt8 precedence; Boolean dontFrag; SInt8 timeToLive; SInt8 security; SInt8 optionCnt; SInt8 options[40]; Ptr userDataPtr; }; typedef struct TCPOpenPB TCPOpenPB; struct TCPSendPB { SInt8 ulpTimeoutValue; SInt8 ulpTimeoutAction; SInt8 validityFlags; Boolean pushFlag; Boolean urgentFlag; SInt8 filler; /* Filler for proper byte alignment */ Ptr wdsPtr; unsigned long sendFree; unsigned short sendLength; Ptr userDataPtr; }; typedef struct TCPSendPB TCPSendPB; /* for receive and return rcv buff calls */ /* Note: the filler in the following structure is in a different location than */ /* that specified in the Programmer's Guide. */ struct TCPReceivePB { SInt8 commandTimeoutValue; Boolean markFlag; Boolean urgentFlag; SInt8 filler; /* Filler for proper byte alignment */ Ptr rcvBuff; unsigned short rcvBuffLen; Ptr rdsPtr; unsigned short rdsLength; unsigned short secondTimeStamp; Ptr userDataPtr; }; typedef struct TCPReceivePB TCPReceivePB; struct TCPClosePB { SInt8 ulpTimeoutValue; SInt8 ulpTimeoutAction; SInt8 validityFlags; SInt8 filler; /* Filler for proper byte alignment */ Ptr userDataPtr; }; typedef struct TCPClosePB TCPClosePB; struct HistoBucket { unsigned short value; unsigned long counter; }; typedef struct HistoBucket HistoBucket; enum { NumOfHistoBuckets = 7 }; struct TCPConnectionStats { unsigned long dataPktsRcvd; unsigned long dataPktsSent; unsigned long dataPktsResent; unsigned long bytesRcvd; unsigned long bytesRcvdDup; unsigned long bytesRcvdPastWindow; unsigned long bytesSent; unsigned long bytesResent; unsigned short numHistoBuckets; struct HistoBucket sentSizeHisto[NumOfHistoBuckets]; unsigned short lastRTT; unsigned short tmrSRTT; unsigned short rttVariance; unsigned short tmrRTO; SInt8 sendTries; SInt8 sourchQuenchRcvd; }; typedef struct TCPConnectionStats TCPConnectionStats; struct TCPStatusPB { SInt8 ulpTimeoutValue; SInt8 ulpTimeoutAction; long unused; ip_addr remoteHost; tcp_port remotePort; ip_addr localHost; tcp_port localPort; SInt8 tosFlags; SInt8 precedence; SInt8 connectionState; SInt8 filler; /* Filler for proper byte alignment */ unsigned short sendWindow; unsigned short rcvWindow; unsigned short amtUnackedData; unsigned short amtUnreadData; Ptr securityLevelPtr; unsigned long sendUnacked; unsigned long sendNext; unsigned long congestionWindow; unsigned long rcvNext; unsigned long srtt; unsigned long lastRTT; unsigned long sendMaxSegSize; struct TCPConnectionStats *connStatPtr; Ptr userDataPtr; }; typedef struct TCPStatusPB TCPStatusPB; struct TCPAbortPB { Ptr userDataPtr; }; typedef struct TCPAbortPB TCPAbortPB; struct TCPParam { unsigned long tcpRtoA; unsigned long tcpRtoMin; unsigned long tcpRtoMax; unsigned long tcpMaxSegSize; unsigned long tcpMaxConn; unsigned long tcpMaxWindow; }; typedef struct TCPParam TCPParam; struct TCPStats { unsigned long tcpConnAttempts; unsigned long tcpConnOpened; unsigned long tcpConnAccepted; unsigned long tcpConnClosed; unsigned long tcpConnAborted; unsigned long tcpOctetsIn; unsigned long tcpOctetsOut; unsigned long tcpOctetsInDup; unsigned long tcpOctetsRetrans; unsigned long tcpInputPkts; unsigned long tcpOutputPkts; unsigned long tcpDupPkts; unsigned long tcpRetransPkts; }; typedef struct TCPStats TCPStats; typedef StreamPtr *StreamPPtr; struct TCPGlobalInfoPB { struct TCPParam *tcpParamPtr; struct TCPStats *tcpStatsPtr; StreamPPtr tcpCDBTable[1]; Ptr userDataPtr; unsigned short maxTCPConnections; }; typedef struct TCPGlobalInfoPB TCPGlobalInfoPB; typedef void (*TCPIOCompletionProcPtr)(struct TCPiopb *iopb); #if GENERATINGCFM typedef UniversalProcPtr TCPIOCompletionUPP; #else typedef TCPIOCompletionProcPtr TCPIOCompletionUPP; #endif struct TCPiopb { SInt8 fill12[12]; TCPIOCompletionUPP ioCompletion; short ioResult; Ptr ioNamePtr; short ioVRefNum; short ioCRefNum; short csCode; StreamPtr tcpStream; union { struct TCPCreatePB create; struct TCPOpenPB open; struct TCPSendPB send; struct TCPReceivePB receive; struct TCPClosePB close; struct TCPAbortPB abort; struct TCPStatusPB status; struct TCPGlobalInfoPB globalInfo; } csParam; }; typedef struct TCPiopb TCPiopb; enum { UDPCreate = 20, UDPRead = 21, UDPBfrReturn = 22, UDPWrite = 23, UDPRelease = 24, UDPMaxMTUSize = 25, UDPStatus = 26, UDPMultiCreate = 27, UDPMultiSend = 28, UDPMultiRead = 29, UDPCtlMax = 29 }; enum { UDPDataArrival = 1, UDPICMPReceived = 2, lastUDPEvent = 32767 }; typedef unsigned short UDPEventCode; typedef pascal void (*UDPNotifyProcPtr)(StreamPtr udpStream, unsigned short eventCode, Ptr userDataPtr, struct ICMPReport *icmpMsg); #if GENERATINGCFM typedef UniversalProcPtr UDPNotifyUPP; #else typedef UDPNotifyProcPtr UDPNotifyUPP; #endif typedef unsigned short udp_port; /* for create and release calls */ struct UDPCreatePB { Ptr rcvBuff; unsigned long rcvBuffLen; UDPNotifyUPP notifyProc; unsigned short localPort; Ptr userDataPtr; udp_port endingPort; }; typedef struct UDPCreatePB UDPCreatePB; struct UDPSendPB { unsigned short reserved; ip_addr remoteHost; udp_port remotePort; Ptr wdsPtr; Boolean checkSum; SInt8 filler; /* Filler for proper byte alignment */ unsigned short sendLength; Ptr userDataPtr; udp_port localPort; }; typedef struct UDPSendPB UDPSendPB; /* for receive and buffer return calls */ struct UDPReceivePB { unsigned short timeOut; ip_addr remoteHost; udp_port remotePort; Ptr rcvBuff; unsigned short rcvBuffLen; unsigned short secondTimeStamp; Ptr userDataPtr; ip_addr destHost; /* only for use with multi rcv */ udp_port destPort; /* only for use with multi rcv */ }; typedef struct UDPReceivePB UDPReceivePB; struct UDPMTUPB { unsigned short mtuSize; ip_addr remoteHost; Ptr userDataPtr; }; typedef struct UDPMTUPB UDPMTUPB; typedef void (*UDPIOCompletionProcPtr)(struct UDPiopb *iopb); #if GENERATINGCFM typedef UniversalProcPtr UDPIOCompletionUPP; #else typedef UDPIOCompletionProcPtr UDPIOCompletionUPP; #endif struct UDPiopb { SInt8 fill12[12]; UDPIOCompletionUPP ioCompletion; short ioResult; Ptr ioNamePtr; short ioVRefNum; short ioCRefNum; short csCode; StreamPtr udpStream; union { struct UDPCreatePB create; struct UDPSendPB send; struct UDPReceivePB receive; struct UDPMTUPB mtu; } csParam; }; typedef struct UDPiopb UDPiopb; #if GENERATINGCFM #else #endif enum { uppGetIPIOCompletionProcInfo = kCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct GetAddrParamBlock*))), uppIPIOCompletionProcInfo = kCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct ICMPParamBlock*))), uppICMPEchoNotifyProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct ICMPParamBlock*))), uppTCPNotifyProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(StreamPtr))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned short))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(unsigned short))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(struct ICMPReport*))), uppTCPIOCompletionProcInfo = kCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct TCPiopb*))), uppUDPNotifyProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(StreamPtr))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned short))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Ptr))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(struct ICMPReport*))), uppUDPIOCompletionProcInfo = kCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct UDPiopb*))) }; #if GENERATINGCFM #define NewGetIPIOCompletionProc(userRoutine) \ (GetIPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppGetIPIOCompletionProcInfo, GetCurrentArchitecture()) #define NewIPIOCompletionProc(userRoutine) \ (IPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppIPIOCompletionProcInfo, GetCurrentArchitecture()) #define NewICMPEchoNotifyProc(userRoutine) \ (ICMPEchoNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppICMPEchoNotifyProcInfo, GetCurrentArchitecture()) #define NewTCPNotifyProc(userRoutine) \ (TCPNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppTCPNotifyProcInfo, GetCurrentArchitecture()) #define NewTCPIOCompletionProc(userRoutine) \ (TCPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppTCPIOCompletionProcInfo, GetCurrentArchitecture()) #define NewUDPNotifyProc(userRoutine) \ (UDPNotifyUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUDPNotifyProcInfo, GetCurrentArchitecture()) #define NewUDPIOCompletionProc(userRoutine) \ (UDPIOCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUDPIOCompletionProcInfo, GetCurrentArchitecture()) #else #define NewGetIPIOCompletionProc(userRoutine) \ ((GetIPIOCompletionUPP) (userRoutine)) #define NewIPIOCompletionProc(userRoutine) \ ((IPIOCompletionUPP) (userRoutine)) #define NewICMPEchoNotifyProc(userRoutine) \ ((ICMPEchoNotifyUPP) (userRoutine)) #define NewTCPNotifyProc(userRoutine) \ ((TCPNotifyUPP) (userRoutine)) #define NewTCPIOCompletionProc(userRoutine) \ ((TCPIOCompletionUPP) (userRoutine)) #define NewUDPNotifyProc(userRoutine) \ ((UDPNotifyUPP) (userRoutine)) #define NewUDPIOCompletionProc(userRoutine) \ ((UDPIOCompletionUPP) (userRoutine)) #endif #if GENERATINGCFM #define CallGetIPIOCompletionProc(userRoutine, iopb) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppGetIPIOCompletionProcInfo, (iopb)) #define CallIPIOCompletionProc(userRoutine, iopb) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppIPIOCompletionProcInfo, (iopb)) #define CallICMPEchoNotifyProc(userRoutine, iopb) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppICMPEchoNotifyProcInfo, (iopb)) #define CallTCPNotifyProc(userRoutine, tcpStream, eventCode, userDataPtr, terminReason, icmpMsg) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppTCPNotifyProcInfo, (tcpStream), (eventCode), (userDataPtr), (terminReason), (icmpMsg)) #define CallTCPIOCompletionProc(userRoutine, iopb) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppTCPIOCompletionProcInfo, (iopb)) #define CallUDPNotifyProc(userRoutine, udpStream, eventCode, userDataPtr, icmpMsg) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppUDPNotifyProcInfo, (udpStream), (eventCode), (userDataPtr), (icmpMsg)) #define CallUDPIOCompletionProc(userRoutine, iopb) \ CallUniversalProc((UniversalProcPtr)(userRoutine), uppUDPIOCompletionProcInfo, (iopb)) #else #define CallGetIPIOCompletionProc(userRoutine, iopb) \ (*(userRoutine))((iopb)) #define CallIPIOCompletionProc(userRoutine, iopb) \ (*(userRoutine))((iopb)) #define CallICMPEchoNotifyProc(userRoutine, iopb) \ (*(userRoutine))((iopb)) #define CallTCPNotifyProc(userRoutine, tcpStream, eventCode, userDataPtr, terminReason, icmpMsg) \ (*(userRoutine))((tcpStream), (eventCode), (userDataPtr), (terminReason), (icmpMsg)) #define CallTCPIOCompletionProc(userRoutine, iopb) \ (*(userRoutine))((iopb)) #define CallUDPNotifyProc(userRoutine, udpStream, eventCode, userDataPtr, icmpMsg) \ (*(userRoutine))((udpStream), (eventCode), (userDataPtr), (icmpMsg)) #define CallUDPIOCompletionProc(userRoutine, iopb) \ (*(userRoutine))((iopb)) #endif #if PRAGMA_IMPORT_SUPPORTED #pragma import off #endif #if PRAGMA_ALIGN_SUPPORTED #pragma options align=reset #endif #ifdef __cplusplus } #endif #endif /* __MACTCP__ */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SocketPlugin/68K/dnr.c ================================================ /* File: DNR.c Contains: DNR library for MPW Copyright: 1989-1995 by Apple Computer, Inc., all rights reserved Version: Technology: Networking Package: Use with MacTCP 2.0.6 and the Universal Interfaces 2.1b1 Change History (most recent first): <3> 1/23/95 rrk implemented use of universal procptrs Changed selector name HINFO to HXINFO due to conflict of name in MacTCP header Removed use of TrapAvailable and exchanged for the TrapExists call. Changed symbol codeHandle to gDNRCodeHndl Changed symbol dnr to gDNRCodePtr Further modifications by Steve Falkenburg, Apple MacDTS 8/91 Modifications by Jim Matthews, Dartmouth College, 5/91 */ #include "sq.h" #ifndef __OSUTILS__ #include #endif #ifndef __ERRORS__ #include #endif #ifndef __FILES__ #include #endif #ifndef __RESOURCES__ #include #endif #ifndef __MEMORY__ #include #endif #ifndef __TRAPS__ #include #endif #ifndef __GESTALT__ #include #endif #ifndef __FOLDERS__ #include #endif #ifndef __TOOLUTILS__ #include #endif #ifndef __MACTCP__ #include "MacTCP.h" #endif #ifndef __ADDRESSXLATION__ #include "AddressXlation.h" #endif // think C compatibility stuff #ifndef _GestaltDispatch #define _GestaltDispatch _Gestalt #endif /* RRK Modification 1/95 - commenting out the following defines as they are defined in the DNRCalls.h header file */ void GetSystemFolder(short *vRefNumP, long *dirIDP); void GetCPanelFolder(short *vRefNumP, long *dirIDP); short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID); short OpenOurRF(void); short NumToolboxTraps(void); TrapType GetTrapType(short theTrap); Boolean TrapExists(short theTrap); static Handle gDNRCodeHndl = nil; static ProcPtr gDNRCodePtr = nil; /* Check the bits of a trap number to determine its type. */ /* InitGraf is always implemented (trap $A86E). If the trap table is big ** enough, trap $AA6E will always point to either Unimplemented or some other ** trap, but will never be the same as InitGraf. Thus, you can check the size ** of the trap table by asking if the address of trap $A86E is the same as ** $AA6E. */ #pragma segment UtilMain short NumToolboxTraps(void) { if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap)) return(0x200); else return(0x400); } #pragma segment UtilMain TrapType GetTrapType(short theTrap) { /* OS traps start with A0, Tool with A8 or AA. */ if ((theTrap & 0x0800) == 0) /* per D.A. */ return(OSTrap); else return(ToolTrap); } Boolean TrapExists(short theTrap) { TrapType theTrapType; theTrapType = GetTrapType(theTrap); if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps())) theTrap = _Unimplemented; return(NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap, theTrapType)); } void GetSystemFolder(short *vRefNumP, long *dirIDP) { SysEnvRec info; long wdProcID; SysEnvirons(1, &info); if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) { *vRefNumP = 0; *dirIDP = 0; } } void GetCPanelFolder(short *vRefNumP, long *dirIDP) { Boolean hasFolderMgr = false; long feature; if (TrapExists(_GestaltDispatch)) if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true; if (!hasFolderMgr) { GetSystemFolder(vRefNumP, dirIDP); return; } else { if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) { *vRefNumP = 0; *dirIDP = 0; } } } /* SearchFolderForDNRP is called to search a folder for files that might contain the 'dnrp' resource */ short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID) { HParamBlockRec fi; Str255 filename; short refnum; fi.fileParam.ioCompletion = nil; fi.fileParam.ioNamePtr = filename; fi.fileParam.ioVRefNum = vRefNum; fi.fileParam.ioDirID = dirID; fi.fileParam.ioFDirIndex = 1; while (PBHGetFInfo(&fi, false) == noErr) { /* scan system folder for driver resource files of specific type & creator */ if (fi.fileParam.ioFlFndrInfo.fdType == targetType && fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) { /* found the MacTCP driver file? */ refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm); if (GetIndResource('dnrp', 1) == NULL) CloseResFile(refnum); else return refnum; } /* check next file in system folder */ fi.fileParam.ioFDirIndex++; fi.fileParam.ioDirID = dirID; /* PBHGetFInfo() clobbers ioDirID */ } return(-1); } /* OpenOurRF is called to open the MacTCP driver resources */ short OpenOurRF(void) { short refnum; short vRefNum; long dirID; /* first search Control Panels for MacTCP 1.1 */ GetCPanelFolder(&vRefNum, &dirID); refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID); if (refnum != -1) return(refnum); /* next search System Folder for MacTCP 1.0.x */ GetSystemFolder(&vRefNum, &dirID); refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID); if (refnum != -1) return(refnum); /* finally, search Control Panels for MacTCP 1.0.x */ GetCPanelFolder(&vRefNum, &dirID); refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID); if (refnum != -1) return(refnum); return -1; } OSErr OpenResolver(char *fileName) { short refnum; OSErr rc; if (gDNRCodePtr != nil) /* resolver already loaded in */ return(noErr); /* open the MacTCP driver to get DNR resources. Search for it based on creator & type rather than simply file name */ refnum = OpenOurRF(); /* ignore failures since the resource may have been installed in the System file if running on a Mac 512Ke */ /* load in the DNR resource package */ gDNRCodeHndl = GetIndResource('dnrp', 1); if (gDNRCodeHndl == nil) { /* can't open DNR */ return(ResError()); } DetachResource(gDNRCodeHndl); if (refnum != -1) { CloseResFile(refnum); } /* lock the DNR resource since it cannot be reloated while opened */ MoveHHi(gDNRCodeHndl); HLock(gDNRCodeHndl); gDNRCodePtr = (ProcPtr)*gDNRCodeHndl; /* call open resolver */ // RRK modification 1/95 use CallOpenResolverProc define to call UPP rc = CallOpenResolverProc(gDNRCodePtr, OPENRESOLVER, fileName); if (rc != noErr) { /* problem with open resolver, flush it */ HUnlock(gDNRCodeHndl); DisposeHandle(gDNRCodeHndl); gDNRCodePtr = nil; } return(rc); } OSErr CloseResolver(void) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); /* call close resolver */ // RRK modification 1/95 use CallCloseResolverProc define to call UPP // (void) (*dnr)(CLOSERESOLVER); CallCloseResolverProc(gDNRCodePtr, CLOSERESOLVER); /* release the DNR resource package */ HUnlock(gDNRCodeHndl); DisposeHandle(gDNRCodeHndl); gDNRCodePtr = nil; return(noErr); } // RRK modification 1/95 declare parameter resultProc to be of type // ResultProcUPP instead of a long OSErr StrToAddr(char *hostName, struct hostInfo *rtnStruct, ResultUPP resultproc, Ptr userDataPtr) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallStrToAddrProc define to call UPP // return((*dnr)(STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr)); return (CallStrToAddrProc(gDNRCodePtr, STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr)); } OSErr AddrToStr(unsigned long addr, char *addrStr) { OSErr err; if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallAddrToStrProc define to call UPP // (*dnr)(ADDRTOSTR, addr, addrStr); err = CallAddrToStrProc(gDNRCodePtr, ADDRTOSTR, addr, addrStr); return(noErr); } OSErr EnumCache(EnumResultUPP resultproc, Ptr userDataPtr) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallEnumCacheProc define to call UPP // return((*dnr)(ENUMCACHE, resultproc, userDataPtr)); return (CallEnumCacheProc(gDNRCodePtr, ENUMCACHE, resultproc, userDataPtr)); } OSErr AddrToName(unsigned long addr, struct hostInfo *rtnStruct, ResultUPP resultproc, Ptr userDataPtr) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallAddrToNameProc define to call UPP // return((*dnr)(ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr)); return(CallAddrToNameProc(gDNRCodePtr, ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr)); } extern OSErr HInfo(char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallHInfoProc define to call UPP // return((*dnr)(HINFO, hostName, returnRecPtr, resultProc, userDataPtr)); return(CallHInfoProc(gDNRCodePtr, HXINFO, hostName, returnRecPtr, resultProc, userDataPtr)); } extern OSErr MXInfo(char *hostName, struct returnRec *returnRecPtr, ResultProc2UPP resultProc, Ptr userDataPtr) { if (gDNRCodePtr == nil) /* resolver not loaded error */ return(notOpenErr); // RRK modification 1/95 use CallHInfoProc define to call UPP // return((*dnr)(MXINFO, hostName, returnRecPtr, resultProc, userDataPtr)); return(CallMXInfoProc(gDNRCodePtr, MXINFO, hostName, returnRecPtr, resultProc, userDataPtr)); } /* removed ; (causes syntax err in Think C 5.0 */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SocketPlugin/68K/sqMacNetworkNOMACTCP.c ================================================ #include #if 1 #include #include #include #include #include #include #include #if !TARGET_API_MAC_CARBON #ifndef NewOTNotifyUPP typedef struct OTConfiguration* OTConfigurationRef; #define OTNotifyUPP OTNotifyProcPtr #define NewOTNotifyUPP(userRoutine) userRoutine #define DisposeOTNotifyUPP(userRoutine) #endif #endif #include "sq.h" #include "SocketPlugin.h" //#define OTSERVER /* May 1st 2000 An Open Transport 2.0 version of source code for TCP/IP & UDP support Some of this the code was descended from Apple sample source written by: Eric Okholm However getting it to work was done by John M Mcintosh of Corporate Smalltalk Consulting Ltd johnmci@smalltalkconsulting.com http://www.smalltalkconsulting.com In May of 2000 under contract to Disney Some of the original source code was written by John Maloney of Disney thoughout the 1990's The basic intent was to make the code fully interrupt driven No limits.... Well maybe we throttle read buffers to some parcel of memory to prevent us from using all the memory on the box. Sends depend on lowerlayer buffering/flow control. Testing from a 500Mhz PowerBook showed we could saturate a 100MB ethernet when sending data oneway. UDP and TCP/IP are all supported. Note for TCP we turn on two options IP_REUSEADDR, and IP_KEEPALIVE. We do NOT handle T_EXDATA data V1.0 May 18th 2000, JMM (TCP/IP and UDP) V1.1 May 19th 2000, JMM Cleanup V1.2 may 20th 2000, JMM UDP free buffer cleanup, relook at resolver terminate to fix crash V1.3 may 23rd 2000, JMM fix T_UDERR crash V1.3.1 may 24th 2000, JMM UDP work V1.3.2 may 25th 2000, JMM socket options work V1.3.3 may 27th 2000, JMM rewrote resolver V1.3.4 Jun 7th 2000, JMM some integration V1.3.5 Jun 9th 2000, JMM Dan Ingalls found some interesting bugs with a T_GODATA on T_CONNECT. V1.3.6 Jun 10th 2000, JMM fix a fatal but in close/close pattern I made on the 9th. V1.3.7 Aug 1st 2000, JMM Some carbon work, reviewed open non-existent port logic fix so unavailable port causes immediate failure V1.3.8 Aug 29th 2000, JMM Fix problem with recusion on make me an EP. v1.3.9 Sept 28th 2000, JMM Problem with accept somewhere (so harden code) v1.3.10 Oct 4th 2000, JMM Issue with destory and free buffers, and disconnect on read with buffer restriction v1.3.11 Nov 11th 2000, JMM extra buffer for server version v1.3.12 Jan 2001, Karl Goiser Carbon changes Notes beware semaphore's lurk for socket support. Three semaphores lives in Smalltalk, waiting for connect/disconnect/listen, sending data, and receiving data. When to tap the semaphore is based on inferences driven from the smalltalk code. We really need a call to tell us intent. waitForDisconnectUntil: via closeAndDestroy: after primSocketCloseConnection: waitForDataUntil: Usually before primitiveSocketReceiveDataBufCount: after checking SocketReceiveDataAvailable waitForSendDoneUntil: via sendData: or sendSomeData:startIndex;count: before calls to primitiveSocketSendDataBufCount waitForConnectionUntil: via waitForAcceptUntil and many places afer doing primitiveSocketConnectToPort */ /*** Socket Type Constants ***/ #define TCPSocketType 0 #define UDPSocketType 1 #define TCPListenerSocketType 2 //These are special to enable the right options for listening. Not Exposed to Smalltalk #define UDPListenerSocketType 3 //Very special not really linked to an EP structure. Not Exposed to Smalltalk /*** Resolver Status Constants ***/ #define RESOLVER_UNINITIALIZED 0 #define RESOLVER_SUCCESS 1 #define RESOLVER_BUSY 2 #define RESOLVER_ERROR 3 #define RESOLVER_NAMETOADDR 4 #define RESOLVER_ADDRTONAME 5 /*** TCP Socket Status Constants ***/ #define InvalidSocket -1 #define Unconnected 0 #define WaitingForConnection 1 #define Connected 2 #define OtherEndClosed 3 #define ThisEndClosed 4 // Overall program states enum { kProgramRunning = 1, kProgramDone = 2 }; // Bit numbers in EPInfo stateFlags fields enum { kOpenInProgressBit = 0, kUnConnected = 1, kWaitingForConnection = 2, kConnected = 3, kSendIsBlocked = 4, kOtherEndClosed = 5, kThisEndClosed = 6, kPassconBit = 7 }; // Bit numbers in EPInfo stateFlags2 fields enum { kFlushDisconnectInProgressBit = 0, kMakeEPIdle = 1, kEPIsBroken = 2, kReadFlowControl = 3, kPassconNeeded = 4, kTapSemaphore = 5, kTapSemaphoreReadData = 6, kTapSemaphoreWriteData = 7 }; // Bit numbers in EPInfo stateFlags3 fields enum { kKeepAliveOptionNeeded = 0, kSleepKilledMe = 1, kWaitingForBind = 2 }; enum { kOTVersion111 = 0x01110000, kOTVersion112 = 0x01120000, kOTVersion113 = 0x01130000, kOTVersion130 = 0x01300000 }; const kTCPKeepAliveInMinutes = 10; // 10 minutes keep alive #ifdef OTSERVER const kReadBuffersToAllocate = 256; // Memory Allocation issue how big, this means 256x mtu size * 4 But for 68K we do 1/2 size #else const kReadBuffersToAllocate = 50; // Memory Allocation issue how big, this means 50x mtu size * 4 But for 68K we do 1/2 size #endif // Endpoint Info Structure struct EPInfo { EndpointRef erf; // actual endpoint OTLink link; // link into an OT LIFO (atomic) OTLink globalLink; // link that follows all allocated EPs SInt32 outstandingSends; // number of sends outstanding OTList readBuffers; // Read buffers SInt32 bytesPendingToRead; // bytes outstanding to read SInt32 semaIndex; // semaphore index SInt32 readSemaIndex; // read semaphore SInt32 writeSemaIndex; // write semaphore SInt32 UDPMaximumSize; // max size if a UDP endpoint SInt32 lastError; // last error code UInt8 stateFlags; // various status fields UInt8 stateFlags2; // various status fields UInt8 stateFlags3; // various status fields UInt8 socketType; // type of socket, tcp, udp, or tcp/udp listener InetAddress localAddress; // local address at bind time (ignored used call to get current) InetAddress remoteAddress; // remote address at connect (ignored used call to get current) Boolean UDPMoreFlag; // UDP more of datagram flag set }; typedef struct EPInfo EPInfo; struct ReadBuffer // Structure to contain read data. { OTLink fNext; // link into an OT FIFO UInt32 readBufferSize; UInt32 readBufferOriginalSize; char * readBufferData; char * readBufferPtr; //Sliding pointer used to partial read buffer. InetAddress UDPAddress; //UDP address Boolean UDPMoreFlag; //UDP more of datagram flag set }; typedef struct ReadBuffer ReadBuffer; struct TKeepAliveOpt { UInt32 len; OTXTILevel level; OTXTIName name; UInt32 status; UInt32 tcpKeepAliveOn; UInt32 tcpKeepAliveTimer; }; typedef struct TKeepAliveOpt TKeepAliveOpt; struct TLingerOpt { UInt32 len; OTXTILevel level; OTXTIName name; UInt32 status; UInt32 tcpLingerOn; UInt32 tcpLingerTimer; }; typedef struct TLingerOpt TLingerOpt; /*** Variables ***/ extern struct VirtualMachine *interpreterProxy; EPInfo* gDNSResolver; //Our resolver SInt32 gDNSResolverStatus = RESOLVER_UNINITIALIZED; SInt32 gDNSResolverError = noErr; SInt32 gDNSResolverSemaIndex; //This gets changed at startup time. InetHostInfo gDNSHostInfo; InetDomainName gDNSAddrStr; //Length of domain names? Old code was 512, but specs say 256. InetHost gDNSAddr; SInt32 gDNSLookupType; OTConfigurationRef gCfgMastertcp = NULL; OTConfigurationRef gCfgMasterudp = NULL; OTConfigurationRef gCfgMasterListener = NULL; OTLIFO gFreeReadBuffersLIFO; // Buffers that are free to read into OTLIFO* gFreeReadBuffers = &gFreeReadBuffersLIFO; SInt32 gFreeReadBuffersCounter = 0; SInt32 gSocketsAllocated = 0; UInt32 gmtuSize = 1024; //This gets changed at startup time. SInt32 gthisNetSession = 0; //This gets changed at startup time. SInt32 gMaxConnections = 0; //This gets changed at startup time. UInt32 gOTVersion; //Gets set to OT version, to help us with special cases. SInt32 gProgramState = 0; //This gets changed at startup time. typedef struct OpaqueOTClientContextPtr* gClientContext; OTLIFO gIdleEPLIFO[3]; OTLIFO* gIdleEPs[3]; SInt32 gIdleEPCounter[3]; OTLIFO gBrokenEPLIFO; OTLIFO* gBrokenEPs = &gBrokenEPLIFO; OTLIFO gAllEPLIFO; OTLIFO* gAllEPs = &gAllEPLIFO; OTNotifyUPP DNSNotifierUPP,NotifierSocketUPP,NotifierSocketUDPUPP,NotifierSocketListenerUPP; /*** Private TCP Socket Functions ***/ /*** Private Resolver Functions ***/ static void ResolverInitialize(); static void ResolverTerminate(void); static void ResolverStart (); /*** Other Private Functions ***/ void CFMTerminate (void); static Boolean DestroyAllOpenSockets(void); static Boolean SocketValid(SocketPtr s); static Boolean PortNumberValid(InetPort port) ; static SInt32 unmapStatus(EPInfo *); static void Recycle(); static void makeEPIdle(EPInfo *epi); static void purgeReadBuffers(EPInfo *epi); static void makeEPBrokenThenIdle(EPInfo* epi,OTResult error); static void makeEPBroken(EPInfo* epi,OTResult error); static EPInfo* getOrMakeMeAnEP(UInt8 aSocketType,short counter); static Boolean makeMeAnEP(UInt8 aSocketType); static void attemptToCloseAndDeleteThisEP (EPInfo *epi); static void makeEPUnconnected(EPInfo* epi); static void SetEPLastError(EPInfo* epi,OTResult error); static void TapAllInterestedSemaphores(EPInfo *epi); int socketInit(void); int socketShutdown(void); static pascal void DNSNotifier(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocket(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocketUDP(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocketListener(void* context, OTEventCode event, OTResult result, void* cookie); static SInt32 internalSocketCreate(SocketPtr s, SInt32 netType, SInt32 socketType, SInt32 recvBufSize, SInt32 sendBufSize, SInt32 semaIndex, SInt32 readSemaIndex, SInt32 writeSemaIndex, UInt8 aExtraSocketHint); static Boolean EPOpen(EPInfo* epi); static Boolean EPClose(EPInfo*); static void DoListenAccept(EPInfo* acceptor,EPInfo* theServer); static void DoConnect(EPInfo* epi,InetHost addr, InetPort port); static void DoBind(EPInfo* epi,InetHost addr, InetPort port,UInt8 aExtraSocketHint, OTQLen queueDepth ); static UInt32 ReadData(EPInfo* epi, char* specialBuffer, UInt32 specialBufferSize); static OTResult SendData(EPInfo* epi, char* buffer, UInt32 size); static OSStatus doAbortConnection(EPInfo* epi); static void NoCopyReceiveWalkingBufferChain(EPInfo *epi,OTBufferInfo *bufferInfo); static UInt32 readBytes(EPInfo* epi,char *buf,UInt32 adjustedBufSize); static UInt32 readBytesUDP(EPInfo* epi,InetAddress *fromAddress, int *moreFlag, char *buf,UInt32 adjustedBufSize); static SInt32 lookupOptionName(EPInfo *epi, Boolean trueIfGet, char *aString, UInt32 value, SInt32 *result); static OTResult SetFourByteOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetOneByteOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetKeepAliveOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetLingerOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); // Some diagnostic routines void JMMLogMessage(Str255 input); void JMMLogMessageAndNumber(Str255 msg,long number); void JMMWriteLog(); /*** Network Functions ***/ int socketInit() { // //Don't actually do any network work until we are newworked initialized //This prevents kicking off internet dialup connections until needed // return true; } int socketShutdown() { CFMTerminate(); return true; } int sqNetworkInit(int resolverSemaIndex) { // // Initialize the network and return 0 if successful // Loads Open transport, allocates memory for read buffers and various other tasks // SInt32 i; OSStatus err = noErr; InetInterfaceInfo interfaceInformation; UInt8 aSocketType; ReadBuffer *readBufferObject; long check68KorPPC; if (gthisNetSession != 0) return 0; /* noop if network is already initialized */ #if TARGET_API_MAC_CARBON err = InitOpenTransportInContext (kInitOTForExtensionMask, &gClientContext); #else err = InitOpenTransport(); #endif if (err) return -1; err = Gestalt(gestaltOpenTptVersions, (long*) &gOTVersion); if (err || (gOTVersion < kOTVersion112)) { // Please install Open Transport 1.1.2 or later // This might change to 1.3 since tech notes talked about // previous versions having problems with acksend logic. // return -111; } err = Gestalt(gestaltSysArchitecture, (long*) &check68KorPPC); gProgramState = kProgramRunning; // //Setup the head of the idle queues // for (i=0;i<3;i++) { gIdleEPs[i] = &gIdleEPLIFO[i]; gIdleEPs[i]->fHead = NULL; gIdleEPCounter[i] = 0; } gBrokenEPs->fHead = NULL; gFreeReadBuffers->fHead = NULL; gAllEPs->fHead = NULL; gMaxConnections = 24; // Build 8 of each of listeners, tcp, udp. DNSNotifierUPP = NewOTNotifyUPP(DNSNotifier); NotifierSocketUPP = NewOTNotifyUPP(NotifierSocket); NotifierSocketUDPUPP = NewOTNotifyUPP(NotifierSocketUDP); NotifierSocketListenerUPP = NewOTNotifyUPP(NotifierSocketListener); #if TARGET_API_MAC_CARBON gDNSResolver = (EPInfo*) OTAllocMemInContext(sizeof(EPInfo), gClientContext); #else gDNSResolver = (EPInfo*) OTAllocMem(sizeof(EPInfo)); #endif if (gDNSResolver == NULL) return -1; gDNSResolverSemaIndex = resolverSemaIndex; ResolverInitialize(); /* Get MTU and default selected host address */ OTInetGetInterfaceInfo (&interfaceInformation,kDefaultInetInterface); gmtuSize = interfaceInformation.fIfMTU; // // Open endpoints // gCfgMastertcp = OTCreateConfiguration(kTCPName); if (gCfgMastertcp == NULL) return -3; gCfgMasterudp = OTCreateConfiguration(kUDPName); if (gCfgMasterudp == NULL) return -4; gCfgMasterListener = OTCreateConfiguration("tilisten, tcp"); //Note use of special tilisten logic if (gCfgMasterListener == NULL) return -5; // //Build all our EPs, lots of work happens lower down asyncronously // aSocketType = TCPSocketType; for (i = 0; i < gMaxConnections; i++) { makeMeAnEP(aSocketType); aSocketType = ++aSocketType > 2 ? TCPSocketType : aSocketType; } #ifdef OTSERVER for (i = 0; i < 256; i++) { makeMeAnEP(TCPSocketType); } #endif // //Build storage objects for read buffers //How much memory to allocate still is a mystery // for (i=0;isuccess(false); return -25; } OTMemzero(readBufferObject,sizeof(ReadBuffer)); if (gestalt68k == check68KorPPC) readBufferObject->readBufferOriginalSize = (gmtuSize > 0) ? gmtuSize*2 : 1024; else readBufferObject->readBufferOriginalSize = (gmtuSize > 0) ? gmtuSize*4 : 1024; #if TARGET_API_MAC_CARBON readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMemInContext(readBufferObject->readBufferOriginalSize, gClientContext); #else readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMem(readBufferObject->readBufferOriginalSize); #endif if ( readBufferObject->readBufferData == nil) { interpreterProxy->success(false); return -25; } OTLIFOEnqueue(gFreeReadBuffers, &readBufferObject->fNext); gFreeReadBuffersCounter++; } /* Success! Create a session ID that is unlikely to be repeated. Zero is never used for a valid session number. */ gthisNetSession = clock() + time(NULL); if (gthisNetSession == 0) gthisNetSession = 1; /* don't use 0 */ return 0; } void CFMTerminate (void) /* termination either via a CFM or Squeak call*/ { sqNetworkShutdown(); } void sqNetworkShutdown(void) { /* shut down the network */ if (gthisNetSession == 0) return; /* noop if network is already shut down */ gthisNetSession = 0; gProgramState = kProgramDone; DestroyAllOpenSockets(); #if TARGET_API_MAC_CARBON CloseOpenTransportInContext(gClientContext); #else CloseOpenTransport(); #endif } /*** Resolver Functions ***/ static void ResolverInitialize() { OSStatus err; // // Prepare to open internet services // to invoke DNR services // OTMemzero(gDNSResolver, sizeof(EPInfo)); #if TARGET_API_MAC_CARBON gDNSResolver->erf = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, gClientContext); #else gDNSResolver->erf = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err); #endif gDNSResolver->semaIndex = gDNSResolverSemaIndex; if (err != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; gDNSResolverError = err; return; } gDNSResolverStatus = RESOLVER_SUCCESS; gDNSResolverError = kOTNoError; err = OTSetAsynchronous(gDNSResolver->erf); err = OTSetNonBlocking(gDNSResolver->erf); err = OTInstallNotifier(gDNSResolver->erf, DNSNotifierUPP, gDNSResolver); } static void ResolverStart () { OSStatus err; // // Invoke DNR service Async, this meants the DNSNotifier will handle the actual // lookup and work, flags like the gDNSResolverStatus are used to indicate back // to Squeak when the work is done // if (gDNSResolver->erf == NULL) //Sleep fix, other endpoints are more explicit about this issue. ResolverInitialize(); gDNSResolverStatus = RESOLVER_BUSY; switch (gDNSLookupType) { case RESOLVER_NAMETOADDR: { err = OTInetStringToAddress((InetSvcRef)gDNSResolver->erf, gDNSAddrStr, &gDNSHostInfo); break; } case RESOLVER_ADDRTONAME: { err = OTInetAddressToName((InetSvcRef)gDNSResolver->erf, gDNSAddr, gDNSAddrStr); break; } } if (err != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; gDNSResolverError = err; } } void ResolverTerminate(void) { //JMM if the resolver is opening what happens? gDNSResolverStatus = RESOLVER_UNINITIALIZED; if (gDNSResolver->erf == NULL) return; EPClose(gDNSResolver); OTMemzero(gDNSResolver, sizeof(EPInfo)); } void sqResolverAbort(void) { // // Abort this running resolver request // if (gDNSResolverStatus == RESOLVER_BUSY) { ResolverTerminate(); ResolverInitialize(); } } void sqResolverAddrLookupResult(char *nameForAddress, int nameSize) { // // copy the name found by the last address lookup into the given string // OTMemcpy(nameForAddress, gDNSAddrStr, (UInt32) nameSize); } int sqResolverAddrLookupResultSize(void) { // // return the length of the looked up name // return (long) strlen(gDNSAddrStr); } int sqResolverError(void) { // // Return OT error number // return gDNSResolverError; } int sqResolverLocalAddress(void) { // // Watch out for dynamic changing of this information, so don't cache // InetInterfaceInfo interfaceInformation; OTInetGetInterfaceInfo (&interfaceInformation,kDefaultInetInterface); gDNSResolverStatus = RESOLVER_SUCCESS; gDNSResolverError = noErr; return (long) interfaceInformation.fAddress; } int sqResolverNameLookupResult(void) { // // Return address from last lookup // return (int) gDNSAddr; } void sqResolverStartAddrLookup(int address) { // // start process to lookup name from address // if (gDNSResolverStatus == RESOLVER_BUSY) return; gDNSAddr = (InetHost) address; gDNSLookupType = RESOLVER_ADDRTONAME; ResolverStart(); } void sqResolverStartNameLookup(char *hostName, int nameSize) { // // start process to lookup address from name // UInt32 len; if (gDNSResolverStatus == RESOLVER_BUSY) return; len = (UInt32) ((nameSize <= kMaxHostNameLen) ? nameSize : kMaxHostNameLen); //Old limit was 500 but that appeared to be wrong OTMemcpy(gDNSAddrStr, hostName, len); gDNSAddrStr[len] = '\0'; gDNSLookupType = RESOLVER_NAMETOADDR; ResolverStart(); } int sqResolverStatus(void) { // // return resolver status, this is different from resolver error code // status is the same among implementations, error is implementation dependent // return gDNSResolverStatus; } //================================ // Socket logic // void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex) { // //Old call from old image using new VM //Just make new call // sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( s, netType, socketType, recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { OSErr error; netType; recvBufSize; sendBufSize; // //Create a socket given the supplied information //We don't bind the socket to a local port until //we do the connection. This of course could change? // error = internalSocketCreate( s, netType, socketType, recvBufSize, sendBufSize, semaIndex, readSemaIndex, writeSemaIndex, (UInt8) socketType); if (error != noErr) { interpreterProxy->success(false); return; } } static SInt32 internalSocketCreate( SocketPtr s, SInt32 netType, SInt32 socketType, SInt32 recvBufSize, SInt32 sendBufSize, SInt32 semaIndex, SInt32 readSemaIndex, SInt32 writeSemaIndex, UInt8 aExtraSocketHint) { // // Internal logic to open a socket for a connection or to listen // Note how we ignore buffer sizes! // EPInfo* epi; socketType; netType; recvBufSize; sendBufSize; // //Make the socket invalid and then get an idle EP //Technically we only run out of EP when we run out of memory // s->sessionID = 0; if (gProgramState != kProgramRunning ) { interpreterProxy->success(false); return -1; } epi = getOrMakeMeAnEP(aExtraSocketHint,0); if (epi == NULL) { interpreterProxy->success(false); return -1; } epi->outstandingSends = 0; epi->bytesPendingToRead = 0; epi->semaIndex = semaIndex; epi->readSemaIndex = readSemaIndex; epi->writeSemaIndex = writeSemaIndex; epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; SetEPLastError(epi,noErr); epi->socketType = aExtraSocketHint; OTInitInetAddress(&epi->remoteAddress, 0, 0); OTInitInetAddress(&epi->localAddress, 0, 0); if (aExtraSocketHint == UDPSocketType) OTAtomicSetBit(&epi->stateFlags, kConnected); //udp is always connected else OTAtomicSetBit(&epi->stateFlags, kUnConnected); s->sessionID = gthisNetSession; s->socketType = (aExtraSocketHint == UDPSocketType) ? UDPSocketType : TCPSocketType; s->privateSocketPtr = epi; gSocketsAllocated++; return 0; } void sqSocketListenOnPort(SocketPtr s, int port) { // //Listen on port for a connection, this is not the approved method //sqSocketListenOnPortBacklogSize is the best way if you are a server //However this works ok for UDP and kinda for onetime connections in TCP // EPInfo* epi; if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == TCPSocketType) { DoBind(epi,0,(InetPort) port,TCPListenerSocketType,1); if (epi->localAddress.fPort != port) {//We die if we don't get the port we want sqSocketDestroy(s); interpreterProxy->success(false); } } else {//udp DoBind(epi,0,(InetPort) port,UDPListenerSocketType,1); } } void sqSocketListenOnPortBacklogSize(SocketPtr s, int port, int backlogSize) { EPInfo* epi; SInt32 sema,readSema,writeSema; OSErr error; // //Listen on port for a connection, this is the best method if you are //a server. Works in conjunction with accept. Shouldn't drop connections //OT's special listener logic queues up the listen requestions // if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; if (s->socketType == TCPSocketType) { epi = (EPInfo *) s->privateSocketPtr; sema = epi->semaIndex; readSema = epi->readSemaIndex; writeSema = epi->writeSemaIndex; makeEPIdle(epi); //Special case really need a listener EP, so put this EP back on the queue //This may seem odd but the epi is allocated before we know what type it is. //Would need to change Squeak to indicate type at creation! error = internalSocketCreate( s, 0, TCPSocketType, 0, 0, sema, readSema, writeSema, TCPListenerSocketType); if (error != noErr) { interpreterProxy->success(false); return; } epi = (EPInfo *) s->privateSocketPtr; DoBind(epi,0,(InetPort) port,TCPListenerSocketType,(OTQLen) backlogSize); if (epi->localAddress.fPort != port) {//The port we wanted must match, otherwise we die sqSocketDestroy(s); interpreterProxy->success(false); } } else {//udp not allowed interpreterProxy->success(false); } } void sqSocketAcceptFromRecvBytesSendBytesSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex){ // //Old call from old image using new VM //Just make new call // sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( s, serverSocket, recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { // //Accept incoming request from a listener //We take information from the listener, create a new socket //and accept the incoming call // EPInfo* epiSocket; EPInfo* epiServerSocket; Boolean doLeave; OSErr error; long count=0; if (!SocketValid(serverSocket)) return; if (serverSocket->socketType == TCPSocketType) { error = internalSocketCreate( s, 0, TCPSocketType, recvBufSize, sendBufSize, semaIndex, readSemaIndex, writeSemaIndex, TCPSocketType); if (error != noErr) { interpreterProxy->success(false); return; } epiSocket = (EPInfo *) s->privateSocketPtr; DoBind(epiSocket,0,0,TCPSocketType,0); // interrupt driven to T_TBINDCOMPLETE while (count++ < 100 && (OTAtomicTestBit(&epiSocket->stateFlags3, kWaitingForBind) == true)) { #ifndef TARGET_API_MAC_CARBON SystemTask(); #endif OTIdle(); } OTAtomicSetBit(&epiSocket->stateFlags2, kPassconNeeded); epiServerSocket = (EPInfo *) serverSocket->privateSocketPtr; OTAtomicSetBit(&epiServerSocket->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epiServerSocket->stateFlags, kUnConnected); OTAtomicClearBit(&epiServerSocket->stateFlags, kConnected); OTAtomicSetBit(&epiServerSocket->stateFlags2, kTapSemaphore); doLeave = OTEnterNotifier(epiServerSocket->erf); DoListenAccept(epiSocket,epiServerSocket); if (doLeave) OTLeaveNotifier(epiServerSocket->erf); } else { //udp interpreterProxy->success(false); } } void sqSocketConnectToPort(SocketPtr s, int addr, int port) { // //Connect this socket to the given host addr and port // EPInfo* epi; OTResult epState; if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == TCPSocketType) { DoBind(epi,(InetHost) addr,(InetPort) port,TCPSocketType,0); // interrupt driven to T_TBINDCOMPLETE which drives T_CONNECT/DoConnect } else {//udp epState = OTGetEndpointState(epi->erf); if (epState == T_UNBND) {//Bind to remote, our side gets wildcarded DoBind(epi,(InetHost) addr,(InetPort) port,UDPSocketType,0); // interrupt driven to T_TBINDCOMPLETE which drives T_CONNECT/DoConnect } else {//Already bound to a port/interface on our side OTInitInetAddress(&epi->remoteAddress, (InetPort) port, (InetHost) addr); } } } int sqSocketSendDataBufCount(SocketPtr s, int buf, int bufSize) { // // Send data really fast // We create a copy of the data and give it to OT to play with // We can get flow controlled lower down, if no flow control then we // tap the semiphore since from squeaks viewpoint data is sent, otherwise when flow control is lifted the // semaphore is tapped in the notification routine // OTResult res ; EPInfo* epi; Boolean doLeave; char * buffer; UInt32 adjustedBufSize = bufSize > 65536 ? 65536 : (UInt32) bufSize; //? Not sure if we really need to do this limiting. if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; // If send is blocked wait for unblocking if (OTAtomicTestBit(&epi->stateFlags, kSendIsBlocked)) { return 0; } if (epi->socketType == UDPSocketType) { //UDP adjust the buffer size again adjustedBufSize = (adjustedBufSize > epi->UDPMaximumSize) ? epi->UDPMaximumSize : adjustedBufSize; } #if TARGET_API_MAC_CARBON buffer = OTAllocMemInContext(adjustedBufSize, gClientContext); #else buffer = OTAllocMem(adjustedBufSize); #endif if (buffer == nil) { //Well maybe we back off and wait awhile? //If we run out of memory and stress the box, well death lurks. adjustedBufSize = 256; #if TARGET_API_MAC_CARBON buffer = OTAllocMemInContext(adjustedBufSize, gClientContext); #else buffer = OTAllocMem(adjustedBufSize); #endif if (buffer == nil) { interpreterProxy->success(false); //Death did lurk SetEPLastError(epi, -1); return -1; } } OTMemcpy(buffer,(void*) buf,adjustedBufSize); doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_GODATA res = SendData(epi,buffer,adjustedBufSize); if (doLeave) OTLeaveNotifier(epi->erf); if (res < 0 ){ SetEPLastError(epi, res); interpreterProxy->success(false); //JMM just for testing return 0; } return res; } // //New primitive for sending UDP data to a particular host/port //Avoids race conditions between binding and send in Smalltalk // int sqSockettoHostportSendDataBufCount(SocketPtr s, int address, int port, int buf, int bufSize) { sqSocketConnectToPort(s, address, port); return sqSocketSendDataBufCount(s, buf, bufSize); } // //Abort the socket // void sqSocketAbortConnection(SocketPtr s) { EPInfo* epi; OSStatus err; if (!SocketValid(s)) return; if (s->socketType == UDPSocketType) { interpreterProxy->success(false); return; } epi = (EPInfo *) s->privateSocketPtr; err = doAbortConnection(epi); } // //Acutal abort logic //We need to flush the queues //Then do a disconnect // static OSStatus doAbortConnection(EPInfo* epi) { SInt32 count = 0; OSStatus err = kOTNoError; if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) { //Do flush and wait for it to happen //Should make sync? // if (epi->outstandingSends != 0) { err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); while (count++ < 100 && (epi->outstandingSends != 0 || OTAtomicTestBit(&epi->stateFlags, kUnConnected) == false)) { OTIdle(); } } makeEPBroken(epi,0); err = OTSndDisconnect(epi->erf, NULL); } if (err != kOTNoError) return err; else return epi->lastError; } // //Socket close logic // void sqSocketCloseConnection(SocketPtr s) { EPInfo* epi; OSStatus err; OTResult epState; OTResult lookResult; if (!SocketValid(s)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == UDPSocketType) {//Handle udp and return OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); return; } OTAtomicSetBit(&epi->stateFlags, kThisEndClosed); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); // old code is sync and doesn't trigger semaphore epState = OTGetEndpointState(epi->erf); if (epState == T_UNINIT || epState == T_UNBND ) { OTAtomicSetBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); TapAllInterestedSemaphores(epi); return; } else err = OTSndOrderlyDisconnect(epi->erf); if (err == kOTNoError) { if (OTAtomicTestBit(&epi->stateFlags, kOtherEndClosed)) { OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (epi->outstandingSends != 0) doAbortConnection(epi); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); } } else {// Could get kOTLookErr with T_DISCONNECT pending lookResult = OTLook(epi->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) { err = OTRcvDisconnect(epi->erf, NULL); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (epi->outstandingSends != 0) doAbortConnection(epi); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); } else { SetEPLastError(epi,err); makeEPBroken(epi,err); TapAllInterestedSemaphores(epi); } } } // //Destroy the socket here we must ensure we cleanup and put the //socket back on the idle or broken EP queue // void sqSocketDestroy(SocketPtr s) { OTResult err; EPInfo* epi; OTResult epState; JMMWriteLog(); //Diagnostics, turned off, must fiddle recompile to turn on. if (!SocketValid(s)) { return; } epi = (EPInfo *) s->privateSocketPtr; OTAtomicSetBit(&epi->stateFlags2, kMakeEPIdle); epState = OTGetEndpointState(epi->erf); if (epState == T_UNINIT || epState == T_UNBND ) { makeEPIdle(epi); //Unbound already so make him idle. } else { if (s->socketType == UDPSocketType) err = OTUnbind(epi->erf); else err = doAbortConnection(epi); if (err != kOTNoError) {//kOTLookErr with T_DATA, book says response is to zap EP. makeEPBrokenThenIdle(epi,err); } } purgeReadBuffers(epi); //JMM Oct 4th 2000 (bug?) s->sessionID = 0; s->socketType = -1; s->privateSocketPtr = nil; gSocketsAllocated--; } // //Check to see if bytes are available // int sqSocketReceiveDataAvailable(SocketPtr s) { EPInfo* epi; static lastTickCount=0; if (!SocketValid(s)) return 0; epi = (EPInfo *) s->privateSocketPtr; if (epi->bytesPendingToRead > 0) return 1; if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) // New case if data pending but flow controlled then go get it return 1; OTAtomicSetBit(&epi->stateFlags2, kTapSemaphoreReadData); //Note how we imply there will be interest in semaphore return 0; } // //Read data into the buffer supplied // int sqSocketReceiveDataBufCount(SocketPtr s, int buf, int bufSize) { EPInfo* epi; UInt32 bytesRead = 0; Boolean doLeave; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_DATA bytesRead = readBytes(epi,(char *) buf,(UInt32) bufSize); if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) { if (bytesRead > 0) ReadData(epi,NULL,0); else bytesRead = ReadData(epi,(char *) buf,(UInt32) bufSize); //special case attempt read into squeak buffer } if (doLeave) OTLeaveNotifier(epi->erf); return (int) bytesRead; } // //New primitive to read UDP data and get data, host/port, and more flag // int sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, int buf, int bufSize, int *address, int *port, int *moreFlag) { EPInfo* epi; UInt32 bytesRead = 0; Boolean doLeave; InetAddress fromAddress; OTMemzero(&fromAddress,sizeof(InetAddress)); *address = 0; *port = 0; *moreFlag = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_DATA bytesRead = readBytesUDP(epi,&fromAddress, moreFlag, (char *) buf,(UInt32) bufSize); *address = fromAddress.fHost; *port = fromAddress.fPort; if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) { if (bytesRead > 0) ReadData(epi,NULL,0); else { bytesRead = ReadData(epi,(char *) buf,(UInt32) bufSize);//special case attempt read into squeak buffer *address = epi->remoteAddress.fHost; //Also we happen to know the address just when into this area *port = epi->remoteAddress.fPort; //JMM more flag? *moreFlag = epi->UDPMoreFlag; } } if (doLeave) OTLeaveNotifier(epi->erf); return (int) bytesRead; } int sqSocketLocalAddress(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; return (int) (epi->localAddress.fHost == 0) ? sqResolverLocalAddress() : epi->localAddress.fHost; } int sqSocketLocalPort(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; return epi->localAddress.fPort; } int sqSocketRemoteAddress(SocketPtr s) { EPInfo* epi; TBind remoteBind; InetAddress remoteAddr; SInt32 counter=0; OSStatus err; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection)) return 0; if (epi->socketType == UDPSocketType) { return (int) epi->remoteAddress.fHost; } //It seems the only reliable way to get the address //Is to make a call // OTMemzero(&remoteBind,sizeof(TBind)); OTMemzero(&remoteAddr,sizeof(InetAddress)); remoteBind.addr.buf = (UInt8 *) &remoteAddr; remoteBind.addr.maxlen = sizeof(InetAddress); err = OTGetProtAddress(epi->erf,0,&remoteBind); while (counter++ < 10 && remoteAddr.fHost == 0) { OTIdle(); } if (err != kOTNoError) return 0; else return (int) remoteAddr.fHost; } int sqSocketRemotePort(SocketPtr s) { EPInfo* epi; TBind remoteBind; InetAddress remoteAddr; SInt32 counter=0; OSStatus err; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection)) return 0; if (epi->socketType == UDPSocketType) { return epi->remoteAddress.fPort; } //It seems the only reliable way to get the port //Is to make a call // OTMemzero(&remoteBind,sizeof(TBind)); OTMemzero(&remoteAddr,sizeof(InetAddress)); remoteBind.addr.buf = (UInt8 *) &remoteAddr; remoteBind.addr.maxlen = sizeof(InetAddress); err = OTGetProtAddress(epi->erf,0,&remoteBind); while (counter++ < 10 && remoteAddr.fHost == 0) { OTIdle(); } if (err != kOTNoError) return 0; else return remoteAddr.fPort; } int sqSocketSendDone(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return 1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kSendIsBlocked)) { OTAtomicSetBit(&epi->stateFlags2, kTapSemaphoreWriteData); //Note the implied intent to use the semaphore return 0; } else { return 1; } } int sqSocketError(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection) && epi->lastError == 0) return kENOTCONNErr; // old code would return unconnectederror if unconnected else return (epi->lastError); } int sqSocketConnectionStatus(SocketPtr s) { if (!SocketValid(s)) return InvalidSocket; return unmapStatus((EPInfo *) s->privateSocketPtr); } static SInt32 unmapStatus(EPInfo *s) { if (OTAtomicTestBit(&s->stateFlags3, kSleepKilledMe)) {return InvalidSocket; } if (OTAtomicTestBit(&s->stateFlags, kThisEndClosed)) {return ThisEndClosed; } if (OTAtomicTestBit(&s->stateFlags, kOtherEndClosed)) {return OtherEndClosed; } if (OTAtomicTestBit(&s->stateFlags, kConnected)) { return Connected; } if (OTAtomicTestBit(&s->stateFlags, kWaitingForConnection)) {return WaitingForConnection; } if (OTAtomicTestBit(&s->stateFlags, kUnConnected)) {return Unconnected; } return 0; } static Boolean SocketValid(SocketPtr s) { if ((s != NULL) && (s->privateSocketPtr != NULL) && (s->sessionID == gthisNetSession) && (s->socketType == TCPSocketType || s->socketType == UDPSocketType) && (!OTAtomicTestBit(&(((EPInfo *)s->privateSocketPtr)->stateFlags3), kSleepKilledMe)) ) return true; interpreterProxy->success(false); return false; } static Boolean PortNumberValid(InetPort port) { if (port <= 65535) { return true; } interpreterProxy->success(false); return false; } //Used to signal all semaphores when we've closed the socket //I guess the read/write/disconnect threads really want to know // static void TapAllInterestedSemaphores(EPInfo *epi) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreReadData)) interpreterProxy->signalSemaphoreWithIndex(epi->readSemaIndex); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); } static Boolean DestroyAllOpenSockets(void) { EPInfo *epi; OTLink* link; ReadBuffer *aBuffer; // // Start closing connector endpoints. // While we could be rude and just close the endpoints, // we try to be polite and wait for all outstanding connections // to finish before closing the endpoints. The is a bit easier // on the server which won't end up keeping around control blocks // for dead connections which it doesn't know are dead. Alternately, // we could just send a disconnect, but this seems cleaner. // (void)OTLIFOStealList(gBrokenEPs); (void)OTLIFOStealList(gIdleEPs[0]); (void)OTLIFOStealList(gIdleEPs[1]); (void)OTLIFOStealList(gIdleEPs[2]); link = OTLIFODequeue(gAllEPs); while (link != NULL) { epi = OTGetLinkObject(link, EPInfo, globalLink); attemptToCloseAndDeleteThisEP(epi); link = OTLIFODequeue(gAllEPs); } // // If the lists are empty now, then all endpoints have been successfully closed, // so the client is stopped now. (Actually we hope that is the case) // // //Free up all the other resources // link = OTLIFODequeue(gFreeReadBuffers); while (link != NULL) { aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); OTFreeMem(aBuffer->readBufferData); OTFreeMem(aBuffer); link = OTLIFODequeue(gFreeReadBuffers); } ResolverTerminate(); OTFreeMem((char*)gDNSResolver); gIdleEPs[0]->fHead = NULL; gIdleEPs[1]->fHead = NULL; gIdleEPs[2]->fHead = NULL; gBrokenEPs->fHead = NULL; OTDestroyConfiguration(gCfgMastertcp); OTDestroyConfiguration(gCfgMasterudp); OTDestroyConfiguration(gCfgMasterListener); DisposeOTNotifyUPP(DNSNotifierUPP); DisposeOTNotifyUPP(NotifierSocketUPP); DisposeOTNotifyUPP(NotifierSocketUDPUPP); DisposeOTNotifyUPP(NotifierSocketListenerUPP); return true; } // // DoBind // // This routine either binds to a wild card address and specfic port if // we are doing a listen, otherwise we bind to a wild card address and // wild card port if we are starting a connection to a remote host. // J M M NOTE A more complex version could use port and addr // Note we don't bind to the local socket until here, we could when // The socket is created, but that leads to odd issues. // static void DoBind(EPInfo* epi,InetHost addr, InetPort port,UInt8 aExtraSocketHint,OTQLen queueDepth ) { OSStatus err; TBind bindReq, bindResult; InetAddress inAddr,bindAddr; switch (aExtraSocketHint) { case TCPSocketType: { // for a connection // Bind the endpoint to a wildcard address // (assign us a port, we don't care which one). // NOTE A more complex version could use port and addr OTInitInetAddress(&epi->remoteAddress, port, addr); OTInitInetAddress(&epi->localAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&inAddr, 0, 0); break; } case UDPSocketType: { // for a connection // Bind the endpoint to earlier supplied information OTInitInetAddress(&epi->remoteAddress, port, addr); OTInitInetAddress(&inAddr, 0, 0); break; } case TCPListenerSocketType: { // For a listen, bind wild card address, but supplied port. // Note the passed in addr should be zero // Note a more complex version could supply the address OTInitInetAddress(&epi->remoteAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&epi->localAddress, port, addr); OTInitInetAddress(&inAddr,port, addr); break; } case UDPListenerSocketType: { // For a listen, bind wild card address, but supplied port. // Note the passed in addr should be zero // Note a more complex version could supply the address OTInitInetAddress(&epi->remoteAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&epi->localAddress, port, addr); OTInitInetAddress(&inAddr,port, addr); break; } } bindReq.addr.len = sizeof(InetAddress); bindReq.addr.buf = (unsigned char*) &inAddr; bindReq.qlen = queueDepth; //Note queue depth for listening bindResult.addr.maxlen = sizeof(InetAddress); bindResult.addr.len = sizeof(InetAddress); bindResult.addr.buf = (unsigned char*) &bindAddr; epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; epi->bytesPendingToRead = 0; SetEPLastError(epi,noErr); if (aExtraSocketHint == TCPSocketType|| aExtraSocketHint == TCPListenerSocketType) { OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); } OTAtomicSetBit(&epi->stateFlags3, kWaitingForBind); err = OTBind(epi->erf, &bindReq, &bindResult); // resume at T_BINDCOMPLETE // for bindReq on listen what is queueDepth now? // bindReq.qlen could have changed // But... No why to feed this back to the client! if (err != kOTNoError) { SetEPLastError(epi,err); makeEPUnconnected(epi); return; } OTMemcpy(&epi->localAddress,bindResult.addr.buf,sizeof(InetAddress)); //Pickup local address return; } // // DoConnect // // This routine attempts establish a new connection to the given // address and port. // Called via the notifier at interrupt time. // static void DoConnect(EPInfo* epi,InetHost addr, InetPort port) { OSStatus err; TCall sndCall; InetAddress inAddr; // Don't want new connections if already shutting down. if (gProgramState != kProgramRunning ) return; OTInitInetAddress(&inAddr, port, addr); OTMemzero(&sndCall, sizeof(TCall)); sndCall.addr.len = sizeof(InetAddress); sndCall.addr.buf = (unsigned char*) &inAddr; err = OTConnect(epi->erf, &sndCall, NULL); //resume at T_CONNECT if (err != kOTNoDataErr) { SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } // // DoListenAccept // // The handling of a T_LISTEN is greatly simplified by use // of the tilisten module, which serializes inbound connections. // This means that when doing an OTAccept we won't get a kOTLookErr // because another inbound connection arrived and created a T_LISTEN. // Without the tilisten module, we have to use the "8 step // listen/accept/disconnect method", which is documented elsewhere. // static void DoListenAccept(EPInfo* acceptor,EPInfo* theServer) { TCall call; InetAddress caddr; OTResult lookResult; OSStatus err; OTMemzero(&call, sizeof(TCall)); call.addr.maxlen = sizeof(InetAddress); call.addr.buf = (unsigned char*) &caddr; err = OTListen(theServer->erf, &call); if (err != kOTNoError) { // // Only two errors are expected at this point. // One would be a kOTNoDataErr, indicating the inbound connection // was unavailable, temporarily hidden by a higher priority streams // message, etc. The more likely error is a kOTLookErr, // which indicates a T_DISCONNECT on the OTLook() // happens when the call we were going to process disconnected. // In that case, go away and wait for the next T_LISTEN event. // if (err == kOTNoDataErr) return; lookResult = OTLook(theServer->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) err = OTRcvDisconnect(theServer->erf, NULL); else SetEPLastError(theServer,lookResult); //JMM Sept28th,2000 ? ok accept it, if we don't does this cause blockage? acceptor->remoteAddress = caddr; err = OTAccept(theServer->erf, acceptor->erf, &call); return; } acceptor->remoteAddress = caddr; err = OTAccept(theServer->erf, acceptor->erf, &call); // // Note an kOTIndOutErr can occur if we are listening on the EP and handling // off to the same EP. Sorry use the listento:backlogqueue: logic instead // if (err != kOTNoError) { // // Again, we have to be able to handle the connection being disconnected // while we were trying to accept it. // lookResult = OTLook(theServer->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) err = OTRcvDisconnect(theServer->erf, NULL); else SetEPLastError(theServer,lookResult); } } // // EPOpen: // // A front end to OTAsyncOpenEndpoint. // A status bit is set so we know there is an open in progress. // It is cleared when the notifier gets a T_OPENCOMPLETE where the context // pointer is this EPInfo. Until that happens, this EPInfo can't be cleaned // up and released. // static Boolean EPOpen(EPInfo* epi) { OSStatus err; OTAtomicSetBit(&epi->stateFlags, kOpenInProgressBit); SetEPLastError(epi,kOTNoError); epi->UDPMaximumSize = 0; //Remember to figure out the max UDP size. switch (epi->socketType) { case TCPSocketType: { #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMastertcp), 0, NULL, NotifierSocketUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMastertcp), 0, NULL, NotifierSocketUPP, epi); #endif break; } case UDPSocketType: { TEndpointInfo endPointInformation; #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMasterudp), 0, &endPointInformation, NotifierSocketUDPUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMasterudp), 0, &endPointInformation, NotifierSocketUDPUPP, epi); #endif epi->UDPMaximumSize = (endPointInformation.tsdu == T_INFINITE) ? 64*1024 : endPointInformation.tsdu; break; } case TCPListenerSocketType: { #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMasterListener), 0, NULL, NotifierSocketListenerUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMasterListener), 0, NULL, NotifierSocketListenerUPP, epi); #endif break; } } if (err != kOTNoError) { SetEPLastError(epi,err); OTAtomicClearBit(&epi->stateFlags, kOpenInProgressBit); return false; } return (epi->lastError == kOTNoError); } // // EPClose // // This routine is a front end to OTCloseProvider. // Centralizing closing of endpoints makes debugging and instrumentation easier. // static Boolean EPClose(EPInfo* epi) { OSStatus err; // // If an endpoint is still being opened, we can't close it yet. // There is no way to cancel an OTAsyncOpenEndpoint, so we just // have to wait for the T_OPENCOMPLETE event at the notifier. // if ( OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit) ) return false; // // If the OTAsyncOpenEndpoint failed, the endpoint ref will be NULL, // and we don't need to close it now. Also can be NULL or should be NULL if sleeping happened. // if (epi->erf == NULL || OTAtomicClearBit(&epi->stateFlags3, kSleepKilledMe)) { epi->erf = NULL; return true; } if (epi->outstandingSends == 0) { err = OTCloseProvider(epi->erf); epi->erf = NULL; return true; } // // If we get to this point, the endpoint did an OTSnd() with AckSends, // and the T_MEMORYRELEASED event hasn't been returned yet. In order // to make sure we get the event, we flush the stream and then do an // OTDisconnect(). This should get the memory freed so we can close // the endpoint safely. Note, we set a flag so we don't do this // more than once on an endpoint. // J M M I'm not sure we'll ever get here since a flush should have been done higher up // if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) { err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); if (err != kOTNoError) {} } return false; } // // Recycle: // // This routine shouldn't be necessary, but it is helpful to work around both // problems in OpenTransport and bugs in this program. Basicly, whenever an // unexpected error occurs which shouldn't be fatal to the program, the EPInfo // is queued on the BrokenEP queue. When recycle is called, // it will attempt to close the associated endpoint and open // a new one to replace it using the same EPInfo structure. This process of // closing an errant endpoint and opening a replacement is probably the most // reliable way to make sure that this program and OpenTransport can recover // from unexpected happenings in a clean manner. // // Mind you it can be invoked to cleanup UDP sockets that aren't closed // properly due to pending traffice on a busy port. // Solution mentioned in books is to close the EP. // static void Recycle() { OTLink* list = OTLIFOStealList(gBrokenEPs); OTLink* link; EPInfo* epi; while ( (link = list) != NULL ) { list = link->fNext; epi = OTGetLinkObject(link, EPInfo, link); if (!EPClose(epi)) { OTLIFOEnqueue(gBrokenEPs, &epi->link); continue; } if (gProgramState == kProgramRunning) EPOpen(epi); else makeEPIdle(epi); } } // // Make the EP idle, it either goes on an idle queue or gets broken. // static void makeEPIdle(EPInfo *epi) { purgeReadBuffers(epi); if (OTAtomicClearBit(&epi->stateFlags2, kEPIsBroken)) { OTLIFOEnqueue(gBrokenEPs, &epi->link); } else { OTLIFOEnqueue(gIdleEPs[epi->socketType], &epi->link); OTAtomicAdd32(1, &gIdleEPCounter[epi->socketType]); } } static void attemptToCloseAndDeleteThisEP (EPInfo *epi) { purgeReadBuffers(epi); if (!EPClose(epi)) { // Can't close this endpoint yet, so skip it. } else OTFreeMem((char*)epi); } static EPInfo* getOrMakeMeAnEP(UInt8 aSocketType,short counter) { EPInfo *epi; OTLink *link; SInt32 i; Recycle(); //Ensure broken EP get fixed up if (counter > 25) return nil; // End recursion John 2000/8/29 if (gIdleEPCounter[aSocketType] < 5) //Magic Number ensure we have at least 5 EP available. makeMeAnEP(aSocketType); link = OTLIFODequeue(gIdleEPs[aSocketType]); if (link == NULL) { for(i=0;i<10;i++) {OTIdle();}; return getOrMakeMeAnEP(aSocketType,counter+1); //Watch for recursive failure } OTAtomicAdd32(-1, &gIdleEPCounter[aSocketType]); epi = OTGetLinkObject(link, EPInfo, link); if (OTAtomicTestBit(&epi->stateFlags3, kSleepKilledMe)) { // //A broken epi on the idle stack, now the only way we can //get here (I think) is to have gone to sleep which breaks //all the end points. To clean up we must now fix them //So make it idle, of course it's broken //Then recursive call to get another one //This continues until we get a good one // makeEPIdle(epi); return getOrMakeMeAnEP(aSocketType,counter); //Not a recursion issue. } return epi; } // //This is where EP are actually made and opened //EP opening is async // static Boolean makeMeAnEP (UInt8 aSocketType) { EPInfo *epi; #if TARGET_API_MAC_CARBON epi = (EPInfo*) OTAllocMemInContext(sizeof(EPInfo), gClientContext); #else epi = (EPInfo*) OTAllocMem(sizeof(EPInfo)); #endif if (epi == NULL) return false; //Death lurks OTMemzero(epi, sizeof(EPInfo)); //zero it out which makes all the pointers null epi->socketType = aSocketType; OTLIFOEnqueue(gAllEPs, &epi->globalLink); return EPOpen(epi); } static void makeEPUnconnected(EPInfo *epi) { OTAtomicClearBit(&epi->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) //tap to clear waitforconnection on error interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); } static void makeEPConnected(EPInfo *epi) { OTAtomicClearBit(&epi->stateFlags, kWaitingForConnection); OTAtomicClearBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags, kConnected); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) //tap to clear waitforconnection interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); } static void makeEPBrokenThenIdle(EPInfo* epi,OTResult error) { makeEPBroken(epi,error); makeEPIdle(epi); } static void makeEPBroken(EPInfo* epi,OTResult error) { SetEPLastError(epi,error); OTAtomicSetBit(&epi->stateFlags2, kEPIsBroken); } static void SetEPLastError(EPInfo* epi,OTResult error) { if (error < 0) { JMMLogMessageAndNumber("\p NonZero Error For ",epi->semaIndex); JMMLogMessageAndNumber("\p NonZero Error Is ",error); } epi->lastError = error; } // ReadData: // // This routine attempts to read all available data from an endpoint. // it is not necessary for the program to handle // getting back a T_DATA notification DURING an OTRcv() call, as would be // the case if we read from outside the notifier. We must read until we // get a kOTNoDataErr in order to clear the T_DATA event so we will get // another notification of T_DATA in the future. // Note we use EnterNotifier to make this possible // // Note for the curious we attempted to use no-copy receives to get data. This obligates // the program to return the buffers to OT asap. BUT we found we overran memory! // So we reverted to more expensive copies into buffers we have preallocated // // Perhaps a seperate routine for UDP would make sense? // Note May 30/00 we added a special read when we exhaust the internal buffer pool // But data is still pending we allow you to read into the squeak buffer directly // static UInt32 ReadData(EPInfo* epi,char *specialReadBuffer,UInt32 specialReadSize) { OTResult res; OTFlags flags; OTResult epState,err; OTLink *link; ReadBuffer *readBufferObject,simulatedReadBuffer; InetAddress UDPdataFromAddress; if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreReadData)) //tap to clear waitfordata Data Data Data interpreterProxy->signalSemaphoreWithIndex(epi->readSemaIndex); if (specialReadSize > 0) { //Special case drop into squeak buffer, make a simulated buffer object OTMemzero(&simulatedReadBuffer,sizeof(ReadBuffer)); simulatedReadBuffer.readBufferData = specialReadBuffer; simulatedReadBuffer.readBufferSize = simulatedReadBuffer.readBufferOriginalSize = specialReadSize; readBufferObject = &simulatedReadBuffer; } else { link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); //NO free buffers we are flow controled return; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); OTAtomicClearBit(&epi->stateFlags2, kReadFlowControl); } OTMemzero(&UDPdataFromAddress,sizeof(InetAddress)); while (true) { readBufferObject->readBufferPtr = readBufferObject->readBufferData; if (epi->socketType == UDPSocketType) { TUnitData UDPDataInBound; OTFlags flagMeaningMore; OSStatus error; UDPDataInBound.addr.maxlen = sizeof(InetAddress); UDPDataInBound.addr.len = sizeof(InetAddress); UDPDataInBound.addr.buf = (UInt8*) &readBufferObject->UDPAddress; UDPDataInBound.opt.maxlen = 0; UDPDataInBound.opt.len = 0; UDPDataInBound.opt.buf = NULL; UDPDataInBound.udata.maxlen = readBufferObject->readBufferOriginalSize; UDPDataInBound.udata.len = readBufferObject->readBufferOriginalSize; UDPDataInBound.udata.buf = (UInt8*)readBufferObject->readBufferData; error = OTRcvUData(epi->erf, &UDPDataInBound, &flagMeaningMore); if (error != kOTNoError) { res = error; } else { if (UDPDataInBound.addr.len == 0) //Remember UDP address readBufferObject->UDPAddress = UDPdataFromAddress; else UDPdataFromAddress = readBufferObject->UDPAddress; epi->UDPMoreFlag = readBufferObject->UDPMoreFlag = (flagMeaningMore > 0) ? true: false; res = (SInt32) UDPDataInBound.udata.len; OTMemcpy(&epi->remoteAddress,&readBufferObject->UDPAddress,sizeof(InetAddress)); } } else {//A less complicated tcp read res = OTRcv(epi->erf, readBufferObject->readBufferData, readBufferObject->readBufferOriginalSize, &flags); } // // Note, check for 0 because can get a real 0 length receive // in some protocols (not in TCP), which is different from // getting back a kOTNoDataErr. // if (res >= 0) { if (specialReadSize > 0) return (UInt32) res; //Note special case readBufferObject->readBufferSize = (UInt32) res; OTAddLast(&epi->readBuffers,&readBufferObject->fNext); //Put the buffer on the read queue OTAtomicAdd32(res, &epi->bytesPendingToRead); link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); //Our read flow control, OT will block lower down return; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); continue; //Loop around and get more bytes if available } else { if (specialReadSize == 0) { OTLIFOEnqueue(gFreeReadBuffers, &readBufferObject->fNext); //Read above didn't work so put it back on free queue gFreeReadBuffersCounter++; } } if (res == kOTNoDataErr) { // // Since ReadData is only called from inside the notifier // we don't have to worry about having missed a T_DATA // during the OTRcv. // Note use of EnterNotifier logic // if (specialReadSize > 0) OTAtomicClearBit(&epi->stateFlags2, kReadFlowControl); return 0; } if (res == kOTLookErr) { res = OTLook(epi->erf); if (res == T_ORDREL || res == T_DISCONNECT) { // If we got the T_ORDREL, we won't get any more inbound data. // We return and wait for the notifier to get the T_ORDREL notification. // Upon getting it, we will notice we still need to send data and do so. // The T_ORDREL has to be cleared before we can send. // if (specialReadSize > 0 && res == T_DISCONNECT) { //Special case? need to get disconnect err = OTRcvDisconnect(epi->erf, NULL); makeEPUnconnected(epi); } return 0 ; } if (res == T_GODATA) { if (specialReadSize == 0) { link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); return 0 ; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); } else { return 0; } continue; //OT Flow control lifted keep reading. JMM } } else { epState = OTGetEndpointState(epi->erf); if (res == kOTOutStateErr && epState == T_INREL) { // // Occasionally this problem will happen due to what appears // to be an OpenTransport notifier reentrancy problem. // What has occured is that a T_ORDREL event happened and // was processed during ReadData(). This is proven by being // in the T_INREL state without having done a call to // OTRcvOrderlyDisconnect() here. It appears to be a benign // situation, so the way to handle it is to understand that no // more data is going to arrive and go ahead and being our response // to the client. // break; } if (res == kOTOutStateErr && (epState == T_UNBND || epState == T_IDLE ) && specialReadSize > 0) { interpreterProxy->success(false); //JMM Oct 4th 2000 special case fail if read on unbound return 0; } break; //Ok error so break out of loop } } return 0; } // // NOT USED HISTORICAL REASONS // /* static void NoCopyReceiveWalkingBufferChain(EPInfo *epi,OTBufferInfo *bufferInfo) { OSStatus err; OTBuffer *thisBuffer; UInt32 count; ReadBuffer *readBufferObject; thisBuffer = bufferInfo->fBuffer; err = noErr; while (err == noErr && thisBuffer != nil) { count = thisBuffer->fLen; OTAtomicAdd32(count, &epi->bytesPendingToRead); readBufferObject = OTAllocMemInContext(sizeof(ReadBuffer), gClientContext); if (readBufferObject == nil) { SysBeep(5); err = -1; break; } OTMemzero(readBufferObject,sizeof(ReadBuffer)); readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMemInContext(count, gClientContext); if ( readBufferObject->readBufferData == nil) { SysBeep(5); err = -1; break; } readBufferObject->readBufferOriginalSize = readBufferObject->readBufferSize = count; OTMemcpy(readBufferObject->readBufferData,thisBuffer->fData,count); OTAddLast(&epi->readBuffers,&readBufferObject->fNext); thisBuffer = thisBuffer->fNext; } // Clean up. We MUST release the OTBuffer chain to Open Transport // so that it crelease the OTBuffer chain to Open Transport // so that it can reuse it., OTReleaseBuffer does not tolerate // the parameter being nil, so we check for that case first. if (bufferInfo->fBuffer != nil) { OTReleaseBuffer(bufferInfo->fBuffer); } } */ // // Read Bytes from the buffers // Called by Squeak to get the data // static UInt32 readBytes(EPInfo* epi,char *buf,UInt32 adjustedBufSize) { // // Read bytes from buffers // use recursion to fill buf to adjustedBufSize or // til we have no buffers left // By using enterNotifier higher up we avoid race on the readBuffers list // UInt32 increment,bytesRead = 0; ReadBuffer *aBuffer; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); if (aBuffer == nil) return 0; if (aBuffer->readBufferSize > adjustedBufSize) { bytesRead = adjustedBufSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy((char *) buf,aBuffer->readBufferPtr,bytesRead); aBuffer->readBufferPtr += bytesRead; aBuffer->readBufferSize -= bytesRead; OTAddFirst(&epi->readBuffers,&aBuffer->fNext); return bytesRead; } else { bytesRead = aBuffer->readBufferSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy(buf,aBuffer->readBufferPtr,bytesRead); OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; increment = readBytes(epi,buf+bytesRead,adjustedBufSize-bytesRead); bytesRead += increment; return bytesRead; } } static UInt32 readBytesUDP(EPInfo* epi,InetAddress *fromAddress, int * moreFlag, char *buf,UInt32 adjustedBufSize) { // // Read bytes from buffers // For UDP we just drop in the read buffer and address // Don't fill the entire buffer no recursion. // By using enterNotifier higher up we avoid race on the readBuffers list // UInt32 bytesRead = 0; ReadBuffer *aBuffer; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); if (aBuffer == nil) return 0; if (aBuffer->readBufferSize > adjustedBufSize) { bytesRead = adjustedBufSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy((char *) buf,aBuffer->readBufferPtr,bytesRead); aBuffer->readBufferPtr += bytesRead; aBuffer->readBufferSize -= bytesRead; OTMemcpy(fromAddress,&aBuffer->UDPAddress,sizeof(InetAddress)); *moreFlag = aBuffer->UDPMoreFlag; OTAddFirst(&epi->readBuffers,&aBuffer->fNext); return bytesRead; } else { bytesRead = aBuffer->readBufferSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy(buf,aBuffer->readBufferPtr,bytesRead); OTMemcpy(fromAddress,&aBuffer->UDPAddress,sizeof(InetAddress)); *moreFlag = aBuffer->UDPMoreFlag; OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; return bytesRead; } } //Cleanup logic // static void purgeReadBuffers(EPInfo *epi) { ReadBuffer *aBuffer; // //Put buffers for this epi back on the free queue // aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); while (aBuffer != NULL) { OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); } epi->bytesPendingToRead = 0; } // // Send the Bytes (Really fast, we hope) // static SInt32 SendData(EPInfo* epi,char* buffer, UInt32 size) { OTResult res; struct OTData *dataPtr; // // Make sure we record that we are starting a send so we don't try to close // the endpoint before a T_MEMORYRELEASED event is returned. // OTAtomicAdd32(1, &epi->outstandingSends); if (epi->socketType == UDPSocketType) { TUnitData UDPDataOutBound; UDPDataOutBound.addr.maxlen = sizeof(InetAddress); UDPDataOutBound.addr.len = sizeof(InetAddress); UDPDataOutBound.addr.buf = (UInt8*) &epi->remoteAddress; UDPDataOutBound.opt.maxlen = 0; UDPDataOutBound.opt.len = 0; UDPDataOutBound.opt.buf = NULL; UDPDataOutBound.udata.maxlen = size; UDPDataOutBound.udata.len = size; UDPDataOutBound.udata.buf = (UInt8*)buffer; res = OTSndUData(epi->erf,&UDPDataOutBound); if (res == kOTNoError ) return (SInt32) size; // Other Errors could be kOTFlowErr or kOTBadDataErr } else { //TCP Send // // In OT 1.1.2 and previous versions, there is a bug with AckSends // which occurs when the same buffer is sent more than once. In an attempt // to go fast and not allocate memory, TCP may write an IP and TCP header // into the data buffer which is sent. If the buffer is sent more than once // without being refreshed, the data may be corrupted. To work around this, // send the data via an OTData structure, using the gather-write mechanism. // The problem does not occur in this code path, and this will not hinder performance. // The problem will be fixed in the next Open Transport release following 1.1.2. // // Note the MAC OS 8.1 docs alude to a bug before 1.3 where acksends // cause problems if a disconnect flows just right. Unsure if this // will be an issue // if (gOTVersion < kOTVersion113) { #if TARGET_API_MAC_CARBON dataPtr = OTAllocMemInContext(sizeof(OTData), gClientContext); #else dataPtr = OTAllocMem(sizeof(OTData)); #endif if (dataPtr == NULL) { //Death lurks I'm sure OTAtomicAdd32(-1, &epi->outstandingSends); OTFreeMem(buffer); return 0; } dataPtr->fNext = NULL; dataPtr->fData = buffer; dataPtr->fLen = size; res = OTSnd(epi->erf, dataPtr, kNetbufDataIsOTData, 0); //Note in the notification routine we cleanup the allocated dataPtr AND buffer. } else { res = OTSnd(epi->erf, buffer, size, 0); //JMM how to handle kENOMEMErr no memory right now error //Book says to back off and wait but must do a timer or something //Right now we'll fail the primitive higher up since the error code is bad } } if (res == size) return (SInt32) size; if (res >= 0) { // // Implied kOTFlowErr since not all data was accepted. // But maybe we aren't blocked yet so keep sending // return res; } else { // res < 0 OTAtomicAdd32(-1, &epi->outstandingSends); OTFreeMem(buffer); if ((epi->socketType != UDPSocketType) && (gOTVersion < kOTVersion113) ) OTFreeMem(dataPtr); if (res == kOTFlowErr) { // // Flow control back off and wait for T_GODATA // OTAtomicSetBit(&epi->stateFlags, kSendIsBlocked); return 0; } if (res == kOTLookErr) { res = OTLook(epi->erf); if (res == T_ORDREL || res == T_GODATA || res == T_DISCONNECT) { // Wait to get the T_ORDREL at the notifier and handle it there. // Then we will resume sending. // Same applies for other events // //JMM test? OTAtomicSetBit(&epi->stateFlags, kSendIsBlocked); return 0; } else return res; } else return res; } } // //Set the options // int sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(SocketPtr s,int optionNameT, int optionNameSize, int optionValueT, int optionValueSize, int *result) { EPInfo* epi; OTResult error; char optionName[80],optionValue[80]; SInt32 anInteger; *result = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; OTMemcpy(optionName,(char *) optionNameT,optionNameSize); optionName[optionNameSize] = 0x00; OTMemcpy(optionValue,(char *) optionValueT,optionValueSize); optionValue[optionValueSize] = 0x00; CopyCStringToPascal(optionValue,(unsigned char *) optionValue); StringToNum((ConstStr255Param) optionValue,&anInteger); error = lookupOptionName(epi, false, (char *) &optionName, anInteger,(long *) result); return error; } // //Get the options // int sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(SocketPtr s,int optionNameT, int optionNameSize, int *result) { EPInfo* epi; OTResult error; char optionName[80]; *result = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; OTMemcpy(optionName,(char *) optionNameT,optionNameSize); //NEED to fiddle with error number JMM to say readonly notvalid etc. optionName[optionNameSize] = 0x00; error = lookupOptionName(epi, true, (char *) &optionName, NULL,(long *) result); return error; } // A Number of routines to set/get options, first figureout the flags, then call the routine // To set or get the options. static SInt32 lookupOptionName(EPInfo *epi, Boolean trueIfGet, char *aString, UInt32 value, SInt32 *result) { if (strcmp("TCP_MAXSEG",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_MAXSEG,value,result);}; if (strcmp("TCP_NODELAY",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_NODELAY,value,result);}; if (strcmp("TCP_ABORT_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_ABORT_THRESHOLD,value,result);}; if (strcmp("TCP_CONN_NOTIFY_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_CONN_NOTIFY_THRESHOLD,value,result);}; if (strcmp("TCP_CONN_ABORT_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_CONN_ABORT_THRESHOLD,value,result);}; if (strcmp("TCP_NOTIFY_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_NOTIFY_THRESHOLD,value,result);}; if (strcmp("TCP_URGENT_PTR_TYPE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_URGENT_PTR_TYPE,value,result);}; if (strcmp("UDP_CHECKSUM",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_UDP,UDP_CHECKSUM,value,result);}; if (strcmp("SO_DEBUG",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_DEBUG,value,result);}; if (strcmp("SO_REUSEADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_REUSEADDR,value,result);;}; if (strcmp("SO_REUSEPORT",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_REUSEADDR,value,result);}; if (strcmp("SO_DONTROUTE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_DONTROUTE,value,result);}; if (strcmp("SO_BROADCAST",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_BROADCAST,value,result);}; if (strcmp("SO_SNDBUF",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_SNDBUF,value,result);}; if (strcmp("SO_RCVBUF",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_RCVBUF,value,result);}; if (strcmp("SO_KEEPALIVE",aString)==0) {return SetKeepAliveOption(epi,trueIfGet,INET_TCP,TCP_KEEPALIVE,value,result);}; if (strcmp("SO_OOBINLINE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_OOBINLINE,value,result);}; if (strcmp("SO_PRIORITY",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,IP_TOS,value,result);}; if (strcmp("SO_LINGER",aString)==0) {return SetLingerOption(epi,trueIfGet,XTI_GENERIC,XTI_LINGER,value,result);}; if (strcmp("SO_RCVLOWAT",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_RCVLOWAT,value,result);}; if (strcmp("SO_SNDLOWAT",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_SNDLOWAT,value,result);}; if (strcmp("IP_OPTIONS",aString)==0) { }; //JMM What to do here? if (strcmp("IP_TTL",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,IP_TTL,value,result);}; if (strcmp("IP_HDRINCL",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_HDRINCL,value,result);}; //NOT SUPPORT FOR IP if (strcmp("IP_RCVOPTS",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_RCVOPTS,value,result);}; if (strcmp("IP_RCVDSTADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_RCVDSTADDR,value,result);}; if (strcmp("IP_MULTICAST_IF",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_MULTICAST_IF,value,result);}; if (strcmp("IP_MULTICAST_TTL",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,IP_MULTICAST_TTL,value,result);}; if (strcmp("IP_MULTICAST_LOOP",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,IP_MULTICAST_LOOP,value,result);}; /* if (strcmp("IP_ADD_MEMBERSHIP",aString)==0) { return SetJMMByteOption(epi,trueIfGet,INET_IP,IP_ADD_MEMBERSHIP,value,result);}; if (strcmp("IP_DROP_MEMBERSHIP",aString)==0) { return SetJMMByteOption(epi,trueIfGet,INET_IP,IP_DROP_MEMBERSHIP,value,result);}; if (strcmp("IP_BROADCAST_IF",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_BROADCAST_IF,value,result);}; if (strcmp("IP_RCVIFADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,IP_RCVIFADDR,value,result);}; */ *result = 0; return -1; } static OTResult SetFourByteOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; UInt8 optBuffer[kOTFourByteOptionSize]; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; /* Set up the option buffer to specify the option and value to set. */ option->len = kOTFourByteOptionSize; option->level= level; option->name = name; option->status = 0; option->value[0] = value; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(optBuffer); request.opt.maxlen=sizeof(optBuffer); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(optBuffer); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = option->value[0]; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetOneByteOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; UInt8 optBuffer[kOTFourByteOptionSize]; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; /* Set up the option buffer to specify the option and value to set. */ option->len = kOTOneByteOptionSize; option->level= level; option->name = name; option->status = 0; *(unsigned char *)option->value = value; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= kOTOneByteOptionSize; request.opt.maxlen=sizeof(optBuffer); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(optBuffer); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = (UInt32) (*(unsigned char *)option->value); if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetKeepAliveOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; TKeepAliveOpt optBuffer; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; if (value == 0) optBuffer.tcpKeepAliveOn = T_NO; else optBuffer.tcpKeepAliveOn = T_YES; optBuffer.tcpKeepAliveTimer = value; /* Set up the option buffer to specify the option and value to set. */ option->len = sizeof(TKeepAliveOpt); option->level= level; option->name = name; option->status = 0; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(TKeepAliveOpt); request.opt.maxlen=sizeof(TKeepAliveOpt); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(TKeepAliveOpt); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = optBuffer.tcpKeepAliveTimer; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetLingerOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; TLingerOpt optBuffer; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; if (value == 0) optBuffer.tcpLingerOn = T_NO; else optBuffer.tcpLingerOn = T_YES; optBuffer.tcpLingerTimer = value; /* Set up the option buffer to specify the option and value to set. */ option->len = sizeof(TKeepAliveOpt); option->level= level; option->name = name; option->status = 0; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(TKeepAliveOpt); request.opt.maxlen=sizeof(TKeepAliveOpt); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(TKeepAliveOpt); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = optBuffer.tcpLingerTimer; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } // // Notifier: // // Most of the interesting networking code in this program for the resolver resides inside // this notifier. In order to run asynchronously and as fast as possible, // things are done inside the notifier whenever possible. Since almost // everything is done inside the notifier, there was little need for specical // synchronization code. // // Note: The only events which are expected from the DNR are T_DNRSTRINGTOADDRCOMPLETE, // T_DNRADDRTONAMECOMPLETE, and of close sleep/reconfigure notifications. // // static pascal void DNSNotifier(void* context, OTEventCode event, OTResult result, void* cookie) { EPInfo* epi = (EPInfo*) context; JMMLogMessageAndNumber("\p DNS Event ",event); JMMLogMessageAndNumber("\p DNS Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); // // Once the program is shutting down, most events would be uninteresting. // if (gProgramState != kProgramRunning) return; // // Within the notifier, all action is based on the event code. // In this notifier, fatal errors all break out of the switch to the bottom. // As long as everything goes as expected, the case returns rather than breaks. // switch (event) { // // T_DNRSTRINGTOADDRCOMPLETE: // // This event occurs when the DNR has finished an attempt to translate // the server's name into an IP address we can use to connect to. // case T_DNRSTRINGTOADDRCOMPLETE: { gDNSResolverError = result; if (result != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } gDNSAddr = gDNSHostInfo.addrs[0]; gDNSResolverStatus = RESOLVER_SUCCESS; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } // // T_DNRADDRTONAMECOMPLETE: // // This event occurs when the DNR has finished an attempt to translate // the an IP address into a server name. // case T_DNRADDRTONAMECOMPLETE: { gDNSResolverError = result; if (result != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } gDNSResolverStatus = RESOLVER_SUCCESS; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } // // kOTProviderWillClose: // // This event occurs when the user changes TCP/IP in the control panel // case kOTProviderWillClose: case kOTProviderIsClosed: { gDNSResolverError = kOTProviderWillClose; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); ResolverTerminate(); gDNSResolverStatus = RESOLVER_SUCCESS; //Cheat! Keep Squeak happy later we fix the resolver EP. return; } // // default: // // There are events which we don't handle, but we don't expect to see // any of them. In the production version of the program, we ignore the event and try to keep running. // default: { return; } } } // // Notifier for socket: Please note we have another notifier for sockets that do multiple listens // And a different notifier for UDP sockets, however the intesting thing is that we can call /// This routine from othe other as a simple form of inheritence. // // Most of the interesting networking code in this program for socket support resides inside // this notifier. In order to run asynchronously and as fast as possible, // things are done inside the notifier whenever possible. Since almost // everything is done inside the notifier, there was little need for specical // synchronization code. // // IMPORTANT NOTE: Normal events defined by XTI (T_LISTEN, T_CONNECT, etc) // and OT completion events (T_OPENCOMPLETE, T_BINDCOMPLETE, etc.) are not // reentrant. That is, whenever our notifier is invoked with such an event, // the notifier will not be called again by OT for another normal or completion // event until we have returned out of the notifier - even if we make OT calls // from inside the notifier. This is a useful synchronization tool. // However, there are two kinds of events which will cause the notifier to // be reentered. One is T_MEMORYRELEASED, which always happens instantly. // The other are state change events like kOTProviderWillClose. // static pascal void NotifierSocket(void* context, OTEventCode event, OTResult result, void* cookie) { OSStatus err; OTResult epState; EPInfo* epi = (EPInfo*) context; JMMLogMessageAndNumber("\p Event ",event); JMMLogMessageAndNumber("\p Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); // // Once the program is shutting down, most events would be uninteresting. // However, we still need T_OPENCOMPLETE and T_MEMORYRELEASED events since // we can't call CloseOpenTransport until all OTAsyncOpenEndpoints and // OTSends with AckSends have completed. So those specific events // are still accepted. // if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } // // Within the notifier, all action is based on the event code. // In this notifier, fatal errors all break out of the switch to the bottom. // As long as everything goes as expected, the case returns rather than breaks. // switch (event) { // // kStreamIoctlEvent: // // This event is returned when an I_FLUSH ioctl has completed. // The flush was done in an attempt to get back all T_MEMORYRELEASED events // for outstanding OTSnd() calls with Ack Sends. For good measure, we // send a disconnect now. Errors are ignored at this point since it is // possible that the connection will already be gone, etc. // case kStreamIoctlEvent: { if (OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit) != 0) { OTAtomicClearBit(&epi->stateFlags2, kFlushDisconnectInProgressBit); (void) OTSndDisconnect(epi->erf, NULL); } return; } // // T_ACCEPTCOMPLETE: // // This event is received by the listener endpoint only when we open a port with a listen. // The acceptor endpoint will get a T_PASSCON event instead. // case T_ACCEPTCOMPLETE: { SetEPLastError(epi,result); if (result != kOTNoError) { makeEPUnconnected(epi); return; } makeEPConnected(epi); return; } // // T_BINDCOMPLETE: // // This event is returned when an endpoint has been bound to a wildcard addr. // Bind happens when we open a connection to a remote location. // No errors are expected. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) { makeEPUnconnected(epi); return; } if (epi->remoteAddress.fHost != 0) DoConnect(epi,epi->remoteAddress.fHost, epi->remoteAddress.fPort); return; } // // T_CONNECT: // // This event is returned when a connection is established to the server. // The program must call OTRcvConnect() to get the conenction information // and clear the T_CONNECT event from the stream. Since OTRcvConnect() // returns immediately (rather than via a completion event to the notifier) // we can use local stack structures for parameters. // case T_CONNECT: { TCall call; SetEPLastError(epi,result); if (result != kOTNoError) { makeEPUnconnected(epi); return; } // Address of endpoint that has connection // This could be different from original request // Due to hand off to different EP say you connect to // port 80, but you end up on 49160 call.addr.maxlen = sizeof(InetAddress); call.addr.buf = (unsigned char*) &epi->remoteAddress; call.opt.maxlen = 0; call.opt.buf = NULL; call.udata.maxlen = 0; call.udata.buf = NULL; err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); if (err != kOTNoError) { if (err == kOTLookErr) { OSStatus lookStatus; lookStatus = OTLook(epi->erf); if (lookStatus == T_DISCONNECT) { err = OTRcvDisconnect(epi->erf, NULL); if (err != kOTNoError) { if (err == kOTNoDisconnectErr) { err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } else { err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } if (lookStatus == T_GODATA) { // HUH err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPConnected(epi); return; } } //JMM book says may return kOTNoDataErr (no connecton yet) or a kOTLookErr with T_DISCONNECT // BUT we had got T_GODATA WHY? makeEPUnconnected(epi); return; } makeEPConnected(epi); return; // Wait for a T_DATA... } // // T_LISTEN: // case T_LISTEN: { DoListenAccept(epi,epi); return; } // // T_DATA: // // The main rule for processing T_DATA's is to remember that once you have // a T_DATA, you won't get another one until you have read to a kOTNoDataErr. // The advanced rule is to remember that you could get another T_DATA // during an OTRcv() which will eventually return kOTNoDataErr, presenting // the application with a synchronization issue to be most careful about. // // In this application, since an OTRcv() calls are made from inside the notifier, // this particular synchronization issue doesn't become a problem. // case T_DATA: { if (!OTAtomicTestBit(&epi->stateFlags2, kPassconNeeded)) { ReadData(epi,NULL,0); return; } else { // // Here we work around a small OpenTransport bug. // It turns out, since this program does almost everything from inside the notifier, // that during a T_UNBINDCOMPLETE we can put an EPInfo back into the idle list. // If that notification is interrupted by a T_LISTEN at the notifier, we could // end up starting a new connection on the endpoint before OT unwinds the stack // out of the code which delivered the T_UNBINDCOMPLETE. OT has some specific // code to protect against a T_DATA arriving before the T_PASSCON, but in this // case it gets confused and the events arrive out of order. If we try to // do an OTRcv() at this point we will get a kOTStateChangeErr because the endpoint // is still locked by the earlier OTAccept call until the T_PASSCON is delivered // to us. This is fairly benign and can be worked around easily. What we do // is note that the T_PASSCON hasn't arrived yet and defer the call to ReadData() // until it does. // if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 ) { ReadData(epi,NULL,0); return; } } } // // T_PASSCON: // // This event happens on the accepting endpoint, not the listening endpoint. // At this point the connection is fully established and we can begin the // process of downloading data. Note that due to a problem in OT it is // possible for a T_DATA to beat a T_PASSCON to the notifier. When this // happens we note it in the T_DATA case and then start processing the // data here. // case T_PASSCON: { SetEPLastError(epi,result); if (result != kOTNoError) { OTAtomicSetBit(&epi->stateFlags, kPassconBit); makeEPUnconnected(epi); return; } makeEPConnected(epi); if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 ){ // // A T_DATA previously beat the T_PASSCON to our notifier. // Here we help OT out by having deferred data processing until now. // ReadData(epi,NULL,0); } return; } // // T_MEMORYRELEASED // lower level has finished with buffer case T_MEMORYRELEASED: { if (cookie == nil) return; OTAtomicAdd32(-1, &epi->outstandingSends); if (epi->socketType == UDPSocketType) { OTFreeMem(cookie); } else {//tcp if (gOTVersion < kOTVersion113) { struct OTData *data=cookie; OTFreeMem(data->fData); OTFreeMem(data); } else { OTFreeMem(cookie); } } return; } // // T_DISCONNECT: // // An inbound T_DISCONNECT event usually indicates that the other side of the // connection did an abortive disconnect (as opposed to an orderly release). // It also can be generated by the transport provider on the system (e.g. tcp) // when it decides that a connection is no longer in existance. // // We receive the disconnect, but this program ignores the associated reason (NULL param). // It is possible to get back a kOTNoDisconnectErr from the OTRcvDisconnect call. // This can happen when either (1) the disconnect on the stream is hidden by a // higher priority message, or (2) something has flushed or reset the disconnect // event in the meantime. This is not fatal, and the appropriate thing to do is // to pretend the T_DISCONNECT event never happened. Any other error is unexpected // and needs to be reported so we can fix it. Next, unbind the endpoint so we can // reuse it for a new inbound connection. // // It is possible to get an error on the unbind due to a bug in OT 1.1.1 and earlier. // The best thing to do for that is close the endpoint and open a new one to replace it. // We do this back in the main thread so we don't have to deal with synchronization problems. // case T_DISCONNECT: { epState = OTGetEndpointState(epi->erf); err = OTRcvDisconnect(epi->erf, NULL); if (epState == T_OUTCON) { //01Aug2000 fix for bad port, will get disconnect on outgoing connection makeEPUnconnected(epi); } if (err != kOTNoError) { if (err == kOTNoDisconnectErr) return; makeEPBroken(epi,err); return; } /// //Both sides now have closed // OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); err = OTUnbind(epi->erf); TapAllInterestedSemaphores(epi); if (err != kOTNoError) { makeEPBroken(epi,err); } return; } // // T_GODATA: // // This event is received when flow control is lifted. We are under flow control // whenever OTSnd() returns a kOTFlowErr or accepted less bytes than we attempted // to send. // // Note, it is also possible to get a T_GODATA without having invoke flow control. // Be safe and prepare for this. // case T_GODATA: { if (OTAtomicClearBit(&epi->stateFlags, kSendIsBlocked)) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); }; return; } // // T_OPENCOMPLETE: // // This event occurs when an OTAsyncOpenEndpoint() completes. Note that this event, // just like any other async call made from outside the notifier, can occur during // the call to OTAsyncOpenEndpoint(). That is, in the main thread the program did // the OTAsyncOpenEndpoint(), and the notifier is invoked before control is returned // to the line of code following the call to OTAsyncOpenEndpoint(). This is one // event we need to keep track of even if we are shutting down the program since there // is no way to cancel outstanding OTAsyncOpenEndpoint() calls. // case T_OPENCOMPLETE: { TOptMgmt optReq; TOption opt; OTAtomicClearBit(&epi->stateFlags, kOpenInProgressBit); if (result == kOTNoError) epi->erf = (EndpointRef) cookie; else { makeEPBrokenThenIdle(epi,result); return; } if (gProgramState != kProgramRunning) return; // // Set to blocking mode so we don't have to deal with kEAGAIN errors. // Async/blocking is the best mode to write an OpenTransport application in. // err = OTSetBlocking(epi->erf); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); return; } // // Set to AckSends so OT doesn't slow down to copy data sent out. // However, this requires special care when closing endpoints, so don't use // AckSends unless you are prepared for this. Never, ever, close an endpoint // when a send has been done but the T_MEMORYRELEASED event hasn't been returned yet. // err = OTAckSends(epi->erf); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); return; } // // Option Management // // Turn on ip_reuseaddr so we don't have port conflicts in general. // We use local stack structures here since the memory for the // option request structure is free upon return. If we were to request // the option return value, we would have to use static memory for it. // optReq.flags = T_NEGOTIATE; optReq.opt.len = kOTFourByteOptionSize; optReq.opt.buf = (unsigned char *) &opt; opt.len = sizeof(TOption); opt.level = INET_IP; opt.name = IP_REUSEADDR; opt.status = 0; opt.value[0] = 1; if (epi->socketType == TCPSocketType) OTAtomicSetBit(&epi->stateFlags3, kKeepAliveOptionNeeded); err = OTOptionManagement(epi->erf, &optReq, NULL); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); } // // Code path resumes at T_OPTMGMTCOMPLETE // return; } // // T_OPTMGMTCOMPLETE: // // An OTOptionManagement() call has completed. These are used on all // endpoints to set IP_REUSEADDR. It is also used for all endpoints // other than the listener to set TCP_KEEPALIVE which helps recover // server resources if the other side crashes or is unreachable. // case T_OPTMGMTCOMPLETE: { TOptMgmt optReq; if (result != kOTNoError) { makeEPBrokenThenIdle(epi,result); return; } if (OTAtomicClearBit(&epi->stateFlags3, kKeepAliveOptionNeeded)) { TKeepAliveOpt opt; // // Turn on TCP_KEEPALIVE so we can recover from connections which have // gone away which we don't know about. // optReq.flags = T_NEGOTIATE; optReq.opt.len = sizeof(TKeepAliveOpt); optReq.opt.buf = (unsigned char *) &opt; opt.len = sizeof(TKeepAliveOpt); opt.level = INET_TCP; opt.name = TCP_KEEPALIVE; opt.status = 0; opt.tcpKeepAliveOn = 1; opt.tcpKeepAliveTimer = kTCPKeepAliveInMinutes; err = OTOptionManagement(epi->erf, &optReq, NULL); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,result); } return; } makeEPIdle(epi); //This is where more EP enter the queue of available EPs. return; // now wait } // // T_ORDREL: // // This event occurs when an orderly release has been received on the stream. // case T_ORDREL: { err = OTRcvOrderlyDisconnect(epi->erf); if (err != kOTNoError) { // // It is possible for several reasons for the T_ORDREL to have disappeared, // or be temporarily hidden, when we attempt the OTRcvOrderlyDisconnect(). // The best thing to do when this happens is pretend that the event never // occured. We will get another notification of T_ORDREL if the event // becomes unhidden later. Any other form of error is unexpected and // is reported back so we can correct it. // if (err == kOTNoReleaseErr) return; //Can get OTLookErr with T_DISCONNECT makeEPBroken(epi,err); } if (OTAtomicTestBit(&epi->stateFlags, kThisEndClosed)) { /// //Both sides now have closed // OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); epState = OTGetEndpointState(epi->erf); if (epState != T_IDLE) { TapAllInterestedSemaphores(epi); return; } err = OTUnbind(epi->erf); TapAllInterestedSemaphores(epi); if (err != kOTNoError) { makeEPBroken(epi,err); } return; } else { OTAtomicSetBit(&epi->stateFlags, kOtherEndClosed); } // // Sometimes our data sends get stopped with a kOTLookErr // because of a T_ORDREL from the other side (which doesn't close // the connection, it just means they are done sending data). // If so, we still end up in the notifier with the T_ORDREL event, // but we won't resume sending data unless we explictly check // here whether or not we need to do so. // //JMM Test this? if (OTAtomicClearBit(&epi->stateFlags, kSendIsBlocked)) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); }; return; } // // T_UNBINDCOMPLETE: // // This event occurs on completion of an OTUnbind(). // The endpoint is ready for reuse on a new inbound connection. // Note that the OTLIFO structure has atomic queue and dequeue, // which can be helpful for synchronization protection. // case T_UNBINDCOMPLETE: { if (result != kOTNoError) { // // Unbind errors can occur as a result of a bug in OT 1.1.1 and earlier // versions. The best recovery is to put the endpoint in the broken // list for recycling with a clean, new endpoint. // Since we only support 1.1.2 we don't expect to run this code. // makeEPBroken(epi,result); return; } return; } // // T_DISCONNECTCOMPLETE: // // This event occurs on completion of an OTSndDisconnect(). // Called when we abort a socket // case T_DISCONNECTCOMPLETE: { err = OTUnbind(epi->erf); if (err != kOTNoError) { makeEPBroken(epi,err); } purgeReadBuffers(epi); TapAllInterestedSemaphores(epi); if (OTAtomicTestBit(&epi->stateFlags2, kMakeEPIdle)) { //Make EP idle if marked as such only happens via destroy. makeEPIdle(epi); } epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; SetEPLastError(epi,result); OTAtomicSetBit(&epi->stateFlags, kUnConnected); return; } // //Sleep sleep sleep all end points get trashed. // case kOTProviderWillClose: // reconfig stack disconnect and close { makeEPBroken(epi,-12345678); if(OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit)) return; OTSetSynchronous(epi->erf); // set endpoint to sync if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); OTSndDisconnect(epi->erf, NULL); OTUnbind(epi->erf); OTCloseProvider(epi->erf); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags3, kSleepKilledMe); TapAllInterestedSemaphores(epi); return; } case kOTProviderIsClosed: //Sleep lurks { makeEPBroken(epi,-12345678); OTSetSynchronous(epi->erf); // set endpoint to sync if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); OTCloseProvider(epi->erf); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags3, kSleepKilledMe); TapAllInterestedSemaphores(epi); return; } // // default: // // There are events which we don't handle, but we don't expect to see // any of them. When running in debugging mode while developing a program, // we exit with an informational alert. Later, in the production version // of the program, we ignore the event and try to keep running. // default: { return; } } } // // Notifier for listen socket: // static pascal void NotifierSocketListener(void* context, OTEventCode event, OTResult result, void* cookie) { EPInfo* epi = (EPInfo*) context; if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } JMMLogMessageAndNumber("\p Listener Event ",event); JMMLogMessageAndNumber("\p Listener Result ",result); JMMLogMessageAndNumber("\p Listener Id ",epi->semaIndex); switch (event) { // // T_BINDCOMPLETE: // // We only bind the listener endpoint, and bind failure is a fatal error. // Acceptor endpoints are bound within the OTAccept() call when they get a connection. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) makeEPUnconnected(epi); return; } // // T_LISTEN: // case T_LISTEN: { SetEPLastError(epi,result); makeEPConnected(epi); return; } // // T_ACCEPTCOMPLETE: // // This event is received by the listener endpoint only. // The acceptor endpoint will get a T_PASSCON event instead. // case T_ACCEPTCOMPLETE: { SetEPLastError(epi,result); return; } // // default: // // There are events which we don't handle, pass them onwards // default: { NotifierSocket(context, event, result, cookie); return; } } } // // Notifier for UDP listen socket: // static pascal void NotifierSocketUDP(void* context, OTEventCode event, OTResult result, void* cookie) { EPInfo* epi = (EPInfo*) context; OSStatus err; JMMLogMessageAndNumber("\p DNS Event ",event); JMMLogMessageAndNumber("\p DNS Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } switch (event) { //Some sort of UDP send error, too late to tell anyone? // case T_UDERR: { TUDErr uderr; InetAddress errorAddress; uderr.addr.maxlen = sizeof(InetAddress); uderr.addr.len = sizeof(InetAddress); uderr.addr.buf = (UInt8 *) &errorAddress; uderr.opt.maxlen = 0; uderr.opt.len = 0; uderr.opt.buf = NULL; err = OTRcvUDErr(epi->erf, &uderr); if (err != kOTNoError) makeEPBroken(epi,err); SetEPLastError(epi,uderr.error); return; } // // T_DATA: // // Got milk? // case T_DATA: { ReadData(epi,NULL,0); return; } // // T_BINDCOMPLETE: // // This event is returned when an endpoint has been bound. // No errors are expected. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) { makeEPUnconnected(epi); return; } makeEPConnected(epi); return; } // // default: // // There are events which we don't handle, pass them onwards to the regular notifier // default: { NotifierSocket(context, event, result, cookie); return; } } } short gJMMFile=0; OTTimeStamp JMMStartTimeStamp; OTLIFO JMMLogBufferLIFO; // Buffers that are free to read into OTLIFO* JMMLogBufferBuffers = &JMMLogBufferLIFO; void JMMWriteLog() { OSErr error; OTLink* list = OTReverseList(OTLIFOStealList(JMMLogBufferBuffers)); OTLink* link; ReadBuffer *aBuffer; long dummySize; char CH=0x0D; if (true) return; error = HCreate(0,0,"\pJMMFOOBAR.txt",'TEXT','TEXT'); error = HOpenDF(0,0,"\pJMMFOOBAR.txt",fsRdWrPerm,&gJMMFile); error = SetFPos(gJMMFile,fsFromLEOF,0); while ( (link = list) != NULL ) { list = link->fNext; aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); error = FSWrite(gJMMFile,(long *)&aBuffer->readBufferSize,aBuffer->readBufferData); dummySize = 1; error = FSWrite(gJMMFile,&dummySize,&CH); } error = FSClose(gJMMFile); while ( (link = list) != NULL ) { list = link->fNext; aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); OTFreeMem(aBuffer->readBufferData); OTFreeMem(aBuffer); } } void JMMLogMessage(Str255 input) { Str255 timeString; long timeStringLength,inputLength; UInt32 duration; ReadBuffer *readBufferObject; if (true) return; if (gJMMFile == 0) { gJMMFile = 1; OTGetTimeStamp(&JMMStartTimeStamp); JMMLogBufferBuffers->fHead = NULL; } duration = OTElapsedMilliseconds(&JMMStartTimeStamp); NumToString(duration,timeString); timeStringLength = (unsigned char) timeString[0]; inputLength = (unsigned char) input[0]; #if TARGET_API_MAC_CARBON readBufferObject = OTAllocMemInContext(sizeof(ReadBuffer), gClientContext); #else readBufferObject = OTAllocMem(sizeof(ReadBuffer)); #endif if (readBufferObject == NULL) return; OTMemzero(readBufferObject,sizeof(ReadBuffer)); #if TARGET_API_MAC_CARBON readBufferObject->readBufferData = OTAllocMemInContext(60, gClientContext); #else readBufferObject->readBufferData = OTAllocMem(60); #endif if (readBufferObject->readBufferData == NULL) { OTFreeMem(readBufferObject); return; } OTMemcpy(readBufferObject->readBufferData,timeString+1,timeStringLength); OTMemcpy(readBufferObject->readBufferData+timeStringLength,input+1,inputLength); readBufferObject->readBufferSize= timeStringLength+inputLength; OTLIFOEnqueue(JMMLogBufferBuffers, &readBufferObject->fNext); } void JMMLogMessageAndNumber(Str255 msg,long number) { Str255 buffer,numberString; long msgLength,numberLength; if (true) return; NumToString(number,numberString); numberLength = (unsigned char) numberString[0]; msgLength = (unsigned char) msg[0]; OTMemcpy(buffer+1,msg+1,msgLength); OTMemcpy(buffer+1+msgLength,numberString+1,numberLength); buffer[0] = (unsigned char) msgLength+numberLength; JMMLogMessage(buffer); } /* The Open Transport TCP/IP software modules provide a RawIP interface to the IP protocol hostname of '' lookup fails This is OK? Same on linux and old mac version JMM look at tlook page, not sure if we have completely understood it JMM is it legal to send a zero byte buffer need case for this? /* According to the XTI spec ("Section 4.6 Events and TLOOK Error indication"), the SndOrderlyDisconnect and RcvOrderlyDisconnect calls can fail because of a pending T_DISCONNECT event. This is XTI trying to tell you that the a connection on that endpoint broke. This can happen in this asynchronous wacky world of networks and your program will have to call a RcvDisconnect to acknowledge that your endpoint dropped. You might want to check out the OTI spec, which, although it is not always written in the most lucid fashion, does contain valuable information for those involved in OpenTransport programming. Further Information: Title: X/OPEN TRANSPORT INTERFACE (XTI) VER 2 [ 1.0 ed] Author: X/OPEN ISBN #: 0133534596 A Prior to Open Transport 1.3, there was no supported way of calling Open Transport from CFM-68K code. With the introduction of Open Transport 1.3, it is now possible to call the Open Transport client interface from CFM-68K code. The Open Transport 1.3 SDK includes stub libraries and a document, "Open Tpt CFM68K Dev. Note", which explains Open Transport's support for CFM-68K. which is supporte for syste 7.x but you can't install! No standalone installer exists. Coping the OT files kinda works */ #else /* Adjustments for pluginized VM * * Note: The Mac support files have not yet been fully converted to * pluginization. For the time being, it is assumed that they are linked * with the VM. When conversion is complete, they will no longer import * "sq.h" and they will access all VM functions and variables through * the interpreterProxy mechanism. */ #include "sq.h" #include "SocketPlugin.h" /* initialize/shutdown */ int socketInit() { return true; } int socketShutdown() { sqNetworkShutdown(); } /* End of adjustments for pluginized VM */ #include #include #include #include #include #include #include #include #include "MacTCP.h" #include "AddressXLation.h" /*** Socket Type Constants ***/ #define TCPSocketType 0 #define UDPSocketType 1 #define ListenerQueueType 2 /*** Resolver Status Constants ***/ #define RESOLVER_UNINITIALIZED 0 #define RESOLVER_SUCCESS 1 #define RESOLVER_BUSY 2 #define RESOLVER_ERROR 3 /* Resolver State */ typedef struct { int semaIndex; int status; int error; int localAddress; int remoteAddress; struct hostInfo hostInfo; } ResolverStatusRec, *ResolverStatusPtr; /*** TCP Socket Status Constants ***/ #define Unconnected 0 #define WaitingForConnection 1 #define Connected 2 #define OtherEndClosed 3 #define ThisEndClosed 4 /*** TCP Socket State ***/ #define SendBufferSize (8 * 1024) #define RecvBufferSize (8 * 1024) typedef struct { TCPiopb tcpPB; /* TCP parameter block for open/send (must be first) */ TCPiopb closePB; /* TCP parameter block for close */ StreamPtr tcpStream; /* TCP stream */ void * next; /* next socket in a linked list of open sockets */ int semaIndex; int connectStatus; void * nextInListenerQueue; /* next socket in a ListenderQueue waiting socket list */ int dataAvailable; /* suggests that data may be available */ int sendInProgress; int lastError; //xxx char sendBuf[SendBufferSize]; char rcvBuf[1]; /* must be last; length set when allocated */ } TCPSockRec, *TCPSockPtr; typedef struct { TCPiopb tcpPB; TCPSockPtr mySocket; struct wdsEntry wds[2]; char data[SendBufferSize]; } TCPSendBuf, *TCPSendBufPtr; #define SendBufCount 8 TCPSendBuf sendBufPool[SendBufCount]; int nextSendBuf = 0; typedef struct { int localAddress; int localPort; int closed; /* set true by close or abort */ int semaIndex; /* semaphore of the server socket */ int desiredQueueLength; TCPSockPtr waitingSockets; } ListenerQueueRec, *ListenerQueuePtr; /*** UDP Socket Status Constants ***/ #define UnknowRemoteAddrAndPort 0 #define Ready 1 /*** UDP Socket State ***/ typedef struct { void * next; /* next socket in a linked list of open sockets */ int remoteAddress; int remotePort; int semaIndex; int connectStatus; int dataAvailable; /* suggests that data may be available */ int sendInProgress; int lastError; char sendBuf[SendBufferSize]; char rcvBuf[1]; /* must be last; length set when allocated */ } UDPSockRec, *UDPSockPtr; /*** Variables ***/ extern struct VirtualMachine *interpreterProxy; short macTCPRefNum = 0; int mtuSize = 1024; TCPSockPtr openTCPSockets = nil; UDPSockPtr openUDPSockets = nil; ResolverStatusRec resolver = {0, 0, 0, 0, 0, 0, 0}; UniversalProcPtr myExitHandlerProc = nil; UniversalProcPtr oldExitHandlerProc = nil; ResultUPP resolverDoneProc = nil; TCPIOCompletionUPP tcpCloseDoneProc = nil; TCPIOCompletionUPP tcpConnectDoneProc = nil; TCPNotifyUPP tcpNotifyProc = nil; TCPIOCompletionUPP tcpSendDoneProc = nil; UDPNotifyUPP udpNotifyProc = nil; UDPIOCompletionUPP udpSendDoneProc = nil; int thisNetSession = 0; /*** Private TCP Socket Functions ***/ void * TCPSockCreate(void); void TCPSockDestroy(TCPSockPtr s); void TCPSockRemoveFromOpenList(TCPSockPtr s); int TCPSockLocalAddress(TCPSockPtr s); int TCPSockLocalPort(TCPSockPtr s); int TCPSockRemoteAddress(TCPSockPtr s); int TCPSockRemotePort(TCPSockPtr s); void TCPSockConnectTo(TCPSockPtr s, int addr, int port); void TCPSockListenOn(TCPSockPtr s, int port); void TCPSockAbortConnection(TCPSockPtr s); void TCPSockCloseConnection(TCPSockPtr s); int TCPSockDataAvailable(TCPSockPtr s); int TCPSockRecvData(TCPSockPtr s, char *buf, int bufSize); int TCPSockSendData(TCPSockPtr s, char *buf, int bufSize); /*** Private ListenerQueue Socket Functions ***/ void FillListenerQueue(ListenerQueuePtr listener); TCPSockPtr FindConnectedSocket(ListenerQueuePtr listener); TCPSockPtr FindZombieSocket(ListenerQueuePtr listener); void RemoveSocketFromListenerQueue(TCPSockPtr sockToRemove, ListenerQueuePtr listener); ListenerQueuePtr ListenerQueueCreate(TCPSockPtr tcpSocket, int port, int backlogSize); void ListenerQueueDestroy(ListenerQueuePtr listener); int ListenerQueueStatus(ListenerQueuePtr listener); /*** Private UDP Socket Functions ***/ void * UDPSockCreate(void); void UDPSockDestroy(UDPSockPtr s); void UDPSockRemoveFromOpenList(UDPSockPtr s); int UDPSockLocalAddress(UDPSockPtr s); int UDPSockLocalPort(UDPSockPtr s); int UDPSockRemoteAddress(UDPSockPtr s); int UDPSockRemotePort(UDPSockPtr s); void UDPSockConnectTo(UDPSockPtr s, int addr, int port); void UDPSockListenOn(UDPSockPtr s, int port); int UDPSockRecvData(UDPSockPtr s, char *buf, int bufSize); int UDPSockSendData(UDPSockPtr s, char *buf, int bufSize); /*** Other Private Functions ***/ void DestroyAllOpenSockets(void); void InitTCPCmd(int cmd, StreamPtr tcpStream, TCPiopb *paramBlkPtr); void InstallExitHandler(void); void MyExitHandler(void); int PortNumberValid(int port); pascal void ResolverCompletionRoutine(struct hostInfo *hostInfoPtr, char *userDataPtr); int ResolverInitialize(int resolverSemaIndex); void ResolverTerminate(void); int SocketValid(SocketPtr s); void TCPCloseCompletionRoutine(struct TCPiopb *s); void TCPConnectCompletionRoutine(struct TCPiopb *s); pascal void TCPNotificationRoutine( StreamPtr s, unsigned short eventCode, Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg); void TCPSendCompletionRoutine(struct TCPiopb *s); /*** Network Functions ***/ void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { interpreterProxy->success(false); } int sqSockettoHostportSendDataBufCount(SocketPtr s, int address, int port, int buf, int bufSize) { interpreterProxy->success(false); } int sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(SocketPtr s,int optionNameT, int optionNameSize, int *result) { interpreterProxy->success(false); } void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { interpreterProxy->success(false); } int sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, int buf, int bufSize, int *address, int *port, int *moreFlag) { interpreterProxy->success(false); } int sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(SocketPtr s,int optionNameT, int optionNameSize, int optionValueT, int optionValueSize, int *result) { interpreterProxy->success(false); } int sqNetworkInit(int resolverSemaIndex) { /* initialize the network and return 0 if successful */ int localAddr; UDPiopb paramBlock; OSErr err = noErr; if (thisNetSession != 0) return 0; /* noop if network is already initialized */ /* open network driver */ macTCPRefNum = 0; err = OpenDriver("\p.IPP", &macTCPRefNum); if (err != noErr) { return -1; } /* open resolver */ err = ResolverInitialize(resolverSemaIndex); if (err != noErr) { ResolverTerminate(); return -1; } /* get local address */ localAddr = sqResolverLocalAddress(); if (sqResolverError() != noErr) { ResolverTerminate(); return -1; } /* compute MTU (maximum transfer unit) size */ memset(¶mBlock, 0, sizeof(paramBlock)); paramBlock.csCode = UDPMaxMTUSize; paramBlock.csParam.mtu.remoteHost = localAddr; paramBlock.ioCRefNum = macTCPRefNum; err = PBControlSync((ParmBlkPtr) ¶mBlock); if (err == noErr) { mtuSize = paramBlock.csParam.mtu.mtuSize; } else { mtuSize = 1024; /* guess */ ResolverTerminate(); return -1; } resolverDoneProc = NewResultProc(ResolverCompletionRoutine); tcpCloseDoneProc = NewTCPIOCompletionProc(TCPCloseCompletionRoutine); tcpConnectDoneProc = NewTCPIOCompletionProc(TCPConnectCompletionRoutine); tcpNotifyProc = NewTCPNotifyProc(TCPNotificationRoutine); tcpSendDoneProc = NewTCPIOCompletionProc(TCPSendCompletionRoutine); InstallExitHandler(); /* Success! Create a session ID that is unlikely to be repeated. Zero is never used for a valid session number. */ thisNetSession = clock() + time(NULL); if (thisNetSession == 0) thisNetSession = 1; /* don't use 0 */ return 0; } void sqNetworkShutdown(void) { /* shut down the network */ if (thisNetSession == 0) return; /* noop if network is already shut down */ SetToolTrapAddress(oldExitHandlerProc, _ExitToShell); ResolverTerminate(); DestroyAllOpenSockets(); thisNetSession = 0; } /*** Squeak Generic Socket Functions ***/ void sqSocketAbortConnection(SocketPtr s) { if (!SocketValid(s)) return; if (s->socketType == TCPSocketType) { TCPSockAbortConnection((TCPSockPtr) s->privateSocketPtr); return; } if (s->socketType == ListenerQueueType) { ((ListenerQueuePtr) s->privateSocketPtr)->closed = true; /* set closed flag */ return; } success(false); } void sqSocketCloseConnection(SocketPtr s) { if (!SocketValid(s)) return; if (s->socketType == TCPSocketType) { TCPSockCloseConnection((TCPSockPtr) s->privateSocketPtr); return; } if (s->socketType == ListenerQueueType) { ((ListenerQueuePtr) s->privateSocketPtr)->closed = true; /* set closed flag */ return; } success(false); } int sqSocketConnectionStatus(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return ((TCPSockPtr) s->privateSocketPtr)->connectStatus; } if (s->socketType == UDPSocketType) { return ((UDPSockPtr) s->privateSocketPtr)->connectStatus; } if (s->socketType == ListenerQueueType) { return ListenerQueueStatus((ListenerQueuePtr) s->privateSocketPtr); } success(false); } void sqSocketConnectToPort(SocketPtr s, int addr, int port) { if (!SocketValid(s)) return; if (!PortNumberValid(port)) return; if (s->socketType == TCPSocketType) { TCPSockConnectTo((TCPSockPtr) s->privateSocketPtr, addr, port); return; } if (s->socketType == UDPSocketType) { UDPSockConnectTo((UDPSockPtr) s->privateSocketPtr, addr, port); return; } success(false); } void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex) { TCPSockPtr tcpSock = nil; UDPSockPtr udpSock = nil; /* reference args to suppress compiler warnings about unused variables */ s; netType; recvBufSize; sendBufSize; s->sessionID = 0; if (socketType == TCPSocketType) { tcpSock = TCPSockCreate(); if (tcpSock == nil) { success(false); } else { tcpSock->semaIndex = semaIndex; tcpSock->next = openTCPSockets; openTCPSockets = tcpSock; s->sessionID = thisNetSession; s->socketType = TCPSocketType; s->privateSocketPtr = tcpSock; } return; } if (s->socketType == UDPSocketType) { udpSock = UDPSockCreate(); if (udpSock == nil) { success(false); } else { udpSock->semaIndex = semaIndex; udpSock->next = openUDPSockets; openUDPSockets = udpSock; s->sessionID = thisNetSession; s->socketType = UDPSocketType; s->privateSocketPtr = udpSock; } return; } success(false); } void sqSocketDestroy(SocketPtr s) { if (!SocketValid(s)) return; if (s->socketType == TCPSocketType) { TCPSockDestroy((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { UDPSockDestroy((UDPSockPtr) s->privateSocketPtr); } if (s->socketType == ListenerQueueType) { ListenerQueueDestroy((ListenerQueuePtr) s->privateSocketPtr); } s->sessionID = 0; s->socketType = -1; s->privateSocketPtr = nil; } int sqSocketError(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return ((TCPSockPtr) s->privateSocketPtr)->lastError; } if (s->socketType == UDPSocketType) { return ((UDPSockPtr) s->privateSocketPtr)->lastError; } if (s->socketType == ListenerQueueType) { return 0; /* ListenerQueue's themselves never get an error */ } } void sqSocketListenOnPort(SocketPtr s, int port) { if (!SocketValid(s)) return; if (!PortNumberValid(port)) return; if (s->socketType == TCPSocketType) { TCPSockListenOn((TCPSockPtr) s->privateSocketPtr, port); return; } if (s->socketType == UDPSocketType) { UDPSockListenOn((UDPSockPtr) s->privateSocketPtr, port); return; } success(false); } int sqSocketLocalAddress(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockLocalAddress((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { return UDPSockLocalAddress((UDPSockPtr) s->privateSocketPtr); } if (s->socketType == ListenerQueueType) { return ((ListenerQueuePtr) s->privateSocketPtr)->localAddress; } success(false); } int sqSocketLocalPort(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockLocalPort((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { return UDPSockLocalPort((UDPSockPtr) s->privateSocketPtr); } if (s->socketType == ListenerQueueType) { return ((ListenerQueuePtr) s->privateSocketPtr)->localPort; } success(false); } int sqSocketReceiveDataAvailable(SocketPtr s) { if (!SocketValid(s)) return 0; if (s->socketType == TCPSocketType) { return TCPSockDataAvailable((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { return ((UDPSockPtr) s->privateSocketPtr)->dataAvailable; } success(false); } int sqSocketReceiveDataBufCount(SocketPtr s, int buf, int bufSize) { int adjustedBufSize = bufSize > 0xFFFF ? 0xFFFF : bufSize; if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockRecvData((TCPSockPtr) s->privateSocketPtr, (char *) buf, adjustedBufSize); } if (s->socketType == UDPSocketType) { return UDPSockRecvData((UDPSockPtr) s->privateSocketPtr, (char *) buf, adjustedBufSize); } success(false); } int sqSocketRemoteAddress(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockRemoteAddress((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { return UDPSockRemoteAddress((UDPSockPtr) s->privateSocketPtr); } success(false); } int sqSocketRemotePort(SocketPtr s) { if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockRemotePort((TCPSockPtr) s->privateSocketPtr); } if (s->socketType == UDPSocketType) { return UDPSockRemotePort((UDPSockPtr) s->privateSocketPtr); } success(false); } int sqSocketSendDataBufCount(SocketPtr s, int buf, int bufSize) { int adjustedBufSize = bufSize > 0xFFFF ? 0xFFFF : bufSize; if (!SocketValid(s)) return -1; if (s->socketType == TCPSocketType) { return TCPSockSendData((TCPSockPtr) s->privateSocketPtr, (char *) buf, adjustedBufSize); } if (s->socketType == UDPSocketType) { return UDPSockSendData((UDPSockPtr) s->privateSocketPtr, (char *) buf, adjustedBufSize); } success(false); } int sqSocketSendDone(SocketPtr s) { if (!SocketValid(s)) return 1; if (s->socketType == TCPSocketType) { return !((TCPSockPtr) s->privateSocketPtr)->sendInProgress; } if (s->socketType == UDPSocketType) { return !((UDPSockPtr) s->privateSocketPtr)->sendInProgress; } success(false); } /*** Resolver Functions ***/ void sqResolverAbort(void) { int semaIndex; /* abort the current request */ if (resolver.status == RESOLVER_BUSY) { semaIndex = resolver.semaIndex; ResolverTerminate(); ResolverInitialize(semaIndex); } } void sqResolverAddrLookupResult(char *nameForAddress, int nameSize) { /* copy the name found by the last address lookup into the given string */ memcpy(nameForAddress, resolver.hostInfo.cname, nameSize); } int sqResolverAddrLookupResultSize(void) { return strlen(resolver.hostInfo.cname); } int sqResolverError(void) { return resolver.error; } int sqResolverLocalAddress(void) { struct GetAddrParamBlock paramBlock; if (resolver.localAddress == 0) { resolver.remoteAddress = 0; memset(¶mBlock, 0, sizeof(struct GetAddrParamBlock)); paramBlock.ioResult = 1; paramBlock.csCode = ipctlGetAddr; paramBlock.ioCRefNum = macTCPRefNum; PBControlSync((ParmBlkPtr) ¶mBlock); if (paramBlock.ioResult == noErr) { resolver.status = RESOLVER_SUCCESS; resolver.localAddress = paramBlock.ourAddress; resolver.error = noErr; } else { resolver.status = RESOLVER_ERROR; resolver.error = paramBlock.ioResult; } } else { resolver.status = RESOLVER_SUCCESS; resolver.error = noErr; } return resolver.localAddress; } int sqResolverNameLookupResult(void) { /* return the result of the last successful lookup */ return resolver.remoteAddress; } void sqResolverStartAddrLookup(int address) { OSErr err; if (resolver.status == RESOLVER_BUSY) return; resolver.status = RESOLVER_BUSY; resolver.error = noErr; memset(&resolver.hostInfo, 0, sizeof(hostInfo)); err = AddrToName(address, &resolver.hostInfo, resolverDoneProc, (char *) &resolver); if (err == noErr) { /* address was in cache; lookup is already done */ resolver.status = RESOLVER_SUCCESS; } else { if (err != cacheFault) { /* real error */ resolver.status = RESOLVER_ERROR; resolver.error = err; } } } void sqResolverStartNameLookup(char *hostName, int nameSize) { char name[501]; int len; OSErr err; if (resolver.status == RESOLVER_BUSY) return; len = ((nameSize <= 500) ? nameSize : 500); memcpy(name, hostName, len); name[len] = '\0'; resolver.status = RESOLVER_BUSY; resolver.error = noErr; memset(&resolver.hostInfo, 0, sizeof(hostInfo)); err = StrToAddr(name, &resolver.hostInfo, resolverDoneProc, (char *) &resolver); if (err == noErr) { /* address was in cache; lookup is already done */ resolver.status = RESOLVER_SUCCESS; resolver.remoteAddress = resolver.hostInfo.addr[0]; } else { if (err != cacheFault) { /* real error */ resolver.status = RESOLVER_ERROR; resolver.error = err; } } } int sqResolverStatus(void) { return resolver.status; } /*** Private Resolver Functions ***/ int ResolverInitialize(int resolverSemaIndex) { if (resolver.status != RESOLVER_UNINITIALIZED) { ResolverTerminate(); } memset(&resolver, 0, sizeof(ResolverStatusRec)); resolver.status = RESOLVER_UNINITIALIZED; resolver.error = OpenResolver(nil); if (resolver.error != noErr) { resolver.status = RESOLVER_ERROR; return resolver.error; } resolver.semaIndex = resolverSemaIndex; resolver.status = RESOLVER_SUCCESS; return noErr; } static pascal void ResolverCompletionRoutine(struct hostInfo *hostInfoPtr, char *userDataPtr) { ResolverStatusPtr r = (ResolverStatusPtr) userDataPtr; if ((r == null) || (r->status != RESOLVER_BUSY)) return; /* completion routine */ if (r->hostInfo.rtnCode == noErr) { r->status = RESOLVER_SUCCESS; r->remoteAddress = hostInfoPtr->addr[0]; } else { r->status = RESOLVER_ERROR; r->error = hostInfoPtr->rtnCode; } signalSemaphoreWithIndex(r->semaIndex); } void ResolverTerminate(void) { CloseResolver(); memset(&resolver, 0, sizeof(ResolverStatusRec)); resolver.status = RESOLVER_UNINITIALIZED; } /*** Squeak TCP Socket Listen/Accept Functions ***/ ListenerQueuePtr ListenerQueueCreate(TCPSockPtr tcpSocket, int port, int backlogSize) { ListenerQueuePtr listener; /* allocate a new ListenerQueue */ listener = (ListenerQueuePtr) malloc(sizeof(ListenerQueueRec)); if (listener == nil) return nil; /* initialize it */ listener->localAddress = TCPSockLocalAddress(tcpSocket); listener->localPort = port; listener->closed = false; listener->semaIndex = tcpSocket->semaIndex; listener->desiredQueueLength = (backlogSize < 1) ? 1 : backlogSize; listener->waitingSockets = nil; /* add the given socket to the new ListenerQueue */ tcpSocket->nextInListenerQueue = listener->waitingSockets; listener->waitingSockets = tcpSocket; TCPSockListenOn(tcpSocket, listener->localPort); /* create additional waiting sockets in necessary to fill the ListenerQueue */ FillListenerQueue(listener); return listener; } void ListenerQueueDestroy(ListenerQueuePtr listener) { TCPSockPtr thisSock, nextSock; /* destroy all sockets in this ListenerQueue's waiting socket list */ thisSock = listener->waitingSockets; while (thisSock != nil) { nextSock = thisSock->nextInListenerQueue; TCPSockDestroy(thisSock); thisSock = nextSock; } /* clear a few fields, just in case of a dangling reference */ listener->closed = true; listener->semaIndex = 0; listener->waitingSockets = nil; /* free the ListenerQueue */ free(listener); } int ListenerQueueStatus(ListenerQueuePtr listener) { TCPSockPtr sock; if (listener == nil) { success(false); return Unconnected; } if (listener->closed) return Unconnected; /* check for zombie sockets; if there is one, clean up the queue */ if (FindZombieSocket(listener) != nil) { FillListenerQueue(listener); /* removes zombies and refills queue */ } /* scan queue for a connected socket */ sock = FindConnectedSocket(listener); return (sock == nil) ? WaitingForConnection : Connected; } void FillListenerQueue(ListenerQueuePtr listener) { TCPSockPtr sock, newSock; int count, socksToAdd; /* remove from the queue and destroy any zombie sockets */ while ((sock = FindZombieSocket(listener)) != nil) { RemoveSocketFromListenerQueue(sock, listener); TCPSockDestroy(sock); } /* count the number of remaining sockets */ count = 0; sock = listener->waitingSockets; while (sock != nil) { count++; sock = sock->nextInListenerQueue; } /* create enough new sockets up to fill ListenerQueue to desired size */ socksToAdd = listener->desiredQueueLength - count; while (socksToAdd > 0) { newSock = TCPSockCreate(); if (newSock!= nil) { /* set semaphore of the new socket*/ newSock->semaIndex = listener->semaIndex; /* record new socket in openTCPSockets */ newSock->next = openTCPSockets; openTCPSockets = newSock; /* add new socket to the listener queue and start it listening */ newSock->nextInListenerQueue = listener->waitingSockets; listener->waitingSockets = newSock; TCPSockListenOn(newSock, listener->localPort); } socksToAdd--; } } TCPSockPtr FindConnectedSocket(ListenerQueuePtr listener) { /* Return the first connected socket in the given ListenerQueue, or nil if there isn't one. */ TCPSockPtr sock; sock = listener->waitingSockets; while (sock != nil) { if (sock->connectStatus == Connected) return sock; sock = sock->nextInListenerQueue; } return nil; } TCPSockPtr FindZombieSocket(ListenerQueuePtr listener) { /* Return the first socket in the given ListenerQueue that is not connected or waiting for a connection (we call this a zombie), or nil if there isn't one. Zombies are created when a connection is made but broken again before an accept has been done. Since a zombie are no longer waiting for a connection, it takes the place of listening socket. If the queue became filled with zombies no connections could get through. Thus, zombies must be eliminated. As the saying goes: "the only good zombie is a dead zombie." */ TCPSockPtr sock; sock = listener->waitingSockets; while (sock != nil) { if ((sock->connectStatus != WaitingForConnection) && (sock->connectStatus != Connected)) return sock; sock = sock->nextInListenerQueue; } return nil; } void sqSocketAcceptFromRecvBytesSendBytesSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex) { /* Accept a connection for the given server socket. The server socket must have been turned into a listener queue via sqSocketListenOnPortBacklogSize(). If successful, s is initialized to newly connected socket using the given paramenters, and a new listening socket will be created and added to the ListenerQueue to maintain the desired queue length. Note that MacTCP allows multiple sockets to be listening on the same port number and, indeed, this is the only way to support the Unix socket notion of a socket backlog. */ ListenerQueuePtr listener; TCPSockPtr connectedSock; /* server socket must be a valid ListenerQueue */ if ((serverSocket == nil) || (serverSocket->sessionID != thisNetSession) || (serverSocket->socketType != ListenerQueueType) || (serverSocket->privateSocketPtr == nil)) { success(false); return; } /* result socket must be a new, unintialized socket */ if ((s == nil) || (s->sessionID != 0) || (s->socketType != 0) || (s->privateSocketPtr != nil)) { success(false); return; } /* look for a connected socket */ listener = (ListenerQueuePtr) serverSocket->privateSocketPtr; connectedSock = FindConnectedSocket(listener); if (connectedSock == nil) { success(false); } else { /* remove connected socket from the listener queue */ RemoveSocketFromListenerQueue(connectedSock, listener); /* fill in the result socket handle */ connectedSock->semaIndex = semaIndex; s->sessionID = thisNetSession; s->socketType = TCPSocketType; s->privateSocketPtr = connectedSock; } /* ensure that the queue has the desired number of listenening sockets */ FillListenerQueue(listener); } void RemoveSocketFromListenerQueue(TCPSockPtr sockToRemove, ListenerQueuePtr listener) { TCPSockPtr lastSock, thisSock; if (sockToRemove == nil) return; if (listener->waitingSockets == sockToRemove) { listener->waitingSockets = sockToRemove->nextInListenerQueue; sockToRemove->nextInListenerQueue = nil; return; } lastSock = listener->waitingSockets; thisSock = lastSock->nextInListenerQueue; while (thisSock != nil) { if (thisSock == sockToRemove) { lastSock->nextInListenerQueue = sockToRemove->nextInListenerQueue; sockToRemove->nextInListenerQueue = nil; return; } lastSock = thisSock; thisSock = lastSock->nextInListenerQueue; } } void sqSocketListenOnPortBacklogSize(SocketPtr s, int port, int backlogSize) { TCPSockPtr tcpSocket; ListenerQueuePtr listener; /* s must be an TCP socket that is initialized but unconnected */ if ((!SocketValid(s)) || (s->socketType != TCPSocketType)) { success(false); return; } tcpSocket = (TCPSockPtr) s->privateSocketPtr; if (tcpSocket->connectStatus != Unconnected) { success(false); return; } /* make sure the port number is in range */ if (!PortNumberValid(port)) {; success(false); return; } /* create a new listener on the given with the given backlog size */ listener = ListenerQueueCreate((TCPSockPtr) s->privateSocketPtr, port, backlogSize); if (listener == nil) { success(false); return; } /* mutate s into a listener socket: replace the original TCP socket in s with the new listener, and change the type of s to ListenerQueueType */ s->socketType = ListenerQueueType; s->privateSocketPtr = listener; } /*** Private TCP Socket Functions ***/ void * TCPSockCreate(void) { TCPiopb paramBlock; TCPSockPtr s = nil; int minRcvBufSize, rcvBufSize; OSErr err = noErr; rcvBufSize = RecvBufferSize; minRcvBufSize = (4 * mtuSize) + 1024; if (rcvBufSize < minRcvBufSize) rcvBufSize = minRcvBufSize; s = (TCPSockPtr) malloc(sizeof(TCPSockRec) + rcvBufSize); if (s == nil) return nil; /* allocation failed */ memset(s, 0, sizeof(TCPSockRec) + rcvBufSize); InitTCPCmd(TCPCreate, nil, ¶mBlock); paramBlock.csParam.create.rcvBuff = s->rcvBuf; paramBlock.csParam.create.rcvBuffLen = rcvBufSize; paramBlock.csParam.create.notifyProc = tcpNotifyProc; paramBlock.csParam.create.userDataPtr = (Ptr) s; err = PBControlSync((ParmBlkPtr) ¶mBlock); if (err != noErr) { free(s); return nil; } s->tcpStream = paramBlock.tcpStream; return s; } int TCPSockDataAvailable(TCPSockPtr s) { TCPiopb paramBlock; OSErr err = noErr; if ((s == nil) || (s->tcpStream == nil)) { return false; /* already destroyed */ } InitTCPCmd(TCPStatus, s->tcpStream, ¶mBlock); err = PBControlSync((ParmBlkPtr) ¶mBlock); if (err != noErr) { return 0; } return paramBlock.csParam.status.amtUnreadData > 0; } void TCPSockDestroy(TCPSockPtr s) { TCPiopb paramBlock; OSErr err = noErr; if ((s == nil) || (s->tcpStream == nil)) { return; /* already destroyed */ } InitTCPCmd(TCPRelease, s->tcpStream, ¶mBlock); err = PBControlSync((ParmBlkPtr) ¶mBlock); TCPSockRemoveFromOpenList(s); s->tcpStream = nil; free(s); } int TCPSockLocalAddress(TCPSockPtr s) { TCPiopb paramBlock; if ((s == nil) || (s->tcpStream == nil)) { return 0; /* already destroyed */ } InitTCPCmd(TCPStatus, s->tcpStream, ¶mBlock); s->lastError = PBControlSync((ParmBlkPtr) ¶mBlock); if (s->lastError != noErr) { return 0; } return paramBlock.csParam.status.localHost; } int TCPSockLocalPort(TCPSockPtr s) { TCPiopb paramBlock; if ((s == nil) || (s->tcpStream == nil)) { return 0; /* already destroyed */ } InitTCPCmd(TCPStatus, s->tcpStream, ¶mBlock); s->lastError = PBControlSync((ParmBlkPtr) ¶mBlock); if (s->lastError != noErr) { return 0; } return paramBlock.csParam.status.localPort; } int TCPSockRemoteAddress(TCPSockPtr s) { TCPiopb paramBlock; if ((s == nil) || (s->tcpStream == nil)) { return 0; /* already destroyed */ } InitTCPCmd(TCPStatus, s->tcpStream, ¶mBlock); s->lastError = PBControlSync((ParmBlkPtr) ¶mBlock); if (s->lastError != noErr) { return 0; } return paramBlock.csParam.status.remoteHost; } int TCPSockRemotePort(TCPSockPtr s) { TCPiopb paramBlock; if ((s == nil) || (s->tcpStream == nil)) { return 0; /* already destroyed */ } InitTCPCmd(TCPStatus, s->tcpStream, ¶mBlock); s->lastError = PBControlSync((ParmBlkPtr) ¶mBlock); if (s->lastError != noErr) { return 0; } return paramBlock.csParam.status.remotePort; } void TCPSockRemoveFromOpenList(TCPSockPtr s) { TCPSockPtr thisSock, nextSock, previousSock; previousSock = nil; for (thisSock = openTCPSockets; thisSock != nil; thisSock = nextSock) { nextSock = thisSock->next; if (thisSock == s) { if (previousSock == nil) { openTCPSockets = nextSock; } else { previousSock->next = nextSock; } break; } previousSock = thisSock; } } void TCPSockConnectTo(TCPSockPtr s, int addr, int port) { if ((s == nil) || (s->tcpStream == nil)) return; /* socket destroyed */ InitTCPCmd(TCPActiveOpen, s->tcpStream, &s->tcpPB); s->tcpPB.csParam.open.remoteHost = addr; s->tcpPB.csParam.open.remotePort = port; s->connectStatus = WaitingForConnection; s->tcpPB.ioCompletion = tcpConnectDoneProc; s->lastError = PBControlAsync((ParmBlkPtr) &s->tcpPB); if (s->lastError != noErr) { s->connectStatus = Unconnected; } } void TCPSockListenOn(TCPSockPtr s, int port) { if ((s == nil) || (s->tcpStream == nil)) return; /* socket destroyed */ InitTCPCmd(TCPPassiveOpen, s->tcpStream, &s->tcpPB); s->tcpPB.csParam.open.localPort = port; s->connectStatus = WaitingForConnection; s->tcpPB.ioCompletion = tcpConnectDoneProc; s->lastError = PBControlAsync((ParmBlkPtr) &s->tcpPB); if (s->lastError != noErr) { s->connectStatus = Unconnected; } } void TCPSockCloseConnection(TCPSockPtr s) { /* Note: This operation uses a dedicated parameter block so that it can be invoked even in the previous send is not yet complete. It will eventually use a completion routine to delete the socket automatically. For now, this is the client's responsibility. */ if ((s == nil) || (s->tcpStream == nil)) return; /* socket destroyed */ InitTCPCmd(TCPClose, s->tcpStream, &s->closePB); // s->closePB.ioCompletion = tcpCloseDoneProc; s->connectStatus = ThisEndClosed; // xxx remove when making this async s->lastError = PBControlSync((ParmBlkPtr) &s->closePB); } void TCPSockAbortConnection(TCPSockPtr s) { TCPiopb paramBlock; if ((s == nil) || (s->tcpStream == nil)) return; /* socket destroyed */ InitTCPCmd(TCPAbort, s->tcpStream, ¶mBlock); s->lastError = PBControlSync((ParmBlkPtr) ¶mBlock); s->connectStatus = Unconnected; } int TCPSockRecvData(TCPSockPtr s, char *buf, int bufSize) { TCPiopb paramBlock; /* use local parameter block since send may be using one in socket */ OSErr err = noErr; int bytesRead; if ((s->connectStatus == Unconnected) || (s->connectStatus == WaitingForConnection)) { success(false); return 0; /* fail if not connected */ } if (!TCPSockDataAvailable(s)) return 0; /* no data available */ InitTCPCmd(TCPRcv, s->tcpStream, ¶mBlock); paramBlock.csParam.receive.commandTimeoutValue = 1; /* finish in one second, data or not */ paramBlock.csParam.receive.rcvBuff = buf; paramBlock.csParam.receive.rcvBuffLen = bufSize; s->lastError = noErr; err = PBControlSync((ParmBlkPtr) ¶mBlock); /* synchronous */ if (err == noErr) { bytesRead = paramBlock.csParam.receive.rcvBuffLen; } else { /* if err == commandTimeout, no data was available */ bytesRead = 0; if (!((err == commandTimeout) || (err == connectionClosing))) { s->lastError = err; } } s->dataAvailable = (bytesRead != 0); /* if we got data, there may be more */ return bytesRead; } int xxxGOODTCPSockSendData(TCPSockPtr s, char *buf, int bufSize); int xxxGOODTCPSockSendData(TCPSockPtr s, char *buf, int bufSize) { int sendCount; struct wdsEntry wds[2]; buf; /* xxx avoid compiler complaint about unreferenced vars */ /* copy client data into sendBuf to allow asynchronous send */ sendCount = (bufSize <= SendBufferSize) ? bufSize : SendBufferSize; //xxx memcpy(s->sendBuf, buf, sendCount); /* set up WDS entry; zero length marks end of chunk list */ wds[0].length = sendCount; //xxx wds[0].ptr = s->sendBuf; wds[1].length = 0; InitTCPCmd(TCPSend, s->tcpStream, &s->tcpPB); s->tcpPB.csParam.send.wdsPtr = (Ptr) &wds; s->tcpPB.csParam.send.pushFlag = true; s->sendInProgress = true; s->tcpPB.ioCompletion = tcpSendDoneProc; s->lastError = PBControlAsync((ParmBlkPtr) &s->tcpPB); if (s->lastError != noErr) { s->sendInProgress = false; return 0; } return sendCount; } int TCPSockSendData(TCPSockPtr s, char *buf, int bufSize) { TCPSendBufPtr sendBuf; int sendCount; if ((s->connectStatus == Unconnected) || (s->connectStatus == WaitingForConnection)) { success(false); return 0; /* fail if not connected */ } sendBuf = &sendBufPool[nextSendBuf++]; if (nextSendBuf >= SendBufCount) nextSendBuf = 0; sendBuf->mySocket = s; /* copy client data into sendBuf to allow asynchronous send */ sendCount = (bufSize <= SendBufferSize) ? bufSize : SendBufferSize; memcpy(sendBuf->data, buf, sendCount); /* set up WDS entry; zero length marks end of chunk list */ sendBuf->wds[0].length = sendCount; sendBuf->wds[0].ptr = sendBuf->data; sendBuf->wds[1].length = 0; InitTCPCmd(TCPSend, s->tcpStream, &sendBuf->tcpPB); sendBuf->tcpPB.csParam.send.wdsPtr = (Ptr) &sendBuf->wds; sendBuf->tcpPB.csParam.send.pushFlag = true; sendBuf->tcpPB.ioCompletion = tcpSendDoneProc; s->sendInProgress = true; s->lastError = PBControlAsync((ParmBlkPtr) &sendBuf->tcpPB); if (s->lastError != noErr) { s->sendInProgress = false; return 0; } return sendCount; } /*** Private General Utilities ***/ void DestroyAllOpenSockets(void) { while (openTCPSockets != nil) { TCPSockDestroy(openTCPSockets); /* removes socket from the list */ } while (openUDPSockets != nil) { UDPSockDestroy(openUDPSockets); /* removes socket from the list */ } } void InstallExitHandler(void) { /* Install a handler to release all open sockets when terminating this application. The handler will be called even if you type 'es' to MacsBug or use Command-Option-Escape for force the program to exit. The handler is only installed the first time the network is initialized. */ if (oldExitHandlerProc == nil) { oldExitHandlerProc = GetToolTrapAddress(_ExitToShell); myExitHandlerProc = NewRoutineDescriptor((ProcPtr) MyExitHandler, kPascalStackBased, GetCurrentISA()); SetToolTrapAddress(myExitHandlerProc, _ExitToShell); } } void MyExitHandler(void) { SetCurrentA5(); if (thisNetSession == 0) return; /* noop if network is already shut down */ SetToolTrapAddress(oldExitHandlerProc, _ExitToShell); ResolverTerminate(); DestroyAllOpenSockets(); ExitToShell(); } int PortNumberValid(int port) { if (port < 0xFFFF) { return true; } success(false); return false; } int SocketValid(SocketPtr s) { if ((s != NULL) && (s->privateSocketPtr != NULL) && (s->sessionID == thisNetSession)) { if (s->socketType == TCPSocketType) { if (((TCPSockPtr) s->privateSocketPtr)->tcpStream != nil) { return true; } } return true; } success(false); return false; } /*** Private TCP Utilities ***/ void InitTCPCmd(int cmd, StreamPtr tcpStream, TCPiopb *paramBlkPtr) { memset(paramBlkPtr, 0, sizeof(TCPiopb)); paramBlkPtr->csCode = cmd; paramBlkPtr->tcpStream = tcpStream; paramBlkPtr->ioCRefNum = macTCPRefNum; paramBlkPtr->ioResult = 1; } void TCPCloseCompletionRoutine(struct TCPiopb *pbPtr) { TCPSockPtr s = (TCPSockPtr) pbPtr; s->lastError = s->tcpPB.ioResult; if (s->lastError == noErr) { if (s->connectStatus == OtherEndClosed) { s->connectStatus = Unconnected; } else { s->connectStatus = ThisEndClosed; } } signalSemaphoreWithIndex(s->semaIndex); } void TCPConnectCompletionRoutine(struct TCPiopb *pbPtr) { TCPSockPtr s = (TCPSockPtr) pbPtr; s->lastError = s->tcpPB.ioResult; if (s->lastError == noErr) { s->connectStatus = Connected; } else { s->connectStatus = Unconnected; } signalSemaphoreWithIndex(s->semaIndex); } pascal void TCPNotificationRoutine( StreamPtr s, unsigned short eventCode, Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg) { /* called when data arrives or stream status changes */ /* reference args to suppress compiler warnings about unused variables */ s; terminReason; icmpMsg; if (eventCode == TCPDataArrival) { TCPSockPtr tcpSock = (TCPSockPtr) userDataPtr; tcpSock->dataAvailable = true; signalSemaphoreWithIndex(tcpSock->semaIndex); return; } if (eventCode == TCPClosing) { TCPSockPtr tcpSock = (TCPSockPtr) userDataPtr; if (tcpSock->connectStatus == ThisEndClosed) { tcpSock->connectStatus = Unconnected; } else { tcpSock->connectStatus = OtherEndClosed; } signalSemaphoreWithIndex(tcpSock->semaIndex); return; } if (eventCode == TCPTerminate) { TCPSockPtr tcpSock = (TCPSockPtr) userDataPtr; tcpSock->connectStatus = Unconnected; signalSemaphoreWithIndex(tcpSock->semaIndex); return; } } void TCPSendCompletionRoutine(struct TCPiopb *pbPtr) { //xxx TCPSockPtr s = (TCPSockPtr) pbPtr; TCPSockPtr s = ((TCPSendBufPtr) pbPtr)->mySocket; s->lastError = s->tcpPB.ioResult; s->sendInProgress = false; signalSemaphoreWithIndex(s->semaIndex); } /*** Private UDP Socket Functions (not yet implemented) ***/ void * UDPSockCreate(void) { return nil; } void UDPSockDestroy(UDPSockPtr s) { s; } int UDPSockLocalAddress(UDPSockPtr s) { s; } int UDPSockLocalPort(UDPSockPtr s) { s; } int UDPSockRemoteAddress(UDPSockPtr s) { s; } int UDPSockRemotePort(UDPSockPtr s) { s; } void UDPSockConnectTo(UDPSockPtr s, int addr, int port) { s; addr; port; } void UDPSockListenOn(UDPSockPtr s, int port) { s; port; } int UDPSockRecvData(UDPSockPtr s, char *buf, int bufSize) { s; buf; bufSize; } int UDPSockSendData(UDPSockPtr s, char *buf, int bufSize) { s; buf; bufSize; } #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SocketPlugin/sqMacNetwork.c ================================================ #if TARGET_API_MAC_CARBON #include #else #include #include #include #if defined(__MWERKS__) #include #else #include #endif #include #include #include #if !TARGET_API_MAC_CARBON #ifndef NewOTNotifyUPP typedef struct OTConfiguration* OTConfigurationRef; #define OTNotifyUPP OTNotifyProcPtr #define NewOTNotifyUPP(userRoutine) userRoutine #define DisposeOTNotifyUPP(userRoutine) #endif #endif #endif #include "sq.h" #include "SocketPlugin.h" //#define OTSERVER /* May 1st 2000 An Open Transport 2.0 version of source code for TCP/IP & UDP support Some of this the code was descended from Apple sample source written by: Eric Okholm However getting it to work was done by John M Mcintosh of Corporate Smalltalk Consulting Ltd johnmci@smalltalkconsulting.com http://www.smalltalkconsulting.com In May of 2000 under contract to Disney Some of the original source code was written by John Maloney of Disney thoughout the 1990's The basic intent was to make the code fully interrupt driven No limits.... Well maybe we throttle read buffers to some parcel of memory to prevent us from using all the memory on the box. Sends depend on lowerlayer buffering/flow control. Testing from a 500Mhz PowerBook showed we could saturate a 100MB ethernet when sending data oneway. UDP and TCP/IP are all supported. Note for TCP we turn on two options IP_REUSEADDR, and IP_KEEPALIVE. We do NOT handle T_EXDATA data V1.0 May 18th 2000, JMM (TCP/IP and UDP) V1.1 May 19th 2000, JMM Cleanup V1.2 may 20th 2000, JMM UDP free buffer cleanup, relook at resolver terminate to fix crash V1.3 may 23rd 2000, JMM fix T_UDERR crash V1.3.1 may 24th 2000, JMM UDP work V1.3.2 may 25th 2000, JMM socket options work V1.3.3 may 27th 2000, JMM rewrote resolver V1.3.4 Jun 7th 2000, JMM some integration V1.3.5 Jun 9th 2000, JMM Dan Ingalls found some interesting bugs with a T_GODATA on T_CONNECT. V1.3.6 Jun 10th 2000, JMM fix a fatal but in close/close pattern I made on the 9th. V1.3.7 Aug 1st 2000, JMM Some carbon work, reviewed open non-existent port logic fix so unavailable port causes immediate failure V1.3.8 Aug 29th 2000, JMM Fix problem with recusion on make me an EP. v1.3.9 Sept 28th 2000, JMM Problem with accept somewhere (so harden code) v1.3.10 Oct 4th 2000, JMM Issue with destory and free buffers, and disconnect on read with buffer restriction v1.3.11 Nov 11th 2000, JMM extra buffer for server version v1.3.12 Jan 2001, Karl Goiser Carbon changes v1.3.13 Sept 2002, JMM fixes for wildcard port binding, and IP_ADD_MEMBERSHIP logic v1.4.00 Feb 2003, JMM watch out for async port fetch info not working under os-x V1.5.00 Dec 2003, JMM add sqSocketListenOnPortBacklogSizeInterface logic Notes beware semaphore's lurk for socket support. Three semaphores lives in Smalltalk, waiting for connect/disconnect/listen, sending data, and receiving data. When to tap the semaphore is based on inferences driven from the smalltalk code. We really need a call to tell us intent. waitForDisconnectUntil: via closeAndDestroy: after primSocketCloseConnection: waitForDataUntil: Usually before primitiveSocketReceiveDataBufCount: after checking SocketReceiveDataAvailable waitForSendDoneUntil: via sendData: or sendSomeData:startIndex;count: before calls to primitiveSocketSendDataBufCount waitForConnectionUntil: via waitForAcceptUntil and many places afer doing primitiveSocketConnectToPort */ /*** Socket Type Constants ***/ #define TCPSocketType 0 #define UDPSocketType 1 #define TCPListenerSocketType 2 //These are special to enable the right options for listening. Not Exposed to Smalltalk #define UDPListenerSocketType 3 //Very special not really linked to an EP structure. Not Exposed to Smalltalk /*** Resolver Status Constants ***/ #define RESOLVER_UNINITIALIZED 0 #define RESOLVER_SUCCESS 1 #define RESOLVER_BUSY 2 #define RESOLVER_ERROR 3 #define RESOLVER_NAMETOADDR 4 #define RESOLVER_ADDRTONAME 5 /*** TCP Socket Status Constants ***/ #define InvalidSocket -1 #define Unconnected 0 #define WaitingForConnection 1 #define Connected 2 #define OtherEndClosed 3 #define ThisEndClosed 4 // Overall program states enum { kProgramRunning = 1, kProgramDone = 2 }; // Bit numbers in EPInfo stateFlags fields enum { kOpenInProgressBit = 0, kUnConnected = 1, kWaitingForConnection = 2, kConnected = 3, kSendIsBlocked = 4, kOtherEndClosed = 5, kThisEndClosed = 6, kPassconBit = 7 }; // Bit numbers in EPInfo stateFlags2 fields enum { kFlushDisconnectInProgressBit = 0, kMakeEPIdle = 1, kEPIsBroken = 2, kReadFlowControl = 3, kPassconNeeded = 4, kTapSemaphore = 5, kTapSemaphoreReadData = 6, kTapSemaphoreWriteData = 7 }; // Bit numbers in EPInfo stateFlags3 fields enum { kKeepAliveOptionNeeded = 0, kSleepKilledMe = 1, kWaitingForBind = 2 }; enum { kOTVersion111 = 0x01110000, kOTVersion112 = 0x01120000, kOTVersion113 = 0x01130000, kOTVersion130 = 0x01300000 }; const kTCPKeepAliveInMinutes = 10; // 10 minutes keep alive #ifdef OTSERVER const kReadBuffersToAllocate = 256; // Memory Allocation issue how big, this means 256x mtu size * 4 But for 68K we do 1/2 size #else const kReadBuffersToAllocate = 50; // Memory Allocation issue how big, this means 50x mtu size * 4 But for 68K we do 1/2 size #endif // Endpoint Info Structure struct EPInfo { EndpointRef erf; // actual endpoint OTLink link; // link into an OT LIFO (atomic) OTLink globalLink; // link that follows all allocated EPs SInt32 outstandingSends; // number of sends outstanding OTList readBuffers; // Read buffers SInt32 bytesPendingToRead; // bytes outstanding to read SInt32 semaIndex; // semaphore index SInt32 readSemaIndex; // read semaphore SInt32 writeSemaIndex; // write semaphore SInt32 UDPMaximumSize; // max size if a UDP endpoint SInt32 lastError; // last error code UInt8 stateFlags; // various status fields UInt8 stateFlags2; // various status fields UInt8 stateFlags3; // various status fields UInt8 socketType; // type of socket, tcp, udp, or tcp/udp listener InetAddress localAddress; // local address at bind time (ignored used call to get current) InetAddress remoteAddress; // remote address at connect (ignored used call to get current) Boolean UDPMoreFlag; // UDP more of datagram flag set }; typedef struct EPInfo EPInfo; struct ReadBuffer // Structure to contain read data. { OTLink fNext; // link into an OT FIFO UInt32 readBufferSize; UInt32 readBufferOriginalSize; char * readBufferData; char * readBufferPtr; //Sliding pointer used to partial read buffer. InetAddress UDPAddress; //UDP address Boolean UDPMoreFlag; //UDP more of datagram flag set }; typedef struct ReadBuffer ReadBuffer; struct TKeepAliveOpt { UInt32 len; OTXTILevel level; OTXTIName name; UInt32 status; UInt32 tcpKeepAliveOn; UInt32 tcpKeepAliveTimer; }; typedef struct TKeepAliveOpt TKeepAliveOpt; struct TLingerOpt { UInt32 len; OTXTILevel level; OTXTIName name; UInt32 status; UInt32 tcpLingerOn; UInt32 tcpLingerTimer; }; typedef struct TLingerOpt TLingerOpt; /*** Variables ***/ extern struct VirtualMachine *interpreterProxy; EPInfo* gDNSResolver; //Our resolver SInt32 gDNSResolverStatus = RESOLVER_UNINITIALIZED; SInt32 gDNSResolverError = noErr; SInt32 gDNSResolverSemaIndex; //This gets changed at startup time. InetHostInfo gDNSHostInfo; InetDomainName gDNSAddrStr; //Length of domain names? Old code was 512, but specs say 256. InetHost gDNSAddr; SInt32 gDNSLookupType; OTConfigurationRef gCfgMastertcp = NULL; OTConfigurationRef gCfgMasterudp = NULL; OTConfigurationRef gCfgMasterListener = NULL; OTLIFO gFreeReadBuffersLIFO; // Buffers that are free to read into OTLIFO* gFreeReadBuffers = &gFreeReadBuffersLIFO; SInt32 gFreeReadBuffersCounter = 0; SInt32 gSocketsAllocated = 0; UInt32 gmtuSize = 1024; //This gets changed at startup time. SInt32 gthisNetSession = 0; //This gets changed at startup time. SInt32 gMaxConnections = 0; //This gets changed at startup time. UInt32 gOTVersion; //Gets set to OT version, to help us with special cases. SInt32 gProgramState = 0; //This gets changed at startup time. OTClientContextPtr gClientContext; OTLIFO gIdleEPLIFO[3]; OTLIFO* gIdleEPs[3]; SInt32 gIdleEPCounter[3]; OTLIFO gBrokenEPLIFO; OTLIFO* gBrokenEPs = &gBrokenEPLIFO; OTLIFO gAllEPLIFO; OTLIFO* gAllEPs = &gAllEPLIFO; OTNotifyUPP DNSNotifierUPP,NotifierSocketUPP,NotifierSocketUDPUPP,NotifierSocketListenerUPP; /*** Private TCP Socket Functions ***/ /*** Private Resolver Functions ***/ static void ResolverInitialize(); static void ResolverTerminate(void); static void ResolverStart (); /*** Other Private Functions ***/ void CFMTerminate (void); static Boolean DestroyAllOpenSockets(void); static Boolean SocketValid(SocketPtr s); static Boolean PortNumberValid(InetPort port) ; static SInt32 unmapStatus(EPInfo *); static void Recycle(); static void makeEPIdle(EPInfo *epi); static void purgeReadBuffers(EPInfo *epi); static void makeEPBrokenThenIdle(EPInfo* epi,OTResult error); static void makeEPBroken(EPInfo* epi,OTResult error); static EPInfo* getOrMakeMeAnEP(UInt8 aSocketType,short counter); static Boolean makeMeAnEP(UInt8 aSocketType); static void attemptToCloseAndDeleteThisEP (EPInfo *epi); static void makeEPUnconnected(EPInfo* epi); static void SetEPLastError(EPInfo* epi,OTResult error); static void TapAllInterestedSemaphores(EPInfo *epi); int socketInit(void); int socketShutdown(void); static pascal void DNSNotifier(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocket(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocketUDP(void* context, OTEventCode event, OTResult result, void* cookie); static pascal void NotifierSocketListener(void* context, OTEventCode event, OTResult result, void* cookie); static SInt32 internalSocketCreate(SocketPtr s, SInt32 netType, SInt32 socketType, SInt32 recvBufSize, SInt32 sendBufSize, SInt32 semaIndex, SInt32 readSemaIndex, SInt32 writeSemaIndex, UInt8 aExtraSocketHint); static Boolean EPOpen(EPInfo* epi); static Boolean EPClose(EPInfo*); static void DoListenAccept(EPInfo* acceptor,EPInfo* theServer); static void DoConnect(EPInfo* epi,InetHost addr, InetPort port); static void DoBind(EPInfo* epi,InetHost addr, InetPort port,UInt8 aExtraSocketHint, OTQLen queueDepth ); static UInt32 ReadData(EPInfo* epi, char* specialBuffer, UInt32 specialBufferSize); static OTResult SendData(EPInfo* epi, char* buffer, UInt32 size); static OSStatus doAbortConnection(EPInfo* epi); static void NoCopyReceiveWalkingBufferChain(EPInfo *epi,OTBufferInfo *bufferInfo); static UInt32 readBytes(EPInfo* epi,char *buf,UInt32 adjustedBufSize); static UInt32 readBytesUDP(EPInfo* epi,InetAddress *fromAddress, int *moreFlag, char *buf,UInt32 adjustedBufSize); static SInt32 lookupOptionName(EPInfo *epi, Boolean trueIfGet, char *aString, UInt32 value, SInt32 *result); static OTResult SetEightByteOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, char * value, SInt32 *result); static OTResult SetFourByteOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetOneByteOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetKeepAliveOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); static OTResult SetLingerOption(EPInfo* epi, Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *result); // Some diagnostic routines void JMMLogMessage(Str255 input); void JMMLogMessageAndNumber(Str255 msg,long number); void JMMWriteLog(); /*** Network Functions ***/ int socketInit() { // //Don't actually do any network work until we are newworked initialized //This prevents kicking off internet dialup connections until needed // return true; } int socketShutdown() { CFMTerminate(); return true; } int sqNetworkInit(int resolverSemaIndex) { // // Initialize the network and return 0 if successful // Loads Open transport, allocates memory for read buffers and various other tasks // SInt32 i; OSStatus err = noErr; InetInterfaceInfo interfaceInformation; UInt8 aSocketType; ReadBuffer *readBufferObject; long check68KorPPC; if (gthisNetSession != 0) return 0; /* noop if network is already initialized */ #if TARGET_API_MAC_CARBON err = InitOpenTransportInContext (kInitOTForExtensionMask, &gClientContext); #else err = InitOpenTransport(); #endif if (err) return -1; err = Gestalt(gestaltOpenTptVersions, (long*) &gOTVersion); if (err || (gOTVersion < kOTVersion112)) { // Please install Open Transport 1.1.2 or later // This might change to 1.3 since tech notes talked about // previous versions having problems with acksend logic. // return -111; } err = Gestalt(gestaltSysArchitecture, (long*) &check68KorPPC); gProgramState = kProgramRunning; // //Setup the head of the idle queues // for (i=0;i<3;i++) { gIdleEPs[i] = &gIdleEPLIFO[i]; gIdleEPs[i]->fHead = NULL; gIdleEPCounter[i] = 0; } gBrokenEPs->fHead = NULL; gFreeReadBuffers->fHead = NULL; gAllEPs->fHead = NULL; gMaxConnections = 24; // Build 8 of each of listeners, tcp, udp. DNSNotifierUPP = NewOTNotifyUPP(DNSNotifier); NotifierSocketUPP = NewOTNotifyUPP(NotifierSocket); NotifierSocketUDPUPP = NewOTNotifyUPP(NotifierSocketUDP); NotifierSocketListenerUPP = NewOTNotifyUPP(NotifierSocketListener); #if TARGET_API_MAC_CARBON gDNSResolver = (EPInfo*) OTAllocMemInContext(sizeof(EPInfo), gClientContext); #else gDNSResolver = (EPInfo*) OTAllocMem(sizeof(EPInfo)); #endif if (gDNSResolver == NULL) return -1; gDNSResolverSemaIndex = resolverSemaIndex; ResolverInitialize(); /* Get MTU and default selected host address */ OTInetGetInterfaceInfo (&interfaceInformation,kDefaultInetInterface); gmtuSize = interfaceInformation.fIfMTU; // // Open endpoints // gCfgMastertcp = OTCreateConfiguration(kTCPName); if (gCfgMastertcp == NULL) return -3; gCfgMasterudp = OTCreateConfiguration(kUDPName); if (gCfgMasterudp == NULL) return -4; gCfgMasterListener = OTCreateConfiguration("tilisten, tcp"); //Note use of special tilisten logic if (gCfgMasterListener == NULL) return -5; // //Build all our EPs, lots of work happens lower down asyncronously // aSocketType = TCPSocketType; for (i = 0; i < gMaxConnections; i++) { makeMeAnEP(aSocketType); aSocketType = ++aSocketType > 2 ? TCPSocketType : aSocketType; } #ifdef OTSERVER for (i = 0; i < 256; i++) { makeMeAnEP(TCPSocketType); } #endif // //Build storage objects for read buffers //How much memory to allocate still is a mystery // for (i=0;isuccess(false); return -25; } OTMemzero(readBufferObject,sizeof(ReadBuffer)); if (gestalt68k == check68KorPPC) readBufferObject->readBufferOriginalSize = (gmtuSize > 0) ? gmtuSize*2 : 1024; else readBufferObject->readBufferOriginalSize = (gmtuSize > 0) ? gmtuSize*4 : 1024; #if TARGET_API_MAC_CARBON readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMemInContext(readBufferObject->readBufferOriginalSize, gClientContext); #else readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMem(readBufferObject->readBufferOriginalSize); #endif if ( readBufferObject->readBufferData == nil) { interpreterProxy->success(false); return -25; } OTLIFOEnqueue(gFreeReadBuffers, &readBufferObject->fNext); gFreeReadBuffersCounter++; } /* Success! Create a session ID that is unlikely to be repeated. Zero is never used for a valid session number. */ gthisNetSession = ioLowResMSecs() + time(NULL); if (gthisNetSession == 0) gthisNetSession = 1; /* don't use 0 */ return 0; } void CFMTerminate (void) /* termination either via a CFM or Squeak call*/ { sqNetworkShutdown(); } void sqNetworkShutdown(void) { /* shut down the network */ if (gthisNetSession == 0) return; /* noop if network is already shut down */ gthisNetSession = 0; gProgramState = kProgramDone; DestroyAllOpenSockets(); #if TARGET_API_MAC_CARBON CloseOpenTransportInContext(gClientContext); #else CloseOpenTransport(); #endif } /*** Resolver Functions ***/ static void ResolverInitialize() { OSStatus err; // // Prepare to open internet services // to invoke DNR services // OTMemzero(gDNSResolver, sizeof(EPInfo)); #if TARGET_API_MAC_CARBON gDNSResolver->erf = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, gClientContext); #else gDNSResolver->erf = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err); #endif gDNSResolver->semaIndex = gDNSResolverSemaIndex; if (err != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; gDNSResolverError = err; return; } gDNSResolverStatus = RESOLVER_SUCCESS; gDNSResolverError = kOTNoError; err = OTSetAsynchronous(gDNSResolver->erf); err = OTSetNonBlocking(gDNSResolver->erf); err = OTInstallNotifier(gDNSResolver->erf, DNSNotifierUPP, gDNSResolver); } static void ResolverStart () { OSStatus err; // // Invoke DNR service Async, this meants the DNSNotifier will handle the actual // lookup and work, flags like the gDNSResolverStatus are used to indicate back // to Squeak when the work is done // if (gDNSResolver->erf == NULL) //Sleep fix, other endpoints are more explicit about this issue. ResolverInitialize(); gDNSResolverStatus = RESOLVER_BUSY; switch (gDNSLookupType) { case RESOLVER_NAMETOADDR: { err = OTInetStringToAddress((InetSvcRef)gDNSResolver->erf, gDNSAddrStr, &gDNSHostInfo); break; } case RESOLVER_ADDRTONAME: { err = OTInetAddressToName((InetSvcRef)gDNSResolver->erf, gDNSAddr, gDNSAddrStr); break; } } if (err != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; gDNSResolverError = err; } } void ResolverTerminate(void) { //JMM if the resolver is opening what happens? gDNSResolverStatus = RESOLVER_UNINITIALIZED; if (gDNSResolver->erf == NULL) return; EPClose(gDNSResolver); OTMemzero(gDNSResolver, sizeof(EPInfo)); } void sqResolverAbort(void) { // // Abort this running resolver request // if (gDNSResolverStatus == RESOLVER_BUSY) { ResolverTerminate(); ResolverInitialize(); } } void sqResolverAddrLookupResult(char *nameForAddress, int nameSize) { // // copy the name found by the last address lookup into the given string // OTMemcpy(nameForAddress, gDNSAddrStr, (UInt32) nameSize); } int sqResolverAddrLookupResultSize(void) { // // return the length of the looked up name // return (long) strlen(gDNSAddrStr); } int sqResolverError(void) { // // Return OT error number // return gDNSResolverError; } int sqResolverLocalAddress(void) { // // Watch out for dynamic changing of this information, so don't cache // InetInterfaceInfo interfaceInformation; OTInetGetInterfaceInfo (&interfaceInformation,kDefaultInetInterface); gDNSResolverStatus = RESOLVER_SUCCESS; gDNSResolverError = noErr; return (long) interfaceInformation.fAddress; } int sqResolverNameLookupResult(void) { // // Return address from last lookup // return (int) gDNSAddr; } void sqResolverStartAddrLookup(int address) { // // start process to lookup name from address // if (gDNSResolverStatus == RESOLVER_BUSY) return; gDNSAddr = (InetHost) address; gDNSLookupType = RESOLVER_ADDRTONAME; ResolverStart(); } void sqResolverStartNameLookup(char *hostName, int nameSize) { // // start process to lookup address from name // UInt32 len; if (gDNSResolverStatus == RESOLVER_BUSY) return; len = (UInt32) ((nameSize <= kMaxHostNameLen) ? nameSize : kMaxHostNameLen); //Old limit was 500 but that appeared to be wrong OTMemcpy(gDNSAddrStr, hostName, len); gDNSAddrStr[len] = '\0'; gDNSLookupType = RESOLVER_NAMETOADDR; ResolverStart(); } int sqResolverStatus(void) { // // return resolver status, this is different from resolver error code // status is the same among implementations, error is implementation dependent // return gDNSResolverStatus; } //================================ // Socket logic // void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex) { // //Old call from old image using new VM //Just make new call // sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( s, netType, socketType, recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, int netType, int socketType, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { OSErr error; netType; recvBufSize; sendBufSize; // //Create a socket given the supplied information //We don't bind the socket to a local port until //we do the connection. This of course could change? // error = internalSocketCreate( s, netType, socketType, recvBufSize, sendBufSize, semaIndex, readSemaIndex, writeSemaIndex, (UInt8) socketType); if (error != noErr) { interpreterProxy->success(false); return; } } static SInt32 internalSocketCreate( SocketPtr s, SInt32 netType, SInt32 socketType, SInt32 recvBufSize, SInt32 sendBufSize, SInt32 semaIndex, SInt32 readSemaIndex, SInt32 writeSemaIndex, UInt8 aExtraSocketHint) { // // Internal logic to open a socket for a connection or to listen // Note how we ignore buffer sizes! // EPInfo* epi; socketType; netType; recvBufSize; sendBufSize; // //Make the socket invalid and then get an idle EP //Technically we only run out of EP when we run out of memory // s->sessionID = 0; if (gProgramState != kProgramRunning ) { interpreterProxy->success(false); return -1; } epi = getOrMakeMeAnEP(aExtraSocketHint,0); if (epi == NULL) { interpreterProxy->success(false); return -1; } epi->outstandingSends = 0; epi->bytesPendingToRead = 0; epi->semaIndex = semaIndex; epi->readSemaIndex = readSemaIndex; epi->writeSemaIndex = writeSemaIndex; epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; SetEPLastError(epi,noErr); epi->socketType = aExtraSocketHint; OTInitInetAddress(&epi->remoteAddress, 0, 0); OTInitInetAddress(&epi->localAddress, 0, 0); if (aExtraSocketHint == UDPSocketType) OTAtomicSetBit(&epi->stateFlags, kConnected); //udp is always connected else OTAtomicSetBit(&epi->stateFlags, kUnConnected); s->sessionID = gthisNetSession; s->socketType = (aExtraSocketHint == UDPSocketType) ? UDPSocketType : TCPSocketType; s->privateSocketPtr = epi; gSocketsAllocated++; return 0; } void sqSocketListenOnPort(SocketPtr s, int port) { // //Listen on port for a connection, this is not the approved method //sqSocketListenOnPortBacklogSize is the best way if you are a server //However this works ok for UDP and kinda for onetime connections in TCP // EPInfo* epi; if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == TCPSocketType) { DoBind(epi,0,(InetPort) port,TCPListenerSocketType,1); if (port != 0 && epi->localAddress.fPort != port) {//We die if we don't get the port we want sqSocketDestroy(s); interpreterProxy->success(false); } } else {//udp DoBind(epi,0,(InetPort) port,UDPListenerSocketType,1); } } void sqSocketListenOnPortBacklogSize(SocketPtr s, int port, int backlogSize) { sqSocketListenOnPortBacklogSizeInterface(s, port, backlogSize, 0); } void sqSocketListenOnPortBacklogSizeInterface(SocketPtr s, int port, int backlogSize, int addr) { EPInfo* epi; SInt32 sema,readSema,writeSema; OSErr error; // //Listen on port for a connection, this is the best method if you are //a server. Works in conjunction with accept. Shouldn't drop connections //OT's special listener logic queues up the listen requestions // if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; if (s->socketType == TCPSocketType) { epi = (EPInfo *) s->privateSocketPtr; sema = epi->semaIndex; readSema = epi->readSemaIndex; writeSema = epi->writeSemaIndex; makeEPIdle(epi); //Special case really need a listener EP, so put this EP back on the queue //This may seem odd but the epi is allocated before we know what type it is. //Would need to change Squeak to indicate type at creation! error = internalSocketCreate( s, 0, TCPSocketType, 0, 0, sema, readSema, writeSema, TCPListenerSocketType); if (error != noErr) { interpreterProxy->success(false); return; } epi = (EPInfo *) s->privateSocketPtr; DoBind(epi,addr,(InetPort) port,TCPListenerSocketType,(OTQLen) backlogSize); if (port != 0 && epi->localAddress.fPort != port) {//The port we wanted must match, otherwise we die sqSocketDestroy(s); interpreterProxy->success(false); } } else {//udp not allowed interpreterProxy->success(false); } } void sqSocketAcceptFromRecvBytesSendBytesSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex){ // //Old call from old image using new VM //Just make new call // sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( s, serverSocket, recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID( SocketPtr s, SocketPtr serverSocket, int recvBufSize, int sendBufSize, int semaIndex, int readSemaIndex, int writeSemaIndex) { // //Accept incoming request from a listener //We take information from the listener, create a new socket //and accept the incoming call // EPInfo* epiSocket; EPInfo* epiServerSocket; Boolean doLeave; OSErr error; long count=0; if (!SocketValid(serverSocket)) return; if (serverSocket->socketType == TCPSocketType) { error = internalSocketCreate( s, 0, TCPSocketType, recvBufSize, sendBufSize, semaIndex, readSemaIndex, writeSemaIndex, TCPSocketType); if (error != noErr) { interpreterProxy->success(false); return; } epiSocket = (EPInfo *) s->privateSocketPtr; DoBind(epiSocket,0,0,TCPSocketType,0); // interrupt driven to T_TBINDCOMPLETE while (count++ < 100 && (OTAtomicTestBit(&epiSocket->stateFlags3, kWaitingForBind) == true)) { #ifndef TARGET_API_MAC_CARBON SystemTask(); #endif OTIdle(); } OTAtomicSetBit(&epiSocket->stateFlags2, kPassconNeeded); epiServerSocket = (EPInfo *) serverSocket->privateSocketPtr; OTAtomicSetBit(&epiServerSocket->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epiServerSocket->stateFlags, kUnConnected); OTAtomicClearBit(&epiServerSocket->stateFlags, kConnected); OTAtomicSetBit(&epiServerSocket->stateFlags2, kTapSemaphore); doLeave = OTEnterNotifier(epiServerSocket->erf); DoListenAccept(epiSocket,epiServerSocket); if (doLeave) OTLeaveNotifier(epiServerSocket->erf); } else { //udp interpreterProxy->success(false); } } void sqSocketConnectToPort(SocketPtr s, int addr, int port) { // //Connect this socket to the given host addr and port // EPInfo* epi; OTResult epState; if (!SocketValid(s) || !PortNumberValid((InetPort) port)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == TCPSocketType) { DoBind(epi,(InetHost) addr,(InetPort) port,TCPSocketType,0); // interrupt driven to T_TBINDCOMPLETE which drives T_CONNECT/DoConnect } else {//udp epState = OTGetEndpointState(epi->erf); if (epState == T_UNBND) {//Bind to remote, our side gets wildcarded DoBind(epi,(InetHost) addr,(InetPort) port,UDPSocketType,0); // interrupt driven to T_TBINDCOMPLETE which drives T_CONNECT/DoConnect } else {//Already bound to a port/interface on our side OTInitInetAddress(&epi->remoteAddress, (InetPort) port, (InetHost) addr); } } } int sqSocketSendDataBufCount(SocketPtr s, char * buf, int bufSize) { // // Send data really fast // We create a copy of the data and give it to OT to play with // We can get flow controlled lower down, if no flow control then we // tap the semiphore since from squeaks viewpoint data is sent, otherwise when flow control is lifted the // semaphore is tapped in the notification routine // OTResult res ; EPInfo* epi; Boolean doLeave; char * buffer; UInt32 adjustedBufSize = bufSize > 65536 ? 65536 : (UInt32) bufSize; //? Not sure if we really need to do this limiting. if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; // If send is blocked wait for unblocking if (OTAtomicTestBit(&epi->stateFlags, kSendIsBlocked)) { return 0; } if (epi->socketType == UDPSocketType) { //UDP adjust the buffer size again adjustedBufSize = (adjustedBufSize > epi->UDPMaximumSize) ? epi->UDPMaximumSize : adjustedBufSize; } #if TARGET_API_MAC_CARBON buffer = OTAllocMemInContext(adjustedBufSize, gClientContext); #else buffer = OTAllocMem(adjustedBufSize); #endif if (buffer == nil) { //Well maybe we back off and wait awhile? //If we run out of memory and stress the box, well death lurks. adjustedBufSize = 256; #if TARGET_API_MAC_CARBON buffer = OTAllocMemInContext(adjustedBufSize, gClientContext); #else buffer = OTAllocMem(adjustedBufSize); #endif if (buffer == nil) { interpreterProxy->success(false); //Death did lurk SetEPLastError(epi, -1); return -1; } } OTMemcpy(buffer,(void*) buf,adjustedBufSize); doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_GODATA res = SendData(epi,buffer,adjustedBufSize); if (doLeave) OTLeaveNotifier(epi->erf); if (res < 0 ){ SetEPLastError(epi, res); interpreterProxy->success(false); //JMM just for testing return 0; } return res; } // //New primitive for sending UDP data to a particular host/port //Avoids race conditions between binding and send in Smalltalk // int sqSockettoHostportSendDataBufCount(SocketPtr s, int address, int port, char * buf, int bufSize) { sqSocketConnectToPort(s, address, port); return sqSocketSendDataBufCount(s, buf, bufSize); } // //Abort the socket // void sqSocketAbortConnection(SocketPtr s) { EPInfo* epi; OSStatus err; if (!SocketValid(s)) return; if (s->socketType == UDPSocketType) { interpreterProxy->success(false); return; } epi = (EPInfo *) s->privateSocketPtr; err = doAbortConnection(epi); } // //Acutal abort logic //We need to flush the queues //Then do a disconnect // static OSStatus doAbortConnection(EPInfo* epi) { SInt32 count = 0; OSStatus err = kOTNoError; if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) { //Do flush and wait for it to happen //Should make sync? // if (epi->outstandingSends != 0) { err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); while (count++ < 100 && (epi->outstandingSends != 0 || OTAtomicTestBit(&epi->stateFlags, kUnConnected) == false)) { OTIdle(); } } makeEPBroken(epi,0); err = OTSndDisconnect(epi->erf, NULL); } if (err != kOTNoError) return err; else return epi->lastError; } // //Socket close logic // void sqSocketCloseConnection(SocketPtr s) { EPInfo* epi; OSStatus err; OTResult epState; OTResult lookResult; if (!SocketValid(s)) return; epi = (EPInfo *) s->privateSocketPtr; if (s->socketType == UDPSocketType) {//Handle udp and return OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); return; } OTAtomicSetBit(&epi->stateFlags, kThisEndClosed); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); // old code is sync and doesn't trigger semaphore epState = OTGetEndpointState(epi->erf); if (epState == T_UNINIT || epState == T_UNBND ) { OTAtomicSetBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); TapAllInterestedSemaphores(epi); return; } else err = OTSndOrderlyDisconnect(epi->erf); if (err == kOTNoError) { if (OTAtomicTestBit(&epi->stateFlags, kOtherEndClosed)) { OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (epi->outstandingSends != 0) doAbortConnection(epi); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); } } else {// Could get kOTLookErr with T_DISCONNECT pending lookResult = OTLook(epi->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) { err = OTRcvDisconnect(epi->erf, NULL); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (epi->outstandingSends != 0) doAbortConnection(epi); err = OTUnbind(epi->erf); if (err != kOTNoError) { //kOTLookErr with T_DATA, book says response is to zap EP. makeEPBroken(epi,err); } TapAllInterestedSemaphores(epi); } else { SetEPLastError(epi,err); makeEPBroken(epi,err); TapAllInterestedSemaphores(epi); } } } // //Destroy the socket here we must ensure we cleanup and put the //socket back on the idle or broken EP queue // void sqSocketDestroy(SocketPtr s) { OTResult err; EPInfo* epi; OTResult epState; JMMWriteLog(); //Diagnostics, turned off, must fiddle recompile to turn on. if (!SocketValid(s)) { return; } epi = (EPInfo *) s->privateSocketPtr; OTAtomicSetBit(&epi->stateFlags2, kMakeEPIdle); epState = OTGetEndpointState(epi->erf); if (epState == T_UNINIT || epState == T_UNBND ) { makeEPIdle(epi); //Unbound already so make him idle. } else { if (s->socketType == UDPSocketType) err = OTUnbind(epi->erf); else err = doAbortConnection(epi); if (err != kOTNoError) {//kOTLookErr with T_DATA, book says response is to zap EP. makeEPBrokenThenIdle(epi,err); } } purgeReadBuffers(epi); //JMM Oct 4th 2000 (bug?) s->sessionID = 0; s->socketType = -1; s->privateSocketPtr = nil; gSocketsAllocated--; } // //Check to see if bytes are available // int sqSocketReceiveDataAvailable(SocketPtr s) { EPInfo* epi; static lastTickCount=0; if (!SocketValid(s)) return 0; epi = (EPInfo *) s->privateSocketPtr; if (epi->bytesPendingToRead > 0) return 1; if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) // New case if data pending but flow controlled then go get it return 1; OTAtomicSetBit(&epi->stateFlags2, kTapSemaphoreReadData); //Note how we imply there will be interest in semaphore return 0; } // //Read data into the buffer supplied // int sqSocketReceiveDataBufCount(SocketPtr s, char * buf, int bufSize) { EPInfo* epi; UInt32 bytesRead = 0; Boolean doLeave; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_DATA bytesRead = readBytes(epi,(char *) buf,(UInt32) bufSize); if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) { if (bytesRead > 0) ReadData(epi,NULL,0); else bytesRead = ReadData(epi,(char *) buf,(UInt32) bufSize); //special case attempt read into squeak buffer } if (doLeave) OTLeaveNotifier(epi->erf); return (int) bytesRead; } // //New primitive to read UDP data and get data, host/port, and more flag // int sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, char * buf, int bufSize, int *address, int *port, int *moreFlag) { EPInfo* epi; UInt32 bytesRead = 0; Boolean doLeave; InetAddress fromAddress; OTMemzero(&fromAddress,sizeof(InetAddress)); *address = 0; *port = 0; *moreFlag = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; doLeave = OTEnterNotifier(epi->erf); //Avoid race condition for T_DATA bytesRead = readBytesUDP(epi,&fromAddress, moreFlag, (char *) buf,(UInt32) bufSize); *address = fromAddress.fHost; *port = fromAddress.fPort; if (OTAtomicTestBit(&epi->stateFlags2, kReadFlowControl)) { if (bytesRead > 0) ReadData(epi,NULL,0); else { bytesRead = ReadData(epi,(char *) buf,(UInt32) bufSize);//special case attempt read into squeak buffer *address = epi->remoteAddress.fHost; //Also we happen to know the address just when into this area *port = epi->remoteAddress.fPort; //JMM more flag? *moreFlag = epi->UDPMoreFlag; } } if (doLeave) OTLeaveNotifier(epi->erf); return (int) bytesRead; } int sqSocketLocalAddress(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; return (int) (epi->localAddress.fHost == 0) ? sqResolverLocalAddress() : epi->localAddress.fHost; } int sqSocketLocalPort(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; return epi->localAddress.fPort; } int sqSocketRemoteAddress(SocketPtr s) { EPInfo* epi; TBind remoteBind; InetAddress remoteAddr; OSStatus err; Boolean isAsync; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection)) return 0; if (epi->socketType == UDPSocketType) { return (int) epi->remoteAddress.fHost; } if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } //It seems the only reliable way to get the address //Is to make a call // OTMemzero(&remoteBind,sizeof(TBind)); OTMemzero(&remoteAddr,sizeof(InetAddress)); remoteBind.addr.buf = (UInt8 *) &remoteAddr; remoteBind.addr.maxlen = sizeof(InetAddress); err = OTGetProtAddress(epi->erf,0,&remoteBind); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); if (err != kOTNoError) return 0; else { if ((int) remoteAddr.fHost == 0) return (int) epi->remoteAddress.fHost; return (int) remoteAddr.fHost; } } int sqSocketRemotePort(SocketPtr s) { EPInfo* epi; TBind remoteBind; InetAddress remoteAddr; OSStatus err; Boolean isAsync; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection)) return 0; if (epi->socketType == UDPSocketType) { return epi->remoteAddress.fPort; } if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } //It seems the only reliable way to get the port //Is to make a call // OTMemzero(&remoteBind,sizeof(TBind)); OTMemzero(&remoteAddr,sizeof(InetAddress)); remoteBind.addr.buf = (UInt8 *) &remoteAddr; remoteBind.addr.maxlen = sizeof(InetAddress); err = OTGetProtAddress(epi->erf,0,&remoteBind); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); if (err != kOTNoError) return 0; else { if ((int) remoteAddr.fPort == 0) return (int) epi->remoteAddress.fPort; return (int) remoteAddr.fPort; } } int sqSocketSendDone(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return 1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kSendIsBlocked)) { OTAtomicSetBit(&epi->stateFlags2, kTapSemaphoreWriteData); //Note the implied intent to use the semaphore return 0; } else { return 1; } } int sqSocketError(SocketPtr s) { EPInfo* epi; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; if (OTAtomicTestBit(&epi->stateFlags, kUnConnected) && !OTAtomicTestBit(&epi->stateFlags, kWaitingForConnection) && epi->lastError == 0) return kENOTCONNErr; // old code would return unconnectederror if unconnected else return (epi->lastError); } int sqSocketConnectionStatus(SocketPtr s) { if (!SocketValid(s)) return InvalidSocket; return unmapStatus((EPInfo *) s->privateSocketPtr); } static SInt32 unmapStatus(EPInfo *s) { if (OTAtomicTestBit(&s->stateFlags3, kSleepKilledMe)) {return InvalidSocket; } if (OTAtomicTestBit(&s->stateFlags, kThisEndClosed)) {return ThisEndClosed; } if (OTAtomicTestBit(&s->stateFlags, kOtherEndClosed)) {return OtherEndClosed; } if (OTAtomicTestBit(&s->stateFlags, kConnected)) { return Connected; } if (OTAtomicTestBit(&s->stateFlags, kWaitingForConnection)) {return WaitingForConnection; } if (OTAtomicTestBit(&s->stateFlags, kUnConnected)) {return Unconnected; } return 0; } static Boolean SocketValid(SocketPtr s) { if ((s != NULL) && (s->privateSocketPtr != NULL) && (s->sessionID == gthisNetSession) && (gthisNetSession != 0) && (s->socketType == TCPSocketType || s->socketType == UDPSocketType) && (!OTAtomicTestBit(&(((EPInfo *)s->privateSocketPtr)->stateFlags3), kSleepKilledMe)) ) return true; interpreterProxy->success(false); return false; } static Boolean PortNumberValid(InetPort port) { if (port <= 65535) { return true; } interpreterProxy->success(false); return false; } //Used to signal all semaphores when we've closed the socket //I guess the read/write/disconnect threads really want to know // static void TapAllInterestedSemaphores(EPInfo *epi) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreReadData)) interpreterProxy->signalSemaphoreWithIndex(epi->readSemaIndex); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); } static Boolean DestroyAllOpenSockets(void) { EPInfo *epi; OTLink* link; ReadBuffer *aBuffer; // // Start closing connector endpoints. // While we could be rude and just close the endpoints, // we try to be polite and wait for all outstanding connections // to finish before closing the endpoints. The is a bit easier // on the server which won't end up keeping around control blocks // for dead connections which it doesn't know are dead. Alternately, // we could just send a disconnect, but this seems cleaner. // (void)OTLIFOStealList(gBrokenEPs); (void)OTLIFOStealList(gIdleEPs[0]); (void)OTLIFOStealList(gIdleEPs[1]); (void)OTLIFOStealList(gIdleEPs[2]); link = OTLIFODequeue(gAllEPs); while (link != NULL) { epi = OTGetLinkObject(link, EPInfo, globalLink); attemptToCloseAndDeleteThisEP(epi); link = OTLIFODequeue(gAllEPs); } // // If the lists are empty now, then all endpoints have been successfully closed, // so the client is stopped now. (Actually we hope that is the case) // // //Free up all the other resources // link = OTLIFODequeue(gFreeReadBuffers); while (link != NULL) { aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); OTFreeMem(aBuffer->readBufferData); OTFreeMem(aBuffer); link = OTLIFODequeue(gFreeReadBuffers); } ResolverTerminate(); OTFreeMem((char*)gDNSResolver); gIdleEPs[0]->fHead = NULL; gIdleEPs[1]->fHead = NULL; gIdleEPs[2]->fHead = NULL; gBrokenEPs->fHead = NULL; OTDestroyConfiguration(gCfgMastertcp); OTDestroyConfiguration(gCfgMasterudp); OTDestroyConfiguration(gCfgMasterListener); DisposeOTNotifyUPP(DNSNotifierUPP); DisposeOTNotifyUPP(NotifierSocketUPP); DisposeOTNotifyUPP(NotifierSocketUDPUPP); DisposeOTNotifyUPP(NotifierSocketListenerUPP); return true; } // // DoBind // // This routine either binds to a wild card address and specfic port if // we are doing a listen, otherwise we bind to a wild card address and // wild card port if we are starting a connection to a remote host. // J M M NOTE A more complex version could use port and addr // Note we don't bind to the local socket until here, we could when // The socket is created, but that leads to odd issues. // static void DoBind(EPInfo* epi,InetHost addr, InetPort port,UInt8 aExtraSocketHint,OTQLen queueDepth ) { OSStatus err; TBind bindReq, bindResult; InetAddress inAddr,bindAddr; switch (aExtraSocketHint) { case TCPSocketType: { // for a connection // Bind the endpoint to a wildcard address // (assign us a port, we don't care which one). // NOTE A more complex version could use port and addr OTInitInetAddress(&epi->remoteAddress, port, addr); OTInitInetAddress(&epi->localAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&inAddr, 0, 0); break; } case UDPSocketType: { // for a connection // Bind the endpoint to earlier supplied information OTInitInetAddress(&epi->remoteAddress, port, addr); OTInitInetAddress(&inAddr, 0, 0); break; } case TCPListenerSocketType: { // For a listen, bind wild card address, but supplied port. // Note the passed in addr should be zero // Note a more complex version could supply the address OTInitInetAddress(&epi->remoteAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&epi->localAddress, port, addr); OTInitInetAddress(&inAddr,port, addr); break; } case UDPListenerSocketType: { // For a listen, bind wild card address, but supplied port. // Note the passed in addr should be zero // Note a more complex version could supply the address OTInitInetAddress(&epi->remoteAddress, 0, kOTAnyInetAddress); OTInitInetAddress(&epi->localAddress, port, addr); OTInitInetAddress(&inAddr,port, addr); break; } } bindReq.addr.len = sizeof(InetAddress); bindReq.addr.buf = (unsigned char*) &inAddr; bindReq.qlen = queueDepth; //Note queue depth for listening bindResult.addr.maxlen = sizeof(InetAddress); bindResult.addr.len = sizeof(InetAddress); bindResult.addr.buf = (unsigned char*) &bindAddr; epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; epi->bytesPendingToRead = 0; SetEPLastError(epi,noErr); if (aExtraSocketHint == TCPSocketType|| aExtraSocketHint == TCPListenerSocketType) { OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epi->stateFlags2, kTapSemaphore); } OTAtomicSetBit(&epi->stateFlags3, kWaitingForBind); err = OTBind(epi->erf, &bindReq, &bindResult); // resume at T_BINDCOMPLETE // for bindReq on listen what is queueDepth now? // bindReq.qlen could have changed // But... No why to feed this back to the client! if (err != kOTNoError) { SetEPLastError(epi,err); makeEPUnconnected(epi); return; } OTMemcpy(&epi->localAddress,bindResult.addr.buf,sizeof(InetAddress)); //Pickup local address return; } // // DoConnect // // This routine attempts establish a new connection to the given // address and port. // Called via the notifier at interrupt time. // static void DoConnect(EPInfo* epi,InetHost addr, InetPort port) { OSStatus err; TCall sndCall; InetAddress inAddr; // Don't want new connections if already shutting down. if (gProgramState != kProgramRunning ) return; OTInitInetAddress(&inAddr, port, addr); OTMemzero(&sndCall, sizeof(TCall)); sndCall.addr.len = sizeof(InetAddress); sndCall.addr.buf = (unsigned char*) &inAddr; err = OTConnect(epi->erf, &sndCall, NULL); //resume at T_CONNECT if (err != kOTNoDataErr) { SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } // // DoListenAccept // // The handling of a T_LISTEN is greatly simplified by use // of the tilisten module, which serializes inbound connections. // This means that when doing an OTAccept we won't get a kOTLookErr // because another inbound connection arrived and created a T_LISTEN. // Without the tilisten module, we have to use the "8 step // listen/accept/disconnect method", which is documented elsewhere. // static void DoListenAccept(EPInfo* acceptor,EPInfo* theServer) { TCall call; InetAddress caddr; OTResult lookResult; OSStatus err; OTMemzero(&call, sizeof(TCall)); call.addr.maxlen = sizeof(InetAddress); call.addr.buf = (unsigned char*) &caddr; err = OTListen(theServer->erf, &call); if (err != kOTNoError) { // // Only two errors are expected at this point. // One would be a kOTNoDataErr, indicating the inbound connection // was unavailable, temporarily hidden by a higher priority streams // message, etc. The more likely error is a kOTLookErr, // which indicates a T_DISCONNECT on the OTLook() // happens when the call we were going to process disconnected. // In that case, go away and wait for the next T_LISTEN event. // if (err == kOTNoDataErr) return; lookResult = OTLook(theServer->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) err = OTRcvDisconnect(theServer->erf, NULL); else SetEPLastError(theServer,lookResult); //JMM Sept28th,2000 ? ok accept it, if we don't does this cause blockage? acceptor->remoteAddress = caddr; err = OTAccept(theServer->erf, acceptor->erf, &call); return; } acceptor->remoteAddress = caddr; err = OTAccept(theServer->erf, acceptor->erf, &call); // // Note an kOTIndOutErr can occur if we are listening on the EP and handling // off to the same EP. Sorry use the listento:backlogqueue: logic instead // if (err != kOTNoError) { // // Again, we have to be able to handle the connection being disconnected // while we were trying to accept it. // lookResult = OTLook(theServer->erf); if (err == kOTLookErr && lookResult == T_DISCONNECT) err = OTRcvDisconnect(theServer->erf, NULL); else SetEPLastError(theServer,lookResult); } } // // EPOpen: // // A front end to OTAsyncOpenEndpoint. // A status bit is set so we know there is an open in progress. // It is cleared when the notifier gets a T_OPENCOMPLETE where the context // pointer is this EPInfo. Until that happens, this EPInfo can't be cleaned // up and released. // static Boolean EPOpen(EPInfo* epi) { OSStatus err; OTAtomicSetBit(&epi->stateFlags, kOpenInProgressBit); SetEPLastError(epi,kOTNoError); epi->UDPMaximumSize = 0; //Remember to figure out the max UDP size. switch (epi->socketType) { case TCPSocketType: { #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMastertcp), 0, NULL, NotifierSocketUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMastertcp), 0, NULL, NotifierSocketUPP, epi); #endif break; } case UDPSocketType: { TEndpointInfo endPointInformation; #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMasterudp), 0, &endPointInformation, NotifierSocketUDPUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMasterudp), 0, &endPointInformation, NotifierSocketUDPUPP, epi); #endif epi->UDPMaximumSize = (endPointInformation.tsdu == T_INFINITE) ? 64*1024 : endPointInformation.tsdu; break; } case TCPListenerSocketType: { #if TARGET_API_MAC_CARBON err = OTAsyncOpenEndpointInContext(OTCloneConfiguration(gCfgMasterListener), 0, NULL, NotifierSocketListenerUPP, epi, gClientContext); #else err = OTAsyncOpenEndpoint(OTCloneConfiguration(gCfgMasterListener), 0, NULL, NotifierSocketListenerUPP, epi); #endif break; } } if (err != kOTNoError) { SetEPLastError(epi,err); OTAtomicClearBit(&epi->stateFlags, kOpenInProgressBit); return false; } return (epi->lastError == kOTNoError); } // // EPClose // // This routine is a front end to OTCloseProvider. // Centralizing closing of endpoints makes debugging and instrumentation easier. // static Boolean EPClose(EPInfo* epi) { OSStatus err; // // If an endpoint is still being opened, we can't close it yet. // There is no way to cancel an OTAsyncOpenEndpoint, so we just // have to wait for the T_OPENCOMPLETE event at the notifier. // if ( OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit) ) return false; // // If the OTAsyncOpenEndpoint failed, the endpoint ref will be NULL, // and we don't need to close it now. Also can be NULL or should be NULL if sleeping happened. // if (epi->erf == NULL || OTAtomicClearBit(&epi->stateFlags3, kSleepKilledMe)) { epi->erf = NULL; return true; } if (epi->outstandingSends == 0) { err = OTCloseProvider(epi->erf); epi->erf = NULL; return true; } // // If we get to this point, the endpoint did an OTSnd() with AckSends, // and the T_MEMORYRELEASED event hasn't been returned yet. In order // to make sure we get the event, we flush the stream and then do an // OTDisconnect(). This should get the memory freed so we can close // the endpoint safely. Note, we set a flag so we don't do this // more than once on an endpoint. // J M M I'm not sure we'll ever get here since a flush should have been done higher up // if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) { err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); if (err != kOTNoError) {} } return false; } // // Recycle: // // This routine shouldn't be necessary, but it is helpful to work around both // problems in OpenTransport and bugs in this program. Basicly, whenever an // unexpected error occurs which shouldn't be fatal to the program, the EPInfo // is queued on the BrokenEP queue. When recycle is called, // it will attempt to close the associated endpoint and open // a new one to replace it using the same EPInfo structure. This process of // closing an errant endpoint and opening a replacement is probably the most // reliable way to make sure that this program and OpenTransport can recover // from unexpected happenings in a clean manner. // // Mind you it can be invoked to cleanup UDP sockets that aren't closed // properly due to pending traffice on a busy port. // Solution mentioned in books is to close the EP. // static void Recycle() { OTLink* list = OTLIFOStealList(gBrokenEPs); OTLink* link; EPInfo* epi; while ( (link = list) != NULL ) { list = link->fNext; epi = OTGetLinkObject(link, EPInfo, link); if (!EPClose(epi)) { OTLIFOEnqueue(gBrokenEPs, &epi->link); continue; } if (gProgramState == kProgramRunning) EPOpen(epi); else makeEPIdle(epi); } } // // Make the EP idle, it either goes on an idle queue or gets broken. // static void makeEPIdle(EPInfo *epi) { purgeReadBuffers(epi); if (OTAtomicClearBit(&epi->stateFlags2, kEPIsBroken)) { OTLIFOEnqueue(gBrokenEPs, &epi->link); } else { OTLIFOEnqueue(gIdleEPs[epi->socketType], &epi->link); OTAtomicAdd32(1, &gIdleEPCounter[epi->socketType]); } } static void attemptToCloseAndDeleteThisEP (EPInfo *epi) { purgeReadBuffers(epi); if (!EPClose(epi)) { // Can't close this endpoint yet, so skip it. } else OTFreeMem((char*)epi); } static EPInfo* getOrMakeMeAnEP(UInt8 aSocketType,short counter) { EPInfo *epi; OTLink *link; SInt32 i; Recycle(); //Ensure broken EP get fixed up if (counter > 25) return nil; // End recursion John 2000/8/29 if (gIdleEPCounter[aSocketType] < 5) //Magic Number ensure we have at least 5 EP available. makeMeAnEP(aSocketType); link = OTLIFODequeue(gIdleEPs[aSocketType]); if (link == NULL) { for(i=0;i<10;i++) {OTIdle();}; return getOrMakeMeAnEP(aSocketType,counter+1); //Watch for recursive failure } OTAtomicAdd32(-1, &gIdleEPCounter[aSocketType]); epi = OTGetLinkObject(link, EPInfo, link); if (OTAtomicTestBit(&epi->stateFlags3, kSleepKilledMe)) { // //A broken epi on the idle stack, now the only way we can //get here (I think) is to have gone to sleep which breaks //all the end points. To clean up we must now fix them //So make it idle, of course it's broken //Then recursive call to get another one //This continues until we get a good one // makeEPIdle(epi); return getOrMakeMeAnEP(aSocketType,counter); //Not a recursion issue. } return epi; } // //This is where EP are actually made and opened //EP opening is async // static Boolean makeMeAnEP (UInt8 aSocketType) { EPInfo *epi; #if TARGET_API_MAC_CARBON epi = (EPInfo*) OTAllocMemInContext(sizeof(EPInfo), gClientContext); #else epi = (EPInfo*) OTAllocMem(sizeof(EPInfo)); #endif if (epi == NULL) return false; //Death lurks OTMemzero(epi, sizeof(EPInfo)); //zero it out which makes all the pointers null epi->socketType = aSocketType; OTLIFOEnqueue(gAllEPs, &epi->globalLink); return EPOpen(epi); } static void makeEPUnconnected(EPInfo *epi) { OTAtomicClearBit(&epi->stateFlags, kWaitingForConnection); OTAtomicSetBit(&epi->stateFlags, kUnConnected); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) //tap to clear waitforconnection on error interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); } static void makeEPConnected(EPInfo *epi) { OTAtomicClearBit(&epi->stateFlags, kWaitingForConnection); OTAtomicClearBit(&epi->stateFlags, kUnConnected); OTAtomicSetBit(&epi->stateFlags, kConnected); if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphore)) //tap to clear waitforconnection interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); } static void makeEPBrokenThenIdle(EPInfo* epi,OTResult error) { makeEPBroken(epi,error); makeEPIdle(epi); } static void makeEPBroken(EPInfo* epi,OTResult error) { SetEPLastError(epi,error); OTAtomicSetBit(&epi->stateFlags2, kEPIsBroken); } static void SetEPLastError(EPInfo* epi,OTResult error) { if (error < 0) { JMMLogMessageAndNumber("\p NonZero Error For ",epi->semaIndex); JMMLogMessageAndNumber("\p NonZero Error Is ",error); } epi->lastError = error; } // ReadData: // // This routine attempts to read all available data from an endpoint. // it is not necessary for the program to handle // getting back a T_DATA notification DURING an OTRcv() call, as would be // the case if we read from outside the notifier. We must read until we // get a kOTNoDataErr in order to clear the T_DATA event so we will get // another notification of T_DATA in the future. // Note we use EnterNotifier to make this possible // // Note for the curious we attempted to use no-copy receives to get data. This obligates // the program to return the buffers to OT asap. BUT we found we overran memory! // So we reverted to more expensive copies into buffers we have preallocated // // Perhaps a seperate routine for UDP would make sense? // Note May 30/00 we added a special read when we exhaust the internal buffer pool // But data is still pending we allow you to read into the squeak buffer directly // static UInt32 ReadData(EPInfo* epi,char *specialReadBuffer,UInt32 specialReadSize) { OTResult res; OTFlags flags; OTResult epState,err; OTLink *link; ReadBuffer *readBufferObject,simulatedReadBuffer; InetAddress UDPdataFromAddress; if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreReadData)) //tap to clear waitfordata Data Data Data interpreterProxy->signalSemaphoreWithIndex(epi->readSemaIndex); if (specialReadSize > 0) { //Special case drop into squeak buffer, make a simulated buffer object OTMemzero(&simulatedReadBuffer,sizeof(ReadBuffer)); simulatedReadBuffer.readBufferData = specialReadBuffer; simulatedReadBuffer.readBufferSize = simulatedReadBuffer.readBufferOriginalSize = specialReadSize; readBufferObject = &simulatedReadBuffer; } else { link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); //NO free buffers we are flow controled return 0; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); OTAtomicClearBit(&epi->stateFlags2, kReadFlowControl); } OTMemzero(&UDPdataFromAddress,sizeof(InetAddress)); while (true) { readBufferObject->readBufferPtr = readBufferObject->readBufferData; if (epi->socketType == UDPSocketType) { TUnitData UDPDataInBound; OTFlags flagMeaningMore; OSStatus error; UDPDataInBound.addr.maxlen = sizeof(InetAddress); UDPDataInBound.addr.len = sizeof(InetAddress); UDPDataInBound.addr.buf = (UInt8*) &readBufferObject->UDPAddress; UDPDataInBound.opt.maxlen = 0; UDPDataInBound.opt.len = 0; UDPDataInBound.opt.buf = NULL; UDPDataInBound.udata.maxlen = readBufferObject->readBufferOriginalSize; UDPDataInBound.udata.len = readBufferObject->readBufferOriginalSize; UDPDataInBound.udata.buf = (UInt8*)readBufferObject->readBufferData; error = OTRcvUData(epi->erf, &UDPDataInBound, &flagMeaningMore); if (error != kOTNoError) { res = error; } else { if (UDPDataInBound.addr.len == 0) //Remember UDP address readBufferObject->UDPAddress = UDPdataFromAddress; else UDPdataFromAddress = readBufferObject->UDPAddress; epi->UDPMoreFlag = readBufferObject->UDPMoreFlag = (flagMeaningMore > 0) ? true: false; res = (SInt32) UDPDataInBound.udata.len; OTMemcpy(&epi->remoteAddress,&readBufferObject->UDPAddress,sizeof(InetAddress)); } } else {//A less complicated tcp read res = OTRcv(epi->erf, readBufferObject->readBufferData, readBufferObject->readBufferOriginalSize, &flags); } // // Note, check for 0 because can get a real 0 length receive // in some protocols (not in TCP), which is different from // getting back a kOTNoDataErr. // if (res >= 0) { if (specialReadSize > 0) return (UInt32) res; //Note special case readBufferObject->readBufferSize = (UInt32) res; OTAddLast(&epi->readBuffers,&readBufferObject->fNext); //Put the buffer on the read queue OTAtomicAdd32(res, &epi->bytesPendingToRead); link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); //Our read flow control, OT will block lower down return 0; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); continue; //Loop around and get more bytes if available } else { if (specialReadSize == 0) { OTLIFOEnqueue(gFreeReadBuffers, &readBufferObject->fNext); //Read above didn't work so put it back on free queue gFreeReadBuffersCounter++; } } if (res == kOTNoDataErr) { // // Since ReadData is only called from inside the notifier // we don't have to worry about having missed a T_DATA // during the OTRcv. // Note use of EnterNotifier logic // if (specialReadSize > 0) OTAtomicClearBit(&epi->stateFlags2, kReadFlowControl); return 0; } if (res == kOTLookErr) { res = OTLook(epi->erf); if (res == T_ORDREL || res == T_DISCONNECT) { // If we got the T_ORDREL, we won't get any more inbound data. // We return and wait for the notifier to get the T_ORDREL notification. // Upon getting it, we will notice we still need to send data and do so. // The T_ORDREL has to be cleared before we can send. // if (specialReadSize > 0 && res == T_DISCONNECT) { //Special case? need to get disconnect err = OTRcvDisconnect(epi->erf, NULL); makeEPUnconnected(epi); } return 0 ; } if (res == T_GODATA) { if (specialReadSize == 0) { link = OTLIFODequeue(gFreeReadBuffers); if (link == NULL) { OTAtomicSetBit(&epi->stateFlags2, kReadFlowControl); return 0 ; } gFreeReadBuffersCounter--; readBufferObject = OTGetLinkObject(link, ReadBuffer, fNext); } else { return 0; } continue; //OT Flow control lifted keep reading. JMM } } else { epState = OTGetEndpointState(epi->erf); if (res == kOTOutStateErr && epState == T_INREL) { // // Occasionally this problem will happen due to what appears // to be an OpenTransport notifier reentrancy problem. // What has occured is that a T_ORDREL event happened and // was processed during ReadData(). This is proven by being // in the T_INREL state without having done a call to // OTRcvOrderlyDisconnect() here. It appears to be a benign // situation, so the way to handle it is to understand that no // more data is going to arrive and go ahead and being our response // to the client. // break; } if (res == kOTOutStateErr && (epState == T_UNBND || epState == T_IDLE ) && specialReadSize > 0) { interpreterProxy->success(false); //JMM Oct 4th 2000 special case fail if read on unbound return 0; } break; //Ok error so break out of loop } } return 0; } // // NOT USED HISTORICAL REASONS // /* static void NoCopyReceiveWalkingBufferChain(EPInfo *epi,OTBufferInfo *bufferInfo) { OSStatus err; OTBuffer *thisBuffer; UInt32 count; ReadBuffer *readBufferObject; thisBuffer = bufferInfo->fBuffer; err = noErr; while (err == noErr && thisBuffer != nil) { count = thisBuffer->fLen; OTAtomicAdd32(count, &epi->bytesPendingToRead); readBufferObject = OTAllocMemInContext(sizeof(ReadBuffer), gClientContext); if (readBufferObject == nil) { SysBeep(5); err = -1; break; } OTMemzero(readBufferObject,sizeof(ReadBuffer)); readBufferObject->readBufferData = readBufferObject->readBufferPtr = OTAllocMemInContext(count, gClientContext); if ( readBufferObject->readBufferData == nil) { SysBeep(5); err = -1; break; } readBufferObject->readBufferOriginalSize = readBufferObject->readBufferSize = count; OTMemcpy(readBufferObject->readBufferData,thisBuffer->fData,count); OTAddLast(&epi->readBuffers,&readBufferObject->fNext); thisBuffer = thisBuffer->fNext; } // Clean up. We MUST release the OTBuffer chain to Open Transport // so that it crelease the OTBuffer chain to Open Transport // so that it can reuse it., OTReleaseBuffer does not tolerate // the parameter being nil, so we check for that case first. if (bufferInfo->fBuffer != nil) { OTReleaseBuffer(bufferInfo->fBuffer); } } */ // // Read Bytes from the buffers // Called by Squeak to get the data // static UInt32 readBytes(EPInfo* epi,char *buf,UInt32 adjustedBufSize) { // // Read bytes from buffers // use recursion to fill buf to adjustedBufSize or // til we have no buffers left // By using enterNotifier higher up we avoid race on the readBuffers list // UInt32 increment,bytesRead = 0; ReadBuffer *aBuffer; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); if (aBuffer == nil) return 0; if (aBuffer->readBufferSize > adjustedBufSize) { bytesRead = adjustedBufSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy((char *) buf,aBuffer->readBufferPtr,bytesRead); aBuffer->readBufferPtr += bytesRead; aBuffer->readBufferSize -= bytesRead; OTAddFirst(&epi->readBuffers,&aBuffer->fNext); return bytesRead; } else { bytesRead = aBuffer->readBufferSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy(buf,aBuffer->readBufferPtr,bytesRead); OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; increment = readBytes(epi,buf+bytesRead,adjustedBufSize-bytesRead); bytesRead += increment; return bytesRead; } } static UInt32 readBytesUDP(EPInfo* epi,InetAddress *fromAddress, int * moreFlag, char *buf,UInt32 adjustedBufSize) { // // Read bytes from buffers // For UDP we just drop in the read buffer and address // Don't fill the entire buffer no recursion. // By using enterNotifier higher up we avoid race on the readBuffers list // UInt32 bytesRead = 0; ReadBuffer *aBuffer; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); if (aBuffer == nil) return 0; if (aBuffer->readBufferSize > adjustedBufSize) { bytesRead = adjustedBufSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy((char *) buf,aBuffer->readBufferPtr,bytesRead); aBuffer->readBufferPtr += bytesRead; aBuffer->readBufferSize -= bytesRead; OTMemcpy(fromAddress,&aBuffer->UDPAddress,sizeof(InetAddress)); *moreFlag = aBuffer->UDPMoreFlag; OTAddFirst(&epi->readBuffers,&aBuffer->fNext); return bytesRead; } else { bytesRead = aBuffer->readBufferSize; OTAtomicAdd32(-bytesRead, &epi->bytesPendingToRead); OTMemcpy(buf,aBuffer->readBufferPtr,bytesRead); OTMemcpy(fromAddress,&aBuffer->UDPAddress,sizeof(InetAddress)); *moreFlag = aBuffer->UDPMoreFlag; OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; return bytesRead; } } //Cleanup logic // static void purgeReadBuffers(EPInfo *epi) { ReadBuffer *aBuffer; // //Put buffers for this epi back on the free queue // aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); while (aBuffer != NULL) { OTLIFOEnqueue(gFreeReadBuffers, &aBuffer->fNext); gFreeReadBuffersCounter++; aBuffer = (ReadBuffer *) OTRemoveFirst(&epi->readBuffers); } epi->bytesPendingToRead = 0; } // // Send the Bytes (Really fast, we hope) // static SInt32 SendData(EPInfo* epi,char* buffer, UInt32 size) { OTResult res; struct OTData *dataPtr; // // Make sure we record that we are starting a send so we don't try to close // the endpoint before a T_MEMORYRELEASED event is returned. // OTAtomicAdd32(1, &epi->outstandingSends); if (epi->socketType == UDPSocketType) { TUnitData UDPDataOutBound; UDPDataOutBound.addr.maxlen = sizeof(InetAddress); UDPDataOutBound.addr.len = sizeof(InetAddress); UDPDataOutBound.addr.buf = (UInt8*) &epi->remoteAddress; UDPDataOutBound.opt.maxlen = 0; UDPDataOutBound.opt.len = 0; UDPDataOutBound.opt.buf = NULL; UDPDataOutBound.udata.maxlen = size; UDPDataOutBound.udata.len = size; UDPDataOutBound.udata.buf = (UInt8*)buffer; res = OTSndUData(epi->erf,&UDPDataOutBound); if (res == kOTNoError ) return (SInt32) size; // Other Errors could be kOTFlowErr or kOTBadDataErr } else { //TCP Send // // In OT 1.1.2 and previous versions, there is a bug with AckSends // which occurs when the same buffer is sent more than once. In an attempt // to go fast and not allocate memory, TCP may write an IP and TCP header // into the data buffer which is sent. If the buffer is sent more than once // without being refreshed, the data may be corrupted. To work around this, // send the data via an OTData structure, using the gather-write mechanism. // The problem does not occur in this code path, and this will not hinder performance. // The problem will be fixed in the next Open Transport release following 1.1.2. // // Note the MAC OS 8.1 docs alude to a bug before 1.3 where acksends // cause problems if a disconnect flows just right. Unsure if this // will be an issue // if (gOTVersion < kOTVersion113) { #if TARGET_API_MAC_CARBON dataPtr = OTAllocMemInContext(sizeof(OTData), gClientContext); #else dataPtr = OTAllocMem(sizeof(OTData)); #endif if (dataPtr == NULL) { //Death lurks I'm sure OTAtomicAdd32(-1, &epi->outstandingSends); OTFreeMem(buffer); return 0; } dataPtr->fNext = NULL; dataPtr->fData = buffer; dataPtr->fLen = size; res = OTSnd(epi->erf, dataPtr, kNetbufDataIsOTData, 0); //Note in the notification routine we cleanup the allocated dataPtr AND buffer. } else { res = OTSnd(epi->erf, buffer, size, 0); //JMM how to handle kENOMEMErr no memory right now error //Book says to back off and wait but must do a timer or something //Right now we'll fail the primitive higher up since the error code is bad } } if (res == size) return (SInt32) size; if (res >= 0) { // // Implied kOTFlowErr since not all data was accepted. // But maybe we aren't blocked yet so keep sending // return res; } else { // res < 0 OTAtomicAdd32(-1, &epi->outstandingSends); OTFreeMem(buffer); if ((epi->socketType != UDPSocketType) && (gOTVersion < kOTVersion113) ) OTFreeMem(dataPtr); if (res == kOTFlowErr) { // // Flow control back off and wait for T_GODATA // OTAtomicSetBit(&epi->stateFlags, kSendIsBlocked); return 0; } if (res == kOTLookErr) { res = OTLook(epi->erf); if (res == T_ORDREL || res == T_GODATA || res == T_DISCONNECT) { // Wait to get the T_ORDREL at the notifier and handle it there. // Then we will resume sending. // Same applies for other events // //JMM test? OTAtomicSetBit(&epi->stateFlags, kSendIsBlocked); return 0; } else return res; } else return res; } } // //Set the options // int sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(SocketPtr s,char * optionNameT, int optionNameSize, char * optionValueT, int optionValueSize, int *result) { EPInfo* epi; OTResult error; char optionName[80],optionValue[80]; SInt32 anInteger; *result = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; OTMemcpy(optionName,(char *) optionNameT,optionNameSize); optionName[optionNameSize] = 0x00; OTMemcpy(optionValue,(char *) optionValueT,optionValueSize); optionValue[optionValueSize] = 0x00; if (optionValueSize == 8) { error = lookupOptionName(epi, false, (char *) &optionName, (long) &optionValue ,(long *) result); } else { CopyCStringToPascal(optionValue,(unsigned char *) optionValue); StringToNum((ConstStr255Param) optionValue,&anInteger); error = lookupOptionName(epi, false, (char *) &optionName, anInteger,(long *) result); } return error; } // //Get the options // int sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(SocketPtr s,char * optionNameT, int optionNameSize, int *result) { EPInfo* epi; OTResult error; char optionNameTemp[80]; *result = 0; if (!SocketValid(s)) return -1; epi = (EPInfo *) s->privateSocketPtr; OTMemcpy(optionNameTemp,(char *) optionNameT,optionNameSize); //NEED to fiddle with error number JMM to say readonly notvalid etc. optionNameTemp[optionNameSize] = 0x00; error = lookupOptionName(epi, true, (char *) &optionNameTemp, NULL,(long *) result); return error; } // A Number of routines to set/get options, first figureout the flags, then call the routine // To set or get the options. static SInt32 lookupOptionName(EPInfo *epi, Boolean trueIfGet, char *aString, UInt32 value, SInt32 *result) { if (strcmp("TCP_MAXSEG",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_MAXSEG,value,result);}; if (strcmp("TCP_NODELAY",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_NODELAY,value,result);}; if (strcmp("TCP_ABORT_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_ABORT_THRESHOLD,value,result);}; if (strcmp("TCP_CONN_NOTIFY_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_CONN_NOTIFY_THRESHOLD,value,result);}; if (strcmp("TCP_CONN_ABORT_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_CONN_ABORT_THRESHOLD,value,result);}; if (strcmp("TCP_NOTIFY_THRESHOLD",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_NOTIFY_THRESHOLD,value,result);}; if (strcmp("TCP_URGENT_PTR_TYPE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_URGENT_PTR_TYPE,value,result);}; if (strcmp("UDP_CHECKSUM",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_UDP,UDP_CHECKSUM,value,result);}; if (strcmp("SO_DEBUG",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_DEBUG,value,result);}; if (strcmp("SO_REUSEADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_REUSEADDR,value,result);;}; if (strcmp("SO_REUSEPORT",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_REUSEADDR,value,result);}; if (strcmp("SO_DONTROUTE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_DONTROUTE,value,result);}; if (strcmp("SO_BROADCAST",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_BROADCAST,value,result);}; if (strcmp("SO_SNDBUF",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_SNDBUF,value,result);}; if (strcmp("SO_RCVBUF",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_RCVBUF,value,result);}; if (strcmp("SO_KEEPALIVE",aString)==0) {return SetKeepAliveOption(epi,trueIfGet,INET_TCP,TCP_KEEPALIVE,value,result);}; if (strcmp("SO_OOBINLINE",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_TCP,TCP_OOBINLINE,value,result);}; if (strcmp("SO_PRIORITY",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,kIP_TOS,value,result);}; if (strcmp("SO_LINGER",aString)==0) {return SetLingerOption(epi,trueIfGet,XTI_GENERIC,XTI_LINGER,value,result);}; if (strcmp("SO_RCVLOWAT",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_RCVLOWAT,value,result);}; if (strcmp("SO_SNDLOWAT",aString)==0) {return SetFourByteOption(epi,trueIfGet,XTI_GENERIC,XTI_SNDLOWAT,value,result);}; if (strcmp("IP_OPTIONS",aString)==0) { }; //JMM What to do here? if (strcmp("IP_TTL",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,kIP_TTL,value,result);}; if (strcmp("IP_HDRINCL",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_HDRINCL,value,result);}; //NOT SUPPORT FOR IP if (strcmp("IP_RCVOPTS",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_RCVOPTS,value,result);}; if (strcmp("IP_RCVDSTADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_RCVDSTADDR,value,result);}; if (strcmp("IP_MULTICAST_IF",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_MULTICAST_IF,value,result);}; if (strcmp("IP_MULTICAST_TTL",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,kIP_MULTICAST_TTL,value,result);}; if (strcmp("IP_MULTICAST_LOOP",aString)==0) {return SetOneByteOption(epi,trueIfGet,INET_IP,kIP_MULTICAST_LOOP,value,result);}; if (strcmp("IP_ADD_MEMBERSHIP",aString)==0) { return SetEightByteOption(epi,trueIfGet,INET_IP,kIP_ADD_MEMBERSHIP,(char *) value,result);}; if (strcmp("IP_DROP_MEMBERSHIP",aString)==0) { return SetEightByteOption(epi,trueIfGet,INET_IP,kIP_DROP_MEMBERSHIP,(char *) value,result);}; if (strcmp("IP_BROADCAST_IFNAME",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_BROADCAST_IFNAME,value,result);}; if (strcmp("IP_RCVIFADDR",aString)==0) {return SetFourByteOption(epi,trueIfGet,INET_IP,kIP_RCVIFADDR,value,result);}; *result = 0; return -1; } static OTResult SetEightByteOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, char * value, SInt32 *returnValue) { OTResult err; UInt8 optBuffer[kOTFourByteOptionSize+4]; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; /* Set up the option buffer to specify the option and value to set. */ option->len = kOTFourByteOptionSize+4; option->level= level; option->name = name; option->status = 0; if (!trueIfGet) OTMemcpy(option->value,value,8); /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(optBuffer); request.opt.maxlen=sizeof(optBuffer); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(optBuffer); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = option->value[0]; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetFourByteOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; UInt8 optBuffer[kOTFourByteOptionSize]; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; /* Set up the option buffer to specify the option and value to set. */ option->len = kOTFourByteOptionSize; option->level= level; option->name = name; option->status = 0; option->value[0] = value; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(optBuffer); request.opt.maxlen=sizeof(optBuffer); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(optBuffer); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = option->value[0]; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetOneByteOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; UInt8 optBuffer[kOTFourByteOptionSize]; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; /* Set up the option buffer to specify the option and value to set. */ option->len = kOTOneByteOptionSize; option->level= level; option->name = name; option->status = 0; *(unsigned char *)option->value = value; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= kOTOneByteOptionSize; request.opt.maxlen=sizeof(optBuffer); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(optBuffer); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = (UInt32) (*(unsigned char *)option->value); if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetKeepAliveOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; TKeepAliveOpt optBuffer; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; if (value == 0) optBuffer.tcpKeepAliveOn = T_NO; else optBuffer.tcpKeepAliveOn = T_YES; optBuffer.tcpKeepAliveTimer = value; /* Set up the option buffer to specify the option and value to set. */ option->len = sizeof(TKeepAliveOpt); option->level= level; option->name = name; option->status = 0; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(TKeepAliveOpt); request.opt.maxlen=sizeof(TKeepAliveOpt); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(TKeepAliveOpt); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = optBuffer.tcpKeepAliveTimer; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } static OTResult SetLingerOption(EPInfo* epi,Boolean trueIfGet, OTXTILevel level, OTXTIName name, UInt32 value, SInt32 *returnValue) { OTResult err; TLingerOpt optBuffer; TOption *option = (TOption *) &optBuffer; TOptMgmt request; TOptMgmt result; Boolean isAsync=false; if (value == 0) optBuffer.tcpLingerOn = T_NO; else optBuffer.tcpLingerOn = T_YES; optBuffer.tcpLingerTimer = value; /* Set up the option buffer to specify the option and value to set. */ option->len = sizeof(TKeepAliveOpt); option->level= level; option->name = name; option->status = 0; /* Set up request parameter for OTOptionManagement */ request.opt.buf= (UInt8 *) option; request.opt.len= sizeof(TKeepAliveOpt); request.opt.maxlen=sizeof(TKeepAliveOpt); request.flags = trueIfGet ? T_CURRENT : T_NEGOTIATE; /* Set up reply parameter for OTOptionManagement. */ result.opt.buf = (UInt8 *) option; result.opt.maxlen = sizeof(TKeepAliveOpt); if (OTIsSynchronous(epi->erf) == false) { // check whether ep sync or not isAsync = true; // set flag if async OTSetSynchronous(epi->erf); // set endpoint to sync } err = OTOptionManagement(epi->erf, &request, &result); if (isAsync) // restore ep state OTSetAsynchronous(epi->erf); *returnValue = optBuffer.tcpLingerTimer; if (err == noErr) { if (option->status != T_SUCCESS) err = option->status; } return (err); } // // Notifier: // // Most of the interesting networking code in this program for the resolver resides inside // this notifier. In order to run asynchronously and as fast as possible, // things are done inside the notifier whenever possible. Since almost // everything is done inside the notifier, there was little need for specical // synchronization code. // // Note: The only events which are expected from the DNR are T_DNRSTRINGTOADDRCOMPLETE, // T_DNRADDRTONAMECOMPLETE, and of close sleep/reconfigure notifications. // // static pascal void DNSNotifier(void* context, OTEventCode event, OTResult result, void* cookie) { #pragma unused(cookie) EPInfo* epi = (EPInfo*) context; JMMLogMessageAndNumber("\p DNS Event ",event); JMMLogMessageAndNumber("\p DNS Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); // // Once the program is shutting down, most events would be uninteresting. // if (gProgramState != kProgramRunning) return; // // Within the notifier, all action is based on the event code. // In this notifier, fatal errors all break out of the switch to the bottom. // As long as everything goes as expected, the case returns rather than breaks. // switch (event) { // // T_DNRSTRINGTOADDRCOMPLETE: // // This event occurs when the DNR has finished an attempt to translate // the server's name into an IP address we can use to connect to. // case T_DNRSTRINGTOADDRCOMPLETE: { gDNSResolverError = result; if (result != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } gDNSAddr = gDNSHostInfo.addrs[0]; gDNSResolverStatus = RESOLVER_SUCCESS; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } // // T_DNRADDRTONAMECOMPLETE: // // This event occurs when the DNR has finished an attempt to translate // the an IP address into a server name. // case T_DNRADDRTONAMECOMPLETE: { gDNSResolverError = result; if (result != kOTNoError) { gDNSResolverStatus = RESOLVER_ERROR; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } gDNSResolverStatus = RESOLVER_SUCCESS; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); return; } // // kOTProviderWillClose: // // This event occurs when the user changes TCP/IP in the control panel // case kOTProviderWillClose: case kOTProviderIsClosed: { gDNSResolverError = kOTProviderWillClose; interpreterProxy->signalSemaphoreWithIndex(epi->semaIndex); ResolverTerminate(); gDNSResolverStatus = RESOLVER_SUCCESS; //Cheat! Keep Squeak happy later we fix the resolver EP. return; } // // default: // // There are events which we don't handle, but we don't expect to see // any of them. In the production version of the program, we ignore the event and try to keep running. // default: { return; } } } // // Notifier for socket: Please note we have another notifier for sockets that do multiple listens // And a different notifier for UDP sockets, however the intesting thing is that we can call /// This routine from othe other as a simple form of inheritence. // // Most of the interesting networking code in this program for socket support resides inside // this notifier. In order to run asynchronously and as fast as possible, // things are done inside the notifier whenever possible. Since almost // everything is done inside the notifier, there was little need for specical // synchronization code. // // IMPORTANT NOTE: Normal events defined by XTI (T_LISTEN, T_CONNECT, etc) // and OT completion events (T_OPENCOMPLETE, T_BINDCOMPLETE, etc.) are not // reentrant. That is, whenever our notifier is invoked with such an event, // the notifier will not be called again by OT for another normal or completion // event until we have returned out of the notifier - even if we make OT calls // from inside the notifier. This is a useful synchronization tool. // However, there are two kinds of events which will cause the notifier to // be reentered. One is T_MEMORYRELEASED, which always happens instantly. // The other are state change events like kOTProviderWillClose. // static pascal void NotifierSocket(void* context, OTEventCode event, OTResult result, void* cookie) { OSStatus err; OTResult epState; EPInfo* epi = (EPInfo*) context; JMMLogMessageAndNumber("\p Event ",event); JMMLogMessageAndNumber("\p Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); // // Once the program is shutting down, most events would be uninteresting. // However, we still need T_OPENCOMPLETE and T_MEMORYRELEASED events since // we can't call CloseOpenTransport until all OTAsyncOpenEndpoints and // OTSends with AckSends have completed. So those specific events // are still accepted. // if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } // // Within the notifier, all action is based on the event code. // In this notifier, fatal errors all break out of the switch to the bottom. // As long as everything goes as expected, the case returns rather than breaks. // switch (event) { // // kStreamIoctlEvent: // // This event is returned when an I_FLUSH ioctl has completed. // The flush was done in an attempt to get back all T_MEMORYRELEASED events // for outstanding OTSnd() calls with Ack Sends. For good measure, we // send a disconnect now. Errors are ignored at this point since it is // possible that the connection will already be gone, etc. // case kStreamIoctlEvent: { if (OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit) != 0) { OTAtomicClearBit(&epi->stateFlags2, kFlushDisconnectInProgressBit); (void) OTSndDisconnect(epi->erf, NULL); } return; } // // T_ACCEPTCOMPLETE: // // This event is received by the listener endpoint only when we open a port with a listen. // The acceptor endpoint will get a T_PASSCON event instead. // case T_ACCEPTCOMPLETE: { SetEPLastError(epi,result); if (result != kOTNoError) { makeEPUnconnected(epi); return; } makeEPConnected(epi); return; } // // T_BINDCOMPLETE: // // This event is returned when an endpoint has been bound to a wildcard addr. // Bind happens when we open a connection to a remote location. // No errors are expected. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) { makeEPUnconnected(epi); return; } if (epi->remoteAddress.fHost != 0) DoConnect(epi,epi->remoteAddress.fHost, epi->remoteAddress.fPort); return; } // // T_CONNECT: // // This event is returned when a connection is established to the server. // The program must call OTRcvConnect() to get the conenction information // and clear the T_CONNECT event from the stream. Since OTRcvConnect() // returns immediately (rather than via a completion event to the notifier) // we can use local stack structures for parameters. // case T_CONNECT: { TCall call; SetEPLastError(epi,result); if (result != kOTNoError) { makeEPUnconnected(epi); return; } // Address of endpoint that has connection // This could be different from original request // Due to hand off to different EP say you connect to // port 80, but you end up on 49160 call.addr.maxlen = sizeof(InetAddress); call.addr.buf = (unsigned char*) &epi->remoteAddress; call.opt.maxlen = 0; call.opt.buf = NULL; call.udata.maxlen = 0; call.udata.buf = NULL; err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); if (err != kOTNoError) { if (err == kOTLookErr) { OSStatus lookStatus; lookStatus = OTLook(epi->erf); if (lookStatus == T_DISCONNECT) { err = OTRcvDisconnect(epi->erf, NULL); if (err != kOTNoError) { if (err == kOTNoDisconnectErr) { err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } else { err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPUnconnected(epi); return; } } if (lookStatus == T_GODATA) { // HUH err = OTRcvConnect(epi->erf, &call); SetEPLastError(epi,err); makeEPConnected(epi); return; } } //JMM book says may return kOTNoDataErr (no connecton yet) or a kOTLookErr with T_DISCONNECT // BUT we had got T_GODATA WHY? makeEPUnconnected(epi); return; } makeEPConnected(epi); return; // Wait for a T_DATA... } // // T_LISTEN: // case T_LISTEN: { DoListenAccept(epi,epi); return; } // // T_DATA: // // The main rule for processing T_DATA's is to remember that once you have // a T_DATA, you won't get another one until you have read to a kOTNoDataErr. // The advanced rule is to remember that you could get another T_DATA // during an OTRcv() which will eventually return kOTNoDataErr, presenting // the application with a synchronization issue to be most careful about. // // In this application, since an OTRcv() calls are made from inside the notifier, // this particular synchronization issue doesn't become a problem. // case T_DATA: { if (!OTAtomicTestBit(&epi->stateFlags2, kPassconNeeded)) { ReadData(epi,NULL,0); return; } else { // // Here we work around a small OpenTransport bug. // It turns out, since this program does almost everything from inside the notifier, // that during a T_UNBINDCOMPLETE we can put an EPInfo back into the idle list. // If that notification is interrupted by a T_LISTEN at the notifier, we could // end up starting a new connection on the endpoint before OT unwinds the stack // out of the code which delivered the T_UNBINDCOMPLETE. OT has some specific // code to protect against a T_DATA arriving before the T_PASSCON, but in this // case it gets confused and the events arrive out of order. If we try to // do an OTRcv() at this point we will get a kOTStateChangeErr because the endpoint // is still locked by the earlier OTAccept call until the T_PASSCON is delivered // to us. This is fairly benign and can be worked around easily. What we do // is note that the T_PASSCON hasn't arrived yet and defer the call to ReadData() // until it does. // if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 ) { ReadData(epi,NULL,0); return; } } } // // T_PASSCON: // // This event happens on the accepting endpoint, not the listening endpoint. // At this point the connection is fully established and we can begin the // process of downloading data. Note that due to a problem in OT it is // possible for a T_DATA to beat a T_PASSCON to the notifier. When this // happens we note it in the T_DATA case and then start processing the // data here. // case T_PASSCON: { SetEPLastError(epi,result); if (result != kOTNoError) { OTAtomicSetBit(&epi->stateFlags, kPassconBit); makeEPUnconnected(epi); return; } makeEPConnected(epi); if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 ){ // // A T_DATA previously beat the T_PASSCON to our notifier. // Here we help OT out by having deferred data processing until now. // ReadData(epi,NULL,0); } return; } // // T_MEMORYRELEASED // lower level has finished with buffer case T_MEMORYRELEASED: { if (cookie == nil) return; OTAtomicAdd32(-1, &epi->outstandingSends); if (epi->socketType == UDPSocketType) { OTFreeMem(cookie); } else {//tcp if (gOTVersion < kOTVersion113) { struct OTData *data=cookie; OTFreeMem(data->fData); OTFreeMem(data); } else { OTFreeMem(cookie); } } return; } // // T_DISCONNECT: // // An inbound T_DISCONNECT event usually indicates that the other side of the // connection did an abortive disconnect (as opposed to an orderly release). // It also can be generated by the transport provider on the system (e.g. tcp) // when it decides that a connection is no longer in existance. // // We receive the disconnect, but this program ignores the associated reason (NULL param). // It is possible to get back a kOTNoDisconnectErr from the OTRcvDisconnect call. // This can happen when either (1) the disconnect on the stream is hidden by a // higher priority message, or (2) something has flushed or reset the disconnect // event in the meantime. This is not fatal, and the appropriate thing to do is // to pretend the T_DISCONNECT event never happened. Any other error is unexpected // and needs to be reported so we can fix it. Next, unbind the endpoint so we can // reuse it for a new inbound connection. // // It is possible to get an error on the unbind due to a bug in OT 1.1.1 and earlier. // The best thing to do for that is close the endpoint and open a new one to replace it. // We do this back in the main thread so we don't have to deal with synchronization problems. // case T_DISCONNECT: { epState = OTGetEndpointState(epi->erf); err = OTRcvDisconnect(epi->erf, NULL); if (epState == T_OUTCON) { //01Aug2000 fix for bad port, will get disconnect on outgoing connection makeEPUnconnected(epi); } if (err != kOTNoError) { if (err == kOTNoDisconnectErr) return; makeEPBroken(epi,err); return; } /// //Both sides now have closed // OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); err = OTUnbind(epi->erf); TapAllInterestedSemaphores(epi); if (err != kOTNoError) { makeEPBroken(epi,err); } return; } // // T_GODATA: // // This event is received when flow control is lifted. We are under flow control // whenever OTSnd() returns a kOTFlowErr or accepted less bytes than we attempted // to send. // // Note, it is also possible to get a T_GODATA without having invoke flow control. // Be safe and prepare for this. // case T_GODATA: { if (OTAtomicClearBit(&epi->stateFlags, kSendIsBlocked)) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); }; return; } // // T_OPENCOMPLETE: // // This event occurs when an OTAsyncOpenEndpoint() completes. Note that this event, // just like any other async call made from outside the notifier, can occur during // the call to OTAsyncOpenEndpoint(). That is, in the main thread the program did // the OTAsyncOpenEndpoint(), and the notifier is invoked before control is returned // to the line of code following the call to OTAsyncOpenEndpoint(). This is one // event we need to keep track of even if we are shutting down the program since there // is no way to cancel outstanding OTAsyncOpenEndpoint() calls. // case T_OPENCOMPLETE: { TOptMgmt optReq; TOption opt; OTAtomicClearBit(&epi->stateFlags, kOpenInProgressBit); if (result == kOTNoError) epi->erf = (EndpointRef) cookie; else { makeEPBrokenThenIdle(epi,result); return; } if (gProgramState != kProgramRunning) return; // // Set to blocking mode so we don't have to deal with kEAGAIN errors. // Async/blocking is the best mode to write an OpenTransport application in. // err = OTSetBlocking(epi->erf); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); return; } // // Set to AckSends so OT doesn't slow down to copy data sent out. // However, this requires special care when closing endpoints, so don't use // AckSends unless you are prepared for this. Never, ever, close an endpoint // when a send has been done but the T_MEMORYRELEASED event hasn't been returned yet. // err = OTAckSends(epi->erf); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); return; } // // Option Management // // Turn on ip_reuseaddr so we don't have port conflicts in general. // We use local stack structures here since the memory for the // option request structure is free upon return. If we were to request // the option return value, we would have to use static memory for it. // optReq.flags = T_NEGOTIATE; optReq.opt.len = kOTFourByteOptionSize; optReq.opt.buf = (unsigned char *) &opt; opt.len = sizeof(TOption); opt.level = INET_IP; opt.name = kIP_REUSEADDR; opt.status = 0; opt.value[0] = 1; if (epi->socketType == TCPSocketType) OTAtomicSetBit(&epi->stateFlags3, kKeepAliveOptionNeeded); err = OTOptionManagement(epi->erf, &optReq, NULL); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,err); } // // Code path resumes at T_OPTMGMTCOMPLETE // return; } // // T_OPTMGMTCOMPLETE: // // An OTOptionManagement() call has completed. These are used on all // endpoints to set IP_REUSEADDR. It is also used for all endpoints // other than the listener to set TCP_KEEPALIVE which helps recover // server resources if the other side crashes or is unreachable. // case T_OPTMGMTCOMPLETE: { TOptMgmt optReq; if (result != kOTNoError) { makeEPBrokenThenIdle(epi,result); return; } if (OTAtomicClearBit(&epi->stateFlags3, kKeepAliveOptionNeeded)) { TKeepAliveOpt opt; // // Turn on TCP_KEEPALIVE so we can recover from connections which have // gone away which we don't know about. // optReq.flags = T_NEGOTIATE; optReq.opt.len = sizeof(TKeepAliveOpt); optReq.opt.buf = (unsigned char *) &opt; opt.len = sizeof(TKeepAliveOpt); opt.level = INET_TCP; opt.name = TCP_KEEPALIVE; opt.status = 0; opt.tcpKeepAliveOn = 1; opt.tcpKeepAliveTimer = kTCPKeepAliveInMinutes; err = OTOptionManagement(epi->erf, &optReq, NULL); if (err != kOTNoError) { makeEPBrokenThenIdle(epi,result); } return; } makeEPIdle(epi); //This is where more EP enter the queue of available EPs. return; // now wait } // // T_ORDREL: // // This event occurs when an orderly release has been received on the stream. // case T_ORDREL: { err = OTRcvOrderlyDisconnect(epi->erf); if (err != kOTNoError) { // // It is possible for several reasons for the T_ORDREL to have disappeared, // or be temporarily hidden, when we attempt the OTRcvOrderlyDisconnect(). // The best thing to do when this happens is pretend that the event never // occured. We will get another notification of T_ORDREL if the event // becomes unhidden later. Any other form of error is unexpected and // is reported back so we can correct it. // if (err == kOTNoReleaseErr) return; //Can get OTLookErr with T_DISCONNECT makeEPBroken(epi,err); } if (OTAtomicTestBit(&epi->stateFlags, kThisEndClosed)) { /// //Both sides now have closed // OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); epState = OTGetEndpointState(epi->erf); if (epState != T_IDLE) { TapAllInterestedSemaphores(epi); return; } err = OTUnbind(epi->erf); TapAllInterestedSemaphores(epi); if (err != kOTNoError) { makeEPBroken(epi,err); } return; } else { OTAtomicSetBit(&epi->stateFlags, kOtherEndClosed); } // // Sometimes our data sends get stopped with a kOTLookErr // because of a T_ORDREL from the other side (which doesn't close // the connection, it just means they are done sending data). // If so, we still end up in the notifier with the T_ORDREL event, // but we won't resume sending data unless we explictly check // here whether or not we need to do so. // //JMM Test this? if (OTAtomicClearBit(&epi->stateFlags, kSendIsBlocked)) { if (OTAtomicClearBit(&epi->stateFlags2, kTapSemaphoreWriteData)) interpreterProxy->signalSemaphoreWithIndex(epi->writeSemaIndex); }; return; } // // T_UNBINDCOMPLETE: // // This event occurs on completion of an OTUnbind(). // The endpoint is ready for reuse on a new inbound connection. // Note that the OTLIFO structure has atomic queue and dequeue, // which can be helpful for synchronization protection. // case T_UNBINDCOMPLETE: { if (result != kOTNoError) { // // Unbind errors can occur as a result of a bug in OT 1.1.1 and earlier // versions. The best recovery is to put the endpoint in the broken // list for recycling with a clean, new endpoint. // Since we only support 1.1.2 we don't expect to run this code. // makeEPBroken(epi,result); return; } return; } // // T_DISCONNECTCOMPLETE: // // This event occurs on completion of an OTSndDisconnect(). // Called when we abort a socket // case T_DISCONNECTCOMPLETE: { err = OTUnbind(epi->erf); if (err != kOTNoError) { makeEPBroken(epi,err); } purgeReadBuffers(epi); TapAllInterestedSemaphores(epi); if (OTAtomicTestBit(&epi->stateFlags2, kMakeEPIdle)) { //Make EP idle if marked as such only happens via destroy. makeEPIdle(epi); } epi->stateFlags = 0; epi->stateFlags2 = 0; epi->stateFlags3 = 0; SetEPLastError(epi,result); OTAtomicSetBit(&epi->stateFlags, kUnConnected); return; } // //Sleep sleep sleep all end points get trashed. // case kOTProviderWillClose: // reconfig stack disconnect and close { makeEPBroken(epi,-12345678); if(OTAtomicTestBit(&epi->stateFlags, kOpenInProgressBit)) return; OTSetSynchronous(epi->erf); // set endpoint to sync if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); OTSndDisconnect(epi->erf, NULL); OTUnbind(epi->erf); OTCloseProvider(epi->erf); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags3, kSleepKilledMe); TapAllInterestedSemaphores(epi); return; } case kOTProviderIsClosed: //Sleep lurks { makeEPBroken(epi,-12345678); OTSetSynchronous(epi->erf); // set endpoint to sync if ( OTAtomicSetBit(&epi->stateFlags2, kFlushDisconnectInProgressBit) == 0 ) err = OTIoctl(epi->erf, I_FLUSH, (void *)FLUSHRW); OTCloseProvider(epi->erf); OTAtomicSetBit(&epi->stateFlags, kUnConnected); OTAtomicClearBit(&epi->stateFlags, kConnected); OTAtomicClearBit(&epi->stateFlags, kThisEndClosed); OTAtomicClearBit(&epi->stateFlags, kOtherEndClosed); OTAtomicSetBit(&epi->stateFlags3, kSleepKilledMe); TapAllInterestedSemaphores(epi); return; } // // default: // // There are events which we don't handle, but we don't expect to see // any of them. When running in debugging mode while developing a program, // we exit with an informational alert. Later, in the production version // of the program, we ignore the event and try to keep running. // default: { return; } } } // // Notifier for listen socket: // static pascal void NotifierSocketListener(void* context, OTEventCode event, OTResult result, void* cookie) { EPInfo* epi = (EPInfo*) context; if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } JMMLogMessageAndNumber("\p Listener Event ",event); JMMLogMessageAndNumber("\p Listener Result ",result); JMMLogMessageAndNumber("\p Listener Id ",epi->semaIndex); switch (event) { // // T_BINDCOMPLETE: // // We only bind the listener endpoint, and bind failure is a fatal error. // Acceptor endpoints are bound within the OTAccept() call when they get a connection. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) makeEPUnconnected(epi); return; } // // T_LISTEN: // case T_LISTEN: { SetEPLastError(epi,result); makeEPConnected(epi); return; } // // T_ACCEPTCOMPLETE: // // This event is received by the listener endpoint only. // The acceptor endpoint will get a T_PASSCON event instead. // case T_ACCEPTCOMPLETE: { SetEPLastError(epi,result); return; } // // default: // // There are events which we don't handle, pass them onwards // default: { NotifierSocket(context, event, result, cookie); return; } } } // // Notifier for UDP listen socket: // static pascal void NotifierSocketUDP(void* context, OTEventCode event, OTResult result, void* cookie) { EPInfo* epi = (EPInfo*) context; OSStatus err; JMMLogMessageAndNumber("\p DNS Event ",event); JMMLogMessageAndNumber("\p DNS Result ",result); JMMLogMessageAndNumber("\p Id ",epi->semaIndex); if (gProgramState != kProgramRunning) { if ((event != T_OPENCOMPLETE) && (event != T_MEMORYRELEASED)) { return; } } switch (event) { //Some sort of UDP send error, too late to tell anyone? // case T_UDERR: { TUDErr uderr; InetAddress errorAddress; uderr.addr.maxlen = sizeof(InetAddress); uderr.addr.len = sizeof(InetAddress); uderr.addr.buf = (UInt8 *) &errorAddress; uderr.opt.maxlen = 0; uderr.opt.len = 0; uderr.opt.buf = NULL; err = OTRcvUDErr(epi->erf, &uderr); if (err != kOTNoError) makeEPBroken(epi,err); SetEPLastError(epi,uderr.error); return; } // // T_DATA: // // Got milk? // case T_DATA: { ReadData(epi,NULL,0); return; } // // T_BINDCOMPLETE: // // This event is returned when an endpoint has been bound. // No errors are expected. // case T_BINDCOMPLETE: { SetEPLastError(epi,result); OTAtomicClearBit(&epi->stateFlags3, kWaitingForBind); if (result != kOTNoError) { makeEPUnconnected(epi); return; } makeEPConnected(epi); return; } // // default: // // There are events which we don't handle, pass them onwards to the regular notifier // default: { NotifierSocket(context, event, result, cookie); return; } } } short gJMMFile=0; OTTimeStamp JMMStartTimeStamp; OTLIFO JMMLogBufferLIFO; // Buffers that are free to read into OTLIFO* JMMLogBufferBuffers = &JMMLogBufferLIFO; void JMMWriteLog() { OSErr error; OTLink* list = OTReverseList(OTLIFOStealList(JMMLogBufferBuffers)); OTLink* link; ReadBuffer *aBuffer; long dummySize; char CH=0x0D; if (true) return; error = HCreate(0,0,"\pJMMFOOBAR.txt",'TEXT','TEXT'); error = HOpenDF(0,0,"\pJMMFOOBAR.txt",fsRdWrPerm,&gJMMFile); error = SetFPos(gJMMFile,fsFromLEOF,0); while ( (link = list) != NULL ) { list = link->fNext; aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); error = FSWrite(gJMMFile,(long *)&aBuffer->readBufferSize,aBuffer->readBufferData); dummySize = 1; error = FSWrite(gJMMFile,&dummySize,&CH); } error = FSClose(gJMMFile); while ( (link = list) != NULL ) { list = link->fNext; aBuffer = OTGetLinkObject(link, ReadBuffer, fNext); OTFreeMem(aBuffer->readBufferData); OTFreeMem(aBuffer); } } void JMMLogMessage(Str255 input) { Str255 timeString; long timeStringLength,inputLength; UInt32 duration; ReadBuffer *readBufferObject; if (true) return; if (gJMMFile == 0) { gJMMFile = 1; OTGetTimeStamp(&JMMStartTimeStamp); JMMLogBufferBuffers->fHead = NULL; } duration = OTElapsedMilliseconds(&JMMStartTimeStamp); NumToString(duration,timeString); timeStringLength = (unsigned char) timeString[0]; inputLength = (unsigned char) input[0]; #if TARGET_API_MAC_CARBON readBufferObject = OTAllocMemInContext(sizeof(ReadBuffer), gClientContext); #else readBufferObject = OTAllocMem(sizeof(ReadBuffer)); #endif if (readBufferObject == NULL) return; OTMemzero(readBufferObject,sizeof(ReadBuffer)); #if TARGET_API_MAC_CARBON readBufferObject->readBufferData = OTAllocMemInContext(60, gClientContext); #else readBufferObject->readBufferData = OTAllocMem(60); #endif if (readBufferObject->readBufferData == NULL) { OTFreeMem(readBufferObject); return; } OTMemcpy(readBufferObject->readBufferData,timeString+1,timeStringLength); OTMemcpy(readBufferObject->readBufferData+timeStringLength,input+1,inputLength); readBufferObject->readBufferSize= timeStringLength+inputLength; OTLIFOEnqueue(JMMLogBufferBuffers, &readBufferObject->fNext); } void JMMLogMessageAndNumber(Str255 msg,long number) { Str255 buffer,numberString; long msgLength,numberLength; if (true) return; NumToString(number,numberString); numberLength = (unsigned char) numberString[0]; msgLength = (unsigned char) msg[0]; OTMemcpy(buffer+1,msg+1,msgLength); OTMemcpy(buffer+1+msgLength,numberString+1,numberLength); buffer[0] = (unsigned char) msgLength+numberLength; JMMLogMessage(buffer); } /* The Open Transport TCP/IP software modules provide a RawIP interface to the IP protocol hostname of '' lookup fails This is OK? Same on linux and old mac version JMM look at tlook page, not sure if we have completely understood it JMM is it legal to send a zero byte buffer need case for this? /* According to the XTI spec ("Section 4.6 Events and TLOOK Error indication"), the SndOrderlyDisconnect and RcvOrderlyDisconnect calls can fail because of a pending T_DISCONNECT event. This is XTI trying to tell you that the a connection on that endpoint broke. This can happen in this asynchronous wacky world of networks and your program will have to call a RcvDisconnect to acknowledge that your endpoint dropped. You might want to check out the OTI spec, which, although it is not always written in the most lucid fashion, does contain valuable information for those involved in OpenTransport programming. Further Information: Title: X/OPEN TRANSPORT INTERFACE (XTI) VER 2 [ 1.0 ed] Author: X/OPEN ISBN #: 0133534596 A Prior to Open Transport 1.3, there was no supported way of calling Open Transport from CFM-68K code. With the introduction of Open Transport 1.3, it is now possible to call the Open Transport client interface from CFM-68K code. The Open Transport 1.3 SDK includes stub libraries and a document, "Open Tpt CFM68K Dev. Note", which explains Open Transport's support for CFM-68K. which is supporte for syste 7.x but you can't install! No standalone installer exists. Coping the OT files kinda works */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SoundPlugin/sqMacSound.c ================================================ /* Carbon porting notes: Carbon doesn't support the SndPlayDoubleBuffer system routine. This is a command you put in the sound channel which repeatedly calls a callback routine. Technote 1198 describes the situation, a work-around and provides example code. I merely added this code to the end of this file and plugged it into the existing Squeak code. Karl Goiser 14/01/01 */ //johnmci@smalltalkconsulting.com Nov 6th 2000. Added sound volume logic /* Adjustments for pluginized VM * * Note: The Mac support files have not yet been fully converted to * pluginization. For the time being, it is assumed that they are linked * with the VM. When conversion is complete, they will no longer import * "sq.h" and they will access all VM functions and variables through * the interpreterProxy mechanism. */ #include "sq.h" #include "SoundPlugin.h" #if TARGET_API_MAC_CARBON #include #else #include #include #endif extern struct VirtualMachine* interpreterProxy; /* initialize/shutdown */ int soundInit() { return true; } int soundShutdown() { snd_Stop(); return 1;} /* End of adjustments for pluginized VM */ /****** Mac Sound Output Notes: The Squeak sound code produces 16-bit, stereo sound buffers. The was arrived at after experimentation on a PPC 601 at 110 MHz on which I found that: a. using 16-bit sound only slightly increased the background CPU burden and b. 16-bit sound yielded vastly superior sound quality. My understanding is that SoundManager 3.0 or later supports the 16-bit sound interface an all Macs, even if the hardware only supports 8-bits. If this is not true, however, change BYTES_PER_SAMPLE to 1. Then, either the Squeak code will need to be changed to use 8-bit sound buffers, or (preferrably) snd_PlaySamplesFromAtLength will need to do the conversion from 16 to 8 bits. I plan to cross that bridge if and when we need to. The code as currently written was to support Squeak code that generated 8-bit sound buffers. In earlier versions, I experimented with other sound buffer formats. Here are all the sound buffer formats that were used at one point or another: 1. mono, 8-bits -- packed array of bytes (not currently used) 2. stereo, 8-bits -- as above, with L and R channels in alternate bytes (not currently used) 3. stereo, 16-bits -- array of 32-bit words; with L and R channels in high and low half-words Note: 8-bit samples are encoded with 0x80 as the center (zero) value Note: 16-bit samples are encoded as standard, signed integers (i.e., 2's-complement) Note: When the sound drive is operating in "mono", the two stereo channels are mixed together. This feature was added in January, 1998. -- John Maloney, July 28, 1996 -- edited: John Maloney, January 5, 1998 Mac Sound Input Notes: Squeak sound input is currently defined to provide a single (mono) stream of signed 16-bit samples for all platforms. Platforms that only support 8-bit sound input should convert samples to signed 16 bit values, leaving the low order bits zero. Since the available sampling rates differ from platform to platform, the client may not get the requested sampling rate; however, the call snd_GetRecordingSampleRate returns the sampling rate. On many platforms, simultaneous record and playback is permitted only if the input and output sampling rates are the same. -- John Maloney, Aug 22, 1997 ******/ #define BYTES_PER_SAMPLE 2 /*** double-buffer state record ***/ typedef struct { int open; int stereo; int frameCount; int sampleRate; int lastFlipTime; int playSemaIndex; int bufSizeInBytes; int bufState0; int bufState1; int done; } PlayStateRec; /*** possible buffer states ***/ #define BUF_EMPTY 0 #define BUF_FULL 1 #define BUF_PLAYING 2 /*** record buffer state record ***/ /* Note: RECORD_BUFFER_SIZE should be a multiple of 4096 bytes to avoid clicking. (The clicking was observed on a Mac 8100; the behavior of other Macs could differ.) Note: G3 Series Powerbook requires minimum of 4 * 4096 buffer size for stereo. */ #define RECORD_BUFFER_SIZE (4096 * 2) typedef struct { SPB paramBlock; int stereo; int brokenOSXWasMono; int bytesPerSample; int recordSemaIndex; int readIndex; /* index of the next sample to read */ char samples[RECORD_BUFFER_SIZE]; } RecordBufferRec, *RecordBuffer; #if (defined ( __APPLE__ ) && defined ( __MACH__ )) || TARGET_API_MAC_CARBON enum { dbBufferReady = 0x00000001, /*double buffer is filled*/ dbLastBuffer = 0x00000004 /*last double buffer to play*/ }; struct SndDoubleBuffer { long dbNumFrames; long dbFlags; long dbUserInfo[2]; SInt8 dbSoundData[1]; }; typedef struct SndDoubleBuffer SndDoubleBuffer; typedef SndDoubleBuffer * SndDoubleBufferPtr; typedef CALLBACK_API( void , SndDoubleBackProcPtr )(SndChannelPtr channel, SndDoubleBufferPtr doubleBufferPtr); typedef STACK_UPP_TYPE(SndDoubleBackProcPtr) SndDoubleBackUPP; struct SndDoubleBufferHeader { short dbhNumChannels; short dbhSampleSize; short dbhCompressionID; short dbhPacketSize; UnsignedFixed dbhSampleRate; SndDoubleBufferPtr dbhBufferPtr[2]; SndDoubleBackUPP dbhDoubleBack; }; typedef struct SndDoubleBufferHeader SndDoubleBufferHeader; typedef SndDoubleBufferHeader * SndDoubleBufferHeaderPtr; struct SndDoubleBufferHeader2 { short dbhNumChannels; short dbhSampleSize; short dbhCompressionID; short dbhPacketSize; UnsignedFixed dbhSampleRate; SndDoubleBufferPtr dbhBufferPtr[2]; SndDoubleBackUPP dbhDoubleBack; OSType dbhFormat; }; typedef struct SndDoubleBufferHeader2 SndDoubleBufferHeader2; typedef SndDoubleBufferHeader2 * SndDoubleBufferHeader2Ptr; #endif /*** sound output variables ***/ SndChannelPtr chan; PlayStateRec bufState = {false, false, 0, 0, 0, 0, 0, 0, 0, true}; SndDoubleBufferHeader dblBufHeader; /*** sound input variables ***/ RecordBufferRec recordBuffer1, recordBuffer2; int recordingInProgress; long soundInputRefNum; /*** local functions ***/ pascal void DoubleBack(SndChannelPtr chan, SndDoubleBufferPtr buf); int FillBufferWithSilence(SndDoubleBufferPtr buf); pascal void FlipRecordBuffers(SPBPtr pb); int MixInSamples(int count, char *srcBufPtr, int srcStartIndex, char *dstBufPtr, int dstStartIndex); OSErr CarbonSndPlayDoubleBuffer (SndChannelPtr chan, SndDoubleBufferHeaderPtr theParams); pascal void DoubleBack(SndChannelPtr chan, SndDoubleBufferPtr buf) { /* Switch buffers (at interrupt time). The given buffer just finished playing. */ PlayStateRec *state; #pragma unused(chan) /* reference argument to avoid compiler warnings */ state = (PlayStateRec *) buf->dbUserInfo[0]; if (buf->dbUserInfo[1] == 0) { state->bufState0 = BUF_EMPTY; state->bufState1 = BUF_PLAYING; } else { state->bufState0 = BUF_PLAYING; state->bufState1 = BUF_EMPTY; } buf->dbNumFrames = state->frameCount; buf->dbFlags = buf->dbFlags | dbBufferReady; if (state->done) { buf->dbFlags = buf->dbFlags | dbLastBuffer; } else { interpreterProxy->signalSemaphoreWithIndex(state->playSemaIndex); } state->lastFlipTime = interpreterProxy->ioMicroMSecs(); FillBufferWithSilence(buf); /* avoids ugly stutter if not filled in time */ } int FillBufferWithSilence(SndDoubleBufferPtr buf) { unsigned int *sample, *lastSample; sample = (unsigned int *) &buf->dbSoundData[0]; lastSample = (unsigned int *) &buf->dbSoundData[bufState.bufSizeInBytes]; /* word-fill buffer with silence */ if (BYTES_PER_SAMPLE == 1) { while (sample < lastSample) { *sample++ = 0x80808080; /* Note: 0x80 is zero value for 8-bit samples */ } } else { while (sample < lastSample) { *sample++ = 0; } } return 0; } pascal void FlipRecordBuffers(SPBPtr pb) { /* called at interrupt time to exchange the active and inactive record buffers */ RecordBuffer thisBuffer = (RecordBuffer) pb; RecordBuffer nextBuffer = (RecordBuffer) pb->userLong; if (pb->error == 0) { /* restart recording using the other buffer */ SPBRecord(&nextBuffer->paramBlock, true); /* reset the read pointer for the buffer that has just been filled */ thisBuffer->readIndex = 0; interpreterProxy->signalSemaphoreWithIndex(nextBuffer->recordSemaIndex); } } /*** exported sound output functions ***/ int snd_AvailableSpace(void) { if (!bufState.open) return -1; if ((bufState.bufState0 == BUF_EMPTY) || (bufState.bufState1 == BUF_EMPTY)) { return bufState.bufSizeInBytes; } return 0; } int snd_PlaySamplesFromAtLength(int frameCount, int arrayIndex, int startIndex) { SndDoubleBufferPtr buf; int framesWritten; if (!bufState.open) return -1; if (bufState.bufState0 == BUF_EMPTY) { buf = dblBufHeader.dbhBufferPtr[0]; bufState.bufState0 = BUF_FULL; } else { if (bufState.bufState1 == BUF_EMPTY) { buf = dblBufHeader.dbhBufferPtr[1]; bufState.bufState1 = BUF_FULL; } else { return 0; /* neither buffer is available */ } } if (bufState.frameCount < frameCount) { framesWritten = bufState.frameCount; } else { framesWritten = frameCount; } if (BYTES_PER_SAMPLE == 1) { /* 8-bit samples */ unsigned char *src, *dst, *end; src = (unsigned char *) (arrayIndex + startIndex); end = (unsigned char *) src + (framesWritten * (bufState.stereo ? 2 : 1)); dst = (unsigned char *) &buf->dbSoundData[0]; while (src < end) { *dst++ = *src++; } } else { /* 16-bit samples */ short int *src, *dst, *end; src = (short int *) (arrayIndex + (startIndex * 4)); end = (short int *) (arrayIndex + ((startIndex + framesWritten) * 4)); dst = (short int *) &buf->dbSoundData[0]; if (bufState.stereo) { /* stereo */ while (src < end) { *dst++ = *src++; } } else { /* mono */ /* if mono, average the left and right channels of the source */ unsigned int a,b; while (src < end) { a = *src++; b = *src++; *dst++ = (a+b) / 2; } } } return framesWritten; } int MixInSamples(int count, char *srcBufPtr, int srcStartIndex, char *dstBufPtr, int dstStartIndex) { int sample; if (BYTES_PER_SAMPLE == 1) { /* 8-bit samples */ unsigned char *src, *dst, *end; src = (unsigned char *) srcBufPtr + srcStartIndex; end = (unsigned char *) srcBufPtr + (count * (bufState.stereo ? 2 : 1)); dst = (unsigned char *) dstBufPtr + dstStartIndex; while (src < end) { sample = *dst + (*src++ - 128); if (sample > 255) sample = 255; if (sample < 0) sample = 0; *dst++ = sample; } } else { /* 16-bit samples */ short int *src, *dst, *end; src = (short int *) (srcBufPtr + (srcStartIndex * 4)); end = (short int *) (srcBufPtr + ((srcStartIndex + count) * 4)); if (bufState.stereo) { /* stereo */ dst = (short int *) (dstBufPtr + (dstStartIndex * 4)); while (src < end) { sample = *dst + *src++; if (sample > 32767) sample = 32767; if (sample < -32767) sample = -32767; *dst++ = sample; } } else { /* mono */ /* if mono, average the left and right channels of the source */ unsigned int a,b; dst = (short int *) (dstBufPtr + (dstStartIndex * 2)); while (src < end) { a = *src++; b = *src++; sample = *dst + ((a+b) / 2); if (sample > 32767) sample = 32767; if (sample < -32767) sample = -32767; *dst++ = sample; } } } return 0; } int snd_InsertSamplesFromLeadTime(int frameCount, int srcBufPtr, int samplesOfLeadTime) { SndDoubleBufferPtr bufPlaying, otherBuf; int samplesInserted, startSample, count; if (!bufState.open) return -1; if (bufState.bufState0 == BUF_PLAYING) { bufPlaying = dblBufHeader.dbhBufferPtr[0]; otherBuf = dblBufHeader.dbhBufferPtr[1]; } else { bufPlaying = dblBufHeader.dbhBufferPtr[1]; otherBuf = dblBufHeader.dbhBufferPtr[0]; } samplesInserted = 0; /* mix as many samples as can fit into the remainder of the currently playing buffer */ startSample = ((bufState.sampleRate * (interpreterProxy->ioMicroMSecs() - bufState.lastFlipTime)) / 1000) + samplesOfLeadTime; if (startSample < bufState.frameCount) { count = bufState.frameCount - startSample; if (count > frameCount) count = frameCount; MixInSamples(count, (char *) srcBufPtr, 0, (char *) &bufPlaying->dbSoundData[0], startSample); samplesInserted = count; } /* mix remaining samples into the inactive buffer */ count = bufState.frameCount; if (count > (frameCount - samplesInserted)) { count = frameCount - samplesInserted; } MixInSamples(count, (char *) srcBufPtr, samplesInserted, (char *) &otherBuf->dbSoundData[0], 0); return samplesInserted + count; } int snd_PlaySilence(void) { if (!bufState.open) return -1; if (bufState.bufState0 == BUF_EMPTY) { FillBufferWithSilence(dblBufHeader.dbhBufferPtr[0]); bufState.bufState0 = BUF_FULL; } else { if (bufState.bufState1 == BUF_EMPTY) { FillBufferWithSilence(dblBufHeader.dbhBufferPtr[1]); bufState.bufState1 = BUF_FULL; } else { return 0; /* neither buffer is available */ } } return bufState.bufSizeInBytes; } int snd_Start(int frameCount, int samplesPerSec, int stereo, int semaIndex) { OSErr err; SndDoubleBufferPtr buffer; int bytesPerFrame, bufferBytes, i; bytesPerFrame = stereo ? 2 * BYTES_PER_SAMPLE : BYTES_PER_SAMPLE; bufferBytes = ((frameCount * bytesPerFrame) / 8) * 8; /* Note: Must round bufferBytes down to an 8-byte boundary to avoid clicking!!! */ if (bufState.open) { /* still open from last time; clean up before continuing */ snd_Stop(); } bufState.open = false; /* set to true if successful */ bufState.stereo = stereo; bufState.frameCount = bufferBytes / bytesPerFrame; bufState.sampleRate = samplesPerSec; bufState.lastFlipTime = interpreterProxy->ioMicroMSecs(); bufState.playSemaIndex = semaIndex; bufState.bufSizeInBytes = bufferBytes; bufState.bufState0 = BUF_EMPTY; bufState.bufState1 = BUF_EMPTY; bufState.done = false; dblBufHeader.dbhNumChannels = stereo ? 2 : 1; dblBufHeader.dbhSampleSize = BYTES_PER_SAMPLE * 8; dblBufHeader.dbhCompressionID = 0; dblBufHeader.dbhPacketSize = 0; dblBufHeader.dbhSampleRate = samplesPerSec << 16; /* convert to fixed point */ #if TARGET_API_MAC_CARBON dblBufHeader.dbhDoubleBack = nil; #else dblBufHeader.dbhDoubleBack = NewSndDoubleBackProc(DoubleBack); #endif chan = NULL; err = SndNewChannel(&chan, sampledSynth, 0, NULL); if (err != noErr) return false; /* could not open sound channel */ for (i = 0; i < 2; i++) { buffer = (SndDoubleBufferPtr) NewPtrClear(sizeof(SndDoubleBuffer) + bufState.bufSizeInBytes); if (buffer == NULL) { /* could not allocate memory for a buffer; clean up and abort */ SndDisposeChannel(chan, true); #if !TARGET_API_MAC_CARBON DisposeRoutineDescriptor(dblBufHeader.dbhDoubleBack); #endif if (i == 1) { /* free the first buffer */ DisposePtr((char *) dblBufHeader.dbhBufferPtr[1]); dblBufHeader.dbhBufferPtr[1] = NULL; } return false; } buffer->dbNumFrames = bufState.frameCount; buffer->dbFlags = dbBufferReady; buffer->dbUserInfo[0] = (long) &bufState; buffer->dbUserInfo[1] = i; FillBufferWithSilence(buffer); dblBufHeader.dbhBufferPtr[i] = buffer; } #if TARGET_API_MAC_CARBON err = CarbonSndPlayDoubleBuffer(chan, &dblBufHeader); #else err = SndPlayDoubleBuffer(chan, &dblBufHeader); #endif if (err != noErr) return false; /* could not play double buffer */ bufState.open = true; return true; } int snd_Stop(void) { OSErr err; SndDoubleBufferPtr buffer; SCStatus status; long i, junk; if (!bufState.open) return 0; bufState.open = false; bufState.done = true; while (true) { err = SndChannelStatus(chan, sizeof(status), &status); if (err != noErr) break; /* could not get channel status */ if (!status.scChannelBusy) break; Delay(1, (void *) &junk); } SndDisposeChannel(chan, true); #if !TARGET_API_MAC_CARBON DisposeRoutineDescriptor(dblBufHeader.dbhDoubleBack); #endif for (i = 0; i < 2; i++) { buffer = dblBufHeader.dbhBufferPtr[i]; if (buffer != NULL) { DisposePtr((char *) buffer); } dblBufHeader.dbhBufferPtr[i] = NULL; } bufState.open = false; return 0; } /*** exported sound input functions ***/ int snd_SetRecordLevel(int level) { /* set the recording level to a value between 0 (minimum gain) and 1000. */ Fixed inputGainArg; int err; if (!recordingInProgress || (level < 0) || (level > 1000)) { interpreterProxy->success(false); return 0; /* noop if not recording */ } inputGainArg = ((500 + level) << 16) / 1000; /* gain is Fixed between 0.5 and 1.5 */ err = SPBSetDeviceInfo(soundInputRefNum, siInputGain, &inputGainArg); /* don't fail on error; hardware may not support setting the gain */ return 0; } int snd_StartRecording(int desiredSamplesPerSec, int stereo, int semaIndex) { /* turn on sound recording, trying to use a sampling rate close to the one specified. semaIndex is the index in the exportedObject array of a semaphore to be signalled when input data is available. */ Str255 deviceName = "\p"; short automaticGainControlArg; Fixed inputGainArg; long compressionTypeArg; short continuousArg; short sampleSizeArg; short channelCountArg; UnsignedFixed sampleRateArg; int err; long brokenOSXWasMono=0; err = SPBOpenDevice(deviceName, siWritePermission, &soundInputRefNum); if (err != noErr) { interpreterProxy->success(false); return 0; } channelCountArg = stereo ? 2 : 1; err = SPBSetDeviceInfo(soundInputRefNum, siNumberChannels, &channelCountArg); if (err == notEnoughHardwareErr) { stereo = 1; brokenOSXWasMono = 1; channelCountArg = stereo ? 2 : 1; err = SPBSetDeviceInfo(soundInputRefNum, siNumberChannels, &channelCountArg); } if (err != noErr) { interpreterProxy->success(false); SPBCloseDevice(soundInputRefNum); return 0; } /* try to initialize some optional parameters, but don't fail if we can't */ automaticGainControlArg = false; SPBSetDeviceInfo(soundInputRefNum, siAGCOnOff, &automaticGainControlArg); inputGainArg = 1 << 16; /* 1.0 in Fixed */ SPBSetDeviceInfo(soundInputRefNum, siInputGain, &inputGainArg); compressionTypeArg = 'NONE'; SPBSetDeviceInfo(soundInputRefNum, siCompressionType, &compressionTypeArg); continuousArg = true; err = SPBSetDeviceInfo(soundInputRefNum, siContinuous, &continuousArg); if (err != noErr) { interpreterProxy->success(false); SPBCloseDevice(soundInputRefNum); return 0; } sampleSizeArg = 16; err = SPBSetDeviceInfo(soundInputRefNum, siSampleSize, &sampleSizeArg); if (err != noErr) { /* use 8-bit samples */ sampleSizeArg = 8; err = SPBSetDeviceInfo(soundInputRefNum, siSampleSize, &sampleSizeArg); if (err != noErr) { interpreterProxy->success(false); SPBCloseDevice(soundInputRefNum); return 0; } } /* try to set the client's desired sample rate */ sampleRateArg = desiredSamplesPerSec << 16; err = SPBSetDeviceInfo(soundInputRefNum, siSampleRate, &sampleRateArg); if (err != noErr) { /* if client's rate fails, try the nearest common sampling rates in {11025, 22050, 44100} */ if (desiredSamplesPerSec <= 16538) { sampleRateArg = 11025 << 16; } else { if (desiredSamplesPerSec <= 33075) { sampleRateArg = 22050 << 16; } else { sampleRateArg = 44100 << 16; } } /* even if following fails, recording can go on at the default sample rate */ SPBSetDeviceInfo(soundInputRefNum, siSampleRate, &sampleRateArg); } recordBuffer1.paramBlock.inRefNum = soundInputRefNum; recordBuffer1.paramBlock.count = RECORD_BUFFER_SIZE; recordBuffer1.paramBlock.milliseconds = 0; recordBuffer1.paramBlock.bufferLength = RECORD_BUFFER_SIZE; recordBuffer1.paramBlock.bufferPtr = recordBuffer1.samples; #if TARGET_API_MAC_CARBON recordBuffer1.paramBlock.completionRoutine = NewSICompletionUPP(FlipRecordBuffers); #else recordBuffer1.paramBlock.completionRoutine = NewSICompletionProc(FlipRecordBuffers); #endif recordBuffer1.paramBlock.interruptRoutine = nil; recordBuffer1.paramBlock.userLong = (long) &recordBuffer2; /* pointer to other buffer */ recordBuffer1.paramBlock.error = noErr; recordBuffer1.paramBlock.unused1 = 0; recordBuffer1.stereo = stereo; recordBuffer1.brokenOSXWasMono = brokenOSXWasMono; recordBuffer1.bytesPerSample = sampleSizeArg == 8 ? 1 : 2; recordBuffer1.recordSemaIndex = semaIndex; recordBuffer1.readIndex = RECORD_BUFFER_SIZE; recordBuffer2.paramBlock.inRefNum = soundInputRefNum; recordBuffer2.paramBlock.count = RECORD_BUFFER_SIZE; recordBuffer2.paramBlock.milliseconds = 0; recordBuffer2.paramBlock.bufferLength = RECORD_BUFFER_SIZE; recordBuffer2.paramBlock.bufferPtr = recordBuffer2.samples; #if TARGET_API_MAC_CARBON recordBuffer2.paramBlock.completionRoutine = NewSICompletionUPP(FlipRecordBuffers); #else recordBuffer2.paramBlock.completionRoutine = NewSICompletionProc(FlipRecordBuffers); #endif recordBuffer2.paramBlock.interruptRoutine = nil; recordBuffer2.paramBlock.userLong = (long) &recordBuffer1; /* pointer to other buffer */ recordBuffer2.paramBlock.error = noErr; recordBuffer2.paramBlock.unused1 = 0; recordBuffer2.stereo = stereo; recordBuffer2.brokenOSXWasMono = brokenOSXWasMono; recordBuffer2.bytesPerSample = sampleSizeArg == 8 ? 1 : 2; recordBuffer2.recordSemaIndex = semaIndex; recordBuffer2.readIndex = RECORD_BUFFER_SIZE; err = SPBRecord(&recordBuffer1.paramBlock, true); if (err != noErr) { interpreterProxy->success(false); SPBCloseDevice(soundInputRefNum); return 0; } recordingInProgress = true; return 0; } int snd_StopRecording(void) { /* turn off sound recording */ int err; if (!recordingInProgress) return 0; /* noop if not recording */ err = SPBStopRecording(soundInputRefNum); if (err != noErr) interpreterProxy->success(false); SPBCloseDevice(soundInputRefNum); #if TARGET_API_MAC_CARBON DisposeSICompletionUPP(recordBuffer1.paramBlock.completionRoutine); #else DisposeRoutineDescriptor(recordBuffer1.paramBlock.completionRoutine); #endif recordBuffer1.paramBlock.completionRoutine = nil; #if TARGET_API_MAC_CARBON DisposeSICompletionUPP(recordBuffer2.paramBlock.completionRoutine); #else DisposeRoutineDescriptor(recordBuffer2.paramBlock.completionRoutine); #endif recordBuffer2.paramBlock.completionRoutine = nil; recordBuffer1.recordSemaIndex = 0; recordBuffer2.recordSemaIndex = 0; recordingInProgress = false; return 0; } double snd_GetRecordingSampleRate(void) { /* return the actual recording rate; fail if not currently recording */ UnsignedFixed sampleRateArg; int err; if (!recordingInProgress) { interpreterProxy->success(false); return 0.0; } err = SPBGetDeviceInfo(soundInputRefNum, siSampleRate, &sampleRateArg); if (err != noErr) { interpreterProxy->success(false); return 0.0; } return (double) ((sampleRateArg >> 16) & 0xFFFF) + ((double) (sampleRateArg & 0xFFFF) / 65536.0); } int snd_RecordSamplesIntoAtLength(int buf, int startSliceIndex, int bufferSizeInBytes) { /* if data is available, copy as many sample slices as possible into the given buffer starting at the given slice index. do not write past the end of the buffer, which is buf + bufferSizeInBytes. return the number of slices (not bytes) copied. a slice is one 16-bit sample in mono or two 16-bit samples in stereo. */ int bytesPerSlice = (recordBuffer1.brokenOSXWasMono) ? 2 : ((recordBuffer1.stereo) ? 4 : 2); char *nextBuf = (char *) buf + (startSliceIndex * bytesPerSlice); char *bufEnd = (char *) buf + bufferSizeInBytes; char *src, *srcEnd; RecordBuffer recBuf = nil; int bytesCopied; if (!recordingInProgress) { interpreterProxy->success(false); return 0; } /* select the buffer with unread samples, if any */ recBuf = nil; if (recordBuffer1.readIndex < RECORD_BUFFER_SIZE) recBuf = &recordBuffer1; if (recordBuffer2.readIndex < RECORD_BUFFER_SIZE) recBuf = &recordBuffer2; if (recBuf == nil) return 0; /* no samples available */ /* copy samples into the client's buffer */ src = &recBuf->samples[0] + recBuf->readIndex; srcEnd = &recBuf->samples[RECORD_BUFFER_SIZE]; if (recBuf->bytesPerSample == 1) { while ((src < srcEnd) && (nextBuf < bufEnd)) { /* convert 8-bit sample to 16-bit sample */ *nextBuf++ = (*src++) - 128; /* convert from [0-255] to [-128-127] */ *nextBuf++ = 0; /* low-order byte is zero */ } } else { if (recordBuffer1.brokenOSXWasMono) { src++;src++; while ((src < srcEnd) && (nextBuf < bufEnd)) { *nextBuf++ = *src++; *nextBuf++ = *src++; src++;src++; } } else { while ((src < srcEnd) && (nextBuf < bufEnd)) { *nextBuf++ = *src++; } } } recBuf->readIndex = src - &recBuf->samples[0]; /* update read index */ /* return the number of slices copied */ bytesCopied = (int) nextBuf - (buf + (startSliceIndex * bytesPerSlice)); return bytesCopied / bytesPerSlice; } //Nov 6th 2000 void snd_Volume(double *left, double *right) { double temp; SndCommand cmd; long results; OSErr err; *left = 1.0; *right = 1.0; cmd.cmd = getVolumeCmd; cmd.param1 = 0; cmd.param2 = (long) &results; err = -1; if (chan != null) err = SndDoImmediate(chan,&cmd); if (err != noErr) { err = GetDefaultOutputVolume(&results); } if (err != noErr) return; temp = (results & 0xFFFF); *left = temp/256.0; temp = (results >> 16); *right = temp/256.0; } void snd_SetVolume(double left, double right) { unsigned long tempLeft,tempRight; SndCommand cmd; OSErr err; tempLeft = left*256.0 + 0.5; tempLeft = tempLeft & 0xFFFF; tempRight = right*256.0 + 0.5; tempRight= tempRight & 0xFFFF; cmd.cmd = volumeCmd; cmd.param1 = 0; cmd.param2 = (tempRight << 16) | tempLeft; err = -1; if (chan != null) err= SndDoImmediate(chan,&cmd); if (err != noErr) { err = SetDefaultOutputVolume(cmd.param2); } } /* File: CarbonSndPlayDB.c Description:Routines demonstrating how to create a function that works much like the original SndPlayDoubleBuffer but is Carbon compatible (which SndPlayDoubleBuffer isn't). Author: MC Copyright: Copyright 1999-2000 Apple Computer, Inc. All rights reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): */ /* Requirements for using this shim code: 1) The sound channel's queue must be empty before you call CarbonSndPlayDoubleBuffer 2) You cannot call MySndDoImmediate until CarbonSndPlayDoubleBuffer returns. Be careful about calling MySndDoImmediate at interrupt time with a quietCmd. */ /* Some code is commented out becuase knowing who calls it and how allows shortcuts Karl Goiser 14/01/01 */ #if TARGET_API_MAC_CARBON #undef UNNECESSARY_FOR_SQUEAK #if UNNECESSARY_FOR_SQUEAK static pascal void CarbonSndPlayDoubleBufferCleanUpProc (SndChannelPtr theChannel, SndCommand * theCallBackCmd); #endif static pascal void CarbonSndPlayDoubleBufferCallBackProc (SndChannelPtr theChannel, SndCommand * theCallBackCmd); static void InsertSndDoCommand (SndChannelPtr chan, SndCommand * theCmd); static pascal void NMResponseProc (NMRecPtr nmReqPtr); #define kBufSize 2048 // Structs struct PerChanInfo { QElemPtr qLink; /* next queue entry */ short qType; /* queue type = 0 */ short stopping; #if DEBUG OSType magic; #endif SndCallBackUPP usersCallBack; SndDoubleBufferHeaderPtr theParams; CmpSoundHeader soundHeader; }; typedef struct PerChanInfo PerChanInfo; typedef struct PerChanInfo * PerChanInfoPtr; // Globals Boolean gNMRecBusy; NMRecPtr gNMRecPtr; QHdrPtr gFreeList; Ptr gSilenceTwos; Ptr gSilenceOnes; static SndCallBackUPP gCarbonSndPlayDoubleBufferCallBackUPP = nil; static SndCallBackUPP gCarbonSndPlayDoubleBufferCleanUpUPP = nil; #if UNNECESSARY_FOR_SQUEAK // Remember this routine could be called at interrupt time, so don't allocate or deallocate memory. OSErr MySndDoImmediate (SndChannelPtr chan, SndCommand * cmd) { PerChanInfoPtr perChanInfoPtr; // Is this being called on one of the sound channels we are manipulating? // If so, we need to pull our callback out of the way so that the user's commands run if (gCarbonSndPlayDoubleBufferCallBackUPP == chan->callBack) { if (quietCmd == cmd->cmd || flushCmd == cmd->cmd) { // We know that our callBackCmd is the first item in the queue if this is our channel perChanInfoPtr = (PerChanInfoPtr)(chan->queue[chan->qHead].param2); #if DEBUG if (perChanInfoPtr->magic != 'SANE') DebugStr("\pBAD in MySndDoImmediate"); #endif perChanInfoPtr->stopping = true; Enqueue ((QElemPtr)perChanInfoPtr, gFreeList); if (! OTAtomicSetBit (&gNMRecBusy, 0)) { NMInstall (gNMRecPtr); } chan->callBack = perChanInfoPtr->usersCallBack; } } return (SndDoImmediate (chan, cmd)); } #endif /* UNNECESSARY_FOR_SQUEAK */ // This must be called at task time. OSErr CarbonSndPlayDoubleBuffer (SndChannelPtr chan, SndDoubleBufferHeaderPtr theParams) { OSErr err; CompressionInfo compInfo; PerChanInfoPtr perChanInfoPtr; SndCommand playCmd; SndCommand callBack; if (nil == chan) return badChannel; if (nil == theParams) return paramErr; if (nil == gFreeList) { // This can't ever be disposed since we don't know when we might need to use it (at interrupt time) gFreeList = (QHdrPtr)NewPtrClear (sizeof (QHdr)); err = MemError (); if (noErr != err) goto exit; } if (nil == gSilenceOnes) { short i; // This can't ever be disposed since we don't know when we might need to use it (at interrupt time) gSilenceOnes = NewPtr (kBufSize); err = MemError (); if (noErr != err) goto exit; for (i = 0; i < kBufSize; i++) *gSilenceOnes++ = (char)0x80; } if (nil == gSilenceTwos) { // This can't ever be disposed since we don't know when we might need to use it (at interrupt time) gSilenceTwos = NewPtrClear (kBufSize); err = MemError (); if (noErr != err) goto exit; } if (nil == gNMRecPtr) { // This can't ever be disposed since we don't know when we might need to use it (at interrupt time) gNMRecPtr = (NMRecPtr)NewPtr (sizeof (NMRec)); err = MemError (); if (noErr != err) goto exit; // Set up our NMProc info that will dispose of most (but not all) of our memory gNMRecPtr->qLink = nil; gNMRecPtr->qType = 8; gNMRecPtr->nmFlags = 0; gNMRecPtr->nmPrivate = 0; gNMRecPtr->nmReserved = 0; gNMRecPtr->nmMark = nil; gNMRecPtr->nmIcon = nil; gNMRecPtr->nmSound = nil; gNMRecPtr->nmStr = nil; gNMRecPtr->nmResp = NewNMUPP (NMResponseProc); gNMRecPtr->nmRefCon = 0; } perChanInfoPtr = (PerChanInfoPtr)NewPtr (sizeof (PerChanInfo)); err = MemError (); if (noErr != err) goto exit; // Init basic per channel information perChanInfoPtr->qLink = nil; perChanInfoPtr->qType = 0; // not used perChanInfoPtr->stopping = 0; #if DEBUG perChanInfoPtr->magic = 'SANE'; #endif perChanInfoPtr->theParams = theParams; // Have to remember the user's callback function from the sound because // we are going to overwrite it with our own callback function. perChanInfoPtr->usersCallBack = chan->callBack; // Set up the sound header for the bufferCmd that will be used to play // the buffers passed in by the SndPlayDoubleBuffer call. perChanInfoPtr->soundHeader.samplePtr = (Ptr)(theParams->dbhBufferPtr[0]->dbSoundData); perChanInfoPtr->soundHeader.numChannels = theParams->dbhNumChannels; perChanInfoPtr->soundHeader.sampleRate = theParams->dbhSampleRate; perChanInfoPtr->soundHeader.loopStart = 0; perChanInfoPtr->soundHeader.loopEnd = 0; perChanInfoPtr->soundHeader.encode = cmpSH; perChanInfoPtr->soundHeader.baseFrequency = kMiddleC; perChanInfoPtr->soundHeader.numFrames = (unsigned long)theParams->dbhBufferPtr[0]->dbNumFrames; // perChanInfoPtr->soundHeader.AIFFSampleRate = 0; // unused perChanInfoPtr->soundHeader.markerChunk = nil; perChanInfoPtr->soundHeader.futureUse2 = nil; perChanInfoPtr->soundHeader.stateVars = nil; perChanInfoPtr->soundHeader.leftOverSamples = nil; perChanInfoPtr->soundHeader.compressionID = theParams->dbhCompressionID; perChanInfoPtr->soundHeader.packetSize = (unsigned short)theParams->dbhPacketSize; perChanInfoPtr->soundHeader.snthID = 0; perChanInfoPtr->soundHeader.sampleSize = (unsigned short)theParams->dbhSampleSize; perChanInfoPtr->soundHeader.sampleArea[0] = 0; // Is the sound compressed? If so, we need to treat theParams as a SndDoubleBufferHeader2Ptr. if (0 != theParams->dbhCompressionID) { // Sound is compressed err = GetCompressionInfo (theParams->dbhCompressionID, ((SndDoubleBufferHeader2Ptr)theParams)->dbhFormat, theParams->dbhNumChannels, theParams->dbhSampleSize, &compInfo); if (noErr != err) goto exitDispose; perChanInfoPtr->soundHeader.format = compInfo.format; } else { // Sound is not compressed perChanInfoPtr->soundHeader.format = kSoundNotCompressed; } playCmd.cmd = bufferCmd; playCmd.param1 = 0; // unused playCmd.param2 = (long)&perChanInfoPtr->soundHeader; callBack.cmd = callBackCmd; callBack.param1 = 0; // which buffer to fill, 0 buffer, 1, 0, ... callBack.param2 = (long)perChanInfoPtr; // Install our callback function pointer straight into the sound channel structure if (nil == gCarbonSndPlayDoubleBufferCallBackUPP) { gCarbonSndPlayDoubleBufferCallBackUPP = NewSndCallBackUPP(CarbonSndPlayDoubleBufferCallBackProc); } chan->callBack = gCarbonSndPlayDoubleBufferCallBackUPP; #if UNNECESSARY_FOR_SQUEAK if (gCarbonSndPlayDoubleBufferCleanUpUPP == nil) { gCarbonSndPlayDoubleBufferCleanUpUPP = NewSndCallBackProc (CarbonSndPlayDoubleBufferCleanUpProc); } #endif /* UNNECESSARY_FOR_SQUEAK */ err = SndDoCommand (chan, &playCmd, true); if (noErr != err) goto exitDispose; err = SndDoCommand (chan, &callBack, true); if (noErr != err) goto exitDispose; exit: return err; exitDispose: if (nil != perChanInfoPtr) DisposePtr ((Ptr)perChanInfoPtr); goto exit; } #if UNNECESSARY_FOR_SQUEAK static pascal void CarbonSndPlayDoubleBufferCleanUpProc( SndChannelPtr theChannel, SndCommand * theCallBackCmd) { PerChanInfoPtr perChanInfoPtr; perChanInfoPtr = (PerChanInfoPtr)(theCallBackCmd->param2); #if DEBUG if (perChanInfoPtr->magic != 'SANE') DebugStr("\pBAD in CarbonSndPlayDoubleBufferCleanUpProc"); #endif // Put our per channel data on the free queue so we can clean up later Enqueue ((QElemPtr)perChanInfoPtr, gFreeList); // Have to install our Notification Manager routine so that we can clean up the gFreeList if (! OTAtomicSetBit (&gNMRecBusy, 0)) { NMInstall (gNMRecPtr); } // Have to put the user's callback proc back so they get called when the next buffer finishes theChannel->callBack = perChanInfoPtr->usersCallBack; } #endif /* UNNECESSARY_FOR_SQUEAK */ static pascal void CarbonSndPlayDoubleBufferCallBackProc (SndChannelPtr theChannel, SndCommand * theCallBackCmd) { SndDoubleBufferHeaderPtr theParams; SndDoubleBufferPtr emptyBuf; SndDoubleBufferPtr nextBuf; PerChanInfoPtr perChanInfoPtr; SndCommand playCmd; perChanInfoPtr = (PerChanInfoPtr)(theCallBackCmd->param2); #if DEBUG if (perChanInfoPtr->magic != 'SANE') DebugStr("\pBAD in CarbonSndPlayDoubleBufferCallBackProc"); #endif if (true == perChanInfoPtr->stopping) goto exit; theParams = perChanInfoPtr->theParams; // The buffer that just played and needs to be filled emptyBuf = theParams->dbhBufferPtr[theCallBackCmd->param1]; // Clear the ready flag emptyBuf->dbFlags ^= dbBufferReady; // This is the buffer to play now nextBuf = theParams->dbhBufferPtr[!theCallBackCmd->param1]; // Check to see if it is ready, or if we have to wait a bit if (nextBuf->dbFlags & dbBufferReady) { perChanInfoPtr->soundHeader.numFrames = (unsigned long)nextBuf->dbNumFrames; perChanInfoPtr->soundHeader.samplePtr = (Ptr)(nextBuf->dbSoundData); // Flip the bit telling us which buffer is next theCallBackCmd->param1 = !theCallBackCmd->param1; // If this isn't the last buffer, call the user's fill routine if (!(nextBuf->dbFlags & dbLastBuffer)) { // Declare a function pointer to the user's double back proc void (*doubleBackProc)(SndChannel*, SndDoubleBuffer*); // Call user's double back proc doubleBackProc = (void*)DoubleBack; (*doubleBackProc) (theChannel, emptyBuf); } else { // Call our clean up proc when the last buffer finishes theChannel->callBack = gCarbonSndPlayDoubleBufferCleanUpUPP; } } else { // We have to wait for the buffer to become ready. // The real SndPlayDoubleBuffer would play a short bit of silence waiting for // the user to read the audio from disk, so that's what we do here. #if DEBUG DebugStr ("\p buffer is not ready!"); #endif // Play a short section of silence so that we can check the ready flag again if (theParams->dbhSampleSize == 8) { perChanInfoPtr->soundHeader.numFrames = (UInt32)(kBufSize / theParams->dbhNumChannels); perChanInfoPtr->soundHeader.samplePtr = gSilenceOnes; } else { perChanInfoPtr->soundHeader.numFrames = (UInt32)(kBufSize / (theParams->dbhNumChannels * (theParams->dbhSampleSize / 8))); perChanInfoPtr->soundHeader.samplePtr = gSilenceTwos; } } // Insert our callback command InsertSndDoCommand (theChannel, theCallBackCmd); // Play the next buffer playCmd.cmd = bufferCmd; playCmd.param1 = 0; playCmd.param2 = (long)&(perChanInfoPtr->soundHeader); InsertSndDoCommand (theChannel, &playCmd); exit: return; } static void InsertSndDoCommand (SndChannelPtr chan, SndCommand * newCmd) { if (-1 == chan->qHead) { chan->qHead = chan->qTail; } if (1 <= chan->qHead) { chan->qHead--; } else { chan->qHead = chan->qTail; } chan->queue[chan->qHead] = *newCmd; } static pascal void NMResponseProc (NMRecPtr nmReqPtr) { PerChanInfoPtr perChanInfoPtr; OSErr err; NMRemove (nmReqPtr); gNMRecBusy = false; do { perChanInfoPtr = (PerChanInfoPtr)gFreeList->qHead; if (nil != perChanInfoPtr) { err = Dequeue ((QElemPtr)perChanInfoPtr, gFreeList); if (noErr == err) { DisposePtr ((Ptr)perChanInfoPtr); } } } while (nil != perChanInfoPtr && noErr == err); } #endif /* TARGET_API_MAC_CARBON */ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SoundPlugin/sqMacUnixInterfaceSound.c ================================================ /* * sqMacUnixInterfaceSound.c * SqueakVMForCarbon * * Created by John M McIntosh on 2/3/05. * Copyright 2005 __MyCompanyName__. All rights reserved. * */ #include "sq.h" #include "sqMacUnixInterfaceSound.h" #include "SoundPlugin.h" #include "SqModule.h" #include "SqSound.h" extern sqInt sound_Stop(void); sqInt soundInit(void) { return 1; } sqInt soundShutdown(void) { sound_StopRecording(); return 1; } /* output */ sqInt snd_AvailableSpace(void) { return sound_AvailableSpace(); } sqInt snd_InsertSamplesFromLeadTime(sqInt frameCount, void* srcBufPtr, sqInt samplesOfLeadTime) { return sound_InsertSamplesFromLeadTime(frameCount, srcBufPtr, samplesOfLeadTime); } sqInt snd_PlaySamplesFromAtLength(sqInt frameCount, void *srcBufPtr, sqInt startIndex) { return sound_PlaySamplesFromAtLength(frameCount, srcBufPtr, startIndex); } sqInt snd_PlaySilence(void) { return sound_PlaySilence(); } sqInt snd_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex) { return sound_Start(frameCount, samplesPerSec, stereo, semaIndex); } sqInt snd_Stop(void) { return sound_Stop(); } /* input */ sqInt snd_StartRecording(sqInt desiredSamplesPerSec, sqInt stereo, sqInt semaIndex) { return sound_StartRecording(desiredSamplesPerSec, stereo, semaIndex); } sqInt snd_StopRecording(void) { return sound_StopRecording(); } double snd_GetRecordingSampleRate(void) { return sound_GetRecordingSampleRate(); } sqInt snd_RecordSamplesIntoAtLength(void *buf, sqInt startSliceIndex, sqInt bufferSizeInBytes) { return sound_RecordSamplesIntoAtLength(buf, startSliceIndex, bufferSizeInBytes); } /* mixer */ void snd_Volume(double *left, double *right) { sound_Volume(left, right); } void snd_SetVolume(double left, double right) { sound_SetVolume(left, right); } int snd_SetRecordLevel(sqInt level) { return sound_SetRecordLevel(level); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SoundPlugin/sqMacUnixInterfaceSound.h ================================================ /* * sqMacUnixInterfaceSound.h * SqueakVMForCarbon * * Created by John M McIntosh on 2/3/05. * */ sqInt sound_AvailableSpace(void); sqInt sound_InsertSamplesFromLeadTime(sqInt frameCount, void* srcBufPtr, sqInt samplesOfLeadTime); sqInt sound_PlaySamplesFromAtLength(sqInt frameCount, void* srcBufPtr, sqInt startIndex); sqInt sound_PlaySilence(void); sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex); sqInt sound_Stop(void); /* input */ sqInt sound_StartRecording(sqInt desiredSamplesPerSec, sqInt stereo, sqInt semaIndex); sqInt sound_StopRecording(void); double sound_GetRecordingSampleRate(void); sqInt sound_RecordSamplesIntoAtLength(void * buf, sqInt startSliceIndex, sqInt bufferSizeInBytes); /* mixer */ void sound_Volume(double *left, double *right); void sound_SetVolume(double left, double right); sqInt sound_SetRecordLevel(sqInt level); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SoundPlugin/sqUnixSoundDebug.h ================================================ #if 0 # define startSpy(); # define stopSpy(); #else #define RED 0xff0000 #define GREEN 0x00ff00 #define BLUE 0x0000ff #define WHITE 0xffffff #define BLACK 0x000000 #include void rect(int h, int c, float l, float r); void rect(int h, int c, float l, float r) { extern long *dpyPixels; extern int dpyPitch; int left= 250, width= 100, height= 2; long *base= dpyPixels; int pitch= dpyPitch / sizeof(long); int x, y; //printf("rect %d %d %g %g\n", h, c, l, r); assert(l >= 0.0); assert(r >= 0.0); assert(l <= 1.0); assert(r <= 1.0); base+= (int)left; base+= (int)(h * height * pitch); for (y= 0; y < height; ++y) { for (x= (int)(width * l); x < (int)(width * r); ++x) ((long *)base)[x]= c; base+= pitch; } } void fill(int h, int c, float l, float r); void fill(int h, int c, float l, float r) { if (r > 1.0) { rect(h, c, l, 1.0); rect(h, c, 0.0, r - 1.0); } else rect(h, c, l, r); } #if (USE_FIFO) void update(void) { if (output) { Buffer *b= output->buffer; static int phase= 0; float size= b->size; float out= b->optr / size; float avail= b->avail / size; extern long *dpyPixels; fill(0,BLACK, 0.0, out); fill(0,GREEN, out, out+avail); if (out + avail < 1.0) fill(0,BLACK, out+avail, 1.0); fill(2,GREEN, 0.0, avail); fill(2,BLACK, avail, 1.0); phase= 1 - phase; feedback(10, phase * WHITE); memcpy(dpyPixels + 400, output->buffer->data, 400); } } #else void update(void); void update(void) { } #endif static int running= 0; static pthread_t spyThread; static void *spy(void *ignored) { #pragma unused(ignored) struct sched_param params; int policy; if (pthread_getschedparam(pthread_self(), &policy, ¶ms)) perror("getschedparam"); params.sched_priority+= 9; if (pthread_setschedparam(pthread_self(), SCHED_RR, ¶ms)) perror("setschedparam"); for (;;) { update(); usleep(10000); } } void startSpy(void); void startSpy(void) { if (!pthread_create(&spyThread, 0, spy, 0)) running= 1; else perror("pthread_create(spy)"); } void stopSpy(void); void stopSpy(void) { if (running) { if (!pthread_cancel(spyThread)) running= 0; else perror("pthread_cancel(spy)"); running= 0; } } #endif // (DEBUG) ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SoundPlugin/sqUnixSoundMacOSXJMM.c ================================================ /* sqUnixSoundMacOSX.c -- sound support for CoreAudio on Mac OS 10 * * Author: Ian.Piumarta@squeakland.org * * Last edited: 2008-04-21 14:53:42 by piumarta on emilia * Altered by johnmci@smalltalkconsulting.com to remove static defs, fix bugs, powerpc/intel support. * * Copyright (C) 1996-2005 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Notes: // // The image always generates stereo samples. Since the only // supported hardware format is stereo, I cheerfully ignore the stereo // flag in snd_Start(). (Mixing everything down to mono only to have // the format converter break it back into stereo seems pointless.) /// /// Things you can tweak, should you really want to... /// // Do we obey the (huge) default "lead" time of 1024 frames (supplied // by the image) when mixing frames into the buffer, or do we reduce // the lead time to to an absolute (safe) minimum? // #define OBEY_LEAD_TIME 0 /// /// No more user-serviceable parts in this file. Stop Tweaking Now! /// #include #include #include #include #include #include #include #include #define SqueakFrameSize 4 // guaranteed (see class SoundPlayer) #define DeviceFrameSize 8 // ditto (, para 9) char empty[256] = { 0 }; #define DEBUG 0 #define TESTING 0 #if (!TESTING) # include "sq.h" #else inline sqInt signalSemaphoreWithIndex(sqInt sema) { return 0; } inline sqInt success(sqInt flag) { return 0; } inline sqInt primitiveFail(void) { return -1; } #endif #include "sqMacUnixInterfaceSound.h" char *dpyPixels = 0; sqInt dpyPitch = 0; sqInt noSoundMixer = 0; #if (DEBUG) void dumpFormat(AudioStreamBasicDescription *fmt); // atend void dprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } #else // !DEBUG void dumpFormat(AudioStreamBasicDescription *fmt); inline void dumpFormat(AudioStreamBasicDescription *fmt) { #pragma unused(fmt) } #define dprintf(ARGS, ...) // inline void dprintf(const char *fmt, ...) {} #endif // !DEBUG void eprintf(const char *fmt, ...); void eprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } sqInt min(sqInt i, sqInt j); sqInt max(sqInt i, sqInt j); inline sqInt min(sqInt i, sqInt j) { return (i < j) ? i : j; } inline sqInt max(sqInt i, sqInt j) { return (i > j) ? i : j; } // Apple error codes are really (rather contrived) 4-byte chars with // (almost) meaningful content. // char *str4(UInt32 chars); char *str4(UInt32 chars) { static char str[5]; *(sqInt *)&str= chars; str[4]= '\0'; return str; } sqInt checkError(OSStatus err, char *op, char *param); inline sqInt checkError(OSStatus err, char *op, char *param) { if (kAudioHardwareNoError != noErr) { eprintf("sound: %s(%s): error %ld (%s)\n", op, param, err, str4(err)); return 1; } return 0; } /// /// (ring) Buffer -- a FIFO of bytes /// typedef struct { char *data; sqInt size; // capacity sqInt avail; // available data (not available space) sqInt iptr; // next position to write sqInt optr; // next position to read } Buffer; // allocate a new, empty buffer // Buffer *Buffer_new(sqInt size); Buffer *Buffer_new(sqInt size) { Buffer *b= (Buffer *)malloc(sizeof(Buffer)); if (!b) return 0; if (!(b->data= (char *)malloc(size))) { free(b); return 0; } b->size= size; b->avail= 0; b->iptr= 0; b->optr= 0; return b; } // deallocate a buffer // void Buffer_delete(Buffer *b); void Buffer_delete(Buffer *b) { assert(b && b->data); free(b->data); b->data = NULL; free(b); } // answer how many bytes are available for reading // inline sqInt Buffer_avail(Buffer *b); inline sqInt Buffer_avail(Buffer *b) { return b->avail; } // answer how many bytes can be written // inline sqInt Buffer_free(Buffer *b); inline sqInt Buffer_free(Buffer *b) { return b->size - Buffer_avail(b); } // set outputs to address and size of zero (empty), one (contiguous) or two // (wrapped, fragmented) populated regions in the buffer // inline sqInt Buffer_getOutputPointers(Buffer *b, char **p1, sqInt *n1, char **p2, sqInt *n2); inline sqInt Buffer_getOutputPointers(Buffer *b, char **p1, sqInt *n1, char **p2, sqInt *n2) { sqInt optr= b->optr; sqInt avail= Buffer_avail(b); sqInt headroom= b->size - optr; if (avail == 0) { *p1= *p2= 0; *n1= *n2= 0; return 0; } else if (avail <= headroom) { *p1= b->data + optr; *p2= 0; *n1= avail; *n2= 0; return 1; } else { *p1= b->data + optr; *p2= b->data; *n1= headroom; *n2= avail - headroom; return 2; } } // set the output to the current read position and answer the amount of // data at that location // inline sqInt Buffer_getOutputPointer(Buffer *b, char **ptr); inline sqInt Buffer_getOutputPointer(Buffer *b, char **ptr) { sqInt optr= b->optr; sqInt avail= Buffer_avail(b); sqInt headroom= b->size - optr; if (headroom < avail) avail= headroom; assert((optr + avail) <= b->size); *ptr= b->data + optr; return avail; } // set the output to the current write location and answer the number of // bytes that can be written to that location // inline sqInt Buffer_getInputPointer(Buffer *b, char **ptr); inline sqInt Buffer_getInputPointer(Buffer *b, char **ptr) { sqInt iptr= b->iptr; sqInt nfree= Buffer_free(b); sqInt headroom= b->size - iptr; if (headroom < nfree) nfree= headroom; assert((iptr + nfree) <= b->size); *ptr= b->data + iptr; return nfree; } // increment the output pointer over a contiguous section of buffer // inline void Buffer_advanceOutputPointer(Buffer *b, sqInt size); inline void Buffer_advanceOutputPointer(Buffer *b, sqInt size) { sqInt optr= b->optr; sqInt avail= b->avail; optr+= size; avail-= size; assert(optr <= b->size); assert(avail >= 0); if (optr == b->size) optr= 0; b->optr= optr; b->avail= avail; } // advance the input pointer over a contiguous section of buffer // inline void Buffer_advanceInputPointer(Buffer *b, sqInt size); inline void Buffer_advanceInputPointer(Buffer *b, sqInt size) { sqInt iptr= b->iptr; sqInt nfree= Buffer_free(b); nfree -= size; assert(nfree >= 0); iptr += size; assert(iptr <= b->size); if (iptr == b->size) iptr= 0; b->iptr= iptr; b->avail += size; } // clear the given number of bytes at the input position and advance the // input pointer past them // inline void Buffer_prefill(Buffer *b, sqInt bytes); inline void Buffer_prefill(Buffer *b, sqInt bytes) { char *ptr; sqInt size= Buffer_getInputPointer(b, &ptr); assert(bytes <= size); memset(ptr, 0, size); Buffer_advanceInputPointer(b, bytes); } // write at most nbytes from buf into the buffer, wrapping in the middle if // necessary. answer the actual number of bytes written. // inline sqInt Buffer_write(Buffer *b, char *buf, sqInt nbytes); inline sqInt Buffer_write(Buffer *b, char *buf, sqInt nbytes) { sqInt iptr= b->iptr; sqInt bytesToCopy= min(nbytes, Buffer_free(b)); sqInt headroom= b->size - iptr; sqInt bytesCopied= 0; if (bytesToCopy >= headroom) { memcpy(b->data + iptr, buf, headroom); iptr= 0; bytesCopied += headroom; bytesToCopy -= headroom; } if (bytesToCopy) { memcpy(b->data + iptr, buf + bytesCopied, bytesToCopy); iptr += bytesToCopy; bytesCopied += bytesToCopy; } b->iptr= iptr; b->avail += bytesCopied; assert(b->avail <= b->size); return bytesCopied; } inline sqInt Buffer_writeRecheck(Buffer *b, char *buf, sqInt nbytes); inline sqInt Buffer_writeRecheck(Buffer *b, char *buf, sqInt nbytes) { sqInt iptr= b->iptr; sqInt bytesToCopy= min(nbytes, Buffer_free(b)); sqInt headroom= b->size - iptr; sqInt bytesCopied= 0; if (b->data == NULL || buf == NULL) return 0; if (bytesToCopy >= headroom) { memcpy(b->data + iptr, buf, headroom); iptr= 0; bytesCopied += headroom; bytesToCopy -= headroom; } if (bytesToCopy) { memcpy(b->data + iptr, buf + bytesCopied, bytesToCopy); iptr += bytesToCopy; bytesCopied += bytesToCopy; } b->iptr= iptr; b->avail += bytesCopied; assert(b->avail <= b->size); return bytesCopied; } // read at most nbytes from the buffer into buf, wrapping in the middle if // necessary. answer the actual number of bytes read. // inline sqInt Buffer_read(Buffer *b, char *buf, sqInt nbytes); inline sqInt Buffer_read(Buffer *b, char *buf, sqInt nbytes) { sqInt optr= b->optr; sqInt bytesToCopy= min(nbytes, Buffer_avail(b)); sqInt headroom= b->size - optr; sqInt bytesCopied= 0; if (bytesToCopy >= headroom) { memcpy(buf, b->data + optr, headroom); optr= 0; bytesToCopy -= headroom; bytesCopied += headroom; if (bytesToCopy) { memcpy(buf + bytesCopied, b->data, bytesToCopy); optr= bytesToCopy; bytesCopied += bytesToCopy; } } else { memcpy(buf, b->data + optr, bytesToCopy); optr += bytesToCopy; bytesCopied= bytesToCopy; } b->optr= optr; b->avail -= bytesCopied; return bytesCopied; } /// /// Stream -- abstraction over CoreAudio devices and streams /// typedef struct Stream { AudioDeviceID id; // associated with this stream sqInt direction; // 1nput/0utput sqInt sampleRate; // Squeak frames per second sqInt channels; // channels per Squeak frame sqInt devBufSize; // bytes per device buffer sqInt imgBufSize; // bytes per Squeak buffer sqInt cvtBufSize; // bytes per converter buffer Buffer *buffer; // fifo AudioConverterRef converter; // frame format converter sqInt semaphore; // ping me! u_int64_t timestamp; // nominal buffer tail time (uSecs) } Stream; Stream *output= 0; Stream *input= 0; // tell the SoundPlayer that output can be written. // void ioProcSignal(sqInt semaphore); void ioProcSignal(sqInt semaphore) { if (semaphore) signalSemaphoreWithIndex(semaphore); } OSStatus bufferDataProc(AudioConverterRef inAudioConverter, UInt32 *ioDataSize, void **outData, void *context); OSStatus bufferDataProc(AudioConverterRef inAudioConverter, UInt32 *ioDataSize, void **outData, void *context) { #pragma unused(inAudioConverter) Stream *s= (Stream *)context; Buffer *b= s->buffer; char *p1, *p2; sqInt n1, n2; Buffer_getOutputPointers(b, &p1, &n1, &p2, &n2); if (!n1) { *ioDataSize= min(256, *ioDataSize); *outData= (void *)empty; # if (DEBUG) putchar('-'); fflush(stdout); # endif } else { *ioDataSize= n1= min(n1, *ioDataSize); *outData= (void *)p1; Buffer_advanceOutputPointer(b, n1); # if (DEBUG) putchar('+'); fflush(stdout); # endif } return kAudioHardwareNoError; } OSStatus ioProcOutput(AudioDeviceID device, const AudioTimeStamp *currentTime, const AudioBufferList *inputData, const AudioTimeStamp *inputTime, AudioBufferList *outputData, // io param const AudioTimeStamp *outputTime, void *context); // shipout to device (usually 512 frames at 44k1 for builtin audio and // USB). this is asynchronous and runs (implicitly) in its own thread. // OSStatus ioProcOutput(AudioDeviceID device, const AudioTimeStamp *currentTime, const AudioBufferList *inputData, const AudioTimeStamp *inputTime, AudioBufferList *outputData, // io param const AudioTimeStamp *outputTime, void *context) { #pragma unused(device,currentTime,inputData,inputTime,outputTime) Stream *s= (Stream *)context; Buffer *b= s->buffer; if (Buffer_free(b) >= s->imgBufSize) ioProcSignal(s->semaphore); // restart SoundRecorder return AudioConverterFillBuffer(((Stream *)context)->converter, bufferDataProc, context, &outputData->mBuffers[0].mDataByteSize, outputData->mBuffers[0].mData); } // shipin from device (usually 512 frames at 44k1). this is asynchronous and // runs (implicitly) in its own thread. // OSStatus ioProcInput(AudioDeviceID device, const AudioTimeStamp *currentTime, const AudioBufferList *inputData, const AudioTimeStamp *inputTime, AudioBufferList *outputData, // io param const AudioTimeStamp *outputTime, void *context); OSStatus ioProcInput(AudioDeviceID device, const AudioTimeStamp *currentTime, const AudioBufferList *inputData, const AudioTimeStamp *inputTime, AudioBufferList *outputData, // io param const AudioTimeStamp *outputTime, void *context) { #pragma unused(device,currentTime,inputTime,outputData,outputTime) Stream *s= (Stream *)context; Buffer *b= s->buffer; sqInt n= Buffer_free(b); if ((UInt32) n >= inputData->mBuffers[0].mDataByteSize) Buffer_writeRecheck(b, inputData->mBuffers[0].mData, inputData->mBuffers[0].mDataByteSize); if (Buffer_avail(b) >= s->imgBufSize) ioProcSignal(s->semaphore); // restart SoundRecorder return kAudioHardwareNoError; } sqInt getDefaultDevice(AudioDeviceID *id, sqInt direction); sqInt getDefaultDevice(AudioDeviceID *id, sqInt direction) { UInt32 sz= sizeof(*id); return (!checkError(AudioHardwareGetProperty((direction ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice), &sz, (void *)id), "GetProperty", (direction ? "DefaultInput" : "DefaultOutput"))); } // allocate and a Stream and associate it with a suitable device. // Stream *Stream_new(sqInt dir); Stream *Stream_new(sqInt dir) { AudioDeviceID id= 0; Stream *s= 0; if (!getDefaultDevice(&id, dir)) return 0; // no device available if (!(s= (Stream *)calloc(1, sizeof(Stream)))) { eprintf("out of memory"); return 0; } s->id= id; s->direction= dir; dprintf("stream %p[%d] created for device %ld\n", s, dir, id); return s; } // deallocate a Stream. // void Stream_delete(Stream *s); void Stream_delete(Stream *s) { assert(s && s->buffer); Buffer_delete(s->buffer); dprintf("stream %p[%d] deleted\n", s, s->direction); free(s); } // setup conversion from Squeak to device frame format, or vice-versa. // requires: stereo for output, stereo or mono for input. // sqInt Stream_setFormat(Stream *s, sqInt frameCount, sqInt sampleRate, sqInt stereo); sqInt Stream_setFormat(Stream *s, sqInt frameCount, sqInt sampleRate, sqInt stereo) { sqInt nChannels= 1 + stereo; AudioStreamBasicDescription imgFmt, devFmt; UInt32 sz= sizeof(devFmt); if (0 == s->direction) nChannels= 2; // insist if (checkError(AudioDeviceGetProperty(s->id, 0, s->direction, kAudioDevicePropertyStreamFormat, &sz, &devFmt), "GetProperty", "StreamFormat")) return 0; dprintf("stream %p[%d] device format:\n", s, s->direction); dumpFormat(&devFmt); imgFmt.mSampleRate = sampleRate; imgFmt.mFormatID = kAudioFormatLinearPCM; imgFmt.mFormatFlags = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsSignedInteger; imgFmt.mBytesPerPacket = SqueakFrameSize / (3 - nChannels); imgFmt.mFramesPerPacket = 1; imgFmt.mBytesPerFrame = SqueakFrameSize / (3 - nChannels); imgFmt.mChannelsPerFrame = nChannels; imgFmt.mBitsPerChannel = 16; dprintf("stream %p[%d] image format:\n", s, s->direction); dumpFormat(&imgFmt); if (s->direction) // input { if (checkError(AudioConverterNew(&devFmt, &imgFmt, &s->converter), "AudioConverter", "New")) return 0; sz= sizeof(s->cvtBufSize); s->cvtBufSize= 512 * devFmt.mBytesPerFrame; if (checkError(AudioConverterGetProperty(s->converter, kAudioConverterPropertyCalculateOutputBufferSize, &sz, &s->cvtBufSize), "GetProperty", "OutputBufferSize")) return 0; } else // output { if (checkError(AudioConverterNew(&imgFmt, &devFmt, &s->converter), "AudioConverter", "New")) return 0; } s->channels= nChannels; s->sampleRate= sampleRate; s->imgBufSize= SqueakFrameSize * nChannels * frameCount; frameCount= max(frameCount, 512 * sampleRate / devFmt.mSampleRate); s->buffer= Buffer_new((s->direction ? DeviceFrameSize : SqueakFrameSize) * nChannels * frameCount * 2); dprintf("stream %p[%d] sound buffer size %d/%d (%d)\n", s, s->direction, s->imgBufSize, s->buffer->size, frameCount); return 1; } // start the device attached to the stream. // sqInt Stream_startSema(Stream *s, sqInt semaIndex); sqInt Stream_startSema(Stream *s, sqInt semaIndex) { AudioDeviceIOProc ioProc= s->direction ? ioProcInput : ioProcOutput; dprintf("stream %p[%d] startSema: %d\n", s, s->direction, semaIndex); s->semaphore= semaIndex; // can be zero if (checkError(AudioDeviceAddIOProc(s->id, ioProc, (void *)s), "Add", "ioProcOut")) return 0; if (checkError(AudioDeviceStart(s->id, ioProc), "DeviceStart", "ioProcOut")) { AudioDeviceRemoveIOProc(s->id, ioProc); return 0; } dprintf("stream %p[%d] running\n", s, s->direction); return 1; } // stop the device attached to a stream. // sqInt Stream_stop(Stream *s); sqInt Stream_stop(Stream *s) { AudioDeviceIOProc ioProc= s->direction ? ioProcInput : ioProcOutput; checkError(AudioDeviceStop(s->id, ioProc), "DeviceStop", s->direction ? "ioProcIn" : "ioProcOut"); checkError(AudioDeviceRemoveIOProc(s->id, ioProc), "Remove", s->direction ? "ioProcIn" : "ioProcOut"); dprintf("stream %p[%d] stopped\n", s, s->direction); return 1; } /// /// sound output primitives /// sqInt sound_AvailableSpace(void); sqInt sound_AvailableSpace(void) { if (output) return Buffer_free(output->buffer); success(false); return 8192; // so that older images can cope } // mix nFrames of samples into an output buffer. // void mixFrames(short *out, short *in, sqInt nFrames); void mixFrames(short *out, short *in, sqInt nFrames) { while (nFrames--) { sqInt sample; sample= (sqInt)*out + (sqInt)*in++; *out++= (short)max(-32768, min(32767, sample)); sample= (sqInt)*out + (sqInt)*in++; *out++= (short)max(-32768, min(32767, sample)); } } // insert up to frameCount (and no less than frameCount/2 -- see SoundPlayer // class>>startPlayingImmediately: for the [bogus] reasons why) frames into // the front and back buffers, leaving some number of framesOfLeadTime // intact before starging the insertion. (this last parameter is // meaningless for us and could be reduced to zero, but ignoring it causes // strange things to happen. time to rething the image code, methinks.) // // Note: this is only used when the "sound quick start" preference is // enabled in the image. // sqInt sound_InsertSamplesFromLeadTime(sqInt frameCount, void* srcBufPtr, sqInt framesOfLeadTime) { #pragma unused(framesOfLeadTime) Stream *s= output; dprintf("snd_InsertSamples %d From %p LeadTime %d\n", frameCount, srcBufPtr, framesOfLeadTime); if (s) { // data already sent to the device is lost forever, although latency // is only a few hundred frames (and is certainly much lower than the // standard value of `framesOfLeadTime'). instead of putzing around // why not just mix the samples in right away, leaving one h/w // buffer's worth of lead time in case we're interrupted in the // middle? char *frontData= 0, *backData= 0; sqInt frontFrames= 0, backFrames= 0; sqInt framesDone= 0; sqInt leadBytes; # if (OBEY_LEAD_TIME) { AudioTimeStamp timeStamp; u_int64_t then, now; timeStamp.mFlags= kAudioTimeStampHostTimeValid; checkError(AudioDeviceGetCurrentTime(s->id, &timeStamp), "AudioDeviceGetCurrentTime", ""); now= AudioConvertHostTimeToNanos(timeStamp.mHostTime) / 1000ull; then= s->timestamp; leadBytes= ( ((now - then) * (u_int64_t)s->sampleRate) / 1000000ull + framesOfLeadTime ) * SqueakFrameSize; } # else { leadBytes= s->devBufSize; // quantum shipped to the hardware } # endif { sqInt availBytes; sqInt byteCount= frameCount * SqueakFrameSize; Buffer_getOutputPointers(s->buffer, &frontData, &frontFrames, // bytes! &backData, &backFrames); // bytes! availBytes= frontFrames + backFrames; // don't consume more than frameCount - 1 frames leadBytes= max(leadBytes, availBytes - byteCount + SqueakFrameSize); assert((availBytes - leadBytes) < (byteCount)); if (leadBytes < frontFrames) // skip leadBytes into first fragment { frontData += leadBytes; frontFrames -= leadBytes; } else // omit the first fragment { leadBytes -= frontFrames; // lead in second fragment frontFrames= 0; backData += leadBytes; // skip leadBytes into second fragment backFrames -= leadBytes; } frontFrames /= SqueakFrameSize; backFrames /= SqueakFrameSize; } assert((frontFrames + backFrames) < frameCount); // avoid bug in image if ((frontFrames + backFrames) >= (frameCount / 2)) { mixFrames((short *)frontData, (short *)srcBufPtr, frontFrames); srcBufPtr += frontFrames * SqueakFrameSize; mixFrames((short *)backData, (short *)srcBufPtr, backFrames); framesDone= frontFrames + backFrames; } return framesDone; } success(false); return frameCount; } // play (exactly) frameCount of samples (and no less, since the result is // ignored). // sqInt sound_PlaySamplesFromAtLength(sqInt frameCount, void* arrayIndex, sqInt startIndex) { if (output) { sqInt byteCount= frameCount * SqueakFrameSize; if (Buffer_free(output->buffer) >= byteCount) { Buffer_write(output->buffer, (char *)arrayIndex + (startIndex * SqueakFrameSize), byteCount); return frameCount; } return 0; } success(false); return 8192; } // play a buffer's worth of silence (as quietly as possible). // sqInt sound_PlaySilence(void); sqInt sound_PlaySilence(void) { success(false); return 8192; } // shut down sound output. // sqInt sound_Stop(void); sqInt sound_Stop(void) { dprintf("snd_Stop\n"); if (output) { Stream_stop(output); Stream_delete(output); output= 0; } return 1; } // start up sound output. // sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex); sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex) { Stream *s= 0; dprintf("snd_Start frames: %d samplesPerSec: %d stereo: %d semaIndex: %d\n", frameCount, samplesPerSec, stereo, semaIndex); if (output) // there might be a change of sample rate sound_Stop(); if ((s= Stream_new(0))) // 0utput { if (( Stream_setFormat(s, frameCount, samplesPerSec, stereo)) && Stream_startSema(s, semaIndex)) { output= s; return 1; } Stream_delete(s); } return primitiveFail(); } /// /// sound input /// // answer the input sample rate. (this is guaranteed to be the same // as the sample rate that was requested.) // double sound_GetRecordingSampleRate(void); double sound_GetRecordingSampleRate(void) { if (input) return (double)input->sampleRate; //xxx FIXME: this should be FP primitiveFail(); return 0.0L; } sqInt sound_StopRecording(void); sqInt sound_StopRecording(void) { dprintf("snd_StopRecording\n"); if (input) { Stream_stop(input); Stream_delete(input); input= 0; } return 1; } // start up sound input. // sqInt sound_StartRecording(sqInt samplesPerSec, sqInt stereo, sqInt semaIndex); sqInt sound_StartRecording(sqInt samplesPerSec, sqInt stereo, sqInt semaIndex) { Stream *s= 0; dprintf("snd_StartRecording rate: %d stereo: %d semaIndex: %d\n", samplesPerSec, stereo, semaIndex); if (input) // there might be a change of sample rate sound_StopRecording(); if ((s= Stream_new(1))) // 1nput { // approximate the frameCount that output uses for the same sample rate sqInt frameCount= 5288 * samplesPerSec / 44100; if (( Stream_setFormat(s, frameCount, samplesPerSec, stereo)) && Stream_startSema(s, semaIndex)) { input= s; return 1; } Stream_delete(s); } return primitiveFail(); } sqInt sound_RecordSamplesIntoAtLength(void * buf, sqInt startSliceIndex, sqInt bufferSizeInBytes) { if (input) { if (Buffer_avail(input->buffer) >= (512 * DeviceFrameSize)) { sqInt start= startSliceIndex * SqueakFrameSize / 2; sqInt count= min(input->cvtBufSize, bufferSizeInBytes); if (count <= 0) { success(false); return 0; } if (kAudioHardwareNoError == AudioConverterFillBuffer(input->converter, bufferDataProc, input, &count, (char *)buf + start)) return count / (SqueakFrameSize / 2) / input->channels; } return 0; } success(false); return 0; } /// /// mixer /// sqInt getVolume(sqInt dir, double *left, double *right); sqInt getVolume(sqInt dir, double *left, double *right) { UInt32 sz; AudioDeviceID id; Float32 chan1, chan2; if (!getDefaultDevice(&id, dir)) return 0; sz= sizeof(chan1); if (checkError(AudioDeviceGetProperty(id, 1, // left dir, kAudioDevicePropertyVolumeScalar, &sz, &chan1), "GetProperty", "VolumeScalar")) return 0; sz= sizeof(chan2); if (checkError(AudioDeviceGetProperty(id, 2, // right dir, kAudioDevicePropertyVolumeScalar, &sz, &chan2), "GetProperty", "VolumeScalar")) chan2= chan1; *left= chan1; *right= chan2; return 1; } sqInt setVolume(sqInt dir, double dleft, double dright); sqInt setVolume(sqInt dir, double dleft, double dright) { Float32 left= (Float32)dleft; Float32 right= (Float32)dright; UInt32 sz; AudioDeviceID id; if (!getDefaultDevice(&id, dir)) return 0; sz= sizeof(left); if (checkError(AudioDeviceSetProperty(id, 0, 1, // left dir, kAudioDevicePropertyVolumeScalar, sz, &left), "SetProperty", "VolumeScalar")) return 0; sz= sizeof(right); if (checkError(AudioDeviceSetProperty(id, 0, 2, // right dir, kAudioDevicePropertyVolumeScalar, sz, &right), "SetProperty", "VolumeScalar")) return 0; return 1; } // get output gain, 0.0 <= { left, right } <= 1.0 // void sound_Volume(double *left, double *right); void sound_Volume(double *left, double *right) { getVolume(0, left, right); } // set output gain, 0.0 <= { left, right } <= 1.0 // void sound_SetVolume(double left, double right); void sound_SetVolume(double left, double right) { extern sqInt noSoundMixer; //xxx FIXME: this should not be a global option if (noSoundMixer) return; setVolume(0, left, right); } // set recording gain, 0 <= level <= 1000 // sqInt sound_SetRecordLevel(sqInt level); sqInt sound_SetRecordLevel(sqInt level) { extern sqInt noSoundMixer; if (noSoundMixer) return 0; return setVolume(1, (double)level / 1000.0L, (double)level / 1000.0L); } /// /// debugging /// #if (DEBUG) void dumpFormat(AudioStreamBasicDescription *fmt) { UInt32 flags= fmt->mFormatFlags; printf(" sample rate %g\n", fmt->mSampleRate); printf(" format %s\n", str4(fmt->mFormatID)); printf(" flags %08lx", flags); if (flags & kAudioFormatFlagIsBigEndian) printf(" big-endian"); else printf(" little-endian"); if (flags & kAudioFormatFlagIsFloat) printf(" float"); else if (flags & kAudioFormatFlagIsSignedInteger) printf(" signed-sqInt"); else printf(" unsigned-sqInt"); if (flags & kAudioFormatFlagIsPacked) printf(" packed"); else if (flags & kAudioFormatFlagIsAlignedHigh) printf(" aligned-high"); else printf(" aligned-low"); if (flags & kAudioFormatFlagIsNonInterleaved) printf(" interleaved"); else printf(" non-interleaved"); printf("\n"); printf(" bytes per packet %ld\n", fmt->mBytesPerPacket); printf(" frames per packet %ld\n", fmt->mFramesPerPacket); printf(" channels per frame %ld\n", fmt->mChannelsPerFrame); printf(" bytes per frame %ld\n", fmt->mBytesPerFrame); printf(" bits per channel %ld\n", fmt->mBitsPerChannel); } #endif // (DEBUG) #if (!TESTING) # include "SqSound.h" static sqInt sound_SetSwitch(sqInt id, sqInt captureFlag, sqInt parameter) { return -1; } static sqInt sound_GetSwitch(sqInt id, sqInt captureFlag, sqInt channel) { return -1; } static sqInt sound_SetDevice(sqInt id, char *arg) { return -1; } SqSoundDefine(MacOSX); # include "SqModule.h" void sound_parseEnvironment(void); sqInt sound_parseArgument(sqInt argc, char **argv); void sound_printUsage(void); void sound_printUsageNotes(void); void *sound_makeInterface(void); void *np_sound_makeInterface(void); void sound_parseEnvironment(void) {} sqInt sound_parseArgument(sqInt argc, char **argv) { #pragma unused(argc,argv) return 0; } void sound_printUsage(void) {} void sound_printUsageNotes(void) {} void *sound_makeInterface(void) { return &sound_MacOSX_itf; } void *np_sound_makeInterface(void) { return &sound_MacOSX_itf; } SqModuleDefine(sound, MacOSX); #else // TESTING # include "math.h" # define RATE 48000.0 // samples per second # define FRAMES 5288 * RATE / 44100 // nominal buffer size requested by Squeak # define FREQ 440.0 // tuning fork required to verify this ;) short sound[(sqInt)(FRAMES * 2)]; void warble(sqInt n) { double phase = 0.0; double amp = 0.5; double pan = 0.5; double freq = FREQ * 2.0 * 3.14159265359 / RATE; short *out= sound; while (n--) { float wave= sin(phase) * amp; phase= phase + freq; *out++= 32767.0 * wave * (1.0-pan); // left channel *out++= 32767.0 * wave * pan; // right channel } } sqInt main() { sound_Start(FRAMES, RATE, 1, 3); for (;;) { sqInt n= min(sizeof(sound), sound_AvailableSpace()) / 4; if (n) { warble(n); sound_PlaySamplesFromAtLength(n, (sqInt)sound, 0); # if (DEBUG) putchar('.'); fflush(stdout); # endif } else usleep(1000); } (void)sound_InsertSamplesFromLeadTime; (void)sound_PlaySilence; (void)sound_GetRecordingSampleRate; (void)sound_StartRecording; (void)sound_RecordSamplesIntoAtLength; (void)sound_Volume; (void)sound_SetVolume; (void)sound_SetRecordLevel; return 0; } /* cc -g -Wall -DTESTING=1 -o sqUnixSoundMacOSX sqUnixSoundMacOSX.c -framework CoreAudio -framework AudioToolbox */ #endif // TESTING ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SparklePlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable SparklePlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.SparklePlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.0 CFBundleSignature FAST CFBundleVersion 1.0.0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SparklePlugin/interp.h ================================================ /* Automatically generated from Squeak on #(13 May 2005 4:12:19 pm) */ #define SQ_VI_BYTES_PER_WORD 4 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SparklePlugin/sqMacMainObjCSparkle.h ================================================ // // sqMacMainObjCSparkle.h // SqueakVMUNIXPATHSSparkle // // Created by John M McIntosh on 18/11/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. /* MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ void *setupSqueakSparkleUpdater (void); void setAutomaticallyChecksForUpdates(sqInt automaticallyChecksSqueak); sqInt automaticallyChecksForUpdates(void); void setUpdateCheckInterval(double intervalSqueak); double updateCheckInterval(void); void setSendsSystemProfile(sqInt sendsSystemProfileSqueak); sqInt sendsSystemProfile(void); void setAutomaticallyDownloadsUpdates(sqInt automaticallyDownloadsUpdatesSqueak); sqInt automaticallyDownloadsUpdates(void); void checkForUpdatesInBackground(void); sqInt lastUpdateCheckDate(void); void resetUpdateCycle(void); sqInt updateInProgress(void); void setFeedURL(char *feedURLSqueak, sqInt length); char * feedURL(void); void checkForUpdateInformation(void); void checkForUpdates(void); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SparklePlugin/sqMacMainObjCSparkle.m ================================================ // // sqMacMainObjCSparkle.m // SqueakVMUNIXPATHSSparkle // // Created by John M McIntosh on 18/11/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import #import "sq.h" #import "sqMacMainObjCSparkle.h" #import @interface soundAtom : NSObject { } @end @implementation soundAtom // Use this to override the default behavior for Sparkle prompting the user about automatic update checks. - (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle{ return NO; }; // Implement this if you want to do some special handling with the appcast once it finishes loading. - (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast{}; // Sent when a valid update is found by the update driver. - (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update{}; // Sent when a valid update is not found. - (void)updaterDidNotFindUpdate:(SUUpdater *)update{}; // Sent immediately before installing the specified update. - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update{}; // Return YES to delay the relaunch until you do some processing; invoke the given NSInvocation to continue. - (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation { return NO; }; // Called immediately before relaunching. - (void)updaterWillRelaunchApplication:(SUUpdater *)updater{}; // This method allows you to provide a custom version comparator. // If you don't implement this method or return nil, the standard version comparator will be used. - (id )versionComparatorForUpdater:(SUUpdater *)updater { return nil; }; @end; sqInt convertNSDateToSqueakTime(NSDate *givenDate); static SUUpdater * squeakSparkleUpdater= NULL; void *setupSqueakSparkleUpdater (void) { if (squeakSparkleUpdater) return squeakSparkleUpdater; /* NSBundle * bundleForUpdate; bundleForUpdate = [NSBundle mainBundle ]; squeakSparkleUpdater = [SUUpdater updaterForBundle: bundleForUpdate]; */ squeakSparkleUpdater = [SUUpdater sharedUpdater]; //[squeakSparkleUpdater setDelegate: [soundAtom new]]; return squeakSparkleUpdater; } void setAutomaticallyChecksForUpdates(sqInt automaticallyChecksSqueak){ BOOL automaticallyChecks = automaticallyChecksSqueak; [squeakSparkleUpdater setAutomaticallyChecksForUpdates: automaticallyChecks]; } sqInt automaticallyChecksForUpdates(void){ return [squeakSparkleUpdater automaticallyChecksForUpdates]; } void setUpdateCheckInterval(double intervalSqueak) { NSTimeInterval automaticallyChecks = intervalSqueak; [squeakSparkleUpdater setUpdateCheckInterval: automaticallyChecks]; } double updateCheckInterval(void) { return (double) [squeakSparkleUpdater updateCheckInterval]; } void checkForUpdates(void){ return [squeakSparkleUpdater checkForUpdates: nil]; } void setSendsSystemProfile(sqInt sendsSystemProfileSqueak){ BOOL sendsSystemProfile = sendsSystemProfileSqueak; [squeakSparkleUpdater setSendsSystemProfile: sendsSystemProfile]; } sqInt sendsSystemProfile(void){ return [squeakSparkleUpdater sendsSystemProfile]; } void setFeedURL(char *feedURLSqueak, sqInt length){ NSURL * feedURL; NSString * string; string = [[NSString alloc] initWithBytes: feedURLSqueak length: length encoding: NSUTF8StringEncoding]; feedURL = [[NSURL alloc] initWithString: string]; [squeakSparkleUpdater setFeedURL: feedURL]; [feedURL release]; [string release]; } char * feedURL(void){ NSURL * feedURL; NSString * string; feedURL = [squeakSparkleUpdater feedURL]; string = [feedURL absoluteString]; return (char *) [string cStringUsingEncoding: NSUTF8StringEncoding]; } void setAutomaticallyDownloadsUpdates(sqInt automaticallyDownloadsUpdatesSqueak){ BOOL automaticallyDownloadsUpdates = automaticallyDownloadsUpdatesSqueak; [squeakSparkleUpdater setAutomaticallyDownloadsUpdates: automaticallyDownloadsUpdates]; } sqInt automaticallyDownloadsUpdates(void){ return [squeakSparkleUpdater automaticallyDownloadsUpdates]; } void checkForUpdatesInBackground(void){ return [squeakSparkleUpdater checkForUpdatesInBackground]; } void checkForUpdateInformation(void){ return [squeakSparkleUpdater checkForUpdateInformation]; } sqInt lastUpdateCheckDate(void) { NSDate *aNSDate; aNSDate = [squeakSparkleUpdater lastUpdateCheckDate]; return convertNSDateToSqueakTime(aNSDate); } void resetUpdateCycle(void) { [squeakSparkleUpdater resetUpdateCycle]; } sqInt updateInProgress(void) { sqInt returnValue = [squeakSparkleUpdater updateInProgress]; return returnValue; } sqInt convertNSDateToSqueakTime(NSDate *givenDate) { //IM NSTimeInterval dateDifference; static NSDate *squeakEpoch=NULL; if (!givenDate) return 0; if (squeakEpoch == NULL) { NSDateComponents *comps = [NSDateComponents new]; NSCalendar *calenderEnglishUSA = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar]; //Use USA english calender versus user choosen china calender //NSTimeZone* zone =[NSTimeZone timeZoneForSecondsFromGMT: 0]; //[calenderEnglishUSA setTimeZone: zone]; THIS appears not to be needed? [comps setYear: 1901]; [comps setMonth: 1]; [comps setDay: 1]; [comps setHour: 0]; [comps setMinute: 0]; [comps setSecond: 0]; squeakEpoch = [calenderEnglishUSA dateFromComponents: comps]; [squeakEpoch retain]; [comps release]; [calenderEnglishUSA release]; } /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970 */ dateDifference = [givenDate timeIntervalSinceDate: squeakEpoch]; return (sqInt) (usqInt) dateDifference; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable SpellingPlugin CFBundleGetInfoString SpellingPlugin for Squeak CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.SpellingPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName SpellingPlugin for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.0.1b2 CFBundleSignature FAST CFBundleVersion 1.0.1b2 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/JMMMacSpelling.3.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 15 February 2006 at 3:41:19 pm'! "Change Set: JMMMacSpelling Date: 15 June 2005 Author: johnmci@smalltalkconsulting.com Mac Spelling, interface to os-x spelling interface, allows you to check a utf-16 string for errors, set ignored words, change dictionary used, etc"! Object subclass: #MacSpellingInterface instanceVariableNames: '' classVariableNames: 'Tag' poolDictionaries: '' category: 'Multilingual-Editor'! TestCase subclass: #MacSpellingInterfaceTest instanceVariableNames: 'spelling' classVariableNames: '' poolDictionaries: '' category: 'Network-RemoteDirectory'! !MacSpellingInterfaceTest commentStamp: 'JMM 6/15/2005 16:53' prior: 0! Mac spelling checking interface. Test cases uses SpelllingPlugin by John M McIntosh johnmci@smalltalkconsulting.com June 15th 2005 ! !MacSpellingInterface methodsFor: 'converter' stamp: 'JMM 6/15/2005 09:59'! byteStringToUTF16: bytes ^bytes asString convertFromWithConverter: (TextConverter newForEncoding: 'utf-16'). ! ! !MacSpellingInterface methodsFor: 'converter' stamp: 'JMM 6/15/2005 09:38'! unknownToUTF16: candidate ^candidate convertToWithConverter: (TextConverter newForEncoding: 'utf-16'). ! ! !MacSpellingInterface methodsFor: 'guesses' stamp: 'JMM 6/15/2005 09:44'! getGuesses: aString | size collection word utf16 toGuess | toGuess := self unknownToUTF16: aString. size := self primGetGuessesForWordListLength: toGuess withTag: Tag. collection := OrderedCollection new: size. 1 to: size do: [:i | word := self primGetGuessesForWordwithTag: Tag at: i. utf16 := self byteStringToUTF16: word. collection add: utf16]. ^collection! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:36'! getIgnoredWords | size collection word utf16 | size := self primGetIgnoredWordsListLengthWithTag: Tag. size isZero ifTrue: [^OrderedCollection new]. collection := OrderedCollection new: size. 1 to: size do: [:i | word := self primGetIgnoredWordWithTag: Tag at: i. utf16 := self byteStringToUTF16: word. collection add: utf16]. ^collection! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:40'! setIgnoredWords: anArray "AnArray is unicode 16bit values" | utf16 | self primSetIgnoredWordsListLength: anArray size withTag: Tag. 1 to: anArray size do: [:i | utf16 _ self unknownToUTF16: (anArray at: i). self primSetIgnoredWords: utf16 withTag: Tag at: i].! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:39'! setIgnoredWord: aString "unicode32 is unicode value" | utf16 | utf16 := self unknownToUTF16: aString. self primSetNewIgnoredWord: utf16 withTag: Tag ! ! !MacSpellingInterface methodsFor: 'initialize-release' stamp: 'JMM 6/14/2005 17:59'! initialize Tag := self primGetUniqueSpellingTag. ! ! !MacSpellingInterface methodsFor: 'language' stamp: 'JMM 6/14/2005 18:37'! getLanguageString "ByteString , ie english" ^self primGetLanguage! ! !MacSpellingInterface methodsFor: 'language' stamp: 'JMM 6/14/2005 18:21'! setLanguageString: aString "ByteString , ie english" self primSetLanguage: aString! ! !MacSpellingInterface methodsFor: 'spelling' stamp: 'JMM 6/15/2005 09:43'! checkSpellingOf: aString startingAt: anInteger | results utf16 | utf16 := self unknownToUTF16: aString. results := self primCheckSpelling: utf16 startingAt: anInteger. ^results! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:18'! primCheckSpelling: aString startingAt: anInteger ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:14'! primGetGuessesForWordListLength: data withTag: aTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:14'! primGetGuessesForWordwithTag: aTag at: index ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:10'! primGetIgnoredWordsListLengthWithTag: aTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:12'! primGetIgnoredWordWithTag: Tag at: i ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:07'! primGetLanguage ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 17:59'! primGetUniqueSpellingTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:07'! primSetIgnoredWordsListLength: anArray withTag: Tag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:04'! primSetIgnoredWords: string withTag: Tag at: i ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:08'! primSetLanguage: aString ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:15'! primSetNewIgnoredWord: aString withTag: Tag ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 15:44'! testAGuess | s chk | s := spelling getGuesses: 'ackbar2'. self should: [s isEmpty]. s := spelling getGuesses: 'recieve'. chk := s collect: [:e | e asString]. self should: [chk includes: 'receive']. self should: [chk size > 1]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 09:50'! testATag | s | s := spelling primGetUniqueSpellingTag. self should: [s isNumber]. self should: [s > 0]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 09:53'! testGetIgnoredWords | s | s := spelling getIgnoredWords. self should: [s isCollection]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 12:24'! testGetSetLanguageString | l remember | l := spelling getLanguageString. self should: [l size > 0]. remember _ l. spelling setLanguageString: l. l := spelling getLanguageString. self should: [l size > 0]. self should: [remember = l]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:56'! testSetIgnoredWord | w1 i2 i2strings w2 w3 | w1 := self waitASecondRollOver. spelling setIgnoredWord: w1. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. w2 := self waitASecondRollOver. spelling setIgnoredWord: w2. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. self should: [i2strings includes: w2]. spelling setIgnoredWords: (OrderedCollection new). w3 := self waitASecondRollOver. spelling setIgnoredWord: w3. i2 := spelling getIgnoredWords. self should: [i2 size = 1]. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w3]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:38'! testSetIgnoredWords | w1 i i2 i3 i3strings i1strings i2strings | i := spelling getIgnoredWords. i isEmpty ifTrue: [ spelling setIgnoredWords: (OrderedCollection with: 'ackbar'). i2 := spelling getIgnoredWords. self should: [i2 size = 1]. self should: [(i2 at: 1) asString = 'ackbar']. spelling setIgnoredWords: (OrderedCollection with: 'ackbar' with: 'ackbar2'). i3 := spelling getIgnoredWords. self should: [i3 size = 2]. i3strings := i3 collect: [:e | e asString]. self should: [i3strings includes: 'ackbar']. self should: [i3strings includes: 'ackbar2'] ]. i := spelling getIgnoredWords. w1 := self waitASecondRollOver. i1strings := i collect: [:e | e asString]. i1strings add: w1. spelling setIgnoredWords: i1strings. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:48'! testSpelling | s i | spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'receive' startingAt: 1. self should: [(s at: 2) = 0]. spelling setIgnoredWord: 'recieve'. s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 2) = 0]. spelling setIgnoredWords: (OrderedCollection new). s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 7]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:59'! testSpellingOffset | s i | spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. s := spelling checkSpellingOf: 'too recieve' startingAt: 1. self should: [(s at: 1) = 5]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'too more recieve' startingAt: 1. self should: [(s at: 1) = 10]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'toox more recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 4]. s := spelling checkSpellingOf: 'toox more recieve' startingAt: 6. self should: [(s at: 1) = 11]. self should: [(s at: 2) = 7]. ! ! !MacSpellingInterfaceTest methodsFor: 'utility' stamp: 'JMM 6/15/2005 14:16'! waitASecondRollOver | now duration | now := Time millisecondClockValue. [duration := (Time millisecondClockValue) - now. duration > 0] whileFalse: [(Delay forMilliseconds: 10) wait]. ^Time millisecondClockValue printString! ! !MacSpellingInterfaceTest methodsFor: 'initialize-release' stamp: 'JMM 6/15/2005 09:48'! setUp spelling _ MacSpellingInterface new.! ! !MacSpellingInterface reorganize! ('converter' byteStringToUTF16: unknownToUTF16:) ('guesses' getGuesses:) ('ignored words' getIgnoredWords setIgnoredWords: setIgnoredWord:) ('initialize-release' initialize) ('language' getLanguageString setLanguageString:) ('spelling' checkSpellingOf:startingAt:) ('system primitives' primCheckSpelling:startingAt: primGetGuessesForWordListLength:withTag: primGetGuessesForWordwithTag:at: primGetIgnoredWordsListLengthWithTag: primGetIgnoredWordWithTag:at: primGetLanguage primGetUniqueSpellingTag primSetIgnoredWordsListLength:withTag: primSetIgnoredWords:withTag:at: primSetLanguage: primSetNewIgnoredWord:withTag:) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/JMMMacSpelling.4.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 15 February 2006 at 3:41:19 pm'! "Change Set: JMMMacSpelling Date: 15 June 2005 Author: johnmci@smalltalkconsulting.com Mac Spelling, interface to os-x spelling interface, allows you to check a utf-16 string for errors, set ignored words, change dictionary used, etc"! Object subclass: #MacSpellingInterface instanceVariableNames: '' classVariableNames: 'Tag' poolDictionaries: '' category: 'Sophie-Spelling-Mac'! TestCase subclass: #MacSpellingInterfaceTest instanceVariableNames: 'spelling' classVariableNames: '' poolDictionaries: '' category: 'Sophie-Spelling-Mac'! !MacSpellingInterfaceTest commentStamp: 'JMM 6/15/2005 16:53' prior: 0! Mac spelling checking interface. Test cases uses SpelllingPlugin by John M McIntosh johnmci@smalltalkconsulting.com June 15th 2005 ! !MacSpellingInterface methodsFor: 'converter' stamp: 'JMM 6/15/2005 09:59'! byteStringToUTF16: bytes ^bytes asString convertFromWithConverter: (TextConverter newForEncoding: 'utf-16'). ! ! !MacSpellingInterface methodsFor: 'converter' stamp: 'JMM 6/15/2005 09:38'! unknownToUTF16: candidate ^candidate convertToWithConverter: (TextConverter newForEncoding: 'utf-16'). ! ! !MacSpellingInterface methodsFor: 'guesses' stamp: 'JMM 6/15/2005 09:44'! getGuesses: aString | size collection word utf16 toGuess | toGuess := self unknownToUTF16: aString. size := self primGetGuessesForWordListLength: toGuess withTag: Tag. collection := OrderedCollection new: size. 1 to: size do: [:i | word := self primGetGuessesForWordwithTag: Tag at: i. utf16 := self byteStringToUTF16: word. collection add: utf16]. ^collection! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:36'! getIgnoredWords | size collection word utf16 | size := self primGetIgnoredWordsListLengthWithTag: Tag. size isZero ifTrue: [^OrderedCollection new]. collection := OrderedCollection new: size. 1 to: size do: [:i | word := self primGetIgnoredWordWithTag: Tag at: i. utf16 := self byteStringToUTF16: word. collection add: utf16]. ^collection! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:40'! setIgnoredWords: anArray "AnArray is unicode 16bit values" | utf16 | self primSetIgnoredWordsListLength: anArray size withTag: Tag. 1 to: anArray size do: [:i | utf16 _ self unknownToUTF16: (anArray at: i). self primSetIgnoredWords: utf16 withTag: Tag at: i].! ! !MacSpellingInterface methodsFor: 'ignored words' stamp: 'JMM 6/15/2005 09:39'! setIgnoredWord: aString "unicode32 is unicode value" | utf16 | utf16 := self unknownToUTF16: aString. self primSetNewIgnoredWord: utf16 withTag: Tag ! ! !MacSpellingInterface methodsFor: 'initialize-release' stamp: 'JMM 6/14/2005 17:59'! initialize Tag := self primGetUniqueSpellingTag. ! ! !MacSpellingInterface methodsFor: 'language' stamp: 'JMM 6/14/2005 18:37'! getLanguageString "ByteString , ie english" ^self primGetLanguage! ! !MacSpellingInterface methodsFor: 'language' stamp: 'JMM 6/14/2005 18:21'! setLanguageString: aString "ByteString , ie english" self primSetLanguage: aString! ! !MacSpellingInterface methodsFor: 'spelling' stamp: 'JMM 6/15/2005 09:43'! checkSpellingOf: aString startingAt: anInteger | results utf16 | utf16 := self unknownToUTF16: aString. results := self primCheckSpelling: utf16 startingAt: anInteger. ^results! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:18'! primCheckSpelling: aString startingAt: anInteger ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:14'! primGetGuessesForWordListLength: data withTag: aTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:14'! primGetGuessesForWordwithTag: aTag at: index ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:10'! primGetIgnoredWordsListLengthWithTag: aTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:12'! primGetIgnoredWordWithTag: Tag at: i ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:07'! primGetLanguage ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 17:59'! primGetUniqueSpellingTag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:07'! primSetIgnoredWordsListLength: anArray withTag: Tag ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:04'! primSetIgnoredWords: string withTag: Tag at: i ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:08'! primSetLanguage: aString ! ! !MacSpellingInterface methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 18:15'! primSetNewIgnoredWord: aString withTag: Tag ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 15:44'! testAGuess | s chk | s := spelling getGuesses: 'ackbar2'. self should: [s isEmpty]. s := spelling getGuesses: 'recieve'. chk := s collect: [:e | e asString]. self should: [chk includes: 'receive']. self should: [chk size > 1]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 09:50'! testATag | s | s := spelling primGetUniqueSpellingTag. self should: [s isNumber]. self should: [s > 0]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 09:53'! testGetIgnoredWords | s | s := spelling getIgnoredWords. self should: [s isCollection]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 12:24'! testGetSetLanguageString | l remember | l := spelling getLanguageString. self should: [l size > 0]. remember _ l. spelling setLanguageString: l. l := spelling getLanguageString. self should: [l size > 0]. self should: [remember = l]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:56'! testSetIgnoredWord | w1 i2 i2strings w2 w3 | w1 := self waitASecondRollOver. spelling setIgnoredWord: w1. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. w2 := self waitASecondRollOver. spelling setIgnoredWord: w2. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. self should: [i2strings includes: w2]. spelling setIgnoredWords: (OrderedCollection new). w3 := self waitASecondRollOver. spelling setIgnoredWord: w3. i2 := spelling getIgnoredWords. self should: [i2 size = 1]. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w3]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:38'! testSetIgnoredWords | w1 i i2 i3 i3strings i1strings i2strings | i := spelling getIgnoredWords. i isEmpty ifTrue: [ spelling setIgnoredWords: (OrderedCollection with: 'ackbar'). i2 := spelling getIgnoredWords. self should: [i2 size = 1]. self should: [(i2 at: 1) asString = 'ackbar']. spelling setIgnoredWords: (OrderedCollection with: 'ackbar' with: 'ackbar2'). i3 := spelling getIgnoredWords. self should: [i3 size = 2]. i3strings := i3 collect: [:e | e asString]. self should: [i3strings includes: 'ackbar']. self should: [i3strings includes: 'ackbar2'] ]. i := spelling getIgnoredWords. w1 := self waitASecondRollOver. i1strings := i collect: [:e | e asString]. i1strings add: w1. spelling setIgnoredWords: i1strings. i2 := spelling getIgnoredWords. i2strings := i2 collect: [:e | e asString]. self should: [i2strings includes: w1]. spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:48'! testSpelling | s i | spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'receive' startingAt: 1. self should: [(s at: 2) = 0]. spelling setIgnoredWord: 'recieve'. s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 2) = 0]. spelling setIgnoredWords: (OrderedCollection new). s := spelling checkSpellingOf: 'recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 7]. ! ! !MacSpellingInterfaceTest methodsFor: 'running' stamp: 'JMM 6/15/2005 16:59'! testSpellingOffset | s i | spelling setIgnoredWords: (OrderedCollection new). i := spelling getIgnoredWords. self should: [i size = 0]. s := spelling checkSpellingOf: 'too recieve' startingAt: 1. self should: [(s at: 1) = 5]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'too more recieve' startingAt: 1. self should: [(s at: 1) = 10]. self should: [(s at: 2) = 7]. s := spelling checkSpellingOf: 'toox more recieve' startingAt: 1. self should: [(s at: 1) = 1]. self should: [(s at: 2) = 4]. s := spelling checkSpellingOf: 'toox more recieve' startingAt: 6. self should: [(s at: 1) = 11]. self should: [(s at: 2) = 7]. ! ! !MacSpellingInterfaceTest methodsFor: 'utility' stamp: 'JMM 6/15/2005 14:16'! waitASecondRollOver | now duration | now := Time millisecondClockValue. [duration := (Time millisecondClockValue) - now. duration > 0] whileFalse: [(Delay forMilliseconds: 10) wait]. ^Time millisecondClockValue printString! ! !MacSpellingInterfaceTest methodsFor: 'initialize-release' stamp: 'JMM 6/15/2005 09:48'! setUp spelling _ MacSpellingInterface new.! ! !MacSpellingInterface reorganize! ('converter' byteStringToUTF16: unknownToUTF16:) ('guesses' getGuesses:) ('ignored words' getIgnoredWords setIgnoredWords: setIgnoredWord:) ('initialize-release' initialize) ('language' getLanguageString setLanguageString:) ('spelling' checkSpellingOf:startingAt:) ('system primitives' primCheckSpelling:startingAt: primGetGuessesForWordListLength:withTag: primGetGuessesForWordwithTag:at: primGetIgnoredWordsListLengthWithTag: primGetIgnoredWordWithTag:at: primGetLanguage primGetUniqueSpellingTag primSetIgnoredWordsListLength:withTag: primSetIgnoredWords:withTag:at: primSetLanguage: primSetNewIgnoredWord:withTag:) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/JMMMacSpellingPlugin.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 15 June 2005 at 5:04:15 pm'! SmartSyntaxInterpreterPlugin subclass: #SpellingPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! !SpellingPlugin methodsFor: 'initialize' stamp: 'JMM 6/14/2005 10:16'! initialiseModule self export: true. ^self sqSpellingInitialize ! ! !SpellingPlugin methodsFor: 'initialize' stamp: 'JMM 6/14/2005 10:16'! moduleUnloaded: aModuleName "The module with the given name was just unloaded. Make sure we have no dangling references." self export: true. self var: #aModuleName type: 'char *'. (aModuleName strcmp: 'SpellingPlugin') = 0 ifTrue: [self sqSpellingShutdown]! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/15/2005 16:44'! primitiveCheckSpelling: data startingAt: anInteger "data is? Tag that identifies document/image" | resultPtr result arrayOop value length | self var: #result declareC: 'int result[2]'. self var: #resultPtr declareC: 'int * resultPtr=result'. self primitive: 'primitiveCheckSpelling' parameters:#(Oop SmallInteger). length := interpreterProxy stSizeOf: data. self sqSpellingCheckSpelling: (interpreterProxy firstIndexableField: data) startingAt: anInteger - 1 length: length/2 results: resultPtr. arrayOop := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2. 0 to: 1 do:[:i| interpreterProxy pushRemappableOop: arrayOop. value := interpreterProxy positive32BitIntegerFor: (result at: i). arrayOop := interpreterProxy popRemappableOop. interpreterProxy storePointer: i ofObject: arrayOop withValue: value]. ^arrayOop ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/15/2005 14:51'! primitiveGetGuessesForWordListLength: data withTag: aTag "data is? Tag that identifies document/image" | size length | self primitive: 'primitiveGetGuessesForWordListLength' parameters:#(Oop SmallInteger). length := interpreterProxy stSizeOf: data. size := self sqSpellingGuessForWordListLength: (interpreterProxy firstIndexableField: data) withTag: aTag length: length/2. ^size asSmallIntegerObj! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 22:07'! primitiveGetGuessesForWordwithTag: aTag at: index "data is? Tag that identifies document/image" | length oop | self primitive: 'primitiveGetGuessesForWordwithTag' parameters:#(SmallInteger SmallInteger). length := self sqSpellingGuessForWordwithTagLength: aTag at: index-1. oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: length*2. self sqSpellingGuessForWordwithTag: aTag at: index-1 into: (interpreterProxy firstIndexableField: oop). ^oop ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 16:14'! primitiveGetIgnoredWordsListLengthWithTag: aTag "Get ignored word list" | length | self primitive: 'primitiveGetIgnoredWordsListLengthWithTag' parameters:#(SmallInteger). length := self sqSpellingGetIgnoredWordsListLengthWithTag: aTag. ^length asSmallIntegerObj! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 22:06'! primitiveGetIgnoredWordWithTag: aTag at: anIndex "Get ignored word list" | length oop | self primitive: 'primitiveGetIgnoredWordWithTag' parameters:#(SmallInteger SmallInteger). length := self sqSpellingGetIgnoredWordLengthWithTag: aTag at: anIndex-1. oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: length*2. self sqSpellingGetIgnoredWordWithTag: aTag at: anIndex-1 into: (interpreterProxy firstIndexableField: oop). ^oop! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 17:49'! primitiveGetLanguage "Return Language" | length oop | self primitive: 'primitiveGetLanguage'. length := self sqSpellingGetLanguageLength. oop := interpreterProxy instantiateClass: interpreterProxy classString indexableSize: length. self sqSpellingGetLanguageInto: (interpreterProxy firstIndexableField: oop). ^oop ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 17:50'! primitiveGetUniqueSpellingTag "Return Tag that identifies document/image" | tag | self primitive: 'primitiveGetUniqueSpellingTag'. tag := self sqSpellingGetUniqueSpellingTag. ^tag asOop: SmallInteger ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 17:50'! primitiveSetIgnoredWordsListLength: length withTag: aTag "data is? Tag that identifies document/image" self primitive: 'primitiveSetIgnoredWordsListLength' parameters:#(SmallInteger SmallInteger). self sqSpellingSetIgnoredWordsListLength: length withTag: aTag! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 21:56'! primitiveSetIgnoredWords: data withTag: aTag at: anIndex "data is? Tag that identifies document/image" self primitive: 'primitiveSetIgnoredWords' parameters:#(Oop SmallInteger SmallInteger). self sqSpellingSetIgnoredWord: (interpreterProxy firstIndexableField: data) withTag: aTag at: anIndex - 1 length: (interpreterProxy stSizeOf: data)/2 ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 21:52'! primitiveSetLanguage: data "data is? " self primitive: 'primitiveSetLanguage' parameters:#(Oop). self sqSpellingSetLanguage: (interpreterProxy firstIndexableField: data) length: (interpreterProxy stSizeOf: data) ! ! !SpellingPlugin methodsFor: 'system primitives' stamp: 'JMM 6/14/2005 21:55'! primitiveSetNewIgnoredWord: data withTag: aTag "data is? Tag that identifies document/image" self primitive: 'primitiveSetNewIgnoredWord' parameters:#(Oop SmallInteger). self sqSpellingSetNewIgnoredWord: (interpreterProxy firstIndexableField: data) withTag: aTag length: (interpreterProxy stSizeOf: data)/2 ! ! !SpellingPlugin class methodsFor: 'translation' stamp: 'JMM 6/14/2005 10:17'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^true! ! !SpellingPlugin class methodsFor: 'translation' stamp: 'JMM 6/14/2005 10:17'! requiresPlatformFiles "this plugin requires platform specific files in order to work" ^true! ! !SpellingPlugin class reorganize! ('translation' hasHeaderFile requiresPlatformFiles) ! SpellingPlugin removeSelector: #primitiveGetGuessesForWordLength:withTag:! SpellingPlugin removeSelector: #primitiveGetIgnoredWordListLengthWithTag:! SpellingPlugin removeSelector: #primitiveGetIgnoredWordListWithTag:! SpellingPlugin removeSelector: #primitiveGetIgnoredWordsListWithTag:at:! SpellingPlugin removeSelector: #primitiveGuessesForWord:withTag:! SpellingPlugin removeSelector: #primitiveLanguage:! SpellingPlugin removeSelector: #primitiveSetIgnoredWordsLength:forTag:! SpellingPlugin removeSelector: #primitiveSetIgnoredWords:withTag:! SpellingPlugin removeSelector: #primitiveSetIgnoredWord:withTag:! SpellingPlugin removeSelector: #primitiveSetIgnoredWord:withTag:at:! !SpellingPlugin reorganize! ('initialize' initialiseModule moduleUnloaded:) ('system primitives' primitiveCheckSpelling:startingAt: primitiveGetGuessesForWordListLength:withTag: primitiveGetGuessesForWordwithTag:at: primitiveGetIgnoredWordsListLengthWithTag: primitiveGetIgnoredWordWithTag:at: primitiveGetLanguage primitiveGetUniqueSpellingTag primitiveSetIgnoredWordsListLength:withTag: primitiveSetIgnoredWords:withTag:at: primitiveSetLanguage: primitiveSetNewIgnoredWord:withTag:) ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/Info-SpellCheck__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable SpellCheck CFBundleIconFile CFBundleIdentifier CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 0.0.2d1 NSPrincipalClass ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.m ================================================ /* File: SpellCheck.m Contains: This project compiles as a Mach-O bundle from ProjectBuilder. SpellCheck.m contains wrappers to cocoa objective-c routines and exports the wrapper functions as C. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright 2002 Apple Computer, Inc., All Rights Reserved */ #include #include #define DebugSpellCheck 0 static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr); /* Needed to make sure the Cocoa framework has a chance to initialize things in a Carbon app. NSApplicationLoad() is an API introduced in 10.2 which is a startup function to call when running Cocoa code from a Carbon application. Because NSApplicationLoad() is not available pre 10.2, we load the function pointer through CFBundle. If we encounter an error during this process, (i.e. it's not there), we fall back to calling NSApplication *NSApp=[NSApplication sharedApplication]; The fallback method does have bugs with regard to window activation seen when hiding and showing the main application. */ typedef BOOL (*NSApplicationLoadFuncPtr)( void ); void InitializeCocoa() { CFBundleRef appKitBundleRef; NSApplicationLoadFuncPtr myNSApplicationLoad; OSStatus err; // Load the "AppKit.framework" bundl to locate NSApplicationLoad err = LoadFrameworkBundle( CFSTR("AppKit.framework"), &appKitBundleRef ); if (err != noErr) goto FallbackMethod; // Manually load the Mach-O function pointers for the routines we will be using. myNSApplicationLoad = (NSApplicationLoadFuncPtr) CFBundleGetFunctionPointerForName( appKitBundleRef, CFSTR("NSApplicationLoad") ); if ( myNSApplicationLoad == NULL ) goto FallbackMethod; (void) myNSApplicationLoad(); return; FallbackMethod: { NSApplication *NSApp=[NSApplication sharedApplication]; } } /* Returns a guaranteed unique tag to use as the spell document tag for a document. You should use this method to generate tags, if possible, to avoid collisions with other objects that can be spell checked. */ int UniqueSpellDocumentTag() { int tag; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; tag =[NSSpellChecker uniqueSpellDocumentTag]; [pool release]; return( tag ); } /* When a document closes, it should notify the NSSpellChecker via closeSpellDocumentWithTag: so that its ignored word list gets cleaned up. */ void CloseSpellDocumentWithTag( int tag ) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:tag]; [pool release]; } /* Initiates a spell-check of a string. Returns the range of the first misspelled word (and optionally the wordCount by reference). */ CFRange CheckSpellingOfString( CFStringRef stringToCheck, int startingOffset ) { NSRange range = {0,0}; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; range =[[NSSpellChecker sharedSpellChecker] checkSpellingOfString:(NSString *)stringToCheck startingAt:startingOffset]; #if( DebugSpellCheck ) NSLog( @"%u is the location", range.location ); NSLog( @"%u is the length", range.length ); #endif [pool release]; return( *(CFRange*)&range ); } /* Initiates a spell-check of a string. Returns the range of the first misspelled word (and optionally the wordCount by reference). */ CFRange CheckSpellingOfStringWithOptions( CFStringRef stringToCheck, // the string whose spelling we wish to check int startingOffset, // 0-based offset in stringToCheck at which checking starts CFStringRef language, // pass an empty string CFSTR("") to use the default language Boolean wrapFlag, // if true, checking will wrap round to the start of stringToCheck // if false, checdking will stop at the end of stringToCheck int tag, // tag indicating a list of words to be ignored // use UniqueSpellDocumentTag to get a new tag int wordCount ) { NSRange range = {0,0}; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; range =[[NSSpellChecker sharedSpellChecker] checkSpellingOfString:(NSString *)stringToCheck startingAt:startingOffset language:(NSString *)language wrap:(BOOL)wrapFlag inSpellDocumentWithTag:tag wordCount:&wordCount]; [pool release]; return( *(CFRange*)&range ); // If there are no misspellings then it will get a length of zero } /* Add inWord to the list of words to be ignored when using CheckSpellingOfString with tag This method should be called from the client's implementation of -ignoreSpelling: */ void IgnoreWord( CFStringRef wordToIgnore, int tag ) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [[NSSpellChecker sharedSpellChecker] ignoreWord:(NSString *)wordToIgnore inSpellDocumentWithTag:tag]; [pool release]; } /* Set the list of ignored words for tag, replacing any existing list */ void SetIgnoredWords( CFArrayRef inWords, int tag ) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [[NSSpellChecker sharedSpellChecker] setIgnoredWords:(NSArray*)inWords inSpellDocumentWithTag:tag]; [pool release]; } /* Get the list of ignored words for tag Caller must release the result with CFRelease */ CFArrayRef CopyIgnoredWordsInSpellDocumentWithTag( int tag ) { NSArray *array; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // to keep memory requirements down array = [[[NSSpellChecker sharedSpellChecker] ignoredWordsInSpellDocumentWithTag:tag] retain]; [pool release]; return( (CFArrayRef)array ); } /* Get a list of guesses for a misspelled words Caller must release the result with CFRelease */ CFArrayRef GuessesForWord( CFStringRef word ) { NSArray *array; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; array = [[[NSSpellChecker sharedSpellChecker] guessesForWord:(NSString *)word] retain]; [pool release]; return( (CFArrayRef)array ); } static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) { OSStatus err; FSRef frameworksFolderRef; CFURLRef baseURL; CFURLRef bundleURL; if ( bundlePtr == nil ) return( -1 ); *bundlePtr = nil; baseURL = nil; bundleURL = nil; err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef); if (err == noErr) { baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef); if (baseURL == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false); if (bundleURL == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL); if (*bundlePtr == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { if ( ! CFBundleLoadExecutable( *bundlePtr ) ) { err = coreFoundationUnknownErr; } } // Clean up. if (err != noErr && *bundlePtr != nil) { CFRelease(*bundlePtr); *bundlePtr = nil; } if (bundleURL != nil) { CFRelease(bundleURL); } if (baseURL != nil) { CFRelease(baseURL); } return err; } CFStringRef language() { CFStringRef lang; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; lang =(CFStringRef) [[NSSpellChecker sharedSpellChecker] language]; [pool release]; return( lang ); } CFStringRef setLanguage(CFStringRef lang) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [[NSSpellChecker sharedSpellChecker] setLanguage: (NSString *)lang]; [pool release]; return; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.pbproj/apple.pbxuser ================================================ // !$*UTF8*$! { 089C1669FE841209C02AAC07 = { activeBuildStyle = 014CEA420018CDE011CA2923; activeTarget = 089C1673FE841209C02AAC07; perUserDictionary = { PBXWorkspaceConfiguration = { ContentSize = "{970, 838}"; LeftSlideOut = { ActiveTab = 0; Frame = "{{0, 23}, {970, 815}}"; Split0 = { ActiveTab = 2; Frame = "{{224, 0}, {746, 815}}"; Split0 = { Frame = "{{0, 216}, {746, 599}}"; }; SplitCount = 1; Tab0 = { Debugger = { Frame = "{{0, 0}, {484, 208}}"; Split0 = { Frame = "{{0, 24}, {484, 184}}"; Split0 = { Frame = "{{0, 0}, {236, 184}}"; }; Split1 = { Frame = "{{245, 0}, {239, 184}}"; }; SplitCount = 2; }; SplitCount = 1; Tab0 = { Frame = "{{0, 0}, {100, 50}}"; }; Tab1 = { Frame = "{{0, 0}, {100, 50}}"; }; TabCount = 2; }; Frame = "{{0, 0}, {484, 208}}"; LauncherConfigVersion = 4; }; Tab1 = { Frame = "{{0, 0}, {484, 208}}"; LauncherConfigVersion = 3; Runner = { Frame = "{{0, 0}, {484, 208}}"; }; }; Tab2 = { BuildMessageFrame = "{{0, 0}, {748, 137}}"; BuildTranscriptFrame = "{{0, 146}, {748, 48}}"; Frame = "{{0, 0}, {746, 192}}"; }; Tab3 = { Frame = "{{0, 0}, {673, 295}}"; }; TabCount = 4; }; SplitCount = 1; Tab0 = { Frame = "{{0, 0}, {200, 815}}"; }; Tab1 = { ClassesFrame = "{{0, 0}, {202, 56}}"; Frame = "{{0, 0}, {200, 100}}"; MembersFrame = "{{0, 65}, {202, 35}}"; OptionsSetName = "Hierarchy, all classes"; }; Tab2 = { Frame = "{{0, 0}, {200, 100}}"; }; Tab3 = { Frame = "{{0, 0}, {200, 100}}"; Split0 = { Frame = "{{0, 0}, {200, 45}}"; }; Split1 = { Frame = "{{0, 54}, {200, 46}}"; }; SplitCount = 2; }; Tab4 = { Frame = "{{0, 0}, {250, 100}}"; }; TabCount = 5; }; WindowLocation = "{47, 86}"; }; }; wantsIndex = 1; wantsSCM = -1; }; 089C1673FE841209C02AAC07 = { activeExec = 0; }; F54FE585025A713E01CB15F0 = { uiCtxt = { sepNavWindowFrame = "{{136, 164}, {1054, 829}}"; }; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.pbproj/deric.pbxuser ================================================ // !$*UTF8*$! { 089C1669FE841209C02AAC07 = { activeBuildStyle = 014CEA420018CDE011CA2923; activeTarget = 089C1673FE841209C02AAC07; addToTargets = ( 089C1673FE841209C02AAC07, ); perUserDictionary = { PBXWorkspaceConfiguration = { ContentSize = "{877, 600}"; LeftSlideOut = { ActiveTab = 3; Frame = "{{0, 23}, {877, 577}}"; Split0 = { ActiveTab = 2; Frame = "{{224, 0}, {653, 577}}"; Split0 = { Frame = "{{0, 216}, {653, 361}}"; }; SplitCount = 1; Tab0 = { Debugger = { Frame = "{{0, 0}, {484, 208}}"; Split0 = { Frame = "{{0, 24}, {484, 184}}"; Split0 = { Frame = "{{0, 0}, {236, 184}}"; }; Split1 = { Frame = "{{245, 0}, {239, 184}}"; }; SplitCount = 2; }; SplitCount = 1; Tab0 = { Frame = "{{0, 0}, {100, 50}}"; }; Tab1 = { Frame = "{{0, 0}, {100, 50}}"; }; TabCount = 2; }; Frame = "{{0, 0}, {484, 208}}"; LauncherConfigVersion = 4; }; Tab1 = { Frame = "{{0, 0}, {484, 208}}"; LauncherConfigVersion = 3; Runner = { Frame = "{{0, 0}, {484, 208}}"; }; }; Tab2 = { BuildMessageFrame = "{{0, 0}, {655, 137}}"; BuildTranscriptFrame = "{{0, 146}, {655, 48}}"; Frame = "{{0, 0}, {653, 192}}"; }; Tab3 = { Frame = "{{0, 0}, {612, 295}}"; }; TabCount = 4; }; SplitCount = 1; Tab0 = { Frame = "{{0, 0}, {200, 577}}"; }; Tab1 = { ClassesFrame = "{{0, 0}, {202, 56}}"; Frame = "{{0, 0}, {200, 100}}"; MembersFrame = "{{0, 65}, {202, 35}}"; OptionsSetName = "Hierarchy, all classes"; }; Tab2 = { Frame = "{{0, 0}, {200, 100}}"; }; Tab3 = { Frame = "{{0, 0}, {200, 577}}"; Split0 = { Frame = "{{0, 0}, {200, 280}}"; }; Split1 = { Frame = "{{0, 289}, {200, 288}}"; }; SplitCount = 2; }; Tab4 = { Frame = "{{0, 0}, {250, 100}}"; }; TabCount = 5; }; WindowLocation = "{15, 65}"; }; }; wantsIndex = 1; wantsSCM = -1; }; 089C1673FE841209C02AAC07 = { activeExec = 0; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.pbproj/johnmci.mode1 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID 9465F90308611134006CDE9D XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 OpenEditors Content PBXProjectModuleGUID 9465F90408611134006CDE9D PBXProjectModuleLabel SpellCheck.m PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 9465F90508611134006CDE9D PBXProjectModuleLabel SpellCheck.m _historyCapacity 0 bookmark 9465F90608611134006CDE9D history 9465F7F10860E43B006CDE9D SplitCount 1 StatusBarVisibility Geometry Frame {{0, 20}, {962, 622}} PBXModuleWindowStatusBarHidden2 RubberWindowFrame 15 210 962 663 0 0 1440 878 Content PBXProjectModuleGUID 9465F90708611134006CDE9D PBXProjectModuleLabel NSSpellChecker.h PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 9465F90808611134006CDE9D PBXProjectModuleLabel NSSpellChecker.h _historyCapacity 0 bookmark 9465F90A08611134006CDE9D history 9465F90908611134006CDE9D SplitCount 1 StatusBarVisibility Geometry Frame {{0, 20}, {962, 622}} PBXModuleWindowStatusBarHidden2 RubberWindowFrame 38 189 962 663 0 0 1440 878 PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 089C166AFE841209C02AAC07 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 338}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 356}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 224 400 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 203pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel MyNewFile14.java PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel MyNewFile14.java SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {482, 0}} RubberWindowFrame 224 400 690 397 0 0 1440 878 Module PBXNavigatorGroup Proportion 0pt BecomeActive ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 5}, {482, 351}} RubberWindowFrame 224 400 690 397 0 0 1440 878 Module XCDetailModule Proportion 351pt Proportion 482pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 9465F90108611134006CDE9D 1CE0B1FE06471DED0097A5F4 9465F90208611134006CDE9D 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 140567609.54204601 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList 9465F90708611134006CDE9D 9465F90408611134006CDE9D /Users/johnmci/Documents/SqueakSpellingPlugin/SpellCheck/SpellCheck.pbproj WindowString 224 400 690 397 0 0 1440 878 WindowTools Identifier windowTool.build Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CD052900623707200166675 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {500, 215}} RubberWindowFrame 192 257 500 500 0 0 1280 1002 Module PBXNavigatorGroup Proportion 218pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build GeometryConfiguration Frame {{0, 222}, {500, 236}} RubberWindowFrame 192 257 500 500 0 0 1280 1002 Module PBXBuildResultsModule Proportion 236pt Proportion 458pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible 1 TableOfContents 1C78EAA5065D492600B07095 1C78EAA6065D492600B07095 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 192 257 500 500 0 0 1280 1002 Identifier windowTool.debugger Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {317, 164}} {{317, 0}, {377, 164}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {694, 164}} {{0, 164}, {694, 216}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {694, 380}} RubberWindowFrame 321 238 694 422 0 0 1440 878 Module PBXDebugSessionModule Proportion 100% Proportion 100% Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible 1 TableOfContents 1CD10A99069EF8BA00B06720 1C0AD2AB069F1E9B00FABCE6 1C162984064C10D400B95A72 1C0AD2AC069F1E9B00FABCE6 ToolbarConfiguration xcode.toolbar.config.debug WindowString 321 238 694 422 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible 0 Identifier windowTool.find Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CD0528D0623707200166675 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {781, 167}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXNavigatorGroup Proportion 781pt Proportion 50% BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{8, 0}, {773, 254}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXProjectFindModule Proportion 50% Proportion 428pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible 1 TableOfContents 1C530D57069F1CE1000CFCEE 1C530D58069F1CE1000CFCEE 1C530D59069F1CE1000CFCEE 1CDD528C0622207200134675 1C530D5A069F1CE1000CFCEE 1CE0B1FE06471DED0097A5F4 1CD0528E0623707200166675 WindowString 62 385 781 470 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible 0 Identifier MENUSEPARATOR Identifier windowTool.debuggerConsole Layout Dock BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {440, 358}} RubberWindowFrame 650 41 440 400 0 0 1280 1002 Module PBXDebugCLIModule Proportion 358pt Proportion 358pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible 1 TableOfContents 1C78EAAD065D492600B07095 1C78EAAE065D492600B07095 1C78EAAC065D492600B07095 WindowString 650 41 440 400 0 0 1280 1002 Identifier windowTool.run Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {493, 167}} {{0, 176}, {493, 267}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {405, 443}} {{414, 0}, {514, 443}} GeometryConfiguration Frame {{0, 0}, {460, 159}} RubberWindowFrame 316 696 459 200 0 0 1280 1002 Module PBXRunSessionModule Proportion 159pt Proportion 159pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible 1 TableOfContents 1C0AD2B3069F1EA900FABCE6 1C0AD2B4069F1EA900FABCE6 1CD0528B0623707200166675 1C0AD2B5069F1EA900FABCE6 ToolbarConfiguration xcode.toolbar.config.run WindowString 316 696 459 200 0 0 1280 1002 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible 0 Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints Layout Dock BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052930623707200166675 PBXProjectModuleLabel Breakpoints GeometryConfiguration BreakpointsTreeTableConfiguration enabledColumn 16 breakpointColumn 201.5830078125 Frame {{0, 0}, {240, 195}} RubberWindowFrame 342 421 240 216 0 0 1440 878 Module PBXDebugBreakpointsModule Proportion 195pt Proportion 195pt Name Breakpoints ServiceClasses PBXDebugBreakpointsModule StatusbarIsVisible 0 TableOfContents 1C0AD2AD069F1E9B00FABCE6 1C0AD2AE069F1E9B00FABCE6 1CD052930623707200166675 WindowString 342 421 240 216 0 0 1440 878 WindowToolGUID 1C0AD2AD069F1E9B00FABCE6 WindowToolIsVisible 0 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.pbproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 089C1669FE841209C02AAC07 = { activeBuildStyle = 014CEA430018CDE011CA2923; activeTarget = 089C1673FE841209C02AAC07; codeSenseManager = 944D643A085FBA3400600D6E; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 243, 20, 48.1626, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 140567609; PBXWorkspaceStateSaveDate = 140567609; }; perUserProjectItems = { 9465F7F10860E43B006CDE9D = 9465F7F10860E43B006CDE9D; 9465F90608611134006CDE9D = 9465F90608611134006CDE9D; 9465F90908611134006CDE9D = 9465F90908611134006CDE9D; 9465F90A08611134006CDE9D = 9465F90A08611134006CDE9D; }; sourceControlManager = 944D6439085FBA3400600D6E; userBuildSettings = { }; }; 089C1673FE841209C02AAC07 = { activeExec = 0; }; 944D6439085FBA3400600D6E = { fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; isa = PBXSourceControlManager; scmConfiguration = { }; scmType = ""; }; 944D643A085FBA3400600D6E = { indexTemplatePath = ""; isa = PBXCodeSenseManager; }; 9465F7F10860E43B006CDE9D = { fRef = F54FE585025A713E01CB15F0; isa = PBXBookmark; }; 9465F81A0860ECEE006CDE9D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSpellChecker.h; path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSpellChecker.h; refType = 0; sourceTree = ""; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {2744, 1456}}"; sepNavSelRange = "{2647, 21}"; sepNavVisRect = "{{0, 608}, {923, 590}}"; sepNavWindowFrame = "{{38, 133}, {962, 719}}"; }; }; 9465F90608611134006CDE9D = { fRef = F54FE585025A713E01CB15F0; isa = PBXTextBookmark; name = CheckSpellingOfStringWithOptions; rLen = 32; rLoc = 5826; rType = 0; vrLen = 1766; vrLoc = 5764; }; 9465F90908611134006CDE9D = { fRef = 9465F81A0860ECEE006CDE9D; isa = PBXTextBookmark; rLen = 1; rLoc = 64; rType = 1; }; 9465F90A08611134006CDE9D = { fRef = 9465F81A0860ECEE006CDE9D; isa = PBXTextBookmark; name = checkSpellingOfString; rLen = 21; rLoc = 2647; rType = 0; vrLen = 2163; vrLoc = 1686; }; F54FE585025A713E01CB15F0 = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1382, 4340}}"; sepNavSelRange = "{5826, 32}"; sepNavVisRect = "{{0, 2014}, {923, 590}}"; sepNavWindowFrame = "{{15, 154}, {962, 719}}"; }; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SpellCheck/SpellCheck.pbproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 39; objects = { 014CEA410018CDE011CA2923 = { explicitFileType = wrapper.cfbundle; isa = PBXFileReference; path = SpellCheck.bundle; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; 014CEA420018CDE011CA2923 = { buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = YES; }; isa = PBXBuildStyle; name = Development; }; 014CEA430018CDE011CA2923 = { buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; }; //010 //011 //012 //013 //014 //080 //081 //082 //083 //084 089C1669FE841209C02AAC07 = { buildSettings = { }; buildStyles = ( 014CEA420018CDE011CA2923, 014CEA430018CDE011CA2923, ); hasScannedForEncodings = 0; isa = PBXProject; mainGroup = 089C166AFE841209C02AAC07; projectDirPath = ""; targets = ( 089C1673FE841209C02AAC07, ); }; 089C166AFE841209C02AAC07 = { children = ( 08FB77AFFE84173DC02AAC07, 089C167CFE841241C02AAC07, 089C1671FE841209C02AAC07, 19C28FB8FE9D52D311CA2CBB, ); isa = PBXGroup; name = SpellCheck; refType = 4; sourceTree = ""; }; 089C1671FE841209C02AAC07 = { children = ( 1058C7ACFEA557BF11CA2CBB, 1058C7AEFEA557BF11CA2CBB, ); isa = PBXGroup; name = "Frameworks and Libraries"; refType = 4; sourceTree = ""; }; 089C1672FE841209C02AAC07 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; refType = 0; sourceTree = ""; }; 089C1673FE841209C02AAC07 = { buildPhases = ( 089C1674FE841209C02AAC07, 089C1675FE841209C02AAC07, 089C1676FE841209C02AAC07, 089C1677FE841209C02AAC07, 089C1679FE841209C02AAC07, ); buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; HEADER_SEARCH_PATHS = ""; INSTALL_PATH = "$(HOME)/Library/Bundles"; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = SpellCheck; SECTORDER_FLAGS = ""; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = bundle; }; dependencies = ( ); isa = PBXBundleTarget; name = SpellCheck; productInstallPath = "$(HOME)/Library/Bundles"; productName = SpellCheck; productReference = 014CEA410018CDE011CA2923; productSettingsXML = " CFBundleDevelopmentRegion English CFBundleExecutable SpellCheck CFBundleIconFile CFBundleIdentifier CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 0.0.1d1 NSPrincipalClass "; }; 089C1674FE841209C02AAC07 = { buildActionMask = 2147483647; files = ( ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 089C1675FE841209C02AAC07 = { buildActionMask = 2147483647; files = ( 089C1680FE841241C02AAC07, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 089C1676FE841209C02AAC07 = { buildActionMask = 2147483647; files = ( F54FE586025A713E01CB15F0, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 089C1677FE841209C02AAC07 = { buildActionMask = 2147483647; files = ( 1058C7AFFEA557BF11CA2CBB, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 089C1679FE841209C02AAC07 = { buildActionMask = 2147483647; files = ( ); isa = PBXRezBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 089C167CFE841241C02AAC07 = { children = ( 089C167DFE841241C02AAC07, ); isa = PBXGroup; name = Resources; refType = 4; sourceTree = ""; }; 089C167DFE841241C02AAC07 = { children = ( 089C167EFE841241C02AAC07, ); isa = PBXVariantGroup; name = InfoPlist.strings; refType = 4; sourceTree = ""; }; 089C167EFE841241C02AAC07 = { fileEncoding = 10; isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; refType = 4; sourceTree = ""; }; 089C167FFE841241C02AAC07 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; refType = 0; sourceTree = ""; }; 089C1680FE841241C02AAC07 = { fileRef = 089C167DFE841241C02AAC07; isa = PBXBuildFile; settings = { }; }; 08FB77AFFE84173DC02AAC07 = { children = ( F54FE585025A713E01CB15F0, ); isa = PBXGroup; name = Classes; refType = 4; sourceTree = ""; }; //080 //081 //082 //083 //084 //100 //101 //102 //103 //104 1058C7ACFEA557BF11CA2CBB = { children = ( 1058C7ADFEA557BF11CA2CBB, ); isa = PBXGroup; name = "Linked Frameworks"; refType = 4; sourceTree = ""; }; 1058C7ADFEA557BF11CA2CBB = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; refType = 0; sourceTree = ""; }; 1058C7AEFEA557BF11CA2CBB = { children = ( 089C1672FE841209C02AAC07, 089C167FFE841241C02AAC07, ); isa = PBXGroup; name = "Other Frameworks"; refType = 4; sourceTree = ""; }; 1058C7AFFEA557BF11CA2CBB = { fileRef = 1058C7ADFEA557BF11CA2CBB; isa = PBXBuildFile; settings = { }; }; //100 //101 //102 //103 //104 //190 //191 //192 //193 //194 19C28FB8FE9D52D311CA2CBB = { children = ( 014CEA410018CDE011CA2923, ); isa = PBXGroup; name = Products; refType = 4; sourceTree = ""; }; //190 //191 //192 //193 //194 //F50 //F51 //F52 //F53 //F54 F54FE585025A713E01CB15F0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SpellCheck.m; refType = 2; sourceTree = SOURCE_ROOT; }; F54FE586025A713E01CB15F0 = { fileRef = F54FE585025A713E01CB15F0; isa = PBXBuildFile; settings = { }; }; }; rootObject = 089C1669FE841209C02AAC07; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SqueakSpelling.pbproj/johnmci.mode1 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID 94AF35A4084782DD00FA5ACB XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 OpenEditors Content PBXProjectModuleGUID 944D682408609F6D00600D6E PBXProjectModuleLabel sqMacSpellingPlugin.c PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 944D682508609F6D00600D6E PBXProjectModuleLabel sqMacSpellingPlugin.c _historyCapacity 0 bookmark 9465F8FE08611131006CDE9D history 9465F81D0860EE66006CDE9D SplitCount 1 StatusBarVisibility Geometry Frame {{0, 20}, {962, 622}} PBXModuleWindowStatusBarHidden2 RubberWindowFrame 370 106 962 663 0 0 1440 878 PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout BecomeActive ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 289 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 66DF6BFE01D7DCEA00A80119 66B8BC570381F53800A8011A 66DF6BFF01D7DCEA00A80119 66DF6C3901D7DCEA00A80119 66DF6C4501D7DEEE00A80119 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 1CC0EA4004350EF90044410B PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {289, 693}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {306, 711}} GroupTreeTableConfiguration MainColumn 289 RubberWindowFrame 501 97 908 752 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 306pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel sqMacSpellingPlugin.c PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel sqMacSpellingPlugin.c _historyCapacity 0 bookmark 9465F8FD08611131006CDE9D history 949CD5C0085CC32700EB8605 944D6240085F473000600D6E 944D634C085F8DF400600D6E 944D6487085FBC6B00600D6E 944D64BC085FBD7D00600D6E 944D64BE085FBD7D00600D6E 944D66BE085FC3F300600D6E 9465F8D50860F206006CDE9D 9465F8D60860F206006CDE9D 9465F8D70860F206006CDE9D prevStack 949CD5C5085CC32700EB8605 949CD5C6085CC32700EB8605 944D621E085F45A500600D6E 944D6320085F8B7B00600D6E 944D6323085F8B7B00600D6E 944D6326085F8B7B00600D6E 944D6343085F8D4100600D6E 944D64C0085FBD7D00600D6E 9465F8D80860F206006CDE9D 9465F8D90860F206006CDE9D SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {597, 522}} RubberWindowFrame 501 97 908 752 0 0 1440 878 Module PBXNavigatorGroup Proportion 522pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 527}, {597, 184}} RubberWindowFrame 501 97 908 752 0 0 1440 878 Module XCDetailModule Proportion 184pt Proportion 597pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 9465F8030860E667006CDE9D 1CE0B1FE06471DED0097A5F4 9465F8040860E667006CDE9D 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 140579121.27439901 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList 9465F80F0860E667006CDE9D 9465F8100860E667006CDE9D 9465F80C0860E667006CDE9D 944D682408609F6D00600D6E 1C530D57069F1CE1000CFCEE 944D6333085F8B7B00600D6E 94ABA92F0858D3A300079BE1 1CD10A99069EF8BA00B06720 /Users/johnmci/Documents/SqueakSpellingPlugin/SqueakSpelling.pbproj WindowString 501 97 908 752 0 0 1440 878 WindowTools FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel sqMacSpellingPlugin.c StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {879, 594}} RubberWindowFrame 471 28 879 795 0 0 1440 878 Module PBXNavigatorGroup Proportion 594pt BecomeActive ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1012 GeometryConfiguration Frame {{0, 599}, {879, 155}} RubberWindowFrame 471 28 879 795 0 0 1440 878 Module PBXBuildResultsModule Proportion 155pt Proportion 754pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 944D6333085F8B7B00600D6E 9465F8DF0860F206006CDE9D 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 471 28 879 795 0 0 1440 878 WindowToolGUID 944D6333085F8B7B00600D6E WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {192, 191}} {{192, 0}, {1030, 191}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {1222, 191}} {{0, 191}, {1222, 523}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {1222, 714}} RubberWindowFrame 172 66 1222 755 0 0 1440 878 Module PBXDebugSessionModule Proportion 714pt Proportion 714pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 9465F8060860E667006CDE9D 1C162984064C10D400B95A72 9465F8070860E667006CDE9D 9465F8080860E667006CDE9D 9465F8090860E667006CDE9D 9465F80A0860E667006CDE9D 9465F80B0860E667006CDE9D 9465F80C0860E667006CDE9D ToolbarConfiguration xcode.toolbar.config.debug WindowString 172 66 1222 755 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel SpellingPlugin.h StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {791, 416}} RubberWindowFrame 591 13 791 674 0 0 1440 878 Module PBXNavigatorGroup Proportion 791pt Proportion 416pt BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 421}, {791, 212}} RubberWindowFrame 591 13 791 674 0 0 1440 878 Module PBXProjectFindModule Proportion 212pt Proportion 633pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE 9465F8E00860F206006CDE9D 9465F8E10860F206006CDE9D 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 591 13 791 674 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {856, 640}} RubberWindowFrame 558 67 856 681 0 0 1440 878 Module PBXDebugCLIModule Proportion 640pt Proportion 640pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 94ABA92F0858D3A300079BE1 9465F80D0860E667006CDE9D 1C78EAAC065D492600B07095 WindowString 558 67 856 681 0 0 1440 878 WindowToolGUID 94ABA92F0858D3A300079BE1 WindowToolIsVisible Identifier windowTool.run Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {493, 167}} {{0, 176}, {493, 267}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {405, 443}} {{414, 0}, {514, 443}} GeometryConfiguration Frame {{0, 0}, {460, 159}} RubberWindowFrame 316 696 459 200 0 0 1280 1002 Module PBXRunSessionModule Proportion 159pt Proportion 159pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible 1 TableOfContents 1C0AD2B3069F1EA900FABCE6 1C0AD2B4069F1EA900FABCE6 1CD0528B0623707200166675 1C0AD2B5069F1EA900FABCE6 ToolbarConfiguration xcode.toolbar.config.run WindowString 316 696 459 200 0 0 1280 1002 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible 0 Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.breakpoints IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD052930623707200166675 PBXProjectModuleLabel Breakpoints GeometryConfiguration BreakpointsTreeTableConfiguration enabledColumn 16 breakpointColumn 482 Frame {{0, 0}, {506, 360}} RubberWindowFrame 780 250 506 380 0 0 1440 878 Module PBXDebugBreakpointsModule Proportion 360pt Proportion 360pt Name Breakpoints ServiceClasses PBXDebugBreakpointsModule StatusbarIsVisible TableOfContents 1C0AD2AD069F1E9B00FABCE6 94F94C8F085D4373008ACC85 1CD052930623707200166675 WindowString 780 250 506 380 0 0 1440 878 WindowToolGUID 1C0AD2AD069F1E9B00FABCE6 WindowToolIsVisible Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 FirstTimeWindowDisplayed Identifier windowTool.classBrowser IsVertical Layout Dock BecomeActive ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {378, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 332}} MembersFrame {{0, 101}, {378, 231}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 101 PBXMemberBookColumnIdentifier 22 RubberWindowFrame 312 384 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible TableOfContents 1C0AD2AF069F1E9B00FABCE6 949CD652085CD34000EB8605 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 312 384 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SqueakSpelling.pbproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66B8BC5C0381F66500A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 6117}}"; sepNavSelRange = "{16850, 24}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2968}}"; sepNavSelRange = "{1486, 20}"; sepNavVisRect = "{{0, 9}, {673, 397}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66DF6BFD01D7DCEA00A80119 = { activeBuildStyle = 66DF6C4401D7DCEA00A80119; activeExecutable = 94ABA91E0858D35E00079BE1; activeTarget = 94AF34E00846F91100FA5ACB; addToTargets = ( 94AF34E00846F91100FA5ACB, ); breakpoints = ( 944D679B085FDFFE00600D6E, ); codeSenseManager = 9444E60E06E7B8740063F6CC; executables = ( 94ABA91E0858D35E00079BE1, ); expressions = ( buffer, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 200, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 348.5835, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 358, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 63, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 140566658; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = ""; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = ""; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 140566658; }; perUserProjectItems = { 944D621E085F45A500600D6E = 944D621E085F45A500600D6E; 944D6240085F473000600D6E = 944D6240085F473000600D6E; 944D6320085F8B7B00600D6E = 944D6320085F8B7B00600D6E; 944D6323085F8B7B00600D6E = 944D6323085F8B7B00600D6E; 944D6326085F8B7B00600D6E = 944D6326085F8B7B00600D6E; 944D6343085F8D4100600D6E = 944D6343085F8D4100600D6E; 944D634C085F8DF400600D6E = 944D634C085F8DF400600D6E; 944D6487085FBC6B00600D6E = 944D6487085FBC6B00600D6E; 944D64BC085FBD7D00600D6E = 944D64BC085FBD7D00600D6E; 944D64BE085FBD7D00600D6E = 944D64BE085FBD7D00600D6E; 944D64C0085FBD7D00600D6E = 944D64C0085FBD7D00600D6E; 944D66BE085FC3F300600D6E = 944D66BE085FC3F300600D6E; 9465F81D0860EE66006CDE9D = 9465F81D0860EE66006CDE9D; 9465F8D50860F206006CDE9D = 9465F8D50860F206006CDE9D; 9465F8D60860F206006CDE9D = 9465F8D60860F206006CDE9D; 9465F8D70860F206006CDE9D = 9465F8D70860F206006CDE9D; 9465F8D80860F206006CDE9D = 9465F8D80860F206006CDE9D; 9465F8D90860F206006CDE9D = 9465F8D90860F206006CDE9D; 9465F8FD08611131006CDE9D = 9465F8FD08611131006CDE9D; 9465F8FE08611131006CDE9D = 9465F8FE08611131006CDE9D; 949CD5C0085CC32700EB8605 = 949CD5C0085CC32700EB8605; 949CD5C5085CC32700EB8605 = 949CD5C5085CC32700EB8605; 949CD5C6085CC32700EB8605 = 949CD5C6085CC32700EB8605; }; sourceControlManager = 9444E60D06E7B8740063F6CC; userBuildSettings = { }; }; 9444E60D06E7B8740063F6CC = { fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; isa = PBXSourceControlManager; scmConfiguration = { }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC = { indexTemplatePath = ""; isa = PBXCodeSenseManager; }; 944D6214085F458100600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {659, 490}}"; sepNavSelRange = "{251, 0}"; sepNavVisRect = "{{0, 0}, {659, 490}}"; sepNavWindowFrame = "{{176, 7}, {962, 719}}"; }; }; 944D621E085F45A500600D6E = { fRef = 944D6214085F458100600D6E; isa = PBXTextBookmark; name = "English: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 251; vrLoc = 0; }; 944D6240085F473000600D6E = { fRef = 949CD57E085CBE5900EB8605; isa = PBXTextBookmark; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 944D62AC085F7DA800600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {974, 5614}}"; sepNavSelRange = "{1237, 22}"; sepNavVisRect = "{{0, 356}, {923, 590}}"; sepNavWindowFrame = "{{107, 70}, {962, 719}}"; }; }; 944D62B5085F7E2A00600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {750, 384}}"; sepNavSelRange = "{275, 27}"; sepNavVisRect = "{{0, 0}, {750, 384}}"; sepNavWindowFrame = "{{107, 70}, {962, 719}}"; }; }; 944D62E9085F825200600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {662, 490}}"; sepNavSelRange = "{284, 0}"; sepNavVisRect = "{{0, 0}, {659, 490}}"; }; }; 944D62EA085F825200600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1178, 3948}}"; sepNavSelRange = "{4482, 0}"; sepNavVisRect = "{{0, 943}, {923, 590}}"; sepNavWindowFrame = "{{370, 50}, {962, 719}}"; }; }; 944D6320085F8B7B00600D6E = { fRef = 944D62AC085F7DA800600D6E; isa = PBXTextBookmark; name = "SpellingPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 905; vrLoc = 0; }; 944D6323085F8B7B00600D6E = { fRef = 944D62B5085F7E2A00600D6E; isa = PBXTextBookmark; name = "SpellingPlugin.h: 9"; rLen = 0; rLoc = 1128; rType = 0; vrLen = 98; vrLoc = 0; }; 944D6326085F8B7B00600D6E = { fRef = 944D62E9085F825200600D6E; isa = PBXTextBookmark; name = "sqMacSpellingPlugin.h: 71"; rLen = 0; rLoc = 298; rType = 0; vrLen = 0; vrLoc = 871; }; 944D6343085F8D4100600D6E = { fRef = 944D62EA085F825200600D6E; isa = PBXTextBookmark; name = "sqMacSpellingPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 196; vrLoc = 0; }; 944D634C085F8DF400600D6E = { fRef = 944D62E9085F825200600D6E; isa = PBXTextBookmark; name = "sqMacSpellingPlugin.h: sqSpelllingCheckSpellingstartingAtresults"; rLen = 0; rLoc = 284; rType = 0; vrLen = 871; vrLoc = 0; }; 944D6487085FBC6B00600D6E = { fRef = 944D6214085F458100600D6E; isa = PBXTextBookmark; name = "English: 7"; rLen = 0; rLoc = 251; rType = 0; vrLen = 251; vrLoc = 0; }; 944D64BC085FBD7D00600D6E = { fRef = 944D64BD085FBD7D00600D6E; isa = PBXTextBookmark; name = "(null): 7"; rLen = 0; rLoc = 251; rType = 0; vrLen = 251; vrLoc = 0; }; 944D64BD085FBD7D00600D6E = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakSpellingPlugin/build/SpellingPlugin.bundle/Contents/Resources/InfoPlist.strings; refType = 0; sourceTree = ""; }; 944D64BE085FBD7D00600D6E = { fRef = 94AF34F10846F91100FA5ACB; isa = PBXTextBookmark; name = "Info.plist: 27"; rLen = 0; rLoc = 893; rType = 0; vrLen = 903; vrLoc = 0; }; 944D64C0085FBD7D00600D6E = { fRef = 94AF34F10846F91100FA5ACB; isa = PBXTextBookmark; name = "Info.plist: 27"; rLen = 0; rLoc = 893; rType = 0; vrLen = 903; vrLoc = 0; }; 944D66AD085FC39200600D6E = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {556, 490}}"; sepNavSelRange = "{8, 0}"; sepNavVisRect = "{{0, 0}, {556, 490}}"; }; }; 944D66BE085FC3F300600D6E = { fRef = 944D62AC085F7DA800600D6E; isa = PBXTextBookmark; name = SQUEAK_BUILTIN_PLUGIN; rLen = 0; rLoc = 45; rType = 0; vrLen = 777; vrLoc = 2154; }; 944D679B085FDFFE00600D6E = { fileReference = 944D62AC085F7DA800600D6E; isa = PBXFileBreakpoint; lineNumber = 1; state = 1; }; 9465F81D0860EE66006CDE9D = { fRef = 944D62EA085F825200600D6E; isa = PBXTextBookmark; rLen = 1; rLoc = 34; rType = 1; }; 9465F8D50860F206006CDE9D = { fRef = 944D66AD085FC39200600D6E; isa = PBXTextBookmark; name = "PkgInfo: 1"; rLen = 0; rLoc = 8; rType = 0; vrLen = 8; vrLoc = 0; }; 9465F8D60860F206006CDE9D = { fRef = 944D62B5085F7E2A00600D6E; isa = PBXTextBookmark; name = sqSpellingGetLanguageLength; rLen = 27; rLoc = 275; rType = 0; vrLen = 1128; vrLoc = 0; }; 9465F8D70860F206006CDE9D = { comments = "warning: implicit declaration of function `sqSpellingGetLanguageLength'"; fRef = 944D62EA085F825200600D6E; isa = PBXTextBookmark; rLen = 1; rLoc = 93; rType = 1; }; 9465F8D80860F206006CDE9D = { fRef = 944D66AD085FC39200600D6E; isa = PBXTextBookmark; name = "PkgInfo: 1"; rLen = 0; rLoc = 8; rType = 0; vrLen = 8; vrLoc = 0; }; 9465F8D90860F206006CDE9D = { fRef = 944D62B5085F7E2A00600D6E; isa = PBXTextBookmark; name = sqSpellingGetLanguageLength; rLen = 27; rLoc = 275; rType = 0; vrLen = 1128; vrLoc = 0; }; 9465F8FD08611131006CDE9D = { fRef = 944D62EA085F825200600D6E; isa = PBXTextBookmark; name = "sqMacSpellingPlugin.c: 97"; rLen = 0; rLoc = 4272; rType = 0; vrLen = 1020; vrLoc = 3942; }; 9465F8FE08611131006CDE9D = { fRef = 944D62EA085F825200600D6E; isa = PBXTextBookmark; name = "sqMacSpellingPlugin.c: 98"; rLen = 0; rLoc = 4482; rType = 0; vrLen = 1516; vrLoc = 3275; }; 949CD57E085CBE5900EB8605 = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakSerialPortExtendedUnixPlugin/resources/English.lproj/InfoPlist.strings; refType = 0; sourceTree = ""; }; 949CD5C0085CC32700EB8605 = { fRef = 66C6C8E501DB1EC300A80109; isa = PBXBookmark; }; 949CD5C5085CC32700EB8605 = { fRef = 949CD57E085CBE5900EB8605; isa = PBXTextBookmark; name = "InfoPlist.strings: 1"; rLen = 215; rLoc = 0; rType = 0; vrLen = 215; vrLoc = 0; }; 949CD5C6085CC32700EB8605 = { fRef = 66C6C8E501DB1EC300A80109; isa = PBXBookmark; }; 94ABA91E0858D35E00079BE1 = { activeArgIndex = 2147483647; activeArgIndices = ( ); argumentStrings = ( ); configStateDict = { }; cppStopOnCatchEnabled = 0; cppStopOnThrowEnabled = 0; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; isa = PBXExecutable; launchableReference = 94ABA91F0858D35E00079BE1; libgmallocEnabled = 0; name = Squeak; savedGlobals = { /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/ServicesPlugin.bundle/Contents/MacOS/ServicesPlugin = ( { dataValue = " PBXGDB_VarObjDataValue2=0xa24e0c0, rtnCnt=1, parent=0x0, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypes, value=[256]\n"; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypes; type = "char [256]"; value = "[256]"; varobj = var108; }, { dataValue = " PBXGDB_VarObjDataValue2=0x910d3e0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringInLength, value=0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringInLength; type = "long int"; value = 0; varobj = var135; }, { dataValue = " PBXGDB_VarObjDataValue2=0x911b040, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypes, value=[64] "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypes; type = "OSType [64]"; value = "[64]"; varobj = var136; }, { dataValue = " PBXGDB_VarObjDataValue2=0x911b4a0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=specificScrap, value=0x0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = specificScrap; type = ScrapRef; value = 0x0; varobj = var137; }, { dataValue = " PBXGDB_VarObjDataValue2=0x9101420, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringOut, value=0x0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringOut; type = "char *"; value = 0x0; varobj = var139; }, { dataValue = " PBXGDB_VarObjDataValue2=0x9101ac0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringIn, value=0x0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringIn; type = "char *"; value = 0x0; varobj = var140; }, { dataValue = " PBXGDB_VarObjDataValue2=0x9103a40, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=MyAppsDataTypesSize, value=4 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = MyAppsDataTypesSize; type = "long int"; value = 4; varobj = var146; }, { dataValue = " PBXGDB_VarObjDataValue2=0x9103e80, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=myTextStringOutLength, value=0 "; display = YES; filename = /Users/johnmci/Documents/SqueakServicesPlugin/sqMacServices.c; name = myTextStringOutLength; type = "long int"; value = 0; varobj = var147; }, ); /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/SpellingPlugin.bundle/Contents/MacOS/SpellingPlugin = ( { dataValue = " PBXGDB_VarObjDataValue2=0x93d2b90, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaIgnoreWord, value=0x532146c "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaIgnoreWord; type = IgnoreWordProc; value = "0x532146c "; varobj = var115; }, { dataValue = " PBXGDB_VarObjDataValue2=0x97553b0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaCloseSpellDocumentWithTag, value=0x53210fc "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaCloseSpellDocumentWithTag; type = CloseSpellDocumentWithTagProc; value = "0x53210fc "; varobj = var117; }, { dataValue = " PBXGDB_VarObjDataValue2=0x99a8c30, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaUniqueSpellDocumentTag, value=0x5321030 "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaUniqueSpellDocumentTag; type = UniqueSpellDocumentTagProc; value = "0x5321030 "; varobj = var118; }, { dataValue = " PBXGDB_VarObjDataValue2=0x99ab540, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaLanguage, value=0x5321a7c "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaLanguage; type = LanguageProc; value = "0x5321a7c "; varobj = var119; }, { dataValue = " PBXGDB_VarObjDataValue2=0x99ab5e0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaSetIgnoredWords, value=0x532155c "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaSetIgnoredWords; type = SetIgnoredWordsProc; value = "0x532155c "; varobj = var120; }, { dataValue = " PBXGDB_VarObjDataValue2=0x93d33e0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaSetLanguage, value=0x5321b68 "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaSetLanguage; type = SetLanguageProc; value = "0x5321b68 "; varobj = var122; }, { dataValue = " PBXGDB_VarObjDataValue2=0x93d2670, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaIgnoredWordsInSpellDocumentWithTag, value=0x532164c "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaIgnoredWordsInSpellDocumentWithTag; type = IgnoredWordsInSpellDocumentWithTagProc; value = "0x532164c "; varobj = var123; }, { dataValue = " PBXGDB_VarObjDataValue2=0x9712ef0, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaGuessesForWord, value=0x5321760 "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaGuessesForWord; type = GuessesForWordProc; value = "0x5321760 "; varobj = var125; }, { dataValue = " PBXGDB_VarObjDataValue2=0x972a590, rtnCnt=3, parent=0x649ad10, validityStatus=Valid, numChildren=0, childValidityStatus=Invalid, numViewController=0, name=CocoaCheckSpellingOfString, value=0x53211e0 "; display = YES; filename = /Users/johnmci/Documents/SqueakSpellingPlugin/sqMacSpellingPlugin.c; name = CocoaCheckSpellingOfString; type = CheckSpellingOfStringProc; value = "0x53211e0 "; varobj = var128; }, ); }; shlibInfoDictList_v2 = ( { level = 0; path = /usr/lib/system/libmathCommon.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libSystem.B.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libicucore.A.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libauto.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libobjc.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; whenToLoad = 0; }, { level = 0; path = /usr/lib/libz.1.2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Security.framework/Versions/A/Security; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/WebServicesCore.framework/Versions/A/WebServicesCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound; whenToLoad = 0; }, { level = 0; path = /usr/lib/libbsm.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcrypto.0.9.7.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD; whenToLoad = 0; }, { level = 0; path = /usr/lib/libcups.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/FindByContent.framework/Versions/A/FindByContent; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRaw.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libmx.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices; whenToLoad = 0; }, { level = 0; path = /usr/lib/libiconv.2.dylib; whenToLoad = 0; }, { level = 0; path = /usr/lib/libxml2.2.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HTMLRendering.framework/Versions/A/HTMLRendering; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/NavigationServices.framework/Versions/A/NavigationServices; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AGL.framework/Versions/A/AGL; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/QuickTime.framework/Versions/A/QuickTime; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/ZeroLink.framework/Versions/A/ZeroLink; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app/Contents/MacOS/Squeak; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacEncoding.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/interp.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIMenuBar.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMain.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGATS.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCSync.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIClipBoard.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixCommandLineInterface.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUIAppleEvents.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacFileLogic.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacImageIO.ob"; whenToLoad = 0; }, { level = 0; path = /System/Library/Components/DictionaryService.component/Contents/MacOS/DictionaryService; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacMemory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacTime.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/UUIDPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SurfacePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/StarSqueakPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundGenerationPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SoundCodecPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SocketPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SerialPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/SecurityPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MiscPrimitivePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Matrix2x3Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MIDIPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/MacMenubarPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/LargeIntegers.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Klatt.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JoystickTabletPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReaderPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Error.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/JPEGReadWriter2Plugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/InternetConfigPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/HostWindowPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/GeniePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FloatArrayPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/FFTPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DropPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ZipPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/DSAPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BitBltPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B2DPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/BMPReadWriterPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/Squeak3D.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/B3DAcceleratorPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/AsynchFilePlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/ADPCMCodecPlugin.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSerialPort.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/osExports.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqNamedPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqVirtualMachine.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/aio.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacExternalPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacHostWindow.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacSecurity.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqFilePluginBasicPrims.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDirectory.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacDragDrop.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqMacUnixInterfaceSound.ob"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSoundMacOSXJMM.ob"; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/LocalePlugin.bundle/Contents/MacOS/LocalePlugin; whenToLoad = 0; }, { level = 0; path = /Developer/Applications/Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin/Contents/Resources/PBGDBIntrospectionSupport.A.dylib; whenToLoad = 0; }, { level = 0; path = "/Library/Application Support/Apple/Developer Tools/CustomDataViews/CFDataFormatters.bundle/Contents/MacOS/CFDataFormatters"; whenToLoad = 0; }, { level = 0; path = "/Users/johnmci/Documents/Squeak3.8.0/build/SqueakVMForCarbon.build/Squeak VM Debug (Upgraded).build/Objects-normal/ppc/sqUnixSocket.ob"; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/ServicesPlugin.bundle/Contents/MacOS/ServicesPlugin; whenToLoad = 0; }, { level = 0; path = /usr/lib/libgcc_s.1.0.dylib; whenToLoad = 0; }, { level = 0; path = "/usr/lib/libstdc++.6.0.3.dylib"; whenToLoad = 0; }, { level = 0; path = "/Library/Application Support/Apple/Developer Tools/CustomDataViews/CarbonDataFormatters.bundle/Contents/MacOS/CarbonDataFormatters"; whenToLoad = 0; }, { level = 0; path = /usr/lib/dyld; whenToLoad = 0; }, { level = 0; path = /System/Library/PrivateFrameworks/URLMount.framework/Versions/A/URLMount; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/SpellingPlugin.bundle/Contents/MacOS/SpellingPlugin; whenToLoad = 0; }, { level = 0; path = /usr/lib/libsqlite3.0.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit; whenToLoad = 0; }, { level = 0; path = /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa; whenToLoad = 0; }, { level = 0; path = /Users/johnmci/Documents/Squeak3.8.0/build/Plugins/SpellingPlugin.bundle/Contents/Frameworks/SpellCheck.bundle/Contents/MacOS/SpellCheck; whenToLoad = 0; }, ); sourceDirectories = ( ); }; 94ABA91F0858D35E00079BE1 = { isa = PBXFileReference; lastKnownFileType = wrapper.application; name = Squeak.app; path = /Users/johnmci/Documents/Squeak3.8.0/build/Squeak.app; refType = 0; sourceTree = ""; }; 94AF34E00846F91100FA5ACB = { activeExec = 0; }; 94AF34F10846F91100FA5ACB = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {686, 490}}"; sepNavSelRange = "{893, 0}"; sepNavVisRect = "{{0, 0}, {659, 490}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; 94AF35000846F98600FA5ACB = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2590}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/SqueakSpelling.pbproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 39; objects = { 66B8BC570381F53800A8011A = { children = ( 94AF35040846F9AB00FA5ACB, 94AF35000846F98600FA5ACB, 66B8BC580381F61C00A8011A, 66B8BC5A0381F63A00A8011A, 944D66AD085FC39200600D6E, 66B8BC5C0381F66500A8011A, 66B8BC5E0381F69100A8011A, 94ABA8920858C40D00079BE1, ); isa = PBXGroup; name = platforms; path = ../Squeak3.8.0/platforms; refType = 2; sourceTree = SOURCE_ROOT; }; 66B8BC580381F61C00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = "Mac OS/vm/sqConfig.h"; refType = 4; sourceTree = ""; }; 66B8BC5A0381F63A00A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqPlatformSpecific.h"; refType = 0; sourceTree = ""; }; 66B8BC5C0381F66500A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sq.h; path = Cross/vm/sq.h; refType = 4; sourceTree = ""; }; 66B8BC5E0381F69100A8011A = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/Cross/vm/sqVirtualMachine.h; refType = 0; sourceTree = ""; }; 66C6C8E501DB1EC300A80109 = { isa = PBXFileReference; lastKnownFileType = image.icns; path = SqueakPlugin.icns; refType = 4; sourceTree = ""; }; 66DF6BFD01D7DCEA00A80119 = { buildSettings = { }; buildStyles = ( 66DF6C4301D7DCEA00A80119, 66DF6C4401D7DCEA00A80119, ); hasScannedForEncodings = 1; isa = PBXProject; mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119; projectDirPath = ""; targets = ( 94AF34E00846F91100FA5ACB, ); }; 66DF6BFE01D7DCEA00A80119 = { children = ( 944D67D1085FF2C300600D6E, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, 66DF6C3901D7DCEA00A80119, 66DF6C8201D7DF7E00A80119, 66DF6C4501D7DEEE00A80119, 94AF34F10846F91100FA5ACB, ); isa = PBXGroup; refType = 4; sourceTree = ""; }; 66DF6BFF01D7DCEA00A80119 = { children = ( 944D62E9085F825200600D6E, 944D62EA085F825200600D6E, 944D62B5085F7E2A00600D6E, 944D62AC085F7DA800600D6E, ); isa = PBXGroup; name = Sources; refType = 4; sourceTree = ""; }; 66DF6C3901D7DCEA00A80119 = { children = ( 944D6212085F458100600D6E, 66C6C8E501DB1EC300A80109, ); isa = PBXGroup; name = resources; refType = 4; sourceTree = ""; }; 66DF6C4301D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Development; }; 66DF6C4401D7DCEA00A80119 = { buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; OPTIMIZATION_CFLAGS = "-O3 -mcpu=750 -funroll-loops "; OTHER_CFLAGS = "-DTARGET_OS_MAC -DNOPTHREADS"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; }; 66DF6C4501D7DEEE00A80119 = { children = ( 943173AF085CD38900DDDC64, ); isa = PBXGroup; name = Products; refType = 4; sourceTree = ""; }; 66DF6C8201D7DF7E00A80119 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; refType = 0; sourceTree = ""; }; //660 //661 //662 //663 //664 //940 //941 //942 //943 //944 943173AF085CD38900DDDC64 = { explicitFileType = wrapper.cfbundle; includeInIndex = 0; isa = PBXFileReference; path = SpellingPlugin.bundle; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; 944D6212085F458100600D6E = { children = ( 944D6213085F458100600D6E, ); isa = PBXGroup; name = English.lproj; path = resources/English.lproj; refType = 4; sourceTree = ""; }; 944D6213085F458100600D6E = { children = ( 944D6214085F458100600D6E, ); isa = PBXVariantGroup; name = InfoPlist.strings; path = ""; refType = 4; sourceTree = ""; }; 944D6214085F458100600D6E = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = InfoPlist.strings; refType = 4; sourceTree = ""; }; 944D6215085F458100600D6E = { fileRef = 944D6213085F458100600D6E; isa = PBXBuildFile; settings = { }; }; 944D62AC085F7DA800600D6E = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SpellingPlugin.c; refType = 4; sourceTree = ""; }; 944D62AD085F7DA800600D6E = { fileRef = 944D62AC085F7DA800600D6E; isa = PBXBuildFile; settings = { }; }; 944D62B5085F7E2A00600D6E = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpellingPlugin.h; refType = 4; sourceTree = ""; }; 944D62B6085F7E2A00600D6E = { fileRef = 944D62B5085F7E2A00600D6E; isa = PBXBuildFile; settings = { }; }; 944D62E9085F825200600D6E = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sqMacSpellingPlugin.h; refType = 4; sourceTree = ""; }; 944D62EA085F825200600D6E = { fileEncoding = 4; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sqMacSpellingPlugin.c; refType = 4; sourceTree = ""; }; 944D62EB085F825200600D6E = { fileRef = 944D62E9085F825200600D6E; isa = PBXBuildFile; settings = { }; }; 944D62EC085F825200600D6E = { fileRef = 944D62EA085F825200600D6E; isa = PBXBuildFile; settings = { }; }; 944D668E085FC2E200600D6E = { buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( 944D67D3085FF2CF00600D6E, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 944D66AD085FC39200600D6E = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = text; name = PkgInfo; path = build/PkgInfo; refType = 2; sourceTree = SOURCE_ROOT; }; 944D66AE085FC39200600D6E = { fileRef = 944D66AD085FC39200600D6E; isa = PBXBuildFile; settings = { }; }; 944D66AF085FC39800600D6E = { fileRef = 944D66AD085FC39200600D6E; isa = PBXBuildFile; settings = { }; }; 944D66B4085FC3C000600D6E = { buildActionMask = 2147483647; dstPath = Contents; dstSubfolderSpec = 1; files = ( 944D66AF085FC39800600D6E, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 944D67D1085FF2C300600D6E = { isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = SpellCheck.bundle; path = SpellCheck/build/SpellCheck.bundle; refType = 4; sourceTree = ""; }; 944D67D3085FF2CF00600D6E = { fileRef = 944D67D1085FF2C300600D6E; isa = PBXBuildFile; settings = { }; }; 94ABA8920858C40D00079BE1 = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = Cross/vm/sqMemoryAccess.h; refType = 4; sourceTree = ""; }; 94ABA8930858C40D00079BE1 = { fileRef = 94ABA8920858C40D00079BE1; isa = PBXBuildFile; settings = { }; }; 94AF34E00846F91100FA5ACB = { buildPhases = ( 94AF34E10846F91100FA5ACB, 94AF34E70846F91100FA5ACB, 94AF34EA0846F91100FA5ACB, 94AF34EE0846F91100FA5ACB, 94AF34F00846F91100FA5ACB, 944D668E085FC2E200600D6E, 944D66B4085FC3C000600D6E, ); buildRules = ( 94AF34F70846F94F00FA5ACB, ); buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = SpellingPlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = bundle; }; dependencies = ( ); isa = PBXNativeTarget; name = "SqueakSpellingPlugin (Upgraded)"; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 943173AF085CD38900DDDC64; productType = "com.apple.product-type.bundle"; }; 94AF34E10846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E20846F91100FA5ACB, 94AF34E30846F91100FA5ACB, 94AF34E40846F91100FA5ACB, 94AF34E50846F91100FA5ACB, 94AF35010846F98600FA5ACB, 94AF35050846F9AB00FA5ACB, 94ABA8930858C40D00079BE1, 944D62B6085F7E2A00600D6E, 944D62EB085F825200600D6E, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E20846F91100FA5ACB = { fileRef = 66B8BC580381F61C00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E30846F91100FA5ACB = { fileRef = 66B8BC5A0381F63A00A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E40846F91100FA5ACB = { fileRef = 66B8BC5C0381F66500A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E50846F91100FA5ACB = { fileRef = 66B8BC5E0381F69100A8011A; isa = PBXBuildFile; settings = { }; }; 94AF34E70846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34E80846F91100FA5ACB, 944D6215085F458100600D6E, 944D66AE085FC39200600D6E, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34E80846F91100FA5ACB = { fileRef = 66C6C8E501DB1EC300A80109; isa = PBXBuildFile; settings = { }; }; 94AF34EA0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 944D62AD085F7DA800600D6E, 944D62EC085F825200600D6E, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EE0846F91100FA5ACB = { buildActionMask = 2147483647; files = ( 94AF34EF0846F91100FA5ACB, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34EF0846F91100FA5ACB = { fileRef = 66DF6C8201D7DF7E00A80119; isa = PBXBuildFile; settings = { }; }; 94AF34F00846F91100FA5ACB = { buildActionMask = 2147483647; files = ( ); isa = PBXRezBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; 94AF34F10846F91100FA5ACB = { isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; refType = 4; sourceTree = ""; }; 94AF34F70846F94F00FA5ACB = { compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; isa = PBXBuildRule; outputFiles = ( ); }; 94AF35000846F98600FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = "Mac OS/vm/config.h"; refType = 4; sourceTree = ""; }; 94AF35010846F98600FA5ACB = { fileRef = 94AF35000846F98600FA5ACB; isa = PBXBuildFile; settings = { }; }; 94AF35040846F9AB00FA5ACB = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../Squeak3.8.0/src/vm/interp.h; refType = 2; sourceTree = SOURCE_ROOT; }; 94AF35050846F9AB00FA5ACB = { fileRef = 94AF35040846F9AB00FA5ACB; isa = PBXBuildFile; settings = { }; }; }; rootObject = 66DF6BFD01D7DCEA00A80119; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/build/.gdb_history ================================================ ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/build/PkgInfo ================================================ BNDLFAST ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/resources/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ CFBundleName = "SpellingPlugin"; CFBundleShortVersionString = "SpellingPlugin version 1.0.0B1"; CFBundleGetInfoString = "SpellingPlugin version 1.0.0B1"; NSHumanReadableCopyright = "http://www.squeak.org"; ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/sqMacSpellingPlugin.c ================================================ /* * sqMacSpellingPlugin.c * SqueakSpelling * * Created by John M McIntosh on 14/06/05. * Copyright 2005 Corporate Smalltalk Consulting Ltd. All rights reserved. Licenced under the Squeak-L * */ #include "sqMacSpellingPlugin.h" /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #if __BIG_ENDIAN__ #define kCFStringEncodingUTF16Squeak kCFStringEncodingUnicode #else #define kCFStringEncodingUTF16Squeak kCFStringEncodingUTF16BE #endif extern struct VirtualMachine *interpreterProxy; CFBundleRef gSpellingBundle=0; // "SpellCheck.bundle" reference // Function pointer prototypes to the Mach-O Cocoa wrappers typedef CFRange (*CheckSpellingOfStringWithOptionsProc)( CFStringRef, int, CFStringRef,Boolean, int, int ); typedef CFRange (*CheckSpellingOfStringProc)( CFStringRef, int ); typedef void (*IgnoreWordProc)( CFStringRef, int ); typedef CFArrayRef (*GuessesForWordProc)( CFStringRef ); typedef void (*InitializeCocoaProc)(); typedef void (*CloseSpellDocumentWithTagProc)( int ); typedef int (*UniqueSpellDocumentTagProc)(); typedef CFStringRef (*LanguageProc)(); typedef Boolean (*SetLanguageProc)(CFStringRef); typedef CFArrayRef (*IgnoredWordsInSpellDocumentWithTagProc)( int ); typedef void (*SetIgnoredWordsProc)(CFArrayRef, int ); CheckSpellingOfStringProc CocoaCheckSpellingOfString; IgnoreWordProc CocoaIgnoreWord; GuessesForWordProc CocoaGuessesForWord; InitializeCocoaProc CocoaInitializeCocoa; CloseSpellDocumentWithTagProc CocoaCloseSpellDocumentWithTag; UniqueSpellDocumentTagProc CocoaUniqueSpellDocumentTag; LanguageProc CocoaLanguage; SetLanguageProc CocoaSetLanguage; IgnoredWordsInSpellDocumentWithTagProc CocoaIgnoredWordsInSpellDocumentWithTag; SetIgnoredWordsProc CocoaSetIgnoredWords; CheckSpellingOfStringWithOptionsProc CocoaCheckSpellingOfStringWithOptions; void LoadPrivateFrameworkBundle( CFStringRef framework, CFBundleRef *bundlePtr, CFStringRef pluginName ); int gDocumentTag=0; int sqSpellingInitialize(void) { if (gSpellingBundle != NULL) return 1; LoadPrivateFrameworkBundle( CFSTR("SpellCheck.bundle"), &gSpellingBundle,CFSTR("org.squeak.SpellingPlugin") ); if ( gSpellingBundle == NULL ) return 0; CocoaInitializeCocoa = (InitializeCocoaProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("InitializeCocoa") ); if ( CocoaInitializeCocoa != NULL ) CocoaInitializeCocoa(); CocoaCheckSpellingOfString = (CheckSpellingOfStringProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("CheckSpellingOfString") ); CocoaGuessesForWord = (GuessesForWordProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("GuessesForWord") ); CocoaIgnoreWord = (IgnoreWordProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("IgnoreWord") ); CocoaCloseSpellDocumentWithTag = (CloseSpellDocumentWithTagProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("CloseSpellDocumentWithTag") ); CocoaUniqueSpellDocumentTag = (UniqueSpellDocumentTagProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("UniqueSpellDocumentTag") ); CocoaLanguage = (LanguageProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("language") ); CocoaSetLanguage = (SetLanguageProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("setLanguage") ); CocoaIgnoredWordsInSpellDocumentWithTag = (IgnoredWordsInSpellDocumentWithTagProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("CopyIgnoredWordsInSpellDocumentWithTag") ); CocoaSetIgnoredWords = (SetIgnoredWordsProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("SetIgnoredWords") ); CocoaCheckSpellingOfStringWithOptions = (CheckSpellingOfStringWithOptionsProc) CFBundleGetFunctionPointerForName( gSpellingBundle, CFSTR("CheckSpellingOfStringWithOptions") ); gDocumentTag = CocoaUniqueSpellDocumentTag(); return 1; } void sqSpellingShutdown(void) { if (gDocumentTag == 0) return; if (gSpellingBundle == 0) return; CocoaCloseSpellDocumentWithTag(gDocumentTag); } CFStringRef gLanguage=NULL; void sqSpellingCheckSpellingstartingAtlengthresults(char * data,int startLocation,int length, int *results) { CFRange range; CFStringRef stringToSpellCheck; if (gLanguage == NULL) { int ignore; ignore = sqSpellingGetLanguageLength(); } stringToSpellCheck = CFStringCreateWithBytes(kCFAllocatorDefault, data, length*2, kCFStringEncodingUTF16Squeak, false); range = CocoaCheckSpellingOfStringWithOptions( stringToSpellCheck, startLocation, gLanguage, 0, gDocumentTag,0); results[0] = (range.location+1); results[1] = (range.length); CFRelease(stringToSpellCheck); } int sqSpellingGetLanguageLength(void) { gLanguage = CocoaLanguage(); return CFStringGetLength(gLanguage); } void sqSpellingGetLanguageInto(char* string) { CFRange range = { 0, CFStringGetLength(gLanguage)}; CFIndex usedBufLen,actual; actual = CFStringGetBytes(gLanguage, range, kCFStringEncodingMacRoman, 0, false, string,CFStringGetLength(gLanguage), &usedBufLen); } int sqSpellingGetUniqueSpellingTag(void) { return gDocumentTag; } void sqSpellingSetLanguagelength(char *string,int length) { CFStringRef lang; lang = CFStringCreateWithBytes(kCFAllocatorDefault, string, length, kCFStringEncodingMacRoman, false); CocoaSetLanguage(lang); CFRelease(lang); } CFArrayRef guessArray=NULL; int sqSpellingGuessForWordListLengthwithTaglength(char *data, int tag,int size) { CFIndex count; CFStringRef word; if ( guessArray != NULL ) { CFRelease( (void*)guessArray ); guessArray = NULL; } word = CFStringCreateWithBytes(kCFAllocatorDefault, data, size*2, kCFStringEncodingUTF16Squeak, false); guessArray = CocoaGuessesForWord( word ); count = CFArrayGetCount( guessArray ); if (count == 0) { CFRelease( (void*)guessArray ); guessArray = NULL; } CFRelease(word); return count; } int sqSpellingGuessForWordwithTagLengthat(int aTag, int indexs){ if ( guessArray == NULL ) return 0; CFStringRef guess = CFArrayGetValueAtIndex( guessArray, indexs ); return CFStringGetLength(guess); } void sqSpellingGuessForWordwithTagatinto(int aTag,int index, char *data) { if ( guessArray == NULL ) return; { CFStringRef guess = CFArrayGetValueAtIndex( guessArray, index ); CFRange range = { 0, CFStringGetLength(guess)}; CFIndex usedBufLen,actual; actual = CFStringGetBytes(guess, range, kCFStringEncodingUTF16Squeak, 0, false, data,CFStringGetLength(guess)*2, &usedBufLen); if (index+1 == CFArrayGetCount( guessArray )) { CFRelease(guessArray); guessArray = NULL; } } } CFArrayRef ignoredWordsArray=NULL; int sqSpellingGetIgnoredWordsListLengthWithTag(int aTag) { CFIndex count; if ( ignoredWordsArray != NULL ) { CFRelease( (void*)ignoredWordsArray ); ignoredWordsArray = NULL; } ignoredWordsArray = CocoaIgnoredWordsInSpellDocumentWithTag(aTag); if (ignoredWordsArray == NULL) return 0; count = CFArrayGetCount( ignoredWordsArray ); return count; } int sqSpellingGetIgnoredWordLengthWithTagat(int aTag, int anIndex){ if ( ignoredWordsArray == NULL ) return 0; CFStringRef guess = CFArrayGetValueAtIndex( ignoredWordsArray, anIndex ); return CFStringGetLength(guess); } void sqSpellingGetIgnoredWordWithTagatinto(int aTag, int anIndex, char *data) { if ( ignoredWordsArray == NULL ) return; { CFStringRef ignoreWord = CFArrayGetValueAtIndex( ignoredWordsArray, anIndex ); CFRange range = { 0, CFStringGetLength(ignoreWord)}; CFIndex usedBufLen,actual; actual = CFStringGetBytes(ignoreWord, range, kCFStringEncodingUTF16Squeak, 0, false, data,CFStringGetLength(ignoreWord)*2, &usedBufLen); } } CFMutableArrayRef newIgnoredWordsArray=NULL; CFIndex newIgnoredWordsArrayLength=0; void sqSpellingSetIgnoredWordsListLengthwithTag(int length, int aTag) { if ( newIgnoredWordsArray != NULL ) { CFRelease( (void*)newIgnoredWordsArray ); newIgnoredWordsArray = NULL; } newIgnoredWordsArrayLength = length; newIgnoredWordsArray = CFArrayCreateMutable(kCFAllocatorDefault, newIgnoredWordsArrayLength, NULL); if (newIgnoredWordsArrayLength == 0) { CocoaSetIgnoredWords(newIgnoredWordsArray,aTag); CFRelease(newIgnoredWordsArray); newIgnoredWordsArray = NULL; } } void sqSpellingSetIgnoredWordwithTagatlength(char *data,int aTag, int anIndex, int length) { CFStringRef word; if (newIgnoredWordsArray == NULL) return; word = CFStringCreateWithBytes(kCFAllocatorDefault, data, length*2, kCFStringEncodingUTF16Squeak, false); CFArraySetValueAtIndex (newIgnoredWordsArray,anIndex,word); if ((anIndex+1) == newIgnoredWordsArrayLength) { CocoaSetIgnoredWords(newIgnoredWordsArray,aTag); CFRelease(newIgnoredWordsArray); newIgnoredWordsArray = NULL; } } void sqSpellingSetNewIgnoredWordwithTaglength(char *data,int aTag, int length) { CFStringRef word; word = CFStringCreateWithBytes(kCFAllocatorDefault, data, length*2, kCFStringEncodingUTF16Squeak, false); CocoaIgnoreWord(word,aTag); CFRelease(word); } // Utility routine to load a bundle from the applications Frameworks folder. // i.e. : "SpellingChecker.app/Contents/Frameworks/SpellCheck.bundle" void LoadPrivateFrameworkBundle( CFStringRef framework, CFBundleRef *bundlePtr, CFStringRef pluginIdentifier) { CFURLRef baseURL = NULL; CFURLRef bundleURL = NULL; CFBundleRef myAppsBundle = NULL; if ( bundlePtr == NULL ) goto Bail; *bundlePtr = NULL; myAppsBundle = CFBundleGetBundleWithIdentifier(pluginIdentifier); // Get our application's main bundle from Core Foundation if ( myAppsBundle == NULL ) goto Bail; baseURL = CFBundleCopyPrivateFrameworksURL( myAppsBundle ); if ( baseURL == NULL ) goto Bail; bundleURL = CFURLCreateCopyAppendingPathComponent( kCFAllocatorSystemDefault, baseURL, framework, false ); if ( bundleURL == NULL ) goto Bail; *bundlePtr = CFBundleCreate( kCFAllocatorSystemDefault, bundleURL ); if ( *bundlePtr == NULL ) goto Bail; if ( ! CFBundleLoadExecutable( *bundlePtr ) ) { CFRelease( *bundlePtr ); *bundlePtr = NULL; } Bail: // Clean up. if ( bundleURL != NULL ) CFRelease( bundleURL ); if ( baseURL != NULL ) CFRelease( baseURL ); } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SpellingPlugin/sqMacSpellingPlugin.h ================================================ /* * sqMacSpellingPlugin.h * SqueakSpelling * * Created by John M McIntosh on 14/06/05. * */ #include int sqSpellingInitialize(void); void sqSpellingShutdown(void); void sqSpelllingCheckSpellingstartingAtresults(char * data,long startLocation,int length, int *results); int sqSpellingGetIgnoredWordListLengthWithTag(int tag); void sqSpellingGetIgnoredWordListWithTaginto(int tag, char* string); int sqSpelllingGetLanguageLength(void); void sqSpelllingGetLanguageInto(char* string); int sqSpelllingGetUniqueSpellingTag(void); int sqSpelllingGuessForWordLengthwithTag(char * string, int tag); void sqSpelllingGuessForWordwithTaginto(char *string, int tag, char *results); void sqSpelllingSetIgnoredWordwithTag(char *string, int tag); void sqSpelllingSetIgnoredWordswithTag(char *string, int tag); void sqSpelllingSetLanguage(char *string); ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/Info-SqueakFFIPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable SqueakFFIPrims CFBundleGetInfoString SqueakFFIPrims for Squeak CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.SqueakFFIPrims CFBundleInfoDictionaryVersion 6.0 CFBundleName SqueakFFIPrims for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.6.0b5 CFBundleSignature FAST CFBundleVersion 1.6.0b5 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/SqueakFFIPrims.proj.xml ================================================ ]> SqueakFFIPrims UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:SqueakAtSourceForge:squeak:platforms:Mac OS: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SearchPath PathLamie:Squeak:SqueakAtSourceForge:squeak:platforms:Cross: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameSqueakFFIPrims OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000010122D40100000000000010010123650 000200000000000000000000101227A000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources 1 MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileSqueakFFIPrims MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name sqFFI.h MacOS Text Name sqMacFFIPPC.c MacOS Text Name SqueakFFIPrims.c MacOS Text Name MSL SIOUX.PPC.Lib MacOS Library Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name sqFFI.h MacOS Name sqMacFFIPPC.c MacOS Name SqueakFFIPrims.c MacOS Name MSL SIOUX.PPC.Lib MacOS SqueakFFIPrims Source SqueakFFIPrims Name InterfaceLib MacOS SqueakFFIPrims Name MathLib MacOS SqueakFFIPrims Name MSL C.PPC.Lib MacOS SqueakFFIPrims Name MSL RuntimePPC.Lib MacOS SqueakFFIPrims Name MSL SIOUX.PPC.Lib MacOS SqueakFFIPrims Name sqFFI.h MacOS SqueakFFIPrims Name sqMacFFIPPC.c MacOS SqueakFFIPrims Name SqueakFFIPrims.c MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/ppc-darwin-Carbon-UI.c ================================================ #if __BIG_ENDIAN__ // THIS IS BROKEN FOR CROQUET /* ppc-darwin.c -- FFI support for PowerPC on Mach-O (Darwin) * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2004-04-03 02:59:34 by piumarta on emilia.local * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Notes: * * This is a complete rewrite of the version for MacPPC. (The latter * is hopelessly broken when passing long longs or structs containing * an element of alignment less strict than int.) * * Bugs: * * Because of the way strings are handled, this implementation is * neither reentrant nor thread safe. * * References: * * Mach-O Runtime Architecture, Apple Computer Inc., July 2002. */ #include "sq.h" #include "sqFFI.h" #include #include #include #ifndef LONGLONG # define LONGLONG long long #endif #if 0 # define DPRINTF(ARGS) printf ARGS; fflush(stdout) #else # define DPRINTF(ARGS) #endif extern struct VirtualMachine *interpreterProxy; #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else # define primitiveFail() interpreterProxy->primitiveFail(); #endif #define GPR_MAX 8 #define FPR_MAX 13 #define ARG_MAX 512 static char *strings[ARG_MAX]; static int stringCount= 0; static int giLocker; #if 0 static char structs[ARG_MAX * sizeof(int)]; static int structCount= 0; #endif /* the following avoids an awful lot of _very_ inefficient junk in the asm */ static struct { int _gprCount; // 0 int _fprCount; // 4 int _stackIndex; // 8 int *_structReturnValue; // 12 (everything below is 8-byte aligned) LONGLONG _longReturnValue; // 16 double _floatReturnValue; // 24 int _gprs[GPR_MAX]; // 32 double _fprs[FPR_MAX]; // 32 + 4*GPR_MAX int _stack[ARG_MAX]; // 32 + 4*GPR_MAX + 8*FPR_MAX } global; #define gprCount global._gprCount #define fprCount global._fprCount #define stackIndex global._stackIndex #define structReturnValue global._structReturnValue #define longReturnValue global._longReturnValue #define floatReturnValue global._floatReturnValue #define gprs global._gprs #define fprs global._fprs #define stack global._stack extern int ffiCallAddressOf(void *addr, void *globals); int ffiInitialize(void) { DPRINTF(("ffiInitialize\n")); stackIndex= gprCount= fprCount= 0; #if 0 structCount= 0; #endif floatReturnValue= 0.0; return 1; } int ffiSupportsCallingConvention(int callType) { return (callType == FFICallTypeCDecl) || (callType == FFICallTypeApi); } int ffiAlloc(int byteSize) { int ptr= (int)malloc(byteSize); DPRINTF(("ffiAlloc(%d) => %08x\n", byteSize, ptr)); return ptr; } int ffiFree(int ptr) { DPRINTF(("ffiFree(%08x)\n", ptr)); if (ptr) free((void *)ptr); return 1; } #define checkStack() \ if (stackIndex >= ARG_MAX) \ return primitiveFail() #define checkGPR() \ if ((gprCount >= GPR_MAX) && (stackIndex >= ARG_MAX)) \ return primitiveFail() #define qalignStack() stackIndex += (stackIndex & 1) #define pushGPR(value) \ checkGPR(); \ if (gprCount < GPR_MAX) \ gprs[gprCount++]= value; \ stack[stackIndex++]= value #define qalignGPR() gprCount += (gprCount & 1) int ffiPushSignedChar(int value) { DPRINTF(("ffiPushSignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedChar(int value) { DPRINTF(("ffiPushUnsignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedByte(int value) { DPRINTF(("ffiPushSignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedByte(int value) { DPRINTF(("ffiPushUnsignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedShort(int value) { DPRINTF(("ffiPushSignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedShort(int value) { DPRINTF(("ffiPushUnsignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedInt(int value) { DPRINTF(("ffiPushSignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedInt(int value) { DPRINTF(("ffiPushUnsignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedLongLong(int low, int high) { DPRINTF(("ffiPushSignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushUnsignedLongLong(int low, int high) { DPRINTF(("ffiPushUnsignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushPointer(int pointer) { DPRINTF(("ffiPushPointer %08x\n", pointer)); pushGPR(pointer); return 1; } int ffiPushSingleFloat(double value) { DPRINTF(("ffiPushSingleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) fprs[fprCount++]= value; { float floatValue= (float)value; pushGPR(*(int *)&floatValue); } return 1; } int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) fprs[fprCount++]= value; pushGPR(((int *)&value)[0]); pushGPR(((int *)&value)[1]); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; DPRINTF(("ffiPushStringOfLength %d\n", length)); checkGPR(); ptr= (char *)malloc(length + 1); if (!ptr) return primitiveFail(); memcpy(ptr, (void *)srcIndex, length); ptr[length]= '\0'; strings[stringCount++]= ptr; pushGPR((int)ptr); return 1; } static inline int min(int x, int y) { return (x < y) ? x : y; } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int i; char *data = (char *)pointer; char *argp = (char *)&stack[stackIndex]; #define argl (char *)&stack[ARG_MAX] int argSize = *structSpec & FFIStructSizeMask; char *gprp = (char *)&gprs[gprCount]; #define gprl (char *)&gprs[GPR_MAX] int gprSize = min(argSize, gprl - gprp); DPRINTF(("ffiPush %08x Structure %p OfLength %d\n", pointer, structSpec, specSize)); if (gprSize < 4) gprp += (4 - gprSize); if (argSize < 4) argp += (4 - gprSize); if (argp + argSize > argl) return primitiveFail(); memcpy((void *)gprp, (void *)data, gprSize); memcpy((void *)argp, (void *)data, argSize); gprCount += (gprSize + sizeof(int) - 1) / sizeof(int); stackIndex += (argSize + sizeof(int) - 1) / sizeof(int); #undef argl #undef gprl for (i= 0; i < specSize; ++i) { int typeSpec= structSpec[i]; if (typeSpec & FFIFlagPointer) continue; else if (typeSpec & FFIFlagStructure) continue; else { int atomicType= (typeSpec & FFIAtomicTypeMask) >> FFIAtomicTypeShift; switch (atomicType) { case FFITypeSingleFloat: if (fprCount < FPR_MAX) fprs[fprCount++]= *(float *)data; break; case FFITypeDoubleFloat: if (fprCount < FPR_MAX) fprs[fprCount++]= *(double *)data; break; default: break; } data += typeSpec & FFIStructSizeMask; } } return 1; } int ffiCanReturn(int *structSpec, int specSize) { int header= *structSpec; DPRINTF(("ffiCanReturn %p %d\n", structSpec, specSize)); if (header & FFIFlagPointer) return 1; if (header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize= header & FFIStructSizeMask; structReturnValue= malloc(structSize); if (!structReturnValue) return 0; pushGPR((int)structReturnValue); } return 1; } double ffiReturnFloatValue(void) { return floatReturnValue; } int ffiLongLongResultLow(void) { return ((int *)&longReturnValue)[1]; } int ffiLongLongResultHigh(void) { return ((int *)&longReturnValue)[0]; } int ffiStoreStructure(int address, int structSize) { DPRINTF(("ffiStoreStructure %08x %d\n", address, structSize)); memcpy((void *)address, structReturnValue ? (void *)structReturnValue : (void *)&longReturnValue, structSize); return 1; } int ffiCleanup(void) { int i; DPRINTF(("ffiCleanup\n")); for (i= 0; i < stringCount; ++i) free(strings[i]); stringCount= 0; if (structReturnValue) { free(structReturnValue); structReturnValue= 0; } return 1; } int ffiCallAddressOfWithPointerReturnx(int fn, int callType) { DPRINTF(("ffiCallAddressOfWithPointerReturn %08x %d\n", fn, callType)); return ffiCallAddressOf((void *)fn, (void *)&global); } int ffiCallAddressOfWithStructReturnx(int fn, int callType, int* structSpec, int specSize) { DPRINTF(("ffiCallAddressOfWithStructReturn %08x %d %p %d\n", fn, callType, structSpec, specSize)); return ffiCallAddressOf((void *)fn, (void *)&global); } int ffiCallAddressOfWithReturnTypex(int fn, int callType, int typeSpec) { DPRINTF(("ffiCallAddressOfWithReturnType %08x %d %d\n", fn, callType, typeSpec)); return ffiCallAddressOf((void *)fn, (void *)&global); } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*5); foo[0] = 2; foo[1] = ffiCallAddressOfWithPointerReturnx; foo[2] = fn; foo[3] = callType; foo[4] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[4]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*7); foo[0] = 4; foo[1] = ffiCallAddressOfWithStructReturnx; foo[2] = fn; foo[3] = callType; foo[4] = structSpec; foo[5] = specSize; foo[6] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[6]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*6); foo[0] = 3; foo[1] = ffiCallAddressOfWithReturnTypex; foo[2] = fn; foo[3] = callType; foo[4] = typeSpec; foo[5] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[5]; free(foo); return resultsOfCall; } } #if !defined(NO_FFI_TEST) #undef gprCount #undef fprCount #undef stackIndex #undef structReturnValue #undef longReturnValue #undef floatReturnValue #undef gprs #undef fprs #undef stack #include "ppc-global.h" #define offset(field) ((char *)&global._##field - (char *)&global._gprCount) #include void ffiDoAssertions(void) { assert(gprCount == offset(gprCount)); assert(fprCount == offset(fprCount)); assert(stackIndex == offset(stackIndex)); assert(structReturnValue == offset(structReturnValue)); assert(longReturnValue == offset(longReturnValue)); assert(floatReturnValue == offset(floatReturnValue)); assert(gprs == offset(gprs)); assert(fprs == offset(fprs)); assert(stack == offset(stack)); assert(stack + (ARG_MAX * sizeof(int)) == sizeof(global)); } #endif #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/ppc-darwin-asm-MacIntel.S ================================================ #if __BIG_ENDIAN__ // LIKELY BROKEN? FOR CROQUET? NOT SURE COULD BE COMPANION C CODE /* ppc-sysv-asm.S -- PowerPC FFI trampoline for Mach-O -*- asm -*- * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-08-15 15:36:13 by piumarta on emilia.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. */ /* Mach-O PPC stack frames look like this (higher addresses first): * * | caller's lr | * | caller's cr | * caller's sp->| caller's caller's sp | * | fpr save area | * | gpr save area | * | [alignment pad] | * | local variables | * sp + 24 -> | param save area | * sp + 20 -> | caller's toc | * sp + 16 -> | reserved | * sp + 12 -> | reserved | * sp + 8 -> | (callee-save) lr | * sp + 4 -> | (callee-save) cr | * sp + 0 -> | caller's sp | */ #define GPR_MAX 8 #define FPR_MAX 13 #define ARG_MAX 512 #define FRAMESZ 32 #include "ppc-global.h" #define sp r1 .text .globl _ffiCallAddressOf _ffiCallAddressOf: stwu sp, -FRAMESZ(sp) // push trampoline frame mflr r0 stw r0, (FRAMESZ+8)(sp) mfcr r0 stw r0, (FRAMESZ+4)(sp) // saved ccr mtlr r3 // destination fn address stw r4, (FRAMESZ-4)(sp) // globals lwz r5, stackIndex(r4) slwi r10, r5, 2 // param save area size addi r10, r10, 32+15 // round to quad word rlwinm r10, r10, 0,0,27 neg r10, r10 stwux sp, sp, r10 // push ffi caller frame cmpwi r5, 0 // have params? beq+ 2f mtctr r5 // words to move la r10, (stack-4)(r4) // ffi param stack - 4 addi r11, sp, 24-4 // param save area - 4 1: lwzu r0, 4(r10) // copy param save area stwu r0, 4(r11) bdnz 1b 2: lwz r5, fprCount(r4) cmpwi r5, 0 beq+ 4f // no fp args la r11, fprs(r4) cmpwi r5, 4 ble+ 3f lfd f5, 32(r11) lfd f6, 40(r11) lfd f7, 48(r11) lfd f8, 56(r11) # if (FPR_MAX > 8) lfd f9, 64(r11) lfd f10, 72(r11) lfd f11, 80(r11) lfd f12, 88(r11) lfd f13, 96(r11) # endif 3: lfd f1, 0(r11) lfd f2, 8(r11) lfd f3, 16(r11) lfd f4, 24(r11) 4: lwz r5, gprCount(r4) cmpwi r5, 0 beq- 6f // no int args la r11, gprs(r4) cmpwi r5, 4 ble+ 5f lwz r7, 16(r11) lwz r8, 20(r11) lwz r9, 24(r11) lwz r10, 28(r11) 5: lwz r3, 0(r11) lwz r4, 4(r11) lwz r5, 8(r11) lwz r6, 12(r11) 6: blrl // callout lwz sp, 0(sp) // pop ffi caller frame lwz r5, (FRAMESZ-4)(sp) // globals stw r3, longReturnValue+0(r5) stw r4, longReturnValue+4(r5) stfd f1, floatReturnValue(r5) lwz r0, (FRAMESZ+8)(sp) mtlr r0 lwz r0, (FRAMESZ+4)(sp) // saved ccr mtcr r0 addi sp, sp, FRAMESZ // pop trampoline frame blr #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/ppc-global.h ================================================ #define gprCount ( 0) #define fprCount ( 4) #define stackIndex ( 8) #define structReturnValue (12) #define longReturnValue (16) #define floatReturnValue (24) #define gprs (32) #define fprs (32 + 4*GPR_MAX) #define stack (32 + 4*GPR_MAX + 8*FPR_MAX) ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/sqMacFFI.s ================================================ #if __BIG_ENDIAN__ /**************************************************************************** * PROJECT: mac os-x FFI assembler, from the os-9 version * FILE: sqMacFFI.s * CONTENT: * * AUTHOR: Andreas Raab (ar), John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacFFI.s 1369 2006-03-22 04:48:20Z johnmci $ * * NOTES: See change log below. * 1/24/2002 JMM hacked from the original code for os-x, added save for CCR and * tweaked _4_gpregs compare * * 11/14/2002 JMM clean & fix quad word alignment issue * 2/24/2006 JMM unable to compile and work on GCC 3.3, perhaps linkage area is 32, not 24? *****************************************************************************/ #import #import .text .globl _ffiCallAddressOf _ffiCallAddressOf: mflr r0 /* Save link register */ stw r0, 8(sp) mfcr r0 /* save CCR */ stw r0, 4(sp) /* get stack index and preserve it for copying stuff later */ EXTERN_TO_REG(r4, _ffiStackIndex) // lwz r4, ffiStackIndex(r2) /* compute frame size */ rlwinm r5, r4, 2, 0, 29 /* ffiStackIndex words to bytes (e.g., "slwi r5, r4, 2") */ addi r5, r5, 32+15 /* linkage area */ //* JMM 02/25/06 was 24, Ian has 32 */ rlwinm r5,r5,0,0,27 /* JMM round up to quad word*/ neg r5, r5 /* stack goes down */ stwux sp, sp, r5 /* adjust stack frame */ /* load the stack frame area */ /* note: r4 == ffiStackIndex */ addi r5, sp, 24 /* dst = r1 + linkage area, was 24 */ EXTERN_TO_REG(r6, _ffiStackLocation) //lwz r6, ffiStack(r2) /* src = ffiStack */ li r7, 0 /* i = 0 */ b nextItem copyItem: rlwinm r8, r7, 2, 0, 29 /* r8 = i << 2 (e.g., "slwi r8, r7, 2") */ lwzx r0, r6, r8 /* r0 = ffiStack[r8] */ addi r7, r7, 1 /* i = i + 1 */ stwx r0, r5, r8 /* dst[r8] = r0 */ nextItem: cmpw r7, r4 /* i < ffiStackIndex ? */ blt copyItem /* Keep addr somewhere so we can load all regs beforehand */ stw r3, 20(sp) /* load all the floating point registers */ EXTERN_TO_REG(r3, _fpRegCount) //lwz r3, fpRegCount EXTERN_TO_REG(r12, _FPRegsLocation) // lwz r12, FPRegs(r2) cmpwi r3, 0 /* skip all fpregs if no FP values used */ beq _0_fpregs /* was lt should be eq */ cmpwi r3, 8 blt _7_fpregs /* skip last N fpregs if unused */ _all_fpregs: lfd f8, 56(r12) lfd f9, 64(r12) lfd f10, 72(r12) lfd f11, 80(r12) lfd f12, 88(r12) lfd f13, 96(r12) _7_fpregs: lfd f1, 0(r12) lfd f2, 8(r12) lfd f3, 16(r12) lfd f4, 24(r12) lfd f5, 32(r12) lfd f6, 40(r12) lfd f7, 48(r12) _0_fpregs: /* load all the general purpose registers */ EXTERN_TO_REG(r3, _gpRegCount) //lwz r3, gpRegCount EXTERN_TO_REG(r12, _GPRegsLocation) // lwz r12, GPRegs(r2) cmpwi r3, 5 /* 5 was 4 in original code but that seems to be a bug? */ blt _4_gpregs /* skip last four gpregs if unused */ _all_gpregs: lwz r7, 16(r12) lwz r8, 20(r12) lwz r9, 24(r12) lwz r10, 28(r12) _4_gpregs: lwz r3, 0(r12) lwz r4, 4(r12) lwz r5, 8(r12) lwz r6, 12(r12) _0_gpregs: /* go calling out */ //Note: OS-X mach-o does not use TVectors rather the addr is the entry point lwz r12, 20(sp) /* fetch addr */ mtctr r12 /* move entry point into count register */ bctrl /* jump through count register and link */ lwz sp, 0(sp) /* restore frame */ /* store the result of the call */ /* more intelligent logic would have a check for type versus assuming all */ REG_TO_EXTERN(r3,_intReturnValue) // stw r3, intReturnValue(r2) EXTERN_TO_REG(r12, _longReturnValueLocation) //lwz r12, longReturnValue(r2) stw r3, 0(r12) stw r4, 4(r12) EXTERN_TO_REG(r12, _floatReturnValueLocation) //lwz r12, longReturnValue(r2) stfd f1, 0(r12) //stfd f1, floatReturnValue(r2) /* and get out of here */ lwz r0, 4(sp) /*restore CCR */ mtcrf 0xff,r0 lwz r0, 8(sp) /* restore ltr */ mtlr r0 blr #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/sqMacFFIPPC.c ================================================ #if __BIG_ENDIAN__ /**************************************************************************** * PROJECT: Squeak foreign function interface * FILE: sqMacFFIPPC.c * CONTENT: Mac/PPC specific support for the foreign function interface * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: Andreas.Raab@disney.com * RCSID: $Id: sqMacFFIPPC.c 1413 2006-04-10 06:40:23Z johnmci $ * * NOTES: * April 9th, 2006 JMM fix, double was pushed on stack incorrectly, this affected things only when 14 values passed * *****************************************************************************/ #include "sq.h" #include "sqFFI.h" /* note: LONGLONG is usually declared by universal headers */ #ifndef LONGLONG #define LONGLONG long long #endif #define MAX_PATH PATH_MAX //#define DEBUGFFI 1 #if defined ( __APPLE__ ) && defined ( __MACH__ ) #define staticIssue #else #define staticIssue static #endif extern struct VirtualMachine *interpreterProxy; #define primitiveFail() interpreterProxy->primitiveFail(); #define GP_MAX_REGS 8 #define FP_MAX_REGS 13 /* Values passed in GPR3-GPR10 */ static int GPRegs[8]; /* Nr of GPRegs used so far */ staticIssue int gpRegCount = 0; /* Values passed in FPR1-FPR13 */ static double FPRegs[13]; /* Nr of FPRegs used so far */ staticIssue int fpRegCount = 0; /* Max stack size */ #define FFI_MAX_STACK 512 /* The stack used to assemble the arguments for a call */ static int ffiStack[FFI_MAX_STACK]; /* The stack pointer while filling the stack */ staticIssue int ffiStackIndex = 0; /* The area for temporarily allocated strings */ static char *ffiTempStrings[FFI_MAX_STACK]; /* The number of temporarily allocated strings */ static int ffiTempStringCount = 0; /* The return values for calls */ staticIssue int intReturnValue; static LONGLONG longReturnValue; static double floatReturnValue; static int *structReturnValue = NULL; /**************************************************************/ #if DEBUGFFI # define DPRINTF(ARGS) printf ARGS; fflush(stdout) #else # define DPRINTF(ARGS) #endif #define ARG_CHECK() if(gpRegCount >= GP_MAX_REGS && ffiStackIndex >= FFI_MAX_STACK) return primitiveFail(); #define ARG_PUSH(value) { \ ARG_CHECK(); \ if(gpRegCount < GP_MAX_REGS) GPRegs[gpRegCount++] = value; \ DPRINTF(("ARG_PUSH %i (%08x)\n", ffiStackIndex, value)); \ ffiStack[ffiStackIndex++] = value; \ } /*****************************************************************************/ /*****************************************************************************/ static FILE *ffiLogFile = NULL; int ffiLogFileNameOfLength(void *nameIndex, int nameLength) { char fileName[MAX_PATH]; FILE *fp; if(nameIndex && nameLength) { if(nameLength >= MAX_PATH) return 0; strncpy(fileName, nameIndex, nameLength); fileName[nameLength] = 0; /* attempt to open the file and if we can't fail */ fp = fopen(fileName, "at"); if(fp == NULL) return 0; /* close the old log file if needed and use the new one */ if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = fp; fprintf(ffiLogFile, "------- Log started -------\n"); fflush(fp); } else { if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = NULL; } return 1; } int ffiLogCallOfLength(void *nameIndex, int nameLength) { if(ffiLogFile == NULL) return 0; fprintf(ffiLogFile, "%.*s\n", nameIndex, nameLength); fflush(ffiLogFile); } /*****************************************************************************/ /*****************************************************************************/ /* ffiInitialize: Announce that the VM is about to do an external function call. */ int ffiInitialize(void) { ffiStackIndex = 0; gpRegCount = 0; fpRegCount = 0; floatReturnValue = 0.0; return 1; } /* ffiSupportsCallingConvention: Return true if the support code supports the given calling convention. */ int ffiSupportsCallingConvention(int callType) { if(callType == FFICallTypeCDecl) return 1; if(callType == FFICallTypeApi) return 1; return 0; } int ffiAlloc(int byteSize) { int data = (int) malloc(byteSize); DPRINTF(("ffiAlloc (%08x)\n",data)); return data; } int ffiFree(int ptr) { DPRINTF(("ffiFree (%08x)\n",ptr)); if(ptr) free((void*)ptr); return 1; } /*****************************************************************************/ /*****************************************************************************/ int ffiPushSignedChar(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedChar(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedByte(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedByte(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedShort(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedShort(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedInt(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedInt(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedLongLong(int low, int high) { ARG_PUSH(high); ARG_PUSH(low); return 1; } int ffiPushUnsignedLongLong(int low, int high) { ARG_PUSH(high); ARG_PUSH(low); return 1; } int ffiPushSingleFloat(double value) { float floatValue = (float) value; if(fpRegCount < FP_MAX_REGS) { /* Still space in FPRegs - so we use the more accurate double value */ FPRegs[fpRegCount++] = value; } /* Note: Even for args that are passed in FPRegs we pass the actual 32bit value in either GPRegs or stack frame for varargs calls. */ ARG_PUSH(*(int*)(&floatValue)); return 1; } int ffiPushDoubleFloat(double value) { if(fpRegCount < FP_MAX_REGS) { /* Still space in FPRegs */ FPRegs[fpRegCount++] = value; } /* Note: Even for args that are passed in FPRegs we pass the actual 64bit value in either GPRegs or stack frame for varargs calls. */ ARG_PUSH(((int*)(&value))[0]); //JMM April 9th, 2006 was push 1 push 0, but testing shows it was wrong ARG_PUSH(((int*)(&value))[1]); return 1; } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int i, typeSpec; int *data = (int*) pointer; for(i = 0; i> FFIAtomicTypeShift; switch(atomicType) { case FFITypeUnsignedChar: case FFITypeUnsignedByte: ffiPushUnsignedByte(*(unsigned char*)data); break; case FFITypeSignedChar: case FFITypeSignedByte: ffiPushSignedByte(*(signed char*)data); break; case FFITypeUnsignedShort: ffiPushUnsignedShort(*(unsigned short*)data); break; case FFITypeSignedShort: ffiPushSignedShort(*(signed short*)data); break; case FFITypeUnsignedInt: ffiPushUnsignedInt(*(unsigned int*)data); break; case FFITypeSignedInt: ffiPushSignedInt(*(signed int*)data); break; case FFITypeUnsignedLongLong: ffiPushUnsignedLongLong( ((unsigned int*)data)[1], ((unsigned int*)data)[0]); break; case FFITypeSignedLongLong: ffiPushSignedLongLong( ((signed int*)data)[1], ((signed int*)data)[0]); break; case FFITypeSingleFloat: ffiPushSingleFloat( *(float*)data); break; case FFITypeDoubleFloat: { double fArg; ((int*)&fArg)[0] = ((int*)data)[0]; ((int*)&fArg)[1] = ((int*)data)[1]; ffiPushDoubleFloat(fArg); } break; default: return primitiveFail(); } data = (int*) ((int)data + (typeSpec & FFIStructSizeMask)); } } return 1; } int ffiPushPointer(int pointer) { ARG_PUSH(pointer); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; ARG_CHECK(); /* fail before allocating */ ptr = (char*) malloc(length+1); if(!ptr) return primitiveFail(); memcpy(ptr, (void*)srcIndex, length); ptr[length] = 0; ffiTempStrings[ffiTempStringCount++] = ptr; ARG_PUSH((int)ptr); return 1; } /*****************************************************************************/ /*****************************************************************************/ /* ffiCanReturn: Return true if the support code can return the given type. */ int ffiCanReturn(int *structSpec, int specSize) { int header = *structSpec; if(header & FFIFlagPointer) return 1; if(header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize = header & FFIStructSizeMask; structReturnValue = malloc(structSize); if(!structReturnValue) return 0; ARG_PUSH((int)structReturnValue); } return 1; } /* ffiReturnFloatValue: Return the value from a previous ffi call with float return type. */ double ffiReturnFloatValue(void) { DPRINTF(("ffiReturnFloatValue %d\n",floatReturnValue)); return floatReturnValue; } /* ffiLongLongResultLow: Return the low 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultLow(void) { DPRINTF(("ffiLongLongResultLow %i\n",((int*) &longReturnValue)[1])); return ((int*) &longReturnValue)[1]; } /* ffiLongLongResultHigh: Return the high 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultHigh(void) { DPRINTF(("ffiLongLongResultHigh %i\n",((int*) &longReturnValue)[0])); return ((int*) &longReturnValue)[0]; } /* ffiStoreStructure: Store the structure result of a previous ffi call into the given address. */ int ffiStoreStructure(int address, int structSize) { DPRINTF(("ffiStoreStructure\n")); if(structReturnValue) { memcpy((void*)address, (void*)structReturnValue, structSize); } else { memcpy((void*)address, (void*)&intReturnValue, structSize); } return 1; } /* ffiCleanup: Cleanup after a foreign function call has completed. The generic support code only frees the temporarily allocated strings. */ int ffiCleanup(void) { int i; for(i=0; iioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*5); foo[0] = 2; foo[1] = ffiCallAddressOfWithPointerReturnx; foo[2] = fn; foo[3] = callType; foo[4] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[4]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*7); foo[0] = 4; foo[1] = ffiCallAddressOfWithStructReturnx; foo[2] = fn; foo[3] = callType; foo[4] = structSpec; foo[5] = specSize; foo[6] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[6]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*6); foo[0] = 3; foo[1] = ffiCallAddressOfWithReturnTypex; foo[2] = fn; foo[3] = callType; foo[4] = typeSpec; foo[5] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[5]; free(foo); return resultsOfCall; } } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /************ Test functions for the foreign function interface **************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ #ifndef NO_FFI_TEST typedef struct ffiTestPoint2 { int x; int y; } ffiTestPoint2; typedef struct ffiTestPoint4 { int x; int y; int z; int w; } ffiTestPoint4; #pragma export on EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4); EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4); EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4); EXPORT(int) ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8); EXPORT(float) ffiTestFloats(float f1, float f2); EXPORT(float) ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7); EXPORT(float) ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13); EXPORT(float) ffiTestFloats14(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14); EXPORT(double) ffiTestDoubles14(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14); EXPORT(double) ffiTestDoubles(double d1, double d2); EXPORT(char *) ffiPrintString(char *string); EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2); EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2); EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2); EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8a1(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLong8a2(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLonga1(char c1, LONGLONG i1, LONGLONG i2); EXPORT(LONGLONG) ffiTestLongLonga2(char c1, char c2, LONGLONG i1, LONGLONG i2); #pragma export off /* test passing characters */ EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4) { printf("4 characters came in as\nc1 = %c (%x)\nc2 = %c (%x)\nc3 = %c (%x)\nc4 = %c (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return 'C'; } /* test passing shorts */ EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4) { printf("4 shorts came in as\ns1 = %d (%x)\ns2 = %d (%x)\ns3 = %d (%x)\ns4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return -42; } /* test passing ints */ EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4) { printf("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return 42; } EXPORT(int) ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8) { printf("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\ni5 = %d (%x)\ni6 = %d (%x)\ni7 = %d (%x)\ni8 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4, c5, c5, c6, c6, c7, c7, c8, c8); return 42; } /* test passing and returning floats */ EXPORT(float) ffiTestFloats(float f1, float f2) { printf("The two floats are %f and %f\n", f1, f2); return (float) (f1 + f2); } EXPORT(float) ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7) { printf("The 7 floats are %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7); } EXPORT(float) ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13) { printf("The 13 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13); } EXPORT(float) ffiTestFloats14(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14) { printf("The 14 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14); } EXPORT(double) ffiTestDoubles14(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14) { printf("The 14 double are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); return (double) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14); } /* test passing and returning doubles */ EXPORT(double) ffiTestDoubles(double d1, double d2) { printf("The two floats are %f and %f\n", (float)d1, (float)d2); return d1+d2; } /* test passing and returning strings */ EXPORT(char*) ffiPrintString(char *string) { printf("%s\n", string); return string; } /* test passing and returning 64bit structures */ EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2) { ffiTestPoint2 result; printf("pt1.x = %d\npt1.y = %d\npt2.x = %d\npt2.y = %d\n", pt1.x, pt1.y, pt2.x, pt2.y); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; return result; } /* test passing and returning large structures */ EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2) { ffiTestPoint4 result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1.x, pt1.y, pt1.z, pt1.w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2.x, pt2.y, pt2.z, pt2.w); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; result.z = pt1.z + pt2.z; result.w = pt1.w + pt2.w; return result; } /* test passing and returning pointers */ EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2) { ffiTestPoint4 *result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1->x, pt1->y, pt1->z, pt1->w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2->x, pt2->y, pt2->z, pt2->w); result = (ffiTestPoint4*) malloc(sizeof(ffiTestPoint4)); result->x = pt1->x + pt2->x; result->y = pt1->y + pt2->y; result->z = pt1->z + pt2->z; result->w = pt1->w + pt2->w; return result; } /* test passing and returning longlongs */ EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2) { return i1 + i2; } EXPORT(LONGLONG) ffiTestLongLonga1(char c1, LONGLONG i1, LONGLONG i2) { return c1 + i1 + i2; } EXPORT(LONGLONG) ffiTestLongLonga2(char c1, char c2, LONGLONG i1, LONGLONG i2) { return c1 + c2 + i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8a1(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+c9+i1 + i2; } EXPORT(LONGLONG) ffiTestLongLong8a2(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10, LONGLONG i1, LONGLONG i2) { return c1+c2+c3+c4+c5+c6+c7+c8+c9+c10+i1 + i2; } #endif /* NO_FFI_TEST */ #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/sqMacIntel-Win32.c ================================================ #if __LITTLE_ENDIAN__ /**************************************************************************** * PROJECT: Squeak foreign function interface * FILE: sqWin32FFI.c * CONTENT: Win32 support for the foreign function interface * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: sqWin32FFI.c 414 2002-06-01 11:44:39Z andreasraab $ * * NOTES: * Altered by John M McIntosh for Mac Intel Support, use UI Lock, also use system V with Darwin and MacIntel logic assembler * *****************************************************************************/ #include "sq.h" #include "sqFFI.h" #if !defined(PATH_MAX) # include #endif extern struct VirtualMachine *interpreterProxy; #define primitiveFail() interpreterProxy->primitiveFail(); #ifdef _MSC_VER #define LONGLONG __int64 #endif #ifdef __GNUC__ #define LONGLONG long long int #endif /* Max stack size */ #define FFI_MAX_ARGS 128 /* The stack used to assemble the arguments for a call */ int ffiArgs[FFI_MAX_ARGS]; /* The stack pointer while filling the stack */ int ffiArgIndex = 0; /* The area for temporarily allocated strings */ static char *ffiTempStrings[FFI_MAX_ARGS]; /* The number of temporarily allocated strings */ static int ffiTempStringCount = 0; /* The return values for calls */ volatile int intReturnValue; volatile int intReturnValue2; volatile double floatReturnValue; static void* structReturnValue; #define ARG_CHECK() if(ffiArgIndex >= FFI_MAX_ARGS) return primitiveFail(); #define ARG_PUSH(value) { ARG_CHECK(); ffiArgs[ffiArgIndex++] = value; } #define MAX_PATH PATH_MAX /*****************************************************************************/ /*****************************************************************************/ static FILE *ffiLogFile = NULL; int ffiLogFileNameOfLength(void *nameIndex, int nameLength) { char fileName[MAX_PATH]; FILE *fp; if(nameIndex && nameLength) { if(nameLength >= MAX_PATH) return 0; strncpy(fileName, nameIndex, nameLength); fileName[nameLength] = 0; /* attempt to open the file and if we can't fail */ fp = fopen(fileName, "at"); if(fp == NULL) return 0; /* close the old log file if needed and use the new one */ if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = fp; fprintf(ffiLogFile, "------- Log started -------\n"); fflush(fp); } else { if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = NULL; } return 1; } int ffiLogCallOfLength(void *nameIndex, int nameLength) { if(ffiLogFile == NULL) return 0; fprintf(ffiLogFile, "%.*s\n", nameIndex, nameLength); fflush(ffiLogFile); } /*****************************************************************************/ /*****************************************************************************/ /* ffiInitialize: Announce that the VM is about to do an external function call. */ int ffiInitialize(void) { ffiArgIndex = 0; ffiTempStringCount = 0; return 1; } /* ffiSupportsCallingConvention: Return true if the support code supports the given calling convention. */ int ffiSupportsCallingConvention(int callType) { if(callType == FFICallTypeCDecl) return 1; if(callType == FFICallTypeApi) return 1; return 0; } int ffiAlloc(int byteSize) { return (int) malloc(byteSize); } int ffiFree(int ptr) { if(ptr) free((void*)ptr); return 1; } /*****************************************************************************/ /*****************************************************************************/ int ffiPushSignedChar(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedChar(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedByte(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedByte(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedShort(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedShort(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedInt(int value) { ARG_PUSH(value); return 1; } int ffiPushUnsignedInt(int value) { ARG_PUSH(value); return 1; } int ffiPushSignedLongLong(int lowWord, int highWord) { ARG_PUSH(lowWord); ARG_PUSH(highWord); return 1; } int ffiPushUnsignedLongLong(int lowWord, int highWord) { ARG_PUSH(lowWord); ARG_PUSH(highWord); return 1; } int ffiPushSingleFloat(double value) { float floatValue; floatValue = (float) value; ARG_PUSH(*(int*)(&floatValue)); return 1; } int ffiPushDoubleFloat(double value) { ARG_PUSH(((int*)(&value))[0]); ARG_PUSH(((int*)(&value))[1]); return 1; } int ffiPushStructureOfLength(int pointer, int* structSpec, int structSize) { int nItems, i; nItems = ((*structSpec & FFIStructSizeMask) + 3) / 4; if(pointer == 0) return primitiveFail(); for(i=0; i < nItems;i++) ARG_PUSH(((int*)pointer)[i]); return 1; } int ffiPushPointer(int pointer) { ARG_PUSH(pointer); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; ARG_CHECK(); /* fail before allocating */ ptr = (char*) malloc(length+1); if(!ptr) return primitiveFail(); memcpy(ptr, (void*)srcIndex, length); ptr[length] = 0; ffiTempStrings[ffiTempStringCount++] = ptr; ARG_PUSH((int)ptr); return 1; } /*****************************************************************************/ /*****************************************************************************/ /* ffiCanReturn: Return true if the support code can return the given type. */ int ffiCanReturn(int *structSpec, int specSize) { int header = *structSpec; if(header & FFIFlagPointer) return 1; if(header & FFIFlagStructure) { int structSize = header & FFIStructSizeMask; if(structSize > 8) { structReturnValue = malloc(structSize); if(!structReturnValue) return 0; ARG_PUSH((int)structReturnValue); } } return 1; } /* ffiReturnFloatValue: Return the value from a previous ffi call with float return type. */ double ffiReturnFloatValue(void) { return floatReturnValue; } /* ffiLongLongResultLow: Return the low 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultLow(void) { return intReturnValue; } /* ffiLongLongResultHigh: Return the high 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultHigh(void) { return intReturnValue2; } /* ffiStoreStructure: Store the structure result of a previous ffi call into the given address. Note: Since the ST allocator always allocates multiples of 32bit we can use the atomic types for storing <= 64bit result structures. */ int ffiStoreStructure(int address, int structSize) { if(structSize <= 4) { *(int*)address = intReturnValue; return 1; } if(structSize <= 8) { *(int*)address = intReturnValue; *(int*)(address+4) = intReturnValue2; return 1; } /* assume pointer to hidden structure */ memcpy((void*)address, (void*) structReturnValue, structSize); return 1; } /* ffiCleanup: Cleanup after a foreign function call has completed. */ int ffiCleanup(void) { int i; for(i=0; iioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*5); foo[0] = 2; foo[1] = ffiCallAddressOfWithPointerReturnx; foo[2] = fn; foo[3] = callType; foo[4] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[4]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*7); foo[0] = 4; foo[1] = ffiCallAddressOfWithStructReturnx; foo[2] = fn; foo[3] = callType; foo[4] = structSpec; foo[5] = specSize; foo[6] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[6]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*6); foo[0] = 3; foo[1] = ffiCallAddressOfWithReturnTypex; foo[2] = fn; foo[3] = callType; foo[4] = typeSpec; foo[5] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[5]; free(foo); return resultsOfCall; } } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /************ Test functions for the foreign function interface **************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ #ifndef NO_FFI_TEST typedef struct ffiTestPoint2 { int x; int y; } ffiTestPoint2; typedef struct ffiTestPoint4 { int x; int y; int z; int w; } ffiTestPoint4; #pragma export on EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4); EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4); EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4); EXPORT(float) ffiTestFloats(float f1, float f2); EXPORT(double) ffiTestDoubles(double d1, double d2); EXPORT(char *) ffiPrintString(char *string); EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2); EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2); EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2); EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2); #pragma export off /* test passing characters */ EXPORT(char) ffiTestChars(char c1, char c2, char c3, char c4) { printf("4 characters came in as\nc1 = %c (%x)\nc2 = %c (%x)\nc3 = %c (%x)\nc4 = %c (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } /* test passing shorts */ EXPORT(short) ffiTestShorts(short c1, short c2, short c3, short c4) { printf("4 shorts came in as\ns1 = %d (%x)\ns2 = %d (%x)\ns3 = %d (%x)\ns4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } /* test passing ints */ EXPORT(int) ffiTestInts(int c1, int c2, int c3, int c4) { printf("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4); return c1+c2; } /* test passing and returning floats */ EXPORT(float) ffiTestFloats(float f1, float f2) { printf("The two floats are %f and %f\n", f1, f2); return (float) (f1 + f2); } /* test passing and returning doubles */ EXPORT(double) ffiTestDoubles(double d1, double d2) { printf("The two floats are %f and %f\n", (float)d1, (float)d2); return d1+d2; } /* test passing and returning strings */ EXPORT(char*) ffiPrintString(char *string) { printf("%s\n", string); return string; } /* test passing and returning 64bit structures */ EXPORT(ffiTestPoint2) ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2) { ffiTestPoint2 result; printf("pt1.x = %d\npt1.y = %d\npt2.x = %d\npt2.y = %d\n", pt1.x, pt1.y, pt2.x, pt2.y); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; return result; } /* test passing and returning large structures */ EXPORT(ffiTestPoint4) ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2) { ffiTestPoint4 result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1.x, pt1.y, pt1.z, pt1.w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2.x, pt2.y, pt2.z, pt2.w); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; result.z = pt1.z + pt2.z; result.w = pt1.w + pt2.w; return result; } /* test passing and returning pointers */ EXPORT(ffiTestPoint4*) ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2) { ffiTestPoint4 *result; printf("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1->x, pt1->y, pt1->z, pt1->w); printf("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2->x, pt2->y, pt2->z, pt2->w); result = (ffiTestPoint4*) malloc(sizeof(ffiTestPoint4)); result->x = pt1->x + pt2->x; result->y = pt1->y + pt2->y; result->z = pt1->z + pt2->z; result->w = pt1->w + pt2->w; return result; } /* test passing and returning longlongs */ EXPORT(LONGLONG) ffiTestLongLong(LONGLONG i1, LONGLONG i2) { return i1 + i2; } #endif /* NO_FFI_TEST */ #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/x86-sysv-MacIntel.c ================================================ #if __LITTLE_ENDIAN__ // THIS IS BROKEN FOR CROQUET /* ppc-sysv.c -- FFI support for PowerPC SVr4 ABI * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-02-06 20:08:58 by piumarta on felina.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * BUGS: * * Because of the way strings and structs are handled, this implementation * is neither reentrant nor thread safe. */ #include "sq.h" #include "sqFFI.h" #include #include #ifndef LONGLONG # define LONGLONG long long #endif #if 1 # define DPRINTF(ARGS)printf ARGS #else # define DPRINTF(ARGS) #endif #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else extern struct VirtualMachine *interpreterProxy; # define primitiveFail() interpreterProxy->primitiveFail() #endif enum { FFI_MAX_STACK= 512 }; int ffiStack[FFI_MAX_STACK]; int ffiStackIndex= 0; static int giLocker; static char *ffiTempStrings[FFI_MAX_STACK]; static int ffiTempStringCount= 0; volatile int ffiIntReturnValue; volatile int ffiLongReturnValue; volatile double ffiFloatReturnValue; volatile int *ffiStructReturnValue; extern int ffiCallAddressOf(void *addr, void *stack, int size); static FILE *ffiLogFile = NULL; int ffiLogFileNameOfLength(void *nameIndex, int nameLength) { char fileName[MAX_PATH]; FILE *fp; if(nameIndex && nameLength) { if(nameLength >= MAX_PATH) return 0; strncpy(fileName, nameIndex, nameLength); fileName[nameLength] = 0; /* attempt to open the file and if we can't fail */ fp = fopen(fileName, "at"); if(fp == NULL) return 0; /* close the old log file if needed and use the new one */ if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = fp; fprintf(ffiLogFile, "------- Log started -------\n"); fflush(fp); } else { if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = NULL; } return 1; } int ffiLogCallOfLength(void *nameIndex, int nameLength) { if(ffiLogFile == NULL) return 0; fprintf(ffiLogFile, "%.*s\n", nameIndex, nameLength); fflush(ffiLogFile); } int ffiInitialize(void) { ffiStackIndex= 0; ffiFloatReturnValue= 0.0; return 1; } int ffiSupportsCallingConvention(int callType) { return (callType == FFICallTypeCDecl) || (callType == FFICallTypeApi); } int ffiAlloc(int byteSize) { return (int)malloc(byteSize); } int ffiFree(int ptr) { if (ptr) free((void *)ptr); return 1; } #define checkStack() \ if (ffiStackIndex >= FFI_MAX_STACK) \ return primitiveFail(); #define pushInt(value) \ checkStack(); \ ffiStack[ffiStackIndex++]= (value) int ffiCanReturn(int *structSpec, int specSize) { int header= *structSpec; DPRINTF(("ffiCanReturn structSpec %d specSize %d\n", structSpec, specSize)); if (header & FFIFlagPointer) return 1; if (header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize= header & FFIStructSizeMask; ffiStructReturnValue= malloc(structSize); if (!ffiStructReturnValue) return 0; DPRINTF(("ffiCanReturn allocated Spec %d \n", ffiStructReturnValue)); pushInt((int)ffiStructReturnValue); } return 1; } int ffiPushSignedChar(int value) { DPRINTF(("ffiPushSignedChar %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedChar(int value) { DPRINTF(("ffiPushUnsignedChar %d\n", value)); pushInt(value); return 1; } int ffiPushSignedByte(int value) { DPRINTF(("ffiPushSignedByte %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedByte(int value) { DPRINTF(("ffiPushUnsignedByte %d\n", value)); pushInt(value); return 1; } int ffiPushSignedShort(int value) { DPRINTF(("ffiPushSignedShort %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedShort(int value) { DPRINTF(("ffiPushUnsignedShort %d\n", value)); pushInt(value); return 1; } int ffiPushSignedInt(int value) { DPRINTF(("ffiPushSignedInt %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedInt(int value) { DPRINTF(("ffiPushUnsignedInt %d\n", value)); pushInt(value); return 1; } int ffiPushSignedLongLong(int low, int high) { DPRINTF(("ffiPushSignedLongLong %d %d\n", low, high)); pushInt(low); pushInt(high); return 1; } int ffiPushUnsignedLongLong(int low, int high) { DPRINTF(("ffiPushUnsignedLongLong %d %d\n", low, high)); pushInt(low); pushInt(high); return 1; } int ffiPushPointer(int pointer) { DPRINTF(("ffiPushPointer %d\n", pointer)); pushInt(pointer); return 1; } int ffiPushSingleFloat(double value) { float f= (float)value; DPRINTF(("ffiPushSingleFloat %f\n", value)); pushInt(*(int *)&f); return 1; } int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", value)); pushInt(((int *)&value)[0]); pushInt(((int *)&value)[1]); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; DPRINTF(("ffiPushStringOfLength %d\n", length)); checkStack(); ptr= (char *)malloc(length + 1); if (!ptr) return primitiveFail(); DPRINTF((" ++ alloc string\n")); memcpy(ptr, (void *)srcIndex, length); ptr[length]= '\0'; ffiTempStrings[ffiTempStringCount++]= ptr; pushInt((int)ptr); return 1; } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int lbs= *structSpec & FFIStructSizeMask; int size= (lbs + sizeof(int) - 1) / sizeof(int); DPRINTF(("ffiPushStructureOfLength %d (%db %dw)\n", specSize, lbs, size)); if (ffiStackIndex + size > FFI_MAX_STACK) return primitiveFail(); memcpy((void *)(ffiStack + ffiStackIndex), (void *)pointer, lbs); ffiStackIndex += size; return 1; } double ffiReturnFloatValue(void) { return ffiFloatReturnValue; } int ffiLongLongResultLow(void) { return ffiIntReturnValue; } int ffiLongLongResultHigh(void) { return ffiLongReturnValue; } int ffiStoreStructure(int address, int structSize) { DPRINTF(("ffiStoreStructure %d %d\n", address, structSize)); // JMM memcpy((void *)address, (ffiStructReturnValue // ? (void *)ffiStructReturnValue // : (void *)&ffiIntReturnValue), // structSize); if(structSize <= 4) { *(int*)address = ffiIntReturnValue; return 1; } if(structSize <= 8) { *(int*)address = ffiIntReturnValue; *(int*)(address+4) = ffiLongReturnValue; return 1; } /* assume pointer to hidden structure */ memcpy((void*)address, (void*) ffiStructReturnValue, structSize); return 1; } int ffiCleanup(void) { int i; DPRINTF(("ffiCleanup\n")); for (i= 0; i < ffiTempStringCount; ++i) { DPRINTF((" ++ free string\n")); free(ffiTempStrings[i]); } ffiTempStringCount= 0; if (ffiStructReturnValue) { DPRINTF((" ++ free struct\n")); free(ffiStructReturnValue); ffiStructReturnValue= 0; } return 1; } int ffiCallAddressOfWithPointerReturnx(int fn, int callType) { DPRINTF(("ffiCallAddressOfWithPointerReturnx fn %d callType %d \n", fn, callType)); return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } int ffiCallAddressOfWithStructReturnx(int fn, int callType, int* structSpec, int specSize) { DPRINTF(("ffiCallAddressOfWithStructReturnx fn %d callType %d structSpec %d specSize %d\n", fn, callType, structSpec, specSize)); return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } int ffiCallAddressOfWithReturnTypex(int fn, int callType, int typeSpec) { DPRINTF(("ffiCallAddressOfWithReturnTypex fn %d callType %d \n", fn, callType, typeSpec)); return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*5); foo[0] = 2; foo[1] = ffiCallAddressOfWithPointerReturnx; foo[2] = fn; foo[3] = callType; foo[4] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[4]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*7); foo[0] = 4; foo[1] = ffiCallAddressOfWithStructReturnx; foo[2] = fn; foo[3] = callType; foo[4] = structSpec; foo[5] = specSize; foo[6] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[6]; free(foo); return resultsOfCall; } } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { int resultsOfCall; if (giLocker == 0) giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker != 0) { long *foo; foo = malloc(sizeof(long)*6); foo[0] = 3; foo[1] = ffiCallAddressOfWithReturnTypex; foo[2] = fn; foo[3] = callType; foo[4] = typeSpec; foo[5] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = foo[5]; free(foo); return resultsOfCall; } } #if defined(FFI_TEST) void ffiDoAssertions(void) {} #endif #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakFFIPrims/x86-sysv-asm-MacIntel.S ================================================ #if __LITTLE_ENDIAN__ /* x86-sysv-asm.S -- 386 FFI trampoline for SVr4-like ABIs -*- asm -*- * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: Tue Jan 28 16:53:52 2003 by piumarta (Ian Piumarta) on xombul * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. */ #import .text .globl _ffiCallAddressOf _ffiCallAddressOf: /* 8=addr, 12=stack, 16=stackSize */ pushl %ebp movl %esp, %ebp movl 16(%ebp), %ecx testl %ecx, %ecx je 2f subl %ecx, %esp and $0xFFFFFFF0,%esp /*align to 128-bits*/ subl $4, %ecx movl 12(%ebp), %edx 1: movl (%edx,%ecx,1), %eax movl %eax, (%esp,%ecx,1) subl $4, %ecx jnc 1b jmp 3f 2: and $0xFFFFFFF0,%esp /*align to 128-bits*/ 3: cld call *8(%ebp) REG_TO_EXTERN (%eax, _intReturnValue) REG_TO_EXTERN (%edx, _intReturnValue2) PICIFY(_floatReturnValue) fstpl (%edx) NON_LAZY_STUB(_floatReturnValue) movl %ebp, %esp popl %ebp ret #endif ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakObjectiveCPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable ObjectiveCPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.ObjectiveCPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0.7 CFBundleSignature FAST CFBundleVersion 1.0.7 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakObjectiveCPlugin/squeakProxy.h ================================================ // // squeakProxy.h // SqueakObjectiveC // // Created by John M McIntosh on 01/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. /* MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import #import #import "sq.h" extern struct VirtualMachine* interpreterProxy; /* Protocol * foo1 = @protocol(CLLocationManagerDelegate); Protocol * foo2 = @protocol(NSCoding); Protocol * foo3 = @protocol(NSCopying); Protocol * foo4 = @protocol(NSDecimalNumberBehaviors); Protocol * foo5 = @protocol(NSFastEnumeration); Protocol * foo6 = @protocol(NSLocking); Protocol * foo7 = @protocol(NSMutableCopying); Protocol * foo8 = @protocol(NSObject); Protocol * foo9 = @protocol(NSURLAuthenticationChallengeSender); Protocol * foo10 = @protocol(NSURLProtocolClient); Protocol * foo11 = @protocol(UIAccelerometerDelegate); Protocol * foo12 = @protocol(UIAlertViewDelegate); Protocol * foo13 = @protocol(UIApplicationDelegate); Protocol * foo14 = @protocol(UIImagePickerControllerDelegate); Protocol * foo15 = @protocol(UINavigationBarDelegate); Protocol * foo16 = @protocol(UINavigationControllerDelegate); Protocol * foo17 = @protocol(UIPickerViewDataSource); Protocol * foo18 = @protocol(UIPickerViewDelegate); Protocol * foo19 = @protocol(UISearchBarDelegate); Protocol * foo20 = @protocol(UIScrollViewDelegate); Protocol * foo21 = @protocol(UITabBarControllerDelegate); Protocol * foo22 = @protocol(UITabBarDelegate); Protocol * foo23 = @protocol(UITableViewDataSource); Protocol * foo24 = @protocol(UITableViewDelegate); Protocol * foo25 = @protocol(UITextFieldDelegate); Protocol * foo26 = @protocol(UITextInputTraits); Protocol * foo27 = @protocol(UITextViewDelegate); Protocol * foo28 = @protocol(UIWebViewDelegate); */ @interface SqueakProxy : NSObject { sqInt sem; Protocol* protocol; NSInvocation* invocation; NSConditionLock* lock; NSMutableDictionary *sigs; id target; sqInt callbackid; BOOL isCarbonVM; } - (id) initWithSemaphore: (sqInt) squeakSem protocolNSString: (NSString *) nameString target: (id) aTarget; - (void) setReturnValue: (char*) pointer; - (BOOL) isDataTypeAware; - (void) setIsCarbonVM; @property (nonatomic,assign) sqInt sem; @property (nonatomic,assign) Protocol* protocol; @property (nonatomic,assign) NSInvocation* invocation; @property (nonatomic,assign) NSConditionLock* lock; @property (nonatomic,assign) NSMutableDictionary *sigs; @property (nonatomic,retain) id target; @property (nonatomic,assign) sqInt callbackid; @end ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakObjectiveCPlugin/squeakProxy.m ================================================ // // squeakProxy.m // SqueakObjectiveC // // Created by John M McIntosh on 01/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Some code from http://www.squeaksource.com/ObjectiveCBridge.html developers and contributors Creator: Alain Fischer Admin: Avi Bryant, Alain Fischer Developer: Todd Blanchard MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "squeakProxy.h" @implementation SqueakProxy @synthesize sem; @synthesize invocation; @synthesize lock; @synthesize sigs; @synthesize protocol; @synthesize target; @synthesize callbackid; - (id) initWithSemaphore: (sqInt) squeakSem protocolNSString: (NSString *) nameString target: aTarget { sem = squeakSem; if (nameString) protocol = objc_getProtocol([nameString UTF8String]); else protocol = nil; if (aTarget) { [self setTarget: aTarget]; } else { NSObject *dummy = [[NSObject alloc] init]; [self setTarget: dummy]; [dummy release]; } lock = [[NSConditionLock alloc] initWithCondition: 0]; sigs = [[NSMutableDictionary alloc] initWithCapacity: 10]; isCarbonVM = NO; callbackid = 0; return self; } - (void) forwardInvocation: (NSInvocation*) anInvocation { NSDate *timeout; // NSLog(@"forwardInvocation: %@", anInvocation); // NSLog(@"currentThread: %@", [NSThread currentThread]); SEL selector = [anInvocation selector]; NSString *selectorString = NSStringFromSelector(selector); if (![sigs objectForKey: selectorString]) { [anInvocation invokeWithTarget: target]; return; } if([lock lockWhenCondition: 0 beforeDate: (timeout = [[NSDate alloc] initWithTimeIntervalSinceNow: 3.0])]) { // NSLog(@"inside lock 0"); [lock unlockWithCondition: 1]; [timeout release]; invocation = [anInvocation retain]; // NSLog(@"signalling squeak"); interpreterProxy->signalSemaphoreWithIndex(sem); if (isCarbonVM) interpreterProxy->callbackEnter(&callbackid); if([lock lockWhenCondition: 2 beforeDate: (timeout = [[NSDate alloc] initWithTimeIntervalSinceNow: 4.0])]) { // NSLog(@"inside lock 2"); [timeout release]; [invocation release]; invocation = nil; [lock unlockWithCondition: 0]; } else { // NSLog(@"failed lock 2"); [timeout release]; [invocation release]; invocation = nil; [lock unlockWithCondition: 0]; } //NSLog(@"returning"); } else { [timeout release]; //NSLog(@"failed lock 0"); } } - (NSMethodSignature *) methodSignatureForSelector: (SEL) selector { NSMethodSignature* sig; NSString* sigAsString; sig = [target methodSignatureForSelector: selector]; if (sig) return sig; sig = [super methodSignatureForSelector: selector]; if(sig) return sig; NSString *selectorString = NSStringFromSelector (selector); if (sigAsString = [sigs objectForKey: selectorString]) { if (protocol) { struct objc_method_description methodDescription; methodDescription = protocol_getMethodDescription(protocol, selector, YES, YES); if(methodDescription.name == NULL) { methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES); } if(methodDescription.name != NULL) { NSMethodSignature *foo = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; return foo; } } NSMethodSignature *foo = [NSMethodSignature signatureWithObjCTypes: [sigAsString cStringUsingEncoding: NSASCIIStringEncoding]]; return foo; } return nil; } - (BOOL) respondsToSelector: (SEL) selector { if([super respondsToSelector: selector]) return true; if ([target respondsToSelector: selector]) return true; NSString *which = NSStringFromSelector(selector); if ([sigs objectForKey: which]) return true; return false; } - (void) setReturnValue: (char*) pointer { [invocation setReturnValue: &pointer]; } - (BOOL) isDataTypeAware { return YES; } - (void) setIsCarbonVM { isCarbonVM = YES; } - (void) dealloc { [lock release]; [sigs release]; [target release]; [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakObjectiveCPlugin/squeakSUnitTester.h ================================================ // // squeakSUnitTester.h // SqueakObjectiveC // // Created by John M McIntosh on 9/25/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // // #import @interface squeakSUnitTester : NSObject - (char) test0char; - (int) test0int; - (short) test0short; - (long) test0long; - (long long) test0longlong; - (unsigned char) test0unsignedchar; - (unsigned int) test0unsignedint; - (unsigned short) test0unsignedshort; - (unsigned long) test0unsignedlong; - (unsigned long long) test0unsignedlonglong; - (float) test0float; - (double) test0double; - (void) test0void; - (char *) test0charpointer; - (squeakSUnitTester *) test0object; - (Class) test0class; - (SEL) test0methodselector; - (CGRect) test0CGRect; - (char) test0char: (char *) ignore; - (int) test0int: (char *) ignore; - (short) test0short: (char *) ignore; - (long) test0long: (char *) ignore; - (long long) test0longlong: (char *) ignore; - (unsigned char) test0unsignedchar: (char *) ignore; - (unsigned int) test0unsignedint: (char *) ignore; - (unsigned short) test0unsignedshort: (char *) ignore; - (unsigned long) test0unsignedlong: (char *) ignore; - (unsigned long long) test0unsignedlonglong: (char *) ignore; - (float) test0float: (char *) ignore; - (double) test0double: (char *) ignore; - (void) test0void: (char *) ignore; - (char *) test0charpointer: (char *) ignore; - (squeakSUnitTester *) test0object: (char *) ignore; - (Class) test0class: (char *) ignore; - (SEL) test0methodselector: (char *) ignore; - (CGRect) test0CGRect: (char *) ignore; - (char) test0char: (char *) ignore two: (char *) ignore2; - (int) test0int: (char *) ignore two: (char *) ignore2; - (short) test0short: (char *) ignore two: (char *) ignore2; - (long) test0long: (char *) ignore two: (char *) ignore2; - (long long) test0longlong: (char *) ignore two: (char *) ignore2; - (unsigned char) test0unsignedchar: (char *) ignore two: (char *) ignore2; - (unsigned int) test0unsignedint: (char *) ignore two: (char *) ignore2; - (unsigned short) test0unsignedshort: (char *) ignore two: (char *) ignore2; - (unsigned long) test0unsignedlong: (char *) ignore two: (char *) ignore2; - (unsigned long long) test0unsignedlonglong: (char *) ignore two: (char *) ignore2; - (float) test0float: (char *) ignore two: (char *) ignore2; - (double) test0double: (char *) ignore two: (char *) ignore2; - (void) test0void: (char *) ignore two: (char *) ignore2; - (char *) test0charpointer: (char *) ignore two: (char *) ignore2; - (squeakSUnitTester *) test0object: (char *) ignore two: (char *) ignore2; - (Class) test0class: (char *) ignore two: (char *) ignore2; - (SEL) test0methodselector: (char *) ignore two: (char *) ignore2; - (CGRect) test0CGRect: (char *) ignore two: (char *) ignore2; - (char) test0char: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (int) test0int: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (short) test0short: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (long) test0long: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (long long) test0longlong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned char) test0unsignedchar: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned int) test0unsignedint: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned short) test0unsignedshort: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned long) test0unsignedlong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned long long) test0unsignedlonglong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (float) test0float: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (double) test0double: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (void) test0void: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (char *) test0charpointer: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (squeakSUnitTester *) test0object: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (Class) test0class: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (SEL) test0methodselector: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (CGRect) test0CGRect: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (char) test1char: (char) ignore; - (int) test1int: (int) ignore; - (short) test1short: (short) ignore; - (long) test1long: (long) ignore; - (long long) test1longlong: (long long) ignore; - (unsigned char) test1unsignedchar: (unsigned char) ignore; - (unsigned int) test1unsignedint: (unsigned int) ignore; - (unsigned short) test1unsignedshort: (unsigned short) ignore; - (unsigned long) test1unsignedlong: (unsigned long) ignore; - (unsigned long long) test1unsignedlonglong: (unsigned long long) ignore; - (float) test1float: (float) ignore; - (double) test1double: (double) ignore; - (char *) test1charpointer: (char *) ignore; - (squeakSUnitTester *) test1object: (squeakSUnitTester *) ignore; - (Class) test1class: (Class) ignore; - (SEL) test1methodselector: (SEL) ignore; - (CGRect) test1CGRect: (CGRect) ignore; - (char) test2char: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (int) test2int: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (short) test2short: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (long) test2long: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (long long) test2longlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned char) test2unsignedchar: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned int) test2unsignedint: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned short) test2unsignedshort: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned long) test2unsignedlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned long long) test2unsignedlonglong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (float) test2float: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (double) test2double: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (void) test2void: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (char *) test2charpointer: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (squeakSUnitTester *) test2object: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (Class) test2class: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (SEL) test2methodselector: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 ; - (CGRect) test2CGRect: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 ; - (oneway void) testQualifier0v; - (oneway void) testQualifier1v: (squeakSUnitTester *)ignore; - (oneway void) testQualifier2v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2; - (oneway void) testQualifier3v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2 three: (squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1io: (inout squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 three: (inout squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1i: (in squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 three: (in squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1o: (out squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 three: (out squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1r: (inout byref squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 three: (inout byref squeakSUnitTester *)ignore3; @end ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/SqueakObjectiveCPlugin/squeakSUnitTester.m ================================================ // // squeakSUnitTester.m // SqueakObjectiveC // // Created by John M McIntosh on 9/25/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "squeakSUnitTester.h" @implementation squeakSUnitTester - (char) test0char { return 'A'; } - (int) test0int { return -1; } - (short) test0short { return 0xFFFF; } - (long) test0long { return 0xFFFFFFFF; } - (long long) test0longlong { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar{ return 'A'; } - (unsigned int) test0unsignedint{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort { return 0xFFFF; } - (unsigned long) test0unsignedlong{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float { return 8.8; } - (double) test0double { return 8.8; } - (void) test0void { } - (char *) test0charpointer { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object { return [squeakSUnitTester new]; } - (Class) test0class { return [squeakSUnitTester class]; } - (SEL) test0methodselector { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore { return 'A'; } - (int) test0int: (char *)ignore { return -1; } - (short) test0short: (char *)ignore { return 0xFFFF; } - (long) test0long: (char *)ignore { return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore{ return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore { return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore { return 8.8; } - (double) test0double: (char *)ignore { return 8.8; } - (void) test0void: (char *)ignore { } - (char *) test0charpointer: (char *)ignore { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore two: (char *) ignore2 { return 'A'; } - (int) test0int: (char *)ignore two: (char *) ignore2 { return -1; } - (short) test0short: (char *)ignore two: (char *) ignore2{ return 0xFFFF; } - (long) test0long: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore two: (char *) ignore2{ return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore two: (char *) ignore2{ return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore two: (char *) ignore2{ return 8.8; } - (double) test0double: (char *)ignore two: (char *) ignore2{ return 8.8; } - (void) test0void: (char *)ignore two: (char *) ignore2{ } - (char *) test0charpointer: (char *)ignore two: (char *) ignore2{ static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore two: (char *) ignore2 { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore two: (char *) ignore2 { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore two: (char *) ignore2 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore two: (char *) ignore2 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 'A'; } - (int) test0int: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return -1; } - (short) test0short: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFF; } - (long) test0long: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 8.8; } - (double) test0double: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 8.8; } - (void) test0void: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { } - (char *) test0charpointer: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test1char: (char) ignore { return ignore; } - (int) test1int: (int) ignore { return ignore; } - (short) test1short: (short) ignore { return ignore; } - (long) test1long: (long) ignore { return ignore; } - (long long) test1longlong: (long long) ignore { return ignore; } - (unsigned char) test1unsignedchar: (unsigned char) ignore { return ignore; } - (unsigned int) test1unsignedint: (unsigned int) ignore { return ignore; } - (unsigned short) test1unsignedshort: (unsigned short) ignore { return ignore; } - (unsigned long) test1unsignedlong: (unsigned long) ignore { return ignore; } - (unsigned long long) test1unsignedlonglong: (unsigned long long) ignore { return ignore; } - (float) test1float: (float) ignore { return ignore; } - (double) test1double: (double) ignore { return ignore; } - (char *) test1charpointer: (char *) ignore { return ignore; } - (squeakSUnitTester *) test1object: (squeakSUnitTester *) ignore { return ignore; } - (Class) test1class: (Class) ignore { return ignore; } - (SEL) test1methodselector: (SEL) ignore { return ignore; } - (CGRect) test1CGRect: (CGRect) ignore { return ignore; } - (char) test2char: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return 'A'; } - (int) test2int: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return -1; } - (short) test2short: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFF; } - (long) test2long: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (long long) test2longlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test2unsignedchar: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 'A'; } - (unsigned int) test2unsignedint: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (unsigned short) test2unsignedshort: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFF; } - (unsigned long) test2unsignedlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (unsigned long long) test2unsignedlonglong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (float) test2float: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 8.8; } - (double) test2double: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 8.8; } - (void) test2void: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ } - (char *) test2charpointer: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test2object: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return [squeakSUnitTester new]; } - (Class) test2class: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return [squeakSUnitTester class]; } - (SEL) test2methodselector: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test2CGRect: (squeakSUnitTester *) ignore two: (squeakSUnitTester *) ignore2 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (oneway void) testQualifier0v { } - (oneway void) testQualifier1v: (squeakSUnitTester *)ignore { } - (oneway void) testQualifier2v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2;{ } - (oneway void) testQualifier3v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2 three: (squeakSUnitTester *)ignore3 { } - (squeakSUnitTester *) testQualifier1io: (inout squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 three: (inout squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1i: (in squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 three: (in squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1o: (out squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 three: (out squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1r: (inout byref squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 three: (inout byref squeakSUnitTester *)ignore3 { return ignore3; } @end ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/TestOSAPlugin/Info-TestOSAPlugin__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable TestOSAPlugin CFBundleGetInfoString TestOSAPlugin v1.0.2b1 for Squeak, see http://www.squeak.org CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.TestOSAPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName TestOSAPlugin for Squeak CFBundlePackageType BNDL CFBundleShortVersionString 1.0.2b1 CFBundleSignature FAST CFBundleVersion 1.0.2b1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/TestOSAPlugin/JMMFixOSAPluginForOSX.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 31 October 2005 at 3:33:15 pm'! !TestOSAPlugin methodsFor: 'OSA prims' stamp: 'JMM 10/31/2005 11:59'! primOSADoScript: source in: context mode: mode resultType: type to: result |component resultsOfCall giLocker | component := self primitive: 'primOSADoScript' parameters: #(AEDesc OSAID SmallInteger DescType AEDesc) receiver: #ComponentInstance. self cCode: ' giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker !!= 0) { long *foo; foo = malloc(sizeof(long)*9); foo[0] = 6; foo[1] = OSADoScript; foo[2] = *component; foo[3] = source; foo[4] = *context; foo[5] = *type; foo[6] = mode; foo[7] = result; foo[8] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = interpreterProxy->positive32BitIntegerFor(foo[8]); free(foo);}' inSmalltalk: [[component. giLocker]. resultsOfCall := -1]. ^resultsOfCall asOop: Unsigned! ! !TestOSAPlugin methodsFor: 'OSA prims' stamp: 'JMM 10/31/2005 11:59'! primOSAExecute: script in: context mode: mode to: result |component giLocker resultsOfCall | component := self primitive: 'primOSAExecute' parameters: #(OSAID OSAID SmallInteger OSAID) receiver: #ComponentInstance. self cCode: ' giLocker = interpreterProxy->ioLoadFunctionFrom("getUIToLock", ""); if (giLocker !!= 0) { long *foo; foo = malloc(sizeof(long)*8); foo[0] = 5; foo[1] = OSAExecute; foo[2] = *component; foo[3] = *script; foo[4] = *context; foo[5] = mode; foo[6] = result; foo[7] = 0; ((int (*) (void *)) giLocker)(foo); resultsOfCall = interpreterProxy->positive32BitIntegerFor(foo[7]); free(foo); } ' inSmalltalk: [[component. giLocker]. resultsOfCall _ -1]. ^resultsOfCall asOop: Unsigned! ! ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/TestOSAPlugin/TestOSAPlugin.proj.xml ================================================ ]> TestOSAPlugin UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameTestOSAPlugin OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000011391560100000000000010011391E70 00020000000000000000000011390FE000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixname MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources s0 MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath0 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileTestOSAPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name TestOSAPlugin.c MacOS Text Name AppleScriptLib MacOS Library Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name TestOSAPlugin.c MacOS Name AppleScriptLib MacOS TestOSAPlugin Source TestOSAPlugin Name TestOSAPlugin.c MacOS TestOSAPlugin Name MSL C.PPC.Lib MacOS TestOSAPlugin Name MSL RuntimePPC.Lib MacOS TestOSAPlugin Name InterfaceLib MacOS TestOSAPlugin Name MathLib MacOS TestOSAPlugin Name AppleScriptLib MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/UUIDPlugin/sqMacUUID.c ================================================ /**************************************************************************** * PROJECT: UUID support for the mac * FILE: sqMacUUID.c * CONTENT: * * AUTHOR: John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacUUID.c 1708 2007-06-10 00:40:04Z johnmci $ * * Feb 5 2002, JMM cleanup for windows port * */ #include "UUIDPlugin.h" #include "sq.h" extern struct VirtualMachine *interpreterProxy; #include int sqUUIDInit(void); int sqUUIDShutdown(void); int MakeUUID(sqUUID location) { CFUUIDRef theUUID; CFUUIDBytes theBytes; theUUID = CFUUIDCreate (null); theBytes = CFUUIDGetUUIDBytes(theUUID); memcpy((char *) location,(char *) &theBytes,sizeof(sqUUID)); CFRelease(theUUID); return 0; } int sqUUIDInit() { return 1; } int sqUUIDShutdown() { return 1; } ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/UnixOSProcessPlugin/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable UnixOSProcessPlugin CFBundleIconFile SqueakPlugin.icns CFBundleIdentifier org.squeak.UnixOSProcessPlugin CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 4.0.1 CFBundleSignature FAST CFBundleVersion 4.0.1 ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/UnixOSProcessPlugin/PkgInfo ================================================ BNDLFAST ================================================ FILE: vm/src/from_squeak/Mac OS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c ================================================ /* Automatically generated from Squeak on an Array(11 October 2006 2:48:02 pm) */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include /* D T Lewis 2005 - UnixOSProcessPlugin.c translated from class UnixOSProcessPluginInterpreterGetThisSession of OSProcessPlugin version 4.0.1 */ #include #include #include #include #include #include #include #include "config.h" #define FILEHANDLETYPE FILE * /* the type of low level stream to be used in a struct SQFile */ #ifndef SQAIO_H # define SQAIO_H "aio.h" /* aio.h has been renamed to sqaio.h */ #endif #include SQAIO_H #include "FilePlugin.h" #include "SocketPlugin.h" #define SESSIONIDENTIFIERTYPE int #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static void aioForwardwithDataandFlags(int fd, void * data, int flags); static void * callocWrappersize(sqInt count, sqInt objectSize); static sqInt copyBytesFromtolength(unsigned char * charArray1, unsigned char * charArray2, sqInt len); static sqInt createPipeForReaderwriter(FILEHANDLETYPE * readerIOStreamPtr, FILEHANDLETYPE * writerIOStreamPtr); static char * cStringFromString(sqInt aString); static sqInt descriptorTableSize(void); static void dupToStdErr(sqInt anSQFileDataStructure); static void dupToStdIn(sqInt anSQFileDataStructure); static void dupToStdOut(sqInt anSQFileDataStructure); static sqInt fileDescriptorFrom(sqInt aFileHandle); static sqInt fileRecordSize(void); static SQFile * fileValueOf(sqInt anSQFileRecord); static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count); static sqInt forkAndExecInDirectory(sqInt useSignalHandler); #pragma export on EXPORT(pid_t) forkSqueak(sqInt useSignalHandler); #pragma export off static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt getThisSessionIdentifier(void); static sqInt halt(void); static void * handleSignalFunctionAddress(void); static void handleSignal(int sigNum); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt isSQFileObject(sqInt objectPointer); static sqInt makePipeForReaderwriter(FILEHANDLETYPE * readerIOStreamPtr, FILEHANDLETYPE * writerIOStreamPtr); static sqInt msg(char * s); static sqInt newSQFileByteArray(void); static sqInt newSQSocketByteArray(void); static void ** originalSignalHandlers(void); static void * pointerFrom(sqInt aByteArray); #pragma export on EXPORT(sqInt) primitiveAioDisable(void); EXPORT(sqInt) primitiveAioEnable(void); EXPORT(sqInt) primitiveAioHandle(void); EXPORT(sqInt) primitiveAioSuspend(void); EXPORT(sqInt) primitiveArgumentAt(void); EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid); EXPORT(sqInt) primitiveChdir(void); EXPORT(sqInt) primitiveCreatePipe(void); EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveEnvironmentAt(void); EXPORT(sqInt) primitiveEnvironmentAtSymbol(void); EXPORT(sqInt) primitiveErrorMessageAt(void); EXPORT(sqInt) primitiveFileProtectionMask(void); EXPORT(sqInt) primitiveFileStat(void); EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void); EXPORT(sqInt) primitiveForkAndExecInDirectory(void); EXPORT(sqInt) primitiveForkExec(void); EXPORT(sqInt) primitiveForkSqueak(void); EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void); EXPORT(sqInt) primitiveForwardSignalToSemaphore(void); EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void); EXPORT(sqInt) primitiveGetEGid(void); EXPORT(sqInt) primitiveGetEUid(void); EXPORT(sqInt) primitiveGetGid(void); EXPORT(sqInt) primitiveGetPid(void); EXPORT(sqInt) primitiveGetPPid(void); EXPORT(sqInt) primitiveGetSession(void); EXPORT(sqInt) primitiveGetStdErrHandle(void); EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdInHandle(void); EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdOutHandle(void); EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetUid(void); EXPORT(sqInt) primitiveIsAtEndOfFile(void); EXPORT(sqInt) primitiveLockFileRegion(void); EXPORT(sqInt) primitiveMakePipe(void); EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveModuleName(void); EXPORT(sqInt) primitiveNice(void); EXPORT(sqInt) primitivePutEnv(void); EXPORT(sqInt) primitiveRealpath(void); EXPORT(sqInt) primitiveReapChildProcess(void); EXPORT(sqInt) primitiveSemaIndexFor(void); EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSetSemaIndex(void); EXPORT(sqInt) primitiveSigChldNumber(void); EXPORT(sqInt) primitiveSigHupNumber(void); EXPORT(sqInt) primitiveSigIntNumber(void); EXPORT(sqInt) primitiveSigKillNumber(void); EXPORT(sqInt) primitiveSigPipeNumber(void); EXPORT(sqInt) primitiveSigQuitNumber(void); EXPORT(sqInt) primitiveSigTermNumber(void); EXPORT(sqInt) primitiveSigUsr1Number(void); EXPORT(sqInt) primitiveSigUsr2Number(void); EXPORT(sqInt) primitiveSizeOfInt(void); EXPORT(sqInt) primitiveSizeOfPointer(void); EXPORT(sqInt) primitiveSQFileFlush(void); EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetBlocking(void); EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetNonBlocking(void); EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetUnbuffered(void); EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void); EXPORT(sqInt) primitiveTestLockableFileRegion(void); EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber); EXPORT(sqInt) primitiveUnixFileNumber(void); EXPORT(sqInt) primitiveUnlockFileRegion(void); EXPORT(sqInt) primitiveUnsetEnv(void); EXPORT(sqInt) primitiveVersionString(void); #pragma export off static void reapChildProcess(int sigNum); static void restoreDefaultSignalHandlers(void); static sqInt sandboxSecurity(void); static sqInt securityHeurisitic(void); static unsigned char * semaphoreIndices(void); static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static void setSigChldDefaultHandler(void); static void setSigChldHandler(void); static void setSigIntDefaultHandler(void); static void setSigIntIgnore(void); static void * setSignalNumberhandler(sqInt anInteger, void * signalHandlerAddress); static void setSigPipeDefaultHandler(void); static sqInt setSigPipeHandler(void); static void setSigPipeIgnore(void); #pragma export on EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sigChldNumber(void); static void * sigDefaultNumber(void); static void * sigErrorNumber(void); static sqInt sigHupNumber(void); static void * sigIgnoreNumber(void); static sqInt sigIntNumber(void); static sqInt sigKillNumber(void); static sqInt signalArraySize(void); static void ** signalHandlers(void); static sqInt sigPipeNumber(void); static sqInt sigQuitNumber(void); static sqInt sigTermNumber(void); static sqInt sigUsr1Number(void); static sqInt sigUsr2Number(void); static sqInt sizeOfInt(void); static sqInt sizeOfPointer(void); static sqInt sizeOfSession(void); static sqInt socketRecordSize(void); static SQSocket * socketValueOf(sqInt anSQSocketRecord); static sqInt stringFromCString(char *aCString); static char * transientCStringFromString(sqInt aString); static char * versionString(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "UnixOSProcessPlugin 11 October 2006 (i)" #else "UnixOSProcessPlugin 11 October 2006 (e)" #endif ; static void *originalSigHandlers[NSIG]; static int osprocessSandboxSecurity; static unsigned char semaIndices[NSIG]; static sqInt sigChldSemaIndex; static void *sigHandlers[NSIG]; static sqInt vmThread; /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* This function is called to signal a Smalltalk Semaphore when an asynchronous event is detected. When translated to C, the name of this method is aioForwardwithDataandFlags. The event handler is set up by #primitiveAioHandle. */ static void aioForwardwithDataandFlags(int fd, void * data, int flags) { sqInt *pfd; sqInt semaIndex; pfd = data; semaIndex = *pfd; interpreterProxy->signalSemaphoreWithIndex(semaIndex); } /* Using malloc() and calloc() is something I would like to avoid, since it is likely to cause problems some time in the future if somebody redesigns object memory allocation. This wrapper just makes it easy to find senders of calloc() in my code. -dtl */ static void * callocWrappersize(sqInt count, sqInt objectSize) { return calloc(count, objectSize); } /* | chars | chars _ 'abcd'. self new copyBytesFrom: 'wxyz' to: chars length: 4. chars */ static sqInt copyBytesFromtolength(unsigned char * charArray1, unsigned char * charArray2, sqInt len) { unsigned char *p1; sqInt idx; unsigned char *p2; p1 = charArray1; p2 = charArray2; idx = 0; while (idx < len) { *p2 = *p1; p1 += 1; p2 += 1; idx += 1; } } /* Create a pipe and populate the readerIOStream and writerIOStream variables. The SIGPIPE handler must have been set before creating the pipe. Answer true for success, else false. */ static sqInt createPipeForReaderwriter(FILEHANDLETYPE * readerIOStreamPtr, FILEHANDLETYPE * writerIOStreamPtr) { int filedes[2]; if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } /* Answer a new null-terminated C string copied from aString. The C string is allocated from the C runtime heap. See transientCStringFromString for a version which allocates from object memory. Caution: This may invoke the garbage collector. */ static char * cStringFromString(sqInt aString) { sqInt len; char *cString; char *sPtr; sPtr = interpreterProxy->arrayValueOf(aString); len = interpreterProxy->sizeOfSTArrayFromCPrimitive(sPtr); /* Space for a null terminated C string. */ cString = callocWrappersize(len + 1, 1); (char *) strncpy (cString, sPtr, len); return cString; } /* Answer the size of the file descriptor table for a process. I am not sure of the most portable way to do this. If this implementation does not work on your Unix platform, try changing it to answer the value of FOPEN_MAX, which will hopefully be defined in stdio.h. If all else fails, just hard code it to answer 20, which would be safe for any Unix. */ static sqInt descriptorTableSize(void) { return getdtablesize(); } /* Dup a file descriptor to allow it to be attached as the standard error when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdErr(sqInt anSQFileDataStructure) { sqInt filenoToDup; filenoToDup = fileDescriptorFrom(anSQFileDataStructure); if (!(filenoToDup < 0)) { if (!(filenoToDup == 2)) { fflush(stderr); dup2(filenoToDup, 2); } } } /* Dup a file descriptor to allow it to be attached as the standard input when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdIn(sqInt anSQFileDataStructure) { sqInt filenoToDup; filenoToDup = fileDescriptorFrom(anSQFileDataStructure); if (!(filenoToDup < 0)) { if (!(filenoToDup == 0)) { fflush(stdin); dup2(filenoToDup, 0); rewind(stdin); } } } /* Dup a file descriptor to allow it to be attached as the standard output when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdOut(sqInt anSQFileDataStructure) { sqInt filenoToDup; filenoToDup = fileDescriptorFrom(anSQFileDataStructure); if (!(filenoToDup < 0)) { if (!(filenoToDup == 1)) { fflush(stdout); dup2(filenoToDup, 1); } } } /* Answer the OS file descriptor, an integer value, from a SQFile data structure, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). This method may be called from a primitive, and is not intended to be called from Smalltalk. */ static sqInt fileDescriptorFrom(sqInt aFileHandle) { SQFile * sqFile; FILE *osFileStream; /* begin fileValueOf: */ if ((interpreterProxy->isBytes(aFileHandle)) && ((interpreterProxy->byteSizeOf(aFileHandle)) == (fileRecordSize()))) { sqFile = interpreterProxy->arrayValueOf(aFileHandle); goto l1; } else { interpreterProxy->primitiveFail(); sqFile = null; goto l1; } l1: /* end fileValueOf: */; if (sqFile == 0) { return -1; } else { osFileStream = sqFile->file; if (osFileStream == 0) { return -1; } return fileno(osFileStream); } } /* Answer the size of a SQFile data structure in bytes. */ static sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the SQFile data structure file record within anSQFileRecord, which is expected to be a ByteArray of size self>>fileRecordSize. */ static SQFile * fileValueOf(sqInt anSQFileRecord) { if ((interpreterProxy->isBytes(anSQFileRecord)) && ((interpreterProxy->byteSizeOf(anSQFileRecord)) == (fileRecordSize()))) { return interpreterProxy->arrayValueOf(anSQFileRecord); } else { interpreterProxy->primitiveFail(); return null; } } /* Use the address offsets in offsetArray to fix up the pointers in cStringArray. The result is a C array of pointers to char, used for argv and env vectors. */ static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count) { char **ptr; sqInt idx; ptr = ((char **) flattenedArrayOfStrings); idx = 0; while (idx < count) { ptr[idx] = (flattenedArrayOfStrings + (((offsetArray[idx]) >> 1))); idx += 1; } } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. If useSignalHandler is true, set the signal handler for SIGCHLD. Otherwise, assume that death of child events are handled through some other mechanism. In this implementation, memory for the argument and environment arrays is allocated in the image prior to calling this primitive. This allows us to avoid invoking the garbage collector in this primitive (thereby moving the locations of environment and argument memory), but comes at the cost of twiddling C pointers here in the primitive. An alternative to this whole mess is just to malloc the environment and argument vectors, but I think it is a good idea to avoid malloc as much as possible so as not to limit future ObjectMemory implementations. This primitive replaces #primitiveForkAndExec from earlier versions of the plugin. The new name permits backward compatibility for an image running on a VM which does not yet have the updated plugin. This implementation uses a different argument format on the stack, and differs functionally in that the child now closes all file descriptors (including sockets) not required (that is, everything except stdin, stdout, and stderr on descriptors 0, 1 and 2). This eliminates some flakey behavior in child processes connected to Squeak by pipes, which failed to exit at expected times due to the old file descriptors remaining open. This is also cleaner in that garbage descriptors are not left hanging around the the child. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ static sqInt forkAndExecInDirectory(sqInt useSignalHandler) { extern char **envVec; char *pwdPtr; pid_t pid; sqInt argVecBuffer; sqInt *envOffsetPtr; struct itimerval saveIntervalTimer; sqInt envCount; sqInt idx; struct itimerval intervalTimer; sqInt stdOut; char *progNamePtr; char **args; sqInt envOffsets; sqInt envVecBuffer; sqInt stdErr; sqInt workingDir; sqInt pwd; char *envPtr; char *argsPtr; sqInt *argOffsetPtr; sqInt handleCount; sqInt argCount; char **env; sqInt argOffsets; sqInt stdIn; sqInt executableFile; sqInt sigNum; if (useSignalHandler) { setSigChldHandler(); } if ((sandboxSecurity()) == 1) { interpreterProxy->pop(10); interpreterProxy->pushInteger(-1); } else { intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if ((pid = vfork()) == 0) { workingDir = interpreterProxy->stackObjectValue(0); envOffsets = interpreterProxy->stackObjectValue(1); envVecBuffer = interpreterProxy->stackObjectValue(2); argOffsets = interpreterProxy->stackObjectValue(3); argVecBuffer = interpreterProxy->stackObjectValue(4); stdErr = interpreterProxy->stackObjectValue(5); stdOut = interpreterProxy->stackObjectValue(6); stdIn = interpreterProxy->stackObjectValue(7); /* If a new working directory has been specified, try to chdir() to it. */ executableFile = interpreterProxy->stackObjectValue(8); if (workingDir != (interpreterProxy->nilObject())) { pwdPtr = interpreterProxy->firstIndexableField(workingDir); if (pwdPtr == 0) { fprintf(stderr, "bad workingDir parameter\n"); _exit(-1); } else { pwd = chdir(pwdPtr); if (pwd != 0) { perror("chdir"); _exit(-1); } } } /* Dup the file handles to attach the new child process to the right streams on descriptors 0, 1 and 2. */ progNamePtr = interpreterProxy->arrayValueOf(executableFile); if (!(stdErr == (interpreterProxy->nilObject()))) { dupToStdErr(stdErr); } if (!(stdOut == (interpreterProxy->nilObject()))) { dupToStdOut(stdOut); } if (!(stdIn == (interpreterProxy->nilObject()))) { dupToStdIn(stdIn); } /* First Unix file descriptor after stdin, stdout, stderr. */ idx = 3; handleCount = descriptorTableSize(); while (idx < handleCount) { close(idx); idx += 1; } if (envVecBuffer == (interpreterProxy->nilObject())) { env = envVec; } else { envCount = interpreterProxy->stSizeOf(envOffsets); envPtr = interpreterProxy->arrayValueOf(envVecBuffer); envOffsetPtr = interpreterProxy->firstIndexableField(envOffsets); fixPointersInArrayOfStringswithOffsetscount(envPtr, envOffsetPtr, envCount); env = ((char **) envPtr); } argCount = interpreterProxy->stSizeOf(argOffsets); argsPtr = interpreterProxy->arrayValueOf(argVecBuffer); argOffsetPtr = interpreterProxy->firstIndexableField(argOffsets); fixPointersInArrayOfStringswithOffsetscount(argsPtr, argOffsetPtr, argCount); /* Clean things up before clobbering the running image. */ /* Note: If any file descriptors, signal handlers, or other references to external resources need to be cleaned up, do it here. */ args = ((char **) argsPtr); /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } if ((execve(progNamePtr, args, env)) == -1) { perror(progNamePtr); _exit(-1); } else { /* Can't get here from there */; } } else { setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); interpreterProxy->pop(10); interpreterProxy->pushInteger(pid); } } } /* Fork a child process, and continue running squeak in the child process. If displayFlag is true, open a new X display for the child, otherwise the child is a headless Squeak. Answer the result of the fork() call, either the child pid or zero. After calling fork(), two OS processes exist, one of which is the child of the other. On systems which implement copy-on-write memory management, and which support the fork() system call, both processes will be running Smalltalk images, and will be sharing the same memory space. In the original OS process, the resulting value of pid is the process id of the child process (a non-zero integer). In the child process, the value of pid is zero. The child recreates sufficient external resources to continue running. This is done by attaching to a new X session. The child is otherwise a copy of the parent process, and will continue executing the Smalltalk image at the same point as its parent. The return value of this primitive may be used by the two running Smalltalk images to determine which is the parent and which is the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. The new child image does not start itself from the image in the file system; rather it is a clone of the parent image as it existed at the time of primitiveForkSqueak. For this reason, the parent and child should agree in advance as to whom is allowed to save the image to the file system, otherwise one Smalltalk may overwrite the image of the other. This is a simple call to fork(), rather than the more common idiom of vfork() followed by exec(). The vfork() call cannot be used here because it is designed to be followed by an exec(), and its semantics require the parent process to wait for the child to exit. See the BSD programmers documentation for details. */ EXPORT(pid_t) forkSqueak(sqInt useSignalHandler) { pid_t pid; struct itimerval saveIntervalTimer; struct itimerval intervalTimer; intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if (useSignalHandler) { setSigChldHandler(); } /* Enable the timer again before resuming Smalltalk. */ pid = fork(); setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); return pid; } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero, the handler is unregistered, and the VM returns to its default behavior for handling that signal. A handler must be unregistered before it can be registered again. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex) { void * oldHandler; if (semaphoreIndex == 0) { if ((semaIndices[sigNum]) > 0) { oldHandler = originalSigHandlers[sigNum]; setSignalNumberhandler(sigNum, oldHandler); semaIndices[sigNum] = 0; return oldHandler; } else { return sigErrorNumber(); } } if ((semaIndices[sigNum]) > 0) { return sigErrorNumber(); } oldHandler = setSignalNumberhandler(sigNum, handleSignalFunctionAddress()); if (oldHandler != (sigErrorNumber())) { originalSigHandlers[sigNum] = oldHandler; semaIndices[sigNum] = semaphoreIndex; } return oldHandler; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt getThisSessionIdentifier(void) { return interpreterProxy->getThisSessionID(); } static sqInt halt(void) { ; } static void * handleSignalFunctionAddress(void) { return handleSignal; } /* This is a signal handler function which runs when a signal is received from the operating system. When the signal is received, a Smalltalk Semaphore is signaled. This effectively passes the external signal to Squeak to allow it to be handled in Smalltalk. Note the this handler runs the VM in the context of a Unix signal handler in order to signal the Smalltalk Semaphore. In a single threaded Squeak VM, this works fine, however it may not work as expected if pthreads are used for the VM or for any plugins linked internally with the VM. On GCC systems, compiling with -D_REENTRANT seems to produce the intended behavior. */ static void handleSignal(int sigNum) { sqInt semaIndex; semaIndex = semaIndices[sigNum]; forwardSignaltoSemaphoreAt(sigNum, semaIndex); if (semaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(semaIndex); } } EXPORT(sqInt) initialiseModule(void) { osprocessSandboxSecurity = -1; return 1; } /* Answer true if objectPointer appears to be a valid SQFile ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid file reference. */ static sqInt isSQFileObject(sqInt objectPointer) { unsigned char *sqFileBytes; sqInt idx; if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { return 0; } sqFileBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (fileRecordSize())) { if ((sqFileBytes[idx]) != 0) { return 1; } idx += 1; } return 0; } /* Create a pipe and populate the readerIOStream and writerIOStream variables. Make sure the SIGPIPE handler is set before creating the pipe. Answer true for success, else false */ static sqInt makePipeForReaderwriter(FILEHANDLETYPE * readerIOStreamPtr, FILEHANDLETYPE * writerIOStreamPtr) { int filedes[2]; /* begin setSigPipeHandler */ /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } static sqInt msg(char * s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Answer a new ByteArray sized to contain a SQFile data structure. */ static sqInt newSQFileByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); } /* Answer a new ByteArray sized to contain a SQSocket data structure. */ static sqInt newSQSocketByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); } /* An array of signal handler function addresses, one for each signal type. The value at each entry is the address of the original signal handler function prior to having set a handler. */ static void ** originalSignalHandlers(void) { return originalSigHandlers; } /* Answer the pointer represented by aByteArray. */ static void * pointerFrom(sqInt aByteArray) { unsigned char *ptr; sqInt idx; union {void *address; unsigned char bytes[sizeof(void *)];} pointerUnion; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfPointer())))) { return null; } ptr = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfPointer())) { pointerUnion.bytes[idx] = ptr[idx]; idx += 1; } return pointerUnion.address; } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Definitively disable asynchronous event notification for a descriptor. The parameter is a sqFile ByteArray representing the ioHandle for a file. */ EXPORT(sqInt) primitiveAioDisable(void) { sqInt sqFile; int fd; sqFile = interpreterProxy->stackObjectValue(0); fd = fileDescriptorFrom(sqFile); if (fd < 0) { return interpreterProxy->primitiveFail(); } aioDisable(fd); interpreterProxy->pop(2); interpreterProxy->pushInteger(fd); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Enable asynchronous notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, the second parameter is the index of a Semaphore to be notified, and the third parameter is a flag indicating that sqFile represents an external object and should not be closed on termination of aio handling. Answer the semaphore index. */ EXPORT(sqInt) primitiveAioEnable(void) { sqInt sqFile; sqInt semaIndex; sqInt externalObject; int fd; int flags; static int eventSemaphoreIndices[FD_SETSIZE]; sqFile = interpreterProxy->stackObjectValue(2); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } fd = fileDescriptorFrom(sqFile); if (fd < 0) { return interpreterProxy->primitiveFail(); } semaIndex = interpreterProxy->stackIntegerValue(1); eventSemaphoreIndices[semaIndex] = semaIndex; externalObject = interpreterProxy->stackObjectValue(0); if (externalObject == (interpreterProxy->trueObject())) { flags = AIO_EXT; } else { flags = 0; } aioEnable(fd, &(eventSemaphoreIndices[semaIndex]), flags); interpreterProxy->pop(4); interpreterProxy->pushInteger(semaIndex); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Handle asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioHandle(void) { sqInt readWatch; sqInt exceptionWatch; sqInt sqFile; int fd; int flags; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } fd = fileDescriptorFrom(sqFile); if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioHandle(fd, aioForwardwithDataandFlags, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Temporarily suspend asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioSuspend(void) { sqInt readWatch; sqInt exceptionWatch; sqInt sqFile; int fd; int flags; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } fd = fileDescriptorFrom(sqFile); if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioSuspend(fd, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Answer a string containing the OS process argument at index (an Integer) in the argument list. */ EXPORT(sqInt) primitiveArgumentAt(void) { extern char **argVec; sqInt s; sqInt index; char *sPtr; extern int argCnt; index = interpreterProxy->stackIntegerValue(0); if ((index > argCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = argVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Send a null signal to the OS process identified by anIntegerPid. Answer false for a bad parameter on the stack (the common case is for anIntegerPid equal to nil, for which case we should answer false). Answer true if the process exists and can receive signals from this process, otherwise false. This test is useful for determining if a child process still exists following a Squeak image restart. */ EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid) { pid_t pidToSignal; int result; if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, 0); interpreterProxy->pop(2); if (result == 0) { interpreterProxy->push(interpreterProxy->trueObject()); } else { interpreterProxy->push(interpreterProxy->falseObject()); } } else { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->falseObject()); } } /* Call chdir(2) to change current working directory to the specified path string. Answer nil for success, or errno on failure. */ EXPORT(sqInt) primitiveChdir(void) { extern int errno; char *path; path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); if ((chdir(path)) == 0) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipe(void) { SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; SQFile * writerPtr; FILEHANDLETYPE *writerIOStreamPtr; SQFile * readerPtr; sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(writer)) && ((interpreterProxy->byteSizeOf(writer)) == (fileRecordSize()))) { writerPtr = interpreterProxy->arrayValueOf(writer); goto l1; } else { interpreterProxy->primitiveFail(); writerPtr = null; goto l1; } l1: /* end fileValueOf: */; writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(reader)) && ((interpreterProxy->byteSizeOf(reader)) == (fileRecordSize()))) { readerPtr = interpreterProxy->arrayValueOf(reader); goto l2; } else { interpreterProxy->primitiveFail(); readerPtr = null; goto l2; } l2: /* end fileValueOf: */; readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; SQFile * writerPtr; FILEHANDLETYPE *writerIOStreamPtr; SQFile * readerPtr; sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(writer)) && ((interpreterProxy->byteSizeOf(writer)) == (fileRecordSize()))) { writerPtr = interpreterProxy->arrayValueOf(writer); goto l1; } else { interpreterProxy->primitiveFail(); writerPtr = null; goto l1; } l1: /* end fileValueOf: */; writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(reader)) && ((interpreterProxy->byteSizeOf(reader)) == (fileRecordSize()))) { readerPtr = interpreterProxy->arrayValueOf(reader); goto l2; } else { interpreterProxy->primitiveFail(); readerPtr = null; goto l2; } l2: /* end fileValueOf: */; readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Answer a string containing the OS process environment string at index (an Integer) in the environment list. */ EXPORT(sqInt) primitiveEnvironmentAt(void) { extern char **envVec; char **p; sqInt envCnt; sqInt s; sqInt index; char *sPtr; p = envVec; envCnt = 0; while (*p++) envCnt++; index = interpreterProxy->stackIntegerValue(0); if ((index > envCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = envVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Answer the value of an environment variable keyed by a Symbol. */ EXPORT(sqInt) primitiveEnvironmentAtSymbol(void) { char * getenvResult; char *keyCStringPtr; sqInt s; keyCStringPtr = transientCStringFromString(interpreterProxy->stackObjectValue(0)); getenvResult = getenv(keyCStringPtr); if (getenvResult == 0) { return interpreterProxy->primitiveFail(); } else { s = stringFromCString(getenvResult); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Answer a string describing an error message */ EXPORT(sqInt) primitiveErrorMessageAt(void) { char *p; sqInt errMessage; sqInt index; index = interpreterProxy->stackIntegerValue(0); p = ((char *) (strerror(index))); errMessage = stringFromCString(p); interpreterProxy->pop(2); interpreterProxy->push(errMessage); } /* Call stat(2) to obtain the file protection mask for a file. Answer an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileProtectionMask(void) { extern int errno; char *path; struct stat *statBuf; sqInt mode; sqInt result; sqInt buffer; buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); interpreterProxy->stObjectatput(result, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(result, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Call stat(2) to obtain the file protection mask for a file. Answer errno on failure, or on success answer an array with: UID with: GID with: protectionMask. The protectionMask is an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileStat(void) { sqInt uid; sqInt gid; extern int errno; char *path; struct stat *statBuf; sqInt mode; sqInt result; sqInt mask; sqInt buffer; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); uid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(uid_t)); gid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(gid_t)); mask = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; interpreterProxy->stObjectatput(mask, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(mask, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(mask, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(mask, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, mask); interpreterProxy->stObjectatput(result, 2, (((statBuf->st_gid) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, (((statBuf->st_uid) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* This primitive exists only for purposes of testing the fixPointersInArrayOfStrings:withOffsets:count: method. I believe it to be reasonably machine and compiler independent, but have no way of verifying this on a variety of machines, so I'll leave this test method here in case someone runs into problems on other hardware or compilers. -dtl */ EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void) { sqInt cStringArray; sqInt offsetArray; sqInt count; char *flattenedArrayOfStrings; sqInt *offsets; count = interpreterProxy->stackIntegerValue(0); offsetArray = interpreterProxy->stackObjectValue(1); cStringArray = interpreterProxy->stackObjectValue(2); offsets = interpreterProxy->firstIndexableField(offsetArray); flattenedArrayOfStrings = interpreterProxy->arrayValueOf(cStringArray); fixPointersInArrayOfStringswithOffsetscount(flattenedArrayOfStrings, offsets, count); interpreterProxy->pop(4); interpreterProxy->push(cStringArray); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkAndExecInDirectory(void) { return forkAndExecInDirectory(1); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkExec(void) { return forkAndExecInDirectory(0); } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueak(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(1); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(0); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero or nil, the handler is unregistered, and the VM returns to its default behavior for handling that signal. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ EXPORT(sqInt) primitiveForwardSignalToSemaphore(void) { sqInt sigNum; void *handler; sqInt semaphoreIndex; char *hPtr; sqInt idx; sqInt index; union {void *handler; unsigned char bytes[sizeof(void *)];} priorHandler; sqInt priorHandlerObject; index = interpreterProxy->stackValue(0); if (index == (interpreterProxy->nilObject())) { semaphoreIndex = 0; } else { if ((index & 1)) { semaphoreIndex = interpreterProxy->stackIntegerValue(0); } else { return interpreterProxy->primitiveFail(); } } sigNum = interpreterProxy->stackIntegerValue(1); handler = forwardSignaltoSemaphoreAt(sigNum, semaphoreIndex); if (handler == (sigErrorNumber())) { return interpreterProxy->primitiveFail(); } priorHandlerObject = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeOfPointer()); hPtr = interpreterProxy->arrayValueOf(priorHandlerObject); priorHandler.handler = handler; idx = 0; while (idx < (sizeOfPointer())) { hPtr[idx] = priorHandler.bytes[idx]; idx += 1; } interpreterProxy->popthenPush(3, priorHandlerObject); } /* Answer a string containing the current working directory. */ EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void) { sqInt maxSize; sqInt cwdString; sqInt incrementBy; char *cwd; sqInt bufferSize; char *buffer; bufferSize = 100; incrementBy = 100; maxSize = 5000; while (1) { cwdString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); buffer = interpreterProxy->arrayValueOf(cwdString); cwd = getcwd(buffer, bufferSize); if (!((cwd == 0) && (bufferSize < maxSize))) break; bufferSize += incrementBy; } if (cwd == 0) { return interpreterProxy->primitiveFail(); } else { cwdString = stringFromCString(cwd); interpreterProxy->pop(1); interpreterProxy->push(cwdString); } } /* Answer the effective group ID of my OS process */ EXPORT(sqInt) primitiveGetEGid(void) { gid_t eGid; eGid = getegid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eGid); } /* Answer the effective user ID of my OS process */ EXPORT(sqInt) primitiveGetEUid(void) { uid_t eUid; eUid = geteuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eUid); } /* Answer the group ID of my OS process */ EXPORT(sqInt) primitiveGetGid(void) { gid_t gid; gid = getgid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(gid); } /* Answer the process ID of my OS process */ EXPORT(sqInt) primitiveGetPid(void) { pid_t pid; pid = getpid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } /* Answer the process ID of the parent process of my OS process */ EXPORT(sqInt) primitiveGetPPid(void) { pid_t ppid; ppid = getppid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(ppid); } /* Answer the unique session identifier for this Smalltalk instance running in this OS process. The C integer value is coerced into a Smalltalk ByteArray to preserve the full range of possible values. */ EXPORT(sqInt) primitiveGetSession(void) { sqInt sessionOop; SESSIONIDENTIFIERTYPE thisSessionID; unsigned char *sessionByteArrayPointer; sessionOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeOfInt()); sessionByteArrayPointer = interpreterProxy->arrayValueOf(sessionOop); thisSessionID = interpreterProxy->getThisSessionID(); if (thisSessionID == null) { return interpreterProxy->primitiveFail(); } copyBytesFromtolength((unsigned char *)&thisSessionID, sessionByteArrayPointer, sizeOfInt()); interpreterProxy->pop(1); interpreterProxy->push(sessionOop); } /* Answer the file handle for standard error of my OS process */ EXPORT(sqInt) primitiveGetStdErrHandle(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = interpreterProxy->getThisSessionID(); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard error of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process */ EXPORT(sqInt) primitiveGetStdInHandle(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = interpreterProxy->getThisSessionID(); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process */ EXPORT(sqInt) primitiveGetStdOutHandle(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = interpreterProxy->getThisSessionID(); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile * file; sqInt fileOop; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize()))) { file = interpreterProxy->arrayValueOf(fileOop); goto l1; } else { interpreterProxy->primitiveFail(); file = null; goto l1; } l1: /* end fileValueOf: */; thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the user ID of my OS process */ EXPORT(sqInt) primitiveGetUid(void) { uid_t uid; uid = getuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(uid); } /* Take a struct SQFile from the stack, and call feof(3) to determine if the file has reached end of file. */ EXPORT(sqInt) primitiveIsAtEndOfFile(void) { SQFile *sqFile; sqInt result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); if ((feof(sqFile->file)) == 0) { result = interpreterProxy->falseObject(); } else { result = interpreterProxy->trueObject(); } interpreterProxy->pop(2); interpreterProxy->push(result); } /* Take a struct SQFile from the stack, and request a lock on the specified region. If the exclusive flag is true, then request an exclusive (F_WRLCK) lock on the file. Otherwise, request a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). Answer the result of the call to fcntl(). If length is zero, then the entire file will be locked, including region extents that have not yet been allocated for the file. */ EXPORT(sqInt) primitiveLockFileRegion(void) { sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqInt exclusive; sqInt start; SQFile *sqFile; int result; sqInt len; int fileNo; struct flock lockStruct; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } /* Set up the flock structure parameter for fcntl() */ fileNo = fileno(sqFile->file); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipe(void) { SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; SQFile * writerPtr; FILEHANDLETYPE *writerIOStreamPtr; SQFile * readerPtr; sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(writer)) && ((interpreterProxy->byteSizeOf(writer)) == (fileRecordSize()))) { writerPtr = interpreterProxy->arrayValueOf(writer); goto l1; } else { interpreterProxy->primitiveFail(); writerPtr = null; goto l1; } l1: /* end fileValueOf: */; writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(reader)) && ((interpreterProxy->byteSizeOf(reader)) == (fileRecordSize()))) { readerPtr = interpreterProxy->arrayValueOf(reader); goto l2; } else { interpreterProxy->primitiveFail(); readerPtr = null; goto l2; } l2: /* end fileValueOf: */; readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; SQFile * writerPtr; FILEHANDLETYPE *writerIOStreamPtr; SQFile * readerPtr; sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(writer)) && ((interpreterProxy->byteSizeOf(writer)) == (fileRecordSize()))) { writerPtr = interpreterProxy->arrayValueOf(writer); goto l1; } else { interpreterProxy->primitiveFail(); writerPtr = null; goto l1; } l1: /* end fileValueOf: */; writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if ((interpreterProxy->isBytes(reader)) && ((interpreterProxy->byteSizeOf(reader)) == (fileRecordSize()))) { readerPtr = interpreterProxy->arrayValueOf(reader); goto l2; } else { interpreterProxy->primitiveFail(); readerPtr = null; goto l2; } l2: /* end fileValueOf: */; readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Answer a string containing the module name string for this plugin. */ EXPORT(sqInt) primitiveModuleName(void) { char *s; s= (char *)moduleName; interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(s)); } /* Change the scheduling priority of this process by the given nice increment. A positive increment decreases the priority. Only the superuser can specify a negative value (to increase the priority). See man(2) nice. Different versions of Unix are inconsistent in their return values. The only reliable test for success is to clear errno prior to the call, and test its value if the result of nice() is -1. */ EXPORT(sqInt) primitiveNice(void) { extern int errno; sqInt result; int niceIncrement; niceIncrement = interpreterProxy->stackIntegerValue(0); errno = 0; result = nice(niceIncrement); if (result == -1) { if (!(errno == 0)) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Set an environment variable using a string of the form 'KEY=value'. This implementation allocates a C string using malloc to allocate from the C heap (using cStringFromString rather than transientCStringFromString). This is necessary because the C runtime library does not make a copy of the string into separately allocated environment memory. */ EXPORT(sqInt) primitivePutEnv(void) { char *cStringPtr; sqInt keyValueString; keyValueString = interpreterProxy->stackObjectValue(0); cStringPtr = cStringFromString(keyValueString); if ((putenv(cStringPtr)) == 0) { interpreterProxy->pop(2); interpreterProxy->push(keyValueString); } else { return interpreterProxy->primitiveFail(); } } /* Answer the real path for a path string as determined by realpath(). */ EXPORT(sqInt) primitiveRealpath(void) { sqInt newPathString; char *pathString; sqInt s; char * realpathResult; sqInt bufferSize; char *buffer; bufferSize = 1024; newPathString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); interpreterProxy->pushRemappableOop(newPathString); pathString = transientCStringFromString(interpreterProxy->stackObjectValue(0)); newPathString = interpreterProxy->popRemappableOop(); buffer = interpreterProxy->arrayValueOf(newPathString); realpathResult = realpath(pathString, buffer); if (realpathResult == 0) { return interpreterProxy->primitiveFail(); } else { if ((strlen(realpathResult)) >= 1024) { perror("warning: statically allocated array exceeded in UnixOSProcessPlugin>>primitiveRealPath, object memory may have been corrupted"); return interpreterProxy->primitiveFail(); } s = stringFromCString(realpathResult); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Clean up after the death of a child, and answer an array with the pid and the exit status of the child process. Answer nil if the pidToHandle does not exist. */ EXPORT(sqInt) primitiveReapChildProcess(void) { pid_t pidResult; sqInt resultArray; sqInt *arrayPtr; int exitStatus; sqInt pidToHandle; /* Force C code translator to declare the variable */ exitStatus = 0; pidToHandle = interpreterProxy->stackIntegerValue(0); pidResult = waitpid ( pidToHandle, &exitStatus, WNOHANG ); if (pidResult <= 0) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); arrayPtr = interpreterProxy->firstIndexableField(resultArray); arrayPtr[0] = integerObjectOf(pidResult); arrayPtr[1] = integerObjectOf(exitStatus); interpreterProxy->pop(2); interpreterProxy->push(resultArray); } } /* Answer the registration index of the semaphore currently associated with the signal handler for sigNum. */ EXPORT(sqInt) primitiveSemaIndexFor(void) { sqInt sigNum; sqInt index; sigNum = interpreterProxy->stackIntegerValue(0); index = semaIndices[sigNum]; interpreterProxy->pop(1); interpreterProxy->pushInteger(index); } /* Send SIGABRT (abort) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGABRT); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGALRM (alarm clock) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGALRM); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCHLD (child status has changed, usually death of child) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGCHLD); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCONT (continue) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGCONT); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGHUP (hangup) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGHUP); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGINT (interrupt) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGINT); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGKILL (kill, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGKILL); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGPIPE (broken pipe) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGPIPE); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGQUIT (quit) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGQUIT); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGSTOP (stop, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGSTOP); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGTERM (termination) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGTERM); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR1 (User-defined signal 1) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGUSR1); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR2 (User-defined signal 2) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid) { pid_t pidToSignal; int result; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, SIGUSR2); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Set the index of the semaphore used by the OSProcess with which I collaborate. My OSProcess should set this value so that I can use it when handling SIGCHLD signals (death of child). In the C translation this is a static int which would be shared by all instances of UnixOSProcessPlugin, which is expected to be a singleton. Answer the value of the semaphore index. */ EXPORT(sqInt) primitiveSetSemaIndex(void) { sigChldSemaIndex = interpreterProxy->stackIntegerValue(0); interpreterProxy->pop(2); interpreterProxy->pushInteger(sigChldSemaIndex); } /* Integer value corresponding to SIGCHLD */ EXPORT(sqInt) primitiveSigChldNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigChldNumber()); } /* Integer value corresponding to SIGHUP */ EXPORT(sqInt) primitiveSigHupNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigHupNumber()); } /* Integer value corresponding to SIGINT */ EXPORT(sqInt) primitiveSigIntNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigIntNumber()); } /* Integer value corresponding to SIGKILL */ EXPORT(sqInt) primitiveSigKillNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigKillNumber()); } /* Integer value corresponding to SIGPIPE */ EXPORT(sqInt) primitiveSigPipeNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigPipeNumber()); } /* Integer value corresponding to SIGQUIT */ EXPORT(sqInt) primitiveSigQuitNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigQuitNumber()); } /* Integer value corresponding to SIGTERM */ EXPORT(sqInt) primitiveSigTermNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigTermNumber()); } /* Integer value corresponding to SIGUSR1 */ EXPORT(sqInt) primitiveSigUsr1Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr1Number()); } /* Integer value corresponding to SIGUSR2 */ EXPORT(sqInt) primitiveSigUsr2Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr2Number()); } /* Size in bytes of an integer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfInt(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfInt()); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfPointer(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfPointer()); } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. */ EXPORT(sqInt) primitiveSQFileFlush(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(2); interpreterProxy->pushInteger(fflush(sqFile->file)); } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { interpreterProxy->pop(3); interpreterProxy->pushInteger(fflush(sqFile->file)); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetBlocking(void) { sqInt descriptor; SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } descriptor = fileDescriptorFrom(sqFileOop); if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void) { sqInt descriptor; SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { descriptor = fileDescriptorFrom(sqFileOop); if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetNonBlocking(void) { sqInt descriptor; SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } descriptor = fileDescriptorFrom(sqFileOop); if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void) { sqInt descriptor; SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { descriptor = fileDescriptorFrom(sqFileOop); if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. */ EXPORT(sqInt) primitiveSQFileSetUnbuffered(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } retVal = fflush(sqFile->file); setbuf(sqFile->file, NULL); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void) { SESSIONIDENTIFIERTYPE thisSession; SQFile *sqFile; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { retVal = fflush(sqFile->file); setbuf(sqFile->file, NULL); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and check for ability to lock the specified region. If the exclusive flag is true, then specify an exclusive (F_WRLCK) lock on the file. Otherwise, specify a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). If length is zero, then the request is for the entire file to be locked, including region extents that have not yet been allocated for the file. If the fcntl() call fails, answer -1 (the result of the failed call). Otherwise, answer an array with the following six fields: lockable (true or false) l_pid (pid of the process preventing this lock request, or nil) l_type (request type F_WRLCK or F_RDLOCK of the process preventing this lock request) l_whence (the SEEK_SET, SEEK_CUR, or SEEK_END value of the lock preventing this lock request). l_start (offset of the region lock preventing this lock request) l_len (length of the region lock preventing this lock request) */ EXPORT(sqInt) primitiveTestLockableFileRegion(void) { sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqInt exclusive; sqInt start; sqInt resultArray; SQFile *sqFile; int result; sqInt len; int fileNo; sqInt canObtainLock; struct flock lockStruct; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } /* Set up the flock structure parameter for fcntl() */ fileNo = fileno(sqFile->file); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_GETLK, &lockStruct); if (result == -1) { interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } else { if (lockStruct.l_type == F_UNLCK) { canObtainLock = interpreterProxy->trueObject(); } else { canObtainLock = interpreterProxy->falseObject(); } resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 6); interpreterProxy->stObjectatput(resultArray, 1, canObtainLock); interpreterProxy->stObjectatput(resultArray, 2, (((lockStruct.l_pid) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 3, (((lockStruct.l_type) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 4, (((lockStruct.l_whence) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 5, (((lockStruct.l_start) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 6, (((lockStruct.l_len) << 1) | 1)); interpreterProxy->popthenPush(5, resultArray); } } /* Close a file handle at the close(2) level, using a handle returned by #primitiveUnixFileNumber. */ EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber) { int result; int handle; handle = interpreterProxy->stackIntegerValue(0); result = close(handle); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and answer the value of its Unix file number. The Unix file number is not directly useful to Squeak, but may be interesting for debugging problems involving failure to close unused file handles. */ EXPORT(sqInt) primitiveUnixFileNumber(void) { SQFile *sqFile; int fileNo; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); fileNo = fileno(sqFile->file); interpreterProxy->pop(2); interpreterProxy->pushInteger(fileNo); } /* Take a struct SQFile from the stack, and unlock the specified region. Answer the result of the call to fcntl(). If the region is in the file lock cache, remove it, but otherwise ignore the cache. The cache supports Win32 semantics within a single Squeak image, but not across separate images, therefore the unlock should be attempted regardless of whether this image thinks that the region has previously been locked. Answer the result of the call to fcntl(). */ EXPORT(sqInt) primitiveUnlockFileRegion(void) { sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqInt start; SQFile *sqFile; int result; sqInt len; int fileNo; struct flock lockStruct; len = interpreterProxy->stackIntegerValue(0); start = interpreterProxy->stackIntegerValue(1); sqFileOop = interpreterProxy->stackValue(2); if (!(isSQFileObject(sqFileOop))) { return interpreterProxy->primitiveFail(); } /* If the session identifier can be obtained, use it as an additional consistency check */ sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = interpreterProxy->getThisSessionID(); if (thisSession == null) { null; } else { if (!(sqFile->sessionID)) { return interpreterProxy->primitiveFail(); } } /* Set up the flock structure parameter for fcntl() */ fileNo = fileno(sqFile->file); lockStruct.l_type = F_UNLCK; lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(4); interpreterProxy->pushInteger(result); } /* Unset an environment variable. */ /* FIXME: unsetenv() is not portable. For Solaris or any other system which does not support unsetenv(), just comment it out in this method and rebuild the plugin. */ EXPORT(sqInt) primitiveUnsetEnv(void) { sqInt keyString; char *cStringPtr; keyString = interpreterProxy->stackObjectValue(0); /* For Solaris, comment out the following line */ cStringPtr = transientCStringFromString(keyString); unsetenv(cStringPtr); interpreterProxy->pop(1); } /* Answer a string containing the version string for this plugin. */ EXPORT(sqInt) primitiveVersionString(void) { interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(versionString())); } /* This is a signal handler for SIGCHLD. It is not meant to be called from Smalltalk, and should only be called indirectly as a result of a death of child signal from the operating system. Child processes must be cleaned up by the parent, otherwise they continue to exist as zombies until the parent exits. This handler resets the signal handler to catch the next SIGCHLD signal, then sets a semaphore to notify the system that a child process needs to be cleaned up. The actual clean up is done by a Smalltalk process which waits on the semaphore, then calls primitiveReapChildProcess. Note: If child processes die faster than we can clean them up, signals will be lost and child processes will remain as zombies. */ static void reapChildProcess(int sigNum) { setSigChldHandler(); if (sigChldSemaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(sigChldSemaIndex); } } /* Restore signal handlers to their original behaviors. */ static void restoreDefaultSignalHandlers(void) { sqInt sigNum; sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Answer 1 if running in secure mode, else 0. The osprocessSandboxSecurity variable is initialized to -1. On the first call to this method, set its value to either 0 (user has full access to the plugin) or 1 (user is not permitted to do dangerous things). */ static sqInt sandboxSecurity(void) { if (osprocessSandboxSecurity < 0) { osprocessSandboxSecurity = securityHeurisitic(); } return osprocessSandboxSecurity; } /* Answer 0 to permit full access to OSProcess functions, or 1 if access should be restricted for dangerous functions. The rules are: - If the security plugin is not present, grant full access - If the security plugin can be loaded, restrict access unless user has all of secCanWriteImage, secHasFileAccess and secHasSocketAccess */ /* FIXME: This function has not been tested. -dtl */ /* If the security plugin can be loaded, use it to check. If not, assume it's ok */ static sqInt securityHeurisitic(void) { sqInt hasSocketAccess; void (*sHSAfn)(void); sqInt canWriteImage; void (*sCWIfn)(void); void (*sHFAfn)(void); sqInt hasFileAccess; sCWIfn = interpreterProxy->ioLoadFunctionFrom("secCanWriteImage", "SecurityPlugin"); if (sCWIfn == 0) { return 0; } canWriteImage = ((int (*) (void)) sCWIfn)(); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); if (sHFAfn == 0) { return 0; } hasFileAccess = ((int (*) (void)) sHFAfn)(); sHSAfn = interpreterProxy->ioLoadFunctionFrom("secHasSocketAccess", "SecurityPlugin"); if (sHSAfn == 0) { return 0; } hasSocketAccess = ((int (*) (void)) sHSAfn)(); if ((canWriteImage && (hasFileAccess)) && (hasSocketAccess)) { return 0; } else { return 1; } } /* An array of Smalltalk Semaphore indices, one for each signal type for which a handler has been set. If an entry is zero, then no handler is active. */ static unsigned char * semaphoreIndices(void) { return semaIndices; } /* Answer a session ID represented by aByteArray. The session ID is used in the SQFile structure. If that data structure changes, we should see compiler warnings about type mismatch with SESSIONIDENTIFIERTYPE. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray) { union {SESSIONIDENTIFIERTYPE session; unsigned char bytes[sizeof(SESSIONIDENTIFIERTYPE)];} sessionUnion; unsigned char *session; sqInt idx; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfSession())))) { return null; } session = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfSession())) { sessionUnion.bytes[idx] = session[idx]; idx += 1; } return sessionUnion.session; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void setSigChldDefaultHandler(void) { setSignalNumberhandler(sigChldNumber(), sigDefaultNumber()); } /* Set the SIGCHLD signal handler in the virtual machine. */ static void setSigChldHandler(void) { if ((signal(SIGCHLD, reapChildProcess)) == (sigErrorNumber())) { perror("signal"); } } static void setSigIntDefaultHandler(void) { setSignalNumberhandler(sigIntNumber(), sigDefaultNumber()); } /* Set the SIGINT signal handler in the virtual machine to ignore interrupts. */ static void setSigIntIgnore(void) { setSignalNumberhandler(sigIntNumber(), sigIgnoreNumber()); } /* Set a signal handler. The C code translator will convert #sig:nal: into 'signal(parm1, parm2)' */ static void * setSignalNumberhandler(sqInt anInteger, void * signalHandlerAddress) { return signal(anInteger, signalHandlerAddress); } static void setSigPipeDefaultHandler(void) { setSignalNumberhandler(sigPipeNumber(), sigDefaultNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. If a pipe is opened to a child process, and the child exits, then subsequent writes to the pipe generate a SIGPIPE signal. If this signal is not handled, the VM will exit without warning. */ static sqInt setSigPipeHandler(void) { /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. */ static void setSigPipeIgnore(void) { setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } EXPORT(sqInt) shutdownModule(void) { sqInt sigNum; /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Child status has changed (POSIX). */ static sqInt sigChldNumber(void) { return SIGCHLD; } /* Default action for a signal */ static void * sigDefaultNumber(void) { return SIG_DFL; } /* Error return from signal() */ static void * sigErrorNumber(void) { return SIG_ERR; } /* Hangup detected on controlling terminal or death of controlling process */ static sqInt sigHupNumber(void) { return SIGHUP; } /* Ignore action for a signal */ static void * sigIgnoreNumber(void) { return SIG_IGN; } /* Interrupt (ANSI). */ static sqInt sigIntNumber(void) { return SIGINT; } /* Kill signal */ static sqInt sigKillNumber(void) { return SIGKILL; } /* Number of possible signals for this OS plus one. The signal handler arrays declared in #declareCVarsIn: are this size. */ static sqInt signalArraySize(void) { return NSIG; } /* An array of signal handler function addresses, with each entry corresponding to a signal type. */ static void ** signalHandlers(void) { return sigHandlers; } /* Broken pipe (POSIX). */ static sqInt sigPipeNumber(void) { return SIGPIPE; } /* Quit from keyboard */ static sqInt sigQuitNumber(void) { return SIGQUIT; } /* Termination signal. This is the default signal sent by the unix kill(1) command. */ static sqInt sigTermNumber(void) { return SIGTERM; } /* User defined signal number 1. This is value is platform-dependent, so the inSmalltalk default of 10 may be wrong on some platforms. */ static sqInt sigUsr1Number(void) { return SIGUSR1; } /* User defined signal number 2. This is value is platform-dependent, so the inSmalltalk default of 12 may be wrong on some platforms. */ static sqInt sigUsr2Number(void) { return SIGUSR2; } /* Size in bytes of an integer, for this C compiler on this machine. */ static sqInt sizeOfInt(void) { return sizeof(int); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ static sqInt sizeOfPointer(void) { return sizeof(void *); } /* Size of a SESSIONIDENTIFIERTYPE. Should match usage in the SQFile data structure, otherwise we should get compiler warnings. */ static sqInt sizeOfSession(void) { return sizeof(SESSIONIDENTIFIERTYPE); } /* Answer the size of a SQSocket data structure in bytes. */ static sqInt socketRecordSize(void) { return sizeof(SQSocket); } /* Return a pointer to the first byte of of the SQsocket data structure socket record within anSQSocketRecord, which is expected to be a ByteArray of size self>>socketRecordSize. */ static SQSocket * socketValueOf(sqInt anSQSocketRecord) { if ((interpreterProxy->isBytes(anSQSocketRecord)) && ((interpreterProxy->byteSizeOf(anSQSocketRecord)) == (socketRecordSize()))) { return interpreterProxy->arrayValueOf(anSQSocketRecord); } else { return null; } } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(char *aCString) { sqInt len; char *stringPtr; sqInt newString; len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); stringPtr = interpreterProxy->arrayValueOf(newString); (char *)strncpy(stringPtr, aCString, len); return newString; } /* Answer a new null-terminated C string copied from aString. The string is allocated in object memory, and will be moved without warning by the garbage collector. Any C pointer reference the the result is valid only until the garbage collector next runs. Therefore, this method should only be used within a single primitive in a section of code in which the garbage collector is guaranteed not to run. Note also that this method may itself invoke the garbage collector prior to allocating the new C string. Warning: The result of this method will be invalidated by the next garbage collection, including a GC triggered by creation of a new object within a primitive. Do not call this method twice to obtain two string pointers. */ static char * transientCStringFromString(sqInt aString) { sqInt len; char *cString; char *stringPtr; sqInt newString; /* Allocate space for a null terminated C string. */ len = interpreterProxy->sizeOfSTArrayFromCPrimitive(interpreterProxy->arrayValueOf(aString)); interpreterProxy->pushRemappableOop(aString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len + 1); stringPtr = interpreterProxy->arrayValueOf(interpreterProxy->popRemappableOop()); /* Point to the actual C string. */ cString = interpreterProxy->arrayValueOf(newString); (char *)strncpy(cString, stringPtr, len); cString[len] = 0; return cString; } /* Answer a string containing the version string for this plugin. Handle MNU errors, which can occur if class InterpreterPlugin has been removed from the system. Important: When this method is changed, the class side method must also be changed to match. */ /* 4.0 supports 64bit code base */ static char * versionString(void) { static char version[]= "4.0.1"; return version; } #ifdef SQUEAK_BUILTIN_PLUGIN void* UnixOSProcessPlugin_exports[][3] = { {"UnixOSProcessPlugin", "primitiveEnvironmentAt", (void*)primitiveEnvironmentAt}, {"UnixOSProcessPlugin", "primitiveSQFileFlush", (void*)primitiveSQFileFlush}, {"UnixOSProcessPlugin", "getModuleName", (void*)getModuleName}, {"UnixOSProcessPlugin", "primitiveUnsetEnv", (void*)primitiveUnsetEnv}, {"UnixOSProcessPlugin", "primitiveAioDisable", (void*)primitiveAioDisable}, {"UnixOSProcessPlugin", "primitiveGetUid", (void*)primitiveGetUid}, {"UnixOSProcessPlugin", "primitiveSigTermNumber", (void*)primitiveSigTermNumber}, {"UnixOSProcessPlugin", "primitiveFileStat", (void*)primitiveFileStat}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbufferedWithSessionIdentifier", (void*)primitiveSQFileSetUnbufferedWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlockingWithSessionIdentifier", (void*)primitiveSQFileSetNonBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSQFileFlushWithSessionIdentifier", (void*)primitiveSQFileFlushWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSendSigtermTo", (void*)primitiveSendSigtermTo}, {"UnixOSProcessPlugin", "primitiveGetEUid", (void*)primitiveGetEUid}, {"UnixOSProcessPlugin", "primitiveSigQuitNumber", (void*)primitiveSigQuitNumber}, {"UnixOSProcessPlugin", "primitiveSendSigusr1To", (void*)primitiveSendSigusr1To}, {"UnixOSProcessPlugin", "primitiveSendSigcontTo", (void*)primitiveSendSigcontTo}, {"UnixOSProcessPlugin", "primitiveSigUsr1Number", (void*)primitiveSigUsr1Number}, {"UnixOSProcessPlugin", "primitiveMakePipe", (void*)primitiveMakePipe}, {"UnixOSProcessPlugin", "primitiveForkExec", (void*)primitiveForkExec}, {"UnixOSProcessPlugin", "primitiveVersionString", (void*)primitiveVersionString}, {"UnixOSProcessPlugin", "primitiveSendSigstopTo", (void*)primitiveSendSigstopTo}, {"UnixOSProcessPlugin", "forkSqueak", (void*)forkSqueak}, {"UnixOSProcessPlugin", "primitiveSendSigalrmTo", (void*)primitiveSendSigalrmTo}, {"UnixOSProcessPlugin", "primitiveSendSigintTo", (void*)primitiveSendSigintTo}, {"UnixOSProcessPlugin", "primitiveSendSigpipeTo", (void*)primitiveSendSigpipeTo}, {"UnixOSProcessPlugin", "primitiveSendSigquitTo", (void*)primitiveSendSigquitTo}, {"UnixOSProcessPlugin", "primitiveAioHandle", (void*)primitiveAioHandle}, {"UnixOSProcessPlugin", "primitiveAioSuspend", (void*)primitiveAioSuspend}, {"UnixOSProcessPlugin", "primitiveGetPid", (void*)primitiveGetPid}, {"UnixOSProcessPlugin", "primitiveForwardSignalToSemaphore", (void*)primitiveForwardSignalToSemaphore}, {"UnixOSProcessPlugin", "primitiveSendSigusr2To", (void*)primitiveSendSigusr2To}, {"UnixOSProcessPlugin", "primitiveSetSemaIndex", (void*)primitiveSetSemaIndex}, {"UnixOSProcessPlugin", "primitiveAioEnable", (void*)primitiveAioEnable}, {"UnixOSProcessPlugin", "primitiveSendSigkillTo", (void*)primitiveSendSigkillTo}, {"UnixOSProcessPlugin", "primitiveCreatePipeWithSessionIdentifier", (void*)primitiveCreatePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSendSighupTo", (void*)primitiveSendSighupTo}, {"UnixOSProcessPlugin", "primitiveUnixFileClose", (void*)primitiveUnixFileClose}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbuffered", (void*)primitiveSQFileSetUnbuffered}, {"UnixOSProcessPlugin", "primitiveUnlockFileRegion", (void*)primitiveUnlockFileRegion}, {"UnixOSProcessPlugin", "primitiveFileProtectionMask", (void*)primitiveFileProtectionMask}, {"UnixOSProcessPlugin", "primitiveSigIntNumber", (void*)primitiveSigIntNumber}, {"UnixOSProcessPlugin", "shutdownModule", (void*)shutdownModule}, {"UnixOSProcessPlugin", "primitiveSQFileSetBlocking", (void*)primitiveSQFileSetBlocking}, {"UnixOSProcessPlugin", "primitiveSigPipeNumber", (void*)primitiveSigPipeNumber}, {"UnixOSProcessPlugin", "primitiveGetStdInHandleWithSessionIdentifier", (void*)primitiveGetStdInHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveUnixFileNumber", (void*)primitiveUnixFileNumber}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandle", (void*)primitiveGetStdOutHandle}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlocking", (void*)primitiveSQFileSetNonBlocking}, {"UnixOSProcessPlugin", "primitiveSendSigchldTo", (void*)primitiveSendSigchldTo}, {"UnixOSProcessPlugin", "primitiveSemaIndexFor", (void*)primitiveSemaIndexFor}, {"UnixOSProcessPlugin", "primitiveForkSqueakWithoutSigHandler", (void*)primitiveForkSqueakWithoutSigHandler}, {"UnixOSProcessPlugin", "primitivePutEnv", (void*)primitivePutEnv}, {"UnixOSProcessPlugin", "primitiveGetStdInHandle", (void*)primitiveGetStdInHandle}, {"UnixOSProcessPlugin", "primitiveForkSqueak", (void*)primitiveForkSqueak}, {"UnixOSProcessPlugin", "primitiveCreatePipe", (void*)primitiveCreatePipe}, {"UnixOSProcessPlugin", "primitiveForkAndExecInDirectory", (void*)primitiveForkAndExecInDirectory}, {"UnixOSProcessPlugin", "primitiveNice", (void*)primitiveNice}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandle", (void*)primitiveGetStdErrHandle}, {"UnixOSProcessPlugin", "primitiveGetCurrentWorkingDirectory", (void*)primitiveGetCurrentWorkingDirectory}, {"UnixOSProcessPlugin", "primitiveSigHupNumber", (void*)primitiveSigHupNumber}, {"UnixOSProcessPlugin", "primitiveModuleName", (void*)primitiveModuleName}, {"UnixOSProcessPlugin", "primitiveIsAtEndOfFile", (void*)primitiveIsAtEndOfFile}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandleWithSessionIdentifier", (void*)primitiveGetStdErrHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveChdir", (void*)primitiveChdir}, {"UnixOSProcessPlugin", "primitiveSendSigabrtTo", (void*)primitiveSendSigabrtTo}, {"UnixOSProcessPlugin", "primitiveErrorMessageAt", (void*)primitiveErrorMessageAt}, {"UnixOSProcessPlugin", "primitiveSigChldNumber", (void*)primitiveSigChldNumber}, {"UnixOSProcessPlugin", "primitiveCanReceiveSignals", (void*)primitiveCanReceiveSignals}, {"UnixOSProcessPlugin", "primitiveLockFileRegion", (void*)primitiveLockFileRegion}, {"UnixOSProcessPlugin", "primitiveGetGid", (void*)primitiveGetGid}, {"UnixOSProcessPlugin", "primitiveSizeOfInt", (void*)primitiveSizeOfInt}, {"UnixOSProcessPlugin", "primitiveFixPointersInArrayOfStrings", (void*)primitiveFixPointersInArrayOfStrings}, {"UnixOSProcessPlugin", "primitiveGetPPid", (void*)primitiveGetPPid}, {"UnixOSProcessPlugin", "setInterpreter", (void*)setInterpreter}, {"UnixOSProcessPlugin", "primitiveReapChildProcess", (void*)primitiveReapChildProcess}, {"UnixOSProcessPlugin", "primitiveGetSession", (void*)primitiveGetSession}, {"UnixOSProcessPlugin", "primitiveTestLockableFileRegion", (void*)primitiveTestLockableFileRegion}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandleWithSessionIdentifier", (void*)primitiveGetStdOutHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveRealpath", (void*)primitiveRealpath}, {"UnixOSProcessPlugin", "primitiveArgumentAt", (void*)primitiveArgumentAt}, {"UnixOSProcessPlugin", "primitiveGetEGid", (void*)primitiveGetEGid}, {"UnixOSProcessPlugin", "primitiveMakePipeWithSessionIdentifier", (void*)primitiveMakePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSQFileSetBlockingWithSessionIdentifier", (void*)primitiveSQFileSetBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSizeOfPointer", (void*)primitiveSizeOfPointer}, {"UnixOSProcessPlugin", "primitiveEnvironmentAtSymbol", (void*)primitiveEnvironmentAtSymbol}, {"UnixOSProcessPlugin", "initialiseModule", (void*)initialiseModule}, {"UnixOSProcessPlugin", "primitiveSigUsr2Number", (void*)primitiveSigUsr2Number}, {"UnixOSProcessPlugin", "primitiveSigKillNumber", (void*)primitiveSigKillNumber}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/Info-NPSophie__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable NPSophie CFBundleGetInfoString Squeak Browser Plugin 3.8.11b1 http://www.squeak.org CFBundleIconFile resources/ProjectBuilder/SqueakPlugin.icns CFBundleIdentifier org.squeak.SophiePlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName Sophie Browser Plugin CFBundlePackageType BRPL CFBundleShortVersionString Sophie Browser Plugin 3.8.11b1 CFBundleSignature MOSS CFBundleVersion 3.8.11b1 SqueakEncodingType macintosh SqueakMaxHeapSize 536870912 SqueakPluginsBuiltInOrLocalOnly ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/Info-NPSqueak__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable NPSqueak CFBundleGetInfoString Squeak Browser Plugin 3.8.12b1 http://www.squeak.org CFBundleIconFile resources/ProjectBuilder/SqueakPlugin.icns CFBundleIdentifier org.squeak.SqueakPlugin CFBundleInfoDictionaryVersion 6.0 CFBundleName Squeak Browser Plugin CFBundlePackageType BRPL CFBundleShortVersionString Squeak Browser Plugin 3.8.12b1 CFBundleSignature MOSS CFBundleVersion 3.8.12b1 SqueakEncodingType macintosh SqueakMaxHeapSize 536870912 SqueakPluginsBuiltInOrLocalOnly ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/Info-Squeak_VM_Debug__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions image CFBundleTypeIconFile SqueakImage.icns CFBundleTypeName Squeak Image File CFBundleTypeOSTypes STim CFBundleTypeRole Editor CFBundleTypeExtensions changes CFBundleTypeIconFile SqueakChanges.icns CFBundleTypeName Squeak Changes File CFBundleTypeOSTypes STch CFBundleTypeRole Editor CFBundleTypeExtensions sobj CFBundleTypeIconFile SqueakScript.icns CFBundleTypeName Squeak Script File CFBundleTypeOSTypes SOBJ CFBundleTypeRole Editor CFBundleTypeName JPEG CFBundleTypeOSTypes JPEG CFBundleTypeRole Viewer CFBundleTypeName TEXT CFBundleTypeOSTypes TEXT CFBundleTypeRole Viewer CFBundleTypeName ttro CFBundleTypeOSTypes ttro CFBundleTypeRole Viewer CFBundleTypeName HTML CFBundleTypeOSTypes HTML CFBundleTypeRole Viewer CFBundleTypeName RTF CFBundleTypeOSTypes RTF CFBundleTypeRole Viewer CFBundleTypeName TIFF CFBundleTypeOSTypes TIFF CFBundleTypeRole Viewer CFBundleTypeName PICT CFBundleTypeOSTypes PICT CFBundleTypeRole Viewer CFBundleTypeName URL CFBundleTypeOSTypes URL CFBundleTypeRole Viewer CFBundleTypeName ZIP CFBundleTypeOSTypes ZIP CFBundleTypeRole Viewer CFBundleTypeName zip CFBundleTypeOSTypes zip CFBundleTypeRole Viewer CFBundleTypeName BINA CFBundleTypeOSTypes BINA CFBundleTypeRole Viewer CFBundleTypeName GIFf CFBundleTypeOSTypes GIFf CFBundleTypeRole Viewer CFBundleTypeName PNGf CFBundleTypeOSTypes PNGf CFBundleTypeRole Viewer CFBundleTypeName MP3 CFBundleTypeOSTypes MP3 CFBundleTypeRole Viewer CFBundleTypeName MP3! CFBundleTypeOSTypes MP3! CFBundleTypeRole Viewer CFBundleTypeName MP3U CFBundleTypeOSTypes MP3U CFBundleTypeRole Viewer CFBundleTypeName MPEG CFBundleTypeOSTypes MPEG CFBundleTypeRole Viewer CFBundleTypeName mp3! CFBundleTypeOSTypes mp3! CFBundleTypeRole Viewer CFBundleTypeName MPG2 CFBundleTypeOSTypes MPG2 CFBundleTypeRole Viewer CFBundleTypeName MPG3 CFBundleTypeOSTypes MPG3 CFBundleTypeRole Viewer CFBundleTypeName MPG CFBundleTypeOSTypes MPG CFBundleTypeRole Viewer CFBundleTypeName Mp3 CFBundleTypeOSTypes mp3 CFBundleTypeRole Viewer CFBundleTypeName M3U CFBundleTypeOSTypes M3U CFBundleTypeRole Viewer CFBundleTypeName SRCS CFBundleTypeOSTypes SRCS CFBundleTypeRole Viewer CFBundleTypeName Chng CFBundleTypeOSTypes Chng CFBundleTypeRole Viewer CFBundleTypeName HPS5 CFBundleTypeOSTypes HPS5 CFBundleTypeRole Viewer CFBundleTypeExtensions bundle CFBundleTypeIconFile SqueakPlugin.icns CFBundleTypeName Squeak Plugin CFBundleTypeOSTypes BNDL CFBundleTypeRole Editor CFBundleExecutable Squeak CFBundleGetInfoString Squeak VM 3.8.10b16 http://www.squeak.org CFBundleIconFile Squeak.icns CFBundleIdentifier org.squeak.Squeak CFBundleInfoDictionaryVersion 6.0 CFBundleName Squeak CGDisableCoalescedUpdates CFBundlePackageType APPL CFBundleShortVersionString Squeak VM 3.8.10b16 CFBundleSignature FAST CFBundleVersion 3.8.10b16 NSServices NSMenuItem default Squeak DoIt NSMessage doitandreturn NSPortName Squeak NSReturnTypes NSStringPboardType NSSendTypes NSStringPboardType SqueakEncodingType macintosh SqueakFloatingWindowGetsFocus SqueakPluginsBuiltInOrLocalOnly SqueakImageName Squeak.image SqueakMaxHeapSize 536870912 SqueakUIFlushPrimaryDeferNMilliseconds 20 SqueakUIFlushSecondaryCheckForPossibleNeedEveryNMilliseconds 20 SqueakUIFlushSecondaryCleanupDelayMilliseconds 25 SqueakUIFlushUseHighPercisionClock SqueakWindowAttribute ggAAHg== SqueakWindowHasTitle SqueakWindowType 6 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/Info-Squeak_VM_OPT__Upgraded_.plist ================================================ CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions image CFBundleTypeIconFile SqueakImage.icns CFBundleTypeName Squeak Image File CFBundleTypeOSTypes STim CFBundleTypeRole Editor CFBundleTypeExtensions sources CFBundleTypeIconFile SqueakSources.icns CFBundleTypeName Squeak Sources File CFBundleTypeOSTypes STso CFBundleTypeRole Editor CFBundleTypeExtensions changes CFBundleTypeIconFile SqueakChanges.icns CFBundleTypeName Squeak Changes File CFBundleTypeOSTypes STch CFBundleTypeRole Editor CFBundleTypeExtensions sobj CFBundleTypeIconFile SqueakScript.icns CFBundleTypeName Squeak Script File CFBundleTypeOSTypes SOBJ CFBundleTypeRole Editor CFBundleTypeExtensions pr CFBundleTypeIconFile SqueakProject.icns CFBundleTypeName Squeak Project File CFBundleTypeOSTypes STpr CFBundleTypeName JPEG CFBundleTypeOSTypes JPEG CFBundleTypeRole Viewer CFBundleTypeName TEXT CFBundleTypeOSTypes TEXT CFBundleTypeRole Viewer CFBundleTypeName ttro CFBundleTypeOSTypes ttro CFBundleTypeRole Viewer CFBundleTypeName HTML CFBundleTypeOSTypes HTML CFBundleTypeRole Viewer CFBundleTypeName RTF CFBundleTypeOSTypes RTF CFBundleTypeRole Viewer CFBundleTypeName TIFF CFBundleTypeOSTypes TIFF CFBundleTypeRole Viewer CFBundleTypeName PICT CFBundleTypeOSTypes PICT CFBundleTypeRole Viewer CFBundleTypeName URL CFBundleTypeOSTypes URL CFBundleTypeRole Viewer CFBundleTypeName ZIP CFBundleTypeOSTypes ZIP CFBundleTypeRole Viewer CFBundleTypeName zip CFBundleTypeOSTypes zip CFBundleTypeRole Viewer CFBundleTypeName BINA CFBundleTypeOSTypes BINA CFBundleTypeRole Viewer CFBundleTypeName GIFf CFBundleTypeOSTypes GIFf CFBundleTypeRole Viewer CFBundleTypeName PNGf CFBundleTypeOSTypes PNGf CFBundleTypeRole Viewer CFBundleTypeName MP3 CFBundleTypeOSTypes MP3 CFBundleTypeRole Viewer CFBundleTypeName MP3! CFBundleTypeOSTypes MP3! CFBundleTypeRole Viewer CFBundleTypeName MP3U CFBundleTypeOSTypes MP3U CFBundleTypeRole Viewer CFBundleTypeName MPEG CFBundleTypeOSTypes MPEG CFBundleTypeRole Viewer CFBundleTypeName mp3! CFBundleTypeOSTypes mp3! CFBundleTypeRole Viewer CFBundleTypeName MPG2 CFBundleTypeOSTypes MPG2 CFBundleTypeRole Viewer CFBundleTypeName MPG3 CFBundleTypeOSTypes MPG3 CFBundleTypeRole Viewer CFBundleTypeName MPG CFBundleTypeOSTypes MPG CFBundleTypeRole Viewer CFBundleTypeName Mp3 CFBundleTypeOSTypes mp3 CFBundleTypeRole Viewer CFBundleTypeName M3U CFBundleTypeOSTypes M3U CFBundleTypeRole Viewer CFBundleTypeName SRCS CFBundleTypeOSTypes SRCS CFBundleTypeRole Viewer CFBundleTypeName Chng CFBundleTypeOSTypes Chng CFBundleTypeRole Viewer CFBundleTypeName HPS5 CFBundleTypeOSTypes HPS5 CFBundleTypeRole Viewer CFBundleTypeExtensions bundle CFBundleTypeIconFile SqueakPlugin.icns CFBundleTypeName Squeak Plugin CFBundleTypeOSTypes BNDL CFBundleTypeRole Editor CFBundleExecutable Squeak VM Opt CGDisableCoalescedUpdates CFBundleGetInfoString Squeak VM 3.8.10b15 http://www.squeak.org CFBundleIconFile Squeak.icns CFBundleIdentifier org.squeak.Squeak CFBundleInfoDictionaryVersion 6.0 CFBundleName Squeak VM CFBundlePackageType APPL CFBundleShortVersionString Squeak VM 3.8.10b15 CFBundleSignature FAST CFBundleVersion 3.8.10b15 NSServices NSMenuItem default Squeak DoIt NSMessage doitandreturn NSPortName Squeak NSReturnTypes NSStringPboardType NSSendTypes NSStringPboardType SqueakEncodingType macintosh SqueakFloatingWindowGetsFocus SqueakPluginsBuiltInOrLocalOnly SqueakImageName Squeak.image SqueakMaxHeapSize 536870912 SqueakUIFlushPrimaryDeferNMilliseconds 20 SqueakUIFlushSecondaryCheckForPossibleNeedEveryNMilliseconds 20 SqueakUIFlushSecondaryCleanupDelayMilliseconds 25 SqueakUIFlushUseHighPercisionClock SqueakWindowAttribute ggAAHg== SqueakWindowHasTitle SqueakWindowType 6 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/MacVMCorrectFileTypes.st ================================================ 'From Squeak3.7beta of ''1 April 2004'' [latest update: #5954] on 5 June 2005 at 11:11:41 pm'! Object subclass: #MacVMCorrectFileTypes instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Building'! !MacVMCorrectFileTypes commentStamp: '' prior: 0! Correct hfs meta data on c or h or precompiled header files, after SVN removes that data. This enables earlier versions of CodeWarrior to recognise the files. entries _ MacVMCorrectFileTypes new path: 'Macintosh HD:Users:johnmci:Documents:Squeak3.8.0:os9:platforms'.! ]style[(162 107)cred;,f2! !MacVMCorrectFileTypes methodsFor: 'running' stamp: 'JMM 5/23/2005 17:31'! checkDirectoryAndCorrect: aDirectory | dirs files type | aDirectory localName = '.svn' ifTrue: [^self]. dirs _ aDirectory directoryNames. dirs do: [:d | self checkDirectoryAndCorrect: (aDirectory directoryNamed: d)]. files _ aDirectory fileNames. files do: [:f | type _ aDirectory getMacFileTypeAndCreator: f. (type at: 1) asLowercase = 'text' ifFalse: [self checkFileName: f inDirectory: aDirectory]] ! ! !MacVMCorrectFileTypes methodsFor: 'running' stamp: 'JMM 5/23/2005 17:37'! checkFileName: aFileNameString inDirectory: aDirectory | tokens suffix | tokens _ aFileNameString findTokens: $.. tokens size < 2 ifTrue: [^self]. suffix _ tokens last. ((suffix = 'c') | (suffix = 'h') | (suffix = 'pch')) ifTrue: [ aDirectory setMacFileNamed: aFileNameString type: 'TEXT' creator: 'R*ch'. Transcript show: aDirectory printString,' ',aFileNameString;cr]. ! ! !MacVMCorrectFileTypes methodsFor: 'running' stamp: 'JMM 5/23/2005 16:55'! path: aPath | dirs directory | directory _ FileDirectory on: aPath. dirs _ directory directoryNames. dirs do: [:d | self checkDirectoryAndCorrect: (directory directoryNamed: d)]. ! ! ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/MyPlugin v2.proj.xml ================================================ ]> MyPlugin UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameMyPlugin OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints0 MWCodeGen_68K_IEEEdoubles0 MWCodeGen_68K_fardata0 MWCodeGen_68K_farvtables0 MWCodeGen_68K_farstrings0 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMac OS PPC C/C++ MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22656 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources s0 MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP603 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath0 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileMyPlugin MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MyPlugin.c MacOS Text Name MSL C.PPC.Lib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name MyPlugin68K MacOS Library MergeLibrary Name MyPlugin.c MacOS Name MSL C.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name MyPlugin68K MacOS MyPlugin Group 1 MyPlugin Name MyPlugin.c MacOS MyPlugin Name MSL C.PPC.Lib MacOS MyPlugin Name MSL RuntimePPC.Lib MacOS MyPlugin Name InterfaceLib MacOS MyPlugin Name MathLib MacOS Group 2 MyPlugin Name MyPlugin68K MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/MyPlugin68K v2.proj.xml ================================================ ]> MyPlugin68K UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS 68K Linker PreLinker PostLinker TargetnameMyPlugin68K OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeOBJ FileExtension CompilerMPW Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.fr CompilerODFRC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.idl CompilerSOMobjects TS Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.p CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.seg Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K4Byte MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNone MWCodeGen_68K_a6frames0 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeSharedLibrary MWProject_68K_outfileMyPlugin68K MWProject_68K_symfilename MWProject_68K_filecreator1178686292 MWProject_68K_filetype1936223330 MWProject_68K_size0 MWProject_68K_flags0 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize0 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen1 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersCFM68K MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsPragma MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentnameMyPlugin MWCFM68K_initname MWCFM68K_mainname MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_4 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources s0 MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP603 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath0 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeNormal MWLinker_PPC_initname MWLinker_PPC_mainname MWLinker_PPC_termname MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentnameSoundCodecPrims MWPEF_collapsereloads0 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileSoundCodecPrims MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1936223330 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MyPlugin.c MacOS Text Name InterfaceLib MacOS Library Name MSL C.CFM68K Fa(4i_8d).Lib MacOS Library Name MathLibCFM68K (4i_8d).Lib MacOS Library Name MSL MWCFM68KRuntime.Lib MacOS Library Group 1 Protected, Purgeable Name MyPlugin.c MacOS Name InterfaceLib MacOS Name MSL C.CFM68K Fa(4i_8d).Lib MacOS Name MathLibCFM68K (4i_8d).Lib MacOS Name MSL MWCFM68KRuntime.Lib MacOS MyPlugin68K Source MyPlugin68K Name MyPlugin.c MacOS Libraries MyPlugin68K Name MSL C.CFM68K Fa(4i_8d).Lib MacOS MyPlugin68K Name MathLibCFM68K (4i_8d).Lib MacOS MyPlugin68K Name MSL MWCFM68KRuntime.Lib MacOS MyPlugin68K Name InterfaceLib MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/NPSqueakStub.c ================================================ // Stub to call mach-o plugin for better project builder debugging. // By John M McIntosh Jan 2003. (johnmci@smalltalkconsulting.com) // Released under the Squeak-L license // http://www.squeak.org/download/license.html // V1.0 January 2003. // V 1.1 Sept 2003 Add looking in user/local/network/system domains #include "npapi.h" #include "npupp.h" #define EnterCodeResource() #define ExitCodeResource() #define __destroy_global_chain() #define __InitCode__() int printOnOSXPascal(unsigned char * string); int printOnOSX(char * string); int printOnOSXNumber(int number); int printOnOSXPascal(unsigned char * string); int printOnOSXFormat(char * string,char *format); OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr); CFragConnectionID LoadLibViaPath(char *libName); CFragConnectionID LoadLibViaPathInDomain(char *libName, SInt16 domain); int ioFindExternalFunctionIn(char *lookupName, int moduleHandle); int ioFreeModule(int moduleHandle); NPError Private_Initialize(void); void Private_Shutdown(void); NPError Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); NPError Private_Destroy(NPP instance, NPSavedData** save); NPError Private_SetWindow(NPP instance, NPWindow* window); NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason); int32 Private_WriteReady(NPP instance, NPStream* stream); int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname); void Private_Print(NPP instance, NPPrint* platformPrint); int16 Private_HandleEvent(NPP instance, void* event); void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData); jref Private_GetJavaClass(void); typedef short (*GetMainPtr)(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp); // Mach-O function GetMainPtr GetMain = NULL; typedef NPError (*GetPrivate_InitializePtr)(); // Mach-O function GetPrivate_InitializePtr GetPrivate_Initialize = NULL; typedef void (*GetPrivate_ShutdownPtr)(); // Mach-O function GetPrivate_ShutdownPtr GetPrivate_Shutdown = NULL; typedef NPError (*GetPrivate_NewPtr)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); // Mach-O function GetPrivate_NewPtr GetPrivate_New = NULL; typedef NPError (*GetPrivate_DestroyPtr)(NPP instance, NPSavedData** save); // Mach-O function GetPrivate_DestroyPtr GetPrivate_Destroy = NULL; typedef NPError (*GetPrivate_SetWindowPtr)(NPP instance, NPWindow* window); // Mach-O function GetPrivate_SetWindowPtr GetPrivate_SetWindow = NULL; typedef NPError (*GetPrivate_NewStreamPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); // Mach-O function GetPrivate_NewStreamPtr GetPrivate_NewStream = NULL; typedef int32 (*GetPrivate_WriteReadyPtr)(NPP instance, NPStream* stream); // Mach-O function GetPrivate_WriteReadyPtr GetPrivate_WriteReady = NULL; typedef int32 (*GetPrivate_WritePtr)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); // Mach-O function GetPrivate_WritePtr GetPrivate_Write = NULL; typedef void (*GetPrivate_StreamAsFilePtr)(NPP instance, NPStream* stream, const char* fname); // Mach-O function GetPrivate_StreamAsFilePtr GetPrivate_StreamAsFile = NULL; typedef NPError (*GetPrivate_DestroyStreamPtr)(NPP instance, NPStream* stream, NPError reason); // Mach-O function GetPrivate_DestroyStreamPtr GetPrivate_DestroyStream = NULL; typedef int16 (*GetPrivate_HandleEventPtr)(NPP instance, void* event); // Mach-O function GetPrivate_HandleEventPtr GetPrivate_HandleEvent = NULL; typedef void (*GetPrivate_PrintPtr)(NPP instance, NPPrint* platformPrint); // Mach-O function GetPrivate_PrintPtr GetPrivate_Print = NULL; typedef void (*GetPrivate_URLNotifyPtr)(NPP instance, const char* url, NPReason reason, void* notifyData); // Mach-O function GetPrivate_URLNotifyPtr GetPrivate_URLNotify = NULL; typedef jref (*GetPrivate_GetJavaClassPtr)(void); // Mach-O function GetPrivate_GetJavaClassPtr GetPrivate_GetJavaClass = NULL; static CFragConnectionID gWhere; NPNetscapeFuncs gRememberOldgNetscapeFuncsForSafariIssue; NPPluginFuncs gDummyPluginFuncsForSafariIssue; NPP_ShutdownUPP gDummyUnloadUppForSafariIssue; int main(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp) { int err=noErr; int navMinorVers = nsTable->version & 0xFF; gRememberOldgNetscapeFuncsForSafariIssue = *nsTable; gWhere = LoadLibViaPath("NPSqueak.bundle"); if (gWhere == nil) return -1; GetMain = (void *) ioFindExternalFunctionIn("npmain",(int) gWhere); if (GetMain == NULL) GetMain = (void *) ioFindExternalFunctionIn("main",(int) gWhere); err = GetMain(nsTable, pluginFuncs, unloadUpp); // // Set up the plugin function table that Netscape will use to // call us. Netscape needs to know about our version and size // and have a UniversalProcPointer for every function we implement. // pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; pluginFuncs->size = sizeof(NPPluginFuncs); pluginFuncs->newp = NewNPP_NewProc(Private_New); pluginFuncs->destroy = NewNPP_DestroyProc(Private_Destroy); pluginFuncs->setwindow = NewNPP_SetWindowProc(Private_SetWindow); pluginFuncs->newstream = NewNPP_NewStreamProc(Private_NewStream); pluginFuncs->destroystream = NewNPP_DestroyStreamProc(Private_DestroyStream); pluginFuncs->asfile = NewNPP_StreamAsFileProc(Private_StreamAsFile); pluginFuncs->writeready = NewNPP_WriteReadyProc(Private_WriteReady); pluginFuncs->write = NewNPP_WriteProc(Private_Write); pluginFuncs->print = NewNPP_PrintProc(Private_Print); pluginFuncs->event = NewNPP_HandleEventProc(Private_HandleEvent); if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) { pluginFuncs->urlnotify = NewNPP_URLNotifyProc(Private_URLNotify); } if( navMinorVers >= NPVERS_HAS_LIVECONNECT ) { pluginFuncs->javaClass = (JRIGlobalRef) Private_GetJavaClass(); } *unloadUpp = NewNPP_ShutdownProc(Private_Shutdown); return err; } NPError Private_Initialize(void) { NPError err; if (GetPrivate_Initialize == NULL) GetPrivate_Initialize = (void *) ioFindExternalFunctionIn("Private_Initialize",(int) gWhere); err = GetPrivate_Initialize(); return err; } void Private_Shutdown(void) { if (gWhere == NULL) return; if (GetPrivate_Shutdown == NULL) GetPrivate_Shutdown = (void *) ioFindExternalFunctionIn("Private_Shutdown",(int) gWhere); if (GetPrivate_Shutdown == NULL) return; GetPrivate_Shutdown(); ioFreeModule((int) gWhere); gWhere = 0; GetPrivate_Initialize = 0; GetPrivate_Shutdown = 0; GetPrivate_New = 0; GetPrivate_Destroy= 0; GetPrivate_SetWindow= 0; GetPrivate_NewStream= 0; GetPrivate_WriteReady= 0; GetPrivate_Write = 0; GetPrivate_StreamAsFile = 0; GetPrivate_DestroyStream = 0; GetPrivate_HandleEvent = 0; GetPrivate_Print = 0; GetPrivate_URLNotify = 0; GetPrivate_GetJavaClass = 0; } NPError Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) { NPError err; if (gWhere == nil) { gWhere = LoadLibViaPath("NPSqueak.bundle"); if (gWhere == nil) return -1; GetMain = (void *) ioFindExternalFunctionIn("npmain",(int) gWhere); if (GetMain == NULL) GetMain = (void *) ioFindExternalFunctionIn("main",(int) gWhere); err = GetMain(&gRememberOldgNetscapeFuncsForSafariIssue, &gDummyPluginFuncsForSafariIssue, &gDummyUnloadUppForSafariIssue); } if (GetPrivate_New == NULL) GetPrivate_New = (void *) ioFindExternalFunctionIn("Private_New",(int) gWhere); if (GetPrivate_New != NULL) err = GetPrivate_New( pluginType, instance, mode, argc, argn, argv, saved); return err; } NPError Private_Destroy(NPP instance, NPSavedData** save) { NPError err; if (GetPrivate_Destroy == NULL) GetPrivate_Destroy = (void *) ioFindExternalFunctionIn("Private_Destroy",(int) gWhere); if (GetPrivate_Destroy != NULL) err = GetPrivate_Destroy( instance, save); Private_Shutdown(); return NPERR_NO_ERROR; } NPError Private_SetWindow(NPP instance, NPWindow* window) { NPError err; if (GetPrivate_SetWindow == NULL) GetPrivate_SetWindow = (void *) ioFindExternalFunctionIn("Private_SetWindow",(int) gWhere); if (GetPrivate_SetWindow != NULL) err = GetPrivate_SetWindow( instance, window); return err; } NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) { NPError err; if (GetPrivate_NewStream == NULL) GetPrivate_NewStream = (void *) ioFindExternalFunctionIn("Private_NewStream",(int) gWhere); if (GetPrivate_NewStream != NULL) err = GetPrivate_NewStream( instance, type, stream, seekable, stype); return err; } int32 Private_WriteReady(NPP instance, NPStream* stream) { int32 length; if (GetPrivate_WriteReady == NULL) GetPrivate_WriteReady = (void *) ioFindExternalFunctionIn("Private_WriteReady",(int) gWhere); if (GetPrivate_WriteReady != NULL) length = GetPrivate_WriteReady( instance, stream); return length; } int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) { int32 length; if (GetPrivate_Write == NULL) GetPrivate_Write = (void *) ioFindExternalFunctionIn("Private_Write",(int) gWhere); if (GetPrivate_Write != NULL) length = GetPrivate_Write( instance, stream, offset, len, buffer); return length; } void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { if (GetPrivate_StreamAsFile == NULL) GetPrivate_StreamAsFile = (void *) ioFindExternalFunctionIn("Private_StreamAsFile",(int) gWhere); if (GetPrivate_StreamAsFile != NULL) GetPrivate_StreamAsFile( instance, stream, fname); } NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason) { NPError err; if (GetPrivate_DestroyStream == NULL) GetPrivate_DestroyStream = (void *) ioFindExternalFunctionIn("Private_DestroyStream",(int) gWhere); if (GetPrivate_DestroyStream != NULL) err = GetPrivate_DestroyStream( instance, stream, reason); return err; } int16 Private_HandleEvent(NPP instance, void* event) { int16 err; if (GetPrivate_HandleEvent == NULL) GetPrivate_HandleEvent = (void *) ioFindExternalFunctionIn("Private_HandleEvent",(int) gWhere); if (GetPrivate_HandleEvent != NULL) err = GetPrivate_HandleEvent( instance, event); return err; } void Private_Print(NPP instance, NPPrint* platformPrint) { if (GetPrivate_Print == NULL) GetPrivate_Print = (void *) ioFindExternalFunctionIn("Private_Print",(int) gWhere); if (GetPrivate_Print != NULL) GetPrivate_Print( instance, platformPrint); } void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) { if (GetPrivate_URLNotify == NULL) GetPrivate_URLNotify = (void *) ioFindExternalFunctionIn("Private_URLNotify",(int) gWhere); if (GetPrivate_URLNotify != NULL) GetPrivate_URLNotify( instance, url, reason, notifyData); } jref Private_GetJavaClass(void) { if (GetPrivate_GetJavaClass == NULL) GetPrivate_GetJavaClass = (void *) ioFindExternalFunctionIn("Private_GetJavaClass",(int) gWhere); if (GetPrivate_GetJavaClass != NULL) return GetPrivate_GetJavaClass(); } static void* FP2TV (void * fp ) { void **newGlue = NULL ; if ( fp != NULL ) { newGlue = (void**) malloc (2 * sizeof(void *)); if (newGlue != NULL ) { newGlue[0] = fp ; newGlue[1] = NULL ; } } return newGlue; } int ioFindExternalFunctionIn(char *lookupName, int moduleHandle) { void * functionPtr = 0; CFStringRef theString; if (!moduleHandle) return nil; //printOnOSX(lookupName); theString = CFStringCreateWithCString(kCFAllocatorDefault,lookupName,kCFStringEncodingMacRoman); if (theString == nil) return nil; functionPtr = (void*)CFBundleGetFunctionPointerForName((CFBundleRef) moduleHandle,theString); CFRelease(theString); return (int) functionPtr; } /* ioFreeModule: Free the module with the associated handle. WARNING: never primitiveFail() within, just return 0. */ int ioFreeModule(int moduleHandle) { if (!moduleHandle) return 0; CFBundleUnloadExecutable((CFBundleRef) moduleHandle); CFRelease((CFBundleRef) moduleHandle); return 0; } CFragConnectionID LoadLibViaPathInDomain(char *libName,SInt16 domain) { CFragConnectionID libHandle = 0; CFURLRef theURLRef; CFBundleRef theBundle; OSStatus err; CFStringRef libNameCFString; FSRef frameworksFolderRef; CFURLRef baseURL; err = FSFindFolder(domain, kInternetPlugInFolderType, false,&frameworksFolderRef); if (err != noErr) { return nil; } baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault,&frameworksFolderRef); if (baseURL == nil) { return nil; } libNameCFString = CFStringCreateWithCString(kCFAllocatorDefault,libName,kCFStringEncodingMacRoman); if (libNameCFString == nil) { CFRelease(baseURL); return nil; } theURLRef = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL,libNameCFString, false); CFRelease(libNameCFString); CFRelease(baseURL); if (theURLRef == nil) { return nil; } theBundle = CFBundleCreate(kCFAllocatorSystemDefault,theURLRef); CFRelease(theURLRef); if (theBundle == nil) { return nil; } if (!CFBundleLoadExecutable(theBundle)) { CFRelease(theBundle); return nil; } libHandle = (CFragConnectionID) theBundle; return libHandle; } CFragConnectionID LoadLibViaPath(char *libName) { static const SInt16 domain[] = {kUserDomain, kLocalDomain, kNetworkDomain, kSystemDomain, 0}; CFragConnectionID connectionID; SInt32 domainIndex=0; do { connectionID = LoadLibViaPathInDomain(libName,domain[domainIndex]); if (connectionID != nil) return connectionID; domainIndex++; } while (domain[domainIndex] != 0); return nil; } OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) { OSStatus err; FSRef frameworksFolderRef; CFURLRef baseURL; CFURLRef bundleURL; if ( bundlePtr == nil ) return( -1 ); *bundlePtr = nil; baseURL = nil; bundleURL = nil; err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef); if (err == noErr) { baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef); if (baseURL == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false); if (bundleURL == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL); if (*bundlePtr == nil) { err = coreFoundationUnknownErr; } } if (err == noErr) { if ( ! CFBundleLoadExecutable( *bundlePtr ) ) { err = coreFoundationUnknownErr; } } // Clean up. if (err != noErr && *bundlePtr != nil) { CFRelease(*bundlePtr); *bundlePtr = nil; } if (bundleURL != nil) { CFRelease(bundleURL); } if (baseURL != nil) { CFRelease(baseURL); } return err; } int printOnOSXFormat(char * string,char *format) { CFBundleRef bundle; int(*fprintf_ptr)(FILE *stream, const char *format, ...) = NULL; int(*fcnFlush_ptr)(FILE *stream) = NULL; void* fcn_ptr = NULL; void* fcnFlushx_ptr = NULL; OSErr err; FILE* stderr_ptr = NULL; void* __sf_ptr = NULL; err = LoadFrameworkBundle( CFSTR("System.framework"), &bundle ); fcn_ptr = CFBundleGetFunctionPointerForName(bundle, CFSTR("fprintf")); fcnFlushx_ptr = CFBundleGetFunctionPointerForName(bundle, CFSTR("fflush")); __sf_ptr = CFBundleGetDataPointerForName(bundle, CFSTR("__sF")); if(fcn_ptr) { /* cast it */ fprintf_ptr = ( int(*)(FILE *stream, const char *format, ...) ) fcn_ptr; } else { /* it failed, handle that somehow */ return; } if(fcnFlushx_ptr) { /* cast it */ fcnFlush_ptr = ( int(*)(FILE *stream) ) fcnFlushx_ptr; } else { /* it failed, handle that somehow */ return; } if(__sf_ptr) { stderr_ptr = (FILE*) ( ((char*)__sf_ptr) + 176); /* 176 = 88*2, where 88=sizeof(FILE) under BSD */ } else { /* it failed */ return; } fprintf_ptr(stderr_ptr, format,string); fcnFlush_ptr(stderr_ptr); } int printOnOSX(char * string) { return printOnOSXFormat(string,"\n+-+%s"); } int printOnOSXNumber(int number) { return printOnOSXFormat((char *) number,"\n+-+%d"); } int printOnOSXPascal(unsigned char *string) { CopyPascalStringToC((ConstStr255Param) string,(char*) string); printOnOSX((char*) string); CopyCStringToPascal((char*)string,(void *) string); } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/Squeak VM Universal-Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions image CFBundleTypeIconFile SqueakImage.icns CFBundleTypeName Squeak Image File CFBundleTypeOSTypes STim CFBundleTypeRole Editor CFBundleTypeExtensions sources CFBundleTypeIconFile SqueakSources.icns CFBundleTypeName Squeak Sources File CFBundleTypeOSTypes STso CFBundleTypeRole Editor CFBundleTypeExtensions changes CFBundleTypeIconFile SqueakChanges.icns CFBundleTypeName Squeak Changes File CFBundleTypeOSTypes STch CFBundleTypeRole Editor CFBundleTypeExtensions sobj CFBundleTypeIconFile SqueakScript.icns CFBundleTypeName Squeak Script File CFBundleTypeOSTypes SOBJ CFBundleTypeRole Editor CFBundleTypeExtensions pr CFBundleTypeIconFile SqueakProject.icns CFBundleTypeName Squeak Project File CFBundleTypeOSTypes STpr CFBundleTypeName JPEG CFBundleTypeOSTypes JPEG CFBundleTypeRole Viewer CFBundleTypeName TEXT CFBundleTypeOSTypes TEXT CFBundleTypeRole Viewer CFBundleTypeName ttro CFBundleTypeOSTypes ttro CFBundleTypeRole Viewer CFBundleTypeName HTML CFBundleTypeOSTypes HTML CFBundleTypeRole Viewer CFBundleTypeName RTF CFBundleTypeOSTypes RTF CFBundleTypeRole Viewer CFBundleTypeName TIFF CFBundleTypeOSTypes TIFF CFBundleTypeRole Viewer CFBundleTypeName PICT CFBundleTypeOSTypes PICT CFBundleTypeRole Viewer CFBundleTypeName URL CFBundleTypeOSTypes URL CFBundleTypeRole Viewer CFBundleTypeName ZIP CFBundleTypeOSTypes ZIP CFBundleTypeRole Viewer CFBundleTypeName zip CFBundleTypeOSTypes zip CFBundleTypeRole Viewer CFBundleTypeName BINA CFBundleTypeOSTypes BINA CFBundleTypeRole Viewer CFBundleTypeName GIFf CFBundleTypeOSTypes GIFf CFBundleTypeRole Viewer CFBundleTypeName PNGf CFBundleTypeOSTypes PNGf CFBundleTypeRole Viewer CFBundleTypeName MP3 CFBundleTypeOSTypes MP3 CFBundleTypeRole Viewer CFBundleTypeName MP3! CFBundleTypeOSTypes MP3! CFBundleTypeRole Viewer CFBundleTypeName MP3U CFBundleTypeOSTypes MP3U CFBundleTypeRole Viewer CFBundleTypeName MPEG CFBundleTypeOSTypes MPEG CFBundleTypeRole Viewer CFBundleTypeName mp3! CFBundleTypeOSTypes mp3! CFBundleTypeRole Viewer CFBundleTypeName MPG2 CFBundleTypeOSTypes MPG2 CFBundleTypeRole Viewer CFBundleTypeName MPG3 CFBundleTypeOSTypes MPG3 CFBundleTypeRole Viewer CFBundleTypeName MPG CFBundleTypeOSTypes MPG CFBundleTypeRole Viewer CFBundleTypeName Mp3 CFBundleTypeOSTypes mp3 CFBundleTypeRole Viewer CFBundleTypeName M3U CFBundleTypeOSTypes M3U CFBundleTypeRole Viewer CFBundleTypeName SRCS CFBundleTypeOSTypes SRCS CFBundleTypeRole Viewer CFBundleTypeName Chng CFBundleTypeOSTypes Chng CFBundleTypeRole Viewer CFBundleTypeName HPS5 CFBundleTypeOSTypes HPS5 CFBundleTypeRole Viewer CFBundleTypeExtensions bundle CFBundleTypeIconFile SqueakPlugin.icns CFBundleTypeName Squeak Plugin CFBundleTypeOSTypes BNDL CFBundleTypeRole Editor CFBundleExecutable Squeak VM Opt CGDisableCoalescedUpdates CFBundleGetInfoString Squeak VM 3.8.12b4 http://www.squeak.org CFBundleIconFile Squeak.icns CFBundleIdentifier org.squeak.Squeak CFBundleInfoDictionaryVersion 6.0 CFBundleName Squeak VM CFBundlePackageType APPL CFBundleShortVersionString Squeak VM 3.8.12b4 CFBundleSignature FAST CFBundleVersion 3.8.12b4 NSServices NSMenuItem default Squeak DoIt NSMessage doitandreturn NSPortName Squeak NSReturnTypes NSStringPboardType NSSendTypes NSStringPboardType SqueakEncodingType macintosh SqueakFloatingWindowGetsFocus SqueakPluginsBuiltInOrLocalOnly SqueakImageName Squeak.image SqueakMaxHeapSize 536870912 SqueakUIFlushPrimaryDeferNMilliseconds 20 SqueakUIFlushSecondaryCheckForPossibleNeedEveryNMilliseconds 20 SqueakUIFlushSecondaryCleanupDelayMilliseconds 25 SqueakUIFlushUseHighPercisionClock SqueakWindowAttribute ggAAHg== SqueakWindowHasTitle SqueakWindowType 6 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakPro5.xml ================================================ ]> Squeak VM PPC Debug UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path:platforms:Mac OS:vm: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Libraries: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Headers: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameSqueak VM PPC Debug OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000011100D75E82010000000000001000D75F130 0002000000000000000000000D75DFC000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSize MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMacOS Toolbox DEBUG 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle1 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline1 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg1 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources A MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix1 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap1 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termnameSqueakTerminate MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfileSqueak VM PPC Debug MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1095782476 MWProject_PPC_size30000 MWProject_PPC_minsize1000 MWProject_PPC_stacksize80 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library WeakImport Name MSL RuntimePPC.Lib MacOS Library Name AsynchFilePlugin.c MacOS Text Debug Name AsynchFilePlugin.h MacOS Text Name B2DPlugin.c MacOS Text Debug Name b3d.h MacOS Text Name b3dDraw.c MacOS Text Debug Name b3dInit.c MacOS Text Debug Name b3dMain.c MacOS Text Debug Name b3dRemap.c MacOS Text Debug Name b3dTypes.h MacOS Text Name BitBltPlugin.c MacOS Text Debug Name FFTPlugin.c MacOS Text Debug Name FilePlugin.c MacOS Text Debug Name FilePlugin.h MacOS Text Name FloatArrayPlugin.c MacOS Text Debug Name JoystickTabletPlugin.c MacOS Text Debug Name JoystickTabletPlugin.h MacOS Text Name Klatt.c MacOS Text Debug Name LargeIntegers.c MacOS Text Debug Name Matrix2x3Plugin.c MacOS Text Debug Name MIDIPlugin.c MacOS Text Debug Name MidiPlugin.h MacOS Text Name SerialPlugin.c MacOS Text Debug Name SerialPlugin.h MacOS Text Name SocketPlugin.c MacOS Text Debug Name SocketPlugin.h MacOS Text Name SoundCodecPrims.c MacOS Text Debug Name SoundCodecPrims.h MacOS Text Name SoundPlugin.c MacOS Text Debug Name SoundPlugin.h MacOS Text Name sq.h MacOS Text Name sqConfig.h MacOS Text Name sqFilePluginBasicPrims.c MacOS Text Debug Name sqSoundCodecPluginBasicPrims.c MacOS Text Debug Name sqMacAsyncFilePrims.c MacOS Text Debug Name sqMacDirectory.c MacOS Text Debug Name sqMacJoystickAndTablet.c MacOS Text Debug Name sqMacSound.c MacOS Text Debug Name sqMacWindow.c MacOS Text Debug Name sqNamedPrims.c MacOS Text Debug Name sqNamedPrims.h MacOS Text Name sqPlatformSpecific.h MacOS Text Name Squeak3D.c MacOS Text Debug Name SqueakApp.r MacOS Text Debug Name SqueakApp.rsrc MacOS Resource Debug Name sqVirtualMachine.c MacOS Text Debug Name sqVirtualMachine.h MacOS Text Name SurfacePlugin.c MacOS Text Debug Name SurfacePlugin.h MacOS Text Name ZipPlugin.c MacOS Text Debug Name OpenTptInetPPC.o MacOS Library Debug Name OpenTptInternetLib MacOS Library Debug, WeakImport Name OpenTransportExtnPPC.o MacOS Library Debug Name OpenTransportLib MacOS Library Debug, WeakImport Name QuickTimeLib MacOS Library Debug, WeakImport Name sqMacNetwork.c MacOS Text Debug Name PowerMgrLib MacOS Library Debug, WeakImport Name DropPlugin.c MacOS Text Debug Name DropPlugin.h MacOS Text Name sqMacDragDrop.c MacOS Text Debug Name DragLib MacOS Library Debug, WeakImport Name myMacHeaders.pch MacOS Text Debug Name DSAPrims.c MacOS Text Debug Name MiscPrimitivePlugin.c MacOS Text Debug Name ADPCMCodecPlugin.c MacOS Text Debug Name SoundGenerationPlugin.c MacOS Text Debug Name SoundGenerationPlugin.h MacOS Text Name ThreadsLib MacOS Library Debug, WeakImport Name NavigationLib MacOS Library Debug, WeakImport Name MSL C.PPC.Lib MacOS Library Debug Name MSL SIOUX.PPC.Lib MacOS Library Debug Name SecurityPlugin.c MacOS Text Debug Name securityPlugin.h MacOS Text Name sqMacSecurity.c MacOS Text Debug Name JPEGReaderPlugin.c MacOS Text Debug Name StarSqueakPlugin.c MacOS Text Debug Name B3DAcceleratorPlugin.c MacOS Text Debug Name B3DAcceleratorPlugin.h MacOS Text Name sqMacOpenGLInfo.c MacOS Text Debug Name sqMacOpenGL.c MacOS Text Debug Name sqOpenGLRenderer.c MacOS Text Debug Name sqMacOpenGL.h MacOS Text Name sqOpenGLRenderer.h MacOS Text Name OpenGLLibraryStub MacOS Library Debug, WeakImport Name OpenGLUtilityStub MacOS Library Debug, WeakImport Name sqMacMIDI.c MacOS Text Debug Name sqMacSerialPort.c MacOS Text Debug Name sqMacFileLogic.c MacOS Text Debug Name sqMacFileLogic.h MacOS Text Name DisplayLib MacOS Library Debug, WeakImport Name sqMacUUID.c MacOS Text Debug Name UUIDPlugin.c MacOS Text Debug Name UUIDPlugin.h MacOS Text Name sqMacInternetConfiguration.c MacOS Text Debug Name InternetConfigPlugin.c MacOS Text Debug Name InternetConfigPlugin.h MacOS Text Name InternetConfigLib MacOS Library Debug, WeakImport Name USBManagerLib MacOS Library Debug, WeakImport Name Error.c MacOS Text Debug Name jcapimin.c MacOS Text Debug Name jcapistd.c MacOS Text Debug Name jccoefct.c MacOS Text Debug Name jccolor.c MacOS Text Debug Name jcdctmgr.c MacOS Text Debug Name jchuff.c MacOS Text Debug Name jchuff.h MacOS Text Name jcinit.c MacOS Text Debug Name jcmainct.c MacOS Text Debug Name jcmarker.c MacOS Text Debug Name jcmaster.c MacOS Text Debug Name jcomapi.c MacOS Text Debug Name jconfig.h MacOS Text Name jcparam.c MacOS Text Debug Name jcphuff.c MacOS Text Debug Name jcprepct.c MacOS Text Debug Name jcsample.c MacOS Text Debug Name jctrans.c MacOS Text Debug Name jdapimin.c MacOS Text Debug Name jdapistd.c MacOS Text Debug Name jdatadst.c MacOS Text Debug Name jdatasrc.c MacOS Text Debug Name jdcoefct.c MacOS Text Debug Name jdcolor.c MacOS Text Debug Name jdct.h MacOS Text Name jddctmgr.c MacOS Text Debug Name jdhuff.c MacOS Text Debug Name jdhuff.h MacOS Text Name jdinput.c MacOS Text Debug Name jdmainct.c MacOS Text Debug Name jdmarker.c MacOS Text Debug Name jdmaster.c MacOS Text Debug Name jdmerge.c MacOS Text Debug Name jdphuff.c MacOS Text Debug Name jdpostct.c MacOS Text Debug Name jdsample.c MacOS Text Debug Name jdtrans.c MacOS Text Debug Name jerror.c MacOS Text Debug Name jerror.h MacOS Text Name jfdctflt.c MacOS Text Debug Name jfdctfst.c MacOS Text Debug Name jfdctint.c MacOS Text Debug Name jidctflt.c MacOS Text Debug Name jidctfst.c MacOS Text Debug Name jidctint.c MacOS Text Debug Name jidctred.c MacOS Text Debug Name jinclude.h MacOS Text Name jmemdatadst.c MacOS Text Debug Name jmemdatasrc.c MacOS Text Debug Name jmemmgr.c MacOS Text Debug Name jmemnobs.c MacOS Text Debug Name jmemsys.h MacOS Text Name jmorecfg.h MacOS Text Name jpegint.h MacOS Text Name jpeglib.h MacOS Text Name JPEGReadWriter2Plugin.c MacOS Text Debug Name JPEGReadWriter2Plugin.h MacOS Text Name jquant1.c MacOS Text Debug Name jquant2.c MacOS Text Debug Name jutils.c MacOS Text Debug Name jversion.h MacOS Text Name CarbonAccessors.o MacOS Library Debug Name sqMacExternalPrims.c MacOS Text Debug Name sqMacExternalPrims.h MacOS Text Name sqMacImageIO.c MacOS Text Debug Name sqMacImageIO.h MacOS Text Name sqMacMain.c MacOS Text Debug Name sqMacMain.h MacOS Text Name sqMacMemory.c MacOS Text Debug Name sqMacMemory.h MacOS Text Name sqMacTime.c MacOS Text Debug Name sqMacTime.h MacOS Text Name sqMacUIAppleEvents.c MacOS Text Debug Name sqMacUIAppleEvents.h MacOS Text Name sqMacUIClipBoard.c MacOS Text Debug Name sqMacUIClipBoard.h MacOS Text Name sqMacUIConstants.h MacOS Text Name sqMacUIEvents.h MacOS Text Name sqMacUIMenuBar.c MacOS Text Debug Name sqMacUIMenuBar.h MacOS Text Name sqMacWindow.h MacOS Text Name osExports.c MacOS Text Debug Name BMPReadWriterPlugin.c MacOS Text Debug Name GeniePlugin.c MacOS Text Debug Name interp os9.c MacOS Text Debug Name sqMacUIEvents.c MacOS Text Debug Name sqMacEncoding.c MacOS Text Debug Name sqMacEncoding.h MacOS Text Name sqMacHostWindow.c MacOS Text Debug Name sqMacHostWindow.h MacOS Text Name HostWindowPlugin.c MacOS Text Debug Name MacMenubarPlugin.c MacOS Text Debug Name MenusLib MacOS Library Debug Name AppearanceLib MacOS Library Debug Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name ADPCMCodecPlugin.c MacOS Name AsynchFilePlugin.c MacOS Name AsynchFilePlugin.h MacOS Name B2DPlugin.c MacOS Name B3DAcceleratorPlugin.c MacOS Name B3DAcceleratorPlugin.h MacOS Name b3d.h MacOS Name b3dDraw.c MacOS Name b3dInit.c MacOS Name b3dMain.c MacOS Name b3dRemap.c MacOS Name b3dTypes.h MacOS Name BitBltPlugin.c MacOS Name DropPlugin.c MacOS Name DropPlugin.h MacOS Name DSAPrims.c MacOS Name FFTPlugin.c MacOS Name FilePlugin.c MacOS Name FilePlugin.h MacOS Name FloatArrayPlugin.c MacOS Name JoystickTabletPlugin.c MacOS Name JoystickTabletPlugin.h MacOS Name JPEGReaderPlugin.c MacOS Name Klatt.c MacOS Name LargeIntegers.c MacOS Name Matrix2x3Plugin.c MacOS Name MIDIPlugin.c MacOS Name MidiPlugin.h MacOS Name MiscPrimitivePlugin.c MacOS Name SecurityPlugin.c MacOS Name securityPlugin.h MacOS Name SerialPlugin.c MacOS Name SerialPlugin.h MacOS Name SocketPlugin.c MacOS Name SocketPlugin.h MacOS Name SoundCodecPrims.c MacOS Name SoundCodecPrims.h MacOS Name SoundGenerationPlugin.c MacOS Name SoundGenerationPlugin.h MacOS Name SoundPlugin.c MacOS Name SoundPlugin.h MacOS Name sq.h MacOS Name sqConfig.h MacOS Name sqFilePluginBasicPrims.c MacOS Name sqSoundCodecPluginBasicPrims.c MacOS Name sqMacAsyncFilePrims.c MacOS Name sqMacDragDrop.c MacOS Name sqMacDirectory.c MacOS Name sqMacJoystickAndTablet.c MacOS Name sqMacMIDI.c MacOS Name sqMacNetwork.c MacOS Name sqMacOpenGL.c MacOS Name sqMacOpenGLInfo.c MacOS Name sqOpenGLRenderer.c MacOS Name sqMacOpenGL.h MacOS Name sqOpenGLRenderer.h MacOS Name sqMacSecurity.c MacOS Name sqMacSerialPort.c MacOS Name sqMacSound.c MacOS Name sqMacWindow.c MacOS Name sqNamedPrims.c MacOS Name sqNamedPrims.h MacOS Name sqPlatformSpecific.h MacOS Name Squeak3D.c MacOS Name SqueakApp.r MacOS Name SqueakApp.rsrc MacOS Name sqVirtualMachine.c MacOS Name sqVirtualMachine.h MacOS Name StarSqueakPlugin.c MacOS Name SurfacePlugin.c MacOS Name SurfacePlugin.h MacOS Name ZipPlugin.c MacOS Name OpenTptInetPPC.o MacOS Name OpenTptInternetLib MacOS Name OpenTransportExtnPPC.o MacOS Name OpenTransportLib MacOS Name QuickTimeLib MacOS Name PowerMgrLib MacOS Name DragLib MacOS Name myMacHeaders.pch MacOS Name ThreadsLib MacOS Name NavigationLib MacOS Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name OpenGLLibraryStub MacOS Name OpenGLUtilityStub MacOS Name sqMacFileLogic.c MacOS Name sqMacFileLogic.h MacOS Name DisplayLib MacOS Name sqMacUUID.c MacOS Name UUIDPlugin.c MacOS Name UUIDPlugin.h MacOS Name sqMacInternetConfiguration.c MacOS Name InternetConfigPlugin.c MacOS Name InternetConfigPlugin.h MacOS Name InternetConfigLib MacOS Name USBManagerLib MacOS Name Error.c MacOS Name jcapimin.c MacOS Name jcapistd.c MacOS Name jccoefct.c MacOS Name jccolor.c MacOS Name jcdctmgr.c MacOS Name jchuff.c MacOS Name jchuff.h MacOS Name jcinit.c MacOS Name jcmainct.c MacOS Name jcmarker.c MacOS Name jcmaster.c MacOS Name jcomapi.c MacOS Name jconfig.h MacOS Name jcparam.c MacOS Name jcphuff.c MacOS Name jcprepct.c MacOS Name jcsample.c MacOS Name jctrans.c MacOS Name jdapimin.c MacOS Name jdapistd.c MacOS Name jdatadst.c MacOS Name jdatasrc.c MacOS Name jdcoefct.c MacOS Name jdcolor.c MacOS Name jdct.h MacOS Name jddctmgr.c MacOS Name jdhuff.c MacOS Name jdhuff.h MacOS Name jdinput.c MacOS Name jdmainct.c MacOS Name jdmarker.c MacOS Name jdmaster.c MacOS Name jdmerge.c MacOS Name jdphuff.c MacOS Name jdpostct.c MacOS Name jdsample.c MacOS Name jdtrans.c MacOS Name jerror.c MacOS Name jerror.h MacOS Name jfdctflt.c MacOS Name jfdctfst.c MacOS Name jfdctint.c MacOS Name jidctflt.c MacOS Name jidctfst.c MacOS Name jidctint.c MacOS Name jidctred.c MacOS Name jinclude.h MacOS Name jmemdatadst.c MacOS Name jmemdatasrc.c MacOS Name jmemmgr.c MacOS Name jmemnobs.c MacOS Name jmemsys.h MacOS Name jmorecfg.h MacOS Name jpegint.h MacOS Name jpeglib.h MacOS Name JPEGReadWriter2Plugin.c MacOS Name JPEGReadWriter2Plugin.h MacOS Name jquant1.c MacOS Name jquant2.c MacOS Name jutils.c MacOS Name jversion.h MacOS Name CarbonAccessors.o MacOS Name sqMacExternalPrims.c MacOS Name sqMacExternalPrims.h MacOS Name sqMacImageIO.c MacOS Name sqMacImageIO.h MacOS Name sqMacMain.c MacOS Name sqMacMain.h MacOS Name sqMacMemory.c MacOS Name sqMacMemory.h MacOS Name sqMacTime.c MacOS Name sqMacTime.h MacOS Name sqMacUIAppleEvents.c MacOS Name sqMacUIAppleEvents.h MacOS Name sqMacUIClipBoard.c MacOS Name sqMacUIClipBoard.h MacOS Name sqMacUIConstants.h MacOS Name sqMacUIEvents.h MacOS Name sqMacUIMenuBar.c MacOS Name sqMacUIMenuBar.h MacOS Name sqMacWindow.h MacOS Name osExports.c MacOS Name BMPReadWriterPlugin.c MacOS Name GeniePlugin.c MacOS Name interp os9.c MacOS Name sqMacUIEvents.c MacOS Name sqMacEncoding.c MacOS Name sqMacEncoding.h MacOS Name sqMacHostWindow.c MacOS Name sqMacHostWindow.h MacOS Name HostWindowPlugin.c MacOS Name MacMenubarPlugin.c MacOS Name MenusLib MacOS Name AppearanceLib MacOS Squeak VM PPC Opt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path:platforms:Mac OS: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Libraries: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Headers: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameSqueak VM PPC Opt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000FE7503010000000000001000FE75940 0002000000000000000000000FE74BD000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNone MWCodeGen_68K_a6frames0 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMacOS Toolbox 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources A MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix1 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap1 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termnameSqueakTerminate MWPEF_exportsPragma MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeApplication MWProject_PPC_outfileSqueak VM PPC Opt MWProject_PPC_filecreator1178686292 MWProject_PPC_filetype1095782476 MWProject_PPC_size30000 MWProject_PPC_minsize30000 MWProject_PPC_stacksize80 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library WeakImport Name MSL RuntimePPC.Lib MacOS Library Name MSL SIOUX.PPC.Lib MacOS Library Debug Name AsynchFilePlugin.c MacOS Text Name AsynchFilePlugin.h MacOS Text Name B2DPlugin.c MacOS Text Name b3d.h MacOS Text Name b3dDraw.c MacOS Text Name b3dInit.c MacOS Text Name b3dMain.c MacOS Text Name b3dRemap.c MacOS Text Name b3dTypes.h MacOS Text Name BitBltPlugin.c MacOS Text Name FFTPlugin.c MacOS Text Name FilePlugin.c MacOS Text Name FilePlugin.h MacOS Text Name FloatArrayPlugin.c MacOS Text Name JoystickTabletPlugin.c MacOS Text Name JoystickTabletPlugin.h MacOS Text Name Klatt.c MacOS Text Name LargeIntegers.c MacOS Text Name Matrix2x3Plugin.c MacOS Text Name MIDIPlugin.c MacOS Text Name MidiPlugin.h MacOS Text Name SerialPlugin.c MacOS Text Name SerialPlugin.h MacOS Text Name SocketPlugin.c MacOS Text Name SocketPlugin.h MacOS Text Name SoundCodecPrims.c MacOS Text Name SoundCodecPrims.h MacOS Text Name SoundPlugin.c MacOS Text Name SoundPlugin.h MacOS Text Name sq.h MacOS Text Name sqConfig.h MacOS Text Name sqFilePluginBasicPrims.c MacOS Text Name sqSoundCodecPluginBasicPrims.c MacOS Text Name sqMacAsyncFilePrims.c MacOS Text Name sqMacJoystickAndTablet.c MacOS Text Name sqMacSound.c MacOS Text Name sqMacWindow.c MacOS Text Name sqNamedPrims.c MacOS Text Name sqNamedPrims.h MacOS Text Name sqPlatformSpecific.h MacOS Text Name Squeak3D.c MacOS Text Name SqueakApp.r MacOS Text Name SqueakApp.rsrc MacOS Resource Name sqVirtualMachine.c MacOS Text Name sqVirtualMachine.h MacOS Text Name SurfacePlugin.c MacOS Text Name SurfacePlugin.h MacOS Text Name ZipPlugin.c MacOS Text Name OpenTptInetPPC.o MacOS Library WeakImport Name OpenTptInternetLib MacOS Library WeakImport Name OpenTransportExtnPPC.o MacOS Library WeakImport Name OpenTransportLib MacOS Library WeakImport Name QuickTimeLib MacOS Library WeakImport Name sqMacNetwork.c MacOS Text Name PowerMgrLib MacOS Library WeakImport Name DropPlugin.c MacOS Text Name DropPlugin.h MacOS Text Name sqMacDragDrop.c MacOS Text Name DragLib MacOS Library WeakImport Name myMacHeaders.pch MacOS Text Name DSAPrims.c MacOS Text Name MiscPrimitivePlugin.c MacOS Text Name ADPCMCodecPlugin.c MacOS Text Name SoundGenerationPlugin.c MacOS Text Name SoundGenerationPlugin.h MacOS Text Name ThreadsLib MacOS Library WeakImport Name NavigationLib MacOS Library WeakImport Name SecurityPlugin.c MacOS Text Name securityPlugin.h MacOS Text Name sqMacSecurity.c MacOS Text Name JPEGReaderPlugin.c MacOS Text Name StarSqueakPlugin.c MacOS Text Name sqMacOpenGLInfo.c MacOS Text Name sqMacOpenGL.c MacOS Text Name sqOpenGLRenderer.c MacOS Text Name sqMacOpenGL.h MacOS Text Name sqOpenGLRenderer.h MacOS Text Name OpenGLLibraryStub MacOS Library WeakImport Name OpenGLUtilityStub MacOS Library WeakImport Name sqMacMIDI.c MacOS Text Name sqMacSerialPort.c MacOS Text Name sqMacFileLogic.c MacOS Text Name sqMacFileLogic.h MacOS Text Name DisplayLib MacOS Library WeakImport Name sqMacUUID.c MacOS Text Name UUIDPlugin.c MacOS Text Name UUIDPlugin.h MacOS Text Name sqMacInternetConfiguration.c MacOS Text Name InternetConfigPlugin.c MacOS Text Name InternetConfigPlugin.h MacOS Text Name InternetConfigLib MacOS Library WeakImport Name USBManagerLib MacOS Library WeakImport Name Error.c MacOS Text Name jcapimin.c MacOS Text Name jcapistd.c MacOS Text Name jccoefct.c MacOS Text Name jccolor.c MacOS Text Name jcdctmgr.c MacOS Text Name jchuff.c MacOS Text Name jchuff.h MacOS Text Name jcinit.c MacOS Text Name jcmainct.c MacOS Text Name jcmarker.c MacOS Text Name jcmaster.c MacOS Text Name jcomapi.c MacOS Text Name jconfig.h MacOS Text Name jcparam.c MacOS Text Name jcphuff.c MacOS Text Name jcprepct.c MacOS Text Name jcsample.c MacOS Text Name jctrans.c MacOS Text Name jdapimin.c MacOS Text Name jdapistd.c MacOS Text Name jdatadst.c MacOS Text Name jdatasrc.c MacOS Text Name jdcoefct.c MacOS Text Name jdcolor.c MacOS Text Name jdct.h MacOS Text Name jddctmgr.c MacOS Text Name jdhuff.c MacOS Text Name jdhuff.h MacOS Text Name jdinput.c MacOS Text Name jdmainct.c MacOS Text Name jdmarker.c MacOS Text Name jdmaster.c MacOS Text Name jdmerge.c MacOS Text Name jdphuff.c MacOS Text Name jdpostct.c MacOS Text Name jdsample.c MacOS Text Name jdtrans.c MacOS Text Name jerror.c MacOS Text Name jerror.h MacOS Text Name jfdctflt.c MacOS Text Name jfdctfst.c MacOS Text Name jfdctint.c MacOS Text Name jidctflt.c MacOS Text Name jidctfst.c MacOS Text Name jidctint.c MacOS Text Name jidctred.c MacOS Text Name jinclude.h MacOS Text Name jmemdatadst.c MacOS Text Name jmemdatasrc.c MacOS Text Name jmemmgr.c MacOS Text Name jmemnobs.c MacOS Text Name jmemsys.h MacOS Text Name jmorecfg.h MacOS Text Name jpegint.h MacOS Text Name jpeglib.h MacOS Text Name JPEGReadWriter2Plugin.c MacOS Text Name JPEGReadWriter2Plugin.h MacOS Text Name jquant1.c MacOS Text Name jquant2.c MacOS Text Name jutils.c MacOS Text Name jversion.h MacOS Text Name CarbonAccessors.o MacOS Library Name sqMacExternalPrims.c MacOS Text Name sqMacExternalPrims.h MacOS Text Name sqMacImageIO.c MacOS Text Name sqMacImageIO.h MacOS Text Name sqMacMain.c MacOS Text Name sqMacMain.h MacOS Text Name sqMacMemory.c MacOS Text Name sqMacMemory.h MacOS Text Name sqMacTime.c MacOS Text Name sqMacTime.h MacOS Text Name sqMacUIAppleEvents.c MacOS Text Name sqMacUIAppleEvents.h MacOS Text Name sqMacUIClipBoard.c MacOS Text Name sqMacUIClipBoard.h MacOS Text Name sqMacUIConstants.h MacOS Text Name sqMacUIEvents.c MacOS Text Name sqMacUIEvents.h MacOS Text Name sqMacUIMenuBar.c MacOS Text Name sqMacUIMenuBar.h MacOS Text Name sqMacWindow.h MacOS Text Name osExports.c MacOS Text Name B3DAcceleratorPlugin.c MacOS Text Name B3DAcceleratorPlugin.h MacOS Text Name BMPReadWriterPlugin.c MacOS Text Name GeniePlugin.c MacOS Text Name interp os9.c MacOS Text Name sqMacEncoding.c MacOS Text Name sqMacEncoding.h MacOS Text Name sqMacDirectory.c MacOS Text Name sqMacHostWindow.c MacOS Text Name sqMacHostWindow.h MacOS Text Name HostWindowPlugin.c MacOS Text Name MacMenubarPlugin.c MacOS Text Name MenusLib MacOS Library Name AppearanceLib MacOS Library Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name ADPCMCodecPlugin.c MacOS Name AsynchFilePlugin.c MacOS Name AsynchFilePlugin.h MacOS Name B2DPlugin.c MacOS Name b3d.h MacOS Name b3dDraw.c MacOS Name b3dInit.c MacOS Name b3dMain.c MacOS Name b3dRemap.c MacOS Name b3dTypes.h MacOS Name BitBltPlugin.c MacOS Name DropPlugin.c MacOS Name DropPlugin.h MacOS Name DSAPrims.c MacOS Name FFTPlugin.c MacOS Name FilePlugin.c MacOS Name FilePlugin.h MacOS Name FloatArrayPlugin.c MacOS Name InternetConfigPlugin.c MacOS Name InternetConfigPlugin.h MacOS Name JoystickTabletPlugin.c MacOS Name JoystickTabletPlugin.h MacOS Name JPEGReaderPlugin.c MacOS Name Klatt.c MacOS Name LargeIntegers.c MacOS Name Matrix2x3Plugin.c MacOS Name MIDIPlugin.c MacOS Name MidiPlugin.h MacOS Name MiscPrimitivePlugin.c MacOS Name SecurityPlugin.c MacOS Name securityPlugin.h MacOS Name SerialPlugin.c MacOS Name SerialPlugin.h MacOS Name SocketPlugin.c MacOS Name SocketPlugin.h MacOS Name SoundCodecPrims.c MacOS Name SoundCodecPrims.h MacOS Name SoundGenerationPlugin.c MacOS Name SoundGenerationPlugin.h MacOS Name SoundPlugin.c MacOS Name SoundPlugin.h MacOS Name sq.h MacOS Name sqConfig.h MacOS Name sqFilePluginBasicPrims.c MacOS Name sqSoundCodecPluginBasicPrims.c MacOS Name sqMacAsyncFilePrims.c MacOS Name sqMacDragDrop.c MacOS Name sqMacFileLogic.c MacOS Name sqMacFileLogic.h MacOS Name sqMacInternetConfiguration.c MacOS Name sqMacJoystickAndTablet.c MacOS Name sqMacMIDI.c MacOS Name sqMacNetwork.c MacOS Name sqMacOpenGLInfo.c MacOS Name sqMacSecurity.c MacOS Name sqMacSerialPort.c MacOS Name sqMacSound.c MacOS Name sqMacExternalPrims.c MacOS Name sqMacExternalPrims.h MacOS Name sqMacImageIO.c MacOS Name sqMacImageIO.h MacOS Name sqMacMain.c MacOS Name sqMacMain.h MacOS Name sqMacMemory.c MacOS Name sqMacMemory.h MacOS Name sqMacTime.c MacOS Name sqMacTime.h MacOS Name sqMacUIAppleEvents.c MacOS Name sqMacUIAppleEvents.h MacOS Name sqMacUIClipBoard.c MacOS Name sqMacUIClipBoard.h MacOS Name sqMacUIConstants.h MacOS Name sqMacUIEvents.c MacOS Name sqMacUIEvents.h MacOS Name sqMacUIMenuBar.c MacOS Name sqMacUIMenuBar.h MacOS Name sqMacWindow.h MacOS Name sqMacWindow.c MacOS Name sqMacOpenGL.c MacOS Name sqMacOpenGL.h MacOS Name sqMacUUID.c MacOS Name sqOpenGLRenderer.c MacOS Name sqOpenGLRenderer.h MacOS Name sqNamedPrims.c MacOS Name sqNamedPrims.h MacOS Name sqPlatformSpecific.h MacOS Name Squeak3D.c MacOS Name SqueakApp.r MacOS Name SqueakApp.rsrc MacOS Name sqVirtualMachine.c MacOS Name sqVirtualMachine.h MacOS Name StarSqueakPlugin.c MacOS Name SurfacePlugin.c MacOS Name SurfacePlugin.h MacOS Name UUIDPlugin.c MacOS Name UUIDPlugin.h MacOS Name ZipPlugin.c MacOS Name myMacHeaders.pch MacOS Name DisplayLib MacOS Name DragLib MacOS Name MathLib MacOS Name InternetConfigLib MacOS Name NavigationLib MacOS Name OpenGLLibraryStub MacOS Name OpenGLUtilityStub MacOS Name OpenTptInetPPC.o MacOS Name OpenTptInternetLib MacOS Name OpenTransportExtnPPC.o MacOS Name OpenTransportLib MacOS Name PowerMgrLib MacOS Name QuickTimeLib MacOS Name ThreadsLib MacOS Name USBManagerLib MacOS Name CarbonAccessors.o MacOS Name Error.c MacOS Name jcapimin.c MacOS Name jcapistd.c MacOS Name jccoefct.c MacOS Name jccolor.c MacOS Name jcdctmgr.c MacOS Name jchuff.c MacOS Name jchuff.h MacOS Name jcinit.c MacOS Name jcmainct.c MacOS Name jcmarker.c MacOS Name jcmaster.c MacOS Name jcomapi.c MacOS Name jconfig.h MacOS Name jcparam.c MacOS Name jcphuff.c MacOS Name jcprepct.c MacOS Name jcsample.c MacOS Name jctrans.c MacOS Name jdapimin.c MacOS Name jdapistd.c MacOS Name jdatadst.c MacOS Name jdatasrc.c MacOS Name jdcoefct.c MacOS Name jdcolor.c MacOS Name jdct.h MacOS Name jddctmgr.c MacOS Name jdhuff.c MacOS Name jdhuff.h MacOS Name jdinput.c MacOS Name jdmainct.c MacOS Name jdmarker.c MacOS Name jdmaster.c MacOS Name jdmerge.c MacOS Name jdphuff.c MacOS Name jdpostct.c MacOS Name jdsample.c MacOS Name jdtrans.c MacOS Name jerror.c MacOS Name jerror.h MacOS Name jfdctflt.c MacOS Name jfdctfst.c MacOS Name jfdctint.c MacOS Name jidctflt.c MacOS Name jidctfst.c MacOS Name jidctint.c MacOS Name jidctred.c MacOS Name jinclude.h MacOS Name jmemdatadst.c MacOS Name jmemdatasrc.c MacOS Name jmemmgr.c MacOS Name jmemnobs.c MacOS Name jmemsys.h MacOS Name jmorecfg.h MacOS Name jpegint.h MacOS Name jpeglib.h MacOS Name JPEGReadWriter2Plugin.c MacOS Name JPEGReadWriter2Plugin.h MacOS Name jquant1.c MacOS Name jquant2.c MacOS Name jutils.c MacOS Name jversion.h MacOS Name osExports.c MacOS Name B3DAcceleratorPlugin.c MacOS Name B3DAcceleratorPlugin.h MacOS Name BMPReadWriterPlugin.c MacOS Name GeniePlugin.c MacOS Name interp os9.c MacOS Name sqMacEncoding.c MacOS Name sqMacEncoding.h MacOS Name sqMacDirectory.c MacOS Name sqMacHostWindow.c MacOS Name sqMacHostWindow.h MacOS Name HostWindowPlugin.c MacOS Name MacMenubarPlugin.c MacOS Name MenusLib MacOS Name AppearanceLib MacOS Squeak VM NS Plugin Opt UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path:platforms:Mac OS: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Libraries: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SearchPath Path:platforms:Mac OS:vm:PluginSDK 4.01a: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Headers: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameSqueak VM NS Plugin Opt OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A496E7465726E65743A4D6963726F736F6674 20496E7465726E657420353A496E7465726E6574204578706C6F726572203520 466F6C6465723A496E7465726E6574204578706C6F7265720000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000DA6FE4010000000000001000DA70750 0002000000000000000000000DA6F5E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNone MWCodeGen_68K_a6frames0 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMacOS Toolbox 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint1 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources A MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainnamemain MWLinker_PPC_termnameSqueakTerminate MWPEF_exportsAll MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileNS-Squeak VM 3.0 MWProject_PPC_filecreator1297044307 MWProject_PPC_filetype1314082892 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name MSL SIOUX.PPC.Lib MacOS Library Debug Name AsynchFilePlugin.c MacOS Text Name B2DPlugin.c MacOS Text Name BitBltPlugin.c MacOS Text Name FFTPlugin.c MacOS Text Name FilePlugin.c MacOS Text Name FloatArrayPlugin.c MacOS Text Name JoystickTabletPlugin.c MacOS Text Name Klatt.c MacOS Text Name LargeIntegers.c MacOS Text Name Matrix2x3Plugin.c MacOS Text Name MIDIPlugin.c MacOS Text Name SerialPlugin.c MacOS Text Name SocketPlugin.c MacOS Text Name SoundCodecPrims.c MacOS Text Name SoundPlugin.c MacOS Text Name sqNamedPrims.h MacOS Text Name Squeak3D.c MacOS Text Name ZipPlugin.c MacOS Text Name OpenTptInetPPC.o MacOS Library WeakImport Name OpenTptInternetLib MacOS Library WeakImport Name OpenTransportExtnPPC.o MacOS Library WeakImport Name OpenTransportLib MacOS Library WeakImport Name QuickTimeLib MacOS Library WeakImport Name sqMacNSPlugin.c MacOS Text Name SqueakInBrowser.rsrc MacOS Resource Name PowerMgrLib MacOS Library WeakImport Name DropPlugin.c MacOS Text Name DragLib MacOS Library WeakImport Name myMacHeaders.pch MacOS Text Name DSAPrims.c MacOS Text Name MiscPrimitivePlugin.c MacOS Text Name ADPCMCodecPlugin.c MacOS Text Name SoundGenerationPlugin.c MacOS Text Name ThreadsLib MacOS Library WeakImport Name NavigationLib MacOS Library WeakImport Name SecurityPlugin.c MacOS Text Name JPEGReaderPlugin.c MacOS Text Name StarSqueakPlugin.c MacOS Text Name OpenGLLibraryStub MacOS Library WeakImport Name OpenGLUtilityStub MacOS Library WeakImport Name DisplayLib MacOS Library Name UUIDPlugin.c MacOS Text Name InternetConfigPlugin.c MacOS Text Name InternetConfigLib MacOS Library Name USBManagerLib MacOS Library Name JPEGReadWriter2Plugin.c MacOS Text Name CarbonAccessors.o MacOS Library Name sqMacExternalPrims.c MacOS Text Name sqMacExternalPrims.h MacOS Text Name sqMacImageIO.c MacOS Text Name sqMacImageIO.h MacOS Text Name sqMacMain.c MacOS Text Name sqMacMain.h MacOS Text Name sqMacMemory.c MacOS Text Name sqMacMemory.h MacOS Text Name sqMacTime.c MacOS Text Name sqMacTime.h MacOS Text Name sqMacUIAppleEvents.c MacOS Text Name sqMacUIAppleEvents.h MacOS Text Name sqMacUIClipBoard.c MacOS Text Name sqMacUIClipBoard.h MacOS Text Name sqMacUIConstants.h MacOS Text Name sqMacUIEvents.c MacOS Text Name sqMacUIEvents.h MacOS Text Name sqMacUIMenuBar.c MacOS Text Name sqMacUIMenuBar.h MacOS Text Name npmac.cpp MacOS Text Name jni.h MacOS Text Name jni_md.h MacOS Text Name jri.h MacOS Text Name jritypes.h MacOS Text Name jri_md.h MacOS Text Name npapi.h MacOS Text Name npupp.h MacOS Text Name FilePlugin.h MacOS Text Name AsynchFilePlugin.h MacOS Text Name b3d.h MacOS Text Name b3dDraw.c MacOS Text Name b3dMain.c MacOS Text Name b3dInit.c MacOS Text Name b3dRemap.c MacOS Text Name b3dTypes.h MacOS Text Name DropPlugin.h MacOS Text Name InternetConfigPlugin.h MacOS Text Name MidiPlugin.h MacOS Text Name securityPlugin.h MacOS Text Name SerialPlugin.h MacOS Text Name SocketPlugin.h MacOS Text Name SoundCodecPrims.h MacOS Text Name jcapimin.c MacOS Text Name jcapistd.c MacOS Text Name jccoefct.c MacOS Text Name jccolor.c MacOS Text Name jcdctmgr.c MacOS Text Name jchuff.c MacOS Text Name jchuff.h MacOS Text Name jcinit.c MacOS Text Name jcmainct.c MacOS Text Name jcmarker.c MacOS Text Name jcmaster.c MacOS Text Name jcomapi.c MacOS Text Name jconfig.h MacOS Text Name jcparam.c MacOS Text Name jcphuff.c MacOS Text Name jcprepct.c MacOS Text Name jcsample.c MacOS Text Name jctrans.c MacOS Text Name jdapimin.c MacOS Text Name jdapistd.c MacOS Text Name jdatadst.c MacOS Text Name jdatasrc.c MacOS Text Name jdcoefct.c MacOS Text Name jdcolor.c MacOS Text Name jdct.h MacOS Text Name jddctmgr.c MacOS Text Name jdhuff.c MacOS Text Name jdhuff.h MacOS Text Name jdinput.c MacOS Text Name jdmainct.c MacOS Text Name jdmarker.c MacOS Text Name jdmaster.c MacOS Text Name jdmerge.c MacOS Text Name jdphuff.c MacOS Text Name jdpostct.c MacOS Text Name jdsample.c MacOS Text Name jdtrans.c MacOS Text Name jerror.c MacOS Text Name jerror.h MacOS Text Name jfdctflt.c MacOS Text Name jfdctfst.c MacOS Text Name jfdctint.c MacOS Text Name jidctflt.c MacOS Text Name jidctfst.c MacOS Text Name jidctint.c MacOS Text Name jidctred.c MacOS Text Name jinclude.h MacOS Text Name jmemdatadst.c MacOS Text Name jmemdatasrc.c MacOS Text Name jmemmgr.c MacOS Text Name jmemnobs.c MacOS Text Name jmemsys.h MacOS Text Name jmorecfg.h MacOS Text Name jpegint.h MacOS Text Name jpeglib.h MacOS Text Name JPEGReadWriter2Plugin.h MacOS Text Name jquant1.c MacOS Text Name jquant2.c MacOS Text Name jutils.c MacOS Text Name jversion.h MacOS Text Name Error.c MacOS Text Name JoystickTabletPlugin.h MacOS Text Name SoundGenerationPlugin.h MacOS Text Name SoundPlugin.h MacOS Text Name sq.h MacOS Text Name sqConfig.h MacOS Text Name sqFilePluginBasicPrims.c MacOS Text Name sqSoundCodecPluginBasicPrims.c MacOS Text Name sqMacFileLogic.c MacOS Text Name sqMacAsyncFilePrims.c MacOS Text Name sqMacDirectory.c MacOS Text Name sqMacFileLogic.h MacOS Text Name sqMacInternetConfiguration.c MacOS Text Name sqMacJoystickAndTablet.c MacOS Text Name sqMacDragDrop.c MacOS Text Name sqMacMIDI.c MacOS Text Name sqMacNetwork.c MacOS Text Name sqMacOpenGL.c MacOS Text Name sqMacOpenGL.h MacOS Text Name sqMacOpenGLInfo.c MacOS Text Name sqMacSerialPort.c MacOS Text Name sqMacSecurity.c MacOS Text Name sqMacSound.c MacOS Text Name sqMacUUID.c MacOS Text Name sqNamedPrims.c MacOS Text Name sqPlatformSpecific.h MacOS Text Name sqVirtualMachine.h MacOS Text Name sqVirtualMachine.c MacOS Text Name SurfacePlugin.c MacOS Text Name SurfacePlugin.h MacOS Text Name UUIDPlugin.h MacOS Text Name osExports.c MacOS Text Name sqMacWindow.c MacOS Text Name sqMacWindow.h MacOS Text Name BMPReadWriterPlugin.c MacOS Text Name GeniePlugin.c MacOS Text Name interp os9.c MacOS Text Name sqMacEncoding.c MacOS Text Name sqMacEncoding.h MacOS Text Name sqMacHostWindow.h MacOS Text Name sqMacHostWindow.c MacOS Text Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name ADPCMCodecPlugin.c MacOS Name AsynchFilePlugin.c MacOS Name B2DPlugin.c MacOS Name BitBltPlugin.c MacOS Name DropPlugin.c MacOS Name DSAPrims.c MacOS Name FFTPlugin.c MacOS Name FilePlugin.c MacOS Name FloatArrayPlugin.c MacOS Name JoystickTabletPlugin.c MacOS Name JPEGReaderPlugin.c MacOS Name Klatt.c MacOS Name LargeIntegers.c MacOS Name Matrix2x3Plugin.c MacOS Name MIDIPlugin.c MacOS Name MiscPrimitivePlugin.c MacOS Name SecurityPlugin.c MacOS Name SerialPlugin.c MacOS Name SocketPlugin.c MacOS Name SoundCodecPrims.c MacOS Name SoundGenerationPlugin.c MacOS Name SoundPlugin.c MacOS Name sqMacNSPlugin.c MacOS Name sqNamedPrims.h MacOS Name Squeak3D.c MacOS Name StarSqueakPlugin.c MacOS Name ZipPlugin.c MacOS Name OpenTptInetPPC.o MacOS Name OpenTptInternetLib MacOS Name OpenTransportExtnPPC.o MacOS Name OpenTransportLib MacOS Name QuickTimeLib MacOS Name PowerMgrLib MacOS Name DragLib MacOS Name ThreadsLib MacOS Name SqueakInBrowser.rsrc MacOS Name myMacHeaders.pch MacOS Name NavigationLib MacOS Name OpenGLLibraryStub MacOS Name OpenGLUtilityStub MacOS Name DisplayLib MacOS Name UUIDPlugin.c MacOS Name InternetConfigPlugin.c MacOS Name InternetConfigLib MacOS Name USBManagerLib MacOS Name JPEGReadWriter2Plugin.c MacOS Name CarbonAccessors.o MacOS Name sqMacExternalPrims.c MacOS Name sqMacExternalPrims.h MacOS Name sqMacImageIO.c MacOS Name sqMacImageIO.h MacOS Name sqMacMain.c MacOS Name sqMacMain.h MacOS Name sqMacMemory.c MacOS Name sqMacMemory.h MacOS Name sqMacTime.c MacOS Name sqMacTime.h MacOS Name sqMacUIAppleEvents.c MacOS Name sqMacUIAppleEvents.h MacOS Name sqMacUIClipBoard.c MacOS Name sqMacUIClipBoard.h MacOS Name sqMacUIConstants.h MacOS Name sqMacUIEvents.c MacOS Name sqMacUIEvents.h MacOS Name sqMacUIMenuBar.c MacOS Name sqMacUIMenuBar.h MacOS Name npmac.cpp MacOS Name jni.h MacOS Name jni_md.h MacOS Name jri.h MacOS Name jritypes.h MacOS Name jri_md.h MacOS Name npapi.h MacOS Name npupp.h MacOS Name FilePlugin.h MacOS Name AsynchFilePlugin.h MacOS Name b3d.h MacOS Name b3dDraw.c MacOS Name b3dMain.c MacOS Name b3dInit.c MacOS Name b3dRemap.c MacOS Name b3dTypes.h MacOS Name DropPlugin.h MacOS Name InternetConfigPlugin.h MacOS Name MidiPlugin.h MacOS Name securityPlugin.h MacOS Name SerialPlugin.h MacOS Name SocketPlugin.h MacOS Name SoundCodecPrims.h MacOS Name jcapimin.c MacOS Name jcapistd.c MacOS Name jccoefct.c MacOS Name jccolor.c MacOS Name jcdctmgr.c MacOS Name jchuff.c MacOS Name jchuff.h MacOS Name jcinit.c MacOS Name jcmainct.c MacOS Name jcmarker.c MacOS Name jcmaster.c MacOS Name jcomapi.c MacOS Name jconfig.h MacOS Name jcparam.c MacOS Name jcphuff.c MacOS Name jcprepct.c MacOS Name jcsample.c MacOS Name jctrans.c MacOS Name jdapimin.c MacOS Name jdapistd.c MacOS Name jdatadst.c MacOS Name jdatasrc.c MacOS Name jdcoefct.c MacOS Name jdcolor.c MacOS Name jdct.h MacOS Name jddctmgr.c MacOS Name jdhuff.c MacOS Name jdhuff.h MacOS Name jdinput.c MacOS Name jdmainct.c MacOS Name jdmarker.c MacOS Name jdmaster.c MacOS Name jdmerge.c MacOS Name jdphuff.c MacOS Name jdpostct.c MacOS Name jdsample.c MacOS Name jdtrans.c MacOS Name jerror.c MacOS Name jerror.h MacOS Name jfdctflt.c MacOS Name jfdctfst.c MacOS Name jfdctint.c MacOS Name jidctflt.c MacOS Name jidctfst.c MacOS Name jidctint.c MacOS Name jidctred.c MacOS Name jinclude.h MacOS Name jmemdatadst.c MacOS Name jmemdatasrc.c MacOS Name jmemmgr.c MacOS Name jmemnobs.c MacOS Name jmemsys.h MacOS Name jmorecfg.h MacOS Name jpegint.h MacOS Name jpeglib.h MacOS Name JPEGReadWriter2Plugin.h MacOS Name jquant1.c MacOS Name jquant2.c MacOS Name jutils.c MacOS Name jversion.h MacOS Name Error.c MacOS Name JoystickTabletPlugin.h MacOS Name SoundGenerationPlugin.h MacOS Name SoundPlugin.h MacOS Name sq.h MacOS Name sqConfig.h MacOS Name sqFilePluginBasicPrims.c MacOS Name sqSoundCodecPluginBasicPrims.c MacOS Name sqMacFileLogic.c MacOS Name sqMacAsyncFilePrims.c MacOS Name sqMacDirectory.c MacOS Name sqMacFileLogic.h MacOS Name sqMacInternetConfiguration.c MacOS Name sqMacJoystickAndTablet.c MacOS Name sqMacDragDrop.c MacOS Name sqMacMIDI.c MacOS Name sqMacNetwork.c MacOS Name sqMacOpenGL.c MacOS Name sqMacOpenGL.h MacOS Name sqMacOpenGLInfo.c MacOS Name sqMacSerialPort.c MacOS Name sqMacSecurity.c MacOS Name sqMacSound.c MacOS Name sqMacUUID.c MacOS Name sqNamedPrims.c MacOS Name sqPlatformSpecific.h MacOS Name sqVirtualMachine.h MacOS Name sqVirtualMachine.c MacOS Name SurfacePlugin.c MacOS Name SurfacePlugin.h MacOS Name UUIDPlugin.h MacOS Name osExports.c MacOS Name sqMacWindow.c MacOS Name sqMacWindow.h MacOS Name BMPReadWriterPlugin.c MacOS Name GeniePlugin.c MacOS Name interp os9.c MacOS Name sqMacEncoding.c MacOS Name sqMacEncoding.h MacOS Name sqMacHostWindow.h MacOS Name sqMacHostWindow.c MacOS Squeak VM NS Plugin Debug UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path:platforms:Mac OS: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2:Libraries: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll SearchPath Path:platforms:Mac OS:vm:PluginSDK 4.01a: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath PathOpenGL_SDK_1.2: PathFormatMacOS PathRootAbsolute Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameSqueak VM NS Plugin Debug OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.arr Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pl CompilerMW Perl Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue FileExtension.o CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.ppob Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileExtension.rsrc Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000014C616D69653A4170706C69636174696F6E7320284D616320 4F532039293A496E7465726E6574204578706C6F72657220353A496E7465726E 6574204578706C6F726572000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000DA6FE4010000000000001000DA70750 0002000000000000000000000DA6F5E000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagesfalse AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNone MWCodeGen_68K_a6frames0 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileMacOS Toolbox 68K MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint1 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnamemyMacHeadersPPC MWFrontEnd_C_ansistrict0 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline1 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse0 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources A MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorP750 MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific1 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata1 MWCodeGen_PPC_vrsave1 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainnamemain MWLinker_PPC_termnameSqueakTerminate MWPEF_exportsAll MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads1 MWProject_PPC_typeSharedLibrary MWProject_PPC_outfileNS-Squeak VM 3.0 Debug MWProject_PPC_filecreator1297044307 MWProject_PPC_filetype1314082892 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name InterfaceLib MacOS Library WeakImport Name MathLib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name MSL SIOUX.PPC.Lib MacOS Library Debug Name AsynchFilePlugin.c MacOS Text Debug Name B2DPlugin.c MacOS Text Debug Name BitBltPlugin.c MacOS Text Debug Name FFTPlugin.c MacOS Text Debug Name FilePlugin.c MacOS Text Debug Name FloatArrayPlugin.c MacOS Text Debug Name JoystickTabletPlugin.c MacOS Text Debug Name Klatt.c MacOS Text Debug Name LargeIntegers.c MacOS Text Debug Name Matrix2x3Plugin.c MacOS Text Debug Name MIDIPlugin.c MacOS Text Debug Name SerialPlugin.c MacOS Text Debug Name SocketPlugin.c MacOS Text Debug Name SoundCodecPrims.c MacOS Text Debug Name SoundPlugin.c MacOS Text Debug Name sqNamedPrims.h MacOS Text Name Squeak3D.c MacOS Text Debug Name ZipPlugin.c MacOS Text Debug Name OpenTptInetPPC.o MacOS Library WeakImport Name OpenTptInternetLib MacOS Library WeakImport Name OpenTransportExtnPPC.o MacOS Library WeakImport Name OpenTransportLib MacOS Library WeakImport Name QuickTimeLib MacOS Library WeakImport Name sqMacNSPlugin.c MacOS Text Debug Name SqueakInBrowser.rsrc MacOS Resource Name PowerMgrLib MacOS Library WeakImport Name DropPlugin.c MacOS Text Debug Name DragLib MacOS Library WeakImport Name myMacHeaders.pch MacOS Text Debug Name DSAPrims.c MacOS Text Debug Name MiscPrimitivePlugin.c MacOS Text Debug Name ADPCMCodecPlugin.c MacOS Text Debug Name SoundGenerationPlugin.c MacOS Text Debug Name ThreadsLib MacOS Library WeakImport Name NavigationLib MacOS Library Debug, WeakImport Name SecurityPlugin.c MacOS Text Debug Name JPEGReaderPlugin.c MacOS Text Debug Name StarSqueakPlugin.c MacOS Text Debug Name OpenGLLibraryStub MacOS Library Debug, WeakImport Name OpenGLUtilityStub MacOS Library Debug, WeakImport Name DisplayLib MacOS Library Debug Name UUIDPlugin.c MacOS Text Debug Name InternetConfigPlugin.c MacOS Text Debug Name InternetConfigLib MacOS Library Debug Name USBManagerLib MacOS Library Debug Name JPEGReadWriter2Plugin.c MacOS Text Debug Name CarbonAccessors.o MacOS Library Debug Name sqMacExternalPrims.c MacOS Text Debug Name sqMacExternalPrims.h MacOS Text Name sqMacImageIO.c MacOS Text Debug Name sqMacImageIO.h MacOS Text Name sqMacMain.c MacOS Text Debug Name sqMacMain.h MacOS Text Name sqMacMemory.c MacOS Text Debug Name sqMacMemory.h MacOS Text Name sqMacTime.c MacOS Text Debug Name sqMacTime.h MacOS Text Name sqMacUIAppleEvents.c MacOS Text Debug Name sqMacUIAppleEvents.h MacOS Text Name sqMacUIClipBoard.c MacOS Text Debug Name sqMacUIClipBoard.h MacOS Text Name sqMacUIConstants.h MacOS Text Name sqMacUIEvents.c MacOS Text Debug Name sqMacUIEvents.h MacOS Text Name sqMacUIMenuBar.c MacOS Text Debug Name sqMacUIMenuBar.h MacOS Text Name sqMacWindow.h MacOS Text Name sqMacWindow.c MacOS Text Debug Name sqNamedPrims.c MacOS Text Debug Name sqPlatformSpecific.h MacOS Text Name sqVirtualMachine.c MacOS Text Debug Name sqVirtualMachine.h MacOS Text Name SurfacePlugin.c MacOS Text Debug Name SurfacePlugin.h MacOS Text Name UUIDPlugin.h MacOS Text Name AsynchFilePlugin.h MacOS Text Name b3d.h MacOS Text Name b3dDraw.c MacOS Text Debug Name b3dInit.c MacOS Text Debug Name b3dMain.c MacOS Text Debug Name b3dRemap.c MacOS Text Debug Name b3dTypes.h MacOS Text Name DropPlugin.h MacOS Text Name InternetConfigPlugin.h MacOS Text Name JoystickTabletPlugin.h MacOS Text Name MidiPlugin.h MacOS Text Name securityPlugin.h MacOS Text Name SerialPlugin.h MacOS Text Name SocketPlugin.h MacOS Text Name SoundCodecPrims.h MacOS Text Name SoundGenerationPlugin.h MacOS Text Name SoundPlugin.h MacOS Text Name sq.h MacOS Text Name sqConfig.h MacOS Text Name sqFilePluginBasicPrims.c MacOS Text Debug Name sqSoundCodecPluginBasicPrims.c MacOS Text Debug Name sqMacAsyncFilePrims.c MacOS Text Debug Name sqMacFileLogic.c MacOS Text Debug Name sqMacFileLogic.h MacOS Text Name sqMacDirectory.c MacOS Text Debug Name sqMacInternetConfiguration.c MacOS Text Debug Name sqMacUUID.c MacOS Text Debug Name sqMacSound.c MacOS Text Debug Name sqMacSerialPort.c MacOS Text Debug Name sqMacSecurity.c MacOS Text Debug Name sqMacOpenGLInfo.c MacOS Text Debug Name sqMacOpenGL.h MacOS Text Name sqMacNetwork.c MacOS Text Debug Name sqMacMIDI.c MacOS Text Debug Name sqMacOpenGL.c MacOS Text Debug Name sqMacJoystickAndTablet.c MacOS Text Debug Name sqMacDragDrop.c MacOS Text Debug Name FilePlugin.h MacOS Text Name jcapimin.c MacOS Text Debug Name jcapistd.c MacOS Text Debug Name jccoefct.c MacOS Text Debug Name jccolor.c MacOS Text Debug Name jcdctmgr.c MacOS Text Debug Name jchuff.c MacOS Text Debug Name jchuff.h MacOS Text Name jcinit.c MacOS Text Debug Name jcmainct.c MacOS Text Debug Name jcmarker.c MacOS Text Debug Name jcmaster.c MacOS Text Debug Name jcomapi.c MacOS Text Debug Name jconfig.h MacOS Text Name jcparam.c MacOS Text Debug Name jcphuff.c MacOS Text Debug Name jcprepct.c MacOS Text Debug Name jcsample.c MacOS Text Debug Name jctrans.c MacOS Text Debug Name jdapimin.c MacOS Text Debug Name jdapistd.c MacOS Text Debug Name jdatadst.c MacOS Text Debug Name jdatasrc.c MacOS Text Debug Name jdcoefct.c MacOS Text Debug Name jdcolor.c MacOS Text Debug Name jdct.h MacOS Text Name jddctmgr.c MacOS Text Debug Name jdhuff.c MacOS Text Debug Name jdhuff.h MacOS Text Name jdinput.c MacOS Text Debug Name jdmainct.c MacOS Text Debug Name jdmarker.c MacOS Text Debug Name jdmaster.c MacOS Text Debug Name jdmerge.c MacOS Text Debug Name jdphuff.c MacOS Text Debug Name jdpostct.c MacOS Text Debug Name jdsample.c MacOS Text Debug Name jdtrans.c MacOS Text Debug Name jerror.c MacOS Text Debug Name jerror.h MacOS Text Name jfdctflt.c MacOS Text Debug Name jfdctfst.c MacOS Text Debug Name jfdctint.c MacOS Text Debug Name jidctflt.c MacOS Text Debug Name jidctfst.c MacOS Text Debug Name jidctint.c MacOS Text Debug Name jidctred.c MacOS Text Debug Name jinclude.h MacOS Text Name jmemdatadst.c MacOS Text Debug Name jmemdatasrc.c MacOS Text Debug Name jmemmgr.c MacOS Text Debug Name jmemnobs.c MacOS Text Debug Name jmemsys.h MacOS Text Name jmorecfg.h MacOS Text Name jpegint.h MacOS Text Name jpeglib.h MacOS Text Name JPEGReadWriter2Plugin.h MacOS Text Name jquant1.c MacOS Text Debug Name jquant2.c MacOS Text Debug Name jutils.c MacOS Text Debug Name jversion.h MacOS Text Name Error.c MacOS Text Debug Name npmac.cpp MacOS Text Debug Name jni_md.h MacOS Text Name jni.h MacOS Text Name jri.h MacOS Text Name jritypes.h MacOS Text Name jri_md.h MacOS Text Name npapi.h MacOS Text Name npupp.h MacOS Text Name osExports.c MacOS Text Debug Name BMPReadWriterPlugin.c MacOS Text Debug Name GeniePlugin.c MacOS Text Debug Name interp os9.c MacOS Text Debug Name sqMacEncoding.c MacOS Text Debug Name sqMacEncoding.h MacOS Text Name sqMacHostWindow.h MacOS Text Name sqMacHostWindow.c MacOS Text Debug Name MSL C.PPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name MSL RuntimePPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name AsynchFilePlugin.c MacOS Name B2DPlugin.c MacOS Name BitBltPlugin.c MacOS Name DropPlugin.c MacOS Name FFTPlugin.c MacOS Name FilePlugin.c MacOS Name FloatArrayPlugin.c MacOS Name JoystickTabletPlugin.c MacOS Name Klatt.c MacOS Name LargeIntegers.c MacOS Name Matrix2x3Plugin.c MacOS Name MIDIPlugin.c MacOS Name SerialPlugin.c MacOS Name SocketPlugin.c MacOS Name SoundCodecPrims.c MacOS Name SoundPlugin.c MacOS Name sqMacNSPlugin.c MacOS Name sqNamedPrims.h MacOS Name Squeak3D.c MacOS Name ZipPlugin.c MacOS Name OpenTptInetPPC.o MacOS Name OpenTptInternetLib MacOS Name OpenTransportExtnPPC.o MacOS Name OpenTransportLib MacOS Name QuickTimeLib MacOS Name PowerMgrLib MacOS Name SqueakInBrowser.rsrc MacOS Name DragLib MacOS Name myMacHeaders.pch MacOS Name DSAPrims.c MacOS Name MiscPrimitivePlugin.c MacOS Name ADPCMCodecPlugin.c MacOS Name SoundGenerationPlugin.c MacOS Name ThreadsLib MacOS Name NavigationLib MacOS Name SecurityPlugin.c MacOS Name JPEGReaderPlugin.c MacOS Name StarSqueakPlugin.c MacOS Name OpenGLLibraryStub MacOS Name OpenGLUtilityStub MacOS Name DisplayLib MacOS Name UUIDPlugin.c MacOS Name InternetConfigPlugin.c MacOS Name InternetConfigLib MacOS Name USBManagerLib MacOS Name JPEGReadWriter2Plugin.c MacOS Name CarbonAccessors.o MacOS Name sqMacExternalPrims.c MacOS Name sqMacExternalPrims.h MacOS Name sqMacImageIO.c MacOS Name sqMacImageIO.h MacOS Name sqMacMain.c MacOS Name sqMacMain.h MacOS Name sqMacMemory.c MacOS Name sqMacMemory.h MacOS Name sqMacTime.c MacOS Name sqMacTime.h MacOS Name sqMacUIAppleEvents.c MacOS Name sqMacUIAppleEvents.h MacOS Name sqMacUIClipBoard.c MacOS Name sqMacUIClipBoard.h MacOS Name sqMacUIConstants.h MacOS Name sqMacUIEvents.c MacOS Name sqMacUIEvents.h MacOS Name sqMacUIMenuBar.c MacOS Name sqMacUIMenuBar.h MacOS Name sqMacWindow.h MacOS Name sqMacWindow.c MacOS Name sqNamedPrims.c MacOS Name sqPlatformSpecific.h MacOS Name sqVirtualMachine.c MacOS Name sqVirtualMachine.h MacOS Name SurfacePlugin.c MacOS Name SurfacePlugin.h MacOS Name UUIDPlugin.h MacOS Name AsynchFilePlugin.h MacOS Name b3d.h MacOS Name b3dDraw.c MacOS Name b3dInit.c MacOS Name b3dMain.c MacOS Name b3dRemap.c MacOS Name b3dTypes.h MacOS Name DropPlugin.h MacOS Name InternetConfigPlugin.h MacOS Name JoystickTabletPlugin.h MacOS Name MidiPlugin.h MacOS Name securityPlugin.h MacOS Name SerialPlugin.h MacOS Name SocketPlugin.h MacOS Name SoundCodecPrims.h MacOS Name SoundGenerationPlugin.h MacOS Name SoundPlugin.h MacOS Name sq.h MacOS Name sqConfig.h MacOS Name sqFilePluginBasicPrims.c MacOS Name sqSoundCodecPluginBasicPrims.c MacOS Name sqMacAsyncFilePrims.c MacOS Name sqMacFileLogic.c MacOS Name sqMacFileLogic.h MacOS Name sqMacDirectory.c MacOS Name sqMacInternetConfiguration.c MacOS Name sqMacUUID.c MacOS Name sqMacSound.c MacOS Name sqMacSerialPort.c MacOS Name sqMacSecurity.c MacOS Name sqMacOpenGLInfo.c MacOS Name sqMacOpenGL.h MacOS Name sqMacNetwork.c MacOS Name sqMacMIDI.c MacOS Name sqMacOpenGL.c MacOS Name sqMacJoystickAndTablet.c MacOS Name sqMacDragDrop.c MacOS Name FilePlugin.h MacOS Name jcapimin.c MacOS Name jcapistd.c MacOS Name jccoefct.c MacOS Name jccolor.c MacOS Name jcdctmgr.c MacOS Name jchuff.c MacOS Name jchuff.h MacOS Name jcinit.c MacOS Name jcmainct.c MacOS Name jcmarker.c MacOS Name jcmaster.c MacOS Name jcomapi.c MacOS Name jconfig.h MacOS Name jcparam.c MacOS Name jcphuff.c MacOS Name jcprepct.c MacOS Name jcsample.c MacOS Name jctrans.c MacOS Name jdapimin.c MacOS Name jdapistd.c MacOS Name jdatadst.c MacOS Name jdatasrc.c MacOS Name jdcoefct.c MacOS Name jdcolor.c MacOS Name jdct.h MacOS Name jddctmgr.c MacOS Name jdhuff.c MacOS Name jdhuff.h MacOS Name jdinput.c MacOS Name jdmainct.c MacOS Name jdmarker.c MacOS Name jdmaster.c MacOS Name jdmerge.c MacOS Name jdphuff.c MacOS Name jdpostct.c MacOS Name jdsample.c MacOS Name jdtrans.c MacOS Name jerror.c MacOS Name jerror.h MacOS Name jfdctflt.c MacOS Name jfdctfst.c MacOS Name jfdctint.c MacOS Name jidctflt.c MacOS Name jidctfst.c MacOS Name jidctint.c MacOS Name jidctred.c MacOS Name jinclude.h MacOS Name jmemdatadst.c MacOS Name jmemdatasrc.c MacOS Name jmemmgr.c MacOS Name jmemnobs.c MacOS Name jmemsys.h MacOS Name jmorecfg.h MacOS Name jpegint.h MacOS Name jpeglib.h MacOS Name JPEGReadWriter2Plugin.h MacOS Name jquant1.c MacOS Name jquant2.c MacOS Name jutils.c MacOS Name jversion.h MacOS Name Error.c MacOS Name npmac.cpp MacOS Name jni_md.h MacOS Name jni.h MacOS Name jri.h MacOS Name jritypes.h MacOS Name jri_md.h MacOS Name npapi.h MacOS Name npupp.h MacOS Name osExports.c MacOS Name BMPReadWriterPlugin.c MacOS Name GeniePlugin.c MacOS Name interp os9.c MacOS Name sqMacEncoding.c MacOS Name sqMacEncoding.h MacOS Name sqMacHostWindow.h MacOS Name sqMacHostWindow.c MacOS Squeak VM PPC Debug Squeak VM PPC Opt Squeak VM NS Plugin Opt Squeak VM NS Plugin Debug ANSI Libraries PPC Squeak VM PPC Debug Name MSL C.PPC.Lib MacOS Squeak VM PPC Debug Name MSL SIOUX.PPC.Lib MacOS Mac Libraries Squeak VM PPC Debug Name DisplayLib MacOS Squeak VM PPC Debug Name DragLib MacOS Squeak VM PPC Debug Name InterfaceLib MacOS Squeak VM PPC Debug Name InternetConfigLib MacOS Squeak VM PPC Debug Name NavigationLib MacOS PPC Squeak VM PPC Debug Name AppearanceLib MacOS Squeak VM PPC Debug Name CarbonAccessors.o MacOS Squeak VM PPC Debug Name MathLib MacOS Squeak VM PPC Debug Name MenusLib MacOS Squeak VM PPC Debug Name MSL RuntimePPC.Lib MacOS Squeak VM PPC Debug Name OpenGLLibraryStub MacOS Squeak VM PPC Debug Name OpenGLUtilityStub MacOS Squeak VM PPC Debug Name OpenTptInetPPC.o MacOS Squeak VM PPC Debug Name OpenTptInternetLib MacOS Squeak VM PPC Debug Name OpenTransportExtnPPC.o MacOS Squeak VM PPC Debug Name OpenTransportLib MacOS Squeak VM PPC Debug Name PowerMgrLib MacOS Squeak VM PPC Debug Name USBManagerLib MacOS Squeak VM PPC Debug Name QuickTimeLib MacOS Squeak VM PPC Debug Name ThreadsLib MacOS Resources Squeak VM PPC Debug Name myMacHeaders.pch MacOS Squeak VM PPC Debug Name SqueakApp.r MacOS Squeak VM PPC Debug Name SqueakApp.rsrc MacOS Squeak VM NS Plugin Opt Name SqueakInBrowser.rsrc MacOS Sources Squeak VM PPC Debug Name ADPCMCodecPlugin.c MacOS Squeak VM PPC Debug Name AsynchFilePlugin.c MacOS Squeak VM PPC Debug Name AsynchFilePlugin.h MacOS Squeak VM PPC Debug Name B2DPlugin.c MacOS Squeak VM PPC Debug Name b3d.h MacOS Squeak VM PPC Debug Name B3DAcceleratorPlugin.c MacOS Squeak VM PPC Debug Name B3DAcceleratorPlugin.h MacOS Squeak VM PPC Debug Name b3dDraw.c MacOS Squeak VM PPC Debug Name b3dInit.c MacOS Squeak VM PPC Debug Name b3dMain.c MacOS Squeak VM PPC Debug Name b3dRemap.c MacOS Squeak VM PPC Debug Name b3dTypes.h MacOS Squeak VM PPC Debug Name BitBltPlugin.c MacOS Squeak VM PPC Debug Name BMPReadWriterPlugin.c MacOS Squeak VM PPC Debug Name DropPlugin.c MacOS Squeak VM PPC Debug Name DropPlugin.h MacOS Squeak VM PPC Debug Name DSAPrims.c MacOS Squeak VM PPC Debug Name FFTPlugin.c MacOS Squeak VM PPC Debug Name FilePlugin.c MacOS Squeak VM PPC Debug Name FilePlugin.h MacOS Squeak VM PPC Debug Name FloatArrayPlugin.c MacOS Squeak VM PPC Debug Name GeniePlugin.c MacOS Squeak VM PPC Debug Name HostWindowPlugin.c MacOS Squeak VM PPC Debug Name InternetConfigPlugin.c MacOS Squeak VM PPC Debug Name InternetConfigPlugin.h MacOS Squeak VM PPC Debug Name interp os9.c MacOS Squeak VM NS Plugin Opt Name jni.h MacOS Squeak VM NS Plugin Opt Name jni_md.h MacOS Squeak VM PPC Debug Name JoystickTabletPlugin.c MacOS Squeak VM PPC Debug Name JoystickTabletPlugin.h MacOS JPEGPlugin Squeak VM PPC Debug Name Error.c MacOS Squeak VM PPC Debug Name jcapimin.c MacOS Squeak VM PPC Debug Name jcapistd.c MacOS Squeak VM PPC Debug Name jccoefct.c MacOS Squeak VM PPC Debug Name jccolor.c MacOS Squeak VM PPC Debug Name jcdctmgr.c MacOS Squeak VM PPC Debug Name jchuff.c MacOS Squeak VM PPC Debug Name jchuff.h MacOS Squeak VM PPC Debug Name jcinit.c MacOS Squeak VM PPC Debug Name jcmainct.c MacOS Squeak VM PPC Debug Name jcmarker.c MacOS Squeak VM PPC Debug Name jcmaster.c MacOS Squeak VM PPC Debug Name jcomapi.c MacOS Squeak VM PPC Opt Name jconfig.h MacOS Squeak VM PPC Debug Name jconfig.h MacOS Squeak VM PPC Debug Name jcparam.c MacOS Squeak VM PPC Debug Name jcphuff.c MacOS Squeak VM PPC Debug Name jcprepct.c MacOS Squeak VM PPC Debug Name jcsample.c MacOS Squeak VM PPC Debug Name jctrans.c MacOS Squeak VM PPC Debug Name jdapimin.c MacOS Squeak VM PPC Debug Name jdapistd.c MacOS Squeak VM PPC Debug Name jdatadst.c MacOS Squeak VM PPC Debug Name jdatasrc.c MacOS Squeak VM PPC Debug Name jdcoefct.c MacOS Squeak VM PPC Debug Name jdcolor.c MacOS Squeak VM PPC Debug Name jdct.h MacOS Squeak VM PPC Debug Name jddctmgr.c MacOS Squeak VM PPC Debug Name jdhuff.c MacOS Squeak VM PPC Debug Name jdhuff.h MacOS Squeak VM PPC Debug Name jdinput.c MacOS Squeak VM PPC Debug Name jdmainct.c MacOS Squeak VM PPC Debug Name jdmarker.c MacOS Squeak VM PPC Debug Name jdmaster.c MacOS Squeak VM PPC Debug Name jdmerge.c MacOS Squeak VM PPC Debug Name jdphuff.c MacOS Squeak VM PPC Debug Name jdpostct.c MacOS Squeak VM PPC Debug Name jdsample.c MacOS Squeak VM PPC Debug Name jdtrans.c MacOS Squeak VM PPC Debug Name jerror.c MacOS Squeak VM PPC Debug Name jerror.h MacOS Squeak VM PPC Debug Name jfdctflt.c MacOS Squeak VM PPC Debug Name jfdctfst.c MacOS Squeak VM PPC Debug Name jfdctint.c MacOS Squeak VM PPC Debug Name jidctflt.c MacOS Squeak VM PPC Debug Name jidctfst.c MacOS Squeak VM PPC Debug Name jidctint.c MacOS Squeak VM PPC Debug Name jidctred.c MacOS Squeak VM PPC Debug Name jinclude.h MacOS Squeak VM PPC Debug Name jmemdatadst.c MacOS Squeak VM PPC Debug Name jmemdatasrc.c MacOS Squeak VM PPC Debug Name jmemmgr.c MacOS Squeak VM PPC Debug Name jmemnobs.c MacOS Squeak VM PPC Debug Name jmemsys.h MacOS Squeak VM PPC Debug Name jmorecfg.h MacOS Squeak VM PPC Debug Name jpegint.h MacOS Squeak VM PPC Debug Name jpeglib.h MacOS Squeak VM PPC Debug Name JPEGReadWriter2Plugin.c MacOS Squeak VM PPC Debug Name JPEGReadWriter2Plugin.h MacOS Squeak VM PPC Debug Name jquant1.c MacOS Squeak VM PPC Debug Name jquant2.c MacOS Squeak VM PPC Debug Name jutils.c MacOS Squeak VM PPC Debug Name jversion.h MacOS Squeak VM PPC Debug Name JPEGReaderPlugin.c MacOS Squeak VM NS Plugin Opt Name jri.h MacOS Squeak VM NS Plugin Opt Name jritypes.h MacOS Squeak VM NS Plugin Opt Name jri_md.h MacOS Squeak VM PPC Debug Name Klatt.c MacOS Squeak VM PPC Debug Name LargeIntegers.c MacOS Squeak VM PPC Debug Name MacMenubarPlugin.c MacOS Squeak VM PPC Debug Name Matrix2x3Plugin.c MacOS Squeak VM PPC Debug Name MIDIPlugin.c MacOS Squeak VM PPC Debug Name MidiPlugin.h MacOS Squeak VM PPC Debug Name MiscPrimitivePlugin.c MacOS Squeak VM NS Plugin Opt Name npapi.h MacOS Squeak VM NS Plugin Opt Name npmac.cpp MacOS Squeak VM NS Plugin Opt Name npupp.h MacOS Squeak VM PPC Debug Name osExports.c MacOS Squeak VM PPC Debug Name SecurityPlugin.c MacOS Squeak VM PPC Debug Name securityPlugin.h MacOS Squeak VM PPC Debug Name SerialPlugin.c MacOS Squeak VM PPC Debug Name SerialPlugin.h MacOS Squeak VM PPC Debug Name SocketPlugin.c MacOS Squeak VM PPC Debug Name SocketPlugin.h MacOS Squeak VM PPC Debug Name SoundCodecPrims.c MacOS Squeak VM PPC Debug Name SoundCodecPrims.h MacOS Squeak VM PPC Debug Name SoundGenerationPlugin.c MacOS Squeak VM PPC Debug Name SoundGenerationPlugin.h MacOS Squeak VM PPC Debug Name SoundPlugin.c MacOS Squeak VM PPC Debug Name SoundPlugin.h MacOS Squeak VM PPC Debug Name sq.h MacOS Squeak VM PPC Debug Name sqConfig.h MacOS Squeak VM PPC Debug Name sqFilePluginBasicPrims.c MacOS Squeak VM PPC Debug Name sqMacAsyncFilePrims.c MacOS Squeak VM PPC Debug Name sqMacDirectory.c MacOS Squeak VM PPC Debug Name sqMacDragDrop.c MacOS Squeak VM PPC Debug Name sqMacEncoding.c MacOS Squeak VM PPC Debug Name sqMacEncoding.h MacOS Squeak VM PPC Debug Name sqMacExternalPrims.c MacOS Squeak VM PPC Debug Name sqMacExternalPrims.h MacOS Squeak VM PPC Debug Name sqMacFileLogic.c MacOS Squeak VM PPC Debug Name sqMacFileLogic.h MacOS Squeak VM PPC Debug Name sqMacHostWindow.c MacOS Squeak VM PPC Debug Name sqMacHostWindow.h MacOS Squeak VM PPC Debug Name sqMacImageIO.c MacOS Squeak VM PPC Debug Name sqMacImageIO.h MacOS Squeak VM PPC Debug Name sqMacInternetConfiguration.c MacOS Squeak VM PPC Debug Name sqMacJoystickAndTablet.c MacOS Squeak VM PPC Debug Name sqMacMain.c MacOS Squeak VM PPC Debug Name sqMacMain.h MacOS Squeak VM PPC Debug Name sqMacMemory.c MacOS Squeak VM PPC Debug Name sqMacMemory.h MacOS Squeak VM PPC Debug Name sqMacMIDI.c MacOS Squeak VM PPC Debug Name sqMacNetwork.c MacOS Squeak VM NS Plugin Opt Name sqMacNSPlugin.c MacOS Squeak VM PPC Debug Name sqMacOpenGL.c MacOS Squeak VM PPC Debug Name sqMacOpenGL.h MacOS Squeak VM PPC Debug Name sqMacOpenGLInfo.c MacOS Squeak VM PPC Debug Name sqMacSecurity.c MacOS Squeak VM PPC Debug Name sqMacSerialPort.c MacOS Squeak VM PPC Debug Name sqMacSound.c MacOS Squeak VM PPC Debug Name sqMacTime.c MacOS Squeak VM PPC Debug Name sqMacTime.h MacOS Squeak VM PPC Debug Name sqMacUIAppleEvents.c MacOS Squeak VM PPC Debug Name sqMacUIAppleEvents.h MacOS Squeak VM PPC Debug Name sqMacUIClipBoard.c MacOS Squeak VM PPC Debug Name sqMacUIClipBoard.h MacOS Squeak VM PPC Debug Name sqMacUIConstants.h MacOS Squeak VM PPC Debug Name sqMacUIEvents.c MacOS Squeak VM PPC Debug Name sqMacUIEvents.h MacOS Squeak VM PPC Debug Name sqMacUIMenuBar.c MacOS Squeak VM PPC Debug Name sqMacUIMenuBar.h MacOS Squeak VM PPC Debug Name sqMacUUID.c MacOS Squeak VM PPC Debug Name sqMacWindow.c MacOS Squeak VM PPC Debug Name sqMacWindow.h MacOS Squeak VM PPC Debug Name sqNamedPrims.c MacOS Squeak VM PPC Debug Name sqNamedPrims.h MacOS Squeak VM PPC Debug Name sqOpenGLRenderer.c MacOS Squeak VM PPC Debug Name sqOpenGLRenderer.h MacOS Squeak VM PPC Debug Name sqPlatformSpecific.h MacOS Squeak VM PPC Debug Name sqSoundCodecPluginBasicPrims.c MacOS Squeak VM PPC Debug Name Squeak3D.c MacOS Squeak VM PPC Debug Name sqVirtualMachine.c MacOS Squeak VM PPC Debug Name sqVirtualMachine.h MacOS Squeak VM PPC Debug Name StarSqueakPlugin.c MacOS Squeak VM PPC Debug Name SurfacePlugin.c MacOS Squeak VM PPC Debug Name SurfacePlugin.h MacOS Squeak VM PPC Debug Name UUIDPlugin.c MacOS Squeak VM PPC Debug Name UUIDPlugin.h MacOS Squeak VM PPC Debug Name ZipPlugin.c MacOS ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/GeneratePreviewForURL.c ================================================ #include #include #include /* no preview*/ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { return noErr; } void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview) { } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/GenerateThumbnailForURL.c ================================================ /* Copyright (c) 2009 Bert Freudenberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include UInt32 littleEndianUInt32(FILE *stream) { UInt32 n; fread(&n, 4, 1, stream); return CFSwapInt32LittleToHost(n); } UInt16 littleEndianUInt16(FILE *stream) { UInt16 n; fread(&n, 2, 1, stream); return CFSwapInt16LittleToHost(n); } /* We look for "thumbnail.png" in the zip which supposedly is a Squeak Etoys project file. We assume there is no comment appended (so the zip's EOCD is at a fixed offset from the file end) and the thumb is stored uncompressed (so we can pass its data directly to QuickLook) */ OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) { char filename[FILENAME_MAX]; CFURLGetFileSystemRepresentation (url, false, (UInt8*) filename, sizeof(filename)); //printf("Filename: %s\n", filename); FILE *stream= fopen(filename, "r"); char signature[4]; /* Assuming no zip file comment, the End of Central Directory signature starts 22 bytes from the end of the file */ fseek(stream, -22, SEEK_END); fread(&signature, 4, 1, stream); if (0 == strncmp(signature, "PK\005\006", 4)) { fseek(stream, 8, SEEK_CUR); UInt32 centralDirectorySize= littleEndianUInt32(stream); /* go back to start of Central Directory */ fseek(stream, -16-centralDirectorySize, SEEK_CUR); do { /* for each Central Directory entry */ fread(&signature, 4, 1, stream); if (0 == strncmp(signature, "PK\001\002", 4)) { /* parse member */ fseek(stream, 20, SEEK_CUR); UInt32 uncompressedSize= littleEndianUInt32(stream); UInt16 memberNameLength= littleEndianUInt16(stream); UInt16 extraFieldLength= littleEndianUInt16(stream); UInt16 commentLength= littleEndianUInt16(stream); fseek(stream, 8, SEEK_CUR); UInt32 memberPos= littleEndianUInt32(stream); char memberName[FILENAME_MAX]; fread(&memberName, 1, memberNameLength, stream); memberName[memberNameLength]= '\000'; fseek(stream, extraFieldLength + commentLength, SEEK_CUR); //printf("name: %s\n", memberName); //printf("offs: 0x%x\n", memberPos); //printf("size: %i\n", uncompressedSize); if (0 == strcmp(memberName, "thumbnail.png")) { char thumbBytes[20000]; if (uncompressedSize > sizeof(thumbBytes)) goto done; fseek(stream, memberPos+30+memberNameLength+extraFieldLength, SEEK_SET); /* assume thumbnail is stored unencrypted and uncompressed */ fread(thumbBytes, uncompressedSize, 1, stream); if (0 == strncmp(thumbBytes, "\211PNG", 4)) { /* it worked! */ //printf("PNG found!\n"); CFDataRef thumbData= CFDataCreate(kCFAllocatorDefault, (UInt8*)thumbBytes, uncompressedSize); QLThumbnailRequestSetImageWithData(thumbnail, thumbData, NULL); } /* whether it worked or not, we're done here */ goto done; } } else { /* End of Central Directory */ goto done; } } while (true); } else { //printf("End of Central Directory not found\n"); } done: fclose(stream); return noErr; } void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail) { } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeRole QLGenerator LSItemContentTypes org.squeak.project CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier org.squeak.qlgenerator.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundleShortVersionString 1 CFBundleVersion 1.0 CFPlugInDynamicRegisterFunction CFPlugInDynamicRegistration NO CFPlugInFactories FFD8E9C9-4777-4502-811C-15503F9D31EA QuickLookGeneratorPluginFactory CFPlugInTypes 5E2D9680-5022-40FA-B806-43349622E5B9 FFD8E9C9-4777-4502-811C-15503F9D31EA CFPlugInUnloadFunction QLNeedsToBeRunInMainThread QLPreviewHeight 0 QLPreviewWidth 0 QLSupportsConcurrentRequests QLThumbnailMinimumSize 17 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj/bert.mode1v3 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module XCProjectFormatConflictsModule Name Project Format Conflicts List BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console BundleLoadPath MaxInstances n Module XCSnapshotModule Name Snapshots Tool BundlePath /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources Description DefaultDescriptionKey DockingSystemVisible Extension mode1v3 FavBarConfig PBXProjectModuleGUID 4C42C465103B6D9C0059C21A XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1v3 MajorVersion 33 MinorVersion 0 Name Default Notifications OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-combo-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-goOrGo com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 089C166AFE841209C02AAC07 08FB77AFFE84173DC02AAC07 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 1 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 445}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 463}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 1016 596 788 504 0 0 1920 1178 Module PBXSmartGroupTreeModule Proportion 203pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel GeneratePreviewForURL.c PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel GeneratePreviewForURL.c _historyCapacity 0 bookmark 4C6ADC2E103C092B004659EE history 4CCA1982103B72E400C2C8C6 4CCA1987103B72E400C2C8C6 prevStack 4CCA1984103B72E400C2C8C6 4CCA1985103B72E400C2C8C6 SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {580, 285}} RubberWindowFrame 1016 596 788 504 0 0 1920 1178 Module PBXNavigatorGroup Proportion 285pt BecomeActive ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 290}, {580, 173}} RubberWindowFrame 1016 596 788 504 0 0 1920 1178 Module XCDetailModule Proportion 173pt Proportion 580pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 4C6ADC2B103C092B004659EE 1CE0B1FE06471DED0097A5F4 4C6ADC2C103C092B004659EE 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.defaultV3 ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.shortV3 PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 0.0 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 1 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList 4C42C457103B65B50059C21A /Users/bert/Squeakland-SVN/os-x/xcode/SqueakQL/SqueakQL.xcodeproj WindowString 1016 596 788 504 0 0 1920 1178 WindowToolsV3 FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {500, 0}} RubberWindowFrame 976 530 500 500 0 0 1920 1178 Module PBXNavigatorGroup Proportion 0pt ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1011 GeometryConfiguration Frame {{0, 5}, {500, 454}} RubberWindowFrame 976 530 500 500 0 0 1920 1178 Module PBXBuildResultsModule Proportion 454pt Proportion 459pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 4C42C457103B65B50059C21A 4C6ADC2D103C092B004659EE 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.buildV3 WindowString 976 530 500 500 0 0 1920 1178 WindowToolGUID 4C42C457103B65B50059C21A WindowToolIsVisible Identifier windowTool.debugger Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {317, 164}} {{317, 0}, {377, 164}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {694, 164}} {{0, 164}, {694, 216}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {694, 380}} RubberWindowFrame 321 238 694 422 0 0 1440 878 Module PBXDebugSessionModule Proportion 100% Proportion 100% Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible 1 TableOfContents 1CD10A99069EF8BA00B06720 1C0AD2AB069F1E9B00FABCE6 1C162984064C10D400B95A72 1C0AD2AC069F1E9B00FABCE6 ToolbarConfiguration xcode.toolbar.config.debugV3 WindowString 321 238 694 422 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible 0 Identifier windowTool.find Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CD0528D0623707200166675 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {781, 167}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXNavigatorGroup Proportion 781pt Proportion 50% BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{8, 0}, {773, 254}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXProjectFindModule Proportion 50% Proportion 428pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible 1 TableOfContents 1C530D57069F1CE1000CFCEE 1C530D58069F1CE1000CFCEE 1C530D59069F1CE1000CFCEE 1CDD528C0622207200134675 1C530D5A069F1CE1000CFCEE 1CE0B1FE06471DED0097A5F4 1CD0528E0623707200166675 WindowString 62 385 781 470 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible 0 Identifier MENUSEPARATOR Identifier windowTool.debuggerConsole Layout Dock BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {650, 250}} RubberWindowFrame 516 632 650 250 0 0 1680 1027 Module PBXDebugCLIModule Proportion 209pt Proportion 209pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible 1 TableOfContents 1C78EAAD065D492600B07095 1C78EAAE065D492600B07095 1C78EAAC065D492600B07095 ToolbarConfiguration xcode.toolbar.config.consoleV3 WindowString 650 41 650 250 0 0 1280 1002 WindowToolGUID 1C78EAAD065D492600B07095 WindowToolIsVisible 0 Identifier windowTool.snapshots Layout Dock Module XCSnapshotModule Proportion 100% Proportion 100% Name Snapshots ServiceClasses XCSnapshotModule StatusbarIsVisible Yes ToolbarConfiguration xcode.toolbar.config.snapshots WindowString 315 824 300 550 0 0 1440 878 WindowToolIsVisible Yes Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.0950012207031 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints IsVertical 0 Layout Dock BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C77FABC04509CD000000102 PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided no PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 168 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 1C77FABC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {168, 350}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 0 GeometryConfiguration Frame {{0, 0}, {185, 368}} GroupTreeTableConfiguration MainColumn 168 RubberWindowFrame 315 424 744 409 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 185pt ContentConfiguration PBXProjectModuleGUID 1CA1AED706398EBD00589147 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{190, 0}, {554, 368}} RubberWindowFrame 315 424 744 409 0 0 1440 878 Module XCDetailModule Proportion 554pt Proportion 368pt MajorVersion 3 MinorVersion 0 Name Breakpoints ServiceClasses PBXSmartGroupTreeModule XCDetailModule StatusbarIsVisible 1 TableOfContents 1CDDB66807F98D9800BB5817 1CDDB66907F98D9800BB5817 1CE0B1FE06471DED0097A5F4 1CA1AED706398EBD00589147 ToolbarConfiguration xcode.toolbar.config.breakpointsV3 WindowString 315 424 744 409 0 0 1440 878 WindowToolGUID 1CDDB66807F98D9800BB5817 WindowToolIsVisible 1 Identifier windowTool.debugAnimator Layout Dock Module PBXNavigatorGroup Proportion 100% Proportion 100% Name Debug Visualizer ServiceClasses PBXNavigatorGroup StatusbarIsVisible 1 ToolbarConfiguration xcode.toolbar.config.debugAnimatorV3 WindowString 100 100 700 500 0 0 1280 1002 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.projectFormatConflicts Layout Dock Module XCProjectFormatConflictsModule Proportion 100% Proportion 100% Name Project Format Conflicts ServiceClasses XCProjectFormatConflictsModule StatusbarIsVisible 0 WindowContentMinSize 450 300 WindowString 50 850 472 307 0 0 1440 877 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 Identifier windowTool.refactoring IncludeInToolsMenu 0 Layout Dock BecomeActive 1 GeometryConfiguration Frame {0, 0}, {500, 335} RubberWindowFrame {0, 0}, {500, 335} Module XCRefactoringModule Proportion 100% Proportion 100% Name Refactoring ServiceClasses XCRefactoringModule WindowString 200 200 500 356 0 0 1920 1200 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj/bert.pbxuser ================================================ // !$*UTF8*$! { 089C1669FE841209C02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; activeSDKPreference = macosx10.5; activeTarget = 8D57630D048677EA00EA77CD /* SqueakQL */; codeSenseManager = 4C42C428103B1B040059C21A /* Code sense */; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 341, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 272369929; PBXWorkspaceStateSaveDate = 272369929; }; perUserProjectItems = { 4C6ADC2E103C092B004659EE /* PBXTextBookmark */ = 4C6ADC2E103C092B004659EE /* PBXTextBookmark */; 4CCA1982103B72E400C2C8C6 /* PBXTextBookmark */ = 4CCA1982103B72E400C2C8C6 /* PBXTextBookmark */; 4CCA1984103B72E400C2C8C6 /* PBXTextBookmark */ = 4CCA1984103B72E400C2C8C6 /* PBXTextBookmark */; 4CCA1985103B72E400C2C8C6 /* PBXTextBookmark */ = 4CCA1985103B72E400C2C8C6 /* PBXTextBookmark */; 4CCA1987103B72E400C2C8C6 /* PBXTextBookmark */ = 4CCA1987103B72E400C2C8C6 /* PBXTextBookmark */; }; sourceControlManager = 4C42C427103B1B040059C21A /* Source Control */; userBuildSettings = { }; }; 089C167EFE841241C02AAC07 /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1197, 649}}"; sepNavSelRange = "{194, 0}"; sepNavVisRange = "{0, 198}"; sepNavWindowFrame = "{{268, 165}, {1256, 777}}"; }; }; 08FB77B6FE84183AC02AAC07 /* main.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {775, 3796}}"; sepNavSelRange = "{3122, 54}"; sepNavVisRange = "{2713, 594}"; }; }; 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1041, 253}}"; sepNavSelRange = "{131, 0}"; sepNavVisRange = "{0, 387}"; sepNavWindowFrame = "{{275, 255}, {1256, 777}}"; }; }; 4C42C427103B1B040059C21A /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; }; 4C42C428103B1B040059C21A /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 4C6ADC2E103C092B004659EE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 5"; rLen = 0; rLoc = 131; rType = 0; vrLen = 387; vrLoc = 0; }; 4CCA1982103B72E400C2C8C6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 7"; rLen = 0; rLoc = 3836; rType = 0; vrLen = 398; vrLoc = 0; }; 4CCA1984103B72E400C2C8C6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 98"; rLen = 0; rLoc = 3836; rType = 0; vrLen = 439; vrLoc = 3376; }; 4CCA1985103B72E400C2C8C6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 5"; rLen = 0; rLoc = 131; rType = 0; vrLen = 387; vrLoc = 0; }; 4CCA1987103B72E400C2C8C6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 5"; rLen = 0; rLoc = 131; rType = 0; vrLen = 387; vrLoc = 0; }; 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1197, 1776}}"; sepNavSelRange = "{3254, 0}"; sepNavVisRange = "{2748, 1198}"; sepNavWindowFrame = "{{618, 121}, {1256, 777}}"; }; }; 8D57630D048677EA00EA77CD /* SqueakQL */ = { activeExec = 0; }; 8D576317048677EA00EA77CD /* Info.plist */ = { uiCtxt = { sepNavWindowFrame = "{{291, 144}, {1256, 777}}"; }; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj/johnmci.mode1v3 ================================================ ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module XCProjectFormatConflictsModule Name Project Format Conflicts List BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console BundleLoadPath MaxInstances n Module XCSnapshotModule Name Snapshots Tool BundlePath /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources Description DefaultDescriptionKey DockingSystemVisible Extension mode1v3 FavBarConfig PBXProjectModuleGUID 943801FB103CAFFE00A1E999 XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1v3 MajorVersion 33 MinorVersion 0 Name Default Notifications XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusErrorsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusErrorsKey 2 XCObserverAutoDisconnectKey XCObserverDefintionKey PBXStatusWarningsKey 0 XCObserverFactoryKey XCPerspectivesSpecificationIdentifier XCObserverGUIDKey XCObserverProjectIdentifier XCObserverNotificationKey PBXStatusBuildStateMessageNotification XCObserverTargetKey XCMainBuildResultsModuleGUID XCObserverTriggerKey awakenModuleWithObserver: XCObserverValidationKey PBXStatusWarningsKey 2 OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup active-platform-popup active-buildstyle-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-goOrGo com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 089C166AFE841209C02AAC07 08FB77AFFE84173DC02AAC07 089C167CFE841241C02AAC07 19C28FB6FE9D52B211CA2CBB 1C37FBAC04509CD000000102 94F4B5D4103DA39B00AB2C19 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 10 9 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 795}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 813}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 89 -89 1191 854 0 0 1680 1028 Module PBXSmartGroupTreeModule Proportion 203pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel GenerateThumbnailForURL.c PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel GenerateThumbnailForURL.c _historyCapacity 0 bookmark 94F4B5D6103DA3E200AB2C19 history 94380303103CB0AE00A1E999 94923091103D043800DBE2CE 949230A8103D046700DBE2CE 94F4B5B7103DA33F00AB2C19 94F4B5B8103DA33F00AB2C19 prevStack 94380305103CB0AE00A1E999 94380306103CB0AE00A1E999 94923096103D043800DBE2CE 94923097103D043800DBE2CE 949230AA103D046700DBE2CE 94F4B5B9103DA33F00AB2C19 94F4B5BA103DA33F00AB2C19 SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {983, 635}} RubberWindowFrame 89 -89 1191 854 0 0 1680 1028 Module PBXNavigatorGroup Proportion 635pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 640}, {983, 173}} RubberWindowFrame 89 -89 1191 854 0 0 1680 1028 Module XCDetailModule Proportion 173pt Proportion 983pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents 94F4B5BC103DA33F00AB2C19 1CE0B1FE06471DED0097A5F4 94F4B5BD103DA33F00AB2C19 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.defaultV3 ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.shortV3 PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 272474930.71802098 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 2 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList /Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj WindowString 89 -89 1191 854 0 0 1680 1028 WindowToolsV3 FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {500, 218}} RubberWindowFrame 467 386 500 500 0 0 1680 1028 Module PBXNavigatorGroup Proportion 218pt ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1013 GeometryConfiguration Frame {{0, 223}, {500, 236}} RubberWindowFrame 467 386 500 500 0 0 1680 1028 Module PBXBuildResultsModule Proportion 236pt Proportion 459pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents 9438030A103CB0AE00A1E999 9492309A103D043800DBE2CE 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.buildV3 WindowString 467 386 500 500 0 0 1680 1028 WindowToolGUID 9438030A103CB0AE00A1E999 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {316, 185}} {{316, 0}, {378, 185}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {694, 185}} {{0, 185}, {694, 196}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {694, 381}} PBXDebugSessionStackFrameViewKey DebugVariablesTableConfiguration Name 120 Value 85 Summary 148 Frame {{316, 0}, {378, 185}} RubberWindowFrame 467 464 694 422 0 0 1680 1028 RubberWindowFrame 467 464 694 422 0 0 1680 1028 Module PBXDebugSessionModule Proportion 381pt Proportion 381pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 9492309B103D043800DBE2CE 1C162984064C10D400B95A72 9492309C103D043800DBE2CE 9492309D103D043800DBE2CE 9492309E103D043800DBE2CE 9492309F103D043800DBE2CE 949230A0103D043800DBE2CE ToolbarConfiguration xcode.toolbar.config.debugV3 WindowString 467 464 694 422 0 0 1680 1028 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible Identifier windowTool.find Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CD0528D0623707200166675 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {781, 167}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXNavigatorGroup Proportion 781pt Proportion 50% BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{8, 0}, {773, 254}} RubberWindowFrame 62 385 781 470 0 0 1440 878 Module PBXProjectFindModule Proportion 50% Proportion 428pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible 1 TableOfContents 1C530D57069F1CE1000CFCEE 1C530D58069F1CE1000CFCEE 1C530D59069F1CE1000CFCEE 1CDD528C0622207200134675 1C530D5A069F1CE1000CFCEE 1CE0B1FE06471DED0097A5F4 1CD0528E0623707200166675 WindowString 62 385 781 470 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible 0 Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {1076, 780}} RubberWindowFrame 467 65 1076 821 0 0 1680 1028 Module PBXDebugCLIModule Proportion 780pt Proportion 780pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 1C78EAAD065D492600B07095 949230A1103D043800DBE2CE 1C78EAAC065D492600B07095 ToolbarConfiguration xcode.toolbar.config.consoleV3 WindowString 467 65 1076 821 0 0 1680 1028 WindowToolGUID 1C78EAAD065D492600B07095 WindowToolIsVisible Identifier windowTool.snapshots Layout Dock Module XCSnapshotModule Proportion 100% Proportion 100% Name Snapshots ServiceClasses XCSnapshotModule StatusbarIsVisible Yes ToolbarConfiguration xcode.toolbar.config.snapshots WindowString 315 824 300 550 0 0 1440 878 WindowToolIsVisible Yes Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.0950012207031 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints IsVertical 0 Layout Dock BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C77FABC04509CD000000102 PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided no PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 168 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 1C77FABC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {168, 350}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 0 GeometryConfiguration Frame {{0, 0}, {185, 368}} GroupTreeTableConfiguration MainColumn 168 RubberWindowFrame 315 424 744 409 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 185pt ContentConfiguration PBXProjectModuleGUID 1CA1AED706398EBD00589147 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{190, 0}, {554, 368}} RubberWindowFrame 315 424 744 409 0 0 1440 878 Module XCDetailModule Proportion 554pt Proportion 368pt MajorVersion 3 MinorVersion 0 Name Breakpoints ServiceClasses PBXSmartGroupTreeModule XCDetailModule StatusbarIsVisible 1 TableOfContents 1CDDB66807F98D9800BB5817 1CDDB66907F98D9800BB5817 1CE0B1FE06471DED0097A5F4 1CA1AED706398EBD00589147 ToolbarConfiguration xcode.toolbar.config.breakpointsV3 WindowString 315 424 744 409 0 0 1440 878 WindowToolGUID 1CDDB66807F98D9800BB5817 WindowToolIsVisible 1 Identifier windowTool.debugAnimator Layout Dock Module PBXNavigatorGroup Proportion 100% Proportion 100% Name Debug Visualizer ServiceClasses PBXNavigatorGroup StatusbarIsVisible 1 ToolbarConfiguration xcode.toolbar.config.debugAnimatorV3 WindowString 100 100 700 500 0 0 1280 1002 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.projectFormatConflicts Layout Dock Module XCProjectFormatConflictsModule Proportion 100% Proportion 100% Name Project Format Conflicts ServiceClasses XCProjectFormatConflictsModule StatusbarIsVisible 0 WindowContentMinSize 450 300 WindowString 50 850 472 307 0 0 1440 877 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 Identifier windowTool.refactoring IncludeInToolsMenu 0 Layout Dock BecomeActive 1 GeometryConfiguration Frame {0, 0}, {500, 335} RubberWindowFrame {0, 0}, {500, 335} Module XCRefactoringModule Proportion 100% Proportion 100% Name Refactoring ServiceClasses XCRefactoringModule WindowString 200 200 500 356 0 0 1920 1200 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 089C1669FE841209C02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; activeExecutable = 94923083103D036400DBE2CE /* qlmanage */; activeTarget = 8D57630D048677EA00EA77CD /* SqueakQL */; breakpoints = ( 9492308D103D040A00DBE2CE /* GenerateThumbnailForURL.c:47 */, 949230A5103D045000DBE2CE /* GeneratePreviewForURL.c:9 */, ); codeSenseManager = 943801FD103CAFFE00A1E999 /* Code sense */; executables = ( 94923083103D036400DBE2CE /* qlmanage */, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 632, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 744, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 704, 60, 20, 48.16259765625, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 272474930; PBXWorkspaceStateSaveDate = 272474930; }; perUserProjectItems = { 94380303103CB0AE00A1E999 /* PBXTextBookmark */ = 94380303103CB0AE00A1E999 /* PBXTextBookmark */; 94380305103CB0AE00A1E999 /* PlistBookmark */ = 94380305103CB0AE00A1E999 /* PlistBookmark */; 94380306103CB0AE00A1E999 /* PBXTextBookmark */ = 94380306103CB0AE00A1E999 /* PBXTextBookmark */; 94923091103D043800DBE2CE /* PlistBookmark */ = 94923091103D043800DBE2CE /* PlistBookmark */; 94923096103D043800DBE2CE /* PBXTextBookmark */ = 94923096103D043800DBE2CE /* PBXTextBookmark */; 94923097103D043800DBE2CE /* PBXTextBookmark */ = 94923097103D043800DBE2CE /* PBXTextBookmark */; 949230A8103D046700DBE2CE /* PBXTextBookmark */ = 949230A8103D046700DBE2CE /* PBXTextBookmark */; 949230AA103D046700DBE2CE /* PBXTextBookmark */ = 949230AA103D046700DBE2CE /* PBXTextBookmark */; 94F4B5B7103DA33F00AB2C19 /* PBXTextBookmark */ = 94F4B5B7103DA33F00AB2C19 /* PBXTextBookmark */; 94F4B5B8103DA33F00AB2C19 /* PBXTextBookmark */ = 94F4B5B8103DA33F00AB2C19 /* PBXTextBookmark */; 94F4B5B9103DA33F00AB2C19 /* PBXTextBookmark */ = 94F4B5B9103DA33F00AB2C19 /* PBXTextBookmark */; 94F4B5BA103DA33F00AB2C19 /* PBXTextBookmark */ = 94F4B5BA103DA33F00AB2C19 /* PBXTextBookmark */; 94F4B5D6103DA3E200AB2C19 /* PBXTextBookmark */ = 94F4B5D6103DA3E200AB2C19 /* PBXTextBookmark */; }; sourceControlManager = 943801FC103CAFFE00A1E999 /* Source Control */; userBuildSettings = { }; }; 089C167EFE841241C02AAC07 /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {934, 603}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 198}"; }; }; 08FB77B6FE84183AC02AAC07 /* main.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1032, 3150}}"; sepNavSelRange = "{1279, 23}"; sepNavVisRange = "{396, 1671}"; }; }; 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {934, 603}}"; sepNavSelRange = "{142, 21}"; sepNavVisRange = "{0, 387}"; }; }; 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1026, 1680}}"; sepNavSelRange = "{1730, 23}"; sepNavVisRange = "{2671, 1571}"; }; }; 8D57630D048677EA00EA77CD /* SqueakQL */ = { activeExec = 0; }; 943801FC103CAFFE00A1E999 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; }; 943801FD103CAFFE00A1E999 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 94380303103CB0AE00A1E999 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 089C167EFE841241C02AAC07 /* English */; name = "InfoPlist.strings: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 198; vrLoc = 0; }; 94380305103CB0AE00A1E999 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 8D576317048677EA00EA77CD /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/Developer/SqueakQL/Info.plist"; rLen = 0; rLoc = 2147483647; }; 94380306103CB0AE00A1E999 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 089C167EFE841241C02AAC07 /* English */; name = "InfoPlist.strings: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 198; vrLoc = 0; }; 94923083103D036400DBE2CE /* qlmanage */ = { isa = PBXExecutable; activeArgIndices = ( YES, ); argumentStrings = ( "-m", ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; launchableReference = 94923084103D036400DBE2CE /* qlmanage */; libgmallocEnabled = 0; name = qlmanage; savedGlobals = { }; sourceDirectories = ( ); }; 94923084103D036400DBE2CE /* qlmanage */ = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = qlmanage; path = /usr/bin/qlmanage; sourceTree = ""; }; 9492308D103D040A00DBE2CE /* GenerateThumbnailForURL.c:47 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; hitCount = 0; ignoreCount = 0; lineNumber = 47; location = SqueakQL; modificationTime = 272434362.710821; state = 0; }; 94923091103D043800DBE2CE /* PlistBookmark */ = { isa = PlistBookmark; fRef = 8D576317048677EA00EA77CD /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/Developer/SqueakQL/Info.plist"; rLen = 0; rLoc = 2147483647; }; 94923096103D043800DBE2CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1633; vrLoc = 1319; }; 94923097103D043800DBE2CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 387; vrLoc = 0; }; 949230A5103D045000DBE2CE /* GeneratePreviewForURL.c:9 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; functionName = "GeneratePreviewForURL()"; hitCount = 0; ignoreCount = 0; lineNumber = 9; location = SqueakQL; modificationTime = 272434362.723295; state = 0; }; 949230A8103D046700DBE2CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 08FB77B6FE84183AC02AAC07 /* main.c */; name = "main.c: 40"; rLen = 23; rLoc = 1279; rType = 0; vrLen = 1671; vrLoc = 396; }; 949230AA103D046700DBE2CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 08FB77B6FE84183AC02AAC07 /* main.c */; name = "main.c: 40"; rLen = 23; rLoc = 1279; rType = 0; vrLen = 1671; vrLoc = 396; }; 94F4B5B7103DA33F00AB2C19 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 7"; rLen = 21; rLoc = 142; rType = 0; vrLen = 387; vrLoc = 0; }; 94F4B5B8103DA33F00AB2C19 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 47"; rLen = 23; rLoc = 1730; rType = 0; vrLen = 1571; vrLoc = 2671; }; 94F4B5B9103DA33F00AB2C19 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 47"; rLen = 23; rLoc = 1730; rType = 0; vrLen = 1571; vrLoc = 2671; }; 94F4B5BA103DA33F00AB2C19 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; name = "GeneratePreviewForURL.c: 7"; rLen = 21; rLoc = 142; rType = 0; vrLen = 387; vrLoc = 0; }; 94F4B5D6103DA3E200AB2C19 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; name = "GenerateThumbnailForURL.c: 47"; rLen = 23; rLoc = 1730; rType = 0; vrLen = 1571; vrLoc = 2671; }; } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/SqueakQL.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ 2C05A19C06CAA52B00D84F6F /* GeneratePreviewForURL.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */; }; 61E3BCFB0870B4F2002186A0 /* GenerateThumbnailForURL.c in Sources */ = {isa = PBXBuildFile; fileRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */; }; 8D576312048677EA00EA77CD /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB77B6FE84183AC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; }; 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; }; 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; }; C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C86B05260671AA6E00DD9006 /* CoreServices.framework */; }; F28CFBFD0A3EC0AF000ABFF5 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */; }; F28CFC030A3EC0C6000ABFF5 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 08FB77B6FE84183AC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GeneratePreviewForURL.c; sourceTree = ""; }; 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = GenerateThumbnailForURL.c; sourceTree = ""; }; 8D576316048677EA00EA77CD /* SqueakQL.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SqueakQL.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; C86B05260671AA6E00DD9006 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = /System/Library/Frameworks/QuickLook.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8D576313048677EA00EA77CD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */, C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */, F28CFBFD0A3EC0AF000ABFF5 /* ApplicationServices.framework in Frameworks */, F28CFC030A3EC0C6000ABFF5 /* QuickLook.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 089C166AFE841209C02AAC07 /* SqueakQL */ = { isa = PBXGroup; children = ( 08FB77AFFE84173DC02AAC07 /* Source */, 089C167CFE841241C02AAC07 /* Resources */, 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */, 19C28FB6FE9D52B211CA2CBB /* Products */, ); name = SqueakQL; sourceTree = ""; }; 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */ = { isa = PBXGroup; children = ( F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */, F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */, C86B05260671AA6E00DD9006 /* CoreServices.framework */, 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */, ); name = "External Frameworks and Libraries"; sourceTree = ""; }; 089C167CFE841241C02AAC07 /* Resources */ = { isa = PBXGroup; children = ( 8D576317048677EA00EA77CD /* Info.plist */, 8D5B49A704867FD3000E48DA /* InfoPlist.strings */, ); name = Resources; sourceTree = ""; }; 08FB77AFFE84173DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.c */, 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.c */, 08FB77B6FE84183AC02AAC07 /* main.c */, ); name = Source; sourceTree = ""; }; 19C28FB6FE9D52B211CA2CBB /* Products */ = { isa = PBXGroup; children = ( 8D576316048677EA00EA77CD /* SqueakQL.qlgenerator */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 8D57630E048677EA00EA77CD /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 8D57630D048677EA00EA77CD /* SqueakQL */ = { isa = PBXNativeTarget; buildConfigurationList = 2CA3261E0896AD4900168862 /* Build configuration list for PBXNativeTarget "SqueakQL" */; buildPhases = ( 8D57630E048677EA00EA77CD /* Headers */, 8D57630F048677EA00EA77CD /* Resources */, 8D576311048677EA00EA77CD /* Sources */, 8D576313048677EA00EA77CD /* Frameworks */, 8D576315048677EA00EA77CD /* Rez */, ); buildRules = ( ); dependencies = ( ); name = SqueakQL; productInstallPath = /Library/QuickLook; productName = SqueakQL; productReference = 8D576316048677EA00EA77CD /* SqueakQL.qlgenerator */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 089C1669FE841209C02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 2CA326220896AD4900168862 /* Build configuration list for PBXProject "SqueakQL" */; compatibilityVersion = "Xcode 3.1"; hasScannedForEncodings = 1; mainGroup = 089C166AFE841209C02AAC07 /* SqueakQL */; projectDirPath = ""; projectRoot = ""; targets = ( 8D57630D048677EA00EA77CD /* SqueakQL */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 8D57630F048677EA00EA77CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ 8D576315048677EA00EA77CD /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8D576311048677EA00EA77CD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8D576312048677EA00EA77CD /* main.c in Sources */, 2C05A19C06CAA52B00D84F6F /* GeneratePreviewForURL.c in Sources */, 61E3BCFB0870B4F2002186A0 /* GenerateThumbnailForURL.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 8D5B49A704867FD3000E48DA /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 089C167EFE841241C02AAC07 /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 2CA3261F0896AD4900168862 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = NO; INFOPLIST_FILE = Info.plist; INSTALL_PATH = /Library/QuickLook; PRODUCT_NAME = SqueakQL; WRAPPER_EXTENSION = qlgenerator; }; name = Debug; }; 2CA326200896AD4900168862 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = NO; INFOPLIST_FILE = Info.plist; INSTALL_PATH = /Library/QuickLook; PRODUCT_NAME = SqueakQL; WRAPPER_EXTENSION = qlgenerator; }; name = Release; }; 2CA326230896AD4900168862 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = macosx10.5; }; name = Debug; }; 2CA326240896AD4900168862 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; SDKROOT = macosx10.5; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 2CA3261E0896AD4900168862 /* Build configuration list for PBXNativeTarget "SqueakQL" */ = { isa = XCConfigurationList; buildConfigurations = ( 2CA3261F0896AD4900168862 /* Debug */, 2CA326200896AD4900168862 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 2CA326220896AD4900168862 /* Build configuration list for PBXProject "SqueakQL" */ = { isa = XCConfigurationList; buildConfigurations = ( 2CA326230896AD4900168862 /* Debug */, 2CA326240896AD4900168862 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 089C1669FE841209C02AAC07 /* Project object */; } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/SqueakQL/main.c ================================================ //============================================================================== // // DO NO MODIFY THE CONTENT OF THIS FILE // // This file contains the generic CFPlug-in code necessary for your generator // To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c // //============================================================================== #include #include #include #include // ----------------------------------------------------------------------------- // constants // ----------------------------------------------------------------------------- // Don't modify this line #define PLUGIN_ID "FFD8E9C9-4777-4502-811C-15503F9D31EA" // // Below is the generic glue code for all plug-ins. // // You should not have to modify this code aside from changing // names if you decide to change the names defined in the Info.plist // // ----------------------------------------------------------------------------- // typedefs // ----------------------------------------------------------------------------- // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); // The preview generation function to be implemented in GeneratePreviewForURL.c OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); // The layout for an instance of QuickLookGeneratorPlugIn typedef struct __QuickLookGeneratorPluginType { void *conduitInterface; CFUUIDRef factoryID; UInt32 refCount; } QuickLookGeneratorPluginType; // ----------------------------------------------------------------------------- // prototypes // ----------------------------------------------------------------------------- // Forward declaration for the IUnknown implementation. // QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance); HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); ULONG QuickLookGeneratorPluginAddRef(void *thisInstance); ULONG QuickLookGeneratorPluginRelease(void *thisInstance); // ----------------------------------------------------------------------------- // myInterfaceFtbl definition // ----------------------------------------------------------------------------- // The QLGeneratorInterfaceStruct function table. // static QLGeneratorInterfaceStruct myInterfaceFtbl = { NULL, QuickLookGeneratorQueryInterface, QuickLookGeneratorPluginAddRef, QuickLookGeneratorPluginRelease, NULL, NULL, NULL, NULL }; // ----------------------------------------------------------------------------- // AllocQuickLookGeneratorPluginType // ----------------------------------------------------------------------------- // Utility function that allocates a new instance. // You can do some initial setup for the generator here if you wish // like allocating globals etc... // QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) { QuickLookGeneratorPluginType *theNewInstance; theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType)); memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType)); /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct)); /* Retain and keep an open instance refcount for each factory. */ theNewInstance->factoryID = CFRetain(inFactoryID); CFPlugInAddInstanceForFactory(inFactoryID); /* This function returns the IUnknown interface so set the refCount to one. */ theNewInstance->refCount = 1; return theNewInstance; } // ----------------------------------------------------------------------------- // DeallocQuickLookGeneratorPluginType // ----------------------------------------------------------------------------- // Utility function that deallocates the instance when // the refCount goes to zero. // In the current implementation generator interfaces are never deallocated // but implement this as this might change in the future // void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance) { CFUUIDRef theFactoryID; theFactoryID = thisInstance->factoryID; /* Free the conduitInterface table up */ free(thisInstance->conduitInterface); /* Free the instance structure */ free(thisInstance); if (theFactoryID){ CFPlugInRemoveInstanceForFactory(theFactoryID); CFRelease(theFactoryID); } } // ----------------------------------------------------------------------------- // QuickLookGeneratorQueryInterface // ----------------------------------------------------------------------------- // Implementation of the IUnknown QueryInterface function. // HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) { CFUUIDRef interfaceID; interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){ /* If the Right interface was requested, bump the ref count, * set the ppv parameter equal to the instance, and * return good status. */ ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); *ppv = thisInstance; CFRelease(interfaceID); return S_OK; }else{ /* Requested interface unknown, bail with error. */ *ppv = NULL; CFRelease(interfaceID); return E_NOINTERFACE; } } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginAddRef // ----------------------------------------------------------------------------- // Implementation of reference counting for this type. Whenever an interface // is requested, bump the refCount for the instance. NOTE: returning the // refcount is a convention but is not required so don't rely on it. // ULONG QuickLookGeneratorPluginAddRef(void *thisInstance) { ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1; return ((QuickLookGeneratorPluginType*) thisInstance)->refCount; } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginRelease // ----------------------------------------------------------------------------- // When an interface is released, decrement the refCount. // If the refCount goes to zero, deallocate the instance. // ULONG QuickLookGeneratorPluginRelease(void *thisInstance) { ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){ DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance ); return 0; }else{ return ((QuickLookGeneratorPluginType*) thisInstance )->refCount; } } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginFactory // ----------------------------------------------------------------------------- void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) { QuickLookGeneratorPluginType *result; CFUUIDRef uuid; /* If correct type is being requested, allocate an * instance of kQLGeneratorTypeID and return the IUnknown interface. */ if (CFEqual(typeID,kQLGeneratorTypeID)){ uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); result = AllocQuickLookGeneratorPluginType(uuid); CFRelease(uuid); return result; } /* If the requested type is incorrect, return NULL. */ return NULL; } ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/interp.h ================================================ /* Automatically generated from Squeak on #(6 June 2005 10:59:27 pm) */ #define SQ_VI_BYTES_PER_WORD 4 ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/myMacHeaders.c ================================================ /* =========================================================================== MacHeaders.c 1995-1999 Metrowerks Inc. All rights reserved. =========================================================================== Includes used to generate the 'MacHeaders' precompiled header for Metrowerks C/C++. Stop using Strings.h, Types.h, Windows.h and Memory.h. RA/8/19/98 Updated to Universal Headers 3.1 RA/3/05/99 Updated to Universal Interfaces 3.2 RA/7/14/99 Changed commenting style so you can built for ANSI Strict */ /* * Required for c-style toolbox glue functions: c2pstr and p2cstr * (the inverse operation (pointers_in_A0) is performed at the end...) */ #if __MC68K__ && !__CFM68K__ #pragma d0_pointers on #endif /* * To allow the use of ToolBox calls which have now become obsolete on * PowerPC, but which are still needed for System 6 applications, we need to * #define OBSOLETE. If your application will never use these calls then you * can comment out this #define. NB: This is for 68K only ... * #if !defined(powerc) && !defined(OBSOLETE) #define OBSOLETE 1 #endif */ #ifndef OLDROUTINENAMES #define OLDROUTINENAMES 0 #endif #ifndef OLDROUTINELOCATIONS #define OLDROUTINELOCATIONS 0 #endif /* * Metrowerks-specific definitions * * These definitions are commonly used but not in Apple's headers. We define * them in our precompiled header so we can use the Apple headers without * modification. */ #ifndef PtoCstr #define PtoCstr p2cstr #endif #ifndef CtoPstr #define CtoPstr c2pstr #endif #ifndef PtoCString #define PtoCString p2cstr #endif #ifndef CtoPString #define CtoPString c2pstr #endif #ifndef topLeft #define topLeft(r) (((Point *) &(r))[0]) #endif #ifndef botRight #define botRight(r) (((Point *) &(r))[1]) #endif #ifndef TRUE #define TRUE true #endif #ifndef FALSE #define FALSE false #endif /* * Apple Universal Headers 3.2 * * Uncomment any additional #includes you want to add to your MacHeaders. */ /* #include */ /* #include */ #include #include #include #include #include /* #include */ #include #include #include #include #include #include #include #include /* #include */ /* #include New for 3.2 */ /* #include New for 3.2 */ /* #include */ #include /* #include */ /* #include */ #include /* #include */ /* #include */ /* #include */ #include /* #include */ /* #include */ /* #include */ #include /* #include */ #include /* #include */ /* #include */ #include #include /* #include */ /* #include */ #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include /* #include Start using Meuns.h, Devices.h and Events.h */ /* #include */ #include #include /* #include */ /* #include */ #include /* #include */ #include #include /* #include */ #include /* #include */ /* #include */ /* #include */ /* #include New for 3.2 */ /* #include */ /* #include */ /* #include */ #include #include #include /* #include */ #include /* #include */ /* #include */ #include /* #include New for 3.2 */ #include #include #include #include #include /* #include */ /* #include Start using CodeFragments.h */ /* #include */ #include /* #include Merged into Gestalt.h */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include /* #include */ #include /* #include */ #include /* #include */ /* #include */ #include /* #include */ /* #include */ /* #include Start using Script.h */ #include /* #include */ #include /* #include */ #include /* #include */ #include #include /* #include */ /* #include */ #include /* Start using MacMemory.h */ #include /* #include */ #include #include /* #include */ /* #include Start using Multiprocessing.h */ /* #include */ #include /* #include New for 3.2 */ /* #include */ #include #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include #include #include /* #include Start using Events.h */ #include /* #include */ #include #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include Start using ColorPicker.h */ /* #include */ /* #include */ /* #include */ #include #include #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include /* #include */ #include #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include New for 3.2 */ #include /* #include */ /* #include */ /* #include */ /* #include */ #include #include /* #include */ #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ /* #include */ #include /* #include */ #include #include /* Start using TextUtils.h */ /* #include */ /* #include */ /* #include */ #include #include /* #include */ /* #include */ #include #include #include #include /* #include */ /* #include */ #include /* #include */ #include /* Start using MacTypes.h */ /* #include */ /* #include */ /* #include */ #include /* #include */ #include /* Start using MacWindows.h */ /* #include */ /* #include */ /* * Required for c-style toolbox glue functions: c2pstr and p2cstr * (matches the inverse operation at the start of the file...) */ #if __MC68K__ && !__CFM68K__ #pragma d0_pointers reset #endif ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/myMacHeaders.pch ================================================ /**************************************************************************** * PROJECT: Mac window, memory, keyboard interface for netscape plugin logic * FILE: myMacHeaders.pch * CONTENT: * * AUTHOR: John McIntosh, and others. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: myMacHeaders.pch 1191 2005-05-24 03:19:32Z johnmci $ * * NOTES: See change log below. * 1/4/2002 JMM Some carbon cleanup * *****************************************************************************//* =========================================================================== MacHeaders.pch 1995-1999 Metrowerks Inc. All rights reserved. =========================================================================== Script to generate the 'MacHeaders' precompiled header for Metrowerks C. RA/8/19/98 Updated to Universal Headers 3.1 RA/7/14/99 Changed commenting style so you can built for ANSI Strict Support for automatically naming the C precompiled header file ... */ #if __POWERPC__ #pragma precompile_target "myMacHeadersPPC" #elif __CFM68K__ #pragma precompile_target "myMacHeadersCFM68K" #else #pragma precompile_target "myMacHeaders68K" #endif /* Now just include the "MacHeaders.c" source file ... */ #pragma once on #define ACCESSOR_CALLS_ARE_FUNCTIONS 1 #define SQUEAK_BUILTIN_PLUGIN #define SQ_VI_BYTES_PER_WORD 4 //#define BROWSERPLUGIN #include "myMacHeaders.c" #include "config.h" #include "interp.h" ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/myMacHeadersCarbon.pch ================================================ /* =========================================================================== MacHeaders.pch 1995-1999 Metrowerks Inc. All rights reserved. =========================================================================== Script to generate the 'MacHeaders' precompiled header for Metrowerks C. RA/8/19/98 Updated to Universal Headers 3.1 RA/7/14/99 Changed commenting style so you can built for ANSI Strict Support for automatically naming the C precompiled header file ... */ #if __POWERPC__ #pragma precompile_target "myMacHeadersPPCCarbon" #ifndef TARGET_API_MAC_CARBON #define TARGET_API_MAC_CARBON 1 #define ACCESSOR_CALLS_ARE_FUNCTIONS 1 #define OPAQUE_TOOLBOX_STRUCTS 1 #endif #elif __CFM68K__ #pragma precompile_target "myMacHeadersCFM68K" #else #pragma precompile_target "myMacHeaders68K" #endif /* Now just include the "MacHeaders.c" source file ... */ #pragma once on #include "myMacHeaders.c" ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/sqGnu.h ================================================ /* Definitions for "gnuified" interp.c * * Copyright (C) 1996 1997 1998 1999 2000 2001 Ian Piumarta and individual * authors/contributors listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. This notice may not be removed or altered in any source distribution. * * Using or modifying this file for use in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the base * of the distribution before proceeding with any such use. * * You are STRONGLY DISCOURAGED from distributing a modified version of * this file under its original name without permission. If you must * change it, rename it first. */ /* Author: Ian.Piumarta@inria.fr * * Last edited: Fri Aug 11 08:20:28 2000 by piumarta (Ian Piumarta) on emilia * April 17th, 2002, John M McIntosh use jumptable register logic for PPC * Feb 23rd, 2006, John M McIntosh watch usage of __Apple__ also Ian's changes for GCC i386 * December 10th 2008, Eliot Miranda, updated with FP_REG and use of GIV() for * the global struct. * * NOTES: * this file is #included IN PLACE OF sq.h */ #include "sq.h" #define CASE(N) case N: _##N: #if defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__) #define BREAK goto *jumpTableR[currentBytecode] #define PPC_REG_JUMP ; register void **jumpTableR JP_REG; jumpTableR = &jumpTable[0] #else #define BREAK goto *jumpTable[currentBytecode] #define PPC_REG_JUMP #endif #define PRIM_DISPATCH goto *jumpTable[GIV(primitiveIndex)] #define JUMP_TABLE \ void *jumpTable[256]= { \ &&_0, &&_1, &&_2, &&_3, &&_4, &&_5, &&_6, &&_7, &&_8, &&_9, \ &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, \ &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, \ &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, \ &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, \ &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, \ &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, \ &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, \ &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, \ &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, \ &&_100, &&_101, &&_102, &&_103, &&_104, &&_105, &&_106, &&_107, &&_108, &&_109, \ &&_110, &&_111, &&_112, &&_113, &&_114, &&_115, &&_116, &&_117, &&_118, &&_119, \ &&_120, &&_121, &&_122, &&_123, &&_124, &&_125, &&_126, &&_127, &&_128, &&_129, \ &&_130, &&_131, &&_132, &&_133, &&_134, &&_135, &&_136, &&_137, &&_138, &&_139, \ &&_140, &&_141, &&_142, &&_143, &&_144, &&_145, &&_146, &&_147, &&_148, &&_149, \ &&_150, &&_151, &&_152, &&_153, &&_154, &&_155, &&_156, &&_157, &&_158, &&_159, \ &&_160, &&_161, &&_162, &&_163, &&_164, &&_165, &&_166, &&_167, &&_168, &&_169, \ &&_170, &&_171, &&_172, &&_173, &&_174, &&_175, &&_176, &&_177, &&_178, &&_179, \ &&_180, &&_181, &&_182, &&_183, &&_184, &&_185, &&_186, &&_187, &&_188, &&_189, \ &&_190, &&_191, &&_192, &&_193, &&_194, &&_195, &&_196, &&_197, &&_198, &&_199, \ &&_200, &&_201, &&_202, &&_203, &&_204, &&_205, &&_206, &&_207, &&_208, &&_209, \ &&_210, &&_211, &&_212, &&_213, &&_214, &&_215, &&_216, &&_217, &&_218, &&_219, \ &&_220, &&_221, &&_222, &&_223, &&_224, &&_225, &&_226, &&_227, &&_228, &&_229, \ &&_230, &&_231, &&_232, &&_233, &&_234, &&_235, &&_236, &&_237, &&_238, &&_239, \ &&_240, &&_241, &&_242, &&_243, &&_244, &&_245, &&_246, &&_247, &&_248, &&_249, \ &&_250, &&_251, &&_252, &&_253, &&_254, &&_255 \ } PPC_REG_JUMP; #define PRIM_TABLE \ static void *jumpTable[700]= { \ &&_0, &&_1, &&_2, &&_3, &&_4, &&_5, &&_6, &&_7, &&_8, &&_9, \ &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, \ &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, \ &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, \ &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, \ &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, \ &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, \ &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, \ &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, \ &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, \ &&_100, &&_101, &&_102, &&_103, &&_104, &&_105, &&_106, &&_107, &&_108, &&_109, \ &&_110, &&_111, &&_112, &&_113, &&_114, &&_115, &&_116, &&_117, &&_118, &&_119, \ &&_120, &&_121, &&_122, &&_123, &&_124, &&_125, &&_126, &&_127, &&_128, &&_129, \ &&_130, &&_131, &&_132, &&_133, &&_134, &&_135, &&_136, &&_137, &&_138, &&_139, \ &&_140, &&_141, &&_142, &&_143, &&_144, &&_145, &&_146, &&_147, &&_148, &&_149, \ &&_150, &&_151, &&_152, &&_153, &&_154, &&_155, &&_156, &&_157, &&_158, &&_159, \ &&_160, &&_161, &&_162, &&_163, &&_164, &&_165, &&_166, &&_167, &&_168, &&_169, \ &&_170, &&_171, &&_172, &&_173, &&_174, &&_175, &&_176, &&_177, &&_178, &&_179, \ &&_180, &&_181, &&_182, &&_183, &&_184, &&_185, &&_186, &&_187, &&_188, &&_189, \ &&_190, &&_191, &&_192, &&_193, &&_194, &&_195, &&_196, &&_197, &&_198, &&_199, \ &&_200, &&_201, &&_202, &&_203, &&_204, &&_205, &&_206, &&_207, &&_208, &&_209, \ &&_210, &&_211, &&_212, &&_213, &&_214, &&_215, &&_216, &&_217, &&_218, &&_219, \ &&_220, &&_221, &&_222, &&_223, &&_224, &&_225, &&_226, &&_227, &&_228, &&_229, \ &&_230, &&_231, &&_232, &&_233, &&_234, &&_235, &&_236, &&_237, &&_238, &&_239, \ &&_240, &&_241, &&_242, &&_243, &&_244, &&_245, &&_246, &&_247, &&_248, &&_249, \ &&_250, &&_251, &&_252, &&_253, &&_254, &&_255, &&_256, &&_257, &&_258, &&_259, \ &&_260, &&_261, &&_262, &&_263, &&_264, &&_265, &&_266, &&_267, &&_268, &&_269, \ &&_270, &&_271, &&_272, &&_273, &&_274, &&_275, &&_276, &&_277, &&_278, &&_279, \ &&_280, &&_281, &&_282, &&_283, &&_284, &&_285, &&_286, &&_287, &&_288, &&_289, \ &&_290, &&_291, &&_292, &&_293, &&_294, &&_295, &&_296, &&_297, &&_298, &&_299, \ &&_300, &&_301, &&_302, &&_303, &&_304, &&_305, &&_306, &&_307, &&_308, &&_309, \ &&_310, &&_311, &&_312, &&_313, &&_314, &&_315, &&_316, &&_317, &&_318, &&_319, \ &&_320, &&_321, &&_322, &&_323, &&_324, &&_325, &&_326, &&_327, &&_328, &&_329, \ &&_330, &&_331, &&_332, &&_333, &&_334, &&_335, &&_336, &&_337, &&_338, &&_339, \ &&_340, &&_341, &&_342, &&_343, &&_344, &&_345, &&_346, &&_347, &&_348, &&_349, \ &&_350, &&_351, &&_352, &&_353, &&_354, &&_355, &&_356, &&_357, &&_358, &&_359, \ &&_360, &&_361, &&_362, &&_363, &&_364, &&_365, &&_366, &&_367, &&_368, &&_369, \ &&_370, &&_371, &&_372, &&_373, &&_374, &&_375, &&_376, &&_377, &&_378, &&_379, \ &&_380, &&_381, &&_382, &&_383, &&_384, &&_385, &&_386, &&_387, &&_388, &&_389, \ &&_390, &&_391, &&_392, &&_393, &&_394, &&_395, &&_396, &&_397, &&_398, &&_399, \ &&_400, &&_401, &&_402, &&_403, &&_404, &&_405, &&_406, &&_407, &&_408, &&_409, \ &&_410, &&_411, &&_412, &&_413, &&_414, &&_415, &&_416, &&_417, &&_418, &&_419, \ &&_420, &&_421, &&_422, &&_423, &&_424, &&_425, &&_426, &&_427, &&_428, &&_429, \ &&_430, &&_431, &&_432, &&_433, &&_434, &&_435, &&_436, &&_437, &&_438, &&_439, \ &&_440, &&_441, &&_442, &&_443, &&_444, &&_445, &&_446, &&_447, &&_448, &&_449, \ &&_450, &&_451, &&_452, &&_453, &&_454, &&_455, &&_456, &&_457, &&_458, &&_459, \ &&_460, &&_461, &&_462, &&_463, &&_464, &&_465, &&_466, &&_467, &&_468, &&_469, \ &&_470, &&_471, &&_472, &&_473, &&_474, &&_475, &&_476, &&_477, &&_478, &&_479, \ &&_480, &&_481, &&_482, &&_483, &&_484, &&_485, &&_486, &&_487, &&_488, &&_489, \ &&_490, &&_491, &&_492, &&_493, &&_494, &&_495, &&_496, &&_497, &&_498, &&_499, \ &&_500, &&_501, &&_502, &&_503, &&_504, &&_505, &&_506, &&_507, &&_508, &&_509, \ &&_510, &&_511, &&_512, &&_513, &&_514, &&_515, &&_516, &&_517, &&_518, &&_519, \ &&_520, &&_521, &&_522, &&_523, &&_524, &&_525, &&_526, &&_527, &&_528, &&_529, \ &&_530, &&_531, &&_532, &&_533, &&_534, &&_535, &&_536, &&_537, &&_538, &&_539, \ &&_540, &&_541, &&_542, &&_543, &&_544, &&_545, &&_546, &&_547, &&_548, &&_549, \ &&_550, &&_551, &&_552, &&_553, &&_554, &&_555, &&_556, &&_557, &&_558, &&_559, \ &&_560, &&_561, &&_562, &&_563, &&_564, &&_565, &&_566, &&_567, &&_568, &&_569, \ &&_570, &&_571, &&_572, &&_573, &&_574, &&_575, &&_576, &&_577, &&_578, &&_579, \ &&_580, &&_581, &&_582, &&_583, &&_584, &&_585, &&_586, &&_587, &&_588, &&_589, \ &&_590, &&_591, &&_592, &&_593, &&_594, &&_595, &&_596, &&_597, &&_598, &&_599, \ &&_600, &&_601, &&_602, &&_603, &&_604, &&_605, &&_606, &&_607, &&_608, &&_609, \ &&_610, &&_611, &&_612, &&_613, &&_614, &&_615, &&_616, &&_617, &&_618, &&_619, \ &&_620, &&_621, &&_622, &&_623, &&_624, &&_625, &&_626, &&_627, &&_628, &&_629, \ &&_630, &&_631, &&_632, &&_633, &&_634, &&_635, &&_636, &&_637, &&_638, &&_639, \ &&_640, &&_641, &&_642, &&_643, &&_644, &&_645, &&_646, &&_647, &&_648, &&_649, \ &&_650, &&_651, &&_652, &&_653, &&_654, &&_655, &&_656, &&_657, &&_658, &&_659, \ &&_660, &&_661, &&_662, &&_663, &&_664, &&_665, &&_666, &&_667, &&_668, &&_669, \ &&_670, &&_671, &&_672, &&_673, &&_674, &&_675, &&_676, &&_677, &&_678, &&_679, \ &&_680, &&_681, &&_682, &&_683, &&_684, &&_685, &&_686, &&_687, &&_688, &&_689, \ &&_690, &&_691, &&_692, &&_693, &&_694, &&_695, &&_696, &&_697, &&_698, &&_699, \ } /* IP_REG, FP_REG, SP_REG, CB_REG the machine registers in which to place localIP, localFP, localSP and currentBytecode. Wins big on register-deficient architectures -- especially Intel. */ #if defined(__mips__) # define IP_REG asm("$16") # define SP_REG asm("$17") # define CB_REG asm("$18") #endif #if defined(__sparc__) # define IP_REG asm("%l0") # define SP_REG asm("%l1") # define CB_REG asm("%l2") #endif #if defined(__alpha__) # define IP_REG asm("$9") # define SP_REG asm("$10") # define CB_REG asm("$11") #endif #if defined(__i386__) # define IP_REG asm("%esi") # define SP_REG asm("%edi") # define CB_REG asm("%ebx") #endif #if defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__) # define FOO_REG asm("13") # define JP_REG asm("14") # define IP_REG asm("15") # define SP_REG asm("16") # define CB_REG asm("17") #endif #if defined(__hppa__) # define IP_REG asm("%r18") # define SP_REG asm("%r17") # define CB_REG asm("%r16") #endif #if defined(__mc68000__) # define IP_REG asm("a5") # define SP_REG asm("a4") # define CB_REG asm("d7") #endif #if !defined(FOO_REG) # define FOO_REG /* nada */ #endif #if !defined(FP_REG) # define FP_REG /* nada */ #endif ================================================ FILE: vm/src/from_squeak/Mac OS/vm/Developer/sqMacMinimal.c ================================================ /* sqMacMinimal.c This file includes the minimal support code to build a Squeak virtual machine for the Mac. Most primitives are "stubbed-out", meaning that if they are invoked from the image they will return a "primitive failed" error. Among the stubbed out primitives are those that support sound input and output, serial and MIDI ports, networking, ,file directory operations, etc. The basic file read/write operations are NOT stubbed out, although they could be as long as the image loading mechanism still works. The purpose of this file is to provide an implementation roadmap when bootstrapping Squeak on a new platform. Once all the non-stubbed-out functions in this file have been ported, you will have a working, usable Squeak virtual machine! *** Implementation Notes *** I/O Functions The following are essential for display and user interaction: ioScreenSize() ioShowDisplay() ioGetButtonState() ioGetKeystroke() ioMousePoint() ioPeekKeystroke() The following can be made no-ops: ioProcessEvents() -- poll for input events on some platforms ioSetCursor() -- install a 16x16 black and white hardware cursor ioSetCursorWithMask() -- install a masked black and white hardware cursor ioBeep() -- sound a short beep through the speaker ioExit() -- exit the VM: quit the application, reboot, power down, or -- similar behavior appropriate to this platform (if this -- is a noop you simply won't be able to quit from Squeak) File Naming The virtual machine keeps track of the full path name of the Squeak image file and the path to the directory containing the virtual machine. In this minimal implementation, the VM path is the empty string and the image name is hardwired to "squeak.image". It is assumed that the image file, the changes file, the Squeak application, and the system sources file are all in the the same directory, and that this directory is the default working directory for any file operations. Time Functions ioMSecs(), ioMicroMSecs() -- both return a millisecond clock value, but historically -- ioMicroMSecs() used a higher resolution timer; the -- ideal implementation is an inexpensive clock with 1 -- millisecond accuracy, but both functions can use a -- clock with much coarser accuracy (e.g., 50-100 mSecs) -- if necessary ioSeconds() -- returns the number of seconds since Jan 1, 1901. -- optional: may be implemented to always return 0, but then -- the current date and time will be wrong *** Linking *** To build a Macintosh VM using this file, link together: interp.c -- automatically generated interpreter file sqMiscPrims.c -- automatically generated primitives sqMacMinimal.c -- this file plus the appropriate C libraries (e.g. math, strings, standard I/O). The interpreter code depends on the following functions from libraries: math: exp(), log(), atan(), sin(), sqrt(), ldexp(), frexp(), modf() standard i/o: getchar(), putchar(), printf() other: memcpy(), strlen(), clock() The standard i/o functions could be stubbed out; they are only used to report fatal VM errors. */ #include #include #include #include #include #include "sq.h" #include "FilePlugin.h" /*** Mac Toolbox Function that is Missing from Standard Header Files ***/ void ExitToShell(void); /*** Stub Definitions ***/ #define STUBBED_OUT { success(false); } #define DO_NOTHING { } /*** Enumerations ***/ enum { appleID = 1, fileID }; enum { quitItem = 1 }; /*** Variables -- Imported from Virtual Machine ***/ extern int interruptCheckCounter; extern int interruptKeycode; extern int interruptPending; /* set to true by RecordKeystroke if interrupt key is pressed */ /*** Variables -- image and path names ***/ #define IMAGE_NAME_SIZE 300 char imageName[IMAGE_NAME_SIZE + 1]; /* full path to image */ #define SHORTIMAGE_NAME_SIZE 100 char shortImageName[SHORTIMAGE_NAME_SIZE + 1]; /* just the image file name */ #define VMPATH_SIZE 300 char vmPath[VMPATH_SIZE + 1]; /* full path to interpreter's directory */ /*** Variables -- Mac Related ***/ MenuHandle appleMenu = nil; MenuHandle fileMenu = nil; CTabHandle stColorTable = nil; PixMapHandle stPixMap = nil; WindowPtr stWindow = nil; /*** Variables -- Event Recording ***/ #define KEYBUF_SIZE 64 int keyBuf[KEYBUF_SIZE]; /* circular buffer */ int keyBufGet = 0; /* index of next item of keyBuf to read */ int keyBufPut = 0; /* index of next item of keyBuf to write */ int keyBufOverflows = 0; /* number of characters dropped */ int buttonState = 0; /* mouse button and modifier state when mouse button went down or 0 if not pressed */ /* This table maps the 5 Macintosh modifier key bits to 4 Squeak modifier bits. (The Mac shift and caps lock keys are both mapped to the single Squeak shift bit). Mac bits:

*/ /* header_file_macros */ /* */ /* */ /* Header File Macros */ /* */ /* <Abstract> */ /* Macro definitions used to #include specific header files. */ /* */ /* <Description> */ /* The following macros are defined to the name of specific */ /* FreeType~2 header files. They can be used directly in #include */ /* statements as in: */ /* */ /* { */ /* #include FT_FREETYPE_H */ /* #include FT_MULTIPLE_MASTERS_H */ /* #include FT_GLYPH_H */ /* } */ /* */ /* There are several reasons why we are now using macros to name */ /* public header files. The first one is that such macros are not */ /* limited to the infamous 8.3~naming rule required by DOS (and */ /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */ /* */ /* The second reason is that it allows for more flexibility in the */ /* way FreeType~2 is installed on a given system. */ /* */ /*************************************************************************/ /* configuration files */ /************************************************************************* * * @macro: * FT_CONFIG_CONFIG_H * * @description: * A macro used in #include statements to name the file containing * FreeType~2 configuration data. * */ #ifndef FT_CONFIG_CONFIG_H #define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h> #endif /************************************************************************* * * @macro: * FT_CONFIG_STANDARD_LIBRARY_H * * @description: * A macro used in #include statements to name the file containing * FreeType~2 interface to the standard C library functions. * */ #ifndef FT_CONFIG_STANDARD_LIBRARY_H #define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h> #endif /************************************************************************* * * @macro: * FT_CONFIG_OPTIONS_H * * @description: * A macro used in #include statements to name the file containing * FreeType~2 project-specific configuration options. * */ #ifndef FT_CONFIG_OPTIONS_H #define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h> #endif /************************************************************************* * * @macro: * FT_CONFIG_MODULES_H * * @description: * A macro used in #include statements to name the file containing the * list of FreeType~2 modules that are statically linked to new library * instances in @FT_Init_FreeType. * */ #ifndef FT_CONFIG_MODULES_H #define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h> #endif /* */ /* public headers */ /************************************************************************* * * @macro: * FT_FREETYPE_H * * @description: * A macro used in #include statements to name the file containing the * base FreeType~2 API. * */ #define FT_FREETYPE_H <freetype/freetype.h> /************************************************************************* * * @macro: * FT_ERRORS_H * * @description: * A macro used in #include statements to name the file containing the * list of FreeType~2 error codes (and messages). * * It is included by @FT_FREETYPE_H. * */ #define FT_ERRORS_H <freetype/fterrors.h> /************************************************************************* * * @macro: * FT_MODULE_ERRORS_H * * @description: * A macro used in #include statements to name the file containing the * list of FreeType~2 module error offsets (and messages). * */ #define FT_MODULE_ERRORS_H <freetype/ftmoderr.h> /************************************************************************* * * @macro: * FT_SYSTEM_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 interface to low-level operations (i.e., memory management * and stream i/o). * * It is included by @FT_FREETYPE_H. * */ #define FT_SYSTEM_H <freetype/ftsystem.h> /************************************************************************* * * @macro: * FT_IMAGE_H * * @description: * A macro used in #include statements to name the file containing type * definitions related to glyph images (i.e., bitmaps, outlines, * scan-converter parameters). * * It is included by @FT_FREETYPE_H. * */ #define FT_IMAGE_H <freetype/ftimage.h> /************************************************************************* * * @macro: * FT_TYPES_H * * @description: * A macro used in #include statements to name the file containing the * basic data types defined by FreeType~2. * * It is included by @FT_FREETYPE_H. * */ #define FT_TYPES_H <freetype/fttypes.h> /************************************************************************* * * @macro: * FT_LIST_H * * @description: * A macro used in #include statements to name the file containing the * list management API of FreeType~2. * * (Most applications will never need to include this file.) * */ #define FT_LIST_H <freetype/ftlist.h> /************************************************************************* * * @macro: * FT_OUTLINE_H * * @description: * A macro used in #include statements to name the file containing the * scalable outline management API of FreeType~2. * */ #define FT_OUTLINE_H <freetype/ftoutln.h> /************************************************************************* * * @macro: * FT_SIZES_H * * @description: * A macro used in #include statements to name the file containing the * API which manages multiple @FT_Size objects per face. * */ #define FT_SIZES_H <freetype/ftsizes.h> /************************************************************************* * * @macro: * FT_MODULE_H * * @description: * A macro used in #include statements to name the file containing the * module management API of FreeType~2. * */ #define FT_MODULE_H <freetype/ftmodapi.h> /************************************************************************* * * @macro: * FT_RENDER_H * * @description: * A macro used in #include statements to name the file containing the * renderer module management API of FreeType~2. * */ #define FT_RENDER_H <freetype/ftrender.h> /************************************************************************* * * @macro: * FT_TYPE1_TABLES_H * * @description: * A macro used in #include statements to name the file containing the * types and API specific to the Type~1 format. * */ #define FT_TYPE1_TABLES_H <freetype/t1tables.h> /************************************************************************* * * @macro: * FT_TRUETYPE_IDS_H * * @description: * A macro used in #include statements to name the file containing the * enumeration values which identify name strings, languages, encodings, * etc. This file really contains a _large_ set of constant macro * definitions, taken from the TrueType and OpenType specifications. * */ #define FT_TRUETYPE_IDS_H <freetype/ttnameid.h> /************************************************************************* * * @macro: * FT_TRUETYPE_TABLES_H * * @description: * A macro used in #include statements to name the file containing the * types and API specific to the TrueType (as well as OpenType) format. * */ #define FT_TRUETYPE_TABLES_H <freetype/tttables.h> /************************************************************************* * * @macro: * FT_TRUETYPE_TAGS_H * * @description: * A macro used in #include statements to name the file containing the * definitions of TrueType four-byte `tags' which identify blocks in * SFNT-based font formats (i.e., TrueType and OpenType). * */ #define FT_TRUETYPE_TAGS_H <freetype/tttags.h> /************************************************************************* * * @macro: * FT_BDF_H * * @description: * A macro used in #include statements to name the file containing the * definitions of an API which accesses BDF-specific strings from a * face. * */ #define FT_BDF_H <freetype/ftbdf.h> /************************************************************************* * * @macro: * FT_CID_H * * @description: * A macro used in #include statements to name the file containing the * definitions of an API which access CID font information from a * face. * */ #define FT_CID_H <freetype/ftcid.h> /************************************************************************* * * @macro: * FT_GZIP_H * * @description: * A macro used in #include statements to name the file containing the * definitions of an API which supports gzip-compressed files. * */ #define FT_GZIP_H <freetype/ftgzip.h> /************************************************************************* * * @macro: * FT_LZW_H * * @description: * A macro used in #include statements to name the file containing the * definitions of an API which supports LZW-compressed files. * */ #define FT_LZW_H <freetype/ftlzw.h> /************************************************************************* * * @macro: * FT_WINFONTS_H * * @description: * A macro used in #include statements to name the file containing the * definitions of an API which supports Windows FNT files. * */ #define FT_WINFONTS_H <freetype/ftwinfnt.h> /************************************************************************* * * @macro: * FT_GLYPH_H * * @description: * A macro used in #include statements to name the file containing the * API of the optional glyph management component. * */ #define FT_GLYPH_H <freetype/ftglyph.h> /************************************************************************* * * @macro: * FT_BITMAP_H * * @description: * A macro used in #include statements to name the file containing the * API of the optional bitmap conversion component. * */ #define FT_BITMAP_H <freetype/ftbitmap.h> /************************************************************************* * * @macro: * FT_BBOX_H * * @description: * A macro used in #include statements to name the file containing the * API of the optional exact bounding box computation routines. * */ #define FT_BBOX_H <freetype/ftbbox.h> /************************************************************************* * * @macro: * FT_CACHE_H * * @description: * A macro used in #include statements to name the file containing the * API of the optional FreeType~2 cache sub-system. * */ #define FT_CACHE_H <freetype/ftcache.h> /************************************************************************* * * @macro: * FT_CACHE_IMAGE_H * * @description: * A macro used in #include statements to name the file containing the * `glyph image' API of the FreeType~2 cache sub-system. * * It is used to define a cache for @FT_Glyph elements. You can also * use the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need to * store small glyph bitmaps, as it will use less memory. * * This macro is deprecated. Simply include @FT_CACHE_H to have all * glyph image-related cache declarations. * */ #define FT_CACHE_IMAGE_H FT_CACHE_H /************************************************************************* * * @macro: * FT_CACHE_SMALL_BITMAPS_H * * @description: * A macro used in #include statements to name the file containing the * `small bitmaps' API of the FreeType~2 cache sub-system. * * It is used to define a cache for small glyph bitmaps in a relatively * memory-efficient way. You can also use the API defined in * @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images, * including scalable outlines. * * This macro is deprecated. Simply include @FT_CACHE_H to have all * small bitmaps-related cache declarations. * */ #define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H /************************************************************************* * * @macro: * FT_CACHE_CHARMAP_H * * @description: * A macro used in #include statements to name the file containing the * `charmap' API of the FreeType~2 cache sub-system. * * This macro is deprecated. Simply include @FT_CACHE_H to have all * charmap-based cache declarations. * */ #define FT_CACHE_CHARMAP_H FT_CACHE_H /************************************************************************* * * @macro: * FT_MAC_H * * @description: * A macro used in #include statements to name the file containing the * Macintosh-specific FreeType~2 API. The latter is used to access * fonts embedded in resource forks. * * This header file must be explicitly included by client applications * compiled on the Mac (note that the base API still works though). * */ #define FT_MAC_H <freetype/ftmac.h> /************************************************************************* * * @macro: * FT_MULTIPLE_MASTERS_H * * @description: * A macro used in #include statements to name the file containing the * optional multiple-masters management API of FreeType~2. * */ #define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h> /************************************************************************* * * @macro: * FT_SFNT_NAMES_H * * @description: * A macro used in #include statements to name the file containing the * optional FreeType~2 API which accesses embedded `name' strings in * SFNT-based font formats (i.e., TrueType and OpenType). * */ #define FT_SFNT_NAMES_H <freetype/ftsnames.h> /************************************************************************* * * @macro: * FT_OPENTYPE_VALIDATE_H * * @description: * A macro used in #include statements to name the file containing the * optional FreeType~2 API which validates OpenType tables (BASE, GDEF, * GPOS, GSUB, JSTF). * */ #define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h> /************************************************************************* * * @macro: * FT_GX_VALIDATE_H * * @description: * A macro used in #include statements to name the file containing the * optional FreeType~2 API which validates TrueTypeGX/AAT tables (feat, * mort, morx, bsln, just, kern, opbd, trak, prop). * */ #define FT_GX_VALIDATE_H <freetype/ftgxval.h> /************************************************************************* * * @macro: * FT_PFR_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which accesses PFR-specific data. * */ #define FT_PFR_H <freetype/ftpfr.h> /************************************************************************* * * @macro: * FT_STROKER_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which provides functions to stroke outline paths. */ #define FT_STROKER_H <freetype/ftstroke.h> /************************************************************************* * * @macro: * FT_SYNTHESIS_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which performs artificial obliquing and emboldening. */ #define FT_SYNTHESIS_H <freetype/ftsynth.h> /************************************************************************* * * @macro: * FT_XFREE86_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which provides functions specific to the XFree86 and * X.Org X11 servers. */ #define FT_XFREE86_H <freetype/ftxf86.h> /************************************************************************* * * @macro: * FT_TRIGONOMETRY_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which performs trigonometric computations (e.g., * cosines and arc tangents). */ #define FT_TRIGONOMETRY_H <freetype/fttrigon.h> /************************************************************************* * * @macro: * FT_LCD_FILTER_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which performs color filtering for subpixel rendering. */ #define FT_LCD_FILTER_H <freetype/ftlcdfil.h> /************************************************************************* * * @macro: * FT_UNPATENTED_HINTING_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which performs color filtering for subpixel rendering. */ #define FT_UNPATENTED_HINTING_H <freetype/ttunpat.h> /************************************************************************* * * @macro: * FT_INCREMENTAL_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which performs color filtering for subpixel rendering. */ #define FT_INCREMENTAL_H <freetype/ftincrem.h> /************************************************************************* * * @macro: * FT_GASP_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which returns entries from the TrueType GASP table. */ #define FT_GASP_H <freetype/ftgasp.h> /************************************************************************* * * @macro: * FT_ADVANCES_H * * @description: * A macro used in #include statements to name the file containing the * FreeType~2 API which returns individual and ranged glyph advances. */ #define FT_ADVANCES_H <freetype/ftadvanc.h> /* */ #define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h> /* The internals of the cache sub-system are no longer exposed. We */ /* default to FT_CACHE_H at the moment just in case, but we know of */ /* no rogue client that uses them. */ /* */ #define FT_CACHE_MANAGER_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_MRU_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_MANAGER_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_CACHE_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_GLYPH_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_IMAGE_H <freetype/ftcache.h> #define FT_CACHE_INTERNAL_SBITS_H <freetype/ftcache.h> #define FT_INCREMENTAL_H <freetype/ftincrem.h> #define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h> /* * Include internal headers definitions from <freetype/internal/...> * only when building the library. */ #ifdef FT2_BUILD_LIBRARY #define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h> #include FT_INTERNAL_INTERNAL_H #endif /* FT2_BUILD_LIBRARY */ #endif /* __FT2_BUILD_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/config/ftmodule.h ================================================ /* This is a generated file. */ FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) FT_USE_MODULE( FT_Module_Class, autofit_module_class ) FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) FT_USE_MODULE( FT_Module_Class, otv_module_class ) FT_USE_MODULE( FT_Module_Class, psaux_module_class ) FT_USE_MODULE( FT_Module_Class, psnames_module_class ) /* EOF */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/config/ftoption.h ================================================ /***************************************************************************/ /* */ /* ftoption.h */ /* */ /* User-selectable configuration macros (specification only). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTOPTION_H__ #define __FTOPTION_H__ #include <ft2build.h> FT_BEGIN_HEADER /*************************************************************************/ /* */ /* USER-SELECTABLE CONFIGURATION MACROS */ /* */ /* This file contains the default configuration macro definitions for */ /* a standard build of the FreeType library. There are three ways to */ /* use this file to build project-specific versions of the library: */ /* */ /* - You can modify this file by hand, but this is not recommended in */ /* cases where you would like to build several versions of the */ /* library from a single source directory. */ /* */ /* - You can put a copy of this file in your build directory, more */ /* precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD' */ /* is the name of a directory that is included _before_ the FreeType */ /* include path during compilation. */ /* */ /* The default FreeType Makefiles and Jamfiles use the build */ /* directory `builds/<system>' by default, but you can easily change */ /* that for your own projects. */ /* */ /* - Copy the file <ft2build.h> to `$BUILD/ft2build.h' and modify it */ /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */ /* locate this file during the build. For example, */ /* */ /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */ /* #include <freetype/config/ftheader.h> */ /* */ /* will use `$BUILD/myftoptions.h' instead of this file for macro */ /* definitions. */ /* */ /* Note also that you can similarly pre-define the macro */ /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */ /* that are statically linked to the library at compile time. By */ /* default, this file is <freetype/config/ftmodule.h>. */ /* */ /* We highly recommend using the third method whenever possible. */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* Uncomment the line below if you want to activate sub-pixel rendering */ /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */ /* */ /* Note that this feature is covered by several Microsoft patents */ /* and should not be activated in any default build of the library. */ /* */ /* This macro has no impact on the FreeType API, only on its */ /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */ /* FT_Render_Glyph still generates a bitmap that is 3 times larger than */ /* the original size; the difference will be that each triplet of */ /* subpixels has R=G=B. */ /* */ /* This is done to allow FreeType clients to run unmodified, forcing */ /* them to display normal gray-level anti-aliased glyphs. */ /* */ /* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ /*************************************************************************/ /* */ /* Many compilers provide a non-ANSI 64-bit data type that can be used */ /* by FreeType to speed up some computations. However, this will create */ /* some problems when compiling the library in strict ANSI mode. */ /* */ /* For this reason, the use of 64-bit integers is normally disabled when */ /* the __STDC__ macro is defined. You can however disable this by */ /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */ /* */ /* For most compilers, this will only create compilation warnings when */ /* building the library. */ /* */ /* ObNote: The compiler-specific 64-bit integers are detected in the */ /* file `ftconfig.h' either statically or through the */ /* `configure' script on supported platforms. */ /* */ #undef FT_CONFIG_OPTION_FORCE_INT64 /*************************************************************************/ /* */ /* If this macro is defined, do not try to use an assembler version of */ /* performance-critical functions (e.g. FT_MulFix). You should only do */ /* that to verify that the assembler function works properly, or to */ /* execute benchmark tests of the various implementations. */ /* #define FT_CONFIG_OPTION_NO_ASSEMBLER */ /*************************************************************************/ /* */ /* If this macro is defined, try to use an inlined assembler version of */ /* the `FT_MulFix' function, which is a `hotspot' when loading and */ /* hinting glyphs, and which should be executed as fast as possible. */ /* */ /* Note that if your compiler or CPU is not supported, this will default */ /* to the standard and portable implementation found in `ftcalc.c'. */ /* */ #define FT_CONFIG_OPTION_INLINE_MULFIX /*************************************************************************/ /* */ /* LZW-compressed file support. */ /* */ /* FreeType now handles font files that have been compressed with the */ /* `compress' program. This is mostly used to parse many of the PCF */ /* files that come with various X11 distributions. The implementation */ /* uses NetBSD's `zopen' to partially uncompress the file on the fly */ /* (see src/lzw/ftgzip.c). */ /* */ /* Define this macro if you want to enable this `feature'. */ /* */ #define FT_CONFIG_OPTION_USE_LZW /*************************************************************************/ /* */ /* Gzip-compressed file support. */ /* */ /* FreeType now handles font files that have been compressed with the */ /* `gzip' program. This is mostly used to parse many of the PCF files */ /* that come with XFree86. The implementation uses `zlib' to */ /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */ /* */ /* Define this macro if you want to enable this `feature'. See also */ /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ /* */ #define FT_CONFIG_OPTION_USE_ZLIB /*************************************************************************/ /* */ /* ZLib library selection */ /* */ /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */ /* It allows FreeType's `ftgzip' component to link to the system's */ /* installation of the ZLib library. This is useful on systems like */ /* Unix or VMS where it generally is already available. */ /* */ /* If you let it undefined, the component will use its own copy */ /* of the zlib sources instead. These have been modified to be */ /* included directly within the component and *not* export external */ /* function names. This allows you to link any program with FreeType */ /* _and_ ZLib without linking conflicts. */ /* */ /* Do not #undef this macro here since the build system might define */ /* it for certain configurations only. */ /* */ /* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ /*************************************************************************/ /* */ /* DLL export compilation */ /* */ /* When compiling FreeType as a DLL, some systems/compilers need a */ /* special keyword in front OR after the return type of function */ /* declarations. */ /* */ /* Two macros are used within the FreeType source code to define */ /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */ /* */ /* FT_EXPORT( return_type ) */ /* */ /* is used in a function declaration, as in */ /* */ /* FT_EXPORT( FT_Error ) */ /* FT_Init_FreeType( FT_Library* alibrary ); */ /* */ /* */ /* FT_EXPORT_DEF( return_type ) */ /* */ /* is used in a function definition, as in */ /* */ /* FT_EXPORT_DEF( FT_Error ) */ /* FT_Init_FreeType( FT_Library* alibrary ) */ /* { */ /* ... some code ... */ /* return FT_Err_Ok; */ /* } */ /* */ /* You can provide your own implementation of FT_EXPORT and */ /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */ /* will be later automatically defined as `extern return_type' to */ /* allow normal compilation. */ /* */ /* Do not #undef these macros here since the build system might define */ /* them for certain configurations only. */ /* */ /* #define FT_EXPORT(x) extern x */ /* #define FT_EXPORT_DEF(x) x */ /*************************************************************************/ /* */ /* Glyph Postscript Names handling */ /* */ /* By default, FreeType 2 is compiled with the `psnames' module. This */ /* module is in charge of converting a glyph name string into a */ /* Unicode value, or return a Macintosh standard glyph name for the */ /* use with the TrueType `post' table. */ /* */ /* Undefine this macro if you do not want `psnames' compiled in your */ /* build of FreeType. This has the following effects: */ /* */ /* - The TrueType driver will provide its own set of glyph names, */ /* if you build it to support postscript names in the TrueType */ /* `post' table. */ /* */ /* - The Type 1 driver will not be able to synthesize a Unicode */ /* charmap out of the glyphs found in the fonts. */ /* */ /* You would normally undefine this configuration macro when building */ /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ /* */ #define FT_CONFIG_OPTION_POSTSCRIPT_NAMES /*************************************************************************/ /* */ /* Postscript Names to Unicode Values support */ /* */ /* By default, FreeType 2 is built with the `PSNames' module compiled */ /* in. Among other things, the module is used to convert a glyph name */ /* into a Unicode value. This is especially useful in order to */ /* synthesize on the fly a Unicode charmap from the CFF/Type 1 driver */ /* through a big table named the `Adobe Glyph List' (AGL). */ /* */ /* Undefine this macro if you do not want the Adobe Glyph List */ /* compiled in your `PSNames' module. The Type 1 driver will not be */ /* able to synthesize a Unicode charmap out of the glyphs found in the */ /* fonts. */ /* */ #define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST /*************************************************************************/ /* */ /* Support for Mac fonts */ /* */ /* Define this macro if you want support for outline fonts in Mac */ /* format (mac dfont, mac resource, macbinary containing a mac */ /* resource) on non-Mac platforms. */ /* */ /* Note that the `FOND' resource isn't checked. */ /* */ #define FT_CONFIG_OPTION_MAC_FONTS /*************************************************************************/ /* */ /* Guessing methods to access embedded resource forks */ /* */ /* Enable extra Mac fonts support on non-Mac platforms (e.g. */ /* GNU/Linux). */ /* */ /* Resource forks which include fonts data are stored sometimes in */ /* locations which users or developers don't expected. In some cases, */ /* resource forks start with some offset from the head of a file. In */ /* other cases, the actual resource fork is stored in file different */ /* from what the user specifies. If this option is activated, */ /* FreeType tries to guess whether such offsets or different file */ /* names must be used. */ /* */ /* Note that normal, direct access of resource forks is controlled via */ /* the FT_CONFIG_OPTION_MAC_FONTS option. */ /* */ #ifdef FT_CONFIG_OPTION_MAC_FONTS #define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK #endif /*************************************************************************/ /* */ /* Allow the use of FT_Incremental_Interface to load typefaces that */ /* contain no glyph data, but supply it via a callback function. */ /* This allows FreeType to be used with the PostScript language, using */ /* the GhostScript interpreter. */ /* */ /* #define FT_CONFIG_OPTION_INCREMENTAL */ /*************************************************************************/ /* */ /* The size in bytes of the render pool used by the scan-line converter */ /* to do all of its work. */ /* */ /* This must be greater than 4KByte if you use FreeType to rasterize */ /* glyphs; otherwise, you may set it to zero to avoid unnecessary */ /* allocation of the render pool. */ /* */ #define FT_RENDER_POOL_SIZE 16384L /*************************************************************************/ /* */ /* FT_MAX_MODULES */ /* */ /* The maximum number of modules that can be registered in a single */ /* FreeType library object. 32 is the default. */ /* */ #define FT_MAX_MODULES 32 /*************************************************************************/ /* */ /* Debug level */ /* */ /* FreeType can be compiled in debug or trace mode. In debug mode, */ /* errors are reported through the `ftdebug' component. In trace */ /* mode, additional messages are sent to the standard output during */ /* execution. */ /* */ /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ /* */ /* Don't define any of these macros to compile in `release' mode! */ /* */ /* Do not #undef these macros here since the build system might define */ /* them for certain configurations only. */ /* */ /* #define FT_DEBUG_LEVEL_ERROR */ /* #define FT_DEBUG_LEVEL_TRACE */ /*************************************************************************/ /* */ /* Memory Debugging */ /* */ /* FreeType now comes with an integrated memory debugger that is */ /* capable of detecting simple errors like memory leaks or double */ /* deletes. To compile it within your build of the library, you */ /* should define FT_DEBUG_MEMORY here. */ /* */ /* Note that the memory debugger is only activated at runtime when */ /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */ /* */ /* Do not #undef this macro here since the build system might define */ /* it for certain configurations only. */ /* */ /* #define FT_DEBUG_MEMORY */ /*************************************************************************/ /* */ /* Module errors */ /* */ /* If this macro is set (which is _not_ the default), the higher byte */ /* of an error code gives the module in which the error has occurred, */ /* while the lower byte is the real error code. */ /* */ /* Setting this macro makes sense for debugging purposes only, since */ /* it would break source compatibility of certain programs that use */ /* FreeType 2. */ /* */ /* More details can be found in the files ftmoderr.h and fterrors.h. */ /* */ #undef FT_CONFIG_OPTION_USE_MODULE_ERRORS /*************************************************************************/ /* */ /* Position Independent Code */ /* */ /* If this macro is set (which is _not_ the default), FreeType2 will */ /* avoid creating constants that require address fixups. Instead the */ /* constants will be moved into a struct and additional intialization */ /* code will be used. */ /* */ /* Setting this macro is needed for systems that prohibit address */ /* fixups, such as BREW. */ /* */ /* #define FT_CONFIG_OPTION_PIC */ /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ /* embedded bitmaps in all formats using the SFNT module (namely */ /* TrueType & OpenType). */ /* */ #define TT_CONFIG_OPTION_EMBEDDED_BITMAPS /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ /* load and enumerate the glyph Postscript names in a TrueType or */ /* OpenType file. */ /* */ /* Note that when you do not compile the `PSNames' module by undefining */ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ /* contain additional code used to read the PS Names table from a font. */ /* */ /* (By default, the module uses `PSNames' to extract glyph names.) */ /* */ #define TT_CONFIG_OPTION_POSTSCRIPT_NAMES /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ /* access the internal name table in a SFNT-based format like TrueType */ /* or OpenType. The name table contains various strings used to */ /* describe the font, like family name, copyright, version, etc. It */ /* does not contain any glyph name though. */ /* */ /* Accessing SFNT names is done through the functions declared in */ /* `freetype/ftsnames.h'. */ /* */ #define TT_CONFIG_OPTION_SFNT_NAMES /*************************************************************************/ /* */ /* TrueType CMap support */ /* */ /* Here you can fine-tune which TrueType CMap table format shall be */ /* supported. */ #define TT_CONFIG_CMAP_FORMAT_0 #define TT_CONFIG_CMAP_FORMAT_2 #define TT_CONFIG_CMAP_FORMAT_4 #define TT_CONFIG_CMAP_FORMAT_6 #define TT_CONFIG_CMAP_FORMAT_8 #define TT_CONFIG_CMAP_FORMAT_10 #define TT_CONFIG_CMAP_FORMAT_12 #define TT_CONFIG_CMAP_FORMAT_13 #define TT_CONFIG_CMAP_FORMAT_14 /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ /* a bytecode interpreter in the TrueType driver. Note that there are */ /* important patent issues related to the use of the interpreter. */ /* */ /* By undefining this, you will only compile the code necessary to load */ /* TrueType glyphs without hinting. */ /* */ /* Do not #undef this macro here, since the build system might */ /* define it for certain configurations only. */ /* */ /* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ /*************************************************************************/ /* */ /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ /* of the TrueType bytecode interpreter is used that doesn't implement */ /* any of the patented opcodes and algorithms. Note that the */ /* TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* if you define */ /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, either define */ /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */ /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */ /* */ /* This macro is only useful for a small number of font files (mostly */ /* for Asian scripts) that require bytecode interpretation to properly */ /* load glyphs. For all other fonts, this produces unpleasant results, */ /* thus the unpatented interpreter is never used to load glyphs from */ /* TrueType fonts unless one of the following two options is used. */ /* */ /* - The unpatented interpreter is explicitly activated by the user */ /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */ /* when opening the FT_Face. */ /* */ /* - FreeType detects that the FT_Face corresponds to one of the */ /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */ /* contains a hard-coded list of font names and other matching */ /* parameters (see function `tt_face_init' in file */ /* `src/truetype/ttobjs.c'). */ /* */ /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */ /* */ /* { */ /* FT_Parameter parameter; */ /* FT_Open_Args open_args; */ /* */ /* */ /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */ /* */ /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */ /* open_args.pathname = my_font_pathname; */ /* open_args.num_params = 1; */ /* open_args.params = ¶meter; */ /* */ /* error = FT_Open_Face( library, &open_args, index, &face ); */ /* ... */ /* } */ /* */ #define TT_CONFIG_OPTION_UNPATENTED_HINTING /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ /* bytecode interpreter with a huge switch statement, rather than a call */ /* table. This results in smaller and faster code for a number of */ /* architectures. */ /* */ /* Note however that on some compiler/processor combinations, undefining */ /* this macro will generate faster, though larger, code. */ /* */ #define TT_CONFIG_OPTION_INTERPRETER_SWITCH /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */ /* TrueType glyph loader to use Apple's definition of how to handle */ /* component offsets in composite glyphs. */ /* */ /* Apple and MS disagree on the default behavior of component offsets */ /* in composites. Apple says that they should be scaled by the scaling */ /* factors in the transformation matrix (roughly, it's more complex) */ /* while MS says they should not. OpenType defines two bits in the */ /* composite flags array which can be used to disambiguate, but old */ /* fonts will not have them. */ /* */ /* http://partners.adobe.com/asn/developer/opentype/glyf.html */ /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */ /* */ #undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */ /* support for Apple's distortable font technology (fvar, gvar, cvar, */ /* and avar tables). This has many similarities to Type 1 Multiple */ /* Masters support. */ /* */ #define TT_CONFIG_OPTION_GX_VAR_SUPPORT /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_BDF if you want to include support for */ /* an embedded `BDF ' table within SFNT-based bitmap formats. */ /* */ #define TT_CONFIG_OPTION_BDF /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ /* required. */ /* */ #define T1_MAX_DICT_DEPTH 5 /*************************************************************************/ /* */ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ /* calls during glyph loading. */ /* */ #define T1_MAX_SUBRS_CALLS 16 /*************************************************************************/ /* */ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ /* minimum of 16 is required. */ /* */ /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ /* */ #define T1_MAX_CHARSTRINGS_OPERANDS 256 /*************************************************************************/ /* */ /* Define this configuration macro if you want to prevent the */ /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ /* files into an existing face. Note that if set, the T1 driver will be */ /* unable to produce kerning distances. */ /* */ #undef T1_CONFIG_OPTION_NO_AFM /*************************************************************************/ /* */ /* Define this configuration macro if you want to prevent the */ /* compilation of the Multiple Masters font support in the Type 1 */ /* driver. */ /* */ #undef T1_CONFIG_OPTION_NO_MM_SUPPORT /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* Compile autofit module with CJK (Chinese, Japanese, Korean) script */ /* support. */ /* */ #define AF_CONFIG_OPTION_CJK /*************************************************************************/ /* */ /* Compile autofit module with Indic script support. */ /* */ #define AF_CONFIG_OPTION_INDIC /* */ /* * Define this variable if you want to keep the layout of internal * structures that was used prior to FreeType 2.2. This also compiles in * a few obsolete functions to avoid linking problems on typical Unix * distributions. * * For embedded systems or building a new distribution from scratch, it * is recommended to disable the macro since it reduces the library's code * size and activates a few memory-saving optimizations as well. */ #define FT_CONFIG_OPTION_OLD_INTERNALS /* * This macro is defined if either unpatented or native TrueType * hinting is requested by the definitions above. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER #undef TT_CONFIG_OPTION_UNPATENTED_HINTING #elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING #define TT_USE_BYTECODE_INTERPRETER #endif FT_END_HEADER #endif /* __FTOPTION_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/config/ftstdlib.h ================================================ /***************************************************************************/ /* */ /* ftstdlib.h */ /* */ /* ANSI-specific library and header configuration file (specification */ /* only). */ /* */ /* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This file is used to group all #includes to the ANSI C library that */ /* FreeType normally requires. It also defines macros to rename the */ /* standard functions within the FreeType source code. */ /* */ /* Load a file which defines __FTSTDLIB_H__ before this one to override */ /* it. */ /* */ /*************************************************************************/ #ifndef __FTSTDLIB_H__ #define __FTSTDLIB_H__ #include <stddef.h> #define ft_ptrdiff_t ptrdiff_t /**********************************************************************/ /* */ /* integer limits */ /* */ /* UINT_MAX and ULONG_MAX are used to automatically compute the size */ /* of `int' and `long' in bytes at compile-time. So far, this works */ /* for all platforms the library has been tested on. */ /* */ /* Note that on the extremely rare platforms that do not provide */ /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */ /* old Crays where `int' is 36 bits), we do not make any guarantee */ /* about the correct behaviour of FT2 with all fonts. */ /* */ /* In these case, `ftconfig.h' will refuse to compile anyway with a */ /* message like `couldn't find 32-bit type' or something similar. */ /* */ /**********************************************************************/ #include <limits.h> #define FT_CHAR_BIT CHAR_BIT #define FT_INT_MAX INT_MAX #define FT_INT_MIN INT_MIN #define FT_UINT_MAX UINT_MAX #define FT_ULONG_MAX ULONG_MAX /**********************************************************************/ /* */ /* character and string processing */ /* */ /**********************************************************************/ #include <string.h> #define ft_memchr memchr #define ft_memcmp memcmp #define ft_memcpy memcpy #define ft_memmove memmove #define ft_memset memset #define ft_strcat strcat #define ft_strcmp strcmp #define ft_strcpy strcpy #define ft_strlen strlen #define ft_strncmp strncmp #define ft_strncpy strncpy #define ft_strrchr strrchr #define ft_strstr strstr /**********************************************************************/ /* */ /* file handling */ /* */ /**********************************************************************/ #include <stdio.h> #define FT_FILE FILE #define ft_fclose fclose #define ft_fopen fopen #define ft_fread fread #define ft_fseek fseek #define ft_ftell ftell #define ft_sprintf sprintf /**********************************************************************/ /* */ /* sorting */ /* */ /**********************************************************************/ #include <stdlib.h> #define ft_qsort qsort /**********************************************************************/ /* */ /* memory allocation */ /* */ /**********************************************************************/ #define ft_scalloc calloc #define ft_sfree free #define ft_smalloc malloc #define ft_srealloc realloc /**********************************************************************/ /* */ /* miscellaneous */ /* */ /**********************************************************************/ #define ft_atol atol #define ft_labs labs /**********************************************************************/ /* */ /* execution control */ /* */ /**********************************************************************/ #include <setjmp.h> #define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */ /* jmp_buf is defined as a macro */ /* on certain platforms */ #define ft_longjmp longjmp #define ft_setjmp( b ) setjmp( *(jmp_buf*) &(b) ) /* same thing here */ /* the following is only used for debugging purposes, i.e., if */ /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */ #include <stdarg.h> #endif /* __FTSTDLIB_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/freetype.h ================================================ /***************************************************************************/ /* */ /* freetype.h */ /* */ /* FreeType high-level API and common types (specification only). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef FT_FREETYPE_H #error "`ft2build.h' hasn't been included yet!" #error "Please always use macros to include FreeType header files." #error "Example:" #error " #include <ft2build.h>" #error " #include FT_FREETYPE_H" #endif #ifndef __FREETYPE_H__ #define __FREETYPE_H__ #include <ft2build.h> #include FT_CONFIG_CONFIG_H #include FT_ERRORS_H #include FT_TYPES_H FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* user_allocation */ /* */ /* <Title> */ /* User allocation */ /* */ /* <Abstract> */ /* How client applications should allocate FreeType data structures. */ /* */ /* <Description> */ /* FreeType assumes that structures allocated by the user and passed */ /* as arguments are zeroed out except for the actual data. In other */ /* words, it is recommended to use `calloc' (or variants of it) */ /* instead of `malloc' for allocation. */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* B A S I C T Y P E S */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Section> */ /* base_interface */ /* */ /* <Title> */ /* Base Interface */ /* */ /* <Abstract> */ /* The FreeType~2 base font interface. */ /* */ /* <Description> */ /* This section describes the public high-level API of FreeType~2. */ /* */ /* <Order> */ /* FT_Library */ /* FT_Face */ /* FT_Size */ /* FT_GlyphSlot */ /* FT_CharMap */ /* FT_Encoding */ /* */ /* FT_FaceRec */ /* */ /* FT_FACE_FLAG_SCALABLE */ /* FT_FACE_FLAG_FIXED_SIZES */ /* FT_FACE_FLAG_FIXED_WIDTH */ /* FT_FACE_FLAG_HORIZONTAL */ /* FT_FACE_FLAG_VERTICAL */ /* FT_FACE_FLAG_SFNT */ /* FT_FACE_FLAG_KERNING */ /* FT_FACE_FLAG_MULTIPLE_MASTERS */ /* FT_FACE_FLAG_GLYPH_NAMES */ /* FT_FACE_FLAG_EXTERNAL_STREAM */ /* FT_FACE_FLAG_FAST_GLYPHS */ /* FT_FACE_FLAG_HINTER */ /* */ /* FT_STYLE_FLAG_BOLD */ /* FT_STYLE_FLAG_ITALIC */ /* */ /* FT_SizeRec */ /* FT_Size_Metrics */ /* */ /* FT_GlyphSlotRec */ /* FT_Glyph_Metrics */ /* FT_SubGlyph */ /* */ /* FT_Bitmap_Size */ /* */ /* FT_Init_FreeType */ /* FT_Done_FreeType */ /* */ /* FT_New_Face */ /* FT_Done_Face */ /* FT_New_Memory_Face */ /* FT_Open_Face */ /* FT_Open_Args */ /* FT_Parameter */ /* FT_Attach_File */ /* FT_Attach_Stream */ /* */ /* FT_Set_Char_Size */ /* FT_Set_Pixel_Sizes */ /* FT_Request_Size */ /* FT_Select_Size */ /* FT_Size_Request_Type */ /* FT_Size_Request */ /* FT_Set_Transform */ /* FT_Load_Glyph */ /* FT_Get_Char_Index */ /* FT_Get_Name_Index */ /* FT_Load_Char */ /* */ /* FT_OPEN_MEMORY */ /* FT_OPEN_STREAM */ /* FT_OPEN_PATHNAME */ /* FT_OPEN_DRIVER */ /* FT_OPEN_PARAMS */ /* */ /* FT_LOAD_DEFAULT */ /* FT_LOAD_RENDER */ /* FT_LOAD_MONOCHROME */ /* FT_LOAD_LINEAR_DESIGN */ /* FT_LOAD_NO_SCALE */ /* FT_LOAD_NO_HINTING */ /* FT_LOAD_NO_BITMAP */ /* FT_LOAD_CROP_BITMAP */ /* */ /* FT_LOAD_VERTICAL_LAYOUT */ /* FT_LOAD_IGNORE_TRANSFORM */ /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ /* FT_LOAD_FORCE_AUTOHINT */ /* FT_LOAD_NO_RECURSE */ /* FT_LOAD_PEDANTIC */ /* */ /* FT_LOAD_TARGET_NORMAL */ /* FT_LOAD_TARGET_LIGHT */ /* FT_LOAD_TARGET_MONO */ /* FT_LOAD_TARGET_LCD */ /* FT_LOAD_TARGET_LCD_V */ /* */ /* FT_Render_Glyph */ /* FT_Render_Mode */ /* FT_Get_Kerning */ /* FT_Kerning_Mode */ /* FT_Get_Track_Kerning */ /* FT_Get_Glyph_Name */ /* FT_Get_Postscript_Name */ /* */ /* FT_CharMapRec */ /* FT_Select_Charmap */ /* FT_Set_Charmap */ /* FT_Get_Charmap_Index */ /* */ /* FT_FSTYPE_INSTALLABLE_EMBEDDING */ /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING */ /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING */ /* FT_FSTYPE_EDITABLE_EMBEDDING */ /* FT_FSTYPE_NO_SUBSETTING */ /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY */ /* */ /* FT_Get_FSType_Flags */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Struct> */ /* FT_Glyph_Metrics */ /* */ /* <Description> */ /* A structure used to model the metrics of a single glyph. The */ /* values are expressed in 26.6 fractional pixel format; if the flag */ /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */ /* are expressed in font units instead. */ /* */ /* <Fields> */ /* width :: */ /* The glyph's width. */ /* */ /* height :: */ /* The glyph's height. */ /* */ /* horiBearingX :: */ /* Left side bearing for horizontal layout. */ /* */ /* horiBearingY :: */ /* Top side bearing for horizontal layout. */ /* */ /* horiAdvance :: */ /* Advance width for horizontal layout. */ /* */ /* vertBearingX :: */ /* Left side bearing for vertical layout. */ /* */ /* vertBearingY :: */ /* Top side bearing for vertical layout. */ /* */ /* vertAdvance :: */ /* Advance height for vertical layout. */ /* */ typedef struct FT_Glyph_Metrics_ { FT_Pos width; FT_Pos height; FT_Pos horiBearingX; FT_Pos horiBearingY; FT_Pos horiAdvance; FT_Pos vertBearingX; FT_Pos vertBearingY; FT_Pos vertAdvance; } FT_Glyph_Metrics; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Bitmap_Size */ /* */ /* <Description> */ /* This structure models the metrics of a bitmap strike (i.e., a set */ /* of glyphs for a given point size and resolution) in a bitmap font. */ /* It is used for the `available_sizes' field of @FT_Face. */ /* */ /* <Fields> */ /* height :: The vertical distance, in pixels, between two */ /* consecutive baselines. It is always positive. */ /* */ /* width :: The average width, in pixels, of all glyphs in the */ /* strike. */ /* */ /* size :: The nominal size of the strike in 26.6 fractional */ /* points. This field is not very useful. */ /* */ /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */ /* pixels. */ /* */ /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */ /* pixels. */ /* */ /* <Note> */ /* Windows FNT: */ /* The nominal size given in a FNT font is not reliable. Thus when */ /* the driver finds it incorrect, it sets `size' to some calculated */ /* values and sets `x_ppem' and `y_ppem' to the pixel width and */ /* height given in the font, respectively. */ /* */ /* TrueType embedded bitmaps: */ /* `size', `width', and `height' values are not contained in the */ /* bitmap strike itself. They are computed from the global font */ /* parameters. */ /* */ typedef struct FT_Bitmap_Size_ { FT_Short height; FT_Short width; FT_Pos size; FT_Pos x_ppem; FT_Pos y_ppem; } FT_Bitmap_Size; /*************************************************************************/ /*************************************************************************/ /* */ /* O B J E C T C L A S S E S */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_Library */ /* */ /* <Description> */ /* A handle to a FreeType library instance. Each `library' is */ /* completely independent from the others; it is the `root' of a set */ /* of objects like fonts, faces, sizes, etc. */ /* */ /* It also embeds a memory manager (see @FT_Memory), as well as a */ /* scan-line converter object (see @FT_Raster). */ /* */ /* For multi-threading applications each thread should have its own */ /* FT_Library object. */ /* */ /* <Note> */ /* Library objects are normally created by @FT_Init_FreeType, and */ /* destroyed with @FT_Done_FreeType. */ /* */ typedef struct FT_LibraryRec_ *FT_Library; /*************************************************************************/ /* */ /* <Type> */ /* FT_Module */ /* */ /* <Description> */ /* A handle to a given FreeType module object. Each module can be a */ /* font driver, a renderer, or anything else that provides services */ /* to the formers. */ /* */ typedef struct FT_ModuleRec_* FT_Module; /*************************************************************************/ /* */ /* <Type> */ /* FT_Driver */ /* */ /* <Description> */ /* A handle to a given FreeType font driver object. Each font driver */ /* is a special module capable of creating faces from font files. */ /* */ typedef struct FT_DriverRec_* FT_Driver; /*************************************************************************/ /* */ /* <Type> */ /* FT_Renderer */ /* */ /* <Description> */ /* A handle to a given FreeType renderer. A renderer is a special */ /* module in charge of converting a glyph image to a bitmap, when */ /* necessary. Each renderer supports a given glyph image format, and */ /* one or more target surface depths. */ /* */ typedef struct FT_RendererRec_* FT_Renderer; /*************************************************************************/ /* */ /* <Type> */ /* FT_Face */ /* */ /* <Description> */ /* A handle to a given typographic face object. A face object models */ /* a given typeface, in a given style. */ /* */ /* <Note> */ /* Each face object also owns a single @FT_GlyphSlot object, as well */ /* as one or more @FT_Size objects. */ /* */ /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */ /* a given filepathname or a custom input stream. */ /* */ /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */ /* */ /* <Also> */ /* See @FT_FaceRec for the publicly accessible fields of a given face */ /* object. */ /* */ typedef struct FT_FaceRec_* FT_Face; /*************************************************************************/ /* */ /* <Type> */ /* FT_Size */ /* */ /* <Description> */ /* A handle to an object used to model a face scaled to a given */ /* character size. */ /* */ /* <Note> */ /* Each @FT_Face has an _active_ @FT_Size object that is used by */ /* functions like @FT_Load_Glyph to determine the scaling */ /* transformation which is used to load and hint glyphs and metrics. */ /* */ /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */ /* @FT_Request_Size or even @FT_Select_Size to change the content */ /* (i.e., the scaling values) of the active @FT_Size. */ /* */ /* You can use @FT_New_Size to create additional size objects for a */ /* given @FT_Face, but they won't be used by other functions until */ /* you activate it through @FT_Activate_Size. Only one size can be */ /* activated at any given time per face. */ /* */ /* <Also> */ /* See @FT_SizeRec for the publicly accessible fields of a given size */ /* object. */ /* */ typedef struct FT_SizeRec_* FT_Size; /*************************************************************************/ /* */ /* <Type> */ /* FT_GlyphSlot */ /* */ /* <Description> */ /* A handle to a given `glyph slot'. A slot is a container where it */ /* is possible to load any of the glyphs contained in its parent */ /* face. */ /* */ /* In other words, each time you call @FT_Load_Glyph or */ /* @FT_Load_Char, the slot's content is erased by the new glyph data, */ /* i.e., the glyph's metrics, its image (bitmap or outline), and */ /* other control information. */ /* */ /* <Also> */ /* See @FT_GlyphSlotRec for the publicly accessible glyph fields. */ /* */ typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; /*************************************************************************/ /* */ /* <Type> */ /* FT_CharMap */ /* */ /* <Description> */ /* A handle to a given character map. A charmap is used to translate */ /* character codes in a given encoding into glyph indexes for its */ /* parent's face. Some font formats may provide several charmaps per */ /* font. */ /* */ /* Each face object owns zero or more charmaps, but only one of them */ /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */ /* */ /* The list of available charmaps in a face is available through the */ /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */ /* */ /* The currently active charmap is available as `face->charmap'. */ /* You should call @FT_Set_Charmap to change it. */ /* */ /* <Note> */ /* When a new face is created (either through @FT_New_Face or */ /* @FT_Open_Face), the library looks for a Unicode charmap within */ /* the list and automatically activates it. */ /* */ /* <Also> */ /* See @FT_CharMapRec for the publicly accessible fields of a given */ /* character map. */ /* */ typedef struct FT_CharMapRec_* FT_CharMap; /*************************************************************************/ /* */ /* <Macro> */ /* FT_ENC_TAG */ /* */ /* <Description> */ /* This macro converts four-letter tags into an unsigned long. It is */ /* used to define `encoding' identifiers (see @FT_Encoding). */ /* */ /* <Note> */ /* Since many 16-bit compilers don't like 32-bit enumerations, you */ /* should redefine this macro in case of problems to something like */ /* this: */ /* */ /* { */ /* #define FT_ENC_TAG( value, a, b, c, d ) value */ /* } */ /* */ /* to get a simple enumeration without assigning special numbers. */ /* */ #ifndef FT_ENC_TAG #define FT_ENC_TAG( value, a, b, c, d ) \ value = ( ( (FT_UInt32)(a) << 24 ) | \ ( (FT_UInt32)(b) << 16 ) | \ ( (FT_UInt32)(c) << 8 ) | \ (FT_UInt32)(d) ) #endif /* FT_ENC_TAG */ /*************************************************************************/ /* */ /* <Enum> */ /* FT_Encoding */ /* */ /* <Description> */ /* An enumeration used to specify character sets supported by */ /* charmaps. Used in the @FT_Select_Charmap API function. */ /* */ /* <Note> */ /* Despite the name, this enumeration lists specific character */ /* repertories (i.e., charsets), and not text encoding methods (e.g., */ /* UTF-8, UTF-16, etc.). */ /* */ /* Other encodings might be defined in the future. */ /* */ /* <Values> */ /* FT_ENCODING_NONE :: */ /* The encoding value~0 is reserved. */ /* */ /* FT_ENCODING_UNICODE :: */ /* Corresponds to the Unicode character set. This value covers */ /* all versions of the Unicode repertoire, including ASCII and */ /* Latin-1. Most fonts include a Unicode charmap, but not all */ /* of them. */ /* */ /* For example, if you want to access Unicode value U+1F028 (and */ /* the font contains it), use value 0x1F028 as the input value for */ /* @FT_Get_Char_Index. */ /* */ /* FT_ENCODING_MS_SYMBOL :: */ /* Corresponds to the Microsoft Symbol encoding, used to encode */ /* mathematical symbols in the 32..255 character code range. For */ /* more information, see `http://www.ceviz.net/symbol.htm'. */ /* */ /* FT_ENCODING_SJIS :: */ /* Corresponds to Japanese SJIS encoding. More info at */ /* at `http://langsupport.japanreference.com/encoding.shtml'. */ /* See note on multi-byte encodings below. */ /* */ /* FT_ENCODING_GB2312 :: */ /* Corresponds to an encoding system for Simplified Chinese as used */ /* used in mainland China. */ /* */ /* FT_ENCODING_BIG5 :: */ /* Corresponds to an encoding system for Traditional Chinese as */ /* used in Taiwan and Hong Kong. */ /* */ /* FT_ENCODING_WANSUNG :: */ /* Corresponds to the Korean encoding system known as Wansung. */ /* For more information see */ /* `http://www.microsoft.com/typography/unicode/949.txt'. */ /* */ /* FT_ENCODING_JOHAB :: */ /* The Korean standard character set (KS~C 5601-1992), which */ /* corresponds to MS Windows code page 1361. This character set */ /* includes all possible Hangeul character combinations. */ /* */ /* FT_ENCODING_ADOBE_LATIN_1 :: */ /* Corresponds to a Latin-1 encoding as defined in a Type~1 */ /* PostScript font. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_ADOBE_STANDARD :: */ /* Corresponds to the Adobe Standard encoding, as found in Type~1, */ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ /* codes. */ /* */ /* FT_ENCODING_ADOBE_EXPERT :: */ /* Corresponds to the Adobe Expert encoding, as found in Type~1, */ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ /* codes. */ /* */ /* FT_ENCODING_ADOBE_CUSTOM :: */ /* Corresponds to a custom encoding, as found in Type~1, CFF, and */ /* OpenType/CFF fonts. It is limited to 256 character codes. */ /* */ /* FT_ENCODING_APPLE_ROMAN :: */ /* Corresponds to the 8-bit Apple roman encoding. Many TrueType */ /* and OpenType fonts contain a charmap for this encoding, since */ /* older versions of Mac OS are able to use it. */ /* */ /* FT_ENCODING_OLD_LATIN_2 :: */ /* This value is deprecated and was never used nor reported by */ /* FreeType. Don't use or test for it. */ /* */ /* FT_ENCODING_MS_SJIS :: */ /* Same as FT_ENCODING_SJIS. Deprecated. */ /* */ /* FT_ENCODING_MS_GB2312 :: */ /* Same as FT_ENCODING_GB2312. Deprecated. */ /* */ /* FT_ENCODING_MS_BIG5 :: */ /* Same as FT_ENCODING_BIG5. Deprecated. */ /* */ /* FT_ENCODING_MS_WANSUNG :: */ /* Same as FT_ENCODING_WANSUNG. Deprecated. */ /* */ /* FT_ENCODING_MS_JOHAB :: */ /* Same as FT_ENCODING_JOHAB. Deprecated. */ /* */ /* <Note> */ /* By default, FreeType automatically synthesizes a Unicode charmap */ /* for PostScript fonts, using their glyph names dictionaries. */ /* However, it also reports the encodings defined explicitly in the */ /* font file, for the cases when they are needed, with the Adobe */ /* values as well. */ /* */ /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */ /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */ /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out */ /* which encoding is really present. If, for example, the */ /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */ /* the font is encoded in KOI8-R. */ /* */ /* FT_ENCODING_NONE is always set (with a single exception) by the */ /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */ /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */ /* which encoding is really present. For example, */ /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */ /* Russian). */ /* */ /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */ /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */ /* FT_ENCODING_APPLE_ROMAN). */ /* */ /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */ /* @FT_Get_CMap_Language_ID to query the Mac language ID which may */ /* be needed to be able to distinguish Apple encoding variants. See */ /* */ /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */ /* */ /* to get an idea how to do that. Basically, if the language ID */ /* is~0, don't use it, otherwise subtract 1 from the language ID. */ /* Then examine `encoding_id'. If, for example, `encoding_id' is */ /* @TT_MAC_ID_ROMAN and the language ID (minus~1) is */ /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */ /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */ /* variant the Arabic encoding. */ /* */ typedef enum FT_Encoding_ { FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ), FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ), FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ), FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ), /* for backwards compatibility */ FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ), FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ), FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ), FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ), FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ), FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' ) } FT_Encoding; /*************************************************************************/ /* */ /* <Enum> */ /* ft_encoding_xxx */ /* */ /* <Description> */ /* These constants are deprecated; use the corresponding @FT_Encoding */ /* values instead. */ /* */ #define ft_encoding_none FT_ENCODING_NONE #define ft_encoding_unicode FT_ENCODING_UNICODE #define ft_encoding_symbol FT_ENCODING_MS_SYMBOL #define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 #define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 #define ft_encoding_sjis FT_ENCODING_SJIS #define ft_encoding_gb2312 FT_ENCODING_GB2312 #define ft_encoding_big5 FT_ENCODING_BIG5 #define ft_encoding_wansung FT_ENCODING_WANSUNG #define ft_encoding_johab FT_ENCODING_JOHAB #define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD #define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT #define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM #define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN /*************************************************************************/ /* */ /* <Struct> */ /* FT_CharMapRec */ /* */ /* <Description> */ /* The base charmap structure. */ /* */ /* <Fields> */ /* face :: A handle to the parent face object. */ /* */ /* encoding :: An @FT_Encoding tag identifying the charmap. Use */ /* this with @FT_Select_Charmap. */ /* */ /* platform_id :: An ID number describing the platform for the */ /* following encoding ID. This comes directly from */ /* the TrueType specification and should be emulated */ /* for other formats. */ /* */ /* encoding_id :: A platform specific encoding number. This also */ /* comes from the TrueType specification and should be */ /* emulated similarly. */ /* */ typedef struct FT_CharMapRec_ { FT_Face face; FT_Encoding encoding; FT_UShort platform_id; FT_UShort encoding_id; } FT_CharMapRec; /*************************************************************************/ /*************************************************************************/ /* */ /* B A S E O B J E C T C L A S S E S */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_Face_Internal */ /* */ /* <Description> */ /* An opaque handle to an `FT_Face_InternalRec' structure, used to */ /* model private data of a given @FT_Face object. */ /* */ /* This structure might change between releases of FreeType~2 and is */ /* not generally available to client applications. */ /* */ typedef struct FT_Face_InternalRec_* FT_Face_Internal; /*************************************************************************/ /* */ /* <Struct> */ /* FT_FaceRec */ /* */ /* <Description> */ /* FreeType root face class structure. A face object models a */ /* typeface in a font file. */ /* */ /* <Fields> */ /* num_faces :: The number of faces in the font file. Some */ /* font formats can have multiple faces in */ /* a font file. */ /* */ /* face_index :: The index of the face in the font file. It */ /* is set to~0 if there is only one face in */ /* the font file. */ /* */ /* face_flags :: A set of bit flags that give important */ /* information about the face; see */ /* @FT_FACE_FLAG_XXX for the details. */ /* */ /* style_flags :: A set of bit flags indicating the style of */ /* the face; see @FT_STYLE_FLAG_XXX for the */ /* details. */ /* */ /* num_glyphs :: The number of glyphs in the face. If the */ /* face is scalable and has sbits (see */ /* `num_fixed_sizes'), it is set to the number */ /* of outline glyphs. */ /* */ /* For CID-keyed fonts, this value gives the */ /* highest CID used in the font. */ /* */ /* family_name :: The face's family name. This is an ASCII */ /* string, usually in English, which describes */ /* the typeface's family (like `Times New */ /* Roman', `Bodoni', `Garamond', etc). This */ /* is a least common denominator used to list */ /* fonts. Some formats (TrueType & OpenType) */ /* provide localized and Unicode versions of */ /* this string. Applications should use the */ /* format specific interface to access them. */ /* Can be NULL (e.g., in fonts embedded in a */ /* PDF file). */ /* */ /* style_name :: The face's style name. This is an ASCII */ /* string, usually in English, which describes */ /* the typeface's style (like `Italic', */ /* `Bold', `Condensed', etc). Not all font */ /* formats provide a style name, so this field */ /* is optional, and can be set to NULL. As */ /* for `family_name', some formats provide */ /* localized and Unicode versions of this */ /* string. Applications should use the format */ /* specific interface to access them. */ /* */ /* num_fixed_sizes :: The number of bitmap strikes in the face. */ /* Even if the face is scalable, there might */ /* still be bitmap strikes, which are called */ /* `sbits' in that case. */ /* */ /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */ /* strikes in the face. It is set to NULL if */ /* there is no bitmap strike. */ /* */ /* num_charmaps :: The number of charmaps in the face. */ /* */ /* charmaps :: An array of the charmaps of the face. */ /* */ /* generic :: A field reserved for client uses. See the */ /* @FT_Generic type description. */ /* */ /* bbox :: The font bounding box. Coordinates are */ /* expressed in font units (see */ /* `units_per_EM'). The box is large enough */ /* to contain any glyph from the font. Thus, */ /* `bbox.yMax' can be seen as the `maximal */ /* ascender', and `bbox.yMin' as the `minimal */ /* descender'. Only relevant for scalable */ /* formats. */ /* */ /* Note that the bounding box might be off by */ /* (at least) one pixel for hinted fonts. See */ /* @FT_Size_Metrics for further discussion. */ /* */ /* units_per_EM :: The number of font units per EM square for */ /* this face. This is typically 2048 for */ /* TrueType fonts, and 1000 for Type~1 fonts. */ /* Only relevant for scalable formats. */ /* */ /* ascender :: The typographic ascender of the face, */ /* expressed in font units. For font formats */ /* not having this information, it is set to */ /* `bbox.yMax'. Only relevant for scalable */ /* formats. */ /* */ /* descender :: The typographic descender of the face, */ /* expressed in font units. For font formats */ /* not having this information, it is set to */ /* `bbox.yMin'. Note that this field is */ /* usually negative. Only relevant for */ /* scalable formats. */ /* */ /* height :: The height is the vertical distance */ /* between two consecutive baselines, */ /* expressed in font units. It is always */ /* positive. Only relevant for scalable */ /* formats. */ /* */ /* max_advance_width :: The maximal advance width, in font units, */ /* for all glyphs in this face. This can be */ /* used to make word wrapping computations */ /* faster. Only relevant for scalable */ /* formats. */ /* */ /* max_advance_height :: The maximal advance height, in font units, */ /* for all glyphs in this face. This is only */ /* relevant for vertical layouts, and is set */ /* to `height' for fonts that do not provide */ /* vertical metrics. Only relevant for */ /* scalable formats. */ /* */ /* underline_position :: The position, in font units, of the */ /* underline line for this face. It is the */ /* center of the underlining stem. Only */ /* relevant for scalable formats. */ /* */ /* underline_thickness :: The thickness, in font units, of the */ /* underline for this face. Only relevant for */ /* scalable formats. */ /* */ /* glyph :: The face's associated glyph slot(s). */ /* */ /* size :: The current active size for this face. */ /* */ /* charmap :: The current active charmap for this face. */ /* */ /* <Note> */ /* Fields may be changed after a call to @FT_Attach_File or */ /* @FT_Attach_Stream. */ /* */ typedef struct FT_FaceRec_ { FT_Long num_faces; FT_Long face_index; FT_Long face_flags; FT_Long style_flags; FT_Long num_glyphs; FT_String* family_name; FT_String* style_name; FT_Int num_fixed_sizes; FT_Bitmap_Size* available_sizes; FT_Int num_charmaps; FT_CharMap* charmaps; FT_Generic generic; /*# The following member variables (down to `underline_thickness') */ /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ /*# for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; FT_Short ascender; FT_Short descender; FT_Short height; FT_Short max_advance_width; FT_Short max_advance_height; FT_Short underline_position; FT_Short underline_thickness; FT_GlyphSlot glyph; FT_Size size; FT_CharMap charmap; /*@private begin */ FT_Driver driver; FT_Memory memory; FT_Stream stream; FT_ListRec sizes_list; FT_Generic autohint; void* extensions; FT_Face_Internal internal; /*@private end */ } FT_FaceRec; /*************************************************************************/ /* */ /* <Enum> */ /* FT_FACE_FLAG_XXX */ /* */ /* <Description> */ /* A list of bit flags used in the `face_flags' field of the */ /* @FT_FaceRec structure. They inform client applications of */ /* properties of the corresponding face. */ /* */ /* <Values> */ /* FT_FACE_FLAG_SCALABLE :: */ /* Indicates that the face contains outline glyphs. This doesn't */ /* prevent bitmap strikes, i.e., a face can have both this and */ /* and @FT_FACE_FLAG_FIXED_SIZES set. */ /* */ /* FT_FACE_FLAG_FIXED_SIZES :: */ /* Indicates that the face contains bitmap strikes. See also the */ /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */ /* */ /* FT_FACE_FLAG_FIXED_WIDTH :: */ /* Indicates that the face contains fixed-width characters (like */ /* Courier, Lucido, MonoType, etc.). */ /* */ /* FT_FACE_FLAG_SFNT :: */ /* Indicates that the face uses the `sfnt' storage scheme. For */ /* now, this means TrueType and OpenType. */ /* */ /* FT_FACE_FLAG_HORIZONTAL :: */ /* Indicates that the face contains horizontal glyph metrics. This */ /* should be set for all common formats. */ /* */ /* FT_FACE_FLAG_VERTICAL :: */ /* Indicates that the face contains vertical glyph metrics. This */ /* is only available in some formats, not all of them. */ /* */ /* FT_FACE_FLAG_KERNING :: */ /* Indicates that the face contains kerning information. If set, */ /* the kerning distance can be retrieved through the function */ /* @FT_Get_Kerning. Otherwise the function always return the */ /* vector (0,0). Note that FreeType doesn't handle kerning data */ /* from the `GPOS' table (as present in some OpenType fonts). */ /* */ /* FT_FACE_FLAG_FAST_GLYPHS :: */ /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */ /* */ /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */ /* Indicates that the font contains multiple masters and is capable */ /* of interpolating between them. See the multiple-masters */ /* specific API for details. */ /* */ /* FT_FACE_FLAG_GLYPH_NAMES :: */ /* Indicates that the font contains glyph names that can be */ /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */ /* fonts contain broken glyph name tables. Use the function */ /* @FT_Has_PS_Glyph_Names when needed. */ /* */ /* FT_FACE_FLAG_EXTERNAL_STREAM :: */ /* Used internally by FreeType to indicate that a face's stream was */ /* provided by the client application and should not be destroyed */ /* when @FT_Done_Face is called. Don't read or test this flag. */ /* */ /* FT_FACE_FLAG_HINTER :: */ /* Set if the font driver has a hinting machine of its own. For */ /* example, with TrueType fonts, it makes sense to use data from */ /* the SFNT `gasp' table only if the native TrueType hinting engine */ /* (with the bytecode interpreter) is available and active. */ /* */ /* FT_FACE_FLAG_CID_KEYED :: */ /* Set if the font is CID-keyed. In that case, the font is not */ /* accessed by glyph indices but by CID values. For subsetted */ /* CID-keyed fonts this has the consequence that not all index */ /* values are a valid argument to FT_Load_Glyph. Only the CID */ /* values for which corresponding glyphs in the subsetted font */ /* exist make FT_Load_Glyph return successfully; in all other cases */ /* you get an `FT_Err_Invalid_Argument' error. */ /* */ /* Note that CID-keyed fonts which are in an SFNT wrapper don't */ /* have this flag set since the glyphs are accessed in the normal */ /* way (using contiguous indices); the `CID-ness' isn't visible to */ /* the application. */ /* */ /* FT_FACE_FLAG_TRICKY :: */ /* Set if the font is `tricky', this is, it always needs the */ /* font format's native hinting engine to get a reasonable result. */ /* A typical example is the Chinese font `mingli.ttf' which uses */ /* TrueType bytecode instructions to move and scale all of its */ /* subglyphs. */ /* */ /* It is not possible to autohint such fonts using */ /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */ /* @FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING */ /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */ /* probably never want this except for demonstration purposes. */ /* */ /* Currently, there are six TrueType fonts in the list of tricky */ /* fonts; they are hard-coded in file `ttobjs.c'. */ /* */ #define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) #define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) #define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) #define FT_FACE_FLAG_SFNT ( 1L << 3 ) #define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) #define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) #define FT_FACE_FLAG_KERNING ( 1L << 6 ) #define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) #define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) #define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) #define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) #define FT_FACE_FLAG_HINTER ( 1L << 11 ) #define FT_FACE_FLAG_CID_KEYED ( 1L << 12 ) #define FT_FACE_FLAG_TRICKY ( 1L << 13 ) /************************************************************************* * * @macro: * FT_HAS_HORIZONTAL( face ) * * @description: * A macro that returns true whenever a face object contains * horizontal metrics (this is true for all font formats though). * * @also: * @FT_HAS_VERTICAL can be used to check for vertical metrics. * */ #define FT_HAS_HORIZONTAL( face ) \ ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) /************************************************************************* * * @macro: * FT_HAS_VERTICAL( face ) * * @description: * A macro that returns true whenever a face object contains vertical * metrics. * */ #define FT_HAS_VERTICAL( face ) \ ( face->face_flags & FT_FACE_FLAG_VERTICAL ) /************************************************************************* * * @macro: * FT_HAS_KERNING( face ) * * @description: * A macro that returns true whenever a face object contains kerning * data that can be accessed with @FT_Get_Kerning. * */ #define FT_HAS_KERNING( face ) \ ( face->face_flags & FT_FACE_FLAG_KERNING ) /************************************************************************* * * @macro: * FT_IS_SCALABLE( face ) * * @description: * A macro that returns true whenever a face object contains a scalable * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, * and PFR font formats. * */ #define FT_IS_SCALABLE( face ) \ ( face->face_flags & FT_FACE_FLAG_SCALABLE ) /************************************************************************* * * @macro: * FT_IS_SFNT( face ) * * @description: * A macro that returns true whenever a face object contains a font * whose format is based on the SFNT storage scheme. This usually * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded * bitmap fonts. * * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and * @FT_TRUETYPE_TABLES_H are available. * */ #define FT_IS_SFNT( face ) \ ( face->face_flags & FT_FACE_FLAG_SFNT ) /************************************************************************* * * @macro: * FT_IS_FIXED_WIDTH( face ) * * @description: * A macro that returns true whenever a face object contains a font face * that contains fixed-width (or `monospace', `fixed-pitch', etc.) * glyphs. * */ #define FT_IS_FIXED_WIDTH( face ) \ ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) /************************************************************************* * * @macro: * FT_HAS_FIXED_SIZES( face ) * * @description: * A macro that returns true whenever a face object contains some * embedded bitmaps. See the `available_sizes' field of the * @FT_FaceRec structure. * */ #define FT_HAS_FIXED_SIZES( face ) \ ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) /************************************************************************* * * @macro: * FT_HAS_FAST_GLYPHS( face ) * * @description: * Deprecated. * */ #define FT_HAS_FAST_GLYPHS( face ) 0 /************************************************************************* * * @macro: * FT_HAS_GLYPH_NAMES( face ) * * @description: * A macro that returns true whenever a face object contains some glyph * names that can be accessed through @FT_Get_Glyph_Name. * */ #define FT_HAS_GLYPH_NAMES( face ) \ ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) /************************************************************************* * * @macro: * FT_HAS_MULTIPLE_MASTERS( face ) * * @description: * A macro that returns true whenever a face object contains some * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H * are then available to choose the exact design you want. * */ #define FT_HAS_MULTIPLE_MASTERS( face ) \ ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) /************************************************************************* * * @macro: * FT_IS_CID_KEYED( face ) * * @description: * A macro that returns true whenever a face object contains a CID-keyed * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more * details. * * If this macro is true, all functions defined in @FT_CID_H are * available. * */ #define FT_IS_CID_KEYED( face ) \ ( face->face_flags & FT_FACE_FLAG_CID_KEYED ) /************************************************************************* * * @macro: * FT_IS_TRICKY( face ) * * @description: * A macro that returns true whenever a face represents a `tricky' font. * See the discussion of @FT_FACE_FLAG_TRICKY for more details. * */ #define FT_IS_TRICKY( face ) \ ( face->face_flags & FT_FACE_FLAG_TRICKY ) /*************************************************************************/ /* */ /* <Const> */ /* FT_STYLE_FLAG_XXX */ /* */ /* <Description> */ /* A list of bit-flags used to indicate the style of a given face. */ /* These are used in the `style_flags' field of @FT_FaceRec. */ /* */ /* <Values> */ /* FT_STYLE_FLAG_ITALIC :: */ /* Indicates that a given face style is italic or oblique. */ /* */ /* FT_STYLE_FLAG_BOLD :: */ /* Indicates that a given face is bold. */ /* */ /* <Note> */ /* The style information as provided by FreeType is very basic. More */ /* details are beyond the scope and should be done on a higher level */ /* (for example, by analyzing various fields of the `OS/2' table in */ /* SFNT based fonts). */ /* */ #define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) #define FT_STYLE_FLAG_BOLD ( 1 << 1 ) /*************************************************************************/ /* */ /* <Type> */ /* FT_Size_Internal */ /* */ /* <Description> */ /* An opaque handle to an `FT_Size_InternalRec' structure, used to */ /* model private data of a given @FT_Size object. */ /* */ typedef struct FT_Size_InternalRec_* FT_Size_Internal; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Size_Metrics */ /* */ /* <Description> */ /* The size metrics structure gives the metrics of a size object. */ /* */ /* <Fields> */ /* x_ppem :: The width of the scaled EM square in pixels, hence */ /* the term `ppem' (pixels per EM). It is also */ /* referred to as `nominal width'. */ /* */ /* y_ppem :: The height of the scaled EM square in pixels, */ /* hence the term `ppem' (pixels per EM). It is also */ /* referred to as `nominal height'. */ /* */ /* x_scale :: A 16.16 fractional scaling value used to convert */ /* horizontal metrics from font units to 26.6 */ /* fractional pixels. Only relevant for scalable */ /* font formats. */ /* */ /* y_scale :: A 16.16 fractional scaling value used to convert */ /* vertical metrics from font units to 26.6 */ /* fractional pixels. Only relevant for scalable */ /* font formats. */ /* */ /* ascender :: The ascender in 26.6 fractional pixels. See */ /* @FT_FaceRec for the details. */ /* */ /* descender :: The descender in 26.6 fractional pixels. See */ /* @FT_FaceRec for the details. */ /* */ /* height :: The height in 26.6 fractional pixels. See */ /* @FT_FaceRec for the details. */ /* */ /* max_advance :: The maximal advance width in 26.6 fractional */ /* pixels. See @FT_FaceRec for the details. */ /* */ /* <Note> */ /* The scaling values, if relevant, are determined first during a */ /* size changing operation. The remaining fields are then set by the */ /* driver. For scalable formats, they are usually set to scaled */ /* values of the corresponding fields in @FT_FaceRec. */ /* */ /* Note that due to glyph hinting, these values might not be exact */ /* for certain fonts. Thus they must be treated as unreliable */ /* with an error margin of at least one pixel! */ /* */ /* Indeed, the only way to get the exact metrics is to render _all_ */ /* glyphs. As this would be a definite performance hit, it is up to */ /* client applications to perform such computations. */ /* */ /* The FT_Size_Metrics structure is valid for bitmap fonts also. */ /* */ typedef struct FT_Size_Metrics_ { FT_UShort x_ppem; /* horizontal pixels per EM */ FT_UShort y_ppem; /* vertical pixels per EM */ FT_Fixed x_scale; /* scaling values used to convert font */ FT_Fixed y_scale; /* units to 26.6 fractional pixels */ FT_Pos ascender; /* ascender in 26.6 frac. pixels */ FT_Pos descender; /* descender in 26.6 frac. pixels */ FT_Pos height; /* text height in 26.6 frac. pixels */ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ } FT_Size_Metrics; /*************************************************************************/ /* */ /* <Struct> */ /* FT_SizeRec */ /* */ /* <Description> */ /* FreeType root size class structure. A size object models a face */ /* object at a given size. */ /* */ /* <Fields> */ /* face :: Handle to the parent face object. */ /* */ /* generic :: A typeless pointer, which is unused by the FreeType */ /* library or any of its drivers. It can be used by */ /* client applications to link their own data to each size */ /* object. */ /* */ /* metrics :: Metrics for this size object. This field is read-only. */ /* */ typedef struct FT_SizeRec_ { FT_Face face; /* parent face object */ FT_Generic generic; /* generic pointer for client uses */ FT_Size_Metrics metrics; /* size metrics */ FT_Size_Internal internal; } FT_SizeRec; /*************************************************************************/ /* */ /* <Struct> */ /* FT_SubGlyph */ /* */ /* <Description> */ /* The subglyph structure is an internal object used to describe */ /* subglyphs (for example, in the case of composites). */ /* */ /* <Note> */ /* The subglyph implementation is not part of the high-level API, */ /* hence the forward structure declaration. */ /* */ /* You can however retrieve subglyph information with */ /* @FT_Get_SubGlyph_Info. */ /* */ typedef struct FT_SubGlyphRec_* FT_SubGlyph; /*************************************************************************/ /* */ /* <Type> */ /* FT_Slot_Internal */ /* */ /* <Description> */ /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */ /* model private data of a given @FT_GlyphSlot object. */ /* */ typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; /*************************************************************************/ /* */ /* <Struct> */ /* FT_GlyphSlotRec */ /* */ /* <Description> */ /* FreeType root glyph slot class structure. A glyph slot is a */ /* container where individual glyphs can be loaded, be they in */ /* outline or bitmap format. */ /* */ /* <Fields> */ /* library :: A handle to the FreeType library instance */ /* this slot belongs to. */ /* */ /* face :: A handle to the parent face object. */ /* */ /* next :: In some cases (like some font tools), several */ /* glyph slots per face object can be a good */ /* thing. As this is rare, the glyph slots are */ /* listed through a direct, single-linked list */ /* using its `next' field. */ /* */ /* generic :: A typeless pointer which is unused by the */ /* FreeType library or any of its drivers. It */ /* can be used by client applications to link */ /* their own data to each glyph slot object. */ /* */ /* metrics :: The metrics of the last loaded glyph in the */ /* slot. The returned values depend on the last */ /* load flags (see the @FT_Load_Glyph API */ /* function) and can be expressed either in 26.6 */ /* fractional pixels or font units. */ /* */ /* Note that even when the glyph image is */ /* transformed, the metrics are not. */ /* */ /* linearHoriAdvance :: The advance width of the unhinted glyph. */ /* Its value is expressed in 16.16 fractional */ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ /* when loading the glyph. This field can be */ /* important to perform correct WYSIWYG layout. */ /* Only relevant for outline glyphs. */ /* */ /* linearVertAdvance :: The advance height of the unhinted glyph. */ /* Its value is expressed in 16.16 fractional */ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ /* when loading the glyph. This field can be */ /* important to perform correct WYSIWYG layout. */ /* Only relevant for outline glyphs. */ /* */ /* advance :: This is the transformed advance width for the */ /* glyph (in 26.6 fractional pixel format). */ /* */ /* format :: This field indicates the format of the image */ /* contained in the glyph slot. Typically */ /* @FT_GLYPH_FORMAT_BITMAP, */ /* @FT_GLYPH_FORMAT_OUTLINE, or */ /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */ /* possible. */ /* */ /* bitmap :: This field is used as a bitmap descriptor */ /* when the slot format is */ /* @FT_GLYPH_FORMAT_BITMAP. Note that the */ /* address and content of the bitmap buffer can */ /* change between calls of @FT_Load_Glyph and a */ /* few other functions. */ /* */ /* bitmap_left :: This is the bitmap's left bearing expressed */ /* in integer pixels. Of course, this is only */ /* valid if the format is */ /* @FT_GLYPH_FORMAT_BITMAP. */ /* */ /* bitmap_top :: This is the bitmap's top bearing expressed in */ /* integer pixels. Remember that this is the */ /* distance from the baseline to the top-most */ /* glyph scanline, upwards y~coordinates being */ /* *positive*. */ /* */ /* outline :: The outline descriptor for the current glyph */ /* image if its format is */ /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */ /* loaded, `outline' can be transformed, */ /* distorted, embolded, etc. However, it must */ /* not be freed. */ /* */ /* num_subglyphs :: The number of subglyphs in a composite glyph. */ /* This field is only valid for the composite */ /* glyph format that should normally only be */ /* loaded with the @FT_LOAD_NO_RECURSE flag. */ /* For now this is internal to FreeType. */ /* */ /* subglyphs :: An array of subglyph descriptors for */ /* composite glyphs. There are `num_subglyphs' */ /* elements in there. Currently internal to */ /* FreeType. */ /* */ /* control_data :: Certain font drivers can also return the */ /* control data for a given glyph image (e.g. */ /* TrueType bytecode, Type~1 charstrings, etc.). */ /* This field is a pointer to such data. */ /* */ /* control_len :: This is the length in bytes of the control */ /* data. */ /* */ /* other :: Really wicked formats can use this pointer to */ /* present their own glyph image to client */ /* applications. Note that the application */ /* needs to know about the image format. */ /* */ /* lsb_delta :: The difference between hinted and unhinted */ /* left side bearing while autohinting is */ /* active. Zero otherwise. */ /* */ /* rsb_delta :: The difference between hinted and unhinted */ /* right side bearing while autohinting is */ /* active. Zero otherwise. */ /* */ /* <Note> */ /* If @FT_Load_Glyph is called with default flags (see */ /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */ /* its native format (e.g., an outline glyph for TrueType and Type~1 */ /* formats). */ /* */ /* This image can later be converted into a bitmap by calling */ /* @FT_Render_Glyph. This function finds the current renderer for */ /* the native image's format, then invokes it. */ /* */ /* The renderer is in charge of transforming the native image through */ /* the slot's face transformation fields, then converting it into a */ /* bitmap that is returned in `slot->bitmap'. */ /* */ /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ /* to specify the position of the bitmap relative to the current pen */ /* position (e.g., coordinates (0,0) on the baseline). Of course, */ /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */ /* */ /* <Note> */ /* Here a small pseudo code fragment which shows how to use */ /* `lsb_delta' and `rsb_delta': */ /* */ /* { */ /* FT_Pos origin_x = 0; */ /* FT_Pos prev_rsb_delta = 0; */ /* */ /* */ /* for all glyphs do */ /* <compute kern between current and previous glyph and add it to */ /* `origin_x'> */ /* */ /* <load glyph with `FT_Load_Glyph'> */ /* */ /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */ /* origin_x -= 64; */ /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */ /* origin_x += 64; */ /* */ /* prev_rsb_delta = face->glyph->rsb_delta; */ /* */ /* <save glyph image, or render glyph, or ...> */ /* */ /* origin_x += face->glyph->advance.x; */ /* endfor */ /* } */ /* */ typedef struct FT_GlyphSlotRec_ { FT_Library library; FT_Face face; FT_GlyphSlot next; FT_UInt reserved; /* retained for binary compatibility */ FT_Generic generic; FT_Glyph_Metrics metrics; FT_Fixed linearHoriAdvance; FT_Fixed linearVertAdvance; FT_Vector advance; FT_Glyph_Format format; FT_Bitmap bitmap; FT_Int bitmap_left; FT_Int bitmap_top; FT_Outline outline; FT_UInt num_subglyphs; FT_SubGlyph subglyphs; void* control_data; long control_len; FT_Pos lsb_delta; FT_Pos rsb_delta; void* other; FT_Slot_Internal internal; } FT_GlyphSlotRec; /*************************************************************************/ /*************************************************************************/ /* */ /* F U N C T I O N S */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Init_FreeType */ /* */ /* <Description> */ /* Initialize a new FreeType library object. The set of modules */ /* that are registered by this function is determined at build time. */ /* */ /* <Output> */ /* alibrary :: A handle to a new library object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* In case you want to provide your own memory allocating routines, */ /* use @FT_New_Library instead, followed by a call to */ /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */ /* */ FT_EXPORT( FT_Error ) FT_Init_FreeType( FT_Library *alibrary ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Done_FreeType */ /* */ /* <Description> */ /* Destroy a given FreeType library object and all of its children, */ /* including resources, drivers, faces, sizes, etc. */ /* */ /* <Input> */ /* library :: A handle to the target library object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Done_FreeType( FT_Library library ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_OPEN_XXX */ /* */ /* <Description> */ /* A list of bit-field constants used within the `flags' field of the */ /* @FT_Open_Args structure. */ /* */ /* <Values> */ /* FT_OPEN_MEMORY :: This is a memory-based stream. */ /* */ /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */ /* */ /* FT_OPEN_PATHNAME :: Create a new input stream from a C~path */ /* name. */ /* */ /* FT_OPEN_DRIVER :: Use the `driver' field. */ /* */ /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */ /* */ /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */ /* */ /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */ /* */ /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */ /* */ /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */ /* */ /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */ /* */ /* <Note> */ /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */ /* flags are mutually exclusive. */ /* */ #define FT_OPEN_MEMORY 0x1 #define FT_OPEN_STREAM 0x2 #define FT_OPEN_PATHNAME 0x4 #define FT_OPEN_DRIVER 0x8 #define FT_OPEN_PARAMS 0x10 #define ft_open_memory FT_OPEN_MEMORY /* deprecated */ #define ft_open_stream FT_OPEN_STREAM /* deprecated */ #define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */ #define ft_open_driver FT_OPEN_DRIVER /* deprecated */ #define ft_open_params FT_OPEN_PARAMS /* deprecated */ /*************************************************************************/ /* */ /* <Struct> */ /* FT_Parameter */ /* */ /* <Description> */ /* A simple structure used to pass more or less generic parameters to */ /* @FT_Open_Face. */ /* */ /* <Fields> */ /* tag :: A four-byte identification tag. */ /* */ /* data :: A pointer to the parameter data. */ /* */ /* <Note> */ /* The ID and function of parameters are driver-specific. */ /* */ typedef struct FT_Parameter_ { FT_ULong tag; FT_Pointer data; } FT_Parameter; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Open_Args */ /* */ /* <Description> */ /* A structure used to indicate how to open a new font file or */ /* stream. A pointer to such a structure can be used as a parameter */ /* for the functions @FT_Open_Face and @FT_Attach_Stream. */ /* */ /* <Fields> */ /* flags :: A set of bit flags indicating how to use the */ /* structure. */ /* */ /* memory_base :: The first byte of the file in memory. */ /* */ /* memory_size :: The size in bytes of the file in memory. */ /* */ /* pathname :: A pointer to an 8-bit file pathname. */ /* */ /* stream :: A handle to a source stream object. */ /* */ /* driver :: This field is exclusively used by @FT_Open_Face; */ /* it simply specifies the font driver to use to open */ /* the face. If set to~0, FreeType tries to load the */ /* face with each one of the drivers in its list. */ /* */ /* num_params :: The number of extra parameters. */ /* */ /* params :: Extra parameters passed to the font driver when */ /* opening a new face. */ /* */ /* <Note> */ /* The stream type is determined by the contents of `flags' which */ /* are tested in the following order by @FT_Open_Face: */ /* */ /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */ /* memory file of `memory_size' bytes, located at `memory_address'. */ /* The data are are not copied, and the client is responsible for */ /* releasing and destroying them _after_ the corresponding call to */ /* @FT_Done_Face. */ /* */ /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */ /* custom input stream `stream' is used. */ /* */ /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */ /* is a normal file and use `pathname' to open it. */ /* */ /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to */ /* open the file with the driver whose handler is in `driver'. */ /* */ /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */ /* `num_params' and `params' is used. They are ignored otherwise. */ /* */ /* Ideally, both the `pathname' and `params' fields should be tagged */ /* as `const'; this is missing for API backwards compatibility. In */ /* other words, applications should treat them as read-only. */ /* */ typedef struct FT_Open_Args_ { FT_UInt flags; const FT_Byte* memory_base; FT_Long memory_size; FT_String* pathname; FT_Stream stream; FT_Module driver; FT_Int num_params; FT_Parameter* params; } FT_Open_Args; /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Face */ /* */ /* <Description> */ /* This function calls @FT_Open_Face to open a font by its pathname. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* pathname :: A path to the font file. */ /* */ /* face_index :: The index of the face within the font. The first */ /* face has index~0. */ /* */ /* <Output> */ /* aface :: A handle to a new face object. If `face_index' is */ /* greater than or equal to zero, it must be non-NULL. */ /* See @FT_Open_Face for more details. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_New_Face( FT_Library library, const char* filepathname, FT_Long face_index, FT_Face *aface ); /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Memory_Face */ /* */ /* <Description> */ /* This function calls @FT_Open_Face to open a font which has been */ /* loaded into memory. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* file_base :: A pointer to the beginning of the font data. */ /* */ /* file_size :: The size of the memory chunk used by the font data. */ /* */ /* face_index :: The index of the face within the font. The first */ /* face has index~0. */ /* */ /* <Output> */ /* aface :: A handle to a new face object. If `face_index' is */ /* greater than or equal to zero, it must be non-NULL. */ /* See @FT_Open_Face for more details. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* You must not deallocate the memory before calling @FT_Done_Face. */ /* */ FT_EXPORT( FT_Error ) FT_New_Memory_Face( FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Open_Face */ /* */ /* <Description> */ /* Create a face object from a given resource described by */ /* @FT_Open_Args. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* args :: A pointer to an `FT_Open_Args' structure which must */ /* be filled by the caller. */ /* */ /* face_index :: The index of the face within the font. The first */ /* face has index~0. */ /* */ /* <Output> */ /* aface :: A handle to a new face object. If `face_index' is */ /* greater than or equal to zero, it must be non-NULL. */ /* See note below. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* Unlike FreeType 1.x, this function automatically creates a glyph */ /* slot for the face object which can be accessed directly through */ /* `face->glyph'. */ /* */ /* FT_Open_Face can be used to quickly check whether the font */ /* format of a given font resource is supported by FreeType. If the */ /* `face_index' field is negative, the function's return value is~0 */ /* if the font format is recognized, or non-zero otherwise; */ /* the function returns a more or less empty face handle in `*aface' */ /* (if `aface' isn't NULL). The only useful field in this special */ /* case is `face->num_faces' which gives the number of faces within */ /* the font file. After examination, the returned @FT_Face structure */ /* should be deallocated with a call to @FT_Done_Face. */ /* */ /* Each new face object created with this function also owns a */ /* default @FT_Size object, accessible as `face->size'. */ /* */ FT_EXPORT( FT_Error ) FT_Open_Face( FT_Library library, const FT_Open_Args* args, FT_Long face_index, FT_Face *aface ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Attach_File */ /* */ /* <Description> */ /* This function calls @FT_Attach_Stream to attach a file. */ /* */ /* <InOut> */ /* face :: The target face object. */ /* */ /* <Input> */ /* filepathname :: The pathname. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Attach_File( FT_Face face, const char* filepathname ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Attach_Stream */ /* */ /* <Description> */ /* `Attach' data to a face object. Normally, this is used to read */ /* additional information for the face object. For example, you can */ /* attach an AFM file that comes with a Type~1 font to get the */ /* kerning values and other metrics. */ /* */ /* <InOut> */ /* face :: The target face object. */ /* */ /* <Input> */ /* parameters :: A pointer to @FT_Open_Args which must be filled by */ /* the caller. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The meaning of the `attach' (i.e., what really happens when the */ /* new file is read) is not fixed by FreeType itself. It really */ /* depends on the font format (and thus the font driver). */ /* */ /* Client applications are expected to know what they are doing */ /* when invoking this function. Most drivers simply do not implement */ /* file attachments. */ /* */ FT_EXPORT( FT_Error ) FT_Attach_Stream( FT_Face face, FT_Open_Args* parameters ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Done_Face */ /* */ /* <Description> */ /* Discard a given face object, as well as all of its child slots and */ /* sizes. */ /* */ /* <Input> */ /* face :: A handle to a target face object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Done_Face( FT_Face face ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Select_Size */ /* */ /* <Description> */ /* Select a bitmap strike. */ /* */ /* <InOut> */ /* face :: A handle to a target face object. */ /* */ /* <Input> */ /* strike_index :: The index of the bitmap strike in the */ /* `available_sizes' field of @FT_FaceRec structure. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Select_Size( FT_Face face, FT_Int strike_index ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_Size_Request_Type */ /* */ /* <Description> */ /* An enumeration type that lists the supported size request types. */ /* */ /* <Values> */ /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */ /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */ /* used to determine both scaling values. */ /* */ /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */ /* The real dimension. The sum of the the `Ascender' and (minus */ /* of) the `Descender' fields of @FT_FaceRec are used to determine */ /* both scaling values. */ /* */ /* FT_SIZE_REQUEST_TYPE_BBOX :: */ /* The font bounding box. The width and height of the `bbox' field */ /* of @FT_FaceRec are used to determine the horizontal and vertical */ /* scaling value, respectively. */ /* */ /* FT_SIZE_REQUEST_TYPE_CELL :: */ /* The `max_advance_width' field of @FT_FaceRec is used to */ /* determine the horizontal scaling value; the vertical scaling */ /* value is determined the same way as */ /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */ /* values are set to the smaller one. This type is useful if you */ /* want to specify the font size for, say, a window of a given */ /* dimension and 80x24 cells. */ /* */ /* FT_SIZE_REQUEST_TYPE_SCALES :: */ /* Specify the scaling values directly. */ /* */ /* <Note> */ /* The above descriptions only apply to scalable formats. For bitmap */ /* formats, the behaviour is up to the driver. */ /* */ /* See the note section of @FT_Size_Metrics if you wonder how size */ /* requesting relates to scaling values. */ /* */ typedef enum FT_Size_Request_Type_ { FT_SIZE_REQUEST_TYPE_NOMINAL, FT_SIZE_REQUEST_TYPE_REAL_DIM, FT_SIZE_REQUEST_TYPE_BBOX, FT_SIZE_REQUEST_TYPE_CELL, FT_SIZE_REQUEST_TYPE_SCALES, FT_SIZE_REQUEST_TYPE_MAX } FT_Size_Request_Type; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Size_RequestRec */ /* */ /* <Description> */ /* A structure used to model a size request. */ /* */ /* <Fields> */ /* type :: See @FT_Size_Request_Type. */ /* */ /* width :: The desired width. */ /* */ /* height :: The desired height. */ /* */ /* horiResolution :: The horizontal resolution. If set to zero, */ /* `width' is treated as a 26.6 fractional pixel */ /* value. */ /* */ /* vertResolution :: The vertical resolution. If set to zero, */ /* `height' is treated as a 26.6 fractional pixel */ /* value. */ /* */ /* <Note> */ /* If `width' is zero, then the horizontal scaling value is set equal */ /* to the vertical scaling value, and vice versa. */ /* */ typedef struct FT_Size_RequestRec_ { FT_Size_Request_Type type; FT_Long width; FT_Long height; FT_UInt horiResolution; FT_UInt vertResolution; } FT_Size_RequestRec; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Size_Request */ /* */ /* <Description> */ /* A handle to a size request structure. */ /* */ typedef struct FT_Size_RequestRec_ *FT_Size_Request; /*************************************************************************/ /* */ /* <Function> */ /* FT_Request_Size */ /* */ /* <Description> */ /* Resize the scale of the active @FT_Size object in a face. */ /* */ /* <InOut> */ /* face :: A handle to a target face object. */ /* */ /* <Input> */ /* req :: A pointer to a @FT_Size_RequestRec. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* Although drivers may select the bitmap strike matching the */ /* request, you should not rely on this if you intend to select a */ /* particular bitmap strike. Use @FT_Select_Size instead in that */ /* case. */ /* */ FT_EXPORT( FT_Error ) FT_Request_Size( FT_Face face, FT_Size_Request req ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Char_Size */ /* */ /* <Description> */ /* This function calls @FT_Request_Size to request the nominal size */ /* (in points). */ /* */ /* <InOut> */ /* face :: A handle to a target face object. */ /* */ /* <Input> */ /* char_width :: The nominal width, in 26.6 fractional points. */ /* */ /* char_height :: The nominal height, in 26.6 fractional points. */ /* */ /* horz_resolution :: The horizontal resolution in dpi. */ /* */ /* vert_resolution :: The vertical resolution in dpi. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* If either the character width or height is zero, it is set equal */ /* to the other value. */ /* */ /* If either the horizontal or vertical resolution is zero, it is set */ /* equal to the other value. */ /* */ /* A character width or height smaller than 1pt is set to 1pt; if */ /* both resolution values are zero, they are set to 72dpi. */ /* */ /* Don't use this function if you are using the FreeType cache API. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Char_Size( FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Pixel_Sizes */ /* */ /* <Description> */ /* This function calls @FT_Request_Size to request the nominal size */ /* (in pixels). */ /* */ /* <InOut> */ /* face :: A handle to the target face object. */ /* */ /* <Input> */ /* pixel_width :: The nominal width, in pixels. */ /* */ /* pixel_height :: The nominal height, in pixels. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Load_Glyph */ /* */ /* <Description> */ /* A function used to load a single glyph into the glyph slot of a */ /* face object. */ /* */ /* <InOut> */ /* face :: A handle to the target face object where the glyph */ /* is loaded. */ /* */ /* <Input> */ /* glyph_index :: The index of the glyph in the font file. For */ /* CID-keyed fonts (either in PS or in CFF format) */ /* this argument specifies the CID value. */ /* */ /* load_flags :: A flag indicating what to load for this glyph. The */ /* @FT_LOAD_XXX constants can be used to control the */ /* glyph loading process (e.g., whether the outline */ /* should be scaled, whether to load bitmaps or not, */ /* whether to hint the outline, etc). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The loaded glyph may be transformed. See @FT_Set_Transform for */ /* the details. */ /* */ /* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */ /* returned for invalid CID values (this is, for CID values which */ /* don't have a corresponding glyph in the font). See the discussion */ /* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */ /* */ FT_EXPORT( FT_Error ) FT_Load_Glyph( FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Load_Char */ /* */ /* <Description> */ /* A function used to load a single glyph into the glyph slot of a */ /* face object, according to its character code. */ /* */ /* <InOut> */ /* face :: A handle to a target face object where the glyph */ /* is loaded. */ /* */ /* <Input> */ /* char_code :: The glyph's character code, according to the */ /* current charmap used in the face. */ /* */ /* load_flags :: A flag indicating what to load for this glyph. The */ /* @FT_LOAD_XXX constants can be used to control the */ /* glyph loading process (e.g., whether the outline */ /* should be scaled, whether to load bitmaps or not, */ /* whether to hint the outline, etc). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */ /* */ FT_EXPORT( FT_Error ) FT_Load_Char( FT_Face face, FT_ULong char_code, FT_Int32 load_flags ); /************************************************************************* * * @enum: * FT_LOAD_XXX * * @description: * A list of bit-field constants used with @FT_Load_Glyph to indicate * what kind of operations to perform during glyph loading. * * @values: * FT_LOAD_DEFAULT :: * Corresponding to~0, this value is used as the default glyph load * operation. In this case, the following happens: * * 1. FreeType looks for a bitmap for the glyph corresponding to the * face's current size. If one is found, the function returns. * The bitmap data can be accessed from the glyph slot (see note * below). * * 2. If no embedded bitmap is searched or found, FreeType looks for a * scalable outline. If one is found, it is loaded from the font * file, scaled to device pixels, then `hinted' to the pixel grid * in order to optimize it. The outline data can be accessed from * the glyph slot (see note below). * * Note that by default, the glyph loader doesn't render outlines into * bitmaps. The following flags are used to modify this default * behaviour to more specific and useful cases. * * FT_LOAD_NO_SCALE :: * Don't scale the outline glyph loaded, but keep it in font units. * * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and * unsets @FT_LOAD_RENDER. * * FT_LOAD_NO_HINTING :: * Disable hinting. This generally generates `blurrier' bitmap glyph * when the glyph is rendered in any of the anti-aliased modes. See * also the note below. * * This flag is implied by @FT_LOAD_NO_SCALE. * * FT_LOAD_RENDER :: * Call @FT_Render_Glyph after the glyph is loaded. By default, the * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME. * * This flag is unset by @FT_LOAD_NO_SCALE. * * FT_LOAD_NO_BITMAP :: * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this * flag. * * @FT_LOAD_NO_SCALE always sets this flag. * * FT_LOAD_VERTICAL_LAYOUT :: * Load the glyph for vertical text layout. _Don't_ use it as it is * problematic currently. * * FT_LOAD_FORCE_AUTOHINT :: * Indicates that the auto-hinter is preferred over the font's native * hinter. See also the note below. * * FT_LOAD_CROP_BITMAP :: * Indicates that the font driver should crop the loaded bitmap glyph * (i.e., remove all space around its black bits). Not all drivers * implement this. * * FT_LOAD_PEDANTIC :: * Indicates that the font driver should perform pedantic verifications * during glyph loading. This is mostly used to detect broken glyphs * in fonts. By default, FreeType tries to handle broken fonts also. * * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH :: * Indicates that the font driver should ignore the global advance * width defined in the font. By default, that value is used as the * advance width for all glyphs when the face has * @FT_FACE_FLAG_FIXED_WIDTH set. * * This flag exists for historical reasons (to support buggy CJK * fonts). * * FT_LOAD_NO_RECURSE :: * This flag is only used internally. It merely indicates that the * font driver should not load composite glyphs recursively. Instead, * it should set the `num_subglyph' and `subglyphs' values of the * glyph slot accordingly, and set `glyph->format' to * @FT_GLYPH_FORMAT_COMPOSITE. * * The description of sub-glyphs is not available to client * applications for now. * * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM. * * FT_LOAD_IGNORE_TRANSFORM :: * Indicates that the transform matrix set by @FT_Set_Transform should * be ignored. * * FT_LOAD_MONOCHROME :: * This flag is used with @FT_LOAD_RENDER to indicate that you want to * render an outline glyph to a 1-bit monochrome bitmap glyph, with * 8~pixels packed into each byte of the bitmap data. * * Note that this has no effect on the hinting algorithm used. You * should rather use @FT_LOAD_TARGET_MONO so that the * monochrome-optimized hinting algorithm is used. * * FT_LOAD_LINEAR_DESIGN :: * Indicates that the `linearHoriAdvance' and `linearVertAdvance' * fields of @FT_GlyphSlotRec should be kept in font units. See * @FT_GlyphSlotRec for details. * * FT_LOAD_NO_AUTOHINT :: * Disable auto-hinter. See also the note below. * * @note: * By default, hinting is enabled and the font's native hinter (see * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can * disable hinting by setting @FT_LOAD_NO_HINTING or change the * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be * used at all. * * See the description of @FT_FACE_FLAG_TRICKY for a special exception * (affecting only a handful of Asian fonts). * * Besides deciding which hinter to use, you can also decide which * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details. * */ #define FT_LOAD_DEFAULT 0x0 #define FT_LOAD_NO_SCALE 0x1 #define FT_LOAD_NO_HINTING 0x2 #define FT_LOAD_RENDER 0x4 #define FT_LOAD_NO_BITMAP 0x8 #define FT_LOAD_VERTICAL_LAYOUT 0x10 #define FT_LOAD_FORCE_AUTOHINT 0x20 #define FT_LOAD_CROP_BITMAP 0x40 #define FT_LOAD_PEDANTIC 0x80 #define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200 #define FT_LOAD_NO_RECURSE 0x400 #define FT_LOAD_IGNORE_TRANSFORM 0x800 #define FT_LOAD_MONOCHROME 0x1000 #define FT_LOAD_LINEAR_DESIGN 0x2000 #define FT_LOAD_NO_AUTOHINT 0x8000U /* */ /* used internally only by certain font drivers! */ #define FT_LOAD_ADVANCE_ONLY 0x100 #define FT_LOAD_SBITS_ONLY 0x4000 /************************************************************************** * * @enum: * FT_LOAD_TARGET_XXX * * @description: * A list of values that are used to select a specific hinting algorithm * to use by the hinter. You should OR one of these values to your * `load_flags' when calling @FT_Load_Glyph. * * Note that font's native hinters may ignore the hinting algorithm you * have specified (e.g., the TrueType bytecode interpreter). You can set * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. * * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it * always implies @FT_LOAD_FORCE_AUTOHINT. * * @values: * FT_LOAD_TARGET_NORMAL :: * This corresponds to the default hinting algorithm, optimized for * standard gray-level rendering. For monochrome output, use * @FT_LOAD_TARGET_MONO instead. * * FT_LOAD_TARGET_LIGHT :: * A lighter hinting algorithm for non-monochrome modes. Many * generated glyphs are more fuzzy but better resemble its original * shape. A bit like rendering on Mac OS~X. * * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT. * * FT_LOAD_TARGET_MONO :: * Strong hinting algorithm that should only be used for monochrome * output. The result is probably unpleasant if the glyph is rendered * in non-monochrome modes. * * FT_LOAD_TARGET_LCD :: * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally * decimated LCD displays. * * FT_LOAD_TARGET_LCD_V :: * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically * decimated LCD displays. * * @note: * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your * `load_flags'. They can't be ORed. * * If @FT_LOAD_RENDER is also set, the glyph is rendered in the * corresponding mode (i.e., the mode which matches the used algorithm * best) unless @FT_LOAD_MONOCHROME is set. * * You can use a hinting algorithm that doesn't correspond to the same * rendering mode. As an example, it is possible to use the `light' * hinting algorithm and have the results rendered in horizontal LCD * pixel mode, with code like * * { * FT_Load_Glyph( face, glyph_index, * load_flags | FT_LOAD_TARGET_LIGHT ); * * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); * } * */ #define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) #define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) #define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) #define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) #define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) #define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) /************************************************************************** * * @macro: * FT_LOAD_TARGET_MODE * * @description: * Return the @FT_Render_Mode corresponding to a given * @FT_LOAD_TARGET_XXX value. * */ #define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) ) /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Transform */ /* */ /* <Description> */ /* A function used to set the transformation that is applied to glyph */ /* images when they are loaded into a glyph slot through */ /* @FT_Load_Glyph. */ /* */ /* <InOut> */ /* face :: A handle to the source face object. */ /* */ /* <Input> */ /* matrix :: A pointer to the transformation's 2x2 matrix. Use~0 for */ /* the identity matrix. */ /* delta :: A pointer to the translation vector. Use~0 for the null */ /* vector. */ /* */ /* <Note> */ /* The transformation is only applied to scalable image formats after */ /* the glyph has been loaded. It means that hinting is unaltered by */ /* the transformation and is performed on the character size given in */ /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */ /* */ /* Note that this also transforms the `face.glyph.advance' field, but */ /* *not* the values in `face.glyph.metrics'. */ /* */ FT_EXPORT( void ) FT_Set_Transform( FT_Face face, FT_Matrix* matrix, FT_Vector* delta ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_Render_Mode */ /* */ /* <Description> */ /* An enumeration type that lists the render modes supported by */ /* FreeType~2. Each mode corresponds to a specific type of scanline */ /* conversion performed on the outline. */ /* */ /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */ /* field in the @FT_GlyphSlotRec structure gives the format of the */ /* returned bitmap. */ /* */ /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */ /* */ /* <Values> */ /* FT_RENDER_MODE_NORMAL :: */ /* This is the default render mode; it corresponds to 8-bit */ /* anti-aliased bitmaps. */ /* */ /* FT_RENDER_MODE_LIGHT :: */ /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */ /* defined as a separate value because render modes are also used */ /* indirectly to define hinting algorithm selectors. See */ /* @FT_LOAD_TARGET_XXX for details. */ /* */ /* FT_RENDER_MODE_MONO :: */ /* This mode corresponds to 1-bit bitmaps (with 2~levels of */ /* opacity). */ /* */ /* FT_RENDER_MODE_LCD :: */ /* This mode corresponds to horizontal RGB and BGR sub-pixel */ /* displays like LCD screens. It produces 8-bit bitmaps that are */ /* 3~times the width of the original glyph outline in pixels, and */ /* which use the @FT_PIXEL_MODE_LCD mode. */ /* */ /* FT_RENDER_MODE_LCD_V :: */ /* This mode corresponds to vertical RGB and BGR sub-pixel displays */ /* (like PDA screens, rotated LCD displays, etc.). It produces */ /* 8-bit bitmaps that are 3~times the height of the original */ /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ /* */ /* <Note> */ /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph can be */ /* filtered to reduce color-fringes by using @FT_Library_SetLcdFilter */ /* (not active in the default builds). It is up to the caller to */ /* either call @FT_Library_SetLcdFilter (if available) or do the */ /* filtering itself. */ /* */ /* The selected render mode only affects vector glyphs of a font. */ /* Embedded bitmaps often have a different pixel mode like */ /* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform */ /* them into 8-bit pixmaps. */ /* */ typedef enum FT_Render_Mode_ { FT_RENDER_MODE_NORMAL = 0, FT_RENDER_MODE_LIGHT, FT_RENDER_MODE_MONO, FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V, FT_RENDER_MODE_MAX } FT_Render_Mode; /*************************************************************************/ /* */ /* <Enum> */ /* ft_render_mode_xxx */ /* */ /* <Description> */ /* These constants are deprecated. Use the corresponding */ /* @FT_Render_Mode values instead. */ /* */ /* <Values> */ /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */ /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */ /* */ #define ft_render_mode_normal FT_RENDER_MODE_NORMAL #define ft_render_mode_mono FT_RENDER_MODE_MONO /*************************************************************************/ /* */ /* <Function> */ /* FT_Render_Glyph */ /* */ /* <Description> */ /* Convert a given glyph image to a bitmap. It does so by inspecting */ /* the glyph image format, finding the relevant renderer, and */ /* invoking it. */ /* */ /* <InOut> */ /* slot :: A handle to the glyph slot containing the image to */ /* convert. */ /* */ /* <Input> */ /* render_mode :: This is the render mode used to render the glyph */ /* image into a bitmap. See @FT_Render_Mode for a */ /* list of possible values. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, FT_Render_Mode render_mode ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_Kerning_Mode */ /* */ /* <Description> */ /* An enumeration used to specify which kerning values to return in */ /* @FT_Get_Kerning. */ /* */ /* <Values> */ /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */ /* distances (value is~0). */ /* */ /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */ /* distances. */ /* */ /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */ /* units. */ /* */ typedef enum FT_Kerning_Mode_ { FT_KERNING_DEFAULT = 0, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED } FT_Kerning_Mode; /*************************************************************************/ /* */ /* <Const> */ /* ft_kerning_default */ /* */ /* <Description> */ /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */ /* instead. */ /* */ #define ft_kerning_default FT_KERNING_DEFAULT /*************************************************************************/ /* */ /* <Const> */ /* ft_kerning_unfitted */ /* */ /* <Description> */ /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */ /* instead. */ /* */ #define ft_kerning_unfitted FT_KERNING_UNFITTED /*************************************************************************/ /* */ /* <Const> */ /* ft_kerning_unscaled */ /* */ /* <Description> */ /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */ /* instead. */ /* */ #define ft_kerning_unscaled FT_KERNING_UNSCALED /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Kerning */ /* */ /* <Description> */ /* Return the kerning vector between two glyphs of a same face. */ /* */ /* <Input> */ /* face :: A handle to a source face object. */ /* */ /* left_glyph :: The index of the left glyph in the kern pair. */ /* */ /* right_glyph :: The index of the right glyph in the kern pair. */ /* */ /* kern_mode :: See @FT_Kerning_Mode for more information. */ /* Determines the scale and dimension of the returned */ /* kerning vector. */ /* */ /* <Output> */ /* akerning :: The kerning vector. This is either in font units */ /* or in pixels (26.6 format) for scalable formats, */ /* and in pixels for fixed-sizes formats. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* Only horizontal layouts (left-to-right & right-to-left) are */ /* supported by this method. Other layouts, or more sophisticated */ /* kernings, are out of the scope of this API function -- they can be */ /* implemented through format-specific interfaces. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Kerning( FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt kern_mode, FT_Vector *akerning ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Track_Kerning */ /* */ /* <Description> */ /* Return the track kerning for a given face object at a given size. */ /* */ /* <Input> */ /* face :: A handle to a source face object. */ /* */ /* point_size :: The point size in 16.16 fractional points. */ /* */ /* degree :: The degree of tightness. */ /* */ /* <Output> */ /* akerning :: The kerning in 16.16 fractional points. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Track_Kerning( FT_Face face, FT_Fixed point_size, FT_Int degree, FT_Fixed* akerning ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Glyph_Name */ /* */ /* <Description> */ /* Retrieve the ASCII name of a given glyph in a face. This only */ /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. */ /* */ /* <Input> */ /* face :: A handle to a source face object. */ /* */ /* glyph_index :: The glyph index. */ /* */ /* buffer_max :: The maximal number of bytes available in the */ /* buffer. */ /* */ /* <Output> */ /* buffer :: A pointer to a target buffer where the name is */ /* copied to. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* An error is returned if the face doesn't provide glyph names or if */ /* the glyph index is invalid. In all cases of failure, the first */ /* byte of `buffer' is set to~0 to indicate an empty name. */ /* */ /* The glyph name is truncated to fit within the buffer if it is too */ /* long. The returned string is always zero-terminated. */ /* */ /* This function is not compiled within the library if the config */ /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */ /* `include/freetype/config/ftoptions.h'. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Glyph_Name( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Postscript_Name */ /* */ /* <Description> */ /* Retrieve the ASCII PostScript name of a given face, if available. */ /* This only works with PostScript and TrueType fonts. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* */ /* <Return> */ /* A pointer to the face's PostScript name. NULL if unavailable. */ /* */ /* <Note> */ /* The returned pointer is owned by the face and is destroyed with */ /* it. */ /* */ FT_EXPORT( const char* ) FT_Get_Postscript_Name( FT_Face face ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Select_Charmap */ /* */ /* <Description> */ /* Select a given charmap by its encoding tag (as listed in */ /* `freetype.h'). */ /* */ /* <InOut> */ /* face :: A handle to the source face object. */ /* */ /* <Input> */ /* encoding :: A handle to the selected encoding. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function returns an error if no charmap in the face */ /* corresponds to the encoding queried here. */ /* */ /* Because many fonts contain more than a single cmap for Unicode */ /* encoding, this function has some special code to select the one */ /* which covers Unicode best (`best' in the sense that a UCS-4 cmap */ /* is preferred to a UCS-2 cmap). It is thus preferable to */ /* @FT_Set_Charmap in this case. */ /* */ FT_EXPORT( FT_Error ) FT_Select_Charmap( FT_Face face, FT_Encoding encoding ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Charmap */ /* */ /* <Description> */ /* Select a given charmap for character code to glyph index mapping. */ /* */ /* <InOut> */ /* face :: A handle to the source face object. */ /* */ /* <Input> */ /* charmap :: A handle to the selected charmap. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function returns an error if the charmap is not part of */ /* the face (i.e., if it is not listed in the `face->charmaps' */ /* table). */ /* */ /* It also fails if a type~14 charmap is selected. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Charmap( FT_Face face, FT_CharMap charmap ); /************************************************************************* * * @function: * FT_Get_Charmap_Index * * @description: * Retrieve index of a given charmap. * * @input: * charmap :: * A handle to a charmap. * * @return: * The index into the array of character maps within the face to which * `charmap' belongs. * */ FT_EXPORT( FT_Int ) FT_Get_Charmap_Index( FT_CharMap charmap ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Char_Index */ /* */ /* <Description> */ /* Return the glyph index of a given character code. This function */ /* uses a charmap object to do the mapping. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* */ /* charcode :: The character code. */ /* */ /* <Return> */ /* The glyph index. 0~means `undefined character code'. */ /* */ /* <Note> */ /* If you use FreeType to manipulate the contents of font files */ /* directly, be aware that the glyph index returned by this function */ /* doesn't always correspond to the internal indices used within */ /* the file. This is done to ensure that value~0 always corresponds */ /* to the `missing glyph'. */ /* */ FT_EXPORT( FT_UInt ) FT_Get_Char_Index( FT_Face face, FT_ULong charcode ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_First_Char */ /* */ /* <Description> */ /* This function is used to return the first character code in the */ /* current charmap of a given face. It also returns the */ /* corresponding glyph index. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* */ /* <Output> */ /* agindex :: Glyph index of first character code. 0~if charmap is */ /* empty. */ /* */ /* <Return> */ /* The charmap's first character code. */ /* */ /* <Note> */ /* You should use this function with @FT_Get_Next_Char to be able to */ /* parse all character codes available in a given charmap. The code */ /* should look like this: */ /* */ /* { */ /* FT_ULong charcode; */ /* FT_UInt gindex; */ /* */ /* */ /* charcode = FT_Get_First_Char( face, &gindex ); */ /* while ( gindex != 0 ) */ /* { */ /* ... do something with (charcode,gindex) pair ... */ /* */ /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */ /* } */ /* } */ /* */ /* Note that `*agindex' is set to~0 if the charmap is empty. The */ /* result itself can be~0 in two cases: if the charmap is empty or */ /* if the value~0 is the first valid character code. */ /* */ FT_EXPORT( FT_ULong ) FT_Get_First_Char( FT_Face face, FT_UInt *agindex ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Next_Char */ /* */ /* <Description> */ /* This function is used to return the next character code in the */ /* current charmap of a given face following the value `char_code', */ /* as well as the corresponding glyph index. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* char_code :: The starting character code. */ /* */ /* <Output> */ /* agindex :: Glyph index of next character code. 0~if charmap */ /* is empty. */ /* */ /* <Return> */ /* The charmap's next character code. */ /* */ /* <Note> */ /* You should use this function with @FT_Get_First_Char to walk */ /* over all character codes available in a given charmap. See the */ /* note for this function for a simple code example. */ /* */ /* Note that `*agindex' is set to~0 when there are no more codes in */ /* the charmap. */ /* */ FT_EXPORT( FT_ULong ) FT_Get_Next_Char( FT_Face face, FT_ULong char_code, FT_UInt *agindex ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Name_Index */ /* */ /* <Description> */ /* Return the glyph index of a given glyph name. This function uses */ /* driver specific objects to do the translation. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* */ /* glyph_name :: The glyph name. */ /* */ /* <Return> */ /* The glyph index. 0~means `undefined character code'. */ /* */ FT_EXPORT( FT_UInt ) FT_Get_Name_Index( FT_Face face, FT_String* glyph_name ); /************************************************************************* * * @macro: * FT_SUBGLYPH_FLAG_XXX * * @description: * A list of constants used to describe subglyphs. Please refer to the * TrueType specification for the meaning of the various flags. * * @values: * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS :: * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES :: * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID :: * FT_SUBGLYPH_FLAG_SCALE :: * FT_SUBGLYPH_FLAG_XY_SCALE :: * FT_SUBGLYPH_FLAG_2X2 :: * FT_SUBGLYPH_FLAG_USE_MY_METRICS :: * */ #define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 #define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 #define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 #define FT_SUBGLYPH_FLAG_SCALE 8 #define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 #define FT_SUBGLYPH_FLAG_2X2 0x80 #define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 /************************************************************************* * * @func: * FT_Get_SubGlyph_Info * * @description: * Retrieve a description of a given subglyph. Only use it if * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE; an error is * returned otherwise. * * @input: * glyph :: * The source glyph slot. * * sub_index :: * The index of the subglyph. Must be less than * `glyph->num_subglyphs'. * * @output: * p_index :: * The glyph index of the subglyph. * * p_flags :: * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX. * * p_arg1 :: * The subglyph's first argument (if any). * * p_arg2 :: * The subglyph's second argument (if any). * * p_transform :: * The subglyph transformation (if any). * * @return: * FreeType error code. 0~means success. * * @note: * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be * interpreted depending on the flags returned in `*p_flags'. See the * TrueType specification for details. * */ FT_EXPORT( FT_Error ) FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, FT_UInt sub_index, FT_Int *p_index, FT_UInt *p_flags, FT_Int *p_arg1, FT_Int *p_arg2, FT_Matrix *p_transform ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_FSTYPE_XXX */ /* */ /* <Description> */ /* A list of bit flags used in the `fsType' field of the OS/2 table */ /* in a TrueType or OpenType font and the `FSType' entry in a */ /* PostScript font. These bit flags are returned by */ /* @FT_Get_FSType_Flags; they inform client applications of embedding */ /* and subsetting restrictions associated with a font. */ /* */ /* See http://www.adobe.com/devnet/acrobat/pdfs/FontPolicies.pdf for */ /* more details. */ /* */ /* <Values> */ /* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */ /* Fonts with no fsType bit set may be embedded and permanently */ /* installed on the remote system by an application. */ /* */ /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING :: */ /* Fonts that have only this bit set must not be modified, embedded */ /* or exchanged in any manner without first obtaining permission of */ /* the font software copyright owner. */ /* */ /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */ /* If this bit is set, the font may be embedded and temporarily */ /* loaded on the remote system. Documents containing Preview & */ /* Print fonts must be opened `read-only'; no edits can be applied */ /* to the document. */ /* */ /* FT_FSTYPE_EDITABLE_EMBEDDING :: */ /* If this bit is set, the font may be embedded but must only be */ /* installed temporarily on other systems. In contrast to Preview */ /* & Print fonts, documents containing editable fonts may be opened */ /* for reading, editing is permitted, and changes may be saved. */ /* */ /* FT_FSTYPE_NO_SUBSETTING :: */ /* If this bit is set, the font may not be subsetted prior to */ /* embedding. */ /* */ /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */ /* If this bit is set, only bitmaps contained in the font may be */ /* embedded; no outline data may be embedded. If there are no */ /* bitmaps available in the font, then the font is unembeddable. */ /* */ /* <Note> */ /* While the fsType flags can indicate that a font may be embedded, a */ /* license with the font vendor may be separately required to use the */ /* font in this way. */ /* */ #define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 #define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 #define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004 #define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008 #define FT_FSTYPE_NO_SUBSETTING 0x0100 #define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200 /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_FSType_Flags */ /* */ /* <Description> */ /* Return the fsType flags for a font. */ /* */ /* <Input> */ /* face :: A handle to the source face object. */ /* */ /* <Return> */ /* The fsType flags, @FT_FSTYPE_XXX. */ /* */ /* <Note> */ /* Use this function rather than directly reading the `fs_type' field */ /* in the @PS_FontInfoRec structure which is only guaranteed to */ /* return the correct results for Type~1 fonts. */ /* */ FT_EXPORT( FT_UShort ) FT_Get_FSType_Flags( FT_Face face ); /*************************************************************************/ /* */ /* <Section> */ /* glyph_variants */ /* */ /* <Title> */ /* Glyph Variants */ /* */ /* <Abstract> */ /* The FreeType~2 interface to Unicode Ideographic Variation */ /* Sequences (IVS), using the SFNT cmap format~14. */ /* */ /* <Description> */ /* Many CJK characters have variant forms. They are a sort of grey */ /* area somewhere between being totally irrelevant and semantically */ /* distinct; for this reason, the Unicode consortium decided to */ /* introduce Ideographic Variation Sequences (IVS), consisting of a */ /* Unicode base character and one of 240 variant selectors */ /* (U+E0100-U+E01EF), instead of further extending the already huge */ /* code range for CJK characters. */ /* */ /* An IVS is registered and unique; for further details please refer */ /* to Unicode Technical Report #37, the Ideographic Variation */ /* Database. To date (October 2007), the character with the most */ /* variants is U+908A, having 8~such IVS. */ /* */ /* Adobe and MS decided to support IVS with a new cmap subtable */ /* (format~14). It is an odd subtable because it is not a mapping of */ /* input code points to glyphs, but contains lists of all variants */ /* supported by the font. */ /* */ /* A variant may be either `default' or `non-default'. A default */ /* variant is the one you will get for that code point if you look it */ /* up in the standard Unicode cmap. A non-default variant is a */ /* different glyph. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_GetCharVariantIndex */ /* */ /* <Description> */ /* Return the glyph index of a given character code as modified by */ /* the variation selector. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* charcode :: */ /* The character code point in Unicode. */ /* */ /* variantSelector :: */ /* The Unicode code point of the variation selector. */ /* */ /* <Return> */ /* The glyph index. 0~means either `undefined character code', or */ /* `undefined selector code', or `no variation selector cmap */ /* subtable', or `current CharMap is not Unicode'. */ /* */ /* <Note> */ /* If you use FreeType to manipulate the contents of font files */ /* directly, be aware that the glyph index returned by this function */ /* doesn't always correspond to the internal indices used within */ /* the file. This is done to ensure that value~0 always corresponds */ /* to the `missing glyph'. */ /* */ /* This function is only meaningful if */ /* a) the font has a variation selector cmap sub table, */ /* and */ /* b) the current charmap has a Unicode encoding. */ /* */ /* <Since> */ /* 2.3.6 */ /* */ FT_EXPORT( FT_UInt ) FT_Face_GetCharVariantIndex( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_GetCharVariantIsDefault */ /* */ /* <Description> */ /* Check whether this variant of this Unicode character is the one to */ /* be found in the `cmap'. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* charcode :: */ /* The character codepoint in Unicode. */ /* */ /* variantSelector :: */ /* The Unicode codepoint of the variation selector. */ /* */ /* <Return> */ /* 1~if found in the standard (Unicode) cmap, 0~if found in the */ /* variation selector cmap, or -1 if it is not a variant. */ /* */ /* <Note> */ /* This function is only meaningful if the font has a variation */ /* selector cmap subtable. */ /* */ /* <Since> */ /* 2.3.6 */ /* */ FT_EXPORT( FT_Int ) FT_Face_GetCharVariantIsDefault( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_GetVariantSelectors */ /* */ /* <Description> */ /* Return a zero-terminated list of Unicode variant selectors found */ /* in the font. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* <Return> */ /* A pointer to an array of selector code points, or NULL if there is */ /* no valid variant selector cmap subtable. */ /* */ /* <Note> */ /* The last item in the array is~0; the array is owned by the */ /* @FT_Face object but can be overwritten or released on the next */ /* call to a FreeType function. */ /* */ /* <Since> */ /* 2.3.6 */ /* */ FT_EXPORT( FT_UInt32* ) FT_Face_GetVariantSelectors( FT_Face face ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_GetVariantsOfChar */ /* */ /* <Description> */ /* Return a zero-terminated list of Unicode variant selectors found */ /* for the specified character code. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* charcode :: */ /* The character codepoint in Unicode. */ /* */ /* <Return> */ /* A pointer to an array of variant selector code points which are */ /* active for the given character, or NULL if the corresponding list */ /* is empty. */ /* */ /* <Note> */ /* The last item in the array is~0; the array is owned by the */ /* @FT_Face object but can be overwritten or released on the next */ /* call to a FreeType function. */ /* */ /* <Since> */ /* 2.3.6 */ /* */ FT_EXPORT( FT_UInt32* ) FT_Face_GetVariantsOfChar( FT_Face face, FT_ULong charcode ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_GetCharsOfVariant */ /* */ /* <Description> */ /* Return a zero-terminated list of Unicode character codes found for */ /* the specified variant selector. */ /* */ /* <Input> */ /* face :: */ /* A handle to the source face object. */ /* */ /* variantSelector :: */ /* The variant selector code point in Unicode. */ /* */ /* <Return> */ /* A list of all the code points which are specified by this selector */ /* (both default and non-default codes are returned) or NULL if there */ /* is no valid cmap or the variant selector is invalid. */ /* */ /* <Note> */ /* The last item in the array is~0; the array is owned by the */ /* @FT_Face object but can be overwritten or released on the next */ /* call to a FreeType function. */ /* */ /* <Since> */ /* 2.3.6 */ /* */ FT_EXPORT( FT_UInt32* ) FT_Face_GetCharsOfVariant( FT_Face face, FT_ULong variantSelector ); /*************************************************************************/ /* */ /* <Section> */ /* computations */ /* */ /* <Title> */ /* Computations */ /* */ /* <Abstract> */ /* Crunching fixed numbers and vectors. */ /* */ /* <Description> */ /* This section contains various functions used to perform */ /* computations on 16.16 fixed-float numbers or 2d vectors. */ /* */ /* <Order> */ /* FT_MulDiv */ /* FT_MulFix */ /* FT_DivFix */ /* FT_RoundFix */ /* FT_CeilFix */ /* FT_FloorFix */ /* FT_Vector_Transform */ /* FT_Matrix_Multiply */ /* FT_Matrix_Invert */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_MulDiv */ /* */ /* <Description> */ /* A very simple function used to perform the computation `(a*b)/c' */ /* with maximal accuracy (it uses a 64-bit intermediate integer */ /* whenever necessary). */ /* */ /* This function isn't necessarily as fast as some processor specific */ /* operations, but is at least completely portable. */ /* */ /* <Input> */ /* a :: The first multiplier. */ /* b :: The second multiplier. */ /* c :: The divisor. */ /* */ /* <Return> */ /* The result of `(a*b)/c'. This function never traps when trying to */ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ /* on the signs of `a' and `b'. */ /* */ FT_EXPORT( FT_Long ) FT_MulDiv( FT_Long a, FT_Long b, FT_Long c ); /* */ /* The following #if 0 ... #endif is for the documentation formatter, */ /* hiding the internal `FT_MULFIX_INLINED' macro. */ #if 0 /*************************************************************************/ /* */ /* <Function> */ /* FT_MulFix */ /* */ /* <Description> */ /* A very simple function used to perform the computation */ /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ /* used to multiply a given value by a 16.16 fixed float factor. */ /* */ /* <Input> */ /* a :: The first multiplier. */ /* b :: The second multiplier. Use a 16.16 factor here whenever */ /* possible (see note below). */ /* */ /* <Return> */ /* The result of `(a*b)/0x10000'. */ /* */ /* <Note> */ /* This function has been optimized for the case where the absolute */ /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ /* As this happens mainly when scaling from notional units to */ /* fractional pixels in FreeType, it resulted in noticeable speed */ /* improvements between versions 2.x and 1.x. */ /* */ /* As a conclusion, always try to place a 16.16 factor as the */ /* _second_ argument of this function; this can make a great */ /* difference. */ /* */ FT_EXPORT( FT_Long ) FT_MulFix( FT_Long a, FT_Long b ); /* */ #endif #ifdef FT_MULFIX_INLINED #define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b ) #else FT_EXPORT( FT_Long ) FT_MulFix( FT_Long a, FT_Long b ); #endif /*************************************************************************/ /* */ /* <Function> */ /* FT_DivFix */ /* */ /* <Description> */ /* A very simple function used to perform the computation */ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ /* used to divide a given value by a 16.16 fixed float factor. */ /* */ /* <Input> */ /* a :: The first multiplier. */ /* b :: The second multiplier. Use a 16.16 factor here whenever */ /* possible (see note below). */ /* */ /* <Return> */ /* The result of `(a*0x10000)/b'. */ /* */ /* <Note> */ /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */ /* 32~bits, then the division is computed directly. Otherwise, we */ /* use a specialized version of @FT_MulDiv. */ /* */ FT_EXPORT( FT_Long ) FT_DivFix( FT_Long a, FT_Long b ); /*************************************************************************/ /* */ /* <Function> */ /* FT_RoundFix */ /* */ /* <Description> */ /* A very simple function used to round a 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number to be rounded. */ /* */ /* <Return> */ /* The result of `(a + 0x8000) & -0x10000'. */ /* */ FT_EXPORT( FT_Fixed ) FT_RoundFix( FT_Fixed a ); /*************************************************************************/ /* */ /* <Function> */ /* FT_CeilFix */ /* */ /* <Description> */ /* A very simple function used to compute the ceiling function of a */ /* 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number for which the ceiling function is to be computed. */ /* */ /* <Return> */ /* The result of `(a + 0x10000 - 1) & -0x10000'. */ /* */ FT_EXPORT( FT_Fixed ) FT_CeilFix( FT_Fixed a ); /*************************************************************************/ /* */ /* <Function> */ /* FT_FloorFix */ /* */ /* <Description> */ /* A very simple function used to compute the floor function of a */ /* 16.16 fixed number. */ /* */ /* <Input> */ /* a :: The number for which the floor function is to be computed. */ /* */ /* <Return> */ /* The result of `a & -0x10000'. */ /* */ FT_EXPORT( FT_Fixed ) FT_FloorFix( FT_Fixed a ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Vector_Transform */ /* */ /* <Description> */ /* Transform a single vector through a 2x2 matrix. */ /* */ /* <InOut> */ /* vector :: The target vector to transform. */ /* */ /* <Input> */ /* matrix :: A pointer to the source 2x2 matrix. */ /* */ /* <Note> */ /* The result is undefined if either `vector' or `matrix' is invalid. */ /* */ FT_EXPORT( void ) FT_Vector_Transform( FT_Vector* vec, const FT_Matrix* matrix ); /*************************************************************************/ /* */ /* <Section> */ /* version */ /* */ /* <Title> */ /* FreeType Version */ /* */ /* <Abstract> */ /* Functions and macros related to FreeType versions. */ /* */ /* <Description> */ /* Note that those functions and macros are of limited use because */ /* even a new release of FreeType with only documentation changes */ /* increases the version number. */ /* */ /*************************************************************************/ /************************************************************************* * * @enum: * FREETYPE_XXX * * @description: * These three macros identify the FreeType source code version. * Use @FT_Library_Version to access them at runtime. * * @values: * FREETYPE_MAJOR :: The major version number. * FREETYPE_MINOR :: The minor version number. * FREETYPE_PATCH :: The patch level. * * @note: * The version number of FreeType if built as a dynamic link library * with the `libtool' package is _not_ controlled by these three * macros. * */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 3 #define FREETYPE_PATCH 11 /*************************************************************************/ /* */ /* <Function> */ /* FT_Library_Version */ /* */ /* <Description> */ /* Return the version of the FreeType library being used. This is */ /* useful when dynamically linking to the library, since one cannot */ /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */ /* @FREETYPE_PATCH. */ /* */ /* <Input> */ /* library :: A source library handle. */ /* */ /* <Output> */ /* amajor :: The major version number. */ /* */ /* aminor :: The minor version number. */ /* */ /* apatch :: The patch version number. */ /* */ /* <Note> */ /* The reason why this function takes a `library' argument is because */ /* certain programs implement library initialization in a custom way */ /* that doesn't use @FT_Init_FreeType. */ /* */ /* In such cases, the library version might not be available before */ /* the library object has been created. */ /* */ FT_EXPORT( void ) FT_Library_Version( FT_Library library, FT_Int *amajor, FT_Int *aminor, FT_Int *apatch ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_CheckTrueTypePatents */ /* */ /* <Description> */ /* Parse all bytecode instructions of a TrueType font file to check */ /* whether any of the patented opcodes are used. This is only useful */ /* if you want to be able to use the unpatented hinter with */ /* fonts that do *not* use these opcodes. */ /* */ /* Note that this function parses *all* glyph instructions in the */ /* font file, which may be slow. */ /* */ /* <Input> */ /* face :: A face handle. */ /* */ /* <Return> */ /* 1~if this is a TrueType font that uses one of the patented */ /* opcodes, 0~otherwise. */ /* */ /* <Since> */ /* 2.3.5 */ /* */ FT_EXPORT( FT_Bool ) FT_Face_CheckTrueTypePatents( FT_Face face ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Face_SetUnpatentedHinting */ /* */ /* <Description> */ /* Enable or disable the unpatented hinter for a given face. */ /* Only enable it if you have determined that the face doesn't */ /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */ /* */ /* <Input> */ /* face :: A face handle. */ /* */ /* value :: New boolean setting. */ /* */ /* <Return> */ /* The old setting value. This will always be false if this is not */ /* an SFNT font, or if the unpatented hinter is not compiled in this */ /* instance of the library. */ /* */ /* <Since> */ /* 2.3.5 */ /* */ FT_EXPORT( FT_Bool ) FT_Face_SetUnpatentedHinting( FT_Face face, FT_Bool value ); /* */ FT_END_HEADER #endif /* __FREETYPE_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftadvanc.h ================================================ /***************************************************************************/ /* */ /* ftadvanc.h */ /* */ /* Quick computation of advance widths (specification only). */ /* */ /* Copyright 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTADVANC_H__ #define __FTADVANC_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /************************************************************************** * * @section: * quick_advance * * @title: * Quick retrieval of advance values * * @abstract: * Retrieve horizontal and vertical advance values without processing * glyph outlines, if possible. * * @description: * This section contains functions to quickly extract advance values * without handling glyph outlines, if possible. */ /*************************************************************************/ /* */ /* <Const> */ /* FT_ADVANCE_FLAG_FAST_ONLY */ /* */ /* <Description> */ /* A bit-flag to be OR-ed with the `flags' parameter of the */ /* @FT_Get_Advance and @FT_Get_Advances functions. */ /* */ /* If set, it indicates that you want these functions to fail if the */ /* corresponding hinting mode or font driver doesn't allow for very */ /* quick advance computation. */ /* */ /* Typically, glyphs which are either unscaled, unhinted, bitmapped, */ /* or light-hinted can have their advance width computed very */ /* quickly. */ /* */ /* Normal and bytecode hinted modes, which require loading, scaling, */ /* and hinting of the glyph outline, are extremely slow by */ /* comparison. */ /* */ #define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000UL /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Advance */ /* */ /* <Description> */ /* Retrieve the advance value of a given glyph outline in an */ /* @FT_Face. By default, the unhinted advance is returned in font */ /* units. */ /* */ /* <Input> */ /* face :: The source @FT_Face handle. */ /* */ /* gindex :: The glyph index. */ /* */ /* load_flags :: A set of bit flags similar to those used when */ /* calling @FT_Load_Glyph, used to determine what kind */ /* of advances you need. */ /* <Output> */ /* padvance :: The advance value, in either font units or 16.16 */ /* format. */ /* */ /* If @FT_LOAD_VERTICAL_LAYOUT is set, this is the */ /* vertical advance corresponding to a vertical layout. */ /* Otherwise, it is the horizontal advance in a */ /* horizontal layout. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ /* <Note> */ /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ /* if the corresponding font backend doesn't have a quick way to */ /* retrieve the advances. */ /* */ /* A scaled advance is returned in 16.16 format but isn't transformed */ /* by the affine transformation specified by @FT_Set_Transform. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Advance( FT_Face face, FT_UInt gindex, FT_Int32 load_flags, FT_Fixed *padvance ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Advances */ /* */ /* <Description> */ /* Retrieve the advance values of several glyph outlines in an */ /* @FT_Face. By default, the unhinted advances are returned in font */ /* units. */ /* */ /* <Input> */ /* face :: The source @FT_Face handle. */ /* */ /* start :: The first glyph index. */ /* */ /* count :: The number of advance values you want to retrieve. */ /* */ /* load_flags :: A set of bit flags similar to those used when */ /* calling @FT_Load_Glyph. */ /* */ /* <Output> */ /* padvance :: The advances, in either font units or 16.16 format. */ /* This array must contain at least `count' elements. */ /* */ /* If @FT_LOAD_VERTICAL_LAYOUT is set, these are the */ /* vertical advances corresponding to a vertical layout. */ /* Otherwise, they are the horizontal advances in a */ /* horizontal layout. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ /* <Note> */ /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ /* if the corresponding font backend doesn't have a quick way to */ /* retrieve the advances. */ /* */ /* Scaled advances are returned in 16.16 format but aren't */ /* transformed by the affine transformation specified by */ /* @FT_Set_Transform. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Advances( FT_Face face, FT_UInt start, FT_UInt count, FT_Int32 load_flags, FT_Fixed *padvances ); /* */ FT_END_HEADER #endif /* __FTADVANC_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftbbox.h ================================================ /***************************************************************************/ /* */ /* ftbbox.h */ /* */ /* FreeType exact bbox computation (specification). */ /* */ /* Copyright 1996-2001, 2003, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This component has a _single_ role: to compute exact outline bounding */ /* boxes. */ /* */ /* It is separated from the rest of the engine for various technical */ /* reasons. It may well be integrated in `ftoutln' later. */ /* */ /*************************************************************************/ #ifndef __FTBBOX_H__ #define __FTBBOX_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* outline_processing */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Get_BBox */ /* */ /* <Description> */ /* Compute the exact bounding box of an outline. This is slower */ /* than computing the control box. However, it uses an advanced */ /* algorithm which returns _very_ quickly when the two boxes */ /* coincide. Otherwise, the outline Bézier arcs are traversed to */ /* extract their extrema. */ /* */ /* <Input> */ /* outline :: A pointer to the source outline. */ /* */ /* <Output> */ /* abbox :: The outline's exact bounding box. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Get_BBox( FT_Outline* outline, FT_BBox *abbox ); /* */ FT_END_HEADER #endif /* __FTBBOX_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftbdf.h ================================================ /***************************************************************************/ /* */ /* ftbdf.h */ /* */ /* FreeType API for accessing BDF-specific strings (specification). */ /* */ /* Copyright 2002, 2003, 2004, 2006, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTBDF_H__ #define __FTBDF_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* bdf_fonts */ /* */ /* <Title> */ /* BDF and PCF Files */ /* */ /* <Abstract> */ /* BDF and PCF specific API. */ /* */ /* <Description> */ /* This section contains the declaration of functions specific to BDF */ /* and PCF fonts. */ /* */ /*************************************************************************/ /********************************************************************** * * @enum: * FT_PropertyType * * @description: * A list of BDF property types. * * @values: * BDF_PROPERTY_TYPE_NONE :: * Value~0 is used to indicate a missing property. * * BDF_PROPERTY_TYPE_ATOM :: * Property is a string atom. * * BDF_PROPERTY_TYPE_INTEGER :: * Property is a 32-bit signed integer. * * BDF_PROPERTY_TYPE_CARDINAL :: * Property is a 32-bit unsigned integer. */ typedef enum BDF_PropertyType_ { BDF_PROPERTY_TYPE_NONE = 0, BDF_PROPERTY_TYPE_ATOM = 1, BDF_PROPERTY_TYPE_INTEGER = 2, BDF_PROPERTY_TYPE_CARDINAL = 3 } BDF_PropertyType; /********************************************************************** * * @type: * BDF_Property * * @description: * A handle to a @BDF_PropertyRec structure to model a given * BDF/PCF property. */ typedef struct BDF_PropertyRec_* BDF_Property; /********************************************************************** * * @struct: * BDF_PropertyRec * * @description: * This structure models a given BDF/PCF property. * * @fields: * type :: * The property type. * * u.atom :: * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. * * u.integer :: * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER. * * u.cardinal :: * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL. */ typedef struct BDF_PropertyRec_ { BDF_PropertyType type; union { const char* atom; FT_Int32 integer; FT_UInt32 cardinal; } u; } BDF_PropertyRec; /********************************************************************** * * @function: * FT_Get_BDF_Charset_ID * * @description: * Retrieve a BDF font character set identity, according to * the BDF specification. * * @input: * face :: * A handle to the input face. * * @output: * acharset_encoding :: * Charset encoding, as a C~string, owned by the face. * * acharset_registry :: * Charset registry, as a C~string, owned by the face. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with BDF faces, returning an error otherwise. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Charset_ID( FT_Face face, const char* *acharset_encoding, const char* *acharset_registry ); /********************************************************************** * * @function: * FT_Get_BDF_Property * * @description: * Retrieve a BDF property from a BDF or PCF font file. * * @input: * face :: A handle to the input face. * * name :: The property name. * * @output: * aproperty :: The property. * * @return: * FreeType error code. 0~means success. * * @note: * This function works with BDF _and_ PCF fonts. It returns an error * otherwise. It also returns an error if the property is not in the * font. * * A `property' is a either key-value pair within the STARTPROPERTIES * ... ENDPROPERTIES block of a BDF font or a key-value pair from the * `info->props' array within a `FontRec' structure of a PCF font. * * Integer properties are always stored as `signed' within PCF fonts; * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value * for BDF fonts only. * * In case of error, `aproperty->type' is always set to * @BDF_PROPERTY_TYPE_NONE. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Property( FT_Face face, const char* prop_name, BDF_PropertyRec *aproperty ); /* */ FT_END_HEADER #endif /* __FTBDF_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftbitmap.h ================================================ /***************************************************************************/ /* */ /* ftbitmap.h */ /* */ /* FreeType utility functions for bitmaps (specification). */ /* */ /* Copyright 2004, 2005, 2006, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTBITMAP_H__ #define __FTBITMAP_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* bitmap_handling */ /* */ /* <Title> */ /* Bitmap Handling */ /* */ /* <Abstract> */ /* Handling FT_Bitmap objects. */ /* */ /* <Description> */ /* This section contains functions for converting FT_Bitmap objects. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Bitmap_New */ /* */ /* <Description> */ /* Initialize a pointer to an @FT_Bitmap structure. */ /* */ /* <InOut> */ /* abitmap :: A pointer to the bitmap structure. */ /* */ FT_EXPORT( void ) FT_Bitmap_New( FT_Bitmap *abitmap ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Bitmap_Copy */ /* */ /* <Description> */ /* Copy a bitmap into another one. */ /* */ /* <Input> */ /* library :: A handle to a library object. */ /* */ /* source :: A handle to the source bitmap. */ /* */ /* <Output> */ /* target :: A handle to the target bitmap. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Bitmap_Copy( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target); /*************************************************************************/ /* */ /* <Function> */ /* FT_Bitmap_Embolden */ /* */ /* <Description> */ /* Embolden a bitmap. The new bitmap will be about `xStrength' */ /* pixels wider and `yStrength' pixels higher. The left and bottom */ /* borders are kept unchanged. */ /* */ /* <Input> */ /* library :: A handle to a library object. */ /* */ /* xStrength :: How strong the glyph is emboldened horizontally. */ /* Expressed in 26.6 pixel format. */ /* */ /* yStrength :: How strong the glyph is emboldened vertically. */ /* Expressed in 26.6 pixel format. */ /* */ /* <InOut> */ /* bitmap :: A handle to the target bitmap. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The current implementation restricts `xStrength' to be less than */ /* or equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */ /* */ /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */ /* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */ /* */ FT_EXPORT( FT_Error ) FT_Bitmap_Embolden( FT_Library library, FT_Bitmap* bitmap, FT_Pos xStrength, FT_Pos yStrength ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Bitmap_Convert */ /* */ /* <Description> */ /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a */ /* bitmap object with depth 8bpp, making the number of used bytes per */ /* line (a.k.a. the `pitch') a multiple of `alignment'. */ /* */ /* <Input> */ /* library :: A handle to a library object. */ /* */ /* source :: The source bitmap. */ /* */ /* alignment :: The pitch of the bitmap is a multiple of this */ /* parameter. Common values are 1, 2, or 4. */ /* */ /* <Output> */ /* target :: The target bitmap. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* It is possible to call @FT_Bitmap_Convert multiple times without */ /* calling @FT_Bitmap_Done (the memory is simply reallocated). */ /* */ /* Use @FT_Bitmap_Done to finally remove the bitmap object. */ /* */ /* The `library' argument is taken to have access to FreeType's */ /* memory handling functions. */ /* */ FT_EXPORT( FT_Error ) FT_Bitmap_Convert( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target, FT_Int alignment ); /*************************************************************************/ /* */ /* <Function> */ /* FT_GlyphSlot_Own_Bitmap */ /* */ /* <Description> */ /* Make sure that a glyph slot owns `slot->bitmap'. */ /* */ /* <Input> */ /* slot :: The glyph slot. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function is to be used in combination with */ /* @FT_Bitmap_Embolden. */ /* */ FT_EXPORT( FT_Error ) FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Bitmap_Done */ /* */ /* <Description> */ /* Destroy a bitmap object created with @FT_Bitmap_New. */ /* */ /* <Input> */ /* library :: A handle to a library object. */ /* */ /* bitmap :: The bitmap object to be freed. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The `library' argument is taken to have access to FreeType's */ /* memory handling functions. */ /* */ FT_EXPORT( FT_Error ) FT_Bitmap_Done( FT_Library library, FT_Bitmap *bitmap ); /* */ FT_END_HEADER #endif /* __FTBITMAP_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftcache.h ================================================ /***************************************************************************/ /* */ /* ftcache.h */ /* */ /* FreeType Cache subsystem (specification). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTCACHE_H__ #define __FTCACHE_H__ #include <ft2build.h> #include FT_GLYPH_H FT_BEGIN_HEADER /************************************************************************* * * <Section> * cache_subsystem * * <Title> * Cache Sub-System * * <Abstract> * How to cache face, size, and glyph data with FreeType~2. * * <Description> * This section describes the FreeType~2 cache sub-system, which is used * to limit the number of concurrently opened @FT_Face and @FT_Size * objects, as well as caching information like character maps and glyph * images while limiting their maximum memory usage. * * Note that all types and functions begin with the `FTC_' prefix. * * The cache is highly portable and thus doesn't know anything about the * fonts installed on your system, or how to access them. This implies * the following scheme: * * First, available or installed font faces are uniquely identified by * @FTC_FaceID values, provided to the cache by the client. Note that * the cache only stores and compares these values, and doesn't try to * interpret them in any way. * * Second, the cache calls, only when needed, a client-provided function * to convert a @FTC_FaceID into a new @FT_Face object. The latter is * then completely managed by the cache, including its termination * through @FT_Done_Face. * * Clients are free to map face IDs to anything else. The most simple * usage is to associate them to a (pathname,face_index) pair that is * used to call @FT_New_Face. However, more complex schemes are also * possible. * * Note that for the cache to work correctly, the face ID values must be * *persistent*, which means that the contents they point to should not * change at runtime, or that their value should not become invalid. * * If this is unavoidable (e.g., when a font is uninstalled at runtime), * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let * the cache get rid of any references to the old @FTC_FaceID it may * keep internally. Failure to do so will lead to incorrect behaviour * or even crashes. * * To use the cache, start with calling @FTC_Manager_New to create a new * @FTC_Manager object, which models a single cache instance. You can * then look up @FT_Face and @FT_Size objects with * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. * * If you want to use the charmap caching, call @FTC_CMapCache_New, then * later use @FTC_CMapCache_Lookup to perform the equivalent of * @FT_Get_Char_Index, only much faster. * * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then * later use @FTC_ImageCache_Lookup to retrieve the corresponding * @FT_Glyph objects from the cache. * * If you need lots of small bitmaps, it is much more memory efficient * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This * returns @FTC_SBitRec structures, which are used to store small * bitmaps directly. (A small bitmap is one whose metrics and * dimensions all fit into 8-bit integers). * * We hope to also provide a kerning cache in the near future. * * * <Order> * FTC_Manager * FTC_FaceID * FTC_Face_Requester * * FTC_Manager_New * FTC_Manager_Reset * FTC_Manager_Done * FTC_Manager_LookupFace * FTC_Manager_LookupSize * FTC_Manager_RemoveFaceID * * FTC_Node * FTC_Node_Unref * * FTC_ImageCache * FTC_ImageCache_New * FTC_ImageCache_Lookup * * FTC_SBit * FTC_SBitCache * FTC_SBitCache_New * FTC_SBitCache_Lookup * * FTC_CMapCache * FTC_CMapCache_New * FTC_CMapCache_Lookup * *************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** BASIC TYPE DEFINITIONS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /************************************************************************* * * @type: FTC_FaceID * * @description: * An opaque pointer type that is used to identity face objects. The * contents of such objects is application-dependent. * * These pointers are typically used to point to a user-defined * structure containing a font file path, and face index. * * @note: * Never use NULL as a valid @FTC_FaceID. * * Face IDs are passed by the client to the cache manager, which calls, * when needed, the @FTC_Face_Requester to translate them into new * @FT_Face objects. * * If the content of a given face ID changes at runtime, or if the value * becomes invalid (e.g., when uninstalling a font), you should * immediately call @FTC_Manager_RemoveFaceID before any other cache * function. * * Failure to do so will result in incorrect behaviour or even * memory leaks and crashes. */ typedef FT_Pointer FTC_FaceID; /************************************************************************ * * @functype: * FTC_Face_Requester * * @description: * A callback function provided by client applications. It is used by * the cache manager to translate a given @FTC_FaceID into a new valid * @FT_Face object, on demand. * * <Input> * face_id :: * The face ID to resolve. * * library :: * A handle to a FreeType library object. * * req_data :: * Application-provided request data (see note below). * * <Output> * aface :: * A new @FT_Face handle. * * <Return> * FreeType error code. 0~means success. * * <Note> * The third parameter `req_data' is the same as the one passed by the * client when @FTC_Manager_New is called. * * The face requester should not perform funny things on the returned * face object, like creating a new @FT_Size for it, or setting a * transformation through @FT_Set_Transform! */ typedef FT_Error (*FTC_Face_Requester)( FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face* aface ); /* */ #define FT_POINTER_TO_ULONG( p ) ( (FT_ULong)(FT_Pointer)(p) ) #define FTC_FACE_ID_HASH( i ) \ ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \ ( FT_POINTER_TO_ULONG( i ) << 7 ) ) ) /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** CACHE MANAGER OBJECT *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FTC_Manager */ /* */ /* <Description> */ /* This object corresponds to one instance of the cache-subsystem. */ /* It is used to cache one or more @FT_Face objects, along with */ /* corresponding @FT_Size objects. */ /* */ /* The manager intentionally limits the total number of opened */ /* @FT_Face and @FT_Size objects to control memory usage. See the */ /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */ /* */ /* The manager is also used to cache `nodes' of various types while */ /* limiting their total memory usage. */ /* */ /* All limitations are enforced by keeping lists of managed objects */ /* in most-recently-used order, and flushing old nodes to make room */ /* for new ones. */ /* */ typedef struct FTC_ManagerRec_* FTC_Manager; /*************************************************************************/ /* */ /* <Type> */ /* FTC_Node */ /* */ /* <Description> */ /* An opaque handle to a cache node object. Each cache node is */ /* reference-counted. A node with a count of~0 might be flushed */ /* out of a full cache whenever a lookup request is performed. */ /* */ /* If you lookup nodes, you have the ability to `acquire' them, i.e., */ /* to increment their reference count. This will prevent the node */ /* from being flushed out of the cache until you explicitly `release' */ /* it (see @FTC_Node_Unref). */ /* */ /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */ /* */ typedef struct FTC_NodeRec_* FTC_Node; /*************************************************************************/ /* */ /* <Function> */ /* FTC_Manager_New */ /* */ /* <Description> */ /* Create a new cache manager. */ /* */ /* <Input> */ /* library :: The parent FreeType library handle to use. */ /* */ /* max_faces :: Maximum number of opened @FT_Face objects managed by */ /* this cache instance. Use~0 for defaults. */ /* */ /* max_sizes :: Maximum number of opened @FT_Size objects managed by */ /* this cache instance. Use~0 for defaults. */ /* */ /* max_bytes :: Maximum number of bytes to use for cached data nodes. */ /* Use~0 for defaults. Note that this value does not */ /* account for managed @FT_Face and @FT_Size objects. */ /* */ /* requester :: An application-provided callback used to translate */ /* face IDs into real @FT_Face objects. */ /* */ /* req_data :: A generic pointer that is passed to the requester */ /* each time it is called (see @FTC_Face_Requester). */ /* */ /* <Output> */ /* amanager :: A handle to a new manager object. 0~in case of */ /* failure. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FTC_Manager_New( FT_Library library, FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes, FTC_Face_Requester requester, FT_Pointer req_data, FTC_Manager *amanager ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_Manager_Reset */ /* */ /* <Description> */ /* Empty a given cache manager. This simply gets rid of all the */ /* currently cached @FT_Face and @FT_Size objects within the manager. */ /* */ /* <InOut> */ /* manager :: A handle to the manager. */ /* */ FT_EXPORT( void ) FTC_Manager_Reset( FTC_Manager manager ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_Manager_Done */ /* */ /* <Description> */ /* Destroy a given manager after emptying it. */ /* */ /* <Input> */ /* manager :: A handle to the target cache manager object. */ /* */ FT_EXPORT( void ) FTC_Manager_Done( FTC_Manager manager ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_Manager_LookupFace */ /* */ /* <Description> */ /* Retrieve the @FT_Face object that corresponds to a given face ID */ /* through a cache manager. */ /* */ /* <Input> */ /* manager :: A handle to the cache manager. */ /* */ /* face_id :: The ID of the face object. */ /* */ /* <Output> */ /* aface :: A handle to the face object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The returned @FT_Face object is always owned by the manager. You */ /* should never try to discard it yourself. */ /* */ /* The @FT_Face object doesn't necessarily have a current size object */ /* (i.e., face->size can be 0). If you need a specific `font size', */ /* use @FTC_Manager_LookupSize instead. */ /* */ /* Never change the face's transformation matrix (i.e., never call */ /* the @FT_Set_Transform function) on a returned face! If you need */ /* to transform glyphs, do it yourself after glyph loading. */ /* */ /* When you perform a lookup, out-of-memory errors are detected */ /* _within_ the lookup and force incremental flushes of the cache */ /* until enough memory is released for the lookup to succeed. */ /* */ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ /* already been completely flushed, and still no memory was available */ /* for the operation. */ /* */ FT_EXPORT( FT_Error ) FTC_Manager_LookupFace( FTC_Manager manager, FTC_FaceID face_id, FT_Face *aface ); /*************************************************************************/ /* */ /* <Struct> */ /* FTC_ScalerRec */ /* */ /* <Description> */ /* A structure used to describe a given character size in either */ /* pixels or points to the cache manager. See */ /* @FTC_Manager_LookupSize. */ /* */ /* <Fields> */ /* face_id :: The source face ID. */ /* */ /* width :: The character width. */ /* */ /* height :: The character height. */ /* */ /* pixel :: A Boolean. If 1, the `width' and `height' fields are */ /* interpreted as integer pixel character sizes. */ /* Otherwise, they are expressed as 1/64th of points. */ /* */ /* x_res :: Only used when `pixel' is value~0 to indicate the */ /* horizontal resolution in dpi. */ /* */ /* y_res :: Only used when `pixel' is value~0 to indicate the */ /* vertical resolution in dpi. */ /* */ /* <Note> */ /* This type is mainly used to retrieve @FT_Size objects through the */ /* cache manager. */ /* */ typedef struct FTC_ScalerRec_ { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int pixel; FT_UInt x_res; FT_UInt y_res; } FTC_ScalerRec; /*************************************************************************/ /* */ /* <Struct> */ /* FTC_Scaler */ /* */ /* <Description> */ /* A handle to an @FTC_ScalerRec structure. */ /* */ typedef struct FTC_ScalerRec_* FTC_Scaler; /*************************************************************************/ /* */ /* <Function> */ /* FTC_Manager_LookupSize */ /* */ /* <Description> */ /* Retrieve the @FT_Size object that corresponds to a given */ /* @FTC_ScalerRec pointer through a cache manager. */ /* */ /* <Input> */ /* manager :: A handle to the cache manager. */ /* */ /* scaler :: A scaler handle. */ /* */ /* <Output> */ /* asize :: A handle to the size object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The returned @FT_Size object is always owned by the manager. You */ /* should never try to discard it by yourself. */ /* */ /* You can access the parent @FT_Face object simply as `size->face' */ /* if you need it. Note that this object is also owned by the */ /* manager. */ /* */ /* <Note> */ /* When you perform a lookup, out-of-memory errors are detected */ /* _within_ the lookup and force incremental flushes of the cache */ /* until enough memory is released for the lookup to succeed. */ /* */ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ /* already been completely flushed, and still no memory is available */ /* for the operation. */ /* */ FT_EXPORT( FT_Error ) FTC_Manager_LookupSize( FTC_Manager manager, FTC_Scaler scaler, FT_Size *asize ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_Node_Unref */ /* */ /* <Description> */ /* Decrement a cache node's internal reference count. When the count */ /* reaches 0, it is not destroyed but becomes eligible for subsequent */ /* cache flushes. */ /* */ /* <Input> */ /* node :: The cache node handle. */ /* */ /* manager :: The cache manager handle. */ /* */ FT_EXPORT( void ) FTC_Node_Unref( FTC_Node node, FTC_Manager manager ); /************************************************************************* * * @function: * FTC_Manager_RemoveFaceID * * @description: * A special function used to indicate to the cache manager that * a given @FTC_FaceID is no longer valid, either because its * content changed, or because it was deallocated or uninstalled. * * @input: * manager :: * The cache manager handle. * * face_id :: * The @FTC_FaceID to be removed. * * @note: * This function flushes all nodes from the cache corresponding to this * `face_id', with the exception of nodes with a non-null reference * count. * * Such nodes are however modified internally so as to never appear * in later lookups with the same `face_id' value, and to be immediately * destroyed when released by all their users. * */ FT_EXPORT( void ) FTC_Manager_RemoveFaceID( FTC_Manager manager, FTC_FaceID face_id ); /*************************************************************************/ /* */ /* <Section> */ /* cache_subsystem */ /* */ /*************************************************************************/ /************************************************************************* * * @type: * FTC_CMapCache * * @description: * An opaque handle used to model a charmap cache. This cache is to * hold character codes -> glyph indices mappings. * */ typedef struct FTC_CMapCacheRec_* FTC_CMapCache; /************************************************************************* * * @function: * FTC_CMapCache_New * * @description: * Create a new charmap cache. * * @input: * manager :: * A handle to the cache manager. * * @output: * acache :: * A new cache handle. NULL in case of error. * * @return: * FreeType error code. 0~means success. * * @note: * Like all other caches, this one will be destroyed with the cache * manager. * */ FT_EXPORT( FT_Error ) FTC_CMapCache_New( FTC_Manager manager, FTC_CMapCache *acache ); /************************************************************************ * * @function: * FTC_CMapCache_Lookup * * @description: * Translate a character code into a glyph index, using the charmap * cache. * * @input: * cache :: * A charmap cache handle. * * face_id :: * The source face ID. * * cmap_index :: * The index of the charmap in the source face. Any negative value * means to use the cache @FT_Face's default charmap. * * char_code :: * The character code (in the corresponding charmap). * * @return: * Glyph index. 0~means `no glyph'. * */ FT_EXPORT( FT_UInt ) FTC_CMapCache_Lookup( FTC_CMapCache cache, FTC_FaceID face_id, FT_Int cmap_index, FT_UInt32 char_code ); /*************************************************************************/ /* */ /* <Section> */ /* cache_subsystem */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** IMAGE CACHE OBJECT *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /************************************************************************* * * @struct: * FTC_ImageTypeRec * * @description: * A structure used to model the type of images in a glyph cache. * * @fields: * face_id :: * The face ID. * * width :: * The width in pixels. * * height :: * The height in pixels. * * flags :: * The load flags, as in @FT_Load_Glyph. * */ typedef struct FTC_ImageTypeRec_ { FTC_FaceID face_id; FT_Int width; FT_Int height; FT_Int32 flags; } FTC_ImageTypeRec; /************************************************************************* * * @type: * FTC_ImageType * * @description: * A handle to an @FTC_ImageTypeRec structure. * */ typedef struct FTC_ImageTypeRec_* FTC_ImageType; /* */ #define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \ ( (d1)->face_id == (d2)->face_id && \ (d1)->width == (d2)->width && \ (d1)->flags == (d2)->flags ) #define FTC_IMAGE_TYPE_HASH( d ) \ (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id ) ^ \ ( (d)->width << 8 ) ^ (d)->height ^ \ ( (d)->flags << 4 ) ) /*************************************************************************/ /* */ /* <Type> */ /* FTC_ImageCache */ /* */ /* <Description> */ /* A handle to an glyph image cache object. They are designed to */ /* hold many distinct glyph images while not exceeding a certain */ /* memory threshold. */ /* */ typedef struct FTC_ImageCacheRec_* FTC_ImageCache; /*************************************************************************/ /* */ /* <Function> */ /* FTC_ImageCache_New */ /* */ /* <Description> */ /* Create a new glyph image cache. */ /* */ /* <Input> */ /* manager :: The parent manager for the image cache. */ /* */ /* <Output> */ /* acache :: A handle to the new glyph image cache object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FTC_ImageCache_New( FTC_Manager manager, FTC_ImageCache *acache ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_ImageCache_Lookup */ /* */ /* <Description> */ /* Retrieve a given glyph image from a glyph image cache. */ /* */ /* <Input> */ /* cache :: A handle to the source glyph image cache. */ /* */ /* type :: A pointer to a glyph image type descriptor. */ /* */ /* gindex :: The glyph index to retrieve. */ /* */ /* <Output> */ /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ /* failure. */ /* */ /* anode :: Used to return the address of of the corresponding cache */ /* node after incrementing its reference count (see note */ /* below). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The returned glyph is owned and managed by the glyph image cache. */ /* Never try to transform or discard it manually! You can however */ /* create a copy with @FT_Glyph_Copy and modify the new one. */ /* */ /* If `anode' is _not_ NULL, it receives the address of the cache */ /* node containing the glyph image, after increasing its reference */ /* count. This ensures that the node (as well as the @FT_Glyph) will */ /* always be kept in the cache until you call @FTC_Node_Unref to */ /* `release' it. */ /* */ /* If `anode' is NULL, the cache node is left unchanged, which means */ /* that the @FT_Glyph could be flushed out of the cache on the next */ /* call to one of the caching sub-system APIs. Don't assume that it */ /* is persistent! */ /* */ FT_EXPORT( FT_Error ) FTC_ImageCache_Lookup( FTC_ImageCache cache, FTC_ImageType type, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_ImageCache_LookupScaler */ /* */ /* <Description> */ /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */ /* to specify the face ID and its size. */ /* */ /* <Input> */ /* cache :: A handle to the source glyph image cache. */ /* */ /* scaler :: A pointer to a scaler descriptor. */ /* */ /* load_flags :: The corresponding load flags. */ /* */ /* gindex :: The glyph index to retrieve. */ /* */ /* <Output> */ /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ /* failure. */ /* */ /* anode :: Used to return the address of of the corresponding */ /* cache node after incrementing its reference count */ /* (see note below). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The returned glyph is owned and managed by the glyph image cache. */ /* Never try to transform or discard it manually! You can however */ /* create a copy with @FT_Glyph_Copy and modify the new one. */ /* */ /* If `anode' is _not_ NULL, it receives the address of the cache */ /* node containing the glyph image, after increasing its reference */ /* count. This ensures that the node (as well as the @FT_Glyph) will */ /* always be kept in the cache until you call @FTC_Node_Unref to */ /* `release' it. */ /* */ /* If `anode' is NULL, the cache node is left unchanged, which means */ /* that the @FT_Glyph could be flushed out of the cache on the next */ /* call to one of the caching sub-system APIs. Don't assume that it */ /* is persistent! */ /* */ /* Calls to @FT_Set_Char_Size and friends have no effect on cached */ /* glyphs; you should always use the FreeType cache API instead. */ /* */ FT_EXPORT( FT_Error ) FTC_ImageCache_LookupScaler( FTC_ImageCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); /*************************************************************************/ /* */ /* <Type> */ /* FTC_SBit */ /* */ /* <Description> */ /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */ /* structure for details. */ /* */ typedef struct FTC_SBitRec_* FTC_SBit; /*************************************************************************/ /* */ /* <Struct> */ /* FTC_SBitRec */ /* */ /* <Description> */ /* A very compact structure used to describe a small glyph bitmap. */ /* */ /* <Fields> */ /* width :: The bitmap width in pixels. */ /* */ /* height :: The bitmap height in pixels. */ /* */ /* left :: The horizontal distance from the pen position to the */ /* left bitmap border (a.k.a. `left side bearing', or */ /* `lsb'). */ /* */ /* top :: The vertical distance from the pen position (on the */ /* baseline) to the upper bitmap border (a.k.a. `top */ /* side bearing'). The distance is positive for upwards */ /* y~coordinates. */ /* */ /* format :: The format of the glyph bitmap (monochrome or gray). */ /* */ /* max_grays :: Maximum gray level value (in the range 1 to~255). */ /* */ /* pitch :: The number of bytes per bitmap line. May be positive */ /* or negative. */ /* */ /* xadvance :: The horizontal advance width in pixels. */ /* */ /* yadvance :: The vertical advance height in pixels. */ /* */ /* buffer :: A pointer to the bitmap pixels. */ /* */ typedef struct FTC_SBitRec_ { FT_Byte width; FT_Byte height; FT_Char left; FT_Char top; FT_Byte format; FT_Byte max_grays; FT_Short pitch; FT_Char xadvance; FT_Char yadvance; FT_Byte* buffer; } FTC_SBitRec; /*************************************************************************/ /* */ /* <Type> */ /* FTC_SBitCache */ /* */ /* <Description> */ /* A handle to a small bitmap cache. These are special cache objects */ /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */ /* much more efficient way than the traditional glyph image cache */ /* implemented by @FTC_ImageCache. */ /* */ typedef struct FTC_SBitCacheRec_* FTC_SBitCache; /*************************************************************************/ /* */ /* <Function> */ /* FTC_SBitCache_New */ /* */ /* <Description> */ /* Create a new cache to store small glyph bitmaps. */ /* */ /* <Input> */ /* manager :: A handle to the source cache manager. */ /* */ /* <Output> */ /* acache :: A handle to the new sbit cache. NULL in case of error. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FTC_SBitCache_New( FTC_Manager manager, FTC_SBitCache *acache ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_SBitCache_Lookup */ /* */ /* <Description> */ /* Look up a given small glyph bitmap in a given sbit cache and */ /* `lock' it to prevent its flushing from the cache until needed. */ /* */ /* <Input> */ /* cache :: A handle to the source sbit cache. */ /* */ /* type :: A pointer to the glyph image type descriptor. */ /* */ /* gindex :: The glyph index. */ /* */ /* <Output> */ /* sbit :: A handle to a small bitmap descriptor. */ /* */ /* anode :: Used to return the address of of the corresponding cache */ /* node after incrementing its reference count (see note */ /* below). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The small bitmap descriptor and its bit buffer are owned by the */ /* cache and should never be freed by the application. They might */ /* as well disappear from memory on the next cache lookup, so don't */ /* treat them as persistent data. */ /* */ /* The descriptor's `buffer' field is set to~0 to indicate a missing */ /* glyph bitmap. */ /* */ /* If `anode' is _not_ NULL, it receives the address of the cache */ /* node containing the bitmap, after increasing its reference count. */ /* This ensures that the node (as well as the image) will always be */ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ /* */ /* If `anode' is NULL, the cache node is left unchanged, which means */ /* that the bitmap could be flushed out of the cache on the next */ /* call to one of the caching sub-system APIs. Don't assume that it */ /* is persistent! */ /* */ FT_EXPORT( FT_Error ) FTC_SBitCache_Lookup( FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); /*************************************************************************/ /* */ /* <Function> */ /* FTC_SBitCache_LookupScaler */ /* */ /* <Description> */ /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */ /* to specify the face ID and its size. */ /* */ /* <Input> */ /* cache :: A handle to the source sbit cache. */ /* */ /* scaler :: A pointer to the scaler descriptor. */ /* */ /* load_flags :: The corresponding load flags. */ /* */ /* gindex :: The glyph index. */ /* */ /* <Output> */ /* sbit :: A handle to a small bitmap descriptor. */ /* */ /* anode :: Used to return the address of of the corresponding */ /* cache node after incrementing its reference count */ /* (see note below). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The small bitmap descriptor and its bit buffer are owned by the */ /* cache and should never be freed by the application. They might */ /* as well disappear from memory on the next cache lookup, so don't */ /* treat them as persistent data. */ /* */ /* The descriptor's `buffer' field is set to~0 to indicate a missing */ /* glyph bitmap. */ /* */ /* If `anode' is _not_ NULL, it receives the address of the cache */ /* node containing the bitmap, after increasing its reference count. */ /* This ensures that the node (as well as the image) will always be */ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ /* */ /* If `anode' is NULL, the cache node is left unchanged, which means */ /* that the bitmap could be flushed out of the cache on the next */ /* call to one of the caching sub-system APIs. Don't assume that it */ /* is persistent! */ /* */ FT_EXPORT( FT_Error ) FTC_SBitCache_LookupScaler( FTC_SBitCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); /* */ #ifdef FT_CONFIG_OPTION_OLD_INTERNALS /*@***********************************************************************/ /* */ /* <Struct> */ /* FTC_FontRec */ /* */ /* <Description> */ /* A simple structure used to describe a given `font' to the cache */ /* manager. Note that a `font' is the combination of a given face */ /* with a given character size. */ /* */ /* <Fields> */ /* face_id :: The ID of the face to use. */ /* */ /* pix_width :: The character width in integer pixels. */ /* */ /* pix_height :: The character height in integer pixels. */ /* */ typedef struct FTC_FontRec_ { FTC_FaceID face_id; FT_UShort pix_width; FT_UShort pix_height; } FTC_FontRec; /* */ #define FTC_FONT_COMPARE( f1, f2 ) \ ( (f1)->face_id == (f2)->face_id && \ (f1)->pix_width == (f2)->pix_width && \ (f1)->pix_height == (f2)->pix_height ) #define FTC_FONT_HASH( f ) \ (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \ ((f)->pix_width << 8) ^ \ ((f)->pix_height) ) typedef FTC_FontRec* FTC_Font; FT_EXPORT( FT_Error ) FTC_Manager_Lookup_Face( FTC_Manager manager, FTC_FaceID face_id, FT_Face *aface ); FT_EXPORT( FT_Error ) FTC_Manager_Lookup_Size( FTC_Manager manager, FTC_Font font, FT_Face *aface, FT_Size *asize ); #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ /* */ FT_END_HEADER #endif /* __FTCACHE_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftchapters.h ================================================ /***************************************************************************/ /* */ /* This file defines the structure of the FreeType reference. */ /* It is used by the python script which generates the HTML files. */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* <Chapter> */ /* general_remarks */ /* */ /* <Title> */ /* General Remarks */ /* */ /* <Sections> */ /* user_allocation */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* <Chapter> */ /* core_api */ /* */ /* <Title> */ /* Core API */ /* */ /* <Sections> */ /* version */ /* basic_types */ /* base_interface */ /* glyph_variants */ /* glyph_management */ /* mac_specific */ /* sizes_management */ /* header_file_macros */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* <Chapter> */ /* format_specific */ /* */ /* <Title> */ /* Format-Specific API */ /* */ /* <Sections> */ /* multiple_masters */ /* truetype_tables */ /* type1_tables */ /* sfnt_names */ /* bdf_fonts */ /* cid_fonts */ /* pfr_fonts */ /* winfnt_fonts */ /* font_formats */ /* gasp_table */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* <Chapter> */ /* cache_subsystem */ /* */ /* <Title> */ /* Cache Sub-System */ /* */ /* <Sections> */ /* cache_subsystem */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* <Chapter> */ /* support_api */ /* */ /* <Title> */ /* Support API */ /* */ /* <Sections> */ /* computations */ /* list_processing */ /* outline_processing */ /* quick_advance */ /* bitmap_handling */ /* raster */ /* glyph_stroker */ /* system_interface */ /* module_management */ /* gzip */ /* lzw */ /* lcd_filtering */ /* */ /***************************************************************************/ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftcid.h ================================================ /***************************************************************************/ /* */ /* ftcid.h */ /* */ /* FreeType API for accessing CID font information (specification). */ /* */ /* Copyright 2007, 2009 by Dereg Clegg, Michael Toftdal. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTCID_H__ #define __FTCID_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* cid_fonts */ /* */ /* <Title> */ /* CID Fonts */ /* */ /* <Abstract> */ /* CID-keyed font specific API. */ /* */ /* <Description> */ /* This section contains the declaration of CID-keyed font specific */ /* functions. */ /* */ /*************************************************************************/ /********************************************************************** * * @function: * FT_Get_CID_Registry_Ordering_Supplement * * @description: * Retrieve the Registry/Ordering/Supplement triple (also known as the * "R/O/S") from a CID-keyed font. * * @input: * face :: * A handle to the input face. * * @output: * registry :: * The registry, as a C~string, owned by the face. * * ordering :: * The ordering, as a C~string, owned by the face. * * supplement :: * The supplement. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with CID faces, returning an error * otherwise. * * @since: * 2.3.6 */ FT_EXPORT( FT_Error ) FT_Get_CID_Registry_Ordering_Supplement( FT_Face face, const char* *registry, const char* *ordering, FT_Int *supplement); /********************************************************************** * * @function: * FT_Get_CID_Is_Internally_CID_Keyed * * @description: * Retrieve the type of the input face, CID keyed or not. In * constrast to the @FT_IS_CID_KEYED macro this function returns * successfully also for CID-keyed fonts in an SNFT wrapper. * * @input: * face :: * A handle to the input face. * * @output: * is_cid :: * The type of the face as an @FT_Bool. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with CID faces and OpenType fonts, * returning an error otherwise. * * @since: * 2.3.9 */ FT_EXPORT( FT_Error ) FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face, FT_Bool *is_cid ); /********************************************************************** * * @function: * FT_Get_CID_From_Glyph_Index * * @description: * Retrieve the CID of the input glyph index. * * @input: * face :: * A handle to the input face. * * glyph_index :: * The input glyph index. * * @output: * cid :: * The CID as an @FT_UInt. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with CID faces and OpenType fonts, * returning an error otherwise. * * @since: * 2.3.9 */ FT_EXPORT( FT_Error ) FT_Get_CID_From_Glyph_Index( FT_Face face, FT_UInt glyph_index, FT_UInt *cid ); /* */ FT_END_HEADER #endif /* __FTCID_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/fterrdef.h ================================================ /***************************************************************************/ /* */ /* fterrdef.h */ /* */ /* FreeType error codes (specification). */ /* */ /* Copyright 2002, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** LIST OF ERROR CODES/MESSAGES *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */ /* including this file. */ /* generic errors */ FT_NOERRORDEF_( Ok, 0x00, \ "no error" ) FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \ "cannot open resource" ) FT_ERRORDEF_( Unknown_File_Format, 0x02, \ "unknown file format" ) FT_ERRORDEF_( Invalid_File_Format, 0x03, \ "broken file" ) FT_ERRORDEF_( Invalid_Version, 0x04, \ "invalid FreeType version" ) FT_ERRORDEF_( Lower_Module_Version, 0x05, \ "module version is too low" ) FT_ERRORDEF_( Invalid_Argument, 0x06, \ "invalid argument" ) FT_ERRORDEF_( Unimplemented_Feature, 0x07, \ "unimplemented feature" ) FT_ERRORDEF_( Invalid_Table, 0x08, \ "broken table" ) FT_ERRORDEF_( Invalid_Offset, 0x09, \ "broken offset within table" ) FT_ERRORDEF_( Array_Too_Large, 0x0A, \ "array allocation size too large" ) /* glyph/character errors */ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \ "invalid glyph index" ) FT_ERRORDEF_( Invalid_Character_Code, 0x11, \ "invalid character code" ) FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \ "unsupported glyph image format" ) FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \ "cannot render this glyph format" ) FT_ERRORDEF_( Invalid_Outline, 0x14, \ "invalid outline" ) FT_ERRORDEF_( Invalid_Composite, 0x15, \ "invalid composite glyph" ) FT_ERRORDEF_( Too_Many_Hints, 0x16, \ "too many hints" ) FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \ "invalid pixel size" ) /* handle errors */ FT_ERRORDEF_( Invalid_Handle, 0x20, \ "invalid object handle" ) FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \ "invalid library handle" ) FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \ "invalid module handle" ) FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \ "invalid face handle" ) FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \ "invalid size handle" ) FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \ "invalid glyph slot handle" ) FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \ "invalid charmap handle" ) FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \ "invalid cache manager handle" ) FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \ "invalid stream handle" ) /* driver errors */ FT_ERRORDEF_( Too_Many_Drivers, 0x30, \ "too many modules" ) FT_ERRORDEF_( Too_Many_Extensions, 0x31, \ "too many extensions" ) /* memory errors */ FT_ERRORDEF_( Out_Of_Memory, 0x40, \ "out of memory" ) FT_ERRORDEF_( Unlisted_Object, 0x41, \ "unlisted object" ) /* stream errors */ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \ "cannot open stream" ) FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \ "invalid stream seek" ) FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \ "invalid stream skip" ) FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \ "invalid stream read" ) FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \ "invalid stream operation" ) FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \ "invalid frame operation" ) FT_ERRORDEF_( Nested_Frame_Access, 0x57, \ "nested frame access" ) FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \ "invalid frame read" ) /* raster errors */ FT_ERRORDEF_( Raster_Uninitialized, 0x60, \ "raster uninitialized" ) FT_ERRORDEF_( Raster_Corrupted, 0x61, \ "raster corrupted" ) FT_ERRORDEF_( Raster_Overflow, 0x62, \ "raster overflow" ) FT_ERRORDEF_( Raster_Negative_Height, 0x63, \ "negative height while rastering" ) /* cache errors */ FT_ERRORDEF_( Too_Many_Caches, 0x70, \ "too many registered caches" ) /* TrueType and SFNT errors */ FT_ERRORDEF_( Invalid_Opcode, 0x80, \ "invalid opcode" ) FT_ERRORDEF_( Too_Few_Arguments, 0x81, \ "too few arguments" ) FT_ERRORDEF_( Stack_Overflow, 0x82, \ "stack overflow" ) FT_ERRORDEF_( Code_Overflow, 0x83, \ "code overflow" ) FT_ERRORDEF_( Bad_Argument, 0x84, \ "bad argument" ) FT_ERRORDEF_( Divide_By_Zero, 0x85, \ "division by zero" ) FT_ERRORDEF_( Invalid_Reference, 0x86, \ "invalid reference" ) FT_ERRORDEF_( Debug_OpCode, 0x87, \ "found debug opcode" ) FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \ "found ENDF opcode in execution stream" ) FT_ERRORDEF_( Nested_DEFS, 0x89, \ "nested DEFS" ) FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \ "invalid code range" ) FT_ERRORDEF_( Execution_Too_Long, 0x8B, \ "execution context too long" ) FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \ "too many function definitions" ) FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \ "too many instruction definitions" ) FT_ERRORDEF_( Table_Missing, 0x8E, \ "SFNT font table missing" ) FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \ "horizontal header (hhea) table missing" ) FT_ERRORDEF_( Locations_Missing, 0x90, \ "locations (loca) table missing" ) FT_ERRORDEF_( Name_Table_Missing, 0x91, \ "name table missing" ) FT_ERRORDEF_( CMap_Table_Missing, 0x92, \ "character map (cmap) table missing" ) FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \ "horizontal metrics (hmtx) table missing" ) FT_ERRORDEF_( Post_Table_Missing, 0x94, \ "PostScript (post) table missing" ) FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \ "invalid horizontal metrics" ) FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \ "invalid character map (cmap) format" ) FT_ERRORDEF_( Invalid_PPem, 0x97, \ "invalid ppem value" ) FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \ "invalid vertical metrics" ) FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \ "could not find context" ) FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \ "invalid PostScript (post) table format" ) FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \ "invalid PostScript (post) table" ) /* CFF, CID, and Type 1 errors */ FT_ERRORDEF_( Syntax_Error, 0xA0, \ "opcode syntax error" ) FT_ERRORDEF_( Stack_Underflow, 0xA1, \ "argument stack underflow" ) FT_ERRORDEF_( Ignore, 0xA2, \ "ignore" ) /* BDF errors */ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \ "`STARTFONT' field missing" ) FT_ERRORDEF_( Missing_Font_Field, 0xB1, \ "`FONT' field missing" ) FT_ERRORDEF_( Missing_Size_Field, 0xB2, \ "`SIZE' field missing" ) FT_ERRORDEF_( Missing_Chars_Field, 0xB3, \ "`CHARS' field missing" ) FT_ERRORDEF_( Missing_Startchar_Field, 0xB4, \ "`STARTCHAR' field missing" ) FT_ERRORDEF_( Missing_Encoding_Field, 0xB5, \ "`ENCODING' field missing" ) FT_ERRORDEF_( Missing_Bbx_Field, 0xB6, \ "`BBX' field missing" ) FT_ERRORDEF_( Bbx_Too_Big, 0xB7, \ "`BBX' too big" ) FT_ERRORDEF_( Corrupted_Font_Header, 0xB8, \ "Font header corrupted or missing fields" ) FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xB9, \ "Font glyphs corrupted or missing fields" ) /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/fterrors.h ================================================ /***************************************************************************/ /* */ /* fterrors.h */ /* */ /* FreeType error code handling (specification). */ /* */ /* Copyright 1996-2001, 2002, 2004, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This special header file is used to define the handling of FT2 */ /* enumeration constants. It can also be used to generate error message */ /* strings with a small macro trick explained below. */ /* */ /* I - Error Formats */ /* ----------------- */ /* */ /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */ /* defined in ftoption.h in order to make the higher byte indicate */ /* the module where the error has happened (this is not compatible */ /* with standard builds of FreeType 2). You can then use the macro */ /* FT_ERROR_BASE macro to extract the generic error code from an */ /* FT_Error value. */ /* */ /* */ /* II - Error Message strings */ /* -------------------------- */ /* */ /* The error definitions below are made through special macros that */ /* allow client applications to build a table of error message strings */ /* if they need it. The strings are not included in a normal build of */ /* FreeType 2 to save space (most client applications do not use */ /* them). */ /* */ /* To do so, you have to define the following macros before including */ /* this file: */ /* */ /* FT_ERROR_START_LIST :: */ /* This macro is called before anything else to define the start of */ /* the error list. It is followed by several FT_ERROR_DEF calls */ /* (see below). */ /* */ /* FT_ERROR_DEF( e, v, s ) :: */ /* This macro is called to define one single error. */ /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */ /* `v' is the error numerical value. */ /* `s' is the corresponding error string. */ /* */ /* FT_ERROR_END_LIST :: */ /* This macro ends the list. */ /* */ /* Additionally, you have to undefine __FTERRORS_H__ before #including */ /* this file. */ /* */ /* Here is a simple example: */ /* */ /* { */ /* #undef __FTERRORS_H__ */ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ /* #define FT_ERROR_START_LIST { */ /* #define FT_ERROR_END_LIST { 0, 0 } }; */ /* */ /* const struct */ /* { */ /* int err_code; */ /* const char* err_msg; */ /* } ft_errors[] = */ /* */ /* #include FT_ERRORS_H */ /* } */ /* */ /*************************************************************************/ #ifndef __FTERRORS_H__ #define __FTERRORS_H__ /* include module base error codes */ #include FT_MODULE_ERRORS_H /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** SETUP MACROS *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ #undef FT_NEED_EXTERN_C #undef FT_ERR_XCAT #undef FT_ERR_CAT #define FT_ERR_XCAT( x, y ) x ## y #define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) /* FT_ERR_PREFIX is used as a prefix for error identifiers. */ /* By default, we use `FT_Err_'. */ /* */ #ifndef FT_ERR_PREFIX #define FT_ERR_PREFIX FT_Err_ #endif /* FT_ERR_BASE is used as the base for module-specific errors. */ /* */ #ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS #ifndef FT_ERR_BASE #define FT_ERR_BASE FT_Mod_Err_Base #endif #else #undef FT_ERR_BASE #define FT_ERR_BASE 0 #endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */ /* If FT_ERRORDEF is not defined, we need to define a simple */ /* enumeration type. */ /* */ #ifndef FT_ERRORDEF #define FT_ERRORDEF( e, v, s ) e = v, #define FT_ERROR_START_LIST enum { #define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) }; #ifdef __cplusplus #define FT_NEED_EXTERN_C extern "C" { #endif #endif /* !FT_ERRORDEF */ /* this macro is used to define an error */ #define FT_ERRORDEF_( e, v, s ) \ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s ) /* this is only used for <module>_Err_Ok, which must be 0! */ #define FT_NOERRORDEF_( e, v, s ) \ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s ) #ifdef FT_ERROR_START_LIST FT_ERROR_START_LIST #endif /* now include the error codes */ #include FT_ERROR_DEFINITIONS_H #ifdef FT_ERROR_END_LIST FT_ERROR_END_LIST #endif /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** SIMPLE CLEANUP *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ #ifdef FT_NEED_EXTERN_C } #endif #undef FT_ERROR_START_LIST #undef FT_ERROR_END_LIST #undef FT_ERRORDEF #undef FT_ERRORDEF_ #undef FT_NOERRORDEF_ #undef FT_NEED_EXTERN_C #undef FT_ERR_CONCAT #undef FT_ERR_BASE /* FT_KEEP_ERR_PREFIX is needed for ftvalid.h */ #ifndef FT_KEEP_ERR_PREFIX #undef FT_ERR_PREFIX #endif #endif /* __FTERRORS_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftgasp.h ================================================ /***************************************************************************/ /* */ /* ftgasp.h */ /* */ /* Access of TrueType's `gasp' table (specification). */ /* */ /* Copyright 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef _FT_GASP_H_ #define _FT_GASP_H_ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif /*************************************************************************** * * @section: * gasp_table * * @title: * Gasp Table * * @abstract: * Retrieving TrueType `gasp' table entries. * * @description: * The function @FT_Get_Gasp can be used to query a TrueType or OpenType * font for specific entries in its `gasp' table, if any. This is * mainly useful when implementing native TrueType hinting with the * bytecode interpreter to duplicate the Windows text rendering results. */ /************************************************************************* * * @enum: * FT_GASP_XXX * * @description: * A list of values and/or bit-flags returned by the @FT_Get_Gasp * function. * * @values: * FT_GASP_NO_TABLE :: * This special value means that there is no GASP table in this face. * It is up to the client to decide what to do. * * FT_GASP_DO_GRIDFIT :: * Grid-fitting and hinting should be performed at the specified ppem. * This *really* means TrueType bytecode interpretation. * * FT_GASP_DO_GRAY :: * Anti-aliased rendering should be performed at the specified ppem. * * FT_GASP_SYMMETRIC_SMOOTHING :: * Smoothing along multiple axes must be used with ClearType. * * FT_GASP_SYMMETRIC_GRIDFIT :: * Grid-fitting must be used with ClearType's symmetric smoothing. * * @note: * `ClearType' is Microsoft's implementation of LCD rendering, partly * protected by patents. * * @since: * 2.3.0 */ #define FT_GASP_NO_TABLE -1 #define FT_GASP_DO_GRIDFIT 0x01 #define FT_GASP_DO_GRAY 0x02 #define FT_GASP_SYMMETRIC_SMOOTHING 0x08 #define FT_GASP_SYMMETRIC_GRIDFIT 0x10 /************************************************************************* * * @func: * FT_Get_Gasp * * @description: * Read the `gasp' table from a TrueType or OpenType font file and * return the entry corresponding to a given character pixel size. * * @input: * face :: The source face handle. * ppem :: The vertical character pixel size. * * @return: * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no * `gasp' table in the face. * * @since: * 2.3.0 */ FT_EXPORT( FT_Int ) FT_Get_Gasp( FT_Face face, FT_UInt ppem ); /* */ #endif /* _FT_GASP_H_ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftglyph.h ================================================ /***************************************************************************/ /* */ /* ftglyph.h */ /* */ /* FreeType convenience functions to handle glyphs (specification). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This file contains the definition of several convenience functions */ /* that can be used by client applications to easily retrieve glyph */ /* bitmaps and outlines from a given face. */ /* */ /* These functions should be optional if you are writing a font server */ /* or text layout engine on top of FreeType. However, they are pretty */ /* handy for many other simple uses of the library. */ /* */ /*************************************************************************/ #ifndef __FTGLYPH_H__ #define __FTGLYPH_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* glyph_management */ /* */ /* <Title> */ /* Glyph Management */ /* */ /* <Abstract> */ /* Generic interface to manage individual glyph data. */ /* */ /* <Description> */ /* This section contains definitions used to manage glyph data */ /* through generic FT_Glyph objects. Each of them can contain a */ /* bitmap, a vector outline, or even images in other formats. */ /* */ /*************************************************************************/ /* forward declaration to a private type */ typedef struct FT_Glyph_Class_ FT_Glyph_Class; /*************************************************************************/ /* */ /* <Type> */ /* FT_Glyph */ /* */ /* <Description> */ /* Handle to an object used to model generic glyph images. It is a */ /* pointer to the @FT_GlyphRec structure and can contain a glyph */ /* bitmap or pointer. */ /* */ /* <Note> */ /* Glyph objects are not owned by the library. You must thus release */ /* them manually (through @FT_Done_Glyph) _before_ calling */ /* @FT_Done_FreeType. */ /* */ typedef struct FT_GlyphRec_* FT_Glyph; /*************************************************************************/ /* */ /* <Struct> */ /* FT_GlyphRec */ /* */ /* <Description> */ /* The root glyph structure contains a given glyph image plus its */ /* advance width in 16.16 fixed float format. */ /* */ /* <Fields> */ /* library :: A handle to the FreeType library object. */ /* */ /* clazz :: A pointer to the glyph's class. Private. */ /* */ /* format :: The format of the glyph's image. */ /* */ /* advance :: A 16.16 vector that gives the glyph's advance width. */ /* */ typedef struct FT_GlyphRec_ { FT_Library library; const FT_Glyph_Class* clazz; FT_Glyph_Format format; FT_Vector advance; } FT_GlyphRec; /*************************************************************************/ /* */ /* <Type> */ /* FT_BitmapGlyph */ /* */ /* <Description> */ /* A handle to an object used to model a bitmap glyph image. This is */ /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ /* */ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; /*************************************************************************/ /* */ /* <Struct> */ /* FT_BitmapGlyphRec */ /* */ /* <Description> */ /* A structure used for bitmap glyph images. This really is a */ /* `sub-class' of @FT_GlyphRec. */ /* */ /* <Fields> */ /* root :: The root @FT_Glyph fields. */ /* */ /* left :: The left-side bearing, i.e., the horizontal distance */ /* from the current pen position to the left border of the */ /* glyph bitmap. */ /* */ /* top :: The top-side bearing, i.e., the vertical distance from */ /* the current pen position to the top border of the glyph */ /* bitmap. This distance is positive for upwards~y! */ /* */ /* bitmap :: A descriptor for the bitmap. */ /* */ /* <Note> */ /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */ /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */ /* the bitmap's contents easily. */ /* */ /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */ /* and is thus created and destroyed with it. */ /* */ typedef struct FT_BitmapGlyphRec_ { FT_GlyphRec root; FT_Int left; FT_Int top; FT_Bitmap bitmap; } FT_BitmapGlyphRec; /*************************************************************************/ /* */ /* <Type> */ /* FT_OutlineGlyph */ /* */ /* <Description> */ /* A handle to an object used to model an outline glyph image. This */ /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ /* */ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; /*************************************************************************/ /* */ /* <Struct> */ /* FT_OutlineGlyphRec */ /* */ /* <Description> */ /* A structure used for outline (vectorial) glyph images. This */ /* really is a `sub-class' of @FT_GlyphRec. */ /* */ /* <Fields> */ /* root :: The root @FT_Glyph fields. */ /* */ /* outline :: A descriptor for the outline. */ /* */ /* <Note> */ /* You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have */ /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */ /* the outline's content easily. */ /* */ /* As the outline is extracted from a glyph slot, its coordinates are */ /* expressed normally in 26.6 pixels, unless the flag */ /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */ /* */ /* The outline's tables are always owned by the object and are */ /* destroyed with it. */ /* */ typedef struct FT_OutlineGlyphRec_ { FT_GlyphRec root; FT_Outline outline; } FT_OutlineGlyphRec; /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Glyph */ /* */ /* <Description> */ /* A function used to extract a glyph image from a slot. Note that */ /* the created @FT_Glyph object must be released with @FT_Done_Glyph. */ /* */ /* <Input> */ /* slot :: A handle to the source glyph slot. */ /* */ /* <Output> */ /* aglyph :: A handle to the glyph object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, FT_Glyph *aglyph ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Glyph_Copy */ /* */ /* <Description> */ /* A function used to copy a glyph image. Note that the created */ /* @FT_Glyph object must be released with @FT_Done_Glyph. */ /* */ /* <Input> */ /* source :: A handle to the source glyph object. */ /* */ /* <Output> */ /* target :: A handle to the target glyph object. 0~in case of */ /* error. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Glyph_Copy( FT_Glyph source, FT_Glyph *target ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Glyph_Transform */ /* */ /* <Description> */ /* Transform a glyph image if its format is scalable. */ /* */ /* <InOut> */ /* glyph :: A handle to the target glyph object. */ /* */ /* <Input> */ /* matrix :: A pointer to a 2x2 matrix to apply. */ /* */ /* delta :: A pointer to a 2d vector to apply. Coordinates are */ /* expressed in 1/64th of a pixel. */ /* */ /* <Return> */ /* FreeType error code (if not 0, the glyph format is not scalable). */ /* */ /* <Note> */ /* The 2x2 transformation matrix is also applied to the glyph's */ /* advance vector. */ /* */ FT_EXPORT( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, FT_Matrix* matrix, FT_Vector* delta ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_Glyph_BBox_Mode */ /* */ /* <Description> */ /* The mode how the values of @FT_Glyph_Get_CBox are returned. */ /* */ /* <Values> */ /* FT_GLYPH_BBOX_UNSCALED :: */ /* Return unscaled font units. */ /* */ /* FT_GLYPH_BBOX_SUBPIXELS :: */ /* Return unfitted 26.6 coordinates. */ /* */ /* FT_GLYPH_BBOX_GRIDFIT :: */ /* Return grid-fitted 26.6 coordinates. */ /* */ /* FT_GLYPH_BBOX_TRUNCATE :: */ /* Return coordinates in integer pixels. */ /* */ /* FT_GLYPH_BBOX_PIXELS :: */ /* Return grid-fitted pixel coordinates. */ /* */ typedef enum FT_Glyph_BBox_Mode_ { FT_GLYPH_BBOX_UNSCALED = 0, FT_GLYPH_BBOX_SUBPIXELS = 0, FT_GLYPH_BBOX_GRIDFIT = 1, FT_GLYPH_BBOX_TRUNCATE = 2, FT_GLYPH_BBOX_PIXELS = 3 } FT_Glyph_BBox_Mode; /*************************************************************************/ /* */ /* <Enum> */ /* ft_glyph_bbox_xxx */ /* */ /* <Description> */ /* These constants are deprecated. Use the corresponding */ /* @FT_Glyph_BBox_Mode values instead. */ /* */ /* <Values> */ /* ft_glyph_bbox_unscaled :: See @FT_GLYPH_BBOX_UNSCALED. */ /* ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS. */ /* ft_glyph_bbox_gridfit :: See @FT_GLYPH_BBOX_GRIDFIT. */ /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */ /* ft_glyph_bbox_pixels :: See @FT_GLYPH_BBOX_PIXELS. */ /* */ #define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED #define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS #define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT #define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE #define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS /*************************************************************************/ /* */ /* <Function> */ /* FT_Glyph_Get_CBox */ /* */ /* <Description> */ /* Return a glyph's `control box'. The control box encloses all the */ /* outline's points, including Bézier control points. Though it */ /* coincides with the exact bounding box for most glyphs, it can be */ /* slightly larger in some situations (like when rotating an outline */ /* which contains Bézier outside arcs). */ /* */ /* Computing the control box is very fast, while getting the bounding */ /* box can take much more time as it needs to walk over all segments */ /* and arcs in the outline. To get the latter, you can use the */ /* `ftbbox' component which is dedicated to this single task. */ /* */ /* <Input> */ /* glyph :: A handle to the source glyph object. */ /* */ /* mode :: The mode which indicates how to interpret the returned */ /* bounding box values. */ /* */ /* <Output> */ /* acbox :: The glyph coordinate bounding box. Coordinates are */ /* expressed in 1/64th of pixels if it is grid-fitted. */ /* */ /* <Note> */ /* Coordinates are relative to the glyph origin, using the y~upwards */ /* convention. */ /* */ /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */ /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */ /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */ /* is another name for this constant. */ /* */ /* Note that the maximum coordinates are exclusive, which means that */ /* one can compute the width and height of the glyph image (be it in */ /* integer or 26.6 pixels) as: */ /* */ /* { */ /* width = bbox.xMax - bbox.xMin; */ /* height = bbox.yMax - bbox.yMin; */ /* } */ /* */ /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */ /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */ /* which corresponds to: */ /* */ /* { */ /* bbox.xMin = FLOOR(bbox.xMin); */ /* bbox.yMin = FLOOR(bbox.yMin); */ /* bbox.xMax = CEILING(bbox.xMax); */ /* bbox.yMax = CEILING(bbox.yMax); */ /* } */ /* */ /* To get the bbox in pixel coordinates, set `bbox_mode' to */ /* @FT_GLYPH_BBOX_TRUNCATE. */ /* */ /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */ /* to @FT_GLYPH_BBOX_PIXELS. */ /* */ FT_EXPORT( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, FT_UInt bbox_mode, FT_BBox *acbox ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Glyph_To_Bitmap */ /* */ /* <Description> */ /* Convert a given glyph object to a bitmap glyph object. */ /* */ /* <InOut> */ /* the_glyph :: A pointer to a handle to the target glyph. */ /* */ /* <Input> */ /* render_mode :: An enumeration that describes how the data is */ /* rendered. */ /* */ /* origin :: A pointer to a vector used to translate the glyph */ /* image before rendering. Can be~0 (if no */ /* translation). The origin is expressed in */ /* 26.6 pixels. */ /* */ /* destroy :: A boolean that indicates that the original glyph */ /* image should be destroyed by this function. It is */ /* never destroyed in case of error. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function does nothing if the glyph format isn't scalable. */ /* */ /* The glyph image is translated with the `origin' vector before */ /* rendering. */ /* */ /* The first parameter is a pointer to an @FT_Glyph handle, that will */ /* be _replaced_ by this function (with newly allocated data). */ /* Typically, you would use (omitting error handling): */ /* */ /* */ /* { */ /* FT_Glyph glyph; */ /* FT_BitmapGlyph glyph_bitmap; */ /* */ /* */ /* // load glyph */ /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ /* */ /* // extract glyph image */ /* error = FT_Get_Glyph( face->glyph, &glyph ); */ /* */ /* // convert to a bitmap (default render mode + destroying old) */ /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */ /* { */ /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_DEFAULT, */ /* 0, 1 ); */ /* if ( error ) // `glyph' unchanged */ /* ... */ /* } */ /* */ /* // access bitmap content by typecasting */ /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ /* */ /* // do funny stuff with it, like blitting/drawing */ /* ... */ /* */ /* // discard glyph image (bitmap or not) */ /* FT_Done_Glyph( glyph ); */ /* } */ /* */ /* */ /* Here another example, again without error handling: */ /* */ /* */ /* { */ /* FT_Glyph glyphs[MAX_GLYPHS] */ /* */ /* */ /* ... */ /* */ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ /* error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || */ /* FT_Get_Glyph ( face->glyph, &glyph[idx] ); */ /* */ /* ... */ /* */ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ /* { */ /* FT_Glyph bitmap = glyphs[idx]; */ /* */ /* */ /* ... */ /* */ /* // after this call, `bitmap' no longer points into */ /* // the `glyphs' array (and the old value isn't destroyed) */ /* FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); */ /* */ /* ... */ /* */ /* FT_Done_Glyph( bitmap ); */ /* } */ /* */ /* ... */ /* */ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ /* FT_Done_Glyph( glyphs[idx] ); */ /* } */ /* */ FT_EXPORT( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, FT_Render_Mode render_mode, FT_Vector* origin, FT_Bool destroy ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Done_Glyph */ /* */ /* <Description> */ /* Destroy a given glyph. */ /* */ /* <Input> */ /* glyph :: A handle to the target glyph object. */ /* */ FT_EXPORT( void ) FT_Done_Glyph( FT_Glyph glyph ); /* */ /* other helpful functions */ /*************************************************************************/ /* */ /* <Section> */ /* computations */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Matrix_Multiply */ /* */ /* <Description> */ /* Perform the matrix operation `b = a*b'. */ /* */ /* <Input> */ /* a :: A pointer to matrix `a'. */ /* */ /* <InOut> */ /* b :: A pointer to matrix `b'. */ /* */ /* <Note> */ /* The result is undefined if either `a' or `b' is zero. */ /* */ FT_EXPORT( void ) FT_Matrix_Multiply( const FT_Matrix* a, FT_Matrix* b ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Matrix_Invert */ /* */ /* <Description> */ /* Invert a 2x2 matrix. Return an error if it can't be inverted. */ /* */ /* <InOut> */ /* matrix :: A pointer to the target matrix. Remains untouched in */ /* case of error. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ); /* */ FT_END_HEADER #endif /* __FTGLYPH_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftgxval.h ================================================ /***************************************************************************/ /* */ /* ftgxval.h */ /* */ /* FreeType API for validating TrueTypeGX/AAT tables (specification). */ /* */ /* Copyright 2004, 2005, 2006 by */ /* Masatake YAMATO, Redhat K.K, */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* gxvalid is derived from both gxlayout module and otvalid module. */ /* Development of gxlayout is supported by the Information-technology */ /* Promotion Agency(IPA), Japan. */ /* */ /***************************************************************************/ #ifndef __FTGXVAL_H__ #define __FTGXVAL_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* gx_validation */ /* */ /* <Title> */ /* TrueTypeGX/AAT Validation */ /* */ /* <Abstract> */ /* An API to validate TrueTypeGX/AAT tables. */ /* */ /* <Description> */ /* This section contains the declaration of functions to validate */ /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */ /* trak, prop, lcar). */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* */ /* Warning: Use FT_VALIDATE_XXX to validate a table. */ /* Following definitions are for gxvalid developers. */ /* */ /* */ /*************************************************************************/ #define FT_VALIDATE_feat_INDEX 0 #define FT_VALIDATE_mort_INDEX 1 #define FT_VALIDATE_morx_INDEX 2 #define FT_VALIDATE_bsln_INDEX 3 #define FT_VALIDATE_just_INDEX 4 #define FT_VALIDATE_kern_INDEX 5 #define FT_VALIDATE_opbd_INDEX 6 #define FT_VALIDATE_trak_INDEX 7 #define FT_VALIDATE_prop_INDEX 8 #define FT_VALIDATE_lcar_INDEX 9 #define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX /************************************************************************* * * @macro: * FT_VALIDATE_GX_LENGTH * * @description: * The number of tables checked in this module. Use it as a parameter * for the `table-length' argument of function @FT_TrueTypeGX_Validate. */ #define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1) /* */ /* Up to 0x1000 is used by otvalid. Ox2xxx is reserved for feature OT extension. */ #define FT_VALIDATE_GX_START 0x4000 #define FT_VALIDATE_GX_BITFIELD( tag ) \ ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX ) /********************************************************************** * * @enum: * FT_VALIDATE_GXXXX * * @description: * A list of bit-field constants used with @FT_TrueTypeGX_Validate to * indicate which TrueTypeGX/AAT Type tables should be validated. * * @values: * FT_VALIDATE_feat :: * Validate `feat' table. * * FT_VALIDATE_mort :: * Validate `mort' table. * * FT_VALIDATE_morx :: * Validate `morx' table. * * FT_VALIDATE_bsln :: * Validate `bsln' table. * * FT_VALIDATE_just :: * Validate `just' table. * * FT_VALIDATE_kern :: * Validate `kern' table. * * FT_VALIDATE_opbd :: * Validate `opbd' table. * * FT_VALIDATE_trak :: * Validate `trak' table. * * FT_VALIDATE_prop :: * Validate `prop' table. * * FT_VALIDATE_lcar :: * Validate `lcar' table. * * FT_VALIDATE_GX :: * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern, * opbd, trak, prop and lcar). * */ #define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat ) #define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort ) #define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx ) #define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln ) #define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just ) #define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern ) #define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd ) #define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak ) #define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop ) #define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar ) #define FT_VALIDATE_GX ( FT_VALIDATE_feat | \ FT_VALIDATE_mort | \ FT_VALIDATE_morx | \ FT_VALIDATE_bsln | \ FT_VALIDATE_just | \ FT_VALIDATE_kern | \ FT_VALIDATE_opbd | \ FT_VALIDATE_trak | \ FT_VALIDATE_prop | \ FT_VALIDATE_lcar ) /* */ /********************************************************************** * * @function: * FT_TrueTypeGX_Validate * * @description: * Validate various TrueTypeGX tables to assure that all offsets and * indices are valid. The idea is that a higher-level library which * actually does the text layout can access those tables without * error checking (which can be quite time consuming). * * @input: * face :: * A handle to the input face. * * validation_flags :: * A bit field which specifies the tables to be validated. See * @FT_VALIDATE_GXXXX for possible values. * * table_length :: * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH * should be passed. * * @output: * tables :: * The array where all validated sfnt tables are stored. * The array itself must be allocated by a client. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with TrueTypeGX fonts, returning an error * otherwise. * * After use, the application should deallocate the buffers pointed to by * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value * indicates that the table either doesn't exist in the font, the * application hasn't asked for validation, or the validator doesn't have * the ability to validate the sfnt table. */ FT_EXPORT( FT_Error ) FT_TrueTypeGX_Validate( FT_Face face, FT_UInt validation_flags, FT_Bytes tables[FT_VALIDATE_GX_LENGTH], FT_UInt table_length ); /* */ /********************************************************************** * * @function: * FT_TrueTypeGX_Free * * @description: * Free the buffer allocated by TrueTypeGX validator. * * @input: * face :: * A handle to the input face. * * table :: * The pointer to the buffer allocated by * @FT_TrueTypeGX_Validate. * * @note: * This function must be used to free the buffer allocated by * @FT_TrueTypeGX_Validate only. */ FT_EXPORT( void ) FT_TrueTypeGX_Free( FT_Face face, FT_Bytes table ); /* */ /********************************************************************** * * @enum: * FT_VALIDATE_CKERNXXX * * @description: * A list of bit-field constants used with @FT_ClassicKern_Validate * to indicate the classic kern dialect or dialects. If the selected * type doesn't fit, @FT_ClassicKern_Validate regards the table as * invalid. * * @values: * FT_VALIDATE_MS :: * Handle the `kern' table as a classic Microsoft kern table. * * FT_VALIDATE_APPLE :: * Handle the `kern' table as a classic Apple kern table. * * FT_VALIDATE_CKERN :: * Handle the `kern' as either classic Apple or Microsoft kern table. */ #define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 ) #define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 ) #define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE ) /* */ /********************************************************************** * * @function: * FT_ClassicKern_Validate * * @description: * Validate classic (16-bit format) kern table to assure that the offsets * and indices are valid. The idea is that a higher-level library which * actually does the text layout can access those tables without error * checking (which can be quite time consuming). * * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both * the new 32-bit format and the classic 16-bit format, while * FT_ClassicKern_Validate only supports the classic 16-bit format. * * @input: * face :: * A handle to the input face. * * validation_flags :: * A bit field which specifies the dialect to be validated. See * @FT_VALIDATE_CKERNXXX for possible values. * * @output: * ckern_table :: * A pointer to the kern table. * * @return: * FreeType error code. 0~means success. * * @note: * After use, the application should deallocate the buffers pointed to by * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value * indicates that the table doesn't exist in the font. */ FT_EXPORT( FT_Error ) FT_ClassicKern_Validate( FT_Face face, FT_UInt validation_flags, FT_Bytes *ckern_table ); /* */ /********************************************************************** * * @function: * FT_ClassicKern_Free * * @description: * Free the buffer allocated by classic Kern validator. * * @input: * face :: * A handle to the input face. * * table :: * The pointer to the buffer that is allocated by * @FT_ClassicKern_Validate. * * @note: * This function must be used to free the buffer allocated by * @FT_ClassicKern_Validate only. */ FT_EXPORT( void ) FT_ClassicKern_Free( FT_Face face, FT_Bytes table ); /* */ FT_END_HEADER #endif /* __FTGXVAL_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftgzip.h ================================================ /***************************************************************************/ /* */ /* ftgzip.h */ /* */ /* Gzip-compressed stream support. */ /* */ /* Copyright 2002, 2003, 2004, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTGZIP_H__ #define __FTGZIP_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* gzip */ /* */ /* <Title> */ /* GZIP Streams */ /* */ /* <Abstract> */ /* Using gzip-compressed font files. */ /* */ /* <Description> */ /* This section contains the declaration of Gzip-specific functions. */ /* */ /*************************************************************************/ /************************************************************************ * * @function: * FT_Stream_OpenGzip * * @description: * Open a new stream to parse gzip-compressed font files. This is * mainly used to support the compressed `*.pcf.gz' fonts that come * with XFree86. * * @input: * stream :: * The target embedding stream. * * source :: * The source stream. * * @return: * FreeType error code. 0~means success. * * @note: * The source stream must be opened _before_ calling this function. * * Calling the internal function `FT_Stream_Close' on the new stream will * *not* call `FT_Stream_Close' on the source stream. None of the stream * objects will be released to the heap. * * The stream implementation is very basic and resets the decompression * process each time seeking backwards is needed within the stream. * * In certain builds of the library, gzip compression recognition is * automatically handled when calling @FT_New_Face or @FT_Open_Face. * This means that if no font driver is capable of handling the raw * compressed file, the library will try to open a gzipped stream from * it and re-open the face with it. * * This function may return `FT_Err_Unimplemented_Feature' if your build * of FreeType was not compiled with zlib support. */ FT_EXPORT( FT_Error ) FT_Stream_OpenGzip( FT_Stream stream, FT_Stream source ); /* */ FT_END_HEADER #endif /* __FTGZIP_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftimage.h ================================================ /***************************************************************************/ /* */ /* ftimage.h */ /* */ /* FreeType glyph image formats and default raster interface */ /* (specification). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* Note: A `raster' is simply a scan-line converter, used to render */ /* FT_Outlines into FT_Bitmaps. */ /* */ /*************************************************************************/ #ifndef __FTIMAGE_H__ #define __FTIMAGE_H__ /* _STANDALONE_ is from ftgrays.c */ #ifndef _STANDALONE_ #include <ft2build.h> #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* basic_types */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_Pos */ /* */ /* <Description> */ /* The type FT_Pos is a 32-bit integer used to store vectorial */ /* coordinates. Depending on the context, these can represent */ /* distances in integer font units, or 16.16, or 26.6 fixed float */ /* pixel coordinates. */ /* */ typedef signed long FT_Pos; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Vector */ /* */ /* <Description> */ /* A simple structure used to store a 2D vector; coordinates are of */ /* the FT_Pos type. */ /* */ /* <Fields> */ /* x :: The horizontal coordinate. */ /* y :: The vertical coordinate. */ /* */ typedef struct FT_Vector_ { FT_Pos x; FT_Pos y; } FT_Vector; /*************************************************************************/ /* */ /* <Struct> */ /* FT_BBox */ /* */ /* <Description> */ /* A structure used to hold an outline's bounding box, i.e., the */ /* coordinates of its extrema in the horizontal and vertical */ /* directions. */ /* */ /* <Fields> */ /* xMin :: The horizontal minimum (left-most). */ /* */ /* yMin :: The vertical minimum (bottom-most). */ /* */ /* xMax :: The horizontal maximum (right-most). */ /* */ /* yMax :: The vertical maximum (top-most). */ /* */ typedef struct FT_BBox_ { FT_Pos xMin, yMin; FT_Pos xMax, yMax; } FT_BBox; /*************************************************************************/ /* */ /* <Enum> */ /* FT_Pixel_Mode */ /* */ /* <Description> */ /* An enumeration type used to describe the format of pixels in a */ /* given bitmap. Note that additional formats may be added in the */ /* future. */ /* */ /* <Values> */ /* FT_PIXEL_MODE_NONE :: */ /* Value~0 is reserved. */ /* */ /* FT_PIXEL_MODE_MONO :: */ /* A monochrome bitmap, using 1~bit per pixel. Note that pixels */ /* are stored in most-significant order (MSB), which means that */ /* the left-most pixel in a byte has value 128. */ /* */ /* FT_PIXEL_MODE_GRAY :: */ /* An 8-bit bitmap, generally used to represent anti-aliased glyph */ /* images. Each pixel is stored in one byte. Note that the number */ /* of `gray' levels is stored in the `num_grays' field of the */ /* @FT_Bitmap structure (it generally is 256). */ /* */ /* FT_PIXEL_MODE_GRAY2 :: */ /* A 2-bit per pixel bitmap, used to represent embedded */ /* anti-aliased bitmaps in font files according to the OpenType */ /* specification. We haven't found a single font using this */ /* format, however. */ /* */ /* FT_PIXEL_MODE_GRAY4 :: */ /* A 4-bit per pixel bitmap, representing embedded anti-aliased */ /* bitmaps in font files according to the OpenType specification. */ /* We haven't found a single font using this format, however. */ /* */ /* FT_PIXEL_MODE_LCD :: */ /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ /* used for display on LCD displays; the bitmap is three times */ /* wider than the original glyph image. See also */ /* @FT_RENDER_MODE_LCD. */ /* */ /* FT_PIXEL_MODE_LCD_V :: */ /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ /* used for display on rotated LCD displays; the bitmap is three */ /* times taller than the original glyph image. See also */ /* @FT_RENDER_MODE_LCD_V. */ /* */ typedef enum FT_Pixel_Mode_ { FT_PIXEL_MODE_NONE = 0, FT_PIXEL_MODE_MONO, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_GRAY2, FT_PIXEL_MODE_GRAY4, FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_LCD_V, FT_PIXEL_MODE_MAX /* do not remove */ } FT_Pixel_Mode; /*************************************************************************/ /* */ /* <Enum> */ /* ft_pixel_mode_xxx */ /* */ /* <Description> */ /* A list of deprecated constants. Use the corresponding */ /* @FT_Pixel_Mode values instead. */ /* */ /* <Values> */ /* ft_pixel_mode_none :: See @FT_PIXEL_MODE_NONE. */ /* ft_pixel_mode_mono :: See @FT_PIXEL_MODE_MONO. */ /* ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY. */ /* ft_pixel_mode_pal2 :: See @FT_PIXEL_MODE_GRAY2. */ /* ft_pixel_mode_pal4 :: See @FT_PIXEL_MODE_GRAY4. */ /* */ #define ft_pixel_mode_none FT_PIXEL_MODE_NONE #define ft_pixel_mode_mono FT_PIXEL_MODE_MONO #define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY #define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 #define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 /* */ #if 0 /*************************************************************************/ /* */ /* <Enum> */ /* FT_Palette_Mode */ /* */ /* <Description> */ /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */ /* */ /* An enumeration type to describe the format of a bitmap palette, */ /* used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ /* */ /* <Values> */ /* ft_palette_mode_rgb :: The palette is an array of 3-byte RGB */ /* records. */ /* */ /* ft_palette_mode_rgba :: The palette is an array of 4-byte RGBA */ /* records. */ /* */ /* <Note> */ /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */ /* FreeType, these types are not handled by the library itself. */ /* */ typedef enum FT_Palette_Mode_ { ft_palette_mode_rgb = 0, ft_palette_mode_rgba, ft_palette_mode_max /* do not remove */ } FT_Palette_Mode; /* */ #endif /*************************************************************************/ /* */ /* <Struct> */ /* FT_Bitmap */ /* */ /* <Description> */ /* A structure used to describe a bitmap or pixmap to the raster. */ /* Note that we now manage pixmaps of various depths through the */ /* `pixel_mode' field. */ /* */ /* <Fields> */ /* rows :: The number of bitmap rows. */ /* */ /* width :: The number of pixels in bitmap row. */ /* */ /* pitch :: The pitch's absolute value is the number of bytes */ /* taken by one bitmap row, including padding. */ /* However, the pitch is positive when the bitmap has */ /* a `down' flow, and negative when it has an `up' */ /* flow. In all cases, the pitch is an offset to add */ /* to a bitmap pointer in order to go down one row. */ /* */ /* buffer :: A typeless pointer to the bitmap buffer. This */ /* value should be aligned on 32-bit boundaries in */ /* most cases. */ /* */ /* num_grays :: This field is only used with */ /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */ /* levels used in the bitmap. */ /* */ /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */ /* See @FT_Pixel_Mode for possible values. */ /* */ /* palette_mode :: This field is intended for paletted pixel modes; */ /* it indicates how the palette is stored. Not */ /* used currently. */ /* */ /* palette :: A typeless pointer to the bitmap palette; this */ /* field is intended for paletted pixel modes. Not */ /* used currently. */ /* */ /* <Note> */ /* For now, the only pixel modes supported by FreeType are mono and */ /* grays. However, drivers might be added in the future to support */ /* more `colorful' options. */ /* */ typedef struct FT_Bitmap_ { int rows; int width; int pitch; unsigned char* buffer; short num_grays; char pixel_mode; char palette_mode; void* palette; } FT_Bitmap; /*************************************************************************/ /* */ /* <Section> */ /* outline_processing */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Struct> */ /* FT_Outline */ /* */ /* <Description> */ /* This structure is used to describe an outline to the scan-line */ /* converter. */ /* */ /* <Fields> */ /* n_contours :: The number of contours in the outline. */ /* */ /* n_points :: The number of points in the outline. */ /* */ /* points :: A pointer to an array of `n_points' @FT_Vector */ /* elements, giving the outline's point coordinates. */ /* */ /* tags :: A pointer to an array of `n_points' chars, giving */ /* each outline point's type. */ /* */ /* If bit~0 is unset, the point is `off' the curve, */ /* i.e., a Bézier control point, while it is `on' if */ /* set. */ /* */ /* Bit~1 is meaningful for `off' points only. If set, */ /* it indicates a third-order Bézier arc control point; */ /* and a second-order control point if unset. */ /* */ /* If bit~2 is set, bits 5-7 contain the drop-out mode */ /* (as defined in the OpenType specification; the value */ /* is the same as the argument to the SCANMODE */ /* instruction). */ /* */ /* Bits 3 and~4 are reserved for internal purposes. */ /* */ /* contours :: An array of `n_contours' shorts, giving the end */ /* point of each contour within the outline. For */ /* example, the first contour is defined by the points */ /* `0' to `contours[0]', the second one is defined by */ /* the points `contours[0]+1' to `contours[1]', etc. */ /* */ /* flags :: A set of bit flags used to characterize the outline */ /* and give hints to the scan-converter and hinter on */ /* how to convert/grid-fit it. See @FT_OUTLINE_FLAGS. */ /* */ /* <Note> */ /* The B/W rasterizer only checks bit~2 in the `tags' array for the */ /* first point of each contour. The drop-out mode as given with */ /* @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and */ /* @FT_OUTLINE_INCLUDE_STUBS in `flags' is then overridden. */ /* */ typedef struct FT_Outline_ { short n_contours; /* number of contours in glyph */ short n_points; /* number of points in the glyph */ FT_Vector* points; /* the outline's points */ char* tags; /* the points flags */ short* contours; /* the contour end points */ int flags; /* outline masks */ } FT_Outline; /* Following limits must be consistent with */ /* FT_Outline.{n_contours,n_points} */ #define FT_OUTLINE_CONTOURS_MAX SHRT_MAX #define FT_OUTLINE_POINTS_MAX SHRT_MAX /*************************************************************************/ /* */ /* <Enum> */ /* FT_OUTLINE_FLAGS */ /* */ /* <Description> */ /* A list of bit-field constants use for the flags in an outline's */ /* `flags' field. */ /* */ /* <Values> */ /* FT_OUTLINE_NONE :: */ /* Value~0 is reserved. */ /* */ /* FT_OUTLINE_OWNER :: */ /* If set, this flag indicates that the outline's field arrays */ /* (i.e., `points', `flags', and `contours') are `owned' by the */ /* outline object, and should thus be freed when it is destroyed. */ /* */ /* FT_OUTLINE_EVEN_ODD_FILL :: */ /* By default, outlines are filled using the non-zero winding rule. */ /* If set to 1, the outline will be filled using the even-odd fill */ /* rule (only works with the smooth rasterizer). */ /* */ /* FT_OUTLINE_REVERSE_FILL :: */ /* By default, outside contours of an outline are oriented in */ /* clock-wise direction, as defined in the TrueType specification. */ /* This flag is set if the outline uses the opposite direction */ /* (typically for Type~1 fonts). This flag is ignored by the scan */ /* converter. */ /* */ /* FT_OUTLINE_IGNORE_DROPOUTS :: */ /* By default, the scan converter will try to detect drop-outs in */ /* an outline and correct the glyph bitmap to ensure consistent */ /* shape continuity. If set, this flag hints the scan-line */ /* converter to ignore such cases. See below for more information. */ /* */ /* FT_OUTLINE_SMART_DROPOUTS :: */ /* Select smart dropout control. If unset, use simple dropout */ /* control. Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See */ /* below for more information. */ /* */ /* FT_OUTLINE_INCLUDE_STUBS :: */ /* If set, turn pixels on for `stubs', otherwise exclude them. */ /* Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for */ /* more information. */ /* */ /* FT_OUTLINE_HIGH_PRECISION :: */ /* This flag indicates that the scan-line converter should try to */ /* convert this outline to bitmaps with the highest possible */ /* quality. It is typically set for small character sizes. Note */ /* that this is only a hint that might be completely ignored by a */ /* given scan-converter. */ /* */ /* FT_OUTLINE_SINGLE_PASS :: */ /* This flag is set to force a given scan-converter to only use a */ /* single pass over the outline to render a bitmap glyph image. */ /* Normally, it is set for very large character sizes. It is only */ /* a hint that might be completely ignored by a given */ /* scan-converter. */ /* */ /* <Note> */ /* The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, */ /* and @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth */ /* rasterizer. */ /* */ /* There exists a second mechanism to pass the drop-out mode to the */ /* B/W rasterizer; see the `tags' field in @FT_Outline. */ /* */ /* Please refer to the description of the `SCANTYPE' instruction in */ /* the OpenType specification (in file `ttinst1.doc') how simple */ /* drop-outs, smart drop-outs, and stubs are defined. */ /* */ #define FT_OUTLINE_NONE 0x0 #define FT_OUTLINE_OWNER 0x1 #define FT_OUTLINE_EVEN_ODD_FILL 0x2 #define FT_OUTLINE_REVERSE_FILL 0x4 #define FT_OUTLINE_IGNORE_DROPOUTS 0x8 #define FT_OUTLINE_SMART_DROPOUTS 0x10 #define FT_OUTLINE_INCLUDE_STUBS 0x20 #define FT_OUTLINE_HIGH_PRECISION 0x100 #define FT_OUTLINE_SINGLE_PASS 0x200 /************************************************************************* * * @enum: * ft_outline_flags * * @description: * These constants are deprecated. Please use the corresponding * @FT_OUTLINE_FLAGS values. * * @values: * ft_outline_none :: See @FT_OUTLINE_NONE. * ft_outline_owner :: See @FT_OUTLINE_OWNER. * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL. * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL. * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS. * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION. * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS. */ #define ft_outline_none FT_OUTLINE_NONE #define ft_outline_owner FT_OUTLINE_OWNER #define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL #define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL #define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS #define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION #define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS /* */ #define FT_CURVE_TAG( flag ) ( flag & 3 ) #define FT_CURVE_TAG_ON 1 #define FT_CURVE_TAG_CONIC 0 #define FT_CURVE_TAG_CUBIC 2 #define FT_CURVE_TAG_HAS_SCANMODE 4 #define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */ #define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */ #define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \ FT_CURVE_TAG_TOUCH_Y ) #define FT_Curve_Tag_On FT_CURVE_TAG_ON #define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC #define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC #define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X #define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Outline_MoveToFunc */ /* */ /* <Description> */ /* A function pointer type used to describe the signature of a `move */ /* to' function during outline walking/decomposition. */ /* */ /* A `move to' is emitted to start a new contour in an outline. */ /* */ /* <Input> */ /* to :: A pointer to the target point of the `move to'. */ /* */ /* user :: A typeless pointer which is passed from the caller of the */ /* decomposition function. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ typedef int (*FT_Outline_MoveToFunc)( const FT_Vector* to, void* user ); #define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Outline_LineToFunc */ /* */ /* <Description> */ /* A function pointer type used to describe the signature of a `line */ /* to' function during outline walking/decomposition. */ /* */ /* A `line to' is emitted to indicate a segment in the outline. */ /* */ /* <Input> */ /* to :: A pointer to the target point of the `line to'. */ /* */ /* user :: A typeless pointer which is passed from the caller of the */ /* decomposition function. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ typedef int (*FT_Outline_LineToFunc)( const FT_Vector* to, void* user ); #define FT_Outline_LineTo_Func FT_Outline_LineToFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Outline_ConicToFunc */ /* */ /* <Description> */ /* A function pointer type use to describe the signature of a `conic */ /* to' function during outline walking/decomposition. */ /* */ /* A `conic to' is emitted to indicate a second-order Bézier arc in */ /* the outline. */ /* */ /* <Input> */ /* control :: An intermediate control point between the last position */ /* and the new target in `to'. */ /* */ /* to :: A pointer to the target end point of the conic arc. */ /* */ /* user :: A typeless pointer which is passed from the caller of */ /* the decomposition function. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ typedef int (*FT_Outline_ConicToFunc)( const FT_Vector* control, const FT_Vector* to, void* user ); #define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Outline_CubicToFunc */ /* */ /* <Description> */ /* A function pointer type used to describe the signature of a `cubic */ /* to' function during outline walking/decomposition. */ /* */ /* A `cubic to' is emitted to indicate a third-order Bézier arc. */ /* */ /* <Input> */ /* control1 :: A pointer to the first Bézier control point. */ /* */ /* control2 :: A pointer to the second Bézier control point. */ /* */ /* to :: A pointer to the target end point. */ /* */ /* user :: A typeless pointer which is passed from the caller of */ /* the decomposition function. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ typedef int (*FT_Outline_CubicToFunc)( const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, void* user ); #define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc /*************************************************************************/ /* */ /* <Struct> */ /* FT_Outline_Funcs */ /* */ /* <Description> */ /* A structure to hold various function pointers used during outline */ /* decomposition in order to emit segments, conic, and cubic Béziers, */ /* as well as `move to' and `close to' operations. */ /* */ /* <Fields> */ /* move_to :: The `move to' emitter. */ /* */ /* line_to :: The segment emitter. */ /* */ /* conic_to :: The second-order Bézier arc emitter. */ /* */ /* cubic_to :: The third-order Bézier arc emitter. */ /* */ /* shift :: The shift that is applied to coordinates before they */ /* are sent to the emitter. */ /* */ /* delta :: The delta that is applied to coordinates before they */ /* are sent to the emitter, but after the shift. */ /* */ /* <Note> */ /* The point coordinates sent to the emitters are the transformed */ /* version of the original coordinates (this is important for high */ /* accuracy during scan-conversion). The transformation is simple: */ /* */ /* { */ /* x' = (x << shift) - delta */ /* y' = (x << shift) - delta */ /* } */ /* */ /* Set the value of `shift' and `delta' to~0 to get the original */ /* point coordinates. */ /* */ typedef struct FT_Outline_Funcs_ { FT_Outline_MoveToFunc move_to; FT_Outline_LineToFunc line_to; FT_Outline_ConicToFunc conic_to; FT_Outline_CubicToFunc cubic_to; int shift; FT_Pos delta; } FT_Outline_Funcs; /*************************************************************************/ /* */ /* <Section> */ /* basic_types */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Macro> */ /* FT_IMAGE_TAG */ /* */ /* <Description> */ /* This macro converts four-letter tags to an unsigned long type. */ /* */ /* <Note> */ /* Since many 16-bit compilers don't like 32-bit enumerations, you */ /* should redefine this macro in case of problems to something like */ /* this: */ /* */ /* { */ /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */ /* } */ /* */ /* to get a simple enumeration without assigning special numbers. */ /* */ #ifndef FT_IMAGE_TAG #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ value = ( ( (unsigned long)_x1 << 24 ) | \ ( (unsigned long)_x2 << 16 ) | \ ( (unsigned long)_x3 << 8 ) | \ (unsigned long)_x4 ) #endif /* FT_IMAGE_TAG */ /*************************************************************************/ /* */ /* <Enum> */ /* FT_Glyph_Format */ /* */ /* <Description> */ /* An enumeration type used to describe the format of a given glyph */ /* image. Note that this version of FreeType only supports two image */ /* formats, even though future font drivers will be able to register */ /* their own format. */ /* */ /* <Values> */ /* FT_GLYPH_FORMAT_NONE :: */ /* The value~0 is reserved. */ /* */ /* FT_GLYPH_FORMAT_COMPOSITE :: */ /* The glyph image is a composite of several other images. This */ /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */ /* report compound glyphs (like accented characters). */ /* */ /* FT_GLYPH_FORMAT_BITMAP :: */ /* The glyph image is a bitmap, and can be described as an */ /* @FT_Bitmap. You generally need to access the `bitmap' field of */ /* the @FT_GlyphSlotRec structure to read it. */ /* */ /* FT_GLYPH_FORMAT_OUTLINE :: */ /* The glyph image is a vectorial outline made of line segments */ /* and Bézier arcs; it can be described as an @FT_Outline; you */ /* generally want to access the `outline' field of the */ /* @FT_GlyphSlotRec structure to read it. */ /* */ /* FT_GLYPH_FORMAT_PLOTTER :: */ /* The glyph image is a vectorial path with no inside and outside */ /* contours. Some Type~1 fonts, like those in the Hershey family, */ /* contain glyphs in this format. These are described as */ /* @FT_Outline, but FreeType isn't currently capable of rendering */ /* them correctly. */ /* */ typedef enum FT_Glyph_Format_ { FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) } FT_Glyph_Format; /*************************************************************************/ /* */ /* <Enum> */ /* ft_glyph_format_xxx */ /* */ /* <Description> */ /* A list of deprecated constants. Use the corresponding */ /* @FT_Glyph_Format values instead. */ /* */ /* <Values> */ /* ft_glyph_format_none :: See @FT_GLYPH_FORMAT_NONE. */ /* ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE. */ /* ft_glyph_format_bitmap :: See @FT_GLYPH_FORMAT_BITMAP. */ /* ft_glyph_format_outline :: See @FT_GLYPH_FORMAT_OUTLINE. */ /* ft_glyph_format_plotter :: See @FT_GLYPH_FORMAT_PLOTTER. */ /* */ #define ft_glyph_format_none FT_GLYPH_FORMAT_NONE #define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE #define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP #define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE #define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** R A S T E R D E F I N I T I O N S *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* A raster is a scan converter, in charge of rendering an outline into */ /* a a bitmap. This section contains the public API for rasters. */ /* */ /* Note that in FreeType 2, all rasters are now encapsulated within */ /* specific modules called `renderers'. See `freetype/ftrender.h' for */ /* more details on renderers. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Section> */ /* raster */ /* */ /* <Title> */ /* Scanline Converter */ /* */ /* <Abstract> */ /* How vectorial outlines are converted into bitmaps and pixmaps. */ /* */ /* <Description> */ /* This section contains technical definitions. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_Raster */ /* */ /* <Description> */ /* A handle (pointer) to a raster object. Each object can be used */ /* independently to convert an outline into a bitmap or pixmap. */ /* */ typedef struct FT_RasterRec_* FT_Raster; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Span */ /* */ /* <Description> */ /* A structure used to model a single span of gray (or black) pixels */ /* when rendering a monochrome or anti-aliased bitmap. */ /* */ /* <Fields> */ /* x :: The span's horizontal start position. */ /* */ /* len :: The span's length in pixels. */ /* */ /* coverage :: The span color/coverage, ranging from 0 (background) */ /* to 255 (foreground). Only used for anti-aliased */ /* rendering. */ /* */ /* <Note> */ /* This structure is used by the span drawing callback type named */ /* @FT_SpanFunc which takes the y~coordinate of the span as a */ /* a parameter. */ /* */ /* The coverage value is always between 0 and 255. If you want less */ /* gray values, the callback function has to reduce them. */ /* */ typedef struct FT_Span_ { short x; unsigned short len; unsigned char coverage; } FT_Span; /*************************************************************************/ /* */ /* <FuncType> */ /* FT_SpanFunc */ /* */ /* <Description> */ /* A function used as a call-back by the anti-aliased renderer in */ /* order to let client applications draw themselves the gray pixel */ /* spans on each scan line. */ /* */ /* <Input> */ /* y :: The scanline's y~coordinate. */ /* */ /* count :: The number of spans to draw on this scanline. */ /* */ /* spans :: A table of `count' spans to draw on the scanline. */ /* */ /* user :: User-supplied data that is passed to the callback. */ /* */ /* <Note> */ /* This callback allows client applications to directly render the */ /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ /* */ /* This can be used to write anti-aliased outlines directly to a */ /* given background bitmap, and even perform translucency. */ /* */ /* Note that the `count' field cannot be greater than a fixed value */ /* defined by the `FT_MAX_GRAY_SPANS' configuration macro in */ /* `ftoption.h'. By default, this value is set to~32, which means */ /* that if there are more than 32~spans on a given scanline, the */ /* callback is called several times with the same `y' parameter in */ /* order to draw all callbacks. */ /* */ /* Otherwise, the callback is only called once per scan-line, and */ /* only for those scanlines that do have `gray' pixels on them. */ /* */ typedef void (*FT_SpanFunc)( int y, int count, const FT_Span* spans, void* user ); #define FT_Raster_Span_Func FT_SpanFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_BitTest_Func */ /* */ /* <Description> */ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ /* */ /* A function used as a call-back by the monochrome scan-converter */ /* to test whether a given target pixel is already set to the drawing */ /* `color'. These tests are crucial to implement drop-out control */ /* per-se the TrueType spec. */ /* */ /* <Input> */ /* y :: The pixel's y~coordinate. */ /* */ /* x :: The pixel's x~coordinate. */ /* */ /* user :: User-supplied data that is passed to the callback. */ /* */ /* <Return> */ /* 1~if the pixel is `set', 0~otherwise. */ /* */ typedef int (*FT_Raster_BitTest_Func)( int y, int x, void* user ); /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_BitSet_Func */ /* */ /* <Description> */ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ /* */ /* A function used as a call-back by the monochrome scan-converter */ /* to set an individual target pixel. This is crucial to implement */ /* drop-out control according to the TrueType specification. */ /* */ /* <Input> */ /* y :: The pixel's y~coordinate. */ /* */ /* x :: The pixel's x~coordinate. */ /* */ /* user :: User-supplied data that is passed to the callback. */ /* */ /* <Return> */ /* 1~if the pixel is `set', 0~otherwise. */ /* */ typedef void (*FT_Raster_BitSet_Func)( int y, int x, void* user ); /*************************************************************************/ /* */ /* <Enum> */ /* FT_RASTER_FLAG_XXX */ /* */ /* <Description> */ /* A list of bit flag constants as used in the `flags' field of a */ /* @FT_Raster_Params structure. */ /* */ /* <Values> */ /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */ /* */ /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */ /* anti-aliased glyph image should be */ /* generated. Otherwise, it will be */ /* monochrome (1-bit). */ /* */ /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */ /* rendering. In this mode, client */ /* applications must provide their own span */ /* callback. This lets them directly */ /* draw or compose over an existing bitmap. */ /* If this bit is not set, the target */ /* pixmap's buffer _must_ be zeroed before */ /* rendering. */ /* */ /* Note that for now, direct rendering is */ /* only possible with anti-aliased glyphs. */ /* */ /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */ /* rendering mode. If set, the output will */ /* be clipped to a box specified in the */ /* `clip_box' field of the */ /* @FT_Raster_Params structure. */ /* */ /* Note that by default, the glyph bitmap */ /* is clipped to the target pixmap, except */ /* in direct rendering mode where all spans */ /* are generated if no clipping box is set. */ /* */ #define FT_RASTER_FLAG_DEFAULT 0x0 #define FT_RASTER_FLAG_AA 0x1 #define FT_RASTER_FLAG_DIRECT 0x2 #define FT_RASTER_FLAG_CLIP 0x4 /* deprecated */ #define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT #define ft_raster_flag_aa FT_RASTER_FLAG_AA #define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT #define ft_raster_flag_clip FT_RASTER_FLAG_CLIP /*************************************************************************/ /* */ /* <Struct> */ /* FT_Raster_Params */ /* */ /* <Description> */ /* A structure to hold the arguments used by a raster's render */ /* function. */ /* */ /* <Fields> */ /* target :: The target bitmap. */ /* */ /* source :: A pointer to the source glyph image (e.g., an */ /* @FT_Outline). */ /* */ /* flags :: The rendering flags. */ /* */ /* gray_spans :: The gray span drawing callback. */ /* */ /* black_spans :: The black span drawing callback. UNIMPLEMENTED! */ /* */ /* bit_test :: The bit test callback. UNIMPLEMENTED! */ /* */ /* bit_set :: The bit set callback. UNIMPLEMENTED! */ /* */ /* user :: User-supplied data that is passed to each drawing */ /* callback. */ /* */ /* clip_box :: An optional clipping box. It is only used in */ /* direct rendering mode. Note that coordinates here */ /* should be expressed in _integer_ pixels (and not in */ /* 26.6 fixed-point units). */ /* */ /* <Note> */ /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */ /* bit flag is set in the `flags' field, otherwise a monochrome */ /* bitmap is generated. */ /* */ /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */ /* raster will call the `gray_spans' callback to draw gray pixel */ /* spans, in the case of an aa glyph bitmap, it will call */ /* `black_spans', and `bit_test' and `bit_set' in the case of a */ /* monochrome bitmap. This allows direct composition over a */ /* pre-existing bitmap through user-provided callbacks to perform the */ /* span drawing/composition. */ /* */ /* Note that the `bit_test' and `bit_set' callbacks are required when */ /* rendering a monochrome bitmap, as they are crucial to implement */ /* correct drop-out control as defined in the TrueType specification. */ /* */ typedef struct FT_Raster_Params_ { const FT_Bitmap* target; const void* source; int flags; FT_SpanFunc gray_spans; FT_SpanFunc black_spans; /* doesn't work! */ FT_Raster_BitTest_Func bit_test; /* doesn't work! */ FT_Raster_BitSet_Func bit_set; /* doesn't work! */ void* user; FT_BBox clip_box; } FT_Raster_Params; /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_NewFunc */ /* */ /* <Description> */ /* A function used to create a new raster object. */ /* */ /* <Input> */ /* memory :: A handle to the memory allocator. */ /* */ /* <Output> */ /* raster :: A handle to the new raster object. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ /* <Note> */ /* The `memory' parameter is a typeless pointer in order to avoid */ /* un-wanted dependencies on the rest of the FreeType code. In */ /* practice, it is an @FT_Memory object, i.e., a handle to the */ /* standard FreeType memory allocator. However, this field can be */ /* completely ignored by a given raster implementation. */ /* */ typedef int (*FT_Raster_NewFunc)( void* memory, FT_Raster* raster ); #define FT_Raster_New_Func FT_Raster_NewFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_DoneFunc */ /* */ /* <Description> */ /* A function used to destroy a given raster object. */ /* */ /* <Input> */ /* raster :: A handle to the raster object. */ /* */ typedef void (*FT_Raster_DoneFunc)( FT_Raster raster ); #define FT_Raster_Done_Func FT_Raster_DoneFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_ResetFunc */ /* */ /* <Description> */ /* FreeType provides an area of memory called the `render pool', */ /* available to all registered rasters. This pool can be freely used */ /* during a given scan-conversion but is shared by all rasters. Its */ /* content is thus transient. */ /* */ /* This function is called each time the render pool changes, or just */ /* after a new raster object is created. */ /* */ /* <Input> */ /* raster :: A handle to the new raster object. */ /* */ /* pool_base :: The address in memory of the render pool. */ /* */ /* pool_size :: The size in bytes of the render pool. */ /* */ /* <Note> */ /* Rasters can ignore the render pool and rely on dynamic memory */ /* allocation if they want to (a handle to the memory allocator is */ /* passed to the raster constructor). However, this is not */ /* recommended for efficiency purposes. */ /* */ typedef void (*FT_Raster_ResetFunc)( FT_Raster raster, unsigned char* pool_base, unsigned long pool_size ); #define FT_Raster_Reset_Func FT_Raster_ResetFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_SetModeFunc */ /* */ /* <Description> */ /* This function is a generic facility to change modes or attributes */ /* in a given raster. This can be used for debugging purposes, or */ /* simply to allow implementation-specific `features' in a given */ /* raster module. */ /* */ /* <Input> */ /* raster :: A handle to the new raster object. */ /* */ /* mode :: A 4-byte tag used to name the mode or property. */ /* */ /* args :: A pointer to the new mode/property to use. */ /* */ typedef int (*FT_Raster_SetModeFunc)( FT_Raster raster, unsigned long mode, void* args ); #define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Raster_RenderFunc */ /* */ /* <Description> */ /* Invoke a given raster to scan-convert a given glyph image into a */ /* target bitmap. */ /* */ /* <Input> */ /* raster :: A handle to the raster object. */ /* */ /* params :: A pointer to an @FT_Raster_Params structure used to */ /* store the rendering parameters. */ /* */ /* <Return> */ /* Error code. 0~means success. */ /* */ /* <Note> */ /* The exact format of the source image depends on the raster's glyph */ /* format defined in its @FT_Raster_Funcs structure. It can be an */ /* @FT_Outline or anything else in order to support a large array of */ /* glyph formats. */ /* */ /* Note also that the render function can fail and return a */ /* `FT_Err_Unimplemented_Feature' error code if the raster used does */ /* not support direct composition. */ /* */ /* XXX: For now, the standard raster doesn't support direct */ /* composition but this should change for the final release (see */ /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */ /* for examples of distinct implementations which support direct */ /* composition). */ /* */ typedef int (*FT_Raster_RenderFunc)( FT_Raster raster, const FT_Raster_Params* params ); #define FT_Raster_Render_Func FT_Raster_RenderFunc /*************************************************************************/ /* */ /* <Struct> */ /* FT_Raster_Funcs */ /* */ /* <Description> */ /* A structure used to describe a given raster class to the library. */ /* */ /* <Fields> */ /* glyph_format :: The supported glyph format for this raster. */ /* */ /* raster_new :: The raster constructor. */ /* */ /* raster_reset :: Used to reset the render pool within the raster. */ /* */ /* raster_render :: A function to render a glyph into a given bitmap. */ /* */ /* raster_done :: The raster destructor. */ /* */ typedef struct FT_Raster_Funcs_ { FT_Glyph_Format glyph_format; FT_Raster_NewFunc raster_new; FT_Raster_ResetFunc raster_reset; FT_Raster_SetModeFunc raster_set_mode; FT_Raster_RenderFunc raster_render; FT_Raster_DoneFunc raster_done; } FT_Raster_Funcs; /* */ FT_END_HEADER #endif /* __FTIMAGE_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftincrem.h ================================================ /***************************************************************************/ /* */ /* ftincrem.h */ /* */ /* FreeType incremental loading (specification). */ /* */ /* Copyright 2002, 2003, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTINCREM_H__ #define __FTINCREM_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************** * * @section: * incremental * * @title: * Incremental Loading * * @abstract: * Custom Glyph Loading. * * @description: * This section contains various functions used to perform so-called * `incremental' glyph loading. This is a mode where all glyphs loaded * from a given @FT_Face are provided by the client application, * * Apart from that, all other tables are loaded normally from the font * file. This mode is useful when FreeType is used within another * engine, e.g., a PostScript Imaging Processor. * * To enable this mode, you must use @FT_Open_Face, passing an * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an * @FT_Incremental_Interface value. See the comments for * @FT_Incremental_InterfaceRec for an example. * */ /*************************************************************************** * * @type: * FT_Incremental * * @description: * An opaque type describing a user-provided object used to implement * `incremental' glyph loading within FreeType. This is used to support * embedded fonts in certain environments (e.g., PostScript interpreters), * where the glyph data isn't in the font file, or must be overridden by * different values. * * @note: * It is up to client applications to create and implement @FT_Incremental * objects, as long as they provide implementations for the methods * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc * and @FT_Incremental_GetGlyphMetricsFunc. * * See the description of @FT_Incremental_InterfaceRec to understand how * to use incremental objects with FreeType. * */ typedef struct FT_IncrementalRec_* FT_Incremental; /*************************************************************************** * * @struct: * FT_Incremental_MetricsRec * * @description: * A small structure used to contain the basic glyph metrics returned * by the @FT_Incremental_GetGlyphMetricsFunc method. * * @fields: * bearing_x :: * Left bearing, in font units. * * bearing_y :: * Top bearing, in font units. * * advance :: * Glyph advance, in font units. * * @note: * These correspond to horizontal or vertical metrics depending on the * value of the `vertical' argument to the function * @FT_Incremental_GetGlyphMetricsFunc. * */ typedef struct FT_Incremental_MetricsRec_ { FT_Long bearing_x; FT_Long bearing_y; FT_Long advance; } FT_Incremental_MetricsRec; /*************************************************************************** * * @struct: * FT_Incremental_Metrics * * @description: * A handle to an @FT_Incremental_MetricsRec structure. * */ typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics; /*************************************************************************** * * @type: * FT_Incremental_GetGlyphDataFunc * * @description: * A function called by FreeType to access a given glyph's data bytes * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is * enabled. * * Note that the format of the glyph's data bytes depends on the font * file format. For TrueType, it must correspond to the raw bytes within * the `glyf' table. For PostScript formats, it must correspond to the * *unencrypted* charstring bytes, without any `lenIV' header. It is * undefined for any other format. * * @input: * incremental :: * Handle to an opaque @FT_Incremental handle provided by the client * application. * * glyph_index :: * Index of relevant glyph. * * @output: * adata :: * A structure describing the returned glyph data bytes (which will be * accessed as a read-only byte block). * * @return: * FreeType error code. 0~means success. * * @note: * If this function returns successfully the method * @FT_Incremental_FreeGlyphDataFunc will be called later to release * the data bytes. * * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for * compound glyphs. * */ typedef FT_Error (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental, FT_UInt glyph_index, FT_Data* adata ); /*************************************************************************** * * @type: * FT_Incremental_FreeGlyphDataFunc * * @description: * A function used to release the glyph data bytes returned by a * successful call to @FT_Incremental_GetGlyphDataFunc. * * @input: * incremental :: * A handle to an opaque @FT_Incremental handle provided by the client * application. * * data :: * A structure describing the glyph data bytes (which will be accessed * as a read-only byte block). * */ typedef void (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental, FT_Data* data ); /*************************************************************************** * * @type: * FT_Incremental_GetGlyphMetricsFunc * * @description: * A function used to retrieve the basic metrics of a given glyph index * before accessing its data. This is necessary because, in certain * formats like TrueType, the metrics are stored in a different place from * the glyph images proper. * * @input: * incremental :: * A handle to an opaque @FT_Incremental handle provided by the client * application. * * glyph_index :: * Index of relevant glyph. * * vertical :: * If true, return vertical metrics. * * ametrics :: * This parameter is used for both input and output. * The original glyph metrics, if any, in font units. If metrics are * not available all the values must be set to zero. * * @output: * ametrics :: * The replacement glyph metrics in font units. * */ typedef FT_Error (*FT_Incremental_GetGlyphMetricsFunc) ( FT_Incremental incremental, FT_UInt glyph_index, FT_Bool vertical, FT_Incremental_MetricsRec *ametrics ); /************************************************************************** * * @struct: * FT_Incremental_FuncsRec * * @description: * A table of functions for accessing fonts that load data * incrementally. Used in @FT_Incremental_InterfaceRec. * * @fields: * get_glyph_data :: * The function to get glyph data. Must not be null. * * free_glyph_data :: * The function to release glyph data. Must not be null. * * get_glyph_metrics :: * The function to get glyph metrics. May be null if the font does * not provide overriding glyph metrics. * */ typedef struct FT_Incremental_FuncsRec_ { FT_Incremental_GetGlyphDataFunc get_glyph_data; FT_Incremental_FreeGlyphDataFunc free_glyph_data; FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; } FT_Incremental_FuncsRec; /*************************************************************************** * * @struct: * FT_Incremental_InterfaceRec * * @description: * A structure to be used with @FT_Open_Face to indicate that the user * wants to support incremental glyph loading. You should use it with * @FT_PARAM_TAG_INCREMENTAL as in the following example: * * { * FT_Incremental_InterfaceRec inc_int; * FT_Parameter parameter; * FT_Open_Args open_args; * * * // set up incremental descriptor * inc_int.funcs = my_funcs; * inc_int.object = my_object; * * // set up optional parameter * parameter.tag = FT_PARAM_TAG_INCREMENTAL; * parameter.data = &inc_int; * * // set up FT_Open_Args structure * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; * open_args.pathname = my_font_pathname; * open_args.num_params = 1; * open_args.params = ¶meter; // we use one optional argument * * // open the font * error = FT_Open_Face( library, &open_args, index, &face ); * ... * } * */ typedef struct FT_Incremental_InterfaceRec_ { const FT_Incremental_FuncsRec* funcs; FT_Incremental object; } FT_Incremental_InterfaceRec; /*************************************************************************** * * @type: * FT_Incremental_Interface * * @description: * A pointer to an @FT_Incremental_InterfaceRec structure. * */ typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface; /*************************************************************************** * * @constant: * FT_PARAM_TAG_INCREMENTAL * * @description: * A constant used as the tag of @FT_Parameter structures to indicate * an incremental loading object to be used by FreeType. * */ #define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' ) /* */ FT_END_HEADER #endif /* __FTINCREM_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftlcdfil.h ================================================ /***************************************************************************/ /* */ /* ftlcdfil.h */ /* */ /* FreeType API for color filtering of subpixel bitmap glyphs */ /* (specification). */ /* */ /* Copyright 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FT_LCD_FILTER_H__ #define __FT_LCD_FILTER_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************** * * @section: * lcd_filtering * * @title: * LCD Filtering * * @abstract: * Reduce color fringes of LCD-optimized bitmaps. * * @description: * The @FT_Library_SetLcdFilter API can be used to specify a low-pass * filter which is then applied to LCD-optimized bitmaps generated * through @FT_Render_Glyph. This is useful to reduce color fringes * which would occur with unfiltered rendering. * * Note that no filter is active by default, and that this function is * *not* implemented in default builds of the library. You need to * #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file * in order to activate it. */ /**************************************************************************** * * @func: * FT_LcdFilter * * @description: * A list of values to identify various types of LCD filters. * * @values: * FT_LCD_FILTER_NONE :: * Do not perform filtering. When used with subpixel rendering, this * results in sometimes severe color fringes. * * FT_LCD_FILTER_DEFAULT :: * The default filter reduces color fringes considerably, at the cost * of a slight blurriness in the output. * * FT_LCD_FILTER_LIGHT :: * The light filter is a variant that produces less blurriness at the * cost of slightly more color fringes than the default one. It might * be better, depending on taste, your monitor, or your personal vision. * * FT_LCD_FILTER_LEGACY :: * This filter corresponds to the original libXft color filter. It * provides high contrast output but can exhibit really bad color * fringes if glyphs are not extremely well hinted to the pixel grid. * In other words, it only works well if the TrueType bytecode * interpreter is enabled *and* high-quality hinted fonts are used. * * This filter is only provided for comparison purposes, and might be * disabled or stay unsupported in the future. * * @since: * 2.3.0 */ typedef enum FT_LcdFilter_ { FT_LCD_FILTER_NONE = 0, FT_LCD_FILTER_DEFAULT = 1, FT_LCD_FILTER_LIGHT = 2, FT_LCD_FILTER_LEGACY = 16, FT_LCD_FILTER_MAX /* do not remove */ } FT_LcdFilter; /************************************************************************** * * @func: * FT_Library_SetLcdFilter * * @description: * This function is used to apply color filtering to LCD decimated * bitmaps, like the ones used when calling @FT_Render_Glyph with * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V. * * @input: * library :: * A handle to the target library instance. * * filter :: * The filter type. * * You can use @FT_LCD_FILTER_NONE here to disable this feature, or * @FT_LCD_FILTER_DEFAULT to use a default filter that should work * well on most LCD screens. * * @return: * FreeType error code. 0~means success. * * @note: * This feature is always disabled by default. Clients must make an * explicit call to this function with a `filter' value other than * @FT_LCD_FILTER_NONE in order to enable it. * * Due to *PATENTS* covering subpixel rendering, this function doesn't * do anything except returning `FT_Err_Unimplemented_Feature' if the * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not * defined in your build of the library, which should correspond to all * default builds of FreeType. * * The filter affects glyph bitmaps rendered through @FT_Render_Glyph, * @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char. * * It does _not_ affect the output of @FT_Outline_Render and * @FT_Outline_Get_Bitmap. * * If this feature is activated, the dimensions of LCD glyph bitmaps are * either larger or taller than the dimensions of the corresponding * outline with regards to the pixel grid. For example, for * @FT_RENDER_MODE_LCD, the filter adds up to 3~pixels to the left, and * up to 3~pixels to the right. * * The bitmap offset values are adjusted correctly, so clients shouldn't * need to modify their layout and glyph positioning code when enabling * the filter. * * @since: * 2.3.0 */ FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ); /* */ FT_END_HEADER #endif /* __FT_LCD_FILTER_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftlist.h ================================================ /***************************************************************************/ /* */ /* ftlist.h */ /* */ /* Generic list support for FreeType (specification). */ /* */ /* Copyright 1996-2001, 2003, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This file implements functions relative to list processing. Its */ /* data structures are defined in `freetype.h'. */ /* */ /*************************************************************************/ #ifndef __FTLIST_H__ #define __FTLIST_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* list_processing */ /* */ /* <Title> */ /* List Processing */ /* */ /* <Abstract> */ /* Simple management of lists. */ /* */ /* <Description> */ /* This section contains various definitions related to list */ /* processing using doubly-linked nodes. */ /* */ /* <Order> */ /* FT_List */ /* FT_ListNode */ /* FT_ListRec */ /* FT_ListNodeRec */ /* */ /* FT_List_Add */ /* FT_List_Insert */ /* FT_List_Find */ /* FT_List_Remove */ /* FT_List_Up */ /* FT_List_Iterate */ /* FT_List_Iterator */ /* FT_List_Finalize */ /* FT_List_Destructor */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Find */ /* */ /* <Description> */ /* Find the list node for a given listed object. */ /* */ /* <Input> */ /* list :: A pointer to the parent list. */ /* data :: The address of the listed object. */ /* */ /* <Return> */ /* List node. NULL if it wasn't found. */ /* */ FT_EXPORT( FT_ListNode ) FT_List_Find( FT_List list, void* data ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Add */ /* */ /* <Description> */ /* Append an element to the end of a list. */ /* */ /* <InOut> */ /* list :: A pointer to the parent list. */ /* node :: The node to append. */ /* */ FT_EXPORT( void ) FT_List_Add( FT_List list, FT_ListNode node ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Insert */ /* */ /* <Description> */ /* Insert an element at the head of a list. */ /* */ /* <InOut> */ /* list :: A pointer to parent list. */ /* node :: The node to insert. */ /* */ FT_EXPORT( void ) FT_List_Insert( FT_List list, FT_ListNode node ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Remove */ /* */ /* <Description> */ /* Remove a node from a list. This function doesn't check whether */ /* the node is in the list! */ /* */ /* <Input> */ /* node :: The node to remove. */ /* */ /* <InOut> */ /* list :: A pointer to the parent list. */ /* */ FT_EXPORT( void ) FT_List_Remove( FT_List list, FT_ListNode node ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Up */ /* */ /* <Description> */ /* Move a node to the head/top of a list. Used to maintain LRU */ /* lists. */ /* */ /* <InOut> */ /* list :: A pointer to the parent list. */ /* node :: The node to move. */ /* */ FT_EXPORT( void ) FT_List_Up( FT_List list, FT_ListNode node ); /*************************************************************************/ /* */ /* <FuncType> */ /* FT_List_Iterator */ /* */ /* <Description> */ /* An FT_List iterator function which is called during a list parse */ /* by @FT_List_Iterate. */ /* */ /* <Input> */ /* node :: The current iteration list node. */ /* */ /* user :: A typeless pointer passed to @FT_List_Iterate. */ /* Can be used to point to the iteration's state. */ /* */ typedef FT_Error (*FT_List_Iterator)( FT_ListNode node, void* user ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Iterate */ /* */ /* <Description> */ /* Parse a list and calls a given iterator function on each element. */ /* Note that parsing is stopped as soon as one of the iterator calls */ /* returns a non-zero value. */ /* */ /* <Input> */ /* list :: A handle to the list. */ /* iterator :: An iterator function, called on each node of the list. */ /* user :: A user-supplied field which is passed as the second */ /* argument to the iterator. */ /* */ /* <Return> */ /* The result (a FreeType error code) of the last iterator call. */ /* */ FT_EXPORT( FT_Error ) FT_List_Iterate( FT_List list, FT_List_Iterator iterator, void* user ); /*************************************************************************/ /* */ /* <FuncType> */ /* FT_List_Destructor */ /* */ /* <Description> */ /* An @FT_List iterator function which is called during a list */ /* finalization by @FT_List_Finalize to destroy all elements in a */ /* given list. */ /* */ /* <Input> */ /* system :: The current system object. */ /* */ /* data :: The current object to destroy. */ /* */ /* user :: A typeless pointer passed to @FT_List_Iterate. It can */ /* be used to point to the iteration's state. */ /* */ typedef void (*FT_List_Destructor)( FT_Memory memory, void* data, void* user ); /*************************************************************************/ /* */ /* <Function> */ /* FT_List_Finalize */ /* */ /* <Description> */ /* Destroy all elements in the list as well as the list itself. */ /* */ /* <Input> */ /* list :: A handle to the list. */ /* */ /* destroy :: A list destructor that will be applied to each element */ /* of the list. */ /* */ /* memory :: The current memory object which handles deallocation. */ /* */ /* user :: A user-supplied field which is passed as the last */ /* argument to the destructor. */ /* */ FT_EXPORT( void ) FT_List_Finalize( FT_List list, FT_List_Destructor destroy, FT_Memory memory, void* user ); /* */ FT_END_HEADER #endif /* __FTLIST_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftlzw.h ================================================ /***************************************************************************/ /* */ /* ftlzw.h */ /* */ /* LZW-compressed stream support. */ /* */ /* Copyright 2004, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTLZW_H__ #define __FTLZW_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* lzw */ /* */ /* <Title> */ /* LZW Streams */ /* */ /* <Abstract> */ /* Using LZW-compressed font files. */ /* */ /* <Description> */ /* This section contains the declaration of LZW-specific functions. */ /* */ /*************************************************************************/ /************************************************************************ * * @function: * FT_Stream_OpenLZW * * @description: * Open a new stream to parse LZW-compressed font files. This is * mainly used to support the compressed `*.pcf.Z' fonts that come * with XFree86. * * @input: * stream :: The target embedding stream. * * source :: The source stream. * * @return: * FreeType error code. 0~means success. * * @note: * The source stream must be opened _before_ calling this function. * * Calling the internal function `FT_Stream_Close' on the new stream will * *not* call `FT_Stream_Close' on the source stream. None of the stream * objects will be released to the heap. * * The stream implementation is very basic and resets the decompression * process each time seeking backwards is needed within the stream * * In certain builds of the library, LZW compression recognition is * automatically handled when calling @FT_New_Face or @FT_Open_Face. * This means that if no font driver is capable of handling the raw * compressed file, the library will try to open a LZW stream from it * and re-open the face with it. * * This function may return `FT_Err_Unimplemented_Feature' if your build * of FreeType was not compiled with LZW support. */ FT_EXPORT( FT_Error ) FT_Stream_OpenLZW( FT_Stream stream, FT_Stream source ); /* */ FT_END_HEADER #endif /* __FTLZW_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftmac.h ================================================ /***************************************************************************/ /* */ /* ftmac.h */ /* */ /* Additional Mac-specific API. */ /* */ /* Copyright 1996-2001, 2004, 2006, 2007 by */ /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* NOTE: Include this file after <freetype/freetype.h> and after any */ /* Mac-specific headers (because this header uses Mac types such as */ /* Handle, FSSpec, FSRef, etc.) */ /* */ /***************************************************************************/ #ifndef __FTMAC_H__ #define __FTMAC_H__ #include <ft2build.h> FT_BEGIN_HEADER /* gcc-3.4.1 and later can warn about functions tagged as deprecated */ #ifndef FT_DEPRECATED_ATTRIBUTE #if defined(__GNUC__) && \ ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) #define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) #else #define FT_DEPRECATED_ATTRIBUTE #endif #endif /*************************************************************************/ /* */ /* <Section> */ /* mac_specific */ /* */ /* <Title> */ /* Mac Specific Interface */ /* */ /* <Abstract> */ /* Only available on the Macintosh. */ /* */ /* <Description> */ /* The following definitions are only available if FreeType is */ /* compiled on a Macintosh. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Face_From_FOND */ /* */ /* <Description> */ /* Create a new face object from a FOND resource. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* fond :: A FOND resource. */ /* */ /* face_index :: Only supported for the -1 `sanity check' special */ /* case. */ /* */ /* <Output> */ /* aface :: A handle to a new face object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Notes> */ /* This function can be used to create @FT_Face objects from fonts */ /* that are installed in the system as follows. */ /* */ /* { */ /* fond = GetResource( 'FOND', fontName ); */ /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */ /* } */ /* */ FT_EXPORT( FT_Error ) FT_New_Face_From_FOND( FT_Library library, Handle fond, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; /*************************************************************************/ /* */ /* <Function> */ /* FT_GetFile_From_Mac_Name */ /* */ /* <Description> */ /* Return an FSSpec for the disk file containing the named font. */ /* */ /* <Input> */ /* fontName :: Mac OS name of the font (e.g., Times New Roman */ /* Bold). */ /* */ /* <Output> */ /* pathSpec :: FSSpec to the file. For passing to */ /* @FT_New_Face_From_FSSpec. */ /* */ /* face_index :: Index of the face. For passing to */ /* @FT_New_Face_From_FSSpec. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) FT_DEPRECATED_ATTRIBUTE; /*************************************************************************/ /* */ /* <Function> */ /* FT_GetFile_From_Mac_ATS_Name */ /* */ /* <Description> */ /* Return an FSSpec for the disk file containing the named font. */ /* */ /* <Input> */ /* fontName :: Mac OS name of the font in ATS framework. */ /* */ /* <Output> */ /* pathSpec :: FSSpec to the file. For passing to */ /* @FT_New_Face_From_FSSpec. */ /* */ /* face_index :: Index of the face. For passing to */ /* @FT_New_Face_From_FSSpec. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_ATS_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) FT_DEPRECATED_ATTRIBUTE; /*************************************************************************/ /* */ /* <Function> */ /* FT_GetFilePath_From_Mac_ATS_Name */ /* */ /* <Description> */ /* Return a pathname of the disk file and face index for given font */ /* name which is handled by ATS framework. */ /* */ /* <Input> */ /* fontName :: Mac OS name of the font in ATS framework. */ /* */ /* <Output> */ /* path :: Buffer to store pathname of the file. For passing */ /* to @FT_New_Face. The client must allocate this */ /* buffer before calling this function. */ /* */ /* maxPathSize :: Lengths of the buffer `path' that client allocated. */ /* */ /* face_index :: Index of the face. For passing to @FT_New_Face. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_GetFilePath_From_Mac_ATS_Name( const char* fontName, UInt8* path, UInt32 maxPathSize, FT_Long* face_index ) FT_DEPRECATED_ATTRIBUTE; /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Face_From_FSSpec */ /* */ /* <Description> */ /* Create a new face object from a given resource and typeface index */ /* using an FSSpec to the font file. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* spec :: FSSpec to the font file. */ /* */ /* face_index :: The index of the face within the resource. The */ /* first face has index~0. */ /* <Output> */ /* aface :: A handle to a new face object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */ /* it accepts an FSSpec instead of a path. */ /* */ FT_EXPORT( FT_Error ) FT_New_Face_From_FSSpec( FT_Library library, const FSSpec *spec, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Face_From_FSRef */ /* */ /* <Description> */ /* Create a new face object from a given resource and typeface index */ /* using an FSRef to the font file. */ /* */ /* <InOut> */ /* library :: A handle to the library resource. */ /* */ /* <Input> */ /* spec :: FSRef to the font file. */ /* */ /* face_index :: The index of the face within the resource. The */ /* first face has index~0. */ /* <Output> */ /* aface :: A handle to a new face object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */ /* it accepts an FSRef instead of a path. */ /* */ FT_EXPORT( FT_Error ) FT_New_Face_From_FSRef( FT_Library library, const FSRef *ref, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; /* */ FT_END_HEADER #endif /* __FTMAC_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftmm.h ================================================ /***************************************************************************/ /* */ /* ftmm.h */ /* */ /* FreeType Multiple Master font interface (specification). */ /* */ /* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTMM_H__ #define __FTMM_H__ #include <ft2build.h> #include FT_TYPE1_TABLES_H FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* multiple_masters */ /* */ /* <Title> */ /* Multiple Masters */ /* */ /* <Abstract> */ /* How to manage Multiple Masters fonts. */ /* */ /* <Description> */ /* The following types and functions are used to manage Multiple */ /* Master fonts, i.e., the selection of specific design instances by */ /* setting design axis coordinates. */ /* */ /* George Williams has extended this interface to make it work with */ /* both Type~1 Multiple Masters fonts and GX distortable (var) */ /* fonts. Some of these routines only work with MM fonts, others */ /* will work with both types. They are similar enough that a */ /* consistent interface makes sense. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Struct> */ /* FT_MM_Axis */ /* */ /* <Description> */ /* A simple structure used to model a given axis in design space for */ /* Multiple Masters fonts. */ /* */ /* This structure can't be used for GX var fonts. */ /* */ /* <Fields> */ /* name :: The axis's name. */ /* */ /* minimum :: The axis's minimum design coordinate. */ /* */ /* maximum :: The axis's maximum design coordinate. */ /* */ typedef struct FT_MM_Axis_ { FT_String* name; FT_Long minimum; FT_Long maximum; } FT_MM_Axis; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Multi_Master */ /* */ /* <Description> */ /* A structure used to model the axes and space of a Multiple Masters */ /* font. */ /* */ /* This structure can't be used for GX var fonts. */ /* */ /* <Fields> */ /* num_axis :: Number of axes. Cannot exceed~4. */ /* */ /* num_designs :: Number of designs; should be normally 2^num_axis */ /* even though the Type~1 specification strangely */ /* allows for intermediate designs to be present. This */ /* number cannot exceed~16. */ /* */ /* axis :: A table of axis descriptors. */ /* */ typedef struct FT_Multi_Master_ { FT_UInt num_axis; FT_UInt num_designs; FT_MM_Axis axis[T1_MAX_MM_AXIS]; } FT_Multi_Master; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Var_Axis */ /* */ /* <Description> */ /* A simple structure used to model a given axis in design space for */ /* Multiple Masters and GX var fonts. */ /* */ /* <Fields> */ /* name :: The axis's name. */ /* Not always meaningful for GX. */ /* */ /* minimum :: The axis's minimum design coordinate. */ /* */ /* def :: The axis's default design coordinate. */ /* FreeType computes meaningful default values for MM; it */ /* is then an integer value, not in 16.16 format. */ /* */ /* maximum :: The axis's maximum design coordinate. */ /* */ /* tag :: The axis's tag (the GX equivalent to `name'). */ /* FreeType provides default values for MM if possible. */ /* */ /* strid :: The entry in `name' table (another GX version of */ /* `name'). */ /* Not meaningful for MM. */ /* */ typedef struct FT_Var_Axis_ { FT_String* name; FT_Fixed minimum; FT_Fixed def; FT_Fixed maximum; FT_ULong tag; FT_UInt strid; } FT_Var_Axis; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Var_Named_Style */ /* */ /* <Description> */ /* A simple structure used to model a named style in a GX var font. */ /* */ /* This structure can't be used for MM fonts. */ /* */ /* <Fields> */ /* coords :: The design coordinates for this style. */ /* This is an array with one entry for each axis. */ /* */ /* strid :: The entry in `name' table identifying this style. */ /* */ typedef struct FT_Var_Named_Style_ { FT_Fixed* coords; FT_UInt strid; } FT_Var_Named_Style; /*************************************************************************/ /* */ /* <Struct> */ /* FT_MM_Var */ /* */ /* <Description> */ /* A structure used to model the axes and space of a Multiple Masters */ /* or GX var distortable font. */ /* */ /* Some fields are specific to one format and not to the other. */ /* */ /* <Fields> */ /* num_axis :: The number of axes. The maximum value is~4 for */ /* MM; no limit in GX. */ /* */ /* num_designs :: The number of designs; should be normally */ /* 2^num_axis for MM fonts. Not meaningful for GX */ /* (where every glyph could have a different */ /* number of designs). */ /* */ /* num_namedstyles :: The number of named styles; only meaningful for */ /* GX which allows certain design coordinates to */ /* have a string ID (in the `name' table) */ /* associated with them. The font can tell the */ /* user that, for example, Weight=1.5 is `Bold'. */ /* */ /* axis :: A table of axis descriptors. */ /* GX fonts contain slightly more data than MM. */ /* */ /* namedstyles :: A table of named styles. */ /* Only meaningful with GX. */ /* */ typedef struct FT_MM_Var_ { FT_UInt num_axis; FT_UInt num_designs; FT_UInt num_namedstyles; FT_Var_Axis* axis; FT_Var_Named_Style* namedstyle; } FT_MM_Var; /* */ /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Multi_Master */ /* */ /* <Description> */ /* Retrieve the Multiple Master descriptor of a given font. */ /* */ /* This function can't be used with GX fonts. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* <Output> */ /* amaster :: The Multiple Masters descriptor. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Multi_Master( FT_Face face, FT_Multi_Master *amaster ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_MM_Var */ /* */ /* <Description> */ /* Retrieve the Multiple Master/GX var descriptor of a given font. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* <Output> */ /* amaster :: The Multiple Masters/GX var descriptor. */ /* Allocates a data structure, which the user must free */ /* (a single call to FT_FREE will do it). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Get_MM_Var( FT_Face face, FT_MM_Var* *amaster ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_MM_Design_Coordinates */ /* */ /* <Description> */ /* For Multiple Masters fonts, choose an interpolated font design */ /* through design coordinates. */ /* */ /* This function can't be used with GX fonts. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ /* */ /* <Input> */ /* num_coords :: The number of design coordinates (must be equal to */ /* the number of axes in the font). */ /* */ /* coords :: An array of design coordinates. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Set_MM_Design_Coordinates( FT_Face face, FT_UInt num_coords, FT_Long* coords ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Var_Design_Coordinates */ /* */ /* <Description> */ /* For Multiple Master or GX Var fonts, choose an interpolated font */ /* design through design coordinates. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ /* */ /* <Input> */ /* num_coords :: The number of design coordinates (must be equal to */ /* the number of axes in the font). */ /* */ /* coords :: An array of design coordinates. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Var_Design_Coordinates( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_MM_Blend_Coordinates */ /* */ /* <Description> */ /* For Multiple Masters and GX var fonts, choose an interpolated font */ /* design through normalized blend coordinates. */ /* */ /* <InOut> */ /* face :: A handle to the source face. */ /* */ /* <Input> */ /* num_coords :: The number of design coordinates (must be equal to */ /* the number of axes in the font). */ /* */ /* coords :: The design coordinates array (each element must be */ /* between 0 and 1.0). */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Set_MM_Blend_Coordinates( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Var_Blend_Coordinates */ /* */ /* <Description> */ /* This is another name of @FT_Set_MM_Blend_Coordinates. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Var_Blend_Coordinates( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); /* */ FT_END_HEADER #endif /* __FTMM_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftmodapi.h ================================================ /***************************************************************************/ /* */ /* ftmodapi.h */ /* */ /* FreeType modules public interface (specification). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTMODAPI_H__ #define __FTMODAPI_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* module_management */ /* */ /* <Title> */ /* Module Management */ /* */ /* <Abstract> */ /* How to add, upgrade, and remove modules from FreeType. */ /* */ /* <Description> */ /* The definitions below are used to manage modules within FreeType. */ /* Modules can be added, upgraded, and removed at runtime. */ /* */ /*************************************************************************/ /* module bit flags */ #define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */ #define FT_MODULE_RENDERER 2 /* this module is a renderer */ #define FT_MODULE_HINTER 4 /* this module is a glyph hinter */ #define FT_MODULE_STYLER 8 /* this module is a styler */ #define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */ /* scalable fonts */ #define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */ /* support vector outlines */ #define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */ /* own hinter */ /* deprecated values */ #define ft_module_font_driver FT_MODULE_FONT_DRIVER #define ft_module_renderer FT_MODULE_RENDERER #define ft_module_hinter FT_MODULE_HINTER #define ft_module_styler FT_MODULE_STYLER #define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE #define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES #define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER typedef FT_Pointer FT_Module_Interface; /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Module_Constructor */ /* */ /* <Description> */ /* A function used to initialize (not create) a new module object. */ /* */ /* <Input> */ /* module :: The module to initialize. */ /* */ typedef FT_Error (*FT_Module_Constructor)( FT_Module module ); /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Module_Destructor */ /* */ /* <Description> */ /* A function used to finalize (not destroy) a given module object. */ /* */ /* <Input> */ /* module :: The module to finalize. */ /* */ typedef void (*FT_Module_Destructor)( FT_Module module ); /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Module_Requester */ /* */ /* <Description> */ /* A function used to query a given module for a specific interface. */ /* */ /* <Input> */ /* module :: The module to finalize. */ /* */ /* name :: The name of the interface in the module. */ /* */ typedef FT_Module_Interface (*FT_Module_Requester)( FT_Module module, const char* name ); /*************************************************************************/ /* */ /* <Struct> */ /* FT_Module_Class */ /* */ /* <Description> */ /* The module class descriptor. */ /* */ /* <Fields> */ /* module_flags :: Bit flags describing the module. */ /* */ /* module_size :: The size of one module object/instance in */ /* bytes. */ /* */ /* module_name :: The name of the module. */ /* */ /* module_version :: The version, as a 16.16 fixed number */ /* (major.minor). */ /* */ /* module_requires :: The version of FreeType this module requires, */ /* as a 16.16 fixed number (major.minor). Starts */ /* at version 2.0, i.e., 0x20000. */ /* */ /* module_init :: The initializing function. */ /* */ /* module_done :: The finalizing function. */ /* */ /* get_interface :: The interface requesting function. */ /* */ typedef struct FT_Module_Class_ { FT_ULong module_flags; FT_Long module_size; const FT_String* module_name; FT_Fixed module_version; FT_Fixed module_requires; const void* module_interface; FT_Module_Constructor module_init; FT_Module_Destructor module_done; FT_Module_Requester get_interface; } FT_Module_Class; /*************************************************************************/ /* */ /* <Function> */ /* FT_Add_Module */ /* */ /* <Description> */ /* Add a new module to a given library instance. */ /* */ /* <InOut> */ /* library :: A handle to the library object. */ /* */ /* <Input> */ /* clazz :: A pointer to class descriptor for the module. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* An error will be returned if a module already exists by that name, */ /* or if the module requires a version of FreeType that is too great. */ /* */ FT_EXPORT( FT_Error ) FT_Add_Module( FT_Library library, const FT_Module_Class* clazz ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Module */ /* */ /* <Description> */ /* Find a module by its name. */ /* */ /* <Input> */ /* library :: A handle to the library object. */ /* */ /* module_name :: The module's name (as an ASCII string). */ /* */ /* <Return> */ /* A module handle. 0~if none was found. */ /* */ /* <Note> */ /* FreeType's internal modules aren't documented very well, and you */ /* should look up the source code for details. */ /* */ FT_EXPORT( FT_Module ) FT_Get_Module( FT_Library library, const char* module_name ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Remove_Module */ /* */ /* <Description> */ /* Remove a given module from a library instance. */ /* */ /* <InOut> */ /* library :: A handle to a library object. */ /* */ /* <Input> */ /* module :: A handle to a module object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The module object is destroyed by the function in case of success. */ /* */ FT_EXPORT( FT_Error ) FT_Remove_Module( FT_Library library, FT_Module module ); /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Library */ /* */ /* <Description> */ /* This function is used to create a new FreeType library instance */ /* from a given memory object. It is thus possible to use libraries */ /* with distinct memory allocators within the same program. */ /* */ /* Normally, you would call this function (followed by a call to */ /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */ /* instead of @FT_Init_FreeType to initialize the FreeType library. */ /* */ /* <Input> */ /* memory :: A handle to the original memory object. */ /* */ /* <Output> */ /* alibrary :: A pointer to handle of a new library object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_New_Library( FT_Memory memory, FT_Library *alibrary ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Done_Library */ /* */ /* <Description> */ /* Discard a given library object. This closes all drivers and */ /* discards all resource objects. */ /* */ /* <Input> */ /* library :: A handle to the target library. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Done_Library( FT_Library library ); /* */ typedef void (*FT_DebugHook_Func)( void* arg ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Debug_Hook */ /* */ /* <Description> */ /* Set a debug hook function for debugging the interpreter of a font */ /* format. */ /* */ /* <InOut> */ /* library :: A handle to the library object. */ /* */ /* <Input> */ /* hook_index :: The index of the debug hook. You should use the */ /* values defined in `ftobjs.h', e.g., */ /* `FT_DEBUG_HOOK_TRUETYPE'. */ /* */ /* debug_hook :: The function used to debug the interpreter. */ /* */ /* <Note> */ /* Currently, four debug hook slots are available, but only two (for */ /* the TrueType and the Type~1 interpreter) are defined. */ /* */ /* Since the internal headers of FreeType are no longer installed, */ /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */ /* This is a bug and will be fixed in a forthcoming release. */ /* */ FT_EXPORT( void ) FT_Set_Debug_Hook( FT_Library library, FT_UInt hook_index, FT_DebugHook_Func debug_hook ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Add_Default_Modules */ /* */ /* <Description> */ /* Add the set of default drivers to a given library object. */ /* This is only useful when you create a library object with */ /* @FT_New_Library (usually to plug a custom memory manager). */ /* */ /* <InOut> */ /* library :: A handle to a new library object. */ /* */ FT_EXPORT( void ) FT_Add_Default_Modules( FT_Library library ); /************************************************************************** * * @section: * truetype_engine * * @title: * The TrueType Engine * * @abstract: * TrueType bytecode support. * * @description: * This section contains a function used to query the level of TrueType * bytecode support compiled in this version of the library. * */ /************************************************************************** * * @enum: * FT_TrueTypeEngineType * * @description: * A list of values describing which kind of TrueType bytecode * engine is implemented in a given FT_Library instance. It is used * by the @FT_Get_TrueType_Engine_Type function. * * @values: * FT_TRUETYPE_ENGINE_TYPE_NONE :: * The library doesn't implement any kind of bytecode interpreter. * * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED :: * The library implements a bytecode interpreter that doesn't * support the patented operations of the TrueType virtual machine. * * Its main use is to load certain Asian fonts which position and * scale glyph components with bytecode instructions. It produces * bad output for most other fonts. * * FT_TRUETYPE_ENGINE_TYPE_PATENTED :: * The library implements a bytecode interpreter that covers * the full instruction set of the TrueType virtual machine. * See the file `docs/PATENTS' for legal aspects. * * @since: * 2.2 * */ typedef enum FT_TrueTypeEngineType_ { FT_TRUETYPE_ENGINE_TYPE_NONE = 0, FT_TRUETYPE_ENGINE_TYPE_UNPATENTED, FT_TRUETYPE_ENGINE_TYPE_PATENTED } FT_TrueTypeEngineType; /************************************************************************** * * @func: * FT_Get_TrueType_Engine_Type * * @description: * Return an @FT_TrueTypeEngineType value to indicate which level of * the TrueType virtual machine a given library instance supports. * * @input: * library :: * A library instance. * * @return: * A value indicating which level is supported. * * @since: * 2.2 * */ FT_EXPORT( FT_TrueTypeEngineType ) FT_Get_TrueType_Engine_Type( FT_Library library ); /* */ FT_END_HEADER #endif /* __FTMODAPI_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftmoderr.h ================================================ /***************************************************************************/ /* */ /* ftmoderr.h */ /* */ /* FreeType module error offsets (specification). */ /* */ /* Copyright 2001, 2002, 2003, 2004, 2005 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* This file is used to define the FreeType module error offsets. */ /* */ /* The lower byte gives the error code, the higher byte gives the */ /* module. The base module has error offset 0. For example, the error */ /* `FT_Err_Invalid_File_Format' has value 0x003, the error */ /* `TT_Err_Invalid_File_Format' has value 0x1103, the error */ /* `T1_Err_Invalid_File_Format' has value 0x1203, etc. */ /* */ /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h */ /* to make the higher byte always zero (disabling the module error */ /* mechanism). */ /* */ /* It can also be used to create a module error message table easily */ /* with something like */ /* */ /* { */ /* #undef __FTMODERR_H__ */ /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */ /* #define FT_MODERR_START_LIST { */ /* #define FT_MODERR_END_LIST { 0, 0 } }; */ /* */ /* const struct */ /* { */ /* int mod_err_offset; */ /* const char* mod_err_msg */ /* } ft_mod_errors[] = */ /* */ /* #include FT_MODULE_ERRORS_H */ /* } */ /* */ /* To use such a table, all errors must be ANDed with 0xFF00 to remove */ /* the error code. */ /* */ /*************************************************************************/ #ifndef __FTMODERR_H__ #define __FTMODERR_H__ /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** SETUP MACROS *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ #undef FT_NEED_EXTERN_C #ifndef FT_MODERRDEF #ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS #define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v, #else #define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0, #endif #define FT_MODERR_START_LIST enum { #define FT_MODERR_END_LIST FT_Mod_Err_Max }; #ifdef __cplusplus #define FT_NEED_EXTERN_C extern "C" { #endif #endif /* !FT_MODERRDEF */ /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** LIST MODULE ERROR BASES *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ #ifdef FT_MODERR_START_LIST FT_MODERR_START_LIST #endif FT_MODERRDEF( Base, 0x000, "base module" ) FT_MODERRDEF( Autofit, 0x100, "autofitter module" ) FT_MODERRDEF( BDF, 0x200, "BDF module" ) FT_MODERRDEF( Cache, 0x300, "cache module" ) FT_MODERRDEF( CFF, 0x400, "CFF module" ) FT_MODERRDEF( CID, 0x500, "CID module" ) FT_MODERRDEF( Gzip, 0x600, "Gzip module" ) FT_MODERRDEF( LZW, 0x700, "LZW module" ) FT_MODERRDEF( OTvalid, 0x800, "OpenType validation module" ) FT_MODERRDEF( PCF, 0x900, "PCF module" ) FT_MODERRDEF( PFR, 0xA00, "PFR module" ) FT_MODERRDEF( PSaux, 0xB00, "PS auxiliary module" ) FT_MODERRDEF( PShinter, 0xC00, "PS hinter module" ) FT_MODERRDEF( PSnames, 0xD00, "PS names module" ) FT_MODERRDEF( Raster, 0xE00, "raster module" ) FT_MODERRDEF( SFNT, 0xF00, "SFNT module" ) FT_MODERRDEF( Smooth, 0x1000, "smooth raster module" ) FT_MODERRDEF( TrueType, 0x1100, "TrueType module" ) FT_MODERRDEF( Type1, 0x1200, "Type 1 module" ) FT_MODERRDEF( Type42, 0x1300, "Type 42 module" ) FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" ) #ifdef FT_MODERR_END_LIST FT_MODERR_END_LIST #endif /*******************************************************************/ /*******************************************************************/ /***** *****/ /***** CLEANUP *****/ /***** *****/ /*******************************************************************/ /*******************************************************************/ #ifdef FT_NEED_EXTERN_C } #endif #undef FT_MODERR_START_LIST #undef FT_MODERR_END_LIST #undef FT_MODERRDEF #undef FT_NEED_EXTERN_C #endif /* __FTMODERR_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftotval.h ================================================ /***************************************************************************/ /* */ /* ftotval.h */ /* */ /* FreeType API for validating OpenType tables (specification). */ /* */ /* Copyright 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /***************************************************************************/ /* */ /* */ /* Warning: This module might be moved to a different library in the */ /* future to avoid a tight dependency between FreeType and the */ /* OpenType specification. */ /* */ /* */ /***************************************************************************/ #ifndef __FTOTVAL_H__ #define __FTOTVAL_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* ot_validation */ /* */ /* <Title> */ /* OpenType Validation */ /* */ /* <Abstract> */ /* An API to validate OpenType tables. */ /* */ /* <Description> */ /* This section contains the declaration of functions to validate */ /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */ /* */ /*************************************************************************/ /********************************************************************** * * @enum: * FT_VALIDATE_OTXXX * * @description: * A list of bit-field constants used with @FT_OpenType_Validate to * indicate which OpenType tables should be validated. * * @values: * FT_VALIDATE_BASE :: * Validate BASE table. * * FT_VALIDATE_GDEF :: * Validate GDEF table. * * FT_VALIDATE_GPOS :: * Validate GPOS table. * * FT_VALIDATE_GSUB :: * Validate GSUB table. * * FT_VALIDATE_JSTF :: * Validate JSTF table. * * FT_VALIDATE_MATH :: * Validate MATH table. * * FT_VALIDATE_OT :: * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). * */ #define FT_VALIDATE_BASE 0x0100 #define FT_VALIDATE_GDEF 0x0200 #define FT_VALIDATE_GPOS 0x0400 #define FT_VALIDATE_GSUB 0x0800 #define FT_VALIDATE_JSTF 0x1000 #define FT_VALIDATE_MATH 0x2000 #define FT_VALIDATE_OT FT_VALIDATE_BASE | \ FT_VALIDATE_GDEF | \ FT_VALIDATE_GPOS | \ FT_VALIDATE_GSUB | \ FT_VALIDATE_JSTF | \ FT_VALIDATE_MATH /* */ /********************************************************************** * * @function: * FT_OpenType_Validate * * @description: * Validate various OpenType tables to assure that all offsets and * indices are valid. The idea is that a higher-level library which * actually does the text layout can access those tables without * error checking (which can be quite time consuming). * * @input: * face :: * A handle to the input face. * * validation_flags :: * A bit field which specifies the tables to be validated. See * @FT_VALIDATE_OTXXX for possible values. * * @output: * BASE_table :: * A pointer to the BASE table. * * GDEF_table :: * A pointer to the GDEF table. * * GPOS_table :: * A pointer to the GPOS table. * * GSUB_table :: * A pointer to the GSUB table. * * JSTF_table :: * A pointer to the JSTF table. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with OpenType fonts, returning an error * otherwise. * * After use, the application should deallocate the five tables with * @FT_OpenType_Free. A NULL value indicates that the table either * doesn't exist in the font, or the application hasn't asked for * validation. */ FT_EXPORT( FT_Error ) FT_OpenType_Validate( FT_Face face, FT_UInt validation_flags, FT_Bytes *BASE_table, FT_Bytes *GDEF_table, FT_Bytes *GPOS_table, FT_Bytes *GSUB_table, FT_Bytes *JSTF_table ); /* */ /********************************************************************** * * @function: * FT_OpenType_Free * * @description: * Free the buffer allocated by OpenType validator. * * @input: * face :: * A handle to the input face. * * table :: * The pointer to the buffer that is allocated by * @FT_OpenType_Validate. * * @note: * This function must be used to free the buffer allocated by * @FT_OpenType_Validate only. */ FT_EXPORT( void ) FT_OpenType_Free( FT_Face face, FT_Bytes table ); /* */ FT_END_HEADER #endif /* __FTOTVAL_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftoutln.h ================================================ /***************************************************************************/ /* */ /* ftoutln.h */ /* */ /* Support for the FT_Outline type used to store glyph shapes of */ /* most scalable font formats (specification). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTOUTLN_H__ #define __FTOUTLN_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* outline_processing */ /* */ /* <Title> */ /* Outline Processing */ /* */ /* <Abstract> */ /* Functions to create, transform, and render vectorial glyph images. */ /* */ /* <Description> */ /* This section contains routines used to create and destroy scalable */ /* glyph images known as `outlines'. These can also be measured, */ /* transformed, and converted into bitmaps and pixmaps. */ /* */ /* <Order> */ /* FT_Outline */ /* FT_OUTLINE_FLAGS */ /* FT_Outline_New */ /* FT_Outline_Done */ /* FT_Outline_Copy */ /* FT_Outline_Translate */ /* FT_Outline_Transform */ /* FT_Outline_Embolden */ /* FT_Outline_Reverse */ /* FT_Outline_Check */ /* */ /* FT_Outline_Get_CBox */ /* FT_Outline_Get_BBox */ /* */ /* FT_Outline_Get_Bitmap */ /* FT_Outline_Render */ /* */ /* FT_Outline_Decompose */ /* FT_Outline_Funcs */ /* FT_Outline_MoveTo_Func */ /* FT_Outline_LineTo_Func */ /* FT_Outline_ConicTo_Func */ /* FT_Outline_CubicTo_Func */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Decompose */ /* */ /* <Description> */ /* Walk over an outline's structure to decompose it into individual */ /* segments and Bézier arcs. This function is also able to emit */ /* `move to' and `close to' operations to indicate the start and end */ /* of new contours in the outline. */ /* */ /* <Input> */ /* outline :: A pointer to the source target. */ /* */ /* func_interface :: A table of `emitters', i.e., function pointers */ /* called during decomposition to indicate path */ /* operations. */ /* */ /* <InOut> */ /* user :: A typeless pointer which is passed to each */ /* emitter during the decomposition. It can be */ /* used to store the state during the */ /* decomposition. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Decompose( FT_Outline* outline, const FT_Outline_Funcs* func_interface, void* user ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_New */ /* */ /* <Description> */ /* Create a new outline of a given size. */ /* */ /* <Input> */ /* library :: A handle to the library object from where the */ /* outline is allocated. Note however that the new */ /* outline will *not* necessarily be *freed*, when */ /* destroying the library, by @FT_Done_FreeType. */ /* */ /* numPoints :: The maximal number of points within the outline. */ /* */ /* numContours :: The maximal number of contours within the outline. */ /* */ /* <Output> */ /* anoutline :: A handle to the new outline. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The reason why this function takes a `library' parameter is simply */ /* to use the library's memory allocator. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_New( FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline ); FT_EXPORT( FT_Error ) FT_Outline_New_Internal( FT_Memory memory, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Done */ /* */ /* <Description> */ /* Destroy an outline created with @FT_Outline_New. */ /* */ /* <Input> */ /* library :: A handle of the library object used to allocate the */ /* outline. */ /* */ /* outline :: A pointer to the outline object to be discarded. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* If the outline's `owner' field is not set, only the outline */ /* descriptor will be released. */ /* */ /* The reason why this function takes an `library' parameter is */ /* simply to use ft_mem_free(). */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Done( FT_Library library, FT_Outline* outline ); FT_EXPORT( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory, FT_Outline* outline ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Check */ /* */ /* <Description> */ /* Check the contents of an outline descriptor. */ /* */ /* <Input> */ /* outline :: A handle to a source outline. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Check( FT_Outline* outline ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Get_CBox */ /* */ /* <Description> */ /* Return an outline's `control box'. The control box encloses all */ /* the outline's points, including Bézier control points. Though it */ /* coincides with the exact bounding box for most glyphs, it can be */ /* slightly larger in some situations (like when rotating an outline */ /* which contains Bézier outside arcs). */ /* */ /* Computing the control box is very fast, while getting the bounding */ /* box can take much more time as it needs to walk over all segments */ /* and arcs in the outline. To get the latter, you can use the */ /* `ftbbox' component which is dedicated to this single task. */ /* */ /* <Input> */ /* outline :: A pointer to the source outline descriptor. */ /* */ /* <Output> */ /* acbox :: The outline's control box. */ /* */ FT_EXPORT( void ) FT_Outline_Get_CBox( const FT_Outline* outline, FT_BBox *acbox ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Translate */ /* */ /* <Description> */ /* Apply a simple translation to the points of an outline. */ /* */ /* <InOut> */ /* outline :: A pointer to the target outline descriptor. */ /* */ /* <Input> */ /* xOffset :: The horizontal offset. */ /* */ /* yOffset :: The vertical offset. */ /* */ FT_EXPORT( void ) FT_Outline_Translate( const FT_Outline* outline, FT_Pos xOffset, FT_Pos yOffset ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Copy */ /* */ /* <Description> */ /* Copy an outline into another one. Both objects must have the */ /* same sizes (number of points & number of contours) when this */ /* function is called. */ /* */ /* <Input> */ /* source :: A handle to the source outline. */ /* */ /* <Output> */ /* target :: A handle to the target outline. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Copy( const FT_Outline* source, FT_Outline *target ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Transform */ /* */ /* <Description> */ /* Apply a simple 2x2 matrix to all of an outline's points. Useful */ /* for applying rotations, slanting, flipping, etc. */ /* */ /* <InOut> */ /* outline :: A pointer to the target outline descriptor. */ /* */ /* <Input> */ /* matrix :: A pointer to the transformation matrix. */ /* */ /* <Note> */ /* You can use @FT_Outline_Translate if you need to translate the */ /* outline's points. */ /* */ FT_EXPORT( void ) FT_Outline_Transform( const FT_Outline* outline, const FT_Matrix* matrix ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Embolden */ /* */ /* <Description> */ /* Embolden an outline. The new outline will be at most 4~times */ /* `strength' pixels wider and higher. You may think of the left and */ /* bottom borders as unchanged. */ /* */ /* Negative `strength' values to reduce the outline thickness are */ /* possible also. */ /* */ /* <InOut> */ /* outline :: A handle to the target outline. */ /* */ /* <Input> */ /* strength :: How strong the glyph is emboldened. Expressed in */ /* 26.6 pixel format. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The used algorithm to increase or decrease the thickness of the */ /* glyph doesn't change the number of points; this means that certain */ /* situations like acute angles or intersections are sometimes */ /* handled incorrectly. */ /* */ /* If you need `better' metrics values you should call */ /* @FT_Outline_Get_CBox ot @FT_Outline_Get_BBox. */ /* */ /* Example call: */ /* */ /* { */ /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */ /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */ /* FT_Outline_Embolden( &face->slot->outline, strength ); */ /* } */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Embolden( FT_Outline* outline, FT_Pos strength ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Reverse */ /* */ /* <Description> */ /* Reverse the drawing direction of an outline. This is used to */ /* ensure consistent fill conventions for mirrored glyphs. */ /* */ /* <InOut> */ /* outline :: A pointer to the target outline descriptor. */ /* */ /* <Note> */ /* This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */ /* the outline's `flags' field. */ /* */ /* It shouldn't be used by a normal client application, unless it */ /* knows what it is doing. */ /* */ FT_EXPORT( void ) FT_Outline_Reverse( FT_Outline* outline ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Get_Bitmap */ /* */ /* <Description> */ /* Render an outline within a bitmap. The outline's image is simply */ /* OR-ed to the target bitmap. */ /* */ /* <Input> */ /* library :: A handle to a FreeType library object. */ /* */ /* outline :: A pointer to the source outline descriptor. */ /* */ /* <InOut> */ /* abitmap :: A pointer to the target bitmap descriptor. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* This function does NOT CREATE the bitmap, it only renders an */ /* outline image within the one you pass to it! Consequently, the */ /* various fields in `abitmap' should be set accordingly. */ /* */ /* It will use the raster corresponding to the default glyph format. */ /* */ /* The value of the `num_grays' field in `abitmap' is ignored. If */ /* you select the gray-level rasterizer, and you want less than 256 */ /* gray levels, you have to use @FT_Outline_Render directly. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, FT_Outline* outline, const FT_Bitmap *abitmap ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Outline_Render */ /* */ /* <Description> */ /* Render an outline within a bitmap using the current scan-convert. */ /* This function uses an @FT_Raster_Params structure as an argument, */ /* allowing advanced features like direct composition, translucency, */ /* etc. */ /* */ /* <Input> */ /* library :: A handle to a FreeType library object. */ /* */ /* outline :: A pointer to the source outline descriptor. */ /* */ /* <InOut> */ /* params :: A pointer to an @FT_Raster_Params structure used to */ /* describe the rendering operation. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* You should know what you are doing and how @FT_Raster_Params works */ /* to use this function. */ /* */ /* The field `params.source' will be set to `outline' before the scan */ /* converter is called, which means that the value you give to it is */ /* actually ignored. */ /* */ /* The gray-level rasterizer always uses 256 gray levels. If you */ /* want less gray levels, you have to provide your own span callback. */ /* See the @FT_RASTER_FLAG_DIRECT value of the `flags' field in the */ /* @FT_Raster_Params structure for more details. */ /* */ FT_EXPORT( FT_Error ) FT_Outline_Render( FT_Library library, FT_Outline* outline, FT_Raster_Params* params ); /************************************************************************** * * @enum: * FT_Orientation * * @description: * A list of values used to describe an outline's contour orientation. * * The TrueType and PostScript specifications use different conventions * to determine whether outline contours should be filled or unfilled. * * @values: * FT_ORIENTATION_TRUETYPE :: * According to the TrueType specification, clockwise contours must * be filled, and counter-clockwise ones must be unfilled. * * FT_ORIENTATION_POSTSCRIPT :: * According to the PostScript specification, counter-clockwise contours * must be filled, and clockwise ones must be unfilled. * * FT_ORIENTATION_FILL_RIGHT :: * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to * remember that in TrueType, everything that is to the right of * the drawing direction of a contour must be filled. * * FT_ORIENTATION_FILL_LEFT :: * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to * remember that in PostScript, everything that is to the left of * the drawing direction of a contour must be filled. * * FT_ORIENTATION_NONE :: * The orientation cannot be determined. That is, different parts of * the glyph have different orientation. * */ typedef enum FT_Orientation_ { FT_ORIENTATION_TRUETYPE = 0, FT_ORIENTATION_POSTSCRIPT = 1, FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE, FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT, FT_ORIENTATION_NONE } FT_Orientation; /************************************************************************** * * @function: * FT_Outline_Get_Orientation * * @description: * This function analyzes a glyph outline and tries to compute its * fill orientation (see @FT_Orientation). This is done by computing * the direction of each global horizontal and/or vertical extrema * within the outline. * * Note that this will return @FT_ORIENTATION_TRUETYPE for empty * outlines. * * @input: * outline :: * A handle to the source outline. * * @return: * The orientation. * */ FT_EXPORT( FT_Orientation ) FT_Outline_Get_Orientation( FT_Outline* outline ); /* */ FT_END_HEADER #endif /* __FTOUTLN_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftpfr.h ================================================ /***************************************************************************/ /* */ /* ftpfr.h */ /* */ /* FreeType API for accessing PFR-specific data (specification only). */ /* */ /* Copyright 2002, 2003, 2004, 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTPFR_H__ #define __FTPFR_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* pfr_fonts */ /* */ /* <Title> */ /* PFR Fonts */ /* */ /* <Abstract> */ /* PFR/TrueDoc specific API. */ /* */ /* <Description> */ /* This section contains the declaration of PFR-specific functions. */ /* */ /*************************************************************************/ /********************************************************************** * * @function: * FT_Get_PFR_Metrics * * @description: * Return the outline and metrics resolutions of a given PFR face. * * @input: * face :: Handle to the input face. It can be a non-PFR face. * * @output: * aoutline_resolution :: * Outline resolution. This is equivalent to `face->units_per_EM' * for non-PFR fonts. Optional (parameter can be NULL). * * ametrics_resolution :: * Metrics resolution. This is equivalent to `outline_resolution' * for non-PFR fonts. Optional (parameter can be NULL). * * ametrics_x_scale :: * A 16.16 fixed-point number used to scale distance expressed * in metrics units to device sub-pixels. This is equivalent to * `face->size->x_scale', but for metrics only. Optional (parameter * can be NULL). * * ametrics_y_scale :: * Same as `ametrics_x_scale' but for the vertical direction. * optional (parameter can be NULL). * * @return: * FreeType error code. 0~means success. * * @note: * If the input face is not a PFR, this function will return an error. * However, in all cases, it will return valid values. */ FT_EXPORT( FT_Error ) FT_Get_PFR_Metrics( FT_Face face, FT_UInt *aoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ); /********************************************************************** * * @function: * FT_Get_PFR_Kerning * * @description: * Return the kerning pair corresponding to two glyphs in a PFR face. * The distance is expressed in metrics units, unlike the result of * @FT_Get_Kerning. * * @input: * face :: A handle to the input face. * * left :: Index of the left glyph. * * right :: Index of the right glyph. * * @output: * avector :: A kerning vector. * * @return: * FreeType error code. 0~means success. * * @note: * This function always return distances in original PFR metrics * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED * mode, which always returns distances converted to outline units. * * You can use the value of the `x_scale' and `y_scale' parameters * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels. */ FT_EXPORT( FT_Error ) FT_Get_PFR_Kerning( FT_Face face, FT_UInt left, FT_UInt right, FT_Vector *avector ); /********************************************************************** * * @function: * FT_Get_PFR_Advance * * @description: * Return a given glyph advance, expressed in original metrics units, * from a PFR font. * * @input: * face :: A handle to the input face. * * gindex :: The glyph index. * * @output: * aadvance :: The glyph advance in metrics units. * * @return: * FreeType error code. 0~means success. * * @note: * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics * to convert the advance to device sub-pixels (i.e., 1/64th of pixels). */ FT_EXPORT( FT_Error ) FT_Get_PFR_Advance( FT_Face face, FT_UInt gindex, FT_Pos *aadvance ); /* */ FT_END_HEADER #endif /* __FTPFR_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftrender.h ================================================ /***************************************************************************/ /* */ /* ftrender.h */ /* */ /* FreeType renderer modules public interface (specification). */ /* */ /* Copyright 1996-2001, 2005, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTRENDER_H__ #define __FTRENDER_H__ #include <ft2build.h> #include FT_MODULE_H #include FT_GLYPH_H FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* module_management */ /* */ /*************************************************************************/ /* create a new glyph object */ typedef FT_Error (*FT_Glyph_InitFunc)( FT_Glyph glyph, FT_GlyphSlot slot ); /* destroys a given glyph object */ typedef void (*FT_Glyph_DoneFunc)( FT_Glyph glyph ); typedef void (*FT_Glyph_TransformFunc)( FT_Glyph glyph, const FT_Matrix* matrix, const FT_Vector* delta ); typedef void (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph, FT_BBox* abbox ); typedef FT_Error (*FT_Glyph_CopyFunc)( FT_Glyph source, FT_Glyph target ); typedef FT_Error (*FT_Glyph_PrepareFunc)( FT_Glyph glyph, FT_GlyphSlot slot ); /* deprecated */ #define FT_Glyph_Init_Func FT_Glyph_InitFunc #define FT_Glyph_Done_Func FT_Glyph_DoneFunc #define FT_Glyph_Transform_Func FT_Glyph_TransformFunc #define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc #define FT_Glyph_Copy_Func FT_Glyph_CopyFunc #define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc struct FT_Glyph_Class_ { FT_Long glyph_size; FT_Glyph_Format glyph_format; FT_Glyph_InitFunc glyph_init; FT_Glyph_DoneFunc glyph_done; FT_Glyph_CopyFunc glyph_copy; FT_Glyph_TransformFunc glyph_transform; FT_Glyph_GetBBoxFunc glyph_bbox; FT_Glyph_PrepareFunc glyph_prepare; }; typedef FT_Error (*FT_Renderer_RenderFunc)( FT_Renderer renderer, FT_GlyphSlot slot, FT_UInt mode, const FT_Vector* origin ); typedef FT_Error (*FT_Renderer_TransformFunc)( FT_Renderer renderer, FT_GlyphSlot slot, const FT_Matrix* matrix, const FT_Vector* delta ); typedef void (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer, FT_GlyphSlot slot, FT_BBox* cbox ); typedef FT_Error (*FT_Renderer_SetModeFunc)( FT_Renderer renderer, FT_ULong mode_tag, FT_Pointer mode_ptr ); /* deprecated identifiers */ #define FTRenderer_render FT_Renderer_RenderFunc #define FTRenderer_transform FT_Renderer_TransformFunc #define FTRenderer_getCBox FT_Renderer_GetCBoxFunc #define FTRenderer_setMode FT_Renderer_SetModeFunc /*************************************************************************/ /* */ /* <Struct> */ /* FT_Renderer_Class */ /* */ /* <Description> */ /* The renderer module class descriptor. */ /* */ /* <Fields> */ /* root :: The root @FT_Module_Class fields. */ /* */ /* glyph_format :: The glyph image format this renderer handles. */ /* */ /* render_glyph :: A method used to render the image that is in a */ /* given glyph slot into a bitmap. */ /* */ /* transform_glyph :: A method used to transform the image that is in */ /* a given glyph slot. */ /* */ /* get_glyph_cbox :: A method used to access the glyph's cbox. */ /* */ /* set_mode :: A method used to pass additional parameters. */ /* */ /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */ /* This is a pointer to its raster's class. */ /* */ /* raster :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */ /* This is a pointer to the corresponding raster */ /* object, if any. */ /* */ typedef struct FT_Renderer_Class_ { FT_Module_Class root; FT_Glyph_Format glyph_format; FT_Renderer_RenderFunc render_glyph; FT_Renderer_TransformFunc transform_glyph; FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; FT_Raster_Funcs* raster_class; } FT_Renderer_Class; /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Renderer */ /* */ /* <Description> */ /* Retrieve the current renderer for a given glyph format. */ /* */ /* <Input> */ /* library :: A handle to the library object. */ /* */ /* format :: The glyph format. */ /* */ /* <Return> */ /* A renderer handle. 0~if none found. */ /* */ /* <Note> */ /* An error will be returned if a module already exists by that name, */ /* or if the module requires a version of FreeType that is too great. */ /* */ /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */ /* renderer by its name, use @FT_Get_Module. */ /* */ FT_EXPORT( FT_Renderer ) FT_Get_Renderer( FT_Library library, FT_Glyph_Format format ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Set_Renderer */ /* */ /* <Description> */ /* Set the current renderer to use, and set additional mode. */ /* */ /* <InOut> */ /* library :: A handle to the library object. */ /* */ /* <Input> */ /* renderer :: A handle to the renderer object. */ /* */ /* num_params :: The number of additional parameters. */ /* */ /* parameters :: Additional parameters. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* In case of success, the renderer will be used to convert glyph */ /* images in the renderer's known format into bitmaps. */ /* */ /* This doesn't change the current renderer for other formats. */ /* */ FT_EXPORT( FT_Error ) FT_Set_Renderer( FT_Library library, FT_Renderer renderer, FT_UInt num_params, FT_Parameter* parameters ); /* */ FT_END_HEADER #endif /* __FTRENDER_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftsizes.h ================================================ /***************************************************************************/ /* */ /* ftsizes.h */ /* */ /* FreeType size objects management (specification). */ /* */ /* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /* */ /* Typical application would normally not need to use these functions. */ /* However, they have been placed in a public API for the rare cases */ /* where they are needed. */ /* */ /*************************************************************************/ #ifndef __FTSIZES_H__ #define __FTSIZES_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* sizes_management */ /* */ /* <Title> */ /* Size Management */ /* */ /* <Abstract> */ /* Managing multiple sizes per face. */ /* */ /* <Description> */ /* When creating a new face object (e.g., with @FT_New_Face), an */ /* @FT_Size object is automatically created and used to store all */ /* pixel-size dependent information, available in the `face->size' */ /* field. */ /* */ /* It is however possible to create more sizes for a given face, */ /* mostly in order to manage several character pixel sizes of the */ /* same font family and style. See @FT_New_Size and @FT_Done_Size. */ /* */ /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */ /* modify the contents of the current `active' size; you thus need */ /* to use @FT_Activate_Size to change it. */ /* */ /* 99% of applications won't need the functions provided here, */ /* especially if they use the caching sub-system, so be cautious */ /* when using these. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_New_Size */ /* */ /* <Description> */ /* Create a new size object from a given face object. */ /* */ /* <Input> */ /* face :: A handle to a parent face object. */ /* */ /* <Output> */ /* asize :: A handle to a new size object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* You need to call @FT_Activate_Size in order to select the new size */ /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */ /* @FT_Load_Glyph, @FT_Load_Char, etc. */ /* */ FT_EXPORT( FT_Error ) FT_New_Size( FT_Face face, FT_Size* size ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Done_Size */ /* */ /* <Description> */ /* Discard a given size object. Note that @FT_Done_Face */ /* automatically discards all size objects allocated with */ /* @FT_New_Size. */ /* */ /* <Input> */ /* size :: A handle to a target size object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ FT_EXPORT( FT_Error ) FT_Done_Size( FT_Size size ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Activate_Size */ /* */ /* <Description> */ /* Even though it is possible to create several size objects for a */ /* given face (see @FT_New_Size for details), functions like */ /* @FT_Load_Glyph or @FT_Load_Char only use the one which has been */ /* activated last to determine the `current character pixel size'. */ /* */ /* This function can be used to `activate' a previously created size */ /* object. */ /* */ /* <Input> */ /* size :: A handle to a target size object. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* If `face' is the size's parent face object, this function changes */ /* the value of `face->size' to the input size handle. */ /* */ FT_EXPORT( FT_Error ) FT_Activate_Size( FT_Size size ); /* */ FT_END_HEADER #endif /* __FTSIZES_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftsnames.h ================================================ /***************************************************************************/ /* */ /* ftsnames.h */ /* */ /* Simple interface to access SFNT name tables (which are used */ /* to hold font names, copyright info, notices, etc.) (specification). */ /* */ /* This is _not_ used to retrieve glyph names! */ /* */ /* Copyright 1996-2001, 2002, 2003, 2006, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FT_SFNT_NAMES_H__ #define __FT_SFNT_NAMES_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* sfnt_names */ /* */ /* <Title> */ /* SFNT Names */ /* */ /* <Abstract> */ /* Access the names embedded in TrueType and OpenType files. */ /* */ /* <Description> */ /* The TrueType and OpenType specifications allow the inclusion of */ /* a special `names table' in font files. This table contains */ /* textual (and internationalized) information regarding the font, */ /* like family name, copyright, version, etc. */ /* */ /* The definitions below are used to access them if available. */ /* */ /* Note that this has nothing to do with glyph names! */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Struct> */ /* FT_SfntName */ /* */ /* <Description> */ /* A structure used to model an SFNT `name' table entry. */ /* */ /* <Fields> */ /* platform_id :: The platform ID for `string'. */ /* */ /* encoding_id :: The encoding ID for `string'. */ /* */ /* language_id :: The language ID for `string'. */ /* */ /* name_id :: An identifier for `string'. */ /* */ /* string :: The `name' string. Note that its format differs */ /* depending on the (platform,encoding) pair. It can */ /* be a Pascal String, a UTF-16 one, etc. */ /* */ /* Generally speaking, the string is not */ /* zero-terminated. Please refer to the TrueType */ /* specification for details. */ /* */ /* string_len :: The length of `string' in bytes. */ /* */ /* <Note> */ /* Possible values for `platform_id', `encoding_id', `language_id', */ /* and `name_id' are given in the file `ttnameid.h'. For details */ /* please refer to the TrueType or OpenType specification. */ /* */ /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */ /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */ /* */ typedef struct FT_SfntName_ { FT_UShort platform_id; FT_UShort encoding_id; FT_UShort language_id; FT_UShort name_id; FT_Byte* string; /* this string is *not* null-terminated! */ FT_UInt string_len; /* in bytes */ } FT_SfntName; /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Sfnt_Name_Count */ /* */ /* <Description> */ /* Retrieve the number of name strings in the SFNT `name' table. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* <Return> */ /* The number of strings in the `name' table. */ /* */ FT_EXPORT( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Sfnt_Name */ /* */ /* <Description> */ /* Retrieve a string of the SFNT `name' table for a given index. */ /* */ /* <Input> */ /* face :: A handle to the source face. */ /* */ /* idx :: The index of the `name' string. */ /* */ /* <Output> */ /* aname :: The indexed @FT_SfntName structure. */ /* */ /* <Return> */ /* FreeType error code. 0~means success. */ /* */ /* <Note> */ /* The `string' array returned in the `aname' structure is not */ /* null-terminated. The application should deallocate it if it is no */ /* longer in use. */ /* */ /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */ /* `name' table entries, then do a loop until you get the right */ /* platform, encoding, and name ID. */ /* */ FT_EXPORT( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, FT_UInt idx, FT_SfntName *aname ); /* */ FT_END_HEADER #endif /* __FT_SFNT_NAMES_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftstroke.h ================================================ /***************************************************************************/ /* */ /* ftstroke.h */ /* */ /* FreeType path stroker (specification). */ /* */ /* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FT_STROKE_H__ #define __FT_STROKE_H__ #include <ft2build.h> #include FT_OUTLINE_H #include FT_GLYPH_H FT_BEGIN_HEADER /************************************************************************ * * @section: * glyph_stroker * * @title: * Glyph Stroker * * @abstract: * Generating bordered and stroked glyphs. * * @description: * This component generates stroked outlines of a given vectorial * glyph. It also allows you to retrieve the `outside' and/or the * `inside' borders of the stroke. * * This can be useful to generate `bordered' glyph, i.e., glyphs * displayed with a coloured (and anti-aliased) border around their * shape. */ /************************************************************** * * @type: * FT_Stroker * * @description: * Opaque handler to a path stroker object. */ typedef struct FT_StrokerRec_* FT_Stroker; /************************************************************** * * @enum: * FT_Stroker_LineJoin * * @description: * These values determine how two joining lines are rendered * in a stroker. * * @values: * FT_STROKER_LINEJOIN_ROUND :: * Used to render rounded line joins. Circular arcs are used * to join two lines smoothly. * * FT_STROKER_LINEJOIN_BEVEL :: * Used to render beveled line joins; i.e., the two joining lines * are extended until they intersect. * * FT_STROKER_LINEJOIN_MITER :: * Same as beveled rendering, except that an additional line * break is added if the angle between the two joining lines * is too closed (this is useful to avoid unpleasant spikes * in beveled rendering). */ typedef enum FT_Stroker_LineJoin_ { FT_STROKER_LINEJOIN_ROUND = 0, FT_STROKER_LINEJOIN_BEVEL, FT_STROKER_LINEJOIN_MITER } FT_Stroker_LineJoin; /************************************************************** * * @enum: * FT_Stroker_LineCap * * @description: * These values determine how the end of opened sub-paths are * rendered in a stroke. * * @values: * FT_STROKER_LINECAP_BUTT :: * The end of lines is rendered as a full stop on the last * point itself. * * FT_STROKER_LINECAP_ROUND :: * The end of lines is rendered as a half-circle around the * last point. * * FT_STROKER_LINECAP_SQUARE :: * The end of lines is rendered as a square around the * last point. */ typedef enum FT_Stroker_LineCap_ { FT_STROKER_LINECAP_BUTT = 0, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINECAP_SQUARE } FT_Stroker_LineCap; /************************************************************** * * @enum: * FT_StrokerBorder * * @description: * These values are used to select a given stroke border * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder. * * @values: * FT_STROKER_BORDER_LEFT :: * Select the left border, relative to the drawing direction. * * FT_STROKER_BORDER_RIGHT :: * Select the right border, relative to the drawing direction. * * @note: * Applications are generally interested in the `inside' and `outside' * borders. However, there is no direct mapping between these and the * `left' and `right' ones, since this really depends on the glyph's * drawing orientation, which varies between font formats. * * You can however use @FT_Outline_GetInsideBorder and * @FT_Outline_GetOutsideBorder to get these. */ typedef enum FT_StrokerBorder_ { FT_STROKER_BORDER_LEFT = 0, FT_STROKER_BORDER_RIGHT } FT_StrokerBorder; /************************************************************** * * @function: * FT_Outline_GetInsideBorder * * @description: * Retrieve the @FT_StrokerBorder value corresponding to the * `inside' borders of a given outline. * * @input: * outline :: * The source outline handle. * * @return: * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid * outlines. */ FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetInsideBorder( FT_Outline* outline ); /************************************************************** * * @function: * FT_Outline_GetOutsideBorder * * @description: * Retrieve the @FT_StrokerBorder value corresponding to the * `outside' borders of a given outline. * * @input: * outline :: * The source outline handle. * * @return: * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid * outlines. */ FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetOutsideBorder( FT_Outline* outline ); /************************************************************** * * @function: * FT_Stroker_New * * @description: * Create a new stroker object. * * @input: * library :: * FreeType library handle. * * @output: * astroker :: * A new stroker object handle. NULL in case of error. * * @return: * FreeType error code. 0~means success. */ FT_EXPORT( FT_Error ) FT_Stroker_New( FT_Library library, FT_Stroker *astroker ); /************************************************************** * * @function: * FT_Stroker_Set * * @description: * Reset a stroker object's attributes. * * @input: * stroker :: * The target stroker handle. * * radius :: * The border radius. * * line_cap :: * The line cap style. * * line_join :: * The line join style. * * miter_limit :: * The miter limit for the FT_STROKER_LINEJOIN_MITER style, * expressed as 16.16 fixed point value. * * @note: * The radius is expressed in the same units as the outline * coordinates. */ FT_EXPORT( void ) FT_Stroker_Set( FT_Stroker stroker, FT_Fixed radius, FT_Stroker_LineCap line_cap, FT_Stroker_LineJoin line_join, FT_Fixed miter_limit ); /************************************************************** * * @function: * FT_Stroker_Rewind * * @description: * Reset a stroker object without changing its attributes. * You should call this function before beginning a new * series of calls to @FT_Stroker_BeginSubPath or * @FT_Stroker_EndSubPath. * * @input: * stroker :: * The target stroker handle. */ FT_EXPORT( void ) FT_Stroker_Rewind( FT_Stroker stroker ); /************************************************************** * * @function: * FT_Stroker_ParseOutline * * @description: * A convenience function used to parse a whole outline with * the stroker. The resulting outline(s) can be retrieved * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export. * * @input: * stroker :: * The target stroker handle. * * outline :: * The source outline. * * opened :: * A boolean. If~1, the outline is treated as an open path instead * of a closed one. * * @return: * FreeType error code. 0~means success. * * @note: * If `opened' is~0 (the default), the outline is treated as a closed * path, and the stroker generates two distinct `border' outlines. * * If `opened' is~1, the outline is processed as an open path, and the * stroker generates a single `stroke' outline. * * This function calls @FT_Stroker_Rewind automatically. */ FT_EXPORT( FT_Error ) FT_Stroker_ParseOutline( FT_Stroker stroker, FT_Outline* outline, FT_Bool opened ); /************************************************************** * * @function: * FT_Stroker_BeginSubPath * * @description: * Start a new sub-path in the stroker. * * @input: * stroker :: * The target stroker handle. * * to :: * A pointer to the start vector. * * open :: * A boolean. If~1, the sub-path is treated as an open one. * * @return: * FreeType error code. 0~means success. * * @note: * This function is useful when you need to stroke a path that is * not stored as an @FT_Outline object. */ FT_EXPORT( FT_Error ) FT_Stroker_BeginSubPath( FT_Stroker stroker, FT_Vector* to, FT_Bool open ); /************************************************************** * * @function: * FT_Stroker_EndSubPath * * @description: * Close the current sub-path in the stroker. * * @input: * stroker :: * The target stroker handle. * * @return: * FreeType error code. 0~means success. * * @note: * You should call this function after @FT_Stroker_BeginSubPath. * If the subpath was not `opened', this function `draws' a * single line segment to the start position when needed. */ FT_EXPORT( FT_Error ) FT_Stroker_EndSubPath( FT_Stroker stroker ); /************************************************************** * * @function: * FT_Stroker_LineTo * * @description: * `Draw' a single line segment in the stroker's current sub-path, * from the last position. * * @input: * stroker :: * The target stroker handle. * * to :: * A pointer to the destination point. * * @return: * FreeType error code. 0~means success. * * @note: * You should call this function between @FT_Stroker_BeginSubPath and * @FT_Stroker_EndSubPath. */ FT_EXPORT( FT_Error ) FT_Stroker_LineTo( FT_Stroker stroker, FT_Vector* to ); /************************************************************** * * @function: * FT_Stroker_ConicTo * * @description: * `Draw' a single quadratic Bézier in the stroker's current sub-path, * from the last position. * * @input: * stroker :: * The target stroker handle. * * control :: * A pointer to a Bézier control point. * * to :: * A pointer to the destination point. * * @return: * FreeType error code. 0~means success. * * @note: * You should call this function between @FT_Stroker_BeginSubPath and * @FT_Stroker_EndSubPath. */ FT_EXPORT( FT_Error ) FT_Stroker_ConicTo( FT_Stroker stroker, FT_Vector* control, FT_Vector* to ); /************************************************************** * * @function: * FT_Stroker_CubicTo * * @description: * `Draw' a single cubic Bézier in the stroker's current sub-path, * from the last position. * * @input: * stroker :: * The target stroker handle. * * control1 :: * A pointer to the first Bézier control point. * * control2 :: * A pointer to second Bézier control point. * * to :: * A pointer to the destination point. * * @return: * FreeType error code. 0~means success. * * @note: * You should call this function between @FT_Stroker_BeginSubPath and * @FT_Stroker_EndSubPath. */ FT_EXPORT( FT_Error ) FT_Stroker_CubicTo( FT_Stroker stroker, FT_Vector* control1, FT_Vector* control2, FT_Vector* to ); /************************************************************** * * @function: * FT_Stroker_GetBorderCounts * * @description: * Call this function once you have finished parsing your paths * with the stroker. It returns the number of points and * contours necessary to export one of the `border' or `stroke' * outlines generated by the stroker. * * @input: * stroker :: * The target stroker handle. * * border :: * The border index. * * @output: * anum_points :: * The number of points. * * anum_contours :: * The number of contours. * * @return: * FreeType error code. 0~means success. * * @note: * When an outline, or a sub-path, is `closed', the stroker generates * two independent `border' outlines, named `left' and `right'. * * When the outline, or a sub-path, is `opened', the stroker merges * the `border' outlines with caps. The `left' border receives all * points, while the `right' border becomes empty. * * Use the function @FT_Stroker_GetCounts instead if you want to * retrieve the counts associated to both borders. */ FT_EXPORT( FT_Error ) FT_Stroker_GetBorderCounts( FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours ); /************************************************************** * * @function: * FT_Stroker_ExportBorder * * @description: * Call this function after @FT_Stroker_GetBorderCounts to * export the corresponding border to your own @FT_Outline * structure. * * Note that this function appends the border points and * contours to your outline, but does not try to resize its * arrays. * * @input: * stroker :: * The target stroker handle. * * border :: * The border index. * * outline :: * The target outline handle. * * @note: * Always call this function after @FT_Stroker_GetBorderCounts to * get sure that there is enough room in your @FT_Outline object to * receive all new data. * * When an outline, or a sub-path, is `closed', the stroker generates * two independent `border' outlines, named `left' and `right' * * When the outline, or a sub-path, is `opened', the stroker merges * the `border' outlines with caps. The `left' border receives all * points, while the `right' border becomes empty. * * Use the function @FT_Stroker_Export instead if you want to * retrieve all borders at once. */ FT_EXPORT( void ) FT_Stroker_ExportBorder( FT_Stroker stroker, FT_StrokerBorder border, FT_Outline* outline ); /************************************************************** * * @function: * FT_Stroker_GetCounts * * @description: * Call this function once you have finished parsing your paths * with the stroker. It returns the number of points and * contours necessary to export all points/borders from the stroked * outline/path. * * @input: * stroker :: * The target stroker handle. * * @output: * anum_points :: * The number of points. * * anum_contours :: * The number of contours. * * @return: * FreeType error code. 0~means success. */ FT_EXPORT( FT_Error ) FT_Stroker_GetCounts( FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours ); /************************************************************** * * @function: * FT_Stroker_Export * * @description: * Call this function after @FT_Stroker_GetBorderCounts to * export all borders to your own @FT_Outline structure. * * Note that this function appends the border points and * contours to your outline, but does not try to resize its * arrays. * * @input: * stroker :: * The target stroker handle. * * outline :: * The target outline handle. */ FT_EXPORT( void ) FT_Stroker_Export( FT_Stroker stroker, FT_Outline* outline ); /************************************************************** * * @function: * FT_Stroker_Done * * @description: * Destroy a stroker object. * * @input: * stroker :: * A stroker handle. Can be NULL. */ FT_EXPORT( void ) FT_Stroker_Done( FT_Stroker stroker ); /************************************************************** * * @function: * FT_Glyph_Stroke * * @description: * Stroke a given outline glyph object with a given stroker. * * @inout: * pglyph :: * Source glyph handle on input, new glyph handle on output. * * @input: * stroker :: * A stroker handle. * * destroy :: * A Boolean. If~1, the source glyph object is destroyed * on success. * * @return: * FreeType error code. 0~means success. * * @note: * The source glyph is untouched in case of error. */ FT_EXPORT( FT_Error ) FT_Glyph_Stroke( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy ); /************************************************************** * * @function: * FT_Glyph_StrokeBorder * * @description: * Stroke a given outline glyph object with a given stroker, but * only return either its inside or outside border. * * @inout: * pglyph :: * Source glyph handle on input, new glyph handle on output. * * @input: * stroker :: * A stroker handle. * * inside :: * A Boolean. If~1, return the inside border, otherwise * the outside border. * * destroy :: * A Boolean. If~1, the source glyph object is destroyed * on success. * * @return: * FreeType error code. 0~means success. * * @note: * The source glyph is untouched in case of error. */ FT_EXPORT( FT_Error ) FT_Glyph_StrokeBorder( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy ); /* */ FT_END_HEADER #endif /* __FT_STROKE_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftsynth.h ================================================ /***************************************************************************/ /* */ /* ftsynth.h */ /* */ /* FreeType synthesizing code for emboldening and slanting */ /* (specification). */ /* */ /* Copyright 2000-2001, 2003, 2006, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /********* *********/ /********* WARNING, THIS IS ALPHA CODE! THIS API *********/ /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/ /********* FREETYPE DEVELOPMENT TEAM *********/ /********* *********/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* Main reason for not lifting the functions in this module to a */ /* `standard' API is that the used parameters for emboldening and */ /* slanting are not configurable. Consider the functions as a */ /* code resource which should be copied into the application and */ /* adapted to the particular needs. */ #ifndef __FTSYNTH_H__ #define __FTSYNTH_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /* Embolden a glyph by a `reasonable' value (which is highly a matter of */ /* taste). This function is actually a convenience function, providing */ /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */ /* */ /* For emboldened outlines the metrics are estimates only; if you need */ /* precise values you should call @FT_Outline_Get_CBox. */ FT_EXPORT( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); /* Slant an outline glyph to the right by about 12 degrees. */ FT_EXPORT( void ) FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); /* */ FT_END_HEADER #endif /* __FTSYNTH_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftsystem.h ================================================ /***************************************************************************/ /* */ /* ftsystem.h */ /* */ /* FreeType low-level system interface definition (specification). */ /* */ /* Copyright 1996-2001, 2002, 2005 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTSYSTEM_H__ #define __FTSYSTEM_H__ #include <ft2build.h> FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* system_interface */ /* */ /* <Title> */ /* System Interface */ /* */ /* <Abstract> */ /* How FreeType manages memory and i/o. */ /* */ /* <Description> */ /* This section contains various definitions related to memory */ /* management and i/o access. You need to understand this */ /* information if you want to use a custom memory manager or you own */ /* i/o streams. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* M E M O R Y M A N A G E M E N T */ /* */ /*************************************************************************/ /************************************************************************* * * @type: * FT_Memory * * @description: * A handle to a given memory manager object, defined with an * @FT_MemoryRec structure. * */ typedef struct FT_MemoryRec_* FT_Memory; /************************************************************************* * * @functype: * FT_Alloc_Func * * @description: * A function used to allocate `size' bytes from `memory'. * * @input: * memory :: * A handle to the source memory manager. * * size :: * The size in bytes to allocate. * * @return: * Address of new memory block. 0~in case of failure. * */ typedef void* (*FT_Alloc_Func)( FT_Memory memory, long size ); /************************************************************************* * * @functype: * FT_Free_Func * * @description: * A function used to release a given block of memory. * * @input: * memory :: * A handle to the source memory manager. * * block :: * The address of the target memory block. * */ typedef void (*FT_Free_Func)( FT_Memory memory, void* block ); /************************************************************************* * * @functype: * FT_Realloc_Func * * @description: * A function used to re-allocate a given block of memory. * * @input: * memory :: * A handle to the source memory manager. * * cur_size :: * The block's current size in bytes. * * new_size :: * The block's requested new size. * * block :: * The block's current address. * * @return: * New block address. 0~in case of memory shortage. * * @note: * In case of error, the old block must still be available. * */ typedef void* (*FT_Realloc_Func)( FT_Memory memory, long cur_size, long new_size, void* block ); /************************************************************************* * * @struct: * FT_MemoryRec * * @description: * A structure used to describe a given memory manager to FreeType~2. * * @fields: * user :: * A generic typeless pointer for user data. * * alloc :: * A pointer type to an allocation function. * * free :: * A pointer type to an memory freeing function. * * realloc :: * A pointer type to a reallocation function. * */ struct FT_MemoryRec_ { void* user; FT_Alloc_Func alloc; FT_Free_Func free; FT_Realloc_Func realloc; }; /*************************************************************************/ /* */ /* I / O M A N A G E M E N T */ /* */ /*************************************************************************/ /************************************************************************* * * @type: * FT_Stream * * @description: * A handle to an input stream. * */ typedef struct FT_StreamRec_* FT_Stream; /************************************************************************* * * @struct: * FT_StreamDesc * * @description: * A union type used to store either a long or a pointer. This is used * to store a file descriptor or a `FILE*' in an input stream. * */ typedef union FT_StreamDesc_ { long value; void* pointer; } FT_StreamDesc; /************************************************************************* * * @functype: * FT_Stream_IoFunc * * @description: * A function used to seek and read data from a given input stream. * * @input: * stream :: * A handle to the source stream. * * offset :: * The offset of read in stream (always from start). * * buffer :: * The address of the read buffer. * * count :: * The number of bytes to read from the stream. * * @return: * The number of bytes effectively read by the stream. * * @note: * This function might be called to perform a seek or skip operation * with a `count' of~0. * */ typedef unsigned long (*FT_Stream_IoFunc)( FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count ); /************************************************************************* * * @functype: * FT_Stream_CloseFunc * * @description: * A function used to close a given input stream. * * @input: * stream :: * A handle to the target stream. * */ typedef void (*FT_Stream_CloseFunc)( FT_Stream stream ); /************************************************************************* * * @struct: * FT_StreamRec * * @description: * A structure used to describe an input stream. * * @input: * base :: * For memory-based streams, this is the address of the first stream * byte in memory. This field should always be set to NULL for * disk-based streams. * * size :: * The stream size in bytes. * * pos :: * The current position within the stream. * * descriptor :: * This field is a union that can hold an integer or a pointer. It is * used by stream implementations to store file descriptors or `FILE*' * pointers. * * pathname :: * This field is completely ignored by FreeType. However, it is often * useful during debugging to use it to store the stream's filename * (where available). * * read :: * The stream's input function. * * close :: * The stream;s close function. * * memory :: * The memory manager to use to preload frames. This is set * internally by FreeType and shouldn't be touched by stream * implementations. * * cursor :: * This field is set and used internally by FreeType when parsing * frames. * * limit :: * This field is set and used internally by FreeType when parsing * frames. * */ typedef struct FT_StreamRec_ { unsigned char* base; unsigned long size; unsigned long pos; FT_StreamDesc descriptor; FT_StreamDesc pathname; FT_Stream_IoFunc read; FT_Stream_CloseFunc close; FT_Memory memory; unsigned char* cursor; unsigned char* limit; } FT_StreamRec; /* */ FT_END_HEADER #endif /* __FTSYSTEM_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/fttrigon.h ================================================ /***************************************************************************/ /* */ /* fttrigon.h */ /* */ /* FreeType trigonometric functions (specification). */ /* */ /* Copyright 2001, 2003, 2005, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTTRIGON_H__ #define __FTTRIGON_H__ #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* computations */ /* */ /*************************************************************************/ /************************************************************************* * * @type: * FT_Angle * * @description: * This type is used to model angle values in FreeType. Note that the * angle is a 16.16 fixed float value expressed in degrees. * */ typedef FT_Fixed FT_Angle; /************************************************************************* * * @macro: * FT_ANGLE_PI * * @description: * The angle pi expressed in @FT_Angle units. * */ #define FT_ANGLE_PI ( 180L << 16 ) /************************************************************************* * * @macro: * FT_ANGLE_2PI * * @description: * The angle 2*pi expressed in @FT_Angle units. * */ #define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) /************************************************************************* * * @macro: * FT_ANGLE_PI2 * * @description: * The angle pi/2 expressed in @FT_Angle units. * */ #define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) /************************************************************************* * * @macro: * FT_ANGLE_PI4 * * @description: * The angle pi/4 expressed in @FT_Angle units. * */ #define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) /************************************************************************* * * @function: * FT_Sin * * @description: * Return the sinus of a given angle in fixed point format. * * @input: * angle :: * The input angle. * * @return: * The sinus value. * * @note: * If you need both the sinus and cosinus for a given angle, use the * function @FT_Vector_Unit. * */ FT_EXPORT( FT_Fixed ) FT_Sin( FT_Angle angle ); /************************************************************************* * * @function: * FT_Cos * * @description: * Return the cosinus of a given angle in fixed point format. * * @input: * angle :: * The input angle. * * @return: * The cosinus value. * * @note: * If you need both the sinus and cosinus for a given angle, use the * function @FT_Vector_Unit. * */ FT_EXPORT( FT_Fixed ) FT_Cos( FT_Angle angle ); /************************************************************************* * * @function: * FT_Tan * * @description: * Return the tangent of a given angle in fixed point format. * * @input: * angle :: * The input angle. * * @return: * The tangent value. * */ FT_EXPORT( FT_Fixed ) FT_Tan( FT_Angle angle ); /************************************************************************* * * @function: * FT_Atan2 * * @description: * Return the arc-tangent corresponding to a given vector (x,y) in * the 2d plane. * * @input: * x :: * The horizontal vector coordinate. * * y :: * The vertical vector coordinate. * * @return: * The arc-tangent value (i.e. angle). * */ FT_EXPORT( FT_Angle ) FT_Atan2( FT_Fixed x, FT_Fixed y ); /************************************************************************* * * @function: * FT_Angle_Diff * * @description: * Return the difference between two angles. The result is always * constrained to the ]-PI..PI] interval. * * @input: * angle1 :: * First angle. * * angle2 :: * Second angle. * * @return: * Constrained value of `value2-value1'. * */ FT_EXPORT( FT_Angle ) FT_Angle_Diff( FT_Angle angle1, FT_Angle angle2 ); /************************************************************************* * * @function: * FT_Vector_Unit * * @description: * Return the unit vector corresponding to a given angle. After the * call, the value of `vec.x' will be `sin(angle)', and the value of * `vec.y' will be `cos(angle)'. * * This function is useful to retrieve both the sinus and cosinus of a * given angle quickly. * * @output: * vec :: * The address of target vector. * * @input: * angle :: * The address of angle. * */ FT_EXPORT( void ) FT_Vector_Unit( FT_Vector* vec, FT_Angle angle ); /************************************************************************* * * @function: * FT_Vector_Rotate * * @description: * Rotate a vector by a given angle. * * @inout: * vec :: * The address of target vector. * * @input: * angle :: * The address of angle. * */ FT_EXPORT( void ) FT_Vector_Rotate( FT_Vector* vec, FT_Angle angle ); /************************************************************************* * * @function: * FT_Vector_Length * * @description: * Return the length of a given vector. * * @input: * vec :: * The address of target vector. * * @return: * The vector length, expressed in the same units that the original * vector coordinates. * */ FT_EXPORT( FT_Fixed ) FT_Vector_Length( FT_Vector* vec ); /************************************************************************* * * @function: * FT_Vector_Polarize * * @description: * Compute both the length and angle of a given vector. * * @input: * vec :: * The address of source vector. * * @output: * length :: * The vector length. * * angle :: * The vector angle. * */ FT_EXPORT( void ) FT_Vector_Polarize( FT_Vector* vec, FT_Fixed *length, FT_Angle *angle ); /************************************************************************* * * @function: * FT_Vector_From_Polar * * @description: * Compute vector coordinates from a length and angle. * * @output: * vec :: * The address of source vector. * * @input: * length :: * The vector length. * * angle :: * The vector angle. * */ FT_EXPORT( void ) FT_Vector_From_Polar( FT_Vector* vec, FT_Fixed length, FT_Angle angle ); /* */ FT_END_HEADER #endif /* __FTTRIGON_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/fttypes.h ================================================ /***************************************************************************/ /* */ /* fttypes.h */ /* */ /* FreeType simple types definitions (specification only). */ /* */ /* Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTTYPES_H__ #define __FTTYPES_H__ #include <ft2build.h> #include FT_CONFIG_CONFIG_H #include FT_SYSTEM_H #include FT_IMAGE_H #include <stddef.h> FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* basic_types */ /* */ /* <Title> */ /* Basic Data Types */ /* */ /* <Abstract> */ /* The basic data types defined by the library. */ /* */ /* <Description> */ /* This section contains the basic data types defined by FreeType~2, */ /* ranging from simple scalar types to bitmap descriptors. More */ /* font-specific structures are defined in a different section. */ /* */ /* <Order> */ /* FT_Byte */ /* FT_Bytes */ /* FT_Char */ /* FT_Int */ /* FT_UInt */ /* FT_Int16 */ /* FT_UInt16 */ /* FT_Int32 */ /* FT_UInt32 */ /* FT_Short */ /* FT_UShort */ /* FT_Long */ /* FT_ULong */ /* FT_Bool */ /* FT_Offset */ /* FT_PtrDist */ /* FT_String */ /* FT_Tag */ /* FT_Error */ /* FT_Fixed */ /* FT_Pointer */ /* FT_Pos */ /* FT_Vector */ /* FT_BBox */ /* FT_Matrix */ /* FT_FWord */ /* FT_UFWord */ /* FT_F2Dot14 */ /* FT_UnitVector */ /* FT_F26Dot6 */ /* */ /* */ /* FT_Generic */ /* FT_Generic_Finalizer */ /* */ /* FT_Bitmap */ /* FT_Pixel_Mode */ /* FT_Palette_Mode */ /* FT_Glyph_Format */ /* FT_IMAGE_TAG */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_Bool */ /* */ /* <Description> */ /* A typedef of unsigned char, used for simple booleans. As usual, */ /* values 1 and~0 represent true and false, respectively. */ /* */ typedef unsigned char FT_Bool; /*************************************************************************/ /* */ /* <Type> */ /* FT_FWord */ /* */ /* <Description> */ /* A signed 16-bit integer used to store a distance in original font */ /* units. */ /* */ typedef signed short FT_FWord; /* distance in FUnits */ /*************************************************************************/ /* */ /* <Type> */ /* FT_UFWord */ /* */ /* <Description> */ /* An unsigned 16-bit integer used to store a distance in original */ /* font units. */ /* */ typedef unsigned short FT_UFWord; /* unsigned distance */ /*************************************************************************/ /* */ /* <Type> */ /* FT_Char */ /* */ /* <Description> */ /* A simple typedef for the _signed_ char type. */ /* */ typedef signed char FT_Char; /*************************************************************************/ /* */ /* <Type> */ /* FT_Byte */ /* */ /* <Description> */ /* A simple typedef for the _unsigned_ char type. */ /* */ typedef unsigned char FT_Byte; /*************************************************************************/ /* */ /* <Type> */ /* FT_Bytes */ /* */ /* <Description> */ /* A typedef for constant memory areas. */ /* */ typedef const FT_Byte* FT_Bytes; /*************************************************************************/ /* */ /* <Type> */ /* FT_Tag */ /* */ /* <Description> */ /* A typedef for 32-bit tags (as used in the SFNT format). */ /* */ typedef FT_UInt32 FT_Tag; /*************************************************************************/ /* */ /* <Type> */ /* FT_String */ /* */ /* <Description> */ /* A simple typedef for the char type, usually used for strings. */ /* */ typedef char FT_String; /*************************************************************************/ /* */ /* <Type> */ /* FT_Short */ /* */ /* <Description> */ /* A typedef for signed short. */ /* */ typedef signed short FT_Short; /*************************************************************************/ /* */ /* <Type> */ /* FT_UShort */ /* */ /* <Description> */ /* A typedef for unsigned short. */ /* */ typedef unsigned short FT_UShort; /*************************************************************************/ /* */ /* <Type> */ /* FT_Int */ /* */ /* <Description> */ /* A typedef for the int type. */ /* */ typedef signed int FT_Int; /*************************************************************************/ /* */ /* <Type> */ /* FT_UInt */ /* */ /* <Description> */ /* A typedef for the unsigned int type. */ /* */ typedef unsigned int FT_UInt; /*************************************************************************/ /* */ /* <Type> */ /* FT_Long */ /* */ /* <Description> */ /* A typedef for signed long. */ /* */ typedef signed long FT_Long; /*************************************************************************/ /* */ /* <Type> */ /* FT_ULong */ /* */ /* <Description> */ /* A typedef for unsigned long. */ /* */ typedef unsigned long FT_ULong; /*************************************************************************/ /* */ /* <Type> */ /* FT_F2Dot14 */ /* */ /* <Description> */ /* A signed 2.14 fixed float type used for unit vectors. */ /* */ typedef signed short FT_F2Dot14; /*************************************************************************/ /* */ /* <Type> */ /* FT_F26Dot6 */ /* */ /* <Description> */ /* A signed 26.6 fixed float type used for vectorial pixel */ /* coordinates. */ /* */ typedef signed long FT_F26Dot6; /*************************************************************************/ /* */ /* <Type> */ /* FT_Fixed */ /* */ /* <Description> */ /* This type is used to store 16.16 fixed float values, like scaling */ /* values or matrix coefficients. */ /* */ typedef signed long FT_Fixed; /*************************************************************************/ /* */ /* <Type> */ /* FT_Error */ /* */ /* <Description> */ /* The FreeType error code type. A value of~0 is always interpreted */ /* as a successful operation. */ /* */ typedef int FT_Error; /*************************************************************************/ /* */ /* <Type> */ /* FT_Pointer */ /* */ /* <Description> */ /* A simple typedef for a typeless pointer. */ /* */ typedef void* FT_Pointer; /*************************************************************************/ /* */ /* <Type> */ /* FT_Offset */ /* */ /* <Description> */ /* This is equivalent to the ANSI~C `size_t' type, i.e., the largest */ /* _unsigned_ integer type used to express a file size or position, */ /* or a memory block size. */ /* */ typedef size_t FT_Offset; /*************************************************************************/ /* */ /* <Type> */ /* FT_PtrDist */ /* */ /* <Description> */ /* This is equivalent to the ANSI~C `ptrdiff_t' type, i.e., the */ /* largest _signed_ integer type used to express the distance */ /* between two pointers. */ /* */ typedef ft_ptrdiff_t FT_PtrDist; /*************************************************************************/ /* */ /* <Struct> */ /* FT_UnitVector */ /* */ /* <Description> */ /* A simple structure used to store a 2D vector unit vector. Uses */ /* FT_F2Dot14 types. */ /* */ /* <Fields> */ /* x :: Horizontal coordinate. */ /* */ /* y :: Vertical coordinate. */ /* */ typedef struct FT_UnitVector_ { FT_F2Dot14 x; FT_F2Dot14 y; } FT_UnitVector; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Matrix */ /* */ /* <Description> */ /* A simple structure used to store a 2x2 matrix. Coefficients are */ /* in 16.16 fixed float format. The computation performed is: */ /* */ /* { */ /* x' = x*xx + y*xy */ /* y' = x*yx + y*yy */ /* } */ /* */ /* <Fields> */ /* xx :: Matrix coefficient. */ /* */ /* xy :: Matrix coefficient. */ /* */ /* yx :: Matrix coefficient. */ /* */ /* yy :: Matrix coefficient. */ /* */ typedef struct FT_Matrix_ { FT_Fixed xx, xy; FT_Fixed yx, yy; } FT_Matrix; /*************************************************************************/ /* */ /* <Struct> */ /* FT_Data */ /* */ /* <Description> */ /* Read-only binary data represented as a pointer and a length. */ /* */ /* <Fields> */ /* pointer :: The data. */ /* */ /* length :: The length of the data in bytes. */ /* */ typedef struct FT_Data_ { const FT_Byte* pointer; FT_Int length; } FT_Data; /*************************************************************************/ /* */ /* <FuncType> */ /* FT_Generic_Finalizer */ /* */ /* <Description> */ /* Describe a function used to destroy the `client' data of any */ /* FreeType object. See the description of the @FT_Generic type for */ /* details of usage. */ /* */ /* <Input> */ /* The address of the FreeType object which is under finalization. */ /* Its client data is accessed through its `generic' field. */ /* */ typedef void (*FT_Generic_Finalizer)(void* object); /*************************************************************************/ /* */ /* <Struct> */ /* FT_Generic */ /* */ /* <Description> */ /* Client applications often need to associate their own data to a */ /* variety of FreeType core objects. For example, a text layout API */ /* might want to associate a glyph cache to a given size object. */ /* */ /* Most FreeType object contains a `generic' field, of type */ /* FT_Generic, which usage is left to client applications and font */ /* servers. */ /* */ /* It can be used to store a pointer to client-specific data, as well */ /* as the address of a `finalizer' function, which will be called by */ /* FreeType when the object is destroyed (for example, the previous */ /* client example would put the address of the glyph cache destructor */ /* in the `finalizer' field). */ /* */ /* <Fields> */ /* data :: A typeless pointer to any client-specified data. This */ /* field is completely ignored by the FreeType library. */ /* */ /* finalizer :: A pointer to a `generic finalizer' function, which */ /* will be called when the object is destroyed. If this */ /* field is set to NULL, no code will be called. */ /* */ typedef struct FT_Generic_ { void* data; FT_Generic_Finalizer finalizer; } FT_Generic; /*************************************************************************/ /* */ /* <Macro> */ /* FT_MAKE_TAG */ /* */ /* <Description> */ /* This macro converts four-letter tags which are used to label */ /* TrueType tables into an unsigned long to be used within FreeType. */ /* */ /* <Note> */ /* The produced values *must* be 32-bit integers. Don't redefine */ /* this macro. */ /* */ #define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ (FT_Tag) \ ( ( (FT_ULong)_x1 << 24 ) | \ ( (FT_ULong)_x2 << 16 ) | \ ( (FT_ULong)_x3 << 8 ) | \ (FT_ULong)_x4 ) /*************************************************************************/ /*************************************************************************/ /* */ /* L I S T M A N A G E M E N T */ /* */ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Section> */ /* list_processing */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Type> */ /* FT_ListNode */ /* */ /* <Description> */ /* Many elements and objects in FreeType are listed through an */ /* @FT_List record (see @FT_ListRec). As its name suggests, an */ /* FT_ListNode is a handle to a single list element. */ /* */ typedef struct FT_ListNodeRec_* FT_ListNode; /*************************************************************************/ /* */ /* <Type> */ /* FT_List */ /* */ /* <Description> */ /* A handle to a list record (see @FT_ListRec). */ /* */ typedef struct FT_ListRec_* FT_List; /*************************************************************************/ /* */ /* <Struct> */ /* FT_ListNodeRec */ /* */ /* <Description> */ /* A structure used to hold a single list element. */ /* */ /* <Fields> */ /* prev :: The previous element in the list. NULL if first. */ /* */ /* next :: The next element in the list. NULL if last. */ /* */ /* data :: A typeless pointer to the listed object. */ /* */ typedef struct FT_ListNodeRec_ { FT_ListNode prev; FT_ListNode next; void* data; } FT_ListNodeRec; /*************************************************************************/ /* */ /* <Struct> */ /* FT_ListRec */ /* */ /* <Description> */ /* A structure used to hold a simple doubly-linked list. These are */ /* used in many parts of FreeType. */ /* */ /* <Fields> */ /* head :: The head (first element) of doubly-linked list. */ /* */ /* tail :: The tail (last element) of doubly-linked list. */ /* */ typedef struct FT_ListRec_ { FT_ListNode head; FT_ListNode tail; } FT_ListRec; /* */ #define FT_IS_EMPTY( list ) ( (list).head == 0 ) /* return base error code (without module-specific prefix) */ #define FT_ERROR_BASE( x ) ( (x) & 0xFF ) /* return module error code */ #define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U ) #define FT_BOOL( x ) ( (FT_Bool)( x ) ) FT_END_HEADER #endif /* __FTTYPES_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftwinfnt.h ================================================ /***************************************************************************/ /* */ /* ftwinfnt.h */ /* */ /* FreeType API for accessing Windows fnt-specific data. */ /* */ /* Copyright 2003, 2004, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTWINFNT_H__ #define __FTWINFNT_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* winfnt_fonts */ /* */ /* <Title> */ /* Window FNT Files */ /* */ /* <Abstract> */ /* Windows FNT specific API. */ /* */ /* <Description> */ /* This section contains the declaration of Windows FNT specific */ /* functions. */ /* */ /*************************************************************************/ /************************************************************************* * * @enum: * FT_WinFNT_ID_XXX * * @description: * A list of valid values for the `charset' byte in * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX * encodings (except for cp1361) can be found at ftp://ftp.unicode.org * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT. * * @values: * FT_WinFNT_ID_DEFAULT :: * This is used for font enumeration and font creation as a * `don't care' value. Valid font files don't contain this value. * When querying for information about the character set of the font * that is currently selected into a specified device context, this * return value (of the related Windows API) simply denotes failure. * * FT_WinFNT_ID_SYMBOL :: * There is no known mapping table available. * * FT_WinFNT_ID_MAC :: * Mac Roman encoding. * * FT_WinFNT_ID_OEM :: * From Michael Pöttgen <michael@poettgen.de>: * * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM * is used for the charset of vector fonts, like `modern.fon', * `roman.fon', and `script.fon' on Windows. * * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value * specifies a character set that is operating-system dependent. * * The `IFIMETRICS' documentation from the `Windows Driver * Development Kit' says: This font supports an OEM-specific * character set. The OEM character set is system dependent. * * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the * second default codepage that most international versions of * Windows have. It is one of the OEM codepages from * * http://www.microsoft.com/globaldev/reference/cphome.mspx, * * and is used for the `DOS boxes', to support legacy applications. * A German Windows version for example usually uses ANSI codepage * 1252 and OEM codepage 850. * * FT_WinFNT_ID_CP874 :: * A superset of Thai TIS 620 and ISO 8859-11. * * FT_WinFNT_ID_CP932 :: * A superset of Japanese Shift-JIS (with minor deviations). * * FT_WinFNT_ID_CP936 :: * A superset of simplified Chinese GB 2312-1980 (with different * ordering and minor deviations). * * FT_WinFNT_ID_CP949 :: * A superset of Korean Hangul KS~C 5601-1987 (with different * ordering and minor deviations). * * FT_WinFNT_ID_CP950 :: * A superset of traditional Chinese Big~5 ETen (with different * ordering and minor deviations). * * FT_WinFNT_ID_CP1250 :: * A superset of East European ISO 8859-2 (with slightly different * ordering). * * FT_WinFNT_ID_CP1251 :: * A superset of Russian ISO 8859-5 (with different ordering). * * FT_WinFNT_ID_CP1252 :: * ANSI encoding. A superset of ISO 8859-1. * * FT_WinFNT_ID_CP1253 :: * A superset of Greek ISO 8859-7 (with minor modifications). * * FT_WinFNT_ID_CP1254 :: * A superset of Turkish ISO 8859-9. * * FT_WinFNT_ID_CP1255 :: * A superset of Hebrew ISO 8859-8 (with some modifications). * * FT_WinFNT_ID_CP1256 :: * A superset of Arabic ISO 8859-6 (with different ordering). * * FT_WinFNT_ID_CP1257 :: * A superset of Baltic ISO 8859-13 (with some deviations). * * FT_WinFNT_ID_CP1258 :: * For Vietnamese. This encoding doesn't cover all necessary * characters. * * FT_WinFNT_ID_CP1361 :: * Korean (Johab). */ #define FT_WinFNT_ID_CP1252 0 #define FT_WinFNT_ID_DEFAULT 1 #define FT_WinFNT_ID_SYMBOL 2 #define FT_WinFNT_ID_MAC 77 #define FT_WinFNT_ID_CP932 128 #define FT_WinFNT_ID_CP949 129 #define FT_WinFNT_ID_CP1361 130 #define FT_WinFNT_ID_CP936 134 #define FT_WinFNT_ID_CP950 136 #define FT_WinFNT_ID_CP1253 161 #define FT_WinFNT_ID_CP1254 162 #define FT_WinFNT_ID_CP1258 163 #define FT_WinFNT_ID_CP1255 177 #define FT_WinFNT_ID_CP1256 178 #define FT_WinFNT_ID_CP1257 186 #define FT_WinFNT_ID_CP1251 204 #define FT_WinFNT_ID_CP874 222 #define FT_WinFNT_ID_CP1250 238 #define FT_WinFNT_ID_OEM 255 /*************************************************************************/ /* */ /* <Struct> */ /* FT_WinFNT_HeaderRec */ /* */ /* <Description> */ /* Windows FNT Header info. */ /* */ typedef struct FT_WinFNT_HeaderRec_ { FT_UShort version; FT_ULong file_size; FT_Byte copyright[60]; FT_UShort file_type; FT_UShort nominal_point_size; FT_UShort vertical_resolution; FT_UShort horizontal_resolution; FT_UShort ascent; FT_UShort internal_leading; FT_UShort external_leading; FT_Byte italic; FT_Byte underline; FT_Byte strike_out; FT_UShort weight; FT_Byte charset; FT_UShort pixel_width; FT_UShort pixel_height; FT_Byte pitch_and_family; FT_UShort avg_width; FT_UShort max_width; FT_Byte first_char; FT_Byte last_char; FT_Byte default_char; FT_Byte break_char; FT_UShort bytes_per_row; FT_ULong device_offset; FT_ULong face_name_offset; FT_ULong bits_pointer; FT_ULong bits_offset; FT_Byte reserved; FT_ULong flags; FT_UShort A_space; FT_UShort B_space; FT_UShort C_space; FT_UShort color_table_offset; FT_ULong reserved1[4]; } FT_WinFNT_HeaderRec; /*************************************************************************/ /* */ /* <Struct> */ /* FT_WinFNT_Header */ /* */ /* <Description> */ /* A handle to an @FT_WinFNT_HeaderRec structure. */ /* */ typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header; /********************************************************************** * * @function: * FT_Get_WinFNT_Header * * @description: * Retrieve a Windows FNT font info header. * * @input: * face :: A handle to the input face. * * @output: * aheader :: The WinFNT header. * * @return: * FreeType error code. 0~means success. * * @note: * This function only works with Windows FNT faces, returning an error * otherwise. */ FT_EXPORT( FT_Error ) FT_Get_WinFNT_Header( FT_Face face, FT_WinFNT_HeaderRec *aheader ); /* */ FT_END_HEADER #endif /* __FTWINFNT_H__ */ /* END */ /* Local Variables: */ /* coding: utf-8 */ /* End: */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ftxf86.h ================================================ /***************************************************************************/ /* */ /* ftxf86.h */ /* */ /* Support functions for X11. */ /* */ /* Copyright 2002, 2003, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __FTXF86_H__ #define __FTXF86_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* font_formats */ /* */ /* <Title> */ /* Font Formats */ /* */ /* <Abstract> */ /* Getting the font format. */ /* */ /* <Description> */ /* The single function in this section can be used to get the font */ /* format. Note that this information is not needed normally; */ /* however, there are special cases (like in PDF devices) where it is */ /* important to differentiate, in spite of FreeType's uniform API. */ /* */ /* This function is in the X11/xf86 namespace for historical reasons */ /* and in no way depends on that windowing system. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_X11_Font_Format */ /* */ /* <Description> */ /* Return a string describing the format of a given face, using values */ /* which can be used as an X11 FONT_PROPERTY. Possible values are */ /* `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */ /* `PFR', and `Windows~FNT'. */ /* */ /* <Input> */ /* face :: */ /* Input face handle. */ /* */ /* <Return> */ /* Font format string. NULL in case of error. */ /* */ FT_EXPORT( const char* ) FT_Get_X11_Font_Format( FT_Face face ); /* */ FT_END_HEADER #endif /* __FTXF86_H__ */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/t1tables.h ================================================ /***************************************************************************/ /* */ /* t1tables.h */ /* */ /* Basic Type 1/Type 2 tables definitions and interface (specification */ /* only). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __T1TABLES_H__ #define __T1TABLES_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* type1_tables */ /* */ /* <Title> */ /* Type 1 Tables */ /* */ /* <Abstract> */ /* Type~1 (PostScript) specific font tables. */ /* */ /* <Description> */ /* This section contains the definition of Type 1-specific tables, */ /* including structures related to other PostScript font formats. */ /* */ /*************************************************************************/ /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */ /* structures in order to support Multiple Master fonts. */ /*************************************************************************/ /* */ /* <Struct> */ /* PS_FontInfoRec */ /* */ /* <Description> */ /* A structure used to model a Type~1 or Type~2 FontInfo dictionary. */ /* Note that for Multiple Master fonts, each instance has its own */ /* FontInfo dictionary. */ /* */ typedef struct PS_FontInfoRec_ { FT_String* version; FT_String* notice; FT_String* full_name; FT_String* family_name; FT_String* weight; FT_Long italic_angle; FT_Bool is_fixed_pitch; FT_Short underline_position; FT_UShort underline_thickness; } PS_FontInfoRec; /*************************************************************************/ /* */ /* <Struct> */ /* PS_FontInfo */ /* */ /* <Description> */ /* A handle to a @PS_FontInfoRec structure. */ /* */ typedef struct PS_FontInfoRec_* PS_FontInfo; /*************************************************************************/ /* */ /* <Struct> */ /* T1_FontInfo */ /* */ /* <Description> */ /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */ /* kept to maintain source compatibility between various versions of */ /* FreeType. */ /* */ typedef PS_FontInfoRec T1_FontInfo; /*************************************************************************/ /* */ /* <Struct> */ /* PS_PrivateRec */ /* */ /* <Description> */ /* A structure used to model a Type~1 or Type~2 private dictionary. */ /* Note that for Multiple Master fonts, each instance has its own */ /* Private dictionary. */ /* */ typedef struct PS_PrivateRec_ { FT_Int unique_id; FT_Int lenIV; FT_Byte num_blue_values; FT_Byte num_other_blues; FT_Byte num_family_blues; FT_Byte num_family_other_blues; FT_Short blue_values[14]; FT_Short other_blues[10]; FT_Short family_blues [14]; FT_Short family_other_blues[10]; FT_Fixed blue_scale; FT_Int blue_shift; FT_Int blue_fuzz; FT_UShort standard_width[1]; FT_UShort standard_height[1]; FT_Byte num_snap_widths; FT_Byte num_snap_heights; FT_Bool force_bold; FT_Bool round_stem_up; FT_Short snap_widths [13]; /* including std width */ FT_Short snap_heights[13]; /* including std height */ FT_Fixed expansion_factor; FT_Long language_group; FT_Long password; FT_Short min_feature[2]; } PS_PrivateRec; /*************************************************************************/ /* */ /* <Struct> */ /* PS_Private */ /* */ /* <Description> */ /* A handle to a @PS_PrivateRec structure. */ /* */ typedef struct PS_PrivateRec_* PS_Private; /*************************************************************************/ /* */ /* <Struct> */ /* T1_Private */ /* */ /* <Description> */ /* This type is equivalent to @PS_PrivateRec. It is deprecated but */ /* kept to maintain source compatibility between various versions of */ /* FreeType. */ /* */ typedef PS_PrivateRec T1_Private; /*************************************************************************/ /* */ /* <Enum> */ /* T1_Blend_Flags */ /* */ /* <Description> */ /* A set of flags used to indicate which fields are present in a */ /* given blend dictionary (font info or private). Used to support */ /* Multiple Masters fonts. */ /* */ typedef enum T1_Blend_Flags_ { /*# required fields in a FontInfo blend dictionary */ T1_BLEND_UNDERLINE_POSITION = 0, T1_BLEND_UNDERLINE_THICKNESS, T1_BLEND_ITALIC_ANGLE, /*# required fields in a Private blend dictionary */ T1_BLEND_BLUE_VALUES, T1_BLEND_OTHER_BLUES, T1_BLEND_STANDARD_WIDTH, T1_BLEND_STANDARD_HEIGHT, T1_BLEND_STEM_SNAP_WIDTHS, T1_BLEND_STEM_SNAP_HEIGHTS, T1_BLEND_BLUE_SCALE, T1_BLEND_BLUE_SHIFT, T1_BLEND_FAMILY_BLUES, T1_BLEND_FAMILY_OTHER_BLUES, T1_BLEND_FORCE_BOLD, /*# never remove */ T1_BLEND_MAX } T1_Blend_Flags; /* */ /*# backwards compatible definitions */ #define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION #define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS #define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE #define t1_blend_blue_values T1_BLEND_BLUE_VALUES #define t1_blend_other_blues T1_BLEND_OTHER_BLUES #define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH #define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT #define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS #define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS #define t1_blend_blue_scale T1_BLEND_BLUE_SCALE #define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT #define t1_blend_family_blues T1_BLEND_FAMILY_BLUES #define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES #define t1_blend_force_bold T1_BLEND_FORCE_BOLD #define t1_blend_max T1_BLEND_MAX /* maximum number of Multiple Masters designs, as defined in the spec */ #define T1_MAX_MM_DESIGNS 16 /* maximum number of Multiple Masters axes, as defined in the spec */ #define T1_MAX_MM_AXIS 4 /* maximum number of elements in a design map */ #define T1_MAX_MM_MAP_POINTS 20 /* this structure is used to store the BlendDesignMap entry for an axis */ typedef struct PS_DesignMap_ { FT_Byte num_points; FT_Long* design_points; FT_Fixed* blend_points; } PS_DesignMapRec, *PS_DesignMap; /* backwards-compatible definition */ typedef PS_DesignMapRec T1_DesignMap; typedef struct PS_BlendRec_ { FT_UInt num_designs; FT_UInt num_axis; FT_String* axis_names[T1_MAX_MM_AXIS]; FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; FT_Fixed* weight_vector; FT_Fixed* default_weight_vector; PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; PS_Private privates [T1_MAX_MM_DESIGNS + 1]; FT_ULong blend_bitflags; FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; /* since 2.3.0 */ /* undocumented, optional: the default design instance; */ /* corresponds to default_weight_vector -- */ /* num_default_design_vector == 0 means it is not present */ /* in the font and associated metrics files */ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; FT_UInt num_default_design_vector; } PS_BlendRec, *PS_Blend; /* backwards-compatible definition */ typedef PS_BlendRec T1_Blend; /*************************************************************************/ /* */ /* <Struct> */ /* CID_FaceDictRec */ /* */ /* <Description> */ /* A structure used to represent data in a CID top-level dictionary. */ /* */ typedef struct CID_FaceDictRec_ { PS_PrivateRec private_dict; FT_UInt len_buildchar; FT_Fixed forcebold_threshold; FT_Pos stroke_width; FT_Fixed expansion_factor; FT_Byte paint_type; FT_Byte font_type; FT_Matrix font_matrix; FT_Vector font_offset; FT_UInt num_subrs; FT_ULong subrmap_offset; FT_Int sd_bytes; } CID_FaceDictRec; /*************************************************************************/ /* */ /* <Struct> */ /* CID_FaceDict */ /* */ /* <Description> */ /* A handle to a @CID_FaceDictRec structure. */ /* */ typedef struct CID_FaceDictRec_* CID_FaceDict; /* */ /* backwards-compatible definition */ typedef CID_FaceDictRec CID_FontDict; /*************************************************************************/ /* */ /* <Struct> */ /* CID_FaceInfoRec */ /* */ /* <Description> */ /* A structure used to represent CID Face information. */ /* */ typedef struct CID_FaceInfoRec_ { FT_String* cid_font_name; FT_Fixed cid_version; FT_Int cid_font_type; FT_String* registry; FT_String* ordering; FT_Int supplement; PS_FontInfoRec font_info; FT_BBox font_bbox; FT_ULong uid_base; FT_Int num_xuid; FT_ULong xuid[16]; FT_ULong cidmap_offset; FT_Int fd_bytes; FT_Int gd_bytes; FT_ULong cid_count; FT_Int num_dicts; CID_FaceDict font_dicts; FT_ULong data_offset; } CID_FaceInfoRec; /*************************************************************************/ /* */ /* <Struct> */ /* CID_FaceInfo */ /* */ /* <Description> */ /* A handle to a @CID_FaceInfoRec structure. */ /* */ typedef struct CID_FaceInfoRec_* CID_FaceInfo; /*************************************************************************/ /* */ /* <Struct> */ /* CID_Info */ /* */ /* <Description> */ /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */ /* kept to maintain source compatibility between various versions of */ /* FreeType. */ /* */ typedef CID_FaceInfoRec CID_Info; /************************************************************************ * * @function: * FT_Has_PS_Glyph_Names * * @description: * Return true if a given face provides reliable PostScript glyph * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro, * except that certain fonts (mostly TrueType) contain incorrect * glyph name tables. * * When this function returns true, the caller is sure that the glyph * names returned by @FT_Get_Glyph_Name are reliable. * * @input: * face :: * face handle * * @return: * Boolean. True if glyph names are reliable. * */ FT_EXPORT( FT_Int ) FT_Has_PS_Glyph_Names( FT_Face face ); /************************************************************************ * * @function: * FT_Get_PS_Font_Info * * @description: * Retrieve the @PS_FontInfoRec structure corresponding to a given * PostScript font. * * @input: * face :: * PostScript face handle. * * @output: * afont_info :: * Output font info structure pointer. * * @return: * FreeType error code. 0~means success. * * @note: * The string pointers within the font info structure are owned by * the face and don't need to be freed by the caller. * * If the font's format is not PostScript-based, this function will * return the `FT_Err_Invalid_Argument' error code. * */ FT_EXPORT( FT_Error ) FT_Get_PS_Font_Info( FT_Face face, PS_FontInfo afont_info ); /************************************************************************ * * @function: * FT_Get_PS_Font_Private * * @description: * Retrieve the @PS_PrivateRec structure corresponding to a given * PostScript font. * * @input: * face :: * PostScript face handle. * * @output: * afont_private :: * Output private dictionary structure pointer. * * @return: * FreeType error code. 0~means success. * * @note: * The string pointers within the @PS_PrivateRec structure are owned by * the face and don't need to be freed by the caller. * * If the font's format is not PostScript-based, this function returns * the `FT_Err_Invalid_Argument' error code. * */ FT_EXPORT( FT_Error ) FT_Get_PS_Font_Private( FT_Face face, PS_Private afont_private ); /* */ FT_END_HEADER #endif /* __T1TABLES_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ttnameid.h ================================================ /***************************************************************************/ /* */ /* ttnameid.h */ /* */ /* TrueType name ID definitions (specification only). */ /* */ /* Copyright 1996-2002, 2003, 2004, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __TTNAMEID_H__ #define __TTNAMEID_H__ #include <ft2build.h> FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* truetype_tables */ /* */ /*************************************************************************/ /* */ /* Possible values for the `platform' identifier code in the name */ /* records of the TTF `name' table. */ /* */ /*************************************************************************/ /*********************************************************************** * * @enum: * TT_PLATFORM_XXX * * @description: * A list of valid values for the `platform_id' identifier code in * @FT_CharMapRec and @FT_SfntName structures. * * @values: * TT_PLATFORM_APPLE_UNICODE :: * Used by Apple to indicate a Unicode character map and/or name entry. * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note * that name entries in this format are coded as big-endian UCS-2 * character codes _only_. * * TT_PLATFORM_MACINTOSH :: * Used by Apple to indicate a MacOS-specific charmap and/or name entry. * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that * most TrueType fonts contain an Apple roman charmap to be usable on * MacOS systems (even if they contain a Microsoft charmap as well). * * TT_PLATFORM_ISO :: * This value was used to specify Unicode charmaps. It is however * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding * `encoding_id' values. * * TT_PLATFORM_MICROSOFT :: * Used by Microsoft to indicate Windows-specific charmaps. See * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values. * Note that most fonts contain a Unicode charmap using * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS). * * TT_PLATFORM_CUSTOM :: * Used to indicate application-specific charmaps. * * TT_PLATFORM_ADOBE :: * This value isn't part of any font format specification, but is used * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec * structure. See @TT_ADOBE_ID_XXX. */ #define TT_PLATFORM_APPLE_UNICODE 0 #define TT_PLATFORM_MACINTOSH 1 #define TT_PLATFORM_ISO 2 /* deprecated */ #define TT_PLATFORM_MICROSOFT 3 #define TT_PLATFORM_CUSTOM 4 #define TT_PLATFORM_ADOBE 7 /* artificial */ /*********************************************************************** * * @enum: * TT_APPLE_ID_XXX * * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries. * * @values: * TT_APPLE_ID_DEFAULT :: * Unicode version 1.0. * * TT_APPLE_ID_UNICODE_1_1 :: * Unicode 1.1; specifies Hangul characters starting at U+34xx. * * TT_APPLE_ID_ISO_10646 :: * Deprecated (identical to preceding). * * TT_APPLE_ID_UNICODE_2_0 :: * Unicode 2.0 and beyond (UTF-16 BMP only). * * TT_APPLE_ID_UNICODE_32 :: * Unicode 3.1 and beyond, using UTF-32. * * TT_APPLE_ID_VARIANT_SELECTOR :: * From Adobe, not Apple. Not a normal cmap. Specifies variations * on a real cmap. */ #define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ #define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ #define TT_APPLE_ID_ISO_10646 2 /* deprecated */ #define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ #define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ #define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ /*********************************************************************** * * @enum: * TT_MAC_ID_XXX * * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_MACINTOSH charmaps and name entries. * * @values: * TT_MAC_ID_ROMAN :: * TT_MAC_ID_JAPANESE :: * TT_MAC_ID_TRADITIONAL_CHINESE :: * TT_MAC_ID_KOREAN :: * TT_MAC_ID_ARABIC :: * TT_MAC_ID_HEBREW :: * TT_MAC_ID_GREEK :: * TT_MAC_ID_RUSSIAN :: * TT_MAC_ID_RSYMBOL :: * TT_MAC_ID_DEVANAGARI :: * TT_MAC_ID_GURMUKHI :: * TT_MAC_ID_GUJARATI :: * TT_MAC_ID_ORIYA :: * TT_MAC_ID_BENGALI :: * TT_MAC_ID_TAMIL :: * TT_MAC_ID_TELUGU :: * TT_MAC_ID_KANNADA :: * TT_MAC_ID_MALAYALAM :: * TT_MAC_ID_SINHALESE :: * TT_MAC_ID_BURMESE :: * TT_MAC_ID_KHMER :: * TT_MAC_ID_THAI :: * TT_MAC_ID_LAOTIAN :: * TT_MAC_ID_GEORGIAN :: * TT_MAC_ID_ARMENIAN :: * TT_MAC_ID_MALDIVIAN :: * TT_MAC_ID_SIMPLIFIED_CHINESE :: * TT_MAC_ID_TIBETAN :: * TT_MAC_ID_MONGOLIAN :: * TT_MAC_ID_GEEZ :: * TT_MAC_ID_SLAVIC :: * TT_MAC_ID_VIETNAMESE :: * TT_MAC_ID_SINDHI :: * TT_MAC_ID_UNINTERP :: */ #define TT_MAC_ID_ROMAN 0 #define TT_MAC_ID_JAPANESE 1 #define TT_MAC_ID_TRADITIONAL_CHINESE 2 #define TT_MAC_ID_KOREAN 3 #define TT_MAC_ID_ARABIC 4 #define TT_MAC_ID_HEBREW 5 #define TT_MAC_ID_GREEK 6 #define TT_MAC_ID_RUSSIAN 7 #define TT_MAC_ID_RSYMBOL 8 #define TT_MAC_ID_DEVANAGARI 9 #define TT_MAC_ID_GURMUKHI 10 #define TT_MAC_ID_GUJARATI 11 #define TT_MAC_ID_ORIYA 12 #define TT_MAC_ID_BENGALI 13 #define TT_MAC_ID_TAMIL 14 #define TT_MAC_ID_TELUGU 15 #define TT_MAC_ID_KANNADA 16 #define TT_MAC_ID_MALAYALAM 17 #define TT_MAC_ID_SINHALESE 18 #define TT_MAC_ID_BURMESE 19 #define TT_MAC_ID_KHMER 20 #define TT_MAC_ID_THAI 21 #define TT_MAC_ID_LAOTIAN 22 #define TT_MAC_ID_GEORGIAN 23 #define TT_MAC_ID_ARMENIAN 24 #define TT_MAC_ID_MALDIVIAN 25 #define TT_MAC_ID_SIMPLIFIED_CHINESE 25 #define TT_MAC_ID_TIBETAN 26 #define TT_MAC_ID_MONGOLIAN 27 #define TT_MAC_ID_GEEZ 28 #define TT_MAC_ID_SLAVIC 29 #define TT_MAC_ID_VIETNAMESE 30 #define TT_MAC_ID_SINDHI 31 #define TT_MAC_ID_UNINTERP 32 /*********************************************************************** * * @enum: * TT_ISO_ID_XXX * * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_ISO charmaps and name entries. * * Their use is now deprecated. * * @values: * TT_ISO_ID_7BIT_ASCII :: * ASCII. * TT_ISO_ID_10646 :: * ISO/10646. * TT_ISO_ID_8859_1 :: * Also known as Latin-1. */ #define TT_ISO_ID_7BIT_ASCII 0 #define TT_ISO_ID_10646 1 #define TT_ISO_ID_8859_1 2 /*********************************************************************** * * @enum: * TT_MS_ID_XXX * * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_MICROSOFT charmaps and name entries. * * @values: * TT_MS_ID_SYMBOL_CS :: * Corresponds to Microsoft symbol encoding. See * @FT_ENCODING_MS_SYMBOL. * * TT_MS_ID_UNICODE_CS :: * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See * @FT_ENCODING_UNICODE. * * TT_MS_ID_SJIS :: * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS. * * TT_MS_ID_GB2312 :: * Corresponds to Simplified Chinese as used in Mainland China. See * @FT_ENCODING_GB2312. * * TT_MS_ID_BIG_5 :: * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. * See @FT_ENCODING_BIG5. * * TT_MS_ID_WANSUNG :: * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG. * * TT_MS_ID_JOHAB :: * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB. * * TT_MS_ID_UCS_4 :: * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to * the OpenType specification version 1.4 (mid-2001.) */ #define TT_MS_ID_SYMBOL_CS 0 #define TT_MS_ID_UNICODE_CS 1 #define TT_MS_ID_SJIS 2 #define TT_MS_ID_GB2312 3 #define TT_MS_ID_BIG_5 4 #define TT_MS_ID_WANSUNG 5 #define TT_MS_ID_JOHAB 6 #define TT_MS_ID_UCS_4 10 /*********************************************************************** * * @enum: * TT_ADOBE_ID_XXX * * @description: * A list of valid values for the `encoding_id' for * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! * * @values: * TT_ADOBE_ID_STANDARD :: * Adobe standard encoding. * TT_ADOBE_ID_EXPERT :: * Adobe expert encoding. * TT_ADOBE_ID_CUSTOM :: * Adobe custom encoding. * TT_ADOBE_ID_LATIN_1 :: * Adobe Latin~1 encoding. */ #define TT_ADOBE_ID_STANDARD 0 #define TT_ADOBE_ID_EXPERT 1 #define TT_ADOBE_ID_CUSTOM 2 #define TT_ADOBE_ID_LATIN_1 3 /*************************************************************************/ /* */ /* Possible values of the language identifier field in the name records */ /* of the TTF `name' table if the `platform' identifier code is */ /* TT_PLATFORM_MACINTOSH. */ /* */ /* The canonical source for the Apple assigned Language ID's is at */ /* */ /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */ /* */ #define TT_MAC_LANGID_ENGLISH 0 #define TT_MAC_LANGID_FRENCH 1 #define TT_MAC_LANGID_GERMAN 2 #define TT_MAC_LANGID_ITALIAN 3 #define TT_MAC_LANGID_DUTCH 4 #define TT_MAC_LANGID_SWEDISH 5 #define TT_MAC_LANGID_SPANISH 6 #define TT_MAC_LANGID_DANISH 7 #define TT_MAC_LANGID_PORTUGUESE 8 #define TT_MAC_LANGID_NORWEGIAN 9 #define TT_MAC_LANGID_HEBREW 10 #define TT_MAC_LANGID_JAPANESE 11 #define TT_MAC_LANGID_ARABIC 12 #define TT_MAC_LANGID_FINNISH 13 #define TT_MAC_LANGID_GREEK 14 #define TT_MAC_LANGID_ICELANDIC 15 #define TT_MAC_LANGID_MALTESE 16 #define TT_MAC_LANGID_TURKISH 17 #define TT_MAC_LANGID_CROATIAN 18 #define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 #define TT_MAC_LANGID_URDU 20 #define TT_MAC_LANGID_HINDI 21 #define TT_MAC_LANGID_THAI 22 #define TT_MAC_LANGID_KOREAN 23 #define TT_MAC_LANGID_LITHUANIAN 24 #define TT_MAC_LANGID_POLISH 25 #define TT_MAC_LANGID_HUNGARIAN 26 #define TT_MAC_LANGID_ESTONIAN 27 #define TT_MAC_LANGID_LETTISH 28 #define TT_MAC_LANGID_SAAMISK 29 #define TT_MAC_LANGID_FAEROESE 30 #define TT_MAC_LANGID_FARSI 31 #define TT_MAC_LANGID_RUSSIAN 32 #define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 #define TT_MAC_LANGID_FLEMISH 34 #define TT_MAC_LANGID_IRISH 35 #define TT_MAC_LANGID_ALBANIAN 36 #define TT_MAC_LANGID_ROMANIAN 37 #define TT_MAC_LANGID_CZECH 38 #define TT_MAC_LANGID_SLOVAK 39 #define TT_MAC_LANGID_SLOVENIAN 40 #define TT_MAC_LANGID_YIDDISH 41 #define TT_MAC_LANGID_SERBIAN 42 #define TT_MAC_LANGID_MACEDONIAN 43 #define TT_MAC_LANGID_BULGARIAN 44 #define TT_MAC_LANGID_UKRAINIAN 45 #define TT_MAC_LANGID_BYELORUSSIAN 46 #define TT_MAC_LANGID_UZBEK 47 #define TT_MAC_LANGID_KAZAKH 48 #define TT_MAC_LANGID_AZERBAIJANI 49 #define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 #define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 #define TT_MAC_LANGID_ARMENIAN 51 #define TT_MAC_LANGID_GEORGIAN 52 #define TT_MAC_LANGID_MOLDAVIAN 53 #define TT_MAC_LANGID_KIRGHIZ 54 #define TT_MAC_LANGID_TAJIKI 55 #define TT_MAC_LANGID_TURKMEN 56 #define TT_MAC_LANGID_MONGOLIAN 57 #define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 #define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 #define TT_MAC_LANGID_PASHTO 59 #define TT_MAC_LANGID_KURDISH 60 #define TT_MAC_LANGID_KASHMIRI 61 #define TT_MAC_LANGID_SINDHI 62 #define TT_MAC_LANGID_TIBETAN 63 #define TT_MAC_LANGID_NEPALI 64 #define TT_MAC_LANGID_SANSKRIT 65 #define TT_MAC_LANGID_MARATHI 66 #define TT_MAC_LANGID_BENGALI 67 #define TT_MAC_LANGID_ASSAMESE 68 #define TT_MAC_LANGID_GUJARATI 69 #define TT_MAC_LANGID_PUNJABI 70 #define TT_MAC_LANGID_ORIYA 71 #define TT_MAC_LANGID_MALAYALAM 72 #define TT_MAC_LANGID_KANNADA 73 #define TT_MAC_LANGID_TAMIL 74 #define TT_MAC_LANGID_TELUGU 75 #define TT_MAC_LANGID_SINHALESE 76 #define TT_MAC_LANGID_BURMESE 77 #define TT_MAC_LANGID_KHMER 78 #define TT_MAC_LANGID_LAO 79 #define TT_MAC_LANGID_VIETNAMESE 80 #define TT_MAC_LANGID_INDONESIAN 81 #define TT_MAC_LANGID_TAGALOG 82 #define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 #define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 #define TT_MAC_LANGID_AMHARIC 85 #define TT_MAC_LANGID_TIGRINYA 86 #define TT_MAC_LANGID_GALLA 87 #define TT_MAC_LANGID_SOMALI 88 #define TT_MAC_LANGID_SWAHILI 89 #define TT_MAC_LANGID_RUANDA 90 #define TT_MAC_LANGID_RUNDI 91 #define TT_MAC_LANGID_CHEWA 92 #define TT_MAC_LANGID_MALAGASY 93 #define TT_MAC_LANGID_ESPERANTO 94 #define TT_MAC_LANGID_WELSH 128 #define TT_MAC_LANGID_BASQUE 129 #define TT_MAC_LANGID_CATALAN 130 #define TT_MAC_LANGID_LATIN 131 #define TT_MAC_LANGID_QUECHUA 132 #define TT_MAC_LANGID_GUARANI 133 #define TT_MAC_LANGID_AYMARA 134 #define TT_MAC_LANGID_TATAR 135 #define TT_MAC_LANGID_UIGHUR 136 #define TT_MAC_LANGID_DZONGKHA 137 #define TT_MAC_LANGID_JAVANESE 138 #define TT_MAC_LANGID_SUNDANESE 139 #if 0 /* these seem to be errors that have been dropped */ #define TT_MAC_LANGID_SCOTTISH_GAELIC 140 #define TT_MAC_LANGID_IRISH_GAELIC 141 #endif /* The following codes are new as of 2000-03-10 */ #define TT_MAC_LANGID_GALICIAN 140 #define TT_MAC_LANGID_AFRIKAANS 141 #define TT_MAC_LANGID_BRETON 142 #define TT_MAC_LANGID_INUKTITUT 143 #define TT_MAC_LANGID_SCOTTISH_GAELIC 144 #define TT_MAC_LANGID_MANX_GAELIC 145 #define TT_MAC_LANGID_IRISH_GAELIC 146 #define TT_MAC_LANGID_TONGAN 147 #define TT_MAC_LANGID_GREEK_POLYTONIC 148 #define TT_MAC_LANGID_GREELANDIC 149 #define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 /*************************************************************************/ /* */ /* Possible values of the language identifier field in the name records */ /* of the TTF `name' table if the `platform' identifier code is */ /* TT_PLATFORM_MICROSOFT. */ /* */ /* The canonical source for the MS assigned LCID's (seems to) be at */ /* */ /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */ /* */ /* It used to be at various places, among them */ /* */ /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */ /* http://www.microsoft.com/globaldev/reference/loclanghome.asp */ /* http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP */ /* http://msdn.microsoft.com/library/en-us/passport25/ */ /* NET_Passport_VBScript_Documentation/Single_Sign_In/ */ /* Advanced_Single_Sign_In/Localization_and_LCIDs.asp */ /* */ /* Hopefully, it seems now that the Globaldev site prevails... */ /* (updated by Antoine, 2004-02-17) */ #define TT_MS_LANGID_ARABIC_GENERAL 0x0001 #define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 #define TT_MS_LANGID_ARABIC_IRAQ 0x0801 #define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 #define TT_MS_LANGID_ARABIC_LIBYA 0x1001 #define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 #define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 #define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 #define TT_MS_LANGID_ARABIC_OMAN 0x2001 #define TT_MS_LANGID_ARABIC_YEMEN 0x2401 #define TT_MS_LANGID_ARABIC_SYRIA 0x2801 #define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 #define TT_MS_LANGID_ARABIC_LEBANON 0x3001 #define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 #define TT_MS_LANGID_ARABIC_UAE 0x3801 #define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 #define TT_MS_LANGID_ARABIC_QATAR 0x4001 #define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 #define TT_MS_LANGID_CATALAN_SPAIN 0x0403 #define TT_MS_LANGID_CHINESE_GENERAL 0x0004 #define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 #define TT_MS_LANGID_CHINESE_PRC 0x0804 #define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 #define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 #if 1 /* this looks like the correct value */ #define TT_MS_LANGID_CHINESE_MACAU 0x1404 #else /* but beware, Microsoft may change its mind... the most recent Word reference has the following: */ #define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG #endif #if 0 /* used only with .NET `cultures'; commented out */ #define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04 #endif #define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 #define TT_MS_LANGID_DANISH_DENMARK 0x0406 #define TT_MS_LANGID_GERMAN_GERMANY 0x0407 #define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 #define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 #define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 #define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 #define TT_MS_LANGID_GREEK_GREECE 0x0408 /* don't ask what this one means... It is commented out currently. */ #if 0 #define TT_MS_LANGID_GREEK_GREECE2 0x2008 #endif #define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 #define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 #define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 #define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 #define TT_MS_LANGID_ENGLISH_CANADA 0x1009 #define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 #define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 #define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 #define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 #define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 #define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 #define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 #define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 #define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 #define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809 #define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09 #define TT_MS_LANGID_ENGLISH_INDIA 0x4009 #define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 #define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 #define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a #define TT_MS_LANGID_SPANISH_MEXICO 0x080a #define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a #define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a #define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a #define TT_MS_LANGID_SPANISH_PANAMA 0x180a #define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a #define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a #define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a #define TT_MS_LANGID_SPANISH_PERU 0x280a #define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a #define TT_MS_LANGID_SPANISH_ECUADOR 0x300a #define TT_MS_LANGID_SPANISH_CHILE 0x340a #define TT_MS_LANGID_SPANISH_URUGUAY 0x380a #define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a #define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a #define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a #define TT_MS_LANGID_SPANISH_HONDURAS 0x480a #define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a #define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a #define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540a /* The following ID blatantly violate MS specs by using a */ /* sublanguage > 0x1F. */ #define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU #define TT_MS_LANGID_FINNISH_FINLAND 0x040b #define TT_MS_LANGID_FRENCH_FRANCE 0x040c #define TT_MS_LANGID_FRENCH_BELGIUM 0x080c #define TT_MS_LANGID_FRENCH_CANADA 0x0c0c #define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c #define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c #define TT_MS_LANGID_FRENCH_MONACO 0x180c #define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1c0c #define TT_MS_LANGID_FRENCH_REUNION 0x200c #define TT_MS_LANGID_FRENCH_CONGO 0x240c /* which was formerly: */ #define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO #define TT_MS_LANGID_FRENCH_SENEGAL 0x280c #define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c #define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c #define TT_MS_LANGID_FRENCH_MALI 0x340c #define TT_MS_LANGID_FRENCH_MOROCCO 0x380c #define TT_MS_LANGID_FRENCH_HAITI 0x3c0c /* and another violation of the spec (see 0xE40aU) */ #define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU #define TT_MS_LANGID_HEBREW_ISRAEL 0x040d #define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e #define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f #define TT_MS_LANGID_ITALIAN_ITALY 0x0410 #define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 #define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 #define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 #define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 #define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 #define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 #define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 #define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 #define TT_MS_LANGID_POLISH_POLAND 0x0415 #define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 #define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 #define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 #define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 #define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 #define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 #define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 #define TT_MS_LANGID_CROATIAN_CROATIA 0x041a #define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a #define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a #if 0 /* this used to be this value, but it looks like we were wrong */ #define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a #else /* current sources say */ #define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a #define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a /* and XPsp2 Platform SDK added (2004-07-26) */ /* Names are shortened to be significant within 40 chars. */ #define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a #define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a #endif #define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b #define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c #define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d #define TT_MS_LANGID_SWEDISH_FINLAND 0x081d #define TT_MS_LANGID_THAI_THAILAND 0x041e #define TT_MS_LANGID_TURKISH_TURKEY 0x041f #define TT_MS_LANGID_URDU_PAKISTAN 0x0420 #define TT_MS_LANGID_URDU_INDIA 0x0820 #define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 #define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 #define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 #define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 #define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 #define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 #define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 #define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 #define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 #define TT_MS_LANGID_FARSI_IRAN 0x0429 #define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a #define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b #define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c #define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c #define TT_MS_LANGID_BASQUE_SPAIN 0x042d #define TT_MS_LANGID_SORBIAN_GERMANY 0x042e #define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f #define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 #define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 #define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 #define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 #define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 #define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 #define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 #define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 #define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 #define TT_MS_LANGID_HINDI_INDIA 0x0439 #define TT_MS_LANGID_MALTESE_MALTA 0x043a /* Added by XPsp2 Platform SDK (2004-07-26) */ #define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b #define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b #define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b #define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103b #define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143b #define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183b #define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3b #define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203b #define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243b /* ... and we also keep our old identifier... */ #define TT_MS_LANGID_SAAMI_LAPONIA 0x043b #if 0 /* this seems to be a previous inversion */ #define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c #define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c #else #define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c #define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c #endif #define TT_MS_LANGID_YIDDISH_GERMANY 0x043d #define TT_MS_LANGID_MALAY_MALAYSIA 0x043e #define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e #define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f #define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440 /* alias declared in Windows 2000 */ #define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN #define TT_MS_LANGID_SWAHILI_KENYA 0x0441 #define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 #define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 #define TT_MS_LANGID_BENGALI_INDIA 0x0445 #define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 #define TT_MS_LANGID_PUNJABI_INDIA 0x0446 #define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 #define TT_MS_LANGID_GUJARATI_INDIA 0x0447 #define TT_MS_LANGID_ORIYA_INDIA 0x0448 #define TT_MS_LANGID_TAMIL_INDIA 0x0449 #define TT_MS_LANGID_TELUGU_INDIA 0x044a #define TT_MS_LANGID_KANNADA_INDIA 0x044b #define TT_MS_LANGID_MALAYALAM_INDIA 0x044c #define TT_MS_LANGID_ASSAMESE_INDIA 0x044d #define TT_MS_LANGID_MARATHI_INDIA 0x044e #define TT_MS_LANGID_SANSKRIT_INDIA 0x044f #define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 #define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850 #define TT_MS_LANGID_TIBETAN_CHINA 0x0451 /* Don't use the next constant! It has */ /* (1) the wrong spelling (Dzonghka) */ /* (2) Microsoft doesn't officially define it -- */ /* at least it is not in the List of Local */ /* ID Values. */ /* (3) Dzongkha is not the same language as */ /* Tibetan, so merging it is wrong anyway. */ /* */ /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */ #define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 #if 0 /* the following used to be defined */ #define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451 /* ... but it was changed; */ #else /* So we will continue to #define it, but with the correct value */ #define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN #endif #define TT_MS_LANGID_WELSH_WALES 0x0452 #define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 #define TT_MS_LANGID_LAO_LAOS 0x0454 #define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 #define TT_MS_LANGID_GALICIAN_SPAIN 0x0456 #define TT_MS_LANGID_KONKANI_INDIA 0x0457 #define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458 #define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459 #define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859 /* Missing a LCID for Sindhi in Devanagari script */ #define TT_MS_LANGID_SYRIAC_SYRIA 0x045a #define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b #define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c #define TT_MS_LANGID_INUKTITUT_CANADA 0x045d #define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e #define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045f #define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f /* Missing a LCID for Tifinagh script */ #define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */ /* script is yet unclear... might be Arabic, Nagari or Sharada */ #define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 /* ... and aliased (by MS) for compatibility reasons. */ #define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA #define TT_MS_LANGID_NEPALI_NEPAL 0x0461 #define TT_MS_LANGID_NEPALI_INDIA 0x0861 #define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 #define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 #define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 #define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 /* alias declared in Windows 2000 */ #define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES #define TT_MS_LANGID_EDO_NIGERIA 0x0466 #define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 #define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 #define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 #define TT_MS_LANGID_YORUBA_NIGERIA 0x046a #define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046b #define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b #define TT_MS_LANGID_QUECHUA_PERU 0x0c6b #define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c /* Also spelled by XPsp2 Platform SDK (2004-07-26) */ #define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ TT_MS_LANGID_SEPEDI_SOUTH_AFRICA /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */ #define TT_MS_LANGID_IGBO_NIGERIA 0x0470 #define TT_MS_LANGID_KANURI_NIGERIA 0x0471 #define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472 #define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473 #define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873 /* also spelled in the `Passport SDK' list as: */ #define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA #define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474 #define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475 #define TT_MS_LANGID_LATIN 0x0476 #define TT_MS_LANGID_SOMALI_SOMALIA 0x0477 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */ /* not written (but OTOH the peculiar writing system is worth */ /* studying). */ #define TT_MS_LANGID_YI_CHINA 0x0478 #define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479 /* language codes from 0x047a to 0x047f are (still) unknown. */ #define TT_MS_LANGID_UIGHUR_CHINA 0x0480 #define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 #if 0 /* not deemed useful for fonts */ #define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04ff #endif /*************************************************************************/ /* */ /* Possible values of the `name' identifier field in the name records of */ /* the TTF `name' table. These values are platform independent. */ /* */ #define TT_NAME_ID_COPYRIGHT 0 #define TT_NAME_ID_FONT_FAMILY 1 #define TT_NAME_ID_FONT_SUBFAMILY 2 #define TT_NAME_ID_UNIQUE_ID 3 #define TT_NAME_ID_FULL_NAME 4 #define TT_NAME_ID_VERSION_STRING 5 #define TT_NAME_ID_PS_NAME 6 #define TT_NAME_ID_TRADEMARK 7 /* the following values are from the OpenType spec */ #define TT_NAME_ID_MANUFACTURER 8 #define TT_NAME_ID_DESIGNER 9 #define TT_NAME_ID_DESCRIPTION 10 #define TT_NAME_ID_VENDOR_URL 11 #define TT_NAME_ID_DESIGNER_URL 12 #define TT_NAME_ID_LICENSE 13 #define TT_NAME_ID_LICENSE_URL 14 /* number 15 is reserved */ #define TT_NAME_ID_PREFERRED_FAMILY 16 #define TT_NAME_ID_PREFERRED_SUBFAMILY 17 #define TT_NAME_ID_MAC_FULL_NAME 18 /* The following code is new as of 2000-01-21 */ #define TT_NAME_ID_SAMPLE_TEXT 19 /* This is new in OpenType 1.3 */ #define TT_NAME_ID_CID_FINDFONT_NAME 20 /* This is new in OpenType 1.5 */ #define TT_NAME_ID_WWS_FAMILY 21 #define TT_NAME_ID_WWS_SUBFAMILY 22 /*************************************************************************/ /* */ /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ /* */ /* Updated 08-Nov-2008. */ /* */ /* Bit 0 Basic Latin */ #define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ /* Bit 1 C1 Controls and Latin-1 Supplement */ #define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ /* Bit 2 Latin Extended-A */ #define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ /* Bit 3 Latin Extended-B */ #define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ /* Bit 4 IPA Extensions */ /* Phonetic Extensions */ /* Phonetic Extensions Supplement */ #define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ /* U+1D00-U+1D7F */ /* U+1D80-U+1DBF */ /* Bit 5 Spacing Modifier Letters */ /* Modifier Tone Letters */ #define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ /* U+A700-U+A71F */ /* Bit 6 Combining Diacritical Marks */ /* Combining Diacritical Marks Supplement */ #define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ /* U+1DC0-U+1DFF */ /* Bit 7 Greek and Coptic */ #define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ /* Bit 8 Coptic */ #define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ /* Bit 9 Cyrillic */ /* Cyrillic Supplement */ /* Cyrillic Extended-A */ /* Cyrillic Extended-B */ #define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ /* U+0500-U+052F */ /* U+2DE0-U+2DFF */ /* U+A640-U+A69F */ /* Bit 10 Armenian */ #define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ /* Bit 11 Hebrew */ #define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ /* Bit 12 Vai */ #define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ /* Bit 13 Arabic */ /* Arabic Supplement */ #define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ /* U+0750-U+077F */ /* Bit 14 NKo */ #define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ /* Bit 15 Devanagari */ #define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ /* Bit 16 Bengali */ #define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ /* Bit 17 Gurmukhi */ #define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ /* Bit 18 Gujarati */ #define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ /* Bit 19 Oriya */ #define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ /* Bit 20 Tamil */ #define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ /* Bit 21 Telugu */ #define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ /* Bit 22 Kannada */ #define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ /* Bit 23 Malayalam */ #define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ /* Bit 24 Thai */ #define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ /* Bit 25 Lao */ #define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ /* Bit 26 Georgian */ /* Georgian Supplement */ #define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ /* U+2D00-U+2D2F */ /* Bit 27 Balinese */ #define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ /* Bit 28 Hangul Jamo */ #define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ /* Bit 29 Latin Extended Additional */ /* Latin Extended-C */ /* Latin Extended-D */ #define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ /* U+2C60-U+2C7F */ /* U+A720-U+A7FF */ /* Bit 30 Greek Extended */ #define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ /* Bit 31 General Punctuation */ /* Supplemental Punctuation */ #define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ /* U+2E00-U+2E7F */ /* Bit 32 Superscripts And Subscripts */ #define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ /* Bit 33 Currency Symbols */ #define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ /* Bit 34 Combining Diacritical Marks For Symbols */ #define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ /* Bit 35 Letterlike Symbols */ #define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ /* Bit 36 Number Forms */ #define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ /* Bit 37 Arrows */ /* Supplemental Arrows-A */ /* Supplemental Arrows-B */ /* Miscellaneous Symbols and Arrows */ #define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ /* U+27F0-U+27FF */ /* U+2900-U+297F */ /* U+2B00-U+2BFF */ /* Bit 38 Mathematical Operators */ /* Supplemental Mathematical Operators */ /* Miscellaneous Mathematical Symbols-A */ /* Miscellaneous Mathematical Symbols-B */ #define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ /* U+2A00-U+2AFF */ /* U+27C0-U+27EF */ /* U+2980-U+29FF */ /* Bit 39 Miscellaneous Technical */ #define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ /* Bit 40 Control Pictures */ #define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ /* Bit 41 Optical Character Recognition */ #define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ /* Bit 42 Enclosed Alphanumerics */ #define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ /* Bit 43 Box Drawing */ #define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ /* Bit 44 Block Elements */ #define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ /* Bit 45 Geometric Shapes */ #define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ /* Bit 46 Miscellaneous Symbols */ #define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ /* Bit 47 Dingbats */ #define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ /* Bit 48 CJK Symbols and Punctuation */ #define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ /* Bit 49 Hiragana */ #define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ /* Bit 50 Katakana */ /* Katakana Phonetic Extensions */ #define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ /* U+31F0-U+31FF */ /* Bit 51 Bopomofo */ /* Bopomofo Extended */ #define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ /* U+31A0-U+31BF */ /* Bit 52 Hangul Compatibility Jamo */ #define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ /* Bit 53 Phags-Pa */ #define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ #define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ #define TT_UCR_PHAGSPA /* Bit 54 Enclosed CJK Letters and Months */ #define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ /* Bit 55 CJK Compatibility */ #define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ /* Bit 56 Hangul Syllables */ #define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ /* Bit 57 High Surrogates */ /* High Private Use Surrogates */ /* Low Surrogates */ /* */ /* According to OpenType specs v.1.3+, */ /* setting bit 57 implies that there is */ /* at least one codepoint beyond the */ /* Basic Multilingual Plane that is */ /* supported by this font. So it really */ /* means >= U+10000 */ #define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ /* U+DB80-U+DBFF */ /* U+DC00-U+DFFF */ #define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES /* Bit 58 Phoenician */ #define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ /* Bit 59 CJK Unified Ideographs */ /* CJK Radicals Supplement */ /* Kangxi Radicals */ /* Ideographic Description Characters */ /* CJK Unified Ideographs Extension A */ /* CJK Unified Ideographs Extension B */ /* Kanbun */ #define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ /* U+2E80-U+2EFF */ /* U+2F00-U+2FDF */ /* U+2FF0-U+2FFF */ /* U+3400-U+4DB5 */ /*U+20000-U+2A6DF*/ /* U+3190-U+319F */ /* Bit 60 Private Use */ #define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ /* Bit 61 CJK Strokes */ /* CJK Compatibility Ideographs */ /* CJK Compatibility Ideographs Supplement */ #define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ /* U+F900-U+FAFF */ /*U+2F800-U+2FA1F*/ /* Bit 62 Alphabetic Presentation Forms */ #define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ /* Bit 63 Arabic Presentation Forms-A */ #define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ /* Bit 64 Combining Half Marks */ #define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ /* Bit 65 Vertical forms */ /* CJK Compatibility Forms */ #define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ /* U+FE30-U+FE4F */ /* Bit 66 Small Form Variants */ #define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ /* Bit 67 Arabic Presentation Forms-B */ #define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ /* Bit 68 Halfwidth and Fullwidth Forms */ #define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ /* Bit 69 Specials */ #define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ /* Bit 70 Tibetan */ #define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ /* Bit 71 Syriac */ #define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ /* Bit 72 Thaana */ #define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ /* Bit 73 Sinhala */ #define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ /* Bit 74 Myanmar */ #define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ /* Bit 75 Ethiopic */ /* Ethiopic Supplement */ /* Ethiopic Extended */ #define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ /* U+1380-U+139F */ /* U+2D80-U+2DDF */ /* Bit 76 Cherokee */ #define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ /* Bit 77 Unified Canadian Aboriginal Syllabics */ #define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ /* Bit 78 Ogham */ #define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ /* Bit 79 Runic */ #define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ /* Bit 80 Khmer */ /* Khmer Symbols */ #define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ /* U+19E0-U+19FF */ /* Bit 81 Mongolian */ #define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ /* Bit 82 Braille Patterns */ #define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ /* Bit 83 Yi Syllables */ /* Yi Radicals */ #define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ /* U+A490-U+A4CF */ /* Bit 84 Tagalog */ /* Hanunoo */ /* Buhid */ /* Tagbanwa */ #define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ /* U+1720-U+173F */ /* U+1740-U+175F */ /* U+1760-U+177F */ /* Bit 85 Old Italic */ #define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ /* Bit 86 Gothic */ #define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ /* Bit 87 Deseret */ #define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ /* Bit 88 Byzantine Musical Symbols */ /* Musical Symbols */ /* Ancient Greek Musical Notation */ #define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ /*U+1D100-U+1D1FF*/ /*U+1D200-U+1D24F*/ /* Bit 89 Mathematical Alphanumeric Symbols */ #define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ /* Bit 90 Private Use (plane 15) */ /* Private Use (plane 16) */ #define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ /*U+100000-U+10FFFD*/ /* Bit 91 Variation Selectors */ /* Variation Selectors Supplement */ #define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ /*U+E0100-U+E01EF*/ /* Bit 92 Tags */ #define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ /* Bit 93 Limbu */ #define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ /* Bit 94 Tai Le */ #define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ /* Bit 95 New Tai Lue */ #define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ /* Bit 96 Buginese */ #define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ /* Bit 97 Glagolitic */ #define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ /* Bit 98 Tifinagh */ #define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ /* Bit 99 Yijing Hexagram Symbols */ #define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ /* Bit 100 Syloti Nagri */ #define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ /* Bit 101 Linear B Syllabary */ /* Linear B Ideograms */ /* Aegean Numbers */ #define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ /*U+10080-U+100FF*/ /*U+10100-U+1013F*/ /* Bit 102 Ancient Greek Numbers */ #define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ /* Bit 103 Ugaritic */ #define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ /* Bit 104 Old Persian */ #define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ /* Bit 105 Shavian */ #define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ /* Bit 106 Osmanya */ #define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ /* Bit 107 Cypriot Syllabary */ #define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ /* Bit 108 Kharoshthi */ #define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ /* Bit 109 Tai Xuan Jing Symbols */ #define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ /* Bit 110 Cuneiform */ /* Cuneiform Numbers and Punctuation */ #define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ /*U+12400-U+1247F*/ /* Bit 111 Counting Rod Numerals */ #define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ /* Bit 112 Sundanese */ #define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ /* Bit 113 Lepcha */ #define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ /* Bit 114 Ol Chiki */ #define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ /* Bit 115 Saurashtra */ #define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ /* Bit 116 Kayah Li */ #define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ /* Bit 117 Rejang */ #define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ /* Bit 118 Cham */ #define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ /* Bit 119 Ancient Symbols */ #define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ /* Bit 120 Phaistos Disc */ #define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ /* Bit 121 Carian */ /* Lycian */ /* Lydian */ #define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ /*U+10280-U+1029F*/ /*U+10920-U+1093F*/ /* Bit 122 Domino Tiles */ /* Mahjong Tiles */ #define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ /*U+1F000-U+1F02F*/ /* Bit 123-127 Reserved for process-internal usage */ /*************************************************************************/ /* */ /* Some compilers have a very limited length of identifiers. */ /* */ #if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) #define HAVE_LIMIT_ON_IDENTS #endif #ifndef HAVE_LIMIT_ON_IDENTS /*************************************************************************/ /* */ /* Here some alias #defines in order to be clearer. */ /* */ /* These are not always #defined to stay within the 31~character limit */ /* which some compilers have. */ /* */ /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */ /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ /* If you get a warning with such a compiler, use the -i40 switch. */ /* */ #define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ TT_UCR_ARABIC_PRESENTATIONS_A #define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ TT_UCR_ARABIC_PRESENTATIONS_B #define TT_UCR_COMBINING_DIACRITICAL_MARKS \ TT_UCR_COMBINING_DIACRITICS #define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ TT_UCR_COMBINING_DIACRITICS_SYMB #endif /* !HAVE_LIMIT_ON_IDENTS */ FT_END_HEADER #endif /* __TTNAMEID_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/tttables.h ================================================ /***************************************************************************/ /* */ /* tttables.h */ /* */ /* Basic SFNT/TrueType tables definitions and interface */ /* (specification only). */ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __TTTABLES_H__ #define __TTTABLES_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************/ /* */ /* <Section> */ /* truetype_tables */ /* */ /* <Title> */ /* TrueType Tables */ /* */ /* <Abstract> */ /* TrueType specific table types and functions. */ /* */ /* <Description> */ /* This section contains the definition of TrueType-specific tables */ /* as well as some routines used to access and process them. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* <Struct> */ /* TT_Header */ /* */ /* <Description> */ /* A structure used to model a TrueType font header table. All */ /* fields follow the TrueType specification. */ /* */ typedef struct TT_Header_ { FT_Fixed Table_Version; FT_Fixed Font_Revision; FT_Long CheckSum_Adjust; FT_Long Magic_Number; FT_UShort Flags; FT_UShort Units_Per_EM; FT_Long Created [2]; FT_Long Modified[2]; FT_Short xMin; FT_Short yMin; FT_Short xMax; FT_Short yMax; FT_UShort Mac_Style; FT_UShort Lowest_Rec_PPEM; FT_Short Font_Direction; FT_Short Index_To_Loc_Format; FT_Short Glyph_Data_Format; } TT_Header; /*************************************************************************/ /* */ /* <Struct> */ /* TT_HoriHeader */ /* */ /* <Description> */ /* A structure used to model a TrueType horizontal header, the `hhea' */ /* table, as well as the corresponding horizontal metrics table, */ /* i.e., the `hmtx' table. */ /* */ /* <Fields> */ /* Version :: The table version. */ /* */ /* Ascender :: The font's ascender, i.e., the distance */ /* from the baseline to the top-most of all */ /* glyph points found in the font. */ /* */ /* This value is invalid in many fonts, as */ /* it is usually set by the font designer, */ /* and often reflects only a portion of the */ /* glyphs found in the font (maybe ASCII). */ /* */ /* You should use the `sTypoAscender' field */ /* of the OS/2 table instead if you want */ /* the correct one. */ /* */ /* Descender :: The font's descender, i.e., the distance */ /* from the baseline to the bottom-most of */ /* all glyph points found in the font. It */ /* is negative. */ /* */ /* This value is invalid in many fonts, as */ /* it is usually set by the font designer, */ /* and often reflects only a portion of the */ /* glyphs found in the font (maybe ASCII). */ /* */ /* You should use the `sTypoDescender' */ /* field of the OS/2 table instead if you */ /* want the correct one. */ /* */ /* Line_Gap :: The font's line gap, i.e., the distance */ /* to add to the ascender and descender to */ /* get the BTB, i.e., the */ /* baseline-to-baseline distance for the */ /* font. */ /* */ /* advance_Width_Max :: This field is the maximum of all advance */ /* widths found in the font. It can be */ /* used to compute the maximum width of an */ /* arbitrary string of text. */ /* */ /* min_Left_Side_Bearing :: The minimum left side bearing of all */ /* glyphs within the font. */ /* */ /* min_Right_Side_Bearing :: The minimum right side bearing of all */ /* glyphs within the font. */ /* */ /* xMax_Extent :: The maximum horizontal extent (i.e., the */ /* `width' of a glyph's bounding box) for */ /* all glyphs in the font. */ /* */ /* caret_Slope_Rise :: The rise coefficient of the cursor's */ /* slope of the cursor (slope=rise/run). */ /* */ /* caret_Slope_Run :: The run coefficient of the cursor's */ /* slope. */ /* */ /* Reserved :: 8~reserved bytes. */ /* */ /* metric_Data_Format :: Always~0. */ /* */ /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ /* table -- this value can be smaller than */ /* the total number of glyphs in the font. */ /* */ /* long_metrics :: A pointer into the `hmtx' table. */ /* */ /* short_metrics :: A pointer into the `hmtx' table. */ /* */ /* <Note> */ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ /* be identical except for the names of their fields which */ /* are different. */ /* */ /* This ensures that a single function in the `ttload' */ /* module is able to read both the horizontal and vertical */ /* headers. */ /* */ typedef struct TT_HoriHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Width_Max; /* advance width maximum */ FT_Short min_Left_Side_Bearing; /* minimum left-sb */ FT_Short min_Right_Side_Bearing; /* minimum right-sb */ FT_Short xMax_Extent; /* xmax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_HMetrics; /* The following fields are not defined by the TrueType specification */ /* but they are used to connect the metrics header to the relevant */ /* `HMTX' table. */ void* long_metrics; void* short_metrics; } TT_HoriHeader; /*************************************************************************/ /* */ /* <Struct> */ /* TT_VertHeader */ /* */ /* <Description> */ /* A structure used to model a TrueType vertical header, the `vhea' */ /* table, as well as the corresponding vertical metrics table, i.e., */ /* the `vmtx' table. */ /* */ /* <Fields> */ /* Version :: The table version. */ /* */ /* Ascender :: The font's ascender, i.e., the distance */ /* from the baseline to the top-most of */ /* all glyph points found in the font. */ /* */ /* This value is invalid in many fonts, as */ /* it is usually set by the font designer, */ /* and often reflects only a portion of */ /* the glyphs found in the font (maybe */ /* ASCII). */ /* */ /* You should use the `sTypoAscender' */ /* field of the OS/2 table instead if you */ /* want the correct one. */ /* */ /* Descender :: The font's descender, i.e., the */ /* distance from the baseline to the */ /* bottom-most of all glyph points found */ /* in the font. It is negative. */ /* */ /* This value is invalid in many fonts, as */ /* it is usually set by the font designer, */ /* and often reflects only a portion of */ /* the glyphs found in the font (maybe */ /* ASCII). */ /* */ /* You should use the `sTypoDescender' */ /* field of the OS/2 table instead if you */ /* want the correct one. */ /* */ /* Line_Gap :: The font's line gap, i.e., the distance */ /* to add to the ascender and descender to */ /* get the BTB, i.e., the */ /* baseline-to-baseline distance for the */ /* font. */ /* */ /* advance_Height_Max :: This field is the maximum of all */ /* advance heights found in the font. It */ /* can be used to compute the maximum */ /* height of an arbitrary string of text. */ /* */ /* min_Top_Side_Bearing :: The minimum top side bearing of all */ /* glyphs within the font. */ /* */ /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ /* glyphs within the font. */ /* */ /* yMax_Extent :: The maximum vertical extent (i.e., the */ /* `height' of a glyph's bounding box) for */ /* all glyphs in the font. */ /* */ /* caret_Slope_Rise :: The rise coefficient of the cursor's */ /* slope of the cursor (slope=rise/run). */ /* */ /* caret_Slope_Run :: The run coefficient of the cursor's */ /* slope. */ /* */ /* caret_Offset :: The cursor's offset for slanted fonts. */ /* This value is `reserved' in vmtx */ /* version 1.0. */ /* */ /* Reserved :: 8~reserved bytes. */ /* */ /* metric_Data_Format :: Always~0. */ /* */ /* number_Of_HMetrics :: Number of VMetrics entries in the */ /* `vmtx' table -- this value can be */ /* smaller than the total number of glyphs */ /* in the font. */ /* */ /* long_metrics :: A pointer into the `vmtx' table. */ /* */ /* short_metrics :: A pointer into the `vmtx' table. */ /* */ /* <Note> */ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ /* be identical except for the names of their fields which */ /* are different. */ /* */ /* This ensures that a single function in the `ttload' */ /* module is able to read both the horizontal and vertical */ /* headers. */ /* */ typedef struct TT_VertHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Height_Max; /* advance height maximum */ FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ FT_Short yMax_Extent; /* xmax or ymax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_VMetrics; /* The following fields are not defined by the TrueType specification */ /* but they're used to connect the metrics header to the relevant */ /* `HMTX' or `VMTX' table. */ void* long_metrics; void* short_metrics; } TT_VertHeader; /*************************************************************************/ /* */ /* <Struct> */ /* TT_OS2 */ /* */ /* <Description> */ /* A structure used to model a TrueType OS/2 table. This is the long */ /* table version. All fields comply to the TrueType specification. */ /* */ /* Note that we now support old Mac fonts which do not include an */ /* OS/2 table. In this case, the `version' field is always set to */ /* 0xFFFF. */ /* */ typedef struct TT_OS2_ { FT_UShort version; /* 0x0001 - more or 0xFFFF */ FT_Short xAvgCharWidth; FT_UShort usWeightClass; FT_UShort usWidthClass; FT_Short fsType; FT_Short ySubscriptXSize; FT_Short ySubscriptYSize; FT_Short ySubscriptXOffset; FT_Short ySubscriptYOffset; FT_Short ySuperscriptXSize; FT_Short ySuperscriptYSize; FT_Short ySuperscriptXOffset; FT_Short ySuperscriptYOffset; FT_Short yStrikeoutSize; FT_Short yStrikeoutPosition; FT_Short sFamilyClass; FT_Byte panose[10]; FT_ULong ulUnicodeRange1; /* Bits 0-31 */ FT_ULong ulUnicodeRange2; /* Bits 32-63 */ FT_ULong ulUnicodeRange3; /* Bits 64-95 */ FT_ULong ulUnicodeRange4; /* Bits 96-127 */ FT_Char achVendID[4]; FT_UShort fsSelection; FT_UShort usFirstCharIndex; FT_UShort usLastCharIndex; FT_Short sTypoAscender; FT_Short sTypoDescender; FT_Short sTypoLineGap; FT_UShort usWinAscent; FT_UShort usWinDescent; /* only version 1 tables: */ FT_ULong ulCodePageRange1; /* Bits 0-31 */ FT_ULong ulCodePageRange2; /* Bits 32-63 */ /* only version 2 tables: */ FT_Short sxHeight; FT_Short sCapHeight; FT_UShort usDefaultChar; FT_UShort usBreakChar; FT_UShort usMaxContext; } TT_OS2; /*************************************************************************/ /* */ /* <Struct> */ /* TT_Postscript */ /* */ /* <Description> */ /* A structure used to model a TrueType PostScript table. All fields */ /* comply to the TrueType specification. This structure does not */ /* reference the PostScript glyph names, which can be nevertheless */ /* accessed with the `ttpost' module. */ /* */ typedef struct TT_Postscript_ { FT_Fixed FormatType; FT_Fixed italicAngle; FT_Short underlinePosition; FT_Short underlineThickness; FT_ULong isFixedPitch; FT_ULong minMemType42; FT_ULong maxMemType42; FT_ULong minMemType1; FT_ULong maxMemType1; /* Glyph names follow in the file, but we don't */ /* load them by default. See the ttpost.c file. */ } TT_Postscript; /*************************************************************************/ /* */ /* <Struct> */ /* TT_PCLT */ /* */ /* <Description> */ /* A structure used to model a TrueType PCLT table. All fields */ /* comply to the TrueType specification. */ /* */ typedef struct TT_PCLT_ { FT_Fixed Version; FT_ULong FontNumber; FT_UShort Pitch; FT_UShort xHeight; FT_UShort Style; FT_UShort TypeFamily; FT_UShort CapHeight; FT_UShort SymbolSet; FT_Char TypeFace[16]; FT_Char CharacterComplement[8]; FT_Char FileName[6]; FT_Char StrokeWeight; FT_Char WidthType; FT_Byte SerifStyle; FT_Byte Reserved; } TT_PCLT; /*************************************************************************/ /* */ /* <Struct> */ /* TT_MaxProfile */ /* */ /* <Description> */ /* The maximum profile is a table containing many max values which */ /* can be used to pre-allocate arrays. This ensures that no memory */ /* allocation occurs during a glyph load. */ /* */ /* <Fields> */ /* version :: The version number. */ /* */ /* numGlyphs :: The number of glyphs in this TrueType */ /* font. */ /* */ /* maxPoints :: The maximum number of points in a */ /* non-composite TrueType glyph. See also */ /* the structure element */ /* `maxCompositePoints'. */ /* */ /* maxContours :: The maximum number of contours in a */ /* non-composite TrueType glyph. See also */ /* the structure element */ /* `maxCompositeContours'. */ /* */ /* maxCompositePoints :: The maximum number of points in a */ /* composite TrueType glyph. See also the */ /* structure element `maxPoints'. */ /* */ /* maxCompositeContours :: The maximum number of contours in a */ /* composite TrueType glyph. See also the */ /* structure element `maxContours'. */ /* */ /* maxZones :: The maximum number of zones used for */ /* glyph hinting. */ /* */ /* maxTwilightPoints :: The maximum number of points in the */ /* twilight zone used for glyph hinting. */ /* */ /* maxStorage :: The maximum number of elements in the */ /* storage area used for glyph hinting. */ /* */ /* maxFunctionDefs :: The maximum number of function */ /* definitions in the TrueType bytecode for */ /* this font. */ /* */ /* maxInstructionDefs :: The maximum number of instruction */ /* definitions in the TrueType bytecode for */ /* this font. */ /* */ /* maxStackElements :: The maximum number of stack elements used */ /* during bytecode interpretation. */ /* */ /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ /* used for glyph hinting. */ /* */ /* maxComponentElements :: The maximum number of simple (i.e., non- */ /* composite) glyphs in a composite glyph. */ /* */ /* maxComponentDepth :: The maximum nesting depth of composite */ /* glyphs. */ /* */ /* <Note> */ /* This structure is only used during font loading. */ /* */ typedef struct TT_MaxProfile_ { FT_Fixed version; FT_UShort numGlyphs; FT_UShort maxPoints; FT_UShort maxContours; FT_UShort maxCompositePoints; FT_UShort maxCompositeContours; FT_UShort maxZones; FT_UShort maxTwilightPoints; FT_UShort maxStorage; FT_UShort maxFunctionDefs; FT_UShort maxInstructionDefs; FT_UShort maxStackElements; FT_UShort maxSizeOfInstructions; FT_UShort maxComponentElements; FT_UShort maxComponentDepth; } TT_MaxProfile; /*************************************************************************/ /* */ /* <Enum> */ /* FT_Sfnt_Tag */ /* */ /* <Description> */ /* An enumeration used to specify the index of an SFNT table. */ /* Used in the @FT_Get_Sfnt_Table API function. */ /* */ typedef enum FT_Sfnt_Tag_ { ft_sfnt_head = 0, ft_sfnt_maxp = 1, ft_sfnt_os2 = 2, ft_sfnt_hhea = 3, ft_sfnt_vhea = 4, ft_sfnt_post = 5, ft_sfnt_pclt = 6, sfnt_max /* internal end mark */ } FT_Sfnt_Tag; /* */ /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_Sfnt_Table */ /* */ /* <Description> */ /* Return a pointer to a given SFNT table within a face. */ /* */ /* <Input> */ /* face :: A handle to the source. */ /* */ /* tag :: The index of the SFNT table. */ /* */ /* <Return> */ /* A type-less pointer to the table. This will be~0 in case of */ /* error, or if the corresponding table was not found *OR* loaded */ /* from the file. */ /* */ /* <Note> */ /* The table is owned by the face object and disappears with it. */ /* */ /* This function is only useful to access SFNT tables that are loaded */ /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */ /* a list. */ /* */ FT_EXPORT( void* ) FT_Get_Sfnt_Table( FT_Face face, FT_Sfnt_Tag tag ); /************************************************************************** * * @function: * FT_Load_Sfnt_Table * * @description: * Load any font table into client memory. * * @input: * face :: * A handle to the source face. * * tag :: * The four-byte tag of the table to load. Use the value~0 if you want * to access the whole font file. Otherwise, you can use one of the * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new * one with @FT_MAKE_TAG. * * offset :: * The starting offset in the table (or file if tag == 0). * * @output: * buffer :: * The target buffer address. The client must ensure that the memory * array is big enough to hold the data. * * @inout: * length :: * If the `length' parameter is NULL, then try to load the whole table. * Return an error code if it fails. * * Else, if `*length' is~0, exit immediately while returning the * table's (or file) full size in it. * * Else the number of bytes to read from the table or file, from the * starting offset. * * @return: * FreeType error code. 0~means success. * * @note: * If you need to determine the table's length you should first call this * function with `*length' set to~0, as in the following example: * * { * FT_ULong length = 0; * * * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); * if ( error ) { ... table does not exist ... } * * buffer = malloc( length ); * if ( buffer == NULL ) { ... not enough memory ... } * * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); * if ( error ) { ... could not load table ... } * } */ FT_EXPORT( FT_Error ) FT_Load_Sfnt_Table( FT_Face face, FT_ULong tag, FT_Long offset, FT_Byte* buffer, FT_ULong* length ); /************************************************************************** * * @function: * FT_Sfnt_Table_Info * * @description: * Return information on an SFNT table. * * @input: * face :: * A handle to the source face. * * table_index :: * The index of an SFNT table. The function returns * FT_Err_Table_Missing for an invalid value. * * @output: * tag :: * The name tag of the SFNT table. * * length :: * The length of the SFNT table. * * @return: * FreeType error code. 0~means success. * * @note: * SFNT tables with length zero are treated as missing. * */ FT_EXPORT( FT_Error ) FT_Sfnt_Table_Info( FT_Face face, FT_UInt table_index, FT_ULong *tag, FT_ULong *length ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_CMap_Language_ID */ /* */ /* <Description> */ /* Return TrueType/sfnt specific cmap language ID. Definitions of */ /* language ID values are in `freetype/ttnameid.h'. */ /* */ /* <Input> */ /* charmap :: */ /* The target charmap. */ /* */ /* <Return> */ /* The language ID of `charmap'. If `charmap' doesn't belong to a */ /* TrueType/sfnt face, just return~0 as the default value. */ /* */ FT_EXPORT( FT_ULong ) FT_Get_CMap_Language_ID( FT_CharMap charmap ); /*************************************************************************/ /* */ /* <Function> */ /* FT_Get_CMap_Format */ /* */ /* <Description> */ /* Return TrueType/sfnt specific cmap format. */ /* */ /* <Input> */ /* charmap :: */ /* The target charmap. */ /* */ /* <Return> */ /* The format of `charmap'. If `charmap' doesn't belong to a */ /* TrueType/sfnt face, return -1. */ /* */ FT_EXPORT( FT_Long ) FT_Get_CMap_Format( FT_CharMap charmap ); /* */ FT_END_HEADER #endif /* __TTTABLES_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/tttags.h ================================================ /***************************************************************************/ /* */ /* tttags.h */ /* */ /* Tags for TrueType and OpenType tables (specification only). */ /* */ /* Copyright 1996-2001, 2004, 2005, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __TTAGS_H__ #define __TTAGS_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER #define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' ) #define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' ) #define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) #define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' ) #define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' ) #define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) #define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' ) #define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) #define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) #define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) #define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' ) #define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) #define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) #define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) #define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) #define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) #define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' ) #define TTAG_FOND FT_MAKE_TAG( 'F', 'O', 'N', 'D' ) #define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) #define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) #define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) #define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' ) #define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' ) #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) #define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' ) #define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) #define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) #define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) #define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) #define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' ) #define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' ) #define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) #define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' ) #define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) #define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) #define TTAG_LWFN FT_MAKE_TAG( 'L', 'W', 'F', 'N' ) #define TTAG_MATH FT_MAKE_TAG( 'M', 'A', 'T', 'H' ) #define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) #define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' ) #define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) #define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) #define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' ) #define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' ) #define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) #define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' ) #define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) #define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) #define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) #define TTAG_POST FT_MAKE_TAG( 'P', 'O', 'S', 'T' ) #define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) #define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) #define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' ) #define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' ) #define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' ) #define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' ) #define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) #define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) #define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) #define TTAG_TYP1 FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) #define TTAG_typ1 FT_MAKE_TAG( 't', 'y', 'p', '1' ) #define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) #define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) #define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) FT_END_HEADER #endif /* __TTAGS_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/freetype2/freetype/ttunpat.h ================================================ /***************************************************************************/ /* */ /* ttunpat.h */ /* */ /* Definitions for the unpatented TrueType hinting system */ /* */ /* Copyright 2003, 2006 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Written by Graham Asher <graham.asher@btinternet.com> */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #ifndef __TTUNPAT_H__ #define __TTUNPAT_H__ #include <ft2build.h> #include FT_FREETYPE_H #ifdef FREETYPE_H #error "freetype.h of FreeType 1 has been loaded!" #error "Please fix the directory search order for header files" #error "so that freetype.h of FreeType 2 is found first." #endif FT_BEGIN_HEADER /*************************************************************************** * * @constant: * FT_PARAM_TAG_UNPATENTED_HINTING * * @description: * A constant used as the tag of an @FT_Parameter structure to indicate * that unpatented methods only should be used by the TrueType bytecode * interpreter for a typeface opened by @FT_Open_Face. * */ #define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' ) /* */ FT_END_HEADER #endif /* __TTUNPAT_H__ */ /* END */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/FT2Plugin/macFileNameBits.c ================================================ /* * macFileNameBits.c * FT2Plugin support * * Created by John M McIntosh on 21/11/05. * Feb 15th, 2006, use sqFilenameFromString * */ #include "sqVirtualMachine.h" extern struct VirtualMachine * interpreterProxy; void sqFilenameFromString(char *buffer,long fileIndex, long fileLength) { interpreterProxy->ioFilenamefromStringofLengthresolveAliases(buffer,fileIndex, fileLength, 1); } void fetchPreferences() {} /* int IsImageName(char *name) { return 1; }; int isSystem9_0_or_better(void) { return 1; } CFStringEncoding gCurrentVMEncoding=kCFStringEncodingMacRoman; void fetchPreferences() { CFBundleRef myBundle; CFDictionaryRef myDictionary; CFStringRef SqueakVMEncodingType; char encoding[256]; myBundle = CFBundleGetMainBundle(); myDictionary = CFBundleGetInfoDictionary(myBundle); SqueakVMEncodingType = CFDictionaryGetValue(myDictionary, CFSTR("SqueakEncodingType")); if (SqueakVMEncodingType) CFStringGetCString (SqueakVMEncodingType, encoding, 256, kCFStringEncodingMacRoman); else *encoding = 0x00; gCurrentVMEncoding = kCFStringEncodingMacRoman; if (strcmp("UTF-8",encoding) == 0) gCurrentVMEncoding = kCFStringEncodingUTF8; if (strcmp("ShiftJIS",encoding) == 0) gCurrentVMEncoding = kCFStringEncodingShiftJIS; } */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Error_Handler.c ================================================ /* File: Error Handler.c Contains: Implementation of the HID utility error handlers for the HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if !defined (kBuildingLibrary) #define kVerboseErrors // system includes ---------------------------------------------------------- #ifdef kVerboseErrors #include <Carbon/Carbon.h> #endif #endif // not kBuildingLibrary #include <stdio.h> // project includes --------------------------------------------------------- #include "HID_Utilities_Internal.h" // globals (internal/private) ----------------------------------------------- // prototypes (internal/private) -------------------------------------------- // functions (internal/private) --------------------------------------------- #pragma mark - // ------------------------------------- // central error reporting void HIDReportErrorNum (char * strError, long numError) { char errMsgCStr [256]; sprintf (errMsgCStr, "%s #%ld (0x%lx)", strError, numError, numError); // out as debug string #ifdef kVerboseErrors { Str255 strErr = "\p"; CopyCStringToPascal (errMsgCStr, strErr); DebugStr (strErr); } #endif // kVerboseErrors } // ------------------------------------- void HIDReportError (char * strError) { char errMsgCStr [256]; sprintf (errMsgCStr, "%s", strError); // out as debug string #ifdef kVerboseErrors { Str255 strErr = "\p"; CopyCStringToPascal (errMsgCStr, strErr); DebugStr (strErr); } #endif // kVerboseErrors } ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Error_Handler.h ================================================ /* File: HID_Error_Handler.h Contains: Definition of the interfaces to <HID_Error_Handler.c> DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Usage notes: // include control -------------------------------------------------- #ifndef Error_Handler_h #define Error_Handler_h // includes --------------------------------------------------------- #ifdef __cplusplus extern "C" { #endif // structures (public) ----------------------------------------------- // public function declarations ------------------------------------- // Error reporter, can be set to report however the application desires extern void HIDReportError (char * strError); // Error with numeric code reporter, can be set to report however the application desires extern void HIDReportErrorNum (char * strError, long numError); #ifdef __cplusplus } #endif #endif // Error_Handler_h ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Name_Lookup.c ================================================ /* File: HID_Name_Lookup.c Contains: Implementation of the HID device name lookup functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HID_Utilities_Internal.h" #include "HID_Name_Lookup.h" #define FAKE_IT 1 // set true for debugging; returns the vendor, product & cookie (or usage info) as numbers. // --------------------------------- // Load the element strings from the given resource (XML) file into a CFPropertyListRef static CFPropertyListRef xml_load(const CFStringRef pResourceName,const CFStringRef pResourceExtension) { CFPropertyListRef tCFPropertyListRef = NULL; CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), pResourceName, pResourceExtension, NULL); if (NULL != resFileCFURLRef) { CFDataRef resCFDataRef; if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) { if (NULL != resCFDataRef) { CFStringRef errorString; tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); if (NULL == tCFPropertyListRef) CFShow(errorString); CFRelease(resCFDataRef); } } CFRelease(resFileCFURLRef); } return tCFPropertyListRef; } // --------------------------------- // Find an element string in the <HID_cookie_strings.plist> resource (XML) file static Boolean xml_search_cookie(const long pVendorID, const long pProductID, const long pCookie, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load(CFSTR("HID_cookie_strings"), CFSTR("plist")); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef vendorCFDictionaryRef; CFStringRef vendorKeyCFStringRef; vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) { CFDictionaryRef productCFDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef vendorCFStringRef; if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) { //CFShow(vendorCFStringRef); } productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) { CFStringRef fullCFStringRef = NULL; CFStringRef cookieKeyCFStringRef; CFStringRef productCFStringRef; CFStringRef cookieCFStringRef; if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) { //CFShow(productCFStringRef); } cookieKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pCookie); if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, cookieKeyCFStringRef, (const void**) &cookieCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, cookieCFStringRef); // CFShow(cookieCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), vendorCFStringRef, productCFStringRef, cookieKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(cookieKeyCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } // --------------------------------- // Find an element string in the <HID_device_usage_strings.plist> resource (XML) file static Boolean xml_search_usage(const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load(CFSTR("HID_device_usage_strings"), CFSTR("plist")); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef vendorCFDictionaryRef; CFStringRef vendorKeyCFStringRef; vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef)) { CFDictionaryRef productCFDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef vendorCFStringRef; if (!CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef)) { vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("v: %ld"), pVendorID); //CFShow(vendorCFStringRef); } productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID); if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef)) { CFStringRef fullCFStringRef = NULL; CFStringRef usageKeyCFStringRef; CFStringRef productCFStringRef; CFStringRef usageCFStringRef; if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef)) { //CFShow(productCFStringRef); } usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), pUsagePage, pUsage); if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, usageCFStringRef); // CFShow(usageCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"), vendorCFStringRef, productCFStringRef, usageKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(usageKeyCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } // --------------------------------- // set name from vendor id/product id look up Boolean HIDGetElementNameFromVendorProductCookie (const long pVendorID, const long pProductID, const long pCookie, char * pName) { Boolean result = false; *pName = 0; // clear name if (xml_search_cookie(pVendorID, pProductID, pCookie, pName)) return true; switch (pVendorID) { case kMacally: switch (pProductID) { case kiShock: result = true; switch (pCookie) { case 3: sprintf(pName, "D-Pad Up"); break; case 4: sprintf(pName, "D-Pad Down"); break; case 5: sprintf(pName, "D-Pad Left"); break; case 6: sprintf(pName, "D-Pad Right"); break; case 7: sprintf(pName, "Up Button"); break; case 8: sprintf(pName, "Right Button"); break; case 9: sprintf(pName, "Down Button"); break; case 10: sprintf(pName, "Left Button"); break; case 11: sprintf(pName, "C Button"); break; case 12: sprintf(pName, "B Button [Select]"); break; case 13: sprintf(pName, "A Button [Start]"); break; case 14: sprintf(pName, "F Button"); break; case 15: sprintf(pName, "R1 Trigger"); break; case 16: sprintf(pName, "R2 Trigger"); break; case 17: sprintf(pName, "L1 Trigger"); break; case 18: sprintf(pName, "L2 Trigger"); break; case 19: sprintf(pName, "Left Stick Button"); break; case 20: sprintf(pName, "Right Stick Button"); break; case 21: sprintf(pName, "D Button"); break; case 22: sprintf(pName, "E Button"); break; case 23: sprintf(pName, "Left Stick X-Axis"); break; case 24: sprintf(pName, "Left Stick Y-Axis"); break; case 25: sprintf(pName, "Right Stick X-Axis"); break; case 26: sprintf(pName, "Right Stick Y-Axis"); break; default: #if FAKE_IT sprintf(pName, "#{V:Macally, P:iShock, C:%ld}#", pCookie); #else result = false; #endif FAKE_IT break; } break; default: #if FAKE_IT sprintf(pName, "#{V:Macally, P:%ld, C:%ld}#", pProductID, pCookie); break; #else result = false; #endif FAKE_IT break; } break; case kMacsense: switch (pProductID) { case kFunPadF107: result = true; switch (pCookie) { case 3: sprintf(pName, "Button 1"); break; case 4: sprintf(pName, "Button 2"); break; case 5: sprintf(pName, "Button 3"); break; case 6: sprintf(pName, "Button 4"); break; case 7: sprintf(pName, "L1 Trigger"); break; case 8: sprintf(pName, "R1 Trigger"); break; case 9: sprintf(pName, "L2 Trigger"); break; case 10: sprintf(pName, "R2 Trigger"); break; case 11: sprintf(pName, "Right Stick X-Axis"); break; case 12: sprintf(pName, "Right Stick Y-Axis"); break; case 13: sprintf(pName, "Left Stick X-Axis"); break; case 14: sprintf(pName, "Left Stick Y-Axis"); break; case 15: sprintf(pName, "Hat Switch"); break; default: #if FAKE_IT sprintf(pName, "#{V:Macsense, P:FunPad F-107, C:%ld}#", pCookie); #else result = false; #endif FAKE_IT break; } default: #if FAKE_IT sprintf(pName, "#{V:Macsense, P:%ld, C:%ld}#", pProductID, pCookie); #else result = false; #endif FAKE_IT break; } break; default: #if FAKE_IT sprintf(pName, "#{V:%ld, P:%ld, C:%ld}#", pVendorID, pProductID, pCookie); #else result = false; #endif FAKE_IT break; } return result; } // --------------------------------- // set name from vendor id/product id & usage look up Boolean HIDGetElementNameFromVendorProductUsage (const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char * pName) { Boolean result = false; *pName = 0; // clear name if (xml_search_usage(pVendorID, pProductID, pUsagePage, pUsage, pName)) return true; #if FAKE_IT sprintf(pName, "#{V:%ld, P:%ld, U:%ld:%ld}#", pVendorID, pProductID, pUsagePage, pUsage); result = true; #endif return result; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Name_Lookup.h ================================================ /* File: HID_Name_Lookup.h Contains: Definition of the HID device name lookup functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Name_Lookup_h_ #define _HID_Name_Lookup_h_ #include "HID_Utilities.h" // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== // Note: Now that as the device data has now been moved into external .XML files these // constansts should no longer be used. They will eventually be eliminated from this header. #define kMicrosoft 1118 #define kSideWinderFFB2 27 #define kLogitech 1133 #define kWingManStrikeForce3D 49797 #define kMacally 8738 #define kiShock 16400 #define kiShockIIFFB 16416 #define kMacsense 1635 #define kFunPadF107 38916 // ================================== // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // ================================== #ifdef __cplusplus } #endif #endif // _HID_Name_Lookup_h_ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Queue_Utilities.c ================================================ /* File: HID_Queue_Utilities.c Contains: Implementation of the HID queue functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //#include <IOKit/hid/IOHIDDevice.h> #include "HID_Utilities_Internal.h" #include "HID_Utilities_External.h" // ================================== // compiler directives // ================================== #define USE_ASYNC_EVENTS TRUE #define REPORT_ERRORS FALSE // ================================== #if REPORT_ERRORS #define HIDREPORTERRORNUM(s,n) HIDReportErrorNum(s,n) #define HIDREPORTERROR(s) HIDReportError(s) #else #define HIDREPORTERRORNUM(s,n) do {} while (false) #define HIDREPORTERROR(s) do {} while (false) #endif // ================================== // private functions // ================================== // creates a queue for a device static IOReturn hid_CreateQueue (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL == pDevice->queue) // do we already have a queue { if (NULL != pDevice->interface) { pDevice->queue = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocQueue (pDevice->interface); // alloc queue if (pDevice->queue) { result = (*(IOHIDQueueInterface**) pDevice->queue)->create (pDevice->queue, 0, kDeviceQueueSize); // create actual queue if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_CreateQueue - Failed to create queue via create", result); } else { HIDREPORTERROR ("hid_CreateQueue - Failed to alloc IOHIDQueueInterface ** via allocQueue"); result = kIOReturnError; // synthesis error } } else HIDREPORTERRORNUM ("hid_CreateQueue - Device inteface does not exist for queue creation", result); } } else HIDREPORTERRORNUM ("hid_CreateQueue - Invalid Device", result); return result; } // --------------------------------- // returns true if queue is empty false otherwise // error if no device, empty if no queue static unsigned char hid_IsDeviceQueueEmpty (pRecDevice pDevice) { if (HIDIsValidDevice(pDevice)) // need valid device { if (pDevice->queue) // and queue { pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); while (pElement) { if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) return false; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } else HIDREPORTERROR ("hid_IsDeviceQueueEmpty - no queue."); } else HIDREPORTERROR ("hid_IsDeviceQueueEmpty - Invalid device."); return true; } // --------------------------------- // disposes and releases queue, sets queue to NULL,. // Note: will have no effect if device or queue do not exist static IOReturn hid_DisposeReleaseQueue (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) // need valid device { if (pDevice->queue) // and queue { // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to stop queue.", result); // dispose of queue result = (*(IOHIDQueueInterface**) pDevice->queue)->dispose (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to dipose queue.", result); // release the queue result = (*(IOHIDQueueInterface**) pDevice->queue)->Release (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to release queue.", result); pDevice->queue = NULL; } else HIDREPORTERROR ("hid_DisposeReleaseQueue - no queue."); } else HIDREPORTERROR ("hid_DisposeReleaseQueue - Invalid device."); return result; } // ================================== // public functions // --------------------------------- // queues specific element, performing any device queue set up required // queue is started and ready to return events on exit from this function unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice,pElement)) { if (NULL == pDevice->interface) // must have interface { HIDREPORTERROR ("HIDQueueElement - Device does not have interface."); return kIOReturnError; } if (NULL == pDevice->queue) // if no queue create queue result = hid_CreateQueue (pDevice); if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) { HIDREPORTERRORNUM ("HIDQueueElement - problem creating queue.", result); if (kIOReturnSuccess != result) return result; else return kIOReturnError; } // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to stop queue."); // queue element if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to add Element to queue."); } // restart queue result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERROR ("HIDQueueElement - Failed to start queue."); } else { HIDREPORTERROR ("HIDQueueElement - Invalid Device and/or element."); return kIOReturnBadArgument; } return result; } // --------------------------------- // adds all elements to queue, performing any device queue set up required // queue is started and ready to return events on exit from this function unsigned long HIDQueueDevice (pRecDevice pDevice) { IOReturn result = kIOReturnError; // assume failure (pessimist!) pRecElement pElement; if (HIDIsValidDevice(pDevice)) { // error checking if (NULL == pDevice) { HIDREPORTERROR ("HIDQueueDevice - Device does not exist."); return kIOReturnBadArgument; } if (NULL == pDevice->interface) // must have interface { HIDREPORTERROR ("HIDQueueDevice - Device does not have interface."); return kIOReturnError; } if (NULL == pDevice->queue) // if no queue create queue result = hid_CreateQueue (pDevice); if ((kIOReturnSuccess != result) || (NULL == pDevice->queue)) { HIDREPORTERRORNUM ("HIDQueueDevice - problem creating queue.", result); if (kIOReturnSuccess != result) return result; else return kIOReturnError; } // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to stop queue.", result); // queue element // pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput | kHIDElementTypeFeature); while (pElement) { if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to add element to queue.", result); } // pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput | kHIDElementTypeFeature); } // start queue result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDQueueDevice - Failed to start queue.", result); } else HIDREPORTERROR ("HIDQueueDevice - Invalid device."); return result; } // --------------------------------- // removes element for queue, if last element in queue will release queue and closes device interface unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice,pElement)) { if (!pDevice || !pElement) result = kIOReturnBadArgument; else { if ((pDevice->interface) && (pDevice->queue)) { // stop queue result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to stop queue.", result); if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) // if has element then remove { result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to add element to queue", result); } if (hid_IsDeviceQueueEmpty (pDevice)) // release device queue and close interface if queue empty { result = hid_DisposeReleaseQueue (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to dispose and release queue.", result); } else // not empty so restart queue { result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueElement - Failed to start queue.", result); } } else { HIDREPORTERROR ("HIDDequeueElement - No device inteface or queue."); return kIOReturnError; } } } else HIDREPORTERROR ("HIDDequeueElement - Invalid device."); return result; } // --------------------------------- // completely removes all elements from queue and releases queue and closes device interface // does not release device interfaces, application must call HIDReleaseDeviceList on exit unsigned long HIDDequeueDevice (pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; if (HIDIsValidDevice(pDevice)) { if ((pDevice->interface) && (pDevice->queue)) { // iterate through elements and if queued, remove pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); while (pElement) { if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) { result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDDequeueDevice - Failed to remove element from queue.", result); } pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } // ensure queue is disposed and released // interface will be closed and released on call to HIDReleaseDeviceList result = hid_DisposeReleaseQueue (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("removeElement - Failed to dispose and release queue.", result); #if USE_ASYNC_EVENTS else if (NULL != pDevice->queueRunLoopSource) { if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); CFRelease(pDevice->queueRunLoopSource); pDevice->queueRunLoopSource = NULL; } #endif USE_ASYNC_EVENTS } else { HIDREPORTERROR ("HIDDequeueDevice - Invalid device."); result = kIOReturnBadArgument; } return result; } // --------------------------------- // releases all device queues for quit or rebuild (must be called) // does not release device interfaces, application must call HIDReleaseDeviceList on exit unsigned long HIDReleaseAllDeviceQueues (void) { IOReturn result = kIOReturnBadArgument; pRecDevice pDevice = HIDGetFirstDevice (); while (pDevice) { result = HIDDequeueDevice (pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDReleaseAllDeviceQueues - Could not dequeue device.", result); pDevice = HIDGetNextDevice (pDevice); } return result; } // --------------------------------- // Closes and releases interface to device, should be done prior to exting application // Note: will have no affect if device or interface do not exist // application will "own" the device if interface is not closed // (device may have to be plug and re-plugged in different location to get it working again without a restart) unsigned long HIDCloseReleaseInterface (pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; if (HIDIsValidDevice(pDevice) && (NULL != pDevice->interface)) { // close the interface result = (*(IOHIDDeviceInterface**) pDevice->interface)->close (pDevice->interface); if (kIOReturnNotOpen == result) { // do nothing as device was not opened, thus can't be closed } else if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to close IOHIDDeviceInterface.", result); //release the interface result = (*(IOHIDDeviceInterface**) pDevice->interface)->Release (pDevice->interface); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to release interface.", result); pDevice->interface = NULL; } return result; } // --------------------------------- // Get the next event in the queue for a device // elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition // Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility) unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent) { IOReturn result = kIOReturnBadArgument; AbsoluteTime zeroTime = {0,0}; if (HIDIsValidDevice(pDevice)) { if (pDevice->queue) { result = (*(IOHIDQueueInterface**) pDevice->queue)->getNextEvent (pDevice->queue, (IOHIDEventStruct *)pHIDEvent, zeroTime, 0); if (kIOReturnUnderrun == result) return false; // no events in queue not an error per say else if (kIOReturnSuccess != result) // actual error versus just an empty queue HIDREPORTERRORNUM ("HIDGetEvent - Could not get HID event via getNextEvent.", result); else return true; } else HIDREPORTERROR ("HIDGetEvent - queue does not exist."); } else HIDREPORTERROR ("HIDGetEvent - invalid device."); return false; // did not get event } // --------------------------------- // returns current value for element, polling element // will return 0 on error conditions which should be accounted for by application long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement) { IOReturn result = kIOReturnBadArgument; IOHIDEventStruct hidEvent; hidEvent.value = 0; hidEvent.longValueSize = 0; hidEvent.longValue = nil; if (HIDIsValidElement(pDevice, pElement)) { if (NULL != pDevice->interface) { // ++ NOTE: If the element type is feature then use queryElementValue instead of getElementValue if (kIOHIDElementTypeFeature == pElement->type) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->queryElementValue (pDevice->interface, pElement->cookie, &hidEvent,0,NULL,NULL,NULL); if (kIOReturnUnsupported == result) // unless it's unsuported. goto try_getElementValue; else if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via queryElementValue.", result); } else if (pElement->type <= kIOHIDElementTypeInput_ScanCodes) { try_getElementValue: result = (*(IOHIDDeviceInterface**) pDevice->interface)->getElementValue (pDevice->interface, pElement->cookie, &hidEvent); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via getElementValue.", result); } // on 10.0.x this returns the incorrect result for negative ranges, so fix it!!! // this is not required on Mac OS X 10.1+ if ((pElement->min < 0) && (hidEvent.value > pElement->max)) // assume range problem hidEvent.value = hidEvent.value + pElement->min - pElement->max - 1; } else HIDREPORTERROR ("HIDGetElementValue - no interface for device."); } else HIDREPORTERROR ("HIDGetElementValue - invalid device and/or element."); // record min and max for auto scale and auto ... if (hidEvent.value < pElement->calMin) pElement->calMin = hidEvent.value; if (hidEvent.value > pElement->calMax) pElement->calMax = hidEvent.value; // auto user scale return hidEvent.value; } // --------------------------------- // Set an elements value // NOTE: This should only be used when a single element of a report needs to be sent. // If multiple elements are to be send then transactions should be used. long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent) { IOHIDEventStruct* pMyIOHIDEvent = (IOHIDEventStruct*) pIOHIDEvent; IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidElement(pDevice, pElement)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->setElementValue (pDevice->interface, pElement->cookie, pMyIOHIDEvent, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetElementValue - Could not set HID element value via setElementValue.", result); } else HIDREPORTERROR ("HIDSetElementValue - no interface for device."); } else HIDREPORTERROR ("HIDSetElementValue - invalid device and/or element."); return result; } // --------------------------------- // Set a callback to be called when a queue goes from empty to non-empty long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { #if USE_ASYNC_EVENTS // if we don't have a queue runloop source if (NULL == pDevice->queueRunLoopSource) { // then create one result = (*(IOHIDQueueInterface**) pDevice->queue)->createAsyncEventSource((void *) pDevice->queue, (CFRunLoopSourceRef*) &pDevice->queueRunLoopSource); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetQueueCallback - Failed to createAsyncEventSource error: ", result); } // if we have one now if (NULL != pDevice->queueRunLoopSource) { // and it's not already attached to our runloop if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode)) // then attach it now. CFRunLoopAddSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode); } // now install our callback result = (*(IOHIDQueueInterface**) pDevice->queue)->setEventCallout(pDevice->queue, callback, pDevice, pDevice); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDSetQueueCallback - Could not set HID queue callback via setEventCallout.", result); #endif USE_ASYNC_EVENTS } else HIDREPORTERROR ("HIDSetQueueCallback - invalid device and/or element."); return result; } #if 1 // --------------------------------- // Get a report from a device long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize); long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->getReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetReport - Could not getReport, error: ", result); } else HIDREPORTERROR ("HIDGetReport - no interface for device."); } else HIDREPORTERROR ("HIDGetReport - invalid device."); return result; } // --------------------------------- // Send a report to a device long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize); long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize) { IOReturn result = kIOReturnError; // assume failure (pessimist!) if (HIDIsValidDevice(pDevice)) { if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**) pDevice->interface)->setReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil); if (kIOReturnSuccess != result) HIDREPORTERRORNUM ("HIDGetReport - Could not setReport; error: ", result); } else HIDREPORTERROR ("HIDGetReport - no interface for device."); } else HIDREPORTERROR ("HIDGetReport - invalid device."); return result; } #endif ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Queue_Utilities.h ================================================ /* File: HID_Queue_Utilities.h Contains: Definition of the HID queue functions for the HID utilites. DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Queue_Utilities_h_ #define _HID_Queue_Utilities_h_ #include "HID_Utilities.h" // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== enum { kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate of // if states change quickly (updates are only posted on state changes) }; // ================================== // queues specific element, performing any device queue set up required extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); // adds all elements to queue, performing any device queue set up required extern unsigned long HIDQueueDevice (pRecDevice pDevice); // removes element for queue, if last element in queue will release queue and device extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); // completely removes all elements from queue and releases queue and device extern unsigned long HIDDequeueDevice (pRecDevice pDevice); // releases all device queues for quit or rebuild (must be called) extern unsigned long HIDReleaseAllDeviceQueues (void); // releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); // returns current value for element, creating device interface as required, polling element extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); // Set an elements value // NOTE: This should only be used when a single element report needs to be sent. // If multiple elements reports are to be send then transactions should be used. extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pIOHIDEvent); // Set a callback to be called when a queue goes from empty to non-empty extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); #if 0 // Get a report from a device extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize); // Send a report to a device extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize); #endif #ifdef __cplusplus } #endif #endif // _HID_Queue_Utilities_h_ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Utilities.c ================================================ /* File: HID_Utilities.c Contains: Implementation of HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HID_Utilities_Internal.h" #include "HID_Utilities_External.h" #include <IOKit/IOCFPlugIn.h> #include <IOKit/IOKitLib.h> #include <IOKit/IOMessage.h> #include <IOKit/hid/IOHIDUsageTables.h> //================================================================================================ #define USE_NOTIFICATIONS 1 //================================================================================================ // local (static) functions //================================================================================================ static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection); static pRecDevice hid_DisposeDevice (pRecDevice ppDevice); //================================================================================================ // globals //================================================================================================ #if USE_NOTIFICATIONS static IONotificationPortRef gNotifyPort; static io_iterator_t gAddedIter; static CFRunLoopRef gRunLoop; #endif USE_NOTIFICATIONS // for element retrieval static pRecDevice gCurrentGetDevice = NULL; static Boolean gAddAsChild = false; static int gDepth = false; static pRecDevice gpDeviceList = NULL; static UInt32 gNumDevices = 0; #pragma mark private functions // ================================== // private functions static UInt32 hid_CountCurrentDevices (void); // extracts actual specific element information from each element CF dictionary entry static void hid_GetElementInfo (CFTypeRef refElement, pRecElement pElement) { long number; CFTypeRef refType; // type, usagePage, usage already stored refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->cookie = (IOHIDElementCookie) number; else pElement->cookie = (IOHIDElementCookie) 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->min = number; else pElement->min = 0; pElement->calMax = pElement->min; pElement->userMin = kDefaultUserMin; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->max = number; else pElement->max = 0; pElement->calMin = pElement->max; pElement->userMax = kDefaultUserMax; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMin = number; else pElement->scaledMin = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->scaledMax = number; else pElement->scaledMax = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->size = number; else pElement->size = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); if (refType) pElement->relative = CFBooleanGetValue (refType); else pElement->relative = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); if (refType) pElement->wrapping = CFBooleanGetValue (refType); else pElement->wrapping = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); if (refType) pElement->nonLinear = CFBooleanGetValue (refType); else pElement->wrapping = false; #ifdef kIOHIDElementHasPreferredStateKey refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferredStateKey)); #else // Mac OS X 10.0 has spelling error refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); #endif if (refType) pElement->preferredState = CFBooleanGetValue (refType); else pElement->preferredState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); if (refType) pElement->nullState = CFBooleanGetValue (refType); else pElement->nullState = false; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->units = number; else pElement->units = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitExponentKey)); if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) pElement->unitExp = number; else pElement->unitExp = 0; refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementNameKey)); if (refType) if (!CFStringGetCString (refType, pElement->name, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pElement->name."); if (!*pElement->name) { // set name from vendor id, product id & usage info look up if (!HIDGetElementNameFromVendorProductUsage (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, pElement->usagePage, pElement->usage, pElement->name)) { // set name from vendor id/product id look up HIDGetElementNameFromVendorProductCookie (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, (long) pElement->cookie, pElement->name); if (!*pElement->name) { // if no name HIDGetUsageName (pElement->usagePage, pElement->usage, pElement->name); if (!*pElement->name) // if not usage sprintf (pElement->name, "Element"); } } } } // --------------------------------- // examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements // if element of interest allocate storage, add to list and retrieve element specific info // if collection then pass on to deconstruction collection into additional individual elements static void hid_AddElement (CFTypeRef refElement, pRecElement * ppElementCurrent) { pRecDevice pDevice = gCurrentGetDevice; pRecElement pElement = NULL; long elementType, usagePage, usage; CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); if (refElementType) CFNumberGetValue (refElementType, kCFNumberLongType, &elementType); if (refUsagePage) CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage); if (refUsage) CFNumberGetValue (refUsage, kCFNumberLongType, &usage); if (NULL == pDevice) return; if (elementType) { // look at types of interest if (elementType != kIOHIDElementTypeCollection) { if (usagePage && usage) // if valid usage and page { switch (usagePage) // only interested in kHIDPage_GenericDesktop and kHIDPage_Button { case kHIDPage_GenericDesktop: { switch (usage) // look at usage to determine function { case kHIDUsage_GD_X: case kHIDUsage_GD_Y: case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->axis++; break; case kHIDUsage_GD_Slider: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->sliders++; break; case kHIDUsage_GD_Dial: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->dials++; break; case kHIDUsage_GD_Wheel: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->wheels++; break; case kHIDUsage_GD_Hatswitch: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->hats++; break; default: pElement = (pRecElement) malloc (sizeof (recElement)); break; } } break; case kHIDPage_Button: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->buttons++; break; default: // just add a generic element pElement = (pRecElement) malloc (sizeof (recElement)); break; } } #if 0 else HIDReportError ("CFNumberGetValue error when getting value for refUsage or refUsagePage."); #endif 0 } else // collection pElement = (pRecElement) malloc (sizeof (recElement)); } else HIDReportError ("CFNumberGetValue error when getting value for refElementType."); if (pElement) // add to list { // this code builds a binary tree based on the collection hierarchy of inherent in the device element layout // it preserves the structure of the lements as collections have children and elements are siblings to each other // clear record bzero(pElement,sizeof(recElement)); // get element info pElement->type = elementType; pElement->usagePage = usagePage; pElement->usage = usage; pElement->depth = 0; // assume root object hid_GetElementInfo (refElement, pElement); // count elements pDevice->totalElements++; switch (pElement->type) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: pDevice->inputs++; break; case kIOHIDElementTypeOutput: pDevice->outputs++; break; case kIOHIDElementTypeFeature: pDevice->features++; break; case kIOHIDElementTypeCollection: pDevice->collections++; break; default: HIDReportErrorNum ("Unknown element type : ", pElement->type); } if (NULL == *ppElementCurrent) // if at list head { pDevice->pListElements = pElement; // add current element *ppElementCurrent = pElement; // set current element to element we just added } else // have exsiting structure { if (gAddAsChild) // if the previous element was a collection, let's add this as a child of the previous { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pChild) // step down tree until free child node found *ppElementCurrent = (*ppElementCurrent)->pChild; (*ppElementCurrent)->pChild = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth + 1; } else // add as sibling { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pSibling) // step down tree until free sibling node found *ppElementCurrent = (*ppElementCurrent)->pSibling; (*ppElementCurrent)->pSibling = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth; } pElement->pPrevious = *ppElementCurrent; // point to previous *ppElementCurrent = pElement; // set current to our collection } if (elementType == kIOHIDElementTypeCollection) // if this element is a collection of other elements { gAddAsChild = true; // add next set as children to this element gDepth++; hid_GetCollectionElements ((CFMutableDictionaryRef) refElement, &pElement); // recursively process the collection gDepth--; } gAddAsChild = false; // add next as this elements sibling (when return from a collection or with non-collections) } #if 0 else HIDReportError ("hid_AddElement - no element added."); #endif } // --------------------------------- // collects information from each array member in device element list (each array memeber = element) static void hid_GetElementsCFArrayHandler (const void * value, void * parameter) { if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) hid_AddElement ((CFTypeRef) value, (pRecElement *) parameter); } // --------------------------------- // handles retrieval of element information from arrays of elements in device IO registry information static void hid_GetElements (CFTypeRef refElementCurrent, pRecElement *ppCurrentElement) { CFTypeID type = CFGetTypeID (refElementCurrent); if (type == CFArrayGetTypeID()) // if element is an array { CFRange range = {0, CFArrayGetCount (refElementCurrent)}; // CountElementsCFArrayHandler called for each array member CFArrayApplyFunction (refElementCurrent, range, hid_GetElementsCFArrayHandler, ppCurrentElement); } } // --------------------------------- // handles extracting element information from element collection CF types // used from top level element decoding and hierarchy deconstruction to flatten device element list static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection) { CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); if (refElementTop) hid_GetElements (refElementTop, ppCurrentCollection); else HIDReportError ("hid_GetCollectionElements: CFDictionaryGetValue error when creating CFTypeRef for kIOHIDElementKey."); } // --------------------------------- // use top level element usage page and usage to discern device usage page and usage setting appropriate values in device record static void hid_TopLevelElementHandler (const void * value, void * parameter) { CFTypeRef refCF = 0; if ((NULL == value) || (NULL == parameter)) return; // (kIOReturnBadArgument) if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) return; // (kIOReturnBadArgument) refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); } // --------------------------------- // extracts device info from CF dictionary records in IO registry static void hid_GetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, pRecDevice pDevice) { CFMutableDictionaryRef usbProperties = 0; io_registry_entry_t parent1, parent2; // Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also // get dictionary for usb properties: step up two levels and get CF dictionary for USB properties if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) { if (usbProperties) { CFTypeRef refCF = 0; // get device info // try hid dictionary first, if fail then go to usb dictionary // get transport refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDTransportKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->transport, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->transport."); } // get vendorID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVendorIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idVendor")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->vendorID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->vendorID."); } // get product ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idProduct")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->productID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->productID."); } // get product version refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVersionNumberKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->version)) HIDReportError ("CFNumberGetValue error retrieving pDevice->version."); } // get manufacturer name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDManufacturerKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Vendor Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->manufacturer, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->manufacturer."); } // get product name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->product."); } // get serial refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDSerialNumberKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->serial, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->serial."); } // get location ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDLocationIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("locationID")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->locID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->locID."); } // get usage page and usage refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); if (refCF) if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); } if (NULL == refCF) // get top level element HID usage page or usage { // use top level element instead CFTypeRef refCFTopElement = 0; refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); { // refCFTopElement points to an array of element dictionaries CFRange range = {0, CFArrayGetCount (refCFTopElement)}; CFArrayApplyFunction (refCFTopElement, range, hid_TopLevelElementHandler, NULL); } } } else HIDReportError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); CFRelease (usbProperties); if (kIOReturnSuccess != IOObjectRelease (parent2)) HIDReportError ("IOObjectRelease error with parent2."); if (kIOReturnSuccess != IOObjectRelease (parent1)) HIDReportError ("IOObjectRelease error with parent1."); } } // --------------------------------- // adds device to linked list of devices passed in (handles NULL lists properly) // (returns where you just stored it) static pRecDevice* hid_AddDevice (pRecDevice *ppListDeviceHead, pRecDevice pNewDevice) { pRecDevice* result = NULL; if (NULL == *ppListDeviceHead) result = ppListDeviceHead; else { pRecDevice pDevicePrevious = NULL, pDevice = *ppListDeviceHead; while (pDevice) { pDevicePrevious = pDevice; pDevice = pDevicePrevious->pNext; } result = &pDevicePrevious->pNext; } pNewDevice->pNext = NULL; *result = pNewDevice; return result; } // --------------------------------- // given a IO device object build a flat device record including device info and elements static pRecDevice hid_BuildDevice (io_object_t hidDevice) { pRecDevice pDevice = (pRecDevice) malloc (sizeof (recDevice)); if (NULL != pDevice) { // get dictionary for HID properties CFMutableDictionaryRef hidProperties = 0; kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); // clear record bzero(pDevice, sizeof(recDevice)); if ((result == KERN_SUCCESS) && (NULL != hidProperties)) { pRecElement pCurrentElement = NULL; // create device interface result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); if (kIOReturnSuccess != result) HIDReportErrorNum ("HIDCreateOpenDeviceInterface failed.", result); hid_GetDeviceInfo (hidDevice, hidProperties, pDevice); // hidDevice used to find parents in registry tree // set current device for use in getting elements gCurrentGetDevice = pDevice; // Add all elements hid_GetCollectionElements (hidProperties, &pCurrentElement); gCurrentGetDevice = NULL; CFRelease (hidProperties); } else HIDReportErrorNum ("IORegistryEntryCreateCFProperties error when creating deviceProperties.", result); } else HIDReportError ("malloc error when allocating pRecDevice."); return pDevice; } #if USE_NOTIFICATIONS //================================================================================================ // // hid_DeviceNotification // // This routine will get called whenever any kIOGeneralInterest notification happens. We are // interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other // messages are defined in IOMessage.h. // //================================================================================================ // static void hid_DeviceNotification( void *refCon, io_service_t service, natural_t messageType, void *messageArgument ) { #pragma unused(messageArgument) pRecDevice pDevice = (pRecDevice) refCon; if (messageType == kIOMessageServiceIsTerminated) { printf("Device 0x%08x \"%s\"removed.\n", service, pDevice->product); // Free the data we're no longer using now that the device is going away hid_DisposeDevice (pDevice); } } #else static void hid_RemovalCallbackFunction(void * target, IOReturn result, void * refcon, void * sender) { hid_DisposeDevice ((pRecDevice) target); } #endif USE_NOTIFICATIONS //================================================================================================ // // hid_AddDevices // // This routine is the callback for our IOServiceAddMatchingNotification. When we get called // we will look at all the devices that were added and we will: // // 1. Create some private data to relate to each device. // 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device, // using the refCon field to store a pointer to our data. When we get called with // this interest notification, we can grab the refCon and access our private data. // //================================================================================================ // // --------------------------------- // given a IO device iterator, iterate it and add all its devices static void hid_AddDevices (void *refCon, io_iterator_t iterator) { // NOTE: refcon passed in is used to point to the device list head pRecDevice* pListDeviceHead = (pRecDevice*) refCon; IOReturn result = kIOReturnSuccess; io_object_t ioHIDDeviceObject = 0; while ((ioHIDDeviceObject = IOIteratorNext (iterator))) { pRecDevice* pNewDeviceAt = NULL; pRecDevice pNewDevice = hid_BuildDevice (ioHIDDeviceObject); if (pNewDevice) { #if 0 // set true for verbose output printf("\nhid_AddDevices: pNewDevice = {t: \"%s\", v: %ld, p: %ld, v: %ld, m: \"%s\", " \ "p: \"%s\", l: %ld, u: %4.4lX:%4.4lX, #e: %ld, #f: %ld, #i: %ld, #o: %ld, " \ "#c: %ld, #a: %ld, #b: %ld, #h: %ld, #s: %ld, #d: %ld, #w: %ld}.", pNewDevice->transport, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->version, pNewDevice->manufacturer, pNewDevice->product, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage, pNewDevice->totalElements, pNewDevice->features, pNewDevice->inputs, pNewDevice->outputs, pNewDevice->collections, pNewDevice->axis, pNewDevice->buttons, pNewDevice->hats, pNewDevice->sliders, pNewDevice->dials, pNewDevice->wheels ); fflush(stdout); #elif 0 // otherwise output brief description printf("\nhid_AddDevices: pNewDevice = {m: \"%s\" p: \"%s\", vid: %ld, pid: %ld, loc: %8.8lX, usage: %4.4lX:%4.4lX}.", pNewDevice->manufacturer, pNewDevice->product, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage ); fflush(stdout); #endif pNewDeviceAt = hid_AddDevice (pListDeviceHead, pNewDevice); } #if USE_NOTIFICATIONS // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. result = IOServiceAddInterestNotification( gNotifyPort, // notifyPort ioHIDDeviceObject, // service kIOGeneralInterest, // interestType hid_DeviceNotification, // callback pNewDevice, // refCon (io_object_t*) &pNewDevice->notification); // notification if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOServiceAddInterestNotification error: x0%8.8lX.", result); #else result = (*(IOHIDDeviceInterface**)pNewDevice->interface)->setRemovalCallback (pNewDevice->interface, hid_RemovalCallbackFunction,pNewDeviceAt,0); #endif USE_NOTIFICATIONS // release the device object, it is no longer needed result = IOObjectRelease (ioHIDDeviceObject); if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOObjectRelease error with ioHIDDeviceObject.", result); } } // --------------------------------- // disposes of the element list associated with a device and the memory associated with the list // uses depthwise recursion to dispose both collections and elements. static void hid_DisposeDeviceElements (pRecElement pElement) { if (pElement) { if (pElement->pChild) hid_DisposeDeviceElements (pElement->pChild); if (pElement->pSibling) hid_DisposeDeviceElements (pElement->pSibling); free (pElement); } } // --------------------------------- // disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL // all your device no longer belong to us... (i.e., you do not 'own' the device anymore) static pRecDevice hid_DisposeDevice (pRecDevice pDevice) { kern_return_t result = KERN_SUCCESS; pRecDevice pDeviceNext = NULL; if (HIDIsValidDevice(pDevice)) { // save next device prior to disposing of this device pDeviceNext = pDevice->pNext; result = HIDDequeueDevice (pDevice); #if 0 if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: HIDDequeueDevice error: 0x%8.8X.", result); #endif 1 hid_DisposeDeviceElements (pDevice->pListElements); pDevice->pListElements = NULL; result = HIDCloseReleaseInterface (pDevice); // function sanity checks interface value (now application does not own device) if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: HIDCloseReleaseInterface error: 0x%8.8X.", result); #if USE_NOTIFICATIONS if (pDevice->interface) { // replace (*pDevice->interface)->Release(pDevice->interface); result = IODestroyPlugInInterface (pDevice->interface); if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: IODestroyPlugInInterface error: 0x%8.8X.", result); } if (pDevice->notification) { result = IOObjectRelease((io_object_t) pDevice->notification); if (kIOReturnSuccess != result) HIDReportErrorNum ("hid_DisposeDevice: IOObjectRelease error: 0x%8.8X.", result); } #endif USE_NOTIFICATIONS // remove this device from the device list if (gpDeviceList == pDevice) // head of list? gpDeviceList = pDeviceNext; else { pRecDevice pDeviceTemp = pDeviceNext = gpDeviceList; // we're going to return this if we don't find ourselfs in the list while (pDeviceTemp) { if (pDeviceTemp->pNext == pDevice) // found us! { // take us out of linked list pDeviceTemp->pNext = pDeviceNext = pDevice->pNext; break; } pDeviceTemp = pDeviceTemp->pNext; } } free (pDevice); } // update device count gNumDevices = hid_CountCurrentDevices (); return pDeviceNext; } // --------------------------------- // count number of devices in global device list (gpDeviceList) static UInt32 hid_CountCurrentDevices (void) { pRecDevice pDevice = gpDeviceList; UInt32 devices = 0; while (pDevice) { devices++; pDevice = pDevice->pNext; } return devices; } // --------------------------------- // matches type masks passed in to actual element types (which are not set up to be used as a mask static Boolean hid_MatchElementTypeMask (IOHIDElementType type, HIDElementTypeMask typeMask) { if (typeMask & kHIDElementTypeInput) if ((type == kIOHIDElementTypeInput_Misc) || (type == kIOHIDElementTypeInput_Button) || (type == kIOHIDElementTypeInput_Axis) || (type == kIOHIDElementTypeInput_ScanCodes)) return true; if (typeMask & kHIDElementTypeOutput) if (type == kIOHIDElementTypeOutput) return true; if (typeMask & kHIDElementTypeFeature) if (type == kIOHIDElementTypeFeature) return true; if (typeMask & kHIDElementTypeCollection) if (type == kIOHIDElementTypeCollection) return true; return false; } // --------------------------------- static pRecElement hid_GetDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { // we are asking for this element if (NULL != pElement) { if (hid_MatchElementTypeMask (pElement->type, typeMask)) // if the type match what we are looking for return pElement; // return the element else return HIDGetNextDeviceElement (pElement, typeMask); // else get the next one } return NULL; } #define FAKE_IT 0 // set true for debugging; returns the usage & usage page as numbers // --------------------------------- // Load the usage strings from the <HID_usage_strings.plist> resource (XML) file into a CFPropertyListRef static CFPropertyListRef xml_load_usage_strings(void) { CFPropertyListRef tCFPropertyListRef = NULL; CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("HID_usage_strings"), CFSTR("plist"), NULL); if (NULL != resFileCFURLRef) { CFDataRef resCFDataRef; if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil)) { if (NULL != resCFDataRef) { CFStringRef errorString; tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString); if (NULL == tCFPropertyListRef) CFShow(errorString); CFRelease(resCFDataRef); } } CFRelease(resFileCFURLRef); } return tCFPropertyListRef; } // --------------------------------- // Find a usage string in the <HID_usage_strings.plist> resource (XML) file static Boolean xml_GetUsageName(const long valueUsagePage, const long valueUsage, char* pCstr) { static CFPropertyListRef tCFPropertyListRef = NULL; Boolean results = false; if (NULL == tCFPropertyListRef) tCFPropertyListRef = xml_load_usage_strings(); if (NULL != tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef)) { CFDictionaryRef pageCFDictionaryRef; CFStringRef pageKeyCFStringRef; pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsagePage); if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void**) &pageCFDictionaryRef)) { CFStringRef pageCFStringRef; if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, CFSTR("Name"), (const void**) &pageCFStringRef)) { //CFShow(pageCFStringRef); } { CFStringRef fullCFStringRef = NULL; CFStringRef usageKeyCFStringRef; CFStringRef usageCFStringRef; usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsage); if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef)) { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), pageCFStringRef, usageCFStringRef); // CFShow(usageCFStringRef); } #if FAKE_IT else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ #%@"), pageCFStringRef, usageKeyCFStringRef); } #endif if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString( fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman); CFRelease(fullCFStringRef); } CFRelease(usageKeyCFStringRef); } } CFRelease(pageKeyCFStringRef); } //++CFRelease(tCFPropertyListRef); // Leak this! } return results; } #pragma mark public functions // ================================= // public functions // --------------------------------- // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice) { IOReturn result = kIOReturnSuccess; HRESULT plugInResult = S_OK; SInt32 score = 0; IOCFPlugInInterface ** ppPlugInInterface = NULL; if (NULL == pDevice->interface) { result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); if (kIOReturnSuccess == result) { // Call a method of the intermediate plug-in to create the device interface plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); if (S_OK != plugInResult) HIDReportErrorNum ("Couldnt query HID class device interface from plugInInterface", plugInResult); IODestroyPlugInInterface (ppPlugInInterface); // replace (*ppPlugInInterface)->Release (ppPlugInInterface) } else HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); } if (NULL != pDevice->interface) { result = (*(IOHIDDeviceInterface**)pDevice->interface)->open (pDevice->interface, 0); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); } return result; } // --------------------------------- // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, but not user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) // returns true if succesful Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage) { IOReturn result = kIOReturnSuccess; mach_port_t masterPort = 0; if (NULL != gpDeviceList) HIDReleaseDeviceList (); result = IOMasterPort (bootstrap_port, &masterPort); if (kIOReturnSuccess != result) HIDReportErrorNum ("IOMasterPort error with bootstrap_port.", result); else { CFMutableDictionaryRef hidMatchDictionary = NULL; // Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error. { CFNumberRef refUsage = NULL, refUsagePage = NULL; // Set up a matching dictionary to search I/O Registry by class name for all HID class devices. hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); if (NULL != hidMatchDictionary) { if (usagePage) { // Add key for device type (joystick, in this case) to refine the matching dictionary. refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usagePage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); CFRelease (refUsagePage); if (usage) { refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); CFRelease (refUsage); } } CFRetain(hidMatchDictionary); } else HIDReportError ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); } #if USE_NOTIFICATIONS // Create a notification port and add its run loop event source to our run loop // This is how async notifications get set up. { CFRunLoopSourceRef runLoopSource; gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. result = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType hidMatchDictionary, // matching hid_AddDevices, // callback &gpDeviceList, // refCon &gAddedIter // notification ); // call it now to add all existing devices hid_AddDevices(&gpDeviceList,gAddedIter); } #else { io_iterator_t hidObjectIterator = NULL; // Now search I/O Registry for matching devices. result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to create IO object iterator, error:", result); else if (NULL == hidObjectIterator) // likely no HID devices which matched selection criteria are connected HIDReportError ("Warning: Could not find any matching devices, thus iterator creation failed."); if (NULL != hidObjectIterator) { hid_AddDevices(&gpDeviceList,hidObjectIterator); result = IOObjectRelease (hidObjectIterator); // release the iterator if (kIOReturnSuccess != result) HIDReportErrorNum ("IOObjectRelease error with hidObjectIterator.", result); gNumDevices = hid_CountCurrentDevices (); return true; } } #endif USE_NOTIFICATIONS // IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. hidMatchDictionary = NULL; } return false; } // --------------------------------- // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain void HIDReleaseDeviceList (void) { while (NULL != gpDeviceList) gpDeviceList = hid_DisposeDevice (gpDeviceList); // dispose current device return next device will set gpDeviceList to NULL gNumDevices = 0; } // --------------------------------- // does a device list exist Boolean HIDHaveDeviceList (void) { if (NULL != gpDeviceList) return true; return false; } // --------------------------------- // how many HID devices have been found // returns 0 if no device list exist UInt32 HIDCountDevices (void) { gNumDevices = hid_CountCurrentDevices (); return gNumDevices; } // --------------------------------- // how many elements does a specific device have // returns 0 if device is invlaid or NULL UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask) { long count = 0; if (HIDIsValidDevice(pDevice)) { if (typeMask & kHIDElementTypeInput) count += pDevice->inputs; if (typeMask & kHIDElementTypeOutput) count += pDevice->outputs; if (typeMask & kHIDElementTypeFeature) count += pDevice->features; if (typeMask & kHIDElementTypeCollection) count += pDevice->collections; } return count; } // --------------------------------- // get the first device in the device list // returns NULL if no list exists pRecDevice HIDGetFirstDevice (void) { return gpDeviceList; } // --------------------------------- // get next device in list given current device as parameter // returns NULL if end of list pRecDevice HIDGetNextDevice (pRecDevice pDevice) { if (NULL != pDevice) return pDevice->pNext; else return NULL; } // --------------------------------- // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask) { if (HIDIsValidDevice(pDevice)) { if (hid_MatchElementTypeMask (pDevice->pListElements->type, typeMask)) // ensure first type matches return pDevice->pListElements; else return HIDGetNextDeviceElement (pDevice->pListElements, typeMask); } else return NULL; } // --------------------------------- // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { // should only have elements passed in (though someone could mix calls and pass us a collection) // collection means return the next child or sibling (in that order) // element means returnt he next sibling (as elements can't have children if (NULL != pElement) { if (pElement->pChild) { if (pElement->type != kIOHIDElementTypeCollection) HIDReportError ("Malformed element list: found child of element."); else return hid_GetDeviceElement (pElement->pChild, typeMask); // return the child of this element } else if (pElement->pSibling) { return hid_GetDeviceElement (pElement->pSibling, typeMask); //return the sibling of this element } else // at end back up correctly { pRecElement pPreviousElement = NULL; // malformed device ending in collection if (pElement->type == kIOHIDElementTypeCollection) HIDReportError ("Malformed device: found collection at end of element chain."); // walk back up tree to element prior to first collection ecountered and take next element while (NULL != pElement->pPrevious) { pPreviousElement = pElement; pElement = pElement->pPrevious; // look at previous element // if we have a collection and the previous element is the branch element (should have both a colection and next element attached to it) // if we found a collection, which we are not at the sibling level that actually does have siblings if (((pElement->type == kIOHIDElementTypeCollection) && (pPreviousElement != pElement->pSibling) && pElement->pSibling) || // or if we are at the top (NULL == pElement->pPrevious)) // at top of tree break; } if (NULL == pElement->pPrevious) return NULL; // got to top of list with only a collection as the first element // now we must have been down the child route so go down the sibling route pElement = pElement->pSibling; // element of interest return hid_GetDeviceElement (pElement, typeMask); // otherwise return this element } } return NULL; } // --------------------------------- // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask) { pRecElement pPreviousElement = pElement->pPrevious; // walk back up tree to element prior while (pPreviousElement && !hid_MatchElementTypeMask (pPreviousElement->type, typeMask)) { pElement = pPreviousElement; // look at previous element pPreviousElement = pElement->pPrevious; } return pPreviousElement; // return this element } // --------------------------------- // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns "Unknown Type" for invalid types void HIDGetTypeName (IOHIDElementType theType, char * cstrName) { switch (theType) { case kIOHIDElementTypeInput_Misc: sprintf(cstrName, "Miscellaneous Input"); break; case kIOHIDElementTypeInput_Button: sprintf(cstrName, "Button Input"); break; case kIOHIDElementTypeInput_Axis: sprintf(cstrName, "Axis Input"); break; case kIOHIDElementTypeInput_ScanCodes: sprintf(cstrName, "Scan Code Input"); break; case kIOHIDElementTypeOutput: sprintf(cstrName, "Output"); break; case kIOHIDElementTypeFeature: sprintf(cstrName, "Feature"); break; case kIOHIDElementTypeCollection: sprintf(cstrName, "Collection"); break; default: sprintf(cstrName, "Unknown Type"); break; } } // --------------------------------- // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values void HIDGetUsageName (const long valueUsagePage, const long valueUsage, char * cstrName) { if (xml_GetUsageName(valueUsagePage, valueUsage, cstrName)) return; switch (valueUsagePage) { case kHIDPage_Undefined: switch (valueUsage) { default: sprintf (cstrName, "Undefined Page, Usage 0x%lx", valueUsage); break; } break; case kHIDPage_GenericDesktop: switch (valueUsage) { case kHIDUsage_GD_Pointer: sprintf (cstrName, "Pointer"); break; case kHIDUsage_GD_Mouse: sprintf (cstrName, "Mouse"); break; case kHIDUsage_GD_Joystick: sprintf (cstrName, "Joystick"); break; case kHIDUsage_GD_GamePad: sprintf (cstrName, "GamePad"); break; case kHIDUsage_GD_Keyboard: sprintf (cstrName, "Keyboard"); break; case kHIDUsage_GD_Keypad: sprintf (cstrName, "Keypad"); break; case kHIDUsage_GD_MultiAxisController: sprintf (cstrName, "Multi-Axis Controller"); break; case kHIDUsage_GD_X: sprintf (cstrName, "X-Axis"); break; case kHIDUsage_GD_Y: sprintf (cstrName, "Y-Axis"); break; case kHIDUsage_GD_Z: sprintf (cstrName, "Z-Axis"); break; case kHIDUsage_GD_Rx: sprintf (cstrName, "X-Rotation"); break; case kHIDUsage_GD_Ry: sprintf (cstrName, "Y-Rotation"); break; case kHIDUsage_GD_Rz: sprintf (cstrName, "Z-Rotation"); break; case kHIDUsage_GD_Slider: sprintf (cstrName, "Slider"); break; case kHIDUsage_GD_Dial: sprintf (cstrName, "Dial"); break; case kHIDUsage_GD_Wheel: sprintf (cstrName, "Wheel"); break; case kHIDUsage_GD_Hatswitch: sprintf (cstrName, "Hatswitch"); break; case kHIDUsage_GD_CountedBuffer: sprintf (cstrName, "Counted Buffer"); break; case kHIDUsage_GD_ByteCount: sprintf (cstrName, "Byte Count"); break; case kHIDUsage_GD_MotionWakeup: sprintf (cstrName, "Motion Wakeup"); break; case kHIDUsage_GD_Start: sprintf (cstrName, "Start"); break; case kHIDUsage_GD_Select: sprintf (cstrName, "Select"); break; case kHIDUsage_GD_Vx: sprintf (cstrName, "X-Velocity"); break; case kHIDUsage_GD_Vy: sprintf (cstrName, "Y-Velocity"); break; case kHIDUsage_GD_Vz: sprintf (cstrName, "Z-Velocity"); break; case kHIDUsage_GD_Vbrx: sprintf (cstrName, "X-Rotation Velocity"); break; case kHIDUsage_GD_Vbry: sprintf (cstrName, "Y-Rotation Velocity"); break; case kHIDUsage_GD_Vbrz: sprintf (cstrName, "Z-Rotation Velocity"); break; case kHIDUsage_GD_Vno: sprintf (cstrName, "Vno"); break; case kHIDUsage_GD_SystemControl: sprintf (cstrName, "System Control"); break; case kHIDUsage_GD_SystemPowerDown: sprintf (cstrName, "System Power Down"); break; case kHIDUsage_GD_SystemSleep: sprintf (cstrName, "System Sleep"); break; case kHIDUsage_GD_SystemWakeUp: sprintf (cstrName, "System Wake Up"); break; case kHIDUsage_GD_SystemContextMenu: sprintf (cstrName, "System Context Menu"); break; case kHIDUsage_GD_SystemMainMenu: sprintf (cstrName, "System Main Menu"); break; case kHIDUsage_GD_SystemAppMenu: sprintf (cstrName, "System App Menu"); break; case kHIDUsage_GD_SystemMenuHelp: sprintf (cstrName, "System Menu Help"); break; case kHIDUsage_GD_SystemMenuExit: sprintf (cstrName, "System Menu Exit"); break; case kHIDUsage_GD_SystemMenu: sprintf (cstrName, "System Menu"); break; case kHIDUsage_GD_SystemMenuRight: sprintf (cstrName, "System Menu Right"); break; case kHIDUsage_GD_SystemMenuLeft: sprintf (cstrName, "System Menu Left"); break; case kHIDUsage_GD_SystemMenuUp: sprintf (cstrName, "System Menu Up"); break; case kHIDUsage_GD_SystemMenuDown: sprintf (cstrName, "System Menu Down"); break; case kHIDUsage_GD_DPadUp: sprintf (cstrName, "DPad Up"); break; case kHIDUsage_GD_DPadDown: sprintf (cstrName, "DPad Down"); break; case kHIDUsage_GD_DPadRight: sprintf (cstrName, "DPad Right"); break; case kHIDUsage_GD_DPadLeft: sprintf (cstrName, "DPad Left"); break; case kHIDUsage_GD_Reserved: sprintf (cstrName, "Reserved"); break; default: sprintf (cstrName, "Generic Desktop Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Simulation: switch (valueUsage) { default: sprintf (cstrName, "Simulation Usage 0x%lx", valueUsage); break; } break; case kHIDPage_VR: switch (valueUsage) { default: sprintf (cstrName, "VR Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Sport: switch (valueUsage) { default: sprintf (cstrName, "Sport Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Game: switch (valueUsage) { default: sprintf (cstrName, "Game Usage 0x%lx", valueUsage); break; } break; case kHIDPage_KeyboardOrKeypad: switch (valueUsage) { default: sprintf (cstrName, "Keyboard Usage 0x%lx", valueUsage); break; } break; case kHIDPage_LEDs: switch (valueUsage) { // some LED usages case kHIDUsage_LED_IndicatorRed: sprintf (cstrName, "Red LED"); break; case kHIDUsage_LED_IndicatorGreen: sprintf (cstrName, "Green LED"); break; case kHIDUsage_LED_IndicatorAmber: sprintf (cstrName, "Amber LED"); break; case kHIDUsage_LED_GenericIndicator: sprintf (cstrName, "Generic LED"); break; case kHIDUsage_LED_SystemSuspend: sprintf (cstrName, "System Suspend LED"); break; case kHIDUsage_LED_ExternalPowerConnected: sprintf (cstrName, "External Power LED"); break; default: sprintf (cstrName, "LED Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Button: switch (valueUsage) { default: sprintf (cstrName, "Button #%ld", valueUsage); break; } break; case kHIDPage_Ordinal: switch (valueUsage) { default: sprintf (cstrName, "Ordinal Instance %lx", valueUsage); break; } break; case kHIDPage_Telephony: switch (valueUsage) { default: sprintf (cstrName, "Telephony Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Consumer: switch (valueUsage) { default: sprintf (cstrName, "Consumer Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Digitizer: switch (valueUsage) { default: sprintf (cstrName, "Digitizer Usage 0x%lx", valueUsage); break; } break; case kHIDPage_PID: if (((valueUsage >= 0x02) && (valueUsage <= 0x1F)) || ((valueUsage >= 0x29) && (valueUsage <= 0x2F)) || ((valueUsage >= 0x35) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x44) && (valueUsage <= 0x4F)) || (valueUsage == 0x8A) || (valueUsage == 0x93) || ((valueUsage >= 0x9D) && (valueUsage <= 0x9E)) || ((valueUsage >= 0xA1) && (valueUsage <= 0xA3)) || ((valueUsage >= 0xAD) && (valueUsage <= 0xFFFF))) sprintf (cstrName, "PID Reserved"); else switch (valueUsage) { case 0x00: sprintf (cstrName, "PID Undefined Usage"); break; case kHIDUsage_PID_PhysicalInterfaceDevice: sprintf (cstrName, "Physical Interface Device"); break; case kHIDUsage_PID_Normal: sprintf (cstrName, "Normal Force"); break; case kHIDUsage_PID_SetEffectReport: sprintf (cstrName, "Set Effect Report"); break; case kHIDUsage_PID_EffectBlockIndex: sprintf (cstrName, "Effect Block Index"); break; case kHIDUsage_PID_ParamBlockOffset: sprintf (cstrName, "Parameter Block Offset"); break; case kHIDUsage_PID_ROM_Flag: sprintf (cstrName, "ROM Flag"); break; case kHIDUsage_PID_EffectType: sprintf (cstrName, "Effect Type"); break; case kHIDUsage_PID_ET_ConstantForce: sprintf (cstrName, "Effect Type Constant Force"); break; case kHIDUsage_PID_ET_Ramp: sprintf (cstrName, "Effect Type Ramp"); break; case kHIDUsage_PID_ET_CustomForceData: sprintf (cstrName, "Effect Type Custom Force Data"); break; case kHIDUsage_PID_ET_Square: sprintf (cstrName, "Effect Type Square"); break; case kHIDUsage_PID_ET_Sine: sprintf (cstrName, "Effect Type Sine"); break; case kHIDUsage_PID_ET_Triangle: sprintf (cstrName, "Effect Type Triangle"); break; case kHIDUsage_PID_ET_SawtoothUp: sprintf (cstrName, "Effect Type Sawtooth Up"); break; case kHIDUsage_PID_ET_SawtoothDown: sprintf (cstrName, "Effect Type Sawtooth Down"); break; case kHIDUsage_PID_ET_Spring: sprintf (cstrName, "Effect Type Spring"); break; case kHIDUsage_PID_ET_Damper: sprintf (cstrName, "Effect Type Damper"); break; case kHIDUsage_PID_ET_Inertia: sprintf (cstrName, "Effect Type Inertia"); break; case kHIDUsage_PID_ET_Friction: sprintf (cstrName, "Effect Type Friction"); break; case kHIDUsage_PID_Duration: sprintf (cstrName, "Effect Duration"); break; case kHIDUsage_PID_SamplePeriod: sprintf (cstrName, "Effect Sample Period"); break; case kHIDUsage_PID_Gain: sprintf (cstrName, "Effect Gain"); break; case kHIDUsage_PID_TriggerButton: sprintf (cstrName, "Effect Trigger Button"); break; case kHIDUsage_PID_TriggerRepeatInterval: sprintf (cstrName, "Effect Trigger Repeat Interval"); break; case kHIDUsage_PID_AxesEnable: sprintf (cstrName, "Axis Enable"); break; case kHIDUsage_PID_DirectionEnable: sprintf (cstrName, "Direction Enable"); break; case kHIDUsage_PID_Direction: sprintf (cstrName, "Direction"); break; case kHIDUsage_PID_TypeSpecificBlockOffset: sprintf (cstrName, "Type Specific Block Offset"); break; case kHIDUsage_PID_BlockType: sprintf (cstrName, "Block Type"); break; case kHIDUsage_PID_SetEnvelopeReport: sprintf (cstrName, "Set Envelope Report"); break; case kHIDUsage_PID_AttackLevel: sprintf (cstrName, "Envelope Attack Level"); break; case kHIDUsage_PID_AttackTime: sprintf (cstrName, "Envelope Attack Time"); break; case kHIDUsage_PID_FadeLevel: sprintf (cstrName, "Envelope Fade Level"); break; case kHIDUsage_PID_FadeTime: sprintf (cstrName, "Envelope Fade Time"); break; case kHIDUsage_PID_SetConditionReport: sprintf (cstrName, "Set Condition Report"); break; case kHIDUsage_PID_CP_Offset: sprintf (cstrName, "Condition CP Offset"); break; case kHIDUsage_PID_PositiveCoefficient: sprintf (cstrName, "Condition Positive Coefficient"); break; case kHIDUsage_PID_NegativeCoefficient: sprintf (cstrName, "Condition Negative Coefficient"); break; case kHIDUsage_PID_PositiveSaturation: sprintf (cstrName, "Condition Positive Saturation"); break; case kHIDUsage_PID_NegativeSaturation: sprintf (cstrName, "Condition Negative Saturation"); break; case kHIDUsage_PID_DeadBand: sprintf (cstrName, "Condition Dead Band"); break; case kHIDUsage_PID_DownloadForceSample: sprintf (cstrName, "Download Force Sample"); break; case kHIDUsage_PID_IsochCustomForceEnable: sprintf (cstrName, "Isoch Custom Force Enable"); break; case kHIDUsage_PID_CustomForceDataReport: sprintf (cstrName, "Custom Force Data Report"); break; case kHIDUsage_PID_CustomForceData: sprintf (cstrName, "Custom Force Data"); break; case kHIDUsage_PID_CustomForceVendorDefinedData: sprintf (cstrName, "Custom Force Vendor Defined Data"); break; case kHIDUsage_PID_SetCustomForceReport: sprintf (cstrName, "Set Custom Force Report"); break; case kHIDUsage_PID_CustomForceDataOffset: sprintf (cstrName, "Custom Force Data Offset"); break; case kHIDUsage_PID_SampleCount: sprintf (cstrName, "Custom Force Sample Count"); break; case kHIDUsage_PID_SetPeriodicReport: sprintf (cstrName, "Set Periodic Report"); break; case kHIDUsage_PID_Offset: sprintf (cstrName, "Periodic Offset"); break; case kHIDUsage_PID_Magnitude: sprintf (cstrName, "Periodic Magnitude"); break; case kHIDUsage_PID_Phase: sprintf (cstrName, "Periodic Phase"); break; case kHIDUsage_PID_Period: sprintf (cstrName, "Periodic Period"); break; case kHIDUsage_PID_SetConstantForceReport: sprintf (cstrName, "Set Constant Force Report"); break; case kHIDUsage_PID_SetRampForceReport: sprintf (cstrName, "Set Ramp Force Report"); break; case kHIDUsage_PID_RampStart: sprintf (cstrName, "Ramp Start"); break; case kHIDUsage_PID_RampEnd: sprintf (cstrName, "Ramp End"); break; case kHIDUsage_PID_EffectOperationReport: sprintf (cstrName, "Effect Operation Report"); break; case kHIDUsage_PID_EffectOperation: sprintf (cstrName, "Effect Operation"); break; case kHIDUsage_PID_OpEffectStart: sprintf (cstrName, "Op Effect Start"); break; case kHIDUsage_PID_OpEffectStartSolo: sprintf (cstrName, "Op Effect Start Solo"); break; case kHIDUsage_PID_OpEffectStop: sprintf (cstrName, "Op Effect Stop"); break; case kHIDUsage_PID_LoopCount: sprintf (cstrName, "Op Effect Loop Count"); break; case kHIDUsage_PID_DeviceGainReport: sprintf (cstrName, "Device Gain Report"); break; case kHIDUsage_PID_DeviceGain: sprintf (cstrName, "Device Gain"); break; case kHIDUsage_PID_PoolReport: sprintf (cstrName, "PID Pool Report"); break; case kHIDUsage_PID_RAM_PoolSize: sprintf (cstrName, "RAM Pool Size"); break; case kHIDUsage_PID_ROM_PoolSize: sprintf (cstrName, "ROM Pool Size"); break; case kHIDUsage_PID_ROM_EffectBlockCount: sprintf (cstrName, "ROM Effect Block Count"); break; case kHIDUsage_PID_SimultaneousEffectsMax: sprintf (cstrName, "Simultaneous Effects Max"); break; case kHIDUsage_PID_PoolAlignment: sprintf (cstrName, "Pool Alignment"); break; case kHIDUsage_PID_PoolMoveReport: sprintf (cstrName, "PID Pool Move Report"); break; case kHIDUsage_PID_MoveSource: sprintf (cstrName, "Move Source"); break; case kHIDUsage_PID_MoveDestination: sprintf (cstrName, "Move Destination"); break; case kHIDUsage_PID_MoveLength: sprintf (cstrName, "Move Length"); break; case kHIDUsage_PID_BlockLoadReport: sprintf (cstrName, "PID Block Load Report"); break; case kHIDUsage_PID_BlockLoadStatus: sprintf (cstrName, "Block Load Status"); break; case kHIDUsage_PID_BlockLoadSuccess: sprintf (cstrName, "Block Load Success"); break; case kHIDUsage_PID_BlockLoadFull: sprintf (cstrName, "Block Load Full"); break; case kHIDUsage_PID_BlockLoadError: sprintf (cstrName, "Block Load Error"); break; case kHIDUsage_PID_BlockHandle: sprintf (cstrName, "Block Handle"); break; case kHIDUsage_PID_BlockFreeReport: sprintf (cstrName, "PID Block Free Report"); break; case kHIDUsage_PID_TypeSpecificBlockHandle: sprintf (cstrName, "Type Specific Block Handle"); break; case kHIDUsage_PID_StateReport: sprintf (cstrName, "PID State Report"); break; case kHIDUsage_PID_EffectPlaying: sprintf (cstrName, "Effect Playing"); break; case kHIDUsage_PID_DeviceControlReport: sprintf (cstrName, "PID Device Control Report"); break; case kHIDUsage_PID_DeviceControl: sprintf (cstrName, "PID Device Control"); break; case kHIDUsage_PID_DC_EnableActuators: sprintf (cstrName, "Device Control Enable Actuators"); break; case kHIDUsage_PID_DC_DisableActuators: sprintf (cstrName, "Device Control Disable Actuators"); break; case kHIDUsage_PID_DC_StopAllEffects: sprintf (cstrName, "Device Control Stop All Effects"); break; case kHIDUsage_PID_DC_DeviceReset: sprintf (cstrName, "Device Control Reset"); break; case kHIDUsage_PID_DC_DevicePause: sprintf (cstrName, "Device Control Pause"); break; case kHIDUsage_PID_DC_DeviceContinue: sprintf (cstrName, "Device Control Continue"); break; case kHIDUsage_PID_DevicePaused: sprintf (cstrName, "Device Paused"); break; case kHIDUsage_PID_ActuatorsEnabled: sprintf (cstrName, "Actuators Enabled"); break; case kHIDUsage_PID_SafetySwitch: sprintf (cstrName, "Safety Switch"); break; case kHIDUsage_PID_ActuatorOverrideSwitch: sprintf (cstrName, "Actuator Override Switch"); break; case kHIDUsage_PID_ActuatorPower: sprintf (cstrName, "Actuator Power"); break; case kHIDUsage_PID_StartDelay: sprintf (cstrName, "Start Delay"); break; case kHIDUsage_PID_ParameterBlockSize: sprintf (cstrName, "Parameter Block Size"); break; case kHIDUsage_PID_DeviceManagedPool: sprintf (cstrName, "Device Managed Pool"); break; case kHIDUsage_PID_SharedParameterBlocks: sprintf (cstrName, "Shared Parameter Blocks"); break; case kHIDUsage_PID_CreateNewEffectReport: sprintf (cstrName, "Create New Effect Report"); break; case kHIDUsage_PID_RAM_PoolAvailable: sprintf (cstrName, "RAM Pool Available"); break; default: sprintf (cstrName, "PID Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Unicode: switch (valueUsage) { default: sprintf (cstrName, "Unicode Usage 0x%lx", valueUsage); break; } break; case kHIDPage_PowerDevice: if (((valueUsage >= 0x06) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x26) && (valueUsage <= 0x2F)) || ((valueUsage >= 0x39) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x48) && (valueUsage <= 0x4F)) || ((valueUsage >= 0x58) && (valueUsage <= 0x5F)) || (valueUsage == 0x6A) || ((valueUsage >= 0x74) && (valueUsage <= 0xFC))) sprintf (cstrName, "Power Device Reserved"); else switch (valueUsage) { case kHIDUsage_PD_Undefined: sprintf (cstrName, "Power Device Undefined Usage"); break; case kHIDUsage_PD_iName: sprintf (cstrName, "Power Device Name Index"); break; case kHIDUsage_PD_PresentStatus: sprintf (cstrName, "Power Device Present Status"); break; case kHIDUsage_PD_ChangedStatus: sprintf (cstrName, "Power Device Changed Status"); break; case kHIDUsage_PD_UPS: sprintf (cstrName, "Uninterruptible Power Supply"); break; case kHIDUsage_PD_PowerSupply: sprintf (cstrName, "Power Supply"); break; case kHIDUsage_PD_BatterySystem: sprintf (cstrName, "Battery System Power Module"); break; case kHIDUsage_PD_BatterySystemID: sprintf (cstrName, "Battery System ID"); break; case kHIDUsage_PD_Battery: sprintf (cstrName, "Battery"); break; case kHIDUsage_PD_BatteryID: sprintf (cstrName, "Battery ID"); break; case kHIDUsage_PD_Charger: sprintf (cstrName, "Charger"); break; case kHIDUsage_PD_ChargerID: sprintf (cstrName, "Charger ID"); break; case kHIDUsage_PD_PowerConverter: sprintf (cstrName, "Power Converter Power Module"); break; case kHIDUsage_PD_PowerConverterID: sprintf (cstrName, "Power Converter ID"); break; case kHIDUsage_PD_OutletSystem: sprintf (cstrName, "Outlet System power module"); break; case kHIDUsage_PD_OutletSystemID: sprintf (cstrName, "Outlet System ID"); break; case kHIDUsage_PD_Input: sprintf (cstrName, "Power Device Input"); break; case kHIDUsage_PD_InputID: sprintf (cstrName, "Power Device Input ID"); break; case kHIDUsage_PD_Output: sprintf (cstrName, "Power Device Output"); break; case kHIDUsage_PD_OutputID: sprintf (cstrName, "Power Device Output ID"); break; case kHIDUsage_PD_Flow: sprintf (cstrName, "Power Device Flow"); break; case kHIDUsage_PD_FlowID: sprintf (cstrName, "Power Device Flow ID"); break; case kHIDUsage_PD_Outlet: sprintf (cstrName, "Power Device Outlet"); break; case kHIDUsage_PD_OutletID: sprintf (cstrName, "Power Device Outlet ID"); break; case kHIDUsage_PD_Gang: sprintf (cstrName, "Power Device Gang"); break; case kHIDUsage_PD_GangID: sprintf (cstrName, "Power Device Gang ID"); break; case kHIDUsage_PD_PowerSummary: sprintf (cstrName, "Power Device Power Summary"); break; case kHIDUsage_PD_PowerSummaryID: sprintf (cstrName, "Power Device Power Summary ID"); break; case kHIDUsage_PD_Voltage: sprintf (cstrName, "Power Device Voltage"); break; case kHIDUsage_PD_Current: sprintf (cstrName, "Power Device Current"); break; case kHIDUsage_PD_Frequency: sprintf (cstrName, "Power Device Frequency"); break; case kHIDUsage_PD_ApparentPower: sprintf (cstrName, "Power Device Apparent Power"); break; case kHIDUsage_PD_ActivePower: sprintf (cstrName, "Power Device RMS Power"); break; case kHIDUsage_PD_PercentLoad: sprintf (cstrName, "Power Device Percent Load"); break; case kHIDUsage_PD_Temperature: sprintf (cstrName, "Power Device Temperature"); break; case kHIDUsage_PD_Humidity: sprintf (cstrName, "Power Device Humidity"); break; case kHIDUsage_PD_BadCount: sprintf (cstrName, "Power Device Bad Condition Count"); break; case kHIDUsage_PD_ConfigVoltage: sprintf (cstrName, "Power Device Nominal Voltage"); break; case kHIDUsage_PD_ConfigCurrent: sprintf (cstrName, "Power Device Nominal Current"); break; case kHIDUsage_PD_ConfigFrequency: sprintf (cstrName, "Power Device Nominal Frequency"); break; case kHIDUsage_PD_ConfigApparentPower: sprintf (cstrName, "Power Device Nominal Apparent Power"); break; case kHIDUsage_PD_ConfigActivePower: sprintf (cstrName, "Power Device Nominal RMS Power"); break; case kHIDUsage_PD_ConfigPercentLoad: sprintf (cstrName, "Power Device Nominal Percent Load"); break; case kHIDUsage_PD_ConfigTemperature: sprintf (cstrName, "Power Device Nominal Temperature"); break; case kHIDUsage_PD_ConfigHumidity: sprintf (cstrName, "Power Device Nominal Humidity"); break; case kHIDUsage_PD_SwitchOnControl: sprintf (cstrName, "Power Device Switch On Control"); break; case kHIDUsage_PD_SwitchOffControl: sprintf (cstrName, "Power Device Switch Off Control"); break; case kHIDUsage_PD_ToggleControl: sprintf (cstrName, "Power Device Toogle Sequence Control"); break; case kHIDUsage_PD_LowVoltageTransfer: sprintf (cstrName, "Power Device Min Transfer Voltage"); break; case kHIDUsage_PD_HighVoltageTransfer: sprintf (cstrName, "Power Device Max Transfer Voltage"); break; case kHIDUsage_PD_DelayBeforeReboot: sprintf (cstrName, "Power Device Delay Before Reboot"); break; case kHIDUsage_PD_DelayBeforeStartup: sprintf (cstrName, "Power Device Delay Before Startup"); break; case kHIDUsage_PD_DelayBeforeShutdown: sprintf (cstrName, "Power Device Delay Before Shutdown"); break; case kHIDUsage_PD_Test: sprintf (cstrName, "Power Device Test Request/Result"); break; case kHIDUsage_PD_ModuleReset: sprintf (cstrName, "Power Device Reset Request/Result"); break; case kHIDUsage_PD_AudibleAlarmControl: sprintf (cstrName, "Power Device Audible Alarm Control"); break; case kHIDUsage_PD_Present: sprintf (cstrName, "Power Device Present"); break; case kHIDUsage_PD_Good: sprintf (cstrName, "Power Device Good"); break; case kHIDUsage_PD_InternalFailure: sprintf (cstrName, "Power Device Internal Failure"); break; case kHIDUsage_PD_VoltageOutOfRange: sprintf (cstrName, "Power Device Voltage Out Of Range"); break; case kHIDUsage_PD_FrequencyOutOfRange: sprintf (cstrName, "Power Device Frequency Out Of Range"); break; case kHIDUsage_PD_Overload: sprintf (cstrName, "Power Device Overload"); break; case kHIDUsage_PD_OverCharged: sprintf (cstrName, "Power Device Over Charged"); break; case kHIDUsage_PD_OverTemperature: sprintf (cstrName, "Power Device Over Temperature"); break; case kHIDUsage_PD_ShutdownRequested: sprintf (cstrName, "Power Device Shutdown Requested"); break; case kHIDUsage_PD_ShutdownImminent: sprintf (cstrName, "Power Device Shutdown Imminent"); break; case kHIDUsage_PD_SwitchOnOff: sprintf (cstrName, "Power Device On/Off Switch Status"); break; case kHIDUsage_PD_Switchable: sprintf (cstrName, "Power Device Switchable"); break; case kHIDUsage_PD_Used: sprintf (cstrName, "Power Device Used"); break; case kHIDUsage_PD_Boost: sprintf (cstrName, "Power Device Boosted"); break; case kHIDUsage_PD_Buck: sprintf (cstrName, "Power Device Bucked"); break; case kHIDUsage_PD_Initialized: sprintf (cstrName, "Power Device Initialized"); break; case kHIDUsage_PD_Tested: sprintf (cstrName, "Power Device Tested"); break; case kHIDUsage_PD_AwaitingPower: sprintf (cstrName, "Power Device Awaiting Power"); break; case kHIDUsage_PD_CommunicationLost: sprintf (cstrName, "Power Device Communication Lost"); break; case kHIDUsage_PD_iManufacturer: sprintf (cstrName, "Power Device Manufacturer String Index"); break; case kHIDUsage_PD_iProduct: sprintf (cstrName, "Power Device Product String Index"); break; case kHIDUsage_PD_iserialNumber: sprintf (cstrName, "Power Device Serial Number String Index"); break; default: sprintf (cstrName, "Power Device Usage 0x%lx", valueUsage); break; } break; case kHIDPage_BatterySystem: if (((valueUsage >= 0x0A) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x1E) && (valueUsage <= 0x27)) || ((valueUsage >= 0x30) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x4C) && (valueUsage <= 0x5F)) || ((valueUsage >= 0x6C) && (valueUsage <= 0x7F)) || ((valueUsage >= 0x90) && (valueUsage <= 0xBF)) || ((valueUsage >= 0xC3) && (valueUsage <= 0xCF)) || ((valueUsage >= 0xDD) && (valueUsage <= 0xEF)) || ((valueUsage >= 0xF2) && (valueUsage <= 0xFF))) sprintf (cstrName, "Power Device Reserved"); else switch (valueUsage) { case kHIDUsage_BS_Undefined: sprintf (cstrName, "Battery System Undefined"); break; case kHIDUsage_BS_SMBBatteryMode: sprintf (cstrName, "SMB Mode"); break; case kHIDUsage_BS_SMBBatteryStatus: sprintf (cstrName, "SMB Status"); break; case kHIDUsage_BS_SMBAlarmWarning: sprintf (cstrName, "SMB Alarm Warning"); break; case kHIDUsage_BS_SMBChargerMode: sprintf (cstrName, "SMB Charger Mode"); break; case kHIDUsage_BS_SMBChargerStatus: sprintf (cstrName, "SMB Charger Status"); break; case kHIDUsage_BS_SMBChargerSpecInfo: sprintf (cstrName, "SMB Charger Extended Status"); break; case kHIDUsage_BS_SMBSelectorState: sprintf (cstrName, "SMB Selector State"); break; case kHIDUsage_BS_SMBSelectorPresets: sprintf (cstrName, "SMB Selector Presets"); break; case kHIDUsage_BS_SMBSelectorInfo: sprintf (cstrName, "SMB Selector Info"); break; case kHIDUsage_BS_OptionalMfgFunction1: sprintf (cstrName, "Battery System Optional SMB Mfg Function 1"); break; case kHIDUsage_BS_OptionalMfgFunction2: sprintf (cstrName, "Battery System Optional SMB Mfg Function 2"); break; case kHIDUsage_BS_OptionalMfgFunction3: sprintf (cstrName, "Battery System Optional SMB Mfg Function 3"); break; case kHIDUsage_BS_OptionalMfgFunction4: sprintf (cstrName, "Battery System Optional SMB Mfg Function 4"); break; case kHIDUsage_BS_OptionalMfgFunction5: sprintf (cstrName, "Battery System Optional SMB Mfg Function 5"); break; case kHIDUsage_BS_ConnectionToSMBus: sprintf (cstrName, "Battery System Connection To System Management Bus"); break; case kHIDUsage_BS_OutputConnection: sprintf (cstrName, "Battery System Output Connection Status"); break; case kHIDUsage_BS_ChargerConnection: sprintf (cstrName, "Battery System Charger Connection"); break; case kHIDUsage_BS_BatteryInsertion: sprintf (cstrName, "Battery System Battery Insertion"); break; case kHIDUsage_BS_Usenext: sprintf (cstrName, "Battery System Use Next"); break; case kHIDUsage_BS_OKToUse: sprintf (cstrName, "Battery System OK To Use"); break; case kHIDUsage_BS_BatterySupported: sprintf (cstrName, "Battery System Battery Supported"); break; case kHIDUsage_BS_SelectorRevision: sprintf (cstrName, "Battery System Selector Revision"); break; case kHIDUsage_BS_ChargingIndicator: sprintf (cstrName, "Battery System Charging Indicator"); break; case kHIDUsage_BS_ManufacturerAccess: sprintf (cstrName, "Battery System Manufacturer Access"); break; case kHIDUsage_BS_RemainingCapacityLimit: sprintf (cstrName, "Battery System Remaining Capacity Limit"); break; case kHIDUsage_BS_RemainingTimeLimit: sprintf (cstrName, "Battery System Remaining Time Limit"); break; case kHIDUsage_BS_AtRate: sprintf (cstrName, "Battery System At Rate..."); break; case kHIDUsage_BS_CapacityMode: sprintf (cstrName, "Battery System Capacity Mode"); break; case kHIDUsage_BS_BroadcastToCharger: sprintf (cstrName, "Battery System Broadcast To Charger"); break; case kHIDUsage_BS_PrimaryBattery: sprintf (cstrName, "Battery System Primary Battery"); break; case kHIDUsage_BS_ChargeController: sprintf (cstrName, "Battery System Charge Controller"); break; case kHIDUsage_BS_TerminateCharge: sprintf (cstrName, "Battery System Terminate Charge"); break; case kHIDUsage_BS_TerminateDischarge: sprintf (cstrName, "Battery System Terminate Discharge"); break; case kHIDUsage_BS_BelowRemainingCapacityLimit: sprintf (cstrName, "Battery System Below Remaining Capacity Limit"); break; case kHIDUsage_BS_RemainingTimeLimitExpired: sprintf (cstrName, "Battery System Remaining Time Limit Expired"); break; case kHIDUsage_BS_Charging: sprintf (cstrName, "Battery System Charging"); break; case kHIDUsage_BS_Discharging: sprintf (cstrName, "Battery System Discharging"); break; case kHIDUsage_BS_FullyCharged: sprintf (cstrName, "Battery System Fully Charged"); break; case kHIDUsage_BS_FullyDischarged: sprintf (cstrName, "Battery System Fully Discharged"); break; case kHIDUsage_BS_ConditioningFlag: sprintf (cstrName, "Battery System Conditioning Flag"); break; case kHIDUsage_BS_AtRateOK: sprintf (cstrName, "Battery System At Rate OK"); break; case kHIDUsage_BS_SMBErrorCode: sprintf (cstrName, "Battery System SMB Error Code"); break; case kHIDUsage_BS_NeedReplacement: sprintf (cstrName, "Battery System Need Replacement"); break; case kHIDUsage_BS_AtRateTimeToFull: sprintf (cstrName, "Battery System At Rate Time To Full"); break; case kHIDUsage_BS_AtRateTimeToEmpty: sprintf (cstrName, "Battery System At Rate Time To Empty"); break; case kHIDUsage_BS_AverageCurrent: sprintf (cstrName, "Battery System Average Current"); break; case kHIDUsage_BS_Maxerror: sprintf (cstrName, "Battery System Max Error"); break; case kHIDUsage_BS_RelativeStateOfCharge: sprintf (cstrName, "Battery System Relative State Of Charge"); break; case kHIDUsage_BS_AbsoluteStateOfCharge: sprintf (cstrName, "Battery System Absolute State Of Charge"); break; case kHIDUsage_BS_RemainingCapacity: sprintf (cstrName, "Battery System Remaining Capacity"); break; case kHIDUsage_BS_FullChargeCapacity: sprintf (cstrName, "Battery System Full Charge Capacity"); break; case kHIDUsage_BS_RunTimeToEmpty: sprintf (cstrName, "Battery System Run Time To Empty"); break; case kHIDUsage_BS_AverageTimeToEmpty: sprintf (cstrName, "Battery System Average Time To Empty"); break; case kHIDUsage_BS_AverageTimeToFull: sprintf (cstrName, "Battery System Average Time To Full"); break; case kHIDUsage_BS_CycleCount: sprintf (cstrName, "Battery System Cycle Count"); break; case kHIDUsage_BS_BattPackModelLevel: sprintf (cstrName, "Battery System Batt Pack Model Level"); break; case kHIDUsage_BS_InternalChargeController: sprintf (cstrName, "Battery System Internal Charge Controller"); break; case kHIDUsage_BS_PrimaryBatterySupport: sprintf (cstrName, "Battery System Primary Battery Support"); break; case kHIDUsage_BS_DesignCapacity: sprintf (cstrName, "Battery System Design Capacity"); break; case kHIDUsage_BS_SpecificationInfo: sprintf (cstrName, "Battery System Specification Info"); break; case kHIDUsage_BS_ManufacturerDate: sprintf (cstrName, "Battery System Manufacturer Date"); break; case kHIDUsage_BS_SerialNumber: sprintf (cstrName, "Battery System Serial Number"); break; case kHIDUsage_BS_iManufacturerName: sprintf (cstrName, "Battery System Manufacturer Name Index"); break; case kHIDUsage_BS_iDevicename: sprintf (cstrName, "Battery System Device Name Index"); break; case kHIDUsage_BS_iDeviceChemistry: sprintf (cstrName, "Battery System Device Chemistry Index"); break; case kHIDUsage_BS_ManufacturerData: sprintf (cstrName, "Battery System Manufacturer Data"); break; case kHIDUsage_BS_Rechargable: sprintf (cstrName, "Battery System Rechargable"); break; case kHIDUsage_BS_WarningCapacityLimit: sprintf (cstrName, "Battery System Warning Capacity Limit"); break; case kHIDUsage_BS_CapacityGranularity1: sprintf (cstrName, "Battery System Capacity Granularity 1"); break; case kHIDUsage_BS_CapacityGranularity2: sprintf (cstrName, "Battery System Capacity Granularity 2"); break; case kHIDUsage_BS_iOEMInformation: sprintf (cstrName, "Battery System OEM Information Index"); break; case kHIDUsage_BS_InhibitCharge: sprintf (cstrName, "Battery System Inhibit Charge"); break; case kHIDUsage_BS_EnablePolling: sprintf (cstrName, "Battery System Enable Polling"); break; case kHIDUsage_BS_ResetToZero: sprintf (cstrName, "Battery System Reset To Zero"); break; case kHIDUsage_BS_ACPresent: sprintf (cstrName, "Battery System AC Present"); break; case kHIDUsage_BS_BatteryPresent: sprintf (cstrName, "Battery System Battery Present"); break; case kHIDUsage_BS_PowerFail: sprintf (cstrName, "Battery System Power Fail"); break; case kHIDUsage_BS_AlarmInhibited: sprintf (cstrName, "Battery System Alarm Inhibited"); break; case kHIDUsage_BS_ThermistorUnderRange: sprintf (cstrName, "Battery System Thermistor Under Range"); break; case kHIDUsage_BS_ThermistorHot: sprintf (cstrName, "Battery System Thermistor Hot"); break; case kHIDUsage_BS_ThermistorCold: sprintf (cstrName, "Battery System Thermistor Cold"); break; case kHIDUsage_BS_ThermistorOverRange: sprintf (cstrName, "Battery System Thermistor Over Range"); break; case kHIDUsage_BS_VoltageOutOfRange: sprintf (cstrName, "Battery System Voltage Out Of Range"); break; case kHIDUsage_BS_CurrentOutOfRange: sprintf (cstrName, "Battery System Current Out Of Range"); break; case kHIDUsage_BS_CurrentNotRegulated: sprintf (cstrName, "Battery System Current Not Regulated"); break; case kHIDUsage_BS_VoltageNotRegulated: sprintf (cstrName, "Battery System Voltage Not Regulated"); break; case kHIDUsage_BS_MasterMode: sprintf (cstrName, "Battery System Master Mode"); break; case kHIDUsage_BS_ChargerSelectorSupport: sprintf (cstrName, "Battery System Charger Support Selector"); break; case kHIDUsage_BS_ChargerSpec: sprintf (cstrName, "attery System Charger Specification"); break; case kHIDUsage_BS_Level2: sprintf (cstrName, "Battery System Charger Level 2"); break; case kHIDUsage_BS_Level3: sprintf (cstrName, "Battery System Charger Level 3"); break; default: sprintf (cstrName, "Battery System Usage 0x%lx", valueUsage); break; } break; case kHIDPage_AlphanumericDisplay: switch (valueUsage) { default: sprintf (cstrName, "Alphanumeric Display Usage 0x%lx", valueUsage); break; } break; case kHIDPage_BarCodeScanner: switch (valueUsage) { default: sprintf (cstrName, "Bar Code Scanner Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Scale: switch (valueUsage) { default: sprintf (cstrName, "Scale Usage 0x%lx", valueUsage); break; } break; case kHIDPage_CameraControl: switch (valueUsage) { default: sprintf (cstrName, "Camera Control Usage 0x%lx", valueUsage); break; } break; case kHIDPage_Arcade: switch (valueUsage) { default: sprintf (cstrName, "Arcade Usage 0x%lx", valueUsage); break; } break; default: if (valueUsagePage > kHIDPage_VendorDefinedStart) sprintf (cstrName, "Vendor Defined Usage 0x%lx", valueUsage); else sprintf (cstrName, "Page: 0x%lx, Usage: 0x%lx", valueUsagePage, valueUsage); break; } } // --------------------------------- // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement) { if (NULL != pElement) { float deviceScale = pElement->max - pElement->min; float readScale = pElement->calMax - pElement->calMin; if (readScale == 0) return value; // no scaling as else return ((value - pElement->calMin) * deviceScale / readScale) + pElement->min; } else return 0; // bad element passed in } // --------------------------------- // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values SInt32 HIDScaleValue (SInt32 value, pRecElement pElement) { float deviceScale = pElement->userMax - pElement->userMin; float readScale = pElement->max - pElement->min; if (readScale == 0) return value; else return (value - pElement->min) * deviceScale / readScale + pElement->userMin; } // --------------------------------- // convert an element type to a mask HIDElementTypeMask HIDConvertElementTypeToMask (const long type) { HIDElementTypeMask result = kHIDElementTypeAll; switch (type) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: result = kHIDElementTypeInput; break; case kIOHIDElementTypeOutput: result = kHIDElementTypeOutput; break; case kIOHIDElementTypeFeature: result = kHIDElementTypeFeature; break; case kIOHIDElementTypeCollection: result = kHIDElementTypeCollection; break; default: result = kHIDElementTypeAll; break; } return result; } Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice) { pRecDevice pDevice, pBestDevice = NULL; long bestScore = 0; // iterate over all devices pDevice = HIDGetFirstDevice(); while (pDevice) { long deviceScore = 1; if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) { deviceScore += 10; if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) deviceScore += 8; } if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) deviceScore += 9; if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) deviceScore += 5; if (deviceScore > bestScore) { pBestDevice = pDevice; bestScore = deviceScore; #if 0 // set true to output scoring informaton printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pDevice = HIDGetNextDevice(pDevice); } if (NULL != pBestDevice) { *ppFoundDevice = pBestDevice; #if 0 // set true to output scoring informaton printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); #endif return true; } else return false; } // --------------------------------- // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement) { pRecDevice pDevice, pBestDevice = NULL; pRecElement pElement, pBestElement = NULL; HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); long bestScore = 0; // iterate over all devices pDevice = HIDGetFirstDevice(); while (pDevice) { long deviceScore = 1; if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID)) { deviceScore += 10; if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID)) deviceScore += 8; } if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) && (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage))) deviceScore += 9; if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID)) deviceScore += 5; // iterate over all elements of this device pElement = HIDGetFirstDeviceElement(pDevice, hidMask); while (pElement) { long score = deviceScore; if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) { score += 5; if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) score += 4; } else score = 0; #if 0 // set true to output scoring informaton if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here { printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pElement); } #endif if (score > bestScore) { pBestDevice = pDevice; pBestElement = pElement; bestScore = score; #if 0 // set true to output scoring informaton printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pElement = HIDGetNextDeviceElement(pElement, hidMask); } pDevice = HIDGetNextDevice(pDevice); } if ((NULL != pBestDevice) || (NULL != pBestElement)) { *ppFoundDevice = pBestDevice; *ppFoundElement = pBestElement; #if 0 // set true to output scoring informaton printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); #endif return true; } else return false; } // --------------------------------- // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement) { pRecElement pElement, pBestElement = NULL; HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type); long bestScore = 0; if ((NULL == pStartElement) || (NULL == pSearchElement) || (NULL == ppFoundElement)) return false; // iterate over all children of this element pElement = pStartElement->pChild; while (pElement) { long score = 0; #if 0 // set true to output searching informaton printf("\n-HIDFindSubElement, search = {t:%.2lX, u:%.4lX:%.4lX}, match = {t:%.2lX, u:%.4lX:%.4lX, s:\"%s\"}", pSearchElement->type, pSearchElement->usagePage, pSearchElement->usage, pElement->type, pElement->usagePage, pElement->usage, pElement->name); fflush(stdout); #endif if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage))) { score += 4; if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie)) score += 5; } #if 0 // set true to output searching informaton if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here { printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pElement); } #endif if (score > bestScore) { pBestElement = pElement; bestScore = score; #if 0 // set true to output searching informaton printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score); HIDPrintElement(pBestElement); #endif } pElement = HIDGetNextDeviceElement(pElement, hidMask); } #if 0 // set true to output searching informaton if (pBestElement) { printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore); HIDPrintElement(pBestElement); printf("\n"); } #endif *ppFoundElement = pBestElement; return (NULL != pBestElement); } // print out all of an elements information int HIDPrintElement(const pRecElement pElement) { int results; int count; printf("\n"); if (gDepth != pElement->depth) printf("%d",gDepth); for (count = 0;count < pElement->depth;count++) printf(" | "); #if 0 // this is verbose results = printf("-HIDPrintElement = {name: \"%s\", t: 0x%.2lX, u:%ld:%ld, c: %ld, min/max: %ld/%ld, scaled: %ld/%ld, size: %ld, rel: %s, wrap: %s, nonLinear: %s, preferred: %s, nullState: %s, units: %ld, exp: %ld, cal: %ld/%ld, user: %ld/%ld, depth: %ld}.", pElement->name, // name of element (c string) pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change pElement->min, // reported min value possible pElement->max, // reported max value possible pElement->scaledMin, // reported scaled min value possible pElement->scaledMax, // reported scaled max value possible pElement->size, // size in bits of data return from element pElement->relative ? "YES" : "NO", // are reports relative to last report (deltas) pElement->wrapping ? "YES" : "NO", // does element wrap around (one value higher than max is min) pElement->nonLinear ? "YES" : "NO", // are the values reported non-linear relative to element movement pElement->preferredState ? "YES" : "NO",// does element have a preferred state (such as a button) pElement->nullState ? "YES" : "NO", // does element have null state pElement->units, // units value is reported in (not used very often) pElement->unitExp, // exponent for units (also not used very often) pElement->calMin, // min returned value (for calibrate call) pElement->calMax, // max returned value pElement->userMin, // user set min to scale to (for scale call) pElement->userMax, // user set max pElement->depth ); #else // this is brief results = printf("-HIDPrintElement = {t: 0x%lX, u:%ld:%ld, c: %ld, name: \"%s\", d: %ld}.", pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change pElement->name, // name of element (c string) pElement->depth ); #endif fflush(stdout); return results; } // return true if this is a valid device pointer Boolean HIDIsValidDevice(const pRecDevice pSearchDevice) { pRecDevice pDevice = gpDeviceList; while (pDevice) { if (pDevice == pSearchDevice) return true; pDevice = pDevice->pNext; } return false; } // return true if this is a valid element pointer for this device Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement) { if (HIDIsValidDevice(pSearchDevice)) { pRecElement pRecElementTemp = HIDGetFirstDeviceElement(pSearchDevice,kHIDElementTypeAll); while (pRecElementTemp) { if (pRecElementTemp == pSearchElement) return true; pRecElementTemp = HIDGetNextDeviceElement(pRecElementTemp,kHIDElementTypeAll); } } return false; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Utilities.h ================================================ /* File: HID_Utilities.h Contains: External interface for HID Utilities DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_h_ #define _HID_Utilities_h_ #include <Carbon/Carbon.h> #include <IOKit/IOTypes.h> // 10.0.x //#include <IOKit/IOUSBHIDParser.h> // 10.1.x #include <IOKit/hid/IOHIDUsageTables.h> #include <IOKit/hid/IOHIDLib.h> // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== enum { kDefaultUserMin = 0, // default user min and max used for scaling kDefaultUserMax = 255, }; typedef enum HIDElementTypeMask { kHIDElementTypeInput = 1 << 1, kHIDElementTypeOutput = 1 << 2, kHIDElementTypeFeature = 1 << 3, kHIDElementTypeCollection = 1 << 4, kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection }HIDElementTypeMask; struct recElement { IOHIDElementType type; // the type defined by IOHIDElementType in IOHIDKeys.h long usagePage; // usage page from IOUSBHIDParser.h which defines general usage long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage IOHIDElementCookie cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change long min; // reported min value possible long max; // reported max value possible long scaledMin; // reported scaled min value possible long scaledMax; // reported scaled max value possible long size; // size in bits of data return from element Boolean relative; // are reports relative to last report (deltas) Boolean wrapping; // does element wrap around (one value higher than max is min) Boolean nonLinear; // are the values reported non-linear relative to element movement Boolean preferredState; // does element have a preferred state (such as a button) Boolean nullState; // does element have null state long units; // units value is reported in (not used very often) long unitExp; // exponent for units (also not used very often) Str255 name; // name of element (not used often) // runtime variables long minReport; // min returned value long maxReport; // max returned value (calibrate call) long userMin; // user set value to scale to (scale call) long userMax; struct recElement * pPrevious; // previous element (NULL at list head) struct recElement * pChild; // next child (only of collections) struct recElement * pSibling; // next sibling (for elements and collections) }; typedef struct recElement recElement; typedef recElement* pRecElement; struct recDevice { IOHIDDeviceInterface ** interface; // interface to device, NULL = no interface IOHIDQueueInterface ** queue; // device queue, NULL = no queue CFRunLoopSourceRef queueRunLoopSource; // device queue run loop source, NULL == no source IOHIDOutputTransactionInterface ** transaction; // output transaction interface, NULL == no transaction io_object_t notification; // notifications Str255 transport; // device transport long vendorID; // id for device vendor, unique across all devices long productID; // id for particular product, unique across all of a vendors devices long version; // version of product Str255 manufacturer; // name of manufacturer Str255 product; // name of product Str255 serial; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine long usage; // usage page from IOUSBHID Parser.h which defines general usage long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) long features; // number of elements of type kIOHIDElementTypeFeature long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes long outputs; // number of elements of type kIOHIDElementTypeOutput long collections; // number of elements of type kIOHIDElementTypeCollection long axis; // number of axis (calculated, not reported by device) long buttons; // number of buttons (calculated, not reported by device) long hats; // number of hat switches (calculated, not reported by device) long sliders; // number of sliders (calculated, not reported by device) long dials; // number of dials (calculated, not reported by device) long wheels; // number of wheels (calculated, not reported by device) recElement* pListElements; // head of linked list of elements struct recDevice* pNext; // next device }; typedef struct recDevice recDevice; typedef recDevice* pRecDevice; // ================================== // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting extern IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, pRecDevice pDevice); // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, butnot user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain extern void HIDReleaseDeviceList (void); // does a device list exist extern Boolean HIDHaveDeviceList (void); // how many HID devices have been found // returns 0 if no device list exist extern UInt32 HIDCountDevices (void); // how many elements does a specific device have // returns 0 if device is invalid or NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); // get the first device in the device list // returns NULL if no list exists extern pRecDevice HIDGetFirstDevice (void); // get next device in list given current device as parameter // returns NULL if end of list extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns empty string for invlid types extern void HIDGetTypeName (IOHIDElementType type, char * cstrName); // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); // --------------------------------- // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); #ifdef __cplusplus } #endif #endif // _HID_Utilities_h_ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Utilities_External.h ================================================ /* File: HID_Utilities_External.h Contains: Definition of the HID Utilities exported functions DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_External_h_ #define _HID_Utilities_External_h_ // ================================== //includes #if TARGET_RT_MAC_CFM typedef void (*IOHIDCallbackFunction)(void * target, unsigned long result, void* refcon, void * sender); #else #include <IOKit/hid/IOHIDLib.h> #endif TARGET_RT_MAC_CFM #include <stdio.h> #if 0 #include <IOKit/hid/IOHIDUsageTables.h> #include "PID.h" // NOTE: These are now in <IOHIDUsageTables.h> #include "IOHIDPowerUsage.h" // NOTE: These are now in <IOHIDUsageTables.h> #endif // ================================== #ifdef __cplusplus extern "C" { #endif // ================================== // Device and Element Interfaces typedef enum HIDElementTypeMask { kHIDElementTypeInput = 1 << 1, kHIDElementTypeOutput = 1 << 2, kHIDElementTypeFeature = 1 << 3, kHIDElementTypeCollection = 1 << 4, kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection }HIDElementTypeMask; struct recElement { unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h long usagePage; // usage page from IOUSBHIDParser.h which defines general usage long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change long min; // reported min value possible long max; // reported max value possible long scaledMin; // reported scaled min value possible long scaledMax; // reported scaled max value possible long size; // size in bits of data return from element unsigned char relative; // are reports relative to last report (deltas) unsigned char wrapping; // does element wrap around (one value higher than max is min) unsigned char nonLinear; // are the values reported non-linear relative to element movement unsigned char preferredState; // does element have a preferred state (such as a button) unsigned char nullState; // does element have null state long units; // units value is reported in (not used very often) long unitExp; // exponent for units (also not used very often) char name[256]; // name of element (c string) // runtime variables long calMin; // min returned value long calMax; // max returned value (calibrate call) long userMin; // user set value to scale to (scale call) long userMax; struct recElement * pPrevious; // previous element (NULL at list head) struct recElement * pChild; // next child (only of collections) struct recElement * pSibling; // next sibling (for elements and collections) long depth; }; typedef struct recElement recElement; typedef recElement* pRecElement; struct recDevice { void * interface; // interface to device, NULL = no interface void * queue; // device queue, NULL = no queue void * queueRunLoopSource; // device queue run loop source, NULL == no source void * transaction; // output transaction interface, NULL == no interface void * notification; // notifications char transport[256]; // device transport (c string) long vendorID; // id for device vendor, unique across all devices long productID; // id for particular product, unique across all of a vendors devices long version; // version of product char manufacturer[256]; // name of manufacturer char product[256]; // name of product char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often) long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine long usage; // usage page from IOUSBHID Parser.h which defines general usage long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device) long features; // number of elements of type kIOHIDElementTypeFeature long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes long outputs; // number of elements of type kIOHIDElementTypeOutput long collections; // number of elements of type kIOHIDElementTypeCollection long axis; // number of axis (calculated, not reported by device) long buttons; // number of buttons (calculated, not reported by device) long hats; // number of hat switches (calculated, not reported by device) long sliders; // number of sliders (calculated, not reported by device) long dials; // number of dials (calculated, not reported by device) long wheels; // number of wheels (calculated, not reported by device) recElement* pListElements; // head of linked list of elements struct recDevice* pNext; // next device }; typedef struct recDevice recDevice; typedef recDevice* pRecDevice; // ================================== // HID Utilities interface // ================================== // Create and open an interface to device, required prior to extracting values or building queues // Note: appliction now owns the device and must close and release it prior to exiting extern unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice); // builds list of device with elements (allocates memory and captures devices) // list is allcoated internally within HID Utilites and can be accessed via accessor functions // structures within list are considered flat and user accessable, butnot user modifiable // can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list) extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage); // release list built by above function // MUST be called prior to application exit to properly release devices // if not called (or app crashes) devices can be recovered by pluging into different location in USB chain extern void HIDReleaseDeviceList (void); // does a device list exist extern Boolean HIDHaveDeviceList (void); // how many HID devices have been found // returns 0 if no device list exist extern UInt32 HIDCountDevices (void); // how many elements does a specific device have // returns 0 if device is invalid or NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask); // get the first device in the device list // returns NULL if no list exists extern pRecDevice HIDGetFirstDevice (void); // get next device in list given current device as parameter // returns NULL if end of list extern pRecDevice HIDGetNextDevice (pRecDevice pDevice); // get the first element of device passed in as parameter // returns NULL if no list exists or device does not exists or is NULL // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask); // get next element of given device in list given current element as parameter // will walk down each collection then to next element or collection (depthwise traverse) // returns NULL if end of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // get previous element of given device in list given current element as parameter // this wlaks directly up the tree to the top element and does not search at each level // returns NULL if beginning of list // uses mask of HIDElementTypeMask to restrict element found // use kHIDElementTypeIO to get non-collection elements extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask); // returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h) // returns empty string for invlid types extern void HIDGetTypeName (IOHIDElementType theType, char * cstrName); // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h) // returns usage page and usage values in string form for unknown values extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName); // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement); // --------------------------------- // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); // ================================== // Element Event Queue and Value Interfaces enum { kDefaultUserMin = 0, // default user min and max used for scaling kDefaultUserMax = 255 }; enum { kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate of // if states change quickly (updates are only posted on state changes) }; // ================================== // queues specific element, performing any device queue set up required extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement); // adds all elements to queue, performing any device queue set up required extern unsigned long HIDQueueDevice (pRecDevice pDevice); // removes element for queue, if last element in queue will release queue and device extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement); // completely removes all elements from queue and releases queue and device extern unsigned long HIDDequeueDevice (pRecDevice pDevice); // releases all device queues for quit or rebuild (must be called) extern unsigned long HIDReleaseAllDeviceQueues (void); // releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList) extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice); // returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent); // returns current value for element, creating device interface as required, polling element extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); // Set an elements value // NOTE: This should only be used when a single element report needs to be sent. // If multiple elements reports are to be send then transactions should be used. // pIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent); // Set a callback to be called when a queue goes from empty to non-empty extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback); #if 0 // Get a report from a device extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize); // Send a report to a device extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize); #endif // ================================== // HUD utilities interfaces // returns calibrated value given raw value passed in // calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values extern long HIDCalibrateValue (long value, pRecElement pElement); // returns scaled value given raw value passed in // scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values extern long HIDScaleValue (long value, pRecElement pElement); // convert an element type to a mask extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type); // find this device extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement, pRecDevice *ppFoundDevice, pRecElement *ppFoundElement); // find the device and element for this action // Device: serial, vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement); // print out all of an elements information extern int HIDPrintElement(const pRecElement pElement); // return true if this is a valid device pointer extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice); // return true if this is a valid element pointer for this device extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement); // ================================== // Name Lookup Interfaces // set name from vendor id/product id look up (using cookies) extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName); // set name from vendor id/product id look up (using usage page & usage) extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName); // ================================== // Conguration and Save Interfaces enum { kPercentMove = 10 // precent of overall range a element must move to register }; typedef struct recSaveHID { long actionCookie; // device // need to add serial number when I have a test case long vendorID; long productID; long locID; long usage; long usagePage; // elements long usagePageE; long usageE; void * cookie; }recSaveHID,*pRecSaveHID; // polls all devices and elements for a change greater than kPercentMove. Times out after given time // returns true and pointer to device and element if found // returns false and NULL for both parameters if not found extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout); // take input records, save required info // assume file is open and at correct position. extern void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie); // take file, read one record (assume file position is correct and file is open) // search for matching device // return pDevice, pElement and cookie for action extern long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement); // Save the device & element values into the specified key in the specified applications preferences extern Boolean HIDSaveElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement); // Find the specified preference in the specified application // search for matching device and element // return pDevice, pElement that matches extern Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement); // ================================== // Output Transaction interface // Create and open an transaction interface to device, required prior to extracting values or building Transactions extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement); // removes an element from a Transaction extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement); // return true if this transaction contains this element extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement); /* This changes the default value of an element, when the values of the */ /* elements are cleared, on clear or commit, they are reset to the */ /* default value */ /* This call can be made on elements that are not in the transaction, but */ /* has undefined behavior if made on elements not in the transaction */ /* which are later added to the transaction. */ /* In other words, an element should be added before its default is */ /* set, for well defined behavior. */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Get the current setting of an element's default value */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Add a change to the transaction, by setting an element value */ /* The change is not actually made until it is commited */ /* The element must be part of the transaction or this call will fail */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Get the current setting of an element value */ // pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent); /* Commit the transaction, or clear all the changes and start over */ /* timoutMS is the timeout in milliseconds, a zero timeout will cause */ /* this call to be non-blocking (returning queue empty) if there */ /* is a NULL callback, and blocking forever until the queue is */ /* non-empty if their is a valid callback */ /* callback, if non-NULL is a callback to be called when data is */ /* inserted to the queue */ /* callbackTarget and callbackRefcon are passed to the callback */ extern unsigned long HIDTransactionCommit(pRecDevice pDevice); /* Clear all the changes and start over */ extern unsigned long HIDTransactionClear(pRecDevice pDevice); // ================================== #ifdef __cplusplus } #endif #endif // _HID_Utilities_External_h_ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/HID_Utilities_Internal.h ================================================ /* File: HID_Utilities_Internal.h Contains: Definition of HID Utilities internal functions DRI: George Warner Copyright: Copyright 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HID_Utilities_Internal_h_ #define _HID_Utilities_Internal_h_ // Moved into specific "HID_xxx.h" files. #include "HID_Error_Handler.h" #endif // _HID_Utilities_Internal_h_ ================================================ FILE: vm/src/from_squeak/iOS/plugins/JoystickTabletPlugin/sqMacJoystickAndTablet.c ================================================ /* Adjustments for pluginized VM * * Note: The Mac support files have not yet been fully converted to * pluginization. For the time being, it is assumed that they are linked * with the VM. When conversion is complete, they will no longer import * "sq.h" and they will access all VM functions and variables through * the interpreterProxy mechanism. */ #include "sq.h" #include "JoystickTabletPlugin.h" /* End of adjustments for pluginized VM */ #pragma mark Joystick support for Mac OS X #include "HID_Utilities.h" long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement); int joystickInit(void) { HIDBuildDeviceList(kHIDPage_GenericDesktop, 0); return true; } int joystickShutdown() { HIDReleaseDeviceList(); return true; } static pRecDevice getJoystickDevice(int stickIndex) { pRecDevice device = HIDGetFirstDevice(); int stickCount = 0; while (device) { if ( (device->usage == kHIDUsage_GD_Joystick) || (device->usage == kHIDUsage_GD_GamePad) ) { stickCount++; if (stickCount == stickIndex) return device; } device = HIDGetNextDevice(device); } return NULL; } static int getScaledAxisValue(pRecDevice device, pRecElement element, int userMin, int userMax) { SInt32 raw = HIDGetElementValue(device, element); element -> userMin = userMin; element -> userMax = userMax; return (int) HIDScaleValue(raw, element); } int joystickRead(int stickIndex) { /* Return input word for the joystick with the given index (starting at 1). This word is encoded as follows: <onFlag (1 bit)><buttonFlags (5 bits)><x-value (11 bits)><y-value (11 bits)> The highest four bits of the input word are zero. If the onFlag bit is zero, there is no joystick at the given index. The x and y values are 11-bit signed values in the range [-1024..1023] representing the raw (unencoded) joystick position. */ int onFlag = 0; int buttons = 0; int xValue = 0; int yValue = 0; pRecDevice device = getJoystickDevice(stickIndex); if (device) { onFlag = 1; pRecElement element = HIDGetFirstDeviceElement(device, kHIDElementTypeAll); while (element) { switch (element->usagePage) { case kHIDPage_GenericDesktop: switch (element->usage) { case kHIDUsage_GD_X: xValue = getScaledAxisValue(device, element, -1024, 1023); break; case kHIDUsage_GD_Y: yValue = getScaledAxisValue(device, element, -1024, 1023); break; } break; case kHIDPage_Button: { int button = element->usage - kHIDUsage_Button_1; if ((button >= 0) && (button <= 4) ) buttons |= (HIDGetElementValue(device, element) << button); } break; } element = HIDGetNextDeviceElement(element, kHIDElementTypeAll); } } return (onFlag << 27) | (buttons << 22) | ((yValue + 1024) << 11) | (xValue + 1024); } #pragma mark Tablet support for older versions of Mac OS /* Tablet Record (see Apple Tech. Note 266, version 2) */ #define MAX_TRANSDUCERS 4 typedef struct { char DOFTrans; /* degrees of freedom and transducer type */ char orientFlag; /* type of orientation information */ short pressLevels; /* pressure support and number of levels */ unsigned short xScale; /* x scale factor for screen mapping */ short xTrans; /* x translation factor for screen */ unsigned short yScale; /* y scale factor for screen mapping */ short yTrans; /* y translation factor for screen */ unsigned char flags; /* proximity, update flag, and # buttons */ unsigned char pressThresh; /* pressure threshold - normally unused */ short buttonMask; /* button mask of driver-reserved buttons */ short errorFlag; /* error code generated */ short buttons; /* buttons pressed */ short tangPress; /* tangential pressure level */ short pressure; /* normal pressure level */ long timeStamp; /* ticks at latest update */ long xCoord; /* x coordinate in resolution units */ long yCoord; /* y coordinate in resolution units */ long zCoord; /* z coordinate in resolution units */ short xTilt; /* x tilt */ short yTilt; /* y tilt */ short unused[8]; /* remainder of unused attitude matrix */ } TransducerRec, *TransducerRecPtr; typedef struct { char version; /* version of this data format */ char semaphore; /* for future use -- tells if drvr is enabled */ char cursors; /* number of cursors with tablet */ char updateFlags; /* flags used when updating structure */ short angleRes; /* metric bit & angular resolution */ short spaceRes; /* spatial resolution of the tablet */ long xDimension; /* x dimension in resolution units */ long yDimension; /* y dimension in resolution units */ long zDimension; /* z dimension in resolution units */ long xDisplace; /* x displacement - minimum x value */ long yDisplace; /* y displacement - minimum y value */ long zDisplace; /* z displacement - minimum z value */ long reserved; /* reserved */ long tabletID; /* contains 'TBLT' identifying the device */ TransducerRec transducer[MAX_TRANSDUCERS]; } TabletRec, *TabletRecPtr; /*** Variables ***/ TabletRecPtr tablet = nil; /* pointer to a tablet record or nil */ int tabletInit(void); int tabletInit(void) { /* Open the tablet driver and initialize the global pointer to its status record. Return true if a tablet exists, false otherwise. */ return false; } int tabletGetParameters(int cursorIndex, int result[]) { /* Fill in the integer array 'result' with tablet parameter information. For cursor-specific parameters, such as the number of pressure levels, return the information for the cursor with the given index, an integer between 1 and tablet->cursors. */ TransducerRecPtr cursorPtr; int cursor; /* open tablet if necessary; return false if no tablet */ if (tablet == nil) { if (!tabletInit()) return false; } cursor = cursorIndex - 1; if ((cursor < 0) || (cursor >= tablet->cursors)) { return false; } cursorPtr = &tablet->transducer[cursor]; result[0] = tablet->xDimension; result[1] = tablet->yDimension; result[2] = tablet->spaceRes; result[3] = tablet->cursors; /* number of cursors */ result[4] = cursor + 1; result[5] = cursorPtr->xScale; result[6] = cursorPtr->xTrans; result[7] = cursorPtr->yScale; result[8] = cursorPtr->yTrans; result[9] = cursorPtr->pressLevels; result[10] = cursorPtr->pressThresh; if (tablet->angleRes == 0) { result[11] = 0; /* no pen tilt support */ } else { result[11] = tablet->angleRes >> 1; /* number of pen tilt levels */ } return true; } int tabletRead(int cursorIndex, int result[]) { /* Fill in the integer array 'result' with the current data the cursor with the given index, an integer between 1 and tablet->cursors. Note that the timestamp changes only when some new data has arrived from the tablet. */ TransducerRecPtr cursorPtr; int cursor; /* open tablet if necessary; return false if no tablet */ if (tablet == nil) { if (!tabletInit()) return false; } cursor = cursorIndex - 1; if ((cursor < 0) || (cursor >= tablet->cursors)) { return false; } cursorPtr = &tablet->transducer[cursor]; result[0] = cursor + 1; result[1] = cursorPtr->timeStamp; result[2] = cursorPtr->xCoord; result[3] = cursorPtr->yCoord; result[4] = cursorPtr->zCoord; result[5] = cursorPtr->xTilt; result[6] = cursorPtr->yTilt; result[7] = (cursorPtr->DOFTrans & 0x30) >> 4; /* cursor type; 1-pen, 2-puck, 3-eraser */ result[8] = cursorPtr->buttons; result[9] = cursorPtr->pressure; result[10] = cursorPtr->tangPress; result[11] = cursorPtr->flags; return true; } int tabletResultSize(void) { /* Return the size of the integer array required to hold the results of either a tabletGetParameters() or tabletRead() call. The VM allocates an array of this length and passes it as a parameter to be filled in. */ return 12; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/LocalePlugin/sqMacLocaleCarbon.c ================================================ /* * sqMacLocaleCarbon.c * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include "sqMacLocaleCarbon.h" /* Locale support functions */ char * thisLocale; struct lconv * localeTable; sqInt sqLocInitialize(void) { thisLocale = setlocale(LC_ALL,""); localeTable = localeconv(); return true; } /************** Country and language ******************/ /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[4]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode); CFStringGetCString(stringRef, buffer, 4,kCFStringEncodingMacRoman); memcpy(str,buffer,3); CFRelease(userLocaleRef); } /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[4]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode); CFStringGetCString(stringRef, buffer, 4,kCFStringEncodingMacRoman); memcpy(str,buffer,3); CFRelease(userLocaleRef); } /***************** Currency ********************/ /* return 1 (true) if the currency symbol is to be placed in front of the *currency amount */ sqInt sqLocCurrencyNotation(void) { return localeTable->p_cs_precedes; } /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void) { return strlen(localeTable->currency_symbol); } /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str) { strcpy(str, localeTable->currency_symbol); } /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void) { CFLocaleRef userLocaleRef; CFStringRef stringRef; char buffer[7]; userLocaleRef = CFLocaleCopyCurrent(); stringRef = CFLocaleGetValue(userLocaleRef, kCFLocaleMeasurementSystem); CFStringGetCString(stringRef, buffer, 7,kCFStringEncodingMacRoman); CFRelease(userLocaleRef); if (strcmp(buffer, "Metric") == 0) return 1; else return 0; } /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str) { strncpy(str, localeTable->thousands_sep, 1); } /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str) { strncpy(str, localeTable->decimal_point, 1); } /****************** time and date *********************/ sqInt sqLocGetVMOffsetToUTC(void) { /* return 0 for now */ return 0; } sqInt sqLocGetTimezoneOffset(void) { CFTimeZoneRef zoneRef = CFTimeZoneCopySystem (); CFAbsoluteTime timeIs = CFAbsoluteTimeGetCurrent(); CFTimeInterval interval; interval = CFTimeZoneGetSecondsFromGMT (zoneRef,timeIs); CFRelease(zoneRef); return ((sqInt) interval)/60; } /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void) { struct tm * timeBlock; time_t theTime; theTime = time((time_t)NULL); timeBlock = localtime(&theTime); return timeBlock->tm_isdst; } void dateFormatIs(char *buffer,CFDateFormatterStyle type ) { CFDateFormatterRef longFormatter = CFDateFormatterCreate(NULL, NULL, type, type); CFStringRef longStrRef = CFDateFormatterGetFormat(longFormatter); CFStringGetCString(longStrRef, buffer, 255,kCFStringEncodingMacRoman); CFRelease(longFormatter); } /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); return strlen(buffer); } /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); memcpy(str, buffer,strlen(buffer)); } /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterShortStyle); return strlen(buffer); } /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterShortStyle); memcpy(str, buffer,strlen(buffer)); } /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); return strlen(buffer); } /* write the string describing the time formatting into string ptr. * Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str) { char buffer[256]; dateFormatIs(buffer,kCFDateFormatterLongStyle); memcpy(str, buffer,strlen(buffer)); } ================================================ FILE: vm/src/from_squeak/iOS/plugins/LocalePlugin/sqMacLocaleCarbon.h ================================================ /* * sqMacLocaleCarbon.h * SqueakLocale * * Created by John M McIntosh on 6/9/05. * */ #include <Carbon/Carbon.h> #include "sqMemoryAccess.h" #include <locale.h> #include "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/plugins/MIDIPlugin/sqMacMIDI.c ================================================ #include "sq.h" #include "MIDIPlugin.h" #include <Carbon/Carbon.h> #include <QuickTime/QuickTimeMusic.h> extern struct VirtualMachine *interpreterProxy; /* Quicktime MIDI note allocator and channels */ #define FIRST_DRUM_KIT 16385 void* portNamesFn; void* portIsOpenFn; void* portSetControlFn; void* serialPortOpenFn; void* serialPortCloseFn; void* serialPortCountFn; void* serialPortReadIntoFn; void* serialPortWriteFromFn; NoteAllocator na = nil; NoteChannel channel[16] = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}; /* Initial instruments: drums on channel 10, piano on all other channels */ int channelInstrument[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, FIRST_DRUM_KIT, 1, 1, 1, 1, 1, 1}; /* Quicktime MIDI parser state */ enum {idle, want1of2, want2of2, want1of1, sysExclusive}; int state = idle; int argByte1 = 0; int argByte2 = 0; int lastCmdByte = nil; /* number of argument bytes for each MIDI command */ char argumentBytes[128] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /*** Private Functions ***/ int setMidiClockRate(int portNum, int interfaceClockRate); int sqMIDIGetSerialPortCount(void); /*** Quicktime MIDI Support Functions ***/ void closeQuicktimeMIDIPort(void); void openQuicktimeMIDIPort(void); void performMIDICmd(int cmdByte, int arg1, int arg2); void processMIDIByte(int aByte); void startMIDICommand(int cmdByte); /* initialize/shutdown */ int midiInit() { portIsOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortIsOpen", "SerialPlugin"); if (portIsOpenFn == 0) { portIsOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortIsOpen", ""); if (portIsOpenFn == 0) return interpreterProxy->success(false); } portSetControlFn = interpreterProxy->ioLoadFunctionFrom("serialPortSetControl", "SerialPlugin"); if (portSetControlFn == 0) { portSetControlFn = interpreterProxy->ioLoadFunctionFrom("serialPortSetControl", ""); if (portSetControlFn == 0) return interpreterProxy->success(false); } serialPortCloseFn = interpreterProxy->ioLoadFunctionFrom("serialPortClose", "SerialPlugin"); if (serialPortCloseFn == 0) { serialPortCloseFn = interpreterProxy->ioLoadFunctionFrom("serialPortClose", ""); if (serialPortCloseFn == 0) return interpreterProxy->success(false); } serialPortCountFn = interpreterProxy->ioLoadFunctionFrom("serialPortCount", "SerialPlugin"); if (serialPortCountFn == 0) { serialPortCountFn = interpreterProxy->ioLoadFunctionFrom("serialPortCount", ""); if (serialPortCountFn == 0) return interpreterProxy->success(false); } portNamesFn = interpreterProxy->ioLoadFunctionFrom("serialPortNames", "SerialPlugin"); if (portNamesFn == 0) { portNamesFn = interpreterProxy->ioLoadFunctionFrom("serialPortNames", ""); if (portNamesFn == 0) return interpreterProxy->success(false); } serialPortOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortOpen", "SerialPlugin"); if (serialPortOpenFn == 0) { serialPortOpenFn = interpreterProxy->ioLoadFunctionFrom("serialPortOpen", ""); if (serialPortOpenFn == 0) return interpreterProxy->success(false); } serialPortReadIntoFn = interpreterProxy->ioLoadFunctionFrom("serialPortReadInto", "SerialPlugin"); if (serialPortReadIntoFn == 0) { serialPortReadIntoFn = interpreterProxy->ioLoadFunctionFrom("serialPortReadInto", ""); if (serialPortReadIntoFn == 0) return interpreterProxy->success(false); } serialPortWriteFromFn = interpreterProxy->ioLoadFunctionFrom("serialPortWriteFrom", "SerialPlugin"); if (serialPortWriteFromFn == 0) { serialPortWriteFromFn = interpreterProxy->ioLoadFunctionFrom("serialPortWriteFrom", ""); if (serialPortWriteFromFn == 0) return interpreterProxy->success(false); } return true; } int midiShutdown() { return 1; } /* helper function for MIDI module */ int sqMIDIParameter(int whichParameter, int modify, int newValue); int sqMIDIParameterSet(int whichParameter, int newValue) { sqMIDIParameter(whichParameter, true, newValue); return 0; } int sqMIDIParameterGet(int whichParameter) { sqMIDIParameter(whichParameter, false, 0); return 0; } int setMidiClockRate(int portNum, int interfaceClockRate) { #pragma unused(portNum, interfaceClockRate) /* Put the given port into MIDI mode, which uses a clock supplied by an external MIDI interface adaptor to determine the baud rate. Possible external clock rates: 31.25 KHz, 0.5 MHz, 1 MHz, or 2 MHz. */ return false; }/*** MIDI Parameters (used with sqMIDIParameter function) ***/ #define sqMIDIInstalled 1 /* Read-only. Return 1 if a MIDI driver is installed, 0 if not. On OMS-based MIDI drivers, this returns 1 only if the OMS system is properly installed and configured. */ #define sqMIDIVersion 2 /* Read-only. Return the integer version number of this MIDI driver. The version numbering sequence is relative to a particular driver. That is, version 3 of the Macintosh MIDI driver is not necessarily related to version 3 of the Win95 MIDI driver. */ #define sqMIDIHasBuffer 3 /* Read-only. Return 1 if this MIDI driver has a time-stamped output buffer, 0 otherwise. Such a buffer allows the client to schedule MIDI output packets to be sent later. This can allow more precise timing, since the driver uses timer interrupts to send the data at the right time even if the processor is in the midst of a long-running Squeak primitive or is running some other application or system task. */ #define sqMIDIHasDurs 4 /* Read-only. Return 1 if this MIDI driver supports an extended primitive for note-playing that includes the note duration and schedules both the note-on and the note-off messages in the driver. Otherwise, return 0. */ #define sqMIDICanSetClock 5 /* Read-only. Return 1 if this MIDI drivers clock can be set via an extended primitive, 0 if not. */ #define sqMIDICanUseSemaphore 6 /* Read-only. Return 1 if this MIDI driver can signal a semaphore when MIDI input arrives. Otherwise, return 0. If this driver supports controller caching and it is enabled, then incoming controller messages will not signal the semaphore. */ #define sqMIDIEchoOn 7 /* Read-write. If this flag is set to a non-zero value, and if the driver supports echoing, then incoming MIDI events will be echoed immediately. If this driver does not support echoing, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIUseControllerCache 8 /* Read-write. If this flag is set to a non-zero value, and if the driver supports a controller cache, then the driver will maintain a cache of the latest value seen for each MIDI controller, and control update messages will be filtered out of the incoming MIDI stream. An extended MIDI primitive allows the client to poll the driver for the current value of each controller. If this driver does not support a controller cache, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIEventsAvailable 9 /* Read-only. Return the number of MIDI packets in the input queue. */ #define sqMIDIFlushDriver 10 /* Write-only. Setting this parameter to any value forces the driver to flush its I/0 buffer, discarding all unprocessed data. Reading this parameter returns 0. Setting this parameter will do nothing if the driver does not support buffer flushing. */ #define sqMIDIClockTicksPerSec 11 /* Read-only. Return the MIDI clock rate in ticks per second. */ #define sqMIDIHasInputClock 12 /* Read-only. Return 1 if this MIDI driver timestamps incoming MIDI data with the current value of the MIDI clock, 0 otherwise. If the driver does not support such timestamping, then the client must read input data frequently and provide its own timestamping. */ /*** MIDI Functions ***/ int sqMIDIClosePort(int portNum) { /* Close the given MIDI port. Do nothing if the port is not open. Fail if there is no port of the given number.*/ int serialPorts; serialPorts = sqMIDIGetSerialPortCount(); if (portNum == serialPorts) { closeQuicktimeMIDIPort(); return 0; } else { if (serialPortCloseFn == 0) { return interpreterProxy->success(false); } return ((int (*) (int)) serialPortCloseFn)(portNum); } } int sqMIDIGetClock(void) { /* Return the current value of the clock used to schedule MIDI events. The MIDI clock is assumed to wrap at or before half the maximum positive SmallInteger value. This allows events to be scheduled into the future without overflowing into LargePositiveIntegers. This implementation does not support event scheduling, so it just returns the value of the Squeak millisecond clock. */ return interpreterProxy->ioMicroMSecs(); } int sqMIDIGetSerialPortCount(void) { /* Return the number of available hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ int serialPorts; if (serialPortCountFn == 0) { return 0; } serialPorts = ((int (*) (void)) serialPortCountFn)(); return serialPorts; /* serial ports */ } int sqMIDIGetPortCount(void) { /* Return the number of available MIDI interfaces, including both hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ return sqMIDIGetSerialPortCount() + 1; /* serial ports + QuickTime Synth */ } int sqMIDIGetPortDirectionality(int portNum) { /* Return an integer indicating the directionality of the given port where: 1 = input, 2 = output, 3 = bidirectional. Fail if there is no port of the given number. */ int serialPorts; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { return 2; } else { return 3; } } int sqMIDIGetPortName(int portNum, int namePtr, int length) { /* Copy the name of the given MIDI port into the string at the given address. Copy at most length characters, and return the number of characters copied. Fail if there is no port of the given number.*/ char userName[256], inName[256], outName[256]; int serialPorts, count; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { strcpy(userName, "QuickTime MIDI"); } else { if (portNamesFn == 0) { return 0; } ((int (*) (int , char *, char *, char *)) portNamesFn)(portNum, userName, inName, outName); } count = strlen(userName); if (count > length) count = length; memcpy((void *) namePtr, userName, count); return count; } int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate) { /* Open the given port, if possible. If non-zero, readSemaphoreIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Note that not all implementations support read semaphores (this one does not); see sqMIDICanUseSemaphore. The interfaceClockRate parameter specifies the clock speed for an external MIDI interface adaptor on platforms that use such adaptors (e.g., Macintosh). Fail if there is no port of the given number.*/ #pragma unused(readSemaIndex) int serialPorts; int err; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { openQuicktimeMIDIPort(); return 0; } if (serialPortOpenFn == 0) { return interpreterProxy->success(false); } err = ((int (*) (int , int , int , int , int , int , int , int , int ))serialPortOpenFn)(portNum, 9600, 1, 0, 8, 0, 0, 0, 0); if (!err) { err = setMidiClockRate(portNum, interfaceClockRate); if (err) { sqMIDIClosePort(portNum); } } return 0; } int sqMIDIParameter(int whichParameter, int modify, int newValue) { /* Read or write the given MIDI driver parameter. If modify is 0, then newValue is ignored and the current value of the specified parameter is returned. If modify is non-zero, then the specified parameter is set to newValue. Note that many MIDI driver parameters are read-only; attempting to set one of these parameters fails. For boolean parameters, true = 1, false = 0. */ #pragma unused(newValue) if (modify == 0) { switch(whichParameter) { case sqMIDIInstalled: return 1; break; case sqMIDIVersion: return 100; break; case sqMIDIHasBuffer: case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: case sqMIDIEchoOn: case sqMIDIUseControllerCache: return 0; break; case sqMIDIEventsAvailable: return 1; /* pretend that events are always available */ break; case sqMIDIFlushDriver: return 0; break; case sqMIDIClockTicksPerSec: return 1000; break; case sqMIDIHasInputClock: return 0; break; default: return interpreterProxy->success(false); } } else { switch(whichParameter) { case sqMIDIInstalled: case sqMIDIVersion: case sqMIDIHasBuffer: case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: return interpreterProxy->success(false); break; case sqMIDIEchoOn: /* noop; echoing not supported */ break; case sqMIDIUseControllerCache: /* noop; controller cache not supported */ break; case sqMIDIEventsAvailable: return interpreterProxy->success(false); break; case sqMIDIFlushDriver: /* noop; buffer flushing not supported */ break; case sqMIDIClockTicksPerSec: return interpreterProxy->success(false); break; default: return interpreterProxy->success(false); } } return 0; } int sqMIDIPortReadInto(int portNum, int count, int bufferPtr) { /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Copy up to (length - 4) bytes of incoming MIDI data into that buffer, preceded by a 4-byte timestamp in the units of the MIDI clock, most significant byte first. Implementations that do not support timestamping of incoming data as it arrives (see sqMIDIHasInputClock) simply set the timestamp to the value of the MIDI clock when this function is called. Return the total number of bytes read, including the timestamp bytes. Return zero if no data is available. Fail if the buffer is shorter than five bytes, since there must be enough room for the timestamp plus at least one data byte. */ int bytesRead; if (count < 5) return interpreterProxy->success(false); if (serialPortReadIntoFn == 0) { return interpreterProxy->success(false); } bytesRead = ((int (*) (int , int , int )) serialPortReadIntoFn)(portNum, count - 4, bufferPtr + 4); if (bytesRead == 0) return 0; *((int *) bufferPtr) = sqMIDIGetClock(); /* set timestamp */ return bytesRead + 4; } int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time) { /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Send its contents to the given port when the MIDI clock reaches the given time. If time equals zero, then send the data immediately. Implementations that do not support a timestamped output queue, such as this one, always send the data immediately; see sqMIDIHasBuffer. */ #pragma unused(time) int serialPorts, i; unsigned char *bytePtr; serialPorts = sqMIDIGetSerialPortCount(); if (portNum > serialPorts) return interpreterProxy->success(false); if (portNum == serialPorts) { if (!na) return interpreterProxy->success(false); /* QuickTime port not open */ bytePtr = (unsigned char *) bufferPtr; for (i = 0; i < count; i++) { processMIDIByte(*bytePtr++); } return count; } if (serialPortWriteFromFn == 0) { return interpreterProxy->success(false); } return ((int (*) (int , int , int )) serialPortWriteFromFn)(portNum, count - 4, bufferPtr + 4); } /*** Quicktime MIDI Support Functions ***/ void closeQuicktimeMIDIPort(void) { int i; if (!na) return; for (i = 0; i < 16; i++) { /* dispose of note channels */ if (channel[i]) NADisposeNoteChannel(na, channel[i]); channel[i] = nil; } CloseComponent(na); /* close note allocator */ } void openQuicktimeMIDIPort(void) { ComponentResult err; NoteRequest nr; NoteChannel nc; int i; short shortpoly; Fixed fixedtypical; closeQuicktimeMIDIPort(); na = OpenDefaultComponent('nota', 0); if (!na) return; for (i = 0; i < 16; i++) { shortpoly = CFSwapInt16HostToBig(11); memcpy(&nr.info.polyphony,&shortpoly,2); /* max simultaneous tones */ fixedtypical = CFSwapInt32HostToBig(0x00010000); memcpy(&nr.info.typicalPolyphony,&fixedtypical,4); NAStuffToneDescription(na, 1, &nr.tone); err = NANewNoteChannel(na, &nr, &nc); if (err || !nc) { closeQuicktimeMIDIPort(); return; } NAResetNoteChannel(na, nc); NASetInstrumentNumber(na, nc, channelInstrument[i]); channel[i] = nc; } state = idle; argByte1 = 0; argByte2 = 0; lastCmdByte = nil; return; } void performMIDICmd(int cmdByte, int arg1, int arg2) { /* Perform the given MIDI command with the given arguments. */ int ch, cmd, val, instrument, bend; ch = cmdByte & 0x0F; cmd = cmdByte & 0xF0; if (cmd == 128) { /* note off */ NAPlayNote(na, channel[ch], arg1, 0); } if (cmd == 144) { /* note on */ NAPlayNote(na, channel[ch], arg1, arg2); } if (cmd == 176) { /* control change */ if ((arg1 >= 32) && (arg1 <= 63)) { val = arg2 << 1; /* LSB of controllers 0-31 */ } else { val = arg2 << 8; /* scale MSB to QT controller range */ } NASetController(na, channel[ch], arg1, val); } if (cmd == 192) { /* program change */ if (ch == 9) { instrument = FIRST_DRUM_KIT + arg1; /* if channel 10, select a drum set */ } else { instrument = arg1 + 1; } NASetInstrumentNumber(na, channel[ch], instrument); channelInstrument[ch] = instrument; } if (cmd == 224) { /* pitch bend */ bend = ((arg2 << 7) + arg1) - (64 << 7); bend = bend / 32; /* default sensitivity = +/- 2 semitones */ NASetController(na, channel[ch], kControllerPitchBend, bend); } } void processMIDIByte(int aByte) { /* Process the given incoming MIDI byte and perform any completed commands. */ if (aByte > 247) return; /* skip all real-time messages */ switch (state) { case idle: if (aByte >= 128) { /* start a new command using the action table */ startMIDICommand(aByte); } else { /* data byte arrived in idle state: use running status if possible */ if (lastCmdByte == nil) { return; /* last command byte is not defined; just skip this byte */ } else { /* process this data as if it had the last command byte in front of it */ startMIDICommand(lastCmdByte); /* the previous line put us into a new state; we now do a recursive call to process the data byte in this new state. */ processMIDIByte(aByte); return; } } break; case want1of2: argByte1 = aByte; state = want2of2; break; case want2of2: argByte2 = aByte; performMIDICmd(lastCmdByte, argByte1, argByte2); state = idle; break; case want1of1: argByte1 = aByte; performMIDICmd(lastCmdByte, argByte1, 0); state = idle; break; case sysExclusive: if (aByte < 128) { /* skip a system exclusive data byte */ } else { if (aByte < 248) { /* a system exclusive message can be terminated by any non-real-time command byte */ state = idle; if (aByte != 247) { processMIDIByte(aByte); /* if not endSysExclusive, byte is the start the next command */ } } } break; } } void startMIDICommand(int cmdByte) { /* Start processing a MIDI message beginning with the given command byte. */ int argCount; argCount = argumentBytes[cmdByte - 128]; switch (argCount) { case 0: /* start a zero argument command (e.g., a real-time message) */ /* Stay in the current state and don't change active status. Real-time messages may arrive between data bytes without disruption. */ performMIDICmd(cmdByte, 0, 0); break; case 1: /* start a one argument command */ lastCmdByte = cmdByte; state = want1of1; break; case 2: /* start a two argument command */ lastCmdByte = cmdByte; state = want1of2; break; case 3: /* start a variable length 'system exclusive' command */ /* a system exclusive command clears running status */ lastCmdByte = nil; state = sysExclusive; break; } } ================================================ FILE: vm/src/from_squeak/iOS/plugins/MacMenubarPlugin/MacMenuOS9ToOSX.h ================================================ // // MacMenuOS9ToOSX.h // SqueakPureObjc // // Created by John M McIntosh on 09-12-26. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. // #include "MacMenubarPlugin.h" ================================================ FILE: vm/src/from_squeak/iOS/plugins/MacMenubarPlugin/MacMenuOS9ToOSX.m ================================================ // // MacMenuOS9ToOSX.m // SqueakPureObjc // // Created by John M McIntosh on 09-12-26. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. // #import "MacMenuOS9ToOSX.h" Boolean ioCheckMenuHandle(MenuHandle menuHandle) { int menuID; if (menuHandle == 0) return true; menuID = GetMenuID(menuHandle); if (menuID == 0) return false; return true; } MenuRef GetMenuHandle(MenuID menuID){ NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; NSMenuItem *menuRef = [mainMenu itemAtIndex: menuID]; MenuRef handle = (MenuRef)menuRef; return handle; }; void DisableMenuItem( MenuRef theMenu, MenuItemIndex item){}; void GetMenuItemText( MenuRef theMenu, MenuItemIndex item, Str255 itemString){}; OSErr SetMenuItemCommandID( MenuRef inMenu, MenuItemIndex inItem, MenuCommand inCommandID){}; void DisposeMenu(MenuRef theMenu){ //Do nothing I think }; OSErr GetMenuItemFontID( MenuRef inMenu, MenuItemIndex inItem, SInt16 * outFontID){}; OSErr SetMenuItemHierarchicalID( MenuRef inMenu, MenuItemIndex inItem, MenuID inHierID){}; OSErr GetMenuItemCommandID( MenuRef inMenu, MenuItemIndex inItem, MenuCommand * outCommandID){}; void SetItemIcon( MenuRef theMenu, MenuItemIndex item, short iconIndex) {}; void SetItemCmd( MenuRef theMenu, MenuItemIndex item, CharParameter cmdChar){}; MenuRef NewMenu( MenuID menuID, ConstStr255Param menuTitle){}; void SetItemMark( MenuRef theMenu, MenuItemIndex item, CharParameter markChar){}; extern Boolean IsMenuBarVisible(void){}; void DeleteMenu(MenuID menuID){ NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; [mainMenu removeItemAtIndex: menuID]; }; void ShowMenuBar(void){}; OSStatus AppendMenuItemText( MenuRef menu, ConstStr255Param inString) {}; OSErr SetMenuItemKeyGlyph( MenuRef inMenu, MenuItemIndex inItem, SInt16 inGlyph){}; void DeleteMenuItem( MenuRef theMenu, MenuItemIndex item) {}; OSErr GetMenuItemKeyGlyph( MenuRef inMenu, MenuItemIndex inItem, SInt16 * outGlyph){}; void ClearMenuBar(void){}; void SetItemStyle( MenuRef theMenu, MenuItemIndex item, StyleParameter chStyle) {}; void GetItemIcon( MenuRef theMenu, MenuItemIndex item, short * iconIndex){}; void EnableMenuItem( MenuRef theMenu, MenuItemIndex item){}; MenuBarHandle GetMenuBar(void){}; void GetItemMark( MenuRef theMenu, MenuItemIndex item, CharParameter * markChar){}; void HideMenuBar(void){}; void GetItemStyle( MenuRef theMenu, MenuItemIndex item, Style * chStyle){}; void EnableMenuItemIcon( MenuRef theMenu, MenuItemIndex item){}; void HiliteMenu(MenuID menuID){}; void InsertMenuItem( MenuRef theMenu, ConstStr255Param itemString, MenuItemIndex afterItem){}; void DisableMenuItemIcon( MenuRef theMenu, MenuItemIndex item){}; OSErr SetMenuItemModifiers( MenuRef inMenu, MenuItemIndex inItem, UInt8 inModifiers){}; void SetMenuItemText( MenuRef theMenu, MenuItemIndex item, ConstStr255Param itemString){}; OSErr SetMenuItemTextEncoding( MenuRef inMenu, MenuItemIndex inItem, TextEncoding inScriptID){}; OSStatus SetMenuTitle( MenuRef menu, ConstStr255Param title) {}; void CheckMenuItem( MenuRef theMenu, MenuItemIndex item, Boolean checked){}; Boolean IsMenuItemIconEnabled( MenuRef menu, MenuItemIndex item){}; OSErr SetMenuItemFontID( MenuRef inMenu, MenuItemIndex inItem, SInt16 inFontID){}; void InsertIntlResMenu( MenuRef theMenu, ResType theType, MenuItemIndex afterItem, short scriptFilter){}; Boolean IsMenuItemEnabled( MenuRef menu, MenuItemIndex item){}; extern void DrawMenuBar(void){}; OSErr GetMenuItemModifiers( MenuRef inMenu, MenuItemIndex inItem, UInt8 * outModifiers){}; OSErr GetMenuItemHierarchicalID( MenuRef inMenu, MenuItemIndex inItem, MenuID * outHierID){}; StringPtr GetMenuTitle( MenuRef menu, Str255 title){}; void SetMenuBar(MenuBarHandle mbar){}; UInt16 CountMenuItems(MenuRef theMenu){}; void GetItemCmd( MenuRef theMenu, MenuItemIndex item, CharParameter * cmdChar){}; MenuID GetMenuID(MenuRef menu){ NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; NSMenuItem *menuItem = (NSMenuItem *) menu; return (MenuID) [mainMenu indexOfItem: menuItem]; }; void InsertMenu( MenuRef theMenu, MenuID beforeID) {}; void InsertFontResMenu( MenuRef theMenu, MenuItemIndex afterItem, short scriptFilter){}; void AppendMenu( MenuRef menu, ConstStr255Param data){}; OSErr GetMenuItemTextEncoding( MenuRef inMenu, MenuItemIndex inItem, TextEncoding * outScriptID){}; void InvalMenuBar(void){}; void EnableMenuCommand( MenuRef inMenu, MenuCommand inCommandID){}; OSStatus CreateStandardWindowMenu( OptionBits inOptions, MenuRef * outMenu){}; void DisableMenuCommand( MenuRef inMenu, MenuCommand inCommandID){}; OSStatus DisposeMenuBar(MenuBarHandle inMbar){}; OSStatus GetIndMenuItemWithCommandID( MenuRef inMenu, MenuCommand inCommandID, UInt32 inItemIndex, MenuRef * outMenu, /* can be NULL */ MenuItemIndex * outIndex){ NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; NSMenuItem *inputMenu = (NSMenuItem *) inMenu; OSType inputCommandID = inCommandID; }; ================================================ FILE: vm/src/from_squeak/iOS/plugins/MacMenubarPlugin/MacMenubarPlugin.h ================================================ #if __LP64__ typedef unsigned int UInt32; typedef signed int SInt32; #else typedef unsigned long UInt32; typedef signed long SInt32; #endif typedef void * MenuHandle; typedef unsigned char Boolean; typedef const unsigned char * ConstStr255Param; typedef int MenuCommand; typedef char * Ptr; typedef Ptr * Handle; typedef int MenuItemIndex; typedef short CharParameter; typedef unsigned char Style; typedef int MenuID; typedef short SInt16; typedef UInt32 TextEncoding; typedef unsigned char Str255[256]; typedef UInt32 FourCharCode; typedef FourCharCode ResType; typedef void* MenuBarHandle; typedef SInt16 OSErr; typedef SInt32 OSStatus; typedef short StyleParameter; typedef unsigned char UInt8; typedef unsigned char * StringPtr; typedef unsigned short UInt16; typedef UInt32 OptionBits; typedef void* MenuRef; Boolean ioCheckMenuHandle(MenuHandle menuHandle); #define TARGET_API_MAC_CARBON 1 #define kHICommandHide 'hide' MenuRef GetMenuHandle(MenuID menuID); void DisableMenuItem( MenuRef theMenu, MenuItemIndex item); void GetMenuItemText( MenuRef theMenu, MenuItemIndex item, Str255 itemString); OSErr SetMenuItemCommandID( MenuRef inMenu, MenuItemIndex inItem, MenuCommand inCommandID); void DisposeMenu(MenuRef theMenu); OSErr GetMenuItemFontID( MenuRef inMenu, MenuItemIndex inItem, SInt16 * outFontID); OSErr SetMenuItemHierarchicalID( MenuRef inMenu, MenuItemIndex inItem, MenuID inHierID); OSErr GetMenuItemCommandID( MenuRef inMenu, MenuItemIndex inItem, MenuCommand * outCommandID); void SetItemIcon( MenuRef theMenu, MenuItemIndex item, short iconIndex) ; void SetItemCmd( MenuRef theMenu, MenuItemIndex item, CharParameter cmdChar); MenuRef NewMenu( MenuID menuID, ConstStr255Param menuTitle); void SetItemMark( MenuRef theMenu, MenuItemIndex item, CharParameter markChar); extern Boolean IsMenuBarVisible(void); void DeleteMenu(MenuID menuID); void ShowMenuBar(void); OSStatus AppendMenuItemText( MenuRef menu, ConstStr255Param inString) ; OSErr SetMenuItemKeyGlyph( MenuRef inMenu, MenuItemIndex inItem, SInt16 inGlyph); void DeleteMenuItem( MenuRef theMenu, MenuItemIndex item) ; OSErr GetMenuItemKeyGlyph( MenuRef inMenu, MenuItemIndex inItem, SInt16 * outGlyph); void ClearMenuBar(void); void SetItemStyle( MenuRef theMenu, MenuItemIndex item, StyleParameter chStyle) ; void GetItemIcon( MenuRef theMenu, MenuItemIndex item, short * iconIndex); void MacEnableMenuItem( MenuRef theMenu, MenuItemIndex item); MenuBarHandle GetMenuBar(void); void GetItemMark( MenuRef theMenu, MenuItemIndex item, CharParameter * markChar); void HideMenuBar(void); void GetItemStyle( MenuRef theMenu, MenuItemIndex item, Style * chStyle); void EnableMenuItemIcon( MenuRef theMenu, MenuItemIndex item); void HiliteMenu(MenuID menuID); void InsertMenuItem( MenuRef theMenu, ConstStr255Param itemString, MenuItemIndex afterItem); void DisableMenuItemIcon( MenuRef theMenu, MenuItemIndex item); OSErr SetMenuItemModifiers( MenuRef inMenu, MenuItemIndex inItem, UInt8 inModifiers); void SetMenuItemText( MenuRef theMenu, MenuItemIndex item, ConstStr255Param itemString); OSErr SetMenuItemTextEncoding( MenuRef inMenu, MenuItemIndex inItem, TextEncoding inScriptID); OSStatus SetMenuTitle( MenuRef menu, ConstStr255Param title) ; void CheckMenuItem( MenuRef theMenu, MenuItemIndex item, Boolean checked); Boolean IsMenuItemIconEnabled( MenuRef menu, MenuItemIndex item); OSErr SetMenuItemFontID( MenuRef inMenu, MenuItemIndex inItem, SInt16 inFontID); void InsertIntlResMenu( MenuRef theMenu, ResType theType, MenuItemIndex afterItem, short scriptFilter); Boolean IsMenuItemEnabled( MenuRef menu, MenuItemIndex item); extern void DrawMenuBar(void); OSErr GetMenuItemModifiers( MenuRef inMenu, MenuItemIndex inItem, UInt8 * outModifiers); OSErr GetMenuItemHierarchicalID( MenuRef inMenu, MenuItemIndex inItem, MenuID * outHierID); StringPtr GetMenuTitle( MenuRef menu, Str255 title); void SetMenuBar(MenuBarHandle mbar); UInt16 CountMenuItems(MenuRef theMenu); void GetItemCmd( MenuRef theMenu, MenuItemIndex item, CharParameter * cmdChar); MenuID GetMenuID(MenuRef menu); void InsertMenu( MenuRef theMenu, MenuID beforeID) ; void InsertFontResMenu( MenuRef theMenu, MenuItemIndex afterItem, short scriptFilter); void AppendMenu( MenuRef menu, ConstStr255Param data); OSErr GetMenuItemTextEncoding( MenuRef inMenu, MenuItemIndex inItem, TextEncoding * outScriptID); void InvalMenuBar(void); void EnableMenuCommand( MenuRef inMenu, MenuCommand inCommandID); OSStatus CreateStandardWindowMenu( OptionBits inOptions, MenuRef * outMenu); void DisableMenuCommand( MenuRef inMenu, MenuCommand inCommandID); OSStatus DisposeMenuBar(MenuBarHandle inMbar); OSStatus GetIndMenuItemWithCommandID( MenuRef inMenu, MenuCommand inCommandID, UInt32 inItemIndex, MenuRef * outMenu, /* can be NULL */ MenuItemIndex * outIndex); ================================================ FILE: vm/src/from_squeak/iOS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:15 pm'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer ' classVariableNames: 'Registry ' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer ' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 18:12'! buffer ^buffer! ! !MPEGFile methodsFor: 'access' stamp: 'JMM 1/20/2006 23:15'! isBufferBased ^(buffer == nil) not ! ! !MPEGFile methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:11'! openBuffer: aByteArray pathToFile := nil. buffer _ aByteArray. fileBits := self primFileOpenABuffer: aByteArray size: aByteArray size. fileBits notNil ifTrue: [fileIndex := Smalltalk registerExternalObject: fileBits. self register.] ! ! !MPEGFile methodsFor: 'primitives' stamp: 'JMM 1/20/2006 17:52'! primFileOpenABuffer: buffer size: aSize "Open the file" <primitive: 'primitiveMPEG3OpenABuffer' module: 'Mpeg3Plugin'> self primitiveFailed! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:18'! openBuffer: aBuffer ^self new openBuffer: aBuffer! ! !MPEGFile class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 23:05'! openFileUseBuffer: aPath | bar bytes | bar _ StandardFileStream oldFileNamed: aPath. bar binary. bytes _ bar contents. ^self new openBuffer: bytes! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:10'! external [external hasVideo] on: Error do: [self isBuffer ifTrue: [external := MPEGFile openBuffer: external buffer] ifFalse: [(MPEGFile isFileValidMPEG: external fileName) ifFalse: [^self error: 'Mpeg File is invalid']. external := MPEGFile openFile: external fileName]]. ^external! ! !MPEGPlayer methodsFor: 'access' stamp: 'JMM 1/20/2006 18:05'! isBuffer ^isBuffer == true! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:17'! initializeWithBuffer: aBuffer form: aForm isBuffer := true. buffer := aBuffer. self initialize: aBuffer. self form: aForm. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:07'! initializeWithBuffer: aBuffer morph: aMorphic isBuffer _ true. buffer _ aBuffer. self initialize: aBuffer. self morph: aMorphic. ^self! ! !MPEGPlayer methodsFor: 'initialize-release' stamp: 'JMM 1/20/2006 18:54'! initialize: aPath self halt. self isBuffer ifTrue: [external := MPEGFile openBuffer: buffer] ifFalse: [(MPEGFile isFileValidMPEG: aPath) ifFalse: [^nil]. external := MPEGFile openFile: aPath.]. self playerProcessPriority: Processor userSchedulingPriority. self lastDelay: 10. volume := 1.0. errorForSoundStart := 500. semaphoreForSound := Semaphore new. self startTime: (Array new: self totalVideoStreams). self clockBias: (Array new: self totalVideoStreams withAll: 0).! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:16'! playBuffer: aBuffer onForm: aForm ^self new initializeWithBuffer: aBuffer morph: aForm! ! !MPEGPlayer class methodsFor: 'instance creation' stamp: 'JMM 1/20/2006 18:06'! playBuffer: aBuffer onMorph: aMorph ^self new initializeWithBuffer: aBuffer morph: aMorph! ! Object subclass: #MPEGPlayer instanceVariableNames: 'external form startTime clockBias frameRate lastDelay noSound sampleRate audioPlayerProcess videoPlayerProcess playerProcessPriority soundQueue timeCheck semaphoreForSound errorForSoundStart morph volume buffer isBuffer' classVariableNames: '' poolDictionaries: '' category: 'Movies-Kernel'! Object subclass: #MPEGFile instanceVariableNames: 'pathToFile fileBits fileIndex endianness buffer' classVariableNames: 'Registry' poolDictionaries: '' category: 'Movies-Kernel'! ================================================ FILE: vm/src/from_squeak/iOS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegBufferTest.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:22 pm'! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! isThereAFile mpegFile isBufferBased ifTrue: [^true]. ^(FileStream isAFileNamed: mpegFile fileName)! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:15'! moviePosition "Answer a number between 0.0 and 1.0 indicating the current position within the movie." mpegFile ifNil: [^ 0.0]. mpegFile fileHandle ifNil: [^ 0.0]. self isThereAFile ifFalse: [^0.0]. mpegFile hasVideo ifTrue: [^ ((mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0)) min: 1.0]. soundTrack ifNotNil: [^ soundTrack soundPosition]. ^ 0.0 ! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalFrames "Answer the total number of frames in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ mpegFile videoFrames: 0! ! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'JMM 1/20/2006 23:16'! totalSeconds "Answer the total number of seconds in this movie." mpegFile ifNil: [^ 0]. mpegFile fileHandle ifNil: [^ 0]. self isThereAFile ifFalse: [^ 0]. mpegFile hasVideo ifFalse: [^ 0]. ^ self totalFrames asFloat / (mpegFile videoFrameRate: 0)! ! !MPEGDisplayMorph methodsFor: 'commands' stamp: 'JMM 1/20/2006 23:09'! startPlaying "Start playing the movie at the current position." | frameIndex | self stopPlaying. stopFrame := nil. self mpegFileIsOpen ifFalse: [^ self]. (mpegFile fileName notNil) ifTrue: [(FileStream isAFileNamed: mpegFile fileName) ifFalse: [ | newFileResult newFileName | self inform: 'Path changed. Enter new one for: ', (FileDirectory localNameFor: mpegFile fileName). newFileResult := StandardFileMenu oldFile. newFileName := newFileResult directory fullNameFor: newFileResult name. mpegFile openFile: newFileName]]. mpegFile hasAudio ifTrue: [mpegFile hasVideo ifTrue: ["set movie frame position from soundTrack position" soundTrack reset. "ensure file is open before positioning" soundTrack soundPosition: (mpegFile videoGetFrame: 0) asFloat / (mpegFile videoFrames: 0). "now set frame index from the soundtrack position for best sync" frameIndex := ((soundTrack millisecondsSinceStart * desiredFrameRate) // 1000). frameIndex := (frameIndex max: 0) min: ((mpegFile videoFrames: 0) - 3). mpegFile videoSetFrame: frameIndex stream: 0]. SoundPlayer stopReverb. soundTrack volume: volume. soundTrack repeat: repeat. soundTrack resumePlaying. startFrame := startMSecs := 0] ifFalse: [soundTrack := nil. startFrame := mpegFile videoGetFrame: 0. startMSecs := Time millisecondClockValue]. running := true! ! !MPEGDisplayMorph methodsFor: 'file open/close' stamp: 'JMM 1/20/2006 23:02'! openFileNamed: mpegFileName "Try to open the MPEG file with the given name. Answer true if successful." | e | self closeFile. (FileDirectory default fileExists: mpegFileName) ifFalse: [self inform: ('File not found: {1}' translated format: {mpegFileName}). ^ false]. (MPEGFile isFileValidMPEG: mpegFileName) ifTrue: [mpegFile := MPEGFile openFileUseBuffer: mpegFileName] ifFalse: [ (JPEGMovieFile isJPEGMovieFile: mpegFileName) ifTrue: [mpegFile := JPEGMovieFile new openFileNamed: mpegFileName] ifFalse: [self inform: ('Not an MPEG or JPEG movie file: {1}' translated format: {mpegFileName}). ^ false]]. mpegFile fileHandle ifNil: [^ false]. "initialize soundTrack" mpegFile hasAudio ifTrue: [soundTrack := mpegFile audioPlayerForChannel: 1] ifFalse: [soundTrack := nil]. mpegFile hasVideo ifTrue: [ "set screen size and display first frame" desiredFrameRate := mpegFile videoFrameRate: 0. soundTrack ifNotNil: [ "compute frame rate from length of audio track" desiredFrameRate := (mpegFile videoFrames: 0) / soundTrack duration]. e := (mpegFile videoFrameWidth: 0)@(mpegFile videoFrameHeight: 0). frameBuffer := Form extent: e depth: (Display depth max: 16). super extent: e. self nextFrame] ifFalse: [ "hide screen for audio-only files" super extent: 250@0]. ! ! ================================================ FILE: vm/src/from_squeak/iOS/plugins/Mpeg3Plugin/changesetsForInMemoryBuffer/JMMMpegPluginBuffer.1.cs ================================================ 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 20 January 2006 at 11:22:10 pm'! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:07'! primitiveMPEG3CheckSig: path | result sz storage | "int mpeg3_check_sig(char *path)" self var: #storage declareC: 'char storage[1024] '. self primitive: 'primitiveMPEG3CheckSig' parameters: #(String). sz _ interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. self cCode: 'result = mpeg3_check_sig(storage)'. ^result asOop: Boolean ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 18:38'! primitiveMPEG3OpenABuffer: path size: size | mpeg3Oop index | self var: #index declareC: 'mpeg3_t ** index'. self primitive: 'primitiveMPEG3OpenABuffer' parameters: #(String SmallInteger). mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(path,size); makeFileEntry(*index)'. ^mpeg3Oop. ! ! !Mpeg3Plugin methodsFor: 'primitives' stamp: 'JMM 1/20/2006 19:11'! primitiveMPEG3Open: path | mpeg3Oop index sz storage | "mpeg3_t* mpeg3_open(char *path)" self var: #index declareC: 'mpeg3_t ** index'. self var: #storage declareC: 'char storage[1024]'. self primitive: 'primitiveMPEG3Open' parameters: #(String). sz := interpreterProxy byteSizeOf: path cPtrAsOop. self cCode: 'sqFilenameFromStringOpen(storage, path, sz)'. mpeg3Oop := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. index := self cCoerce: (interpreterProxy firstIndexableField: mpeg3Oop) to: 'mpeg3_t **'. self cCode: '*index = mpeg3_open(storage,0); makeFileEntry(*index)'. ^mpeg3Oop. ! ! ================================================ FILE: vm/src/from_squeak/iOS/plugins/Mpeg3Plugin/sqMacFileBits.c ================================================ /* * sqMacFileBits.c * mpeglibAudioVideo * * Created by John M McIntosh on 15/02/06. * Copyright 2006 __MyCompanyName__. All rights reserved. * */ #include "sqMacFileBits.h" ================================================ FILE: vm/src/from_squeak/iOS/plugins/Mpeg3Plugin/sqMacFileBits.h ================================================ /* * macFileNameBits.c * FT2Plugin support * * Created by John M McIntosh on 21/11/05. * Feb 15th, 2006, use sqFilenameFromString * */ #include "sqVirtualMachine.h" extern struct VirtualMachine * interpreterProxy; void sqFilenameFromStringOpen(char *buffer,long fileIndex, long fileLength, int flag) { interpreterProxy->ioFilenamefromStringofLengthresolveAliases(buffer,fileIndex, fileLength, flag); } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SecurityPlugin/sqMacSecurity.c ================================================ // John M McIntosh on 5/15/08. // Copyright Corporate Smalltalk Consulting Ltd 2000-2008. All rights reserved. /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // //JMM 2/13/01 create docs folder if non-existant //JMM 4/4/01 look for documents/My Squeak folder versus just documents as secure location //JMM 5/3/01 path was wrong for unsecure folder which uncovered a bug in lookupPath //JMM 8/15/01 only allow call to ioInitSecurity Once, also return proper return code //JMM 9/5/01 make it as a plugin // 3.7.0bx Nov 24th, 2003 JMM gCurrentVMEncoding //May 16th, 2008. IPhone #include "sq.h" #include "SecurityPlugin.h" #include "FilePlugin.h" #include <limits.h> typedef unsigned char Boolean; #define DELIMITERInt '/' extern struct VirtualMachine * interpreterProxy; #define fromSqueak(string,length) string void fixPath(char *path); sqInt dir_CreateSecurity(char *pathString, sqInt pathStringLength); sqInt _ioSetFileAccess(sqInt enable); static char secureUserDirectory[PATH_MAX]; static char untrustedUserDirectory[PATH_MAX]; static Boolean gInitialized = false; /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* file security */ static sqInt allowFileAccess = 1; /* full access to files */ static sqInt isAccessiblePathName(char *pathName) { sqInt i; /* Check if the path/file name is subdirectory of the image path */ for(i=0; i<strlen(untrustedUserDirectory)-1; i++) if(untrustedUserDirectory[i] != pathName[i]) return 0; /* special check for the trusted directory */ if(pathName[i] == 0) return 1; /* allow access to trusted directory */ /* check last character in image path (e.g., backslash) */ if(untrustedUserDirectory[i] != pathName[i]) return 0; return 1; } static sqInt isAccessibleFileName(char *fileName) { sqInt i; /* Check if the path/file name is subdirectory of the image path */ for(i=0; i<strlen(untrustedUserDirectory); i++) if(untrustedUserDirectory[i] != fileName[i]) return 0; return 1; } /* directory access */ sqInt ioCanCreatePathOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathStringLength) if(allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanListPathOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathStringLength) if(allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanDeletePathOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathStringLength) if(allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } /* file access */ sqInt ioCanOpenFileOfSizeWritable(char* pathString, sqInt pathStringLength, sqInt writeFlag) { #pragma unused(pathStringLength,writeFlag) if(allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanOpenAsyncFileOfSizeWritable(char* pathString, sqInt pathStringLength, sqInt writeFlag) { return ioCanOpenFileOfSizeWritable(pathString,pathStringLength,writeFlag); } sqInt ioCanDeleteFileOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathStringLength) if(allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanRenameFileOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathStringLength) if(allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanGetFileTypeOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathString,pathStringLength) return 1; /* of no importance here */ } sqInt ioCanSetFileTypeOfSize(char* pathString, sqInt pathStringLength) { #pragma unused(pathString,pathStringLength) return 1; /* of no importance here */ } /* disabling/querying */ sqInt ioDisableFileAccess(void) { allowFileAccess = 0; return 0; } sqInt ioHasFileAccess(void) { return allowFileAccess; } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* image security */ static sqInt allowImageWrite = 1; /* allow writing the image */ sqInt ioCanRenameImage(void) { return allowImageWrite; /* only when we're allowed to save the image */ } sqInt ioCanWriteImage() { return allowImageWrite; } sqInt ioDisableImageWrite() { allowImageWrite = 0; return 0; } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* socket security - for now it's all or nothing */ static sqInt allowSocketAccess = 1; /* allow access to sockets */ sqInt ioCanCreateSocketOfType(sqInt netType, sqInt socketType) { #pragma unused(netType,socketType) return allowSocketAccess; } sqInt ioCanConnectToPort(sqInt netAddr, sqInt port) { #pragma unused(netAddr,port) return allowSocketAccess; } sqInt ioCanListenOnPort(sqInt s, sqInt port) { #pragma unused(s,port) return allowSocketAccess; } sqInt ioDisableSocketAccess() { allowSocketAccess = 0; return 0; } sqInt ioHasSocketAccess() { return allowSocketAccess; } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* SecurityPlugin primitive support */ char *ioGetSecureUserDirectory(void) { return secureUserDirectory; } char *ioGetUntrustedUserDirectory(void) { return untrustedUserDirectory; } /* note: following is called from VM directly, not from plugin */ sqInt ioInitSecurity(void) { extern char gSqueakUntrustedDirectoryName[],gSqueakTrustedDirectoryName[]; if (gInitialized) return 1; gInitialized = true; secureUserDirectory[0] = 0x00; strlcpy(secureUserDirectory, gSqueakTrustedDirectoryName,PATH_MAX); untrustedUserDirectory[0] = 0x00; strlcpy(untrustedUserDirectory, gSqueakUntrustedDirectoryName,PATH_MAX); return 1; } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* private entries for restoring rights */ sqInt _ioSetImageWrite(sqInt enable); sqInt _ioSetImageWrite(sqInt enable) { if(enable == allowImageWrite) return 1; allowImageWrite = enable; return 1; } sqInt _ioSetFileAccess(sqInt enable); sqInt _ioSetFileAccess(sqInt enable) { if(enable == allowFileAccess) return 1; allowFileAccess = enable; return 1; } sqInt _ioSetSocketAccess(sqInt enable); sqInt _ioSetSocketAccess(sqInt enable) { if(enable == allowSocketAccess) return 1; allowSocketAccess = enable; return 1; } void fixPath(char *path) { long i; for(i=strlen(path);i>0;i--) if(path[i-1]==DELIMITERInt) { path[i-1]=0x00; return; } } sqInt dir_CreateSecurity(char *pathString, sqInt pathStringLength) { /* Create a new directory with the given path. By default, this directory is created in the current directory. Use a full path name such as "MyDisk:Working:New Folder" to create folders elsewhere. */ //JMM tests create file in Vm directory, other place, other volume return (sqInt) dir_Create(pathString, pathStringLength); } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SerialPlugin/sqMacSerialPort.c ================================================ /**************************************************************************** * PROJECT: Squeak Headers * FILE: sqMacSerialPort.c * CONTENT: * * AUTHOR: John Maloney, John McIntosh, and others. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: $Id: sqMacSerialPort.c 1708 2007-06-10 00:40:04Z johnmci $ * * NOTES: * Feb 22nd, 2002, JMM enable 16 ports for serial, versus four, which was capped at 2? ****************************************************************************/ #include "sq.h" #include "SerialPlugin.h" #include <Carbon/Carbon.h> extern struct VirtualMachine *interpreterProxy; /*** Constants ***/ #define INPUT_BUF_SIZE 1000 /*** Serial Ports ***/ #define MAX_PORTS 16 static short outRefNum[MAX_PORTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /*** Private Functions ***/ int setHandshakeOptions(int portNum, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); int serialPortSetControl(int portNum,int control, char *data); int serialPortIsOpen(int portNum); int serialPortNames(int portNum, char *portName, char *inName, char *outName); /* initialize/shutdown */ int serialPortInit() { return true; } int serialPortShutdown() { int i; for(i=0;i<MAX_PORTS;i++) { if (serialPortIsOpen(i)) serialPortClose(i); } return 1; } EXPORT (int) serialPortCount(void) { /* Return the number of serial ports available on this machine */ return false; } int serialPortIsOpen(int portNum) { if ((portNum < 0) || (portNum >= MAX_PORTS)) return false; return outRefNum[portNum] != 0; } int serialPortSetControl(int portNum,int control, char *data) { #pragma unused(portNum,control,data) return -1; } int serialPortNames(int portNum, char *portName, char *inName, char *outName) { /* Fill in the user name and input and output port names for the given port number. Note that ports are numbered starting with zero. */ #pragma unused(portNum,portName,inName,outName) return false; } int setHandshakeOptions( int portNum, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar) { /* Set the given port's handshaking parameters. */ #pragma unused(portNum,inFlowCtrl,outFlowCtrl,xOnChar,xOffChar) return false; } /*** Serial Port Functions ***/ EXPORT (int) serialPortClose(int portNum) { #pragma unused(portNum) return false; } EXPORT (int) serialPortOpen( int portNum, int baudRate, int stopBitsType, int parityType, int dataBits, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar) { /* Open the given serial port using the given settings. The baud rate can be any number between about 224 and 57600; the driver will pick a clock divisor that will generate the closest available baud rate. */ #pragma unused(portNum,baudRate,stopBitsType,parityType,dataBits,inFlowCtrl,outFlowCtrl,xOnChar,xOffChar) return false; } EXPORT (int) serialPortReadInto(int portNum, int count, int bufferPtr) { /* Read up to count bytes from the given serial port into the given byte array. Read only up to the number of bytes in the port's input buffer; if fewer bytes than count have been received, do not wait for additional data to arrive. Return zero if no data is available. */ #pragma unused(portNum,count,bufferPtr) return false; } EXPORT (int) serialPortWriteFrom(int portNum, int count, int bufferPtr) { /* Write count bytes from the given byte array to the given serial port's output buffer. Return the number of bytes written. This implementation is synchronous: it doesn't return until the data has been sent. However, other implementations may return before transmission is complete. */ long int byteCount = count; int osErr; if (!serialPortIsOpen(portNum)) { return interpreterProxy->success(false); } osErr = FSWrite(outRefNum[portNum], &byteCount, (char *) bufferPtr); if (osErr != noErr) { return interpreterProxy->success(false); } return byteCount; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SoundPlugin/sqSqueakSoundCoreAudio.h ================================================ // // sqSqueakSoundCoreAudio.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 11/10/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "sq.h" #import "Queue.h" #import <AudioToolbox/AudioToolbox.h> static const int kNumberOfBuffers=4; @interface sqSqueakSoundCoreAudio : NSObject { AudioQueueRef inputAudioQueue; sqInt semaIndexForInput; UInt32 bufferSizeForInput; sqInt inputIsRunning; double inputSampleRate; sqInt inputChannels; AudioStreamBasicDescription *inputFormat; AudioQueueBufferRef *inputBuffers; AudioQueueRef outputAudioQueue; Queue* soundInQueue; sqInt semaIndexForOutput; UInt32 bufferSizeForOutput; BOOL outputIsRunning; AudioStreamBasicDescription *outputFormat; AudioQueueBufferRef *outputBuffers; Queue* soundOutQueue; } - (sqInt) soundInit; - (sqInt) soundShutdown; - (sqInt) snd_Start: (sqInt) frameCount samplesPerSec: (sqInt) samplesPerSec stereo: (sqInt) stereo semaIndex: (sqInt) semaIndex; - (sqInt) snd_Stop; - (void) snd_Stop_Force; - (sqInt) snd_StopAndDispose; - (sqInt) snd_PlaySilence; - (sqInt) snd_AvailableSpace; - (sqInt) snd_PlaySamplesFromAtLength: (sqInt) frameCount arrayIndex: (char *) arrayIndex startIndex: (usqInt) startIndex; - (sqInt) snd_InsertSamplesFromLeadTime: (sqInt) frameCount srcBufPtr: (char*) srcBufPtr samplesOfLeadTime: (sqInt) samplesOfLeadTime; - (sqInt) snd_StartRecording: (sqInt) desiredSamplesPerSec stereo: (sqInt) stereo semaIndex: (sqInt) semaIndex; - (sqInt) snd_RecordSamplesIntoAtLength: (char*) arrayIndex startSliceIndex: (usqInt) startSliceIndex bufferSizeInBytes: (usqInt) bufferSizeInBytes; - (sqInt) snd_StopRecording; - (double) snd_GetRecordingSampleRate; @property (nonatomic) AudioQueueRef outputAudioQueue; @property (nonatomic) AudioQueueRef inputAudioQueue; @property (nonatomic) sqInt semaIndexForOutput; @property (nonatomic) UInt32 bufferSizeForOutput; @property (nonatomic) sqInt semaIndexForInput; @property (nonatomic) UInt32 bufferSizeForInput; @property (nonatomic) sqInt inputChannels; @property (nonatomic) sqInt inputIsRunning; @property (nonatomic) BOOL outputIsRunning; @property (nonatomic) double inputSampleRate; @property (nonatomic) AudioStreamBasicDescription* outputFormat; @property (nonatomic) AudioStreamBasicDescription* inputFormat; @property (nonatomic) AudioQueueBufferRef * outputBuffers; @property (nonatomic) AudioQueueBufferRef * inputBuffers; @property (nonatomic,retain) Queue* soundOutQueue; @property (nonatomic,retain) Queue* soundInQueue; @end @interface soundAtom : NSObject { char *data; usqInt byteCount; usqInt startOffset; } - (id) initWith: (char*) buffer count: (usqInt) bytes; @property (nonatomic,assign) char * data; @property (nonatomic,assign) usqInt byteCount; @property (nonatomic,assign) usqInt startOffset; @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SoundPlugin/sqSqueakSoundCoreAudio.m ================================================ // // sqSqueakSoundCoreAudio.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 11/10/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "sqSqueakSoundCoreAudio.h" #define SqueakFrameSize 4 // guaranteed (see class SoundPlayer) extern struct VirtualMachine* interpreterProxy; void MyAudioQueueOutputCallback (void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer); void MyAudioQueueOutputCallback (void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { sqSqueakSoundCoreAudio * myInstance = ( sqSqueakSoundCoreAudio *)inUserData; soundAtom *atom = [myInstance.soundOutQueue returnOldest]; if (!atom) { inBuffer->mAudioDataByteSize = MIN(inBuffer->mAudioDataBytesCapacity,2644); memset(inBuffer->mAudioData,0,inBuffer->mAudioDataByteSize); //NSLog(@"%i Fill sound buffer with zero %i bytes",ioMSecs(),inBuffer->mAudioDataByteSize); } else { if (inBuffer->mAudioDataBytesCapacity >= atom.byteCount) { atom = [myInstance.soundOutQueue returnAndRemoveOldest]; inBuffer->mAudioDataByteSize = (int) atom.byteCount; memcpy(inBuffer->mAudioData,atom.data,atom.byteCount); [atom release]; //NSLog(@"%i Fill sound buffer with %i bytesA",ioMSecs(),inBuffer->mAudioDataByteSize); } else { inBuffer->mAudioDataByteSize = (int) MIN(atom.byteCount - atom.startOffset,inBuffer->mAudioDataBytesCapacity); memcpy(inBuffer->mAudioData,atom.data+atom.startOffset,inBuffer->mAudioDataByteSize); atom.startOffset = atom.startOffset + inBuffer->mAudioDataByteSize; if (atom.startOffset == atom.byteCount) { atom = [myInstance.soundOutQueue returnAndRemoveOldest]; //ignore now it's empty [atom release]; } //NSLog(@"%i Fill sound buffer with %i bytesB",ioMSecs(),inBuffer->mAudioDataByteSize); } } AudioQueueEnqueueBuffer(inAQ,inBuffer,0,nil); interpreterProxy->signalSemaphoreWithIndex(myInstance.semaIndexForOutput); } void MyAudioQueuePropertyListenerProc ( void * inUserData, AudioQueueRef inAQ, AudioQueuePropertyID inID); void MyAudioQueuePropertyListenerProc ( void * inUserData, AudioQueueRef inAQ, AudioQueuePropertyID inID) { sqInt isRunning; UInt32 size = sizeof(isRunning); sqSqueakSoundCoreAudio * myInstance = ( sqSqueakSoundCoreAudio *)inUserData; AudioQueueGetProperty (inAQ, kAudioQueueProperty_IsRunning, &isRunning, &size); myInstance.outputIsRunning = isRunning; //NSLog(@"%i Is Running %i",ioMSecs(),isRunning); } void MyAudioQueueInputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs); void MyAudioQueueInputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) { sqSqueakSoundCoreAudio * myInstance = ( sqSqueakSoundCoreAudio *)inUserData; if (!myInstance.inputIsRunning) return; if (inNumberPacketDescriptions > 0) { soundAtom *atom = [[soundAtom alloc] initWith: inBuffer->mAudioData count: inBuffer->mAudioDataByteSize]; [myInstance.soundInQueue addItem: atom]; [atom release]; } AudioQueueEnqueueBuffer (inAQ, inBuffer, 0, NULL ); interpreterProxy->signalSemaphoreWithIndex(myInstance.semaIndexForInput); } @implementation soundAtom @synthesize data; @synthesize byteCount; @synthesize startOffset; - initWith: (char*) buffer count: (usqInt) bytes { data = malloc(bytes); memcpy(data,buffer,bytes); byteCount = bytes; startOffset = 0; return self; } - (void)dealloc { if (data) free(data); data = 0; byteCount = 0; startOffset = 0; [super dealloc]; } @end @implementation sqSqueakSoundCoreAudio @synthesize outputAudioQueue; @synthesize inputAudioQueue; @synthesize semaIndexForOutput; @synthesize bufferSizeForOutput; @synthesize semaIndexForInput; @synthesize bufferSizeForInput; @synthesize inputSampleRate; @synthesize outputFormat; @synthesize inputFormat; @synthesize outputIsRunning; @synthesize inputIsRunning; @synthesize soundOutQueue; @synthesize soundInQueue; @synthesize outputBuffers; @synthesize inputBuffers; @synthesize inputChannels; - (sqInt) soundInit { //NSLog(@"%i sound init",ioMSecs()); self.outputAudioQueue = nil; self.inputAudioQueue = nil; self.semaIndexForOutput = 0; self.semaIndexForInput = 0; self.outputFormat = calloc(1,sizeof(AudioStreamBasicDescription)); self.inputFormat = calloc(1,sizeof(AudioStreamBasicDescription)); self.outputBuffers = calloc((unsigned)kNumberOfBuffers,sizeof(AudioQueueBufferRef)); self.inputBuffers = calloc((unsigned) kNumberOfBuffers,sizeof(AudioQueueBufferRef)); soundOutQueue = [Queue new]; soundInQueue = [Queue new]; return 1; } - (sqInt) soundShutdown { //NSLog(@"%i sound shutdown",ioMSecs()); if (self.outputAudioQueue) { [self snd_StopAndDispose]; } if (self.inputAudioQueue) { [self snd_StopRecording]; } return 1; } - (sqInt) snd_Start: (sqInt) frameCount samplesPerSec: (sqInt) samplesPerSec stereo: (sqInt) stereo semaIndex: (sqInt) semaIndex { //NSLog(@"%i sound start playing frame count %i samples %i",ioMSecs(),frameCount,samplesPerSec); OSStatus result; int nChannels= 1 + (int)stereo; if (frameCount <= 0 || samplesPerSec <= 0 || stereo < 0 || stereo > 1) return interpreterProxy->primitiveFail(); self.semaIndexForOutput = semaIndex; AudioStreamBasicDescription check; bzero(&check,sizeof(AudioStreamBasicDescription)); check.mSampleRate = (Float64)samplesPerSec; check.mFormatID = kAudioFormatLinearPCM; check.mFormatFlags = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsSignedInteger; check.mBytesPerPacket = SqueakFrameSize / (3 - nChannels); check.mFramesPerPacket = 1; check.mBytesPerFrame = SqueakFrameSize / (3 - nChannels); check.mChannelsPerFrame = nChannels; check.mBitsPerChannel = 16; /* we want to create a new audio queue only if we have to */ if (self.outputAudioQueue == nil || (memcmp(&check,self.outputFormat,sizeof(AudioStreamBasicDescription) != 0))) { AudioQueueRef newQueue; //NSLog(@"%i create new audioqueue",ioMSecs()); if (self.outputAudioQueue) [self snd_StopAndDispose]; *self.outputFormat = check; result = AudioQueueNewOutput (self.outputFormat, &MyAudioQueueOutputCallback, (void*) self, NULL, NULL, 0, &newQueue); if (result) return interpreterProxy->primitiveFail(); self.outputAudioQueue = newQueue; AudioQueueAddPropertyListener (self.outputAudioQueue, kAudioQueueProperty_IsRunning, MyAudioQueuePropertyListenerProc, self); self.bufferSizeForOutput = (unsigned) (SqueakFrameSize * nChannels * frameCount * 2); int i; for (i = 0; i < kNumberOfBuffers; ++i) { result = AudioQueueAllocateBuffer(self.outputAudioQueue, self.bufferSizeForOutput/16, &self.outputBuffers[i]); if(result) return interpreterProxy->primitiveFail(); } } else { //NSLog(@"%i reuse audioqueue",ioMSecs()); } return 1; } - (sqInt) snd_Stop { if (!self.outputIsRunning) return 1; //NSLog(@"%i sound stop",ioMSecs()); self.outputIsRunning = NO; if (!self.outputAudioQueue) return 0; OSStatus result = AudioQueueStop (self.outputAudioQueue,true); //This implicitly invokes AudioQueueReset if (result) return 0; return 1; } - (void) snd_Stop_Force { if (!self.outputAudioQueue) return; //NSLog(@"%i sound stop force",ioMSecs()); OSStatus result = AudioQueueStop (self.outputAudioQueue,true); //This implicitly invokes AudioQueueReset #pragma unused(result) } - (sqInt) snd_StopAndDispose { //NSLog(@"%i sound stopAndDispose",ioMSecs()); if (!self.outputAudioQueue) return 0; [self snd_Stop]; OSStatus result = AudioQueueDispose (self.outputAudioQueue,true); #pragma unused(result) self.outputAudioQueue = nil; self.soundOutQueue = [Queue new]; return 1; } - (sqInt) snd_PlaySilence { //NSLog(@"%i sound play silence",ioMSecs()); interpreterProxy->success(false); return 8192; } - (sqInt) snd_AvailableSpace { if (!self.outputAudioQueue) return interpreterProxy->primitiveFail(); if ([self.soundOutQueue pendingElements] > 2) return 0; return self.bufferSizeForOutput; } - (sqInt) snd_PlaySamplesFromAtLength: (sqInt) frameCount arrayIndex: (char *) arrayIndex startIndex: (usqInt) startIndex { OSStatus result; usqInt byteCount= frameCount * SqueakFrameSize; if (!self.outputAudioQueue) return interpreterProxy->primitiveFail(); if (frameCount <= 0 || startIndex > byteCount) return interpreterProxy->primitiveFail(); //NSLog(@"%i sound place samples on queue frames %i startIndex %i count %i",ioMSecs(),frameCount,startIndex,byteCount-startIndex); soundAtom *atom = [[soundAtom alloc] initWith: arrayIndex+startIndex count: (unsigned) (byteCount-startIndex)]; [self.soundOutQueue addItem: atom]; [atom release]; if (!self.outputIsRunning) { int i; for (i = 0; i < kNumberOfBuffers; ++i) { MyAudioQueueOutputCallback (self,self.outputAudioQueue,self.outputBuffers[i]); } UInt32 outNumberOfFramesPrepared; AudioQueuePrime(self.outputAudioQueue,0,&outNumberOfFramesPrepared); result = AudioQueueStart (self.outputAudioQueue,NULL); //Force it as running self.outputIsRunning = YES; } return 1; } - (sqInt) snd_InsertSamplesFromLeadTime: (sqInt) frameCount srcBufPtr: (char*) srcBufPtr samplesOfLeadTime: (sqInt) samplesOfLeadTime { //NOT IMPLEMEMENTED return 0; } - (sqInt) snd_StartRecording: (sqInt) desiredSamplesPerSec stereo: (sqInt) stereo semaIndex: (sqInt) semaIndex { if (desiredSamplesPerSec <= 0 || stereo < 0 || stereo > 1) return interpreterProxy->primitiveFail(); if (self.inputAudioQueue) { [self snd_StopRecording]; } self.semaIndexForInput = semaIndex; self.inputSampleRate = (float) desiredSamplesPerSec; sqInt frameCount = 5288 * desiredSamplesPerSec / 44100; self.inputChannels = 1 + stereo; self.inputFormat->mSampleRate = (Float64)desiredSamplesPerSec; self.inputFormat->mFormatID = kAudioFormatLinearPCM; self.inputFormat->mFormatFlags = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked ; self.inputFormat->mBytesPerPacket = (int) SqueakFrameSize / (3 - (int)self.inputChannels); self.inputFormat->mFramesPerPacket = 1; self.inputFormat->mBytesPerFrame =(int) SqueakFrameSize / (3 - (int)self.inputChannels); self.inputFormat->mChannelsPerFrame =(int) self.inputChannels; self.inputFormat->mBitsPerChannel = 16; self.bufferSizeForInput = (unsigned) (SqueakFrameSize * self.inputChannels * frameCount * 2/4); //Currently squeak does this thing where it stops yet leaves data in queue, this causes us to lose dota if the buffer is too big AudioQueueRef newQueue; OSStatus result = AudioQueueNewInput (self.inputFormat, &MyAudioQueueInputCallback, (void*) self, NULL, NULL, 0, &newQueue); if (result) return interpreterProxy->primitiveFail(); self.inputAudioQueue = newQueue; int i; for (i = 0; i < kNumberOfBuffers; ++i) { result = AudioQueueAllocateBuffer(self.inputAudioQueue, self.bufferSizeForInput, &self.inputBuffers[i]); if(result) return interpreterProxy->primitiveFail(); result = AudioQueueEnqueueBuffer(self.inputAudioQueue,self.inputBuffers[i],0,NULL); if(result) return interpreterProxy->primitiveFail(); } inputIsRunning = 1; result = AudioQueueStart (self.inputAudioQueue,NULL); if(result) return interpreterProxy->primitiveFail(); return 1; } - (sqInt) snd_StopRecording { if (!self.inputAudioQueue) return 0; self.inputIsRunning = 0; OSStatus result = AudioQueueStop (self.inputAudioQueue,true); //This implicitly invokes AudioQueueReset if (result) return 0; result = AudioQueueDispose (self.inputAudioQueue,true); self.inputAudioQueue = nil; self.soundInQueue = [Queue new]; return 1; } - (double) snd_GetRecordingSampleRate { if (!self.inputAudioQueue) return interpreterProxy->primitiveFail(); return inputSampleRate; } - (sqInt) snd_RecordSamplesIntoAtLength: (char*) arrayIndex startSliceIndex: (usqInt) startSliceIndex bufferSizeInBytes: (usqInt) bufferSizeInBytes { usqInt count; if (!self.inputAudioQueue) return interpreterProxy->primitiveFail(); if (startSliceIndex > bufferSizeInBytes) return interpreterProxy->primitiveFail(); usqInt start= startSliceIndex * SqueakFrameSize / 2; soundAtom *atom = [self.soundInQueue returnOldest]; if (atom == nil) return 0; if (bufferSizeInBytes-start >= atom.byteCount && atom.startOffset == 0) { atom = [self.soundInQueue returnAndRemoveOldest]; memcpy(arrayIndex+start,atom.data,atom.byteCount); count= MIN(atom.byteCount, bufferSizeInBytes - start); [atom release]; return count / (SqueakFrameSize / 2) / self.inputChannels; } else { count= MIN(atom.byteCount-atom.startOffset, bufferSizeInBytes - start); memcpy(arrayIndex+start,atom.data+atom.startOffset,count); atom.startOffset = atom.startOffset + (count); if (atom.startOffset == atom.byteCount) { atom = [self.soundInQueue returnAndRemoveOldest]; //ignore now it's empty [atom release]; } return count / (SqueakFrameSize / 2) / self.inputChannels; } } @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.h ================================================ /* * sqSqueakSoundCoreAudioAPI.h * SqueakNoOGLIPhone * Created by John M McIntosh on 11/10/08. Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #include "sq.h" #include "SoundPlugin.h" ================================================ FILE: vm/src/from_squeak/iOS/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.m ================================================ /* * sqSqueakSoundCoreAudioAPI.c * SqueakNoOGLIPhone * Created by John M McIntosh on 11/10/08. Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakSoundCoreAudioAPI.h" #import "sqSqueakAppDelegate.h" extern sqSqueakAppDelegate *gDelegateApp; sqInt soundInit(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic soundInit]; } sqInt soundShutdown(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic soundShutdown]; } /* sound output */ sqInt snd_AvailableSpace(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_AvailableSpace]; } sqInt snd_InsertSamplesFromLeadTime(sqInt frameCount, void * srcBufPtr, sqInt samplesOfLeadTime){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_InsertSamplesFromLeadTime: frameCount srcBufPtr: (char *)srcBufPtr samplesOfLeadTime: samplesOfLeadTime]; } sqInt snd_PlaySamplesFromAtLength(sqInt frameCount, void * arrayIndex, sqInt startIndex){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_PlaySamplesFromAtLength: frameCount arrayIndex: (char*) arrayIndex startIndex: (usqInt) startIndex]; } sqInt snd_PlaySilence(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_PlaySilence]; } sqInt snd_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_Start: frameCount samplesPerSec: samplesPerSec stereo: stereo semaIndex: semaIndex]; } sqInt snd_Stop(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_Stop]; } /* sound input */ sqInt snd_SetRecordLevel(sqInt level) { return 0; } sqInt snd_StartRecording(sqInt desiredSamplesPerSec, sqInt stereo, sqInt semaIndex){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_StartRecording:desiredSamplesPerSec stereo: stereo semaIndex: semaIndex ]; } sqInt snd_StopRecording(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_StopRecording]; } double snd_GetRecordingSampleRate(void){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_GetRecordingSampleRate]; } sqInt snd_RecordSamplesIntoAtLength(void * buf, sqInt startSliceIndex, sqInt bufferSizeInBytes){ return [gDelegateApp.squeakApplication.soundInterfaceLogic snd_RecordSamplesIntoAtLength:(char *) buf startSliceIndex: (usqInt) startSliceIndex bufferSizeInBytes: (usqInt) bufferSizeInBytes]; } void snd_Volume(double *left, double *right){} void snd_SetVolume(double left, double right){} ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakFFIPrims/dummyFFI.c ================================================ // // SqueakNoOGLIPhoneAppDelegate.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/15/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "dummyFFI.h" #include "sqFFI.h" int ffiPushSignedByte(int value) { return 1; } int ffiPushUnsignedByte(int value) { return 1; } int ffiPushSignedShort(int value) { return 1; } int ffiPushUnsignedShort(int value) { return 1; } int ffiPushSignedInt(int value) { return 1; } int ffiPushUnsignedInt(int value) { return 1; } # define primitiveFail() 0 int ffiPushSignedLongLong(int low, int high) { return primitiveFail(); } int ffiPushUnsignedLongLong(int low, int high) { return primitiveFail(); } int ffiPushSignedChar(int value) { return 1; } int ffiPushUnsignedChar(int value) { return 1; } int ffiPushBool(int value) { return 1; } int ffiPushSingleFloat(double value) { return 1; } int ffiPushDoubleFloat(double value) { return 1; } /* ffiReturnFloatValue: Return the value from a previous ffi call with float return type. */ double ffiReturnFloatValue(void) { return 0; } /* ffiLongLongResultLow: Return the low 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultLow(void) { return 0; } /* ffiLongLongResultHigh: Return the high 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultHigh(void) { return 0; } /* ffiStoreStructure: Store the structure result of a previous ffi call into the given address*/ int ffiStoreStructure(int address, int structSize) { return 1; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return 0; } int ffiPushStringOfLength(int srcIndex, int length) { return 0; } /* ffiAlloc: Allocate space from the external heap */ int ffiAlloc(int byteSize) { return 0; } /* ffiFree: Free space from the external heap */ int ffiFree(int pointer) { return 1; } int ffiInitialize(void) { return 1; } int ffiCallAddressOfWithStructReturn(int fn, int callType, int *structSpec, int specSize) { return 0; } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { return 0; } int ffiCanReturn(int *structSpec, int specSize) { return 0; } /* ffiCleanup: Cleanup after a foreign function call has completed. The generic support code only frees the temporarily allocated strings. */ int ffiCleanup(void) { return 0; } /* ffiSupportsCallingConvention: Return true if the support code supports the given calling convention */ int ffiSupportsCallingConvention(int callType) { return 0; } int ffiPushStructureOfLength(int pointer, int* structSpec, int structSize) { return 0; } int ffiPushPointer(int pointer) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakFFIPrims/dummyFFI.h ================================================ /* * dummyFFI.h * SqueakNoOGLIPhone * * Created by John M McIntosh on 10/24/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/Info-SqueakLocalePlugin__Upgraded_.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>LocalePlugin</string> <key>CFBundleGetInfoString</key> <string>LocalePlugin for Squeak, Cocoa based</string> <key>CFBundleIconFile</key> <string>SqueakPlugin.icns</string> <key>CFBundleIdentifier</key> <string>org.squeak.LocalePlugin</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>LocalePlugin</string> <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> <string>2.1b1</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>3</string> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/MAC.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>040F1CC512CD2220008BA0CB</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>94E7F9191237565E00A03A11</string> <string>66B8BC570381F53800A8011A</string> <string>94E7F8371237541300A03A11</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>23</integer> <integer>22</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 65}, {186, 445}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 463}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>334 210 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Cocoa.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Cocoa.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>040F1DB112CD26E4008BA0CB</string> <key>history</key> <array> <string>040F1CB812CD2220008BA0CB</string> <string>040F1CB912CD2220008BA0CB</string> <string>040F1CBA12CD2220008BA0CB</string> <string>040F1CBB12CD2220008BA0CB</string> <string>040F1CBC12CD2220008BA0CB</string> <string>040F1CBD12CD2220008BA0CB</string> <string>040F1CBE12CD2220008BA0CB</string> <string>040F1CBF12CD2220008BA0CB</string> <string>040F1CC012CD2220008BA0CB</string> <string>040F1DAF12CD26E4008BA0CB</string> <string>040F1DB012CD26E4008BA0CB</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {580, 269}}</string> <key>RubberWindowFrame</key> <string>334 210 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>269pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 274}, {580, 189}}</string> <key>RubberWindowFrame</key> <string>334 210 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>189pt</string> </dict> </array> <key>Proportion</key> <string>580pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>040F1DB312CD26E4008BA0CB</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>040F1DB412CD26E4008BA0CB</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>040F1CC612CD2220008BA0CB</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj</string> </array> <key>WindowString</key> <string>334 210 788 504 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {500, 218}}</string> <key>RubberWindowFrame</key> <string>355 191 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>218pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 223}, {500, 236}}</string> <key>RubberWindowFrame</key> <string>355 191 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>459pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>040F1CC612CD2220008BA0CB</string> <string>040F1DB512CD26E4008BA0CB</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>355 191 500 500 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>040F1CC612CD2220008BA0CB</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugger</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {317, 164}}</string> <string>{{317, 0}, {377, 164}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 164}}</string> <string>{{0, 164}, {694, 216}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 380}}</string> <key>RubberWindowFrame</key> <string>321 238 694 422 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C0AD2AB069F1E9B00FABCE6</string> <string>1C162984064C10D400B95A72</string> <string>1C0AD2AC069F1E9B00FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>321 238 694 422 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.find</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528D0623707200166675</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 167}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>50%</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{8, 0}, {773, 254}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>50%</string> </dict> </array> <key>Proportion</key> <string>428pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>1C530D58069F1CE1000CFCEE</string> <string>1C530D59069F1CE1000CFCEE</string> <string>1CDD528C0622207200134675</string> <string>1C530D5A069F1CE1000CFCEE</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>62 385 781 470 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {650, 250}}</string> <key>RubberWindowFrame</key> <string>516 632 650 250 0 0 1680 1027 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>1C78EAAE065D492600B07095</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>650 41 650 250 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/MAC.pbxuser ================================================ // !$*UTF8*$! { 040F1C9D12CD1FEF008BA0CB /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; }; 040F1C9E12CD1FEF008BA0CB /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 040F1CB812CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5C0381F66500A8011A /* sq.h */; name = "sq.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 393; vrLoc = 0; }; 040F1CB912CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; name = "sqVirtualMachine.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 510; vrLoc = 0; }; 040F1CBA12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 652; vrLoc = 0; }; 040F1CBB12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF35000846F98600FA5ACB /* config.h */; name = "config.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 904; vrLoc = 0; }; 040F1CBC12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC580381F61C00A8011A /* sqConfig.h */; name = "sqConfig.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 302; vrLoc = 0; }; 040F1CBD12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 870; vrLoc = 0; }; 040F1CBE12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8900858C3F900079BE1 /* LocalePlugin.h */; name = "LocalePlugin.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 522; vrLoc = 0; }; 040F1CBF12CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */; name = "LocalePlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 533; vrLoc = 0; }; 040F1CC012CD2220008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */; name = "sqMacLocaleCocoa.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 755; vrLoc = 0; }; 040F1DA112CD2673008BA0CB /* Cocoa.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Cocoa.h; sourceTree = "<group>"; }; 040F1DAF12CD26E4008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; name = "sqMacLocaleCocoa.m: 6"; rLen = 0; rLoc = 92; rType = 0; vrLen = 754; vrLoc = 0; }; 040F1DB012CD26E4008BA0CB /* PBXBookmark */ = { isa = PBXBookmark; fRef = 040F1DA112CD2673008BA0CB /* Cocoa.h */; }; 040F1DB112CD26E4008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1DB212CD26E4008BA0CB /* Cocoa.h */; name = "Cocoa.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 485; vrLoc = 0; }; 040F1DB212CD26E4008BA0CB /* Cocoa.h */ = { isa = PBXFileReference; name = Cocoa.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h; sourceTree = "<absolute>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1370, 237}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 485}"; }; }; 66B8BC580381F61C00A8011A /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {519, 245}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 302}"; }; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {579, 2210}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 870}"; }; }; 66B8BC5C0381F66500A8011A /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {551, 7254}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 393}"; }; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {519, 3952}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 510}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Development; activeTarget = 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */; codeSenseManager = 040F1C9E12CD1FEF008BA0CB /* Code sense */; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 341, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 301, 60, 20, 48.16259765625, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 315434587; PBXWorkspaceStateSaveDate = 315434587; }; perUserProjectItems = { 040F1CB812CD2220008BA0CB /* PBXTextBookmark */ = 040F1CB812CD2220008BA0CB /* PBXTextBookmark */; 040F1CB912CD2220008BA0CB /* PBXTextBookmark */ = 040F1CB912CD2220008BA0CB /* PBXTextBookmark */; 040F1CBA12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBA12CD2220008BA0CB /* PBXTextBookmark */; 040F1CBB12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBB12CD2220008BA0CB /* PBXTextBookmark */; 040F1CBC12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBC12CD2220008BA0CB /* PBXTextBookmark */; 040F1CBD12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBD12CD2220008BA0CB /* PBXTextBookmark */; 040F1CBE12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBE12CD2220008BA0CB /* PBXTextBookmark */; 040F1CBF12CD2220008BA0CB /* PBXTextBookmark */ = 040F1CBF12CD2220008BA0CB /* PBXTextBookmark */; 040F1CC012CD2220008BA0CB /* PBXTextBookmark */ = 040F1CC012CD2220008BA0CB /* PBXTextBookmark */; 040F1DAF12CD26E4008BA0CB /* PBXTextBookmark */ = 040F1DAF12CD26E4008BA0CB /* PBXTextBookmark */; 040F1DB012CD26E4008BA0CB /* PBXBookmark */ = 040F1DB012CD26E4008BA0CB /* PBXBookmark */; 040F1DB112CD26E4008BA0CB /* PBXTextBookmark */ = 040F1DB112CD26E4008BA0CB /* PBXTextBookmark */; }; sourceControlManager = 040F1C9D12CD1FEF008BA0CB /* Source Control */; userBuildSettings = { }; }; 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {519, 4771}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 533}"; }; }; 94ABA8900858C3F900079BE1 /* LocalePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {558, 1274}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 522}"; }; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {523, 2314}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 652}"; }; }; 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */ = { activeExec = 0; }; 94AF35000846F98600FA5ACB /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {537, 2249}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 904}"; }; }; 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {544, 533}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 755}"; }; }; 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {537, 3380}}"; sepNavSelRange = "{92, 0}"; sepNavVisRange = "{0, 754}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/johnmci.mode1 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXRunSessionModule</string> <key>Name</key> <string>Run Log</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>94AF35A4084782DD00FA5ACB</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1</string> <key>MajorVersion</key> <integer>31</integer> <key>MinorVersion</key> <integer>1</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-target-popup</string> <string>active-buildstyle-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>buildOrClean</string> <string>build-and-runOrDebug</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>toggle-editor</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66B8BC570381F53800A8011A</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>11</integer> <integer>8</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 733}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 751}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>115 104 919 792 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>LocalePlugin.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>LocalePlugin.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>94B4E4A70C75EA3800F83D97</string> <key>history</key> <array> <string>944D6258085F474800600D6E</string> <string>94BBFE8908A46E3D00181406</string> <string>94BB001D08A54ECD00181406</string> <string>94CB5D6309E1DEC400AD2895</string> <string>94ACFA7709EEFA300043ED40</string> <string>94ACFA7809EEFA300043ED40</string> <string>94B4E4990C75EA3700F83D97</string> <string>9457F0A509C0D6F000D1610A</string> </array> <key>prevStack</key> <array> <string>947907390858EDF80068B3F8</string> <string>94461699085E5999004F7BD5</string> <string>9446169B085E5999004F7BD5</string> <string>944D625B085F474800600D6E</string> <string>946D55B2089DFA400081F0EE</string> <string>94BBFE8E08A46E3D00181406</string> <string>94BB005208A5562100181406</string> <string>94B4E49A0C75EA3700F83D97</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {711, 692}}</string> <key>RubberWindowFrame</key> <string>115 104 919 792 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>692pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 697}, {711, 54}}</string> <key>RubberWindowFrame</key> <string>115 104 919 792 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>54pt</string> </dict> </array> <key>Proportion</key> <string>711pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>94B4E49C0C75EA3700F83D97</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>94B4E49D0C75EA3700F83D97</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.short</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>209054117.07446</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>/Users/johnmci/Documents/SqueakLocale/SqueakLocale.xcodeproj</string> </array> <key>WindowString</key> <string>115 104 919 792 0 0 1680 1028 </string> <key>WindowTools</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {879, 130}}</string> <key>RubberWindowFrame</key> <string>444 71 879 795 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>130pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBuildLogShowsTranscriptDefaultKey</key> <string>{{0, 5}, {879, 614}}</string> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 135}, {879, 619}}</string> <key>RubberWindowFrame</key> <string>444 71 879 795 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>619pt</string> </dict> </array> <key>Proportion</key> <string>754pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94BBFEA708A46E3D00181406</string> <string>94B2DFEA09C7B53D00C46523</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.build</string> <key>WindowString</key> <string>444 71 879 795 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>94BBFEA708A46E3D00181406</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {410, 251}}</string> <string>{{0, 251}, {410, 371}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {410, 622}}</string> <string>{{410, 0}, {820, 622}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1230, 622}}</string> <key>RubberWindowFrame</key> <string>208 95 1230 663 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>622pt</string> </dict> </array> <key>Proportion</key> <string>622pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>94BBFEA908A46E3D00181406</string> <string>1C162984064C10D400B95A72</string> <string>94BBFEAA08A46E3D00181406</string> <string>94BBFEAB08A46E3D00181406</string> <string>94BBFEAC08A46E3D00181406</string> <string>94BBFEAD08A46E3D00181406</string> <string>94BBFEAE08A46E3D00181406</string> <string>94BBFEAF08A46E3D00181406</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debug</string> <key>WindowString</key> <string>208 95 1230 663 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {791, 416}}</string> <key>RubberWindowFrame</key> <string>629 73 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>791pt</string> </dict> </array> <key>Proportion</key> <string>416pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 421}, {791, 212}}</string> <key>RubberWindowFrame</key> <string>629 73 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>633pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>94B4E49E0C75EA3700F83D97</string> <string>94B4E49F0C75EA3700F83D97</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>629 73 791 674 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {686, 500}}</string> <key>RubberWindowFrame</key> <string>759 114 686 541 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>500pt</string> </dict> </array> <key>Proportion</key> <string>500pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94ABA92F0858D3A300079BE1</string> <string>94BBFFFF08A5476700181406</string> <string>1C78EAAC065D492600B07095</string> </array> <key>WindowString</key> <string>759 114 686 541 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>94ABA92F0858D3A300079BE1</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.run</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>LauncherConfigVersion</key> <string>3</string> <key>PBXProjectModuleGUID</key> <string>1CD0528B0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Run</string> <key>Runner</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {493, 167}}</string> <string>{{0, 176}, {493, 267}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {405, 443}}</string> <string>{{414, 0}, {514, 443}}</string> </array> </dict> </dict> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {460, 159}}</string> <key>RubberWindowFrame</key> <string>316 696 459 200 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXRunSessionModule</string> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Name</key> <string>Run Log</string> <key>ServiceClasses</key> <array> <string>PBXRunSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C0AD2B3069F1EA900FABCE6</string> <string>1C0AD2B4069F1EA900FABCE6</string> <string>1CD0528B0623707200166675</string> <string>1C0AD2B5069F1EA900FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.run</string> <key>WindowString</key> <string>316 696 459 200 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C0AD2B3069F1EA900FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>2</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpoints</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimator</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/johnmci.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>9471AF5E1107A072004DD8A7</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>373</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>94E7F9191237565E00A03A11</string> <string>66B8BC570381F53800A8011A</string> <string>94E7F8371237541300A03A11</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>15</integer> <integer>13</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {373, 917}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {390, 935}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>373</real> </array> <key>RubberWindowFrame</key> <string>10 52 1502 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>390pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMacLocaleCocoa.m</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMacLocaleCocoa.m</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9420ABC41239521400EF4FDF</string> <key>history</key> <array> <string>944D6258085F474800600D6E</string> <string>94BB001D08A54ECD00181406</string> <string>94E7F76F1237474100A03A11</string> <string>94E7F7711237474100A03A11</string> <string>94E7F92F1237572100A03A11</string> <string>94E7F989123759D900A03A11</string> <string>94E7F98A123759D900A03A11</string> <string>94E7FA0112375E5F00A03A11</string> <string>94E9A04012380A3A0048557C</string> <string>94E9A04212380A3A0048557C</string> <string>94E9A04D12380B990048557C</string> <string>94E9A0A012380D830048557C</string> <string>94E9A0B012380E2B0048557C</string> <string>94E9A0B112380E2B0048557C</string> <string>94E9A0B212380E2B0048557C</string> <string>94E9A0B312380E2B0048557C</string> <string>94E9A0B412380E2B0048557C</string> <string>94E9A0B512380E2B0048557C</string> <string>9420ABBC123951F800EF4FDF</string> <string>9420ABBD123951F800EF4FDF</string> <string>9420ABBE123951F800EF4FDF</string> <string>9420ABBF123951F800EF4FDF</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1107, 867}}</string> <key>RubberWindowFrame</key> <string>10 52 1502 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>867pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 872}, {1107, 63}}</string> <key>RubberWindowFrame</key> <string>10 52 1502 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>63pt</string> </dict> </array> <key>Proportion</key> <string>1107pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>9420ABC1123951F800EF4FDF</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>9420ABC2123951F800EF4FDF</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>305746452.50028902</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>9471AF5F1107A072004DD8A7</string> <string>/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj</string> </array> <key>WindowString</key> <string>10 52 1502 976 0 0 1680 1028 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {879, 255}}</string> <key>RubberWindowFrame</key> <string>281 201 879 795 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>255pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 260}, {879, 494}}</string> <key>RubberWindowFrame</key> <string>281 201 879 795 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>494pt</string> </dict> </array> <key>Proportion</key> <string>754pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9471AF5F1107A072004DD8A7</string> <string>9420ABC3123951F800EF4FDF</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>281 201 879 795 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9471AF5F1107A072004DD8A7</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {615, 332}}</string> <string>{{615, 0}, {615, 332}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1230, 332}}</string> <string>{{0, 332}, {1230, 290}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1230, 622}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>120</real> <string>Value</string> <real>85</real> <string>Summary</string> <real>385</real> </array> <key>Frame</key> <string>{{615, 0}, {615, 332}}</string> <key>RubberWindowFrame</key> <string>446 132 1230 663 0 0 1680 1028 </string> </dict> <key>RubberWindowFrame</key> <string>446 132 1230 663 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>622pt</string> </dict> </array> <key>Proportion</key> <string>622pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>94E9A0321237F5DB0048557C</string> <string>1C162984064C10D400B95A72</string> <string>94E9A0331237F5DB0048557C</string> <string>94E9A0341237F5DB0048557C</string> <string>94E9A0351237F5DB0048557C</string> <string>94E9A0361237F5DB0048557C</string> <string>94E9A0371237F5DB0048557C</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>446 132 1230 663 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>LocalePlugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {791, 294}}</string> <key>RubberWindowFrame</key> <string>629 73 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>791pt</string> </dict> </array> <key>Proportion</key> <string>294pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 299}, {791, 334}}</string> <key>RubberWindowFrame</key> <string>629 73 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>334pt</string> </dict> </array> <key>Proportion</key> <string>633pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>94E9A0BE12380FBC0048557C</string> <string>94E9A0BF12380FBC0048557C</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>629 73 791 674 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {686, 500}}</string> <key>RubberWindowFrame</key> <string>25 376 686 541 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>500pt</string> </dict> </array> <key>Proportion</key> <string>500pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>94E9A05A12380BB30048557C</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>25 376 686 541 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66B8BC580381F61C00A8011A /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 788}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 302}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 2197}}"; sepNavSelRange = "{1460, 0}"; sepNavVisRange = "{0, 2732}"; sepNavVisRect = "{{0, 190}, {673, 397}}"; }; }; 66B8BC5C0381F66500A8011A /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 5889}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2268}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 3575}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1859}"; sepNavVisRect = "{{0, 2585}, {673, 397}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Deployment; activeExecutable = 94ABA91E0858D35E00079BE1 /* Squeak */; activeTarget = 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */; addToTargets = ( 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */, ); breakpoints = ( 947906FD0858E5030068B3F8 /* sqMacLocaleCarbon.c:67 */, 94BB001C08A54ECA00181406 /* sqMacLocaleCarbon.c:205 */, 94E7F7F91237521E00A03A11 /* sqMacLocaleCocoa.m:188 */, 94E9A0231237F5D80048557C /* sqMacLocaleCocoa.m:49 */, 94E9A0251237F5D90048557C /* sqMacLocaleCocoa.m:66 */, ); codeSenseManager = 9444E60E06E7B8740063F6CC /* Code sense */; executables = ( 94ABA91E0858D35E00079BE1 /* Squeak */, ); expressions = ( buffer, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 377, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 868, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 120, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 828, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 305745864; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 305745864; }; perUserProjectItems = { 9420ABBC123951F800EF4FDF /* PBXTextBookmark */ = 9420ABBC123951F800EF4FDF /* PBXTextBookmark */; 9420ABBD123951F800EF4FDF /* PBXTextBookmark */ = 9420ABBD123951F800EF4FDF /* PBXTextBookmark */; 9420ABBE123951F800EF4FDF /* PlistBookmark */ = 9420ABBE123951F800EF4FDF /* PlistBookmark */; 9420ABBF123951F800EF4FDF /* PBXTextBookmark */ = 9420ABBF123951F800EF4FDF /* PBXTextBookmark */; 9420ABC41239521400EF4FDF /* PBXTextBookmark */ = 9420ABC41239521400EF4FDF /* PBXTextBookmark */; 944D6258085F474800600D6E /* PBXTextBookmark */ = 944D6258085F474800600D6E /* PBXTextBookmark */; 94BB001D08A54ECD00181406 /* PBXTextBookmark */ = 94BB001D08A54ECD00181406 /* PBXTextBookmark */; 94E7F76F1237474100A03A11 /* PBXTextBookmark */ = 94E7F76F1237474100A03A11 /* PBXTextBookmark */; 94E7F7711237474100A03A11 /* PBXTextBookmark */ = 94E7F7711237474100A03A11 /* PBXTextBookmark */; 94E7F92F1237572100A03A11 /* PBXTextBookmark */ = 94E7F92F1237572100A03A11 /* PBXTextBookmark */; 94E7F989123759D900A03A11 /* PBXTextBookmark */ = 94E7F989123759D900A03A11 /* PBXTextBookmark */; 94E7F98A123759D900A03A11 /* PBXTextBookmark */ = 94E7F98A123759D900A03A11 /* PBXTextBookmark */; 94E7FA0112375E5F00A03A11 /* PBXTextBookmark */ = 94E7FA0112375E5F00A03A11 /* PBXTextBookmark */; 94E9A04012380A3A0048557C /* PBXTextBookmark */ = 94E9A04012380A3A0048557C /* PBXTextBookmark */; 94E9A04212380A3A0048557C /* PBXTextBookmark */ = 94E9A04212380A3A0048557C /* PBXTextBookmark */; 94E9A04D12380B990048557C /* PBXTextBookmark */ = 94E9A04D12380B990048557C /* PBXTextBookmark */; 94E9A0A012380D830048557C /* PBXTextBookmark */ = 94E9A0A012380D830048557C /* PBXTextBookmark */; 94E9A0B012380E2B0048557C /* PBXTextBookmark */ = 94E9A0B012380E2B0048557C /* PBXTextBookmark */; 94E9A0B112380E2B0048557C /* PBXTextBookmark */ = 94E9A0B112380E2B0048557C /* PBXTextBookmark */; 94E9A0B212380E2B0048557C /* PBXTextBookmark */ = 94E9A0B212380E2B0048557C /* PBXTextBookmark */; 94E9A0B312380E2B0048557C /* PBXTextBookmark */ = 94E9A0B312380E2B0048557C /* PBXTextBookmark */; 94E9A0B412380E2B0048557C /* PBXTextBookmark */ = 94E9A0B412380E2B0048557C /* PBXTextBookmark */; 94E9A0B512380E2B0048557C /* PBXTextBookmark */ = 94E9A0B512380E2B0048557C /* PBXTextBookmark */; }; sourceControlManager = 9444E60D06E7B8740063F6CC /* Source Control */; userBuildSettings = { }; }; 9420ABBC123951F800EF4FDF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF35040846F9AB00FA5ACB /* interp.h */; name = "interp.h: 12"; rLen = 1; rLoc = 317; rType = 0; vrLen = 1522; vrLoc = 0; }; 9420ABBD123951F800EF4FDF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */; name = "LocalePlugin.c: 115"; rLen = 19; rLoc = 3116; rType = 0; vrLen = 1770; vrLoc = 2156; }; 9420ABBE123951F800EF4FDF /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info-SqueakLocalePlugin__Upgraded_.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleVersion, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/plugins/SqueakLocale/Info-SqueakLocalePlugin__Upgraded_.plist"; rLen = 0; rLoc = 9223372036854775807; }; 9420ABBF123951F800EF4FDF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; name = "sqMacLocaleCocoa.m: 56"; rLen = 9; rLoc = 2315; rType = 0; vrLen = 2544; vrLoc = 1005; }; 9420ABC41239521400EF4FDF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; name = "sqMacLocaleCocoa.m: 102"; rLen = 22; rLoc = 4212; rType = 0; vrLen = 2600; vrLoc = 3379; }; 94405843085E5A7A004495D0 /* InfoPlist.strings */ = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = /Users/johnmci/Documents/SqueakLocale/build/LocalePlugin.bundle/Contents/Resources/English.lproj/InfoPlist.strings; sourceTree = "<absolute>"; }; 9444E60D06E7B8740063F6CC /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 944D6258085F474800600D6E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94405843085E5A7A004495D0 /* InfoPlist.strings */; name = "InfoPlist.strings: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 263; vrLoc = 0; }; 947906FD0858E5030068B3F8 /* sqMacLocaleCarbon.c:67 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94ABA89B0858C5FA00079BE1 /* sqMacLocaleCarbon.c */; functionName = "sqLocMeasurementMetric()"; hitCount = 0; ignoreCount = 0; lineNumber = 67; modificationTime = 305664750.455028; originalNumberOfMultipleMatches = 1; state = 1; }; 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1405, 4797}}"; sepNavSelRange = "{3116, 19}"; sepNavVisRange = "{2156, 1770}"; sepNavVisRect = "{{0, 1920}, {670, 660}}"; sepNavWindowFrame = "{{153, 28}, {962, 719}}"; }; }; 94ABA8900858C3F900079BE1 /* LocalePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 1222}}"; sepNavSelRange = "{1369, 0}"; sepNavVisRange = "{878, 2289}"; sepNavVisRect = "{{0, 0}, {400, 654}}"; }; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 2535}}"; sepNavSelRange = "{145, 0}"; sepNavVisRange = "{0, 1639}"; sepNavWindowFrame = "{{38, 28}, {1206, 974}}"; }; }; 94ABA89B0858C5FA00079BE1 /* sqMacLocaleCarbon.c */ = { isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleCarbon.c; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/plugins/SqueakLocale/sqMacLocaleCarbon.c; sourceTree = "<absolute>"; }; 94ABA91E0858D35E00079BE1 /* Squeak */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; launchableReference = 94ABA91F0858D35E00079BE1 /* Squeak.app */; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); variableFormatDictionary = { }; }; 94ABA91F0858D35E00079BE1 /* Squeak.app */ = { isa = PBXFileReference; explicitFileType = wrapper.application; name = Squeak.app; path = ../../vm/build/Debug/Squeak.app; sourceTree = SOURCE_ROOT; }; 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */ = { activeExec = 0; }; 94AF34F10846F91100FA5ACB /* Info-SqueakLocalePlugin__Upgraded_.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {686, 654}}"; sepNavSelRange = "{823, 0}"; sepNavVisRect = "{{0, 0}, {400, 654}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; 94AF35000846F98600FA5ACB /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 2288}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1913}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; 94AF35040846F9AB00FA5ACB /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 835}}"; sepNavSelRange = "{317, 1}"; sepNavVisRange = "{0, 1522}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; sepNavWindowFrame = "{{61, 7}, {1206, 974}}"; }; }; 94BB001C08A54ECA00181406 /* sqMacLocaleCarbon.c:205 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94ABA89B0858C5FA00079BE1 /* sqMacLocaleCarbon.c */; functionName = "getCountryOrLanguage()"; hitCount = 0; ignoreCount = 0; lineNumber = 205; modificationTime = 305664750.455007; originalNumberOfMultipleMatches = 1; state = 1; }; 94BB001D08A54ECD00181406 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BBFE8D08A46E3D00181406 /* sqMacLocaleOS9.c */; name = smRegionCode; rLen = 12; rLoc = 737; rType = 0; vrLen = 1065; vrLoc = 0; }; 94BBFE8D08A46E3D00181406 /* sqMacLocaleOS9.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleOS9.c; path = /Users/johnmci/Documents/SqueakLocale/sqMacLocaleOS9.c; sourceTree = "<absolute>"; }; 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 815}}"; sepNavSelRange = "{1727, 14}"; sepNavVisRange = "{0, 1741}"; sepNavWindowFrame = "{{61, 7}, {1206, 974}}"; }; }; 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1058, 3341}}"; sepNavSelRange = "{4212, 22}"; sepNavVisRange = "{3379, 2600}"; sepNavWindowFrame = "{{38, 28}, {1206, 974}}"; }; }; 94E7F76F1237474100A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F7701237474100A03A11 /* sqMacLocaleCarbon.h */; name = "sqMacLocaleCarbon.h: 9"; rLen = 6; rLoc = 107; rType = 0; vrLen = 189; vrLoc = 0; }; 94E7F7701237474100A03A11 /* sqMacLocaleCarbon.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMacLocaleCarbon.h; path = /Users/johnmci/Documents/SqueakLocale/sqMacLocaleCarbon.h; sourceTree = "<absolute>"; }; 94E7F7711237474100A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F7721237474100A03A11 /* sqMacLocaleCarbon.c */; name = "sqMacLocaleCarbon.c: 3"; rLen = 12; rLoc = 31; rType = 0; vrLen = 1756; vrLoc = 0; }; 94E7F7721237474100A03A11 /* sqMacLocaleCarbon.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleCarbon.c; path = /Users/johnmci/Documents/SqueakLocale/sqMacLocaleCarbon.c; sourceTree = "<absolute>"; }; 94E7F7F91237521E00A03A11 /* sqMacLocaleCocoa.m:188 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; hitCount = 0; ignoreCount = 0; lineNumber = 188; location = LocalePlugin; modificationTime = 305663429.897318; originalNumberOfMultipleMatches = 1; state = 1; }; 94E7F92F1237572100A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */; name = "sqMacLocaleCocoa.h: 39"; rLen = 14; rLoc = 1727; rType = 0; vrLen = 1741; vrLoc = 0; }; 94E7F989123759D900A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8900858C3F900079BE1 /* LocalePlugin.h */; name = "LocalePlugin.h: 45"; rLen = 0; rLoc = 1369; rType = 0; vrLen = 2289; vrLoc = 878; }; 94E7F98A123759D900A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F98B123759D900A03A11 /* sqUnixLocale.c */; name = "sqUnixLocale.c: 74"; rLen = 21; rLoc = 1811; rType = 0; vrLen = 1507; vrLoc = 606; }; 94E7F98B123759D900A03A11 /* sqUnixLocale.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixLocale.c; path = "/Volumes/330GB Photos/Cog/platforms/unix/plugins/LocalePlugin/sqUnixLocale.c"; sourceTree = "<absolute>"; }; 94E7FA0112375E5F00A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7FA0212375E5F00A03A11 /* sqSqueakOSXApplication+clipboard.m */; name = "sqSqueakOSXApplication+clipboard.m: 76"; rLen = 0; rLoc = 3258; rType = 0; vrLen = 2662; vrLoc = 945; }; 94E7FA0212375E5F00A03A11 /* sqSqueakOSXApplication+clipboard.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+clipboard.m"; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/OSX/sqSqueakOSXApplication+clipboard.m"; sourceTree = "<absolute>"; }; 94E9A0231237F5D80048557C /* sqMacLocaleCocoa.m:49 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; hitCount = 1; ignoreCount = 0; lineNumber = 49; location = LocalePlugin; modificationTime = 305663558.04379; originalNumberOfMultipleMatches = 1; state = 1; }; 94E9A0251237F5D90048557C /* sqMacLocaleCocoa.m:66 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; hitCount = 0; ignoreCount = 0; lineNumber = 66; location = LocalePlugin; modificationTime = 305663429.897705; originalNumberOfMultipleMatches = 1; state = 1; }; 94E9A04012380A3A0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A04112380A3A0048557C /* sqMacLocaleOS9.c */; name = "sqMacLocaleOS9.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1838; vrLoc = 3456; }; 94E9A04112380A3A0048557C /* sqMacLocaleOS9.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleOS9.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/LocalePlugin/sqMacLocaleOS9.c"; sourceTree = "<absolute>"; }; 94E9A04212380A3A0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A04312380A3A0048557C /* sqMacLocaleCarbon.c */; name = "sqMacLocaleCarbon.c: 23"; rLen = 48; rLoc = 469; rType = 0; vrLen = 1869; vrLoc = 0; }; 94E9A04312380A3A0048557C /* sqMacLocaleCarbon.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleCarbon.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/LocalePlugin/sqMacLocaleCarbon.c"; sourceTree = "<absolute>"; }; 94E9A04D12380B990048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A04E12380B990048557C /* sqUnixLocale.c */; name = "sqUnixLocale.c: 742"; rLen = 19; rLoc = 22241; rType = 0; vrLen = 1146; vrLoc = 21234; }; 94E9A04E12380B990048557C /* sqUnixLocale.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixLocale.c; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/unix/plugins/LocalePlugin/sqUnixLocale.c; sourceTree = "<absolute>"; }; 94E9A05212380B990048557C /* sqUnixLocale.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixLocale.c; path = /Users/johnmci/Documents/Squeak3.8.0/History/4.2.4b1/platforms/unix/plugins/LocalePlugin/sqUnixLocale.c; sourceTree = "<absolute>"; }; 94E9A0A012380D830048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A05212380B990048557C /* sqUnixLocale.c */; name = "sqUnixLocale.c: 736"; rLen = 9; rLoc = 22178; rType = 0; vrLen = 1082; vrLoc = 21298; }; 94E9A0B012380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5C0381F66500A8011A /* sq.h */; name = "sq.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2268; vrLoc = 0; }; 94E9A0B112380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; name = "sqVirtualMachine.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1859; vrLoc = 0; }; 94E9A0B212380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 5"; rLen = 0; rLoc = 145; rType = 0; vrLen = 1639; vrLoc = 0; }; 94E9A0B312380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC580381F61C00A8011A /* sqConfig.h */; name = "sqConfig.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 302; vrLoc = 0; }; 94E9A0B412380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 31"; rLen = 0; rLoc = 1460; rType = 0; vrLen = 2732; vrLoc = 0; }; 94E9A0B512380E2B0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF35000846F98600FA5ACB /* config.h */; name = "config.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1913; vrLoc = 0; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/SqueakLocale.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 94ABA8880858C2CB00079BE1 /* LocalePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */; }; 94ABA8910858C3F900079BE1 /* LocalePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ABA8900858C3F900079BE1 /* LocalePlugin.h */; }; 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; }; 94AF34E20846F91100FA5ACB /* sqConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC580381F61C00A8011A /* sqConfig.h */; }; 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; }; 94AF34E40846F91100FA5ACB /* sq.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5C0381F66500A8011A /* sq.h */; }; 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; }; 94AF34E80846F91100FA5ACB /* SqueakPlugin.icns in Resources */ = {isa = PBXBuildFile; fileRef = 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */; }; 94AF35010846F98600FA5ACB /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF35000846F98600FA5ACB /* config.h */; }; 94AF35050846F9AB00FA5ACB /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF35040846F9AB00FA5ACB /* interp.h */; }; 94E7F6C7123740F900A03A11 /* sqMacLocaleCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */; }; 94E7F6C8123740F900A03A11 /* sqMacLocaleCocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */; }; 94E7F9051237550300A03A11 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94E7F9041237550300A03A11 /* Cocoa.framework */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 94AF34F70846F94F00FA5ACB /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; outputFiles = ( ); }; /* End PBXBuildRule section */ /* Begin PBXFileReference section */ 66B8BC580381F61C00A8011A /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sqConfig.h; sourceTree = "<group>"; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sqPlatformSpecific.h; sourceTree = "<group>"; }; 66B8BC5C0381F66500A8011A /* sq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sq.h; sourceTree = "<group>"; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sqVirtualMachine.h; sourceTree = "<group>"; }; 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakPlugin.icns; path = ../../vm/OSX/SqueakPlugin.icns; sourceTree = "<group>"; }; 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = LocalePlugin.c; sourceTree = "<group>"; }; 94ABA8900858C3F900079BE1 /* LocalePlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = LocalePlugin.h; path = ../../../../../Cross/plugins/LocalePlugin/LocalePlugin.h; sourceTree = "<group>"; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sqMemoryAccess.h; sourceTree = "<group>"; }; 94AF34F10846F91100FA5ACB /* Info-SqueakLocalePlugin__Upgraded_.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-SqueakLocalePlugin__Upgraded_.plist"; sourceTree = "<group>"; }; 94AF34F20846F91100FA5ACB /* LocalePlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LocalePlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 94AF35000846F98600FA5ACB /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; }; 94AF35040846F9AB00FA5ACB /* interp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../../vm/interp.h; sourceTree = "<group>"; }; 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacLocaleCocoa.h; sourceTree = "<group>"; }; 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqMacLocaleCocoa.m; sourceTree = "<group>"; }; 94E7F9041237550300A03A11 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 94AF34EE0846F91100FA5ACB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 94E7F9051237550300A03A11 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 66B8BC570381F53800A8011A /* iPhone */ = { isa = PBXGroup; children = ( 94AF35000846F98600FA5ACB /* config.h */, 66B8BC580381F61C00A8011A /* sqConfig.h */, 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */, ); name = iPhone; path = ../../vm/iPhone; sourceTree = SOURCE_ROOT; }; 66DF6BFE01D7DCEA00A80119 = { isa = PBXGroup; children = ( 94E7F9191237565E00A03A11 /* vm */, 66B8BC570381F53800A8011A /* iPhone */, 94E7F8371237541300A03A11 /* LocalePlugin */, 66DF6BFF01D7DCEA00A80119 /* Sources */, 66DF6C3901D7DCEA00A80119 /* resources */, 66DF6C4501D7DEEE00A80119 /* Products */, 94AF34F10846F91100FA5ACB /* Info-SqueakLocalePlugin__Upgraded_.plist */, 94E7F9041237550300A03A11 /* Cocoa.framework */, ); sourceTree = "<group>"; }; 66DF6BFF01D7DCEA00A80119 /* Sources */ = { isa = PBXGroup; children = ( 94E7F6C5123740F900A03A11 /* sqMacLocaleCocoa.h */, 94E7F6C6123740F900A03A11 /* sqMacLocaleCocoa.m */, ); name = Sources; sourceTree = "<group>"; }; 66DF6C3901D7DCEA00A80119 /* resources */ = { isa = PBXGroup; children = ( 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */, ); name = resources; sourceTree = "<group>"; }; 66DF6C4501D7DEEE00A80119 /* Products */ = { isa = PBXGroup; children = ( 94AF34F20846F91100FA5ACB /* LocalePlugin.bundle */, ); name = Products; sourceTree = "<group>"; }; 94E7F8371237541300A03A11 /* LocalePlugin */ = { isa = PBXGroup; children = ( 94ABA8900858C3F900079BE1 /* LocalePlugin.h */, 94ABA8870858C2CB00079BE1 /* LocalePlugin.c */, 94AF35040846F9AB00FA5ACB /* interp.h */, ); name = LocalePlugin; path = ../../vm/src/plugins/LocalePlugin; sourceTree = SOURCE_ROOT; }; 94E7F9191237565E00A03A11 /* vm */ = { isa = PBXGroup; children = ( 66B8BC5C0381F66500A8011A /* sq.h */, 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */, 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */, ); name = vm; path = ../../../Cross/vm; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 94AF34E10846F91100FA5ACB /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 94AF34E20846F91100FA5ACB /* sqConfig.h in Headers */, 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */, 94AF34E40846F91100FA5ACB /* sq.h in Headers */, 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */, 94AF35010846F98600FA5ACB /* config.h in Headers */, 94AF35050846F9AB00FA5ACB /* interp.h in Headers */, 94ABA8910858C3F900079BE1 /* LocalePlugin.h in Headers */, 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */, 94E7F6C7123740F900A03A11 /* sqMacLocaleCocoa.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 943BD77109BFD3D00013220E /* Build configuration list for PBXNativeTarget "SqueakLocalePlugin" */; buildPhases = ( 94AF34E10846F91100FA5ACB /* Headers */, 94AF34E70846F91100FA5ACB /* Resources */, 94AF34EA0846F91100FA5ACB /* Sources */, 94AF34EE0846F91100FA5ACB /* Frameworks */, 94AF34F00846F91100FA5ACB /* Rez */, ); buildRules = ( 94AF34F70846F94F00FA5ACB /* PBXBuildRule */, ); dependencies = ( ); name = SqueakLocalePlugin; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 94AF34F20846F91100FA5ACB /* LocalePlugin.bundle */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 66DF6BFD01D7DCEA00A80119 /* Project object */ = { isa = PBXProject; buildConfigurationList = 943BD77509BFD3D00013220E /* Build configuration list for PBXProject "SqueakLocale" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 94AF34E00846F91100FA5ACB /* SqueakLocalePlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 94AF34E70846F91100FA5ACB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 94AF34E80846F91100FA5ACB /* SqueakPlugin.icns in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ 94AF34F00846F91100FA5ACB /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 94AF34EA0846F91100FA5ACB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 94ABA8880858C2CB00079BE1 /* LocalePlugin.c in Sources */, 94E7F6C8123740F900A03A11 /* sqMacLocaleCocoa.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 943BD77209BFD3D00013220E /* Development */ = { isa = XCBuildConfiguration; buildSettings = { GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GENERATE_PKGINFO_FILE = YES; INFOPLIST_FILE = "Info-SqueakLocalePlugin__Upgraded_.plist"; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; PRODUCT_NAME = LocalePlugin; SECTORDER_FLAGS = ""; USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../vm/iPhone\""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Development; }; 943BD77309BFD3D00013220E /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CODE_SIGN_IDENTITY = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; COPY_PHASE_STRIP = YES; GENERATE_PKGINFO_FILE = YES; INFOPLIST_FILE = "Info-SqueakLocalePlugin__Upgraded_.plist"; PRODUCT_NAME = LocalePlugin; SDKROOT = macosx10.5; USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../vm/iPhone\""; WRAPPER_EXTENSION = bundle; }; name = Deployment; }; 943BD77609BFD3D00013220E /* Development */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.5; SDKROOT = macosx10.5; }; name = Development; }; 943BD77709BFD3D00013220E /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.5; SDKROOT = macosx10.5; }; name = Deployment; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 943BD77109BFD3D00013220E /* Build configuration list for PBXNativeTarget "SqueakLocalePlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 943BD77209BFD3D00013220E /* Development */, 943BD77309BFD3D00013220E /* Deployment */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Development; }; 943BD77509BFD3D00013220E /* Build configuration list for PBXProject "SqueakLocale" */ = { isa = XCConfigurationList; buildConfigurations = ( 943BD77609BFD3D00013220E /* Development */, 943BD77709BFD3D00013220E /* Deployment */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Development; }; /* End XCConfigurationList section */ }; rootObject = 66DF6BFD01D7DCEA00A80119 /* Project object */; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/sqMacLocaleCocoa.h ================================================ // // sqMacLocaleCocoa.h // SqueakLocale // // Created by John M McIntosh on 10-09-07. /* Copyright (c) 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> #import "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakLocale/sqMacLocaleCocoa.m ================================================ // // sqMacLocaleCocoa.m // SqueakLocale // // Created by John M McIntosh on 10-09-07. /* Copyright (c) 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqMacLocaleCocoa.h" sqInt sqLocInitialize(void) { return true; } /************** Country and language ******************/ /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *countryCode = [locale objectForKey: NSLocaleCountryCode]; NSUInteger usedByteCount = 0; [countryCode getBytes: str maxLength: 3 usedLength: &usedByteCount encoding: NSMacOSRomanStringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,3) remainingRange: NULL]; } /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *languageCode = [locale objectForKey: NSLocaleLanguageCode]; NSUInteger usedByteCount = 0; [languageCode getBytes: str maxLength: 3 usedLength: &usedByteCount encoding: NSMacOSRomanStringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,3) remainingRange: NULL]; } /***************** Currency ********************/ /* return 1 (true) if the currency symbol is to be placed in front of the *currency amount */ sqInt sqLocCurrencyNotation(void) { NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease]; [numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle]; NSString *numberAsString = [numberFormatter stringFromNumber:[NSNumber numberWithFloat: 1.2f]]; NSRange currencyLocation = [numberAsString rangeOfString:[numberFormatter currencySymbol]]; return (sqInt) (currencyLocation.location == 0); } /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *currencySymbol = [locale objectForKey: NSLocaleCurrencySymbol]; return [currencySymbol lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; } /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *currencySymbol = [locale objectForKey: NSLocaleCurrencySymbol]; NSUInteger usedByteCount = 0; [currencySymbol getBytes: str maxLength: sqLocCurrencySymbolSize() usedLength: &usedByteCount encoding: NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[currencySymbol length]) remainingRange: NULL]; } /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSNumber *metric = [locale objectForKey: NSLocaleUsesMetricSystem]; return [metric boolValue]; } /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *grouping = [locale objectForKey: NSLocaleGroupingSeparator]; NSUInteger usedByteCount = 0; [grouping getBytes: str maxLength: 1 usedLength: &usedByteCount encoding: NSMacOSRomanStringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[grouping length]) remainingRange: NULL]; } /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str) { NSLocale *locale = [NSLocale autoupdatingCurrentLocale]; NSString *decimal = [locale objectForKey: NSLocaleDecimalSeparator]; NSUInteger usedByteCount = 0; [decimal getBytes: str maxLength: 1 usedLength: &usedByteCount encoding: NSMacOSRomanStringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[decimal length]) remainingRange: NULL]; } /****************** time and date *********************/ sqInt sqLocGetVMOffsetToUTC(void) { /* return 0 for now */ return 0; } sqInt sqLocGetTimezoneOffset(void) { NSTimeZone *tz = [NSTimeZone systemTimeZone]; NSInteger offset = [tz secondsFromGMT]; return (offset)/60; } /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void) { NSTimeZone *tz = [NSTimeZone systemTimeZone]; return [tz isDaylightSavingTime]; } /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:NSDateFormatterLongStyle]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; NSString *fmt = [dateFormatter dateFormat]; return [fmt lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; } /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:NSDateFormatterLongStyle]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; NSString *fmt = [dateFormatter dateFormat]; NSUInteger usedByteCount = 0; [fmt getBytes: str maxLength: sqLocLongDateFormatSize() usedLength: &usedByteCount encoding: NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[fmt length]) remainingRange: NULL]; } /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(void) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:kCFDateFormatterShortStyle]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; NSString *fmt = [dateFormatter dateFormat]; return [fmt lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; } /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:kCFDateFormatterShortStyle]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; NSString *fmt = [dateFormatter dateFormat]; NSUInteger usedByteCount = 0; [fmt getBytes: str maxLength: sqLocLongDateFormatSize() usedLength: &usedByteCount encoding: NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[fmt length]) remainingRange: NULL]; } /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:kCFDateFormatterNoStyle]; [dateFormatter setTimeStyle:kCFDateFormatterMediumStyle]; NSString *fmt = [dateFormatter dateFormat]; return [fmt lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; } /* write the string describing the time formatting into string ptr. * Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str) { NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateFormatter setDateStyle:kCFDateFormatterNoStyle]; [dateFormatter setTimeStyle:kCFDateFormatterMediumStyle]; NSString *fmt = [dateFormatter dateFormat]; NSUInteger usedByteCount = 0; [fmt getBytes: str maxLength: sqLocTimeFormatSize() usedLength: &usedByteCount encoding: NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0,[fmt length]) remainingRange: NULL]; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/Info.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>ObjectiveCPlugin</string> <key>CFBundleIconFile</key> <string>SqueakPlugin.icns</string> <key>CFBundleIdentifier</key> <string>org.squeak.ObjectiveCPlugin</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> <string>1.0.3</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>1.0.3</string> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/PDColoredProgressView.h ================================================ // // PDColoredProgressView.h // PDColoredProgressViewDemo // // Created by Pascal Widdershoven on 03-01-09. // Copyright 2009 P-development. All rights reserved. // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must // not claim that you wrote the original software. If you use this // software in a product, an acknowledgment in the product // documentation (and/or about box) would be appreciated but is not // required. // // 2. Altered source versions must be plainly marked as such, and must // not be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. // #import <UIKit/UIKit.h> @interface PDColoredProgressView : UIProgressView { UIColor *_tintColor; } /** Set the desired tintColor for this control **/ - (void) setTintColor: (UIColor *) aColor; @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/PDColoredProgressView.m ================================================ // // PDColoredProgressView.m // PDColoredProgressViewDemo // // Created by Pascal Widdershoven on 03-01-09. // Copyright 2009 P-development. All rights reserved. // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must // not claim that you wrote the original software. If you use this // software in a product, an acknowledgment in the product // documentation (and/or about box) would be appreciated but is not // required. // // 2. Altered source versions must be plainly marked as such, and must // not be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. // #import "PDColoredProgressView.h" #import "drawing.m" @implementation PDColoredProgressView - (void)drawRect:(CGRect)rect { if([self progressViewStyle] == UIProgressViewStyleDefault) { CGContextRef ctx = UIGraphicsGetCurrentContext(); //draw first white layer addRoundedRectToPath(ctx, rect, 4, 4); CGContextClip(ctx); CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextFillRect(ctx, rect); //draw lower gray line CGContextSetRGBStrokeColor(ctx, 178.0/255.0, 178.0/255.0, 178.0/255.0, 0.9); CGContextSetLineWidth(ctx, 2); CGContextMoveToPoint(ctx, 2.2, rect.size.height); CGContextAddLineToPoint(ctx, rect.size.width - 2.2, rect.size.height); CGContextStrokePath(ctx); //fill upperhalf with light grey CGRect upperhalf = rect; upperhalf.size.height /= 1.75; upperhalf.origin.y = 0; CGContextSetRGBFillColor(ctx, 202.0/255.0, 202.0/255.0, 202.0/255.0, 0.9); CGContextFillRect(ctx, upperhalf); //fill a part of the upper half with a somewhat darker grey CGRect upperhalfTop = upperhalf; upperhalfTop.size.height /= 2.7; CGContextSetRGBFillColor(ctx, 163.0/255.0, 163.0/255.0, 163.0/255.0, 0.8); CGContextFillRect(ctx, upperhalfTop); //fill the progress part with our tintcolor if(_tintColor == nil) _tintColor = [[UIColor alloc]initWithRed: 43.0/255.0 green: 134.0/255.0 blue: 225.0/255.0 alpha: 1]; CGRect progressRect = rect; progressRect.size.width *= [self progress]; addRoundedRectToPath(ctx, progressRect, 4, 4); CGContextClip(ctx); CGContextSetFillColorWithColor(ctx, [_tintColor CGColor]); CGContextFillRect(ctx, progressRect); progressRect.size.width -= 1.25; progressRect.origin.x += 0.625; progressRect.size.height -= 1.25; progressRect.origin.y += 0.625; addRoundedRectToPath(ctx, progressRect, 4, 4); CGContextClip(ctx); CGContextSetLineWidth(ctx, 1); CGContextSetRGBStrokeColor(ctx, 20.0/255.0, 20.0/255.0, 20.0/255.0, 0.6); CGContextStrokeRect(ctx, progressRect); //draw white linear gradient over upperhalf CGFloat colors[8] = { 1, 1, 1, 0.45, 1, 1, 1, 0.75 }; fillRectWithLinearGradient(ctx, upperhalf, colors, 2, nil); } else { [super drawRect: rect]; } } - (void) setTintColor: (UIColor *) aColor { [_tintColor release]; _tintColor = [aColor retain]; } - (void)dealloc { [super dealloc]; [_tintColor release]; } @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/drawing.m ================================================ // // drawing.m // PDColoredProgressViewDemo // // Created by Pascal Widdershoven on 03-01-09. // Copyright 2009 P-development. All rights reserved. // static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight) { float fw, fh; // If the width or height of the corner oval is zero, then it reduces to a right angle, // so instead of a rounded rectangle we have an ordinary one. if (ovalWidth == 0 || ovalHeight == 0) { CGContextAddRect(context, rect); return; } // Save the context's state so that the translate and scale can be undone with a call // to CGContextRestoreGState. CGContextSaveGState(context); // Translate the origin of the contex to the lower left corner of the rectangle. CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); //Normalize the scale of the context so that the width and height of the arcs are 1.0 CGContextScaleCTM(context, ovalWidth, ovalHeight); // Calculate the width and height of the rectangle in the new coordinate system. fw = CGRectGetWidth(rect) / ovalWidth; fh = CGRectGetHeight(rect) / ovalHeight; // CGContextAddArcToPoint adds an arc of a circle to the context's path (creating the rounded // corners). It also adds a line from the path's last point to the begining of the arc, making // the sides of the rectangle. CGContextMoveToPoint(context, fw, fh/2); // Start at lower right corner CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); // Top right corner CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); // Top left corner CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); // Lower left corner CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // Back to lower right // Close the path CGContextClosePath(context); // Restore the context's state. This removes the translation and scaling // but leaves the path, since the path is not part of the graphics state. CGContextRestoreGState(context); } static void fillRectWithLinearGradient(CGContextRef context, CGRect rect, CGFloat colors[], int numberOfColors, CGFloat locations[]) { CGContextSaveGState(context); if(!CGContextIsPathEmpty(context)) CGContextClip(context); CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); CGPoint start = CGPointMake(0, 0); CGPoint end = CGPointMake(0, rect.size.height); CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); CGGradientRef gradient = CGGradientCreateWithColorComponents(space, colors, locations, numberOfColors); CGContextDrawLinearGradient(context, gradient, end, start, 0); CGContextRestoreGState(context); CGColorSpaceRelease(space); CGGradientRelease(gradient); } ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/squeakProxy.h ================================================ // // squeakProxy.h // SqueakObjectiveC // // Created by John M McIntosh on 01/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. /* MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <objc/runtime.h> #import "sq.h" extern struct VirtualMachine* interpreterProxy; /* Protocol * foo1 = @protocol(CLLocationManagerDelegate); Protocol * foo2 = @protocol(NSCoding); Protocol * foo3 = @protocol(NSCopying); Protocol * foo4 = @protocol(NSDecimalNumberBehaviors); Protocol * foo5 = @protocol(NSFastEnumeration); Protocol * foo6 = @protocol(NSLocking); Protocol * foo7 = @protocol(NSMutableCopying); Protocol * foo8 = @protocol(NSObject); Protocol * foo9 = @protocol(NSURLAuthenticationChallengeSender); Protocol * foo10 = @protocol(NSURLProtocolClient); Protocol * foo11 = @protocol(UIAccelerometerDelegate); Protocol * foo12 = @protocol(UIAlertViewDelegate); Protocol * foo13 = @protocol(UIApplicationDelegate); Protocol * foo14 = @protocol(UIImagePickerControllerDelegate); Protocol * foo15 = @protocol(UINavigationBarDelegate); Protocol * foo16 = @protocol(UINavigationControllerDelegate); Protocol * foo17 = @protocol(UIPickerViewDataSource); Protocol * foo18 = @protocol(UIPickerViewDelegate); Protocol * foo19 = @protocol(UISearchBarDelegate); Protocol * foo20 = @protocol(UIScrollViewDelegate); Protocol * foo21 = @protocol(UITabBarControllerDelegate); Protocol * foo22 = @protocol(UITabBarDelegate); Protocol * foo23 = @protocol(UITableViewDataSource); Protocol * foo24 = @protocol(UITableViewDelegate); Protocol * foo25 = @protocol(UITextFieldDelegate); Protocol * foo26 = @protocol(UITextInputTraits); Protocol * foo27 = @protocol(UITextViewDelegate); Protocol * foo28 = @protocol(UIWebViewDelegate); */ @interface SqueakProxy : NSObject { sqInt sem; Protocol* protocol; NSInvocation* invocation; NSConditionLock* lockForSqueak; NSMutableDictionary *sigs; id target; sqInt callbackid; BOOL isCarbonVM; } - (id) initWithSemaphore: (sqInt) squeakSem protocolNSString: (NSString *) nameString target: (id) aTarget; - (void) setReturnValue: (void*) pointer; - (BOOL) isDataTypeAware; - (void) setIsCarbonVM; @property (nonatomic,assign) sqInt sem; @property (nonatomic,assign) Protocol* protocol; @property (nonatomic,assign) NSInvocation* invocation; @property (nonatomic,assign) NSConditionLock* lockForSqueak; @property (nonatomic,assign) NSMutableDictionary *sigs; @property (nonatomic,retain) id target; @property (nonatomic,assign) sqInt callbackid; @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/squeakProxy.m ================================================ // // squeakProxy.m // SqueakObjectiveC // // Created by John M McIntosh on 01/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Some code from http://www.squeaksource.com/ObjectiveCBridge.html developers and contributors Creator: Alain Fischer Admin: Avi Bryant, Alain Fischer Developer: Todd Blanchard MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "squeakProxy.h" @implementation SqueakProxy @synthesize sem; @synthesize invocation; @synthesize lockForSqueak; @synthesize sigs; @synthesize protocol; @synthesize target; @synthesize callbackid; - (id) initWithSemaphore: (sqInt) squeakSem protocolNSString: (NSString *) nameString target: aTarget { sem = squeakSem; if (nameString) protocol = objc_getProtocol([nameString UTF8String]); else protocol = nil; if (aTarget) { [self setTarget: aTarget]; } else { NSObject *dummy = [[NSObject alloc] init]; [self setTarget: dummy]; [dummy release]; } lockForSqueak = [[NSConditionLock alloc] initWithCondition: 0]; sigs = [[NSMutableDictionary alloc] initWithCapacity: 10]; isCarbonVM = NO; callbackid = 0; return self; } #include <dlfcn.h> /*- (void) forwardInvocation: (NSInvocation*) anInvocation { NSDate *timeout; // NSLog(@"forwardInvocation: %@", anInvocation); // NSLog(@"currentThread: %@", [NSThread currentThread]); SEL selector = [anInvocation selector]; NSString *selectorString = NSStringFromSelector(selector); if (![sigs objectForKey: selectorString]) { [anInvocation invokeWithTarget: target]; return; } if([lockForSqueak lockWhenCondition: 0 beforeDate: (timeout = [[NSDate alloc] initWithTimeIntervalSinceNow: 3.0])]) { // NSLog(@"inside lock 0"); [lockForSqueak unlockWithCondition: 1]; [timeout release]; invocation = [anInvocation retain]; // NSLog(@"signalling squeak"); interpreterProxy->signalSemaphoreWithIndex(sem); if (isCarbonVM) interpreterProxy->callbackEnter(&callbackid); if([lockForSqueak lockWhenCondition: 2 beforeDate: (timeout = [[NSDate alloc] initWithTimeIntervalSinceNow: 5.0])]) { // NSLog(@"inside lock 2"); [timeout release]; [invocation release]; invocation = nil; [lockForSqueak unlockWithCondition: 0]; } else { // NSLog(@"failed lock 2"); [timeout release]; [invocation release]; invocation = nil; [lockForSqueak unlockWithCondition: 0]; } //NSLog(@"returning"); } else { [timeout release]; //NSLog(@"failed lock 0"); } }*/ - (NSMethodSignature *) methodSignatureForSelector: (SEL) selector { NSMethodSignature* sig; NSString* sigAsString; sig = [target methodSignatureForSelector: selector]; if (sig) return sig; sig = [super methodSignatureForSelector: selector]; if(sig) return sig; NSString *selectorString = NSStringFromSelector (selector); if (sigAsString = [sigs objectForKey: selectorString]) { if (protocol) { struct objc_method_description methodDescription; methodDescription = protocol_getMethodDescription(protocol, selector, YES, YES); if(methodDescription.name == NULL) { methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES); } if(methodDescription.name != NULL) { NSMethodSignature *foo = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; return foo; } } NSMethodSignature *foo = [NSMethodSignature signatureWithObjCTypes: [sigAsString cStringUsingEncoding: NSASCIIStringEncoding]]; return foo; } return nil; } - (BOOL) respondsToSelector: (SEL) selector { if([super respondsToSelector: selector]) return true; if ([target respondsToSelector: selector]) return true; NSString *which = NSStringFromSelector(selector); if ([sigs objectForKey: which]) return true; return false; } - (void) setReturnValue: (void*) pointer { [invocation setReturnValue: &pointer]; } - (BOOL) isDataTypeAware { return YES; } - (void) setIsCarbonVM { isCarbonVM = YES; } - (void) dealloc { [lockForSqueak release]; [sigs release]; [target release]; [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/squeakSUnitTester.h ================================================ // // squeakSUnitTester.h // SqueakObjectiveC // // Created by John M McIntosh on 9/25/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // // @interface squeakSUnitTester : NSObject - (char) test0char; - (int) test0int; - (short) test0short; - (long) test0long; - (long long) test0longlong; - (unsigned char) test0unsignedchar; - (unsigned int) test0unsignedint; - (unsigned short) test0unsignedshort; - (unsigned long) test0unsignedlong; - (unsigned long long) test0unsignedlonglong; - (float) test0float; - (double) test0double; - (void) test0void; - (char *) test0charpointer; - (squeakSUnitTester *) test0object; - (Class) test0class; - (SEL) test0methodselector; - (CGRect) test0CGRect; - (char) test0char: (char *) ignore; - (int) test0int: (char *) ignore; - (short) test0short: (char *) ignore; - (long) test0long: (char *) ignore; - (long long) test0longlong: (char *) ignore; - (unsigned char) test0unsignedchar: (char *) ignore; - (unsigned int) test0unsignedint: (char *) ignore; - (unsigned short) test0unsignedshort: (char *) ignore; - (unsigned long) test0unsignedlong: (char *) ignore; - (unsigned long long) test0unsignedlonglong: (char *) ignore; - (float) test0float: (char *) ignore; - (double) test0double: (char *) ignore; - (void) test0void: (char *) ignore; - (char *) test0charpointer: (char *) ignore; - (squeakSUnitTester *) test0object: (char *) ignore; - (Class) test0class: (char *) ignore; - (SEL) test0methodselector: (char *) ignore; - (CGRect) test0CGRect: (char *) ignore; - (char) test0char: (char *) ignore two: (char *) ignore2; - (int) test0int: (char *) ignore two: (char *) ignore2; - (short) test0short: (char *) ignore two: (char *) ignore2; - (long) test0long: (char *) ignore two: (char *) ignore2; - (long long) test0longlong: (char *) ignore two: (char *) ignore2; - (unsigned char) test0unsignedchar: (char *) ignore two: (char *) ignore2; - (unsigned int) test0unsignedint: (char *) ignore two: (char *) ignore2; - (unsigned short) test0unsignedshort: (char *) ignore two: (char *) ignore2; - (unsigned long) test0unsignedlong: (char *) ignore two: (char *) ignore2; - (unsigned long long) test0unsignedlonglong: (char *) ignore two: (char *) ignore2; - (float) test0float: (char *) ignore two: (char *) ignore2; - (double) test0double: (char *) ignore two: (char *) ignore2; - (void) test0void: (char *) ignore two: (char *) ignore2; - (char *) test0charpointer: (char *) ignore two: (char *) ignore2; - (squeakSUnitTester *) test0object: (char *) ignore two: (char *) ignore2; - (Class) test0class: (char *) ignore two: (char *) ignore2; - (SEL) test0methodselector: (char *) ignore two: (char *) ignore2; - (CGRect) test0CGRect: (char *) ignore two: (char *) ignore2; - (char) test0char: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (int) test0int: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (short) test0short: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (long) test0long: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (long long) test0longlong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned char) test0unsignedchar: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned int) test0unsignedint: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned short) test0unsignedshort: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned long) test0unsignedlong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (unsigned long long) test0unsignedlonglong: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (float) test0float: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (double) test0double: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (void) test0void: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (char *) test0charpointer: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (squeakSUnitTester *) test0object: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (Class) test0class: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (SEL) test0methodselector: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (CGRect) test0CGRect: (char *) ignore two: (char *) ignore2 three: (char *) ignore3; - (char) test1char: (char) ignore; - (int) test1int: (int) ignore; - (short) test1short: (short) ignore; - (long) test1long: (long) ignore; - (long long) test1longlong: (long long) ignore; - (unsigned char) test1unsignedchar: (unsigned char) ignore; - (unsigned int) test1unsignedint: (unsigned int) ignore; - (unsigned short) test1unsignedshort: (unsigned short) ignore; - (unsigned long) test1unsignedlong: (unsigned long) ignore; - (unsigned long long) test1unsignedlonglong: (unsigned long long) ignore; - (float) test1float: (float) ignore; - (double) test1double: (double) ignore; - (char *) test1charpointer: (char *) ignore; - (squeakSUnitTester *) test1object: (squeakSUnitTester *) ignore; - (Class) test1class: (Class) ignore; - (SEL) test1methodselector: (SEL) ignore; - (CGRect) test1CGRect: (CGRect) ignore; - (char) test2char: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (int) test2int: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (short) test2short: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (long) test2long: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (long long) test2longlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned char) test2unsignedchar: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned int) test2unsignedint: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned short) test2unsignedshort: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned long) test2unsignedlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (unsigned long long) test2unsignedlonglong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (float) test2float: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (double) test2double: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (void) test2void: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (char *) test2charpointer: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (squeakSUnitTester *) test2object: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (Class) test2class: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2; - (SEL) test2methodselector: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 ; - (CGRect) test2CGRect: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 ; - (oneway void) testQualifier0v; - (oneway void) testQualifier1v: (squeakSUnitTester *)ignore; - (oneway void) testQualifier2v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2; - (oneway void) testQualifier3v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2 three: (squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1io: (inout squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 three: (inout squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1i: (in squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 three: (in squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1o: (out squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 three: (out squeakSUnitTester *)ignore3; - (squeakSUnitTester *) testQualifier1r: (inout byref squeakSUnitTester *)ignore; - (squeakSUnitTester *) testQualifier2r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2; - (squeakSUnitTester *) testQualifier3r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 three: (inout byref squeakSUnitTester *)ignore3; @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/SqueakObjectiveC/squeakSUnitTester.m ================================================ // // squeakSUnitTester.m // SqueakObjectiveC // // Created by John M McIntosh on 9/25/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "squeakSUnitTester.h" @implementation squeakSUnitTester - (char) test0char { return 'A'; } - (int) test0int { return -1; } - (short) test0short { return 0xFFFF; } - (long) test0long { return 0xFFFFFFFF; } - (long long) test0longlong { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar{ return 'A'; } - (unsigned int) test0unsignedint{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort { return 0xFFFF; } - (unsigned long) test0unsignedlong{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float { return 8.8f; } - (double) test0double { return 8.8; } - (void) test0void { } - (char *) test0charpointer { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object { return [squeakSUnitTester new]; } - (Class) test0class { return [squeakSUnitTester class]; } - (SEL) test0methodselector { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore { return 'A'; } - (int) test0int: (char *)ignore { return -1; } - (short) test0short: (char *)ignore { return 0xFFFF; } - (long) test0long: (char *)ignore { return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore{ return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore { return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore { return 8.8f; } - (double) test0double: (char *)ignore { return 8.8; } - (void) test0void: (char *)ignore { } - (char *) test0charpointer: (char *)ignore { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore two: (char *) ignore2 { return 'A'; } - (int) test0int: (char *)ignore two: (char *) ignore2 { return -1; } - (short) test0short: (char *)ignore two: (char *) ignore2{ return 0xFFFF; } - (long) test0long: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore two: (char *) ignore2{ return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore two: (char *) ignore2{ return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore two: (char *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore two: (char *) ignore2{ return 8.8f; } - (double) test0double: (char *)ignore two: (char *) ignore2{ return 8.8; } - (void) test0void: (char *)ignore two: (char *) ignore2{ } - (char *) test0charpointer: (char *)ignore two: (char *) ignore2{ static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore two: (char *) ignore2 { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore two: (char *) ignore2 { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore two: (char *) ignore2 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore two: (char *) ignore2 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test0char: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 'A'; } - (int) test0int: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return -1; } - (short) test0short: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFF; } - (long) test0long: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (long long) test0longlong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test0unsignedchar: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 'A'; } - (unsigned int) test0unsignedint: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (unsigned short) test0unsignedshort: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFF; } - (unsigned long) test0unsignedlong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFF; } - (unsigned long long) test0unsignedlonglong: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 0xFFFFFFFFFFFFFFFFLL; } - (float) test0float: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 8.8f; } - (double) test0double: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return 8.8; } - (void) test0void: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { } - (char *) test0charpointer: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test0object: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return [squeakSUnitTester new]; } - (Class) test0class: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { return [squeakSUnitTester class]; } - (SEL) test0methodselector: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test0CGRect: (char *)ignore two: (char *) ignore2 three: (char *) ignore3 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (char) test1char: (char) ignore { return ignore; } - (int) test1int: (int) ignore { return ignore; } - (short) test1short: (short) ignore { return ignore; } - (long) test1long: (long) ignore { return ignore; } - (long long) test1longlong: (long long) ignore { return ignore; } - (unsigned char) test1unsignedchar: (unsigned char) ignore { return ignore; } - (unsigned int) test1unsignedint: (unsigned int) ignore { return ignore; } - (unsigned short) test1unsignedshort: (unsigned short) ignore { return ignore; } - (unsigned long) test1unsignedlong: (unsigned long) ignore { return ignore; } - (unsigned long long) test1unsignedlonglong: (unsigned long long) ignore { return ignore; } - (float) test1float: (float) ignore { return ignore; } - (double) test1double: (double) ignore { return ignore; } - (char *) test1charpointer: (char *) ignore { return ignore; } - (squeakSUnitTester *) test1object: (squeakSUnitTester *) ignore { return ignore; } - (Class) test1class: (Class) ignore { return ignore; } - (SEL) test1methodselector: (SEL) ignore { return ignore; } - (CGRect) test1CGRect: (CGRect) ignore { return ignore; } - (char) test2char: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return 'A'; } - (int) test2int: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return -1; } - (short) test2short: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFF; } - (long) test2long: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (long long) test2longlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (unsigned char) test2unsignedchar: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 'A'; } - (unsigned int) test2unsignedint: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (unsigned short) test2unsignedshort: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFF; } - (unsigned long) test2unsignedlong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFF; } - (unsigned long long) test2unsignedlonglong: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 0xFFFFFFFFFFFFFFFFLL; } - (float) test2float: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 8.8f; } - (double) test2double: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ return 8.8; } - (void) test2void: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ } - (char *) test2charpointer: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2{ static char* squeak = "squeak"; return squeak; } - (squeakSUnitTester *) test2object: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return [squeakSUnitTester new]; } - (Class) test2class: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { return [squeakSUnitTester class]; } - (SEL) test2methodselector: (squeakSUnitTester *)ignore two: (squeakSUnitTester *) ignore2 { SEL selector; selector = NSSelectorFromString( @"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:"); return selector; } - (CGRect) test2CGRect: (squeakSUnitTester *) ignore two: (squeakSUnitTester *) ignore2 { CGRect foo; foo.origin.x = 1.0; foo.origin.y = 2.0; foo.size.width = 3.0; foo.size.height = 4.0; return foo; } - (oneway void) testQualifier0v { } - (oneway void) testQualifier1v: (squeakSUnitTester *)ignore { } - (oneway void) testQualifier2v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2;{ } - (oneway void) testQualifier3v: (squeakSUnitTester *)ignore two: (squeakSUnitTester *)ignore2 three: (squeakSUnitTester *)ignore3 { } - (squeakSUnitTester *) testQualifier1io: (inout squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3io: (inout squeakSUnitTester *)ignore two: (inout squeakSUnitTester *)ignore2 three: (inout squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1i: (in squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3i: (in squeakSUnitTester *)ignore two: (in squeakSUnitTester *)ignore2 three: (in squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1o: (out squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3o: (out squeakSUnitTester *)ignore two: (out squeakSUnitTester *)ignore2 three: (out squeakSUnitTester *)ignore3 { return ignore3; } - (squeakSUnitTester *) testQualifier1r: (inout byref squeakSUnitTester *)ignore { return ignore; } - (squeakSUnitTester *) testQualifier2r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 { return ignore2; } - (squeakSUnitTester *) testQualifier3r: (inout byref squeakSUnitTester *)ignore two: (inout byref squeakSUnitTester *)ignore2 three: (inout byref squeakSUnitTester *)ignore3 { return ignore3; } @end ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/Info.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>UnixOSProcessPlugin</string> <key>CFBundleGetInfoString</key> <string>UnixOSProcessPlugin V6.0.0 for Squeak</string> <key>CFBundleIconFile</key> <string>SqueakPlugin.icns</string> <key>CFBundleIdentifier</key> <string>org.squeakfoundation.UnixOSProcessPlugin</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>UnixOSProcessPlugin V6.0.0 for Squeak</string> <key>CFBundlePackageType</key> <string>BNDL</string> <key>CFBundleShortVersionString</key> <string>2.3.11</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>6.0.0</string> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/PkgInfo ================================================ BNDLFAST ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/MAC.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>040F1C0512CD192C008BA0CB</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>4CA7E553092CC67E0044FE85</string> <string>4CA7E552092CC66D0044FE85</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>1</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 629}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 647}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>30 83 908 688 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info.plist</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info.plist</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>04F8801412D5055800C22208</string> <key>history</key> <array> <string>040F1C8B12CD1FB5008BA0CB</string> <string>040F1C8D12CD1FB5008BA0CB</string> <string>040F200612CD355F008BA0CB</string> <string>040F200812CD355F008BA0CB</string> <string>040F200912CD355F008BA0CB</string> <string>040F204F12CD42CD008BA0CB</string> <string>040F20A612CE03DF008BA0CB</string> <string>040F1E8912CD27A1008BA0CB</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {700, 434}}</string> <key>RubberWindowFrame</key> <string>30 83 908 688 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>434pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 439}, {700, 208}}</string> <key>RubberWindowFrame</key> <string>30 83 908 688 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>208pt</string> </dict> </array> <key>Proportion</key> <string>700pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>04F87F9812D4DBD900C22208</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>04F87F9912D4DBD900C22208</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>040F1C0612CD192C008BA0CB</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj</string> </array> <key>WindowString</key> <string>30 83 908 688 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {702, 358}}</string> <key>RubberWindowFrame</key> <string>191 86 702 640 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>358pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 363}, {702, 236}}</string> <key>RubberWindowFrame</key> <string>191 86 702 640 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>599pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>040F1C0612CD192C008BA0CB</string> <string>04F87F9A12D4DBD900C22208</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>191 86 702 640 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>040F1C0612CD192C008BA0CB</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugger</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {317, 164}}</string> <string>{{317, 0}, {377, 164}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 164}}</string> <string>{{0, 164}, {694, 216}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 380}}</string> <key>RubberWindowFrame</key> <string>321 238 694 422 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C0AD2AB069F1E9B00FABCE6</string> <string>1C162984064C10D400B95A72</string> <string>1C0AD2AC069F1E9B00FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>321 238 694 422 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>sqVirtualMachine.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>51 278 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>212pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 217}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>51 278 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>429pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>040F204D12CD4294008BA0CB</string> <string>040F204E12CD4294008BA0CB</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>51 278 781 470 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {650, 250}}</string> <key>RubberWindowFrame</key> <string>516 632 650 250 0 0 1680 1027 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>1C78EAAE065D492600B07095</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>650 41 650 250 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/MAC.pbxuser ================================================ // !$*UTF8*$! { 040F1BF912CD18CC008BA0CB /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; }; 040F1BFA12CD18CC008BA0CB /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 040F1C0812CD1991008BA0CB /* UnixOSProcessPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {894, 49374}}"; sepNavSelRange = "{52201, 0}"; sepNavVisRange = "{52011, 917}"; }; }; 040F1C2D12CD1B19008BA0CB /* SocketPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1601, 845}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 890}"; }; }; 040F1C3112CD1B51008BA0CB /* FilePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 819}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{884, 1618}"; }; }; 040F1C4312CD1C70008BA0CB /* sqaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {639, 1339}}"; sepNavSelRange = "{443, 0}"; sepNavVisRange = "{720, 1174}"; }; }; 040F1C8B12CD1FB5008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1C2D12CD1B19008BA0CB /* SocketPlugin.h */; name = "SocketPlugin.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 890; vrLoc = 0; }; 040F1C8D12CD1FB5008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4C2DFB1309335838008B95AB /* PkgInfo */; name = "PkgInfo: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 8; vrLoc = 0; }; 040F1E8912CD27A1008BA0CB /* PlistBookmark */ = { isa = PlistBookmark; fRef = 040F1BFB12CD18FF008BA0CB /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/plugins/UnixOSProcessPlugin/Info.plist"; rLen = 0; rLoc = 9223372036854775808; }; 040F200612CD355F008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F200712CD355F008BA0CB /* Carbon.h */; name = "Carbon.h: 54"; rLen = 0; rLoc = 1026; rType = 0; vrLen = 568; vrLoc = 773; }; 040F200712CD355F008BA0CB /* Carbon.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Carbon.h; path = /System/Library/Frameworks/Carbon.framework/Headers/Carbon.h; sourceTree = "<absolute>"; }; 040F200812CD355F008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1C4312CD1C70008BA0CB /* sqaio.h */; name = "sqaio.h: 11"; rLen = 0; rLoc = 443; rType = 0; vrLen = 1174; vrLoc = 720; }; 040F200912CD355F008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1C3112CD1B51008BA0CB /* FilePlugin.h */; name = "FilePlugin.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1618; vrLoc = 884; }; 040F204F12CD42CD008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 159"; rLen = 78; rLoc = 6543; rType = 0; vrLen = 1044; vrLoc = 5676; }; 040F20A612CE03DF008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4CA7E550092CC6680044FE85 /* ft2build.h */; name = "ft2build.h: 13"; rLen = 0; rLoc = 973; rType = 0; vrLen = 2342; vrLoc = 0; }; 04F8801412D5055800C22208 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 040F1BFB12CD18FF008BA0CB /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleShortVersionString, ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/plugins/UnixOSProcessPlugin/Info.plist"; rLen = 0; rLoc = 9223372036854775807; }; 4C2DFB1309335838008B95AB /* PkgInfo */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {591, 361}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 8}"; }; }; 4CA7E550092CC6680044FE85 /* ft2build.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {639, 754}}"; sepNavSelRange = "{973, 0}"; sepNavVisRange = "{0, 2342}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Deployment; activeTarget = 942103F2084F50DF006A0FD2 /* UnixOSProcessPlugin */; addToTargets = ( 942103F2084F50DF006A0FD2 /* UnixOSProcessPlugin */, ); codeSenseManager = 040F1BFA12CD18CC008BA0CB /* Code sense */; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 461, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 421, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 315939788; PBXWorkspaceStateSaveDate = 315939788; }; perUserProjectItems = { 040F1C8B12CD1FB5008BA0CB /* PBXTextBookmark */ = 040F1C8B12CD1FB5008BA0CB /* PBXTextBookmark */; 040F1C8D12CD1FB5008BA0CB /* PBXTextBookmark */ = 040F1C8D12CD1FB5008BA0CB /* PBXTextBookmark */; 040F1E8912CD27A1008BA0CB /* PlistBookmark */ = 040F1E8912CD27A1008BA0CB /* PlistBookmark */; 040F200612CD355F008BA0CB /* PBXTextBookmark */ = 040F200612CD355F008BA0CB /* PBXTextBookmark */; 040F200812CD355F008BA0CB /* PBXTextBookmark */ = 040F200812CD355F008BA0CB /* PBXTextBookmark */; 040F200912CD355F008BA0CB /* PBXTextBookmark */ = 040F200912CD355F008BA0CB /* PBXTextBookmark */; 040F204F12CD42CD008BA0CB /* PBXTextBookmark */ = 040F204F12CD42CD008BA0CB /* PBXTextBookmark */; 040F20A612CE03DF008BA0CB /* PBXTextBookmark */ = 040F20A612CE03DF008BA0CB /* PBXTextBookmark */; 04F8801412D5055800C22208 /* PlistBookmark */ = 04F8801412D5055800C22208 /* PlistBookmark */; }; sourceControlManager = 040F1BF912CD18CC008BA0CB /* Source Control */; userBuildSettings = { }; }; 9407B2F910DA271000AE2B55 /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {999, 4056}}"; sepNavSelRange = "{7199, 37}"; sepNavVisRange = "{6939, 429}"; }; }; 942103F2084F50DF006A0FD2 /* UnixOSProcessPlugin */ = { activeExec = 0; }; 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1202, 2275}}"; sepNavSelRange = "{6543, 78}"; sepNavVisRange = "{5676, 1044}"; }; }; 949BB00C09327C3300684056 /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {537, 2249}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 904}"; }; }; 949BB01709327C9D00684056 /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {663, 361}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 634}"; }; }; 949BB07A09328C1500684056 /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {551, 7254}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 393}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/bert.mode1 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXRunSessionModule</string> <key>Name</key> <string>Run Log</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>4C4BDFAA08EBD932008EB73B</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1</string> <key>MajorVersion</key> <integer>31</integer> <key>MinorVersion</key> <integer>1</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-target-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>buildOrClean</string> <string>build-and-runOrDebug</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>toggle-editor</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>4CA7E553092CC67E0044FE85</string> <string>4CA7E552092CC66D0044FE85</string> <string>66DF6C3901D7DCEA00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1CC0EA4004350EF90044410B</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>29</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 427}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 445}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>185 311 862 486 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>MyNewFile14.java</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>MyNewFile14.java</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {654, 0}}</string> <key>RubberWindowFrame</key> <string>185 311 862 486 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 5}, {654, 440}}</string> <key>RubberWindowFrame</key> <string>185 311 862 486 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>440pt</string> </dict> </array> <key>Proportion</key> <string>654pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>4C703A0509336218008E817B</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>4C703A0609336218008E817B</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.short</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>4CED2BC108EC5536007BDF80</string> <string>/Users/bert/Squeak/VM/squeak/FT2Plugin.xcodeproj</string> </array> <key>WindowString</key> <string>185 311 862 486 0 0 1440 878 </string> <key>WindowTools</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {837, 290}}</string> <key>RubberWindowFrame</key> <string>394 248 837 572 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>290pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 295}, {837, 236}}</string> <key>RubberWindowFrame</key> <string>394 248 837 572 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>531pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>4CED2BC108EC5536007BDF80</string> <string>4C703A0709336218008E817B</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.build</string> <key>WindowString</key> <string>394 248 837 572 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>4CED2BC108EC5536007BDF80</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugger</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {317, 164}}</string> <string>{{317, 0}, {377, 164}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 164}}</string> <string>{{0, 164}, {694, 216}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 380}}</string> <key>RubberWindowFrame</key> <string>321 238 694 422 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C0AD2AB069F1E9B00FABCE6</string> <string>1C162984064C10D400B95A72</string> <string>1C0AD2AC069F1E9B00FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debug</string> <key>WindowString</key> <string>321 238 694 422 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.find</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528D0623707200166675</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 167}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>50%</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{8, 0}, {773, 254}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>50%</string> </dict> </array> <key>Proportion</key> <string>428pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>1C530D58069F1CE1000CFCEE</string> <string>1C530D59069F1CE1000CFCEE</string> <string>1CDD528C0622207200134675</string> <string>1C530D5A069F1CE1000CFCEE</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>62 385 781 470 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {440, 358}}</string> <key>RubberWindowFrame</key> <string>650 41 440 400 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>358pt</string> </dict> </array> <key>Proportion</key> <string>358pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>1C78EAAE065D492600B07095</string> <string>1C78EAAC065D492600B07095</string> </array> <key>WindowString</key> <string>650 41 440 400 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.run</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>LauncherConfigVersion</key> <string>3</string> <key>PBXProjectModuleGUID</key> <string>1CD0528B0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Run</string> <key>Runner</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {493, 167}}</string> <string>{{0, 176}, {493, 267}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {405, 443}}</string> <string>{{414, 0}, {514, 443}}</string> </array> </dict> </dict> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {460, 159}}</string> <key>RubberWindowFrame</key> <string>316 696 459 200 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXRunSessionModule</string> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Name</key> <string>Run Log</string> <key>ServiceClasses</key> <array> <string>PBXRunSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C0AD2B3069F1EA900FABCE6</string> <string>1C0AD2B4069F1EA900FABCE6</string> <string>1CD0528B0623707200166675</string> <string>1C0AD2B5069F1EA900FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.run</string> <key>WindowString</key> <string>316 696 459 200 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C0AD2B3069F1EA900FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>2</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpoints</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimator</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/bert.pbxuser ================================================ // !$*UTF8*$! { 4C4BDFA608EBD91A008EB73B /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; scmType = ""; }; 4C4BDFA708EBD91A008EB73B /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 4CA7E52C092CC14E0044FE85 /* FT2Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1055, 15414}}"; sepNavSelRange = "{32183, 0}"; sepNavVisRect = "{{0, 14633}, {1055, 375}}"; sepNavWindowFrame = "{{146, 180}, {1094, 504}}"; }; }; 4CA7E530092CC16B0044FE85 /* Info-FT2Plugin.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1055, 406}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {1055, 375}}"; sepNavWindowFrame = "{{87, 348}, {1094, 504}}"; }; }; 4CA7E550092CC6680044FE85 /* ft2build.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1055, 854}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 479}, {1055, 375}}"; sepNavWindowFrame = "{{223, 222}, {1094, 504}}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Deployment; activeBuildStyle = 66DF6C4301D7DCEA00A80119 /* Development */; activeTarget = 942103F2084F50DF006A0FD2 /* FT2Plugin */; addToTargets = ( 942103F2084F50DF006A0FD2 /* FT2Plugin */, ); codeSenseManager = 4C4BDFA708EBD91A008EB73B /* Code sense */; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXBookmarksDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBookmarksDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 200, 57.5835, ); PBXFileTableDataSourceColumnsKey = ( PBXBookmarksDataSource_LocationID, PBXBookmarksDataSource_NameID, PBXBookmarksDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 305, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 131, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 415, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 120, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID; PBXFileTableDataSourceColumnWidthsKey = ( 16, 200, 50, 183, ); PBXFileTableDataSourceColumnsKey = ( PBXSymbolsDataSource_SymbolTypeIconID, PBXSymbolsDataSource_SymbolNameID, PBXSymbolsDataSource_SymbolTypeID, PBXSymbolsDataSource_ReferenceNameID, ); }; PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 391, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_SCM_ColumnID, PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 235, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 154362372; PBXWorkspaceStateSaveDate = 154362372; }; sourceControlManager = 4C4BDFA608EBD91A008EB73B /* Source Control */; userBuildSettings = { }; }; 942103F2084F50DF006A0FD2 /* FT2Plugin */ = { activeExec = 0; }; 944E9BEC05E91D17003F0BED /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1055, 375}}"; sepNavSelRange = "{342, 0}"; sepNavVisRect = "{{0, 0}, {1055, 375}}"; sepNavWindowFrame = "{{163, 96}, {1094, 504}}"; }; }; 949BB07809328BF600684056 /* sqMacFileLogic.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1055, 17332}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 14696}, {1055, 375}}"; sepNavWindowFrame = "{{64, 369}, {1094, 504}}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/johnmci.mode1 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXRunSessionModule</string> <key>Name</key> <string>Run Log</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>949BB01409327C5100684056</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1</string> <key>MajorVersion</key> <integer>31</integer> <key>MinorVersion</key> <integer>1</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>941C754A0C066D47006D7AAC</string> <key>PBXProjectModuleLabel</key> <string>freetype.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>941C754B0C066D47006D7AAC</string> <key>PBXProjectModuleLabel</key> <string>freetype.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>948177AB0C6F8439000C8E8C</string> <key>history</key> <array> <string>941C756D0C069601006D7AAC</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {987, 883}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>15 99 987 924 0 0 1680 1028 </string> </dict> </dict> </array> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-target-popup</string> <string>active-buildstyle-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>buildOrClean</string> <string>build-and-runOrDebug</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>toggle-editor</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>326</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>4CA7E553092CC67E0044FE85</string> <string>4CA7E552092CC66D0044FE85</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>24</integer> <integer>23</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {326, 794}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {343, 812}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>326</real> </array> <key>RubberWindowFrame</key> <string>4 161 1184 853 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>343pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>948177A80C6F8439000C8E8C</string> <key>history</key> <array> <string>940E41A709A44B07004715E5</string> <string>940E41F009A44C0E004715E5</string> <string>943BD83109C005AD0013220E</string> <string>943BD83309C005AD0013220E</string> <string>9495AC950ACA07A100D58F66</string> <string>945838D60BD1454000CB0CB0</string> <string>941BF5330BDECAEA00D361A5</string> <string>941BF5340BDECAEA00D361A5</string> <string>941BF5520BDECB7300D361A5</string> <string>941C756C0C069601006D7AAC</string> </array> <key>prevStack</key> <array> <string>949BB31F0932DE2B00684056</string> <string>94E854C409339FA600B1FC29</string> <string>940E41AB09A44B07004715E5</string> <string>940E41AD09A44B07004715E5</string> <string>943BD83809C005AD0013220E</string> <string>945838D90BD1454000CB0CB0</string> <string>941BF5380BDECAEA00D361A5</string> <string>941BF53A0BDECAEA00D361A5</string> <string>941BF5540BDECB7300D361A5</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {836, 698}}</string> <key>RubberWindowFrame</key> <string>4 161 1184 853 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>698pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 703}, {836, 109}}</string> <key>RubberWindowFrame</key> <string>4 161 1184 853 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>109pt</string> </dict> </array> <key>Proportion</key> <string>836pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>948177A90C6F8439000C8E8C</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>948177AA0C6F8439000C8E8C</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.short</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>208633425.40347701</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>9481777B0C6F7E56000C8E8C</string> <string>941C754A0C066D47006D7AAC</string> <string>/Users/johnmci/Documents/SqueakFontsBertFT2/FT2PluginProj/FT2Plugin copy.xcodeproj</string> </array> <key>WindowString</key> <string>4 161 1184 853 0 0 1680 1028 </string> <key>WindowTools</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1065, 489}}</string> <key>RubberWindowFrame</key> <string>602 232 1065 683 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>489pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 494}, {1065, 148}}</string> <key>RubberWindowFrame</key> <string>602 232 1065 683 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>148pt</string> </dict> </array> <key>Proportion</key> <string>642pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94E8549C09339D8200B1FC29</string> <string>941BF5220BDECACE00D361A5</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.build</string> <key>WindowString</key> <string>602 232 1065 683 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>94E8549C09339D8200B1FC29</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {477, 466}}</string> <string>{{477, 0}, {728, 466}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1205, 466}}</string> <string>{{0, 466}, {1205, 233}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1205, 699}}</string> <key>RubberWindowFrame</key> <string>281 172 1205 740 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>699pt</string> </dict> </array> <key>Proportion</key> <string>699pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>948177750C6F7E56000C8E8C</string> <string>1C162984064C10D400B95A72</string> <string>948177760C6F7E56000C8E8C</string> <string>948177770C6F7E56000C8E8C</string> <string>948177780C6F7E56000C8E8C</string> <string>948177790C6F7E56000C8E8C</string> <string>9481777A0C6F7E56000C8E8C</string> <string>9481777B0C6F7E56000C8E8C</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debug</string> <key>WindowString</key> <string>281 172 1205 740 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1108, 288}}</string> <key>RubberWindowFrame</key> <string>181 128 1108 722 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>1108pt</string> </dict> </array> <key>Proportion</key> <string>288pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 293}, {1108, 388}}</string> <key>RubberWindowFrame</key> <string>181 128 1108 722 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>388pt</string> </dict> </array> <key>Proportion</key> <string>681pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>947C55DA0C03365B003F76BD</string> <string>947C55DB0C03365B003F76BD</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>181 128 1108 722 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {440, 358}}</string> <key>RubberWindowFrame</key> <string>655 401 440 400 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>358pt</string> </dict> </array> <key>Proportion</key> <string>359pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>949BB2980932C81E00684056</string> <string>941C75580C066DB6006D7AAC</string> <string>1C78EAAC065D492600B07095</string> </array> <key>WindowString</key> <string>655 401 440 400 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>949BB2980932C81E00684056</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.run</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>LauncherConfigVersion</key> <string>3</string> <key>PBXProjectModuleGUID</key> <string>1CD0528B0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Run</string> <key>Runner</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {493, 167}}</string> <string>{{0, 176}, {493, 267}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {405, 443}}</string> <string>{{414, 0}, {514, 443}}</string> </array> </dict> </dict> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {460, 159}}</string> <key>RubberWindowFrame</key> <string>316 696 459 200 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXRunSessionModule</string> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Name</key> <string>Run Log</string> <key>ServiceClasses</key> <array> <string>PBXRunSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C0AD2B3069F1EA900FABCE6</string> <string>1C0AD2B4069F1EA900FABCE6</string> <string>1CD0528B0623707200166675</string> <string>1C0AD2B5069F1EA900FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.run</string> <key>WindowString</key> <string>316 696 459 200 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C0AD2B3069F1EA900FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>79 552 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>79 552 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>2</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>941C75590C066DB6006D7AAC</string> <string>941C755A0C066DB6006D7AAC</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpoints</string> <key>WindowString</key> <string>79 552 744 409 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>941C75590C066DB6006D7AAC</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimator</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/johnmci.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>94B1A5F10D4496030012B20F</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>944067E810E6ACE300353B27</string> <key>PBXProjectModuleLabel</key> <string>fttypes.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>944067E910E6ACE300353B27</string> <key>PBXProjectModuleLabel</key> <string>fttypes.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9460BC771116DA46003C837E</string> <key>history</key> <array> <string>944067EC10E6ACE300353B27</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1326, 913}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>15 69 1326 954 0 0 1680 1028 </string> </dict> </dict> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>944067EE10E6ACE300353B27</string> <key>PBXProjectModuleLabel</key> <string>freetype.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>944067EF10E6ACE300353B27</string> <key>PBXProjectModuleLabel</key> <string>freetype.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9460BC791116DA46003C837E</string> <key>history</key> <array> <string>944067F210E6ACE300353B27</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1326, 913}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>15 69 1326 954 0 0 1680 1028 </string> </dict> </dict> </array> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>326</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>4CA7E553092CC67E0044FE85</string> <string>4CA7E552092CC66D0044FE85</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>25</integer> <integer>24</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {326, 919}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {343, 937}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>326</real> </array> <key>RubberWindowFrame</key> <string>306 50 1353 978 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>343pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9460BC741116DA46003C837E</string> <key>history</key> <array> <string>9495AC950ACA07A100D58F66</string> <string>941BF5340BDECAEA00D361A5</string> <string>94F6F5970D86101D00E75319</string> <string>9467D0D10E7BC0020031C57C</string> <string>94C1A1310F3771F500A2AC5E</string> <string>9433FBBF10DA2F6900405B56</string> <string>9480105710DEFB9C001E390E</string> <string>948010CC10DF048B001E390E</string> <string>9440665810E5ADDB00353B27</string> <string>944067E510E6ACE300353B27</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1005, 793}}</string> <key>RubberWindowFrame</key> <string>306 50 1353 978 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>793pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 798}, {1005, 139}}</string> <key>RubberWindowFrame</key> <string>306 50 1353 978 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>139pt</string> </dict> </array> <key>Proportion</key> <string>1005pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>9460BC751116DA46003C837E</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>9460BC761116DA46003C837E</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>286710342.34468597</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>94F6F4C60D85FFD500E75319</string> <string>1CD10A99069EF8BA00B06720</string> <string>944067EE10E6ACE300353B27</string> <string>944067E810E6ACE300353B27</string> <string>/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj</string> </array> <key>WindowString</key> <string>306 50 1353 978 0 0 1680 1028 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1219, 220}}</string> <key>RubberWindowFrame</key> <string>111 283 1219 701 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>220pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 225}, {1219, 435}}</string> <key>RubberWindowFrame</key> <string>111 283 1219 701 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>435pt</string> </dict> </array> <key>Proportion</key> <string>660pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94F6F4C60D85FFD500E75319</string> <string>9460BC7B1116DA46003C837E</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowString</key> <string>111 283 1219 701 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>94F6F4C60D85FFD500E75319</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {489, 478}}</string> <string>{{489, 0}, {909, 478}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1398, 478}}</string> <string>{{0, 478}, {1398, 449}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1398, 927}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>217</real> <string>Value</string> <real>178</real> <string>Summary</string> <real>489</real> </array> <key>Frame</key> <string>{{489, 0}, {909, 478}}</string> <key>RubberWindowFrame</key> <string>260 60 1398 968 0 0 1680 1028 </string> </dict> <key>RubberWindowFrame</key> <string>260 60 1398 968 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>927pt</string> </dict> </array> <key>Proportion</key> <string>927pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>9460BC7C1116DA46003C837E</string> <string>1C162984064C10D400B95A72</string> <string>9460BC7D1116DA46003C837E</string> <string>9460BC7E1116DA46003C837E</string> <string>9460BC7F1116DA46003C837E</string> <string>9460BC801116DA46003C837E</string> <string>9460BC811116DA46003C837E</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>260 60 1398 968 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>FT2Plugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1208, 526}}</string> <key>RubberWindowFrame</key> <string>333 35 1208 930 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>1208pt</string> </dict> </array> <key>Proportion</key> <string>526pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 531}, {1208, 358}}</string> <key>RubberWindowFrame</key> <string>333 35 1208 930 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>358pt</string> </dict> </array> <key>Proportion</key> <string>889pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>9440665510E5ADC100353B27</string> <string>9440665610E5ADC100353B27</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>333 35 1208 930 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1563, 702}}</string> <key>RubberWindowFrame</key> <string>5 197 1563 743 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>702pt</string> </dict> </array> <key>Proportion</key> <string>702pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>9440665710E5ADC100353B27</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>5 197 1563 743 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>31 162 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>31 162 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9440671910E5B9EE00353B27</string> <string>9440671A10E5B9EE00353B27</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>31 162 744 409 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9440671910E5B9EE00353B27</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 4C2DFB1309335838008B95AB /* PkgInfo */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1024, 457}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {1024, 457}}"; sepNavWindowFrame = "{{15, 4}, {1044, 869}}"; }; }; 4CA7E52C092CC14E0044FE85 /* FT2Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {956, 23972}}"; sepNavSelRange = "{1145, 0}"; sepNavVisRange = "{0, 1838}"; sepNavVisRect = "{{0, 12144}, {795, 666}}"; sepNavWindowFrame = "{{38, 55}, {772, 797}}"; }; }; 4CA7E530092CC16B0044FE85 /* Info-FT2Plugin.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {733, 668}}"; sepNavSelRange = "{637, 0}"; sepNavVisRect = "{{0, 0}, {733, 668}}"; sepNavWindowFrame = "{{61, 34}, {772, 797}}"; }; }; 4CA7E550092CC6680044FE85 /* ft2build.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {787, 770}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 3590}"; sepNavVisRect = "{{0, 0}, {719, 496}}"; sepNavWindowFrame = "{{15, 68}, {980, 805}}"; }; }; 4CED2BBF08EC3935007BDF80 /* sqVirtualMachine.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {781, 4862}}"; sepNavSelRange = "{1000, 20}"; sepNavVisRange = "{526, 2209}"; sepNavVisRect = "{{0, 0}, {491, 512}}"; sepNavWindowFrame = "{{61, 36}, {828, 795}}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Deployment; activeExecutable = 949BB27E0932C7DF00684056 /* SqueakVM */; activeSDKPreference = macosx10.5; activeTarget = 942103F2084F50DF006A0FD2 /* FT2Plugin */; addToTargets = ( 942103F2084F50DF006A0FD2 /* FT2Plugin */, ); breakpoints = ( ); codeSenseManager = 949BAFE809326DA600684056 /* Code sense */; executables = ( 949BB27E0932C7DF00684056 /* SqueakVM */, ); perUserDictionary = { "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_ContinueID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 210, 20, 110, 109, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXBreakpointsDataSource_ActionID, PBXBreakpointsDataSource_TypeID, PBXBreakpointsDataSource_BreakpointID, PBXBreakpointsDataSource_UseID, PBXBreakpointsDataSource_LocationID, PBXBreakpointsDataSource_ConditionID, PBXBreakpointsDataSource_ContinueID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 666, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 766, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 792, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 726, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 286710319; PBXWorkspaceStateSaveDate = 286710319; }; perUserProjectItems = { 941BF5340BDECAEA00D361A5 /* PBXTextBookmark */ = 941BF5340BDECAEA00D361A5 /* PBXTextBookmark */; 9433FBBF10DA2F6900405B56 /* PBXTextBookmark */ = 9433FBBF10DA2F6900405B56 /* PBXTextBookmark */; 9440665810E5ADDB00353B27 /* PBXTextBookmark */ = 9440665810E5ADDB00353B27 /* PBXTextBookmark */; 944067E510E6ACE300353B27 /* PBXTextBookmark */ = 944067E510E6ACE300353B27 /* PBXTextBookmark */; 944067EC10E6ACE300353B27 /* PBXTextBookmark */ = 944067EC10E6ACE300353B27 /* PBXTextBookmark */; 944067F210E6ACE300353B27 /* PBXTextBookmark */ = 944067F210E6ACE300353B27 /* PBXTextBookmark */; 9460BC741116DA46003C837E /* PBXTextBookmark */ = 9460BC741116DA46003C837E /* PBXTextBookmark */; 9460BC771116DA46003C837E /* PBXTextBookmark */ = 9460BC771116DA46003C837E /* PBXTextBookmark */; 9460BC791116DA46003C837E /* PBXTextBookmark */ = 9460BC791116DA46003C837E /* PBXTextBookmark */; 9467D0D10E7BC0020031C57C /* PBXTextBookmark */ = 9467D0D10E7BC0020031C57C /* PBXTextBookmark */; 9480105710DEFB9C001E390E /* PBXTextBookmark */ = 9480105710DEFB9C001E390E /* PBXTextBookmark */; 948010CC10DF048B001E390E /* PBXTextBookmark */ = 948010CC10DF048B001E390E /* PBXTextBookmark */; 9495AC950ACA07A100D58F66 /* PBXTextBookmark */ = 9495AC950ACA07A100D58F66 /* PBXTextBookmark */; 94C1A1310F3771F500A2AC5E /* PBXTextBookmark */ = 94C1A1310F3771F500A2AC5E /* PBXTextBookmark */; 94F6F5970D86101D00E75319 /* PBXTextBookmark */ = 94F6F5970D86101D00E75319 /* PBXTextBookmark */; }; sourceControlManager = 949BAFE709326DA600684056 /* Source Control */; userBuildSettings = { }; }; 9407B2F910DA271000AE2B55 /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 3471}}"; sepNavSelRange = "{2625, 19}"; sepNavVisRange = "{1025, 3006}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 940E416E09A448AA004715E5 /* macFileNameBits.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {956, 719}}"; sepNavSelRange = "{302, 0}"; sepNavVisRange = "{0, 1284}"; sepNavVisRect = "{{0, 0}, {1024, 457}}"; sepNavWindowFrame = "{{763, 43}, {828, 795}}"; }; }; 941BF43E0BDEB4B700D361A5 /* tttables.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {787, 9254}}"; sepNavSelRange = "{160, 11}"; sepNavVisRange = "{0, 2768}"; sepNavVisRect = "{{0, 0}, {719, 496}}"; sepNavWindowFrame = "{{38, 128}, {841, 874}}"; }; }; 941BF5340BDECAEA00D361A5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4C2DFB1309335838008B95AB /* PkgInfo */; name = "PkgInfo: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 8; vrLoc = 0; }; 941FC1910A75607B0071CA29 /* Squeak VM Opt.app */ = { isa = PBXFileReference; explicitFileType = wrapper.application; name = "Squeak VM Opt.app"; path = ../../../../build/Debug/Squeak.app; sourceTree = SOURCE_ROOT; }; 942103F2084F50DF006A0FD2 /* FT2Plugin */ = { activeExec = 0; }; 9433FBBF10DA2F6900405B56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 74"; rLen = 0; rLoc = 3027; rType = 0; vrLen = 2127; vrLoc = 1864; }; 9440665810E5ADDB00353B27 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940E416E09A448AA004715E5 /* macFileNameBits.c */; name = "macFileNameBits.c: 14"; rLen = 0; rLoc = 302; rType = 0; vrLen = 1284; vrLoc = 0; }; 944067E510E6ACE300353B27 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4CA7E52C092CC14E0044FE85 /* FT2Plugin.c */; name = "FT2Plugin.c: 1"; rLen = 1; rLoc = 64; rType = 0; vrLen = 1708; vrLoc = 0; }; 944067EC10E6ACE300353B27 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 944067ED10E6ACE300353B27 /* fttypes.h */; name = "fttypes.h: 579"; rLen = 48; rLoc = 34831; rType = 0; vrLen = 2881; vrLoc = 32095; }; 944067ED10E6ACE300353B27 /* fttypes.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fttypes.h; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fttypes.h"; sourceTree = "<absolute>"; }; 944067F210E6ACE300353B27 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 944067F310E6ACE300353B27 /* freetype.h */; name = "freetype.h: 3020"; rLen = 7; rLoc = 187419; rType = 0; vrLen = 4656; vrLoc = 185351; }; 944067F310E6ACE300353B27 /* freetype.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = freetype.h; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/freetype.h"; sourceTree = "<absolute>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 50427}}"; sepNavSelRange = "{187419, 7}"; sepNavVisRange = "{185351, 4578}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1651}}"; sepNavSelRange = "{3027, 0}"; sepNavVisRange = "{1864, 2127}"; sepNavVisRect = "{{0, 1209}, {1067, 256}}"; }; }; 9460BC741116DA46003C837E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4CA7E52C092CC14E0044FE85 /* FT2Plugin.c */; name = "FT2Plugin.c: 45"; rLen = 0; rLoc = 1145; rType = 0; vrLen = 1838; vrLoc = 0; }; 9460BC771116DA46003C837E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9460BC781116DA46003C837E /* fttypes.h */; name = "fttypes.h: 579"; rLen = 48; rLoc = 34831; rType = 0; vrLen = 2959; vrLoc = 32017; }; 9460BC781116DA46003C837E /* fttypes.h */ = { isa = PBXFileReference; name = fttypes.h; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fttypes.h"; sourceTree = "<absolute>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 7865}}"; sepNavSelRange = "{34831, 48}"; sepNavVisRange = "{32017, 2959}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9460BC791116DA46003C837E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9460BC7A1116DA46003C837E /* freetype.h */; name = "freetype.h: 3020"; rLen = 7; rLoc = 187419; rType = 0; vrLen = 4578; vrLoc = 185351; }; 9460BC7A1116DA46003C837E /* freetype.h */ = { isa = PBXFileReference; name = freetype.h; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/freetype.h"; sourceTree = "<absolute>"; }; 9467D0D10E7BC0020031C57C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941BF43E0BDEB4B700D361A5 /* tttables.h */; name = "tttables.h: 3"; rLen = 11; rLoc = 160; rType = 0; vrLen = 2768; vrLoc = 0; }; 9480105710DEFB9C001E390E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949BB01909327CC500684056 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 95"; rLen = 0; rLoc = 3934; rType = 0; vrLen = 3568; vrLoc = 2563; }; 948010CC10DF048B001E390E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949BB01709327C9D00684056 /* interp.h */; name = "interp.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 697; vrLoc = 0; }; 9495AC950ACA07A100D58F66 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4CA7E530092CC16B0044FE85 /* Info-FT2Plugin.plist */; name = "Info-FT2Plugin.plist: 26"; rLen = 0; rLoc = 877; rType = 0; vrLen = 900; vrLoc = 0; }; 949BAFE709326DA600684056 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; scmType = ""; }; 949BAFE809326DA600684056 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 949BB01709327C9D00684056 /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {968, 635}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 697}"; }; }; 949BB01909327CC500684056 /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {968, 2288}}"; sepNavSelRange = "{3934, 0}"; sepNavVisRange = "{2563, 3568}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 949BB07A09328C1500684056 /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1067, 5866}}"; sepNavSelRange = "{5164, 23}"; sepNavVisRect = "{{0, 1601}, {1067, 256}}"; }; }; 949BB23909328D7E00684056 /* macFileNameBits.c */ = { isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = macFileNameBits.c; path = /Users/johnmci/Documents/SqueakFontsBertFT2/FT2PluginProj/macFileNameBits.c; sourceTree = "<absolute>"; }; 949BB27E0932C7DF00684056 /* SqueakVM */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; launchableReference = 941FC1910A75607B0071CA29 /* Squeak VM Opt.app */; libgmallocEnabled = 0; name = SqueakVM; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); variableFormatDictionary = { }; }; 94C1A1310F3771F500A2AC5E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949BB23909328D7E00684056 /* macFileNameBits.c */; name = "macFileNameBits.c: 17"; rLen = 0; rLoc = 427; rType = 0; vrLen = 1280; vrLoc = 0; }; 94F6F5970D86101D00E75319 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4CA7E550092CC6680044FE85 /* ft2build.h */; name = "ft2build.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 3590; vrLoc = 0; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 42; objects = { /* Begin PBXBuildFile section */ 040F1BFC12CD18FF008BA0CB /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 040F1BFB12CD18FF008BA0CB /* Info.plist */; }; 040F1C0912CD1991008BA0CB /* UnixOSProcessPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F1C0812CD1991008BA0CB /* UnixOSProcessPlugin.c */; }; 040F1C2E12CD1B19008BA0CB /* SocketPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 040F1C2D12CD1B19008BA0CB /* SocketPlugin.h */; }; 040F1C3212CD1B51008BA0CB /* FilePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 040F1C3112CD1B51008BA0CB /* FilePlugin.h */; }; 040F1C4412CD1C70008BA0CB /* sqaio.h in Headers */ = {isa = PBXBuildFile; fileRef = 040F1C4312CD1C70008BA0CB /* sqaio.h */; }; 4C2DFB2D093359A8008B95AB /* PkgInfo in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C2DFB1309335838008B95AB /* PkgInfo */; }; 4CA7E551092CC6680044FE85 /* ft2build.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA7E550092CC6680044FE85 /* ft2build.h */; }; 9407B2FA10DA271000AE2B55 /* sqVirtualMachine.h in Headers */ = {isa = PBXBuildFile; fileRef = 9407B2F910DA271000AE2B55 /* sqVirtualMachine.h */; }; 942103F9084F50DF006A0FD2 /* sqConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 944E9BEC05E91D17003F0BED /* sqConfig.h */; }; 942103FB084F50DF006A0FD2 /* sqPlatformSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */; }; 942103FD084F50DF006A0FD2 /* SqueakPlugin.icns in Resources */ = {isa = PBXBuildFile; fileRef = 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */; }; 949BB00D09327C3300684056 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 949BB00C09327C3300684056 /* config.h */; }; 949BB01809327C9D00684056 /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 949BB01709327C9D00684056 /* interp.h */; }; 949BB01A09327CC500684056 /* sqMemoryAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 949BB01909327CC500684056 /* sqMemoryAccess.h */; }; 949BB07B09328C1500684056 /* sq.h in Headers */ = {isa = PBXBuildFile; fileRef = 949BB07A09328C1500684056 /* sq.h */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 94D066A8084F978100D2CF17 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.gcc.4_2; fileType = sourcecode.c; isEditable = 1; outputFiles = ( ); }; /* End PBXBuildRule section */ /* Begin PBXCopyFilesBuildPhase section */ 4C2DFB2B09335970008B95AB /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 12; dstPath = ..; dstSubfolderSpec = 7; files = ( 4C2DFB2D093359A8008B95AB /* PkgInfo in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 040F1BFB12CD18FF008BA0CB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 040F1C0812CD1991008BA0CB /* UnixOSProcessPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UnixOSProcessPlugin.c; sourceTree = "<group>"; }; 040F1C2D12CD1B19008BA0CB /* SocketPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SocketPlugin.h; path = ../../../Cross/plugins/SocketPlugin/SocketPlugin.h; sourceTree = SOURCE_ROOT; }; 040F1C3112CD1B51008BA0CB /* FilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FilePlugin.h; path = ../../../Cross/plugins/FilePlugin/FilePlugin.h; sourceTree = SOURCE_ROOT; }; 040F1C4312CD1C70008BA0CB /* sqaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqaio.h; path = ../../../unix/vm/sqaio.h; sourceTree = SOURCE_ROOT; }; 4C2DFB1309335838008B95AB /* PkgInfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = PkgInfo; sourceTree = "<group>"; }; 4CA7E550092CC6680044FE85 /* ft2build.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ft2build.h; path = /usr/X11R6/include/ft2build.h; sourceTree = "<absolute>"; }; 4CF9AFE9092E090000DBD378 /* UnixOSProcessPlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnixOSProcessPlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakPlugin.icns; path = ../../vm/OSX/SqueakPlugin.icns; sourceTree = "<group>"; }; 9407B2F910DA271000AE2B55 /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = ../../../Cross/vm/sqVirtualMachine.h; sourceTree = SOURCE_ROOT; }; 944E9BEC05E91D17003F0BED /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = ../../vm/iPhone/sqConfig.h; sourceTree = "<group>"; }; 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = ../../vm/iPhone/sqPlatformSpecific.h; sourceTree = "<group>"; }; 949BB00C09327C3300684056 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../../vm/iPhone/config.h; sourceTree = "<group>"; }; 949BB01709327C9D00684056 /* interp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../../../../src/vm/interp.h; sourceTree = "<group>"; }; 949BB01909327CC500684056 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = ../../../Cross/vm/sqMemoryAccess.h; sourceTree = "<group>"; }; 949BB07A09328C1500684056 /* sq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sq.h; path = ../../../Cross/vm/sq.h; sourceTree = "<group>"; }; 949BB07C09328C9D00684056 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; 949BB08109328CD500684056 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 94210404084F50DF006A0FD2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 4CA7E552092CC66D0044FE85 /* Headers */ = { isa = PBXGroup; children = ( 9407B2F910DA271000AE2B55 /* sqVirtualMachine.h */, 949BB07A09328C1500684056 /* sq.h */, 949BB01909327CC500684056 /* sqMemoryAccess.h */, 949BB01709327C9D00684056 /* interp.h */, 949BB00C09327C3300684056 /* config.h */, 4CA7E550092CC6680044FE85 /* ft2build.h */, 944E9BEC05E91D17003F0BED /* sqConfig.h */, 944E9BEE05E91D17003F0BED /* sqPlatformSpecific.h */, ); name = Headers; sourceTree = "<group>"; }; 4CA7E553092CC67E0044FE85 /* Libraries */ = { isa = PBXGroup; children = ( 949BB08109328CD500684056 /* Carbon.framework */, 949BB07C09328C9D00684056 /* CoreFoundation.framework */, ); name = Libraries; sourceTree = "<group>"; }; 66DF6BFE01D7DCEA00A80119 = { isa = PBXGroup; children = ( 040F1BFB12CD18FF008BA0CB /* Info.plist */, 4C2DFB1309335838008B95AB /* PkgInfo */, 66DF6BFF01D7DCEA00A80119 /* source */, 4CA7E553092CC67E0044FE85 /* Libraries */, 4CA7E552092CC66D0044FE85 /* Headers */, 66DF6C3901D7DCEA00A80119 /* resources */, 66DF6C4501D7DEEE00A80119 /* Products */, ); sourceTree = "<group>"; }; 66DF6BFF01D7DCEA00A80119 /* source */ = { isa = PBXGroup; children = ( 040F1C4312CD1C70008BA0CB /* sqaio.h */, 040F1C3112CD1B51008BA0CB /* FilePlugin.h */, 040F1C2D12CD1B19008BA0CB /* SocketPlugin.h */, 040F1C0812CD1991008BA0CB /* UnixOSProcessPlugin.c */, ); name = source; path = ../../../../src/plugins/UnixOSProcessPlugin; sourceTree = "<group>"; }; 66DF6C3901D7DCEA00A80119 /* resources */ = { isa = PBXGroup; children = ( 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */, ); name = resources; sourceTree = "<group>"; }; 66DF6C4501D7DEEE00A80119 /* Products */ = { isa = PBXGroup; children = ( 4CF9AFE9092E090000DBD378 /* UnixOSProcessPlugin.bundle */, ); name = Products; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 942103F3084F50DF006A0FD2 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 942103F9084F50DF006A0FD2 /* sqConfig.h in Headers */, 942103FB084F50DF006A0FD2 /* sqPlatformSpecific.h in Headers */, 4CA7E551092CC6680044FE85 /* ft2build.h in Headers */, 949BB00D09327C3300684056 /* config.h in Headers */, 949BB01809327C9D00684056 /* interp.h in Headers */, 949BB01A09327CC500684056 /* sqMemoryAccess.h in Headers */, 949BB07B09328C1500684056 /* sq.h in Headers */, 9407B2FA10DA271000AE2B55 /* sqVirtualMachine.h in Headers */, 040F1C2E12CD1B19008BA0CB /* SocketPlugin.h in Headers */, 040F1C3212CD1B51008BA0CB /* FilePlugin.h in Headers */, 040F1C4412CD1C70008BA0CB /* sqaio.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 942103F2084F50DF006A0FD2 /* UnixOSProcessPlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 949BAFDF09326DA600684056 /* Build configuration list for PBXNativeTarget "UnixOSProcessPlugin" */; buildPhases = ( 942103F3084F50DF006A0FD2 /* Headers */, 942103FC084F50DF006A0FD2 /* Resources */, 4C2DFB2B09335970008B95AB /* CopyFiles */, 942103FF084F50DF006A0FD2 /* Sources */, 94210404084F50DF006A0FD2 /* Frameworks */, 94210406084F50DF006A0FD2 /* Rez */, ); buildRules = ( 94D066A8084F978100D2CF17 /* PBXBuildRule */, ); dependencies = ( ); name = UnixOSProcessPlugin; productName = "PrintJobPlugin Debug"; productReference = 4CF9AFE9092E090000DBD378 /* UnixOSProcessPlugin.bundle */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 66DF6BFD01D7DCEA00A80119 /* Project object */ = { isa = PBXProject; buildConfigurationList = 949BAFE309326DA600684056 /* Build configuration list for PBXProject "UnixOSProcessPlugin" */; compatibilityVersion = "Xcode 2.4"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 942103F2084F50DF006A0FD2 /* UnixOSProcessPlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 942103FC084F50DF006A0FD2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 942103FD084F50DF006A0FD2 /* SqueakPlugin.icns in Resources */, 040F1BFC12CD18FF008BA0CB /* Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ 94210406084F50DF006A0FD2 /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 942103FF084F50DF006A0FD2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 040F1C0912CD1991008BA0CB /* UnixOSProcessPlugin.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 949BAFE009326DA600684056 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; COPY_PHASE_STRIP = YES; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = Info.plist; ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-undefined", dynamic_lookup, ); PRODUCT_NAME = UnixOSProcessPlugin; SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Development; }; 949BAFE109326DA600684056 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = Info.plist; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-flat_namespace", "-undefined", warning, ); PER_ARCH_CFLAGS_i386 = "-O3 -Wall"; PER_ARCH_CFLAGS_ppc = "-O3 -fPIC"; PRELINK_LIBS = ""; PRODUCT_NAME = UnixOSProcessPlugin; SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; ZERO_LINK = NO; }; name = Deployment; }; 949BAFE209326DA600684056 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( ppc, i386, ); GCC_OPTIMIZATION_LEVEL = 2; GCC_PREPROCESSOR_DEFINITIONS = TARGET_API_MAC_CARBON; HEADER_SEARCH_PATHS = ( /Developer/Headers/FlatCarbon, /usr/X11R6/include/freetype2, ); INFOPLIST_FILE = "Info-FT2Plugin.plist"; LIBRARY_SEARCH_PATHS = ( "$(SRCROOT)", "$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/usr/X11R6/lib", "$(SRCROOT)/../fonts/freetype-2.1.10/objs", "$(SRCROOT)/../fonts/freetype-2.1.10/objs/intel", ); OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = FT2Plugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Default; }; 949BAFE409326DA600684056 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { GENERATE_MASTER_OBJECT_FILE = NO; SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; }; name = Development; }; 949BAFE509326DA600684056 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { GENERATE_MASTER_OBJECT_FILE = NO; OTHER_LDFLAGS = ""; PRELINK_FLAGS = ""; PRELINK_LIBS = ""; SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; }; name = Deployment; }; 949BAFE609326DA600684056 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { GENERATE_MASTER_OBJECT_FILE = NO; SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 949BAFDF09326DA600684056 /* Build configuration list for PBXNativeTarget "UnixOSProcessPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 949BAFE009326DA600684056 /* Development */, 949BAFE109326DA600684056 /* Deployment */, 949BAFE209326DA600684056 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; 949BAFE309326DA600684056 /* Build configuration list for PBXProject "UnixOSProcessPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 949BAFE409326DA600684056 /* Development */, 949BAFE509326DA600684056 /* Deployment */, 949BAFE609326DA600684056 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 66DF6BFD01D7DCEA00A80119 /* Project object */; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/MAC.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>040F1A2512CD1578008BA0CB</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66B8BC570381F53800A8011A</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>11</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 445}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 463}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>20 260 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMemoryAccess.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMemoryAccess.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>040F1A3512CD16D0008BA0CB</string> <key>history</key> <array> <string>040F1A2F12CD16D0008BA0CB</string> <string>040F1A3012CD16D0008BA0CB</string> <string>040F1A3112CD16D0008BA0CB</string> <string>040F1A3212CD16D0008BA0CB</string> <string>040F1A3312CD16D0008BA0CB</string> <string>040F1A3412CD16D0008BA0CB</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {580, 277}}</string> <key>RubberWindowFrame</key> <string>20 260 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>277pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 282}, {580, 181}}</string> <key>RubberWindowFrame</key> <string>20 260 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>181pt</string> </dict> </array> <key>Proportion</key> <string>580pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>040F1A2312CD1578008BA0CB</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>040F1A2412CD1578008BA0CB</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>040F1A2612CD1578008BA0CB</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.xcodeproj</string> </array> <key>WindowString</key> <string>20 260 788 504 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {500, 218}}</string> <key>RubberWindowFrame</key> <string>191 226 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>218pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 223}, {500, 236}}</string> <key>RubberWindowFrame</key> <string>191 226 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>459pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>040F1A2612CD1578008BA0CB</string> <string>040F1A2712CD1578008BA0CB</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>191 226 500 500 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>040F1A2612CD1578008BA0CB</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugger</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {317, 164}}</string> <string>{{317, 0}, {377, 164}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 164}}</string> <string>{{0, 164}, {694, 216}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 380}}</string> <key>RubberWindowFrame</key> <string>321 238 694 422 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C0AD2AB069F1E9B00FABCE6</string> <string>1C162984064C10D400B95A72</string> <string>1C0AD2AC069F1E9B00FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>321 238 694 422 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.find</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528D0623707200166675</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 167}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>50%</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{8, 0}, {773, 254}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>50%</string> </dict> </array> <key>Proportion</key> <string>428pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>1C530D58069F1CE1000CFCEE</string> <string>1C530D59069F1CE1000CFCEE</string> <string>1CDD528C0622207200134675</string> <string>1C530D5A069F1CE1000CFCEE</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>62 385 781 470 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {650, 250}}</string> <key>RubberWindowFrame</key> <string>516 632 650 250 0 0 1680 1027 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>1C78EAAE065D492600B07095</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>650 41 650 250 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/MAC.pbxuser ================================================ // !$*UTF8*$! { 040F1A2112CD1470008BA0CB /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; }; 040F1A2212CD1470008BA0CB /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 040F1A2A12CD1687008BA0CB /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {519, 245}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 302}"; }; }; 040F1A2B12CD1687008BA0CB /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {537, 2249}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 904}"; }; }; 040F1A2F12CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1A2A12CD1687008BA0CB /* sqConfig.h */; name = "sqConfig.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 302; vrLoc = 0; }; 040F1A3012CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F1A2B12CD1687008BA0CB /* config.h */; name = "config.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 904; vrLoc = 0; }; 040F1A3112CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 870; vrLoc = 0; }; 040F1A3212CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5C0381F66500A8011A /* sq.h */; name = "sq.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 393; vrLoc = 0; }; 040F1A3312CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; name = "sqVirtualMachine.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 510; vrLoc = 0; }; 040F1A3412CD16D0008BA0CB /* PBXBookmark */ = { isa = PBXBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; }; 040F1A3512CD16D0008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 12"; rLen = 0; rLoc = 497; rType = 0; vrLen = 652; vrLoc = 0; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {579, 2210}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 870}"; }; }; 66B8BC5C0381F66500A8011A /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {551, 7254}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 393}"; }; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {519, 3952}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 510}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Development; activeTarget = 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */; addToTargets = ( 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */, ); codeSenseManager = 040F1A2212CD1470008BA0CB /* Code sense */; perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 341, 20, 48.16259765625, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 315429969; PBXWorkspaceStateSaveDate = 315429969; }; perUserProjectItems = { 040F1A2F12CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A2F12CD16D0008BA0CB /* PBXTextBookmark */; 040F1A3012CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A3012CD16D0008BA0CB /* PBXTextBookmark */; 040F1A3112CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A3112CD16D0008BA0CB /* PBXTextBookmark */; 040F1A3212CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A3212CD16D0008BA0CB /* PBXTextBookmark */; 040F1A3312CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A3312CD16D0008BA0CB /* PBXTextBookmark */; 040F1A3412CD16D0008BA0CB /* PBXBookmark */ = 040F1A3412CD16D0008BA0CB /* PBXBookmark */; 040F1A3512CD16D0008BA0CB /* PBXTextBookmark */ = 040F1A3512CD16D0008BA0CB /* PBXTextBookmark */; }; sourceControlManager = 040F1A2112CD1470008BA0CB /* Source Control */; userBuildSettings = { }; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {523, 2314}}"; sepNavSelRange = "{497, 0}"; sepNavVisRange = "{0, 652}"; }; }; 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */ = { activeExec = 0; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/johnmci.mode1 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXRunSessionModule</string> <key>Name</key> <string>Run Log</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>94AF35A4084782DD00FA5ACB</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1</string> <key>MajorVersion</key> <integer>31</integer> <key>MinorVersion</key> <integer>1</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>9446BA210C8126AA005E579E</string> <key>PBXProjectModuleLabel</key> <string>sqMacQuicktimeInteface.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>9446BA220C8126AA005E579E</string> <key>PBXProjectModuleLabel</key> <string>sqMacQuicktimeInteface.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9446BA230C8126AA005E579E</string> <key>history</key> <array> <string>9446BA1D0C7F9A3C005E579E</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1364, 623}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>38 188 1364 664 0 0 1680 1028 </string> </dict> </dict> </array> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-target-popup</string> <string>active-buildstyle-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>buildOrClean</string> <string>build-and-runOrDebug</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>toggle-editor</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>291</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66B8BC570381F53800A8011A</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1CC0EA4004350EF90044410B</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>13</integer> <integer>12</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {291, 687}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {308, 705}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>291</real> </array> <key>RubberWindowFrame</key> <string>573 282 1093 746 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>308pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>SqueakPlugin.icns</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>SqueakPlugin.icns</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9446BA1E0C8126AA005E579E</string> <key>history</key> <array> <string>94F9B20F0AAF9CF20084BAF1</string> <string>94A6D45E0ADEAFC4003E9CBE</string> <string>94A6D4600ADEAFC4003E9CBE</string> <string>94B4E3640B608E950095E823</string> <string>946618740B8CD72500AA8AE3</string> <string>9466187F0B8CD74300AA8AE3</string> <string>94255A010BCAB363006C9CF0</string> </array> <key>prevStack</key> <array> <string>949CD5C6085CC32700EB8605</string> <string>94ECA4AA097E137A00C2C7BA</string> <string>94ECA522097E18C600C2C7BA</string> <string>94ECA680097EC85D00C2C7BA</string> <string>94ECA688097ECFBF00C2C7BA</string> <string>94E73FC10B0052CB0017E7BA</string> <string>94B4E3660B608E950095E823</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {780, 642}}</string> <key>RubberWindowFrame</key> <string>573 282 1093 746 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>642pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 647}, {780, 58}}</string> <key>RubberWindowFrame</key> <string>573 282 1093 746 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>58pt</string> </dict> </array> <key>Proportion</key> <string>780pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>9446BA1F0C8126AA005E579E</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>9446BA200C8126AA005E579E</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.short</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>209689144.27254501</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>/Users/johnmci/Documents/SqueakQuicktimePlugin/SqueakQuicktime copy.xcodeproj</string> <string>9446BA210C8126AA005E579E</string> </array> <key>WindowString</key> <string>573 282 1093 746 0 0 1680 1028 </string> <key>WindowTools</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {879, 326}}</string> <key>RubberWindowFrame</key> <string>91 68 879 795 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>326pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 331}, {879, 423}}</string> <key>RubberWindowFrame</key> <string>91 68 879 795 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>423pt</string> </dict> </array> <key>Proportion</key> <string>754pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94E4F4CD08D0A1CA00B9E724</string> <string>945C091209E8C91000AD1BBC</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.build</string> <key>WindowString</key> <string>91 68 879 795 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>94E4F4CD08D0A1CA00B9E724</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {68, 262}}</string> <string>{{0, 262}, {68, 442}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {68, 704}}</string> <string>{{68, 0}, {1074, 704}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1142, 704}}</string> <key>RubberWindowFrame</key> <string>335 27 1142 745 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>704pt</string> </dict> </array> <key>Proportion</key> <string>704pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>94C7543D09C9DC4E00CA7462</string> <string>1C162984064C10D400B95A72</string> <string>94C7543E09C9DC4E00CA7462</string> <string>94C7543F09C9DC4E00CA7462</string> <string>94C7544009C9DC4E00CA7462</string> <string>94C7544109C9DC4E00CA7462</string> <string>94C7544209C9DC4E00CA7462</string> <string>94C7544309C9DC4E00CA7462</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debug</string> <key>WindowString</key> <string>335 27 1142 745 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>sqMacQuicktimeInteface.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {791, 416}}</string> <key>RubberWindowFrame</key> <string>750 33 791 674 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>791pt</string> </dict> </array> <key>Proportion</key> <string>416pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 421}, {791, 212}}</string> <key>RubberWindowFrame</key> <string>750 33 791 674 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>633pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>94B4E36A0B608E950095E823</string> <string>94B4E36B0B608E950095E823</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>750 33 791 674 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {696, 544}}</string> <key>RubberWindowFrame</key> <string>635 69 696 585 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>544pt</string> </dict> </array> <key>Proportion</key> <string>544pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94ABA92F0858D3A300079BE1</string> <string>9410FB9909AA6FD0002FD7B7</string> <string>1C78EAAC065D492600B07095</string> </array> <key>WindowString</key> <string>635 69 696 585 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>94ABA92F0858D3A300079BE1</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.run</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>LauncherConfigVersion</key> <string>3</string> <key>PBXProjectModuleGUID</key> <string>1CD0528B0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Run</string> <key>Runner</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {493, 167}}</string> <string>{{0, 176}, {493, 267}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {405, 443}}</string> <string>{{414, 0}, {514, 443}}</string> </array> </dict> </dict> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {460, 159}}</string> <key>RubberWindowFrame</key> <string>316 696 459 200 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXRunSessionModule</string> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Proportion</key> <string>159pt</string> </dict> </array> <key>Name</key> <string>Run Log</string> <key>ServiceClasses</key> <array> <string>PBXRunSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C0AD2B3069F1EA900FABCE6</string> <string>1C0AD2B4069F1EA900FABCE6</string> <string>1CD0528B0623707200166675</string> <string>1C0AD2B5069F1EA900FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.run</string> <key>WindowString</key> <string>316 696 459 200 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C0AD2B3069F1EA900FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>2</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpoints</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimator</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {378, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 332}}</string> <key>MembersFrame</key> <string>{{0, 101}, {378, 231}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>101</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>RubberWindowFrame</key> <string>312 384 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>949CD652085CD34000EB8605</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>312 384 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/johnmci.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>94CD97670E87A9D300A81A01</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>944BAB8B0E942CD80008DAC7</string> <key>PBXProjectModuleLabel</key> <string>squeakSUnitTester.m</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>944BAB8C0E942CD80008DAC7</string> <key>PBXProjectModuleLabel</key> <string>squeakSUnitTester.m</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9494083D0E95F46800A2D848</string> <key>history</key> <array> <string>94659C230E955378008D8B0E</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {997, 901}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>662 86 997 942 0 0 1680 1028 </string> </dict> </dict> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>944BAB2B0E941B9C0008DAC7</string> <key>PBXProjectModuleLabel</key> <string>ObjectiveCPlugin.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>944BAB2C0E941B9C0008DAC7</string> <key>PBXProjectModuleLabel</key> <string>ObjectiveCPlugin.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9494083E0E95F46800A2D848</string> <key>history</key> <array> <string>94659C240E955378008D8B0E</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1012, 918}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>739 51 1012 959 0 0 1680 1028 </string> </dict> </dict> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>943C82D00E87E32400A8C956</string> <key>PBXProjectModuleLabel</key> <string>sqUnixObjC.m</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>943C82D10E87E32400A8C956</string> <key>PBXProjectModuleLabel</key> <string>sqUnixObjC.m</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9494083F0E95F46800A2D848</string> <key>history</key> <array> <string>94659C250E955378008D8B0E</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1012, 918}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>63 69 1012 959 0 0 1680 1028 </string> </dict> </dict> </array> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-target-popup</string> <string>active-buildstyle-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>buildOrClean</string> <string>build-and-goOrGo</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>toggle-editor</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>291</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>66DF6BFE01D7DCEA00A80119</string> <string>66B8BC570381F53800A8011A</string> <string>66DF6BFF01D7DCEA00A80119</string> <string>66DF6C3901D7DCEA00A80119</string> <string>66DF6C4501D7DEEE00A80119</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>19</integer> <integer>18</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {291, 894}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {308, 912}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>291</real> </array> <key>RubberWindowFrame</key> <string>214 75 1190 953 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>308pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>CFNetworkErrors.h</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>CFNetworkErrors.h</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9494083B0E95F46800A2D848</string> <key>history</key> <array> <string>94A6D4600ADEAFC4003E9CBE</string> <string>9466187F0B8CD74300AA8AE3</string> <string>94CD975D0E87A9D300A81A01</string> <string>94CD975E0E87A9D300A81A01</string> <string>94CD97C60E87AF8E00A81A01</string> <string>94CD993D0E87B2D700A81A01</string> <string>943C82CA0E87E32400A8C956</string> <string>943C836E0E8828FE00A8C956</string> <string>943C84110E89158B00A8C956</string> <string>94A698220E89A647005A25C0</string> <string>94A698240E89A647005A25C0</string> <string>94D209B80E8AB02E0083E28B</string> <string>94D20B110E8BCDB40083E28B</string> <string>94E6590A0E9043640088C3B5</string> <string>94E6590C0E9043640088C3B5</string> <string>94E659C70E9092870088C3B5</string> <string>94659C130E9545F2008D8B0E</string> <string>94659C140E9545F2008D8B0E</string> <string>9494081F0E95F19600A2D848</string> <string>949408200E95F19600A2D848</string> <string>949408210E95F19600A2D848</string> </array> <key>prevStack</key> <array> <string>949CD5C6085CC32700EB8605</string> <string>94ECA4AA097E137A00C2C7BA</string> <string>94ECA522097E18C600C2C7BA</string> <string>94ECA688097ECFBF00C2C7BA</string> <string>94CD97620E87A9D300A81A01</string> <string>94CD993F0E87B2D700A81A01</string> <string>943C82CE0E87E32400A8C956</string> <string>943C82EE0E8803BA00A8C956</string> <string>943C830C0E88267200A8C956</string> <string>943C836F0E8828FE00A8C956</string> <string>94D20AE50E8BC5CF0083E28B</string> <string>94D20AE60E8BC5CF0083E28B</string> <string>94D20B2F0E8BDD5B0083E28B</string> <string>94E659110E9043640088C3B5</string> <string>94E659130E9043640088C3B5</string> <string>949408230E95F19600A2D848</string> <string>949408240E95F19600A2D848</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {877, 849}}</string> <key>RubberWindowFrame</key> <string>214 75 1190 953 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>849pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 854}, {877, 58}}</string> <key>RubberWindowFrame</key> <string>214 75 1190 953 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>58pt</string> </dict> </array> <key>Proportion</key> <string>877pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>949408260E95F19600A2D848</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>949408270E95F19600A2D848</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>244708456.54791301</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>943C82D00E87E32400A8C956</string> <string>944BAB2B0E941B9C0008DAC7</string> <string>944BAB8B0E942CD80008DAC7</string> <string>94CD97520E87A82A00A81A01</string> <string>/Users/johnmci/Documents/SqueakObjectiveCPlugin/SqueakObjectiveC.xcodeproj</string> </array> <key>WindowString</key> <string>214 75 1190 953 0 0 1680 1028 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>ObjectiveCPlugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {952, 541}}</string> <key>RubberWindowFrame</key> <string>568 71 952 957 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>541pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBuildLogShowsTranscriptDefaultKey</key> <string>{{0, 252}, {952, 118}}</string> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 546}, {952, 370}}</string> <key>RubberWindowFrame</key> <string>568 71 952 957 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>370pt</string> </dict> </array> <key>Proportion</key> <string>916pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94CD97520E87A82A00A81A01</string> <string>949407F50E95F0B000A2D848</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowString</key> <string>568 71 952 957 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>94CD97520E87A82A00A81A01</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {786, 373}}</string> <string>{{786, 0}, {356, 373}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1142, 373}}</string> <string>{{0, 373}, {1142, 331}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1142, 704}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>120</real> <string>Value</string> <real>85</real> <string>Summary</string> <real>126</real> </array> <key>Frame</key> <string>{{786, 0}, {356, 373}}</string> <key>RubberWindowFrame</key> <string>517 103 1142 745 0 0 1680 1028 </string> </dict> <key>RubberWindowFrame</key> <string>517 103 1142 745 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>704pt</string> </dict> </array> <key>Proportion</key> <string>704pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>949407F60E95F0B000A2D848</string> <string>1C162984064C10D400B95A72</string> <string>949407F70E95F0B000A2D848</string> <string>949407F80E95F0B000A2D848</string> <string>949407F90E95F0B000A2D848</string> <string>949407FA0E95F0B000A2D848</string> <string>949407FB0E95F0B000A2D848</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>517 103 1142 745 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>ObjectiveCPlugin.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {791, 416}}</string> <key>RubberWindowFrame</key> <string>990 57 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>791pt</string> </dict> </array> <key>Proportion</key> <string>416pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 421}, {791, 212}}</string> <key>RubberWindowFrame</key> <string>990 57 791 674 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>633pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>944BAB360E941B9C0008DAC7</string> <string>944BAB370E941B9C0008DAC7</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>990 57 791 674 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {696, 544}}</string> <key>RubberWindowFrame</key> <string>840 77 696 585 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>544pt</string> </dict> </array> <key>Proportion</key> <string>544pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>944BAB590E9425D90008DAC7</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>840 77 696 585 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.09500122070312</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> <string>1C3E0DCA080725EA00A55177</string> <string>1C3E0DCA080725EA00A55177</string> <string>1C3E0DCC080725EA11A45113</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>1</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>424 558 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>424 558 744 409 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94E659030E90432E0088C3B5</string> <string>94E659040E90432E0088C3B5</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>424 558 744 409 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>94E659030E90432E0088C3B5</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <true/> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {378, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 332}}</string> <key>MembersFrame</key> <string>{{0, 101}, {378, 231}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>101</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>RubberWindowFrame</key> <string>312 384 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>312 384 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 66B8BC580381F61C00A8011A /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {903, 509}}"; sepNavSelRange = "{111, 22}"; sepNavVisRange = "{0, 345}"; }; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1056, 1820}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1796}"; sepNavVisRect = "{{0, 0}, {609, 594}}"; }; }; 66B8BC5C0381F66500A8011A /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 6117}}"; sepNavSelRange = "{16850, 24}"; sepNavVisRect = "{{0, 5935}, {740, 73}}"; }; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {731, 2954}}"; sepNavSelRange = "{2891, 0}"; sepNavVisRange = "{1476, 2084}"; sepNavVisRect = "{{0, 1587}, {711, 429}}"; sepNavWindowFrame = "{{84, 252}, {750, 558}}"; }; }; 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */ = { uiCtxt = { sepNavWindowFrame = "{{15, 153}, {1364, 720}}"; }; }; 66DF6BFD01D7DCEA00A80119 /* Project object */ = { activeBuildConfigurationName = Deployment; activeExecutable = 94ABA91E0858D35E00079BE1 /* Squeak */; activeTarget = 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */; addToTargets = ( 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */, ); breakpoints = ( 94A8BB7D0E91EB65007DDB7F /* ObjectiveCPlugin.c:1104 */, 944BAB3F0E9421B10008DAC7 /* ObjectiveCPlugin.c:357 */, 944BAB5D0E9426DB0008DAC7 /* ObjectiveCPlugin.c:360 */, 944BAB670E94277D0008DAC7 /* ObjectiveCPlugin.c:1220 */, ); codeSenseManager = 9444E60E06E7B8740063F6CC /* Code sense */; executables = ( 94ABA91E0858D35E00079BE1 /* Squeak */, ); expressions = ( buffer, ); perUserDictionary = { "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 198, 20, 99, 99, 29, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXBreakpointsDataSource_ActionID, PBXBreakpointsDataSource_TypeID, PBXBreakpointsDataSource_BreakpointID, PBXBreakpointsDataSource_UseID, PBXBreakpointsDataSource_LocationID, PBXBreakpointsDataSource_ConditionID, PBXBreakpointsDataSource_IgnoreCountID, PBXBreakpointsDataSource_ContinueID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 200, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 429, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 638, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 425.2085, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 598, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 244707468; PBXPrepackagedSmartGroups_v2 = ( { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; activationKey = OldTargetSmartGroup; clz = PBXTargetSmartGroup; description = "Displays all targets of the project."; globalID = 1C37FABC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXTargetSmartGroup2; description = "Displays all targets of the project as well as nested build phases."; globalID = 1C37FBAC04509CD000000102; name = Targets; preferences = { image = Targets; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXExecutablesSmartGroup; description = "Displays all executables of the project."; globalID = 1C37FAAC04509CD000000102; name = Executables; preferences = { image = Executable; }; }, { " PBXTransientLocationAtTop " = bottom; absolutePathToBundle = ""; clz = PBXErrorsWarningsSmartGroup; description = "Displays files with errors or warnings."; globalID = 1C08E77C0454961000C914BD; name = "Errors and Warnings"; preferences = { fnmatch = ""; image = WarningsErrors; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = 1CC0EA4004350EF90044410B; name = "Implementation Files"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "This group displays Interface Builder NIB Files."; globalID = 1CC0EA4004350EF90041110B; name = "NIB Files"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXFindSmartGroup; description = "Displays Find Results."; globalID = 1C37FABC05509CD000000102; name = "Find Results"; preferences = { image = spyglass; }; }, { PBXTransientLocationAtTop = no; absolutePathToBundle = ""; clz = PBXBookmarksSmartGroup; description = "Displays Project Bookmarks."; globalID = 1C37FABC05539CD112110102; name = Bookmarks; preferences = { image = Bookmarks; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = XCSCMSmartGroup; description = "Displays files with interesting SCM status."; globalID = E2644B35053B69B200211256; name = SCM; preferences = { image = PBXRepository; isLeaf = 0; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXSymbolsSmartGroup; description = "Displays all symbols for the project."; globalID = 1C37FABC04509CD000100104; name = "Project Symbols"; preferences = { image = ProjectSymbols; isLeaf = 1; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Filter SmartGroup"; preferences = { canSave = 1; fnmatch = "*.nib"; image = SmartFolder; isLeaf = 0; recursive = 1; regex = ""; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; absolutePathToBundle = ""; clz = PBXFilenameSmartGroup; description = "Filters items in a given group (potentially recursively) based on matching the name with the regular expression of the filter."; globalID = PBXTemplateMarker; name = "Simple Regular Expression SmartGroup"; preferences = { canSave = 1; fnmatch = ""; image = SmartFolder; isLeaf = 0; recursive = 1; regex = "?*\\.[mcMC]"; root = "<PROJECT>"; }; }, { PBXTransientLocationAtTop = bottom; clz = XDDesignSmartGroup; description = "Displays Xdesign models"; globalID = 2E4A936305E6979E00701470; name = Design; preferences = { image = Design; isLeaf = 0; }; }, ); PBXWorkspaceContents = ( { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 9, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( 66DF6BFE01D7DCEA00A80119, 66B8BC570381F53800A8011A, 66DF6BFF01D7DCEA00A80119, ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }, ); "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; "PBXWorkspaceContents:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { PBXProjectWorkspaceModule_StateKey_Rev39 = { PBXProjectWorkspaceModule_DataSourceSelectionKey_Rev6 = { BoundsStr = "{{0, 0}, {469, 441}}"; Rows = ( 0, ); VisibleRectStr = "{{0, 0}, {469, 441}}"; }; PBXProjectWorkspaceModule_EditorOpen = false; PBXProjectWorkspaceModule_EmbeddedNavigatorGroup = { PBXSplitModuleInNavigatorKey = { SplitCount = 1; }; }; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { PBXProjectWorkspaceModule_SGTM_Geometry = { _collapsingFrameDimension = 0; _indexOfCollapsedView = 0; _percentageOfCollapsedView = 0; sizes = ( "{{0, 0}, {182, 458}}", "{{182, 0}, {484, 458}}", ); }; }; PBXProjectWorkspaceModule_OldDetailFrame = "{{0, 0}, {484, 458}}"; PBXProjectWorkspaceModule_OldEditorFrame = "{{0, 0}, {750, 480}}"; PBXProjectWorkspaceModule_OldSuperviewFrame = "{{182, 0}, {484, 458}}"; PBXProjectWorkspaceModule_SGTM = { PBXBottomSmartGroupGIDs = ( 1C37FBAC04509CD000000102, 1C37FAAC04509CD000000102, 1C08E77C0454961000C914BD, 1CC0EA4004350EF90044410B, 1CC0EA4004350EF90041110B, 1C37FABC05509CD000000102, 1C37FABC05539CD112110102, E2644B35053B69B200211256, 1C37FABC04509CD000100104, ); PBXSmartGroupTreeModuleColumnData = { PBXSmartGroupTreeModuleColumnWidthsKey = ( 165, ); PBXSmartGroupTreeModuleColumnsKey_v4 = ( MainColumn, ); }; PBXSmartGroupTreeModuleOutlineStateKey_v7 = { PBXSmartGroupTreeModuleOutlineStateExpansionKey = ( ); PBXSmartGroupTreeModuleOutlineStateSelectionKey = ( ( 0, ), ); PBXSmartGroupTreeModuleOutlineStateVisibleRectKey = "{{0, 0}, {165, 440}}"; }; PBXTopSmartGroupGIDs = ( ); }; }; }; PBXWorkspaceGeometries = ( { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }, ); "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXBuildResultsModule" = { Frame = "{{0, 0}, {480, 217}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "272 407 480 238 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXDebugCLIModule" = { Frame = "{{0, 0}, {400, 201}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "50 718 400 222 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXNavigatorGroup" = { Frame = "{{0, 0}, {750, 481}}"; PBXModuleWindowStatusBarHidden = YES; RubberWindowFrame = "61 197 750 502 0 0 1024 746 "; }; "PBXWorkspaceGeometries:PBXConfiguration.PBXModule.PBXProjectWorkspaceModule" = { Frame = "{{0, 0}, {666, 458}}"; PBXProjectWorkspaceModule_GeometryKey_Rev15 = { }; RubberWindowFrame = "212 190 666 500 0 0 1024 746 "; }; PBXWorkspaceStateSaveDate = 244707468; }; perUserProjectItems = { 943C82CA0E87E32400A8C956 /* PBXTextBookmark */ = 943C82CA0E87E32400A8C956 /* PBXTextBookmark */; 943C82CE0E87E32400A8C956 /* PBXTextBookmark */ = 943C82CE0E87E32400A8C956 /* PBXTextBookmark */; 943C82EE0E8803BA00A8C956 /* PBXTextBookmark */ = 943C82EE0E8803BA00A8C956 /* PBXTextBookmark */; 943C830C0E88267200A8C956 /* PBXTextBookmark */ = 943C830C0E88267200A8C956 /* PBXTextBookmark */; 943C836E0E8828FE00A8C956 /* PBXTextBookmark */ = 943C836E0E8828FE00A8C956 /* PBXTextBookmark */; 943C836F0E8828FE00A8C956 /* PBXTextBookmark */ = 943C836F0E8828FE00A8C956 /* PBXTextBookmark */; 943C84110E89158B00A8C956 /* PBXTextBookmark */ = 943C84110E89158B00A8C956 /* PBXTextBookmark */; 94659C130E9545F2008D8B0E /* PBXTextBookmark */ = 94659C130E9545F2008D8B0E /* PBXTextBookmark */; 94659C140E9545F2008D8B0E /* PBXTextBookmark */ = 94659C140E9545F2008D8B0E /* PBXTextBookmark */; 94659C230E955378008D8B0E /* PBXTextBookmark */ = 94659C230E955378008D8B0E /* PBXTextBookmark */; 94659C240E955378008D8B0E /* PBXTextBookmark */ = 94659C240E955378008D8B0E /* PBXTextBookmark */; 94659C250E955378008D8B0E /* PBXTextBookmark */ = 94659C250E955378008D8B0E /* PBXTextBookmark */; 9466187F0B8CD74300AA8AE3 /* PBXTextBookmark */ = 9466187F0B8CD74300AA8AE3 /* PBXTextBookmark */; 9494081F0E95F19600A2D848 /* PBXTextBookmark */ = 9494081F0E95F19600A2D848 /* PBXTextBookmark */; 949408200E95F19600A2D848 /* PlistBookmark */ = 949408200E95F19600A2D848 /* PlistBookmark */; 949408210E95F19600A2D848 /* PBXTextBookmark */ = 949408210E95F19600A2D848 /* PBXTextBookmark */; 949408230E95F19600A2D848 /* PBXTextBookmark */ = 949408230E95F19600A2D848 /* PBXTextBookmark */; 949408240E95F19600A2D848 /* PlistBookmark */ = 949408240E95F19600A2D848 /* PlistBookmark */; 9494083B0E95F46800A2D848 /* PBXTextBookmark */ = 9494083B0E95F46800A2D848 /* PBXTextBookmark */; 9494083D0E95F46800A2D848 /* PBXTextBookmark */ = 9494083D0E95F46800A2D848 /* PBXTextBookmark */; 9494083E0E95F46800A2D848 /* PBXTextBookmark */ = 9494083E0E95F46800A2D848 /* PBXTextBookmark */; 9494083F0E95F46800A2D848 /* PBXTextBookmark */ = 9494083F0E95F46800A2D848 /* PBXTextBookmark */; 949CD5C6085CC32700EB8605 /* PBXBookmark */ = 949CD5C6085CC32700EB8605 /* PBXBookmark */; 94A698220E89A647005A25C0 /* PBXTextBookmark */ = 94A698220E89A647005A25C0 /* PBXTextBookmark */; 94A698240E89A647005A25C0 /* PBXTextBookmark */ = 94A698240E89A647005A25C0 /* PBXTextBookmark */; 94A6D4600ADEAFC4003E9CBE /* PBXTextBookmark */ = 94A6D4600ADEAFC4003E9CBE /* PBXTextBookmark */; 94CD975D0E87A9D300A81A01 /* PBXBookmark */ = 94CD975D0E87A9D300A81A01 /* PBXBookmark */; 94CD975E0E87A9D300A81A01 /* PBXTextBookmark */ = 94CD975E0E87A9D300A81A01 /* PBXTextBookmark */; 94CD97620E87A9D300A81A01 /* PBXTextBookmark */ = 94CD97620E87A9D300A81A01 /* PBXTextBookmark */; 94CD97C60E87AF8E00A81A01 /* PBXTextBookmark */ = 94CD97C60E87AF8E00A81A01 /* PBXTextBookmark */; 94CD993D0E87B2D700A81A01 /* PBXTextBookmark */ = 94CD993D0E87B2D700A81A01 /* PBXTextBookmark */; 94CD993F0E87B2D700A81A01 /* PBXTextBookmark */ = 94CD993F0E87B2D700A81A01 /* PBXTextBookmark */; 94D209B80E8AB02E0083E28B /* PBXTextBookmark */ = 94D209B80E8AB02E0083E28B /* PBXTextBookmark */; 94D20AE50E8BC5CF0083E28B /* PBXTextBookmark */ = 94D20AE50E8BC5CF0083E28B /* PBXTextBookmark */; 94D20AE60E8BC5CF0083E28B /* PBXTextBookmark */ = 94D20AE60E8BC5CF0083E28B /* PBXTextBookmark */; 94D20B110E8BCDB40083E28B /* PBXTextBookmark */ = 94D20B110E8BCDB40083E28B /* PBXTextBookmark */; 94D20B2F0E8BDD5B0083E28B /* PBXTextBookmark */ = 94D20B2F0E8BDD5B0083E28B /* PBXTextBookmark */; 94E6590A0E9043640088C3B5 /* PBXTextBookmark */ = 94E6590A0E9043640088C3B5 /* PBXTextBookmark */; 94E6590C0E9043640088C3B5 /* PBXTextBookmark */ = 94E6590C0E9043640088C3B5 /* PBXTextBookmark */; 94E659110E9043640088C3B5 /* PBXTextBookmark */ = 94E659110E9043640088C3B5 /* PBXTextBookmark */; 94E659130E9043640088C3B5 /* PBXTextBookmark */ = 94E659130E9043640088C3B5 /* PBXTextBookmark */; 94E659C70E9092870088C3B5 /* PBXTextBookmark */ = 94E659C70E9092870088C3B5 /* PBXTextBookmark */; 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */ = 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */; 94ECA522097E18C600C2C7BA /* PBXTextBookmark */ = 94ECA522097E18C600C2C7BA /* PBXTextBookmark */; 94ECA688097ECFBF00C2C7BA /* PBXTextBookmark */ = 94ECA688097ECFBF00C2C7BA /* PBXTextBookmark */; }; sourceControlManager = 9444E60D06E7B8740063F6CC /* Source Control */; userBuildSettings = { }; }; 9410FB8509AA6FBF002FD7B7 /* Sophie.app */ = { isa = PBXFileReference; explicitFileType = wrapper.application; name = Sophie.app; path = "/Users/johnmci/Documents/Squeak3.8.0/build/Squeak 3.8.18beta4U.app"; sourceTree = "<absolute>"; }; 943C82B20E87CC1F00A8C956 /* NSNull.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSNull.h; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNull.h; sourceTree = "<absolute>"; }; 943C82CA0E87E32400A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C82CB0E87E32400A8C956 /* NSString.h */; name = "NSString.h: 58"; rLen = 71; rLoc = 2261; rType = 0; vrLen = 1873; vrLoc = 1388; }; 943C82CB0E87E32400A8C956 /* NSString.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSString.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSString.h; sourceTree = "<absolute>"; }; 943C82CE0E87E32400A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD99620E87CBE500A81A01 /* NSObject.h */; name = "NSObject.h: 40"; rLen = 11; rLoc = 892; rType = 0; vrLen = 932; vrLoc = 0; }; 943C82EE0E8803BA00A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C82B20E87CC1F00A8C956 /* NSNull.h */; name = "NSNull.h: 9"; rLen = 18; rLoc = 160; rType = 0; vrLen = 185; vrLoc = 0; }; 943C830C0E88267200A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; name = "sqVirtualMachine.h: 27"; rLen = 5; rLoc = 664; rType = 0; vrLen = 1334; vrLoc = 0; }; 943C836E0E8828FE00A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 53"; rLen = 6; rLoc = 1428; rType = 0; vrLen = 1330; vrLoc = 1028; }; 943C836F0E8828FE00A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 53"; rLen = 6; rLoc = 1428; rType = 0; vrLen = 1330; vrLoc = 1028; }; 943C84110E89158B00A8C956 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD99620E87CBE500A81A01 /* NSObject.h */; name = "NSObject.h: 25"; rLen = 2; rLoc = 524; rType = 0; vrLen = 932; vrLoc = 0; }; 9444E60D06E7B8740063F6CC /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; scmType = scm.cvs; }; 9444E60E06E7B8740063F6CC /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 944BAB3F0E9421B10008DAC7 /* ObjectiveCPlugin.c:357 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C687380E900903006CAD50 /* ObjectiveCPlugin.c */; functionName = "primitiveMethodSignatureGetMethodReturnLength()"; hitCount = 0; ignoreCount = 0; lineNumber = 357; location = ObjectiveCPlugin; modificationTime = 244590292.240876; state = 1; }; 944BAB5D0E9426DB0008DAC7 /* ObjectiveCPlugin.c:360 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */; functionName = "primitiveMethodSignatureGetMethodReturnLength()"; hitCount = 0; ignoreCount = 0; lineNumber = 360; location = ObjectiveCPlugin; modificationTime = 244590299.513966; state = 1; }; 944BAB670E94277D0008DAC7 /* ObjectiveCPlugin.c:1220 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */; functionName = "primitivePerformSelectorWith()"; hitCount = 1; ignoreCount = 0; lineNumber = 1220; location = ObjectiveCPlugin; modificationTime = 244590626.643746; state = 1; }; 94659C130E9545F2008D8B0E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C687380E900903006CAD50 /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 121"; rLen = 2; rLoc = 4044; rType = 0; vrLen = 1293; vrLoc = 3051; }; 94659C140E9545F2008D8B0E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A4A0E8BBF840083E28B /* squeakSUnitTester.m */; name = "squeakSUnitTester.m: 348"; rLen = 9; rLoc = 10513; rType = 0; vrLen = 2257; vrLoc = 10591; }; 94659C230E955378008D8B0E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A4A0E8BBF840083E28B /* squeakSUnitTester.m */; name = "squeakSUnitTester.m: 411"; rLen = 0; rLoc = 13143; rType = 0; vrLen = 2432; vrLoc = 10868; }; 94659C240E955378008D8B0E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 1360"; rLen = 0; rLoc = 41293; rType = 0; vrLen = 1860; vrLoc = 8821; }; 94659C250E955378008D8B0E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94659C260E955378008D8B0E /* sqUnixObjC.m */; name = "sqUnixObjC.m: 254"; rLen = 15; rLoc = 7007; rType = 0; vrLen = 3311; vrLoc = 6346; }; 94659C260E955378008D8B0E /* sqUnixObjC.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixObjC.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/sqUnixObjC.m"; sourceTree = "<absolute>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {965, 7672}}"; sepNavSelRange = "{7007, 15}"; sepNavVisRange = "{6346, 3311}"; sepNavWindowFrame = "{{63, 13}, {1012, 1015}}"; }; }; 9466187F0B8CD74300AA8AE3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ECA4E7097E15F800C2C7BA /* PkgInfo */; name = "PkgInfo: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 8; vrLoc = 0; }; 9494081F0E95F19600A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A490E8BBF840083E28B /* squeakSUnitTester.h */; name = "squeakSUnitTester.h: 159"; rLen = 0; rLoc = 9528; rType = 0; vrLen = 4749; vrLoc = 5180; }; 949408200E95F19600A2D848 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleVersion, ); name = /Users/johnmci/Documents/SqueakObjectiveCPlugin/Info.plist; rLen = 5; rLoc = 0; }; 949408210E95F19600A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; comments = "error: parse error before \"__AVAILABILITY_INTERNAL__MAC_10_5\""; fRef = 949408220E95F19600A2D848 /* CFNetworkErrors.h */; rLen = 1; rLoc = 52; rType = 1; }; 949408220E95F19600A2D848 /* CFNetworkErrors.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFNetworkErrors.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/Headers/CFNetworkErrors.h; sourceTree = "<absolute>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {954, 3346}}"; sepNavSelRange = "{1051, 124}"; sepNavVisRange = "{0, 1298}"; }; }; 949408230E95F19600A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A490E8BBF840083E28B /* squeakSUnitTester.h */; name = "squeakSUnitTester.h: 159"; rLen = 0; rLoc = 9528; rType = 0; vrLen = 4749; vrLoc = 5180; }; 949408240E95F19600A2D848 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleVersion, ); name = /Users/johnmci/Documents/SqueakObjectiveCPlugin/Info.plist; rLen = 5; rLoc = 0; }; 9494083B0E95F46800A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9494083C0E95F46800A2D848 /* CFNetworkErrors.h */; name = "CFNetworkErrors.h: 53"; rLen = 124; rLoc = 1051; rType = 0; vrLen = 1298; vrLoc = 0; }; 9494083C0E95F46800A2D848 /* CFNetworkErrors.h */ = { isa = PBXFileReference; name = CFNetworkErrors.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/Headers/CFNetworkErrors.h; sourceTree = "<absolute>"; }; 9494083D0E95F46800A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A4A0E8BBF840083E28B /* squeakSUnitTester.m */; name = "squeakSUnitTester.m: 411"; rLen = 0; rLoc = 13143; rType = 0; vrLen = 2432; vrLoc = 10868; }; 9494083E0E95F46800A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 1360"; rLen = 0; rLoc = 41293; rType = 0; vrLen = 1611; vrLoc = 8821; }; 9494083F0E95F46800A2D848 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949408400E95F46800A2D848 /* sqUnixObjC.m */; name = "sqUnixObjC.m: 254"; rLen = 15; rLoc = 7007; rType = 0; vrLen = 3311; vrLoc = 6346; }; 949408400E95F46800A2D848 /* sqUnixObjC.m */ = { isa = PBXFileReference; name = sqUnixObjC.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/sqUnixObjC.m"; sourceTree = "<absolute>"; }; 949CD5C6085CC32700EB8605 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */; }; 94A698220E89A647005A25C0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A698230E89A647005A25C0 /* objc.h */; name = "objc.h: 39"; rLen = 34; rLoc = 1260; rType = 0; vrLen = 1344; vrLoc = 0; }; 94A698230E89A647005A25C0 /* objc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = objc.h; path = /Developer/SDKs/MacOSX10.4u.sdk/usr/include/objc/objc.h; sourceTree = "<absolute>"; }; 94A698240E89A647005A25C0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A698250E89A647005A25C0 /* objc.h */; name = "objc.h: 45"; rLen = 40; rLoc = 1387; rType = 0; vrLen = 815; vrLoc = 1019; }; 94A698250E89A647005A25C0 /* objc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = objc.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/usr/include/objc/objc.h; sourceTree = "<absolute>"; }; 94A6D4600ADEAFC4003E9CBE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */; name = stQuicktimeSetSemaphorefor; rLen = 26; rLoc = 467; rType = 0; vrLen = 565; vrLoc = 0; }; 94A8BB7D0E91EB65007DDB7F /* ObjectiveCPlugin.c:1104 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C687380E900903006CAD50 /* ObjectiveCPlugin.c */; functionName = "primitiveNSInvocationSetStringType()"; hitCount = 0; ignoreCount = 0; lineNumber = 1104; location = ObjectiveCPlugin; modificationTime = 244590037.338519; state = 2; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {756, 2422}}"; sepNavSelRange = "{1428, 6}"; sepNavVisRange = "{1028, 1330}"; }; }; 94ABA91E0858D35E00079BE1 /* Squeak */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; launchableReference = 9410FB8509AA6FBF002FD7B7 /* Sophie.app */; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; sourceDirectories = ( ); }; 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */ = { activeExec = 0; }; 94AF34F10846F91100FA5ACB /* Info.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {739, 610}}"; sepNavSelRange = "{731, 0}"; sepNavVisRect = "{{0, 0}, {739, 610}}"; sepNavWindowFrame = "{{84, 91}, {962, 719}}"; }; }; 94AF35000846F98600FA5ACB /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {673, 2590}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {673, 397}}"; }; }; 94C687380E900903006CAD50 /* ObjectiveCPlugin.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ObjectiveCPlugin.c; path = "/Users/johnmci/Documents/Squeak/Squeak3.8.1-6747-basic#2/src32iPhone/plugins/ObjectiveCPlugin/ObjectiveCPlugin.c"; sourceTree = "<group>"; uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {965, 19390}}"; sepNavSelRange = "{41293, 0}"; sepNavVisRange = "{8821, 1668}"; sepNavWindowFrame = "{{739, -5}, {1012, 1015}}"; }; }; 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {965, 19390}}"; sepNavSelRange = "{41293, 0}"; sepNavVisRange = "{8821, 1611}"; sepNavWindowFrame = "{{739, -5}, {1012, 1015}}"; }; }; 94CD975D0E87A9D300A81A01 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 66C6C8E501DB1EC300A80109 /* SqueakPlugin.icns */; }; 94CD975E0E87A9D300A81A01 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1796; vrLoc = 0; }; 94CD97620E87A9D300A81A01 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; name = "sqPlatformSpecific.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1796; vrLoc = 0; }; 94CD979D0E87ACBD00A81A01 /* NSNull.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSNull.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNull.h; sourceTree = "<absolute>"; }; 94CD97C40E87AF6D00A81A01 /* stdarg.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stdarg.h; path = /Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h; sourceTree = "<absolute>"; }; 94CD97C60E87AF8E00A81A01 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD979D0E87ACBD00A81A01 /* NSNull.h */; name = "NSNull.h: 9"; rLen = 18; rLoc = 160; rType = 0; vrLen = 185; vrLoc = 0; }; 94CD993D0E87B2D700A81A01 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD97C40E87AF6D00A81A01 /* stdarg.h */; name = "stdarg.h: 4"; rLen = 25; rLoc = 100; rType = 0; vrLen = 234; vrLoc = 0; }; 94CD993F0E87B2D700A81A01 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD97C40E87AF6D00A81A01 /* stdarg.h */; name = "stdarg.h: 4"; rLen = 25; rLoc = 100; rType = 0; vrLen = 234; vrLoc = 0; }; 94CD99620E87CBE500A81A01 /* NSObject.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObject.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObject.h; sourceTree = "<absolute>"; }; 94D209B80E8AB02E0083E28B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; name = "sqVirtualMachine.h: 72"; rLen = 0; rLoc = 2891; rType = 0; vrLen = 2084; vrLoc = 1476; }; 94D20A490E8BBF840083E28B /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1686, 2254}}"; sepNavSelRange = "{9528, 0}"; sepNavVisRange = "{5180, 4749}"; sepNavWindowFrame = "{{864, 7}, {583, 1021}}"; }; }; 94D20A4A0E8BBF840083E28B /* squeakSUnitTester.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1086, 5768}}"; sepNavSelRange = "{13143, 0}"; sepNavVisRange = "{10868, 2432}"; sepNavWindowFrame = "{{662, 30}, {997, 998}}"; }; }; 94D20AE50E8BC5CF0083E28B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CD97380E87A7CC00A81A01 /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 432"; rLen = 27; rLoc = 12775; rType = 0; vrLen = 1159; vrLoc = 12086; }; 94D20AE60E8BC5CF0083E28B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A490E8BBF840083E28B /* squeakSUnitTester.h */; name = "squeakSUnitTester.h: 37"; rLen = 0; rLoc = 1764; rType = 0; vrLen = 1836; vrLoc = 0; }; 94D20B110E8BCDB40083E28B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20B120E8BCDB40083E28B /* NSObjCRuntime.h */; name = "NSObjCRuntime.h: 59"; rLen = 3; rLoc = 1445; rType = 0; vrLen = 1428; vrLoc = 775; }; 94D20B120E8BCDB40083E28B /* NSObjCRuntime.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObjCRuntime.h; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObjCRuntime.h; sourceTree = "<absolute>"; }; 94D20B2F0E8BDD5B0083E28B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D20A4A0E8BBF840083E28B /* squeakSUnitTester.m */; name = "squeakSUnitTester.m: 65"; rLen = 0; rLoc = 2182; rType = 0; vrLen = 1042; vrLoc = 1886; }; 94E6590A0E9043640088C3B5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6590B0E9043640088C3B5 /* sqMacDragDrop.c */; name = "sqMacDragDrop.c: 543"; rLen = 0; rLoc = 16628; rType = 0; vrLen = 1500; vrLoc = 15128; }; 94E6590B0E9043640088C3B5 /* sqMacDragDrop.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacDragDrop.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/DropPlugin/sqMacDragDrop.c"; sourceTree = "<absolute>"; }; 94E6590C0E9043640088C3B5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6590D0E9043640088C3B5 /* sqMacWindowUniversal.c */; name = "sqMacWindowUniversal.c: 361"; rLen = 27; rLoc = 12118; rType = 0; vrLen = 1812; vrLoc = 11210; }; 94E6590D0E9043640088C3B5 /* sqMacWindowUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindowUniversal.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqMacWindowUniversal.c"; sourceTree = "<absolute>"; }; 94E659110E9043640088C3B5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659120E9043640088C3B5 /* sqMacDragDrop.c */; name = "sqMacDragDrop.c: 456"; rLen = 26; rLoc = 14041; rType = 0; vrLen = 1777; vrLoc = 13155; }; 94E659120E9043640088C3B5 /* sqMacDragDrop.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacDragDrop.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/DropPlugin/sqMacDragDrop.c"; sourceTree = "<absolute>"; }; 94E659130E9043640088C3B5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659140E9043640088C3B5 /* sqMacWindowUniversal.c */; name = "sqMacWindowUniversal.c: 361"; rLen = 27; rLoc = 12118; rType = 0; vrLen = 1812; vrLoc = 11210; }; 94E659140E9043640088C3B5 /* sqMacWindowUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindowUniversal.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqMacWindowUniversal.c"; sourceTree = "<absolute>"; }; 94E659C70E9092870088C3B5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C82B20E87CC1F00A8C956 /* NSNull.h */; name = "NSNull.h: 9"; rLen = 18; rLoc = 160; rType = 0; vrLen = 185; vrLoc = 0; }; 94ECA4AA097E137A00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AF34F10846F91100FA5ACB /* Info.plist */; name = Quickt; rLen = 6; rLoc = 284; rType = 0; vrLen = 758; vrLoc = 0; }; 94ECA4E7097E15F800C2C7BA /* PkgInfo */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {739, 610}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {739, 610}}"; }; }; 94ECA522097E18C600C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ECA4E7097E15F800C2C7BA /* PkgInfo */; name = "PkgInfo: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 8; vrLoc = 0; }; 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */ = { isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuicktimePlugin.h; path = /Users/johnmci/Documents/SqueakObjectiveCPlugin/platforms/Cross/plugins/QuicktimePlugin/QuicktimePlugin.h; sourceTree = "<absolute>"; }; 94ECA688097ECFBF00C2C7BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ECA52C097E197400C2C7BA /* QuicktimePlugin.h */; name = stQuicktimeSetSemaphorefor; rLen = 26; rLoc = 467; rType = 0; vrLen = 565; vrLoc = 0; }; } ================================================ FILE: vm/src/from_squeak/iOS/plugins/UnixOSProcessPlugin/UnixOSProcessPluginOLD.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ 040F1A2C12CD1687008BA0CB /* sqConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 040F1A2A12CD1687008BA0CB /* sqConfig.h */; }; 040F1A2D12CD1687008BA0CB /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 040F1A2B12CD1687008BA0CB /* config.h */; }; 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */; }; 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */; }; 94AF34E40846F91100FA5ACB /* sq.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5C0381F66500A8011A /* sq.h */; }; 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */; }; 94AF35050846F9AB00FA5ACB /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AF35040846F9AB00FA5ACB /* interp.h */; }; 94CD97E40E87B00D00A81A01 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94CD97E30E87B00D00A81A01 /* Foundation.framework */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 94AF34F70846F94F00FA5ACB /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.gcc.3_3; fileType = sourcecode.c; isEditable = 1; outputFiles = ( ); }; /* End PBXBuildRule section */ /* Begin PBXFileReference section */ 040F1A2A12CD1687008BA0CB /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqConfig.h; path = iOS/vm/iPhone/sqConfig.h; sourceTree = "<group>"; }; 040F1A2B12CD1687008BA0CB /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = iOS/vm/iPhone/config.h; sourceTree = "<group>"; }; 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqPlatformSpecific.h; path = iOS/vm/iPhone/sqPlatformSpecific.h; sourceTree = "<group>"; }; 66B8BC5C0381F66500A8011A /* sq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sq.h; path = Cross/vm/sq.h; sourceTree = "<group>"; }; 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqVirtualMachine.h; path = Cross/vm/sqVirtualMachine.h; sourceTree = "<group>"; }; 943173AF085CD38900DDDC64 /* ObjectiveCPlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjectiveCPlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sqMemoryAccess.h; path = Cross/vm/sqMemoryAccess.h; sourceTree = "<group>"; }; 94AF34F10846F91100FA5ACB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 94AF35040846F9AB00FA5ACB /* interp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = interp.h; path = ../src/vm/interp.h; sourceTree = "<group>"; }; 94CD97E30E87B00D00A81A01 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 94ECA4E7097E15F800C2C7BA /* PkgInfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = PkgInfo; path = build/PkgInfo; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 94AF34EE0846F91100FA5ACB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 94CD97E40E87B00D00A81A01 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 66B8BC570381F53800A8011A /* platforms */ = { isa = PBXGroup; children = ( 040F1A2A12CD1687008BA0CB /* sqConfig.h */, 040F1A2B12CD1687008BA0CB /* config.h */, 94AF35040846F9AB00FA5ACB /* interp.h */, 66B8BC5A0381F63A00A8011A /* sqPlatformSpecific.h */, 66B8BC5C0381F66500A8011A /* sq.h */, 66B8BC5E0381F69100A8011A /* sqVirtualMachine.h */, 94ABA8920858C40D00079BE1 /* sqMemoryAccess.h */, ); name = platforms; path = ../../..; sourceTree = SOURCE_ROOT; }; 66DF6BFE01D7DCEA00A80119 = { isa = PBXGroup; children = ( 94ECA4E7097E15F800C2C7BA /* PkgInfo */, 94AF34F10846F91100FA5ACB /* Info.plist */, 66B8BC570381F53800A8011A /* platforms */, 66DF6BFF01D7DCEA00A80119 /* Sources */, 94CD97E30E87B00D00A81A01 /* Foundation.framework */, 66DF6C4501D7DEEE00A80119 /* Products */, ); sourceTree = "<group>"; }; 66DF6BFF01D7DCEA00A80119 /* Sources */ = { isa = PBXGroup; children = ( ); name = Sources; sourceTree = "<group>"; }; 66DF6C4501D7DEEE00A80119 /* Products */ = { isa = PBXGroup; children = ( 943173AF085CD38900DDDC64 /* ObjectiveCPlugin.bundle */, ); name = Products; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 94AF34E10846F91100FA5ACB /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 94AF34E30846F91100FA5ACB /* sqPlatformSpecific.h in Headers */, 94AF34E40846F91100FA5ACB /* sq.h in Headers */, 94AF34E50846F91100FA5ACB /* sqVirtualMachine.h in Headers */, 94AF35050846F9AB00FA5ACB /* interp.h in Headers */, 94ABA8930858C40D00079BE1 /* sqMemoryAccess.h in Headers */, 040F1A2C12CD1687008BA0CB /* sqConfig.h in Headers */, 040F1A2D12CD1687008BA0CB /* config.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 94ECA1E7097DC27D00C2C7BA /* Build configuration list for PBXNativeTarget "ObjectiveCPlugin" */; buildPhases = ( 94AF34E10846F91100FA5ACB /* Headers */, 94AF34E70846F91100FA5ACB /* Resources */, 94AF34EA0846F91100FA5ACB /* Sources */, 94AF34EE0846F91100FA5ACB /* Frameworks */, 94AF34F00846F91100FA5ACB /* Rez */, ); buildRules = ( 94AF34F70846F94F00FA5ACB /* PBXBuildRule */, ); dependencies = ( ); name = ObjectiveCPlugin; productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; productName = "mpeg3PluginBundle Debug"; productReference = 943173AF085CD38900DDDC64 /* ObjectiveCPlugin.bundle */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 66DF6BFD01D7DCEA00A80119 /* Project object */ = { isa = PBXProject; buildConfigurationList = 94ECA1EB097DC27D00C2C7BA /* Build configuration list for PBXProject "UnixOSProcessPlugin" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 66DF6BFE01D7DCEA00A80119; productRefGroup = 66DF6C4501D7DEEE00A80119 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 94AF34E00846F91100FA5ACB /* ObjectiveCPlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 94AF34E70846F91100FA5ACB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ 94AF34F00846F91100FA5ACB /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 94AF34EA0846F91100FA5ACB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 94ECA1E8097DC27D00C2C7BA /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = 4.0; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_LDFLAGS = ""; PRODUCT_NAME = ObjectiveCPlugin; SDKROOT = macosx10.5; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Development; }; 94ECA1E9097DC27D00C2C7BA /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_VERSION = 4.0; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; PRODUCT_NAME = ObjectiveCPlugin; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", ); WRAPPER_EXTENSION = bundle; }; name = Deployment; }; 94ECA1EA097DC27D00C2C7BA /* Default */ = { isa = XCBuildConfiguration; buildSettings = { GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = 3; GCC_VERSION_i386 = ""; GCC_VERSION_ppc = ""; HEADER_SEARCH_PATHS = /Developer/Headers/FlatCarbon; INFOPLIST_FILE = Info.plist; MACOSX_DEPLOYMENT_TARGET = 10.5; OTHER_LDFLAGS = ""; PER_ARCH_CFLAGS_i386 = ""; PER_ARCH_CFLAGS_ppc = ""; PRODUCT_NAME = QuicktimePlugin; SDKROOT = macosx10.5; SDKROOT_i386 = ""; SDKROOT_ppc = ""; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = bundle; }; name = Default; }; 94ECA1EC097DC27D00C2C7BA /* Development */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.5; SDKROOT = macosx10.5; }; name = Development; }; 94ECA1ED097DC27D00C2C7BA /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.5; SDKROOT = macosx10.5; }; name = Deployment; }; 94ECA1EE097DC27D00C2C7BA /* Default */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; SDKROOT = iphoneos2.0; }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 94ECA1E7097DC27D00C2C7BA /* Build configuration list for PBXNativeTarget "ObjectiveCPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 94ECA1E8097DC27D00C2C7BA /* Development */, 94ECA1E9097DC27D00C2C7BA /* Deployment */, 94ECA1EA097DC27D00C2C7BA /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; 94ECA1EB097DC27D00C2C7BA /* Build configuration list for PBXProject "UnixOSProcessPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( 94ECA1EC097DC27D00C2C7BA /* Development */, 94ECA1ED097DC27D00C2C7BA /* Deployment */, 94ECA1EE097DC27D00C2C7BA /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 66DF6BFD01D7DCEA00A80119 /* Project object */; } ================================================ FILE: vm/src/from_squeak/iOS/vm/5.x.x Release Notes.rtf ================================================ {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 {\fonttbl\f0\fnil\fcharset0 Geneva;\f1\fnil\fcharset0 LucidaGrande;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww20740\viewh15740\viewkind0 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f0\fs24 \cf0 Mac VM 5.7b1 Cocoa for os-x 10.5 and iPhone 2.x\ \f1\b\fs22 \ Revision: \b0 199 \f0\fs24 5.7b1 \f1\b\fs22 \ Date: \b0 Wednesday, June 16, 2010 12:04:22 AM PT \b \ Author: \b0 jmm \b \ \ \b0 Mac Cocoa VM 5.7b1 Move towards June 15th VMMaker source \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SqueakFFIPrims/sqManualSurface.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/AsynchFilePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/AsynchFilePlugin/AsynchFilePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/JoystickTabletPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/JoystickTabletPlugin/JoystickTabletPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SerialPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SerialPlugin/SerialPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/plugins.int\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/64interp.h\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/AsynchFilePlugin/AsynchFilePlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B2DPlugin/B2DPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BMPReadWriterPlugin/BMPReadWriterPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BitBltPlugin/BitBltPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ClipboardExtendedPlugin/ClipboardExtendedPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DSAPrims/DSAPrims.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DropPlugin/DropPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FFTPlugin/FFTPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FilePlugin/FilePlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FloatArrayPlugin/FloatArrayPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/GeniePlugin/GeniePlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/HostWindowPlugin/HostWindowPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/InternetConfigPlugin/InternetConfigPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReaderPlugin/JPEGReaderPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JoystickTabletPlugin/JoystickTabletPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Klatt/Klatt.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/LargeIntegers/LargeIntegers.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MIDIPlugin/MIDIPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MacMenubarPlugin/MacMenubarPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Matrix2x3Plugin/Matrix2x3Plugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/RePlugin/RePlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SecurityPlugin/SecurityPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SerialPlugin/SerialPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SocketPlugin/SocketPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundCodecPrims/SoundCodecPrims.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundPlugin/SoundPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Squeak3D/Squeak3D.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/StarSqueakPlugin/StarSqueakPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/UUIDPlugin/UUIDPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ZipPlugin/ZipPlugin.c\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/sqNamedPrims.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/Info-iPhone.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info 64*64.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/HostWindowPlugin/HostWindowPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SoundPlugin/SoundPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SqueakFFIPrims/sqFFI.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sq.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqNamedPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqVirtualMachine.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqVirtualMachine.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/plugins/UUIDPlugin/sqUnixUUID.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/SqDisplay.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/SqSound.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/aio.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/debug.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/debug.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/dlfcn-dyld.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixCharConv.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixCharConv.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixEvent.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixExternalPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixMain.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/sqUnixMemory.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/B2DPlugin/B2DPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/BMPReadWriterPlugin/BMPReadWriterPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/BitBltPlugin/BitBltPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/DropPlugin/DropPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/FFTPlugin/FFTPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/FilePlugin/FilePlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/FloatArrayPlugin/FloatArrayPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/GeniePlugin/GeniePlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/HostWindowPlugin/HostWindowPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/InternetConfigPlugin/InternetConfigPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/JPEGReaderPlugin/JPEGReaderPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/Klatt/Klatt.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/LargeIntegers/LargeIntegers.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/MIDIPlugin/MIDIPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/MacMenubarPlugin/MacMenubarPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/Matrix2x3Plugin/Matrix2x3Plugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/RePlugin/RePlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SecurityPlugin/SecurityPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SocketPlugin/SocketPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SoundCodecPrims/SoundCodecPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SoundPlugin/SoundPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/Squeak3D/Squeak3D.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/SqueakFFIPrims/SqueakFFIPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/StarSqueakPlugin/StarSqueakPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/UUIDPlugin/UUIDPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ZipPlugin/ZipPlugin.c\ \b \ \ 5.4b2\ File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 184 \b \ Date: \b0 Monday, January 25, 2010 12:15:10 PM PT \b \ Author: \b0 jmm \b \ \ \b0 rename interp.h header for 64bit squeak it's breaking things by includes from 32bit squeak \ sqiPhoneScreenAndWindow.m\ use rect versus *rect in drawRect\ \ sqSqueakScreenAndWindow.m\ pass rect in versus pointer to rect since we need to\ pass rect to invalidateRect anyway\ \ SqueakOSXAppDelegate.m\ remove check for 64bit image in getfullscreen\ update to 5.4b2\ \ sqSqueakScreenAndWindow.h\ pass rect versus *rect\ \ sqSqueakOSXApplication+attributes.m\ version number change\ \ sqSqueakOSXScreenAndWindow.m\ CLANG hates (NSRect) = (CGRect)\ \ sqSqueakOSXApplication+cursor.m\ let's not leak cursors\ \ sqSqueakOSXNSView.m\ change the cursor to arrow when click in resize widget\ change back when unclick\ drawRect: is drawRect (NSRect) not (NSRect*)\ \ sqSqueakOSXApplication+imageReadWrite.m\ Open panel has to let you click only on *.image types, not others. \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/64interp.h Copied from revision: 183 path: /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+cursor.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+imageReadWrite.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqiPhoneScreenAndWindow.m\ \ \ \f0\fs24 Mac VM 5.4b1 Cocoa for os-x 10.5 and iPhone 2.x\ \f1\fs22 \ \b File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 183 \b \ Date: \b0 Friday, January 22, 2010 12:46:14 PM PT \b \ Author: \b0 jmm \b \ \ \b0 Add microSeconds. \ Rebuild interp.c for 64bit source\ \ Interp.c\ add ioMicroSeconds\ \ sq.h\ add ioMicroSeconds\ \ ChipboardExtendedPlugin.c\ has to include sqMacExtendedClipboard.h so that 64bit failure does not occur\ \ SqueakOSXAppDelegate.m\ Some funky issue with storage of headers in 64bit images\ and how it affects full screen flag\ work around for now.\ \ sqMacV2Time\ add ioMicroSeconds\ \ sqSqueakOSXNSView.h\ remove compiler warning \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info 64*64.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sq.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqMacV2Time.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ClipboardExtendedPlugin/ClipboardExtendedPlugin.c\ \ \f0\fs24 Mac VM 5.3b1 Cocoa for os-x 10.5 and iPhone 2.x\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \cf0 Support for Closures, OS-X, iPhone.\ \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f1\b\fs22 \cf0 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m \b \ Revision: \b0 176 \b \ Date: \b0 Sunday, January 10, 2010 11:32:48 PM PT \b \ Author: \b0 jmm \b \ \ \b0 5.3b1 remove some NSLog, ensure modifier flags get passed onto doCommand: logic properly \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakEventsAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 174 \b \ Date: \b0 Sunday, January 10, 2010 10:55:42 PM PT \b \ Author: \b0 jmm \b \ \ \b0 5.3b1 compile work \b \ \ Changes:\ \b0 D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakNoOGLIPhone_Prefix.pch\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqiPhoneScreenAndWindow.m\ \f0\fs24 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \cf0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f1\b\fs22 \cf0 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m \b \ Revision: \b0 173 \b \ Date: \b0 Sunday, January 10, 2010 10:24:54 PM PT \b \ Author: \b0 jmm \b \ \ \b0 We consolidate the drawing logic between os-x and iphone & fix keyboard logic (partially)\ \ In ioForceDisplayUpdate we do \ lockWhenCondition: 0\ move the drawing queue to the frame queue\ unlockWIthCondition: 1\ schedule postIoForceDisplayUpdateUsingRectangle on the main thread wait until done. \ This does setNeedsDisplayInRect: on the mainView\ \ This ensures we are doing the invalidate rectangle logic on the main view. \ \ Later drawRect: will run on the view, this does\ lockWhenCondition: 1\ move the data from the frameQueue to the CGContext (aka screen). \ unlockWithCondition: 0\ \ Therefore the ioForceDisplayUpdate will block until the last drawRect: happens. \ The drawRect: will block until the ioForceDisplayUpdate: has put data into the frameQueue\ however it does check for data before doing the lock. \ \ \ sqSqueakSoundCoreAudioAPI.m/h\ fix /* & // to remove compiler warning\ \ sqSqueakEventAPI.m/h \ add optional logging in ioGetNextEvent\ \ sqSqueakMainApplication+attributes.m/h\ add "const" to getAttribute: \ \ sqSqueakScreenAndWindow.h/m\ moving lockForScreenUpdate down\ \ sqSqueakScreenAndWindow.h\ lockForScreenUpdate logic\ add postIoForceDisplayUpdateUsingRectangle\ \ SqueakOSXAppDelegate.m\ version number change\ \ sqSqueakOSXApplication+attributes.m\ version number change\ \ sqSqueakOSXNSView.h\ sqSqueakOSXNSView.m\ \ sqSqueakOSXScreenAndWindow.m\ override postIoForceDisplayUpdateUsingRectangle\ \ sqSqueakIPhoneApplication+attributes.m\ version number change\ \ sqiPhoneScreenAndWindow.m/h\ lockForScreenUpdate goes to super class\ \ Work work work on keyboard logic.\ \b \ \ Changes:\ \b0 D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakNoOGLIPhone.xcodeproj/johnmci.mode1v3\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakNoOGLIPhone.xcodeproj/johnmci.pbxuser\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakNoOGLIPhone.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/Info-iPhone.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakEventsAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakMainApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqiPhoneScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqiPhoneScreenAndWindow.m\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 172 \b \ Date: \b0 Tuesday, January 5, 2010 6:39:04 PM PT \b \ Author: \b0 jmm \b \ \ \b0 V5.2b3 mac osx vm 2.1.0 iphone vm\ for 5.2.b3 we fix option arrow key\ for 2.1.0 we move to current pharo pharo1.0-10502-rc1dev09.12.2.image\ this also required changing source file name in _imageReadWrite \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/PharoV10.sources\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/iPhone.10418.changes\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/iPhone.10418.image\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/Info-iPhone.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/iPhone.changes\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/iPhone.image\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+imageReadWrite.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.c\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 169 \b \ Date: \b0 Monday, January 4, 2010 1:12:46 AM PT \b \ Author: \b0 jmm \b \ \ \b0 5.2b2 fix for jpeg read/write bad form bitmap addressing code \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.c\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 167 \b \ Date: \b0 Saturday, January 2, 2010 9:01:04 PM PT \b \ Author: \b0 jmm \b \ \ \b0 os-x 5.2b1 (11)\ iphone 2.1.0\ \ sqMacExtendedClipboard.m/h\ add cocoa support for extended clipboard logic. \ \ MacMenuOS9ToOSX.m/h \ MacMenubarPlugin.h\ Add start of mac menu support. In Progress, not usable\ \ sqSqueakScreenAndWindow.m\ Refactor the iphone versus os-x drawing a bit. Needs more adjustment\ \ SqueakOSXAppDelegate.m\ sqSqueakOSXApplication-attributes.m \ Tweak version to 5.2b1 (11)\ \ \ iphone 2.1.0\ Fix drawing, yes it was busted. \ Add clipboard support\ \ sqSqueakiPhoneApplication+clipboard.m/h\ sqSqueakIPhoneClipboardClipboardAPI.m/h \ clipboard support for squeak\ \ sqMacExtendedClipboard.m/h\ clipboard support for Pharo\ \ src\ Add ClipboardExtendedPlugin\ Add macMenubarPlugin\ \ \ \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/ClipboardExtended\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/ClipboardExtended/sqMacExtendedClipboard.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/ClipboardExtended/sqMacExtendedClipboard.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config/ftconfig.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config/ftheader.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config/ftmodule.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config/ftoption.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/config/ftstdlib.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/freetype.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftadvanc.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftbbox.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftbdf.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftbitmap.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftcache.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftchapters.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftcid.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fterrdef.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fterrors.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftgasp.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftglyph.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftgxval.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftgzip.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftimage.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftincrem.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftlcdfil.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftlist.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftlzw.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftmac.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftmm.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftmodapi.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftmoderr.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftotval.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftoutln.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftpfr.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftrender.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftsizes.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftsnames.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftstroke.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftsynth.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftsystem.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fttrigon.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/fttypes.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftwinfnt.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ftxf86.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/t1tables.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ttnameid.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/tttables.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/tttags.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/freetype2/freetype/ttunpat.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/MacMenubarPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/MacMenubarPlugin/MacMenuOS9ToOSX.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/MacMenubarPlugin/MacMenuOS9ToOSX.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/MacMenubarPlugin/MacMenubarPlugin.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+clipboard.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+clipboard.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneClipboardAPI.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneClipboardAPI.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/plugins/ClipboardExtended\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/plugins/ClipboardExtended/sqMacExtendedClipboard.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/plugins/ClipboardExtended/sqMacExtendedClipboard.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ClipboardExtendedPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ClipboardExtendedPlugin/ClipboardExtendedPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/MacMenubarPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/MacMenubarPlugin/MacMenubarPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/Info-iPhone.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info 64*64.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/macintoshextra.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/sqNamedPrims.h\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 166 \b \ Date: \b0 Friday, January 1, 2010 1:01:54 PM PT \b \ Author: \b0 jmm \b \ \ \b0 minor changes for 64bit image compile for 32bit powerpc \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/sqNamedPrims.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ \f0\fs24 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \cf0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f1\b\fs22 \cf0 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 165 \b \ Date: \b0 Friday, December 25, 2009 8:08:07 PM PT \b \ Author: \b0 jmm \b \ \ \b0 5.1.b1 changes to expose sqBaseMemory address for plugins to link to . \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/.DS_Store\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/.DS_Store\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/bert.mode1\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/bert.pbxuser\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/johnmci.mode1\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/johnmci.mode1v3\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/johnmci.pbxuser\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/FT2Plugin.xcodeproj/project.pbxproj\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/Info-FT2Plugin.plist\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/PkgInfo\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/libfreetype.a\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/FT2Plugin/macFileNameBits.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/plugins/FT2Plugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/plugins/FT2Plugin/.DS_Store\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/plugins/FT2Plugin/FT2Plugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqMacV2Memory.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqPlatformSpecific.h\ \b File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 163 \b \ Date: \b0 Tuesday, December 8, 2009 10:00:41 PM PT \b \ Author: \b0 jmm \b \ \ \b0 Fix issue with malloc in 1/2/4/8/16 to 32bit translators. \ We need to allocate storage, then free after the draw. \ \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewClut.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/BitMapConversionLogicFromX11.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewBitmapConversion.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewBitmapConversion.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/drawingImageAtom.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/drawingImageAtom.m\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 162 \b \ Date: \b0 Tuesday, December 8, 2009 1:17:32 PM PT \b \ Author: \b0 jmm \b \ \ \b0 Add 1,2,4,8,16 bit form support\ NOT COMPLETED, need to figure out how to dispose of malloc\ \ sqSqueakScreenAPI.m\ \ ioHasDisplayDepth\ should have used ioHasDisplayDepth: versus ioDisplayDepth (bug)\ \ \ sqSqueakScreenAndWindow.m\ sqSqueakScreenAndWindow.h\ \ refractor to use \ CGDataProviderCreateWithData\ by default\ and have a method to create the CGImageRef so \ os-x can use default or calculate bitmap. \ \ \ sqSqueakOSXNSView.h\ sqSqueakOSXNSView.m\ \ refactor to use colormap and support 1,2,4,8,16 bit forms\ \ sqSqueakOSXScreenAndWindow.h\ sqSqueakOSXScreenAndWindow.m\ \ ioHasDisplayDepth fix\ refractor to build 32bit screen using default logic or\ calculate 1,2,4,8,16 version \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/BitMapConversionLogicFromX11.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/BitMapConversionLogicFromX11.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewBitmapConversion.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewBitmapConversion.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqViewClut.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqMacUnixExternalPrims.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/.DS_Store\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/.DS_Store\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 161 \b \ Date: \b0 Wednesday, December 2, 2009 2:46:02 PM PT \b \ Author: \b0 jmm \b \ \ \b0 Beta 9\ as shipped \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info 64*64.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/DropPlugin/DropPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SecurityPlugin/SecurityPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SocketPlugin/SocketPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SoundPlugin/SoundPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/UUIDPlugin/UUIDPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqNamedPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SecurityPlugin/sqMacSecurity.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudio.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudioAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqMacV2Time.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakEventsAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXDropAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqDummyaio.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqDummyaio.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/plugins/SocketPlugin/sqUnixSocket.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/plugins/UUIDPlugin/sqUnixUUID.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/vm/aio.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 160 \b \ Date: \b0 Wednesday, December 2, 2009 2:16:07 AM PT \b \ Author: \b0 jmm \b \ \ \b0 beta 9\ Add the 64bit image SRC\ fix some implicit routine defs \ \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/.DS_Store\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/plugins\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/plugins.ext\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/plugins.int\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/plugins/IA32ABI\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/.DS_Store\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/interp.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ADPCMCodecPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/AsynchFilePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/AsynchFilePlugin/AsynchFilePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B2DPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B2DPlugin/B2DPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B3DAcceleratorPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BMPReadWriterPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BMPReadWriterPlugin/BMPReadWriterPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BitBltPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/BitBltPlugin/BitBltPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DSAPrims\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DSAPrims/DSAPrims.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DropPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/DropPlugin/DropPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FFTPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FFTPlugin/FFTPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FilePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FilePlugin/FilePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FloatArrayPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/FloatArrayPlugin/FloatArrayPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/GeniePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/GeniePlugin/GeniePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/HostWindowPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/HostWindowPlugin/HostWindowPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/InternetConfigPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/InternetConfigPlugin/InternetConfigPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReadWriter2Plugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReaderPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JPEGReaderPlugin/JPEGReaderPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JoystickTabletPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/JoystickTabletPlugin/JoystickTabletPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Klatt\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Klatt/Klatt.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/LargeIntegers\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/LargeIntegers/LargeIntegers.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MIDIPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MIDIPlugin/MIDIPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MacMenubarPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MacMenubarPlugin/MacMenubarPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Matrix2x3Plugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Matrix2x3Plugin/Matrix2x3Plugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MiscPrimitivePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/RePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/RePlugin/RePlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SecurityPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SecurityPlugin/SecurityPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SerialPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SerialPlugin/SerialPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SocketPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SocketPlugin/SocketPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundCodecPrims\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundCodecPrims/SoundCodecPrims.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundGenerationPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SoundPlugin/SoundPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Squeak3D\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/Squeak3D/Squeak3D.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/StarSqueakPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/StarSqueakPlugin/StarSqueakPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/SurfacePlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/UUIDPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/UUIDPlugin/UUIDPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ZipPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/intplugins/ZipPlugin/ZipPlugin.c\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src64/vm/sqNamedPrims.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqMemoryAccess.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/interp.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqPlatformSpecific.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.h\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 159 \b \ Date: \b0 Tuesday, December 1, 2009 11:20:44 PM PT \b \ Author: \b0 jmm \b \ \ \b0 beta 9 \ Update to vmmaker 153 plus misc fixes for 64bit \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/DropPlugin/DropPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SerialPlugin/SerialPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sq.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/vm/sqMemoryAccess.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakVmAndImagePathAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 151 \b \ Date: \b0 Monday, November 30, 2009 12:17:37 AM PT \b \ Author: \b0 jmm \b \ \ \b0 beta 7\ fix leak of Queue objects\ rework flush force update to avoid leaks of timer \ \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/Queue.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 150 \b \ Date: \b0 Sunday, November 29, 2009 8:44:42 PM PT \b \ Author: \b0 jmm \b \ \ \b0 Beta 7\ \ sqMacUnixExternalPrims.m \ fix some warning msgs\ \ Queue.m\ Queue.h\ add accessor to get queue array so we can iterate over\ \ sqSqueakMainApplication+screen.m\ sqSqueakMainApplication+screen.h\ unionScreenArea, pass rect in, versus pointer\ \ sqSqueakScreenAndWindow.h\ sqSqueakScreenAndWindow.m\ \ Refactor drawing, before we would draw to a drawing queue\ then move items to the frame queue, then schedule a update\ on the view to draw the items from the drawing queue\ \ This didn't work well on os-x. So now we draw to the drawing \ queue, on a frame boundary (explicit or forced) we put the drawing queue to the frame queue, and force a draw on the main thread. \ \ Queues are retain, versus assign\ \ SqueakOSXAppDelegate.m\ update prompt\ Fix issue with path to file to open at launch\ \ sqSqueakOSXApplication+imageReadWrite.m\ Fix issue with path to file to open at launch\ \ \ sqSqueakOSXApplication.m\ compiler warning msgs\ \ sqSqueakOSXDropAPI.m\ Oops set dropInit and dropShutdown return values to 1, versus 0\ \ \ sqSqueakOSXFileDirectoryInterface.m\ Use objective-c 2 iterator\ \ sqSqueakOSXNSView.h\ sqSqueakOSXNSView.m\ Add draw immediate logic\ Use objective-c 2 iterator\ \ \ sqSqueakOSXScreenAndWindow.m\ refactor drawing\ \ SqueakUIController.m\ drop some stale commented out code\ \ SqueakUIView.m\ refactor drawing\ \ \ sqSqueakIPhoneApplication+events.m\ Use objective-c 2 iterator\ \ sqiPhoneScreenAndWindow.m\ postIoForceDisplayUpdateUsingRectangle\ \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/sqMacUnixExternalPrims.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/Queue.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/Queue.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakMainApplication+screen.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakMainApplication+screen.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+imageReadWrite.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXDropAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXFileDirectoryInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIController.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqiPhoneScreenAndWindow.m\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 148 \b \ Date: \b0 Saturday, November 28, 2009 12:21:54 AM PT \b \ Author: \b0 jmm \b \ \ \b0 pre beta 7 check in\ we are adding drag and drop\ resize of os-x window\ ioLoadModule logic\ \ revisions to some funky alloc/release to autorelease patterns. \ \ details \ \ sqSqueakFileDirectoryAPI.m\ \ createFilePathFromString \ needs to better manage autorelease objects\ \ sqSqueakFileDirectoryInterface.h\ sqSqueakFileDirectoryInterface.m\ rename copyResolvedAliasFiles to resolvedAliasFiles\ refractor management of autoreleased objects\ \ sqSqueakScreenAndWindow.m\ force first screen update to catch DOA images\ \ SqueakOSXAppDelegate.m\ enable resize again\ \ macintoshosxextra.c\ ioloadmodule to new class\ \ sqSqueakOSXApplication+events.h\ sqSqueakOSXApplication+events.m\ sqSqueakOSXDropAPI.h\ sqSqueakOSXDropAPI.m\ Add lots of code for drag/drop, not working yet. \ \ sqSqueakOSXFileDirectoryInterface.m\ resolvedAliasFiles\ needs to better manage autorelease objects\ \ sqSqueakOSXNSView.m\ sqSqueakOSXNSView.h\ \ lots added for drag/drop\ \ sqSqueakIPhoneFileDirectoryInterface.m\ resolvedAliasFiles.m\ is always in a auto-release pool, why add another. \ \ \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/sqMacUnixExternalPrims.m\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXDropAPI.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXDropAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/English.lproj/MainMenu.xib\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakFileDirectoryAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakFileDirectoryInterface.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakFileDirectoryInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/macintoshosxextra.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXFileDirectoryInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneFileDirectoryInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/sqNamedPrims.h\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 147 \b \ Date: \b0 Friday, November 27, 2009 2:15:01 PM PT \b \ Author: \b0 jmm \b \ \ \b0 beta 6\ \ sqSqueakSoundCoreAudio.h\ sqSqueakSoundCoreAudio.m\ \ add stop_force, StopAndDispose\ use retain on queues, outputRunning is BOOL\ Buffer number goes from 3 to 4\ Set zero sound fill to 2644 bytes from 512\ Don't make new audioqueue if old one can be reused. \ Don't dispose of audioqueue on regular stop\ In playSamples use MyAudioQueueOutputCallback() to populate queues if required. \ \ sqSqueakOSXSoundCoreAudio.h\ sqSqueakOSXSoundCoreAudio.m\ Override class for os-x to ensure we don't \ restart entire sound system on each squeak stop/start sound\ \ sqSUnitTester.m \ Fix compiler warnings about double constants being returned as float\ \ sqSqueakAttributesAPI.m\ cast strlen to sqInt\ \ sqSqueakFileDirectoryInterface.m\ cast strlen to sqInt\ fix casting for type/creator which are 32bit things\ \ sqSqueakMainApplication\ inputSemaphoreINdex is a sqInt\ \ sqSqueakScreenAPI.m\ ioShowDisplayOnWindow first pram is a unsigned char *, fix \ references, also do pointerForOops in proper place\ \ \ sqSqueakScreenAndWindow.h\ windowIndex is a sqInt \ \ sqSqueakVmAndImagePathAPI.m\ cast strlen to sqInt\ \ SqueakOSXAppDelegate.m\ It's a cocoa squeak 64bit vm, with 32bit image.. \ \ \ sqSqueakOSXSoundCoreAudio.h\ sqSqueakOSXSoundCoreAudio.m\ OS-X override to ensure we start sound system only once. \ \ sqSqueakOSXApplication+clipboard.m\ cast strlen to sqInt\ \ sqSqueakOSXApplication+events.h\ sqSqueakOSXApplication+events.m\ squeak modifier & buttonState is an int\ \ sqSqueakOSXApplication.h\ gMaxHeapSize is a usqInt\ Also setup sound system\ \ \ sqSqueakOSXInfoPlistInterface.h\ sqSqueakOSXInfoPlistInterface.m\ SqueakMaxHeapSize is a usqInt\ \ TSK \ sqMacV2Memory.c\ extern memory is a usqInt not a char *\ some casting of void* to (char*)\ memory is zero if in 64bit mode 32bit image. So fix freeMemory\ \ Various fixes to the Objective-C plugin \ for casting and for long on 64bit is 64bits wide. \ \b \ \ Changes:\ \b0 A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/RePlugin/configx.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/plugins\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/plugins/SoundPlugin\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.h\ A /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.m\ D /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/RePlugin/config.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/RePlugin/internal.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudio.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SoundPlugin/sqSqueakSoundCoreAudio.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SqueakObjectiveC/squeakSUnitTester.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakAttributesAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakFileDirectoryInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakMainApplication.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakVmAndImagePathAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+clipboard.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXInfoPlistInterface.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXInfoPlistInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqMacV2Memory.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/interp.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/HostWindowPlugin/HostWindowPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ObjectiveCPlugin/ObjectiveCPlugin.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/Squeak3D/Squeak3D.c\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 146 \b \ Date: \b0 Thursday, November 26, 2009 7:29:49 PM PT \b \ Author: \b0 jmm \b \ \ \b0 HostWindowPlugin.h\ 64bit prep work\ For all usages of int make those sqInt\ \ SecurityPlugin.h\ SecurityPlugin.c\ inDisableImageWrite/ioCanWriteImage/ioCanRenameImage are sqInt\ \ \ sqSqueakCursorAPI.m\ 64bit prep work\ For all usages of int make those sqInt\ ioSetCursor\ \ sqSqueakScreenAPI.m\ 64bit prep work\ For all usages of int make those sqInt\ ioShowDisplayOnWindow\ \ SqueakOSXAppDelegate.h\ For 10.5 build add protocol NSApplicationDelegate def\ \ SqueakOSXAppDelegate.m\ setInitialFirstResponder\ \ macintoshosxextra.c\ For all usages of int make those squint\ \ sqSqueakOSXNSView.m\ 10.5 only calls insertText: (bug)\ enable option/shift for esc/tab/return/cursor/page\ \ sqSqueakOSXScreenAndWindow.h\ For 10.5 build add protocol NSWndowDelegate def\ \ sqMacV2Memory.c\ sqMemoryBase set memory base on squeak vmmaker defs, not x64\ \ \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/HostWindowPlugin/HostWindowPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Cross/plugins/SecurityPlugin/SecurityPlugin.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/plugins/SecurityPlugin/sqMacSecurity.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakCursorAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAPI.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/macintoshosxextra.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+attributes.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/plugins/HostWindowPlugin/sqMacHostWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/iPhone/sqMacV2Memory.c\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/src/vm/intplugins/ObjectiveCPlugin/ObjectiveCPlugin.c\ \f0\fs24 \ \f1\b\fs22 File: \b0 /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/SqueakPureObjc.xcodeproj/project.pbxproj \b \ Revision: \b0 145 \b \ Date: \b0 Wednesday, November 25, 2009 11:49:52 PM PT \b \ Author: \b0 jmm \b \ \ \b0 beta 3\ Update powerpc compiler options. \ \ sqSqueakMainApplication+vmAndImagePath.m\ 10.6 URL call backported to 10.5\ \ SqueakOSXAppDelegate.m\ mess with window open code\ fix window title\ \ sqSqueakOSXApplication+events.m\ sqSqueakOSXApplication+events.h\ Add wheel mouse logic\ \ sqSqueakOSXApplication+imageReadWrite.m\ Add override for setting window title\ \ sqSqueakOSXInfoPlistInterface.m\ 10.6 URL call backported to 10.5\ \ sqSqueakOSXNSView.m\ 10.6 cursor call backported to 10.5\ Add wheel mouse logic\ \ sqSqueakOSXScreenAndWindow.h\ retain timer for forced flush\ \ sqSqueakOSXScreenAndWindow.m\ timer was not reset correctly for 2nd+ flushes\ This caused drawing problems. \b \ \ Changes:\ \b0 M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/English.lproj/MainMenu.xib\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc-Info.plist\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.mode1v3\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/johnmci.pbxuser\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/SqueakPureObjc.xcodeproj/project.pbxproj\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakScreenAndWindow.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/SqueakOSXAppDelegate.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+events.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXApplication+imageReadWrite.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXInfoPlistInterface.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXNSView.m\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.h\ M /SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhone/platforms/Mac OSObjC/vm/OSX/sqSqueakOSXScreenAndWindow.m \f0\fs24 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \cf0 \ } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/Queue.h ================================================ /* File: Queue.h Abstract: Interface file for the Queue class. This class makes use of the NSMutableArray to define and maintain a standard queue data structure to hold Cocoa objects. Objects can be added & removed from the queue as desired and their order at insertion time is maintained. Version: 1.0 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright (C) 2007 Apple Inc. All Rights Reserved. */ @interface Queue : NSObject { NSMutableArray *mItemArray; } -(NSUInteger) pendingElements; -(id)returnAndRemoveOldest; -(id)returnOldest; -(void)addItem:(id)anItem; -(NSArray *) elements; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/Queue.m ================================================ /* File: Queue.m Abstract: Implementation file for the Queue class. This class makes use of the NSMutableArray to define and maintain a standard queue data structure to hold Cocoa objects. Objects can be added & removed from the queue as desired and their order at insertion time is maintained. Version: 1.0 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright (C) 2007 Apple Inc. All Rights Reserved. */ #import "Queue.h" @implementation Queue // Initialize a empty mutable array for queue items // which we can fill - (id) init { self = [super init]; { mItemArray = [[NSMutableArray alloc] initWithCapacity :10]; } return self; } // Returns (and removes) the oldest item in the queue -(id)returnAndRemoveOldest { id anObject = nil; @synchronized(self) { anObject = [mItemArray lastObject]; if (anObject) { [anObject retain]; [mItemArray removeLastObject]; } } return anObject; } // Returns the oldest item in the queue or nil -(id)returnOldest { id anObject = nil; @synchronized(self) { anObject = [mItemArray lastObject]; } return anObject; } // Adds the specified item to the queue -(void)addItem:(id)anItem { @synchronized(self) { [mItemArray insertObject:anItem atIndex:0]; } } -(NSUInteger) pendingElements { return [mItemArray count]; } - (NSArray *) elements { return mItemArray; } - (void) dealloc { [mItemArray release]; [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqMacV2Time.c ================================================ /* * sqMacV2Time.c * * * Created by John M McIntosh on 5/12/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * Small parts of this code is * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "sq.h" #include "sqDummyaio.h" #include "sqMacV2Time.h" #include <sys/types.h> #include <sys/time.h> static struct timeval startUpTime; #if STACKVM /* all three methods have their roots in the original unix port from the late 90's */ /* * In the Cog VMs time management is in platforms/unix/vm/sqUnixHeartbeat.c. */ /* * Compute the time via the old method for sanity checking purposes. */ int ioOldMSecs() { struct timeval now; gettimeofday(&now, 0); if ((now.tv_usec-= startUpTime.tv_usec) < 0) { now.tv_usec+= 1000000; now.tv_sec-= 1; } now.tv_sec-= startUpTime.tv_sec; return (now.tv_usec / 1000 + now.tv_sec * 1000); } void SetUpTimers(void) { extern void ioInitTime(void); /* set up the backwardcompatibility micro/millisecond clock */ gettimeofday(&startUpTime, 0); /* setup the spiffy new 64-bit microsecond clock. */ ioInitTime(); } #else /* STACKVM */ void SetUpTimers(void) { /* set up the micro/millisecond clock */ gettimeofday(&startUpTime, 0); } sqLong ioMicroSeconds(void) { //API Documented struct timeval now; sqLong theTimeIs; gettimeofday(&now, 0); if ((now.tv_usec-= startUpTime.tv_usec) < 0) { now.tv_usec+= 1000000; now.tv_sec-= 1; } now.tv_sec-= startUpTime.tv_sec; theTimeIs = now.tv_usec; theTimeIs = theTimeIs + now.tv_sec * 1000000; return theTimeIs; } sqInt ioMicroMSecs(void) { //API Documented struct timeval now; sqInt theTimeIs; gettimeofday(&now, 0); if ((now.tv_usec-= startUpTime.tv_usec) < 0) { now.tv_usec+= 1000000; now.tv_sec-= 1; } now.tv_sec-= startUpTime.tv_sec; theTimeIs = ((now.tv_usec / 1000 + now.tv_sec * 1000) & MillisecondClockMask); return theTimeIs; } sqInt ioMSecs(void) { //API Documented return ioMicroMSecs(); } sqInt ioSeconds(void) { //API Documented time_t unixTime; sqInt theSecondsAre; unixTime = time(0); unixTime += localtime(&unixTime)->tm_gmtoff; /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970: 17 leap years and 52 non-leap years later than Squeak. */ theSecondsAre = unixTime + ((52*365UL + 17*366UL) * 24*60*60UL); return theSecondsAre; } sqInt ioUtcWithOffset(sqLong *microSeconds, int *offset) { struct timeval timeval; if (gettimeofday(&timeval, NULL) == -1) return -1; time_t seconds = timeval.tv_sec; suseconds_t usec = timeval.tv_usec; *microSeconds = seconds * 1000000 + usec; *offset = localtime(&seconds)->tm_gmtoff; return 0; } sqInt ioRelinquishProcessorForMicroseconds(sqInt microSeconds) { //API Documented /* This operation is platform dependent. */ #pragma unused(microSeconds) extern sqInt setInterruptCheckCounter(sqInt value); //This is a VM Callback # if ROAR_VM aioSleep(0); setInterruptCheckCounter(0); # else sqInt realTimeToWait,now,next; extern sqInt getNextWakeupTick(void); //This is a VM Callback setInterruptCheckCounter(0); now = ioMSecs(); next = getNextWakeupTick(); /*BUG??? what if clock wraps? */ if (next <= now) if (next == 0) realTimeToWait = 16; else { return 0; } else realTimeToWait = next - now; aioSleep((int) realTimeToWait*1000); # endif // !ROAR_VM return 0; } #endif /* STACKVM */ ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqMacV2Time.h ================================================ /* * sqMacV2Time.h * * * Created by John M McIntosh on 5/12/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ void SetUpTimers(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakAppDelegate.h ================================================ // // sqSqueakAppDelegate.h // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // 10/01/08 add <UIAccelerometerDelegate> // #import <Foundation/Foundation.h> #import "sqSqueakMainApplication.h" @interface sqSqueakAppDelegate : NSObject { sqSqueakMainApplication *squeakApplication; } @property (nonatomic,retain) sqSqueakMainApplication *squeakApplication; - (void) makeMainWindowOnMainThread ; - (void) makeMainWindow; - (id) createPossibleWindow; - (NSTimeInterval) squeakUIFlushPrimaryDeferNMilliseconds; - (sqSqueakMainApplication *) makeApplicationInstance; - (void) workerThreadStart; - (void) singleThreadStart; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakAppDelegate.m ================================================ // // sqSqueakAppDelegate.m // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakAppDelegate.h" #import "sqMacHostWindow.h" @implementation sqSqueakAppDelegate @synthesize squeakApplication; - (void) makeMainWindow { /*Beware creating a main window must be done on main thread it will not work from this interpreter squeak thread */ sqInt width,height; windowDescriptorBlock *windowBlock; id createdWindow = [self createPossibleWindow]; extern sqInt getSavedWindowSize(void); //This is VM Callback extern sqInt setSavedWindowSize(sqInt value); //This is VM Callback /* get old window size */ width = ((unsigned) getSavedWindowSize()) >> 16; height = getSavedWindowSize() & 0xFFFF; windowBlock = AddWindowBlock(); windowBlock-> handle = createdWindow; windowBlock->context = nil; windowBlock->updateArea = CGRectZero; width = (usqInt) ioScreenSize() >> 16; height = ioScreenSize() & 0xFFFF; setSavedWindowSize( (width << 16) |(height & 0xFFFF)); windowBlock->width = width; windowBlock->height = height; extern sqInt getFullScreenFlag(void); ioSetFullScreen(getFullScreenFlag()); } - (sqSqueakMainApplication *) makeApplicationInstance { return nil; } - (NSTimeInterval) squeakUIFlushPrimaryDeferNMilliseconds { return 0.0333f; } - (void) makeMainWindowOnMainThread {}; - (id) createPossibleWindow { return NULL;}; - (void) workerThreadStart { // Run the squeak process in a worker thread NSThread* myThread = [[NSThread alloc] initWithTarget: self.squeakApplication selector: @selector(runSqueak) object:nil]; #if COGVM [myThread setStackSize: [myThread stackSize]*4]; #endif [myThread start]; } - (void) singleThreadStart { /* This the carbon logic model described by http://developer.apple.com/qa/qa2001/qa1061.html */ [[NSRunLoop mainRunLoop] performSelector: @selector(runSqueak) target: self.squeakApplication argument: nil order: 1 modes: [NSArray arrayWithObject: NSDefaultRunLoopMode]]; } - (void)dealloc { [squeakApplication release]; [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakAttributesAPI.h ================================================ // // sqSqueakAttributesAPI.h // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakAttributesAPI.m ================================================ // // sqSqueakAttributesAPI.m // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakAttributesAPI.h" #import "sq.h" #import "sqSqueakAppDelegate.h" #import "sqSqueakMainApplication+attributes.h" extern sqSqueakAppDelegate *gDelegateApp; sqInt attributeSize(sqInt indexNumber) { //API Documented return (sqInt) strlen([gDelegateApp.squeakApplication getAttribute: indexNumber]); } sqInt getAttributeIntoLength(sqInt indexNumber, sqInt byteArrayIndex, sqInt length) { //API Documented [gDelegateApp.squeakApplication getAttribute: indexNumber into: pointerForIndex_xxx_dmu((usqInt) byteArrayIndex) length: length]; return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakCursorAPI.h ================================================ // // sqSqueakCursorAPI.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakCursorAPI.m ================================================ // // sqSqueakCursorAPI.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakCursorAPI.h" #import "sqSqueakAppDelegate.h" #import "sqSqueakMainApplication+cursor.h" #import "sqSqueakOSXApplication+cursor.h" extern sqSqueakAppDelegate *gDelegateApp; sqInt ioSetCursor(sqInt cursorBitsIndex, sqInt offsetX, sqInt offsetY) { /* Old version; forward to new version. */ [gDelegateApp.squeakApplication setCursor: cursorBitsIndex withMask: 0 offsetX: offsetX offsetY: offsetY]; return 0; } sqInt ioSetCursorWithMask( sqInt cursorBitsIndex, sqInt cursorMaskIndex, sqInt offsetX, sqInt offsetY) { [gDelegateApp.squeakApplication setCursor: cursorBitsIndex withMask: cursorMaskIndex offsetX: offsetX offsetY: offsetY]; return 0; } sqInt ioSetCursorARGB(sqInt cursorBitsIndex, sqInt extentX, sqInt extentY, sqInt offsetX, sqInt offsetY) { return [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication ioSetCursorARGB: cursorBitsIndex extentX: extentX extentY: extentY offsetX: offsetX offsetY: offsetY]; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakEventsAPI.h ================================================ // // sqSqueakEventsAPI.h // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakEventsAPI.m ================================================ // // sqSqueakEventsAPI.m // // // Created by John M McIntosh on 6/14/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakAppDelegate.h" #import "sqSqueakEventsAPI.h" #import "sqSqueakMainApplication+events.h" #import "sqSqueakScreenAndWindow.h" #import "sqaio.h" extern sqSqueakAppDelegate *gDelegateApp; extern struct VirtualMachine* interpreterProxy; extern BOOL gQuitNowRightNow; extern sqSqueakScreenAndWindow *getMainWindowDelegate(); sqInt ioProcessEvents(void) { //API Documented aioPoll(0); if ([getMainWindowDelegate() forceUpdateFlush]) { [getMainWindowDelegate() ioForceDisplayUpdate]; } if (interpreterProxy->methodPrimitiveIndex() != 0) { [gDelegateApp.squeakApplication pumpRunLoop]; } if (gQuitNowRightNow) { ioExit(); //This might not return, might call exittoshell } return 0; } sqInt ioSetInputSemaphore(sqInt semaIndex) { //API Documented gDelegateApp.squeakApplication.inputSemaphoreIndex = semaIndex; return 0; } sqInt ioGetNextEvent( sqInputEvent *evt) { //API Documented [gDelegateApp.squeakApplication ioGetNextEvent: evt]; /* if (evt->type != 0) { NSLog(@"evt.type %i keyboard pc %i cc %i uc %i m %i",evt->type,((sqKeyboardEvent *)evt)->pressCode,((sqKeyboardEvent *) evt)->charCode,((sqKeyboardEvent *) evt)->utf32Code,((sqKeyboardEvent *) evt)->modifiers); } */ return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.h ================================================ // // sqSqueakFileDirectoryAPI.h // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #import "sq.h" NSString* createFilePathFromString(char * aFilenameString, sqInt filenameLength, sqInt resolveAlias); ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.m ================================================ // // sqSqueakFileDirectoryAPI.m // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. V1.05b1 Add auto release pool to wrap getting directory information V1.05b1 fix issue with sqGetFilenameFromString when getting target of symbolic link ensure we make a copy */ // #import "sqSqueakFileDirectoryAPI.h" #import "sqSqueakAppDelegate.h" #import "sq.h" #import "FilePlugin.h" #define DELIMITERInt '/' extern sqSqueakAppDelegate *gDelegateApp; sqInt dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator){ //API Documented /* filename is file name filenameSize is size of file name fType and fCreator is type and creator codes (4 bytes preallocated) */ NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_GetMacFileTypeAndCreator: filename fileNameSize: filenameSize fType: fType fCreator: fCreator]; [pool drain]; return status; } sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { //API Documented /* filename is file name filenameSize is size of file name fType and fCreator is type and creator codes (4 bytes) */ NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_SetMacFileTypeAndCreator: filename fileNameSize: filenameSize fType: fType fCreator: fCreator]; [pool drain]; return status; } sqInt dir_Delimitor(void) { //API Documented return DELIMITERInt; } sqInt dir_Lookup(char *pathString, sqInt pathStringLength, sqInt index, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { //API Documented /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries 2 if the given path has bad syntax or does not reach a directory */ /*Implementation notes if pathStringLength = 0 then we use the current working directory if pathStringLength > 0 then we resolve the pathString and alias */ NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_Lookup: pathString length: pathStringLength index: index name: name length: nameLength creationDate: creationDate modificationDate: modificationDate isDirectory: isDirectory sizeIfFile: sizeIfFile]; [pool drain]; return status; } sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char* nameString, sqInt nameStringLength, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_EntryLookup: pathString length: pathStringLength returnName: nameString returnNameLength: nameStringLength name: name length: nameLength creationDate: creationDate modificationDate: modificationDate isDirectory: isDirectory sizeIfFile: sizeIfFile]; [pool drain]; return status; } sqInt dir_Create(char *pathString, sqInt pathStringLength){ //API Documented NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_Create: pathString length: pathStringLength]; [pool drain]; return status; } sqInt dir_Delete(char *pathString, sqInt pathStringLength){ NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt status = [gDelegateApp.squeakApplication.fileDirectoryLogic dir_Delete: pathString length: pathStringLength]; [pool drain]; return status; } NSString* createFilePathFromString(char * aFilenameString, sqInt filenameLength, sqInt resolveAlias) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSString * filePath = [[[NSString alloc] initWithBytes: aFilenameString length: (NSUInteger) filenameLength encoding: NSUTF8StringEncoding] autorelease]; if (!filePath) { [pool drain]; return NULL; } if (resolveAlias) { filePath = [gDelegateApp.squeakApplication.fileDirectoryLogic resolvedAliasFiles: filePath]; } else { NSString *owningDirectoryPath = [filePath stringByDeletingLastPathComponent]; NSString *newFilePath = [gDelegateApp.squeakApplication.fileDirectoryLogic resolvedAliasFiles: owningDirectoryPath]; filePath = [newFilePath stringByAppendingPathComponent: [filePath lastPathComponent]]; } [filePath retain]; [pool drain]; return filePath; } sqInt sqGetFilenameFromString(char * aCharBuffer, char * aFilenameString, sqInt filenameLength, sqInt resolveAlias) { //API Documented BOOL ok; if (!aCharBuffer || !aFilenameString) return 0; NSString *filePath = createFilePathFromString(aFilenameString,filenameLength,resolveAlias); ok = [filePath getFileSystemRepresentation: aCharBuffer maxLength: 1000]; //1000 is coded by callers, really should pass in, but historical issue, this also includes null byte which is accounted for by maxLength //Obviously this is a problem that lets a caller do a buffer overflow? [filePath release]; return 0; } /* This routine is exposed but no-one seems to call it from the VM in the past the macintosh VM used this to set the working directory based on where the VM was opened from, but it seems now post os-x no-one uses it */ sqInt dir_PathToWorkingDir(char *pathName, sqInt pathNameMax){ //API Documented return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakFileDirectoryInterface.h ================================================ // // sqSqueakFileDirectoryInterface.h // // // Created by John M McIntosh on 6/14/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #import "sq.h" @interface sqSqueakFileDirectoryInterface : NSObject { NSString* lastPathForDirLookup; NSInteger lastIndexForDirLookup; NSArray * directoryContentsForDirLookup; } - (BOOL) setWorkingDirectory; - (sqInt) dir_EntryLookup: (const char *) pathString length: (sqInt) pathStringLength returnName: (char *) nameString returnNameLength: (sqInt) nameStringLength name: (char *) name length: (sqInt *) nameLength creationDate: (sqInt *) creationDate modificationDate: (sqInt *) modificationDate isDirectory: (sqInt *) isDirectory sizeIfFile: (squeakFileOffsetType *) sizeIfFile; - (sqInt) dir_Lookup: (const char *) pathString length: (sqInt) pathStringLength index: (sqInt) index name: (char *) name length: (sqInt *) nameLength creationDate: (sqInt *) creationDate modificationDate: (sqInt *) modificationDate isDirectory: (sqInt *) isDirectory sizeIfFile: (squeakFileOffsetType *) sizeIfFile; - (sqInt) dir_Create: (char *) pathString length: (sqInt) pathStringLength; - (sqInt) dir_Delete: (char *) pathString length: (sqInt) pathStringLength; - (sqInt) dir_GetMacFileTypeAndCreator: (char *) filename fileNameSize: (sqInt) filenameSize fType: (char *) fType fCreator: (char *) fCreator; - (sqInt) dir_SetMacFileTypeAndCreator: (char *) filename fileNameSize: (sqInt) filenameSize fType: (char *) fType fCreator: (char *) fCreator; - (NSString *) resolvedAliasFiles: (NSString *) filePath; @property (nonatomic,retain) NSString* lastPathForDirLookup; @property (nonatomic,assign) NSInteger lastIndexForDirLookup; @property (nonatomic,retain) NSArray * directoryContentsForDirLookup; @end sqInt convertToSqueakTime(NSDate *givenDate); ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakFileDirectoryInterface.m ================================================ // // sqSqueakFileDirectoryInterface.m // // // Created by John M McIntosh on 6/14/08. // // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakFileDirectoryInterface.h" #import "sqSqueakFileDirectoryAPI.h" @implementation sqSqueakFileDirectoryInterface @synthesize lastPathForDirLookup; @synthesize lastIndexForDirLookup; @synthesize directoryContentsForDirLookup; - (BOOL) setWorkingDirectory { // "changeCurrentDirectoryPath:(" return YES; } - (sqInt) dir_EntryLookup: (const char *) pathString length: (sqInt) pathStringLength returnName: (char *) nameString returnNameLength: (sqInt) nameStringLength name: (char *) name length: (sqInt *) nameLength creationDate: (sqInt *) creationDate modificationDate: (sqInt *) modificationDate isDirectory: (sqInt *) isDirectory sizeIfFile: (squeakFileOffsetType *) sizeIfFile { #warning this is not implementation return 0; } - (sqInt) dir_Lookup: (const char *) pathString length: (sqInt) pathStringLength index: (sqInt) index name: (char *) name length: (sqInt *) nameLength creationDate: (sqInt *) creationDate modificationDate: (sqInt *) modificationDate isDirectory: (sqInt *) isDirectory sizeIfFile: (squeakFileOffsetType *) sizeIfFile { NSFileManager * fileMgr = [NSFileManager defaultManager]; NSString* directoryPath = NULL; NSString* filePath; NSString* fileName; NSDictionary * fileAttributes; BOOL readDirectory = false; /*** Constants ***/ #define ENTRY_FOUND 0 #define NO_MORE_ENTRIES 1 #define BAD_PATH 2 /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if (pathStringLength <= 0) { self.lastPathForDirLookup =[fileMgr currentDirectoryPath]; } if (pathStringLength > 0) directoryPath = [[[NSString alloc] initWithBytes: pathString length: (NSUInteger) pathStringLength encoding: NSUTF8StringEncoding] autorelease]; if (directoryPath == NULL) return BAD_PATH; if ([self.lastPathForDirLookup isEqualToString: directoryPath]) { if (lastIndexForDirLookup >= index) readDirectory = true; } else { readDirectory = true; } if (readDirectory) { self.directoryContentsForDirLookup = [fileMgr contentsOfDirectoryAtPath: directoryPath error: NULL]; if (!directoryContentsForDirLookup) { NSString *newFilePath = [self resolvedAliasFiles: directoryPath]; self.directoryContentsForDirLookup = [fileMgr contentsOfDirectoryAtPath: newFilePath error: NULL]; if (!directoryContentsForDirLookup) { return BAD_PATH; } else { self.lastPathForDirLookup = directoryPath; } } else { self.lastPathForDirLookup = directoryPath; } } lastIndexForDirLookup = index; //Note index is 1 based, but objc is 0 based if (index < 1 || (NSUInteger) index > [directoryContentsForDirLookup count]) return NO_MORE_ENTRIES; filePath = [ directoryContentsForDirLookup objectAtIndex: (NSUInteger) (index-1)]; filePath = [[ lastPathForDirLookup stringByAppendingString: @"/"] stringByAppendingString: filePath] ; fileName = [[filePath lastPathComponent] precomposedStringWithCanonicalMapping]; strlcpy(name,[fileName UTF8String],256); *nameLength = (sqInt) strlen(name); //This minics the unix port where we resolve the file name, but the symbolic file lookup can fail. //The unix port says, oh file was there, but stat/lstat fails, so mmm kinda continue //However to deal with Finder Aliases we have to be more clever. NSError *error; NSString *fileType; NSString *newFilePath = [self resolvedAliasFiles: filePath]; fileAttributes = [fileMgr attributesOfItemAtPath: filePath error: &error]; if ([filePath isEqualToString: newFilePath]) { if (!fileAttributes) { return ENTRY_FOUND; } fileType = [fileAttributes objectForKey: NSFileType]; *isDirectory = [fileType isEqualToString: NSFileTypeDirectory] ? 1 : 0; } else { NSDictionary *fileAttributesPossibleAlias = [fileMgr attributesOfItemAtPath: newFilePath error: &error]; // do symbolic link fileAttributes = fileAttributesPossibleAlias; fileType = [fileAttributesPossibleAlias objectForKey: NSFileType]; *isDirectory = [fileType isEqualToString: NSFileTypeDirectory] ? 1 : 0; } *creationDate = convertToSqueakTime([fileAttributes objectForKey: NSFileCreationDate ]); *modificationDate = convertToSqueakTime([fileAttributes objectForKey: NSFileModificationDate]); *sizeIfFile = [[fileAttributes objectForKey: NSFileSize] integerValue]; /* POSSIBLE IPHONE BUG CHECK */ if (*creationDate == 0) *creationDate = *modificationDate; return ENTRY_FOUND; } - (sqInt) dir_Create: (char *) pathString length: (sqInt) pathStringLength; { NSFileManager * fileMgr = [NSFileManager defaultManager]; NSString* directoryPath = NULL; BOOL ok; if (pathString == nil || pathStringLength <= 0 || pathStringLength >= PATH_MAX) //This is not a null terminated string so >= versus > return 0; directoryPath = createFilePathFromString(pathString,pathStringLength, 1); if (directoryPath == NULL) return 0; #warning what file permissions are used here? Defaults according to the manual, but unix port sets permissions & with defaults NSError *error; ok = [fileMgr createDirectoryAtPath: directoryPath withIntermediateDirectories: NO attributes: NULL error: &error]; [directoryPath release]; return ok; } - (sqInt) dir_Delete: (char *) pathString length: (sqInt) pathStringLength; { NSFileManager * fileMgr = [NSFileManager defaultManager]; NSString* directoryPath = NULL; BOOL ok; NSArray *directoryContentsForDirLookupCheck; if (pathString == nil || pathStringLength <= 0 || pathStringLength >= PATH_MAX) //This is not a null terminated string so >= versus > return 0; directoryPath = createFilePathFromString(pathString,pathStringLength, 1); if (directoryPath == NULL) return 0; NSError *error; directoryContentsForDirLookupCheck = [fileMgr contentsOfDirectoryAtPath: directoryPath error: &error]; if (directoryContentsForDirLookupCheck == NULL || ([directoryContentsForDirLookupCheck count])) { /* We don't recursive delete directory, that is too dangerous, let the squeak programmer do it which is why if the directory content count is > 0 we abort the delete */ [directoryPath release]; return 0; } /* The call below deletes the file, link, or directory (including, recursively, all subdirectories, files, and links in the directory) identified by a given path. See comment above to protect against disaster, so in theory the directory has to be empty */ ok = [fileMgr removeItemAtPath: directoryPath error: NULL]; /*Ensure we note we need to clean up the cached directory */ if (lastPathForDirLookup) { self.lastPathForDirLookup = NULL; } [directoryPath release]; return ok; } - (sqInt) dir_GetMacFileTypeAndCreator: (char *) filename fileNameSize: (sqInt) filenameSize fType: (char *) fType fCreator: (char *) fCreator { NSFileManager * fileMgr = [NSFileManager defaultManager]; if (filename == nil || filenameSize <= 0 || !fType || !fCreator) return 0; bzero(fType, 4); bzero(fCreator, 4); NSString *filePath = createFilePathFromString(filename,filenameSize, 1); if (!filePath) return 0; NSError *error; NSDictionary * fileAttributes = [fileMgr attributesOfItemAtPath:filePath error:&error]; [filePath release]; if (!fileAttributes) return 0; NSNumber *typeCode = [fileAttributes objectForKey: NSFileHFSTypeCode]; NSNumber *creatorCode = [fileAttributes objectForKey: NSFileHFSCreatorCode]; if (creatorCode == NULL || typeCode == NULL) return 0; *((uint32_t *) fType) = (uint32_t) CFSwapInt32BigToHost([typeCode unsignedIntValue]); *((uint32_t *) fCreator)= (uint32_t) CFSwapInt32BigToHost([creatorCode unsignedIntValue]); return 1; } - (sqInt) dir_SetMacFileTypeAndCreator: (char *) filename fileNameSize: (sqInt) filenameSize fType: (char *) fType fCreator: (char *) fCreator { NSFileManager * fileMgr = [NSFileManager defaultManager]; if (filename == nil || filenameSize <= 0 || !fType || !fCreator) return 0; NSString *filePath = createFilePathFromString(filename,filenameSize, 1); if (!filePath) { return 0; } NSNumber *typeCode,*creatorCode; typeCode = [NSNumber numberWithUnsignedLong: CFSwapInt32HostToBig(*((uint32_t *) fType))]; creatorCode = [NSNumber numberWithUnsignedLong: CFSwapInt32HostToBig(*((uint32_t *) fCreator))]; NSMutableDictionary *fileAttributes = [NSMutableDictionary new]; [fileAttributes setObject: typeCode forKey: NSFileHFSTypeCode]; [fileAttributes setObject: creatorCode forKey: NSFileHFSCreatorCode]; BOOL ok=[fileMgr setAttributes: fileAttributes ofItemAtPath: filePath error: NULL]; [fileAttributes release]; [filePath release]; return ok; } - (NSString *) resolvedAliasFiles: (NSString *) filePath { return filePath; } - (void)dealloc { [super dealloc]; [lastPathForDirLookup release]; [directoryContentsForDirLookup release]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakInfoPlistInterface.h ================================================ // // sqSqueakInfoPlistInterface.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 9/1/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/NSUserDefaults.h> @interface sqSqueakInfoPlistInterface : NSObject { NSUserDefaults* defaults; BOOL SqueakUseFileMappedMMAP; } - (void) parseInfoPlist; @property (nonatomic,retain) NSUserDefaults* defaults; @property (nonatomic,assign) BOOL SqueakUseFileMappedMMAP; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakInfoPlistInterface.m ================================================ // // sqSqueakInfoPlistInterface.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 9/1/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakInfoPlistInterface.h" @implementation sqSqueakInfoPlistInterface @synthesize defaults,SqueakUseFileMappedMMAP; - (void) parseInfoPlist { self.defaults = [NSUserDefaults standardUserDefaults]; /* Debug code, dump user defaults to NSLog so we can determine what settings the user has NSDictionary * foodictionaryRepresentation; foodictionaryRepresentation = [defaults dictionaryRepresentation]; for (id key in foodictionaryRepresentation) { NSLog(@"key: %@, value: %@", key, [foodictionaryRepresentation objectForKey:key]); } */ return; } - (void)dealloc { [super dealloc]; [defaults release]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApp.h ================================================ /* * sqSqueakMainApp.h * * * Created by John M McIntosh on 5/15/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // void sigsegv(int ignore); void mtfsfi(unsigned long long fpscr); void fldcw(unsigned int cw); ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApp.m ================================================ /* * sqSqueakMainApp.m * * * Created by John M McIntosh on 5/15/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * Small parts of this code is * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakAppDelegate.h" #import "sq.h" #import "sqSqueakMainApp.h" #import "sqMacV2Memory.h" #import <limits.h> #warning what about these guyes? /*** Variables -- globals for access from pluggable primitives ***/ EXPORT(int) argCnt= 0; EXPORT(char**) argVec= 0; EXPORT(char**) envVec= 0; extern sqSqueakAppDelegate *gDelegateApp; BOOL gQuitNowRightNow=false,gSqueakHeadless=false; int gSqueakUseFileMappedMMAP=0; char gSqueakUntrustedDirectoryName[PATH_MAX]; char gSqueakTrustedDirectoryName[PATH_MAX]; sqInt printAllStacks(void); sqInt printCallStack(void); extern void dumpPrimTraceLog(void); extern BOOL NSApplicationLoad(void); #if COGVM || STACKVM /* Print an error message, possibly a stack trace, and exit. */ /* Disable Intel compiler inlining of error which is used for breakpoints */ #pragma auto_inline off void error(char *msg) { /* flag prevents recursive error when trying to print a broken stack */ static sqInt printingStack = false; printf("\n%s\n\n", msg); if (ioOSThreadsEqual(ioCurrentOSThread(),getVMOSThread())) { if (!printingStack) { printingStack = true; printf("\n\nSmalltalk stack dump:\n"); printCallStack(); } } else printf("\nCan't dump Smalltalk stack. Not in VM thread\n"); printf("\nMost recent primitives\n"); dumpPrimTraceLog(); abort(); } #pragma auto_inline on void sigsegv(int ignore) { #pragma unused(ignore) error("Segmentation fault"); } #else void sigsegv(int ignore) { #pragma unused(ignore) /* error("Segmentation fault"); */ static int printingStack= 0; printf("\nSegmentation fault\n\ns"); if (!printingStack) { printingStack= 1; printAllStacks(); } abort(); } #endif sqInt ioExit(void) { //API Documented [gDelegateApp.squeakApplication ioExit]; return 0; } sqInt ioExitWithErrorCode(int ec) { //API Documented [gDelegateApp.squeakApplication ioExitWithErrorCode: ec]; return 0; } sqInt ioDisablePowerManager(sqInt disableIfNonZero) { //API Documented return 0; } #if COGVM /* * Support code for Cog. * a) Answer whether the C frame pointer is in use, for capture of the C stack * pointers. */ # if defined(i386) || defined(__i386) || defined(__i386__) /* * Cog has already captured CStackPointer before calling this routine. Record * the original value, capture the pointers again and determine if CFramePointer * lies between the two stack pointers and hence is likely in use. This is * necessary since optimizing C compilers for x86 may use %ebp as a general- * purpose register, in which case it must not be captured. */ int isCFramePointerInUse() { extern unsigned long CStackPointer, CFramePointer; extern void (*ceCaptureCStackPointers)(void); unsigned long currentCSP = CStackPointer; currentCSP = CStackPointer; ceCaptureCStackPointers(); assert(CStackPointer < currentCSP); return CFramePointer >= CStackPointer && CFramePointer <= currentCSP; } # endif /* defined(i386) || defined(__i386) || defined(__i386__) */ #endif /* COGVM */ /* Andreas' stubs */ char* ioGetLogDirectory(void) { return ""; }; sqInt ioSetLogDirectoryOfSize(void* lblIndex, sqInt sz){ return 1; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+attributes.h ================================================ // // sqSqueakMainApplication+attributes.h // // Created by John M McIntosh on 5/22/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (attributes) - (void) getAttribute:(sqInt) indexNumber into:(char *) byteArray length:(sqInt) length; - (const char *) getAttribute:(sqInt) indexNumber; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+attributes.m ================================================ // // sqSqueakMainApplication+attributes.m // // Created by John M McIntosh on 5/22/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication+attributes.h" #import "sqSqueakMainApplication+vmAndImagePath.h" extern struct VirtualMachine* interpreterProxy; @implementation sqSqueakMainApplication (attributes) - (void) getAttribute:(sqInt)indexNumber into:(char *) byteArrayIndex length:(sqInt)length { //indexNumber is a postive/negative number //byteArrayIndex is actually the address of where to put the data //length is how many bytes the target can hold if(!byteArrayIndex) return; *byteArrayIndex = 0x00; if (length > 0) strncpy(byteArrayIndex, [self getAttribute: indexNumber], (size_t) length); //This does not need to be strlcpy } - (const char *) getAttribute:(sqInt)indexNumber { //indexNumber is a postive/negative number if (indexNumber < 0) /* VM argument */ { if (-indexNumber <= [self.argsArguments count]) return (char *) [self.argsArguments objectAtIndex: (NSUInteger) (-indexNumber - 1)]; } else { switch (indexNumber) { case 0: return (char *) [self getVMPath]; case 1: return (char *) [self getImageName]; case 1004: { /* Interpreter version string */ static char data[255]; bzero(data,sizeof(data)); strlcat(data,interpreterVersion,sizeof(data)); strlcat(data," ",sizeof(data)); NSString *versionString =[[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleVersion"]; if (versionString == nil) return data; const char *versonStringAsCString = [ versionString cStringUsingEncoding: [self currentVMEncoding]]; if (versonStringAsCString == nil) return data; strlcat(data,versonStringAsCString,sizeof(data)); return data; } case 1201: /* macintosh file name size */ return "255"; case 1202: /* macintosh file error peek */ return "0"; default: if ((indexNumber - 2) >= 0 && ((indexNumber - 2) < [self.argsArguments count])) return (char *) [[self.argsArguments objectAtIndex: (NSUInteger) (indexNumber - 2)] cStringUsingEncoding: [self currentVMEncoding]]; } } interpreterProxy->success(false); return ""; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+cursor.h ================================================ // // sqSqueakMainApplication+cursor.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (cursor) - (void) setCursor: (sqInt) cursorBitsIndex withMask: (sqInt) cursorMaskIndex offsetX: (sqInt) offsetX offsetY: (sqInt) offsetY; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+cursor.m ================================================ // // sqSqueakMainApplication+cursor.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication+cursor.h" @implementation sqSqueakMainApplication (cursor) - (void) setCursor: (sqInt) cursorBitsIndex withMask: (sqInt) cursorMaskIndex offsetX: (sqInt) offsetX offsetY: (sqInt) offsetY { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+events.h ================================================ // // sqSqueakMainApplication+events.h // // Created by John M McIntosh on 6/21/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (events) - (void) ioGetNextEvent: (sqInputEvent *) evt; - (void) processAsOldEventOrComplexEvent: (id) event placeIn: (sqInputEvent *) evt; - (void) pumpRunLoop; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+events.m ================================================ // // sqSqueakMainApplication+events.m // // Created by John M McIntosh on 6/21/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication+events.h" @implementation sqSqueakMainApplication (events) - (void) pumpRunLoop { /* static NSTimeInterval old = 0.0; NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; if ((now - old) < 1.0/60.0) { return; } old = now; */ /* This the carbon logic model described by http://developer.apple.com/qa/qa2001/qa1061.html but fails on device, bug tracking number 5971848 */ NSRunLoop *theRL = [NSRunLoop mainRunLoop]; BOOL result = [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]; // while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource); // TEST WHICH IS BETTER? SInt32 what = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); #pragma unused(result) } - (void) ioGetNextEvent: (sqInputEvent *) evt { ioProcessEvents(); id event = [eventQueue returnAndRemoveOldest]; if (event) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; [self processAsOldEventOrComplexEvent: event placeIn: evt]; [event release]; [pool drain]; } } - (void ) processAsOldEventOrComplexEvent: (id) event placeIn: (sqInputEvent *) evt { if ([event isKindOfClass: [NSData class]]) { [event getBytes: evt length: sizeof(sqInputEvent)]; return; } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.h ================================================ // // sqSqueakMainApplication+imageReadWrite.h // // Created by John M McIntosh on 5/22/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (imageReadWrite) - (void) findImageViaBundleOrPreferences; - (BOOL) readImageIntoMemory; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.m ================================================ // // sqSqueakMainApplication+imageReadWrite.m // // Created by John M McIntosh on 5/22/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication+imageReadWrite.h" #import "sqMacV2Memory.h" @implementation sqSqueakMainApplication (imageReadWrite) - (void) findImageViaBundleOrPreferences { } - (BOOL) readImageIntoMemory { NSAutoreleasePool * pool = [NSAutoreleasePool new]; const char * characterPathForImage = (const char *) [[NSFileManager defaultManager] fileSystemRepresentationWithPath: [self.imageNameURL path]]; sqImageFile f; if (!characterPathForImage) { [pool drain]; return NO; } f = sqImageFileOpen(characterPathForImage, "rb"); # ifndef ROAR_VM readImageFromFileHeapSizeStartingAt(f, sqGetAvailableMemory(), (squeakFileOffsetType) 0); //This is a VM Callback # endif // ROAR_VM sqImageFileClose(f); [pool drain]; return YES; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+screen.h ================================================ // // sqSqueakMainApplication+screen.h // // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" #import "sqMacHostWindow.h" @interface sqSqueakMainApplication (screen) - (void) unionScreenArea: (windowDescriptorBlock *) windowBlock clip: (CGRect ) clip; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+screen.m ================================================ // // sqSqueakMainApplication+screen.m // // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication+screen.h" #import "HostWindowPlugin.h" @implementation sqSqueakMainApplication (screen) - (void) unionScreenArea: (windowDescriptorBlock *) windowBlock clip: (CGRect ) clip { if (CGRectIsEmpty(windowBlock->updateArea)) windowBlock->updateArea = clip; else windowBlock->updateArea = CGRectUnion(windowBlock->updateArea, clip); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+sound.h ================================================ // // sqSqueakMainApplication+sound.h // // Created by John M McIntosh on 5/31/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (sound) - (void) ioBeep; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+sound.m ================================================ // // sqSqueakMainApplication+sound.m // // Created by John M McIntosh on 5/31/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "sqSqueakMainApplication+sound.h" @implementation sqSqueakMainApplication (sound) - (void) ioBeep { // SysBeep(1000); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.h ================================================ // // sqSqueakMainApplication+vmAndImagePath.h // // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" @interface sqSqueakMainApplication (vmAndImagePath) - (void) setVMPathFromApplicationDirectory; - (BOOL) ImageNameIsEmpty; - (const char *) getImageName; - (void) imageNameGet:(char *) sqImageName length:(sqInt) length; - (void) imageNamePut:(const char *) sqImageName; - (const char *) getVMPath; - (void) vmPathGet:(char *) sqVMPath length:(sqInt) length; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.m ================================================ // // sqSqueakMainApplication+vmAndImagePath.m // // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. V1.05b1 use alloc form of NSURL */ // #import "sqSqueakMainApplication+vmAndImagePath.h" #import "sqSqueakAppDelegate.h" extern sqSqueakAppDelegate *gDelegateApp; @implementation sqSqueakMainApplication (vmAndImagePath) - (void) setVMPathFromApplicationDirectory { self.vmPathStringURL = [NSURL fileURLWithPath: [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]]; } - (BOOL) ImageNameIsEmpty { if (self.imageNameURL) return false; return true; } - (const char *) getImageName { return [[[self.imageNameURL path] precomposedStringWithCanonicalMapping] UTF8String]; } - (void) imageNameGet:(char *) sqImageName length:(sqInt)length { //sqImageName is actually the address of where to put the data //length is how many bytes the target can hold if (!sqImageName) return; *sqImageName = 0x00; if (length > 0) strncpy(sqImageName, [self getImageName],(size_t) length); //This does not need to be strlcpy since the data is not null terminated /* ok do we need to check for length of getImageName? if length > strlen(getImageName) then it fills with 0x00 if length < strlen(getImageName) then we get a partial string and no trailing /0 if length == strlen(getImageName) then we get the string and no trailing /0 which is what is desired. */ } - (void) imageNamePut:(const char *) sqImageName { if (!sqImageName) return; self.imageNameURL = [NSURL fileURLWithPath: [NSString stringWithUTF8String: sqImageName] isDirectory: NO]; } - (const char *) getVMPath { return [[[[self vmPathStringURL] path] precomposedStringWithCanonicalMapping] UTF8String]; } - (void) vmPathGet:(char *) sqVMPath length:(sqInt)length { //sqVMPath is actually the address of where to put the data //length is how many bytes the target can hold if (!sqVMPath) return; *sqVMPath = 0x00; if (length > 0) { strlcpy(sqVMPath, [self getVMPath], (size_t) length); sqVMPath[length-1] = '/'; // BUG length here is 1 offset, so need to subtract 1 to add on the '/' which is +1 via VMPathLength } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication.h ================================================ // // sqSqueakMainApplication.h // // // Created by John M McIntosh on 5/15/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #import "sq.h" #import "Queue.h" #import "sqSqueakFileDirectoryInterface.h" #import "sqSqueakScreenAndWindow.h" #import "sqSqueakInfoPlistInterface.h" #import "sqSqueakSoundCoreAudio.h" @interface sqSqueakMainApplication : NSObject { NSURL* vmPathStringURL; NSURL* imageNameURL; NSStringEncoding currentVMEncoding; NSMutableArray *argsArguments; sqSqueakFileDirectoryInterface* fileDirectoryLogic; sqSqueakInfoPlistInterface* infoPlistInterfaceLogic; sqSqueakSoundCoreAudio* soundInterfaceLogic; sqInt inputSemaphoreIndex; //event semaphore for VM thread Queue* eventQueue; //event queue for user events from UI thread } - (void) setupFloat; - (void) setupErrorRecovery; - (void) fetchPreferences; - (sqSqueakInfoPlistInterface *) newSqSqueakInfoPlistInterfaceCreation; - (void) doHeadlessSetup; - (void) doMemorySetup; - (void) parseUnixArgs; - (void) setupMenus; - (void) setupTimers; - (void) setupAIO; - (void) setupEventQueue; - (void) setupBrowserLogic; - (void) setupSoundLogic; - (void) runSqueak; - (void) MenuBarRestore; - (void) ioExit; - (void) ioExitWithErrorCode: (int) ec; - (sqSqueakFileDirectoryInterface *) newFileDirectoryInterfaceInstance; @property (nonatomic,retain) NSURL* vmPathStringURL; @property (nonatomic,retain) sqSqueakInfoPlistInterface* infoPlistInterfaceLogic; @property (nonatomic,retain) sqSqueakSoundCoreAudio* soundInterfaceLogic; @property (nonatomic,retain) NSURL* imageNameURL; @property (nonatomic,assign) sqInt inputSemaphoreIndex; @property (nonatomic,assign) NSStringEncoding currentVMEncoding; @property (nonatomic,retain) Queue* eventQueue; @property (nonatomic,retain) sqSqueakFileDirectoryInterface * fileDirectoryLogic; @property (nonatomic,retain) NSMutableArray* argsArguments; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakMainApplication.m ================================================ // // sqSqueakMainApplication.m // // // Created by John M McIntosh on 5/15/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. V1.05b1 fix various issues with memory allocation/free, rework logic so you can free entire interpreter loop on quit. */ // #import <Foundation/Foundation.h> #import "sqSqueakMainApplication.h" #import "sqSqueakMainApp.h" #import "sqSqueakAppDelegate.h" #import "sq.h" #import "sqSqueakMainApplication+vmAndImagePath.h" #import "sqSqueakMainApplication+imageReadWrite.h" #import "sqSqueakSoundCoreAudio.h" #import "Queue.h" extern BOOL gSqueakHeadless; extern sqSqueakAppDelegate *gDelegateApp; @implementation sqSqueakMainApplication; @synthesize vmPathStringURL; @synthesize imageNameURL; @synthesize inputSemaphoreIndex; @synthesize currentVMEncoding; @synthesize eventQueue; @synthesize fileDirectoryLogic; @synthesize infoPlistInterfaceLogic; @synthesize soundInterfaceLogic; @synthesize argsArguments; // Define the VM call backs for initalization and similar purposes # ifdef ROAR_VM extern void initialize_basic_subsystems(); extern void initialize_interpreter_instances_selftest_and_interpreter_proxy(char** orig_argv); extern void read_image(char* image_path); extern void begin_interpretation(); extern void set_num_cores(char* num_cores_str); # else extern sqInt interpret(void); extern void sqMacMemoryFree(void); # endif // ! ROAR_VM - (void) setupFloat { } - (void) setupErrorRecovery { signal(SIGSEGV, sigsegv); } - (sqSqueakInfoPlistInterface *) newSqSqueakInfoPlistInterfaceCreation { return [sqSqueakInfoPlistInterface new]; } - (void) fetchPreferences { infoPlistInterfaceLogic = [self newSqSqueakInfoPlistInterfaceCreation]; [infoPlistInterfaceLogic parseInfoPlist]; currentVMEncoding = NSUTF8StringEncoding; } - (void) doHeadlessSetup { gSqueakHeadless = false; } - (void) doMemorySetup { } - (void) parseUnixArgs { } - (void) setupMenus { } - (void) setupTimers { extern void SetUpTimers(void); SetUpTimers(); } - (void) setupAIO { void aioInit(void); aioInit(); #if STACKVM || COGVM ioInitThreads(); #endif } - (void) setupEventQueue { eventQueue = [Queue new]; } - (void) setupBrowserLogic { } - (void) setupSoundLogic { soundInterfaceLogic = [sqSqueakSoundCoreAudio new]; } - (sqSqueakFileDirectoryInterface *) newFileDirectoryInterfaceInstance { return [sqSqueakFileDirectoryInterface new]; } - (void) runSqueak { //STEFAN: here is were we need to hack into NSAutoreleasePool * pool = [NSAutoreleasePool new]; //Needed since this is a worker thread, see comments in NSAutoreleasePool Class Reference about Threads [self setupFloat]; //JMM We have code for intel and powerpc float, but arm? [self setupErrorRecovery]; [self fetchPreferences]; fileDirectoryLogic = [self newFileDirectoryInterfaceInstance]; [self setVMPathFromApplicationDirectory]; if (![self.fileDirectoryLogic setWorkingDirectory]) { [pool drain]; return; } [self parseUnixArgs]; //JMM here we parse the unixArgs //JMM now we wait for the open document apple events (normally) [self doHeadlessSetup]; //JMM after wait normally if headless and no imageName then exit -42 [self doMemorySetup]; if ([self ImageNameIsEmpty]) [self findImageViaBundleOrPreferences]; if ([self ImageNameIsEmpty]) { [pool drain]; return; } # ifdef ROAR_VM char * characterPathForImage = (char *) [[NSFileManager defaultManager] fileSystemRepresentationWithPath: [self.imageNameURL path]]; # else if (![self readImageIntoMemory]) { [pool drain]; return; } # endif // ROAR_VM [self setupMenus]; [self setupTimers]; [self setupAIO]; [self setupBrowserLogic]; [self setupSoundLogic]; [gDelegateApp makeMainWindow]; # ifdef ROAR_VM initialize_basic_subsystems(); set_num_cores("1"); //STEFAN TODO try 2 initialize_interpreter_instances_selftest_and_interpreter_proxy(NULL); read_image(characterPathForImage); begin_interpretation(); # else interpret(); # endif // ROAR_VM [pool drain]; //may not return here, could call exit() via quit image [self release]; } - (void) MenuBarRestore { } - (void) ioExit { [self ioExitWithErrorCode: 0]; } - (void) ioExitWithErrorCode: (int) ec { ioShutdownAllModules(); [self MenuBarRestore]; exit(ec); //Will not return } - (void)dealloc { [infoPlistInterfaceLogic release]; [soundInterfaceLogic release]; [vmPathStringURL release]; [imageNameURL release]; [fileDirectoryLogic release]; [eventQueue release]; # ifndef ROAR_VM sqMacMemoryFree(); # endif // !ROAR_VM [super dealloc]; } @end int plugInTimeToReturn(void); int plugInTimeToReturn(void) { extern BOOL gQuitNowRightNow; if (gQuitNowRightNow) return true; return false; } sqInt convertToSqueakTime(NSDate *givenDate) { time_t unixTime = [givenDate timeIntervalSince1970]; #ifdef HAVE_TM_GMTOFF unixTime+= localtime(&unixTime)->tm_gmtoff; #else # ifdef HAVE_TIMEZONE unixTime+= ((daylight) * 60*60) - timezone; # else # error: cannot determine timezone correction # endif #endif /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970: 17 leap years and 52 non-leap years later than Squeak. */ return unixTime + ((52*365UL + 17*366UL) * 24*60*60UL); } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakScreenAPI.h ================================================ /* * sqSqueakScreenAPI.h * * * Created by John M McIntosh on 5/15/08. Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakScreenAPI.m ================================================ /* * sqSqueakScreenAPI.m * * * Created by John M McIntosh on 5/15/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sq.h" #import "sqSqueakScreenAPI.h" #import "sqSqueakScreenAndWindow.h" #ifdef BUILD_FOR_OSX #include "sqMacHostWindow.h" extern wHandleType windowHandleFromIndex(sqInt windowIndex); #else #include "SqueakNoOGLIPhoneAppDelegate.h" extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; #endif sqSqueakScreenAndWindow *getMainWindowDelegate() { #ifdef BUILD_FOR_OSX return ((NSWindow *) windowHandleFromIndex(1)).delegate; #else return [gDelegateApp screenAndWindow]; #endif } sqInt ioScreenSize(void) { //API Documented return [getMainWindowDelegate() ioScreenSize]; } sqInt ioScreenDepth(void) { //API Documented return [getMainWindowDelegate() ioScreenDepth]; } sqInt ioHasDisplayDepth(sqInt depth) { //API Documented return [getMainWindowDelegate() ioHasDisplayDepth: depth]; } sqInt ioForceDisplayUpdate(void){ //API Documented [getMainWindowDelegate() ioForceDisplayUpdate]; return 0; } sqInt ioSetFullScreen(sqInt fullScreen) { //API Documented [getMainWindowDelegate() ioSetFullScreen: fullScreen]; extern sqInt setFullScreenFlag(sqInt fullScreen); setFullScreenFlag(fullScreen); return 0; } sqInt ioShowDisplayOnWindow(unsigned char * dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB, sqInt windowIndex); sqInt ioShowDisplay( sqInt dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB) { //API Documented ioShowDisplayOnWindow((unsigned char *)pointerForIndex_xxx_dmu(dispBitsIndex), width, height, depth, affectedL, affectedR, affectedT, affectedB, 1); return 1; } sqInt ioShowDisplayOnWindow(unsigned char* dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB, sqInt windowIndex) { //API Documented return [getMainWindowDelegate() ioShowDisplayOnWindow: dispBitsIndex width: (int) width height: (int) height depth: (int) depth affectedL: (int) affectedL affectedR: (int) affectedR affectedT: (int) affectedT affectedB: (int) affectedB windowIndex: (int) windowIndex]; } char *ioGetWindowLabel(void) { return nil; } sqInt ioSetWindowLabelOfSize(void *lblIndex, sqInt sz) { return 0; } sqInt ioGetWindowWidth(void) { return 0; } sqInt ioGetWindowHeight(void) { return 0; } sqInt ioSetWindowWidthHeight(sqInt w, sqInt h) { return 0; } sqInt ioIsWindowObscured(void) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakScreenAndWindow.h ================================================ // // sqSqueakScreenAndWindow.h // // // Created by John M McIntosh on 6/14/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #import "sq.h" @interface sqSqueakScreenAndWindow : NSObject { sqInt windowIndex; NSTimeInterval squeakUIFlushPrimaryDeferNMilliseconds; NSTimeInterval lastFlushTime; NSTimer *blip; BOOL forceUpdateFlush; BOOL displayIsDirty; } - (sqInt) ioScreenSize; - (sqInt) ioScreenDepth; - (sqInt) ioHasDisplayDepth: (sqInt) depth; - (void) ioForceDisplayUpdate; - (void) ioSetFullScreen: (sqInt) fullScreen; - (int) ioShowDisplayOnWindow: (unsigned char*) dispBitsIndex width: (int) width height: (int) height depth: (int) depth affectedL: (int) affectedL affectedR: (int) affectedR affectedT: (int) affectedT affectedB: (int) affectedB windowIndex: (int) windowIndex; - (id) getMainView; - (void) ioForceDisplayUpdateFlush: (NSTimer*)theTimer; @property (nonatomic,assign) sqInt windowIndex; @property (nonatomic,retain) NSTimer *blip; @property (nonatomic,assign) NSTimeInterval squeakUIFlushPrimaryDeferNMilliseconds; @property (nonatomic,assign) NSTimeInterval lastFlushTime; @property (nonatomic,assign) BOOL forceUpdateFlush; @property (nonatomic,assign) BOOL displayIsDirty; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakScreenAndWindow.m ================================================ // // sqSqueakScreenAndWindow.m // // // Created by John M McIntosh on 6/14/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakScreenAndWindow.h" #import "sqSqueakMainApplication+screen.h" #import "sqMacHostWindow.h" #ifdef BUILD_FOR_OSX #import "SqueakOSXAppDelegate.h" extern SqueakOSXAppDelegate *gDelegateApp; #else #import "SqueakNoOGLIPhoneAppDelegate.h" SqueakNoOGLIPhoneAppDelegate *gDelegateApp; #endif void MyProviderReleaseData ( void *info, const void *data, size_t size ); void MyProviderReleaseData ( void *info, const void *data, size_t size ) { } @implementation sqSqueakScreenAndWindow @synthesize windowIndex; @synthesize blip,squeakUIFlushPrimaryDeferNMilliseconds,forceUpdateFlush,lastFlushTime,displayIsDirty; - (id)init { self = [super init]; if (self) { // Initialization code here. squeakUIFlushPrimaryDeferNMilliseconds = 0.0f; forceUpdateFlush = NO; displayIsDirty = NO; } return self; } - (id) getMainView { return NULL; } - (void) ioSetFullScreen: (sqInt) fullScreen { } - (sqInt) ioScreenSize { sqInt w, h; #if BUILD_FOR_OSX NSRect screenSize = [gDelegateApp.mainView bounds]; #else CGRect screenSize = [gDelegateApp.mainView bounds]; #endif w = (sqInt) screenSize.size.width; h = (sqInt) screenSize.size.height; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } - (sqInt) ioScreenDepth { return 32; } - (sqInt) ioHasDisplayDepth: (sqInt) depth { if (depth == 32) return true; return false; } - (void) ioForceDisplayUpdateActual { lastFlushTime = [NSDate timeIntervalSinceReferenceDate]; self.displayIsDirty = NO; self.forceUpdateFlush = NO; if ([NSThread isMainThread]) [[self getMainView] drawThelayers]; else { [[self getMainView] performSelectorOnMainThread: @selector(drawThelayers) withObject: nil waitUntilDone: NO]; } } - (void) ioForceDisplayUpdate { [self ioForceDisplayUpdateActual]; } - (int) ioShowDisplayOnWindowActual: (unsigned char*) dispBitsIndex width: (int) width height: (int) height depth: (int) depth affectedL: (int) affectedL affectedR: (int) affectedR affectedT: (int) affectedT affectedB: (int) affectedB windowIndex: (int) passedWindowIndex { static CGColorSpaceRef colorspace = NULL; sqInt pitch; windowDescriptorBlock *targetWindowBlock = windowBlockFromIndex(passedWindowIndex); if (colorspace == NULL) { colorspace = CGColorSpaceCreateDeviceRGB(); //Special case of first draw [self ioShowDisplayOnWindow:dispBitsIndex width:width height: height depth: depth affectedL: 0 affectedR: width affectedT: 0 affectedB: height windowIndex: passedWindowIndex]; // [self ioForceDisplayUpdate]; return 0; } if (affectedL < 0) affectedL = 0; if (affectedT < 0) affectedT = 0; if (affectedR > width) affectedR = width; if (affectedB > height) affectedB = height; if ((targetWindowBlock->handle == nil) || ((affectedR - affectedL) <= 0) || ((affectedB - affectedT) <= 0)){ return 0; } pitch = ((((width)*(depth) + 31) >> 5) << 2); CGRect clip = CGRectMake((CGFloat)affectedL,(CGFloat)(height-affectedB), (CGFloat)(affectedR-affectedL), (CGFloat)(affectedB-affectedT)); [gDelegateApp.mainView drawImageUsingClip: clip]; self.displayIsDirty = YES; if ((targetWindowBlock->width != width || targetWindowBlock->height != height)) { targetWindowBlock->width = width; targetWindowBlock->height = height; } return 0; } - (void) ioForceDisplayUpdateFlush: (NSTimer*)theTimer { NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; if (self.displayIsDirty && ((now - self.lastFlushTime) > squeakUIFlushPrimaryDeferNMilliseconds)) { self.lastFlushTime = now; self.forceUpdateFlush = YES; } } - (int) ioShowDisplayOnWindow: (unsigned char*) dispBitsIndex width: (int) width height: (int) height depth: (int) depth affectedL: (int) affectedL affectedR: (int) affectedR affectedT: (int) affectedT affectedB: (int) affectedB windowIndex: (int) passedWindowIndex { int value; value = [self ioShowDisplayOnWindowActual:dispBitsIndex width: width height: height depth:depth affectedL:affectedL affectedR:affectedR affectedT:affectedT affectedB:affectedB windowIndex: passedWindowIndex]; if (!self.blip) { if (squeakUIFlushPrimaryDeferNMilliseconds == 0.0f) squeakUIFlushPrimaryDeferNMilliseconds = [gDelegateApp squeakUIFlushPrimaryDeferNMilliseconds]; self.blip = [NSTimer timerWithTimeInterval: squeakUIFlushPrimaryDeferNMilliseconds target:self selector:@selector(ioForceDisplayUpdateFlush:) userInfo:nil repeats: YES]; [[NSRunLoop mainRunLoop] addTimer: self.blip forMode: NSDefaultRunLoopMode]; } return value; } - (void)dealloc { [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakSoundAPI.h ================================================ // // sqSqueakSoundAPI.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/21/08. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakSoundAPI.m ================================================ // // sqSqueakSoundAPI.m // // Created by John M McIntosh on 6/21/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakSoundAPI.h" #import "sqSqueakAppDelegate.h" #import "sqSqueakMainApplication+sound.h" extern sqSqueakAppDelegate *gDelegateApp; sqInt ioBeep() { //API Documented [gDelegateApp.squeakApplication ioBeep]; return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakVmAndImagePathAPI.h ================================================ // // sqSqueakVmAndImagePathAPI.h // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/Classes/sqSqueakVmAndImagePathAPI.m ================================================ // // sqSqueakVmAndImagePathAPI.m // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // /* imageName is a character stored and known by the VM but we use a URI for image name. So a bit of house keeping is required to sync the two data items */ #import "sqSqueakVmAndImagePathAPI.h" #import "sqSqueakAppDelegate.h" #import "sqSqueakMainApplication+vmAndImagePath.h" extern sqSqueakAppDelegate *gDelegateApp; char imageName[PATH_MAX]="Squeak.image"; char *getImageName(void) { return (char *) [gDelegateApp.squeakApplication getImageName]; } sqInt imageNameSize(void){ return (sqInt) strlen(getImageName()); } sqInt imageNameGetLength(sqInt sqImageNameIndex, sqInt length){ [gDelegateApp.squeakApplication imageNameGet: pointerForIndex_xxx_dmu((usqInt)sqImageNameIndex) length: length]; return 0; } sqInt imageNamePutLength(sqInt sqImageNameIndex, sqInt length){ if (length > 0 && (length < PATH_MAX)) { strncpy(imageName,pointerForIndex_xxx_dmu((usqInt)sqImageNameIndex),(size_t) length); //This does not need to be strlcpy since the data is not null terminated imageName[length] = 0x00; //Ensure we nil terminate the image name string [gDelegateApp.squeakApplication imageNamePut:imageName]; } return 0; } //getVMPath returns without a trailing '/', so increment by one sqInt vmPathSize(void){ return (sqInt) strlen([gDelegateApp.squeakApplication getVMPath]) + 1; } sqInt vmPathGetLength(sqInt sqVMPathIndex, sqInt length){ [gDelegateApp.squeakApplication vmPathGet: pointerForIndex_xxx_dmu((usqInt)sqVMPathIndex) length: length]; return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/English.lproj/Localizable.strings ================================================ /* Localizable.strings SqueakPureObjc Created by John M McIntosh on 09-11-24. Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. */ "SqueakSelectImagePanePrompt" = "Select a Squeak image file to open"; ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/aio.c ================================================ /* aio.c -- asynchronous file i/o * * Copyright (C) 1996-2006 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Ian.Piumarta@squeakland.org * * Last edited: 2006-10-18 10:07:06 by piumarta on emilia.local */ #include "sqaio.h" #ifdef HAVE_CONFIG_H # include "config.h" # ifdef HAVE_UNISTD_H # include <sys/types.h> # include <unistd.h> # endif /* HAVE_UNISTD_H */ # ifdef NEED_GETHOSTNAME_P extern int gethostname(); # endif # include <stdio.h> # include <signal.h> # include <errno.h> # include <fcntl.h> # include <sys/file.h> # include <sys/ioctl.h> # ifdef HAVE_SYS_TIME_H # include <sys/time.h> # else # include <time.h> # endif # ifdef HAS_SYS_SELECT_H # include <sys/select.h> # endif # ifndef FIONBIO # ifdef HAVE_SYS_FILIO_H # include <sys/filio.h> # endif # ifndef FIONBIO # ifdef FIOSNBIO # define FIONBIO FIOSNBIO # else # error: FIONBIO is not defined # endif # endif # endif # if !defined(O_NONBLOCK) && defined(O_NDELAY) # define O_NONBLOCK O_NDELAY # endif # if !defined(FASYNC) && defined(O_ASYNC) # define FASYNC O_ASYNC # endif #else /* !HAVE_CONFIG_H -- assume lowest common demoninator */ # include <stdio.h> # include <stdlib.h> # include <unistd.h> # include <errno.h> # include <signal.h> # include <sys/types.h> # include <sys/time.h> # include <sys/select.h> # include <sys/ioctl.h> # include <fcntl.h> #endif #undef DEBUG #undef DEBUG_TICKER #if defined(DEBUG) int aioLastTick= 0; int aioThisTick= 0; # define FPRINTF(X) { aioThisTick= ioLowResMSecs(); fprintf(stderr, "%8d %8d ", aioThisTick, aioThisTick - aioLastTick); aioLastTick= aioThisTick; fprintf X; } #else # define FPRINTF(X) #endif #if defined(DEBUG_TICKER) static char *ticks= "-\\|/"; static char *ticker= ""; #define DO_TICK() \ { \ fprintf(stderr, "\r%c\r", *ticker); \ if (!*ticker++) ticker= ticks; \ } #else # define DO_TICK() #endif #define _DO_FLAG_TYPE() _DO(AIO_R, rd) _DO(AIO_W, wr) _DO(AIO_X, ex) static int one= 1; static aioHandler rdHandler[FD_SETSIZE]; static aioHandler wrHandler[FD_SETSIZE]; static aioHandler exHandler[FD_SETSIZE]; static void *clientData[FD_SETSIZE]; static int maxFd; static fd_set fdMask; /* handled by aio */ static fd_set rdMask; /* handle read */ static fd_set wrMask; /* handle write */ static fd_set exMask; /* handle exception */ static fd_set xdMask; /* external descriptor */ static void undefinedHandler(int fd, void *clientData, int flags) { fprintf(stderr, "undefined handler called (fd %d, flags %x)\n", fd, flags); } #ifdef DEBUG static char *handlerName(aioHandler h) { if (h == undefinedHandler) return "undefinedHandler"; #ifdef DEBUG_SOCKETS { extern char *socketHandlerName(aioHandler); return socketHandlerName(h); } #endif return "***unknown***"; } #endif /* initialise asynchronous i/o */ void aioInit(void) { extern void forceInterruptCheck(int); /* not really, but hey */ FD_ZERO(&fdMask); FD_ZERO(&rdMask); FD_ZERO(&wrMask); FD_ZERO(&exMask); FD_ZERO(&xdMask); maxFd= 0; signal(SIGPIPE, SIG_IGN); signal(SIGIO, forceInterruptCheck); } /* disable handlers and close all handled non-exteral descriptors */ void aioFini(void) { int fd; for (fd= 0; fd < maxFd; fd++) if (FD_ISSET(fd, &fdMask) && !(FD_ISSET(fd, &xdMask))) { aioDisable(fd); close(fd); FD_CLR(fd, &fdMask); FD_CLR(fd, &rdMask); FD_CLR(fd, &wrMask); FD_CLR(fd, &exMask); } while (maxFd && !FD_ISSET(maxFd - 1, &fdMask)) --maxFd; signal(SIGPIPE, SIG_DFL); } /* answer whether i/o becomes possible within the given number of microSeconds */ int aioPoll(int microSeconds) { int fd, ms; fd_set rd, wr, ex; FPRINTF((stderr, "aioPoll(%d)\n", microSeconds)); DO_TICK(); /* get out early if there is no pending i/o and no need to relinquish cpu */ if ((maxFd == 0) && (microSeconds == 0)) return 0; rd= rdMask; wr= wrMask; ex= exMask; #ifdef BUILD_FOR_OSX #else if (maxFd == 0) return 0; #endif ms= (int) ioMSecs(); for (;;) { struct timeval tv; int n, now,why; tv.tv_sec= microSeconds / 1000000; tv.tv_usec= microSeconds % 1000000; n= select(maxFd, &rd, &wr, &ex, &tv); why = errno; if (n > 0) break; if (n == 0) return 0; if (errno && (EINTR != errno)) { fprintf(stderr, "errno %d\n", errno); perror("select"); return 0; } now= (int) ioMSecs(); microSeconds -= (now - ms) * 1000; if (microSeconds <= 0) return 0; ms= now; } for (fd= 0; fd < maxFd; ++fd) { # define _DO(FLAG, TYPE) \ { \ if (FD_ISSET(fd, &TYPE)) \ { \ aioHandler handler= TYPE##Handler[fd]; \ FD_CLR(fd, &TYPE##Mask); \ TYPE##Handler[fd]= undefinedHandler; \ handler(fd, clientData[fd], FLAG); \ } \ } _DO_FLAG_TYPE(); # undef _DO } return 1; } /* sleep for microSeconds or until i/o becomes possible, avoiding sleeping in select() is timeout too small */ int aioSleep(int microSeconds) { #if defined(HAVE_NANOSLEEP) if (microSeconds < (1000000/60)) /* < 1 timeslice? */ { if (!aioPoll(0)) { int error,why; struct timespec rqtp= { 0, microSeconds * 1000 }; struct timespec rmtp; error = nanosleep(&rqtp, &rmtp); if (error == -1) { why = errno; } microSeconds= 0; /* poll but don't block */ } } #endif return aioPoll(microSeconds); } /* enable asynchronous notification for a descriptor */ void aioEnable(int fd, void *data, int flags) { FPRINTF((stderr, "aioEnable(%d)\n", fd)); if (fd < 0) { FPRINTF((stderr, "aioEnable(%d): IGNORED\n", fd)); return; } if (FD_ISSET(fd, &fdMask)) { fprintf(stderr, "aioEnable: descriptor %d already enabled\n", fd); return; } clientData[fd]= data; rdHandler[fd]= wrHandler[fd]= exHandler[fd]= undefinedHandler; FD_SET(fd, &fdMask); FD_CLR(fd, &rdMask); FD_CLR(fd, &wrMask); FD_CLR(fd, &exMask); if (fd >= maxFd) maxFd= fd + 1; if (flags & AIO_EXT) { FD_SET(fd, &xdMask); /* we should not set NBIO ourselves on external descriptors! */ } else { /* enable non-blocking asynchronous i/o and delivery of SIGIO to the active process */ int arg; FD_CLR(fd, &xdMask); # if defined(O_ASYNC) if ( fcntl(fd, F_SETOWN, getpid() ) < 0) perror("fcntl(F_SETOWN, getpid())"); if ((arg= fcntl(fd, F_GETFL, 0 )) < 0) perror("fcntl(F_GETFL)"); if ( fcntl(fd, F_SETFL, arg | O_NONBLOCK | O_ASYNC) < 0) perror("fcntl(F_SETFL, O_ASYNC)"); # elif defined(FASYNC) if ( fcntl(fd, F_SETOWN, getpid() ) < 0) perror("fcntl(F_SETOWN, getpid())"); if ((arg= fcntl(fd, F_GETFL, 0 )) < 0) perror("fcntl(F_GETFL)"); if ( fcntl(fd, F_SETFL, arg | O_NONBLOCK | FASYNC ) < 0) perror("fcntl(F_SETFL, FASYNC)"); # elif defined(FIOASYNC) arg= getpid(); if (ioctl(fd, SIOCSPGRP, &arg) < 0) perror("ioctl(SIOCSPGRP, getpid())"); arg= 1; if (ioctl(fd, FIOASYNC, &arg) < 0) perror("ioctl(FIOASYNC, 1)"); # endif } } /* install/change the handler for a descriptor */ void aioHandle(int fd, aioHandler handlerFn, int mask) { FPRINTF((stderr, "aioHandle(%d, %s, %d)\n", fd, handlerName(handlerFn), mask)); if (fd < 0) { FPRINTF((stderr, "aioHandle(%d): IGNORED\n", fd)); return; } # define _DO(FLAG, TYPE) \ if (mask & FLAG) { \ FD_SET(fd, &TYPE##Mask); \ TYPE##Handler[fd]= handlerFn; \ } _DO_FLAG_TYPE(); # undef _DO } /* temporarily suspend asynchronous notification for a descriptor */ void aioSuspend(int fd, int mask) { if (fd < 0) { FPRINTF((stderr, "aioSuspend(%d): IGNORED\n", fd)); return; } FPRINTF((stderr, "aioSuspend(%d)\n", fd)); # define _DO(FLAG, TYPE) \ { \ if (mask & FLAG) \ { \ FD_CLR(fd, &TYPE##Mask); \ TYPE##Handler[fd]= undefinedHandler; \ } \ } _DO_FLAG_TYPE(); # undef _DO } /* definitively disable asynchronous notification for a descriptor */ void aioDisable(int fd) { if (fd < 0) { FPRINTF((stderr, "aioDisable(%d): IGNORED\n", fd)); return; } FPRINTF((stderr, "aioDisable(%d)\n", fd)); aioSuspend(fd, AIO_RWX); FD_CLR(fd, &xdMask); FD_CLR(fd, &fdMask); rdHandler[fd]= wrHandler[fd]= exHandler[fd]= 0; clientData[fd]= 0; /* keep maxFd accurate (drops to zero if no more sockets) */ while (maxFd && !FD_ISSET(maxFd - 1, &fdMask)) --maxFd; } ================================================ FILE: vm/src/from_squeak/iOS/vm/Common/main.m ================================================ // // main.m // // Created by John M McIntosh on 5/15/08. // 11/01/09 Altered for os-x version /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #ifdef BUILD_FOR_OSX #import <Cocoa/Cocoa.h> int main(int argc, char **argv, char **envp) { extern int argCnt; extern char **argVec; extern char **envVec; argCnt = argc; argVec= argv; envVec = envp; return NSApplicationMain(argc, (const char **) argv); } #else #import <UIKit/UIKit.h> int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool drain]; return retVal; } #endif ================================================ FILE: vm/src/from_squeak/iOS/vm/English.lproj/MainMenu.xib ================================================ <?xml version="1.0" encoding="UTF-8"?> <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">1060</int> <string key="IBDocument.SystemVersion">10F569</string> <string key="IBDocument.InterfaceBuilderVersion">804</string> <string key="IBDocument.AppKitVersion">1038.29</string> <string key="IBDocument.HIToolboxVersion">461.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="NS.object.0">804</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> <integer value="371"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> <object class="NSMutableDictionary" key="IBDocument.Metadata"> <string key="NS.key.0">PluginDependencyRecalculationVersion</string> <integer value="1" key="NS.object.0"/> </object> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSCustomObject" id="1021"> <string key="NSClassName">NSApplication</string> </object> <object class="NSCustomObject" id="1014"> <string key="NSClassName">FirstResponder</string> </object> <object class="NSCustomObject" id="1050"> <string key="NSClassName">SqueakOSXApplication</string> </object> <object class="NSMenu" id="649796088"> <string key="NSTitle">AMainMenu</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="694149608"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">SqueakOSXApp</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <object class="NSCustomResource" key="NSOnImage" id="35465992"> <string key="NSClassName">NSImage</string> <string key="NSResourceName">NSMenuCheckmark</string> </object> <object class="NSCustomResource" key="NSMixedImage" id="502551668"> <string key="NSClassName">NSImage</string> <string key="NSResourceName">NSMenuMixedState</string> </object> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="110575045"> <string key="NSTitle">SqueakOSXApp</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="238522557"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">About SqueakOSXApp</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="304266470"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="609285721"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Preferences…</string> <string key="NSKeyEquiv">,</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="481834944"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1046388886"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Services</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="752062318"> <string key="NSTitle">Services</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <string key="NSName">_NSServicesMenu</string> </object> </object> <object class="NSMenuItem" id="646227648"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="755159360"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <string key="NSTitle">Hide SqueakOSXApp</string> <string key="NSKeyEquiv">h</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="342932134"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <string key="NSTitle">Hide Others</string> <string key="NSKeyEquiv">h</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="908899353"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Show All</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1056857174"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="632727374"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <string key="NSTitle">Quit SqueakOSXApp</string> <string key="NSKeyEquiv">q</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSAppleMenu</string> </object> </object> <object class="NSMenuItem" id="379814623"> <reference key="NSMenu" ref="649796088"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsHidden">YES</bool> <string key="NSTitle">File</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="720053764"> <string key="NSTitle">File</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="705341025"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">New</string> <string key="NSKeyEquiv">n</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="722745758"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Open…</string> <string key="NSKeyEquiv">o</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1025936716"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Open Recent</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="1065607017"> <string key="NSTitle">Open Recent</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="759406840"> <reference key="NSMenu" ref="1065607017"/> <string key="NSTitle">Clear Menu</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSRecentDocumentsMenu</string> </object> </object> <object class="NSMenuItem" id="425164168"> <reference key="NSMenu" ref="720053764"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="776162233"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Close</string> <string key="NSKeyEquiv">w</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1023925487"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Save</string> <string key="NSKeyEquiv">s</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="117038363"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Save As…</string> <string key="NSKeyEquiv">S</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="579971712"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Revert to Saved</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1010469920"> <reference key="NSMenu" ref="720053764"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="294629803"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Page Setup...</string> <string key="NSKeyEquiv">P</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSToolTip"/> </object> <object class="NSMenuItem" id="49223823"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Print…</string> <string key="NSKeyEquiv">p</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="952259628"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Edit</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="789758025"> <string key="NSTitle">Edit</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="1058277027"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Undo</string> <string key="NSKeyEquiv">z</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="790794224"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Redo</string> <string key="NSKeyEquiv">Z</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1040322652"> <reference key="NSMenu" ref="789758025"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="296257095"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Cut</string> <string key="NSKeyEquiv">x</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="860595796"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Copy</string> <string key="NSKeyEquiv">c</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="29853731"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Paste</string> <string key="NSKeyEquiv">v</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="437104165"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Delete</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="583158037"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Select All</string> <string key="NSKeyEquiv">a</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="713487014"> <reference key="NSMenu" ref="649796088"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsHidden">YES</bool> <string key="NSTitle">Window</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="835318025"> <string key="NSTitle">Window</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="1011231497"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Minimize</string> <string key="NSKeyEquiv">m</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="575023229"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Zoom</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="299356726"> <reference key="NSMenu" ref="835318025"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="625202149"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Bring All to Front</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSWindowsMenu</string> </object> </object> <object class="NSMenuItem" id="448692316"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Help</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="992780483"> <string key="NSTitle">Help</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="105068016"> <reference key="NSMenu" ref="992780483"/> <string key="NSTitle">SqueakOSXApp Help</string> <string key="NSKeyEquiv">?</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSHelpMenu</string> </object> </object> </object> <string key="NSName">_NSMainMenu</string> </object> <object class="NSWindowTemplate" id="972006081"> <int key="NSWindowStyleMask">15</int> <int key="NSWindowBacking">2</int> <string key="NSWindowRect">{{335, 390}, {480, 360}}</string> <int key="NSWTFlags">880279552</int> <string key="NSWindowTitle">SqueakOSXApp</string> <string key="NSWindowClass">NSWindow</string> <nil key="NSViewClass"/> <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <object class="NSView" key="NSWindowView" id="439893737"> <reference key="NSNextResponder"/> <int key="NSvFlags">274</int> <string key="NSFrameSize">{480, 360}</string> <reference key="NSSuperview"/> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> </object> <object class="NSCustomObject" id="976324537"> <string key="NSClassName">SqueakOSXAppDelegate</string> </object> <object class="NSCustomObject" id="755631768"> <string key="NSClassName">NSFontManager</string> </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performMiniaturize:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1011231497"/> </object> <int key="connectionID">37</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">arrangeInFront:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="625202149"/> </object> <int key="connectionID">39</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">print:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="49223823"/> </object> <int key="connectionID">86</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">runPageLayout:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="294629803"/> </object> <int key="connectionID">87</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">clearRecentDocuments:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="759406840"/> </object> <int key="connectionID">127</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">orderFrontStandardAboutPanel:</string> <reference key="source" ref="1021"/> <reference key="destination" ref="238522557"/> </object> <int key="connectionID">142</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performClose:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="776162233"/> </object> <int key="connectionID">193</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">undo:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1058277027"/> </object> <int key="connectionID">223</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">copy:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="860595796"/> </object> <int key="connectionID">224</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">paste:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="29853731"/> </object> <int key="connectionID">226</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">cut:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="296257095"/> </object> <int key="connectionID">228</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">redo:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="790794224"/> </object> <int key="connectionID">231</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">selectAll:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="583158037"/> </object> <int key="connectionID">232</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">delete:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="437104165"/> </object> <int key="connectionID">235</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performZoom:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="575023229"/> </object> <int key="connectionID">240</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">saveDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1023925487"/> </object> <int key="connectionID">362</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">saveDocumentAs:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="117038363"/> </object> <int key="connectionID">363</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">revertDocumentToSaved:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="579971712"/> </object> <int key="connectionID">364</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">hide:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="755159360"/> </object> <int key="connectionID">367</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">hideOtherApplications:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="342932134"/> </object> <int key="connectionID">368</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">unhideAllApplications:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="908899353"/> </object> <int key="connectionID">370</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">newDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="705341025"/> </object> <int key="connectionID">373</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">openDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="722745758"/> </object> <int key="connectionID">374</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">terminate:</string> <reference key="source" ref="1050"/> <reference key="destination" ref="632727374"/> </object> <int key="connectionID">449</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">showHelp:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="105068016"/> </object> <int key="connectionID">493</int> </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">delegate</string> <reference key="source" ref="1021"/> <reference key="destination" ref="976324537"/> </object> <int key="connectionID">495</int> </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">window</string> <reference key="source" ref="976324537"/> <reference key="destination" ref="972006081"/> </object> <int key="connectionID">532</int> </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">mainView</string> <reference key="source" ref="976324537"/> <reference key="destination" ref="439893737"/> </object> <int key="connectionID">533</int> </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> <object class="NSArray" key="object" id="0"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <reference key="children" ref="1048"/> <nil key="parent"/> </object> <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="1021"/> <reference key="parent" ref="0"/> <string key="objectName">File's Owner</string> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="1014"/> <reference key="parent" ref="0"/> <string key="objectName">First Responder</string> </object> <object class="IBObjectRecord"> <int key="objectID">-3</int> <reference key="object" ref="1050"/> <reference key="parent" ref="0"/> <string key="objectName">Application</string> </object> <object class="IBObjectRecord"> <int key="objectID">29</int> <reference key="object" ref="649796088"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="713487014"/> <reference ref="694149608"/> <reference ref="952259628"/> <reference ref="379814623"/> <reference ref="448692316"/> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">19</int> <reference key="object" ref="713487014"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="835318025"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">56</int> <reference key="object" ref="694149608"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="110575045"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">217</int> <reference key="object" ref="952259628"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="789758025"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">83</int> <reference key="object" ref="379814623"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="720053764"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">81</int> <reference key="object" ref="720053764"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1023925487"/> <reference ref="117038363"/> <reference ref="49223823"/> <reference ref="722745758"/> <reference ref="705341025"/> <reference ref="1025936716"/> <reference ref="294629803"/> <reference ref="776162233"/> <reference ref="425164168"/> <reference ref="579971712"/> <reference ref="1010469920"/> </object> <reference key="parent" ref="379814623"/> </object> <object class="IBObjectRecord"> <int key="objectID">75</int> <reference key="object" ref="1023925487"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">80</int> <reference key="object" ref="117038363"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">78</int> <reference key="object" ref="49223823"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">72</int> <reference key="object" ref="722745758"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">82</int> <reference key="object" ref="705341025"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">124</int> <reference key="object" ref="1025936716"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1065607017"/> </object> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">77</int> <reference key="object" ref="294629803"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">73</int> <reference key="object" ref="776162233"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">79</int> <reference key="object" ref="425164168"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">112</int> <reference key="object" ref="579971712"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">74</int> <reference key="object" ref="1010469920"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">125</int> <reference key="object" ref="1065607017"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="759406840"/> </object> <reference key="parent" ref="1025936716"/> </object> <object class="IBObjectRecord"> <int key="objectID">126</int> <reference key="object" ref="759406840"/> <reference key="parent" ref="1065607017"/> </object> <object class="IBObjectRecord"> <int key="objectID">205</int> <reference key="object" ref="789758025"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="437104165"/> <reference ref="583158037"/> <reference ref="1058277027"/> <reference ref="296257095"/> <reference ref="29853731"/> <reference ref="860595796"/> <reference ref="1040322652"/> <reference ref="790794224"/> </object> <reference key="parent" ref="952259628"/> </object> <object class="IBObjectRecord"> <int key="objectID">202</int> <reference key="object" ref="437104165"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">198</int> <reference key="object" ref="583158037"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">207</int> <reference key="object" ref="1058277027"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">199</int> <reference key="object" ref="296257095"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">203</int> <reference key="object" ref="29853731"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">197</int> <reference key="object" ref="860595796"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">206</int> <reference key="object" ref="1040322652"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">215</int> <reference key="object" ref="790794224"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">57</int> <reference key="object" ref="110575045"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="238522557"/> <reference ref="755159360"/> <reference ref="908899353"/> <reference ref="632727374"/> <reference ref="646227648"/> <reference ref="609285721"/> <reference ref="481834944"/> <reference ref="304266470"/> <reference ref="1046388886"/> <reference ref="1056857174"/> <reference ref="342932134"/> </object> <reference key="parent" ref="694149608"/> </object> <object class="IBObjectRecord"> <int key="objectID">58</int> <reference key="object" ref="238522557"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">134</int> <reference key="object" ref="755159360"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">150</int> <reference key="object" ref="908899353"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">136</int> <reference key="object" ref="632727374"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">144</int> <reference key="object" ref="646227648"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">129</int> <reference key="object" ref="609285721"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">143</int> <reference key="object" ref="481834944"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">236</int> <reference key="object" ref="304266470"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">131</int> <reference key="object" ref="1046388886"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="752062318"/> </object> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">149</int> <reference key="object" ref="1056857174"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">145</int> <reference key="object" ref="342932134"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">130</int> <reference key="object" ref="752062318"/> <reference key="parent" ref="1046388886"/> </object> <object class="IBObjectRecord"> <int key="objectID">24</int> <reference key="object" ref="835318025"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="299356726"/> <reference ref="625202149"/> <reference ref="575023229"/> <reference ref="1011231497"/> </object> <reference key="parent" ref="713487014"/> </object> <object class="IBObjectRecord"> <int key="objectID">92</int> <reference key="object" ref="299356726"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">5</int> <reference key="object" ref="625202149"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">239</int> <reference key="object" ref="575023229"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">23</int> <reference key="object" ref="1011231497"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">371</int> <reference key="object" ref="972006081"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="439893737"/> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">372</int> <reference key="object" ref="439893737"/> <reference key="parent" ref="972006081"/> </object> <object class="IBObjectRecord"> <int key="objectID">420</int> <reference key="object" ref="755631768"/> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">490</int> <reference key="object" ref="448692316"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="992780483"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">491</int> <reference key="object" ref="992780483"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="105068016"/> </object> <reference key="parent" ref="448692316"/> </object> <object class="IBObjectRecord"> <int key="objectID">492</int> <reference key="object" ref="105068016"/> <reference key="parent" ref="992780483"/> </object> <object class="IBObjectRecord"> <int key="objectID">494</int> <reference key="object" ref="976324537"/> <reference key="parent" ref="0"/> </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>-3.IBPluginDependency</string> <string>112.IBPluginDependency</string> <string>112.ImportedFromIB2</string> <string>124.IBPluginDependency</string> <string>124.ImportedFromIB2</string> <string>125.IBPluginDependency</string> <string>125.ImportedFromIB2</string> <string>125.editorWindowContentRectSynchronizationRect</string> <string>126.IBPluginDependency</string> <string>126.ImportedFromIB2</string> <string>129.IBPluginDependency</string> <string>129.ImportedFromIB2</string> <string>130.IBPluginDependency</string> <string>130.ImportedFromIB2</string> <string>130.editorWindowContentRectSynchronizationRect</string> <string>131.IBPluginDependency</string> <string>131.ImportedFromIB2</string> <string>134.IBPluginDependency</string> <string>134.ImportedFromIB2</string> <string>136.IBPluginDependency</string> <string>136.ImportedFromIB2</string> <string>143.IBPluginDependency</string> <string>143.ImportedFromIB2</string> <string>144.IBPluginDependency</string> <string>144.ImportedFromIB2</string> <string>145.IBPluginDependency</string> <string>145.ImportedFromIB2</string> <string>149.IBPluginDependency</string> <string>149.ImportedFromIB2</string> <string>150.IBPluginDependency</string> <string>150.ImportedFromIB2</string> <string>19.IBPluginDependency</string> <string>19.ImportedFromIB2</string> <string>197.IBPluginDependency</string> <string>197.ImportedFromIB2</string> <string>198.IBPluginDependency</string> <string>198.ImportedFromIB2</string> <string>199.IBPluginDependency</string> <string>199.ImportedFromIB2</string> <string>202.IBPluginDependency</string> <string>202.ImportedFromIB2</string> <string>203.IBPluginDependency</string> <string>203.ImportedFromIB2</string> <string>205.IBEditorWindowLastContentRect</string> <string>205.IBPluginDependency</string> <string>205.ImportedFromIB2</string> <string>205.editorWindowContentRectSynchronizationRect</string> <string>206.IBPluginDependency</string> <string>206.ImportedFromIB2</string> <string>207.IBPluginDependency</string> <string>207.ImportedFromIB2</string> <string>215.IBPluginDependency</string> <string>215.ImportedFromIB2</string> <string>217.IBPluginDependency</string> <string>217.ImportedFromIB2</string> <string>23.IBPluginDependency</string> <string>23.ImportedFromIB2</string> <string>236.IBPluginDependency</string> <string>236.ImportedFromIB2</string> <string>239.IBPluginDependency</string> <string>239.ImportedFromIB2</string> <string>24.IBEditorWindowLastContentRect</string> <string>24.IBPluginDependency</string> <string>24.ImportedFromIB2</string> <string>24.editorWindowContentRectSynchronizationRect</string> <string>29.IBEditorWindowLastContentRect</string> <string>29.IBPluginDependency</string> <string>29.ImportedFromIB2</string> <string>29.WindowOrigin</string> <string>29.editorWindowContentRectSynchronizationRect</string> <string>371.IBEditorWindowLastContentRect</string> <string>371.IBPluginDependency</string> <string>371.IBWindowTemplateEditedContentRect</string> <string>371.NSWindowTemplate.visibleAtLaunch</string> <string>371.editorWindowContentRectSynchronizationRect</string> <string>371.windowTemplate.maxSize</string> <string>372.CustomClassName</string> <string>372.IBPluginDependency</string> <string>490.IBPluginDependency</string> <string>491.IBEditorWindowLastContentRect</string> <string>491.IBPluginDependency</string> <string>492.IBPluginDependency</string> <string>5.IBPluginDependency</string> <string>5.ImportedFromIB2</string> <string>56.IBPluginDependency</string> <string>56.ImportedFromIB2</string> <string>57.IBEditorWindowLastContentRect</string> <string>57.IBPluginDependency</string> <string>57.ImportedFromIB2</string> <string>57.editorWindowContentRectSynchronizationRect</string> <string>58.IBPluginDependency</string> <string>58.ImportedFromIB2</string> <string>72.IBPluginDependency</string> <string>72.ImportedFromIB2</string> <string>73.IBPluginDependency</string> <string>73.ImportedFromIB2</string> <string>74.IBPluginDependency</string> <string>74.ImportedFromIB2</string> <string>75.IBPluginDependency</string> <string>75.ImportedFromIB2</string> <string>77.IBPluginDependency</string> <string>77.ImportedFromIB2</string> <string>78.IBPluginDependency</string> <string>78.ImportedFromIB2</string> <string>79.IBPluginDependency</string> <string>79.ImportedFromIB2</string> <string>80.IBPluginDependency</string> <string>80.ImportedFromIB2</string> <string>81.IBEditorWindowLastContentRect</string> <string>81.IBPluginDependency</string> <string>81.ImportedFromIB2</string> <string>81.editorWindowContentRectSynchronizationRect</string> <string>82.IBPluginDependency</string> <string>82.ImportedFromIB2</string> <string>83.IBPluginDependency</string> <string>83.ImportedFromIB2</string> <string>92.IBPluginDependency</string> <string>92.ImportedFromIB2</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{522, 812}, {146, 23}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{436, 809}, {64, 6}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{547, 180}, {254, 283}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{187, 434}, {243, 243}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{654, 239}, {194, 73}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{525, 802}, {197, 73}}</string> <string>{{380, 836}, {474, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{74, 862}</string> <string>{{6, 978}, {478, 20}}</string> <string>{{380, 496}, {480, 360}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{380, 496}, {480, 360}}</string> <boolean value="NO"/> <string>{{33, 99}, {480, 360}}</string> <string>{3.40282e+38, 3.40282e+38}</string> <string>sqSqueakOSXNSView</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{793, 813}, {210, 23}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{286, 129}, {275, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{23, 794}, {245, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{452, 109}, {196, 203}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{145, 474}, {199, 203}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="sourceID"/> <int key="maxID">533</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">SqueakOSXAppDelegate</string> <string key="superclassName">sqSqueakAppDelegate</string> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>mainView</string> <string>window</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>sqSqueakOSXNSView</string> <string>NSWindow</string> </object> </object> <object class="NSMutableDictionary" key="toOneOutletInfosByName"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>mainView</string> <string>window</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBToOneOutletInfo"> <string key="name">mainView</string> <string key="candidateClassName">sqSqueakOSXNSView</string> </object> <object class="IBToOneOutletInfo"> <string key="name">window</string> <string key="candidateClassName">NSWindow</string> </object> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">OSX/SqueakOSXAppDelegate.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">SqueakOSXApplication</string> <string key="superclassName">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">OSX/SqueakOSXApplication.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakAppDelegate</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">Common/Classes/sqSqueakAppDelegate.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakOSXNSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">OSX/SqViewBitmapConversion.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakOSXNSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">OSX/SqViewClut.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakOSXNSView</string> <string key="superclassName">NSOpenGLView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">OSX/sqSqueakOSXNSView.h</string> </object> </object> </object> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <string key="superclassName">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="822405504"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="850738725"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="624831158"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSBrowser</string> <string key="superclassName">NSControl</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSControl</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="310914472"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocument</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>printDocument:</string> <string>revertDocumentToSaved:</string> <string>runPageLayout:</string> <string>saveDocument:</string> <string>saveDocumentAs:</string> <string>saveDocumentTo:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>id</string> <string>id</string> <string>id</string> <string>id</string> <string>id</string> <string>id</string> </object> </object> <object class="NSMutableDictionary" key="actionInfosByName"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>printDocument:</string> <string>revertDocumentToSaved:</string> <string>runPageLayout:</string> <string>saveDocument:</string> <string>saveDocumentAs:</string> <string>saveDocumentTo:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBActionInfo"> <string key="name">printDocument:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">revertDocumentToSaved:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">runPageLayout:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">saveDocument:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">saveDocumentAs:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">saveDocumentTo:</string> <string key="candidateClassName">id</string> </object> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocument</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocumentController</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>clearRecentDocuments:</string> <string>newDocument:</string> <string>openDocument:</string> <string>saveAllDocuments:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>id</string> <string>id</string> <string>id</string> <string>id</string> </object> </object> <object class="NSMutableDictionary" key="actionInfosByName"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>clearRecentDocuments:</string> <string>newDocument:</string> <string>openDocument:</string> <string>saveAllDocuments:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBActionInfo"> <string key="name">clearRecentDocuments:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">newDocument:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">openDocument:</string> <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> <string key="name">saveAllDocuments:</string> <string key="candidateClassName">id</string> </object> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSFontManager</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="946436764"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSFormatter</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMatrix</string> <string key="superclassName">NSControl</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMenu</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1056362899"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMenuItem</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="472958451"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMovieView</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="822405504"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="850738725"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="624831158"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="310914472"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="946436764"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="1056362899"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="809545482"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="260078765"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSError.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">PrintCore.framework/Headers/PDEPluginInterface.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSOpenGLView</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSOpenGLView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSResponder</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSTableView</string> <string key="superclassName">NSControl</string> <reference key="sourceIdentifier" ref="809545482"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSText</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSText.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <reference key="sourceIdentifier" ref="472958451"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <string key="superclassName">NSResponder</string> <reference key="sourceIdentifier" ref="260078765"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <string key="superclassName">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> <integer value="1060" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> <integer value="3000" key="NS.object.0"/> </object> <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> <string key="IBDocument.LastKnownRelativeProjectPath">../SqueakPureObjcCOGVM.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> <object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>NSMenuCheckmark</string> <string>NSMenuMixedState</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>{9, 8}</string> <string>{7, 2}</string> </object> </object> </data> </archive> ================================================ FILE: vm/src/from_squeak/iOS/vm/Entitlements.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>get-task-allow</key> <true/> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/Info-iPhone.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleDisplayName</key> <string>${PRODUCT_NAME}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIconFile</key> <string>Squeak72x72.png</string> <key>CFBundleIconFiles</key> <array> <string>Squeak72x72.png</string> <string>Squeak72x72.png</string> </array> <key>CFBundleIdentifier</key> <string>soft.roarvm.poc</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>${PRODUCT_NAME}</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>3.0</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>0.1</string> <key>LSRequiresIPhoneOS</key> <true/> <key>NSMainNibFile</key> <string>MainWindow</string> <key>NSMainNibFile~ipad</key> <string>MainWindow-iPad</string> <key>UIFileSharingEnabled</key> <true/> <key>UIInterfaceOrientation</key> <string>UIInterfaceOrientationPortrait</string> <key>UIPrerenderedIcon</key> <true/> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/MainWindow.xib ================================================ <?xml version="1.0" encoding="UTF-8"?> <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">512</int> <string key="IBDocument.SystemVersion">10D573</string> <string key="IBDocument.InterfaceBuilderVersion">762</string> <string key="IBDocument.AppKitVersion">1038.29</string> <string key="IBDocument.HIToolboxVersion">460.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string key="NS.object.0">87</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> <integer value="2"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> </object> <object class="NSMutableDictionary" key="IBDocument.Metadata"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys" id="0"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBProxyObject" id="841351856"> <string key="IBProxiedObjectIdentifier">IBFilesOwner</string> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> </object> <object class="IBProxyObject" id="64004946"> <string key="IBProxiedObjectIdentifier">IBFirstResponder</string> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> </object> <object class="IBUICustomObject" id="664661524"> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> </object> <object class="IBUIWindow" id="380026005"> <reference key="NSNextResponder"/> <int key="NSvFlags">1316</int> <object class="NSPSMatrix" key="NSFrameMatrix"/> <string key="NSFrameSize">{320, 480}</string> <reference key="NSSuperview"/> <object class="NSColor" key="IBUIBackgroundColor"> <int key="NSColorSpace">1</int> <bytes key="NSRGB">MSAxIDEAA</bytes> </object> <bool key="IBUIOpaque">NO</bool> <bool key="IBUIClearsContextBeforeDrawing">NO</bool> <bool key="IBUIMultipleTouchEnabled">YES</bool> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> <bool key="IBUIVisibleAtLaunch">YES</bool> </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBCocoaTouchOutletConnection" key="connection"> <string key="label">delegate</string> <reference key="source" ref="841351856"/> <reference key="destination" ref="664661524"/> </object> <int key="connectionID">4</int> </object> <object class="IBConnectionRecord"> <object class="IBCocoaTouchOutletConnection" key="connection"> <string key="label">window</string> <reference key="source" ref="664661524"/> <reference key="destination" ref="380026005"/> </object> <int key="connectionID">5</int> </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> <reference key="object" ref="0"/> <reference key="children" ref="1000"/> <nil key="parent"/> </object> <object class="IBObjectRecord"> <int key="objectID">2</int> <reference key="object" ref="380026005"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="841351856"/> <reference key="parent" ref="0"/> <string key="objectName">File's Owner</string> </object> <object class="IBObjectRecord"> <int key="objectID">3</int> <reference key="object" ref="664661524"/> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="64004946"/> <reference key="parent" ref="0"/> </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>-1.CustomClassName</string> <string>-2.CustomClassName</string> <string>2.IBAttributePlaceholdersKey</string> <string>2.IBEditorWindowLastContentRect</string> <string>2.IBPluginDependency</string> <string>3.CustomClassName</string> <string>3.IBPluginDependency</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>UIApplication</string> <string>UIResponder</string> <object class="NSMutableDictionary"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <string>{{362, 376}, {320, 480}}</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>SqueakNoOGLIPhoneAppDelegate</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="sourceID"/> <int key="maxID">14</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">SqueakNoOGLIPhoneAppDelegate</string> <string key="superclassName">sqSqueakAppDelegate</string> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>mainView</string> <string>viewController</string> <string>window</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>SqueakUIView</string> <string>SqueakUIController</string> <string>UIWindow</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakNoOGLIPhoneAppDelegate.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">SqueakUIController</string> <string key="superclassName">UIViewController</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">SqueakUIView</string> <string key="superclassName">UIView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">UIApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+Network.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakAppDelegate</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/Common/Classes/sqSqueakAppDelegate.h</string> </object> </object> </object> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSError.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">PrintCore.framework/Headers/PDEPluginInterface.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string> <integer value="512" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string> <integer value="800" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string> <integer value="3000" key="NS.object.0"/> </object> <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> <string key="IBDocument.LastKnownRelativeProjectPath">SqueakPureObjc.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> <string key="IBCocoaTouchPluginVersion">87</string> </data> </archive> ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/BitMapConversionLogicFromX11.c ================================================ /* * BitMapConversionLogicFromX11.c * SqueakPureObjc * * Created by John M McIntosh on 09-12-08. * Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. * This code is comes from the sqUnixX11.c logic to convert Squeak Forms to 32bit image data * */ /* sqUnixX11.c -- support for display via the X Window System. * * Copyright (C) 1996-2008 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "BitMapConversionLogicFromX11.h" //#define DEBUG #include <stdio.h> void copyImage16To32(short *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB) { long scanLine16, firstWord16, lastWord16; long scanLine32, firstWord32; int line; register unsigned int col; #if defined(DEBUG) fprintf(stderr, "copyImg16to32 %p -> %p (%d %d) %d %d %d %d\n", fromImageData, toImageData, width, height, affectedT, affectedL, affectedB, affectedR); #endif #define map16To32(w) (col= (w), \ (((col >> 10) & 0x1f) << 3) | \ (((col >> 5) & 0x1f) << 11) | \ ((col & 0x1f) << 19)) scanLine16= bytesPerLine(width, 16); firstWord16= scanLine16*affectedT + bytesPerLineRD(affectedL, 16); lastWord16= scanLine16*affectedT + bytesPerLine(affectedR, 16); scanLine32= bytesPerLine(width, 32); firstWord32= 0; for (line= affectedT; line < affectedB; line++) { register unsigned short *from= (unsigned short *)((long)fromImageData+firstWord16); register unsigned short *limit= (unsigned short *)((long)fromImageData+lastWord16); register unsigned int *to= (unsigned int *)((long)toImageData+firstWord32); while (from < limit) { # if defined(WORDS_BIGENDIAN) to[0]= map16To32(from[0]); to[1]= map16To32(from[1]); # else to[0]= map16To32(from[1]); to[1]= map16To32(from[0]); # endif from+= 2; to+= 2; } firstWord16+= scanLine16; lastWord16+= scanLine16; firstWord32+= scanLine32; } #undef map16To32 } void copyImage8To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors) { long scanLine8, firstWord8, lastWord8; long scanLine32, firstWord32; int line; scanLine8= bytesPerLine(width, 8); firstWord8= scanLine8*affectedT + bytesPerLineRD(affectedL, 8); lastWord8= scanLine8*affectedT + bytesPerLine(affectedR, 8); scanLine32= bytesPerLine(width, 32); firstWord32= 0; for (line= affectedT; line < affectedB; line++) { register unsigned char *from= (unsigned char *)((long)fromImageData+firstWord8); register unsigned char *limit= (unsigned char *)((long)fromImageData+lastWord8); register unsigned int *to= (unsigned int *)((long)toImageData+firstWord32); while (from < limit) { # if defined(WORDS_BIGENDIAN) to[0]= stColors[from[0]]; to[1]= stColors[from[1]]; to[2]= stColors[from[2]]; to[3]= stColors[from[3]]; # else to[0]= stColors[from[3]]; to[1]= stColors[from[2]]; to[2]= stColors[from[1]]; to[3]= stColors[from[0]]; # endif from+= 4; to+= 4; } firstWord8+= scanLine8; lastWord8+= scanLine8; firstWord32+= scanLine32; } } void copyImage4To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors) { int scanLine4, firstWord4, firstShift4; long scanLine32, firstWord32, lastWord32; long line; scanLine4= bytesPerLine(width, 4); firstWord4= scanLine4*affectedT + bytesPerLineRD(affectedL, 4); firstShift4= 28 - ((affectedL & 7) * 4); scanLine32= bytesPerLine(width, 32); firstWord32= 0; lastWord32= bytesPerLineRD(affectedR, 32); for (line= affectedT; line < affectedB; line++) { register unsigned int *from= (unsigned int *)((long)fromImageData+firstWord4); register unsigned int *to= (unsigned int *)((long)toImageData+firstWord32); register unsigned int *limit= (unsigned int *)((long)toImageData+lastWord32); register int shift= firstShift4; while (to < limit) { *to= stColors[(*from >> shift) & 15]; to++; shift-= 4; if (shift < 0) { shift= 28; from++; } } firstWord4+= scanLine4; firstWord32+= scanLine32; lastWord32+= scanLine32; } } void copyImage2To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors) { long scanLine2, firstWord2, firstShift2; long scanLine32, firstWord32, lastWord32; int line; scanLine2= bytesPerLine(width, 2); firstWord2= scanLine2*affectedT + bytesPerLineRD(affectedL, 2); firstShift2= 30 - ((affectedL & 15) * 2); scanLine32= bytesPerLine(width, 32); firstWord32= 0; lastWord32= bytesPerLineRD(affectedR, 32); for (line= affectedT; line < affectedB; line++) { register unsigned int *from= (unsigned int *)((long)fromImageData+firstWord2); register unsigned int *to= (unsigned int *)((long)toImageData+firstWord32); register unsigned int *limit= (unsigned int *)((long)toImageData+lastWord32); register int shift= firstShift2; while (to < limit) { *to= stColors[(*from >> shift) & 3]; to++; shift-= 2; if (shift < 0) { shift= 30; from++; } } firstWord2+= scanLine2; firstWord32+= scanLine32; lastWord32+= scanLine32; } } void copyImage1To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors) { long scanLine1, firstWord1, firstShift1; long scanLine32, firstWord32, lastWord32; int line; scanLine1= bytesPerLine(width, 1); firstWord1= scanLine1*affectedT + bytesPerLineRD(affectedL, 1); firstShift1= 31 - (affectedL & 31); scanLine32= bytesPerLine(width, 32); firstWord32= 0; lastWord32= bytesPerLine(affectedR, 32); for (line= affectedT; line < affectedB; line++) { register unsigned int *from= (unsigned int *)((long)fromImageData+firstWord1); register unsigned int *to= (unsigned int *)((long)toImageData+firstWord32); register unsigned int *limit= (unsigned int *)((long)toImageData+lastWord32); register int shift= firstShift1; while (to < limit) { *to= stColors[(*from >> shift) & 1]; to++; shift--; if (shift < 0) { shift= 31; from++; } } firstWord1+= scanLine1; firstWord32+= scanLine32; lastWord32+= scanLine32; } } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/BitMapConversionLogicFromX11.h ================================================ /* * BitMapConversionLogicFromX11.h * SqueakPureObjc * * Created by John M McIntosh on 09-12-08. * Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. * * This code is comes from the sqUnixX11.c logic to convert Squeak Forms to 32bit image data */ #define bytesPerLine(width, depth) ((((width)*(depth) + 31) >> 5) << 2) #define bytesPerLineRD(width, depth) ((((width)*(depth)) >> 5) << 2) void copyImage16To32(short *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB); void copyImage8To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int *colorMap); void copyImage2To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors); void copyImage1To32(int *fromImageData, int *toImageData, int width, int height, int affectedL, int affectedT, int affectedR, int affectedB, unsigned int * stColors); ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/Credits.rtf ================================================ {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc \f0\fs22 \cf0 Thanks to the European Smalltalk User Group\ (ESUG) for funding the iPhone implementation,\ and the Cocoa OS-X rewrite for 64 bits.\ \ OS-X & iOS port: John M McIntosh.\ Copyright (c) 2009-2010 Corporate Smalltalk Consulting Ltd.\ \ With some code by Ian Piumarta, \ clues from Marcel Weiher's Cocoa port,\ and bits from John Maloney and others.\ \ All contributions from Teleplace in this release are\ Copyright (c) 2010 Teleplace, Inc.} ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/English.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/English.lproj/MainMenu.xib ================================================ <?xml version="1.0" encoding="UTF-8"?> <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">1060</int> <string key="IBDocument.SystemVersion">10A324</string> <string key="IBDocument.InterfaceBuilderVersion">719</string> <string key="IBDocument.AppKitVersion">1015</string> <string key="IBDocument.HIToolboxVersion">418.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="NS.object.0">719</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> <integer value="371"/> <integer value="29"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> <object class="NSMutableDictionary" key="IBDocument.Metadata"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys" id="0"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSCustomObject" id="1021"> <string key="NSClassName">NSApplication</string> </object> <object class="NSCustomObject" id="1014"> <string key="NSClassName">FirstResponder</string> </object> <object class="NSCustomObject" id="1050"> <string key="NSClassName">NSApplication</string> </object> <object class="NSMenu" id="649796088"> <string key="NSTitle">AMainMenu</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="694149608"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">SqueakOSXApp</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <object class="NSCustomResource" key="NSOnImage" id="35465992"> <string key="NSClassName">NSImage</string> <string key="NSResourceName">NSMenuCheckmark</string> </object> <object class="NSCustomResource" key="NSMixedImage" id="502551668"> <string key="NSClassName">NSImage</string> <string key="NSResourceName">NSMenuMixedState</string> </object> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="110575045"> <string key="NSTitle">SqueakOSXApp</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="238522557"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">About SqueakOSXApp</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="304266470"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="609285721"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Preferences…</string> <string key="NSKeyEquiv">,</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="481834944"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1046388886"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Services</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="752062318"> <string key="NSTitle">Services</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <string key="NSName">_NSServicesMenu</string> </object> </object> <object class="NSMenuItem" id="646227648"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="755159360"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Hide SqueakOSXApp</string> <string key="NSKeyEquiv">h</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="342932134"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Hide Others</string> <string key="NSKeyEquiv">h</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="908899353"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Show All</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1056857174"> <reference key="NSMenu" ref="110575045"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="632727374"> <reference key="NSMenu" ref="110575045"/> <string key="NSTitle">Quit SqueakOSXApp</string> <string key="NSKeyEquiv">q</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSAppleMenu</string> </object> </object> <object class="NSMenuItem" id="379814623"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">File</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="720053764"> <string key="NSTitle">File</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="705341025"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">New</string> <string key="NSKeyEquiv">n</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="722745758"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Open…</string> <string key="NSKeyEquiv">o</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1025936716"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Open Recent</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="1065607017"> <string key="NSTitle">Open Recent</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="759406840"> <reference key="NSMenu" ref="1065607017"/> <string key="NSTitle">Clear Menu</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSRecentDocumentsMenu</string> </object> </object> <object class="NSMenuItem" id="425164168"> <reference key="NSMenu" ref="720053764"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="776162233"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Close</string> <string key="NSKeyEquiv">w</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1023925487"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Save</string> <string key="NSKeyEquiv">s</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="117038363"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Save As…</string> <string key="NSKeyEquiv">S</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="579971712"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Revert to Saved</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1010469920"> <reference key="NSMenu" ref="720053764"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="294629803"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Page Setup...</string> <string key="NSKeyEquiv">P</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSToolTip"/> </object> <object class="NSMenuItem" id="49223823"> <reference key="NSMenu" ref="720053764"/> <string key="NSTitle">Print…</string> <string key="NSKeyEquiv">p</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="952259628"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Edit</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="789758025"> <string key="NSTitle">Edit</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="1058277027"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Undo</string> <string key="NSKeyEquiv">z</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="790794224"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Redo</string> <string key="NSKeyEquiv">Z</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1040322652"> <reference key="NSMenu" ref="789758025"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="296257095"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Cut</string> <string key="NSKeyEquiv">x</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="860595796"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Copy</string> <string key="NSKeyEquiv">c</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="29853731"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Paste</string> <string key="NSKeyEquiv">v</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="82994268"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Paste and Match Style</string> <string key="NSKeyEquiv">V</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="437104165"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Delete</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="583158037"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Select All</string> <string key="NSKeyEquiv">a</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="212016141"> <reference key="NSMenu" ref="789758025"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="892235320"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Find</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="963351320"> <string key="NSTitle">Find</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="447796847"> <reference key="NSMenu" ref="963351320"/> <string key="NSTitle">Find…</string> <string key="NSKeyEquiv">f</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">1</int> </object> <object class="NSMenuItem" id="326711663"> <reference key="NSMenu" ref="963351320"/> <string key="NSTitle">Find Next</string> <string key="NSKeyEquiv">g</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">2</int> </object> <object class="NSMenuItem" id="270902937"> <reference key="NSMenu" ref="963351320"/> <string key="NSTitle">Find Previous</string> <string key="NSKeyEquiv">G</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">3</int> </object> <object class="NSMenuItem" id="159080638"> <reference key="NSMenu" ref="963351320"/> <string key="NSTitle">Use Selection for Find</string> <string key="NSKeyEquiv">e</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">7</int> </object> <object class="NSMenuItem" id="88285865"> <reference key="NSMenu" ref="963351320"/> <string key="NSTitle">Jump to Selection</string> <string key="NSKeyEquiv">j</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="972420730"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Spelling and Grammar</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="769623530"> <string key="NSTitle">Spelling and Grammar</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="679648819"> <reference key="NSMenu" ref="769623530"/> <string key="NSTitle">Show Spelling and Grammar</string> <string key="NSKeyEquiv">:</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="96193923"> <reference key="NSMenu" ref="769623530"/> <string key="NSTitle">Check Document Now</string> <string key="NSKeyEquiv">;</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="859480356"> <reference key="NSMenu" ref="769623530"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="948374510"> <reference key="NSMenu" ref="769623530"/> <string key="NSTitle">Check Spelling While Typing</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="967646866"> <reference key="NSMenu" ref="769623530"/> <string key="NSTitle">Check Grammar With Spelling</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="795346622"> <reference key="NSMenu" ref="769623530"/> <string key="NSTitle">Correct Spelling Automatically</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="507821607"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Substitutions</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="698887838"> <string key="NSTitle">Substitutions</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="65139061"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Show Substitutions</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="19036812"> <reference key="NSMenu" ref="698887838"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="605118523"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Smart Copy/Paste</string> <string key="NSKeyEquiv">f</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">1</int> </object> <object class="NSMenuItem" id="197661976"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Smart Quotes</string> <string key="NSKeyEquiv">g</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">2</int> </object> <object class="NSMenuItem" id="672708820"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Smart Dashes</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="708854459"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Smart Links</string> <string key="NSKeyEquiv">G</string> <int key="NSKeyEquivModMask">1179648</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">3</int> </object> <object class="NSMenuItem" id="537092702"> <reference key="NSMenu" ref="698887838"/> <string key="NSTitle">Text Replacement</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="288088188"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Transformations</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="579392910"> <string key="NSTitle">Transformations</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="1060694897"> <reference key="NSMenu" ref="579392910"/> <string key="NSTitle">Make Upper Case</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="879586729"> <reference key="NSMenu" ref="579392910"/> <string key="NSTitle">Make Lower Case</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="56570060"> <reference key="NSMenu" ref="579392910"/> <string key="NSTitle">Capitalize</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="676164635"> <reference key="NSMenu" ref="789758025"/> <string key="NSTitle">Speech</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="785027613"> <string key="NSTitle">Speech</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="731782645"> <reference key="NSMenu" ref="785027613"/> <string key="NSTitle">Start Speaking</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="680220178"> <reference key="NSMenu" ref="785027613"/> <string key="NSTitle">Stop Speaking</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> </object> </object> </object> <object class="NSMenuItem" id="302598603"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Format</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="941447902"> <string key="NSTitle">Format</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="792887677"> <reference key="NSMenu" ref="941447902"/> <string key="NSTitle">Font</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="786677654"> <string key="NSTitle">Font</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="159677712"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Show Fonts</string> <string key="NSKeyEquiv">t</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="305399458"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Bold</string> <string key="NSKeyEquiv">b</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">2</int> </object> <object class="NSMenuItem" id="814362025"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Italic</string> <string key="NSKeyEquiv">i</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">1</int> </object> <object class="NSMenuItem" id="330926929"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Underline</string> <string key="NSKeyEquiv">u</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="533507878"> <reference key="NSMenu" ref="786677654"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="158063935"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Bigger</string> <string key="NSKeyEquiv">+</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">3</int> </object> <object class="NSMenuItem" id="885547335"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Smaller</string> <string key="NSKeyEquiv">-</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <int key="NSTag">4</int> </object> <object class="NSMenuItem" id="901062459"> <reference key="NSMenu" ref="786677654"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="767671776"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Kern</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="175441468"> <string key="NSTitle">Kern</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="252969304"> <reference key="NSMenu" ref="175441468"/> <string key="NSTitle">Use Default</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="766922938"> <reference key="NSMenu" ref="175441468"/> <string key="NSTitle">Use None</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="677519740"> <reference key="NSMenu" ref="175441468"/> <string key="NSTitle">Tighten</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="238351151"> <reference key="NSMenu" ref="175441468"/> <string key="NSTitle">Loosen</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="691570813"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Ligature</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="1058217995"> <string key="NSTitle">Ligature</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="706297211"> <reference key="NSMenu" ref="1058217995"/> <string key="NSTitle">Use Default</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="568384683"> <reference key="NSMenu" ref="1058217995"/> <string key="NSTitle">Use None</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="663508465"> <reference key="NSMenu" ref="1058217995"/> <string key="NSTitle">Use All</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="769124883"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Baseline</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="18263474"> <string key="NSTitle">Baseline</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="257962622"> <reference key="NSMenu" ref="18263474"/> <string key="NSTitle">Use Default</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="644725453"> <reference key="NSMenu" ref="18263474"/> <string key="NSTitle">Superscript</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1037576581"> <reference key="NSMenu" ref="18263474"/> <string key="NSTitle">Subscript</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="941806246"> <reference key="NSMenu" ref="18263474"/> <string key="NSTitle">Raise</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1045724900"> <reference key="NSMenu" ref="18263474"/> <string key="NSTitle">Lower</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="739652853"> <reference key="NSMenu" ref="786677654"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="1012600125"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Show Colors</string> <string key="NSKeyEquiv">C</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="214559597"> <reference key="NSMenu" ref="786677654"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="596732606"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Copy Style</string> <string key="NSKeyEquiv">c</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="393423671"> <reference key="NSMenu" ref="786677654"/> <string key="NSTitle">Paste Style</string> <string key="NSKeyEquiv">v</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSFontMenu</string> </object> </object> <object class="NSMenuItem" id="215659978"> <reference key="NSMenu" ref="941447902"/> <string key="NSTitle">Text</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="446991534"> <string key="NSTitle">Text</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="875092757"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Align Left</string> <string key="NSKeyEquiv">{</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="630155264"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Center</string> <string key="NSKeyEquiv">|</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="945678886"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Justify</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="512868991"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Align Right</string> <string key="NSKeyEquiv">}</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="163117631"> <reference key="NSMenu" ref="446991534"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="31516759"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Writing Direction</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="956096989"> <string key="NSTitle">Writing Direction</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="257099033"> <reference key="NSMenu" ref="956096989"/> <bool key="NSIsDisabled">YES</bool> <string key="NSTitle">Paragraph</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="551969625"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="249532473"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="607364498"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="508151438"> <reference key="NSMenu" ref="956096989"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="981751889"> <reference key="NSMenu" ref="956096989"/> <bool key="NSIsDisabled">YES</bool> <string key="NSTitle">Selection</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="380031999"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="825984362"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="560145579"> <reference key="NSMenu" ref="956096989"/> <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="908105787"> <reference key="NSMenu" ref="446991534"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="644046920"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Show Ruler</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="231811626"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Copy Ruler</string> <string key="NSKeyEquiv">c</string> <int key="NSKeyEquivModMask">1310720</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="883618387"> <reference key="NSMenu" ref="446991534"/> <string key="NSTitle">Paste Ruler</string> <string key="NSKeyEquiv">v</string> <int key="NSKeyEquivModMask">1310720</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> </object> </object> </object> <object class="NSMenuItem" id="586577488"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">View</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="466310130"> <string key="NSTitle">View</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="102151532"> <reference key="NSMenu" ref="466310130"/> <string key="NSTitle">Show Toolbar</string> <string key="NSKeyEquiv">t</string> <int key="NSKeyEquivModMask">1572864</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="237841660"> <reference key="NSMenu" ref="466310130"/> <string key="NSTitle">Customize Toolbar…</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> </object> </object> <object class="NSMenuItem" id="713487014"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Window</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="835318025"> <string key="NSTitle">Window</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="1011231497"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Minimize</string> <string key="NSKeyEquiv">m</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="575023229"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Zoom</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="299356726"> <reference key="NSMenu" ref="835318025"/> <bool key="NSIsDisabled">YES</bool> <bool key="NSIsSeparator">YES</bool> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> <object class="NSMenuItem" id="625202149"> <reference key="NSMenu" ref="835318025"/> <string key="NSTitle">Bring All to Front</string> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSWindowsMenu</string> </object> </object> <object class="NSMenuItem" id="448692316"> <reference key="NSMenu" ref="649796088"/> <string key="NSTitle">Help</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="992780483"> <string key="NSTitle">Help</string> <object class="NSMutableArray" key="NSMenuItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMenuItem" id="105068016"> <reference key="NSMenu" ref="992780483"/> <string key="NSTitle">SqueakOSXApp Help</string> <string key="NSKeyEquiv">?</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> </object> <string key="NSName">_NSHelpMenu</string> </object> </object> </object> <string key="NSName">_NSMainMenu</string> </object> <object class="NSWindowTemplate" id="972006081"> <int key="NSWindowStyleMask">15</int> <int key="NSWindowBacking">2</int> <string key="NSWindowRect">{{335, 390}, {480, 360}}</string> <int key="NSWTFlags">1954021376</int> <string key="NSWindowTitle">SqueakOSXApp</string> <string key="NSWindowClass">NSWindow</string> <nil key="NSViewClass"/> <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <object class="NSView" key="NSWindowView" id="439893737"> <reference key="NSNextResponder"/> <int key="NSvFlags">256</int> <string key="NSFrameSize">{480, 360}</string> <reference key="NSSuperview"/> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> </object> <object class="NSCustomObject" id="976324537"> <string key="NSClassName">SqueakOSXAppAppDelegate</string> </object> <object class="NSCustomObject" id="755631768"> <string key="NSClassName">NSFontManager</string> </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performMiniaturize:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1011231497"/> </object> <int key="connectionID">37</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">arrangeInFront:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="625202149"/> </object> <int key="connectionID">39</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">print:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="49223823"/> </object> <int key="connectionID">86</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">runPageLayout:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="294629803"/> </object> <int key="connectionID">87</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">clearRecentDocuments:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="759406840"/> </object> <int key="connectionID">127</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">orderFrontStandardAboutPanel:</string> <reference key="source" ref="1021"/> <reference key="destination" ref="238522557"/> </object> <int key="connectionID">142</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performClose:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="776162233"/> </object> <int key="connectionID">193</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleContinuousSpellChecking:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="948374510"/> </object> <int key="connectionID">222</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">undo:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1058277027"/> </object> <int key="connectionID">223</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">copy:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="860595796"/> </object> <int key="connectionID">224</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">checkSpelling:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="96193923"/> </object> <int key="connectionID">225</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">paste:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="29853731"/> </object> <int key="connectionID">226</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">stopSpeaking:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="680220178"/> </object> <int key="connectionID">227</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">cut:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="296257095"/> </object> <int key="connectionID">228</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">showGuessPanel:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="679648819"/> </object> <int key="connectionID">230</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">redo:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="790794224"/> </object> <int key="connectionID">231</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">selectAll:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="583158037"/> </object> <int key="connectionID">232</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">startSpeaking:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="731782645"/> </object> <int key="connectionID">233</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">delete:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="437104165"/> </object> <int key="connectionID">235</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performZoom:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="575023229"/> </object> <int key="connectionID">240</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performFindPanelAction:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="447796847"/> </object> <int key="connectionID">241</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">centerSelectionInVisibleArea:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="88285865"/> </object> <int key="connectionID">245</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleGrammarChecking:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="967646866"/> </object> <int key="connectionID">347</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleSmartInsertDelete:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="605118523"/> </object> <int key="connectionID">355</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleAutomaticQuoteSubstitution:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="197661976"/> </object> <int key="connectionID">356</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleAutomaticLinkDetection:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="708854459"/> </object> <int key="connectionID">357</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">saveDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1023925487"/> </object> <int key="connectionID">362</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">saveDocumentAs:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="117038363"/> </object> <int key="connectionID">363</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">revertDocumentToSaved:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="579971712"/> </object> <int key="connectionID">364</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">runToolbarCustomizationPalette:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="237841660"/> </object> <int key="connectionID">365</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleToolbarShown:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="102151532"/> </object> <int key="connectionID">366</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">hide:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="755159360"/> </object> <int key="connectionID">367</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">hideOtherApplications:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="342932134"/> </object> <int key="connectionID">368</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">unhideAllApplications:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="908899353"/> </object> <int key="connectionID">370</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">newDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="705341025"/> </object> <int key="connectionID">373</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">openDocument:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="722745758"/> </object> <int key="connectionID">374</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">addFontTrait:</string> <reference key="source" ref="755631768"/> <reference key="destination" ref="305399458"/> </object> <int key="connectionID">421</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">addFontTrait:</string> <reference key="source" ref="755631768"/> <reference key="destination" ref="814362025"/> </object> <int key="connectionID">422</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">modifyFont:</string> <reference key="source" ref="755631768"/> <reference key="destination" ref="885547335"/> </object> <int key="connectionID">423</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">orderFrontFontPanel:</string> <reference key="source" ref="755631768"/> <reference key="destination" ref="159677712"/> </object> <int key="connectionID">424</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">modifyFont:</string> <reference key="source" ref="755631768"/> <reference key="destination" ref="158063935"/> </object> <int key="connectionID">425</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">raiseBaseline:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="941806246"/> </object> <int key="connectionID">426</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">lowerBaseline:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1045724900"/> </object> <int key="connectionID">427</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">copyFont:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="596732606"/> </object> <int key="connectionID">428</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">subscript:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1037576581"/> </object> <int key="connectionID">429</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">superscript:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="644725453"/> </object> <int key="connectionID">430</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">tightenKerning:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="677519740"/> </object> <int key="connectionID">431</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">underline:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="330926929"/> </object> <int key="connectionID">432</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">orderFrontColorPanel:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1012600125"/> </object> <int key="connectionID">433</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">useAllLigatures:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="663508465"/> </object> <int key="connectionID">434</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">loosenKerning:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="238351151"/> </object> <int key="connectionID">435</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">pasteFont:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="393423671"/> </object> <int key="connectionID">436</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">unscript:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="257962622"/> </object> <int key="connectionID">437</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">useStandardKerning:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="252969304"/> </object> <int key="connectionID">438</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">useStandardLigatures:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="706297211"/> </object> <int key="connectionID">439</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">turnOffLigatures:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="568384683"/> </object> <int key="connectionID">440</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">turnOffKerning:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="766922938"/> </object> <int key="connectionID">441</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">terminate:</string> <reference key="source" ref="1050"/> <reference key="destination" ref="632727374"/> </object> <int key="connectionID">449</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleAutomaticSpellingCorrection:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="795346622"/> </object> <int key="connectionID">456</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">orderFrontSubstitutionsPanel:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="65139061"/> </object> <int key="connectionID">458</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleAutomaticDashSubstitution:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="672708820"/> </object> <int key="connectionID">461</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleAutomaticTextReplacement:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="537092702"/> </object> <int key="connectionID">463</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">uppercaseWord:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="1060694897"/> </object> <int key="connectionID">464</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">capitalizeWord:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="56570060"/> </object> <int key="connectionID">467</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">lowercaseWord:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="879586729"/> </object> <int key="connectionID">468</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">pasteAsPlainText:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="82994268"/> </object> <int key="connectionID">486</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performFindPanelAction:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="326711663"/> </object> <int key="connectionID">487</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performFindPanelAction:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="270902937"/> </object> <int key="connectionID">488</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">performFindPanelAction:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="159080638"/> </object> <int key="connectionID">489</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">showHelp:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="105068016"/> </object> <int key="connectionID">493</int> </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">delegate</string> <reference key="source" ref="1021"/> <reference key="destination" ref="976324537"/> </object> <int key="connectionID">495</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">alignCenter:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="630155264"/> </object> <int key="connectionID">518</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">pasteRuler:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="883618387"/> </object> <int key="connectionID">519</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">toggleRuler:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="644046920"/> </object> <int key="connectionID">520</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">alignRight:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="512868991"/> </object> <int key="connectionID">521</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">copyRuler:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="231811626"/> </object> <int key="connectionID">522</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">alignJustified:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="945678886"/> </object> <int key="connectionID">523</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">alignLeft:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="875092757"/> </object> <int key="connectionID">524</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeBaseWritingDirectionNatural:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="551969625"/> </object> <int key="connectionID">525</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeBaseWritingDirectionLeftToRight:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="249532473"/> </object> <int key="connectionID">526</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeBaseWritingDirectionRightToLeft:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="607364498"/> </object> <int key="connectionID">527</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeTextWritingDirectionNatural:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="380031999"/> </object> <int key="connectionID">528</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeTextWritingDirectionLeftToRight:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="825984362"/> </object> <int key="connectionID">529</int> </object> <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">makeTextWritingDirectionRightToLeft:</string> <reference key="source" ref="1014"/> <reference key="destination" ref="560145579"/> </object> <int key="connectionID">530</int> </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">window</string> <reference key="source" ref="976324537"/> <reference key="destination" ref="972006081"/> </object> <int key="connectionID">532</int> </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> <reference key="object" ref="0"/> <reference key="children" ref="1048"/> <nil key="parent"/> </object> <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="1021"/> <reference key="parent" ref="0"/> <string key="objectName">File's Owner</string> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="1014"/> <reference key="parent" ref="0"/> <string key="objectName">First Responder</string> </object> <object class="IBObjectRecord"> <int key="objectID">-3</int> <reference key="object" ref="1050"/> <reference key="parent" ref="0"/> <string key="objectName">Application</string> </object> <object class="IBObjectRecord"> <int key="objectID">29</int> <reference key="object" ref="649796088"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="713487014"/> <reference ref="694149608"/> <reference ref="952259628"/> <reference ref="379814623"/> <reference ref="586577488"/> <reference ref="302598603"/> <reference ref="448692316"/> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">19</int> <reference key="object" ref="713487014"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="835318025"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">56</int> <reference key="object" ref="694149608"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="110575045"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">217</int> <reference key="object" ref="952259628"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="789758025"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">83</int> <reference key="object" ref="379814623"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="720053764"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">81</int> <reference key="object" ref="720053764"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1023925487"/> <reference ref="117038363"/> <reference ref="49223823"/> <reference ref="722745758"/> <reference ref="705341025"/> <reference ref="1025936716"/> <reference ref="294629803"/> <reference ref="776162233"/> <reference ref="425164168"/> <reference ref="579971712"/> <reference ref="1010469920"/> </object> <reference key="parent" ref="379814623"/> </object> <object class="IBObjectRecord"> <int key="objectID">75</int> <reference key="object" ref="1023925487"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">80</int> <reference key="object" ref="117038363"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">78</int> <reference key="object" ref="49223823"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">72</int> <reference key="object" ref="722745758"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">82</int> <reference key="object" ref="705341025"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">124</int> <reference key="object" ref="1025936716"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1065607017"/> </object> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">77</int> <reference key="object" ref="294629803"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">73</int> <reference key="object" ref="776162233"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">79</int> <reference key="object" ref="425164168"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">112</int> <reference key="object" ref="579971712"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">74</int> <reference key="object" ref="1010469920"/> <reference key="parent" ref="720053764"/> </object> <object class="IBObjectRecord"> <int key="objectID">125</int> <reference key="object" ref="1065607017"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="759406840"/> </object> <reference key="parent" ref="1025936716"/> </object> <object class="IBObjectRecord"> <int key="objectID">126</int> <reference key="object" ref="759406840"/> <reference key="parent" ref="1065607017"/> </object> <object class="IBObjectRecord"> <int key="objectID">205</int> <reference key="object" ref="789758025"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="437104165"/> <reference ref="583158037"/> <reference ref="1058277027"/> <reference ref="212016141"/> <reference ref="296257095"/> <reference ref="29853731"/> <reference ref="860595796"/> <reference ref="1040322652"/> <reference ref="790794224"/> <reference ref="892235320"/> <reference ref="972420730"/> <reference ref="676164635"/> <reference ref="507821607"/> <reference ref="288088188"/> <reference ref="82994268"/> </object> <reference key="parent" ref="952259628"/> </object> <object class="IBObjectRecord"> <int key="objectID">202</int> <reference key="object" ref="437104165"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">198</int> <reference key="object" ref="583158037"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">207</int> <reference key="object" ref="1058277027"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">214</int> <reference key="object" ref="212016141"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">199</int> <reference key="object" ref="296257095"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">203</int> <reference key="object" ref="29853731"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">197</int> <reference key="object" ref="860595796"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">206</int> <reference key="object" ref="1040322652"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">215</int> <reference key="object" ref="790794224"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">218</int> <reference key="object" ref="892235320"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="963351320"/> </object> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">216</int> <reference key="object" ref="972420730"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="769623530"/> </object> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">200</int> <reference key="object" ref="769623530"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="948374510"/> <reference ref="96193923"/> <reference ref="679648819"/> <reference ref="967646866"/> <reference ref="859480356"/> <reference ref="795346622"/> </object> <reference key="parent" ref="972420730"/> </object> <object class="IBObjectRecord"> <int key="objectID">219</int> <reference key="object" ref="948374510"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">201</int> <reference key="object" ref="96193923"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">204</int> <reference key="object" ref="679648819"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">220</int> <reference key="object" ref="963351320"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="270902937"/> <reference ref="88285865"/> <reference ref="159080638"/> <reference ref="326711663"/> <reference ref="447796847"/> </object> <reference key="parent" ref="892235320"/> </object> <object class="IBObjectRecord"> <int key="objectID">213</int> <reference key="object" ref="270902937"/> <reference key="parent" ref="963351320"/> </object> <object class="IBObjectRecord"> <int key="objectID">210</int> <reference key="object" ref="88285865"/> <reference key="parent" ref="963351320"/> </object> <object class="IBObjectRecord"> <int key="objectID">221</int> <reference key="object" ref="159080638"/> <reference key="parent" ref="963351320"/> </object> <object class="IBObjectRecord"> <int key="objectID">208</int> <reference key="object" ref="326711663"/> <reference key="parent" ref="963351320"/> </object> <object class="IBObjectRecord"> <int key="objectID">209</int> <reference key="object" ref="447796847"/> <reference key="parent" ref="963351320"/> </object> <object class="IBObjectRecord"> <int key="objectID">57</int> <reference key="object" ref="110575045"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="238522557"/> <reference ref="755159360"/> <reference ref="908899353"/> <reference ref="632727374"/> <reference ref="646227648"/> <reference ref="609285721"/> <reference ref="481834944"/> <reference ref="304266470"/> <reference ref="1046388886"/> <reference ref="1056857174"/> <reference ref="342932134"/> </object> <reference key="parent" ref="694149608"/> </object> <object class="IBObjectRecord"> <int key="objectID">58</int> <reference key="object" ref="238522557"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">134</int> <reference key="object" ref="755159360"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">150</int> <reference key="object" ref="908899353"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">136</int> <reference key="object" ref="632727374"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">144</int> <reference key="object" ref="646227648"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">129</int> <reference key="object" ref="609285721"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">143</int> <reference key="object" ref="481834944"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">236</int> <reference key="object" ref="304266470"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">131</int> <reference key="object" ref="1046388886"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="752062318"/> </object> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">149</int> <reference key="object" ref="1056857174"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">145</int> <reference key="object" ref="342932134"/> <reference key="parent" ref="110575045"/> </object> <object class="IBObjectRecord"> <int key="objectID">130</int> <reference key="object" ref="752062318"/> <reference key="parent" ref="1046388886"/> </object> <object class="IBObjectRecord"> <int key="objectID">24</int> <reference key="object" ref="835318025"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="299356726"/> <reference ref="625202149"/> <reference ref="575023229"/> <reference ref="1011231497"/> </object> <reference key="parent" ref="713487014"/> </object> <object class="IBObjectRecord"> <int key="objectID">92</int> <reference key="object" ref="299356726"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">5</int> <reference key="object" ref="625202149"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">239</int> <reference key="object" ref="575023229"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">23</int> <reference key="object" ref="1011231497"/> <reference key="parent" ref="835318025"/> </object> <object class="IBObjectRecord"> <int key="objectID">295</int> <reference key="object" ref="586577488"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="466310130"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">296</int> <reference key="object" ref="466310130"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="102151532"/> <reference ref="237841660"/> </object> <reference key="parent" ref="586577488"/> </object> <object class="IBObjectRecord"> <int key="objectID">297</int> <reference key="object" ref="102151532"/> <reference key="parent" ref="466310130"/> </object> <object class="IBObjectRecord"> <int key="objectID">298</int> <reference key="object" ref="237841660"/> <reference key="parent" ref="466310130"/> </object> <object class="IBObjectRecord"> <int key="objectID">211</int> <reference key="object" ref="676164635"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="785027613"/> </object> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">212</int> <reference key="object" ref="785027613"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="680220178"/> <reference ref="731782645"/> </object> <reference key="parent" ref="676164635"/> </object> <object class="IBObjectRecord"> <int key="objectID">195</int> <reference key="object" ref="680220178"/> <reference key="parent" ref="785027613"/> </object> <object class="IBObjectRecord"> <int key="objectID">196</int> <reference key="object" ref="731782645"/> <reference key="parent" ref="785027613"/> </object> <object class="IBObjectRecord"> <int key="objectID">346</int> <reference key="object" ref="967646866"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">348</int> <reference key="object" ref="507821607"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="698887838"/> </object> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">349</int> <reference key="object" ref="698887838"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="605118523"/> <reference ref="197661976"/> <reference ref="708854459"/> <reference ref="65139061"/> <reference ref="19036812"/> <reference ref="672708820"/> <reference ref="537092702"/> </object> <reference key="parent" ref="507821607"/> </object> <object class="IBObjectRecord"> <int key="objectID">350</int> <reference key="object" ref="605118523"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">351</int> <reference key="object" ref="197661976"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">354</int> <reference key="object" ref="708854459"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">371</int> <reference key="object" ref="972006081"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="439893737"/> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">372</int> <reference key="object" ref="439893737"/> <reference key="parent" ref="972006081"/> </object> <object class="IBObjectRecord"> <int key="objectID">375</int> <reference key="object" ref="302598603"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="941447902"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">376</int> <reference key="object" ref="941447902"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="792887677"/> <reference ref="215659978"/> </object> <reference key="parent" ref="302598603"/> </object> <object class="IBObjectRecord"> <int key="objectID">377</int> <reference key="object" ref="792887677"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="786677654"/> </object> <reference key="parent" ref="941447902"/> </object> <object class="IBObjectRecord"> <int key="objectID">388</int> <reference key="object" ref="786677654"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="159677712"/> <reference ref="305399458"/> <reference ref="814362025"/> <reference ref="330926929"/> <reference ref="533507878"/> <reference ref="158063935"/> <reference ref="885547335"/> <reference ref="901062459"/> <reference ref="767671776"/> <reference ref="691570813"/> <reference ref="769124883"/> <reference ref="739652853"/> <reference ref="1012600125"/> <reference ref="214559597"/> <reference ref="596732606"/> <reference ref="393423671"/> </object> <reference key="parent" ref="792887677"/> </object> <object class="IBObjectRecord"> <int key="objectID">389</int> <reference key="object" ref="159677712"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">390</int> <reference key="object" ref="305399458"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">391</int> <reference key="object" ref="814362025"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">392</int> <reference key="object" ref="330926929"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">393</int> <reference key="object" ref="533507878"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">394</int> <reference key="object" ref="158063935"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">395</int> <reference key="object" ref="885547335"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">396</int> <reference key="object" ref="901062459"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">397</int> <reference key="object" ref="767671776"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="175441468"/> </object> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">398</int> <reference key="object" ref="691570813"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1058217995"/> </object> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">399</int> <reference key="object" ref="769124883"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="18263474"/> </object> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">400</int> <reference key="object" ref="739652853"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">401</int> <reference key="object" ref="1012600125"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">402</int> <reference key="object" ref="214559597"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">403</int> <reference key="object" ref="596732606"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">404</int> <reference key="object" ref="393423671"/> <reference key="parent" ref="786677654"/> </object> <object class="IBObjectRecord"> <int key="objectID">405</int> <reference key="object" ref="18263474"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="257962622"/> <reference ref="644725453"/> <reference ref="1037576581"/> <reference ref="941806246"/> <reference ref="1045724900"/> </object> <reference key="parent" ref="769124883"/> </object> <object class="IBObjectRecord"> <int key="objectID">406</int> <reference key="object" ref="257962622"/> <reference key="parent" ref="18263474"/> </object> <object class="IBObjectRecord"> <int key="objectID">407</int> <reference key="object" ref="644725453"/> <reference key="parent" ref="18263474"/> </object> <object class="IBObjectRecord"> <int key="objectID">408</int> <reference key="object" ref="1037576581"/> <reference key="parent" ref="18263474"/> </object> <object class="IBObjectRecord"> <int key="objectID">409</int> <reference key="object" ref="941806246"/> <reference key="parent" ref="18263474"/> </object> <object class="IBObjectRecord"> <int key="objectID">410</int> <reference key="object" ref="1045724900"/> <reference key="parent" ref="18263474"/> </object> <object class="IBObjectRecord"> <int key="objectID">411</int> <reference key="object" ref="1058217995"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="706297211"/> <reference ref="568384683"/> <reference ref="663508465"/> </object> <reference key="parent" ref="691570813"/> </object> <object class="IBObjectRecord"> <int key="objectID">412</int> <reference key="object" ref="706297211"/> <reference key="parent" ref="1058217995"/> </object> <object class="IBObjectRecord"> <int key="objectID">413</int> <reference key="object" ref="568384683"/> <reference key="parent" ref="1058217995"/> </object> <object class="IBObjectRecord"> <int key="objectID">414</int> <reference key="object" ref="663508465"/> <reference key="parent" ref="1058217995"/> </object> <object class="IBObjectRecord"> <int key="objectID">415</int> <reference key="object" ref="175441468"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="252969304"/> <reference ref="766922938"/> <reference ref="677519740"/> <reference ref="238351151"/> </object> <reference key="parent" ref="767671776"/> </object> <object class="IBObjectRecord"> <int key="objectID">416</int> <reference key="object" ref="252969304"/> <reference key="parent" ref="175441468"/> </object> <object class="IBObjectRecord"> <int key="objectID">417</int> <reference key="object" ref="766922938"/> <reference key="parent" ref="175441468"/> </object> <object class="IBObjectRecord"> <int key="objectID">418</int> <reference key="object" ref="677519740"/> <reference key="parent" ref="175441468"/> </object> <object class="IBObjectRecord"> <int key="objectID">419</int> <reference key="object" ref="238351151"/> <reference key="parent" ref="175441468"/> </object> <object class="IBObjectRecord"> <int key="objectID">420</int> <reference key="object" ref="755631768"/> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">450</int> <reference key="object" ref="288088188"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="579392910"/> </object> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">451</int> <reference key="object" ref="579392910"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="1060694897"/> <reference ref="879586729"/> <reference ref="56570060"/> </object> <reference key="parent" ref="288088188"/> </object> <object class="IBObjectRecord"> <int key="objectID">452</int> <reference key="object" ref="1060694897"/> <reference key="parent" ref="579392910"/> </object> <object class="IBObjectRecord"> <int key="objectID">453</int> <reference key="object" ref="859480356"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">454</int> <reference key="object" ref="795346622"/> <reference key="parent" ref="769623530"/> </object> <object class="IBObjectRecord"> <int key="objectID">457</int> <reference key="object" ref="65139061"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">459</int> <reference key="object" ref="19036812"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">460</int> <reference key="object" ref="672708820"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">462</int> <reference key="object" ref="537092702"/> <reference key="parent" ref="698887838"/> </object> <object class="IBObjectRecord"> <int key="objectID">465</int> <reference key="object" ref="879586729"/> <reference key="parent" ref="579392910"/> </object> <object class="IBObjectRecord"> <int key="objectID">466</int> <reference key="object" ref="56570060"/> <reference key="parent" ref="579392910"/> </object> <object class="IBObjectRecord"> <int key="objectID">485</int> <reference key="object" ref="82994268"/> <reference key="parent" ref="789758025"/> </object> <object class="IBObjectRecord"> <int key="objectID">490</int> <reference key="object" ref="448692316"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="992780483"/> </object> <reference key="parent" ref="649796088"/> </object> <object class="IBObjectRecord"> <int key="objectID">491</int> <reference key="object" ref="992780483"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="105068016"/> </object> <reference key="parent" ref="448692316"/> </object> <object class="IBObjectRecord"> <int key="objectID">492</int> <reference key="object" ref="105068016"/> <reference key="parent" ref="992780483"/> </object> <object class="IBObjectRecord"> <int key="objectID">494</int> <reference key="object" ref="976324537"/> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">496</int> <reference key="object" ref="215659978"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="446991534"/> </object> <reference key="parent" ref="941447902"/> </object> <object class="IBObjectRecord"> <int key="objectID">497</int> <reference key="object" ref="446991534"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="875092757"/> <reference ref="630155264"/> <reference ref="945678886"/> <reference ref="512868991"/> <reference ref="163117631"/> <reference ref="31516759"/> <reference ref="908105787"/> <reference ref="644046920"/> <reference ref="231811626"/> <reference ref="883618387"/> </object> <reference key="parent" ref="215659978"/> </object> <object class="IBObjectRecord"> <int key="objectID">498</int> <reference key="object" ref="875092757"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">499</int> <reference key="object" ref="630155264"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">500</int> <reference key="object" ref="945678886"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">501</int> <reference key="object" ref="512868991"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">502</int> <reference key="object" ref="163117631"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">503</int> <reference key="object" ref="31516759"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="956096989"/> </object> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">504</int> <reference key="object" ref="908105787"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">505</int> <reference key="object" ref="644046920"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">506</int> <reference key="object" ref="231811626"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">507</int> <reference key="object" ref="883618387"/> <reference key="parent" ref="446991534"/> </object> <object class="IBObjectRecord"> <int key="objectID">508</int> <reference key="object" ref="956096989"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="257099033"/> <reference ref="551969625"/> <reference ref="249532473"/> <reference ref="607364498"/> <reference ref="508151438"/> <reference ref="981751889"/> <reference ref="380031999"/> <reference ref="825984362"/> <reference ref="560145579"/> </object> <reference key="parent" ref="31516759"/> </object> <object class="IBObjectRecord"> <int key="objectID">509</int> <reference key="object" ref="257099033"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">510</int> <reference key="object" ref="551969625"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">511</int> <reference key="object" ref="249532473"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">512</int> <reference key="object" ref="607364498"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">513</int> <reference key="object" ref="508151438"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">514</int> <reference key="object" ref="981751889"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">515</int> <reference key="object" ref="380031999"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">516</int> <reference key="object" ref="825984362"/> <reference key="parent" ref="956096989"/> </object> <object class="IBObjectRecord"> <int key="objectID">517</int> <reference key="object" ref="560145579"/> <reference key="parent" ref="956096989"/> </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>-3.IBPluginDependency</string> <string>112.IBPluginDependency</string> <string>112.ImportedFromIB2</string> <string>124.IBPluginDependency</string> <string>124.ImportedFromIB2</string> <string>125.IBPluginDependency</string> <string>125.ImportedFromIB2</string> <string>125.editorWindowContentRectSynchronizationRect</string> <string>126.IBPluginDependency</string> <string>126.ImportedFromIB2</string> <string>129.IBPluginDependency</string> <string>129.ImportedFromIB2</string> <string>130.IBPluginDependency</string> <string>130.ImportedFromIB2</string> <string>130.editorWindowContentRectSynchronizationRect</string> <string>131.IBPluginDependency</string> <string>131.ImportedFromIB2</string> <string>134.IBPluginDependency</string> <string>134.ImportedFromIB2</string> <string>136.IBPluginDependency</string> <string>136.ImportedFromIB2</string> <string>143.IBPluginDependency</string> <string>143.ImportedFromIB2</string> <string>144.IBPluginDependency</string> <string>144.ImportedFromIB2</string> <string>145.IBPluginDependency</string> <string>145.ImportedFromIB2</string> <string>149.IBPluginDependency</string> <string>149.ImportedFromIB2</string> <string>150.IBPluginDependency</string> <string>150.ImportedFromIB2</string> <string>19.IBPluginDependency</string> <string>19.ImportedFromIB2</string> <string>195.IBPluginDependency</string> <string>195.ImportedFromIB2</string> <string>196.IBPluginDependency</string> <string>196.ImportedFromIB2</string> <string>197.IBPluginDependency</string> <string>197.ImportedFromIB2</string> <string>198.IBPluginDependency</string> <string>198.ImportedFromIB2</string> <string>199.IBPluginDependency</string> <string>199.ImportedFromIB2</string> <string>200.IBEditorWindowLastContentRect</string> <string>200.IBPluginDependency</string> <string>200.ImportedFromIB2</string> <string>200.editorWindowContentRectSynchronizationRect</string> <string>201.IBPluginDependency</string> <string>201.ImportedFromIB2</string> <string>202.IBPluginDependency</string> <string>202.ImportedFromIB2</string> <string>203.IBPluginDependency</string> <string>203.ImportedFromIB2</string> <string>204.IBPluginDependency</string> <string>204.ImportedFromIB2</string> <string>205.IBEditorWindowLastContentRect</string> <string>205.IBPluginDependency</string> <string>205.ImportedFromIB2</string> <string>205.editorWindowContentRectSynchronizationRect</string> <string>206.IBPluginDependency</string> <string>206.ImportedFromIB2</string> <string>207.IBPluginDependency</string> <string>207.ImportedFromIB2</string> <string>208.IBPluginDependency</string> <string>208.ImportedFromIB2</string> <string>209.IBPluginDependency</string> <string>209.ImportedFromIB2</string> <string>210.IBPluginDependency</string> <string>210.ImportedFromIB2</string> <string>211.IBPluginDependency</string> <string>211.ImportedFromIB2</string> <string>212.IBPluginDependency</string> <string>212.ImportedFromIB2</string> <string>212.editorWindowContentRectSynchronizationRect</string> <string>213.IBPluginDependency</string> <string>213.ImportedFromIB2</string> <string>214.IBPluginDependency</string> <string>214.ImportedFromIB2</string> <string>215.IBPluginDependency</string> <string>215.ImportedFromIB2</string> <string>216.IBPluginDependency</string> <string>216.ImportedFromIB2</string> <string>217.IBPluginDependency</string> <string>217.ImportedFromIB2</string> <string>218.IBPluginDependency</string> <string>218.ImportedFromIB2</string> <string>219.IBPluginDependency</string> <string>219.ImportedFromIB2</string> <string>220.IBEditorWindowLastContentRect</string> <string>220.IBPluginDependency</string> <string>220.ImportedFromIB2</string> <string>220.editorWindowContentRectSynchronizationRect</string> <string>221.IBPluginDependency</string> <string>221.ImportedFromIB2</string> <string>23.IBPluginDependency</string> <string>23.ImportedFromIB2</string> <string>236.IBPluginDependency</string> <string>236.ImportedFromIB2</string> <string>239.IBPluginDependency</string> <string>239.ImportedFromIB2</string> <string>24.IBEditorWindowLastContentRect</string> <string>24.IBPluginDependency</string> <string>24.ImportedFromIB2</string> <string>24.editorWindowContentRectSynchronizationRect</string> <string>29.IBEditorWindowLastContentRect</string> <string>29.IBPluginDependency</string> <string>29.ImportedFromIB2</string> <string>29.WindowOrigin</string> <string>29.editorWindowContentRectSynchronizationRect</string> <string>295.IBPluginDependency</string> <string>296.IBEditorWindowLastContentRect</string> <string>296.IBPluginDependency</string> <string>296.editorWindowContentRectSynchronizationRect</string> <string>297.IBPluginDependency</string> <string>298.IBPluginDependency</string> <string>346.IBPluginDependency</string> <string>346.ImportedFromIB2</string> <string>348.IBPluginDependency</string> <string>348.ImportedFromIB2</string> <string>349.IBEditorWindowLastContentRect</string> <string>349.IBPluginDependency</string> <string>349.ImportedFromIB2</string> <string>349.editorWindowContentRectSynchronizationRect</string> <string>350.IBPluginDependency</string> <string>350.ImportedFromIB2</string> <string>351.IBPluginDependency</string> <string>351.ImportedFromIB2</string> <string>354.IBPluginDependency</string> <string>354.ImportedFromIB2</string> <string>371.IBEditorWindowLastContentRect</string> <string>371.IBPluginDependency</string> <string>371.IBWindowTemplateEditedContentRect</string> <string>371.NSWindowTemplate.visibleAtLaunch</string> <string>371.editorWindowContentRectSynchronizationRect</string> <string>371.windowTemplate.maxSize</string> <string>372.IBPluginDependency</string> <string>375.IBPluginDependency</string> <string>376.IBEditorWindowLastContentRect</string> <string>376.IBPluginDependency</string> <string>377.IBPluginDependency</string> <string>388.IBEditorWindowLastContentRect</string> <string>388.IBPluginDependency</string> <string>389.IBPluginDependency</string> <string>390.IBPluginDependency</string> <string>391.IBPluginDependency</string> <string>392.IBPluginDependency</string> <string>393.IBPluginDependency</string> <string>394.IBPluginDependency</string> <string>395.IBPluginDependency</string> <string>396.IBPluginDependency</string> <string>397.IBPluginDependency</string> <string>398.IBPluginDependency</string> <string>399.IBPluginDependency</string> <string>400.IBPluginDependency</string> <string>401.IBPluginDependency</string> <string>402.IBPluginDependency</string> <string>403.IBPluginDependency</string> <string>404.IBPluginDependency</string> <string>405.IBPluginDependency</string> <string>406.IBPluginDependency</string> <string>407.IBPluginDependency</string> <string>408.IBPluginDependency</string> <string>409.IBPluginDependency</string> <string>410.IBPluginDependency</string> <string>411.IBPluginDependency</string> <string>412.IBPluginDependency</string> <string>413.IBPluginDependency</string> <string>414.IBPluginDependency</string> <string>415.IBPluginDependency</string> <string>416.IBPluginDependency</string> <string>417.IBPluginDependency</string> <string>418.IBPluginDependency</string> <string>419.IBPluginDependency</string> <string>450.IBPluginDependency</string> <string>451.IBEditorWindowLastContentRect</string> <string>451.IBPluginDependency</string> <string>452.IBPluginDependency</string> <string>453.IBPluginDependency</string> <string>454.IBPluginDependency</string> <string>457.IBPluginDependency</string> <string>459.IBPluginDependency</string> <string>460.IBPluginDependency</string> <string>462.IBPluginDependency</string> <string>465.IBPluginDependency</string> <string>466.IBPluginDependency</string> <string>485.IBPluginDependency</string> <string>490.IBPluginDependency</string> <string>491.IBEditorWindowLastContentRect</string> <string>491.IBPluginDependency</string> <string>492.IBPluginDependency</string> <string>496.IBPluginDependency</string> <string>497.IBEditorWindowLastContentRect</string> <string>497.IBPluginDependency</string> <string>498.IBPluginDependency</string> <string>499.IBPluginDependency</string> <string>5.IBPluginDependency</string> <string>5.ImportedFromIB2</string> <string>500.IBPluginDependency</string> <string>501.IBPluginDependency</string> <string>502.IBPluginDependency</string> <string>503.IBPluginDependency</string> <string>504.IBPluginDependency</string> <string>505.IBPluginDependency</string> <string>506.IBPluginDependency</string> <string>507.IBPluginDependency</string> <string>508.IBEditorWindowLastContentRect</string> <string>508.IBPluginDependency</string> <string>509.IBPluginDependency</string> <string>510.IBPluginDependency</string> <string>511.IBPluginDependency</string> <string>512.IBPluginDependency</string> <string>513.IBPluginDependency</string> <string>514.IBPluginDependency</string> <string>515.IBPluginDependency</string> <string>516.IBPluginDependency</string> <string>517.IBPluginDependency</string> <string>56.IBPluginDependency</string> <string>56.ImportedFromIB2</string> <string>57.IBEditorWindowLastContentRect</string> <string>57.IBPluginDependency</string> <string>57.ImportedFromIB2</string> <string>57.editorWindowContentRectSynchronizationRect</string> <string>58.IBPluginDependency</string> <string>58.ImportedFromIB2</string> <string>72.IBPluginDependency</string> <string>72.ImportedFromIB2</string> <string>73.IBPluginDependency</string> <string>73.ImportedFromIB2</string> <string>74.IBPluginDependency</string> <string>74.ImportedFromIB2</string> <string>75.IBPluginDependency</string> <string>75.ImportedFromIB2</string> <string>77.IBPluginDependency</string> <string>77.ImportedFromIB2</string> <string>78.IBPluginDependency</string> <string>78.ImportedFromIB2</string> <string>79.IBPluginDependency</string> <string>79.ImportedFromIB2</string> <string>80.IBPluginDependency</string> <string>80.ImportedFromIB2</string> <string>81.IBEditorWindowLastContentRect</string> <string>81.IBPluginDependency</string> <string>81.ImportedFromIB2</string> <string>81.editorWindowContentRectSynchronizationRect</string> <string>82.IBPluginDependency</string> <string>82.ImportedFromIB2</string> <string>83.IBPluginDependency</string> <string>83.ImportedFromIB2</string> <string>92.IBPluginDependency</string> <string>92.ImportedFromIB2</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{522, 812}, {146, 23}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{436, 809}, {64, 6}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{753, 187}, {275, 113}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{608, 612}, {275, 83}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{547, 180}, {254, 283}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{187, 434}, {243, 243}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{608, 612}, {167, 43}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{753, 217}, {238, 103}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{608, 612}, {241, 103}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{654, 239}, {194, 73}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{525, 802}, {197, 73}}</string> <string>{{380, 836}, {512, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{74, 862}</string> <string>{{6, 978}, {478, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{604, 269}, {231, 43}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{475, 832}, {234, 43}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{746, 287}, {220, 133}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{608, 612}, {215, 63}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{380, 496}, {480, 360}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{380, 496}, {480, 360}}</string> <integer value="1"/> <string>{{33, 99}, {480, 360}}</string> <string>{3.40282e+38, 3.40282e+38}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{591, 420}, {83, 43}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{523, 2}, {178, 283}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{753, 197}, {170, 63}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{725, 289}, {246, 23}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{674, 260}, {204, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{878, 180}, {164, 173}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{286, 129}, {275, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{23, 794}, {245, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{452, 109}, {196, 203}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{145, 474}, {199, 203}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="sourceID"/> <int key="maxID">532</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">SqueakOSXAppAppDelegate</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="outlets"> <string key="NS.key.0">window</string> <string key="NS.object.0">NSWindow</string> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">SqueakOSXAppAppDelegate.h</string> </object> </object> </object> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <string key="superclassName">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="822405504"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="850738725"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="624831158"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSBrowser</string> <string key="superclassName">NSControl</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSControl</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="310914472"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocument</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>printDocument:</string> <string>revertDocumentToSaved:</string> <string>runPageLayout:</string> <string>saveDocument:</string> <string>saveDocumentAs:</string> <string>saveDocumentTo:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>id</string> <string>id</string> <string>id</string> <string>id</string> <string>id</string> <string>id</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocument</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSDocumentController</string> <string key="superclassName">NSObject</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>clearRecentDocuments:</string> <string>newDocument:</string> <string>openDocument:</string> <string>saveAllDocuments:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>id</string> <string>id</string> <string>id</string> <string>id</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSFontManager</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="946436764"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSFormatter</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMatrix</string> <string key="superclassName">NSControl</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMenu</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1056362899"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMenuItem</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="472958451"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSMovieView</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="822405504"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="850738725"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="624831158"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="310914472"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="946436764"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <reference key="sourceIdentifier" ref="1056362899"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="809545482"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier" id="260078765"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSError.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSResponder</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSTableView</string> <string key="superclassName">NSControl</string> <reference key="sourceIdentifier" ref="809545482"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSText</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSText.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSTextView</string> <string key="superclassName">NSText</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <reference key="sourceIdentifier" ref="472958451"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSView</string> <string key="superclassName">NSResponder</string> <reference key="sourceIdentifier" ref="260078765"/> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <string key="superclassName">NSResponder</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSWindow</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> <integer value="1060" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> <integer value="3000" key="NS.object.0"/> </object> <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> <string key="IBDocument.LastKnownRelativeProjectPath">../SqueakOSXApp.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> </data> </archive> ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqViewBitmapConversion.h ================================================ /* SqViewBitmapConversion.h created by marcel on Fri 04-Dec-1998 */ // CocoaSqueak // John Notes: Waste not want not. /* From: Marcel Weiher <marcel.weiher@gmail.com> To: johnmci@smalltalkconsulting.com In-Reply-To: <BEB4569D-C606-4FF4-9B1B-A95570E38B94@smalltalkconsulting.com> Subject: Re: [squeak-dev] Squeak and the iPhone References: <998FEB36-B9FC-427D-AA74-8A9F517432AB@smalltalkconsulting.com> <1f426d6e0806110542l4fa971bi50f429dbf9ba0809@mail.gmail.com> <FB804A64-E03C-4B68-B8F1-8FF135227F3B@gmail.com> <4D79AAD3-1CFC-431B-AB6B-7E230B0DC5A7@mac.com> <BEB4569D-C606-4FF4-9B1B-A95570E38B94@smalltalkconsulting.com> Message-Id: <CCD6C9FE-483B-4A64-86B9-8D2647E54139@gmail.com> Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Reply-To: Marcel Weiher <marcel.weiher@gmail.com>, The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> Mime-Version: 1.0 (Apple Message framework v924) Date: Wed, 18 Jun 2008 12:00:05 -0700 Cc: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> X-Mailer: Apple Mail (2.924) X-Brightmail-Tracker: AAAAAA== The source code has been made available again at http://www.metaobject.com/downloads/Squeak/ ... In the meantime, you have my express permission to use it under an MIT license. */ #import "sqSqueakOSXNSView.h" #import "BitMapConversionLogicFromX11.h" @interface sqSqueakOSXNSView(BitmapConversion) -(CGImageRef)extractPixels_1_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory; -(CGImageRef)extractPixels_2_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory; -(CGImageRef)extractPixels_4_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory; -(CGImageRef)extractPixels_8_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory; -(CGImageRef)extractPixels_16_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom tempMemory: (void **) tempMemory; -(CGImageRef)computeBitmapFromBitsIndex:(void*)srcBits width:(int)width height:(int)height depth:(int)depth left:(int)left right:(int)right top:(int)top bottom:(int)bottom tempMemory: (void**) tempMemory; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqViewBitmapConversion.m ================================================ /* SqViewBitmapConversion.m created by marcel on Fri 04-Dec-1998 */ // CocoaSqueak // // John Notes: Waste not want not. /* From: Marcel Weiher <marcel.weiher@gmail.com> To: johnmci@smalltalkconsulting.com In-Reply-To: <BEB4569D-C606-4FF4-9B1B-A95570E38B94@smalltalkconsulting.com> Subject: Re: [squeak-dev] Squeak and the iPhone References: <998FEB36-B9FC-427D-AA74-8A9F517432AB@smalltalkconsulting.com> <1f426d6e0806110542l4fa971bi50f429dbf9ba0809@mail.gmail.com> <FB804A64-E03C-4B68-B8F1-8FF135227F3B@gmail.com> <4D79AAD3-1CFC-431B-AB6B-7E230B0DC5A7@mac.com> <BEB4569D-C606-4FF4-9B1B-A95570E38B94@smalltalkconsulting.com> Message-Id: <CCD6C9FE-483B-4A64-86B9-8D2647E54139@gmail.com> Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Reply-To: Marcel Weiher <marcel.weiher@gmail.com>, The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> Mime-Version: 1.0 (Apple Message framework v924) Date: Wed, 18 Jun 2008 12:00:05 -0700 Cc: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> X-Mailer: Apple Mail (2.924) X-Brightmail-Tracker: AAAAAA== The source code has been made available again at http://www.metaobject.com/downloads/Squeak/ ... In the meantime, you have my express permission to use it under an MIT license. */ #import "SqViewBitmapConversion.h" @implementation sqSqueakOSXNSView(BitmapConversion) #define debug(a) #define CHECKANDRETURN(expr) \ { NSBitmapImageRep* bitmap=expr; if(bitmap!=NULL){ CGImageRef ref = [bitmap CGImage]; [bitmap release]; return(ref);}\ NSLog(@"initData:%08x\npixelsWide:%d\npixelsHigh:%d\nbitsPerSample:%d\nsamplesPerPixel:%d\nhasAlpha:%d\nisPlanar:%d\ncolorSpaceName:%@\nbytesPerRow:%d\nbitsPerPixel:%d\n",\ (int)dBits,right-left,bottom-top,bitsPerSample,\ samplesPerPixel,NO,NO,colorSpace,bytesPerRow,bitsPerPixel);\ return(0);\ } -(CGImageRef)extractPixels_1_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory { int bitsPerSample=8; int samplesPerPixel=3; int bitsPerPixel=32; int bytesPerRow=bytesPerLine(srcPixelWidth, 32); NSString* colorSpace=NSDeviceRGBColorSpace; size_t totalSize=bytesPerRow * ((bottom-top)+1); int* dBits=(int*)malloc(totalSize); *tempMemory = dBits; copyImage1To32(srcBits, dBits, srcPixelWidth, height, left, top, right, bottom,colorMap); CHECKANDRETURN([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&dBits pixelsWide:right-left pixelsHigh:bottom-top bitsPerSample:bitsPerSample samplesPerPixel:samplesPerPixel hasAlpha:NO isPlanar:NO colorSpaceName:colorSpace bytesPerRow:bytesPerRow bitsPerPixel:bitsPerPixel]); }//extractPixels_1_to_32; -(CGImageRef)extractPixels_2_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory { int bitsPerSample=8; int samplesPerPixel=3; int bitsPerPixel=32; int bytesPerRow=bytesPerLine(srcPixelWidth, 32); NSString* colorSpace=NSDeviceRGBColorSpace; size_t totalSize=bytesPerRow * ((bottom-top)+1); int* dBits=(int*)malloc(totalSize); *tempMemory = dBits; copyImage2To32(srcBits, dBits, srcPixelWidth, height, left, top, right, bottom,colorMap); CHECKANDRETURN([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&dBits pixelsWide:right-left pixelsHigh:bottom-top bitsPerSample:bitsPerSample samplesPerPixel:samplesPerPixel hasAlpha:NO isPlanar:NO colorSpaceName:colorSpace bytesPerRow:bytesPerRow bitsPerPixel:bitsPerPixel]); }//extractPixels_2_to_32; -(CGImageRef)extractPixels_4_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory { int bitsPerSample=8; int samplesPerPixel=3; int bitsPerPixel=32; int bytesPerRow=bytesPerLine(srcPixelWidth, 32); NSString* colorSpace=NSDeviceRGBColorSpace; size_t totalSize=bytesPerRow * ((bottom-top)+1); int* dBits=(int*)malloc(totalSize); *tempMemory = dBits; copyImage4To32(srcBits, dBits, srcPixelWidth, height, left, top, right, bottom,colorMap); CHECKANDRETURN([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&dBits pixelsWide:right-left pixelsHigh:bottom-top bitsPerSample:bitsPerSample samplesPerPixel:samplesPerPixel hasAlpha:NO isPlanar:NO colorSpaceName:colorSpace bytesPerRow:bytesPerRow bitsPerPixel:bitsPerPixel]); }//extractPixels_4_to_32; -(CGImageRef)extractPixels_8_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom colorMap: (unsigned int *) colorMap tempMemory: (void **) tempMemory { int bitsPerSample=8; int samplesPerPixel=3; int bitsPerPixel=32; int bytesPerRow=bytesPerLine(srcPixelWidth, 32); NSString* colorSpace=NSDeviceRGBColorSpace; size_t totalSize=bytesPerRow * ((bottom-top)+1); int* dBits=(int*)malloc(totalSize); *tempMemory = dBits; copyImage8To32(srcBits, dBits, srcPixelWidth, height, left, top, right, bottom,colorMap); CHECKANDRETURN([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&dBits pixelsWide:right-left pixelsHigh:bottom-top bitsPerSample:bitsPerSample samplesPerPixel:samplesPerPixel hasAlpha:NO isPlanar:NO colorSpaceName:colorSpace bytesPerRow:bytesPerRow bitsPerPixel:bitsPerPixel]); }//extractPixels_8_to_32; -(CGImageRef)extractPixels_16_to_32:(void*)srcBits srcPixelWidth:(int)srcPixelWidth height: (int) height left:(int)left right:(int)right top:(int)top bottom:(int)bottom tempMemory: (void **) tempMemory { int bitsPerSample=8; int samplesPerPixel=3; int bitsPerPixel=32; int bytesPerRow=bytesPerLine(srcPixelWidth, 32); NSString* colorSpace=NSDeviceRGBColorSpace; size_t totalSize=bytesPerRow * ((bottom-top)+1); int* dBits=(int*)malloc(totalSize); *tempMemory = dBits; copyImage16To32(srcBits, dBits, srcPixelWidth, height, left, top, right, bottom); CHECKANDRETURN([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&dBits pixelsWide:right-left pixelsHigh:bottom-top bitsPerSample:bitsPerSample samplesPerPixel:samplesPerPixel hasAlpha:NO isPlanar:NO colorSpaceName:colorSpace bytesPerRow:bytesPerRow bitsPerPixel:bitsPerPixel]); }//extractPixels_16_to_32; -(CGImageRef)computeBitmapFromBitsIndex:(void*)srcBits width:(int)width height:(int)height depth:(int)depth left:(int)left right:(int)right top:(int)top bottom:(int)bottom tempMemory: (void**) tempMemory { /* It seems that NSImage will replace its NSBitmapImageRep with a NXCachedImageRep of the whole bitmap upon receiving a composite:fromRect:toPoint: message. Therefore: 1- it is useless to keep our own "cached" image; 2- we may as well copy to the right format & depth the affected rectangle in a temporary bitmap, and draw it directly. */ debug(int dummy=fprintf(stderr,"%s\n",sel_getName(_cmd));\ int fummy=fflush(stderr);) switch(depth){ case 1: return([self extractPixels_1_to_32:srcBits srcPixelWidth:width height: height left:left right:right top:top bottom:bottom colorMap: colorMap32 tempMemory: tempMemory]); break; case 2: return([self extractPixels_2_to_32:srcBits srcPixelWidth:width height: height left:left right:right top:top bottom:bottom colorMap: colorMap32 tempMemory: tempMemory]); break; case 4: return([self extractPixels_4_to_32:srcBits srcPixelWidth:width height: height left:left right:right top:top bottom:bottom colorMap: colorMap32 tempMemory: tempMemory]); break; case 8: return([self extractPixels_8_to_32:srcBits srcPixelWidth:width height: height left:left right:right top:top bottom:bottom colorMap: colorMap32 tempMemory: tempMemory]); break; case 16: return([self extractPixels_16_to_32:srcBits srcPixelWidth:width height: height left:left right:right top:top bottom:bottom tempMemory: tempMemory]); break; default: switch(NSRunAlertPanel(@"Error", @"Cocoa user interface for Squeak doesn't support image depth of %d.\n", @"Continue",@"Quit",NULL,depth)){ case NSAlertDefaultReturn: return(0); case NSAlertAlternateReturn: ioExit(); return(0); case NSAlertErrorReturn: default: NSLog(@"Cocoa user interface for Squeak doesn't support image depth of %d.\n",depth); ioExit(); return(0); } } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqViewClut.h ================================================ /* SqViewClut.h created by marcel on Sat 23-Dec-2000 */ #import "sqSqueakOSXNSView.h" @class sqSqueakOSXNSView; @interface sqSqueakOSXNSView(Clut) -(void)initializeSqueakColorMap; -(void)setColorEntry:(int)i red:(int)r green:(int)g blue:(int)b; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqViewClut.m ================================================ /* SqViewClut.m created by marcel on Sat 23-Dec-2000 */ #import "sqSqueakOSXNSView.h" @implementation sqSqueakOSXNSView(Clut) -(void)initializeSqueakColorMap { colorMap32=(unsigned int*)malloc(sizeof(unsigned int)*256); #define SetColorEntry(i,r,g,b) [self setColorEntry:i red:r green:g blue:b] /* 1-bit colors (monochrome) */ SetColorEntry(0, 65535, 65535, 65535); /* white or transparent */ SetColorEntry(1, 0, 0, 0); /* black */ /* additional colors for 2-bit color */ SetColorEntry(2, 65535, 65535, 65535); /* opaque white */ SetColorEntry(3, 32768, 32768, 32768); /* 1/2 gray */ /* additional colors for 4-bit color */ SetColorEntry( 4, 65535, 0, 0); /* red */ SetColorEntry( 5, 0, 65535, 0); /* green */ SetColorEntry( 6, 0, 0, 65535); /* blue */ SetColorEntry( 7, 0, 65535, 65535); /* cyan */ SetColorEntry( 8, 65535, 65535, 0); /* yellow */ SetColorEntry( 9, 65535, 0, 65535); /* magenta */ SetColorEntry(10, 8192, 8192, 8192); /* 1/8 gray */ SetColorEntry(11, 16384, 16384, 16384); /* 2/8 gray */ SetColorEntry(12, 24576, 24576, 24576); /* 3/8 gray */ SetColorEntry(13, 40959, 40959, 40959); /* 5/8 gray */ SetColorEntry(14, 49151, 49151, 49151); /* 6/8 gray */ SetColorEntry(15, 57343, 57343, 57343); /* 7/8 gray */ /* additional colors for 8-bit color */ /* 24 more shades of gray (does not repeat 1/8th increments) */ SetColorEntry(16, 2048, 2048, 2048); /* 1/32 gray */ SetColorEntry(17, 4096, 4096, 4096); /* 2/32 gray */ SetColorEntry(18, 6144, 6144, 6144); /* 3/32 gray */ SetColorEntry(19, 10240, 10240, 10240); /* 5/32 gray */ SetColorEntry(20, 12288, 12288, 12288); /* 6/32 gray */ SetColorEntry(21, 14336, 14336, 14336); /* 7/32 gray */ SetColorEntry(22, 18432, 18432, 18432); /* 9/32 gray */ SetColorEntry(23, 20480, 20480, 20480); /* 10/32 gray */ SetColorEntry(24, 22528, 22528, 22528); /* 11/32 gray */ SetColorEntry(25, 26624, 26624, 26624); /* 13/32 gray */ SetColorEntry(26, 28672, 28672, 28672); /* 14/32 gray */ SetColorEntry(27, 30720, 30720, 30720); /* 15/32 gray */ SetColorEntry(28, 34815, 34815, 34815); /* 17/32 gray */ SetColorEntry(29, 36863, 36863, 36863); /* 18/32 gray */ SetColorEntry(30, 38911, 38911, 38911); /* 19/32 gray */ SetColorEntry(31, 43007, 43007, 43007); /* 21/32 gray */ SetColorEntry(32, 45055, 45055, 45055); /* 22/32 gray */ SetColorEntry(33, 47103, 47103, 47103); /* 23/32 gray */ SetColorEntry(34, 51199, 51199, 51199); /* 25/32 gray */ SetColorEntry(35, 53247, 53247, 53247); /* 26/32 gray */ SetColorEntry(36, 55295, 55295, 55295); /* 27/32 gray */ SetColorEntry(37, 59391, 59391, 59391); /* 29/32 gray */ SetColorEntry(38, 61439, 61439, 61439); /* 30/32 gray */ SetColorEntry(39, 63487, 63487, 63487); /* 31/32 gray */ /* The remainder of color table defines a color cube with six steps for each primary color. Note that the corners of this cube repeat previous colors, but simplifies the mapping between RGB colors and color map indices. This color cube spans indices 40 through 255. */ { int r,g,b; for(r=0;r<6;r++){ for(g=0;g<6;g++){ for(b=0;b<6;b++){ int i=40+((36*r)+(6*b)+g); if(i>255){ fprintf(stderr,"index out of range " "in color table compuation\n"); } SetColorEntry(i,(r*65535)/5,(g*65535)/5,(b*65535)/5); } } } } }//initializeSqueakColorMap; -(void)setColorEntry:(int)i red:(int)r green:(int)g blue:(int)b { colorMap32[i]=NSSwapHostIntToBig((((r)&0xff00)<<16)|(((g)&0xff00)<<8)|((b)&0xff00)|0xff); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqueakOSXAppDelegate.h ================================================ // // SqueakOSXAppDelegate.h // SqueakOSXApp // // Created by John M McIntosh on 09-11-10. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> #import "sqSqueakAppDelegate.h" #import "sqSqueakOSXApplication.h" #import "sqSqueakOSXNSView.h" @protocol NSApplicationDelegate <NSObject> @end @class sqSqueakMainApplication; @interface SqueakOSXAppDelegate : sqSqueakAppDelegate <NSApplicationDelegate> { NSWindow *window; sqSqueakOSXNSView *mainView; BOOL checkForFileNameOnFirstParm; NSString *possibleImageNameAtLaunchTime; } @property (nonatomic,assign) IBOutlet NSWindow *window; @property (nonatomic,assign) IBOutlet sqSqueakOSXNSView *mainView; @property (nonatomic,retain) NSString *possibleImageNameAtLaunchTime; @property (nonatomic,assign) BOOL checkForFileNameOnFirstParm; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqueakOSXAppDelegate.m ================================================ // // SqueakOSXAppDelegate.m // SqueakOSXApp // // Created by John M McIntosh on 09-11-10. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "SqueakOSXAppDelegate.h" #import "sqSqueakOSXApplication.h" #import "sqSqueakOSXScreenAndWindow.h" #import "sqMacHostWindow.h" #import "sqSqueakOSXInfoPlistInterface.h" SqueakOSXAppDelegate *gDelegateApp; @implementation SqueakOSXAppDelegate @synthesize window,mainView,possibleImageNameAtLaunchTime,checkForFileNameOnFirstParm; - (sqSqueakMainApplication *) makeApplicationInstance { return [sqSqueakOSXApplication new]; } - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { self.checkForFileNameOnFirstParm = YES; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSAutoreleasePool * pool = [NSAutoreleasePool new]; gDelegateApp = self; squeakApplication = [self makeApplicationInstance]; sqSqueakOSXScreenAndWindow *windowHandler = [sqSqueakOSXScreenAndWindow new]; windowHandler.mainViewOnWindow = self.mainView; self.mainView.windowLogic = windowHandler; windowHandler.windowIndex = 1; [windowHandler.mainViewOnWindow initializeVariables]; self.window.delegate = windowHandler; self.window.contentResizeIncrements = NSMakeSize(8.0f,8.0f); [self.squeakApplication setupEventQueue]; [self singleThreadStart]; // [self workerThreadStart]; [pool drain]; } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { return NO; } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { [self.window performClose: self.window]; return NSTerminateCancel; } - (id) createPossibleWindow { sqInt width,height; extern sqInt getSavedWindowSize(void); //This is VM Callback width = ((unsigned) getSavedWindowSize()) >> 16; height = getSavedWindowSize() & 0xFFFF; width = (sqInt) ((width*4)/32.0f+0.5)*8.0; //JMM OPEN/GL THOUGHTS FOR PERFORMANCE NSSize sizeOfWindowContent; sizeOfWindowContent.width = width; sizeOfWindowContent.height = height; [gDelegateApp.window setContentSize: sizeOfWindowContent]; NSRect resetFrame; resetFrame.origin.x = 0.0f; resetFrame.origin.y = 0.0f; resetFrame.size.width = width; resetFrame.size.height = height; [gDelegateApp.window setAcceptsMouseMovedEvents: YES]; [gDelegateApp.window useOptimizedDrawing: YES]; [gDelegateApp.window setTitle: [[self.squeakApplication.imageNameURL path] lastPathComponent]]; [gDelegateApp.window setRepresentedURL: self.squeakApplication.imageNameURL]; [gDelegateApp.window setInitialFirstResponder: gDelegateApp.mainView]; [gDelegateApp.window setShowsResizeIndicator: NO]; extern sqInt getFullScreenFlag(void); #if (SQ_VI_BYTES_PER_WORD == 4) NSPanel *panel; if (sizeof(void*) == 8) { panel= NSGetAlertPanel(@"About this Alpha Version of Cocoa Squeak 64/32 bits 5.7b3 (21)", @"Only use this VM for testing, it lacks mac menu integration.", @"Dismiss", nil, nil); } else { return self.window; } #else #if COGVM #error bad #endif NSPanel *panel; if (sizeof(long) == 8) { panel= NSGetAlertPanel(@"About this Alpha Version of Cocoa Squeak 64/64 bits 5.7b3 (21)", @"Only use this VM for testing, it lacks mac menu integration.", @"Dismiss", nil, nil); } else { panel= NSGetAlertPanel(@"About this Alpha Version of Cocoa Squeak 32/64 bits 5.7b3 (21)", @"Only use this VM for testing, it lacks mac menu integration.", @"Dismiss", nil, nil); } #endif NSRect frame= [panel frame]; frame.size.width *= 1.5f; [panel setFrame: frame display: NO]; [NSApp runModalForWindow: panel]; [panel close]; return self.window; } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)fileName { // NSLog(@"openFile state %i with file %@",checkForFileNameOnFirstParm,fileName); if (self.checkForFileNameOnFirstParm == YES) { self.checkForFileNameOnFirstParm = NO; self.possibleImageNameAtLaunchTime = fileName; return YES; } else { if ([(sqSqueakOSXApplication*)self.squeakApplication isImageFile: fileName] == YES) { NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; LSLaunchURLSpec launchSpec; launchSpec.appURL = (CFURLRef)url; launchSpec.passThruParams = NULL; launchSpec.itemURLs = (CFArrayRef)[NSArray arrayWithObject:[NSURL fileURLWithPath: fileName]]; launchSpec.launchFlags = kLSLaunchDefaults | kLSLaunchNewInstance; launchSpec.asyncRefCon = NULL; OSErr err = LSOpenFromURLSpec(&launchSpec, NULL); // NSLog(@"error %i",err); #pragma unused(err) } } return NO; } - (NSTimeInterval) squeakUIFlushPrimaryDeferNMilliseconds { return ((sqSqueakOSXInfoPlistInterface*) self.squeakApplication.infoPlistInterfaceLogic).SqueakUIFlushPrimaryDeferNMilliseconds; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqueakOSXApplication.h ================================================ // // SqueakOSXApplication.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-22. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> @interface SqueakOSXApplication : NSApplication { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/SqueakOSXApplication.m ================================================ // // SqueakOSXApplication.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-22. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "SqueakOSXApplication.h" #import "sqSqueakOSXScreenAndWindow.h" #import "sqSqueakOSXNSView.h" @implementation SqueakOSXApplication -(void)sendEvent:(NSEvent*)anEvent { if ( [anEvent type] == NSKeyDown && ([anEvent modifierFlags] & NSCommandKeyMask) != 0 ) { NSWindow *who = [anEvent window]; sqSqueakOSXScreenAndWindow *squeakScreenWindow = (sqSqueakOSXScreenAndWindow *) who.delegate; sqSqueakOSXNSView *view; if (squeakScreenWindow) view = squeakScreenWindow.mainViewOnWindow; else view = [who contentView]; [view fakeKeyDownUp: anEvent]; } else { [super sendEvent:anEvent]; } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/dtraceOperationsPerSecond.d ================================================ #pragma D option quiet dtrace:::BEGIN { printf("Sampling... Hit Ctrl-C to end.\n"); start = timestamp; } objc$target::-drawRect?:entry { @operationspercpu[cpu] = count(); @totaloperationexecutions[probemod] = count(); @multicoredistributionofalloperations = lquantize((cpu + 1), 1, 16, 1); @multicoredistributionofoperations[probemod] = lquantize((cpu + 1), 1, 16, 1); starttimeformethod[probemod] = timestamp; cpustarttimeformethod[probemod] = vtimestamp; methodhasenteredatleastonce[probemod] = 1; } objc$target::-drawRect?:return /methodhasenteredatleastonce[probemod] == 1/ { @overallexecutions[probemod] = count(); @averageexecutiontime[probemod] = avg((timestamp - starttimeformethod[probemod]) / 1000); @averagecpuexecutiontime[probemod] = avg((vtimestamp - cpustarttimeformethod[probemod]) / 1000); } tick-1s { printa("%30s %10@u operations / s\n", @totaloperationexecutions); clear(@totaloperationexecutions); } dtrace:::END { seconds = (timestamp - start) / 1000000000; normalize(@averageexecutiontime, 1000); normalize(@averagecpuexecutiontime, 1000); printf("Ran for %u seconds\n", seconds); printf("%30s %20s %20s %20s\n", "Operation", "Executions","Average time (ms)", "CPU average time (ms)"); printa("%30s %20@u %20@u %20@u\n", @overallexecutions, @averageexecutiontime, @averagecpuexecutiontime); printf("\nCPU core distribution of all operations:\n"); printa(@multicoredistributionofalloperations); printf("CPU core distribution, by operation type:\n"); printa(@multicoredistributionofoperations); } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/dtracedrawrecttiming.d ================================================ #pragma D option quiet objc$target::-drawRect?:entry { start[probemod] = timestamp; } objc$target::-drawRect?:return { printf("%30s %10s Execution time: %u us\n", probemod, probefunc, (timestamp - start[probemod]) / 1000); } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/keyBoardStrokeDetails.h ================================================ // // keyBoardStrokeDetails.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-22. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> @interface keyBoardStrokeDetails : NSObject { unsigned short keyCode; NSUInteger modifierFlags; } @property (nonatomic,assign) unsigned short keyCode; @property (nonatomic,assign) NSUInteger modifierFlags; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/keyBoardStrokeDetails.m ================================================ // // keyBoardStrokeDetails.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-22. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "keyBoardStrokeDetails.h" @implementation keyBoardStrokeDetails @synthesize keyCode, modifierFlags; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/macintoshosxextra.c ================================================ /* * macintoshosxextra.c * SqueakPureObjc * * Created by John M McIntosh on 09-11-14. * Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ #include "macintoshosxextra.h" #include <sys/syslimits.h> sqInt ioFormPrint(sqInt bitsAddr, sqInt width, sqInt height, sqInt depth, double hScale, double vScale, sqInt landscapeFlag) { /* experimental: print a form with the given bitmap, width, height, and depth at the given horizontal and vertical scales in the given orientation However John Mcintosh has introduced a printjob class and plugin to replace this primitive */ #pragma unused( bitsAddr, width, height, depth, hScale, vScale, landscapeFlag) return true; } sqInt ioGetButtonState() {return 0;} sqInt ioGetKeystroke() {return -1;} sqInt ioMousePoint() {return 0;} sqInt ioPeekKeystroke() {return 0;} sqInt ioSetDisplayMode( sqInt width, sqInt height, sqInt depth, sqInt fullscreenFlag) {return 0;} //int plugInTimeToReturn(void) { // return false; //} sqInt clearProfile(void){return 0;} sqInt dumpProfile(void){return 0;} sqInt startProfiling(void){return 0;} sqInt stopProfiling(void) {return 0;} int plugInNotifyUser(char *msg); int plugInNotifyUser(char *msg) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/macintoshosxextra.h ================================================ /* * macintoshosxextra.h * SqueakPureObjc * * Created by John M McIntosh on 09-11-14. * Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ #include "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/plugins/HostWindowPlugin/sqMacHostWindow.h ================================================ /* * sqMacHostWindow.h * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic Altered for IPhone */ /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "HostWindowPlugin.h" #ifdef BUILD_FOR_OSX #include <ApplicationServices/ApplicationServices.h> #else #include <CoreGraphics/CoreGraphics.h> #endif /* window handle type */ #define wHandleType void * #define wIndexType sqInt typedef struct windowDescriptorBlock { struct windowDescriptorBlock * next; wHandleType handle; wIndexType windowIndex; /* extra fields to support your platform needs */ void * context; CGRect updateArea; sqInt width; sqInt height; } windowDescriptorBlock; windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle); sqInt windowIndexFromBlock( windowDescriptorBlock * thisWindow); sqInt windowIndexFromHandle(wHandleType windowHandle); wHandleType windowHandleFromIndex(wIndexType windowIndex); windowDescriptorBlock *AddWindowBlock(void); windowDescriptorBlock *windowBlockFromIndex(sqInt windowIndex); sqInt getCurrentIndexInUse(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/plugins/HostWindowPlugin/sqMacHostWindow.m ================================================ /* * sqMacHostWindow.m * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * Copyright Corporate Smalltalk Consulting Ltd 2008. All rights reserved. * July 15th 2005 add logic to flush QD buffers for os-x 10.4 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic May 15th, 2008 IPhone Sept 6th, 2010 Cocoa */ /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include <Cocoa/Cocoa.h> #include "sqVirtualMachine.h" #include "sqMacHostWindow.h" #include <stdlib.h> extern struct VirtualMachine *interpreterProxy; sqInt RemoveWindowBlock(windowDescriptorBlock * thisWindow); sqInt createWindowWidthheightoriginXyattrlength(sqInt w,sqInt h,sqInt x,sqInt y, char * list, sqInt listLength) { return -1; } int closeWindow(int windowIndex) { NSWindow *windowHandle; windowHandle = windowHandleFromIndex(windowIndex); if(windowHandle == NULL) return 0; windowBlockFromIndex(windowIndex)->context = NULL; RemoveWindowBlock(windowBlockFromIndex(windowIndex)); [windowHandle close]; return 1; } sqInt ioPositionOfWindow(wIndexType windowIndex) { if (windowHandleFromIndex(windowIndex) == NULL) return -1; return (0 << 16) | (0 & 0xFFFF); /* left is high 16 bits; top is low 16 bits */ } sqInt ioPositionOfWindowSetxy(wIndexType windowIndex, sqInt x, sqInt y) { return -1; } sqInt ioSizeOfWindow(wIndexType windowIndex) { sqInt w=0, h=0; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } int ioPositionOfNativeDisplay(unsigned long windowHandle) { sqInt w=0, h=0; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } sqInt ioSizeOfWindowSetxy(wIndexType windowIndex, sqInt x, sqInt y) { return (0); /* w is high 16 bits; h is low 16 bits */ } sqInt ioSetTitleOfWindow(sqInt windowIndex, char * newTitle, sqInt sizeOfTitle) { return 1; } sqInt ioCloseAllWindows(void) { return 1; } /* addendum to sqPlatformSpecific.h */ /* multiple host windows stuff */ static windowDescriptorBlock *windowListRoot = NULL; /* end addendum to sqPlatformSpecific.h */ /* simple linked list management code */ /* window list management */ windowDescriptorBlock *windowBlockFromIndex(sqInt windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry; entry = entry->next; } return NULL; } windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry; entry = entry->next; } return NULL; } wHandleType windowHandleFromIndex(sqInt windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry->handle; entry = entry->next; } return NULL; } sqInt windowIndexFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry->windowIndex; entry = entry->next; } return 0; } sqInt windowIndexFromBlock( windowDescriptorBlock * thisWindow) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry == thisWindow) return entry->windowIndex; entry = entry->next; } return 0; } static sqInt nextIndex = 1; windowDescriptorBlock *AddWindowBlock(void) { /* create a new entry in the linkedlist of windows. * If the calloc fails, return NULL which will then go back to the * prim and fail it cleanly. * Initialize the block to a sensible state */ windowDescriptorBlock *thisWindow; thisWindow = (windowDescriptorBlock*) calloc(1, sizeof(windowDescriptorBlock)); if ( thisWindow == NULL) { return NULL; } thisWindow->next = windowListRoot; thisWindow->windowIndex = nextIndex++; thisWindow->handle = NULL; windowListRoot = thisWindow; return windowListRoot; } /* * RemoveWindowBlock: * Remove the given entry from the list of windows. * free it, if found. */ sqInt RemoveWindowBlock(windowDescriptorBlock * thisWindow) { windowDescriptorBlock *prevEntry; /* Unlink the entry from the module chain */ if(thisWindow == windowListRoot) { windowListRoot = thisWindow->next; } else { prevEntry = windowListRoot; while(prevEntry->next != thisWindow) { prevEntry = prevEntry->next; if (prevEntry == NULL) { return 0; } } prevEntry->next = thisWindow->next; } free(thisWindow); return 1; } sqInt getCurrentIndexInUse(void) { return nextIndex-1; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.h ================================================ // // sqSqueakOSXSoundCoreAudio.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-27. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakSoundCoreAudio.h" @interface sqSqueakOSXSoundCoreAudio : sqSqueakSoundCoreAudio { } - (sqInt) soundInitOverride; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.m ================================================ // // sqSqueakOSXSoundCoreAudio.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-27. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */// #import "sqSqueakOSXSoundCoreAudio.h" @implementation sqSqueakOSXSoundCoreAudio - (sqInt) soundInit { return 1; } - (sqInt) soundInitOverride { //NSLog(@"%i sound init",ioMSecs()); self.outputAudioQueue = nil; self.inputAudioQueue = nil; self.semaIndexForOutput = 0; self.semaIndexForInput = 0; self.outputFormat = calloc(1,sizeof(AudioStreamBasicDescription)); self.inputFormat = calloc(1,sizeof(AudioStreamBasicDescription)); self.outputBuffers = calloc((unsigned)kNumberOfBuffers,sizeof(AudioQueueBufferRef)); self.inputBuffers = calloc((unsigned) kNumberOfBuffers,sizeof(AudioQueueBufferRef)); soundOutQueue = [Queue new]; soundInQueue = [Queue new]; return 1; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqMacUnixExternalPrims.m ================================================ // Created by John M McIntosh on 09-11-27. // This file orginally comes from the sqUnixExternalPrims.c written by Ian Piumarta // With additional work for the 3.x and 4.x series of macintosh carbon vms // To preserve the behavior, bugs, etc I decided to copy the code versus a new re-write /* sqUnixExternalPrims.c -- Unix named primitives and loadable modules * * Copyright (C) 1996-2009 by Ian Piumarta * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2005-04-06 06:09:36 by piumarta on pauillac.hpl.hp.com * Altered by John M McIntosh johnmci@smalltalkconsulting.com Feb 24th, 2006 for os-x carbon support 3.8.11b2 load from resource location first, avoid plugins external directory because of intel migration effort issues. 3.8.17b1 April 25, 2007, JMM rework for 10.2.8 backwards support using Ian's dl* logic. 5.0.0b6 Nov 27, 2009, JMM rework for the 32/64bit 5.0 VM */ #import "sqSqueakOSXInfoPlistInterface.h" #import "SqueakOSXAppDelegate.h" #import "sq.h" extern SqueakOSXAppDelegate *gDelegateApp; # define dprintf(ARGS) if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug) fprintf ARGS #if defined(HAVE_LIBDL) /* non-starter without this! */ #include <dlfcn.h> #include <sys/param.h> #include <sys/stat.h> /* get a value for RTLD_NOW, with increasing levels of desperation... */ #if !defined(RTLD_NOW) # if defined(DL_NOW) # define RTLD_NOW DL_NOW # elif defined(RTLD_LAZY) # define RTLD_NOW RTLD_LAZY # elif defined(DL_LAZY) # define RTLD_NOW DL_LAZY # else # warning: defining RTLD_NOW as 1 # define RTLD_NOW 1 # endif #endif #if !defined(RTLD_GLOBAL) # define RTLD_GLOBAL 0 #endif #endif /*** local functions ***/ void *ioLoadModuleRaw(char *pluginName); /* Attempt to load the shared library named by the concatenation of prefix, * moduleName and suffix. Answer the new module entry, or 0 if the shared * library could not be loaded. */ static void *tryLoadingInternals(NSString *libNameString) { struct stat buf; int err; void *handle = NULL; const char* libName = [libNameString fileSystemRepresentation]; if ((!(err= stat(libName, &buf))) && S_ISDIR(buf.st_mode)) { dprintf((stderr, "ignoring directory: %s\n", libName)); } else { dprintf((stderr, "tryLoading %s\n", libName)); handle= dlopen(libName, RTLD_NOW | RTLD_GLOBAL); if (handle == NULL) { const char* why = dlerror(); if ((!err) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug)) fprintf(stderr, "ioLoadModule(%s):\n %s\n", libName, why); } else { return handle; } } return NULL; } static void *tryLoading(NSString *dirNameString, char *moduleName) { void *handle= NULL; NSString *libName; libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]]; libName = [libName stringByAppendingPathExtension: @"bundle/Contents/MacOS/"]; libName = [libName stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]]; handle = tryLoadingInternals(libName); if (handle) return handle; libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]]; handle = tryLoadingInternals(libName); if (handle) return handle; if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) return NULL; static char *prefixes[]= { "", "lib", 0 }; static char *suffixes[]= { "", "so", "dylib",0 }; char **prefix= NULL, **suffix= NULL; for (prefix= prefixes; *prefix; ++prefix) for (suffix= suffixes; *suffix; ++suffix) { libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: *prefix]]; libName = [libName stringByAppendingString: [NSString stringWithUTF8String: moduleName]]; libName = [libName stringByAppendingPathExtension: [NSString stringWithUTF8String: *suffix]]; handle = tryLoadingInternals(libName); if (handle) return handle; } return NULL; } /* Find and load the named module. Answer 0 if not found (do NOT fail * the primitive!). */ void *ioLoadModule(const char *pluginName) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; void* result = ioLoadModuleRaw(pluginName); [pool drain]; return result; } void *ioLoadModuleRaw(char *pluginName) { void *handle= null; if ((pluginName == null) || (pluginName[0] == 0x00)) { handle = dlopen(0, RTLD_NOW | RTLD_GLOBAL); if (handle == null) { char * why = dlerror(); dprintf((stderr, "ioLoadModule(<intrinsic>): %s\n", why)); } else { dprintf((stderr, "loaded: <intrinsic>\n")); return handle; } } /* first, look in the "<Squeak VM directory>Plugins" directory for the library */ NSString *pluginDirPath = [[gDelegateApp.squeakApplication.vmPathStringURL path] stringByAppendingPathComponent: @"Plugins/"]; NSString *vmDirPath = [[NSBundle mainBundle] resourcePath]; if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) { if ( (handle= tryLoading( vmDirPath, pluginName)) || (handle= tryLoading( pluginDirPath, pluginName))) return handle; } else { if (( handle= tryLoading( pluginDirPath, pluginName)) || (handle= tryLoading( @"./", pluginName)) || (handle= tryLoading( vmDirPath, pluginName)) || (handle= tryLoading( @"", pluginName)) ) return handle; } // the following is needed so that, for example, the FFI can pick up // things like <cdecl: 'xyz' module: 'CoreServices'> { static char *frameworks[]= { "", "/CoreServices.framework/Frameworks", "/ApplicationServices.framework/Frameworks", "/Carbon.framework/Frameworks", 0 }; static NSString *systemFolder = NULL; char **framework= NULL; char workingData[PATH_MAX+1]; size_t pluginNameLength; NSString *path,*path2; if (!systemFolder) { struct FSRef frameworksFolderRef; OSErr err = FSFindFolder(kSystemDomain, kFrameworksFolderType, false, &frameworksFolderRef); #pragma unused(err) NSURL *myURLRef = (NSURL *) CFURLCreateFromFSRef(kCFAllocatorDefault, &frameworksFolderRef); systemFolder = [[myURLRef path] retain]; CFRelease(myURLRef); } pluginNameLength = strlen(pluginName); if (pluginNameLength > 10) { strncpy(workingData,pluginName+pluginNameLength-10,10); workingData[10] = 0x00; if (strcmp(workingData,".framework") == 0) { strncpy(workingData,pluginName,pluginNameLength-10); workingData[pluginNameLength-10] = 0x00; path = [vmDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]]; if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) { path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]]; if ((handle = tryLoadingInternals(path2))) return handle; } else { if ((handle= tryLoading(path, workingData))) return handle; } path = [pluginDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]]; if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) { path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]]; if ((handle = tryLoadingInternals(path2))) return handle; } else { if ((handle= tryLoading(path, workingData))) return handle; } path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]]; if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) { path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]]; if ((handle = tryLoadingInternals(path2))) return handle; } else { if ((handle= tryLoading(path, workingData))) return handle; } } } if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) return NULL; for (framework= frameworks; *framework; ++framework) { path = [[systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]] stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]]; if ((handle= tryLoading(path, pluginName))) return handle; path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]]; path = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]]; path = [path stringByAppendingPathExtension: @"framework"]; if ((handle= tryLoading(path, pluginName))) return handle; } } return NULL; } /* Find a function in a loaded module. Answer 0 if not found (do NOT * fail the primitive!). */ void *ioFindExternalFunctionIn(const char *lookupName, void *moduleHandle) { char buf[NAME_MAX+1]; snprintf(buf, sizeof(buf), "%s", lookupName); void *fn = dlsym(moduleHandle, buf); dprintf((stderr, "ioFindExternalFunctionIn(%s, %ld)\n",lookupName, (long) moduleHandle)); if ((fn == NULL) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug) && strcmp(lookupName, "initialiseModule") && strcmp(lookupName, "shutdownModule") && strcmp(lookupName, "setInterpreter") && strcmp(lookupName, "getModuleName")) { char *why = dlerror(); fprintf(stderr, "ioFindExternalFunctionIn(%s, %p):\n %s\n",lookupName, moduleHandle, why); } return fn; } /* Free the module with the associated handle. Answer 0 on error (do * NOT fail the primitive!). */ sqInt ioFreeModule(void *moduleHandle) { int results = dlclose(moduleHandle); if (results) { char* why = dlerror(); dprintf((stderr, "ioFreeModule(%ld): %s\n", (long) moduleHandle, why)); return 0; } return 1; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqMacV2Browser.h ================================================ // // sqMacV2Browser.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/17/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // BOOL browserActiveAndDrawingContextOk(void); BOOL browserActiveAndDrawingContextOkAndInFullScreenMode(void); BOOL browserActiveAndDrawingContextOkAndNOTInFullScreenMode(void); BOOL browserWasHeadlessButMadeFullScreen(void); sqInt browserGetWindowSize(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqMacV2Browser.m ================================================ // // sqMacV2Browser.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/17/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // #import "sq.h" #import "sqMacV2Browser.h" BOOL gSqueakBrowserSubProcess=false,gSqueakBrowserWasHeadlessButMadeFullScreen=false; void *SharedBrowserBitMapContextRef=NULL; extern sqInt getFullScreenFlag(void); //This is VM callback BOOL b(void) { return gSqueakBrowserWasHeadlessButMadeFullScreen; } BOOL browserActiveAndDrawingContextOk(void) { return gSqueakBrowserSubProcess && SharedBrowserBitMapContextRef; } BOOL browserActiveAndDrawingContextOkAndInFullScreenMode(void) { return browserActiveAndDrawingContextOk() && browserWasHeadlessButMadeFullScreen() && getFullScreenFlag(); } BOOL browserActiveAndDrawingContextOkAndNOTInFullScreenMode(void) { return browserActiveAndDrawingContextOk() && !getFullScreenFlag(); } sqInt browserGetWindowSize(void) { return 0; } BOOL browserWasHeadlessButMadeFullScreen() { return gSqueakBrowserWasHeadlessButMadeFullScreen; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqMacV2Window.h ================================================ /* * sqMacV2Window.h * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/16/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // void * getSTWindow(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqMacV2Window.m ================================================ /* * sqMacV2Window.m * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/16/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // #import "sq.h" #import "sqMacV2Window.h" #import "sqMacHostWindow.h" #import "SqueakOSXAppDelegate.h" #import "sqMacV2Browser.h" extern BOOL gSqueakHeadless; extern SqueakOSXAppDelegate *gSqueakApplication; void * getSTWindow(void) { if (gSqueakHeadless && !browserActiveAndDrawingContextOk()) return NULL; return windowHandleFromIndex(1); } void makeMainWindow(void) { sqInt width,height; windowDescriptorBlock *windowBlock; extern sqInt getSavedWindowSize(void); //This is VM Callback extern sqInt setSavedWindowSize(sqInt value); //This is VM Callback /* get old window size */ width = (unsigned) getSavedWindowSize() >> 16; height = getSavedWindowSize() & 0xFFFF; windowBlock = AddWindowBlock(); windowBlock-> handle = gSqueakApplication.window; windowBlock->context = nil; windowBlock->updateArea = CGRectZero; width = (usqInt) ioScreenSize() >> 16; height = ioScreenSize() & 0xFFFF; setSavedWindowSize( (width << 16) |(height & 0xFFFF)); windowBlock->width = width; windowBlock->height = height; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakMainApplication+screen.h ================================================ // // sqSqueakMainApplication+screen.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/22/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // #import "sqSqueakMainApplication.h" #import "sqMacHostWindow.h" @interface sqSqueakMainApplication (screen) - (sqInt) ioScreenSize; - (void) unionScreenArea: (windowDescriptorBlock *) windowBlock clip: (CGRect *) clip; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakMainApplication+screen.m ================================================ // // sqSqueakMainApplication+screen.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/22/08. // Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // #import "SqueakNoOGLIPhoneAppDelegate.h" #import "sqSqueakMainApplication+screen.h" #import "sqMacV2Browser.h" #import "sqMacV2Window.h" #import "HostWindowPlugin.h" extern SqueakNoOGLIPhoneAppDelegate *gSqueakApplication; extern BOOL gSqueakHeadless; @implementation sqSqueakMainApplication (screen) - (sqInt) ioScreenSize { sqInt w, h; sqInt browserGetWindowSize(void); void makeMainWindow(void); sqInt getCurrentIndexInUse(void); extern BOOL gSqueakExplicitWindowOpenNeeded; if (gSqueakHeadless && !browserActiveAndDrawingContextOk()) return ((16 << 16) | 16); if (browserActiveAndDrawingContextOkAndNOTInFullScreenMode()) return browserGetWindowSize(); if (getSTWindow() == NULL && !gSqueakExplicitWindowOpenNeeded) { makeMainWindow(); } @synchronized(gSqueakApplication.mainView) { CGRect screenSize = [gSqueakApplication.mainView bounds]; w = (sqInt) screenSize.size.width; h = (sqInt) screenSize.size.height; } return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } - (void) unionScreenArea: (windowDescriptorBlock *) windowBlock clip: (CGRect *) clip { // printf("\n top %f left %f height %f width %f",clip->origin.y,clip->origin.x,clip->size.height,clip->size.width); if (CGRectIsEmpty(windowBlock->updateArea)) windowBlock->updateArea = *clip; else windowBlock->updateArea = CGRectUnion(windowBlock->updateArea, *clip); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+attributes.h ================================================ // // sqSqueakOSXApplication+attributes.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-11. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" @interface sqSqueakOSXApplication (attributes) @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+attributes.m ================================================ // // sqSqueakOSXApplication+attributes.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-11. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication+attributes.h" #import "sqSqueakMainApplication+attributes.h" #import "sqSqueakMainApplication+vmAndImagePath.h" extern struct VirtualMachine* interpreterProxy; @implementation sqSqueakOSXApplication (attributes) - (char *) getAttribute:(sqInt)indexNumber { //indexNumber is a postive/negative number #warning to test switch (indexNumber) { case 1001: /* OS type: "unix", "win32", "mac", ... */ return "Mac OS"; case 1002: { /* OS name: "solaris2.5" on unix, "win95" on win32, ... */ SInt32 myattr; static char data[32]; Gestalt(gestaltSystemVersion, &myattr); sprintf(data,"%X",(unsigned int) myattr); return data; } case 1003: { /* processor architecture: "68k", "x86", "PowerPC", ... */ SInt32 myattr; Gestalt(gestaltSysArchitecture, &myattr); if (myattr == gestalt68k) return "68K"; if (myattr == gestaltPowerPC) return "powerpc"; if (myattr == gestaltIntel) return "intel"; return "unknown"; } case 1005: { return "Aqua"; } case 1006: {/* vm build string also info.plist */ #if (SQ_VI_BYTES_PER_WORD == 4) #if STACKVM return "Mac Cocoa Cog 5.8b12 21-Sep-10 >1B0534FA-246C-47C5-AB29-7A76C81CCDCB<"; // return "Mac Cocoa Cog 5.8b11 12-Sep-10 >9BFC792A-F173-4C65-AD2A-FFFB1D52DAC2<"; // return "Mac Cocoa Cog 5.8b10 07-Sep-10 >8AD3A516-DBAC-4CD4-BC89-8F21317DF7E1<"; // return "Mac Cocoa Cog 5.8b9 06-Sep-10 >01641B99-1842-4422-A99D-43153BEDEFFA<"; // return "Mac Cocoa Cog 5.8b8 04-Sep-10 >8A66B7E0-B578-4E5F-97B4-6195547A35F5<"; // return "Mac Cocoa Cog 5.8b7 02-Sep-10 >4EBF00E3-453E-4010-9AC8-6B64C292984B<"; // return "Mac Cocoa Cog 5.8b6 31-Aug-10 >DFB49E57-40FB-44B9-97D3-B7CA51608429<"; // return "Mac Cocoa Cog 5.8b5 30-Aug-10 >0A92B82A-9AC1-4B0E-9DEE-440C3FFAE568<"; // return "Mac Cocoa Cog 5.8b4 27-Aug-10 >5954D562-FB39-4195-9D19-EBB49FAECCF7<"; // return "Mac Cocoa Cog 5.8b3 21-Aug-10 >5954D562-FB39-4195-9D19-EBB49FAECCF7<"; // return "Mac Cocoa Cog 5.8b2 08-Jul-10 >7BCAB029-A835-4D12-946D-4AB7083D2955<"; // return "Mac Cocoa Cog 5.8b1 07-Jul-10 >529F6B5A-DC81-4C1F-81B6-3D99741B954A<"; #else return "Mac Cocoa 5.7b3 27-Aug-10 >7BCAB029-A835-4D12-946D-4AB7083D2955<"; // return "Mac Cocoa 5.7b2 08-Jul-10 >7BCAB029-A835-4D12-946D-4AB7083D2955<"; // return "Mac Cocoa 5.7b1 15-Jun-10 >34286DE5-3BD3-40D8-9700-4C41C772B16B<"; #endif // return "Mac Cocoa 5.7b1 15-Jun-10 >34286DE5-3BD3-40D8-9700-4C41C772B16B<"; // return "Mac Cocoa 5.6b1 02-Mar-10 >9E99B1C2-0B6B-4944-8B6F-74030D14F3C6<"; // return "Mac Cocoa 5.5b1 16-Feb-10 >2EE2964B-462A-4F66-92AF-C810216EF798<"; // return "Mac Cocoa 5.4b2 24-Jan-10 >2EE2964B-462A-4F66-92AF-C810216EF798<"; // return "Mac Cocoa 5.4b1 20-Jan-10 >F0EB07E3-7805-4C09-8419-D8316F7ADC21<"; // return "Mac Cocoa 5.3b1 06-Jan-10 >0DADC752-8E86-48FC-8D6B-CC97482C6851<"; // return "Mac Cocoa 5.2b3 05-Jan-10 >1618879A-3D07-427F-A8CB-5B3DF73ED840<"; // return "Mac Cocoa 5.2b2 04-Jan-10 >94E27C49-8575-4604-A2C4-0A5C659CC734<"; // return "Mac Cocoa 5.2b1 02-Jan-10 >D94A0034-7415-4AA1-AA7C-B35BBCDBA0D4<"; // return "Mac Cocoa 5.1b1 25-Dec-09 >C0908D0B-4D97-47CA-9FAB-479AFC6BA978<"; // return "Mac Cocoa 5.0b9 02-Dec-09 >C8598ABA-DA73-4A71-836C-62C4369D5A0F<"; #else return "Mac Cocoa 5.7b2 64/64 bits 08-Jul-10 >7BCAB029-A835-4D12-946D-4AB7083D2955<"; // return "Mac Cocoa 5.7b1 64/64 bits 15-Jun-10 >34286DE5-3BD3-40D8-9700-4C41C772B16B<"; // return "Mac Cocoa 5.6b1 64/64 bits 02-Mar-10 >9E99B1C2-0B6B-4944-8B6F-74030D14F3C6<"; // return "Mac Cocoa 5.5b1 64/64 bits 16-Feb-10 >70984CDA-9482-4E7F-BCF0-08C635E0A7BF<"; // return "Mac Cocoa 5.4b2 64/64 bits 24-Jan-10 >70984CDA-9482-4E7F-BCF0-08C635E0A7BF<"; // return "Mac Cocoa 5.4b1 64/64 bits 20-Jan-10 >E27846BC-15A7-4BE8-B467-B645E9D37163<"; // return "Mac Cocoa 5.3b1 64/64 bits 06-Jan-10 >0DADC752-8E86-48FC-8D6B-CC97482C6851<"; // return "Mac Cocoa 5.2b3 64/64 bits 05-Jan-10 >1618879A-3D07-427F-A8CB-5B3DF73ED840<"; // return "Mac Cocoa 5.2b2 64/64 bits 04-Jan-10 >94E27C49-8575-4604-A2C4-0A5C659CC734<"; // return "Mac Cocoa 5.2b1 64/64 bits 02-Jan-10 >D94A0034-7415-4AA1-AA7C-B35BBCDBA0D4<"; // return "Mac Cocoa 5.1b1 64/64 bits 25-Dec-09 >C0908D0B-4D97-47CA-9FAB-479AFC6BA978<"; // return "Mac Cocoa 5.0b9 64/64 bits 02-Dec-09 >C8598ABA-DA73-4A71-836C-62C4369D5A0F<"; // return "Mac Cocoa 5.0b8 01-Dec-09 >2329A610-327B-403D-960E-EEF3C369D032<"; // return "Mac Cocoa 5.0b7 29-Nov-09 >1215B15B-9463-4D53-BA13-AA989DAB5C01<"; // return "Mac Cocoa 5.0b6 27-Nov-09 >CF087523-A432-4427-9AD3-4ACF26336A08<"; // return "Mac Cocoa 5.0b5 26-Nov-09 >9C6EF973-CECF-4E38-B5E0-BB9986A03D5D<"; // return "Mac Cocoa 5.0b4 26-Nov-09 >DA33132E-D7E6-48C4-8363-EB7408E3124B<"; // return "Mac Cocoa 5.0.0b1 11-Nov-09 >40BF8061-CC65-4E5E-9841-6BB5E809A688<"; #endif } case 1007: { /* vm build string also info.plist */ #if STACKVM extern char *__interpBuildInfo; return __interpBuildInfo; #endif break; } case 1008: { /* vm build string also info.plist */ # if COGVM extern char *__cogitBuildInfo; return __cogitBuildInfo; #endif break; } default: break; } return (char *) [super getAttribute: indexNumber]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+clipboard.h ================================================ // // sqSqueakOSXApplication+clipboard.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-23. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" @interface sqSqueakOSXApplication (clipboard) - (sqInt) clipboardSize; - (void) clipboardRead: (sqInt) count into: (char *)byteArrayIndex startingAt: (sqInt) startIndex; - (void) clipboardWrite: (sqInt) count from: (char *)byteArrayIndex startingAt: (sqInt) startIndex; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+clipboard.m ================================================ // // sqSqueakOSXApplication+clipboard.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-23. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. // Some code sqUnixQuartz.m -- display via native windows on Mac OS X -*- ObjC -*- // Author: Ian Piumarta <ian.piumarta@squeakland.org> /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication+clipboard.h" static char * clipboard=NULL; @implementation sqSqueakOSXApplication (clipboard) /* Cheat, we always call clipboardSize before clipboardRead, so obviously we can do the read when asking for the size */ - (sqInt) clipboardSize { NSPasteboard *pboard= [NSPasteboard generalPasteboard]; NSString *type= [pboard availableTypeFromArray: [NSArray arrayWithObject: NSStringPboardType]]; if (clipboard) free(clipboard); clipboard = NULL; if (type != NULL) { NSString *possibleData = [pboard stringForType: type]; if (!possibleData) return 0; const char *contents= [[possibleData precomposedStringWithCanonicalMapping] UTF8String]; if (contents != nil) clipboard= strdup(contents); } return clipboard ? (sqInt) strlen(clipboard) : 0; } //Evil assumption is that clipboardSize size <= byteArrayIndex size - (void) clipboardRead: (sqInt) count into: (char *)byteArrayIndex startingAt: (sqInt) startIndex { if (clipboard){ memcpy((char *)byteArrayIndex + startIndex, clipboard, count); //use memcpy versus strlcpy, targets is not null terminated. } } - (void) clipboardWrite: (sqInt) count from: (char *)byteArrayIndex startingAt: (sqInt) startIndex { NSPasteboard *pboard= [NSPasteboard generalPasteboard]; NSString * string = [[NSString alloc] initWithBytes: byteArrayIndex length:(NSUInteger)count encoding: NSUTF8StringEncoding]; [pboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: nil]; [pboard setString: string forType: NSStringPboardType]; [string release]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+cursor.h ================================================ // // sqSqueakOSXApplication+cursor.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" @interface sqSqueakOSXApplication (cursor) - (sqInt) ioSetCursorARGB: (sqInt) cursorBitsIndex extentX: (sqInt) extentX extentY: (sqInt) extentY offsetX: (sqInt) offsetX offsetY: (sqInt) offsetY; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+cursor.m ================================================ // // sqSqueakOSXApplication+cursor.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. // Some code sqUnixQuartz.m -- display via native windows on Mac OS X -*- ObjC -*- // Author: Ian Piumarta <ian.piumarta@squeakland.org> /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" #import "sqSqueakOSXApplication+cursor.h" extern BOOL gSqueakHeadless; extern BOOL browserActiveAndDrawingContextOk(void); BOOL browserActiveAndDrawingContextOkAndInFullScreenMode(void); @implementation sqSqueakOSXApplication (cursor) - (void) setCursor: (sqInt) cursorBitsIndex withMask: (sqInt) cursorMaskIndex offsetX: (sqInt) offsetX offsetY: (sqInt) offsetY { /* Set the 16x16 cursor bitmap. If cursorMaskIndex is nil, then make the mask the same as the cursor bitmap. If not, then mask and cursor bits combined determine how cursor is displayed: mask cursor effect 0 0 transparent (underlying pixel shows through) 1 1 opaque black 1 0 opaque white 0 1 invert the underlying pixel */ if (gSqueakHeadless && !browserActiveAndDrawingContextOk()) return; NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSBitmapImageRep *bitmap= [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL pixelsWide: 16 pixelsHigh: 16 bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSCalibratedBlackColorSpace bytesPerRow: 2 bitsPerPixel: 0] autorelease]; unsigned char* planes[5]; [bitmap getBitmapDataPlanes:planes]; unsigned char* data; unsigned char* mask; NSInteger i; data=planes[0]; mask=planes[1]; for (i= 0; i < 16; ++i) { unsigned int word= ((unsigned int *)pointerForIndex_xxx_dmu(cursorBitsIndex))[i]; data[i*2 + 0]= (word >> 24) & 0xFF; data[i*2 + 1]= (word >> 16) & 0xFF; if (cursorMaskIndex) word= ((unsigned int *)pointerForIndex_xxx_dmu(cursorMaskIndex))[i]; else word = 0xFFFFFFFF; mask[i*2 + 0]= (word >> 24) & 0xFF; mask[i*2 + 1]= (word >> 16) & 0xFF; } NSImage *image = [[NSImage new] autorelease]; [image addRepresentation: bitmap]; NSPoint hotSpot= { -offsetX, -offsetY }; self.squeakCursor = nil; squeakCursor = [[NSCursor alloc] initWithImage: image hotSpot: hotSpot]; /* if (browserActiveAndDrawingContextOkAndNOTInFullScreenMode()) browserSetCursor(&macCursor); */ #warning what about browser if (!gSqueakHeadless || browserActiveAndDrawingContextOkAndInFullScreenMode()) { self.squeakHasCursor = YES; [self.squeakCursor performSelectorOnMainThread: @selector(set) withObject: nil waitUntilDone: NO]; } [pool drain]; } - (sqInt) ioSetCursorARGB: (sqInt) cursorBitsIndex extentX: (sqInt) extentX extentY: (sqInt) extentY offsetX: (sqInt) offsetX offsetY: (sqInt) offsetY { if (gSqueakHeadless) return 0; if (browserActiveAndDrawingContextOk() && !browserActiveAndDrawingContextOkAndInFullScreenMode()) return 0; NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; NSBitmapImageRep *bitmap= [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL pixelsWide: extentX pixelsHigh: extentY bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bytesPerRow: extentX * 4 bitsPerPixel: 0] autorelease]; unsigned int *planes[5]; [bitmap getBitmapDataPlanes: (unsigned char **) planes]; unsigned int *src= (unsigned int*) pointerForIndex_xxx_dmu(cursorBitsIndex); unsigned int *dst= planes[0]; sqInt i; for (i= 0; i < extentX * extentY; ++i, ++dst, ++src) { #if VMENDIANNESS *dst= ((*src & 0xFF000000) >> 24) | ((*src & 0x00FFFFFF) << 8) ; // ARGB to RGBA #else *dst= (*src & 0xFF00FF00) | ((*src & 0x000000FF) << 16) | ((*src & 0x00FF0000) >> 16); // BGRA to RGBA #endif } NSImage *image= [[[NSImage alloc] init] autorelease]; [image addRepresentation: bitmap]; NSPoint hotSpot= { -offsetX, -offsetY }; self.squeakHasCursor = YES; self.squeakCursor = nil; squeakCursor= [[NSCursor alloc] initWithImage: image hotSpot: hotSpot]; [self.squeakCursor performSelectorOnMainThread: @selector(set) withObject: nil waitUntilDone: NO]; [pool drain]; return 1; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+events.h ================================================ // // sqSqueakOSXApplication+events.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-15. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" #import "sqSqueakMainApplication+events.h" #import "sqSqueakOSXNSView.h" @class NSWIndow; @interface sqSqueakOSXApplication (events) - (void) recordCharEvent:(NSString *) unicodeString fromView: (sqSqueakOSXNSView *) mainView; - (void) recordKeyUpEvent:(NSEvent *)theEvent fromView: (sqSqueakOSXNSView*) aView ; - (void) recordMouseEvent: (NSEvent*) theEvent fromView: (sqSqueakOSXNSView*) aView; - (void) recordWheelEvent: (NSEvent*) theEvent fromView: (sqSqueakOSXNSView*) aView; - (void) pushEventToQueue: (sqInputEvent *) evt; - (void) fakeMouseWheelKeyboardEventsKeyCode: (int) keyCode ascii: (int) ascii windowIndex: (int) windowIndex; - (int) mapMouseAndModifierStateToSqueakBits: (NSEvent *) event; - (NSUInteger) translateCocoaModifiersToCarbonModifiers: (NSUInteger) modifiers; - (int) translateCocoaModifiersToSqueakModifiers: (NSUInteger) modifiers; - (void) recordDragEvent: (int) dragType numberOfFiles: (int) numFiles where: (NSPoint) local_point windowIndex: (sqInt) windowIndex; - (void) recordWindowEvent: (int) type window: (NSWIndow *) window; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+events.m ================================================ // // sqSqueakOSXApplication+events.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-15. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication+events.h" #import "SqueakOSXAppDelegate.h" #import "sqSqueakOSXScreenAndWindow.h" #import "sqMacV2Browser.h" #import "sqSqueakOSXInfoPlistInterface.h" #import "keyBoardStrokeDetails.h" #import "sqSqueakOSXNSView.h" #import "sqMacHostWindow.h" extern struct VirtualMachine* interpreterProxy; extern SqueakOSXAppDelegate *gDelegateApp; /* This table maps the 5 Macintosh modifier key bits to 4 Squeak modifier bits. (The Mac shift and caps lock keys are both mapped to the single Squeak shift bit). This was true for squeak upto 3.0.7. Then in 3.0.8 we decided to not map the cap lock key to shift Mac bits: <control><option><caps lock><shift><command> ST bits: <command><option><control><shift> */ char modifierMap[256] = { 0, 8, 1, 9, 0, 8, 1, 9, 4, 12, 5, 13, 4, 12, 5, 13, //Track left and right shift keys 2, 10, 3, 11, 2, 10, 3, 11, 6, 14, 7, 15, 6, 14, 7, 15, 1, 9, 1, 9, 1, 9, 1, 9, 5, 13, 5, 13, 5, 13, 5, 13, 3, 11, 3, 11, 3, 11, 3, 11, 7, 15, 7, 15, 7, 15, 7, 15, 4, 12, 5, 13, 4, 12, 5, 13, 4, 12, 5, 13, 4, 12, 5, 13, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 5, 13, 5, 13, 5, 13, 5, 13, 5, 13, 5, 13, 5, 13, 5, 13, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 2, 10, 3, 11, 2, 10, 3, 11, 6, 14, 7, 15, 6, 14, 7, 15, 2, 10, 3, 11, 2, 10, 3, 11, 6, 14, 7, 15, 6, 14, 7, 15, 3, 11, 3, 11, 3, 11, 3, 11, 7, 15, 7, 15, 7, 15, 7, 15, 3, 11, 3, 11, 3, 11, 3, 11, 7, 15, 7, 15, 7, 15, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 6, 14, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15, 7, 15 }; enum { /* modifiers */ activeFlagBit = 0, /* activate? (activateEvt and mouseDown)*/ btnStateBit = 7, /* state of button?*/ cmdKeyBit = 8, /* command key down?*/ shiftKeyBit = 9, /* shift key down?*/ alphaLockBit = 10, /* alpha lock down?*/ optionKeyBit = 11, /* option key down?*/ controlKeyBit = 12, /* control key down?*/ rightShiftKeyBit = 13, /* right shift key down? Not supported on Mac OS X.*/ rightOptionKeyBit = 14, /* right Option key down? Not supported on Mac OS X.*/ rightControlKeyBit = 15 /* right Control key down? Not supported on Mac OS X.*/ }; enum { activeFlag = 1 << activeFlagBit, btnState = 1 << btnStateBit, cmdKey = 1 << cmdKeyBit, shiftKey = 1 << shiftKeyBit, alphaLock = 1 << alphaLockBit, optionKey = 1 << optionKeyBit, controlKey = 1 << controlKeyBit, rightShiftKey = 1 << rightShiftKeyBit, /* Not supported on Mac OS X.*/ rightOptionKey = 1 << rightOptionKeyBit, /* Not supported on Mac OS X.*/ rightControlKey = 1 << rightControlKeyBit /* Not supported on Mac OS X.*/ }; static int buttonState=0; @implementation sqSqueakOSXApplication (events) - (void) pumpRunLoop { [super pumpRunLoop]; NSEvent *event; while (event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil inMode: NSEventTrackingRunLoopMode dequeue: YES]) [NSApp sendEvent: event]; /* http://www.cocoabuilder.com/archive/cocoa/228473-receiving-user-events-from-within-an-nstimer-callback.html The reason you have to do this and can't just run the runloop is because the event loop is actually a separate concept from the runloop. It's a bit confusing because the event loop is implemented using the runloop, but if you just run the runloop on the main thread, events won't get processed. You have to explicitly run this in order to get them to be processed. Note that using the default runloop mode with this is generally a bad idea. By running in the default mode you allow *everything* else to run, which means that some other code might decide that *it* wants an inner event loop as well. If you then want to quit before that other code has finished, tough cookies. Much better to control things more tightly by using a different runloop mode. */ } - (void ) processAsOldEventOrComplexEvent: (id) event placeIn: (sqInputEvent *) evt { if ([[event objectAtIndex: 0] intValue] == 1) { [(NSData *)[event objectAtIndex: 1] getBytes: evt length: sizeof(sqInputEvent)]; if (evt->type == EventTypeKeyboard) { // NSLog(@"keyboard pc %i cc %i uc %i m %i",((sqKeyboardEvent *)evt)->pressCode,((sqKeyboardEvent *) evt)->charCode,((sqKeyboardEvent *) evt)->utf32Code,((sqKeyboardEvent *) evt)->modifiers); } return; } } - (void) pushEventToQueue: (sqInputEvent *) evt { NSMutableArray* data = [NSMutableArray new]; [data addObject: [NSNumber numberWithInteger: 1]]; [data addObject: [NSData dataWithBytes:(const void *) evt length: sizeof(sqInputEvent)]]; [eventQueue addItem: data]; [data release]; } - (void) recordCharEvent:(NSString *) unicodeString fromView: (sqSqueakOSXNSView *) mainView { sqKeyboardEvent evt; unichar unicode; unsigned char macRomanCharacter; NSInteger i; NSRange picker; NSUInteger totaLength; evt.type = EventTypeKeyboard; evt.timeStamp = (int) ioMSecs(); picker.location = 0; picker.length = 1; totaLength = [unicodeString length]; for (i=0;i < totaLength;i++) { unicode = [unicodeString characterAtIndex: i]; if (mainView.lastSeenKeyBoardStrokeDetails) { evt.modifiers = [self translateCocoaModifiersToSqueakModifiers: mainView.lastSeenKeyBoardStrokeDetails.modifierFlags]; evt.charCode = mainView.lastSeenKeyBoardStrokeDetails.keyCode; } else { evt.modifiers = 0; evt.charCode = 0; } if ((evt.modifiers & CommandKeyBit) && (evt.modifiers & ShiftKeyBit)) { /* command and shift */ if ((unicode >= 97) && (unicode <= 122)) { /* convert ascii code of command-shift-letter to upper case */ unicode = unicode - 32; } } NSString *lookupString = [[NSString alloc] initWithCharacters: &unicode length: 1]; [lookupString getBytes: &macRomanCharacter maxLength: 1 usedLength: NULL encoding: NSMacOSRomanStringEncoding options: 0 range: picker remainingRange: NULL]; [lookupString release]; evt.pressCode = EventKeyDown; unsigned short keyCodeRemembered = evt.charCode; evt.utf32Code = 0; evt.reserved1 = 0; evt.windowIndex = (int) mainView.windowLogic.windowIndex; [self pushEventToQueue: (sqInputEvent *)&evt]; evt.charCode = macRomanCharacter; evt.pressCode = EventKeyChar; evt.modifiers = evt.modifiers; evt.utf32Code = unicode; [self pushEventToQueue: (sqInputEvent *) &evt]; if (i > 1 || !mainView.lastSeenKeyBoardStrokeDetails) { evt.pressCode = EventKeyUp; evt.charCode = keyCodeRemembered; evt.utf32Code = 0; [self pushEventToQueue: (sqInputEvent *) &evt]; } } interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void) recordKeyUpEvent:(NSEvent *)theEvent fromView: (sqSqueakOSXNSView*) aView { sqKeyboardEvent evt; evt.type = EventTypeKeyboard; evt.timeStamp = (int) ioMSecs(); evt.charCode = [theEvent keyCode]; evt.pressCode = EventKeyUp; evt.modifiers = [self translateCocoaModifiersToSqueakModifiers: [theEvent modifierFlags]]; evt.utf32Code = 0; evt.reserved1 = 0; evt.windowIndex = (int) aView.windowLogic.windowIndex; [self pushEventToQueue: (sqInputEvent *) &evt]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void) recordMouseEvent:(NSEvent *)theEvent fromView: (sqSqueakOSXNSView *) aView{ sqMouseEvent evt; evt.type = EventTypeMouse; evt.timeStamp = (int) ioMSecs(); NSPoint local_point = [aView convertPoint: [theEvent locationInWindow] fromView:nil]; evt.x = (int) lrintf(local_point.x); evt.y = (int) lrintf(local_point.y); int buttonAndModifiers = [self mapMouseAndModifierStateToSqueakBits: theEvent]; evt.buttons = buttonAndModifiers & 0x07; evt.modifiers = buttonAndModifiers >> 3; #if COGVM | STACKVM evt.nrClicks = 0; #else evt.reserved1 = 0; #endif evt.windowIndex = (int) aView.windowLogic.windowIndex; [self pushEventToQueue:(sqInputEvent *) &evt]; //NSLog(@"mouse hit x %i y %i buttons %i mods %i",evt.x,evt.y,evt.buttons,evt.modifiers); interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void) recordWheelEvent:(NSEvent *) theEvent fromView: (sqSqueakOSXNSView *) aView{ [self recordMouseEvent: theEvent fromView: aView]; CGFloat x = [theEvent deltaX]; CGFloat y = [theEvent deltaY]; if (x != 0.0f) { [self fakeMouseWheelKeyboardEventsKeyCode: (x < 0 ? 124 : 123) ascii: (x < 0 ? 29 : 28) windowIndex: (int) aView.windowLogic.windowIndex]; } if (y != 0.0f) { [self fakeMouseWheelKeyboardEventsKeyCode: (y < 0 ? 125 : 126) ascii: (y < 0 ? 31 : 30) windowIndex: (int) aView.windowLogic.windowIndex]; } } - (void) fakeMouseWheelKeyboardEventsKeyCode: (int) keyCode ascii: (int) ascii windowIndex: (int) windowIndex { sqKeyboardEvent evt; evt.type = EventTypeKeyboard; evt.timeStamp = (int) ioMSecs(); evt.pressCode = EventKeyDown; evt.charCode = keyCode; evt.utf32Code = 0; evt.reserved1 = 0; evt.modifiers = modifierMap[(controlKey >> 8)]; evt.windowIndex = windowIndex; [self pushEventToQueue:(sqInputEvent *) &evt]; evt.pressCode = EventKeyChar; evt.charCode = ascii; evt.utf32Code = ascii; [self pushEventToQueue:(sqInputEvent *) &evt]; evt.pressCode = EventKeyUp; evt.charCode = keyCode; evt.utf32Code = 0; [self pushEventToQueue:(sqInputEvent *) &evt]; } - (int) translateCocoaModifiersToSqueakModifiers: (NSUInteger) modifiers { NSUInteger keyBoardModifiers = [self translateCocoaModifiersToCarbonModifiers: modifiers]; return ((modifierMap[((keyBoardModifiers & 0xFFFF) >> 8)])); } - (NSUInteger) translateCocoaModifiersToCarbonModifiers: (NSUInteger) modifiers { NSUInteger keyBoardModifiers=0; if (modifiers & NSAlphaShiftKeyMask) keyBoardModifiers |= alphaLock; if (modifiers & NSShiftKeyMask) keyBoardModifiers |= shiftKey; if (modifiers & NSControlKeyMask) keyBoardModifiers |= controlKey; if (modifiers & NSAlternateKeyMask) keyBoardModifiers |= optionKey; if (modifiers & NSCommandKeyMask) keyBoardModifiers |= cmdKey; return keyBoardModifiers; } - (int) mapMouseAndModifierStateToSqueakBits: (NSEvent *) event { /* On a two- or three-button mouse, the left button is normally considered primary and the right button secondary, but left-handed users can reverse these settings as a matter of preference. The middle button on a three-button mouse is always the tertiary button. ' But mapping assumes 1,2,3 red, yellow, blue */ NSInteger stButtons,modifier,mappedButton; NSInteger mouseButton=0; static NSInteger buttonStateBits[4] = {0,0,0,0}; stButtons = buttonState; NSUInteger keyBoardCarbonModifiers = [self translateCocoaModifiersToCarbonModifiers: [event modifierFlags]]; NSInteger whatHappened = [event type]; if (whatHappened != NSMouseMoved && whatHappened != NSScrollWheel) { stButtons = 0; mouseButton = 0; if (whatHappened == NSLeftMouseUp || whatHappened == NSLeftMouseDown) mouseButton = 1; if (whatHappened == NSRightMouseUp || whatHappened == NSRightMouseDown) mouseButton = 2; if (!mouseButton) mouseButton = [event buttonNumber] + 1; //buttonNumber seems to count from 0. if (mouseButton > 0 && mouseButton < 4) { modifier = 0; if (keyBoardCarbonModifiers & cmdKey ) modifier = 1; if (keyBoardCarbonModifiers & optionKey) modifier = 2; if (keyBoardCarbonModifiers & controlKey) modifier = 3; if (browserActiveAndDrawingContextOkAndNOTInFullScreenMode()) mappedButton = [(sqSqueakOSXInfoPlistInterface *) self.infoPlistInterfaceLogic getSqueakBrowserMouseMappingsAt: modifier by: mouseButton]; else mappedButton = [(sqSqueakOSXInfoPlistInterface *) self.infoPlistInterfaceLogic getSqueakMouseMappingsAt: modifier by: mouseButton]; buttonStateBits[mappedButton] = (whatHappened == NSLeftMouseUp || whatHappened == NSRightMouseUp || whatHappened == NSOtherMouseUp) ? 0 : 1; stButtons |= mappedButton == 1 ? (buttonStateBits[mappedButton] ? RedButtonBit : 0) : 0; stButtons |= mappedButton == 2 ? (buttonStateBits[mappedButton] ? YellowButtonBit : 0) : 0; stButtons |= mappedButton == 3 ? (buttonStateBits[mappedButton] ? BlueButtonBit : 0) : 0; } } // button state: low three bits are mouse buttons; next 8 bits are modifier bits buttonState = (int) (modifierMap[((keyBoardCarbonModifiers & 0xFFFF) >> 8)] << 3) | (int) (stButtons & 0x7); return buttonState; } - (void) recordDragEvent: (int) dragType numberOfFiles: (int) numFiles where: (NSPoint) local_point windowIndex: (sqInt) windowIndex { sqDragDropFilesEvent evt; evt.type= EventTypeDragDropFiles; evt.timeStamp= (int) ioMSecs(); evt.dragType= dragType; evt.x = (int) lrintf(local_point.x); evt.y = (int) lrintf(local_point.y); evt.modifiers= (buttonState >> 3); evt.numFiles= numFiles; evt.windowIndex = (int) windowIndex; [self pushEventToQueue: (sqInputEvent *) &evt]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void) recordWindowEvent: (int) windowType window: (NSWIndow *) window { sqWindowEvent evt; evt.type= EventTypeWindow; evt.timeStamp= (int) ioMSecs(); evt.action= windowType; evt.value1 = 0; evt.value2 = 0; evt.value3 = 0; evt.value4 = 0; evt.windowIndex = windowIndexFromHandle((wHandleType)window); [self pushEventToQueue: (sqInputEvent *) &evt]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+imageReadWrite.h ================================================ // // sqSqueakOSXApplication+imageReadWrite.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-13. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" @interface sqSqueakOSXApplication (imageReadWrite) - (void) attempToOpenImageFromOpenPanel; - (BOOL) setImageNamePathIfItWasReadable: (NSString *) filePath; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication+imageReadWrite.m ================================================ // // sqSqueakOSXApplication+imageReadWrite.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-13. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication+imageReadWrite.h" #import "sqSqueakMainApplication+vmAndImagePath.h" #import "sqSqueakOSXInfoPlistInterface.h" #import "SqueakOSXAppDelegate.h" extern SqueakOSXAppDelegate *gDelegateApp; @implementation sqSqueakOSXApplication (imageReadWrite) - (void) attempToOpenImageFromOpenPanel { NSOpenPanel *panel= [NSOpenPanel openPanel]; NSString *promptTitle = NSLocalizedString(@"SqueakSelectImagePanePrompt",nil); NSArray *types = [[NSArray alloc] initWithObjects: @"image", nil ]; [panel setTitle: promptTitle]; [panel setFloatingPanel: YES]; [panel setOneShot: YES]; [panel setReleasedWhenClosed: YES]; [panel setAllowedFileTypes: types]; [panel center]; if (NSOKButton == [panel runModalForTypes: types]) { NSArray *urls= [panel URLs]; if (1 == [urls count]) [self setImageNamePathIfItWasReadable: [[urls objectAtIndex: 0] path]]; } else { exit(142); } [types release]; } - (BOOL) setImageNamePathIfItWasReadable: (NSString *) filePath { BOOL fileIsReadable = [[NSFileManager defaultManager] isReadableFileAtPath: filePath]; if (fileIsReadable) { [(sqSqueakOSXInfoPlistInterface*)[self infoPlistInterfaceLogic] setOverrideSqueakImageName: filePath]; [self imageNamePut: [filePath UTF8String]]; } return fileIsReadable; } - (void) findImageViaBundleOrPreferences { NSAutoreleasePool * pool = [NSAutoreleasePool new]; /* Check for squeak image name in resource directory if not found then check for image after resolving image name incase it's a ./ or ../ or ~/ etc plus also could be in working directory? So first let's see if the imageName is a partial path, if so use it. otherwise check the resource directory then the vmpath. */ NSBundle *mainBundle = [NSBundle mainBundle]; NSString *resourcePath = [mainBundle resourcePath]; BOOL fileIsReadable; // extern char imageName[]; #warning do we check for imageName that is elsewhere? like ~/Foo/squeak.image NSString *possibleImage; NSString *imageNameString; if (gDelegateApp.possibleImageNameAtLaunchTime) { imageNameString = possibleImage = gDelegateApp.possibleImageNameAtLaunchTime; } else { imageNameString = [NSString stringWithUTF8String: imageName]; possibleImage = [imageNameString stringByStandardizingPath]; } if ([imageNameString compare: possibleImage] == NSOrderedSame) { if ([possibleImage isAbsolutePath]) { fileIsReadable = [self setImageNamePathIfItWasReadable: possibleImage]; } else { NSString *fullResourcePathToImage = [resourcePath stringByAppendingPathComponent: imageNameString]; fileIsReadable = [self setImageNamePathIfItWasReadable: fullResourcePathToImage]; if (!fileIsReadable){ NSString *vmPath = [self.vmPathStringURL path]; NSString *fullVMPathToImage = [vmPath stringByAppendingPathComponent: imageNameString]; fileIsReadable = [self setImageNamePathIfItWasReadable: fullVMPathToImage]; } } } else { fileIsReadable = [self setImageNamePathIfItWasReadable: possibleImage]; } // At this point we did not find a file name in the resources or in the vm directory or via a set image name if (!fileIsReadable) { [self performSelectorOnMainThread: @selector(attempToOpenImageFromOpenPanel) withObject: nil waitUntilDone: YES]; } [pool drain]; return; } - (void) imageNamePut:(const char *) sqImageName { if (!sqImageName) return; [super imageNamePut: sqImageName]; [gDelegateApp.window setRepresentedURL: self.imageNameURL]; [gDelegateApp.window setTitle: [[self.imageNameURL path] lastPathComponent]]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication.h ================================================ // // sqSqueakOSXApplication.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-10. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> #import "sqSqueakMainApplication.h" @interface sqSqueakOSXApplication : sqSqueakMainApplication { NSCursor *squeakCursor; BOOL squeakHasCursor; } @property (nonatomic,retain) NSCursor *squeakCursor; @property (nonatomic,assign) BOOL squeakHasCursor; - (NSInteger) parseArgument: (NSString *) argData peek: (NSString *) peek; - (void) parseArgs: (NSArray *) args; - (void) parseEnv: (NSDictionary *) env; - (long long) strtobkm: (const char *) chr; - (void) usage; - (void) printUsage; - (void) printUsageNotes; - (BOOL)isImageFile:(NSString *)filePath; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXApplication.m ================================================ // // sqSqueakOSXApplication.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-10. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXApplication.h" #import "sqSqueakOSXFileDirectoryInterface.h" #import "sqSqueakOSXInfoPlistInterface.h" #import "sqSqueakOSXSoundCoreAudio.h" #import "sqSqueakSoundCoreAudioAPI.h" usqInt gMaxHeapSize=512*1024*1024; #if defined(__GNUC__) && ( defined(i386) || defined(__i386) || defined(__i386__) \ || defined(i486) || defined(__i486) || defined (__i486__) \ || defined(intel) || defined(x86) || defined(i86pc) \ || defined(__x86_64__)) void fldcw(unsigned int cw) { __asm__("fldcw %0" :: "m"(cw)); } #else # define fldcw(cw) #endif #if defined(__GNUC__) && ( defined(ppc) || defined(__ppc) || defined(__ppc__) \ || defined(POWERPC) || defined(__POWERPC) || defined (__POWERPC__) ) void mtfsfi(unsigned long long fpscr) { __asm__("lfd f0, %0" :: "m"(fpscr)); __asm__("mtfsf 0xff, f0"); } #else void mtfsfi(unsigned long long fpscr) {} # define mtfsfi(fpscr) #endif @implementation sqSqueakOSXApplication @synthesize squeakHasCursor,squeakCursor; - (void) setupFloat { fldcw(0x12bf); /* signed infinity, round to nearest, REAL8, disable intrs, disable signals */ mtfsfi((unsigned long long ) 0); /* disable signals, IEEE mode, round to nearest */ } - (sqSqueakFileDirectoryInterface *) newFileDirectoryInterfaceInstance { return [sqSqueakOSXFileDirectoryInterface new]; } - (sqSqueakInfoPlistInterface *) newSqSqueakInfoPlistInterfaceCreation { return [sqSqueakOSXInfoPlistInterface new]; } - (void) doHeadlessSetup { [super doHeadlessSetup]; extern BOOL gSqueakHeadless; if (gSqueakHeadless) return; #warning untested ProcessSerialNumber psn = { 0, kCurrentProcess }; ProcessInfoRec info; bzero(&info, sizeof(ProcessInfoRec)); info.processInfoLength = sizeof(ProcessInfoRec); GetProcessInformation(&psn,&info); if ((info.processMode & modeOnlyBackground) && TransformProcessType != NULL) { OSStatus returnCode = TransformProcessType(& psn, kProcessTransformToForegroundApplication); #pragma unused(returnCode) SetFrontProcess(&psn); } } - (void) doMemorySetup { gMaxHeapSize = ((sqSqueakOSXInfoPlistInterface*) self.infoPlistInterfaceLogic).SqueakMaxHeapSize; } - (void) setupSoundLogic { self.soundInterfaceLogic = [sqSqueakOSXSoundCoreAudio new]; [(sqSqueakOSXSoundCoreAudio *) self.soundInterfaceLogic soundInitOverride]; snd_Start(2644, 22050, 1, 0); char slience[10576]; bzero(&slience, sizeof(slience)); snd_PlaySamplesFromAtLength(2644,(usqInt * ) &slience,0); [self.soundInterfaceLogic snd_Stop_Force]; } - (void) parseUnixArgs { NSProcessInfo *p = [NSProcessInfo processInfo]; [self parseArgs: [p arguments]]; [self parseEnv: [p environment]]; } - (NSInteger) parseArgument: (NSString *) argData peek: (NSString *) peek { if ([argData compare: @"--"] == NSOrderedSame) { return 1; } NS_DURING; if ([argData compare: @"-psn_" options: NSLiteralSearch range: NSMakeRange(0,5)] == NSOrderedSame) { return 1; } NS_HANDLER; NS_ENDHANDLER; if ([argData compare: @"-help"] == NSOrderedSame) { [self usage]; return 1; } if ([argData compare: @"-headless"] == NSOrderedSame) { extern BOOL gSqueakHeadless; gSqueakHeadless = YES; return 1; } if ([argData compare: @"-memory"] == NSOrderedSame) { gMaxHeapSize = (usqInt) [self strtobkm: [peek UTF8String]]; return 2; } return 0; } - (void) parseArgs: (NSArray *) args{ argsArguments = [[NSMutableArray alloc] initWithCapacity: [args count]]; if ([args count] < 2) return; NSMutableArray *revisedArgs = [args mutableCopyWithZone: NULL]; [revisedArgs removeObjectAtIndex:0]; NSUInteger i,result; BOOL optionsCompleted = NO; for (i=0; i<[revisedArgs count]; i++) { NSString *argData = [revisedArgs objectAtIndex:i]; NSString *peek = (i == ([revisedArgs count] - 1)) ? @"" : [revisedArgs objectAtIndex:i+1]; if ([argData compare: @"--"] == NSOrderedSame) { optionsCompleted = YES; continue; } if (!optionsCompleted && [[argData substringToIndex: 1] compare: @"-"] != NSOrderedSame) { optionsCompleted = YES; continue; } if (optionsCompleted) { [self.argsArguments addObject: argData]; } else { result = [self parseArgument: argData peek: peek]; if (result == 0) /* option not recognised */ { fprintf(stderr, "unknown option: %s\n", [argData UTF8String]); [self usage]; } if (result == 2) i++; } } [revisedArgs release]; } - (long long) strtobkm: (const char *) str { char *suffix; long long value= strtoll(str, &suffix, 10); switch (*suffix) { case 'k': case 'K': value*= 1024LL; break; case 'm': case 'M': value*= 1024LL*1024LL; break; } return value; } - (void) parseEnv: (NSDictionary *) env { #warning untested! NSString *imageNameString = [env objectForKey: @"SQUEAK_IMAGE"]; if (imageNameString) { [(sqSqueakOSXInfoPlistInterface*) self.infoPlistInterfaceLogic setOverrideSqueakImageName: imageNameString]; } NSString *memoryString = [env objectForKey: @"SQUEAK_MEMORY"]; if (memoryString) { gMaxHeapSize = (usqInt) [self strtobkm: [memoryString UTF8String]]; } } - (void) usage { printf("Usage: [<option>...] [<imageName> [<argument>...]]\n"); printf(" [<option>...] -- [<argument>...]\n"); [self printUsage]; printf("\nNotes:\n"); printf(" <imageName> defaults to `Squeak.image'.\n"); [self printUsageNotes]; exit(1); } - (void) printUsage { printf("\nCommon <option>s:\n"); printf(" -help print this help message, then exit\n"); printf(" -memory <size>[mk] use fixed heap size (added to image size)\n"); printf(" -headless run in headless (no window) mode (default: false)\n"); } - (void) printUsageNotes { printf(" If `-memory' is not specified then the heap will grow dynamically.\n"); printf(" <argument>s are ignored, but are processed by the Squeak image.\n"); printf(" The first <argument> normally names a Squeak `script' to execute.\n"); printf(" Precede <arguments> by `--' to use default image.\n"); } - (BOOL) isImageFile: (NSString *) filePath { NSFileManager *dfm = [NSFileManager defaultManager]; BOOL isDirectory; [dfm fileExistsAtPath: filePath isDirectory: &isDirectory]; if (isDirectory) return NO; BOOL fileIsReadable = [[NSFileManager defaultManager] isReadableFileAtPath: filePath]; if (fileIsReadable == NO) return NO; if ([[[filePath lastPathComponent] pathExtension] compare: @"image" options: NSCaseInsensitiveSearch] == NSOrderedSame) return YES; return NO; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXClipboardAPI.h ================================================ // // sqSqueakOSXClipboardAPI.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-23. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXClipboardAPI.m ================================================ // // sqSqueakOSXClipboardAPI.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-23. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXClipboardAPI.h" #import "SqueakOSXAppDelegate.h" #import "sqSqueakOSXApplication+clipboard.h" extern SqueakOSXAppDelegate *gDelegateApp; /* Clipboard (cut/copy/paste). */ sqInt clipboardSize(void) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt value = [(sqSqueakOSXApplication *)gDelegateApp.squeakApplication clipboardSize]; [pool drain]; return value; } sqInt clipboardReadIntoAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex){ NSAutoreleasePool * pool = [NSAutoreleasePool new]; [(sqSqueakOSXApplication *)gDelegateApp.squeakApplication clipboardRead: count into: (char *) pointerForIndex_xxx_dmu((usqInt)byteArrayIndex) startingAt: startIndex]; [pool drain]; return 0; } sqInt clipboardWriteFromAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex){ NSAutoreleasePool * pool = [NSAutoreleasePool new]; [(sqSqueakOSXApplication *)gDelegateApp.squeakApplication clipboardWrite: count from: (char *)pointerForIndex_xxx_dmu((usqInt)byteArrayIndex) startingAt: startIndex]; [pool drain]; return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXDropAPI.h ================================================ // // sqSqueakOSXDropAPI.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-27. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "DropPlugin.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXDropAPI.m ================================================ // // sqSqueakOSXDropAPI.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-27. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXScreenAndWindow.h" #include "sqMacHostWindow.h" #include "sq.h" extern wHandleType windowHandleFromIndex(sqInt windowIndex); extern struct VirtualMachine* interpreterProxy; sqInt dropInit(void) { return 1; }; sqInt dropShutdown(void) { return 1; }; char* dropRequestFileName(sqInt dropIndex) { /* return name of file or NULL if error */ sqSqueakOSXNSView* view = ((sqSqueakOSXScreenAndWindow*)((NSWindow *)windowHandleFromIndex(1)).delegate).mainViewOnWindow; NSString *fileNameString = [view dragFileNameStringAtIndex: dropIndex]; return (char *) [fileNameString UTF8String]; } /* note: dropRequestFileHandle needs to bypass plugin security checks when implemented */ sqInt dropRequestFileHandle(sqInt dropIndex) { /* return READ-ONLY file handle OOP or nilObject if error */ char *fileName = dropRequestFileName(dropIndex); if (!fileName) return 0; void *fn = interpreterProxy->ioLoadFunctionFrom("fileOpenNamesizewritesecure", "FilePlugin"); if (fn == NULL) { /* begin primitiveFail */ interpreterProxy->success(false); return 0; } sqInt result = ((sqInt (*) (char * nameIndex, sqInt nameSize, sqInt writeFlag, sqInt secureFlag)) fn)(fileName,(sqInt) strlen(fileName), 0,0); return result; } sqInt sqSecFileAccessCallback(void *ptr) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXFileDirectoryInterface.h ================================================ // // sqSqueakOSXFileDirectoryInterface.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-11. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> #import "sqSqueakFileDirectoryInterface.h" @interface sqSqueakOSXFileDirectoryInterface : sqSqueakFileDirectoryInterface { } - (NSString *)resolveAliasAtPath:(NSString *)aliasFullPath; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXFileDirectoryInterface.m ================================================ // // sqSqueakOSXFileDirectoryInterface.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-11. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ /* The resolve Alias logic is via http://blacktree-alchemy.googlecode.com/svn/branches/B5X/README.markdown Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // #import "sqSqueakOSXFileDirectoryInterface.h" #import "SqueakOSXAppDelegate.h" extern SqueakOSXAppDelegate *gDelegateApp; @implementation sqSqueakOSXFileDirectoryInterface - (BOOL) setWorkingDirectory { if (1) return 1; //for people wanting to do ./Squeak.app foobar.image zingger.st NSString *path = [gDelegateApp.squeakApplication.vmPathStringURL path]; BOOL results = [[NSFileManager defaultManager] changeCurrentDirectoryPath: path]; return results; } - (NSString *)resolvedAliasFiles:(NSString *)filePath { NSArray *compoents = [[filePath stringByStandardizingPath] pathComponents]; NSString *thisComponent; NSString *path = [[NSString new] autorelease]; for (thisComponent in compoents) { path = [path stringByAppendingPathComponent:thisComponent]; if (![[NSFileManager defaultManager] fileExistsAtPath:path]) continue; LSItemInfoRecord infoRec; LSCopyItemInfoForURL((CFURLRef) [NSURL fileURLWithPath:path], kLSRequestBasicFlagsOnly, &infoRec); if (infoRec.flags & kLSItemInfoIsAliasFile) path = [[self resolveAliasAtPath:path] stringByResolvingSymlinksInPath]; } return path; } - (NSString *)resolveAliasAtPath:(NSString *)aliasFullPath { NSString *outString = nil; NSURL *url; FSRef aliasRef; Boolean targetIsFolder; Boolean wasAliased; if (!CFURLGetFSRef((CFURLRef) [NSURL fileURLWithPath:aliasFullPath], &aliasRef) || FSResolveAliasFileWithMountFlags(&aliasRef, true, &targetIsFolder, &wasAliased, kResolveAliasFileNoUI) != noErr) return nil; if (url = (NSURL *)CFURLCreateFromFSRef(kCFAllocatorDefault, &aliasRef)) { outString = [url path]; CFRelease(url); return outString; } return nil; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXInfoPlistInterface.h ================================================ // // sqSqueakOSXInfoPlistInterface.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-12. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakInfoPlistInterface.h" #import "sq.h" @interface sqSqueakOSXInfoPlistInterface : sqSqueakInfoPlistInterface { NSInteger SqueakDebug; BOOL SqueakQuitOnQuitAppleEvent; BOOL SqueakPluginsBuiltInOrLocalOnly; BOOL SqueakExplicitWindowOpenNeeded; usqInt SqueakMaxHeapSize; NSURL *SqueakUnTrustedDirectory; NSURL *SqueakTrustedDirectory; NSURL *SqueakResourceDirectory; NSTimeInterval SqueakUIFlushPrimaryDeferNMilliseconds; float SqueakUIFadeForFullScreenInSeconds; NSInteger SqueakMouseMappings[4][4]; NSInteger SqueakBrowserMouseMappings[4][4]; NSInteger SqueakNumStackPages; NSInteger SqueakEdenBytes; } @property (nonatomic,assign) NSInteger SqueakDebug; @property (nonatomic,assign) NSInteger SqueakNumStackPages; @property (nonatomic,assign) NSInteger SqueakEdenBytes; @property (nonatomic,assign) BOOL SqueakQuitOnQuitAppleEvent; @property (nonatomic,assign) BOOL SqueakPluginsBuiltInOrLocalOnly; @property (nonatomic,assign) BOOL SqueakExplicitWindowOpenNeeded; @property (nonatomic,assign) usqInt SqueakMaxHeapSize; @property (nonatomic,retain) NSURL* SqueakUnTrustedDirectory; @property (nonatomic,retain) NSURL* SqueakTrustedDirectory; @property (nonatomic,retain) NSURL* SqueakResourceDirectory; @property (nonatomic,assign) NSTimeInterval SqueakUIFlushPrimaryDeferNMilliseconds; @property (nonatomic,assign) float SqueakUIFadeForFullScreenInSeconds; - (void) setInfoPlistNumberValueFrom: (NSDictionary*) dict key: (NSString *) key default: (NSInteger) number using: (SEL) selector; - (void) setInfoPlistFloatNumberValueFrom: (NSDictionary*) dict key: (NSString *) key default: (float) number using: (SEL) selector; - (void) setInfoPlistBooleanValueFrom: (NSDictionary*) dict key: (NSString *) key default: (BOOL) defaultBool using: (SEL) selector; - (void) setInfoPlistNumberValueForMouseX: (NSInteger) x Y: (NSInteger) y from: (NSDictionary*) dict key: (NSString *) key default: (NSInteger) number browser: (BOOL) browser; - (NSURL *) expandNSStringIntoNSURL: (NSString*) originalPath doOptionalSqueakLandLogic: (BOOL) isetoysonastick; - (NSString *) fixupNonAbsolutePath: (NSString *) partialPathString; - (void) setOverrideSqueakImageName: (NSString *) v; - (NSInteger) getSqueakMouseMappingsAt: (NSInteger) i by: (NSInteger) j; - (NSInteger) getSqueakBrowserMouseMappingsAt: (NSInteger) i by: (NSInteger) j; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXInfoPlistInterface.m ================================================ // // sqSqueakOSXInfoPlistInterface.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-12. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXInfoPlistInterface.h" extern int gSqueakUseFileMappedMMAP; @implementation sqSqueakOSXInfoPlistInterface @synthesize SqueakDebug,SqueakQuitOnQuitAppleEvent, SqueakMaxHeapSize,SqueakUnTrustedDirectory,SqueakTrustedDirectory,SqueakResourceDirectory, SqueakPluginsBuiltInOrLocalOnly,SqueakExplicitWindowOpenNeeded,SqueakUIFlushPrimaryDeferNMilliseconds,SqueakNumStackPages,SqueakEdenBytes, SqueakUIFadeForFullScreenInSeconds; - (void) setOverrideSqueakNumStackPages: (NSNumber *) v { self.SqueakNumStackPages = [v integerValue]; } - (void) setOverrideSqueakEdenBytes: (NSNumber *) v { self.SqueakEdenBytes = [v integerValue]; } - (void) setOverrideSqueakDebug: (NSNumber *) v { self.SqueakDebug = [v integerValue]; } - (void) setOverrideSqueakQuitOnQuitAppleEvent: (NSNumber *) v { self.SqueakQuitOnQuitAppleEvent = [v boolValue]; } - (void) setOverrideSqueakUseFileMappedMMAP: (NSNumber *) v { self.SqueakUseFileMappedMMAP = [v boolValue]; gSqueakUseFileMappedMMAP = [v boolValue] == YES; } - (void) setOverrideSqueakPluginsBuiltInOrLocalOnly: (NSNumber *) v { self.SqueakPluginsBuiltInOrLocalOnly = [v boolValue]; } - (void) setOverrideSqueakExplicitWindowOpenNeeded: (NSNumber *) v { self.SqueakExplicitWindowOpenNeeded = [v boolValue]; } - (void) setOverrideSqueakMaxHeapSize: (NSNumber *) v { self.SqueakMaxHeapSize = [v unsignedIntValue]; } - (void) setOverrideSqueakUIFadeForFullScreenInSeconds: (NSNumber *) v { self.SqueakUIFadeForFullScreenInSeconds = [v floatValue]; } - (void) setOverrideSqueakUIFlushPrimaryDeferNMilliseconds: (NSNumber *) v { self.SqueakUIFlushPrimaryDeferNMilliseconds = [v doubleValue]/1000.0; } - (void) setOverrideSqueakUnTrustedDirectory: (NSString *) v { self.SqueakUnTrustedDirectory = [self expandNSStringIntoNSURL: v doOptionalSqueakLandLogic: YES]; const char *dataInFileSystemRep = [[NSFileManager defaultManager] fileSystemRepresentationWithPath: [self.SqueakUnTrustedDirectory path]]; extern char gSqueakUntrustedDirectoryName[]; strlcpy(gSqueakUntrustedDirectoryName, dataInFileSystemRep, PATH_MAX); strlcat(gSqueakUntrustedDirectoryName,"/",PATH_MAX); } - (void) setOverrideSqueakTrustedDirectory: (NSString *) v { self.SqueakTrustedDirectory = [self expandNSStringIntoNSURL: v doOptionalSqueakLandLogic: YES]; const char *dataInFileSystemRep = [[NSFileManager defaultManager] fileSystemRepresentationWithPath: [self.SqueakTrustedDirectory path]]; extern char gSqueakTrustedDirectoryName[]; strlcpy(gSqueakTrustedDirectoryName, dataInFileSystemRep, PATH_MAX); strlcat(gSqueakTrustedDirectoryName,"/",PATH_MAX); } - (void) setOverrideSqueakResourceDirectory: (NSString *) v { if (!v) return; self.SqueakResourceDirectory = [self expandNSStringIntoNSURL: v doOptionalSqueakLandLogic: YES]; } - (void) setOverrideSqueakImageName: (NSString *) v { if (!v) return; extern char imageName[]; strlcpy(imageName,[v UTF8String],PATH_MAX); } - (NSInteger) getSqueakMouseMappingsAt: (NSInteger) i by: (NSInteger) j { return SqueakMouseMappings[i][j]; } - (NSInteger) getSqueakBrowserMouseMappingsAt: (NSInteger) i by: (NSInteger) j { return SqueakBrowserMouseMappings[i][j]; } - (void) setInfoPlistNSStringValueFrom: (NSDictionary*) dict key: (NSString *) key default: (NSString*) defaultString using: (SEL) selector{ NSString *str = [dict objectForKey: key]; str = (str) ? str : defaultString; [self performSelectorOnMainThread: selector withObject: str waitUntilDone: YES]; } - (void) setInfoPlistNumberValueFrom: (NSDictionary*) dict key: (NSString *) key default: (NSInteger) defaultInteger using: (SEL) selector{ NSNumber *num = [dict objectForKey: key]; num = (num) ? num : [NSNumber numberWithInteger: defaultInteger]; [self performSelectorOnMainThread: selector withObject: num waitUntilDone: YES]; } - (void) setInfoPlistFloatNumberValueFrom: (NSDictionary*) dict key: (NSString *) key default: (float) defaultFloat using: (SEL) selector{ NSNumber *num = [dict objectForKey: key]; num = (num) ? num : [NSNumber numberWithFloat: defaultFloat]; [self performSelectorOnMainThread: selector withObject: num waitUntilDone: YES]; } - (void) setInfoPlistBooleanValueFrom: (NSDictionary*) dict key: (NSString *) key default: (BOOL) defaultBool using: (SEL) selector{ NSNumber *num = [dict objectForKey: key]; num = (num) ? num : [NSNumber numberWithBool: defaultBool]; [self performSelectorOnMainThread: selector withObject: num waitUntilDone: YES]; } - (void) setInfoPlistNumberValueForMouseX: (NSInteger) x Y: (NSInteger) y from: (NSDictionary*) dict key: (NSString *) key default: (NSInteger) number browser: (BOOL) browser { NSNumber *num = [dict objectForKey: key]; NSInteger numberAsInteger = (num) ? [num integerValue] : number; if (browser) { SqueakBrowserMouseMappings[x][y] = numberAsInteger; } else { SqueakMouseMappings[x][y] = numberAsInteger; } } - (NSURL *) expandNSStringIntoNSURL: (NSString*) originalPath doOptionalSqueakLandLogic: (BOOL) isetoysonastick { NSString *checkFortilda = [originalPath stringByStandardizingPath]; if (isetoysonastick) { NSString *standardizedString; BOOL isAbsolutePath = [checkFortilda isAbsolutePath]; if (!isAbsolutePath) { NSString *filePath = [self fixupNonAbsolutePath: checkFortilda]; standardizedString = [filePath stringByStandardizingPath]; } else { standardizedString = checkFortilda; } return [NSURL fileURLWithPath: standardizedString]; } return [NSURL fileURLWithPath: checkFortilda]; } - (NSString *) fixupNonAbsolutePath: (NSString *) partialPathString { NSBundle *mainBundle = [NSBundle mainBundle]; NSString *resourcePath = [mainBundle resourcePath]; NSString *actualPath = [resourcePath stringByAppendingPathComponent: partialPathString]; return actualPath ; } - (void) parseInfoPlist { NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSBundle *mainBundle = [NSBundle mainBundle]; NSDictionary *dict = [mainBundle infoDictionary]; [self setInfoPlistNumberValueFrom: dict key: @"SqueakNumStackPages" default: 0 using: @selector(setOverrideSqueakNumStackPages:)]; [self setInfoPlistNumberValueFrom: dict key: @"SqueakEdenBytes" default: 0 using: @selector(setOverrideSqueakEdenBytes:)]; [self setInfoPlistNumberValueFrom: dict key: @"SqueakDebug" default: 0 using: @selector(setOverrideSqueakDebug:)]; [self setInfoPlistBooleanValueFrom: dict key: @"SqueakQuitOnQuitAppleEvent" default: NO using: @selector(setOverrideSqueakQuitOnQuitAppleEvent:)]; [self setInfoPlistBooleanValueFrom: dict key: @"SqueakUseFileMappedMMAP" default: NO using: @selector(setOverrideSqueakUseFileMappedMMAP:)]; [self setInfoPlistNumberValueFrom: dict key: @"SqueakMaxHeapSize" default: 512*1024*1024 using: @selector(setOverrideSqueakMaxHeapSize:)]; [self setInfoPlistNumberValueFrom: dict key: @"SqueakUIFlushPrimaryDeferNMilliseconds" default: 20 using: @selector(setOverrideSqueakUIFlushPrimaryDeferNMilliseconds:)]; [self setInfoPlistFloatNumberValueFrom: dict key: @"SqueakUIFadeForFullScreenInSeconds" default: 1.5 using: @selector(setOverrideSqueakUIFadeForFullScreenInSeconds:)]; [self setInfoPlistNSStringValueFrom: dict key: @"SqueakUnTrustedDirectory" default: @"/foobar/tooBar/forSqueak/bogus/" using: @selector(setOverrideSqueakUnTrustedDirectory:)]; [self setInfoPlistNSStringValueFrom: dict key: @"SqueakTrustedDirectory" default: @"/foobar/tooBar/forSqueak/bogus/" using: @selector(setOverrideSqueakTrustedDirectory:)]; [self setInfoPlistNSStringValueFrom: dict key: @"SqueakResourceDirectory" default: NULL using: @selector(setSqueakResourceDirectory:)]; [self setInfoPlistBooleanValueFrom: dict key: @"SqueakPluginsBuiltInOrLocalOnly" default: YES using: @selector(setOverrideSqueakPluginsBuiltInOrLocalOnly:)]; [self setInfoPlistBooleanValueFrom: dict key: @"SqueakExplicitWindowOpenNeeded" default: NO using: @selector(setOverrideSqueakExplicitWindowOpenNeeded:)]; [self setInfoPlistNSStringValueFrom: dict key: @"SqueakImageName" default: @"Squeak.image" using: @selector(setOverrideSqueakImageName:)]; [self setInfoPlistNumberValueForMouseX: 0 Y: 1 from: dict key: @"SqueakMouseNoneButton1" default: 1 browser: NO]; [self setInfoPlistNumberValueForMouseX: 0 Y: 2 from: dict key: @"SqueakMouseNoneButton2" default: 3 browser: NO]; [self setInfoPlistNumberValueForMouseX: 0 Y: 3 from: dict key: @"SqueakMouseNoneButton3" default: 2 browser: NO]; [self setInfoPlistNumberValueForMouseX: 1 Y: 1 from: dict key: @"SqueakMouseCmdButton1" default: 3 browser: NO]; [self setInfoPlistNumberValueForMouseX: 1 Y: 2 from: dict key: @"SqueakMouseCmdButton2" default: 3 browser: NO]; [self setInfoPlistNumberValueForMouseX: 1 Y: 3 from: dict key: @"SqueakMouseCmdButton3" default: 2 browser: NO]; [self setInfoPlistNumberValueForMouseX: 2 Y: 1 from: dict key: @"SqueakMouseOptionButton1" default: 2 browser: NO]; [self setInfoPlistNumberValueForMouseX: 2 Y: 2 from: dict key: @"SqueakMouseOptionButton2" default: 3 browser: NO]; [self setInfoPlistNumberValueForMouseX: 2 Y: 3 from: dict key: @"SqueakMouseOptionButton3" default: 2 browser: NO]; [self setInfoPlistNumberValueForMouseX: 3 Y: 1 from: dict key: @"SqueakMouseControlButton1" default: 1 browser: NO]; [self setInfoPlistNumberValueForMouseX: 3 Y: 2 from: dict key: @"SqueakMouseControlButton2" default: 3 browser: NO]; [self setInfoPlistNumberValueForMouseX: 3 Y: 3 from: dict key: @"SqueakMouseControlButton3" default: 2 browser: NO]; [self setInfoPlistNumberValueForMouseX: 0 Y: 1 from: dict key: @"SqueakBrowserMouseNoneButton1" default: 1 browser: YES]; [self setInfoPlistNumberValueForMouseX: 0 Y: 2 from: dict key: @"SqueakBrowserMouseNoneButton2" default: 3 browser: YES]; [self setInfoPlistNumberValueForMouseX: 0 Y: 3 from: dict key: @"SqueakBrowserMouseNoneButton3" default: 2 browser: YES]; [self setInfoPlistNumberValueForMouseX: 1 Y: 1 from: dict key: @"SqueakBrowserMouseCmdButton1" default: 3 browser: YES]; [self setInfoPlistNumberValueForMouseX: 1 Y: 2 from: dict key: @"SqueakBrowserMouseCmdButton2" default: 3 browser: YES]; [self setInfoPlistNumberValueForMouseX: 1 Y: 3 from: dict key: @"SqueakBrowserMouseCmdButton3" default: 2 browser: YES]; [self setInfoPlistNumberValueForMouseX: 2 Y: 1 from: dict key: @"SqueakBrowserMouseOptionButton1" default: 2 browser: YES]; [self setInfoPlistNumberValueForMouseX: 2 Y: 2 from: dict key: @"SqueakBrowserMouseOptionButton2" default: 3 browser: YES]; [self setInfoPlistNumberValueForMouseX: 2 Y: 3 from: dict key: @"SqueakBrowserMouseOptionButton3" default: 2 browser: YES]; [self setInfoPlistNumberValueForMouseX: 3 Y: 1 from: dict key: @"SqueakBrowserMouseControlButton1" default: 1 browser: YES]; [self setInfoPlistNumberValueForMouseX: 3 Y: 2 from: dict key: @"SqueakBrowserMouseControlButton2" default: 3 browser: YES]; [self setInfoPlistNumberValueForMouseX: 3 Y: 3 from: dict key: @"SqueakBrowserMouseControlButton3" default: 2 browser: YES]; [pool drain]; } @end /* @"SqueakWindowAttribute" NO @"SqueakWindowHasTitle" NO @"SqueakFloatingWindowGetsFocus" NO @"SqueakEncodingType" NO SqueakUIFlushUseHighPercisionClock SqueakUIFlushPrimaryDeferNMilliseconds SqueakUIFlushSecondaryCleanupDelayMilliseconds SqueakUIFlushSecondaryCheckForPossibleNeedEveryNMilliseconds */ ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXNSView.h ================================================ // // sqSqueakOSXNSView.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Cocoa/Cocoa.h> #include <ApplicationServices/ApplicationServices.h> #import "keyBoardStrokeDetails.h" @class sqSqueakOSXScreenAndWindow; #import "sq.h" @interface sqSqueakOSXNSView : NSOpenGLView <NSTextInputClient> { sqSqueakOSXScreenAndWindow *windowLogic; NSTrackingRectTag squeakTrackingRectForCursor; NSRange inputMark; NSRange inputSelection; keyBoardStrokeDetails* lastSeenKeyBoardStrokeDetails; keyBoardStrokeDetails* lastSeenKeyBoardModifierDetails; BOOL dragInProgress; int dragCount; BOOL firstDrawCompleted; BOOL syncNeeded; NSMutableArray* dragItems; CGDisplayFadeReservationToken fadeToken; NSRect savedScreenBoundsAtTimeOfFullScreen; CGColorSpaceRef colorspace; unsigned int* colorMap32; BOOL clippyIsEmpty; CGRect clippy; } @property (nonatomic,assign) NSTrackingRectTag squeakTrackingRectForCursor; @property (nonatomic,retain) keyBoardStrokeDetails* lastSeenKeyBoardStrokeDetails; @property (nonatomic,retain) keyBoardStrokeDetails* lastSeenKeyBoardModifierDetails; @property (nonatomic,assign) BOOL dragInProgress; @property (nonatomic,assign) int dragCount; @property (nonatomic,retain) NSMutableArray* dragItems; @property (nonatomic,assign) sqSqueakOSXScreenAndWindow *windowLogic; @property (nonatomic,assign) NSRect savedScreenBoundsAtTimeOfFullScreen; - (void) initializeVariables; - (void) fakeKeyDownUp: (NSEvent*) theEvent; - (NSString*) dragFileNameStringAtIndex:(sqInt) index; - (void) ioSetFullScreen: (sqInt) fullScreen; - (void)fadeOut; - (void)fadeIn; - (void) drawImageUsingClip: (CGRect) clip; - (NSUInteger) countNumberOfNoneSqueakImageFilesInDraggedFiles: (id<NSDraggingInfo>)info; - (NSMutableArray *) filterOutSqueakImageFilesFromDraggedFiles: (id<NSDraggingInfo>)info; - (NSMutableArray *) filterSqueakImageFilesFromDraggedFiles: (id<NSDraggingInfo>)info; -(void)setupOpenGL; - (void) drawThelayers; @end #import "SqViewClut.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXNSView.m ================================================ // // sqSqueakOSXNSView.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. // Some code sqUnixQuartz.m -- display via native windows on Mac OS X -*- ObjC -*- // Author: Ian Piumarta <ian.piumarta@squeakland.org> /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <QuartzCore/QuartzCore.h> #import "sqSqueakOSXNSView.h" #import "sqSqueakOSXScreenAndWindow.h" #import "SqueakOSXAppDelegate.h" #import "sqSqueakOSXApplication+events.h" #import "sqSqueakOSXInfoPlistInterface.h" #import "sq.h" #import "sqVirtualMachine.h" //#import <OpenGL/CGLMacro.h> extern SqueakOSXAppDelegate *gDelegateApp; extern struct VirtualMachine* interpreterProxy; static NSString *stringWithCharacter(unichar character) { return [NSString stringWithCharacters: &character length: 1]; } @implementation sqSqueakOSXNSView @synthesize squeakTrackingRectForCursor,lastSeenKeyBoardStrokeDetails, lastSeenKeyBoardModifierDetails,dragInProgress,dragCount,dragItems,windowLogic,savedScreenBoundsAtTimeOfFullScreen; + (NSOpenGLPixelFormat *)defaultPixelFormat { NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFAAccelerated, NSOpenGLPFANoRecovery, NSOpenGLPFABackingStore, 0 }; return[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; } - (void)awakeFromNib { self = [self initWithFrame: self.frame pixelFormat: [[self class] defaultPixelFormat] ]; inputMark = NSMakeRange(NSNotFound, 0); inputSelection = NSMakeRange(0, 0); [self registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; // NSLog(@"registerForDraggedTypes"); dragInProgress = NO; dragCount = 0; dragItems = NULL; clippyIsEmpty = YES; colorspace = CGColorSpaceCreateDeviceRGB(); [self initializeSqueakColorMap]; } - (void) initializeVariables { } - (void) dealloc { [super dealloc]; free(colorMap32); CGColorSpaceRelease(colorspace); } - (BOOL) acceptsFirstResponder { return YES; } - (BOOL)isFlipped { return YES; } - (BOOL)isOpaque { return YES; } - (void)viewDidMoveToWindow { if (self.squeakTrackingRectForCursor) [self removeTrackingRect: self.squeakTrackingRectForCursor]; self.squeakTrackingRectForCursor = [self addTrackingRect: [self bounds] owner: self userData:NULL assumeInside: NO]; } - (void) updateTrackingAreas { [super updateTrackingAreas]; [self removeTrackingRect: self.squeakTrackingRectForCursor]; self.squeakTrackingRectForCursor = [self addTrackingRect: [self bounds] owner: self userData:NULL assumeInside: NO]; } - (void) viewWillStartLiveResize { // [self.window setShowsResizeIndicator: YES]; [[NSCursor arrowCursor] set]; } - (void) viewDidEndLiveResize { // [self.window setShowsResizeIndicator: NO]; [((sqSqueakOSXApplication*) gDelegateApp.squeakApplication).squeakCursor performSelectorOnMainThread: @selector(set) withObject: nil waitUntilDone: NO]; } - (void) drawImageUsingClip: (CGRect) clip { if (clippyIsEmpty){ clippy = clip; clippyIsEmpty = NO; } else { clippy = CGRectUnion(clippy, clip); } syncNeeded = YES; } - (void) drawThelayers { if (syncNeeded) { [self drawRect: NSRectFromCGRect(clippy)]; syncNeeded = NO; clippyIsEmpty = YES; // CGL_MACRO_DECLARE_VARIABLES(); glFlush(); [[self openGLContext] flushBuffer]; } if (!firstDrawCompleted) { firstDrawCompleted = YES; if (getFullScreenFlag() == 0) [self.window makeKeyAndOrderFront: self]; } } -(void)setupOpenGL { // CGL_MACRO_DECLARE_VARIABLES(); // Enable the multithreading CGLContextObj ctx = [[self openGLContext] CGLContextObj]; CGLEnable( ctx, kCGLCEMPEngine); // GLint newSwapInterval = 1; // CGLSetParameter(cgl_ctx, kCGLCPSwapInterval, &newSwapInterval); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glClearColor(1.0, 1.0, 1.0, 1.0); glColor4f(1.0, 1.0, 1.0, 1.0); glDisable(GL_DITHER); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glDisable(GL_STENCIL_TEST); glDisable(GL_FOG); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable (GL_SCISSOR_TEST); glDisable (GL_CULL_FACE); glStencilMask(0); glPixelZoom(1.0,1.0); glEnable(GL_TEXTURE_RECTANGLE_ARB); glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 0.0); glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei( GL_UNPACK_ROW_LENGTH, self.frame.size.width ); GLuint dt = 1; glDeleteTextures(1, &dt); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 1); syncNeeded = NO; } - (void)loadTexturesFrom: (void*) lastBitsIndex subRectangle: (NSRect) subRect { // CGL_MACRO_DECLARE_VARIABLES(); static void *previousLastBitsIndex=null; NSRect r=[self frame]; if (!(previousLastBitsIndex == lastBitsIndex)) { previousLastBitsIndex = lastBitsIndex; glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, r.size.width*r.size.height*4,lastBitsIndex); } glViewport( subRect.origin.x,subRect.origin.y, subRect.size.width,subRect.size.height ); char *subimg = ((char*)lastBitsIndex) + (unsigned int)(subRect.origin.x + (r.size.height-subRect.origin.y-subRect.size.height)*r.size.width)*4; glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, subRect.size.width, subRect.size.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, subimg ); // NSLog(@" draw %f %f %f %f",subRect.origin.x,subRect.origin.y,subRect.size.width,subRect.size.height); } -(void)defineQuad:(NSRect)r { // CGL_MACRO_DECLARE_VARIABLES(); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, 1.0f); glTexCoord2f(0.0f, r.size.height); glVertex2f(-1.0f, -1.0f); glTexCoord2f(r.size.width, r.size.height); glVertex2f(1.0f, -1.0f); glTexCoord2f(r.size.width, 0.0f); glVertex2f(1.0f, 1.0f); glEnd(); } - (void)update // moved or resized { NSRect rect; [super update]; [[self openGLContext] makeCurrentContext]; // CGL_MACRO_DECLARE_VARIABLES(); [[self openGLContext] update]; rect = [self bounds]; glViewport(0, 0, (int) rect.size.width, (int) rect.size.height); glPixelStorei( GL_UNPACK_ROW_LENGTH, rect.size.width ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); [self setNeedsDisplay:true]; } - (void)reshape // scrolled, moved or resized { NSRect rect; [super reshape]; [[self openGLContext] makeCurrentContext]; // CGL_MACRO_DECLARE_VARIABLES(); [[self openGLContext] update]; rect = [self bounds]; glViewport(0, 0, (int) rect.size.width, (int) rect.size.height); glPixelStorei( GL_UNPACK_ROW_LENGTH, rect.size.width ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); [self setNeedsDisplay:true]; } -(void)drawRect:(NSRect)rect { // NSLog(@" draw %f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); sqInt formObj = interpreterProxy->displayObject(); sqInt formPtrOop = interpreterProxy->fetchPointerofObject(0, formObj); void* dispBitsIndex = interpreterProxy->firstIndexableField(formPtrOop); static int inited=NO; if ( dispBitsIndex ) { [[self openGLContext] makeCurrentContext]; if (!inited) { [self setupOpenGL]; inited=YES; } [self loadTexturesFrom:dispBitsIndex subRectangle: rect]; [self defineQuad:rect]; } } - (void)mouseEntered:(NSEvent *)theEvent { [((sqSqueakOSXApplication*) gDelegateApp.squeakApplication).squeakCursor set]; } - (void)mouseExited:(NSEvent *)theEvent { [[NSCursor arrowCursor] set]; } - (void)mouseMoved:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)mouseDragged:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)rightMouseDragged:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)otherMouseDragged:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)scrollWheel:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordWheelEvent: theEvent fromView: self]; } - (void)mouseUp:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)rightMouseUp:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)otherMouseUp:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)mouseDown:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)rightMouseDown:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (void)otherMouseDown:(NSEvent *)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordMouseEvent: theEvent fromView: self]; } - (NSString *) dealWithOpenStepChars: (NSString *) openStep { unichar keyChar; static unichar combiningHelpChar[] = {0x003F, 0x20DD}; keyChar = [openStep characterAtIndex: 0]; //http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/KEYBOARD.TXT switch (keyChar) { case NSUpArrowFunctionKey: keyChar = 30; break; case NSDownArrowFunctionKey: keyChar = 31; break; case NSLeftArrowFunctionKey: keyChar = 28; break; case NSRightArrowFunctionKey: keyChar = 29; break; case NSInsertFunctionKey: return [NSString stringWithCharacters: combiningHelpChar length: 2]; case NSDeleteFunctionKey: keyChar = 0x2326; break; case NSHomeFunctionKey: keyChar = 1; break; case NSEndFunctionKey: keyChar = 4; break; case NSPageUpFunctionKey: keyChar = 0x21DE; break; case NSPageDownFunctionKey: keyChar = 0x21DF; break; case NSClearLineFunctionKey: keyChar = 0x2327; break; case 127: keyChar = 8; break; default: if (keyChar >= NSF1FunctionKey && keyChar <= NSF35FunctionKey) { keyChar = 0; } } return stringWithCharacter(keyChar); } -(void) fakeKeyDownUp: (NSEvent*) theEvent { //http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT //http://www.internet4classrooms.com/mac_ext.gif //http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-571.html keyBoardStrokeDetails *aKeyBoardStrokeDetails = [[keyBoardStrokeDetails alloc] init]; aKeyBoardStrokeDetails.keyCode = [theEvent keyCode]; aKeyBoardStrokeDetails.modifierFlags = [theEvent modifierFlags]; NSArray *down = [[NSArray alloc] initWithObjects: theEvent,nil]; @synchronized(self) { lastSeenKeyBoardStrokeDetails = aKeyBoardStrokeDetails; NSString *possibleConversion = [theEvent characters]; if ([possibleConversion length] > 0) { NSString *c = [self dealWithOpenStepChars: possibleConversion]; [self insertText: c replacementRange: NSMakeRange(NSNotFound, 0)]; } self.lastSeenKeyBoardStrokeDetails = NULL; [self keyUp: theEvent]; } [down release]; } -(void)keyDown:(NSEvent*)theEvent { keyBoardStrokeDetails *aKeyBoardStrokeDetails = [[keyBoardStrokeDetails alloc] init]; aKeyBoardStrokeDetails.keyCode = [theEvent keyCode]; aKeyBoardStrokeDetails.modifierFlags = [theEvent modifierFlags]; NSArray *down = [[NSArray alloc] initWithObjects: theEvent,nil]; @synchronized(self) { lastSeenKeyBoardStrokeDetails = aKeyBoardStrokeDetails; [self interpretKeyEvents: down]; self.lastSeenKeyBoardStrokeDetails = NULL; } [down release]; } -(void)keyUp:(NSEvent*)theEvent { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordKeyUpEvent: theEvent fromView: self]; } /* 10.5 seems only to call insertText:, but 10.6 calls insertText:replacementRange: */ - (void)insertText:(id)aString { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordCharEvent: aString fromView: self]; } - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordCharEvent: aString fromView: self]; } - (void)flagsChanged:(NSEvent *)theEvent { keyBoardStrokeDetails *aKeyBoardStrokeDetails = [[keyBoardStrokeDetails alloc] init]; aKeyBoardStrokeDetails.keyCode = [theEvent keyCode]; aKeyBoardStrokeDetails.modifierFlags = [theEvent modifierFlags]; self.lastSeenKeyBoardModifierDetails = aKeyBoardStrokeDetails; [aKeyBoardStrokeDetails release]; } - (void)doCommandBySelector:(SEL)aSelector { unichar unicode; unsigned short keyCode; NSString *unicodeString; BOOL isFunctionKey = NO; if (self.lastSeenKeyBoardModifierDetails) { isFunctionKey = (self.lastSeenKeyBoardModifierDetails.modifierFlags & NSFunctionKeyMask) == NSFunctionKeyMask; } #define encode(c, k, s) if (aSelector == @selector(s)) { unicode = c; keyCode = k; unicodeString = [NSString stringWithCharacters: &unicode length: 1]; } //http://developer.apple.com/documentation/mac/Text/Text-571.html encode( 8, 51, deleteBackward:) else encode( 8, 51, deleteWordBackward:) else encode(127, 51, deleteForward:) else encode(127, 51, deleteWordForward:) else encode( 8, 51, deleteBackwardByDecomposingPreviousCharacter:) else encode( (isFunctionKey ? 3: 13), (isFunctionKey ? 76: 36), insertNewline:) else encode( 13, 36, insertLineBreak:) else encode( 13, 36, insertNewlineIgnoringFieldEditor:) else encode( 9, 48, insertTab:) else encode( 9, 48, insertBacktab:) else encode( 9, 48, insertTabIgnoringFieldEditor:) else encode( 28, 123, moveLeft:) else encode( 29, 124, moveRight:) else encode( 30, 126, moveUp:) else encode( 31, 125, moveDown:) else encode( 30, 126, moveBackward:) else encode( 31, 125, moveForward:) else encode( 28, 123, moveLeftAndModifySelection:) else encode( 29, 124, moveRightAndModifySelection:) else encode( 30, 126, moveUpAndModifySelection:) else encode( 31, 125, moveDownAndModifySelection:) else encode( 28, 123, moveWordLeftAndModifySelection:) else encode( 29, 124, moveWordRightAndModifySelection:) else encode( 28, 123, moveWordLeft:) else encode( 29, 124, moveWordRight:) else encode( 30, 126, moveParagraphBackwardAndModifySelection:) else encode( 31, 125, moveParagraphForwardAndModifySelection:) else encode( 11, 116, pageUp:) else encode( 12, 121, pageDown:) else encode( 11, 116, pageUpAndModifySelection:) else encode( 12, 121, pageDownAndModifySelection:) else encode( (isFunctionKey ? 11 : 30), (isFunctionKey ? 116 : 126), scrollPageUp:) else encode( (isFunctionKey ? 12 : 31), (isFunctionKey ? 121 : 125), scrollPageDown:) else encode( 1, 115, moveToBeginningOfDocument:) else encode( 4, 119, moveToEndOfDocument:) else encode( (isFunctionKey ? 1 : 28), (isFunctionKey ? 115 : 123), moveToLeftEndOfLine:) else encode( (isFunctionKey ? 4 : 29), (isFunctionKey ? 119 : 124), moveToRightEndOfLine:) else encode( (isFunctionKey ? 1 : 28), (isFunctionKey ? 115 : 123), moveToLeftEndOfLineAndModifySelection:) else encode( (isFunctionKey ? 4 : 29), (isFunctionKey ? 119 : 124), moveToRightEndOfLineAndModifySelection:) else encode( 1, 115, scrollToBeginningOfDocument:) else encode( 4, 119, scrollToEndOfDocument:) else encode( 1, 115, moveToBeginningOfDocumentAndModifySelection:) else encode( 4, 119, moveToEndOfDocumentAndModifySelection:) else encode( 27, 53, cancelOperation:) else encode( 27, 53, cancel:) else encode( 27, 53, complete:) else encode( 27, 71, delete:) else return; @synchronized(self) { keyBoardStrokeDetails *aKeyBoardStrokeDetails = [[keyBoardStrokeDetails alloc] init]; aKeyBoardStrokeDetails.keyCode = keyCode; aKeyBoardStrokeDetails.modifierFlags = self.lastSeenKeyBoardModifierDetails.modifierFlags; lastSeenKeyBoardStrokeDetails = aKeyBoardStrokeDetails; [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordCharEvent: unicodeString fromView: self]; self.lastSeenKeyBoardStrokeDetails = NULL; } } - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { inputMark= NSMakeRange(0, 1); inputSelection= NSMakeRange(NSNotFound, 0); } - (void) unmarkText { inputMark= NSMakeRange(NSNotFound, 0); } - (BOOL) hasMarkedText { return inputMark.location != NSNotFound; } - (NSInteger) conversationIdentifier { return (NSInteger )self; } - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { return nil; } - (NSRange) markedRange { return inputMark; } - (NSRange) selectedRange { return inputSelection; } - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { return NSMakeRect(0,0, 0,0); } - (NSUInteger) characterIndexForPoint: (NSPoint)thePoint { return 0; } - (NSArray *) validAttributesForMarkedText { return nil; } - (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex { return NO; } - (NSMutableArray *) filterSqueakImageFilesFromDraggedFiles: (id<NSDraggingInfo>)info { NSPasteboard *pboard= [info draggingPasteboard]; NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10]; if ([[pboard types] containsObject: NSFilenamesPboardType]) { NSArray *files= [pboard propertyListForType: NSFilenamesPboardType]; NSString *fileName; for (fileName in files) { if ([((sqSqueakOSXApplication*) gDelegateApp.squeakApplication) isImageFile: fileName] == YES) [results addObject: fileName]; } } return results; } - (NSMutableArray *) filterOutSqueakImageFilesFromDraggedFiles: (id<NSDraggingInfo>)info { NSPasteboard *pboard= [info draggingPasteboard]; NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10]; if ([[pboard types] containsObject: NSFilenamesPboardType]) { NSArray *files= [pboard propertyListForType: NSFilenamesPboardType]; NSString *fileName; for (fileName in files) { if ([((sqSqueakOSXApplication*) gDelegateApp.squeakApplication) isImageFile: fileName] == NO) [results addObject: fileName]; } } return results; } - (NSUInteger) countNumberOfNoneSqueakImageFilesInDraggedFiles: (id<NSDraggingInfo>)info { NSArray *files = [self filterOutSqueakImageFilesFromDraggedFiles: info]; return [files count]; } - (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)info { if (self.dragInProgress) return NSDragOperationNone; dragInProgress = YES; self.dragCount = (int) [self countNumberOfNoneSqueakImageFilesInDraggedFiles: info]; if (self.dragCount) [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordDragEvent: DragEnter numberOfFiles: self.dragCount where: [info draggingLocation] windowIndex: self.windowLogic.windowIndex]; return NSDragOperationGeneric; } - (NSDragOperation) draggingUpdated: (id<NSDraggingInfo>)info { if (self.dragCount) [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordDragEvent: DragMove numberOfFiles: self.dragCount where: [info draggingLocation] windowIndex: self.windowLogic.windowIndex]; return NSDragOperationGeneric; } - (void) draggingExited: (id<NSDraggingInfo>)info { if (self.dragCount) [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordDragEvent: DragLeave numberOfFiles: self.dragCount where: [info draggingLocation] windowIndex: self.windowLogic.windowIndex]; self.dragCount = 0; self.dragInProgress = NO; self.dragItems = NULL; } - (BOOL) performDragOperation: (id<NSDraggingInfo>)info { if (self.dragCount) { self.dragItems = [self filterOutSqueakImageFilesFromDraggedFiles: info]; [(sqSqueakOSXApplication *) gDelegateApp.squeakApplication recordDragEvent: DragDrop numberOfFiles: self.dragCount where: [info draggingLocation] windowIndex: self.windowLogic.windowIndex]; } NSArray *images = [self filterSqueakImageFilesFromDraggedFiles: info]; if ([images count] > 0) { for (NSString *item in images ){ NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; LSLaunchURLSpec launchSpec; launchSpec.appURL = (CFURLRef)url; launchSpec.passThruParams = NULL; launchSpec.itemURLs = (CFArrayRef) [NSArray arrayWithObject:[NSURL fileURLWithPath: item]]; launchSpec.launchFlags = kLSLaunchDefaults | kLSLaunchNewInstance; launchSpec.asyncRefCon = NULL; OSErr err = LSOpenFromURLSpec(&launchSpec, NULL); #pragma unused(err) } } dragInProgress = NO; return YES; } - (NSString*) dragFileNameStringAtIndex: (sqInt) index { if (!self.dragItems) return NULL; if (index < 1 || index > [self.dragItems count]) return NULL; NSString *filePath = [self.dragItems objectAtIndex: (NSUInteger) index - 1]; return filePath; } - (BOOL)ignoreModifierKeysWhileDragging { return YES; } - (void) ioSetFullScreen: (sqInt) fullScreen { if ([self isInFullScreenMode] == YES && (fullScreen == 1)) return; if ([self isInFullScreenMode] == NO && (fullScreen == 0)) return; if ([self isInFullScreenMode] == NO && (fullScreen == 1)) { self.savedScreenBoundsAtTimeOfFullScreen = (NSRect) [self bounds]; [self fadeOut]; [self enterFullScreenMode:[NSScreen mainScreen] withOptions: nil]; extern struct VirtualMachine* interpreterProxy; interpreterProxy->fullDisplayUpdate(); [self fadeIn]; } if ([self isInFullScreenMode] == YES && (fullScreen == 0)) { [self fadeOut]; [self exitFullScreenModeWithOptions: NULL]; [self fadeIn]; if ([self.window isKeyWindow] == NO) { [self.window makeKeyAndOrderFront: self]; // NOT SURE IF THIS IS NEEDED, MORE TESTING [self.window setContentSize: self.savedScreenBoundsAtTimeOfFullScreen.size]; } } } - (void)fadeOut { CGDisplayErr err; err = CGAcquireDisplayFadeReservation((CGDisplayReservationInterval)kCGMaxDisplayReservationInterval, &fadeToken); if (err == kCGErrorSuccess) { CGDisplayFade(fadeToken, ((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakUIFadeForFullScreenInSeconds, (CGDisplayBlendFraction)kCGDisplayBlendNormal, (CGDisplayBlendFraction)kCGDisplayBlendSolidColor, 0.0f, 0.0f, 0.0f, TRUE); } } - (void)fadeIn { CGDisplayErr err; err = CGDisplayFade(fadeToken, ((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakUIFadeForFullScreenInSeconds, (CGDisplayBlendFraction)kCGDisplayBlendSolidColor, (CGDisplayBlendFraction)kCGDisplayBlendNormal, 0.0f, 0.0f, 0.0f, TRUE); if (err == kCGErrorSuccess) { CGReleaseDisplayFadeReservation(fadeToken); } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXScreenAndWindow.h ================================================ // // sqSqueakOSXScreenAndWindow.h // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakScreenAndWindow.h" #import "sqSqueakOSXNSView.h" @protocol NSWindowDelegate <NSObject> @end @interface sqSqueakOSXScreenAndWindow : sqSqueakScreenAndWindow <NSWindowDelegate>{ sqSqueakOSXNSView *mainViewOnWindow; } @property (nonatomic,retain) sqSqueakOSXNSView *mainViewOnWindow; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/OSX/sqSqueakOSXScreenAndWindow.m ================================================ // // sqSqueakOSXScreenAndWindow.m // SqueakPureObjc // // Created by John M McIntosh on 09-11-14. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakOSXScreenAndWindow.h" #import "SqueakOSXAppDelegate.h" #import "sqMacHostWindow.h" #import "sqSqueakOSXInfoPlistInterface.h" #import "SqViewBitmapConversion.h" extern SqueakOSXAppDelegate *gDelegateApp; @implementation sqSqueakOSXScreenAndWindow @synthesize mainViewOnWindow; -(id) getMainView { return (sqSqueakOSXNSView*) self.mainViewOnWindow; } - (void) dealloc { [mainViewOnWindow release]; [super dealloc]; } - (void) ioSetFullScreen: (sqInt) fullScreen { [[self getMainView] ioSetFullScreen: fullScreen]; } - (sqInt) ioHasDisplayDepth: (sqInt) depth { if (depth == 1 || depth == 2 || depth == 4 || depth == 8 || depth==16 || depth==32 ) return true; return false; } - (BOOL)windowShouldClose:(id)window { [gDelegateApp.squeakApplication recordWindowEvent: WindowEventClose window: window]; return NO; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Resources-iPad/MainWindow-iPad.xib ================================================ <?xml version="1.0" encoding="UTF-8"?> <archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">512</int> <string key="IBDocument.SystemVersion">10D573</string> <string key="IBDocument.InterfaceBuilderVersion">762</string> <string key="IBDocument.AppKitVersion">1038.29</string> <string key="IBDocument.HIToolboxVersion">460.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string key="NS.object.0">87</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> </object> <object class="NSMutableDictionary" key="IBDocument.Metadata"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys" id="0"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBProxyObject" id="841351856"> <string key="IBProxiedObjectIdentifier">IBFilesOwner</string> <string key="targetRuntimeIdentifier">IBIPadFramework</string> </object> <object class="IBProxyObject" id="64004946"> <string key="IBProxiedObjectIdentifier">IBFirstResponder</string> <string key="targetRuntimeIdentifier">IBIPadFramework</string> </object> <object class="IBUICustomObject" id="664661524"> <string key="targetRuntimeIdentifier">IBIPadFramework</string> </object> <object class="IBUIWindow" id="380026005"> <nil key="NSNextResponder"/> <int key="NSvFlags">1292</int> <object class="NSPSMatrix" key="NSFrameMatrix"/> <string key="NSFrameSize">{768, 1024}</string> <object class="NSColor" key="IBUIBackgroundColor"> <int key="NSColorSpace">1</int> <bytes key="NSRGB">MSAxIDEAA</bytes> </object> <bool key="IBUIOpaque">NO</bool> <bool key="IBUIClearsContextBeforeDrawing">NO</bool> <bool key="IBUIMultipleTouchEnabled">YES</bool> <string key="targetRuntimeIdentifier">IBIPadFramework</string> <bool key="IBUIVisibleAtLaunch">YES</bool> <bool key="IBUIResizesToFullScreen">YES</bool> </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBCocoaTouchOutletConnection" key="connection"> <string key="label">delegate</string> <reference key="source" ref="841351856"/> <reference key="destination" ref="664661524"/> </object> <int key="connectionID">4</int> </object> <object class="IBConnectionRecord"> <object class="IBCocoaTouchOutletConnection" key="connection"> <string key="label">window</string> <reference key="source" ref="664661524"/> <reference key="destination" ref="380026005"/> </object> <int key="connectionID">5</int> </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> <reference key="object" ref="0"/> <reference key="children" ref="1000"/> <nil key="parent"/> </object> <object class="IBObjectRecord"> <int key="objectID">2</int> <reference key="object" ref="380026005"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="841351856"/> <reference key="parent" ref="0"/> <string key="objectName">File's Owner</string> </object> <object class="IBObjectRecord"> <int key="objectID">3</int> <reference key="object" ref="664661524"/> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="64004946"/> <reference key="parent" ref="0"/> </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>-1.CustomClassName</string> <string>-2.CustomClassName</string> <string>2.IBAttributePlaceholdersKey</string> <string>2.IBEditorWindowLastContentRect</string> <string>2.IBPluginDependency</string> <string>3.CustomClassName</string> <string>3.IBPluginDependency</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>UIApplication</string> <string>UIResponder</string> <object class="NSMutableDictionary"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <string>{{362, 376}, {320, 480}}</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>SqueakNoOGLIPhoneAppDelegate</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> <reference key="dict.sortedKeys" ref="0"/> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> </object> <nil key="sourceID"/> <int key="maxID">14</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">SqueakNoOGLIPhoneAppDelegate</string> <string key="superclassName">sqSqueakAppDelegate</string> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>mainView</string> <string>viewController</string> <string>window</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>SqueakUIView</string> <string>SqueakUIController</string> <string>UIWindow</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakNoOGLIPhoneAppDelegate.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">SqueakUIController</string> <string key="superclassName">UIViewController</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">SqueakUIView</string> <string key="superclassName">UIView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/SqueakUIView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">UIApplication</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/iPhone/Classes/sqSqueakIPhoneApplication+Network.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">sqSqueakAppDelegate</string> <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">platforms/Mac OSObjC/vm/Common/Classes/sqSqueakAppDelegate.h</string> </object> </object> </object> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSView.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSError.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">PrintCore.framework/Headers/PDEPluginInterface.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string> </object> </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> <string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string> <integer value="512" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string> <integer value="800" key="NS.object.0"/> </object> <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string> <integer value="3000" key="NS.object.0"/> </object> <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> <string key="IBDocument.LastKnownRelativeProjectPath">SqueakNoOGLIPhone.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> <string key="IBCocoaTouchPluginVersion">87</string> </data> </archive> ================================================ FILE: vm/src/from_squeak/iOS/vm/RoarVMOnIPad.xcodeproj/johnmci.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>9424FF4A0DDC8675009912BF</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array> <dict> <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> <string>946720301261864D00F97C81</string> <key>PBXProjectModuleLabel</key> <string>SqueakPureObjc-Info.plist</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>946720311261864D00F97C81</string> <key>PBXProjectModuleLabel</key> <string>SqueakPureObjc-Info.plist</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>946720321261864D00F97C81</string> <key>history</key> <array> <string>94672008126185F600F97C81</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>Geometry</key> <dict> <key>Frame</key> <string>{{0, 20}, {1346, 877}}</string> <key>PBXModuleWindowStatusBarHidden2</key> <false/> <key>RubberWindowFrame</key> <string>334 110 1346 918 0 0 1680 1028 </string> </dict> </dict> </array> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>22</real> <real>421</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>SCMStatusColumn</string> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>9412CAB20E6C037B00DB8625</string> <string>29B97315FDCFA39411CA2CEA</string> <string>9424FF570DDCB17F009912BF</string> <string>94BCE77E0DDDF61200F38F31</string> <string>94BCE77F0DDDF61200F38F31</string> <string>94883B3F0E0C2B9C005A4738</string> <string>94BCE7840DDDF61200F38F31</string> <string>94BCE6880DDDECC200F38F31</string> <string>9424FF580DDCB18C009912BF</string> <string>9424FF590DDCB198009912BF</string> <string>947E642610AA0E1100D3B69E</string> <string>94C4B82C10C06F0D00CD4F90</string> <string>943B9C9D1235C5120056205E</string> <string>947E647610AA0FF200D3B69E</string> <string>9452D5EF0E044AC2000AD792</string> <string>9452D5F00E044AD1000AD792</string> <string>9424FF5A0DDCB19F009912BF</string> <string>94BCE6640DDDEB5000F38F31</string> <string>94BCE6650DDDEB5000F38F31</string> <string>080E96DDFE201D6D7F000001</string> <string>94E658DC0DDD03FE00358328</string> <string>94E658DF0DDD03FE00358328</string> <string>94E658E20DDD03FE00358328</string> <string>94210B270E956AC200C1A314</string> <string>94E6590F0DDD03FE00358328</string> <string>29B97317FDCFA39411CA2CEA</string> <string>947E64DC10AA18FE00D3B69E</string> <string>29B97323FDCFA39411CA2CEA</string> <string>19C28FACFE9D520D11CA2CBB</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {443, 917}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {460, 935}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>SCMStatusColumn</string> <real>22</real> <string>MainColumn</string> <real>421</real> </array> <key>RubberWindowFrame</key> <string>117 49 1383 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>460pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info-iPhone.plist</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info-iPhone.plist</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>9467202F1261864D00F97C81</string> <key>history</key> <array> <string>94BCE7390DDDEF8200F38F31</string> <string>94547F160DE0AC7D00DD588F</string> <string>945481A60DE2A79200DD588F</string> <string>94B1514E0DE2CE530059F208</string> <string>945E9D7C0DE525E100CDF01E</string> <string>94F8E42E0DE6129D003F4F53</string> <string>94E297D10DECA72F009CF73A</string> <string>94E297D30DECA72F009CF73A</string> <string>94E297D50DECA72F009CF73A</string> <string>94E297D70DECA72F009CF73A</string> <string>94554E670DF1171500FB176B</string> <string>94554E690DF1171500FB176B</string> <string>94554EB80DF1A86A00FB176B</string> <string>94F5C1870DF26EF200099B11</string> <string>94F5C25F0DF42C7600099B11</string> <string>94F5C2600DF42C7600099B11</string> <string>94AB2E6A0E003879006A79E4</string> <string>94AB2E6C0E003879006A79E4</string> <string>945F30FC0E0C763800CFF3DC</string> <string>948704AE0E12CABF00D565C3</string> <string>948704B20E12CABF00D565C3</string> <string>9487071F0E132B1000D565C3</string> <string>94ED7EFA0E6C2ABE00F4DD03</string> <string>94B88C560E81500200C98131</string> <string>94F155570E83EA1F001657CE</string> <string>94F155580E83EA1F001657CE</string> <string>947332EE0EA70E8C003F9084</string> <string>942B77330EA7E642004B266D</string> <string>942B77380EA7E642004B266D</string> <string>942B779B0EA7F2E0004B266D</string> <string>942B779C0EA7F2E0004B266D</string> <string>942B77B90EA800E1004B266D</string> <string>942B77BB0EA800E1004B266D</string> <string>94638CEA0EB16F1100A3F155</string> <string>947E210C0EB28486007957D0</string> <string>9471E48A0EB6C393000AE79D</string> <string>94476EC40EBFAB320095D6D7</string> <string>9478E13D0EC8EB46007096A7</string> <string>94E2DAD40ED2351B00012E92</string> <string>94E2DB270ED2355F00012E92</string> <string>946D973B0FE165B70038846B</string> <string>9421AB550FF1807D008F54E9</string> <string>947E61D610AA049300D3B69E</string> <string>947E61DA10AA049300D3B69E</string> <string>947E61DC10AA049300D3B69E</string> <string>947E644910AA0F2C00D3B69E</string> <string>947E644B10AA0F2C00D3B69E</string> <string>947E645010AA0F2C00D3B69E</string> <string>942ABEC510AA34820086D908</string> <string>94BCAD4A10AB981B00F87527</string> <string>94BCAE9010ACA3A300F87527</string> <string>94BCAFC710ACC89100F87527</string> <string>94C887D410ADCC0D007CB39E</string> <string>94C888B710ADE75B007CB39E</string> <string>94C88B6810AF26F8007CB39E</string> <string>94C2074310AF5FB7002F4160</string> <string>94C2091210AF7413002F4160</string> <string>94C2092A10AF769A002F4160</string> <string>94C2092D10AF769A002F4160</string> <string>94C367C010AF9C0A0041953A</string> <string>94C367C210AF9C0A0041953A</string> <string>94C367D110AF9C830041953A</string> <string>94C3696410AFB7550041953A</string> <string>94C3698D10B082DF0041953A</string> <string>94C3699110B082DF0041953A</string> <string>9484F86210B0DCC60038BDC0</string> <string>9484F86510B0DCC60038BDC0</string> <string>9484F8FC10B0E1770038BDC0</string> <string>9484F9CE10B13E1C0038BDC0</string> <string>94CA691410B1CAD8007F207C</string> <string>9456C24F10B2F268000BF3DE</string> <string>9456C25A10B2F2C9000BF3DE</string> <string>9456C32210B32F43000BF3DE</string> <string>9456C34E10B33618000BF3DE</string> <string>9456C3CB10B341F9000BF3DE</string> <string>94F89AFE10B4997900556475</string> <string>94F89BDE10B4B77400556475</string> <string>94F89BE010B4B77400556475</string> <string>94F89C9110B4C0B800556475</string> <string>94D73E5210B5B9CE00F8C034</string> <string>94D73E5410B5B9CE00F8C034</string> <string>94D73E5610B5B9CE00F8C034</string> <string>94D73E5810B5B9CE00F8C034</string> <string>94D73E5A10B5B9CE00F8C034</string> <string>94D73E5C10B5B9CE00F8C034</string> <string>94D73E5E10B5B9CE00F8C034</string> <string>94D73E6010B5B9CE00F8C034</string> <string>94D73E6210B5B9CE00F8C034</string> <string>94D73E6410B5B9CE00F8C034</string> <string>94D73E6810B5B9CE00F8C034</string> <string>94D73E6A10B5B9CE00F8C034</string> <string>94D73EE610B5CF8400F8C034</string> <string>94D73F4910B5DA4E00F8C034</string> <string>94D73FA010B5E5A200F8C034</string> <string>94D73FAD10B5E69900F8C034</string> <string>94D73FB510B5E6DA00F8C034</string> <string>94D7401510B5F8AF00F8C034</string> <string>94D7403810B5FDDB00F8C034</string> <string>94D7403A10B5FDDB00F8C034</string> <string>94D7403C10B5FDDB00F8C034</string> <string>94D740B210B6242000F8C034</string> <string>9406E7E210B663F4002F81F2</string> <string>9406E87110B66A74002F81F2</string> <string>9406E8CC10B67499002F81F2</string> <string>94D715CB10B723B200F69A71</string> <string>94D7174110B72FDF00F69A71</string> <string>94D7177D10B73A3800F69A71</string> <string>94D7178410B73A3800F69A71</string> <string>94D7178610B73A3800F69A71</string> <string>94D7178810B73A3800F69A71</string> <string>94D7178A10B73A3800F69A71</string> <string>94D7178C10B73A3800F69A71</string> <string>94D7179110B73A3800F69A71</string> <string>94D717BE10B73DD900F69A71</string> <string>94D717F810B743B800F69A71</string> <string>94D7183810B74BF300F69A71</string> <string>94D7183A10B74BF300F69A71</string> <string>94A1B2AA10B9E92A00C64473</string> <string>94A1B41E10BA05E600C64473</string> <string>94862F8310BA182500CAA2EB</string> <string>94862F9E10BA1A0100CAA2EB</string> <string>9486302A10BA247200CAA2EB</string> <string>9492450510BA42EF00E726F5</string> <string>9492450710BA42EF00E726F5</string> <string>9492450910BA42EF00E726F5</string> <string>949245B210BA4A6200E726F5</string> <string>945C4D7C10BB0A8500548CC1</string> <string>945C4EAC10BB348300548CC1</string> <string>9428BBAD10BB50E200DAD287</string> <string>9428BC5510BB74BF00DAD287</string> <string>9428BC5710BB74BF00DAD287</string> <string>9428BF3810BBC2ED00DAD287</string> <string>9428BF4F10BBCAAC00DAD287</string> <string>9473A34810BBD84100ED7D00</string> <string>94F5F29110BC518B00847EEE</string> <string>94F5F29210BC518B00847EEE</string> <string>94F5F29410BC518B00847EEE</string> <string>94F5F29510BC518B00847EEE</string> <string>94F5F2A810BC539700847EEE</string> <string>941441FD10BC817D0088F8AC</string> <string>9414420110BC817D0088F8AC</string> <string>9414425110BC8A620088F8AC</string> <string>949198B010BC8DFC00C629D1</string> <string>949198C910BC8FBB00C629D1</string> <string>94D16BFC10BCEFEE00A69A89</string> <string>94D16BFE10BCEFEE00A69A89</string> <string>94D16C2A10BCF28A00A69A89</string> <string>94D16C4010BCF3E100A69A89</string> <string>94D16CA310BCF93000A69A89</string> <string>9430325510BD0B6D0045D33B</string> <string>9430329A10BD103B0045D33B</string> <string>9430329B10BD103B0045D33B</string> <string>94E4930310BD32D00011AC75</string> <string>94CFE4AF10BE3CA600847DF5</string> <string>94CFE6A910BE63A900847DF5</string> <string>94CFE6B810BE63A900847DF5</string> <string>94CFE6B910BE63A900847DF5</string> <string>94CFE6C010BE63A900847DF5</string> <string>94CFE70110BE683800847DF5</string> <string>9475F4DB10BEF4100047A24B</string> <string>9475F56B10BF20A00047A24B</string> <string>9475F5A710BF25A10047A24B</string> <string>94E583DB10BF43970073FD63</string> <string>94E584AE10BF6EE30073FD63</string> <string>94E584FF10BF79AB0073FD63</string> <string>94E5850010BF79AB0073FD63</string> <string>948FAA0310BF855500BE88CF</string> <string>948FAB5B10BFAD3C00BE88CF</string> <string>94C4B83610C0708F00CD4F90</string> <string>946DA7E010C0A7A400F26F56</string> <string>946DA8D910C0C32800F26F56</string> <string>946DA8DA10C0C32800F26F56</string> <string>946DA8DB10C0C32800F26F56</string> <string>946DAA3810C0D8B700F26F56</string> <string>946DAA3A10C0D8B700F26F56</string> <string>946DAA3C10C0D8B700F26F56</string> <string>946DAB5110C0F2B000F26F56</string> <string>947713D410C45E5F00890A9B</string> <string>94B7898910C4F95E005EA70D</string> <string>9487755C10C64FF100E4AEC5</string> <string>9487755D10C64FF100E4AEC5</string> <string>9402DDB610CE12A5005C2102</string> <string>94D3660B10CEE03900805023</string> <string>94B954A010E6D0F700DC476A</string> <string>9493E98F10EE90BC000C4FB3</string> <string>9448940B10F3E8FF00FB3EC8</string> <string>947923FE1102BE53007C87F8</string> <string>947924171102E275007C87F8</string> <string>9473A95A1102F70B00D135CB</string> <string>9473A9701103BE0A00D135CB</string> <string>948C0820112DE98D0017EE7F</string> <string>94E8EEEA11C94D5D0049D853</string> <string>949DDD6D11D141080017F79B</string> <string>94E745ED11E5346100E90B3A</string> <string>94E745EF11E5346100E90B3A</string> <string>94E746D011E539AF00E90B3A</string> <string>949AD25011E5469C006D6BF4</string> <string>94EF6D6D11E55E31003BA64D</string> <string>94C3AC3E11E6C9D000DBE1E9</string> <string>94F1F6B111EB8E14004B3AE3</string> <string>94D051D3120CE2D40039F8B7</string> <string>9483EAFB121C60C70070C43B</string> <string>94669D8C1225EF670062028C</string> <string>940CA58B1226E9B2008BF48A</string> <string>94329B3E122729BA0090298B</string> <string>94329B3F122729BA0090298B</string> <string>94329B40122729BA0090298B</string> <string>94329B5412272A0C0090298B</string> <string>94329D6412274F350090298B</string> <string>94329D6612274F350090298B</string> <string>94329D6812274F350090298B</string> <string>94329D6A12274F350090298B</string> <string>94329E0E12275AC30090298B</string> <string>94329E0F12275AC30090298B</string> <string>94329FEA122765A60090298B</string> <string>941DE8041227A7600027D899</string> <string>941DE8061227A7600027D899</string> <string>94A3ED241228213E00DF449D</string> <string>94A3ED251228213E00DF449D</string> <string>94A3ED261228213E00DF449D</string> <string>94A3ED891228429500DF449D</string> <string>94D12BE412289C66006B7504</string> <string>940C29221228BDC80009E415</string> <string>947E96231228DB0D0065B3BA</string> <string>947E96251228DB0D0065B3BA</string> <string>944EB0211228E96100EF9C64</string> <string>940590F1122AF9ED009939CE</string> <string>940590F3122AF9ED009939CE</string> <string>94B6A65D122C6E760069D952</string> <string>94A3D790122CB56400DCE9B4</string> <string>943B9D191235C5FE0056205E</string> <string>94E7F9A912375A9600A03A11</string> <string>94E7F9AA12375A9600A03A11</string> <string>94E7F9AB12375A9600A03A11</string> <string>94E99F3412378CD30048557C</string> <string>94E99F8012378DAB0048557C</string> <string>94E9A007123790840048557C</string> <string>94E9A00B123790840048557C</string> <string>94E9A19812381F180048557C</string> <string>94E9A1CB123833B00048557C</string> <string>94077C1E1238400500B9AC1E</string> <string>940BE5991239F2BF00674A11</string> <string>9439F48C123ABD080003F15C</string> <string>9431CA91123B509800C97383</string> <string>9431CB57123B5AF100C97383</string> <string>9431CBD2123B5F9900C97383</string> <string>94FB0AA7123B63D200026016</string> <string>94FB0B55123B6A8300026016</string> <string>94FB0B57123B6A8300026016</string> <string>94FB0B59123B6A8300026016</string> <string>94FB0B5B123B6A8300026016</string> <string>94FB0B5D123B6A8300026016</string> <string>948DB86B123B76F40002F636</string> <string>94607E0E123B7A8C008BA756</string> <string>942F452E123BF48A002B05DF</string> <string>942F4564123BF600002B05DF</string> <string>942F4752123C09BF002B05DF</string> <string>94C16BCB123D78C200A8622A</string> <string>94C16BD5123D7C9300A8622A</string> <string>94BE8B2C123D943800C89FDD</string> <string>94CAA52E123DCAB700651F54</string> <string>94CAA5D8123DDCFE00651F54</string> <string>94CAA648123DE2EF00651F54</string> <string>9489E678123E0AA300ECCD51</string> <string>9489E68F123E0D7900ECCD51</string> <string>94993996123E2D34005260E4</string> <string>94C8D074123EC12D0019544B</string> <string>94C8D0AF123EC4A90019544B</string> <string>94C8D26B123EEE2E0019544B</string> <string>94269EA0123EF54A00CB5A57</string> <string>94269F10123EF9E800CB5A57</string> <string>9426A1E7123EFEDA00CB5A57</string> <string>9426A1F8123F006800CB5A57</string> <string>9426A208123F017D00CB5A57</string> <string>9426A209123F017D00CB5A57</string> <string>9426A228123F01C000CB5A57</string> <string>9451E5AE123F051700B4119F</string> <string>9451E5C5123F062B00B4119F</string> <string>9451E5D5123F07C100B4119F</string> <string>94FF88971240458F00B1021A</string> <string>94FF88981240458F00B1021A</string> <string>94FF88991240458F00B1021A</string> <string>944B0D451248105F00CA74EA</string> <string>944B0D461248105F00CA74EA</string> <string>949CDD0612496F030034C107</string> <string>949CDD0712496F030034C107</string> <string>949CDD0812496F030034C107</string> <string>947CB8991249932E00131713</string> <string>947CB8B81249949B00131713</string> <string>9472586B1254FECD00A8DE45</string> <string>9472586C1254FECD00A8DE45</string> <string>941C7389125BE0BC00CF8153</string> <string>941C738A125BE0BC00CF8153</string> <string>941C738B125BE0BC00CF8153</string> <string>941C738C125BE0BC00CF8153</string> <string>941C738D125BE0BC00CF8153</string> <string>941C738E125BE0BC00CF8153</string> <string>941C738F125BE0BC00CF8153</string> <string>941C7390125BE0BC00CF8153</string> <string>941C7391125BE0BC00CF8153</string> <string>94CAC151125FBC1400CF9255</string> <string>94671FFD12617CFE00F97C81</string> <string>946720241261864D00F97C81</string> <string>946720251261864D00F97C81</string> <string>946720271261864D00F97C81</string> <string>946720291261864D00F97C81</string> <string>9467202B1261864D00F97C81</string> <string>9467202C1261864D00F97C81</string> <string>9467202D1261864D00F97C81</string> <string>9467202E1261864D00F97C81</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {918, 708}}</string> <key>RubberWindowFrame</key> <string>117 49 1383 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>708pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 713}, {918, 222}}</string> <key>RubberWindowFrame</key> <string>117 49 1383 976 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>222pt</string> </dict> </array> <key>Proportion</key> <string>918pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>9467200012617CFE00F97C81</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>9467200112617CFE00F97C81</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>308381261.54535502</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>9424FF6E0DDCB226009912BF</string> <string>1C530D57069F1CE1000CFCEE</string> <string>946720301261864D00F97C81</string> <string>/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc.xcodeproj</string> </array> <key>WindowString</key> <string>117 49 1383 976 0 0 1680 1028 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1366, 463}}</string> <key>RubberWindowFrame</key> <string>51 60 1366 968 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>463pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 468}, {1366, 459}}</string> <key>RubberWindowFrame</key> <string>51 60 1366 968 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>459pt</string> </dict> </array> <key>Proportion</key> <string>927pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9424FF6E0DDCB226009912BF</string> <string>9467200212617CFE00F97C81</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowString</key> <string>51 60 1366 968 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9424FF6E0DDCB226009912BF</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {544, 394}}</string> <string>{{544, 0}, {764, 394}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1308, 394}}</string> <string>{{0, 394}, {1308, 528}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1308, 922}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>262</real> <string>Value</string> <real>191</real> <string>Summary</string> <real>286</real> </array> <key>Frame</key> <string>{{544, 0}, {764, 394}}</string> <key>RubberWindowFrame</key> <string>499 65 1308 963 0 0 1680 1028 </string> </dict> <key>RubberWindowFrame</key> <string>499 65 1308 963 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>922pt</string> </dict> </array> <key>Proportion</key> <string>922pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>946720331261864D00F97C81</string> <string>1C162984064C10D400B95A72</string> <string>946720341261864D00F97C81</string> <string>946720351261864D00F97C81</string> <string>946720361261864D00F97C81</string> <string>946720371261864D00F97C81</string> <string>946720381261864D00F97C81</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>499 65 1308 963 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>sqSqueakOSXApplication.m</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1417, 604}}</string> <key>RubberWindowFrame</key> <string>-29 -234 1417 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>1417pt</string> </dict> </array> <key>Proportion</key> <string>604pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 609}, {1417, 374}}</string> <key>RubberWindowFrame</key> <string>-29 -234 1417 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>374pt</string> </dict> </array> <key>Proportion</key> <string>983pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>9467200312617CFE00F97C81</string> <string>9467200412617CFE00F97C81</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>-29 -234 1417 1024 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1273, 856}}</string> <key>RubberWindowFrame</key> <string>105 93 1273 897 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>856pt</string> </dict> </array> <key>Proportion</key> <string>856pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>947CB8B1124993E000131713</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>105 93 1273 897 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.snapshots</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>945480600DE1484B00DD588F</string> <key>PBXProjectModuleLabel</key> <string>Snapshots</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1593, 926}}</string> <key>RubberWindowFrame</key> <string>-19 61 1593 967 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>926pt</string> </dict> </array> <key>Proportion</key> <string>926pt</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>945480610DE1484B00DD588F</string> <string>94F7102110C332830095BDD8</string> <string>945480600DE1484B00DD588F</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>-19 61 1593 967 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>945480610DE1484B00DD588F</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.scm</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>sqSqueakOSXApplication.m</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1582, 220}}</string> <key>RubberWindowFrame</key> <string>98 4 1582 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>220pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXCVSModuleFilterTypeKey</key> <integer>1031</integer> <key>PBXCVSModuleTreeModuleColumnData</key> <dict> <key>PBXCVSModuleTreeModuleColumnWidthsKey</key> <array> <real>1000</real> <real>56</real> <real>63</real> <real>60</real> <real>63</real> <real>139</real> </array> <key>PBXCVSModuleTreeModuleColumnsKey</key> <array> <string>Name</string> <string>Status</string> <string>Update</string> <string>Revision</string> <string>Author</string> <string>Date</string> </array> </dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM Results</string> <key>SCMActivityViewerShowingDefaultKey</key> <string>{{0, 652}, {1582, 106}}</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 225}, {1582, 758}}</string> <key>RubberWindowFrame</key> <string>98 4 1582 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>758pt</string> </dict> </array> <key>Proportion</key> <string>983pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9488792B0E0F2F8000555242</string> <string>947CB89E1249932E00131713</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>98 4 1582 1024 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9488792B0E0F2F8000555242</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>275</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> <string>1C3E0DCA080725EA00A55177</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {275, 829}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {292, 847}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>275</real> </array> <key>RubberWindowFrame</key> <string>7 60 1661 888 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>292pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{297, 0}, {1364, 847}}</string> <key>RubberWindowFrame</key> <string>7 60 1661 888 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>1364pt</string> </dict> </array> <key>Proportion</key> <string>847pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>949FAC8E116406F800A106F0</string> <string>949FAC8F116406F800A106F0</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>7 60 1661 888 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>949FAC8E116406F800A106F0</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, project classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - sqSqueakIPhoneApplication</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {870, 155}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {1122, 883}}</string> <key>MembersFrame</key> <string>{{0, 160}, {870, 723}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>593</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>RubberWindowFrame</key> <string>28 117 1122 903 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>883pt</string> </dict> </array> <key>Proportion</key> <string>883pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>94269F3A123EFC1B00CB5A57</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>28 117 1122 903 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>949E5F260DE3F297007388E0</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1293, 860}}</string> <key>RubberWindowFrame</key> <string>268 92 1293 901 0 0 1680 1028 </string> <key>XCRefactoringSplitViewLowerHeight</key> <real>394</real> <key>XCRefactoringSplitViewTotalHeight</key> <real>800</real> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>860pt</string> </dict> </array> <key>Proportion</key> <string>860pt</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>949E5F270DE3F297007388E0</string> <string>941C7371125BE08800CF8153</string> <string>949E5F260DE3F297007388E0</string> </array> <key>WindowString</key> <string>268 92 1293 901 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>949E5F270DE3F297007388E0</string> <key>WindowToolIsVisible</key> <false/> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/RoarVMOnIPad.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1118, 880}}"; sepNavSelRange = "{3090, 0}"; sepNavVisRange = "{0, 3388}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {943, 3471}}"; sepNavSelRange = "{2481, 8}"; sepNavVisRange = "{1560, 2001}"; sepNavWindowFrame = "{{254, 4}, {1426, 1019}}"; }; }; 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */ = { activeExec = 0; executables = ( 9424FF3E0DDC8654009912BF /* Squeak */, ); }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeArchitecturePreference = armv6; activeBuildConfigurationName = Debug; activeExecutable = 947E62FD10AA098300D3B69E /* SqueakPureObjc */; activeSDKPreference = macosx10.5; activeTarget = 947E626F10AA098300D3B69E /* SqueakPureObjc */; addToTargets = ( 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */, ); breakpoints = ( 94D7181B10B74A2500F69A71 /* sqSqueakOSXNSView.m:488 */, 94D7181D10B74A2600F69A71 /* sqSqueakOSXNSView.m:484 */, 94D7182310B74A2900F69A71 /* sqSqueakOSXNSView.m:472 */, 94D7182910B74A4A00F69A71 /* sqSqueakOSXNSView.m:460 */, 94D7182D10B74A4E00F69A71 /* sqSqueakOSXNSView.m:468 */, 94D7183310B74BD100F69A71 /* sqSqueakOSXNSView.m:500 */, 94A1B1B810B9C1A800C64473 /* sqMacUIEventsUniversal.c:1429 */, 945C4E6310BB29B500548CC1 /* sqSqueakFileDirectoryInterface.m:118 */, 945C4E8010BB2CE000548CC1 /* sqSqueakFileDirectoryInterface.m:102 */, 9428BC5C10BB760200DAD287 /* sqSqueakOSXApplication+clipboard.m:59 */, 9428BCDC10BB937100DAD287 /* sqSqueakFileDirectoryInterface.m:218 */, 9428BD7010BBA1DC00DAD287 /* sqSqueakFileDirectoryInterface.m:179 */, 9428BD7710BBA26000DAD287 /* sqSqueakFileDirectoryInterface.m:204 */, 94F5F28710BC517200847EEE /* sqSqueakOSXNSView.m:455 */, 94F5F28B10BC517500847EEE /* sqSqueakOSXNSView.m:476 */, 94F5F28D10BC517700847EEE /* sqSqueakOSXNSView.m:480 */, 946DA99210C0CE1900F26F56 /* sqSqueakOSXDropAPI.m:79 */, 946DAB1210C0F00400F26F56 /* sqMacUnixExternalPrims.m:219 */, 9476030E10C375C300B621C9 /* sqSqueakOSXApplication.m:259 */, 9476031010C375C600B621C9 /* sqSqueakOSXApplication.m:264 */, 947713B610C45C0A00890A9B /* Queue.m:117 */, 9458511410F03996001401E7 /* sqMacExtendedClipboard.m:101 */, 9458523210F040A0001401E7 /* sqMacExtendedClipboard.m:37 */, 9458523410F040A1001401E7 /* sqMacExtendedClipboard.m:45 */, 9458523610F040A2001401E7 /* sqMacExtendedClipboard.m:50 */, 9458523A10F040AF001401E7 /* sqMacExtendedClipboard.m:72 */, 9458524810F04272001401E7 /* sqMacExtendedClipboard.m:88 */, 9458527F10F045FB001401E7 /* sqSqueakIPhoneClipboardAPI.m:31 */, 9458528110F045FC001401E7 /* sqSqueakIPhoneClipboardAPI.m:24 */, 9458528310F045FD001401E7 /* sqSqueakIPhoneClipboardAPI.m:17 */, 9496D5CD10FAFA29007762DE /* sqSqueakOSXNSView.m:375 */, 940CD113110E3E6500A9344A /* sqSqueakOSXDropAPI.m:53 */, 94C0D1AC112D5DAE00213581 /* sqSqueakScreenAPI.m:79 */, 941C24EF1198BBE3008BF398 /* sqSqueakScreenAndWindow.m:96 */, 947CB8D01249955E00131713 /* sqSqueakFileDirectoryInterface.m:150 */, ); codeSenseManager = 9424FF430DDC8673009912BF /* Code sense */; executables = ( 9424FF3E0DDC8654009912BF /* Squeak */, 947E62FD10AA098300D3B69E /* SqueakPureObjc */, 948774A910C64DD800E4AEC5 /* SqueakPureObjc64*64 */, ); expressions = ( pluginExports, ); ignoreBreakpointsInProjectsDict = { SqueakVMUNIXPATHS = Ignored; }; perUserDictionary = { "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 401, 20, 301, 301, 232, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXBreakpointsDataSource_ActionID, PBXBreakpointsDataSource_TypeID, PBXBreakpointsDataSource_BreakpointID, PBXBreakpointsDataSource_UseID, PBXBreakpointsDataSource_LocationID, PBXBreakpointsDataSource_ConditionID, PBXBreakpointsDataSource_IgnoreCountID, PBXBreakpointsDataSource_ContinueID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXBookmarksDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBookmarksDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 200, 481, ); PBXFileTableDataSourceColumnsKey = ( PBXBookmarksDataSource_LocationID, PBXBookmarksDataSource_NameID, PBXBookmarksDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 734, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 737, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 679, 20, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_FiletypeID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 574, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolTypeIconID; PBXFileTableDataSourceColumnWidthsKey = ( 16, 200, 50, 534.20849609375, ); PBXFileTableDataSourceColumnsKey = ( PBXSymbolsDataSource_SymbolTypeIconID, PBXSymbolsDataSource_SymbolNameID, PBXSymbolsDataSource_SymbolTypeID, PBXSymbolsDataSource_ReferenceNameID, ); }; PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 839, 20, 48.16259765625, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_SCM_ColumnID, PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 725, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 308378853; PBXWorkspaceStateSaveDate = 308378853; }; perUserProjectItems = { 9402DDB610CE12A5005C2102 /* PBXTextBookmark */ = 9402DDB610CE12A5005C2102 /* PBXTextBookmark */; 940590F1122AF9ED009939CE /* PBXTextBookmark */ = 940590F1122AF9ED009939CE /* PBXTextBookmark */; 940590F3122AF9ED009939CE /* PBXTextBookmark */ = 940590F3122AF9ED009939CE /* PBXTextBookmark */; 9406E7E210B663F4002F81F2 /* PBXTextBookmark */ = 9406E7E210B663F4002F81F2 /* PBXTextBookmark */; 9406E87110B66A74002F81F2 /* PBXTextBookmark */ = 9406E87110B66A74002F81F2 /* PBXTextBookmark */; 9406E8CC10B67499002F81F2 /* PBXTextBookmark */ = 9406E8CC10B67499002F81F2 /* PBXTextBookmark */; 94077C1E1238400500B9AC1E /* PBXTextBookmark */ = 94077C1E1238400500B9AC1E /* PBXTextBookmark */; 940BE5991239F2BF00674A11 /* PBXTextBookmark */ = 940BE5991239F2BF00674A11 /* PBXTextBookmark */; 940C29221228BDC80009E415 /* PBXTextBookmark */ = 940C29221228BDC80009E415 /* PBXTextBookmark */; 940CA58B1226E9B2008BF48A /* PBXTextBookmark */ = 940CA58B1226E9B2008BF48A /* PBXTextBookmark */; 941441FD10BC817D0088F8AC /* PBXTextBookmark */ = 941441FD10BC817D0088F8AC /* PBXTextBookmark */; 9414420110BC817D0088F8AC /* PBXTextBookmark */ = 9414420110BC817D0088F8AC /* PBXTextBookmark */; 9414425110BC8A620088F8AC /* PBXBookmark */ = 9414425110BC8A620088F8AC /* PBXBookmark */; 941C7389125BE0BC00CF8153 /* PBXTextBookmark */ = 941C7389125BE0BC00CF8153 /* PBXTextBookmark */; 941C738A125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738A125BE0BC00CF8153 /* PBXTextBookmark */; 941C738B125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738B125BE0BC00CF8153 /* PBXTextBookmark */; 941C738C125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738C125BE0BC00CF8153 /* PBXTextBookmark */; 941C738D125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738D125BE0BC00CF8153 /* PBXTextBookmark */; 941C738E125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738E125BE0BC00CF8153 /* PBXTextBookmark */; 941C738F125BE0BC00CF8153 /* PBXTextBookmark */ = 941C738F125BE0BC00CF8153 /* PBXTextBookmark */; 941C7390125BE0BC00CF8153 /* PBXTextBookmark */ = 941C7390125BE0BC00CF8153 /* PBXTextBookmark */; 941C7391125BE0BC00CF8153 /* PBXTextBookmark */ = 941C7391125BE0BC00CF8153 /* PBXTextBookmark */; 941DE8041227A7600027D899 /* PBXTextBookmark */ = 941DE8041227A7600027D899 /* PBXTextBookmark */; 941DE8061227A7600027D899 /* PBXTextBookmark */ = 941DE8061227A7600027D899 /* PBXTextBookmark */; 9421AB550FF1807D008F54E9 /* PBXTextBookmark */ = 9421AB550FF1807D008F54E9 /* PBXTextBookmark */; 94269EA0123EF54A00CB5A57 /* PBXTextBookmark */ = 94269EA0123EF54A00CB5A57 /* PBXTextBookmark */; 94269F10123EF9E800CB5A57 /* PBXTextBookmark */ = 94269F10123EF9E800CB5A57 /* PBXTextBookmark */; 9426A1E7123EFEDA00CB5A57 /* PBXTextBookmark */ = 9426A1E7123EFEDA00CB5A57 /* PBXTextBookmark */; 9426A1F8123F006800CB5A57 /* PBXTextBookmark */ = 9426A1F8123F006800CB5A57 /* PBXTextBookmark */; 9426A208123F017D00CB5A57 /* PlistBookmark */ = 9426A208123F017D00CB5A57 /* PlistBookmark */; 9426A209123F017D00CB5A57 /* PBXTextBookmark */ = 9426A209123F017D00CB5A57 /* PBXTextBookmark */; 9426A228123F01C000CB5A57 /* PBXTextBookmark */ = 9426A228123F01C000CB5A57 /* PBXTextBookmark */; 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */ = 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */; 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */ = 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */; 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */ = 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */; 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */ = 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */; 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */ = 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */; 942ABEC510AA34820086D908 /* PBXTextBookmark */ = 942ABEC510AA34820086D908 /* PBXTextBookmark */; 942B77330EA7E642004B266D /* PBXTextBookmark */ = 942B77330EA7E642004B266D /* PBXTextBookmark */; 942B77380EA7E642004B266D /* PBXTextBookmark */ = 942B77380EA7E642004B266D /* PBXTextBookmark */; 942B779B0EA7F2E0004B266D /* PBXTextBookmark */ = 942B779B0EA7F2E0004B266D /* PBXTextBookmark */; 942B779C0EA7F2E0004B266D /* PBXTextBookmark */ = 942B779C0EA7F2E0004B266D /* PBXTextBookmark */; 942B77B90EA800E1004B266D /* PBXTextBookmark */ = 942B77B90EA800E1004B266D /* PBXTextBookmark */; 942B77BB0EA800E1004B266D /* PBXTextBookmark */ = 942B77BB0EA800E1004B266D /* PBXTextBookmark */; 942F452E123BF48A002B05DF /* PBXTextBookmark */ = 942F452E123BF48A002B05DF /* PBXTextBookmark */; 942F4564123BF600002B05DF /* PBXTextBookmark */ = 942F4564123BF600002B05DF /* PBXTextBookmark */; 942F4752123C09BF002B05DF /* PBXTextBookmark */ = 942F4752123C09BF002B05DF /* PBXTextBookmark */; 9430325510BD0B6D0045D33B /* PBXTextBookmark */ = 9430325510BD0B6D0045D33B /* PBXTextBookmark */; 9430329A10BD103B0045D33B /* PBXTextBookmark */ = 9430329A10BD103B0045D33B /* PBXTextBookmark */; 9430329B10BD103B0045D33B /* PBXTextBookmark */ = 9430329B10BD103B0045D33B /* PBXTextBookmark */; 9431CA91123B509800C97383 /* PBXTextBookmark */ = 9431CA91123B509800C97383 /* PBXTextBookmark */; 9431CB57123B5AF100C97383 /* PBXTextBookmark */ = 9431CB57123B5AF100C97383 /* PBXTextBookmark */; 9431CBD2123B5F9900C97383 /* PBXTextBookmark */ = 9431CBD2123B5F9900C97383 /* PBXTextBookmark */; 94329B3E122729BA0090298B /* PBXTextBookmark */ = 94329B3E122729BA0090298B /* PBXTextBookmark */; 94329B3F122729BA0090298B /* PBXTextBookmark */ = 94329B3F122729BA0090298B /* PBXTextBookmark */; 94329B40122729BA0090298B /* PBXTextBookmark */ = 94329B40122729BA0090298B /* PBXTextBookmark */; 94329B5412272A0C0090298B /* PBXTextBookmark */ = 94329B5412272A0C0090298B /* PBXTextBookmark */; 94329D6412274F350090298B /* PBXTextBookmark */ = 94329D6412274F350090298B /* PBXTextBookmark */; 94329D6612274F350090298B /* PBXTextBookmark */ = 94329D6612274F350090298B /* PBXTextBookmark */; 94329D6812274F350090298B /* PBXTextBookmark */ = 94329D6812274F350090298B /* PBXTextBookmark */; 94329D6A12274F350090298B /* PBXTextBookmark */ = 94329D6A12274F350090298B /* PBXTextBookmark */; 94329E0E12275AC30090298B /* PBXTextBookmark */ = 94329E0E12275AC30090298B /* PBXTextBookmark */; 94329E0F12275AC30090298B /* PBXTextBookmark */ = 94329E0F12275AC30090298B /* PBXTextBookmark */; 94329FEA122765A60090298B /* PBXTextBookmark */ = 94329FEA122765A60090298B /* PBXTextBookmark */; 9439F48C123ABD080003F15C /* PBXTextBookmark */ = 9439F48C123ABD080003F15C /* PBXTextBookmark */; 943B9D191235C5FE0056205E /* PBXTextBookmark */ = 943B9D191235C5FE0056205E /* PBXTextBookmark */; 94476EC40EBFAB320095D6D7 /* PBXTextBookmark */ = 94476EC40EBFAB320095D6D7 /* PBXTextBookmark */; 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */ = 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */; 944B0D451248105F00CA74EA /* PBXTextBookmark */ = 944B0D451248105F00CA74EA /* PBXTextBookmark */; 944B0D461248105F00CA74EA /* PBXTextBookmark */ = 944B0D461248105F00CA74EA /* PBXTextBookmark */; 944EB0211228E96100EF9C64 /* PBXTextBookmark */ = 944EB0211228E96100EF9C64 /* PBXTextBookmark */; 9451E5AE123F051700B4119F /* PBXTextBookmark */ = 9451E5AE123F051700B4119F /* PBXTextBookmark */; 9451E5C5123F062B00B4119F /* PBXTextBookmark */ = 9451E5C5123F062B00B4119F /* PBXTextBookmark */; 9451E5D5123F07C100B4119F /* PBXTextBookmark */ = 9451E5D5123F07C100B4119F /* PBXTextBookmark */; 94547F160DE0AC7D00DD588F /* PBXTextBookmark */ = 94547F160DE0AC7D00DD588F /* PBXTextBookmark */; 945481A60DE2A79200DD588F /* PBXTextBookmark */ = 945481A60DE2A79200DD588F /* PBXTextBookmark */; 94554E670DF1171500FB176B /* PBXTextBookmark */ = 94554E670DF1171500FB176B /* PBXTextBookmark */; 94554E690DF1171500FB176B /* PBXTextBookmark */ = 94554E690DF1171500FB176B /* PBXTextBookmark */; 94554EB80DF1A86A00FB176B /* PBXTextBookmark */ = 94554EB80DF1A86A00FB176B /* PBXTextBookmark */; 9456C24F10B2F268000BF3DE /* PBXTextBookmark */ = 9456C24F10B2F268000BF3DE /* PBXTextBookmark */; 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */ = 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */; 9456C32210B32F43000BF3DE /* PBXTextBookmark */ = 9456C32210B32F43000BF3DE /* PBXTextBookmark */; 9456C34E10B33618000BF3DE /* PBXTextBookmark */ = 9456C34E10B33618000BF3DE /* PBXTextBookmark */; 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */ = 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */; 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */ = 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */; 945C4EAC10BB348300548CC1 /* PBXTextBookmark */ = 945C4EAC10BB348300548CC1 /* PBXTextBookmark */; 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */ = 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */; 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */ = 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */; 94607E0E123B7A8C008BA756 /* PBXTextBookmark */ = 94607E0E123B7A8C008BA756 /* PBXTextBookmark */; 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */ = 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */; 94669D8C1225EF670062028C /* PBXTextBookmark */ = 94669D8C1225EF670062028C /* PBXTextBookmark */; 94671FFD12617CFE00F97C81 /* PBXTextBookmark */ = 94671FFD12617CFE00F97C81 /* PBXTextBookmark */; 94672008126185F600F97C81 /* PBXBookmark */ = 94672008126185F600F97C81 /* PBXBookmark */; 946720241261864D00F97C81 /* PBXTextBookmark */ = 946720241261864D00F97C81 /* PBXTextBookmark */; 946720251261864D00F97C81 /* PBXTextBookmark */ = 946720251261864D00F97C81 /* PBXTextBookmark */; 946720271261864D00F97C81 /* PlistBookmark */ = 946720271261864D00F97C81 /* PlistBookmark */; 946720291261864D00F97C81 /* PlistBookmark */ = 946720291261864D00F97C81 /* PlistBookmark */; 9467202B1261864D00F97C81 /* PBXTextBookmark */ = 9467202B1261864D00F97C81 /* PBXTextBookmark */; 9467202C1261864D00F97C81 /* PlistBookmark */ = 9467202C1261864D00F97C81 /* PlistBookmark */; 9467202D1261864D00F97C81 /* PlistBookmark */ = 9467202D1261864D00F97C81 /* PlistBookmark */; 9467202E1261864D00F97C81 /* PlistBookmark */ = 9467202E1261864D00F97C81 /* PlistBookmark */; 9467202F1261864D00F97C81 /* PlistBookmark */ = 9467202F1261864D00F97C81 /* PlistBookmark */; 946720321261864D00F97C81 /* PlistBookmark */ = 946720321261864D00F97C81 /* PlistBookmark */; 946D973B0FE165B70038846B /* PBXTextBookmark */ = 946D973B0FE165B70038846B /* PBXTextBookmark */; 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */ = 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */; 946DA8D910C0C32800F26F56 /* PBXTextBookmark */ = 946DA8D910C0C32800F26F56 /* PBXTextBookmark */; 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */ = 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */; 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */ = 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */; 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */; 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */; 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */; 946DAB5110C0F2B000F26F56 /* PBXTextBookmark */ = 946DAB5110C0F2B000F26F56 /* PBXTextBookmark */; 9471E48A0EB6C393000AE79D /* PBXTextBookmark */ = 9471E48A0EB6C393000AE79D /* PBXTextBookmark */; 9472586B1254FECD00A8DE45 /* PBXTextBookmark */ = 9472586B1254FECD00A8DE45 /* PBXTextBookmark */; 9472586C1254FECD00A8DE45 /* PBXTextBookmark */ = 9472586C1254FECD00A8DE45 /* PBXTextBookmark */; 947332EE0EA70E8C003F9084 /* PBXTextBookmark */ = 947332EE0EA70E8C003F9084 /* PBXTextBookmark */; 9473A34810BBD84100ED7D00 /* PBXTextBookmark */ = 9473A34810BBD84100ED7D00 /* PBXTextBookmark */; 9473A95A1102F70B00D135CB /* PBXTextBookmark */ = 9473A95A1102F70B00D135CB /* PBXTextBookmark */; 9473A9701103BE0A00D135CB /* PBXTextBookmark */ = 9473A9701103BE0A00D135CB /* PBXTextBookmark */; 9475F4DB10BEF4100047A24B /* PBXTextBookmark */ = 9475F4DB10BEF4100047A24B /* PBXTextBookmark */; 9475F56B10BF20A00047A24B /* PBXTextBookmark */ = 9475F56B10BF20A00047A24B /* PBXTextBookmark */; 9475F5A710BF25A10047A24B /* PBXTextBookmark */ = 9475F5A710BF25A10047A24B /* PBXTextBookmark */; 947713D410C45E5F00890A9B /* PBXTextBookmark */ = 947713D410C45E5F00890A9B /* PBXTextBookmark */; 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */ = 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */; 947923FE1102BE53007C87F8 /* PBXTextBookmark */ = 947923FE1102BE53007C87F8 /* PBXTextBookmark */; 947924171102E275007C87F8 /* PBXTextBookmark */ = 947924171102E275007C87F8 /* PBXTextBookmark */; 947CB8991249932E00131713 /* PBXTextBookmark */ = 947CB8991249932E00131713 /* PBXTextBookmark */; 947CB8B81249949B00131713 /* PBXTextBookmark */ = 947CB8B81249949B00131713 /* PBXTextBookmark */; 947E210C0EB28486007957D0 /* PBXTextBookmark */ = 947E210C0EB28486007957D0 /* PBXTextBookmark */; 947E61D610AA049300D3B69E /* PBXTextBookmark */ = 947E61D610AA049300D3B69E /* PBXTextBookmark */; 947E61DA10AA049300D3B69E /* PBXTextBookmark */ = 947E61DA10AA049300D3B69E /* PBXTextBookmark */; 947E61DC10AA049300D3B69E /* PBXTextBookmark */ = 947E61DC10AA049300D3B69E /* PBXTextBookmark */; 947E644910AA0F2C00D3B69E /* PBXTextBookmark */ = 947E644910AA0F2C00D3B69E /* PBXTextBookmark */; 947E644B10AA0F2C00D3B69E /* PBXTextBookmark */ = 947E644B10AA0F2C00D3B69E /* PBXTextBookmark */; 947E645010AA0F2C00D3B69E /* PBXTextBookmark */ = 947E645010AA0F2C00D3B69E /* PBXTextBookmark */; 947E96231228DB0D0065B3BA /* PBXTextBookmark */ = 947E96231228DB0D0065B3BA /* PBXTextBookmark */; 947E96251228DB0D0065B3BA /* PBXTextBookmark */ = 947E96251228DB0D0065B3BA /* PBXTextBookmark */; 9483EAFB121C60C70070C43B /* PBXTextBookmark */ = 9483EAFB121C60C70070C43B /* PBXTextBookmark */; 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */ = 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */; 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */ = 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */; 9484F8FC10B0E1770038BDC0 /* PBXBookmark */ = 9484F8FC10B0E1770038BDC0 /* PBXBookmark */; 9484F9CE10B13E1C0038BDC0 /* PBXTextBookmark */ = 9484F9CE10B13E1C0038BDC0 /* PBXTextBookmark */; 94862F8310BA182500CAA2EB /* PBXTextBookmark */ = 94862F8310BA182500CAA2EB /* PBXTextBookmark */; 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */ = 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */; 9486302A10BA247200CAA2EB /* PBXTextBookmark */ = 9486302A10BA247200CAA2EB /* PBXTextBookmark */; 948704AE0E12CABF00D565C3 /* PBXTextBookmark */ = 948704AE0E12CABF00D565C3 /* PBXTextBookmark */; 948704B20E12CABF00D565C3 /* PBXTextBookmark */ = 948704B20E12CABF00D565C3 /* PBXTextBookmark */; 9487071F0E132B1000D565C3 /* PBXTextBookmark */ = 9487071F0E132B1000D565C3 /* PBXTextBookmark */; 9487755C10C64FF100E4AEC5 /* PBXTextBookmark */ = 9487755C10C64FF100E4AEC5 /* PBXTextBookmark */; 9487755D10C64FF100E4AEC5 /* PBXTextBookmark */ = 9487755D10C64FF100E4AEC5 /* PBXTextBookmark */; 9489E678123E0AA300ECCD51 /* PBXTextBookmark */ = 9489E678123E0AA300ECCD51 /* PBXTextBookmark */; 9489E68F123E0D7900ECCD51 /* PlistBookmark */ = 9489E68F123E0D7900ECCD51 /* PlistBookmark */; 948C0820112DE98D0017EE7F /* PBXTextBookmark */ = 948C0820112DE98D0017EE7F /* PBXTextBookmark */; 948DB86B123B76F40002F636 /* PBXTextBookmark */ = 948DB86B123B76F40002F636 /* PBXTextBookmark */; 948FAA0310BF855500BE88CF /* PBXTextBookmark */ = 948FAA0310BF855500BE88CF /* PBXTextBookmark */; 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */ = 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */; 949198B010BC8DFC00C629D1 /* PBXTextBookmark */ = 949198B010BC8DFC00C629D1 /* PBXTextBookmark */; 949198C910BC8FBB00C629D1 /* PBXTextBookmark */ = 949198C910BC8FBB00C629D1 /* PBXTextBookmark */; 9492450510BA42EF00E726F5 /* PBXTextBookmark */ = 9492450510BA42EF00E726F5 /* PBXTextBookmark */; 9492450710BA42EF00E726F5 /* PBXTextBookmark */ = 9492450710BA42EF00E726F5 /* PBXTextBookmark */; 9492450910BA42EF00E726F5 /* PBXTextBookmark */ = 9492450910BA42EF00E726F5 /* PBXTextBookmark */; 949245B210BA4A6200E726F5 /* PBXTextBookmark */ = 949245B210BA4A6200E726F5 /* PBXTextBookmark */; 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */ = 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */; 94993996123E2D34005260E4 /* PBXTextBookmark */ = 94993996123E2D34005260E4 /* PBXTextBookmark */; 949AD25011E5469C006D6BF4 /* PBXTextBookmark */ = 949AD25011E5469C006D6BF4 /* PBXTextBookmark */; 949CDD0612496F030034C107 /* PBXTextBookmark */ = 949CDD0612496F030034C107 /* PBXTextBookmark */; 949CDD0712496F030034C107 /* PBXTextBookmark */ = 949CDD0712496F030034C107 /* PBXTextBookmark */; 949CDD0812496F030034C107 /* PBXTextBookmark */ = 949CDD0812496F030034C107 /* PBXTextBookmark */; 949DDD6D11D141080017F79B /* PBXTextBookmark */ = 949DDD6D11D141080017F79B /* PBXTextBookmark */; 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */ = 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */; 94A1B41E10BA05E600C64473 /* PBXTextBookmark */ = 94A1B41E10BA05E600C64473 /* PBXTextBookmark */; 94A3D790122CB56400DCE9B4 /* PBXTextBookmark */ = 94A3D790122CB56400DCE9B4 /* PBXTextBookmark */; 94A3ED241228213E00DF449D /* PBXTextBookmark */ = 94A3ED241228213E00DF449D /* PBXTextBookmark */; 94A3ED251228213E00DF449D /* PBXTextBookmark */ = 94A3ED251228213E00DF449D /* PBXTextBookmark */; 94A3ED261228213E00DF449D /* PBXTextBookmark */ = 94A3ED261228213E00DF449D /* PBXTextBookmark */; 94A3ED891228429500DF449D /* PBXTextBookmark */ = 94A3ED891228429500DF449D /* PBXTextBookmark */; 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */ = 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */; 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */ = 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */; 94B1514E0DE2CE530059F208 /* PBXTextBookmark */ = 94B1514E0DE2CE530059F208 /* PBXTextBookmark */; 94B6A65D122C6E760069D952 /* PBXTextBookmark */ = 94B6A65D122C6E760069D952 /* PBXTextBookmark */; 94B7898910C4F95E005EA70D /* PBXTextBookmark */ = 94B7898910C4F95E005EA70D /* PBXTextBookmark */; 94B88C560E81500200C98131 /* PBXTextBookmark */ = 94B88C560E81500200C98131 /* PBXTextBookmark */; 94B954A010E6D0F700DC476A /* PBXTextBookmark */ = 94B954A010E6D0F700DC476A /* PBXTextBookmark */; 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */ = 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */; 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */ = 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */; 94BCAFC710ACC89100F87527 /* PBXTextBookmark */ = 94BCAFC710ACC89100F87527 /* PBXTextBookmark */; 94BCE7390DDDEF8200F38F31 /* PBXTextBookmark */ = 94BCE7390DDDEF8200F38F31 /* PBXTextBookmark */; 94BE8B2C123D943800C89FDD /* PBXTextBookmark */ = 94BE8B2C123D943800C89FDD /* PBXTextBookmark */; 94C16BCB123D78C200A8622A /* PBXTextBookmark */ = 94C16BCB123D78C200A8622A /* PBXTextBookmark */; 94C16BD5123D7C9300A8622A /* PBXTextBookmark */ = 94C16BD5123D7C9300A8622A /* PBXTextBookmark */; 94C2074310AF5FB7002F4160 /* PBXTextBookmark */ = 94C2074310AF5FB7002F4160 /* PBXTextBookmark */; 94C2091210AF7413002F4160 /* PBXTextBookmark */ = 94C2091210AF7413002F4160 /* PBXTextBookmark */; 94C2092A10AF769A002F4160 /* PBXTextBookmark */ = 94C2092A10AF769A002F4160 /* PBXTextBookmark */; 94C2092D10AF769A002F4160 /* PBXTextBookmark */ = 94C2092D10AF769A002F4160 /* PBXTextBookmark */; 94C367C010AF9C0A0041953A /* PBXTextBookmark */ = 94C367C010AF9C0A0041953A /* PBXTextBookmark */; 94C367C210AF9C0A0041953A /* PBXTextBookmark */ = 94C367C210AF9C0A0041953A /* PBXTextBookmark */; 94C367D110AF9C830041953A /* PBXTextBookmark */ = 94C367D110AF9C830041953A /* PBXTextBookmark */; 94C3696410AFB7550041953A /* PBXTextBookmark */ = 94C3696410AFB7550041953A /* PBXTextBookmark */; 94C3698D10B082DF0041953A /* PBXTextBookmark */ = 94C3698D10B082DF0041953A /* PBXTextBookmark */; 94C3699110B082DF0041953A /* PBXTextBookmark */ = 94C3699110B082DF0041953A /* PBXTextBookmark */; 94C3AC3E11E6C9D000DBE1E9 /* PBXTextBookmark */ = 94C3AC3E11E6C9D000DBE1E9 /* PBXTextBookmark */; 94C4B83610C0708F00CD4F90 /* PBXTextBookmark */ = 94C4B83610C0708F00CD4F90 /* PBXTextBookmark */; 94C887D410ADCC0D007CB39E /* PBXTextBookmark */ = 94C887D410ADCC0D007CB39E /* PBXTextBookmark */; 94C888B710ADE75B007CB39E /* PBXTextBookmark */ = 94C888B710ADE75B007CB39E /* PBXTextBookmark */; 94C88B6810AF26F8007CB39E /* PBXTextBookmark */ = 94C88B6810AF26F8007CB39E /* PBXTextBookmark */; 94C8D074123EC12D0019544B /* PBXTextBookmark */ = 94C8D074123EC12D0019544B /* PBXTextBookmark */; 94C8D0AF123EC4A90019544B /* PBXTextBookmark */ = 94C8D0AF123EC4A90019544B /* PBXTextBookmark */; 94C8D26B123EEE2E0019544B /* PBXTextBookmark */ = 94C8D26B123EEE2E0019544B /* PBXTextBookmark */; 94CA691410B1CAD8007F207C /* PBXTextBookmark */ = 94CA691410B1CAD8007F207C /* PBXTextBookmark */; 94CAA52E123DCAB700651F54 /* PBXTextBookmark */ = 94CAA52E123DCAB700651F54 /* PBXTextBookmark */; 94CAA5D8123DDCFE00651F54 /* PBXTextBookmark */ = 94CAA5D8123DDCFE00651F54 /* PBXTextBookmark */; 94CAA648123DE2EF00651F54 /* PBXTextBookmark */ = 94CAA648123DE2EF00651F54 /* PBXTextBookmark */; 94CAC151125FBC1400CF9255 /* PBXTextBookmark */ = 94CAC151125FBC1400CF9255 /* PBXTextBookmark */; 94CFE4AF10BE3CA600847DF5 /* PBXTextBookmark */ = 94CFE4AF10BE3CA600847DF5 /* PBXTextBookmark */; 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */; 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */; 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */; 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */; 94CFE70110BE683800847DF5 /* PBXTextBookmark */ = 94CFE70110BE683800847DF5 /* PBXTextBookmark */; 94D051D3120CE2D40039F8B7 /* PBXTextBookmark */ = 94D051D3120CE2D40039F8B7 /* PBXTextBookmark */; 94D12BE412289C66006B7504 /* PBXTextBookmark */ = 94D12BE412289C66006B7504 /* PBXTextBookmark */; 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */ = 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */; 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */ = 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */; 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */ = 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */; 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */ = 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */; 94D16CA310BCF93000A69A89 /* PBXTextBookmark */ = 94D16CA310BCF93000A69A89 /* PBXTextBookmark */; 94D3660B10CEE03900805023 /* PBXTextBookmark */ = 94D3660B10CEE03900805023 /* PBXTextBookmark */; 94D715CB10B723B200F69A71 /* PBXTextBookmark */ = 94D715CB10B723B200F69A71 /* PBXTextBookmark */; 94D7174110B72FDF00F69A71 /* PBXTextBookmark */ = 94D7174110B72FDF00F69A71 /* PBXTextBookmark */; 94D7177D10B73A3800F69A71 /* PBXTextBookmark */ = 94D7177D10B73A3800F69A71 /* PBXTextBookmark */; 94D7178410B73A3800F69A71 /* PBXTextBookmark */ = 94D7178410B73A3800F69A71 /* PBXTextBookmark */; 94D7178610B73A3800F69A71 /* PBXTextBookmark */ = 94D7178610B73A3800F69A71 /* PBXTextBookmark */; 94D7178810B73A3800F69A71 /* PBXTextBookmark */ = 94D7178810B73A3800F69A71 /* PBXTextBookmark */; 94D7178A10B73A3800F69A71 /* PBXTextBookmark */ = 94D7178A10B73A3800F69A71 /* PBXTextBookmark */; 94D7178C10B73A3800F69A71 /* PBXTextBookmark */ = 94D7178C10B73A3800F69A71 /* PBXTextBookmark */; 94D7179110B73A3800F69A71 /* PBXTextBookmark */ = 94D7179110B73A3800F69A71 /* PBXTextBookmark */; 94D717BE10B73DD900F69A71 /* PBXTextBookmark */ = 94D717BE10B73DD900F69A71 /* PBXTextBookmark */; 94D717F810B743B800F69A71 /* PBXTextBookmark */ = 94D717F810B743B800F69A71 /* PBXTextBookmark */; 94D7183810B74BF300F69A71 /* PBXTextBookmark */ = 94D7183810B74BF300F69A71 /* PBXTextBookmark */; 94D7183A10B74BF300F69A71 /* PBXTextBookmark */ = 94D7183A10B74BF300F69A71 /* PBXTextBookmark */; 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */ = 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */; 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */ = 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */; 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */ = 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */; 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */ = 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */; 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */ = 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */; 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */ = 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */; 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */ = 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */; 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */ = 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */; 94D7403C10B5FDDB00F8C034 /* PBXTextBookmark */ = 94D7403C10B5FDDB00F8C034 /* PBXTextBookmark */; 94D740B210B6242000F8C034 /* PBXTextBookmark */ = 94D740B210B6242000F8C034 /* PBXTextBookmark */; 94E297D10DECA72F009CF73A /* PBXTextBookmark */ = 94E297D10DECA72F009CF73A /* PBXTextBookmark */; 94E297D30DECA72F009CF73A /* PBXTextBookmark */ = 94E297D30DECA72F009CF73A /* PBXTextBookmark */; 94E297D50DECA72F009CF73A /* PBXTextBookmark */ = 94E297D50DECA72F009CF73A /* PBXTextBookmark */; 94E297D70DECA72F009CF73A /* PBXTextBookmark */ = 94E297D70DECA72F009CF73A /* PBXTextBookmark */; 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */ = 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */; 94E2DB270ED2355F00012E92 /* PBXTextBookmark */ = 94E2DB270ED2355F00012E92 /* PBXTextBookmark */; 94E4930310BD32D00011AC75 /* PBXTextBookmark */ = 94E4930310BD32D00011AC75 /* PBXTextBookmark */; 94E583DB10BF43970073FD63 /* PBXTextBookmark */ = 94E583DB10BF43970073FD63 /* PBXTextBookmark */; 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */ = 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */; 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */ = 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */; 94E5850010BF79AB0073FD63 /* PBXTextBookmark */ = 94E5850010BF79AB0073FD63 /* PBXTextBookmark */; 94E745ED11E5346100E90B3A /* PBXTextBookmark */ = 94E745ED11E5346100E90B3A /* PBXTextBookmark */; 94E745EF11E5346100E90B3A /* PBXTextBookmark */ = 94E745EF11E5346100E90B3A /* PBXTextBookmark */; 94E746D011E539AF00E90B3A /* PBXTextBookmark */ = 94E746D011E539AF00E90B3A /* PBXTextBookmark */; 94E7F9A912375A9600A03A11 /* PBXTextBookmark */ = 94E7F9A912375A9600A03A11 /* PBXTextBookmark */; 94E7F9AA12375A9600A03A11 /* PBXTextBookmark */ = 94E7F9AA12375A9600A03A11 /* PBXTextBookmark */; 94E7F9AB12375A9600A03A11 /* PBXTextBookmark */ = 94E7F9AB12375A9600A03A11 /* PBXTextBookmark */; 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */ = 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */; 94E99F3412378CD30048557C /* PBXTextBookmark */ = 94E99F3412378CD30048557C /* PBXTextBookmark */; 94E99F8012378DAB0048557C /* PBXTextBookmark */ = 94E99F8012378DAB0048557C /* PBXTextBookmark */; 94E9A007123790840048557C /* PBXTextBookmark */ = 94E9A007123790840048557C /* PBXTextBookmark */; 94E9A00B123790840048557C /* PBXTextBookmark */ = 94E9A00B123790840048557C /* PBXTextBookmark */; 94E9A19812381F180048557C /* PBXTextBookmark */ = 94E9A19812381F180048557C /* PBXTextBookmark */; 94E9A1CB123833B00048557C /* PBXTextBookmark */ = 94E9A1CB123833B00048557C /* PBXTextBookmark */; 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */ = 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */; 94EF6D6D11E55E31003BA64D /* PBXTextBookmark */ = 94EF6D6D11E55E31003BA64D /* PBXTextBookmark */; 94F155570E83EA1F001657CE /* PBXTextBookmark */ = 94F155570E83EA1F001657CE /* PBXTextBookmark */; 94F155580E83EA1F001657CE /* PBXTextBookmark */ = 94F155580E83EA1F001657CE /* PBXTextBookmark */; 94F1F6B111EB8E14004B3AE3 /* PBXTextBookmark */ = 94F1F6B111EB8E14004B3AE3 /* PBXTextBookmark */; 94F5C1870DF26EF200099B11 /* PBXTextBookmark */ = 94F5C1870DF26EF200099B11 /* PBXTextBookmark */; 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */ = 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */; 94F5C2600DF42C7600099B11 /* PBXTextBookmark */ = 94F5C2600DF42C7600099B11 /* PBXTextBookmark */; 94F5F29110BC518B00847EEE /* PBXTextBookmark */ = 94F5F29110BC518B00847EEE /* PBXTextBookmark */; 94F5F29210BC518B00847EEE /* PBXTextBookmark */ = 94F5F29210BC518B00847EEE /* PBXTextBookmark */; 94F5F29410BC518B00847EEE /* PBXTextBookmark */ = 94F5F29410BC518B00847EEE /* PBXTextBookmark */; 94F5F29510BC518B00847EEE /* PBXTextBookmark */ = 94F5F29510BC518B00847EEE /* PBXTextBookmark */; 94F5F2A810BC539700847EEE /* PBXTextBookmark */ = 94F5F2A810BC539700847EEE /* PBXTextBookmark */; 94F89AFE10B4997900556475 /* PBXTextBookmark */ = 94F89AFE10B4997900556475 /* PBXTextBookmark */; 94F89BDE10B4B77400556475 /* PBXTextBookmark */ = 94F89BDE10B4B77400556475 /* PBXTextBookmark */; 94F89BE010B4B77400556475 /* PBXTextBookmark */ = 94F89BE010B4B77400556475 /* PBXTextBookmark */; 94F89C9110B4C0B800556475 /* PBXTextBookmark */ = 94F89C9110B4C0B800556475 /* PBXTextBookmark */; 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */ = 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */; 94FB0AA7123B63D200026016 /* PBXTextBookmark */ = 94FB0AA7123B63D200026016 /* PBXTextBookmark */; 94FB0B55123B6A8300026016 /* PBXTextBookmark */ = 94FB0B55123B6A8300026016 /* PBXTextBookmark */; 94FB0B57123B6A8300026016 /* PBXTextBookmark */ = 94FB0B57123B6A8300026016 /* PBXTextBookmark */; 94FB0B59123B6A8300026016 /* PBXTextBookmark */ = 94FB0B59123B6A8300026016 /* PBXTextBookmark */; 94FB0B5B123B6A8300026016 /* PBXTextBookmark */ = 94FB0B5B123B6A8300026016 /* PBXTextBookmark */; 94FB0B5D123B6A8300026016 /* PBXTextBookmark */ = 94FB0B5D123B6A8300026016 /* PBXTextBookmark */; 94FF88971240458F00B1021A /* PBXTextBookmark */ = 94FF88971240458F00B1021A /* PBXTextBookmark */; 94FF88981240458F00B1021A /* PBXTextBookmark */ = 94FF88981240458F00B1021A /* PBXTextBookmark */; 94FF88991240458F00B1021A /* PBXTextBookmark */ = 94FF88991240458F00B1021A /* PBXTextBookmark */; }; sourceControlManager = 9424FF420DDC8673009912BF /* Source Control */; userBookmarkGroup = 94B8F4B910CF5BFF00F0DD6B /* PBXBookmarkGroup */; userBuildSettings = { }; }; 29B97316FDCFA39411CA2CEA /* main.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 804}}"; sepNavSelRange = "{1872, 0}"; sepNavVisRange = "{0, 2149}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1208, 824}}"; sepNavSelRange = "{1850, 8}"; sepNavVisRange = "{0, 1878}"; sepNavWindowFrame = "{{483, 4}, {694, 1008}}"; }; }; 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 1040}}"; sepNavSelRange = "{2139, 0}"; sepNavVisRange = "{2081, 171}"; sepNavWindowFrame = "{{483, -9}, {694, 1008}}"; }; }; 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {2070, 1066}}"; sepNavSelRange = "{2824, 26}"; sepNavVisRange = "{1744, 1329}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {2077, 3549}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1455}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DD6F10CE0E91005C2102 /* SqViewClut.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1066}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1379}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DDB610CE12A5005C2102 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9402DDB710CE12A5005C2102 /* SqView.h */; name = "SqView.h: 50"; rLen = 33; rLoc = 1358; rType = 0; vrLen = 1671; vrLoc = 0; }; 9402DDB710CE12A5005C2102 /* SqView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqView.h; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqView.h"; sourceTree = "<absolute>"; }; 9402F2AE0F3F9BB900F3D637 /* PDColoredProgressView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 546}}"; sepNavSelRange = "{1081, 6}"; sepNavVisRange = "{31, 1299}"; }; }; 9402F2AF0F3F9BB900F3D637 /* PDColoredProgressView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {964, 1547}}"; sepNavSelRange = "{3465, 0}"; sepNavVisRange = "{2282, 1236}"; sepNavWindowFrame = "{{204, 6}, {1346, 974}}"; }; }; 9402F2C50F3F9C5600F3D637 /* drawing.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1492, 897}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1669}"; }; }; 940590F1122AF9ED009939CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940590F2122AF9ED009939CE /* macvideo.cpp */; name = "macvideo.cpp: 883"; rLen = 30; rLoc = 41143; rType = 0; vrLen = 5248; vrLoc = 36665; }; 940590F2122AF9ED009939CE /* macvideo.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = macvideo.cpp; path = /opt/intel/Compiler/11.1/076/Frameworks/tbb/examples/common/gui/macvideo.cpp; sourceTree = "<absolute>"; }; 940590F3122AF9ED009939CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940590F4122AF9ED009939CE /* mglPrivateCreateTexture.c */; name = "mglPrivateCreateTexture.c: 216"; rLen = 19; rLoc = 7694; rType = 0; vrLen = 2995; vrLoc = 6467; }; 940590F4122AF9ED009939CE /* mglPrivateCreateTexture.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mglPrivateCreateTexture.c; path = /Users/johnmci/Shared/mglPrivateCreateTexture.c; sourceTree = "<absolute>"; }; 9406E7E210B663F4002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36A6D10B091BB0041953A /* NSCursor.h */; name = "NSCursor.h: 75"; rLen = 41; rLoc = 3288; rType = 0; vrLen = 1499; vrLoc = 1836; }; 9406E87110B66A74002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87210B66A74002F81F2 /* SqueakInterpreterEventSensor.h */; name = "SqueakInterpreterEventSensor.h: 11"; rLen = 8; rLoc = 416; rType = 0; vrLen = 555; vrLoc = 0; }; 9406E87210B66A74002F81F2 /* SqueakInterpreterEventSensor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakInterpreterEventSensor.h; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakInterpreterEventSensor.h"; sourceTree = "<absolute>"; }; 9406E87510B66A74002F81F2 /* SqueakInterpreterEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreterEventSensor.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakInterpreterEventSensor.m"; sourceTree = "<absolute>"; }; 9406E87710B66A74002F81F2 /* SqViewEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewEventSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewEventSensor.m"; sourceTree = "<absolute>"; }; 9406E8CC10B67499002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E8CD10B67499002F81F2 /* NSTextStorageScripting.h */; name = "NSTextStorageScripting.h: 21"; rLen = 25; rLoc = 417; rType = 0; vrLen = 620; vrLoc = 0; }; 9406E8CD10B67499002F81F2 /* NSTextStorageScripting.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextStorageScripting.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextStorageScripting.h; sourceTree = "<absolute>"; }; 9406E8D110B67499002F81F2 /* NSRange.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSRange.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRange.h; sourceTree = "<absolute>"; }; 94077C1E1238400500B9AC1E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */; name = "sqSqueakOSXApplication+cursor.m: 79"; rLen = 0; rLoc = 3281; rType = 0; vrLen = 1906; vrLoc = 1937; }; 940BE5791239F10000674A11 /* SqueakUIViewCALayer.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 790}}"; sepNavSelRange = "{1808, 26}"; sepNavVisRange = "{0, 2012}"; }; }; 940BE57A1239F10000674A11 /* SqueakUIViewCALayer.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1440, 1703}}"; sepNavSelRange = "{3908, 13}"; sepNavVisRange = "{392, 2904}"; sepNavWindowFrame = "{{170, 4}, {860, 1024}}"; }; }; 940BE5991239F2BF00674A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */; name = "sqiPhoneScreenAndWindow.m: 59"; rLen = 12; rLoc = 2228; rType = 0; vrLen = 2310; vrLoc = 0; }; 940BE5E71239F50100674A11 /* SqueakUIViewOpenGL.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 1105}}"; sepNavSelRange = "{1885, 0}"; sepNavVisRange = "{706, 2099}"; sepNavWindowFrame = "{{15, 4}, {860, 1024}}"; }; }; 940BE5E81239F50100674A11 /* SqueakUIViewOpenGL.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {943, 2704}}"; sepNavSelRange = "{5746, 0}"; sepNavVisRange = "{5080, 2039}"; sepNavWindowFrame = "{{15, 4}, {860, 1024}}"; }; }; 940C29221228BDC80009E415 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658F80DDD03FE00358328 /* GeniePlugin.c */; name = "GeniePlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1889; vrLoc = 0; }; 940CA5401226E8D5008BF48A /* mpeg3io.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mpeg3io.c; path = /Users/johnmci/Documents/SqueakmpegFullSource/libmpeg/mpeg3io.c; sourceTree = "<absolute>"; }; 940CA58B1226E9B2008BF48A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CA5401226E8D5008BF48A /* mpeg3io.c */; name = "mpeg3io.c: 5"; rLen = 8; rLoc = 48; rType = 0; vrLen = 2211; vrLoc = 0; }; 940CD113110E3E6500A9344A /* sqSqueakOSXDropAPI.m:53 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 53; location = Squeak; modificationTime = 306811868.294592; originalNumberOfMultipleMatches = 1; state = 1; }; 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {950, 801}}"; sepNavSelRange = "{95, 1688}"; sepNavVisRange = "{0, 1839}"; }; }; 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {955, 1378}}"; sepNavSelRange = "{3142, 0}"; sepNavVisRange = "{2103, 2036}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 651}}"; sepNavSelRange = "{1933, 14}"; sepNavVisRange = "{0, 2070}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 832}}"; sepNavSelRange = "{2410, 0}"; sepNavVisRange = "{0, 2404}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 941441FD10BC817D0088F8AC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941441FE10BC817D0088F8AC /* NSSavePanel.h */; name = "NSSavePanel.h: 207"; rLen = 23; rLoc = 10442; rType = 0; vrLen = 3994; vrLoc = 8956; }; 941441FE10BC817D0088F8AC /* NSSavePanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSavePanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSavePanel.h; sourceTree = "<absolute>"; }; 9414420010BC817D0088F8AC /* NSPanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPanel.h; sourceTree = "<absolute>"; }; 9414420110BC817D0088F8AC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9414420210BC817D0088F8AC /* NSOpenPanel.h */; name = "NSOpenPanel.h: 43"; rLen = 24; rLoc = 877; rType = 0; vrLen = 1896; vrLoc = 0; }; 9414420210BC817D0088F8AC /* NSOpenPanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSOpenPanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSOpenPanel.h; sourceTree = "<absolute>"; }; 9414425110BC8A620088F8AC /* PBXBookmark */ = { isa = PBXBookmark; fRef = 94F3A9690E6BFA7C00E0B12A /* Squeak.png */; }; 941724420F36624C0031AF33 /* squeakProxy.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2509}}"; sepNavSelRange = "{3440, 13}"; sepNavVisRange = "{2612, 1371}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 941724430F36624C0031AF33 /* squeakProxy.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1274}}"; sepNavSelRange = "{3291, 34}"; sepNavVisRange = "{1854, 2107}"; }; }; 941C24EF1198BBE3008BF398 /* sqSqueakScreenAndWindow.m:96 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */; functionName = "-ioScreenSize"; hitCount = 0; ignoreCount = 0; lineNumber = 96; location = Squeak; modificationTime = 306811863.5436839; originalNumberOfMultipleMatches = 1; state = 2; }; 941C7389125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */; name = "sqUnixSocket.c: 1273"; rLen = 91; rLoc = 34809; rType = 0; vrLen = 1919; vrLoc = 33997; }; 941C738A125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */; name = "sqSqueakIPhoneApplication+attributes.h: 39"; rLen = 39; rLoc = 1806; rType = 0; vrLen = 1953; vrLoc = 0; }; 941C738B125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */; name = "sqSqueakIPhoneApplication+attributes.m: 62"; rLen = 0; rLoc = 2521; rType = 0; vrLen = 2745; vrLoc = 2069; }; 941C738C125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */; name = "sqSqueakIPhoneApplication+clipboard.h: 44"; rLen = 227; rLoc = 1982; rType = 0; vrLen = 2214; vrLoc = 0; }; 941C738D125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */; name = "sqSqueakOSXApplication+clipboard.h: 42"; rLen = 11; rLoc = 1957; rType = 0; vrLen = 2202; vrLoc = 0; }; 941C738E125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */; name = "sqSqueakiPhoneApplication+sound.m: 72"; rLen = 8; rLoc = 3235; rType = 0; vrLen = 2690; vrLoc = 600; }; 941C738F125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */; name = "sqSqueakMainApplication+attributes.h: 42"; rLen = 14; rLoc = 1867; rType = 0; vrLen = 2027; vrLoc = 0; }; 941C7390125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */; name = "sqSqueakIPhoneApplication+clipboard.m: 13"; rLen = 25; rLoc = 287; rType = 0; vrLen = 1522; vrLoc = 0; }; 941C7391125BE0BC00CF8153 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */; name = "sqSqueakIPhoneApplication+imageReadWrite.m: 68"; rLen = 0; rLoc = 2953; rType = 0; vrLen = 2560; vrLoc = 1667; }; 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */ = { uiCtxt = { sepNavWindowFrame = "{{15, 166}, {1288, 857}}"; }; }; 941DE8041227A7600027D899 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941DE8051227A7600027D899 /* sqUnixQuartzGL.h */; name = "sqUnixQuartzGL.h: 10"; rLen = 0; rLoc = 234; rType = 0; vrLen = 2585; vrLoc = 0; }; 941DE8051227A7600027D899 /* sqUnixQuartzGL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqUnixQuartzGL.h; path = "/Users/johnmci/Documents/SqueakIA32ABIPlugin/platforms/unix/vm-display-Quartz/sqUnixQuartzGL.h"; sourceTree = "<absolute>"; }; 941DE8061227A7600027D899 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941DE8071227A7600027D899 /* bluepony.c */; name = "bluepony.c: 374"; rLen = 0; rLoc = 10642; rType = 0; vrLen = 1270; vrLoc = 10231; }; 941DE8071227A7600027D899 /* bluepony.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = bluepony.c; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/MultiGPUIOSurface/bluepony.c"; sourceTree = "<absolute>"; }; 94210B280E956AC200C1A314 /* ObjectiveCPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 27417}}"; sepNavSelRange = "{50573, 27}"; sepNavVisRange = "{49405, 1113}"; sepNavWindowFrame = "{{50, 470}, {750, 558}}"; }; }; 9421AB550FF1807D008F54E9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949EFD7D0FF17FED00F540EB /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1049; vrLoc = 0; }; 9424FF3E0DDC8654009912BF /* Squeak */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 0; environmentEntries = ( { active = NO; name = NSAutoreleaseHaltOnFreedObject; value = YES; }, { active = NO; name = NSZombieEnabled; value = YES; }, { active = NO; name = NSAutoreleaseFreedObjectCheckEnabled; value = YES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); startupPath = "<<ProductDirectory>>"; variableFormatDictionary = { $cpsr = 1; $cs = 1; $d0 = 1; $d1 = 1; $d10 = 1; $d11 = 1; $d12 = 1; $d13 = 1; $d14 = 1; $d15 = 1; $d2 = 1; $d3 = 1; $d4 = 1; $d5 = 1; $d6 = 1; $d7 = 1; $d8 = 1; $d9 = 1; $ds = 1; $eax = 1; $ebp = 1; $ebx = 1; $ecx = 1; $edi = 1; $edx = 1; $eflags = 1; $eip = 1; $es = 1; $esi = 1; $esp = 1; $fs = 1; $gs = 1; $ip = 1; $lr = 1; $mxcsr = 1; $pc = 1; $r0 = 1; $r1 = 1; $r2 = 1; $r3 = 1; $r4 = 1; $r5 = 1; $r6 = 1; $r7 = 1; $r8 = 1; $r9 = 1; $s0 = 1; $s1 = 1; $s10 = 1; $s11 = 1; $s12 = 1; $s13 = 1; $s14 = 1; $s15 = 1; $s16 = 1; $s17 = 1; $s18 = 1; $s19 = 1; $s2 = 1; $s20 = 1; $s21 = 1; $s22 = 1; $s23 = 1; $s24 = 1; $s25 = 1; $s26 = 1; $s27 = 1; $s28 = 1; $s29 = 1; $s3 = 1; $s30 = 1; $s31 = 1; $s4 = 1; $s5 = 1; $s6 = 1; $s7 = 1; $s8 = 1; $s9 = 1; $sl = 1; $sp = 1; $ss = 1; "actually-void *-sqAllocateMemoryMac" = 2; "data-id-primitiveNSInvocationGetObjectType" = 1; "dateDifference-sqInt-convertToSqueakTime" = 1; "fileSize-off_t-sqAllocateMemoryMac" = 2; "mFormatID-UInt32--[sqSqueakSoundCoreAudio snd_StartRecording:stereo:semaIndex:]" = 5; "possibleLocation-void *-sqAllocateMemoryMac" = 2; "returnValue-struct objc_object * volatile-primitivePerformSelector" = 2; "startOfAnonymousMemory-void *-sqAllocateMemoryMac" = 1; "startOfAnonymousMemoryPageSize-size_t-sqAllocateMemoryMac" = 1; "what-long int--[SqueakProxy forwardInvocation:]" = 1; "why-int-aioPoll" = 1; }; }; 9424FF420DDC8673009912BF /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryName = "http://svn.isqueak.org/"; repositoryNamesForRoots = { "" = SqueakVM; }; }; }; 9424FF430DDC8673009912BF /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 9424FF5B0DDCB1C7009912BF /* sqGnu.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2730}}"; sepNavSelRange = "{11912, 7}"; sepNavVisRange = "{10662, 1331}"; sepNavWindowFrame = "{{15, 4}, {1194, 1019}}"; }; }; 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {880, 2171}}"; sepNavSelRange = "{5526, 13}"; sepNavVisRange = "{1516, 4419}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9424FF5D0DDCB1C7009912BF /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 5915}}"; sepNavSelRange = "{17240, 12}"; sepNavVisRange = "{15657, 1848}"; sepNavWindowFrame = "{{73, 4}, {1326, 1010}}"; }; }; 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 6890}}"; sepNavSelRange = "{7355, 12}"; sepNavVisRange = "{6567, 1343}"; sepNavWindowFrame = "{{15, 38}, {847, 985}}"; }; }; 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 5018}}"; sepNavSelRange = "{12743, 13}"; sepNavVisRange = "{11544, 1334}"; }; }; 9424FF610DDCB1C7009912BF /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3796}}"; sepNavSelRange = "{8117, 13}"; sepNavVisRange = "{7104, 1841}"; sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2106}}"; sepNavSelRange = "{4053, 0}"; sepNavVisRange = "{1926, 1426}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 9424FF650DDCB1EF009912BF /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2587}}"; sepNavSelRange = "{3427, 14}"; sepNavVisRange = "{3136, 845}"; sepNavWindowFrame = "{{38, 17}, {847, 985}}"; }; }; 9424FF660DDCB1EF009912BF /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 651}}"; sepNavSelRange = "{302, 0}"; sepNavVisRange = "{0, 302}"; }; }; 9424FF670DDCB202009912BF /* sqMacV2Memory.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1069, 2457}}"; sepNavSelRange = "{2732, 0}"; sepNavVisRange = "{2453, 2079}"; sepNavWindowFrame = "{{518, 45}, {905, 983}}"; }; }; 9424FF680DDCB202009912BF /* sqMacV2Memory.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1208, 847}}"; sepNavSelRange = "{2075, 15}"; sepNavVisRange = "{0, 2098}"; sepNavWindowFrame = "{{15, 40}, {905, 983}}"; }; }; 9424FF710DDCB234009912BF /* macintoshextra.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 676}}"; sepNavSelRange = "{841, 12}"; sepNavVisRange = "{3, 1655}"; sepNavWindowFrame = "{{539, 15}, {905, 983}}"; }; }; 9424FF720DDCB234009912BF /* macintoshextra.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 629}}"; sepNavSelRange = "{183, 15}"; sepNavVisRange = "{0, 198}"; }; }; 9424FF750DDCB271009912BF /* osExports.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {802, 587}}"; sepNavSelRange = "{389, 0}"; sepNavVisRange = "{0, 571}"; }; }; 94269E6A123EF51B00CB5A57 /* Root.plist */ = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Root.plist; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Settings.bundle/Root.plist; sourceTree = "<absolute>"; }; 94269EA0123EF54A00CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; name = "sqSqueakAppDelegate.m: 63"; rLen = 916; rLoc = 2465; rType = 0; vrLen = 1597; vrLoc = 2227; }; 94269F10123EF9E800CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */; name = "sqSqueakIPhoneInfoPlistInterface.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2024; vrLoc = 0; }; 9426A1E7123EFEDA00CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */; name = "sqSqueakIPhoneApplication+Network.m: 36"; rLen = 0; rLoc = 978; rType = 0; vrLen = 1575; vrLoc = 0; }; 9426A1F8123F006800CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; name = "sqMacV2Memory.c: 74"; rLen = 0; rLoc = 2732; rType = 0; vrLen = 2079; vrLoc = 2453; }; 9426A208123F017D00CB5A57 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94269E6A123EF51B00CB5A57 /* Root.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Settings.bundle/Root.plist; rLen = 0; rLoc = 9223372036854775808; }; 9426A209123F017D00CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */; name = "sqSqueakIPhoneApplication.m: 60"; rLen = 0; rLoc = 2492; rType = 0; vrLen = 2437; vrLoc = 855; }; 9426A228123F01C000CB5A57 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */; name = "sqSqueakInfoPlistInterface.m: 64"; rLen = 0; rLoc = 2410; rType = 0; vrLen = 2404; vrLoc = 0; }; 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 623}}"; sepNavSelRange = "{0, 1814}"; sepNavVisRange = "{0, 1814}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 871}}"; sepNavSelRange = "{2023, 17}"; sepNavVisRange = "{1165, 1672}"; sepNavWindowFrame = "{{16, 4}, {878, 1019}}"; }; }; 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 611}}"; sepNavSelRange = "{1933, 22}"; sepNavVisRange = "{61, 2141}"; }; }; 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1092}}"; sepNavSelRange = "{3341, 105}"; sepNavVisRange = "{2024, 1589}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBAE10BB50E200DAD287 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1028"; rLen = 9; rLoc = 28100; rType = 0; vrLen = 1398; vrLoc = 27330; }; 9428BBAE10BB50E200DAD287 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakIA32ABIPlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9428BBE210BB565100DAD287 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm-display-Quartz/zzz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9428BBE510BB565100DAD287 /* NSPasteboard.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPasteboard.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPasteboard.h; sourceTree = "<absolute>"; }; 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFC410ACC89100F87527 /* string.h */; name = "string.h: 83"; rLen = 44; rLoc = 3369; rType = 0; vrLen = 1928; vrLoc = 2407; }; 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBE510BB565100DAD287 /* NSPasteboard.h */; name = "NSPasteboard.h: 138"; rLen = 50; rLoc = 9563; rType = 0; vrLen = 3372; vrLoc = 7682; }; 9428BC5C10BB760200DAD287 /* sqSqueakOSXApplication+clipboard.m:59 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */; functionName = "-clipboardSize"; hitCount = 0; ignoreCount = 0; lineNumber = 59; location = Squeak; modificationTime = 306811863.542986; originalNumberOfMultipleMatches = 1; state = 2; }; 9428BCDC10BB937100DAD287 /* sqSqueakFileDirectoryInterface.m:218 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Delete:length:"; hitCount = 0; ignoreCount = 0; lineNumber = 218; location = Squeak; modificationTime = 306811863.5429969; originalNumberOfMultipleMatches = 1; state = 2; }; 9428BD7010BBA1DC00DAD287 /* sqSqueakFileDirectoryInterface.m:179 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Create:length:"; hitCount = 0; ignoreCount = 0; lineNumber = 179; location = Squeak; modificationTime = 306811863.5430089; originalNumberOfMultipleMatches = 1; state = 2; }; 9428BD7710BBA26000DAD287 /* sqSqueakFileDirectoryInterface.m:204 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Delete:length:"; hitCount = 0; ignoreCount = 0; lineNumber = 204; location = Squeak; modificationTime = 306811863.543022; originalNumberOfMultipleMatches = 1; state = 2; }; 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC3710AB79DA00F87527 /* NSArray.h */; name = "NSArray.h: 91"; rLen = 15; rLoc = 4609; rType = 0; vrLen = 2275; vrLoc = 3251; }; 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC3C10AB79DA00F87527 /* NSDictionary.h */; name = "NSDictionary.h: 75"; rLen = 19; rLoc = 3192; rType = 0; vrLen = 2430; vrLoc = 1218; }; 942ABD9410AA1F8E0086D908 /* CGGeometry.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGGeometry.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGGeometry.h; sourceTree = "<absolute>"; }; 942ABE0910AA21270086D908 /* NSView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSView.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSView.h; sourceTree = "<absolute>"; }; 942ABEC410AA34820086D908 /* sqMacUIEventsUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUIEventsUniversal.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/vm/sqMacUIEventsUniversal.c"; sourceTree = "<absolute>"; }; 942ABEC510AA34820086D908 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABEC610AA34820086D908 /* sqMacHostWindow.h */; name = "sqMacHostWindow.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 845; vrLoc = 0; }; 942ABEC610AA34820086D908 /* sqMacHostWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMacHostWindow.h; path = "/Volumes/pm/Mail/IMAP-johnmci@smalltalkconsulting.com@imap.gmail.com/[Gmail]/Sent Mail.imapmbox/Attachments/2958644/8/sqMacHostWindow.h"; sourceTree = "<absolute>"; }; 942B77300EA7E642004B266D /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = "/Users/johnmci/Documents/Squeak/Squeak3.8.1-6747-basic#2/src32iPhone/vm/interp.c"; sourceTree = "<absolute>"; }; 942B77330EA7E642004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77340EA7E642004B266D /* sqWin32Prefs.c */; name = "sqWin32Prefs.c: 184"; rLen = 15; rLoc = 6379; rType = 0; vrLen = 1782; vrLoc = 5482; }; 942B77340EA7E642004B266D /* sqWin32Prefs.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Prefs.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Prefs.c; sourceTree = "<absolute>"; }; 942B77380EA7E642004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E6D0DF1171500FB176B /* sqWin32Window.c */; name = "sqWin32Window.c: 65"; rLen = 19; rLoc = 2258; rType = 0; vrLen = 2119; vrLoc = 1403; }; 942B778B0EA7EF0B004B266D /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakQuicktimePlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 942B779B0EA7F2E0004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E640DF1171500FB176B /* sqUnixX11.c */; name = "sqUnixX11.c: 1316"; rLen = 6; rLoc = 37289; rType = 0; vrLen = 1058; vrLoc = 36631; }; 942B779C0EA7F2E0004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B778B0EA7EF0B004B266D /* sqUnixX11.c */; name = "sqUnixX11.c: 1332"; rLen = 6; rLoc = 37592; rType = 0; vrLen = 1035; vrLoc = 36654; }; 942B77B90EA800E1004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77BA0EA800E1004B266D /* sqWin32Alloc.c */; name = "sqWin32Alloc.c: 55"; rLen = 10; rLoc = 2096; rType = 0; vrLen = 1633; vrLoc = 2014; }; 942B77BA0EA800E1004B266D /* sqWin32Alloc.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Alloc.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Alloc.c; sourceTree = "<absolute>"; }; 942B77BB0EA800E1004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77BC0EA800E1004B266D /* sqWin32Alloc.h */; name = "sqWin32Alloc.h: 15"; rLen = 18; rLoc = 487; rType = 0; vrLen = 955; vrLoc = 0; }; 942B77BC0EA800E1004B266D /* sqWin32Alloc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqWin32Alloc.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Alloc.h; sourceTree = "<absolute>"; }; 942CF43710BFCD52008F9BB7 /* sqGnu.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/unix/vm/sqGnu.h; sourceTree = "<absolute>"; }; 942CF46B10BCE44B009BD905 /* NSWindowController.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindowController.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindowController.h; sourceTree = "<absolute>"; }; 942F452E123BF48A002B05DF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */; name = "sqSqueakEventsAPI.m: 47"; rLen = 48; rLoc = 1984; rType = 0; vrLen = 2086; vrLoc = 573; }; 942F4564123BF600002B05DF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */; name = "sqSqueakMainApplication.m: 104"; rLen = 11; rLoc = 3377; rType = 0; vrLen = 1507; vrLoc = 3128; }; 942F4752123C09BF002B05DF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */; name = "SqueakUIController.h: 6"; rLen = 1688; rLoc = 95; rType = 0; vrLen = 1839; vrLoc = 0; }; 942F6FFC1102F5A300A0A349 /* NSNull.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSNull.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNull.h; sourceTree = "<absolute>"; }; 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1169, 764}}"; sepNavSelRange = "{1777, 0}"; sepNavVisRange = "{0, 1781}"; sepNavWindowFrame = "{{913, 18}, {694, 1008}}"; }; }; 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1053}}"; sepNavSelRange = "{2669, 0}"; sepNavVisRange = "{2061, 1010}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1378, 895}}"; sepNavSelRange = "{1881, 65}"; sepNavVisRange = "{0, 1955}"; sepNavWindowFrame = "{{15, 4}, {1425, 1023}}"; }; }; 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1378, 1053}}"; sepNavSelRange = "{2004, 25}"; sepNavVisRange = "{465, 2827}"; sepNavWindowFrame = "{{15, 4}, {1425, 1023}}"; }; }; 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1352}}"; sepNavSelRange = "{1982, 14}"; sepNavVisRange = "{1842, 1584}"; sepNavWindowFrame = "{{38, 4}, {997, 998}}"; }; }; 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 572}}"; sepNavSelRange = "{1882, 14}"; sepNavVisRange = "{0, 1953}"; }; }; 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1819, 94}"; sepNavVisRange = "{0, 1919}"; sepNavWindowFrame = "{{337, 21}, {1288, 857}}"; }; }; 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {985, 1664}}"; sepNavSelRange = "{2953, 0}"; sepNavVisRange = "{1667, 2560}"; sepNavWindowFrame = "{{642, 10}, {1017, 978}}"; }; }; 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1810, 0}"; sepNavVisRange = "{0, 1951}"; }; }; 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 884}}"; sepNavSelRange = "{7, 38}"; sepNavVisRange = "{294, 572}"; sepNavWindowFrame = "{{38, 4}, {1274, 998}}"; }; }; 9430325510BD0B6D0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAB0410AB6DC000F87527 /* NSApplication.h */; name = "NSApplication.h: 314"; rLen = 11; rLoc = 14168; rType = 0; vrLen = 2745; vrLoc = 14077; }; 9430329A10BD103B0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAF7D10ACC0D900F87527 /* NSPathUtilities.h */; name = "NSPathUtilities.h: 26"; rLen = 25; rLoc = 696; rType = 0; vrLen = 1577; vrLoc = 0; }; 9430329B10BD103B0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC0310AB759300F87527 /* NSURL.h */; name = "NSURL.h: 36"; rLen = 5; rLoc = 1448; rType = 0; vrLen = 2612; vrLoc = 0; }; 943198450DDF4D9800EB8E60 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9431CA91123B509800C97383 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9439F9BA123B3BDB0003F15C /* GLString.m */; name = "GLString.m: 213"; rLen = 15; rLoc = 8673; rType = 0; vrLen = 1891; vrLoc = 7793; }; 9431CB57123B5AF100C97383 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940BE5791239F10000674A11 /* SqueakUIViewCALayer.h */; name = "SqueakUIViewCALayer.h: 40"; rLen = 26; rLoc = 1808; rType = 0; vrLen = 2012; vrLoc = 0; }; 9431CBB2123B5E0400C97383 /* SqueakV41.sources */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {3988, 5.68763e+06}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{752, 3467}"; }; }; 9431CBD2123B5F9900C97383 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9431CBB2123B5E0400C97383 /* SqueakV41.sources */; name = "SqueakV41.sources: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 3467; vrLoc = 752; }; 94329B2F122727BC0090298B /* stack_logging.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = stack_logging.c; path = "/Users/johnmci/Shared/Libc-594.9.1/gen/stack_logging.c"; sourceTree = "<absolute>"; }; 94329B31122727BC0090298B /* osgdb_ImageIO.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = osgdb_ImageIO.cpp; path = /Users/johnmci/Shared/osgdb_ImageIO.cpp; sourceTree = "<absolute>"; }; 94329B33122727BC0090298B /* stack_logging_disk.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = stack_logging_disk.c; path = "/Users/johnmci/Shared/Libc-594.9.1/gen/stack_logging_disk.c"; sourceTree = "<absolute>"; }; 94329B3E122729BA0090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329B33122727BC0090298B /* stack_logging_disk.c */; name = "stack_logging_disk.c: 14"; rLen = 0; rLoc = 615; rType = 0; vrLen = 2182; vrLoc = 0; }; 94329B3F122729BA0090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329B31122727BC0090298B /* osgdb_ImageIO.cpp */; name = "osgdb_ImageIO.cpp: 26"; rLen = 0; rLoc = 1170; rType = 0; vrLen = 2416; vrLoc = 0; }; 94329B40122729BA0090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329B2F122727BC0090298B /* stack_logging.c */; name = "stack_logging.c: 11"; rLen = 0; rLoc = 478; rType = 0; vrLen = 2414; vrLoc = 0; }; 94329B5412272A0C0090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329B5512272A0C0090298B /* NSZone.h */; name = "NSZone.h: 59"; rLen = 17; rLoc = 2898; rType = 0; vrLen = 3026; vrLoc = 0; }; 94329B5512272A0C0090298B /* NSZone.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSZone.h; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.2.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSZone.h; sourceTree = "<absolute>"; }; 94329D6412274F350090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6512274F350090298B /* ClientOpenGLView.m */; name = "ClientOpenGLView.m: 145"; rLen = 13; rLoc = 4761; rType = 0; vrLen = 1608; vrLoc = 3748; }; 94329D6512274F350090298B /* ClientOpenGLView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ClientOpenGLView.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/MultiGPUIOSurface/ClientOpenGLView.m"; sourceTree = "<absolute>"; }; 94329D6612274F350090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6712274F350090298B /* sqOpenGLRenderer.c */; name = "sqOpenGLRenderer.c: 95"; rLen = 0; rLoc = 3086; rType = 0; vrLen = 2590; vrLoc = 2485; }; 94329D6712274F350090298B /* sqOpenGLRenderer.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqOpenGLRenderer.c; path = "/Users/johnmci/Documents/Squeak/Squeak3.0 Folder/Squeak 3.1.1/sqOpenGLRenderer.c"; sourceTree = "<absolute>"; }; 94329D6812274F350090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6912274F350090298B /* OpenGLRenderer.m */; name = "OpenGLRenderer.m: 16"; rLen = 0; rLoc = 729; rType = 0; vrLen = 2048; vrLoc = 9387; }; 94329D6912274F350090298B /* OpenGLRenderer.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OpenGLRenderer.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/GLEssentials/Classes/OpenGLRenderer.m"; sourceTree = "<absolute>"; }; 94329D6A12274F350090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6B12274F350090298B /* sqUnixQuartzGL.h */; name = "sqUnixQuartzGL.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 3333; vrLoc = 0; }; 94329D6B12274F350090298B /* sqUnixQuartzGL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqUnixQuartzGL.h; path = "/Volumes/330GB Photos/Cog Before Aug 2010 changes/platforms/unix/vm-display-Quartz/sqUnixQuartzGL.h"; sourceTree = "<absolute>"; }; 94329D6D12274F350090298B /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Volumes/330GB Photos/Cog Before Aug 2010 changes/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94329D6F12274F350090298B /* SqView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqView.h; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/SqueakAppKit/SqView.h"; sourceTree = "<absolute>"; }; 94329E0E12275AC30090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6F12274F350090298B /* SqView.h */; name = "SqView.h: 4"; rLen = 1; rLoc = 42; rType = 0; vrLen = 1636; vrLoc = 0; }; 94329E0F12275AC30090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94329D6D12274F350090298B /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 162"; rLen = 8; rLoc = 5164; rType = 0; vrLen = 1838; vrLoc = 3983; }; 94329FEA122765A60090298B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */; name = "SqViewBitmapConversion.m: 203"; rLen = 26; rLoc = 7753; rType = 0; vrLen = 2204; vrLoc = 7161; }; 94360A8C10E84CC90060221A /* NSException.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSException.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSException.h; sourceTree = "<absolute>"; }; 9439F48C123ABD080003F15C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */; name = "sqMacV2Time.c: 153"; rLen = 36; rLoc = 4434; rType = 0; vrLen = 1421; vrLoc = 3666; }; 9439F9BA123B3BDB0003F15C /* GLString.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GLString.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/CocoaGL/GLString.m"; sourceTree = "<absolute>"; }; 943B9C9E1235C5120056205E /* sqMacHostWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1039, 2496}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2559}"; }; }; 943B9D191235C5FE0056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */; name = "sqSqueakMainApplication+events.h: 19"; rLen = 0; rLoc = 788; rType = 0; vrLen = 2027; vrLoc = 0; }; 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 22139}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 873}"; }; }; 94476EC40EBFAB320095D6D7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */; name = "SoundGenerationPlugin.c: 176"; rLen = 0; rLoc = 5124; rType = 0; vrLen = 999; vrLoc = 4556; }; 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943198450DDF4D9800EB8E60 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 406"; rLen = 36; rLoc = 11460; rType = 0; vrLen = 1419; vrLoc = 10879; }; 944895AD10F4081300FB3EC8 /* PharoV10.sources */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3.55387e+06}}"; sepNavSelRange = "{3217524, 3}"; sepNavVisRange = "{3217191, 992}"; }; }; 944B0D451248105F00CA74EA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */; name = "SqueakOSXAppDelegate.m: 60"; rLen = 17; rLoc = 2423; rType = 0; vrLen = 2306; vrLoc = 982; }; 944B0D461248105F00CA74EA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940BE57A1239F10000674A11 /* SqueakUIViewCALayer.m */; name = "SqueakUIViewCALayer.m: 102"; rLen = 13; rLoc = 3908; rType = 0; vrLen = 2330; vrLoc = 2527; }; 944EB0211228E96100EF9C64 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E96281228DB0D0065B3BA /* sqMacOpenGL.c */; name = "sqMacOpenGL.c: 36"; rLen = 26; rLoc = 1218; rType = 0; vrLen = 1982; vrLoc = 0; }; 9451E5AE123F051700B4119F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */; name = "sqSqueakIPhoneInfoPlistInterface.m: 73"; rLen = 0; rLoc = 3179; rType = 0; vrLen = 2316; vrLoc = 2263; }; 9451E5C5123F062B00B4119F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */; name = "sqSqueakScreenAPI.m: 81"; rLen = 0; rLoc = 2640; rType = 0; vrLen = 1683; vrLoc = 2078; }; 9451E5D5123F07C100B4119F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */; name = "sqSqueakScreenAndWindow.m: 167"; rLen = 0; rLoc = 5194; rType = 0; vrLen = 2293; vrLoc = 4247; }; 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{409, 0}"; sepNavVisRange = "{0, 562}"; }; }; 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 845}}"; sepNavSelRange = "{978, 0}"; sepNavVisRange = "{0, 1575}"; }; }; 9452D5D70E044A9D000AD792 /* Queue.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 845}}"; sepNavSelRange = "{2692, 0}"; sepNavVisRange = "{1337, 1516}"; sepNavWindowFrame = "{{15, 4}, {1593, 1019}}"; }; }; 9452D5D80E044A9D000AD792 /* Queue.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {970, 1612}}"; sepNavSelRange = "{3222, 18}"; sepNavVisRange = "{2686, 983}"; sepNavWindowFrame = "{{38, 12}, {1017, 978}}"; }; }; 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1394, 2366}}"; sepNavSelRange = "{2909, 23}"; sepNavVisRange = "{2158, 1300}"; sepNavWindowFrame = "{{239, 129}, {1441, 887}}"; }; }; 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 626}}"; sepNavSelRange = "{72, 0}"; sepNavVisRange = "{0, 1791}"; }; }; 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 572}}"; sepNavSelRange = "{1792, 10}"; sepNavVisRange = "{3, 1942}"; }; }; 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1111, 2665}}"; sepNavSelRange = "{4819, 15}"; sepNavVisRange = "{3477, 2333}"; sepNavWindowFrame = "{{15, 40}, {905, 983}}"; }; }; 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1170}}"; sepNavSelRange = "{3565, 19}"; sepNavVisRange = "{2087, 1518}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1259, 4251}}"; sepNavSelRange = "{5775, 0}"; sepNavVisRange = "{4703, 1866}"; sepNavWindowFrame = "{{406, 9}, {1334, 1019}}"; }; }; 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1976}}"; sepNavSelRange = "{2096, 153}"; sepNavVisRange = "{1167, 1649}"; }; }; 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 666}}"; sepNavSelRange = "{1322, 449}"; sepNavVisRange = "{0, 1868}"; }; }; 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{2087, 0}"; sepNavVisRange = "{0, 2202}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 1378}}"; sepNavSelRange = "{2337, 4}"; sepNavVisRange = "{2021, 1680}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1157}}"; sepNavSelRange = "{2228, 0}"; sepNavVisRange = "{1856, 1684}"; sepNavWindowFrame = "{{264, 4}, {694, 1008}}"; }; }; 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {858, 2704}}"; sepNavSelRange = "{2396, 0}"; sepNavVisRange = "{1427, 1757}"; sepNavWindowFrame = "{{657, 4}, {905, 983}}"; }; }; 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {936, 766}}"; sepNavSelRange = "{88, 1700}"; sepNavVisRange = "{0, 1790}"; }; }; 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {873, 754}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2110}"; }; }; 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{78, 0}"; sepNavVisRange = "{0, 1785}"; }; }; 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1538, 1118}}"; sepNavSelRange = "{2380, 11}"; sepNavVisRange = "{1779, 1225}"; sepNavWindowFrame = "{{668, 13}, {1012, 1015}}"; }; }; 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 691}}"; sepNavSelRange = "{1872, 63}"; sepNavVisRange = "{0, 1943}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1081, 871}}"; sepNavSelRange = "{2228, 12}"; sepNavVisRange = "{0, 2310}"; sepNavWindowFrame = "{{802, 9}, {878, 1019}}"; }; }; 94547F160DE0AC7D00DD588F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94547F170DE0AC7D00DD588F /* sqMacMain.c */; name = "sqMacMain.c: 486"; rLen = 37; rLoc = 19144; rType = 0; vrLen = 1112; vrLoc = 18071; }; 94547F170DE0AC7D00DD588F /* sqMacMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacMain.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/vm/sqMacMain.c"; sourceTree = "<absolute>"; }; 9454809B0DE2945300DD588F /* sqMacUnixFileInterface.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUnixFileInterface.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/plugins/FilePlugin/sqMacUnixFileInterface.c"; sourceTree = "<absolute>"; }; 945481A60DE2A79200DD588F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9454809B0DE2945300DD588F /* sqMacUnixFileInterface.c */; name = "sqMacUnixFileInterface.c: 512"; rLen = 40; rLoc = 16278; rType = 0; vrLen = 1679; vrLoc = 15123; }; 94554E640DF1171500FB176B /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakSpellingPlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 94554E670DF1171500FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E680DF1171500FB176B /* sqUnixX11.c */; name = "sqUnixX11.c: 2319"; rLen = 12; rLoc = 63841; rType = 0; vrLen = 1057; vrLoc = 63650; }; 94554E680DF1171500FB176B /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakServicesPlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 94554E690DF1171500FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E6A0DF1171500FB176B /* sqMacWindow.c */; name = "sqMacWindow.c: 797"; rLen = 17; rLoc = 29608; rType = 0; vrLen = 994; vrLoc = 29083; }; 94554E6A0DF1171500FB176B /* sqMacWindow.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindow.c; path = "/Users/johnmci/Documents/SqueakServicesPlugin/platforms/Mac OS/vm/sqMacWindow.c"; sourceTree = "<absolute>"; }; 94554E6D0DF1171500FB176B /* sqWin32Window.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Window.c; path = /Users/johnmci/Documents/SqueakServicesPlugin/platforms/win32/vm/sqWin32Window.c; sourceTree = "<absolute>"; }; 94554E7F0DF1171500FB176B /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 94554EB80DF1A86A00FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E7F0DF1171500FB176B /* sqUnixMain.c */; name = "sqUnixMain.c: 526"; rLen = 12; rLoc = 12689; rType = 0; vrLen = 1587; vrLoc = 12009; }; 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1902, 6}"; sepNavVisRange = "{0, 1915}"; sepNavWindowFrame = "{{15, 22}, {1064, 1001}}"; }; }; 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 1001}}"; sepNavSelRange = "{3235, 8}"; sepNavVisRange = "{600, 2690}"; }; }; 9456C24F10B2F268000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABD9410AA1F8E0086D908 /* CGGeometry.h */; name = "CGGeometry.h: 29"; rLen = 16; rLoc = 429; rType = 0; vrLen = 1403; vrLoc = 0; }; 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C25B10B2F2C9000BF3DE /* types.h */; name = "types.h: 83"; rLen = 25; rLoc = 3624; rType = 0; vrLen = 1820; vrLoc = 2321; }; 9456C25B10B2F2C9000BF3DE /* types.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = types.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/i386/types.h; sourceTree = "<absolute>"; }; 9456C2F910B32D2A000BF3DE /* NSString.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSString.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSString.h; sourceTree = "<absolute>"; }; 9456C32210B32F43000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C32310B32F43000BF3DE /* NSClipView.h */; name = "NSClipView.h: 22"; rLen = 9; rLoc = 509; rType = 0; vrLen = 2046; vrLoc = 0; }; 9456C32310B32F43000BF3DE /* NSClipView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSClipView.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSClipView.h; sourceTree = "<absolute>"; }; 9456C34E10B33618000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C34F10B33618000BF3DE /* CALayer.h */; name = "CALayer.h: 169"; rLen = 35; rLoc = 5389; rType = 0; vrLen = 2280; vrLoc = 4266; }; 9456C34F10B33618000BF3DE /* CALayer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CALayer.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CALayer.h; sourceTree = "<absolute>"; }; 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C3CC10B341F9000BF3DE /* NSAffineTransform.h */; name = "NSAffineTransform.h: 39"; rLen = 8; rLoc = 933; rType = 0; vrLen = 1411; vrLoc = 0; }; 9456C3CC10B341F9000BF3DE /* NSAffineTransform.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSAffineTransform.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSAffineTransform.h; sourceTree = "<absolute>"; }; 94584F6110F020BD001401E7 /* ClipboardExtendedPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1317, 3289}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 883}"; }; }; 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1062, 1469}}"; sepNavSelRange = "{2557, 0}"; sepNavVisRange = "{2199, 1891}"; sepNavWindowFrame = "{{242, 4}, {1438, 968}}"; }; }; 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 507}}"; sepNavSelRange = "{1388, 0}"; sepNavVisRange = "{336, 1542}"; sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 9458511410F03996001401E7 /* sqMacExtendedClipboard.m:101 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */; functionName = "sqPasteboardCopyItemFlavorDataformatformatLength()"; hitCount = 0; ignoreCount = 0; lineNumber = 101; location = Squeak; modificationTime = 306811868.07592; originalNumberOfMultipleMatches = 1; state = 1; }; 945851EE10F03E60001401E7 /* sqMacExtendedClipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1331, 873}}"; sepNavSelRange = "{7, 24}"; sepNavVisRange = "{0, 1878}"; sepNavWindowFrame = "{{15, 4}, {1378, 1024}}"; }; }; 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1062, 1365}}"; sepNavSelRange = "{3036, 111}"; sepNavVisRange = "{1719, 1665}"; sepNavWindowFrame = "{{61, 13}, {1438, 968}}"; }; }; 9458523210F040A0001401E7 /* sqMacExtendedClipboard.m:37 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 37; location = Squeak; modificationTime = 306811868.118221; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523410F040A1001401E7 /* sqMacExtendedClipboard.m:45 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 45; location = Squeak; modificationTime = 306811868.142344; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523610F040A2001401E7 /* sqMacExtendedClipboard.m:50 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 50; location = Squeak; modificationTime = 306811868.183629; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523A10F040AF001401E7 /* sqMacExtendedClipboard.m:72 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 72; location = Squeak; modificationTime = 306811868.2171251; originalNumberOfMultipleMatches = 1; state = 1; }; 9458524810F04272001401E7 /* sqMacExtendedClipboard.m:88 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 88; location = Squeak; modificationTime = 306811868.249962; originalNumberOfMultipleMatches = 1; state = 1; }; 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 769}}"; sepNavSelRange = "{58, 44}"; sepNavVisRange = "{0, 1817}"; }; }; 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 786}}"; sepNavSelRange = "{586, 13}"; sepNavVisRange = "{0, 1345}"; }; }; 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 794}}"; sepNavSelRange = "{1982, 227}"; sepNavVisRange = "{0, 2214}"; sepNavWindowFrame = "{{15, 17}, {1261, 1006}}"; }; }; 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {943, 794}}"; sepNavSelRange = "{287, 25}"; sepNavVisRange = "{0, 1522}"; }; }; 9458527F10F045FB001401E7 /* sqSqueakIPhoneClipboardAPI.m:31 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 31; modificationTime = 306812454.06156; originalNumberOfMultipleMatches = 1; state = 1; }; 9458528110F045FC001401E7 /* sqSqueakIPhoneClipboardAPI.m:24 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 24; modificationTime = 306812454.061646; originalNumberOfMultipleMatches = 1; state = 1; }; 9458528310F045FD001401E7 /* sqSqueakIPhoneClipboardAPI.m:17 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 17; modificationTime = 306812454.061617; originalNumberOfMultipleMatches = 1; state = 1; }; 945BA53B10B218F700C2020C /* math.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = math.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/architecture/i386/math.h; sourceTree = "<absolute>"; }; 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945C4D7D10BB0A8500548CC1 /* OSTypes.h */; name = "OSTypes.h: 73"; rLen = 35; rLoc = 2233; rType = 0; vrLen = 1245; vrLoc = 1528; }; 945C4D7D10BB0A8500548CC1 /* OSTypes.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OSTypes.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/libkern/OSTypes.h; sourceTree = "<absolute>"; }; 945C4E6310BB29B500548CC1 /* sqSqueakFileDirectoryInterface.m:118 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Lookup:length:index:name:length:creationDate:modificationDate:isDirectory:sizeIfFile:"; hitCount = 0; ignoreCount = 0; lineNumber = 118; location = Squeak; modificationTime = 306811863.542962; originalNumberOfMultipleMatches = 1; state = 2; }; 945C4E8010BB2CE000548CC1 /* sqSqueakFileDirectoryInterface.m:102 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Lookup:length:index:name:length:creationDate:modificationDate:isDirectory:sizeIfFile:"; hitCount = 0; ignoreCount = 0; lineNumber = 102; location = Squeak; modificationTime = 306811863.542974; originalNumberOfMultipleMatches = 1; state = 2; }; 945C4EAC10BB348300548CC1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAAE810AB6C3500F87527 /* NSFileManager.h */; name = "NSFileManager.h: 162"; rLen = 14; rLoc = 11455; rType = 0; vrLen = 4578; vrLoc = 9506; }; 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945E9D7D0DE525E100CDF01E /* npsqueak.c */; name = "npsqueak.c: 1113"; rLen = 21; rLoc = 33897; rType = 0; vrLen = 2274; vrLoc = 32164; }; 945E9D7D0DE525E100CDF01E /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak/npsqueak.c"; sourceTree = "<absolute>"; }; 945F30620E0C6A5000CFF3DC /* SqueakApplication.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakApplication.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/SqueakApplication.m"; sourceTree = "<absolute>"; }; 945F30670E0C6A5000CFF3DC /* SqueakInterpreter.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreter.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreter.m"; sourceTree = "<absolute>"; }; 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945F30670E0C6A5000CFF3DC /* SqueakInterpreter.m */; name = "SqueakInterpreter.m: 200"; rLen = 13; rLoc = 5497; rType = 0; vrLen = 1593; vrLoc = 2040; }; 94607E0E123B7A8C008BA756 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948DB86E123B76F40002F636 /* SqueakGL.c */; name = "SqueakGL.c: 715"; rLen = 0; rLoc = 23713; rType = 0; vrLen = 1751; vrLoc = 23260; }; 94638B260EAFB77B00A3F155 /* iPhone.changes */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 898248}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 507}"; }; }; 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638CEB0EB16F1100A3F155 /* unxMapMemory.h */; name = "unxMapMemory.h: 270"; rLen = 6; rLoc = 8341; rType = 0; vrLen = 1425; vrLoc = 0; }; 94638CEB0EB16F1100A3F155 /* unxMapMemory.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = unxMapMemory.h; path = "/Users/johnmci/Work In Progress/cincom/VWSourceCode/bkup621/src-51.4/plat/unxMapMemory.h"; sourceTree = "<absolute>"; }; 94638CF50EB16F1100A3F155 /* sqUnixMemory.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMemory.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqUnixMemory.c; sourceTree = "<absolute>"; }; 9463943D0E95845000015851 /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1219, 2646}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1036}"; }; }; 9463943E0E95845000015851 /* squeakSUnitTester.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6762}}"; sepNavSelRange = "{4085, 11}"; sepNavVisRange = "{3547, 944}"; }; }; 94669D8C1225EF670062028C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */; name = "BitMapConversionLogicFromX11.h: 18"; rLen = 14; rLoc = 581; rType = 0; vrLen = 1092; vrLoc = 0; }; 94671FFD12617CFE00F97C81 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */; name = "JPEGReadWriter2Plugin.c: 679"; rLen = 17; rLoc = 20722; rType = 0; vrLen = 2103; vrLoc = 19321; }; 94672008126185F600F97C81 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */; }; 946720241261864D00F97C81 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */; name = "sqSqueakOSXApplication.m: 236"; rLen = 7; rLoc = 7274; rType = 0; vrLen = 1802; vrLoc = 6321; }; 946720251261864D00F97C81 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946720261261864D00F97C81 /* ntpdate.c */; name = "ntpdate.c: 122"; rLen = 18; rLoc = 3665; rType = 0; vrLen = 1762; vrLoc = 13286; }; 946720261261864D00F97C81 /* ntpdate.c */ = { isa = PBXFileReference; name = ntpdate.c; path = "/Users/johnmci/Shared/zntpdate-0.4.12/src/ntpdate.c"; sourceTree = "<absolute>"; }; 946720271261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 946720281261864D00F97C81 /* Info.plist */; fallbackIsa = PBXBookmark; isK = 1; kPath = ( SqueakUnTrustedDirectory, ); name = "/Users/johnmci/Documents/Squeak3.8.0/build/Squeak 4.2.5beta1U.app/Contents/Info.plist"; rLen = 24; rLoc = 0; }; 946720281261864D00F97C81 /* Info.plist */ = { isa = PBXFileReference; name = Info.plist; path = "/Users/johnmci/Documents/Squeak3.8.0/build/Squeak 4.2.5beta1U.app/Contents/Info.plist"; sourceTree = "<absolute>"; }; 946720291261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 9467202A1261864D00F97C81 /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakUnTrustedDirectory, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/build/Distribution/Squeak 5.8b10.app/Contents/Info.plist"; rLen = 0; rLoc = 9223372036854775807; }; 9467202A1261864D00F97C81 /* Info.plist */ = { isa = PBXFileReference; name = Info.plist; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/build/Distribution/Squeak 5.8b10.app/Contents/Info.plist"; sourceTree = "<absolute>"; }; 9467202B1261864D00F97C81 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */; name = "sqSqueakInfoPlistInterface.h: 44"; rLen = 14; rLoc = 1933; rType = 0; vrLen = 2070; vrLoc = 0; }; 9467202C1261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 948774B110C64DD800E4AEC5 /* SqueakPureObjc-Info 64x64.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakUseFileMappedMMAP, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc-Info 64x64.plist"; rLen = 0; rLoc = 9223372036854775807; }; 9467202D1261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakPluginsBuiltInOrLocalOnly, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc-Info.plist"; rLen = 0; rLoc = 9223372036854775807; }; 9467202E1261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94C36C9710B0CF290041953A /* Info-iPhone.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleVersion, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Info-iPhone.plist"; rLen = 5; rLoc = 0; }; 9467202F1261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94C36C9710B0CF290041953A /* Info-iPhone.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleVersion, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Info-iPhone.plist"; rLen = 5; rLoc = 0; }; 946720321261864D00F97C81 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakUnTrustedDirectory, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc-Info.plist"; rLen = 0; rLoc = 9223372036854775807; }; 946D973B0FE165B70038846B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946D973C0FE165B70038846B /* sqSqueakEventsAPI.m */; name = "sqSqueakEventsAPI.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 989; vrLoc = 2044; }; 946D973C0FE165B70038846B /* sqSqueakEventsAPI.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqSqueakEventsAPI.m; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakEventsAPI.m"; sourceTree = "<absolute>"; }; 946DA77210C09A8C00F26F56 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakPrintJobPlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 946DA7D710C0A6C700F26F56 /* NSWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindow.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h; sourceTree = "<absolute>"; }; 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA7E110C0A7A400F26F56 /* NSView.h */; name = "NSView.h: 327"; rLen = 23; rLoc = 10791; rType = 0; vrLen = 2404; vrLoc = 9657; }; 946DA7E110C0A7A400F26F56 /* NSView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSView.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSView.h; sourceTree = "<absolute>"; }; 946DA8D210C0C30D00F26F56 /* DropPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2548}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1485}"; sepNavWindowFrame = "{{254, 4}, {1426, 1019}}"; }; }; 946DA8D910C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA7D710C0A6C700F26F56 /* NSWindow.h */; name = "NSWindow.h: 580"; rLen = 23; rLoc = 22568; rType = 0; vrLen = 2638; vrLoc = 21350; }; 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA77210C09A8C00F26F56 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2093"; rLen = 0; rLoc = 54353; rType = 0; vrLen = 1177; vrLoc = 53870; }; 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA8DC10C0C32800F26F56 /* NSDragging.h */; name = "NSDragging.h: 56"; rLen = 64; rLoc = 1665; rType = 0; vrLen = 2094; vrLoc = 0; }; 946DA8DC10C0C32800F26F56 /* NSDragging.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDragging.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSDragging.h; sourceTree = "<absolute>"; }; 946DA8EF10C0C38600F26F56 /* DropPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 169}}"; sepNavSelRange = "{300, 21}"; sepNavVisRange = "{0, 490}"; }; }; 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 507}}"; sepNavSelRange = "{7, 20}"; sepNavVisRange = "{0, 400}"; }; }; 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1079}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1643}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 946DA99210C0CE1900F26F56 /* sqSqueakOSXDropAPI.m:79 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 79; location = Squeak; modificationTime = 306811867.904445; originalNumberOfMultipleMatches = 1; state = 1; }; 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3965}}"; sepNavSelRange = "{5437, 17}"; sepNavVisRange = "{4718, 1216}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3910C0D8B700F26F56 /* sqUnixMain.c */; name = "sqUnixMain.c: 709"; rLen = 12; rLoc = 18115; rType = 0; vrLen = 1874; vrLoc = 17010; }; 946DAA3910C0D8B700F26F56 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakExuperyPlugin/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3B10C0D8B700F26F56 /* sqMacMain.c */; name = "sqMacMain.c: 473"; rLen = 13; rLoc = 17090; rType = 0; vrLen = 2581; vrLoc = 14967; }; 946DAA3B10C0D8B700F26F56 /* sqMacMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacMain.c; path = "/Users/johnmci/Documents/SqueakExuperyPlugin/platforms/Mac OS/vm/sqMacMain.c"; sourceTree = "<absolute>"; }; 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3D10C0D8B700F26F56 /* sqUnixExternalPrims.c */; name = "sqUnixExternalPrims.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1365; vrLoc = 4834; }; 946DAA3D10C0D8B700F26F56 /* sqUnixExternalPrims.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixExternalPrims.c; path = "/Users/johnmci/Documents/SqueakHydraZBaseCheck/HydraVM-src/platforms/unix/vm/sqUnixExternalPrims.c"; sourceTree = "<absolute>"; }; 946DAB1210C0F00400F26F56 /* sqMacUnixExternalPrims.m:219 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */; functionName = "ioLoadModuleRaw()"; hitCount = 0; ignoreCount = 0; lineNumber = 219; location = Squeak; modificationTime = 306811867.942082; originalNumberOfMultipleMatches = 1; state = 1; }; 946DAB5110C0F2B000F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA8D210C0C30D00F26F56 /* DropPlugin.c */; name = "DropPlugin.c: 178"; rLen = 18; rLoc = 4453; rType = 0; vrLen = 1680; vrLoc = 3335; }; 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 988}}"; sepNavSelRange = "{2843, 13}"; sepNavVisRange = "{1784, 1182}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1496, 2912}}"; sepNavSelRange = "{5194, 0}"; sepNavVisRange = "{4247, 2293}"; sepNavWindowFrame = "{{148, 9}, {1131, 1019}}"; }; }; 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1331, 896}}"; sepNavSelRange = "{1936, 23}"; sepNavVisRange = "{0, 2324}"; sepNavWindowFrame = "{{15, 4}, {1378, 1024}}"; }; }; 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1547}}"; sepNavSelRange = "{3575, 9}"; sepNavVisRange = "{2835, 989}"; sepNavWindowFrame = "{{731, 4}, {860, 1024}}"; }; }; 9471E48A0EB6C393000AE79D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */; name = "StarSqueakPlugin.c: 95"; rLen = 2; rLoc = 2480; rType = 0; vrLen = 1031; vrLoc = 2015; }; 9472586B1254FECD00A8DE45 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94883B2A0E0C2A5E005A4738 /* aio.c */; name = "aio.c: 235"; rLen = 0; rLoc = 5593; rType = 0; vrLen = 1297; vrLoc = 4842; }; 9472586C1254FECD00A8DE45 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659100DDD03FE00358328 /* SocketPlugin.c */; name = "SocketPlugin.c: 1231"; rLen = 91; rLoc = 36324; rType = 0; vrLen = 2532; vrLoc = 34415; }; 947332EE0EA70E8C003F9084 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947332EF0EA70E8C003F9084 /* sqWin32Stubs.c */; name = "sqWin32Stubs.c: 18"; rLen = 18; rLoc = 607; rType = 0; vrLen = 2348; vrLoc = 0; }; 947332EF0EA70E8C003F9084 /* sqWin32Stubs.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Stubs.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Stubs.c; sourceTree = "<absolute>"; }; 9473A34810BBD84100ED7D00 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCACE310AB8AE300F87527 /* NSObject.h */; name = "NSObject.h: 74"; rLen = 3; rLoc = 1310; rType = 0; vrLen = 1170; vrLoc = 936; }; 9473A95A1102F70B00D135CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F6FFC1102F5A300A0A349 /* NSNull.h */; name = "NSNull.h: 9"; rLen = 0; rLoc = 159; rType = 0; vrLen = 184; vrLoc = 0; }; 9473A9701103BE0A00D135CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942CF43710BFCD52008F9BB7 /* sqGnu.h */; name = "sqGnu.h: 187"; rLen = 0; rLoc = 11295; rType = 0; vrLen = 2361; vrLoc = 9051; }; 9475F4DB10BEF4100047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E4936F10BD39E20011AC75 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2177"; rLen = 0; rLoc = 56455; rType = 0; vrLen = 1151; vrLoc = 55829; }; 9475F56B10BF20A00047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9475F56C10BF20A00047A24B /* AudioQueue.h */; name = "AudioQueue.h: 1116"; rLen = 66; rLoc = 56155; rType = 0; vrLen = 2628; vrLoc = 54742; }; 9475F56C10BF20A00047A24B /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 9475F58210BF227D0047A24B /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 9475F5A710BF25A10047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9475F58210BF227D0047A24B /* NSApplication.h */; name = "NSApplication.h: 18"; rLen = 21; rLoc = 470; rType = 0; vrLen = 1966; vrLoc = 0; }; 9476030E10C375C300B621C9 /* sqSqueakOSXApplication.m:259 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */; functionName = "-isImageFile:"; hitCount = 0; ignoreCount = 0; lineNumber = 259; location = Squeak; modificationTime = 306811867.974928; originalNumberOfMultipleMatches = 1; state = 1; }; 9476031010C375C600B621C9 /* sqSqueakOSXApplication.m:264 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */; functionName = "-isImageFile:"; hitCount = 0; ignoreCount = 0; lineNumber = 264; location = Squeak; modificationTime = 306811868.008287; originalNumberOfMultipleMatches = 1; state = 1; }; 947713B610C45C0A00890A9B /* Queue.m:117 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5D80E044A9D000AD792 /* Queue.m */; functionName = "-dealloc"; hitCount = 0; ignoreCount = 0; lineNumber = 117; location = Squeak; modificationTime = 306811863.543401; originalNumberOfMultipleMatches = 1; state = 2; }; 947713C410C45DD700890A9B /* NSDebug.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDebug.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDebug.h; sourceTree = "<absolute>"; }; 947713D410C45E5F00890A9B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947713C410C45DD700890A9B /* NSDebug.h */; name = "NSDebug.h: 53"; rLen = 36; rLoc = 2244; rType = 0; vrLen = 2334; vrLoc = 74; }; 9478E0250EC8D957007096A7 /* dummyFFI.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2652}}"; sepNavSelRange = "{3356, 8}"; sepNavVisRange = "{2987, 642}"; }; }; 9478E0260EC8D957007096A7 /* dummyFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {899, 548}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1760}"; sepNavWindowFrame = "{{15, 166}, {1288, 857}}"; }; }; 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {964, 2535}}"; sepNavSelRange = "{1808, 17}"; sepNavVisRange = "{0, 2274}"; }; }; 9478E02B0EC8D957007096A7 /* squeakSUnitTester.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 5928}}"; sepNavSelRange = "{12415, 0}"; sepNavVisRange = "{11760, 1507}"; }; }; 9478E0320EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 720}}"; sepNavSelRange = "{103, 1666}"; sepNavVisRange = "{0, 1809}"; }; }; 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 1157}}"; sepNavSelRange = "{2107, 0}"; sepNavVisRange = "{1885, 2226}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9478E05E0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1062, 1404}}"; sepNavSelRange = "{2099, 24}"; sepNavVisRange = "{1871, 2592}"; sepNavWindowFrame = "{{52, 4}, {997, 998}}"; }; }; 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 5720}}"; sepNavSelRange = "{10010, 0}"; sepNavVisRange = "{9239, 849}"; sepNavWindowFrame = "{{38, 3}, {1587, 998}}"; }; }; 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9478E13E0EC8EB46007096A7 /* AudioQueue.h */; name = "AudioQueue.h: 2"; rLen = 10; rLoc = 19; rType = 0; vrLen = 1351; vrLoc = 0; }; 9478E13E0EC8EB46007096A7 /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 947923FE1102BE53007C87F8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947923FF1102BE53007C87F8 /* sqUnixMain.c */; name = "sqUnixMain.c: 176"; rLen = 281; rLoc = 5149; rType = 0; vrLen = 1173; vrLoc = 4547; }; 947923FF1102BE53007C87F8 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Volumes/px2/business/SqueakiPhone/archivesOLDSTUFF/platformsOLDDrawing/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 947924171102E275007C87F8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658E60DDD03FE00358328 /* B2DPlugin.c */; name = "B2DPlugin.c: 6117"; rLen = 12; rLoc = 189972; rType = 0; vrLen = 1391; vrLoc = 189145; }; 947CB8991249932E00131713 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */; name = "sqSqueakOSXApplication+attributes.m: 47"; rLen = 12; rLoc = 2065; rType = 0; vrLen = 2011; vrLoc = 1048; }; 947CB8B81249949B00131713 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; name = "sqSqueakFileDirectoryInterface.m: 171"; rLen = 8; rLoc = 6206; rType = 0; vrLen = 2075; vrLoc = 5070; }; 947CB8D01249955E00131713 /* sqSqueakFileDirectoryInterface.m:150 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; functionName = "-dir_Lookup:length:index:name:length:creationDate:modificationDate:isDirectory:sizeIfFile:"; hitCount = 0; ignoreCount = 0; lineNumber = 150; location = Squeak; modificationTime = 306812254.47955; originalNumberOfMultipleMatches = 1; state = 1; }; 947E20F50EB281C5007957D0 /* SqueakFFIPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 37401}}"; sepNavSelRange = "{63121, 2}"; sepNavVisRange = "{62724, 744}"; }; }; 947E20F90EB2826C007957D0 /* sqFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2210}}"; sepNavSelRange = "{2071, 8}"; sepNavVisRange = "{1307, 1682}"; }; }; 947E210C0EB28486007957D0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638CF50EB16F1100A3F155 /* sqUnixMemory.c */; name = "sqUnixMemory.c: 214"; rLen = 6; rLoc = 6843; rType = 0; vrLen = 1296; vrLoc = 6040; }; 947E21310EB2868A007957D0 /* dummyFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 494}}"; sepNavSelRange = "{87, 0}"; sepNavVisRange = "{0, 1201}"; }; }; 947E21320EB2868A007957D0 /* dummyFFI.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2587}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 891}"; }; }; 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1039, 823}}"; sepNavSelRange = "{114, 0}"; sepNavVisRange = "{0, 149}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {972, 7812}}"; sepNavSelRange = "{13195, 0}"; sepNavVisRect = "{{0, 7107}, {972, 697}}"; sepNavWindowFrame = "{{334, 54}, {1346, 974}}"; }; }; 947E61D610AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61D710AA049300D3B69E /* Availability.h */; name = "Availability.h: 124"; rLen = 11; rLoc = 5703; rType = 0; vrLen = 2202; vrLoc = 4378; }; 947E61D710AA049300D3B69E /* Availability.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Availability.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/Availability.h; sourceTree = "<absolute>"; }; 947E61DA10AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61DB10AA049300D3B69E /* AudioFileStream.h */; name = "AudioFileStream.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 805; vrLoc = 0; }; 947E61DB10AA049300D3B69E /* AudioFileStream.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioFileStream.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioFileStream.h; sourceTree = "<absolute>"; }; 947E61DC10AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61DD10AA049300D3B69E /* AudioFormat.h */; name = "AudioFormat.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 779; vrLoc = 0; }; 947E61DD10AA049300D3B69E /* AudioFormat.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioFormat.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioFormat.h; sourceTree = "<absolute>"; }; 947E626F10AA098300D3B69E /* SqueakPureObjc */ = { activeExec = 0; executables = ( 947E62FD10AA098300D3B69E /* SqueakPureObjc */, ); }; 947E62FD10AA098300D3B69E /* SqueakPureObjc */ = { isa = PBXExecutable; activeArgIndices = ( NO, NO, NO, NO, NO, ); argumentStrings = ( "-memory 52m", "-help", bork.image, 232, 242, ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStyle = 4; class = XCIndigoRunLaunchConfig; commandLineArgs = ( ); displayName = "iPhone Simulator runner"; environment = { }; identifier = com.apple.Xcode.launch.iPhoneSimulatorRunConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( { active = NO; name = NSAutoreleaseHaltOnFreedObject; value = YES; }, { active = NO; name = NSDebugEnabled; value = YES; }, { active = NO; name = NSAutoreleaseFreedObjectCheckEnabled; value = YES; }, { active = NO; name = NSZombieEnabled; value = YES; }, { active = NO; name = DYLD_INSERT_LIBRARIES; value = /usr/lib/libMallocDebug.A.dylib; }, { active = NO; name = MallocPreScribble; value = YES; }, { active = NO; name = MallocScribble; value = YES; }, { active = NO; name = MallocGuardEdges; value = YES; }, { active = NO; name = NSDebugConcurrentViewDrawing; value = YES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakPureObjc; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); startupPath = "<<ProductDirectory>>"; variableFormatDictionary = { $cs = 1; $ds = 1; $eax = 1; $ebp = 1; $ebx = 1; $ecx = 1; $edi = 1; $edx = 1; $eflags = 1; $eip = 1; $es = 1; $esi = 1; $esp = 1; $fs = 1; $gs = 1; $r10 = 1; $r11 = 1; $r12 = 1; $r13 = 1; $r14 = 1; $r15 = 1; $r8 = 1; $r9 = 1; $rax = 1; $rbp = 1; $rbx = 1; $rcx = 1; $rdi = 1; $rdx = 1; $rip = 1; $rsi = 1; $rsp = 1; $ss = 1; "*from-short unsigned int-copyImage16To32" = 3; "_return_value-sqInt-primitiveGetMenuHandle" = 1; "b-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "bits-NSInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; "currentVMEncoding-NSInteger-\U0001\U0000-[sqSqueakMainApplication(attributes) getAttribute:]" = 1; "g-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "inCommandID-MenuCommand-GetIndMenuItemWithCommandID" = 5; "inputCommandID-OSType-GetIndMenuItemWithCommandID" = 5; "mask-NSInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; "modifierFlags-NSUInteger--[sqSqueakOSXNSView doCommandBySelector:]" = 3; "modifierFlags-NSUInteger--[sqSqueakOSXNSView fakeKeyDownUp:]" = 1; "oop-usqInt-pointerForOop" = 1; "oop-usqInt-sweepPhase" = 2; "r-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "rgb-short int--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "rgb-short unsigned int--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "shift-NSUInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; "to1-int-copyImage16To32" = 3; "to2-int-copyImage16To32" = 1; }; }; 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {802, 587}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1518}"; }; }; 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {802, 780}}"; sepNavSelRange = "{1504, 0}"; sepNavVisRange = "{492, 1556}"; }; }; 947E644910AA0F2C00D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */; name = "BMPReadWriterPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1250; vrLoc = 0; }; 947E644B10AA0F2C00D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658F20DDD03FE00358328 /* FFTPlugin.c */; name = "FFTPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1243; vrLoc = 0; }; 947E645010AA0F2C00D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */; name = "JPEGReaderPlugin.c: 115"; rLen = 0; rLoc = 3465; rType = 0; vrLen = 1395; vrLoc = 2800; }; 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 780}}"; sepNavSelRange = "{1916, 50}"; sepNavVisRange = "{1643, 459}"; sepNavWindowFrame = "{{522, 48}, {1017, 978}}"; }; }; 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 2327}}"; sepNavSelRange = "{2423, 17}"; sepNavVisRange = "{982, 2306}"; sepNavWindowFrame = "{{1157, -86}, {1426, 1019}}"; }; }; 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1379, 891}}"; sepNavSelRange = "{1861, 62}"; sepNavVisRange = "{0, 2397}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3484}}"; sepNavSelRange = "{4978, 7}"; sepNavVisRange = "{4433, 1240}"; sepNavWindowFrame = "{{522, 48}, {1017, 978}}"; }; }; 947E96231228DB0D0065B3BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E96241228DB0D0065B3BA /* sqWin32OpenGL.c */; name = "sqWin32OpenGL.c: 23"; rLen = 0; rLoc = 650; rType = 0; vrLen = 1947; vrLoc = 0; }; 947E96241228DB0D0065B3BA /* sqWin32OpenGL.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32OpenGL.c; path = "/Users/johnmci/Documents/SqueakHydraZBaseCheck/HydraVM-src/platforms/win32/plugins/B3DAcceleratorPlugin/sqWin32OpenGL.c"; sourceTree = "<absolute>"; }; 947E96251228DB0D0065B3BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E96261228DB0D0065B3BA /* sqOpenGLRenderer.c */; name = "sqOpenGLRenderer.c: 268"; rLen = 20; rLoc = 8356; rType = 0; vrLen = 1808; vrLoc = 7505; }; 947E96261228DB0D0065B3BA /* sqOpenGLRenderer.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqOpenGLRenderer.c; path = /Users/johnmci/Documents/SqueakExuperyPlugin/platforms/Cross/plugins/B3DAcceleratorPlugin/sqOpenGLRenderer.c; sourceTree = "<absolute>"; }; 947E96281228DB0D0065B3BA /* sqMacOpenGL.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacOpenGL.c; path = "/Volumes/330GB Photos/Cog Before Aug 2010 changes/platforms/Mac OS/plugins/B3DAcceleratorPlugin/sqMacOpenGL.c"; sourceTree = "<absolute>"; }; 9483EAFB121C60C70070C43B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */; name = "SqueakOSXApplication.m: 41"; rLen = 17; rLoc = 1874; rType = 0; vrLen = 2433; vrLoc = 0; }; 9484F7B910B0D3600038BDC0 /* SystemConfiguration.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemConfiguration.h; path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/Headers/SystemConfiguration.h; sourceTree = "<absolute>"; }; 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9484F7B910B0D3600038BDC0 /* SystemConfiguration.h */; name = "SystemConfiguration.h: 109"; rLen = 30; rLoc = 4596; rType = 0; vrLen = 1985; vrLoc = 3539; }; 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9484F86610B0DCC60038BDC0 /* ABGlobals.h */; name = "ABGlobals.h: 162"; rLen = 6; rLoc = 6912; rType = 0; vrLen = 2845; vrLoc = 5737; }; 9484F86610B0DCC60038BDC0 /* ABGlobals.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ABGlobals.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AddressBook.framework/Versions/A/Headers/ABGlobals.h; sourceTree = "<absolute>"; }; 9484F8FC10B0E1770038BDC0 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 945550910DF2041100FB176B /* Default.png */; }; 9484F9CE10B13E1C0038BDC0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658F00DDD03FE00358328 /* DSAPrims.c */; name = "DSAPrims.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 846; vrLoc = 0; }; 94862F8310BA182500CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3696610AFB7550041953A /* NSBitmapImageRep.h */; name = "NSBitmapImageRep.h: 100"; rLen = 24; rLoc = 4439; rType = 0; vrLen = 3020; vrLoc = 3019; }; 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAD0410AB922600F87527 /* NSObjCRuntime.h */; name = "NSObjCRuntime.h: 193"; rLen = 5; rLoc = 6827; rType = 0; vrLen = 1591; vrLoc = 6049; }; 9486302A10BA247200CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3696310AFB7550041953A /* NSGraphics.h */; name = "NSGraphics.h: 92"; rLen = 159; rLoc = 2874; rType = 0; vrLen = 3496; vrLoc = 1601; }; 948704AE0E12CABF00D565C3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948704AF0E12CABF00D565C3 /* BitBlt.java */; name = "BitBlt.java: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1739; vrLoc = 0; }; 948704AF0E12CABF00D565C3 /* BitBlt.java */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.java; name = BitBlt.java; path = /Users/johnmci/Shared/JSqueak/BitBlt.java; sourceTree = "<absolute>"; }; 948704B20E12CABF00D565C3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */; name = "Matrix2x3Plugin.c: 629"; rLen = 25; rLoc = 18495; rType = 0; vrLen = 1410; vrLoc = 0; }; 9487071F0E132B1000D565C3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948707200E132B1000D565C3 /* sqGnu.h */; name = "sqGnu.h: 3"; rLen = 1318; rLoc = 43; rType = 0; vrLen = 1999; vrLoc = 0; }; 948707200E132B1000D565C3 /* sqGnu.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqGnu.h; sourceTree = "<absolute>"; }; 948773F910C64DD800E4AEC5 /* SqueakPureObjc64*64 */ = { activeExec = 0; executables = ( 948774A910C64DD800E4AEC5 /* SqueakPureObjc64*64 */, ); }; 948774A910C64DD800E4AEC5 /* SqueakPureObjc64*64 */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = "SqueakPureObjc64*64"; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); variableFormatDictionary = { "localHomeContext-sqInt-interpret" = 1; "memStart-sqInt-readImageFromFileHeapSizeStartingAt" = 1; "objectPointer-sqInt-primitiveFileGetPosition" = 1; "oop-sqInt-longAt" = 1; "oop-usqInt-sweepPhase" = 1; "oopSize-sqInt-sweepPhase" = 2; }; }; 948774B110C64DD800E4AEC5 /* SqueakPureObjc-Info 64x64.plist */ = { uiCtxt = { sepNavWindowFrame = "{{354, 18}, {1326, 1010}}"; }; }; 9487755C10C64FF100E4AEC5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6591F0DDD03FE00358328 /* ZipPlugin.c */; name = "ZipPlugin.c: 54"; rLen = 11; rLoc = 1700; rType = 0; vrLen = 2153; vrLoc = 710; }; 9487755D10C64FF100E4AEC5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */; name = "UUIDPlugin.c: 114"; rLen = 19; rLoc = 2745; rType = 0; vrLen = 1164; vrLoc = 2105; }; 94883B2A0E0C2A5E005A4738 /* aio.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1146, 5525}}"; sepNavSelRange = "{5593, 0}"; sepNavVisRange = "{4842, 1297}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1461, 27508}}"; sepNavSelRange = "{34809, 91}"; sepNavVisRange = "{33997, 1919}"; sepNavWindowFrame = "{{38, 14}, {799, 988}}"; }; }; 9489E678123E0AA300ECCD51 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */; name = "SqueakNoOGLIPhoneAppDelegate.h: 60"; rLen = 12; rLoc = 3167; rType = 0; vrLen = 3201; vrLoc = 109; }; 9489E68F123E0D7900ECCD51 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Entitlements.plist; rLen = 0; rLoc = 9223372036854775808; }; 948C0820112DE98D0017EE7F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948C0821112DE98D0017EE7F /* interp.c */; name = "interp.c: 4824"; rLen = 58; rLoc = 159330; rType = 0; vrLen = 1795; vrLoc = 158125; }; 948C0821112DE98D0017EE7F /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/src/vm/interp.c; sourceTree = "<absolute>"; }; 948DB86B123B76F40002F636 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C540E81500200C98131 /* SqView.m */; name = "SqView.m: 409"; rLen = 1; rLoc = 11128; rType = 0; vrLen = 1589; vrLoc = 10506; }; 948DB86E123B76F40002F636 /* SqueakGL.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = SqueakGL.c; path = "/Users/johnmci/Documents/Squeak/Disney Related Changes/plugin-build/Squeak3DX/SqueakGL.c"; sourceTree = "<absolute>"; }; 948FAA0310BF855500BE88CF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948FAA0410BF855500BE88CF /* string.h */; name = "string.h: 85"; rLen = 35; rLoc = 3458; rType = 0; vrLen = 2317; vrLoc = 3588; }; 948FAA0410BF855500BE88CF /* string.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = string.h; path = /Developer/SDKs/MacOSX10.5.sdk/usr/include/string.h; sourceTree = "<absolute>"; }; 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5838E10BF3E080073FD63 /* AudioQueue.h */; name = "AudioQueue.h: 695"; rLen = 0; rLoc = 34190; rType = 0; vrLen = 3087; vrLoc = 33171; }; 949198B010BC8DFC00C629D1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88C0E10AF4196007CB39E /* NSGeometry.h */; name = "NSGeometry.h: 100"; rLen = 74; rLoc = 2081; rType = 0; vrLen = 1067; vrLoc = 1388; }; 949198C910BC8FBB00C629D1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C2F910B32D2A000BF3DE /* NSString.h */; name = "NSString.h: 103"; rLen = 7; rLoc = 4785; rType = 0; vrLen = 3169; vrLoc = 3123; }; 9492450510BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492450610BA42EF00E726F5 /* SqueakApplication.h */; name = "SqueakApplication.h: 12"; rLen = 17; rLoc = 192; rType = 0; vrLen = 237; vrLoc = 0; }; 9492450610BA42EF00E726F5 /* SqueakApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakApplication.h; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/SqueakApplication.h"; sourceTree = "<absolute>"; }; 9492450710BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492450810BA42EF00E726F5 /* SqueakApplication.m */; name = "SqueakApplication.m: 2"; rLen = 17; rLoc = 7; rType = 0; vrLen = 1109; vrLoc = 0; }; 9492450810BA42EF00E726F5 /* SqueakApplication.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakApplication.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/SqueakApplication.m"; sourceTree = "<absolute>"; }; 9492450910BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945F30620E0C6A5000CFF3DC /* SqueakApplication.m */; name = "SqueakApplication.m: 12"; rLen = 611; rLoc = 185; rType = 0; vrLen = 797; vrLoc = 0; }; 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 674}}"; sepNavSelRange = "{1872, 0}"; sepNavVisRange = "{0, 1877}"; }; }; 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 806}}"; sepNavSelRange = "{1942, 10}"; sepNavVisRange = "{1096, 1337}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9492455D10BA462B00E726F5 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 949245B210BA4A6200E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492455D10BA462B00E726F5 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1937"; rLen = 17; rLoc = 51207; rType = 0; vrLen = 1549; vrLoc = 51264; }; 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94360A8C10E84CC90060221A /* NSException.h */; name = "NSException.h: 67"; rLen = 9; rLoc = 2116; rType = 0; vrLen = 2363; vrLoc = 1177; }; 9496D5CD10FAFA29007762DE /* sqSqueakOSXNSView.m:375 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-doCommandBySelector:"; hitCount = 0; ignoreCount = 0; lineNumber = 375; location = Squeak; modificationTime = 306811863.543633; originalNumberOfMultipleMatches = 1; state = 2; }; 94993996123E2D34005260E4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B6E9D910BC775E00333E9E /* English */; name = "Localizable.strings: 9"; rLen = 0; rLoc = 238; rType = 0; vrLen = 238; vrLoc = 0; }; 949AD25011E5469C006D6BF4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF710DDCB234009912BF /* macintoshextra.c */; name = "macintoshextra.c: 33"; rLen = 6; rLoc = 1040; rType = 0; vrLen = 1922; vrLoc = 0; }; 949CDD0612496F030034C107 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 29B97316FDCFA39411CA2CEA /* main.m */; name = "main.m: 44"; rLen = 0; rLoc = 1872; rType = 0; vrLen = 2149; vrLoc = 0; }; 949CDD0712496F030034C107 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */; name = "SqueakNoOGLIPhoneAppDelegate.m: 64"; rLen = 8; rLoc = 2481; rType = 0; vrLen = 2001; vrLoc = 1560; }; 949CDD0812496F030034C107 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */; name = "sqSqueakMainApplication+attributes.m: 63"; rLen = 13; rLoc = 2654; rType = 0; vrLen = 1981; vrLoc = 1894; }; 949DDD4811D13F630017F79B /* NSDateFormatter.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDateFormatter.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDateFormatter.h; sourceTree = "<absolute>"; }; 949DDD6D11D141080017F79B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949DDD4811D13F630017F79B /* NSDateFormatter.h */; name = "NSDateFormatter.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2173; vrLoc = 0; }; 949E5B970DE3623B007388E0 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {950, 755}}"; sepNavSelRange = "{1860, 0}"; sepNavVisRange = "{0, 2260}"; sepNavWindowFrame = "{{21, 20}, {694, 1008}}"; }; }; 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1202, 2626}}"; sepNavSelRange = "{2633, 45}"; sepNavVisRange = "{0, 2530}"; sepNavWindowFrame = "{{152, 50}, {1040, 978}}"; }; }; 949EFD7D0FF17FED00F540EB /* ObjectiveCPlugin.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ObjectiveCPlugin.c; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/src/vm/intplugins/ObjectiveCPlugin/ObjectiveCPlugin.c; sourceTree = "<absolute>"; }; 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 598}}"; sepNavSelRange = "{1867, 14}"; sepNavVisRange = "{0, 2022}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 1417}}"; sepNavSelRange = "{2521, 0}"; sepNavVisRange = "{2069, 2745}"; sepNavWindowFrame = "{{812, 34}, {818, 994}}"; }; }; 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{1898, 31}"; sepNavVisRange = "{0, 1966}"; }; }; 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 793}}"; sepNavSelRange = "{2012, 17}"; sepNavVisRange = "{785, 536}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1039, 796}}"; sepNavSelRange = "{1280, 0}"; sepNavVisRange = "{0, 1983}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 676}}"; sepNavSelRange = "{1967, 6}"; sepNavVisRange = "{0, 2166}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0EBB20DE608350071C8B9 /* squeakAudioVideoPipeLineSignalInterface.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = squeakAudioVideoPipeLineSignalInterface.c; path = "/Volumes/pm/Mail Downloads/squeakAudioVideoPipeLineSignalInterface.c"; sourceTree = "<absolute>"; }; 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 598}}"; sepNavSelRange = "{2009, 11}"; sepNavVisRange = "{3, 2024}"; sepNavWindowFrame = "{{15, 4}, {1042, 1024}}"; }; }; 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1144}}"; sepNavSelRange = "{2268, 85}"; sepNavVisRange = "{1788, 1208}"; sepNavWindowFrame = "{{744, 20}, {847, 985}}"; }; }; 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {854, 738}}"; sepNavSelRange = "{7, 16}"; sepNavVisRange = "{0, 1798}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{1957, 42}"; sepNavVisRange = "{0, 2013}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1878, 6}"; sepNavVisRange = "{0, 1891}"; sepNavWindowFrame = "{{38, 145}, {1288, 857}}"; }; }; 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{88, 1697}"; sepNavVisRange = "{0, 1901}"; }; }; 94A1B1B810B9C1A800C64473 /* sqMacUIEventsUniversal.c:1429 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 942ABEC410AA34820086D908 /* sqMacUIEventsUniversal.c */; hitCount = 0; ignoreCount = 0; lineNumber = 1429; location = "Squeak VM Opt"; modificationTime = 306811863.5429469; originalNumberOfMultipleMatches = 1; state = 2; }; 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 859}}"; sepNavSelRange = "{1866, 25}"; sepNavVisRange = "{0, 2034}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 859}}"; sepNavSelRange = "{1829, 38}"; sepNavVisRange = "{0, 1908}"; }; }; 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B2AB10B9E92A00C64473 /* NSCache.h */; name = "NSCache.h: 25"; rLen = 52; rLoc = 427; rType = 0; vrLen = 1024; vrLoc = 0; }; 94A1B2AB10B9E92A00C64473 /* NSCache.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCache.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSCache.h; sourceTree = "<absolute>"; }; 94A1B41E10BA05E600C64473 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B41F10BA05E600C64473 /* objc.h */; name = "objc.h: 64"; rLen = 46; rLoc = 1748; rType = 0; vrLen = 1238; vrLoc = 1195; }; 94A1B41F10BA05E600C64473 /* objc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = objc.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/objc/objc.h; sourceTree = "<absolute>"; }; 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1169, 764}}"; sepNavSelRange = "{78, 0}"; sepNavVisRange = "{0, 1806}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1781}}"; sepNavSelRange = "{1975, 0}"; sepNavVisRange = "{1792, 903}"; sepNavWindowFrame = "{{20, 20}, {694, 1008}}"; }; }; 94A349B50DDCDBE200D1D4A9 /* iPhone.image */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {807273, 3.9741e+06}}"; sepNavSelRange = "{18277000, 0}"; sepNavVisRange = "{1158, 1564}"; }; }; 94A3D780122CB52800DCE9B4 /* johnmci.pbxuser */ = { isa = PBXFileReference; lastKnownFileType = text; name = johnmci.pbxuser; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc.xcodeproj/johnmci.pbxuser; sourceTree = "<absolute>"; }; 94A3D790122CB56400DCE9B4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A3D780122CB52800DCE9B4 /* johnmci.pbxuser */; name = "johnmci.pbxuser: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 3097; vrLoc = 0; }; 94A3ED241228213E00DF449D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */; name = "sqSqueakOSXApplication+imageReadWrite.h: 42"; rLen = 0; rLoc = 1939; rType = 0; vrLen = 2010; vrLoc = 0; }; 94A3ED251228213E00DF449D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */; name = "sqSqueakOSXInfoPlistInterface.m: 137"; rLen = 27; rLoc = 5705; rType = 0; vrLen = 2312; vrLoc = 4190; }; 94A3ED261228213E00DF449D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */; name = "sqSqueakOSXApplication+attributes.h: 6"; rLen = 1692; rLoc = 109; rType = 0; vrLen = 1897; vrLoc = 0; }; 94A3ED891228429500DF449D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */; name = "sqiPhoneScreenAndWindow.h: 42"; rLen = 23; rLoc = 1909; rType = 0; vrLen = 1943; vrLoc = 0; }; 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AB2E6B0E003879006A79E4 /* npsqueak.c */; name = "npsqueak.c: 984"; rLen = 1; rLoc = 28701; rType = 0; vrLen = 2346; vrLoc = 28415; }; 94AB2E6B0E003879006A79E4 /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak copy 1/npsqueak.c"; sourceTree = "<absolute>"; }; 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AB2E6D0E003879006A79E4 /* npsqueak.c */; name = "npsqueak.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1371; vrLoc = 0; }; 94AB2E6D0E003879006A79E4 /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak copy/npsqueak.c"; sourceTree = "<absolute>"; }; 94B1514E0DE2CE530059F208 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B1514F0DE2CE530059F208 /* sqMacWindowUniversal.c */; name = "sqMacWindowUniversal.c: 580"; rLen = 14; rLoc = 21540; rType = 0; vrLen = 1552; vrLoc = 21405; }; 94B1514F0DE2CE530059F208 /* sqMacWindowUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindowUniversal.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/vm/sqMacWindowUniversal.c"; sourceTree = "<absolute>"; }; 94B6A65D122C6E760069D952 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */; name = "sqVirtualMachine.c: 169"; rLen = 13; rLoc = 6331; rType = 0; vrLen = 2104; vrLoc = 5268; }; 94B6E9D910BC775E00333E9E /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {955, 760}}"; sepNavSelRange = "{238, 0}"; sepNavVisRange = "{0, 238}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 94B7898910C4F95E005EA70D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CFE6BD10BE63A900847DF5 /* SqViewEventSensor.m */; name = "SqViewEventSensor.m: 80"; rLen = 22; rLoc = 2119; rType = 0; vrLen = 1922; vrLoc = 499; }; 94B88C540E81500200C98131 /* SqView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqView.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/SqueakAppKit/SqView.m"; sourceTree = "<absolute>"; }; 94B88C560E81500200C98131 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C570E81500200C98131 /* MsgContext.m */; name = "MsgContext.m: 97"; rLen = 26; rLoc = 3007; rType = 0; vrLen = 2255; vrLoc = 4983; }; 94B88C570E81500200C98131 /* MsgContext.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MsgContext.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/MsgContext.m"; sourceTree = "<absolute>"; }; 94B88C640E81500200C98131 /* SqueakObjcBridge.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakObjcBridge.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakObjcBridge.m"; sourceTree = "<absolute>"; }; 94B8F4B910CF5BFF00F0DD6B /* PBXBookmarkGroup */ = { isa = PBXBookmarkGroup; children = ( 94B8F54210CF675200F0DD6B /* PBXBookmark */, ); name = Root; }; 94B8F54210CF675200F0DD6B /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9402DD6F10CE0E91005C2102 /* SqViewClut.m */; }; 94B8F54E10CF677800F0DD6B /* SqViewClut.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 455}}"; sepNavSelRange = "{66, 17}"; sepNavVisRange = "{0, 254}"; }; }; 94B9528510E6B79E00DC476A /* MacMenubarPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3354}}"; sepNavSelRange = "{1194, 0}"; sepNavVisRange = "{1043, 535}"; sepNavWindowFrame = "{{602, 4}, {1078, 1014}}"; }; }; 94B9533310E6BD7100DC476A /* MacMenuOS9ToOSX.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 537}}"; sepNavSelRange = "{201, 0}"; sepNavVisRange = "{0, 201}"; sepNavWindowFrame = "{{554, 14}, {1078, 1014}}"; }; }; 94B9533410E6BD7100DC476A /* MacMenuOS9ToOSX.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3705}}"; sepNavSelRange = "{1329, 39}"; sepNavVisRange = "{979, 704}"; sepNavWindowFrame = "{{15, 9}, {1078, 1014}}"; }; }; 94B954A010E6D0F700DC476A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */; name = "MacMenubarPlugin.c: 711"; rLen = 6; rLoc = 20318; rType = 0; vrLen = 1584; vrLoc = 19909; }; 94BCAAE810AB6C3500F87527 /* NSFileManager.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSFileManager.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFileManager.h; sourceTree = "<absolute>"; }; 94BCAB0410AB6DC000F87527 /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {996, 793}}"; sepNavSelRange = "{2017, 0}"; sepNavVisRange = "{0, 2022}"; }; }; 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1227, 1482}}"; sepNavSelRange = "{2931, 56}"; sepNavVisRange = "{1654, 2388}"; sepNavWindowFrame = "{{38, 4}, {1274, 998}}"; }; }; 94BCAC0310AB759300F87527 /* NSURL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSURL.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURL.h; sourceTree = "<absolute>"; }; 94BCAC3710AB79DA00F87527 /* NSArray.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSArray.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSArray.h; sourceTree = "<absolute>"; }; 94BCAC3C10AB79DA00F87527 /* NSDictionary.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDictionary.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDictionary.h; sourceTree = "<absolute>"; }; 94BCAC4E10AB7A2B00F87527 /* NSProcessInfo.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSProcessInfo.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSProcessInfo.h; sourceTree = "<absolute>"; }; 94BCACE310AB8AE300F87527 /* NSObject.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObject.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObject.h; sourceTree = "<absolute>"; }; 94BCAD0410AB922600F87527 /* NSObjCRuntime.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObjCRuntime.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObjCRuntime.h; sourceTree = "<absolute>"; }; 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 572}}"; sepNavSelRange = "{1876, 14}"; sepNavVisRange = "{0, 1897}"; }; }; 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2093}}"; sepNavSelRange = "{3476, 0}"; sepNavVisRange = "{2592, 2204}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC4E10AB7A2B00F87527 /* NSProcessInfo.h */; name = "NSProcessInfo.h: 20"; rLen = 13; rLoc = 437; rType = 0; vrLen = 861; vrLoc = 0; }; 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 1066}}"; sepNavSelRange = "{855, 0}"; sepNavVisRange = "{710, 3469}"; sepNavWindowFrame = "{{29, 4}, {1326, 1010}}"; }; }; 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3471}}"; sepNavSelRange = "{7638, 17}"; sepNavVisRange = "{6700, 1350}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE9110ACA3A300F87527 /* NSUserDefaults.h */; name = "NSUserDefaults.h: 13"; rLen = 14; rLoc = 365; rType = 0; vrLen = 2118; vrLoc = 0; }; 94BCAE9110ACA3A300F87527 /* NSUserDefaults.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSUserDefaults.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSUserDefaults.h; sourceTree = "<absolute>"; }; 94BCAE9D10ACA3A300F87527 /* NSBundle.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSBundle.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSBundle.h; sourceTree = "<absolute>"; }; 94BCAEDF10ACAE2500F87527 /* NSValue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSValue.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValue.h; sourceTree = "<absolute>"; }; 94BCAF7D10ACC0D900F87527 /* NSPathUtilities.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPathUtilities.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSPathUtilities.h; sourceTree = "<absolute>"; }; 94BCAFC410ACC89100F87527 /* string.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = string.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/string.h; sourceTree = "<absolute>"; }; 94BCAFC710ACC89100F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFC810ACC89100F87527 /* CFBundle.h */; name = "CFBundle.h: 113"; rLen = 33; rLoc = 4376; rType = 0; vrLen = 2277; vrLoc = 2928; }; 94BCAFC810ACC89100F87527 /* CFBundle.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFBundle.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFBundle.h; sourceTree = "<absolute>"; }; 94BCAFCA10ACC89100F87527 /* CFURL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFURL.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFURL.h; sourceTree = "<absolute>"; }; 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 936}}"; sepNavSelRange = "{2227, 20}"; sepNavVisRange = "{0, 2553}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94BCE6870DDDECB800F38F31 /* HostWindowPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 728}}"; sepNavSelRange = "{996, 13}"; sepNavVisRange = "{0, 2779}"; sepNavWindowFrame = "{{15, 59}, {1394, 964}}"; }; }; 94BCE7390DDDEF8200F38F31 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659080DDD03FE00358328 /* MIDIPlugin.c */; name = "MIDIPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 864; vrLoc = 0; }; 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 611}}"; sepNavSelRange = "{20, 18}"; sepNavVisRange = "{0, 275}"; }; }; 94BCE7A60DDDF8F800F38F31 /* sqaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1313}}"; sepNavSelRange = "{3879, 7}"; sepNavVisRange = "{2703, 1444}"; }; }; 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 691}}"; sepNavSelRange = "{2306, 110}"; sepNavVisRange = "{0, 2421}"; sepNavWindowFrame = "{{73, 45}, {905, 983}}"; }; }; 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1272, 3081}}"; sepNavSelRange = "{11094, 0}"; sepNavVisRange = "{1938, 2200}"; sepNavWindowFrame = "{{775, 1}, {905, 983}}"; }; }; 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {858, 2561}}"; sepNavSelRange = "{2124, 115}"; sepNavVisRange = "{1236, 1931}"; sepNavWindowFrame = "{{775, 4}, {905, 983}}"; }; }; 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {858, 3341}}"; sepNavSelRange = "{2225, 50}"; sepNavVisRange = "{647, 2896}"; sepNavWindowFrame = "{{15, 40}, {905, 983}}"; }; }; 94BD816F11C8A58D00556751 /* sqManualSurface.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2145}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2172}"; }; }; 94BE8B2C123D943800C89FDD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; name = "sqSqueakIPhoneClipboardAPI.m: 19"; rLen = 13; rLoc = 586; rType = 0; vrLen = 1345; vrLoc = 0; }; 94C0D1AC112D5DAE00213581 /* sqSqueakScreenAPI.m:79 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 79; location = Squeak; modificationTime = 306811863.5436701; originalNumberOfMultipleMatches = 1; state = 2; }; 94C16BCB123D78C200A8622A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */; name = "sqSqueakOSXApplication+events.m: 94"; rLen = 0; rLoc = 4315; rType = 0; vrLen = 1968; vrLoc = 8312; }; 94C16BD5123D7C9300A8622A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658E00DDD03FE00358328 /* interp.c */; name = "interp.c: 15817"; rLen = 19; rLoc = 512103; rType = 0; vrLen = 1945; vrLoc = 511094; }; 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {955, 1157}}"; sepNavSelRange = "{2337, 10}"; sepNavVisRange = "{1313, 2364}"; sepNavWindowFrame = "{{15, 4}, {719, 1019}}"; }; }; 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 9737}}"; sepNavSelRange = "{2976, 13}"; sepNavVisRange = "{2225, 1245}"; sepNavWindowFrame = "{{25, 4}, {860, 1024}}"; }; }; 94C206AA10AF5107002F4160 /* NSImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSImageRep.h; sourceTree = "<absolute>"; }; 94C206D210AF5536002F4160 /* CGImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGImage.h; sourceTree = "<absolute>"; }; 94C206D810AF5536002F4160 /* NSGraphicsContext.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGraphicsContext.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphicsContext.h; sourceTree = "<absolute>"; }; 94C206DA10AF5536002F4160 /* CGContext.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGContext.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGContext.h; sourceTree = "<absolute>"; }; 94C2070610AF5A9E002F4160 /* NSImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSImage.h; sourceTree = "<absolute>"; }; 94C2074310AF5FB7002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206AA10AF5107002F4160 /* NSImageRep.h */; name = "NSImageRep.h: 45"; rLen = 33; rLoc = 1303; rType = 0; vrLen = 1800; vrLoc = 0; }; 94C207E910AF66D7002F4160 /* NSWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindow.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h; sourceTree = "<absolute>"; }; 94C2091010AF7413002F4160 /* CIImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIImage.h; sourceTree = "<absolute>"; }; 94C2091210AF7413002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2091310AF7413002F4160 /* NSCIImageRep.h */; name = "NSCIImageRep.h: 29"; rLen = 26; rLoc = 776; rType = 0; vrLen = 841; vrLoc = 0; }; 94C2091310AF7413002F4160 /* NSCIImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCIImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSCIImageRep.h; sourceTree = "<absolute>"; }; 94C2092A10AF769A002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2091010AF7413002F4160 /* CIImage.h */; name = "CIImage.h: 98"; rLen = 15; rLoc = 3526; rType = 0; vrLen = 1904; vrLoc = 2714; }; 94C2092D10AF769A002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206D810AF5536002F4160 /* NSGraphicsContext.h */; name = "NSGraphicsContext.h: 59"; rLen = 39; rLoc = 2654; rType = 0; vrLen = 1997; vrLoc = 2593; }; 94C367C010AF9C0A0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C367C110AF9C0A0041953A /* Aliases.h */; name = "Aliases.h: 286"; rLen = 34; rLoc = 9594; rType = 0; vrLen = 1442; vrLoc = 8779; }; 94C367C110AF9C0A0041953A /* Aliases.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Aliases.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/Aliases.h; sourceTree = "<absolute>"; }; 94C367C210AF9C0A0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C367C310AF9C0A0041953A /* LSInfo.h */; name = "LSInfo.h: 257"; rLen = 22; rLoc = 9965; rType = 0; vrLen = 1369; vrLoc = 9104; }; 94C367C310AF9C0A0041953A /* LSInfo.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LSInfo.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSInfo.h; sourceTree = "<absolute>"; }; 94C367D110AF9C830041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFCA10ACC89100F87527 /* CFURL.h */; name = "CFURL.h: 636"; rLen = 20; rLoc = 30806; rType = 0; vrLen = 2114; vrLoc = 29706; }; 94C3682410AFA39A0041953A /* macintoshosxextra.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {996, 770}}"; sepNavSelRange = "{192, 0}"; sepNavVisRange = "{0, 192}"; }; }; 94C3682510AFA39A0041953A /* macintoshosxextra.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 572}}"; sepNavSelRange = "{927, 14}"; sepNavVisRange = "{0, 1287}"; }; }; 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 585}}"; sepNavSelRange = "{1874, 6}"; sepNavVisRange = "{0, 2040}"; sepNavWindowFrame = "{{38, 24}, {1017, 978}}"; }; }; 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2028}}"; sepNavSelRange = "{4018, 8}"; sepNavVisRange = "{3843, 1708}"; sepNavWindowFrame = "{{254, 9}, {1426, 1019}}"; }; }; 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 616}}"; sepNavSelRange = "{9, 12}"; sepNavVisRange = "{0, 1788}"; }; }; 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 858}}"; sepNavSelRange = "{2229, 0}"; sepNavVisRange = "{909, 1896}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 585}}"; sepNavSelRange = "{1949, 6}"; sepNavVisRange = "{0, 2021}"; }; }; 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 624}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1651}"; }; }; 94C368F610AFAEA60041953A /* QuickdrawTypes.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QuickdrawTypes.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/Headers/QuickdrawTypes.h; sourceTree = "<absolute>"; }; 94C368F910AFAEA60041953A /* CFByteOrder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFByteOrder.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFByteOrder.h; sourceTree = "<absolute>"; }; 94C3696310AFB7550041953A /* NSGraphics.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGraphics.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphics.h; sourceTree = "<absolute>"; }; 94C3696410AFB7550041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C368F610AFAEA60041953A /* QuickdrawTypes.h */; name = "QuickdrawTypes.h: 262"; rLen = 16; rLoc = 8337; rType = 0; vrLen = 1520; vrLoc = 7208; }; 94C3696610AFB7550041953A /* NSBitmapImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSBitmapImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSBitmapImageRep.h; sourceTree = "<absolute>"; }; 94C3698D10B082DF0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C368F910AFAEA60041953A /* CFByteOrder.h */; name = "CFByteOrder.h: 78"; rLen = 20; rLoc = 1887; rType = 0; vrLen = 1136; vrLoc = 1325; }; 94C3699110B082DF0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3699210B082DF0041953A /* NSColor.h */; name = "NSColor.h: 65"; rLen = 7; rLoc = 3749; rType = 0; vrLen = 2379; vrLoc = 2696; }; 94C3699210B082DF0041953A /* NSColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSColor.h; sourceTree = "<absolute>"; }; 94C36A6D10B091BB0041953A /* NSCursor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCursor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSCursor.h; sourceTree = "<absolute>"; }; 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 715}}"; sepNavSelRange = "{1877, 0}"; sepNavVisRange = "{854, 1965}"; sepNavWindowFrame = "{{149, 4}, {905, 983}}"; }; }; 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1412, 5057}}"; sepNavSelRange = "{5031, 11}"; sepNavVisRange = "{4186, 1935}"; sepNavWindowFrame = "{{15, 4}, {1131, 1019}}"; }; }; 94C36AD910B0AF960041953A /* NSEvent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSEvent.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSEvent.h; sourceTree = "<absolute>"; }; 94C36C9710B0CF290041953A /* Info-iPhone.plist */ = { uiCtxt = { sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 94C3AC3E11E6C9D000DBE1E9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */; name = "sqUnixUUID.c: 2"; rLen = 18; rLoc = 20; rType = 0; vrLen = 275; vrLoc = 0; }; 94C4B80F10C06C4700CD4F90 /* configx.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {994, 799}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1946}"; }; }; 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 724}}"; sepNavSelRange = "{1876, 22}"; sepNavVisRange = "{0, 1939}"; }; }; 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 793}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1758}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 94C4B83610C0708F00CD4F90 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659160DDD03FE00358328 /* SoundPlugin.c */; name = "SoundPlugin.c: 103"; rLen = 9; rLoc = 2783; rType = 0; vrLen = 1524; vrLoc = 1817; }; 94C887D410ADCC0D007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C887D510ADCC0D007CB39E /* NSThread.h */; name = "NSThread.h: 75"; rLen = 96; rLoc = 1964; rType = 0; vrLen = 2073; vrLoc = 503; }; 94C887D510ADCC0D007CB39E /* NSThread.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSThread.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSThread.h; sourceTree = "<absolute>"; }; 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {995, 745}}"; sepNavSelRange = "{1939, 0}"; sepNavVisRange = "{0, 2010}"; }; }; 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1755}}"; sepNavSelRange = "{3696, 8}"; sepNavVisRange = "{2509, 1374}"; sepNavWindowFrame = "{{685, 4}, {878, 1019}}"; }; }; 94C888B710ADE75B007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE9D10ACA3A300F87527 /* NSBundle.h */; name = "NSBundle.h: 11"; rLen = 8; rLoc = 335; rType = 0; vrLen = 2317; vrLoc = 0; }; 94C88B6810AF26F8007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88B6910AF26F8007CB39E /* squeakProxy.m */; name = "squeakProxy.m: 124"; rLen = 22; rLoc = 3876; rType = 0; vrLen = 1083; vrLoc = 3252; }; 94C88B6910AF26F8007CB39E /* squeakProxy.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = squeakProxy.m; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/Blob/platforms/Mac OSObjC/plugins/SqueakObjectiveC/squeakProxy.m"; sourceTree = "<absolute>"; }; 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 676}}"; sepNavSelRange = "{1911, 85}"; sepNavVisRange = "{55, 2056}"; sepNavWindowFrame = "{{16, 4}, {1392, 1019}}"; }; }; 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 975}}"; sepNavSelRange = "{2308, 15}"; sepNavVisRange = "{983, 1403}"; sepNavWindowFrame = "{{334, 25}, {1346, 974}}"; }; }; 94C88C0E10AF4196007CB39E /* NSGeometry.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGeometry.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSGeometry.h; sourceTree = "<absolute>"; }; 94C8D074123EC12D0019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; name = "SqueakUIView.m: 68"; rLen = 45; rLoc = 2633; rType = 0; vrLen = 2530; vrLoc = 0; }; 94C8D0A9123EC3920019544B /* gl.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = gl.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/gl.h; sourceTree = "<absolute>"; }; 94C8D0AF123EC4A90019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C8D0A9123EC3920019544B /* gl.h */; name = "gl.h: 375"; rLen = 16; rLoc = 12095; rType = 0; vrLen = 1941; vrLoc = 10609; }; 94C8D26B123EEE2E0019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */; name = "SqueakUIController.m: 71"; rLen = 0; rLoc = 3142; rType = 0; vrLen = 2036; vrLoc = 2103; }; 94CA691410B1CAD8007F207C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */; name = "SecurityPlugin.c: 109"; rLen = 14; rLoc = 3415; rType = 0; vrLen = 1013; vrLoc = 2696; }; 94CAA52E123DCAB700651F54 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */; name = "SqueakUIView.h: 43"; rLen = 0; rLoc = 1860; rType = 0; vrLen = 2260; vrLoc = 0; }; 94CAA5D8123DDCFE00651F54 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */; name = "sqSqueakOSXNSView.h: 56"; rLen = 10; rLoc = 2337; rType = 0; vrLen = 2364; vrLoc = 1313; }; 94CAA648123DE2EF00651F54 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */; name = "sqSqueakOSXApplication+imageReadWrite.m: 126"; rLen = 27; rLoc = 4983; rType = 0; vrLen = 2097; vrLoc = 3204; }; 94CAC151125FBC1400CF9255 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */; name = "sqSqueakIPhoneApplication+events.m: 229"; rLen = 0; rLoc = 11094; rType = 0; vrLen = 2200; vrLoc = 1938; }; 94CFE4AF10BE3CA600847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659120DDD03FE00358328 /* SoundCodecPrims.c */; name = "SoundCodecPrims.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1395; vrLoc = 0; }; 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C207E910AF66D7002F4160 /* NSWindow.h */; name = "NSWindow.h: 453"; rLen = 8; rLoc = 19650; rType = 0; vrLen = 2322; vrLoc = 18630; }; 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87510B66A74002F81F2 /* SqueakInterpreterEventSensor.m */; name = "SqueakInterpreterEventSensor.m: 54"; rLen = 8; rLoc = 1477; rType = 0; vrLen = 1077; vrLoc = 1241; }; 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89AED10B497F400556475 /* NSResponder.h */; name = "NSResponder.h: 31"; rLen = 12; rLoc = 957; rType = 0; vrLen = 1492; vrLoc = 0; }; 94CFE6BD10BE63A900847DF5 /* SqViewEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewEventSensor.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/SqueakAppKit/SqViewEventSensor.m"; sourceTree = "<absolute>"; }; 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945BA53B10B218F700C2020C /* math.h */; name = "math.h: 379"; rLen = 8; rLoc = 15491; rType = 0; vrLen = 1479; vrLoc = 14505; }; 94CFE70110BE683800847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36AD910B0AF960041953A /* NSEvent.h */; name = "NSEvent.h: 246"; rLen = 6; rLoc = 8572; rType = 0; vrLen = 1801; vrLoc = 7114; }; 94D051D3120CE2D40039F8B7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638B260EAFB77B00A3F155 /* iPhone.changes */; name = "iPhone.changes: 134722"; rLen = 0; rLoc = 4068487; rType = 0; vrLen = 1428; vrLoc = 940; }; 94D12BE412289C66006B7504 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */; name = "BitBltPlugin.c: 2459"; rLen = 0; rLoc = 71472; rType = 0; vrLen = 1211; vrLoc = 71047; }; 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16BFD10BCEFEE00A69A89 /* Document.m */; name = "Document.m: 35"; rLen = 32; rLoc = 1133; rType = 0; vrLen = 1663; vrLoc = 14; }; 94D16BFD10BCEFEE00A69A89 /* Document.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Document.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/Document.m"; sourceTree = "<absolute>"; }; 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942CF46B10BCE44B009BD905 /* NSWindowController.h */; name = "NSWindowController.h: 13"; rLen = 18; rLoc = 224; rType = 0; vrLen = 2830; vrLoc = 0; }; 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBE210BB565100DAD287 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1031"; rLen = 1; rLoc = 27820; rType = 0; vrLen = 1184; vrLoc = 27288; }; 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16C4110BCF3E100A69A89 /* CGDirectDisplay.h */; name = "CGDirectDisplay.h: 336"; rLen = 22; rLoc = 13802; rType = 0; vrLen = 2189; vrLoc = 12694; }; 94D16C4110BCF3E100A69A89 /* CGDirectDisplay.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGDirectDisplay.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGDirectDisplay.h; sourceTree = "<absolute>"; }; 94D16C6510BCF5B700A69A89 /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 94D16CA310BCF93000A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16C6510BCF5B700A69A89 /* NSApplication.h */; name = "NSApplication.h: 269"; rLen = 43; rLoc = 10310; rType = 0; vrLen = 2825; vrLoc = 9201; }; 94D16CAF10BCF96B00A69A89 /* Credits.rtf */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {972, 725}}"; sepNavSelRange = "{51, 0}"; sepNavVisRect = "{{0, 0}, {972, 725}}"; sepNavWindowFrame = "{{175, 9}, {878, 1019}}"; }; }; 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {995, 844}}"; sepNavSelRange = "{581, 14}"; sepNavVisRange = "{0, 1092}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 3029}}"; sepNavSelRange = "{1749, 84}"; sepNavVisRange = "{1665, 2000}"; sepNavWindowFrame = "{{715, -46}, {1326, 1010}}"; }; }; 94D3660B10CEE03900805023 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D3660C10CEE03900805023 /* CIImage.h */; name = "CIImage.h: 32"; rLen = 4; rLoc = 826; rType = 0; vrLen = 2058; vrLoc = 0; }; 94D3660C10CEE03900805023 /* CIImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIImage.h; path = /System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIImage.h; sourceTree = "<absolute>"; }; 94D715CB10B723B200F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D715CC10B723B200F69A71 /* NSData.h */; name = "NSData.h: 45"; rLen = 6; rLoc = 1410; rType = 0; vrLen = 1584; vrLoc = 0; }; 94D715CC10B723B200F69A71 /* NSData.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSData.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSData.h; sourceTree = "<absolute>"; }; 94D7173610B72F8800F69A71 /* FunctionKeyNames.strings */ = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = FunctionKeyNames.strings; path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/FunctionKeyNames.strings; sourceTree = "<absolute>"; }; 94D7174110B72FDF00F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7173610B72F8800F69A71 /* FunctionKeyNames.strings */; name = "FunctionKeyNames.strings: 2"; rLen = 9; rLoc = 29; rType = 0; vrLen = 802; vrLoc = 0; }; 94D7177D10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7177E10B73A3800F69A71 /* SqueakEventQueue.m */; name = "SqueakEventQueue.m: 90"; rLen = 17; rLoc = 2396; rType = 0; vrLen = 1483; vrLoc = 736; }; 94D7177E10B73A3800F69A71 /* SqueakEventQueue.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakEventQueue.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakEventQueue.m"; sourceTree = "<absolute>"; }; 94D7178010B73A3800F69A71 /* SqueakInterpreterEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreterEventSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreterEventSensor.m"; sourceTree = "<absolute>"; }; 94D7178310B73A3800F69A71 /* SqViewInputSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewInputSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewInputSensor.m"; sourceTree = "<absolute>"; }; 94D7178410B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178510B73A3800F69A71 /* SqueakController.m */; name = "SqueakController.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1497; vrLoc = 370; }; 94D7178510B73A3800F69A71 /* SqueakController.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakController.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/SqueakController.m"; sourceTree = "<absolute>"; }; 94D7178610B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178710B73A3800F69A71 /* SqViewBitmapConversion.m */; name = "SqViewBitmapConversion.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1336; vrLoc = 7040; }; 94D7178710B73A3800F69A71 /* SqViewBitmapConversion.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewBitmapConversion.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewBitmapConversion.m"; sourceTree = "<absolute>"; }; 94D7178810B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178910B73A3800F69A71 /* SqView.m */; name = "SqView.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2292; vrLoc = 6209; }; 94D7178910B73A3800F69A71 /* SqView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqView.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqView.m"; sourceTree = "<absolute>"; }; 94D7178A10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178B10B73A3800F69A71 /* SqClipboardHandler.m */; name = "SqClipboardHandler.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1588; vrLoc = 0; }; 94D7178B10B73A3800F69A71 /* SqClipboardHandler.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqClipboardHandler.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqClipboardHandler.m"; sourceTree = "<absolute>"; }; 94D7178C10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178D10B73A3800F69A71 /* CarbonSound.c */; name = "CarbonSound.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2068; vrLoc = 1940; }; 94D7178D10B73A3800F69A71 /* CarbonSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = CarbonSound.c; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/CarbonSound.c"; sourceTree = "<absolute>"; }; 94D7178F10B73A3800F69A71 /* SqueakInterpreterEventSensor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakInterpreterEventSensor.h; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreterEventSensor.h"; sourceTree = "<absolute>"; }; 94D7179110B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7179210B73A3800F69A71 /* FScriptTextView.m */; name = "FScriptTextView.m: 126"; rLen = 138; rLoc = 4464; rType = 0; vrLen = 1701; vrLoc = 4066; }; 94D7179210B73A3800F69A71 /* FScriptTextView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FScriptTextView.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/FScriptTextView.m"; sourceTree = "<absolute>"; }; 94D717BE10B73DD900F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E8D110B67499002F81F2 /* NSRange.h */; name = "NSRange.h: 12"; rLen = 23; rLoc = 213; rType = 0; vrLen = 1181; vrLoc = 0; }; 94D717E610B7421F00F69A71 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakSparklePlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94D717F810B743B800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D717E610B7421F00F69A71 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2301"; rLen = 18; rLoc = 59489; rType = 0; vrLen = 1347; vrLoc = 59154; }; 94D7181B10B74A2500F69A71 /* sqSqueakOSXNSView.m:488 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; hitCount = 0; ignoreCount = 0; lineNumber = 488; location = Squeak; modificationTime = 306811863.542772; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7181D10B74A2600F69A71 /* sqSqueakOSXNSView.m:484 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-firstRectForCharacterRange:"; hitCount = 0; ignoreCount = 0; lineNumber = 484; location = Squeak; modificationTime = 306811863.542882; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7182310B74A2900F69A71 /* sqSqueakOSXNSView.m:472 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-attributedSubstringFromRange:"; hitCount = 0; ignoreCount = 0; lineNumber = 472; location = Squeak; modificationTime = 306811863.542899; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7182910B74A4A00F69A71 /* sqSqueakOSXNSView.m:460 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-unmarkText"; hitCount = 0; ignoreCount = 0; lineNumber = 460; location = Squeak; modificationTime = 306811863.542913; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7182D10B74A4E00F69A71 /* sqSqueakOSXNSView.m:468 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-conversationIdentifier"; hitCount = 0; ignoreCount = 0; lineNumber = 468; location = Squeak; modificationTime = 306811863.542924; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7183310B74BD100F69A71 /* sqSqueakOSXNSView.m:500 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-drawsVerticallyForCharacterAtIndex:"; hitCount = 0; ignoreCount = 0; lineNumber = 500; location = Squeak; modificationTime = 306811863.542935; originalNumberOfMultipleMatches = 1; state = 2; }; 94D7183810B74BF300F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7183910B74BF300F69A71 /* NSInputManager.h */; name = "NSInputManager.h: 21"; rLen = 68; rLoc = 621; rType = 0; vrLen = 1979; vrLoc = 0; }; 94D7183910B74BF300F69A71 /* NSInputManager.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSInputManager.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSInputManager.h; sourceTree = "<absolute>"; }; 94D7183A10B74BF300F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7183B10B74BF300F69A71 /* NSTextInputClient.h */; name = "NSTextInputClient.h: 32"; rLen = 20; rLoc = 1358; rType = 0; vrLen = 2207; vrLoc = 0; }; 94D7183B10B74BF300F69A71 /* NSTextInputClient.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextInputClient.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextInputClient.h; sourceTree = "<absolute>"; }; 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5310B5B9CE00F8C034 /* cl.h */; name = "cl.h: 118"; rLen = 0; rLoc = 4914; rType = 0; vrLen = 2396; vrLoc = 3357; }; 94D73E5310B5B9CE00F8C034 /* cl.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cl.h; path = /System/Library/Frameworks/OpenCL.framework/Versions/A/Headers/cl.h; sourceTree = "<absolute>"; }; 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5510B5B9CE00F8C034 /* float-i32.h */; name = "float-i32.h: 20"; rLen = 35; rLoc = 653; rType = 0; vrLen = 2227; vrLoc = 0; }; 94D73E5510B5B9CE00F8C034 /* float-i32.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i32.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i32.h"; sourceTree = "<absolute>"; }; 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5710B5B9CE00F8C034 /* float-i128.h */; name = "float-i128.h: 19"; rLen = 11; rLoc = 649; rType = 0; vrLen = 2262; vrLoc = 0; }; 94D73E5710B5B9CE00F8C034 /* float-i128.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i128.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i128.h"; sourceTree = "<absolute>"; }; 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5910B5B9CE00F8C034 /* float-i386.h */; name = "float-i386.h: 20"; rLen = 11; rLoc = 670; rType = 0; vrLen = 2261; vrLoc = 0; }; 94D73E5910B5B9CE00F8C034 /* float-i386.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i386.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i386.h"; sourceTree = "<absolute>"; }; 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5B10B5B9CE00F8C034 /* float-m68k.h */; name = "float-m68k.h: 20"; rLen = 11; rLoc = 677; rType = 0; vrLen = 2268; vrLoc = 0; }; 94D73E5B10B5B9CE00F8C034 /* float-m68k.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-m68k.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-m68k.h"; sourceTree = "<absolute>"; }; 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5D10B5B9CE00F8C034 /* float-sh.h */; name = "float-sh.h: 19"; rLen = 11; rLoc = 642; rType = 0; vrLen = 2198; vrLoc = 0; }; 94D73E5D10B5B9CE00F8C034 /* float-sh.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-sh.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-sh.h"; sourceTree = "<absolute>"; }; 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5F10B5B9CE00F8C034 /* float-sparc.h */; name = "float-sparc.h: 20"; rLen = 11; rLoc = 729; rType = 0; vrLen = 2320; vrLoc = 0; }; 94D73E5F10B5B9CE00F8C034 /* float-sparc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-sparc.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-sparc.h"; sourceTree = "<absolute>"; }; 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6110B5B9CE00F8C034 /* float-vax.h */; name = "float-vax.h: 6"; rLen = 0; rLoc = 173; rType = 0; vrLen = 2188; vrLoc = 0; }; 94D73E6110B5B9CE00F8C034 /* float-vax.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-vax.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-vax.h"; sourceTree = "<absolute>"; }; 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6310B5B9CE00F8C034 /* float-i64.h */; name = "float-i64.h: 20"; rLen = 35; rLoc = 660; rType = 0; vrLen = 2261; vrLoc = 0; }; 94D73E6310B5B9CE00F8C034 /* float-i64.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i64.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i64.h"; sourceTree = "<absolute>"; }; 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6510B5B9CE00F8C034 /* dummyFFI.c */; name = "dummyFFI.c: 116"; rLen = 19; rLoc = 2641; rType = 0; vrLen = 813; vrLoc = 2018; }; 94D73E6510B5B9CE00F8C034 /* dummyFFI.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dummyFFI.c; path = /Users/johnmci/Shared/plugins/SqueakFFIPrims/dummyFFI.c; sourceTree = "<absolute>"; }; 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6910B5B9CE00F8C034 /* c90-float-1.c */; name = "c90-float-1.c: 47"; rLen = 11; rLoc = 855; rType = 0; vrLen = 1089; vrLoc = 0; }; 94D73E6910B5B9CE00F8C034 /* c90-float-1.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "c90-float-1.c"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/testsuite/gcc.dg/c90-float-1.c"; sourceTree = "<absolute>"; }; 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6B10B5B9CE00F8C034 /* enquire.c */; name = "enquire.c: 1232"; rLen = 48; rLoc = 38198; rType = 0; vrLen = 1282; vrLoc = 37320; }; 94D73E6B10B5B9CE00F8C034 /* enquire.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = enquire.c; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/enquire.c"; sourceTree = "<absolute>"; }; 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89C5A10B4BF2800556475 /* NSRunLoop.h */; name = "NSRunLoop.h: 30"; rLen = 8; rLoc = 714; rType = 0; vrLen = 1899; vrLoc = 0; }; 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABE0910AA21270086D908 /* NSView.h */; name = "NSView.h: 219"; rLen = 8; rLoc = 7448; rType = 0; vrLen = 2783; vrLoc = 6088; }; 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73FA110B5E5A200F8C034 /* CIColor.h */; name = "CIColor.h: 50"; rLen = 16; rLoc = 1220; rType = 0; vrLen = 1382; vrLoc = 0; }; 94D73FA110B5E5A200F8C034 /* CIColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIColor.h; sourceTree = "<absolute>"; }; 94D73FA410B5E5A200F8C034 /* CGColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGColor.h; sourceTree = "<absolute>"; }; 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73FA410B5E5A200F8C034 /* CGColor.h */; name = "CGColor.h: 44"; rLen = 68; rLoc = 1614; rType = 0; vrLen = 2485; vrLoc = 0; }; 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206DA10AF5536002F4160 /* CGContext.h */; name = "CGContext.h: 402"; rLen = 62; rLoc = 14416; rType = 0; vrLen = 511; vrLoc = 14175; }; 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2070610AF5A9E002F4160 /* NSImage.h */; name = "NSImage.h: 187"; rLen = 103; rLoc = 8443; rType = 0; vrLen = 6322; vrLoc = 6281; }; 94D7402810B5FA6100F8C034 /* CGDataProvider.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGDataProvider.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGDataProvider.h; sourceTree = "<absolute>"; }; 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206D210AF5536002F4160 /* CGImage.h */; name = "CGImage.h: 56"; rLen = 17; rLoc = 1989; rType = 0; vrLen = 2464; vrLoc = 1345; }; 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7402810B5FA6100F8C034 /* CGDataProvider.h */; name = "CGDataProvider.h: 114"; rLen = 79; rLoc = 4291; rType = 0; vrLen = 2286; vrLoc = 4217; }; 94D7403C10B5FDDB00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659020DDD03FE00358328 /* Klatt.c */; name = "Klatt.c: 188"; rLen = 20; rLoc = 4929; rType = 0; vrLen = 1387; vrLoc = 4016; }; 94D740B210B6242000F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D740B310B6242000F8C034 /* mman.h */; name = "mman.h: 161"; rLen = 64; rLoc = 6016; rType = 0; vrLen = 1386; vrLoc = 5938; }; 94D740B310B6242000F8C034 /* mman.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mman.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h; sourceTree = "<absolute>"; }; 94E297D10DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D20DECA72F009CF73A /* config.h */; name = "config.h: 154"; rLen = 60; rLoc = 3675; rType = 0; vrLen = 993; vrLoc = 2863; }; 94E297D20DECA72F009CF73A /* config.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = /Users/johnmci/Documents/SqueakGStreamer/platforms/unix/bld/config.h; sourceTree = "<absolute>"; }; 94E297D30DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D40DECA72F009CF73A /* version.c */; name = "version.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 65; vrLoc = 0; }; 94E297D40DECA72F009CF73A /* version.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = version.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/version.c; sourceTree = "<absolute>"; }; 94E297D50DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D60DECA72F009CF73A /* version.h */; name = "version.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 89; vrLoc = 0; }; 94E297D60DECA72F009CF73A /* version.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/version.h; sourceTree = "<absolute>"; }; 94E297D70DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5B970DE3623B007388E0 /* sqUnixMain.c */; name = "sqUnixMain.c: 417"; rLen = 15; rLoc = 10250; rType = 0; vrLen = 1200; vrLoc = 9269; }; 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E2DAD50ED2351B00012E92 /* sqMacUnixInterfaceSound.c */; name = "sqMacUnixInterfaceSound.c: 46"; rLen = 29; rLoc = 774; rType = 0; vrLen = 808; vrLoc = 382; }; 94E2DAD50ED2351B00012E92 /* sqMacUnixInterfaceSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUnixInterfaceSound.c; path = "/Users/johnmci/Documents/SqueakSpellingPlugin/platforms/Mac OS/plugins/SoundPlugin/sqMacUnixInterfaceSound.c"; sourceTree = "<absolute>"; }; 94E2DADE0ED2351B00012E92 /* sqUnixSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixSound.c; path = /Users/johnmci/Documents/SqueakServicesPlugin/platforms/unix/plugins/SoundPlugin/sqUnixSound.c; sourceTree = "<absolute>"; }; 94E2DB270ED2355F00012E92 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E2DADE0ED2351B00012E92 /* sqUnixSound.c */; name = "sqUnixSound.c: 114"; rLen = 0; rLoc = 4098; rType = 0; vrLen = 922; vrLoc = 3342; }; 94E4930310BD32D00011AC75 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9414420010BC817D0088F8AC /* NSPanel.h */; name = "NSPanel.h: 43"; rLen = 165; rLoc = 3279; rType = 0; vrLen = 3883; vrLoc = 0; }; 94E4936F10BD39E20011AC75 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/Squeak3.8.0.0CLosureWithEncryption/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94E5838A10BF3E080073FD63 /* NSTextInputClient.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextInputClient.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextInputClient.h; sourceTree = "<absolute>"; }; 94E5838E10BF3E080073FD63 /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 94E583DB10BF43970073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5838A10BF3E080073FD63 /* NSTextInputClient.h */; name = "NSTextInputClient.h: 20"; rLen = 75; rLoc = 497; rType = 0; vrLen = 2725; vrLoc = 0; }; 94E5846510BF67600073FD63 /* NSResponder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSResponder.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSResponder.h; sourceTree = "<absolute>"; }; 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5846510BF67600073FD63 /* NSResponder.h */; name = "NSResponder.h: 99"; rLen = 46; rLoc = 3759; rType = 0; vrLen = 2139; vrLoc = 2704; }; 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178310B73A3800F69A71 /* SqViewInputSensor.m */; name = "SqViewInputSensor.m: 34"; rLen = 22; rLoc = 478; rType = 0; vrLen = 1359; vrLoc = 0; }; 94E5850010BF79AB0073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87710B66A74002F81F2 /* SqViewEventSensor.m */; name = "SqViewEventSensor.m: 29"; rLen = 7; rLoc = 449; rType = 0; vrLen = 1509; vrLoc = 0; }; 94E658DE0DDD03FE00358328 /* plugins.int */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {3239, 363}}"; sepNavSelRange = "{0, 526}"; sepNavVisRange = "{0, 526}"; }; }; 94E658E00DDD03FE00358328 /* interp.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {3694, 358800}}"; sepNavSelRange = "{803236, 0}"; sepNavVisRange = "{801178, 1807}"; sepNavWindowFrame = "{{38, 34}, {1438, 968}}"; }; }; 94E658E10DDD03FE00358328 /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {661, 637}}"; sepNavSelRange = "{422, 14}"; sepNavVisRange = "{258, 1264}"; sepNavWindowFrame = "{{38, 14}, {799, 988}}"; }; }; 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 10348}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 410}"; }; }; 94E658E60DDD03FE00358328 /* B2DPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 131001}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1388}"; }; }; 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1944, 73697}}"; sepNavSelRange = "{126261, 0}"; sepNavVisRange = "{125512, 1456}"; }; }; 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 2860}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E658F00DDD03FE00358328 /* DSAPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 8112}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E658F20DDD03FE00358328 /* FFTPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 4823}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 366}"; }; }; 94E658F40DDD03FE00358328 /* FilePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 11648}}"; sepNavSelRange = "{13767, 50}"; sepNavVisRange = "{12643, 1804}"; sepNavWindowFrame = "{{21, 20}, {694, 1008}}"; }; }; 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 7592}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 192}"; }; }; 94E658F80DDD03FE00358328 /* GeniePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1594, 5135}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1889}"; }; }; 94E658FA0DDD03FE00358328 /* HostWindowPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1860, 5122}}"; sepNavSelRange = "{3964, 41}"; sepNavVisRange = "{3221, 1609}"; }; }; 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 17043}}"; sepNavSelRange = "{9474, 0}"; sepNavVisRange = "{9324, 406}"; }; }; 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1195, 9087}}"; sepNavSelRange = "{20722, 17}"; sepNavVisRange = "{19321, 2103}"; }; }; 94E659020DDD03FE00358328 /* Klatt.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 19500}}"; sepNavSelRange = "{44049, 0}"; sepNavVisRange = "{43900, 200}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 94E659040DDD03FE00358328 /* LargeIntegers.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1342, 30290}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 869}"; }; }; 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 8814}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E659080DDD03FE00358328 /* MIDIPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1867, 4784}}"; sepNavSelRange = "{3309, 0}"; sepNavVisRange = "{3006, 515}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 10634}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 844}"; }; }; 94E6590C0DDD03FE00358328 /* RePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {3113, 6032}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 871}"; }; }; 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 4043}}"; sepNavSelRange = "{536, 18}"; sepNavVisRange = "{0, 1028}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94E659100DDD03FE00358328 /* SocketPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 23192}}"; sepNavSelRange = "{36324, 91}"; sepNavVisRange = "{34415, 2532}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94E659120DDD03FE00358328 /* SoundCodecPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 2886}}"; sepNavSelRange = "{2059, 0}"; sepNavVisRange = "{1965, 173}"; }; }; 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 9087}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E659160DDD03FE00358328 /* SoundPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 6175}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 895}"; sepNavWindowFrame = "{{38, 28}, {1346, 974}}"; }; }; 94E659180DDD03FE00358328 /* Squeak3D.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 39598}}"; sepNavSelRange = "{65323, 16}"; sepNavVisRange = "{64437, 1713}"; }; }; 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1412, 4316}}"; sepNavSelRange = "{4752, 0}"; sepNavVisRange = "{4329, 952}"; }; }; 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2067}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 867}"; sepNavWindowFrame = "{{38, 17}, {847, 985}}"; }; }; 94E6591F0DDD03FE00358328 /* ZipPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 17446}}"; sepNavSelRange = "{1700, 11}"; sepNavVisRange = "{710, 2153}"; sepNavWindowFrame = "{{15, 22}, {1064, 1001}}"; }; }; 94E659200DDD03FE00358328 /* sqNamedPrims.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {870, 1079}}"; sepNavSelRange = "{2091, 0}"; sepNavVisRange = "{558, 1778}"; sepNavWindowFrame = "{{15, 9}, {1078, 1014}}"; }; }; 94E659430DDD04FA00358328 /* AsynchFilePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 501}}"; sepNavSelRange = "{404, 19}"; sepNavVisRange = "{0, 659}"; }; }; 94E659450DDD04FA00358328 /* FilePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 767}}"; sepNavSelRange = "{1735, 10}"; sepNavVisRange = "{440, 1866}"; sepNavWindowFrame = "{{15, 25}, {997, 998}}"; }; }; 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 4706}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1082}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94E659490DDD053900358328 /* SurfacePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {784, 2990}}"; sepNavSelRange = "{2333, 0}"; sepNavVisRange = "{1279, 2223}"; }; }; 94E6594A0DDD053900358328 /* SurfacePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {784, 1716}}"; sepNavSelRange = "{27, 0}"; sepNavVisRange = "{0, 2637}"; }; }; 94E6594D0DDD053900358328 /* SecurityPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 481}}"; sepNavSelRange = "{290, 3}"; sepNavVisRange = "{117, 443}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94E6594F0DDD053900358328 /* SoundGenerationPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{299, 3}"; sepNavVisRange = "{0, 360}"; }; }; 94E659530DDD053900358328 /* jcapimin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3822}}"; sepNavSelRange = "{7008, 3}"; sepNavVisRange = "{5989, 1240}"; }; }; 94E659550DDD053900358328 /* jccoefct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5863}}"; sepNavSelRange = "{9819, 3}"; sepNavVisRange = "{8276, 1834}"; }; }; 94E659560DDD053900358328 /* jccolor.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5889}}"; sepNavSelRange = "{9842, 3}"; sepNavVisRange = "{9173, 1109}"; }; }; 94E659570DDD053900358328 /* jcdctmgr.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4966}}"; sepNavSelRange = "{6549, 3}"; sepNavVisRange = "{5884, 1542}"; }; }; 94E659580DDD053900358328 /* jchuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 11778}}"; sepNavSelRange = "{22307, 3}"; sepNavVisRange = "{21622, 1607}"; }; }; 94E6595B0DDD053900358328 /* jcmainct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3783}}"; sepNavSelRange = "{7591, 3}"; sepNavVisRange = "{6975, 964}"; }; }; 94E6595C0DDD053900358328 /* jcmarker.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8866}}"; sepNavSelRange = "{10933, 3}"; sepNavVisRange = "{10271, 1095}"; }; }; 94E6595D0DDD053900358328 /* jcmaster.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 7553}}"; sepNavSelRange = "{10789, 3}"; sepNavVisRange = "{10099, 1218}"; }; }; 94E6595E0DDD053900358328 /* jcomapi.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 1512}}"; sepNavSelRange = "{2136, 7}"; sepNavVisRange = "{1428, 1392}"; }; }; 94E659600DDD053900358328 /* jcparam.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8164}}"; sepNavSelRange = "{18163, 3}"; sepNavVisRange = "{17732, 1161}"; }; }; 94E659610DDD053900358328 /* jcphuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 10920}}"; sepNavSelRange = "{18752, 3}"; sepNavVisRange = "{17946, 1058}"; }; }; 94E659620DDD053900358328 /* jcprepct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4628}}"; sepNavSelRange = "{9095, 3}"; sepNavVisRange = "{8327, 1337}"; }; }; 94E659630DDD053900358328 /* jcsample.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6994}}"; sepNavSelRange = "{7407, 3}"; sepNavVisRange = "{6537, 1530}"; }; }; 94E659640DDD053900358328 /* jctrans.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5187}}"; sepNavSelRange = "{13272, 3}"; sepNavVisRange = "{12530, 1091}"; }; }; 94E659650DDD053900358328 /* jdapimin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5135}}"; sepNavSelRange = "{7807, 3}"; sepNavVisRange = "{7168, 1550}"; }; }; 94E659690DDD053900358328 /* jdcoefct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 9451}}"; sepNavSelRange = "{21428, 3}"; sepNavVisRange = "{20759, 1160}"; }; }; 94E6596A0DDD053900358328 /* jdcolor.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5057}}"; sepNavSelRange = "{8235, 3}"; sepNavVisRange = "{7573, 1344}"; }; }; 94E6596B0DDD053900358328 /* jdct.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2275}}"; sepNavSelRange = "{693, 3}"; sepNavVisRange = "{0, 1654}"; }; }; 94E6596D0DDD053900358328 /* jdhuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8229}}"; sepNavSelRange = "{15652, 3}"; sepNavVisRange = "{14578, 1143}"; }; }; 94E6596E0DDD053900358328 /* jdhuff.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2574}}"; sepNavSelRange = "{4464, 3}"; sepNavVisRange = "{2783, 1780}"; }; }; 94E6596F0DDD053900358328 /* jdinput.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4810}}"; sepNavSelRange = "{6703, 3}"; sepNavVisRange = "{5969, 1701}"; }; }; 94E659700DDD053900358328 /* jdmainct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6149}}"; sepNavSelRange = "{7953, 3}"; sepNavVisRange = "{7137, 1484}"; }; }; 94E659710DDD053900358328 /* jdmarker.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 17706}}"; sepNavSelRange = "{40391, 3}"; sepNavVisRange = "{38997, 1561}"; }; }; 94E659720DDD053900358328 /* jdmaster.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 7085}}"; sepNavSelRange = "{14890, 3}"; sepNavVisRange = "{14181, 1516}"; }; }; 94E659730DDD053900358328 /* jdmerge.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5187}}"; sepNavSelRange = "{10331, 3}"; sepNavVisRange = "{9363, 1315}"; }; }; 94E659740DDD053900358328 /* jdphuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8606}}"; sepNavSelRange = "{15744, 3}"; sepNavVisRange = "{14845, 1126}"; }; }; 94E659760DDD053900358328 /* jdsample.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6409}}"; sepNavSelRange = "{11463, 3}"; sepNavVisRange = "{10845, 1368}"; }; }; 94E659770DDD053900358328 /* jdtrans.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2002}}"; sepNavSelRange = "{995, 7}"; sepNavVisRange = "{0, 1708}"; }; }; 94E659790DDD053900358328 /* jerror.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4121}}"; sepNavSelRange = "{12583, 3}"; sepNavVisRange = "{11937, 1999}"; }; }; 94E6597C0DDD053900358328 /* jfdctint.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3809}}"; sepNavSelRange = "{5901, 3}"; sepNavVisRange = "{5152, 1247}"; }; }; 94E6597D0DDD053900358328 /* jidctflt.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3094}}"; sepNavSelRange = "{7928, 3}"; sepNavVisRange = "{6879, 1380}"; }; }; 94E6597E0DDD053900358328 /* jidctfst.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4706}}"; sepNavSelRange = "{9786, 3}"; sepNavVisRange = "{8848, 1431}"; }; }; 94E6597F0DDD053900358328 /* jidctint.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5044}}"; sepNavSelRange = "{11723, 3}"; sepNavVisRange = "{10788, 1464}"; }; }; 94E659800DDD053900358328 /* jidctred.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{11209, 3}"; sepNavVisRange = "{10458, 1488}"; }; }; 94E659810DDD053900358328 /* jinclude.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 1372}}"; sepNavSelRange = "{1563, 7}"; sepNavVisRange = "{935, 1412}"; }; }; 94E659820DDD053900358328 /* jmemdatadst.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1924}}"; sepNavSelRange = "{4506, 0}"; sepNavVisRange = "{4026, 877}"; }; }; 94E659830DDD053900358328 /* jmemdatasrc.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2600}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 661}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94E659840DDD053900358328 /* jmemmgr.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 14313}}"; sepNavSelRange = "{20872, 3}"; sepNavVisRange = "{20200, 1407}"; }; }; 94E659860DDD053900358328 /* jmemsys.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2730}}"; sepNavSelRange = "{1380, 7}"; sepNavVisRange = "{578, 1969}"; }; }; 94E659870DDD053900358328 /* jmorecfg.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{4500, 3}"; sepNavVisRange = "{3819, 1298}"; }; }; 94E659880DDD053900358328 /* jpegint.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5135}}"; sepNavSelRange = "{8138, 3}"; sepNavVisRange = "{6999, 1671}"; }; }; 94E659890DDD053900358328 /* jpeglib.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 14287}}"; sepNavSelRange = "{44121, 3}"; sepNavVisRange = "{43159, 1631}"; }; }; 94E6598A0DDD053900358328 /* JPEGReadWriter2Plugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{400, 3}"; sepNavVisRange = "{0, 606}"; }; }; 94E6598B0DDD053900358328 /* jquant1.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 10946}}"; sepNavSelRange = "{23424, 3}"; sepNavVisRange = "{22008, 1505}"; }; }; 94E6598C0DDD053900358328 /* jquant2.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 17212}}"; sepNavSelRange = "{35564, 3}"; sepNavVisRange = "{34161, 1581}"; }; }; 94E6598D0DDD053900358328 /* jutils.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2379}}"; sepNavSelRange = "{709, 3}"; sepNavVisRange = "{0, 1126}"; }; }; 94E659910DDD053900358328 /* UUIDPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 141}}"; sepNavSelRange = "{224, 0}"; sepNavVisRange = "{0, 247}"; }; }; 94E659930DDD053900358328 /* SoundPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 891}}"; sepNavSelRange = "{752, 96}"; sepNavVisRange = "{0, 1267}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 94E659970DDD053900358328 /* b3d.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1547}}"; sepNavSelRange = "{1163, 18}"; sepNavVisRange = "{725, 933}"; }; }; 94E659990DDD053900358328 /* b3dAlloc.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2044}}"; sepNavSelRange = "{2615, 7}"; sepNavVisRange = "{1909, 1488}"; }; }; 94E6599A0DDD053900358328 /* b3dDraw.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 6643}}"; sepNavSelRange = "{13439, 0}"; sepNavVisRange = "{12902, 1039}"; }; }; 94E6599B0DDD053900358328 /* b3dInit.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 9113}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1197}"; }; }; 94E6599C0DDD053900358328 /* b3dMain.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 19292}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 866}"; }; }; 94E6599D0DDD053900358328 /* b3dRemap.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3718}}"; sepNavSelRange = "{7538, 0}"; sepNavVisRange = "{6829, 1035}"; }; }; 94E6599E0DDD053900358328 /* b3dTypes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 4420}}"; sepNavSelRange = "{4491, 13}"; sepNavVisRange = "{3977, 898}"; }; }; 94E659A00DDD053900358328 /* SocketPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1601, 1118}}"; sepNavSelRange = "{3647, 30}"; sepNavVisRange = "{757, 4070}"; }; }; 94E659A30DDD053900358328 /* SoundCodecPrims.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{3, 10}"; sepNavVisRange = "{0, 401}"; }; }; 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 50479}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 631}"; }; }; 94E65A290DDD053900358328 /* chartables.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2457}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1175}"; }; }; 94E65A2B0DDD053900358328 /* get.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2860}}"; sepNavSelRange = "{4454, 0}"; sepNavVisRange = "{4071, 824}"; }; }; 94E65A2C0DDD053900358328 /* internal.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 5629}}"; sepNavSelRange = "{1665, 0}"; sepNavVisRange = "{1415, 1340}"; }; }; 94E65A2E0DDD053900358328 /* pcre.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 66248}}"; sepNavSelRange = "{91389, 0}"; sepNavVisRange = "{91065, 550}"; sepNavWindowFrame = "{{683, 16}, {997, 998}}"; }; }; 94E65A2F0DDD053900358328 /* pcre.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 1495}}"; sepNavSelRange = "{2990, 3}"; sepNavVisRange = "{1856, 1482}"; }; }; 94E65A300DDD053900358328 /* rePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1010, 637}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1259}"; }; }; 94E65A340DDD053900358328 /* study.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{3001, 3}"; sepNavVisRange = "{2296, 1397}"; }; }; 94E745ED11E5346100E90B3A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */; name = "sqSqueakOSXInfoPlistInterface.h: 39"; rLen = 0; rLoc = 1840; rType = 0; vrLen = 2792; vrLoc = 854; }; 94E745EF11E5346100E90B3A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */; name = "sqSqueakMainApp.h: 33"; rLen = 449; rLoc = 1322; rType = 0; vrLen = 1868; vrLoc = 0; }; 94E746D011E539AF00E90B3A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658F40DDD03FE00358328 /* FilePlugin.c */; name = "FilePlugin.c: 362"; rLen = 4; rLoc = 12226; rType = 0; vrLen = 1651; vrLoc = 11431; }; 94E7F9A912375A9600A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943B9C9E1235C5120056205E /* sqMacHostWindow.m */; name = "sqMacHostWindow.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2559; vrLoc = 0; }; 94E7F9AA12375A9600A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */; name = "SqueakPureObjc_Prefix.pch: 6"; rLen = 0; rLoc = 114; rType = 0; vrLen = 149; vrLoc = 0; }; 94E7F9AB12375A9600A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9478E05E0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.h */; name = "sqSqueakSoundCoreAudio.h: 51"; rLen = 24; rLoc = 2099; rType = 0; vrLen = 2592; vrLoc = 1871; }; 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E8EEEB11C94D5D0049D853 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2113"; rLen = 12; rLoc = 55330; rType = 0; vrLen = 1130; vrLoc = 54733; }; 94E8EEEB11C94D5D0049D853 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/Squeak3.8.0/History/4.2.4b1/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94E99F3412378CD30048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77300EA7E642004B266D /* interp.c */; name = "interp.c: 2284"; rLen = 14; rLoc = 81797; rType = 0; vrLen = 2291; vrLoc = 79683; }; 94E99F3612378CD30048557C /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Users/johnmci/Documents/Squeak3.8.0.0WithEncryption/src/vm/interp.c; sourceTree = "<absolute>"; }; 94E99F4012378D660048557C /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/src32/vm/interp.c; sourceTree = "<absolute>"; }; 94E99F8012378DAB0048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E99F4012378D660048557C /* interp.c */; name = "interp.c: 16"; rLen = 0; rLoc = 337; rType = 0; vrLen = 2614; vrLoc = 100117; }; 94E9A007123790840048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */; name = "sqSqueakMainApplication+screen.h: 28"; rLen = 0; rLoc = 1280; rType = 0; vrLen = 1983; vrLoc = 0; }; 94E9A00B123790840048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E99F3612378CD30048557C /* interp.c */; name = "interp.c: 4166"; rLen = 13; rLoc = 139308; rType = 0; vrLen = 1967; vrLoc = 72464; }; 94E9A1071238161A0048557C /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = "/Users/johnmci/Documents/Squeak/Squeak3.8g-6665#2/platforms/unix/src/vm/interp.c"; sourceTree = "<absolute>"; }; 94E9A19812381F180048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A1071238161A0048557C /* interp.c */; name = "interp.c: 2267"; rLen = 0; rLoc = 81024; rType = 0; vrLen = 2535; vrLoc = 79835; }; 94E9A1AF12382FFD0048557C /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 94E9A1CB123833B00048557C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E9A1AF12382FFD0048557C /* sqUnixMain.c */; name = "sqUnixMain.c: 225"; rLen = 19; rLoc = 6421; rType = 0; vrLen = 1608; vrLoc = 5582; }; 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ED7EFB0E6C2ABE00F4DD03 /* Document.m */; name = "Document.m: 75"; rLen = 20; rLoc = 2275; rType = 0; vrLen = 1332; vrLoc = 1613; }; 94ED7EFB0E6C2ABE00F4DD03 /* Document.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Document.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/Document.m"; sourceTree = "<absolute>"; }; 94EF6D6D11E55E31003BA64D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94EF6D6E11E55E31003BA64D /* sqUnixSocket.c */; name = "sqUnixSocket.c: 73"; rLen = 1; rLoc = 2408; rType = 0; vrLen = 976; vrLoc = 1899; }; 94EF6D6E11E55E31003BA64D /* sqUnixSocket.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixSocket.c; path = "/Volumes/pm/Mail Downloads/sqUnixSocket.c"; sourceTree = "<absolute>"; }; 94F155570E83EA1F001657CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C640E81500200C98131 /* SqueakObjcBridge.m */; name = "SqueakObjcBridge.m: 291"; rLen = 0; rLoc = 8126; rType = 0; vrLen = 2591; vrLoc = 6567; }; 94F155580E83EA1F001657CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F155590E83EA1F001657CE /* FSNSProxy.m */; name = "FSNSProxy.m: 24"; rLen = 26; rLoc = 737; rType = 0; vrLen = 1622; vrLoc = 0; }; 94F155590E83EA1F001657CE /* FSNSProxy.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FSNSProxy.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/FSNSProxy.m"; sourceTree = "<absolute>"; }; 94F1F6B111EB8E14004B3AE3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF5B0DDCB1C7009912BF /* sqGnu.h */; name = "sqGnu.h: 187"; rLen = 7; rLoc = 11528; rType = 0; vrLen = 1875; vrLoc = 0; }; 94F3A9690E6BFA7C00E0B12A /* Squeak.png */ = { uiCtxt = { sepNavWindowFrame = "{{61, 124}, {1288, 857}}"; }; }; 94F5C1870DF26EF200099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1880DF26EF200099B11 /* interp.c */; name = "interp.c: 5170"; rLen = 7; rLoc = 155552; rType = 0; vrLen = 1874; vrLoc = 154817; }; 94F5C1880DF26EF200099B11 /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Users/johnmci/Documents/SqueakSquatSpoon/src/vm/interp.c; sourceTree = "<absolute>"; }; 94F5C1910DF26EF200099B11 /* gnu-interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "gnu-interp.c"; path = "/Volumes/pm/Mail Downloads/gnu-interp.c"; sourceTree = "<absolute>"; }; 94F5C1930DF26EF200099B11 /* gnu-interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "gnu-interp.c"; path = "/Users/johnmci/Work In Progress/squeak Bugs/unixcompiletoomanyinstructions]/memoryAllocationNotes/gnu-interp.c"; sourceTree = "<absolute>"; }; 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1930DF26EF200099B11 /* gnu-interp.c */; name = "gnu-interp.c: 5409"; rLen = 7; rLoc = 161001; rType = 0; vrLen = 1782; vrLoc = 160256; }; 94F5C2600DF42C7600099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1910DF26EF200099B11 /* gnu-interp.c */; name = "gnu-interp.c: 5916"; rLen = 7; rLoc = 193171; rType = 0; vrLen = 1899; vrLoc = 192393; }; 94F5F28710BC517200847EEE /* sqSqueakOSXNSView.m:455 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-setMarkedText:selectedRange:replacementRange:"; hitCount = 0; ignoreCount = 0; lineNumber = 455; location = Squeak; modificationTime = 306811863.543034; originalNumberOfMultipleMatches = 1; state = 2; }; 94F5F28B10BC517500847EEE /* sqSqueakOSXNSView.m:476 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-markedRange"; hitCount = 0; ignoreCount = 0; lineNumber = 476; location = Squeak; modificationTime = 306811863.5430461; originalNumberOfMultipleMatches = 1; state = 2; }; 94F5F28D10BC517700847EEE /* sqSqueakOSXNSView.m:480 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-selectedRange"; hitCount = 0; ignoreCount = 0; lineNumber = 480; location = Squeak; modificationTime = 306811863.543057; originalNumberOfMultipleMatches = 1; state = 2; }; 94F5F29110BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178F10B73A3800F69A71 /* SqueakInterpreterEventSensor.h */; name = "SqueakInterpreterEventSensor.h: 10"; rLen = 8; rLoc = 322; rType = 0; vrLen = 461; vrLoc = 0; }; 94F5F29210BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F29310BC518B00847EEE /* macXCanvas.m */; name = "macXCanvas.m: 174"; rLen = 8; rLoc = 3716; rType = 0; vrLen = 1886; vrLoc = 3759; }; 94F5F29310BC518B00847EEE /* macXCanvas.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = macXCanvas.m; path = "/Users/johnmci/Work In Progress/cincom/VWSourceCode/721/src/plat/macXCanvas.m"; sourceTree = "<absolute>"; }; 94F5F29410BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178010B73A3800F69A71 /* SqueakInterpreterEventSensor.m */; name = "SqueakInterpreterEventSensor.m: 40"; rLen = 8; rLoc = 1108; rType = 0; vrLen = 1744; vrLoc = 0; }; 94F5F29510BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F29610BC518B00847EEE /* ShellView.m */; name = "ShellView.m: 121"; rLen = 8; rLoc = 4069; rType = 0; vrLen = 2026; vrLoc = 3111; }; 94F5F29610BC518B00847EEE /* ShellView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ShellView.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/ShellView.m"; sourceTree = "<absolute>"; }; 94F5F2A810BC539700847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F2A910BC539700847EEE /* NSSet.h */; name = "NSSet.h: 58"; rLen = 69; rLoc = 2031; rType = 0; vrLen = 1982; vrLoc = 721; }; 94F5F2A910BC539700847EEE /* NSSet.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSet.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSSet.h; sourceTree = "<absolute>"; }; 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {869, 785}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2024}"; sepNavWindowFrame = "{{896, 50}, {1017, 978}}"; }; }; 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1508}}"; sepNavSelRange = "{2213, 17}"; sepNavVisRange = "{2004, 1724}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94F89AED10B497F400556475 /* NSResponder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSResponder.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSResponder.h; sourceTree = "<absolute>"; }; 94F89AFE10B4997900556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89AFF10B4997900556475 /* IOLLEvent.h */; name = "IOLLEvent.h: 384"; rLen = 79; rLoc = 14824; rType = 0; vrLen = 2433; vrLoc = 0; }; 94F89AFF10B4997900556475 /* IOLLEvent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IOLLEvent.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/IOKit.framework/Versions/A/Headers/hidsystem/IOLLEvent.h; sourceTree = "<absolute>"; }; 94F89BDE10B4B77400556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89BDF10B4B77400556475 /* CGBase.h */; name = "CGBase.h: 105"; rLen = 30; rLoc = 2998; rType = 0; vrLen = 1747; vrLoc = 1331; }; 94F89BDF10B4B77400556475 /* CGBase.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGBase.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGBase.h; sourceTree = "<absolute>"; }; 94F89BE010B4B77400556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAEDF10ACAE2500F87527 /* NSValue.h */; name = "NSValue.h: 52"; rLen = 27; rLoc = 1223; rType = 0; vrLen = 1478; vrLoc = 0; }; 94F89C5A10B4BF2800556475 /* NSRunLoop.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSRunLoop.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRunLoop.h; sourceTree = "<absolute>"; }; 94F89C9110B4C0B800556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89C9210B4C0B800556475 /* NSTimer.h */; name = "NSTimer.h: 14"; rLen = 30; rLoc = 564; rType = 0; vrLen = 1132; vrLoc = 0; }; 94F89C9210B4C0B800556475 /* NSTimer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTimer.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSTimer.h; sourceTree = "<absolute>"; }; 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0EBB20DE608350071C8B9 /* squeakAudioVideoPipeLineSignalInterface.c */; name = "squeakAudioVideoPipeLineSignalInterface.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2018; vrLoc = 0; }; 94FB0AA7123B63D200026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0AA8123B63D200026016 /* teximage.c */; name = "teximage.c: 1633"; rLen = 15; rLoc = 54425; rType = 0; vrLen = 1976; vrLoc = 53379; }; 94FB0AA8123B63D200026016 /* teximage.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = teximage.c; path = "/Users/johnmci/Work In Progress/stx/support/MESA/Mesa-3.0/src/teximage.c"; sourceTree = "<absolute>"; }; 94FB0B55123B6A8300026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0B56123B6A8300026016 /* sqOpenGLRenderer.c */; name = "sqOpenGLRenderer.c: 897"; rLen = 0; rLoc = 28946; rType = 0; vrLen = 1861; vrLoc = 28206; }; 94FB0B56123B6A8300026016 /* sqOpenGLRenderer.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqOpenGLRenderer.c; path = /Users/johnmci/Documents/SqueakQuicktimePlugin/platforms/Cross/plugins/B3DAcceleratorPlugin/sqOpenGLRenderer.c; sourceTree = "<absolute>"; }; 94FB0B57123B6A8300026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0B58123B6A8300026016 /* NeonEngine.m */; name = "NeonEngine.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1183; vrLoc = 1832; }; 94FB0B58123B6A8300026016 /* NeonEngine.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NeonEngine.m; path = "/Volumes/pm/Mail Downloads/iProPutt/NeonEngine/NeonEngine.m"; sourceTree = "<absolute>"; }; 94FB0B59123B6A8300026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0B5A123B6A8300026016 /* NeonEngine.m */; name = "NeonEngine.m: 17"; rLen = 0; rLoc = 287; rType = 0; vrLen = 1057; vrLoc = 0; }; 94FB0B5A123B6A8300026016 /* NeonEngine.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NeonEngine.m; path = /Volumes/px2/business/archive/iProPutt/NeonEngine/NeonEngine.m; sourceTree = "<absolute>"; }; 94FB0B5B123B6A8300026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0B5C123B6A8300026016 /* EAGLView.m */; name = "EAGLView.m: 19"; rLen = 0; rLoc = 920; rType = 0; vrLen = 2853; vrLoc = 0; }; 94FB0B5C123B6A8300026016 /* EAGLView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = EAGLView.m; path = "/Volumes/330GB Photos/temp/GLSprite/Classes/EAGLView.m"; sourceTree = "<absolute>"; }; 94FB0B5D123B6A8300026016 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94FB0B5E123B6A8300026016 /* EAGLView.m */; name = "EAGLView.m: 71"; rLen = 0; rLoc = 1636; rType = 0; vrLen = 1323; vrLoc = 1387; }; 94FB0B5E123B6A8300026016 /* EAGLView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = EAGLView.m; path = /Volumes/px2/business/SqueakiPhone/archivesOLDSTUFF/SqueakIPhone/Classes/EAGLView.m; sourceTree = "<absolute>"; }; 94FF88971240458F00B1021A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940BE5E71239F50100674A11 /* SqueakUIViewOpenGL.h */; name = "SqueakUIViewOpenGL.h: 43"; rLen = 0; rLoc = 1885; rType = 0; vrLen = 2099; vrLoc = 706; }; 94FF88981240458F00B1021A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; name = "sqSqueakOSXNSView.m: 74"; rLen = 9; rLoc = 2921; rType = 0; vrLen = 1647; vrLoc = 1928; }; 94FF88991240458F00B1021A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940BE5E81239F50100674A11 /* SqueakUIViewOpenGL.m */; name = "SqueakUIViewOpenGL.m: 163"; rLen = 0; rLoc = 5746; rType = 0; vrLen = 2039; vrLoc = 5080; }; 94FFF7A40EBE2B9C00C69C79 /* SqueakV39.sources */ = { uiCtxt = { sepNavFolds = "{\n c = (\n {\n l = \"123>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\t\\n\\tself should: [ self compile: '<foo bar>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo 1>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo bar zork>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo bar 1>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\t\\nself should: [ self compile: '<foo: bar:>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo: #bar: zork:>' selector: #zork ] raise: SyntaxErrorNotification.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileNumber\\n\\tself assertPragma: 'foo: 123' givesKeyword: #foo: arguments: #( 123 ).\\n\\tself assertPragma: 'foo: -123' givesKeyword: #foo: arguments: #( -123 ).\\n\\tself assertPragma: 'foo: 12.3' givesKeyword: #foo: arguments: #( 12.3 ).\\n\\tself assertPragma: 'foo: -12.3' givesKeyword: #foo: arguments: #( -12.3 ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileString\\n\\tself assertPragma: 'foo: ''''' givesKeyword: #foo: arguments: #( '' ).\\n\\tself assertPragma: 'foo: ''bar''' givesKeyword: #foo: arguments: #( 'bar' ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileSymbol\\n\\tself assertPragma: 'foo: #bar' givesKeyword: #foo: arguments: #( bar ).\\n\\tself assertPragma: 'foo: #bar:' givesKeyword: #foo: arguments: #( bar: ).\\n\\tself assertPragma: 'foo: #bar:zork:' givesKeyword: #foo: arguments: #( bar:zork: ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 7/3/2006 15:00'!\\ntestCompileTemps\\n\\t\\\"Pragmas should be placeable before and after temps.\\\"\\n\\t\\n\\tself \\n\\t\\tshouldnt: [\\n\\t\\t\\tself assert: (self compile: '| temps | <foo>' selector: #zork) \\n\\t\\t\\t\\tpragmas notEmpty ]\\n\\t\\traise: SyntaxErrorNotification.\\n\\tself \\n\\t\\tshouldnt: [\\n\\t\\t\\tself assert: (self compile: '<foo> | temps |' selector: #zork) \\n\\t\\t\\t\\tpragmas notEmpty ]\\n\\t\\traise: SyntaxErrorNotification.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 2/6/2006 21:04'!\\ntestCompileValue\\n\\tself assertPragma: 'foo: true' givesKeyword: #foo: arguments: #( true ).\\n\\tself assertPragma: 'foo: false' givesKeyword: #foo: arguments: #( false ).\\n\\tself assertPragma: 'foo: nil' givesKeyword: #foo: arguments: #( nil ).\\n\\t\\n\\tself assertPragma: 'foo: String' givesKeyword: #foo: arguments: { String }.\\n\\tself assertPragma: 'foo: Pragma' givesKeyword: #foo: arguments: { Pragma }.! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'lr 1/20/2006 07:54'!\\ntestMethod\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma method == (self class >> #bar).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'md 2/18/2006 19:59'!\\ntestMethodClass\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma methodClass == self class.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'lr 1/20/2006 07:54'!\\ntestSelector\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma selector == #bar.! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-compiled' stamp: 'lr 2/6/2006 21:03'!\\ntestNoPragma\\n\\t| method |\\n\\tmethod := self compile: '' selector: #foo.\\n\\tself assert: method pragmas = #().! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:31'!\\ntestPrimitiveIndexed1\\n\\t\\\"This test useses the #instVarAt: primitive.\\\"\\n\\t\\n\\tself compile: '<primitive: 74> ^ #inst' selector: #inst.\\n\\tself assert: self inst = #inst.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:31'!\\ntestPrimitiveIndexed2\\n\\t\\\"This test useses the #asOop primitive.\\\"\\n\\n\\tself compile: '<primitive: 75> ^ #oop' selector: #oop.\\n\\tself assert: self oop = self asOop.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:42'!\\ntestPrimitiveNamed1\\n\\t\\\"This test useses the #primitiveDirectoryLookup primitive.\\\"\\n\\n\\tself compile: '<primitive: ''primitiveDirectoryLookup'' module: ''FilePlugin''> ^ #lookup' selector: #lookup.\\n\\tself assert: self lookup = #lookup.\\n\\t\\n! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:41'!\\ntestPrimitiveNamed2\\n\\t\\\"This test useses the #primPathNameDelimiter primitive.\\\"\\n\\n\\tself compile: '<primitive: ''primitiveDirectoryDelimitor'' module: ''FilePlugin''> ^ #delim' selector: #delim.\\n\\tself assert: self delim = FileDirectory primPathNameDelimiter.\\n\\t\\n! !\\nObject subclass: #MethodProperties\\n\\tinstanceVariableNames: 'properties pragmas selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Methods'!\\n!MethodProperties commentStamp: 'lr 2/6/2006 19:31' prior: 0!\\nI am class holding state for compiled methods. All my instance variables should be actually part of the CompiledMethod itself, but the current implementation of the VM doesn't allow this.\\n\\nI am a compact class and optimized for size and speed, since every CompiledMethod points onto an instance of myself. I am mostly polymorphic to the protocol of an identity-dictionary, so that key-value pairs can be easily stored and retreived without the need to add new variables. However keep in mind that instantiating a dictionary consumes much more memory than adding an instance-variable, so it might be clever to add a new variable if the property is going to be used by every compiled method.!\\n\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'lr 2/6/2006 19:11'!\\npragmas\\n\\t^ pragmas! !\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!\\nselector\\n\\t^selector! !\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!\\nselector: aSymbol\\n\\tselector := aSymbol! !\\n\\n\\n!MethodProperties methodsFor: 'initialization' stamp: 'lr 2/6/2006 19:12'!\\ninitialize\\n\\tsuper initialize.\\n\\tpragmas := #().! !\\n\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:04'!\\nat: aKey\\n\\t\\\"Answer the property value associated with aKey.\\\"\\n\\t\\n\\t^ self at: aKey ifAbsent: [ self error: 'Property not found' ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:47'!\\nat: aKey ifAbsentPut: aBlock\\n\\t\\\"Answer the property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value.\\\"\\n\\t\\n\\t^ self at: aKey ifAbsent: [ self at: aKey put: aBlock value ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!\\nat: aKey ifAbsent: aBlock\\n\\t\\\"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock.\\\"\\n\\t\\n\\tproperties isNil ifTrue: [ ^ aBlock value ].\\n\\t^ properties at: aKey ifAbsent: aBlock.! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:06'!\\nat: aKey put: anObject\\n\\t\\\"Set the property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject.\\\"\\n\\n\\tproperties ifNil: [ properties := IdentityDictionary new ].\\n\\t^ properties at: aKey put: anObject.! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:11'!\\nincludesKey: aKey\\n\\t\\\"Test if the property aKey is present.\\\"\\n\\t\\n\\t^ properties notNil and: [ properties includesKey: aKey ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:48'!\\nremoveKey: aKey\\n\\t\\\"Remove the property with aKey. Answer the property or raise an error if aKey isn't found.\\\"\\n\\t\\n\\t^ self removeKey: aKey ifAbsent: [ self error: 'Property not found' ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!\\nremoveKey: aKey ifAbsent: aBlock\\n\\t\\\"Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock.\\\"\\n\\t\\n\\t| answer |\\n\\tproperties isNil ifTrue: [ ^ aBlock value ].\\n\\tanswer := properties removeKey: aKey ifAbsent: aBlock.\\n\\tproperties isEmpty ifTrue: [ properties := nil ].\\n\\t^ answer.! !\\n\\n\\n!MethodProperties methodsFor: 'private' stamp: 'lr 2/6/2006 20:36'!\\naddPragma: aPragma\\n\\tpragmas := pragmas copyWith: aPragma.! !\\n\\n\\n!MethodProperties methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!\\nisMethodProperties\\n\\t^true! !\\n\\n\\n!MethodProperties methodsFor: 'copying' stamp: 'md 3/1/2006 15:30'!\\npostCopy\\n\\tproperties := properties copy.\\n\\tpragmas := pragmas copy.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMethodProperties class\\n\\tinstanceVariableNames: ''!\\n\\n!MethodProperties class methodsFor: 'class initialization' stamp: 'lr 2/6/2006 22:06'!\\ninitialize\\n\\tself becomeCompact.! !\\nTestCase subclass: #MethodPropertiesTest\\n\\tinstanceVariableNames: 'method'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Methods'!\\n\\n!MethodPropertiesTest methodsFor: 'private' stamp: 'lr 2/6/2006 20:43'!\\npropertyDictionaryFor: aMethod\\n\\t^ aMethod properties instVarNamed: 'properties'.! !\\n\\n\\n!MethodPropertiesTest methodsFor: 'running' stamp: 'lr 1/20/2006 19:16'!\\nsetUp\\n\\tmethod := Object >> #halt.! !\\n\\n!MethodPropertiesTest methodsFor: 'running' stamp: 'lr 1/20/2006 19:20'!\\ntearDown\\n\\tObject recompile: #halt from: Object.! !\\n\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'kwl 7/26/2006 11:41'!\\ntestAllMethodsHaveMethodClass\\n\\tSmalltalk garbageCollect.\\n\\tself assert: (CompiledMethod allInstances\\n\\t\\t\\treject: [:cm | cm literals last isVariableBinding\\n\\t\\t\\t\\t\\tand: [cm literals last value isBehavior\\n\\t\\t\\t\\t\\t\\t\\tor: [cm literals last value isTrait]]]) isEmpty\\n\\t\\t\\tdescription: 'CompiledMethods must have methodClass literal'! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'kwl 7/26/2006 11:40'!\\ntestAllMethodsHaveNewPropertyFormat\\n\\tSmalltalk garbageCollect.\\n\\tself assert: (CompiledMethod allInstances\\n\\t\\t\\treject: [:cm | cm hasNewPropertyFormat]) isEmpty\\n\\t\\tdescription: 'CompiledMethods must have new property format'! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:21'!\\ntestAt\\n\\tself should: [ method properties at: #zork ] raise: Error.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself assert: (method properties at: #zork) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtIfAbsent\\n\\tself assert: (method properties at: #zork ifAbsent: [ 'hello' ]) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 'hi'.\\n\\tself assert: (method properties at: #zork ifAbsent: [ 'hello' ]) = 'hi'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtIfAbsentPut\\n\\tself assert: (method properties at: #zork ifAbsentPut: [ 'hello' ]) = 'hello'.\\n\\tself assert: (method properties at: #zork ifAbsentPut: [ 'hi' ]) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtPut\\n\\tself assert: (method properties at: #zork put: 'hello') = 'hello'.\\n\\tself assert: (method properties at: #zork) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:19'!\\ntestIncludesKey\\n\\tself deny: (method properties includesKey: #zork).\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 123.\\n\\tself assert: (method properties includesKey: #zork).! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestRemoveKey\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself should: [ method properties removeKey: #halt ] raise: Error.\\n\\tself assert: (method properties removeKey: #zork) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tself should: [ method properties removeKey: #zork ] raise: Error.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestRemoveKeyifAbsent\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself assert: (method properties removeKey: #halt ifAbsent: [ 'hi' ]) = 'hi'.\\n\\tself assert: (method properties removeKey: #zork ifAbsent: [ 'hi' ]) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tself should: (method properties removeKey: #zork ifAbsent: [ 'hi' ]) = 'hi'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.! !\\nObject subclass: #MethodReference\\n\\tinstanceVariableNames: 'classSymbol classIsMeta methodSymbol stringVersion'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!MethodReference commentStamp: 'tlk 5/9/2006 18:43' prior: 0!\\nA MethodReference is is a lightweight proxy for a CompiledMethod. Has methods for pointed to the CompileMethod's source statements, byte codes. Is heavily used my Tools.\\n\\nInstance Variables\\n\\tclassIsMeta:\\t\\t Boolean class vs. instance\\n\\tclassSymbol:\\t\\tSymbol for method's class (without class keyword if meta)\\n\\tmethodSymbol:\\t\\tSymbol for method's selector\\n\\tstringVersion:\\t\\t'Class>>selector:' format\\n\\n!\\n\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/8/2003 11:54'!\\nhash\\n\\t\\\"Answer a SmallInteger whose value is related to the receiver's \\n\\tidentity.\\\"\\n\\t^ (self species hash bitXor: self classSymbol hash)\\n\\t\\tbitXor: self methodSymbol hash! !\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'RAA 5/28/2001 11:56'!\\n<= anotherMethodReference\\n\\n\\tclassSymbol < anotherMethodReference classSymbol ifTrue: [^true].\\n\\tclassSymbol > anotherMethodReference classSymbol ifTrue: [^false].\\n\\tclassIsMeta = anotherMethodReference classIsMeta ifFalse: [^classIsMeta not].\\n\\t^methodSymbol <= anotherMethodReference methodSymbol\\n! !\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/7/2003 13:18'!\\n= anotherMethodReference \\n\\t\\\"Answer whether the receiver and the argument represent the \\n\\tsame object.\\\"\\n\\t^ self species == anotherMethodReference species\\n\\t\\tand: [self classSymbol = anotherMethodReference classSymbol]\\n\\t\\tand: [self classIsMeta = anotherMethodReference classIsMeta]\\n\\t\\tand: [self methodSymbol = anotherMethodReference methodSymbol]! !\\n\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 06:19'!\\nasStringOrText\\n\\n\\t^stringVersion! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:11'!\\nclassIsMeta\\n\\n\\t^classIsMeta! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'!\\nclassSymbol\\n\\n\\t^classSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'md 8/27/2005 17:17'!\\nisValid\\n\\t\\\"Answer whether the receiver represents a current selector or Comment\\\"\\n\\n\\t| aClass |\\n\\tmethodSymbol isDoIt ifTrue: [^ false].\\n\\t(aClass _ self actualClass) ifNil: [^ false].\\n\\t^ (aClass includesSelector: methodSymbol) or:\\n\\t\\t[methodSymbol == #Comment]! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'!\\nmethodSymbol\\n\\n\\t^methodSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'sw 11/5/2001 00:53'!\\nprintOn: aStream\\n\\t\\\"Print the receiver on a stream\\\"\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' ', self actualClass name, ' >> ', methodSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'sr 6/4/2004 01:55'!\\nsourceString\\n\\t^ (self actualClass sourceCodeAt: self methodSymbol) asString! !\\n\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 07:34'!\\nsetClassAndSelectorIn: csBlock\\n\\n\\t^csBlock value: self actualClass value: methodSymbol! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 06:04'!\\nsetClassSymbol: classSym classIsMeta: isMeta methodSymbol: methodSym stringVersion: aString \\n\\n\\tclassSymbol _ classSym.\\n\\tclassIsMeta _ isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aString.! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 08:06'!\\nsetClass: aClass methodSymbol: methodSym stringVersion: aString \\n\\n\\tclassSymbol _ aClass theNonMetaClass name.\\n\\tclassIsMeta _ aClass isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aString.! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 11:34'!\\nsetStandardClass: aClass methodSymbol: methodSym\\n\\n\\tclassSymbol _ aClass theNonMetaClass name.\\n\\tclassIsMeta _ aClass isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aClass name , ' ' , methodSym.! !\\n\\n\\n!MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'!\\nstringVersion\\n\\n\\t^stringVersion! !\\n\\n!MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'!\\nstringVersion: aString\\n\\n\\tstringVersion _ aString! !\\n\\n\\n!MethodReference methodsFor: '*fixUnderscores' stamp: 'cmm 5/1/2006 19:38'!\\nfixUnderscores\\n\\t\\\"Replace underscores with :=. Answer true if fixed or no fix necessary, false if manual fix required\\\"\\n\\n\\t| src cm ts |\\n\\t\\\"Check if we do need to do anything\\\"\\n\\tsrc := self actualClass sourceCodeAt: methodSymbol.\\n\\t(src includes: $_) ifFalse: [^true].\\n\\n\\t\\\"Chicken out if there is a literal underscore\\\"\\n\\tcm := self actualClass compiledMethodAt: methodSymbol.\\n\\t(cm hasLiteralSuchThat: [:lit | \\n\\t\\tlit = $_ or: [lit isString and: [lit includes: $_]]]) ifTrue: [^false].\\n\\n\\t\\\"Otherwise, replace underscores with :=\\\"\\n\\tsrc := src copyReplaceAll: '_' with: ':='.\\n\\tts := self timeStamp.\\n\\tts = '' ifTrue: [ts := nil].\\n\\tself actualClass \\n\\t\\tcompile: src\\n\\t\\tclassified: ClassOrganizer default\\n\\t\\twithStamp: ts \\n\\t\\tnotifying: nil.\\n\\n\\t^true\\n! !\\n\\n\\n!MethodReference methodsFor: '*Kernel-Traits' stamp: 'md 3/3/2006 09:25'!\\nactualClass \\n\\n\\t| actualClass |\\n\\n\\tactualClass _ Smalltalk at: classSymbol ifAbsent: [^nil].\\n\\tclassIsMeta ifTrue: [^actualClass classSide].\\n\\t^actualClass\\n\\n! !\\n\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:55'!\\nasMethodDefinition\\n\\t^ MCMethodDefinition forMethodReference: self! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ncategory\\n\\t^ self actualClass organization categoryOfElement: methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ncompiledMethod\\n\\t^ self actualClass compiledMethodAt: methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'al 10/9/2005 20:05'!\\nisLocalSelector\\n\\t^self actualClass\\n\\t\\tincludesLocalSelector: self methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:59'!\\nsource\\n\\t^ (self actualClass sourceCodeAt: methodSymbol) asString withSqueakLineEndings! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ntimeStamp\\n\\t^ self compiledMethod timeStamp! !\\n\\n\\n!MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'!\\nsourceCode\\n\\t^ self actualClass sourceCodeAt: methodSymbol! !\\n\\n\\n!MethodReference methodsFor: '*OB-Standard' stamp: 'dvf 8/19/2005 17:16'!\\nasNode\\n\\t^OBMethodNode on: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMethodReference class\\n\\tinstanceVariableNames: ''!\\n\\n!MethodReference class methodsFor: 'instance creation' stamp: 'ab 2/6/2005 16:22'!\\nclass: aClass selector: aSelector\\n\\t^ self new setStandardClass: aClass methodSymbol: aSelector! !\\nClassTestCase subclass: #MethodReferenceTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Browser-Tests'!\\n\\n!MethodReferenceTest methodsFor: 'Running' stamp: 'sd 11/20/2005 21:27'!\\ntestEquals\\n\\t| aMethodReference anotherMethodReference |\\n\\taMethodReference := MethodReference new.\\n\\tanotherMethodReference := MethodReference new.\\n\\t\\\" \\n\\ttwo fresh instances should be equals between them\\\"\\n\\tself\\n\\t\\tshould: [aMethodReference = anotherMethodReference].\\n\\tself\\n\\t\\tshould: [aMethodReference hash = anotherMethodReference hash].\\n\\t\\\" \\n\\ttwo instances representing the same method (same class and \\n\\tsame selector) should be equals\\\"\\n\\taMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tanotherMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tself\\n\\t\\tshould: [aMethodReference = anotherMethodReference].\\n\\tself\\n\\t\\tshould: [aMethodReference hash = anotherMethodReference hash] ! !\\n\\n!MethodReferenceTest methodsFor: 'Running' stamp: 'sd 11/20/2005 21:27'!\\ntestNotEquals\\n\\t| aMethodReference anotherMethodReference |\\n\\taMethodReference := MethodReference new.\\n\\tanotherMethodReference := MethodReference new.\\n\\t\\\"\\\"\\n\\taMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tanotherMethodReference setStandardClass: String class methodSymbol: #foo.\\n\\t\\\" \\n\\tdifferente classes, same selector -> no more equals\\\"\\n\\tself\\n\\t\\tshouldnt: [aMethodReference = anotherMethodReference].\\n\\t\\\" \\n\\tsame classes, diferente selector -> no more equals\\\"\\n\\tanotherMethodReference setStandardClass: String methodSymbol: #bar.\\n\\tself\\n\\t\\tshouldnt: [aMethodReference = anotherMethodReference] ! !\\nParseNode subclass: #MethodTempsNode\\n\\tinstanceVariableNames: 'temporaries'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-ParseNodes'!\\nMethodInterface subclass: #MethodWithInterface\\n\\tinstanceVariableNames: 'playerClass'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n!MethodWithInterface commentStamp: '<historical>' prior: 0!\\nA MethodInterface bound to an actual class.\\n\\n\\tselector\\t\\t\\t\\t\\tA symbol - the selector being described\\n\\targumentSpecifications\\tA list of specifications for the formal arguments of the method\\n\\tresultSpecification \\t\\tA characterization of the return value of the method\\n\\tuserLevel\\t\\t\\t\\t\\n\\tattributeKeywords\\t\\tA list of symbols, comprising keywords that the user wishes to\\n\\t\\t\\t\\t\\t\\t\\t\\tassociate with this method\\n\\tdefaultStatus\\t\\t\\tThe status to apply to new instances of the class by default\\n\\tdefaultFiresPerTick\\t\\tHow many fires per tick, by default, should be allowed if ticking.\\n\\tplayerClass\\t\\t\\t\\tThe actual class with which this script is associated!\\n\\n\\n!MethodWithInterface methodsFor: 'access' stamp: 'sw 3/28/2001 16:25'!\\nplayerClass\\n\\t\\\"Answer the playerClass associated with the receiver. Note: fixes up cases where the playerClass slot was a Playerxxx object because of an earlier bug\\\"\\n\\n\\t^ (playerClass isKindOf: Class)\\n\\t\\tifTrue:\\n\\t\\t\\t[playerClass]\\n\\t\\tifFalse:\\n\\t\\t\\t[playerClass _ playerClass class]! !\\n\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 1/30/2001 11:37'!\\nconvertFromUserScript: aUserScript\\n\\t\\\"The argument represents an old UserScript object. convert it over\\\"\\n\\n\\tdefaultStatus _ aUserScript status.! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 1/26/2001 16:44'!\\ninitialize\\n\\t\\\"Initialize the receiver by setting its inst vars to default values\\\"\\n\\n\\tsuper initialize.\\n\\tdefaultStatus _ #normal! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 2/20/2001 03:29'!\\nisTextuallyCoded\\n\\t\\\"Answer whether the receiver is in a textually-coded state. A leftover from much earlier times, this is a vacuous backstop\\\"\\n\\n\\t^ false! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 9/12/2001 11:59'!\\nplayerClass: aPlayerClass selector: aSelector\\n\\t\\\"Set the playerClass and selector of the receiver\\\"\\n\\n\\tplayerClass _ aPlayerClass.\\n\\tselector _ aSelector.! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'nk 7/2/2004 07:18'!\\nstatus\\n\\t^defaultStatus\\n! !\\n\\n\\n!MethodWithInterface methodsFor: 'rename' stamp: 'sw 2/17/2001 04:10'!\\nokayToRename\\n\\t\\\"Answer whether the receiver is in a state to be renamed.\\\"\\n\\n\\t^ true! !\\n\\n!MethodWithInterface methodsFor: 'rename' stamp: 'sw 3/11/2003 00:01'!\\nrenameScript: newSelector fromPlayer: aPlayer\\n\\n\\t\\\"The receiver's selector has changed to the new selector. Get various things right, including the physical appearance of any Scriptor open on this method\\\"\\n\\n\\n\\n\\tself allScriptEditors do:\\n\\n\\t\\t[:aScriptEditor | aScriptEditor renameScriptTo: newSelector].\\n\\n\\n\\n\\t(selector numArgs = 0 and: [newSelector numArgs = 1])\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self argumentVariables: (OrderedCollection with:\\n\\n\\t\\t\\t\\t(Variable new name: #parameter type: #Number))].\\n\\n\\t(selector numArgs = 1 and: [newSelector numArgs = 0])\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self argumentVariables: OrderedCollection new].\\n\\n\\n\\n\\tselector _ newSelector asSymbol.\\n\\n\\tself bringUpToDate.\\n\\n\\tself playerClass atSelector: selector putScript: self.\\n\\n\\tself allScriptActivationButtons do:\\n\\n\\t\\t[:aButton | aButton bringUpToDate].\\n\\n\\n\\n! !\\n\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/10/2003 23:58'!\\nallScriptActivationButtons\\n\\n\\t\\\"Answer all the script-activation buttons that exist for this interface\\\"\\n\\n\\n\\n\\t^ ScriptActivationButton allInstances select: \\n\\n\\t\\t[:aButton | aButton uniclassScript == self]! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/28/2001 16:26'!\\nallScriptEditors\\n\\t\\\"Answer all the script editors that exist for the class and selector of this interface\\\"\\n\\n\\t^ ScriptEditorMorph allInstances select: \\n\\t\\t[:aScriptEditor | aScriptEditor playerScripted class == self playerClass and:\\n\\t\\t\\t[aScriptEditor scriptName == selector]]! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 2/17/2001 03:28'!\\ncurrentScriptEditor: anEditor\\n\\t\\\"Set the receiver's currentScriptEditor as indicated, if I care. MethodWithInterface does not care, since it does not hold on to a ScriptEditor. A subclass of mine, however does, or did, care\\\"! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/28/2001 16:26'!\\ninstantiatedScriptEditorForPlayer: aPlayer\\n\\t\\\"Return a new script editor for the player and selector\\\"\\n\\n\\t| aScriptEditor |\\n\\taScriptEditor _ (self playerClass includesSelector: selector) \\n\\t\\t\\tifTrue: [ScriptEditorMorph new \\n\\t\\t\\t\\tfromExistingMethod: selector \\n\\t\\t\\t\\tforPlayer: aPlayer]\\n\\t\\t\\tifFalse: [ScriptEditorMorph new\\n\\t\\t\\t\\tsetMorph: aPlayer costume\\n\\t\\t\\t\\tscriptName: selector].\\n\\t\\tdefaultStatus == #ticking ifTrue:\\n\\t\\t\\t[aPlayer costume arrangeToStartStepping].\\n\\t\\n\\t^ aScriptEditor! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 7/28/2001 01:00'!\\nrecompileScriptFromTilesUnlessTextuallyCoded\\n\\t\\\"Recompile Script From Tiles Unless Textually Coded. For the universal-tiles MethodWithInterface case, this is moot. Used only in support of a reintegration of Open-school forked projects from Sept 2000 in 7/01\\\"! !\\n\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 3/28/2001 16:26'!\\nbringUpToDate\\n\\t\\\"Bring all scriptors related to this method up to date. Note that this will not change the senders of this method if the selector changed -- that's something still ahead.\\\"\\n\\n\\t(ScriptEditorMorph allInstances select:\\n\\t\\t[:m | (m playerScripted isMemberOf: self playerClass) and: [m scriptName == selector]])\\n\\t\\t\\tdo:\\n\\t\\t\\t\\t[:m | m bringUpToDate]! !\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 2/20/2001 03:43'!\\nrevertToLastSavedTileVersionFor: anEditor\\n\\t\\\"revert to the last saved tile version. Only for universal tiles.\\\"\\n\\n\\tanEditor removeAllButFirstSubmorph.\\n\\tanEditor insertUniversalTiles.\\n\\tanEditor showingMethodPane: false! !\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 2/20/2001 03:41'!\\nsaveScriptVersion: timeStamp\\n\\t\\\"Save the tile script version if I do that sort of thing\\\"! !\\nAlignmentMorph subclass: #MidiInputMorph\\n\\tinstanceVariableNames: 'midiPortNumber midiSynth instrumentSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Scores'!\\n!MidiInputMorph commentStamp: '<historical>' prior: 0!\\nI am the user interface for a simple software MIDI synthesizer that is driven by external MIDI input. I come with controls for a single MIDI channel (channel 1), but allow channel controls for additional MIDI channels to be added by the user. The volume, pan, and instrument of each channel can be controlled independently.\\n!\\n\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naddChannel\\n\\t\\\"Add a set of controls for another channel. Prompt the user for the channel number.\\\"\\n\\n\\t| menu existingChannels newChannel |\\n\\tmenu := CustomMenu new.\\n\\texistingChannels := Set new.\\n\\t1 to: 16 do: [:ch | (instrumentSelector at: ch) ifNotNil: [existingChannels add: ch]].\\n\\t1 to: 16 do: [:ch |\\n\\t\\t(existingChannels includes: ch) ifFalse: [\\n\\t\\t\\tmenu add: ch printString action: ch]].\\n\\tnewChannel := menu startUp.\\n\\tnewChannel ifNotNil: [self addChannelControlsFor: newChannel].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naddChannelControlsFor: channelIndex\\n\\n\\t| r divider col |\\n\\tr := self makeRow\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tr addMorphBack: (self channelNumAndMuteButtonFor: channelIndex).\\n\\tr addMorphBack: (Morph new extent: 10@5; color: color). \\\"spacer\\\"\\n\\tr addMorphBack: (self panAndVolControlsFor: channelIndex).\\n\\n\\tdivider := AlignmentMorph new\\n\\t\\textent: 10@1;\\n\\t\\tborderWidth: 1;\\n\\t\\tlayoutInset: 0;\\n\\t\\tborderColor: #raised;\\n\\t\\tcolor: color;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #rigid.\\n\\n\\tcol := self lastSubmorph.\\n\\tcol addMorphBack: divider.\\n\\tcol addMorphBack: r.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'gm 2/28/2003 00:00'!\\natChannel: channelIndex from: aPopUpChoice selectInstrument: selection \\n\\t| oldSnd name snd instSelector |\\n\\toldSnd := midiSynth instrumentForChannel: channelIndex.\\n\\t(selection beginsWith: 'edit ') \\n\\t\\tifTrue: \\n\\t\\t\\t[name := selection copyFrom: 6 to: selection size.\\n\\t\\t\\taPopUpChoice contentsClipped: name.\\n\\t\\t\\t(oldSnd isKindOf: FMSound) | (oldSnd isKindOf: LoopedSampledSound) \\n\\t\\t\\t\\tifTrue: [EnvelopeEditorMorph openOn: oldSnd title: name].\\n\\t\\t\\t(oldSnd isKindOf: SampledInstrument) \\n\\t\\t\\t\\tifTrue: [EnvelopeEditorMorph openOn: oldSnd allNotes first title: name].\\n\\t\\t\\t^self].\\n\\tsnd := nil.\\n\\t1 to: instrumentSelector size\\n\\t\\tdo: \\n\\t\\t\\t[:i | \\n\\t\\t\\t(channelIndex ~= i and: \\n\\t\\t\\t\\t\\t[(instSelector := instrumentSelector at: i) notNil \\n\\t\\t\\t\\t\\t\\tand: [selection = instSelector contents]]) \\n\\t\\t\\t\\tifTrue: [snd := midiSynth instrumentForChannel: i]].\\t\\\"use existing instrument prototype\\\"\\n\\tsnd ifNil: \\n\\t\\t\\t[snd := (selection = 'clink' \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[(SampledSound samples: SampledSound coffeeCupClink samplingRate: 11025)]\\n\\t\\t\\t\\t\\t\\tifFalse: [(AbstractSound soundNamed: selection) ])copy ].\\n\\tmidiSynth instrumentForChannel: channelIndex put: snd.\\n\\t(instrumentSelector at: channelIndex) contentsClipped: selection! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nchannelNumAndMuteButtonFor: channelIndex\\n\\n\\t| muteButton instSelector r |\\n\\tmuteButton := SimpleSwitchMorph new\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\toffColor: color;\\n\\t\\tcolor: color;\\n\\t\\tlabel: 'Mute';\\n\\t\\ttarget: midiSynth;\\n\\t\\tactionSelector: #mutedForChannel:put:;\\n\\t\\targuments: (Array with: channelIndex).\\n\\tinstSelector := PopUpChoiceMorph new\\n\\t\\textent: 95@14;\\n\\t\\tcontentsClipped: 'oboe1';\\n\\t\\ttarget: self;\\n\\t\\tactionSelector: #atChannel:from:selectInstrument:;\\n\\t\\tgetItemsSelector: #instrumentChoicesForChannel:;\\n\\t\\tgetItemsArgs: (Array with: channelIndex).\\n\\tinstSelector arguments:\\n\\t\\t(Array with: channelIndex with: instSelector).\\n\\tinstrumentSelector at: channelIndex put: instSelector.\\n\\n\\tr := self makeRow\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\textent: 70@10.\\n\\tr addMorphBack:\\n\\t\\t(StringMorph\\n\\t\\t\\tcontents: channelIndex printString\\n\\t\\t\\tfont: (TextStyle default fontOfSize: 24)).\\n\\tchannelIndex < 10\\n\\t\\tifTrue: [r addMorphBack: (Morph new color: color; extent: 19@8)] \\\"spacer\\\"\\n\\t\\tifFalse: [r addMorphBack: (Morph new color: color; extent: 8@8)]. \\\"spacer\\\"\\n\\tr addMorphBack: instSelector.\\n\\tr addMorphBack: (AlignmentMorph newRow color: color). \\\"spacer\\\"\\n\\tr addMorphBack: muteButton.\\n\\t^ r\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/13/1999 07:33'!\\ncloseMIDIPort\\n\\n\\tmidiSynth isOn ifTrue: [midiSynth stopMIDITracking].\\n\\tmidiSynth closeMIDIPort.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/6/1999 07:55'!\\ndisableReverb: aBoolean\\n\\n\\taBoolean\\n\\t\\tifTrue: [SoundPlayer stopReverb]\\n\\t\\tifFalse: [SoundPlayer startReverb].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninstrumentChoicesForChannel: channelIndex\\n\\n\\t| names inst |\\n\\tnames := AbstractSound soundNames asOrderedCollection.\\n\\tnames := names collect: [:n |\\n\\t\\tinst := AbstractSound soundNamed: n.\\n\\t\\t(inst isKindOf: UnloadedSound)\\n\\t\\t\\tifTrue: [n, '(out)']\\n\\t\\t\\tifFalse: [n]].\\n\\tnames add: 'clink'.\\n\\tnames add: 'edit ', (instrumentSelector at: channelIndex) contents.\\n\\t^ names asArray\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninvokeMenu\\n\\t\\\"Invoke a menu of additonal commands.\\\"\\n\\n\\t| aMenu |\\n\\taMenu := CustomMenu new.\\n\\taMenu add: 'add channel' translated action: #addChannel.\\n\\taMenu add: 'reload instruments' translated target: AbstractSound selector: #updateScorePlayers.\\n\\tmidiSynth isOn ifFalse: [\\n\\t\\taMenu add: 'set MIDI port' translated action: #setMIDIPort.\\n\\t\\tmidiSynth midiPort\\n\\t\\t\\tifNotNil: [aMenu add: 'close MIDI port' translated action: #closeMIDIPort]].\\t\\n\\taMenu invokeOn: self defaultSelection: nil.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmakeControls\\n\\n\\t| bb r reverbSwitch onOffSwitch |\\n\\tbb := SimpleButtonMorph new\\n\\t\\ttarget: self;\\n\\t\\tborderColor: #raised;\\n\\t\\tborderWidth: 2;\\n\\t\\tcolor: color.\\n\\tr := AlignmentMorph newRow.\\n\\tr color: bb color; borderWidth: 0; layoutInset: 0.\\n\\tr hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tr addMorphBack: (\\n\\t\\tbb label: '<>';\\n\\t\\t\\tactWhen: #buttonDown;\\n\\t\\t\\tactionSelector: #invokeMenu).\\n\\tonOffSwitch := SimpleSwitchMorph new\\n\\t\\toffColor: color;\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\tborderWidth: 2;\\n\\t\\tlabel: 'On';\\n\\t\\tactionSelector: #toggleOnOff;\\n\\t\\ttarget: self;\\n\\t\\tsetSwitchState: false.\\n\\tr addMorphBack: onOffSwitch.\\n\\treverbSwitch := SimpleSwitchMorph new\\n\\t\\toffColor: color;\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\tborderWidth: 2;\\n\\t\\tlabel: 'Reverb Disable';\\n\\t\\tactionSelector: #disableReverb:;\\n\\t\\ttarget: self;\\n\\t\\tsetSwitchState: SoundPlayer isReverbOn not.\\n\\tr addMorphBack: reverbSwitch.\\n\\t^ r\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/9/2000 21:19'!\\nmakeRow\\n\\n\\t^ AlignmentMorph newRow\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #leftCenter;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npanAndVolControlsFor: channelIndex\\n\\n\\t| volSlider panSlider c r middleLine |\\n\\tvolSlider := SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 101@2;\\n\\t\\ttarget: midiSynth;\\n\\t\\targuments: (Array with: channelIndex);\\n\\t\\tactionSelector: #volumeForChannel:put:;\\n\\t\\tminVal: 0.0;\\n\\t\\tmaxVal: 1.0;\\n\\t\\tadjustToValue: (midiSynth volumeForChannel: channelIndex).\\n\\tpanSlider := SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 101@2;\\n\\t\\ttarget: midiSynth;\\n\\t\\targuments: (Array with: channelIndex);\\n\\t\\tactionSelector: #panForChannel:put:;\\n\\t\\tminVal: 0.0;\\n\\t\\tmaxVal: 1.0;\\t\\t\\n\\t\\tadjustToValue: (midiSynth panForChannel: channelIndex).\\n\\tc := AlignmentMorph newColumn\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #topCenter;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tmiddleLine := Morph new \\\"center indicator for pan slider\\\"\\n\\t\\tcolor: (Color r: 0.4 g: 0.4 b: 0.4);\\n\\t\\textent: 1@(panSlider height - 4);\\n\\t\\tposition: panSlider center x@(panSlider top + 2).\\n\\tpanSlider addMorphBack: middleLine.\\n\\tr := self makeRow.\\n\\tr addMorphBack: (StringMorph contents: '0').\\n\\tr addMorphBack: volSlider.\\n\\tr addMorphBack: (StringMorph contents: '10').\\n\\tc addMorphBack: r.\\n\\tr := self makeRow.\\n\\tr addMorphBack: (StringMorph contents: 'L').\\n\\tr addMorphBack: panSlider.\\n\\tr addMorphBack: (StringMorph contents: 'R').\\n\\tc addMorphBack: r.\\n\\t^ c\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsetMIDIPort\\n\\n\\t| portNum |\\n\\tportNum := SimpleMIDIPort outputPortNumFromUser.\\n\\tportNum ifNil: [^ self].\\n\\tmidiPortNumber := portNum.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntoggleOnOff\\n\\n\\tmidiSynth isOn\\n\\t\\tifTrue: [\\n\\t\\t\\tmidiSynth stopMIDITracking]\\n\\t\\tifFalse: [\\n\\t\\t\\tmidiPortNumber ifNil: [self setMIDIPort].\\n\\t\\t\\tmidiPortNumber ifNil: [midiPortNumber := 0].\\n\\t\\t\\tmidiSynth midiPort: (SimpleMIDIPort openOnPortNumber: midiPortNumber).\\n\\t\\t\\tmidiSynth startMIDITracking].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nupdateInstrumentsFromLibraryExcept: soundsBeingEdited\\n\\t\\\"The instrument library has been modified. Update my instruments with the new versions from the library. Use a single instrument prototype for all parts with the same name; this allows the envelope editor to edit all the parts by changing a single sound prototype.\\\"\\n\\n\\t\\\"soundsBeingEdited is a collection of sounds being edited (by an EnvelopeEditor). If any of my instruments share one of these, then they will be left alone so as not to disturb that dynamic linkage.\\\"\\n\\n\\t| unloadPostfix myInstruments name displaysAsUnloaded isUnloaded |\\n\\tunloadPostfix := '(out)'.\\n\\tmyInstruments := Dictionary new.\\n\\t1 to: instrumentSelector size do: [:i |\\n\\t\\tname := (instrumentSelector at: i) contents.\\n\\t\\tdisplaysAsUnloaded := name endsWith: unloadPostfix.\\n\\t\\tdisplaysAsUnloaded ifTrue: [\\n\\t\\t\\tname := name copyFrom: 1 to: name size - unloadPostfix size].\\n\\t\\t(myInstruments includesKey: name) ifFalse: [\\n\\t\\t\\tmyInstruments at: name put:\\n\\t\\t\\t\\t(name = 'clink'\\n\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t(SampledSound\\n\\t\\t\\t\\t\\t\\t\\tsamples: SampledSound coffeeCupClink\\n\\t\\t\\t\\t\\t\\t\\tsamplingRate: 11025) copy]\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t(AbstractSound\\n\\t\\t\\t\\t\\t\\t\\tsoundNamed: name\\n\\t\\t\\t\\t\\t\\t\\tifAbsent: [\\n\\t\\t\\t\\t\\t\\t\\t\\t(instrumentSelector at: i) contentsClipped: 'default'.\\n\\t\\t\\t\\t\\t\\t\\t\\tFMSound default]) copy])].\\n\\t\\t(soundsBeingEdited includes: (midiSynth instrumentForChannel: i)) ifFalse:\\n\\t\\t\\t[\\\"Do not update any instrument that is currently being edited\\\"\\n\\t\\t\\tmidiSynth instrumentForChannel: i put: (myInstruments at: name)].\\n\\n\\t\\t\\\"update loaded/unloaded status in instrumentSelector if necessary\\\"\\n\\t\\tisUnloaded := (myInstruments at: name) isKindOf: UnloadedSound.\\n\\t\\t(displaysAsUnloaded and: [isUnloaded not])\\n\\t\\t\\tifTrue: [(instrumentSelector at: i) contentsClipped: name].\\n\\t\\t(displaysAsUnloaded not and: [isUnloaded])\\n\\t\\t\\tifTrue: [(instrumentSelector at: i) contentsClipped: name, unloadPostfix]].\\n! !\\n\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:38'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryLightGray! !\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself listDirection: #topToBottom;\\n\\t wrapCentering: #center;\\n\\t\\t cellPositioning: #topCenter;\\n\\t hResizing: #spaceFill;\\n\\t vResizing: #spaceFill;\\n\\t layoutInset: 3.\\n\\tmidiPortNumber := nil.\\n\\tmidiSynth := MIDISynth new.\\n\\tinstrumentSelector := Array new: 16.\\n\\tself removeAllMorphs.\\n\\tself addMorphBack: self makeControls.\\n\\tself addMorphBack: (AlignmentMorph newColumn color: color;\\n\\t\\t\\t layoutInset: 0).\\n\\tself addChannelControlsFor: 1.\\n\\tself extent: 20 @ 20! !\\nObject subclass: #MidiPrimTester\\n\\tinstanceVariableNames: 'port'\\n\\tclassVariableNames: 'CanSetClock CanUseSemaphore ClockTicksPerSec EchoOn EventsAvailable FlushDriver HasBuffer HasDurs HasInputClock Installed UseControllerCache Version'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Serial Port'!\\n!MidiPrimTester commentStamp: '<historical>' prior: 0!\\nThis class simply demonstrates and tests the MIDI primitives. MIDI applications should use Stephen Pope's MIDIPort class, which will replace this one.\\n\\nThe Macintosh, and perhaps some other platforms, can send and receive MIDI data over a serial port by using an external clock signal supplied by an external MIDI adapter to generate the correct MIDI baud rate. Typical clock speeds of such adapters are 1, 2, or 0.5 MHz. This clock speed can be specified when a MIDI port is opened. On other platforms, this clock speed parameter is ignored.\\n!\\n\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIClosePort: portNum\\n\\n\\t<primitive: 'primitiveMIDIClosePort' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetClock\\n\\n\\t<primitive: 'primitiveMIDIGetClock' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortCount\\n\\n\\t<primitive: 'primitiveMIDIGetPortCount' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortDirectionality: portNum\\n\\n\\t<primitive: 'primitiveMIDIGetPortDirectionality' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortName: portNum\\n\\n\\t<primitive: 'primitiveMIDIGetPortName' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIOpenPort: portNum readSemaIndex: readSemaIndex interfaceClockRate: interfaceClockRate\\n\\t\\\"Open the given MIDI port. If non-zero, readSemaIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Not all platforms support signalling the read semaphore. InterfaceClockRate specifies the clock rate of the external MIDI interface adaptor on Macintosh computers; it is ignored on other platforms.\\\"\\n\\n\\t<primitive: 'primitiveMIDIOpenPort' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIParameterGet: whichParameter\\n\\n\\t<primitive: 'primitiveMIDIParameterGetOrSet' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIParameterSet: whichParameter to: newValue\\n\\n\\t<primitive: 'primitiveMIDIParameterGetOrSet' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIReadPort: portNum into: byteArray\\n\\n\\t<primitive: 'primitiveMIDIRead' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIWritePort: portNum from: byteArray at: midiClockValue\\n\\n\\t<primitive: 'primitiveMIDIWrite' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 10:30'!\\ngetDriverParameters\\n\\t\\\"Return a string that describes this platform's MIDI parameters.\\\"\\n\\t\\\"MidiPrimTester new getDriverParameters\\\"\\n\\n\\t| s parameterNames v |\\n\\tparameterNames _ #(Installed Version HasBuffer HasDurs CanSetClock CanUseSemaphore EchoOn UseControllerCache EventsAvailable FlushDriver ClockTicksPerSec HasInputClock).\\n\\n\\ts _ WriteStream on: String new.\\n\\ts cr.\\n\\t1 to: parameterNames size do: [:i |\\n\\t\\tv _ self primMIDIParameterGet: i.\\n\\t\\ts nextPutAll: (parameterNames at: i).\\n\\t\\ts nextPutAll: ' = '.\\n\\t\\ts print: v; cr].\\n\\n\\ts nextPutAll: 'MIDI Echoing is '.\\n\\t(self canTurnOnParameter: EchoOn)\\n\\t\\tifTrue: [s nextPutAll: 'supported.'; cr]\\n\\t\\tifFalse: [s nextPutAll: 'not supported.'; cr].\\n\\n\\ts nextPutAll: 'Controller Caching is '.\\n\\t(self canTurnOnParameter: UseControllerCache)\\n\\t\\tifTrue: [s nextPutAll: 'supported.'; cr]\\n\\t\\tifFalse: [s nextPutAll: 'not supported.'; cr].\\n\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:33'!\\ngetInputForSeconds: seconds onPort: portNum\\n\\t\\\"Collect MIDI input from the given port for the given number of seconds, and answer a string describing the data read.\\\"\\n\\t\\\"MidiPrimTester new getInputForSeconds: 5 onPort: 0\\\"\\n\\n\\t| buf bufList endTime n midiStartTime s t |\\n\\t\\\"collect the data\\\"\\n\\tself openPort: portNum andDo: [\\n\\t\\tbuf _ ByteArray new: 1000.\\n\\t\\tbufList _ OrderedCollection new.\\n\\t\\tmidiStartTime _ self primMIDIGetClock.\\n\\t\\tendTime _ Time millisecondClockValue + (seconds * 1000).\\n\\t\\t[Time millisecondClockValue < endTime] whileTrue: [\\n\\t\\t\\tn _ self primMIDIReadPort: portNum into: buf.\\n\\t\\t\\tn > 0 ifTrue: [bufList add: (buf copyFrom: 1 to: n)].\\n\\t\\t\\t(Delay forMilliseconds: 5) wait]].\\n\\n\\t\\\"format the data into a string\\\"\\n\\ts _ WriteStream on: String new.\\n\\ts cr.\\n\\tbufList do: [:b |\\n\\t\\tt _ (self bufferTimeStampFrom: b) - midiStartTime.\\n\\t\\ts print: t.\\n\\t\\ts nextPutAll: ': '.\\n\\t\\t5 to: b size do: [:i | s print: (b at: i); space].\\n\\t\\ts cr].\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 10:05'!\\ngetPortList\\n\\t\\\"Return a string that describes this platform's MIDI ports.\\\"\\n\\t\\\"MidiPrimTester new getPortList\\\"\\n\\n\\t| s portCount dir directionString |\\n\\ts _ WriteStream on: String new.\\n\\ts cr; nextPutAll: 'MIDI Ports:'; cr.\\n\\tportCount _ self primMIDIGetPortCount.\\n\\t0 to: portCount - 1 do: [:i |\\n\\t\\ts tab.\\n\\t\\ts print: i; nextPutAll: ': '. \\n\\t\\ts nextPutAll: (self primMIDIGetPortName: i).\\n\\t\\tdir _ self primMIDIGetPortDirectionality: i.\\n\\t\\tdirectionString _ dir printString. \\\"default\\\"\\n\\t\\tdir = 1 ifTrue: [directionString _ '(in)'].\\n\\t\\tdir = 2 ifTrue: [directionString _ '(out)'].\\n\\t\\tdir = 3 ifTrue: [directionString _ '(in/out)'].\\n\\t\\ts space; nextPutAll: directionString; cr].\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 11:24'!\\nplayDrumRoll: mSecsBetweenNotes count: tapCount onPort: portNum\\n\\t\\\"MidiPrimTester new playDrumRoll: 75 count: 64 onPort: 0\\\"\\n\\t\\\"Play middle-C tapCount times with the given space between notes. This example works best with a short percussive voice, like a drum.\\\"\\n\\t\\\"Details: This test can be used to investigate the real-time performance of your system. On a 110 MHz PowerPC Mac, this method can genererate very fast and smooth drum rolls up to about 100 beats/sec (10 mSecs between notes). However, many factors can prevent one from seeing this level of performance including a slow CPU, lack of a level-2 cache, networking or other background processes stealing chunks of processor time from Squeak, or a sluggish MIDI synthesizer.\\\"\\n\\t\\\"Details: By default, this method does an incremental GC on every note. While not really needed for this example, it illustrates a useful technique for real-time processing in Squeak: do an incremental GC when you know you have a few milliseconds of idle time to avoid triggering one during a time-critical task. In this case, we're also using the GC time to provide a small delay between the note-on and note-off events. If the GC time is too short, as it could be on a fast machine, the note may not sound at all unless you add a few milliseconds of additional delay!!\\\"\\n\\t\\\"Note: This example works best if the VM's millisecond clock has 1 millisecond resolution.\\\"\\n\\n\\t| gcDuringNote noteOn noteOff endTime waitTime |\\n\\tgcDuringNote _ true.\\n\\t\\\"these events use running status, so the command byte is omitted\\\"\\n\\tnoteOn _ #(60 100) as: ByteArray.\\n\\tnoteOff _ #(60 0) as: ByteArray.\\n\\tself primMIDIOpenPort: portNum readSemaIndex: 0 interfaceClockRate: 1000000.\\n\\n\\t\\\"send an initial event with command byte to initiate running status\\\"\\n\\tself primMIDIWritePort: portNum from: (#(144 60 0) as: ByteArray) at: 0.\\n\\n\\t1 to: tapCount do: [:i |\\n\\t\\tendTime _ Time millisecondClockValue + mSecsBetweenNotes.\\n\\t\\tself primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\tgcDuringNote\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\\"do quick GC; takes a few milliseconds and provides the note-down time\\\"\\n\\t\\t\\t\\t\\\"Note: if GC is too fast on your machine, you need to add a few mSecs delay!!\\\"\\n\\t\\t\\t\\tSmalltalk garbageCollectMost]\\n\\t\\t\\tifFalse: [(Delay forMilliseconds: 3) wait].\\n\\n\\t\\tself primMIDIWritePort: portNum from: noteOff at: 0.\\n\\t\\twaitTime _ endTime - Time millisecondClockValue.\\n\\t\\twaitTime > 0 ifTrue: [(Delay forMilliseconds: waitTime) wait]].\\n\\n\\tself primMIDIClosePort: portNum.\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:16'!\\nplayNoteOnPort: portNum\\n\\t\\\"MidiPrimTester new playNoteOnPort: 0\\\"\\n\\n\\t| noteOn noteOff bytesWritten |\\n\\tnoteOn _ #(144 60 100) as: ByteArray.\\n\\tnoteOff _ #(144 60 0) as: ByteArray.\\n\\tself openPort: portNum andDo: [\\n\\t\\tbytesWritten _ self primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\t(Delay forMilliseconds: 500) wait.\\n\\t\\tbytesWritten _ bytesWritten + (self primMIDIWritePort: portNum from: noteOff at: 0)].\\n\\n\\tbytesWritten = 6 ifFalse: [self error: 'not all bytes were sent'].\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:17'!\\nplayScale: mSecsPerNote onPort: portNum\\n\\t\\\"MidiPrimTester new playScale: 130 onPort: 0\\\"\\n\\n\\t| noteOn noteOff |\\n\\tnoteOn _ #(144 0 100) as: ByteArray.\\n\\tnoteOff _ #(144 0 0) as: ByteArray.\\n\\tself openPort: portNum andDo: [\\n\\t\\t#(60 62 64 65 67 69 71 72 74 72 71 69 67 65 64 62 60) do: [:midiKey | \\n\\t\\t\\tnoteOn at: 2 put: midiKey.\\n\\t\\t\\tnoteOff at: 2 put: midiKey.\\n\\t\\t\\tself primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\t\\t(Delay forMilliseconds: mSecsPerNote - 10) wait.\\n\\t\\t\\tself primMIDIWritePort: portNum from: noteOff at: 0.\\n\\t\\t\\t(Delay forMilliseconds: 10) wait]].\\n! !\\n\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 12:48'!\\nbufferTimeStampFrom: aByteArray\\n\\t\\\"Return the timestamp from the given MIDI input buffer. Assume the given buffer is at least 4 bytes long.\\\"\\n\\n\\t^ ((aByteArray at: 1) bitShift: 24) +\\n\\t ((aByteArray at: 2) bitShift: 16) +\\n\\t ((aByteArray at: 3) bitShift: 8) +\\n\\t (aByteArray at: 4)\\n! !\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 12:48'!\\ncanTurnOnParameter: whichParameter\\n\\t\\\"Return true if the given MIDI parameter can be turned on. Leave the parameter in its orginal state.\\\"\\n\\n\\t| old canSet |\\n\\told _ self primMIDIParameterGet: whichParameter.\\n\\tself primMIDIParameterSet: whichParameter to: 1.\\n\\tcanSet _ (self primMIDIParameterGet: whichParameter) = 1.\\n\\tself primMIDIParameterSet: whichParameter to: old.\\n\\t^ canSet\\n! !\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 15:32'!\\nopenPort: portNum andDo: aBlock\\n\\t\\\"Open the given MIDI port, evaluate the block, and close the port again. Answer the value of the block.\\\"\\n\\n\\t| result |\\n\\tself primMIDIClosePort: portNum.\\n\\tself primMIDIOpenPort: portNum readSemaIndex: 0 interfaceClockRate: 1000000.\\n\\tresult _ aBlock value.\\n\\tself primMIDIClosePort: portNum.\\n\\t^ result\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMidiPrimTester class\\n\\tinstanceVariableNames: ''!\\n\\n!MidiPrimTester class methodsFor: 'class initialization' stamp: 'yo 12/3/2004 17:05'!\\ninitialize\\n\\t\\\"Initialize the MIDI parameter constants.\\\"\\n\\t\\\"MidiPrimTester initialize\\\"\\n\\n\\tInstalled _ 1.\\n\\t\\t\\\"Read-only. Return 1 if a MIDI driver is installed, 0 if not.\\n\\t\\t On OMS-based MIDI drivers, this returns 1 only if the OMS\\n\\t\\t system is properly installed and configured.\\\"\\n\\n\\tVersion _ 2.\\n\\t\\t\\\"Read-only. Return the integer version number of this MIDI driver.\\n\\t\\t The version numbering sequence is relative to a particular driver.\\n\\t\\t That is, version 3 of the Macintosh MIDI driver is not necessarily\\n\\t\\t related to version 3 of the Win95 MIDI driver.\\\"\\n\\n\\tHasBuffer _ 3.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver has a time-stamped output\\n\\t\\t buffer, 0 otherwise. Such a buffer allows the client to schedule\\n\\t\\t MIDI output packets to be sent later. This can allow more precise\\n\\t\\t timing, since the driver uses timer interrupts to send the data\\n\\t\\t at the right time even if the processor is in the midst of a\\n\\t\\t long-running Squeak primitive or is running some other application\\n\\t\\t or system task.\\\"\\n\\n\\tHasDurs _ 4.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver supports an extended\\n\\t\\t primitive for note-playing that includes the note duration and\\n\\t\\t schedules both the note-on and the note-off messages in the\\n\\t\\t driver. Otherwise, return 0.\\\"\\n\\n\\tCanSetClock _ 5.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver's clock can be set\\n\\t\\t via an extended primitive, 0 if not.\\\"\\n\\n\\tCanUseSemaphore _ 6.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver can signal a semaphore\\n\\t\\t when MIDI input arrives. Otherwise, return 0. If this driver\\n\\t\\t supports controller caching and it is enabled, then incoming\\n\\t\\t controller messages will not signal the semaphore.\\\"\\n\\n\\tEchoOn _ 7.\\n\\t\\t\\\"Read-write. If this flag is set to a non-zero value, and if\\n\\t\\t the driver supports echoing, then incoming MIDI events will\\n\\t\\t be echoed immediately. If this driver does not support echoing,\\n\\t\\t then queries of this parameter will always return 0 and\\n\\t\\t attempts to change its value will do nothing.\\\"\\n\\n\\tUseControllerCache _ 8.\\n\\t\\t\\\"Read-write. If this flag is set to a non-zero value, and if\\n\\t\\t the driver supports a controller cache, then the driver will\\n\\t\\t maintain a cache of the latest value seen for each MIDI controller,\\n\\t\\t and control update messages will be filtered out of the incoming\\n\\t\\t MIDI stream. An extended MIDI primitive allows the client to\\n\\t\\t poll the driver for the current value of each controller. If\\n\\t\\t this driver does not support a controller cache, then queries\\n\\t\\t of this parameter will always return 0 and attempts to change\\n\\t\\t its value will do nothing.\\\"\\n\\n\\tEventsAvailable _ 9.\\n\\t\\t\\\"Read-only. Return the number of MIDI packets in the input queue.\\\"\\n\\n\\tFlushDriver _ 10.\\n\\t\\t\\\"Write-only. Setting this parameter to any value forces the driver\\n\\t\\t to flush its I/0 buffer, discarding all unprocessed data. Reading\\n\\t\\t this parameter returns 0. Setting this parameter will do nothing\\n\\t\\t if the driver does not support buffer flushing.\\\"\\n\\n\\tClockTicksPerSec _ 11.\\n\\t\\t\\\"Read-only. Return the MIDI clock rate in ticks per second.\\\"\\n\\n\\tHasInputClock _ 12.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver timestamps incoming\\n\\t\\t MIDI data with the current value of the MIDI clock, 0 otherwise.\\n\\t\\t If the driver does not support such timestamping, then the\\n\\t\\t client must read input data frequently and provide its own\\n\\t\\t timestamping.\\\"\\n! !\\nObject subclass: #MimeConverter\\n\\tinstanceVariableNames: 'dataStream mimeStream'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Streams'!\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:55'!\\ndataStream\\n\\t^dataStream! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!\\ndataStream: anObject\\n\\tdataStream _ anObject! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:53'!\\nmimeStream\\n\\t^mimeStream! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!\\nmimeStream: anObject\\n\\tmimeStream _ anObject! !\\n\\n\\n!MimeConverter methodsFor: 'conversion' stamp: 'bf 11/12/1998 13:30'!\\nmimeDecode\\n\\t\\\"Do conversion reading from mimeStream writing to dataStream\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!MimeConverter methodsFor: 'conversion' stamp: 'bf 11/12/1998 13:31'!\\nmimeEncode\\n\\t\\\"Do conversion reading from dataStream writing to mimeStream\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMimeConverter class\\n\\tinstanceVariableNames: ''!\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:47'!\\nforEncoding: encodingString\\n\\t\\\"Answer a converter class for the given encoding or nil if unknown\\\"\\n\\tencodingString ifNil: [^nil].\\n\\t^ encodingString asLowercase caseOf: \\n\\t\\t{ ['base64'] -> [Base64MimeConverter].\\n\\t\\t ['quoted-printable'] -> [QuotedPrintableMimeConverter]}\\n\\t\\totherwise: [].\\n! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:43'!\\nmimeDecode: aStringOrStream as: contentsClass\\n\\t^ contentsClass streamContents: [:out |\\n\\t\\tself mimeDecode: aStringOrStream to: out]! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeDecode: aStringOrStream to: outStream\\n\\tself new\\n\\t\\tmimeStream: (aStringOrStream isStream\\n\\t\\t\\tifTrue: [aStringOrStream]\\n\\t\\t\\tifFalse: [ReadStream on: aStringOrStream]);\\n\\t\\tdataStream: outStream;\\n\\t\\tmimeDecode! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeEncode: aCollectionOrStream\\n\\t^ String streamContents: [:out |\\n\\t\\tself mimeEncode: aCollectionOrStream to: out]! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeEncode: aCollectionOrStream to: outStream\\n\\tself new\\n\\t\\tdataStream: (aCollectionOrStream isStream\\n\\t\\t\\tifTrue: [aCollectionOrStream]\\n\\t\\t\\tifFalse: [ReadStream on: aCollectionOrStream]);\\n\\t\\tmimeStream: outStream;\\n\\t\\tmimeEncode! !\\nPolygonMorph subclass: #MixedCurveMorph\\n\\tinstanceVariableNames: 'slopeClamps'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic-NewCurve'!\\n!MixedCurveMorph commentStamp: '<historical>' prior: 0!\\nA MixedCurveMorph is Curve that can be broken up into separately curved segments. It allows for the creation of matching edges( e. g. for jigsaw puzzle pieces).\\n\\nInstance Variables\\n\\tslopeClamps:\\t\\t<Array>\\n\\nslopeClamps\\n\\t- elements of array are either 0 or nil. Indicating whether slope for the corresponding vertex is 0@0 or unknown and therefore to be calculated. There is one element for each vertex.\\n\\t\\n\\t\\n!\\n\\n\\n!MixedCurveMorph methodsFor: 'access' stamp: 'wiz 2/8/2006 18:59'!\\nclamps\\n\\\" Return a collection of clamps the same size as vertices.\\n\\tIf necessary default to unclamped slopes.\\n\\\"\\n\\nslopeClamps \\n\\tifNil: [ ^ slopeClamps := Array new: vertices size ] .\\nslopeClamps size = vertices size\\n\\tifFalse: [ ^ slopeClamps := Array new: vertices size ] . \\n\\t^ slopeClamps ! !\\n\\n!MixedCurveMorph methodsFor: 'access' stamp: 'wiz 2/8/2006 17:44'!\\nhandleColorAt: vertIndex\\n \\\" clamped handles are cyan and \\n\\tunclamped handles are yellow.\\\"\\n\\n(self clamps at: vertIndex ) ifNil: [ ^ Color yellow ] .\\n^ Color cyan \\n! !\\n\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 17:50'!\\nclickVertex: ix event: evt fromHandle: handle\\n\\\" Toggle the state of the clamp. \\\"\\n\\\"Note: self clamps assures slopeClamps will be same size as vertices\\\"\\n\\n(self clamps at: ix) \\n\\tifNil:\\t [ slopeClamps at: ix put: 0 ]\\n\\tifNotNil: [ slopeClamps at: ix put: nil ] .\\n\\tself setVertices: vertices .\\n\\t\\n! !\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 18:01'!\\ndeleteVertexAt: anIndex\\n\\t\\t\\t(slopeClamps :=\\n\\t\\t\\t\\t\\t\\tslopeClamps\\n\\t\\t\\t\\t\\t\\tcopyReplaceFrom: anIndex\\n\\t\\t\\t\\t\\t\\tto: anIndex\\n\\t\\t\\t\\t\\t\\twith: Array new) .\\n\\t\\t\\tself\\n\\t\\t\\t\\tsetVertices: (vertices\\n\\t\\t\\t\\t\\t\\tcopyReplaceFrom: anIndex\\n\\t\\t\\t\\t\\t\\tto: anIndex\\n\\t\\t\\t\\t\\t\\twith: Array new).\\n\\t\\t\\t\\t\\t\\t! !\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 18:29'!\\ninsertVertexAt: anIndex put: aValue\\n\\t\\\"New vertexs are unclamped.\\\"\\n\\t\\\"Note: order is important. \\n\\tThe clamps array must match vertex size before setVertices: is performed.\\\"\\n\\tslopeClamps := slopeClamps \\n\\t\\tcopyReplaceFrom: anIndex + 1 to: anIndex with: (Array with: nil).\\n\\tself setVertices: (vertices copyReplaceFrom: anIndex + 1 to: anIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twith: (Array with: aValue)).! !\\n\\n\\n!MixedCurveMorph methodsFor: 'initialization' stamp: 'wiz 2/12/2006 05:59'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tself extent: 32@20 .\\n\\n\\tself rectOval.\\n\\tself clamps . \\\"This initializes slopeClamps.\\\"\\n\\tslopeClamps at: 1 put: 0 .\\n\\tslopeClamps at: 4 put: 0 .\\n\\t\\n\\tclosed _ true.\\n\\tsmoothCurve _ true.\\n\\tarrows _ #none.\\n\\tself computeBounds! !\\n\\n\\n!MixedCurveMorph methodsFor: 'smoothing' stamp: 'wiz 2/18/2006 12:53'!\\nslopes: knots \\n\\t\\\"Choose slopes according to state of polygon and preferences\\\"\\n\\tself isCurvy\\n\\t\\tifFalse: [^ knots segmentedSlopes].\\n\\t^ (closed\\n\\t\\t\\tand: [self isCurvier])\\n\\t\\tifTrue: [ knots closedCubicSlopes: self clamps ]\\n\\t\\tifFalse: [knots naturalCubicSlopes: self clamps ]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMixedCurveMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MixedCurveMorph class methodsFor: 'as yet unclassified' stamp: 'wiz 2/12/2006 17:12'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Mixed'\\n\\t\\tcategories:\\t\\t#('Graphics' 'Basic')\\n\\t\\tdocumentation:\\t'A Curve with optional bends and segments. Shift click to get handles.\\n\\t\\t\\tClick handles to change bends. Move handles to move the points.'! !\\nAbstractSound subclass: #MixedSound\\n\\tinstanceVariableNames: 'sounds leftVols rightVols soundDone'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t| dur |\\n\\tdur := 0.\\n\\tsounds do: [:snd | dur := dur max: snd duration].\\n\\t^ dur\\n! !\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'jm 12/16/2001 20:23'!\\nisStereo\\n\\n\\t^ true\\n! !\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'jm 2/4/98 13:37'!\\nsounds\\n\\n\\t^ sounds\\n! !\\n\\n\\n!MixedSound methodsFor: 'composition'!\\n+ aSound\\n\\t\\\"Return the mix of the receiver and the argument sound.\\\"\\n\\n\\t^ self add: aSound\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'jm 1/5/98 13:47'!\\nadd: aSound\\n\\t\\\"Add the given sound with a pan setting of centered and no attenuation.\\\"\\n\\n\\tself add: aSound pan: 0.5 volume: 1.0.\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'jm 1/5/98 13:47'!\\nadd: aSound pan: leftRightPan\\n\\t\\\"Add the given sound with the given left-right panning and no attenuation.\\\"\\n\\n\\tself add: aSound pan: leftRightPan volume: 1.0.\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nadd: aSound pan: leftRightPan volume: volume\\n\\t\\\"Add the given sound with the given left-right pan, where 0.0 is full left, 1.0 is full right, and 0.5 is centered. The loudness of the sound will be scaled by volume, which ranges from 0 to 1.0.\\\"\\n\\n\\t| pan vol |\\n\\tpan := ((leftRightPan * ScaleFactor) asInteger max: 0) min: ScaleFactor.\\n\\tvol := ((volume * ScaleFactor) asInteger max: 0) min: ScaleFactor.\\n\\tsounds := sounds copyWith: aSound.\\n\\tleftVols := leftVols copyWith: ((ScaleFactor - pan) * vol) // ScaleFactor.\\n\\trightVols := rightVols copyWith: (pan * vol) // ScaleFactor.\\n! !\\n\\n\\n!MixedSound methodsFor: 'copying' stamp: 'jm 12/15/97 19:13'!\\ncopy\\n\\t\\\"Copy my component sounds.\\\"\\n\\n\\t^ super copy copySounds\\n! !\\n\\n!MixedSound methodsFor: 'copying' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopySounds\\n\\t\\\"Private!! Support for copying. Copy my component sounds and settings array.\\\"\\n\\n\\tsounds := sounds collect: [:s | s copy].\\n\\tleftVols := leftVols copy.\\n\\trightVols := rightVols copy.\\n! !\\n\\n\\n!MixedSound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tsounds := Array new.\\n\\tleftVols := Array new.\\n\\trightVols := Array new.\\n! !\\n\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'jm 11/25/97 13:40'!\\ndoControl\\n\\n\\tsuper doControl.\\n\\t1 to: sounds size do: [:i | (sounds at: i) doControl].\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol\\n\\t\\\"Play a number of sounds concurrently. The level of each sound can be set independently for the left and right channels.\\\"\\n\\n\\t| snd left right |\\n\\t1 to: sounds size do: [:i |\\n\\t\\t(soundDone at: i) ifFalse: [\\n\\t\\t\\tsnd := sounds at: i.\\n\\t\\t\\tleft := (leftVol * (leftVols at: i)) // ScaleFactor.\\n\\t\\t\\tright := (rightVol * (rightVols at: i)) // ScaleFactor.\\n\\t\\t\\tsnd samplesRemaining > 0\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tsnd mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: left rightVol: right]\\n\\t\\t\\t\\tifFalse: [soundDone at: i put: true]]].\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreset\\n\\n\\tsuper reset.\\n\\tsounds do: [:snd | snd reset].\\n\\tsoundDone := (Array new: sounds size) atAllPut: false.\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplesRemaining\\n\\n\\t| remaining r |\\n\\tremaining := 0.\\n\\t1 to: sounds size do: [:i |\\n\\t\\tr := (sounds at: i) samplesRemaining.\\n\\t\\tr > remaining ifTrue: [remaining := r]].\\n\\n\\t^ remaining\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'jm 1/10/1999 08:45'!\\nstopGracefully\\n\\t\\\"End this note with a graceful decay. If the note has envelopes, determine the decay time from its envelopes.\\\"\\n\\n\\tsuper stopGracefully.\\n\\tsounds do: [:s | s stopGracefully].\\n! !\\nStream subclass: #MockSocketStream\\n\\tinstanceVariableNames: 'atEnd inStream outStream'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'NetworkTests-Kernel'!\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 12:51'!\\natEnd: aBoolean\\n\\tatEnd := aBoolean.! !\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 13:29'!\\ninStream\\n\\t^inStream! !\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 13:08'!\\noutStream\\n\\t^outStream! !\\n\\n\\n!MockSocketStream methodsFor: 'initialize-release' stamp: 'fbs 3/22/2004 13:29'!\\ninitialize\\n\\tself resetInStream.\\n\\tself resetOutStream.! !\\n\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:10'!\\nnextLine\\n\\t^self nextLineCrLf! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:09'!\\nnextLineCrLf\\n\\t^(self upToAll: String crlf).! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:28'!\\nresetInStream\\n\\tinStream := WriteStream on: ''.! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:09'!\\nupToAll: delims\\n\\t^self inStream upToAll: delims.! !\\n\\n\\n!MockSocketStream methodsFor: 'stream out' stamp: 'fbs 3/22/2004 13:28'!\\nresetOutStream\\n\\toutStream := WriteStream on: ''.! !\\n\\n!MockSocketStream methodsFor: 'stream out' stamp: 'fbs 3/22/2004 13:07'!\\nsendCommand: aString\\n\\tself outStream\\n\\t\\tnextPutAll: aString;\\n\\t\\tnextPutAll: String crlf.! !\\n\\n\\n!MockSocketStream methodsFor: 'testing' stamp: 'fbs 3/22/2004 13:08'!\\natEnd\\n\\t^self inStream atEnd.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMockSocketStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MockSocketStream class methodsFor: 'instance creation' stamp: 'fbs 3/22/2004 12:46'!\\non: socket\\n\\t^self basicNew initialize! !\\nController subclass: #ModalController\\n\\tinstanceVariableNames: 'modeActive'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Framework'!\\n!ModalController commentStamp: '<historical>' prior: 0!\\nI am a controller that puts the poor user into a mode by not relinquishing control. However, I do pass control onto my underlings. Some underling is expected to end the mode by sending me 'close'. Watch out Larry Tesler, the mode lives on...\\n!\\n\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:05'!\\nclose\\n\\t\\\"This is how we leave the mode.\\\" \\n\\n\\tmodeActive _ false.\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:02'!\\ncontrolInitialize\\n\\n\\tmodeActive _ true.\\n\\t^ super controlInitialize\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'!\\nisControlActive\\n\\n\\t^ modeActive\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'!\\nisControlWanted\\n\\n\\t^ modeActive\\n! !\\nStandardSystemView subclass: #ModalSystemWindowView\\n\\tinstanceVariableNames: 'modalBorder'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n!ModalSystemWindowView commentStamp: '<historical>' prior: 0!\\nI am a view for a Modal System Window. I vary from StandardSystemView, of which I am a subclass in a few ways:\\n\\n\\t(1) I use ModalController as my default controller;\\n\\t(2) When asked to update with the symbol #close, I direct the controller to close;\\n\\t(3) I display a slightly different title bar with no control boxes.!\\n\\n\\n!ModalSystemWindowView methodsFor: 'controller access' stamp: 'acg 2/9/2000 00:58'!\\ndefaultControllerClass\\n\\n\\t^ModalController! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/18/2000 20:24'!\\ndisplay\\n\\n\\tsuper display.\\n\\tself displayLabelBackground: false.\\n\\tself displayLabelText.\\n! !\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/19/2000 00:59'!\\ndisplayBorder\\n\\t\\\"Display the receiver's border (using the receiver's borderColor).\\\"\\n\\n\\tmodalBorder ifFalse: [^super displayBorder].\\n\\n\\tDisplay\\n\\t\\tborder: self displayBox\\n\\t\\twidthRectangle: (1@1 corner: 2@2)\\n\\t\\trule: Form over\\n\\t\\tfillColor: Color black.\\n\\tDisplay\\n\\t\\tborder: (self displayBox insetBy: (1@1 corner: 2@2))\\n\\t\\twidthRectangle: (4@4 corner: 3@3)\\n\\t\\trule: Form over\\n\\t\\tfillColor: (Color r: 16rEA g: 16rEA b: 16rEA).\\n! !\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/9/2000 07:21'!\\ndisplayLabelBoxes\\n\\t\\\"Modal dialogs don't have closeBox or growBox.\\\"\\n! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/18/2000 20:41'!\\nborderWidth: anObject\\n\\n\\tmodalBorder _ false.\\n\\t^super borderWidth: anObject! !\\n\\n!ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/19/2000 00:50'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\tsuper initialize.\\n\\tself borderWidth: 5.\\n\\tself noLabel.\\n\\tmodalBorder _ true.! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'label access' stamp: 'acg 2/9/2000 08:35'!\\nbackgroundColor\\n\\t^Color lightYellow! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'modal dialog' stamp: 'BG 12/13/2002 11:33'!\\ndoModalDialog\\n\\n\\t| savedArea |\\n\\tself resizeInitially.\\n\\tself resizeTo: \\n\\t\\t((self windowBox)\\n\\t\\t\\talign: self windowBox center\\n\\t\\t\\twith: Display boundingBox aboveCenter).\\n\\tsavedArea _ Form fromDisplay: self windowBox.\\n\\tself displayEmphasized.\\n\\tself controller startUp.\\n\\tself release.\\n\\tsavedArea displayOn: Display at: self windowOrigin.\\n! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'model access' stamp: 'acg 2/9/2000 00:57'!\\nupdate: aSymbol\\n\\taSymbol = #close\\n\\t\\tifTrue: [^self controller close].\\n\\t^super update: aSymbol! !\\nObject subclass: #Model\\n\\tinstanceVariableNames: 'dependents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!Model commentStamp: '<historical>' prior: 0!\\nProvides a superclass for classes that function as models. The only behavior provided is fast dependents maintenance, which bypasses the generic DependentsFields mechanism. 1/23/96 sw!\\n\\n\\n!Model methodsFor: 'copying' stamp: 'tk 10/21/2002 12:59'!\\nveryDeepFixupWith: deepCopier \\n\\t\\\"See if the dependents are being copied also. If so, point at the new copies. (The dependent has self as its model.)\\n\\tDependents handled in class Object, when the model is not a Model, are fixed up in Object veryDeepCopy.\\\"\\n\\n\\t| originalDependents refs newDependent |\\n\\tsuper veryDeepFixupWith: deepCopier.\\n\\toriginalDependents _ dependents.\\n\\toriginalDependents ifNil: [\\n\\t\\t^self.\\n\\t\\t].\\n\\tdependents _ nil.\\n\\trefs _ deepCopier references.\\n\\toriginalDependents\\n\\t\\tdo: [:originalDependent | \\n\\t\\t\\tnewDependent _ refs\\n\\t\\t\\t\\t\\t\\tat: originalDependent\\n\\t\\t\\t\\t\\t\\tifAbsent: [].\\n\\t\\t\\tnewDependent\\n\\t\\t\\t\\tifNotNil: [self addDependent: newDependent]]!\\n]style[(29 206 19 395)f1b,f1,f1LObject veryDeepCopy;,f1! !\\n\\n!Model methodsFor: 'copying' stamp: 'RB 9/20/2001 16:25'!\\nveryDeepInner: deepCopier\\n\\t\\\"Shallow copy dependents and fix them later\\\"\\n! !\\n\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:26'!\\ncanDiscardEdits\\n\\t\\\"Answer true if none of the views on this model has unaccepted edits that matter.\\\"\\n\\n\\tdependents ifNil: [^ true].\\n\\t^ super canDiscardEdits\\n! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sw 2/6/2001 04:13'!\\ncontainingWindow\\n\\t\\\"Answer the window that holds the receiver. The dependents technique is odious and may not be airtight, if multiple windows have the same model.\\\"\\n\\n\\t^ self dependents detect:\\n\\t\\t[:d | ((d isKindOf: SystemWindow orOf: StandardSystemView) or: [d isKindOf: MVCWiWPasteUpMorph]) and: [d model == self]] ifNone: [nil]! !\\n\\n!Model methodsFor: 'dependents' stamp: 'jm 3/24/98 15:12'!\\nhasUnacceptedEdits\\n\\t\\\"Answer true if any of the views on this model has unaccepted edits.\\\"\\n\\n\\tdependents == nil ifTrue: [^ false].\\n\\t^ super hasUnacceptedEdits\\n! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'!\\nmyDependents\\n\\t^ dependents! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'!\\nmyDependents: aCollectionOrNil\\n\\tdependents _ aCollectionOrNil! !\\n\\n!Model methodsFor: 'dependents' stamp: 'gm 2/16/2003 20:37'!\\ntopView\\n\\t\\\"Find the first top view on me. Is there any danger of their being two with the same model? Any danger from ungarbage collected old views? Ask if schedulled?\\\"\\n\\n\\tdependents ifNil: [^nil].\\n\\tSmalltalk isMorphic \\n\\t\\tifTrue: \\n\\t\\t\\t[dependents \\n\\t\\t\\t\\tdo: [:v | ((v isSystemWindow) and: [v isInWorld]) ifTrue: [^v]].\\n\\t\\t\\t^nil].\\n\\tdependents do: [:v | v superView ifNil: [v model == self ifTrue: [^v]]].\\n\\t^nil! !\\n\\n\\n!Model methodsFor: 'keyboard' stamp: 'nk 6/29/2004 14:46'!\\narrowKey: aChar from: view\\n\\t\\\"backstop; all the PluggableList* classes actually handle arrow keys, and the models handle other keys.\\\"\\n\\t^false! !\\n\\n\\n!Model methodsFor: 'menus' stamp: 'di 4/11/98 11:34'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked.\\\" \\n\\n\\t\\\"default is that the editor does all\\\"\\n\\t^ otherTarget perform: selector.! !\\n\\n!Model methodsFor: 'menus' stamp: 'tk 4/17/1998 17:28'!\\nselectedClass\\n\\t\\\"All owners of TextViews are asked this during a doIt\\\"\\n\\t^ nil! !\\n\\n!Model methodsFor: 'menus' stamp: 'zz 3/2/2004 23:49'!\\nstep\\n\\t\\\"Default for morphic models is no-op\\\"! !\\n\\n!Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'!\\ntrash\\n\\t\\\"What should be displayed if a trash pane is restored to initial state\\\"\\n\\n\\t^ ''! !\\n\\n!Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'!\\ntrash: ignored\\n\\t\\\"Whatever the user submits to the trash, it need not be saved.\\\"\\n\\n\\t^ true! !\\n\\n\\n!Model methodsFor: '*services-base' stamp: 'rr 3/21/2006 11:54'!\\nrequestor\\n\\t^ Requestor default! !\\n\\n\\n!Model methodsFor: '*Tools' stamp: 'ar 9/27/2005 20:59'!\\naddItem: classAndMethod\\n\\t\\\"Make a linked message list and put this method in it\\\"\\n\\t| list |\\n\\n\\tself flag: #mref.\\t\\\"classAndMethod is a String\\\"\\n\\n\\tMessageSet \\n\\t\\tparse: classAndMethod \\n\\t\\ttoClassAndSelector: [ :class :sel |\\n\\t\\t\\tclass ifNil: [^self].\\n\\t\\t\\tlist := OrderedCollection with: (\\n\\t\\t\\t\\tMethodReference new\\n\\t\\t\\t\\t\\tsetClass: class \\n\\t\\t\\t\\t\\tmethodSymbol: sel \\n\\t\\t\\t\\t\\tstringVersion: classAndMethod\\n\\t\\t\\t).\\n\\t\\t\\tMessageSet \\n\\t\\t\\t\\topenMessageList: list \\n\\t\\t\\t\\tname: 'Linked by HyperText'.\\n\\t\\t]\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModel class\\n\\tinstanceVariableNames: ''!\\n\\n!Model class methodsFor: 'toolbuilder' stamp: 'ar 2/11/2005 16:26'!\\nbuildWith: toolBuilder\\n\\t^self new buildWith: toolBuilder! !\\nObject subclass: #ModelExtension\\n\\tinstanceVariableNames: 'interests lock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Traits-LocalSends'!\\n\\n!ModelExtension methodsFor: 'access to cache' stamp: 'dvf 9/14/2005 11:27'!\\nhaveInterestsIn: aClass \\n\\tlock critical: [^interests includes: aClass]\\n! !\\n\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/14/2005 11:11'!\\nlostInterest: client inAll: classes\\n\\tlock critical: [interests removeAll: classes]! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/2/2005 11:43'!\\nlostInterest: client in: class\\n\\tself lostInterest: client inAll: {class}! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/14/2005 11:28'!\\nnoteInterestOf: client inAll: classes\\n\\tlock critical: [interests addAll: classes].! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/2/2005 11:44'!\\nnoteInterestOf: client in: class\\n\\tself noteInterestOf: client inAll: {class}! !\\n\\n\\n!ModelExtension methodsFor: 'invalidation' stamp: 'dvf 9/14/2005 11:11'!\\ninitialize\\n\\tlock := Semaphore forMutualExclusion. \\n\\tinterests := IdentityBag new.\\n\\tSystemChangeNotifier uniqueInstance \\n\\t\\tnotify: self\\n\\t\\tofSystemChangesOfItem: #class\\n\\t\\tusing: #classChanged:.\\n\\tSystemChangeNotifier uniqueInstance \\n\\t\\tnotify: self\\n\\t\\tofSystemChangesOfItem: #method\\n\\t\\tusing: #classChanged:.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModelExtension class\\n\\tinstanceVariableNames: 'current'!\\n\\n!ModelExtension class methodsFor: 'accessing' stamp: 'dvf 9/1/2005 21:16'!\\ncurrent\\n\\t^current! !\\n\\n!ModelExtension class methodsFor: 'accessing' stamp: 'dvf 9/1/2005 21:16'!\\ncurrent: anObject\\n\\t^current := anObject! !\\n\\n\\n!ModelExtension class methodsFor: 'initialize-release' stamp: 'dvf 9/2/2005 12:20'!\\ninitialize\\n\\tself isAbstract not ifTrue:\\n\\t\\t[self current: self new]! !\\n\\n!ModelExtension class methodsFor: 'initialize-release' stamp: 'dvf 9/2/2005 12:20'!\\nisAbstract\\n\\t^self == ModelExtension! !\\n\\n\\n!ModelExtension class methodsFor: 'instance creation' stamp: 'dvf 9/1/2005 21:16'!\\ndoWithTemporaryInstance: aBlock \\n\\t| singleton |\\n\\tsingleton := self current.\\n\\t\\n\\t[self current: self new.\\n\\taBlock value] ensure: [self current: singleton]! !\\nModifiedEvent subclass: #ModifiedClassDefinitionEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'!\\nclassVarNames\\n\\t^ item classVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'!\\ninstVarNames\\n\\t^ item instVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'!\\noldClassVarNames\\n\\t^ oldItem classVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'!\\noldInstVarNames\\n\\t^ oldItem instVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'!\\noldSharedPools\\n\\t^ oldItem sharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:28'!\\noldSuperclass\\n\\t^ oldItem superclass! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'!\\nsharedPools\\n\\t^ item sharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:28'!\\nsuperclass\\n\\t^ item superclass! !\\n\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:31'!\\nareClassVarsModified\\n\\t^ self classVarNames ~= self oldClassVarNames! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:30'!\\nareInstVarsModified\\n\\t^ self instVarNames ~= self oldInstVarNames! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:32'!\\nareSharedPoolsModified\\n\\t^ self sharedPools ~= self oldSharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:29'!\\nisSuperclassModified\\n\\t^ item superclass ~~ oldItem superclass! !\\n\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:48'!\\nanyChanges\\n\\t^ self isSuperclassModified or: [self areInstVarsModified or: [self areClassVarsModified or: [self areSharedPoolsModified or: [self isTraitCompositionModified]]]]! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:59'!\\nisTraitCompositionModified\\n\\t^self traitComposition printString ~= self oldTraitComposition printString! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:50'!\\noldTraitComposition\\n\\t^ oldItem traitComposition! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/18/2004 10:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' Super: ';\\n\\t\\tprint: self isSuperclassModified;\\n\\t\\tnextPutAll: ' TraitComposition: ';\\n\\t\\tprint: self isTraitCompositionModified;\\n\\t\\tnextPutAll: ' InstVars: ';\\n\\t\\tprint: self areInstVarsModified;\\n\\t\\tnextPutAll: ' ClassVars: ';\\n\\t\\tprint: self areClassVarsModified;\\n\\t\\tnextPutAll: ' SharedPools: ';\\n\\t\\tprint: self areSharedPoolsModified.! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:50'!\\ntraitComposition\\n\\t^ item traitComposition! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedClassDefinitionEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedClassDefinitionEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:26'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind! !\\n\\n\\n!ModifiedClassDefinitionEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 11:52'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\t| instance |\\n\\tinstance := self item: newClass kind: self classKind.\\n\\tinstance oldItem: oldClass.\\n\\t^instance! !\\nAbstractEvent subclass: #ModifiedEvent\\n\\tinstanceVariableNames: 'oldItem'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedEvent methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:08'!\\noldItem\\n\\t^ oldItem! !\\n\\n\\n!ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 15:10'!\\nprintEventKindOn: aStream\\n\\n\\taStream nextPutAll: 'Modified'! !\\n\\n!ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 17:57'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' oldItem: ';\\n\\t\\tprint: oldItem.! !\\n\\n\\n!ModifiedEvent methodsFor: 'testing' stamp: 'NS 1/19/2004 15:09'!\\nisModified\\n\\n\\t^true! !\\n\\n\\n!ModifiedEvent methodsFor: 'private-accessing' stamp: 'NS 1/19/2004 15:08'!\\noldItem: anItem\\n\\toldItem _ anItem! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:10'!\\nchangeKind\\n\\n\\t^#Modified! !\\n\\n!ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:25'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind with: self methodKind with: self categoryKind with: self protocolKind! !\\n\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 19:37'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\t^ ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass! !\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 11:40'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass\\n\\t| instance |\\n\\tinstance := self method: newMethod selector: aSymbol class: aClass.\\n\\tinstance oldItem: oldMethod.\\n\\t^ instance! !\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 11:40'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\t| instance |\\n\\tinstance := self method: newMethod selector: aSymbol class: aClass requestor: requestor.\\n\\tinstance oldItem: oldMethod.\\n\\t^ instance! !\\nModifiedEvent subclass: #ModifiedTraitDefinitionEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'testing' stamp: 'al 7/18/2004 11:08'!\\nanyChanges\\n\\t^ self isTraitCompositionModified! !\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'testing' stamp: 'al 7/18/2004 10:43'!\\nisTraitCompositionModified\\n\\t^self traitComposition printString ~= self oldTraitComposition printString! !\\n\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\noldTraitComposition\\n\\t^ oldItem traitComposition! !\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\ntraitComposition\\n\\t^ item traitComposition! !\\n\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'printing' stamp: 'al 7/18/2004 10:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' TraitComposition: ';\\n\\t\\tprint: self isTraitCompositionModified! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedTraitDefinitionEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedTraitDefinitionEvent class methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind! !\\n\\n\\n!ModifiedTraitDefinitionEvent class methodsFor: 'instance creation' stamp: 'al 7/18/2004 10:50'!\\ntraitDefinitionChangedFrom: oldTrait to: newTrait\\n\\t| instance |\\n\\tinstance _ self item: newTrait kind: self classKind.\\n\\tinstance oldItem: oldTrait.\\n\\t^instance! !\\nObject subclass: #Monitor\\n\\tinstanceVariableNames: 'mutex ownerProcess nestingLevel defaultQueue queueDict queuesMutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!Monitor commentStamp: 'md 3/3/2006 09:19' prior: 0!\\nA monitor provides process synchronization that is more high level than the one provided by a Semaphore. Similar to the classical definition of a Monitor it has the following properties:\\n\\n1) At any time, only one process can execute code inside a critical section of a monitor.\\n2) A monitor is reentrant, which means that the active process in a monitor never gets blocked when it enters a (nested) critical section of the same monitor.\\n3) Inside a critical section, a process can wait for an event that may be coupled to a certain condition. If the condition is not fulfilled, the process leaves the monitor temporarily (in order to let other processes enter) and waits until another process signals the event. Then, the original process checks the condition again (this is often necessary because the state of the monitor could have changed in the meantime) and continues if it is fulfilled.\\n4) The monitor is fair, which means that the process that is waiting on a signaled condition the longest gets activated first.\\n5) The monitor allows you to define timeouts after which a process gets activated automatically.\\n\\n\\nBasic usage:\\n\\nMonitor>>critical: aBlock\\nCritical section.\\nExecutes aBlock as a critical section. At any time, only one process can execute code in a critical section.\\nNOTE: All the following synchronization operations are only valid inside the critical section of the monitor!!\\n\\nMonitor>>wait\\nUnconditional waiting for the default event.\\nThe current process gets blocked and leaves the monitor, which means that the monitor allows another process to execute critical code. When the default event is signaled, the original process is resumed.\\n\\nMonitor>>waitWhile: aBlock\\nConditional waiting for the default event.\\nThe current process gets blocked and leaves the monitor only if the argument block evaluates to true. This means that another process can enter the monitor. When the default event is signaled, the original process is resumed, which means that the condition (argument block) is checked again. Only if it evaluates to false, does execution proceed. Otherwise, the process gets blocked and leaves the monitor again...\\n\\nMonitor>>waitUntil: aBlock\\nConditional waiting for the default event.\\nSee Monitor>>waitWhile: aBlock.\\n\\nMonitor>>signal\\nOne process waiting for the default event is woken up.\\n\\nMonitor>>signalAll\\nAll processes waiting for the default event are woken up.\\n\\n\\nUsing non-default (specific) events:\\n\\nMonitor>>waitFor: aSymbol\\nUnconditional waiting for the non-default event represented by the argument symbol.\\nSame as Monitor>>wait, but the process gets only reactivated by the specific event and not the default event.\\n\\nMonitor>>waitWhile: aBlock for: aSymbol\\nConfitional waiting for the non-default event represented by the argument symbol.\\nSame as Monitor>>waitWhile:for:, but the process gets only reactivated by the specific event and not the default event.\\n\\nMonitor>>waitUntil: aBlock for: aSymbol\\nConfitional waiting for the non-default event represented by the argument symbol.\\nSee Monitor>>waitWhile:for: aBlock.\\n\\nMonitor>>signal: aSymbol\\nOne process waiting for the given event is woken up. If there is no process waiting for this specific event, a process waiting for the default event gets resumed.\\n\\nMonitor>>signalAll: aSymbol\\nAll process waiting for the given event or the default event are woken up.\\n\\nMonitor>>signalReallyAll\\nAll processes waiting for any events (default or specific) are woken up.\\n\\n\\nUsing timeouts\\n\\nMonitor>>waitMaxMilliseconds: anInteger\\nMonitor>>waitFor: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>wait (resp. Monitor>>waitFor:), but the process gets automatically woken up when the specified time has passed.\\n\\nMonitor>>waitWhile: aBlock maxMilliseconds: anInteger\\nMonitor>>waitWhile: aBlock for: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>waitWhile: (resp. Monitor>>waitWhile:for:), but the process gets automatically woken up when the specified time has passed.\\n\\nMonitor>>waitUntil: aBlock maxMilliseconds: anInteger\\nMonitor>>waitUntil: aBlock for: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>waitUntil: (resp. Monitor>>waitUntil:for:), but the process gets automatically woken up when the specified time has passed.!\\n\\n\\n!Monitor methodsFor: 'accessing' stamp: 'NS 7/1/2002 20:02'!\\ncleanup\\n\\tself checkOwnerProcess.\\n\\tself critical: [self privateCleanup].! !\\n\\n\\n!Monitor methodsFor: 'initialize-release' stamp: 'NS 4/13/2004 16:12'!\\ninitialize\\n\\tmutex _ Semaphore forMutualExclusion.\\n\\tqueuesMutex _ Semaphore forMutualExclusion.\\n\\tnestingLevel _ 0.! !\\n\\n\\n!Monitor methodsFor: 'signaling-default' stamp: 'NS 7/1/2002 21:57'!\\nsignal\\n\\t\\\"One process waiting for the default event is woken up.\\\"\\n\\n\\t^ self signal: nil! !\\n\\n!Monitor methodsFor: 'signaling-default' stamp: 'NS 7/1/2002 21:57'!\\nsignalAll\\n\\t\\\"All processes waiting for the default event are woken up.\\\"\\n\\n\\t^ self signalAll: nil! !\\n\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 4/13/2004 15:12'!\\nsignal: aSymbolOrNil\\n\\t\\\"One process waiting for the given event is woken up. If there is no process waiting \\n\\tfor this specific event, a process waiting for the default event gets resumed.\\\"\\n\\n\\t| queue |\\n\\tself checkOwnerProcess.\\n\\tqueue _ self queueFor: aSymbolOrNil.\\n\\tqueue isEmpty ifTrue: [queue _ self defaultQueue].\\n\\tself signalQueue: queue.! !\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 7/1/2002 22:02'!\\nsignalAll: aSymbolOrNil\\n\\t\\\"All process waiting for the given event or the default event are woken up.\\\"\\n\\n\\t| queue |\\n\\tself checkOwnerProcess.\\n\\tqueue _ self queueFor: aSymbolOrNil.\\n\\tself signalAllInQueue: self defaultQueue.\\n\\tqueue ~~ self defaultQueue ifTrue: [self signalAllInQueue: queue].! !\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 7/1/2002 22:02'!\\nsignalReallyAll\\n\\t\\\"All processes waiting for any events (default or specific) are woken up.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself signalAll.\\n\\tself queueDict valuesDo: [:queue |\\n\\t\\tself signalAllInQueue: queue].! !\\n\\n\\n!Monitor methodsFor: 'synchronization' stamp: 'NS 4/14/2004 13:13'!\\ncritical: aBlock\\n\\t\\\"Critical section.\\n\\tExecutes aBlock as a critical section. At any time, only one process can be executing code \\n\\tin a critical section.\\n\\tNOTE: All the following synchronization operations are only valid inside the critical section \\n\\tof the monitor!!\\\"\\n\\n\\t| result |\\n\\t[self enter.\\n\\tresult _ aBlock value] ensure: [self exit].\\n\\t^ result.! !\\n\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'NS 7/1/2002 21:55'!\\nwait\\n\\t\\\"Unconditional waiting for the default event.\\n\\tThe current process gets blocked and leaves the monitor, which means that the monitor\\n\\tallows another process to execute critical code. When the default event is signaled, the\\n\\toriginal process is resumed.\\\"\\n\\n\\t^ self waitMaxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'NS 7/1/2002 21:56'!\\nwaitUntil: aBlock\\n\\t\\\"Conditional waiting for the default event.\\n\\tSee Monitor>>waitWhile: aBlock.\\\"\\n\\n\\t^ self waitUntil: aBlock for: nil! !\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'fbs 3/24/2004 14:39'!\\nwaitWhile: aBlock\\n\\t\\\"Conditional waiting for the default event.\\n\\tThe current process gets blocked and leaves the monitor only if the argument block\\n\\tevaluates to true. This means that another process can enter the monitor. When the \\n\\tdefault event is signaled, the original process is resumed, which means that the condition\\n\\t(argument block) is checked again. Only if it evaluates to false, does execution proceed.\\n\\tOtherwise, the process gets blocked and leaves the monitor again...\\\"\\n\\n\\t^ self waitWhile: aBlock for: nil! !\\n\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 21:58'!\\nwaitFor: aSymbolOrNil\\n\\t\\\"Unconditional waiting for the non-default event represented by the argument symbol.\\n\\tSame as Monitor>>wait, but the process gets only reactivated by the specific event and \\n\\tnot the default event.\\\"\\n\\n\\t^ self waitFor: aSymbolOrNil maxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 22:01'!\\nwaitUntil: aBlock for: aSymbolOrNil\\n\\t\\\"Confitional waiting for the non-default event represented by the argument symbol.\\n\\tSee Monitor>>waitWhile:for: aBlock.\\\"\\n\\n\\t^ self waitUntil: aBlock for: aSymbolOrNil maxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 22:01'!\\nwaitWhile: aBlock for: aSymbolOrNil\\n\\t\\\"Confitional waiting for the non-default event represented by the argument symbol.\\n\\tSame as Monitor>>waitWhile:for:, but the process gets only reactivated by the specific \\n\\tevent and not the default event.\\\"\\n\\n\\t^ self waitWhile: aBlock for: aSymbolOrNil maxMilliseconds: nil! !\\n\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:03'!\\nwaitFor: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitFor:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself waitInQueue: (self queueFor: aSymbolOrNil) maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:04'!\\nwaitFor: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitFor:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitFor: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:04'!\\nwaitMaxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>wait, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitFor: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitMaxSeconds: aNumber\\n\\t\\\"Same as Monitor>>wait, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitMaxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock for: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitUntil:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: [aBlock value not] for: aSymbolOrNil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock for: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitUntil:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock for: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitUntil:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock for: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitUntil: aBlock maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitUntil:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock for: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitWhile:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself waitWhile: aBlock inQueue: (self queueFor: aSymbolOrNil) maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock for: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitWhile:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock for: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitWhile:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock for: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitWhile:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:40'!\\ncheckOwnerProcess\\n\\tself isOwnerProcess\\n\\t\\tifFalse: [self error: 'Monitor access violation'].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:06'!\\ndefaultQueue\\n\\tdefaultQueue ifNil: [defaultQueue _ OrderedCollection new].\\n\\t^ defaultQueue! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:37'!\\nenter\\n\\tself isOwnerProcess ifTrue: [\\n\\t\\tnestingLevel _ nestingLevel + 1.\\n\\t] ifFalse: [\\n\\t\\tmutex wait.\\n\\t\\townerProcess _ Processor activeProcess.\\n\\t\\tnestingLevel _ 1.\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:38'!\\nexit\\n\\tnestingLevel _ nestingLevel - 1.\\n\\tnestingLevel < 1 ifTrue: [\\n\\t\\townerProcess _ nil.\\n\\t\\tmutex signal\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:32'!\\nexitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\t| lock delay |\\n\\tqueuesMutex \\n\\t\\tcritical: [lock _ anOrderedCollection addLast: Semaphore new].\\n\\tself exit.\\n\\tanIntegerOrNil isNil ifTrue: [\\n\\t\\tlock wait\\n\\t] ifFalse: [\\n\\t\\tdelay _ MonitorDelay signalLock: lock afterMSecs: anIntegerOrNil inMonitor: self queue: anOrderedCollection.\\n\\t\\tlock wait.\\n\\t\\tdelay unschedule.\\n\\t].\\n\\tself enter.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:42'!\\nisOwnerProcess\\n\\t^ Processor activeProcess == ownerProcess! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:14'!\\nprivateCleanup\\n\\tqueuesMutex critical: [\\n\\t\\tdefaultQueue isEmpty ifTrue: [defaultQueue _ nil].\\n\\t\\tqueueDict ifNotNil: [\\n\\t\\t\\tqueueDict copy keysAndValuesDo: [:id :queue | \\n\\t\\t\\t\\tqueue isEmpty ifTrue: [queueDict removeKey: id]].\\n\\t\\t\\tqueueDict isEmpty ifTrue: [queueDict _ nil].\\n\\t\\t].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:10'!\\nqueueDict\\n\\tqueueDict ifNil: [queueDict _ IdentityDictionary new].\\n\\t^ queueDict.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:12'!\\nqueueFor: aSymbol\\n\\taSymbol ifNil: [^ self defaultQueue].\\n\\t^ self queueDict \\n\\t\\tat: aSymbol \\n\\t\\tifAbsent: [self queueDict at: aSymbol put: OrderedCollection new].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:10'!\\nsignalAllInQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\tanOrderedCollection do: [:lock | lock signal].\\n\\t\\tanOrderedCollection removeAllSuchThat: [:each | true].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:34'!\\nsignalLock: aSemaphore inQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\taSemaphore signal.\\n\\t\\tanOrderedCollection remove: aSemaphore ifAbsent: [].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:10'!\\nsignalQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\tanOrderedCollection isEmpty ifTrue: [^ self].\\n\\t\\tanOrderedCollection removeFirst signal.\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 13:17'!\\nwaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\tself exitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 13:17'!\\nwaitWhile: aBlock inQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\t[aBlock value] whileTrue: [self exitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonitor class\\n\\tinstanceVariableNames: ''!\\nDelay subclass: #MonitorDelay\\n\\tinstanceVariableNames: 'monitor queue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!MonitorDelay commentStamp: 'NS 4/13/2004 16:51' prior: 0!\\nThis is a specialization of the class Delay that is used for the implementation of the class Monitor.!\\n\\n\\n!MonitorDelay methodsFor: 'private' stamp: 'NS 4/13/2004 16:26'!\\nsetDelay: anInteger forSemaphore: aSemaphore monitor: aMonitor queue: anOrderedCollection\\n\\tmonitor _ aMonitor.\\n\\tqueue _ anOrderedCollection.\\n\\tself setDelay: anInteger forSemaphore: aSemaphore.! !\\n\\n!MonitorDelay methodsFor: 'private' stamp: 'NS 4/13/2004 16:22'!\\nsignalWaitingProcess\\n\\t\\\"The delay time has elapsed; signal the waiting process.\\\"\\n\\n\\tbeingWaitedOn _ false.\\n\\tmonitor signalLock: delaySemaphore inQueue: queue.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonitorDelay class\\n\\tinstanceVariableNames: ''!\\n\\n!MonitorDelay class methodsFor: 'instance creation' stamp: 'NS 4/13/2004 16:25'!\\nsignalLock: aSemaphore afterMSecs: anInteger inMonitor: aMonitor queue: anOrderedCollection\\n\\tanInteger < 0 ifTrue: [self error: 'delay times cannot be negative'].\\n\\t^ (self new setDelay: anInteger forSemaphore: aSemaphore monitor: aMonitor queue: anOrderedCollection) schedule! !\\nTestCase subclass: #MonitorTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Processes'!\\n\\n!MonitorTest methodsFor: 'examples' stamp: 'md 3/19/2006 21:15'!\\ntestExample1\\n\\n\\t| producer1 producer2 monitor goal work counter goalReached finished |\\n\\tgoal _ (1 to: 1000) asOrderedCollection.\\n\\twork _ OrderedCollection new.\\n\\tcounter := 0.\\n\\tgoalReached := false.\\n\\tfinished := Semaphore new.\\n\\tmonitor := Monitor new.\\n\\n\\tproducer1 := [\\n [monitor critical:\\n [monitor waitUntil: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal\\n ].\\n goalReached\\n ]\\n whileFalse.\\n finished signal.\\n\\t].\\n\\n\\tproducer2 := [\\n [monitor critical:\\n [monitor waitWhile: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal].\\n goalReached\\n ] whileFalse.\\n finished signal\\n\\t].\\n\\n\\tproducer1 forkAt: Processor userBackgroundPriority.\\n\\tproducer2 forkAt: Processor userBackgroundPriority.\\n\\n\\tfinished wait; wait.\\n\\tself assert: goal = work! !\\n\\n!MonitorTest methodsFor: 'examples' stamp: 'md 3/19/2006 21:19'!\\ntestExample2\\n\\t\\\"Here is a second version that does not use a semaphore to inform the \\n\\tforking process about termination of both forked processes\\\"\\n\\n\\t| producer1 producer2 monitor goal work counter goalReached activeProducers|\\n\\tgoal _ (1 to: 1000) asOrderedCollection.\\n\\twork _ OrderedCollection new.\\n\\tcounter := 0.\\n\\tgoalReached := false.\\n\\tactiveProducers := 0.\\n\\tmonitor := Monitor new.\\n\\n producer1 :=\\n [ monitor critical: [activeProducers := activeProducers + 1].\\n [monitor critical:\\n [monitor waitUntil: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n \\\" Transcript show: 'P1 '; show: counter printString; show: ' ';\\n show: activeProducers printString; cr.\\\"\\n goalReached := counter >= goal size.\\n monitor signal\\n ].\\n goalReached\\n ]\\n whileFalse.\\n monitor critical: [activeProducers := activeProducers - 1.\\n monitor signal: #finish].\\n ] .\\n\\n producer2 :=\\n [monitor critical: [activeProducers := activeProducers + 1].\\n\\n [monitor critical:\\n [monitor waitWhile: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal].\\n goalReached ] whileFalse.\\n monitor critical: [\\n\\t\\tactiveProducers := activeProducers - 1. \\n\\t\\tmonitor signal: #finish].\\n\\t].\\n\\n\\tproducer1 forkAt: Processor userBackgroundPriority.\\n\\tproducer2 forkAt: Processor userBackgroundPriority.\\n\\n\\n\\tmonitor critical: [\\n\\t\\tmonitor waitUntil: [activeProducers = 0 & (goalReached)]\\n\\t\\t\\t\\tfor: #finish.\\n \\t].\\n\\n\\tself assert: goal = work\\n! !\\nTimespan subclass: #Month\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'ChronologyConstants'\\n\\tcategory: 'Kernel-Chronology'!\\n!Month commentStamp: 'brp 5/13/2003 09:48' prior: 0!\\nI represent a month.!\\n\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:04'!\\nasMonth\\n\\n\\t^ self\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\ndaysInMonth\\n\\n\\t^ self duration days.! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nindex\\n\\n\\t^ self monthIndex\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nname\\n\\n\\n\\t^ self monthName\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nprevious\\n\\n\\n\\t^ self class starting: (self start - 1)\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nprintOn: aStream\\n\\n\\n\\taStream nextPutAll: self monthName, ' ', self year printString.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonth class\\n\\tinstanceVariableNames: ''!\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:27'!\\ndaysInMonth: indexOrName forYear: yearInteger \\n\\n\\t| index |\\n\\tindex _ indexOrName isInteger \\n\\t\\t\\t\\tifTrue: [indexOrName]\\n\\t\\t\\t\\tifFalse: [self indexOfMonth: indexOrName].\\n\\t^ (DaysInMonth at: index)\\n\\t\\t\\t+ ((index = 2\\n\\t\\t\\t\\t\\tand: [Year isLeapYear: yearInteger])\\n\\t\\t\\t\\t\\t\\tifTrue: [1] ifFalse: [0])! !\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 09:29'!\\nindexOfMonth: aMonthName\\n\\n\\n\\t1 to: 12 do: [ :i | (aMonthName, '*' match: (MonthNames at: i)) ifTrue: [^i] ].\\n\\n\\tself error: aMonthName , ' is not a recognized month name'.! !\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 09:02'!\\nnameOfMonth: anIndex\\n\\n\\t^ MonthNames at: anIndex.! !\\n\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:22'!\\nmonth: month year: year\\n\\t\\\"Create a Month for the given <year> and <month>.\\n\\t<month> may be a number or a String with the\\n\\tname of the month. <year> should be with 4 digits.\\\"\\n\\n\\t^ self starting: (DateAndTime year: year month: month day: 1)\\n! !\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:21'!\\nreadFrom: aStream\\n\\n\\t| m y c |\\n\\n\\tm _ (ReadWriteStream with: '') reset.\\n\\n\\t[(c _ aStream next) isSeparator] whileFalse: [m nextPut: c].\\n\\n\\t[(c _ aStream next) isSeparator] whileTrue.\\n\\n\\ty _ (ReadWriteStream with: '') reset.\\n\\n\\ty nextPut: c.\\n\\n\\t[aStream atEnd] whileFalse: [y nextPut: aStream next].\\n\\n\\n\\t^ self \\n\\t\\tmonth: m contents\\n\\t\\tyear: y contents\\n\\n\\\"Month readFrom: 'July 1998' readStream\\\"\\n! !\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/1/2003 13:59'!\\nstarting: aDateAndTime duration: aDuration \\n\\t\\\"Override - a each month has a defined duration\\\"\\n\\t| start adjusted days |\\n\\tstart _ aDateAndTime asDateAndTime.\\n\\tadjusted _ DateAndTime\\n\\t\\t\\t\\tyear: start year\\n\\t\\t\\t\\tmonth: start month\\n\\t\\t\\t\\tday: 1.\\n\\tdays _ self daysInMonth: adjusted month forYear: adjusted year.\\n\\t^ super\\n\\t\\tstarting: adjusted\\n\\t\\tduration: (Duration days: days)! !\\nClassTestCase subclass: #MonthTest\\n\\tinstanceVariableNames: 'month'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Chronology'!\\n!MonthTest commentStamp: 'brp 7/26/2003 22:44' prior: 0!\\nThis is the unit test for the class Month.\\n!\\n\\n\\n!MonthTest methodsFor: 'Coverage' stamp: 'brp 7/27/2003 12:42'!\\nclassToBeTested\\n\\n\\t^ Month! !\\n\\n!MonthTest methodsFor: 'Coverage' stamp: 'brp 7/26/2003 23:29'!\\nselectorsToBeIgnored\\n\\n\\t| deprecated private special |\\n\\tdeprecated := #().\\n\\tprivate := #( #printOn: ).\\n\\tspecial := #( #next ).\\n\\n\\t^ super selectorsToBeIgnored, deprecated, private, special.! !\\n\\n\\n!MonthTest methodsFor: 'Running' stamp: 'brp 8/6/2003 19:37'!\\nsetUp\\n\\n\\tsuper setUp.\\n\\tmonth _ Month month: 7 year: 1998.! !\\n\\n!MonthTest methodsFor: 'Running' stamp: 'brp 8/6/2003 19:37'!\\ntearDown\\n\\n\\tsuper tearDown.\\n\\tmonth _ nil.! !\\n\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:52'!\\ntestConverting\\n\\n\\tself assert: month asDate = '1 July 1998' asDate! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 1/30/2005 09:35'!\\ntestEnumerating\\n\\t| weeks |\\n\\tweeks := OrderedCollection new.\\n\\tmonth weeksDo: [ :w | weeks add: w start ].\\n\\t0 to: 4 do: [ :i | weeks remove: (Week starting: ('29 June 1998' asDate addDays: i * 7)) start ].\\n\\tself assert: weeks isEmpty! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 8/23/2003 16:08'!\\ntestInquiries\\n\\n\\tself \\n\\t\\tassert: month index = 7;\\n\\t\\tassert: month name = #July;\\n\\t\\tassert: month duration = (31 days).\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'nk 7/30/2004 17:52'!\\ntestInstanceCreation\\n\\t| m1 m2 |\\n\\tm1 := Month starting: '4 July 1998' asDate.\\n\\tm2 := Month month: #July year: 1998.\\n\\tself\\n\\t\\tassert: month = m1;\\n\\t\\tassert: month = m2! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 23:02'!\\ntestPreviousNext\\n\\t| n p |\\n\\tn := month next.\\n\\tp := month previous.\\n\\n\\tself\\n\\t\\tassert: n year = 1998;\\n\\t\\tassert: n index = 8;\\n\\t\\tassert: p year = 1998;\\n\\t\\tassert: p index = 6.\\n\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:50'!\\ntestPrinting\\n\\n\\tself \\n\\t\\tassert: month printString = 'July 1998'.\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:46'!\\ntestReadFrom\\n\\n\\t| m |\\n\\tm := Month readFrom: 'July 1998' readStream.\\n\\tself \\n\\t\\tassert: m = month! !\\nGesturalEvent subclass: #MoodGesturalEvent\\n\\tinstanceVariableNames: 'state'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-Events'!\\n\\n!MoodGesturalEvent methodsFor: 'accessing' stamp: 'len 9/7/1999 02:22'!\\nstate\\n\\t^ state! !\\n\\n!MoodGesturalEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nstate: aSymbol\\n\\tstate := aSymbol asSymbol! !\\n\\n\\n!MoodGesturalEvent methodsFor: 'playing' stamp: 'len 9/7/1999 02:23'!\\nactOn: aHeadMorph\\n\\taHeadMorph face perform: self state! !\\n\\n\\n!MoodGesturalEvent methodsFor: 'printing' stamp: 'len 9/7/1999 02:26'!\\nprintOn: aStream\\n\\taStream nextPutAll: 'set ', self state, ' mood'! !\\nObject subclass: #Morph\\n\\tinstanceVariableNames: 'bounds owner submorphs fullBounds color extension'\\n\\tclassVariableNames: 'EmptyArray'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!Morph commentStamp: 'efc 2/26/2003 20:01' prior: 0!\\nA Morph (from the Greek \\\"shape\\\" or \\\"form\\\") is an interactive graphical object. General information on the Morphic system can be found at http://minnow.cc.gatech.edu/squeak/30. \\n\\nMorphs exist in a tree, rooted at a World (generally a PasteUpMorph). The morphs owned by a morph are its submorphs. Morphs are drawn recursively; if a Morph has no owner it never gets drawn. To hide a Morph and its submorphs, set its #visible property to false using the #visible: method. \\n\\nThe World (screen) coordinate system is used for most coordinates, but can be changed if there is a TransformMorph somewhere in the owner chain. \\n\\nMy instance variables have accessor methods (e.g., #bounds, #bounds:). Most users should use the accessor methods instead of using the instance variables directly.\\n\\nStructure:\\ninstance var \\tType \\t\\t\\tDescription \\nbounds \\t\\t\\tRectangle \\t\\tA Rectangle indicating my position and a size that will enclose \\t\\t\\t\\t\\t\\t\\t\\t\\tme. \\nowner \\t\\t\\tMorph\\t\\t \\tMy parent Morph, or nil for the top-level Morph, which is a\\n \\t\\t\\t\\tor nil\\t\\t\\tworld, typically a PasteUpMorph.\\nsubmorphs \\t\\tArray \\t\\t\\tMy child Morphs. \\nfullBounds \\t\\tRectangle \\t\\tA Rectangle minimally enclosing me and my submorphs. \\ncolor \\t\\t\\tColor \\t\\t\\tMy primary color. Subclasses can use this in different ways. \\nextension \\t\\tMorphExtension Allows extra properties to be stored without adding a\\n\\t\\t\\t\\tor nil \\t\\t\\t\\tstorage burden to all morphs. \\n\\nBy default, Morphs do not position their submorphs. Morphs may position their submorphs directly or use a LayoutPolicy to automatically control their submorph positioning.\\n\\nAlthough Morph has some support for BorderStyle, most users should use BorderedMorph if they want borders.!\\n]style[(2 5 130 37 59 12 325 14 209 12 2 4 4 11 1 11 9 90 5 123 5 35 9 66 5 78 14 209 12 91 11 24 13 22)f1,f1LMorph Hierarchy;,f1,f1Rhttp://minnow.cc.gatech.edu/squeak/30;,f1,f1LPasteUpMorph Comment;,f1,f1LTransformMorph Comment;,f1,f1u,f1,f1u,f1,f1u,f1i,f1,f1LRectangle Comment;,f1,f1LMorph Comment;,f1,f1LArray Comment;,f1,f1LRectangle Comment;,f1,f1LColor Comment;,f1,f1LMorphExtension Comment;,f1,f1LLayoutPolicy Comment;,f1,f1LBorderStyle Comment;,f1,f1LBorderedMorph Comment;,f1!\\n\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/11/1998 16:46'!\\nactorState\\n\\t\\\"This method instantiates actorState as a side-effect.\\n\\tFor simple queries, use actorStateOrNil\\\"\\n\\t| state |\\n\\tstate _ self actorStateOrNil.\\n\\tstate ifNil:\\n\\t\\t[state _ ActorState new initializeFor: self assuredPlayer.\\n\\t\\tself actorState: state].\\n\\t^ state! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:51'!\\nactorStateOrNil\\n\\t\\\"answer the redeiver's actorState\\\"\\n\\t^ extension ifNotNil: [extension actorState]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:52'!\\nactorState: anActorState \\n\\t\\\"change the receiver's actorState\\\"\\n\\tself assureExtension actorState: anActorState! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/18/2001 20:09'!\\nadoptPaneColor: paneColor\\n\\tself submorphsDo:[:m| m adoptPaneColor: paneColor].! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:51'!\\nballoonText\\n\\t\\\"Answer balloon help text or nil, if no help is available. \\n\\tNB: subclasses may override such that they programatically \\n\\tconstruct the text, for economy's sake, such as model phrases in \\n\\ta Viewer\\\"\\n\\n\\t| text balloonSelector aString |\\n\\textension ifNil: [^nil].\\n\\t(text := extension balloonText) ifNotNil: [^text].\\n\\t(balloonSelector := extension balloonTextSelector) ifNotNil: \\n\\t\\t\\t[aString := ScriptingSystem helpStringOrNilFor: balloonSelector.\\n\\t\\t\\t(aString isNil and: [balloonSelector == #methodComment]) \\n\\t\\t\\t\\tifTrue: [aString := self methodCommentAsBalloonHelp].\\n\\t\\t\\t((aString isNil and: [balloonSelector numArgs = 0]) \\n\\t\\t\\t\\tand: [self respondsTo: balloonSelector]) \\n\\t\\t\\t\\t\\tifTrue: [aString := self perform: balloonSelector]].\\n\\t^aString ifNotNil: \\n\\t\\t\\t[aString asString \\n\\t\\t\\t\\twithNoLineLongerThan: Preferences maxBalloonHelpLineLength]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:52'!\\nballoonTextSelector\\n\\t\\\"Answer balloon text selector item in the extension, nil if none\\\"\\n\\t^ extension ifNotNil: [extension balloonTextSelector]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:50'!\\nballoonTextSelector: aSelector \\n\\t\\\"change the receiver's balloonTextSelector\\\"\\n\\tself assureExtension balloonTextSelector: aSelector! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/31/2001 21:06'!\\nbeFlap: aBool\\n\\t\\\"Mark the receiver with the #flap property, or unmark it\\\"\\n\\n\\taBool\\n\\t\\tifTrue:\\n\\t\\t\\t[self setProperty: #flap toValue: true.\\n\\t\\t\\tself hResizing: #rigid.\\n\\t\\t\\tself vResizing: #rigid]\\n\\t\\tifFalse:\\n\\t\\t\\t[self removeProperty: #flap]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:57'!\\nbeSticky\\n\\t\\\"make the receiver sticky\\\"\\n\\tself assureExtension sticky: true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:52'!\\nbeUnsticky\\n\\t\\\"If the receiver is marked as sticky, make it now be unsticky\\\"\\n\\textension ifNotNil: [extension sticky: false]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/25/2001 18:28'!\\nborderColor\\n\\t^self borderStyle color! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/15/2004 10:55'!\\nborderColor: aColorOrSymbolOrNil \\n\\t\\\"Unfortunately, the argument to borderColor could be more than \\tjust a color. \\n\\tIt could also be a symbol, in which case it is to be interpreted as a style identifier.\\n\\tBut I might not be able to draw that kind of border, so it may have to be ignored.\\n\\tOr it could be nil, in which case I should revert to the default border.\\\"\\n\\n\\t| style newStyle |\\n\\tstyle := self borderStyle.\\n\\tstyle baseColor = aColorOrSymbolOrNil\\n\\t\\tifTrue: [^ self].\\n\\n\\taColorOrSymbolOrNil isColor\\n\\t\\tifTrue: [style style = #none \\\"default border?\\\"\\n\\t\\t\\t\\tifTrue: [self borderStyle: (SimpleBorder width: 0 color: aColorOrSymbolOrNil)]\\n\\t\\t\\t\\tifFalse: [style baseColor: aColorOrSymbolOrNil.\\n\\t\\t\\t\\t\\tself changed].\\n\\t\\t\\t^ self].\\n\\n\\tself\\n\\t\\tborderStyle: ( ({ nil. #none } includes: aColorOrSymbolOrNil)\\n\\t\\t\\t\\tifTrue: [BorderStyle default]\\n\\t\\t\\t\\tifFalse: [ \\\"a symbol\\\"\\n\\t\\t\\t\\t\\tself doesBevels ifFalse: [ ^self ].\\n\\t\\t\\t\\t\\tnewStyle := (BorderStyle perform: aColorOrSymbolOrNil)\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: style color;\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: style width;\\n\\t\\t\\t\\t\\t\\t\\t\\tyourself.\\n\\t\\t\\t\\t\\t(self canDrawBorder: newStyle)\\n\\t\\t\\t\\t\\t\\tifTrue: [newStyle]\\n\\t\\t\\t\\t\\t\\tifFalse: [style]])! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 11/26/2001 14:53'!\\nborderStyle\\n\\t^(self valueOfProperty: #borderStyle ifAbsent:[BorderStyle default]) trackColorFrom: self! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/26/2001 16:18'!\\nborderStyleForSymbol: aStyleSymbol\\n\\t\\\"Answer a suitable BorderStyle for me of the type represented by a given symbol\\\"\\n\\n\\t| aStyle existing |\\n\\taStyle _ BorderStyle borderStyleForSymbol: aStyleSymbol asSymbol.\\n\\taStyle ifNil: [self error: 'bad style'].\\n\\texisting _ self borderStyle.\\n\\taStyle width: existing width;\\n\\t\\tbaseColor: existing baseColor.\\n\\t^ (self canDrawBorder: aStyle)\\n\\t\\tifTrue:\\n\\t\\t\\t[aStyle]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/11/2001 22:14'!\\nborderStyle: newStyle\\n\\tnewStyle = self borderStyle ifFalse:[\\n\\t\\t(self canDrawBorder: newStyle) ifFalse:[\\n\\t\\t\\t\\\"Replace the suggested border with a simple one\\\"\\n\\t\\t\\t^self borderStyle: (BorderStyle width: newStyle width color: (newStyle trackColorFrom: self) color)].\\n\\t\\tself setProperty: #borderStyle toValue: newStyle.\\n\\t\\tself changed].! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/25/2001 18:28'!\\nborderWidth\\n\\t^self borderStyle width! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 2/6/2001 14:02'!\\nborderWidthForRounding\\n\\n\\t^ self borderWidth! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/14/2004 17:48'!\\nborderWidth: aNumber\\n\\t| style |\\n\\tstyle _ self borderStyle.\\n\\tstyle width = aNumber ifTrue: [ ^self ].\\n\\n\\tstyle style = #none\\n\\t\\tifTrue: [ self borderStyle: (SimpleBorder width: aNumber color: Color transparent) ]\\n\\t\\tifFalse: [ style width: aNumber. self changed ].\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/1/2004 16:10'!\\nclearArea\\n\\t\\\"Answer the clear area of the receiver. It means the area free \\n\\tof docking bars.\\\"\\n\\t| visTop visBottom visLeft visRight |\\n\\n\\tvisTop := self top.\\n\\tvisBottom := self bottom.\\n\\tvisLeft := self left.\\n\\tvisRight := self right.\\n\\n\\tself dockingBars\\n\\t\\tdo: [:each | \\n\\t\\t\\t(each isAdheringToTop and: [each bottom > visTop])\\n\\t\\t\\t\\tifTrue: [visTop := each bottom].\\n\\n\\t\\t\\t(each isAdheringToBottom and: [each top < visBottom])\\n\\t\\t\\t\\tifTrue: [visBottom := each top].\\n\\n\\t\\t\\t(each isAdheringToLeft and: [each right > visLeft])\\n\\t\\t\\t\\tifTrue: [visLeft := each right].\\n\\n\\t\\t\\t(each isAdheringToRight and: [each left < visRight])\\n\\t\\t\\t\\tifTrue: [visRight := each left]\\n\\t\\t].\\n\\n\\t^ Rectangle\\n\\t\\tleft: visLeft\\n\\t\\tright: visRight\\n\\t\\ttop: visTop\\n\\t\\tbottom: visBottom\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 2/15/2001 15:55'!\\ncolor\\n\\n\\t^ color \\t\\\"has already been set to ((self valueOfProperty: #fillStyle) asColor)\\\"! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/15/2001 22:40'!\\ncolorForInsets\\n\\t\\\"Return the color to be used for shading inset borders. The default is my own color, but it might want to be, eg, my owner's color. Whoever's color ends up prevailing, the color itself gets the last chance to determine, so that when, for example, an InfiniteForm serves as the color, callers won't choke on some non-Color object being returned\\\"\\n\\t(color isColor and:[color isTransparent and:[owner notNil]]) ifTrue:[^owner colorForInsets].\\n\\t^ color colorForInsets\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/6/2001 09:03'!\\ncolor: aColor\\n\\t\\\"Set the receiver's color. Directly set the color if appropriate, else go by way of fillStyle\\\"\\n\\n\\t(aColor isColor or: [aColor isKindOf: InfiniteForm]) ifFalse:[^ self fillStyle: aColor].\\n\\tcolor = aColor ifFalse:\\n\\t\\t[self removeProperty: #fillStyle.\\n\\t\\tcolor _ aColor.\\n\\t\\tself changed]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:14'!\\nconnections\\n\\t\\\"Empty method in absence of connectors\\\"\\n\\t^ #()! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/27/2001 17:56'!\\ncouldHaveRoundedCorners\\n\\t^ true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/15/2004 07:50'!\\ndoesBevels\\n\\t\\\"To return true means that this object can show bevelled borders, and\\n\\ttherefore can accept, eg, #raised or #inset as valid borderColors.\\n\\tMust be overridden by subclasses that do not support bevelled borders.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:53'!\\neventHandler\\n\\t\\\"answer the receiver's eventHandler\\\"\\n\\t^ extension ifNotNil: [extension eventHandler] ! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 19:25'!\\neventHandler: anEventHandler \\n\\t\\\"Note that morphs can share eventHandlers and all is OK. \\\"\\n\\tself assureExtension eventHandler: anEventHandler! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 9/22/2000 13:36'!\\nforwardDirection\\n\\t\\\"Return the receiver's forward direction (in eToy terms)\\\"\\n\\t^self valueOfProperty: #forwardDirection ifAbsent:[0.0]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 1/3/1999 12:25'!\\nhasTranslucentColor\\n\\t\\\"Answer true if this any of this morph is translucent but not transparent.\\\"\\n\\n\\t^ color isColor and: [color isTranslucentColor]\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/30/1998 12:44'!\\nhighlight\\n\\t\\\"The receiver is being asked to appear in a highlighted state. Mostly used for textual morphs\\\"\\n\\tself color: self highlightColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/6/1999 02:09'!\\nhighlightColor\\n\\t\\n\\t| val |\\n\\t^ (val _ self valueOfProperty: #highlightColor)\\n\\t\\tifNotNil:\\n\\t\\t\\t[val ifNil: [self error: 'nil highlightColor']]\\n\\t\\tifNil:\\n\\t\\t\\t[owner ifNil: [self color] ifNotNil: [owner highlightColor]]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 7/2/1998 13:51'!\\nhighlightColor: aColor\\n\\tself setProperty: #highlightColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 1/31/2002 10:25'!\\ninsetColor\\n\\towner ifNil:[^self color].\\n\\t^ self colorForInsets! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 6/13/2001 01:04'!\\nisFlap\\n\\t\\\"Answer whether the receiver claims to be a flap\\\"\\n\\n\\t^ self hasProperty: #flap! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:53'!\\nisLocked\\n\\t\\\"answer whether the receiver is Locked\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension locked! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/27/2000 17:42'!\\nisShared\\n\\t\\\"Answer whether the receiver has the #shared property. This property allows it to be treated as a 'background' item\\\"\\n\\n\\t^ self hasProperty: #shared! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:57'!\\nisSticky\\n\\t\\\"answer whether the receiver is Sticky\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension sticky! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/4/97 12:05'!\\nlock\\n\\tself lock: true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:58'!\\nlock: aBoolean \\n\\t\\\"change the receiver's lock property\\\"\\n\\t(extension isNil and: [aBoolean not]) ifTrue: [^ self].\\n\\tself assureExtension locked: aBoolean! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 6/20/2001 15:45'!\\nmethodCommentAsBalloonHelp\\n\\t\\\"Given that I am a morph that is associated with an object and a method, answer a suitable method comment relating to that object & method if possible\\\"\\n\\n\\t| inherentSelector actual |\\n\\t(inherentSelector _ self valueOfProperty: #inherentSelector)\\n\\t\\tifNotNil:\\n\\t\\t\\t[(actual _ (self ownerThatIsA: PhraseTileMorph orA: SyntaxMorph) actualObject) ifNotNil:\\n\\t\\t\\t\\t[^ actual class precodeCommentOrInheritedCommentFor: inherentSelector]].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/23/1999 22:35'!\\nmodelOrNil\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:54'!\\nplayer\\n\\t\\\"answer the receiver's player\\\"\\n\\t^ extension ifNotNil: [extension player]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:18'!\\nplayerRepresented\\n\\t\\\"Answer the player represented by the receiver. Morphs that serve as references to other morphs reimplement this; be default a morph represents its own player.\\\"\\n\\n\\t^ self player! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:53'!\\nplayer: anObject \\n\\t\\\"change the receiver's player\\\"\\n\\tself assureExtension player: anObject! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/3/1999 13:08'!\\npresenter\\n\\t^ owner ifNotNil: [owner presenter] ifNil: [self currentWorld presenter]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 3/7/2003 15:24'!\\nraisedColor\\n\\t\\\"Return the color to be used for shading raised borders. The \\n\\tdefault is my own color, but it might want to be, eg, my \\n\\towner's color. Whoever's color ends up prevailing, the color \\n\\titself gets the last chance to determine, so that when, for \\n\\texample, an InfiniteForm serves as the color, callers won't choke \\n\\ton some non-Color object being returned\\\"\\n\\t(color isColor\\n\\t\\t\\tand: [color isTransparent\\n\\t\\t\\t\\t\\tand: [owner notNil]])\\n\\t\\tifTrue: [^ owner raisedColor].\\n\\t^ color asColor raisedColor!\\n]style[(11 2 355 3 5 18 5 26 5 24 5 18 5 20)f2b,f2,f2c145043000,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/6/1999 02:09'!\\nregularColor\\n\\t\\n\\t| val |\\n\\t^ (val _ self valueOfProperty: #regularColor)\\n\\t\\tifNotNil:\\n\\t\\t\\t[val ifNil: [self error: 'nil regularColor']]\\n\\t\\tifNil:\\n\\t\\t\\t[owner ifNil: [self color] ifNotNil: [owner regularColor]]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 7/2/1998 13:51'!\\nregularColor: aColor\\n\\tself setProperty: #regularColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/29/2000 14:56'!\\nrememberedColor\\n\\t\\\"Answer a rememberedColor, or nil if none\\\"\\n\\n\\t^ self valueOfProperty: #rememberedColor ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/29/2000 15:47'!\\nrememberedColor: aColor\\n\\t\\\"Place aColor in a property so I can retrieve it later. A tortuous but expedient flow of data\\\"\\n\\n\\t^ self setProperty: #rememberedColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 16:33'!\\nresistsRemoval\\n\\t\\\"Answer whether the receiver is marked as resisting removal\\\"\\n\\n\\t^ self hasProperty: #resistsRemoval! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 16:33'!\\nresistsRemoval: aBoolean\\n\\t\\\"Set the receiver's resistsRemoval property as indicated\\\"\\n\\n\\taBoolean\\n\\t\\tifTrue:\\n\\t\\t\\t[self setProperty: #resistsRemoval toValue: true]\\n\\t\\tifFalse:\\n\\t\\t\\t[self removeProperty: #resistsRemoval]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 9/4/2004 10:49'!\\nscaleFactor\\n\\t^self valueOfProperty: #scaleFactor ifAbsent: [ 1.0 ]\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/26/2001 16:16'!\\nsetBorderStyle: aSymbol\\n\\t\\\"Set the border style of my costume\\\"\\n\\n\\t| aStyle |\\n\\taStyle _ self borderStyleForSymbol: aSymbol.\\n\\taStyle ifNil: [^ self].\\n\\t(self canDrawBorder: aStyle)\\n\\t\\tifTrue:\\n\\t\\t\\t[self borderStyle: aStyle]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 12/4/1998 13:06'!\\nsqkPage\\n\\t^ self valueOfProperty: #SqueakPage! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 08:33'!\\nsticky: aBoolean \\n\\t\\\"change the receiver's sticky property\\\"\\n\\textension sticky: aBoolean! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'RAA 2/19/2001 17:38'!\\ntoggleLocked\\n\\t\\n\\tself lock: self isLocked not! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 12:21'!\\ntoggleResistsRemoval\\n\\t\\\"Toggle the resistsRemoval property\\\"\\n\\n\\tself resistsRemoval\\n\\t\\tifTrue:\\n\\t\\t\\t[self removeProperty: #resistsRemoval]\\n\\t\\tifFalse:\\n\\t\\t\\t[self setProperty: #resistsRemoval toValue: true]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 08:53'!\\ntoggleStickiness\\n\\t\\\"togle the receiver's Stickiness\\\"\\n\\textension ifNil: [^ self beSticky].\\n\\textension sticky: extension sticky not! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/30/1998 12:44'!\\nunHighlight\\n\\tself color: self regularColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 8/11/1998 12:33'!\\nunlock\\n\\tself lock: false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/15/97 23:59'!\\nunlockContents\\n\\tself submorphsDo:\\n\\t\\t[:m | m unlock]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 2/17/1999 11:45'!\\nurl\\n\\t\\\"If I have been assigned a url, return it. For PasteUpMorphs mostly.\\\"\\n\\t| sq |\\n\\t(sq _ self sqkPage) ifNotNil: [^ sq url].\\n\\t^ self valueOfProperty: #url\\n\\t\\t! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 12/16/1998 11:54'!\\nuserString\\n\\t\\\"Do I have a text string to be searched on?\\\"\\n\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/27/2004 11:45'!\\nviewBox\\n\\t^ self pasteUpMorph viewBox! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/1/2004 16:14'!\\nvisibleClearArea\\n\\t\\\"Answer the receiver visible clear area. The intersection \\n\\tbetween the clear area and the viewbox.\\\"\\n\\t^ self viewBox intersect: self clearArea! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:14'!\\nwantsEmbeddingsVocabulary\\n\\t\\\"Empty method in absence of connectors\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 6/23/2001 16:06'!\\nwantsToBeCachedByHand\\n\\t\\\"Return true if the receiver wants to be cached by the hand when it is dragged around.\\n\\tNote: The default implementation queries all submorphs since subclasses may have shapes that do not fill the receiver's bounds completely.\\\"\\n\\tself hasTranslucentColor ifTrue:[^false].\\n\\tself submorphsDo:[:m|\\n\\t\\tm wantsToBeCachedByHand ifFalse:[^false].\\n\\t].\\n\\t^true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 8/31/2004 16:21'!\\nwantsToBeTopmost\\n\\t\\\"Answer if the receiver want to be one of the topmost objects in its owner\\\"\\n\\t^ self isFlapOrTab! !\\n\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:46'!\\nassureExtension\\n\\t\\\"creates an extension for the receiver if needed\\\"\\n\\textension ifNil: [self initializeExtension].\\n\\t^ extension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'dgd 2/16/2003 19:22'!\\nextension\\n\\t\\\"answer the recevier's extension\\\"\\n\\t^ extension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:31'!\\nhasExtension\\n\\t\\\"answer whether the receiver has extention\\\"\\n\\t^ extension notNil! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:35'!\\ninitializeExtension\\n\\t\\\"private - initializes the receiver's extension\\\"\\n\\textension := MorphExtension new! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:46'!\\nprivateExtension: aMorphExtension\\n\\t\\\"private - change the receiver's extension\\\"\\n\\textension := aMorphExtension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:47'!\\nresetExtension\\n\\t\\\"reset the extension slot if it is not needed\\\"\\n\\t(extension notNil and: [extension isDefault]) ifTrue: [extension := nil] ! !\\n\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:47'!\\nhasProperty: aSymbol \\n\\t\\\"Answer whether the receiver has the property named aSymbol\\\"\\n\\textension ifNil: [^ false].\\n\\t^extension hasProperty: aSymbol! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:47'!\\notherProperties\\n\\t\\\"answer the receiver's otherProperties\\\"\\n\\t^ extension ifNotNil: [extension otherProperties]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:48'!\\nremoveProperty: aSymbol \\n\\t\\\"removes the property named aSymbol if it exists\\\"\\n\\textension ifNil: [^ self].\\n\\textension removeProperty: aSymbol! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'tk 10/9/2002 08:30'!\\nsetProperties: aList\\n\\t\\\"Set many properties at once from a list of prop, value, prop, value\\\"\\n\\n\\t1 to: aList size by: 2 do: [:ii |\\n\\t\\tself setProperty: (aList at: ii) toValue: (aList at: ii+1)].! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:48'!\\nsetProperty: aSymbol toValue: anObject \\n\\t\\\"change the receiver's property named aSymbol to anObject\\\"\\n\\tanObject ifNil: [^ self removeProperty: aSymbol].\\n\\tself assureExtension setProperty: aSymbol toValue: anObject! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:53'!\\nvalueOfProperty: aSymbol \\n\\t\\\"answer the value of the receiver's property named aSymbol\\\"\\n\\t^ extension ifNotNil: [extension valueOfProperty: aSymbol]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'dgd 2/16/2003 20:55'!\\nvalueOfProperty: aSymbol ifAbsentPut: aBlock \\n\\t\\\"If the receiver possesses a property of the given name, answer \\n\\tits value. If not, then create a property of the given name, give \\n\\tit the value obtained by evaluating aBlock, then answer that \\n\\tvalue\\\"\\n\\t^ self assureExtension valueOfProperty: aSymbol ifAbsentPut: aBlock! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:50'!\\nvalueOfProperty: aSymbol ifAbsent: aBlock \\n\\t\\\"if the receiver possesses a property of the given name, answer \\n\\tits value. If not then evaluate aBlock and answer the result of \\n\\tthis block evaluation\\\"\\n\\t^ extension \\n\\t\\tifNotNil: [extension valueOfProperty: aSymbol ifAbsent: aBlock]\\n\\t\\tifNil: [aBlock value]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:49'!\\nvalueOfProperty: aSymbol ifPresentDo: aBlock \\n\\t\\\"If the receiver has a property of the given name, evaluate \\n\\taBlock on behalf of the value of that property\\\"\\n\\textension ifNil: [^ self].\\n\\t^ aBlock value: (extension valueOfProperty: aSymbol ifAbsent: [^ self])! !\\n\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:35'!\\nfullLoadCachedState\\n\\t\\\"Load the cached state of the receiver and its full submorph tree.\\\"\\n\\n\\tself allMorphsDo: [:m | m loadCachedState].\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:34'!\\nfullReleaseCachedState\\n\\t\\\"Release the cached state of the receiver and its full submorph tree.\\\"\\n\\n\\tself allMorphsDo: [:m | m releaseCachedState].\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:37'!\\nloadCachedState\\n\\t\\\"Load the cached state of this morph. This method may be called to pre-load the cached state of a morph to avoid delays when it is first used. (Cached state can always be recompued on demand, so a morph should not rely on this method being called.) Implementations of this method should do 'super loadCachedState'. This default implementation does nothing.\\\"\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'md 4/3/2006 12:02'!\\nreleaseCachedState\\n\\t\\\"Release any state that can be recomputed on demand, such as the pixel values for a color gradient or the editor state for a TextMorph. This method may be called to save space when a morph becomes inaccessible. Implementations of this method should do 'super releaseCachedState'.\\\"\\n\\tself borderStyle releaseCachedState. \\n! !\\n\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sd 3/30/2005 22:04'!\\nabstractAModel\\n\\t\\\"Find data-containing fields in me. Make a new class, whose instance variables are named for my fields, and whose values are the values I am showing. Use a CardPlayer for now. Force the user to name the fields. Make slots for text, Number Watchers, SketchMorphs, and ImageMorphs.\\\"\\n\\n\\t| instVarNames unnamed ans player twoListsOfMorphs holdsSepData docks oldPlayer iVarName |\\n\\t(oldPlayer := self player) ifNotNil: \\n\\t\\t\\t[oldPlayer belongsToUniClass \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Player\\\"\\n\\n\\t\\t\\t\\t\\toldPlayer class instVarNames notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[self \\n\\t\\t\\t\\t\\t\\t\\t\\tinform: 'I already have a regular Player, so I can''t have a CardPlayer'.\\n\\t\\t\\t\\t\\t\\t\\t^true]]].\\n\\ttwoListsOfMorphs := StackMorph discoverSlots: self.\\n\\tholdsSepData := twoListsOfMorphs first.\\n\\tinstVarNames := ''.\\n\\tholdsSepData do: \\n\\t\\t\\t[:ea | \\n\\t\\t\\tiVarName := Scanner wellFormedInstanceVariableNameFrom: ea knownName.\\n\\t\\t\\tiVarName = ea knownName ifFalse: [ea name: iVarName].\\n\\t\\t\\tinstVarNames := instVarNames , iVarName , ' '].\\n\\tunnamed := twoListsOfMorphs second.\\t\\\"have default names\\\"\\n\\tinstVarNames isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tinform: 'No named fields were found.\\nPlease get a halo on each field and give it a name.\\nLabels or non-data fields should be named \\\"shared xxx\\\".'.\\n\\t\\t\\t^false].\\n\\tunnamed notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[ans := PopUpMenu \\n\\t\\t\\t\\t\\t\\tconfirm: 'Data fields are ' , instVarNames printString \\n\\t\\t\\t\\t\\t\\t\\t\\t, ('\\\\Some fields are not named. Are they labels or non-data fields?' \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t, '\\\\Please get a halo on each data field and give it a name.') withCRs\\n\\t\\t\\t\\t\\t\\ttrueChoice: 'All other fields are non-data fields'\\n\\t\\t\\t\\t\\t\\tfalseChoice: 'Stop. Let me give a name to some more fields'.\\n\\t\\t\\tans ifFalse: [^false]].\\n\\tunnamed \\n\\t\\twithIndexDo: [:mm :ind | mm setName: 'shared label ' , ind printString].\\n\\t\\\"Make a Player with instVarNames. Make me be the costume\\\"\\n\\tplayer := CardPlayer instanceOfUniqueClassWithInstVarString: instVarNames\\n\\t\\t\\t\\tandClassInstVarString: ''.\\n\\tself player: player.\\n\\tplayer costume: self.\\n\\t\\\"Fill in the instance values. Make docks first.\\\"\\n\\tdocks := OrderedCollection new.\\n\\tholdsSepData do: \\n\\t\\t\\t[:morph | \\n\\t\\t\\tmorph setProperty: #shared toValue: true.\\t\\\"in case it is deeply embedded\\\"\\n\\t\\t\\tmorph setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\t\\t\\tplayer class compileInstVarAccessorsFor: morph knownName.\\n\\t\\t\\tmorph isSyntaxMorph ifTrue: [morph setTarget: player].\\t\\\"hookup the UpdatingString!!\\\"\\n\\t\\t\\tdocks addAll: morph variableDocks].\\n\\tplayer class newVariableDocks: docks.\\n\\tdocks do: [:dd | dd storeMorphDataInInstance: player].\\n\\t\\\"oldPlayer class mdict do: [:assoc | move to player].\\tmove methods to new class?\\\"\\n\\t\\\"oldPlayer become: player.\\\"\\n\\t^true\\t\\\"success\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:31'!\\nbeAStackBackground\\n\\t\\\"Transform the receiver into one that has stack-background behavior. If just becoming a stack, allocate a uniclass to represent the cards (if one does not already exist\\\"\\n\\n\\tself assuredCardPlayer assureUniClass.\\n\\tself setProperty: #tabAmongFields toValue: true.\\n\\tself setProperty: #stackBackground toValue: true.\\n\\t\\\"put my submorphs onto the background\\\"\\n\\tsubmorphs do: [:mm | mm setProperty: #shared toValue: true].\\n\\tself reassessBackgroundShape! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 11/8/2002 14:57'!\\nbecomeSharedBackgroundField\\n\\t\\\"Mark the receiver as holding separate data for each instance (i.e., like a 'background field') and reassess the shape of the corresponding background so that it will be able to accommodate this arrangement.\\\"\\n\\n\\t((self hasProperty: #shared) and: [self hasProperty: #holdsSeparateDataForEachInstance])\\n\\t\\tifFalse: \\n\\t\\t\\t[self setProperty: #shared toValue: true.\\n\\t\\t\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\t\\t\\tself stack reassessBackgroundShape]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 18:54'!\\ncontainsCard: aCard\\n\\t\\\"Answer whether the given card belongs to the uniclass representing the receiver\\\"\\n\\n\\t^ self isStackBackground and: [aCard isKindOf: self player class baseUniclass]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/27/2000 17:36'!\\ncouldHoldSeparateDataForEachInstance\\n\\t\\\"Answer whether this type of morph is inherently capable of holding separate data for each instance ('card data')\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:32'!\\ncurrentDataInstance\\n\\t\\\"Answer the current data instance\\\"\\n\\n\\t^ self player! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:33'!\\nexplainDesignations\\n\\t\\\"Hand the user an object that contains explanations for the designation feedback used\\\"\\n\\n\\tStackMorph designationsExplainer openInHand\\n\\n\\t\\\"self currentWorld explainDesignations\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:49'!\\ngoToNextCardInStack\\n\\t\\\"Tell my stack to advance to the next page\\\"\\n\\n\\tself stackDo: [:aStack | aStack goToNextCardInStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:52'!\\ngoToPreviousCardInStack\\n\\t\\\"Tell my stack to advance to the previous card\\\"\\n\\t\\n\\tself stackDo: [:aStack | aStack goToPreviousCardInStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/27/2000 17:41'!\\nholdsSeparateDataForEachInstance\\n\\t\\\"Answer whether the receiver is currently behaving as a 'background field', i.e., whether it is marked as shared (viz. occurring on the background of a stack) *and* is marked as holding separate data for each instance\\\"\\n\\n\\t^ self isShared and: [self hasProperty: #holdsSeparateDataForEachInstance]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'yo 2/17/2005 17:47'!\\ninsertAsStackBackground\\n\\t\\\"I am not yet in a stack. Find a Stack that my reference point (center) overlaps, and insert me as a new background.\\\"\\n\\n\\t| aMorph |\\n\\tself isStackBackground ifTrue: [^ Beeper beep].\\t\\n\\t\\t\\\"already in a stack. Must clear flags when remove.\\\"\\n\\\"\\tself potentialEmbeddingTargets do: [:mm | No, force user to choose a stack. \\n\\t\\t(mm respondsTo: #insertAsBackground:resize:) ifTrue: [\\n\\t\\t\\t^ mm insertAsBackground: self resize: false]].\\n\\\"\\n\\t\\\"None found, ask user\\\"\\n\\tself inform: 'Please click on a Stack' translated.\\n\\tSensor waitNoButton.\\n\\taMorph _ self world chooseClickTarget.\\n\\taMorph ifNil: [^ self].\\n\\t(aMorph ownerThatIsA: StackMorph) insertAsBackground: self resize: false.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:35'!\\ninsertCard\\n\\t\\\"Insert a new card in the stack, with the receiver as its background, and have it become the current card of the stack\\\"\\n\\n\\tself stackDo: [:aStack | aStack insertCardOfBackground: self]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 11/8/2002 15:16'!\\ninstallAsCurrent: anInstance\\n\\t\\\"Install anInstance as the one currently viewed in the receiver. Dock up all the morphs in the receiver which contain data rooted in the player instance to the instance data. Run any 'opening' scripts that pertain.\\\"\\n\\n\\t| fieldList itsFocus |\\n\\tself player == anInstance ifTrue: [^ self].\\n\\tfieldList _ self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]].\\n\\tself currentWorld hands do:\\n\\t\\t[:aHand | (itsFocus _ aHand keyboardFocus) notNil ifTrue:\\n\\t\\t\\t[(fieldList includes: itsFocus) ifTrue: [aHand newKeyboardFocus: nil]]].\\n\\n\\tself player uninstallFrom: self. \\\"out with the old\\\"\\n\\n\\tanInstance installPrivateMorphsInto: self.\\n\\tself changed.\\n\\tanInstance costume: self.\\n\\tself player: anInstance.\\n\\tself player class variableDocks do:\\n\\t\\t[:aVariableDock | aVariableDock dockMorphUpToInstance: anInstance].\\n\\tself currentWorld startSteppingSubmorphsOf: self! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:42'!\\nisStackBackground\\n\\t\\\"Answer whether the receiver serves as a background of a stack\\\"\\n\\n\\t^ ((owner isKindOf: StackMorph) and: [owner currentPage == self]) or:\\n\\t\\t[self hasProperty: #stackBackground]\\n\\n\\t\\\"This odd property-based check is because when a paste-up-morph is not the *current* background of a stack, it is maddeningly ownerlyess\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:38'!\\nmakeHoldSeparateDataForEachInstance\\n\\t\\\"Mark the receiver as holding separate data for each instance (i.e., like a 'background field') and reassess the shape of the corresponding background so that it will be able to accommodate this arrangement.\\\"\\n\\n\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\tself stack reassessBackgroundShape.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'nb 6/17/2003 12:25'!\\nnewCard\\n\\t\\\"Create a new card for the receiver and return it\\\"\\n\\n\\t| aNewInstance |\\n\\tself isStackBackground ifFalse: [^ Beeper beep]. \\\"bulletproof against deconstruction\\\"\\n\\taNewInstance _ self player class baseUniclass new.\\n\\t^ aNewInstance! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'md 10/22/2003 15:52'!\\nreassessBackgroundShape\\n\\t\\\"A change has been made which may affect the instance structure of the Card uniclass that holds the instance state, which can also be thought of as the 'card data'.\\\"\\n\\n\\t\\\"Caution: still to be done: the mechanism so that when a new instance variable is added, it gets initialized in all subinstances of the receiver's player, which are the cards of this shape. One needs to take into account here the instance variable names coming in; those that are unchanged should keep their values, but those that have newly arrived should obtain their default values from the morphs on whose behalf they are being maintained in the model\\\"\\n\\n\\t| takenNames uniqueName requestedName variableDocks docks sepDataMorphs sorted existing name1 name2 |\\n\\tself isStackBackground ifFalse: [^Beeper beep].\\t\\\"bulletproof against deconstruction\\\"\\n\\tCursor wait showWhile: \\n\\t\\t\\t[variableDocks := OrderedCollection new.\\t\\\"This will be stored in the uniclass's \\n\\t\\t\\tclass-side inst var #variableDocks\\\"\\n\\t\\t\\ttakenNames := OrderedCollection new.\\n\\t\\t\\tsepDataMorphs := OrderedCollection new.\\t\\\"fields, holders of per-card data\\\"\\n\\t\\t\\tself submorphs do: \\n\\t\\t\\t\\t\\t[:aMorph | \\n\\t\\t\\t\\t\\taMorph renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\t\\t\\tifTrue: [sepDataMorphs add: aMorph renderedMorph]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"look for buried fields, inside a frame\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\taMorph renderedMorph isShared \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[aMorph allMorphs do: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:mm | \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmm renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [sepDataMorphs add: mm renderedMorph]]]]].\\n\\t\\t\\tsorted := SortedCollection new \\n\\t\\t\\t\\t\\t\\tsortBlock: [:a :b | (a valueOfProperty: #cardInstance) notNil].\\t\\\"puts existing ones first\\\"\\n\\t\\t\\tsorted addAll: sepDataMorphs.\\n\\t\\t\\tsorted do: \\n\\t\\t\\t\\t\\t[:aMorph | \\n\\t\\t\\t\\t\\tdocks := aMorph variableDocks.\\n\\t\\t\\t\\t\\t\\\"Each morph can request multiple variables. \\n\\tThis complicates matters somewhat but creates a generality for Fabrk-like uses.\\n\\tEach spec is an instance of VariableDock, and it provides a point of departure\\n\\tfor the negotiation between the PasteUp and its constitutent morphs\\\"\\n\\t\\t\\t\\t\\tdocks do: \\n\\t\\t\\t\\t\\t\\t\\t[:aVariableDock | \\n\\t\\t\\t\\t\\t\\t\\tuniqueName := self player \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniqueInstanceVariableNameLike: (requestedName := aVariableDock \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvariableName)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texcluding: takenNames.\\n\\t\\t\\t\\t\\t\\t\\tuniqueName ~= requestedName \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[aVariableDock variableName: uniqueName.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taMorph noteNegotiatedName: uniqueName for: requestedName].\\n\\t\\t\\t\\t\\t\\t\\ttakenNames add: uniqueName].\\n\\t\\t\\t\\t\\tvariableDocks addAll: docks].\\n\\t\\t\\texisting := self player class instVarNames.\\n\\t\\t\\tvariableDocks := (variableDocks asSortedCollection: \\n\\t\\t\\t\\t\\t\\t\\t[:dock1 :dock2 | \\n\\t\\t\\t\\t\\t\\t\\tname1 := dock1 variableName.\\n\\t\\t\\t\\t\\t\\t\\tname2 := dock2 variableName.\\n\\t\\t\\t\\t\\t\\t\\t(existing indexOf: name1 ifAbsent: [0]) \\n\\t\\t\\t\\t\\t\\t\\t\\t< (existing indexOf: name2 ifAbsent: [variableDocks size])]) \\n\\t\\t\\t\\t\\t\\tasOrderedCollection.\\n\\t\\t\\tself player class setNewInstVarNames: (variableDocks \\n\\t\\t\\t\\t\\t\\tcollect: [:info | info variableName asString]).\\n\\t\\t\\t\\\"NB: sets up accessors, and removes obsolete ones\\\"\\n\\t\\t\\tself player class newVariableDocks: variableDocks]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:46'!\\nrelaxGripOnVariableNames\\n\\t\\\"Abandon any memory of specific variable names that should be preserved. The overall situation here is not yet completely understood, and this relaxation is basically always done on each reassessment of the background shape nowadays. But this doesn't feel quite right, because if the user has somehow intervened to specify certain name preference we should perhaps honored it. Or perhaps that is no longer relevant. ????\\\"\\n\\n\\tself submorphs do:\\n\\t\\t[:m | m removeProperty: #variableName.\\n\\t\\tm removeProperty: #setterSelector].\\n\\tself reassessBackgroundShape\\n! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:47'!\\nreshapeBackground\\n\\t\\\"Abandon any memory of variable-name preferences, and reassess the shape of the background\\\"\\n\\n\\tself relaxGripOnVariableNames.\\n\\t\\\"self reassessBackgroundShape.\\talready done there\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/24/2000 06:30'!\\nsetAsDefaultValueForNewCard\\n\\t\\\"Set the receiver's current value as the one to be used to supply the default value for a variable on a new card. This implementation does not support multiple variables per morph, which is problematical\\\"\\n\\n\\tself setProperty: #defaultValue toValue: self currentDataValue deepCopy! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:48'!\\nshowBackgroundObjects\\n\\t\\\"Momentarily highlight just the background objects on the current playfield\\\"\\n\\n\\tself isStackBackground ifFalse: [^ self].\\n\\tself invalidRect: self bounds.\\n\\tself currentWorld doOneCycle.\\n\\tDisplay restoreAfter:\\n\\t\\t[self submorphsDo:\\n\\t\\t\\t[:aMorph | (aMorph renderedMorph hasProperty: #shared)\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[Display border: (aMorph fullBoundsInWorld insetBy: -6) \\n\\t\\t\\t\\t\\t\\t\\twidth: 6 rule: Form over fillColor: Color blue]]]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'aoy 2/15/2003 21:50'!\\nshowDesignationsOfObjects\\n\\t\\\"Momentarily show the designations of objects on the receiver\\\"\\n\\n\\t| colorToUse aLabel |\\n\\tself isStackBackground ifFalse: [^self].\\n\\tself submorphsDo: \\n\\t\\t\\t[:aMorph | \\n\\t\\t\\taLabel :=aMorph renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[colorToUse := Color orange.\\n\\t\\t\\t\\t\\t aMorph externalName]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[colorToUse := aMorph isShared ifFalse: [Color red] ifTrue: [Color green].\\n\\t\\t\\t\\t\\t nil].\\n\\t\\t\\tDisplay \\n\\t\\t\\t\\tborder: (aMorph fullBoundsInWorld insetBy: -6)\\n\\t\\t\\t\\twidth: 6\\n\\t\\t\\t\\trule: Form over\\n\\t\\t\\t\\tfillColor: colorToUse.\\n\\t\\t\\taLabel ifNotNil: \\n\\t\\t\\t\\t\\t[aLabel asString \\n\\t\\t\\t\\t\\t\\tdisplayOn: Display\\n\\t\\t\\t\\t\\t\\tat: aMorph fullBoundsInWorld bottomLeft + (0 @ 5)\\n\\t\\t\\t\\t\\t\\ttextColor: Color blue]].\\n\\tSensor anyButtonPressed \\n\\t\\tifTrue: [Sensor waitNoButton]\\n\\t\\tifFalse: [Sensor waitButton].\\n\\tWorld fullRepaintNeeded! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:50'!\\nshowForegroundObjects\\n\\t\\\"Temporarily highlight the foreground objects\\\"\\n\\n\\tself isStackBackground ifFalse: [^ self].\\n\\tDisplay restoreAfter:\\n\\t\\t[self submorphsDo:\\n\\t\\t\\t[:aMorph | aMorph renderedMorph isShared\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[Display border: (aMorph fullBoundsInWorld insetBy: -6) \\n\\t\\t\\t\\t\\t\\twidth: 6 rule: Form over fillColor: Color orange]]]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:53'!\\nstack\\n\\t\\\"Answer the nearest containing Stack, or, if none, a stack in the current project, and if still none, nil. The extra messiness is because uninstalled backgrounds don't have an owner pointers to their stack.\\\"\\n\\n\\t| aStack bkgnd |\\n\\tbkgnd _ self orOwnerSuchThat: [:oo | oo hasProperty: #myStack].\\n\\tbkgnd ifNotNil: [^ bkgnd valueOfProperty: #myStack].\\n\\n\\t\\\"fallbacks\\\"\\n\\t(aStack _ self ownerThatIsA: StackMorph) ifNotNil: [^ aStack].\\n\\t^ Project current currentStack! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:38'!\\nstackDo: aBlock\\n\\t\\\"If the receiver has a stack, evaluate aBlock on its behalf\\\"\\n\\n\\t| aStack |\\n\\t(aStack _ self ownerThatIsA: StackMorph) ifNotNil:\\n\\t\\t[^ aBlock value: aStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:38'!\\nstopHoldingSeparateDataForEachInstance\\n\\t\\\"Make the receiver no longer hold separate data for each instance\\\"\\n\\n\\tself removeProperty: #holdsSeparateDataForEachInstance.\\n\\tself stack reassessBackgroundShape.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'dgd 8/28/2004 19:15'!\\ntabHitWithEvent: anEvent\\n\\t\\\"The tab key was hit. The keyboard focus has referred this event to me, though this perhaps seems rather backwards. Anyway, the assumption is that I have the property #tabAmongFields, so now the task is to tab to the next field.\\\"\\n\\n\\t| currentFocus fieldList anIndex itemToHighlight variableBearingMorphs otherAmenableMorphs |\\n\\tcurrentFocus _ anEvent hand keyboardFocus.\\n\\tfieldList _ self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]].\\n\\n\\tfieldList isEmpty ifTrue:[^ self].\\n\\n\\tvariableBearingMorphs _ self player isNil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue:[#()]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse:[self player class variableDocks collect: [:vd | vd definingMorph] thenSelect: [:m | m isInWorld]].\\n\\totherAmenableMorphs _ (self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]])\\n\\t\\t\\tcopyWithoutAll: variableBearingMorphs.\\n\\tfieldList _ variableBearingMorphs, otherAmenableMorphs.\\n\\n\\tanIndex _ fieldList indexOf: currentFocus ifAbsent: [nil].\\n\\titemToHighlight _ fieldList atWrap: \\n\\t\\t(anIndex ifNotNil: [anEvent shiftPressed ifTrue: [anIndex - 1] ifFalse: [anIndex + 1]]\\n\\t\\t\\t\\tifNil: [1]).\\n\\tanEvent hand newKeyboardFocus: itemToHighlight. self flag: #arNote. \\\"really???\\\"\\n\\titemToHighlight editor selectAll.\\n\\titemToHighlight invalidRect: itemToHighlight bounds ! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/4/2001 20:57'!\\nwrapWithAStack\\n\\t\\\"Install me as a card inside a new stack. The stack has no border or controls, so I my look is unchanged. If I don't already have a CardPlayer, find my data fields and make one. Be ready to make new cards in the stack that look like me, but hold different field data.\\\"\\n\\n\\tself player class officialClass == CardPlayer ifFalse: [\\n\\t\\tself abstractAModel ifFalse: [^ false]].\\n\\tStackMorph new initializeWith: self.\\n\\tself stack addHalo.\\t\\\"Makes it easier for the user\\\"! !\\n\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 8/12/2003 21:50'!\\naddedMorph: aMorph\\n\\t\\\"Notify the receiver that the given morph was just added.\\\"\\n! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'sw 9/10/1998 08:18'!\\ncolorChangedForSubmorph: aSubmorph\\n\\t\\\"The color associated with aSubmorph was changed through the UI; react if needed\\\"! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 11/12/2000 18:50'!\\ninvalidRect: damageRect\\n\\t^self invalidRect: damageRect from: self! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'md 4/3/2006 11:52'!\\ninvalidRect: aRectangle from: aMorph\\n\\t| damageRect |\\n\\taRectangle hasPositiveExtent ifFalse: [ ^self ].\\n\\tdamageRect _ aRectangle.\\n\\taMorph == self ifFalse:[\\n\\t\\t\\\"Clip to receiver's clipping bounds if the damage came from a child\\\"\\n\\t\\tself clipSubmorphs \\n\\t\\t\\tifTrue:[damageRect _ aRectangle intersect: self clippingBounds]].\\n\\towner ifNotNil: [owner invalidRect: damageRect from: self].! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'sw 7/8/1998 13:21'!\\nownerChanged\\n\\t\\\"The receiver's owner, some kind of a pasteup, has changed its layout.\\\"\\n\\n\\tself snapToEdgeIfAppropriate! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 8/12/2003 22:26'!\\nprivateInvalidateMorph: aMorph\\n\\t\\\"Private. Invalidate the given morph after adding or removing.\\n\\tThis method is private because a) we're invalidating the morph 'remotely'\\n\\tand b) it forces a fullBounds computation which should not be necessary\\n\\tfor a general morph c) the morph may or may not actually invalidate\\n\\tanything (if it's not in the world nothing will happen) and d) the entire\\n\\tmechanism should be rewritten.\\\"\\n\\taMorph fullBounds.\\n\\taMorph changed! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'tk 8/24/2001 22:07'!\\nuserSelectedColor: aColor\\n\\t\\\"The user, via the UI, chose aColor to be the color for the receiver; set it, and tell my owner in case he wishes to react\\\"\\n\\tself color: aColor.\\n\\tself world ifNotNil: [owner colorChangedForSubmorph: self]! !\\n\\n\\n!Morph methodsFor: 'classification' stamp: 'sw 2/26/2002 23:29'!\\ndemandsBoolean\\n\\t\\\"Answer whether the receiver will only accept a drop if it is boolean-valued. Particular to tile-scripting.\\\"\\n\\n\\t^ self hasProperty: #demandsBoolean! !\\n\\n!Morph methodsFor: 'classification' stamp: 'di 5/7/1998 01:21'!\\nisAlignmentMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/15/2000 17:56'!\\nisBalloonHelp\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/28/2000 13:54'!\\nisFlapOrTab\\n\\t^self isFlap or:[self isFlapTab]! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/28/2000 13:53'!\\nisFlapTab\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'jm 4/17/1998 00:44'!\\nisFlexMorph\\n\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'classification'!\\nisHandMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 10/3/2000 18:11'!\\nisModalShell\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'sw 1/29/98 21:51'!\\nisPlayfieldLike\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'jm 5/7/1998 13:45'!\\nisRenderer\\n\\t\\\"A *renderer* morph transforms the appearance of its submorph in some manner. For example, it might supply a drop shadow or scale and rotate the morph it encases. Answer true if this morph acts as a renderer. This default implementation returns false.\\\"\\n\\t\\\"Details: A renderer is assumed to have a single submorph. Renderers may be nested to concatenate their transformations. It is useful to be able to find the outer-most renderer. This can be done by ascending the owner chain from the rendered morph. To find the morph being rendered, one can descend through the (singleton) submorph lists of the renderer chain until a non-renderer is encountered.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 6/30/2001 13:13'!\\nisStandardViewer\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'di 11/2/2000 13:24'!\\nisSyntaxMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 12/16/2001 18:28'!\\nisTextMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification'!\\nisWorldMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification'!\\nisWorldOrHandMorph\\n\\n\\t^ self isWorldMorph or: [self isHandMorph]! !\\n\\n\\n!Morph methodsFor: 'connectors-scripting' stamp: 'nk 9/10/2004 11:37'!\\nwantsConnectorVocabulary\\n\\t\\\"Answer true if I want to show a 'connector' vocabulary\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'converting'!\\nasDraggableMorph\\n\\t^self! !\\n\\n!Morph methodsFor: 'converting' stamp: 'wiz 2/19/2006 19:01'!\\nasSnapshotThumbnail\\n\\t^(ThumbnailImageMorph new newImage: self imageForm ) extent: 90 asPoint .! !\\n\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/19/2001 18:21'!\\ncopy\\n\\n\\t^ self veryDeepCopy! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/14/2001 12:47'!\\ndeepCopy\\n\\n\\tself error: 'Please use veryDeepCopy'.\\n! !\\n\\n!Morph methodsFor: 'copying' stamp: 'sw 4/19/2005 17:02'!\\nduplicate\\n\\t\\\"Make and return a duplicate of the receiver\\\"\\n\\n\\t| newMorph aName w aPlayer topRend |\\n\\t((topRend _ self topRendererOrSelf) ~~ self) ifTrue: [^ topRend duplicate].\\n\\n\\tself okayToDuplicate ifFalse: [^ self].\\n\\taName _ (w _ self world) ifNotNil:\\n\\t\\t[w nameForCopyIfAlreadyNamed: self].\\n\\tnewMorph _ self veryDeepCopy.\\n\\taName ifNotNil: [newMorph setNameTo: aName].\\n\\n\\tnewMorph arrangeToStartStepping.\\n\\tnewMorph privateOwner: nil. \\\"no longer in world\\\"\\n\\tnewMorph isPartsDonor: false. \\\"no longer parts donor\\\"\\n\\t(aPlayer _ newMorph player) belongsToUniClass ifTrue:\\n\\t\\t[aPlayer class bringScriptsUpToDate].\\n\\taPlayer ifNotNil: [ActiveWorld presenter flushPlayerListCache].\\n\\t^ newMorph! !\\n\\n!Morph methodsFor: 'copying' stamp: 'nk 3/12/2001 17:07'!\\nduplicateMorphCollection: aCollection\\n\\t\\\"Make and return a duplicate of the receiver\\\"\\n\\n\\t| newCollection names |\\n\\n\\tnames _ aCollection collect: [ :ea | | newMorph w |\\n\\t\\t(w _ ea world) ifNotNil:\\n\\t\\t\\t[w nameForCopyIfAlreadyNamed: ea].\\n\\t].\\n\\n\\tnewCollection _ aCollection veryDeepCopy.\\n\\n\\tnewCollection with: names do: [ :newMorph :name |\\n\\t\\tname ifNotNil: [ newMorph setNameTo: name ].\\n\\t\\tnewMorph arrangeToStartStepping.\\n\\t\\tnewMorph privateOwner: nil. \\\"no longer in world\\\"\\n\\t\\tnewMorph isPartsDonor: false. \\\"no longer parts donor\\\"\\n\\t].\\n\\n\\t^newCollection! !\\n\\n!Morph methodsFor: 'copying' stamp: 'sw 2/16/2001 16:30'!\\nfullCopy\\n\\t\\\"Deprecated, but maintained for backward compatibility with existing code (no senders in the base 3.0 image). Calls are revectored to #veryDeepCopy, but note that #veryDeepCopy does not do exactly the same thing that the original #fullCopy did, so beware!!\\\"\\n\\n\\t^ self veryDeepCopy! !\\n\\n!Morph methodsFor: 'copying' stamp: 'md 2/27/2006 08:53'!\\nupdateReferencesUsing: aDictionary \\n\\t\\\"Update intra-morph references within a composite morph that \\n\\thas been copied. For example, if a button refers to morph X in \\n\\tthe orginal \\n\\tcomposite then the copy of that button in the new composite \\n\\tshould refer to \\n\\tthe copy of X in new composite, not the original X. This default \\n\\timplementation updates the contents of any morph-bearing slot. \\n\\tIt may be \\n\\toverridden to avoid this behavior if so desired.\\\"\\n\\t| old |\\n\\tMorph instSize + 1\\n\\t\\tto: self class instSize\\n\\t\\tdo: [:i | \\n\\t\\t\\told _ self instVarAt: i.\\n\\t\\t\\told isMorph\\n\\t\\t\\t\\tifTrue: [self\\n\\t\\t\\t\\t\\t\\tinstVarAt: i\\n\\t\\t\\t\\t\\t\\tput: (aDictionary\\n\\t\\t\\t\\t\\t\\t\\t\\tat: old\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsent: [old])]].\\n\\textension ifNotNil: [extension updateReferencesUsing: aDictionary]! !\\n\\n!Morph methodsFor: 'copying' stamp: 'nk 10/11/2003 16:59'!\\nusableSiblingInstance\\n\\t\\\"Return another similar morph whose Player is of the same class as mine.\\n\\tDo not open it in the world.\\\"\\n\\n\\t| aName usedNames newPlayer newMorph topRenderer |\\n\\t(topRenderer := self topRendererOrSelf) == self \\n\\t\\tifFalse: [^topRenderer usableSiblingInstance].\\n\\tself assuredPlayer assureUniClass.\\n\\tnewMorph := self veryDeepCopySibling.\\n\\tnewPlayer := newMorph player.\\n\\tnewPlayer resetCostumeList.\\n\\t(aName := self knownName) isNil \\n\\t\\tifTrue: [self player notNil ifTrue: [aName := newMorph innocuousName]].\\n\\t\\\"Force a difference here\\\"\\n\\taName notNil \\n\\t\\tifTrue: \\n\\t\\t\\t[usedNames := (self world ifNil: [OrderedCollection new]\\n\\t\\t\\t\\t\\t\\tifNotNil: [self world allKnownNames]) copyWith: aName.\\n\\t\\t\\tnewMorph setNameTo: (Utilities keyLike: aName\\n\\t\\t\\t\\t\\t\\tsatisfying: [:f | (usedNames includes: f) not])].\\n\\tnewMorph privateOwner: nil.\\n\\tnewPlayer assureEventHandlerRepresentsStatus.\\n\\tself presenter flushPlayerListCache.\\n\\t^newMorph! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 1/6/1999 17:27'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. See veryDeepInner:, veryDeepFixupWith:\\\"\\n\\n\\tself prepareToBeSaved.\\n\\t^ super veryDeepCopyWith: deepCopier! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/3/2001 14:29'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If some fields were weakly copied, fix new copy here.\\\"\\n\\n\\t\\\"super veryDeepFixupWith: deepCopier.\\tObject has no fixups, so don't call it\\\"\\n\\n\\t\\\"If my owner is being duplicated too, then store his duplicate.\\n\\t If I am owned outside the duplicated tree, then I am no longer owned!!\\\"\\n\\towner _ deepCopier references at: owner ifAbsent: [nil].\\n\\n! !\\n\\n!Morph methodsFor: 'copying' stamp: 'md 2/27/2006 08:47'!\\nveryDeepInner: deepCopier \\n\\t\\\"The inner loop, so it can be overridden when a field should not \\n\\tbe traced.\\\"\\n\\t\\\"super veryDeepInner: deepCopier.\\tknow Object has no inst vars\\\"\\n\\tbounds _ bounds clone.\\n\\t\\\"Points are shared with original\\\"\\n\\t\\\"owner _ owner.\\tspecial, see veryDeepFixupWith:\\\"\\n\\tsubmorphs _ submorphs veryDeepCopyWith: deepCopier.\\n\\t\\\"each submorph's fixup will install me as the owner\\\"\\n\\t\\\"fullBounds _ fullBounds.\\tfullBounds is shared with original!!\\\"\\n\\tcolor _ color veryDeepCopyWith: deepCopier.\\n\\t\\\"color, if simple, will return self. may be complex\\\"\\n\\textension := (extension veryDeepCopyWith: deepCopier)! !\\n\\n\\n!Morph methodsFor: 'creation' stamp: 'tk 2/6/1999 22:43'!\\nasMorph\\n\\t^ self! !\\n\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 8/30/2003 20:36'!\\naddDebuggingItemsTo: aMenu hand: aHandMorph\\n\\taMenu add: 'debug...' translated subMenu: (self buildDebugMenu: aHandMorph)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 1/19/2001 07:51'!\\naddMouseActionIndicatorsWidth: anInteger color: aColor\\n\\n\\tself deleteAnyMouseActionIndicators.\\n\\n\\tself changed.\\n\\tself hasRolloverBorder: true.\\n\\tself setProperty: #rolloverWidth toValue: anInteger@anInteger.\\n\\tself setProperty: #rolloverColor toValue: aColor.\\n\\tself layoutChanged.\\n\\tself changed.\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 4/25/2004 14:23'!\\naddMouseUpAction\\n\\t| codeToRun oldCode |\\n\\toldCode := self\\n\\t\\t\\t\\tvalueOfProperty: #mouseUpCodeToRun\\n\\t\\t\\t\\tifAbsent: [''].\\n\\tcodeToRun := FillInTheBlank request: 'MouseUp expression:' translated initialAnswer: oldCode.\\n\\tself addMouseUpActionWith: codeToRun! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 2/22/2003 13:41'!\\naddMouseUpActionWith: codeToRun \\n\\t((codeToRun isMessageSend) not and: [codeToRun isEmptyOrNil]) \\n\\t\\tifTrue: [^self].\\n\\tself setProperty: #mouseUpCodeToRun toValue: codeToRun.\\n\\tself \\n\\t\\ton: #mouseUp\\n\\t\\tsend: #programmedMouseUp:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseDown\\n\\t\\tsend: #programmedMouseDown:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseEnter\\n\\t\\tsend: #programmedMouseEnter:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseLeave\\n\\t\\tsend: #programmedMouseLeave:for:\\n\\t\\tto: self! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 1/3/2001 06:42'!\\naddViewingItemsTo: aMenu\\n\\t\\\"Add viewing-related items to the given menu. If any are added, this method is also responsible for adding a line after them\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 2/22/2003 14:27'!\\nallStringsAfter: aSubmorph \\n\\t\\\"return an OrderedCollection of strings of text in my submorphs. If aSubmorph is non-nil, begin with that container.\\\"\\n\\n\\t| list string ok |\\n\\tlist := OrderedCollection new.\\n\\tok := aSubmorph isNil.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:sub | \\n\\t\\t\\tok ifFalse: [ok := sub == aSubmorph].\\t\\\"and do this one too\\\"\\n\\t\\t\\tok \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[(string := sub userString) ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[string isString ifTrue: [list add: string] ifFalse: [list addAll: string]]]].\\n\\t^list! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:27'!\\naltSpecialCursor0\\n\\t\\\"an arrow\\\"\\n\\t^(Form\\n\\textent: 16@16\\n\\tdepth: 8\\n\\tfromArray: #( 0 0 0 0 14869218 3806520034 3806520034 3791650816 14848144 2425393296 2425393378 0 14848144 2425393296 2425414144 0 14848144 2425393296 2430730240 0 14848144 2425393296 3791650816 0 14848144 2425393378 3791650816 0 14848144 2425414370 3806461952 0 14848144 2430788322 3806519808 0 14848144 3791651042 3806520034 0 14848226 0 3806520034 3791650816 14868992 0 14869218 3806461952 14811136 0 58082 3806519808 0 0 226 3806520034 0 0 0 3806520034 0 0 0 14869218)\\n\\toffset: 0@0)\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:28'!\\naltSpecialCursor1\\n\\t\\\"a star and an arrow\\\"\\n\\t^(Form\\n\\textent: 31@26\\n\\tdepth: 8\\n\\tfromArray: #( 14417920 0 0 0 0 0 0 0 3705461980 3705461980 3705405440 0 0 0 0 0 3705461980 3705461980 3705461760 0 0 0 0 0 14474460 3705461980 3705405440 0 0 0 0 0 56540 3705461980 3690987520 0 0 3690987520 0 0 220 3705461980 3705461760 0 0 3690987520 0 0 220 3705405440 3705461980 0 0 3705405440 0 0 0 3705461760 56540 3690987520 220 3705405440 0 0 0 3705405440 220 3705461760 220 3705405440 0 0 0 0 0 14474460 220 3705461760 0 0 0 0 0 56540 3691044060 3705461760 0 0 0 0 0 220 3705461980 3705461760 0 0 0 0 56540 3705461980 3705461980 3705461980 3705461980 3705461760 0 0 220 3705461980 3705461980 3705461980 3705461980 3705461760 0 0 0 3705461980 3705461980 3705461980 3705461980 3705405440 0 0 0 14474460 3705461980 3705461980 3705461980 3690987520 0 0 0 56540 3705461980 3705461980 3705461760 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 0 3705461980 3705461980 3690987520 0 0 0 0 0 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 14474460 3705405440 0 0 0 0 220 3705405440 220 3705461760 0 0 0 0 56540 3690987520 0 3705461760 0 0 0 0 56540 0 0 14474240 0)\\n\\toffset: 0@0)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:41'!\\naltSpecialCursor2\\n\\t| f |\\n\\t\\\"a blue box with transparent center\\\"\\n\\tf _ Form extent: 32@32 depth: 32.\\n\\tf offset: (f extent // 2) negated.\\n\\tf fill: f boundingBox rule: Form over fillColor: (Color blue alpha: 0.5).\\n\\tf fill: (f boundingBox insetBy: 4) rule: Form over fillColor: Color transparent.\\n\\t^f\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:42'!\\naltSpecialCursor3\\n\\t\\n\\t^self altSpecialCursor3: Color blue! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:41'!\\naltSpecialCursor3: aColor\\n\\t| f box |\\n\\t\\\"a bulls-eye pattern in this color\\\"\\n\\tf _ Form extent: 32@32 depth: 32.\\n\\tf offset: (f extent // 2) negated.\\n\\tbox _ f boundingBox.\\n\\t[ box width > 0] whileTrue: [\\n\\t\\tf fill: box rule: Form over fillColor: aColor.\\n\\t\\tf fill: (box insetBy: 2) rule: Form over fillColor: Color transparent.\\n\\t\\tbox _ box insetBy: 4.\\n\\t].\\n\\t^f\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'nk 6/14/2004 16:14'!\\nbuildDebugMenu: aHand\\n\\t\\\"Answer a debugging menu for the receiver. The hand argument is seemingly historical and plays no role presently\\\"\\n\\n\\t| aMenu aPlayer |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\t(self hasProperty: #errorOnDraw) ifTrue:\\n\\t\\t[aMenu add: 'start drawing again' translated action: #resumeAfterDrawError.\\n\\t\\taMenu addLine].\\n\\t(self hasProperty: #errorOnStep) ifTrue:\\n\\t\\t[aMenu add: 'start stepping again' translated action: #resumeAfterStepError.\\n\\t\\taMenu addLine].\\n\\n\\taMenu add: 'inspect morph' translated action: #inspectInMorphic:.\\n\\taMenu add: 'inspect owner chain' translated action: #inspectOwnerChain.\\n\\tSmalltalk isMorphic ifFalse:\\n\\t\\t[aMenu add: 'inspect morph (in MVC)' translated action: #inspect].\\n\\n\\tself isMorphicModel ifTrue:\\n\\t\\t[aMenu add: 'inspect model' translated target: self model action: #inspect].\\n\\t(aPlayer _ self player) ifNotNil:\\n\\t\\t[aMenu add: 'inspect player' translated target: aPlayer action: #inspect].\\n\\n aMenu add: 'explore morph' translated target: self selector: #explore.\\n\\n\\taMenu addLine.\\n\\taPlayer ifNotNil:\\n\\t\\t[ aMenu add: 'viewer for Player' translated target: self player action: #beViewed.\\n\\taMenu balloonTextForLastItem: 'Opens a viewer on my Player -- this is the same thing you get if you click on the cyan \\\"View\\\" halo handle' translated ].\\n\\n\\taMenu add: 'viewer for Morph' translated target: self action: #viewMorphDirectly.\\n\\taMenu balloonTextForLastItem: 'Opens a Viewer on this Morph, rather than on its Player' translated.\\n\\taMenu addLine.\\n\\n\\taPlayer ifNotNil:\\n\\t\\t[aPlayer class isUniClass ifTrue: [\\n\\t\\t\\taMenu add: 'browse player class' translated target: aPlayer action: #browseHierarchy]].\\n\\taMenu add: 'browse morph class' translated target: self selector: #browseHierarchy.\\n\\t(self isMorphicModel)\\n\\t\\tifTrue: [aMenu\\n\\t\\t\\t\\tadd: 'browse model class'\\n\\t\\t\\t\\ttarget: self model\\n\\t\\t\\t\\tselector: #browseHierarchy].\\n\\taMenu addLine.\\n\\n\\taPlayer ifNotNil:\\n\\t\\t[aMenu add: 'player protocol (tiles)' translated target: aPlayer action: #openInstanceBrowserWithTiles\\n\\t\\t\\t\\\"#browseProtocolForPlayer\\\"].\\n\\taMenu add: 'morph protocol (text)' translated target: self selector: #haveFullProtocolBrowsed.\\n\\taMenu add: 'morph protocol (tiles)' translated target: self selector: #openInstanceBrowserWithTiles.\\n\\taMenu addLine.\\n\\n\\tself addViewingItemsTo: aMenu.\\n\\taMenu \\n\\t\\tadd: 'make own subclass' translated action: #subclassMorph;\\n\\t\\tadd: 'internal name ' translated action: #choosePartName;\\n\\t\\tadd: 'save morph in file' translated action: #saveOnFile;\\n\\t\\taddLine;\\n\\t\\tadd: 'call #tempCommand' translated action: #tempCommand;\\n\\t\\tadd: 'define #tempCommand' translated action: #defineTempCommand;\\n\\t\\taddLine;\\n\\n\\t\\tadd: 'control-menu...' translated target: self selector: #invokeMetaMenu:;\\n\\t\\tadd: 'edit balloon help' translated action: #editBalloonHelpText.\\n\\n\\t^ aMenu! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'ar 9/27/2005 20:29'!\\ndefineTempCommand\\n\\t\\\"To use this, comment out what's below here, and substitute your own code.\\nYou will then be able to invoke it from the standard debugging menus. If invoked from the world menu, you'll always get it invoked on behalf of the world, but if invoked from an individual morph's meta-menu, it will be invoked on behalf of that individual morph.\\n\\nNote that you can indeed reimplement tempCommand in an individual morph's class if you wish\\\"\\n\\n\\tToolSet browse: Morph\\n\\t\\tselector: #tempCommand! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 1/19/2001 07:51'!\\ndeleteAnyMouseActionIndicators\\n\\n\\tself changed.\\n\\t(self valueOfProperty: #mouseActionIndicatorMorphs ifAbsent: [#()]) do: [ :each |\\n\\t\\teach deleteWithSiblings\\t\\t\\\"one is probably enough, but be safe\\\"\\n\\t].\\n\\tself removeProperty: #mouseActionIndicatorMorphs.\\n\\tself hasRolloverBorder: false.\\n\\tself removeProperty: #rolloverWidth.\\n\\tself removeProperty: #rolloverColor.\\n\\tself layoutChanged.\\n\\tself changed.\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 7/17/2001 19:08'!\\nhandMeTilesToFire \\n\\t\\\"Construct a phrase of tiles comprising a line of code that will 'fire' this object, and hand it to the user\\\"\\n\\n\\tActiveHand attachMorph: (self assuredPlayer tilesToCall: MethodInterface firingInterface)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'ar 10/5/2000 17:38'!\\ninspectArgumentsPlayerInMorphic: evt\\n\\tevt hand attachMorph: ((Inspector openAsMorphOn: self player) extent: 300@200)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 11/5/1998 20:31'!\\ninspectOwnerChain\\n\\tself ownerChain inspectWithLabel: 'Owner chain for ', self printString! !\\n\\n!Morph methodsFor: 'debug and other'!\\ninstallModelIn: ignored\\n\\t\\\"Simple morphs have no model\\\"\\n\\t\\\"See MorphicApp for other behavior\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 2/6/2001 22:35'!\\nmouseUpCodeOrNil\\n\\t\\\"If the receiver has a mouseUpCodeToRun, return it, else return nil\\\"\\n\\n\\t^ self valueOfProperty: #mouseUpCodeToRun ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 2/22/2003 19:05'!\\nownerChain\\n\\t\\\"Answer a list of objects representing the receiver and all of its owners. The first element is the receiver, and the last one is typically the world in which the receiver resides\\\"\\n\\n\\t| c next |\\n\\tc := OrderedCollection with: self.\\n\\tnext := self.\\n\\t[(next := next owner) notNil] whileTrue: [c add: next].\\n\\t^c asArray! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:16'!\\nprogrammedMouseDown: anEvent for: aMorph\\n\\n\\taMorph addMouseActionIndicatorsWidth: 15 color: (Color blue alpha: 0.7).\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:16'!\\nprogrammedMouseEnter: anEvent for: aMorph\\n\\n\\taMorph addMouseActionIndicatorsWidth: 10 color: (Color blue alpha: 0.3).\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:10'!\\nprogrammedMouseLeave: anEvent for: aMorph\\n\\n\\tself deleteAnyMouseActionIndicators.\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 2/22/2003 13:41'!\\nprogrammedMouseUp: anEvent for: aMorph \\n\\t| aCodeString |\\n\\tself deleteAnyMouseActionIndicators.\\n\\taCodeString := self valueOfProperty: #mouseUpCodeToRun ifAbsent: [^self].\\n\\t(self fullBounds containsPoint: anEvent cursorPoint) ifFalse: [^self].\\n\\t\\n\\t[(aCodeString isMessageSend) \\n\\t\\tifTrue: [aCodeString value]\\n\\t\\tifFalse: \\n\\t\\t\\t[Compiler \\n\\t\\t\\t\\tevaluate: aCodeString\\n\\t\\t\\t\\tfor: self\\n\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\tlogged: false]] \\n\\t\\t\\ton: ProgressTargetRequestNotification\\n\\t\\t\\tdo: [:ex | ex resume: self]\\t\\\"in case a save/load progress display needs a home\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:43'!\\nremoveMouseUpAction\\n\\n\\tself primaryHand showTemporaryCursor: nil.\\n\\tself removeProperty: #mouseUpCodeToRun.\\n\\t#(mouseUp mouseEnter mouseLeave mouseDown) do: [ :sym |\\n\\t\\tself\\n\\t\\t\\ton: sym \\n\\t\\t\\tsend: #yourself \\n\\t\\t\\tto: nil.\\n\\t]\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 5/24/2000 18:20'!\\nresumeAfterDrawError\\n\\n\\tself changed.\\n\\tself removeProperty:#errorOnDraw.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 5/24/2000 18:20'!\\nresumeAfterStepError\\n\\t\\\"Resume stepping after an error has occured.\\\"\\n\\n\\tself startStepping. \\\"Will #step\\\"\\n\\tself removeProperty:#errorOnStep. \\\"Will remove prop only if #step was okay\\\"\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 8/30/2003 20:43'!\\ntempCommand\\n\\t\\\"Generic backstop. If you care to, you can comment out what's below here, and substitute your own code, though the intention of design of the feature is that you leave this method as it is, and instead reimplement tempCommand in the class of whatever individual morph you care to. In any case, once you have your own #tempCommand in place, you will then be able to invoke it from the standard debugging menus.\\\"\\n\\n\\tself inform: 'Before calling tempCommand, you\\nshould first give it a definition. To\\ndo this, choose \\\"define tempCommand\\\"\\nfrom the debug menu.' translated! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 8/4/2001 00:33'!\\nviewMorphDirectly\\n\\t\\\"Open a Viewer directly on the Receiver, i.e. no Player involved\\\"\\n\\n\\tself presenter viewObjectDirectly: self renderedMorph\\n\\n\\t! !\\n\\n\\n!Morph methodsFor: 'dispatching' stamp: 'nk 2/15/2004 09:16'!\\ndisableSubmorphFocusForHand: aHandMorph\\n\\t\\\"Check whether this morph or any of its submorph has the Genie focus.\\n\\tIf yes, disable it.\\\"\\n! !\\n\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 6/24/1998 14:10'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"May be overridden by any subclasses with opaque regions\\\"\\n\\n\\t^ Array with: aRectangle! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 6/4/2000 22:02'!\\nboundingBoxOfSubmorphs\\n\\t| aBox |\\n\\taBox _ bounds origin extent: self minimumExtent. \\\"so won't end up with something empty\\\"\\n\\tsubmorphs do:\\n\\t\\t[:m | m visible ifTrue: [aBox _ aBox quickMerge: m fullBounds]].\\n\\t^ aBox\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 2/15/2001 14:51'!\\nboundsWithinCorners\\n\\n\\t^ CornerRounder rectWithinCornersOf: self bounds! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/4/2000 23:39'!\\nchangeClipSubmorphs\\n\\tself clipSubmorphs: self clipSubmorphs not.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 2/16/2003 20:02'!\\nclipLayoutCells\\n\\t\\\"Drawing/layout specific. If this property is set, clip the \\n\\tsubmorphs of the receiver by its cell bounds.\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #clipLayoutCells\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 10/29/2000 19:22'!\\nclipLayoutCells: aBool\\n\\t\\\"Drawing/layout specific. If this property is set, clip the submorphs of the receiver by its cell bounds.\\\"\\n\\taBool == false\\n\\t\\tifTrue:[self removeProperty: #clipLayoutCells]\\n\\t\\tifFalse:[self setProperty: #clipLayoutCells toValue: aBool].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 10/29/2000 19:16'!\\nclippingBounds\\n\\t\\\"Return the bounds to which any submorphs should be clipped if the property is set\\\"\\n\\t^self innerBounds! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 4/3/2006 11:53'!\\nclipSubmorphs\\n\\t\\\"Drawing specific. If this property is set, clip the receiver's \\n\\tsubmorphs to the receiver's clipping bounds.\\\"\\n\\t\\n\\textension ifNil: [^false].\\n\\t^ self\\n\\t\\tvalueOfProperty: #clipSubmorphs\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/12/2000 18:47'!\\nclipSubmorphs: aBool\\n\\t\\\"Drawing specific. If this property is set, clip the receiver's submorphs to the receiver's clipping bounds.\\\"\\n\\tself invalidRect: self fullBounds.\\n\\taBool == false\\n\\t\\tifTrue:[self removeProperty: #clipSubmorphs]\\n\\t\\tifFalse:[self setProperty: #clipSubmorphs toValue: aBool].\\n\\tself invalidRect: self fullBounds.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'tk 8/2/1998 14:33'!\\ndoesOwnRotation\\n\\t\\\"Some morphs don't want to TransformMorph to rotate their images, but we do\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'panda 4/28/2000 11:59'!\\ndrawDropHighlightOn: aCanvas\\n\\tself highlightedForDrop ifTrue: [\\n\\t\\taCanvas frameRectangle: self fullBounds color: self dropHighlightColor].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 12/30/2001 19:17'!\\ndrawDropShadowOn: aCanvas\\n\\n\\taCanvas \\n\\t\\ttranslateBy: self shadowOffset \\n\\t\\tduring: [ :shadowCanvas |\\n\\t\\t\\tshadowCanvas shadowColor: self shadowColor.\\n\\t\\t\\tshadowCanvas roundCornersOf: self during: [ \\n\\t\\t\\t\\t(shadowCanvas isVisible: self bounds) ifTrue:[shadowCanvas drawMorph: self ]]\\n\\t\\t].\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 4/2/1999 13:13'!\\ndrawErrorOn: aCanvas\\n\\t\\\"The morph (or one of its submorphs) had an error in its drawing method.\\\"\\n\\taCanvas\\n\\t\\tframeAndFillRectangle: bounds\\n\\t\\tfillColor: Color red\\n\\t\\tborderWidth: 1\\n\\t\\tborderColor: Color yellow.\\n\\taCanvas line: bounds topLeft to: bounds bottomRight width: 1 color: Color yellow.\\n\\taCanvas line: bounds topRight to: bounds bottomLeft width: 1 color: Color yellow.! !\\n\\n!Morph methodsFor: 'drawing' stamp: ' 9/3/2000 13:55'!\\ndrawMouseDownHighlightOn: aCanvas\\n\\tself highlightedForMouseDown ifTrue: [\\n\\t\\taCanvas frameRectangle: self fullBounds color: self color darker darker].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 8/25/2001 17:31'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds fillStyle: self fillStyle borderStyle: self borderStyle.\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'wiz 3/21/2006 20:44'!\\ndrawRolloverBorderOn: aCanvas \\n\\t| colorToUse offsetToUse myShadow newForm f |\\n\\tcolorToUse := self\\n\\t\\t\\t\\tvalueOfProperty: #rolloverColor\\n\\t\\t\\t\\tifAbsent: [Color blue alpha: 0.5].\\n\\toffsetToUse := self\\n\\t\\t\\t\\tvalueOfProperty: #rolloverWidth\\n\\t\\t\\t\\tifAbsent: [10 @ 10].\\n\\tself hasRolloverBorder: false.\\n\\tmyShadow := self shadowForm.\\n\\tself hasRolloverBorder: true.\\n\\tmyShadow offset: 0 @ 0.\\n\\tf := ColorForm extent: myShadow extent depth: 1.\\n\\tmyShadow displayOn: f.\\n\\tf colors: {Color transparent. colorToUse}.\\n\\tnewForm := Form extent: offsetToUse * 2 + myShadow extent depth: 32.\\n\\t(WarpBlt current toForm: newForm) sourceForm: f;\\n\\t\\t cellSize: 1;\\n\\t\\t combinationRule: 3;\\n\\t\\t copyQuad: f boundingBox innerCorners toRect: newForm boundingBox.\\n\\taCanvas\\n\\t\\ttranslateBy: offsetToUse negated\\n\\t\\tduring: [:shadowCanvas | \\n\\t\\t\\tshadowCanvas shadowColor: colorToUse.\\n\\t\\t\\tshadowCanvas paintImage: newForm at: self position]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 2/22/2003 14:31'!\\ndrawSubmorphsOn: aCanvas \\n\\t\\\"Display submorphs back to front\\\"\\n\\n\\t| drawBlock |\\n\\tsubmorphs isEmpty ifTrue: [^self].\\n\\tdrawBlock := [:canvas | submorphs reverseDo: [:m | canvas fullDrawMorph: m]].\\n\\tself clipSubmorphs \\n\\t\\tifTrue: [aCanvas clipBy: self clippingBounds during: drawBlock]\\n\\t\\tifFalse: [drawBlock value: aCanvas]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'RAA 1/6/2001 22:12'!\\nexpandFullBoundsForDropShadow: aRectangle\\n\\t\\\"Return an expanded rectangle for an eventual drop shadow\\\"\\n\\t| delta box |\\n\\n\\tbox _ aRectangle.\\n\\tdelta _ self shadowOffset.\\n\\tbox _ delta x >= 0 \\n\\t\\tifTrue:[box right: aRectangle right + delta x]\\n\\t\\tifFalse:[box left: aRectangle left + delta x].\\n\\tbox _ delta y >= 0\\n\\t\\tifTrue:[box bottom: aRectangle bottom + delta y]\\n\\t\\tifFalse:[box top: aRectangle top + delta y].\\n\\t^box! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/8/2000 19:29'!\\nexpandFullBoundsForRolloverBorder: aRectangle\\n\\t| delta |\\n\\tdelta _ self valueOfProperty: #rolloverWidth ifAbsent: [10@10].\\n\\t^aRectangle expandBy: delta.\\n\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 11/26/2003 17:43'!\\nflashBounds\\n\\t\\\"Flash the receiver's bounds -- does not use the receiver's color, thus works with StringMorphs and SketchMorphs, etc., for which #flash is useless. No senders initially, but useful to send this from a debugger or inspector\\\"\\n\\n\\t5 timesRepeat:\\n\\t\\t[Display flash: self boundsInWorld andWait: 120]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 12/30/2001 15:22'!\\nfullDrawOn: aCanvas\\n\\t\\\"Draw the full Morphic structure on the given Canvas\\\"\\n\\n\\tself visible ifFalse: [^ self].\\n\\t(aCanvas isVisible: self fullBounds) ifFalse:[^self].\\n\\t(self hasProperty: #errorOnDraw) ifTrue:[^self drawErrorOn: aCanvas].\\n\\t\\\"Note: At some point we should generalize this into some sort of \\n\\tmulti-canvas so that we can cross-optimize some drawing operations.\\\"\\n\\t\\\"Pass 1: Draw eventual drop-shadow\\\"\\n\\tself hasDropShadow ifTrue: [self drawDropShadowOn: aCanvas].\\n\\t(self hasRolloverBorder and: [(aCanvas seesNothingOutside: self bounds) not])\\n\\t\\tifTrue: [self drawRolloverBorderOn: aCanvas].\\n\\n\\t\\\"Pass 2: Draw receiver itself\\\"\\n\\taCanvas roundCornersOf: self during:[\\n\\t\\t(aCanvas isVisible: self bounds) ifTrue:[aCanvas drawMorph: self].\\n\\t\\tself drawSubmorphsOn: aCanvas.\\n\\t\\tself drawDropHighlightOn: aCanvas.\\n\\t\\tself drawMouseDownHighlightOn: aCanvas].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 8/30/2003 20:20'!\\nhasClipSubmorphsString\\n\\t\\\"Answer a string that represents the clip-submophs checkbox\\\"\\n\\t^ (self clipSubmorphs\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'provide clipping' translated! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/30/1998 18:27'!\\nhide\\n\\towner ifNil: [^ self].\\n\\tself visible ifTrue: [self visible: false. self changed]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'LC 5/18/2000 08:48'!\\nhighlightedForMouseDown\\n\\t^(self valueOfProperty: #highlightedForMouseDown) == true! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'LC 5/18/2000 08:51'!\\nhighlightForMouseDown\\n\\tself highlightForMouseDown: true! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 3/17/2001 15:56'!\\nhighlightForMouseDown: aBoolean\\n\\taBoolean \\n\\t\\tifTrue:[self setProperty: #highlightedForMouseDown toValue: aBoolean]\\n\\t\\tifFalse:[self removeProperty: #highlightedForMouseDown. self resetExtension].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'jm 6/11/97 17:21'!\\nimageForm\\n\\n\\t^ self imageFormForRectangle: self fullBounds\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 7/8/1998 12:42'!\\nimageFormDepth: depth\\n\\n\\t^ self imageForm: depth forRectangle: self fullBounds\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 9/9/1998 22:25'!\\nimageFormForRectangle: rect\\n\\n\\t^ self imageForm: Display depth forRectangle: rect\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 9/1/2000 14:23'!\\nimageFormWithout: stopMorph andStopThere: stopThere\\n\\t\\\"Like imageForm, except it does not display stopMorph,\\n\\tand it will not display anything above it if stopThere is true.\\n\\tReturns a pair of the imageForm and a boolean that is true\\n\\t\\tif it has hit stopMorph, and display should stop.\\\"\\n\\t| canvas rect |\\n\\trect _ self fullBounds.\\n\\tcanvas _ ColorPatchCanvas extent: rect extent depth: Display depth.\\n\\tcanvas stopMorph: stopMorph.\\n\\tcanvas doStop: stopThere.\\n\\tcanvas translateBy: rect topLeft negated during:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ Array with: (canvas form offset: rect topLeft)\\n\\t\\t\\twith: canvas foundMorph! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'nk 9/1/2004 15:08'!\\nimageForm: depth backgroundColor: aColor forRectangle: rect\\n\\t| canvas |\\n\\tcanvas _ Display defaultCanvasClass extent: rect extent depth: depth.\\n\\tcanvas translateBy: rect topLeft negated\\n\\t\\tduring:[:tempCanvas| \\n\\t\\t\\ttempCanvas fillRectangle: rect color: aColor.\\n\\t\\t\\ttempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: rect topLeft! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 9/1/2000 14:23'!\\nimageForm: depth forRectangle: rect\\n\\t| canvas |\\n\\tcanvas _ Display defaultCanvasClass extent: rect extent depth: depth.\\n\\tcanvas translateBy: rect topLeft negated\\n\\t\\tduring:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: rect topLeft! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/10/1999 23:25'!\\nrefreshWorld\\n\\t| aWorld |\\n\\t(aWorld _ self world) ifNotNil: [aWorld displayWorldSafely]\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'JW 7/12/2005 20:12'!\\nshadowForm\\n\\t\\\"Return a form representing the 'shadow' of the receiver - e.g., all pixels that are occupied by the receiver are one, all others are zero.\\\"\\n\\t| canvas |\\n\\tcanvas := (Display defaultCanvasClass extent: self fullBounds extent depth: 1)\\n\\t\\t\\t\\tasShadowDrawingCanvas: Color black. \\\"Color black represents one for 1bpp\\\"\\n\\tcanvas translateBy: bounds topLeft negated\\n\\t\\tduring:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: bounds topLeft\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/22/1998 20:29'!\\nshow\\n\\t\\\"Make sure this morph is on-stage.\\\"\\n\\tself visible ifFalse: [self visible: true. self changed]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 2/27/2006 08:49'!\\nvisible\\n\\t\\\"answer whether the receiver is visible\\\"\\n\\textension ifNil: [^ true].\\n\\t^ extension visible! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 2/27/2006 08:49'!\\nvisible: aBoolean \\n\\t\\\"set the 'visible' attribute of the receiver to aBoolean\\\"\\n\\t(extension isNil and:[aBoolean]) ifTrue: [^ self].\\n\\tself visible == aBoolean ifTrue: [^ self].\\n\\tself assureExtension visible: aBoolean.\\n\\tself changed! !\\n\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'RAA 1/19/2001 07:51'!\\naddDropShadow\\n\\n\\tself hasDropShadow ifTrue:[^self].\\n\\tself changed.\\n\\tself hasDropShadow: true.\\n\\tself shadowOffset: 3@3.\\n\\tself layoutChanged.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 8/30/2003 16:48'!\\naddDropShadowMenuItems: aMenu hand: aHand\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu\\n\\t\\taddUpdating: #hasDropShadowString\\n\\t\\taction: #toggleDropShadow.\\n\\tmenu addLine.\\n\\tmenu add: 'shadow color...' translated target: self selector: #changeShadowColor.\\n\\tmenu add: 'shadow offset...' translated target: self selector: #setShadowOffset:.\\n\\taMenu add: 'drop shadow' translated subMenu: menu.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:22'!\\nchangeShadowColor\\n\\t\\\"Change the shadow color of the receiver -- triggered, e.g. from a menu\\\"\\n\\n\\tColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: self activeHand;\\n\\t\\ttarget: self;\\n\\t\\tselector: #shadowColor:;\\n\\t\\toriginalColor: self shadowColor;\\n\\t\\tputUpFor: self near: self fullBoundsInWorld! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 2/16/2003 21:42'!\\nhasDropShadow\\n\\t\\\"answer whether the receiver has DropShadow\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #hasDropShadow\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 8/30/2003 16:49'!\\nhasDropShadowString\\n\\t^ (self hasDropShadow\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'show shadow' translated! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 19:03'!\\nhasDropShadow: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasDropShadow toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasDropShadow]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 2/16/2003 21:58'!\\nhasRolloverBorder\\n\\t\\\"answer whether the receiver has RolloverBorder\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #hasRolloverBorder\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'RAA 11/7/2000 15:54'!\\nhasRolloverBorder: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasRolloverBorder toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasRolloverBorder]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 11/12/2000 18:57'!\\nremoveDropShadow\\n\\tself hasDropShadow ifFalse:[^self].\\n\\tself changed.\\n\\tself hasDropShadow: false.\\n\\tfullBounds ifNotNil:[fullBounds _ self privateFullBounds].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:58'!\\nsetShadowOffset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:\\n\\t\\t[:newPoint | self shadowPoint: newPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:59'!\\nshadowColor\\n\\t^self valueOfProperty: #shadowColor ifAbsent:[Color black]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:22'!\\nshadowColor: aColor\\n\\tself shadowColor = aColor ifFalse:[self changed].\\n\\tself setProperty: #shadowColor toValue: aColor.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:57'!\\nshadowOffset\\n\\t\\\"Return the current shadow offset\\\"\\n\\t^self valueOfProperty: #shadowOffset ifAbsent:[0@0]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 19:00'!\\nshadowOffset: aPoint\\n\\t\\\"Set the current shadow offset\\\"\\n\\t(aPoint isNil or:[(aPoint x isZero) & (aPoint y isZero)])\\n\\t\\tifTrue:[self removeProperty: #shadowOffset]\\n\\t\\tifFalse:[self setProperty: #shadowOffset toValue: aPoint].! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 11/12/2000 18:58'!\\nshadowPoint: newPoint\\n\\tself changed.\\n\\tself shadowOffset: newPoint - self center // 5.\\n\\tfullBounds ifNotNil:[fullBounds _ self privateFullBounds].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:16'!\\ntoggleDropShadow\\n\\tself hasDropShadow\\n\\t\\tifTrue:[self removeDropShadow]\\n\\t\\tifFalse:[self addDropShadow].! !\\n\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 20:00'!\\naboutToBeGrabbedBy: aHand\\n\\t\\\"The receiver is being grabbed by a hand.\\n\\tPerform necessary adjustments (if any) and return the actual morph\\n\\tthat should be added to the hand.\\\"\\n\\t| extentToHandToHand cmd |\\n\\tself formerOwner: owner.\\n\\tself formerPosition: self position.\\n\\tcmd _ self undoGrabCommand.\\n\\tcmd ifNotNil:[self setProperty: #undoGrabCommand toValue: cmd].\\n\\t(extentToHandToHand _ self valueOfProperty: #expandedExtent)\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[self removeProperty: #expandedExtent.\\n\\t\\t\\t\\tself extent: extentToHandToHand].\\n\\t^self \\\"Grab me\\\"! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:41'!\\ndisableDragNDrop\\n\\tself enableDragNDrop: false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:50'!\\ndragEnabled\\n\\t\\\"Get this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\t^(self valueOfProperty: #dragEnabled) == true\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:18'!\\ndragEnabled: aBool\\n\\t^self enableDrag: aBool! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:20'!\\ndragNDropEnabled\\n\\t\\\"Note: This method is only useful for dragEnabled == dropEnabled at all times\\\"\\n\\tself separateDragAndDrop.\\n\\t^self dragEnabled and:[self dropEnabled]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 18:36'!\\ndragSelectionColor\\n\\t^ Color magenta! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:51'!\\ndropEnabled\\n\\t\\\"Get this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\t^(self valueOfProperty: #dropEnabled) == true\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:18'!\\ndropEnabled: aBool\\n\\t^self enableDrop: aBool! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 10:52'!\\ndropHighlightColor\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 18:08'!\\ndropSuccessColor\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:41'!\\nenableDragNDrop\\n\\tself enableDragNDrop: true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:21'!\\nenableDragNDrop: aBoolean\\n\\t\\\"Set both properties at once\\\"\\n\\tself separateDragAndDrop.\\n\\tself enableDrag: aBoolean.\\n\\tself enableDrop: aBoolean.! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:50'!\\nenableDrag: aBoolean\\n\\tself setProperty: #dragEnabled toValue: aBoolean! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:51'!\\nenableDrop: aBoolean\\n\\tself setProperty: #dropEnabled toValue: aBoolean! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:13'!\\nformerOwner\\n\\t^self valueOfProperty: #formerOwner! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 2/22/2003 14:31'!\\nformerOwner: aMorphOrNil \\n\\taMorphOrNil isNil \\n\\t\\tifTrue: [self removeProperty: #formerOwner]\\n\\t\\tifFalse: [self setProperty: #formerOwner toValue: aMorphOrNil]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:13'!\\nformerPosition\\n\\t^self valueOfProperty: #formerPosition! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 2/22/2003 14:31'!\\nformerPosition: formerPosition \\n\\tformerPosition isNil \\n\\t\\tifTrue: [self removeProperty: #formerPosition]\\n\\t\\tifFalse: [self setProperty: #formerPosition toValue: formerPosition]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/6/2000 15:13'!\\ngrabTransform\\n\\t\\\"Return the transform for the receiver which should be applied during grabbing\\\"\\n\\t^owner ifNil:[IdentityTransform new] ifNotNil:[owner grabTransform]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 10:53'!\\nhighlightedForDrop\\n\\t^(self valueOfProperty: #highlightedForDrop) == true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 11:51'!\\nhighlightForDrop\\n\\tself highlightForDrop: true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 12:01'!\\nhighlightForDrop: aBoolean\\n\\tself setProperty: #highlightedForDrop toValue: aBoolean.\\n\\tself changed! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 9/10/2004 13:42'!\\njustDroppedInto: aMorph event: anEvent\\n\\t\\\"This message is sent to a dropped morph after it has been dropped on -- and been accepted by -- a drop-sensitive morph\\\"\\n\\n\\t| aWindow partsBinCase cmd aStack |\\n\\t(self formerOwner notNil and: [self formerOwner ~~ aMorph])\\n\\t\\tifTrue: [self removeHalo].\\n\\tself formerOwner: nil.\\n\\tself formerPosition: nil.\\n\\tcmd _ self valueOfProperty: #undoGrabCommand.\\n\\tcmd ifNotNil:[aMorph rememberCommand: cmd.\\n\\t\\t\\t\\tself removeProperty: #undoGrabCommand].\\n\\t(partsBinCase _ aMorph isPartsBin) ifFalse:\\n\\t\\t[self isPartsDonor: false].\\n\\t(aWindow _ aMorph ownerThatIsA: SystemWindow) ifNotNil:\\n\\t\\t[aWindow isActive ifFalse:\\n\\t\\t\\t[aWindow activate]].\\n\\t(self isInWorld and: [partsBinCase not]) ifTrue:\\n\\t\\t[self world startSteppingSubmorphsOf: self].\\n\\t\\\"Note an unhappy inefficiency here: the startStepping... call will often have already been called in the sequence leading up to entry to this method, but unfortunately the isPartsDonor: call often will not have already happened, with the result that the startStepping... call will not have resulted in the startage of the steppage.\\\"\\n\\n\\t\\\"An object launched by certain parts-launcher mechanisms should end up fully visible...\\\"\\n\\t(self hasProperty: #beFullyVisibleAfterDrop) ifTrue:\\n\\t\\t[aMorph == ActiveWorld ifTrue:\\n\\t\\t\\t[self goHome].\\n\\t\\tself removeProperty: #beFullyVisibleAfterDrop].\\n\\n\\t(self holdsSeparateDataForEachInstance and: [(aStack _ self stack) notNil])\\n\\t\\tifTrue:\\n\\t\\t\\t[aStack reassessBackgroundShape]\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 2/6/2001 22:12'!\\njustGrabbedFrom: formerOwner\\n\\t\\\"The receiver was just grabbed from its former owner and is now attached to the hand. By default, we pass this message on if we're a renderer.\\\"\\n\\t(self isRenderer and:[self hasSubmorphs]) \\n\\t\\tifTrue:[self firstSubmorph justGrabbedFrom: formerOwner].! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 3/27/2001 11:52'!\\nnameForUndoWording\\n\\t\\\"Return wording appropriate to the receiver for use in an undo-related menu item (and perhaps elsewhere)\\\"\\n\\n\\t| aName |\\n\\taName _ self knownName ifNil: [self renderedMorph class name].\\n\\t^ aName truncateTo: 24! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'di 12/12/2000 14:35'!\\nrejectDropMorphEvent: evt\\n\\t\\\"The receiver has been rejected, and must be put back somewhere. There are three cases:\\n\\t(1) It remembers its former owner and position, and goes right back there\\n\\t(2) It remembers its former position only, in which case it was torn off from a parts bin, and the UI is that it floats back to its donor position and then vanishes.\\n\\t(3) Neither former owner nor position is remembered, in which case it is whisked to the Trash\\\"\\n\\n\\tself removeProperty: #undoGrabCommand.\\n\\t(self formerOwner notNil and: [self formerOwner isPartsBin not]) ifTrue:\\n\\t\\t[^ self slideBackToFormerSituation: evt].\\n\\n\\tself formerPosition ifNotNil: \\\"Position but no owner -- can just make it vanish\\\"\\n\\t\\t[^ self vanishAfterSlidingTo: self formerPosition event: evt].\\n\\t\\t\\n\\tself slideToTrash: evt! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 1/11/1999 20:07'!\\nrepelsMorph: aMorph event: ev\\n\\t^ false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 12:02'!\\nresetHighlightForDrop\\n\\tself highlightForDrop: false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:24'!\\nseparateDragAndDrop\\n\\t\\\"Conversion only. Separate the old #dragNDropEnabled into #dragEnabled and #dropEnabled and remove the old property.\\\"\\n\\t| dnd |\\n\\t(self hasProperty: #dragNDropEnabled) ifFalse:[^self].\\n\\tdnd _ (self valueOfProperty: #dragNDropEnabled) == true.\\n\\tself dragEnabled: dnd.\\n\\tself dropEnabled: dnd.\\n\\tself removeProperty: #dragNDropEnabled.\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 8/12/2003 23:35'!\\nslideBackToFormerSituation: evt \\n\\t| slideForm formerOwner formerPosition aWorld startPoint endPoint trans |\\n\\tformerOwner := self formerOwner.\\n\\tformerPosition := self formerPosition.\\n\\taWorld := evt hand world.\\n\\ttrans := formerOwner transformFromWorld.\\n\\tslideForm := trans isPureTranslation \\n\\t\\t\\t\\tifTrue: [self imageForm offset: 0 @ 0]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[((TransformationMorph new asFlexOf: self) transform: trans) imageForm \\n\\t\\t\\t\\t\\t\\toffset: 0 @ 0]. \\n\\tstartPoint := evt hand fullBounds origin.\\n\\tendPoint := trans localPointToGlobal: formerPosition.\\n\\towner removeMorph: self.\\n\\taWorld displayWorld.\\n\\tslideForm \\n\\t\\tslideFrom: startPoint\\n\\t\\tto: endPoint\\n\\t\\tnSteps: 12\\n\\t\\tdelay: 15.\\n\\tformerOwner addMorph: self.\\n\\tself position: formerPosition.\\n\\tself justDroppedInto: formerOwner event: evt! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 4/3/2006 14:12'!\\nslideToTrash: evt\\n\\t\\\"Perhaps slide the receiver across the screen to a trash can and make it disappear into it. In any case, remove the receiver from the screen.\\\"\\n\\n\\t| aForm trash startPoint endPoint morphToSlide |\\n\\t((self renderedMorph == Utilities scrapsBook) or: [self renderedMorph isKindOf: TrashCanMorph]) ifTrue:\\n\\t\\t[self dismissMorph. ^ self].\\n\\tPreferences slideDismissalsToTrash ifTrue:\\n\\t\\t[morphToSlide _ self representativeNoTallerThan: 200 norWiderThan: 200 thumbnailHeight: 100.\\n\\t\\taForm _ morphToSlide imageForm offset: (0@0).\\n\\t\\ttrash _ ActiveWorld\\n\\t\\t\\tfindDeepSubmorphThat:\\n\\t\\t\\t\\t[:aMorph | (aMorph isKindOf: TrashCanMorph) and:\\n\\t\\t\\t\\t\\t[aMorph topRendererOrSelf owner == ActiveWorld]]\\n\\t\\t\\tifAbsent:\\n\\t\\t\\t\\t[trash _ TrashCanMorph new.\\n\\t\\t\\t\\ttrash bottomLeft: ActiveWorld bottomLeft - (-10@10).\\n\\t\\t\\t\\ttrash openInWorld.\\n\\t\\t\\t\\ttrash].\\n\\t\\tendPoint _ trash fullBoundsInWorld center.\\n\\t\\tstartPoint _ self topRendererOrSelf fullBoundsInWorld center - (aForm extent // 2)].\\n\\tself dismissMorph.\\n\\tActiveWorld displayWorld.\\n\\tPreferences slideDismissalsToTrash ifTrue:\\n\\t\\t[aForm slideFrom: startPoint to: endPoint nSteps: 12 delay: 15].\\n\\tUtilities addToTrash: self! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'mir 1/4/2001 11:02'!\\nstartDrag: anItem with: anObject\\n\\tself currentHand attachMorph: anObject! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:46'!\\ntoggleDragNDrop\\n\\t\\\"Toggle this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\t\\tself enableDragNDrop: self dragNDropEnabled not.\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing'!\\ntransportedMorph\\n\\t^self! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 8/26/2003 21:44'!\\nundoGrabCommand\\n\\t\\\"Return an undo command for grabbing the receiver\\\"\\n\\n\\t| cmd |\\n\\towner ifNil:\\n\\t\\t[^ nil]. \\\"no owner - no undo\\\"\\n\\t^ (cmd _ Command new)\\n\\t\\tcmdWording: 'move ' translated, self nameForUndoWording;\\n\\t\\tundoTarget: self\\n\\t\\tselector: #undoMove:redo:owner:bounds:predecessor:\\n\\t\\targuments: {cmd. false. owner. self bounds. (owner morphPreceding: self)};\\n\\t\\tyourself! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'bf 1/5/2000 19:11'!\\nvanishAfterSlidingTo: aPosition event: evt\\n\\n\\t| aForm aWorld startPoint endPoint |\\n\\taForm _ self imageForm offset: 0@0.\\n\\taWorld _ self world.\\n\\tstartPoint _ evt hand fullBounds origin.\\n\\tself delete.\\n\\taWorld displayWorld.\\n\\tendPoint _ aPosition.\\n\\taForm slideFrom: startPoint to: endPoint nSteps: 12 delay: 15.\\n\\tPreferences soundsEnabled ifTrue: [TrashCanMorph playDeleteSound].\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:24'!\\nwantsDroppedMorph: aMorph event: evt\\n\\t\\\"Return true if the receiver wishes to accept the given morph, which is being dropped by a hand in response to the given event. Note that for a successful drop operation both parties need to agree. The symmetric check is done automatically via aMorph wantsToBeDroppedInto: self.\\\"\\n\\n\\t^self dropEnabled! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 9/18/2000 18:34'!\\nwantsToBeDroppedInto: aMorph\\n\\t\\\"Return true if it's okay to drop the receiver into aMorph. This check is symmetric to #wantsDroppedMorph:event: to give both parties a chance of figuring out whether they like each other.\\\"\\n\\t^true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 2/10/1999 05:44'!\\nwantsToBeOpenedInWorld\\n\\t\\\"Return true if the receiver wants to be put into the World directly,\\n\\trather than allowing the user to place it (e.g., prevent attaching me\\n\\tto the hand after choosing 'new morph' in the world menu)\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 8/15/2000 16:58'!\\nwillingToBeDiscarded\\n\\t^ true! !\\n\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 9/6/2000 12:42'!\\nclick\\n\\t\\\"Pretend the user clicked on me.\\\"\\n\\n\\t(self handlesMouseDown: nil) ifTrue: [\\n\\t\\tself mouseDown: nil.\\n\\t\\tself mouseUp: nil].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'LC 5/18/2000 09:54'!\\nclick: evt\\n\\t\\\"Handle a single-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\n\\tLC 2/14/2000 08:32 - added: EventHandler notification\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler click: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 3/8/1999 00:17'!\\ncursorPoint\\n\\t^ self currentHand lastEvent cursorPoint! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'jcg 10/2/2001 09:26'!\\ndoubleClickTimeout: evt\\n\\t\\\"Handle a double-click timeout event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler doubleClickTimeout: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'LC 5/18/2000 09:54'!\\ndoubleClick: evt\\n\\t\\\"Handle a double-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\n\\tLC 2/14/2000 08:32 - added: EventHandler notification\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler doubleClick: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 1/10/2001 21:28'!\\ndropFiles: anEvent\\n\\t\\\"Handle a number of files dropped from the OS\\\"\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'RAA 2/12/2001 15:26'!\\nfirstClickTimedOut: evt\\n\\t\\\"Useful for double-click candidates who want to know whether or not the click is a single or double. In this case, ignore the #click: and wait for either this or #doubleClick:\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'nk 3/10/2004 19:48'!\\nhandlerForYellowButtonDown: anEvent \\n\\t\\\"Return the (prospective) handler for a mouse down event with the yellow button pressed.\\n\\tThe \\thandler is temporarily installed and can be used for morphs further \\n\\tdown the hierarchy to negotiate whether the inner or the outer \\n\\tmorph should finally handle the event.\\\"\\n\\n\\t(self hasYellowButtonMenu or: [ self handlesMouseDown: anEvent ])\\n\\t\\tifFalse: [ ^ nil].\\t\\\"Not interested.\\\"\\n\\n\\tanEvent handler\\n\\t\\tifNil: [^ self].\\t\\\"Nobody else was interested\\\"\\n\\n\\t\\\"Same priority but I am innermost.\\\"\\n\\t^ self mouseDownPriority >= anEvent handler mouseDownPriority\\n\\t\\tifFalse: [nil ]\\n\\t\\tifTrue: [self]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/28/2000 22:18'!\\nhandlesKeyboard: evt\\n\\t\\\"Return true if the receiver wishes to handle the given keyboard event\\\"\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesKeyboard: evt].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'nk 2/14/2004 18:42'!\\nhandlesMouseDown: evt\\n\\t\\\"Do I want to receive mouseDown events (mouseDown:, mouseMove:, mouseUp:)?\\\"\\n\\t\\\"NOTE: The default response is false, except if you have added sensitivity to mouseDown events using the on:send:to: mechanism. Subclasses that implement these messages directly should override this one to return true.\\\" \\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseDown: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:31'!\\nhandlesMouseOverDragging: evt\\n\\t\\\"Return true if I want to receive mouseEnterDragging: and mouseLeaveDragging: when the hand drags something over me (button up or button down), or when the mouse button is down but there is no mouseDown recipient. The default response is false, except if you have added sensitivity to mouseEnterLaden: or mouseLeaveLaden:, using the on:send:to: mechanism.\\\"\\n\\t\\\"NOTE: If the hand state matters in these cases, it may be tested by constructs such as\\n\\t\\tevent anyButtonPressed\\n\\t\\tevent hand hasSubmorphs\\\"\\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseOverDragging: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:31'!\\nhandlesMouseOver: evt\\n\\t\\\"Do I want to receive mouseEnter: and mouseLeave: when the button is up and the hand is empty? The default response is false, except if you have added sensitivity to mouseEnter: or mouseLeave:, using the on:send:to: mechanism.\\\" \\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseOver: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/22/2000 17:06'!\\nhandlesMouseStillDown: evt\\n\\t\\\"Return true if the receiver wants to get repeated #mouseStillDown: messages between #mouseDown: and #mouseUp\\\"\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseStillDown: evt].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 4/2/98 14:16'!\\nhasFocus\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling'!\\nkeyboardFocusChange: aBoolean\\n\\t\\\"The message is sent to a morph when its keyboard focus change. The given argument indicates that the receiver is gaining keyboard focus (versus losing) the keyboard focus. Morphs that accept keystrokes should change their appearance in some way when they are the current keyboard focus. This default implementation does nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 9/14/2000 18:23'!\\nkeyDown: anEvent\\n\\t\\\"Handle a key down event. The default response is to do nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:05'!\\nkeyStroke: anEvent\\n\\t\\\"Handle a keystroke event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler keyStroke: anEvent fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'KTT 6/1/2004 11:41'!\\nkeyUp: anEvent\\n\\t\\\"Handle a key up event. The default response is to do nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 9/19/2004 13:14'!\\nmouseDown: evt \\n\\t\\\"Handle a mouse down event. The default response is to let my \\n\\teventHandler, if any, handle it.\\\"\\n\\tevt yellowButtonPressed\\n\\t\\tifTrue: [\\\"First check for option (menu) click\\\"\\n\\t\\t\\t^ self yellowButtonActivity: evt shiftPressed].\\n\\tself eventHandler\\n\\t\\tifNotNil: [self eventHandler mouseDown: evt fromMorph: self]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:33'!\\nmouseEnterDragging: evt\\n\\t\\\"Handle a mouseEnterDragging event, meaning the mouse just entered my bounds with a button pressed or laden with submorphs. The default response is to let my eventHandler, if any, handle it, or else to do nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[^ self eventHandler mouseEnterDragging: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:00'!\\nmouseEnter: evt\\n\\t\\\"Handle a mouseEnter event, meaning the mouse just entered my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseEnter: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:38'!\\nmouseLeaveDragging: evt\\n\\t\\\"Handle a mouseLeaveLaden event, meaning the mouse just left my bounds with a button pressed or laden with submorphs. The default response is to let my eventHandler, if any, handle it; else to do nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseLeaveDragging: evt fromMorph: self]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:01'!\\nmouseLeave: evt\\n\\t\\\"Handle a mouseLeave event, meaning the mouse just left my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseLeave: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:04'!\\nmouseMove: evt\\n\\t\\\"Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseMove: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:02'!\\nmouseStillDownThreshold\\n\\t\\\"Return the number of milliseconds after which mouseStillDown: should be sent\\\"\\n\\t^200! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/22/2000 17:08'!\\nmouseStillDown: evt\\n\\t\\\"Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseStillDown: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:05'!\\nmouseUp: evt\\n\\t\\\"Handle a mouse up event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseUp: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 8/28/2004 18:20'!\\nmoveOrResizeFromKeystroke: anEvent \\n\\t\\\"move or resize the receiver based on a keystroke\\\"\\n\\t| dir | \\n\\n\\tanEvent keyValue = 28 ifTrue: [dir := -1 @ 0].\\n\\tanEvent keyValue = 29 ifTrue: [dir := 1 @ 0].\\n\\tanEvent keyValue = 30 ifTrue: [dir := 0 @ -1].\\n\\tanEvent keyValue = 31 ifTrue: [dir := 0 @ 1].\\n\\n\\tdir notNil\\n\\t\\tifTrue:[\\n\\t\\t\\tanEvent controlKeyPressed ifTrue: [dir := dir * 10].\\n\\n\\t\\t\\tanEvent shiftPressed\\n\\t\\t\\t\\tifTrue: [self extent: self extent + dir]\\n\\t\\t\\t\\tifFalse: [self position: self position + dir].\\n\\n\\t\\t\\t\\\"anEvent wasHandled: true.\\\"\\n\\t]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:01'!\\non: eventName send: selector to: recipient\\n\\tself eventHandler ifNil: [self eventHandler: EventHandler new].\\n\\tself eventHandler on: eventName send: selector to: recipient! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 3/18/2001 17:21'!\\non: eventName send: selector to: recipient withValue: value\\n\\t\\\"NOTE: selector must take 3 arguments, of which value will be the *** FIRST ***\\\"\\n\\n\\tself eventHandler ifNil: [self eventHandler: EventHandler new].\\n\\tself eventHandler on: eventName send: selector to: recipient withValue: value\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'fbs 1/7/2005 15:43'!\\npreferredKeyboardBounds\\n\\n\\t^ self bounds: self bounds in: World.\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'fbs 1/7/2005 15:42'!\\npreferredKeyboardPosition\\n\\n\\t^ (self bounds: self bounds in: World) topLeft.\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:02'!\\nremoveLink: actionCode\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler on: actionCode send: nil to: nil]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/16/1998 08:06'!\\nrestoreSuspendedEventHandler\\n\\t| savedHandler |\\n\\t(savedHandler _ self valueOfProperty: #suspendedEventHandler) ifNotNil:\\n\\t\\t[self eventHandler: savedHandler].\\n\\tsubmorphs do: [:m | m restoreSuspendedEventHandler]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'mir 5/23/2000 17:43'!\\nstartDrag: evt\\n\\t\\\"Handle a double-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler startDrag: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/16/1998 08:07'!\\nsuspendEventHandler\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self setProperty: #suspendedEventHandler toValue: self eventHandler.\\n\\t\\tself eventHandler: nil].\\n\\tsubmorphs do: [:m | m suspendEventHandler]. \\\"All those rectangles\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 8/28/2004 18:42'!\\ntabAmongFields\\n\\t^ Preferences tabAmongFields\\n\\t\\tor: [self hasProperty: #tabAmongFields] ! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'RAA 6/19/2000 07:13'!\\ntransformFromOutermostWorld\\n\\t\\\"Return a transform to map world coordinates into my local coordinates\\\"\\n\\n\\t\\\"self isWorldMorph ifTrue: [^ MorphicTransform identity].\\\"\\n\\t^ self transformFrom: self outermostWorldMorph! !\\n\\n!Morph methodsFor: 'event handling'!\\ntransformFromWorld\\n\\t\\\"Return a transform to map world coordinates into my local coordinates\\\"\\n\\n\\t^ self transformFrom: nil! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 14:36'!\\ntransformFrom: uberMorph \\n\\t\\\"Return a transform to be used to map coordinates in a morph above me into my childrens coordinates, or vice-versa. This is used to support scrolling, scaling, and/or rotation. This default implementation just returns my owner's transform or the identity transform if my owner is nil. \\n\\tNote: This method cannot be used to map into the receiver's coordinate system!!\\\"\\n\\n\\t(self == uberMorph or: [owner isNil]) ifTrue: [^IdentityTransform new].\\n\\t^owner transformFrom: uberMorph! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 1/10/2001 21:28'!\\nwantsDropFiles: anEvent\\n\\t\\\"Return true if the receiver wants files dropped from the OS.\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/2000 11:46'!\\nwantsEveryMouseMove\\n\\t\\\"Unless overridden, this method allows processing to skip mouse move events\\n\\twhen processing is lagging. No 'significant' event (down/up, etc) will be skipped.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/3/97 02:11'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t\\\"Answer whether a plain mouse click on aSubmorph, a text-edit-capable thing, should result in a text selection there\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 5/6/1998 12:54'!\\nwouldAcceptKeyboardFocus\\n\\t\\\"Answer whether a plain mouse click on the receiver should result in a text selection there\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 8/29/2000 14:57'!\\nwouldAcceptKeyboardFocusUponTab\\n\\t\\\"Answer whether the receiver is in the running as the new keyboard focus if the tab key were hit at a meta level. This provides the leverage for tabbing among fields of a card, for example.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 7/28/2005 13:02'!\\nyellowButtonActivity: shiftState \\n\\t\\\"Find me or my outermost owner that has items to add to a \\n\\tyellow button menu. \\n\\tshiftState is true if the shift was pressed. \\n\\tOtherwise, build a menu that contains the contributions from \\n\\tmyself and my interested submorphs, \\n\\tand present it to the user.\\\"\\n\\t| menu |\\n\\tself isWorldMorph\\n\\t\\tifFalse: [| outerOwner | \\n\\t\\t\\touterOwner := self outermostOwnerWithYellowButtonMenu.\\n\\t\\t\\touterOwner\\n\\t\\t\\t\\tifNil: [^ self].\\n\\t\\t\\touterOwner == self\\n\\t\\t\\t\\tifFalse: [^ outerOwner yellowButtonActivity: shiftState]].\\n\\tmenu := self buildYellowButtonMenu: ActiveHand.\\n\\tmenu\\n\\t\\taddTitle: self externalName\\n\\t\\ticon: (self iconOrThumbnailOfSize: (Preferences tinyDisplay ifTrue: [16] ifFalse: [28])).\\n\\tmenu popUpInWorld: self currentWorld! !\\n\\n\\n!Morph methodsFor: 'events-accessing' stamp: 'rw 4/25/2002 07:18'!\\nactionMap\\n\\t\\\"Answer an action map\\\"\\n\\n\\t| actionMap |\\n\\tactionMap := self valueOfProperty: #actionMap.\\n\\tactionMap ifNil:\\n\\t\\t[actionMap _ self createActionMap].\\n\\t^ actionMap! !\\n\\n!Morph methodsFor: 'events-accessing' stamp: 'rw 4/25/2002 07:17'!\\nupdateableActionMap\\n\\t\\\"Answer an updateable action map, saving it in my #actionMap property\\\"\\n\\t\\n\\t| actionMap |\\n\\tactionMap := self valueOfProperty: #actionMap.\\n\\tactionMap ifNil:\\n\\t\\t[actionMap _ self createActionMap.\\n\\t\\tself setProperty: #actionMap toValue: actionMap].\\n\\t^ actionMap! !\\n\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: #() after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: #() at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector withArguments: args after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: args at: Time millisecondClockValue + delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:15'!\\naddAlarm: aSelector withArguments: args at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler addAlarm: aSelector withArguments: args for: self at: scheduledTime].! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1) after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1) at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 with: arg2 after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1 with: arg2) after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 with: arg2 at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1 with: arg2) at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:34'!\\nalarmScheduler\\n\\t\\\"Return the scheduler being responsible for triggering alarms\\\"\\n\\t^self world! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:14'!\\nremoveAlarm: aSelector\\n\\t\\\"Remove the given alarm\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler removeAlarm: aSelector for: self].! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:15'!\\nremoveAlarm: aSelector at: scheduledTime\\n\\t\\\"Remove the given alarm\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler removeAlarm: aSelector at: scheduledTime for: self].! !\\n\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 17:58'!\\ncontainsPoint: aPoint event: anEvent\\n\\t\\\"Return true if aPoint is considered to be inside the receiver for the given event.\\n\\tThe default implementation treats locked children as integral part of their owners.\\\"\\n\\t(self fullBounds containsPoint: aPoint) ifFalse:[^false].\\n\\t(self containsPoint: aPoint) ifTrue:[^true].\\n\\tself submorphsDo:[:m|\\n\\t\\t(m isLocked and:[m fullContainsPoint: \\n\\t\\t\\t((m transformedFrom: self) globalPointToLocal: aPoint)]) ifTrue:[^true]].\\n\\t^false! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 14:51'!\\ndefaultEventDispatcher\\n\\t\\\"Return the default event dispatcher to use with events that are directly sent to the receiver\\\"\\n\\t^MorphicEventDispatcher new! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 1/10/2001 21:35'!\\nhandleDropFiles: anEvent\\n\\t\\\"Handle a drop from the OS.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t(self wantsDropFiles: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself dropFiles: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'di 12/12/2000 14:39'!\\nhandleDropMorph: anEvent\\n\\t\\\"Handle a dropping morph.\\\"\\n\\t| aMorph localPt |\\n\\taMorph _ anEvent contents.\\n\\t\\\"Do a symmetric check if both morphs like each other\\\"\\n\\t((self wantsDroppedMorph: aMorph event: anEvent)\\t\\\"I want her\\\"\\n\\t\\tand: [aMorph wantsToBeDroppedInto: self])\\t\\t\\\"she wants me\\\"\\n\\t\\tifFalse: [aMorph removeProperty: #undoGrabCommand.\\n\\t\\t\\t\\t^ self].\\n\\tanEvent wasHandled: true.\\n\\t\\\"Transform the morph into the receiver's coordinate frame. This is currently incomplete since it only takes the offset into account where it really should take the entire transform.\\\"\\n\\tlocalPt _ (self transformedFrom: anEvent hand world) \\\"full transform down\\\"\\n\\t\\t\\t\\tglobalPointToLocal: aMorph referencePosition.\\n\\taMorph referencePosition: localPt.\\n\\tself acceptDroppingMorph: aMorph event: anEvent.\\n\\taMorph justDroppedInto: self event: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 21:13'!\\nhandleEvent: anEvent\\n\\t\\\"Handle the given event\\\"\\n\\t^anEvent sentTo: self.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/4/2000 18:48'!\\nhandleFocusEvent: anEvent\\n\\t\\\"Handle the given event. This message is sent if the receiver currently has the focus and is therefore receiving events directly from some hand.\\\"\\n\\t^self handleEvent: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 23:01'!\\nhandleKeyDown: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\t^self keyDown: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 23:01'!\\nhandleKeyUp: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\t^self keyUp: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'md 8/2/2006 18:57'!\\nhandleKeystroke: anEvent \\n\\t\\\"System level event handling.\\\"\\n\\t\\n\\tanEvent wasHandled\\n\\t\\tifTrue: [^ self].\\n\\t(self handlesKeyboard: anEvent)\\n\\t\\tifFalse: [^ self].\\n\\tanEvent wasHandled: true.\\n\\t^ self keyStroke: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/16/2000 14:22'!\\nhandleListenEvent: anEvent\\n\\t\\\"Handle the given event. This message is sent if the receiver is a registered listener for the given event.\\\"\\n\\t^anEvent sentTo: self.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'dgd 9/10/2004 13:36'!\\nhandleMouseDown: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent wasHandled: true.\\n\\n\\t(anEvent controlKeyPressed\\n\\t\\t\\tand: [Preferences cmdGesturesEnabled])\\n\\t\\tifTrue: [^ self invokeMetaMenu: anEvent].\\n\\n\\t\\\"Make me modal during mouse transitions\\\"\\n\\tanEvent hand newMouseFocus: self event: anEvent.\\n\\tanEvent blueButtonChanged ifTrue:[^self blueButtonDown: anEvent].\\n\\t\\n\\t\\\"this mouse down could be the start of a gesture, or the end of a gesture focus\\\"\\n\\t(self isGestureStart: anEvent)\\n\\t\\tifTrue: [^ self gestureStart: anEvent].\\n\\n\\tself mouseDown: anEvent.\\n\\n\\tPreferences maintainHalos\\n\\t\\tifFalse:[ anEvent hand removeHaloFromClick: anEvent on: self ].\\n\\n\\t(self handlesMouseStillDown: anEvent) ifTrue:[\\n\\t\\tself startStepping: #handleMouseStillDown: \\n\\t\\t\\tat: Time millisecondClockValue + self mouseStillDownThreshold\\n\\t\\t\\targuments: {anEvent copy resetHandlerFields}\\n\\t\\t\\tstepTime: self mouseStillDownStepRate ].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 8/8/2001 15:29'!\\nhandleMouseEnter: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\t(anEvent isDraggingEvent) ifTrue:[\\n\\t\\t(self handlesMouseOverDragging: anEvent) ifTrue:[\\n\\t\\t\\tanEvent wasHandled: true.\\n\\t\\t\\tself mouseEnterDragging: anEvent].\\n\\t\\t^self].\\n\\tself wantsHalo \\\"If receiver wants halo and balloon, trigger balloon after halo\\\"\\n\\t\\tifTrue:[anEvent hand triggerHaloFor: self after: self haloDelayTime]\\n\\t\\tifFalse:[self wantsBalloon\\n\\t\\t\\tifTrue:[anEvent hand triggerBalloonFor: self after: self balloonHelpDelayTime]].\\n\\t(self handlesMouseOver: anEvent) ifTrue:[\\n\\t\\tanEvent wasHandled: true.\\n\\t\\tself mouseEnter: anEvent.\\n\\t].! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/6/2000 00:15'!\\nhandleMouseLeave: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent isDraggingEvent ifTrue:[\\n\\t\\t(self handlesMouseOverDragging: anEvent) ifTrue:[\\n\\t\\t\\tanEvent wasHandled: true.\\n\\t\\t\\tself mouseLeaveDragging: anEvent].\\n\\t\\t^self].\\n\\t(self handlesMouseOver: anEvent) ifTrue:[\\n\\t\\tanEvent wasHandled: true.\\n\\t\\tself mouseLeave: anEvent.\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'nk 6/13/2004 09:16'!\\nhandleMouseMove: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t\\\"Rules say that by default a morph gets #mouseMove iff\\n\\t\\t* the hand is not dragging anything,\\n\\t\\t\\t+ and some button is down,\\n\\t\\t\\t+ and the receiver is the current mouse focus.\\\"\\n\\t(anEvent hand hasSubmorphs) ifTrue:[^self].\\n\\t(anEvent anyButtonPressed and:[anEvent hand mouseFocus == self]) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself mouseMove: anEvent.\\n\\t(self handlesMouseStillDown: anEvent) ifTrue:[\\n\\t\\t\\\"Step at the new location\\\"\\n\\t\\tself startStepping: #handleMouseStillDown: \\n\\t\\t\\tat: Time millisecondClockValue\\n\\t\\t\\targuments: {anEvent copy resetHandlerFields}\\n\\t\\t\\tstepTime: self mouseStillDownStepRate ].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 4/23/2001 17:24'!\\nhandleMouseOver: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent hand mouseFocus == self ifTrue:[\\n\\t\\t\\\"Got this directly through #handleFocusEvent: so check explicitly\\\"\\n\\t\\t(self containsPoint: anEvent position event: anEvent) ifFalse:[^self]].\\n\\tanEvent hand noticeMouseOver: self event: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/22/2000 17:11'!\\nhandleMouseStillDown: anEvent\\n\\t\\\"Called from the stepping mechanism for morphs wanting continuously repeated 'yes the mouse is still down, yes it is still down, yes it has not changed yet, no the mouse is still not up, yes the button is down' etc messages\\\"\\n\\t(anEvent hand mouseFocus == self) \\n\\t\\tifFalse:[^self stopSteppingSelector: #handleMouseStillDown:].\\n\\tself mouseStillDown: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/22/2000 17:09'!\\nhandleMouseUp: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand mouseFocus == self ifFalse:[^self]. \\\"Not interested in other parties\\\"\\n\\tanEvent hand releaseMouseFocus: self.\\n\\tanEvent wasHandled: true.\\n\\tanEvent blueButtonChanged\\n\\t\\tifTrue:[self blueButtonUp: anEvent]\\n\\t\\tifFalse:[self mouseUp: anEvent.\\n\\t\\t\\t\\tself stopSteppingSelector: #handleMouseStillDown:].! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'md 10/22/2003 15:55'!\\nhandleUnknownEvent: anEvent\\n\\t\\\"An event of an unknown type was sent to the receiver. What shall we do?!!\\\"\\n\\tBeeper beep. \\n\\tanEvent printString displayAt: 0@0.\\n\\tanEvent wasHandled: true.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'sw 10/5/2002 01:47'!\\nmouseDownPriority\\n\\t\\\"Return the default mouse down priority for the receiver\\\"\\n\\n\\t^ (self isPartsDonor or: [self isPartsBin])\\n\\t\\tifTrue:\\t[50]\\n\\t\\tifFalse:\\t[0]\\n\\n\\t\\\"The above is a workaround for the complete confusion between parts donors and parts bins. Morphs residing in a parts bin may or may not have the parts donor property set; if they have they may or may not actually handle events. To work around this, parts bins get an equal priority to parts donors so that when a morph in the parts bin does have the property set but does not handle the event we still get a copy from picking it up through the parts bin. Argh. This just *cries* for a cleanup.\\\"\\n\\t\\\"And the above comment is Andreas's from 10/2000, which was formerly retrievable by a #flag: call which however caused a problem when trying to recompile the method from decompiled source.\\\"! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 17:14'!\\nprocessEvent: anEvent\\n\\t\\\"Process the given event using the default event dispatcher.\\\"\\n\\t^self processEvent: anEvent using: self defaultEventDispatcher! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/18/2000 19:14'!\\nprocessEvent: anEvent using: defaultDispatcher\\n\\t\\\"This is the central entry for dispatching events in morphic. Given some event and a default dispatch strategy, find the right receiver and let him handle it.\\n\\tWARNING: This is a powerful hook. If you want to use a different event dispatcher from the default, here is the place to hook it in. Depending on how the dispatcher is written (e.g., whether it calls simply #processEvent: or #processEvent:using:) you can change the dispatch strategy for entire trees of morphs. Similarly, you can disable entire trees of morphs from receiving any events whatsoever. Read the documentation in class MorphicEventDispatcher before playing with it. \\\"\\n\\t(self rejectsEvent: anEvent) ifTrue:[^#rejected].\\n\\t^defaultDispatcher dispatchEvent: anEvent with: self! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/5/2000 19:25'!\\nrejectDropEvent: anEvent\\n\\t\\\"This hook allows the receiver to repel a drop operation currently executed. The method is called prior to checking children so the receiver must validate that the event was really designated for it.\\n\\tNote that the ordering of the tests below is designed to avoid a (possibly expensive) #fullContainsPoint: test. If the receiver doesn't want to repel the morph anyways we don't need to check after all.\\\"\\n\\t(self repelsMorph: anEvent contents event: anEvent) ifFalse:[^self]. \\\"not repelled\\\"\\n\\t(self fullContainsPoint: anEvent position) ifFalse:[^self]. \\\"not for me\\\"\\n\\t\\\"Throw it away\\\"\\n\\tanEvent wasHandled: true.\\n\\tanEvent contents rejectDropMorphEvent: anEvent.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/12/2000 23:40'!\\nrejectsEvent: anEvent\\n\\t\\\"Return true to reject the given event. Rejecting an event means neither the receiver nor any of it's submorphs will be given any chance to handle it.\\\"\\n\\t^self isLocked or:[self visible not]! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 21:09'!\\ntransformedFrom: uberMorph\\n\\t\\\"Return a transform to map coordinates of uberMorph, a morph above me in my owner chain, into the coordinates of MYSELF not any of my children.\\\"\\n\\tself flag: #arNote. \\\"rename this method\\\"\\n\\towner ifNil:[^IdentityTransform new].\\n\\t^ (owner transformFrom: uberMorph)! !\\n\\n\\n!Morph methodsFor: 'events-removing' stamp: 'rw 4/25/2002 07:18'!\\nreleaseActionMap\\n\\t\\\"Release the action map\\\"\\n\\t\\n \\tself removeProperty: #actionMap! !\\n\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 08:35'!\\nattachToResource\\n\\t\\\"Produce a morph from a file -- either a saved .morph file or a graphics file\\\"\\n\\n\\t| pathName |\\n\\tpathName _ Utilities chooseFileWithSuffixFromList: (#('.morph'), Utilities graphicsFileSuffixes)\\n\\t\\t\\twithCaption: 'Choose a file\\nto load'.\\n\\tpathName ifNil: [^ self]. \\\"User made no choice\\\"\\n\\tpathName == #none ifTrue: [^ self inform: \\n'Sorry, no suitable files found\\n(names should end with .morph, .gif,\\n.bmp, .jpeg, .jpe, .jp, or .form)'].\\n\\n\\tself setProperty: #resourceFilePath toValue: pathName! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tak 2/10/2006 02:24'!\\nprepareToBeSaved\\n\\t\\\"Prepare this morph to be saved to disk. Subclasses should nil out any instance variables that holds state that should not be saved, such as cached Forms. Note that this operation may take more drastic measures than releaseCachedState; for example, it might discard the transcript of an interactive chat session.\\\"\\n\\n\\tself releaseCachedState.\\n\\tself formerOwner: nil.\\n\\tself formerPosition: nil.\\n\\tself removeProperty: #undoGrabCommand.\\n\\tfullBounds _ nil! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 2/17/1999 17:50'!\\nreserveUrl: urlString\\n\\t\\\"Write a dummy object to the server to hold a name and place for this object.\\\"\\n\\n\\t| dummy ext str |\\n\\tdummy _ PasteUpMorph new.\\n\\tdummy borderWidth: 2.\\n\\tdummy setProperty: #initialExtent toValue: (ext _ 300@100).\\n\\tdummy topLeft: 50@50; extent: ext.\\t\\\"reset when comes in\\\"\\n\\tstr _ (TextMorph new) topLeft: dummy topLeft + (10@10); \\n\\t\\textent: dummy width - 15 @ 30.\\n\\tdummy addMorph: str.\\n\\tstr contents: 'This is a place holder only. Please \\\\find the original page and choose \\\\\\\"send this page to server\\\"' withCRs.\\n\\tstr extent: dummy width - 15 @ 30.\\n\\tdummy saveOnURL: urlString.\\n\\n\\t\\\"Claim that url myself\\\"\\n\\tself setProperty: #SqueakPage toValue: dummy sqkPage.\\n\\t(dummy sqkPage) contentsMorph: self; dirty: true.\\n\\t^ self url! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 08:52'!\\nsaveAsResource\\n\\n\\t| pathName |\\n\\t(self hasProperty: #resourceFilePath) ifFalse: [^ self].\\n\\tpathName _ self valueOfProperty: #resourceFilePath.\\n\\t(pathName asLowercase endsWith: '.morph') ifFalse:\\n\\t\\t[^ self error: 'Can only update morphic resources'].\\n\\t(FileStream newFileNamed: pathName) fileOutClass: nil andObject: self.! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'ar 9/27/2005 21:02'!\\nsaveDocPane\\n\\n\\tSmalltalk at: #DocLibrary ifPresent:[:dl| dl external saveDocCheck: self]! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'yo 7/2/2004 13:14'!\\nsaveOnFile\\n\\t\\\"Ask the user for a filename and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| aFileName fileStream ok |\\n\\taFileName _ ('my {1}' translated format: {self class name}) asFileName.\\t\\\"do better?\\\"\\n\\taFileName _ FillInTheBlank request: 'File name? (\\\".morph\\\" will be added to end)' translated \\n\\t\\t\\tinitialAnswer: aFileName.\\n\\taFileName isEmpty ifTrue: [^ Beeper beep].\\n\\tself allMorphsDo: [:m | m prepareToBeSaved].\\n\\n\\tok _ aFileName endsWith: '.morph'.\\t\\\"don't double them\\\"\\n\\tok _ ok | (aFileName endsWith: '.sp').\\n\\tok ifFalse: [aFileName _ aFileName,'.morph'].\\n\\tfileStream _ FileStream newFileNamed: aFileName asFileName.\\n\\tfileStream fileOutClass: nil andObject: self.\\t\\\"Puts UniClass definitions out anyway\\\"! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 7/16/1999 13:03'!\\nsaveOnURL\\n\\t\\\"Ask the user for a url and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| um pg |\\n\\t(pg _ self saveOnURLbasic) == #cancel ifTrue: [^ self].\\n\\tum _ URLMorph newForURL: pg url.\\n\\tum setURL: pg url page: pg.\\n\\tpg isContentsInMemory ifTrue: [pg computeThumbnail].\\n\\tum isBookmark: true.\\n\\tum removeAllMorphs.\\n\\tum color: Color transparent.\\n\\tself primaryHand attachMorph: um.! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'dgd 2/22/2003 14:35'!\\nsaveOnURLbasic\\n\\t\\\"Ask the user for a url and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| url pg stamp pol |\\n\\t(pg := self valueOfProperty: #SqueakPage) ifNil: [pg := SqueakPage new]\\n\\t\\tifNotNil: \\n\\t\\t\\t[pg contentsMorph ~~ self \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self inform: 'morph''s SqueakPage property is out of date'.\\n\\t\\t\\t\\t\\tpg := SqueakPage new]].\\n\\t(url := pg url) ifNil: \\n\\t\\t\\t[url := ServerDirectory defaultStemUrl , '1.sp'.\\t\\\"A new legal place\\\"\\n\\t\\t\\turl := FillInTheBlank \\n\\t\\t\\t\\t\\t\\trequest: 'url of a place to store this object.\\nMust begin with file:// or ftp://'\\n\\t\\t\\t\\t\\t\\tinitialAnswer: url.\\n\\t\\t\\turl isEmpty ifTrue: [^#cancel]].\\n\\tstamp := Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: self author: stamp.\\n\\tSqueakPageCache atURL: url put: pg.\\t\\\"setProperty: #SqueakPage\\\"\\n\\t(pol := pg policy) ifNil: [pol := #neverWrite].\\n\\tpg\\n\\t\\tpolicy: #now;\\n\\t\\tdirty: true.\\n\\tpg write.\\t\\\"force the write\\\"\\n\\tpg policy: pol.\\n\\t^pg! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 11/20/1998 11:47'!\\nsaveOnURL: suggestedUrlString\\n\\t\\\"Save myself on a SmartReferenceStream file. If I don't already have a url, use the suggested one. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| url pg stamp pol |\\n\\t(pg _ self valueOfProperty: #SqueakPage) ifNil: [pg _ SqueakPage new]\\n\\t\\tifNotNil: [pg contentsMorph ~~ self ifTrue: [\\n\\t\\t\\t\\tself inform: 'morph''s SqueakPage property is out of date'.\\n\\t\\t\\t\\tpg _ SqueakPage new]].\\n\\t(url _ pg url) ifNil: [url _ pg urlNoOverwrite: suggestedUrlString].\\n\\tstamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: self author: stamp.\\n\\tSqueakPageCache atURL: url put: pg.\\t\\\"setProperty: #SqueakPage\\\"\\n\\t(pol _ pg policy) ifNil: [pol _ #neverWrite].\\n\\tpg policy: #now; dirty: true. pg write.\\t\\\"force the write\\\"\\n\\tpg policy: pol.\\n\\t^ pg! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 09:15'!\\nupdateAllFromResources\\n\\n\\tself allMorphsDo: [:m | m updateFromResource]! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'nk 1/6/2004 12:38'!\\nupdateFromResource\\n\\t| pathName newMorph f |\\n\\t(pathName := self valueOfProperty: #resourceFilePath) ifNil: [^self].\\n\\t(pathName asLowercase endsWith: '.morph') \\n\\t\\tifTrue: \\n\\t\\t\\t[newMorph := (FileStream readOnlyFileNamed: pathName) fileInObjectAndCode.\\n\\t\\t\\t(newMorph isMorph) \\n\\t\\t\\t\\tifFalse: [^self error: 'Resource not a single morph']]\\n\\t\\tifFalse: \\n\\t\\t\\t[f := Form fromFileNamed: pathName.\\n\\t\\t\\tf ifNil: [^self error: 'unrecognized image file format'].\\n\\t\\t\\tnewMorph := World drawingClass withForm: f].\\n\\tnewMorph setProperty: #resourceFilePath toValue: pathName.\\n\\tself owner replaceSubmorph: self by: newMorph! !\\n\\n\\n!Morph methodsFor: 'filter streaming' stamp: 'ar 10/26/2000 19:55'!\\ndrawOnCanvas: aCanvas\\n\\t^aCanvas fullDraw: self.\\n! !\\n\\n\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 7/24/97 11:55'!\\nalign: aPoint1 with: aPoint2\\n\\t\\\"Translate by aPoint2 - aPoint1.\\\"\\n\\n\\t^ self position: self position + (aPoint2 - aPoint1)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:17'!\\nbottom\\n\\t\\\" Return the y-coordinate of my bottom side \\\"\\n\\n\\t^ bounds bottom! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nbottomCenter\\n\\n\\t^ bounds bottomCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'tk 9/8/97 10:44'!\\nbottomLeft\\n\\n\\t^ bounds bottomLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:08'!\\nbottomLeft: aPoint\\n\\t\\\" Move me so that my bottom left corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x) @ (aPoint y - self height)).\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 6/12/97 11:17'!\\nbottomRight\\n\\n\\t^ bounds bottomRight! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:09'!\\nbottomRight: aPoint\\n\\t\\\" Move me so that my bottom right corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x - bounds width) @ (aPoint y - self height))\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:14'!\\nbottom: aNumber\\n\\t\\\" Move me so that my bottom is at the y-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (bounds left @ (aNumber - self height))! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'jm 8/3/97 15:50'!\\nbounds\\n\\t\\\"Return the bounds of this morph.\\\"\\n\\t\\\"Note: It is best not to override this method because many methods in Morph and its subclasses use the instance variable directly rather than 'self bounds'. Instead, subclasses should be sure that the bounds instance variable is correct.\\\"\\n\\n\\t^ bounds\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:05'!\\nboundsInWorld\\n\\t^self bounds: self bounds in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nboundsIn: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\t^self bounds: self bounds in: referenceMorph! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 12/14/2000 13:48'!\\nbounds: newBounds\\n\\t| oldExtent newExtent |\\n\\toldExtent _ self extent.\\n\\tnewExtent _ newBounds extent.\\n\\t(oldExtent dotProduct: oldExtent) <= (newExtent dotProduct: newExtent) ifTrue:[\\n\\t\\t\\\"We're growing. First move then resize.\\\"\\n\\t\\tself position: newBounds topLeft; extent: newExtent.\\n\\t] ifFalse:[\\n\\t\\t\\\"We're shrinking. First resize then move.\\\"\\n\\t\\tself extent: newExtent; position: newBounds topLeft.\\n\\t].! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nbounds: aRectangle from: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\towner ifNil: [^ aRectangle].\\n\\t^(owner transformFrom: referenceMorph) globalBoundsToLocal: aRectangle\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nbounds: aRectangle in: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\towner ifNil: [^ aRectangle].\\n\\t^(owner transformFrom: referenceMorph) localBoundsToGlobal: aRectangle\\n! !\\n\\n!Morph methodsFor: 'geometry'!\\ncenter\\n\\n\\t^ bounds center! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/11/1999 18:48'!\\ncenter: aPoint\\n\\tself position: (aPoint - (self extent // 2))! !\\n\\n!Morph methodsFor: 'geometry'!\\nextent\\n\\n\\t^ bounds extent! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'laza 3/25/2004 21:31'!\\nextent: aPoint\\n\\n\\tbounds extent = aPoint ifTrue: [^ self].\\n\\tself changed.\\n\\tbounds _ (bounds topLeft extent: aPoint) rounded.\\n\\tself layoutChanged.\\n\\tself changed.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:06'!\\nfullBoundsInWorld\\n\\t^self bounds: self fullBounds in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:06'!\\nglobalPointToLocal: aPoint\\n\\t^self point: aPoint from: nil! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 9/15/2000 14:21'!\\ngriddedPoint: ungriddedPoint\\n\\n\\t| griddingContext |\\n\\tself flag: #arNote. \\\"Used by event handling - should transform to pasteUp for gridding\\\"\\n\\t(griddingContext _ self pasteUpMorph) ifNil: [^ ungriddedPoint].\\n\\t^ griddingContext gridPoint: ungriddedPoint! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 8/25/2000 00:35'!\\ngridPoint: ungriddedPoint\\n\\n\\t^ ungriddedPoint! !\\n\\n!Morph methodsFor: 'geometry'!\\nheight\\n\\n\\t^ bounds height! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:22'!\\nheight: aNumber\\n\\t\\\" Set my height; my position (top-left corner) and width will remain the same \\\"\\n\\n\\tself extent: self width@aNumber asInteger.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 12/22/2001 22:43'!\\ninnerBounds\\n\\t\\\"Return the inner rectangle enclosed by the bounds of this morph excluding the space taken by its borders. For an unbordered morph, this is just its bounds.\\\"\\n\\n\\t^ self bounds insetBy: self borderWidth! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:16'!\\nleft\\n\\t\\\" Return the x-coordinate of my left side \\\"\\n\\n\\t^ bounds left! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nleftCenter\\n\\n\\t^ bounds leftCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:15'!\\nleft: aNumber\\n\\t\\\" Move me so that my left side is at the x-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (aNumber @ bounds top)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:07'!\\nlocalPointToGlobal: aPoint\\n\\t^self point: aPoint in: nil! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/4/2000 21:59'!\\nminimumExtent\\n\\t| ext |\\n\\t\\\"This returns the minimum extent that the morph may be shrunk to. Not honored in too many places yet, but respected by the resizeToFit feature, at least. copied up from SystemWindow 6/00\\\"\\n\\t(ext _ self valueOfProperty: #minimumExtent)\\n\\t\\tifNotNil:\\n\\t\\t\\t[^ ext].\\n\\t^ 100 @ 80! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/4/2000 22:00'!\\nminimumExtent: aPoint\\n\\t\\\"Remember a minimumExtent, for possible future use\\\"\\n\\n\\tself setProperty: #minimumExtent toValue: aPoint\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 7/10/1999 17:26'!\\nnextOwnerPage\\n\\t\\\"Tell my container to advance to the next page\\\"\\n\\t| targ |\\n\\ttarg _ self ownerThatIsA: BookMorph.\\n\\ttarg ifNotNil: [targ nextPage]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 11/12/2000 22:06'!\\nouterBounds\\n\\t\\\"Return the 'outer' bounds of the receiver, e.g., the bounds that need to be invalidated when the receiver changes.\\\"\\n\\t| box |\\n\\tbox _ self bounds.\\n\\tself hasDropShadow ifTrue:[box _ self expandFullBoundsForDropShadow: box].\\n\\tself hasRolloverBorder ifTrue:[box _ self expandFullBoundsForRolloverBorder: box].\\n\\t^box! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'nk 5/19/2003 20:39'!\\noverlapsShadowForm: itsShadow bounds: itsBounds\\n\\t\\\"Answer true if itsShadow and my shadow overlap at all\\\"\\n\\t| andForm overlapExtent |\\n\\toverlapExtent _ (itsBounds intersect: self fullBounds) extent.\\n\\toverlapExtent > (0 @ 0)\\n\\t\\tifFalse: [^ false].\\n\\tandForm _ self shadowForm.\\n\\toverlapExtent ~= self fullBounds extent\\n\\t\\tifTrue: [andForm _ andForm\\n\\t\\t\\t\\t\\t\\tcontentsOfArea: (0 @ 0 extent: overlapExtent)].\\n\\tandForm _ andForm\\n\\t\\t\\t\\tcopyBits: (self fullBounds translateBy: itsShadow offset negated)\\n\\t\\t\\t\\tfrom: itsShadow\\n\\t\\t\\t\\tat: 0 @ 0\\n\\t\\t\\t\\tclippingBox: (0 @ 0 extent: overlapExtent)\\n\\t\\t\\t\\trule: Form and\\n\\t\\t\\t\\tfillColor: nil.\\n\\t^ andForm bits\\n\\t\\tanySatisfy: [:w | w ~= 0]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:02'!\\npointFromWorld: aPoint\\n\\t^self point: aPoint from: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:03'!\\npointInWorld: aPoint\\n\\t^self point: aPoint in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:01'!\\npoint: aPoint from: aReferenceMorph\\n\\n\\towner ifNil: [^ aPoint].\\n\\t^ (owner transformFrom: aReferenceMorph) globalPointToLocal: aPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:01'!\\npoint: aPoint in: aReferenceMorph\\n\\n\\towner ifNil: [^ aPoint].\\n\\t^ (owner transformFrom: aReferenceMorph) localPointToGlobal: aPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry'!\\nposition\\n\\n\\t^ bounds topLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 9/30/1998 12:11'!\\npositionInWorld\\n\\n\\t^ self pointInWorld: self position.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 10/9/1998 08:56'!\\npositionSubmorphs\\n\\tself submorphsDo:\\n\\t\\t[:aMorph | aMorph snapToEdgeIfAppropriate]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'wiz 11/25/2004 12:54'!\\nposition: aPoint \\n\\t\\\"Change the position of this morph and and all of its\\n\\tsubmorphs. \\\"\\n\\t| delta box |\\n\\tdelta := aPoint asNonFractionalPoint - bounds topLeft.\\n\\t(delta x = 0\\n\\t\\t\\tand: [delta y = 0])\\n\\t\\tifTrue: [^ self].\\n\\t\\\"Null change\\\"\\n\\tbox := self fullBounds.\\n\\t(delta dotProduct: delta)\\n\\t\\t\\t> 100\\n\\t\\tifTrue: [\\\"e.g., more than 10 pixels moved\\\"\\n\\t\\t\\tself invalidRect: box.\\n\\t\\t\\tself\\n\\t\\t\\t\\tinvalidRect: (box translateBy: delta)]\\n\\t\\tifFalse: [self\\n\\t\\t\\t\\tinvalidRect: (box\\n\\t\\t\\t\\t\\t\\tmerge: (box translateBy: delta))].\\n\\tself privateFullMoveBy: delta.\\n\\towner\\n\\t\\tifNotNil: [owner layoutChanged]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 7/10/1999 17:27'!\\npreviousOwnerPage\\n\\t\\\"Tell my container to advance to the previous page\\\"\\n\\t| targ |\\n\\ttarg _ self ownerThatIsA: BookMorph.\\n\\ttarg ifNotNil: [targ previousPage]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:16'!\\nright\\n\\t\\\" Return the x-coordinate of my right side \\\"\\n\\t^ bounds right! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nrightCenter\\n\\n\\t^ bounds rightCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:15'!\\nright: aNumber\\n\\t\\\" Move me so that my right side is at the x-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aNumber - bounds width) @ bounds top)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'bf 1/5/2000 19:08'!\\nscreenLocation\\n\\t\\\"For compatibility only\\\"\\n\\n\\t^ self fullBounds origin! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sma 2/5/2000 13:58'!\\nscreenRectangle\\n\\t\\\"For compatibility only\\\"\\n\\n\\t^ self fullBounds! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'tk 7/14/2001 11:11'!\\nsetConstrainedPosition: aPoint hangOut: partiallyOutside\\n\\t\\\"Change the position of this morph and and all of its submorphs to aPoint, but don't let me go outside my owner's bounds. Let me go within two pixels of completely outside if partiallyOutside is true.\\\"\\n\\n\\t| trialRect delta boundingMorph bRect |\\n\\towner ifNil:[^self].\\n\\ttrialRect _ aPoint extent: self bounds extent.\\n\\tboundingMorph _ self topRendererOrSelf owner.\\n\\tdelta _ boundingMorph\\n\\t\\t\\tifNil: [0@0]\\n\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\tbRect _ partiallyOutside \\n\\t\\t\\t\\t\\tifTrue: [boundingMorph bounds insetBy: \\n\\t\\t\\t\\t\\t\\t\\t\\tself extent negated + boundingMorph borderWidth + (2@2)]\\n\\t\\t\\t\\t\\tifFalse: [boundingMorph bounds].\\n\\t\\t\\t\\ttrialRect amountToTranslateWithin: bRect].\\n\\tself position: aPoint + delta.\\n\\tself layoutChanged \\\"So that, eg, surrounding text will readjust\\\"\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 2/16/1999 22:05'!\\nshiftSubmorphsOtherThan: listNotToShift by: delta\\n\\t| rejectList |\\n\\trejectList _ listNotToShift ifNil: [OrderedCollection new].\\n\\t(submorphs copyWithoutAll: rejectList) do:\\n\\t\\t[:m | m position: (m position + delta)]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:17'!\\ntop\\n\\t\\\" Return the y-coordinate of my top side \\\"\\n\\n\\t^ bounds top! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\ntopCenter\\n\\n\\t^ bounds topCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 6/12/97 11:07'!\\ntopLeft\\n\\n\\t^ bounds topLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:10'!\\ntopLeft: aPoint\\n\\t\\\" Move me so that my top left corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: aPoint\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 8/20/97 23:04'!\\ntopRight\\n\\n\\t^ bounds topRight! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:12'!\\ntopRight: aPoint\\n\\t\\\" Move me so that my top right corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x - bounds width) @ (aPoint y))\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:14'!\\ntop: aNumber\\n\\t\\\" Move me so that my top is at the y-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (bounds left @ aNumber)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/22/2000 18:03'!\\ntransformedBy: aTransform\\n\\taTransform isIdentity ifTrue:[^self].\\n\\taTransform isPureTranslation ifTrue:[\\n\\t\\t^self position: (aTransform localPointToGlobal: self position).\\n\\t].\\n\\t^self addFlexShell transformedBy: aTransform! !\\n\\n!Morph methodsFor: 'geometry'!\\nwidth\\n\\n\\t^ bounds width! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:22'!\\nwidth: aNumber\\n\\t\\\" Set my width; my position (top-left corner) and height will remain the same \\\"\\n\\n\\tself extent: aNumber asInteger@self height.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 2/23/98 11:36'!\\nworldBounds\\n\\t^ self world bounds! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'dgd 9/10/2004 12:37'!\\nworldBoundsForHalo\\n\\t\\\"Answer the rectangle to be used as the inner dimension of my halos.\\n\\tAllow for showing either bounds or fullBounds, and compensate for the optional bounds rectangle.\\\"\\n\\n\\t| r |\\n\\tr _ (Preferences haloEnclosesFullBounds)\\n\\t\\tifFalse: [ self boundsIn: nil ]\\n\\t\\tifTrue: [ self fullBoundsInWorld ].\\n\\tPreferences showBoundsInHalo ifTrue: [ ^r outsetBy: 2 ].\\n\\t^r! !\\n\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 12:00'!\\naddTransparentSpacerOfSize: aPoint\\n\\tself addMorphBack: (self transparentSpacerOfSize: aPoint)! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 12:01'!\\nbeTransparent\\n\\tself color: Color transparent! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'RAA 11/8/2000 18:29'!\\ncartesianBoundsTopLeft\\n\\t\\\"Answer the origin of this morph relative to it's container's cartesian origin. \\n\\tNOTE: y DECREASES toward the bottom of the screen\\\"\\n\\n\\t| w container |\\n\\n\\tw _ self world ifNil: [^ bounds origin].\\n\\tcontainer _ self referencePlayfield ifNil: [w].\\n\\t^ (bounds left - container cartesianOrigin x) @\\n\\t\\t(container cartesianOrigin y - bounds top)! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 1/17/2000 20:55'!\\ncartesianXY: coords\\n\\t^ self x: coords x y: coords y\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 9/9/1998 22:49'!\\ncolorUnder\\n\\t\\\"Return the color of under the receiver's center.\\\"\\n\\n\\tself isInWorld\\n\\t\\tifTrue: [^ self world colorAt: (self pointInWorld: self referencePosition) belowMorph: self]\\n\\t\\tifFalse: [^ Color black].\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 7/7/2003 17:18'!\\ncolor: sensitiveColor sees: soughtColor \\n\\t\\\"Return true if any of my pixels of sensitiveColor intersect with pixels of soughtColor.\\\"\\n\\n\\t\\\"Make a mask with black where sensitiveColor is, white elsewhere\\\"\\n\\n\\t| myImage sensitivePixelMask map patchBelowMe tfm morphAsFlexed i1 pasteUp |\\n\\tpasteUp _ self world ifNil: [ ^false ].\\n\\ttfm := self transformFrom: pasteUp.\\n\\tmorphAsFlexed := tfm isIdentity \\n\\t\\t\\t\\tifTrue: [self]\\n\\t\\t\\t\\tifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].\\n\\tmyImage := morphAsFlexed imageForm offset: 0 @ 0.\\n\\tsensitivePixelMask := Form extent: myImage extent depth: 1.\\n\\t\\\"ensure at most a 16-bit map\\\"\\n\\tmap := Bitmap new: (1 bitShift: (myImage depth - 1 min: 15)).\\n\\tmap at: (i1 := sensitiveColor indexInMap: map) put: 1.\\n\\tsensitivePixelMask \\n\\t\\tcopyBits: sensitivePixelMask boundingBox\\n\\t\\tfrom: myImage form\\n\\t\\tat: 0 @ 0\\n\\t\\tcolorMap: map.\\n\\n\\t\\\"get an image of the world below me\\\"\\n\\tpatchBelowMe := pasteUp \\n\\t\\t\\t\\tpatchAt: morphAsFlexed fullBounds\\n\\t\\t\\t\\twithout: self\\n\\t\\t\\t\\tandNothingAbove: false.\\n\\t\\\"\\nsensitivePixelMask displayAt: 0@0.\\npatchBelowMe displayAt: 100@0.\\n\\\"\\n\\t\\\"intersect world pixels of the color we're looking for with the sensitive pixels\\\"\\n\\tmap at: i1 put: 0.\\t\\\"clear map and reuse it\\\"\\n\\tmap at: (soughtColor indexInMap: map) put: 1.\\n\\tsensitivePixelMask \\n\\t\\tcopyBits: patchBelowMe boundingBox\\n\\t\\tfrom: patchBelowMe\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: patchBelowMe boundingBox\\n\\t\\trule: Form and\\n\\t\\tfillColor: nil\\n\\t\\tmap: map.\\n\\t\\\"\\nsensitivePixelMask displayAt: 200@0.\\n\\\"\\n\\t^(sensitivePixelMask tallyPixelValues second) > 0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 10/1/2000 11:54'!\\ndegreesOfFlex\\n\\t\\\"Return any rotation due to flexing\\\"\\n\\t\\\"NOTE: because renderedMorph, which is used by the halo to set heading, goes down through dropShadows as well as transformations, we need this method (and its other implems) to come back up through such a chain.\\\"\\n\\t^ 0.0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 14:29'!\\nforwardDirection: newDirection\\n\\t\\\"Set the receiver's forward direction (in eToy terms)\\\"\\n\\tself setProperty: #forwardDirection toValue: newDirection.! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 9/8/2000 16:35'!\\ngetIndexInOwner\\n\\t\\\"Answer which position the receiver holds in its owner's hierarchy\\\"\\n\\n\\t\\\"NB: There is some concern about submorphs that aren't really to be counted, such as a background morph of a playfield.\\\"\\n\\n\\t| container topRenderer |\\n\\tcontainer _ (topRenderer _ self topRendererOrSelf) owner.\\n\\t^ container submorphIndexOf: topRenderer.! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 9/20/2004 14:15'!\\ngoHome\\n\\t| box fb |\\n\\towner isInMemory ifFalse: [^ self].\\n\\towner isNil ifTrue: [^ self].\\n\\tself visible ifFalse: [^ self].\\n\\n\\tbox := owner visibleClearArea.\\n\\tfb := self fullBounds.\\n\\n\\tfb left < box left\\n\\t\\tifTrue: [self left: box left - fb left + self left].\\n\\tfb right > box right\\n\\t\\tifTrue: [self right: box right - fb right + self right].\\n\\n\\tfb top < box top\\n\\t\\tifTrue: [self top: box top - fb top + self top].\\n\\tfb bottom > box bottom\\n\\t\\tifTrue: [self bottom: box bottom - fb bottom + self bottom].\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 10/1/2000 11:50'!\\nheading\\n\\t\\\"Return the receiver's heading (in eToy terms)\\\"\\n\\towner ifNil: [^ self forwardDirection].\\n\\t^ self forwardDirection + owner degreesOfFlex! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 13:37'!\\nheading: newHeading\\n\\t\\\"Set the receiver's heading (in eToy terms)\\\"\\n\\tself isFlexed ifFalse:[self addFlexShell].\\n\\towner rotationDegrees: (newHeading - self forwardDirection).! !\\n\\n!Morph methodsFor: 'geometry eToy'!\\nmove: aMorph toPosition: aPointOrNumber\\n\\t\\\"Support for e-toy demo. Move the given submorph to the given position. Allows the morph's owner to determine the policy for motion. For example, moving forward through a table might mean motion only in the x-axis with wrapping modulo the table size.\\\"\\n\\n\\taMorph position: aPointOrNumber asPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:12'!\\nreferencePosition\\n\\t\\\"Return the current reference position of the receiver\\\"\\n\\t| box |\\n\\tbox _ self bounds.\\n\\t^box origin + (self rotationCenter * box extent).\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/25/1999 16:49'!\\nreferencePositionInWorld\\n\\n\\t^ self pointInWorld: self referencePosition\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/25/1999 23:33'!\\nreferencePositionInWorld: aPoint\\n\\t| localPosition |\\n\\tlocalPosition _ owner\\n\\t\\tifNil: [aPoint]\\n\\t\\tifNotNil: [(owner transformFrom: self world) globalPointToLocal: aPoint].\\n\\n\\tself referencePosition: localPosition\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/27/2000 14:04'!\\nreferencePosition: aPosition\\n\\t\\\"Move the receiver to match its reference position with aPosition\\\"\\n\\t| newPos intPos |\\n\\tnewPos _ self position + (aPosition - self referencePosition).\\n\\tintPos _ newPos asIntegerPoint.\\n\\tnewPos = intPos \\n\\t\\tifTrue:[self position: intPos]\\n\\t\\tifFalse:[self position: newPos].! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:10'!\\nrotationCenter\\n\\t\\\"Return the rotation center of the receiver. The rotation center defines the relative offset inside the receiver's bounds for locating the reference position.\\\"\\n\\t^self valueOfProperty: #rotationCenter ifAbsent:[0.5@0.5]\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:11'!\\nrotationCenter: aPointOrNil\\n\\t\\\"Set the new rotation center of the receiver. The rotation center defines the relative offset inside the receiver's bounds for locating the reference position.\\\"\\n\\taPointOrNil isNil\\n\\t\\tifTrue:[self removeProperty: #rotationCenter]\\n\\t\\tifFalse:[self setProperty: #rotationCenter toValue: aPointOrNil]\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 9/4/2004 11:04'!\\nscaleFactor: newScale \\n\\t\\\"Backstop for morphs that don't have to do something special to set their \\n\\tscale \\\"\\n\\t| toBeScaled |\\n\\ttoBeScaled := self.\\n\\tnewScale = 1.0\\n\\t\\tifTrue: [(self heading isZero\\n\\t\\t\\t\\t\\tand: [self isFlexMorph])\\n\\t\\t\\t\\tifTrue: [toBeScaled := self removeFlexShell]]\\n\\t\\tifFalse: [self isFlexMorph\\n\\t\\t\\t\\tifFalse: [toBeScaled := self addFlexShellIfNecessary]].\\n\\n\\ttoBeScaled scale: newScale.\\n\\n\\ttoBeScaled == self ifTrue: [\\n\\t\\tnewScale = 1.0\\n\\t\\t\\tifTrue: [ self removeProperty: #scaleFactor ]\\n\\t\\t\\tifFalse: [ self setProperty: #scaleFactor toValue: newScale ]]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 9/4/2004 11:00'!\\nscale: newScale\\n\\t\\\"Backstop for morphs that don't have to do something special to set their scale\\\"\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 6/12/2001 05:23'!\\nsetDirectionFrom: aPoint\\n\\t| delta degrees |\\n\\tdelta _ (self transformFromWorld globalPointToLocal: aPoint) - self referencePosition.\\n\\tdegrees _ delta degrees + 90.0.\\n\\tself forwardDirection: (degrees \\\\\\\\ 360) rounded.\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 8/31/2000 11:18'!\\nsetIndexInOwner: anInteger\\n\\t\\\"Answer which position the receiver holds in its owner's hierarchy\\\"\\n\\n\\t\\\"There is some concern about submorphs that aren't really to be counted, such as a background morph of a playfield.\\\"\\n\\t| container topRenderer indexToUse |\\n\\tcontainer _ (topRenderer _ self topRendererOrSelf) owner.\\n\\tindexToUse _ (anInteger min: container submorphCount) max: 1.\\n\\tcontainer addMorph: topRenderer asElementNumber: indexToUse! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'wiz 11/6/2005 17:10'!\\nsimplySetVisible: aBoolean\\n\\t\\\"Set the receiver's visibility property. This mild circumlocution is because my TransfomationMorph #visible: method would also set the visibility flag of my flexee, which in this case is pointless because it's the flexee that calls this.\\n\\tThis appears in morph as a backstop for morphs that don't inherit from TFMorph\\\"\\n\\n\\tself visible: aBoolean! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 7/7/2003 17:19'!\\ntouchesColor: soughtColor \\n\\t\\\"Return true if any of my pixels overlap pixels of soughtColor.\\\"\\n\\n\\t\\\"Make a shadow mask with black in my shape, white elsewhere\\\"\\n\\n\\t| map patchBelowMe shadowForm tfm morphAsFlexed pasteUp |\\n\\tpasteUp := self world ifNil: [ ^false ].\\n\\n\\ttfm := self transformFrom: pasteUp.\\n\\tmorphAsFlexed := tfm isIdentity \\n\\t\\t\\t\\tifTrue: [self]\\n\\t\\t\\t\\tifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].\\n\\tshadowForm := morphAsFlexed shadowForm offset: 0 @ 0.\\n\\n\\t\\\"get an image of the world below me\\\"\\n\\tpatchBelowMe := (pasteUp \\n\\t\\t\\t\\tpatchAt: morphAsFlexed fullBounds\\n\\t\\t\\t\\twithout: self\\n\\t\\t\\t\\tandNothingAbove: false) offset: 0 @ 0.\\n\\t\\\"\\nshadowForm displayAt: 0@0.\\npatchBelowMe displayAt: 100@0.\\n\\\"\\n\\t\\\"intersect world pixels of the color we're looking for with our shape.\\\"\\n\\t\\\"ensure a maximum 16-bit map\\\"\\n\\tmap := Bitmap new: (1 bitShift: (patchBelowMe depth - 1 min: 15)).\\n\\tmap at: (soughtColor indexInMap: map) put: 1.\\n\\tshadowForm \\n\\t\\tcopyBits: patchBelowMe boundingBox\\n\\t\\tfrom: patchBelowMe\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: patchBelowMe boundingBox\\n\\t\\trule: Form and\\n\\t\\tfillColor: nil\\n\\t\\tmap: map.\\n\\t\\\"\\nshadowForm displayAt: 200@0.\\n\\\"\\n\\t^(shadowForm tallyPixelValues second) > 0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 11:50'!\\ntransparentSpacerOfSize: aPoint\\n\\t^ (Morph new extent: aPoint) color: Color transparent! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'tk 7/8/1998 23:47'!\\nwrap\\n\\n\\t| myBox box newX newY wrapped |\\n\\towner ifNil: [^ self].\\n\\tmyBox _ self fullBounds.\\n\\tmyBox corner < (50000@50000) ifFalse: [\\n\\t\\tself inform: 'Who is trying to wrap a hidden object?'. ^ self].\\n\\tbox _ owner bounds.\\n\\tnewX _ self position x.\\n\\tnewY _ self position y.\\n\\twrapped _ false.\\n\\t((myBox right < box left) or: [myBox left > box right]) ifTrue: [\\n\\t\\tnewX _ box left + ((self position x - box left) \\\\\\\\ box width).\\n\\t\\twrapped _ true].\\n\\t((myBox bottom < box top) or: [myBox top > box bottom]) ifTrue: [\\n\\t\\tnewY _ box top + ((self position y - box top) \\\\\\\\ box height).\\n\\t\\twrapped _ true].\\n\\tself position: newX@newY.\\n\\t(wrapped and: [owner isPlayfieldLike])\\n\\t\\tifTrue: [owner changed]. \\\"redraw all turtle trails if wrapped\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 2/22/2003 14:37'!\\nx\\n\\t\\\"Return my horizontal position relative to the cartesian origin of a relevant playfield\\\"\\n\\n\\t| aPlayfield |\\n\\taPlayfield := self referencePlayfield.\\n\\t^aPlayfield isNil \\n\\t\\tifTrue: [self referencePosition x]\\n\\t\\tifFalse: [self referencePosition x - aPlayfield cartesianOrigin x]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'aoy 2/17/2003 01:00'!\\nx: aNumber \\n\\t\\\"Set my horizontal position relative to the cartesian origin of the playfield or the world.\\\"\\n\\n\\t| offset aPlayfield newX |\\n\\taPlayfield := self referencePlayfield.\\n\\toffset := self left - self referencePosition x.\\n\\tnewX := aPlayfield isNil\\n\\t\\t\\t\\tifTrue: [aNumber + offset]\\n\\t\\t\\t\\tifFalse: [aPlayfield cartesianOrigin x + aNumber + offset].\\n\\tself position: newX @ bounds top! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 1/17/2000 20:04'!\\nx: xCoord y: yCoord\\n\\t| aWorld xyOffset delta aPlayfield |\\n\\t(aWorld _ self world) ifNil: [^ self position: xCoord @ yCoord].\\n\\txyOffset _ self topLeft - self referencePosition.\\n\\tdelta _ (aPlayfield _ self referencePlayfield)\\n\\t\\tifNil:\\n\\t\\t\\t[xCoord @ (aWorld bottom - yCoord)]\\n\\t\\tifNotNil:\\n\\t\\t\\t[aPlayfield cartesianOrigin + (xCoord @ (yCoord negated))].\\n\\tself position: (xyOffset + delta)\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 2/22/2003 14:37'!\\ny\\n\\t\\\"Return my vertical position relative to the cartesian origin of the playfield or the world. Note that larger y values are closer to the top of the screen.\\\"\\n\\n\\t| w aPlayfield |\\n\\tw := self world.\\n\\tw ifNil: [^bounds top].\\n\\taPlayfield := self referencePlayfield.\\n\\t^aPlayfield isNil \\n\\t\\tifTrue: [w cartesianOrigin y - self referencePosition y]\\n\\t\\tifFalse: [aPlayfield cartesianOrigin y - self referencePosition y]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'aoy 2/17/2003 01:00'!\\ny: aNumber \\n\\t\\\"Set my vertical position relative to the cartesian origin of the playfield or the world. Note that larger y values are closer to the top of the screen.\\\"\\n\\n\\t| w offset newY aPlayfield |\\n\\tw := self world.\\n\\tw ifNil: [^self position: bounds left @ aNumber].\\n\\taPlayfield := self referencePlayfield.\\n\\toffset := self top - self referencePosition y.\\n\\tnewY := aPlayfield isNil\\n\\t\\t\\t\\tifTrue: [w bottom - aNumber + offset]\\n\\t\\t\\t\\tifFalse: [aPlayfield cartesianOrigin y - aNumber + offset].\\n\\tself position: bounds left @ newY! !\\n\\n\\n!Morph methodsFor: 'geometry testing'!\\ncontainsPoint: aPoint\\n\\n\\t^ self bounds containsPoint: aPoint! !\\n\\n!Morph methodsFor: 'geometry testing' stamp: 'di 5/3/2000 19:05'!\\nfullContainsPoint: aPoint\\n\\n\\t(self fullBounds containsPoint: aPoint) ifFalse: [^ false]. \\\"quick elimination\\\"\\n\\t(self containsPoint: aPoint) ifTrue: [^ true]. \\\"quick acceptance\\\"\\n\\tsubmorphs do: [:m | (m fullContainsPoint: aPoint) ifTrue: [^ true]].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'geometry testing' stamp: 'dgd 2/22/2003 14:33'!\\nobtrudesBeyondContainer\\n\\t\\\"Answer whether the receiver obtrudes beyond the bounds of its container\\\"\\n\\n\\t| top |\\n\\ttop := self topRendererOrSelf.\\n\\t(top owner isNil or: [top owner isHandMorph]) ifTrue: [^false].\\n\\t^(top owner bounds containsRect: top bounds) not! !\\n\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/7/1999 18:57'!\\naddHalo\\n\\t\\\"Invoke a halo programatically (e.g., not from a meta gesture)\\\"\\n\\t^self addHalo: nil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/10/2000 19:03'!\\naddHalo: evt\\n\\t| halo prospectiveHaloClass |\\n\\tprospectiveHaloClass _ Smalltalk at: self haloClass ifAbsent: [HaloMorph].\\n\\thalo _ prospectiveHaloClass new bounds: self worldBoundsForHalo.\\n\\thalo popUpFor: self event: evt.\\n\\t^halo! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/7/1999 21:55'!\\naddHalo: evt from: formerHaloOwner\\n\\t\\\"Transfer a halo from the former halo owner to the receiver\\\"\\n\\t^self addHalo: evt! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/30/2004 02:53'!\\naddHandlesTo: aHaloMorph box: box\\n\\t\\\"Add halo handles to the halo. Apply the halo filter if appropriate\\\"\\n\\n\\t| wantsIt aSelector |\\n\\taHaloMorph haloBox: box.\\n\\tPreferences haloSpecifications do:\\n\\t\\t[:aSpec | \\n\\t\\t\\taSelector _ aSpec addHandleSelector.\\n\\t\\t\\twantsIt _ Preferences selectiveHalos\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[self wantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[true].\\n\\t\\t\\twantsIt ifTrue:\\n\\t\\t\\t\\t[(#(addMakeSiblingHandle: addDupHandle:) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t[wantsIt _ self preferredDuplicationHandleSelector = aSelector].\\n\\t\\t\\twantsIt ifTrue:\\n\\t\\t\\t\\t[aHaloMorph perform: aSelector with: aSpec]]].\\n\\n\\taHaloMorph innerTarget addOptionalHandlesTo: aHaloMorph box: box! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 8/8/2001 17:31'!\\naddMagicHaloFor: aHand\\n\\t| halo prospectiveHaloClass |\\n\\taHand halo ifNotNil:[\\n\\t\\taHand halo target == self ifTrue:[^self].\\n\\t\\taHand halo isMagicHalo ifFalse:[^self]].\\n\\tprospectiveHaloClass _ Smalltalk at: self haloClass ifAbsent: [HaloMorph].\\n\\thalo _ prospectiveHaloClass new bounds: self worldBoundsForHalo.\\n\\thalo popUpMagicallyFor: self hand: aHand.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/22/2000 20:41'!\\naddOptionalHandlesTo: aHalo box: box\\n\\taHalo addDirectionHandles! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/21/1999 17:52'!\\naddSimpleHandlesTo: aHaloMorph box: aBox\\n\\t^ aHaloMorph addSimpleHandlesTo: aHaloMorph box: aBox! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/26/2000 19:37'!\\naddWorldHandlesTo: aHaloMorph box: box\\n\\taHaloMorph haloBox: box.\\n\\tPreferences haloSpecificationsForWorld do:\\n\\t\\t[:aSpec | \\n\\t\\t\\taHaloMorph perform: aSpec addHandleSelector with: aSpec].\\n\\taHaloMorph innerTarget addOptionalHandlesTo: aHaloMorph box: box! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 14:54'!\\nballoonColor\\n\\t^ self\\n\\t\\tvalueOfProperty: #balloonColor\\n\\t\\tifAbsent: [self defaultBalloonColor]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 14:55'!\\nballoonColor: aColor\\n\\t^ self\\n\\t\\tsetProperty: #balloonColor\\n\\t\\ttoValue: aColor! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:29'!\\nballoonFont\\n\\t^ self\\n\\t\\tvalueOfProperty: #balloonFont\\n\\t\\tifAbsent: [self defaultBalloonFont]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:30'!\\nballoonFont: aFont \\n\\t^ self setProperty: #balloonFont toValue: aFont! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 2/7/2000 11:27'!\\nballoonHelpAligner\\n\\t\\\"Answer the morph to which the receiver's balloon help should point\\\"\\n\\t^ (self valueOfProperty: #balloonTarget) ifNil: [self]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/7/2004 18:35'!\\nballoonHelpDelayTime\\n\\t\\\"Return the number of milliseconds before a balloon help should be put up on the receiver. The balloon help will only be put up if the receiver responds to #wantsBalloon by returning true.\\\"\\n\\t^ Preferences balloonHelpDelayTime! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 4/3/2006 14:15'!\\nballoonHelpTextForHandle: aHandle\\n\\t\\\"Answer a string providing balloon help for the given halo handle\\\"\\n\\n\\t| itsSelector |\\n\\titsSelector _ aHandle eventHandler firstMouseSelector.\\n\\n\\t(itsSelector == #doRecolor:with:) ifTrue:\\n\\t\\t[^ Preferences propertySheetFromHalo\\n\\t\\t\\tifTrue: ['Open a property sheet.']\\n\\t\\t\\tifFalse: ['Change color']].\\n\\n\\t(itsSelector == #mouseDownInDimissHandle:with:) ifTrue:\\n\\t\\t[^ Preferences preserveTrash\\n\\t\\t\\tifTrue: ['Move to trash']\\n\\t\\t\\tifFalse: ['Remove from screen']].\\n\\n\\t#(\\t(addFullHandles\\t\\t\\t\\t\\t\\t\\t'More halo handles')\\n\\t\\t(addSimpleHandles\\t\\t\\t\\t\\t\\t'Fewer halo handles')\\n\\t\\t(chooseEmphasisOrAlignment\\t\\t\\t\\t'Emphasis & alignment')\\n\\t\\t(chooseFont\\t\\t\\t\\t\\t\\t\\t\\t'Change font')\\n\\t\\t(chooseNewGraphicFromHalo\\t\\t\\t\\t'Choose a new graphic')\\n\\t\\t(chooseStyle\\t\\t\\t\\t\\t\\t\\t\\t'Change style')\\n\\t\\t(dismiss\\t\\t\\t\\t\\t\\t\\t\\t\\t'Remove')\\n\\t\\t(doDebug:with:\\t\\t\\t\\t\\t\\t\\t'Debug')\\n\\t\\t(doDirection:with:\\t\\t\\t\\t\\t\\t'Choose forward direction')\\n\\t\\t(doDup:with:\\t\\t\\t\\t\\t\\t\\t'Duplicate')\\n\\t\\t(doMakeSibling:with: \\t\\t\\t\\t\\t'Make a sibling')\\n\\t\\t(doMenu:with:\\t\\t\\t\\t\\t\\t\\t'Menu')\\n\\t\\t(doGrab:with:\\t\\t\\t\\t\\t\\t\\t'Pick up')\\n\\t\\t(editButtonsScript\\t\\t\\t\\t\\t\\t'See the script for this button')\\n\\t\\t(editDrawing\\t\\t\\t\\t\\t\\t\\t'Repaint')\\n\\t\\t(maybeDoDup:with:\\t\\t\\t\\t\\t\\t'Duplicate')\\n\\t\\t(makeNascentScript\\t\\t\\t\\t\\t\\t'Make a scratch script')\\n\\t\\t(makeNewDrawingWithin\\t\\t\\t\\t'Paint new object')\\n\\t\\t(mouseDownInCollapseHandle:with:\\t\\t'Collapse')\\n\\t\\t(mouseDownOnHelpHandle:\\t\\t\\t\\t'Help')\\n\\t\\t(openViewerForArgument\\t\\t\\t\\t'Open a Viewer for me. Press shift for a snapshot.')\\n\\t\\t(openViewerForTarget:with:\\t\\t\\t\\t'Open a Viewer for me. Press shift for a snapshot.')\\n\\t\\t(paintBackground\\t\\t\\t\\t\\t\\t'Paint background')\\n\\t\\t(prepareToTrackCenterOfRotation:with:\\t'Move object or set center of rotation')\\n\\t\\t(presentViewMenu\\t\\t\\t\\t\\t\\t'Present the Viewing menu')\\n\\t\\t(startDrag:with:\\t\\t\\t\\t\\t\\t\\t'Move')\\n\\t\\t(startGrow:with:\\t\\t\\t\\t\\t\\t\\t'Change size') \\n\\t\\t(startRot:with:\\t\\t\\t\\t\\t\\t\\t'Rotate')\\n\\t\\t(startScale:with:\\t\\t\\t\\t\\t\\t\\t'Change scale') \\n\\t\\t(tearOffTile\\t\\t\\t\\t\\t\\t\\t\\t'Make a tile representing this object')\\n\\t\\t(tearOffTileForTarget:with:\\t\\t\\t\\t'Make a tile representing this object')\\n\\t\\t(trackCenterOfRotation:with:\\t\\t\\t\\t'Set center of rotation')\\n\\t) \\n\\tdo:\\n\\t\\t[:pair | itsSelector == pair first ifTrue: [^ pair last]].\\n\\n\\t^ 'unknown halo handle'! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'RAA 7/21/2000 11:10'!\\nboundsForBalloon\\n\\n\\t\\\"some morphs have bounds that are way too big\\\"\\n\\t^self boundsInWorld! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 3/1/2000 11:39'!\\ncomeToFrontAndAddHalo\\n\\tself comeToFront.\\n\\tself addHalo! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 16:15'!\\ndefaultBalloonColor\\n\\t^ Display depth <= 2\\n\\t\\tifTrue: [Color white]\\n\\t\\tifFalse: [BalloonMorph balloonColor]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:23'!\\ndefaultBalloonFont\\n\\t^ BalloonMorph balloonFont! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/11/2000 18:24'!\\ndefersHaloOnClickTo: aSubMorph\\n\\t\\\"If a cmd-click on aSubMorph would make it a preferred recipient of the halo, answer true\\\"\\n\\t\\\"May want to add a way (via a property) for morphs to assert true here -- this would let certain kinds of morphs that are unusually reluctant to take the halo on initial click\\\"\\n\\n\\t^ false\\n\\t! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:03'!\\ndeleteBalloon\\n\\t\\\"If I am showing a balloon, delete it.\\\"\\n\\t| w |\\n\\tw _ self world ifNil:[^self].\\n\\tw deleteBalloonTarget: self.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'em 3/24/2005 10:02'!\\neditBalloonHelpContent: aString\\n\\t| reply |\\n\\treply _ FillInTheBlank\\n\\t\\tmultiLineRequest: 'Edit the balloon help text for ' translated, self externalName\\n\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\tinitialAnswer: (aString ifNil: [self noHelpString] ifNotNil: [aString])\\n\\t\\tanswerHeight: 200.\\n\\treply ifNil: [^ self]. \\\"User cancelled out of the dialog\\\"\\n\\t(reply isEmpty or: [reply asString = self noHelpString])\\n\\t\\tifTrue: [self setBalloonText: nil]\\n\\t\\tifFalse: [self setBalloonText: reply]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 12/23/1999 13:24'!\\neditBalloonHelpText\\n\\t\\\"Modify the receiver's balloon help text.\\\"\\n\\n\\tself editBalloonHelpContent: self balloonText! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 3/17/2001 13:19'!\\nhalo\\n\\n\\t(self outermostWorldMorph ifNil: [^nil]) haloMorphs do: [:h | h target == self ifTrue: [^ h]].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/15/2000 16:13'!\\nhaloClass\\n\\t\\\"Answer the name of the desired kind of HaloMorph to launch on behalf of the receiver\\\"\\n\\n\\t^ #HaloMorph\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 8/8/2001 15:40'!\\nhaloDelayTime\\n\\t\\\"Return the number of milliseconds before a halo should be put up on the receiver. The halo will only be put up if the receiver responds to #wantsHalo by returning true.\\\"\\n\\t^800! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/15/2000 16:16'!\\nhasHalo\\n\\t^self hasProperty: #hasHalo.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/28/2000 17:54'!\\nhasHalo: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasHalo toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasHalo]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 2/22/2003 19:05'!\\nisLikelyRecipientForMouseOverHalos\\n\\t^self player notNil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:05'!\\nmouseDownOnHelpHandle: anEvent\\n\\t\\\"The mouse went down in the show-balloon handle\\\"\\n\\t\\n\\t| str |\\n\\tanEvent shiftPressed ifTrue: [^ self editBalloonHelpText].\\n\\tstr _ self balloonText.\\n\\tstr ifNil: [str _ self noHelpString].\\n\\tself showBalloon: str hand: anEvent hand.\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'em 3/24/2005 10:05'!\\nnoHelpString\\n\\t^ 'Help not yet supplied' translated! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/15/2001 12:23'!\\nokayToAddDismissHandle\\n\\t\\\"Answer whether a halo on the receiver should offer a dismiss handle. This provides a hook for making it harder to disassemble some strucures even momentarily\\\"\\n\\n\\t^ self holdsSeparateDataForEachInstance not and:\\n\\t\\t[self resistsRemoval not]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/26/2000 12:11'!\\nokayToAddGrabHandle\\n\\t\\\"Answer whether a halo on the receiver should offer a grab handle. This provides a hook for making it harder to deconstruct some strucures even momentarily\\\"\\n\\n\\t^ self holdsSeparateDataForEachInstance not ! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:50'!\\nokayToBrownDragEasily\\n\\t\\\"Answer whether it it okay for the receiver to be brown-dragged easily -- i.e. repositioned within its container without extracting it. At present this is just a hook -- nobody declines.\\\"\\n\\n\\t^ true\\n\\n\\n\\n\\\"\\n\\t^ (self topRendererOrSelf owner isKindOf: PasteUpMorph) and:\\n\\t\\t[self layoutPolicy isNil]\\\"! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 15:02'!\\nokayToExtractEasily\\n\\t\\\"Answer whether it it okay for the receiver to be extracted easily. Not yet hooked up to the halo-permissions mechanism.\\\"\\n\\n\\t^ self topRendererOrSelf owner dragNDropEnabled! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/29/2001 06:29'!\\nokayToResizeEasily\\n\\t\\\"Answer whether it is appropriate to have the receiver be easily resized by the user from the halo\\\"\\n\\n\\t^ true\\n\\n\\t\\\"This one was too jarring, not that it didn't most of the time do the right thing but because some of the time it didn't, such as in a holder. If we pursue this path, the test needs to be airtight, obviously...\\n\\t^ (self topRendererOrSelf owner isKindOf: PasteUpMorph) and:\\n\\t\\t[self layoutPolicy isNil]\\\"! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:44'!\\nokayToRotateEasily\\n\\t\\\"Answer whether it is appropriate for a rotation handle to be shown for the receiver. This is a hook -- at present nobody declines.\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/31/2004 03:30'!\\npreferredDuplicationHandleSelector\\n\\t\\\"Answer the selector, either #addMakeSiblingHandle: or addDupHandle:, to be offered as the default in a halo open on me\\\"\\n\\n\\tPreferences oliveHandleForScriptedObjects ifFalse:\\n\\t\\t[^ #addDupHandle:].\\n\\t^ self renderedMorph valueOfProperty: #preferredDuplicationHandleSelector ifAbsent:\\n\\t\\t[self player class isUniClass\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[#addMakeSiblingHandle:]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[#addDupHandle:]]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/9/2004 22:43'!\\nremoveHalo\\n\\t\\\"remove the surrounding halo (if any)\\\"\\n\\tself halo isNil\\n\\t\\tifFalse: [self primaryHand removeHalo]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 12/23/1999 13:32'!\\nsetBalloonText: stringOrText\\n\\t\\\"Set receiver's balloon help text. Pass nil to remove the help.\\\"\\n\\n\\tself setBalloonText: stringOrText maxLineLength: Preferences maxBalloonHelpLineLength! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'md 2/27/2006 09:54'!\\nsetBalloonText: stringOrText maxLineLength: aLength \\n\\t\\\"Set receiver's balloon help text. Pass nil to remove the help.\\\"\\n\\t(extension isNil and: [stringOrText isNil]) ifTrue: [^ self].\\n\\tself assureExtension balloonText: \\n\\t\\t(stringOrText ifNotNil: [stringOrText asString withNoLineLongerThan: aLength])! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/29/1999 17:38'!\\nsetCenteredBalloonText: aString\\n\\tself setBalloonText: aString.\\n\\tself setProperty: #helpAtCenter toValue: true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:06'!\\nshowBalloon: msgString\\n\\t\\\"Pop up a balloon containing the given string,\\n\\tfirst removing any existing BalloonMorphs in the world.\\\"\\n\\t| w |\\n\\tself showBalloon: msgString hand: ((w _ self world) ifNotNil:[w activeHand]).! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'bf 11/1/2000 15:58'!\\nshowBalloon: msgString hand: aHand\\n\\t\\\"Pop up a balloon containing the given string,\\n\\tfirst removing any existing BalloonMorphs in the world.\\\"\\n\\n\\t| w balloon h |\\n\\t(w _ self world) ifNil: [^ self].\\n\\th _ aHand.\\n\\th ifNil:[\\n\\t\\th _ w activeHand].\\n\\tballoon _ BalloonMorph string: msgString for: self balloonHelpAligner.\\n\\tballoon popUpFor: self hand: h.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/10/2004 13:59'!\\ntransferHalo: event from: formerHaloOwner\\n\\t\\\"Progressively transfer the halo to the next likely recipient\\\"\\n\\t| localEvt w target |\\n\\n\\tself flag: #workAround. \\\"For halo's distinction between 'target' and 'innerTarget' we need to bypass any renderers.\\\"\\n\\t(formerHaloOwner == self and:[self isRenderer and:[self wantsHaloFromClick not]]) ifTrue:[\\n\\t\\tevent shiftPressed ifTrue:[\\n\\t\\t\\ttarget _ owner.\\n\\t\\t\\tlocalEvt _ event transformedBy: (self transformedFrom: owner).\\n\\t\\t] ifFalse:[\\n\\t\\t\\ttarget _ self renderedMorph.\\n\\t\\t\\tlocalEvt _ event transformedBy: (target transformedFrom: self).\\n\\t\\t].\\n\\t\\t^target transferHalo: localEvt from: target].\\n\\n\\\"\\tformerHaloOwner == self ifTrue:[^ self removeHalo].\\\"\\n\\n\\t\\\"Never transfer halo to top-most world\\\"\\n\\t(self isWorldMorph and:[owner isNil]) ifFalse:[\\n\\t\\t(self wantsHaloFromClick and:[formerHaloOwner ~~ self]) \\n\\t\\t\\tifTrue:[^self addHalo: event from: formerHaloOwner]].\\n\\n\\tevent shiftPressed ifTrue:[\\n\\t\\t\\\"Pass it outwards\\\"\\n\\t\\towner ifNotNil:[^owner transferHalo: event from: formerHaloOwner].\\n\\t\\t\\\"We're at the top level; throw the event back in to find recipient\\\"\\n\\t\\tformerHaloOwner removeHalo.\\n\\t\\t^self processEvent: event copy resetHandlerFields.\\n\\t].\\n\\tself submorphsDo:[:m|\\n\\t\\tlocalEvt _ event transformedBy: (m transformedFrom: self).\\n\\t\\t(m fullContainsPoint: localEvt position) \\n\\t\\t\\tifTrue:[^m transferHalo: event from: formerHaloOwner].\\n\\t].\\n\\t\\\"We're at the bottom most level; throw the event back up to the root to find recipient\\\"\\n\\tformerHaloOwner removeHalo.\\n\\n\\tPreferences maintainHalos ifFalse:[\\n\\t\\t(w _ self world) ifNil: [ ^self ].\\n\\t\\tlocalEvt _ event transformedBy: (self transformedFrom: w) inverseTransformation.\\n\\t\\t^w processEvent: localEvt resetHandlerFields.\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'rhi 10/5/2001 20:49'!\\nwantsBalloon\\n\\t\\\"Answer true if receiver wants to show a balloon help text is a few moments.\\\"\\n\\n\\t^ (self balloonText notNil) and: [Preferences balloonHelpEnabled]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/29/2001 19:50'!\\nwantsDirectionHandles\\n\\t^self valueOfProperty: #wantsDirectionHandles ifAbsent:[Preferences showDirectionHandles]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/29/2001 19:52'!\\nwantsDirectionHandles: aBool\\n\\taBool == Preferences showDirectionHandles\\n\\t\\tifTrue:[self removeProperty: #wantsDirectionHandles]\\n\\t\\tifFalse:[self setProperty: #wantsDirectionHandles toValue: aBool].\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 2/22/2003 19:06'!\\nwantsHalo\\n\\t| topOwner |\\n\\t^(topOwner := self topRendererOrSelf owner) notNil \\n\\t\\tand: [topOwner wantsHaloFor: self]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 4/8/98 13:26'!\\nwantsHaloFor: aSubMorph\\n\\t^ false! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/25/2000 17:43'!\\nwantsHaloFromClick\\n\\t^ true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:49'!\\nwantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph\\n\\t\\\"Answer whether the receiver would like to offer the halo handle with the given selector (e.g. #addCollapseHandle:)\\\"\\n\\n\\t(#(addDismissHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self resistsRemoval not].\\n\\n\\t(#( addDragHandle: ) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToBrownDragEasily].\\n\\n\\t(#(addGrowHandle: addScaleHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToResizeEasily].\\n\\n\\t(#( addRotateHandle: ) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToRotateEasily].\\n\\n\\t(#(addRecolorHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self renderedMorph wantsRecolorHandle].\\n\\n\\ttrue ifTrue: [^ true]\\n\\t! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/9/2000 16:56'!\\nwantsScriptorHaloHandle\\n\\t\\\"Answer whether the receiver would like to have a Scriptor halo handle put up on its behalf. Initially, only the ScriptableButton says yes\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'nk 6/12/2004 09:32'!\\nwantsSimpleSketchMorphHandles\\n\\t\\\"Answer true if my halo's simple handles should include the simple sketch morph handles.\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:00'!\\nbasicInitialize\\n\\t\\\"Do basic generic initialization of the instance variables: \\n\\tSet up the receiver, created by a #basicNew and now ready to \\n\\tbe initialized, by placing initial values in the instance variables \\n\\tas appropriate\\\"\\nowner _ nil.\\n\\tsubmorphs _ EmptyArray.\\n\\tbounds _ self defaultBounds.\\n\\t\\n\\tcolor _ self defaultColor! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:06'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 50 @ 40! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'fbs 1/5/2005 09:17'!\\ninAScrollPane\\n\\t\\\"Answer a scroll pane that allows the user to scroll the receiver in either direction. It will have permanent scroll bars unless you take some special action.\\\"\\n\\n\\t| widget |\\n\\twidget _ ScrollPane new.\\n\\twidget extent: ((self width min: 300 max: 100) @ (self height min: 150 max: 100));\\n\\t\\tborderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget color: self color darker darker.\\n\\t^ widget! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 6/26/2001 10:56'!\\ninATwoWayScrollPane\\n\\t\\\"Answer a two-way scroll pane that allows the user to scroll the receiver in either direction. It will have permanent scroll bars unless you take some special action.\\\"\\n\\n\\t| widget |\\n\\twidget _ TwoWayScrollPane new.\\n\\twidget extent: ((self width min: 300 max: 100) @ (self height min: 150 max: 100));\\n\\t\\tborderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget color: self color darker darker.\\n\\t^ widget! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 17:30'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\nowner _ nil.\\n\\tsubmorphs _ EmptyArray.\\n\\tbounds _ self defaultBounds.\\n\\t\\n\\tcolor _ self defaultColor! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 1/31/2001 13:57'!\\nintoWorld: aWorld\\n\\t\\\"The receiver has just appeared in a new world. Note:\\n\\t\\t* aWorld can be nil (due to optimizations in other places)\\n\\t\\t* owner is already set\\n\\t\\t* owner's submorphs may not include receiver yet.\\n\\tImportant: Keep this method fast - it is run whenever morphs are added.\\\"\\n\\taWorld ifNil:[^self].\\n\\tself wantsSteps ifTrue:[aWorld startStepping: self].\\n\\tself submorphsDo:[:m| m intoWorld: aWorld].\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 10/18/2000 12:33'!\\nopenCenteredInWorld\\n\\n\\tself \\n\\t\\tfullBounds;\\n\\t\\tposition: Display extent - self extent // 2;\\n\\t\\topenInWorld.! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 3/21/2000 14:46'!\\nopenInHand\\n\\t\\\"Attach the receiver to the current hand in the current morphic world\\\"\\n\\n\\tself currentHand attachMorph: self! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'jm 7/5/1998 12:40'!\\nopenInMVC\\n\\n\\tMorphWorldView\\n\\t\\topenWorldWith: self\\n\\t\\tlabelled: self defaultLabelForInspector.\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'djp 10/24/1999 17:13'!\\nopenInWindow\\n\\n\\t^self openInWindowLabeled: self defaultLabelForInspector\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sma 4/22/2000 20:28'!\\nopenInWindowLabeled: aString\\n\\n\\t^self openInWindowLabeled: aString inWorld: self currentWorld! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 5/25/2000 08:12'!\\nopenInWindowLabeled: aString inWorld: aWorld\\n\\n\\t| window extent |\\n\\n\\twindow _ (SystemWindow labelled: aString) model: nil.\\n\\twindow \\n\\t\\t\\\" guess at initial extent\\\"\\n\\t\\tbounds: (RealEstateAgent initialFrameFor: window initialExtent: self fullBounds extent world: aWorld);\\n\\t\\taddMorph: self frame: (0@0 extent: 1@1);\\n\\t\\tupdatePaneColors.\\n\\t\\\" calculate extent after adding in case any size related attributes were changed. Use\\n\\tfullBounds in order to trigger re-layout of layout morphs\\\"\\n\\textent _ self fullBounds extent + \\n\\t\\t\\t(window borderWidth@window labelHeight) + window borderWidth.\\n\\twindow extent: extent.\\n\\taWorld addMorph: window.\\n\\twindow activate.\\n\\taWorld startSteppingSubmorphsOf: window.\\n\\t^window\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 6/14/2000 18:09'!\\nopenInWorld\\n \\\"Add this morph to the world. If in MVC, then provide a Morphic window for it.\\\"\\n\\n self couldOpenInMorphic\\n ifTrue: [self openInWorld: self currentWorld]\\n ifFalse: [self openInMVC]! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 9/1/2004 16:12'!\\nopenInWorld: aWorld\\n\\t\\\"Add this morph to the requested World.\\\"\\n\\t(aWorld visibleClearArea origin ~= (0@0) and: [self position = (0@0)]) ifTrue:\\n\\t\\t[self position: aWorld visibleClearArea origin].\\n\\taWorld addMorph: self.\\n\\taWorld startSteppingSubmorphsOf: self! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 1/31/2001 13:58'!\\noutOfWorld: aWorld\\n\\t\\\"The receiver has just appeared in a new world. Notes:\\n\\t\\t* aWorld can be nil (due to optimizations in other places)\\n\\t\\t* owner is still valid\\n\\tImportant: Keep this method fast - it is run whenever morphs are removed.\\\"\\n\\taWorld ifNil:[^self].\\n\\t\\\"ar 1/31/2001: We could explicitly stop stepping the receiver here but for the sake of speed I'm for now relying on the lazy machinery in the world itself.\\\"\\n\\t\\\"aWorld stopStepping: self.\\\"\\n\\tself submorphsDo:[:m| m outOfWorld: aWorld].\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 3/3/2001 15:28'!\\nresourceJustLoaded\\n\\t\\\"In case resource relates to me\\\"\\n\\tself releaseCachedState.! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 9/11/1998 11:13'!\\nstandardPalette\\n\\t\\\"Answer a standard palette forced by some level of enclosing presenter, or nil if none\\\"\\n\\t| pal aPresenter itsOwner |\\n\\t(aPresenter _ self presenter) ifNil: [^ nil].\\n\\t^ (pal _ aPresenter ownStandardPalette)\\n\\t\\tifNotNil: [pal]\\n\\t\\tifNil:\\t[(itsOwner _ aPresenter associatedMorph owner)\\n\\t\\t\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t\\t\\t[itsOwner standardPalette]\\n\\t\\t\\t\\t\\tifNil:\\n\\t\\t\\t\\t\\t\\t[nil]]! !\\n\\n\\n!Morph methodsFor: 'latter day support' stamp: 'sw 1/6/2005 01:26'!\\nisEtoyReadout\\n\\t\\\"Answer whether the receiver can serve as an etoy readout\\\"\\n\\n\\t^ false! !\\n\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:33'!\\nacceptDroppingMorph: aMorph event: evt\\n\\t\\\"This message is sent when a morph is dropped onto a morph that has agreed to accept the dropped morph by responding 'true' to the wantsDroppedMorph:Event: message. This default implementation just adds the given morph to the receiver.\\\"\\n\\t| layout |\\n\\tlayout _ self layoutPolicy.\\n\\tlayout ifNil:[^self addMorph: aMorph].\\n\\tself privateAddMorph: aMorph \\n\\t\\tatIndex: (layout indexForInserting: aMorph at: evt position in: self).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:34'!\\nadjustLayoutBounds\\n\\t\\\"Adjust the receivers bounds depending on the resizing strategy imposed\\\"\\n\\t| hFit vFit box myExtent extent |\\n\\thFit _ self hResizing.\\n\\tvFit _ self vResizing.\\n\\t(hFit == #shrinkWrap or:[vFit == #shrinkWrap]) ifFalse:[^self]. \\\"not needed\\\"\\n\\tbox _ self layoutBounds.\\n\\tmyExtent _ box extent.\\n\\textent _ self submorphBounds corner - box origin.\\n\\thFit == #shrinkWrap ifTrue:[myExtent _ extent x @ myExtent y].\\n\\tvFit == #shrinkWrap ifTrue:[myExtent _ myExtent x @ extent y].\\n\\t\\\"Make sure we don't get smaller than minWidth/minHeight\\\"\\n\\tmyExtent x < self minWidth ifTrue:[\\n\\t\\tmyExtent _ (myExtent x max: \\n\\t\\t\\t(self minWidth - self bounds width + self layoutBounds width)) @ myExtent y].\\n\\tmyExtent y < self minHeight ifTrue:[\\n\\t\\tmyExtent _ myExtent x @ (myExtent y max:\\n\\t\\t\\t(self minHeight - self bounds height + self layoutBounds height))].\\n\\tself layoutBounds: (box origin extent: myExtent).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:31'!\\ndoLayoutIn: layoutBounds \\n\\t\\\"Compute a new layout based on the given layout bounds.\\\"\\n\\n\\t\\\"Note: Testing for #bounds or #layoutBounds would be sufficient to\\n\\tfigure out if we need an invalidation afterwards but #outerBounds\\n\\tis what we need for all leaf nodes so we use that.\\\"\\n\\n\\t| layout box priorBounds |\\n\\tpriorBounds := self outerBounds.\\n\\tsubmorphs isEmpty ifTrue: [^fullBounds := priorBounds].\\n\\t\\\"Send #ownerChanged to our children\\\"\\n\\tsubmorphs do: [:m | m ownerChanged].\\n\\tlayout := self layoutPolicy.\\n\\tlayout ifNotNil: [layout layout: self in: layoutBounds].\\n\\tself adjustLayoutBounds.\\n\\tfullBounds := self privateFullBounds.\\n\\tbox := self outerBounds.\\n\\tbox = priorBounds \\n\\t\\tifFalse: [self invalidRect: (priorBounds quickMerge: box)]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 1/1/2002 20:00'!\\nfullBounds\\n\\t\\\"Return the bounding box of the receiver and all its children. Recompute the layout if necessary.\\\"\\n\\tfullBounds ifNotNil:[^fullBounds].\\n\\t\\\"Errors at this point can be critical so make sure we catch 'em all right\\\"\\n\\t[self doLayoutIn: self layoutBounds] on: Error do:[:ex|\\n\\t\\t\\\"This should do it unless you don't screw up the bounds\\\"\\n\\t\\tfullBounds _ bounds.\\n\\t\\tex pass].\\n\\t^fullBounds! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 23:10'!\\nlayoutBounds\\n\\t\\\"Return the bounds for laying out children of the receiver\\\"\\n\\t| inset box |\\n\\tinset _ self layoutInset.\\n\\tbox _ self innerBounds.\\n\\tinset isZero ifTrue:[^box].\\n\\t^box insetBy: inset.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 10/31/2000 21:09'!\\nlayoutBounds: aRectangle\\n\\t\\\"Set the bounds for laying out children of the receiver.\\n\\tNote: written so that #layoutBounds can be changed without touching this method\\\"\\n\\t| outer inner |\\n\\touter _ self bounds.\\n\\tinner _ self layoutBounds.\\n\\tbounds _ aRectangle origin + (outer origin - inner origin) corner:\\n\\t\\t\\t\\taRectangle corner + (outer corner - inner corner).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 1/27/2001 14:41'!\\nlayoutChanged\\n\\t| layout |\\n\\tfullBounds ifNil:[^self]. \\\"layout will be recomputed so don't bother\\\"\\n\\tfullBounds _ nil.\\n\\tlayout _ self layoutPolicy.\\n\\tlayout ifNotNil:[layout flushLayoutCache].\\n\\towner ifNotNil: [owner layoutChanged].\\n\\t\\\"note: does not send #ownerChanged here - we'll do this when computing the new layout\\\"! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 8/6/2001 09:55'!\\nlayoutInBounds: cellBounds\\n\\t\\\"Layout specific. Apply the given bounds to the receiver after being layed out in its owner.\\\"\\n\\t| box aSymbol delta |\\n\\tfullBounds ifNil:[\\\"We are getting new bounds here but we haven't computed the receiver's layout yet. Although the receiver has reported its minimal size before the actual size it has may differ from what would be after the layout. Normally, this isn't a real problem, but if we have #shrinkWrap constraints then the receiver's bounds may be larger than the cellBounds. THAT is a problem because the centering may not work correctly if the receiver shrinks after the owner layout has been computed. To avoid this problem, we compute the receiver's layout now. Note that the layout computation is based on the new cell bounds rather than the receiver's current bounds.\\\"\\n\\t\\tcellBounds origin = self bounds origin ifFalse:[\\n\\t\\t\\tbox _ self outerBounds.\\n\\t\\t\\tdelta _ cellBounds origin - self bounds origin.\\n\\t\\t\\tself invalidRect: (box merge: (box translateBy: delta)).\\n\\t\\t\\tself privateFullMoveBy: delta]. \\\"sigh...\\\"\\n\\t\\tbox _ cellBounds origin extent: \\\"adjust for #rigid receiver\\\"\\n\\t\\t\\t(self hResizing == #rigid ifTrue:[self bounds extent x] ifFalse:[cellBounds extent x]) @\\n\\t\\t\\t(self vResizing == #rigid ifTrue:[self bounds extent y] ifFalse:[cellBounds extent y]).\\n\\t\\t\\\"Compute inset of layout bounds\\\"\\n\\t\\tbox _ box origin - (self bounds origin - self layoutBounds origin) corner:\\n\\t\\t\\t\\t\\tbox corner - (self bounds corner - self layoutBounds corner).\\n\\t\\t\\\"And do the layout within the new bounds\\\"\\n\\t\\tself layoutBounds: box.\\n\\t\\tself doLayoutIn: box].\\n\\tcellBounds = self fullBounds ifTrue:[^self]. \\\"already up to date\\\"\\n\\tcellBounds extent = self fullBounds extent \\\"nice fit\\\"\\n\\t\\tifTrue:[^self position: cellBounds origin].\\n\\tbox _ bounds.\\n\\t\\\"match #spaceFill constraints\\\"\\n\\tself hResizing == #spaceFill \\n\\t\\tifTrue:[box _ box origin extent: cellBounds width @ box height].\\n\\tself vResizing == #spaceFill\\n\\t\\tifTrue:[box _ box origin extent: box width @ cellBounds height].\\n\\t\\\"align accordingly\\\"\\n\\taSymbol _ (owner ifNil:[self]) cellPositioning.\\n\\tbox _ box align: (box perform: aSymbol) with: (cellBounds perform: aSymbol).\\n\\t\\\"and install new bounds\\\"\\n\\tself bounds: box.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:35'!\\nlayoutProportionallyIn: newBounds\\n\\t\\\"Layout specific. Apply the given bounds to the receiver.\\\"\\n\\t| box frame |\\n\\tframe _ self layoutFrame ifNil:[^self].\\n\\t\\\"before applying the proportional values make sure the receiver's layout is computed\\\"\\n\\tself fullBounds. \\\"sigh...\\\"\\n\\t\\\"compute the cell size the receiver has given its layout frame\\\"\\n\\tbox _ frame layout: self bounds in: newBounds.\\n\\t(box = self bounds) ifTrue:[^self]. \\\"no change\\\"\\n\\t^self layoutInBounds: box.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminExtent\\n\\t\\\"Layout specific. Return the minimum size the receiver can be represented in.\\n\\tImplementation note: When this message is sent from an owner trying to lay out its children it will traverse down the morph tree and recompute the minimal arrangement of the morphs based on which the minimal extent is returned. When a morph with some layout strategy is encountered, the morph will ask its strategy to compute the new arrangement. However, since the final size given to the receiver is unknown at the point of the query, the assumption is made that the current bounds of the receiver are the base on which the layout should be computed. This scheme prevents strange layout changes when for instance, a table is contained in another table. Unless the inner table has been resized manually (which means its bounds are already enlarged) the arrangement of the inner table will not change here. Thus the entire layout computation is basically an iterative process which may have different results depending on the incremental changes applied.\\\"\\n\\n\\t| layout minExtent extra hFit vFit |\\n\\thFit := self hResizing.\\n\\tvFit := self vResizing.\\n\\t(hFit == #spaceFill or: [vFit == #spaceFill]) \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"The receiver will not adjust to parents layout by growing or shrinking,\\n\\t\\twhich means that an accurate layout defines the minimum size.\\\"\\n\\n\\t\\t\\t^self fullBounds extent].\\n\\n\\t\\\"An exception -- a receiver with #shrinkWrap constraints but no children is being treated #rigid (the equivalent to a #spaceFill receiver in a non-layouting owner)\\\"\\n\\tself hasSubmorphs \\n\\t\\tifFalse: \\n\\t\\t\\t[hFit == #shrinkWrap ifTrue: [hFit := #rigid].\\n\\t\\t\\tvFit == #shrinkWrap ifTrue: [vFit := #rigid]].\\n\\tlayout := self layoutPolicy.\\n\\tlayout isNil \\n\\t\\tifTrue: [minExtent := 0 @ 0]\\n\\t\\tifFalse: [minExtent := layout minExtentOf: self in: self layoutBounds].\\n\\thFit == #rigid \\n\\t\\tifTrue: [minExtent := self fullBounds extent x @ minExtent y]\\n\\t\\tifFalse: \\n\\t\\t\\t[extra := self bounds width - self layoutBounds width.\\n\\t\\t\\tminExtent := (minExtent x + extra) @ minExtent y].\\n\\tminExtent := vFit == #rigid \\n\\t\\t\\t\\tifTrue: [minExtent x @ self fullBounds extent y]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[extra := self bounds height - self layoutBounds height.\\n\\t\\t\\t\\t\\tminExtent x @ (minExtent y + extra)].\\n\\tminExtent := minExtent max: self minWidth @ self minHeight.\\n\\t^minExtent! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/16/2003 21:52'!\\nminHeight\\n\\t\\\"answer the receiver's minHeight\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #minHeight\\n\\t\\tifAbsent: [2]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminHeight: aNumber \\n\\taNumber isNil \\n\\t\\tifTrue: [self removeProperty: #minHeight]\\n\\t\\tifFalse: [self setProperty: #minHeight toValue: aNumber].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/16/2003 21:54'!\\nminWidth\\n\\t\\\"answer the receiver's minWidth\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #minWidth\\n\\t\\tifAbsent: [2]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminWidth: aNumber \\n\\taNumber isNil \\n\\t\\tifTrue: [self removeProperty: #minWidth]\\n\\t\\tifFalse: [self setProperty: #minWidth toValue: aNumber].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:33'!\\nprivateFullBounds\\n\\t\\\"Private. Compute the actual full bounds of the receiver\\\"\\n\\n\\t| box |\\n\\tsubmorphs isEmpty ifTrue: [^self outerBounds].\\n\\tbox := self outerBounds copy.\\n\\tbox := box quickMerge: (self clipSubmorphs \\n\\t\\t\\t\\t\\t\\tifTrue: [self submorphBounds intersect: self clippingBounds]\\n\\t\\t\\t\\t\\t\\tifFalse: [self submorphBounds]).\\n\\t^box origin asIntegerPoint corner: box corner asIntegerPoint! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/2/2000 17:42'!\\nsubmorphBounds\\n\\t\\\"Private. Compute the actual full bounds of the receiver\\\"\\n\\t| box subBox |\\n\\tsubmorphs do: [:m | \\n\\t\\t(m visible) ifTrue: [\\n\\t\\t\\tsubBox _ m fullBounds.\\n\\t\\t\\tbox \\n\\t\\t\\t\\tifNil:[box _ subBox copy]\\n\\t\\t\\t\\tifNotNil:[box _ box quickMerge: subBox]]].\\n\\tbox ifNil:[^self bounds]. \\\"e.g., having submorphs but not visible\\\"\\n\\t^ box origin asIntegerPoint corner: box corner asIntegerPoint\\n! !\\n\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:57'!\\naddCellLayoutMenuItems: aMenu hand: aHand\\n\\t\\\"Cell (e.g., child) related items\\\"\\n\\t| menu sub |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\t\\tmenu addUpdating: #hasDisableTableLayoutString action: #changeDisableTableLayout.\\n\\t\\tmenu addLine.\\n\\n\\t\\tsub _ MenuMorph new defaultTarget: self.\\n\\t\\t#(rigid shrinkWrap spaceFill) do:[:sym|\\n\\t\\t\\tsub addUpdating: #hResizingString: target: self selector: #hResizing: argumentList: (Array with: sym)].\\n\\t\\tmenu add:'horizontal resizing' translated subMenu: sub.\\n\\n\\t\\tsub _ MenuMorph new defaultTarget: self.\\n\\t\\t#(rigid shrinkWrap spaceFill) do:[:sym|\\n\\t\\t\\tsub addUpdating: #vResizingString: target: self selector: #vResizing: argumentList: (Array with: sym)].\\n\\t\\tmenu add:'vertical resizing' translated subMenu: sub.\\n\\n\\taMenu ifNotNil:[aMenu add: 'child layout' translated subMenu: menu].\\n\\t^menu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:51'!\\naddLayoutMenuItems: topMenu hand: aHand\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addUpdating: #hasNoLayoutString action: #changeNoLayout.\\n\\taMenu addUpdating: #hasProportionalLayoutString action: #changeProportionalLayout.\\n\\taMenu addUpdating: #hasTableLayoutString action: #changeTableLayout.\\n\\taMenu addLine.\\n\\taMenu add: 'change layout inset...' translated action: #changeLayoutInset:.\\n\\taMenu addLine.\\n\\tself addCellLayoutMenuItems: aMenu hand: aHand.\\n\\tself addTableLayoutMenuItems: aMenu hand: aHand.\\n\\ttopMenu ifNotNil:[topMenu add: 'layout' translated subMenu: aMenu].\\n\\t^aMenu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:07'!\\naddTableLayoutMenuItems: aMenu hand: aHand\\n\\t| menu sub |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addUpdating: #hasReverseCellsString action: #changeReverseCells.\\n\\tmenu addUpdating: #hasClipLayoutCellsString action: #changeClipLayoutCells.\\n\\tmenu addUpdating: #hasRubberBandCellsString action: #changeRubberBandCells.\\n\\tmenu addLine.\\n\\tmenu add: 'change cell inset...' translated action: #changeCellInset:.\\n\\tmenu add: 'change min cell size...' translated action: #changeMinCellSize:.\\n\\tmenu add: 'change max cell size...' translated action: #changeMaxCellSize:.\\n\\tmenu addLine.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(leftToRight rightToLeft topToBottom bottomToTop) do:[:sym|\\n\\t\\tsub addUpdating: #listDirectionString: target: self selector: #changeListDirection: argumentList: (Array with: sym)].\\n\\tmenu add: 'list direction' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none leftToRight rightToLeft topToBottom bottomToTop) do:[:sym|\\n\\t\\tsub addUpdating: #wrapDirectionString: target: self selector: #wrapDirection: argumentList: (Array with: sym)].\\n\\tmenu add: 'wrap direction' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(center topLeft topRight bottomLeft bottomRight topCenter leftCenter rightCenter bottomCenter) do:[:sym|\\n\\t\\tsub addUpdating: #cellPositioningString: target: self selector: #cellPositioning: argumentList: (Array with: sym)].\\n\\tmenu add: 'cell positioning' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(topLeft bottomRight center justified) do:[:sym|\\n\\t\\tsub addUpdating: #listCenteringString: target: self selector: #listCentering: argumentList: (Array with: sym)].\\n\\tmenu add: 'list centering' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(topLeft bottomRight center justified) do:[:sym|\\n\\t\\tsub addUpdating: #wrapCenteringString: target: self selector: #wrapCentering: argumentList: (Array with: sym)].\\n\\tmenu add: 'wrap centering' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none equal) do:[:sym|\\n\\t\\tsub addUpdating: #listSpacingString: target: self selector: #listSpacing: argumentList: (Array with: sym)].\\n\\tmenu add: 'list spacing' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none localRect localSquare globalRect globalSquare) do:[:sym|\\n\\t\\tsub addUpdating: #cellSpacingString: target: self selector: #cellSpacing: argumentList: (Array with: sym)].\\n\\tmenu add: 'cell spacing' translated subMenu: sub.\\n\\n\\taMenu ifNotNil:[aMenu add: 'table layout' translated subMenu: menu].\\n\\t^menu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:08'!\\nchangeCellInset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself cellInset: (newPoint - evt cursorPoint) asIntegerPoint // 5].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 18:54'!\\nchangeClipLayoutCells\\n\\tself invalidRect: self fullBounds.\\n\\tself clipLayoutCells: self clipLayoutCells not.\\n\\tself invalidRect: self fullBounds.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeDisableTableLayout\\n\\tself disableTableLayout: self disableTableLayout not.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:09'!\\nchangeLayoutInset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself layoutInset: (newPoint - evt cursorPoint) asIntegerPoint // 5].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeListDirection: aSymbol\\n\\t| listDir wrapDir |\\n\\tself listDirection: aSymbol.\\n\\t(self wrapDirection == #none) ifTrue:[^self].\\n\\t\\\"otherwise automatically keep a valid table layout\\\"\\n\\tlistDir _ self listDirection.\\n\\twrapDir _ self wrapDirection.\\n\\t(listDir == #leftToRight or:[listDir == #rightToLeft]) ifTrue:[\\n\\t\\twrapDir == #leftToRight ifTrue:[^self wrapDirection: #topToBottom].\\n\\t\\twrapDir == #rightToLeft ifTrue:[^self wrapDirection: #bottomToTop].\\n\\t] ifFalse:[\\n\\t\\twrapDir == #topToBottom ifTrue:[^self wrapDirection: #leftToRight].\\n\\t\\twrapDir == #bottomToTop ifTrue:[^self wrapDirection: #rightToLeft].\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeMaxCellSize: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself maxCellSize: (newPoint - evt cursorPoint) asIntegerPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeMinCellSize: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself minCellSize: (newPoint - evt cursorPoint) asIntegerPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeNoLayout\\n\\tself layoutPolicy ifNil:[^self]. \\\"already no layout\\\"\\n\\tself layoutPolicy: nil.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeProportionalLayout\\n\\t| layout |\\n\\t((layout _ self layoutPolicy) notNil and:[layout isProportionalLayout])\\n\\t\\tifTrue:[^self]. \\\"already proportional layout\\\"\\n\\tself layoutPolicy: ProportionalLayout new.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeReverseCells\\n\\tself reverseTableCells: self reverseTableCells not.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeRubberBandCells\\n\\tself rubberBandCells: self rubberBandCells not.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:20'!\\nchangeTableLayout\\n\\t| layout |\\n\\t((layout _ self layoutPolicy) notNil and:[layout isTableLayout])\\n\\t\\tifTrue:[^self]. \\\"already table layout\\\"\\n\\tself layoutPolicy: TableLayout new.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:09'!\\nhasClipLayoutCellsString\\n\\t^ (self clipLayoutCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'clip to cell size' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:58'!\\nhasDisableTableLayoutString\\n\\t^ (self disableTableLayout\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'disable layout in tables' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 10/8/2003 19:23'!\\nhasNoLayoutString\\n\\t^ (self layoutPolicy isNil\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'no layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:55'!\\nhasProportionalLayoutString\\n\\t| layout |\\n\\t^ (((layout := self layoutPolicy) notNil\\n\\t\\t\\tand: [layout isProportionalLayout])\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'proportional layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:08'!\\nhasReverseCellsString\\n\\t^ (self reverseTableCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'reverse table cells' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:09'!\\nhasRubberBandCellsString\\n\\t^ (self rubberBandCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'rubber band cells' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:59'!\\nhasTableLayoutString\\n\\t| layout |\\n\\t^ (((layout := self layoutPolicy) notNil\\n\\t\\t\\tand: [layout isTableLayout])\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'table layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 10/19/2003 11:23'!\\nlayoutMenuPropertyString: aSymbol from: currentSetting \\n\\t| onOff wording |\\n\\tonOff := aSymbol == currentSetting\\n\\t\\t\\t\\tifTrue: ['<on>']\\n\\t\\t\\t\\tifFalse: ['<off>'].\\n\\t\\\"\\\"\\n\\twording := String\\n\\t\\t\\t\\tstreamContents: [:stream | \\n\\t\\t\\t\\t\\t| index | \\n\\t\\t\\t\\t\\tindex := 1.\\n\\t\\t\\t\\t\\taSymbol\\n\\t\\t\\t\\t\\t\\tkeysAndValuesDo: [:idx :ch | ch isUppercase\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [\\\"\\\"stream nextPutAll: (aSymbol copyFrom: index to: idx - 1) asLowercase.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tstream nextPutAll: ' '.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tindex := idx]].\\n\\t\\t\\t\\t\\tindex < aSymbol size\\n\\t\\t\\t\\t\\t\\tifTrue: [stream nextPutAll: (aSymbol copyFrom: index to: aSymbol size) asLowercase]].\\n\\t\\\"\\\"\\n\\t^ onOff , wording translated! !\\n\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:56'!\\nassureLayoutProperties\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\tprops == self ifTrue:[props _ nil].\\n\\tprops ifNil:[\\n\\t\\tprops _ LayoutProperties new initializeFrom: self.\\n\\t\\tself layoutProperties: props].\\n\\t^props! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:57'!\\nassureTableProperties\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\tprops == self ifTrue:[props _ nil].\\n\\tprops ifNil:[\\n\\t\\tprops _ TableLayoutProperties new initializeFrom: self.\\n\\t\\tself layoutProperties: props].\\n\\tprops includesTableProperties \\n\\t\\tifFalse:[self layoutProperties: (props _ props asTableLayoutProperties)].\\n\\t^props! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellInset\\n\\t\\\"Layout specific. This property specifies an extra inset for each cell in the layout.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props cellInset].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellInset: aNumber\\n\\t\\\"Layout specific. This property specifies an extra inset for each cell in the layout.\\\"\\n\\tself assureTableProperties cellInset: aNumber.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellPositioning\\n\\t\\\"Layout specific. This property describes how the receiver should be layed out in its owner when the bounds of the cell assigned to the receiver do not exactly match its bounds. Possible values are:\\n\\t\\t#topLeft, #topRight, #bottomLeft, #bottomRight, #topCenter, #leftCenter, #rightCenter, #bottomCenter, #center \\n\\twhich align the receiver's bounds with the cell at the given point.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#center] ifNotNil:[props cellPositioning].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:48'!\\ncellPositioningString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self cellPositioning! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:39'!\\ncellPositioning: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be layed out in its owner when the bounds of the cell assigned to the receiver do not exactly match its bounds. Possible values are:\\n\\t\\t#topLeft, #topRight, #bottomLeft, #bottomRight, #topCenter, #leftCenter, #rightCenter, #bottomCenter, #center \\n\\twhich align the receiver's bounds with the cell at the given point.\\\"\\n\\tself assureTableProperties cellPositioning: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:55'!\\ncellSpacing\\n\\t\\\"Layout specific. This property describes how the cell size for each element in a list should be computed.\\n\\t\\t#globalRect - globally equal rectangular cells\\n\\t\\t#globalSquare - globally equal square cells\\n\\t\\t#localRect - locally (e.g., per row/column) equal rectangular cells\\n\\t\\t#localSquare - locally (e.g., per row/column) equal square cells\\n\\t\\t#none - cells are sized based on available row/column constraints\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props cellSpacing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\ncellSpacingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self cellSpacing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:56'!\\ncellSpacing: aSymbol\\n\\t\\\"Layout specific. This property describes how the cell size for each element in a list should be computed.\\n\\t\\t#globalRect - globally equal rectangular cells\\n\\t\\t#globalSquare - globally equal square cells\\n\\t\\t#localRect - locally (e.g., per row/column) equal rectangular cells\\n\\t\\t#localSquare - locally (e.g., per row/column) equal square cells\\n\\t\\t#none - cells are sized based on available row/column constraints\\n\\t\\\"\\n\\tself assureTableProperties cellSpacing: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:56'!\\ndisableTableLayout\\n\\t\\\"Layout specific. Disable laying out the receiver in table layout\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props disableTableLayout].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:06'!\\ndisableTableLayout: aBool\\n\\t\\\"Layout specific. Disable laying out the receiver in table layout\\\"\\n\\tself assureLayoutProperties disableTableLayout: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:57'!\\nhResizing\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#rigid] ifNotNil:[props hResizing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/31/2000 20:45'!\\nhResizingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self hResizing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:06'!\\nhResizing: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\tself assureLayoutProperties hResizing: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 09:59'!\\nlayoutFrame\\n\\t\\\"Layout specific. Return the layout frame describing where the \\n\\treceiver should appear in a proportional layout\\\"\\n\\t^ extension ifNotNil: [extension layoutFrame]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:20'!\\nlayoutFrame: aLayoutFrame\\n\\t\\\"Layout specific. Return the layout frame describing where the receiver should appear in a proportional layout\\\"\\n\\tself layoutFrame == aLayoutFrame ifTrue:[^self].\\n\\tself assureExtension layoutFrame: aLayoutFrame.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 16:38'!\\nlayoutInset\\n\\t\\\"Return the extra inset for layouts\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props layoutInset].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 16:38'!\\nlayoutInset: aNumber\\n\\t\\\"Return the extra inset for layouts\\\"\\n\\tself assureTableProperties layoutInset: aNumber.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 10:00'!\\nlayoutPolicy\\n\\t\\\"Layout specific. Return the layout policy describing how children \\n\\tof the receiver should appear.\\\"\\n\\t^ extension ifNotNil: [ extension layoutPolicy]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:21'!\\nlayoutPolicy: aLayoutPolicy\\n\\t\\\"Layout specific. Return the layout policy describing how children of the receiver should appear.\\\"\\n\\tself layoutPolicy == aLayoutPolicy ifTrue:[^self].\\n\\tself assureExtension layoutPolicy: aLayoutPolicy.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 09:58'!\\nlayoutProperties\\n\\t\\\"Return the current layout properties associated with the \\n\\treceiver\\\"\\n\\t^ extension ifNotNil: [ extension layoutProperties]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:21'!\\nlayoutProperties: newProperties\\n\\t\\\"Return the current layout properties associated with the receiver\\\"\\n\\tself layoutProperties == newProperties ifTrue:[^self].\\n\\tself assureExtension layoutProperties: newProperties.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:58'!\\nlistCentering\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of primary direction\\n\\t\\t#bottomRight - center at end of primary direction\\n\\t\\t#center - center in the middle of primary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topLeft] ifNotNil:[props listCentering].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistCenteringString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listCentering! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:05'!\\nlistCentering: aSymbol\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of primary direction\\n\\t\\t#bottomRight - center at end of primary direction\\n\\t\\t#center - center in the middle of primary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\tself assureTableProperties listCentering: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nlistDirection\\n\\t\\\"Layout specific. This property describes the direction in which a list-like layout should be applied. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\tindicating the direction in which any layout should take place\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topToBottom] ifNotNil:[props listDirection].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistDirectionString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listDirection! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nlistDirection: aSymbol\\n\\t\\\"Layout specific. This property describes the direction in which a list-like layout should be applied. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\tindicating the direction in which any layout should take place\\\"\\n\\tself assureTableProperties listDirection: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nlistSpacing\\n\\t\\\"Layout specific. This property describes how the heights for different rows in a table layout should be handled.\\n\\t\\t#equal - all rows have the same height\\n\\t\\t#none - all rows may have different heights\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props listSpacing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistSpacingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listSpacing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nlistSpacing: aSymbol\\n\\t\\\"Layout specific. This property describes how the heights for different rows in a table layout should be handled.\\n\\t\\t#equal - all rows have the same height\\n\\t\\t#none - all rows may have different heights\\n\\t\\\"\\n\\tself assureTableProperties listSpacing: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nmaxCellSize\\n\\t\\\"Layout specific. This property specifies the maximum size of a table cell.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[SmallInteger maxVal] ifNotNil:[props maxCellSize].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nmaxCellSize: aPoint\\n\\t\\\"Layout specific. This property specifies the maximum size of a table cell.\\\"\\n\\tself assureTableProperties maxCellSize: aPoint.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:00'!\\nminCellSize\\n\\t\\\"Layout specific. This property specifies the minimal size of a table cell.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props minCellSize].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nminCellSize: aPoint\\n\\t\\\"Layout specific. This property specifies the minimal size of a table cell.\\\"\\n\\tself assureTableProperties minCellSize: aPoint.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:01'!\\nreverseTableCells\\n\\t\\\"Layout specific. This property describes if the cells should be treated in reverse order of submorphs.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props reverseTableCells].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nreverseTableCells: aBool\\n\\t\\\"Layout specific. This property describes if the cells should be treated in reverse order of submorphs.\\\"\\n\\tself assureTableProperties reverseTableCells: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:01'!\\nrubberBandCells\\n\\t\\\"Layout specific. This property describes if a parent that is #shrinkWrapped around its children should ignore any #spaceFill children. E.g., when #rubberBandCells is true, the compound layout will always stay at the smallest available size, even though some child may be able to grow.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props rubberBandCells].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nrubberBandCells: aBool\\n\\t\\\"Layout specific. This property describes if a parent that is #shrinkWrapped around its children should ignore any #spaceFill children. E.g., when #rubberBandCells is true, the compound layout will always stay at the smallest available size, even though some child may be able to grow.\\\"\\n\\tself assureTableProperties rubberBandCells: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'dgd 2/16/2003 20:02'!\\nspaceFillWeight\\n\\t\\\"Layout specific. This property describes the relative weight that \\n\\tshould be given to the receiver when extra space is distributed \\n\\tbetween different #spaceFill cells.\\\"\\n\\n\\t^ self\\n\\t\\tvalueOfProperty: #spaceFillWeight\\n\\t\\tifAbsent: [1]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/15/2000 14:16'!\\nspaceFillWeight: aNumber\\n\\t\\\"Layout specific. This property describes the relative weight that should be given to the receiver when extra space is distributed between different #spaceFill cells.\\\"\\n\\taNumber = 1\\n\\t\\tifTrue:[self removeProperty: #spaceFillWeight]\\n\\t\\tifFalse:[self setProperty: #spaceFillWeight toValue: aNumber].\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'tk 10/30/2001 18:39'!\\nvResizeToFit: aBoolean\\n\\taBoolean ifTrue:[\\n\\t\\tself vResizing: #shrinkWrap.\\n\\t] ifFalse:[\\n\\t\\tself vResizing: #rigid.\\n\\t].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:02'!\\nvResizing\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#rigid] ifNotNil:[props vResizing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/31/2000 20:45'!\\nvResizingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self vResizing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nvResizing: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\tself assureLayoutProperties vResizing: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:02'!\\nwrapCentering\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of secondary direction\\n\\t\\t#bottomRight - center at end of secondary direction\\n\\t\\t#center - center in the middle of secondary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topLeft] ifNotNil:[props wrapCentering].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 03:00'!\\nwrapCenteringString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self wrapCentering! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapCentering: aSymbol\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of secondary direction\\n\\t\\t#bottomRight - center at end of secondary direction\\n\\t\\t#center - center in the middle of secondary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\tself assureTableProperties wrapCentering: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapDirection\\n\\t\\\"Layout specific. This property describes the direction along which a list-like layout should be wrapped. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\t\\t#none\\n\\tindicating in which direction wrapping should occur. This direction must be orthogonal to the list direction, that is if listDirection is #leftToRight or #rightToLeft then wrapDirection must be #topToBottom or #bottomToTop and vice versa.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props wrapDirection].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 03:00'!\\nwrapDirectionString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self wrapDirection ! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapDirection: aSymbol\\n\\t\\\"Layout specific. This property describes the direction along which a list-like layout should be wrapped. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\t\\t#none\\n\\tindicating in which direction wrapping should occur. This direction must be orthogonal to the list direction, that is if listDirection is #leftToRight or #rightToLeft then wrapDirection must be #topToBottom or #bottomToTop and vice versa.\\\"\\n\\tself assureTableProperties wrapDirection: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 5/17/2001 17:57'!\\ncurrentVocabulary\\n\\t\\\"Answer the receiver's current vocabulary\\\"\\n\\n\\t| outer |\\n\\t^ (outer _ self ownerThatIsA: StandardViewer orA: ScriptEditorMorph) \\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[outer currentVocabulary]\\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[super currentVocabulary]! !\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 10/10/1999 10:23'!\\nflash\\n\\t| c w |\\n\\tc _ self color.\\n\\tself color: Color black.\\n\\t(w _ self world) ifNotNil: [w displayWorldSafely].\\n\\tself color: c\\n! !\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 7/20/1999 08:13'!\\nscriptPerformer\\n\\t^ self topRendererOrSelf player ifNil: [self]! !\\n\\n\\n!Morph methodsFor: 'menu' stamp: 'sw 11/27/2001 15:21'!\\naddBorderStyleMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Probably one could offer border-style items even if it's not a borderedMorph, so this remains a loose end for the moment\\\"\\n! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 2/15/2004 09:08'!\\naddGestureMenuItems: aMenu hand: aHandMorph\\n\\t\\\"If the receiver wishes the Genie menu items, add a line to the menu and then those Genie items, else do nothing\\\"! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 6/15/2004 07:11'!\\naddGraphModelYellowButtonItemsTo: aCustomMenu event: evt\\n\\t^aCustomMenu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 17:47'!\\naddModelYellowButtonItemsTo: aCustomMenu event: evt \\n\\t\\\"Give my models a chance to add their context-menu items to \\n\\taCustomMenu.\\\"\\n\\tself model\\n\\t\\tifNotNilDo: [:mod |\\n\\t\\t\\tmod\\n\\t\\t\\t\\taddModelYellowButtonMenuItemsTo: aCustomMenu\\n\\t\\t\\t\\tforMorph: self\\n\\t\\t\\t\\thand: evt hand]! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 3/10/2004 19:49'!\\naddMyYellowButtonMenuItemsToSubmorphMenus\\n\\t\\\"Answer true if I have items to add to the context menus of my submorphs\\\"\\n\\n\\t^true! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/13/2004 19:23'!\\naddNestedYellowButtonItemsTo: aMenu event: evt \\n\\t\\\"Add items to aMenu starting with me and proceeding down \\n\\tthrough my submorph chain, \\n\\tletting any submorphs that include the event position \\n\\tcontribute their items to the bottom of the menu, separated by \\n\\ta line.\\\"\\n\\t| underMouse |\\n\\n\\tself addYellowButtonMenuItemsTo: aMenu event: evt.\\n\\n\\tunderMouse := self\\n\\t\\t\\t\\tsubmorphThat: [:each | each containsPoint: evt position]\\n\\t\\t\\t\\tifNone: [^ self].\\n\\n\\t(underMouse addMyYellowButtonMenuItemsToSubmorphMenus\\n\\t\\t\\tand: [underMouse hasYellowButtonMenu])\\n\\t\\tifTrue: [| submenu |\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\tsubmenu := MenuMorph new defaultTarget: underMouse.\\n\\t\\t\\tunderMouse addNestedYellowButtonItemsTo: submenu event: evt.\\n\\t\\t\\taMenu\\n\\t\\t\\t\\tadd: underMouse externalName\\n\\t\\t\\t\\ticon: (underMouse iconOrThumbnailOfSize: 16)\\n\\t\\t\\t\\tsubMenu: submenu\\n\\t\\t]\\n! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 7/28/2005 13:02'!\\naddTitleForHaloMenu: aMenu \\n\\taMenu\\n\\t\\taddTitle: self externalName\\n\\t\\ticon: (self iconOrThumbnailOfSize: (Preferences tinyDisplay ifFalse:[28] ifTrue:[16]))! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 10/13/2004 13:47'!\\naddYellowButtonMenuItemsTo: aMenu event: evt \\n\\t\\\"Populate aMenu with appropriate menu items for a \\n\\tyellow-button (context menu) click.\\\"\\n\\taMenu defaultTarget: self.\\n\\t\\\"\\\"\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\t\\\"\\\"\\n\\tself addModelYellowButtonItemsTo: aMenu event: evt.\\n\\t\\\"\\\"\\n\\tPreferences generalizedYellowButtonMenu\\n\\t\\tifFalse: [^ self].\\n\\t\\\"\\\"\\n\\tPreferences cmdGesturesEnabled\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'inspect' translated action: #inspect].\\n\\t\\\"\\\"\\n\\taMenu addLine.\\n\\tself world selectedObject == self\\n\\t\\tifTrue: [aMenu add: 'deselect' translated action: #removeHalo]\\n\\t\\tifFalse: [aMenu add: 'select' translated action: #addHalo].\\n\\t\\\"\\\"\\n\\t(self isWorldMorph\\n\\t\\t\\tor: [self mustBeBackmost]\\n\\t\\t\\tor: [self wantsToBeTopmost])\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'send to back' translated action: #goBehind.\\n\\t\\t\\taMenu add: 'bring to front' translated action: #comeToFront.\\n\\t\\t\\tself addEmbeddingMenuItemsTo: aMenu hand: evt hand].\\n\\t\\\"\\\"\\n\\tself isWorldMorph\\n\\t\\tifFalse: [\\\"\\\"\\n\\tSmalltalk\\n\\t\\tat: #NCAAConnectorMorph\\n\\t\\tifPresent: [:connectorClass | \\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'connect to' translated action: #startWiring.\\n\\t\\t\\taMenu addLine].\\n\\t\\\"\\\"\\n\\n\\t\\t\\tself isFullOnScreen\\n\\t\\t\\t\\tifFalse: [aMenu add: 'move onscreen' translated action: #goHome]].\\n\\t\\\"\\\"\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\tself addLayoutMenuItems: aMenu hand: evt hand.\\n\\t\\t\\t(owner notNil\\n\\t\\t\\t\\t\\tand: [owner isTextMorph])\\n\\t\\t\\t\\tifTrue: [self addTextAnchorMenuItems: aMenu hand: evt hand]].\\n\\t\\\"\\\"\\n\\tself isWorldMorph\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\tself addToggleItemsToHaloMenu: aMenu].\\n\\t\\\"\\\"\\n\\taMenu addLine.\\n\\tself isWorldMorph\\n\\t\\tifFalse: [aMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:].\\n\\t(self allStringsAfter: nil) isEmpty\\n\\t\\tifFalse: [aMenu add: 'copy text' translated action: #clipText].\\n\\t\\\"\\\"\\n\\tself addExportMenuItems: aMenu hand: evt hand.\\n\\t\\\"\\\"\\n\\t(Preferences noviceMode not\\n\\t\\t\\tand: [self isWorldMorph not])\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'adhere to edge...' translated action: #adhereToEdge].\\n\\t\\\"\\\"\\n\\tself addCustomMenuItems: aMenu hand: evt hand! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 17:23'!\\nbuildYellowButtonMenu: aHand \\n\\t\\\"build the morph menu for the yellow button\\\"\\n\\t| menu |\\n\\tmenu := MenuMorph new defaultTarget: self.\\n\\tself addNestedYellowButtonItemsTo: menu event: ActiveEvent.\\n\\tMenuIcons decorateMenu: menu.\\n\\t^ menu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 4/4/2006 14:43'!\\nhasYellowButtonMenu\\n\\t\\\"Answer true if I have any items at all for a context (yellow \\n\\tbutton) menu.\\\"\\n\\t^ self wantsYellowButtonMenu\\n\\t\\t\\tor: [self models anySatisfy: [:each | each hasModelYellowButtonMenuItems]]! !\\n\\n!Morph methodsFor: 'menu' stamp: 'tak 7/17/2004 18:20'!\\nofferCostumeViewerMenu: aMenu\\n\\t\\\"do nothing\\\"! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 3/10/2004 19:51'!\\noutermostOwnerWithYellowButtonMenu\\n\\t\\\"Answer me or my outermost owner that is willing to contribute menu items to a context menu.\\n\\tDon't include the world.\\\"\\n\\n\\t| outermost |\\n\\toutermost _ self outermostMorphThat: [ :ea |\\n\\t\\tea isWorldMorph not and: [ ea hasYellowButtonMenu ]].\\n\\t^outermost ifNil: [ self hasYellowButtonMenu ifTrue: [ self ] ifFalse: []] ! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/29/2004 13:26'!\\nstartWiring\\n\\tSmalltalk\\n\\t\\tat: #NCAAConnectorMorph\\n\\t\\tifPresent: [:connectorClass | connectorClass newCurvyArrow startWiringFrom: self] ! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 18:20'!\\nwantsYellowButtonMenu\\n\\t\\\"Answer true if the receiver wants a yellow button menu\\\"\\n\\tself\\n\\t\\tvalueOfProperty: #wantsYellowButtonMenu\\n\\t\\tifPresentDo: [:value | ^ value].\\n\\t\\\"\\\"\\n\\tself isInSystemWindow\\n\\t\\tifTrue: [^ false].\\\"\\\"\\n\\t(Preferences noviceMode\\n\\t\\t\\tand: [self isInDockingBar])\\n\\t\\tifTrue: [^ false].\\\"\\\"\\n\\t^ Preferences generalizedYellowButtonMenu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 18:35'!\\nwantsYellowButtonMenu: aBoolean \\n\\t\\\"Change the receiver to wants or not a yellow button menu\\\"\\n\\tself setProperty: #wantsYellowButtonMenu toValue: aBoolean! !\\n\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/6/2004 11:38'!\\nabsorbStateFromRenderer: aRenderer \\n\\t\\\"Transfer knownName, actorState, visible, and player info over from aRenderer, which was formerly imposed above me as a transformation shell but is now going away.\\\"\\n\\n\\t| current |\\n\\t(current _ aRenderer actorStateOrNil) ifNotNil:\\n\\t\\t[self actorState: current.\\n\\t\\taRenderer actorState: nil].\\n\\n\\t(current _ aRenderer knownName) ifNotNil:\\n\\t\\t[self setNameTo: current.\\n\\t\\taRenderer setNameTo: nil].\\n\\n\\t(current _ aRenderer player) ifNotNil:\\n\\t\\t[self player: current.\\n\\t\\tcurrent rawCostume: self.\\n\\t\\taRenderer player: nil].\\n\\n\\tself visible: aRenderer visible! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/27/2001 14:36'!\\naddAddHandMenuItemsForHalo: aMenu hand: aHandMorph\\n\\t\\\"The former charter of this method was to add halo menu items that pertained specifically to the hand. Over time this charter has withered, and most morphs reimplement this method simply to add their morph-specific menu items. So in the latest round, all other implementors in the standard image have been removed. However, this is left here as a hook for the benefit of existing code in client uses.\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 11/15/2003 19:25'!\\naddCopyItemsTo: aMenu\\n\\t\\\"Add copy-like items to the halo menu\\\"\\n\\n\\t| subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:.\\n\\tsubMenu add: 'copy text' translated action: #clipText.\\n\\tsubMenu add: 'copy Postscript' translated action: #clipPostscript.\\n\\tsubMenu add: 'print Postscript to file...' translated target: self selector: #printPSToFile.\\n\\taMenu add: 'copy & print...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/27/1998 03:44'!\\naddCustomHaloMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Add morph-specific items to the given menu which was invoked by the given hand from the halo. To get started, we defer to the counterpart method used with the option-menu, but in time we can have separate menu choices for halo-menus and for option-menus\\\"\\n\\n\\tself addCustomMenuItems: aMenu hand: aHandMorph! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/27/2001 07:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\t\\\"Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.\\\"\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 2/16/2004 13:29'!\\naddExportMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Add export items to the menu\\\"\\n\\n\\taMenu ifNotNil:\\n\\t\\t[ | aSubMenu |\\n\\t\\taSubMenu _ MenuMorph new defaultTarget: self.\\n\\t\\taSubMenu add: 'BMP file' translated action: #exportAsBMP.\\n\\t\\taSubMenu add: 'GIF file' translated action: #exportAsGIF.\\n\\t\\taSubMenu add: 'JPEG file' translated action: #exportAsJPEG.\\n\\t\\taSubMenu add: 'PNG file' translated action: #exportAsPNG.\\n\\t\\taMenu add: 'export...' translated subMenu: aSubMenu]\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 16:44'!\\naddFillStyleMenuItems: aMenu hand: aHand\\n\\t\\\"Add the items for changing the current fill style of the Morph\\\"\\n\\t| menu |\\n\\tself canHaveFillStyles ifFalse:[^aMenu add: 'change color...' translated target: self action: #changeColor].\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tself fillStyle addFillStyleMenuItems: menu hand: aHand from: self.\\n\\tmenu addLine.\\n\\tmenu add: 'solid fill' translated action: #useSolidFill.\\n\\tmenu add: 'gradient fill' translated action: #useGradientFill.\\n\\tmenu add: 'bitmap fill' translated action: #useBitmapFill.\\n\\tmenu add: 'default fill' translated action: #useDefaultFill.\\n\\taMenu add: 'fill style' translated subMenu: menu.\\n\\t\\\"aMenu add: 'change color...' translated action: #changeColor\\\"! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/12/2005 23:13'!\\naddHaloActionsTo: aMenu\\n\\t\\\"Add items to aMenu representing actions requestable via halo\\\"\\n\\n\\t| subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu addTitle: self externalName.\\n\\tsubMenu addStayUpItemSpecial.\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'delete' translated action: #dismissViaHalo.\\n\\tsubMenu balloonTextForLastItem: 'Delete this object -- warning -- can be destructive!!' translated.\\n\\n\\tself maybeAddCollapseItemTo: subMenu.\\n\\tsubMenu add: 'grab' translated action: #openInHand.\\n\\tsubMenu balloonTextForLastItem: 'Pick this object up -- warning, since this removes it from its container, it can have adverse effects.' translated.\\n\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'resize' translated action: #resizeFromMenu.\\n\\tsubMenu balloonTextForLastItem: 'Change the size of this object' translated.\\n\\n\\tsubMenu add: 'duplicate' translated action: #maybeDuplicateMorph.\\n\\tsubMenu balloonTextForLastItem: 'Hand me a copy of this object' translated.\\n\\t\\\"Note that this allows access to the non-instancing duplicate even when this is a uniclass instance\\\"\\n\\n\\tself couldMakeSibling ifTrue:\\n\\t\\t[subMenu add: 'make a sibling' translated action: #handUserASibling.\\n\\t\\tsubMenu balloonTextForLastItem: 'Make a new sibling of this object and hand it to me' translated].\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'property sheet' translated target: self renderedMorph action: #openAPropertySheet.\\n\\tsubMenu balloonTextForLastItem: 'Open a property sheet for me. Allows changing lots of stuff at once.' translated.\\n\\n\\tsubMenu add: 'set color' translated target: self renderedMorph action: #changeColor.\\n\\tsubMenu balloonTextForLastItem: 'Change the color of this object' translated.\\n\\n\\tsubMenu add: 'viewer' translated target: self action: #beViewed.\\n\\tsubMenu balloonTextForLastItem: 'Open a Viewer that will allow everything about this object to be seen and controlled.' translated.\\n\\n\\tsubMenu add: 'tile browser' translated target: self action: #openInstanceBrowserWithTiles.\\n\\tsubMenu balloonTextForLastItem: 'Open a tool that will facilitate tile scripting of this object.' translated.\\n\\n\\tsubMenu add: 'hand me a tile' translated target: self action: #tearOffTile.\\n\\tsubMenu balloonTextForLastItem: 'Hand me a tile represting this object' translated.\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'inspect' translated target: self action: #inspect.\\n\\tsubMenu balloonTextForLastItem: 'Open an Inspector on this object' translated.\\n\\n\\taMenu add: 'halo actions...' translated subMenu: subMenu\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 3/2/2004 22:11'!\\naddMiscExtrasTo: aMenu\\n\\n\\t\\\"Add a submenu of miscellaneous extra items to the menu.\\\"\\n\\n\\n\\n\\t| realOwner realMorph subMenu |\\n\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\n\\t(self isWorldMorph not and: [(self renderedMorph isSystemWindow) not])\\n\\n\\t\\tifTrue: [subMenu add: 'put in a window' translated action: #embedInWindow].\\n\\n\\n\\n\\tself isWorldMorph ifFalse:\\n\\n\\t\\t[subMenu add: 'adhere to edge...' translated action: #adhereToEdge.\\n\\n\\t\\tsubMenu addLine].\\n\\n\\n\\n\\trealOwner _ (realMorph _ self topRendererOrSelf) owner.\\n\\n\\t(realOwner isKindOf: TextPlusPasteUpMorph) ifTrue:\\n\\n\\t\\t[subMenu add: 'GeeMail stuff...' translated subMenu: (realOwner textPlusMenuFor: realMorph)].\\n\\n\\n\\n\\tsubMenu\\n\\n\\t\\tadd: 'add mouse up action' translated action: #addMouseUpAction;\\n\\n\\t\\tadd: 'remove mouse up action' translated action: #removeMouseUpAction;\\n\\n\\t\\tadd: 'hand me tiles to fire this button' translated action: #handMeTilesToFire.\\n\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'arrowheads on pen trails...' translated action: #setArrowheads.\\n\\n\\tsubMenu addLine.\\n\\n\\n\\n\\tsubMenu defaultTarget: self topRendererOrSelf.\\n\\n\\tsubMenu add: 'draw new path' translated action: #definePath.\\n\\n\\tsubMenu add: 'follow existing path' translated action: #followPath.\\n\\n\\tsubMenu add: 'delete existing path' translated action: #deletePath.\\n\\n\\tsubMenu addLine.\\n\\n\\n\\n\\tself addGestureMenuItems: subMenu hand: ActiveHand.\\n\\n\\n\\n\\taMenu add: 'extras...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 1/6/2004 12:53'!\\naddPaintingItemsTo: aMenu hand: aHandMorph \\n\\t| subMenu movies |\\n\\tsubMenu := MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'repaint' translated action: #editDrawing.\\n\\tsubMenu add: 'set rotation center' translated action: #setRotationCenter.\\n\\tsubMenu add: 'reset forward-direction' translated\\n\\t\\taction: #resetForwardDirection.\\n\\tsubMenu add: 'set rotation style' translated action: #setRotationStyle.\\n\\tsubMenu add: 'erase pixels of color' translated\\n\\t\\taction: #erasePixelsOfColor:.\\n\\tsubMenu add: 'recolor pixels of color' translated\\n\\t\\taction: #recolorPixelsOfColor:.\\n\\tsubMenu add: 'reduce color palette' translated action: #reduceColorPalette:.\\n\\tsubMenu add: 'add a border around this shape...' translated\\n\\t\\taction: #addBorderToShape:.\\n\\tmovies := (self world rootMorphsAt: aHandMorph targetOffset) \\n\\t\\t\\t\\tselect: [:m | (m isKindOf: MovieMorph) or: [m isSketchMorph]].\\n\\tmovies size > 1 \\n\\t\\tifTrue: \\n\\t\\t\\t[subMenu add: 'insert into movie' translated action: #insertIntoMovie:].\\n\\taMenu add: 'painting...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/12/2005 23:12'!\\naddPlayerItemsTo: aMenu\\n\\t\\\"Add player-related items to the menu if appropriate\\\"\\n\\n\\t| aPlayer subMenu |\\n\\tself couldMakeSibling ifFalse: [^ self].\\n\\taPlayer _ self topRendererOrSelf player.\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'make a sibling instance' translated target: self action: #makeNewPlayerInstance:.\\n\\tsubMenu balloonTextForLastItem: 'Makes another morph whose player is of the same class as this one. Both siblings will share the same scripts' translated.\\n\\n\\tsubMenu add: 'make multiple siblings...' translated target: self action: #makeMultipleSiblings:.\\n\\tsubMenu balloonTextForLastItem: 'Make any number of sibling instances all at once' translated.\\n\\n\\t(aPlayer belongsToUniClass and: [aPlayer class instanceCount > 1]) ifTrue:\\n\\t\\t[subMenu addLine.\\n\\t\\tsubMenu add: 'make all siblings look like me' translated target: self action: #makeSiblingsLookLikeMe:.\\n\\t\\tsubMenu balloonTextForLastItem: 'make all my sibling instances look like me.' translated.\\n\\n\\t\\tsubMenu add: 'bring all siblings to my location' translated target: self action: #bringAllSiblingsToMe:.\\n\\t\\tsubMenu balloonTextForLastItem: 'find all sibling instances and bring them to me' translated.\\n\\n\\t\\tsubMenu add: 'apply status to all siblngs' translated target: self action: #applyStatusToAllSiblings:.\\n\\t\\tsubMenu balloonTextForLastItem: 'apply the current status of all of my scripts to the scripts of all my siblings' translated].\\n\\n\\t\\tsubMenu add: 'indicate all siblings' translated target: self action: #indicateAllSiblings.\\n\\t\\tsubMenu balloonTextForLastItem: 'momentarily show, by flashing , all of my visible siblings.'.\\n\\n\\t\\taMenu add: 'siblings...' translated subMenu: subMenu\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:34'!\\naddStackItemsTo: aMenu\\n\\t\\\"Add stack-related items to the menu\\\"\\n\\n\\t| stackSubMenu |\\n\\tstackSubMenu _ MenuMorph new defaultTarget: self.\\n\\t(owner notNil and: [owner isStackBackground]) ifTrue:\\n\\t\\t[self isShared\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self couldHoldSeparateDataForEachInstance\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'Background field, shared value' translated target: self action: #putOnBackground.\\n\\t\\t\\t\\t\\t\\tstackSubMenu add: 'Background field, individual values' translated target: self action: #becomeSharedBackgroundField]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'put onto Background' translated target: self action: #putOnBackground]]\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[stackSubMenu add: 'remove from Background' translated target: self action: #putOnForeground.\\n\\t\\t\\t\\tself couldHoldSeparateDataForEachInstance ifTrue:\\n\\t\\t\\t\\t\\t[self holdsSeparateDataForEachInstance\\n\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'start holding separate data for each instance' translated target: self action: #makeHoldSeparateDataForEachInstance]\\n\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'stop holding separate data for each instance' translated target: self action: #stopHoldingSeparateDataForEachInstance].\\n\\t\\t\\t\\t\\t\\t\\tstackSubMenu add: 'be default value on new card' translated target: self action: #setAsDefaultValueForNewCard.\\n\\t\\t\\t\\t\\t\\t\\t(self hasProperty: #thumbnailImage)\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'stop using for reference thumbnail' translated target: self action: #stopUsingForReferenceThumbnail]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'start using for reference thumbnail' translated target: self action: #startUsingForReferenceThumbnail]]].\\n\\t\\t\\t\\tstackSubMenu addLine].\\n\\n\\t(self isStackBackground) ifFalse:\\n\\t\\t[stackSubMenu add: 'be a card in an existing stack...' translated action: #insertAsStackBackground].\\n\\tstackSubMenu add: 'make an instance for my data' translated action: #abstractAModel.\\n\\t(self isStackBackground) ifFalse:\\n\\t\\t[stackSubMenu add: 'become a stack of cards' translated action: #wrapWithAStack].\\n\\taMenu add: 'stacks and cards...' translated subMenu: stackSubMenu\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 2/15/2004 08:19'!\\naddStandardHaloMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Add standard halo items to the menu\\\"\\n\\n\\t| unlockables |\\n\\n\\tself isWorldMorph ifTrue:\\n\\t\\t[^ self addWorldHaloMenuItemsTo: aMenu hand: aHandMorph].\\n\\n\\tself mustBeBackmost ifFalse:\\n\\t\\t[aMenu add: 'send to back' translated action: #goBehind.\\n\\t\\taMenu add: 'bring to front' translated action: #comeToFront.\\n\\t\\tself addEmbeddingMenuItemsTo: aMenu hand: aHandMorph.\\n\\t\\taMenu addLine].\\n\\n\\tself addFillStyleMenuItems: aMenu hand: aHandMorph.\\n\\tself addBorderStyleMenuItems: aMenu hand: aHandMorph.\\n\\tself addDropShadowMenuItems: aMenu hand: aHandMorph.\\n\\tself addLayoutMenuItems: aMenu hand: aHandMorph.\\n\\tself addHaloActionsTo: aMenu.\\n\\towner isTextMorph ifTrue:[self addTextAnchorMenuItems: aMenu hand: aHandMorph].\\n\\taMenu addLine.\\n\\tself addToggleItemsToHaloMenu: aMenu.\\n\\taMenu addLine.\\n\\tself addCopyItemsTo: aMenu.\\n\\tself addPlayerItemsTo: aMenu.\\n\\tself addExportMenuItems: aMenu hand: aHandMorph.\\n\\tself addStackItemsTo: aMenu.\\n\\tself addMiscExtrasTo: aMenu.\\n\\tPreferences noviceMode ifFalse:\\n\\t\\t[self addDebuggingItemsTo: aMenu hand: aHandMorph].\\n\\n\\taMenu addLine.\\n\\taMenu defaultTarget: self.\\n\\n\\taMenu addLine.\\n\\n\\tunlockables _ self submorphs select:\\n\\t\\t[:m | m isLocked].\\n\\tunlockables size == 1 ifTrue:\\n\\t\\t[aMenu\\n\\t\\t\\tadd: ('unlock \\\"{1}\\\"' translated format: unlockables first externalName)\\n\\t\\t\\taction: #unlockContents].\\n\\tunlockables size > 1 ifTrue:\\n\\t\\t[aMenu add: 'unlock all contents' translated action: #unlockContents.\\n\\t\\taMenu add: 'unlock...' translated action: #unlockOneSubpart].\\n\\n\\taMenu defaultTarget: aHandMorph.\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 4/3/2006 14:11'!\\naddToggleItemsToHaloMenu: aMenu\\n\\t\\\"Add standard true/false-checkbox items to the memu\\\"\\n\\n\\t#(\\n\\t\\t(resistsRemovalString toggleResistsRemoval 'whether I should be reistant to easy deletion via the pink X handle' true)\\n\\t\\t(stickinessString toggleStickiness 'whether I should be resistant to a drag done by mousing down on me' true)\\n\\t\\t(lockedString lockUnlockMorph 'when \\\"locked\\\", I am inert to all user interactions' true)\\n\\t\\t(hasClipSubmorphsString changeClipSubmorphs 'whether the parts of objects within me that are outside my bounds should be masked.' false)\\n\\t\\t(hasDirectionHandlesString changeDirectionHandles 'whether direction handles are shown with the halo' false)\\n\\t\\t(hasDragAndDropEnabledString changeDragAndDrop 'whether I am open to having objects dropped into me' false)\\n\\t)\\n\\t\\tselect:[:each | Preferences noviceMode not or:[each fourth]]\\n\\t\\tthenDo:\\n\\t\\t[:each |\\n\\t\\t\\taMenu addUpdating: each first action: each second.\\n\\t\\t\\taMenu balloonTextForLastItem: each third translated].\\n\\n\\tself couldHaveRoundedCorners ifTrue:\\n\\t\\t[aMenu addUpdating: #roundedCornersString action: #toggleCornerRounding.\\n\\t\\taMenu balloonTextForLastItem: 'whether my corners should be rounded' translated]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'wiz 2/14/2006 18:54'!\\naddWorldTargetSightingItems: aCustomMenu hand: aHandMorph\\n\\\"Use cursor to select a point on screen.\\nSet target from all possible morphs under cursor sight.\\\" \\n\\t\\n\\taCustomMenu addLine.\\n\\t\\n\\taCustomMenu add: 'sight target' translated action: #sightWorldTargets:.\\n\\t! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 10/17/2003 22:51'!\\nadhereToEdge\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\t#(top right bottom left - center - topLeft topRight bottomRight bottomLeft - none)\\n\\t\\tdo: [:each |\\n\\t\\t\\teach == #-\\n\\t\\t\\t\\tifTrue: [menu addLine]\\n\\t\\t\\t\\tifFalse: [menu add: each asString translated selector: #setToAdhereToEdge: argument: each]].\\n\\tmenu popUpEvent: self currentEvent in: self world! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 2/22/2003 14:26'!\\nadhereToEdge: edgeSymbol \\n\\t(owner isNil or: [owner isHandMorph]) ifTrue: [^self].\\n\\tself perform: (edgeSymbol , ':') asSymbol\\n\\t\\twithArguments: (Array with: (owner perform: edgeSymbol))! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/3/2000 00:14'!\\nadjustedCenter\\n\\t\\\"Provides a hook for objects to provide a reference point other than the receiver's center,for the purpose of centering a submorph under special circumstances, such as BalloonMorph\\\"\\n\\n\\t^ self center! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/3/2000 00:12'!\\nadjustedCenter: c\\n\\t\\\"Set the receiver's position based on the #adjustedCenter protocol for adhereToEdge. By default this simply sets the receiver's center. Though there are (at its inception anyway) no other implementors of this method, it is required in use with the #adhereToEdge when the centering of a submorph is to be with reference to a rectangle other than the receiver's center.\\\"\\n\\n\\tself center: c! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 10/5/2000 17:20'!\\nallMenuWordings\\n\\t| tempMenu |\\n\\ttempMenu _ self buildHandleMenu: self currentHand.\\n\\ttempMenu allMorphsDo: [:m | m step]. \\\"Get wordings current\\\"\\n\\t^ tempMenu allWordings! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 9/6/2000 18:45'!\\nchangeColor\\n\\t\\\"Change the color of the receiver -- triggered, e.g. from a menu\\\"\\n\\n\\tColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: self activeHand;\\n\\t\\ttarget: self;\\n\\t\\tselector: #fillStyle:;\\n\\t\\toriginalColor: self color;\\n\\t\\tputUpFor: self near: self fullBoundsInWorld! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 11/29/2001 19:57'!\\nchangeDirectionHandles\\n\\t^self wantsDirectionHandles: self wantsDirectionHandles not! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 11/2/2000 15:04'!\\nchangeDragAndDrop\\n\\t^self enableDragNDrop: self dragNDropEnabled not! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 12/17/1998 12:09'!\\nchooseNewGraphic\\n\\t\\\"Used by any morph that can be represented by a graphic\\\"\\n\\tself chooseNewGraphicCoexisting: false\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 09:58'!\\nchooseNewGraphicCoexisting: aBoolean \\n\\t\\\"Allow the user to choose a different form for her form-based morph\\\"\\n\\t| replacee aGraphicalMenu |\\n\\taGraphicalMenu := GraphicalMenu new\\n\\t\\t\\t\\tinitializeFor: self\\n\\t\\t\\t\\twithForms: self reasonableForms\\n\\t\\t\\t\\tcoexist: aBoolean.\\n\\taBoolean\\n\\t\\tifTrue: [self primaryHand attachMorph: aGraphicalMenu]\\n\\t\\tifFalse: [replacee := self topRendererOrSelf.\\n\\t\\t\\treplacee owner replaceSubmorph: replacee by: aGraphicalMenu]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/27/2000 17:34'!\\nchooseNewGraphicFromHalo\\n\\t\\\"Allow the user to select a changed graphic to replace the one in the receiver\\\"\\n\\n\\tself currentWorld abandonAllHalos.\\n\\tself chooseNewGraphicCoexisting: true\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/21/2000 15:21'!\\ncollapse\\n\\tCollapsedMorph new beReplacementFor: self! !\\n\\n!Morph methodsFor: 'menus'!\\ndefaultArrowheadSize\\n\\t\\n\\t^ self class defaultArrowheadSize! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 10/25/2000 23:17'!\\ndoMenuItem: menuString\\n\\t| aMenu anItem aNominalEvent aHand |\\n\\taMenu _ self buildHandleMenu: (aHand _ self currentHand).\\n\\taMenu allMorphsDo: [:m | m step]. \\\"Get wordings current\\\"\\n\\tanItem _ aMenu itemWithWording: menuString.\\n\\tanItem ifNil:\\n\\t\\t[^ self player scriptingError: 'Menu item not found: ', menuString].\\n\\taNominalEvent _ MouseButtonEvent new\\n\\t\\tsetType: #mouseDown\\n\\t\\tposition: anItem bounds center\\n\\t\\twhich: 4 \\\"red\\\"\\n\\t\\tbuttons: 4 \\\"red\\\"\\n\\t\\thand: aHand\\n\\t\\tstamp: nil.\\n\\tanItem invokeWithEvent: aNominalEvent! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:50'!\\nexportAsBMP\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.bmp'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tself imageForm writeBMPfileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:50'!\\nexportAsGIF\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.gif'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tGIFReadWriter putForm: self imageForm onFileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:51'!\\nexportAsJPEG\\n\\t\\\"Export the receiver's image as a JPEG\\\"\\n\\n\\t| fName |\\n\\tfName _ FillInTheBlank request: 'Please enter the name' translated initialAnswer: self externalName,'.jpeg'.\\n\\tfName isEmpty ifTrue: [^ self].\\n\\tself imageForm writeJPEGfileNamed: fName! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:51'!\\nexportAsPNG\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.png'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tPNGReadWriter putForm: self imageForm onFileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:23'!\\nhasDirectionHandlesString\\n\\t^ (self wantsDirectionHandles\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'direction handles' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:24'!\\nhasDragAndDropEnabledString\\n\\t\\\"Answer a string to characterize the drag & drop status of the \\n\\treceiver\\\"\\n\\t^ (self dragNDropEnabled\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'accept drops' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 4/3/2006 14:09'!\\nhelpButton\\n\\t\\\"Answer a button whose action would be to put up help concerning the receiver\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton\\n\\t\\ttarget: self;\\n\\t\\tcolor: ColorTheme current helpColor;\\n\\t\\tborderColor: ColorTheme current helpColor muchDarker;\\n\\t\\tborderWidth: 1;\\n\\t\\tlabel: '?' translated font: Preferences standardButtonFont;\\n\\t\\tactionSelector: #presentHelp;\\n\\t\\tsetBalloonText: 'click here for help' translated.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/27/2005 21:01'!\\ninspectInMorphic\\n\\tself currentHand attachMorph: ((ToolSet inspect: self) extent: 300@200)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/27/2005 21:01'!\\ninspectInMorphic: evt\\n\\tevt hand attachMorph: ((ToolSet inspect: self) extent: 300@200)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:20'!\\nlockedString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\t'locked' status\\\"\\n\\t^ (self isLocked\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'be locked' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 9/21/2000 22:50'!\\nlockUnlockMorph\\n\\t\\\"If the receiver is locked, unlock it; if unlocked, lock it\\\"\\n\\n\\tself isLocked ifTrue: [self unlock] ifFalse: [self lock]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/29/1999 15:34'!\\nmakeNascentScript\\n\\t^ self notYetImplemented! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:15'!\\nmaybeAddCollapseItemTo: aMenu\\n\\t\\\"If appropriate, add a collapse item to the given menu\\\"\\n\\n\\t| anOwner |\\n\\t(anOwner _ self topRendererOrSelf owner) ifNotNil:\\n\\t\\t\\t[anOwner isWorldMorph ifTrue:\\n\\t\\t\\t\\t[aMenu add: 'collapse' translated target: self action: #collapse]]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/22/1999 12:13'!\\nmenuItemAfter: menuString\\n\\t| allWordings |\\n\\tallWordings _ self allMenuWordings.\\n\\t^ allWordings atWrap: ((allWordings indexOf: menuString) + 1)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/22/1999 12:14'!\\nmenuItemBefore: menuString\\n\\t| allWordings |\\n\\tallWordings _ self allMenuWordings.\\n\\t^ allWordings atWrap: ((allWordings indexOf: menuString) - 1)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 9/22/2004 20:30'!\\nmodel\\n\\t^ nil ! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 6/12/2001 21:08'!\\npresentHelp\\n\\t\\\"Present a help message if there is one available\\\"\\n\\n\\tself inform: 'Sorry, no help has been\\nprovided here yet.'! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 18:03'!\\nprintPSToFileNamed: aString \\n\\t\\\"Ask the user for a filename and print this morph as postscript.\\\"\\n\\t| fileName rotateFlag psCanvasType psExtension |\\n\\tfileName := aString asFileName.\\n\\tpsCanvasType _ PostscriptCanvas defaultCanvasType.\\n\\tpsExtension _ psCanvasType defaultExtension.\\n\\tfileName := FillInTheBlank request: (String streamContents: [ :s |\\n\\t\\ts nextPutAll: ('File name? (\\\"{1}\\\" will be added to end)' translated format: {psExtension})])\\n\\t\\t\\tinitialAnswer: fileName.\\n\\tfileName isEmpty\\n\\t\\tifTrue: [^ Beeper beep].\\n\\t(fileName endsWith: psExtension)\\n\\t\\tifFalse: [fileName := fileName , psExtension].\\n\\trotateFlag := ((PopUpMenu labels: 'portrait (tall)\\nlandscape (wide)' translated)\\n\\t\\t\\t\\tstartUpWithCaption: 'Choose orientation...' translated)\\n\\t\\t\\t\\t= 2.\\n\\t((FileStream newFileNamed: fileName asFileName) converter: TextConverter defaultSystemConverter)\\n\\t\\tnextPutAll: (psCanvasType morphAsPostscript: self rotated: rotateFlag);\\n\\t\\t close! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/27/2000 06:39'!\\nputOnBackground\\n\\t\\\"Place the receiver, formerly private to its card, onto the shared background. If the receiver needs data carried on its behalf by the card, such data will be represented on every card.\\\"\\n\\n\\t(self hasProperty: #shared) ifTrue: [^ self]. \\\"Already done\\\"\\n\\n\\tself setProperty: #shared toValue: true.\\n\\tself stack ifNotNil: [self stack reassessBackgroundShape]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 9/5/2003 18:25'!\\nputOnForeground\\n\\t\\\"Place the receiver, formerly on the background, onto the foreground. If the receiver needs data carried on its behalf by the card, those data will be lost, so in this case get user confirmation before proceeding.\\\"\\n\\n\\tself holdsSeparateDataForEachInstance \\\"later add the refinement of not putting up the following confirmer if only a single instance of the current background's uniclass exists\\\"\\n\\t\\tifTrue:\\n\\t\\t\\t[self confirm: 'Caution -- every card of this background\\nformerly had its own value for this\\nitem. If you put it on the foreground,\\nthe values of this item on all other\\ncards will be lost' translated\\n\\t\\t\\t\\torCancel: [^ self]].\\n\\n\\tself removeProperty: #shared.\\n\\tself stack reassessBackgroundShape.\\n\\t\\\"still work to be done here!!\\\"! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 22:42'!\\nreasonableBitmapFillForms\\n\\t\\\"Answer an OrderedCollection of forms that could be used to replace my bitmap fill, with my current form first.\\\"\\n\\t| reasonableForms myGraphic |\\n\\treasonableForms := self class allSketchMorphForms.\\n\\treasonableForms addAll: Imports default images.\\n\\treasonableForms addAll: (BitmapFillStyle allSubInstances collect:[:f| f form]).\\n\\treasonableForms\\n\\t\\tremove: (myGraphic := self fillStyle form)\\n\\t\\tifAbsent: [].\\n\\treasonableForms := reasonableForms asOrderedCollection.\\n\\treasonableForms addFirst: myGraphic.\\n\\t^reasonableForms! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 09:55'!\\nreasonableForms\\n\\t\\\"Answer an OrderedCollection of forms that could be used to replace my form, with my current form first.\\\"\\n\\t| reasonableForms myGraphic |\\n\\treasonableForms := self class allSketchMorphForms.\\n\\treasonableForms addAll: Imports default images.\\n\\treasonableForms\\n\\t\\tremove: (myGraphic := self form)\\n\\t\\tifAbsent: [].\\n\\treasonableForms := reasonableForms asOrderedCollection.\\n\\treasonableForms addFirst: myGraphic.\\n\\t^reasonableForms! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:36'!\\nresetForwardDirection\\n\\tself forwardDirection: 0.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:18'!\\nresistsRemovalString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\t'resistsRemoval' status\\\"\\n\\t^ (self resistsRemoval\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'resist being deleted' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 16:58'!\\nsetArrowheads\\n\\t\\\"Let the user edit the size of arrowheads for this object\\\"\\n\\n\\t| aParameter result |\\n\\taParameter _ self renderedMorph valueOfProperty: #arrowSpec ifAbsent:\\n\\t\\t[Preferences parameterAt: #arrowSpec ifAbsent: [5 @ 4]].\\n\\tresult _ Morph obtainArrowheadFor: 'Head size for arrowheads: ' translated defaultValue: aParameter asString.\\n\\tresult ifNotNil:\\n\\t\\t\\t[self renderedMorph setProperty: #arrowSpec toValue: result]\\n\\t\\tifNil:\\n\\t\\t\\t[Beeper beep]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:15'!\\nsetRotationCenter\\n\\t| p |\\n\\tself world displayWorld.\\n\\tCursor crossHair showWhile:\\n\\t\\t[p _ Sensor waitButton].\\n\\tSensor waitNoButton.\\n\\tself setRotationCenterFrom: (self transformFromWorld globalPointToLocal: p).\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:14'!\\nsetRotationCenterFrom: aPoint\\n\\tself rotationCenter: (aPoint - self bounds origin) / self bounds extent asFloatPoint.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'di 12/21/2000 17:18'!\\nsetToAdhereToEdge: anEdge\\n\\tanEdge ifNil: [^ self].\\n\\tanEdge == #none ifTrue: [^ self removeProperty: #edgeToAdhereTo].\\n\\tself setProperty: #edgeToAdhereTo toValue: anEdge.\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 8/30/1998 09:42'!\\nsnapToEdgeIfAppropriate\\n\\t| edgeSymbol oldBounds aWorld |\\n\\t(edgeSymbol _ self valueOfProperty: #edgeToAdhereTo) ifNotNil:\\n\\t\\t[oldBounds _ bounds.\\n\\t\\tself adhereToEdge: edgeSymbol.\\n\\t\\tbounds ~= oldBounds ifTrue: [(aWorld _ self world) ifNotNil: [aWorld viewBox ifNotNil:\\n\\t\\t\\t[aWorld displayWorld]]]]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:19'!\\nstickinessString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\tstickiness status\\\"\\n\\t^ (self isSticky\\n\\t\\tifTrue: ['<yes>']\\n\\t\\tifFalse: ['<no>'])\\n\\t\\t, 'resist being picked up' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/6/2004 12:16'!\\ntransferStateToRenderer: aRenderer\\n\\t\\\"Transfer knownName, actorState, visible, and player info over to aRenderer, which is being imposed above me as a transformation shell\\\"\\n\\n\\t| current |\\n\\t(current _ self actorStateOrNil) ifNotNil:\\n\\t\\t[aRenderer actorState: current.\\n\\t\\tself actorState: nil].\\n\\n\\t(current _ self knownName) ifNotNil:\\n\\t\\t[aRenderer setNameTo: current.\\n\\t\\tself setNameTo: nil].\\n\\n\\t(current _ self player) ifNotNil:\\n\\t\\t[aRenderer player: current.\\n\\t\\tself player rawCostume: aRenderer.\\n\\t\\t\\\"NB player is redundantly pointed to in the extension of both the renderer and the rendee; this is regrettable but many years ago occasionally people tried to make that clean but always ran into problems iirc\\\"\\n\\t\\t\\\"self player: nil\\\"].\\n\\n\\taRenderer simplySetVisible: self visible\\n\\n\\n\\n \\n\\n\\t\\t! !\\n\\n!Morph methodsFor: 'menus' stamp: 'RAA 11/14/2000 13:46'!\\nuncollapseSketch\\n\\n\\t| uncollapsedVersion w whomToDelete |\\n\\n\\t(w _ self world) ifNil: [^self].\\n\\tuncollapsedVersion _ self valueOfProperty: #uncollapsedMorph.\\n\\tuncollapsedVersion ifNil: [^self].\\n\\twhomToDelete _ self valueOfProperty: #collapsedMorphCarrier.\\n\\tuncollapsedVersion setProperty: #collapsedPosition toValue: whomToDelete position.\\n\\n\\twhomToDelete delete.\\n\\tw addMorphFront: uncollapsedVersion.\\n\\n! !\\n\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 9/18/2004 16:24'!\\naddEmbeddingMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Construct a menu offerring embed targets for the receiver. If the incoming menu is is not degenerate, add the constructed menu as a submenu; in any case, answer the embed-target menu\\\"\\n\\n\\t| menu potentialEmbeddingTargets |\\n\\n\\tpotentialEmbeddingTargets := self potentialEmbeddingTargets.\\n\\tpotentialEmbeddingTargets size > 1 ifFalse:[^ self].\\n\\n\\tmenu := MenuMorph new defaultTarget: self.\\n\\n\\tpotentialEmbeddingTargets reverseDo: [:m | \\n\\t\\t\\tmenu\\n\\t\\t\\t\\tadd: (m knownName ifNil:[m class name asString])\\n\\t\\t\\t\\ttarget: m\\n\\t\\t\\t\\tselector: #addMorphFrontFromWorldPosition:\\n\\t\\t\\t\\targument: self topRendererOrSelf.\\n\\n\\t\\t\\tmenu lastItem icon: (m iconOrThumbnailOfSize: 16).\\n\\n\\t\\t\\tself owner == m ifTrue:[menu lastItem emphasis: 1].\\n\\t\\t].\\n\\n\\taMenu add:'embed into' translated subMenu: menu.\\n\\n\\t^ menu! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/29/2001 02:50'!\\napplyStatusToAllSiblings: evt\\n\\t\\\"Apply the statuses of all my scripts to the script status of all my siblings\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPlayer instantiatedUserScriptsDo: \\n\\t\\t[:aScriptInstantiation | aScriptInstantiation assignStatusToAllSiblings]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:51'!\\nbeThisWorldsModel\\n\\n\\tself world setModel: self.\\n\\tself model: nil slotName: nil.\\t\\\"A world's model cannot have another model\\\"! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'yo 3/15/2005 14:45'!\\nblueButtonDown: anEvent\\n\\t\\\"Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph.\\\"\\n\\t| h tfm doNotDrag |\\n\\th _ anEvent hand halo.\\n\\t\\\"Prevent wrap around halo transfers originating from throwing the event back in\\\"\\n\\tdoNotDrag _ false.\\n\\th ifNotNil:[\\n\\t\\t(h innerTarget == self) ifTrue:[doNotDrag _ true].\\n\\t\\t(h innerTarget hasOwner: self) ifTrue:[doNotDrag _ true].\\n\\t\\t(self hasOwner: h target) ifTrue:[doNotDrag _ true]].\\n\\n\\ttfm _ (self transformedFrom: nil) inverseTransformation.\\n\\n\\t\\\"cmd-drag on flexed morphs works better this way\\\"\\n\\th _ self addHalo: (anEvent transformedBy: tfm).\\n\\th ifNil: [^ self].\\n\\tdoNotDrag ifTrue:[^self].\\n\\t\\\"Initiate drag transition if requested\\\"\\n\\tanEvent hand \\n\\t\\twaitForClicksOrDrag: h\\n\\t\\tevent: (anEvent transformedBy: tfm)\\n\\t\\tselectors: { nil. nil. nil. #dragTarget:. }\\n\\t\\tthreshold: 5.\\n\\t\\\"Pass focus explicitly here\\\"\\n\\tanEvent hand newMouseFocus: h.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 9/15/2000 20:25'!\\nblueButtonUp: anEvent\\n\\t\\\"Ignored. Theoretically we should never get here since control is transferred to the halo on #blueButtonDown: but subclasses may implement this differently.\\\"! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/19/2001 18:10'!\\nbringAllSiblingsToMe: evt\\n\\t\\\"bring all siblings of the receiver's player found in the same container to the receiver's location.\\\"\\n\\n\\t| aPlayer aPosition aContainer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPosition _ self topRendererOrSelf position.\\n\\taContainer _ self topRendererOrSelf owner.\\n\\t(aPlayer class allInstances copyWithout: aPlayer) do:\\n\\t\\t[:each |\\n\\t\\t\\t(aContainer submorphs includes: each costume) ifTrue:\\n\\t\\t\\t\\t[each costume position: aPosition]]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 9/18/2004 17:23'!\\nbuildHandleMenu: aHand\\n\\t\\\"Build the morph menu for the given morph's halo's menu handle. This menu has two sections. The first section contains commands that are interpreted by the hand; the second contains commands provided by the target morph. This method allows the morph to decide which items should be included in the hand's section of the menu.\\\"\\n\\n\\t| menu |\\n\\n\\t(Preferences generalizedYellowButtonMenu\\n\\t\\t\\tand: [Preferences noviceMode])\\n\\t\\tifTrue: [^ self buildYellowButtonMenu: aHand].\\n\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addStayUpItem.\\n\\tmenu addLine.\\n\\tself addStandardHaloMenuItemsTo: menu hand: aHand.\\n\\tmenu defaultTarget: aHand.\\n\\tself addAddHandMenuItemsForHalo: menu hand: aHand.\\n\\tmenu defaultTarget: self.\\n\\tself addCustomHaloMenuItems: menu hand: aHand.\\n\\tmenu defaultTarget: aHand.\\n\\t^ menu\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 11/15/2003 19:29'!\\nbuildMetaMenu: evt\\n\\t\\\"Build the morph menu. This menu has two sections. The first section contains commands that are handled by the hand; the second contains commands handled by the argument morph.\\\"\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addStayUpItem.\\n\\tmenu add: 'grab' translated action: #grabMorph:.\\n\\tmenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:.\\n\\tself maybeAddCollapseItemTo: menu.\\n\\tmenu add: 'delete' translated action: #dismissMorph:.\\n\\tmenu addLine.\\n\\tmenu add: 'copy text' translated action: #clipText.\\n\\tmenu add: 'copy Postscript' translated action: #clipPostscript.\\n\\tmenu add: 'print Postscript to file...' translated action: #printPSToFile.\\n\\tmenu addLine.\\n\\tmenu add: 'go behind' translated action: #goBehind.\\n\\tmenu add: 'add halo' translated action: #addHalo:.\\n\\tmenu add: 'duplicate' translated action: #maybeDuplicateMorph:.\\n\\n\\tself addEmbeddingMenuItemsTo: menu hand: evt hand.\\n\\n\\tmenu add: 'resize' translated action: #resizeMorph:.\\n\\t\\\"Give the argument control over what should be done about fill styles\\\"\\n\\tself addFillStyleMenuItems: menu hand: evt hand.\\n\\tself addDropShadowMenuItems: menu hand: evt hand.\\n\\tself addLayoutMenuItems: menu hand: evt hand.\\n\\tmenu addUpdating: #hasClipSubmorphsString target: self selector: #changeClipSubmorphs argumentList: #().\\n\\tmenu addLine.\\n\\n\\t(self morphsAt: evt position) size > 1 ifTrue:\\n\\t\\t[menu add: 'submorphs...' translated\\n\\t\\t\\ttarget: self\\n\\t\\t\\tselector: #invokeMetaMenuAt:event:\\n\\t\\t\\targument: evt position].\\n\\tmenu addLine.\\n\\tmenu add: 'inspect' translated selector: #inspectAt:event: argument: evt position.\\n\\tmenu add: 'explore' translated action: #explore.\\n\\tmenu add: 'browse hierarchy' translated action: #browseHierarchy.\\n\\tmenu add: 'make own subclass' translated action: #subclassMorph.\\n\\tmenu addLine.\\n\\tmenu add: 'set variable name...' translated action: #choosePartName.\\n\\t(self isMorphicModel) ifTrue:\\n\\t\\t[menu add: 'save morph as prototype' translated action: #saveAsPrototype.\\n\\t\\t(self ~~ self world modelOrNil) ifTrue:\\n\\t\\t\\t [menu add: 'become this world''s model' translated action: #beThisWorldsModel]].\\n\\tmenu add: 'save morph in file' translated action: #saveOnFile.\\n\\t(self hasProperty: #resourceFilePath)\\n\\t\\tifTrue: [((self valueOfProperty: #resourceFilePath) endsWith: '.morph')\\n\\t\\t\\t\\tifTrue: [menu add: 'save as resource' translated action: #saveAsResource].\\n\\t\\t\\t\\tmenu add: 'update from resource' translated action: #updateFromResource]\\n\\t\\tifFalse: [menu add: 'attach to resource' translated action: #attachToResource].\\n\\tmenu add: 'show actions' translated action: #showActions.\\n\\tmenu addLine.\\n\\tself addDebuggingItemsTo: menu hand: evt hand.\\n\\n\\tself addCustomMenuItems: menu hand: evt hand.\\n\\t^ menu\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 18:54'!\\nchangeColorTarget: anObject selector: aSymbol originalColor: aColor hand: aHand\\n\\t\\\"Put up a color picker for changing some kind of color. May be modal or modeless, depending on #modalColorPickers setting\\\"\\n\\tself flag: #arNote. \\\"Simplify this due to anObject == self for almost all cases\\\"\\n\\t^ ColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: aHand;\\n\\t\\ttarget: anObject;\\n\\t\\tselector: aSymbol;\\n\\t\\toriginalColor: aColor;\\n\\t\\tputUpFor: anObject near: (anObject isMorph\\n\\t\\t\\t\\t\\tifTrue:\\t [Rectangle center: self position extent: 20]\\n\\t\\t\\t\\t\\tifFalse: [anObject == self world\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [anObject viewBox bottomLeft + (20@-20) extent: 200]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [anObject fullBoundsInWorld]]);\\n\\t\\tyourself! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:44'!\\ncopyToPasteBuffer: evt\\n\\tself okayToDuplicate ifTrue:[evt hand copyToPasteBuffer: self].! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'mir 3/17/2006 18:02'!\\ndismissMorph\\n\\t\\\"This is called from an explicit halo destroy/delete action.\\\"\\n\\n\\t| w |\\n\\tw _ self world ifNil:[^self].\\n\\tw abandonAllHalos; stopStepping: self.\\n\\tself delete! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'mir 3/17/2006 18:01'!\\ndismissMorph: evt\\n\\tself dismissMorph! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 2/19/2006 12:41'!\\nduplicateMorphImage: evt \\n\\t\\\"Make and return a imageMorph of the receiver's argument imageForm\\\"\\n\\t| dup |\\n\\tdup := self asSnapshotThumbnail withSnapshotBorder.\\n\\tdup bounds: self bounds.\\n\\tevt hand grabMorph: dup from: owner.\\n\\t\\\"duplicate was ownerless so use #grabMorph:from: here\\\"\\n\\t^ dup! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 11/4/2000 17:56'!\\nduplicateMorph: evt\\n\\t\\\"Make and return a duplicate of the receiver's argument\\\"\\n\\t| dup |\\n\\tdup _ self duplicate.\\n\\tevt hand grabMorph: dup from: owner. \\\"duplicate was ownerless so use #grabMorph:from: here\\\"\\n\\t^dup! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/7/2000 20:53'!\\nembedInto: evt\\n\\t\\\"Embed the receiver into some other morph\\\"\\n\\t| menu target |\\n\\tmenu _ CustomMenu new.\\n\\tself potentialEmbeddingTargets do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUpWithCaption: ('Place ', self externalName, ' in...').\\n\\ttarget ifNil:[^self].\\n\\ttarget addMorphFront: self fromWorldPosition: self positionInWorld.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/6/2000 16:37'!\\ngrabMorph: evt\\n\\n\\tevt hand grabMorph: self! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/7/2000 18:44'!\\nhandlerForBlueButtonDown: anEvent\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event.\\n\\tNote: Halos handle blue button events themselves so we will only be asked if there is currently no halo on top of us.\\\"\\n\\tself wantsHaloFromClick ifFalse:[^nil].\\n\\tanEvent handler ifNil:[^self].\\n\\tanEvent handler isPlayfieldLike ifTrue:[^self]. \\\"by default exclude playfields\\\"\\n\\t(anEvent shiftPressed)\\n\\t\\tifFalse:[^nil] \\\"let outer guy have it\\\"\\n\\t\\tifTrue:[^self] \\\"let me have it\\\"\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/12/2000 17:07'!\\nhandlerForMetaMenu: evt\\n\\t\\\"Return the prospective handler for invoking the meta menu. By default, the top-most morph in the innermost world gets this menu\\\"\\n\\tself isWorldMorph ifTrue:[^self].\\n\\tevt handler ifNotNil:[evt handler isWorldMorph ifTrue:[^self]].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'yo 2/12/2005 15:25'!\\nindicateAllSiblings\\n\\t\\\"Indicate all the receiver and all its siblings by flashing momentarily.\\\"\\n\\n\\t| aPlayer allBoxes |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [^ self \\\"error: 'not uniclass'\\\"].\\n\\tallBoxes _ aPlayer class allInstances\\n\\t\\tselect: [:m | m costume world == ActiveWorld]\\n\\t\\tthenCollect: [:m | m costume boundsInWorld].\\n\\n\\t5 timesRepeat:\\n\\t\\t[Display flashAll: allBoxes andWait: 120]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/10/2000 14:09'!\\ninspectAt: aPoint event: evt\\n\\t| menu morphs target |\\n\\tmenu _ CustomMenu new.\\n\\tmorphs _ self morphsAt: aPoint.\\n\\t(morphs includes: self) ifFalse:[morphs _ morphs copyWith: self].\\n\\tmorphs do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUpWithCaption: ('inspect whom?\\n(deepest at top)').\\n\\ttarget ifNil:[^self].\\n\\ttarget inspectInMorphic: evt! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/10/2000 14:26'!\\ninvokeMetaMenuAt: aPoint event: evt\\n\\t| menu morphs target |\\n\\tmenu _ CustomMenu new.\\n\\tmorphs _ self morphsAt: aPoint.\\n\\t(morphs includes: self) ifFalse:[morphs _ morphs copyWith: self].\\n\\tmorphs size = 1 ifTrue:[morphs first invokeMetaMenu: evt].\\n\\tmorphs do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUp.\\n\\ttarget ifNil:[^self].\\n\\ttarget invokeMetaMenu: evt! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'fc 4/27/2004 21:54'!\\ninvokeMetaMenu: evt\\n\\t| menu |\\n\\tmenu _ self buildMetaMenu: evt.\\n\\tmenu addTitle: self externalName.\\n\\tself world ifNotNil: [\\n\\t\\tmenu popUpEvent: evt in: self world\\n\\t]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 4/12/2005 23:09'!\\nmakeMultipleSiblings: evt\\n\\t\\\"Make multiple siblings, first prompting the user for how many\\\"\\n\\n\\t| result |\\n\\tself topRendererOrSelf couldMakeSibling ifFalse: [^ Beeper beep].\\n\\tresult _ FillInTheBlank request: 'how many siblings do you want?' translated initialAnswer: '2'.\\n\\tresult isEmptyOrNil ifTrue: [^ self].\\n\\tresult first isDigit ifFalse: [^ Beeper beep].\\n\\tself topRendererOrSelf makeSiblings: result asInteger.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 19:20'!\\nmakeNewPlayerInstance: evt\\n\\t\\\"Make a duplicate of the receiver's argument. This is called only where the argument has an associated Player as its costumee, and the intent here is to make another instance of the same uniclass as the donor Player itself. Much works, but there are flaws so this shouldn't be used without recognizing the risks\\\"\\n\\n\\tevt hand attachMorph: self usableSiblingInstance! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/12/2001 22:47'!\\nmakeSiblingsLookLikeMe: evt\\n\\t\\\"Make all my siblings wear the same costume that I am wearing.\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPlayer class allInstancesDo:\\n\\t\\t[:anInstance | anInstance == aPlayer ifFalse:\\n\\t\\t\\t[anInstance wearCostumeOf: aPlayer]]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/29/2001 17:11'!\\nmakeSiblings: count\\n\\t\\\"Make multiple sibling, and return the list\\\"\\n\\n\\t| aPosition anInstance listOfNewborns |\\n\\taPosition _ self position.\\n\\tlistOfNewborns _ (1 to: count asInteger) asArray collect: \\n\\t\\t[:anIndex |\\n\\t\\t\\tanInstance _ self usableSiblingInstance.\\n\\t\\t\\towner addMorphFront: anInstance.\\n\\t\\t\\taPosition _ aPosition + (10@10).\\n\\t\\t\\tanInstance position: aPosition.\\n\\t\\t\\tanInstance].\\n\\tself currentWorld startSteppingSubmorphsOf: self topRendererOrSelf owner.\\n\\t^ listOfNewborns! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 4/19/2005 14:55'!\\nmaybeDuplicateMorph\\n\\t\\\"Maybe duplicate the morph\\\"\\n\\n\\tself okayToDuplicate ifTrue:\\n\\t\\t[self topRendererOrSelf duplicate openInHand]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 17:32'!\\nmaybeDuplicateMorph: evt\\n\\tself okayToDuplicate ifTrue:[^self duplicateMorph: evt]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'RAA 2/19/2001 16:52'!\\nopenAPropertySheet\\n\\n\\tObjectPropertiesMorph basicNew\\n\\t\\ttargetMorph: self;\\n\\t\\tinitialize;\\n\\t\\topenNearTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'RAA 3/15/2001 12:56'!\\nopenATextPropertySheet\\n\\n\\t\\\"should only be sent to morphs that are actually supportive\\\"\\n\\n\\tTextPropertiesMorph basicNew\\n\\t\\ttargetMorph: self;\\n\\t\\tinitialize;\\n\\t\\topenNearTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 1/2/2005 01:06'!\\npotentialEmbeddingTargets\\n\\t\\\"Return the potential targets for embedding the receiver\\\"\\n\\n\\t| oneUp topRend |\\n\\t(oneUp _ (topRend _ self topRendererOrSelf) owner) ifNil:[^#()].\\n\\t^ (oneUp morphsAt: topRend referencePosition behind: topRend unlocked: true) select:\\n\\t\\t[:m | m isFlexMorph not]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/17/2004 22:17'!\\npotentialTargets\\n\\t\\\"Return the potential targets for the receiver.\\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\towner ifNil:[^#()].\\n\\t^owner morphsAt: self referencePosition behind: self unlocked: true not! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 02:46'!\\npotentialTargetsAt: aPoint \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\towner\\n\\t\\tifNil: [^ #()].\\n\\t^ owner\\n\\t\\tmorphsAt: aPoint\\n\\t\\t! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 11/27/2001 14:59'!\\nresizeFromMenu\\n\\t\\\"Commence an interaction that will resize the receiver\\\"\\n\\n\\tself resizeMorph: ActiveEvent! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'st 9/14/2004 12:30'!\\nresizeMorph: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo: [:newPoint | \\n\\t\\tself extent: (self griddedPoint: newPoint) - self bounds topLeft].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:50'!\\nsaveAsPrototype\\n\\t(SelectionMenu confirm: 'Make this morph the prototype for ', self class printString, '?')\\n\\t\\tifFalse: [^ self].\\n\\tself class prototype: self.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 9/27/2005 20:29'!\\nshowActions\\n\\t\\\"Put up a message list browser of all the code that this morph \\n\\twould run for mouseUp, mouseDown, mouseMove, mouseEnter, \\n\\tmouseLeave, and \\n\\tmouseLinger. tk 9/13/97\\\"\\n\\t| list cls selector adder |\\n\\tlist := SortedCollection new.\\n\\tadder := [:mrClass :mrSel | list\\n\\t\\t\\t\\tadd: (MethodReference new setStandardClass: mrClass methodSymbol: mrSel)].\\n\\t\\\"the eventHandler\\\"\\n\\tself eventHandler\\n\\t\\tifNotNil: [list := self eventHandler methodRefList.\\n\\t\\t\\t(self eventHandler handlesMouseDown: nil)\\n\\t\\t\\t\\tifFalse: [adder value: HandMorph value: #grabMorph:]].\\n\\t\\\"If not those, then non-default raw events\\\"\\n\\t#(#keyStroke: #mouseDown: #mouseEnter: #mouseLeave: #mouseMove: #mouseUp: #doButtonAction )\\n\\t\\tdo: [:sel | \\n\\t\\t\\tcls := self class whichClassIncludesSelector: sel.\\n\\t\\t\\tcls\\n\\t\\t\\t\\tifNotNil: [\\\"want more than default behavior\\\"\\n\\t\\t\\t\\t\\tcls == Morph\\n\\t\\t\\t\\t\\t\\tifFalse: [adder value: cls value: sel]]].\\n\\t\\\"The mechanism on a Button\\\"\\n\\t(self respondsTo: #actionSelector)\\n\\t\\tifTrue: [\\\"A button\\\"\\n\\t\\t\\tselector := self actionSelector.\\n\\t\\t\\tcls := self target class whichClassIncludesSelector: selector.\\n\\t\\t\\tcls\\n\\t\\t\\t\\tifNotNil: [\\\"want more than default behavior\\\"\\n\\t\\t\\t\\t\\tcls == Morph\\n\\t\\t\\t\\t\\t\\tifFalse: [adder value: cls value: selector]]].\\n\\tToolSet openMessageList: list name: 'Actions of ' , self printString autoSelect: false! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 19:21'!\\nshowHiders\\n\\tself allMorphsDo:[:m | m show]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/13/2006 22:09'!\\nsightTargets: event \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\t| bullseye |\\n\\towner\\n\\t\\tifNil: [^ #()].\\n\\tbullseye := Point fromUserWithCursor: Cursor target.\\n\\tself targetFromMenu: (self potentialTargetsAt: bullseye) asKnownNameMenu popupAt: bullseye! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/13/2006 22:10'!\\nsightWorldTargets: event \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\t| bullseye myWorld |\\n\\tmyWorld := self world\\n\\t\\tifNil: [^ #()].\\n\\tbullseye := Point fromUserWithCursor: Cursor target.\\n\\tself targetFromMenu: ( myWorld morphsAt: bullseye) asKnownNameMenu popupAt: bullseye! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:50'!\\nsubclassMorph\\n\\t\\\"Create a new subclass of this morph's class and make this morph be an instance of it.\\\"\\n\\n\\t| oldClass newClassName newClass newMorph |\\n\\toldClass _ self class.\\n\\tnewClassName _ FillInTheBlank\\n\\t\\trequest: 'Please give this new class a name'\\n\\t\\tinitialAnswer: oldClass name.\\n\\tnewClassName = '' ifTrue: [^ self].\\n\\t(Smalltalk includesKey: newClassName)\\n\\t\\tifTrue: [^ self inform: 'Sorry, there is already a class of that name'].\\n\\n\\tnewClass _ oldClass subclass: newClassName asSymbol\\n\\t\\tinstanceVariableNames: ''\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: oldClass category asString.\\n\\tnewMorph _ self as: newClass.\\n\\tself become: newMorph.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 01:25'!\\ntargetFromMenu: aMenu \\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| newTarget |\\n\\t\\n\\tnewTarget := aMenu startUpWithCaption: self externalName , ' targets...'.\\n\\tnewTarget\\n\\t\\tifNil: [^ self].\\n\\tself target: newTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 12:22'!\\ntargetFromMenu: aMenu popupAt: aPoint \\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| newTarget |\\n\\tnewTarget := aMenu startUpWithCaption: self externalName , ' targets... '\\n\\tat: aPoint .\\n\\t\\\"self halt .\\\"\\n\\tnewTarget\\n\\t\\tifNil: [^ self].\\n\\tself target: newTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/17/2004 23:27'!\\ntargetWith: evt\\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| menu newTarget |\\n\\tmenu _ CustomMenu new.\\n\\tself potentialTargets do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\tnewTarget _ menu startUpWithCaption: ( self externalName, ' targets...').\\n\\tnewTarget ifNil:[^self].\\n\\tself target: newTarget.! !\\n\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'dgd 9/27/2004 12:12'!\\nroundUpStrays\\n\\tself submorphs\\n\\t\\tdo: [:each | each roundUpStrays]! !\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'sw 7/20/2001 00:15'!\\nsetExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\n\\tself extent: anExtent! !\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'sw 2/2/2006 00:43'!\\nsetFlexExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed. Set the extent of the top renderer as indicated.\\\"\\n\\n\\tself addFlexShellIfNecessary.\\n\\tself topRendererOrSelf extent: anExtent! !\\n\\n\\n!Morph methodsFor: 'naming' stamp: 'fc 4/27/2004 21:58'!\\nchoosePartName\\n\\t\\\"Pick an unused name for this morph.\\\"\\n\\t| className |\\n\\tself world ifNil: [^nil].\\n\\t(self world model isKindOf: Component) ifTrue:\\n\\t\\t[self knownName ifNil: [^ self nameMeIn: self world]\\n\\t\\t\\t\\t\\tifNotNil: [^ self renameMe]].\\n\\tclassName _ self class name.\\n\\t(className size > 5 and: [className endsWith: 'Morph'])\\n\\t\\tifTrue: [className _ className copyFrom: 1 to: className size - 5].\\n\\t^ self world model addPartNameLike: className withValue: self! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:28'!\\ndownshiftedNameOfObjectRepresented\\n\\t\\\"Answer the downshiped version of the external name of the object represented\\\"\\n\\n\\t^ self nameOfObjectRepresented asLowercase! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 8/30/2003 15:52'!\\ninnocuousName\\n\\t\\\"Choose an innocuous name for the receiver -- one that does not end in the word Morph\\\"\\n\\n\\t| className allKnownNames |\\n\\tclassName _ self defaultNameStemForInstances.\\n\\t(className size > 5 and: [className endsWith: 'Morph'])\\n\\t\\tifTrue: [className _ className copyFrom: 1 to: className size - 5].\\n\\tclassName _ className asString translated.\\n\\tallKnownNames _ self world ifNil: [OrderedCollection new] ifNotNil: [self world allKnownNames].\\n\\t^ Utilities keyLike: className asString satisfying:\\n\\t\\t[:aName | (allKnownNames includes: aName) not]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 9/21/2000 13:18'!\\nnameForFindWindowFeature\\n\\t\\\"Answer the name to show in a list of windows-and-morphs to represent the receiver\\\"\\n\\n\\t^ self knownName ifNil: [self class name]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 2/22/2003 14:33'!\\nnameInModel\\n\\t\\\"Return the name for this morph in the underlying model or nil.\\\"\\n\\n\\t| w |\\n\\tw := self world.\\n\\tw isNil ifTrue: [^nil] ifFalse: [^w model nameFor: self]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:24'!\\nnameOfObjectRepresented\\n\\t\\\"Answer the external name of the object represented\\\"\\n\\n\\t^ self externalName! !\\n\\n!Morph methodsFor: 'naming' stamp: 'gm 2/22/2003 13:16'!\\nname: aName \\n\\t(aName isString) ifTrue: [self setNameTo: aName]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 2/16/2003 21:57'!\\nsetNamePropertyTo: aName \\n\\t\\\"change the receiver's externalName\\\"\\n\\tself assureExtension externalName: aName! !\\n\\n!Morph methodsFor: 'naming' stamp: 'yo 12/3/2004 17:02'!\\nsetNameTo: aName \\n\\t| nameToUse nameString |\\n\\tnameToUse := aName ifNotNil: \\n\\t\\t\\t\\t\\t[(nameString := aName asString) notEmpty ifTrue: [nameString] ifFalse: ['*']].\\n\\tself setNamePropertyTo: nameToUse\\t\\\"no Texts here!!\\\"! !\\n\\n!Morph methodsFor: 'naming' stamp: 'gm 2/22/2003 13:16'!\\nspecialNameInModel\\n\\t\\\"Return the name for this morph in the underlying model or nil.\\\"\\n\\n\\t\\\"Not an easy problem. For now, take the first part of the mouseDownSelector symbol in my eventHandler (fillBrushMouseUp:morph: gives 'fillBrush'). 5/26/97 tk\\\"\\n\\n\\t| hh |\\n\\t(self isMorphicModel) \\n\\t\\tifTrue: [^self slotName]\\n\\t\\tifFalse: \\n\\t\\t\\t[self eventHandler ifNotNil: \\n\\t\\t\\t\\t\\t[self eventHandler mouseDownSelector ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[hh := self eventHandler mouseDownSelector indexOfSubCollection: 'Mouse'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1.\\n\\t\\t\\t\\t\\t\\t\\thh > 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^self eventHandler mouseDownSelector copyFrom: 1 to: hh - 1]].\\n\\t\\t\\t\\t\\tself eventHandler mouseUpSelector ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[hh := self eventHandler mouseUpSelector indexOfSubCollection: 'Mouse'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1.\\n\\t\\t\\t\\t\\t\\t\\thh > 0 ifTrue: [^self eventHandler mouseUpSelector copyFrom: 1 to: hh - 1]]]].\\n\\n\\t\\\"\\t(self eventHandler mouseDownRecipient respondsTo: #nameFor:) ifTrue: [\\n\\t\\t\\t\\t\\t^ self eventHandler mouseDownRecipient nameFor: self]]].\\t\\\"\\n\\t\\\"myModel _ self findA: MorphicModel.\\n\\t\\t\\tmyModel ifNotNil: [^ myModel slotName]\\\"\\n\\t^self world specialNameInModelFor: self! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/27/2000 17:47'!\\ntryToRenameTo: aName\\n\\t\\\"A new name has been submited; make sure it's appropriate, and react accordingly. This circumlocution provides the hook by which the simple renaming of a field can result in a change to variable names in a stack, etc. There are some problems to worry about here.\\\"\\n\\n\\t| aStack |\\n\\t(self holdsSeparateDataForEachInstance and: [(aStack _ self stack) notNil])\\n\\t\\tifTrue:\\n\\t\\t\\t[self topRendererOrSelf setNameTo: aName.\\n\\t\\t\\taStack reassessBackgroundShape]\\n\\t\\tifFalse:\\n\\t\\t\\t[self renameTo: aName]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 1/29/2001 02:49'!\\nupdateAllScriptingElements\\n\\t\\\"A sledge-hammer sweep from the world down to make sure that all live scripting elements are up to date. Presently in eclipse, not sent at the moment.\\\"\\n\\n\\t| aPasteUp |\\n\\t(aPasteUp _ self topPasteUp) ifNotNil:\\n\\t\\t[aPasteUp allTileScriptingElements do: [:m | m bringUpToDate]]! !\\n\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'tk 11/26/2004 06:02'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\n\\n\\t(varDict at: #ClassName) == #DropShadowMorph ifTrue: [\\n\\n\\t\\tvarDict at: #ClassName put: #Morph.\\t\\\"so we don't\\n\\nrepeat this\\\"\\n\\n\\t\\t^ self convertNovember2000DropShadow: varDict using:\\n\\nsmartRefStrm\\n\\n\\t\\t\\t\\\"always returns a new object of a different class\\\"\\n\\n\\t].\\n\\n\\tvarDict at: 'costumee' ifPresent: [ :x |\\n\\n\\t\\tself convertAugust1998: varDict using: smartRefStrm].\\n\\n\\t\\t\\\"never returns a different object\\\"\\n\\n\\n\\n\\t\\\"5/18/2000\\\"\\n\\n\\tvarDict at: 'openToDragNDrop' ifPresent: [ :x | self\\n\\nenableDragNDrop: x ].\\n\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n\\n\\n\\n\\n! !\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'dgd 2/22/2003 14:33'!\\nobjectForDataStream: refStrm \\n\\t\\\"I am being written out on an object file\\\"\\n\\n\\t| dp |\\n\\tself sqkPage ifNotNil: \\n\\t\\t\\t[refStrm rootObject == self | (refStrm rootObject == self sqkPage) \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[self url notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[dp := self sqkPage copyForSaving.\\t\\\"be careful touching this object!!\\\"\\n\\t\\t\\t\\t\\t\\t\\trefStrm replace: self with: dp.\\n\\t\\t\\t\\t\\t\\t\\t^dp]]].\\n\\tself prepareToBeSaved.\\t\\\"Amen\\\"\\n\\t^self! !\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'tk 7/11/1998 18:53'!\\nstoreDataOn: aDataStream\\n\\t\\\"Let all Morphs be written out. All owners are weak references. They only go out if the owner is in the tree being written.\\\"\\n\\t| cntInstVars cntIndexedVars ti localInstVars |\\n\\n\\t\\\"block my owner unless he is written out by someone else\\\"\\n\\tcntInstVars _ self class instSize.\\n\\tcntIndexedVars _ self basicSize.\\n\\tlocalInstVars _ Morph instVarNames.\\n\\tti _ 2. \\n\\t((localInstVars at: ti) = 'owner') & (Morph superclass == Object) ifFalse:\\n\\t\\t\\t[self error: 'this method is out of date'].\\n\\taDataStream\\n\\t\\tbeginInstance: self class\\n\\t\\tsize: cntInstVars + cntIndexedVars.\\n\\t1 to: ti-1 do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\taDataStream nextPutWeak: owner.\\t\\\"owner only written if in our tree\\\"\\n\\tti+1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]! !\\n\\n\\n!Morph methodsFor: 'other events' stamp: 'sw 8/1/2001 14:08'!\\nmenuButtonMouseEnter: event\\n\\t\\\"The mouse entered a menu-button area; show the menu cursor temporarily\\\"\\n\\n\\tevent hand showTemporaryCursor: Cursor menu! !\\n\\n!Morph methodsFor: 'other events' stamp: 'sw 8/1/2001 14:09'!\\nmenuButtonMouseLeave: event\\n\\t\\\"The mouse left a menu-button area; restore standard cursor\\\"\\n\\n\\tevent hand showTemporaryCursor: nil! !\\n\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 8/12/2001 02:07'!\\ninitializeToStandAlone\\n\\t\\\"Set up the receiver, created by a #basicNew and now ready to be initialized, as a fully-formed morph suitable for providing a graphic for a parts bin surrogate, and, when such a parts-bin surrogate is clicked on, for attaching to the hand as a viable stand-alone morph. Because of historical precedent, #initialize has been expected to handle this burden, though a great number of morphs actually cannot stand alone. In any case, by default we call the historical #initialize, though unhappily, so that all existing morphs will work no worse than before when using this protocol.\\\"\\n\\n\\tself initialize! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'di 11/13/2000 00:49'!\\ninPartsBin\\n\\n\\tself isPartsDonor ifTrue: [^ true].\\n\\tself allOwnersDo: [:m | m isPartsBin ifTrue: [^ true]].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 8/12/97 14:16'!\\nisPartsBin\\n\\t^ false! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'md 2/27/2006 09:53'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension isPartsDonor! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'md 2/27/2006 09:59'!\\nisPartsDonor: aBoolean \\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\t(extension isNil and: [aBoolean not]) ifTrue: [^ self].\\n\\tself assureExtension isPartsDonor: aBoolean! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'di 8/11/1998 13:02'!\\nmarkAsPartsDonor\\n\\t\\\"Mark the receiver specially so that mouse actions on it are interpreted as 'tearing off a copy'\\\"\\n\\n\\tself isPartsDonor: true! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'ar 10/6/2000 22:45'!\\npartRepresented\\n\\t^self! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 4/22/1998 14:45'!\\nresidesInPartsBin\\n\\t\\\"Answer true if the receiver is, or has some ancestor owner who is, a parts bin\\\"\\n\\t^ owner ifNotNil: [owner residesInPartsBin] ifNil: [false]! !\\n\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nchoosePenColor: evt\\n\\tself assuredPlayer choosePenColor: evt! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nchoosePenSize\\n\\tself assuredPlayer choosePenSize! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenColor\\n\\t^ self player ifNotNil: [self actorState getPenColor] ifNil: [Color green]! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenDown\\n\\tself player ifNil: [^ false].\\n\\t^ self actorState getPenDown! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenSize\\n\\tself player ifNil: [^ 1].\\n\\t^ self actorState getPenSize! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nliftPen\\n\\tself assuredPlayer liftPen! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nlowerPen\\n\\tself assuredPlayer lowerPen! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\npenColor: aColor\\n\\tself assuredPlayer penColor: aColor! !\\n\\n!Morph methodsFor: 'pen' stamp: 'di 9/3/1998 10:38'!\\npenUpWhile: changeBlock \\n\\t\\\"Suppress any possible pen trail during the execution of changeBlock\\\"\\n\\tself getPenDown\\n\\t\\tifTrue: [\\\"If this is a costume for a player with its pen down, suppress any line.\\\"\\n\\t\\t\\t\\tself liftPen.\\n\\t\\t\\t\\tchangeBlock value.\\n\\t\\t\\t\\tself lowerPen]\\n\\t\\tifFalse: [\\\"But usually, just do it.\\\"\\n\\t\\t\\t\\tchangeBlock value]! !\\n\\n!Morph methodsFor: 'pen' stamp: 'dgd 2/22/2003 14:36'!\\ntrailMorph\\n\\t\\\"You can't draw trails on me, but try my owner.\\\"\\n\\n\\towner isNil ifTrue: [^nil].\\n\\t^owner trailMorph! !\\n\\n\\n!Morph methodsFor: 'printing' stamp: 'bf 7/17/2003 12:53'!\\nclipText\\n\\t\\\"Copy the text in the receiver or in its submorphs to the clipboard\\\"\\n\\t| content |\\n\\t\\\"My own text\\\"\\n\\tcontent _ self userString.\\n\\t\\\"Or in my submorphs\\\"\\n\\tcontent ifNil: [\\n\\t\\t| list |\\n\\t\\tlist _ self allStringsAfter: nil.\\n\\t\\tlist notEmpty ifTrue: [\\n\\t\\t\\tcontent _ String streamContents: [:stream |\\n\\t\\t\\t\\tlist do: [:each | stream nextPutAll: each; cr]]]].\\n\\t\\\"Did we find something?\\\"\\n\\tcontent\\n\\t\\tifNil: [self flash \\\"provide feedback\\\"]\\n\\t\\tifNotNil: [Clipboard clipboardText: content].! !\\n\\n!Morph methodsFor: 'printing' stamp: 'dgd 2/22/2003 14:27'!\\ncolorString: aColor \\n\\taColor isNil ifTrue: [^'nil'].\\n\\tColor colorNames \\n\\t\\tdo: [:colorName | aColor = (Color perform: colorName) ifTrue: [^'Color ' , colorName]].\\n\\t^aColor storeString! !\\n\\n!Morph methodsFor: 'printing'!\\nconstructorString\\n\\n\\t^ String streamContents: [:s | self printConstructorOn: s indent: 0].\\n! !\\n\\n!Morph methodsFor: 'printing'!\\nfullPrintOn: aStream\\n\\n\\taStream nextPutAll: self class name , ' newBounds: (';\\n\\t\\tprint: bounds;\\n\\t\\tnextPutAll: ') color: ' , (self colorString: color)! !\\n\\n!Morph methodsFor: 'printing'!\\ninitString\\n\\n\\t^ String streamContents: [:s | self fullPrintOn: s]! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/26/2001 07:22'!\\nmorphReport\\n\\n\\t^self morphReportFor: #(hResizing vResizing bounds)! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/25/2001 17:47'!\\nmorphReportFor: attributeList\\n\\n\\t| s |\\n\\n\\ts _ WriteStream on: String new.\\n\\tself\\n\\t\\tmorphReportFor: attributeList \\n\\t\\ton: s \\n\\t\\tindent: 0.\\n\\tStringHolder new contents: s contents; openLabel: 'morph report'! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/25/2001 17:48'!\\nmorphReportFor: attributeList on: aStream indent: anInteger\\n\\n\\tanInteger timesRepeat: [aStream tab].\\n\\taStream print: self; space.\\n\\tattributeList do: [ :a | aStream print: (self perform: a); space].\\n\\taStream cr.\\n\\tsubmorphs do: [ :sub |\\n\\t\\tsub morphReportFor: attributeList on: aStream indent: anInteger + 1\\n\\t].! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/1/2001 17:42'!\\npagesHandledAutomatically\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'printing'!\\nprintConstructorOn: aStream indent: level\\n\\n\\t^ self printConstructorOn: aStream indent: level nodeDict: IdentityDictionary new\\n! !\\n\\n!Morph methodsFor: 'printing'!\\nprintConstructorOn: aStream indent: level nodeDict: nodeDict\\n\\t| nodeString |\\n\\t(nodeString _ nodeDict at: self ifAbsent: [nil])\\n\\t\\tifNotNil: [^ aStream nextPutAll: nodeString].\\n\\tsubmorphs isEmpty ifFalse: [aStream nextPutAll: '('].\\n\\taStream nextPutAll: '('.\\n\\tself fullPrintOn: aStream.\\n\\taStream nextPutAll: ')'.\\n\\tsubmorphs isEmpty ifTrue: [^ self].\\n\\tsubmorphs size <= 4\\n\\tifTrue:\\n\\t\\t[aStream crtab: level+1;\\n\\t\\t\\tnextPutAll: 'addAllMorphs: (Array'.\\n\\t\\t1 to: submorphs size do:\\n\\t\\t\\t[:i | aStream crtab: level+1; nextPutAll: 'with: '.\\n\\t\\t\\t(submorphs at: i) printConstructorOn: aStream indent: level+1 nodeDict: nodeDict].\\n\\t\\taStream nextPutAll: '))']\\n\\tifFalse:\\n\\t\\t[aStream crtab: level+1;\\n\\t\\t\\tnextPutAll: 'addAllMorphs: ((Array new: ', submorphs size printString, ')'.\\n\\t\\t1 to: submorphs size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\taStream crtab: level+1; nextPutAll: 'at: ', i printString, ' put: '.\\n\\t\\t\\t(submorphs at: i) printConstructorOn: aStream indent: level+1 nodeDict: nodeDict.\\n\\t\\t\\taStream nextPutAll: ';'].\\n\\t\\taStream crtab: level+1; nextPutAll: 'yourself))']! !\\n\\n!Morph methodsFor: 'printing' stamp: 'dgd 2/22/2003 19:05'!\\nprintOn: aStream \\n\\t| aName |\\n\\tsuper printOn: aStream.\\n\\t(aName := self knownName) notNil \\n\\t\\tifTrue: [aStream nextPutAll: '<' , aName , '>'].\\n\\taStream nextPutAll: '('.\\n\\taStream\\n\\t\\tprint: self identityHash;\\n\\t\\tnextPutAll: ')'! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 9/18/2000 10:22'!\\nprintSpecs\\n\\n\\t| printSpecs |\\n\\n\\tprintSpecs _ self valueOfProperty: #PrintSpecifications.\\n\\tprintSpecs ifNil: [\\n\\t\\tprintSpecs _ PrintSpecifications defaultSpecs.\\n\\t\\tself printSpecs: printSpecs.\\n\\t].\\n\\t^printSpecs! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 9/18/2000 10:21'!\\nprintSpecs: aPrintSecification\\n\\n\\tself setProperty: #PrintSpecifications toValue: aPrintSecification.\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'jm 5/28/1998 18:00'!\\nprintStructureOn: aStream indent: tabCount\\n\\n\\ttabCount timesRepeat: [aStream tab].\\n\\tself printOn: aStream.\\n\\taStream cr.\\n\\tself submorphsDo: [:m | m printStructureOn: aStream indent: tabCount + 1].\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'sw 10/27/2000 17:45'!\\nreportableSize\\n\\t\\\"Answer a size worth reporting as the receiver's size in a list view\\\"\\n\\n\\t| total |\\n\\ttotal _ super reportableSize.\\n\\tsubmorphs do:\\n\\t\\t[:m | total _ total + m reportableSize].\\n\\t^ total! !\\n\\n!Morph methodsFor: 'printing' stamp: 'jm 5/28/1998 17:58'!\\nstructureString\\n\\t\\\"Return a string that showing this morph and all its submorphs in an indented list that reflects its structure.\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: (String new: 1000).\\n\\tself printStructureOn: s indent: 0.\\n\\t^ s contents\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'sw 10/27/2000 17:47'!\\ntextToPaste\\n\\t\\\"If the receiver has text to offer pasting, answer it, else answer nil\\\"\\n\\n\\t^ nil! !\\n\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'sw 3/30/2005 03:44'!\\naddFlexShell\\n\\t\\\"Wrap a rotating and scaling shell around this morph.\\\"\\n\\n\\t| oldHalo flexMorph myWorld anIndex |\\n\\n\\tmyWorld _ self world.\\n\\toldHalo _ self halo.\\n\\tanIndex _ self owner submorphIndexOf: self.\\n\\tself owner addMorph: (flexMorph _ self newTransformationMorph asFlexOf: self)\\n\\t\\tasElementNumber: anIndex.\\n\\tself transferStateToRenderer: flexMorph.\\n\\toldHalo ifNotNil: [oldHalo setTarget: flexMorph].\\n\\tmyWorld ifNotNil: [myWorld startSteppingSubmorphsOf: flexMorph].\\n\\n\\t^ flexMorph! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'di 11/28/2001 18:22'!\\naddFlexShellIfNecessary\\n\\t\\\"If this morph requires a flex shell to scale or rotate,\\n\\t\\tthen wrap it in one and return it.\\n\\tPolygons, eg, may override to return themselves.\\\"\\n\\n\\t^ self addFlexShell! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'ar 11/24/1998 14:19'!\\nkeepsTransform\\n\\t\\\"Return true if the receiver will keep it's transform while being grabbed by a hand.\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'ar 2/16/1999 18:59'!\\nnewTransformationMorph\\n\\t^TransformationMorph new! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'mu 3/29/2004 17:33'!\\nremoveFlexShell\\n\\tself isFlexed\\n\\t\\tifTrue: [self owner removeFlexShell]! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'jm 4/25/1998 05:19'!\\nrotationDegrees\\n\\t\\\"Default implementation.\\\"\\n\\n\\t^ 0.0\\n! !\\n\\n\\n!Morph methodsFor: 'rounding' stamp: 'mk 8/7/2005 10:03'!\\ncornerStyle: aSymbol\\n\\t\\\"This method makes it possible to set up desired corner style. aSymbol has to be one of:\\n\\t\\t#square\\n\\t\\t#rounded\\\"\\n\\n\\taSymbol == #square\\n\\t\\tifTrue:[self removeProperty: #cornerStyle]\\n\\t\\tifFalse:[self setProperty: #cornerStyle toValue: aSymbol].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'mk 8/14/2005 13:31'!\\nroundedCorners\\n\\t\\\"Return a list of those corners to round.\\n\\n\\t\\t1-4\\n\\t\\t| |\\n\\t\\t2-3\\n\\n\\tReturned array contains `codes' of those corners, which should be rounded.\\n\\n\\t1 denotes top-left corner\\n\\t2 denotes bottom-left corner\\n\\t3 denotes bottom-right corner\\n\\t4 denotes top-right corner.\\n\\n\\tThus, if this method returned #(2 3) that would mean that bottom (left and right)\\n\\tcorners would be rounded whereas top (left and right) corners wouldn't be rounded.\\n\\n\\tThis method returns #(1 2 3 4) and that means that all the corners should be rounded.\\\"\\n\\n\\t^ #(1 2 3 4)! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'dgd 9/6/2003 18:27'!\\nroundedCornersString\\n\\t\\\"Answer the string to put in a menu that will invite the user to \\n\\tswitch to the opposite corner-rounding mode\\\"\\n\\t^ (self wantsRoundedCorners\\n\\t\\tifTrue: ['<yes>']\\n\\t\\tifFalse: ['<no>'])\\n\\t\\t, 'round corners' translated! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'ar 12/25/2001 19:44'!\\ntoggleCornerRounding\\n\\tself cornerStyle == #rounded\\n\\t\\tifTrue: [self cornerStyle: #square]\\n\\t\\tifFalse: [self cornerStyle: #rounded].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'ar 12/22/2001 22:45'!\\nwantsRoundedCorners\\n\\t\\\"Return true if the receiver wants its corners rounded\\\"\\n\\t^ self cornerStyle == #rounded! !\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: 'scripting' stamp: 'dgd 7/4/2004 12:41'!\\narrowDeltaFor: aGetSelector \\n\\t\\\"Answer a number indicating the default arrow delta to be \\n\\tused in a numeric readout with the given get-selector. This is \\n\\ta hook that subclasses of Morph can reimplement.\\\"\\n\\taGetSelector == #getScaleFactor\\n\\t\\tifTrue: [^ 0.1].\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'ar 1/25/2001 12:50'!\\nasEmptyPermanentScriptor\\n\\t\\\"Answer a new empty permanent scriptor derived from info deftly secreted in the receiver. Good grief\\\"\\n\\n\\t| aScriptor aPlayer |\\n\\taPlayer _ self valueOfProperty: #newPermanentPlayer.\\n\\taPlayer assureUniClass.\\n\\taScriptor _ aPlayer newScriptorAround: nil.\\n\\taScriptor position: (self world primaryHand position - (10 @ 10)).\\n\\taPlayer updateAllViewersAndForceToShow: #scripts.\\n\\t^ aScriptor! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 10/17/2001 09:46'!\\nbringTileScriptingElementsUpToDate\\n\\t\\\"Send #bringUpToDate to every tile-scripting element of the receiver, including possibly the receiver itself\\\"\\n\\n\\t(self allMorphs select: [:s | s isTileScriptingElement]) do:\\n\\t\\t[:el | el bringUpToDate]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'RAA 3/9/2001 11:39'!\\nbringUpToDate\\n\\n\\t(self buttonProperties ifNil: [^self]) bringUpToDate! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 7/19/2005 01:55'!\\ndefaultFloatPrecisionFor: aGetSelector\\n\\t\\\"Answer a number indicating the default float precision to be used in a numeric readout for which the receiver provides the data. Individual morphs can override this. Showing fractional values for readouts of getCursor was in response to an explicit request from ack\\\"\\n\\n\\t(self renderedMorph decimalPlacesForGetter: aGetSelector) ifNotNilDo: [:places | ^ (Utilities floatPrecisionForDecimalPlaces: places)].\\n\\n\\t(#(getCursor getNumericValue getNumberAtCursor getCursorWrapped getScaleFactor getUnitVector getAlpha) includes: aGetSelector)\\n\\t\\tifTrue:\\n\\t\\t\\t[^ 0.01].\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/12/2005 13:26'!\\nfilterViewerCategoryDictionary: dict\\n\\t\\\"dict has keys of categories and values of priority.\\n\\tYou can re-order or remove categories here.\\\"\\n\\n\\tself wantsConnectionVocabulary\\n\\t\\tifFalse: [ dict removeKey: #'connections to me' ifAbsent: [].\\n\\t\\t\\tdict removeKey: #connection ifAbsent: []].\\n\\tself wantsConnectorVocabulary\\n\\t\\tifFalse: [ dict removeKey: #connector ifAbsent: [] ].\\n\\tself wantsEmbeddingsVocabulary\\n\\t\\tifFalse: [dict removeKey: #embeddings ifAbsent: []].\\n\\tPreferences eToyFriendly\\n\\t\\tifTrue:\\n\\t\\t\\t[dict removeKey: #layout ifAbsent: []].\\n\\t(Preferences eToyFriendly or: [self isWorldMorph not]) ifTrue:\\n\\t\\t[dict removeKey: #preferences ifAbsent: []].! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'tk 10/1/97 18:23'!\\nisTileLike\\n\\t\\\"Cannot be dropped into a script\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'RAA 3/9/2001 11:47'!\\nisTileScriptingElement\\n\\n\\t^ self hasButtonProperties and: [self buttonProperties isTileScriptingElement]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:53'!\\njettisonScripts\\n\\tself player ifNotNil: [self player class jettisonScripts]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'LC 9/28/1999 21:57'!\\nmakeAllTilesColored\\n\\tself allMorphsDo: \\n\\t\\t[:m | m restoreTypeColor]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'LC 9/28/1999 21:57'!\\nmakeAllTilesGreen\\n\\tself allMorphsDo: \\n\\t\\t[:m | m useUniformTileColor]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:59'!\\nrestoreTypeColor\\n\\tself player ifNotNil: [self player allScriptEditors do:\\n\\t\\t[:anEditor | anEditor allMorphsDo:\\n\\t\\t\\t[:m | m restoreTypeColor]]]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:46'!\\nscriptEditorFor: aScriptName\\n\\t^ self assuredPlayer scriptEditorFor: aScriptName! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 7/5/2005 00:31'!\\ntearOffTile\\n\\t\\\"Tear off a tile representing the player associated with the receiver. This is obtained from the top renderer\\\"\\n\\n\\t^ self topRendererOrSelf assuredPlayer tearOffTileForSelf! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'nk 8/21/2004 12:17'!\\ntriggerScript: aSymbol\\n\\t\\\"Have my player perform the script of the given name, which is guaranteed to exist.\\\"\\n\\n\\t^self assuredPlayer triggerScript: aSymbol! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:55'!\\nuseUniformTileColor\\n\\tself player ifNotNil:\\n\\t\\t[self player allScriptEditors do:\\n\\t\\t\\t[:anEditor | anEditor allMorphsDo:\\n\\t\\t\\t\\t[:m | m useUniformTileColor]]]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 10/18/2000 10:32'!\\nviewAfreshIn: aPasteUp showingScript: aScriptName at: aPosition\\n\\t\\\"Obtain a smartly updated ScriptEditor for the given script name and zap it into place at aPosition\\\"\\n\\n\\t| anEditor |\\n\\tself player updateAllViewersAndForceToShow: #scripts.\\n\\tanEditor _ self player scriptEditorFor: aScriptName.\\n\\taPasteUp ifNotNil: [aPasteUp addMorph: anEditor].\\n\\tanEditor position: aPosition.\\n\\tanEditor currentWorld startSteppingSubmorphsOf: anEditor! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'nk 8/21/2004 08:39'!\\nwantsConnectionVocabulary\\n\\tsubmorphs ifNil: [ ^true ].\\t\\\"called from EToyVocabulary>>initialize after basicNew\\\"\\n\\n\\t^ (Preferences valueOfFlag: #alwaysShowConnectionVocabulary)\\n\\t\\tor: [ self connections isEmpty not ]! !\\n\\n\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:27'!\\narrangeToStartStepping\\n\\t\\\"Arrange to start getting sent the 'step' message, but don't do that initial #step call that startStepping does\\\"\\n\\n\\tself arrangeToStartSteppingIn: self world! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:26'!\\narrangeToStartSteppingIn: aWorld\\n\\t\\\"Start getting sent the 'step' message in aWorld. Like startSteppingIn:, but without the initial one to get started'\\\"\\n\\taWorld ifNotNil:\\n\\t\\t[aWorld startStepping: self.\\n\\t\\tself changed]! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:28'!\\nisStepping\\n\\t\\\"Return true if the receiver is currently stepping in its world\\\"\\n\\t| aWorld |\\n\\t^ (aWorld _ self world)\\n\\t\\tifNil:\\t\\t[false]\\n\\t\\tifNotNil:\\t[aWorld isStepping: self]! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:43'!\\nisSteppingSelector: aSelector\\n\\t\\\"Return true if the receiver is currently stepping in its world\\\"\\n\\t| aWorld |\\n\\t^ (aWorld _ self world)\\n\\t\\tifNil:\\t\\t[false]\\n\\t\\tifNotNil:\\t[aWorld isStepping: self selector: aSelector]! !\\n\\n!Morph methodsFor: 'stepping and presenter'!\\nstart\\n\\t\\\"Start running my script. For ordinary morphs, this means start stepping.\\\"\\n\\n\\tself startStepping.\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 1/31/2001 13:07'!\\nstartStepping\\n\\t\\\"Start getting sent the 'step' message.\\\"\\n\\tself startStepping: #stepAt: at: Time millisecondClockValue arguments: nil stepTime: nil.! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 7/19/1998 11:51'!\\nstartSteppingIn: aWorld\\n\\t\\\"Start getting sent the 'step' message in aWorld\\\"\\n\\n\\tself step. \\\"one to get started!!\\\"\\n\\taWorld ifNotNil: [aWorld startStepping: self].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:42'!\\nstartSteppingSelector: aSelector\\n\\t\\\"Start getting sent the 'step' message.\\\"\\n\\tself startStepping: aSelector at: Time millisecondClockValue arguments: nil stepTime: nil.! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:36'!\\nstartStepping: aSelector at: scheduledTime arguments: args stepTime: stepTime\\n\\t\\\"Start stepping the receiver\\\"\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [\\n\\t\\tw startStepping: self at: scheduledTime selector: aSelector arguments: args stepTime: stepTime.\\n\\t\\tself changed].! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 2/12/2001 17:04'!\\nstep\\n\\t\\\"Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.\\\"\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 2/12/2001 18:05'!\\nstepAt: millisecondClockValue\\n\\t\\\"Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message.\\n\\tThe millisecondClockValue parameter gives the value of the millisecond clock at the moment of dispatch.\\n\\tDefault is to dispatch to the parameterless step method for the morph, but this protocol makes it possible for some morphs to do differing things depending on the clock value\\\"\\n\\tself player ifNotNilDo:[:p| p stepAt: millisecondClockValue].\\n\\tself step\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter'!\\nstop\\n\\t\\\"Stop running my script. For ordinary morphs, this means stop stepping.\\\"\\n\\n\\tself stopStepping.\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 12/15/2000 00:00'!\\nstopStepping\\n\\t\\\"Stop getting sent the 'step' message.\\\"\\n\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [w stopStepping: self].\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 12/15/2000 00:00'!\\nstopSteppingSelector: aSelector\\n\\t\\\"Stop getting sent the given message.\\\"\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [w stopStepping: self selector: aSelector].\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 10/11/1999 12:59'!\\nstopSteppingSelfAndSubmorphs\\n\\tself allMorphsDo: [:m | m stopStepping]\\n! !\\n\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 3/18/2001 00:11'!\\nactiveHand\\n\\t^ActiveHand! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 01:00'!\\nallOwners\\n\\t\\\"Return the owners of the reciever\\\"\\n\\n\\t^ Array streamContents: [:strm | self allOwnersDo: [:m | strm nextPut: m]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 9/14/2000 16:47'!\\nallOwnersDo: aBlock\\n\\t\\\"Evaluate aBlock with all owners of the receiver\\\"\\n\\towner ifNotNil:[^owner withAllOwnersDo: aBlock].! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:48'!\\nfirstOwnerSuchThat: conditionBlock\\n\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [^ m]].\\n\\t^ nil\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 10/3/2000 15:36'!\\nhasOwner: aMorph\\n\\t\\\"Return true if the receiver has aMorph in its owner chain\\\"\\n\\taMorph ifNil:[^true].\\n\\tself allOwnersDo:[:m| m = aMorph ifTrue:[^true]].\\n\\t^false! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 9/1/2004 17:17'!\\nisInDockingBar\\n\\t\\\"answer if the receiver is in a menu bar\\\"\\n\\t^ (owner notNil) and: [owner isDockingBar]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 9/18/2004 15:56'!\\nisInSystemWindow\\n\\t\\\"answer if the receiver is in a system window\\\"\\n\\t^ owner isMorph and:[owner isSystemWindow or:[owner isInSystemWindow]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 19:05'!\\nisInWorld\\n\\t\\\"Return true if this morph is in a world.\\\"\\n\\n\\t^self world notNil! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 8/29/2000 14:55'!\\nmorphPreceding: aSubmorph\\n\\t\\\"Answer the morph immediately preceding aSubmorph, or nil if none\\\"\\n\\n\\t| anIndex |\\n\\tanIndex _ submorphs indexOf: aSubmorph ifAbsent: [^ nil].\\n\\t^ anIndex > 1\\n\\t\\tifTrue:\\n\\t\\t\\t[submorphs at: (anIndex - 1)]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:13'!\\nnearestOwnerThat: conditionBlock\\n\\t\\\"Return the first enclosing morph for which aBlock evaluates to true, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: conditionBlock\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:49'!\\norOwnerSuchThat: conditionBlock\\n\\n\\t(conditionBlock value: self) ifTrue: [^ self].\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [^ m]].\\n\\t^ nil\\n\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:50'!\\noutermostMorphThat: conditionBlock\\n\\t\\\"Return the outermost containing morph for which aBlock is true, or nil if none\\\"\\n\\n\\t| outermost |\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [outermost _ m]].\\n\\t^ outermost! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 3/18/2001 00:12'!\\noutermostWorldMorph\\n\\n\\t| outer |\\n\\tWorld ifNotNil:[^World].\\n\\tself flag: #arNote. \\\"stuff below is really only for MVC\\\"\\n\\touter _ self outermostMorphThat: [ :x | x isWorldMorph].\\n\\touter ifNotNil: [^outer].\\n\\tself isWorldMorph ifTrue: [^self].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'structure'!\\nowner\\n\\t\\\"Returns the owner of this morph, which may be nil.\\\"\\n\\n\\t^ owner! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:18'!\\nownerThatIsA: aClass\\n\\t\\\"Return the first enclosing morph that is a kind of aClass, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: [:m | m isKindOf: aClass]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:20'!\\nownerThatIsA: firstClass orA: secondClass\\n\\t\\\"Return the first enclosing morph that is a kind of one of the two classes given, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: [:m | (m isKindOf: firstClass) or: [m isKindOf: secondClass]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 7/1/1998 18:02'!\\npasteUpMorph\\n\\t\\\"Answer the closest containing morph that is a PasteUp morph\\\"\\n\\t^ self ownerThatIsA: PasteUpMorph! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 8/28/2004 18:43'!\\npasteUpMorphHandlingTabAmongFields\\n\\t\\\"Answer the nearest PasteUpMorph in my owner chain that has the tabAmongFields property, or nil if none\\\"\\n\\n\\t| aPasteUp |\\n\\taPasteUp _ self owner.\\n\\t[aPasteUp notNil] whileTrue:\\n\\t\\t[aPasteUp tabAmongFields ifTrue:\\n\\t\\t\\t[^ aPasteUp].\\n\\t\\taPasteUp _ aPasteUp owner].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'structure' stamp: 'RAA 6/13/2000 15:01'!\\nprimaryHand\\n\\n | outer |\\n outer _ self outermostWorldMorph ifNil: [^ nil].\\n ^ outer activeHand ifNil: [outer firstHand]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:34'!\\nrenderedMorph\\n\\t\\\"If the receiver is a renderer morph, answer the rendered morph. Otherwise, answer the receiver. A renderer morph with no submorphs answers itself. See the comment in Morph>isRenderer.\\\"\\n\\n\\tself isRenderer ifFalse: [^self].\\n\\tsubmorphs isEmpty ifTrue: [^self].\\n\\t^self firstSubmorph renderedMorph! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:34'!\\nroot\\n\\t\\\"Return the root of the composite morph containing the receiver. The owner of the root is either nil, a WorldMorph, or a HandMorph. If the receiver's owner is nil, the root is the receiver itself. This method always returns a morph.\\\"\\n\\n\\t(owner isNil or: [owner isWorldOrHandMorph]) ifTrue: [^self].\\n\\t^owner root! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 8/4/1999 15:41'!\\nrootAt: location\\n\\t\\\"Just return myself, unless I am a WorldWindow.\\n\\tIf so, then return the appropriate root in that world\\\"\\n\\n\\t^ self! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 8/30/1998 09:47'!\\ntopPasteUp\\n\\t\\\"If the receiver is in a world, return that; otherwise return the outermost pasteup morph\\\"\\n\\t^ self outermostMorphThat: [:m | m isKindOf: PasteUpMorph]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 19:06'!\\ntopRendererOrSelf\\n\\t\\\"Answer the topmost renderer for this morph, or this morph itself if it has no renderer. See the comment in Morph>isRenderer.\\\"\\n\\n\\t| top topsOwner |\\n\\towner ifNil: [^self].\\n\\tself isWorldMorph ifTrue: [^self].\\t\\\"ignore scaling of this world\\\"\\n\\ttop := self.\\n\\ttopsOwner := top owner.\\n\\t[topsOwner notNil and: [topsOwner isRenderer]] whileTrue: \\n\\t\\t\\t[top := topsOwner.\\n\\t\\t\\ttopsOwner := top owner].\\n\\t^top! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:59'!\\nwithAllOwners\\n\\t\\\"Return the receiver and all its owners\\\"\\n\\n\\t^ Array streamContents: [:strm | self withAllOwnersDo: [:m | strm nextPut: m]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 9/14/2000 16:48'!\\nwithAllOwnersDo: aBlock\\n\\t\\\"Evaluate aBlock with the receiver and all of its owners\\\"\\n\\taBlock value: self.\\n\\towner ifNotNil:[^owner withAllOwnersDo: aBlock].! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:36'!\\nworld\\n\\t^owner isNil ifTrue: [nil] ifFalse: [owner world]! !\\n\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/14/2001 12:50'!\\nallKnownNames\\n\\t\\\"Return a list of all known names based on the scope of the receiver. Does not include the name of the receiver itself. Items in parts bins are excluded. Reimplementors (q.v.) can extend the list\\\"\\n\\n\\t^ Array streamContents:\\n\\t\\t[:s | self allSubmorphNamesDo: [:n | s nextPut: n]]\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nallMorphs\\n\\t\\\"Return a collection containing all morphs in this composite morph (including the receiver).\\\"\\n\\n\\t| all |\\n\\tall _ OrderedCollection new: 100.\\n\\tself allMorphsDo: [: m | all add: m].\\n\\t^ all! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:27'!\\nallMorphsDo: aBlock \\n\\t\\\"Evaluate the given block for all morphs in this composite morph (including the receiver).\\\"\\n\\n\\tsubmorphs do: [:m | m allMorphsDo: aBlock].\\n\\taBlock value: self! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 10/31/97 20:05'!\\nallNonSubmorphMorphs\\n\\t\\\"Return a collection containing all morphs in this morph which are not currently in the submorph containment hierarchy (put in primarily for bookmorphs)\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/14/2001 12:44'!\\nallSubmorphNamesDo: nameBlock\\n\\t\\\"Return a list of all known names of submorphs and nested submorphs of the receiver, based on the scope of the receiver. Items in parts bins are excluded\\\"\\n\\n\\tself isPartsBin ifTrue: [^ self]. \\\"Don't report names from parts bins\\\"\\n\\tself submorphsDo: \\n\\t\\t[:m | m knownName ifNotNilDo: [:n | nameBlock value: n].\\n\\t\\tm allSubmorphNamesDo: nameBlock].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 8/31/2004 16:53'!\\ndockingBars\\n\\t\\\"Answer the receiver's dockingBars\\\"\\n\\t^ self submorphs\\n\\t\\tselect: [:each | each isDockingBar]\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'rhi 9/10/2000 12:12'!\\nfindA: aClass\\n\\t\\\"Return the first submorph of the receiver that is descended from the given class. Return nil if there is no such submorph. Clients of this code should always check for a nil return value so that the code will be robust if the user takes the morph apart.\\\"\\n\\n\\t^self submorphs\\n\\t\\tdetect: [:p | p isKindOf: aClass]\\n\\t\\tifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 1/9/2001 12:30'!\\nfindDeeplyA: aClass\\n\\t\\\"Return a morph in the submorph tree of the receiver that is descended from the given class. Return nil if there is no such morph. Clients of this code should always check for a nil return value so that the code will be robust if the user takes the morph apart.\\\"\\n\\n\\t^ (self allMorphs copyWithout: self)\\n\\t\\tdetect: [:p | p isKindOf: aClass]\\n\\t\\tifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'LC 9/28/1999 19:12'!\\nfindDeepSubmorphThat: block1 ifAbsent: block2 \\n\\tself\\n\\t\\tallMorphsDo: [:m | (block1 value: m)\\n\\t\\t\\t\\t== true ifTrue: [^ m]].\\n\\t^ block2 value! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 3/17/2001 15:32'!\\nfindSubmorphBinary: aBlock\\n\\t\\\"Use binary search for finding a specific submorph of the receiver. Caller must be certain that the ordering holds for the submorphs.\\\"\\n\\t^submorphs findBinary: aBlock ifNone:[nil].! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:31'!\\nfirstSubmorph\\n\\t^submorphs first! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nhasSubmorphs\\n\\t^submorphs notEmpty! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 7/3/1998 17:11'!\\nhasSubmorphWithProperty: aSymbol\\n\\tsubmorphs detect: [:m | m hasProperty: aSymbol] ifNone: [^ false].\\n\\t^ true! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/31/2000 11:04'!\\nindexOfMorphAbove: aPoint\\n\\t\\\"Return index of lowest morph whose bottom is above aPoint.\\n\\tWill return 0 if the first morph is not above aPoint.\\\"\\n\\n\\tsubmorphs withIndexDo: [:mm :ii | \\n\\t\\tmm fullBounds bottom >= aPoint y ifTrue: [^ ii - 1]].\\n\\t^ submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nlastSubmorph\\n\\t^submorphs last! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 9/6/2004 14:17'!\\nmainDockingBars\\n\\t\\\"Answer the receiver's main dockingBars\\\"\\n\\t^ self dockingBars\\n\\t\\tselect: [:each | each hasProperty: #mainDockingBarTimeStamp]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:40'!\\nmorphsAt: aPoint\\n\\t\\\"Return a collection of all morphs in this morph structure that contain the given point, possibly including the receiver itself. The order is deepest embedding first.\\\"\\n\\t^self morphsAt: aPoint unlocked: false! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nmorphsAt: aPoint behind: aMorph unlocked: aBool \\n\\t\\\"Return all morphs at aPoint that are behind frontMorph; if aBool is true return only unlocked, visible morphs.\\\"\\n\\n\\t| isBack found all tfm |\\n\\tall := (aMorph isNil or: [owner isNil]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Traverse down\\\"\\n\\n\\t\\t\\t\\t\\t(self fullBounds containsPoint: aPoint) ifFalse: [^#()].\\n\\t\\t\\t\\t\\t(aBool and: [self isLocked or: [self visible not]]) ifTrue: [^#()].\\n\\t\\t\\t\\t\\tnil]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[\\\"Traverse up\\\"\\n\\n\\t\\t\\t\\t\\ttfm := self transformedFrom: owner.\\n\\t\\t\\t\\t\\tall := owner \\n\\t\\t\\t\\t\\t\\t\\t\\tmorphsAt: (tfm localPointToGlobal: aPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tbehind: self\\n\\t\\t\\t\\t\\t\\t\\t\\tunlocked: aBool.\\n\\t\\t\\t\\t\\tWriteStream with: all].\\n\\tisBack := aMorph isNil.\\n\\tself submorphsDo: \\n\\t\\t\\t[:m | \\n\\t\\t\\tisBack \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[tfm := m transformedFrom: self.\\n\\t\\t\\t\\t\\tfound := m \\n\\t\\t\\t\\t\\t\\t\\t\\tmorphsAt: (tfm globalPointToLocal: aPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tbehind: nil\\n\\t\\t\\t\\t\\t\\t\\t\\tunlocked: aBool.\\n\\t\\t\\t\\t\\tfound notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[all ifNil: [all := WriteStream on: #()].\\n\\t\\t\\t\\t\\t\\t\\tall nextPutAll: found]].\\n\\t\\t\\tm == aMorph ifTrue: [isBack := true]].\\n\\t(isBack and: [self containsPoint: aPoint]) \\n\\t\\tifTrue: \\n\\t\\t\\t[all ifNil: [^Array with: self].\\n\\t\\t\\tall nextPut: self].\\n\\t^all ifNil: [#()] ifNotNil: [all contents]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:40'!\\nmorphsAt: aPoint unlocked: aBool\\n\\t\\\"Return a collection of all morphs in this morph structure that contain the given point, possibly including the receiver itself. The order is deepest embedding first.\\\"\\n\\t| mList |\\n\\tmList _ WriteStream on: #().\\n\\tself morphsAt: aPoint unlocked: aBool do:[:m| mList nextPut: m].\\n\\t^mList contents! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:37'!\\nmorphsAt: aPoint unlocked: aBool do: aBlock\\n\\t\\\"Evaluate aBlock with all the morphs starting at the receiver which appear at aPoint. If aBool is true take only visible, unlocked morphs into account.\\\"\\n\\t| tfm |\\n\\t(self fullBounds containsPoint: aPoint) ifFalse:[^self].\\n\\t(aBool and:[self isLocked or:[self visible not]]) ifTrue:[^self].\\n\\tself submorphsDo:[:m|\\n\\t\\ttfm _ m transformedFrom: self.\\n\\t\\tm morphsAt: (tfm globalPointToLocal: aPoint) unlocked: aBool do: aBlock].\\n\\t(self containsPoint: aPoint) ifTrue:[aBlock value: self].! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOf: someMorph overlapping: aRectangle do: aBlock\\n\\t\\\"Evaluate aBlock with all top-level morphs in front of someMorph that overlap with the given rectangle. someMorph is either an immediate child of the receiver or nil (in which case all submorphs of the receiver are enumerated).\\\"\\n\\tself submorphsDo:[:m|\\n\\t\\tm == someMorph ifTrue:[\\\"Try getting out quickly\\\"\\n\\t\\t\\towner ifNil:[^self].\\n\\t\\t\\t^owner morphsInFrontOf: self overlapping: aRectangle do: aBlock].\\n\\t\\t(m fullBoundsInWorld intersects: aRectangle)\\n\\t\\t\\tifTrue:[aBlock value: m]].\\n\\towner ifNil:[^self].\\n\\t^owner morphsInFrontOf: self overlapping: aRectangle do: aBlock.! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOverlapping: aRectangle\\n\\t\\\"Return all top-level morphs in front of someMorph that overlap with the given rectangle.\\\"\\n\\t| morphList |\\n\\tmorphList _ WriteStream on: Array new.\\n\\tself morphsInFrontOf: nil overlapping: aRectangle do:[:m | morphList nextPut: m].\\n\\t^morphList contents! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOverlapping: aRectangle do: aBlock\\n\\t\\\"Evaluate aBlock with all top-level morphs in front of someMorph that overlap with the given rectangle.\\\"\\n\\t^self morphsInFrontOf: nil overlapping: aRectangle do: aBlock! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 8/13/2003 11:32'!\\nnoteNewOwner: aMorph\\n\\t\\\"I have just been added as a submorph of aMorph\\\"! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'RAA 6/11/2000 20:41'!\\nrootMorphsAtGlobal: aPoint\\n\\t\\\"Return the list of root morphs containing the given point, excluding the receiver.\\n\\tar 11/8/1999: Moved into morph for an incredibly ugly hack in 3D worlds\\\"\\n\\n\\t^ self rootMorphsAt: (self pointFromWorld: aPoint)! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:44'!\\nrootMorphsAt: aPoint\\n\\t\\\"Return the list of root morphs containing the given point, excluding the receiver.\\n\\tar 11/8/1999: Moved into morph for an incredibly ugly hack in 3D worlds\\\"\\nself flag: #arNote. \\\"check this at some point\\\"\\n\\t^ self submorphs select:\\n\\t\\t[:m | (m fullContainsPoint: aPoint) and: [m isLocked not]]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:35'!\\nshuffleSubmorphs\\n\\t\\\"Randomly shuffle the order of my submorphs. Don't call this method lightly!!\\\"\\n\\n\\t| bg |\\n\\tself invalidRect: self fullBounds.\\n\\t(submorphs notEmpty and: [submorphs last mustBeBackmost]) \\n\\t\\tifTrue: \\n\\t\\t\\t[bg := submorphs last.\\n\\t\\t\\tbg privateDelete].\\n\\tsubmorphs := submorphs shuffled.\\n\\tbg ifNotNil: [self addMorphBack: bg].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/20/2000 13:12'!\\nsubmorphAfter\\n\\t\\\"Return the submorph after (behind) me, or nil\\\"\\n\\t| ii |\\n\\towner ifNil: [^ nil].\\n\\t^ (ii _ owner submorphIndexOf: self) = owner submorphs size \\n\\t\\tifTrue: [nil]\\n\\t\\tifFalse: [owner submorphs at: ii+1].\\n\\t\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/20/2000 13:13'!\\nsubmorphBefore\\n\\t\\\"Return the submorph after (behind) me, or nil\\\"\\n\\t| ii |\\n\\towner ifNil: [^ nil].\\n\\t^ (ii _ owner submorphIndexOf: self) = 1 \\n\\t\\tifTrue: [nil]\\n\\t\\tifFalse: [owner submorphs at: ii-1].\\n\\t\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nsubmorphCount\\n\\n\\t^ submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 4/9/98 14:26'!\\nsubmorphNamed: aName\\n\\t^ self submorphNamed: aName ifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'gm 2/22/2003 13:16'!\\nsubmorphNamed: aName ifNone: aBlock \\n\\t\\\"Find the first submorph with this name, or a button with an action selector of that name\\\"\\n\\n\\t| sub args |\\n\\tself submorphs do: [:p | p knownName = aName ifTrue: [^p]].\\n\\tself submorphs do: \\n\\t\\t\\t[:button | \\n\\t\\t\\t(button respondsTo: #actionSelector) \\n\\t\\t\\t\\tifTrue: [button actionSelector == aName ifTrue: [^button]].\\n\\t\\t\\t((button respondsTo: #arguments) and: [(args := button arguments) notNil]) \\n\\t\\t\\t\\tifTrue: [(args at: 2 ifAbsent: [nil]) == aName ifTrue: [^button]].\\n\\t\\t\\t(button isAlignmentMorph) \\n\\t\\t\\t\\tifTrue: [(sub := button submorphNamed: aName ifNone: [nil]) ifNotNil: [^sub]]].\\n\\t^aBlock value! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'rhi 9/10/2000 12:12'!\\nsubmorphOfClass: aClass\\n\\n\\t^self findA: aClass! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'efc 8/6/2005 11:35'!\\nsubmorphs\\n\\t\\\"This method returns my actual submorphs collection. Modifying the collection directly could be dangerous; make a copy if you need to alter it.\\\"\\n\\t^ submorphs ! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/4/97 14:30'!\\nsubmorphsBehind: aMorph do: aBlock\\n\\t| behind |\\n\\tbehind _ false.\\n\\tsubmorphs do:\\n\\t\\t[:m | m == aMorph ifTrue: [behind _ true]\\n\\t\\t\\t\\t\\t\\tifFalse: [behind ifTrue: [aBlock value: m]]].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:35'!\\nsubmorphsDo: aBlock \\n\\tsubmorphs do: aBlock! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/4/97 14:29'!\\nsubmorphsInFrontOf: aMorph do: aBlock\\n\\t| behind |\\n\\tbehind _ false.\\n\\tsubmorphs do:\\n\\t\\t[:m | m == aMorph ifTrue: [behind _ true]\\n\\t\\t\\t\\t\\t\\tifFalse: [behind ifFalse: [aBlock value: m]]].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nsubmorphsReverseDo: aBlock\\n\\n\\tsubmorphs reverseDo: aBlock.! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 8/15/97 22:03'!\\nsubmorphsSatisfying: aBlock\\n\\t^ submorphs select: [:m | (aBlock value: m) == true]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 10/26/1999 23:42'!\\nsubmorphThat: block1 ifNone: block2\\n\\t^ submorphs detect: [:m | (block1 value: m) == true] ifNone: [block2 value]\\n\\t! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 7/3/1998 18:47'!\\nsubmorphWithProperty: aSymbol\\n\\t^ submorphs detect: [:aMorph | aMorph hasProperty: aSymbol] ifNone: [nil]! !\\n\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'tk 12/15/1998 14:23'!\\nabandon\\n\\t\\\"Like delete, but we really intend not to use this morph again. Clean up a few things.\\\"\\n\\n\\tself delete! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/28/2001 08:39'!\\nactWhen\\n\\t\\\"Answer when the receiver, probably being used as a button, should have its action triggered\\\"\\n\\n\\t^ self valueOfProperty: #actWhen ifAbsentPut: [#buttonDown]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/25/2001 10:23'!\\nactWhen: aButtonPhase\\n\\t\\\"Set the receiver's actWhen trait\\\"\\n\\n\\tself setProperty: #actWhen toValue: aButtonPhase! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 23:28'!\\naddAllMorphs: aCollection\\n\\t^self privateAddAllMorphs: aCollection atIndex: submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 23:29'!\\naddAllMorphs: aCollection after: anotherMorph\\n\\t^self privateAddAllMorphs: aCollection \\n\\t\\t\\tatIndex: (submorphs indexOf: anotherMorph ifAbsent: [submorphs size])! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:55'!\\naddMorphBack: aMorph\\n\\t^self privateAddMorph: aMorph atIndex: submorphs size+1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'RAA 12/15/2000 19:34'!\\naddMorphCentered: aMorph\\n\\n\\taMorph position: bounds center - (aMorph extent // 2).\\n\\tself addMorphFront: aMorph.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 12/16/2001 21:08'!\\naddMorphFrontFromWorldPosition: aMorph\\n\\t^self addMorphFront: aMorph fromWorldPosition: aMorph positionInWorld.! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:54'!\\naddMorphFront: aMorph\\n\\t^self privateAddMorph: aMorph atIndex: 1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 11/15/1998 23:42'!\\naddMorphFront: aMorph fromWorldPosition: wp\\n\\n\\tself addMorphFront: aMorph.\\n\\taMorph position: (self transformFromWorld globalPointToLocal: wp)! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 2/22/2003 14:26'!\\naddMorphNearBack: aMorph \\n\\t| bg |\\n\\t(submorphs notEmpty and: [submorphs last mustBeBackmost]) \\n\\t\\tifTrue: \\n\\t\\t\\t[bg := submorphs last.\\n\\t\\t\\tbg privateDelete].\\n\\tself addMorphBack: aMorph.\\n\\tbg ifNotNil: [self addMorphBack: bg]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove'!\\naddMorph: aMorph\\n\\n\\tself addMorphFront: aMorph.! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:54'!\\naddMorph: newMorph after: aMorph\\n\\t\\\"Add the given morph as one of my submorphs, inserting it after anotherMorph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: (submorphs indexOf: aMorph)+1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/7/2000 08:29'!\\naddMorph: aMorph asElementNumber: aNumber\\n\\t\\\"Add the given morph so that it becomes the aNumber'th element of my submorph list. If aMorph is already one of my submorphs, reposition it\\\"\\n\\n\\t(submorphs includes: aMorph) ifTrue:\\n\\t\\t[aMorph privateDelete].\\n\\t(aNumber <= submorphs size)\\n\\t\\tifTrue:\\n\\t\\t\\t[self addMorph: aMorph inFrontOf: (submorphs at: aNumber)]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorphBack: aMorph]\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:44'!\\naddMorph: newMorph behind: aMorph\\n\\t\\\"Add a morph to the list of submorphs behind the specified morph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: (submorphs indexOf: aMorph) + 1.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'JW 2/1/2001 12:52'!\\naddMorph: aMorph fullFrame: aLayoutFrame\\n\\n\\taMorph layoutFrame: aLayoutFrame.\\n\\taMorph hResizing: #spaceFill; vResizing: #spaceFill.\\n\\tself addMorph: aMorph.\\n\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:45'!\\naddMorph: newMorph inFrontOf: aMorph\\n\\t\\\"Add a morph to the list of submorphs in front of the specified morph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: ((submorphs indexOf: aMorph) max: 1).! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 4/4/2006 17:17'!\\nallMorphsWithPlayersDo: aTwoArgumentBlock \\n\\t\\\"Evaluate the given block for all morphs in this composite morph that have non-nil players.\\n\\tAlso evaluate the block for the receiver if it has a player.\\\"\\n\\n\\tsubmorphs do: [:m | m allMorphsWithPlayersDo: aTwoArgumentBlock ].\\n\\tself playerRepresented ifNotNilDo: [ :p | aTwoArgumentBlock value: self value: p ].\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 2/22/2003 14:30'!\\ncomeToFront\\n\\t| outerMorph |\\n\\touterMorph := self topRendererOrSelf.\\n\\t(outerMorph owner isNil or: [outerMorph owner hasSubmorphs not]) \\n\\t\\tifTrue: [^self].\\n\\touterMorph owner firstSubmorph == outerMorph \\n\\t\\tifFalse: [outerMorph owner addMorphFront: outerMorph]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'di 10/27/97 23:26'!\\ncopyWithoutSubmorph: sub\\n\\t\\\"Needed to get a morph to draw without one of its submorphs.\\n\\tNOTE: This must be thrown away immediately after use.\\\"\\n\\t^ self clone privateSubmorphs: (submorphs copyWithout: sub)! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 9/10/2004 19:02'!\\ndelete\\n\\t\\\"Remove the receiver as a submorph of its owner and make its \\n\\tnew owner be nil.\\\"\\n\\n\\t| aWorld |\\n\\tself removeHalo.\\n\\taWorld := self world ifNil: [World].\\n\\t\\\"Terminate genie recognition focus\\\"\\n\\t\\\"I encountered a case where the hand was nil, so I put in a little \\n\\tprotection - raa \\\"\\n\\t\\\" This happens when we are in an MVC project and open\\n\\t a morphic window. - BG \\\"\\n\\taWorld ifNotNil:\\n\\t [self disableSubmorphFocusForHand: self activeHand.\\n\\t self activeHand releaseKeyboardFocus: self;\\n\\t\\t releaseMouseFocus: self.].\\n\\towner ifNotNil:[ self privateDelete.\\n\\t\\tself player ifNotNilDo: [ :player |\\n\\t\\t\\t\\\"Player must be notified\\\"\\n\\t\\t\\tplayer noteDeletionOf: self fromWorld: aWorld]].! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 9/1/2004 16:26'!\\ndeleteDockingBars\\n\\t\\\"Delete the receiver's docking bars\\\"\\n\\tself dockingBars\\n\\t\\tdo: [:each | each delete]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 7/3/1998 11:02'!\\ndeleteSubmorphsWithProperty: aSymbol\\n\\tsubmorphs copy do:\\n\\t\\t[:m | (m hasProperty: aSymbol) ifTrue: [m delete]]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 2/2/2006 02:39'!\\ndismissViaHalo\\n\\t\\\"The user has clicked in the delete halo-handle. This provides a hook in case some concomitant action should be taken, or if the particular morph is not one which should be put in the trash can, for example.\\\"\\n\\n\\t| cmd |\\n\\tself setProperty: #lastPosition toValue: self positionInWorld.\\n\\tself dismissMorph.\\n\\tPreferences preserveTrash ifTrue: [ \\n\\t\\tPreferences slideDismissalsToTrash\\n\\t\\t\\tifTrue:[self slideToTrash: nil]\\n\\t\\t\\tifFalse:[TrashCanMorph moveToTrash: self].\\n\\t].\\n\\n\\tcmd _ Command new cmdWording: 'dismiss ' translated, self externalName.\\n\\tcmd undoTarget: ActiveWorld selector: #reintroduceIntoWorld: argument: self.\\n\\tcmd redoTarget: ActiveWorld selector: #onceAgainDismiss: argument: self.\\n\\tActiveWorld rememberCommand: cmd! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 4/9/98 22:44'!\\ngoBehind\\n\\n\\towner addMorphNearBack: self.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/10/2003 18:31'!\\nprivateDelete\\n\\t\\\"Remove the receiver as a submorph of its owner\\\"\\n\\towner ifNotNil:[owner removeMorph: self].! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'nk 10/16/2003 14:08'!\\nremoveAllMorphs\\n\\t| oldMorphs myWorld |\\n\\tmyWorld _ self world.\\n\\t(fullBounds notNil or:[myWorld notNil]) ifTrue:[self invalidRect: self fullBounds].\\n\\tsubmorphs do: [:m | myWorld ifNotNil: [ m outOfWorld: myWorld ]. m privateOwner: nil].\\n\\toldMorphs _ submorphs.\\n\\tsubmorphs _ EmptyArray.\\n\\toldMorphs do: [ :m | self removedMorph: m ].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'nk 10/16/2003 14:02'!\\nremoveAllMorphsIn: aCollection\\n\\t\\\"greatly speeds up the removal of *lots* of submorphs\\\"\\n\\t| set myWorld |\\n\\tset _ IdentitySet new: aCollection size * 4 // 3.\\n\\taCollection do: [:each | each owner == self ifTrue: [ set add: each]].\\n\\tmyWorld _ self world.\\n\\t(fullBounds notNil or:[myWorld notNil]) ifTrue:[self invalidRect: self fullBounds].\\n\\tset do: [:m | myWorld ifNotNil: [ m outOfWorld: myWorld ]. m privateOwner: nil].\\n\\tsubmorphs _ submorphs reject: [ :each | set includes: each].\\n\\tset do: [ :m | self removedMorph: m ].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 22:01'!\\nremovedMorph: aMorph\\n\\t\\\"Notify the receiver that aMorph was just removed from its children\\\"\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'di 10/18/2004 21:50'!\\nremoveMorph: aMorph\\n\\t\\\"Remove the given morph from my submorphs\\\"\\n\\t| aWorld |\\n\\taMorph owner == self ifFalse:[^self].\\n\\taWorld := self world.\\n\\taWorld ifNotNil:[\\n\\t\\taMorph outOfWorld: aWorld.\\n\\t\\tself privateInvalidateMorph: aMorph.\\n\\t].\\n\\tself privateRemove: aMorph.\\n\\taMorph privateOwner: nil.\\n\\tself removedMorph: aMorph.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 10/25/1999 23:34'!\\nreplaceSubmorph: oldMorph by: newMorph\\n\\t| index itsPosition w |\\n\\toldMorph stopStepping.\\n\\titsPosition _ oldMorph referencePositionInWorld.\\n\\tindex _ submorphs indexOf: oldMorph.\\n\\toldMorph privateDelete.\\n\\tself privateAddMorph: newMorph atIndex: index.\\n\\tnewMorph referencePositionInWorld: itsPosition.\\n\\t(w _ newMorph world) ifNotNil:\\n\\t\\t[w startSteppingSubmorphsOf: newMorph]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/1/2000 10:16'!\\nsubmorphIndexOf: aMorph\\n\\t\\\"Assuming aMorph to be one of my submorphs, answer where it occurs in my submorph list\\\"\\n\\n\\t^ submorphs indexOf: aMorph ifAbsent: [nil]! !\\n\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 12/4/2000 10:44'!\\ncanDrawAtHigherResolution\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 8/25/2001 19:14'!\\ncanDrawBorder: aBorderStyle\\n\\t\\\"Return true if the receiver can be drawn with the given border style.\\\"\\n\\t^true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 10/20/2000 14:47'!\\ncompleteModificationHash\\n\\n\\\"World completeModificationHash\\\"\\n\\n\\t| resultSize result here i |\\n\\tresultSize _ 10.\\n\\tresult _ ByteArray new: resultSize.\\n\\tself allMorphsDo: [ :each | \\n\\t\\there _ each modificationHash.\\n\\t\\there withIndexDo: [ :ch :index |\\n\\t\\t\\ti _ index \\\\\\\\ resultSize + 1.\\n\\t\\t\\tresult at: i put: ((result at: i) bitXor: ch asciiValue)\\n\\t\\t].\\n\\t].\\n\\t^result! !\\n\\n!Morph methodsFor: 'testing' stamp: 'sw 3/30/2005 04:17'!\\ncouldMakeSibling\\n\\t\\\"Answer whether it is appropriate to ask the receiver to make a sibling\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dgd 8/31/2004 15:00'!\\nisDockingBar\\n\\t\\\"Return true if the receiver is a docking bar\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 9/22/2000 13:44'!\\nisFlexed\\n\\t\\\"Return true if the receiver is currently flexed\\\"\\n\\towner ifNil:[^false].\\n\\t^owner isFlexMorph! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dgd 9/20/2004 14:31'!\\nisFullOnScreen\\n\\t\\\"Answer if the receiver is full contained in the owner visible \\n\\tarea.\\\"\\n\\towner isInMemory\\n\\t\\tifFalse: [^ true].\\n\\towner isNil\\n\\t\\tifTrue: [^ true].\\n\\tself visible\\n\\t\\tifFalse: [^ true].\\n\\t^ owner clearArea containsRect: self fullBounds! !\\n\\n!Morph methodsFor: 'testing' stamp: 'nk 10/13/2003 18:36'!\\nisLineMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'testing'!\\nisMorph\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'nk 6/12/2004 09:17'!\\nisSketchMorph\\n\\t^self class isSketchMorphClass! !\\n\\n!Morph methodsFor: 'testing' stamp: 'md 2/27/2006 09:59'!\\nknownName\\n\\t\\\"answer a name by which the receiver is known, or nil if none\\\"\\n\\t^ extension ifNotNil: [extension externalName]! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 10/20/2000 14:47'!\\nmodificationHash\\n\\n\\t^String \\n\\t\\tstreamContents: [ :strm |\\n\\t\\t\\tself longPrintOn: strm\\n\\t\\t]\\n\\t\\tlimitedTo: 25\\n! !\\n\\n!Morph methodsFor: 'testing' stamp: 'tk 7/28/2005 04:46'!\\nrenameInternal: aName \\n\\t\\\"Change the internal name (because of a conflict) but leave the external name unchanged. Change Player class name, but do not change the names that appear in tiles. When coming in from disk, and have name conflict, References will already have the new name. \\\"\\n\\n\\tself knownName = aName ifTrue: [^ aName].\\n\\tself topRendererOrSelf setNameTo: aName.\\n\\t\\n\\t\\\"References dictionary already has key aName\\\"\\n\\n\\t\\\"If this player has a viewer flap, it will remain present\\\"\\n\\n\\t\\\"Tiles in scripts all stay the same\\\"\\n\\n\\t\\\"Compiled methods for scripts have been fixed up because the same association was reused\\\"\\n\\t\\n\\t^ aName! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dvf 8/23/2003 11:50'!\\nrenameTo: aName \\n\\t\\\"Set Player name in costume. Update Viewers. Fix all tiles (old style). fix \\n\\tReferences. New tiles: recompile, and recreate open scripts. If coming in \\n\\tfrom disk, and have name conflict, References will already have new \\n\\tname. \\\"\\n\\n\\t| aPresenter putInViewer aPasteUp renderer oldKey assoc classes oldName |\\n\\toldName := self knownName.\\n\\t(renderer := self topRendererOrSelf) setNameTo: aName.\\n\\tputInViewer := false.\\n\\t((aPresenter := self presenter) isNil or: [renderer player isNil]) \\n\\t\\tifFalse: \\n\\t\\t\\t[putInViewer := aPresenter currentlyViewing: renderer player.\\n\\t\\t\\tputInViewer ifTrue: [renderer player viewerFlapTab hibernate]].\\n\\t\\\"empty it temporarily\\\"\\n\\t(aPasteUp := self topPasteUp) \\n\\t\\tifNotNil: [aPasteUp allTileScriptingElements do: [:m | m bringUpToDate]].\\n\\t\\\"Fix References dictionary. See restoreReferences to know why oldKey is \\n\\talready aName, but oldName is the old name.\\\"\\n\\toldKey := References keyAtIdentityValue: renderer player ifAbsent: [].\\n\\toldKey ifNotNil: \\n\\t\\t\\t[assoc := References associationAt: oldKey.\\n\\t\\t\\toldKey = aName \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[\\\"normal rename\\\"\\n\\n\\t\\t\\t\\t\\tassoc key: (renderer player uniqueNameForReferenceFrom: aName).\\n\\t\\t\\t\\t\\tReferences rehash]].\\n\\tputInViewer ifTrue: [aPresenter viewMorph: self].\\n\\t\\\"recreate my viewer\\\"\\n\\toldKey ifNil: [^aName].\\n\\t\\\"Force strings in tiles to be remade with new name. New tiles only.\\\"\\n\\tPreferences universalTiles ifFalse: [^aName].\\n\\tclasses := (self systemNavigation allCallsOn: assoc) \\n\\t\\t\\t\\tcollect: [:each | each classSymbol].\\n\\tclasses asSet \\n\\t\\tdo: [:clsName | (Smalltalk at: clsName) replaceSilently: oldName to: aName].\\n\\t\\\"replace in text body of all methods. Can be wrong!!\\\"\\n\\t\\\"Redo the tiles that are showing. This is also done in caller in \\n\\tunhibernate. \\\"\\n\\taPasteUp ifNotNil: \\n\\t\\t\\t[aPasteUp allTileScriptingElements do: \\n\\t\\t\\t\\t\\t[:mm | \\n\\t\\t\\t\\t\\t\\\"just ScriptEditorMorphs\\\"\\n\\n\\t\\t\\t\\t\\tnil.\\n\\t\\t\\t\\t\\t(mm isKindOf: ScriptEditorMorph) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[((mm playerScripted class compiledMethodAt: mm scriptName) \\n\\t\\t\\t\\t\\t\\t\\t\\thasLiteral: assoc) \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[mm\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thibernate;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tunhibernate]]]].\\n\\t^aName! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 12/3/2001 12:33'!\\nshouldDropOnMouseUp\\n\\t| former |\\n\\tformer _ self formerPosition ifNil:[^false].\\n\\t^(former dist: self position) > 10! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 1/16/2001 17:20'!\\nstepTime\\n\\t\\\"Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.\\\"\\n\\n\\t^ self topRendererOrSelf player ifNotNil: [10] ifNil: [1000]! !\\n\\n!Morph methodsFor: 'testing' stamp: 'sw 10/24/2004 15:28'!\\nwantsSteps\\n\\t\\\"Return true if the receiver overrides the default Morph step method.\\\"\\n\\t\\\"Details: Find first class in superclass chain that implements #step and return true if it isn't class Morph.\\\"\\n\\n\\t| c |\\n\\tself isPartsDonor ifTrue: [^ false].\\n\\t(self == self topRendererOrSelf) ifTrue: [self player wantsSteps ifTrue: [^ true]].\\n\\tc _ self class.\\n\\t[c includesSelector: #step] whileFalse: [c _ c superclass].\\n\\t^ c ~= Morph! !\\n\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/17/2001 12:45'!\\naddTextAnchorMenuItems: topMenu hand: aHand\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addUpdating: #hasInlineAnchorString action: #changeInlineAnchor.\\n\\taMenu addUpdating: #hasParagraphAnchorString action: #changeParagraphAnchor.\\n\\taMenu addUpdating: #hasDocumentAnchorString action: #changeDocumentAnchor.\\n\\ttopMenu ifNotNil:[topMenu add: 'text anchor' subMenu: aMenu].\\n\\t^aMenu! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:47'!\\nchangeDocumentAnchor\\n\\t\\\"Change the anchor from/to document anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #document \\n\\t\\tifTrue: [#paragraph]\\n\\t\\tifFalse: [ #document].\\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:48'!\\nchangeInlineAnchor\\n\\t\\\"Change the anchor from/to line anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #inline \\n\\t\\t\\t\\tifTrue: [#paragraph]\\n\\t\\t\\t\\tifFalse: [#inline]. \\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:48'!\\nchangeParagraphAnchor\\n\\t\\\"Change the anchor from/to paragraph anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #paragraph \\n\\t\\tifTrue: [#document]\\n\\t\\tifFalse: [#paragraph].\\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasDocumentAnchorString\\n\\t^ (self textAnchorType == #document\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Document' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasInlineAnchorString\\n\\t^ (self textAnchorType == #inline\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Inline' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasParagraphAnchorString\\n\\t^ (self textAnchorType == #paragraph\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Paragraph' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 19:47'!\\nrelativeTextAnchorPosition\\n\\t^self valueOfProperty: #relativeTextAnchorPosition! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 19:22'!\\nrelativeTextAnchorPosition: aPoint\\n\\t^self setProperty: #relativeTextAnchorPosition toValue: aPoint! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 18:36'!\\ntextAnchorType\\n\\t^self valueOfProperty: #textAnchorType ifAbsent:[#document]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 18:37'!\\ntextAnchorType: aSymbol\\n\\taSymbol == #document\\n\\t\\tifTrue:[^self removeProperty: #textAnchorType]\\n\\t\\tifFalse:[^self setProperty: #textAnchorType toValue: aSymbol].! !\\n\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 10/26/2000 08:32'!\\ndemandsThumbnailing\\n\\t\\\"Answer whether the receiver, if in a thumbnailable parts bin, wants to be thumbnailed whether or not size requires it\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/12/2004 21:12'!\\nicon\\n\\t\\\"Answer a form with an icon to represent the receiver\\\"\\n\\t^ self valueOfProperty: #icon! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/12/2004 20:33'!\\niconOrThumbnail\\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\n\\t^ self icon\\n\\t\\tifNil: [ | maxExtent fb |maxExtent := 320 @ 240.\\n\\t\\t\\tfb := self fullBounds.\\n\\t\\t\\tfb area <= (maxExtent x * maxExtent y)\\n\\t\\t\\t\\tifTrue: [self imageForm]\\n\\t\\t\\t\\tifFalse: [self imageFormForRectangle: (fb topLeft extent: maxExtent)]\\n\\t\\t]\\n! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/13/2004 12:43'!\\niconOrThumbnailOfSize: aNumberOrPoint \\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\n\\t^ self iconOrThumbnail scaledIntoFormOfSize: aNumberOrPoint\\n! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 8/16/2000 17:40'!\\nmorphRepresented\\n\\t\\\"If the receiver is an alias, answer the morph it represents; else answer self\\\"\\n\\n\\t^ self! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 6/16/1999 11:29'!\\npermitsThumbnailing\\n\\t^ true! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'ar 11/9/2000 20:42'!\\nreadoutForField: fieldSym\\n\\t\\\"Provide a readout that will show the value of the slot/pseudoslot of the receiver generated by sending fieldSym to the receiver\\\"\\n\\n\\t| aContainer |\\n\\t\\\"still need to get this right\\\"\\n\\taContainer _ AlignmentMorph newColumn.\\n\\taContainer layoutInset: 0; hResizing: #rigid; vResizing: #shrinkWrap.\\n\\taContainer addMorphBack: (StringMorph new contents: (self perform: fieldSym) asString).\\n\\t^ aContainer! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 12/6/2000 21:28'!\\nrepresentativeNoTallerThan: maxHeight norWiderThan: maxWidth thumbnailHeight: thumbnailHeight\\n\\t\\\"Return a morph representing the receiver but which is no taller than aHeight. If the receiver is already small enough, just return it, else return a MorphThumbnail companioned to the receiver, enforcing the maxWidth. If the receiver personally *demands* thumbnailing, do it even if there is no size-related reason to do it.\\\"\\n\\n\\tself demandsThumbnailing ifFalse:\\n\\t\\t[self permitsThumbnailing ifFalse: [^ self].\\n\\t\\t(self fullBounds height <= maxHeight and: [self fullBounds width <= maxWidth]) ifTrue: [^ self]].\\n\\n\\t^ MorphThumbnail new extent: maxWidth @ (thumbnailHeight min: self fullBounds height); morphRepresented: self! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'tk 3/28/2000 11:08'!\\nupdateThumbnailUrl\\n\\t\\\"If I have a cached thumbnail, then update it's urls.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail pageMorph: self url inBook: owner url]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\t\\\"Test and removal are because the thumbnail is being replaced \\n\\t\\t\\tby another Morph. We don't know why. Need to fix that at \\n\\t\\t\\tthe source.\\\"! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'tk 3/28/2000 21:55'!\\nupdateThumbnailUrlInBook: bookUrl\\n\\t\\\"If I have a cached thumbnail, then update it's urls.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail pageMorph: self url inBook: bookUrl]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\t\\\"Test and removal are because the thumbnail is being replaced \\n\\t\\t\\tby another Morph. We don't know why. Need to fix that at \\n\\t\\t\\tthe source.\\\"! !\\n\\n\\n!Morph methodsFor: 'undo' stamp: 'ar 8/31/2000 23:15'!\\ncommandHistory\\n\\t\\\"Return the command history for the receiver\\\"\\n\\t| w |\\n\\t(w _ self world) ifNotNil:[^w commandHistory].\\n\\t(w _ self currentWorld) ifNotNil:[^w commandHistory].\\n\\t^CommandHistory new. \\\"won't really record anything but prevent breaking things\\\"! !\\n\\n!Morph methodsFor: 'undo' stamp: 'md 10/22/2003 15:56'!\\nundoMove: cmd redo: redo owner: formerOwner bounds: formerBounds predecessor: formerPredecessor \\n\\t\\\"Handle undo and redo of move commands in morphic\\\"\\n\\n\\tself owner ifNil: [^Beeper beep].\\n\\tredo \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"undo sets up the redo state first\\\"\\n\\n\\t\\t\\tcmd \\n\\t\\t\\t\\tredoTarget: self\\n\\t\\t\\t\\tselector: #undoMove:redo:owner:bounds:predecessor:\\n\\t\\t\\t\\targuments: { \\n\\t\\t\\t\\t\\t\\tcmd.\\n\\t\\t\\t\\t\\t\\ttrue.\\n\\t\\t\\t\\t\\t\\towner.\\n\\t\\t\\t\\t\\t\\tbounds.\\n\\t\\t\\t\\t\\t\\towner morphPreceding: self}].\\n\\tformerOwner ifNotNil: \\n\\t\\t\\t[formerPredecessor ifNil: [formerOwner addMorphFront: self]\\n\\t\\t\\t\\tifNotNil: [formerOwner addMorph: self after: formerPredecessor]].\\n\\tself bounds: formerBounds.\\n\\t(self isSystemWindow) ifTrue: [self activate]! !\\n\\n\\n!Morph methodsFor: 'updating' stamp: 'ar 6/25/2001 19:46'!\\nchanged\\n\\t\\\"Report that the area occupied by this morph should be redrawn.\\\"\\n\\t^fullBounds \\n\\t\\tifNil:[self invalidRect: self outerBounds]\\n\\t\\tifNotNil:[self invalidRect: fullBounds]! !\\n\\n\\n!Morph methodsFor: 'user interface' stamp: 'tak 3/15/2005 17:36'!\\nbecomeModal\\n\\tself currentWorld\\n\\t\\tifNotNil: [self currentWorld modalWindow: self]! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'sw 5/29/2000 00:41'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\t^ super printString truncateTo: 40! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'tak 3/15/2005 17:10'!\\ndoCancel\\n\\tself delete! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'sw 10/2/97 23:08'!\\ninitialExtent\\n\\t| ext |\\n\\t(ext _ self valueOfProperty: #initialExtent)\\n\\t\\tifNotNil:\\n\\t\\t\\t[^ ext].\\n\\t^ super initialExtent! !\\n\\n\\n!Morph methodsFor: 'viewer' stamp: 'sw 10/30/1998 14:46'!\\nexternalName\\n\\t^ self knownName ifNil: [self innocuousName]! !\\n\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/25/1999 11:11'!\\ncanHaveFillStyles\\n\\t\\\"Return true if the receiver can have general fill styles; not just colors.\\n\\tThis method is for gradually converting old morphs.\\\"\\n\\t^self class == Morph \\\"no subclasses\\\"! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'mk 8/7/2005 10:02'!\\ncornerStyle\\n\\t\\\"Returns one of the following symbols:\\n\\t\\t#square\\n\\t\\t#rounded\\n\\taccording to the current corner style.\\\"\\n\\n\\t^ self valueOfProperty: #cornerStyle ifAbsent: [#square]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 8/28/2003 15:56'!\\ndefaultBitmapFillForm\\n\\t^ImageMorph defaultForm.\\n! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'dgd 2/16/2003 20:02'!\\nfillStyle\\n\\t\\\"Return the current fillStyle of the receiver.\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #fillStyle\\n\\t\\tifAbsent: [\\\"Workaround already converted morphs\\\"\\n\\t\\t\\tcolor\\n\\t\\t\\t\\tifNil: [self defaultColor]]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/18/1999 07:05'!\\nfillStyle: aFillStyle\\n\\t\\\"Set the current fillStyle of the receiver.\\\"\\n\\tself setProperty: #fillStyle toValue: aFillStyle.\\n\\t\\\"Workaround for Morphs not yet converted\\\"\\n\\tcolor _ aFillStyle asColor.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'dgd 1/7/2005 19:31'!\\nfillWithRamp: rampSpecsOrColor oriented: aRatio \\n\\trampSpecsOrColor isColor\\n\\t\\tifTrue: [self color: rampSpecsOrColor\\\".\\n\\t\\t\\tself borderColor: rampSpecsOrColor muchDarker\\\"]\\n\\t\\tifFalse: [| fill | \\n\\t\\t\\tfill := GradientFillStyle ramp: rampSpecsOrColor.\\n\\t\\t\\tfill origin: self bounds topLeft.\\n\\t\\t\\tfill direction: (self bounds extent * aRatio) truncated.\\n\\t\\t\\tfill radial: false.\\n\\t\\t\\tself fillStyle: fill.\\n\\t\\t\\tself borderColor: (rampSpecsOrColor first value mixed: 0.5 with: rampSpecsOrColor last value) muchDarker]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 8/28/2003 15:57'!\\nuseBitmapFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\t| fill |\\n\\tself fillStyle isBitmapFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tfill _ BitmapFillStyle fromForm: self defaultBitmapFillForm.\\n\\t\\\"Note: Must fix the origin due to global coordinates\\\"\\n\\tfill origin: self bounds origin.\\n\\tself fillStyle: fill.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/25/1999 11:11'!\\nuseDefaultFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\tself fillStyle: self defaultColor.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 2/27/2003 11:48'!\\nuseGradientFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\t| fill color1 color2 |\\n\\tself fillStyle isGradientFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tcolor1 _ self color asColor.\\n\\tcolor2 _ color1 negated.\\n\\tfill _ GradientFillStyle ramp: {0.0 -> color1. 1.0 -> color2}.\\n\\tfill origin: self topLeft.\\n\\tfill direction: 0 @ self bounds extent y.\\n\\tfill normal: self bounds extent x @ 0.\\n\\tfill radial: false.\\n\\tself fillStyle: fill! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/18/1999 06:57'!\\nuseSolidFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\tself fillStyle isSolidFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tself fillStyle: self fillStyle asColor. \\\"Try minimizing changes\\\"! !\\n\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 2/16/2001 13:57'!\\naddMorphInFrontOfLayer: aMorph\\n\\n\\t| targetLayer layerHere |\\n\\n\\ttargetLayer _ aMorph morphicLayerNumberWithin: self.\\n\\tsubmorphs do: [ :each |\\n\\t\\teach == aMorph ifTrue: [^self].\\n\\t\\tlayerHere _ each morphicLayerNumberWithin: self.\\n\\t\\t\\\"the <= is the difference - it insures we go to the front of our layer\\\"\\n\\t\\ttargetLayer <= layerHere ifTrue: [\\n\\t\\t\\t^self addMorph: aMorph inFrontOf: each\\n\\t\\t].\\n\\t].\\n\\tself addMorphBack: aMorph.\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 6/29/2000 10:49'!\\naddMorphInLayer: aMorph\\n\\n\\tsubmorphs do: [ :each |\\n\\t\\teach == aMorph ifTrue: [^self].\\n\\t\\taMorph morphicLayerNumber < each morphicLayerNumber ifTrue: [\\n\\t\\t\\t^self addMorph: aMorph inFrontOf: each\\n\\t\\t].\\n\\t].\\n\\tself addMorphBack: aMorph\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'gk 5/24/2004 15:43'!\\neToyRejectDropMorph: morphToDrop event: evt\\n\\n\\t| tm am |\\n\\n\\ttm _ TextMorph new \\n\\t\\tbeAllFont: ((TextStyle named: Preferences standardEToysFont familyName) fontOfSize: 24);\\n\\t\\tcontents: 'GOT IT!!'.\\n\\t(am _ AlignmentMorph new)\\n\\t\\tcolor: Color yellow;\\n\\t\\tlayoutInset: 10;\\n\\t\\tuseRoundedCorners;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\taddMorph: tm;\\n\\t\\tfullBounds;\\n\\t\\tposition: (self bounds center - (am extent // 2));\\n\\t\\topenInWorld: self world.\\n\\tSoundService default playSoundNamed: 'yum' ifAbsentReadFrom: 'yum.aif'.\\n\\tmorphToDrop rejectDropMorphEvent: evt.\\t\\t\\\"send it back where it came from\\\"\\n\\tam delete\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 7/19/2000 20:44'!\\nmorphicLayerNumber\\n\\n\\t\\\"helpful for insuring some morphs always appear in front of or behind others.\\n\\tsmaller numbers are in front\\\"\\n\\n\\t^(owner isNil or: [owner isWorldMorph]) ifTrue: [\\n\\t\\tself valueOfProperty: #morphicLayerNumber ifAbsent: [100]\\n\\t] ifFalse: [\\n\\t\\towner morphicLayerNumber\\n\\t].\\n\\n\\t\\\"leave lots of room for special things\\\"! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 2/16/2001 13:54'!\\nmorphicLayerNumberWithin: anOwner\\n\\n\\t\\\"helpful for insuring some morphs always appear in front of or behind others.\\n\\tsmaller numbers are in front\\\"\\n\\n\\t^(owner isNil or: [owner isWorldMorph or: [anOwner == owner]]) ifTrue: [\\n\\t\\tself valueOfProperty: #morphicLayerNumber ifAbsent: [100]\\n\\t] ifFalse: [\\n\\t\\towner morphicLayerNumber\\n\\t].\\n\\n\\t\\\"leave lots of room for special things\\\"! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 7/16/2000 13:54'!\\nrandomBoundsFor: aMorph\\n\\n\\t| trialRect |\\n\\ttrialRect _ (\\n\\t\\tself topLeft + \\n\\t\\t\\t((self width * (15 + 75 atRandom/100)) rounded @\\n\\t\\t\\t(self height * (15 + 75 atRandom/100)) rounded)\\n\\t) extent: aMorph extent.\\n\\t^trialRect translateBy: (trialRect amountToTranslateWithin: self bounds)\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'ar 3/18/2001 00:14'!\\nshouldGetStepsFrom: aWorld\\n\\t^self world == aWorld! !\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/24/2003 17:31'!\\ninstantiatedUserScriptsDo: aBlock\\n\\tself actorStateOrNil ifNotNilDo: [ :aState | aState instantiatedUserScriptsDictionary do: aBlock]! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:36'!\\nremoveAllEventTriggers\\n\\t\\\"Remove all the event registrations for my Player.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\t| player |\\n\\t(player _ self player) ifNil: [ ^self ].\\n\\tself removeAllEventTriggersFor: player.\\n\\tself currentWorld removeAllEventTriggersFor: player.! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/24/2003 17:46'!\\nremoveAllEventTriggersFor: aPlayer\\n\\t\\\"Remove all the event registrations for aPlayer.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\tself removeActionsSatisfying: \\n\\t\\t\\t[:action | action receiver == aPlayer and: [(#(#doScript: #triggerScript:) includes: action selector) ]].! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:37'!\\nremoveEventTrigger: aSymbol\\n\\t\\\"Remove all the event registrations for my Player that are triggered by aSymbol.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\t| player |\\n\\t(player _ self player) ifNil: [ ^self ].\\n\\tself removeEventTrigger: aSymbol for: player.\\n\\tself currentWorld removeEventTrigger: aSymbol for: player.! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:24'!\\nremoveEventTrigger: aSymbol for: aPlayer \\n\\t\\\"Remove all the event registrations for aPlayer that are triggered by \\n\\taSymbol. User custom events are triggered at the World, \\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\tself removeActionsSatisfying: [:action | action receiver == aPlayer\\n\\t\\t\\t\\tand: [(#(#doScript: #triggerScript: ) includes: action selector)\\n\\t\\t\\t\\t\\t\\tand: [action arguments first == aSymbol]]]! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:11'!\\nrenameScriptActionsFor: aPlayer from: oldSelector to: newSelector\\n\\n\\tself updateableActionMap keysAndValuesDo: [ :event :sequence |\\n\\t\\tsequence asActionSequence do: [ :action |\\n\\t\\t\\t((action receiver == aPlayer)\\n\\t\\t\\t\\tand: [ (#(doScript: triggerScript:) includes: action selector)\\n\\t\\t\\t\\t\\tand: [ action arguments first == oldSelector ]])\\n\\t\\t\\t\\t\\t\\tifTrue: [ action arguments at: 1 put: newSelector ]]]\\n! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 11:00'!\\ntriggerCustomEvent: aSymbol\\n\\t\\\"Trigger whatever scripts may be connected to the custom event named aSymbol\\\"\\n\\n\\tself currentWorld triggerEtoyEvent: aSymbol from: self! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 10:54'!\\ntriggerEtoyEvent: aSymbol\\n\\t\\\"Trigger whatever scripts may be connected to the event named aSymbol.\\n\\tIf anyone comes back to ask who sent it, return our player.\\\"\\n\\n\\t[ self triggerEvent: aSymbol ]\\n\\t\\ton: GetTriggeringObjectNotification do: [ :ex |\\n\\t\\t\\tex isNested\\n\\t\\t\\t\\tifTrue: [ ex pass ]\\n\\t\\t\\t\\tifFalse: [ ex resume: self assuredPlayer ]]\\n! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 10:58'!\\ntriggerEtoyEvent: aSymbol from: aMorph\\n\\t\\\"Trigger whatever scripts may be connected to the event named aSymbol.\\n\\tIf anyone comes back to ask who sent it, return aMorph's player.\\\"\\n\\n\\t[ self triggerEvent: aSymbol ]\\n\\t\\ton: GetTriggeringObjectNotification do: [ :ex |\\n\\t\\t\\tex isNested\\n\\t\\t\\t\\tifTrue: [ ex pass ]\\n\\t\\t\\t\\tifFalse: [ ex resume: aMorph assuredPlayer ]]\\n! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*Flash-classification' stamp: 'ar 8/10/1998 18:50'!\\nisFlashMorph\\n\\t^false! !\\n\\n\\n!Morph methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 17:31'!\\nunfilteredCategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer, in order of:\\n\\t- masterOrderingOfCategorySymbols first\\n\\t- others last in order by translated wording\\\"\\n\\t\\\"\\n\\tMorph basicNew unfilteredCategoriesForViewer\\n\\t\\\"\\n\\t^self renderedMorph class unfilteredCategoriesForViewer.\\n! !\\n\\n\\n!Morph methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 1/7/2005 19:07'!\\nhighlightOnlySubmorph: aMorph\\n\\t\\\"Distinguish only aMorph with border highlighting (2-pixel wide red); make all my other submorphs have one-pixel-black highlighting. This is a rather special-purpose and hard-coded highlighting regime, of course. Later, if someone cared to do it, we could parameterize the widths and colors via properties, or some such.\\\"\\n\\n\\tself submorphs do:\\n\\t\\t[:m |\\n\\t\\t\\tm == aMorph\\n\\t\\t\\t\\tifTrue: [m borderWidth: 1; borderColor: Color red. m firstSubmorph color: Color red]\\n\\t\\t\\t\\tifFalse: [m borderWidth: 1; borderColor: Color black. m firstSubmorph color: Color black]\\n\\t\\t].\\n! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*MorphicExtras-geometry' stamp: 'dgd 8/31/2004 16:22'!\\nshiftSubmorphsBy: delta\\n\\tself shiftSubmorphsOtherThan: (submorphs select: [:m | m wantsToBeTopmost]) by: delta! !\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*MorphicExtras-menus' stamp: 'dgd 4/3/2006 14:18'!\\ndismissButton\\n\\t\\\"Answer a button whose action would be to dismiss the receiver, and whose action is to send #delete to the receiver\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton\\n\\t\\ttarget: self topRendererOrSelf;\\n\\t\\tcolor: ColorTheme current cancelColor;\\n\\t\\tborderColor: ColorTheme current cancelColor muchDarker;\\n\\t\\tborderWidth: 1;\\n\\t\\tlabel: 'X' font: Preferences standardButtonFont;\\n\\t\\tactionSelector: #delete;\\n\\t\\tsetBalloonText: 'dismiss' translated.\\n\\t^ aButton! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*services-base' stamp: 'rr 6/10/2005 11:30'!\\nrequestor\\n\\t^ owner ifNil: [super requestor] ifNotNil: [owner requestor]! !\\n\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 17:29'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tt > rightTime ifTrue: [^ self]. \\n\\tt < leftTime ifTrue: [^ self].\\n\\tmorphList add: (self left: (pianoRoll xForTime: t)).\\n! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 15:48'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tself triggerActionFromPianoRoll.! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'stephaneducasse 2/4/2006 20:40'!\\njustDroppedIntoPianoRoll: pianoRoll event: evt\\n\\t\\n\\t| ambientEvent startTimeInScore |\\n\\tstartTimeInScore := pianoRoll timeForX: self left.\\n\\n\\tambientEvent := AmbientEvent new \\n\\t\\tmorph: self;\\n\\t\\ttime: startTimeInScore.\\n\\n\\tpianoRoll score addAmbientEvent: ambientEvent.\\n\\n\\t\\\"self endTime > pianoRoll scorePlayer durationInTicks ifTrue:\\n\\t\\t[pianoRoll scorePlayer updateDuration]\\\"\\n! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:21'!\\npauseFrom: scorePlayer\\n\\n\\t\\\"subclasses should take five\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:22'!\\nresetFrom: scorePlayer\\n\\n\\t\\\"subclasses should revert to their initial state\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:21'!\\nresumeFrom: scorePlayer\\n\\n\\t\\\"subclasses should continue from their current position\\\"\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ntriggerActionFromPianoRoll\\n\\n\\t| evt |\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tself world ifNil: [^self].\\n\\tevt := MouseEvent new setType: nil position: self center buttons: 0 hand: self world activeHand.\\n\\tself programmedMouseUp: evt for: self.\\n\\n! !\\n\\n\\n!Morph methodsFor: 'private' stamp: 'sw 10/25/2000 06:11'!\\nmoveWithPenDownBy: delta\\n\\t\\\"If this is a costume for a player with its pen down, draw a line.\\\"\\n\\n\\t| trailMorph tfm start tfmEnd |\\n\\t(trailMorph _ self trailMorph) ifNotNil:\\n\\t\\t[tfm _ self owner transformFrom: trailMorph.\\n\\t\\tstart _ self referencePosition.\\n\\t\\ttrailMorph batchPenTrails\\n\\t\\t\\tifTrue: [trailMorph notePenDown: true\\n\\t\\t\\t\\t\\t\\t\\t\\tforPlayer: self player\\n\\t\\t\\t\\t\\t\\t\\t\\tat: (tfm localPointToGlobal: start)]\\n\\t\\t\\tifFalse: [trailMorph drawPenTrailFor: self\\n\\t\\t\\t\\t\\t\\t\\t\\tfrom: (tfm localPointToGlobal: start)\\n\\t\\t\\t\\t\\t\\t\\t\\tto: (tfmEnd _ tfm localPointToGlobal: start + delta).\\n\\t\\t\\t\\t\\ttrailMorph noteNewLocation: tfmEnd forPlayer: self player]]\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'nk 10/11/2003 16:08'!\\nprivateAddAllMorphs: aCollection atIndex: index\\n\\t\\\"Private. Add aCollection of morphs to the receiver\\\"\\n\\t| myWorld itsWorld otherSubmorphs |\\n\\tmyWorld _ self world.\\n\\totherSubmorphs _ submorphs copyWithoutAll: aCollection.\\n\\t(index between: 0 and: otherSubmorphs size)\\n\\t\\tifFalse: [^ self error: 'index out of range'].\\n\\tindex = 0\\n\\t\\tifTrue:[\\tsubmorphs _ aCollection asArray, otherSubmorphs]\\n\\t\\tifFalse:[\\tindex = otherSubmorphs size\\n\\t\\t\\tifTrue:[\\tsubmorphs _ otherSubmorphs, aCollection]\\n\\t\\t\\tifFalse:[\\tsubmorphs _ otherSubmorphs copyReplaceFrom: index + 1 to: index with: aCollection ]].\\n\\taCollection do: [:m | | itsOwner |\\n\\t\\titsOwner _ m owner.\\n\\t\\titsOwner ifNotNil: [\\n\\t\\t\\titsWorld _ m world.\\n\\t\\t\\t(itsWorld == myWorld) ifFalse: [\\n\\t\\t\\t\\titsWorld ifNotNil: [self privateInvalidateMorph: m].\\n\\t\\t\\t\\tm outOfWorld: itsWorld].\\n\\t\\t\\t(itsOwner ~~ self) ifTrue: [\\n\\t\\t\\t\\tm owner privateRemove: m.\\n\\t\\t\\t\\tm owner removedMorph: m ]].\\n\\t\\tm privateOwner: self.\\n\\t\\tmyWorld ifNotNil: [self privateInvalidateMorph: m].\\n\\t\\t(myWorld == itsWorld) ifFalse: [m intoWorld: myWorld].\\n\\t\\titsOwner == self ifFalse: [\\n\\t\\t\\tself addedMorph: m.\\n\\t\\t\\tm noteNewOwner: self ].\\n\\t].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'nk 10/11/2003 16:08'!\\nprivateAddMorph: aMorph atIndex: index\\n\\n\\t| oldIndex myWorld itsWorld oldOwner |\\n\\t((index >= 1) and: [index <= (submorphs size + 1)])\\n\\t\\tifFalse: [^ self error: 'index out of range'].\\n\\tmyWorld _ self world.\\n\\toldOwner _ aMorph owner.\\n\\t(oldOwner == self and: [(oldIndex _ submorphs indexOf: aMorph) > 0]) ifTrue:[\\n\\t\\t\\\"aMorph's position changes within in the submorph chain\\\"\\n\\t\\toldIndex < index ifTrue:[\\n\\t\\t\\t\\\"moving aMorph to back\\\"\\n\\t\\t\\tsubmorphs replaceFrom: oldIndex to: index-2 with: submorphs startingAt: oldIndex+1.\\n\\t\\t\\tsubmorphs at: index-1 put: aMorph.\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"moving aMorph to front\\\"\\n\\t\\t\\toldIndex-1 to: index by: -1 do:[:i|\\n\\t\\t\\t\\tsubmorphs at: i+1 put: (submorphs at: i)].\\n\\t\\t\\tsubmorphs at: index put: aMorph.\\n\\t\\t].\\n\\t] ifFalse:[\\n\\t\\t\\\"adding a new morph\\\"\\n\\t\\toldOwner ifNotNil:[\\n\\t\\t\\titsWorld _ aMorph world.\\n\\t\\t\\titsWorld ifNotNil: [self privateInvalidateMorph: aMorph].\\n\\t\\t\\t(itsWorld == myWorld) ifFalse: [aMorph outOfWorld: itsWorld].\\n\\t\\t\\toldOwner privateRemove: aMorph.\\n\\t\\t\\toldOwner removedMorph: aMorph.\\n\\t\\t].\\n\\t\\taMorph privateOwner: self.\\n\\t\\tsubmorphs _ submorphs copyReplaceFrom: index to: index-1 with: (Array with: aMorph).\\n\\t\\t(itsWorld == myWorld) ifFalse: [aMorph intoWorld: myWorld].\\n\\t].\\n\\tmyWorld ifNotNil:[self privateInvalidateMorph: aMorph].\\n\\tself layoutChanged.\\n\\toldOwner == self ifFalse: [\\n\\t\\tself addedMorph: aMorph.\\n\\t\\taMorph noteNewOwner: self ].\\n! !\\n\\n!Morph methodsFor: 'private'!\\nprivateBounds: boundsRect\\n\\t\\\"Private!! Use position: and/or extent: instead.\\\"\\n\\n\\tfullBounds _ nil.\\n\\tbounds _ boundsRect.! !\\n\\n!Morph methodsFor: 'private' stamp: 'jm 5/29/1998 21:28'!\\nprivateColor: aColor\\n\\n\\tcolor _ aColor.\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'RAA 5/23/2000 11:31'!\\nprivateDeleteWithAbsolutelyNoSideEffects\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\t\\\"used to delete a morph from an inactive world\\\"\\n\\n\\towner ifNil: [^self].\\n\\towner privateRemoveMorphWithAbsolutelyNoSideEffects: self.\\n\\towner _ nil.\\n\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'tk 8/30/1998 09:58'!\\nprivateFullBounds: boundsRect\\n\\t\\\"Private!! Computed automatically.\\\"\\n\\n\\tfullBounds _ boundsRect.! !\\n\\n!Morph methodsFor: 'private' stamp: 'ar 12/16/2001 21:47'!\\nprivateFullMoveBy: delta\\n\\t\\\"Private!! Relocate me and all of my subMorphs by recursion. Subclasses that implement different coordinate systems may override this method.\\\"\\n\\n\\tself privateMoveBy: delta.\\n\\t1 to: submorphs size do: [:i |\\n\\t\\t(submorphs at: i) privateFullMoveBy: delta].\\n\\towner ifNotNil:[\\n\\t\\towner isTextMorph ifTrue:[owner adjustTextAnchor: self]].! !\\n\\n!Morph methodsFor: 'private' stamp: 'md 2/27/2006 08:55'!\\nprivateMoveBy: delta \\n\\t\\\"Private!! Use 'position:' instead.\\\"\\n\\t| fill |\\n\\textension ifNotNil: [extension player\\n\\t\\t\\t\\tifNotNil: [\\\"Most cases eliminated fast by above test\\\"\\n\\t\\t\\t\\t\\tself getPenDown\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"If this is a costume for a player with its \\n\\t\\t\\t\\t\\t\\t\\tpen down, draw a line.\\\"\\n\\t\\t\\t\\t\\t\\t\\tself moveWithPenDownBy: delta]]].\\n\\tbounds _ bounds translateBy: delta.\\n\\tfullBounds ifNotNil: [fullBounds _ fullBounds translateBy: delta].\\n\\tfill _ self fillStyle.\\n\\tfill isOrientedFill ifTrue: [fill origin: fill origin + delta]! !\\n\\n!Morph methodsFor: 'private'!\\nprivateOwner: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\towner _ aMorph.! !\\n\\n!Morph methodsFor: 'private' stamp: 'RAA 5/23/2000 11:30'!\\nprivateRemoveMorphWithAbsolutelyNoSideEffects: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\t\\\"used to delete a morph from an inactive world\\\"\\n\\n\\tsubmorphs _ submorphs copyWithout: aMorph.\\n\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'di 10/18/2004 21:49'!\\nprivateRemove: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\tsubmorphs _ submorphs copyWithout: aMorph.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'private'!\\nprivateSubmorphs\\n\\t\\\"Private!! Use 'submorphs' instead.\\\"\\n\\n\\t^ submorphs! !\\n\\n!Morph methodsFor: 'private'!\\nprivateSubmorphs: aCollection\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\tsubmorphs _ aCollection.! !\\n\\n\\n!Morph methodsFor: 'accessing-backstop' stamp: 'wiz 2/14/2006 19:02'!\\ntarget: aMorph\\n\\\"Morphs with targets will override. This backstop does nothing.\\\"\\n\\\"This is here because targeting meta-actions are taken at morph level. \\nDo not remove.\\\"! !\\n\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/27/2005 23:29'!\\naccumlatePlayersInto: aCollection andSelectorsInto: selectorsCollection\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue: [\\n\\t\\t\\t(tile type = #objRef and: [tile actualObject isKindOf: Player]) ifTrue: [\\n\\t\\t\\t\\taCollection add: tile actualObject\\n\\t\\t\\t]\\n\\t\\t].\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue: [\\n\\t\\t\\t(tile type = #operator) ifTrue: [\\n\\t\\t\\t\\tselectorsCollection add: tile operatorOrExpression\\n\\t\\t\\t]\\n\\t\\t].\\n\\t\\ttile accumlatePlayersInto: aCollection andSelectorsInto: selectorsCollection\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'translation' stamp: 'sw 3/7/2004 13:03'!\\nisPlayer: aPlayer ofReferencingTile: tile\\n\\t\\\"Answer whether the given player is the object referred to by the given tile, or a sibling of that object. This theoretically is only sent to PhraseTileMorphs, so this version is theoretically never reached\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/27/2005 23:33'!\\nisTurtleRow\\n\\n\\t| aCollection selectorCollection |\\n\\taCollection _ Set new.\\n\\tselectorCollection _ Set new.\\n\\tself accumlatePlayersInto: aCollection andSelectorsInto: selectorCollection.\\n\\t#(turtleCount: turtleCount grouped: grouped) do: [:sel |\\n\\t\\t(selectorCollection includes: sel) ifTrue: [^ false].\\n\\t].\\n\\n\\taCollection do: [:e |\\n\\t\\t(e isKindOf: KedamaExamplerPlayer) ifTrue: [^ true].\\n\\t].\\n\\t^ false.\\n! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/18/2004 10:31'!\\ntraverseRowTranslateSlotOld: oldSlotName of: aPlayer to: newSlotName\\n\\t\\\"Traverse my submorphs, translating submorphs appropriately given the slot rename\\\"\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue:\\n\\t\\t\\t[tile assignmentRoot = oldSlotName ifTrue:\\n\\t\\t\\t\\t[(self isPlayer: aPlayer ofReferencingTile: tile) ifTrue:\\n\\t\\t\\t\\t\\t[tile setRoot: newSlotName]]].\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue:\\n\\t\\t\\t[(tile operatorOrExpression = (Utilities getterSelectorFor: oldSlotName)) ifTrue:\\n\\t\\t\\t\\t[(self isPlayer: aPlayer ofReferencingTile: tile) ifTrue:\\n\\t\\t\\t\\t\\t[tile setOperator: (Utilities getterSelectorFor: newSlotName)]]].\\n\\t\\ttile traverseRowTranslateSlotOld: oldSlotName of: aPlayer to: newSlotName]! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/18/2004 10:32'!\\ntraverseRowTranslateSlotOld: oldSlotName to: newSlotName\\n\\t\\\"Traverse my submorphs, translating submorphs appropriately given the slot rename\\\"\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue: \\n\\t\\t\\t[tile assignmentRoot = oldSlotName ifTrue: [tile setRoot: newSlotName]].\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue:\\n\\t\\t\\t[(tile operatorOrExpression = (Utilities getterSelectorFor: oldSlotName)) ifTrue:\\n\\t\\t\\t\\t[tile setOperator: (Utilities getterSelectorFor: newSlotName)]].\\n\\t\\ttile traverseRowTranslateSlotOld: oldSlotName to: newSlotName]! !\\n\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/9/1999 17:43'!\\nadaptToWorld: aWorld\\n\\t\\\"The receiver finds itself operating in a possibly-different new world. If any of the receiver's parts are world-dependent (such as a target of a SimpleButtonMorph, etc.), then have them adapt accordingly\\\"\\n\\tsubmorphs do: [:m | m adaptToWorld: aWorld].\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler adaptToWorld: aWorld]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 5/17/2001 12:47'!\\nadoptVocabulary: aVocabulary\\n\\t\\\"Make aVocabulary be the one used by me and my submorphs\\\"\\n\\n\\tself submorphsDo: [:m | m adoptVocabulary: aVocabulary]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'yo 1/9/2004 16:10'!\\nallMorphsAndBookPagesInto: aSet\\n\\t\\\"Return a set of all submorphs. Don't forget the hidden ones like BookMorph pages that are not showing. Consider only objects that are in memory (see allNonSubmorphMorphs).\\\" \\n\\n\\tsubmorphs do: [:m | m allMorphsAndBookPagesInto: aSet].\\n\\tself allNonSubmorphMorphs do: [:m | \\n\\t\\t\\t(aSet includes: m) ifFalse: [\\\"Stop infinite recursion\\\"\\n\\t\\t\\t\\tm allMorphsAndBookPagesInto: aSet]].\\n\\taSet add: self.\\n\\tself player ifNotNil:\\n\\t\\t[self player allScriptEditors do: [:e | e allMorphsAndBookPagesInto: aSet]].\\n\\t^ aSet! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 1/13/2001 11:27'!\\nappearsToBeSameCostumeAs: aMorph\\n\\n\\t^false\\n! !\\n\\n!Morph methodsFor: 'e-toy support'!\\nasNumber: aPointOrNumber\\n\\t\\\"Support for e-toy demo.\\\"\\n\\n\\taPointOrNumber class = Point\\n\\t\\tifTrue: [^ aPointOrNumber r]\\n\\t\\tifFalse: [^ aPointOrNumber].\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nk 1/6/2004 12:37'!\\nasWearableCostume\\n\\t\\\"Return a wearable costume for some player\\\"\\n\\t^(World drawingClass withForm: self imageForm) copyCostumeStateFrom: self! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'mir 6/13/2001 14:34'!\\nasWearableCostumeOfExtent: extent\\n\\t\\\"Return a wearable costume for some player\\\"\\n\\t^self asWearableCostume! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 12/20/1999 17:36'!\\nautomaticViewing\\n\\t\\\"Backstop, in case this message gets sent to an owner that is not a playfield\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 5/18/2001 11:17'!\\nchangeAllBorderColorsFrom: oldColor to: newColor\\n\\t\\\"Set any occurrence of oldColor as a border color in my entire submorph tree to be newColor\\\"\\n\\n\\t(self allMorphs select: [:m | m respondsTo: #borderColor:]) do:\\n\\t\\t[:aMorph | aMorph borderColor = oldColor ifTrue: [aMorph borderColor: newColor]]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/1/97 00:18'!\\nconfigureForKids\\n\\tsubmorphs ifNotNil:\\n\\t\\t[submorphs do: [:m | m configureForKids]]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/6/2001 04:21'!\\ncontainingWindow\\n\\t\\\"Answer a window or window-with-mvc that contains the receiver\\\"\\n\\n\\t^ self ownerThatIsA: SystemWindow orA: MVCWiWPasteUpMorph! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:38'!\\ncopyCostumeStateFrom: aMorph\\n\\t\\\"Copy all state that should be persistant for costumes from aMorph\\\"\\n\\tself rotationCenter: aMorph rotationCenter.\\n\\tself rotationStyle: aMorph rotationStyle.\\n\\tself referencePosition: aMorph referencePosition.\\n\\tself forwardDirection: aMorph forwardDirection.\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/22/1998 20:28'!\\ncurrentPlayerDo: aBlock\\n\\t\\\"If the receiver is a viewer/scriptor associated with a current Player object, evaluate the given block against that object\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/8/2000 16:34'!\\ncursor\\n\\t\\\"vacuous backstop in case it gets sent to a morph that doesn't know what to do with it\\\"\\n\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/7/2000 09:28'!\\ncursor: aNumber\\n\\t\\\"vacuous backstop in case it gets sent to a morph that doesn't know what to do with it\\\"\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/13/2002 17:44'!\\ndecimalPlacesForGetter: aGetter\\n\\t\\\"Answer the decimal places I prefer for showing a slot with the given getter, or nil if none\\\"\\n\\n\\t| decimalPrefs |\\n\\tdecimalPrefs _ self renderedMorph valueOfProperty: #decimalPlacePreferences ifAbsent: [^ nil].\\n\\t^ decimalPrefs at: aGetter ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/24/2000 05:52'!\\ndefaultValueOrNil\\n\\t\\\"If the receiver has a property named #defaultValue, return that property's value, else return nil\\\"\\n\\n\\t^ self valueOfProperty: #defaultValue ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sd 3/30/2005 22:04'!\\ndefaultVariableName\\n\\t\\\"If the receiver is of the sort that wants a variable maintained on its behalf in the 'card' data, then return a variable name to be used for that datum. What is returned here is only a point of departure in the forthcoming negotiation\\\"\\n\\n\\t^ Scanner wellFormedInstanceVariableNameFrom: (self valueOfProperty: #variableName ifAbsent: [self externalName])! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nb 6/17/2003 12:25'!\\ndefinePath\\n\\t| points lastPoint aForm offset currentPoint dwell ownerPosition |\\n\\tpoints _ OrderedCollection new: 70.\\n\\tlastPoint _ nil.\\n\\taForm _ self imageForm.\\n\\toffset _ aForm extent // 2.\\n\\townerPosition _ owner position.\\n\\tCursor move show.\\n\\tSensor waitButton.\\n\\t[Sensor anyButtonPressed and: [points size < 100]] whileTrue:\\n\\t\\t[currentPoint _ Sensor cursorPoint.\\n\\t\\tdwell _ 0.\\n\\t\\tcurrentPoint = lastPoint\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[dwell _ dwell + 1.\\n\\t\\t\\t\\t((dwell \\\\\\\\ 1000) = 0) ifTrue:\\n\\t\\t\\t\\t\\t[Beeper beep]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self position: (currentPoint - offset).\\n\\t\\t\\t\\tself world displayWorld.\\n\\t\\t\\t\\t(Delay forMilliseconds: 20) wait.\\n\\t\\t\\t\\tpoints add: currentPoint.\\n\\t\\t\\t\\tlastPoint _ currentPoint]].\\n\\tpoints size > 1\\n\\t\\tifFalse:\\n\\t\\t\\t[self inform: 'no path obtained']\\n\\t\\tifTrue:\\n\\t\\t\\t[points size = 100 ifTrue: [self playSoundNamed: 'croak'].\\n\\n\\t\\t\\tTranscript cr; show: 'path defined with\\n', points size printString, ' points'.\\n\\t\\t\\tself renderedMorph setProperty: #pathPoints toValue: \\n\\t\\t\\t\\t(points collect: [:p | p - ownerPosition])].\\n\\n\\tCursor normal show\\n\\t\\t! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 1/5/1999 10:05'!\\ndeletePath\\n\\tself removeProperty: #pathPoints! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/26/1999 23:32'!\\nembeddedInMorphicWindowLabeled: labelString\\n\\t| window |\\n\\twindow _ (SystemWindow labelled: labelString) model: nil.\\n\\twindow setStripeColorsFrom: nil defaultBackgroundColor.\\n\\twindow addMorph: self frame: (0@0 extent: 1@1).\\n\\t^ window! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 5/25/2000 09:06'!\\nembedInWindow\\n\\n\\t| window worldToUse |\\n\\n\\tworldToUse _ self world.\\t\\t\\\"I'm assuming we are already in a world\\\"\\n\\twindow _ (SystemWindow labelled: self defaultLabelForInspector) model: nil.\\n\\twindow bounds: ((self position - ((0@window labelHeight) + window borderWidth))\\n\\t\\t\\t\\t\\t\\tcorner: self bottomRight + window borderWidth).\\n\\twindow addMorph: self frame: (0@0 extent: 1@1).\\n\\twindow updatePaneColors.\\n\\tworldToUse addMorph: window.\\n\\twindow activate! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 2/22/2003 14:31'!\\nenclosingEditor\\n\\t\\\"Return the next editor around the receiver\\\"\\n\\n\\t| tested |\\n\\ttested := owner.\\n\\t[tested isNil] whileFalse: \\n\\t\\t\\t[tested isTileEditor ifTrue: [^tested].\\n\\t\\t\\ttested := tested owner].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/15/1999 19:38'!\\nenforceTileColorPolicy\\n\\tPreferences coloredTilesEnabled\\n\\t\\tifTrue:\\n\\t\\t\\t[self makeAllTilesColored]\\n\\t\\tifFalse:\\n\\t\\t\\t[self makeAllTilesGreen]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 10/4/2000 08:29'!\\nfenceEnabled\\n\\n\\t\\\"in case a non-pasteUp is used as a container\\\"\\n\\n\\t^Preferences fenceEnabled! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nb 6/17/2003 12:25'!\\nfollowPath\\n\\t| pathPoints offset |\\n\\t(pathPoints _ self renderedMorph valueOfProperty: #pathPoints) ifNil: [^ Beeper beep].\\n\\toffset _ owner position - (self extent // 2).\\n\\tpathPoints do:\\n\\t\\t[:aPoint |\\n\\t\\t\\tself position: aPoint + offset.\\n\\t\\t\\tself world displayWorld.\\n\\t\\t\\t(Delay forMilliseconds: 20) wait]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/18/2003 02:54'!\\ngetCharacters\\n\\t\\\"obtain a string value from the receiver. The default generic response is simply the name of the object.\\\"\\n\\n\\t^ self externalName! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/1/2000 10:15'!\\ngetNumericValue\\n\\t\\\"Only certain kinds of morphs know how to deal with this frontally; here we provide support for a numeric property of any morph\\\"\\n\\n\\t^ self valueOfProperty: #numericValue ifAbsent: [0]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'kfr 9/4/2004 15:22'!\\ngridFormOrigin: origin grid: smallGrid background: backColor line: lineColor\\n\\n\\t| bigGrid gridForm gridOrigin |\\n\\tgridOrigin _ origin \\\\\\\\ smallGrid.\\n\\tbigGrid _ (smallGrid asPoint x) @ (smallGrid asPoint y).\\n\\tgridForm _ Form extent: bigGrid depth: Display depth.\\n\\tbackColor ifNotNil: [gridForm fillWithColor: backColor].\\n\\tgridOrigin x to: gridForm width by: smallGrid x do:\\n\\t\\t[:x | gridForm fill: (x@0 extent: 1@gridForm height) fillColor: lineColor].\\n\\tgridOrigin y to: gridForm height by: smallGrid y do:\\n\\t\\t[:y | gridForm fill: (0@y extent: gridForm width@1) fillColor: lineColor].\\n\\t^ InfiniteForm with: gridForm\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 4/12/2005 23:07'!\\nhandUserASibling\\n\\t\\\"Make and hand the user a sibling instance. Force the creation of a uniclass at this point if one does not already exist for the receiver.\\\"\\n\\n\\t| topRend |\\n\\ttopRend _ self topRendererOrSelf.\\n\\ttopRend couldMakeSibling ifFalse: [^ Beeper beep].\\n\\n\\ttopRend assuredPlayer assureUniClass.\\n\\t(topRend makeSiblings: 1) first openInHand! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/21/1998 15:54'!\\nisAViewer\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 6/30/1999 20:29'!\\nisCandidateForAutomaticViewing\\n\\t^ true! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 2/7/2001 17:58'!\\nisTileEditor\\n\\t\\\"No, I'm not\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/9/2000 16:48'!\\nlistViewLineForFieldList: aFieldList\\n\\t\\\"Answer a ListLineView object which describes the receiver\\\"\\n\\n\\t| aLine |\\n\\taLine _ ListViewLine new objectRepresented: self.\\n\\taFieldList do:\\n\\t\\t[:fieldSym | aLine addMorphBack: (self readoutForField: fieldSym).\\n\\t\\taLine addTransparentSpacerOfSize: (7 @ 0)].\\n\\t^ aLine! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 9/6/2003 18:10'!\\nmakeGraphPaper\\n\\t| smallGrid backColor lineColor |\\n\\tsmallGrid _ Compiler evaluate: (FillInTheBlank request: 'Enter grid size' translated initialAnswer: '16').\\n\\tsmallGrid ifNil: [^ self].\\n\\tUtilities informUser: 'Choose a background color' translated during: [backColor _ Color fromUser].\\n\\tUtilities informUser: 'Choose a line color' translated during: [lineColor _ Color fromUser].\\n\\tself makeGraphPaperGrid: smallGrid background: backColor line: lineColor.! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'di 9/7/2000 20:44'!\\nmakeGraphPaperGrid: smallGrid background: backColor line: lineColor\\n\\n\\t| gridForm |\\n\\tgridForm _ self gridFormOrigin: 0@0 grid: smallGrid asPoint background: backColor line: lineColor.\\n\\tself color: gridForm.\\n\\tself world ifNotNil: [self world fullRepaintNeeded].\\n\\tself changed: #newColor. \\\"propagate to view\\\"\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 4/16/1998 13:46'!\\nmustBeBackmost\\n\\t\\\"Answer whether the receiver needs to be the backmost morph in its owner's submorph list\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/13/2002 17:45'!\\nnoteDecimalPlaces: aNumber forGetter: aGetter\\n\\t\\\"Make a mental note of the user's preference for a particular number of decimal places to be associated with the slot with the given getter\\\"\\n\\n\\t(self renderedMorph valueOfProperty: #decimalPlacePreferences ifAbsentPut: [IdentityDictionary new])\\n\\t\\tat: aGetter put: aNumber! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/26/2000 11:37'!\\nnoteNegotiatedName: uniqueName for: requestedName\\n\\t\\\"This works, kind of, for morphs that have a single variable. Still holding out for generality of morphs being able to have multiple variables, but need a driving example\\\"\\n\\n\\tself setProperty: #variableName toValue: uniqueName.\\n\\tself setProperty: #setterSelector toValue: (Utilities setterSelectorFor: uniqueName).\\n\\tself setNameTo: uniqueName! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/9/2000 06:43'!\\nobjectViewed\\n\\t\\\"Answer the morph associated with the player that the structure the receiver currently finds itself within represents.\\\"\\n\\n\\t^ (self outermostMorphThat: [:o | o isKindOf: Viewer orOf: ScriptEditorMorph]) objectViewed! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/31/2004 14:11'!\\npinkXButton\\n\\t\\\"Answer a button with the old X on a pink background, targeted to self\\\"\\n\\n\\t| aButton |\\n\\taButton _ IconicButton new labelGraphic: (ScriptingSystem formAtKey: #PinkX).\\n\\taButton color: Color transparent; borderWidth: 0; shedSelvedge; actWhen: #buttonUp.\\n\\taButton target: self.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/11/2004 16:23'!\\nreferencePlayfield\\n\\t\\\"Answer the PasteUpMorph to be used for cartesian-coordinate reference\\\"\\n\\n\\t| former |\\n\\towner ifNotNil:\\n\\t\\t[(self topRendererOrSelf owner isHandMorph and: [(former _ self formerOwner) notNil])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[former _ former renderedMorph.\\n\\t\\t\\t\\t^ former isPlayfieldLike \\n\\t\\t\\t\\t\\tifTrue: [former]\\n\\t\\t\\t\\t\\tifFalse: [former referencePlayfield]]].\\n\\n\\tself allOwnersDo: [:o | o isPlayfieldLike ifTrue: [^ o]].\\n\\t^ ActiveWorld! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:40'!\\nrotationStyle\\n\\t\\\"Return the 'rotation style' of the receiver\\\"\\n\\t^#normal! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:40'!\\nrotationStyle: aSymbol\\n\\t\\\"Set the 'rotation style' of the receiver; this is ignored for non-sketches\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 3/9/2001 14:37'!\\nsetAsActionInButtonProperties: buttonProperties\\n\\n\\t^false\\t\\\"means I don't know how to be set as a button action\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/15/2000 06:26'!\\nsetNumericValue: aValue\\n\\t\\\"Set the receiver's contents to reflect the given numeric value. Only certain kinds of morphs know what to do with this, the rest, for now, stash the number in a property, where it may not be visible but at least it won't be lost, and can be retrieved by the companion getter. This code is never reached under normal circumstances, because the #numericValue slot is not shown in Viewers for most kinds of morphs, and those kinds of morphs that do show it also reimplement this method. However, this code *could* be reached via a user script which sends #setNumericValue: but whose receiver has been changed, via tile-scripting drag and drop for example, to one that doesn't directly handle numbers\\\"\\n\\n\\tScriptingSystem informScriptingUser: 'an unusual setNumericValue: call was made'.\\n\\tself renderedMorph setProperty: #numericValue toValue: aValue\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 7/21/1998 21:18'!\\nsetStandardTexture\\n\\t| parms |\\n\\tparms _ self textureParameters.\\n\\tself makeGraphPaperGrid: parms first\\n\\t\\tbackground: parms second\\n\\t\\tline: parms third! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/27/2000 17:46'!\\nslotSpecifications\\n\\t\\\"A once and possibly future feature; retained here for backward-compatibility bulletproofing.\\\"\\n\\n\\t^ #()! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/11/1998 16:55'!\\nsucceededInRevealing: aPlayer\\n\\taPlayer == self player ifTrue: [^ true].\\n\\tsubmorphs do:\\n\\t\\t[:m | (m succeededInRevealing: aPlayer) ifTrue: [^ true]].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/31/2004 14:06'!\\ntanOButton\\n\\t\\\"Answer a button with the old O on a tan background, targeted to self\\\"\\n\\n\\t| aButton |\\n\\taButton _ IconicButton new labelGraphic: (ScriptingSystem formAtKey: #TanO).\\n\\taButton color: Color transparent; borderWidth: 0; shedSelvedge; actWhen: #buttonUp.\\n\\taButton target: self.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 7/21/1998 21:17'!\\ntextureParameters\\n\\t\\\"Answer a triplet giving the preferred grid size, background color, and line color. The choices here are as suggested by Alan, 9/13/97\\\"\\n\\n\\t^ Array with: 16 with: Color lightYellow with: Color lightGreen lighter lighter! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 2/22/2003 14:35'!\\ntopEditor\\n\\t\\\"Return the top-most editor around the receiver\\\"\\n\\n\\t| found tested |\\n\\ttested := self.\\n\\t[tested isNil] whileFalse: \\n\\t\\t\\t[tested isTileEditor ifTrue: [found := tested].\\n\\t\\t\\ttested := tested owner].\\n\\t^found! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 10/8/2003 19:30'!\\nunlockOneSubpart\\n\\t| unlockables aMenu reply |\\n\\tunlockables _ self submorphs select:\\n\\t\\t[:m | m isLocked].\\n\\tunlockables size <= 1 ifTrue: [^ self unlockContents].\\n\\taMenu _ SelectionMenu labelList: (unlockables collect: [:m | m externalName]) selections: unlockables.\\n\\treply _ aMenu startUpWithCaption: 'Who should be be unlocked?' translated.\\n\\treply isNil ifTrue: [^ self].\\n\\treply unlock! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'tk 10/19/1999 07:16'!\\nupdateCachedThumbnail\\n\\t\\\"If I have a cached thumbnail, then update it. Copied up from Dan's original version in PasteUpMorph so it can be used by all morphs.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail computeThumbnail]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\\"Test and removal are because the thumbnail is being replaced by another Morph. We don't know why. Need to fix that at the source.\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 11/27/2001 14:52'!\\nwantsRecolorHandle\\n\\t\\\"Answer whether the receiver would like a recoloring halo handle to be put up. Since this handle also presently affords access to the property-sheet, it is presently always allowed, even though SketchMorphs don't like regular recoloring\\\"\\n\\n\\t^ true\\n\\t\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 2/5/2001 15:35'!\\nwrappedInWindowWithTitle: aTitle\\n\\t| aWindow w2 |\\n\\taWindow _ (SystemWindow labelled: aTitle) model: Model new.\\n\\taWindow addMorph: self frame: (0@0 extent: 1@1).\\n\\tw2 _ aWindow borderWidth * 2.\\n\\tw2 _ 3.\\t\\t\\\"oh, well\\\"\\n\\taWindow extent: self fullBounds extent + (0 @ aWindow labelHeight) + (w2 @ w2).\\n\\t^ aWindow! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'tk 9/3/1999 11:46'!\\nwrappedInWindow: aSystemWindow\\n\\t| aWindow |\\n\\taWindow _ aSystemWindow model: Model new.\\n\\taWindow addMorph: self frame: (0@0 extent: 1@1).\\n\\taWindow extent: self extent.\\n\\t^ aWindow! !\\n\\n\\n!Morph methodsFor: 'messenger' stamp: 'sw 11/3/2001 12:23'!\\naffiliatedSelector\\n\\t\\\"Answer a selector affiliated with the receiver for the purposes of launching a messenger. Reimplement this to plug into the messenger service\\\"\\n\\n\\t^ nil! !\\n\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 09:58'!\\nallowsGestureStart: evt\\n\\t^false! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/11/2004 17:45'!\\nisGestureStart: anEvent\\n\\t\\\"This mouse down could be the start of a gesture, or the end of a gesture focus\\\"\\n\\n\\tanEvent hand isGenieEnabled\\n\\t\\tifFalse: [ ^false ].\\n\\n\\t(self allowsGestureStart: anEvent)\\n\\t\\tifTrue: [^ true ].\\t\\t\\\"could be the start of a gesture\\\"\\n\\n\\t\\\"otherwise, check for whether it's time to disable the Genie auto-focus\\\"\\n\\t(anEvent hand isGenieFocused\\n\\t\\tand: [anEvent whichButton ~= anEvent hand focusStartEvent whichButton])\\n\\t\\t\\tifTrue: [anEvent hand disableGenieFocus].\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/11/2004 17:30'!\\nmouseStillDownStepRate\\n\\t\\\"At what rate do I want to receive #mouseStillDown: notifications?\\\"\\n\\t^1! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 06:38'!\\nredButtonGestureDictionaryOrName: aSymbolOrDictionary! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 06:38'!\\nyellowButtonGestureDictionaryOrName: aSymbolOrDictionary! !\\n\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'di 9/22/1999 08:45'!\\nasEPS\\n\\n\\t^ EPSCanvas morphAsPostscript: self rotated: false.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases'!\\nasPostscript\\n\\t^self asEPS.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'di 9/22/1999 08:45'!\\nasPostscriptPrintJob\\n\\n\\t^ DSCPostscriptCanvas morphAsPostscript: self rotated: false.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'ar 1/16/2001 17:06'!\\nclipPostscript\\n\\t^Clipboard clipboardText: self asPostscript.\\n\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'mpw 8/10/1930 05:21'!\\ndrawPostscriptOn: aCanvas\\n\\n\\tself drawOn:aCanvas.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'mpw 8/10/1930 05:25'!\\nfullDrawPostscriptOn: aCanvas\\n\\n\\tself fullDrawOn:aCanvas.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'nk 12/29/2003 10:55'!\\nprintPSToFile\\n\\t\\n\\tself printPSToFileNamed: self externalName! !\\n\\n\\n!Morph methodsFor: 'player' stamp: 'tk 10/30/2001 12:13'!\\nassuredCardPlayer\\n\\t\\\"Answer the receiver's player, creating a new one if none currently exists\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self player) ifNotNil: [\\n\\t\\t(aPlayer isKindOf: CardPlayer) \\n\\t\\t\\t\\tifTrue: [^ aPlayer]\\n\\t\\t\\t\\tifFalse: [self error: 'Must convert to a CardPlayer']\\n\\t\\t\\t\\t\\t\\\"later convert using as: and remove the error\\\"].\\n\\tself assureExternalName. \\\"a default may be given if not named yet\\\"\\n\\tself player: (aPlayer _ UnscriptedCardPlayer newUserInstance).\\n\\t\\t\\\"Force it to be a CardPlayer. Morph class no longer dictates what kind of player\\\"\\n\\taPlayer costume: self.\\n\\tself presenter ifNotNil: [self presenter flushPlayerListCache].\\n\\t^ aPlayer! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 2/19/1999 09:06'!\\nassuredPlayer\\n\\t\\\"Answer the receiver's player, creating a new one if none currently exists\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self player) ifNil:\\n\\t\\t[self assureExternalName. \\\"a default may be given if not named yet\\\"\\n\\t\\tself player: (aPlayer _ self newPlayerInstance). \\n\\t\\t\\t\\\"Different morphs may demand different player types\\\"\\n\\t\\taPlayer costume: self.\\n\\t\\tself presenter ifNotNil: [self presenter flushPlayerListCache]].\\n\\t^ aPlayer! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 8/10/2000 00:06'!\\nassureExternalName\\n\\t| aName |\\n\\t^ (aName _ self knownName) ifNil:\\n\\t\\t[self setNameTo: (aName _ self externalName).\\n\\t\\t^ aName]! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 10/27/2000 17:38'!\\ncurrentDataValue\\n\\t\\\"Answer the data value associated with the receiver. Useful in conjunction with default-value setting\\\"\\n\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 9/15/1998 13:33'!\\nnewPlayerInstance\\n\\t^ UnscriptedPlayer newUserInstance! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 1/22/2001 14:25'!\\nokayToDuplicate\\n\\t\\\"Formerly this protocol was used to guard against awkward situations when there were anonymous scripts in the etoy system. Nowadays we just always allow duplication\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'player' stamp: 'mir 6/13/2001 14:45'!\\nshouldRememberCostumes\\n\\t^true! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 8/11/1998 16:54'!\\nshowPlayerMenu\\n\\tself player ifNotNil:\\n\\t\\t[self player showPlayerMenu]! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 10/6/2000 07:37'!\\nvariableDocks\\n\\t\\\"Answer a list of VariableDocker objects for docking up my data with an instance held in my containing playfield. The simple presence of some objects on a Playfield will result in the maintenance of instance data on the corresponding Card. This is a generalization of the HyperCard 'field' idea. If there is already a cachedVariableDocks cached, use that. For this all to work happily, one must be certain to invalidate the #cachedVariableDocks cache when that's appropriate.\\\"\\n\\n\\t^ self valueOfProperty: #cachedVariableDocks ifAbsent: [#()]! !\\n\\n\\n!Morph methodsFor: 'player commands' stamp: 'nb 6/17/2003 12:25'!\\nbeep: soundName\\n\\n\\tself playSoundNamed: soundName\\n! !\\n\\n!Morph methodsFor: 'player commands'!\\njumpTo: aPoint\\n\\t\\\"Let my owner decide how I move.\\\"\\n\\n\\towner move: self toPosition: aPoint.\\n! !\\n\\n!Morph methodsFor: 'player commands' stamp: 'sw 2/16/1999 11:33'!\\nmakeFenceSound\\n\\tPreferences soundsEnabled ifTrue:\\n\\t\\t[self playSoundNamed: 'scratch'].\\n! !\\n\\n!Morph methodsFor: 'player commands' stamp: 'gk 2/23/2004 21:08'!\\nplaySoundNamed: soundName\\n\\t\\\"Play the sound with the given name.\\n\\tDoes nothing if this image lacks sound playing facilities.\\\"\\n\\n\\tSoundService default playSoundNamed: soundName asString! !\\n\\n!Morph methodsFor: 'player commands'!\\nset: aPointOrNumber\\n\\t\\\"Set my position.\\\"\\n\\n\\tself jumpTo: aPointOrNumber.\\n! !\\n\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 14:45'!\\nbuttonProperties\\n\\n\\t^self valueOfProperty: #universalButtonProperties! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 14:45'!\\nbuttonProperties: propertiesOrNil\\n\\n\\tpropertiesOrNil ifNil: [\\n\\t\\tself removeProperty: #universalButtonProperties\\n\\t] ifNotNil: [\\n\\t\\tself setProperty: #universalButtonProperties toValue: propertiesOrNil\\n\\t].! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 07:49'!\\nensuredButtonProperties\\n\\n\\tself hasButtonProperties ifFalse: [\\n\\t\\tself buttonProperties: (ButtonProperties new visibleMorph: self)\\n\\t].\\n\\t^self buttonProperties! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 07:18'!\\nhasButtonProperties\\n\\n\\t^self hasProperty: #universalButtonProperties! !\\n\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 17:12'!\\ncategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the \\n\\tviewer, in order\\\"\\n\\t| dict aList |\\n\\tdict := Dictionary new.\\n\\tself unfilteredCategoriesForViewer\\n\\t\\twithIndexDo: [:cat :index | dict at: cat put: index].\\n\\tself filterViewerCategoryDictionary: dict.\\n\\taList := SortedCollection\\n\\t\\t\\t\\tsortBlock: [:a :b | (dict at: a)\\n\\t\\t\\t\\t\\t\\t< (dict at: b)].\\n\\taList addAll: dict keys.\\n\\t^ aList asArray! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 17:09'!\\nselectorsForViewer\\n\\t\\\"Answer a list of symbols representing all the selectors available in all my viewer categories\\\"\\n\\n\\t| aClass aList itsAdditions added addBlock |\\n\\taClass := self renderedMorph class.\\n\\taList := OrderedCollection new.\\n\\tadded := Set new.\\n\\taddBlock := [ :sym | (added includes: sym) ifFalse: [ added add: sym. aList add: sym ]].\\n\\n\\t[aClass == Morph superclass] whileFalse: \\n\\t\\t\\t[(aClass hasAdditionsToViewerCategories) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[itsAdditions := aClass allAdditionsToViewerCategories.\\n\\t\\t\\t\\t\\titsAdditions do: [ :add | add do: [:aSpec |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"the spec list\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #command ifTrue: [ addBlock value: aSpec second].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #slot \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[ addBlock value: (aSpec seventh).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t addBlock value: aSpec ninth]]]].\\n\\t\\t\\taClass := aClass superclass].\\n\\n\\t^aList copyWithoutAll: #(#unused #dummy)\\n\\n\\t\\\"SimpleSliderMorph basicNew selectorsForViewer\\\"! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 17:14'!\\nselectorsForViewerIn: aCollection\\n\\t\\\"Answer a list of symbols representing all the selectors available in all my viewer categories, selecting only the ones in aCollection\\\"\\n\\n\\t| aClass aList itsAdditions added addBlock |\\n\\taClass := self renderedMorph class.\\n\\taList := OrderedCollection new.\\n\\tadded := Set new.\\n\\taddBlock := [ :sym |\\n\\t\\t(added includes: sym) ifFalse: [ (aCollection includes: sym)\\n\\t\\t\\tifTrue: [ added add: sym. aList add: sym ]]].\\n\\n\\t[aClass == Morph superclass] whileFalse: \\n\\t\\t\\t[(aClass hasAdditionsToViewerCategories) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[itsAdditions := aClass allAdditionsToViewerCategories.\\n\\t\\t\\t\\t\\titsAdditions do: [ :add | add do: [:aSpec |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"the spec list\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #command ifTrue: [ addBlock value: aSpec second].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #slot \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[ addBlock value: (aSpec seventh).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t addBlock value: aSpec ninth]]]].\\n\\t\\t\\taClass := aClass superclass].\\n\\n\\t^aList copyWithoutAll: #(#unused #dummy)\\n\\n\\t\\\"SimpleSliderMorph basicNew selectorsForViewerIn: \\n\\t#(setTruncate: getColor setColor: getKnobColor setKnobColor: getWidth setWidth: getHeight setHeight: getDropEnabled setDropEnabled:)\\n\\t\\\"! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 9/4/2004 11:47'!\\nunderstandsBorderVocabulary\\n\\t\\\"Replace the 'isKindOf: BorderedMorph' so that (for instance) Connectors can have their border vocabulary visible in viewers.\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'object fileIn' stamp: 'dgd 2/22/2003 14:30'!\\nconvertAugust1998: varDict using: smartRefStrm \\n\\t\\\"These variables are automatically stored into the new instance \\n\\t('bounds' 'owner' 'submorphs' 'fullBounds' 'color' ). \\n\\tThis method is for additional changes. Use statements like (foo _ \\n\\tvarDict at: 'foo').\\\"\\n\\n\\t\\\"Be sure to to fill in ('extension' ) and deal with the information \\n\\tin ('eventHandler' 'properties' 'costumee' )\\\"\\n\\n\\t\\\"This method moves all property variables as well as \\n\\teventHandler, and costumee into a morphicExtension.\\\"\\n\\n\\t\\\"Move refs to eventhandler and costumee into extension\\\"\\n\\n\\t| propVal |\\n\\t(varDict at: 'eventHandler') isNil \\n\\t\\tifFalse: [self eventHandler: (varDict at: 'eventHandler')].\\n\\t(varDict at: 'costumee') isNil \\n\\t\\tifFalse: [self player: (varDict at: 'costumee')].\\n\\t(varDict at: 'properties') isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[(varDict at: 'properties') keys do: \\n\\t\\t\\t\\t\\t[:key | \\n\\t\\t\\t\\t\\t\\\"Move property extensions into extension\\\"\\n\\n\\t\\t\\t\\t\\tpropVal := (varDict at: 'properties') at: key.\\n\\t\\t\\t\\t\\tpropVal ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[key == #possessive \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [propVal == true ifTrue: [self bePossessive]]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[key ifNotNil: [self assureExtension convertProperty: key toValue: propVal]]]]]! !\\n\\n!Morph methodsFor: 'object fileIn' stamp: 'md 2/27/2006 09:56'!\\nconvertNovember2000DropShadow: varDict using: smartRefStrm \\n\\t\\\"Work hard to eliminate the DropShadow. Inst vars are already \\n\\tstored into.\\\"\\n\\n\\t| rend |\\n\\tsubmorphs notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[rend := submorphs first renderedMorph.\\n\\t\\t\\t\\\"a text?\\\"\\n\\t\\t\\trend setProperty: #hasDropShadow toValue: true.\\n\\t\\t\\trend setProperty: #shadowColor toValue: (varDict at: 'color').\\n\\t\\t\\trend setProperty: #shadowOffset toValue: (varDict at: 'shadowOffset').\\n\\t\\t\\t\\\"ds owner ifNotNil: [ds owner addAllMorphs: ds \\n\\t\\t\\tsubmorphs]. ^rend does this\\\"\\n\\t\\t\\trend privateOwner: owner.\\n\\t\\t\\textension ifNotNil: [\\n\\t\\t\\t\\textension actorState ifNotNil: [rend actorState: self extension actorState].\\n\\t\\t\\t\\textension externalName ifNotNil: [rend setNameTo: self extension externalName].\\n\\t\\t\\t\\textension player ifNotNil: [\\n\\t\\t\\t\\t\\t\\t\\trend player: extension player.\\n\\t\\t\\t\\t\\t\\t\\textension player rawCostume: rend]].\\n\\t\\t\\t^rend].\\n\\t(rend := Morph new) color: Color transparent.\\n\\t^rend! !\\n\\n\\n!Morph methodsFor: 'system primitives' stamp: 'sw 10/27/2000 17:37'!\\ncreationStamp\\n\\t\\\"Answer the creation stamp stored within the receiver, if any\\\"\\n\\n\\t^ self valueOfProperty: #creationStamp ifAbsent: [super creationStamp]! !\\n\\n\\n!Morph methodsFor: 'button' stamp: 'sw 2/6/2001 23:09'!\\ndoButtonAction\\n\\t\\\"If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism. Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts\\\"! !\\n\\n!Morph methodsFor: 'button' stamp: 'sw 2/6/2001 23:22'!\\nfire\\n\\t\\\"If the receiver has any kind of button-action defined, fire that action now. Any morph can have special, personal mouseUpCodeToRun, and that will be triggered by this. Additionally, some morphs have specific buttonness, and these get sent the #doButtonAction message to carry out their firing. Finally, some morphs have mouse behaviors associated with one or more Player scripts.\\n\\tFor the present, we'll try out doing *all* the firings this object can do. \\\"\\n\\n\\tself firedMouseUpCode. \\t\\\"This will run the mouseUpCodeToRun, if any\\\"\\n\\n\\tself player ifNotNil:\\t\\t\\n\\t\\t[self player fireOnce]. \\\"Run mouseDown and mouseUp scripts\\\"\\n\\n\\tself doButtonAction\\t\\t\\t\\\"Do my native button action, if any\\\"! !\\n\\n!Morph methodsFor: 'button' stamp: 'dgd 2/22/2003 14:31'!\\nfiredMouseUpCode\\n\\t\\\"If the user has special mouseUpCodeToRun, then fire it once right now and return true, else return false\\\"\\n\\n\\t| evt |\\n\\t(self world isNil or: [self mouseUpCodeOrNil isNil]) ifTrue: [^false].\\n\\tevt := MouseEvent new \\n\\t\\t\\t\\tsetType: nil\\n\\t\\t\\t\\tposition: self center\\n\\t\\t\\t\\tbuttons: 0\\n\\t\\t\\t\\thand: self world activeHand.\\n\\tself programmedMouseUp: evt for: self.\\n\\t^true! !\\n\\n\\n!Morph methodsFor: 'event handling-override' stamp: 'nk 3/10/2004 19:47'!\\nhandlerForMouseDown: anEvent \\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily \\n\\tinstalled and can be used for morphs further down the hierarchy to negotiate whether \\n\\tthe inner or the outer morph should finally handle the event.\\\"\\n\\n\\tanEvent blueButtonPressed\\n\\t\\tifTrue: [^ self handlerForBlueButtonDown: anEvent].\\n\\tanEvent yellowButtonPressed\\n\\t\\tifTrue: [^ self handlerForYellowButtonDown: anEvent].\\n\\tanEvent controlKeyPressed\\n\\t\\tifTrue: [^ self handlerForMetaMenu: anEvent].\\n\\t(self handlesMouseDown: anEvent)\\n\\t\\tifFalse: [^ nil].\\t\\\"not interested\\\"\\n\\n\\tanEvent handler\\n\\t\\tifNil: [^ self ].\\t\\\"Same priority but I am innermost\\\"\\n\\n\\t\\\"Nobody else was interested\\\"\\n\\t^self mouseDownPriority >= anEvent handler mouseDownPriority\\n\\t\\tifTrue: [ self]\\n\\t\\tifFalse: [ nil]! !\\n\\n\\n!Morph methodsFor: 'texture support' stamp: 'dgd 2/16/2003 20:02'!\\nisValidWonderlandTexture\\n\\t\\\"Return true if the receiver is a valid wonderland texture\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #isValidWonderlandTexture\\n\\t\\tifAbsent: [true]! !\\n\\n\\n!Morph methodsFor: 'model access' stamp: 'nk 3/10/2004 19:51'!\\nmodels\\n\\t\\\"Answer a collection of whatever models I may have.\\\"\\n\\n\\tself modelOrNil ifNil: [ ^EmptyArray ].\\n\\t^Array with: self modelOrNil! !\\n\\n\\n!Morph methodsFor: 'player viewer' stamp: 'wiz 1/1/2006 12:58'!\\nopenViewerForArgument\\n\\t\\\"Open up a viewer for a player associated with the morph in question. \\\"\\n\\tself presenter viewMorph: self! !\\n\\n!Morph methodsFor: 'player viewer' stamp: 'sw 3/13/98 17:40'!\\nupdateLiteralLabel\\n\\t\\\"Backstop -- updatingStringMorphs inform their owners with this message when they've changed; some Morphs care, others don't\\\"! !\\n\\n\\n!Morph methodsFor: 'other' stamp: 'sw 10/30/2001 13:12'!\\nremoveAllButFirstSubmorph\\n\\t\\\"Remove all of the receiver's submorphs other than the first one.\\\"\\n\\n\\tself submorphs allButFirst do: [:m | m delete]! !\\n\\n\\n!Morph methodsFor: 'selected object' stamp: 'dgd 8/28/2004 16:30'!\\nselectedObject\\n\\t\\\"answer the selected object for the hand or nil is none\\\"\\n\\t^ self primaryHand selectedObject! !\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!Morph class methodsFor: 'class initialization' stamp: 'hg 8/3/2000 16:43'!\\ninitialize\\n\\t\\\"Morph initialize\\\"\\n\\n\\t\\\"this empty array object is shared by all morphs with no submorphs:\\\"\\n\\tEmptyArray _ Array new.\\n\\tFileList registerFileReader: self! !\\n\\n\\n!Morph class methodsFor: 'connectors-scripting' stamp: 'nk 9/10/2004 11:34'!\\nadditionsToViewerCategoryConnection\\n\\t\\\"Answer viewer additions for the 'connection' category\\\"\\n\\t\\\"Vocabulary initialize\\\"\\n\\n\\t^{\\n\\t\\t#'connections to me'.\\n\\t\\t#(\\n\\t\\t(command tellAllPredecessors: 'Send a message to all graph predecessors' ScriptName)\\n\\t\\t(command tellAllSuccessors: 'Send a message to all graph predecessors' ScriptName)\\n\\t\\t(command tellAllIncomingConnections: 'Send a message to all the connectors whose destination end is connected to me' ScriptName)\\n\\t\\t(command tellAllOutgoingConnections: 'Send a message to all the connectors whose source end is connected to me' ScriptName)\\n\\t\\t(slot incomingConnectionCount 'The number of connectors whose destination end is connected to me' Number readOnly Player getIncomingConnectionCount unused unused)\\n\\t\\t(slot outgoingConnectionCount 'The number of connectors whose source end is connected to me' Number readOnly Player getOutgoingConnectionCount unused unused)\\n\\t\\t)\\n\\t}\\n! !\\n\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'nk 7/16/2003 15:54'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\n\\t^({ 'morph'. 'morphs'. 'sp'. '*' } includes: suffix)\\n\\t\\tifTrue: [\\n\\t\\t\\t{SimpleServiceEntry \\n\\t\\t\\t\\tprovider: self \\n\\t\\t\\t\\tlabel: 'load as morph'\\n\\t\\t\\t\\tselector: #fromFileName:\\n\\t\\t\\t\\tdescription: 'load as morph'}]\\n\\t\\tifFalse: [#()]! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'yo 8/7/2003 11:02'!\\nfromFileName: fullName\\n\\t\\\"Reconstitute a Morph from the file, presumed to be represent a Morph saved\\n\\tvia the SmartRefStream mechanism, and open it in an appropriate Morphic world\\\"\\n\\n \\t| aFileStream morphOrList |\\n\\taFileStream _ (MultiByteBinaryOrTextStream with: ((FileStream readOnlyFileNamed: fullName) binary contentsOfEntireFile)) binary reset.\\n\\tmorphOrList _ aFileStream fileInObjectAndCode.\\n\\t(morphOrList isKindOf: SqueakPage) ifTrue: [morphOrList _ morphOrList contentsMorph].\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue: [ActiveWorld addMorphsAndModel: morphOrList]\\n\\t\\tifFalse:\\n\\t\\t\\t[morphOrList isMorph ifFalse: [self inform: 'Can only load a single morph\\ninto an mvc project via this mechanism.'].\\n\\t\\t\\tmorphOrList openInWorld]! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 02:43'!\\nserviceLoadMorphFromFile\\n\\t\\\"Answer a service for loading a .morph file\\\"\\n\\n\\t^ SimpleServiceEntry \\n\\t\\tprovider: self \\n\\t\\tlabel: 'load as morph'\\n\\t\\tselector: #fromFileName:\\n\\t\\tdescription: 'load as morph'\\n\\t\\tbuttonLabel: 'load'! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'sd 2/1/2002 21:45'!\\nservices\\n\\n\\t^ Array with: self serviceLoadMorphFromFile! !\\n\\n\\n!Morph class methodsFor: 'initialize-release' stamp: 'SD 11/15/2001 22:22'!\\nunload\\n\\n\\tFileList unregisterFileReader: self ! !\\n\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'efo 5/3/2002 14:59'!\\ninitializedInstance\\n\\t\\\"Answer an instance of the receiver which in some sense is initialized. In the case of Morphs, this will yield an instance that can be attached to the Hand after having received the same kind of basic initialization that would be obtained from an instance chosen from the 'new morph' menu.\\n\\tReturn nil if the receiver is reluctant for some reason to return such a thing\\\"\\n\\n\\t^ (self class includesSelector: #descriptionForPartsBin)\\n\\t\\tifTrue:\\n\\t\\t\\t[self newStandAlone]\\n\\t\\tifFalse:\\n\\t\\t\\t[self new]! !\\n\\n!Morph class methodsFor: 'instance creation'!\\nnewBounds: bounds\\n\\n\\t^ self new privateBounds: bounds! !\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'jm 5/29/1998 21:28'!\\nnewBounds: bounds color: color\\n\\n\\t^ (self new privateBounds: bounds) privateColor: color\\n! !\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'sw 8/4/97 12:05'!\\nnewSticky\\n\\n\\t^ self new beSticky! !\\n\\n\\n!Morph class methodsFor: 'misc' stamp: 'sw 8/4/1998 16:51'!\\nmorphsUnknownToTheirOwners\\n\\t\\\"Return a list of all morphs (other than HandMorphs) whose owners do not contain them in their submorph lists\\\"\\n\\t\\\"Morph morphsUnknownToTheirOwners\\\"\\n\\t| problemMorphs itsOwner |\\n\\tproblemMorphs _ OrderedCollection new.\\n\\tself allSubInstances do:\\n\\t\\t[:m | (m isHandMorph not and: [((itsOwner _ m owner) ~~ nil and: [(itsOwner submorphs includes: m) not])])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[problemMorphs add: m]].\\n\\t^ problemMorphs! !\\n\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'di 6/22/97 09:07'!\\nincludeInNewMorphMenu\\n\\t\\\"Return true for all classes that can be instantiated from the menu\\\"\\n\\t^ true! !\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'sw 6/28/2001 11:33'!\\nnewStandAlone\\n\\t\\\"Answer an instance capable of standing by itself as a usable morph.\\\"\\n\\n\\t^ self basicNew initializeToStandAlone! !\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'sw 8/2/2001 12:01'!\\npartName: aName categories: aList documentation: aDoc\\n\\t\\\"Answer a DescriptionForPartsBin which will represent a launch of a new instance of my class via the #newStandAlone protocol sent to my class. Use the category-list and documentation provided\\\"\\n\\n\\n\\t^ DescriptionForPartsBin new\\n\\t\\tformalName: aName\\n\\t\\tcategoryList: aList\\n\\t\\tdocumentation: aDoc\\n\\t\\tglobalReceiverSymbol: self name\\n\\t\\tnativitySelector: #newStandAlone! !\\n\\n\\n!Morph class methodsFor: 'scripting' stamp: 'sw 7/20/2005 01:20'!\\nadditionsToViewerCategoryColorAndBorder\\n\\t\\\"Answer viewer additions for the 'color & border' category\\\"\\n\\n\\t^#(\\n\\t\\t#'color & border' \\n\\t\\t(\\n\\t\\t\\t(slot color 'The color of the object' Color readWrite Player getColor Player setColor:)\\n\\t\\t\\t(slot opacity '0 means completely transparent, 1 means completely opaque' Number readWrite Player getAlpha Player setAlpha:)\\n\\t\\t\\t(slot borderStyle 'The style of the object''s border' BorderStyle readWrite Player getBorderStyle player setBorderStyle:)\\n\\t\\t\\t(slot borderColor 'The color of the object''s border' Color readWrite Player getBorderColor Player setBorderColor:)\\n\\t\\t\\t(slot borderWidth 'The width of the object''s border' Number readWrite Player getBorderWidth Player setBorderWidth:)\\n\\t\\t\\t(slot roundedCorners 'Whether corners should be rounded' Boolean readWrite Player getRoundedCorners Player setRoundedCorners:)\\n\\n\\t\\t\\t(slot gradientFill 'Whether a gradient fill should be used' Boolean readWrite Player getUseGradientFill Player setUseGradientFill:)\\n\\t\\t\\t(slot secondColor 'The second color used when gradientFill is in effect' Color readWrite Player getSecondColor Player setSecondColor:)\\n\\n\\t\\t\\t(slot radialFill 'Whether the gradient fill, if used, should be radial' Boolean readWrite Player getRadialGradientFill Player setRadialGradientFill:)\\n\\n\\t\\t\\t(slot dropShadow 'Whether a drop shadow is shown' Boolean readWrite Player getDropShadow Player setDropShadow:)\\n\\t\\t\\t(slot shadowColor 'The color of the drop shadow' Color readWrite Player getShadowColor Player setShadowColor:)\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'sw 8/11/97 13:17'!\\nauthoringPrototype\\n\\t\\\"Answer an instance of the receiver suitable for placing in a parts bin for authors\\\"\\n\\t\\n\\t^ self new markAsPartsDonor! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'bf 9/11/2004 17:18'!\\nhasAdditionsToViewerCategories\\n\\t^ self class selectors\\n\\t\\tanySatisfy: [:each | each == #additionsToViewerCategories\\n\\t\\t\\t\\tor: [(each beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\t\\tand: [(each at: 26 ifAbsent: []) ~= $:]]]! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'yo 3/15/2005 14:10'!\\nhelpContributions\\n\\t\\\"Answer a list of pairs of the form (<symbol> <help message> ) to contribute to the system help dictionary\\\"\\n\\t\\n\\\"NB: Many of the items here are not needed any more since they're specified as part of command definitions now. Someone needs to take the time to go through the list and remove items no longer needed. But who's got that kind of time?\\\"\\n\\n\\t^ #(\\n\\t\\t(acceptScript:for:\\n\\t\\t\\t'submit the contents of the given script editor as the code defining the given selector')\\n\\t\\t(actorState\\n\\t\\t\\t'return the ActorState object for the receiver, creating it if necessary')\\n\\t\\t(addInstanceVariable\\n\\t\\t\\t'start the interaction for adding a new variable to the object')\\n\\t\\t(addPlayerMenuItemsTo:hand:\\n\\t\\t\\t'add player-specific menu items to the given menu, on behalf of the given hand. At present, these are only commands relating to the turtle')\\n\\t\\t(addYesNoToHand\\n\\t\\t\\t'Press here to tear off a TEST/YES/NO unit which you can drop into your script')\\n\\t\\t(allScriptEditors\\n\\t\\t\\t'answer a list off the extant ScriptEditors for the receiver')\\n\\t\\t(amount\\n\\t\\t\\t'The amount of displacement')\\n\\t\\t(angle\\t\\n\\t\\t\\t'The angular displacement')\\n\\t\\t(anonymousScriptEditorFor:\\n\\t\\t\\t'answer a new ScriptEditor object to serve as the place for scripting an anonymous (unnamed, unsaved) script for the receiver')\\n\\t\\t(append:\\n\\t\\t\\t'add an object to this container')\\n\\t\\t(prepend:\\n\\t\\t\\t'add an object to this container')\\n\\t\\t(assignDecrGetter:setter:amt:\\n\\t\\t\\t'evaluate the decrement variant of assignment')\\n\\t\\t(assignGetter:setter:amt:\\n\\t\\t\\t'evaluate the vanilla variant of assignment')\\n\\t\\t(assignIncrGetter:setter:amt:\\n\\t\\t\\t'evalute the increment version of assignment')\\n\\t\\t(assignMultGetter:setter:amt:\\n\\t\\t\\t'evaluate the multiplicative version of assignment')\\n\\t\\t(assureEventHandlerRepresentsStatus\\n\\t\\t\\t'make certain that the event handler associated with my current costume is set up to conform to my current script-status')\\n\\t\\t(assureExternalName\\n\\t\\t\\t'If I do not currently have an external name assigned, get one now')\\n\\t\\t(assureUniClass\\n\\t\\t\\t'make certain that I am a member a uniclass (i.e. a unique subclass); if I am not, create one now and become me into an instance of it')\\n\\t\\t(availableCostumeNames\\n\\t\\t\\t'answer a list of strings representing the names of all costumes currently available for me')\\n\\t\\t(availableCostumesForArrows\\n\\t\\t\\t'answer a list of actual, instantiated costumes for me, which can be cycled through as the user hits a next-costume or previous-costume button in a viewer')\\n\\t\\t(beep:\\n\\t\\t\\t'make the specified sound')\\n\\t\\t(borderColor\\n\\t\\t\\t'The color of the object''s border')\\n\\t\\t(borderWidth\\n\\t\\t\\t'The width of the object''s border')\\n\\t\\t(bottom\\n\\t\\t\\t'My bottom edge, measured downward from the top edge of the world')\\n\\t\\t(bounce:\\n\\t\\t\\t'If object strayed beyond the boundaries of its container, make it reflect back into it, making the specified noise while doing so.')\\n\\t\\t(bounce\\n\\t\\t\\t'If object strayed beyond the boundaries of its container, make it reflect back into it')\\n\\t\\t(chooseTrigger\\n'When this script should run.\\n\\\"normal\\\" means \\\"only when called\\\"')\\n\\t\\t(clearTurtleTrails\\n\\t\\t\\t'Clear all the pen trails in the interior.')\\n\\t\\t(clearOwnersPenTrails\\n\\t\\t\\t'Clear all the pen trails in my container.')\\n\\t\\t(color\\t\\n\\t\\t\\t'The object''s interior color')\\n\\t\\t(colorSees\\n\\t\\t\\t'Whether a given color in the object is over another given color')\\n\\t\\t(colorUnder\\n\\t\\t\\t'The color under the center of the object')\\n\\t\\t(copy\\n\\t\\t\\t'Return a new object that is very much like this one')\\n\\t\\t(cursor\\t\\n\\t\\t\\t'The index of the chosen element')\\n\\t\\t(deleteCard\\n\\t\\t\\t'Delete the current card.')\\n\\t\\t(dismiss\\n\\t\\t\\t'Click here to dismiss me')\\n\\t\\t(doMenuItem:\\n\\t\\t\\t'Do a menu item, the same way as if it were chosen manually')\\n\\t\\t(doScript:\\n\\t\\t\\t'Perform the given script once, on the next tick.')\\n\\t\\t(elementNumber\\n\\t\\t\\t'My element number as seen by my owner')\\n\\t\\t(fire\\n\\t\\t\\t'Run any and all button-firing scripts of this object')\\n\\t\\t(firstPage\\n\\t\\t\\t'Go to first page of book')\\n\\t\\t(followPath\\n\\t\\t\\t\\t'Retrace the path the object has memorized, if any.')\\n\\t\\t(forward:\\n\\t\\t\\t'Moves the object forward in the direction it is heading') \\n\\t\\t(goto:\\n\\t\\t\\t'Go to the specfied book page')\\n\\t\\t(goToNextCardInStack\\n\\t\\t\\t'Go to the next card')\\n\\t\\t(goToPreviousCardInStack\\n\\t\\t\\t'Go to the previous card.')\\n\\t\\t(goToRightOf:\\n\\t\\t\\t'Align the object just to the right of any specified object.')\\n\\t\\t(heading\\n\\t\\t\\t'Which direction the object is facing. 0 is straight up') \\n\\t\\t(height\\t\\n\\t\\t\\t'The distance between the top and bottom edges of the object')\\n\\t\\t(hide\\n\\t\\t\\t'Make the object so that it does not display and cannot handle input')\\n\\t\\t(initiatePainting\\t\\n\\t\\t\\t'Initiate painting of a new object in the standard playfield.')\\n\\t\\t(initiatePaintingIn:\\n\\t\\t\\t'Initiate painting of a new object in the given place.')\\n\\t\\t(isOverColor\\n\\t\\t\\t'Whether any part of this object is directly over the specified color')\\n\\t\\t(isUnderMouse\\n\\t\\t\\t'Whether any part of this object is beneath the current mouse-cursor position')\\n\\t\\t(lastPage\\n\\t\\t\\t'Go to the last page of the book.')\\n\\t\\t(left\\n\\t\\t\\t'My left edge, measured from the left edge of the World')\\n\\t\\t(leftRight\\n\\t\\t\\t'The horizontal displacement')\\n\\t\\t(liftAllPens\\n\\t\\t\\t'Lift the pens on all the objects in my interior.')\\n\\t\\t(lowerAllPens\\n\\t\\t\\t'Lower the pens on all the objects in my interior.')\\n\\t\\t(mouseX\\n\\t\\t\\t'The x coordinate of the mouse pointer')\\n\\t\\t(mouseY\\n\\t\\t\\t'The y coordinate of the mouse pointer')\\n\\t\\t(moveToward:\\n\\t\\t\\t'Move in the direction of another object.')\\n\\t\\t(insertCard\\n\\t\\t\\t'Create a new card.')\\n\\t\\t(nextPage\\n\\t\\t\\t'Go to next page.')\\n\\t\\t(numberAtCursor\\n\\t\\t\\t'The number held by the object at the chosen element')\\n\\t\\t(objectNameInHalo\\n\\t\\t\\t'Object''s name -- To change: click here, edit, hit ENTER')\\n\\t\\t(obtrudes\\n\\t\\t\\t'Whether any part of the object sticks out beyond its container''s borders')\\n\\t\\t(offerScriptorMenu\\n\\t\\t\\t'The Scriptee.\\nPress here to get a menu')\\n\\t\\t(pauseScript:\\n\\t\\t\\t'Make a running script become paused.')\\n\\t\\t(penDown\\n\\t\\t\\t'Whether the object''s pen is down (true) or up (false)')\\n\\t\\t(penColor\\n\\t\\t\\t'The color of the object''s pen')\\n\\t\\t(penSize\\t\\n\\t\\t\\t'The size of the object''s pen')\\n\\t\\t(clearPenTrails\\n\\t\\t\\t'Clear all pen trails in the current playfield')\\n\\t\\t(playerSeeingColorPhrase\\n\\t\\t\\t'The player who \\\"sees\\\" a given color')\\n\\t\\t(previousPage\\n\\t\\t\\t'Go to previous page')\\n\\n\\t\\t(show\\n\\t\\t\\t'If object was hidden, make it show itself again.')\\n\\t\\t(startScript:\\n\\t\\t\\t'Make a script start running.')\\n\\t\\t(stopScript:\\n\\t\\t\\t'Make a script stop running.')\\n\\t\\t(top\\n\\t\\t\\t'My top edge, measured downward from the top edge of the world')\\n\\t\\t(right\\n\\t\\t\\t'My right edge, measured from the left edge of the world')\\n\\t\\t(roundUpStrays\\n\\t\\t\\t'Bring all out-of-container subparts back into view.')\\n\\t\\t(scaleFactor\\n\\t\\t\\t'The amount by which the object is scaled')\\n\\t\\t(stopScript:\\n\\t\\t\\t'make the specified script stop running')\\n\\t\\t(tellAllSiblings:\\n\\t\\t\\t'send a message to all of my sibling instances')\\n\\t\\t(try\\n\\t\\t\\t'Run this command once.')\\n\\t\\t(tryMe\\n\\t\\t\\t'Click here to run this script once; hold button down to run repeatedly')\\n\\t\\t(turn:\\t\\t\\t\\t\\n\\t\\t\\t'Change the heading of the object by the specified amount')\\n\\t\\t(unhideHiddenObjects\\n\\t\\t\\t'Unhide all hidden objects.')\\n\\t\\t(upDown\\n\\t\\t\\t'The vertical displacement')\\n\\t\\t(userScript\\n\\t\\t\\t'This is a script defined by you.')\\n\\t\\t(userSlot\\n\\t\\t\\t'This is a variable defined by you. Click here to change its type')\\n\\t\\t(valueAtCursor\\n\\t\\t\\t'The chosen element')\\n\\t\\t(wearCostumeOf:\\n\\t\\t\\t'Wear the same kind of costume as the other object')\\n\\t\\t(width\\t\\n\\t\\t\\t'The distance between the left and right edges of the object')\\n\\t\\t(wrap\\n\\t\\t\\t'If object has strayed beond the boundaries of its container, make it reappear from the opposite edge.')\\n\\t\\t(x\\n\\t\\t\\t'The x coordinate, measured from the left of the container')\\n\\t\\t(y\\n\\t\\t\\t'The y-coordinate, measured upward from the bottom of the container')\\n\\n\\t\\t)\\n! !\\n\\n\\n!Morph class methodsFor: 'testing' stamp: 'nk 6/12/2004 09:20'!\\nallSketchMorphClasses\\n\\t\\\"Morph allSketchMorphClasses\\\"\\n\\t^ Array\\n\\t\\tstreamContents: [:s | self\\n\\t\\t\\t\\twithAllSubclassesDo: [:cls | cls isSketchMorphClass\\n\\t\\t\\t\\t\\t\\tifTrue: [s nextPut: cls ]]]\\n! !\\n\\n!Morph class methodsFor: 'testing' stamp: 'yo 3/17/2005 09:07'!\\nallSketchMorphForms\\n\\t\\\"Answer a Set of forms of SketchMorph (sub) instances, except those \\n\\tused as button images, ones being edited, and those with 0 extent.\\\"\\n\\n\\t| reasonableForms form |\\n\\treasonableForms := Set new.\\n\\tMorph allSketchMorphClasses do:\\n\\t\\t[:cls | cls allInstances do:\\n\\t\\t\\t[:m | (m owner isKindOf: SketchEditorMorph orOf: IconicButton)\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[form _ m form.\\n\\t\\t\\t\\t\\t((form width > 0) and: [form height > 0]) ifTrue: [reasonableForms add: form]]]].\\n\\t^ reasonableForms! !\\n\\n!Morph class methodsFor: 'testing' stamp: 'nk 6/12/2004 09:17'!\\nisSketchMorphClass\\n\\t^false! !\\n\\n\\n!Morph class methodsFor: '*eToys-customevents-user events' stamp: 'sw 6/16/2005 01:26'!\\nadditionsToViewerCategoryUserEvents\\n\\t\\\"Answer further viewer additions relating to user-defined events; these appear in the 'scripting' category\\\"\\n\\n\\t^ Preferences allowEtoyUserCustomEvents\\n\\t\\tifTrue: [ #(scripting (\\n\\t\\t\\t(command triggerCustomEvent: 'trigger a user-defined (global) event' CustomEvents)\\n\\t\\t\\t(slot triggeringObject 'the object that is triggering an event, either user-defined or pre-defined' Player readOnly Player getTriggeringObject unused unused)))]\\n\\t\\tifFalse: [#(scripting ())]! !\\n\\n\\n!Morph class methodsFor: '*eToys-new-morph participation' stamp: 'sw 10/24/2001 15:51'!\\npartName: aName categories: aList documentation: aDoc sampleImageForm: aForm\\n\\t\\\"Answer a DescriptionForPartsBin which will represent a launch of a new instance of my class via the #newStandAlone protocol sent to my class. Use the category-list and documentation provided. This variant allows an overriding image form to be provided, useful in cases where we don't want to launch a sample instance just to get the form\\\"\\n\\n\\n\\t| descr |\\n\\tdescr _ DescriptionForPartsBin new\\n\\t\\tformalName: aName\\n\\t\\tcategoryList: aList\\n\\t\\tdocumentation: aDoc\\n\\t\\tglobalReceiverSymbol: self name\\n\\t\\tnativitySelector: #newStandAlone.\\n\\tdescr sampleImageForm: aForm.\\n\\t^ descr\\n! !\\n\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/27/2001 17:40'!\\nadditionsToViewerCategoryBasic\\n\\t\\\"Answer viewer additions for the 'basic' category\\\"\\n\\n\\t^#(\\n\\t\\tbasic \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y \\t'The y coordinate' Number readWrite Player \\tgetY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\t\\t\\t(command forward: 'Moves the object forward in the direction it is heading' Number)\\n\\t\\t\\t(command turn: 'Change the heading of the object by the specified amount' Number)\\n\\t\\t\\t(command beep: 'Make the specified sound' Sound)\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 4/20/2002 00:47'!\\nadditionsToViewerCategoryDragAndDrop\\n\\t\\\"Answer viewer additions for the 'drag & drop' category\\\"\\n\\n\\t^#(\\n\\t\\t#'drag & drop'\\n \\n\\t\\t(\\n\\t\\t\\t(slot 'drop enabled' 'Whether drop is enabled' Boolean readWrite Player getDropEnabled Player setDropEnabled:)\\n\\t\\t\\t(slot 'resist being picked up' 'Whether a simple mouse-drag on this object should allow it to be picked up' Boolean readWrite Player getSticky Player setSticky:)\\n\\t\\t\\t(slot 'resist deletion' 'Whether this is resistant to easy removal via the pink X halo handle.' Boolean readWrite Player getResistsRemoval Player setResistsRemoval:)\\n\\t\\t\\t(slot 'be locked' 'Whether this object should be blind to all input' Boolean readWrite Player getIsLocked Player setIsLocked:)\\n\\t\\t\\n\\t\\t))! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/17/2002 13:58'!\\nadditionsToViewerCategoryGeometry\\n\\t\\\"answer additions to the geometry viewer category\\\"\\n\\n\\t^ #(geometry \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y 'The y coordinate' Number readWrite Player getY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\n\\t\\t\\t(slot scaleFactor 'The factor by which the object is magnified' Number readWrite Player getScaleFactor Player setScaleFactor:)\\n\\t\\t\\t(slot left 'The left edge' Number readWrite Player getLeft Player setLeft:)\\n\\t\\t\\t(slot right 'The right edge' Number readWrite Player getRight Player setRight:)\\n\\t\\t\\t(slot top 'The top edge' Number readWrite Player getTop Player setTop:) \\n\\t\\t\\t(slot bottom 'The bottom edge' Number readWrite Player getBottom Player setBottom:) \\n\\t\\t\\t(slot length 'The length' Number readWrite Player getLength Player setLength:) \\n\\t\\t\\t(slot width 'The width' Number readWrite Player getWidth Player setWidth:)\\n\\n\\t\\t\\t(slot headingTheta 'The angle, in degrees, that my heading vector makes with the positive x-axis' Number readWrite Player getHeadingTheta Player setHeadingTheta:)\\n\\n\\t\\t\\t(slot distance 'The length of the vector connecting the origin to the object''s position' Number readWrite Player getDistance Player setDistance:)\\n\\t\\t\\t(slot theta 'The angle between the positive x-axis and the vector connecting the origin to the object''s position' Number readWrite Player getTheta Player setTheta: )\\n\\t\\t)\\n\\t)\\n\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 11/16/2001 10:21'!\\nadditionsToViewerCategoryLayout\\n\\t\\\"Answer viewer additions for the 'layout' category\\\"\\n\\n\\t^#(\\n\\t\\tlayout \\n\\t\\t(\\n\\t\\t\\t(slot clipSubmorphs 'Whether or not to clip my submorphs' Boolean readWrite Player getClipSubmorphs Player setClipSubmorphs:)\\n\\n\\t\\t))\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 7/8/2004 00:20'!\\nadditionsToViewerCategoryMiscellaneous\\n\\t\\\"Answer viewer additions for the 'miscellaneous' category\\\"\\n\\n\\t^#(\\n\\t\\tmiscellaneous \\n\\t\\t(\\n\\t\\t\\t(command doMenuItem: 'do the menu item' Menu)\\n\\t\\t\\t(command show 'make the object visible')\\n\\t\\t\\t(command hide 'make the object invisible')\\n\\t\\t\\t(command wearCostumeOf: 'wear the costume of...' Player)\\n\\n\\t\\t\\t(command fire 'trigger any and all of this object''s button actions')\\n\\t\\t\\t(slot copy 'returns a copy of this object' Player readOnly Player getNewClone\\t unused unused)\\n\\t\\t\\t(slot elementNumber 'my index in my container' Number readWrite Player getIndexInOwner Player setIndexInOwner:)\\n\\t\\t\\t(slot holder 'the object''s container' Player readOnly Player getHolder Player setHolder:)\\n\\t\\t\\t(command stamp 'add my image to the pen trails')\\n\\t\\t\\t(command erase 'remove this object from the screen')\\n\\t\\t\\t(command stampAndErase 'add my image to the pen trails and go away')\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'dgd 8/8/2003 22:17'!\\nadditionsToViewerCategoryMotion\\n\\t\\\"Answer viewer additions for the 'motion' category\\\"\\n\\n\\t^#(\\n\\t\\tmotion \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y \\t'The y coordinate' Number readWrite Player \\tgetY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\t\\t\\t(command forward: 'Moves the object forward in the direction it is heading' Number)\\n\\t\\t\\t(slot obtrudes 'whether the object sticks out over its container''s edge' Boolean readOnly Player getObtrudes unused unused) \\n\\t\\t\\t(command turnToward: 'turn toward the given object' Player) \\n\\t\\t\\t(command moveToward: 'move toward the given object' Player) \\n\\t\\t\\t(command turn: 'Change the heading of the object by the specified amount' Number)\\n\\t\\t\\t(command bounce: 'bounce off the edge if hit' Sound) \\n\\t\\t\\t(command wrap 'wrap off the edge if appropriate') \\n\\t\\t\\t(command followPath 'follow the yellow brick road') \\n\\t\\t\\t(command goToRightOf: 'place this object to the right of another' Player)\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 12/9/2001 23:26'!\\nadditionsToViewerCategoryObservation\\n\\t\\\"Answer viewer additions for the 'observations' category\\\"\\n\\n\\t^#(\\n\\t\\tobservation\\n \\n\\t\\t(\\n\\t\\t\\t(slot colorUnder 'The color under the center of the object' Color readOnly Player getColorUnder unused unused )\\n\\t\\t\\t(slot brightnessUnder 'The brightness under the center of the object' Number readOnly Player getBrightnessUnder unused unused)\\n\\t\\t\\t(slot luminanceUnder 'The luminance under the center of the object' Number readOnly Player getLuminanceUnder unused unused)\\n\\t\\t\\t(slot saturationUnder 'The saturation under the center of the object' Number readOnly Player getSaturationUnder unused unused)\\n\\t\\t\\n\\t\\t))\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 4/17/2003 12:05'!\\nadditionsToViewerCategoryPenUse\\n\\t\\\"Answer viewer additions for the 'pen use' category\\\"\\n\\n\\t^#(\\n\\t\\t#'pen use' \\n\\t\\t(\\n\\t\\t\\t(slot penColor 'the color of ink used by the pen' Color readWrite Player getPenColor Player setPenColor:) \\n\\t\\t\\t(slot penSize 'the width of the pen' Number readWrite Player getPenSize Player setPenSize:) \\n\\t\\t\\t(slot penDown 'whether the pen is currently down' Boolean readWrite Player getPenDown Player setPenDown:)\\n\\t\\t\\t(slot trailStyle 'determines whether lines, arrows, arrowheads, or dots are used when I put down a pen trail' TrailStyle readWrite Player getTrailStyle Player setTrailStyle:)\\n\\t\\t\\t(slot dotSize 'diameter of dot to use when trailStyle is dots' Number readWrite Player getDotSize Player setDotSize:)\\n\\t\\t\\t(command clearOwnersPenTrails 'clear all pen trails in my containing playfield')\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 2/19/2003 18:04'!\\nadditionsToViewerCategoryScripting\\n\\t\\\"Answer viewer additions for the 'scripting' category\\\"\\n\\n\\t^#(\\n\\t\\tscripting \\n\\t\\t(\\n\\n\\t\\t\\t(command startScript: 'start the given script ticking' ScriptName)\\n\\t\\t\\t(command pauseScript: 'make the given script be \\\"paused\\\"' ScriptName)\\n\\t\\t\\t(command stopScript: 'make the given script be \\\"normal\\\"' ScriptName)\\n\\n\\t\\t\\t(command startAll: 'start the given script ticking in the object and all of its siblings.' ScriptName)\\n\\t\\t\\t(command pauseAll: 'make the given script be \\\"paused\\\" in the object and all of its siblings' ScriptName)\\n\\t\\t\\t(command stopAll: 'make the given script be \\\"normal\\\" in the object and all of its siblings' ScriptName)\\n\\n\\t\\t\\t(command doScript: 'run the given script once, on the next tick' ScriptName)\\n\\t\\t\\t(command tellSelfAndAllSiblings: 'run the given script in the object and in all of its siblings' ScriptName)\\n\\t\\t\\t(command tellAllSiblings: 'send a message to all siblings' ScriptName)))! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'RAA 5/18/2001 12:48'!\\nadditionsToViewerCategoryScripts\\n\\n\\t\\\"note: if you change the thing below you also need to change #tileScriptCommands.\\\"\\n\\n\\t^#(\\n\\t\\tscripts \\n\\t\\t(\\n\\t\\t\\t(command emptyScript 'an empty script')\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'nk 10/14/2004 10:59'!\\nadditionsToViewerCategoryTests\\n\\t\\\"Answer viewer additions for the 'tests' category.\\\"\\n\\n\\\"Note: Because of intractable performance problems in continuously evaluating isOverColor in a Viewer, the isOverColor entry is not given a readout\\\"\\n\\n\\t^#(\\n\\t\\t#tests \\n\\t\\t(\\n\\t\\t\\t(slot isOverColor 'whether any part of the object is over the given color' Boolean\\treadOnly Player seesColor: unused unused)\\n\\t\\t\\t(slot isUnderMouse 'whether the object is under the current mouse position' Boolean readOnly\\tPlayer getIsUnderMouse unused unused)\\n\\t\\t\\t(slot colorSees\\t'whether the given color sees the given color' Boolean readOnly\\tPlayer color:sees:\\tunused\\tunused)\\n\\t\\t\\t(slot overlaps 'whether I overlap a given object' Boolean readOnly Player overlaps: unused unused)\\n\\t\\t\\t(slot overlapsAny 'whether I overlap a given object or one of its siblings or similar objects' Boolean readOnly Player overlapsAny: unused unused)\\n\\t\\t\\t(slot touchesA\\t'whether I overlap any Sketch that is showing the same picture as a particular prototype.' Boolean readOnly Player touchesA:\\tunused\\tunused)\\n\\t\\t\\t(slot obtrudes 'whether the object sticks out over its container''s edge' Boolean readOnly Player getObtrudes unused unused)\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/17/2002 10:00'!\\nvectorAdditions\\n\\t\\\"Answer slot/command definitions for the vector experiment\\\"\\n\\n\\t^ # (\\n(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n(slot y 'The y coordinate' Number readWrite Player getY Player setY:)\\n(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n(slot distance 'The length of the vector connecting the origin to the object''s position' Number readWrite Player getDistance Player setDistance:)\\n(slot theta 'The angle between the positive x-axis and the vector connecting the origin to the object''s position' Number readWrite Player getTheta Player setTheta: )\\n(slot headingTheta 'The angle that my heading vector makes with the positive x-axis' Number readWrite Player getHeadingTheta Player setHeadingTheta:)\\n\\n(command + 'Adds two players together, treating each as a vector from the origin.' Player)\\n(command - 'Subtracts one player from another, treating each as a vector from the origin.' Player)\\n(command * 'Multiply a player by a Number, treating the Player as a vector from the origin.' Number)\\n(command / 'Divide a player by a Number, treating the Player as a vector from the origin.' Number)\\n\\n(command incr: 'Each Player is a vector from the origin. Increase one by the amount of the other.' Player)\\n(command decr: 'Each Player is a vector from the origin. Decrease one by the amount of the other.' Player)\\n(command multBy: 'A Player is a vector from the origin. Multiply its length by the factor.' Number)\\n(command dividedBy: 'A Player is a vector from the origin. Divide its length by the factor.' Number)\\n\\t)! !\\n\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 10/11/2003 18:17'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the\\n\\tphrases this kind of morph wishes to add to various Viewer categories.\\n\\n\\tThis version factors each category definition into a separate method.\\n\\n\\tSubclasses that have additions can either:\\n\\t\\t- override this method, or\\n\\t\\t- (preferably) define one or more additionToViewerCategory* methods.\\n\\n\\tThe advantage of the latter technique is that class extensions may be added\\n\\tby external packages without having to re-define additionsToViewerCategories.\\n\\t\\\"\\n\\t^#()! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 16:35'!\\nadditionsToViewerCategory: aCategoryName\\n\\t\\\"Answer a list of viewer specs for items to be added to the given category on behalf of the receiver. Each class in a morph's superclass chain is given the opportunity to add more things\\\"\\n\\n\\taCategoryName == #vector ifTrue:\\n\\t\\t[^ self vectorAdditions].\\n\\t^self allAdditionsToViewerCategories at: aCategoryName ifAbsent: [ #() ].! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 10/11/2003 18:06'!\\nadditionToViewerCategorySelectors\\n\\t\\\"Answer the list of my selectors matching additionsToViewerCategory*\\\"\\n\\t^self class organization allMethodSelectors select: [ :ea |\\n\\t\\t(ea beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\tand: [ (ea at: 26 ifAbsent: []) ~= $: ]]! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 16:56'!\\nallAdditionsToViewerCategories\\n\\t\\\"Answer a Dictionary of (<categoryName> <list of category specs>) that \\n\\tdefines the phrases this kind of morph wishes to add to various Viewer categories. \\n\\t \\n\\tThis version allows each category definition to be defined in one or more separate methods. \\n\\t \\n\\tSubclasses that have additions can either:\\n\\t- override #additionsToViewerCategories, or\\n\\t- (preferably) define one or more additionToViewerCategory* methods.\\n\\n\\tThe advantage of the latter technique is that class extensions may be added by\\n\\texternal packages without having to re-define additionsToViewerCategories.\\\"\\n\\n\\t\\\"\\n\\tMorph allAdditionsToViewerCategories\\n\\t\\\"\\n\\t| dict |\\n\\tdict := IdentityDictionary new.\\n\\t(self class includesSelector: #additionsToViewerCategories)\\n\\t\\tifTrue: [self additionsToViewerCategories\\n\\t\\t\\t\\tdo: [:group | group\\n\\t\\t\\t\\t\\t\\tpairsDo: [:key :list | (dict\\n\\t\\t\\t\\t\\t\\t\\t\\tat: key\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [OrderedCollection new])\\n\\t\\t\\t\\t\\t\\t\\t\\taddAll: list]]].\\n\\tself class selectors\\n\\t\\tdo: [:aSelector | ((aSelector beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\tand: [(aSelector at: 26 ifAbsent: []) ~= $:])\\n\\t\\t\\t\\tifTrue: [(self perform: aSelector)\\n\\t\\t\\t\\t\\t\\tpairsDo: [:key :list | (dict\\n\\t\\t\\t\\t\\t\\t\\t\\tat: key\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [OrderedCollection new])\\n\\t\\t\\t\\t\\t\\t\\t\\taddAll: list]]].\\n\\t^ dict! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nunfilteredCategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer for one of my instances, in order of:\\n\\t- masterOrderingOfCategorySymbols first\\n\\t- others last in order by translated wording\\\"\\n\\t\\\"\\n\\tMorph unfilteredCategoriesForViewer\\n\\t\\\"\\n\\n\\t| aClass additions masterOrder |\\n\\taClass := self.\\n\\tadditions := OrderedCollection new.\\n\\t[aClass == Morph superclass ] whileFalse: [\\n\\t\\tadditions addAll: (aClass allAdditionsToViewerCategories keys\\n\\t\\t\\tasSortedCollection: [ :a :b | a translated < b translated ]).\\n\\t\\taClass := aClass superclass ]. \\n\\n\\tmasterOrder := EToyVocabulary masterOrderingOfCategorySymbols.\\n\\n\\t^(masterOrder intersection: additions), (additions difference: masterOrder).! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-arrow head size'!\\ndefaultArrowheadSize\\n\\t\\n\\t^ 5 @ 4! !\\n\\n!Morph class methodsFor: '*MorphicExtras-arrow head size'!\\nobtainArrowheadFor: aPrompt defaultValue: defaultPoint\\n\\t\\\"Allow the user to supply a point to serve as an arrowhead size. Answer nil if we fail to get a good point\\\"\\n\\n\\t| result |\\n\\tresult := FillInTheBlank request: aPrompt initialAnswer: defaultPoint asString.\\n\\tresult isEmptyOrNil ifTrue: [^ nil].\\n\\t^ [(Point readFrom: (ReadStream on: result))]\\n\\t\\ton: Error do: [:ex | nil].! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-new-morph participation' stamp: 'sw 11/27/2001 13:20'!\\naddPartsDescriptorQuadsTo: aList if: aBlock\\n\\t\\\"For each of the standard objects to be put into parts bins based on declarations in this class, add a parts-launching quintuplet to aList, provided that the boolean-valued-block-with-one-argument supplied evaluates to true when provided the DescriptionForPartsBin\\\"\\n\\n\\t| info more |\\n\\t(self class includesSelector: #descriptionForPartsBin) ifTrue:\\n\\t\\t[info _ self descriptionForPartsBin.\\n\\t\\t(aBlock value: info) ifTrue:\\n\\t\\t\\t[aList add:\\n\\t\\t\\t\\t{info globalReceiverSymbol.\\n\\t\\t\\t\\tinfo nativitySelector.\\n\\t\\t\\t\\tinfo formalName.\\n\\t\\t\\t\\tinfo documentation.\\n\\t\\t\\t\\tinfo sampleImageFormOrNil}]].\\n\\n\\t(self class includesSelector: #supplementaryPartsDescriptions)\\n\\t\\tifTrue:\\n\\t\\t\\t[more _ self supplementaryPartsDescriptions.\\n\\t\\t\\t(more isKindOf: DescriptionForPartsBin) ifTrue: [more _ Array with: more].\\n\\t\\t\\t\\t\\\"The above being a mild bit of forgiveness, so that in the usual only-one\\n\\t\\t\\t\\tcase, the user need not return a collection\\\"\\n\\t\\t\\tmore do:\\n\\t\\t\\t\\t[:aPartsDescription | (aBlock value: aPartsDescription) ifTrue:\\n\\t\\t\\t\\t\\t[aList add:\\n\\t\\t\\t\\t\\t\\t{aPartsDescription globalReceiverSymbol.\\n\\t\\t\\t\\t\\t\\taPartsDescription nativitySelector.\\n\\t\\t\\t\\t\\t\\taPartsDescription formalName.\\n\\t\\t\\t\\t\\t\\taPartsDescription documentation.\\n\\t\\t\\t\\t\\t\\taPartsDescription sampleImageFormOrNil}]]]! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-parts bin' stamp: 'sw 8/12/2001 14:26'!\\nsupplementaryPartsDescriptions\\n\\t\\\"Answer a list of DescriptionForPartsBin objects that characterize objects that this class wishes to contribute to Stationery bins *other* than by the standard default #newStandAlone protocol\\\"\\n\\n\\t^ {\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Status'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Buttons to run, stop, or single-step scripts'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #scriptControlButtons.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Scripting'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'A confined place for drawing and scripting, with its own private stop/step/go buttons.'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #newScriptingSpace.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Random'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'A tile that will produce a random number in a given range'\\n\\t\\t\\tglobalReceiverSymbol: #RandomNumberTile\\n\\t\\t\\tnativitySelector: #new.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'ButtonDown?'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Tiles for querying whether the mouse button is down'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #anyButtonPressedTiles.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'ButtonUp?'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Tiles for querying whether the mouse button is up'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #noButtonPressedTiles.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'NextPage'\\n\\t\\t\\tcategoryList: #(Presentation)\\n\\t\\t\\tdocumentation: 'A button which, when clicked, takes the reader to the next page of a book'\\n\\t\\t\\tglobalReceiverSymbol: #BookMorph\\n\\t\\t\\tnativitySelector: #nextPageButton.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'PreviousPage'\\n\\t\\t\\tcategoryList: #(Presentation)\\n\\t\\t\\tdocumentation: 'A button which, when clicked, takes the reader to the next page of a book'\\n\\t\\t\\tglobalReceiverSymbol: #BookMorph\\n\\t\\t\\tnativitySelector: #previousPageButton.},\\n\\n\\t(Flaps quadsDefiningToolsFlap collect:\\n\\t\\t[:aQuad | DescriptionForPartsBin fromQuad: aQuad categoryList: #(Tools)])! !\\n\\n\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'al 11/28/2005 16:46'!\\nnoteAddedSelector: aSelector meta: isMeta\\n\\t\\\"Any change to an additionsToViewer... method can invalidate existing etoy vocabularies.\\n\\tThe #respondsTo: test is to allow loading the FlexibleVocabularies change set without having to worry about method ordering.\\\"\\n\\t(isMeta\\n\\t\\t\\tand: [(aSelector beginsWith: 'additionsToViewer')\\n\\t\\t\\t\\t\\tand: [self respondsTo: #hasAdditionsToViewerCategories]])\\n\\t\\tifTrue: [Vocabulary changeMadeToViewerAdditions].\\n\\tsuper noteCompilationOf: aSelector meta: isMeta! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/15/2004 12:40'!\\nnoteCompilationOf: aSelector meta: isMeta\\n\\t\\\"This method does nothing and should be removed!!\\\"\\n\\n\\t^ super noteCompilationOf: aSelector meta: isMeta! !\\nRectangleMorph subclass: #MorphExample\\n\\tinstanceVariableNames: 'phase ball star'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n!MorphExample commentStamp: 'kfr 10/26/2003 18:38' prior: 0!\\nThis is a example of how to use a morph. It consists of only two \\nmethods, initialize and step.\\n\\nDoIt:\\nMorphExample new openInWorld.\\n\\n\\n\\n!\\n\\n\\n!MorphExample methodsFor: 'initialization' stamp: 'dgd 2/21/2003 19:59'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tphase _ 1.\\n\\tself extent: 200 @ 200.\\n\\tball _ EllipseMorph new extent: 30 @ 30.\\n\\tself\\n\\t\\taddMorph: ((star _ StarMorph new extent: 150 @ 150) center: self center)! !\\n\\n\\n!MorphExample methodsFor: 'stepping and presenter' stamp: 'kfr 10/26/2003 18:33'!\\nstep\\n\\tphase _ phase\\\\\\\\8 + 1.\\n\\tphase = 1 ifTrue: [^ ball delete].\\n\\tphase < 4 ifTrue:[^self].\\n\\tphase = 4 ifTrue: [self addMorph: ball].\\n\\tball align: ball center with: (star vertices at: (phase-3*2)).! !\\nObject subclass: #MorphExtension\\n\\tinstanceVariableNames: 'locked visible sticky balloonText balloonTextSelector externalName isPartsDonor actorState player eventHandler otherProperties'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MorphExtension commentStamp: '<historical>' prior: 0!\\nMorphExtension provides access to extra instance state that is not required in most simple morphs. This allows simple morphs to remain relatively lightweight while still admitting more complex structures as necessary. The otherProperties field takes this policy to the extreme of allowing any number of additional named attributes, albeit at a certain cost in speed and space.!\\n\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:52'!\\nballoonText\\n\\t^ balloonText! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:52'!\\nballoonTextSelector\\n\\t^ balloonTextSelector! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:51'!\\nballoonTextSelector: aSymbol \\n\\t\\\"change the receiver's balloonTextSelector\\\"\\n\\tballoonTextSelector _ aSymbol! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:55'!\\nballoonText: newValue\\n\\tballoonText _ newValue! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:51'!\\neventHandler\\n\\t\\\"answer the receiver's eventHandler\\\"\\n\\t^ eventHandler ! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:56'!\\neventHandler: newValue\\n\\teventHandler _ newValue! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:57'!\\nexternalName: aString \\n\\t\\\"change the receiver's externalName\\\"\\n\\texternalName _ aString! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:38'!\\nlocked\\n\\t\\\"answer whether the receiver is Locked\\\"\\n\\t^ locked! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:48'!\\nlocked: aBoolean \\n\\t\\\"change the receiver's locked property\\\"\\n\\tlocked _ aBoolean! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/14/1998 13:07'!\\nsticky\\n\\t^ sticky! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:47'!\\nsticky: aBoolean \\n\\t\\\"change the receiver's sticky property\\\"\\n\\tsticky _ aBoolean! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:41'!\\nvisible\\n\\t\\\"answer whether the receiver is visible\\\"\\n\\t^ visible! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:55'!\\nvisible: newValue\\n\\tvisible _ newValue! !\\n\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:17'!\\nlayoutFrame\\n\\t^self valueOfProperty: #layoutFrame ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutFrame: aLayoutFrame \\n\\taLayoutFrame isNil\\n\\t\\tifTrue: [self removeProperty: #layoutFrame]\\n\\t\\tifFalse: [self setProperty: #layoutFrame toValue: aLayoutFrame]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:17'!\\nlayoutPolicy\\n\\t^self valueOfProperty: #layoutPolicy ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutPolicy: aLayoutPolicy \\n\\taLayoutPolicy isNil\\n\\t\\tifTrue: [self removeProperty: #layoutPolicy]\\n\\t\\tifFalse: [self setProperty: #layoutPolicy toValue: aLayoutPolicy]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:18'!\\nlayoutProperties\\n\\t^self valueOfProperty: #layoutProperties ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutProperties: newProperties \\n\\t\\\"Return the current layout properties associated with the receiver\\\"\\n\\n\\tnewProperties isNil\\n\\t\\tifTrue: [self removeProperty: #layoutProperties]\\n\\t\\tifFalse: [self setProperty: #layoutProperties toValue: newProperties]! !\\n\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:41'!\\nassureOtherProperties\\n\\t\\\"creates an otherProperties for the receiver if needed\\\"\\n\\totherProperties ifNil: [self initializeOtherProperties].\\n\\t^ otherProperties! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:36'!\\nhasOtherProperties\\n\\t\\\"answer whether the receiver has otherProperties\\\"\\n\\t^ otherProperties notNil! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:42'!\\nhasProperty: aSymbol \\n\\t\\\"Answer whether the receiver has the property named aSymbol\\\"\\n\\t| property |\\n\\totherProperties ifNil: [^ false].\\n\\tproperty := otherProperties at: aSymbol ifAbsent: [].\\n\\tproperty isNil ifTrue: [^ false].\\n\\tproperty == false ifTrue: [^ false].\\n\\t^ true! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:36'!\\ninitializeOtherProperties\\n\\t\\\"private - initializes the receiver's otherProperties\\\"\\n\\totherProperties := IdentityDictionary new! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:04'!\\notherProperties\\n\\t\\\"answer the receiver's otherProperties\\\"\\n\\t^ otherProperties! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:20'!\\nprivateOtherProperties: anIndentityDictionary \\n\\t\\\"private - change the receiver's otherProperties\\\"\\n\\totherProperties _ anIndentityDictionary ! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:37'!\\nremoveOtherProperties\\n\\t\\\"Remove the 'other' properties\\\"\\n\\totherProperties := nil! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:43'!\\nremoveProperty: aSymbol \\n\\t\\\"removes the property named aSymbol if it exists\\\"\\n\\totherProperties ifNil: [^ self].\\n\\totherProperties removeKey: aSymbol ifAbsent: [].\\n\\totherProperties isEmpty ifTrue: [self removeOtherProperties]! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:49'!\\nsetProperty: aSymbol toValue: abObject \\n\\t\\\"change the receiver's property named aSymbol to anObject\\\"\\n\\tself assureOtherProperties at: aSymbol put: abObject! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:45'!\\nsortedPropertyNames\\n\\t\\\"answer the receiver's property names in a sorted way\\\"\\n\\n\\t| props |\\n\\tprops := WriteStream on: (Array new: 10).\\n\\tlocked == true ifTrue: [props nextPut: #locked].\\n\\tvisible == false ifTrue: [props nextPut: #visible].\\n\\tsticky == true ifTrue: [props nextPut: #sticky].\\n\\tballoonText isNil ifFalse: [props nextPut: #balloonText].\\n\\tballoonTextSelector isNil ifFalse: [props nextPut: #balloonTextSelector].\\n\\texternalName isNil ifFalse: [props nextPut: #externalName].\\n\\tisPartsDonor == true ifTrue: [props nextPut: #isPartsDonor].\\n\\tactorState isNil ifFalse: [props nextPut: #actorState].\\n\\tplayer isNil ifFalse: [props nextPut: #player].\\n\\teventHandler isNil ifFalse: [props nextPut: #eventHandler].\\n\\t otherProperties ifNotNil: [otherProperties associationsDo: [:a | props nextPut: a key]].\\n\\t^props contents sort: [:s1 :s2 | s1 <= s2]! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:00'!\\nvalueOfProperty: aSymbol \\n\\\"answer the value of the receiver's property named aSymbol\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: aSymbol\\n\\t\\tifAbsent: []! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:28'!\\nvalueOfProperty: aSymbol ifAbsentPut: aBlock \\n\\t\\\"If the receiver possesses a property of the given name, answer \\n\\tits value. If not, then create a property of the given name, give \\n\\tit the value obtained by evaluating aBlock, then answer that \\n\\tvalue\\\"\\n\\t^self assureOtherProperties at: aSymbol ifAbsentPut: aBlock! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:43'!\\nvalueOfProperty: aSymbol ifAbsent: aBlock \\n\\t\\\"if the receiver possesses a property of the given name, answer \\n\\tits value. If not then evaluate aBlock and answer the result of \\n\\tthis block evaluation\\\"\\n\\totherProperties ifNil: [^ aBlock value].\\n\\t^ otherProperties at: aSymbol ifAbsent: [^ aBlock value]! !\\n\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:20'!\\ncopyWeakly\\n\\t\\\"list of names of properties whose values should be weak-copied when veryDeepCopying a morph. See DeepCopier.\\\"\\n\\n\\t^ #(formerOwner newPermanentPlayer logger graphModel gestureDictionaryOrName)\\n\\t\\\"add yours to this list\\\" \\n\\n\\t\\\"formerOwner should really be nil at the time of the copy, but this will work just fine.\\\"! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:23'!\\npropertyNamesNotCopied\\n\\t\\\"list of names of properties whose values should be deleted when veryDeepCopying a morph.\\n\\tSee DeepCopier.\\\"\\n\\n\\t^ #(connectedConstraints connectionHighlights highlightedTargets)\\n\\t\\\"add yours to this list\\\" \\n! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:39'!\\nveryDeepFixupWith: deepCopier \\n\\t\\\"If target and arguments fields were weakly copied, fix them here.\\n\\tIf they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\n\\tsuper veryDeepFixupWith: deepCopier.\\n\\totherProperties ifNil: [ ^self ].\\n\\n\\t\\\"Properties whose values are only copied weakly replace those values if they were copied via another path\\\"\\n\\tself copyWeakly do: [ :propertyName |\\n\\t\\totherProperties at: propertyName ifPresent: [ :property |\\n\\t\\t\\totherProperties at: propertyName\\n\\t\\t\\t\\tput: (deepCopier references at: property ifAbsent: [ property ])]].\\n! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:45'!\\nveryDeepInner: deepCopier \\n\\t\\\"Copy all of my instance variables.\\n\\tSome otherProperties need to be not copied at all, but shared. Their names are given by copyWeakly.\\n\\tSome otherProperties should not be copied or shared. Their names are given by propertyNamesNotCopied.\\n\\tThis is special code for the dictionary. See DeepCopier, and veryDeepFixupWith:.\\\"\\n\\n\\t| namesOfWeaklyCopiedProperties weaklyCopiedValues |\\n\\tsuper veryDeepInner: deepCopier.\\n\\tlocked _ locked veryDeepCopyWith: deepCopier.\\n\\tvisible _ visible veryDeepCopyWith: deepCopier.\\n\\tsticky _ sticky veryDeepCopyWith: deepCopier.\\n\\tballoonText _ balloonText veryDeepCopyWith: deepCopier.\\n\\tballoonTextSelector _ balloonTextSelector veryDeepCopyWith: deepCopier.\\n\\texternalName _ externalName veryDeepCopyWith: deepCopier.\\n\\tisPartsDonor _ isPartsDonor veryDeepCopyWith: deepCopier.\\n\\tactorState _ actorState veryDeepCopyWith: deepCopier.\\n\\tplayer _ player veryDeepCopyWith: deepCopier.\\t\\t\\\"Do copy the player of this morph\\\"\\n\\teventHandler _ eventHandler veryDeepCopyWith: deepCopier. \\t\\\"has its own restrictions\\\"\\n\\n\\totherProperties ifNil: [ ^self ].\\n\\n\\totherProperties := otherProperties copy.\\n\\tself propertyNamesNotCopied do: [ :propName | otherProperties removeKey: propName ifAbsent: [] ].\\n\\n\\tnamesOfWeaklyCopiedProperties _ self copyWeakly.\\n\\tweaklyCopiedValues _ namesOfWeaklyCopiedProperties collect: [ :propName | otherProperties removeKey: propName ifAbsent: [] ].\\n\\n\\t\\\"Now copy all the others.\\\"\\n\\totherProperties := otherProperties veryDeepCopyWith: deepCopier.\\n\\n\\t\\\"And replace the weak ones.\\\"\\n\\tnamesOfWeaklyCopiedProperties with: weaklyCopiedValues do: [ :name :value | value ifNotNil: [ otherProperties at: name put: value ]].\\n! !\\n\\n\\n!MorphExtension methodsFor: 'initialization' stamp: 'di 8/16/1998 12:02'!\\ninitialize\\n\\t\\\"Init all booleans to default values\\\"\\n\\tlocked _ false.\\n\\tvisible _ true.\\n\\tsticky _ false.\\n\\tisPartsDonor _ false.\\n! !\\n\\n\\n!MorphExtension methodsFor: 'object fileIn' stamp: 'dgd 2/16/2003 21:06'!\\nconvertProperty: aSymbol toValue: anObject \\n\\t\\\"These special cases move old properties into named fields of the \\n\\textension\\\"\\n\\taSymbol == #locked\\n\\t\\tifTrue: [^ locked _ anObject].\\n\\taSymbol == #visible\\n\\t\\tifTrue: [^ visible _ anObject].\\n\\taSymbol == #sticky\\n\\t\\tifTrue: [^ sticky _ anObject].\\n\\taSymbol == #balloonText\\n\\t\\tifTrue: [^ balloonText _ anObject].\\n\\taSymbol == #balloonTextSelector\\n\\t\\tifTrue: [^ balloonTextSelector _ anObject].\\n\\taSymbol == #actorState\\n\\t\\tifTrue: [^ actorState _ anObject].\\n\\taSymbol == #player\\n\\t\\tifTrue: [^ player _ anObject].\\n\\taSymbol == #name\\n\\t\\tifTrue: [^ externalName _ anObject].\\n\\t\\\"*renamed*\\\"\\n\\taSymbol == #partsDonor\\n\\t\\tifTrue: [^ isPartsDonor _ anObject].\\n\\t\\\"*renamed*\\\"\\n\\tself assureOtherProperties at: aSymbol put: anObject! !\\n\\n\\n!MorphExtension methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:45'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"inst vars have default booplean values.\\\"\\n\\n\\tlocked ifNil: [locked _ false].\\n\\tvisible ifNil: [visible _ true].\\n\\tsticky ifNil: [sticky _ false].\\n\\tisPartsDonor ifNil: [isPartsDonor _ false].\\n\\t^ self! !\\n\\n\\n!MorphExtension methodsFor: 'other' stamp: 'md 2/27/2006 08:39'!\\ninspectElement\\n\\t\\\"Create and schedule an Inspector on the otherProperties and the \\n\\tnamed properties.\\\"\\n\\t| key obj |\\n\\tkey _ (SelectionMenu selections: self sortedPropertyNames)\\n\\t\\t\\t\\tstartUpWithCaption: 'Inspect which property?'.\\n\\tkey\\n\\t\\tifNil: [^ self].\\n\\tobj _ otherProperties\\n\\t\\t\\t\\tat: key\\n\\t\\t\\t\\tifAbsent: ['nOT a vALuE'].\\n\\tobj = 'nOT a vALuE'\\n\\t\\tifTrue: [(self perform: key) inspect\\n\\t\\t\\t\\\"named properties\\\"]\\n\\t\\tifFalse: [obj inspect]! !\\n\\n!MorphExtension methodsFor: 'other' stamp: 'md 2/27/2006 08:42'!\\nisDefault\\n\\t\\\"Return true if the receiver is a default and can be omitted\\\"\\n\\tlocked == true\\n\\t\\tifTrue: [^ false].\\n\\tvisible == false\\n\\t\\tifTrue: [^ false].\\n\\tsticky == true\\n\\t\\tifTrue: [^ false].\\n\\tballoonText isNil\\n\\t\\tifFalse: [^ false].\\n\\tballoonTextSelector isNil\\n\\t\\tifFalse: [^ false].\\n\\texternalName isNil\\n\\t\\tifFalse: [^ false].\\n\\tisPartsDonor == true\\n\\t\\tifTrue: [^ false].\\n\\tactorState isNil\\n\\t\\tifFalse: [^ false].\\n\\tplayer isNil\\n\\t\\tifFalse: [^ false].\\n\\teventHandler isNil\\n\\t\\tifFalse: [^ false].\\n\\totherProperties ifNotNil: [otherProperties isEmpty ifFalse: [^ false]].\\n\\t^ true! !\\n\\n\\n!MorphExtension methodsFor: 'printing' stamp: 'md 2/27/2006 08:45'!\\nprintOn: aStream \\n\\t\\\"Append to the argument, aStream, a sequence of characters that \\n\\tidentifies the receiver.\\\" \\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' ' , self identityHashPrintString.\\n\\tlocked == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [locked] '].\\n\\tvisible == false\\n\\t\\tifTrue: [aStream nextPutAll: '[not visible] '].\\n\\tsticky == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [sticky] '].\\n\\tballoonText\\n\\t\\tifNotNil: [aStream nextPutAll: ' [balloonText] '].\\n\\tballoonTextSelector\\n\\t\\tifNotNil: [aStream nextPutAll: ' [balloonTextSelector: ' , balloonTextSelector printString , '] '].\\n\\texternalName\\n\\t\\tifNotNil: [aStream nextPutAll: ' [externalName = ' , externalName , ' ] '].\\n\\tisPartsDonor == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [isPartsDonor] '].\\n\\tplayer\\n\\t\\tifNotNil: [aStream nextPutAll: ' [player = ' , player printString , '] '].\\n\\teventHandler\\n\\t\\tifNotNil: [aStream nextPutAll: ' [eventHandler = ' , eventHandler printString , '] '].\\n\\t(otherProperties isNil or: [otherProperties isEmpty ]) ifTrue: [^ self].\\n\\taStream nextPutAll: ' [other: '.\\n\\tself otherProperties\\n\\t\\tkeysDo: [:aKey | aStream nextPutAll: ' (' , aKey , ' -> ' , (self otherProperties at: aKey) printString , ')'].\\n\\taStream nextPut: $]! !\\n\\n\\n!MorphExtension methodsFor: 'viewer' stamp: 'di 8/10/1998 14:47'!\\nexternalName\\n\\t^ externalName! !\\n\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:56'!\\nactorState\\n\\t\\\"answer the redeiver's actorState\\\"\\n\\t^ actorState ! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:53'!\\nactorState: anActorState \\n\\\"change the receiver's actorState\\\"\\n\\tactorState _ anActorState! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:42'!\\nplayer\\n\\t\\\"answer the receiver's player\\\"\\n\\t^ player! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:53'!\\nplayer: anObject \\n\\t\\\"change the receiver's player\\\"\\n\\tplayer _ anObject ! !\\n\\n\\n!MorphExtension methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 2/16/2003 21:37'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\t^ isPartsDonor! !\\n\\n!MorphExtension methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 2/16/2003 21:40'!\\nisPartsDonor: aBoolean \\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\tisPartsDonor _ aBoolean! !\\n\\n\\n!MorphExtension methodsFor: '*MorphicExtras-copying' stamp: 'md 2/27/2006 08:44'!\\nupdateReferencesUsing: aDictionary \\n\\t\\\"Update intra-morph references within a composite morph that \\n\\thas been copied. For example, if a button refers to morph X in \\n\\tthe orginal \\n\\tcomposite then the copy of that button in the new composite \\n\\tshould refer to \\n\\tthe copy of X in new composite, not the original X. This default \\n\\timplementation updates the contents of any morph-bearing slot.\\\"\\n\\n\\t| old |\\n\\teventHandler isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[self eventHandler: self eventHandler copy.\\n\\t\\t\\t1 to: self eventHandler class instSize\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\told := eventHandler instVarAt: i.\\n\\t\\t\\t\\t\\told isMorph \\n\\t\\t\\t\\t\\t\\tifTrue: [eventHandler instVarAt: i put: (aDictionary at: old ifAbsent: [old])]]].\\n\\totherProperties ifNotNil: [otherProperties associationsDo: [:assn | \\n\\t\\t\\t\\t\\tassn value: (aDictionary at: assn value ifAbsent: [assn value])]]! !\\nObject subclass: #MorphHierarchy\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphHierarchy methodsFor: 'private' stamp: 'dgd 9/26/2004 18:28'!\\nasMorph\\n\\t\\\"Answer the morph version of the receiver\\\"\\n\\t| morph |\\n\\tmorph := MorphHierarchyListMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\tlist: #roots\\n\\t\\t\\t\\tselected: nil\\n\\t\\t\\t\\tchangeSelected: #selected:.\\n\\t\\\"\\\"\\n\\t^ morph inAContainer! !\\n\\n\\n!MorphHierarchy methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:29'!\\nroots\\n\\t\\\"Answer the roots for the Object Hierarchy, that means answer the World\\\"\\n\\t^ {MorphListItemWrapper with: World}! !\\n\\n!MorphHierarchy methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:30'!\\nselected: aMorphListItemWrapper \\n\\t\\\"Change the selected object\\\"\\n\\t| newSelection |\\n\\taMorphListItemWrapper isNil\\n\\t\\tifTrue: [^ self].\\n\\tnewSelection := aMorphListItemWrapper withoutListWrapper.\\n\\tnewSelection == World selectedObject\\n\\t\\tifTrue: [newSelection removeHalo]\\n\\t\\tifFalse: [newSelection addHalo].\\n\\tself changed: #selected! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphHierarchy class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphHierarchy class methodsFor: 'opening' stamp: 'dgd 9/25/2004 21:50'!\\nopenOrDelete\\n\\t| oldMorph |\\n\\toldMorph := World submorphs\\n\\t\\t\\t\\tdetect: [:each | each hasProperty: #morphHierarchy]\\n\\t\\t\\t\\tifNone: [| newMorph | \\n\\t\\t\\t\\t\\tnewMorph := self new asMorph.\\n\\t\\t\\t\\t\\tnewMorph bottomLeft: ActiveHand position.\\n\\t\\t\\t\\t\\tnewMorph openInWorld.\\n\\t\\t\\t\\t\\tnewMorph isFullOnScreen\\n\\t\\t\\t\\t\\t\\tifFalse: [newMorph goHome].\\n\\t\\t\\t\\t\\t^ self].\\n\\t\\\"\\\"\\n\\toldMorph delete! !\\nSimpleHierarchicalListMorph subclass: #MorphHierarchyListMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphHierarchyListMorph methodsFor: 'private' stamp: 'dgd 9/26/2004 18:57'!\\ncreateContainer\\n\\t\\\"Private - Create a container\\\"\\n\\t| container |\\n\\tcontainer := BorderedMorph new.\\n\\tcontainer extent: (World extent * (1 / 4 @ (2 / 3))) rounded.\\n\\tcontainer layoutPolicy: TableLayout new.\\n\\tcontainer hResizing: #rigid.\\n\\tcontainer vResizing: #rigid.\\n\\tcontainer\\n\\t\\tsetColor: Preferences menuColor\\n\\t\\tborderWidth: Preferences menuBorderWidth\\n\\t\\tborderColor: Preferences menuBorderColor.\\n\\tcontainer layoutInset: 0.\\n\\t\\\"container useRoundedCorners.\\\"\\n\\t\\\"\\\"\\n\\tcontainer setProperty: #morphHierarchy toValue: true.\\n\\tcontainer setNameTo: 'Objects Hierarchy' translated.\\n\\t\\\"\\\"\\n\\t^ container! !\\n\\n!MorphHierarchyListMorph methodsFor: 'private' stamp: 'dgd 9/26/2004 18:27'!\\ninAContainer\\n\\t\\\"Answer the receiver contained in a proper container\\\"\\n\\t| container |\\n\\tcontainer := self createContainer.\\n\\tcontainer addMorphBack: self.\\n\\t\\\" \\n\\tnasty hack to force the scroolbar recreation\\\"\\n\\tself extent: container extent - container borderWidth.\\n\\t\\\"\\\"\\n\\t^ container! !\\n\\n\\n!MorphHierarchyListMorph methodsFor: 'initialization' stamp: 'dgd 9/26/2004 18:18'!\\non: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel \\n\\tsuper\\n\\t\\ton: anObject\\n\\t\\tlist: getListSel\\n\\t\\tselected: getSelectionSel\\n\\t\\tchangeSelected: setSelectionSel\\n\\t\\tmenu: getMenuSel\\n\\t\\tkeystroke: keyActionSel.\\n\\t\\\"\\\"\\n\\tself borderWidth: 0.\\n\\tself autoDeselect: false.\\n\\tself enableDrag: false.\\n\\tself enableDrop: true.\\n\\tself hResizing: #spaceFill.\\n\\tself vResizing: #spaceFill.\\nself expandRoots! !\\n\\n\\n!MorphHierarchyListMorph methodsFor: 'selection' stamp: 'dgd 9/25/2004 21:28'!\\nsetSelectedMorph: aMorph \\n\\tsuper setSelectedMorph: aMorph.\\nself owner isNil ifFalse:[self owner delete]! !\\nListItemWrapper subclass: #MorphListItemWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphListItemWrapper methodsFor: 'converting' stamp: 'dgd 9/26/2004 18:26'!\\nasString\\n\\t\\\"Answer the string representation of the receiver\\\"\\n\\t^ item externalName! !\\n\\n\\n!MorphListItemWrapper methodsFor: 'accessing' stamp: 'dgd 1/7/2005 20:01'!\\ncontents\\n\\t\\\"Answer the receiver's contents\\\"\\n\\n\\t| tentative submorphs |\\n\\ttentative := item submorphs\\n\\t\\t\\t\\tcollect: [:each | each renderedMorph].\\n\\n\\tsubmorphs := Preferences noviceMode\\n\\t\\t\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\t\\t\\ttentative\\n\\t\\t\\t\\t\\t\\treject: [:each | \\\"\\\"\\n\\t\\t\\t\\t\\t\\t\\teach isSystemWindow\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isDockingBar]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isKindOf: HaloMorph]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each hasProperty: #morphHierarchy]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isFlapOrTab]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isObjectsTool]]]\\n\\t\\t\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\t\\t\\ttentative\\n\\t\\t\\t\\t\\t\\treject: [:each | each isKindOf: HaloMorph]].\\n\\n\\t^ submorphs\\n\\t\\tcollect: [:each | self class with: each]! !\\n\\n!MorphListItemWrapper methodsFor: 'accessing' stamp: 'dgd 7/28/2005 13:03'!\\nicon\\n\\t\\\"Answer a form to be used as icon\\\"\\n\\t^ item iconOrThumbnailOfSize: ((Preferences tinyDisplay ifTrue: [16] ifFalse: [28]))! !\\nObjectOut subclass: #MorphObjectOut\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 4/6/1999 10:00'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Bring in the object, install, then resend aMessage\\\"\\n\\t| aMorph myUrl oldFlag response |\\n\\t\\\"Transcript show: thisContext sender selector; cr.\\\" \\\"useful for debugging\\\"\\n\\toldFlag _ recursionFlag.\\n\\trecursionFlag _ true.\\n\\tmyUrl _ url.\\t\\\"can't use inst vars after become\\\"\\n\\t\\\"fetch the object\\\"\\n\\taMorph _ self xxxFetch.\\t\\t\\\"watch out for the become!!\\\"\\n\\t\\t\\t\\\"Now we ARE a MORPH\\\"\\n\\toldFlag == true ifTrue: [\\n\\t\\tresponse _ (PopUpMenu labels: 'proceed normally\\\\debug' withCRs)\\n\\t\\t\\tstartUpWithCaption: 'Object being fetched for a second time.\\nShould not happen, and needs to be fixed later.'.\\n\\t\\tresponse = 2 ifTrue: [self halt]].\\t\\\"We are already the new object\\\"\\n\\n\\taMorph setProperty: #SqueakPage toValue: \\n\\t\\t\\t(SqueakPageCache pageCache at: myUrl).\\n\\t\\\"Can't be a super message, since this is the first message sent to this object\\\"\\n\\t^ aMorph perform: aMessage selector withArguments: aMessage arguments\\n! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 10/22/1998 15:43'!\\nfullReleaseCachedState\\n\\t\\\"do nothing, especially don't bring in my object!!\\\"! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 2/24/1999 00:08'!\\nsmallThumbnailForPageSorter\\n\\n\\t^ self sqkPage thumbnail! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 2/24/1999 00:09'!\\nthumbnailForPageSorter\\n\\n\\t^ self sqkPage thumbnail! !\\nTestCase subclass: #MorphTest\\n\\tinstanceVariableNames: 'morph world'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicTests-Kernel'!\\n!MorphTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class Morph. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\ngetWorld\\n\\t^ world\\n\\t\\tifNil: [world := Project newMorphic world]! !\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\nsetUp\\n\\tmorph := Morph new! !\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\ntearDown\\n\\tmorph delete.\\n\\tworld\\n\\t\\tifNotNil: [Project deletingProject: world project]! !\\n\\n\\n!MorphTest methodsFor: 'testing - classification' stamp: 'md 4/16/2003 17:11'!\\ntestIsMorph\\n\\tself assert: (morph isMorph).! !\\n\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:31'!\\ntestOverlapAny\\n\\t\\\"self debug: #testOverlapAny\\\"\\n\\t| p1 p2 |\\n\\tp1 _ Morph new assuredPlayer.\\n\\tp2 _ EllipseMorph new assuredPlayer.\\n\\t\\\"Same position\\\"\\n\\tp1 costume position: 0@0.\\n\\tp2 costume position: 0@0.\\n\\tself assert: (p1 overlapsAny: p2).\\n\\t\\\"Different position\\\"\\n\\tp1 costume position: 0@0.\\n\\tp2 costume position: 500@0.\\n\\tself assert: (p1 overlapsAny: p2) not.! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:56'!\\ntestOverlapAnyDeletedPlayer\\n\\t\\\"self debug: #testOverlapAnyDeletedPlayer\\\"\\n\\t| me friend sibling |\\n\\tme := Morph new assuredPlayer assureUniClass; yourself.\\n\\tfriend := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tsibling := friend getNewClone.\\n\\tsibling costume delete.\\n\\tself getWorld addMorph: me costume.\\n\\t\\\"Same position but deleted\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 0 @ 0.\\n\\tsibling costume position: 0 @ 0.\\n\\tself assert: (me overlapsAny: friend) not.\\n\\tself assert: (me overlapsAny: sibling) not! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:40'!\\ntestOverlapAnyScriptedPlayer\\n\\t\\\"self debug: #testOverlapAnyScriptedPlayer\\\"\\n\\t| me friend other sibling |\\n\\tme := Morph new assuredPlayer assureUniClass; yourself.\\n\\tfriend := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tsibling := friend getNewClone.\\n\\tother := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tself getWorld addMorph: me costume;\\n\\t\\t addMorph: friend costume;\\n\\t\\t addMorph: other costume;\\n\\t\\t addMorph: sibling costume.\\n\\t\\\"myself\\\"\\n\\tself assert: (me overlapsAny: me) not.\\n\\t\\\"Same position with sibling\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 500 @ 0.\\n\\tother costume position: 500 @ 0.\\n\\tsibling costume position: 0@0.\\n\\tself assert: (me overlapsAny: friend).\\n\\t\\\"Different position with sibling but same class\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 500 @ 0.\\n\\tsibling costume position: 500@ 0.\\n\\tother costume position: 0 @ 0.\\n\\tself assert: (me overlapsAny: friend) not! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:32'!\\ntestOverlapAnyUnscriptedPlayer\\n\\t\\\"self debug: #testOverlapAnyUnscriptedPlayer\\\"\\n\\t| p1 p2 p3 |\\n\\tp1 := Morph new assuredPlayer.\\n\\tp2 := EllipseMorph new assuredPlayer.\\n\\tp3 := EllipseMorph new assuredPlayer.\\n\\tself getWorld addMorph: p1 costume;\\n\\t\\t addMorph: p2 costume;\\n\\t\\t addMorph: p3 costume.\\n\\t\\\"Same class, same position\\\"\\n\\tp1 costume position: 0 @ 0.\\n\\tp2 costume position: 500 @ 0.\\n\\tp3 costume position: 0 @ 0.\\n\\tself\\n\\t\\tassert: (p1 overlapsAny: p2).\\n\\t\\\"Same class, different position\\\"\\n\\tp1 costume position: 0 @ 0.\\n\\tp2 costume position: 1000 @ 0.\\n\\tp3 costume position: 500 @ 0.\\n\\tself assert: (p1 overlapsAny: p2) not.\\n! !\\n\\n\\n!MorphTest methodsFor: 'testing - initialization' stamp: 'md 4/16/2003 17:10'!\\ntestOpenInWorld\\n\\tself shouldnt: [morph openInWorld] raise: Error.! !\\n\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/4/2003 00:11'!\\ntestIntoWorldCollapseOutOfWorld\\n\\t| m1 m2 collapsed |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"add them to basic morph\\\"\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"open the guy\\\"\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"collapse it\\\"\\n\\tcollapsed := \\tCollapsedMorph new beReplacementFor: morph.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\n\\t\\\"expand it\\\"\\n\\tcollapsed collapseOrExpand.\\n\\tself assert: (m1 intoWorldCount = 2).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 2).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\n\\t\\\"delete it\\\"\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 2).\\n\\tself assert: (m1 outOfWorldCount = 2).\\n\\tself assert: (m2 intoWorldCount = 2).\\n\\tself assert: (m2 outOfWorldCount = 2).\\n! !\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/4/2003 00:12'!\\ntestIntoWorldDeleteOutOfWorld\\n\\t| m1 m2 |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\t! !\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/10/2003 18:30'!\\ntestIntoWorldTransferToNewGuy\\n\\t| m1 m2 |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tm2 addMorphFront: m1.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n! !\\nSketchMorph subclass: #MorphThumbnail\\n\\tinstanceVariableNames: 'morphRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Books'!\\n!MorphThumbnail commentStamp: '<historical>' prior: 0!\\nA morph whose appearance is a thumbnail of some other morph.!\\n\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 11/13/1998 09:53'!\\ncomputeThumbnail\\n\\t\\\"Assumption on entry:\\n The receiver's width represents the maximum width allowable.\\n The receiver's height represents the exact height desired.\\\"\\n\\n\\t| f scaleX scaleY |\\n\\tf _ morphRepresented imageForm.\\n\\tmorphRepresented fullReleaseCachedState.\\n\\tscaleY _ self height / f height. \\\"keep height invariant\\\"\\n\\tscaleX _ ((morphRepresented width * scaleY) <= self width)\\n\\t\\tifTrue:\\n\\t\\t\\t[scaleY] \\\"the usual case; same scale factor, to preserve aspect ratio\\\"\\n\\t\\tifFalse:\\n\\t\\t\\t[self width / f width].\\n\\tself form: (f magnify: f boundingBox by: (scaleX @ scaleY) smoothing: 2).\\n\\tself extent: originalForm extent! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 7/6/1998 22:08'!\\ngrabOriginal\\n\\tself primaryHand attachMorph: morphRepresented! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'ar 10/7/2000 15:38'!\\nmorphRepresented: aMorph\\n\\n\\tmorphRepresented _ aMorph.\\n\\tself computeThumbnail.\\n! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'md 10/22/2003 15:24'!\\nrevealOriginal\\n\\t((owner isKindOf: PasteUpMorph) and: [owner alwaysShowThumbnail]) \\n\\t\\tifTrue: [^Beeper beep].\\n\\tmorphRepresented owner isNil \\n\\t\\tifTrue: [^owner replaceSubmorph: self by: morphRepresented].\\n\\tBeeper beep! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 8/10/1998 07:05'!\\nsmaller\\n\\tself form: (self form copy: (0@0 extent: self form extent // 2))! !\\n\\n\\n!MorphThumbnail methodsFor: 'copying' stamp: 'tk 1/8/1999 09:39'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If target and arguments fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\nsuper veryDeepFixupWith: deepCopier.\\nmorphRepresented _ deepCopier references at: morphRepresented \\n\\t\\tifAbsent: [morphRepresented].! !\\n\\n!MorphThumbnail methodsFor: 'copying' stamp: 'tk 1/8/1999 09:39'!\\nveryDeepInner: deepCopier\\n\\t\\\"Copy all of my instance variables. Some need to be not copied at all, but shared. \\tWarning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.\\\"\\n\\nsuper veryDeepInner: deepCopier.\\nmorphRepresented _ morphRepresented.\\t\\t\\\"Weakly copied\\\"! !\\n\\n\\n!MorphThumbnail methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGray! !\\n\\n!MorphThumbnail methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:51'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\t| f |\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\n\\tf _ Form extent: 60 @ 80 depth: Display depth.\\n\\tf fill: f boundingBox fillColor: color.\\n\\tself form: f! !\\n\\n\\n!MorphThumbnail methodsFor: 'menus' stamp: 'dgd 8/30/2003 21:53'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'reveal original morph' translated action: #revealOriginal.\\n\\taCustomMenu add: 'grab original morph' translated action: #grabOriginal.\\n! !\\n\\n\\n!MorphThumbnail methodsFor: 'naming' stamp: 'bf 3/31/1999 12:24'!\\ninnocuousName\\n\\t^ morphRepresented isNil\\n\\t\\tifTrue: [super innocuousName]\\n\\t\\tifFalse: [morphRepresented innocuousName]! !\\n\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'dgd 2/16/2003 21:37'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\t^ self partRepresented isPartsDonor! !\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'dgd 2/16/2003 21:40'!\\nisPartsDonor: aBoolean\\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\tself partRepresented isPartsDonor: aBoolean! !\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'ar 10/6/2000 22:46'!\\npartRepresented\\n\\t^self morphRepresented! !\\n\\n\\n!MorphThumbnail methodsFor: 'thumbnail' stamp: 'jm 11/17/97 17:30'!\\nmorphRepresented\\n\\n\\t^ morphRepresented\\n! !\\n\\n!MorphThumbnail methodsFor: 'thumbnail' stamp: 'bf 3/31/1999 07:54'!\\nrepresentativeNoTallerThan: maxHeight norWiderThan: maxWidth thumbnailHeight: thumbnailHeight\\n\\n\\t\\\"Return a morph representing the receiver but which is no taller than aHeight. If the receiver is already small enough, just return it, else return a MorphThumbnail companioned to the receiver, enforcing the maxWidth\\\"\\n\\n\\t(self height <= maxHeight and: [self width <= maxWidth]) ifTrue: [^ self].\\n\\n\\t^ MorphThumbnail new\\n\\t\\textent: maxWidth @ (thumbnailHeight min: self height);\\n\\t\\tmorphRepresented: morphRepresented! !\\nListItemWrapper subclass: #MorphWithSubmorphsWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!MorphWithSubmorphsWrapper commentStamp: 'ls 3/1/2004 17:32' prior: 0!\\nDisplay a morph in a SimpleHierarchicalListMorph, and arrange to recursively display the morph's submorphs. The \\\"item\\\" that is wrapped is the morph to display.!\\n\\n\\n!MorphWithSubmorphsWrapper methodsFor: 'hierarchy' stamp: 'ls 3/1/2004 17:34'!\\ncontents\\n\\t^item submorphs collect: [ :m |\\n\\t\\tself class with: m ]! !\\nController subclass: #MorphWorldController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-ST80'!\\n!MorphWorldController commentStamp: '<historical>' prior: 0!\\nI am a controller for SceneViews. I support gestures for scrolling, click-selection, and area selection of scene glyphs. (See the class comment in GestureController for more details about gestures.) I also support construction operations such as inserting new glyphs and merging glyphs to make them share a common point.\\n\\nThe mapping of gestures to actions is as follows (see GestureController comment for more about gestures):\\n\\n Click:\\n\\tclick on glyph\\t\\t\\t\\tselect glyph\\n\\tshift-click on glyph\\t\\t\\ttoggle selection of that glyph\\n\\tclick on background\\t\\t\\tclear selection\\n Double click:\\n\\tdouble-click on glyph\\t\\t\\tinspect glyph\\n\\tdouble-click on background\\t\\tselect all\\n Hold/Drag/Sweep:\\n\\thold (no movement)\\t\\t\\tyellow-button menu\\n\\tdrag (up/left movement)\\t\\tscrolling hand\\n\\tsweep (down/right movement)\\tselect glyphs in region\\n\\tshift-sweep\\t\\t\\t\\t\\ttoggle selection of glyphs in region\\n!\\n\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/26/1999 10:00'!\\ncontrolInitialize\\n\\t\\\"This window is becoming active.\\\"\\n\\n\\ttrue ifTrue: [model becomeTheActiveWorldWith: nil].\\n\\n\\tmodel canvas ifNil: [ \\\"i.e., only on first entry\\\"\\n\\t\\t\\\"In case of, eg, inspect during balloon help...\\\"\\n\\t\\tmodel submorphsDo: [:m | \\\"delete any existing balloons\\\"\\n\\t\\t\\t(m isKindOf: BalloonMorph) ifTrue: [m delete]].\\n\\n\\t\\tmodel handsDo: [:h | h initForEvents].\\n\\t\\tview displayView]. \\\"initializes the WorldMorph's canvas\\\"\\n! !\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/16/2001 22:43'!\\ncontrolLoop \\n\\t\\\"Overridden to keep control active when the hand goes out of the view\\\"\\n\\n\\t| db |\\n\\t[self viewHasCursor \\\"working in the window\\\"\\n\\t\\tor: [Sensor noButtonPressed \\\"wandering with no button pressed\\\"\\n\\t\\tor: [model primaryHand submorphs size > 0 \\\"dragging something outside\\\"]]]\\n\\t\\twhileTrue: \\\"... in other words anything but clicking outside\\\"\\n\\t\\t\\t[self controlActivity.\\n\\n\\t\\t\\t\\\"Check for reframing since we hold control here\\\"\\n\\t\\t\\tdb _ view superView displayBox.\\n\\t\\t\\tview superView controller checkForReframe.\\n\\t\\t\\tdb = view superView displayBox ifFalse:\\n\\t\\t\\t\\t[self controlInitialize \\\"reframe world if bounds changed\\\"]].\\n! !\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/16/2001 13:58'!\\ncontrolTerminate \\n\\t\\\"This window is becoming inactive; restore the normal cursor.\\\"\\n\\n\\tCursor normal show.\\n\\tActiveWorld _ ActiveHand _ ActiveEvent _ nil! !\\n\\n\\n!MorphWorldController methodsFor: 'control defaults' stamp: 'jm 2/20/98 13:37'!\\ncontrolActivity\\n\\t\\\"Do one step of the Morphic interaction loop. Called repeatedly while window is active.\\\"\\n\\n\\tmodel doOneCycle.\\n! !\\n\\n!MorphWorldController methodsFor: 'control defaults' stamp: 'jm 6/17/97 10:29'!\\nisControlActive\\n\\n\\t^ sensor redButtonPressed or: [self viewHasCursor]! !\\nView subclass: #MorphWorldView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'FullColorWhenInactive'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-ST80'!\\n!MorphWorldView commentStamp: '<historical>' prior: 0!\\nI am a view used to display a Scene. I may be scrolled by adjusting my offset. My default controller is SceneController.\\n\\nSceneViews encapsulate the notion of a changing foreground and a fixed background during interactive updates. During an interaction (such as dragging), some of the glyphs will not change location or appearance. These are part of the \\\"background\\\". All glyphs that may change (the \\\"foreground\\\" glyphs) are painted against this unchanging backdrop during the interaction.\\n\\nInstance Variables:\\n\\toffset\\t\\t\\t\\tthe current offset of this view (used for scrolling)\\n\\tenclosingRect \\t\\ta rectangle large enough to contain all the objects in the scene, plus a small border (this is a cache that must be recomputed when glyphs are moved, added, or removed from the scene)\\n\\tbackgroundForm\\t\\ta <Form> containing the fixed background\\n\\tvisibleForeground\\t\\tthe glyphs that are changing but not selected during an interaction\\n\\tselectedForeground\\tthe selected glyphs that are changing during an interaction!\\n\\n\\n!MorphWorldView methodsFor: 'as yet unclassified' stamp: 'md 2/24/2006 21:24'!\\nupdateSubWindowExtent\\n\\t\\\"If this MorphWorldView represents a single Morphic SystemWindow, then update that window to match the size of the WorldView.\\\"\\n\\n\\t| numMorphs subWindow |\\n\\tnumMorphs := model submorphs size.\\n\\t\\\"(Allow for the existence of an extra NewHandleMorph (for resizing).)\\\"\\n\\t(numMorphs = 0 or: [numMorphs > 2]) ifTrue: [^self].\\n\\tsubWindow := model submorphs detect: [:ea | ea respondsTo: #label]\\n\\t\\t\\t\\tifNone: [^self].\\n\\tsuperView label = subWindow label ifFalse: [^self].\\n\\tsubWindow position: model position + (0 @ -16).\\t\\\"adjust for WiW changes\\\"\\n\\tsubWindow extent: model extent - (0 @ -16).\\n\\tsubWindow isActive ifFalse: [subWindow activate]! !\\n\\n\\n!MorphWorldView methodsFor: 'controller access'!\\ndefaultControllerClass\\n\\n\\t^ MorphWorldController! !\\n\\n\\n!MorphWorldView methodsFor: 'deEmphasizing' stamp: 'RAA 5/24/2000 10:34'!\\ndeEmphasizeView \\n\\t\\\"This window is becoming inactive.\\\"\\n\\n\\tCursor normal show. \\\"restore the normal cursor\\\"\\n\\tmodel deEmphasizeViewMVC: self topView cacheBitsAsTwoTone.\\n! !\\n\\n\\n!MorphWorldView methodsFor: 'displaying' stamp: 'dew 11/8/1999 02:01'!\\ndisplayView\\n\\t\\\"This method is called by the system when the top view is framed or moved.\\\"\\n\\t| topView |\\n\\tmodel viewBox: self insetDisplayBox.\\n\\tself updateSubWindowExtent.\\n\\ttopView _ self topView.\\n\\t(topView == ScheduledControllers scheduledControllers first view\\n\\t\\tor: [topView cacheBitsAsTwoTone not])\\n\\t\\tifTrue: [model displayWorldSafely]\\n\\t\\tifFalse: [model displayWorldAsTwoTone]. \\\"just restoring the screen\\\"! !\\n\\n\\n!MorphWorldView methodsFor: 'updating' stamp: 'sw 9/26/97 20:56'!\\nupdate: symbol\\n\\n\\t^ symbol == #newColor\\n\\t\\tifTrue: [self topView backgroundColor: model color dominantColor; uncacheBits; display]\\n\\t\\tifFalse: [super update: symbol].\\n! !\\n\\n\\n!MorphWorldView methodsFor: 'private' stamp: 'dew 11/8/1999 02:00'!\\ncomputeInsetDisplayBox\\n\\t\\\"This overrides the same method in View. (It avoids using displayTransform: because it can return inaccurate results, causing a MorphWorldView's inset display box to creep inward when resized.)\\\"\\n\\n\\t^superView insetDisplayBox insetBy: borderWidth! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphWorldView class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'nk 7/30/2004 21:52'!\\nconvertToMVCWiWPasteUpMorph\\n\\t\\\"\\nMorphWorldView convertToMVCWiWPasteUpMorph\\n\\\"\\n\\n\\t| current w newModel topView |\\n\\tSmalltalk isMorphic ifTrue: [^self inform: 'do this in MVC'].\\n\\tcurrent := self allInstances \\n\\t\\t\\t\\tselect: [:each | each model class == PasteUpMorph].\\n\\tcurrent do: \\n\\t\\t\\t[:oldWorldView | \\n\\t\\t\\tw := MVCWiWPasteUpMorph newWorldForProject: nil.\\n\\t\\t\\tw\\n\\t\\t\\t\\tcolor: oldWorldView model color;\\n\\t\\t\\t\\taddAllMorphs: oldWorldView model submorphs.\\n\\t\\t\\tnewModel := CautiousModel new initialExtent: 300 @ 300.\\n\\t\\t\\ttopView := self fullColorWhenInactive \\n\\t\\t\\t\\t\\t\\tifTrue: [ColorSystemView new]\\n\\t\\t\\t\\t\\t\\tifFalse: [StandardSystemView new].\\n\\t\\t\\ttopView\\n\\t\\t\\t\\tmodel: newModel;\\n\\t\\t\\t\\tlabel: oldWorldView topView label;\\n\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\taddSubView: (self new model: w);\\n\\t\\t\\t\\tbackgroundColor: w color.\\n\\t\\t\\ttopView controller openNoTerminate.\\n\\t\\t\\ttopView reframeTo: (oldWorldView topView expandedFrame \\n\\t\\t\\t\\t\\t\\texpandBy: (0 @ 0 extent: 0 @ topView labelHeight)).\\n\\t\\t\\toldWorldView topView controller closeAndUnscheduleNoTerminate].\\n\\tScheduledControllers restore.\\n\\tProcessor terminateActive! !\\n\\n!MorphWorldView class methodsFor: 'instance creation'!\\nfullColorWhenInactive\\n\\n\\tFullColorWhenInactive ifNil: [FullColorWhenInactive _ true].\\n\\t^ FullColorWhenInactive\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'di 2/26/98 09:17'!\\nfullColorWhenInactive: fullColor\\n\\t\\\"MorphWorldView fullColorWhenInactive: true\\\"\\n\\t\\\"If FullColorWhenInactive is true then WorldMorphViews will created inside StandardSystemViews that cache their contents in full-color when the window is inactive. If it is false, only a half-tone gray approximation of the colors will be cached to save space.\\\"\\n\\n\\tFullColorWhenInactive _ fullColor.\\n\\n\\t\\\"Retroactively convert all extant windows\\\"\\n\\t((fullColor ifTrue: [StandardSystemView] ifFalse: [ColorSystemView])\\n\\t\\tallInstances select:\\n\\t\\t\\t[:v | v subViews notNil and: [v subViews isEmpty not and: [v firstSubView isKindOf: MorphWorldView]]])\\n\\t\\tdo: [:v | v uncacheBits.\\n\\t\\t\\tv controller toggleTwoTone]! !\\n\\n!MorphWorldView class methodsFor: 'instance creation'!\\nopenOn: aMorphWorld\\n\\t\\\"Open a view on the given WorldMorph.\\\"\\n\\n\\tself openOn: aMorphWorld label: 'A Morphic World'.! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sw 10/2/97 23:17'!\\nopenOn: aWorldMorph label: aString\\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\t^ self openOn: aWorldMorph label: aString model: (CautiousModel new initialExtent: aWorldMorph initialExtent)! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sw 9/21/1998 17:54'!\\nopenOn: aWorldMorph label: aString cautionOnClose: aBoolean\\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\t| aModel |\\n\\taModel _ aBoolean\\n\\t\\tifTrue:\\t\\t[CautiousModel new]\\n\\t\\tifFalse:\\t\\t[WorldViewModel new].\\n\\t^ self openOn: aWorldMorph label: aString model: (aModel initialExtent: aWorldMorph initialExtent)! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'jm 1/31/98 20:24'!\\nopenOn: aWorldMorph label: aString extent: aPoint\\n\\t\\\"Open a view with the given label and extent on the given WorldMorph.\\\"\\n\\n\\t^ self openOn: aWorldMorph\\n\\t\\tlabel: aString\\n\\t\\tmodel: (CautiousModel new initialExtent: aPoint)\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'nk 7/30/2004 22:37'!\\nopenOn: aWorldMorph label: aString model: aModel \\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\n\\t| topView |\\n\\ttopView := self fullColorWhenInactive \\n\\t\\t\\t\\tifTrue: [topView := ColorSystemView new]\\n\\t\\t\\t\\tifFalse: [topView := StandardSystemView new].\\n\\ttopView\\n\\t\\tmodel: aModel;\\n\\t\\tlabel: aString;\\n\\t\\tborderWidth: 1;\\n\\t\\taddSubView: (self new model: aWorldMorph);\\n\\t\\tbackgroundColor: aWorldMorph color.\\n\\t\\\"minimumSize: aWorldMorph extent + (2@2); \\\"\\t\\\"add border width\\\"\\n\\ttopView controller open! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'di 11/26/1999 11:46'!\\nopenWorld\\n\\n\\t| w |\\n\\t(w _ MVCWiWPasteUpMorph newWorldForProject: nil).\\n\\tw bounds: (0@0 extent: 400@300).\\n\\tself openOn: w\\n\\t\\tlabel: 'A Morphic World'\\n\\t\\textent: w fullBounds extent + 2.\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sma 6/12/2000 14:18'!\\nopenWorldWith: aMorph labelled: labelString\\n\\n\\t| w |\\n\\t(w _ MVCWiWPasteUpMorph newWorldForProject: nil) addMorph: aMorph.\\n\\tw extent: aMorph fullBounds extent.\\n\\tw startSteppingSubmorphsOf: aMorph.\\n\\tself openOn: w\\n\\t\\tlabel: labelString\\n\\t\\textent: w fullBounds extent + 2.\\n! !\\nMessageSend subclass: #MorphicAlarm\\n\\tinstanceVariableNames: 'scheduledTime numArgs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MorphicAlarm methodsFor: 'accessing' stamp: 'ar 9/11/2000 16:44'!\\nscheduledTime\\n\\t\\\"Return the time (in milliseconds) that the receiver is scheduled to be executed\\\"\\n\\t^scheduledTime! !\\n\\n!MorphicAlarm methodsFor: 'accessing' stamp: 'ar 9/11/2000 16:45'!\\nscheduledTime: msecs\\n\\t\\\"Set the time (in milliseconds) that the receiver is scheduled to be executed\\\"\\n\\tscheduledTime _ msecs! !\\n\\n\\n!MorphicAlarm methodsFor: 'evaluating' stamp: 'ar 10/22/2000 17:36'!\\nvalue: anArgument\\n\\t| nArgs |\\n\\tnumArgs ifNil:[numArgs _ selector numArgs].\\n\\tnArgs _ arguments ifNil:[0] ifNotNil:[arguments size].\\n\\tnArgs = numArgs ifTrue:[\\n\\t\\t\\\"Ignore extra argument\\\"\\n\\t\\t^self value].\\n\\t^arguments isNil\\n\\t\\tifTrue: [receiver perform: selector with: anArgument]\\n\\t\\tifFalse: [receiver perform: selector withArguments: (arguments copyWith: anArgument)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicAlarm class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicAlarm class methodsFor: 'instance creation' stamp: 'ar 9/11/2000 16:44'!\\nscheduledAt: scheduledTime receiver: aTarget selector: aSelector arguments: argArray\\n\\t^(self receiver: aTarget selector: aSelector arguments: argArray)\\n\\t\\tscheduledTime: scheduledTime.! !\\nObject subclass: #MorphicEvent\\n\\tinstanceVariableNames: 'timeStamp source'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n!MorphicEvent commentStamp: '<historical>' prior: 0!\\nThis class represents the base for all events.\\n\\nInstance variables:\\n\\tstamp\\t<Integer>\\tThe millisecond clock time stamp (based on Time millisecondClock)\\n\\tsource\\t<Hand | nil>\\tIf non-nil the hand that generated the event.!\\n\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 21:28'!\\ncursorPoint\\n\\t\\\"Backward compatibility. Use #position instead\\\"\\n\\t^ self position! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 16:48'!\\nhand\\n\\t\\\"Return the source that generated the event\\\"\\n\\t^source! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'wiz 12/8/2004 23:13'!\\nposition\\n\\t\\\"Since cursorPoint is defined and refers to position it should be defined\\n\\there as well\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 15:29'!\\ntimeStamp\\n\\t\\\"Return the millisecond clock value at which the event was generated\\\"\\n\\t^timeStamp ifNil:[timeStamp _ Time millisecondClockValue]! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 15:34'!\\ntype\\n\\t\\\"Return a symbol indicating the type this event.\\\"\\n\\t^self subclassResponsibility! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 01:19'!\\nwasHandled\\n\\t\\\"Return true if this event was handled. May be ignored for some types of events.\\\"\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 01:20'!\\nwasHandled: aBool\\n\\t\\\"Determine if this event was handled. May be ignored for some types of events.\\\"! !\\n\\n\\n!MorphicEvent methodsFor: 'comparing' stamp: 'ar 9/13/2000 15:36'!\\n= anEvent\\n\\tanEvent isMorphicEvent ifFalse:[^false].\\n\\t^self type = anEvent type! !\\n\\n!MorphicEvent methodsFor: 'comparing' stamp: 'ar 9/13/2000 15:36'!\\nhash\\n\\t^self type hash! !\\n\\n\\n!MorphicEvent methodsFor: 'dispatching' stamp: 'ar 9/15/2000 21:12'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\t^anObject handleUnknownEvent: self! !\\n\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/10/2000 01:18'!\\ncopyHandlerState: anEvent\\n\\t\\\"Copy the handler state from anEvent. Used for quickly transferring handler information between transformed events.\\\"\\n! !\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/10/2000 01:18'!\\nresetHandlerFields\\n\\t\\\"Reset anything that is used to cross-communicate between two eventual handlers during event dispatch\\\"! !\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:21'!\\ntype: eventType readFrom: aStream\\n\\t\\\"Read a MorphicEvent from the given stream.\\\"\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 16:05'!\\nconvertOctober2000: varDict using: smartRefStrm\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\t\\\"These are going away #('type' 'cursorPoint' 'buttons' 'keyValue' 'sourceHand'). Possibly store their info in another variable?\\\"\\n\\t| type cursorPoint buttons keyValue sourceHand |\\n\\ttype _ varDict at: 'type'.\\n\\tcursorPoint _ varDict at: 'cursorPoint'.\\n\\tbuttons _ varDict at: 'buttons'.\\n\\tkeyValue _ varDict at: 'keyValue'.\\n\\tsourceHand _ varDict at: 'sourceHand'.\\n\\ttype == #mouseMove ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: cursorPoint\\n\\t\\t\\tendPoint: cursorPoint\\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: sourceHand \\n\\t\\t\\tstamp: nil].\\n\\t(type == #mouseDown) | (type == #mouseUp) ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: cursorPoint\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: sourceHand\\n\\t\\t\\t\\tstamp: nil].\\n\\t(type == #keystroke) | (type == #keyDown) | (type == #keyUp) ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: cursorPoint\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: sourceHand\\n\\t\\t\\tstamp: nil].\\n\\t\\\"All others will be handled there\\\"\\n\\t^MorphicUnknownEvent new! !\\n\\n\\n!MorphicEvent methodsFor: 'objects from disk' stamp: 'RAA 12/21/2000 11:35'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\t| answer |\\n\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\tvarDict at: 'cursorPoint' ifPresent: [ :x | \\n\\t\\tanswer _ self convertOctober2000: varDict using: smartRefStrm.\\n\\t\\tvarDict removeKey: 'cursorPoint'.\\t\\\"avoid doing this again\\\"\\n\\t\\t^answer\\n\\t].\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/22/2000 10:36'!\\nisDraggingEvent\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:17'!\\nisDropEvent\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:19'!\\nisKeyboard\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 10/10/2000 21:27'!\\nisKeystroke\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:37'!\\nisMorphicEvent\\n\\t^true! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:19'!\\nisMouse\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/14/2000 18:21'!\\nisMouseOver\\n\\t^self type == #mouseOver! !\\n\\n\\n!MorphicEvent methodsFor: 'transforming' stamp: 'ar 9/13/2000 15:47'!\\ntransformedBy: aMorphicTransform\\n\\t\\\"Return the receiver transformed by the given transform into a local coordinate system.\\\"\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'private' stamp: 'ar 10/25/2000 21:26'!\\nsetHand: aHand\\n\\tsource _ aHand! !\\n\\n!MorphicEvent methodsFor: 'private' stamp: 'ar 10/25/2000 20:53'!\\nsetTimeStamp: stamp\\n\\ttimeStamp _ stamp.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 00:44'!\\nconvertObsolete: anEvent\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\t| type cursorPoint buttons keyValue sourceHand |\\n\\ttype _ anEvent type.\\n\\tcursorPoint _ anEvent cursorPoint.\\n\\tbuttons _ anEvent buttons.\\n\\tkeyValue _ anEvent keyValue.\\n\\tsourceHand _ anEvent hand.\\n\\ttype == #mouseMove ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: cursorPoint\\n\\t\\t\\tendPoint: cursorPoint\\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: sourceHand \\n\\t\\t\\tstamp: nil].\\n\\t(type == #mouseDown) | (type == #mouseUp) ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: cursorPoint\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: sourceHand\\n\\t\\t\\t\\tstamp: nil].\\n\\t(type == #keystroke) | (type == #keyDown) | (type == #keyUp) ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: cursorPoint\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: sourceHand\\n\\t\\t\\tstamp: nil].\\n\\t^nil! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 00:49'!\\nreadFrom: aStream\\n\\t\\\"Read a MorphicEvent from the given stream.\\\"\\n\\t| typeString c |\\n\\ttypeString _ String streamContents:\\n\\t\\t[:s | [(c _ aStream next) isLetter] whileTrue: [s nextPut: c]].\\n\\ttypeString = 'mouseMove' ifTrue:[^MouseMoveEvent type: #mouseMove readFrom: aStream].\\n\\ttypeString = 'mouseDown' ifTrue:[^MouseButtonEvent type: #mouseDown readFrom: aStream].\\n\\ttypeString = 'mouseUp' ifTrue:[^MouseButtonEvent type: #mouseUp readFrom: aStream].\\n\\n\\ttypeString = 'keystroke' ifTrue:[^KeyboardEvent type: #keystroke readFrom: aStream].\\n\\ttypeString = 'keyDown' ifTrue:[^KeyboardEvent type: #keyDown readFrom: aStream].\\n\\ttypeString = 'keyUp' ifTrue:[^KeyboardEvent type: #keyUp readFrom: aStream].\\n\\n\\ttypeString = 'mouseOver' ifTrue:[^MouseEvent type: #mouseOver readFrom: aStream].\\n\\ttypeString = 'mouseEnter' ifTrue:[^MouseEvent type: #mouseEnter readFrom: aStream].\\n\\ttypeString = 'mouseLeave' ifTrue:[^MouseEvent type: #mouseLeave readFrom: aStream].\\n\\n\\ttypeString = 'unknown' ifTrue:[^MorphicUnknownEvent type: #unknown readFrom: aStream].\\n\\n\\t^nil\\n! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/25/2000 21:58'!\\nreadFromObsolete: aStream\\n\\t\\\"Read one of those old and now obsolete events from the stream\\\"\\n\\t| type x y buttons keyValue typeString c |\\n\\ttypeString _ String streamContents:\\n\\t\\t[:s | [(c _ aStream next) isLetter] whileTrue: [s nextPut: c]].\\n\\ttypeString = 'mouseMove'\\n\\t\\tifTrue: [type _ #mouseMove \\\"fast treatment of common case\\\"]\\n\\t\\tifFalse: [type _ typeString asSymbol].\\n\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\n\\tbuttons _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\n\\tkeyValue _ Integer readFrom: aStream.\\n\\n\\ttypeString = 'mouseMove' ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: x@y \\n\\t\\t\\tendPoint: x@y \\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: nil \\n\\t\\t\\tstamp: nil].\\n\\t(typeString = 'mouseDown') | (typeString = 'mouseUp') ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: x@y\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: nil\\n\\t\\t\\t\\tstamp: nil].\\n\\t(typeString = 'keystroke') | (typeString = 'keyDown') | (typeString = 'keyUp') ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: x@y\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: nil\\n\\t\\t\\tstamp: nil].\\n\\n\\t^nil! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/24/2000 16:32'!\\ntype: eventType readFrom: aStream\\n\\t^self new type: eventType readFrom: aStream! !\\n\\n\\n!MorphicEvent class methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:32'!\\nfromStringArray: array\\n\\t\\\"decode an event that was encoded with encodedAsStringArray\\\"\\n\\t| type |\\n\\ttype := (array at: 1).\\n\\t(type = 'mouseMove')\\n\\t\\tifTrue:[^MouseMoveEvent new decodeFromStringArray: array].\\n\\t(type = 'mouseDown' or:[type = 'mouseUp']) \\n\\t\\tifTrue:[^MouseButtonEvent new decodeFromStringArray: array].\\n\\t(type = 'keystroke' or:[type = 'keyDown' or:[type = 'keyUp']]) \\n\\t\\tifTrue:[^KeyboardEvent new decodeFromStringArray: array].\\n\\t^nil! !\\nObject subclass: #MorphicEventDecoder\\n\\tinstanceVariableNames: 'connection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!MorphicEventDecoder commentStamp: '<historical>' prior: 0!\\ndecode messages sent via a MorphicEventEncoder.!\\n\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'RAA 11/8/2000 15:15'!\\napply: aStringArray to: aHand\\n\\t\\\"decode aStringArray, and apply the encoded command to aHand\\\"\\n\\n\\taStringArray first = 'event' ifTrue: [\\n\\t\\t^self applyEventMessage: aStringArray to: aHand\\n\\t].\\n\\taStringArray first = 'viewExtent' ifTrue: [\\n\\t\\t^self applyViewExtentMessage: aStringArray to: aHand\\n\\t].\\n\\taStringArray first = 'beginBuffering' ifTrue: [\\n\\t\\t^aHand convertRemoteClientToBuffered\\n\\t].\\n\\n\\t^self error: 'unknown message type: ', aStringArray first! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ar 10/26/2000 01:55'!\\napplyEventMessage: aStringArray to: aHand\\n\\t| event |\\n\\tevent := MorphicEvent fromStringArray: (aStringArray copyFrom: 2 to: aStringArray size).\\n\\tevent ifNotNil:[aHand queueEvent: event].! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 3/25/2000 16:56'!\\napplyMessagesTo: aHand\\n\\t| msg |\\n\\t\\\"apply all queued events to the given hand\\\"\\n\\t\\\"currently, there is no way to extract the rawmessages. This is simply because I didn't feel like implementing individual classes for each message -lex\\\"\\n\\t[ msg := connection nextOrNil. msg notNil ] whileTrue: [\\n\\t\\tself apply: msg to: aHand ].\\n! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 4/11/2000 19:00'!\\napplyViewExtentMessage: aStringArray to: aHand\\n\\t| newViewExtent |\\n\\tnewViewExtent := CanvasDecoder decodePoint: aStringArray second.\\n\\n\\taHand setViewExtent: newViewExtent! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 3/24/2000 22:54'!\\nprocessIO\\n\\tconnection processIO! !\\n\\n\\n!MorphicEventDecoder methodsFor: 'initialization' stamp: 'ls 3/24/2000 21:42'!\\nconnection: aConnection\\n\\tconnection := aConnection! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEventDecoder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEventDecoder class methodsFor: 'instance creation' stamp: 'ls 3/24/2000 21:43'!\\non: aStringArray\\n\\t^self basicNew connection: aStringArray! !\\nObject subclass: #MorphicEventDispatcher\\n\\tinstanceVariableNames: 'lastType lastDispatch'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n!MorphicEventDispatcher commentStamp: '<historical>' prior: 0!\\nThe class represents a strategy for dispatching events to some immediate child of a morph. It is used by morphs to delegate the somewhat complex action of dispatching events accurately. !\\n\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 01:20'!\\ndispatchDefault: anEvent with: aMorph\\n\\t\\\"Dispatch the given event. The event will be passed to the front-most visible submorph that contains the position wrt. to the event.\\\"\\n\\t| localEvt index child morphs inside |\\n\\t\\\"See if we're fully outside aMorphs bounds\\\"\\n\\t(aMorph fullBounds containsPoint: anEvent position) ifFalse:[^#rejected]. \\\"outside\\\"\\n\\t\\\"Traverse children\\\"\\n\\tindex _ 1.\\n\\tmorphs _ aMorph submorphs.\\n\\tinside _ false.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\t\\\"Not rejected. The event was in some submorph of the receiver\\\"\\n\\t\\t\\tinside _ true.\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[anEvent copyHandlerState: localEvt].\\n\\t\\t\\tindex _ morphs size. \\\"break\\\"\\n\\t\\t].\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\t\\\"Check for being inside the receiver\\\"\\n\\tinside ifFalse:[inside _ aMorph containsPoint: anEvent position event: anEvent].\\n\\tinside ifTrue:[^aMorph handleEvent: anEvent].\\n\\t^#rejected\\n! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:13'!\\ndispatchDropEvent: anEvent with: aMorph\\n\\t\\\"Find the appropriate receiver for the event and let it handle it. The dispatch is similar to the default dispatch with one difference: Morphs are given the chance to reject an entire drop operation. If the operation is rejected, no drop will be executed.\\\"\\n\\t| inside index morphs child localEvt |\\n\\t\\\"Try to get out quickly\\\"\\n\\t(aMorph fullBounds containsPoint: anEvent cursorPoint)\\n\\t\\tifFalse:[^#rejected].\\n\\t\\\"Give aMorph a chance to repel the dropping morph\\\"\\n\\taMorph rejectDropEvent: anEvent.\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\n\\t\\\"Go looking if any of our submorphs wants it\\\"\\n\\tindex _ 1.\\n\\tinside _ false.\\n\\tmorphs _ aMorph submorphs.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[^anEvent wasHandled: true]. \\\"done\\\"\\n\\t\\t\\tinside _ true.\\n\\t\\t\\tindex _ morphs size]. \\\"break\\\"\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\tinside ifFalse:[inside _ aMorph containsPoint: anEvent cursorPoint event: anEvent].\\n\\tinside ifTrue:[^aMorph handleEvent: anEvent].\\n\\t^#rejected! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 1/10/2001 21:43'!\\ndispatchEvent: anEvent with: aMorph\\n\\t\\\"Dispatch the given event for a morph that has chosen the receiver to dispatch its events. The method implements a shortcut for repeated dispatches of events using the same dispatcher.\\\"\\n\\tanEvent type == lastType ifTrue:[^self perform: lastDispatch with: anEvent with: aMorph].\\n\\t\\\"Otherwise classify\\\"\\n\\tlastType _ anEvent type.\\n\\tanEvent isMouse ifTrue:[\\n\\t\\tanEvent isMouseDown ifTrue:[\\n\\t\\t\\tlastDispatch _ #dispatchMouseDown:with:.\\n\\t\\t\\t^self dispatchMouseDown: anEvent with: aMorph]].\\n\\tanEvent type == #dropEvent ifTrue:[\\n\\t\\tlastDispatch _ #dispatchDropEvent:with:.\\n\\t\\t^self dispatchDropEvent: anEvent with: aMorph].\\n\\tlastDispatch _ #dispatchDefault:with:.\\n\\t^self dispatchDefault: anEvent with: aMorph! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:14'!\\ndispatchMouseDown: anEvent with: aMorph\\n\\t\\\"Find the appropriate receiver for the event and let it handle it. Default rules:\\n\\t* The top-most chain of visible, unlocked morphs containing the event position will get a chance to handle the event.\\n\\t* When travelling down the hierarchy a prospective handler for the event is installed. This prospective handler can be used by submorphs wishing to handle the mouse down for negotiating who the receiver is.\\n\\t* When travelling up, the prospective handler is always executed. The handler needs to check if the event was handled before as well as checking if somebody else's handler has been installed.\\n\\t* If another handler has been installed but the event was not handled it means that somebody up in the hierarchy wants to handle the event.\\n\\\"\\n\\t| globalPt localEvt index child morphs handler inside lastHandler |\\n\\t\\\"Try to get out quickly\\\"\\n\\tglobalPt _ anEvent cursorPoint.\\n\\t(aMorph fullBounds containsPoint: globalPt) ifFalse:[^#rejected].\\n\\n\\t\\\"Install the prospective handler for the receiver\\\"\\n\\tlastHandler _ anEvent handler. \\\"in case the mouse wasn't even in the receiver\\\"\\n\\thandler _ aMorph handlerForMouseDown: anEvent.\\n\\thandler ifNotNil:[anEvent handler: handler].\\n\\n\\t\\\"Now give our submorphs a chance to handle the event\\\"\\n\\tindex _ 1.\\n\\tmorphs _ aMorph submorphs.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\t\\\"Some child did contain the point so we're part of the top-most chain.\\\"\\n\\t\\t\\tinside _ false.\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[anEvent copyHandlerState: localEvt].\\n\\t\\t\\tindex _ morphs size].\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\t(inside == false or:[aMorph containsPoint: anEvent cursorPoint event: anEvent]) ifTrue:[\\n\\t\\t\\\"Receiver is in the top-most unlocked, visible chain.\\\"\\n\\t\\thandler ifNotNil:[handler handleEvent: anEvent].\\n\\t\\t\\\"Note: Re-installing the handler is not really necessary but good style.\\\"\\n\\t\\tanEvent handler: lastHandler.\\n\\t\\t^self\\n\\t].\\n\\t\\\"Mouse was not on receiver nor any of its children\\\"\\n\\tanEvent handler: lastHandler.\\n\\t^#rejected! !\\nObject subclass: #MorphicEventEncoder\\n\\tinstanceVariableNames: 'connection lastEventSent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!MorphicEventEncoder commentStamp: '<historical>' prior: 0!\\nA filter which translates MorphEvent's into StringArray's.!\\n\\n\\n!MorphicEventEncoder methodsFor: 'initialization' stamp: 'ls 3/24/2000 21:38'!\\nconnection: aConnection\\n\\tconnection := aConnection! !\\n\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/24/2000 21:42'!\\nflush\\n\\tconnection flush! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/24/2000 21:38'!\\nprocessIO\\n\\tconnection processIO! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'RAA 12/13/2000 08:19'!\\nrequestBufferedConnection\\n\\t\\\"request the opposite side to send complete screen updates rather than discrete drawing commands\\\"\\n\\t\\n\\tconnection nextPut: { 'beginBuffering' }\\n! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/26/2000 01:08'!\\nsendEvent: anEvent\\n\\t(anEvent isMouseMove and: [ anEvent = lastEventSent ]) ifTrue: [\\n\\t\\t\\\"save on network traffic--don't send duplicate mouse moves\\\"\\n\\t\\t^self ].\\n\\tlastEventSent := anEvent.\\n\\tconnection nextPut: #('event'), anEvent encodedAsStringArray! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 4/11/2000 18:59'!\\nsendViewExtent: newExtent\\n\\t\\\"inform the opposite side that our view extent has changed\\\"\\n\\t\\n\\tconnection nextPut: { 'viewExtent'. CanvasEncoder encodePoint: newExtent }\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEventEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEventEncoder class methodsFor: 'instance creation' stamp: 'ls 3/24/2000 21:43'!\\non: aStringArray\\n\\t^self basicNew connection: aStringArray! !\\nBorderedMorph subclass: #MorphicModel\\n\\tinstanceVariableNames: 'model slotName open'\\n\\tclassVariableNames: 'TimeOfError'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MorphicModel commentStamp: '<historical>' prior: 0!\\nMorphicModels are used to represent structures with state and behavior as well as graphical structure. A morphicModel is usually the root of a morphic tree depicting its appearance. The tree is constructed concretely by adding its consituent morphs to a world.\\n\\nWhen a part is named in a world, it is given a new slot in the model. When a part is sensitized, it is named, and a set of mouse-driven methods is also generated in the model. These may be edited to induce particular behavior. When a variable is added through the morphic world, it is given a slot in the model, along with a set of access methods.\\n\\nIn addition for public variables (and this is the default for now), methods are generated and called in any outer model in which this model gets embedded, thus propagating variable changes outward.!\\n\\n\\n!MorphicModel methodsFor: 'access'!\\nmodel \\n\\t^ model! !\\n\\n!MorphicModel methodsFor: 'access'!\\nslotName\\n\\t^ slotName! !\\n\\n!MorphicModel methodsFor: 'access' stamp: '6/7/97 10:40 di'!\\nwantsSlot\\n\\t\\\"Override this default for models that want to be installed in theri model\\\"\\n\\t^ false! !\\n\\n\\n!MorphicModel methodsFor: 'accessing' stamp: 'sw 10/23/1999 22:36'!\\nmodelOrNil\\n\\t^ model! !\\n\\n\\n!MorphicModel methodsFor: 'caching' stamp: 'sw 3/6/2001 11:22'!\\nreleaseCachedState\\n\\t\\\"Release cached state of the receiver\\\"\\n\\n\\t(model ~~ self and: [model respondsTo: #releaseCachedState]) ifTrue:\\n\\t\\t[model releaseCachedState].\\n\\tsuper releaseCachedState! !\\n\\n\\n!MorphicModel methodsFor: 'classification' stamp: 'ar 10/5/2000 16:40'!\\nisMorphicModel\\n\\t^true! !\\n\\n\\n!MorphicModel methodsFor: 'compilation'!\\naddPartNameLike: className withValue: aMorph\\n\\t| otherNames i default partName stem |\\n\\tstem _ className first asLowercase asString , className allButFirst.\\n\\totherNames _ self class allInstVarNames.\\n\\ti _ 1.\\n\\t[otherNames includes: (default _ stem, i printString)]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\tpartName _ FillInTheBlank\\n\\t\\trequest: 'Please give this part a name'\\n\\t\\tinitialAnswer: default.\\n\\t(otherNames includes: partName)\\n\\t\\tifTrue: [self inform: 'Sorry, that name is already used'. ^ nil].\\n\\tself class addInstVarName: partName.\\n\\tself instVarAt: self class instSize put: aMorph. \\\"Assumes added as last field\\\"\\n\\t^ partName! !\\n\\n!MorphicModel methodsFor: 'compilation' stamp: 'tk 4/18/97'!\\ncompileAccessForSlot: aSlotName\\n\\t\\\"Write the method to get at this inst var. \\\"\\n\\t\\\"Instead call the right thing to make this happen?\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: (String new: 2000).\\n\\ts nextPutAll: aSlotName; cr; tab; nextPutAll: '^', aSlotName.\\n\\tself class\\n\\t\\tcompile: s contents\\n\\t\\tclassified: 'public access'\\n\\t\\tnotifying: nil.\\n! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\ncompilePropagationMethods\\n\\t| varName |\\n\\t(self class organization listAtCategoryNamed: 'private - propagation' asSymbol)\\n\\t\\tdo: [:sel | varName _ sel allButLast.\\n\\t\\t\\tmodel class compilePropagationForVarName: varName slotName: slotName]! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nnameFor: aMorph\\n\\t\\\"Return the name of the slot containing the given morph or nil if that morph has not been named.\\\"\\n\\n\\t| allNames start |\\n\\tallNames _ self class allInstVarNames.\\n\\tstart _ MorphicModel allInstVarNames size + 1.\\n\\tstart to: allNames size do: [:i |\\n\\t\\t(self instVarAt: i) == aMorph ifTrue: [^ allNames at: i]].\\n\\t^ nil\\n! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\npropagate: value as: partStoreSelector\\n\\tmodel ifNil: [^ self].\\n\\\"\\n\\tLater we can cache this for more speed as follows...\\n\\t(partName == cachedPartName and: [slotName == cachedSlotName])\\n\\t\\tifFalse: [cachedPartName _ partName.\\n\\t\\t\\t\\tcachedSlotName _ slotName.\\n\\t\\t\\t\\tcachedStoreSelector _ (slotName , partStoreSelector) asSymbol].\\n\\tmodel perform: cachedStoreSelector with: value].\\n\\\"\\n\\tmodel perform: (self slotSelectorFor: partStoreSelector) with: value! !\\n\\n!MorphicModel methodsFor: 'compilation' stamp: 'tk 10/31/97 12:33'!\\nremoveAll\\n\\t\\\"Clear out all script methods and subpart instance variables in me. Start over.\\\"\\n\\t\\\"self removeAll\\\"\\n\\t\\\"MorphicModel2 removeAll\\\"\\n\\nself class == MorphicModel ifTrue: [^ self].\\t\\\"Must be a subclass!!\\\"\\nself class removeCategory: 'scripts'.\\nself class instVarNames do: [:nn | self class removeInstVarName: nn].! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nslotSelectorFor: selectorBody\\n\\t| selector |\\n\\tmodel ifNil: [^ nil].\\n\\t\\\"Make up selector from slotname if any\\\"\\n\\tselector _ (slotName ifNil: [selectorBody]\\n\\t\\t\\t\\t\\tifNotNil: [slotName , selectorBody]) asSymbol.\\n\\t(model canUnderstand: selector) ifFalse:\\n\\t\\t[self halt: 'Compiling a null response for ' , model class name , '>>' , selector].\\n\\t^ selector! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nuse: cachedSelector orMakeModelSelectorFor: selectorBody in: selectorBlock\\n\\t| selector |\\n\\tmodel ifNil: [^ nil].\\n\\tcachedSelector ifNil:\\n\\t\\t\\t[\\\"Make up selector from slotname if any\\\"\\n\\t\\t\\tselector _ (slotName ifNil: [selectorBody]\\n\\t\\t\\t\\t\\t\\t\\t\\tifNotNil: [slotName , selectorBody]) asSymbol.\\n\\t\\t\\t(model class canUnderstand: selector) ifFalse:\\n\\t\\t\\t\\t[(self confirm: 'Shall I compile a null response for'\\n\\t\\t\\t\\t\\t\\t\\t, Character cr asString\\n\\t\\t\\t\\t\\t\\t\\t, model class name , '>>' , selector)\\n\\t\\t\\t\\t\\t\\tifFalse: [self halt].\\n\\t\\t\\t\\tmodel class compile: (String streamContents:\\n\\t\\t\\t\\t\\t\\t\\t\\t[:s | selector keywords doWithIndex:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:k :i | s nextPutAll: k , ' arg' , i printString].\\n\\t\\t\\t\\t\\t\\t\\t\\ts cr; nextPutAll: '\\\"Automatically generated null response.\\\"'.\\n\\t\\t\\t\\t\\t\\t\\t\\ts cr; nextPutAll: '\\\"Add code below for appropriate behavior...\\\"'.])\\n\\t\\t\\t\\t\\t\\t\\tclassified: 'input events'\\n\\t\\t\\t\\t\\t\\t\\tnotifying: nil]]\\n\\t\\tifNotNil:\\n\\t\\t\\t[selector _ cachedSelector].\\n\\t^ selectorBlock value: selector! !\\n\\n\\n!MorphicModel methodsFor: 'debug and other' stamp: '6/7/97 10:43 di'!\\ninstallModelIn: aWorld\\n\\n\\tself wantsSlot ifFalse: [^ self]. \\\"No real need to install\\\"\\n\\tslotName _ aWorld model addPartNameLike: self class name withValue: self.\\n\\tslotName ifNil: [^ self]. \\\"user chose bad slot name\\\"\\n\\tself model: aWorld model slotName: slotName.\\n\\tself compilePropagationMethods.\\n\\taWorld model compileAccessForSlot: slotName.\\n! !\\n\\n\\n!MorphicModel methodsFor: 'drag and drop' stamp: 'di 6/22/97 23:17'!\\nallowSubmorphExtraction\\n\\t^ self isOpen\\n! !\\n\\n!MorphicModel methodsFor: 'drag and drop' stamp: 'di 6/22/97 23:16'!\\nisOpen\\n\\t\\\"Support drag/drop and other edits.\\\"\\n\\t^ open! !\\n\\n\\n!MorphicModel methodsFor: 'geometry'!\\nnewBounds: newBounds\\n\\tself bounds: newBounds! !\\n\\n!MorphicModel methodsFor: 'geometry'!\\nrecomputeBounds\\n\\n\\t| bnds |\\n\\tbnds _ submorphs first bounds.\\n\\tbounds _ bnds origin corner: bnds corner. \\\"copy it!!\\\"\\n\\tfullBounds _ nil.\\n\\tbounds _ self fullBounds.\\n! !\\n\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color yellow! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:07'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 200 @ 100! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color transparent! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'tk 4/15/97'!\\nduplicate: newGuy from: oldGuy\\n\\t\\\"oldGuy has just been duplicated and will stay in this world. Make sure all the MorphicModel requirements are carried out for the copy. Ask user to rename it. \\\"\\n\\n\\tnewGuy installModelIn: oldGuy world.\\n\\tnewGuy copySlotMethodsFrom: oldGuy slotName.! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:47'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\topen _ false! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'jm\\n 8/20/1998 09:08'!\\nmodel: anObject\\n\\t\\\"Set my model and make me me a dependent of the given object.\\\"\\n\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel _ anObject.\\n! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'di 6/21/97 13:25'!\\nmodel: thang slotName: nameOfThisPart\\n\\tmodel _ thang.\\n\\tslotName _ nameOfThisPart.\\n\\topen _ false.! !\\n\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:53'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\tmodel ifNotNil: [model addModelMenuItemsTo: aCustomMenu forMorph: self hand: aHandMorph].\\n\\tself isOpen ifTrue: [aCustomMenu add: 'close editing' translated action: #closeToEdits]\\n\\t\\t\\tifFalse: [aCustomMenu add: 'open editing' translated action: #openToEdits].\\n! !\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'di 6/20/97 15:36'!\\ncloseToEdits\\n\\t\\\"Disable this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\topen _ false\\n! !\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'di 6/20/97 15:36'!\\nopenToEdits\\n\\t\\\"Enable this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\topen _ true\\n! !\\n\\n\\n!MorphicModel methodsFor: 'naming' stamp: 'dgd 2/21/2003 23:00'!\\nchoosePartName\\n\\t\\\"When I am renamed, get a slot, make default methods, move any existing methods. ** Does not clean up old inst var name or methods** \\\"\\n\\n\\t| old |\\n\\told := slotName.\\n\\tsuper choosePartName.\\n\\tslotName ifNil: [^self].\\t\\\"user chose bad slot name\\\"\\n\\tself model: self world model slotName: slotName.\\n\\told isNil\\n\\t\\tifTrue: [self compilePropagationMethods]\\n\\t\\tifFalse: [self copySlotMethodsFrom: old]\\n\\t\\\"old ones not erased!!\\\"! !\\n\\n\\n!MorphicModel methodsFor: 'printing'!\\ninitString\\n\\n\\t^ String streamContents:\\n\\t\\t[:s | s nextPutAll: self class name;\\n\\t\\t\\tnextPutAll: ' newBounds: (';\\n\\t\\t\\tprint: bounds;\\n\\t\\t\\tnextPutAll: ') model: self slotName: ';\\n\\t\\t\\tprint: slotName]! !\\n\\n\\n!MorphicModel methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 18:51'!\\nallKnownNames\\n\\t\\\"Return a list of all known names based on the scope of the receiver. If the receiver is a member of a uniclass, incorporate the original 1997 logic that queries the known names of the values of all the instance variables.\\\"\\n\\n\\t| superNames |\\n\\tsuperNames := super allKnownNames.\\t\\\"gather them from submorph tree\\\"\\n\\t^self belongsToUniClass \\n\\t\\tifTrue: \\n\\t\\t\\t[superNames , (self instanceVariableValues \\n\\t\\t\\t\\t\\t\\tselect: [:e | e notNil and: [e knownName notNil]]\\n\\t\\t\\t\\t\\t\\tthenCollect: [:e | e knownName])]\\n\\t\\tifFalse: [superNames]! !\\n\\n\\n!MorphicModel methodsFor: 'submorphs-add/remove' stamp: 'gm 2/22/2003 12:51'!\\ndelete\\n\\t(model isMorphicModel) ifFalse: [^super delete].\\n\\tslotName ifNotNil: \\n\\t\\t\\t[(PopUpMenu confirm: 'Shall I remove the slot ' , slotName \\n\\t\\t\\t\\t\\t\\t, '\\nalong with all associated methods?') \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[(model class selectors select: [:s | s beginsWith: slotName]) \\n\\t\\t\\t\\t\\t\\tdo: [:s | model class removeSelector: s].\\n\\t\\t\\t\\t\\t(model class instVarNames includes: slotName) \\n\\t\\t\\t\\t\\t\\tifTrue: [model class removeInstVarName: slotName]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(PopUpMenu \\n\\t\\t\\t\\t\\t\\tconfirm: '...but should I at least dismiss this morph?\\n[choose no to leave everything unchanged]') \\n\\t\\t\\t\\t\\t\\t\\tifFalse: [^self]]].\\n\\tsuper delete! !\\n\\n\\n!MorphicModel methodsFor: '*MorphicExtras-compilation'!\\ncompileInitMethods\\n\\t| s nodeDict varNames |\\n\\tnodeDict _ IdentityDictionary new.\\n\\ts _ WriteStream on: (String new: 2000).\\n\\tvarNames _ self class allInstVarNames.\\n\\ts nextPutAll: 'initMorph'.\\n\\t3 to: self class instSize do:\\n\\t\\t[:i | (self instVarAt: i) isMorph ifTrue:\\n\\t\\t\\t[s cr; tab; nextPutAll: (varNames at: i) , ' _ '.\\n\\t\\t\\ts nextPutAll: (self instVarAt: i) initString; nextPutAll: '.'.\\n\\t\\t\\tnodeDict at: (self instVarAt: i) put: (varNames at: i)]].\\n\\tsubmorphs do: \\n\\t\\t[:m | s cr; tab; nextPutAll: 'self addMorph: '.\\n\\t\\tm printConstructorOn: s indent: 1 nodeDict: nodeDict.\\n\\t\\ts nextPutAll: '.'].\\n\\tself class\\n\\t\\tcompile: s contents\\n\\t\\tclassified: 'initialization'\\n\\t\\tnotifying: nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicModel class\\n\\tinstanceVariableNames: 'prototype'!\\n\\n!MorphicModel class methodsFor: 'compilation' stamp: 'tk 3/10/98 18:03'!\\ncategoryForSubclasses\\n\\t^ 'Morphic-Models'! !\\n\\n!MorphicModel class methodsFor: 'compilation' stamp: 'sw 5/23/2001 13:51'!\\nchooseNewName\\n\\t\\\"Choose a new name for the receiver, persisting until an acceptable name is provided or until the existing name is resubmitted\\\"\\n\\n\\t| oldName newName |\\n\\toldName _ self name.\\n\\t\\t[newName _ (FillInTheBlank request: 'Please give this Model a name'\\n\\t\\t\\t\\t\\tinitialAnswer: oldName) asSymbol.\\n\\t\\tnewName = oldName ifTrue: [^ self].\\n\\t\\tSmalltalk includesKey: newName]\\n\\t\\twhileTrue:\\n\\t\\t[self inform: 'Sorry, that name is already in use.'].\\n\\tself rename: newName.! !\\n\\n!MorphicModel class methodsFor: 'compilation'!\\ncompileAccessorsFor: varName\\n\\tself compile: (\\n'&var\\n\\t\\\"Return the value of &var\\\"\\n\\t^ &var'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'public access' notifying: nil.\\n\\tself compile: (\\n'&varPut: newValue\\n\\t\\\"Assign newValue to &var.\\n\\tAdd code below to update related graphics appropriately...\\\"\\n\\n\\t&var _ newValue.'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'public access' notifying: nil.\\n\\tself compile: (\\n'&var: newValue\\n\\t\\\"Assigns newValue to &var and updates owner\\\"\\n\\t&var _ newValue.\\n\\tself propagate: &var as: ''&var:'''\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'private - propagation' notifying: nil.\\n! !\\n\\n!MorphicModel class methodsFor: 'compilation'!\\ncompilePropagationForVarName: varName slotName: slotName\\n\\tself compile: ((\\n'&slot&var: newValue\\n\\t\\\"The value of &var in &slot has changed to newValue.\\n\\tThis value can be read elsewhere in code with\\n\\t\\t&slot &var\\n\\tand it can be stored into with\\n\\t\\t&slot &varPut: someValue\\\"\\n\\n\\t\\\"Add code for appropriate response here...\\\"'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\t\\tcopyReplaceAll: '&slot' with: slotName)\\n\\t\\tclassified: 'input events' notifying: nil.\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'compiling' stamp: 'sw 5/13/1998 14:33'!\\nacceptsLoggingOfCompilation\\n\\t\\\"Dont log sources for my automatically-generated subclasses. Can easily switch this back when it comes to deal with Versions, etc.\\\"\\n\\n\\t^ self == MorphicModel or: [(name last isDigit) not]! !\\n\\n!MorphicModel class methodsFor: 'compiling' stamp: 'sw 8/4/97 17:16'!\\nwantsChangeSetLogging\\n\\t\\\"Log changes for MorphicModel itself and for things like PlayWithMe2, but not for automatically-created subclasses like MorphicModel1, MorphicModel2, etc.\\\"\\n\\n\\t^ self == MorphicModel or:\\n\\t\\t[(self class name beginsWith: 'Morphic') not]! !\\n\\n\\n!MorphicModel class methodsFor: 'housekeeping' stamp: 'jm 7/30/97 16:40'!\\nremoveUninstantiatedModels\\n\\t\\\"With the user's permission, remove the classes of any models that have neither instances nor subclasses.\\\"\\n\\t\\\"MorphicModel removeUninstantiatedModels\\\"\\n\\n\\t| candidatesForRemoval ok |\\n\\tSmalltalk garbageCollect.\\n\\tcandidatesForRemoval _\\n\\t\\tMorphicModel subclasses select: [:c |\\n\\t\\t\\t(c instanceCount = 0) and: [c subclasses size = 0]].\\n\\tcandidatesForRemoval do: [:c |\\n\\t\\tok _ self confirm: 'Are you certain that you\\nwant to delete the class ', c name, '?'.\\n\\t\\tok ifTrue: [c removeFromSystem]].\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'instance creation' stamp: 'tk 8/13/1998 12:58'!\\nnew\\n\\t\\\"Return a copy of the prototype, if there is one.\\n\\tOtherwise create a new instance normally.\\\"\\n\\n\\tself hasPrototype ifTrue: [^ prototype veryDeepCopy].\\n\\t^ super new\\n! !\\n\\n!MorphicModel class methodsFor: 'instance creation' stamp: 'di 6/22/97 09:27'!\\nnewBounds: bounds model: thang slotName: nameOfThisPart\\n\\t^ (super new model: thang slotName: nameOfThisPart)\\n\\t\\tnewBounds: bounds! !\\n\\n\\n!MorphicModel class methodsFor: 'new-morph participation' stamp: 'di 2/21/98 11:01'!\\nincludeInNewMorphMenu\\n\\t\\\"Only include Models that are appropriate\\\"\\n\\t^ false! !\\n\\n\\n!MorphicModel class methodsFor: 'prototype access'!\\nprototype\\n\\t\\\"Return the prototype for this morph.\\\"\\n\\n\\t^ prototype\\n! !\\n\\n!MorphicModel class methodsFor: 'prototype access' stamp: 'gm 2/22/2003 19:13'!\\nprototype: aMorph\\n\\t\\\"Store a copy of the given morph as a prototype to be copied to make new instances.\\\"\\n\\n\\taMorph ifNil: [prototype _ nil. ^ self].\\n\\n\\tprototype _ aMorph veryDeepCopy.\\n\\t(prototype isMorphicModel) ifTrue: \\n\\t\\t[prototype model: nil slotName: nil].\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'queries'!\\nhasPrototype\\n\\t\\\"Return true if there is a prototype for this morph.\\\"\\n\\n\\t^ prototype ~~ nil\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'subclass creation'!\\nnewSubclass\\n\\t| i className |\\n\\ti _ 1.\\n\\t[className _ (self name , i printString) asSymbol.\\n\\t Smalltalk includesKey: className]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\n\\t^ self subclass: className\\n\\t\\tinstanceVariableNames: ''\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: 'Morphic-Models'! !\\n\\n\\n!MorphicModel class methodsFor: 'testing' stamp: 'tk 3/15/98 20:13'!\\nofficialClass\\n\\t\\\"We want to make a new instance of the receiver, which is a subclass of MorphicModel. Answer who to make a new subclass of. Also used to tell if a given class is a UniClass, existing only for its single instance.\\\"\\n\\n\\t^ self name last isDigit ifTrue: [MorphicModel] ifFalse: [self]\\n\\t\\t\\\"MorphicModel7 can not have subclasses, but Slider and SystemWindow may\\\"! !\\n\\n\\n!MorphicModel class methodsFor: '*eToys-queries' stamp: 'sw 2/27/2002 14:58'!\\nbaseUniclass\\n\\t\\\"Answer the uniclass that new instances should be instances of. This protocol is primarily intended for the Player lineage, but can get sent to a MorphicModel subclass when the project-loading mechanism is scrambling to fix up projects that have naming conflicts with the project being loaded.\\\"\\n\\n\\t| curr |\\n\\tcurr _ self.\\n\\t[curr theNonMetaClass superclass name endsWithDigit]\\n\\t\\twhileTrue:\\n\\t\\t\\t[curr _ curr superclass].\\n\\t^ curr\\n\\n\\\"PlayWithMe1 baseUniclass\\\"! !\\nAppRegistry subclass: #MorphicTextEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\nToolBuilder subclass: #MorphicToolBuilder\\n\\tinstanceVariableNames: 'widgets panes parentMenu'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicToolBuilder commentStamp: 'ar 2/11/2005 15:02' prior: 0!\\nThe Morphic tool builder.!\\n\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:40'!\\nclose: aWidget\\n\\t\\\"Close a previously opened widget\\\"\\n\\taWidget delete! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 2/28/2006 17:39'!\\nopen: anObject\\n\\t\\\"Build and open the object. Answer the widget opened.\\\"\\n\\t| morph |\\n\\tmorph := self build: anObject.\\n\\t(morph isKindOf: MenuMorph)\\n\\t\\tifTrue:[morph popUpInWorld: World].\\n\\t(morph isKindOf: SystemWindow)\\n\\t\\tifTrue:[morph openInWorldExtent: morph extent]\\n\\t\\tifFalse:[morph openInWorld].\\n\\t^morph! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:40'!\\nopen: anObject label: aString\\n\\t\\\"Build an open the object, labeling it appropriately. Answer the widget opened.\\\"\\n\\t| window |\\n\\twindow := self open: anObject.\\n\\twindow setLabel: aString.\\n\\t^window! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:41'!\\nrunModal: aWidget\\n\\t\\\"Run the (previously opened) widget modally, e.g., \\n\\tdo not return control to the sender before the user has responded.\\\"\\n\\t[aWidget world notNil] whileTrue: [\\n\\t\\taWidget outermostWorldMorph doOneCycle.\\n\\t].\\n! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 2/12/2005 14:22'!\\nbuildPluggableActionButton: aSpec\\n\\t| button |\\n\\tbutton := self buildPluggableButton: aSpec.\\n\\tbutton beActionButton.\\n\\t^button! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:27'!\\nbuildPluggableButton: aSpec\\n\\t| widget label state action enabled |\\n\\tlabel := aSpec label.\\n\\tstate := aSpec state.\\n\\taction := aSpec action.\\n\\twidget := PluggableButtonMorphPlus on: aSpec model\\n\\t\\t\\t\\tgetState: (state isSymbol ifTrue:[state])\\n\\t\\t\\t\\taction: nil\\n\\t\\t\\t\\tlabel: (label isSymbol ifTrue:[label]).\\n\\tself register: widget id: aSpec name.\\n\\tenabled := aSpec enabled.\\n\\tenabled isSymbol\\n\\t\\tifTrue:[widget getEnabledSelector: enabled]\\n\\t\\tifFalse:[widget enabled:enabled].\\n\\twidget action: action.\\n\\twidget getColorSelector: aSpec color.\\n\\twidget offColor: Color transparent.\\n\\taSpec help ifNotNil:[widget setBalloonText: aSpec help].\\n\\t(label isSymbol or:[label == nil]) ifFalse:[widget label: label].\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'md 8/15/2005 17:55'!\\nbuildPluggableInputField: aSpec\\n\\t| widget |\\n\\twidget := self buildPluggableText: aSpec.\\n\\twidget acceptOnCR: true.\\n\\twidget hideScrollBarsIndefinitely.\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/15/2005 12:07'!\\nbuildPluggableList: aSpec\\n\\t| widget listClass getIndex setIndex |\\n\\taSpec getSelected ifNil:[\\n\\t\\tlistClass := PluggableListMorphPlus.\\n\\t\\tgetIndex := aSpec getIndex.\\n\\t\\tsetIndex := aSpec setIndex.\\n\\t] ifNotNil:[\\n\\t\\tlistClass := PluggableListMorphByItemPlus.\\n\\t\\tgetIndex := aSpec getSelected.\\n\\t\\tsetIndex := aSpec setSelected.\\n\\t].\\n\\twidget := listClass on: aSpec model\\n\\t\\t\\t\\tlist: aSpec list\\n\\t\\t\\t\\tselected: getIndex\\n\\t\\t\\t\\tchangeSelected: setIndex\\n\\t\\t\\t\\tmenu: aSpec menu\\n\\t\\t\\t\\tkeystroke: aSpec keyPress.\\n\\tself register: widget id: aSpec name.\\n\\twidget dragItemSelector: aSpec dragItem.\\n\\twidget dropItemSelector: aSpec dropItem.\\n\\twidget wantsDropSelector: aSpec dropAccept.\\n\\twidget autoDeselect: aSpec autoDeselect.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec list ifNotNil:[panes add: aSpec list].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:27'!\\nbuildPluggableMultiSelectionList: aSpec\\n\\t| widget listClass |\\n\\taSpec getSelected ifNotNil:[^self error:'There is no PluggableListMorphOfManyByItem'].\\n\\tlistClass := PluggableListMorphOfMany.\\n\\twidget := listClass on: aSpec model\\n\\t\\tlist: aSpec list\\n\\t\\tprimarySelection: aSpec getIndex\\n\\t\\tchangePrimarySelection: aSpec setIndex\\n\\t\\tlistSelection: aSpec getSelectionList\\n\\t\\tchangeListSelection: aSpec setSelectionList\\n\\t\\tmenu: aSpec menu.\\n\\tself register: widget id: aSpec name.\\n\\twidget keystrokeActionSelector: aSpec keyPress.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec list ifNotNil:[panes add: aSpec list].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:28'!\\nbuildPluggablePanel: aSpec\\n\\t| widget children |\\n\\twidget := PluggablePanelMorph new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\twidget color: Color transparent.\\n\\twidget clipSubmorphs: true.\\n\\tchildren := aSpec children.\\n\\tchildren isSymbol ifTrue:[\\n\\t\\twidget getChildrenSelector: children.\\n\\t\\twidget update: children.\\n\\t\\tchildren := #().\\n\\t].\\n\\tself buildAll: children in: widget.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tself setLayout: aSpec layout in: widget.\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:28'!\\nbuildPluggableText: aSpec\\n\\t| widget |\\n\\twidget := PluggableTextMorphPlus on: aSpec model\\n\\t\\t\\t\\ttext: aSpec getText \\n\\t\\t\\t\\taccept: aSpec setText\\n\\t\\t\\t\\treadSelection: aSpec selection \\n\\t\\t\\t\\tmenu: aSpec menu.\\n\\tself register: widget id: aSpec name.\\n\\twidget getColorSelector: aSpec color.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec getText ifNotNil:[panes add: aSpec getText].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/15/2005 12:10'!\\nbuildPluggableTree: aSpec\\n\\t| widget |\\n\\twidget := PluggableTreeMorph new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\twidget getSelectedPathSelector: aSpec getSelectedPath.\\n\\twidget setSelectedSelector: aSpec setSelected.\\n\\twidget getChildrenSelector: aSpec getChildren.\\n\\twidget hasChildrenSelector: aSpec hasChildren.\\n\\twidget getLabelSelector: aSpec label.\\n\\twidget getIconSelector: aSpec icon.\\n\\twidget getHelpSelector: aSpec help.\\n\\twidget getMenuSelector: aSpec menu.\\n\\twidget keystrokeActionSelector: aSpec keyPress.\\n\\twidget getRootsSelector: aSpec roots.\\n\\twidget autoDeselect: aSpec autoDeselect.\\n\\twidget dropItemSelector: aSpec dropItem.\\n\\twidget wantsDropSelector: aSpec dropAccept.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec roots ifNotNil:[panes add: aSpec roots].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 9/17/2005 21:07'!\\nbuildPluggableWindow: aSpec\\n\\t| widget children label |\\n\\taSpec layout == #proportional ifFalse:[\\n\\t\\t\\\"This needs to be implemented - probably by adding a single pane and then the rest\\\"\\n\\t\\t^self error: 'Not implemented'.\\n\\t].\\n\\twidget := PluggableSystemWindow new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\t(label := aSpec label) ifNotNil:[\\n\\t\\tlabel isSymbol \\n\\t\\t\\tifTrue:[widget getLabelSelector: label]\\n\\t\\t\\tifFalse:[widget setLabel: label]].\\n\\tchildren := aSpec children.\\n\\tchildren isSymbol ifTrue:[\\n\\t\\twidget getChildrenSelector: children.\\n\\t\\twidget update: children.\\n\\t\\tchildren := #().\\n\\t].\\n\\twidget closeWindowSelector: aSpec closeAction.\\n\\tpanes := OrderedCollection new.\\n\\tself buildAll: children in: widget.\\n\\taSpec extent ifNotNil:[widget extent: aSpec extent].\\n\\twidget setUpdatablePanesFrom: panes.\\n\\t^widget! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/17/2005 00:00'!\\nadd: aMorph to: aParent\\n\\taParent addMorphBack: aMorph.\\n\\taParent isSystemWindow ifTrue:[\\n\\t\\taParent addPaneMorph: aMorph.\\n\\t].! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'stephaneducasse 2/3/2006 22:35'!\\nasFrame: aRectangle\\n\\t| frame |\\n\\taRectangle ifNil:[^nil].\\n\\tframe := LayoutFrame new.\\n\\tframe \\n\\t\\tleftFraction: aRectangle left; \\n\\t\\trightFraction: aRectangle right; \\n\\t\\ttopFraction: aRectangle top; \\n\\t\\tbottomFraction: aRectangle bottom.\\n\\t^frame! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/14/2005 22:28'!\\nregister: widget id: id\\n\\tid ifNil:[^self].\\n\\twidgets ifNil:[widgets := Dictionary new].\\n\\twidgets at: id put: widget.! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 2/12/2005 19:20'!\\nsetFrame: aRectangle in: widget\\n\\t| frame |\\n\\taRectangle ifNil:[^nil].\\n\\tframe := self asFrame: aRectangle.\\n\\twidget layoutFrame: frame.\\n\\twidget hResizing: #spaceFill; vResizing: #spaceFill.\\n\\t(parent isSystemWindow) ifTrue:[\\n\\t\\twidget borderWidth: 2; borderColor: #inset.\\n\\t].! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 2/10/2005 22:28'!\\nsetLayout: layout in: widget\\n\\tlayout == #proportional ifTrue:[\\n\\t\\twidget layoutPolicy: ProportionalLayout new.\\n\\t\\t^self].\\n\\tlayout == #horizontal ifTrue:[\\n\\t\\twidget layoutPolicy: TableLayout new.\\n\\t\\twidget listDirection: #leftToRight.\\n\\t\\twidget submorphsDo:[:m| m hResizing: #spaceFill; vResizing: #spaceFill].\\n\\t\\t\\\"and then some...\\\"\\n\\t\\t^self].\\n\\tlayout == #vertical ifTrue:[\\n\\t\\twidget layoutPolicy: TableLayout new.\\n\\t\\twidget listDirection: #topToBottom.\\n\\t\\twidget submorphsDo:[:m| m hResizing: #spaceFill; vResizing: #spaceFill].\\n\\t\\t\\\"and then some...\\\"\\n\\t\\t^self].\\n\\t^self error: 'Unknown layout: ', layout.! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/14/2005 22:30'!\\nwidgetAt: id ifAbsent: aBlock\\n\\twidgets ifNil:[^aBlock value].\\n\\t^widgets at: id ifAbsent: aBlock! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'building' stamp: 'ar 2/28/2006 17:30'!\\nbuildPluggableMenu: menuSpec \\n\\t| prior menu |\\n\\tprior := parentMenu.\\n\\tparentMenu := menu := MenuMorph new.\\n\\tmenuSpec label ifNotNil:[parentMenu addTitle: menuSpec label].\\n\\tmenuSpec items do:[:each| each buildWith: self].\\n\\tparentMenu := prior.\\n\\t^menu! !\\n\\n!MorphicToolBuilder methodsFor: 'building' stamp: 'ar 2/28/2006 17:37'!\\nbuildPluggableMenuItem: itemSpec\\n\\t| item action label menu |\\n\\titem _ MenuItemMorph new.\\n\\tlabel := itemSpec label.\\n\\titemSpec checked ifTrue:[label := '<on>', label] ifFalse:[label := '<off>', label].\\n\\titem contents: label.\\n\\titem isEnabled: itemSpec enabled.\\n\\t(action := itemSpec action) ifNotNil:[\\n\\t\\titem \\n\\t\\t\\ttarget: action receiver;\\n\\t\\t\\tselector: action selector;\\n\\t\\t\\targuments: action arguments.\\n\\t].\\n\\t(menu := itemSpec subMenu) ifNotNil:[\\n\\t\\titem subMenu: (menu buildWith: self).\\n\\t].\\n\\tparentMenu ifNotNil:[parentMenu addMorphBack: item].\\n\\t^item! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicToolBuilder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicToolBuilder class methodsFor: 'accessing' stamp: 'ar 2/11/2005 15:24'!\\nisActiveBuilder\\n\\t\\\"Answer whether I am the currently active builder\\\"\\n\\t^Smalltalk isMorphic! !\\nToolBuilderTests subclass: #MorphicToolBuilderTests\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicToolBuilderTests commentStamp: 'ar 2/11/2005 15:02' prior: 0!\\nTests for the Morphic tool builder.!\\n\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:26'!\\nacceptWidgetText\\n\\twidget hasUnacceptedEdits: true.\\n\\twidget accept.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 6/21/2005 10:35'!\\nbuttonWidgetEnabled\\n\\t\\\"Answer whether the current widget (a button) is currently enabled\\\"\\n\\t^widget enabled! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:22'!\\nchangeListWidget\\n\\twidget changeModelSelection: widget getCurrentSelectionIndex + 1.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:15'!\\nfireButtonWidget\\n\\twidget performAction.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'cwp 6/9/2005 00:11'!\\nfireMenuItemWidget\\n\\t(widget itemWithWording: 'Menu Item')\\n\\t\\tifNotNilDo: [:item | item doButtonAction]! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 14:46'!\\nsetUp\\n\\tsuper setUp.\\n\\tbuilder := MorphicToolBuilder new.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 21:43'!\\nwidgetColor\\n\\t\\\"Answer color from widget\\\"\\n\\t^widget color! !\\n\\n\\n!MorphicToolBuilderTests methodsFor: 'tests-window' stamp: 'ar 2/13/2005 13:52'!\\ntestWindowDynamicLabel\\n\\tself makeWindow.\\n\\tself assert: (widget label = 'TestLabel').! !\\n\\n!MorphicToolBuilderTests methodsFor: 'tests-window' stamp: 'ar 2/13/2005 13:52'!\\ntestWindowStaticLabel\\n\\t| spec |\\n\\tspec := builder pluggableWindowSpec new.\\n\\tspec model: self.\\n\\tspec children: #().\\n\\tspec label: 'TestLabel'.\\n\\twidget := builder build: spec.\\n\\tself assert: (widget label = 'TestLabel').! !\\nDisplayTransform subclass: #MorphicTransform\\n\\tinstanceVariableNames: 'offset angle scale'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Transformations'!\\n!MorphicTransform commentStamp: '<historical>' prior: 0!\\nThis class implements simple translation, scaling and rotation for points, as well as inverse transformations. These transformations are used in TransformMorphs (clipping scrollers) and TransformationMorphs (general flex-morph wrappers) to map, eg, global mouse coords into local coords, and to invert, eg, local damage rectangles into global damage rectangles.!\\n\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nangle\\n\\t^ angle! !\\n\\n!MorphicTransform methodsFor: 'accessing' stamp: 'ar 11/9/1998 14:33'!\\ninverseTransformation\\n\\t\\\"Return the inverse transformation of the receiver\\\"\\n\\t^MorphicTransform\\n\\t\\toffset: (self transform: 0@0) - (self transform: offset)\\n\\t\\tangle: angle negated\\n\\t\\tscale: scale reciprocal! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\noffset\\n\\t^ offset\\n! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nscale\\n\\t^ scale! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithAngle: a\\n\\t\\\"Return a copy of me with a different Angle\\\"\\n\\t^ self copy setAngle: a! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithOffset: a\\n\\t\\\"Return a copy of me with a different Offset\\\"\\n\\t^ self copy setOffset: a! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithScale: a\\n\\t\\\"Return a copy of me with a different Scale\\\"\\n\\t^ self copy setScale: a! !\\n\\n\\n!MorphicTransform methodsFor: 'composing' stamp: 'nk 3/9/2001 13:55'!\\ncomposedWithLocal: aTransform\\n\\taTransform isIdentity ifTrue:[^self].\\n\\tself isIdentity ifTrue:[^aTransform].\\n\\taTransform isMorphicTransform ifFalse:[^super composedWithLocal: aTransform].\\n\\tself isPureTranslation ifTrue:[\\n\\t\\t^aTransform withOffset: aTransform offset + self offset].\\n\\taTransform isPureTranslation ifTrue:[\\n\\t\\t^self withOffset: (self localPointToGlobal: aTransform offset negated) negated].\\n\\t^super composedWithLocal: aTransform.! !\\n\\n\\n!MorphicTransform methodsFor: 'converting' stamp: 'ar 11/2/1998 20:14'!\\nasMatrixTransform2x3\\n\\t^((MatrixTransform2x3 withRotation: angle radiansToDegrees negated) composedWithLocal:\\n\\t\\t(MatrixTransform2x3 withScale: scale))\\n\\t\\t\\toffset: offset negated! !\\n\\n!MorphicTransform methodsFor: 'converting' stamp: 'di 10/26/1999 17:03'!\\nasMorphicTransform\\n\\n\\t^ self! !\\n\\n\\n!MorphicTransform methodsFor: 'initialize' stamp: 'ar 11/2/1998 20:58'!\\nsetIdentiy\\n\\tscale _ 1.0.\\n\\toffset _ 0@0.\\n\\tangle _ 0.0.! !\\n\\n\\n!MorphicTransform methodsFor: 'printing' stamp: 'ar 5/19/1999 18:21'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut:$(;\\n\\t\\tnextPutAll:'angle = '; print: angle;\\n\\t\\tnextPutAll:'; scale = '; print: scale;\\n\\t\\tnextPutAll:'; offset = '; print: offset;\\n\\t\\tnextPut:$).! !\\n\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 20:57'!\\nisIdentity\\n\\t\\\"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself.\\\"\\n\\n\\t^ self isPureTranslation and: [offset = (0@0)]\\n! !\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 19:51'!\\nisMorphicTransform\\n\\t^true! !\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 20:57'!\\nisPureTranslation\\n\\t\\\"Return true if the receiver specifies no rotation or scaling.\\\"\\n\\n\\t^ angle = 0.0 and: [scale = 1.0]\\n! !\\n\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 3/4/98 19:10'!\\ncomposedWith: aTransform\\n\\t\\\"Return a new transform that has the effect of transforming points first by the receiver and then by the argument.\\\"\\n\\n\\tself isIdentity ifTrue: [^ aTransform].\\n\\taTransform isIdentity ifTrue: [^ self].\\n\\t^ CompositeTransform new globalTransform: self\\n\\t\\t\\t\\t\\t\\t\\tlocalTransform: aTransform! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/28/1999 09:10'!\\ninvert: aPoint\\n\\t\\\"Transform the given point from local to global coordinates.\\\"\\n\\t| p3 p2 |\\n\\tself isPureTranslation ifTrue: [^ aPoint - offset].\\n\\tp3 _ aPoint * scale.\\n\\tp2 _ ((p3 x * angle cos) + (p3 y * angle sin))\\n\\t\\t@ ((p3 y * angle cos) - (p3 x * angle sin)).\\n\\t^ (p2 - offset)\\n! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/3/1998 00:18'!\\ninvertBoundsRect: aRectangle\\n\\t\\\"Return a rectangle whose coordinates have been transformed\\n\\tfrom local back to global coordinates. NOTE: if the transformation\\n\\tis not just a translation, then it will compute the bounding box\\n\\tin global coordinates.\\\"\\n\\t| outerRect |\\n\\tself isPureTranslation\\n\\tifTrue:\\n\\t\\t[^ (self invert: aRectangle topLeft)\\n\\t\\t\\tcorner: (self invert: aRectangle bottomRight)]\\n\\tifFalse:\\n\\t\\t[outerRect _ Rectangle encompassing:\\n\\t\\t\\t(aRectangle innerCorners collect: [:p | self invert: p]).\\n\\t\\t\\\"Following asymmetry due to likely subsequent truncation\\\"\\n\\t\\t^ outerRect topLeft - (1@1) corner: outerRect bottomRight + (2@2)]! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/2/1998 08:54'!\\ninvertRect: aRectangle\\n\\n\\tself error: 'method name changed to emphasize enclosing bounds'.\\n\\t^ self invertBoundsRect: aRectangle! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/28/1999 09:05'!\\ntransform: aPoint\\n\\t\\\"Transform the given point from global to local coordinates.\\\"\\n\\t| p2 p3 |\\n\\tself isPureTranslation ifTrue: [^ aPoint + offset].\\n\\tp2 _ aPoint + offset.\\n\\tp3 _ (((p2 x * angle cos) - (p2 y * angle sin))\\n\\t\\t@ ((p2 y * angle cos) + (p2 x * angle sin)))\\n\\t\\t\\t/ scale.\\n\\t^ p3! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/3/1998 00:18'!\\ntransformBoundsRect: aRectangle\\n\\t\\\"Return a rectangle whose coordinates have been transformed\\n\\tfrom global to local coordinates. NOTE: if the transformation\\n\\tis not just a translation, then it will compute the bounding box\\n\\tin global coordinates.\\\"\\n\\t| outerRect |\\n\\tself isPureTranslation\\n\\tifTrue:\\n\\t\\t[^ (self transform: aRectangle topLeft)\\n\\t\\t\\tcorner: (self transform: aRectangle bottomRight)]\\n\\tifFalse:\\n\\t\\t[outerRect _ Rectangle encompassing:\\n\\t\\t\\t(aRectangle innerCorners collect: [:p | self transform: p]).\\n\\t\\t\\\"Following asymmetry due to likely subsequent truncation\\\"\\n\\t\\t^ outerRect topLeft - (1@1) corner: outerRect bottomRight + (2@2)]! !\\n\\n\\n!MorphicTransform methodsFor: 'transforming points' stamp: 'ar 11/2/1998 16:13'!\\nglobalPointToLocal: aPoint\\n\\t\\\"Transform aPoint from global coordinates into local coordinates\\\"\\n\\t^self transform: aPoint! !\\n\\n!MorphicTransform methodsFor: 'transforming points' stamp: 'ar 11/2/1998 16:32'!\\nlocalPointToGlobal: aPoint\\n\\t\\\"Transform aPoint from global coordinates into local coordinates\\\"\\n\\t^self invert: aPoint! !\\n\\n\\n!MorphicTransform methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ls 10/9/1999 19:06'!\\nencodeForRemoteCanvas\\n\\t\\\"encode this transform into a string for use by a RemoteCanvas\\\"\\n\\t^String streamContents: [ :str |\\n\\t\\tstr nextPutAll: 'Morphic,';\\n\\t\\t\\tprint: offset x truncated;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: offset y truncated;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: scale;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: angle\\n\\t]! !\\n\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetAngle: aFloat\\n\\n\\tangle _ aFloat.\\n! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetOffset: aPoint\\n\\n\\toffset _ aPoint.\\n! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetOffset: aPoint angle: a scale: s\\n\\n\\toffset _ aPoint.\\n\\tangle _ a.\\n\\tscale _ s! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetScale: aFloat\\n\\n\\tscale _ aFloat.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicTransform class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\nidentity\\n\\n\\t^ self offset: 0@0 angle: 0.0 scale: 1.0! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\nnew\\n\\n\\t^ self offset: 0@0\\n! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\noffset: aPoint\\n\\n\\t^ self offset: aPoint angle: 0.0 scale: 1.0! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\noffset: aPoint angle: a scale: s\\n\\n\\t^ self basicNew setOffset: aPoint angle: a scale: s! !\\n\\n\\n!MorphicTransform class methodsFor: '*nebraska-instance creation' stamp: 'sd 11/20/2005 21:25'!\\nfromRemoteCanvasEncoding: encoded\\n\\t\\\"DisplayTransform fromRemoteCanvasEncoding: 'Morphic,-88,-128,1.345165663873898,0.1352584843149221'\\\"\\n\\t| type offsetXEnc offsetYEnc scaleEnc angleEnc offsetX offsetY angle scale rs |\\n\\n\\t\\\"separate the numbers\\\"\\n\\trs := ReadStream on: encoded.\\n\\ttype := rs upTo: $,.\\n\\toffsetXEnc := rs upTo: $,.\\n\\toffsetYEnc := rs upTo: $,.\\n\\tscaleEnc := rs upTo: $,.\\n\\tangleEnc := rs upToEnd.\\n\\n\\t\\\"decode the numbers\\\"\\n\\toffsetX := Integer readFromString: offsetXEnc.\\n\\toffsetY := Integer readFromString: offsetYEnc.\\n\\n\\tscale := Number readFromString: scaleEnc.\\n\\tangle := Number readFromString: angleEnc.\\n\\n\\t\\\"create an instance\\\"\\n\\t^self offset: offsetX@offsetY angle: angle scale: scale! !\\nUIManager subclass: #MorphicUIManager\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicUIManager commentStamp: 'ar 2/11/2005 21:52' prior: 0!\\nThe Morphic ui manager.!\\n\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/16/2005 19:37'!\\nchooseDirectory: label from: dir\\n\\t\\\"Let the user choose a directory\\\"\\n\\t^FileList2 modalFolderSelector: dir! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/17/2005 00:28'!\\nchooseFileMatching: patterns label: aString\\n\\t\\\"Let the user choose a file matching the given patterns\\\"\\n\\t| result |\\n\\tresult := FileList2 modalFileSelectorForSuffixes: patterns.\\n\\t^result ifNotNil:[result fullName]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 10:47'!\\nchooseFrom: aList lines: linesArray title: aString\\n\\t\\\"Choose an item from the given list. Answer the index of the selected item.\\\"\\n\\t| menu |\\n\\tmenu := PopUpMenu labelArray: aList lines: linesArray.\\n\\t^aString isEmpty ifTrue:[menu startUp] ifFalse:[menu startUpWithCaption: aString]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/15/2005 23:44'!\\nchooseFrom: labelList values: valueList lines: linesArray title: aString\\n\\t\\\"Choose an item from the given list. Answer the selected item.\\\"\\n\\t| menu |\\n\\tmenu := SelectionMenu labels: labelList lines: linesArray selections: valueList.\\n\\t^aString isEmpty ifTrue:[menu startUp] ifFalse:[menu startUpWithCaption: aString]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:45'!\\nconfirm: queryString\\n\\t\\\"Put up a yes/no menu with caption queryString. Answer true if the \\n\\tresponse is yes, false if no. This is a modal question--the user must \\n\\trespond yes or no.\\\"\\n\\t^PopUpMenu confirm: queryString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 09:49'!\\nconfirm: aString orCancel: cancelBlock\\n\\t\\\"Put up a yes/no/cancel menu with caption aString. Answer true if \\n\\tthe response is yes, false if no. If cancel is chosen, evaluate \\n\\tcancelBlock. This is a modal question--the user must respond yes or no.\\\"\\n\\t^PopUpMenu confirm: aString orCancel: cancelBlock! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:13'!\\ndisplayProgress: titleString at: aPoint from: minVal to: maxVal during: workBlock\\n\\t\\\"Display titleString as a caption over a progress bar while workBlock is evaluated.\\\"\\n\\t^ProgressInitiationException \\n\\t\\tdisplay: titleString\\n\\t\\tat: aPoint \\n\\t\\tfrom: minVal \\n\\t\\tto: maxVal \\n\\t\\tduring: workBlock! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/17/2005 00:27'!\\nedit: aText label: labelString accept: anAction\\n\\t\\\"Open an editor on the given string/text\\\"\\n\\t| window holder text |\\n\\tholder := StringHolder new.\\n\\tholder contents: aText.\\n\\ttext := PluggableTextMorphPlus \\n\\t\\ton: holder \\n\\t\\ttext: #contents \\n\\t\\taccept: #acceptContents: \\n\\t\\treadSelection: nil \\n\\t\\tmenu: nil.\\n\\ttext acceptAction: anAction.\\n\\twindow := SystemWindow new.\\n\\tlabelString ifNotNil:[window setLabel: labelString].\\n\\twindow addMorph: text frame: (0@0 extent: 1@1).\\n\\twindow paneColor: Color gray.\\n\\twindow openInWorld.\\n! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:07'!\\ninformUserDuring: aBlock\\n\\t\\\"Display a message above (or below if insufficient room) the cursor \\n\\tduring execution of the given block.\\n\\t\\tUIManager default informUserDuring:[:bar|\\n\\t\\t\\t#(one two three) do:[:info|\\n\\t\\t\\t\\tbar value: info.\\n\\t\\t\\t\\t(Delay forSeconds: 1) wait]]\\\"\\n\\t(MVCMenuMorph from: (SelectionMenu labels: '') title: '\\t\\t\\t\\t\\t\\t')\\n\\t\\tinformUserAt: Sensor cursorPoint during: aBlock.! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:46'!\\ninform: aString\\n\\t\\\"Display a message for the user to read and then dismiss\\\"\\n\\t^PopUpMenu inform: aString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:05'!\\nmultiLineRequest: queryString centerAt: aPoint initialAnswer: defaultAnswer answerHeight: answerHeight\\n\\t\\\"Create a multi-line instance of me whose question is queryString with\\n\\tthe given initial answer. Invoke it centered at the given point, and\\n\\tanswer the string the user accepts. Answer nil if the user cancels. An\\n\\tempty string returned means that the ussr cleared the editing area and\\n\\tthen hit 'accept'. Because multiple lines are invited, we ask that the user\\n\\tuse the ENTER key, or (in morphic anyway) hit the 'accept' button, to \\n\\tsubmit; that way, the return key can be typed to move to the next line.\\\"\\n\\t^FillInTheBlank multiLineRequest: queryString centerAt: aPoint initialAnswer: defaultAnswer answerHeight: answerHeight! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:47'!\\nrequestPassword: queryString\\n\\t\\\"Create an instance of me whose question is queryString. Invoke it centered\\n\\tat the cursor, and answer the string the user accepts. Answer the empty \\n\\tstring if the user cancels.\\\"\\n\\t^FillInTheBlank requestPassword: queryString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:46'!\\nrequest: queryString initialAnswer: defaultAnswer \\n\\t\\\"Create an instance of me whose question is queryString with the given \\n\\tinitial answer. Invoke it centered at the given point, and answer the \\n\\tstring the user accepts. Answer the empty string if the user cancels.\\\"\\n\\t^FillInTheBlank request: queryString initialAnswer: defaultAnswer ! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicUIManager class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicUIManager class methodsFor: 'accessing' stamp: 'ar 2/11/2005 15:41'!\\nisActiveManager\\n\\t\\\"Answer whether I should act as the active ui manager\\\"\\n\\t^Smalltalk isMorphic! !\\nMorphicEvent subclass: #MorphicUnknownEvent\\n\\tinstanceVariableNames: 'type argument'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'EventSensorConstants'\\n\\tcategory: 'Morphic-Events'!\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 20:04'!\\nargument\\n\\t^argument! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 20:04'!\\nargument: arg\\n\\targument _ arg! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 19:55'!\\nposition\\n\\t^0@0! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 19:55'!\\ntype\\n\\t^type! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'initialize' stamp: 'ar 10/26/2000 01:20'!\\ntype: eventType readFrom: aStream\\n\\t| typeAndArg |\\n\\ttimeStamp _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ttypeAndArg _ Object readFrom: aStream.\\n\\ttype _ typeAndArg first.\\n\\targument _ typeAndArg last.! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'objects from disk' stamp: 'RAA 12/20/2000 17:48'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\ttype ifNil: [type _ #startSound].\\n\\tsource ifNil: [source _ varDict at: 'sourceHand'].\\n\\targument ifNil: [argument _ varDict at: 'sound' ifAbsent: [nil]].\\t\\\"???\\\"\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'printing' stamp: 'ar 10/26/2000 01:19'!\\nstoreOn: aStream\\n\\taStream nextPutAll: 'unknown'.\\n\\taStream space.\\n\\tself timeStamp storeOn: aStream.\\n\\taStream space.\\n\\t{type. argument} storeOn: aStream.! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'private' stamp: 'ar 10/25/2000 19:59'!\\nsetType: evtType argument: arg\\n\\ttype _ evtType.\\n\\targument _ arg.! !\\n\\n!MorphicUnknownEvent methodsFor: 'private' stamp: 'ar 10/25/2000 19:58'!\\nsetType: evtType argument: arg hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\targument _ arg.\\n\\tsource _ evtHand.\\n\\ttimeStamp _ stamp.! !\\nMorph subclass: #MouseActionIndicatorMorph\\n\\tinstanceVariableNames: 'siblings'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!MouseActionIndicatorMorph commentStamp: '<historical>' prior: 0!\\nI am used to highlight morphs which have a special mouseup action!\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:49'!\\ndeleteWithSiblings\\n\\n\\tsiblings do: [ :each | each delete]\\n! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:49'!\\nsiblings: aCollection\\n\\n\\tsiblings _ aCollection.\\n! !\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/12/2000 10:48'!\\nhandlesMouseOver: evt\\n\\n\\t^true! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/17/2000 09:52'!\\nhandlesMouseOverDragging: evt\\n\\n\\t^true! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/12/2000 10:50'!\\nmouseEnter: evt\\n\\n\\tself deleteWithSiblings\\n! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/17/2000 09:52'!\\nmouseEnterDragging: evt\\n\\n\\tself deleteWithSiblings\\n! !\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'initialization' stamp: 'RAA 7/12/2000 10:48'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tsiblings _ #().! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMouseActionIndicatorMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MouseActionIndicatorMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 11:08'!\\nworld: aWorld inner: innerRectangle outer: outerRectangle color: aColor\\n\\n\\t| allRects allMorphs |\\n\\n\\tallRects _ outerRectangle areasOutside: innerRectangle.\\n\\tallMorphs _ allRects collect: [ :each |\\n\\t\\tself new bounds: each; color: aColor\\n\\t].\\n\\tallMorphs do: [ :each |\\n\\t\\teach siblings: allMorphs; openInWorld: aWorld\\n\\t].\\n\\t^allMorphs\\n\\n\\n! !\\nMouseEvent subclass: #MouseButtonEvent\\n\\tinstanceVariableNames: 'whichButton'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:58'!\\nblueButtonChanged\\n\\t\\\"Answer true if the blue mouse button has changed. This is the third mouse button or cmd+click on the Mac.\\\"\\n\\n\\t^ whichButton anyMask: 1! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:58'!\\nredButtonChanged\\n\\t\\\"Answer true if the red mouse button has changed. This is the first mouse button.\\\"\\n\\n\\t^ whichButton anyMask: 4! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'nk 3/11/2004 17:44'!\\nwhichButton\\n\\t^whichButton! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:59'!\\nyellowButtonChanged\\n\\t\\\"Answer true if the yellow mouse button has changed. This is the second mouse button or option+click on the Mac.\\\"\\n\\n\\t^ whichButton anyMask: 2! !\\n\\n\\n!MouseButtonEvent methodsFor: 'dispatching' stamp: 'ar 9/16/2000 13:05'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseDown ifTrue:[^anObject handleMouseDown: self].\\n\\ttype == #mouseUp ifTrue:[^anObject handleMouseUp: self].\\n\\t^super sentTo: anObject! !\\n\\n\\n!MouseButtonEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:29'!\\ntype: eventType readFrom: aStream\\n\\tsuper type: eventType readFrom: aStream.\\n\\taStream skip: 1.\\n\\twhichButton _ Integer readFrom: aStream.! !\\n\\n\\n!MouseButtonEvent methodsFor: 'printing' stamp: 'ar 10/24/2000 16:29'!\\nstoreOn: aStream\\n\\tsuper storeOn: aStream.\\n\\taStream space.\\n\\twhichButton storeOn: aStream.! !\\n\\n\\n!MouseButtonEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'dgd 2/22/2003 19:00'!\\ndecodeFromStringArray: array \\n\\t\\\"decode the receiver from an array of strings\\\"\\n\\n\\ttype := array first asSymbol.\\n\\tposition := CanvasDecoder decodePoint: (array second).\\n\\tbuttons := CanvasDecoder decodeInteger: (array third).\\n\\twhichButton := CanvasDecoder decodeInteger: (array fourth)! !\\n\\n!MouseButtonEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:24'!\\nencodedAsStringArray\\n\\t\\\"encode the receiver into an array of strings, such that it can be retrieved via the fromStringArray: class method\\\"\\n\\t^{\\n\\t\\ttype.\\n\\t\\tCanvasEncoder encodePoint: position.\\n\\t\\tCanvasEncoder encodeInteger: buttons.\\n\\t\\tCanvasEncoder encodeInteger: whichButton.\\n\\t}! !\\n\\n\\n!MouseButtonEvent methodsFor: 'private' stamp: 'ar 10/5/2000 23:55'!\\nsetType: evtType position: evtPos which: button buttons: evtButtons hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\tposition _ evtPos.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.\\n\\twhichButton _ button.\\n\\ttimeStamp _ stamp.! !\\nObject subclass: #MouseClickState\\n\\tinstanceVariableNames: 'clickClient clickState firstClickDown firstClickUp firstClickTime clickSelector dblClickSelector dblClickTime dblClickTimeoutSelector dragSelector dragThreshold'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MouseClickState commentStamp: '<historical>' prior: 0!\\nMouseClickState is a simple class managing the distinction between clicks, double clicks, and drag operations. It has been factored out of HandMorph due to the many instVars.\\n\\nInstance variables:\\n\\tclickClient \\t<Morph>\\t\\tThe client wishing to receive #click:, #dblClick:, or #drag messages\\n\\tclickState \\t<Symbol>\\tThe internal state of handling the last event (#firstClickDown, #firstClickUp, #firstClickTimedOut)\\n\\tfirstClickDown \\t<MorphicEvent>\\tThe #mouseDown event after which the client wished to receive #click: or similar messages\\n\\tfirstClickUp \\t<MorphicEvent>\\tThe first mouse up event which came in before the double click time out was exceeded (it is sent if there is a timout after the first mouse up event occured)\\n\\tfirstClickTime \\t<Integer>\\tThe millisecond clock value of the first event\\n\\tclickSelector \\t<Symbol>\\tThe selector to use for sending #click: messages\\n\\tdblClickSelector \\t<Symbol>\\tThe selector to use for sending #doubleClick: messages\\n\\tdblClickTime \\t<Integer>\\tTimout in milliseconds for a double click operation\\n\\tdragSelector \\t<Symbol>\\tThe selector to use for sending #drag: messages\\n\\tdragThreshold \\t<Integer>\\tThreshold used for determining if a #drag: message is sent (pixels!!)\\n!\\n\\n\\n!MouseClickState methodsFor: 'as yet unclassified' stamp: 'nk 7/26/2004 09:13'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $[; print: clickState; nextPut: $]\\n! !\\n\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:23'!\\nclick\\n\\n\\tclickSelector ifNotNil: [clickClient perform: clickSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:24'!\\ndoubleClick\\n\\n\\tdblClickSelector ifNotNil: [clickClient perform: dblClickSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 13:09'!\\ndoubleClickTimeout\\n\\n\\tdblClickTimeoutSelector ifNotNil: [\\n\\t\\tclickClient perform: dblClickTimeoutSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:27'!\\ndrag: event\\n\\n\\tdragSelector ifNotNil: [clickClient perform: dragSelector with: event]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'nk 7/26/2004 10:21'!\\nhandleEvent: evt from: aHand\\n\\t\\\"Process the given mouse event to detect a click, double-click, or drag.\\n\\tReturn true if the event should be processed by the sender, false if it shouldn't.\\n\\tNOTE: This method heavily relies on getting *all* mouse button events.\\\"\\n\\t| localEvt timedOut isDrag |\\n\\ttimedOut _ (evt timeStamp - firstClickTime) > dblClickTime.\\n\\tlocalEvt _ evt transformedBy: (clickClient transformedFrom: aHand owner).\\n\\tisDrag _ (localEvt position - firstClickDown position) r > dragThreshold.\\n\\tclickState == #firstClickDown ifTrue: [\\n\\t\\t\\\"Careful here - if we had a slow cycle we may have a timedOut mouseUp event\\\"\\n\\t\\t(timedOut and:[localEvt isMouseUp not]) ifTrue:[\\n\\t\\t\\t\\\"timeout before #mouseUp -> keep waiting for drag if requested\\\"\\n\\t\\t\\tclickState _ #firstClickTimedOut.\\n\\t\\t\\tdragSelector ifNil:[\\n\\t\\t\\t\\taHand resetClickState.\\n\\t\\t\\t\\tself doubleClickTimeout; click \\\"***\\\"].\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseUp ifTrue:[\\n\\n\\t\\t\\t(timedOut or:[dblClickSelector isNil]) ifTrue:[\\n\\t\\t\\t\\tself click.\\n\\t\\t\\t\\taHand resetClickState.\\n\\t\\t\\t\\t^true].\\n\\t\\t\\t\\\"Otherwise transfer to #firstClickUp\\\"\\n\\t\\t\\tfirstClickUp _ evt copy.\\n\\t\\t\\tclickState _ #firstClickUp.\\n\\t\\t\\t\\\"If timedOut or the client's not interested in dbl clicks get outta here\\\"\\n\\t\\t\\tself click.\\n\\t\\t\\taHand handleEvent: firstClickUp.\\n\\t\\t\\t^false].\\n\\t\\tisDrag ifTrue:[\\\"drag start\\\"\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tdragSelector \\\"If no drag selector send #click instead\\\"\\n\\t\\t\\t\\tifNil: [self click]\\n\\t\\t\\t\\tifNotNil: [self drag: firstClickDown].\\n\\t\\t\\t^true].\\n\\t\\t^false].\\n\\n\\tclickState == #firstClickTimedOut ifTrue:[\\n\\t\\tlocalEvt isMouseUp ifTrue:[\\\"neither drag nor double click\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout; click. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tisDrag ifTrue:[\\\"drag start\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout; drag: firstClickDown. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\t^false].\\n\\n\\tclickState = #firstClickUp ifTrue:[\\n\\t\\t(timedOut) ifTrue:[\\n\\t\\t\\t\\\"timed out after mouseUp - signal timeout and pass the event\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseDown ifTrue:[\\\"double click\\\"\\n\\t\\t\\tclickState _ #secondClickDown.\\n\\t\\t\\t^false]].\\n\\n\\tclickState == #secondClickDown ifTrue: [\\n\\t\\ttimedOut ifTrue:[\\n\\t\\t\\t\\\"timed out after second mouseDown - pass event after signaling timeout\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tisDrag ifTrue: [\\\"drag start\\\"\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tdragSelector \\\"If no drag selector send #click instead\\\"\\n\\t\\t\\t\\tifNil: [self click]\\n\\t\\t\\t\\tifNotNil: [self drag: firstClickDown].\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseUp ifTrue: [\\\"double click\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClick.\\n\\t\\t\\t^false]\\n\\t].\\n\\n\\t^true\\n! !\\n\\n\\n!MouseClickState methodsFor: 'initialize' stamp: 'jcg 9/21/2001 13:08'!\\nclient: aMorph click: aClickSelector dblClick: aDblClickSelector dblClickTime: timeOut dblClickTimeout: aDblClickTimeoutSelector drag: aDragSelector threshold: aNumber event: firstClickEvent\\n\\tclickClient _ aMorph.\\n\\tclickSelector _ aClickSelector.\\n\\tdblClickSelector _ aDblClickSelector.\\n\\tdblClickTime _ timeOut.\\n\\tdblClickTimeoutSelector _ aDblClickTimeoutSelector.\\n\\tdragSelector _ aDragSelector.\\n\\tdragThreshold _ aNumber.\\n\\tfirstClickDown _ firstClickEvent.\\n\\tfirstClickTime _ firstClickEvent timeStamp.\\n\\tclickState _ #firstClickDown.! !\\nUserInputEvent subclass: #MouseEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 22:51'!\\ncursorPoint\\n\\t\\\"Answer the location of the cursor's hotspot when this event occured.\\\"\\n\\n\\t^ position! !\\n\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nanyButtonPressed\\n\\t\\\"Answer true if any mouse button is being pressed.\\\"\\n\\n\\t^ buttons anyMask: self class anyButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nblueButtonPressed\\n\\t\\\"Answer true if the blue mouse button is being pressed. This is the third mouse button or cmd+click on the Mac.\\\"\\n\\n\\t^ buttons anyMask: self class blueButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nredButtonPressed\\n\\t\\\"Answer true if the red mouse button is being pressed. This is the first mouse button.\\\"\\n\\n\\t^ buttons anyMask: self class redButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'ar 9/15/2000 22:51'!\\ntargetPoint\\n\\t\\\"Answer the location of the cursor's hotspot, adjusted by the offset\\n\\tof the last mouseDown relative to the recipient morph.\\\"\\n\\n\\t^ position - source targetOffset! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nyellowButtonPressed\\n\\t\\\"Answer true if the yellow mouse button is being pressed. This is the second mouse button or option+click on the Mac.\\\"\\n\\n\\t^ buttons anyMask: self class yellowButton! !\\n\\n\\n!MouseEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:50'!\\n= aMorphicEvent\\n\\tsuper = aMorphicEvent ifFalse:[^false].\\n\\tposition = aMorphicEvent position ifFalse: [^ false].\\n\\tbuttons = aMorphicEvent buttons ifFalse: [^ false].\\n\\t^ true\\n! !\\n\\n!MouseEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:47'!\\nhash\\n\\t^ position hash + buttons hash! !\\n\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/10/2000 21:17'!\\nasMouseEnter\\n\\t^self clone setType: #mouseEnter! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/10/2000 21:17'!\\nasMouseLeave\\n\\t^self clone setType: #mouseLeave! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/6/2000 18:59'!\\nasMouseMove\\n\\t\\\"Convert the receiver into a mouse move\\\"\\n\\t^MouseMoveEvent new setType: #mouseMove startPoint: position endPoint: position trail: {position. position} buttons: buttons hand: source stamp: Time millisecondClockValue.! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 9/25/2000 14:29'!\\nasMouseOver\\n\\t\\\"Convert the receiver into a mouse over event\\\"\\n\\t^MouseEvent new setType: #mouseOver position: position buttons: buttons hand: source! !\\n\\n\\n!MouseEvent methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:15'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseOver ifTrue:[^anObject handleMouseOver: self].\\n\\ttype == #mouseEnter ifTrue:[^anObject handleMouseEnter: self].\\n\\ttype == #mouseLeave ifTrue:[^anObject handleMouseLeave: self].\\n\\t^super sentTo: anObject.! !\\n\\n\\n!MouseEvent methodsFor: 'initialize' stamp: 'ar 10/25/2000 22:08'!\\ntype: eventType readFrom: aStream\\n\\t| x y |\\n\\ttype _ eventType.\\n\\ttimeStamp _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\tbuttons _ Integer readFrom: aStream.\\n\\tposition _ x@y.\\n! !\\n\\n\\n!MouseEvent methodsFor: 'printing' stamp: 'ar 10/7/2000 22:01'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $[.\\n\\taStream nextPutAll: self cursorPoint printString; space.\\n\\taStream nextPutAll: type; space.\\n\\taStream nextPutAll: self modifierString.\\n\\taStream nextPutAll: self buttonString.\\n\\taStream nextPutAll: timeStamp printString.\\n\\taStream nextPut: $].! !\\n\\n!MouseEvent methodsFor: 'printing' stamp: 'ar 10/25/2000 22:09'!\\nstoreOn: aStream\\n\\n\\taStream nextPutAll: type.\\n\\taStream space.\\n\\tself timeStamp storeOn: aStream.\\n\\taStream space.\\n\\tposition x storeOn: aStream.\\n\\taStream space.\\n\\tposition y storeOn: aStream.\\n\\taStream space.\\n\\tbuttons storeOn: aStream.! !\\n\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 10/5/2000 19:43'!\\nisDraggingEvent\\n\\tsource ifNil:[^false].\\n\\tsource hasSubmorphs ifTrue:[^true].\\n\\tself anyButtonPressed ifTrue:[^true].\\n\\t^false! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:30'!\\nisMouse\\n\\t^true! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseDown\\n\\t^self type == #mouseDown! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseEnter\\n\\t^self type == #mouseEnter! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseLeave\\n\\t^self type == #mouseLeave! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseMove\\n\\t^self type == #mouseMove! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseUp\\n\\t^self type == #mouseUp! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:29'!\\nisMove\\n\\t^false! !\\n\\n\\n!MouseEvent methodsFor: 'private' stamp: 'ar 10/10/2000 21:15'!\\nsetType: aSymbol\\n\\t\\\"For quick conversion between event types\\\"\\n\\ttype _ aSymbol.! !\\n\\n!MouseEvent methodsFor: 'private' stamp: 'ar 9/15/2000 22:53'!\\nsetType: evtType position: evtPos buttons: evtButtons hand: evtHand\\n\\ttype _ evtType.\\n\\tposition _ evtPos.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMouseEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nanyButton\\n\\t^ 7! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nblueButton\\n\\t^ 1! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nredButton\\n\\t^ 4! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nyellowButton\\n\\t^ 2! !\\nController subclass: #MouseMenuController\\n\\tinstanceVariableNames: 'redButtonMenu redButtonMessages'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Kernel-Remnants'!\\n!MouseMenuController commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:28'!\\ncontrolActivity\\n\\t\\\"Refer to the comment in Controller|controlActivity.\\\"\\n\\t| cursorPoint |\\n\\tcursorPoint _ sensor cursorPoint.\\n\\tsuper controlActivity.\\n\\t(cursorPoint = sensor cursorPoint and: [self viewHasCursor])\\n\\t\\tifTrue: \\n\\t\\t\\t[sensor redButtonPressed ifTrue: [^ self redButtonActivity].\\n\\t\\t\\tsensor yellowButtonPressed ifTrue: [^ self yellowButtonActivity].\\n\\t\\t\\tsensor blueButtonPressed ifTrue: [^ self blueButtonActivity]]! !\\n\\n!MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 11:24'!\\nisControlActive \\n\\t\\\"In contrast to class Controller, only blue button but not yellow button\\n\\tevents will end the receiver's control loop.\\\"\\n\\n\\t^ self viewHasCursor and: [sensor blueButtonPressed not]! !\\n\\n\\n!MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'!\\nrelease\\n\\tsuper release.\\n\\tredButtonMenu release! !\\n\\n!MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'!\\nreset\\n\\t\\\"Eliminate references to all mouse button menus.\\\"\\n\\n\\tredButtonMenu _ nil.\\n\\tredButtonMessages _ nil! !\\n\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 15:01'!\\nblueButtonActivity\\n\\t\\\"This normally opens the window menu. It is a no-op here\\n\\tas only the StandardSystemController deals with that kind\\n\\tof menus.\\\"! !\\n\\n!MouseMenuController methodsFor: 'menu messages'!\\nperformMenuMessage: aSelector\\n\\t\\\"Perform a menu command by sending self the message aSelector.\\n\\t Default does nothing special.\\\"\\n\\n\\t^self perform: aSelector! !\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:56'!\\nredButtonActivity\\n\\t\\\"Determine which item in the red button pop-up menu is selected. If one \\n\\tis selected, then send the corresponding message to the object designated \\n\\tas the menu message receiver.\\\"\\n\\n\\t| index |\\n\\tredButtonMenu ~~ nil\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ redButtonMenu startUp.\\n\\t\\t\\tindex ~= 0 \\n\\t\\t\\t\\tifTrue: [self perform: (redButtonMessages at: index)]]\\n\\t\\tifFalse: [super controlActivity]! !\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:59'!\\nyellowButtonActivity\\n\\t\\\"This normally opens a popup menu. Determine the selected\\n\\titem and, if one is selected, then send the corresponding message\\n\\tto either the model or the receiver.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: sensor leftShiftDown! !\\n\\n\\n!MouseMenuController methodsFor: 'menu setup'!\\nredButtonMenu: aSystemMenu redButtonMessages: anArray \\n\\t\\\"Initialize the pop-up menu that should appear when the user presses the \\n\\tred mouse button to be aSystemMenu. The corresponding messages that \\n\\tshould be sent are listed in the array, anArray.\\\"\\n\\n\\tredButtonMenu release.\\n\\tredButtonMenu _ aSystemMenu.\\n\\tredButtonMessages _ anArray! !\\n\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:36'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t^ view getMenu: shiftKeyState! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 2/17/2002 04:35'!\\npluggableYellowButtonActivity: shiftKeyState\\n\\t\\\"Invoke the model's popup menu.\\\"\\n\\n\\t| menu |\\n\\t(menu _ self getPluggableYellowButtonMenu: shiftKeyState)\\n\\t\\tifNil:\\n\\t\\t\\t[sensor waitNoButton]\\n\\t\\tifNotNil:\\n\\t\\t\\t[self terminateAndInitializeAround:\\n\\t\\t\\t\\t[menu invokeOn: model orSendTo: self]]! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 3/22/2001 12:03'!\\nshiftedTextPaneMenuRequest\\n\\t\\\"The user chose the more... branch from the text-pane menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: true! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'!\\nshiftedYellowButtonActivity\\n\\t\\\"Invoke the model's special popup menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: true! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'!\\nunshiftedYellowButtonActivity\\n\\t\\\"Invoke the model's normal popup menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: false! !\\nMouseEvent subclass: #MouseMoveEvent\\n\\tinstanceVariableNames: 'startPoint trail'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 22:51'!\\nendPoint\\n\\t\\\"Return the point where the movement ended.\\\"\\n\\t^position! !\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 16:25'!\\nstartPoint\\n\\t\\\"Return the point where the movement started.\\\"\\n\\t^startPoint! !\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 10/24/2000 16:33'!\\ntrail\\n\\t\\\"Return any immediate points that have been assembled along the move\\\"\\n\\t^trail ifNil:[#()]! !\\n\\n\\n!MouseMoveEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:49'!\\n= aMorphicEvent\\n\\tsuper = aMorphicEvent ifFalse:[^false].\\n\\tposition = aMorphicEvent position ifFalse: [^ false].\\n\\tstartPoint = aMorphicEvent startPoint ifFalse: [^ false].\\n\\tbuttons = aMorphicEvent buttons ifFalse: [^ false].\\n\\t^ true\\n! !\\n\\n!MouseMoveEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:49'!\\nhash\\n\\t^ position hash + startPoint hash + buttons hash! !\\n\\n\\n!MouseMoveEvent methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:15'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseMove ifTrue:[^anObject handleMouseMove: self].\\n\\t^super sentTo: anObject.\\n! !\\n\\n\\n!MouseMoveEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:31'!\\ntype: eventType readFrom: aStream\\n\\t| x y |\\n\\tsuper type: eventType readFrom: aStream.\\n\\taStream skip: 1.\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\tstartPoint _ x@y.! !\\n\\n\\n!MouseMoveEvent methodsFor: 'printing' stamp: 'ar 10/7/2000 22:00'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $[.\\n\\taStream nextPutAll: self startPoint printString; space.\\n\\taStream nextPutAll: self endPoint printString; space.\\n\\taStream nextPutAll: self type; space.\\n\\taStream nextPutAll: self modifierString.\\n\\taStream nextPutAll: self buttonString.\\n\\taStream nextPutAll: timeStamp printString.\\n\\taStream nextPut: $].! !\\n\\n!MouseMoveEvent methodsFor: 'printing' stamp: 'ar 10/24/2000 16:30'!\\nstoreOn: aStream\\n\\tsuper storeOn: aStream.\\n\\taStream space.\\n\\tself startPoint x storeOn: aStream.\\n\\taStream space.\\n\\tself startPoint y storeOn: aStream.\\n\\taStream space.\\n\\t\\\"trail storeOn: aStream.\\\"! !\\n\\n\\n!MouseMoveEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:29'!\\nisMove\\n\\t^true! !\\n\\n\\n!MouseMoveEvent methodsFor: 'transforming' stamp: 'ar 9/15/2000 22:52'!\\ntransformBy: aMorphicTransform\\n\\t\\\"Transform the receiver into a local coordinate system.\\\"\\n\\tposition _ aMorphicTransform globalPointToLocal: position.\\n\\tstartPoint _ aMorphicTransform globalPointToLocal: startPoint.! !\\n\\n!MouseMoveEvent methodsFor: 'transforming' stamp: 'ar 9/15/2000 22:52'!\\ntranslateBy: delta\\n\\t\\\"add delta to cursorPoint, and return the new event\\\"\\n\\tposition _ position + delta.\\n\\tstartPoint _ startPoint + delta.! !\\n\\n\\n!MouseMoveEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'dgd 2/22/2003 19:01'!\\ndecodeFromStringArray: array \\n\\t\\\"decode the receiver from an array of strings\\\"\\n\\n\\ttype := array first asSymbol.\\n\\tposition := CanvasDecoder decodePoint: (array second).\\n\\tbuttons := CanvasDecoder decodeInteger: (array third).\\n\\tstartPoint := CanvasDecoder decodePoint: (array fourth)! !\\n\\n!MouseMoveEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:25'!\\nencodedAsStringArray\\n\\t\\\"encode the receiver into an array of strings, such that it can be retrieved via the fromStringArray: class method\\\"\\n\\t^{\\n\\t\\ttype.\\n\\t\\tCanvasEncoder encodePoint: position.\\n\\t\\tCanvasEncoder encodeInteger: buttons.\\n\\t\\tCanvasEncoder encodePoint: startPoint.\\n\\t}! !\\n\\n\\n!MouseMoveEvent methodsFor: 'private' stamp: 'ar 10/5/2000 23:55'!\\nsetType: evtType startPoint: evtStart endPoint: evtEnd trail: evtTrail buttons: evtButtons hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\tstartPoint _ evtStart.\\n\\tposition _ evtEnd.\\n\\ttrail _ evtTrail.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.\\n\\ttimeStamp _ stamp.! !\\nObject subclass: #MouseOverHandler\\n\\tinstanceVariableNames: 'mouseOverMorphs enteredMorphs overMorphs leftMorphs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseOverHandler methodsFor: 'event handling' stamp: 'ar 9/28/2000 18:52'!\\nnoticeMouseOver: aMorph event: anEvent\\n\\t\\\"Remember that the mouse is currently over some morph\\\"\\n\\t(leftMorphs includes: aMorph) \\n\\t\\tifTrue:[leftMorphs remove: aMorph]\\n\\t\\tifFalse:[enteredMorphs nextPut: aMorph].\\n\\toverMorphs nextPut: aMorph.\\n! !\\n\\n!MouseOverHandler methodsFor: 'event handling' stamp: 'dgd 2/21/2003 23:00'!\\nprocessMouseOver: anEvent \\n\\t\\\"Re-establish the z-order for all morphs wrt the given event\\\"\\n\\n\\t| hand localEvt focus evt |\\n\\thand := anEvent hand.\\n\\tleftMorphs := mouseOverMorphs asIdentitySet.\\n\\t\\\"Assume some coherence for the number of objects in over list\\\"\\n\\toverMorphs := WriteStream on: (Array new: leftMorphs size).\\n\\tenteredMorphs := WriteStream on: #().\\n\\t\\\"Now go looking for eventual mouse overs\\\"\\n\\thand handleEvent: anEvent asMouseOver.\\n\\t\\\"Get out early if there's no change\\\"\\n\\t(leftMorphs isEmpty and: [enteredMorphs position = 0]) \\n\\t\\tifTrue: [^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tfocus := hand mouseFocus.\\n\\t\\\"Send #mouseLeave as appropriate\\\"\\n\\tevt := anEvent asMouseLeave.\\n\\t\\\"Keep the order of the left morphs by recreating it from the mouseOverMorphs\\\"\\n\\tleftMorphs size > 1 \\n\\t\\tifTrue: [leftMorphs := mouseOverMorphs select: [:m | leftMorphs includes: m]].\\n\\tleftMorphs do: \\n\\t\\t\\t[:m | \\n\\t\\t\\t(m == focus or: [m hasOwner: focus]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[localEvt := evt transformedBy: (m transformedFrom: hand).\\n\\t\\t\\t\\t\\tm handleEvent: localEvt]\\n\\t\\t\\t\\tifFalse: [overMorphs nextPut: m]].\\n\\t\\\"Send #mouseEnter as appropriate\\\"\\n\\tevt := anEvent asMouseEnter.\\n\\tenteredMorphs ifNil: \\n\\t\\t\\t[\\\"inform: was called in handleEvent:\\\"\\n\\n\\t\\t\\t^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tenteredMorphs := enteredMorphs contents.\\n\\tenteredMorphs reverseDo: \\n\\t\\t\\t[:m | \\n\\t\\t\\t(m == focus or: [m hasOwner: focus]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[localEvt := evt transformedBy: (m transformedFrom: hand).\\n\\t\\t\\t\\t\\tm handleEvent: localEvt]].\\n\\t\\\"And remember the over list\\\"\\n\\toverMorphs ifNil: \\n\\t\\t\\t[\\\"inform: was called in handleEvent:\\\"\\n\\n\\t\\t\\t^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tmouseOverMorphs := overMorphs contents.\\n\\tleftMorphs := enteredMorphs := overMorphs := nil! !\\n\\n\\n!MouseOverHandler methodsFor: 'initialize-release' stamp: 'ar 9/28/2000 17:08'!\\ninitialize\\n\\tmouseOverMorphs _ #().! !\\nMovieClipStartMorph subclass: #MovieClipEndMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieClipEndMorph commentStamp: '<historical>' prior: 0!\\nThe idea is that soon we will show the soundtrack extending between the start cue and the end morph.!\\n\\n\\n!MovieClipEndMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieFileName: movieFileName image: aForm player: aMoviePlayer frameNumber: n\\n\\n\\tmovieClipFileName := movieFileName.\\n\\tself image: aForm frameNumber: n.\\n\\tmoviePlayerMorph := movieClipPlayer := aMoviePlayer.\\n\\tscoreEvent := AmbientEvent new morph: self.\\n! !\\n\\n\\n!MovieClipEndMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:42'!\\nthumbnailHeight\\n\\n\\t^ 30! !\\n\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/26/2000 00:25'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t\\\"Ignored -- all display is done by the starting morph -- see superclass\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/11/2000 23:06'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\tmovieClipPlayer ifNotNil:\\n\\t\\t[\\\"If being shown as a clip, then tell the clipPlayer to stop showing this clip\\\"\\n\\t\\tmovieClipPlayer stopRunning]! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\npauseFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\nresetFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\nresumeFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\nMovieFrameSyncMorph subclass: #MovieClipStartMorph\\n\\tinstanceVariableNames: 'movieClipPlayer movieClipFileName soundTrackFileName soundTrackPlayerReady soundTrackMorph soundTrackTimeScale scoreEvent endMorph clipColor colorMorph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieClipStartMorph commentStamp: '<historical>' prior: 0!\\nThis class and its subclasses act to syncronize movie players with the progress of a MIDI score and further background can be found in the comment for MoviePlayerMorph.\\n\\nMovieClipStartMorphs are used where you have a movie clip player plex. You can create such a plex by opening a midi score, spawning a piano roll (by the button of that name), and then choosing 'add movie clip player' from the piano roll menu. Much simpler, you can open a MoviePlayerMorph as a new morph, and then choose 'make a new movie' from its menu. This plex then serves as a central editable score for composing movie clips.\\n\\nTo add a new movie clip to the score, open a movie from the fileList (or as a new morph followed by 'open a movie'). Play or otherwise position the clip to the desired starting position, and then tear off a thumbnail and drop it into the score at the desired time. The starting thumbnail (MovieClipStartMorph) will appear in the score, tied to an endMorph by a colored stripe. The ending time will be chosen based on the total length of the clip, a default starting clip length (200 frames), and possible interference with other clips that follow it.\\n\\nTo reposition a clip, you can pick up its clipStart with halo black handle, and drop it elsewhere. The rest of the clip will follow as best it can. To delete a clip, delete its clipStart. To change the duration of a clip, play the composition up to some point in that clip, and pause it. Then use the controls on the central movie player to move forward or backward to the desired ending frame, and choose 'end clip here' from the player menu.!\\n\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/19/2000 14:27'!\\nendMorph\\n\\n\\t^ endMorph! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: newFrame\\n\\n\\tframeNumber := newFrame! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieClipPlayer: aMoviePlayerMorph\\n\\t\\\"For now, these morphs work both as a sync point in a long movie, and\\n\\tas a cue point for a short clip in a longer score.\\n\\tTo a cue point, this method provides a reference to the clip player.\\\"\\n\\n\\tmovieClipPlayer := aMoviePlayerMorph! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/25/2000 22:02'!\\nrelatedPlayer\\n \\n\\t^ movieClipPlayer! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/19/2000 12:24'!\\nscoreEvent\\n\\t^ scoreEvent! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:46'!\\ncolorMargin\\n\\t\\\"How far the clip span color highlight extends outside the starting clip\\\"\\n\\n\\t^ 5! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncolorMorph\\n\\tcolorMorph ifNotNil: [^ colorMorph].\\n\\n\\t\\\"Make up a morph to highlight the span of this clip.\\\"\\n\\tColorIndex := (ColorIndex ifNil: [0]) + 2 \\\\\\\\ 8 + 1.\\n\\t^ colorMorph := Morph newBounds: (0@0 extent: 9@9) color: ((Color wheel: 8) at: ColorIndex)\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:23'!\\nsoundTrackHeight\\n\\n\\t^ 40! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:58'!\\nsoundTrackOnBottom \\\"a local preference during test\\\"\\n\\n\\t^ false! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 12:32'!\\nthumbnailHeight\\n\\n\\t^ 60! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'dropping/grabbing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\njustDroppedInto: newOwner event: evt\\n\\t| pianoRoll syncMorph |\\n\\t\\\"When dropping this morph into a pianoRoll, add a corresponding\\n\\tevent to the score so that it will always appear when played,\\n\\tin addition to possibly triggering other actions\\\"\\n\\n\\t(newOwner isKindOf: PianoRollScoreMorph)\\n\\tifTrue:\\n\\t\\t[pianoRoll := newOwner.\\n\\t\\tpianoRoll movieClipPlayer ifNil:\\n\\t\\t\\t[\\\"This PianoRoll is not a clip player -- replace me by a SyncMorph\\\"\\n\\t\\t\\tsyncMorph := MovieFrameSyncMorph new\\n\\t\\t\\t\\t\\t\\timage: image\\n\\t\\t\\t\\t\\t\\tplayer: moviePlayerMorph\\n\\t\\t\\t\\t\\t\\tframeNumber: frameNumber.\\n\\t\\t\\tpianoRoll replaceSubmorph: self by: syncMorph.\\n\\t\\t\\t\\\"rewrite to use justDroppedInto:...\\\"\\n\\t\\t\\tpianoRoll score removeAmbientEventWithMorph: self;\\n\\t\\t\\t\\t\\taddAmbientEvent: (scoreEvent\\n\\t\\t\\t\\t\\t\\tmorph: syncMorph;\\n\\t\\t\\t\\t\\t\\ttime: (pianoRoll timeForX: self left)).\\n\\t\\t\\t^ self].\\n\\n\\t\\tself movieClipPlayer: pianoRoll movieClipPlayer.\\n\\t\\tself setTimeInScore: pianoRoll score\\n\\t\\t\\t\\t\\tnear: (pianoRoll timeForX: self left).\\n\\t\\tself endTime > newOwner scorePlayer durationInTicks ifTrue:\\n\\t\\t\\t[newOwner scorePlayer updateDuration]]\\n\\tifFalse:\\n\\t\\t[\\\"Dropped it somewhere else -- delete related morphs\\\"\\n\\t\\tendMorph ifNotNil: [endMorph delete].\\n\\t\\tsoundTrackMorph ifNotNil: [soundTrackMorph delete]].\\n\\n\\tsuper justDroppedInto: newOwner event: evt\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:24'!\\nendTime\\n\\n\\t^ endMorph scoreEvent time! !\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:27'!\\nframeAtTick: time\\n\\t\\\"Return the frame number corresponding to the given tick time\\\"\\n\\n\\t^ frameNumber +\\n\\t\\t((time - self startTime) asFloat\\n\\t\\t\\t/ (self endTime - self startTime)\\n\\t\\t\\t* (endMorph frameNumber - frameNumber)) asInteger! !\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:24'!\\nstartTime\\n\\n\\t^ scoreEvent time! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nimage: aForm frameNumber: n\\n\\n\\tself image: (aForm magnifyBy: self thumbnailHeight asFloat / aForm height).\\n\\tframeNumber := n.! !\\n\\n!MovieClipStartMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieFileName: movieFileName soundTrackFileName: soundFileName\\n\\t\\t\\timage: aForm player: aMoviePlayer frameNumber: n\\n\\tmovieClipFileName := movieFileName.\\n\\tsoundTrackFileName := soundFileName.\\n\\tself image: aForm frameNumber: n.\\n\\tmoviePlayerMorph := aMoviePlayer.\\n\\tsoundTrackPlayerReady := moviePlayerMorph scorePlayer copy.\\n\\tscoreEvent := AmbientEvent new morph: self.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'dgd 2/22/2003 14:09'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime \\n\\t\\\"This code handles both the start and end morphs.\\\"\\n\\n\\t| startX endX h delta |\\n\\tself startTime > rightTime \\n\\t\\tifTrue: [^self\\t\\\"Start time has not come into view.\\\"].\\n\\tself endTime < leftTime ifTrue: [^self\\t\\\"End time has passed out of view.\\\"].\\n\\tstartX := pianoRoll xForTime: self startTime.\\n\\tendX := pianoRoll xForTime: self endTime.\\n\\th := self colorMargin.\\t\\\"Height of highlight bar over thumbnails.\\\"\\n\\tmorphList add: (self align: self bottomLeft\\n\\t\\t\\t\\twith: startX @ (pianoRoll bottom - pianoRoll borderWidth - h)).\\n\\tmorphList \\n\\t\\tadd: (endMorph align: endMorph bounds rightCenter with: endX @ self center y).\\n\\tmorphList add: (self colorMorph \\n\\t\\t\\t\\tbounds: (self topLeft - (0 @ h) corner: endMorph right @ (self bottom + h))).\\n\\t(soundTrackMorph isNil and: [moviePlayerMorph scorePlayer isNil]) \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Wants a sound track\\\"\\n\\n\\t\\t\\t(soundTrackMorph isNil or: [pianoRoll timeScale ~= soundTrackTimeScale]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Needs a new sound track\\\"\\n\\n\\t\\t\\t\\t\\tself buildSoundTrackMorphFor: pianoRoll].\\n\\t\\t\\tmorphList add: (soundTrackMorph align: soundTrackMorph bottomLeft\\n\\t\\t\\t\\t\\t\\twith: colorMorph topLeft).\\n\\t\\t\\tself soundTrackOnBottom \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[soundTrackMorph align: soundTrackMorph bottomLeft with: self bottomLeft.\\n\\t\\t\\t\\t\\tdelta := 0 @ self soundTrackHeight.\\n\\t\\t\\t\\t\\tself position: self position - delta.\\n\\t\\t\\t\\t\\tendMorph position: endMorph position - delta.\\n\\t\\t\\t\\t\\tcolorMorph position: colorMorph position - delta]]! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'di 10/26/2000 00:09'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"If being shown as a clip, then tell the clipPlayer to start showing this clip\\\"\\n\\tmovieClipPlayer setCueMorph: self.\\n\\tmovieClipPlayer openFileNamed: movieClipFileName\\n\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\tandPlayFrom: frameNumber.\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'dgd 2/22/2003 14:09'!\\nresetFrom: scorePlayer \\n\\t(movieClipPlayer cueMorph isNil \\n\\t\\tor: [self startTime < movieClipPlayer cueMorph startTime]) \\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[movieClipPlayer\\n\\t\\t\\t\\t\\topenFileNamed: movieClipFileName\\n\\t\\t\\t\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\t\\t\\t\\tandPlayFrom: frameNumber;\\n\\t\\t\\t\\t\\tsetCueMorph: self;\\n\\t\\t\\t\\t\\tstep;\\n\\t\\t\\t\\t\\tpauseFrom: scorePlayer]! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nresumeFrom: scorePlayer\\n\\n\\t| time |\\n\\t\\\"New movie clip style of use.\\\"\\n\\ttime := scorePlayer ticksSinceStart.\\n\\ttime < self startTime ifTrue: [^ self]. \\\"It's not my time yet\\\"\\n\\ttime > self endTime ifTrue: [^ self]. \\\"It's past my time\\\"\\n\\n\\t\\\"The player is starting in the midst of this clip.\\\"\\n\\tmovieClipPlayer openFileNamed: movieClipFileName\\n\\t\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\t\\tandPlayFrom: (self frameAtTick: time);\\n\\t\\tsetCueMorph: self.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'submorphs-add/remove' stamp: 'di 10/23/2000 10:24'!\\ndelete\\n\\t(owner isKindOf: PianoRollScoreMorph) ifTrue:\\n\\t\\t[owner score removeAmbientEventWithMorph: self.\\n\\t\\tendMorph ifNotNil: [owner score removeAmbientEventWithMorph: endMorph]].\\n\\tendMorph ifNotNil: [endMorph delete].\\n\\tsoundTrackMorph ifNotNil: [soundTrackMorph delete].\\n\\tcolorMorph ifNotNil: [colorMorph delete].\\n\\tsuper delete.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nbuildSoundTrackMorphFor: pianoRoll\\n\\t| stopTime soundTrackForm startTime samplesPerTick samplesPerMs |\\n\\tsoundTrackTimeScale := pianoRoll timeScale. \\\"pixels per tick\\\"\\n\\tsamplesPerTick := moviePlayerMorph scorePlayer originalSamplingRate \\\"Samples per sec\\\"\\n\\t\\t\\t\\t\\t\\t* pianoRoll scorePlayer secsPerTick. \\\"secs per tick\\\"\\n\\tsamplesPerMs := moviePlayerMorph scorePlayer originalSamplingRate / 1000.0.\\n\\tstartTime := frameNumber * moviePlayerMorph msPerFrame. \\\"ms\\\"\\n\\tstopTime := endMorph frameNumber * moviePlayerMorph msPerFrame.\\n\\tsoundTrackForm := moviePlayerMorph scorePlayer\\n\\t\\tvolumeForm: self soundTrackHeight\\n\\t\\tfrom: (startTime * samplesPerMs) rounded\\n\\t\\tto: (stopTime * samplesPerMs) rounded\\n\\t\\tnSamplesPerPixel: samplesPerTick / soundTrackTimeScale.\\n\\t^ soundTrackMorph := ImageMorph new image: soundTrackForm! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'di 10/29/2000 08:02'!\\nsetEndFrameNumber: frame\\n\\n\\tself setEndFrameNumber: frame tickTime: nil! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetEndFrameNumber: frameOrNil tickTime: timeOrNil\\n\\t\\\"May be called with either time or frame being nil,\\n\\tin which case the other will br computed.\\\"\\n\\n\\t| pianoRoll frame time |\\n\\tpianoRoll := movieClipPlayer pianoRoll.\\n\\tframe := frameOrNil ifNil:\\n\\t\\t[frameNumber + \\n\\t\\t\\t((timeOrNil - self startTime)\\n\\t\\t\\t* (pianoRoll scorePlayer secsPerTick*1000.0)\\n\\t\\t\\t/ moviePlayerMorph msPerFrame) asInteger - 1].\\n\\ttime := timeOrNil ifNil:\\n\\t\\t[self startTime + \\\"in ticks\\\"\\n\\t\\t\\t(pianoRoll scorePlayer ticksForMSecs:\\n\\t\\t\\t(frameOrNil - frameNumber) * moviePlayerMorph msPerFrame)].\\n\\tendMorph ifNil:\\n\\t\\t[endMorph := MovieClipEndMorph new\\n\\t\\t\\tmovieFileName: movieClipFileName\\n\\t\\t\\timage: (moviePlayerMorph pageFormForFrame: frame)\\n\\t\\t\\tplayer: movieClipPlayer\\n\\t\\t\\tframeNumber: frame]\\n\\t\\tifNotNil:\\n\\t\\t[endMorph image: (moviePlayerMorph pageFormForFrame: frame)\\n\\t\\t\\tframeNumber: frame].\\n\\n\\tendMorph scoreEvent time: time.\\n\\tpianoRoll score removeAmbientEventWithMorph: endMorph;\\n\\t\\taddAmbientEvent: endMorph scoreEvent.\\n\\tsoundTrackMorph := nil. \\\"Force it to be recomputed.\\\"\\n\\tpianoRoll rebuildFromScore\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetTimeInScore: score near: dropTime\\n\\t\\\"Find a time to place this clip that does not overlap other clips.\\n\\tSo, if I start in the middle of another clip, move me to the end of it,\\n\\tand if I start very soon after another clip, put me right at the end.\\n\\tThen, if my end goes beyond the start of another clip, shorten me\\n\\tso I end right before that clip.\\\"\\n\\n\\t| startTime endTime delta endFrame |\\n\\tstartTime := dropTime.\\n\\tendMorph ifNil: [endFrame := moviePlayerMorph frameCount]\\n\\t\\t\\tifNotNil: [endFrame := endMorph frameNumber].\\n\\tendTime := startTime \\\"in ticks\\\"\\n\\t\\t+ (movieClipPlayer pianoRoll scorePlayer ticksForMSecs:\\n\\t\\t\\t(endFrame - frameNumber)\\n\\t\\t\\t* moviePlayerMorph msPerFrame).\\n\\tscore eventMorphsDo:\\n\\t\\t[:m | (m ~~ self and: [m isMemberOf: self class]) ifTrue:\\n\\t\\t\\t\\t[((startTime between: m startTime and: m endTime)\\n\\t\\t\\t\\t\\tor: [startTime between: m endTime and: m endTime+50])\\n\\t\\t\\t\\t\\tifTrue: [\\\"If I start in the middle of another clip, or a little\\n\\t\\t\\t\\t\\t\\t\\tpast its end, move me exactly to the end of it\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelta := (m endTime + 1) - startTime.\\n\\t\\t\\t\\t\\t\\t\\tstartTime := startTime + delta.\\n\\t\\t\\t\\t\\t\\t\\tendTime := endTime + delta].\\n\\t\\t\\t\\t(endTime between: m startTime and: m endTime)\\n\\t\\t\\t\\t\\tifTrue: [\\\"If my end goes overlaps another clip, shorten me so I fit.\\\"\\n\\t\\t\\t\\t\\t\\t\\tendTime := m startTime - 1].\\n\\t\\t\\t\\t]].\\n\\tscoreEvent time: startTime.\\n\\tscore removeAmbientEventWithMorph: self;\\n\\t\\t\\taddAmbientEvent: scoreEvent.\\n\\tself setEndFrameNumber: endFrame tickTime: endTime.\\n! !\\nImageMorph subclass: #MovieFrameSyncMorph\\n\\tinstanceVariableNames: 'moviePlayerMorph frameNumber'\\n\\tclassVariableNames: 'ColorIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieFrameSyncMorph commentStamp: '<historical>' prior: 0!\\nThis class and its subclasses act to syncronize movie players with the progress of a MIDI score and further background can be found in the comment for MoviePlayerMorph.\\n\\nThere are two main forms of synchroniztion.\\n\\nMovieFrameSyncMorphs are used where you have a MIDI score open with a piano roll, and a separate MoviePlayer Morph. A MovieFrameSyncMorph can be torn off from the MoviePlayer with a shift-drag gesture or menu command, and can then be dropped into a MIDI score. They are used to start a movie player at a given place in the score, and then to stretch or compress the movie frame rate so that certain frames are synchronized with the corresponding points in the score.\\n\\nMovieClipStartMorphs (q.v.) and MovieClipEndMorphs are used for the other kind of synchronization, namely where you wish to assemble a number of movie clips in a sequence.!\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 8/6/1998 14:13'!\\nframeNumber\\n\\t^ frameNumber! !\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 10/11/2000 21:39'!\\nmoviePlayerMorph\\n \\n\\t^ moviePlayerMorph! !\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 10/25/2000 22:02'!\\nrelatedPlayer\\n \\n\\t^ moviePlayerMorph! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'dropping/grabbing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\njustDroppedInto: newOwner event: evt \\n\\t| pianoRoll |\\n\\t\\\"When dropping this morph into a pianoRoll, add a corresponding\\n\\tevent to the score so that it will always appear when played,\\n\\tin addition to possibly triggering other actions\\\"\\n\\n\\t(self isMemberOf: MovieFrameSyncMorph) ifFalse:\\n\\t\\t[^ super justDroppedInto: newOwner event: evt].\\n\\n\\t(newOwner isKindOf: PianoRollScoreMorph)\\n\\tifTrue:\\n\\t\\t[\\\"Legacy code for existing sync morphs\\\"\\n\\t\\tpianoRoll := newOwner.\\n\\t\\tpianoRoll score\\n\\t\\t\\tremoveAmbientEventWithMorph: self;\\n\\t\\t\\taddAmbientEvent: (AmbientEvent new\\n\\t\\t\\t\\t\\t\\tmorph: self;\\n\\t\\t\\t\\t\\t\\ttime: (pianoRoll timeForX: self left))].\\n\\n\\tsuper justDroppedInto: newOwner event: evt\\n! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'events' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nnextSyncEventAfter: index inTrack: track\\n\\t| evt |\\n\\tindex to: track size do:\\n\\t\\t[:i | evt := track at: i.\\n\\t\\t((evt morph isMemberOf: self class)\\n\\t\\t\\tand: [evt morph moviePlayerMorph == moviePlayerMorph])\\n\\t\\t\\tifTrue: [^ evt]].\\n\\t^ nil! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nimage: aForm player: aMoviePlayer frameNumber: n\\n\\tself image: aForm.\\n\\tmoviePlayerMorph := aMoviePlayer.\\n\\tframeNumber := n! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t| leftX |\\n\\tt > rightTime ifTrue: [^ self \\\"Start time has not come into view.\\\"]. \\n\\tleftX := pianoRoll xForTime: t.\\n\\t(leftX + self width) < pianoRoll left ifTrue: [^ self \\\"End time has passed out of view.\\\"].\\n\\tmorphList add: \\n\\t\\t(self align: self bottomLeft\\n\\t\\t\\twith: leftX @ (pianoRoll bottom - pianoRoll borderWidth)).\\n! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'dgd 2/21/2003 22:58'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick \\n\\t\\\"Set frame number and milliseconds since start in case of drift\\\"\\n\\n\\t| next |\\n\\tmoviePlayerMorph frameNumber: frameNumber\\n\\t\\tmsSinceStart: scorePlayer millisecondsSinceStart.\\n\\n\\t\\\"If there is a later sync point, set the appropriate frame rate until then.\\\"\\n\\t(next := self nextSyncEventAfter: index inTrack: track) isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[moviePlayerMorph msPerFrame: (next time - ticks) * secsPerTick * 1000.0 \\n\\t\\t\\t\\t\\t\\t/ (next morph frameNumber - self frameNumber)]! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'RAA 12/11/2000 22:58'!\\njustDroppedIntoPianoRoll: pianoRoll event: evt\\n\\n\\t\\\"since these morphs handle their own dropping, ignore\\\"! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:03'!\\npauseFrom: scorePlayer\\n\\n\\tself relatedPlayer pauseFrom: scorePlayer! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:02'!\\nresetFrom: scorePlayer\\n\\n\\tself relatedPlayer resetFrom: scorePlayer! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:03'!\\nresumeFrom: scorePlayer\\n\\n\\tself relatedPlayer resumeFrom: scorePlayer! !\\nMorph subclass: #MovieMorph\\n\\tinstanceVariableNames: 'playMode msecsPerFrame rotationDegrees scalePoint frameList currentFrameIndex dwellCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic'!\\n\\n!MovieMorph methodsFor: 'accessing'!\\nform\\n\\n\\t^ self currentFrame form\\n! !\\n\\n!MovieMorph methodsFor: 'accessing' stamp: 'jm 7/24/97 15:05'!\\nscalePoint\\n\\n\\t^ scalePoint\\n! !\\n\\n!MovieMorph methodsFor: 'accessing' stamp: 'jm 7/24/97 15:05'!\\nscalePoint: newScalePoint\\n\\n\\t| frame |\\n\\tnewScalePoint ~= scalePoint ifTrue: [\\n\\t\\tself changed.\\n\\t\\tscalePoint _ newScalePoint.\\n\\t\\tframe _ self currentFrame.\\n\\t\\tframe ifNotNil: [frame scalePoint: newScalePoint].\\n\\t\\tself layoutChanged.\\n\\t\\tself changed].\\n! !\\n\\n\\n!MovieMorph methodsFor: 'drawing' stamp: 'dgd 2/22/2003 18:47'!\\ndrawOn: aCanvas \\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\tframe notNil \\n\\t\\tifTrue: [^frame drawOn: aCanvas]\\n\\t\\tifFalse: [^super drawOn: aCanvas]! !\\n\\n\\n!MovieMorph methodsFor: 'geometry testing' stamp: 'dgd 2/22/2003 18:48'!\\ncontainsPoint: p \\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\t^ (frame notNil and: [playMode = #stop]) \\n\\t\\tifTrue: [frame containsPoint: p]\\n\\t\\tifFalse: [super containsPoint: p]! !\\n\\n\\n!MovieMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 1\\n\\t\\tg: 0\\n\\t\\tb: 1! !\\n\\n!MovieMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:47'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tplayMode _ #stop.\\n\\t\\\"#stop, #playOnce, or #loop\\\"\\n\\tmsecsPerFrame _ 200.\\n\\trotationDegrees _ 0.\\n\\tscalePoint _ 1.0 @ 1.0.\\n\\tframeList _ EmptyArray.\\n\\tcurrentFrameIndex _ 1.\\n\\tdwellCount _ 0! !\\n\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'nk 6/12/2004 09:59'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\t| movies subMenu |\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tframeList size > 1 ifTrue: [\\n\\t\\tsubMenu add: 'repaint' translated action: #editDrawing.\\n\\t\\tsubMenu add: 'set rotation center' translated action: #setRotationCenter.\\n\\t\\tsubMenu add: 'play once' translated action: #playOnce.\\n\\t\\tsubMenu add: 'play loop' translated action: #playLoop.\\n\\t\\tsubMenu add: 'stop playing' translated action: #stopPlaying.\\n\\t\\tcurrentFrameIndex > 1 ifTrue: [\\n\\t\\t\\tsubMenu add: 'previous frame' translated action: #previousFrame].\\n\\t\\tcurrentFrameIndex < frameList size ifTrue: [\\n\\t\\t\\tsubMenu add: 'next frame' translated action: #nextFrame]].\\n\\tsubMenu add: 'extract this frame' translated action: #extractFrame:.\\n\\tmovies _\\n\\t\\t(self world rootMorphsAt: aHandMorph targetOffset)\\n\\t\\t\\tselect: [:m | (m isKindOf: MovieMorph) or:\\n\\t\\t\\t\\t\\t\\t[m isSketchMorph]].\\n\\t(movies size > 1) ifTrue:\\n\\t\\t[subMenu add: 'insert into movie' translated action: #insertIntoMovie:].\\n\\taCustomMenu add: 'movie...' translated subMenu: subMenu\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nadvanceFrame\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [self setFrame: currentFrameIndex + 1]\\n\\t\\tifFalse: [self setFrame: 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 18:47'!\\neditDrawing\\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\tframe notNil \\n\\t\\tifTrue: [frame editDrawingIn: self pasteUpMorph forBackground: false]! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nextractFrame: evt\\n\\n\\t| f |\\n\\tf _ self currentFrame.\\n\\tf ifNil: [^ self].\\n\\tframeList _ frameList copyWithout: f.\\n\\tframeList isEmpty\\n\\t\\tifTrue: [self position: f position]\\n\\t\\tifFalse: [self setFrame: currentFrameIndex].\\n\\tevt hand attachMorph: f.\\n! !\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'nk 6/12/2004 09:59'!\\ninsertIntoMovie: evt\\n\\n\\t| movies aTarget |\\n\\tmovies _\\n\\t\\t(self world rootMorphsAt: evt hand targetOffset)\\n\\t\\t\\tselect: [:m | ((m isKindOf: MovieMorph) or:\\n\\t\\t\\t\\t\\t\\t [m isSketchMorph]) and: [m ~= self]].\\n\\tmovies isEmpty ifTrue: [^ self].\\n\\taTarget _ movies first.\\n\\t(aTarget isSketchMorph) ifTrue:\\n\\t\\t[aTarget _ aTarget replaceSelfWithMovie].\\n\\tmovies first insertFrames: frameList.\\n\\tself delete.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nnextFrame\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [self setFrame: currentFrameIndex + 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nplayLoop\\n\\n\\tplayMode _ #loop.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nplayOnce\\n\\n\\tself setFrame: 1.\\n\\tplayMode _ #playOnce.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\npreviousFrame\\n\\n\\tcurrentFrameIndex > 1\\n\\t\\tifTrue: [self setFrame: currentFrameIndex - 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nstopPlaying\\n\\n\\tplayMode _ #stop.\\n\\tself setFrame: 1.\\n! !\\n\\n\\n!MovieMorph methodsFor: 'rotate scale and flex'!\\nrotationDegrees\\n\\n\\t^ rotationDegrees\\n! !\\n\\n\\n!MovieMorph methodsFor: 'stepping and presenter'!\\nstep\\n\\n\\tplayMode = #stop ifTrue: [^ self].\\n\\n\\tdwellCount > 0 ifTrue: [\\n\\t\\tdwellCount _ dwellCount - 1.\\n\\t\\t^ self].\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [^ self setFrame: currentFrameIndex + 1].\\n\\n\\tplayMode = #loop\\n\\t\\tifTrue: [self setFrame: 1]\\n\\t\\tifFalse: [playMode _ #stop].\\n! !\\n\\n\\n!MovieMorph methodsFor: 'testing'!\\nstepTime\\n\\n\\t^ msecsPerFrame\\n! !\\n\\n\\n!MovieMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 08:03'!\\ncurrentFrame\\n\\tframeList isEmpty ifTrue: [^nil].\\n currentFrameIndex := currentFrameIndex min: (frameList size).\\n currentFrameIndex := currentFrameIndex max: 1.\\n\\t^frameList at: currentFrameIndex! !\\n\\n!MovieMorph methodsFor: 'private'!\\ninsertFrames: newFrames\\n\\t\\\"Insert the given collection of frames into this movie just after the currentrame.\\\"\\n\\n\\tframeList isEmpty ifTrue: [\\n\\t\\tframeList _ newFrames asArray copy.\\n\\t\\tself setFrame: 1.\\n\\t\\t^ self].\\n\\n\\tframeList _\\n\\t\\tframeList\\n\\t\\t\\tcopyReplaceFrom: currentFrameIndex + 1 \\\"insert before\\\"\\n\\t\\t\\tto: currentFrameIndex\\n\\t\\t\\twith: newFrames.\\n! !\\n\\n!MovieMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 08:08'!\\nsetFrame: newFrameIndex \\n\\t| oldFrame p newFrame |\\n\\toldFrame := self currentFrame.\\n\\toldFrame ifNil: [^self].\\n\\tself changed.\\n\\tp := oldFrame referencePosition.\\n\\tcurrentFrameIndex := newFrameIndex.\\n currentFrameIndex := currentFrameIndex min: (frameList size). \\n\\tcurrentFrameIndex := currentFrameIndex max: 1.\\n\\tnewFrame := frameList at: currentFrameIndex.\\n\\tnewFrame referencePosition: p.\\n\\toldFrame delete.\\n\\tself addMorph: newFrame.\\n\\tdwellCount := newFrame framesToDwell.\\n\\tself layoutChanged.\\n\\tself changed! !\\nBookMorph subclass: #MoviePlayerMorph\\n\\tinstanceVariableNames: 'movieFileName movieFile frameSize frameDepth frameNumber frameCount playDirection msSinceStart msAtStart msAtLastSync frameAtLastSync msPerFrame frameBufferIfScaled soundTrackFileName scorePlayer soundTrackForm soundTrackMorph pianoRoll cueMorph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MoviePlayerMorph commentStamp: '<historical>' prior: 0!\\nMoviePlayerMorph plays images from a file using async io. The file format is simple but non-standard (see below).\\n\\nThe heart of the play logic is in the step method. Note that play is driven by a simulated time since start. For a movie with a sound score, this is the millisecondsSinceStart of the score player, whereas a movie by itself gets this from the millisecondClock minus msAtStart.\\n\\nMovie players are designed to be used in three ways\\n\\t1. Select a movie in the file list, 'open as movie', and play it.\\n\\t2. As in (1), but drop thumbnails for various frames into a\\n\\t\\tMIDI piano roll to synchronize video with music.\\n\\t3. Open a MoviePlayerMorph as a 'new morph', and choose\\n\\t\\t'make a new movie' from the menu.\\n\\nIn (1) and (2), a shift-drag is used to 'tear off' a thumbnail reference morph to the currently visible frame of this clips. The thumbnail can then be dropped in a MIDI score player to either syncronize that frame with what point in the music, or to cause that clip to being playing in the shared player of a SqueakMovie plex.\\n\\nWhen making a new movie, an empty score and piano roll are linked to the movie player, as a SqueakMovie plex. You can then open another movie as a clip, and drop a thumbnail morph into the score to start that clip playing at that frame in the shared player. If you pause while playing that clip, you can manually play the clip forward and backward in the current clip. if you stop at a given frame, you can choose 'end clip here' from the shared player menu to shorten or lengthen the clip.\\n\\nClips can be moved by picking up the starting thumbnail (use halo black handle), and dropping them elsewhere. If you try to place one clip in the middle of another, it will slide to the end. If you position one clip close to the end of another, it will sidle up to make them contiguous.\\n\\nIf you wish a soundtrack to be included with a clip, make sure it has been opened in the source clip player before tearing off the starting thumbnail.\\n\\nAbout the .movie file format...\\nThe following code was used to convert 27 files into a movie. They were named\\n\\t'BalloonDrop10fps003.bmp' through 'BalloonDrop10fps081.bmp'\\nincrementing by 003. Each was known to be a 320x240 image in 32-bit BMP format.\\nNote the 27 in the 5th line is the number of frames, = (3 to: 81 by: 3) size.\\n\\n\\t| ps zps f32 out ff |\\n\\tout _ FileStream newFileNamed: 'BalloonDrop10fps.movie'.\\n\\tout binary.\\n\\tff _ Form extent: 320@240 depth: 16.\\n\\t#(22 320 240 16 27 100000) , (7 to: 32)\\n\\t\\tdo: [:i | out nextInt32Put: i].\\n\\t\\t\\n\\t3 to: 81 by: 3 do:\\n\\t\\t[:i | ps _ i printString. zps _ ps padded: #left to: 3 with: $0.\\n\\t\\tf32 _ Form fromFileNamed:\\n\\t\\t\\t'BalloonDrop10fps' , zps , '.bmp'.\\n\\t\\tf32 displayOn: ff at: 0@0. \\\"Convert down to 16 bits\\\"\\n\\t\\tff display; writeOnMovie: out].\\n\\tout close.\\n!\\n\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/26/2000 00:18'!\\ncueMorph\\n\\t^ cueMorph! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/4/2000 17:19'!\\nfileName\\n\\t^ movieFileName! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/22/2000 10:54'!\\nframeCount\\n\\n\\t^ frameCount! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: n\\n\\n\\tframeNumber := n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: n msSinceStart: ms\\n\\t\\\"Set the current frame number, and save the scorePlayer's simulated time for synchronization.\\\"\\n\\n\\tframeAtLastSync := n.\\n\\tmsAtLastSync := ms.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/19/2000 16:31'!\\nmsPerFrame\\n\\t^ msPerFrame! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmsPerFrame: n\\n\\t\\\"Set a new frame rate, base on, eg, score synchronization info.\\\"\\n\\n\\tmsPerFrame := n.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npageFormForFrame: frameNo\\n\\n\\t| f form oldFrame |\\noldFrame := frameNumber.\\nself goToPage: frameNo.\\nform := currentPage image deepCopy.\\nself goToPage: oldFrame.\\ntrue ifTrue: [^ form].\\n\\n\\tf := FileStream readOnlyFileNamed: movieFileName.\\n\\tform := Form extent: frameSize depth: frameDepth.\\n\\n\\t\\\"For some weird reason, the next line does not work...\\\"\\n\\tf position: (self filePosForFrameNo: frameNo).\\n\\t\\\"... but this line was found empirically to work instead.\\\"\\n\\tf position: (128 + ((frameNo-1)*(form bits size*4+4)) + 4).\\n\\n\\tf nextInto: form bits.\\n\\tf close.\\n\\t^ form! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/15/2000 19:15'!\\nrelativePosition\\n\\n\\t^ frameNumber asFloat / frameCount! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/11/2000 12:13'!\\nscorePlayer\\n\\n\\t^ scorePlayer! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nscorePlayer: aScorePlayer\\n\\n\\tscorePlayer := aScorePlayer! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetCueMorph: aMorph\\n\\tcueMorph := aMorph\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/13/2000 11:51'!\\nsoundTrackFileName\\n\\t^ soundTrackFileName! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'controls and layout' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nshowHideSoundTrack\\n\\n\\tsoundTrackForm ifNotNil:\\n\\t\\t[soundTrackMorph delete.\\n\\t\\t^ soundTrackForm := soundTrackMorph := nil].\\n\\n\\tsoundTrackForm := scorePlayer volumeForm: 20 from: 1 to: scorePlayer samples size nSamplesPerPixel: 250.\\n\\tsoundTrackMorph := ImageMorph new image: (Form extent: 140 @ soundTrackForm height).\\n\\tsoundTrackMorph addMorph:\\n\\t\\t(Morph newBounds: (soundTrackMorph bounds topCenter extent: 1@soundTrackMorph height)\\n\\t\\t\\t\\t\\tcolor: Color red).\\n\\tself addMorph: soundTrackMorph after: currentPage.\\n\\tself layoutChanged.\\n\\tself stepSoundTrack.\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'copying' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nduplicate\\n\\t| dup |\\n\\tplayDirection ~= 0 ifTrue: [self stopPlay].\\n\\tdup := super duplicate.\\n\\tdup scorePlayer: scorePlayer copy. \\\"Share sound track if any.\\\"\\n\\t^ dup duplicateMore startStepping! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'event handling' stamp: 'di 10/16/2000 13:27'!\\nhandlesMouseDown: evt\\n\\t\\\"We use shift drag to 'tear off' a thumbnail\\\"\\n\\n\\tevt shiftPressed ifTrue: [^ true].\\n\\t^ super handlesMouseDown: evt! !\\n\\n!MoviePlayerMorph methodsFor: 'event handling' stamp: 'di 10/16/2000 13:32'!\\nmouseDown: evt\\n\\t\\\"We use shift drag to 'tear off' a thumbnail\\\"\\n\\n\\tevt shiftPressed ifTrue: [^ self makeThumbnailInHand: evt hand].\\n\\t^ super mouseDown: evt\\n\\t\\t! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'geometry' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nextent: newExtent\\n\\n\\t| tlMargin brMargin pageExtent scale fullSizeImage |\\n\\tfullSizeImage := frameBufferIfScaled ifNil: [currentPage image].\\n\\tframeCount ifNil: [^ self]. \\\"Not yet open\\\"\\n\\ttlMargin := currentPage topLeft - self topLeft.\\n\\tbrMargin := self bottomRight - currentPage bottomRight.\\n\\tpageExtent := newExtent - brMargin - tlMargin.\\n\\tscale := pageExtent x asFloat / frameSize x min: pageExtent y asFloat / frameSize y.\\n\\t(scale := scale max: 0.25) > 0.9 ifTrue: [scale := 1.0].\\n\\n\\tpageExtent := (frameSize * scale) rounded.\\n\\tpageExtent = frameSize\\n\\t\\tifTrue: [currentPage image: fullSizeImage.\\n\\t\\t\\t\\tframeBufferIfScaled := nil]\\n\\t\\tifFalse: [currentPage image: (Form extent: pageExtent depth: frameDepth).\\n\\t\\t\\t\\tframeBufferIfScaled := fullSizeImage.\\n\\t\\t\\t\\t(WarpBlt current toForm: currentPage image) sourceForm: fullSizeImage;\\n\\t\\t\\t\\t\\tcombinationRule: 3;\\n\\t\\t\\t\\t\\tcopyQuad: fullSizeImage boundingBox innerCorners\\n\\t\\t\\t\\t\\t\\ttoRect: currentPage image boundingBox].\\n\\t^ self layoutChanged\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'geometry' stamp: 'dgd 2/22/2003 19:01'!\\nposition: newPos \\n\\tsuper position: newPos.\\n\\t(currentPage notNil and: [currentPage left odd]) \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"crude word alignment for depth = 16\\\"\\n\\n\\t\\t\\tsuper position: newPos + (1 @ 0)]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:38'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryLightGray! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nduplicateMore\\n\\t\\\"Duplicate dies not replicate Forms, but MoviePlayers need this.\\\"\\n\\n\\tframeBufferIfScaled := frameBufferIfScaled deepCopy.\\n\\tcurrentPage image: currentPage image deepCopy.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'di 10/8/2000 21:43'!\\nopenFileNamed: fName \\n\\tself pvtOpenFileNamed: fName.\\n\\tself goToPage: 1! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nopenFileNamed: fName withScorePlayer: playerReady andPlayFrom: frameNo\\n\\t\\\"Note: The plan is that the score player (a SampledSound) is already spaced\\n\\tforward to this frame number so it does not need to be reset as would normally\\n\\thappen in startRunning.\\\"\\n\\n\\tself pvtOpenFileNamed: fName.\\n\\tscorePlayer := playerReady.\\n\\tframeNumber := frameNo.\\n\\tframeAtLastSync := frameNo.\\n\\tmsAtLastSync := frameAtLastSync * msPerFrame.\\n\\tself playForward.! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetInitialState\\n\\tsuper setInitialState.\\n\\\"\\\"\\n\\tself layoutInset: 3.\\n\\tpageSize := frameSize := 200 @ 200.\\n\\tframeDepth := 8.\\n\\tself disableDragNDrop! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 13:22'!\\nstopSoundTrackIfAny\\n\\tscorePlayer isNil ifTrue: [^self].\\n\\t(scorePlayer isKindOf: SampledSound) \\n\\t\\tifTrue: [scorePlayer endGracefully]\\n\\t\\tifFalse: [scorePlayer := nil]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 13:21'!\\naddSoundTrack\\n\\t| fileName |\\n\\tfileName := Utilities chooseFileWithSuffixFromList: #('.aif' '.wav')\\n\\t\\t\\t\\twithCaption: 'Choose a sound track file'.\\n\\tfileName isNil ifTrue: [^self].\\n\\tsoundTrackFileName := fileName.\\n\\tself tryToShareScoreFor: soundTrackFileName.\\n\\tscorePlayer ifNil: \\n\\t\\t\\t[('*aif' match: fileName) \\n\\t\\t\\t\\tifTrue: [scorePlayer := SampledSound fromAIFFfileNamed: fileName].\\n\\t\\t\\t('*wav' match: fileName) \\n\\t\\t\\t\\tifTrue: [scorePlayer := SampledSound fromWaveFileNamed: fileName]].\\n\\tsoundTrackForm ifNotNil: \\n\\t\\t\\t[\\\"Compute new soundTrack if we're showing it.\\\"\\n\\n\\t\\t\\tself\\n\\t\\t\\t\\tshowHideSoundTrack;\\n\\t\\t\\t\\tshowHideSoundTrack]! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'di 10/19/2000 17:07'!\\nendClipHere\\n\\t\\\"Change set the termination time for this clip via the endMorph\\\"\\n\\n\\tcueMorph ifNil: [^ self].\\n\\tcueMorph setEndFrameNumber: frameNumber\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ninvokeBookMenu\\n\\t\\\"Invoke the book's control panel menu.\\\"\\n\\t| aMenu |\\n\\taMenu := MVCMenuMorph new defaultTarget: self.\\n\\taMenu add:\\t'make a new movie' translated action: #makeAMovie.\\n\\taMenu add:\\t'open movie file' translated action: #openMovieFile.\\n\\taMenu add:\\t'add sound track' translated action: #addSoundTrack.\\n\\taMenu addLine.\\n\\tscorePlayer ifNotNil:\\n\\t\\t[soundTrackForm isNil\\n\\t\\t\\tifTrue: [aMenu add:\\t'show sound track' translated action: #showHideSoundTrack]\\n\\t\\t\\tifFalse: [aMenu add:\\t'hide sound track' translated action: #showHideSoundTrack]].\\n\\taMenu add:\\t'make thumbnail' translated action: #thumbnailForThisPage.\\n\\tcueMorph ifNotNil:\\n\\t\\t[\\\"Should check if piano roll and score already have a start event\\n\\t\\tprior to this time.\\\"\\n\\t\\taMenu add:\\t'end clip here' translated action: #endClipHere].\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmakeAMovie\\n\\t| scoreController score |\\n\\tframeSize := 640@480. frameDepth := 16. self makeMyPage; changed.\\n\\n\\t(score := MIDIScore new initialize) \\\"addAmbientEvent: (AmbientEvent new time: 200*60)\\\".\\n\\tscoreController := ScorePlayerMorph new\\n\\t\\t\\tonScorePlayer: (ScorePlayer onScore: score) title: 'sMovie'.\\n\\tpianoRoll := PianoRollScoreMorph new on: scoreController scorePlayer.\\n\\tself pianoRoll: pianoRoll. \\\"back link\\\"\\n\\tpianoRoll enableDragNDrop;\\n\\t\\tuseRoundedCorners;\\n\\t\\tmovieClipPlayer: self;\\n\\t\\tborderWidth: 2;\\n\\t\\textent: self width @ 120;\\n\\t\\talign: pianoRoll topLeft with: self bottomLeft - (0@2);\\n\\t\\topenInWorld.\\n\\tscoreController extent: self width @ scoreController height;\\n\\t\\talign: scoreController topLeft with: pianoRoll bottomLeft - (0@2);\\n\\t\\topenInWorld.\\n\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nopenMovieFile\\n\\t| fileName |\\n\\tfileName := Utilities chooseFileWithSuffixFromList: #('.movie')\\n\\t\\t\\t\\t\\twithCaption: 'Choose a movie file to open'.\\n\\tfileName ifNotNil:\\n\\t\\t[self openFileNamed: fileName.\\n\\t\\tself showMoreControls]! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nscanBySlider\\n\\t| scrollSlider handle |\\n\\tscrollSlider := SimpleSliderMorph new extent: 150@10;\\n\\t\\tcolor: color; sliderColor: Color gray;\\n\\t\\ttarget: self; actionSelector: #goToRelativePosition:;\\n\\t\\tadjustToValue: self relativePosition.\\n\\t(handle := scrollSlider firstSubmorph) on: #mouseUp send: #delete to: scrollSlider.\\n\\tscrollSlider align: handle center with: self activeHand position.\\n\\tself world addMorph: scrollSlider.\\n\\tself activeHand targetOffset: (handle width // 2) @ 0.\\n\\tself activeHand newMouseFocus: handle! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'di 10/16/2000 13:31'!\\nthumbnailForThisPage\\n\\t\\\"Overridden to make a MovieFrameSyncMorph\\\"\\n\\n\\t^ self makeThumbnailInHand: self activeHand\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'menu commands' stamp: 'di 7/6/1998 19:32'!\\nfirstPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: 1\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu commands' stamp: 'di 7/6/1998 14:05'!\\ninsertPage\\n\\t^ self makeMyPage! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'movie clip player' stamp: 'di 10/19/2000 22:02'!\\npianoRoll\\n\\t^ pianoRoll! !\\n\\n!MoviePlayerMorph methodsFor: 'movie clip player' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npianoRoll: aPianoRollScoreMorph\\n\\t\\\"Provides access also to the score and scorePlayer\\\"\\n\\n\\tpianoRoll := aPianoRollScoreMorph\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ngoToPage: i\\n\\tcurrentPage ifNil: [self makeMyPage].\\n\\tframeNumber := i.\\n\\tplayDirection := 0.\\n\\tself startRunning; step. \\\"will stop after first step\\\"\\n\\tsoundTrackMorph ifNotNilDo: [:m | m image fillWhite].\\n\\tself stepSoundTrack.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'di 7/6/1998 19:29'!\\nlastPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: frameCount\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nnextPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: (frameNumber := frameNumber + 1 min: frameCount).\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npreviousPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: (frameNumber := frameNumber - 1 max: 1).\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'di 10/16/2000 13:20'!\\nfullControlSpecs\\n\\t^ #(\\t\\n\\t\\t\\t( '\\U00b7'\\t\\tinvokeBookMenu 'Invoke menu')\\n\\t\\t\\t( '<--'\\t\\tfirstPage\\t\\t'Go to first page')\\n\\t\\t\\t( '<<'\\t\\tplayReverse\\t\\t'Play backward')\\n\\t\\t\\t( '<-' \\t\\tpreviousPage\\t'Back one frame')\\n\\t\\t\\t( '| |' \\t\\tstopPlay\\t\\t'Stop playback')\\n\\t\\t\\t( '->'\\t\\tnextPage\\t\\t'Forward one frame')\\n\\t\\t\\t( '>>'\\t\\tplayForward\\t'Play forward')\\n\\t\\t\\t( '-->'\\t\\tlastPage\\t\\t\\t'Go to final page')\\n\\t\\t\\t( '<->'\\t\\tscanBySlider\\t'Scan by slider' 'menu')\\n\\t\\t\\\"Note extra spec 'menu' causes mousedown activation -- see makePageControlsFrom:\\\"\\n\\t)! !\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'di 10/24/2000 16:55'!\\nshowPageControls\\n\\tself showPageControls: self fullControlSpecs.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nshowPageControls: controlSpecs \\n\\t| pageControls |\\n\\tself hidePageControls.\\n\\n\\tpageControls := self makePageControlsFrom: controlSpecs.\\n\\tpageControls borderWidth: 0; layoutInset: 0; extent: pageControls width@14.\\n\\tpageControls setProperty: #pageControl toValue: true.\\n\\tpageControls setNameTo: 'Page Controls'.\\n\\tpageControls eventHandler: (EventHandler new on: #mouseDown send: #move to: self).\\n\\tself addMorphBack: pageControls beSticky! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npauseFrom: player\\n\\n\\tplayDirection := 0.\\n\\tself step.! !\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:06'!\\nresetFrom: player\\n\\tself pauseFrom: player.\\n\\tself firstPage! !\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nresumeFrom: player\\n\\tplayDirection ~= 0 ifTrue: [^ self]. \\\"Already running\\\"\\n\\tplayDirection := 1.\\n\\tpianoRoll ifNil:\\n\\t\\t[\\\"Sync movie to score player if not a clip player\\\"\\n\\t\\tscorePlayer := player].\\n\\tself startRunning! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'di 10/16/2000 11:02'!\\ngoToRelativePosition: newPos\\n\\n\\tmovieFile ifNotNil: [^ self].\\n\\tself goToPage: ((newPos*frameCount) asInteger min: frameCount max: 1).\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplayForward\\n\\t(playDirection ~= 0 or: [frameNumber >= frameCount]) ifTrue:\\n\\t\\t[^ self]. \\\"No-op during play or at end\\\"\\n\\tplayDirection := 1.\\n\\tself startRunning! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplayReverse\\n\\t(playDirection ~= 0 or: [frameNumber <= 1]) ifTrue:\\n\\t\\t[^ self]. \\\"No-op during play or at end\\\"\\n\\tplayDirection := -1.\\n\\tself startRunning! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstopPlay\\n\\n\\tplayDirection := 0.\\n\\tself step! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'rounding' stamp: 'di 10/22/2000 23:41'!\\nwantsRoundedCorners\\n\\t^ Preferences roundedWindowCorners or: [super wantsRoundedCorners]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'di 9/5/2000 23:09'!\\nfileByteCountPerFrame\\n\\t\\n\\t^ (frameBufferIfScaled ifNil: [currentPage image]) bits size * 4\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'di 5/27/1999 22:40'!\\nfilePosForFrameNo: frameNo\\n\\t\\n\\t^ 128 + ((frameNo-1)*(4+self fileByteCountPerFrame)) + 4\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'dgd 2/22/2003 13:22'!\\nstartRunning\\n\\t| ms |\\n\\t(frameBufferIfScaled ifNil: [currentPage image]) unhibernate.\\n\\tmovieFile := AsyncFile new \\n\\t\\t\\t\\topen: (FileDirectory default fullNameFor: movieFileName)\\n\\t\\t\\t\\tforWrite: false.\\n\\tmovieFile \\n\\t\\tprimReadStart: movieFile fileHandle\\n\\t\\tfPosition: (self filePosForFrameNo: frameNumber)\\n\\t\\tcount: self fileByteCountPerFrame.\\n\\tscorePlayer isNil \\n\\t\\tifTrue: \\n\\t\\t\\t[ms := Time millisecondClockValue.\\n\\t\\t\\tmsAtStart := ms - ((frameNumber - 1) * msPerFrame).\\n\\t\\t\\tmsAtLastSync := ms - msAtStart]\\n\\t\\tifFalse: \\n\\t\\t\\t[(playDirection > 0 and: [scorePlayer isKindOf: SampledSound]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[scorePlayer\\n\\t\\t\\t\\t\\t\\treset;\\n\\t\\t\\t\\t\\t\\tplaySilentlyUntil: (frameNumber - 1) * msPerFrame / 1000.0;\\n\\t\\t\\t\\t\\t\\tinitialVolume: 1.0.\\n\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t[scorePlayer resumePlaying.\\n\\t\\t\\t\\t\\tmsAtLastSync := scorePlayer millisecondsSinceStart] \\n\\t\\t\\t\\t\\t\\t\\tforkAt: Processor userInterruptPriority].\\n\\t\\t\\tmsAtLastSync := scorePlayer millisecondsSinceStart].\\n\\tframeAtLastSync := frameNumber! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'dgd 2/22/2003 13:22'!\\nstep\\n\\t\\\"NOTE: The movie player has two modes of play, depending on whether scorePlayer is nil or not. If scorePlayer is nil, then play runs according to the millisecond clock. If scorePlayer is not nil, then the scorePlayer is consulted for synchronization. If the movie is running ahead, then some calls on step will skip their action until the right time. If the movie is running behind, then the frame may advance by more than one to maintain synchronization.\\\"\\n\\n\\t\\\"ALSO: This player operates with overlapped disk i/o. This means that while one frame is being displayed, the next frame in sequence is being read into a disk buffer. The value of frameNumber corresponds to the frame currently visible.\\\"\\n\\n\\t\\\"This code may not work right for playing backwards right now.\\n\\tSingle-step and backwards (dir <= 0) should just run open-loop.\\\"\\n\\n\\t| byteCount simTime ms nextFrameNumber |\\n\\tmovieFile isNil ifTrue: [^self].\\n\\tscorePlayer isNil \\n\\t\\tifTrue: \\n\\t\\t\\t[(ms := Time millisecondClockValue) < msAtStart \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"clock rollover\\\"\\n\\n\\t\\t\\t\\t\\tmsAtStart := ms - (frameNumber * msPerFrame)].\\n\\t\\t\\tsimTime := ms - msAtStart]\\n\\t\\tifFalse: [simTime := scorePlayer millisecondsSinceStart].\\n\\tplayDirection > 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[nextFrameNumber := frameAtLastSync \\n\\t\\t\\t\\t\\t\\t+ ((simTime - msAtLastSync) // msPerFrame).\\n\\t\\t\\tnextFrameNumber = frameNumber \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[((scorePlayer isKindOf: AbstractSound) and: [scorePlayer isPlaying not]) \\n\\t\\t\\t\\t\\t\\tifTrue: [^self stopRunning].\\n\\t\\t\\t\\t\\t^self]]\\n\\t\\tifFalse: \\n\\t\\t\\t[nextFrameNumber := playDirection < 0 \\n\\t\\t\\t\\t\\t\\tifTrue: [frameNumber - 1]\\n\\t\\t\\t\\t\\t\\tifFalse: [frameNumber]].\\n\\tbyteCount := self fileByteCountPerFrame.\\n\\tself stepSoundTrack.\\n\\tmovieFile waitForCompletion.\\n\\tmovieFile \\n\\t\\tprimReadResult: movieFile fileHandle\\n\\t\\tintoBuffer: (frameBufferIfScaled ifNil: [currentPage image]) bits\\n\\t\\tat: 1\\n\\t\\tcount: byteCount // 4.\\n\\tframeBufferIfScaled ifNotNil: \\n\\t\\t\\t[\\\"If this player has been shrunk, then we have to warp to the current page.\\\"\\n\\n\\t\\t\\t(WarpBlt current toForm: currentPage image)\\n\\t\\t\\t\\tsourceForm: frameBufferIfScaled;\\n\\t\\t\\t\\tcombinationRule: 3;\\n\\t\\t\\t\\tcellSize: (playDirection = 0 \\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Use smoothing if just stepping\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t2]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [1]);\\n\\t\\t\\t\\tcopyQuad: frameBufferIfScaled boundingBox innerCorners\\n\\t\\t\\t\\t\\ttoRect: currentPage image boundingBox].\\n\\tcurrentPage changed.\\n\\tframeNumber := nextFrameNumber.\\n\\t(playDirection = 0 or: \\n\\t\\t\\t[(playDirection > 0 and: [frameNumber >= frameCount]) \\n\\t\\t\\t\\tor: [playDirection < 0 and: [frameNumber <= 1]]]) \\n\\t\\tifTrue: [^self stopRunning].\\n\\n\\t\\\"Start the read operation for the next frame...\\\"\\n\\tmovieFile \\n\\t\\tprimReadStart: movieFile fileHandle\\n\\t\\tfPosition: (self filePosForFrameNo: frameNumber)\\n\\t\\tcount: byteCount! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'aoy 2/15/2003 21:45'!\\nstepSoundTrack\\n\\t| x image timeInMillisecs |\\n\\tscorePlayer ifNil: [^self].\\n\\tsoundTrackForm ifNil: [^self].\\n\\ttimeInMillisecs := playDirection = 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Stepping forward or back\\\"\\n\\n\\t\\t\\t (frameNumber - 1) * msPerFrame]\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Driven by sound track\\\"\\n\\n\\t\\t\\t scorePlayer millisecondsSinceStart].\\n\\tx := timeInMillisecs / 1000.0 * scorePlayer originalSamplingRate // 250.\\n\\timage := soundTrackMorph image.\\n\\timage \\n\\t\\tcopy: (image boundingBox translateBy: (x - (image width // 2)) @ 0)\\n\\t\\tfrom: soundTrackForm\\n\\t\\tto: 0 @ 0\\n\\t\\trule: Form over.\\n\\tsoundTrackMorph changed! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstopRunning\\n\\t\\\"Must only be called with no outstanding file read requests...\\\"\\n\\tmovieFile ifNotNil: [movieFile close. movieFile := nil].\\n\\tplayDirection := 0.\\n\\tself stopSoundTrackIfAny\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'testing' stamp: 'di 8/8/1998 11:57'!\\nstepTime\\n\\t^ 0 \\\"step as fast as possible\\\"! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmakeMyPage\\n\\n\\tcurrentPage ifNotNil:\\n\\t\\t[(currentPage isMemberOf: ImageMorph)\\n\\t\\t\\tifTrue: [\\\"currentPage is already an ImageMorph.\\\"\\n\\t\\t\\t\\t\\t(currentPage image extent = frameSize\\n\\t\\t\\t\\t\\t\\tand: [currentPage image depth = frameDepth])\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self \\\"page is already properly dimensioned.\\\"].\\n\\t\\t\\t\\t\\t^ currentPage image: (Form extent: frameSize depth: frameDepth)]\\n\\t\\t\\tifFalse: [currentPage releaseCachedState; delete]].\\n\\tcurrentPage := ImageMorph new image: (Form extent: frameSize depth: frameDepth).\\n\\tcurrentPage lock.\\n\\tpages := OrderedCollection with: currentPage.\\n\\tself addMorphFront: currentPage! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'di 10/25/2000 23:01'!\\nmakeThumbnailInHand: aHand\\n\\n\\tscorePlayer ifNotNil:\\n\\t\\t[\\\"Position the soundTrack for this frameNumber\\\"\\n\\t\\tscorePlayer reset; playSilentlyUntil: frameNumber - 1 * msPerFrame / 1000.0].\\n\\n\\taHand attachMorph:\\n\\t\\t(MovieClipStartMorph new\\n\\t\\t\\tmovieFileName: movieFileName\\n\\t\\t\\tsoundTrackFileName: soundTrackFileName\\n\\t\\t\\timage: currentPage image\\n\\t\\t\\tplayer: self\\n\\t\\t\\tframeNumber: frameNumber)\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npvtOpenFileNamed: fName\\n\\t\\\"Private - open on the movie file iof the given name\\\"\\n\\n\\t| f w h d n m |\\n\\tself stopRunning.\\n\\tfName = movieFileName ifTrue: [^ self]. \\\"No reopen necessary on same file\\\"\\n\\n\\tmovieFileName := fName.\\n\\t\\\"Read movie file parameters from 128-byte header...\\n\\t\\t(records follow as {N=int32, N words}*)\\\"\\n\\tf := (FileStream oldFileNamed: movieFileName) binary.\\n\\t\\tf nextInt32.\\n\\t\\tw := f nextInt32.\\n\\t\\th := f nextInt32.\\n\\t\\td := f nextInt32.\\n\\t\\tn := f nextInt32.\\n\\t\\tm := f nextInt32.\\n\\t\\tf close.\\n\\tpageSize := frameSize := w@h.\\n\\tframeDepth := d.\\n\\tframeCount := n.\\n\\tframeNumber := 1.\\n\\tplayDirection := 0.\\n\\tmsAtLastSync := 0.\\n\\tmsPerFrame := m/1000.0.\\n\\tself makeMyPage.\\n\\t(SmalltalkImage current platformName = 'Mac OS') ifTrue:[\\n\\t\\t(SmalltalkImage current extraVMMemory < self fileByteCountPerFrame) ifTrue:\\n\\t\\t\\t[^ self inform:\\n'Playing movies in Squeak requires that extra memory be allocated\\nfor asynchronous file IO. This particular movie requires a buffer of\\n' ,\\n(self fileByteCountPerFrame printString) , ' bytes, but you only have ' , (SmalltalkImage current extraVMMemory printString) , ' allocated.\\nYou can evaluate ''SmalltalkImage current extraVMMemory'' to check your allocation,\\nand ''SmalltalkImage current extraVMMemory: 485000'' or the like to increase your allocation.\\nNote that raising your allocation in this way only marks your image as\\nneeding this much, so you must then save, quit, and start over again\\nbefore you can run this movie. Good luck.']].\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ntryToShareScoreFor: fileName\\n\\n\\tscorePlayer := nil.\\n\\tself class allInstancesDo:\\n\\t\\t[:mp | mp == self ifFalse:\\n\\t\\t\\t[mp soundTrackFileName = fileName ifTrue:\\n\\t\\t\\t\\t[\\\"Found this score already open in another player\\n\\t\\t\\t\\t\\t-- return a copy that shares the same sound buffer.\\\"\\n\\t\\t\\t\\tmp scorePlayer ifNotNil: [^ scorePlayer := mp scorePlayer copy reset]]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMoviePlayerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MoviePlayerMorph class methodsFor: 'class initialization' stamp: 'hg 8/3/2000 16:59'!\\ninitialize\\n\\n\\tFileList registerFileReader: self! !\\n\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sd 2/6/2002 21:36'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\n\\t^(suffix = 'movie') | (suffix = '*')\\n\\t\\tifTrue: [ self services]\\n\\t\\tifFalse: [#()]! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'hg 8/3/2000 17:01'!\\nopenAsMovie: fullFileName\\n\\t\\\"Open a MoviePlayerMorph on the given file (must be in .movie format).\\\"\\n \\n\\t(self new openFileNamed: fullFileName) openInWorld! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 01:23'!\\nserviceOpenAsMovie\\n\\t\\\"Answer a service for opening a file as a movie\\\"\\n\\n\\t^ SimpleServiceEntry \\n\\t\\tprovider: self \\n\\t\\tlabel: 'open as movie'\\n\\t\\tselector: #openAsMovie:\\n\\t\\tdescription: 'open file as movie'\\n\\t\\tbuttonLabel: 'open'! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sw 9/7/2004 18:21'!\\nservices\\n\\t\\\"Formerly: answer a service for opening as a movie. Nowadays... no services\\\"\\n\\n\\t^ #().\\n\\\"\\n\\t^ Array with: self serviceOpenAsMovie\\\"\\n\\n\\t! !\\n\\n\\n!MoviePlayerMorph class methodsFor: 'initialize-release' stamp: 'SD 11/15/2001 22:22'!\\nunload\\n\\n\\tFileList unregisterFileReader: self ! !\\nEllipseMorph subclass: #MovingEyeMorph\\n\\tinstanceVariableNames: 'inner iris'\\n\\tclassVariableNames: 'IrisSize'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n\\n!MovingEyeMorph methodsFor: 'as yet unclassified' stamp: 'yo 2/15/2001 15:24'!\\nirisPos: cp\\n\\n\\t| a b theta x y |\\n\\ttheta _ (cp - self center) theta.\\n\\ta _ inner width // 2.\\n\\tb _ inner height // 2.\\n\\tx _ a * (theta cos).\\n\\ty _ b * (theta sin).\\n\\tiris position: ((x@y) asIntegerPoint) + self center - (iris extent // 2).! !\\n\\n\\n!MovingEyeMorph methodsFor: 'geometry' stamp: 'yo 2/15/2001 15:59'!\\nextent: aPoint\\n\\n\\tsuper extent: aPoint.\\n\\tinner extent: (self extent * ((1.0@1.0)-IrisSize)) asIntegerPoint.\\n\\tiris extent: (self extent * IrisSize) asIntegerPoint.\\n\\tinner position: (self center - (inner extent // 2)) asIntegerPoint.\\n! !\\n\\n\\n!MovingEyeMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:42'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!MovingEyeMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:42'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tinner _ EllipseMorph new.\\n\\tinner color: self color.\\n\\tinner extent: (self extent * (1.0 @ 1.0 - IrisSize)) asIntegerPoint.\\n\\tinner borderColor: self color.\\n\\tinner borderWidth: 0.\\n\\\"\\\"\\n\\tiris _ EllipseMorph new.\\n\\tiris color: Color white.\\n\\tiris extent: (self extent * IrisSize) asIntegerPoint.\\n\\\"\\\"\\n\\tself addMorphCentered: inner.\\n\\tinner addMorphCentered: iris.\\n\\\"\\\"\\n\\tself extent: 26 @ 33! !\\n\\n\\n!MovingEyeMorph methodsFor: 'stepping and presenter' stamp: 'di 2/18/2001 00:10'!\\nstep\\n\\t| cp |\\n\\tcp _ self globalPointToLocal: World primaryHand position.\\n\\t(inner containsPoint: cp)\\n\\t\\tifTrue: [iris position: (cp - (iris extent // 2))]\\n\\t\\tifFalse: [self irisPos: cp].\\n\\tself changed \\\"cover up gribblies if embedded in Flash\\\"! !\\n\\n\\n!MovingEyeMorph methodsFor: 'testing' stamp: 'yo 2/15/2001 15:38'!\\nstepTime\\n\\n\\t^ 100.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMovingEyeMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MovingEyeMorph class methodsFor: 'class initialization' stamp: 'yo 2/15/2001 16:04'!\\ninitialize\\n\\\"\\n\\tMovingEyeMorph initialize\\n\\\"\\n\\tIrisSize _ (0.42@0.50).! !\\n\\n\\n!MovingEyeMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:51'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'MovingEye'\\n\\t\\tcategories:\\t\\t#('Demo')\\n\\t\\tdocumentation:\\t'An eye which follows the cursor'! !\\nSoundCodec subclass: #MuLawCodec\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DecodingTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!MuLawCodec commentStamp: '<historical>' prior: 0!\\nI represent a mu-law (u-law) codec. I compress sound data by a factor of 2:1 by encoding the most significant 12 bits of each 16-bit sample as a signed, exponentially encoded byte. The idea is to use more resolution for smaller lower sample values. This encoding was developed for the North American phone system and a variant of it, a-law, is a European phone standard. It is a popular sound encoding on Unix platforms (.au files).\\n!\\n\\n\\n!MuLawCodec methodsFor: 'external access' stamp: 'di 2/8/1999 22:28'!\\nuLawDecodeSample: byte\\n\\t\\\"Decode a 16-bit signed sample from 8 bits using uLaw decoding\\\"\\n\\n\\t^ DecodingTable at: byte + 1! !\\n\\n!MuLawCodec methodsFor: 'external access' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuLawEncodeSample: sample\\n\\t\\\"Encode a 16-bit signed sample into 8 bits using uLaw encoding\\\"\\n\\n\\t| s |\\n\\ts := sample // 8. \\\"drop 3 least significant bits\\\"\\n\\ts < 0 ifTrue: [^ (self uLawEncode12Bits: 0-s) + 16r80]\\n\\t\\tifFalse: [^ (self uLawEncode12Bits: s)].\\n! !\\n\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'jm 2/2/1999 09:15'!\\nbytesPerEncodedFrame\\n\\t\\\"Answer the number of bytes required to hold one frame of compressed sound data. Answer zero if this codec produces encoded frames of variable size.\\\"\\n\\n\\t^ 1\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecodeFrames: frameCount from: srcByteArray at: srcIndex into: dstSoundBuffer at: dstIndex\\n\\t\\\"Decode the given number of monophonic frames starting at the given index in the given ByteArray of compressed sound data and storing the decoded samples into the given SoundBuffer starting at the given destination index. Answer a pair containing the number of bytes of compressed data consumed and the number of decompressed samples produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\t| dst |\\n\\tdst := dstIndex.\\n\\tsrcIndex to: srcIndex + frameCount - 1 do: [:src |\\n\\t\\tdstSoundBuffer at: dst put: (DecodingTable at: (srcByteArray at: src) + 1).\\n\\t\\tdst := dst + 1].\\n\\t^ Array with: frameCount with: frameCount\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'di 2/8/1999 22:25'!\\nencodeFrames: frameCount from: srcSoundBuffer at: srcIndex into: dstByteArray at: dstIndex\\n\\t\\\"Encode the given number of frames starting at the given index in the given monophonic SoundBuffer and storing the encoded sound data into the given ByteArray starting at the given destination index. Encode only as many complete frames as will fit into the destination. Answer a pair containing the number of samples consumed and the number of bytes of compressed data produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tsrcIndex to: srcIndex + frameCount - 1 do: [:i |\\n\\t\\tdstByteArray at: i put: (self uLawEncodeSample: (srcSoundBuffer at: i))].\\n\\t^ Array with: frameCount with: frameCount\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'jm 2/2/1999 09:11'!\\nsamplesPerFrame\\n\\t\\\"Answer the number of sound samples per compression frame.\\\"\\n\\n\\t^ 1\\n! !\\n\\n\\n!MuLawCodec methodsFor: 'private' stamp: 'di 2/9/1999 13:25'!\\nuLawEncode12Bits: s\\n\\t\\\"Encode a 12-bit unsigned sample (0-4095) into 7 bits using uLaw encoding.\\n\\tThis gets called by a method that scales 16-bit signed integers down to a\\n\\t\\t12-bit magnitude, and then ORs in 16r80 if they were negative.\\n\\tDetail: May get called with s >= 4096, and this works fine.\\\"\\n\\n\\ts < 496 ifTrue: [\\n\\t\\ts < 112 ifTrue: [\\n\\t\\t\\ts < 48 ifTrue: [\\n\\t\\t\\t\\ts < 16\\n\\t\\t\\t\\t\\tifTrue: [^ 16r70 bitOr: (15 - s)]\\n\\t\\t\\t\\t\\tifFalse: [^ 16r60 bitOr: (15 - ((s - 16) bitShift: -1))]].\\n\\t\\t\\t^ 16r50 bitOr: (15 - ((s - 48) bitShift: -2))].\\n\\t\\ts < 240\\n\\t\\t\\tifTrue: [^ 16r40 bitOr: (15 - ((s - 112) bitShift: -3))]\\n\\t\\t\\tifFalse: [^ 16r30 bitOr: (15 - ((s - 240) bitShift: -4))]].\\n\\n\\ts < 2032 ifTrue: [\\n\\t\\ts < 1008\\n\\t\\t\\tifTrue: [^ 16r20 bitOr: (15 - ((s - 496) bitShift: -5))]\\n\\t\\t\\tifFalse: [^ 16r10 bitOr: (15 - ((s - 1008) bitShift: -6))]].\\n\\n\\ts < 4080\\n\\t\\tifTrue: [^ 15 - ((s - 2032) bitShift: -7)]\\n\\t\\tifFalse: [^ 0].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMuLawCodec class\\n\\tinstanceVariableNames: ''!\\n\\n!MuLawCodec class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"Build the 256 entry table to be used to decode 8-bit uLaw-encoded samples.\\\"\\n\\t\\\"MuLawCodec initialize\\\"\\n\\n\\t| encoded codec lastEncodedPos lastEncodedNeg |\\n\\tDecodingTable := Array new: 256.\\n\\tcodec := self new.\\n\\tlastEncodedPos := nil.\\n\\tlastEncodedNeg := nil.\\n\\t4095 to: 0 by: -1 do: [:s |\\n\\t\\tencoded := codec uLawEncode12Bits: s.\\n\\t\\tlastEncodedPos = encoded\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tDecodingTable at: (encoded + 1) put: (s bitShift: 3).\\n\\t\\t\\t\\tlastEncodedPos := encoded].\\n\\t\\tencoded := encoded bitOr: 16r80.\\n\\t\\tlastEncodedNeg = encoded\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tDecodingTable at: (encoded + 1) put: (s bitShift: 3) negated.\\n\\t\\t\\t\\tlastEncodedNeg := encoded]].\\n! !\\nReadWriteStream subclass: #MultiByteBinaryOrTextStream\\n\\tinstanceVariableNames: 'isBinary converter'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n!MultiByteBinaryOrTextStream commentStamp: '<historical>' prior: 0!\\nIt is similar to MultiByteFileStream, but works on in memory stream.!\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:16'!\\nascii\\n\\tisBinary _ false\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:16'!\\nbinary\\n\\tisBinary _ true\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'nk 8/2/2004 17:02'!\\nconverter\\n\\n\\tconverter ifNil: [converter _ self class defaultConverter].\\n\\t^ converter\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 8/7/2003 09:12'!\\nconverter: aConverter\\n\\n\\tconverter _ aConverter.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:25'!\\nisBinary\\n\\t^ isBinary! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 16:33'!\\ntext\\n\\tisBinary _ false\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:10'!\\nfileInObjectAndCodeForProject\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileInProject. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:46'!\\nfileInProject\\n\\n\\tself setConverterForCodeForProject.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:46'!\\nsetConverterForCodeForProject\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'converting' stamp: 'yo 11/11/2002 13:16'!\\nasBinaryOrTextStream\\n\\n\\t^ self\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 8/17/2004 10:02'!\\nfileIn\\n\\n\\tself setConverterForCode.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 11/11/2002 16:31'!\\nfileInObjectAndCode\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileIn. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'tak 1/12/2005 13:47'!\\nfileOutClass: extraClass andObject: theObject \\n\\tUTF8TextConverter writeBOMOn: self.\\n\\t^ super fileOutClass: extraClass andObject: theObject! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 8/18/2004 09:36'!\\nsetConverterForCode\\n\\n\\t| current |\\n\\tcurrent _ converter saveStateOf: self.\\n\\tself position: 0.\\n\\tself binary.\\n\\t((self next: 3) = (ByteArray with: 16rEF with: 16rBB with: 16rBF)) ifTrue: [\\n\\t\\tself converter: UTF8TextConverter new\\n\\t] ifFalse: [\\n\\t\\tself converter: MacRomanTextConverter new.\\n\\t].\\n\\tconverter restoreStateOf: self with: current.\\n\\tself text.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 7/7/2004 09:43'!\\nsetEncoderForSourceCodeNamed: streamName\\n\\n\\t| l |\\n\\tl _ streamName asLowercase.\\n\\\"\\t((l endsWith: FileStream multiCs) or: [\\n\\t\\t(l endsWith: FileStream multiSt) or: [\\n\\t\\t\\t(l endsWith: (FileStream multiSt, '.gz')) or: [\\n\\t\\t\\t\\t(l endsWith: (FileStream multiCs, '.gz'))]]]) ifTrue: [\\n\\t\\t\\t\\t\\tself converter: UTF8TextConverter new.\\n\\t\\t\\t\\t\\t^ self.\\n\\t].\\n\\\"\\n\\t((l endsWith: FileStream cs) or: [\\n\\t\\t(l endsWith: FileStream st) or: [\\n\\t\\t\\t(l endsWith: (FileStream st, '.gz')) or: [\\n\\t\\t\\t\\t(l endsWith: (FileStream cs, '.gz'))]]]) ifTrue: [\\n\\t\\t\\t\\t\\tself converter: MacRomanTextConverter new.\\n\\t\\t\\t\\t\\t^ self.\\n\\t].\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'properties-setting' stamp: 'yo 11/14/2002 13:49'!\\nsetFileTypeToObject\\n\\t\\\"do nothing. We don't have a file type\\\"! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 7/30/2004 06:59'!\\ncontents\\n\\n\\t| ret state |\\n\\tstate _ converter saveStateOf: self.\\n\\tret _ self upToEnd.\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ ret.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:39'!\\nnext\\n\\n\\t| n |\\n\\tn _ self converter nextFromStream: self.\\n\\tn ifNil: [^ nil].\\n\\tisBinary and: [n isCharacter ifTrue: [^ n asciiValue]].\\n\\t^ n.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'ar 4/12/2005 17:34'!\\nnext: anInteger \\n\\n\\t| multiString |\\n\\t\\\"self halt.\\\"\\n\\tself isBinary ifTrue: [^ (super next: anInteger) asByteArray].\\n\\tmultiString _ WideString new: anInteger.\\n\\t1 to: anInteger do: [:index |\\n\\t\\t| character |\\n\\t\\t(character _ self next) ifNotNil: [\\n\\t\\t\\tmultiString at: index put: character\\n\\t\\t] ifNil: [\\n\\t\\t\\tmultiString _ multiString copyFrom: 1 to: index - 1.\\n\\t\\t\\t^ multiString\\n\\t\\t]\\n\\t].\\n\\t^ multiString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:05'!\\nnextDelimited: terminator\\n\\n\\t| out ch pos |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\tpos _ self position.\\n\\tself next = terminator ifFalse: [\\n\\t\\t\\\"absorb initial terminator\\\"\\n\\t\\tself position: pos.\\n\\t].\\n\\t[(ch _ self next) == nil] whileFalse: [\\n\\t\\t(ch = terminator) ifTrue: [\\n\\t\\t\\tself peek = terminator ifTrue: [\\n\\t\\t\\t\\tself next. \\\"skip doubled terminator\\\"\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nnextMatchAll: aColl\\n\\n | save |\\n save _ converter saveStateOf: self.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n converter restoreStateOf: self with: save.\\n ^ false.\\n\\t\\t].\\n\\t].\\n ^ true.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/14/2002 13:54'!\\nnextPut: aCharacter\\n\\n\\taCharacter isInteger ifTrue: [^ super nextPut: aCharacter asCharacter].\\n\\t^ self converter nextPut: aCharacter toStream: self\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nnextPutAll: aCollection\\n\\n\\tself isBinary ifTrue: [\\n\\t\\t^ super nextPutAll: aCollection.\\n\\t].\\n\\taCollection do: [:e | self nextPut: e].\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/14/2002 13:54'!\\npadToEndWith: aChar\\n\\t\\\"We don't have pages, so we are at the end, and don't need to pad.\\\"! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:04'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\n\\t| next pos |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tpos _ self position.\\n\\tnext _ self next.\\n\\tself position: pos.\\n\\t^ next.\\n\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:25'!\\npeekFor: item \\n\\n\\t| next state |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\tstate _ converter saveStateOf: self.\\n\\t(next _ self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ false.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'nk 7/29/2004 12:02'!\\nreset\\n\\n\\tsuper reset.\\n\\tisBinary ifNil: [isBinary _ false].\\n\\tcollection class == ByteArray ifTrue: [\\\"Store as String and convert as needed.\\\"\\n\\t\\tcollection _ collection asString.\\n\\t\\tisBinary _ true].\\n\\n\\tself converter. \\\"ensure that we have a converter.\\\"! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:17'!\\nskipSeparators\\n\\n\\t[self atEnd] whileFalse: [\\n\\t\\tself basicNext isSeparator ifFalse: [\\n\\t\\t\\t^ self position: self position - 1]]\\n\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:04'!\\nskipSeparatorsAndPeekNext\\n\\n\\t\\\"A special function to make nextChunk fast\\\"\\n\\t| peek pos |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tpos _ self position.\\n\\t\\t(peek _ self next) isSeparator ifFalse: [\\n\\t\\t\\tself position: pos.\\n\\t\\t\\t^ peek.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nupTo: delim \\n\\n\\t| out ch |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\t[(ch _ self next) isNil] whileFalse: [\\n\\t\\t(ch = delim) ifTrue: [\\n\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:17'!\\nupToEnd\\n\\n\\t| newStream element newCollection |\\n\\tnewCollection _ self isBinary\\n\\t\\t\\t\\tifTrue: [ByteArray new: 100]\\n\\t\\t\\t\\tifFalse: [String new: 100].\\n\\tnewStream _ WriteStream on: newCollection.\\n\\t[(element _ self next) notNil]\\n\\t\\twhileTrue: [newStream nextPut: element].\\n\\t^ newStream contents\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private' stamp: 'nk 8/2/2004 17:01'!\\nguessConverter\\n\\t^ (self originalContents includesSubString: (ByteArray withAll: {27. 36}) asString)\\n\\t\\tifTrue: [CompoundTextConverter new]\\n\\t\\tifFalse: [self class defaultConverter ]! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 16:01'!\\nbasicNext\\n\\n\\t^ super next \\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'md 10/20/2004 15:32'!\\nbasicNext: anInteger\\n\\n\\t^ super next: anInteger.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNext: n into: aString\\n\\n\\t^ super next: n into: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextInto: aString\\n\\n\\t^ super nextInto: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextPut: char\\n\\n\\t^ super nextPut: char.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextPutAll: aString\\n\\n\\t^ super nextPutAll: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPeek\\n\\n\\t^ super peek\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPosition\\n\\n\\t^ super position.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPosition: pos\\n\\n\\t^ super position: pos.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiByteBinaryOrTextStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'defaults' stamp: 'yo 2/25/2005 20:04'!\\ndefaultConverter\\n\\t^ Latin1TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'instance creation' stamp: 'ykoubo 9/28/2003 19:59'!\\non: aCollection encoding: encodingName \\n\\t| aTextConverter |\\n\\tencodingName isNil\\n\\t\\tifTrue: [aTextConverter _ TextConverter default]\\n\\t\\tifFalse: [aTextConverter _ TextConverter newForEncoding: encodingName].\\n\\t^ (self on: aCollection)\\n\\t\\tconverter: aTextConverter! !\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'instance creation' stamp: 'yo 11/23/2003 20:32'!\\nwith: aCollection encoding: encodingName \\n\\t| aTextConverter |\\n\\tencodingName isNil\\n\\t\\tifTrue: [aTextConverter _ TextConverter default]\\n\\t\\tifFalse: [aTextConverter _ TextConverter newForEncoding: encodingName].\\n\\t^ (self with: aCollection)\\n\\t\\tconverter: aTextConverter! !\\nStandardFileStream subclass: #MultiByteFileStream\\n\\tinstanceVariableNames: 'converter lineEndConvention wantsLineEndConversion'\\n\\tclassVariableNames: 'Cr CrLf Lf LineEndDefault LineEndStrings LookAheadCount'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n!MultiByteFileStream commentStamp: '<historical>' prior: 0!\\nThe central class to access the external file. The interface of this object is similar to good old StandardFileStream, but internally it asks the converter, which is a sub-instance of TextConverter, and do the text conversion.\\n\\n It also combined the good old CrLfFileStream. CrLfFileStream class>>new now returns an instance of MultiByteFileStream.\\n\\n There are several pitfalls:\\n\\n * You always have to be careful about the binary/text distinction. In #text mode, it usually interpret the bytes.\\n * A few file pointer operations treat the file as uninterpreted byte no matter what. This means that if you use 'fileStream skip: -1', 'fileStream position: x', etc. in #text mode, the file position can be in the middle of multi byte character. If you want to implement some function similar to #peek for example, call the saveStateOf: and restoreStateOf: methods to be able to get back to the original state.\\n * #lineEndConvention: and #wantsLineEndConversion: (and #binary) can cause some puzzling situation because the inst var lineEndConvention and wantsLineEndConversion are mutated. If you have any suggestions to clean up the protocol, please let me know.!\\n\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:57'!\\nascii\\n\\n\\tsuper ascii.\\n\\tself detectLineEndConvention.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:57'!\\nbinary\\n\\n\\tsuper binary.\\n\\tlineEndConvention _ nil.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/18/2003 15:11'!\\nconverter\\n\\n\\tconverter ifNil: [converter _ TextConverter defaultSystemConverter].\\n\\t^ converter\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/28/2002 11:09'!\\nconverter: aConverter\\n\\n\\tconverter _ aConverter.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/6/2003 11:56'!\\nfileInEncodingName: aString\\n\\n\\tself converter: (TextConverter newForEncoding: aString).\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'nk 9/5/2004 12:57'!\\nlineEndConvention\\n\\n\\t^lineEndConvention! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:59'!\\nlineEndConvention: aSymbol\\n\\n\\tlineEndConvention _ aSymbol.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 04:24'!\\nwantsLineEndConversion: aBoolean\\n\\n\\twantsLineEndConversion _ aBoolean.\\n\\tself detectLineEndConvention.! !\\n\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/24/2004 13:38'!\\nbareNext\\n\\n\\t ^ self converter nextFromStream: self.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 02:56'!\\nconvertStringFromCr: aString \\n\\t| inStream outStream |\\n\\tlineEndConvention ifNil: [^ aString].\\n\\tlineEndConvention == #cr ifTrue: [^ aString].\\n\\tlineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Cr with: Lf].\\n\\t\\\"lineEndConvention == #crlf\\\"\\n\\tinStream _ ReadStream on: aString.\\n\\toutStream _ WriteStream on: (String new: aString size).\\n\\t[inStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[outStream nextPutAll: (inStream upTo: Cr).\\n\\t\\t\\t(inStream atEnd not or: [aString last = Cr])\\n\\t\\t\\t\\tifTrue: [outStream nextPutAll: CrLf]].\\n\\t^ outStream contents! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 02:56'!\\nconvertStringToCr: aString \\n\\t| inStream outStream |\\n\\tlineEndConvention ifNil: [^ aString].\\n\\tlineEndConvention == #cr ifTrue: [^ aString].\\n\\tlineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Lf with: Cr].\\n\\t\\\"lineEndConvention == #crlf\\\"\\n\\tinStream _ ReadStream on: aString.\\n\\toutStream _ WriteStream on: (String new: aString size).\\n\\t[inStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[outStream nextPutAll: (inStream upTo: Cr).\\n\\t\\t\\t(inStream atEnd not or: [aString last = Cr])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[outStream nextPut: Cr.\\n\\t\\t\\t\\t\\tinStream peek = Lf ifTrue: [inStream next]]].\\n\\t^ outStream contents! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'nk 9/5/2004 12:50'!\\ndetectLineEndConvention\\n\\t\\\"Detect the line end convention used in this stream. The result may be either #cr, #lf or #crlf.\\\"\\n\\t| char numRead state |\\n\\tself isBinary ifTrue: [^ self error: 'Line end conventions are not used on binary streams'].\\n\\tself wantsLineEndConversion ifFalse: [^ lineEndConvention _ nil.].\\n\\tself closed ifTrue: [^ lineEndConvention _ LineEndDefault.].\\n\\n\\t\\\"Default if nothing else found\\\"\\n\\tnumRead _ 0.\\n\\tstate _ converter saveStateOf: self.\\n\\tlineEndConvention _ nil.\\n\\t[super atEnd not and: [numRead < LookAheadCount]]\\n\\t\\twhileTrue: \\n\\t\\t\\t[char _ self next.\\n\\t\\t\\tchar = Lf\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[converter restoreStateOf: self with: state.\\n\\t\\t\\t\\t\\t^ lineEndConvention _ #lf].\\n\\t\\t\\tchar = Cr\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self peek = Lf\\n\\t\\t\\t\\t\\t\\tifTrue: [lineEndConvention _ #crlf]\\n\\t\\t\\t\\t\\t\\tifFalse: [lineEndConvention _ #cr].\\n\\t\\t\\t\\t\\tconverter restoreStateOf: self with: state.\\n\\t\\t\\t\\t\\t^ lineEndConvention].\\n\\t\\t\\tnumRead _ numRead + 1].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ lineEndConvention _ LineEndDefault.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'nk 9/5/2004 12:51'!\\ndoConversion\\n\\n\\t^self wantsLineEndConversion and: [ lineEndConvention notNil ]! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/24/2004 13:44'!\\nnext: n innerFor: aString\\n\\n\\t| peekChar state |\\n\\t\\\"if we just read a CR, and the next character is an LF, then skip the LF\\\"\\n\\taString size = 0 ifTrue: [^ aString].\\n\\t(aString last = Character cr) ifTrue: [\\n\\t\\tstate _ converter saveStateOf: self.\\n\\t\\tpeekChar _ self bareNext.\\t\\t\\\"super peek doesn't work because it relies on #next\\\"\\n\\t\\t(peekChar notNil and: [peekChar ~= Character lf]) ifTrue: [\\n\\t\\t\\tconverter restoreStateOf: self with: state.\\n\\t\\t].\\n\\t].\\n \\n\\t^ aString withSqueakLineEndings.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 03:51'!\\nwantsLineEndConversion\\n\\n\\t^ wantsLineEndConversion ifNil: [false].\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'yo 8/17/2004 10:03'!\\nfileIn\\n\\n\\tself setConverterForCode.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'ar 7/29/2005 22:33'!\\nfileInObjectAndCodeForProject\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileInProject. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'ar 7/29/2005 22:33'!\\nfileInProject\\n\\n\\tself setConverterForCodeForProject.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'tak 1/12/2005 14:48'!\\nfileOutClass: extraClass andObject: theObject \\n\\tself binary.\\n\\tUTF8TextConverter writeBOMOn: self.\\n\\tself text.\\n\\t^ super fileOutClass: extraClass andObject: theObject! !\\n\\n\\n!MultiByteFileStream methodsFor: 'open/close' stamp: 'md 7/20/2006 11:05'!\\nopen: fileName forWrite: writeMode \\n\\t| result |\\n\\tresult := super open: fileName forWrite: writeMode.\\n\\tresult ifNotNil: [\\n\\t\\t\\tconverter ifNil: [converter := UTF8TextConverter new].\\n\\t\\t\\tself detectLineEndConvention].\\n\\t^result! !\\n\\n!MultiByteFileStream methodsFor: 'open/close' stamp: 'yo 8/13/2003 13:51'!\\nreset\\n\\n\\tsuper reset.\\n\\tconverter ifNil: [\\n\\t\\tconverter _ UTF8TextConverter new.\\n\\t].\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/24/2004 13:49'!\\nnext\\n\\n\\t| char secondChar state |\\n\\tchar _ self converter nextFromStream: self.\\n\\tself doConversion ifTrue: [\\n\\t\\tchar == Cr ifTrue: [\\n\\t\\t\\tstate _ converter saveStateOf: self.\\n\\t\\t\\tsecondChar _ self bareNext.\\n\\t\\t\\tsecondChar ifNotNil: [secondChar == Lf ifFalse: [converter restoreStateOf: self with: state]].\\n\\t\\t^Cr].\\n\\t\\tchar == Lf ifTrue: [^Cr].\\n\\t].\\n\\t^ char.\\n\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 7/31/2004 18:03'!\\nnext: anInteger \\n\\n\\t| multiString |\\n\\tself isBinary ifTrue: [^ super next: anInteger].\\n\\tmultiString _ String new: anInteger.\\n\\t1 to: anInteger do: [:index |\\n\\t\\t| character |\\n\\t\\t(character _ self next) ifNotNil: [\\n\\t\\t\\tmultiString at: index put: character\\n\\t\\t] ifNil: [\\n\\t\\t\\tmultiString _ multiString copyFrom: 1 to: index - 1.\\n\\t\\t\\tself doConversion ifFalse: [\\n\\t\\t\\t\\t^ multiString\\n\\t\\t\\t].\\n\\t\\t\\t^ self next: anInteger innerFor: multiString.\\n\\t\\t]\\n\\t].\\n\\tself doConversion ifFalse: [\\n\\t\\t^ multiString\\n\\t].\\n\\n\\tmultiString _ self next: anInteger innerFor: multiString.\\n\\t(multiString size = anInteger or: [self atEnd]) ifTrue: [ ^ multiString].\\n\\t^ multiString, (self next: anInteger - multiString size).\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 03:26'!\\nnextDelimited: terminator\\n\\n\\t| out ch save |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\tsave _ converter saveStateOf: self.\\n\\n\\tself next = terminator ifFalse: [\\n\\t\\t\\\"absorb initial terminator\\\"\\n\\t\\tconverter restoreStateOf: self with: save.\\n\\t].\\n\\t[(ch _ self next) == nil] whileFalse: [\\n\\t\\t(ch = terminator) ifTrue: [\\n\\t\\t\\tself peek = terminator ifTrue: [\\n\\t\\t\\t\\tself next. \\\"skip doubled terminator\\\"\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:13'!\\nnextMatchAll: aColl\\n\\n | save |\\n save _ converter saveStateOf: self.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n converter restoreStateOf: self with: save.\\n ^ false.\\n\\t\\t].\\n\\t].\\n ^ true.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 03:42'!\\nnextPut: aCharacter\\n\\n\\taCharacter isInteger ifTrue: [^ super nextPut: aCharacter].\\n\\tself doConversion ifTrue: [\\n\\t\\taCharacter = Cr ifTrue: [\\n\\t\\t\\t(LineEndStrings at: lineEndConvention) do: [:e | converter nextPut: e toStream: self].\\n\\t\\t] ifFalse: [\\n\\t\\t\\tconverter nextPut: aCharacter toStream: self\\n\\t\\t].\\n\\t\\t^ aCharacter\\n\\t].\\n\\t^ self converter nextPut: aCharacter toStream: self\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 5/23/2003 09:40'!\\nnextPutAll: aCollection\\n\\n\\t(self isBinary or: [aCollection class == ByteArray]) ifTrue: [\\n\\t\\t^ super nextPutAll: aCollection.\\n\\t].\\n\\taCollection do: [:e | self nextPut: e].\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 04:00'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\n\\t| next save |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tsave _ converter saveStateOf: self.\\n\\tnext _ self next.\\n\\tconverter restoreStateOf: self with: save.\\n\\t^ next.\\n\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:15'!\\npeekFor: item \\n\\n\\t| next state |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\tstate _ converter saveStateOf: self.\\n\\t(next _ self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ false.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/24/2004 13:35'!\\nskipSeparators\\n\\n\\t| state |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tstate _ converter saveStateOf: self.\\n\\t\\tself next isSeparator ifFalse: [\\n\\t\\t\\t^ converter restoreStateOf: self with: state]]\\n\\n\\n\\\"\\t[self atEnd] whileFalse: [\\n\\t\\tself next isSeparator ifFalse: [\\n\\t\\t\\t^ self position: self position - converter currentCharSize.\\n\\t\\t].\\n\\t].\\n\\\"\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 04:01'!\\nskipSeparatorsAndPeekNext\\n\\n\\t\\\"A special function to make nextChunk fast\\\"\\n\\t| peek save |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tsave _ converter saveStateOf: self.\\n\\t\\t(peek _ self next) isSeparator ifFalse: [\\n\\t\\t\\tconverter restoreStateOf: self with: save.\\n\\t\\t\\t^ peek.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:17'!\\nupTo: delim \\n\\n\\t| out ch |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\t[(ch _ self next) isNil] whileFalse: [\\n\\t\\t(ch = delim) ifTrue: [\\n\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/30/2002 16:39'!\\nupToEnd\\n\\n\\t| newStream element |\\n\\tcollection _ self isBinary\\n\\t\\t\\t\\tifTrue: [ByteArray new: 100]\\n\\t\\t\\t\\tifFalse: [String new: 100].\\n\\tnewStream _ WriteStream on: collection.\\n\\t[(element _ self next) notNil]\\n\\t\\twhileTrue: [newStream nextPut: element].\\n\\t^ newStream contents\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'remnant' stamp: 'yo 8/28/2002 11:06'!\\naccepts: aSymbol\\n\\n \\t^ converter accepts: aSymbol.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'remnant' stamp: 'yo 8/28/2002 11:09'!\\nfilterFor: aFileStream\\n\\n\\t| rw |\\n\\tname _ aFileStream name.\\n\\trw _ aFileStream isReadOnly not.\\n\\taFileStream close.\\n\\tself open: name forWrite: rw.\\n\\t^self.\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'private' stamp: 'mir 8/25/2004 17:27'!\\nsetConverterForCode\\n\\n\\t| current |\\n\\t(SourceFiles at: 2)\\n\\t\\tifNotNil: [self fullName = (SourceFiles at: 2) fullName ifTrue: [^ self]].\\n\\tcurrent _ self converter saveStateOf: self.\\n\\tself position: 0.\\n\\tself binary.\\n\\t((self next: 3) = (ByteArray with: 16rEF with: 16rBB with: 16rBF)) ifTrue: [\\n\\t\\tself converter: UTF8TextConverter new\\n\\t] ifFalse: [\\n\\t\\tself converter: MacRomanTextConverter new.\\n\\t].\\n\\tconverter restoreStateOf: self with: current.\\n\\tself text.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private' stamp: 'ar 7/29/2005 22:33'!\\nsetConverterForCodeForProject\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'md 10/17/2004 16:09'!\\nbasicNext: anInteger\\n\\n\\t^ super next: anInteger.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNext: n into: aString\\n\\n\\t^ super next: n into: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextInto: aString\\n\\n\\t^ super nextInto: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextPut: char\\n\\n\\t^ super nextPut: char.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextPutAll: aString\\n\\n\\t^ super nextPutAll: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicPeek\\n\\n\\t^ super peek\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicPosition\\n\\n\\t^ super position.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicPosition: pos\\n\\n\\t^ super position: pos.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicReadInto: byteArray startingAt: startIndex count: count\\n\\n\\t^ super readInto: byteArray startingAt: startIndex count: count.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicSetToEnd\\n\\n\\t^ super setToEnd.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicSkip: n\\n\\n\\t^ super skip: n.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicUpTo: delim\\n\\n\\t^ super upTo: delim.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:09'!\\nbasicVerbatim: aString\\n\\n\\t^ super verbatim: aString.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiByteFileStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:45'!\\ndefaultToCR\\n\\n\\t\\\"MultiByteFileStream defaultToCR\\\"\\n\\tLineEndDefault := #cr.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:45'!\\ndefaultToCRLF\\n\\n\\t\\\"MultiByteFileStream defaultToCRLF\\\"\\n\\tLineEndDefault := #crlf.! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:46'!\\ndefaultToLF\\n\\n\\t\\\"MultiByteFileStream defaultToLF\\\"\\n\\tLineEndDefault := #lf.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\nguessDefaultLineEndConvention\\n\\n\\t\\\"Lets try to guess the line end convention from what we know about the path name delimiter from FileDirectory.\\\"\\n\\tFileDirectory pathNameDelimiter = $: ifTrue:[^self defaultToCR].\\n\\tFileDirectory pathNameDelimiter = $/ ifTrue:[^self defaultToLF].\\n\\tFileDirectory pathNameDelimiter = $\\\\ ifTrue:[^self defaultToCRLF].\\n\\t\\\"in case we don't know\\\"\\n\\t^self defaultToCR.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\ninitialize\\n\\n\\t\\\"MultiByteFileStream initialize\\\"\\n\\tCr := Character cr.\\n\\tLf := Character lf.\\n\\tCrLf := String with: Cr with: Lf.\\n\\tLineEndStrings := Dictionary new.\\n\\tLineEndStrings at: #cr put: (String with: Character cr).\\n\\tLineEndStrings at: #lf put: (String with: Character lf).\\n\\tLineEndStrings at: #crlf put: (String with: Character cr with: Character lf).\\n\\tLookAheadCount := 2048.\\n\\tSmalltalk addToStartUpList: self.\\n\\tself startUp.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\nstartUp\\n\\n\\tself guessDefaultLineEndConvention.\\n! !\\n\\n\\n!MultiByteFileStream class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 11:43'!\\nnewFrom: aFileStream\\n\\n\\t| rw n |\\n\\tn _ aFileStream name.\\n\\trw _ aFileStream isReadOnly not.\\n\\taFileStream close.\\n\\t^self new open: n forWrite: rw.\\n! !\\nPluggableCanvas subclass: #MultiCanvas\\n\\tinstanceVariableNames: 'canvases extent depth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n!MultiCanvas commentStamp: '<historical>' prior: 0!\\nA canvas which forwards drawing commands to sub-canvases.!\\n\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 20:48'!\\naddCanvas: aCanvas\\n\\tcanvases add: aCanvas! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'RAA 11/7/2000 17:46'!\\nclipRect\\n\\t\\n\\t^super clipRect ifNil: [\\n\\t\\t0@0 extent: 5000@5000\\n\\t].! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'RAA 8/14/2000 10:27'!\\ncontentsOfArea: aRectangle into: aForm\\n\\n\\tself apply: [ :c |\\n\\t\\t(c isKindOf: FormCanvas) ifTrue: [\\n\\t\\t\\tc contentsOfArea: aRectangle into: aForm.\\n\\t\\t\\t^aForm\\n\\t\\t].\\n\\t].\\n\\tself apply: [ :c |\\n\\t\\tc contentsOfArea: aRectangle into: aForm.\\n\\t\\t^aForm.\\n\\t].\\n\\t^aForm! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 4/8/2000 22:35'!\\ndepth\\n\\t^depth! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 4/8/2000 22:35'!\\nextent\\n\\t^extent! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 20:48'!\\nremoveCanvas: aCanvas\\n\\tcanvases remove: aCanvas ifAbsent: []! !\\n\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'RAA 8/1/2000 13:50'!\\nallocateForm: extentPoint\\n\\t\\\"Allocate a new form which is similar to the receiver and can be used for accelerated blts\\\"\\n\\t^Form extent: extentPoint depth: self depth! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:35'!\\ndepth: newDepth\\n\\t\\\"set the extent to be used with this canvas\\\"\\n\\tdepth := newDepth.! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:34'!\\nextent: newExtent\\n\\t\\\"set the extent to be used with this canvas\\\"\\n\\textent := newExtent.! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:34'!\\ninitialize\\n\\tcanvases := Set new.\\n\\textent := 600@400.\\n\\tdepth := 32. ! !\\n\\n\\n!MultiCanvas methodsFor: 'private' stamp: 'RAA 11/6/2000 14:17'!\\napply: aCommand\\n\\n\\tself flag: #roundedRudeness.\\t\\n\\t\\\"This rudeness is to help get rounded corners to work right on RemoteCanvases. Since the RemoteCanvas has no other way to read its bits, we are grabbing them from Display for now. To support this, we need to see that the Display is written before any RemoteCanvases\\\"\\n\\n\\tcanvases do: [ :canvas | \\n\\t\\t(canvas isKindOf: FormCanvas) ifTrue: [aCommand value: canvas]\\n\\t].\\n\\tcanvases do: [ :canvas | \\n\\t\\t(canvas isKindOf: FormCanvas) ifFalse: [aCommand value: canvas]\\n\\t].\\n! !\\nMultiCharacterScanner subclass: #MultiCanvasCharacterScanner\\n\\tinstanceVariableNames: 'canvas fillBlt foregroundColor runX lineY'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCanvasCharacterScanner methodsFor: 'accessing' stamp: 'yo 12/18/2002 13:55'!\\ncanvas: aCanvas\\n\\t\\\"set the canvas to draw on\\\"\\n\\tcanvas ifNotNil: [ self inform: 'initializing twice!!' ].\\n\\tcanvas _ aCanvas! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:55'!\\ndisplayLine: textLine offset: offset leftInRun: leftInRun\\n\\t| nowLeftInRun done startLoc startIndex stopCondition |\\n\\t\\\"largely copied from DisplayScanner's routine\\\"\\n\\n\\tline _ textLine.\\n\\tforegroundColor ifNil: [ foregroundColor _ Color black ].\\n\\tleftMargin _ (line leftMarginForAlignment: alignment) + offset x.\\n\\n\\trightMargin _ line rightMargin + offset x.\\n\\tlineY _ line top + offset y.\\n\\tlastIndex _ textLine first.\\n\\tleftInRun <= 0\\n\\t\\tifTrue: [self setStopConditions. \\\"also sets the font\\\"\\n\\t\\t\\t\\tnowLeftInRun _ text runLengthFor: lastIndex]\\n\\t\\tifFalse: [nowLeftInRun _ leftInRun].\\n\\trunX _ destX _ leftMargin.\\n\\n\\trunStopIndex _ lastIndex + (nowLeftInRun - 1) min: line last.\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\n\\t[done] whileFalse: [\\n\\t\\t\\\"remember where this portion of the line starts\\\"\\n\\t\\tstartLoc _ destX@destY.\\n\\t\\tstartIndex _ lastIndex.\\n\\n\\t\\t\\\"find the end of this portion of the line\\\"\\n\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\tkern: kern \\\"displaying: false\\\".\\n\\n\\t\\t\\\"display that portion of the line\\\"\\n\\t\\tcanvas drawString: text string\\n\\t\\t\\tfrom: startIndex to: lastIndex\\n\\t\\t\\tat: startLoc\\n\\t\\t\\tfont: font\\n\\t\\t\\tcolor: foregroundColor.\\n\\n\\t\\t\\\"handle the stop condition\\\"\\n\\t\\tdone _ self perform: stopCondition\\n\\t].\\n\\n\\t^runStopIndex - lastIndex! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ncr\\n\\t\\\"When a carriage return is encountered, simply increment the pointer \\n\\tinto the paragraph.\\\"\\n\\n\\tlastIndex_ lastIndex + 1.\\n\\t^false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ncrossedX\\n\\t\\\"This condition will sometimes be reached 'legally' during display, when, \\n\\tfor instance the space that caused the line to wrap actually extends over \\n\\tthe right boundary. This character is allowed to display, even though it \\n\\tis technically outside or straddling the clipping ectangle since it is in \\n\\tthe normal case not visible and is in any case appropriately clipped by \\n\\tthe scanner.\\\"\\n\\n\\t\\\"self fillLeading.\\\"\\n\\t^ true ! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\nendOfRun\\n\\t\\\"The end of a run in the display case either means that there is actually \\n\\ta change in the style (run code) to be associated with the string or the \\n\\tend of this line has been reached.\\\"\\n\\t| runLength |\\n\\n\\tlastIndex = line last ifTrue: [^true].\\n\\trunX _ destX.\\n\\trunLength _ text runLengthFor: (lastIndex _ lastIndex + 1).\\n\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\tself setStopConditions.\\n\\t^ false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\npaddedSpace\\n\\t\\\"Each space is a stop condition when the alignment is right justified. \\n\\tPadding must be added to the base width of the space according to \\n\\twhich space in the line this space is and according to the amount of \\n\\tspace that remained at the end of the line when it was composed.\\\"\\n\\n\\tdestX _ destX + spaceWidth + (line justifiedPadFor: spaceCount).\\n\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (textStyle alignment = Justified ifTrue: [#paddedSpace]).\\n! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ntab\\n\\n\\tdestX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"imbedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse: \\n\\t\\t\\t[textStyle nextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin].\\n\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:55'!\\ndoesDisplaying\\n\\t^false \\\"it doesn't do displaying using copyBits\\\"! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 1/6/2005 23:00'!\\nsetFont\\n\\tforegroundColor ifNil: [foregroundColor _ Color black].\\n\\tsuper setFont.\\n\\tbaselineY _ lineY + line baseline.\\n\\tdestY _ baselineY - font ascent.! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:55'!\\ntextColor: color\\n\\tforegroundColor _ color! !\\nMultiCharacterScanner subclass: #MultiCharacterBlockScanner\\n\\tinstanceVariableNames: 'characterPoint characterIndex lastCharacter lastCharacterExtent lastSpaceOrTabExtent nextLeftMargin specialWidth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\ncharacterBlockAtPoint: aPoint in: aParagraph\\n\\t\\\"Answer a CharacterBlock for character in aParagraph at point aPoint. It \\n\\tis assumed that aPoint has been transformed into coordinates appropriate \\n\\tto the text's destination form rectangle and the composition rectangle.\\\"\\n\\n\\tself initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle.\\n\\tcharacterPoint _ aPoint.\\n\\t^self buildCharacterBlockIn: aParagraph! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'nk 11/22/2004 14:36'!\\ncharacterBlockAtPoint: aPoint index: index in: textLine\\n\\t\\\"This method is the Morphic characterBlock finder. It combines\\n\\tMVC's characterBlockAtPoint:, -ForIndex:, and buildCharcterBlock:in:\\\"\\n\\t| runLength lineStop done stopCondition |\\n\\tline := textLine.\\n\\trightMargin := line rightMargin.\\n\\tlastIndex := line first.\\n\\tself setStopConditions.\\t\\t\\\"also sets font\\\"\\n\\tcharacterIndex := index. \\\" == nil means scanning for point\\\"\\n\\tcharacterPoint := aPoint.\\n\\t(characterPoint isNil or: [characterPoint y > line bottom])\\n\\t\\tifTrue: [characterPoint := line bottomRight].\\n\\t(text isEmpty or: [(characterPoint y < line top or: [characterPoint x < line left])\\n\\t\\t\\t\\tor: [characterIndex notNil and: [characterIndex < line first]]])\\n\\t\\tifTrue:\\t[^ (CharacterBlock new stringIndex: line first text: text\\n\\t\\t\\t\\t\\ttopLeft: line leftMargin@line top extent: 0 @ textStyle lineGrid)\\n\\t\\t\\t\\t\\ttextLine: line].\\n\\tdestX := leftMargin := line leftMarginForAlignment: alignment.\\n\\tdestY := line top.\\n\\trunLength := text runLengthFor: line first.\\n\\tcharacterIndex\\n\\t\\tifNotNil:\\t[lineStop := characterIndex \\\"scanning for index\\\"]\\n\\t\\tifNil:\\t[lineStop := line last \\\"scanning for point\\\"].\\n\\trunStopIndex := lastIndex + (runLength - 1) min: lineStop.\\n\\tlastCharacterExtent := 0 @ line lineHeight.\\n\\tspaceCount := 0.\\n\\n\\tdone := false.\\n\\t[done] whileFalse:\\n\\t\\t[stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\tin: text string rightX: characterPoint x\\n\\t\\t\\tstopConditions: stopConditions kern: kern.\\n\\t\\t\\\"see setStopConditions for stopping conditions for character block \\toperations.\\\"\\n\\t\\tself lastCharacterExtentSetX: (specialWidth\\n\\t\\t\\tifNil: [font widthOf: (text at: lastIndex)]\\n\\t\\t\\tifNotNil: [specialWidth]).\\n\\t\\t(self perform: stopCondition) ifTrue:\\n\\t\\t\\t[characterIndex\\n\\t\\t\\t\\tifNil: [\\n\\t\\t\\t\\t\\t\\\"Result for characterBlockAtPoint: \\\"\\n\\t\\t\\t\\t\\t(stopCondition ~~ #cr and: [ lastIndex == line last\\n\\t\\t\\t\\t\\t\\tand: [ aPoint x > ((characterPoint x) + (lastCharacterExtent x / 2)) ]])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [ \\\"Correct for right half of last character in line\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: lastIndex + 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttext: text\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + (lastCharacterExtent x @ 0) + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\textent: 0 @ lastCharacterExtent y)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line ].\\n\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: lastIndex\\n\\t\\t\\t\\t\\t\\t\\ttext: text topLeft: characterPoint + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\t\\textent: lastCharacterExtent - (font baseKern @ 0))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line]\\n\\t\\t\\t\\tifNotNil: [\\\"Result for characterBlockForIndex: \\\"\\n\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: characterIndex\\n\\t\\t\\t\\t\\t\\t\\ttext: text topLeft: characterPoint + ((font descentKern) - kern @ 0)\\n\\t\\t\\t\\t\\t\\t\\textent: lastCharacterExtent)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line]]]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\ncharacterBlockForIndex: targetIndex in: aParagraph \\n\\t\\\"Answer a CharacterBlock for character in aParagraph at targetIndex. The \\n\\tcoordinates in the CharacterBlock will be appropriate to the intersection \\n\\tof the destination form rectangle and the composition rectangle.\\\"\\n\\n\\tself \\n\\t\\tinitializeFromParagraph: aParagraph \\n\\t\\tclippedBy: aParagraph clippingRectangle.\\n\\tcharacterIndex _ targetIndex.\\n\\tcharacterPoint _ \\n\\t\\taParagraph rightMarginForDisplay @ \\n\\t\\t\\t(aParagraph topAtLineIndex: \\n\\t\\t\\t\\t(aParagraph lineIndexOfCharacterIndex: characterIndex)).\\n\\t^self buildCharacterBlockIn: aParagraph! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\nindentationLevel: anInteger\\n\\tsuper indentationLevel: anInteger.\\n\\tnextLeftMargin _ leftMargin.\\n\\tindentationLevel timesRepeat: [\\n\\t\\tnextLeftMargin _ textStyle nextTabXFrom: nextLeftMargin\\n\\t\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\t\\trightMargin: rightMargin]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].\\n\\tspecialWidth _ anchoredMorph width.\\n\\t^ true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 8/6/2003 05:55'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| encoding f nextDestX maxAscii startEncoding char charValue |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tchar _ (sourceString at: lastIndex).\\n\\t\\tcharValue _ char charCode.\\n\\t\\tcharValue > maxAscii ifTrue: [charValue _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: charValue + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t^ stops at: charValue + 1\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (self widthOf: char inFont: font).\\n\\t\\tnextDestX > rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 1/6/2005 22:55'!\\ncr \\n\\t\\\"Answer a CharacterBlock that specifies the current location of the mouse \\n\\trelative to a carriage return stop condition that has just been \\n\\tencountered. The ParagraphEditor convention is to denote selections by \\n\\tCharacterBlocks, sometimes including the carriage return (cursor is at \\n\\tthe end) and sometimes not (cursor is in the middle of the text).\\\"\\n\\n\\t((characterIndex ~= nil\\n\\t\\tand: [characterIndex > text size])\\n\\t\\t\\tor: [(line last = text size)\\n\\t\\t\\t\\tand: [(destY + line lineHeight) < characterPoint y]])\\n\\t\\tifTrue:\\t[\\\"When off end of string, give data for next character\\\"\\n\\t\\t\\t\\tdestY _ destY + line lineHeight.\\n\\t\\t\\t\\tbaselineY _ line lineHeight.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tcharacterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ destY.\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^ true].\\n\\t\\tlastCharacter _ CR.\\n\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\tself lastCharacterExtentSetX: rightMargin - destX.\\n\\t\\t^true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\ncrossedX\\n\\t\\\"Text display has wrapping. The scanner just found a character past the x \\n\\tlocation of the cursor. We know that the cursor is pointing at a character \\n\\tor before one.\\\"\\n\\n\\t| leadingTab currentX |\\n\\tcharacterIndex == nil ifFalse: [\\n\\t\\t\\\"If the last character of the last line is a space,\\n\\t\\tand it crosses the right margin, then locating\\n\\t\\tthe character block after it is impossible without this hack.\\\"\\n\\t\\tcharacterIndex > text size ifTrue: [\\n\\t\\t\\tlastIndex _ characterIndex.\\n\\t\\t\\tcharacterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ (destY + line lineHeight).\\n\\t\\t\\t^true]].\\n\\tcharacterPoint x <= (destX + (lastCharacterExtent x // 2))\\n\\t\\tifTrue:\\t[lastCharacter _ (text at: lastIndex).\\n\\t\\t\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\t\\t\\t^true].\\n\\tlastIndex >= line last \\n\\t\\tifTrue:\\t[lastCharacter _ (text at: line last).\\n\\t\\t\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\t\\t\\t^true].\\n\\n\\t\\\"Pointing past middle of a character, return the next character.\\\"\\n\\tlastIndex _ lastIndex + 1.\\n\\tlastCharacter _ text at: lastIndex.\\n\\tcurrentX _ destX + lastCharacterExtent x + kern.\\n\\tself lastCharacterExtentSetX: (font widthOf: lastCharacter).\\n\\tcharacterPoint _ currentX @ destY.\\n\\tlastCharacter = Space ifFalse: [^ true].\\n\\n\\t\\\"Yukky if next character is space or tab.\\\"\\n\\talignment = Justified ifTrue:\\n\\t\\t[self lastCharacterExtentSetX:\\n\\t\\t\\t(lastCharacterExtent x + \\t(line justifiedPadFor: (spaceCount + 1))).\\n\\t\\t^ true].\\n\\n\\ttrue ifTrue: [^ true].\\n\\t\\\"NOTE: I find no value to the following code, and so have defeated it - DI\\\"\\n\\n\\t\\\"See tabForDisplay for illumination on the following awfulness.\\\"\\n\\tleadingTab _ true.\\n\\tline first to: lastIndex - 1 do:\\n\\t\\t[:index | (text at: index) ~= Tab ifTrue: [leadingTab _ false]].\\n\\t(alignment ~= Justified or: [leadingTab])\\n\\t\\tifTrue:\\t[self lastCharacterExtentSetX: (textStyle nextTabXFrom: currentX\\n\\t\\t\\t\\t\\tleftMargin: leftMargin rightMargin: rightMargin) -\\n\\t\\t\\t\\t\\t\\tcurrentX]\\n\\t\\tifFalse:\\t[self lastCharacterExtentSetX: (((currentX + (textStyle tabWidth -\\n\\t\\t\\t\\t\\t\\t(line justifiedTabDeltaFor: spaceCount))) -\\n\\t\\t\\t\\t\\t\\t\\tcurrentX) max: 0)].\\n\\t^ true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\nendOfRun\\n\\t\\\"Before arriving at the cursor location, the selection has encountered an \\n\\tend of run. Answer false if the selection continues, true otherwise. Set \\n\\tup indexes for building the appropriate CharacterBlock.\\\"\\n\\n\\t| runLength lineStop |\\n\\t(((characterIndex ~~ nil and:\\n\\t\\t[runStopIndex < characterIndex and: [runStopIndex < text size]])\\n\\t\\t\\tor:\\t[characterIndex == nil and: [lastIndex < line last]]) or: [\\n\\t\\t\\t\\t((lastIndex < line last)\\n\\t\\t\\t\\tand: [((text at: lastIndex) leadingChar ~= (text at: lastIndex+1) leadingChar)\\n\\t\\t\\t\\t\\tand: [lastIndex ~= characterIndex]])])\\n\\t\\tifTrue:\\t[\\\"We're really at the end of a real run.\\\"\\n\\t\\t\\t\\trunLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).\\n\\t\\t\\t\\tcharacterIndex ~~ nil\\n\\t\\t\\t\\t\\tifTrue:\\t[lineStop _ characterIndex\\t\\\"scanning for index\\\"]\\n\\t\\t\\t\\t\\tifFalse:\\t[lineStop _ line last\\t\\t\\t\\\"scanning for point\\\"].\\n\\t\\t\\t\\t(runStopIndex _ lastIndex + (runLength - 1)) > lineStop\\n\\t\\t\\t\\t\\tifTrue: \\t[runStopIndex _ lineStop].\\n\\t\\t\\t\\tself setStopConditions.\\n\\t\\t\\t\\t^false].\\n\\n\\tlastCharacter _ text at: lastIndex.\\n\\tcharacterPoint _ destX @ destY.\\n\\t((lastCharacter = Space and: [alignment = Justified])\\n\\t\\tor: [lastCharacter = Tab and: [lastSpaceOrTabExtent notNil]])\\n\\t\\tifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent].\\n\\tcharacterIndex ~~ nil\\n\\t\\tifTrue:\\t[\\\"If scanning for an index and we've stopped on that index,\\n\\t\\t\\t\\tthen we back destX off by the width of the character stopped on\\n\\t\\t\\t\\t(it will be pointing at the right side of the character) and return\\\"\\n\\t\\t\\t\\trunStopIndex = characterIndex\\n\\t\\t\\t\\t\\tifTrue:\\t[self characterPointSetX: destX - lastCharacterExtent x.\\n\\t\\t\\t\\t\\t\\t\\t^true].\\n\\t\\t\\t\\t\\\"Otherwise the requested index was greater than the length of the\\n\\t\\t\\t\\tstring. Return string size + 1 as index, indicate further that off the\\n\\t\\t\\t\\tstring by setting character to nil and the extent to 0.\\\"\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^true].\\n\\n\\t\\\"Scanning for a point and either off the end of the line or off the end of the string.\\\"\\n\\trunStopIndex = text size\\n\\t\\tifTrue:\\t[\\\"off end of string\\\"\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^true].\\n\\t\\\"just off end of line without crossing x\\\"\\n\\tlastIndex _ lastIndex + 1.\\n\\t^true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\npaddedSpace\\n\\t\\\"When the line is justified, the spaces will not be the same as the font's \\n\\tspace character. A padding of extra space must be considered in trying \\n\\tto find which character the cursor is pointing at. Answer whether the \\n\\tscanning has crossed the cursor.\\\"\\n\\n\\t| pad |\\n\\tpad _ 0.\\n\\tspaceCount _ spaceCount + 1.\\n\\tpad _ line justifiedPadFor: spaceCount.\\n\\tlastSpaceOrTabExtent _ lastCharacterExtent copy.\\n\\tself lastSpaceOrTabExtentSetX: spaceWidth + pad.\\n\\t(destX + lastSpaceOrTabExtent x) >= characterPoint x\\n\\t\\tifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy.\\n\\t\\t\\t\\t^self crossedX].\\n\\tlastIndex _ lastIndex + 1.\\n\\tdestX _ destX + lastSpaceOrTabExtent x.\\n\\t^ false\\n! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\nsetFont\\n\\tspecialWidth _ nil.\\n\\tsuper setFont! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 10/18/2004 14:31'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (alignment = Justified ifTrue: [#paddedSpace]).\\n! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\ntab\\n\\t| currentX |\\n\\tcurrentX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"imbedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse:\\n\\t\\t\\t[textStyle\\n\\t\\t\\t\\tnextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin].\\n\\tlastSpaceOrTabExtent _ lastCharacterExtent copy.\\n\\tself lastSpaceOrTabExtentSetX: (currentX - destX max: 0).\\n\\tcurrentX >= characterPoint x\\n\\t\\tifTrue: \\n\\t\\t\\t[lastCharacterExtent _ lastSpaceOrTabExtent copy.\\n\\t\\t\\t^ self crossedX].\\n\\tdestX _ currentX.\\n\\tlastIndex _ lastIndex + 1.\\n\\t^false! !\\n\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nbuildCharacterBlockIn: para\\n\\t| lineIndex runLength lineStop done stopCondition |\\n\\t\\\"handle nullText\\\"\\n\\t(para numberOfLines = 0 or: [text size = 0])\\n\\t\\tifTrue:\\t[^ CharacterBlock new stringIndex: 1 \\\"like being off end of string\\\"\\n\\t\\t\\t\\t\\ttext: para text\\n\\t\\t\\t\\t\\ttopLeft: (para leftMarginForDisplayForLine: 1 alignment: (alignment ifNil:[textStyle alignment]))\\n\\t\\t\\t\\t\\t\\t\\t\\t@ para compositionRectangle top\\n\\t\\t\\t\\t\\textent: 0 @ textStyle lineGrid].\\n\\t\\\"find the line\\\"\\n\\tlineIndex _ para lineIndexOfTop: characterPoint y.\\n\\tdestY _ para topAtLineIndex: lineIndex.\\n\\tline _ para lines at: lineIndex.\\n\\trightMargin _ para rightMarginForDisplay.\\n\\n\\t(lineIndex = para numberOfLines and:\\n\\t\\t[(destY + line lineHeight) < characterPoint y])\\n\\t\\t\\tifTrue:\\t[\\\"if beyond lastLine, force search to last character\\\"\\n\\t\\t\\t\\t\\tself characterPointSetX: rightMargin]\\n\\t\\t\\tifFalse:\\t[characterPoint y < (para compositionRectangle) top\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"force search to first line\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tcharacterPoint _ (para compositionRectangle) topLeft].\\n\\t\\t\\t\\t\\tcharacterPoint x > rightMargin\\n\\t\\t\\t\\t\\t\\tifTrue:\\t[self characterPointSetX: rightMargin]].\\n\\tdestX _ (leftMargin _ para leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment])).\\n\\tnextLeftMargin_ para leftMarginForDisplayForLine: lineIndex+1 alignment: (alignment ifNil:[textStyle alignment]).\\n\\tlastIndex _ line first.\\n\\n\\tself setStopConditions.\\t\\t\\\"also sets font\\\"\\n\\trunLength _ (text runLengthFor: line first).\\n\\tcharacterIndex == nil\\n\\t\\tifTrue:\\t[lineStop _ line last \\\"characterBlockAtPoint\\\"]\\n\\t\\tifFalse:\\t[lineStop _ characterIndex \\\"characterBlockForIndex\\\"].\\n\\t(runStopIndex _ lastIndex + (runLength - 1)) > lineStop\\n\\t\\tifTrue:\\t[runStopIndex _ lineStop].\\n\\tlastCharacterExtent _ 0 @ line lineHeight.\\n\\tspaceCount _ 0. done _ false.\\n\\tself handleIndentation.\\n\\n\\t[done]\\n\\twhileFalse:\\n\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\tin: text string rightX: characterPoint x\\n\\t\\t\\tstopConditions: stopConditions kern: kern.\\n\\n\\t\\\"see setStopConditions for stopping conditions for character block \\toperations.\\\"\\n\\tself lastCharacterExtentSetX: (font widthOf: (text at: lastIndex)).\\n\\t(self perform: stopCondition) ifTrue:\\n\\t\\t[characterIndex == nil\\n\\t\\t\\tifTrue: [\\\"characterBlockAtPoint\\\"\\n\\t\\t\\t\\t\\t^ CharacterBlock new stringIndex: lastIndex text: text\\n\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\textent: lastCharacterExtent]\\n\\t\\t\\tifFalse: [\\\"characterBlockForIndex\\\"\\n\\t\\t\\t\\t\\t^ CharacterBlock new stringIndex: lastIndex text: text\\n\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + ((font descentKern) - kern @ 0)\\n\\t\\t\\t\\t\\t\\textent: lastCharacterExtent]]]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\ncharacterPointSetX: xVal\\n\\tcharacterPoint _ xVal @ characterPoint y! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nlastCharacterExtentSetX: xVal\\n\\tlastCharacterExtent _ xVal @ lastCharacterExtent y! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nlastSpaceOrTabExtentSetX: xVal\\n\\tlastSpaceOrTabExtent _ xVal @ lastSpaceOrTabExtent y! !\\nObject subclass: #MultiCharacterScanner\\n\\tinstanceVariableNames: 'destX lastIndex xTable destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks presentation presentationLine numOfComposition baselineY firstDestX'\\n\\tclassVariableNames: 'DefaultStopConditions NilCondition PaddedSpaceCondition SpaceCondition'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\ninitialize\\n\\tdestX _ destY _ leftMargin _ 0.! !\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\ninitializeStringMeasurer\\n\\tstopConditions _ Array new: 258.\\n\\tstopConditions at: CrossedX put: #crossedX.\\n\\tstopConditions at: EndOfRun put: #endOfRun.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\nwantsColumnBreaks: aBoolean\\n\\n\\twantsColumnBreaks _ aBoolean! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/3/2003 12:09'!\\naddCharToPresentation: char\\n\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 16:15'!\\nregisterBreakableIndex\\n\\n\\t\\\"Record left x and character index of the line-wrappable point. \\n\\tThe default implementation here does nothing.\\\"\\n\\n\\t^ false.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/23/2003 14:25'!\\nremoveLastCharFromPresentation\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/1/2003 10:43'!\\nwidthOf: char inFont: aFont\\n\\n\\t(char isMemberOf: CombinedChar) ifTrue: [\\n\\t\\t^ aFont widthOf: char base.\\n\\t] ifFalse: [\\n\\t\\t^ aFont widthOf: char.\\n\\t].\\n\\n\\n! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/18/2002 13:53'!\\nbasicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\t\\\"Primitive. This is the inner loop of text display--but see \\n\\tscanCharactersFrom: to:rightX: which would get the string, \\n\\tstopConditions and displaying from the instance. March through source \\n\\tString from startIndex to stopIndex. If any character is flagged with a \\n\\tnon-nil entry in stops, then return the corresponding value. Determine \\n\\twidth of each character from xTable, indexed by map. \\n\\tIf dextX would exceed rightX, then return stops at: 258. \\n\\tAdvance destX by the width of the character. If stopIndex has been\\n\\treached, then return stops at: 257. Optional. \\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\t| ascii nextDestX char |\\n\\t<primitive: 103>\\n\\tlastIndex _ startIndex.\\n\\t[lastIndex <= stopIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[char _ (sourceString at: lastIndex).\\n\\t\\t\\tascii _ char asciiValue + 1.\\n\\t\\t\\t(stops at: ascii) == nil ifFalse: [^stops at: ascii].\\n\\t\\t\\t\\\"Note: The following is querying the font about the width\\n\\t\\t\\tsince the primitive may have failed due to a non-trivial\\n\\t\\t\\tmapping of characters to glyphs or a non-existing xTable.\\\"\\n\\t\\t\\tnextDestX _ destX + (font widthOf: char).\\n\\t\\t\\tnextDestX > rightX ifTrue: [^stops at: CrossedX].\\n\\t\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\t\\tlastIndex _ lastIndex + 1].\\n\\tlastIndex _ stopIndex.\\n\\t^stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/30/2002 22:59'!\\ncombinableChar: char for: prevEntity\\n\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/20/2002 11:46'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ encodingClass isBreakableAt: index in: sourceString.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:03'!\\nscanJapaneseCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\t\\\"xTable _ f xTable.\\n\\t\\tmaxAscii _ xTable size - 2.\\\"\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\t(font isMemberOf: HostFont) ifTrue: [\\n\\t\\t\\tf _ font.\\n\\t\\t\\tmaxAscii _ f maxAscii.\\n\\t\\t\\tspaceWidth _ f widthOf: Space.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tmaxAscii _ font maxAscii.\\n\\t\\t].\\n\\t].\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\t\\\"self halt.\\\"\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: ascii + 1) ~~ nil]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: (EncodedCharSet charsetAt: encoding)) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX > rightX ifTrue: [firstDestX ~= destX ifTrue: [^ stops at: CrossedX]].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:09'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| charCode encoding f maxAscii startEncoding combining combined combiningIndex c |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ font widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t\\tspaceWidth _ font widthOf: Space.\\n\\t].\\n\\n\\tcombining _ nil.\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tcharCode _ (sourceString at: lastIndex) charCode.\\n\\t\\tc _ (sourceString at: lastIndex).\\n\\t\\tcombining ifNil: [\\n\\t\\t\\tcombining _ CombinedChar new.\\n\\t\\t\\tcombining add: c.\\n\\t\\t\\tcombiningIndex _ lastIndex.\\n\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t] ifNotNil: [\\n\\t\\t\\t(combining add: c) ifFalse: [\\n\\t\\t\\t\\tself addCharToPresentation: (combined _ combining combined).\\n\\t\\t\\t\\tcombining _ CombinedChar new.\\n\\t\\t\\t\\tcombining add: c.\\n\\t\\t\\t\\tcharCode _ combined charCode.\\n\\t\\t\\t\\tencoding _ combined leadingChar.\\n\\t\\t\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1.\\n\\t\\t\\t\\t\\t(encoding = 0 and: [(stopConditions at: charCode + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t\\t\\t\\t^ stops at: charCode + 1\\n\\t\\t\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t\\t\\t ^ stops at: EndOfRun\\n\\t\\t\\t\\t\\t].\\n\\t\\t\\t\\t].\\n\\t\\t\\t\\tcharCode > maxAscii ifTrue: [charCode _ maxAscii].\\n\\t\\t\\t\\t\\\"\\\"\\n\\t\\t\\t\\t(encoding = 0 and: [(stopConditions at: charCode + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t\\t\\tcombining ifNotNil: [\\n\\t\\t\\t\\t\\t\\tself addCharToPresentation: (combining combined).\\n\\t\\t\\t\\t\\t].\\n\\t\\t\\t\\t\\t^ stops at: charCode + 1\\n\\t\\t\\t\\t].\\n\\t\\t\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\t\\t\\tself registerBreakableIndex.\\n\\t\\t\\t\\t].\\t\\t\\n\\t\\t\\t\\tdestX > rightX ifTrue: [\\n\\t\\t\\t\\t\\tdestX ~= firstDestX ifTrue: [\\n\\t\\t\\t\\t\\t\\tlastIndex _ combiningIndex.\\n\\t\\t\\t\\t\\t\\tself removeLastCharFromPresentation.\\n\\t\\t\\t\\t\\t\\t^ stops at: CrossedX]].\\n\\t\\t\\t\\tcombiningIndex _ lastIndex.\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t] ifTrue: [\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tnumOfComposition _ numOfComposition + 1.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\tcombining ifNotNil: [\\n\\t\\tcombined _ combining combined.\\n\\t\\tself addCharToPresentation: combined.\\n\\t\\t\\\"assuming that there is always enough space for at least one character\\\".\\n\\t\\tdestX _ destX + (self widthOf: combined inFont: font).\\n\\t].\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:08'!\\nscanMultiCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [ascii < stopConditions size and: [(stopConditions at: ascii + 1) ~~ nil]]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX > rightX ifTrue: [destX ~= firstDestX ifTrue: [^ stops at: CrossedX]].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:08'!\\nscanMultiCharactersR2LFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t\\\"Note that 'rightX' really means 'endX' in R2L context. Ie. rightX is usually smaller than destX.\\\"\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: ascii + 1) ~~ nil]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX - (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX < rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX - kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\ncolumnBreak\\n\\n\\t^true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nembeddedObject\\n\\t| savedIndex |\\n\\tsavedIndex _ lastIndex.\\n\\ttext attributesAt: lastIndex do:[:attr| \\n\\t\\tattr anchoredMorph ifNotNil:[\\n\\t\\t\\t\\\"Following may look strange but logic gets reversed.\\n\\t\\t\\tIf the morph fits on this line we're not done (return false for true) \\n\\t\\t\\tand if the morph won't fit we're done (return true for false)\\\"\\n\\t\\t\\t(self placeEmbeddedObject: attr anchoredMorph) ifFalse:[^true]]].\\n\\tlastIndex _ savedIndex + 1. \\\"for multiple(!!) embedded morphs\\\"\\n\\t^false! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nhandleIndentation\\n\\tself indentationLevel timesRepeat: [\\n\\t\\tself plainTab]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nindentationLevel\\n\\t\\\"return the number of tabs that are currently being placed at the beginning of each line\\\"\\n\\t^indentationLevel ifNil:[0]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nindentationLevel: anInteger\\n\\t\\\"set the number of tabs to put at the beginning of each line\\\"\\n\\tindentationLevel _ anInteger! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nleadingTab\\n\\t\\\"return true if only tabs lie to the left\\\"\\n\\tline first to: lastIndex do:\\n\\t\\t[:i | (text at: i) == Tab ifFalse: [^ false]].\\n\\t^ true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 1/18/2005 08:08'!\\nmeasureString: aString inFont: aFont from: startIndex to: stopIndex\\n\\t\\\"WARNING: In order to use this method the receiver has to be set up using #initializeStringMeasurer\\\"\\n\\tdestX _ destY _ lastIndex _ 0.\\n\\tbaselineY _ aFont ascent.\\n\\txTable _ aFont xTable.\\n\\tfont := aFont. \\\" added Dec 03, 2004 \\\"\\n\\\"\\tmap _ aFont characterToGlyphMap.\\\"\\n\\tself scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999 stopConditions: stopConditions kern: 0.\\n\\t^destX! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t\\\"Place the anchoredMorph or return false if it cannot be placed.\\n\\tIn any event, advance destX by its width.\\\"\\n\\t| w |\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\tdestX _ destX + (w _ anchoredMorph width).\\n\\t(destX > rightMargin and: [(leftMargin + w) <= rightMargin])\\n\\t\\tifTrue: [\\\"Won't fit, but would on next line\\\"\\n\\t\\t\\t\\t^ false].\\n\\tlastIndex _ lastIndex + 1.\\n\\tself setFont. \\\"Force recalculation of emphasis for next run\\\"\\n\\t^ true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nplainTab\\n\\t\\\"This is the basic method of adjusting destX for a tab.\\\"\\n\\tdestX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"embedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse: \\n\\t\\t\\t[textStyle nextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 19:53'!\\nscanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| startEncoding selector |\\n\\t(sourceString isByteString) ifTrue: [^ self basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta.].\\n\\n\\t(sourceString isWideString) ifTrue: [\\n\\t\\tstartIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\t\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\t\\tselector _ (EncodedCharSet charsetAt: startEncoding) scanSelector.\\n\\t\\t^ self perform: selector withArguments: (Array with: startIndex with: stopIndex with: sourceString with: rightX with: stopConditions with: kernDelta).\\n\\t].\\n\\t\\n\\t^ stops at: EndOfRun\\n! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\naddEmphasis: code\\n\\t\\\"Set the bold-ital-under-strike emphasis.\\\"\\n\\temphasisCode _ emphasisCode bitOr: code! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\naddKern: kernDelta\\n\\t\\\"Set the current kern amount.\\\"\\n\\tkern _ kern + kernDelta! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ninitializeFromParagraph: aParagraph clippedBy: clippingRectangle\\n\\n\\ttext _ aParagraph text.\\n\\ttextStyle _ aParagraph textStyle. \\n! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetActualFont: aFont\\n\\t\\\"Set the basal font to an isolated font reference.\\\"\\n\\n\\tfont _ aFont! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetAlignment: style\\n\\talignment _ style.\\n\\t! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/19/2002 02:05'!\\nsetConditionArray: aSymbol\\n\\n\\taSymbol == #paddedSpace ifTrue: [^stopConditions _ PaddedSpaceCondition \\\"copy\\\"].\\n\\t\\\"aSymbol == #space ifTrue: [^stopConditions _ SpaceCondition copy].\\\"\\n\\taSymbol == nil ifTrue: [^stopConditions _ NilCondition \\\"copy\\\"].\\n\\tself error: 'undefined stopcondition for space character'.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'tak 12/19/2004 15:45'!\\nsetFont\\n\\t| priorFont |\\n\\t\\\"Set the font and other emphasis.\\\"\\n\\tpriorFont _ font.\\n\\ttext == nil ifFalse:[\\n\\t\\temphasisCode _ 0.\\n\\t\\tkern _ 0.\\n\\t\\tindentationLevel _ 0.\\n\\t\\talignment _ textStyle alignment.\\n\\t\\tfont _ nil.\\n\\t\\t(text attributesAt: lastIndex forStyle: textStyle)\\n\\t\\t\\tdo: [:att | att emphasizeScanner: self]].\\n\\tfont == nil ifTrue:\\n\\t\\t[self setFont: textStyle defaultFontIndex].\\n\\tfont _ font emphasized: emphasisCode.\\n\\tpriorFont ifNotNil: [destX _ destX + priorFont descentKern].\\n\\tdestX _ destX - font descentKern.\\n\\t\\\"NOTE: next statement should be removed when clipping works\\\"\\n\\tleftMargin ifNotNil: [destX _ destX max: leftMargin].\\n\\tkern _ kern - font baseKern.\\n\\n\\t\\\"Install various parameters from the font.\\\"\\n\\tspaceWidth _ font widthOf: Space.\\n\\txTable _ font xTable.\\n\\\"\\tmap _ font characterToGlyphMap.\\\"\\n\\tstopConditions _ DefaultStopConditions.! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetFont: fontNumber\\n\\t\\\"Set the font by number from the textStyle.\\\"\\n\\n\\tself setActualFont: (textStyle fontAt: fontNumber)! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ntext: t textStyle: ts\\n\\ttext _ t.\\n\\ttextStyle _ ts! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ntextColor: ignored\\n\\t\\\"Overridden in DisplayScanner\\\"! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiCharacterScanner class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiCharacterScanner class methodsFor: 'class initialization' stamp: 'yo 12/18/2002 14:09'!\\ninitialize\\n\\\"\\n\\tMultiCharacterScanner initialize\\n\\\"\\n\\t| a |\\n\\ta _ Array new: 258.\\n\\ta at: 1 + 1 put: #embeddedObject.\\n\\ta at: Tab asciiValue + 1 put: #tab.\\n\\ta at: CR asciiValue + 1 put: #cr.\\n\\ta at: EndOfRun put: #endOfRun.\\n\\ta at: CrossedX put: #crossedX.\\n\\tNilCondition _ a copy.\\n\\tDefaultStopConditions _ a copy.\\n\\n\\tPaddedSpaceCondition _ a copy.\\n\\tPaddedSpaceCondition at: Space asciiValue + 1 put: #paddedSpace.\\n\\t\\n\\tSpaceCondition _ a copy.\\n\\tSpaceCondition at: Space asciiValue + 1 put: #space.\\n! !\\nMultiCharacterScanner subclass: #MultiCompositionScanner\\n\\tinstanceVariableNames: 'spaceX lineHeight baseline breakableIndex lineHeightAtBreak baselineAtBreak breakAtSpace lastWidth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 1/3/2003 02:33'!\\npresentation\\n\\n\\t^ presentation.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 1/3/2003 02:33'!\\npresentationLine\\n\\n\\t^ presentationLine.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 12/18/2002 14:56'!\\nrightX\\n\\t\\\"Meaningful only when a line has just been composed -- refers to the \\n\\tline most recently composed. This is a subtrefuge to allow for easy \\n\\tresizing of a composition rectangle to the width of the maximum line. \\n\\tUseful only when there is only one line in the form or when each line \\n\\tis terminated by a carriage return. Handy for sizing menus and lists.\\\"\\n\\n\\tbreakAtSpace ifTrue: [^ spaceX].\\n\\n\\t^ destX.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'intialize-release' stamp: 'yo 12/18/2002 13:57'!\\nforParagraph: aParagraph\\n\\t\\\"Initialize the receiver for scanning the given paragraph.\\\"\\n\\n\\tself\\n\\t\\tinitializeFromParagraph: aParagraph\\n\\t\\tclippedBy: aParagraph clippingRectangle.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 2/10/2004 23:00'!\\naddCharToPresentation: char\\n\\n\\tpresentation nextPut: char.\\n\\tlastWidth _ self widthOf: char inFont: font.\\n\\tdestX _ destX + lastWidth.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/16/2003 17:38'!\\ngetPresentation\\n\\n\\t^ presentation contents.\\n\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/16/2003 17:28'!\\ngetPresentationLine\\n\\n\\t^ presentationLine.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 11:51'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ encodingClass isBreakableAt: index in: sourceString.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 16:28'!\\nregisterBreakableIndex\\n\\n\\t\\\"Record left x and character index of the line-wrappable point. \\n\\tUsed for wrap-around. Answer whether the character has crossed the \\n\\tright edge of the composition rectangle of the paragraph.\\\"\\n\\n\\t(text at: lastIndex) = Character space ifTrue: [\\n\\t\\tbreakAtSpace _ true.\\n\\t\\tspaceX _ destX.\\n\\t\\tspaceCount _ spaceCount + 1.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t\\tbreakableIndex _ lastIndex.\\n\\t\\tdestX > rightMargin ifTrue: \\t[^self crossedX].\\n\\t] ifFalse: [\\n\\t\\tbreakAtSpace _ false.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t\\tbreakableIndex _ lastIndex - 1.\\n\\t].\\n\\t^ false.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 2/10/2004 22:59'!\\nremoveLastCharFromPresentation\\n\\n\\tpresentation ifNotNil: [\\n\\t\\tpresentation position: presentation position - 1.\\n\\t].\\n\\tdestX _ destX - lastWidth.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 17:34'!\\ncomposeFrom: startIndex inRectangle: lineRectangle\\n\\tfirstLine: firstLine leftSide: leftSide rightSide: rightSide\\n\\t\\\"Answer an instance of TextLineInterval that represents the next line in the paragraph.\\\"\\n\\t| runLength done stopCondition |\\n\\t\\\"Set up margins\\\"\\n\\tleftMargin _ lineRectangle left.\\n\\tleftSide ifTrue: [leftMargin _ leftMargin +\\n\\t\\t\\t\\t\\t\\t(firstLine ifTrue: [textStyle firstIndent]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [textStyle restIndent])].\\n\\tdestX _ spaceX _ leftMargin.\\n\\tfirstDestX _ destX.\\n\\trightMargin _ lineRectangle right.\\n\\trightSide ifTrue: [rightMargin _ rightMargin - textStyle rightIndent].\\n\\tlastIndex _ startIndex.\\t\\\"scanning sets last index\\\"\\n\\tdestY _ lineRectangle top.\\n\\tlineHeight _ baseline _ 0. \\\"Will be increased by setFont\\\"\\n\\tself setStopConditions.\\t\\\"also sets font\\\"\\n\\trunLength _ text runLengthFor: startIndex.\\n\\trunStopIndex _ (lastIndex _ startIndex) + (runLength - 1).\\n\\tline _ (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)\\n\\t\\t\\t\\trectangle: lineRectangle.\\n\\tpresentationLine _ (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)\\n\\t\\t\\t\\trectangle: lineRectangle.\\n\\tnumOfComposition _ 0.\\n\\tspaceCount _ 0.\\n\\tself handleIndentation.\\n\\tleftMargin _ destX.\\n\\tline leftMargin: leftMargin.\\n\\tpresentationLine leftMargin: leftMargin.\\n\\n\\tpresentation _ TextStream on: (Text fromString: (WideString new: text size)).\\n\\n\\tdone _ false.\\n\\t[done]\\n\\t\\twhileFalse: \\n\\t\\t\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\\"See setStopConditions for stopping conditions for composing.\\\"\\n\\t\\t\\t(self perform: stopCondition)\\n\\t\\t\\t\\tifTrue: [presentationLine lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading.\\n\\t\\t\\t\\t\\t\\t^ line lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading]]! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 17:34'!\\ncomposeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph \\n\\t\\\"Answer an instance of TextLineInterval that represents the next line in the paragraph.\\\"\\n\\t| runLength done stopCondition |\\n\\tdestX _ spaceX _ leftMargin _ aParagraph leftMarginForCompositionForLine: lineIndex.\\n\\tdestY _ 0.\\n\\trightMargin _ aParagraph rightMarginForComposition.\\n\\tleftMargin >= rightMargin ifTrue: [self error: 'No room between margins to compose'].\\n\\tlastIndex _ startIndex.\\t\\\"scanning sets last index\\\"\\n\\tlineHeight _ textStyle lineGrid. \\\"may be increased by setFont:...\\\"\\n\\tbaseline _ textStyle baseline.\\n\\tbaselineY _ destY + baseline.\\n\\tself setStopConditions.\\t\\\"also sets font\\\"\\n\\tself handleIndentation.\\n\\trunLength _ text runLengthFor: startIndex.\\n\\trunStopIndex _ (lastIndex _ startIndex) + (runLength - 1).\\n\\tline _ TextLineInterval\\n\\t\\tstart: lastIndex\\n\\t\\tstop: 0\\n\\t\\tinternalSpaces: 0\\n\\t\\tpaddingWidth: 0.\\n\\tpresentationLine _ TextLineInterval\\n\\t\\tstart: lastIndex\\n\\t\\tstop: 0\\n\\t\\tinternalSpaces: 0\\n\\t\\tpaddingWidth: 0.\\n\\tnumOfComposition _ 0.\\n\\tpresentation _ TextStream on: (Text fromString: (WideString new: text size)).\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\t[done]\\n\\t\\twhileFalse: \\n\\t\\t\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\\"See setStopConditions for stopping conditions for composing.\\\"\\n\\t\\t\\t(self perform: stopCondition)\\n\\t\\t\\t\\tifTrue: [presentationLine lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading.\\n\\t\\t\\t\\t\\t\\t^line lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading]]! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'yo 1/3/2003 11:54'!\\ncrossedX\\n\\t\\\"There is a word that has fallen across the right edge of the composition \\n\\trectangle. This signals the need for wrapping which is done to the last \\n\\tspace that was encountered, as recorded by the space stop condition.\\\"\\n\\n\\t(breakAtSpace) ifTrue: [\\n\\t\\tspaceCount >= 1 ifTrue:\\n\\t\\t\\t[\\\"The common case. First back off to the space at which we wrap.\\\"\\n\\t\\t\\tline stop: breakableIndex.\\n\\t\\t\\tpresentationLine stop: breakableIndex - numOfComposition.\\n\\t\\t\\tlineHeight _ lineHeightAtBreak.\\n\\t\\t\\tbaseline _ baselineAtBreak.\\n\\t\\t\\tspaceCount _ spaceCount - 1.\\n\\t\\t\\tbreakableIndex _ breakableIndex - 1.\\n\\n\\t\\t\\t\\\"Check to see if any spaces preceding the one at which we wrap.\\n\\t\\t\\t\\tDouble space after punctuation, most likely.\\\"\\n\\t\\t\\t[(spaceCount > 1 and: [(text at: breakableIndex) = Space])]\\n\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t[spaceCount _ spaceCount - 1.\\n\\t\\t\\t\\t\\t\\\"Account for backing over a run which might\\n\\t\\t\\t\\t\\t\\tchange width of space.\\\"\\n\\t\\t\\t\\t\\tfont _ text fontAt: breakableIndex withStyle: textStyle.\\n\\t\\t\\t\\t\\tbreakableIndex _ breakableIndex - 1.\\n\\t\\t\\t\\t\\tspaceX _ spaceX - (font widthOf: Space)].\\n\\t\\t\\tline paddingWidth: rightMargin - spaceX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t\\t\\tpresentationLine internalSpaces: spaceCount.\\n\\t\\t\\tline internalSpaces: spaceCount]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"Neither internal nor trailing spaces -- almost never happens.\\\"\\n\\t\\t\\tlastIndex _ lastIndex - 1.\\n\\t\\t\\t[destX <= rightMargin]\\n\\t\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t\\t[destX _ destX - (font widthOf: (text at: lastIndex)).\\n\\t\\t\\t\\t\\tlastIndex _ lastIndex - 1].\\n\\t\\t\\tspaceX _ destX.\\n\\t\\t\\tline paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine stop: (lastIndex max: line first).\\n\\t\\t\\tline stop: (lastIndex max: line first)].\\n\\t\\t^true\\n\\t].\\n\\n\\t(breakableIndex isNil or: [breakableIndex < line first]) ifTrue: [\\n\\t\\t\\\"Any breakable point in this line. Just wrap last character.\\\"\\n\\t\\tbreakableIndex _ lastIndex - 1.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t].\\n\\n\\t\\\"It wasn't a space, but anyway this is where we break the line.\\\"\\n\\tline stop: breakableIndex.\\n\\tpresentationLine stop: breakableIndex.\\n\\tlineHeight _ lineHeightAtBreak.\\n\\tbaseline _ baselineAtBreak.\\n\\t^ true.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'tak 12/22/2004 00:59'!\\nsetActualFont: aFont\\n\\t\\\"Keep track of max height and ascent for auto lineheight\\\"\\n\\t| descent |\\n\\tsuper setActualFont: aFont.\\n\\t\\\"' ', lastIndex printString, ' ' displayAt: (lastIndex * 15)@0.\\\"\\n\\tlineHeight == nil\\n\\t\\tifTrue: [descent _ font descent.\\n\\t\\t\\t\\tbaseline _ font ascent.\\n\\t\\t\\t\\tlineHeight _ baseline + descent]\\n\\t\\tifFalse: [descent _ lineHeight - baseline max: font descent.\\n\\t\\t\\t\\tbaseline _ baseline max: font ascent.\\n\\t\\t\\t\\tlineHeight _ lineHeight max: baseline + descent]! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\ncolumnBreak\\n\\n\\t\\\"Answer true. Set up values for the text line interval currently being \\n\\tcomposed.\\\"\\n\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\tspaceX _ destX.\\n\\tline paddingWidth: rightMargin - spaceX.\\n\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t^true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\ncr\\n\\t\\\"Answer true. Set up values for the text line interval currently being \\n\\tcomposed.\\\"\\n\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\tspaceX _ destX.\\n\\tline paddingWidth: rightMargin - spaceX.\\n\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t^true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 2/10/2004 23:03'!\\nendOfRun\\n\\t\\\"Answer true if scanning has reached the end of the paragraph. \\n\\tOtherwise step conditions (mostly install potential new font) and answer \\n\\tfalse.\\\"\\n\\n\\t| runLength |\\n\\tlastIndex = text size\\n\\tifTrue:\\t[line stop: lastIndex.\\n\\t\\t\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\t\\t\\tspaceX _ destX.\\n\\t\\t\\tline paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - destX.\\n\\t\\t\\t^true]\\n\\tifFalse:\\t[\\n\\t\\t\\t\\\"(text at: lastIndex) charCode = 32 ifTrue: [destX _ destX + spaceWidth].\\\"\\n\\t\\t\\trunLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).\\n\\t\\t\\trunStopIndex _ lastIndex + (runLength - 1).\\n\\t\\t\\tself setStopConditions.\\n\\t\\t\\t^false]\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t| descent |\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [\\\"It doesn't fit\\\"\\n\\t\\t\\\"But if it's the first character then leave it here\\\"\\n\\t\\tlastIndex < line first ifFalse:[\\n\\t\\t\\tline stop: lastIndex-1.\\n\\t\\t\\t^ false]].\\n\\tdescent _ lineHeight - baseline.\\n\\tlineHeight _ lineHeight max: anchoredMorph height.\\n\\tbaseline _ lineHeight - descent.\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\t^ true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 21:47'!\\nsetFont\\n\\tsuper setFont.\\n\\tbreakAtSpace _ false.\\n\\twantsColumnBreaks == true ifTrue: [\\n\\t\\tstopConditions _ stopConditions copy.\\n\\t\\tstopConditions at: TextComposer characterForColumnBreak asciiValue + 1 put: #columnBreak.\\n\\t].\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:57'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:57'!\\ntab\\n\\t\\\"Advance destination x according to tab settings in the paragraph's \\n\\ttextStyle. Answer whether the character has crossed the right edge of \\n\\tthe composition rectangle of the paragraph.\\\"\\n\\n\\tdestX _ textStyle\\n\\t\\t\\t\\tnextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.\\n\\tdestX > rightMargin ifTrue:\\t[^self crossedX].\\n\\tlastIndex _ lastIndex + 1.\\n\\t^false\\n! !\\nMultiCharacterScanner subclass: #MultiDisplayScanner\\n\\tinstanceVariableNames: 'bitBlt lineY runX foregroundColor backgroundColor fillBlt lineHeight paragraph paragraphColor morphicOffset ignoreColorChanges'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiDisplayScanner methodsFor: 'MVC-compatibility' stamp: 'yo 1/7/2005 12:15'!\\ndisplayLines: linesInterval in: aParagraph clippedBy: visibleRectangle\\n\\t\\\"The central display routine. The call on the primitive \\n\\t(scanCharactersFrom:to:in:rightX:) will be interrupted according to an \\n\\tarray of stop conditions passed to the scanner at which time the code to \\n\\thandle the stop condition is run and the call on the primitive continued \\n\\tuntil a stop condition returns true (which means the line has \\n\\tterminated).\\\"\\n\\t| runLength done stopCondition leftInRun startIndex string lastPos |\\n\\t\\\"leftInRun is the # of characters left to scan in the current run;\\n\\t\\twhen 0, it is time to call 'self setStopConditions'\\\"\\n\\tmorphicOffset _ 0@0.\\n\\tleftInRun _ 0.\\n\\tself initializeFromParagraph: aParagraph clippedBy: visibleRectangle.\\n\\tignoreColorChanges _ false.\\n\\tparagraph _ aParagraph.\\n\\tforegroundColor _ paragraphColor _ aParagraph foregroundColor.\\n\\tbackgroundColor _ aParagraph backgroundColor.\\n\\taParagraph backgroundColor isTransparent\\n\\t\\tifTrue: [fillBlt _ nil]\\n\\t\\tifFalse: [fillBlt _ bitBlt copy. \\\"Blt to fill spaces, tabs, margins\\\"\\n\\t\\t\\t\\tfillBlt sourceForm: nil; sourceOrigin: 0@0.\\n\\t\\t\\t\\tfillBlt fillColor: aParagraph backgroundColor].\\n\\trightMargin _ aParagraph rightMarginForDisplay.\\n\\tlineY _ aParagraph topAtLineIndex: linesInterval first.\\n\\tbitBlt destForm deferUpdatesIn: visibleRectangle while: [\\n\\t\\tlinesInterval do: \\n\\t\\t\\t[:lineIndex | \\n\\t\\t\\tleftMargin _ aParagraph leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment]).\\n\\t\\t\\tdestX _ (runX _ leftMargin).\\n\\t\\t\\tline _ aParagraph lines at: lineIndex.\\n\\t\\t\\tlineHeight _ line lineHeight.\\n\\t\\t\\tfillBlt == nil ifFalse:\\n\\t\\t\\t\\t[fillBlt destX: visibleRectangle left destY: lineY\\n\\t\\t\\t\\t\\twidth: visibleRectangle width height: lineHeight; copyBits].\\n\\t\\t\\tlastIndex _ line first.\\n\\t\\t\\tleftInRun <= 0\\n\\t\\t\\t\\tifTrue: [self setStopConditions. \\\"also sets the font\\\"\\n\\t\\t\\t\\t\\t\\tleftInRun _ text runLengthFor: line first].\\n\\t\\t\\tbaselineY _ lineY + line baseline.\\n\\t\\t\\tdestY _ baselineY - font ascent. \\\"Should have happened in setFont\\\"\\n\\t\\t\\trunLength _ leftInRun.\\n\\t\\t\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\t\\t\\tleftInRun _ leftInRun - (runStopIndex - lastIndex + 1).\\n\\t\\t\\tspaceCount _ 0.\\n\\t\\t\\tdone _ false.\\n\\t\\t\\tstring _ text string.\\n\\t\\t\\tself handleIndentation.\\n\\t\\t\\t[done] whileFalse:[\\n\\t\\t\\t\\tstartIndex _ lastIndex.\\n\\t\\t\\t\\tlastPos _ destX@destY.\\n\\t\\t\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\t\\tin: string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\tlastIndex >= startIndex ifTrue:[\\n\\t\\t\\t\\t\\tfont displayString: string on: bitBlt \\n\\t\\t\\t\\t\\t\\tfrom: startIndex to: lastIndex at: lastPos kern: kern baselineY: baselineY].\\n\\t\\t\\t\\t\\\"see setStopConditions for stopping conditions for displaying.\\\"\\n\\t\\t\\t\\tdone _ self perform: stopCondition].\\n\\t\\t\\tfillBlt == nil ifFalse:\\n\\t\\t\\t\\t[fillBlt destX: destX destY: lineY width: visibleRectangle right-destX height: lineHeight; copyBits].\\n\\t\\t\\tlineY _ lineY + lineHeight]]! !\\n\\n!MultiDisplayScanner methodsFor: 'MVC-compatibility' stamp: 'yo 3/14/2005 06:48'!\\ninitializeFromParagraph: aParagraph clippedBy: clippingRectangle\\n\\n\\tsuper initializeFromParagraph: aParagraph clippedBy: clippingRectangle.\\n\\tbitBlt _ BitBlt asGrafPort toForm: aParagraph destinationForm.\\n\\tbitBlt sourceX: 0; width: 0.\\t\\\"Init BitBlt so that the first call to a primitive will not fail\\\"\\n\\tbitBlt combinationRule: Form paint.\\n\\tbitBlt colorMap:\\n\\t\\t(Bitmap with: 0 \\\"Assumes 1-bit deep fonts\\\"\\n\\t\\t\\t\\twith: (bitBlt destForm pixelValueFor: aParagraph foregroundColor)).\\n\\tbitBlt clipRect: clippingRectangle.\\n! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 11:52'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ false.\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'multilingual scanning' stamp: 'yo 8/6/2003 05:57'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| encoding f nextDestX maxAscii startEncoding char charValue |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tchar _ (sourceString at: lastIndex).\\n\\t\\tcharValue _ char charCode.\\n\\t\\tcharValue > maxAscii ifTrue: [charValue _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: charValue + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t^ stops at: charValue + 1\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (self widthOf: char inFont: font).\\n\\t\\tnextDestX > rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'scanning' stamp: 'yo 1/7/2005 12:15'!\\ndisplayLine: textLine offset: offset leftInRun: leftInRun\\n\\t\\\"The call on the primitive (scanCharactersFrom:to:in:rightX:) will be interrupted according to an array of stop conditions passed to the scanner at which time the code to handle the stop condition is run and the call on the primitive continued until a stop condition returns true (which means the line has terminated). leftInRun is the # of characters left to scan in the current run; when 0, it is time to call setStopConditions.\\\"\\n\\t| done stopCondition nowLeftInRun startIndex string lastPos |\\n\\tline _ textLine.\\n\\tmorphicOffset _ offset.\\n\\tlineY _ line top + offset y.\\n\\tlineHeight _ line lineHeight.\\n\\trightMargin _ line rightMargin + offset x.\\n\\tlastIndex _ line first.\\n\\tleftInRun <= 0 ifTrue: [self setStopConditions].\\n\\tleftMargin _ (line leftMarginForAlignment: alignment) + offset x.\\n\\tdestX _ runX _ leftMargin.\\n\\tfillBlt == nil ifFalse:\\n\\t\\t[\\\"Not right\\\"\\n\\t\\tfillBlt destX: line left destY: lineY\\n\\t\\t\\twidth: line width left height: lineHeight; copyBits].\\n\\tlastIndex _ line first.\\n\\tleftInRun <= 0\\n\\t\\tifTrue: [nowLeftInRun _ text runLengthFor: lastIndex]\\n\\t\\tifFalse: [nowLeftInRun _ leftInRun].\\n\\tbaselineY _ lineY + line baseline.\\n\\tdestY _ baselineY - font ascent.\\n\\trunStopIndex _ lastIndex + (nowLeftInRun - 1) min: line last.\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\tstring _ text string.\\n\\t[done] whileFalse:[\\n\\t\\tstartIndex _ lastIndex.\\n\\t\\tlastPos _ destX@destY.\\n\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\tin: string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\tkern: kern.\\n\\t\\tlastIndex >= startIndex ifTrue:[\\n\\t\\t\\tfont displayString: string on: bitBlt \\n\\t\\t\\t\\tfrom: startIndex to: lastIndex at: lastPos kern: kern baselineY: baselineY].\\n\\t\\t\\\"see setStopConditions for stopping conditions for displaying.\\\"\\n\\t\\tdone _ self perform: stopCondition.\\n\\t\\t\\\"lastIndex > runStopIndex ifTrue: [done _ true].\\\"\\n\\t].\\n\\t^ runStopIndex - lastIndex \\\"Number of characters remaining in the current run\\\"! !\\n\\n!MultiDisplayScanner methodsFor: 'scanning' stamp: 'lr 1/21/2006 16:01'!\\nplaceEmbeddedObject: anchoredMorph\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[\\n\\t\\tanchoredMorph position: \\n\\t\\t\\tanchoredMorph relativeTextAnchorPosition +\\n\\t\\t\\t(anchoredMorph owner textBounds origin x @ 0)\\n\\t\\t\\t- (0@morphicOffset y) + (0@lineY).\\n\\t\\t^true\\n\\t].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].\\n\\tanchoredMorph isMorph ifTrue: [\\n\\t\\tanchoredMorph position: ((destX - anchoredMorph width)@lineY) - morphicOffset\\n\\t] ifFalse: [\\n\\t\\tdestY _ lineY.\\n\\t\\tbaselineY _ lineY + anchoredMorph height..\\n\\t\\trunX _ destX.\\n\\t\\tanchoredMorph \\n\\t\\t\\tdisplayOn: bitBlt destForm \\n\\t\\t\\tat: destX - anchoredMorph width @ destY\\n\\t\\t\\tclippingBox: bitBlt clipRect\\n\\t\\t\\trule: Form blend\\n\\t\\t\\tfillColor: Color white \\n\\t].\\n\\t^ true! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ncr\\n\\t\\\"When a carriage return is encountered, simply increment the pointer \\n\\tinto the paragraph.\\\"\\n\\n\\tlastIndex_ lastIndex + 1.\\n\\t^false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ncrossedX\\n\\t\\\"This condition will sometimes be reached 'legally' during display, when, \\n\\tfor instance the space that caused the line to wrap actually extends over \\n\\tthe right boundary. This character is allowed to display, even though it \\n\\tis technically outside or straddling the clipping ectangle since it is in \\n\\tthe normal case not visible and is in any case appropriately clipped by \\n\\tthe scanner.\\\"\\n\\n\\t^ true ! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nendOfRun\\n\\t\\\"The end of a run in the display case either means that there is actually \\n\\ta change in the style (run code) to be associated with the string or the \\n\\tend of this line has been reached.\\\"\\n\\t| runLength |\\n\\tlastIndex = line last ifTrue: [^true].\\n\\trunX _ destX.\\n\\trunLength _ text runLengthFor: (lastIndex _ lastIndex + 1).\\n\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\tself setStopConditions.\\n\\t^ false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\npaddedSpace\\n\\t\\\"Each space is a stop condition when the alignment is right justified. \\n\\tPadding must be added to the base width of the space according to \\n\\twhich space in the line this space is and according to the amount of \\n\\tspace that remained at the end of the line when it was composed.\\\"\\n\\n\\tspaceCount _ spaceCount + 1.\\n\\tdestX _ destX + spaceWidth + (line justifiedPadFor: spaceCount).\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nplainTab\\n\\t| oldX |\\n\\toldX _ destX.\\n\\tsuper plainTab.\\n\\tfillBlt == nil ifFalse:\\n\\t\\t[fillBlt destX: oldX destY: destY width: destX - oldX height: font height; copyBits]! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (alignment = Justified ifTrue: [#paddedSpace]).\\n\\n\\\"\\n\\talignment = Justified ifTrue: [\\n\\t\\tstopConditions == DefaultStopConditions \\n\\t\\t\\tifTrue:[stopConditions _ stopConditions copy].\\n\\t\\tstopConditions at: Space asciiValue + 1 put: #paddedSpace]\\n\\\"! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ntab\\n\\tself plainTab.\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 1/23/2003 14:40'!\\npresentationText: t\\n\\n\\ttext _ t.\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\nsetDestForm: df\\n\\tbitBlt setDestForm: df.! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 1/6/2005 23:06'!\\nsetFont \\n\\tforegroundColor _ paragraphColor.\\n\\tsuper setFont. \\\"Sets font and emphasis bits, and maybe foregroundColor\\\"\\n\\tfont installOn: bitBlt foregroundColor: foregroundColor backgroundColor: Color transparent.\\n\\ttext ifNotNil:[\\n\\t\\tbaselineY _ lineY + line baseline.\\n\\t\\tdestY _ baselineY - font ascent].\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\nsetPort: aBitBlt\\n\\t\\\"Install the BitBlt to use\\\"\\n\\tbitBlt _ aBitBlt.\\n\\tbitBlt sourceX: 0; width: 0.\\t\\\"Init BitBlt so that the first call to a primitive will not fail\\\"\\n\\tbitBlt sourceForm: nil. \\\"Make sure font installation won't be confused\\\"\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\ntext: t textStyle: ts foreground: foreColor background: backColor fillBlt: blt ignoreColorChanges: shadowMode\\n\\ttext _ t.\\n\\ttextStyle _ ts. \\n\\tforegroundColor _ paragraphColor _ foreColor.\\n\\t(backgroundColor _ backColor) isTransparent ifFalse:\\n\\t\\t[fillBlt _ blt.\\n\\t\\tfillBlt fillColor: backgroundColor].\\n\\tignoreColorChanges _ shadowMode! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\ntextColor: textColor\\n\\tignoreColorChanges ifTrue: [^ self].\\n\\tforegroundColor _ textColor! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiDisplayScanner class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiDisplayScanner class methodsFor: 'queries' stamp: 'yo 12/18/2002 13:58'!\\ndefaultFont\\n\\t^ TextStyle defaultFont! !\\nNewParagraph subclass: #MultiNewParagraph\\n\\tinstanceVariableNames: 'presentationText presentationLines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 16:09'!\\ndisplayOn: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\n\\t| visibleRectangle offset leftInRun line |\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ somePosition - positionWhenComposed.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ lines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 22:33'!\\ndisplayOnTest: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\n\\t| visibleRectangle offset leftInRun line |\\n\\t(presentationText isNil or: [presentationLines isNil]) ifTrue: [\\n\\t\\t^ self displayOn: aCanvas using: displayScanner at: somePosition.\\n\\t].\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ somePosition - positionWhenComposed.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ presentationLines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\nmultiComposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult composer presentationInfo |\\n\\n\\tcomposer _ MultiTextComposer new.\\n\\tpresentationLines _ nil.\\n\\tpresentationText _ nil.\\n\\tnewResult _ composer\\n\\t\\tmultiComposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\tpresentationInfo _ composer getPresentationInfo.\\n\\tpresentationLines _ presentationInfo first asArray.\\n\\tpresentationText _ presentationInfo second.\\n\\t\\\"maxRightX printString displayAt: 0@0.\\\"\\n\\t^maxRightX\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 17:31'!\\npresentationLines\\n\\n\\t^ presentationLines.\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 17:31'!\\npresentationText\\n\\n\\t^ presentationText.\\n! !\\nFormCanvas subclass: #MultiResolutionCanvas\\n\\tinstanceVariableNames: 'deferredMorphs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/4/2000 12:00'!\\ndeferredMorphs\\n\\n\\t^deferredMorphs! !\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/4/2000 11:58'!\\ndeferredMorphs: aCollection\\n\\n\\tdeferredMorphs _ aCollection! !\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/17/2000 13:25'!\\ninitializeFrom: aFormCanvas\\n\\n\\torigin _ aFormCanvas origin.\\n\\tclipRect _ aFormCanvas privateClipRect.\\n\\tform _ aFormCanvas form.\\n\\tport _ aFormCanvas privatePort.\\n\\tshadowColor _ aFormCanvas shadowColor.\\n! !\\n\\n\\n!MultiResolutionCanvas methodsFor: 'drawing-general' stamp: 'RAA 12/4/2000 12:00'!\\nfullDraw: aMorph\\n\\n\\taMorph canDrawAtHigherResolution ifTrue: [\\n\\t\\tdeferredMorphs ifNil: [deferredMorphs _ OrderedCollection new].\\n\\t\\tdeferredMorphs add: aMorph.\\n\\t] ifFalse: [\\n\\t\\tsuper fullDraw: aMorph\\n\\t].! !\\nTTCFont subclass: #MultiTTCFont\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:08'!\\naccess: char at: index\\n\\n\\t| wcache entry |\\n\\twcache _ self cache.\\n\\tentry _ wcache at: index.\\n\\twcache replaceFrom: index to: wcache size - 1 with: wcache startingAt: index + 1.\\n\\twcache at: wcache size put: entry.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:09'!\\nat: char put: form\\n\\n\\t| wcache |\\n\\twcache _ self cache.\\n\\twcache replaceFrom: 1 to: wcache size - 1 with: wcache startingAt: 2.\\n\\twcache at: wcache size\\n\\t\\tput: (Array with: char asciiValue with: foregroundColor with: form).\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:27'!\\nflushCache\\n\\n\\tcache at: 1 put: ((1 to: 128) collect: [:i | Array with: -1 with: nil with: nil]).\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 21:04'!\\nformOf: char\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\t^ form.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\t^ newForm.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 1/7/2005 11:09'!\\nglyphInfoOf: char into: glyphInfoArray\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\tglyphInfoArray at: 1 put: form;\\n\\t\\t\\tat: 2 put: 0;\\n\\t\\t\\tat: 3 put: form width;\\n\\t\\t\\tat: 4 put: (self ascentOf: char);\\n\\t\\t\\tat: 5 put: self.\\n\\t\\t^ glyphInfoArray.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\n\\tglyphInfoArray at: 1 put: newForm;\\n\\t\\tat: 2 put: 0;\\n\\t\\tat: 3 put: newForm width;\\n\\t\\tat: 4 put: (self ascentOf: char);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:39'!\\nhasCached: char ifTrue: twoArgBlock\\n\\n\\t| value elem |\\n\\tvalue _ char asciiValue.\\n\\n\\tself cache size to: 1 by: -1 do: [:i |\\n\\t\\telem _ self cache at: i.\\n\\t\\t(elem first = value and: [elem second = foregroundColor]) ifTrue: [\\n\\t\\t\\t^ twoArgBlock value: elem third value: i.\\n\\t\\t].\\n\\t].\\n\\t^ false.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/29/2003 15:01'!\\nisTTCFont\\n\\t^true! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:30'!\\nwidthOf: char\\n\\n\\t\\\"This method cannot use #formOf: because formOf: discriminates the color and causes unnecessary bitmap creation.\\\"\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\t^ form width.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\t^ newForm width.\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiTTCFont class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiTTCFont class methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:34'!\\ncacheAllNil\\n\\\"\\n\\tself cacheAllNil\\n\\\"\\n\\tself allInstances do: [:inst |\\n\\t\\tinst cache do: [:e |\\n\\t\\t\\te third ifNotNil: [^ false].\\n\\t\\t].\\n\\t].\\n\\n\\t^ true.\\n! !\\nTextComposer subclass: #MultiTextComposer\\n\\tinstanceVariableNames: 'presentation presentationLines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\ncomposeEachRectangleIn: rectangles\\n\\n\\t| myLine lastChar |\\n\\n\\t1 to: rectangles size do: [:i | \\n\\t\\tcurrCharIndex <= theText size ifFalse: [^false].\\n\\t\\tmyLine _ scanner \\n\\t\\t\\tcomposeFrom: currCharIndex \\n\\t\\t\\tinRectangle: (rectangles at: i)\\t\\t\\t\\t\\n\\t\\t\\tfirstLine: isFirstLine \\n\\t\\t\\tleftSide: i=1 \\n\\t\\t\\trightSide: i=rectangles size.\\n\\t\\tlines addLast: myLine.\\n\\t\\tpresentationLines addLast: scanner getPresentationLine.\\n\\t\\tpresentation ifNil: [presentation _ scanner getPresentation]\\n\\t\\t\\tifNotNil: [presentation _ presentation, scanner getPresentation].\\n\\t\\tactualHeight _ actualHeight max: myLine lineHeight. \\\"includes font changes\\\"\\n\\t\\tcurrCharIndex _ myLine last + 1.\\n\\t\\tlastChar _ theText at: myLine last.\\n\\t\\tlastChar = Character cr ifTrue: [^#cr].\\n\\t\\twantsColumnBreaks ifTrue: [\\n\\t\\t\\tlastChar = TextComposer characterForColumnBreak ifTrue: [^#columnBreak].\\n\\t\\t].\\n\\t].\\n\\t^false! !\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\ngetPresentationInfo\\n\\n\\t^ Array with: presentationLines with: presentation.\\n! !\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/16/2003 17:30'!\\nmultiComposeLinesFrom: argStart to: argStop delta: argDelta into: argLinesCollection priorLines: argPriorLines atY: argStartY textStyle: argTextStyle text: argText container: argContainer wantsColumnBreaks: argWantsColumnBreaks\\n\\n\\twantsColumnBreaks _ argWantsColumnBreaks.\\n\\tlines _ argLinesCollection.\\n\\tpresentationLines _ argLinesCollection copy.\\n\\ttheTextStyle _ argTextStyle.\\n\\ttheText _ argText.\\n\\ttheContainer _ argContainer.\\n\\tdeltaCharIndex _ argDelta.\\n\\tcurrCharIndex _ startCharIndex _ argStart.\\n\\tstopCharIndex _ argStop.\\n\\tprevLines _ argPriorLines.\\n\\tcurrentY _ argStartY.\\n\\tdefaultLineHeight _ theTextStyle lineGrid.\\n\\tmaxRightX _ theContainer left.\\n\\tpossibleSlide _ stopCharIndex < theText size and: [theContainer isMemberOf: Rectangle].\\n\\tnowSliding _ false.\\n\\tprevIndex _ 1.\\n\\tscanner _ MultiCompositionScanner new text: theText textStyle: theTextStyle.\\n\\tscanner wantsColumnBreaks: wantsColumnBreaks.\\n\\tisFirstLine _ true.\\n\\tself composeAllLines.\\n\\tisFirstLine ifTrue: [\\\"No space in container or empty text\\\"\\n\\t\\tself \\n\\t\\t\\taddNullLineWithIndex: startCharIndex\\n\\t\\t\\tandRectangle: (theContainer topLeft extent: 0@defaultLineHeight)\\n\\t] ifFalse: [\\n\\t\\tself fixupLastLineIfCR\\n\\t].\\n\\t^{lines asArray. maxRightX}\\n\\n! !\\nLazyListMorph subclass: #MulticolumnLazyListMorph\\n\\tinstanceVariableNames: 'columnWidths'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n!MulticolumnLazyListMorph commentStamp: '<historical>' prior: 0!\\nA variant of LazyListMorph that can display multi-column lists.!\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'as yet unclassified' stamp: 'ls 5/17/2001 21:23'!\\ngetListItem: index\\n\\t^listSource getListRow: index! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'as yet unclassified' stamp: 'ls 5/18/2001 16:43'!\\nlistChanged\\n\\tcolumnWidths := nil.\\n\\tsuper listChanged! !\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'nk 1/10/2004 16:19'!\\ndisplay: items atRow: row on: canvas \\n\\t\\\"display the specified item, which is on the specified row; for Multicolumn \\n\\tlists, items will be a list of strings\\\"\\n\\t| drawBounds |\\n\\tdrawBounds := self drawBoundsForRow: row.\\n\\tdrawBounds := drawBounds intersect: self bounds.\\n\\titems\\n\\t\\twith: (1 to: items size)\\n\\t\\tdo: [:item :index | \\n\\t\\t\\t\\\"move the bounds to the right at each step\\\"\\n\\t\\t\\tindex > 1\\n\\t\\t\\t\\tifTrue: [drawBounds := drawBounds left: drawBounds left + 6\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t+ (columnWidths at: index - 1)].\\n\\t\\t\\titem isText\\n\\t\\t\\t\\tifTrue: [canvas\\n\\t\\t\\t\\t\\t\\tdrawString: item\\n\\t\\t\\t\\t\\t\\tin: drawBounds\\n\\t\\t\\t\\t\\t\\tfont: (font\\n\\t\\t\\t\\t\\t\\t\\t\\temphasized: (item emphasisAt: 1))\\n\\t\\t\\t\\t\\t\\tcolor: (self colorForRow: row)]\\n\\t\\t\\t\\tifFalse: [canvas\\n\\t\\t\\t\\t\\t\\tdrawString: item\\n\\t\\t\\t\\t\\t\\tin: drawBounds\\n\\t\\t\\t\\t\\t\\tfont: font\\n\\t\\t\\t\\t\\t\\tcolor: (self colorForRow: row)]]! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'ls 5/17/2001 21:58'!\\ndrawOn: aCanvas\\n self getListSize = 0 ifTrue:[ ^self ].\\n\\n self setColumnWidthsFor: aCanvas.\\n\\n super drawOn: aCanvas! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'sps 3/23/2004 15:51'!\\nsetColumnWidthsFor: aCanvas\\n | row topRow bottomRow |\\n \\\"set columnWidths for drawing on the specified canvas\\\"\\n\\t\\tcolumnWidths ifNil: [\\n\\t\\tcolumnWidths := (self item: 1) collect: [ :ignored | 0 ]. ].\\n\\ttopRow := (self topVisibleRowForCanvas: aCanvas) max: 1.\\n\\tbottomRow := (self bottomVisibleRowForCanvas: aCanvas) max: 1.\\n\\ttopRow > bottomRow ifTrue: [ ^ self ].\\n\\ttopRow to: bottomRow do: [ :rowIndex |\\n row := self item: rowIndex.\\n columnWidths := columnWidths with: row collect: [ :currentWidth :item |\\n\\t\\t\\t\\t| widthOfItem |\\n\\t\\t\\t\\twidthOfItem := (font widthOfStringOrText: item).\\n\\t\\t\\t\\twidthOfItem > currentWidth\\n\\t\\t\\t\\t\\tifTrue: [ self changed. widthOfItem ]\\n\\t\\t\\t\\t\\tifFalse: [ currentWidth ] ] ]! !\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'scroll range' stamp: 'sps 4/2/2004 12:16'!\\nhUnadjustedScrollRange\\n\\\"multi column list morphs don't use hScrollbars\\\"\\n\\n\\t^0\\n\\n! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'scroll range' stamp: 'ls 4/17/2004 12:21'!\\nwidthToDisplayItem: item\\n\\t| widths |\\n\\twidths := item collect: [ :each | super widthToDisplayItem: each ].\\n\\t^widths sum + (10 * (widths size - 1)) \\\"add in space between the columns\\\"\\n! !\\nSketchMorph subclass: #MultiuserTinyPaint\\n\\tinstanceVariableNames: 'drawState'\\n\\tclassVariableNames: 'LastMouseIndex PenColorIndex PenIndex PenSizeIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-AdditionalWidgets'!\\n!MultiuserTinyPaint commentStamp: '<historical>' prior: 0!\\nA very simple paint program that handles multiple users (hands).\\nEach user has their own brush size and color.\\n!\\n\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nhandlesMouseDown: evt\\n\\n\\t^ true\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nmouseDown: evt\\n\\n\\t| state |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\tstate at: LastMouseIndex put: evt cursorPoint.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nmouseMove: evt\\n\\n\\t| state lastP p pen |\\n\\tstate _ drawState at: evt hand ifAbsent: [^ self].\\n\\tlastP _ state at: LastMouseIndex.\\n\\tp _ evt cursorPoint.\\n\\tp = lastP ifTrue: [^ self].\\n\\n\\tpen _ state at: PenIndex.\\n\\tpen drawFrom: lastP - bounds origin to: p - bounds origin.\\n\\tself invalidRect: (\\n\\t\\t((lastP min: p) - pen sourceForm extent) corner:\\n\\t\\t((lastP max: p) + pen sourceForm extent)).\\n\\tstate at: LastMouseIndex put: p.\\n! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryVeryLightGray! !\\n\\n!MultiuserTinyPaint methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:52'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tdrawState _ IdentityDictionary new.\\n\\tself clear! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'clear' translated action: #clear.\\n\\taCustomMenu add: 'pen color' translated action: #setPenColor:.\\n\\taCustomMenu add: 'pen size' translated action: #setPenSize:.\\n\\\"\\taCustomMenu add: 'fill' translated action: #fill:.\\\"\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 11/4/97 07:15'!\\nbrushColor: aColor hand: hand\\n\\n\\t| state |\\n\\t(drawState includesKey: hand) ifFalse: [self createDrawStateFor: hand].\\n\\tstate _ drawState at: hand.\\n\\t(state at: PenIndex) color: aColor.\\n\\tstate at: PenColorIndex put: aColor.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 11/4/97 07:15'!\\nclear\\n\\n\\t| newPen |\\n\\tself form: ((Form extent: 400@300 depth: 8) fillColor: color).\\n\\tdrawState do: [:state |\\n\\t\\tnewPen _ Pen newOnForm: originalForm.\\n\\t\\tnewPen roundNib: (state at: PenSizeIndex).\\n\\t\\tnewPen color: (state at: PenColorIndex).\\n\\t\\tstate at: PenIndex put: newPen].\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'bf 1/5/2000 19:12'!\\nfill: evt\\n\\n\\t| state fillPt |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\n\\tCursor blank show.\\n\\tCursor crossHair showWhile:\\n\\t\\t[fillPt _ Sensor waitButton - self position].\\n\\toriginalForm shapeFill: (state at: PenColorIndex) interiorPoint: fillPt.\\n\\tself changed.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 9/26/97 14:47'!\\npenSize: anInteger hand: hand\\n\\n\\t| state |\\n\\t(drawState includesKey: hand) ifFalse: [self createDrawStateFor: hand].\\n\\tstate _ drawState at: hand.\\n\\tstate at: PenSizeIndex put: anInteger.\\n\\t(state at: PenIndex) roundNib: anInteger.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'ar 10/5/2000 18:52'!\\nsetPenColor: evt\\n\\t| state |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\tself changeColorTarget: self selector: #brushColor:hand: originalColor: (state at: PenColorIndex) hand: evt hand! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'RAA 6/12/2000 09:07'!\\nsetPenSize: evt\\n\\n\\t| menu sizes |\\n\\tmenu _ MenuMorph new.\\n\\tsizes _ (0 to: 5), (6 to: 12 by: 2), (15 to: 40 by: 5).\\n\\tsizes do: [:w |\\n\\t\\tmenu add: w printString\\n\\t\\t\\ttarget: self\\n\\t\\t\\tselector: #penSize:hand:\\n\\t\\t\\targumentList: (Array with: w with: evt hand)].\\n\\n\\tmenu popUpEvent: evt in: self world! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'private' stamp: 'jm 11/4/97 07:15'!\\ncreateDrawStateFor: aHand\\n\\n\\t| pen state |\\n\\tpen _ Pen newOnForm: originalForm.\\n\\tstate _ Array new: 4.\\n\\tstate at: PenIndex put: pen.\\n\\tstate at: PenSizeIndex put: 3.\\n\\tstate at: PenColorIndex put: Color red.\\n\\tstate at: LastMouseIndex put: nil.\\n\\tdrawState at: aHand put: state.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiuserTinyPaint class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiuserTinyPaint class methodsFor: 'class initialization' stamp: 'jm 11/4/97 07:15'!\\ninitialize\\n\\t\\\"MultiuserTinyPaint initialize\\\"\\n\\n\\t\\\"indices into the state array for a given hand\\\"\\n\\tPenIndex _ 1.\\n\\tPenSizeIndex _ 2.\\n\\tPenColorIndex _ 3.\\n\\tLastMouseIndex _ 4.\\n! !\\nObject subclass: #Mutex\\n\\tinstanceVariableNames: 'semaphore owner'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!Mutex commentStamp: '<historical>' prior: 0!\\nA Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested.\\n\\nInstance variables:\\n\\tsemaphore\\t<Semaphore>\\t\\tThe (primitive) semaphore used for synchronization.\\n\\towner\\t\\t<Process>\\t\\tThe process owning the mutex.!\\n\\n\\n!Mutex methodsFor: 'initialize' stamp: 'das 11/3/2005 22:53'!\\ninitialize\\n\\tsemaphore := Semaphore forMutualExclusion.! !\\n\\n\\n!Mutex methodsFor: 'mutual exclusion' stamp: 'das 11/3/2005 22:53'!\\ncritical: aBlock\\n\\t\\\"Evaluate aBlock protected by the receiver.\\\"\\n\\t| activeProcess |\\n\\tactiveProcess := Processor activeProcess.\\n\\tactiveProcess == owner ifTrue:[^aBlock value].\\n\\t^semaphore critical:[\\n\\t\\towner := activeProcess.\\n\\t\\taBlock ensure:[owner := nil]].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMutex class\\n\\tinstanceVariableNames: ''!\\nObject subclass: #MutexSet\\n\\tinstanceVariableNames: 'array'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!MutexSet commentStamp: '<historical>' prior: 0!\\nA MutexSet helps with aquiring a set of mutexes.!\\n\\n\\n!MutexSet methodsFor: 'initialize' stamp: 'das 11/3/2005 22:54'!\\nwithAll: mutexList\\n\\tarray := mutexList.! !\\n\\n\\n!MutexSet methodsFor: 'mutual exclusion' stamp: 'das 11/3/2005 22:54'!\\ncritical: aBlock\\n\\t\\\"Evaluate aBlock aquiring all mutexes\\\"\\n\\t^self pvtCritical: aBlock startingAt: 1! !\\n\\n\\n!MutexSet methodsFor: 'private' stamp: 'das 11/3/2005 22:54'!\\npvtCritical: aBlock startingAt: index\\n\\t| mutex |\\n\\tindex > array size ifTrue:[^aBlock value].\\n\\tmutex := array at: index.\\n\\t^mutex critical:[self pvtCritical: aBlock startingAt: index+1].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMutexSet class\\n\\tinstanceVariableNames: ''!\\n\\n!MutexSet class methodsFor: 'instance creation' stamp: 'das 11/3/2005 22:54'!\\nwithAll: mutexList\\n\\t^self new withAll: mutexList! !\\nAppRegistry subclass: #MvcTextEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\n!MvcTextEditor commentStamp: 'tween 8/27/2004 12:24' prior: 0!\\nA subclass of AppRegistry which allows the user, or Browser add-ons, to control which class is used when creating the code editing view in mvc Browsers!\\n\\nError subclass: #MyResumableTestError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\n\\n!MyResumableTestError methodsFor: 'exceptionDescription' stamp: 'tfei 6/13/1999 00:46'!\\nisResumable\\n\\n\\t^true! !\\nError subclass: #MyTestError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\nNotification subclass: #MyTestNotification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\nNetworkError subclass: #NameLookupFailure\\n\\tinstanceVariableNames: 'hostName'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NameLookupFailure commentStamp: 'mir 5/12/2003 18:16' prior: 0!\\nSignals that a name lookup operation failed.\\n\\n\\thostName\\thostName for which the name loopup failed\\n!\\n\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'rbb 2/18/2005 14:27'!\\ndefaultAction\\n\\t\\\"Backward compatibility\\\"\\n\\t| response |\\n\\tresponse _ (UIManager default chooseFrom: #( 'Retry' 'Give Up')\\n\\t\\t\\ttitle: self messageText).\\n\\t^ response = 2\\n\\t\\tifFalse: [self retry]! !\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'len 12/14/2002 11:57'!\\nhostName\\n\\t^ hostName! !\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'len 12/14/2002 11:57'!\\nhostName: aString\\n\\thostName _ aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNameLookupFailure class\\n\\tinstanceVariableNames: ''!\\n\\n!NameLookupFailure class methodsFor: 'instance creation' stamp: 'len 12/14/2002 11:57'!\\nhostName: aString\\n\\t^ self new hostName: aString! !\\nObject subclass: #NameOfSubclass\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-Bugs'!\\nUpdatingStringMorph subclass: #NameStringInHalo\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n!NameStringInHalo commentStamp: 'kfr 10/27/2003 16:29' prior: 0!\\nShows the name of the morph in the halo. !\\n\\n\\n!NameStringInHalo methodsFor: 'accessing' stamp: 'sw 9/17/1999 13:17'!\\ninterimContents: aString\\n\\tself contents: aString.\\n\\tself placeContents! !\\n\\n\\n!NameStringInHalo methodsFor: 'as yet unclassified' stamp: 'di 11/25/1999 23:40'!\\nplaceContents\\n\\t| namePosition |\\n\\t(owner notNil and: [owner isInWorld]) ifTrue:\\n\\t\\t[namePosition _ owner basicBox bottomCenter -\\n\\t\\t\\t((self width // 2) @ (owner handleSize negated // 2 - 1)).\\n\\t\\tnamePosition _ namePosition min: self world viewBox bottomRight - self extent y + 2.\\n\\t\\tself bounds: (namePosition extent: self extent)]! !\\n\\n\\n!NameStringInHalo methodsFor: 'drawing' stamp: 'sw 9/7/1999 21:27'!\\ndrawOn: aCanvas\\n\\taCanvas fillRectangle: self bounds color: Color white.\\n\\tsuper drawOn: aCanvas.! !\\n\\n\\n!NameStringInHalo methodsFor: 'editing' stamp: 'sw 9/17/1999 13:41'!\\ncancelEdits\\n\\tself interimContents: target externalName.\\n\\tsuper cancelEdits! !\\nObject subclass: #NaturalLanguageFormTranslator\\n\\tinstanceVariableNames: 'id generics'\\n\\tclassVariableNames: 'CachedTranslations'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Localization'!\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:15'!\\ngenerics\\n\\t^generics ifNil: [generics := Dictionary new]! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:27'!\\nlocaleID\\n\\t^id! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:26'!\\nlocaleID: anID\\n\\tid := anID! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:17'!\\nname: formName form: translatedForm \\n\\tself generics at: formName put: translatedForm.\\n! !\\n\\n\\n!NaturalLanguageFormTranslator methodsFor: 'i/o' stamp: 'yo 1/13/2005 14:02'!\\nsaveFormsOn: aStream\\n\\n\\t| rr |\\n\\trr _ ReferenceStream on: aStream.\\n\\trr nextPut: {id isoString. generics}.\\n\\trr close.\\n! !\\n\\n\\n!NaturalLanguageFormTranslator methodsFor: 'utilities' stamp: 'yo 1/13/2005 11:35'!\\ntranslate: aString\\n\\n\\t^ (self generics\\n\\t\\tat: aString ifAbsent: [nil]) deepCopy.\\n\\n\\t\\\"Do you like to write 'form ifNotNil: [form deepCopy]'?\\\"\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNaturalLanguageFormTranslator class\\n\\tinstanceVariableNames: ''!\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\ncachedTranslations\\n\\t\\\"CachedTranslations := nil\\\" \\n\\t^CachedTranslations ifNil: [CachedTranslations := Dictionary new]! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nisoLanguage: isoLanguage\\n\\t\\\"Return the generic language translator as there is no information about the country code\\\"\\n\\n\\t^self isoLanguage: isoLanguage isoCountry: nil! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nisoLanguage: isoLanguage isoCountry: isoCountry\\n\\t^self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry)! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nlocaleID: localeID \\n\\t^ self cachedTranslations\\n\\t\\tat: localeID\\n\\t\\tifAbsentPut: [self new localeID: localeID]! !\\n\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'i/o' stamp: 'yo 1/13/2005 14:02'!\\nloadFormsFrom: aStream\\n\\n\\t| rr pair inst |\\n\\trr _ ReferenceStream on: aStream.\\n\\tpair _ rr next.\\n\\tinst _ self localeID: (LocaleID isoString: pair first).\\n\\tpair second associationsDo: [:assoc |\\n\\t\\tinst name: assoc key form: assoc value.\\n\\t].\\n\\t^ inst.\\n! !\\nObject subclass: #NaturalLanguageTranslator\\n\\tinstanceVariableNames: 'id generics contexts'\\n\\tclassVariableNames: 'AllKnownPhrases CachedTranslations'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Localization'!\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'dgd 8/13/2004 21:12'!\\ndisplayLanguage\\n\\t^ id displayLanguage! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'dgd 10/7/2004 20:50'!\\ndisplayName\\n\\t^ id displayName! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:41'!\\nisoCountry\\n\\t^self localeID isoCountry! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:42'!\\nisoLanguage\\n\\t^self localeID isoLanguage! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:42'!\\nlocaleID\\n\\t^id! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/21/2004 17:00'!\\ntranslations\\n\\t^self generics! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/21/2004 17:03'!\\nuntranslated\\n\\t| translations |\\n\\ttranslations := self translations.\\n\\t^self class allKnownPhrases reject: [:each | translations includesKey: each]! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/16/2004 11:04'!\\nfileOutHeader\\n\\t^ '''Translation dictionary'''! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/28/2004 14:50'!\\nfileOutHeaderOn: aStream \\n\\taStream nextChunkPut: self fileOutHeader;\\n\\t\\t cr.\\n\\taStream timeStamp; cr.\\n\\taStream nextPut: $!!.\\n\\taStream nextChunkPut: '(' , self class name , ' localeID: ' , id storeString , ')'.\\n\\taStream cr! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 11/29/2005 11:19'!\\nfileOutOn: aStream \\n\\t\\\"self current fileOutOn: Transcript. Transcript endEntry\\\"\\n\\tself fileOutHeaderOn: aStream.\\n\\tself fileOutOn: aStream keys: nil! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 11/29/2005 11:19'!\\nfileOutOn: aStream keys: keys \\n\\t\\\"self current fileOutOn: Transcript. Transcript endEntry\\\"\\n\\t(keys\\n\\t\\tifNil: [generics keys asSortedCollection])\\n\\t\\tdo: [:key | self\\n\\t\\t\\t\\tnextChunkPut: (generics associationAt: key)\\n\\t\\t\\t\\ton: aStream].\\n\\tkeys\\n\\t\\tifNil: [self untranslated\\n\\t\\t\\t\\tdo: [:each | self nextChunkPut: each -> '' on: aStream]].\\n\\taStream nextPut: $!!;\\n\\t\\t cr! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/16/2004 09:26'!\\nnextChunkPut: anObject on: aStream \\n\\t| i remainder terminator |\\n\\tterminator := $!!.\\n\\tremainder := anObject storeString.\\n\\t[(i := remainder indexOf: terminator) = 0]\\n\\t\\twhileFalse: [aStream\\n\\t\\t\\t\\tnextPutAll: (remainder copyFrom: 1 to: i).\\n\\t\\t\\taStream nextPut: terminator.\\n\\t\\t\\t\\\"double imbedded terminators\\\"\\n\\t\\t\\tremainder := remainder copyFrom: i + 1 to: remainder size].\\n\\taStream nextPutAll: remainder.\\n\\taStream nextPut: terminator; cr.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 12/15/2004 16:07'!\\nscanFrom: aStream \\n\\t\\\"Read a definition of dictionary. \\n\\tMake sure current locale corresponds my locale id\\\"\\n\\t| aString newTranslations assoc currentPlatform |\\n\\tnewTranslations := Dictionary new.\\n\\tcurrentPlatform := Locale currentPlatform.\\n\\t[Locale\\n\\t\\tcurrentPlatform: (Locale localeID: id).\\n\\t[aString := aStream nextChunk withSqueakLineEndings.\\n\\taString size > 0]\\n\\t\\twhileTrue: [assoc := Compiler evaluate: aString.\\n\\t\\t\\tassoc value = ''\\n\\t\\t\\t\\tifTrue: [self class registerPhrase: assoc key]\\n\\t\\t\\t\\tifFalse: [newTranslations add: assoc]]]\\n\\t\\tensure: [Locale currentPlatform: currentPlatform].\\n\\tself mergeTranslations: newTranslations! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 2/25/2005 09:37'!\\nwriteAsMimeString\\n\\n\\t| fileName fileStream tmpStream s2 gzs |\\n\\ttmpStream _ MultiByteBinaryOrTextStream on: ''.\\n\\ttmpStream converter: UTF8TextConverter new.\\n\\tself fileOutOn: tmpStream.\\n\\ts2 _ RWBinaryOrTextStream on: ''.\\n\\tgzs := GZipWriteStream on: s2.\\n\\ttmpStream reset.\\n\\tgzs nextPutAll: (tmpStream binary contentsOfEntireFile asString) contents.\\n\\tgzs close.\\n\\ts2 reset.\\n\\n\\tfileName _ id isoString, '.translation.gz.mime'.\\n\\tfileStream _ FileStream newFileNamed: fileName.\\n\\tfileStream nextPutAll: (Base64MimeConverter mimeEncode: s2) contents.\\n\\tfileStream close.\\n! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'initialize-release' stamp: 'mir 7/15/2004 14:41'!\\nlocaleID: anID\\n\\tid := anID! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'printing' stamp: 'nk 8/29/2004 10:51'!\\nprintOn: aStream\\n\\taStream nextPutAll: self class name; nextPut: $(; print: self localeID; nextPut: $)! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 7/21/2004 18:02'!\\ncheckPhrase: phrase translation: translation! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 7/30/2004 13:03'!\\nphrase: phraseString translation: translationString \\n\\tself generics at: phraseString put: translationString asString.\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 8/2/2004 12:27'!\\nrawPhrase: phraseString translation: translationString \\n\\tself generics at: phraseString put: translationString asString.\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 1/14/2005 16:25'!\\nrawRemoveUntranslated: untranslated\\n\\n\\tself class allKnownPhrases removeKey: untranslated ifAbsent: [].\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 8/1/2004 01:07'!\\nremoveTranslationFor: phraseString\\n\\tself generics removeKey: phraseString ifAbsent: [].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 1/14/2005 16:25'!\\nremoveUntranslated: untranslated\\n\\n\\tself class allKnownPhrases removeKey: untranslated ifAbsent: [].\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'em 3/23/2005 12:08'!\\ntranslate: aString\\n\\t^self generics\\n\\t\\tat: aString\\n\\t\\tifAbsent: [self class registeredPhraseFor: aString. \\n\\t\\t\\t\\t\\tself changed: #untranslated. \\n\\t\\t\\t\\t\\tself localeID hasParent\\n\\t\\t\\tifTrue: [(self class localeID: self localeID parent) translate: aString]\\n\\t\\t\\tifFalse: [aString]]! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 6/30/2004 20:22'!\\ntranslate: aString in: aContext! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 7/15/2004 14:58'!\\ntranslationFor: aString\\n\\t^self translate: aString! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'user interface' stamp: 'dgd 8/13/2004 21:54'!\\ndefaultBackgroundColor\\n\\t\\\"answer the receiver's defaultBackgroundColor for views\\\"\\n\\t^ Color cyan! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'private' stamp: 'mir 6/30/2004 20:23'!\\ngenerics\\n\\t^generics ifNil: [generics := Dictionary new]! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 7/30/2004 13:00'!\\nloadFromFileNamed: fileNameString \\n\\t\\\"Load translations from an external file\\\"\\n\\n\\t| stream |\\n\\t[stream := FileStream readOnlyFileNamed: fileNameString.\\n\\tself loadFromStream: stream]\\n\\t\\tensure: [stream close].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'tak 11/16/2004 12:37'!\\nloadFromRefStream: stream \\n\\t\\\"Load translations from an external file\\\"\\n\\t| loadedArray refStream |\\n\\trefStream := ReferenceStream on: stream.\\n\\t[loadedArray := refStream next]\\n\\t\\tensure: [refStream close].\\n\\tself processExternalObject: loadedArray ! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'em 3/30/2005 14:32'!\\nloadFromStream: stream \\n\\t\\\"Load translations from an external file\\\"\\n\\t| header isFileIn |\\n\\theader := '''Translation dictionary'''.\\n\\tisFileIn := (stream next: header size)\\n\\t\\t\\t\\t= header.\\n\\tstream reset.\\n\\tisFileIn\\n\\t\\tifTrue: [stream fileInAnnouncing: 'Loading ' translated, stream localName]\\n\\t\\tifFalse: [self loadFromRefStream: stream]! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 8/2/2004 12:27'!\\nmergeTranslations: newTranslations\\n\\t\\\"Merge a new set of translations into the exiting table.\\n\\tOverwrites existing entries.\\\"\\n\\n\\tnewTranslations keysAndValuesDo: [:key :value |\\n\\t\\tself rawPhrase: (self class registeredPhraseFor: key) translation: value].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'mir 7/15/2004 20:04'!\\nprocessExternalObject: anArray \\n\\t\\\"pivate - process the external object\\\"\\n\\n\\t\\\"new format -> {translations. untranslated}\\\"\\n\\n\\tanArray second do: [:each | self class registerPhrase: each].\\n\\n\\tself mergeTranslations: anArray first! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 2/17/2005 15:45'!\\nsaveToFileNamed: fileNameString \\n\\t\\\"save the receiver's translations to a file named fileNameString\\\"\\n\\t| stream |\\n\\t\\\"Set true if you need to save as binary\\\"\\n\\tfalse\\n\\t\\tifTrue: [stream := ReferenceStream fileNamed: fileNameString.\\n\\t\\t\\tstream nextPut: {self translations. self untranslated}.\\n\\t\\t\\tstream close.\\n\\t\\t\\t^ self].\\n\\tstream := FileStream fileNamed: fileNameString.\\n\\t[self fileOutOn: stream]\\n\\t\\tensure: [stream close]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNaturalLanguageTranslator class\\n\\tinstanceVariableNames: ''!\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 20:20'!\\navailableLanguageLocaleIDs\\n\\t\\\"Return the locale ids for the currently available languages. \\n\\tMeaning those which either internally or externally have \\n\\ttranslations available.\\\"\\n\\t\\\"NaturalLanguageTranslator availableLanguageLocaleIDs\\\"\\n\\t^ CachedTranslations values collect:[:each | each localeID]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 19:39'!\\ncurrent\\n\\t^ LocaleID current translator\\n\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'nk 8/29/2004 14:23'!\\ndefault\\n\\t^self localeID: (LocaleID default)\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:36'!\\nisoLanguage: isoLanguage\\n\\t\\\"Return the generic language translator as there is no information about the country code\\\"\\n\\n\\t^self isoLanguage: isoLanguage isoCountry: nil! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:36'!\\nisoLanguage: isoLanguage isoCountry: isoCountry\\n\\t^self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry)! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 19:18'!\\nlocaleID: localeID \\n\\t^ self cachedTranslations\\n\\t\\tat: localeID\\n\\t\\tifAbsentPut: [self new localeID: localeID]! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 8/11/2004 13:38'!\\ninitialize\\n\\t\\\"NaturalLanguageTranslator initialize\\\"\\n\\n\\tFileList registerFileReader: self.\\n\\tSmalltalk addToStartUpList: NaturalLanguageTranslator after: FileDirectory.\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 7/15/2004 19:48'!\\nresetCaches\\n\\t\\\"NaturalLanguageTranslator resetCaches\\\"\\n\\n\\tCachedTranslations := nil.\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 8/31/2005 23:37'!\\nstartUp: resuming \\n\\t| defaultID |\\n\\tresuming\\n\\t\\tifFalse: [^ self].\\n\\t\\\"\\\"\\n\\tdefaultID := LocaleID current.\\n\\tself cachedTranslations\\n\\t\\tat: defaultID\\n\\t\\tifAbsent: [self localeID: defaultID].\\n\\t\\\"\\\"\\n\\tself loadAvailableExternalLocales! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 8/11/2004 10:52'!\\nfileReaderServicesForFile: fullName suffix: suffix \\n\\t\\\"Answer the file services associated with given file\\\"\\n\\t^ (suffix = self translationSuffix) | (suffix = '*')\\n\\t\\tifTrue: [{self serviceMergeLanguageTranslations}]\\n\\t\\tifFalse: [#()]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'tak 3/14/2005 15:51'!\\nloadForLocaleIsoString: localeString fromGzippedMimeLiteral: mimeString \\n\\t\\\"merge the translation from the mime literal.\\\"\\n\\t| stream localeID translator gs rbStream s currentPlatform |\\n\\ts := Base64MimeConverter mimeDecodeToBytes: mimeString readStream.\\n\\ts reset.\\n\\tgs := GZipReadStream on: s.\\n\\trbStream := MultiByteBinaryOrTextStream with: gs contents asString.\\n\\trbStream converter: UTF8TextConverter new.\\n\\trbStream reset.\\n\\tlocaleID := LocaleID isoString: localeString.\\n\\tcurrentPlatform := Locale currentPlatform.\\n\\t[Locale\\n\\t\\tcurrentPlatform: (Locale localeID: localeID).\\n\\tstream := ReadStream on: rbStream contents]\\n\\t\\tensure: [Locale currentPlatform: currentPlatform].\\n\\ttranslator := self localeID: localeID.\\n\\ttranslator loadFromStream: stream.\\n\\tLanguageEnvironment resetKnownEnvironments! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'yo 2/24/2005 21:04'!\\nmergeTranslationFileNamed: fileFullNameString \\n\\t\\\"merge the translation in the file named fileFullNameString\\\"\\n\\n\\t| stream localeID translator |\\n\\tstream := FileStream readOnlyFileNamed: fileFullNameString.\\n\\t[localeID := LocaleID isoString: stream localName sansPeriodSuffix.\\n\\ttranslator := self localeID: localeID.\\n\\ttranslator loadFromStream: stream]\\n\\t\\tensure: [stream close].\\n\\tLanguageEnvironment resetKnownEnvironments.\\n\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 7/21/2004 13:45'!\\nserviceMergeLanguageTranslations\\n\\t\\\"Answer a service for merging of translation files\\\"\\n\\t^ SimpleServiceEntry\\n\\t\\tprovider: self\\n\\t\\tlabel: 'merge the translation file'\\n\\t\\tselector: #mergeTranslationFileNamed:\\n\\t\\tdescription: 'merge the translation file into the language named like the file'\\n\\t\\tbuttonLabel: 'merge'! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 7/21/2004 13:45'!\\nservices\\n\\t\\\"Answer potential file services associated with this class\\\"\\n\\t^ {self serviceMergeLanguageTranslations}! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/15/2004 19:58'!\\nallKnownPhrases\\n\\t^AllKnownPhrases ifNil: [AllKnownPhrases := Dictionary new: 2051]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/13/2004 00:06'!\\ncachedTranslations\\n\\t\\\"CachedTranslations := nil\\\" \\n\\t^CachedTranslations ifNil: [CachedTranslations := Dictionary new]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 8/31/2005 16:55'!\\ncleanUpCache\\n\\t\\\"NaturalLanguageTranslator cleanUpCache\\\"\\n\\n\\tself cachedTranslations keys do: [:key |\\n\\t\\tkey isoLanguage size > 2 ifTrue: [self cachedTranslations removeKey: key]]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/15/2004 20:02'!\\nregisterPhrase: phrase\\n\\t\\\"Using a Dictionary so we can lookup existing string instead of creating needless copies when loading a translation.\\\"\\n\\tself allKnownPhrases at: phrase put: phrase! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/21/2004 14:18'!\\nregisteredPhraseFor: phrase\\n\\t\\\"Using a Dictionary so we can lookup existing string instead of creating needless copies when loading a translation.\\\"\\n\\t^self allKnownPhrases at: phrase ifAbsentPut: [phrase]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 8/11/2004 10:52'!\\ntranslationSuffix\\n\\t^'translation'! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'nk 8/21/2004 13:03'!\\ndirectoryForLanguage: isoLanguage country: isoCountry create: createDir\\n\\t\\\"Try to locate the <prefs>/locale/<language>{/<country>} folder.\\n\\tIf createDir is set, create the path down to country or language, depending on wether it's specified..\\n\\tReturn the directory for country or language depending on specification.\\n\\tIf neither exists, nil\\\"\\n\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'es' country: nil create: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: 'DE' create: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: 'US' create: false\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: nil create: true\\\"\\n\\n\\t\\\"If this fails, there is nothing we can do about it here\\\"\\n\\t| localeDir countryDir languageDir |\\n\\tlocaleDir := self localeDirCreate: createDir.\\n\\tlocaleDir ifNil: [^nil].\\n\\n\\tisoCountry ifNil: [\\n\\t\\tlanguageDir := localeDir directoryNamed: isoLanguage.\\n\\t\\tcreateDir\\n\\t\\t\\tifTrue: [languageDir assureExistence].\\n\\t\\t^languageDir exists\\n\\t\\t\\tifTrue: [languageDir]\\n\\t\\t\\tifFalse: [nil]].\\n\\n\\tcountryDir := languageDir directoryNamed: isoCountry.\\n\\tcreateDir\\n\\t\\tifTrue: [countryDir assureExistence].\\n\\n\\t^countryDir exists\\n\\t\\tifTrue: [countryDir]\\n\\t\\tifFalse: [nil]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/11/2004 10:44'!\\ndirectoryForLocaleID: localeID create: createDir\\n\\t\\\"Try to locate the <prefs>/locale/<language>{/<country>} folder.\\n\\tIf createDir is set, create the path down to country or language, depending on locale.\\n\\tReturn the directory for country or language depending on locale.\\n\\tIf neither exists, nil\\\"\\n\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: nil readOnly: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: 'DE' readOnly: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: 'US' readOnly: false\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: nil readOnly: true\\\"\\n\\n\\t^self directoryForLanguage: localeID isoLanguage country: localeID isoCountry create: createDir! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 11:57'!\\nloadAvailableExternalLocales\\n\\t\\\"private - register locales IDs based on the content of the <prefs>/locale/ directory\\\"\\n\\t| localeDir |\\n\\tlocaleDir := self localeDirCreate: false.\\n\\tlocaleDir ifNil: [^ #()].\\n\\n\\tlocaleDir directoryNames\\n\\t\\tdo: [:langDirName | \\n\\t\\t\\t| langDir | \\n\\t\\t\\tlangDir := localeDir directoryNamed: langDirName.\\n\\n\\t\\t\\t(langDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\t\\t\\tifNotEmpty: [self loadTranslatorForIsoLanguage: langDirName isoCountry: nil].\\n\\n\\t\\t\\tlangDir directoryNames\\n\\t\\t\\t\\tdo: [:countryDirName | \\n\\t\\t\\t\\t\\t| countryDir | \\n\\t\\t\\t\\t\\tcountryDir := langDirName directoryNamed: countryDirName.\\n\\t\\t\\t\\t\\t(countryDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\t\\t\\t\\t\\tifNotEmpty: [self loadTranslatorForIsoLanguage: langDirName isoCountry: countryDirName]\\n\\t\\t\\t]\\n\\t\\t].\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'nk 8/21/2004 13:00'!\\nloadExternalTranslationsFor: translator\\n\\t\\\"Try to load translations from external external files.\\n\\tThe files are located in the <prefs>/locale/<language>{/<country>} folder.\\n\\tThere can be more than one file for each location, so applications can install their own partial translation tables. All files in the specific folder are loaded.\\\"\\n\\n\\t| translationDir |\\n\\ttranslationDir := self directoryForLocaleID: translator localeID create: false.\\n\\ttranslationDir ifNil: [ ^nil ]. \\n\\t(translationDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\tdo: [:fileName | translator loadFromFileNamed: (translationDir fullNameFor: fileName)]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 11:59'!\\nloadTranslatorForIsoLanguage: isoLanguage isoCountry: isoCountry \\n\\t\\\"private - load the translations from <prefs>/locale/ directory \\n\\tthe procedure is to assure the existence of a translator for the \\n\\tgiven language/country and then load the external translations for this translator\\\"\\n\\n\\t| translator |\\n\\ttranslator := self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry).\\n\\n\\tself loadExternalTranslationsFor: translator! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 12:03'!\\nlocaleDirCreate: createDir\\n\\t\\\"Try to locate the <prefs>/locale/ folder.\\n\\tIf createDir is set, try to create the path.\\n\\tIf it doesn't exist, return nil\\\"\\n\\n\\t\\\"If this fails, there is nothing we can do about it here\\\"\\n\\t| prefDir localeDir |\\n\\t(createDir not\\n\\t\\t\\tand: [ExternalSettings preferenceDirectory isNil])\\n\\t\\tifTrue: [^ nil].\\n\\n\\tprefDir := ExternalSettings assuredPreferenceDirectory.\\n\\tprefDir exists\\n\\t\\tifFalse: [^nil].\\n\\n\\n\\tlocaleDir := prefDir directoryNamed: 'locale'.\\n\\tcreateDir\\n\\t\\tifTrue: [localeDir assureExistence].\\n\\t^localeDir exists\\n\\t\\tifTrue: [localeDir]\\n\\t\\tifFalse: [nil]! !\\nObject subclass: #NebraskaClient\\n\\tinstanceVariableNames: 'connection encoder hand canvas'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaClient commentStamp: '<historical>' prior: 0!\\nA client that has connected to a Nebraska server, seen from the server's point of view.!\\n\\n\\n!NebraskaClient methodsFor: 'as yet unclassified' stamp: 'RAA 7/31/2000 23:59'!\\nbacklog\\n\\n\\t^connection backlog! !\\n\\n!NebraskaClient methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:30'!\\ncurrentStatusString\\n\\n\\t(connection isNil or: [connection isConnected not]) ifTrue: [^'nada'].\\n\\t^(NetNameResolver stringFromAddress: connection remoteAddress),\\n\\t\\t' - ',\\n\\t\\t(self backlog // 1024) printString,'k'! !\\n\\n\\n!NebraskaClient methodsFor: 'attributes' stamp: 'ls 3/25/2000 22:27'!\\ncanvas\\n\\t\\\"return the hand this canvas that should be drawn on for this client\\\"\\n\\t^canvas! !\\n\\n!NebraskaClient methodsFor: 'attributes' stamp: 'ls 3/25/2000 22:27'!\\nhand\\n\\t\\\"return the hand this client is controlling\\\"\\n\\t^hand! !\\n\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\nconvertToBuffered\\n\\n\\tcanvas purgeOutputQueue.\\n\\tcanvas := canvas asBufferedCanvas.! !\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ndestroy\\n\\thand ifNotNil:[hand world ifNotNil:[hand world removeHand: hand]].\\n\\tconnection ifNotNil:[connection destroy].\\n\\tencoder := canvas := hand := connection := nil.! !\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitialize: aConnection\\n\\n\\t| remoteAddress userPicture |\\n\\n\\tconnection := aConnection.\\n\\thand := RemoteControlledHandMorph on: (MorphicEventDecoder on: aConnection).\\n\\thand nebraskaClient: self.\\n\\tremoteAddress := connection remoteAddress.\\n\\tremoteAddress ifNotNil: [remoteAddress := NetNameResolver stringFromAddress: remoteAddress].\\n\\tuserPicture := EToySenderMorph pictureForIPAddress: remoteAddress.\\n\\thand\\n\\t\\tuserInitials: ((EToySenderMorph nameForIPAddress: remoteAddress) ifNil: ['???'])\\n\\t\\tandPicture: (userPicture ifNotNil: [userPicture scaledToSize: 16@20]).\\n\\tencoder := CanvasEncoder on: aConnection.\\n\\tcanvas := RemoteCanvas\\n\\t\\tconnection: encoder\\n\\t\\tclipRect: NebraskaServer extremelyBigRectangle\\n\\t\\ttransform: MorphicTransform identity! !\\n\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 4/9/2000 14:43'!\\nextent: newExtent depth: newDepth\\n\\tencoder extent: newExtent depth: newDepth! !\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 3/25/2000 22:25'!\\nisConnected\\n\\t^connection isConnected! !\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 3/25/2000 22:25'!\\nprocessIO\\n\\tconnection processIO.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaClient class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaClient class methodsFor: 'instance creation' stamp: 'ls 3/25/2000 22:28'!\\nonConnection: aStringSocket\\n\\t^self new initialize: aStringSocket! !\\nObject subclass: #NebraskaDebug\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DEBUG Details'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaDebug commentStamp: '<historical>' prior: 0!\\nBufferedCanvas enabled: false.\\nBufferedCanvas enabled: true.\\n\\nNebraskaDebug beginStats\\nNebraskaDebug showStats\\nNebraskaDebug stopAndShowAll\\nNebraskaDebug killStats\\nStringSocket showRatesSeen\\nStringSocket clearRatesSeen\\nNebraskaDebug showAndClearStats: #allStats\\nNebraskaDebug showAndClearStats: #queuedbufferSizes\\n\\n\\nCanvasEncoder beginStats\\nCanvasEncoder showStats\\nCanvasEncoder killStats\\nNebraskaDebug showStats: #peerBytesSent\\nNebraskaDebug showStats: #soundReductionTime\\nNebraskaDebug showStats: #FormEncodeTimes\\nNebraskaDebug showStats: #SendReceiveStats\\nNebraskaDebug showStats: #sendDeltas\\nNebraskaDebug showStats: #bigImage\\nNebraskaDebug showStats: #sketch\\nNebraskaDebug showStats: #addToOutBuf:\\n----\\nbuffered off, painting 125kb/s, dragging 400kb/s\\nbuffered on, painting 100kb/s, dragging 170kb/s!\\n]style[(62 142 14 78 17 3 73 415)f1cblue;,f1cblack;,f1,f1cblack;,f1cred;,f1cblack;,f1cblue;,f1cblack;!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaDebug class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nat: queueName add: anArray\\n\\n\\t| now |\\n\\n\\tDEBUG ifNil: [\\n\\t\\tqueueName == #sketchZZZ ifFalse: [^self].\\n\\t\\t\\\"Details := OrderedCollection new.\\\"\\n\\t\\tself beginStats.\\n\\t].\\n\\t(Details notNil and: [Details size < 20]) ifTrue: [\\n\\t\\tDetails add: thisContext longStack\\n\\t].\\n\\tnow := Time millisecondClockValue.\\n\\tDEBUG add: {now},anArray,{queueName}.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nbeginStats\\n\\n\\tDEBUG := OrderedCollection new! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nkillStats\\n\\n\\tDEBUG := nil.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowAndClearStats: queueName\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tself \\n\\t\\tshowStats: queueName \\n\\t\\tfrom: DEBUG.\\n\\tDEBUG := nil.! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'nb 6/17/2003 12:25'!\\nshowStats\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tDEBUG explore.! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'nb 6/17/2003 12:25'!\\nshowStats: queueName\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tself \\n\\t\\tshowStats: queueName \\n\\t\\tfrom: DEBUG.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowStats: queueName from: aCollection\\n\\n\\t| xx answer prevTime currTime |\\n\\n\\tprevTime := nil.\\n\\tanswer := String streamContents: [ :s | \\n\\t\\ts nextPutAll: (aCollection last first - aCollection first first) asStringWithCommas,' ms';cr;cr.\\n\\t\\taCollection withIndexDo: [ :each :index | \\n\\t\\t\\t(queueName == #allStats or: [queueName == each last]) ifTrue: [\\n\\t\\t\\t\\tcurrTime := each first.\\n\\t\\t\\t\\txx := currTime printString.\\n\\t\\t\\t\\tprevTime ifNil: [prevTime := currTime].\\n\\t\\t\\t\\ts nextPutAll: index printString,'. ',\\n\\t\\t\\t\\t\\t(xx allButLast: 3),'.',(xx last: 3),' ',(currTime - prevTime) printString,' '.\\n\\t\\t\\t\\ts nextPutAll: each allButFirst printString; cr.\\n\\t\\t\\t\\tprevTime := currTime.\\n\\t\\t\\t].\\n\\t\\t]\\n\\t].\\n\\tStringHolder new \\n\\t\\tcontents: answer;\\n\\t\\topenLabel: queueName! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nstopAndShowAll\\n\\n\\t| prev |\\n\\nself halt.\\t\\\"not updated to new format\\\"\\n\\n\\tprev := DEBUG.\\n\\tDEBUG := nil.\\n\\tprev ifNil: [^Beeper beep].\\n\\tprev keysAndValuesDo: [ :k :v |\\n\\t\\tself showStats: k from: v\\n\\t].! !\\nProjectNavigationMorph subclass: #NebraskaNavigationMorph\\n\\tinstanceVariableNames: 'nebraskaBorder nebraskaTerminal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:49'!\\naddButtons\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {self buttonScale}.\\n\\t\\tself inAColumn: {self buttonQuit}.\\n\\t\\tself inAColumn: {self buttonBuffered}.\\n\\t}.\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:26'!\\nbufferNebraska\\n\\n\\tnebraskaTerminal requestBufferedConnection\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:23'!\\nbuttonBuffered\\n\\n\\t^self makeButton: 'B' balloonText: 'Request buffered Nebraska session' for: #bufferNebraska\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:34'!\\nbuttonScale\\n\\n\\t^self makeButton: '1x1' balloonText: 'Switch between 1x1 and scaled view' for: #toggleFullView\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:47'!\\ncurrentNavigatorVersion\\n\\n\\t^1\\t\\t\\\"not particularly relevant here\\\"! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'yo 11/4/2002 21:06'!\\nfontForButtons\\n\\n\\t^ TextStyle defaultFont.\\n\\t\\\"^Preferences standardButtonFont\\\"! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\nnebraskaBorder: aNebraskaBorder\\n\\n\\tnebraskaBorder := aNebraskaBorder! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\nnebraskaTerminal: aNebraskaTerminal\\n\\n\\tnebraskaTerminal := aNebraskaTerminal! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\npositionVertically\\n\\n\\t| w |\\n\\tw := self world ifNil: [^self].\\n\\tself top < w top ifTrue: [self top: w top].\\n\\tself bottom > w bottom ifTrue: [self bottom: w bottom].! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:47'!\\nquitNebraska\\n\\n\\tnebraskaBorder ifNotNil: [nebraskaBorder delete].\\n\\tself delete.! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:48'!\\ntoggleFullView\\n\\n\\tnebraskaBorder ifNotNil: [nebraskaBorder toggleFullView]! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'dropping/grabbing' stamp: 'RAA 11/8/2000 11:42'!\\nwantsToBeDroppedInto: aMorph\\n\\n\\t\\\"avoid difficulties in placement\\\"\\n\\t^(aMorph isKindOf: NetworkTerminalMorph) not! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'initialization' stamp: 'dgd 2/16/2003 14:11'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color yellow ! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'stepping and presenter' stamp: 'RAA 11/8/2000 11:37'!\\nstep\\n\\n\\tsuper step.\\n\\t(nebraskaBorder isNil or: [nebraskaBorder world isNil]) ifTrue: [self delete].! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'the buttons' stamp: 'RAA 11/8/2000 11:36'!\\nbuttonQuit\\n\\n\\t^self makeButton: 'Quit' balloonText: 'Quit this Nebraska session' for: #quitNebraska\\n! !\\nModel subclass: #NebraskaServer\\n\\tinstanceVariableNames: 'worldDepth world clients listenQueue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaServer commentStamp: '<historical>' prior: 0!\\nA Nebraska server has a private world and some collection of clients. It associates a RemoteControlledHand for each client. Redraw events in the world are broadcasted to all connected clients. A Nebraska server can listen on a TCP/IP port and accept new clients. Current version has been modified so that the server serves the world in which it was launched. Other variations are certainly possible.\\n\\nTo start a server, execute the following code:\\n\\tNebraskaServerMorph serveWorld: World\\n\\nTo start a client, run the following in another image:\\n\\tNetworkTerminalMorph openAndConnectTo: 'servername'\\n\\nFill in your server's hostname for 'servername'. At this point, everything should be working!!\\n\\nBefore starting a server, you can tweak these:\\nBufferedCanvas enabled: false.\\nBufferedCanvas enabled: true.\\n\\nAt any time you can do these:\\nNebraskaDebug beginStats\\nNebraskaDebug showStats\\nNebraskaDebug showStats: #delays\\nNebraskaDebug showStats: #bigImage\\nNebraskaDebug showStats: #FormEncodeTimes\\nNebraskaDebug killStats\\n\\nNOTE: if you want to have a local view of the server, you shouldn't use the TCP connections. The problem is that the server will occasionally do a #flush, and it won't work due to single threading. The better solution is to use a LoopBackStringSocket instead of a regular StringSocket, but there is no handy method for that right now....\\n\\n\\n!\\n]style[(266 136 49 39 56 53 96 46 1 62 29 525)f1,f1cred;,f1,f1cblue;,f1,f1cblue;,f1,f1cblue;,f1,f1cred;,f1cblue;,f1!\\n\\n\\n!NebraskaServer methodsFor: 'accessing' stamp: 'ar 10/26/2000 14:23'!\\nclients\\n\\t^clients ifNil:[#()].! !\\n\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 4/11/2000 19:48'!\\nextent: newExtent depth: newDepth\\n\\t\\\"modify the extent and/or depth of the shared world\\\"\\n\\tclients do: [ :client |\\n\\t\\tclient extent: newExtent depth: newDepth ].\\n\\tworld extent: newExtent.\\n\\n\\tworldDepth := newDepth.! !\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 4/11/2000 18:41'!\\nnumClients\\n\\t\\\"return the number of connected clients\\\"\\n\\t^clients size! !\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 3/25/2000 23:13'!\\nsharedWorld\\n\\t^world! !\\n\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'ar 10/26/2000 14:02'!\\ndestroy\\n\\tself stopListening.\\n\\tclients do:[:each| each destroy].\\n\\tself breakDependents.! !\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'ar 10/26/2000 14:20'!\\ninitialize\\n\\tclients := IdentitySet new.\\n\\tself extent: 800@600 depth: 16.! !\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitializeForWorld: aWorld\\n\\n\\tworld := aWorld.\\n\\tclients := IdentitySet new.\\n\\tself extent: world extent depth: Display depth.\\n\\taWorld remoteServer: self.! !\\n\\n\\n!NebraskaServer methodsFor: 'menus' stamp: 'RAA 7/31/2000 22:28'!\\nstep\\n\\n\\tself processIO.\\n\\n\\t\\\"savedWorld := Processor activeProcess world.\\n\\tProcessor activeProcess setWorld: world.\\\"\\n\\n\\tself flag: #bob.\\t\\t\\\"in this version, world is THE WORLD, so it steps itself\\\"\\n\\t\\\"world doOneCycle.\\\"\\n\\n\\t\\\"Processor activeProcess setWorld: savedWorld.\\\"\\n\\n\\tclients do: [ :each | each canvas apply: [ :ignore | ]].\\t\\\"for modes that need a little push\\\"\\n! !\\n\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:35'!\\nacceptNewConnections\\n\\t| connection |\\n\\tlistenQueue ifNil: [ ^self ].\\n\\t[ clients size > 20 ifTrue: [ \\\"too many connections!!\\\" ^self ].\\n\\t connection := listenQueue getConnectionOrNil. \\n\\t connection isNil ] \\n\\twhileFalse: [\\n\\t self addClientFromConnection: (StringSocket on: connection) ].! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'sd 11/20/2005 21:25'!\\nacceptNullConnection\\n\\n\\t| twins |\\n\\n\\ttwins := LoopbackStringSocket newPair.\\n\\tself addClientFromConnection: twins first.\\n\\t(NullTerminalMorph new connection: twins second) openInWorld.\\n! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'sd 11/20/2005 21:25'!\\nacceptPhonyConnection\\n\\n\\t| twins |\\n\\n\\ttwins := LoopbackStringSocket newPair.\\n\\tself addClientFromConnection: twins first.\\n\\t(NetworkTerminalMorph new connection: twins second) inspect \\\"openInWorld\\\".\\n! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'RAA 7/20/2000 10:03'!\\naddClientFromConnection: connection\\n\\t| client |\\n\\n\\tclient := NebraskaClient onConnection: connection.\\n\\tclients add: client.\\n\\tclient extent: world extent depth: worldDepth.\\n\\tworld addRemoteClient: client.\\n\\tself changed: #numClients.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'RAA 8/1/2000 00:01'!\\nbacklog\\n\\n\\t^clients inject: 0 into: [ :max :each | max max: each backlog]! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:36'!\\nprocessIO\\n\\tself pruneDeadConnections.\\n\\tself acceptNewConnections.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ar 10/26/2000 14:20'!\\npruneDeadConnections\\n\\t| deadConnections |\\n\\tdeadConnections := clients select: [ :client | client isConnected not ].\\n\\tdeadConnections do: [ :client |\\n\\t\\tworld removeRemoteClient: client].\\n\\n\\tdeadConnections isEmpty ifTrue:[ ^self ].\\n\\n\\tclients removeAll: deadConnections.\\n\\tself changed: #numClients.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:31'!\\nstartListeningOnPort: portNumber\\n\\tSocket initializeNetwork.\\n\\tself stopListening.\\n\\tlistenQueue := ConnectionQueue portNumber: portNumber queueLength: 5.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:32'!\\nstopListening\\n\\tlistenQueue ifNil: [ ^self ].\\n\\tlistenQueue destroy.\\n\\tlistenQueue := nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaServer class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaServer class methodsFor: 'as yet unclassified' stamp: 'RAA 7/24/2000 12:06'!\\ndefaultPort\\n\\n\\t^9091! !\\n\\n!NebraskaServer class methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 14:59'!\\nextremelyBigRectangle\\n\\n\\t^(0@0 extent: 5000@5000)! !\\n\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'mu 11/28/2003 19:38'!\\nnewForWorld: aWorld\\n\\n\\t^self basicNew initializeForWorld: aWorld! !\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 14:00'!\\nserveWorld: aWorld\\n\\n\\t^self serveWorld: aWorld onPort: self defaultPort! !\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nserveWorld: aWorld onPort: aPortNumber\\n\\n\\t| server |\\n\\n\\tUtilities authorName.\\t\\\"since we will need it later\\\"\\n\\n\\tserver := self newForWorld: aWorld.\\n\\tserver startListeningOnPort: aPortNumber.\\n\\t^server\\n\\t\\\"server acceptNullConnection\\\"\\t\\t\\\"server acceptPhonyConnection.\\\"\\n! !\\nAlignmentMorphBob1 subclass: #NebraskaServerMorph\\n\\tinstanceVariableNames: 'server slowCounter previousBacklog lastFullUpdateTime currentStatusString fullDisplay previousClients currentBacklogString'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaServerMorph commentStamp: '<historical>' prior: 0!\\nA cheezy morph that simply steps a Nebraska server instance over and over.!\\n\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'RAA 5/31/2001 15:03'!\\ncurrentBacklogString\\n\\n\\t^currentBacklogString! !\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'RAA 11/8/2000 16:07'!\\ncurrentStatusString\\n\\n\\t^currentStatusString! !\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'ar 10/26/2000 14:05'!\\nserver\\n\\t^self world remoteServer! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:25'!\\nupdateCurrentStatusString\\n\\n\\tself server ifNil:[\\n\\t\\tcurrentStatusString := '<Nebraska not active>' translated.\\n\\t\\tcurrentBacklogString := ''.\\n\\t] ifNotNil:[\\n\\t\\tcurrentStatusString := \\n\\t\\t\\t' Nebraska: ' translated, \\n\\t\\t\\tself server numClients printString, \\n\\t\\t\\t' clients' translated.\\n\\t\\tcurrentBacklogString := 'backlog: ' translated,\\n\\t\\t\\t\\t((previousBacklog := self server backlog) // 1024) printString,'k'\\n\\t].\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color white! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tfullDisplay := false.\\n\\t\\n\\tlastFullUpdateTime := 0.\\n\\tself listDirection: #topToBottom;\\n\\t\\t hResizing: #shrinkWrap;\\n\\t\\t vResizing: #shrinkWrap! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\nrebuild\\n\\n\\t| myServer toggle closeBox font |\\n\\n\\tfont := StrikeFont familyName: #Palatino size: 14.\\n\\tself removeAllMorphs.\\n\\tself setColorsAndBorder.\\n\\tself updateCurrentStatusString.\\n\\ttoggle := SimpleHierarchicalListMorph new perform: (\\n\\t\\tfullDisplay ifTrue: [#expandedForm] ifFalse: [#notExpandedForm]\\n\\t).\\n\\tcloseBox := SimpleButtonMorph new borderWidth: 0;\\n\\t\\t\\tlabel: 'X' font: Preferences standardButtonFont; color: Color transparent;\\n\\t\\t\\tactionSelector: #delete; target: self; extent: 14@14;\\n\\t\\t\\tsetBalloonText: 'End Nebrasks session'.\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {closeBox}.\\n\\t\\tself inAColumn: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: self;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentStatusString;\\n\\t\\t\\t\\tcontents: self currentStatusString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}.\\n\\t\\tself inAColumn: {\\n\\t\\t\\ttoggle asMorph\\n\\t\\t\\t\\ton: #mouseUp send: #toggleFull to: self;\\n\\t\\t\\t\\tsetBalloonText: 'Show more or less of Nebraska Status'\\n\\t\\t}.\\n\\t}.\\n\\tmyServer := self server.\\n\\t(myServer isNil or: [fullDisplay not]) ifTrue: [\\n\\t\\t^World startSteppingSubmorphsOf: self\\n\\t].\\n\\t\\\"--- the expanded display ---\\\"\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: self;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentBacklogString;\\n\\t\\t\\t\\tcontents: self currentBacklogString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\t(StringMorph contents: '--clients--' translated) lock; font: font.\\n\\t\\t}.\\n\\t}.\\n\\n\\tmyServer clients do: [ :each |\\n\\t\\tself addARow: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: each;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentStatusString;\\n\\t\\t\\t\\tcontents: each currentStatusString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}\\n\\t].\\n\\tWorld startSteppingSubmorphsOf: self.! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'aoy 2/15/2003 21:35'!\\nsetColorsAndBorder\\n\\t| worldColor c |\\n\\tc := ((Preferences menuColorFromWorld and: [Display depth > 4]) \\n\\t\\t\\t\\tand: [(worldColor := self currentWorld color) isColor]) \\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[worldColor luminance > 0.7 \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [worldColor mixed: 0.8 with: Color black]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [worldColor mixed: 0.4 with: Color white]]\\n\\t\\t\\t\\t\\tifFalse: [Preferences menuColor]. \\n\\tself color: c.\\n\\tself borderColor: #raised.\\n\\tself borderWidth: Preferences menuBorderWidth.\\n\\tself useRoundedCorners! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ntoggleFull\\n\\n\\tfullDisplay := fullDisplay not.\\n\\tself rebuild.\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'stepping and presenter' stamp: 'sd 11/20/2005 21:25'!\\nstep\\n\\n\\t| now |\\n\\n\\tself server ifNil: [ ^self ].\\n\\tself server step.\\n\\tnow := Time millisecondClockValue.\\n\\t(now - lastFullUpdateTime) abs > 5000 ifTrue: [\\n\\t\\tlastFullUpdateTime := now.\\n\\t\\t(previousBacklog = self server backlog and: [self server clients = previousClients]) ifFalse: [\\n\\t\\t\\tpreviousClients := self server clients copy.\\n\\t\\t\\tself rebuild\\n\\t\\t]\\n\\t].\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'submorphs-add/remove' stamp: 'ar 10/26/2000 14:07'!\\ndelete\\n\\tself server ifNotNil:[\\n\\t\\t(self confirm:'Shutdown the server?') \\n\\t\\t\\tifTrue:[self world remoteServer: nil]].\\n\\tsuper delete.! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'testing' stamp: 'RAA 11/8/2000 15:57'!\\nstepTime\\n\\n\\t^10! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'updating' stamp: 'RAA 11/8/2000 16:03'!\\nupdate: aSymbol\\n\\n\\tself rebuild.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaServerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 8/15/2000 14:49'!\\nkillOldServers\\n\\n\\tNebraskaServerMorph allInstances do: [ :each |\\n\\t\\teach delete.\\n\\t].\\n\\tNebraskaServer allInstances do: [ :each |\\n\\t\\teach stopListening.\\n\\t\\tDependentsFields removeKey: each ifAbsent: [].\\n\\t].\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:06'!\\nserveWorld\\n\\n\\t^ self serveWorld: ActiveWorld.\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:07'!\\nserveWorldButton\\n\\n\\t| button |\\n\\tbutton _ ScriptableButton new.\\n\\tbutton target: NebraskaServerMorph.\\n\\tbutton actionSelector: #serveWorld.\\n\\tbutton arguments: #().\\n\\tbutton label: 'Share'.\\n\\tbutton color: Color yellow.\\n\\t^ button.\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'wiz 1/9/2005 15:12'!\\nserveWorld: aWorld\\n\\t\\\"Check to make sure things won't crash. See Mantis #0000519\\\"\\n\\taWorld isSafeToServe ifTrue:[\\n\\t\\t^self serveWorld: aWorld onPort: NebraskaServer defaultPort]\\n\\t! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'ar 10/26/2000 14:05'!\\nserveWorld: aWorld onPort: aPortNumber\\n\\n\\t| server |\\n\\tserver := NebraskaServer serveWorld: aWorld onPort: aPortNumber.\\n\\t(self new) openInWorld: aWorld.\\n\\n\\t\\\"server acceptNullConnection\\\"\\t\\t\\\"server acceptPhonyConnection.\\\"\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:08'!\\nsupplementaryPartsDescriptions\\n\\t^ {DescriptionForPartsBin\\n\\t\\tformalName: 'NebraskaServer'\\n\\t\\tcategoryList: #('Collaborative')\\n\\t\\tdocumentation: 'A button to start the Nebraska desktop sharing server' translated\\n\\t\\tglobalReceiverSymbol: #NebraskaServerMorph\\n\\t\\tnativitySelector: #serveWorldButton\\n\\t}! !\\nObject subclass: #NetNameResolver\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DefaultHostName HaveNetwork ResolverBusy ResolverError ResolverMutex ResolverReady ResolverSemaphore ResolverUninitialized'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NetNameResolver commentStamp: '<historical>' prior: 0!\\nThis class implements TCP/IP style network name lookup and translation facilities.\\n\\nAttempt to keep track of whether there is a network available.\\nHaveNetwork\\ttrue if last attempt to contact the network was successful.\\nLastContact\\t\\tTime of that contact (totalSeconds).\\nhaveNetwork\\treturns true, false, or #expired. True means there was contact in the last 30 minutes. False means contact failed or was false last time we asked. Get out of false state by making contact with a server in some way (FileList or updates).!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNetNameResolver class\\n\\tinstanceVariableNames: ''!\\n\\n!NetNameResolver class methodsFor: 'address string utils' stamp: 'jm 9/15/97 06:19'!\\naddressFromString: addressString\\n\\t\\\"Return the internet address represented by the given string. The string should contain four positive decimal integers delimited by periods, commas, or spaces, where each integer represents one address byte. Return nil if the string is not a host address in an acceptable format.\\\"\\n\\t\\\"NetNameResolver addressFromString: '1.2.3.4'\\\"\\n\\t\\\"NetNameResolver addressFromString: '1,2,3,4'\\\"\\n\\t\\\"NetNameResolver addressFromString: '1 2 3 4'\\\"\\n\\n\\t| newAddr s byte delimiter |\\n\\tnewAddr _ ByteArray new: 4.\\n\\ts _ ReadStream on: addressString.\\n\\ts skipSeparators.\\n\\t1 to: 4 do: [:i |\\n\\t\\tbyte _ self readDecimalByteFrom: s.\\n\\t\\tbyte = nil ifTrue: [^ nil].\\n\\t\\tnewAddr at: i put: byte.\\n\\t\\ti < 4 ifTrue: [\\n\\t\\t\\tdelimiter _ s next.\\n\\t\\t\\t((delimiter = $.) or: [(delimiter = $,) or: [delimiter = $ ]])\\n\\t\\t\\t\\tifFalse: [^ nil]]].\\n\\t^ newAddr\\n! !\\n\\n!NetNameResolver class methodsFor: 'address string utils' stamp: 'jm 9/15/97 16:52'!\\nstringFromAddress: addr\\n\\t\\\"Return a string representing the given host address as four decimal bytes delimited with decimal points.\\\"\\n\\t\\\"NetNameResolver stringFromAddress: NetNameResolver localHostAddress\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: ''.\\n\\t1 to: 3 do: [ :i | (addr at: i) printOn: s. s nextPut: $.].\\n\\t(addr at: 4) printOn: s.\\n\\t^ s contents\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'class initialization' stamp: 'jm 9/17/97 16:18'!\\ninitialize\\n\\t\\\"NetNameResolver initialize\\\"\\n\\t\\\"Note: On the Mac, the name resolver is asynchronous (i.e., Squeak can do other things while it is working), but can only handle one request at a time. On other platforms, such as Unix, the resolver is synchronous; a call to, say, the name lookup primitive will block all Squeak processes until it returns.\\\"\\n\\n\\t\\\"Resolver Status Values\\\"\\n\\tResolverUninitialized _ 0.\\t\\\"network is not initialized\\\"\\n\\tResolverReady _ 1.\\t\\t\\t\\\"resolver idle, last request succeeded\\\"\\n\\tResolverBusy _ 2.\\t\\t\\t\\\"lookup in progress\\\"\\n\\tResolverError _ 3.\\t\\t\\t\\\"resolver idle, last request failed\\\"\\n\\n\\tDefaultHostName _ ''.\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'ls 9/5/1998 01:14'!\\naddressForName: aString\\n\\t^self addressForName: aString timeout: 60! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mu 9/7/2003 22:53'!\\naddressForName: hostName timeout: secs\\n\\t\\\"Look up the given host name and return its address. Return nil if the address is not found in the given number of seconds.\\\"\\n\\t\\\"NetNameResolver addressForName: 'create.ucsb.edu' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '100000jobs.de' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '1.7.6.4' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '' timeout: 30 (This seems to return nil?)\\\"\\n\\n\\t| deadline result |\\n\\tself initializeNetwork.\\n\\t\\\"check if this is a valid numeric host address (e.g. 1.2.3.4)\\\"\\n\\tresult _ self addressFromString: hostName.\\n\\tresult isNil ifFalse: [^result].\\n\\n\\t\\\"Look up a host name, including ones that start with a digit (e.g. 100000jobs.de or squeak.org)\\\"\\n\\tdeadline _ Time millisecondClockValue + (secs * 1000).\\n\\t\\\"Protect the execution of this block, as the ResolverSemaphore is used for both parts of the transaction.\\\"\\n\\tself resolverMutex\\n\\t\\tcritical: [\\n\\t\\t\\t(self waitForResolverReadyUntil: deadline)\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself primStartLookupOfName: hostName.\\n\\t\\t\\t\\t\\t(self waitForCompletionUntil: deadline)\\n\\t\\t\\t\\t\\t\\tifTrue: [result _ self primNameLookupResult]\\n\\t\\t\\t\\t\\t\\tifFalse: [(NameLookupFailure hostName: hostName) signal: 'Could not resolve the server named: ', hostName]]\\n\\t\\t\\t\\tifFalse: [(NameLookupFailure hostName: hostName) signal: 'Could not resolve the server named: ', hostName]].\\n\\t^result! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'jm 9/15/97 16:52'!\\nlocalAddressString\\n\\t\\\"Return a string representing the local host address as four decimal bytes delimited with decimal points.\\\"\\n\\t\\\"NetNameResolver localAddressString\\\"\\n\\n\\t^ NetNameResolver stringFromAddress: NetNameResolver localHostAddress\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mir 2/22/2002 15:50'!\\nlocalHostAddress\\n\\t\\\"Return the local address of this host.\\\"\\n\\t\\\"NetNameResolver localHostAddress\\\"\\n\\n\\tself initializeNetwork.\\n\\t^ self primLocalAddress\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mir 2/22/2002 15:12'!\\nlocalHostName\\n\\t\\\"Return the local name of this host.\\\"\\n\\t\\\"NetNameResolver localHostName\\\"\\n\\n\\t| hostName |\\n\\thostName _ NetNameResolver\\n\\t\\tnameForAddress: self localHostAddress\\n\\t\\ttimeout: 5.\\n\\t^hostName\\n\\t\\tifNil: [self localAddressString]\\n\\t\\tifNotNil: [hostName]! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'nk 6/27/2003 10:51'!\\nnameForAddress: hostAddress timeout: secs\\n\\t\\\"Look up the given host address and return its name. Return nil if the lookup fails or is not completed in the given number of seconds. Depends on the given host address being known to the gateway, which may not be the case for dynamically allocated addresses.\\\"\\n\\t\\\"NetNameResolver\\n\\t\\tnameForAddress: (NetNameResolver addressFromString: '128.111.92.2')\\n\\t\\ttimeout: 30\\\"\\n\\n\\t| deadline result |\\n\\tself initializeNetwork.\\n\\tdeadline _ Time millisecondClockValue + (secs * 1000).\\n\\t\\\"Protect the execution of this block, as the ResolverSemaphore is used for both parts of the transaction.\\\"\\n\\tself resolverMutex\\n\\t\\tcritical: [\\n\\t\\t\\tresult _ (self waitForResolverReadyUntil: deadline)\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself primStartLookupOfAddress: hostAddress.\\n\\t\\t\\t\\t\\t(self waitForCompletionUntil: deadline)\\n\\t\\t\\t\\t\\t\\tifTrue: [self primAddressLookupResult]\\n\\t\\t\\t\\t\\t\\tifFalse: [nil]]\\n\\t\\t\\t\\tifFalse: [nil]].\\n\\t^result\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'jm 9/17/97 16:26'!\\npromptUserForHostAddress\\n\\t\\\"Ask the user for a host name and return its address.\\\"\\n\\t\\\"NetNameResolver promptUserForHostAddress\\\"\\n\\n\\t^ NetNameResolver promptUserForHostAddressDefault: ''\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'rbb 3/1/2005 11:01'!\\npromptUserForHostAddressDefault: defaultName\\n\\t\\\"Ask the user for a host name and return its address. If the default name is the empty string, use the last host name as the default.\\\"\\n\\t\\\"NetNameResolver promptUserForHostAddressDefault: ''\\\"\\n\\n\\t| default hostName serverAddr |\\n\\tdefaultName isEmpty\\n\\t\\tifTrue: [default := DefaultHostName]\\n\\t\\tifFalse: [default := defaultName].\\n\\thostName := UIManager default\\n\\t\\trequest: 'Host name or address?'\\n\\t\\tinitialAnswer: default.\\n\\thostName isEmpty ifTrue: [^ 0].\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 15.\\n\\thostName size > 0 ifTrue: [DefaultHostName := hostName].\\n\\t^ serverAddr! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'JMM 5/3/2000 11:25'!\\nresolverError\\n\\t^self primNameResolverError\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'JMM 5/3/2000 11:25'!\\nresolverStatus\\n\\t^self primNameResolverStatus\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 15:03'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails.\\\"\\n\\t\\\"NetNameResolver initializeNetwork\\\"\\n\\n\\t| semaIndex |\\n\\tself resolverStatus = ResolverUninitialized\\n\\t\\tifFalse: [^HaveNetwork _ true]. \\\"network is already initialized\\\"\\n\\n\\tHaveNetwork _ false.\\t\\\"in case abort\\\"\\n\\tResolverSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: ResolverSemaphore.\\n\\n\\t\\\"result is nil if network initialization failed, self if it succeeds\\\"\\n\\t(self primInitializeNetwork: semaIndex)\\n\\t\\tifNil: [NoNetworkError signal: 'failed network initialization']\\n\\t\\tifNotNil: [HaveNetwork _ true].\\n! !\\n\\n!NetNameResolver class methodsFor: 'network initialization' stamp: 'ar 2/2/2001 15:09'!\\nprimInitializeNetwork: resolverSemaIndex\\n\\t\\\"Initialize the network drivers on platforms that need it, such as the Macintosh, and return nil if network initialization failed or the reciever if it succeeds. Since mobile computers may not always be connected to a network, this method should NOT be called automatically at startup time; rather, it should be called when first starting a networking application. It is a noop if the network driver has already been initialized. If non-zero, resolverSemaIndex is the index of a VM semaphore to be associated with the network name resolver. This semaphore will be signalled when the resolver status changes, such as when a name lookup query is completed.\\\"\\n\\t\\\"Note: some platforms (e.g., Mac) only allow only one name lookup query at a time, so a manager process should be used to serialize resolver lookup requests.\\\"\\n\\n\\t<primitive: 'primitiveInitializeNetwork' module: 'SocketPlugin'>\\n\\t^ nil \\\"return nil if primitive fails\\\"\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAbortLookup\\n\\t\\\"Abort the current lookup operation, freeing the name resolver for the next query.\\\"\\n\\n\\t<primitive: 'primitiveResolverAbortLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAddressLookupResult\\n\\t\\\"Return the host name found by the last host address lookup. Returns nil if the last lookup was unsuccessful.\\\"\\n\\n\\t<primitive: 'primitiveResolverAddressLookupResult' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimLocalAddress\\n\\t\\\"Return the local address of this host.\\\"\\n\\n\\t<primitive: 'primitiveResolverLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameLookupResult\\n\\t\\\"Return the host address found by the last host name lookup. Returns nil if the last lookup was unsuccessful.\\\"\\n\\n\\t<primitive: 'primitiveResolverNameLookupResult' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameResolverError\\n\\t\\\"Return an integer reflecting the error status of the last network name resolver request. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveResolverError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameResolverStatus\\n\\t\\\"Return an integer reflecting the status of the network name resolver. For a list of possible values, see the comment in the 'initialize' method of this class.\\\"\\n\\n\\t<primitive: 'primitiveResolverStatus' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartLookupOfAddress: hostAddr\\n\\t\\\"Look up the given host address in the Domain Name Server to find its name. This call is asynchronous. To get the results, wait for it to complete or time out and then use primAddressLookupResult.\\\"\\n\\n\\t<primitive: 'primitiveResolverStartAddressLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartLookupOfName: hostName\\n\\t\\\"Look up the given host name in the Domain Name Server to find its address. This call is asynchronous. To get the results, wait for it to complete or time out and then use primNameLookupResult.\\\"\\n\\n\\t<primitive: 'primitiveResolverStartNameLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 13:57'!\\nreadDecimalByteFrom: aStream\\n\\t\\\"Read a positive, decimal integer from the given stream. Stop when a non-digit or end-of-stream is encountered. Return nil if stream is not positioned at a decimal digit or if the integer value read exceeds 255.\\nJMM - 000503 fixed didn't work correctly\\\"\\n\\n\\t| digitSeen value digit |\\n\\tdigitSeen _ false.\\n\\tvalue _ 0.\\n\\t[aStream atEnd] whileFalse: \\n\\t\\t[digit _ aStream next digitValue.\\n\\t\\t(digit < 0 or: [digit > 9]) ifTrue: [\\n\\t\\t\\taStream skip: -1.\\n\\t\\t\\t(digitSeen not or: [value > 255]) ifTrue: [^ nil].\\n\\t\\t\\t^ value].\\n\\t\\tdigitSeen _ true.\\n\\t\\tvalue _ (value * 10) + digit].\\n\\t(digitSeen not or: [value > 255]) ifTrue: [^ nil].\\n\\t^ value\\n! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'mir 6/18/2001 21:05'!\\nresolverMutex\\n\\tResolverMutex ifNil: [ResolverMutex _ Semaphore forMutualExclusion].\\n\\t^ResolverMutex! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 11:35'!\\nwaitForCompletionUntil: deadline\\n\\t\\\"Wait up to the given number of seconds for the resolver to be ready to accept a new request. Return true if the resolver is ready, false if the network is not initialized or the resolver does not become free within the given time period.\\\"\\n\\n\\t| status |\\n\\tstatus _ self resolverStatus.\\n\\t[(status = ResolverBusy) and:\\n\\t [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\t\\\"wait for resolver to be available\\\"\\n\\t\\t\\tResolverSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self resolverStatus].\\n\\n\\tstatus = ResolverReady\\n\\t\\tifTrue: [^ true]\\n\\t\\tifFalse: [\\n\\t\\t\\tstatus = ResolverBusy ifTrue: [self primAbortLookup].\\n\\t\\t\\t^ false].\\n! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 11:36'!\\nwaitForResolverReadyUntil: deadline\\n\\t\\\"Wait up to the given number of seconds for the resolver to be ready to accept a new request. Return true if the resolver is not busy, false if the network is not initialized or the resolver does not become free within the given time period.\\\"\\n\\n\\t| status |\\n\\tstatus _ self resolverStatus.\\n\\tstatus = ResolverUninitialized ifTrue: [^ false].\\n\\n\\t[(status = ResolverBusy) and:\\n\\t [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\t\\\"wait for resolver to be available\\\"\\n\\t\\t\\tResolverSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self resolverStatus].\\n\\n\\t^ status ~= ResolverBusy\\n! !\\nError subclass: #NetworkError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NetworkError commentStamp: 'mir 5/12/2003 18:12' prior: 0!\\nAbstract super class for all network related exceptions.!\\n\\nEmbeddedWorldBorderMorph subclass: #NetworkTerminalBorderMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NetworkTerminalBorderMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\ntoggleFullView\\n\\t\\\"Toggle the full view for network terminal\\\"\\n\\t| fullExtent priorExtent |\\n\\tfullExtent := self worldIEnclose extent + (2 * self borderWidth).\\n\\tpriorExtent := self valueOfProperty: #priorExtent.\\n\\tpriorExtent ifNil:[\\n\\t\\tself setProperty: #priorExtent toValue: self extent.\\n\\t\\tself extent: fullExtent.\\n\\t\\tself position: self position + self borderWidth asPoint negated.\\n\\t] ifNotNil:[\\n\\t\\tself removeProperty: #priorExtent.\\n\\t\\tself extent: priorExtent.\\n\\t\\tself position: (self position max: 0@0).\\n\\t].! !\\n\\n\\n!NetworkTerminalBorderMorph methodsFor: 'boxes' stamp: 'RAA 8/15/2000 12:21'!\\nboxesAndColorsAndSelectors\\n\\n\\t^#()! !\\n\\n\\n!NetworkTerminalBorderMorph methodsFor: 'initialization' stamp: 'RAA 12/14/2000 14:12'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself setBalloonText: nil.\\t\\t\\\"'I am a view on another Squeak'.\\\"\\n\\tself layoutInset: 0.\\n! !\\nMorph subclass: #NetworkTerminalMorph\\n\\tinstanceVariableNames: 'connection decoder eventEncoder backgroundForm enteringHand'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NetworkTerminalMorph commentStamp: '<historical>' prior: 0!\\nA morph used to communicate with a remote image. It sends all mouse/keyboard events to the remote side, and it displays canvas commands that are sent back.!\\n\\n\\n!NetworkTerminalMorph methodsFor: 'as yet unclassified' stamp: 'RAA 8/29/2000 12:13'!\\naddScalingMenuItems: menu hand: aHandMorph\\n\\n\\t\\\"for comaptibility when in scaled frame\\\"! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/25/2000 13:00'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"I assume that we are opaque\\\"\\n\\n\\t^ aRectangle areasOutside: self bounds! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/24/2000 11:43'!\\ndrawOn: aCanvas\\n\\n\\tbackgroundForm ifNotNil: [\\n\\t\\taCanvas clipBy: bounds during: [ :c |\\n\\t\\t\\tc drawImage: backgroundForm at: bounds topLeft\\n\\t\\t].\\n\\t].\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:25'!\\nforceToFront: aRegion\\n\\t| highQuality |\\n\\t\\\"force the given region from the drawing form onto the background form\\\"\\n\\n\\thighQuality := false.\\t\\t\\\"highQuality is slower\\\"\\n\\n\\tself updateBackgroundForm.\\n\\tbackgroundForm\\n\\t\\tcopy: aRegion\\n\\t\\tfrom: aRegion topLeft\\n\\t\\tin: decoder drawingForm\\n\\t\\trule: Form over.\\n\\tself invalidRect: (\\n\\t\\thighQuality ifTrue: [\\n\\t\\t\\tbounds\\n\\t\\t] ifFalse: [\\n\\t\\t\\t(aRegion expandBy: 4) translateBy: bounds topLeft\\t\\\"try to remove gribblys\\\"\\n\\t\\t]\\n\\t)\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\nupdateBackgroundForm\\n\\t\\\"make sure that our background form matches what the server has most recently requested\\\"\\n\\n\\t| drawingForm |\\n\\n\\tdrawingForm := decoder drawingForm.\\n\\t(drawingForm extent = backgroundForm extent and: [\\n\\t\\tdrawingForm depth = backgroundForm depth ]) ifTrue: [\\n\\t\\t\\t\\\"they match just fine\\\"\\n\\t\\t\\t^self ].\\n\\n\\tbackgroundForm := drawingForm deepCopy.\\t\\t\\\"need copy to capture the moment\\\"\\n\\tself extent: backgroundForm extent.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'dropping/grabbing' stamp: 'RAA 11/5/2000 13:26'!\\nwantsDroppedMorph: aMorph event: evt\\n\\n\\t^true.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 11/5/2000 13:23'!\\ncommResult: anArrayOfAssociations\\n\\n\\t\\\"ignore for now\\\"! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:25'!\\nhandlesMouseOver: evt\\n\\t^true! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:24'!\\nmouseEnter: evt\\n\\tevt hand newKeyboardFocus: self.\\n\\tevt hand needsToBeDrawn ifTrue:[Cursor blank show].! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:25'!\\nmouseLeave: evt\\n\\n\\tevt hand needsToBeDrawn ifTrue:[Cursor normal show].! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 8/15/2000 11:34'!\\nsendEvent: evt\\n\\n\\tself sendEventAsIs: (evt translatedBy: bounds topLeft negated).! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 8/15/2000 11:33'!\\nsendEventAsIs: evt\\n\\n\\teventEncoder ifNil: [ ^self ].\\n\\teventEncoder sendEvent: evt.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:02'!\\nhandleKeyDown: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:02'!\\nhandleKeyUp: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:11'!\\nhandleKeystroke: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:03'!\\nhandleMouseDown: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent wasHandled: true.\\n\\tanEvent hand newMouseFocus: self event: anEvent.\\n\\tanEvent hand removeHaloFromClick: anEvent on: self.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:04'!\\nhandleMouseMove: anEvent\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t(anEvent hand hasSubmorphs) ifTrue:[^self].\\n\\t(anEvent anyButtonPressed and:[anEvent hand mouseFocus ~~ self]) ifTrue:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:03'!\\nhandleMouseUp: anEvent\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand mouseFocus == self ifFalse:[^self]. \\\"Not interested in other parties\\\"\\n\\tanEvent hand releaseMouseFocus: self.\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:06'!\\nhandlerForMouseDown: anEvent\\n\\t^self! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'geometry' stamp: 'RAA 7/24/2000 11:35'!\\nextent: newExtent\\n\\n\\tsuper extent: newExtent.\\n\\teventEncoder sendViewExtent: self extent! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 12:06'!\\nconnection: aConnection\\n\\n\\tconnection := aConnection.\\n\\tdecoder := CanvasDecoder connection: aConnection.\\n\\teventEncoder := MorphicEventEncoder on: aConnection.! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\tsuper initialize.\\n\\tbackgroundForm := (\\n\\t\\t(StringMorph contents: '......' font: (TextStyle default fontOfSize: 24))\\n\\t\\t\\tcolor: Color white\\n\\t) imageForm.\\n\\tbounds := backgroundForm boundingBox.\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 10:45'!\\nopenInStyle: aSymbol\\n\\n\\taSymbol == #naked ifTrue: [\\n\\t\\tself openInWorld.\\n\\t].\\n\\taSymbol == #scaled ifTrue: [\\n\\t\\tself openScaled.\\n\\t].\\n\\taSymbol == #bordered ifTrue: [\\n\\t\\tAlignmentMorph newColumn\\n\\t\\t\\thResizing: \\t#shrinkWrap;\\n\\t\\t\\tvResizing: \\t#shrinkWrap;\\n\\t\\t\\tborderWidth: 8;\\n\\t\\t\\tborderColor: Color blue;\\n\\t\\t\\taddMorph: self;\\n\\t\\t\\topenInWorld.\\n\\t].\\n\\n\\t[\\n\\t\\t[self world isNil] whileFalse: [(Delay forSeconds: 2) wait].\\n\\t\\tself disconnect.\\n\\t] fork.\\n\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\nopenScaled\\n\\n\\t| window tm |\\n\\twindow := NetworkTerminalBorderMorph new\\n\\t\\tminWidth: 100;\\n\\t\\tminHeight: 100;\\n\\t\\tborderWidth: 8;\\n\\t\\tborderColor: Color orange;\\n\\t\\tbounds: (0@0 extent: Display extent * 3 // 4).\\n\\ttm := BOBTransformationMorph new.\\n\\ttm useRegularWarpBlt: true.\\t\\t\\\"try to reduce memory used\\\"\\n\\twindow addMorphBack: tm.\\n\\ttm addMorph: self.\\n\\twindow openInWorld.\\n\\tNebraskaNavigationMorph new \\n\\t\\tnebraskaBorder: window;\\n\\t\\tnebraskaTerminal: self;\\n\\t\\topenInWorld.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'layout' stamp: 'sd 11/20/2005 21:25'!\\nacceptDroppingMorph: morphToDrop event: evt\\n\\n\\t| myCopy outData null |\\n\\n\\t(morphToDrop isKindOf: NewHandleMorph) ifTrue: [\\t\\t\\t\\\"don't send these\\\"\\n\\t\\t^morphToDrop rejectDropMorphEvent: evt.\\n\\t].\\n\\tself eToyRejectDropMorph: morphToDrop event: evt.\\t\\t\\\"we don't really want it\\\"\\n\\n\\t\\\"7 mar 2001 - remove #veryDeepCopy\\\"\\n\\tmyCopy := morphToDrop.\\t\\\"gradient fills require doing this second\\\"\\n\\tmyCopy setProperty: #positionInOriginatingWorld toValue: morphToDrop position.\\n\\n\\toutData := myCopy eToyStreamedRepresentationNotifying: nil.\\n\\tnull := String with: 0 asCharacter.\\n\\tEToyPeerToPeer new \\n\\t\\tsendSomeData: {\\n\\t\\t\\tEToyIncomingMessage typeMorph,null. \\n\\t\\t\\tPreferences defaultAuthorName,null.\\n\\t\\t\\toutData\\n\\t\\t}\\n\\t\\tto: (NetNameResolver stringFromAddress: connection remoteAddress)\\n\\t\\tfor: self.\\n! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'shutting down' stamp: 'ls 4/11/2000 18:36'!\\ndisconnect\\n\\tconnection ifNotNil: [ connection destroy ].\\n\\teventEncoder := connection := decoder := nil.! !\\n\\n!NetworkTerminalMorph methodsFor: 'shutting down' stamp: 'RAA 12/13/2000 08:21'!\\nrequestBufferedConnection\\n\\n\\teventEncoder ifNotNil: [eventEncoder requestBufferedConnection].\\n! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'stepping and presenter' stamp: 'ar 10/25/2000 23:19'!\\nstep\\n\\n\\tdecoder ifNil: [ ^self ].\\n\\tdecoder processIOOnForce: [ :rectangle | self forceToFront: rectangle ].! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'testing' stamp: 'ls 3/25/2000 16:58'!\\nstepTime\\n\\t^10! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNetworkTerminalMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'RAA 8/4/2000 15:13'!\\nconnectTo: serverHost\\n\\n\\t^self connectTo: serverHost port: NebraskaServer defaultPort\\n\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nconnectTo: serverHost port: serverPort\\n\\n\\t| stringSock |\\n\\n\\tstringSock := self socketConnectedTo: serverHost port: serverPort.\\n\\t^self new connection: stringSock\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'RAA 7/24/2000 12:08'!\\nopenAndConnectTo: serverHost\\n\\n\\t^self openAndConnectTo: serverHost port: NebraskaServer defaultPort\\n\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nopenAndConnectTo: serverHost port: serverPort\\n\\n\\t| stringSock me |\\n\\n\\tstringSock := self socketConnectedTo: serverHost port: serverPort.\\n\\tme := self new connection: stringSock.\\n\\t^me openInStyle: #naked\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nsocketConnectedTo: serverHost port: serverPort\\n\\n\\t| sock |\\n\\n\\tSocket initializeNetwork.\\n\\tsock := Socket new.\\n\\t[sock connectTo: (NetNameResolver addressForName: serverHost) port: serverPort]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | self error: 'could not connect to server' ].\\n\\t^StringSocket on: sock\\n\\n! !\\nHandleMorph subclass: #NewHandleMorph\\n\\tinstanceVariableNames: 'hand offset waitingForClickInside'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'di 5/18/1998 15:27'!\\nfollowHand: aHand forEachPointDo: block1 lastPointDo: block2\\n\\thand _ aHand.\\n\\tpointBlock _ block1.\\n\\tlastPointBlock _ block2.\\n\\tself position: hand lastEvent cursorPoint - (self extent // 2)! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'ar 8/16/2001 15:48'!\\nfollowHand: aHand forEachPointDo: block1 lastPointDo: block2 withCursor: aCursor\\n\\thand _ aHand.\\n\\thand showTemporaryCursor: aCursor \\\"hotSpotOffset: aCursor offset negated\\\".\\n\\tborderWidth _ 0.\\n\\tcolor _ Color transparent.\\n\\tpointBlock _ block1.\\n\\tlastPointBlock _ block2.\\n\\tself position: hand lastEvent cursorPoint - (self extent // 2)! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'RAA 4/19/2001 11:36'!\\nsensorMode\\n\\n\\t\\\"If our client is still addressing the Sensor directly, we need to do so as well\\\"\\n\\t^self valueOfProperty: #sensorMode ifAbsent: [false].\\n! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'RAA 4/19/2001 11:36'!\\nsensorMode: aBoolean\\n\\n\\t\\\"If our client is still addressing the Sensor directly, we need to do so as well\\\"\\n\\tself setProperty: #sensorMode toValue: aBoolean.\\n! !\\n\\n\\n!NewHandleMorph methodsFor: 'dropping/grabbing' stamp: 'di 4/30/1999 14:06'!\\njustDroppedInto: aMorph event: anEvent\\n\\t\\\"No dropping behavior because stepping will delete me.\\n\\tMoreover it needs to be done that way to evaluate lastPointBlock\\\"\\n! !\\n\\n!NewHandleMorph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:16'!\\nundoGrabCommand\\n\\t^nil! !\\n\\n\\n!NewHandleMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:29'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\n\\tsuper initialize.\\n\\\"\\\"\\n\\twaitingForClickInside _ true.\\n\\tPreferences noviceMode\\n\\t\\tifTrue: [self setBalloonText: 'stretch']! !\\n\\n\\n!NewHandleMorph methodsFor: 'stepping and presenter' stamp: 'RAA 4/19/2001 11:37'!\\nstep\\n\\t| eventSource |\\n\\n\\teventSource _ self sensorMode ifTrue: [\\n\\t\\tSensor\\n\\t] ifFalse: [\\n\\t\\thand lastEvent\\n\\t].\\n\\teventSource anyButtonPressed\\n\\t\\tifTrue: [waitingForClickInside _ false.\\n\\t\\t\\t\\tself position: eventSource cursorPoint - (self extent // 2).\\n\\t\\t\\t\\tpointBlock value: self center]\\n\\t\\tifFalse: [waitingForClickInside\\n\\t\\t\\t\\t\\tifTrue: [(self containsPoint: eventSource cursorPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [\\\"mouse wandered out before clicked\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t^ self delete]]\\n\\t\\t\\t\\t\\tifFalse: [lastPointBlock value: self center.\\n\\t\\t\\t\\t\\t\\t\\t^ self delete]]! !\\n\\n\\n!NewHandleMorph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/16/2001 15:38'!\\ndelete\\n\\thand ifNotNil:[\\n\\t\\thand showTemporaryCursor: nil.\\n\\t].\\n\\tsuper delete.! !\\n\\n\\n!NewHandleMorph methodsFor: 'WiW support' stamp: 'RAA 1/10/2001 10:15'!\\nmorphicLayerNumber\\n\\n\\t^1\\t\\t\\\"handles are very front-like - e.g. the spawn reframe logic actually asks if the first submorph of the world is one of us before deciding to create one\\\"! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNewHandleMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NewHandleMorph class methodsFor: 'new-morph participation' stamp: 'di 5/3/1998 10:08'!\\nincludeInNewMorphMenu\\n\\t^ false! !\\nObject subclass: #NewParagraph\\n\\tinstanceVariableNames: 'text textStyle firstCharacterIndex container lines positionWhenComposed offsetToEnd maxRightX selectionStart selectionStop wantsColumnBreaks focused'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!NewParagraph commentStamp: '<historical>' prior: 0!\\nA Paragraph represents text that has been laid out, or composed, in some container.\\n\\ttext \\t\\tA Text with encoded per-character emphasis.\\n\\ttextStyle\\tA TextStyle with font set, line height and horizontal alignment.\\n\\tfirstCharacterIndex The starting index in text for this paragraph, allowing\\n\\t\\t\\t\\tcomposition of a long text into a number of containers.\\n\\tcontainer\\tA Rectangle or TextContainer that determines where text can go.\\n\\tlines\\t\\tAn Array of TextLines comprising the final layout of the text\\n\\t\\t\\t\\tafter it has been composed within its container.\\n\\tpositionWhenComposed As its name implies. Allows display at new locations\\n\\t\\t\\t\\twithout the need to recompose the text.\\nLines are ordered vertically. However, for a given y, there may be several lines in left to right order. Lines must never be empty, even if text is empty.\\n\\nNotes on yet another hack - 5 Feb 2001\\n\\nWe really need to clean up #composeLinesFrom:to:delta:into:priorLines:atY:!!!!!!\\n\\nI added one more habdful of code to correct:\\n\\nThis is an annoying bug that's been around for a couple of years, but I finally figured out how to duplicate the problem, so I figured I'd just report it now. (It doesn't necessarily have to be fixed for 3.0 if it looks messy, but if it's a simple fix, it would be worth it.)\\n\\nIn Morphic, if you have the following text in a workspace:\\n\\nThis is line 1\\nThis is line 2\\n\\n**and** you have a return character after line 2, you will normally be able to click the mouse two times below line 2 in order to select all the text. If you edit line 2 (e.g. so that it reads \\\"line number 2\\\"), you can still select all the text by clicking below the second line. However, if you edit line 1, you will not be able to select all the text from the bottom in the same way. Things get messed up such that the last return character seems to be gone. In this state, if you position the cursor immediately after the 2, and press the right arrow, the cursor jumps to the beginning of line 2... oof. (report by Doug Way)\\n\\nWhile I don't have a very deep understanding of the above mentioned method, I was able to determine that text ending in a CR worked better in the editor when the last entry in <lines> had a start of text size + 1 and a stop of text size. I have accordingly added code near the end to ensure this. It seems to have fixed the problem, but we do need to clean this baby up some day. - Bob\\n!\\n]style[(830 38 127 1000 388)f1,f2cblue;,f1,f1cred;,f1!\\n\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 11/16/97 09:02'!\\nadjustedFirstCharacterIndex\\n\\t\\\"Return the index in the text where this paragraph WOULD begin if nothing had changed, except the size of the text -- ie if there have only been an insertion of deletion in the preceding morphs\\\"\\n\\toffsetToEnd ifNil: [^ -1].\\n\\t^ text size - offsetToEnd! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/24/97 17:38'!\\nextent\\n\\t^ container width @ (lines last bottom - lines first top)! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 11/8/97 15:41'!\\nfirstCharacterIndex\\n\\t^ firstCharacterIndex! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'rr 3/22/2004 12:42'!\\nfocused\\n\\tfocused ifNil: [focused := false].\\n\\t^ focused! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'rr 3/22/2004 12:41'!\\nfocused: aBoolean\\n\\tfocused := aBoolean! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/23/97 21:01'!\\nlastCharacterIndex\\n\\t^ lines last last! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'sbw 10/13/1999 22:31'!\\nnumberOfLines\\n\\n\\t^lines size! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'sw 1/13/98 21:31'!\\nstring\\n\\t^ text string! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/21/97 14:39'!\\ntext\\n\\t^ text! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'jm 11/19/97 20:27'!\\ntextOwner: ignored \\\"See TextOnCurve\\\"! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/21/97 14:39'!\\ntextStyle\\n\\t^ textStyle! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/23/97 19:33'!\\ntextStyle: aTextStyle \\n\\t\\\"Set the style by which the receiver should display its text.\\\"\\n\\ttextStyle _ aTextStyle! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'RAA 5/6/2001 15:04'!\\nwantsColumnBreaks\\n\\n\\t^wantsColumnBreaks! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'RAA 5/6/2001 15:03'!\\nwantsColumnBreaks: aBoolean\\n\\n\\twantsColumnBreaks _ aBoolean! !\\n\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\ncentered \\n\\ttextStyle centered! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\njustified \\n\\ttextStyle justified! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\nleftFlush \\n\\ttextStyle leftFlush! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\nrightFlush \\n\\ttextStyle rightFlush! !\\n\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'jm 2/25/2003 16:20'!\\nOLDcomposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines atY: startingY \\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| charIndex lineY lineHeight scanner line row firstLine lineHeightGuess saveCharIndex hitCR maybeSlide sliding bottom priorIndex priorLine |\\n\\tcharIndex := start.\\n\\tlines := lineColl.\\n\\tlineY := startingY.\\n\\tlineHeightGuess := textStyle lineGrid.\\n\\tmaxRightX := container left.\\n\\tmaybeSlide := stop < text size and: [container isMemberOf: Rectangle].\\n\\tsliding := false.\\n\\tpriorIndex := 1.\\n\\tbottom := container bottom.\\n\\tscanner := CompositionScanner new text: text textStyle: textStyle.\\n\\tfirstLine := true.\\n\\t[charIndex <= text size and: [lineY + lineHeightGuess <= bottom]] \\n\\t\\twhileTrue: \\n\\t\\t\\t[sliding \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Having detected the end of rippling recoposition, we are only sliding old lines\\\"\\n\\n\\t\\t\\t\\t\\tpriorIndex < priorLines size \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"Adjust and re-use previously composed line\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tpriorIndex := priorIndex + 1.\\n\\t\\t\\t\\t\\t\\t\\tpriorLine := (priorLines at: priorIndex) slideIndexBy: delta\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tandMoveTopTo: lineY.\\n\\t\\t\\t\\t\\t\\t\\tlineColl addLast: priorLine.\\n\\t\\t\\t\\t\\t\\t\\tlineY := priorLine bottom.\\n\\t\\t\\t\\t\\t\\t\\tcharIndex := priorLine last + 1]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"There are no more priorLines to slide.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tsliding := maybeSlide := false]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[lineHeight := lineHeightGuess.\\n\\t\\t\\t\\t\\tsaveCharIndex := charIndex.\\n\\t\\t\\t\\t\\thitCR := false.\\n\\t\\t\\t\\t\\trow := container rectanglesAt: lineY height: lineHeight.\\n\\t\\t\\t\\t\\t1 to: row size\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\t\\t(charIndex <= text size and: [hitCR not]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[line := scanner \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomposeFrom: charIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinRectangle: (row at: i)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfirstLine: firstLine\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tleftSide: i = 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trightSide: i = row size.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlines addLast: line.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(text at: line last) = Character cr ifTrue: [hitCR := true].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlineHeight := lineHeight max: line lineHeight.\\t\\\"includes font changes\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex := line last + 1]].\\n\\n\\t\\t\\t\\t\\tlineY := lineY + lineHeight.\\n\\t\\t\\t\\t\\trow notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[lineY > bottom \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Oops -- the line is really too high to fit -- back out\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex := saveCharIndex.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\trow do: [:r | lines removeLast]]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"It's OK -- the line still fits.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxRightX := maxRightX max: scanner rightX.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t1 to: row size - 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"Adjust heights across row if necess\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(lines at: lines size - row size + i) lineHeight: lines last lineHeight\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseline: lines last baseline].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex > text size \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"end of text\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thitCR \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"If text ends with CR, add a null line at the end\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlineY + lineHeightGuess <= container bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[row := container rectanglesAt: lineY height: lineHeightGuess.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trow notEmpty \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[line := (TextLine \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstart: charIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstop: charIndex - 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinternalSpaces: 0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpaddingWidth: 0)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trectangle: row first;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlines addLast: line]]].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlines := lines asArray.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t^maxRightX].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tfirstLine := false]].\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t(maybeSlide and: [charIndex > stop]) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"Check whether we are now in sync with previously composed lines\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t\\t[priorIndex < priorLines size \\n\\t\\t\\t\\t\\t\\t\\t\\tand: [(priorLines at: priorIndex) first < (charIndex - delta)]] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twhileTrue: [priorIndex := priorIndex + 1].\\n\\t\\t\\t\\t\\t\\t\\t(priorLines at: priorIndex) first = (charIndex - delta) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Yes -- next line will have same start as prior line.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tpriorIndex := priorIndex - 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmaybeSlide := false.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tsliding := true]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[priorIndex = priorLines size \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Weve reached the end of priorLines,\\n\\t\\t\\t\\t\\t\\t\\t\\tso no use to keep looking for lines to slide.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaybeSlide := false]]]]].\\n\\tfirstLine \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"No space in container or empty text\\\"\\n\\n\\t\\t\\tline := (TextLine \\n\\t\\t\\t\\t\\t\\tstart: start\\n\\t\\t\\t\\t\\t\\tstop: start - 1\\n\\t\\t\\t\\t\\t\\tinternalSpaces: 0\\n\\t\\t\\t\\t\\t\\tpaddingWidth: 0)\\n\\t\\t\\t\\t\\t\\trectangle: (container topLeft extent: 0 @ lineHeightGuess);\\n\\t\\t\\t\\t\\t\\tlineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\t\\t\\tlines := Array with: line]\\n\\t\\tifFalse: [self fixLastWithHeight: lineHeightGuess].\\n\\t\\\"end of container\\\"\\n\\tlines := lines asArray.\\n\\t^maxRightX! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 11/8/97 15:31'!\\ncompose: t style: ts from: startingIndex in: textContainer\\n\\ttext _ t.\\n\\ttextStyle _ ts.\\n\\tfirstCharacterIndex _ startingIndex.\\n\\toffsetToEnd _ text size - firstCharacterIndex.\\n\\tcontainer _ textContainer.\\n\\tself composeAll! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/20/2002 16:18'!\\ncomposeAll\\n\\ttext string isOctetString ifTrue: [\\n\\t\\t^ self composeLinesFrom: firstCharacterIndex to: text size delta: 0\\n\\t\\t\\tinto: OrderedCollection new priorLines: Array new atY: container top.\\n\\t].\\n\\n\\t^ self multiComposeLinesFrom: firstCharacterIndex to: text size delta: 0\\n\\t\\tinto: OrderedCollection new priorLines: Array new atY: container top.\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 11/15/97 09:21'!\\ncomposeAllStartingAt: characterIndex\\n\\tfirstCharacterIndex _ characterIndex.\\n\\toffsetToEnd _ text size - firstCharacterIndex.\\n\\tself composeAll! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 5/7/2001 10:58'!\\ncomposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult |\\n\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\t^maxRightX\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 10/22/97 11:13'!\\ncompositionRectangle\\n\\t^ container! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 2/25/2001 15:02'!\\nfixLastWithHeight: lineHeightGuess\\n\\\"This awful bit is to ensure that if we have scanned all the text and the last character is a CR that there is a null line at the end of lines. Sometimes this was not happening which caused anomalous selections when selecting all the text. This is implemented as a post-composition fixup because I coul;dn't figure out where to put it in the main logic.\\\"\\n\\n\\t| oldLastLine newRectangle line |\\n\\n\\t(text size > 1 and: [text last = Character cr]) ifFalse: [^self].\\n\\n\\toldLastLine _ lines last.\\n\\toldLastLine last - oldLastLine first >= 0 ifFalse: [^self].\\n\\toldLastLine last = text size ifFalse: [^self].\\n\\n\\tnewRectangle _ oldLastLine left @ oldLastLine bottom \\n\\t\\t\\t\\textent: 0@(oldLastLine bottom - oldLastLine top).\\n\\t\\\"Even though we may be below the bottom of the container,\\n\\tit is still necessary to compose the last line for consistency...\\\"\\n\\n\\tline _ TextLine start: text size+1 stop: text size internalSpaces: 0 paddingWidth: 0.\\n\\tline rectangle: newRectangle.\\n\\tline lineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\tlines _ lines, (Array with: line).\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 1/3/2003 12:17'!\\nmultiComposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult |\\n\\n\\tnewResult _ MultiTextComposer new\\n\\t\\tmultiComposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\t\\\"maxRightX printString displayAt: 0@0.\\\"\\n\\t^maxRightX\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/20/2002 16:18'!\\nrecomposeFrom: start to: stop delta: delta\\n\\t\\\"Recompose this paragraph. The altered portion is between start and stop.\\n\\tRecomposition may continue to the end of the text, due to a ripple effect.\\n\\tDelta is the amount by which the current text is longer than it was\\n\\twhen its current lines were composed.\\\"\\n\\t| startLine newLines |\\n\\t\\\"Have to recompose line above in case a word-break was affected.\\\"\\n\\tstartLine _ (self lineIndexForCharacter: start) - 1 max: 1.\\n\\t[startLine > 1 and: [(lines at: startLine-1) top = (lines at: startLine) top]]\\n\\t\\twhileTrue: [startLine _ startLine - 1]. \\\"Find leftmost of line pieces\\\"\\n\\tnewLines _ OrderedCollection new: lines size + 1.\\n\\t1 to: startLine-1 do: [:i | newLines addLast: (lines at: i)].\\n\\ttext string isOctetString ifTrue: [\\n\\t\\t^ self composeLinesFrom: (lines at: startLine) first to: stop delta: delta\\n\\t\\t\\tinto: newLines priorLines: lines\\n\\t\\t\\tatY: (lines at: startLine) top.\\n\\t].\\n\\tself multiComposeLinesFrom: (lines at: startLine) first to: stop delta: delta\\n\\t\\tinto: newLines priorLines: lines\\n\\t\\tatY: (lines at: startLine) top.\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 5/6/2001 15:09'!\\ntestNewComposeAll\\n\\t| newResult |\\n\\tself \\n\\t\\tOLDcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top.\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: false.\\n\\tnewResult first with: lines do: [ :e1 :e2 |\\n\\t\\te1 longPrintString = e2 longPrintString ifFalse: [self halt].\\n\\t].\\n\\tnewResult second = maxRightX ifFalse: [self halt].\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/17/2002 14:48'!\\ntestNewComposeAll2\\n\\t| newResult |\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: false.\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/18/2002 15:00'!\\ntestNewComposeAll3\\n\\t| newResult |\\n\\tnewResult _ TextComposer new\\n\\t\\tmultiComposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: (0@0 extent: 31@60)\\n\\t\\twantsColumnBreaks: false.\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n\\n!NewParagraph methodsFor: 'copying' stamp: 'di 5/21/1998 21:45'!\\ndeepCopy\\n\\t\\\"Don't want to copy the container (etc) or fonts in the TextStyle.\\\"\\n\\t| new |\\n\\tnew _ self copy.\\n\\tnew textStyle: textStyle copy\\n\\t\\tlines: lines copy\\n\\t\\ttext: text deepCopy.\\n\\t^ new! !\\n\\n\\n!NewParagraph methodsFor: 'display' stamp: 'di 8/13/2000 12:27'!\\nasParagraphForPostscript\\n\\n\\t^ self! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'lr 7/12/2006 09:27'!\\ncaretWidth\\n\\t^ Preferences caretWidth! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'nk 8/31/2004 11:10'!\\ndisplaySelectionInLine: line on: aCanvas \\n\\t| leftX rightX w caretColor |\\n\\tselectionStart ifNil: [^self].\\t\\\"No selection\\\"\\n\\taCanvas isShadowDrawing ifTrue: [ ^self ].\\t\\\"don't draw selection with shadow\\\"\\n\\tselectionStart = selectionStop \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Only show caret on line where clicked\\\"\\n\\n\\t\\t\\tselectionStart textLine ~= line ifTrue: [^self]]\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Test entire selection before or after here\\\"\\n\\n\\t\\t\\t(selectionStop stringIndex < line first \\n\\t\\t\\t\\tor: [selectionStart stringIndex > (line last + 1)]) ifTrue: [^self].\\t\\\"No selection on this line\\\"\\n\\t\\t\\t(selectionStop stringIndex = line first \\n\\t\\t\\t\\tand: [selectionStop textLine ~= line]) ifTrue: [^self].\\t\\\"Selection ends on line above\\\"\\n\\t\\t\\t(selectionStart stringIndex = (line last + 1) \\n\\t\\t\\t\\tand: [selectionStop textLine ~= line]) ifTrue: [^self]].\\t\\\"Selection begins on line below\\\"\\n\\tleftX := (selectionStart stringIndex < line first \\n\\t\\t\\t\\tifTrue: [line ]\\n\\t\\t\\t\\tifFalse: [selectionStart ])left.\\n\\trightX := (selectionStop stringIndex > (line last + 1) or: \\n\\t\\t\\t\\t\\t[selectionStop stringIndex = (line last + 1) \\n\\t\\t\\t\\t\\t\\tand: [selectionStop textLine ~= line]]) \\n\\t\\t\\t\\tifTrue: [line right]\\n\\t\\t\\t\\tifFalse: [selectionStop left].\\n\\tselectionStart = selectionStop \\n\\t\\tifTrue: \\n\\t\\t\\t[rightX := rightX + 1.\\n\\t\\t\\tw := self caretWidth.\\n\\t\\t\\tcaretColor := self insertionPointColor.\\n\\t\\t\\t1 to: w\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\\"Draw caret triangles at top and bottom\\\"\\n\\n\\t\\t\\t\\t\\taCanvas fillRectangle: ((leftX - w + i - 1) @ (line top + i - 1) \\n\\t\\t\\t\\t\\t\\t\\t\\textent: ((w - i) * 2 + 3) @ 1)\\n\\t\\t\\t\\t\\t\\tcolor: caretColor.\\n\\t\\t\\t\\t\\taCanvas fillRectangle: ((leftX - w + i - 1) @ (line bottom - i) \\n\\t\\t\\t\\t\\t\\t\\t\\textent: ((w - i) * 2 + 3) @ 1)\\n\\t\\t\\t\\t\\t\\tcolor: caretColor].\\n\\t\\t\\taCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom)\\n\\t\\t\\t\\tcolor: caretColor]\\n\\t\\tifFalse: \\n\\t\\t\\t[aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom)\\n\\t\\t\\t\\tcolor: self selectionColor]! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'rr 3/22/2004 19:56'!\\ninsertionPointColor\\n\\tself focused ifFalse: [^ Color transparent].\\n\\t^ Display depth <= 2\\n\\t\\tifTrue: [Color black]\\n\\t\\tifFalse: [Preferences insertionPointColor]! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'rr 3/23/2004 19:52'!\\nselectionColor\\n\\t| color |\\n\\tDisplay depth = 1 ifTrue: [^ Color veryLightGray].\\n\\tDisplay depth = 2 ifTrue: [^ Color gray].\\n\\tcolor := Preferences textHighlightColor.\\n\\tself focused ifFalse: [color := color alphaMixed: 0.2 with: Color veryVeryLightGray].\\n\\t^ color! !\\n\\n\\n!NewParagraph methodsFor: 'editing' stamp: 'mk 5/28/2005 11:15'!\\nclickAt: clickPoint for: model controller: editor\\n\\t\\\"Give sensitive text a chance to fire. Display flash: (100@100 extent: 100@100).\\\"\\n\\t| startBlock action target range boxes box |\\n\\taction _ false.\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\t(text attributesAt: startBlock stringIndex forStyle: textStyle) \\n\\t\\tdo: [:att | att mayActOnClick ifTrue:\\n\\t\\t\\t\\t[(target _ model) ifNil: [target _ editor morph].\\n\\t\\t\\t\\trange _ text rangeOf: att startingAt: startBlock stringIndex.\\n\\t\\t\\t\\tboxes _ self selectionRectsFrom: (self characterBlockForIndex: range first) \\n\\t\\t\\t\\t\\t\\t\\tto: (self characterBlockForIndex: range last+1).\\n\\t\\t\\t\\tbox _ boxes detect: [:each | each containsPoint: clickPoint] ifNone: [nil].\\n\\t\\t\\t\\tbox ifNotNil:\\n\\t\\t\\t\\t\\t[ box _ (editor transformFrom: nil) invertBoundsRect: box.\\n\\t\\t\\t\\t\\teditor morph allOwnersDo: [ :m | box _ box intersect: (m boundsInWorld) ].\\n\\t\\t\\t\\t\\tUtilities awaitMouseUpIn: box\\n\\t\\t\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\t\\t\\tifSucceed: [(att actOnClickFor: target in: self at: clickPoint editor: editor) ifTrue: [action _ true]].\\n\\t\\t\\t\\t\\tCursor currentCursor == Cursor webLink ifTrue:[Cursor normal show].\\n\\t\\t\\t\\t]]].\\n\\t^ action! !\\n\\n!NewParagraph methodsFor: 'editing' stamp: 'di 4/28/1999 10:14'!\\nreplaceFrom: start to: stop with: aText displaying: displayBoolean \\n\\t\\\"Edit the text, and then recompose the lines.\\\" \\n\\ttext replaceFrom: start to: stop with: aText.\\n\\tself recomposeFrom: start to: start + aText size - 1 delta: aText size - (stop-start+1)! !\\n\\n\\n!NewParagraph methodsFor: 'fonts-display' stamp: 'nk 3/20/2004 11:13'!\\ndisplayOn: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\t| visibleRectangle offset leftInRun line |\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ (somePosition - positionWhenComposed) truncated.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ lines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n\\n!NewParagraph methodsFor: 'initialize-release' stamp: 'tak 12/21/2004 13:29'!\\ninitialize\\n\\tself positionWhenComposed: 0 @ 0! !\\n\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ar 4/12/2005 19:53'!\\ncharacterBlockAtPoint: aPoint \\n\\t\\\"Answer a CharacterBlock for the character in the text at aPoint.\\\"\\n\\t| line |\\n\\tline _ lines at: (self lineIndexForPoint: aPoint).\\n\\t^ ((text string isWideString) ifTrue: [\\n\\t\\tMultiCharacterBlockScanner new text: text textStyle: textStyle\\n\\t] ifFalse: [CharacterBlockScanner new text: text textStyle: textStyle])\\n\\t\\tcharacterBlockAtPoint: aPoint index: nil\\n\\t\\tin: line! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ar 4/12/2005 19:53'!\\ncharacterBlockForIndex: index \\n\\t\\\"Answer a CharacterBlock for the character in text at index.\\\"\\n\\t| line |\\n\\tline _ lines at: (self lineIndexForCharacter: index).\\n\\t^ ((text string isWideString) ifTrue: [\\n\\t\\tMultiCharacterBlockScanner new text: text textStyle: textStyle\\n\\t] ifFalse: [\\n\\t\\tCharacterBlockScanner new text: text textStyle: textStyle\\n\\t])\\n\\t\\tcharacterBlockAtPoint: nil index: ((index max: line first) min: text size+1)\\n\\t\\tin: line! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'jm 11/19/97 22:56'!\\ncontainsPoint: aPoint\\n\\t^ (lines at: (self lineIndexForPoint: aPoint)) rectangle\\n\\t\\tcontainsPoint: aPoint! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 10/5/1998 12:59'!\\ndefaultCharacterBlock\\n\\t^ (CharacterBlock new stringIndex: firstCharacterIndex text: text\\n\\t\\t\\ttopLeft: lines first topLeft extent: 0 @ 0)\\n\\t\\ttextLine: lines first! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 11/30/97 12:10'!\\nselectionRects\\n\\t\\\"Return an array of rectangles representing the selection region.\\\"\\n\\tselectionStart ifNil: [^ Array new].\\n\\t^ self selectionRectsFrom: selectionStart to: selectionStop! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ls 11/2/2001 23:10'!\\nselectionRectsFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Return an array of rectangles representing the area between the two character blocks given as arguments.\\\"\\n\\t| line1 line2 rects cb1 cb2 w |\\n\\tcharacterBlock1 <= characterBlock2\\n\\t\\tifTrue: [cb1 _ characterBlock1. cb2 _ characterBlock2]\\n\\t\\tifFalse: [cb2 _ characterBlock1. cb1 _ characterBlock2].\\n\\tcb1 = cb2 ifTrue:\\n\\t\\t[w _ self caretWidth.\\n\\t\\t^ Array with: (cb1 topLeft - (w@0) corner: cb1 bottomLeft + ((w+1)@0))].\\n\\tline1 _ self lineIndexForCharacter: cb1 stringIndex.\\n\\tline2 _ self lineIndexForCharacter: cb2 stringIndex.\\n\\tline1 = line2 ifTrue:\\n\\t\\t[^ Array with: (cb1 topLeft corner: cb2 bottomRight)].\\n\\trects _ OrderedCollection new.\\n\\trects addLast: (cb1 topLeft corner: (lines at: line1) bottomRight).\\n\\tline1+1 to: line2-1 do: [ :i |\\n\\t\\t| line |\\n\\t\\tline := lines at: i.\\n\\t\\t(line left = rects last left and: [ line right = rects last right ])\\n\\t\\t\\tifTrue: [ \\\"new line has same margins as old one -- merge them, so that the caller gets as few rectangles as possible\\\"\\n\\t\\t\\t\\t\\t| lastRect |\\n\\t\\t\\t\\t\\tlastRect := rects removeLast.\\n\\t\\t\\t\\t\\trects add: (lastRect bottom: line bottom) ]\\n\\t\\t\\tifFalse: [ \\\"differing margins; cannot merge\\\"\\n\\t\\t\\t\\t\\trects add: line rectangle ] ].\\n\\n\\trects addLast: ((lines at: line2) topLeft corner: cb2 bottomLeft).\\n\\t^ rects! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 12/2/97 19:57'!\\nselectionStart: startBlock selectionStop: stopBlock\\n\\tselectionStart _ startBlock.\\n\\tselectionStop _ stopBlock.! !\\n\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 11/8/97 15:47'!\\nadjustLineIndicesBy: delta\\n\\tfirstCharacterIndex _ firstCharacterIndex + delta.\\n\\tlines do: [:line | line slide: delta].\\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/26/97 15:57'!\\nadjustRightX\\n\\t| shrink |\\n\\tshrink _ container right - maxRightX.\\n\\tlines do: [:line | line paddingWidth: (line paddingWidth - shrink)].\\n\\tcontainer _ container withRight: maxRightX! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:17'!\\nfastFindFirstLineSuchThat: lineBlock\\n\\t\\\"Perform a binary search of the lines array and return the index\\n\\tof the first element for which lineBlock evaluates as true.\\n\\tThis assumes the condition is one that goes from false to true for\\n\\tincreasing line numbers (as, eg, yval > somey or start char > somex).\\n\\tIf lineBlock is not true for any element, return size+1.\\\"\\n\\t| index low high |\\n\\tlow _ 1.\\n\\thigh _ lines size.\\n\\t[index _ high + low // 2.\\n\\tlow > high]\\n\\t\\twhileFalse: \\n\\t\\t\\t[(lineBlock value: (lines at: index))\\n\\t\\t\\t\\tifTrue: [high _ index - 1]\\n\\t\\t\\t\\tifFalse: [low _ index + 1]].\\n\\t^ low! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'RAA 8/30/1998 15:30'!\\nindentationOfLineIndex: lineIndex ifBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the line at lineIndex. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\n\\t If the line is word-wrap overflow, back up a line and recur.\\\"\\n\\n\\t| arrayIndex first last cr |\\n\\tcr _ Character cr.\\n\\tarrayIndex _ lineIndex.\\n\\t[first _ (lines at: arrayIndex) first.\\n\\t first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: \\\"word wrap\\\"\\n\\t\\t[arrayIndex _ arrayIndex - 1].\\n\\tlast _ (lines at: arrayIndex) last.\\n\\t\\n\\t^(text string copyFrom: first to: last) indentationIfBlank: aBlock.\\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:11'!\\nlineIndexForCharacter: index\\n\\t\\\"Answer the index of the line in which to select the character at index.\\\"\\n\\t^ (self fastFindFirstLineSuchThat: [:line | line first > index]) - 1 max: 1! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:13'!\\nlineIndexForPoint: aPoint\\n\\t\\\"Answer the index of the line in which to select the character nearest to aPoint.\\\"\\n\\t| i py |\\n\\tpy _ aPoint y truncated.\\n\\n\\t\\\"Find the first line at this y-value\\\"\\n\\ti _ (self fastFindFirstLineSuchThat: [:line | line bottom > py]) min: lines size.\\n\\n\\t\\\"Now find the first line at this x-value\\\"\\n\\t[i < lines size and: [(lines at: i+1) top = (lines at: i) top\\n\\t\\t\\t\\tand: [aPoint x >= (lines at: i+1) left]]]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\t^ i! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'RAA 8/30/1998 15:04'!\\nlineIndexOfCharacterIndex: characterIndex \\n\\t\\\"Answer the line index for a given characterIndex.\\\"\\n\\t\\\"apparently the selector changed with NewParagraph\\\"\\n\\n\\t^self lineIndexForCharacter: characterIndex \\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/24/97 17:40'!\\nlines\\n\\t^ lines! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'edc 6/18/2004 09:10'!\\nmoveBy: delta\\n\\tlines do: [:line | line moveBy: delta].\\n\\tpositionWhenComposed ifNotNil:[\\n\\tpositionWhenComposed _ positionWhenComposed + delta].\\n\\tcontainer _ container translateBy: delta! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/21/97 21:36'!\\npositionWhenComposed: pos\\n\\tpositionWhenComposed _ pos! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 5/21/1998 21:47'!\\ntextStyle: ts lines: l text: t\\n\\t\\\"Private -- just a service for deepCopy\\\"\\n\\ttextStyle _ ts.\\n\\tlines _ l.\\n\\ttext _ t.! !\\nSystemWindow subclass: #NewWorldWindow\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-AdditionalWorlds'!\\n\\n!NewWorldWindow methodsFor: 'color' stamp: 'nb 6/17/2003 12:25'!\\nsetWindowColor: incomingColor\\n\\t| existingColor aColor |\\n\\n\\tincomingColor ifNil: [^ self]. \\\"it happens\\\"\\n\\taColor _ incomingColor asNontranslucentColor.\\n\\t(aColor = ColorPickerMorph perniciousBorderColor \\n\\t\\tor: [aColor = Color black]) ifTrue: [^ self].\\n\\texistingColor _ self paneColorToUse.\\n\\texistingColor ifNil: [^ Beeper beep].\\n\\tself setStripeColorsFrom: aColor\\n\\t\\t\\n! !\\n\\n\\n!NewWorldWindow methodsFor: 'initialization' stamp: 'ar 5/11/2001 23:48'!\\nopenInWorld: aWorld\\n\\t| xxx |\\n\\t\\\"This msg and its callees result in the window being activeOnlyOnTop\\\"\\n\\n\\txxx _ RealEstateAgent initialFrameFor: self world: aWorld.\\n\\n\\t\\\"Bob say: 'opening in ',xxx printString,' out of ',aWorld bounds printString.\\n\\t6 timesRepeat: [Display flash: xxx andWait: 300].\\\"\\n\\n\\tself bounds: xxx.\\n\\t^self openAsIsIn: aWorld.! !\\n\\n\\n!NewWorldWindow methodsFor: 'label' stamp: 'sw 5/19/2001 10:44'!\\nsetStripeColorsFrom: paneColor\\n\\t\\\"Since our world may be *any* color, try to avoid really dark colors so title will show\\\"\\n\\n\\t| revisedColor |\\n\\tstripes ifNil: [^ self].\\n\\trevisedColor _ paneColor atLeastAsLuminentAs: 0.1 .\\n\\tself isActive ifTrue:\\n\\t\\t[stripes second \\n\\t\\t\\tcolor: revisedColor; \\n\\t\\t\\tborderColor: stripes second color darker.\\n\\t\\tstripes first \\n\\t\\t\\tcolor: stripes second borderColor darker;\\n\\t\\t\\tborderColor: stripes first color darker.\\n\\t\\t^ self].\\n\\t\\\"This could be much faster\\\"\\n\\tstripes second \\n\\t\\tcolor: revisedColor; \\n\\t\\tborderColor: revisedColor.\\n\\tstripes first \\n\\t\\tcolor: revisedColor; \\n\\t\\tborderColor: revisedColor! !\\n\\n\\n!NewWorldWindow methodsFor: 'panes' stamp: 'ar 11/9/2000 01:31'!\\naddMorph: aMorph frame: relFrame\\n\\t| cc |\\n\\tcc _ aMorph color.\\n\\tsuper addMorph: aMorph frame: relFrame.\\n\\taMorph color: cc.! !\\n\\n!NewWorldWindow methodsFor: 'panes' stamp: 'RAA 6/1/2000 18:21'!\\nupdatePaneColors\\n\\t\\\"Useful when changing from monochrome to color display\\\"\\n\\n\\tself setStripeColorsFrom: self paneColorToUse.\\n\\n\\t\\\"paneMorphs do: [:p | p color: self paneColorToUse].\\\"\\t\\\"since pane is a world, skip this\\\"\\n! !\\n\\n\\n!NewWorldWindow methodsFor: 'stepping' stamp: 'RAA 6/1/2000 18:30'!\\namendSteppingStatus! !\\n\\n\\n!NewWorldWindow methodsFor: 'testing' stamp: 'RAA 6/1/2000 18:33'!\\nwantsSteps\\n\\t\\n\\t^true! !\\nController subclass: #NoController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Framework'!\\n!NoController commentStamp: '<historical>' prior: 0!\\nI represent a controller that never wants control. I am the controller for views that are non-interactive.!\\n\\n\\n!NoController methodsFor: 'basic control sequence'!\\nstartUp\\n\\t\\\"I do nothing.\\\"\\n\\n\\t^self! !\\n\\n\\n!NoController methodsFor: 'control defaults'!\\nisControlActive \\n\\t\\\"Refer to the comment in Controller|isControlActive.\\\"\\n\\n\\t^false! !\\n\\n!NoController methodsFor: 'control defaults'!\\nisControlWanted \\n\\t\\\"Refer to the comment in Controller|isControlWanted.\\\"\\n\\n\\t^false! !\\nClipboardInterpreter subclass: #NoConversionClipboardInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!NoConversionClipboardInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 8/11/2003 19:03'!\\nfromSystemClipboard: aString\\n\\n\\t^ aString.\\n! !\\n\\n!NoConversionClipboardInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 8/11/2003 21:06'!\\ntoSystemClipboard: aString\\n\\n\\t| result |\\n\\taString isOctetString ifTrue: [^ aString asOctetString].\\n\\n\\tresult _ WriteStream on: (String new: aString size).\\n\\taString do: [:each | each value < 256 ifTrue: [result nextPut: each]].\\n\\t^ result contents.\\n! !\\nKeyboardInputInterpreter subclass: #NoInputInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!NoInputInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 7/25/2003 14:59'!\\nnextCharFrom: sensor firstEvt: evtBuf\\n\\n\\n\\n\\t| keyValue |\\n\\n\\tkeyValue := evtBuf third.\\n\\n\\t^ keyValue asCharacter.\\n\\n! !\\nNetworkError subclass: #NoNetworkError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NoNetworkError commentStamp: 'mir 5/12/2003 18:17' prior: 0!\\nSignals that no network was found. This could happen, e.g., on dial-up connection when no connection was established when Squeak tried to access it.\\n\\n!\\n\\nError subclass: #NonBooleanReceiver\\n\\tinstanceVariableNames: 'object'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n\\n!NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'!\\nobject\\n\\t^object! !\\n\\n!NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'!\\nobject: anObject\\n\\tobject _ anObject! !\\n\\n\\n!NonBooleanReceiver methodsFor: 'signaledException' stamp: 'hmm 7/29/2001 21:37'!\\nisResumable\\n\\n\\t^true! !\\nAbstractScoreEvent subclass: #NoteEvent\\n\\tinstanceVariableNames: 'duration midiKey velocity channel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Scores'!\\n!NoteEvent commentStamp: '<historical>' prior: 0!\\nRepresents a note on or off event in a MIDI score.\\n!\\n\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/30/97 22:02'!\\nchannel\\n\\n\\t^ channel\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nchannel: midiChannel\\n\\n\\tchannel := midiChannel.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/18/97 19:10'!\\nduration\\n\\n\\t^ duration\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nduration: aNumber\\n\\n\\tduration := aNumber.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 8/27/1998 16:38'!\\nendTime\\n\\n\\t^ time + duration\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nkey: midiKeyNum velocity: midiVelocity channel: midiChannel\\n\\n\\tmidiKey := midiKeyNum.\\n\\tvelocity := midiVelocity.\\n\\tchannel := midiChannel.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/18/97 20:58'!\\nmidiKey\\n\\n\\t^ midiKey\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmidiKey: midiKeyNum\\n\\n\\tmidiKey := midiKeyNum.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 8/3/1998 17:06'!\\npitch\\n\\t\\\"Convert my MIDI key number to a pitch and return it.\\\"\\n\\n\\t^ AbstractSound pitchForMIDIKey: midiKey\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/30/97 09:32'!\\nvelocity\\n\\n\\t^ velocity\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nvelocity: midiVelocity\\n\\n\\tvelocity := midiVelocity.\\n! !\\n\\n\\n!NoteEvent methodsFor: 'classification' stamp: 'jm 12/31/97 11:48'!\\nisNoteEvent\\n\\n\\t^ true\\n! !\\n\\n\\n!NoteEvent methodsFor: 'midi' stamp: 'jm 9/10/1998 15:58'!\\nendNoteOnMidiPort: aMidiPort\\n\\t\\\"Output a noteOff event to the given MIDI port. (Actually, output a noteOff event with zero velocity. This does the same thing, but allows running status to be used when sending a mixture of note on and off commands.)\\\"\\n\\n\\taMidiPort\\n\\t\\tmidiCmd: 16r90\\n\\t\\tchannel: channel\\n\\t\\tbyte: midiKey\\n\\t\\tbyte: 0.\\n! !\\n\\n!NoteEvent methodsFor: 'midi' stamp: 'jm 9/10/1998 15:56'!\\nstartNoteOnMidiPort: aMidiPort\\n\\t\\\"Output a noteOn event to the given MIDI port.\\\"\\n\\n\\taMidiPort\\n\\t\\tmidiCmd: 16r90\\n\\t\\tchannel: channel\\n\\t\\tbyte: midiKey\\n\\t\\tbyte: velocity.\\n! !\\n\\n\\n!NoteEvent methodsFor: 'printing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nkeyName\\n\\t\\\"Return a note name for my pitch.\\\"\\n\\n\\t| pitchName octave |\\n\\tpitchName := #(c cs d ef e f fs g af a bf b) at: (midiKey \\\\\\\\ 12) + 1.\\n\\toctave := (#(-1 0 1 2 3 4 5 6 7 8 9) at: (midiKey // 12) + 1) printString.\\n\\t^ pitchName, octave\\n! !\\n\\n!NoteEvent methodsFor: 'printing' stamp: 'jm 1/3/98 08:59'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $(.\\n\\ttime printOn: aStream.\\n\\taStream nextPutAll: ': '.\\n\\taStream nextPutAll: self keyName.\\n\\taStream space.\\n\\tduration printOn: aStream.\\n\\taStream nextPut: $).\\n! !\\nException subclass: #Notification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n!Notification commentStamp: '<historical>' prior: 0!\\nA Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect.!\\n\\n\\n!Notification methodsFor: 'exceptionDescription' stamp: 'pnm 8/16/2000 15:04'!\\ndefaultAction\\n\\t\\\"No action is taken. The value nil is returned as the value of the message that signaled the exception.\\\"\\n\\n\\t^nil! !\\n\\n!Notification methodsFor: 'exceptionDescription' stamp: 'tfei 6/4/1999 18:17'!\\nisResumable\\n\\t\\\"Answer true. Notification exceptions by default are specified to be resumable.\\\"\\n\\n\\t^true! !\\nPluggableCanvas subclass: #NullCanvas\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n!NullCanvas commentStamp: '<historical>' prior: 0!\\nA canvas which ignores all drawing commands.!\\n\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:11'!\\nclipRect\\n\\t^1@1 extent: 99@99! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:11'!\\nextent\\n\\t^100@100! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:12'!\\nform\\n\\t^Form extent: self extent! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:13'!\\norigin\\n\\t^0@0! !\\n\\n\\n!NullCanvas methodsFor: 'copying' stamp: 'ls 3/20/2000 21:26'!\\ncopyClipRect: clipRect\\n\\t\\\"who cares what the clipping rectangle is?\\\"\\n\\t^self! !\\n\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:41'!\\nclipBy: region during: aBlock\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:39'!\\ntransformBy: aDisplayTransform clippingTo: aClipRect during: aBlock smoothing: cellSize\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:40'!\\ntranslateBy: delta during: aBlock\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\nObject subclass: #NullEncoder\\n\\tinstanceVariableNames: 'target filterSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'RAA 9/17/2000 11:53'!\\nclose\\n\\n\\t^target close.\\n! !\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'MPW 1/1/1901 00:56'!\\ncontents\\n\\t^target contents.\\n! !\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'MPW 1/1/1901 00:16'!\\ntarget\\n\\t^target.! !\\n\\n\\n!NullEncoder methodsFor: 'initialization' stamp: 'MPW 1/1/1901 00:04'!\\ninitWithTarget:aTarget\\n\\ttarget _ aTarget.\\n\\tfilterSelector _ self class filterSelector.\\n\\t^self.\\n! !\\n\\n\\n!NullEncoder methodsFor: 'processing' stamp: 'MPW 1/1/1901 01:19'!\\nprocess:anObject\\n\\tself write:anObject.\\n\\t^self contents.! !\\n\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'MPW 1/1/1901 01:17'!\\nforward:anObject\\n\\tanObject ~= nil ifTrue:[target write:anObject].\\n! !\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'mpw 8/13/1999 10:54'!\\nwrite:anObject\\n\\tfilterSelector ifNil:[filterSelector_self class filterSelector].\\n\\tanObject ifNotNil: [anObject perform:filterSelector with:self].\\n! !\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'MPW 1/1/1901 01:16'!\\nwriteObject:anObject\\n\\t^self forward:anObject.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNullEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!NullEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 00:02'!\\ndefaultTarget\\n\\t^OrderedCollection new.\\n! !\\n\\n!NullEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 00:02'!\\nfilterSelector\\n\\t^#writeOnFilterStream:\\n! !\\n\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 00:55'!\\nstream\\n\\t^self streamOn:self defaultTarget. \\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 00:05'!\\nstream:newTarget\\n\\t^self new initWithTarget:newTarget.\\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 01:15'!\\nstreamOn:newTargetCollection\\n\\t^self new initWithTarget:newTargetCollection.\\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 02:20'!\\nstreamOnFile:fileName\\n\\t^self new initWithTarget:(FileStream newFileNamed: fileName).\\n! !\\n\\n\\n!NullEncoder class methodsFor: 'processing' stamp: 'MPW 1/1/1901 01:20'!\\nprocess:anObject\\n\\t^self stream process:anObject.\\n\\n! !\\nNetworkTerminalMorph subclass: #NullTerminalMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NullTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/22/2000 07:20'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds fillStyle: Color orange.\\n\\taCanvas frameRectangle: self bounds color: Color black! !\\n\\n!NullTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/22/2000 07:22'!\\nforceToFront: aRegion\\n\\t\\\"force the given region from the drawing form onto the background form\\\"\\n\\tself updateBackgroundForm.\\n\\n! !\\n\\n\\n!NullTerminalMorph methodsFor: 'geometry' stamp: 'sd 11/20/2005 21:26'!\\nextent: newExtent\\n\\n\\t| aPoint |\\n\\taPoint := 50@50.\\n\\tbounds extent = aPoint ifFalse: [\\n\\t\\tself changed.\\n\\t\\tbounds := bounds topLeft extent: aPoint.\\n\\t\\tself layoutChanged.\\n\\t\\tself changed\\n\\t].\\n\\teventEncoder sendViewExtent: newExtent! !\\nMagnitude subclass: #Number\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Numbers'!\\n!Number commentStamp: '<historical>' prior: 0!\\nClass Number holds the most general methods for dealing with numbers. Subclasses Float, Fraction, and Integer, and their subclasses, provide concrete representations of a numeric quantity.\\n\\nAll of Number's subclasses participate in a simple type coercion mechanism that supports mixed-mode arithmetic and comparisons. It works as follows: If\\n\\tself<typeA> op: arg<typeB>\\nfails because of incompatible types, then it is retried in the following guise:\\n\\t(arg adaptTypeA: self) op: arg adaptToTypeA.\\nThis gives the arg of typeB an opportunity to resolve the incompatibility, knowing exactly what two types are involved. If self is more general, then arg will be converted, and viceVersa. This mechanism is extensible to any new number classes that one might wish to add to Squeak. The only requirement is that every subclass of Number must support a pair of conversion methods specific to each of the other subclasses of Number.!\\n\\n\\n!Number methodsFor: 'arithmetic'!\\n* aNumber \\n\\t\\\"Answer the result of multiplying the receiver by aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n+ aNumber \\n\\t\\\"Answer the sum of the receiver and aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n- aNumber \\n\\t\\\"Answer the difference between the receiver and aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n/ aNumber \\n\\t\\\"Answer the result of dividing the receiver by aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n// aNumber \\n\\t\\\"Integer quotient defined by division with truncation toward negative \\n\\tinfinity. 9//4 = 2, -9//4 = -3. -0.9//0.4 = -3. \\\\\\\\ answers the remainder \\n\\tfrom this division.\\\"\\n\\n\\t^(self / aNumber) floor! !\\n\\n!Number methodsFor: 'arithmetic'!\\n\\\\\\\\ aNumber \\n\\t\\\"modulo. Remainder defined in terms of //. Answer a Number with the \\n\\tsame sign as aNumber. e.g. 9\\\\\\\\4 = 1, -9\\\\\\\\4 = 3, 9\\\\\\\\-4 = -3, 0.9\\\\\\\\0.4 = 0.1.\\\"\\n\\n\\t^self - (self // aNumber * aNumber)! !\\n\\n!Number methodsFor: 'arithmetic'!\\nabs\\n\\t\\\"Answer a Number that is the absolute value (positive magnitude) of the \\n\\treceiver.\\\"\\n\\n\\tself < 0\\n\\t\\tifTrue: [^self negated]\\n\\t\\tifFalse: [^self]! !\\n\\n!Number methodsFor: 'arithmetic' stamp: 'mk 10/27/2003 21:00'!\\narg\\n\\t\\\"Answer the argument of the receiver (see Complex | arg).\\\"\\n\\t\\n\\tself isZero ifTrue: [self error: 'Zero (0 + 0 i) does not have an argument.'].\\n\\t0 < self\\n\\t\\tifTrue: [^ 0]\\n\\t\\tifFalse: [^ Float pi]! !\\n\\n!Number methodsFor: 'arithmetic'!\\nnegated\\n\\t\\\"Answer a Number that is the negation of the receiver.\\\"\\n\\n\\t^0 - self! !\\n\\n!Number methodsFor: 'arithmetic'!\\nquo: aNumber \\n\\t\\\"Integer quotient defined by division with truncation toward zero. -9 quo: \\n\\t4 = -2, -0.9 quo: 0.4 = -2. rem: answers the remainder from this division.\\\"\\n\\n\\t^(self / aNumber) truncated! !\\n\\n!Number methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'!\\nreciprocal\\n\\t\\\"Answer 1 divided by the receiver. Create an error notification if the \\n\\treceiver is 0.\\\"\\n\\t#Numeric.\\n\\t\\\"Changed 200/01/19 For ANSI <number> support.\\\"\\n\\tself = 0 ifTrue: [^ (ZeroDivide dividend: self) signal\\\"<- Chg\\\"].\\n\\t^ 1 / self! !\\n\\n!Number methodsFor: 'arithmetic'!\\nrem: aNumber \\n\\t\\\"Remainder defined in terms of quo:. Answer a Number with the same \\n\\tsign as self. e.g. 9 rem: 4 = 1, -9 rem: 4 = -1. 0.9 rem: 0.4 = 0.1.\\\"\\n\\n\\t^self - ((self quo: aNumber) * aNumber)! !\\n\\n\\n!Number methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'!\\ncloseTo: num\\n\\t\\\"are these two numbers close?\\\"\\n\\n\\t| ans |\\n\\tnum isFloat ifTrue: [^ num closeTo: self asFloat].\\n\\t[ans _ self = num] ifError: [:aString :aReceiver | ^ false].\\n\\t^ ans! !\\n\\n\\n!Number methodsFor: 'converting' stamp: 'avi 9/6/2005 22:07'!\\nprintShowingDecimalPlaces: placesDesired\\n\\t\\\"Print the receiver showing precisely the given number of places desired . If the placesDesired provided is positive, a decimal point and that many digits after the decimal point will always be shown. If the placesDesired is zero, a whole number will be shown, without a decimal point. This method could probably be greatly optimized -- improvements welcomed.\\\"\\n\\n\\t| precision rounded integerString fractionString |\\n\\tplacesDesired <= 0 ifTrue: [^ self rounded printString].\\n\\tprecision _ Utilities floatPrecisionForDecimalPlaces: placesDesired.\\n\\trounded _ self roundTo: precision.\\n\\tintegerString _ rounded integerPart asInteger asString.\\n\\tfractionString _ (rounded fractionPart abs / precision) asInteger asString.\\n\\t^ String streamContents:\\n\\t\\t[:s |\\n\\t\\ts nextPutAll: integerString.\\n\\t\\ts nextPut: $..\\n\\t\\t(placesDesired - fractionString size) timesRepeat: [s nextPut: $0].\\n\\t\\ts nextPutAll: fractionString]\\n\\\"\\n23 printShowingDecimalPlaces: 2\\n23.5698 printShowingDecimalPlaces: 2\\n-234.567 printShowingDecimalPlaces: 5\\n23.4567 printShowingDecimalPlaces: 0\\n100000000 printShowingDecimalPlaces: 1\\n\\\"! !\\n\\n!Number methodsFor: 'converting'!\\n@ y \\n\\t\\\"Primitive. Answer a Point whose x value is the receiver and whose y \\n\\tvalue is the argument. Optional. No Lookup. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 18>\\n\\t^Point x: self y: y! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:43'!\\nadaptToCollection: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Collection, return a Collection of\\n\\tthe results of each element combined with me in that expression.\\\"\\n\\n\\t^ rcvr collect: [:element | element perform: selector with: self]! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:21'!\\nadaptToFloat: rcvr andSend: selector \\n\\t\\\"If I am involved in arithmetic with a Float, convert me to a Float.\\\"\\n\\t^ rcvr perform: selector with: self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToFraction: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Fraction, convert us and evaluate exprBlock.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToInteger: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Integer, convert us and evaluate exprBlock.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToPoint: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Point, convert me to a Point.\\\"\\n\\t^ rcvr perform: selector with: self@self! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nadaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector \\n\\t\\\"Do any required conversion and then the arithmetic. \\n\\treceiverScaledDecimal arithmeticOpSelector self.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ScaledDecimal support.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:45'!\\nadaptToString: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a String, convert it to a Number.\\\"\\n\\t^ rcvr asNumber perform: selector with: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'ar 5/20/2001 01:40'!\\nasB3DVector3\\n\\t^self@self@self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/13/2003 10:13'!\\nasDuration\\n\\n\\n\\n\\t^ Duration nanoSeconds: self asInteger\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatD\\n\\t\\\"Answer a d precision floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatE\\n\\t\\\"Answer a floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatQ\\n\\t\\\"Answer a floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting'!\\nasInteger\\n\\t\\\"Answer an Integer nearest the receiver toward zero.\\\"\\n\\n\\t^self truncated! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 2/16/1999 18:15'!\\nasNumber\\n\\t^ self! !\\n\\n!Number methodsFor: 'converting'!\\nasPoint\\n\\t\\\"Answer a Point with the receiver as both coordinates; often used to \\n\\tsupply the same value in two dimensions, as with symmetrical gridding \\n\\tor scaling.\\\"\\n\\n\\t^self @ self! !\\n\\n!Number methodsFor: 'converting' stamp: 'dtl 9/25/2004 11:47'!\\nasScaledDecimal\\n\\t\\\"Answer a scaled decimal number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\n\\t^ self asScaledDecimal: 8\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasScaledDecimal: scale \\n\\t\\\"Answer a scaled decimal number, with a fractional precision of scale, \\n\\tapproximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For number protocol.\\\"\\n\\t^ ScaledDecimal newFromNumber: self scale: scale! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 9/8/97 16:30'!\\nasSmallAngleDegrees\\n\\t\\\"Return the receiver normalized to lie within the range (-180, 180)\\\"\\n\\n\\t| pos |\\n\\tpos _ self \\\\\\\\ 360.\\n\\tpos > 180 ifTrue: [pos _ pos - 360].\\n\\t^ pos\\n\\n\\\"#(-500 -300 -150 -5 0 5 150 300 500 1200) collect: [:n | n asSmallAngleDegrees]\\\"! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 10/7/1999 12:24'!\\nasSmallPositiveDegrees\\n\\t\\\"Return the receiver normalized to lie within the range (0, 360)\\\"\\n\\n\\t| result |\\n\\tresult _ self.\\n\\t[result < 0] whileTrue: [result _ result + 360].\\n\\t^ result \\\\\\\\ 360\\n\\n\\\"#(-500 -300 -150 -5 0 5 150 300 500 1200) collect: [:n | n asSmallPositiveDegrees]\\\"! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:12'!\\nday\\n\\n\\n\\n\\t^ self sign days! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\ndays\\n\\n\\n\\n\\t^ Duration days: self! !\\n\\n!Number methodsFor: 'converting'!\\ndegreesToRadians\\n\\t\\\"The receiver is assumed to represent degrees. Answer the conversion to \\n\\tradians.\\\"\\n\\n\\t^self asFloat degreesToRadians! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:28'!\\nhour\\n\\n\\n\\n\\t^ self sign hours\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\nhours\\n\\n\\n\\n\\t^ Duration hours: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'mk 10/27/2003 18:17'!\\ni\\n\\t^ Complex real: 0 imaginary: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:26'!\\nmilliSecond\\n\\n\\n\\n\\t^ self sign milliSeconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 9/25/2003 13:16'!\\nmilliSeconds\\n\\n\\n\\n\\t^ Duration milliSeconds: self\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:16'!\\nminute\\n\\n\\n\\n\\t^ self sign minutes\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\nminutes\\n\\n\\n\\n\\t^ Duration minutes: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:27'!\\nnanoSecond\\n\\n\\n\\n\\t^ self sign nanoSeconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 08:52'!\\nnanoSeconds\\n\\n\\n\\n\\t^ Duration nanoSeconds: self.! !\\n\\n!Number methodsFor: 'converting'!\\nradiansToDegrees\\n\\t\\\"The receiver is assumed to represent radians. Answer the conversion to \\n\\tdegrees.\\\"\\n\\n\\t^self asFloat radiansToDegrees! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:17'!\\nsecond\\n\\n\\n\\n\\t^ self sign seconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:57'!\\nseconds\\n\\n\\n\\n\\t^ Duration seconds: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/21/2003 08:20'!\\nsign: aNumber\\n\\n\\t\\\"Return a Number with the same sign as aNumber\\\"\\n\\n\\n\\n\\t^ aNumber positive ifTrue: [self abs] ifFalse: [self abs negated].! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:19'!\\nweek\\n\\n\\n\\n\\t^ self sign weeks\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:57'!\\nweeks\\n\\n\\n\\n\\t^ Duration weeks: self! !\\n\\n\\n!Number methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'!\\nbyteEncode:aStream\\n\\t^aStream writeNumber:self.\\n! !\\n\\n\\n!Number methodsFor: 'intervals'!\\nto: stop\\n\\t\\\"Answer an Interval from the receiver up to the argument, stop, \\n\\tincrementing by 1.\\\"\\n\\n\\t^Interval from: self to: stop by: 1! !\\n\\n!Number methodsFor: 'intervals'!\\nto: stop by: step\\n\\t\\\"Answer an Interval from the receiver up to the argument, stop, \\n\\tincrementing by step.\\\"\\n\\n\\t^Interval from: self to: stop by: step! !\\n\\n!Number methodsFor: 'intervals' stamp: 'tao 1/30/1999 08:58'!\\nto: stop by: step do: aBlock \\n\\t\\\"Normally compiled in-line, and therefore not overridable.\\n\\tEvaluate aBlock for each element of the interval (self to: stop by: \\nstep).\\\"\\n\\t| nextValue |\\n\\tnextValue _ self.\\n\\tstep = 0 ifTrue: [self error: 'step must be non-zero'].\\n\\tstep < 0\\n\\t\\tifTrue: [[stop <= nextValue]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\t\\t\\tnextValue _ nextValue + step]]\\n\\t\\tifFalse: [[stop >= nextValue]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\t\\t\\tnextValue _ nextValue + step]]! !\\n\\n!Number methodsFor: 'intervals'!\\nto: stop do: aBlock \\n\\t\\\"Normally compiled in-line, and therefore not overridable.\\n\\tEvaluate aBlock for each element of the interval (self to: stop by: 1).\\\"\\n\\t| nextValue |\\n\\tnextValue _ self.\\n\\t[nextValue <= stop]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\tnextValue _ nextValue + 1]! !\\n\\n\\n!Number methodsFor: 'mathematical functions'!\\narcCos \\n\\t\\\"The receiver is the cosine of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcCos! !\\n\\n!Number methodsFor: 'mathematical functions'!\\narcSin\\n\\t\\\"The receiver is the sine of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcSin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\narcTan\\n\\t\\\"The receiver is the tangent of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcTan! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'jsp 2/24/1999 15:20'!\\narcTan: denominator\\n\\t\\\"The receiver is the tangent of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^(self asFloat) arcTan: denominator.! !\\n\\n!Number methodsFor: 'mathematical functions'!\\ncos\\n\\t\\\"The receiver represents an angle measured in radians. Answer its cosine.\\\"\\n\\n\\t^self asFloat cos! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'!\\ndegreeCos\\n\\t\\\"Answer the cosine of the receiver taken as an angle in degrees.\\\"\\n\\t\\n\\t^ (90 + self) degreeSin! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'!\\ndegreeSin\\n\\t\\\"Answer the sine of the receiver taken as an angle in degrees.\\\"\\n\\t\\n\\t^ self asFloat degreesToRadians sin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nexp\\n\\t\\\"Answer the exponential of the receiver as a floating point number.\\\"\\n\\n\\t^self asFloat exp! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'jm 3/27/98 06:16'!\\nfloorLog: radix\\n\\t\\\"Answer the floor of the log base radix of the receiver.\\\"\\n\\n\\t^ self asFloat floorLog: radix\\n! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'ar 8/31/2000 20:05'!\\ninterpolateTo: aNumber at: param\\n\\t^self + (aNumber - self * param)! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nln\\n\\t\\\"Answer the natural log of the receiver.\\\"\\n\\n\\t^self asFloat ln! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'di 9/8/1998 17:10'!\\nlog\\n\\t\\\"Answer the base-10 log of the receiver.\\\"\\n\\n\\t^self asFloat log! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nlog: aNumber \\n\\t\\\"Answer the log base aNumber of the receiver.\\\"\\n\\n\\t^self ln / aNumber ln! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'RJ 3/15/1999 19:35'!\\nraisedTo: aNumber \\n\\t\\\"Answer the receiver raised to aNumber.\\\"\\n\\n\\taNumber isInteger ifTrue:\\n\\t\\t[\\\"Do the special case of integer power\\\"\\n\\t\\t^ self raisedToInteger: aNumber].\\n\\tself < 0 ifTrue:\\n\\t\\t[ self error: self printString, ' raised to a non-integer power' ].\\n\\taNumber = 0 ifTrue: [^ 1].\\t\\t\\\"Special case of exponent=0\\\"\\n\\t(self = 0) | (aNumber = 1) ifTrue:\\n\\t\\t[^ self].\\t\\t\\t\\t\\t\\t\\\"Special case of exponent=1\\\"\\n\\t^ (aNumber * self ln) exp\\t\\t\\\"Otherwise use logarithms\\\"! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'RAH 4/25/2000 19:49'!\\nraisedToInteger: operand \\n\\t\\\"Answer the receiver raised to the power operand, an Integer.\\\"\\n\\t| count result |\\n\\t#Numeric.\\n\\t\\\"Changed 200/01/19 For ANSI <number> support.\\\"\\n\\toperand isInteger ifFalse: [^ ArithmeticError signal: 'parameter is not an Integer'\\\"<- Chg\\\"].\\n\\toperand = 0 ifTrue: [^ self class one].\\n\\toperand = 1 ifTrue: [^ self].\\n\\toperand < 0 ifTrue: [^ (self raisedToInteger: operand negated) reciprocal].\\n\\tcount := 1.\\n\\t[(count := count + count) < operand] whileTrue.\\n\\tresult := self class one.\\n\\t[count > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[result := result * result.\\n\\t\\t\\t(operand bitAnd: count)\\n\\t\\t\\t\\t= 0 ifFalse: [result := result * self].\\n\\t\\t\\tcount := count bitShift: -1].\\n\\t^ result! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsin\\n\\t\\\"The receiver represents an angle measured in radians. Answer its sine.\\\"\\n\\n\\t^self asFloat sin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsqrt\\n\\t\\\"Answer the square root of the receiver.\\\"\\n\\n\\t^self asFloat sqrt! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsquared\\n\\t\\\"Answer the receiver multipled by itself.\\\"\\n\\n\\t^self * self! !\\n\\n!Number methodsFor: 'mathematical functions'!\\ntan\\n\\t\\\"The receiver represents an angle measured in radians. Answer its \\n\\ttangent.\\\"\\n\\n\\t^self asFloat tan! !\\n\\n\\n!Number methodsFor: 'printing'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\n\\t^ super defaultLabelForInspector, ': ', self printString! !\\n\\n!Number methodsFor: 'printing' stamp: 'sw 6/29/1999 21:10'!\\nisOrAreStringWith: aNoun\\n\\t| result |\\n\\tresult _ self = 1\\n\\t\\tifTrue:\\n\\t\\t\\t[' is one ']\\n\\t\\tifFalse:\\n\\t\\t\\t[self = 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[' are no ']\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[' are ', self printString, ' ']].\\n\\tresult _ result, aNoun.\\n\\tself = 1 ifFalse: [result _ result, 's'].\\n\\t^ result\\n\\n\\\"#(0 1 2 98.6) do:\\n\\t[:num | Transcript cr; show: 'There', (num isOrAreStringWith: 'way'), ' to skin a cat']\\\"! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:53'!\\nprintOn: aStream\\n\\tself printOn: aStream base: 10! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:55'!\\nprintOn: aStream base: base\\n\\t^self subclassResponsibility! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/30/2004 10:50'!\\nprintString\\n\\t^self printStringBase: 10! !\\n\\n!Number methodsFor: 'printing'!\\nprintStringBase: base\\n\\t^ String streamContents:\\n\\t\\t[:strm | self printOn: strm base: base]! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:50'!\\nstoreOn: aStream \\n\\tself printOn: aStream! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:59'!\\nstoreOn: aStream base: base\\n\\tself printOn: aStream base: base! !\\n\\n!Number methodsFor: 'printing'!\\nstoreStringBase: base\\n\\t^ String streamContents: [:strm | self storeOn: strm base: base]! !\\n\\n!Number methodsFor: 'printing' stamp: 'sw 7/1/1998 12:33'!\\nstringForReadout\\n\\t^ self rounded printString! !\\n\\n\\n!Number methodsFor: 'testing' stamp: 'sw 9/27/2001 17:26'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t^ #Number! !\\n\\n!Number methodsFor: 'testing'!\\neven\\n\\t\\\"Answer whether the receiver is an even number.\\\"\\n\\n\\t^self \\\\\\\\ 2 = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'sw 12/30/1998 13:21'!\\nisDivisibleBy: aNumber\\n\\taNumber = 0 ifTrue: [^ false].\\n\\taNumber isInteger ifFalse: [^ false].\\n\\t^ (self \\\\\\\\ aNumber) = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'!\\nisInf\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 4/19/98 23:33'!\\nisInfinite\\n\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'!\\nisNaN\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing'!\\nisNumber\\n\\t^ true! !\\n\\n!Number methodsFor: 'testing'!\\nisZero\\n\\t^self = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:18'!\\nnegative\\n\\t\\\"Answer whether the receiver is mathematically negative.\\\"\\n\\n\\t^ self < 0! !\\n\\n!Number methodsFor: 'testing'!\\nodd\\n\\t\\\"Answer whether the receiver is an odd number.\\\"\\n\\n\\t^self even == false! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:17'!\\npositive\\n\\t\\\"Answer whether the receiver is positive or equal to 0. (ST-80 protocol).\\n\\tSee also strictlyPositive\\\"\\n\\n\\t^ self >= 0! !\\n\\n!Number methodsFor: 'testing'!\\nsign\\n\\t\\\"Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0.\\\"\\n\\n\\tself > 0 ifTrue: [^1].\\n\\tself < 0 ifTrue: [^-1].\\n\\t^0! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:02'!\\nstrictlyPositive\\n\\t\\\"Answer whether the receiver is mathematically positive.\\\"\\n\\n\\t^ self > 0! !\\n\\n\\n!Number methodsFor: 'truncation and round off'!\\nceiling\\n\\t\\\"Answer the integer nearest the receiver toward positive infinity.\\\"\\n\\n\\tself <= 0.0\\n\\t\\tifTrue: [^self truncated]\\n\\t\\tifFalse: [^self negated floor negated]! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'di 2/19/98 21:58'!\\ndetentBy: detent atMultiplesOf: grid snap: snap\\n\\t\\\"Map all values that are within detent/2 of any multiple of grid to that multiple. Otherwise, if snap is true, return self, meaning that the values in the dead zone will never be returned. If snap is false, then expand the range between dead zones so that it covers the range between multiples of the grid, and scale the value by that factor.\\\"\\n\\t| r1 r2 |\\n\\tr1 _ self roundTo: grid. \\\"Nearest multiple of grid\\\"\\n\\t(self roundTo: detent) = r1 ifTrue: [^ r1]. \\\"Snap to that multiple...\\\"\\n\\tsnap ifTrue: [^ self]. \\\"...or return self\\\"\\n\\n\\tr2 _ self < r1 \\\"Nearest end of dead zone\\\"\\n\\t\\tifTrue: [r1 - (detent asFloat/2)]\\n\\t\\tifFalse: [r1 + (detent asFloat/2)].\\n\\t\\\"Scale values between dead zones to fill range between multiples\\\"\\n\\t^ r1 + ((self - r2) * grid asFloat / (grid - detent))\\n\\\"\\n\\t(170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: true] \\t(170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: false]\\n\\t(3.9 to: 4.1 by: 0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: true] \\t(-3.9 to: -4.1 by: -0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: false]\\n\\\"! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nfloor\\n\\t\\\"Answer the integer nearest the receiver toward negative infinity.\\\"\\n\\n\\t| truncation |\\n\\ttruncation _ self truncated.\\n\\tself >= 0 ifTrue: [^truncation].\\n\\tself = truncation\\n\\t\\tifTrue: [^truncation]\\n\\t\\tifFalse: [^truncation - 1]! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'!\\nfractionPart\\n\\t\\\"Answer the fractional part of the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"2000/03/04 Harmon R. Added ANSI <number> protocol\\\"\\n\\t^ self - self truncated! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'!\\nintegerPart\\n\\t\\\"Answer the integer part of the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"2000/03/04 Harmon R. Added ANSI <number> protocol\\\"\\n\\t^ self truncated! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nreduce\\n \\\"If self is close to an integer, return that integer\\\"\\n ^ self! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'di 10/4/1999 08:08'!\\nroundTo: quantum \\n\\t\\\"Answer the nearest number that is a multiple of quantum.\\\"\\n\\n\\t^(self / quantum) rounded * quantum! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nroundUpTo: aNumber \\n\\t\\\"Answer the next multiple of aNumber toward infinity that is nearest the \\n\\treceiver.\\\"\\n\\n\\t^(self/aNumber) ceiling * aNumber! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nrounded\\n\\t\\\"Answer the integer nearest the receiver.\\\"\\n\\n\\t^(self + (self sign / 2)) truncated! !\\n\\n!Number methodsFor: 'truncation and round off'!\\ntruncateTo: aNumber \\n\\t\\\"Answer the next multiple of aNumber toward zero that is nearest the \\n\\treceiver.\\\"\\n\\n\\t^(self quo: aNumber)\\n\\t\\t* aNumber! !\\n\\n!Number methodsFor: 'truncation and round off'!\\ntruncated\\n\\t\\\"Answer an integer nearest the receiver toward zero.\\\"\\n\\n\\t^self quo: 1! !\\n\\n\\n!Number methodsFor: '*eToys-printing' stamp: 'sw 10/31/97 13:54'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new addArrows; setLiteral: self; addSuffixIfCan\\n! !\\n\\n\\n!Number methodsFor: '*eToys-vocabulary' stamp: 'sw 8/3/2001 13:43'!\\nvocabularyDemanded\\n\\t\\\"Answer the vocabulary normally preferred by this object\\\"\\n\\n\\t^ Vocabulary numberVocabulary! !\\n\\n\\n!Number methodsFor: '*Morphic-NewCurve-testing' stamp: 'jmv 2/21/2006 13:15'!\\nisNonZero\\n\\t\\\"Return true for numbers not zero and false for all other\\n\\tobjects \\\"\\n\\t^ self isZero not! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNumber class\\n\\tinstanceVariableNames: ''!\\n\\n!Number class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 21:46'!\\nreadExactlyFrom: stringOrStream \\n\\t\\\"Answer a number as described on aStream. The number may\\n\\tinclude a leading radix specification, as in 16rFADE\\\"\\n\\t\\n\\t^(SqNumberParser on: stringOrStream) nextNumber! !\\n\\n!Number class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 22:40'!\\nreadFrom: stringOrStream \\n\\t\\\"Answer a number as described on aStream. The number may\\n\\tinclude a leading radix specification, as in 16rFADE\\\"\\n\\t| value base aStream sign |\\n\\taStream _ (stringOrStream isString)\\n\\t\\tifTrue: [ReadStream on: stringOrStream]\\n\\t\\tifFalse: [stringOrStream].\\n\\t(aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan].\\n\\tsign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1].\\n\\t(aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign].\\n\\tbase _ 10.\\n\\tvalue _ Integer readFrom: aStream base: base.\\n\\t(aStream peekFor: $r)\\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"<base>r<integer>\\\"\\n\\t\\t\\t(base _ value) < 2 ifTrue: [^self error: 'Invalid radix'].\\n\\t\\t\\t(aStream peekFor: $-) ifTrue: [sign _ sign negated].\\n\\t\\t\\tvalue _ Integer readFrom: aStream base: base].\\n\\t^ self readRemainderOf: value from: aStream base: base withSign: sign.! !\\n\\n!Number class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 22:41'!\\nreadFrom: stringOrStream base: base\\n\\t\\\"Answer a number as described on aStream in the given number base.\\\"\\n\\n\\t| aStream sign |\\n\\taStream _ (stringOrStream isString)\\n\\t\\tifTrue: [ReadStream on: stringOrStream]\\n\\t\\tifFalse: [stringOrStream].\\n\\t(aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan].\\n\\tsign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1].\\n\\t(aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign].\\n\\t^ self readRemainderOf: (Integer readFrom: aStream base: base)\\n\\t\\t\\tfrom: aStream base: base withSign: sign! !\\n\\n\\n!Number class methodsFor: 'private' stamp: 'dtl 7/3/2006 17:41'!\\nreadExponent: baseValue base: base from: aStream\\n\\t\\\"Complete creation of a number, reading exponent from aStream. Answer the\\n\\tnumber, or nil if parsing fails.\\n\\t<number>(e|d|q)<exponent>>\\\"\\n\\n\\t| sign exp value |\\n\\t('edq' includes: aStream next) ifFalse: [^ nil].\\n\\tsign := ((aStream peek) == $-)\\n\\t\\tifTrue: [aStream next. -1]\\n\\t\\tifFalse: [1].\\n\\t(aStream atEnd or: [(aStream peek digitValue between: 0 and: 9) not])\\n\\t\\tifTrue: [^ nil]. \\\"Avoid throwing an error\\\"\\n\\texp := (Integer readFrom: aStream base: 10) * sign.\\n\\tvalue := baseValue * (base raisedTo: exp).\\n\\t^ value\\n! !\\n\\n!Number class methodsFor: 'private' stamp: 'dtl 7/4/2006 08:32'!\\nreadRemainderOf: integerPart from: aStream base: base withSign: sign \\n\\t\\\"Read optional fractional part and exponent or decimal scale, and return the final result\\\"\\n\\t\\\"Changed 200/01/19 For ANSI Numeric Literals support.\\\"\\n\\t\\\"Number readFrom: '3r-22.2'\\\"\\n\\n\\t| value fractionDigits fracpos fractionPart fraction pos v foundDecimal |\\n\\t#Numeric.\\n\\tvalue := integerPart.\\n\\tfractionDigits := 0.\\n\\tfoundDecimal := false.\\n\\t(aStream peekFor: $.)\\n\\t\\tifTrue: [\\\"<integer>.<fraction>\\\"\\n\\t\\t\\tfoundDecimal := true.\\n\\t\\t\\t(aStream atEnd not\\n\\t\\t\\t\\t\\tand: [aStream peek digitValue between: 0 and: base - 1])\\n\\t\\t\\t\\tifTrue: [fracpos := aStream position.\\n\\t\\t\\t\\t\\tfractionPart := Integer readFrom: aStream base: base.\\n\\t\\t\\t\\t\\tfraction := fractionPart asFloat\\n\\t\\t\\t\\t\\t\\t\\t\\t/ (base raisedTo: aStream position - fracpos).\\n\\t\\t\\t\\t\\tfractionDigits := aStream position - fracpos.\\n\\t\\t\\t\\t\\tvalue := value asFloat + fraction]].\\n\\n\\tpos := aStream position.\\n\\t(v := self readScaledDecimal: integerPart\\n\\t\\t\\tfractionPart: fractionPart\\n\\t\\t\\tdigits: fractionDigits\\n\\t\\t\\tbase: base\\n\\t\\t\\tsign: sign\\n\\t\\t\\tfrom: aStream)\\n\\t\\tifNil: [aStream position: pos]\\n\\t\\tifNotNil: [^ v \\\"<number>s<scale>>\\\"].\\n\\n\\tpos := aStream position.\\n\\t(v := self readExponent: value base: base from: aStream)\\n\\t\\tifNil: [aStream position: pos.\\n\\t\\t\\t(foundDecimal and: [fractionDigits = 0])\\n\\t\\t\\t\\tifTrue: [\\\"oops - just <integer>.\\\"\\n\\t\\t\\t\\t\\t\\t\\taStream skip: -1.\\n\\t\\t\\t\\t\\t\\t\\t\\\"un-gobble the period\\\"\\n\\t\\t\\t\\t\\t\\t\\t^ value * sign]]\\n\\t\\tifNotNil: [value := v \\\"<number>(e|d|q)<exponent>>\\\"].\\n\\n\\t(value isFloat\\n\\t\\t\\tand: [value = 0.0\\n\\t\\t\\t\\t\\tand: [sign = -1]])\\n\\t\\tifTrue: [^ Float negativeZero]\\n\\t\\tifFalse: [^ value * sign]! !\\n\\n!Number class methodsFor: 'private' stamp: 'md 7/15/2006 18:00'!\\nreadScaledDecimal: integerPart fractionPart: fractionPart digits: fractionDigits base: base sign: sign from: aStream \\n\\t\\\"Complete creation of a ScaledDecimal, reading scale from aStream. Answer\\n\\ta ScaledDecimal, or nil if parsing fails.\\n\\t<number>s[<scale>]\\\"\\n\\n\\t| scale decimalMultiplier decimalFraction |\\n\\taStream atEnd ifTrue: [^ nil].\\n\\t(aStream next == $s) ifFalse: [^ nil].\\n\\t\\\"<number>s<scale>\\\"\\n\\t(aStream atEnd not and: [aStream peek digitValue between: 0 and: 9])\\n\\t\\tifTrue: [scale := Integer readFrom: aStream]\\n\\t\\tifFalse: [^ nil].\\n\\tscale isNil\\n\\t\\tifTrue: [\\\"<number>s\\\"\\n\\t\\t\\tfractionDigits = 0\\n\\t\\t\\t\\tifTrue: [\\\"<integer>s\\\"\\n\\t\\t\\t\\t\\tscale := 0]\\n\\t\\t\\t\\tifFalse: [\\\"<integer>.<fraction>s\\\"\\n\\t\\t\\t\\t\\tscale := fractionDigits]].\\n\\tfractionPart isNil\\n\\t\\tifTrue: [^ ScaledDecimal newFromNumber: integerPart * sign scale: scale]\\n\\t\\tifFalse: [decimalMultiplier := base raisedTo: fractionDigits.\\n\\t\\t\\tdecimalFraction := integerPart * decimalMultiplier + fractionPart * sign / decimalMultiplier.\\n\\t\\t\\t^ ScaledDecimal newFromNumber: decimalFraction scale: scale]! !\\nTestCase subclass: #NumberParsingTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n!NumberParsingTest commentStamp: 'dtl 11/24/2004 15:35' prior: 0!\\nTests to verify parsing of numbers from streams and strings.\\n\\nNote: ScaledDecimalTest contains related tests for parsing ScaledDecimal.!\\n\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:29'!\\ntestFloatFromStreamAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs _ '10r-12.3456' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -12.3456 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456e2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456e2e2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs upToEnd = 'e2'.\\n\\n\\trs _ '10r-12.3456d2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '-12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '12.3456z2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 12.3456 = aFloat.\\n\\tself assert: rs upToEnd = 'z2'.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'nice 4/28/2006 01:20'!\\ntestFloatFromStreamWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs _ '1.0e-14' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '1.0e-14 1' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = ' 1'.\\n\\n\\trs _ '1.0e-14eee' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = 'eee'.\\n\\n\\trs _ '1.0e14e10' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e14 = aFloat.\\n\\tself assert: rs upToEnd = 'e10'.\\n\\n\\trs _ '1.0e+14e' readStream. \\\"Plus sign is not parseable\\\"\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e+14e'.\\n\\n\\trs _ '1.0e' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e'.! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:07'!\\ntestFloatFromStringAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| aFloat |\\n\\taFloat _ '10r-12.3456' asNumber.\\n\\tself assert: -12.3456 = aFloat.\\n\\taFloat _ '10r-12.3456e2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '10r-12.3456d2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '10r-12.3456q2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '-12.3456q2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '12.3456q2' asNumber.\\n\\tself assert: 1234.56 = aFloat.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:12'!\\ntestFloatFromStringWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| aFloat |\\n\\taFloat _ '1.0e-14' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e-14 1' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e-14e' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e14e' asNumber.\\n\\tself assert: 1.0e14 = aFloat.\\n\\taFloat _ '1.0e+14e' asNumber. \\\"Plus sign is not parseable\\\"\\n\\tself assert: 1.0 = aFloat.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'nice 4/28/2006 01:39'!\\ntestFloatReadError\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs num |\\n\\trs := '1e' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 'e'.\\n\\t\\n\\trs := '1s' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 's'.\\n\\n\\trs := '1.' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: num isInteger.\\n\\tself assert: rs upToEnd = '.'.\\n\\t\\n\\trs := '' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := 'foo' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\n\\trs := 'radix' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '.e0' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '-.e0' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '--1' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 18:16'!\\ntestFloatReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber _ '2r1.0101e9' asNumber.\\n\\tself assert: 672.0 = aNumber.\\n\\tself assert: (Number readFrom: '2r1.0101e9') = (1.3125 * (2 raisedTo: 9)).\\n\\trs _ ReadStream on: '2r1.0101e9e9'.\\n\\tself assert: (Number readFrom: rs) = 672.0.\\n\\tself assert: rs upToEnd = 'e9'\\n! !\\n\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'dtl 11/24/2004 14:05'!\\ntestIntegerFromString\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tTrailing decimal points should be ignored.\\\"\\n\\n\\tself assert: ('123' asNumber == 123).\\n\\tself assert: ('-123' asNumber == -123).\\n\\tself assert: ('123.' asNumber == 123).\\n\\tself assert: ('-123.' asNumber == -123).\\n\\tself assert: ('123This is not to be read' asNumber == 123).\\n\\tself assert: ('123s could be confused with a ScaledDecimal' asNumber == 123).\\n\\tself assert: ('123e could be confused with a Float' asNumber == 123).\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'tween 7/8/2006 12:31'!\\ntestIntegerReadFrom\\n\\t\\\"Ensure remaining characters in a stream are not lost when parsing an integer.\\\"\\n\\n\\t| rs i s |\\n\\trs _ ReadStream on: '123s could be confused with a ScaledDecimal'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 's could be confused with a ScaledDecimal' = s.\\n\\trs _ ReadStream on: '123.s could be confused with a ScaledDecimal'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: '.s could be confused with a ScaledDecimal' = s.\\n\\trs _ ReadStream on: '123sA has unary message sA'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 'sA has unary message sA' = s.\\t\\n\\trs _ ReadStream on: '123sB has unary message sB'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 'sB has unary message sB' = s.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'dtl 11/24/2004 18:18'!\\ntestIntegerReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber _ '2r1e26' asNumber.\\n\\tself assert: 67108864 = aNumber.\\n\\tself assert: (Number readFrom: '2r1e26') = (2 raisedTo: 26).\\n\\trs _ '2r1e26eee' readStream.\\n\\tself assert: (Number readFrom: rs) = 67108864.\\n\\tself assert: rs upToEnd = 'eee'\\n! !\\nClassTestCase subclass: #NumberTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n\\n!NumberTest methodsFor: 'tests' stamp: 'fbs 3/8/2006 11:24'!\\ntestPrintShowingDecimalPlaces\\n\\n\\tself assert: (111.2 printShowingDecimalPlaces: 2) = '111.20'.\\n\\tself assert: (111.2 printShowingDecimalPlaces: 0) = '111'.\\n\\tself assert: (111 printShowingDecimalPlaces: 0) = '111'.\\n\\tself assert: (111111111111111 printShowingDecimalPlaces: 2) = '111111111111111.00'.\\n\\tself assert: (10 printShowingDecimalPlaces: 20) ='10.00000000000000000000'.\\n! !\\n\\n!NumberTest methodsFor: 'tests' stamp: 'sd 6/5/2005 08:56'!\\ntestReadFrom\\n\\t\\n\\tself assert: 1.0e-14\\t= (Number readFrom: '1.0e-14').\\n\\tself assert: 2r1e26\\t= (Number readFrom: '2r1e26').! !\\nDataType subclass: #NumberType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n!NumberType commentStamp: 'sw 10/3/2002 02:18' prior: 0!\\nNumberType is a data type representing a numeric value.!\\n\\n\\n!NumberType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ (1 to: 9) atRandom! !\\n\\n\\n!NumberType methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\t| aMethodCategory aMethodInterface |\\n\\tsuper initialize.\\n\\t\\\"Vocabulary replaceNumberVocabulary\\\"\\n\\t\\\"Vocabulary addVocabulary: Vocabulary newNumberVocabulary\\\"\\n\\n\\tself vocabularyName: #Number.\\n\\tself documentation: 'Numbers are things that can do arithmetic, have their magnitudes compared, etc.'.\\n\\n#((comparing\\t\\t\\t\\t'Determining which of two numbers is larger'\\n\\t\\t(= < > <= >= ~= ~~))\\n(arithmetic \\t\\t\\t\\t'Basic numeric operation'\\n\\t\\t(* + - / // \\\\\\\\ abs negated quo: rem:))\\n(testing \\t\\t\\t\\t\\t'Testing a number'\\n\\t\\t(even isDivisibleBy: negative odd positive sign))\\n(#'mathematical functions'\\t'Trigonometric and exponential functions'\\n\\t\\t(cos exp ln log log: raisedTo: sin sqrt squared tan raisedToInteger:))\\n(converting \\t\\t\\t\\t'Converting a number to another form'\\n\\t\\t(@ asInteger asPoint degreesToRadians radiansToDegrees asSmallAngleDegrees asSmallPositiveDegrees))\\n(#'truncation and round off' 'Making a real number (with a decimal point) into an integer'\\n\\t\\t(ceiling floor roundTo: roundUpTo: rounded truncateTo: truncated))\\n) do:\\n\\n\\t\\t[:item | \\n\\t\\t\\taMethodCategory := ElementCategory new categoryName: item first.\\n\\t\\t\\taMethodCategory documentation: item second.\\n\\t\\t\\titem third do:\\n\\t\\t\\t\\t[:aSelector | \\n\\t\\t\\t\\t\\taMethodInterface := MethodInterface new conjuredUpFor: aSelector class: (Number whichClassIncludesSelector: aSelector).\\n\\t\\t\\t\\t\\taMethodInterface argumentVariables do:\\n\\t\\t\\t\\t\\t\\t\\t[:var | var variableType: #Number].\\n\\n\\t\\t\\t\\t\\t(#(* + - / // \\\\\\\\ abs negated quo: rem:\\n\\t\\t\\t\\t\\t\\tcos exp ln log log: raisedTo: sin sqrt squared tan raisedToInteger:\\n\\t\\t\\t\\t\\t\\tasInteger degreesToRadians radiansToDegrees asSmallAngleDegrees asSmallPositiveDegrees)\\n\\t\\t\\t\\t\\t\\t\\tincludes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Number].\\n\\n\\t\\t\\t\\t\\t(#( @ asPoint ) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Point].\\n\\n\\t\\t\\t\\t\\t(#(= < > <= >= ~= ~~ even isDivisibleBy: negative odd positive) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Boolean].\\n\\n\\t\\t\\t\\t\\taMethodInterface setNotToRefresh. \\n\\t\\t\\t\\t\\tself atKey: aSelector putMethodInterface: aMethodInterface.\\n\\t\\t\\t\\t\\taMethodCategory elementAt: aSelector put: aMethodInterface].\\n\\t\\t\\tself addCategory: aMethodCategory].\\n\\n\\\"\\n(('truncation and round off' ceiling detentBy:atMultiplesOf:snap: floor roundTo: roundUpTo: rounded truncateTo: truncated)\\n('testing' basicType even isDivisibleBy: isInf isInfinite isNaN isNumber isZero negative odd positive sign strictlyPositive)\\n('converting' @ adaptToCollection:andSend: adaptToFloat:andSend: adaptToFraction:andSend: adaptToInteger:andSend: adaptToPoint:andSend: adaptToString:andSend: asInteger asNumber asPoint asSmallAngleDegrees asSmallPositiveDegrees degreesToRadians radiansToDegrees)\\n('intervals' to: to:by: to:by:do: to:do:)\\n('printing' defaultLabelForInspector isOrAreStringWith: newTileMorphRepresentative printOn: printStringBase: storeOn: storeOn:base: storeStringBase: stringForReadout)\\n('comparing' closeTo:)\\n('filter streaming' byteEncode:)\\n('as yet unclassified' reduce)\\\"\\n\\n\\n\\n! !\\n\\n\\n!NumberType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(0.8 0.4 0.2)! !\\n\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'dgd 9/6/2003 20:30'!\\naddExtraItemsToMenu: aMenu forSlotSymbol: slotSym\\n\\t\\\"If the receiver has extra menu items to add to the slot menu, here is its chance to do it. The defaultTarget of the menu is the player concerned.\\\"\\n\\n\\taMenu add: 'decimal places...' translated selector: #setPrecisionFor: argument: slotSym.\\n\\taMenu balloonTextForLastItem: 'Lets you choose how many decimal places should be shown in readouts for this variable' translated! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/15/2002 16:50'!\\naddUserSlotItemsTo: aMenu slotSymbol: slotSym\\n\\t\\\"Optionally add items to the menu that pertain to a user-defined slot of the given symbol\\\"\\n\\n\\t\\\"aMenu add: 'decimal places...' selector: #setPrecisionFor: argument: slotSym\\n\\tNB: This item is now generically added for system as well as user slots, so the addition is now done in NubmerType.addExtraItemsToMenu:forSlotSymbol:\\\"! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 02:53'!\\ncomparatorForSampleBoolean\\n\\t\\\"Answer the comparator to use in tile coercions involving the receiver; normally, the equality comparator is used but NumberType overrides\\\"\\n\\n\\t^ #<! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:30'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t^ 5 newTileMorphRepresentative typeColor: self typeColor! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:37'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ NumericReadoutTile new typeColor: Color lightGray lighter! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/26/2001 03:11'!\\nwantsAssignmentTileVariants\\n\\t\\\"Answer whether an assignment tile for a variable of this type should show variants to increase-by, decrease-by, multiply-by.\\\"\\n\\n\\t^ true! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/26/2001 03:18'!\\nwantsSuffixArrow\\n\\t\\\"Answer whether a tile showing data of this type would like to have a suffix arrow\\\"\\n\\n\\t^ true! !\\nTileMorph subclass: #NumericReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'ar 9/15/2000 23:27'!\\nabandonLabelFocus\\n\\t| aLabel |\\n\\t\\\"If the receiver's label has editing focus, abandon it\\\"\\n\\tself flag: #arNote. \\\"Probably unnecessary\\\"\\n\\t(aLabel _ self labelMorph) ifNotNil:\\n\\t\\t[aLabel hasFocus ifTrue:\\n\\t\\t\\t[aLabel contents: aLabel readFromTarget.\\n\\t\\t\\taLabel handsWithMeForKeyboardFocus do:\\n\\t\\t\\t\\t[:aHand | aHand releaseKeyboardFocus]]]! !\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'tak 12/6/2004 01:53'!\\nliteralFromContents\\n\\t| label |\\n\\tlabel _ self labelMorph\\n\\t\\t\\t\\tifNil: [^ super literal].\\n\\tlabel step.\\n\\t^ literal _ label valueFromContents! !\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'tak 4/6/2005 14:10'!\\nliteral: anObject \\n\\tliteral := anObject.\\n\\tself updateLiteralLabel.\\n\\tself labelMorph\\n\\t\\tifNotNilDo: [:label | label informTarget]! !\\n\\n\\n!NumericReadoutTile methodsFor: 'literal' stamp: 'sw 9/15/1999 15:14'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"like literal:width: but does not inform the target\\\"\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last setWidth: w.\\n\\tself updateLiteralLabel! !\\n\\n\\n!NumericReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:01'!\\nbasicWidth\\n\\t^ 26! !\\n\\n!NumericReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:18'!\\nminimumWidth\\n\\t^ 40! !\\n\\n\\n!NumericReadoutTile methodsFor: 'mouse' stamp: 'ar 10/25/2000 18:07'!\\nhandlesMouseMove: evt\\n\\t^true! !\\n\\n\\n!NumericReadoutTile methodsFor: 'parts bin' stamp: 'sw 11/15/2001 20:22'!\\ninitializeToStandAlone\\n\\t\\\"Enclose my prototype in a SyntaxMorph. For the ObjectTool\\\"\\n\\n\\t| aWatcher aTile aLine aColor ms slotMsg |\\n\\n\\tsuper initializeToStandAlone.\\n\\taColor _ Color r: 0.387 g: 0.581 b: 1.0.\\n\\taTile _ self typeColor: aColor.\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true;\\n\\t\\tgetSelector: nil;\\n\\t\\tputSelector: nil;\\n\\t\\tsetToAllowTextEdit.\\n\\taWatcher target: nil.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\n\\tms _ MessageSend receiver: nil selector: #aNumber arguments: #().\\n\\tslotMsg _ ms asTilesIn: Player globalNames: false.\\n\\t\\t\\\"For CardPlayers, use 'aPlayer'. For others, name it, and use its name.\\\"\\n\\tms _ MessageSend receiver: 3 selector: #= asSymbol arguments: #(5).\\n\\taLine _ ms asTilesIn: Player globalNames: false.\\n\\taLine firstSubmorph delete.\\t\\t\\\"A little over-complicated? Yes?\\\"\\n\\taLine addMorphFront: (slotMsg submorphs second) firstSubmorph.\\n\\taLine addMorphFront: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine lastSubmorph delete.\\n\\taLine lastSubmorph delete.\\n\\taLine color: aColor.\\n\\taLine addMorphBack: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine addMorphBack: aTile.\\n\\taLine cellPositioning: #leftCenter.\\n\\taWatcher step; fitContents.\\n\\t^ aLine markAsPartsDonor.! !\\n\\n\\n!NumericReadoutTile methodsFor: 'testing' stamp: 'tk 11/1/2001 12:41'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type I hold\\\"\\n\\n\\t\\\"Number String Boolean player collection sound color etc\\\"\\n\\t^ #Number! !\\n\\n\\n!NumericReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 23:36'!\\nmouseStillDown: evt \\n\\t(self labelMorph notNil\\n\\t\\t\\tand: [self labelMorph containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [^ self labelMorph mouseDown: evt].\\n\\t^ super mouseStillDown: evt! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNumericReadoutTile class\\n\\tinstanceVariableNames: ''!\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'tk 12/14/2001 19:32'!\\nborderedPrototype\\n\\t\\\"Just number and up/down arrows\\\"\\n\\n\\t| aWatcher aTile |\\n\\n\\taTile _ self new typeColor: (Color r: 0.387 g: 0.581 b: 1.0).\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true; setNameTo: 'value'.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows; setNameTo: 'Number (mid)'.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\taWatcher step; fitContents; setToAllowTextEdit.\\n\\t^ aTile extent: 30@24; markAsPartsDonor! !\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'tk 12/14/2001 19:29'!\\nsimplePrototype\\n\\t\\\"Bare number readout. Will keep up to data with a number once it has target, getterSelector, setterSelector.\\\"\\n\\n\\t^ (UpdatingStringMorph new) contents: '5'; growable: true; setToAllowTextEdit; \\n\\t\\tstep; fitContents; setNameTo: 'Number (bare)'; markAsPartsDonor! !\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'nk 8/23/2004 18:11'!\\nsupplementaryPartsDescriptions\\n\\t\\\"Answer additional items for the parts bin\\\"\\n\\n\\tPreferences universalTiles ifFalse: [^ #()].\\n\\n\\t^ {DescriptionForPartsBin\\n\\t\\tformalName: 'Number (fancy)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value. Shift-click on title to edit.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #authoringPrototype.\\n\\n\\t DescriptionForPartsBin\\n\\t\\tformalName: 'Number (bare)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #simplePrototype.\\n\\n\\t DescriptionForPartsBin\\n\\t\\tformalName: 'Number (mid)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #borderedPrototype}! !\\n\\n\\n!NumericReadoutTile class methodsFor: 'scripting' stamp: 'tk 12/14/2001 19:30'!\\nauthoringPrototype\\n\\t\\\"Enclose my prototype in a SyntaxMorph.\\\"\\n\\n\\t| aWatcher aTile aLine aColor ms slotMsg |\\n\\n\\taColor _ Color r: 0.387 g: 0.581 b: 1.0.\\n\\taTile _ self new typeColor: aColor.\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true;\\n\\t\\tsetToAllowTextEdit;\\n\\t\\tgetSelector: nil;\\n\\t\\tputSelector: nil.\\n\\taWatcher target: nil.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\n\\t\\\"This is the long way around to do this...\\\"\\n\\tms _ MessageSend receiver: nil selector: #aNumber arguments: #().\\n\\tslotMsg _ ms asTilesIn: Player globalNames: false.\\n\\t\\t\\\"For CardPlayers, use 'aPlayer'. For others, name it, and use its name.\\\"\\n\\tms _ MessageSend receiver: 3 selector: #= asSymbol arguments: #(5).\\n\\taLine _ ms asTilesIn: Player globalNames: false.\\n\\taLine firstSubmorph delete.\\t\\n\\taLine addMorphFront: (slotMsg submorphs second) firstSubmorph.\\n\\taLine firstSubmorph setNameTo: 'label'.\\n\\taLine addMorphFront: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine lastSubmorph delete.\\n\\taLine lastSubmorph delete.\\n\\taLine color: aColor; setNameTo: 'Number (fancy)'.\\n\\taLine addMorphBack: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine addMorphBack: aTile.\\n\\taLine readOut setNameTo: 'value'.\\n\\taLine cellPositioning: #leftCenter.\\n\\taWatcher step; fitContents.\\n\\t^ aLine markAsPartsDonor.! !\\nOBAnnouncement subclass: #OBAboutToChange\\n\\tinstanceVariableNames: 'veto'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBAboutToChange methodsFor: 'vetos' stamp: 'cwp 4/17/2006 22:18'!\\nisVetoed\\n\\t^ veto notNil! !\\n\\n!OBAboutToChange methodsFor: 'vetos' stamp: 'cwp 4/17/2006 19:45'!\\nveto\\n\\tveto _ true! !\\nMessageSend subclass: #OBAction\\n\\tinstanceVariableNames: 'announcer dispatcher label buttonLabel keystroke icon'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n!OBAction commentStamp: 'cwp 3/4/2004 20:52' prior: 0!\\nActions represent commands for manipulating the graph domain. They can be made available through menus or buttons in the browser. They carry information on how they should be presented to the user, and are responsible for handling exceptions generated when they are triggered. Actions are created by Actors.\\n\\niVars: \\n\\nlabel \\t\\ta string which describes the action for the user.\\nmonitor \\twhen the action is triggered, any notifications raised \\n\\t\\t\\twill be passed to this object for processing!\\n\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:25'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:25'!\\nannouncer: anAnnouncer\\n\\tannouncer _ anAnnouncer! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:35'!\\nbuttonLabel\\n\\t^ buttonLabel! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:35'!\\nbuttonLabel: aString\\n\\tbuttonLabel _ aString\\n\\t! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 16:42'!\\nicon\\n\\t^icon! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 16:42'!\\nicon: anIcon\\n\\ticon _ anIcon! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 14:16'!\\nkeystroke\\n\\t^keystroke! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 14:16'!\\nkeystroke: aChar\\n\\tkeystroke _ aChar! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 1/7/2004 09:11'!\\nlabel\\n\\t^ label! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 1/7/2004 09:12'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:40'!\\nwantsButton\\n\\t^ buttonLabel notNil! !\\n\\n\\n!OBAction methodsFor: 'evaluating' stamp: 'cwp 1/7/2004 18:22'!\\nperform: aSelector orSendTo: anObject\\n\\t^ self perform: aSelector! !\\n\\n!OBAction methodsFor: 'evaluating' stamp: 'cwp 6/4/2006 00:58'!\\ntrigger\\n\\t[self value]\\n\\t\\ton: OBAnnouncerRequest\\n\\t\\tdo: [:notification | notification resume: announcer].! !\\n\\n\\n!OBAction methodsFor: 'morphic' stamp: 'hpt 5/17/2004 17:00'!\\naddItemToMenu: aMenu\\n\\taMenu\\n\\t\\tadd: self labelWithKeystroke\\n\\t\\ttarget: self \\n\\t\\tselector: #trigger.\\n\\tPreferences menuWithIcons & self icon notNil\\n\\t\\tifTrue: [aMenu lastItem icon: self icon].\\n\\taMenu addBlankIconsIfNecessary: MenuIcons blankIcon.! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'cwp 7/8/2006 12:55'!\\nbuttonLabelMorph\\n\\t^ StringMorph \\n\\t\\tcontents: self buttonLabel \\n\\t\\tfont: Preferences standardButtonFont! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'cwp 7/8/2006 12:54'!\\nbuttonMorph\\n\\t^ (PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: nil\\n\\t\\taction: #trigger\\n\\t\\tlabel: #buttonLabelMorph)\\t\\n\\t\\t\\tonColor: Color lightGray lighter offColor: Color lightGray twiceLighter;\\n\\t\\t\\tborderWidth: 2;\\n\\t\\t\\tborderRaised;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\tsetBalloonText: label! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'hpt 5/17/2004 14:17'!\\nlabelWithKeystroke\\n\\t^keystroke\\n\\t\\tifNil: [label]\\n\\t\\tifNotNil: [label, ' (', keystroke asString, ')']! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAction class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 3/10/2004 23:36'!\\nlabel: aString buttonLabel: aString2 receiver: anObject selector: aSelector arguments: anArray\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tbuttonLabel: aString2! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 18:49'!\\nlabel: aString buttonLabel: aString2 receiver: anObject selector: aSelector \\narguments: anArray keystroke: aChar icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tbuttonLabel: aString2;\\n\\t\\tkeystroke: aChar;\\n\\t\\ticon: anIcon! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 1/7/2004 09:20'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) label: aString! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 16:50'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\ticon: anIcon! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 14:16'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray keystroke: aChar\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tkeystroke: aChar! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 16:50'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray keystroke: aChar icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tkeystroke: aChar;\\n\\t\\ticon: anIcon! !\\nObject subclass: #OBActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n!OBActor commentStamp: 'cwp 1/7/2005 23:14' prior: 0!\\nActors provide the basic units of domain-related functionality. They are attached to metanodes, and supply the Actions used to build context menus and buttons in the browser. Actors can be proxies for functionality supplied by other classes, as in OBFileRegistryActor, or they may supply the funtionality them selves. \\n\\nOBActor is an abstract class which defines the protocol Actors must implement. Actors need not be subclasses of OBActor, however.!\\n\\n\\n!OBActor methodsFor: 'accessing' stamp: 'cwp 9/16/2004 23:25'!\\nactionWithLabel: aString selector: aSymbol \\n\\tself shouldBeImplemented! !\\n\\n\\n!OBActor methodsFor: 'public' stamp: 'cwp 2/4/2004 15:25'!\\nactionsForNode: aNode\\n\\t^#()! !\\n\\n!OBActor methodsFor: 'public' stamp: 'cwp 2/5/2004 20:12'!\\nactionsForParent: aNode\\n\\t^#()! !\\n\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:30'!\\ndeleteIcon\\n\\t^ MenuIcons tryIcons: #(deleteIcon smallDeleteIcon)! !\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:31'!\\nfindIcon\\n\\t^ MenuIcons tryIcons: #(findIcon smallFindIcon)! !\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:31'!\\nnewIcon\\n\\t^ MenuIcons tryIcons: #(newIcon smallNewIcon)! !\\nOBMethodCategoryNode subclass: #OBAllMethodCategoryNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBAllMethodCategoryNode commentStamp: 'cwp 1/8/2005 12:31' prior: 0!\\nOBAllMethodCategory implements the synthetic '-- all --' category, which contains all the methods in a class.!\\n\\n\\n!OBAllMethodCategoryNode methodsFor: 'accessing'!\\ncategory\\n\\t^ 'as yet unclassified'! !\\n\\n!OBAllMethodCategoryNode methodsFor: 'accessing'!\\nmethodReferences\\n\\t^ self theClass selectors asSortedArray \\n\\t\\tcollect: [:ea | MethodReference new setStandardClass: self theClass methodSymbol: ea]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAllMethodCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAllMethodCategoryNode class methodsFor: 'as yet unclassified'!\\non: className\\n\\t^ self on: '-- all --' inClass: className! !\\nObject subclass: #OBAnnouncement\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\nObject subclass: #OBAnnouncer\\n\\tinstanceVariableNames: 'subscriptions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/5/2006 00:39'!\\nannounce: anObject\\n\\n\\t| ann |\\n\\tann _ anObject asAnnouncement.\\n\\tsubscriptions keysAndValuesDo:\\n\\t\\t[:class :action |\\n\\t\\t(ann isKindOf: class) ifTrue: [action valueWithArguments: {ann}]].\\n\\t^ ann! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/3/2006 21:21'!\\nobserve: aClass do: aValuable \\n\\t| actions |\\n\\tactions _ subscriptions at: aClass ifAbsent: [ActionSequence new].\\n\\tsubscriptions at: aClass put: (actions copyWith: aValuable).! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/3/2006 23:31'!\\nobserve: aClass send: aSelector to: anObject\\n\\tself\\n\\t\\tobserve: aClass\\n\\t\\tdo: (MessageSend receiver: anObject selector: aSelector)! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/10/2006 00:40'!\\nunsubscribe: anObject\\n\\tsubscriptions keysAndValuesDo:\\n\\t\\t[:class :actions |\\n\\t\\tsubscriptions at: class put: (actions reject: [:ea | ea receiver == anObject])].\\n\\tsubscriptions keysAndValuesRemove: [:key :value | value isEmpty]! !\\n\\n\\n!OBAnnouncer methodsFor: 'initialize-release' stamp: 'cwp 4/17/2006 11:51'!\\ninitialize\\n\\tsubscriptions _ IdentityDictionary new.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAnnouncer class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAnnouncer class methodsFor: 'instance creation' stamp: 'cwp 6/4/2006 00:55'!\\ncurrent\\n\\t^ OBAnnouncerRequest signal! !\\n\\n!OBAnnouncer class methodsFor: 'instance creation' stamp: 'cwp 4/17/2006 11:50'!\\nnew\\n\\t^ self basicNew initialize! !\\nNotification subclass: #OBAnnouncerRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\nOBInteractionRequest subclass: #OBBrowseRequest\\n\\tinstanceVariableNames: 'browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBBrowseRequest commentStamp: 'cwp 12/7/2004 00:10' prior: 0!\\nThis notification is raised whenever a browser needs to be opened. The default action is to open a SystemWindow in Morphic, but it can be caught in situations where that's not appropriate. The OB test suite uses this extensively. !\\n\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 18:45'!\\nbrowser\\n\\t^ browser! !\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 18:45'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser! !\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 21:27'!\\ndefaultAction\\n\\t^ browser openInMorphic! !\\n\\n\\n!OBBrowseRequest methodsFor: 'testing' stamp: 'cwp 10/17/2004 19:32'!\\nisBrowseRequest\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBBrowseRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBBrowseRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 10/17/2004 18:45'!\\nsignal: aBrowser\\n\\t^ (self new browser: aBrowser) signal! !\\nObject subclass: #OBBrowser\\n\\tinstanceVariableNames: 'panels announcer'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBBrowser commentStamp: 'cwp 1/7/2005 23:17' prior: 0!\\nOBBrowser is the core of OmniBrower. It's the root object for each browser and the model for the SystemWindows which display them. Its main responsibily is managing panels, particularly passing update messages between them.\\n\\nOn the class side, OBBrowser provides some default settings for creating and opening browsers. Subclasses can override these settings to acheive customized behavior.\\n\\niVars:\\n\\npanels\\t- A collection of objects which manage submorphs of the browser's SystemWindow.\\n\\ncVars:\\n\\nMetaGraphs - A dictionary matching names to metagraphs!\\n\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:36'!\\naddPanel: aPanel\\n\\tpanels add: aPanel.\\n\\taPanel browser: self.\\n! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:42'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 11/20/2004 21:00'!\\ncurrentNode\\n\\t^self navigationPanel currentNode! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 11/20/2004 21:00'!\\ncurrentOrRootNode\\n\\t^self navigationPanel currentOrRootNode! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 8/31/2004 13:04'!\\ndefaultLabel\\n\\t^ self class titleForRoot: self root! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 12/5/2004 16:25'!\\nnavigationPanel\\n\\t^ panels \\n\\t\\tdetect: [:ea | ea isNavigation] \\n\\t\\tifNone: [self error: 'No navigation panel configured']! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 9/17/2004 00:53'!\\npanels\\n\\t^ panels! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 6/28/2006 00:44'!\\nrequestor\\n\\t^ OBRequestor for: self! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'dvf 9/5/2005 17:30'!\\nselectionPath\\n\\t^self navigationPanel selectionPath! !\\n\\n\\n!OBBrowser methodsFor: 'callbacks' stamp: 'cwp 11/20/2004 21:05'!\\nlabelString\\n\\t| label |\\n\\tlabel := self navigationPanel labelString.\\n\\t^label \\n\\t\\tifNil: [self defaultLabel]\\n\\t\\tifNotNil: [self defaultLabel , ': ' , label]! !\\n\\n!OBBrowser methodsFor: 'callbacks' stamp: 'cwp 4/17/2006 19:52'!\\nokToChange\\n\\t^ (self announcer announce: OBAboutToChange) isVetoed not! !\\n\\n\\n!OBBrowser methodsFor: 'initializing' stamp: 'cwp 6/4/2006 14:09'!\\ninitialize\\n\\tpanels _ OrderedCollection new.\\n\\tannouncer _ OBAnnouncer new.\\n\\tself subscribe! !\\n\\n!OBBrowser methodsFor: 'initializing' stamp: 'cwp 12/5/2004 16:24'!\\nsetMetaNode: aMetaNode node: aNode \\n\\tself navigationPanel setMetaNode: aMetaNode node: aNode! !\\n\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/27/2004 22:21'!\\ndefaultBackgroundColor\\n\\t^ Color gray veryMuchLighter! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 12/5/2004 14:23'!\\nmorph\\n\\t| window |\\n\\twindow := SystemWindow labelled: self defaultLabel.\\n\\twindow model: self.\\n\\tpanels isEmpty ifFalse: [self morphicPanelLayout addMorphsTo: window].\\n\\t^window! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/21/2004 00:31'!\\nmorphicPanelLayout\\n\\t^ OBMorphicPanelLayout for: panels! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/21/2004 00:30'!\\nopenInMorphic\\n\\t^ self morph openInWorld! !\\n\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 11/20/2004 21:00'!\\njumpToRoot\\n\\t^self navigationPanel jumpToRoot! !\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 11/20/2004 21:00'!\\njumpTo: aNode \\n\\tself navigationPanel jumpTo: aNode! !\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 9/17/2005 17:48'!\\nroot\\n\\t^self navigationPanel root! !\\n\\n\\n!OBBrowser methodsFor: 'opening' stamp: 'cwp 10/17/2004 21:31'!\\nopen\\n\\t^ OBBrowseRequest signal: self! !\\n\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:29'!\\ndontTranscribe\\n\\tself announcer unsubscribe: self.\\n\\tself subscribe.! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 4/24/2006 15:10'!\\nrelabel: ann\\n\\tself changed: #relabel.\\n! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/4/2006 18:50'!\\nsignalRefresh\\n\\tself announcer announce: OBRefreshRequired! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/6/2006 00:25'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBSelectionChanged send: #relabel: to: self! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/6/2006 00:26'!\\ntranscribe\\n\\tself announcer observe: OBAnnouncement do: [:ann | Transcript cr; show: ann].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBBrowser class methodsFor: 'auto opening' stamp: 'cwp 12/6/2004 23:22'!\\nopen\\n\\t^ self new open! !\\n\\n!OBBrowser class methodsFor: 'auto opening' stamp: 'cwp 12/5/2004 17:03'!\\nopenRoot: rootNode selection: selectedNode\\n\\t^ (self root: rootNode selection: selectedNode) open! !\\n\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:10'!\\ndefaultMetaNode\\n\\tself subclassResponsibility! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/6/2004 23:20'!\\ndefaultRootNode\\n\\tself subclassResponsibility! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:10'!\\ndefinitionPanel\\n\\t^ OBDefinitionPanel new! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:01'!\\nmaxPanes\\n\\t^ self paneCount! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:00'!\\nminPanes\\n\\t^ self paneCount! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 16:55'!\\nnavigationPanel\\n\\t^ OBColumnPanel minPanes: self minPanes maxPanes: self maxPanes! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 11/26/2004 22:27'!\\noptionalButtonPanel\\n\\t| labels panel |\\n\\tlabels _ self optionalButtons.\\n\\t(Preferences optionalButtons and: [labels isEmpty not]) ifTrue: \\n\\t\\t[panel _ OBFixedButtonPanel new.\\n\\t\\tlabels do: [:ea | panel addButtonWithLabel: ea]].\\n\\t^ panel! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:07'!\\noptionalButtons\\n\\t^ #()! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:01'!\\npaneCount\\n\\t^ 4! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 15:06'!\\npanels\\n\\t^ {self navigationPanel. self optionalButtonPanel. self definitionPanel} \\n\\t\\treject: [:ea | ea isNil]! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:32'!\\ntitle\\n\\t^ 'OmniBrowser'! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 13:02'!\\ntitleForRoot: aNode\\n\\t^ self title! !\\n\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 18:12'!\\nmetaNode: metaNode node: rootNode \\n\\t^ self metaNode: metaNode root: rootNode selection: nil panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/17/2005 01:16'!\\nmetaNode: metaNode root: rootNode selection: selectedNode\\n\\t^ self metaNode: metaNode root: rootNode selection: selectedNode panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/6/2004 21:59'!\\nmetaNode: metaNode root: rootNode selection: selectedNode panels: panels\\n\\t| browser |\\n\\tbrowser _ self basicNew initialize.\\n\\tpanels do: [:ea | browser addPanel: ea].\\n\\tbrowser setMetaNode: metaNode node: rootNode.\\n\\tselectedNode ifNotNil: [browser jumpTo: selectedNode].\\n\\t^ browser! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/16/2005 23:25'!\\nnew\\n\\t^ self \\n\\t\\tmetaNode: self defaultMetaNode\\n\\t\\troot: self defaultRootNode\\n\\t\\tselection: nil\\n\\t\\tpanels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 15:26'!\\nroot: aNode \\n\\t^ self root: aNode selection: nil! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/16/2005 23:25'!\\nroot: rootNode selection: selectedNode\\n\\t^ self metaNode: self defaultMetaNode root: rootNode selection: selectedNode panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/6/2004 22:04'!\\nselection: selectedNode\\n\\t^ self root: self defaultRootNode selection: selectedNode! !\\n\\nObject subclass: #OBButtonModel\\n\\tinstanceVariableNames: 'bar label'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBButtonModel commentStamp: 'cwp 3/5/2004 12:15' prior: 0!\\nAn OBButtonModel serves as a model for PluggableButtonMorphs used OBRadioButtonBar. OBRadioButtonBar cannot be a direct model for its PBMs, since it can contain a variable number of buttons.\\n\\niVars:\\n\\nbar\\t\\t- the OBRadioButton bar to which this button belongs\\nlabel\\t- the label of the button!\\n\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 2/24/2004 18:29'!\\nbar: aRadioButtonBar\\n\\tbar _ aRadioButtonBar! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 3/2/2004 21:46'!\\nlabel\\n\\t^ label! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 2/24/2004 18:29'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 11/27/2004 00:50'!\\nselectionChanged\\n\\tself changed: #isSelected.\\n\\tself changed: #labelMorph! !\\n\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:42'!\\nisSelected\\n\\t^ bar isSelected: self! !\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/28/2006 10:45'!\\nlabelMorph\\n\\t^ (StringMorph \\n\\t\\tcontents: self label \\n\\t\\tfont: TextStyle defaultFont)\\n\\t\\t\\tcolor: (self isEnabled ifTrue: [Color black] ifFalse: [Color gray]);\\n\\t\\t\\tyourself! !\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 19:30'!\\npush\\n\\tbar push: self.! !\\n\\n\\n!OBButtonModel methodsFor: 'morphs' stamp: 'lr 3/23/2006 18:08'!\\nmorph\\n\\t| morph |\\n\\tmorph := PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: #isSelected\\n\\t\\taction: #push\\n\\t\\tlabel: #labelMorph.\\n\\tmorph \\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill.\\n\\t^ morph! !\\n\\n\\n!OBButtonModel methodsFor: 'testing' stamp: 'cwp 11/27/2004 19:09'!\\nisEnabled\\n\\t^ bar isEnabled: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBButtonModel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 8/29/2004 13:31'!\\noffColor\\n\\t^ Color lightGray twiceLighter! !\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 8/29/2004 13:30'!\\nonColor\\n\\t^ Color lightGray lighter! !\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 2/24/2004 18:35'!\\nwithLabel: aString inBar: aRadioButtonBar\\n\\t^ self new label: aString; bar: aRadioButtonBar! !\\nOBActor subclass: #OBCategoryActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n!OBCategoryActor commentStamp: 'cwp 1/7/2005 23:43' prior: 0!\\nOBCategory actor implements a number of actions useful for manipulating both class and method categories.!\\n\\n\\n!OBCategoryActor methodsFor: 'public' stamp: 'cwp 7/10/2006 21:33'!\\nactionsForNode: aNode\\n\\t^ Array\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'remove'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #remove:\\n\\t\\t\\t\\targuments: {aNode}\\n\\t\\t\\t\\tkeystroke: $x\\n\\t\\t\\t\\ticon: self deleteIcon)\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'rename...'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #rename:\\n\\t\\t\\t\\targuments: {aNode})! !\\n\\n!OBCategoryActor methodsFor: 'public' stamp: 'cwp 1/9/2005 11:30'!\\nactionsForParent: aNode\\n\\t| actions |\\n\\tactions _ self stdActionsForParent: aNode.\\n\\taNode organization \\n\\t\\t\\tisClassOrganizer ifTrue: [actions _ actions copyWith: (self categorizeActionFor: aNode)].\\n\\t^ actions! !\\n\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2005 19:20'!\\nalphabetizeCategoriesIn: aNode \\n\\taNode organization sortCategories.\\n\\taNode signalChildrenChanged! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2004 22:53'!\\ncategorizeIn: aClassOrganizer \\n\\t\\\"Categorize methods by looking in parent classes for a method category.\\\"\\n\\t| organizers |\\n\\torganizers := aClassOrganizer subject withAllSuperclasses collect: [:ea | ea organization].\\n\\t(aClassOrganizer listAtCategoryNamed: ClassOrganizer default) do: [:sel | | found |\\n\\t\\tfound := (organizers collect: [ :org | org categoryOfElement: sel])\\n\\t\\t\\tdetect: [:ea | ea ~= ClassOrganizer default and: [ ea ~= nil]]\\n\\t\\t\\tifNone: [].\\n\\t\\tfound ifNotNil: [aClassOrganizer classify: sel under: found]]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/20/2005 08:40'!\\ncreateIn: aNode\\n\\t| catName organization |\\n\\torganization := aNode organization.\\n\\tcatName := OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\t\\ttemplate: (self categoryTemplateFor: organization).\\n\\tcatName ifNotNil:\\t[organization addCategory: catName.\\n\\t\\t\\t\\t\\t\\t(aNode categoryNodeNamed: catName) signalSelection].! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2004 21:55'!\\nremoveEmptyCategoriesIn: anOrganizer \\n\\tanOrganizer removeEmptyCategories! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove: aNode\\n\\t| list choice |\\n\\tlist := aNode container organization listAtCategoryNamed: aNode name.\\n\\tlist isEmpty ifTrue: [^ aNode remove].\\n\\tchoice := OBConfirmationRequest prompt: 'Are you sure you want to\\nremove this category \\nand all its elements?' confirm: 'Remove'.\\n\\tchoice ifTrue: [^ aNode remove]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2005 18:51'!\\nrename: aNode\\n\\t| category |\\n\\tcategory := OBTextRequest\\n\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\ttemplate: aNode name.\\n\\tcategory ifNotNil:\\t\\n\\t\\t[aNode container organization renameCategory: aNode name toBe: category.\\n\\t\\taNode signalChanged]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 6/4/2006 18:56'!\\nreorganizeCategoriesIn: anOrganizer\\n\\t| definition |\\n\\tdefinition _ OBOrganizationDefinition on: anOrganizer.\\n\\tdefinition signalChange.! !\\n\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 9/18/2004 23:52'!\\ncategorizeActionFor: aNode\\n\\t^ OBAction\\n\\t\\tlabel: 'categorize automatically'\\n\\t\\treceiver: self\\n\\t\\tselector: #categorizeIn:\\n\\t\\targuments: (Array with: aNode organization)! !\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 6/25/2006 17:36'!\\ncategoryTemplateFor: anOrganization\\n\\t^ anOrganization isClassOrganizer\\n\\t\\tifTrue: ['category name']\\n\\t\\tifFalse: ['Category-Name']! !\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 7/10/2006 21:49'!\\nstdActionsForParent: aNode\\n\\t^ Array\\n\\t\\twith: (OBAction \\n\\t\\t\\t\\tlabel: 'create category...'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #createIn:\\n\\t\\t\\t\\targuments: (Array with: aNode)\\n\\t\\t\\t\\ticon: self newIcon)\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'alphabetize categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #alphabetizeCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode))\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'remove empty categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #removeEmptyCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode organization))\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'reorganize categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #reorganizeCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode organization))\\n! !\\nObject subclass: #OBCategoryServant\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n\\n!OBCategoryServant methodsFor: 'private' stamp: 'cwp 6/25/2006 17:32'!\\ncategoryTemplateFor: anOrganization\\n\\t^ anOrganization isClassOrganizer\\n\\t\\tifTrue: ['category name']\\n\\t\\tifFalse: ['Category-Name']! !\\n\\n\\n!OBCategoryServant methodsFor: 'actions' stamp: 'cwp 6/29/2006 00:13'!\\ncreateCategory: aRequestor\\n\\t| catName organization node |\\n\\tnode _ aRequestor requestCurrentNode.\\n\\torganization _ node organization.\\n\\tcatName _ OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\t\\ttemplate: (self categoryTemplateFor: organization).\\n\\tcatName ifNotNil:\\t[organization addCategory: catName.\\n\\t\\t\\t\\t\\t\\taRequestor select: (node categoryNodeNamed: catName)].! !\\n\\n\\n!OBCategoryServant methodsFor: 'accessing' stamp: 'cwp 6/25/2006 17:25'!\\nservices\\n\\t| selectors |\\n\\tselectors _ self class organization listAtCategoryNamed: 'services'.\\n\\t^ selectors collect: [:ea | self perform: ea].\\n\\t! !\\n\\n\\n!OBCategoryServant methodsFor: 'services' stamp: 'cwp 6/30/2006 00:51'!\\nsvcCreateCategory\\n\\t^ (OBService action: (MessageSend receiver: self selector: #createCategory:))\\n\\t\\tcondition: [:req | req requestNode hasOrganization];\\n\\t\\tlabel: 'create category...'! !\\nOBAnnouncement subclass: #OBChildrenChanged\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBChildrenChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode\\n\\t^ node! !\\n\\n!OBChildrenChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBChildrenChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBChildrenChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBInteractionRequest subclass: #OBChoiceRequest\\n\\tinstanceVariableNames: 'prompt labels values lines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBChoiceRequest commentStamp: 'cwp 3/5/2004 12:26' prior: 0!\\nThis notification is used to ask the user for to choose from a list of alternatives. Its defaultAction is to open a PopUpMenu. Test cases an intercept the notification and respond programmatically.\\n\\nprompt\\t- A string describing the choice the user is asked to make.\\nlabels\\t- A list of strings describing the alternatives.\\nvalues\\t- When the user chooses an alternative, the corresponding item from this list is returned!\\n\\n\\n!OBChoiceRequest methodsFor: 'initializing' stamp: 'cwp 7/9/2006 00:05'!\\nsetPrompt: aString labels: labelArray values: valueArray lines: lineArray\\n\\tprompt _ aString.\\n\\tlabels _ labelArray.\\n\\tvalues _ valueArray.\\n\\tlines _ lineArray.! !\\n\\n\\n!OBChoiceRequest methodsFor: 'signaling' stamp: 'cwp 7/9/2006 00:09'!\\ndefaultAction\\n\\t^ values \\n\\t\\tat: ((PopUpMenu labelArray: labels lines: lines) startUpWithCaption: prompt)\\n\\t\\tifAbsent: [nil]! !\\n\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nlabels\\n\\t^ labels! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/9/2006 00:11'!\\nlines\\n\\t^ lines! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nprompt\\n\\t^ prompt! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nvalues\\n\\t^ values! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBChoiceRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:07'!\\nlabels: anArray\\n\\t^ self\\n\\t\\tprompt: nil\\n\\t\\tlabels: anArray\\n\\t\\tvalues: anArray\\n\\t\\tlines: #()! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:08'!\\nlabels: labelArray lines: lineArray\\n\\t^ self\\n\\t\\tprompt: nil\\n\\t\\tlabels: labelArray\\n\\t\\tvalues: labelArray\\n\\t\\tlines: lineArray! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:06'!\\nprompt: aString labels: labelArray values: valueArray\\n\\t^ self\\n\\t\\tprompt: aString\\n\\t\\tlabels: labelArray\\n\\t\\t values: valueArray\\n\\t\\tlines: #()! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:05'!\\nprompt: aString labels: labelArray values: valueArray lines: lineArray\\n\\t^ (self new \\n\\t\\tsetPrompt: aString \\n\\t\\tlabels: labelArray \\n\\t\\tvalues: valueArray \\n\\t\\tlines: lineArray) \\n\\t\\t\\tsignal! !\\nOBActor subclass: #OBClassActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n!OBClassActor commentStamp: 'cwp 1/7/2005 23:44' prior: 0!\\nOBClassActor provides basic actions for manipulating classes.!\\n\\n\\n!OBClassActor methodsFor: 'querying' stamp: 'cwp 7/10/2006 22:35'!\\nactionsForNode: aClassNode\\n\\t^ {OBAction\\n\\t\\t\\tlabel: 'remove' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #remove:\\n\\t\\t\\targuments: {aClassNode}\\n\\t\\t\\tkeystroke: $x \\n\\t\\t\\ticon: self deleteIcon.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'rename...' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #rename:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'copy...' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #copy:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'subclass template'\\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #subclassTemplate:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'browse references'\\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #browseReferences:\\n\\t\\t\\targuments: {aClassNode}\\n\\t}! !\\n\\n\\n!OBClassActor methodsFor: 'private' stamp: 'lr 3/28/2006 12:05'!\\nbrowseObsoleteRefs: aClassNode as: oldName \\n\\t| binding |\\n\\tbinding := aClassNode theNonMetaClass environment \\n\\t\\t\\t\\tassociationAt: aClassNode theNonMetaClass name.\\n\\t(SystemNavigation default allCallsOn: binding) isEmpty \\n\\t\\tifFalse: [OBReferencesBrowser\\n\\t\\t\\t\\t\\tbrowseRoot: aClassNode\\n\\t\\t\\t\\t\\ttitle: 'Obsolete references to']! !\\n\\n!OBClassActor methodsFor: 'private' stamp: 'cwp 7/8/2006 13:59'!\\ncopyClass: oldClass as: newName\\n\\t| oldDefinition newDefinition newClass |\\n\\t(oldClass environment hasClassNamed: newName)\\n\\t\\tifTrue: [^self error: newName, ' already exists'].\\n\\toldDefinition := oldClass definition.\\n\\tnewDefinition := oldDefinition \\n\\t\\t\\t\\t\\t\\tcopyReplaceAll: '#' , oldClass name asString \\n\\t\\t\\t\\t\\t\\twith: '#' , newName asString.\\n\\tCursor wait \\n\\t\\tshowWhile: [newClass := Compiler evaluate: newDefinition logged: true.\\n\\t\\t\\t\\t\\tnewClass copyAllCategoriesFrom: oldClass.\\n\\t\\t\\t\\t\\tnewClass class copyAllCategoriesFrom: oldClass class].\\n\\t^ newClass! !\\n\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:10'!\\nbrowseReferences: aClassNode \\n\\tOBReferencesBrowser browseRoot: aClassNode theNonMetaClass asNode! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'dvf 8/31/2005 13:11'!\\ncopy: aClassNode\\n\\t| newName newClass |\\n\\tnewName := OBTextRequest\\n\\t\\t\\tprompt: 'Please type new class name'\\n\\t\\t\\ttemplate: aClassNode theNonMetaClassName asString.\\n\\tnewName ifNotNil:\\t[newClass := self\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopyClass: aClassNode theNonMetaClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tas: newName asSymbol.\\n\\t\\t\\t\\t\\t\\t(newClass asNode) signalSelection].! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:04'!\\nremove: aClassNode\\n\\t(OBConfirmationRequest\\n\\t\\tprompt: 'Are you certain that you \\nwant to REMOVE the class ', aClassNode theNonMetaClassName, ' from the system?'\\n\\t\\tconfirm: 'Remove')\\n\\t\\t\\tifTrue: [aClassNode theNonMetaClass removeFromSystem.\\n\\t\\t\\t\\t\\taClassNode signalDeletion]! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:05'!\\nrename: aClassNode\\n\\t| newName |\\n\\tnewName := OBTextRequest\\n\\t\\t\\t\\t\\tprompt: 'Please type new class name' \\n\\t\\t\\t\\t\\ttemplate: aClassNode theNonMetaClassName asString.\\n\\tnewName ifNotNil:\\t[ | oldName |\\n\\t\\t\\t\\t\\t\\toldName := aClassNode theNonMetaClass name.\\n\\t\\t\\t\\t\\t\\taClassNode theNonMetaClass environment \\n\\t\\t\\t\\t\\t\\t\\trenameClassNamed: oldName\\n\\t\\t\\t\\t\\t\\t\\tas: newName asSymbol.\\n\\t\\t\\t\\t\\t\\tself browseObsoleteRefs: aClassNode as: oldName].\\n\\t! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'cwp 6/4/2006 18:53'!\\nsubclassTemplate: aClassNode \\n\\t| class definition |\\n\\tclass _ aClassNode theNonMetaClass.\\n\\tdefinition _ (OBClassDefinition \\n\\t\\t\\t\\t\\tenvironment: class environment \\n\\t\\t\\t\\t\\ttemplate: (Class \\n\\t\\t\\t\\t\\t\\t\\t\\ttemplateForSubclassOf: class \\n\\t\\t\\t\\t\\t\\t\\t\\tcategory: class category)).\\n\\tdefinition signalChange.! !\\nOBCodeNode subclass: #OBClassAwareNode\\n\\tinstanceVariableNames: 'theClass superior'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassAwareNode commentStamp: 'cwp 1/8/2005 11:23' prior: 0!\\nOBClassAware node models program elements that are part of a class. It provides methods for manipulating the class, as well as methods relating to sorting according to class hierarchy.\\n\\niVars\\n\\ntheClass \\t- the class that this node is part of\\nsuperior \\t- during hierarchical sorting this refers to the nearest superclass\\n\\t\\t\\t that belongs to the group being sorted!\\n\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:04'!\\nadoptSuperior: other \\n\\t| descent |\\n\\tdescent := self theClass allSuperclasses reversed.\\n\\t(descent indexOf: other theClass) > (descent indexOf: self superiorClass) \\n\\t\\tifTrue: [superior := other]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:04'!\\nsortsBefore: aClassNode\\n\\t| own other |\\n\\town := self withSuperiors.\\n\\tother := aClassNode withSuperiors.\\n\\t1 \\tto: (own size min: other size)\\n\\t\\tdo: [:i | (own at: i) == (other at: i) ifFalse: \\n\\t\\t\\t\\t[^ (own at: i) theClassName <= (other at: i) theClassName]].\\n\\t^ other includes: self\\n\\t! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperior\\n\\t^ superior! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiorClass\\n\\t^superior ifNotNil: [superior theClass]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiors\\n\\t| result |\\n\\tresult := OrderedCollection new.\\n\\tself superiorsDo: [:ea | result add: ea].\\n\\t^ result asArray reversed! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiorsDo: aBlock\\n\\t| cursor |\\n\\tcursor := superior.\\n\\t[cursor isNil] whileFalse:\\n\\t\\t[aBlock value: cursor.\\n\\t\\tcursor := cursor superior]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'dvf 8/16/2005 17:23'!\\nsuperior: other \\n\\tsuperior := other! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nwithSuperiors\\n\\t| result |\\n\\tresult := OrderedCollection new.\\n\\tresult add: self.\\n\\tself superiorsDo: [:ea | result add: ea].\\n\\t^ result asArray reversed! !\\n\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'lr 3/6/2006 19:24'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'lr 3/6/2006 19:22'!\\nbrowseHierarchically\\n\\tOBHierarchyBrowser openOnClass: self theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:10'!\\nbrowseHierarchyAction\\n\\t^ self \\n\\t\\taction: #browseHierarchically \\n\\t\\tbuttonLabel: 'hierarchy' \\n\\t\\tmenuLabel: 'browse hierarchy'.\\n! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:34'!\\nchaseVars\\n\\tOBVariablesBrowser browseRoot: self classNode! !\\n\\n\\n!OBClassAwareNode methodsFor: 'nodes' stamp: 'dvf 8/31/2005 13:11'!\\nclassNode\\n\\t^self theClass asNode! !\\n\\n\\n!OBClassAwareNode methodsFor: 'displaying' stamp: 'dvf 8/17/2005 14:59'!\\nindent\\n\\t| size indent |\\n\\tsize := 0.\\n\\tself superiorsDo: [:ea | size := size + 1].\\n\\tindent := Text new: size * 2.\\n\\tindent atAllPut: $ .\\n\\t^ indent! !\\n\\n!OBClassAwareNode methodsFor: 'displaying' stamp: 'cwp 1/7/2005 22:21'!\\nindentedName\\n\\t^ self indent, self name! !\\n\\n\\n!OBClassAwareNode methodsFor: 'ancestry' stamp: 'cwp 12/5/2004 12:56'!\\nisDescendantOfClassCat: aClassCategoryNode\\n\\n\\t\\\"optimized version: sending #category to the class is slow\\\"\\n\\t^ (self theNonMetaClass environment organization \\n\\t\\tlistAtCategoryNamed: aClassCategoryNode name)\\n\\t\\t\\tincludes: self theNonMetaClassName\\n\\n! !\\n\\n!OBClassAwareNode methodsFor: 'ancestry'!\\nisDescendantOfClass: aClassNode\\n\\t^ self theClassName = aClassNode theClassName! !\\n\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClass\\n\\t^ theClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClassName\\n\\t^ self theClass name! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClass: aClass\\n\\ttheClass := aClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheMetaClass\\n\\t^ self theClass theMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheNonMetaClass\\n\\t^ self theClass theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheNonMetaClassName\\n\\t^ self theNonMetaClass name! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassAwareNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassAwareNode class methodsFor: 'sorting' stamp: 'cwp 12/12/2004 22:13'!\\nsortHierarchically: nodes\\n\\tnodes do: [:a | nodes do: [:b | a adoptSuperior: b]].\\n\\tnodes sort: [:a : b | a sortsBefore: b].\\n\\t^ nodes! !\\nOBCodeNode subclass: #OBClassCategoryNode\\n\\tinstanceVariableNames: 'environment name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassCategoryNode commentStamp: 'cwp 1/8/2005 12:58' prior: 0!\\nOBClassCategory represents a system category in the image's SystemOrganization.!\\n\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:40'!\\nactions\\n\\t^ {\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t}\\n! !\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:44'!\\nbrowse\\n\\tOBSystemBrowser openOnEnvironment: environment category: name! !\\n\\n!OBClassCategoryNode methodsFor: 'actions'!\\nfileOut\\n\\tenvironment organization fileOutCategory: name.! !\\n\\n!OBClassCategoryNode methodsFor: 'actions'!\\nprintOut\\n\\tenvironment organization fileOutCategory: name asHtml: true! !\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove\\n\\tenvironment organization removeSystemCategory: name.\\n\\tself signalDeletion! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfClassCat:! !\\n\\n!OBClassCategoryNode methodsFor: 'ancestry'!\\nisDescendantOfClassCat: other\\n\\t^ other name = name! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/15/2005 17:31'!\\nclasses\\n\\t^ self classNames collect: [:ea | (environment at: ea) asNode]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:12'!\\nclassesHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self classes! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/17/2005 17:25'!\\ncomments\\n\\t^ self classNames collect: [:ea | (environment at: ea) asCommentNode ]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:19'!\\ncommentsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self comments! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/15/2005 17:52'!\\nmetaclasses\\n\\t^self classNames collect: [:ea | (environment at: ea) asClassSideNode]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:19'!\\nmetaclassesHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self metaclasses! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'private'!\\nclassNames\\n\\t^ environment organization listAtCategoryNamed: name! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'accessing' stamp: 'cwp 9/22/2004 22:13'!\\ncontainer\\n\\t^ environment! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\ndefinition\\n\\t^ OBClassDefinition \\n\\t\\tenvironment: environment \\n\\t\\ttemplate: ((environment at: #Class) template: name)! !\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\nname\\n\\t^ name! !\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\ntext\\n\\t^ 'Object subclass: #NameOfSubclass\\n\\tinstanceVariableNames: ''''\\n\\tclassVariableNames: ''''\\n\\tpoolDictionaries: ''''\\n\\tcategory: ''', self name, ''''! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'drag and drop'!\\ndropSelector\\n\\t^ #dropOnClassCategory:! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'class creation'!\\nisRedefinedBy: definition\\n\\t\\\"No class is selected, so the definition can't be a redefinition.\\\"\\n\\t\\n\\t^ false! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'initializing'!\\nsetName: aString\\n\\tself setName: aString environment: self class environment! !\\n\\n!OBClassCategoryNode methodsFor: 'initializing'!\\nsetName: aString environment: anEnvironment\\n\\tname := aString asSymbol.\\n\\tenvironment := anEnvironment! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:42'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassCategoryNode class methodsFor: 'actions'!\\nactionsForParent: aNode\\n\\t^ Array with: (OBAction\\n\\t\\t\\t\\t\\t\\tlabel: 'find class...'\\n\\t\\t\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\t\\t\\tselector: #findClassIn:\\n\\t\\t\\t\\t\\t\\targuments: (Array with: aNode environment)\\n\\t\\t\\t\\t\\t\\tkeystroke: $f)\\n! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'dvf 8/31/2005 11:33'!\\nfindClassIn: anEnvironment\\n\\t| pattern class |\\n\\tpattern := OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type the name or fragment to look for' \\n\\t\\t\\t\\t\\ttemplate: ''.\\n\\tpattern ifNil: [^self].\\n\\tclass := self findClassIn: anEnvironment pattern: pattern.\\n\\tclass ifNotNil: [(class asNode) signalSelection].! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'cwp 7/14/2006 14:37'!\\nfindClassIn: anEnvironment pattern: pattern\\n\\t| classNames className toMatch potentialClassNames |\\n\\ttoMatch := (pattern copyWithout: $.) asLowercase.\\n\\tpotentialClassNames := (anEnvironment classNames , anEnvironment traitNames) asArray.\\n\\tclassNames := (pattern endsWith: '.')\\n\\t\\t\\t\\t\\tifTrue: [potentialClassNames\\n\\t\\t\\t\\t\\t\\t\\tselect: [:nm | nm asLowercase = toMatch]]\\n\\t\\t\\t\\t\\tifFalse: [potentialClassNames\\n\\t\\t\\t\\t\\t\\t\\tselect: [:n | n includesSubstring: toMatch caseSensitive: false]].\\n\\tclassNames size = 0 ifTrue: [^ nil].\\n\\tclassNames size = 1 ifTrue: [^ anEnvironment at: classNames first asSymbol].\\n\\tclassName := self userSelectionOf: classNames for: toMatch.\\n\\t^ className ifNotNil: [anEnvironment at: className asSymbol]\\n! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'cwp 7/9/2006 00:10'!\\nuserSelectionOf: classNames for: toMatch \\n\\t| exactMatch labels lines |\\n\\texactMatch := classNames detect: [:ea | ea asLowercase = toMatch] ifNone: [nil].\\n\\texactMatch \\n\\t\\tifNil: [labels _ classNames. lines _ #()]\\n\\t\\tifNotNil: [labels _ classNames copyWithFirst: exactMatch. lines _ #(1)].\\n\\t^ OBChoiceRequest labels: labels lines: lines.! !\\n\\n\\n!OBClassCategoryNode class methodsFor: 'instance creation'!\\non: aString\\n\\t^ self new setName: aString! !\\n\\n!OBClassCategoryNode class methodsFor: 'instance creation'!\\non: aString inEnvironment: anEnvironment\\n\\t^ self new setName: aString environment: anEnvironment! !\\nOBClassAwareNode subclass: #OBClassCommentNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassCommentNode commentStamp: 'cwp 1/8/2005 11:24' prior: 0!\\nOBClassCommentNode represents the comment attached to a particular class. !\\n\\n\\n!OBClassCommentNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:03'!\\nactions\\n\\t^ {\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'\\n\\t}! !\\n\\n\\n!OBClassCommentNode methodsFor: 'public' stamp: 'cwp 12/13/2004 00:51'!\\nname\\n\\t^ self theClass name! !\\n\\n\\n!OBClassCommentNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tself theClass: aClass! !\\n\\n\\n!OBClassCommentNode methodsFor: 'definition'!\\ntext\\n\\t^ self theClass comment! !\\n\\n!OBClassCommentNode methodsFor: 'definition'!\\ntext: aText\\n\\tself theClass comment: aText stamp: Utilities changeStamp.\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassCommentNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassCommentNode class methodsFor: 'as yet unclassified'!\\non: classRef\\n\\t^ self new setClass: classRef! !\\nOBDefinition subclass: #OBClassDefinition\\n\\tinstanceVariableNames: 'environment template'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBClassDefinition commentStamp: 'cwp 1/8/2005 13:13' prior: 0!\\nOBClassDefinition presents a textual interface for examining, modifying and creating classes. Given a class, it knows how to display the definition expression that reflects it's current state, and knows how to create or modify a class given a definition expression.\\n\\nOBClassDefinition implements a number of safety checks when defining or redefining classes, to ensure that existing classes are not accidentally overwritten.!\\n\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\naccept: aText notifying: aController\\n\\t^ self defineClass: aText notifying: aController! !\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\ntext\\n\\t^ template! !\\n\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nconfirmDefinition: definition\\n\\t\\\"Check to make sure the user isn't accidentally over-writing an existing class.\\\"\\n\\t\\n\\t(((self isRedefinition: definition) not) and: [self definedClassExists: definition])\\n\\t\\tifTrue: [^ self confirmRedefinition: definition]\\n\\t\\tifFalse: [^ true]! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nconfirmRedefinition: definition\\n\\t| newName prompt |\\n\\tnewName := self nameOfClassDefinedBy: definition.\\n\\tprompt := (newName, ' is an existing class in this system.\\nRedefining it might cause serious problems.\\nIs this really what you want to do?') asText.\\n\\t^ OBConfirmationRequest\\n\\t\\tprompt: prompt\\n\\t\\tconfirm: 'Redefine'! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\ndefinedClassExists: definition\\n\\t^ environment hasClassNamed: (self nameOfClassDefinedBy: definition)! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nisRedefinition: aDefinition\\n\\t^ (self nameOfClassDefinedBy: aDefinition) = (self nameOfClassDefinedBy: template)! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nnameOfClassDefinedBy: definition\\n\\t^ (Scanner new scanTokens: definition) third! !\\n\\n!OBClassDefinition methodsFor: 'confirmation' stamp: 'cwp 10/18/2004 00:13'!\\nselectedClass\\n\\t^ environment at: (self nameOfClassDefinedBy: template) ifAbsent: [nil]! !\\n\\n\\n!OBClassDefinition methodsFor: 'class definition'!\\ndefineClass: definition notifying: aController\\n\\t| evaluator newClass |\\n\\t(self confirmDefinition: definition) ifFalse: [^ false].\\n\\tevaluator := self evaluatorForDefinition: definition.\\n\\tnewClass := evaluator\\n\\t\\t\\t\\tevaluate: definition\\n\\t\\t\\t\\tnotifying: aController\\n\\t\\t\\t\\tlogged: true.\\n\\tnewClass ifNil: [^ false].\\n\\tself signalSelectionOf: newClass.\\n\\t^ true\\n! !\\n\\n!OBClassDefinition methodsFor: 'class definition'!\\nevaluatorForDefinition: definition\\n\\t| tokens |\\n\\ttokens := Scanner new scanTokens: definition.\\n\\t^ (environment at: tokens first ifAbsent: [nil]) subclassDefinerClass! !\\n\\n!OBClassDefinition methodsFor: 'class definition' stamp: 'cwp 10/23/2005 14:42'!\\nsignalSelectionOf: aClass\\n\\taClass asNode demandSelection! !\\n\\n\\n!OBClassDefinition methodsFor: 'initializing'!\\nsetEnvironment: anEnvironment template: aText\\n\\tenvironment := anEnvironment.\\n\\ttemplate := aText.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassDefinition class methodsFor: 'instance creation'!\\nenvironment: anEnvironment template: aString \\n\\t^ self new setEnvironment: anEnvironment template: aString! !\\nOBClassAwareNode subclass: #OBClassNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassNode commentStamp: 'cwp 1/8/2005 11:27' prior: 0!\\nOBClassNode wraps a class for display in various types of code browsers. It provides many navigation methods for the different types of browsers where classes may appear.!\\n\\n\\n!OBClassNode methodsFor: 'actions' stamp: 'cwp 7/10/2006 22:33'!\\nactions\\n\\t^ {\\n\\t\\tself action: #findMethod \\n\\t\\t\\twithLabel: 'find method...' \\n\\t\\t\\twithKeystroke: $f \\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'.\\n\\t\\tself action: #inspectInstances withLabel: 'inspect instances'.\\n\\t\\tself action: #inspectSubInstances withLabel: 'inspect subinstances'\\n\\t}! !\\n\\n!OBClassNode methodsFor: 'actions' stamp: 'cwp 10/26/2004 00:49'!\\nfileOut\\n\\tself theNonMetaClass fileOut! !\\n\\n!OBClassNode methodsFor: 'actions'!\\nfindMethod\\n\\t| selectors selection |\\n\\tselectors := self theClass selectors asSortedArray.\\n\\tselectors isEmpty ifTrue: [^nil].\\n\\tselection := OBChoiceRequest labels: selectors.\\n\\tselection ifNotNil: [(OBMethodNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: selection\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinClass: self theClass) signalSelection].! !\\n\\n!OBClassNode methodsFor: 'actions'!\\ninspectInstances\\n\\tself theNonMetaClass inspectAllInstances! !\\n\\n!OBClassNode methodsFor: 'actions'!\\ninspectSubInstances\\n\\tself theNonMetaClass inspectSubInstances! !\\n\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 23:05'!\\nallCategory\\n\\t^ Array with: (OBAllMethodCategoryNode on: self theClass)! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 23:06'!\\ncategories\\n\\t^ self theClass organization categories\\n\\t\\tcollect: [:cat | OBMethodCategoryNode on: cat inClass: self theClass]\\n\\t\\t\\t! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:31'!\\nclassHierarchy\\n\\t^ self nodeHierarchyWithClass: OBClassNode! !\\n\\n!OBClassNode methodsFor: 'navigating'!\\nclassVariables\\n\\t^ self theClass allClassVarNames asArray sort\\n\\t\\tcollect: [:ea | OBClassVariableNode on: ea inClass: self theClass]! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:31'!\\ncommentHierarchy\\n\\t^ self nodeHierarchyWithClass: OBClassCommentNode! !\\n\\n!OBClassNode methodsFor: 'navigating'!\\ninstanceVariables\\n\\t^ self theClass allInstVarNames asArray sort\\n\\t\\tcollect: [:ea | OBInstanceVariableNode on: ea inClass: self theClass]! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:30'!\\nmetaclassHierarchy\\n\\t^ self nodeHierarchyWithClass: OBMetaclassNode! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:30'!\\nnodeHierarchyWithClass: aClass\\n\\t^ OBClassAwareNode sortHierarchically: \\n\\t\\t(self surroundingHierarchy collect: [:ea | aClass on: ea])! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:45'!\\nusers\\n\\t^ (SystemNavigation default allCallsOn: (theClass environment associationAt: theClass name))\\n\\t\\tcollect: [:ref | OBClassRefNode on: self name inMethod: ref]! !\\n\\n\\n!OBClassNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfClass:! !\\n\\n\\n!OBClassNode methodsFor: 'nodes' stamp: 'cwp 9/20/2005 08:42'!\\ncategoryNodeNamed: aString \\n\\t^ OBMethodCategoryNode on: aString inClass: theClass! !\\n\\n!OBClassNode methodsFor: 'nodes'!\\nclassCategoryNode\\n\\t^ OBClassCategoryNode \\n\\t\\ton: self theNonMetaClass category\\n\\t\\tinEnvironment: self theClass environment! !\\n\\n\\n!OBClassNode methodsFor: 'accessing'!\\ndefinition\\n\\t^ OBClassDefinition \\n\\t\\tenvironment: self theClass environment \\n\\t\\ttemplate: self theClass definition! !\\n\\n!OBClassNode methodsFor: 'accessing'!\\norganization\\n\\t^ self theClass organization! !\\n\\n!OBClassNode methodsFor: 'accessing' stamp: 'cwp 12/12/2004 23:27'!\\nsurroundingHierarchy\\n\\t ^ (self theClass withAllSuperclasses union: self theClass allSubclasses)\\n\\t\\tasArray! !\\n\\n!OBClassNode methodsFor: 'accessing' stamp: 'cwp 12/12/2004 22:45'!\\n= other\\n\\tself species = other species ifFalse: [^ false].\\n\\t^ self theClass = other theClass! !\\n\\n\\n!OBClassNode methodsFor: 'drag and drop' stamp: 'lr 3/28/2006 18:29'!\\ndropOnClassCategory: aNode\\n\\tself theNonMetaClass category: aNode name.\\n\\tself signalSelection.\\n\\t^ true! !\\n\\n!OBClassNode methodsFor: 'drag and drop' stamp: 'lr 4/6/2006 11:31'!\\ndropSelector\\n\\t^ #dropOnClass:! !\\n\\n\\n!OBClassNode methodsFor: 'displaying' stamp: 'cwp 12/13/2004 00:51'!\\nname\\n\\t^ self theClass name! !\\n\\n!OBClassNode methodsFor: 'displaying'!\\ntitle\\n\\t^ self name! !\\n\\n\\n!OBClassNode methodsFor: 'printing' stamp: 'cwp 12/10/2004 23:53'!\\nprintOn: aStream\\n\\taStream\\n\\t\\tprint: self class;\\n\\t\\tnextPut: $<;\\n\\t\\tprint: self theClass;\\n\\t\\tnextPut: $>! !\\n\\n\\n!OBClassNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tself theClass: aClass! !\\n\\n\\n!OBClassNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:57'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassNode class methodsFor: 'instance creation' stamp: 'cwp 11/30/2004 21:06'!\\non: aClass \\n\\t^ self new setClass: aClass ! !\\nOBMethodNode subclass: #OBClassRefNode\\n\\tinstanceVariableNames: 'className'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassRefNode commentStamp: 'cwp 1/8/2005 12:38' prior: 0!\\nEach instance of OBClassRefNode refers to a reference to a particular class from the source code of a method. It's used in the OBListBrowser created by the 'browse references' class action.!\\n\\n\\n!OBClassRefNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 22:14'!\\nname\\n\\t^ className! !\\n\\n!OBClassRefNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 01:16'!\\nselection\\n\\t| start parser |\\n\\t(parser _ Compiler parserClass new) parseSelector: self source.\\n\\tstart := parser endOfLastToken.\\n\\tstart := (self source asString findString: className startingAt: start).\\n\\t^ start to: start + className size - 1! !\\n\\n\\n!OBClassRefNode methodsFor: 'initialize-release' stamp: 'cwp 12/1/2004 01:10'!\\nsetClassName: theName reference: aMethodRef\\n\\tself setReference: aMethodRef.\\n\\tclassName := theName.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassRefNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassRefNode class methodsFor: 'as yet unclassified' stamp: 'cwp 12/1/2004 00:50'!\\non: aClassName inMethod: aMethodRef\\n\\t^ self new setClassName: aClassName reference: aMethodRef! !\\nObject subclass: #OBClassReference\\n\\tinstanceVariableNames: 'name isMeta'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBClassReference commentStamp: 'cwp 1/8/2005 13:15' prior: 0!\\nOBClassReference provides a way to refer to classes that may or may not be loaded into the image. It refers to the class indirectly, via name, rather than with a direct pointer to the class object. It also provides a number of convenience methods, which makes it more convenient than using the class name directly.!\\n\\n\\n!OBClassReference methodsFor: 'accessing'!\\nbeMeta\\n\\tisMeta := true! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\nbeNonMeta\\n\\tisMeta := false! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\nname\\n\\t^ isMeta\\n\\t\\tifTrue: [name, ' class']\\n\\t\\tifFalse: [name]! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheClass\\n\\t| theClass |\\n\\ttheClass := self theNonMetaClass ifNil: [^ nil].\\n\\t^ isMeta\\n\\t\\tifFalse: [theClass]\\n\\t\\tifTrue: [theClass class]! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaClass\\n\\t^ Smalltalk at: name ifAbsent: [].! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaName\\n\\t^ name! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaName: aSymbol\\n\\tname := aSymbol! !\\n\\n\\n!OBClassReference methodsFor: 'comparing'!\\nhash\\n\\t^ isMeta\\n\\t\\tifTrue: [name hash bitInvert]\\n\\t\\tifFalse: [name hash]! !\\n\\n!OBClassReference methodsFor: 'comparing'!\\n<= other\\n\\t^ self name <= other name! !\\n\\n!OBClassReference methodsFor: 'comparing'!\\n= other\\n\\t^ (other isKindOf: self class) \\n\\t\\tand: [name = other theNonMetaName] \\n\\t\\tand: [isMeta = other isMeta]! !\\n\\n\\n!OBClassReference methodsFor: 'testing'!\\nisMeta\\n\\t^ isMeta! !\\n\\n\\n!OBClassReference methodsFor: 'printing'!\\nprintOn: aStream\\n\\taStream nextPutAll: 'OBClassReference'.\\n\\taStream nextPut: $<.\\n\\taStream nextPutAll: name.\\n\\tisMeta ifTrue: [aStream nextPutAll: ' class'].\\n\\taStream nextPut: $>.! !\\n\\n\\n!OBClassReference methodsFor: 'converting'!\\nreferenceToMethod: aSelector\\n\\t| ref |\\n\\tref := MethodReference new.\\n\\tref setClassSymbol: name classIsMeta: isMeta methodSymbol: aSelector stringVersion: ''.\\n\\t^ ref! !\\n\\n\\n!OBClassReference methodsFor: 'initializing'!\\nsetName: aSymbol\\n\\tname := (aSymbol copyUpTo: $ ) asSymbol.\\n\\tisMeta := aSymbol endsWith: ' class'.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassReference class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nmetaNamed: aSymbol\\n\\t^ (self named: aSymbol) beMeta! !\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nnamed: aSymbol\\n\\t^ self new setName: aSymbol! !\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nto: aClass\\n\\t^ self named: aClass name! !\\nOBVariableNode subclass: #OBClassVariableNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassVariableNode commentStamp: 'cwp 1/8/2005 12:51' prior: 0!\\nOBClassVariable provides a method for finding methods which refer to a shared variable, ie, by searching for an association in the literal frame rather than for bytecodes refering to an instance variable.!\\n\\n\\n!OBClassVariableNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:47'!\\naccessors\\n\\t| literal |\\n\\tliteral := (self theClass withAllSuperclasses \\n\\t\\t\\t\\tgather: [:ea | ea classPool associations])\\n\\t\\t\\t\\t\\tdetect: [:ea | ea key = name].\\n\\t^ ((self systemNavigation allCallsOn: literal) asArray sort)\\n\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\nOBBrowser subclass: #OBCodeBrowser\\n\\tinstanceVariableNames: 'hasChanges'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBCodeBrowser commentStamp: 'cwp 1/7/2005 23:45' prior: 0!\\nOBCodeBrowser is a superclass for all browsers which active code in the image. It provides methods for registering with the SystemChangeNotifier and updating it's display when it receives notification of system changes.!\\n\\n\\n!OBCodeBrowser methodsFor: 'morphic' stamp: 'cwp 1/8/2005 21:55'!\\naddModelItemsToWindowMenu: aMenu\\n\\tSmalltalk \\n\\t\\tat: #SystemBrowser \\n\\t\\tifPresent: [:class | class \\n\\t\\t\\t\\t\\t\\t\\t\\taddRegistryMenuItemsTo: aMenu \\n\\t\\t\\t\\t\\t\\t\\t\\tinAccountOf: OBSystemBrowserAdaptor new].! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\ninitialExtent\\n\\thasChanges := false.\\n\\tself register.\\n\\t^ super initialExtent! !\\n\\n!OBCodeBrowser methodsFor: 'morphic' stamp: 'cwp 6/4/2006 18:51'!\\nstepAt: milliseconds in: aSystemWindow\\n\\thasChanges ifTrue: [self signalRefresh].\\n\\tself clearChanges! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\nwantsStepsIn: aSystemWindow\\n\\t^ true! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\nwindowIsClosing\\n\\tself unregister! !\\n\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 1/7/2005 23:47'!\\nclearChanges\\n\\thasChanges := false! !\\n\\n!OBCodeBrowser methodsFor: 'updating'!\\nevent: anEvent\\n\\thasChanges := true! !\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 3/1/2006 19:48'!\\nregister\\n\\tSystemChangeNotifier uniqueInstance notify: self ofAllSystemChangesUsing: #event:! !\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 3/1/2006 19:48'!\\nunregister\\n\\tSystemChangeNotifier uniqueInstance noMoreNotificationsFor: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBCodeBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBCodeBrowser class methodsFor: 'configuration' stamp: 'lr 3/28/2006 12:00'!\\naddTo: root class: classSel comment: commentSel metaclass: metaclassSel \\n\\t| class metaclass comment methodCategory method allMethodCategory |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tcomment := OBMetaNode named: 'ClassComment'.\\n\\tmetaclass := OBMetaNode named: 'Metaclass'.\\n\\tallMethodCategory := OBMetaNode named: 'AllMethodCategory'.\\n\\tmethodCategory := OBMetaNode named: 'MethodCategory'.\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\troot\\n\\t\\tchildAt: classSel\\n\\t\\t\\tlabeled: 'instance'\\n\\t\\t\\tput: class;\\n\\t\\tchildAt: commentSel\\n\\t\\t\\tlabeled: '?'\\n\\t\\t\\tput: comment;\\n\\t\\tchildAt: metaclassSel\\n\\t\\t\\tlabeled: 'class'\\n\\t\\t\\tput: metaclass;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBClassCategoryNode);\\n\\t\\taddActor: OBCategoryActor new;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tclass\\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\tchildAt: #allCategory put: allMethodCategory;\\n\\t\\tchildAt: #categories put: methodCategory;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\taddActor: OBClassActor new.\\n\\tcomment \\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmetaclass\\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\tchildAt: #allCategory put: allMethodCategory;\\n\\t\\tchildAt: #categories put: methodCategory;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\taddActor: OBClassActor new.\\n\\tallMethodCategory\\n\\t\\tchildAt: #methods put: method;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBMethodCategoryNode).\\n\\tmethodCategory\\n\\t\\tchildAt: #methods put: method;\\n\\t\\taddActor: OBCategoryActor new;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBMethodCategoryNode).\\n\\tmethod addActor: OBNodeActor new.\\n\\t^ root! !\\n\\n!OBCodeBrowser class methodsFor: 'configuration' stamp: 'cwp 12/15/2004 22:52'!\\noptionalButtons\\n\\t^ #('browse' 'variables' 'hierarchy' 'inheritance' 'senders' 'implementors' 'versions')! !\\nOBNode subclass: #OBCodeNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBCodeNode commentStamp: 'cwp 1/8/2005 11:12' prior: 0!\\nOBCodeNode is an abstract superclass for node classes that represent program elements active in the image. Though it provides little functionality, it exists for structural purposes.!\\n\\n\\n!OBCodeNode methodsFor: 'actions' stamp: 'cwp 7/14/2006 14:24'!\\nbrowseAction\\n\\t^ self \\n\\t\\taction: #browse\\n\\t\\twithMenuLabel: 'browse'\\n\\t\\twithButtonLabel: 'browse'\\n\\t\\twithKeystroke: $b\\n\\t\\twithIcon: (MenuIcons tryIcons: #(windowIcon smallWindowIcon)).\\n! !\\n\\n\\n!OBCodeNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:37'!\\nhasOrganization\\n\\t^ false! !\\nOBNode subclass: #OBCollectionNode\\n\\tinstanceVariableNames: 'collection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Nodes'!\\n!OBCollectionNode commentStamp: 'cwp 1/7/2005 23:31' prior: 0!\\nOBCollectionNode is a trivial wrapper for a collection of nodes. It is typically used as an artificial root node for metagraphs that have no natural root.!\\n\\n\\n!OBCollectionNode methodsFor: 'displaying' stamp: 'cwp 3/15/2004 23:19'!\\nname\\n\\t^ collection species name! !\\n\\n\\n!OBCollectionNode methodsFor: 'initalizing' stamp: 'cwp 3/15/2004 23:18'!\\nsetCollection: aCollection\\n\\tcollection _ aCollection! !\\n\\n\\n!OBCollectionNode methodsFor: 'navigating' stamp: 'cwp 3/15/2004 23:19'!\\nchildren\\n\\t^ collection! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBCollectionNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBCollectionNode class methodsFor: 'as yet unclassified' stamp: 'cwp 3/15/2004 23:17'!\\non: aCollection\\n\\t^ self new setCollection: aCollection! !\\nObject subclass: #OBColumn\\n\\tinstanceVariableNames: 'panel filter children selection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBColumn commentStamp: 'cwp 1/7/2005 23:19' prior: 0!\\nAn OBColumn manages a list of nodes, which it displays in a PluggableListMorph in the pane scroller at the top of the browser. All instances of OBColumn belong to an OBColumnPanel. It's main responsibility is keeping its list - and those of its neighbours - up to date. Each column has a MetaNode, which provides the list contents. It uses a filter to meditate between its self and the MetaNode.\\n\\niVars:\\n\\npanel\\t\\t- the panel which owns the column\\nfilter\\t\\t- the filter which manages the column's MetaNode.\\nparent\\t\\t- the node selected in the column to the left of this column\\nchildren \\t- the nodes which make up this column's list\\nselection \\t- the index of the node selected by the user!\\n\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:52'!\\nannouncer\\n\\t^ panel announcer! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:49'!\\nbasicNext\\n\\t^panel columnAfter: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 11/17/2004 00:18'!\\nbrowser\\n\\t^ panel browser! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:58'!\\nfilter\\n\\t^ filter! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/12/2004 18:47'!\\nfilter: aFilter\\n\\tfilter _ aFilter monitor: self.\\n\\tself changed: #filter.! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/28/2006 08:27'!\\nisEmpty\\n\\t^ children isEmpty! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:59'!\\nmetaNode\\n\\t^ self filter metaNode! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/12/2004 20:50'!\\nnext\\n\\t^ self basicNext\\n\\t\\tifNil: [(self hasSelection and: [self shouldBeLast not])\\n\\t\\t\\t\\tifTrue: [self createNext]]\\n\\t! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 9/24/2005 22:45'!\\nparent\\n\\t^ panel parentNodeForColumn: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 6/8/2006 01:32'!\\nparent: aNode\\n\\t\\n\\tself filter: aNode metaNode filter.\\n\\tself getChildren.\\n\\tself clearSelection.\\n\\tself changed: #list.\\n\\tpanel clearAfter: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 6/28/2006 00:53'!\\nrequestor\\n\\t^ self browser requestor node: (self selectedNode ifNil: [self parent])! !\\n\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/24/2005 22:23'!\\nactionSetsForParentNode\\n\\t^ self filter children gather: [:child | child actionSetsForParent: self parent].\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/14/2004 19:08'!\\nactionSetsForSelectedNode\\n\\t| node |\\n\\tnode _ self selectedNode ifNil: [^ #()].\\n\\t^ node metaNode actionSetsForNode: node\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'hpt 5/17/2004 14:19'!\\nactionsForKeystroke: aChar\\n\\t^self actionsForParentNode, self actionsForSelectedNode\\n\\t\\tselect: [:anAction | anAction keystroke == aChar]! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/24/2005 22:23'!\\nactionsForParentNode\\n\\t^ self filter children gather: [:child | child actionsForParent: self parent].\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'avi 3/6/2004 16:26'!\\nactionsForSelectedNode\\n\\t| node |\\n\\tnode _ self selectedNode ifNil: [^ #()].\\n\\t^ node metaNode actionsForNode: node\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/25/2006 00:22'!\\naddActionsToMenu: aMenu\\n\\tself actionSetsForParentNode, self actionSetsForSelectedNode\\n\\t\\tdo: \\n\\t\\t\\t[:set \\n\\t\\t\\t|set do: \\n\\t\\t\\t\\t[:action | \\n\\t\\t\\t\\taction announcer: self announcer.\\n\\t\\t\\t\\taction addItemToMenu: aMenu]]\\n\\t\\tseparatedBy: [aMenu addLine]! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/28/2006 00:24'!\\naddServicesToMenu: aMenu\\n\\t| scan |\\n\\tscan _ self announcer announce: OBServiceScan.\\n\\taMenu \\n\\t\\taddServices: scan services\\n\\t\\tfor: self requestor\\n\\t\\textraLines: #().\\n\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/25/2006 13:55'!\\nservicesForKeystroke: aChar\\n\\t| scan |\\n\\tscan _ self announcer announce: OBServiceScan.\\n\\t^ scan services select: [:ea | ea keystroke == aChar]! !\\n\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/28/2006 00:50'!\\nkeystroke: aChar from: aMorph\\n\\tself isEmpty ifTrue: [^ self].\\n\\t(self actionsForKeystroke: aChar)\\n\\t\\tdo: [:action | \\n\\t\\t\\taction announcer: self announcer.\\n\\t\\t\\taction trigger].\\n\\t(self servicesForKeystroke: aChar)\\n\\t\\tdo: [:service | service condExecuteFor: self requestor]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 12/8/2004 21:21'!\\nlist\\n\\t^ children \\n\\t\\tifNil: [#()]\\n\\t\\tifNotNil: [children collect: [:ea | ea displayString]]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 12/8/2004 21:22'!\\nlistAt: index\\n\\t^ (children at: index ifAbsent: [^ '']) displayString! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 2/29/2004 21:48'!\\nlistSize\\n\\t^ children\\n\\t\\tifNil: [0]\\n\\t\\tifNotNil: [children size]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/25/2006 00:24'!\\nmenu: aMenu\\n\\tself isEmpty ifFalse:\\n\\t\\t[self addActionsToMenu: aMenu.\\n\\t\\tself addServicesToMenu: aMenu].\\n\\t^ aMenu! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 4/18/2006 00:25'!\\nokToChange\\n\\t^ (self announcer announce: OBAboutToChange) isVetoed not! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 11/5/2003 19:01'!\\nselection\\n\\t^ selection ifNil: [0]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/5/2006 23:37'!\\nselection: anInteger\\n\\tselection _ anInteger.\\n\\tself signalSelectionChanged.\\n\\tself changed: #selection.\\n! !\\n\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 6/4/2006 00:37'!\\nacceptDroppingMorph: transferMorph event: evt inMorph: listMorph\\n\\t^ [(self nodeForDroppedMorph: transferMorph event: evt inMorph: listMorph)\\n\\t\\tacceptDroppedNode: transferMorph passenger]\\n\\t\\t\\ton: OBAnnouncerRequest\\n\\t\\t\\tdo: [:notification | notification resume: self announcer]\\n! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 13:45'!\\ndragEnabled\\n\\t^ true! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:35'!\\ndragPassengerFor: item inMorph: listMorph\\n\\t^ self nodeForItem: item inMorph: listMorph! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:37'!\\ndragTransferType\\n\\t^ #OmniBrowser! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:36'!\\ndragTransferTypeForMorph: listMorph\\n\\t^ self dragTransferType! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:30'!\\ndropEnabled\\n\\t^ true! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 3/3/2004 02:23'!\\nnodeForDroppedMorph: transferMorph event: evt inMorph: pluggableListMorph\\n\\t| index item |\\n\\tindex _ pluggableListMorph rowAtLocation: evt position.\\n\\tindex = 0 ifTrue: [^ nil].\\n\\titem _ pluggableListMorph listMorph item: index.\\n\\t^ self nodeForItem: item inMorph: pluggableListMorph! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 6/10/2006 21:59'!\\nnodeForItem: item inMorph: pluggableListMorph\\n\\t^ children \\n\\t\\tdetect: [:child | child displayString = item contents asString]\\n\\t\\tifNone: [item contents]! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 2/25/2004 21:26'!\\nwantsDroppedMorph: transferMorph event: evt inMorph: listMorph\\n\\t| node |\\n\\t(transferMorph isKindOf: TransferMorph) ifFalse: [^ false].\\n\\ttransferMorph dragTransferType == self dragTransferType ifFalse: [^ false].\\n\\tnode _ self nodeForDroppedMorph: transferMorph event: evt inMorph: listMorph.\\n\\t^ node notNil and: [node wantsDroppedNode: transferMorph passenger]! !\\n\\n\\n!OBColumn methodsFor: 'initializing' stamp: 'cwp 6/3/2006 23:38'!\\nsetPanel: aPanel \\n\\tpanel := aPanel.\\n\\tself subscribe.\\n\\tchildren := #().\\n\\tself clearSelection! !\\n\\n!OBColumn methodsFor: 'initializing' stamp: 'cwp 6/3/2006 23:39'!\\nsetPanel: aPanel metaNode: aMetaNode node: aNode \\n\\tpanel := aPanel.\\n\\tself subscribe.\\n\\tfilter := aMetaNode filter monitor: self.\\n\\tchildren _ self filter nodesForParent: aNode.\\n\\tself clearSelection! !\\n\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 12/14/2003 22:15'!\\nbuttonHeight\\n\\t^ 20! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/9/2004 21:06'!\\ncolumnWithHeader\\n\\t| col bh |\\n\\tcol _ BorderedMorph new\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tcellInset: 0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new.\\n\\t\\n\\tbh _ self buttonHeight negated.\\n\\tcol\\n\\t\\taddMorph: self listMorph\\n\\t\\tfullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (0@0 corner: 0@bh)).\\n\\tcol\\n\\t\\taddMorph: self filter buttonMorph\\n\\t\\tfullFrame: (LayoutFrame fractions: (0@1 corner: 1@1) offsets: (0@bh corner: 0@0)).\\n\\t\\t\\n\\n\\t^ col! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/28/2006 08:37'!\\nlistMorph\\n\\t^ (PluggableListMorph\\n\\t\\ton: self\\n\\t\\tlist: #list\\n\\t\\tselected: #selection\\n\\t\\tchangeSelected: #selection:\\n\\t\\tmenu: #menu:\\n\\t\\tkeystroke: #keystroke:from:)\\n\\t\\t\\tgetListElementSelector: #listAt:;\\n\\t\\t\\tgetListSizeSelector: #listSize;\\n\\t\\t\\tdragEnabled: self dragEnabled;\\n\\t\\t\\tdropEnabled: self dropEnabled;\\n\\t\\t\\tborderWidth: 0;\\n\\t\\t\\tautoDeselect: false;\\n\\t\\t\\tadoptPaneColor: panel defaultBackgroundColor;\\n\\t\\t\\tyourself! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 19:17'!\\nmorph\\n\\t^ self isEmpty \\n\\t\\tifTrue: [self simplePane]\\n\\t\\tifFalse: [self filter wantsButton\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [self paneWithHeader]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [self simplePane]]! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 18:11'!\\npaneWithHeader\\n\\t^ OBPane forColumn: self withFilter: self filter! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 18:10'!\\nsimplePane\\n\\t^ OBPane forColumn: self! !\\n\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 9/24/2005 22:29'!\\ngetChildren\\n\\tchildren _ self filter nodesForParent: self parent.\\n\\t^ children! !\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 3/3/2004 00:11'!\\nnextMetaNode\\n\\t^ self selectedNode metaNode! !\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 9/26/2005 00:14'!\\nselectAncestorOf: aNode\\n\\t| ancestor |\\n\\tancestor _ self filter selectAncestorOf: aNode withParent: self parent.\\n\\tancestor ifNotNil:\\n\\t\\t[self \\n\\t\\t\\tgetChildren; \\n\\t\\t\\tchanged: #list;\\n\\t\\t\\tselect: ancestor.\\n\\t\\tpanel selected: self].\\n\\t^ ancestor! !\\n\\n\\n!OBColumn methodsFor: 'printing' stamp: 'avi 3/6/2004 16:23'!\\ndescriptor\\n\\tself isEmpty ifTrue: [^ 'empty'].\\n\\tself hasSelection ifTrue: [^ self selectedNode name].\\n\\t^ ''! !\\n\\n!OBColumn methodsFor: 'printing' stamp: 'cwp 2/11/2004 23:31'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $(.\\n\\taStream nextPutAll: self descriptor.\\n\\taStream nextPut: $)! !\\n\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'avi 3/6/2004 18:05'!\\nclearSelection\\n\\tselection _ 0! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 2/2/2004 21:54'!\\nselectedNode\\n\\t^ children at: self selection ifAbsent: [].! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 7/14/2006 12:50'!\\nselectSilently: aNode\\n\\t| match |\\n\\taNode ifNil: [selection := 0. ^ self].\\n\\tmatch := children \\n\\t\\t\\t\\tdetect: [:ea | ea correspondsWith: aNode] \\n\\t\\t\\t\\tifNone: [selection := 0. ^ self].\\n\\tselection _ children indexOf: match.! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 12/8/2004 22:10'!\\nselect: aNode\\n\\tself selection: (children indexOf: (children detect: [:ea | ea = aNode] ifNone: []))! !\\n\\n\\n!OBColumn methodsFor: 'testing' stamp: 'avi 3/6/2004 23:07'!\\nhasSelection\\n\\t^ self selection > 0! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'cwp 12/20/2004 22:09'!\\nincludesNode: aNode\\n\\t^ children includes: aNode! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'avi 3/6/2004 16:27'!\\nshouldBeLast\\n\\t^ self hasSelection not or: [self nextMetaNode hasChildren not]! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'cwp 2/12/2004 20:18'!\\nwantsButton\\n\\t^ self filter notNil and: [self filter wantsButton]! !\\n\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 22:35'!\\nchildrenChanged: announcement\\n\\t(self parent = announcement node) ifTrue:\\n\\t\\t[self refresh]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 9/25/2005 23:56'!\\nclear\\n\\tfilter _ nil.\\n\\tchildren _ #().\\n\\tself clearSelection.\\n\\tself changed: #list.\\n\\tself changed: #selection.\\n\\tself changed: #filter.! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 9/24/2005 22:56'!\\ncreateNext\\n\\t| nextMetaNode created |\\n\\tnextMetaNode := self nextMetaNode.\\n\\tcreated := nextMetaNode columnInPanel: panel node: self selectedNode.\\n\\tpanel pushColumn: created.\\n\\t^created! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:17'!\\nlistChanged\\n\\tself refreshAndSignal: true! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:19'!\\nnodeChanged: ann\\n\\t(children includes: ann node) ifTrue: [self changed: #list]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:03'!\\nnodeDeleted: announcement \\n\\t\\\"This gets called if an action causes the currently selected node to be deleted.\\\"\\n\\n\\tself selectedNode = announcement node\\n\\t\\tifTrue: \\n\\t\\t\\t[self getChildren.\\n\\t\\t\\tself changed: #list.\\n\\t\\t\\tself selection: 0]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefresh\\n\\tself refreshAndSignal: false! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefresh: ann\\n\\tself refreshAndSignal: false! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefreshAndSignal: aBoolean\\n\\t| node oldChildren shouldSignal |\\n\\tshouldSignal _ aBoolean.\\n\\tself isEmpty ifTrue: [^self].\\n\\tnode := self selectedNode.\\n\\toldChildren := children.\\n\\tself getChildren.\\n\\tchildren = oldChildren ifFalse: \\n\\t\\t[self selectSilently: node.\\n\\t\\tself hasSelection ifFalse: \\n\\t\\t\\t[shouldSignal _ true]].\\n\\tshouldSignal ifTrue: [self signalSelectionChanged].\\n\\tself changed: #list! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/8/2006 00:27'!\\nselectionChanged: ann\\n\\t! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/5/2006 23:31'!\\nsignalSelectionChanged\\n\\tself announcer announce: (OBSelectionChanged column: self)! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/10/2006 00:18'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBRefreshRequired send: #refresh: to: self;\\n\\t\\tobserve: OBNodeChanged send: #nodeChanged: to: self;\\n\\t\\tobserve: OBNodeDeleted send: #nodeDeleted: to: self;\\n\\t\\tobserve: OBChildrenChanged send: #childrenChanged: to: self;\\n\\t\\tobserve: OBSelectionChanged send: #selectionChanged: to: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBColumn class\\n\\tinstanceVariableNames: ''!\\n\\n!OBColumn class methodsFor: 'instance creation' stamp: 'cwp 9/18/2005 13:26'!\\ninPanel: aBrowser\\n\\t^ self new setPanel: aBrowser! !\\n\\n!OBColumn class methodsFor: 'instance creation' stamp: 'cwp 9/18/2005 13:25'!\\ninPanel: aPanel metaNode: aMetaNode node: aNode\\n\\t^ self new\\n\\t\\t\\tsetPanel: aPanel\\n\\t\\t\\tmetaNode: aMetaNode\\n\\t\\t\\tnode: aNode! !\\nOBPanel subclass: #OBColumnPanel\\n\\tinstanceVariableNames: 'root columns minPanes maxPanes'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBColumnPanel commentStamp: 'cwp 12/6/2004 23:50' prior: 0!\\nOBColumnPanel handles navigation around the nodes of the object graph. It maintains a list of columns, which track the user's path through the node tree. As nodes are selected, additional columns are added to the list, which appear as panes on the right of the panel. \\n\\niVars:\\n\\ncolumns\\t- A collection of OBColumns, each of which manages a single pane in the scroller.\\nminPanes - The minimum number of panes that should ever be visible.\\nmaxPanes - The maximum number of panes that should ever be visible.\\n!\\n\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:46'!\\ncolumns\\n\\t^columns! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:46'!\\ncolumns: anObject\\n\\tcolumns := anObject! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:22'!\\ncurrentNode\\n\\t^ self currentColumn ifNotNilDo: [:column | column selectedNode]! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:23'!\\ncurrentOrRootNode\\n\\t^(self columns reversed detect: [:ea | ea hasSelection]\\n\\t\\tifNone: [^self columns first parent]) selectedNode! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 6/5/2006 23:10'!\\nhasSelection\\n\\t^ false! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 23:51'!\\nlabelString\\n\\t| label |\\n\\tself columns reversed do: \\n\\t\\t[:ea | \\n\\t\\tlabel := ea selectedNode ifNotNilDo: [:node | node title].\\n\\t\\tlabel ifNotNil: [^ label]].\\n\\t^ nil\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 23:29'!\\nmaxPanes\\n\\t^maxPanes! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:54'!\\nminPanes\\n\\t^ minPanes! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 2/28/2006 09:59'!\\nparentNodeForColumn: aColumn\\n\\t^ [(columns before: aColumn) selectedNode]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | ^ root]! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'dvf 9/5/2005 18:08'!\\nselectionPath\\n\\t^(self columns \\n\\t\\tcollect: [:e | e parent] \\n\\t\\tthenSelect: [:e | e notNil]) allButFirst! !\\n\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 9/25/2005 23:58'!\\nclearAfter: aColumn \\n\\t| start |\\n\\tstart _ (columns indexOf: aColumn) + 1.\\n\\tstart to: columns size do: [:i | (columns at: i) clear]! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 18:12'!\\ncolumnAfter: aColumn \\n\\t^ [self columns after: aColumn]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | nil]\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 19:07'!\\ncolumnBefore: aColumn \\n\\t^ self columnBefore: aColumn ifAbsent: [nil]\\n\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 19:07'!\\ncolumnBefore: aColumn ifAbsent: aBlock\\n\\t^ [self columns before: aColumn]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | aBlock value]\\n\\n\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 11/16/2004 22:22'!\\ncurrentColumn\\n\\t^self columns reversed detect: [:ea | ea hasSelection] ifNone: []! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 11/16/2004 23:01'!\\nemptyColumn\\n\\t^ OBColumn inPanel: self! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/4/2006 00:39'!\\npopColumn\\n\\tself announcer unsubscribe: self columns removeLast.\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/4/2006 00:40'!\\npushColumn: aColumn \\n\\tself columns addLast: aColumn.\\n\\tself changed: #panes.\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/8/2006 01:35'!\\nselected: aColumn \\n\\taColumn next ifNotNilDo: \\n\\t\\t[:next | \\n\\t\\tnext parent: aColumn selectedNode].! !\\n\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/26/2004 21:55'!\\ndefaultBackgroundColor\\n\\t^ browser defaultBackgroundColor! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/23/2004 00:52'!\\nokToReclaimPane\\n\\tcolumns size > minPanes ifFalse: [^ false].\\n\\t^ columns last isEmpty or: [(columns at: columns size - 1) shouldBeLast].\\n! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/17/2004 22:48'!\\npanes\\n\\t^ columns collect: [:ea | ea morph]! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 9/18/2005 11:49'!\\nreclaimPanes\\n\\t| old |\\n\\told := columns size.\\n\\t[self okToReclaimPane] whileTrue: [self popColumn].\\n\\t^ old - columns size! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/18/2004 00:00'!\\nsizing\\n\\t^ (columns size max: minPanes) min: maxPanes! !\\n\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/17/2004 23:24'!\\nbuildScroller\\n\\t^ (OBPaneScroller withModel: self)\\n\\t\\tname: 'scroller';\\n\\t\\tyourself! !\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/20/2004 22:22'!\\nmorph\\n\\t^ (OBPaneScroller withModel: self)\\n\\t\\tname: 'scroller';\\n\\t\\tyourself! !\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/20/2004 22:26'!\\nmorphHeight\\n\\t^ 0! !\\n\\n\\n!OBColumnPanel methodsFor: 'initializing' stamp: 'cwp 9/24/2005 22:45'!\\nsetMetaNode: aMetaNode node: aNode \\n\\troot _ aNode.\\n\\troot metaNode: aMetaNode.\\n\\tself pushColumn: (aMetaNode columnInPanel: self node: root).\\n\\tminPanes - self columns size \\n\\t\\ttimesRepeat: [self pushColumn: self emptyColumn]! !\\n\\n!OBColumnPanel methodsFor: 'initializing' stamp: 'cwp 12/5/2004 16:54'!\\nsetMinPanes: min maxPanes: max\\n\\tcolumns _ OrderedCollection new.\\n\\tminPanes _ min.\\n\\tmaxPanes _ max! !\\n\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 6/9/2006 23:18'!\\nhopTo: aNode \\n\\t| column |\\n\\tcolumn := self columns last.\\n\\t[column refreshAndSignal: false; includesNode: aNode]\\n\\t\\twhileFalse: [column := self \\n\\t\\t\\t\\t\\t\\tcolumnBefore: column \\n\\t\\t\\t\\t\\t\\tifAbsent: [^ self jumpTo: aNode]].\\n\\tcolumn select: aNode! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 11/16/2004 23:34'!\\njumpToRoot\\n\\t^ self columns first selection: 0! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 6/10/2006 00:11'!\\njumpTo: aNode \\n\\t| column ancestor |\\n\\tcolumn := self columns first.\\n\\t\\n\\t[ancestor := column selectAncestorOf: aNode.\\n\\tancestor = aNode or: [ancestor isNil]] whileFalse:\\n\\t\\t[column := self columns after: column].\\n\\t\\n\\tself announcer announce: (OBSelectionChanged column: column)! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 9/24/2005 22:47'!\\nroot\\n\\t^ root! !\\n\\n\\n!OBColumnPanel methodsFor: 'testing' stamp: 'cwp 11/20/2004 21:10'!\\nisNavigation\\n\\t^ true! !\\n\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 23:52'!\\nnodeDeleted: ann\\n\\tann node = self root \\n\\t\\tifTrue: \\n\\t\\t\\t[self columns first clear.\\n\\t\\t\\tself announcer announce: (OBSelectionChanged column: self)]! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 01:03'!\\nselectNode: announcement\\n\\t^ self hopTo: announcement node! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 01:33'!\\nselectionChanged: ann\\n\\tann column hasSelection\\n\\t\\tifTrue: [self selected: ann column]\\n\\t\\tifFalse: [self clearAfter: ann column]\\n! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 01:32'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectingNode send: #selectNode: to: self;\\n\\t\\tobserve: OBSelectionChanged send: #selectionChanged: to: self;\\n\\t\\tobserve: OBNodeCreated send: #selectNode: to: self;\\n\\t\\tobserve: OBNodeDeleted send: #nodeDeleted: to: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBColumnPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBColumnPanel class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 16:56'!\\nminPanes: min maxPanes: max\\n\\t^ self basicNew setMinPanes: min maxPanes: max! !\\n\\n!OBColumnPanel class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 16:56'!\\nnew\\n\\t^ self minPanes: 1 maxPanes: 1! !\\nOBInteractionRequest subclass: #OBConfirmationRequest\\n\\tinstanceVariableNames: 'prompt confirm cancel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBConfirmationRequest commentStamp: 'cwp 3/5/2004 12:30' prior: 0!\\nThis notification is used to ask the user to confirm some kind potentially dangerous operation. Its default action is to open a PopUpMenu.\\n\\niVars:\\n\\nprompt\\t\\t- a string describing the situation the user is asked to confirm\\nconfirm\\t\\t- a string describing the action that will be taken if the user confirms\\ncancel\\t\\t- a string describing the action that will be taken if the user does not confirm!\\n\\n\\n!OBConfirmationRequest methodsFor: 'initalizing' stamp: 'cwp 2/28/2004 12:00'!\\nsetPrompt: promptString confirm: confirmString cancel: cancelString\\n\\tprompt _ promptString.\\n\\tconfirm _ confirmString.\\n\\tcancel _ cancelString! !\\n\\n\\n!OBConfirmationRequest methodsFor: 'responding' stamp: 'cwp 2/28/2004 12:11'!\\ncancel\\n\\tself resume: false! !\\n\\n!OBConfirmationRequest methodsFor: 'responding' stamp: 'cwp 2/28/2004 12:11'!\\nok\\n\\tself resume: true! !\\n\\n\\n!OBConfirmationRequest methodsFor: 'user interaction' stamp: 'cwp 6/4/2006 14:17'!\\ndefaultAction\\n\\t(prompt beginsWith: 'BogusD') ifTrue: [self halt].\\n\\t^ PopUpMenu confirm: prompt trueChoice: confirm falseChoice: cancel! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBConfirmationRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:09'!\\nnewPrompt: prompt confirm: confirm cancel: cancel\\n\\t^ self new setPrompt: prompt confirm: confirm cancel: cancel! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:13'!\\nprompt: prompt\\n\\t^ self prompt: prompt confirm: 'Ok'! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:12'!\\nprompt: prompt confirm: confirm\\n\\t^ self prompt: prompt confirm: confirm cancel: 'Cancel'! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:02'!\\nprompt: prompt confirm: confirm cancel: cancel\\n\\t^ (self newPrompt: prompt confirm: confirm cancel: cancel) signal! !\\nObject subclass: #OBDefinition\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Utilities'!\\n!OBDefinition commentStamp: 'cwp 1/7/2005 23:38' prior: 0!\\nThe responsibility of a definition is to express a node's composition textually and respond to changes in the text by updating the node it represents. For example,a file browser might use a file definition to allow editing of a files contents.!\\n\\n\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:51'!\\naccept: aText notifying: aController\\n\\t^ self text: aText! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:08'!\\ndoItContext\\n\\t^ nil! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 2/28/2005 23:23'!\\ndoItReceiver\\n\\t| class |\\n\\tclass _ self selectedClass.\\n\\t^ class\\n\\t\\tifNotNil: [class theNonMetaClass]\\n\\t\\tifNil: [FakeClassPool new]! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 22:16'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:52'!\\ntext\\n\\t^ ''! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 22:16'!\\ntextSelection\\n\\t^ self selection! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:52'!\\ntext: aText\\n\\t^ false! !\\n\\n\\n!OBDefinition methodsFor: 'updating' stamp: 'cwp 6/4/2006 18:53'!\\nsignalChange\\n\\tOBAnnouncer current announce: (OBDefinitionChanged definition: self)! !\\nOBAnnouncement subclass: #OBDefinitionChanged\\n\\tinstanceVariableNames: 'definition node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:25'!\\ndefinition\\n\\t^ definition! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:26'!\\ndefinition: aDefinition\\n\\tdefinition _ aDefinition! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:47'!\\nnode\\n\\t^ node! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:47'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBDefinitionChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBDefinitionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:28'!\\ndefinition: aDefinition\\n\\t^ self new\\n\\t\\tdefinition: aDefinition;\\n\\t\\tyourself! !\\n\\n!OBDefinitionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:27'!\\nnode: aNode definition: aDefinition\\n\\t^ self new\\n\\t\\tnode: aNode;\\n\\t\\tdefinition: aDefinition;\\n\\t\\tyourself! !\\nOBPanel subclass: #OBDefinitionPanel\\n\\tinstanceVariableNames: 'definition'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBDefinitionPanel commentStamp: 'cwp 1/7/2005 23:35' prior: 0!\\nOBDefinition serves as the model for the text pane of a typical browser. It's main responsibility is to act as a relay between a PluggableTextMorph and a Definition supplied by the currently selected node.\\n\\niVars:\\n\\nbrowser - The browser of which this panel is a part.\\n!\\n\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 9/17/2004 00:56'!\\ndefinition: aDefinition\\n\\tdefinition _ aDefinition.\\n\\tself changed: #text! !\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 3/22/2004 20:06'!\\ngetDefinition\\n\\t^ browser currentNode ifNotNilDo: [:node | node definition]! !\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 3/22/2004 20:41'!\\nwithDefinitionDo: workBlock ifNil: nilBlock\\n\\tdefinition ifNil: [ ^ nilBlock value].\\n\\t^ workBlock value: definition! !\\n\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 6/4/2006 00:41'!\\naccept: aText notifying: aController\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | [def accept: aText notifying: aController]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: OBAnnouncerRequest\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdo: [:notification | notification resume: self announcer]]\\n\\t\\tifNil: [true]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:23'!\\ndoItContext\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #doItContext) ifTrue: [def doItContext]]\\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:23'!\\ndoItReceiver\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #doItReceiver) ifTrue: [def doItReceiver]]\\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 10/24/2004 09:16'!\\nmenu: aMenu shifted: aBoolean\\n\\t| items |\\n\\titems _ aBoolean \\n\\t\\tifTrue: [self shiftedYellowButtonMenu] \\n\\t\\tifFalse: [self yellowButtonMenu].\\n\\titems do: [:ea |\\n\\t\\t\\t ea = #-\\n\\t\\t\\t\\tifFalse: [aMenu add: ea first action: ea second]\\n\\t\\t\\t\\tifTrue: [aMenu addLine]].\\n\\t^ aMenu ! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 10/24/2004 09:27'!\\nperform: aSelector orSendTo: anObject\\n\\t| receiver |\\n\\treceiver _ (self respondsTo: aSelector) ifTrue: [self] ifFalse: [anObject].\\n\\treceiver perform: aSelector! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:22'!\\nselectedClass\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #selectedClass) ifTrue: [def selectedClass]] \\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 21:15'!\\nselection\\n\\t^ self withDefinitionDo: [:def | def textSelection] ifNil: [1 to: 0]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:42'!\\ntext\\n\\t^ self withDefinitionDo: [:def | def text] ifNil: ['']! !\\n\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 10/30/2004 22:03'!\\nmorph\\n\\t^ (OBPluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #text\\n\\t\\taccept: #accept:notifying:\\n\\t\\treadSelection: #selection\\n\\t\\tmenu: #menu:shifted:)\\n\\t\\t\\tfont: Preferences standardCodeFont;\\n\\t\\t\\tyourself\\n\\t\\t\\t\\n\\t\\\"see CodeHolder>>buildMorphicCodePaneWith:\\\"! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 3/9/2004 21:35'!\\nmorphHeight\\n\\t^ 0! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 7/14/2006 01:17'!\\nshiftedYellowButtonMenu\\n\\t^ {\\n\\t\\t{'explain' translated.\\t\\t\\t\\t\\t\\t#explain}.\\n\\t\\t#-.\\n\\t\\t{'selectors containing it (W)' translated.\\t\\t#methodNamesContainingIt}.\\n\\t\\t{'method strings with it (E)' translated.\\t\\t#methodStringsContainingit}.\\n\\t\\t{'method source with it' translated.\\t\\t\\t#methodSourceContainingIt}.\\n\\t\\t{'class names containing it' translated.\\t\\t#classNamesContainingIt}.\\n\\t\\t{'class comments with it' translated.\\t\\t\\t#classCommentsContainingIt}.\\n\\t\\t{'change sets with it' translated.\\t\\t\\t\\t#browseChangeSetsWithSelector}.\\n\\t\\t#-.\\n\\t\\t{'save contents to file...' translated.\\t\\t\\t#saveContentsInFile}.\\n\\t\\t#-.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t\\t\\t#yellowButtonActivity}.\\n\\t}\\n! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 10/24/2004 23:28'!\\nyellowButtonMenu\\n\\t^ {\\n\\t\\t{'find...(f)' translated.\\t\\t\\t\\t#find}.\\t\\t\\t \\n\\t\\t{'find again (g)' translated.\\t\\t\\t#findAgain}.\\t\\t \\n\\t\\t{'set search string (h)' translated.\\t#setSearchString}.\\n\\t\\t#-.\\t \\n\\t\\t{'do again (j)' translated.\\t\\t\\t#again}.\\t\\t \\n\\t\\t{'undo (z)' translated.\\t\\t\\t\\t#undo}.\\t\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'copy (c)' translated.\\t\\t\\t\\t#copySelection}.\\t \\n\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t#cut}.\\t\\t\\t \\n\\t\\t{'paste (v)' translated.\\t\\t\\t\\t#paste}.\\t\\t \\n\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'accept (s)' translated.\\t\\t\\t\\t#accept}.\\t\\t \\n\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t#cancel}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'do it (d)' translated.\\t\\t\\t\\t#doIt}.\\t\\t\\t \\n\\t\\t{'print it (p)' translated.\\t\\t\\t\\t#printIt}.\\t\\t \\n\\t\\t{'inspect it (i)' translated.\\t\\t\\t#inspectIt}.\\t\\t \\n\\t\\t{'explore it (I)' translated.\\t\\t\\t#exploreIt}.\\t\\t \\n\\t\\t{'debug it' translated.\\t\\t\\t\\t#debugIt}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'browse it (b)' translated.\\t\\t\\t\\t\\t#browseIt}.\\n\\t\\t{'senders of it (n)' translated.\\t\\t\\t\\t#sendersOfIt}.\\n\\t\\t{'implementors of it (m)' translated.\\t\\t\\t#implementorsOfIt}.\\n\\t\\t{'references to it (N)' translated.\\t\\t\\t\\t#referencesToIt}.\\n\\t\\t#-.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t#shiftedTextPaneMenuRequest}.\\n\\t}\\n! !\\n\\n\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 4/18/2006 21:31'!\\naboutToChange: ann\\n\\t| ok |\\n\\tself canDiscardEdits ifTrue: [^ true].\\n\\tok _ OBConfirmationRequest\\n\\t\\t\\tprompt: 'Changes have not been saved.\\nIs it OK to discard those changes?'\\n\\t\\t\\tconfirm: 'Discard changes'.\\n\\tok\\n\\t\\tifTrue: [self changed: #clearUserEdits]\\n\\t\\tifFalse: [ann veto]! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 11:31'!\\ndefinitionChanged: ann\\n\\tdefinition _ ann definition.\\n\\tself changed: #text! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/3/2006 21:55'!\\nrefresh: announcement\\n\\t| oldDefinition |\\n\\tdefinition ifNil: [^ self].\\n\\toldDefinition _ definition.\\n\\tdefinition _ self getDefinition.\\n\\tdefinition text = oldDefinition text ifTrue: [^ self].\\n\\tself canDiscardEdits\\n\\t\\t\\tifTrue: [self changed: #text]\\n\\t\\t\\tifFalse: [self changed: #codeChangedElsewhere]! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 4/24/2006 16:06'!\\nselectionChanged: ann\\n\\tself definition: self getDefinition! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 11:30'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBAboutToChange\\n\\t\\tsend: #aboutToChange:\\n\\t\\tto: self;\\n\\t\\t\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self;\\n\\t\\t\\n\\t\\tobserve: OBRefreshRequired\\n\\t\\tsend: #refresh:\\n\\t\\tto: self;\\n\\t\\t\\t\\t\\n\\t\\tobserve: OBDefinitionChanged\\n\\t\\tsend: #definitionChanged: \\n\\t\\tto: self.! !\\n\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'pmm 7/6/2006 20:49'!\\nbrowseIt: aSymbol\\n\\t| entry |\\n\\tentry := self selectedClass environment at: aSymbol ifAbsent: [nil].\\n\\tentry ifNil: [^ self implementorsOfIt: aSymbol].\\n\\t(entry isBehavior or: [entry isTrait ])\\n\\t\\tifFalse: [entry := entry class].\\n\\tOBSystemBrowser openOnClass: entry.\\n\\t^ true\\n\\t! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nimplementorsOfIt: aSelector \\n\\tOBImplementorsBrowser browseRoot: (OBSelectorNode on: aSelector).\\n\\t^true! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nreferencesToIt: aClassName \\n\\t| class |\\n\\tclass := self selectedClass environment at: aClassName ifAbsent: [^false].\\n\\tclass isBehavior ifFalse: [^false].\\n\\tOBReferencesBrowser browseRoot: (OBClassNode on: class).\\n\\t^true! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nsendersOfIt: aSelector \\n\\tOBSendersBrowser browseRoot: (OBSelectorNode on: aSelector).\\n\\t^true! !\\nNotification subclass: #OBDispatcherRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\nOBCodeNode subclass: #OBEnvironmentNode\\n\\tinstanceVariableNames: 'environment'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBEnvironmentNode commentStamp: 'cwp 1/8/2005 13:01' prior: 0!\\nOBEnvironmentNode wraps an instance of SystemDictionary. In current Squeak images, there is only one such instance, but OB-Standard is coded so as to use rely on this assumption as little as possible. Thus OBEnvironmentNode typically serves as the root of the standard browser, and passes its environment on to other nodes in the tree.!\\n\\n\\n!OBEnvironmentNode methodsFor: 'navigating'!\\ncategories\\n\\t^ environment organization categories collect: [:cat | OBClassCategoryNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ton: cat\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinEnvironment: environment]! !\\n\\n!OBEnvironmentNode methodsFor: 'navigating' stamp: 'cwp 9/20/2005 08:43'!\\ncategoryNodeNamed: aString \\n\\t^ OBClassCategoryNode on: aString! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'accessing'!\\nenvironment\\n\\t^ environment! !\\n\\n!OBEnvironmentNode methodsFor: 'accessing'!\\norganization\\n\\t^ self environment organization! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'displaying'!\\nname \\n\\t^ 'Squeak'! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'initializing'!\\nsetEnvironment: anEnvironment\\n\\tenvironment := anEnvironment! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:54'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBEnvironmentNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBEnvironmentNode class methodsFor: 'as yet unclassified'!\\nforImage\\n\\t^ self on: Smalltalk! !\\n\\n!OBEnvironmentNode class methodsFor: 'as yet unclassified'!\\non: anEnvironment\\n\\t^ self new setEnvironment: anEnvironment! !\\nObject subclass: #OBFilter\\n\\tinstanceVariableNames: 'metaNode monitor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBFilter commentStamp: 'cwp 3/4/2004 21:53' prior: 0!\\nA browser's metagraph defines the way in which the user may traverse the graph of objects which make up the browser's domain. But it's not always desirable to have all the nodes made available by the metagraph to be visible in the browser. An filter provides a strategy for filtering out some of the nodes from the display. \\n\\nOBFilter provides a \\\"null\\\" filter - one that does no filtering at all - and serves as a superclass for other filters. !\\n\\n\\n!OBFilter methodsFor: 'accessing' stamp: 'cwp 2/11/2004 23:48'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBFilter methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:56'!\\nmonitor: aMonitor\\n\\tmonitor _ aMonitor! !\\n\\n\\n!OBFilter methodsFor: 'initalizing' stamp: 'cwp 2/9/2004 20:54'!\\nsetMetaNode: aMetaNode\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/9/2004 20:50'!\\nchildren\\n\\t^ metaNode children! !\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/9/2004 20:52'!\\nnodesForParent: aNode\\n\\t^ metaNode nodesForParent: aNode! !\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/29/2004 14:34'!\\nselectAncestorOf: aNode withParent: parentNode\\n\\t^ (metaNode nodesForParent: parentNode)\\n\\t\\tdetect: [:child | child isAncestorOf: aNode] \\n\\t\\tifNone: [nil]! !\\n\\n\\n!OBFilter methodsFor: 'queries' stamp: 'cwp 2/9/2004 21:06'!\\nwantsButton\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBFilter class\\n\\tinstanceVariableNames: ''!\\n\\n!OBFilter class methodsFor: 'as yet unclassified' stamp: 'cwp 2/9/2004 20:54'!\\nforMetaNode: aMetaNode\\n\\t^ self new setMetaNode: aMetaNode! !\\nOBPanel subclass: #OBFixedButtonPanel\\n\\tinstanceVariableNames: 'models actions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBFixedButtonPanel commentStamp: 'cwp 1/7/2005 23:35' prior: 0!\\nOBFixedButtonPanel displays a horizontal row of buttons. In contrast to OBVarButtonPanel, the buttons do not change as nodes are selected in the navigation panel; instead they are enabled and disabled according to whether the actions they represent are applicable to the selected node.!\\n\\n\\n!OBFixedButtonPanel methodsFor: 'accessing' stamp: 'cwp 11/26/2004 22:53'!\\nbuttonModels\\n\\t^ models! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:20'!\\nisEnabled: aModel\\n\\t^ (actions at: aModel) notNil! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:20'!\\nisSelected: aModel\\n\\t^ true! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 8/29/2004 11:28'!\\npush: aModel\\n\\t(actions at: aModel) ifNotNilDo: [:action | action trigger]! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 6/3/2006 22:15'!\\nselectionChanged: ann\\n\\t| node nodeActions |\\n\\tnode _ browser currentNode ifNil: [^ self].\\n\\tnodeActions _ (node metaNode actionsForNode: node) select: [:ea | ea wantsButton].\\n\\tactions keys do: \\n\\t\\t[:model | \\n\\t\\tactions at: model put: nil.\\n\\t\\tnodeActions do: \\n\\t\\t\\t[:action | model label = action buttonLabel ifTrue: [actions at: model put: action]]].\\n\\tactions keys do: [:ea | ea selectionChanged].! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 6/3/2006 22:14'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'lr 3/23/2006 18:14'!\\ncreateMorph\\n\\t^(RectangleMorph new)\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tborderWidth: 0;\\n\\t\\twrapCentering: #center;\\n\\t\\tcellPositioning: #leftCenter;\\n\\t\\trubberBandCells: true;\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 2;\\n\\t\\tyourself! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:24'!\\nmorph\\n\\t| morph |\\n\\tmorph := self createMorph.\\n\\tself buttonModels do: [:ea | morph addMorphBack: (self morphForModel: ea)].\\n\\t^morph! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:25'!\\nmorphForModel: aModel\\n\\t| morph paneColor |\\n\\tmorph _ aModel morph.\\n\\tpaneColor _ browser defaultBackgroundColor.\\n\\tmorph onColor: paneColor darker offColor: paneColor lighter.\\n\\t^ morph! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'lr 3/23/2006 18:15'!\\nmorphHeight\\n\\t^ 30! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'initializing' stamp: 'cwp 11/26/2004 22:53'!\\ninitialize\\n\\tmodels _ OrderedCollection new.\\n\\tactions _ Dictionary new.! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'public' stamp: 'cwp 11/26/2004 22:52'!\\naddButtonWithLabel: label\\n\\t| model |\\n\\tmodel _ OBButtonModel withLabel: label inBar: self.\\n\\tmodels add: model.\\n\\tactions at: model put: nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBFixedButtonPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBFixedButtonPanel class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2006 10:41'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBCodeBrowser subclass: #OBHierarchyBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBHierarchyBrowser commentStamp: 'cwp 1/7/2005 23:50' prior: 0!\\nOBHierarchyBrowser provides a three-pane browers that displays a class within it's surrounding hierarchy - both superclasses and subclasses!\\n\\n\\n!OBHierarchyBrowser methodsFor: 'as yet unclassified' stamp: 'cwp 12/13/2004 00:40'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen! !\\n\\n!OBHierarchyBrowser methodsFor: 'as yet unclassified' stamp: 'cwp 12/13/2004 01:00'!\\ndefaultLabel\\n\\t^ self root name, ' Hierarchy'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBHierarchyBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:06'!\\ndefaultMetaNode\\n\\t^ self \\n\\t\\taddTo: (OBMetaNode named: 'RootClass')\\n\\t\\tclass: #classHierarchy \\n\\t\\tcomment: #commentHierarchy \\n\\t\\tmetaclass: #metaclassHierarchy.\\n! !\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'cwp 12/13/2004 00:37'!\\npaneCount\\n\\t^ 3! !\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'cwp 12/13/2004 01:00'!\\ntitleForRoot: aNode\\n\\t^ aNode name, ' Hierarchy'! !\\n\\n\\n!OBHierarchyBrowser class methodsFor: 'instance creation' stamp: 'lr 3/6/2006 19:28'!\\nonClass: aClass \\n\\t^self root: aClass asNode selection: aClass asNode! !\\n\\n\\n!OBHierarchyBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 22:49'!\\nopenOnClass: aClass\\n\\t^ (self onClass: aClass) open! !\\nOBListBrowser subclass: #OBImplementorsBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBImplementorsBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'cwp 3/2/2006 15:35'!\\nchaseImplementorsNav: navSelector\\n\\t| message implementor |\\n\\tmessage := OBMetaNode named: 'Message'.\\n\\timplementor := OBMetaNode named: 'Implementor'.\\n\\timplementor\\n\\t\\tdisplaySelector: #indentedFullName;\\n\\t\\tchildAt: #messages put: message;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmessage\\n\\t\\tchildAt: navSelector labeled: 'implementors' put: implementor;\\n\\t\\taddActor: OBNodeActor new.\\n\\t^ implementor! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\ndefaultMetaNode\\n\\t^ self hierarchicalImplementors! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\nhierarchicalImplementors\\n\\t^ self implementorsNav: #implementorsHierarchically! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\nimplementorsNav: navSelector\\n\\t| selector implementors |\\n\\tselector := OBMetaNode named: 'Selector'.\\n\\timplementors := OBMetaNode named: 'Implementors'.\\n\\t\\n\\tselector \\n\\t\\tchildAt: navSelector labeled: 'list' put: implementors;\\n\\t\\tchildAt: navSelector labeled: 'chase' put: (self chaseImplementorsNav: navSelector);\\n\\t\\tfilterClass: OBModalFilter.\\n\\timplementors \\n\\t\\tdisplaySelector: #indentedFullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\t^ selector! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:36'!\\ntitle\\n\\t^ 'Implementors of'! !\\nOBActor subclass: #OBImplementorsViewActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'cwp 7/14/2006 14:28'!\\nactionsForParent: aNode\\n\\t^{OBAction\\n\\t\\t\\tlabel: 'add implementor' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #addImplementor:\\n\\t\\t\\targuments: {aNode}\\n\\t\\t\\tkeystroke: $a\\n\\t\\t\\ticon: self newIcon}! !\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'dvf 9/12/2005 16:34'!\\naddImplementor: aNode \\n\\t| class sel |\\n\\tsel := aNode selector.\\n\\tclass := self getClassForNewImplementationOf: sel.\\n\\tclass ifNil: [^self].\\n\\t(class selectors includes: sel) \\n\\t\\tifTrue: [^self inform: class name , ' already implements #' , sel].\\n\\tclass compile: aNode selector , '\\n\\tself shouldBeImplemented'.\\n\\t(OBMethodNode on: sel inClass: class) signalSelection! !\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'dvf 9/12/2005 16:14'!\\ngetClassForNewImplementationOf: sel \\n\\t| className |\\n\\tclassName := (OBTextRequest \\n\\t\\t\\t\\tprompt: 'Please type class name in which to implement ' , sel\\n\\t\\t\\t\\ttemplate: '') ifNil: [''].\\n\\t^(Smalltalk classNamed: className withBlanksTrimmed) ifNil: \\n\\t\\t\\t[self inform: 'Class ' , className , ' not found'.\\n\\t\\t\\tnil]! !\\nOBCodeBrowser subclass: #OBInheritanceBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBInheritanceBrowser commentStamp: 'cwp 1/7/2005 23:51' prior: 0!\\nOBInheritanceBrowser shows the inheritance hierarchy of a method, both superclass implementations which it overrides, and subclass implementations which override it.!\\n\\n\\n!OBInheritanceBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBInheritanceBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:08'!\\ndefaultMetaNode\\n\\t| method root |\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\troot := OBMetaNode named: 'Root'.\\n\\troot\\n\\t\\tchildAt: #children put: method.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\tchildAt: #overrides put: method;\\n\\t\\taddActor: OBNodeActor new.\\n\\t^ root! !\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration'!\\ntitle\\n\\t^ 'Inheritance'! !\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration' stamp: 'cwp 11/25/2004 22:05'!\\ntitleForRoot: aCollectionNode\\n\\t^ 'Inheritance of ', aCollectionNode children first selector printString! !\\nOBVariableNode subclass: #OBInstanceVariableNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBInstanceVariableNode commentStamp: 'cwp 1/8/2005 12:50' prior: 0!\\nOBClassVariable provides a method for finding methods which refer to an instance, ie, by searching for instance variable access bytecodes rather than for an association in the literal frame.!\\n\\n\\n!OBInstanceVariableNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:48'!\\naccessors\\n\\t| accessors |\\n\\taccessors := OrderedCollection new.\\n\\tself theClass withAllSubAndSuperclassesDo: [:class |\\n\\t\\t(class whichSelectorsAccess: name) asSortedCollection\\n\\t\\t\\tdo: [:ea | ea = #DoIt ifFalse: [accessors add: \\n\\t\\t\\t\\t\\t(self referenceForMethod: ea ofClass: class name)]]].\\n\\t^ accessors asArray\\tcollect: [:ref | OBMethodNode on: ref]! !\\nNotification subclass: #OBInteractionRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBInteractionRequest commentStamp: 'cwp 12/7/2004 00:13' prior: 0!\\nOBInteractionRequest is an abstract superclass for notifications that request some interaction with the user. It's useful for catching such notifications in an exception handler, while allowing other notifications to operate normally.!\\n\\n\\n!OBInteractionRequest methodsFor: 'as yet unclassified' stamp: 'cwp 10/17/2004 19:31'!\\nisBrowseRequest\\n\\t^ false! !\\nOBCodeBrowser subclass: #OBListBrowser\\n\\tinstanceVariableNames: 'labelPrefix'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBListBrowser commentStamp: 'cwp 1/7/2005 23:53' prior: 0!\\nOBListBrowsers are used to display simple lists of methods, such as senders or implementors.!\\n\\n\\n!OBListBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:58'!\\ndefaultBackgroundColor\\n\\t^ Color lightBlue! !\\n\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 11/25/2004 22:21'!\\ndefaultLabel\\n\\t^ self labelPrefix, ' ', self root name printString! !\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 11/25/2004 22:18'!\\nlabelPrefix\\n\\t^ labelPrefix ifNil: [labelPrefix _ self root metaNode edges first label capitalized, ' of']! !\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 10/17/2004 20:54'!\\nlabelPrefix: aString\\n\\tlabelPrefix _ aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBListBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBListBrowser class methodsFor: 'opening' stamp: 'avi 9/17/2005 01:34'!\\nbrowseRoot: aNode\\n\\tself browseRoot: aNode title: self title! !\\n\\n!OBListBrowser class methodsFor: 'opening' stamp: 'avi 9/17/2005 01:21'!\\nbrowseRoot: aNode title: aString \\n\\t(self metaNode: self defaultMetaNode root: aNode selection: nil)\\n\\t\\tlabelPrefix: aString;\\n\\t\\topen\\n\\t! !\\n\\n\\n!OBListBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 17:54'!\\nmaxPanes\\n\\t^ 2! !\\n\\n!OBListBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 17:54'!\\nminPanes\\n\\t^ 1! !\\nOBMethodNode subclass: #OBMessageNode\\n\\tinstanceVariableNames: 'message'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMessageNode commentStamp: 'cwp 1/8/2005 12:40' prior: 0!\\nAn OBMessageNode refers to a message send in the source code of a method. They are typically used in the 'senders' browser.!\\n\\n\\n!OBMessageNode methodsFor: 'navigating'!\\nimplementors\\n\\t^ self implementorsOf: message! !\\n\\n!OBMessageNode methodsFor: 'navigating'!\\nsendersOfMessage\\n\\t^ self sendersOf: message! !\\n\\n\\n!OBMessageNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:26'!\\nname\\n\\t^ message! !\\n\\n\\n!OBMessageNode methodsFor: 'accessing'!\\nselection\\n\\t| methodNode assoc |\\n\\tmethodNode := Parser new \\n\\t\\t\\t\\t\\tparse: self source\\n\\t\\t\\t\\t\\tclass: self theClass.\\n\\tassoc := (methodNode encoder rawSourceRanges) \\n\\t\\t\\tassociations detect: [:ea | ea key isMessage: message receiver: nil arguments: nil]\\n\\t\\t\\t\\t\\t\\tifNone: [nil -> (1 to: 0)].\\n\\t\\t\\t\\t\\t\\t\\\"Some messages are generated by the compiler.\\\"\\n\\t^ assoc value! !\\n\\n\\n!OBMessageNode methodsFor: 'initializing'!\\nsetMessage: aSelector selector: aSelector2 class: aClass\\n\\tmessage := aSelector.\\n\\tselector := aSelector2.\\n\\tself theClass: aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMessageNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\nfromMethodNode: aMethodNode\\n\\t^ self new \\n\\t\\tsetMessage: aMethodNode selector\\n\\t\\tselector: aMethodNode selector\\n\\t\\tclass: aMethodNode theClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\non: aSelector inMethodNode: aNode\\n\\t^ self \\n\\t\\ton: aSelector \\n\\t\\tinMethod: aNode selector \\n\\t\\tinClass: aNode theClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation' stamp: 'cwp 12/8/2004 23:46'!\\non: aSelector inMethodReference: ref\\n\\t^ self \\n\\t\\ton: aSelector \\n\\t\\tinMethod: ref methodSymbol\\n\\t\\tinClass: ref actualClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\non: aSelector inMethod: aSelector2 inClass: classRef\\n\\t^ self new setMessage: aSelector selector: aSelector2 class: classRef! !\\nObject subclass: #OBMetaEdge\\n\\tinstanceVariableNames: 'label selector metaNode'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBMetaEdge commentStamp: 'cwp 1/7/2005 23:20' prior: 0!\\nAn OBMetaEdge is an edge in the browser's metagraph. It represents a message sent to a node to obtain further nodes. It is refered to by the \\\"parent\\\" metanode, and refers to the \\\"child\\\" metanode.\\n\\niVars:\\n\\nlabel \\t\\t- a string describing the metaNode, for filters which allow the user \\n\\t\\t\\t to choose which edges to follow\\nselector\\t- when a node is selected by the user, this message will be \\n\\t\\t\\t sent to it to obtain its children\\nmetaNode \\t- a MetaNode corresponding to the nodes answered by the above message\\n\\t\\t!\\n\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nlabel\\n\\t^ label! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 3/3/2004 00:12'!\\nnodesForParent: aNode\\n\\t^ (aNode perform: selector) do: [:ea | ea metaNode: metaNode]\\n! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nselector\\n\\t^ selector! !\\n\\n\\n!OBMetaEdge methodsFor: 'initializing' stamp: 'cwp 2/7/2004 22:36'!\\nsetLabel: aString selector: aSelector metaNode: aMetaNode\\n\\tlabel _ aString.\\n\\tselector _ aSelector.\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBMetaEdge methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:03'!\\nprintOn: aStream\\n\\taStream nextPutAll: selector printString, '->'. \\n\\tmetaNode shortPrintOn: aStream.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMetaEdge class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMetaEdge class methodsFor: 'as yet unclassified' stamp: 'cwp 2/7/2004 22:35'!\\nlabel: aString selector: aSelector metaNode: aMetaNode\\n\\t^ self new setLabel: aString selector: aSelector metaNode: aMetaNode! !\\n\\n!OBMetaEdge class methodsFor: 'as yet unclassified' stamp: 'cwp 2/9/2004 22:32'!\\nselector: aSelector metaNode: aMetaNode\\n\\t^ self new setLabel: aSelector asString selector: aSelector metaNode: aMetaNode! !\\nObject subclass: #OBMetaNode\\n\\tinstanceVariableNames: 'name filterClass columnClass edges actors displaySelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBMetaNode commentStamp: 'cwp 1/7/2005 23:23' prior: 0!\\nA MetaNode represents a hypothetical node in the browser's domain graph.\\n\\niVars:\\n\\nfilterClass\\t\\t\\t- the class used to filter this hypothetical node's children\\ncolumnClass\\t\\t- the class of column used to display this node's children\\nedges\\t\\t\\t\\t- messages that could be sent to the node to obtain children\\nactors\\t\\t\\t\\t- providers of functionality for manipulating the node\\ndisplaySelector\\t\\t- the message used to retreive a nodes display name!\\n\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 21:41'!\\ndisplaySelector\\n\\t^ displaySelector ifNil: [displaySelector _ #name]! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 21:42'!\\ndisplaySelector: aSelector\\n\\tdisplaySelector _ aSelector! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 3/6/2004 21:54'!\\nname\\n\\t^ name ifNil: ['MetaNode']! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 3/6/2004 21:05'!\\nname: aString\\n\\tname _ aString! !\\n\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 18:59'!\\nactionSetsForNode: aNode\\n\\t^ actors collect: [:actor | actor actionsForNode: aNode]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:01'!\\nactionSetsForParent: aNode\\n\\t^ actors collect: [:actor | actor actionsForParent: aNode]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:00'!\\nactionsForNode: aNode\\n\\t^ (self actionSetsForNode: aNode) gather: [:ea | ea]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:02'!\\nactionsForParent: aNode\\n\\t^ (self actionSetsForParent: aNode) gather: [:ea | ea]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 3/3/2004 22:48'!\\naddActor: anActor\\n\\tactors add: anActor.! !\\n\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/9/2004 20:28'!\\nchildAt: aSelector labeled: aString put: aMetaNode\\n\\tedges add: (OBMetaEdge label: aString selector: aSelector metaNode: aMetaNode)! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:35'!\\nchildAt: aSelector put: aMetaNode\\n\\tedges add: (OBMetaEdge selector: aSelector metaNode: aMetaNode)! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:44'!\\nchildren\\n\\t^ edges collect: [:edge | edge metaNode]! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:38'!\\nhasChildren\\n\\t^ edges isEmpty not! !\\n\\n\\n!OBMetaNode methodsFor: 'columns' stamp: 'avi 3/4/2004 03:11'!\\ncolumnClass: aClass\\n\\tcolumnClass _ aClass! !\\n\\n!OBMetaNode methodsFor: 'columns' stamp: 'cwp 11/16/2004 22:03'!\\ncolumnInPanel: aBrowser node: aNode\\n\\tcolumnClass ifNil: [columnClass _ OBColumn].\\n\\t^ columnClass\\n\\t\\tinPanel: aBrowser\\n\\t\\tmetaNode: self\\n\\t\\tnode: aNode! !\\n\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:26'!\\nfilter\\n\\tfilterClass ifNil: [filterClass _ OBFilter].\\n\\t^ filterClass forMetaNode: self! !\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:02'!\\nfilterClass: aClass\\n\\tfilterClass _ aClass! !\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:00'!\\nmetaNode\\n\\t^ self! !\\n\\n\\n!OBMetaNode methodsFor: 'initializing' stamp: 'cwp 12/8/2004 20:06'!\\ninitialize\\n\\tedges _ OrderedCollection new.\\n\\tactors _ OrderedCollection new.! !\\n\\n\\n!OBMetaNode methodsFor: 'metagraph' stamp: 'cwp 2/9/2004 21:12'!\\nedges\\n\\t^ edges! !\\n\\n\\n!OBMetaNode methodsFor: 'nodes' stamp: 'cwp 3/3/2004 00:22'!\\nnodesForParent: aNode\\n\\t^ edges gather: [:edge | edge nodesForParent: aNode]! !\\n\\n\\n!OBMetaNode methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:01'!\\nprintOn: aStream\\n\\taStream nextPutAll: self name;cr.\\n\\tedges do: [:e | e printOn: aStream. aStream cr].! !\\n\\n!OBMetaNode methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:01'!\\nshortPrintOn: aStream\\n\\taStream nextPutAll: self name.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMetaNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMetaNode class methodsFor: 'instance creation' stamp: 'cwp 3/6/2004 21:06'!\\nnamed: aString\\n\\t^ self new name: aString! !\\n\\n!OBMetaNode class methodsFor: 'instance creation' stamp: 'cwp 3/3/2004 23:08'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBClassNode subclass: #OBMetaclassNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMetaclassNode commentStamp: 'cwp 1/8/2005 11:29' prior: 0!\\nOBMetaclassNode is essentially the same as an OBClassNode, but overrides a few methods to work properly with metaclasses.!\\n\\n\\n!OBMetaclassNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:57'!\\nbrowse\\n\\t^ OBSystemBrowser openOnClass: self theNonMetaClass ! !\\n\\n\\n!OBMetaclassNode methodsFor: 'displaying' stamp: 'cwp 12/13/2004 00:56'!\\nname \\n\\t^ self nonMetaName! !\\n\\n!OBMetaclassNode methodsFor: 'displaying'!\\nnonMetaName\\n\\t^ self theNonMetaClass name! !\\n\\n\\n!OBMetaclassNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tsuper setClass: aClass theMetaClass\\n\\t\\t! !\\nOBClassAwareNode subclass: #OBMethodCategoryNode\\n\\tinstanceVariableNames: 'name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodCategoryNode commentStamp: 'cwp 1/8/2005 12:29' prior: 0!\\nOBMethodCategory represents a category within a ClassOrganization. Instead of an organization definition, OBMethodCategory presents a MethodDefinition with the class' default method template.!\\n\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:04'!\\nactions\\n\\t^ {\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'\\n\\t}\\n! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:50'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass category: name! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions'!\\nfileOut\\n\\tself theClass fileOutCategory: name! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove\\n\\tself theClass removeCategory: name.\\n\\tself signalDeletion! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfMethodCat:! !\\n\\n!OBMethodCategoryNode methodsFor: 'ancestry'!\\nisDescendantOfMethodCat: other\\n\\t^ (other theClassName = self theClassName) and: [other name = name]! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'accessing'!\\ncategory\\n\\t^ name! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing'!\\ncontainer\\n\\t^ self theClass! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing' stamp: 'cwp 9/14/2005 09:06'!\\nmethodReferences\\n\\t^ (self theClass organization listAtCategoryNamed: name)\\n\\t\\tcollect: [:ea | MethodReference new\\n\\t\\t\\t\\t\\t\\tsetClassSymbol: self theNonMetaClassName\\n\\t\\t\\t\\t\\t\\tclassIsMeta: self theClass isMeta\\n\\t\\t\\t\\t\\t\\tmethodSymbol: ea\\n\\t\\t\\t\\t\\t\\tstringVersion: '']\\n! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing' stamp: 'dvf 8/16/2005 17:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $<.\\n\\tself name printOn: aStream.\\n\\taStream nextPut: $>.! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'public'!\\ndefinition\\n\\t^ OBMethodDefinition inCategory: self category inClass: self theClass! !\\n\\n!OBMethodCategoryNode methodsFor: 'public'!\\nname\\n\\t^ name! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'drag and drop' stamp: 'lr 4/6/2006 11:46'!\\ndropOnClass: aNode\\n\\tself methods do: [ :each | each dropOnClass: aNode ].\\n\\taNode signalChildrenChanged.\\n\\t^ true! !\\n\\n!OBMethodCategoryNode methodsFor: 'drag and drop'!\\ndropSelector\\n\\t^ #dropOnMethodCategory:! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'comparing' stamp: 'cwp 12/20/2004 00:53'!\\nhash\\n\\t^ self name hash! !\\n\\n!OBMethodCategoryNode methodsFor: 'comparing' stamp: 'cwp 12/20/2004 00:50'!\\n= other\\n\\tself species = other species ifFalse: [^ false].\\t\\n\\tself theClass = other theClass ifFalse: [^ false].\\n\\t^ self name = other name! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/19/2005 17:16'!\\nmethods\\n\\t^ self methodReferences collect: [:ref | ref asNode]! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'initializing'!\\nsetName: aString class: aClass\\n\\tname := aString.\\n\\tself theClass: aClass! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:48'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodCategoryNode class methodsFor: 'actions' stamp: 'cwp 9/18/2004 22:58'!\\nactionsForParent: aNode\\n\\t^ #()! !\\n\\n\\n!OBMethodCategoryNode class methodsFor: 'instance creation'!\\non: aString inClass: aClassReference\\n\\t^ self new setName: aString class: aClassReference! !\\nOBDefinition subclass: #OBMethodDefinition\\n\\tinstanceVariableNames: 'theClass category source selection callback'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBMethodDefinition commentStamp: 'cwp 1/8/2005 13:20' prior: 0!\\nOBMethodDefinition knows how to present method source in the browser's text pane and compile a new CompiledMethod when the source changes. It implements several safety checks to ensure that methods are not accidentally overwritten.!\\n\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 9/18/2005 14:53'!\\naccept: aText notifying: aController\\n\\t| newSelector |\\n\\tnewSelector := self compileMethod: aText notifying: aController.\\n\\tnewSelector ifNil: [^ false].\\n\\t(self nodeFor: newSelector) demandSelection.\\n\\t^ true! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 10/17/2004 23:16'!\\nredefineSource: aText selector: newSelector\\n\\tnewSelector = self selector \\n\\t\\tifTrue: [source := aText]\\n\\t\\tifFalse: [(self methodNodeFor: newSelector) signalSelection].\\n! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks'!\\nselectedClass\\n\\t^ self theClass! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks'!\\nselection\\n\\t^ selection ifNil: [1 to: (source ifNil: [self text size] ifNotNil: [0])]! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 11/29/2004 21:21'!\\ntext\\n\\t^ source \\n\\t\\tifNotNil: [source asText makeSelectorBold]\\n\\t\\tifNil: [self theClass sourceCodeTemplate]! !\\n\\n\\n!OBMethodDefinition methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:36'!\\ncallback: aBlockContext \\n\\tcallback _ aBlockContext! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\ncategory\\n\\t^ category ifNil: [category := self theClass whichCategoryIncludesSelector: self selector]! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\nselector\\n\\t^ source ifNotNil: [Parser new parseSelector: source]! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\ntheClass\\n\\t^ theClass! !\\n\\n\\n!OBMethodDefinition methodsFor: 'compiling'!\\ncompileMethod: aText notifying: aController\\n\\t^ (self confirmMethod: aText)\\n\\t\\tifTrue: [self theClass \\n\\t\\t\\t\\t\\tcompile: aText \\n\\t\\t\\t\\t\\tclassified: self category \\n\\t\\t\\t\\t\\tnotifying: aController]\\n\\t\\tifFalse: [nil]! !\\n\\n!OBMethodDefinition methodsFor: 'compiling' stamp: 'cwp 10/17/2004 23:33'!\\nnodeFor: aSelector\\n\\t^ callback value: aSelector! !\\n\\n\\n!OBMethodDefinition methodsFor: 'confirming' stamp: 'cwp 10/17/2004 22:42'!\\nconfirmMethod: aText\\n\\t| sel |\\n\\tsel _ Parser new parseSelector: aText.\\n\\t^ (self theClass isMeta \\n\\t\\t\\tand: [(self selectorAlreadyDefined: sel) not] \\n\\t\\t\\tand: [Metaclass isScarySelector: sel])\\n\\t\\t\\t\\tifTrue: [self confirmScarySelector: sel]\\n\\t\\t\\t\\tifFalse: [^ true]! !\\n\\n!OBMethodDefinition methodsFor: 'confirming'!\\nconfirmScarySelector: aSelector\\n\\t| prompt |\\n\\tprompt := aSelector, ' is used in the existing class system.\\nOverriding it could cause serious problems.\\nIs this really what you want to do?'.\\n\\n\\t^ OBConfirmationRequest\\n\\t\\tprompt: prompt\\n\\t\\tconfirm: 'Override'! !\\n\\n!OBMethodDefinition methodsFor: 'confirming'!\\nselectorAlreadyDefined: aSelector\\n\\t^ self theClass selectors includes: aSelector! !\\n\\n\\n!OBMethodDefinition methodsFor: 'initializing' stamp: 'cwp 10/17/2004 23:33'!\\nsetClass: aClass category: aString source: aText selection: anInterval\\n\\ttheClass := aClass.\\n\\tcategory := aString.\\n\\tsource := aText.\\n\\tselection := anInterval.\\n\\tcallback := [:sel | OBMethodNode on: sel inClass: theClass]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\ninCategory: aString inClass: aClass\\n\\t^ self \\n\\t\\tselection: nil\\n\\t\\tsource: nil\\n\\t\\tinCategory: aString\\n\\t\\tinClass: aClass! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\nselection: anInterval source: aText inCategory: aCategory inClass: aClass\\n\\t^ self new\\n\\t\\tsetClass: aClass\\n\\t\\tcategory: aCategory\\n\\t\\tsource: aText\\n\\t\\tselection: anInterval! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\nselection: anInterval source: aText inClass: aClass\\n\\t^ self \\n\\t\\tselection: anInterval\\n\\t\\tsource: aText\\n\\t\\tinCategory: nil\\n\\t\\tinClass: aClass\\t! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:03'!\\nsource: aText inClass: aClass\\n\\t^ self \\n\\t\\tselection: nil\\n\\t\\tsource: aText\\n\\t\\tinCategory: nil\\n\\t\\tinClass: aClass! !\\nOBClassAwareNode subclass: #OBMethodNode\\n\\tinstanceVariableNames: 'selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodNode commentStamp: 'cwp 1/8/2005 12:37' prior: 0!\\nOBMethodNode wraps a method in a particular class. It supplies an OBMethodDefinition for displaying and editing the source code of the method, and various actions for manipulating the method. It has two roles: first it appears in the right most pane of a standard system browser. Second, it often serves as the root node for an OBListBrowser, and has navigation methods for senders, implementors etc.\\n\\nOBMethodNode also serves as the superclass for nodes that represent *parts* of a method, such as sends of a particular message, references to a class, accesses to a instance variable, etc.!\\n\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/12/2006 15:36'!\\nactions\\n\\t^{ \\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself \\n\\t\\t\\taction: #browseSenders\\n\\t\\t\\twithMenuLabel: 'senders'\\n\\t\\t\\twithButtonLabel: 'senders'\\n\\t\\t\\twithKeystroke: $n\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself \\n\\t\\t\\taction: #browseImplementors\\n\\t\\t\\twithMenuLabel: 'implementors'\\n\\t\\t\\twithButtonLabel: 'implementors'\\n\\t\\t\\twithKeystroke: $m\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself \\n\\t\\t\\taction: #browseVersions\\n\\t\\t\\tbuttonLabel: 'versions'\\n\\t\\t\\tmenuLabel: 'versions'.\\n\\t\\tself \\n\\t\\t\\taction: #browseInheritance\\n\\t\\t\\tbuttonLabel: 'inheritance'\\n\\t\\t\\tmenuLabel: 'inheritance'.\\n\\t\\tself \\n\\t\\t\\taction: #chaseVars\\n\\t\\t\\tbuttonLabel: 'variables'\\n\\t\\t\\tmenuLabel: 'chase variables'.\\n\\t\\tself \\n\\t\\t\\taction: #remove\\n\\t\\t\\twithLabel: 'remove'\\n\\t\\t\\twithKeystroke: $x\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(deleteIcon smallDeleteIcon)).\\n\\t\\tself moveToPackageAction\\n\\t}\\n! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 18:35'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass selector: selector! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:29'!\\nbrowseClass: aClass\\n\\taClass browseRoot: self copy! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:28'!\\nbrowseImplementors\\n\\tself browseClass: OBImplementorsBrowser! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 18:03'!\\nbrowseInheritance\\n\\tOBInheritanceBrowser openRoot: self inheritanceRoot selection: self! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:28'!\\nbrowseSenders\\n\\tself browseClass: OBSendersBrowser! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 15:42'!\\nbrowseVersions\\n\\tOBVersionBrowser openOn: self copy! !\\n\\n!OBMethodNode methodsFor: 'actions'!\\nfileOut\\n\\tself theClass fileOutMethod: selector! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/11/2006 02:43'!\\nmoveToPackage\\n\\t| packagesNames selection packages |\\n\\tpackages := PackageOrganizer default packages \\n\\t\\t\\t\\t\\tasSortedCollection: [:a :b | a packageName <= b packageName].\\n\\tpackagesNames := packages collect: [:ea | ea packageName].\\n\\tselection := OBChoiceRequest prompt: nil labels: packagesNames values: packages.\\n\\tselection ifNotNil: [selection addMethod: self reference].! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/12/2006 15:37'!\\nmoveToPackageAction\\n\\t^ self \\n\\t\\taction: #moveToPackage\\n\\t\\twithMenuLabel: 'move to package...'\\n\\t\\twithButtonLabel: 'move method'\\n\\t\\twithKeystroke: $p\\n\\t\\twithIcon: (MenuIcons tryIcons: #(windowIcon smallWindowIcon)).\\n! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 10/18/2004 00:30'!\\nremove\\n\\t| senders choice |\\n\\tsenders _ SystemNavigation default allCallsOn: self selector.\\n\\tsenders isEmpty ifTrue: [^ self doRemove].\\n\\tchoice _ OBChoiceRequest\\n\\t\\t\\t\\tprompt: 'This message has ', senders size asString, ' senders.'\\n\\t\\t\\t\\tlabels: #('Remove it' \\n\\t\\t\\t\\t\\t\\t'Remove, then browse senders' \\n\\t\\t\\t\\t\\t\\t'Don''t remove, but show me those senders' \\n\\t\\t\\t\\t\\t\\t'Forget it -- do nothing -- sorry I asked')\\n\\t\\t\\t\\tvalues: #(doRemove removeAndBrowse simpleBrowseSenders nil).\\n\\tchoice ifNotNil: [^ self perform: choice]\\n! !\\n\\n!OBMethodNode methodsFor: 'actions'!\\nselectMessage\\n\\t| messages sel |\\n\\tmessages := self messageSelectors copyWithFirst: selector.\\n\\tsel := (OBChoiceRequest labels: messages).\\n\\t^ sel ifNotNil: [OBMessageNode on: sel inMethodNode: self]! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/1/2004 00:36'!\\nsource\\n\\t^ (self theClass sourceCodeAt: self selector ifAbsent: [^ '']) \\n\\t\\tasText makeSelectorBold! !\\n\\n\\n!OBMethodNode methodsFor: 'private'!\\naddOverridersOf: aSelector inClass: aClass to: aCollection\\n\\taClass subclasses do: \\n\\t\\t[:ea | (ea includesSelector: aSelector)\\n\\t\\t\\t\\t\\tifTrue: [aCollection add: ea]\\n\\t\\t\\t\\t\\tifFalse: [self addOverridersOf: aSelector inClass: ea to: aCollection]]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 10/18/2004 00:29'!\\ndoRemove\\n\\tself theClass removeSelector: self selector.\\n\\tself signalDeletion! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 12/8/2004 23:48'!\\nimplementorsOf: aSelector\\n\\t^ (SystemNavigation default allImplementorsOf: aSelector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 12/8/2004 23:49'!\\ninheritanceRoot\\n\\t| rootClass |\\n\\trootClass := (self theClass withAllSuperclasses asArray\\n\\t\\t\\t\\t\\tselect: [:ea | ea includesSelector: self selector]) last.\\n\\t^ OBCollectionNode on: {OBMethodNode \\n\\t\\t\\t\\t\\t\\t\\t\\ton: self selector \\n\\t\\t\\t\\t\\t\\t\\t\\tinClass: rootClass}! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nmessageSelectors\\n\\t^ ((self theClass compiledMethodAt: self selector ifAbsent: [^ #()]) messages) asSortedArray! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nremoveAndBrowse\\n\\tself simpleBrowseSenders.\\n\\tself theClass removeSelector: self selector.\\n\\tself signalDeletion! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nsendersOf: aSelector\\n\\t^ (SystemNavigation default allCallsOn: aSelector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: aSelector inMethodReference: ref]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'avi 9/17/2005 01:29'!\\nsimpleBrowseSenders\\n\\tOBSendersBrowser browseRoot: self! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nsourcePointer\\n\\t^ (self theClass compiledMethodAt: self selector) sourcePointer! !\\n\\n\\n!OBMethodNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfMethod: ! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 12/2/2004 23:28'!\\nisDescendantOfMethodCat: aMethodCatNode\\n\\t^ (self theClass organization categoryOfElement: self selector) = aMethodCatNode name! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:55'!\\nisDescendantOfMethodVersion: anOBMethodVersionNode \\n\\t^ false! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 11/28/2004 10:37'!\\nisDescendantOfMethod: other\\n\\t^ other selector = selector\\n\\t\\tand: [self theClass withAllSuperclasses includes: other theClass].\\n\\t! !\\n\\n\\n!OBMethodNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 00:36'!\\ndefinition\\n\\t^ OBMethodDefinition\\n\\t\\tselection: self selection\\n\\t\\tsource: self source\\n\\t\\tinClass: self theClass! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nreference\\n\\t^ self referenceForMethod: selector ofClass: self theClassName! !\\n\\n!OBMethodNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 00:37'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nselector\\n\\t^ selector! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nsourceFiles\\n\\t^ OBSourceFilesRequest signal! !\\n\\n\\n!OBMethodNode methodsFor: 'drag and drop' stamp: 'lr 4/18/2006 08:55'!\\ndropOnClass: aNode\\n\\taNode theClass \\n\\t\\tcompile: self source\\n\\t\\tclassified: (self theClass organization \\n\\t\\t\\tcategoryOfElement: self selector).\\n\\tInputSensor default shiftPressed\\n\\t\\tifFalse: [ self theClass removeSelector: self selector ].\\n\\taNode signalChildrenChanged.\\n\\t^ true! !\\n\\n!OBMethodNode methodsFor: 'drag and drop' stamp: 'cwp 9/18/2005 19:01'!\\ndropOnMethodCategory: aNode\\n\\n\\t\\\"We don't support dropping on another class yet.\\\"\\n\\taNode theClass = self theClass ifFalse: [^ false].\\n\\t\\n\\tself theClass organization classify: self selector under: aNode name.\\n\\taNode signalChildrenChanged.\\n\\t\\n\\t^ true! !\\n\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'lr 3/29/2006 12:08'!\\ndisplayString\\n\\t^ (self theClass respondsTo: #includesLocalSelector:) \\n\\t\\tifFalse: [ super displayString ]\\n\\t\\tifTrue: [\\n\\t\\t\\t(self theClass includesLocalSelector: selector)\\n\\t\\t\\t\\tifTrue: [ super displayString ]\\n\\t\\t\\t\\tifFalse: [ \\n\\t\\t\\t\\t\\tsuper displayString asText \\n\\t\\t\\t\\t\\t\\taddAttribute: TextEmphasis italic ] ]! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:08'!\\nfullName\\n\\t^ self theClassName, '>>', selector! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/20/2004 23:13'!\\nindentedFullName\\n\\t^ self indent, self fullName! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:08'!\\nname\\n\\t^ selector! !\\n\\n\\n!OBMethodNode methodsFor: 'comparing' stamp: 'cwp 12/8/2004 22:07'!\\nhash\\n\\t^ theClass hash bitXor: selector hash! !\\n\\n!OBMethodNode methodsFor: 'comparing' stamp: 'cwp 12/8/2004 22:07'!\\n= other\\n\\t^ (self species = other species)\\n\\t\\tand: [self theClass = other theClass] \\n\\t\\tand: [self selector = other selector]! !\\n\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 1/2/2005 23:12'!\\nimplementors\\n\\t^ self implementorsOf: selector! !\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 22:35'!\\nimplementorsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self implementors! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nmessages\\n\\t^ (((self theClass\\n\\t\\t\\t\\tcompiledMethodAt: self selector \\n\\t\\t\\t\\tifAbsent: [^ #()]) messages) asSortedArray)\\n\\t\\t\\t\\t\\tcollect: [:sel | OBMessageNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: sel \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinMethod: selector \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinClass: self theClass]! !\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:49'!\\noverrides\\n\\t| classes |\\n\\tclasses := OrderedCollection new.\\n\\tself addOverridersOf: self selector inClass: self theClass to: classes.\\n\\t^ classes collect: [:ea | OBMethodNode on: selector inClass: ea] ! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nselectorAndMessages\\n\\t^ self messages copyWithFirst: self messageNode! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nsenders\\n\\t^ self sendersOf: selector! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nversions\\n\\t^ (OBMethodVersion scan: self sourceFiles from: self sourcePointer)\\n\\t\\tcollect: [:ea | OBMethodVersionNode on: ea]! !\\n\\n\\n!OBMethodNode methodsFor: 'nodes'!\\nmessageNode\\n\\t^ OBMessageNode fromMethodNode: self! !\\n\\n\\n!OBMethodNode methodsFor: 'printing' stamp: 'cwp 12/8/2004 21:59'!\\nprintOn: aStream\\n\\taStream\\n\\t\\tnextPutAll: self class name;\\n\\t\\tnextPut: $<;\\n\\t\\tnextPutAll: self theClass name;\\n\\t\\tnextPut: $#;\\n\\t\\tnextPutAll: self selector;\\n\\t\\tnextPut: $>! !\\n\\n\\n!OBMethodNode methodsFor: 'initializing'!\\nsetReference: aMethodReference\\n\\tself \\n\\t\\tsetSelector: aMethodReference methodSymbol\\n\\t\\tclass: (aMethodReference actualClass)! !\\n\\n!OBMethodNode methodsFor: 'initializing'!\\nsetSelector: aSelector class: aClass\\n\\tselector := aSelector.\\n\\tself theClass: aClass\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodNode class methodsFor: 'instance creation'!\\non: aMethodReference\\n\\t^ self new setReference: aMethodReference! !\\n\\n!OBMethodNode class methodsFor: 'instance creation'!\\non: aSelector inClass: aClassReference\\n\\t^ self new setSelector: aSelector class: aClassReference! !\\nObject subclass: #OBMethodVersion\\n\\tinstanceVariableNames: 'sources pointer classRef className category stamp prior selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBMethodVersion commentStamp: 'cwp 1/8/2005 13:25' prior: 0!\\nOBMethodVerison represents a version of a method found in the .sources or .changes files. It provides methods for parsing the method definition referenced by a source pointer, and for filing in the source to replace the current version of the method.!\\n\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ncategory\\n\\t^ category! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nclassSymbol\\n\\t^ classRef name! !\\n\\n!OBMethodVersion methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:51'!\\nlatest\\n\\t^ self class \\n\\t\\t\\tfromSources: sources \\n\\t\\t\\tandPointer: (classRef theClass compiledMethodAt: selector) sourcePointer! !\\n\\n!OBMethodVersion methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:42'!\\npointer\\n\\t^ pointer! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nselector\\n\\t^ selector ifNil: [self setSelector]! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nsource\\n\\t| file |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tfile position: (sources filePositionFromSourcePointer: pointer).\\n\\t^ file nextChunk asText makeSelectorBold! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nstamp\\n\\t^ stamp! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ntheClass\\n\\t^ classRef theClass! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ntheClassName\\n\\t^ classRef name! !\\n\\n\\n!OBMethodVersion methodsFor: 'compiling'!\\nfileIn\\n\\t(self theClass) ifNotNilDo: [:class | class\\n\\t\\t\\t\\t\\t\\t \\t\\t\\t\\tcompile: self source \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclassified: self category \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twithStamp: self stamp \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil]\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t! !\\n\\n\\n!OBMethodVersion methodsFor: 'comparing' stamp: 'cwp 10/17/2004 23:45'!\\nhash\\n\\t^ pointer hash! !\\n\\n!OBMethodVersion methodsFor: 'comparing' stamp: 'cwp 10/17/2004 23:45'!\\n= other\\n\\t^ self species = other species and: [self pointer = other pointer]! !\\n\\n\\n!OBMethodVersion methodsFor: 'initializing' stamp: 'cwp 11/6/2004 23:14'!\\nparseChunk: aString\\n\\t| tokens |\\n\\ttokens := Scanner new scanTokens: aString.\\n\\tclassRef := OBClassReference named: tokens first.\\n\\ttokens second = #class\\n\\t\\tifTrue: [classRef beMeta.\\n\\t\\t\\t\\tcategory := tokens fourth.\\n\\t\\t\\t\\tstamp := tokens sixth]\\n\\t\\tifFalse: [category := tokens third.\\n\\t\\t\\t\\ttokens size > 3 ifTrue: [stamp := tokens fifth]].\\n\\ttokens size > 6 ifTrue: [prior := tokens last].! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nparseSource\\n\\t| file position chunk |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tposition := sources filePositionFromSourcePointer: pointer.\\n\\tposition > file size ifTrue: [self error: 'Invalid source pointer'].\\n\\t\\n\\tfile position: (0 max: position-150). \\t\\\"Skip back to before the preamble\\\"\\n\\t\\t[file position < (position-1)] \\t\\\"then pick it up from the front\\\"\\n\\t\\t\\twhileTrue: [chunk := file nextChunk].\\n\\t\\n\\tself parseChunk: chunk.! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nprevious\\n\\t^ prior ifNotNil: [self class fromSources: sources andPointer: prior]! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nsetSelector\\n\\t| file |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tfile position: (sources filePositionFromSourcePointer: pointer).\\n\\t^ selector := Parser new parseSelector: file nextChunk.! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nsetSources: aSourceFileArray pointer: aSourcePointer\\n\\tsources := aSourceFileArray.\\n\\tpointer := aSourcePointer.\\n\\tself parseSource.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodVersion class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodVersion class methodsFor: 'instance creation'!\\nfromSources: sources andPointer: pointer\\n\\t^ self new setSources: sources pointer: pointer! !\\n\\n\\n!OBMethodVersion class methodsFor: 'scanning'!\\nscan: sources from: pointer \\n\\t| versions current |\\n\\t\\n\\tversions := OrderedCollection new.\\n\\tcurrent := OBMethodVersion fromSources: sources andPointer: pointer.\\n\\t[current notNil]\\n\\t\\twhileTrue: [versions add: current.\\n\\t\\t\\t\\t\\tcurrent := current previous].\\n\\t^ versions! !\\n\\n!OBMethodVersion class methodsFor: 'scanning'!\\nversionsOfMethod: methodReference \\n\\t| class selector |\\n\\tclass := methodReference actualClass.\\n\\tselector := methodReference methodSymbol.\\n\\t^ self scan: SourceFiles from: (class compiledMethodAt: selector) sourcePointer! !\\nOBClassAwareNode subclass: #OBMethodVersionNode\\n\\tinstanceVariableNames: 'version'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodVersionNode commentStamp: 'cwp 1/8/2005 12:41' prior: 0!\\nOBMethodVersions refer to OBMethodVersions, and are used by the VersionBrowser.!\\n\\n\\n!OBMethodVersionNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:38'!\\nactions\\n\\t^ {\\n\\t\\tself browseAction.\\n\\t \\tself action: #revert buttonLabel: 'revert' menuLabel: 'revert to selected version'\\n\\t}! !\\n\\n!OBMethodVersionNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:51'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass selector: version selector! !\\n\\n!OBMethodVersionNode methodsFor: 'actions'!\\nrevert\\n\\tversion fileIn! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:41'!\\nancestrySelector\\n\\t^ #isDescendantOfMethodVersion:! !\\n\\n!OBMethodVersionNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:43'!\\nisDescendantOfMethodVersion: aNode\\n\\t^ (version = aNode version)! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:57'!\\ncategory\\n\\t^ self theClass organization categoryOfElement: version selector! !\\n\\n!OBMethodVersionNode methodsFor: 'accessing'!\\nreference\\n\\t^ self referenceForMethod: version selector ofClass: self theClassName.! !\\n\\n!OBMethodVersionNode methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:44'!\\nversion\\n\\t^ version! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'compiling' stamp: 'cwp 10/17/2004 23:53'!\\ndefinition\\n\\t^ (OBMethodDefinition source: version source inClass: self theClass)\\n\\t\\tcallback: [:sel | \\n\\t\\t\\t\\t\\tversion selector = sel\\n\\t\\t\\t\\t\\t\\tifTrue: [self class on: version latest]\\n\\t\\t\\t\\t\\t\\tifFalse: [OBMethodNode on: sel inClass: self theClass]]! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'displaying' stamp: 'cwp 11/27/2004 21:38'!\\nname\\n\\t| stamp |\\n\\tstamp := version stamp ifNil: ['<timestamp missing>'].\\n\\t^ version theClassName, '>>', version selector, ' ', stamp! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'initializing'!\\nsetVersion: aMethodVersion\\n\\tversion := aMethodVersion.\\n\\tself theClass: version theClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodVersionNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodVersionNode class methodsFor: 'instance creation'!\\non: aMethodVersion \\n\\t^ self new setVersion: aMethodVersion! !\\nOBFilter subclass: #OBModalFilter\\n\\tinstanceVariableNames: 'selection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Utilities'!\\n!OBModalFilter commentStamp: 'cwp 1/7/2005 23:39' prior: 0!\\nOBModalFilter is used to implement the 'instance/?/class' buttons in a standard class browser. In functional terms it filters the nodes of a column according to the edge of the metagraph that they correspond to. OBModalFilter displays an OBRadioButtonBar in its column's pane, with one button per edge. Only nodes from the currently selected edge are allowed in the column.\\n\\niVars:\\n\\nselection\\t- the currently selected edge!\\n\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 2/25/2004 00:28'!\\nlist\\n\\t^ metaNode edges collect: [:edge | edge label]! !\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 2/9/2004 21:10'!\\nselection\\n\\t^ selection ifNil: [selection _ 1]! !\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 6/6/2006 00:20'!\\nselection: anInteger\\n\\tselection _ anInteger.\\n\\tself changed: #selection.\\n\\tmonitor listChanged.\\n! !\\n\\n\\n!OBModalFilter methodsFor: 'morphs' stamp: 'cwp 11/27/2004 18:01'!\\nbuttonMorph\\n\\t^ OBRadioButtonBar\\n\\t\\ton: self\\n\\t\\tlist: #list\\n\\t\\tselected: #selection\\n\\t\\tchangeSelected: #selection:! !\\n\\n\\n!OBModalFilter methodsFor: 'public' stamp: 'cwp 3/3/2004 00:23'!\\nnodesForParent: aNode\\n\\t^ self selectedEdge nodesForParent: aNode! !\\n\\n!OBModalFilter methodsFor: 'public' stamp: 'cwp 2/29/2004 14:35'!\\nselectAncestorOf: aNode withParent: parentNode\\n\\t| ancestor |\\n\\t1 \\tto: metaNode edges size \\n\\t \\tdo: [:i | selection _ i.\\n\\t\\t\\tancestor _ (self nodesForParent: parentNode)\\n\\t\\t\\t\\tdetect: [:child | child isAncestorOf: aNode] \\n\\t\\t\\t\\tifNone: [nil].\\n\\t\\t\\tancestor ifNotNil: [self changed: #selection. ^ ancestor]].\\n\\t^ nil! !\\n\\n\\n!OBModalFilter methodsFor: 'queries' stamp: 'cwp 2/9/2004 21:08'!\\nwantsButton\\n\\t^ true! !\\n\\n\\n!OBModalFilter methodsFor: 'selection' stamp: 'cwp 2/9/2004 21:11'!\\nincrementSelection\\n\\tselection _ selection + 1.\\n\\t(selection > metaNode edges size) ifTrue: [selection _ 1].! !\\n\\n!OBModalFilter methodsFor: 'selection' stamp: 'cwp 2/9/2004 21:11'!\\nselectedEdge\\n\\t^ metaNode edges at: self selection ! !\\nObject subclass: #OBMorphicPanelLayout\\n\\tinstanceVariableNames: 'panels'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBMorphicPanelLayout commentStamp: 'cwp 1/7/2005 23:42' prior: 0!\\nOBMorphicPanelLayout implements a somewhat hairy algorithm for layoung out panels in a morphic SystemWindow. It is the default layout strategy used by OBBrowser. Subclasses of OBBrowser may use other layout strategies to customize their appearance.!\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'initializing' stamp: 'cwp 11/21/2004 00:23'!\\nsetPanels: aCollection \\n\\tpanels := aCollection! !\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'public' stamp: 'cwp 11/21/2004 00:26'!\\naddMorphsTo: aMorph\\n\\tself addNavMorphTo: aMorph.\\n\\t(panels size > 1) ifTrue: [self addOtherMorphsTo: aMorph].\\n\\t! !\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:25'!\\naddNavMorphTo: aMorph\\n\\taMorph \\n\\t\\taddMorph: self navigationPanel buildScroller\\n\\t\\tfullFrame: (LayoutFrame fractions: (0 @ 0 extent: 1 @ self columnProportion)).\\n! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:37'!\\naddOtherMorphsTo: aMorph\\n\\t| heights variableCount fraction offset vExtent h nonNavPanels |\\n\\tnonNavPanels := panels reject: [:ea | ea isNavigation].\\n\\tnonNavPanels isEmpty ifTrue: [^ self].\\n\\theights _ nonNavPanels collect: [:ea | ea morphHeight].\\n\\tvariableCount _ heights \\n\\t\\t\\t\\t\\t\\tinject: 0 \\n\\t\\t\\t\\t\\t\\tinto: [:count :ea | ea = 0 ifTrue: [count + 1] ifFalse: [count]].\\n\\tfraction _ self columnProportion.\\n\\toffset _ 0.\\n\\tvExtent _ 1- fraction / variableCount.\\n\\tnonNavPanels with: heights do: [:panel :height | \\n\\t\\th _ height = 0 ifTrue: [vExtent] ifFalse: [0].\\n\\t\\taMorph \\n\\t\\t\\taddMorph: panel morph\\n\\t\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\t\\t\\t\\tfractions: (0@fraction extent: 1@h)\\n\\t\\t\\t\\t\\t\\t\\toffsets: (0@offset corner: 0@height)).\\n\\t\\theight = 0 \\n\\t\\t\\tifTrue: \\t[offset _ 0.\\n\\t\\t\\t\\t\\tfraction _ fraction + vExtent]\\n\\t\\t\\tifFalse: \\t[offset _ offset + height]]\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\t\\t\\t! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:26'!\\ncolumnProportion\\n\\t^ panels size = 1\\n\\t\\tifTrue: [1]\\n\\t\\tifFalse: [0.4]! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:28'!\\nnavigationPanel\\n\\t^ panels detect: [:ea | ea isNavigation]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMorphicPanelLayout class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMorphicPanelLayout class methodsFor: 'intance creation' stamp: 'cwp 11/20/2004 23:32'!\\nfor: aCollection\\n\\t^ self new setPanels: aCollection! !\\nObject subclass: #OBNode\\n\\tinstanceVariableNames: 'metaNode'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBNode commentStamp: 'cwp 3/4/2004 22:20' prior: 0!\\nA node is a wrapper for an object in the browser's domain graph. OBNode is an abstract superclass for concrete nodes which might appear in the browser.\\n\\niVars:\\n\\nmetaNode - the MetaNode which produced this node!\\n\\n\\n!OBNode methodsFor: 'accessing' stamp: 'cwp 3/3/2004 23:24'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBNode methodsFor: 'accessing' stamp: 'cwp 3/3/2004 23:24'!\\nmetaNode: aMetaNode\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 00:44'!\\nancestrySelector\\n\\t^ #isDescendantOf: ! !\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 01:47'!\\nisAncestorOf: aNode\\n\\t^ aNode perform: self ancestrySelector with: self! !\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 00:44'!\\nisDescendantOf: aNode\\n\\t^ false! !\\n\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 7/14/2006 12:37'!\\ncorrespondsWith: aNode\\n\\t^ self displayString = aNode displayString! !\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 1/31/2004 14:57'!\\nhash\\n\\t^ self name hash! !\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 1/31/2004 14:57'!\\n= other\\n\\t^ self class = other class and: [self name = other name]! !\\n\\n\\n!OBNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:36'!\\ndisplayString\\n\\t^ self perform: metaNode displaySelector! !\\n\\n!OBNode methodsFor: 'displaying' stamp: 'cwp 8/28/2004 00:14'!\\ntitle\\n\\t^ nil! !\\n\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:28'!\\nacceptDroppedNode: aNode\\n \\t^ aNode perform: self dropSelector with: self\\n! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:00'!\\nasDraggableMorph\\n\\t^(StringMorph contents: self name)\\n\\t\\tcolor: Color white;\\n\\t\\tyourself! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:29'!\\ndropSelector\\n\\t\\\"Override in subclasses\\\"\\n\\t\\n\\t^ #dropOnNode: ! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:28'!\\nwantsDroppedNode: aNode\\n\\t^ aNode respondsTo: self dropSelector! !\\n\\n\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 2/29/2004 13:49'!\\naccept: aText notifying: aController\\n\\t^ self text: aText! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 1/7/2004 09:25'!\\nactions\\n\\t^ #()! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 3/22/2004 20:48'!\\ndefinition\\n\\t^ self! !\\n\\n!OBNode methodsFor: 'public' stamp: 'dvf 8/17/2005 13:57'!\\ndisplayName\\n\\t\\\"expected to return a decorated text (rather than string) version of name\\\"\\n\\t^self name asText! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 12/10/2003 22:27'!\\nname\\n\\tself subclassResponsibility! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 12/7/2003 19:27'!\\ntext\\n\\t^ ''! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 2/29/2004 18:30'!\\ntextSelection\\n\\t^ 1 to: 0! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 3/14/2004 14:09'!\\ntext: aText\\n\\t^ false! !\\n\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 3/10/2004 00:29'!\\naction: aSelector buttonLabel: buttonString menuLabel: menuString\\n\\t^ OBAction\\n\\t\\tlabel: menuString\\n\\t\\tbuttonLabel: buttonString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 2/3/2004 22:29'!\\naction: aSelector withLabel: aString\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 16:51'!\\naction: aSelector withLabel: aString withIcon: anIcon\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 14:28'!\\naction: aSelector withLabel: aString withKeystroke: aChar\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 16:51'!\\naction: aSelector withLabel: aString withKeystroke: aChar withIcon: anIcon\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 12/5/2004 20:11'!\\naction: aSelector withMenuLabel: aString withButtonLabel: aString2 withKeystroke: aChar withIcon: anIcon \\n\\t^OBAction \\n\\t\\tlabel: aString\\n\\t\\tbuttonLabel: aString2\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 2/7/2004 21:29'!\\nreferenceForMethod: selector ofClass: className\\n\\t| classIsMeta symbol |\\n\\tclassIsMeta _ className endsWith: ' class'.\\n\\tsymbol _ classIsMeta ifTrue: [(className allButLast: 6) asSymbol] ifFalse: [className].\\n\\t^ MethodReference new \\n\\t\\tsetClassSymbol: symbol\\n\\t\\tclassIsMeta: classIsMeta\\n\\t\\tmethodSymbol: selector\\n\\t\\tstringVersion: symbol, '>>', selector! !\\n\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:18'!\\nannounce: anObject\\n\\t^ OBAnnouncer current ifNotNilDo: [:announcer | announcer announce: anObject]! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 01:06'!\\ndemandSelection\\n\\t^ OBAnnouncer current announce: (OBNodeCreated node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalChanged\\n\\tself announce: (OBNodeChanged node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalChildrenChanged\\n\\tself announce: (OBChildrenChanged node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalDeletion\\n\\tself announce: (OBNodeDeleted node: self)\\n! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 13:59'!\\nsignalSelection\\n\\t(self announce: OBAboutToChange)\\n\\t\\tisVetoed ifFalse: [self announce: (OBSelectingNode node: self)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNode class methodsFor: 'as yet unclassified' stamp: 'cwp 2/5/2004 20:25'!\\nactionsForParent: aNode\\n\\t^ #()! !\\n\\n!OBNode class methodsFor: 'as yet unclassified' stamp: 'cwp 12/18/2003 22:11'!\\nfromAssociation: anAssociationNode\\n\\t^ self on: anAssociationNode value! !\\nOBActor subclass: #OBNodeActor\\n\\tinstanceVariableNames: 'nodeClass'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Actors'!\\n!OBNodeActor commentStamp: 'cwp 3/5/2004 12:23' prior: 0!\\nFor simplicity, many actions are implemented by the nodes themselves. When the contextual menu for a node is displayed, this Actor gathers those actions and makes them available in to the user.\\n\\nIf a node class is specified, the OBNodeActor will also make available any class side actions provided by the node class. This is convenient for the user, since it makes it possible to invoke an action without first selecting a node. Many 'create' actions are implemented in this way.\\n\\niVars:\\n\\nnodeClass - if not nil, this class's class-side actions will be available to the user as well.!\\n\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 1/23/2004 23:24'!\\nactionsForNode: aNode\\n\\t^ aNode actions! !\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 3/3/2004 22:46'!\\nactionsForParent: aNode\\n\\t^ nodeClass \\n\\t\\tifNotNil: [nodeClass actionsForParent: aNode]\\n\\t\\tifNil: [#()]! !\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 3/3/2004 22:42'!\\nnodeClass: aClass\\n\\tnodeClass _ aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeActor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeActor class methodsFor: 'as yet unclassified' stamp: 'cwp 3/3/2004 22:51'!\\nonNodeClass: aClass\\n\\t^ self new nodeClass: aClass! !\\nOBAnnouncement subclass: #OBNodeChanged\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBNodeCreated\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeCreated methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 00:53'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeCreated methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 00:53'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeCreated class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeCreated class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 01:09'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBNodeDeleted\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeDeleted methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeDeleted methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeDeleted class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeDeleted class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBDefinition subclass: #OBOrganizationDefinition\\n\\tinstanceVariableNames: 'organizer'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBOrganizationDefinition commentStamp: 'cwp 1/8/2005 13:31' prior: 0!\\nOBOrganizationDefinition knows how to display and edit the organization of classes or methods by a Categorizer.!\\n\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:21'!\\norganizer: anOrganizer\\n\\torganizer _ anOrganizer! !\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:18'!\\ntext\\n\\t^ organizer asString! !\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 1/9/2005 11:45'!\\ntext: aText\\n\\torganizer changeFromString: aText asString.\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBOrganizationDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBOrganizationDefinition class methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:20'!\\non: anOrganizer\\n\\t^ self new organizer: anOrganizer! !\\nRectangleMorph subclass: #OBPane\\n\\tinstanceVariableNames: 'model list button'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPane commentStamp: 'cwp 1/7/2005 23:24' prior: 0!\\nAn OBPane is the visual representation of a column in a browser. It contains a morph to display nodes (typically a PluggableListMorph) and (optionally) a morph for communicating with the column's filter. It's main responsibility is to lay out its submorphs as the filter controls are added and removed.\\n\\niVars:\\n\\nmodel\\t- the OBColumn that controls the node list displayed in this pane\\nlist\\t\\t- the morph which displays the node list, usually a PluggableListMorph\\nbutton\\t- the morph which controls the column's filter, usually an OBRadioButtonBar.!\\n\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/2/2004 00:57'!\\nbuttonHeight\\n\\t^ self hasButton\\n\\t\\tifTrue: [button height]\\n\\t\\tifFalse: [self defaultButtonHeight]\\n! !\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/2/2004 01:10'!\\ndefaultButtonHeight\\n\\t^ 23! !\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:19'!\\nnoteNewOwner: aMorph\\n\\tself containingWindow ifNotNilDo: [:window | self adoptPaneColor: window paneColor]! !\\n\\n\\n!OBPane methodsFor: 'geometry' stamp: 'cwp 2/12/2004 18:32'!\\nbounds: aRectangle\\n\\tsuper bounds: aRectangle.\\n\\tself adjustList.\\n\\tself adjustButton.! !\\n\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 18:26'!\\ninitGeometry\\n\\tself\\t\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tcellInset: 0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new.\\n\\t\\t\\n\\tself addMorph: list.\\n\\tlist bounds: self innerBounds.\\n\\t\\t! !\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 18:44'!\\nmodel: anObject\\n\\t\\\"Set my model and make me me a dependent of the given object.\\\"\\n\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel _ anObject.\\n! !\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 19:17'!\\nsetColumn: aColumn filter: aFilter\\n\\tself model: aColumn.\\n\\tlist _ aColumn listMorph.\\n\\tself initGeometry.\\n\\taFilter ifNotNil: [self addButton: aFilter buttonMorph].! !\\n\\n\\n!OBPane methodsFor: 'testing' stamp: 'cwp 2/12/2004 18:35'!\\nhasButton\\n\\t^ button notNil! !\\n\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 11/2/2004 00:53'!\\naddButton: aButton\\n\\tself hasButton ifTrue: [self removeMorph: button].\\n\\tbutton _ aButton.\\n\\tbutton height: self defaultButtonHeight.\\n\\tself \\n\\t\\taddMorph: button;\\n\\t\\tadjustList;\\n\\t\\tadjustButton! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 11/2/2004 00:50'!\\nadjustButton\\n\\t| inner |\\n\\tself hasButton ifTrue: \\n\\t\\t[inner _ self innerBounds.\\n\\t\\tbutton bounds: (inner withTop: inner bottom - self buttonHeight)]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 18:35'!\\nadjustList\\n\\tself hasButton\\n\\t\\t\\tifFalse: [list bounds: self innerBounds]\\n\\t\\t\\tifTrue: [list bounds: (self innerBounds withHeight: (self height - self buttonHeight))]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 20:29'!\\nremoveButton\\n\\tself hasButton \\n\\t\\tifTrue: [self removeMorph: button.\\n\\t\\t\\t\\tbutton _ nil.\\n\\t\\t\\t\\tself adjustList]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 20:23'!\\nupdate: aSelector\\n\\taSelector = #filter ifFalse: [^ self].\\n\\t(model wantsButton)\\n\\t\\t\\tifTrue: [self addButton: model filter buttonMorph]\\n\\t\\t\\tifFalse: [self removeButton]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPane class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPane class methodsFor: 'instance creation' stamp: 'cwp 2/12/2004 18:11'!\\nforColumn: aColumn\\n\\t^ self forColumn: aColumn withFilter: nil! !\\n\\n!OBPane class methodsFor: 'instance creation' stamp: 'cwp 2/12/2004 18:12'!\\nforColumn: aColumn withFilter: aFilter\\n\\t^ self new setColumn: aColumn filter: aFilter! !\\nRectangleMorph subclass: #OBPaneScroller\\n\\tinstanceVariableNames: 'model sizing panes transform scrollBar'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPaneScroller commentStamp: 'cwp 3/5/2004 12:13' prior: 0!\\nInstances of OBPaneScroller contain the panes which represent columns in a browser. Their primary responsibilities are laying out panes to fit the space available and scrolling them horizontally when there isn't sufficient space. \\n\\niVars:\\n\\nsizing\\t\\t- The number of panes which should exactly fit the available space.\\n\\t\\t \\t During layout, the width of the panes is determined accordingly.\\ntransform\\t- A TransformMorph used for scrolling\\nscrollBar\\t- An OBHorizontalScrollBar used for scrolling!\\n\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 22:03'!\\nmodel\\n\\t^model! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 22:11'!\\nmodel: anObject\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel := anObject! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 23:09'!\\npanes\\n\\t^ panes ifNil: [self updatePanes. panes]! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/22/2004 23:19'!\\nsizing\\n\\t^ sizing ifNil: [self updateSizing]! !\\n\\n\\n!OBPaneScroller methodsFor: 'defaults' stamp: 'cwp 8/24/2003 15:13'!\\nseparatorWidth\\n\\t^ 4! !\\n\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 11/23/2004 01:28'!\\ninitialize\\n\\tsuper initialize.\\n\\tself \\n\\t\\tcolor: Color red;\\n\\t\\tborderWidth: 0;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\thResizing: #spaceFill.\\n\\tself \\n\\t\\tinitializeTransform;\\n\\t\\tinitializeScrollbar.\\n\\tself startStepping.! !\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 2/8/2004 11:01'!\\ninitializeScrollbar\\n\\tscrollBar _ OBScrollBar new model: self slotName: 'scrollBar'.\\n\\tscrollBar \\n\\t\\tborderWidth: 0;\\n\\t\\tborderColor: #inset;\\n\\t\\theight: self scrollBarHeight.\\n\\tself resizeScrollBar.\\n! !\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 2/8/2004 10:52'!\\ninitializeTransform\\n\\ttransform _ TransformMorph new.\\n\\ttransform\\n\\t\\tcolor: Color transparent;\\n\\t\\tborderWidth: 0;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tdisableTableLayout;\\n\\t\\tbounds: super innerBounds.\\n\\tself addMorphBack: transform.\\n! !\\n\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:10'!\\nadjustPaneHeight\\n\\t\\\"This gets called after the scrollbar has been shown or hidden, to move the bottom\\n\\tof the panes to the right place.\\\"\\n\\t\\n\\ttransform bounds: self innerBounds.\\n\\ttransform submorphsDo: [:m | m bounds: (m bounds withHeight: self paneHeight)]\\n\\t\\t! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 11/21/2004 23:45'!\\nbounds: aRectangle\\n\\tsuper bounds: aRectangle.\\n\\tself layoutWidgets.\\n\\tself layoutPanes.\\n\\tself setScrollDeltas.\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/26/2004 23:14'!\\ncomputeMorphWidths\\n\\t| paneWidths widths |\\n\\tpaneWidths _ self paneWidthsToFit: self totalPaneWidth.\\n\\twidths _ OrderedCollection new.\\n\\tpaneWidths do: [:w | widths add: w] separatedBy: [widths add: self separatorWidth].\\n\\t^ widths asArray\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:06'!\\ndoLayout\\n\\tself layoutWidgets.\\n\\tself layoutPanes.\\n\\tself hideOrShowScrollBar.\\n\\tself setScrollDeltas.\\n\\tself scrollToRight.! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 10:54'!\\ninnerBounds\\n\\t| rect |\\n\\trect _ super innerBounds.\\n\\t^ self scrollBarIsVisible\\n\\t\\tifTrue: [rect withHeight: rect height - self scrollBarHeight - 1]\\n\\t\\tifFalse: [rect]! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 01:22'!\\nlayoutPanes\\n\\t| widths rect |\\n\\twidths _ self computeMorphWidths.\\n\\trect _ 0@0 extent: (0 @ self paneHeight).\\n\\ttransform submorphs \\n\\t\\t\\t\\t\\twith: widths \\n\\t\\t\\t\\t\\tdo: [:m :w | \\n\\t\\t\\t\\t\\t\\trect _ rect withWidth: w.\\n\\t\\t\\t\\t\\t\\tm bounds: rect.\\n\\t\\t\\t\\t\\t\\trect _ rect translateBy: (w@0)]\\n\\t\\t\\t\\t\\t\\t\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 8/25/2003 22:13'!\\nlayoutWidgets\\n\\t| inner outer |\\n\\touter _ super innerBounds.\\n\\tinner _ self innerBounds.\\n\\ttransform bounds: inner.\\n\\tscrollBar bounds: ((inner left @ inner bottom + 1)\\n\\t\\t\\t\\t\\t\\tcorner: outer bottomRight)! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 11/17/2004 23:09'!\\npaneCount\\n\\t^ self panes size! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 12/6/2003 17:08'!\\npaneHeight\\n\\t^ transform bounds height! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/26/2004 23:14'!\\npaneWidthsToFit: limit\\n\\t| padded |\\n\\tpadded _ Array new: self paneCount.\\n\\tpadded atAllPut: (limit / self sizing) floor.\\n\\t(1 to: limit - padded sum) do: [:i | padded at: i put: (padded at: i) + 1].\\n\\t^ padded\\n\\t\\n\\t! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:03'!\\nresizeScrollBar\\n\\t| inner outer |\\n\\touter _ super innerBounds.\\n\\tinner _ outer withHeight: outer height - self scrollBarHeight - 1.\\n\\tscrollBar bounds: ((inner left @ inner bottom + 1)\\n\\t\\t\\t\\t\\t\\tcorner: outer bottomRight)! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 8/24/2003 14:29'!\\nscrollBarHeight\\n\\t^ 12! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/25/2004 20:23'!\\ntotalPaneWidth\\n\\t^ self innerBounds width - ((self sizing - 1) * self separatorWidth)! !\\n\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 12/6/2003 17:06'!\\nclearPanes\\n\\ttransform removeAllMorphs! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/23/2004 01:22'!\\npopPanes: count\\n\\tcount * 2 timesRepeat: [transform removeMorph: transform lastSubmorph].\\n\\tpanes removeLast: count! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/17/2004 22:46'!\\npushPane: aMorph\\n\\taMorph \\n\\t\\tborderWidth: 0;\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #rigid;\\n\\t\\tlayoutInset: 0.\\n\\ttransform hasSubmorphs ifTrue: [transform addMorphBack: self separator].\\n\\ttransform addMorphBack: aMorph.\\n! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/27/2004 01:03'!\\nseparator\\n\\t^ BorderedSubpaneDividerMorph vertical \\n\\t\\tborderWidth: self separatorWidth / 2;\\n\\t\\tcolor: model defaultBackgroundColor duller;\\n\\t\\tborderRaised.! !\\n\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:44'!\\nhideOrShowScrollBar\\n\\tself isScrollable ifTrue: [self showScrollBar] ifFalse: [self hideScrollBar]! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 11:10'!\\nhideScrollBar\\n\\tself removeMorph: scrollBar.\\n\\tself adjustPaneHeight.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:42'!\\nisScrollable\\n\\t^ self leftoverScrollRange > 0! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 21:04'!\\nleftoverScrollRange\\n\\t^ (self totalScrollRange - self innerBounds width roundTo: self scrollDeltaWidth) max: 0\\n! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:56'!\\nscrollBarIsVisible\\n\\t^ submorphs includes: scrollBar! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/23/2003 16:21'!\\nscrollDeltaWidth\\n\\t^ 1! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 12/8/2003 21:42'!\\nscrollToRight\\n\\t^ scrollBar setValue: 1.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 21:14'!\\nsetScrollDeltas\\n\\t| range interval value |\\n\\ttransform hasSubmorphs ifFalse: [scrollBar interval: 1.0. ^ self].\\n\\trange _ self leftoverScrollRange.\\n\\trange = 0 ifTrue: [^ scrollBar interval: 1.0; setValue: 0].\\n\\tinterval _ ((self innerBounds width) / self totalScrollRange) asFloat.\\n\\tvalue _ (transform offset x / range min: 1.0) asFloat.\\n\\tscrollBar interval: interval.\\n\\tscrollBar setValue: value.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 11:11'!\\nshowScrollBar\\n\\tself scrollBarIsVisible ifTrue: [^ self].\\n\\tself resizeScrollBar.\\n\\tself addMorphFront: scrollBar.\\n\\tself adjustPaneHeight.\\n\\t! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 19:27'!\\ntotalScrollRange\\n\\t| submorphBounds |\\n\\tsubmorphBounds := transform localSubmorphBounds ifNil: [^ 0].\\n\\t^ submorphBounds width\\n! !\\n\\n\\n!OBPaneScroller methodsFor: 'stepping' stamp: 'cwp 11/21/2004 15:38'!\\nstep\\n\\tself reclaimPanes! !\\n\\n!OBPaneScroller methodsFor: 'stepping' stamp: 'cwp 11/24/2004 22:29'!\\nstepTime\\n\\t^ 250! !\\n\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:23'!\\nreclaimPanes\\n\\t| reclaimed |\\n\\treclaimed := model reclaimPanes.\\n\\treclaimed isZero\\tifFalse: \\n\\t\\t[self \\n\\t\\t \\tpopPanes: reclaimed;\\n\\t\\t\\tbasicUpdateSizing;\\n\\t\\t\\tlayoutPanes;\\n\\t\\t\\thideOrShowScrollBar;\\n\\t\\t\\tsetScrollDeltas]! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/21/2004 13:51'!\\nscrollBarValue: value\\n\\ttransform hasSubmorphs ifFalse: [^ self].\\n\\ttransform offset: (self leftoverScrollRange * value) rounded @ 0.! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:34'!\\nupdatePanes\\n\\t| count |\\n\\tmodel ifNil: [panes := Array new. ^ self].\\n\\tcount := panes ifNotNil: [panes size] ifNil: [0].\\n\\tself basicUpdatePanes.\\n\\tself basicUpdateSizing.\\t\\n\\tself layoutPanes.\\n\\tpanes size = count\\n\\t\\tifFalse: [self hideOrShowScrollBar.\\n\\t\\t\\t\\tself setScrollDeltas].\\n\\tpanes size > count ifTrue: [self scrollToRight].\\n\\t^ panes! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:14'!\\nupdateSizing\\n\\t| old |\\n\\told := sizing.\\n\\tself basicUpdateSizing.\\n\\tsizing = old ifFalse: [self layoutPanes].\\n\\t^sizing! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/17/2004 22:40'!\\nupdate: aSymbol\\n\\taSymbol = #sizing ifTrue: [^ self updateSizing].\\n\\taSymbol = #panes ifTrue: [^ self updatePanes].! !\\n\\n\\n!OBPaneScroller methodsFor: 'private' stamp: 'cwp 11/23/2004 01:31'!\\nbasicUpdatePanes\\n\\tpanes := model ifNotNil: [model panes] ifNil: [Array new].\\t\\t\\n\\tself clearPanes.\\n\\tpanes do: [:ea | self pushPane: ea].\\n! !\\n\\n!OBPaneScroller methodsFor: 'private' stamp: 'cwp 11/23/2004 01:14'!\\nbasicUpdateSizing\\n\\tmodel ifNil: [sizing := 1] ifNotNil: [sizing := model sizing]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPaneScroller class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPaneScroller class methodsFor: 'as yet unclassified' stamp: 'cwp 11/17/2004 22:01'!\\nwithModel: aModel\\n\\t^ self new model: aModel! !\\nObject subclass: #OBPanel\\n\\tinstanceVariableNames: 'browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBPanel commentStamp: 'cwp 1/7/2005 23:23' prior: 0!\\nA panel is an object that manages part of the browser's window. It provides a protocol for receiving notifications when the current domain node changes, and reacts to these changes.!\\n\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:52'!\\nannouncer\\n\\t^ browser announcer! !\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:58'!\\nbrowser\\n\\t^ browser! !\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 4/17/2006 22:17'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser.\\n\\tself subscribe! !\\n\\n\\n!OBPanel methodsFor: 'testing' stamp: 'cwp 11/20/2004 21:09'!\\nisNavigation\\n\\t^ false! !\\n\\n\\n!OBPanel methodsFor: 'updating' stamp: 'cwp 4/17/2006 19:36'!\\nsubscribe! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPanel class methodsFor: 'instance creation' stamp: 'cwp 8/31/2004 10:46'!\\ninBrowser: aBrowser\\n\\t^ self new browser: aBrowser! !\\nPluggableTextMorph subclass: #OBPluggableTextMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPluggableTextMorph commentStamp: 'cwp 12/7/2004 00:04' prior: 0!\\nThis is a trivial subclass of PluggableTextMorph. It overrides initialization methods to use an OBTextMorph rather than a regular TextMorph!\\n\\n\\n!OBPluggableTextMorph methodsFor: 'event handling' stamp: 'cwp 10/30/2004 23:07'!\\nkeyStroke: evt\\n\\t^ textMorph keyStroke: evt! !\\n\\n\\n!OBPluggableTextMorph methodsFor: 'model access' stamp: 'cwp 10/30/2004 22:57'!\\nsetText: aText\\n\\tscrollBar setValue: 0.0.\\n\\ttextMorph\\n\\t\\tifNil: [textMorph _ OBTextMorph new\\n\\t\\t\\t\\t\\t\\tcontents: aText wrappedTo: self innerBounds width-6.\\n\\t\\t\\t\\ttextMorph setEditView: self.\\n\\t\\t\\t\\tscroller addMorph: textMorph]\\n\\t\\tifNotNil: [textMorph newContents: aText].\\n\\tself hasUnacceptedEdits: false.\\n\\tself setScrollDeltas.! !\\nRectangleMorph subclass: #OBRadioButtonBar\\n\\tinstanceVariableNames: 'model buttons selection getListSelector getSelectionSelector setSelectionSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBRadioButtonBar commentStamp: 'cwp 1/7/2005 23:27' prior: 0!\\nAn OBRadioButtonBar is similar to a PluggableListMorph except that it displays a row of buttons rather than a vertical list. Clicking on a button selects it.\\n\\nmodel\\t\\t\\t\\t- the model for this button bar\\nbuttons\\t\\t\\t- a collection of OBButtonModels, which are derived from the model's list\\nselection\\t\\t\\t- the index of the currently selected button\\ngetListSelector\\t \\t- the message for getting the list of labels for the buttons\\ngetSelectionSelector\\t- the message for getting the index of the currently selected item\\nsetSelectionSelector\\t- the message for informing the model that a button has been clicked!\\n\\n\\n!OBRadioButtonBar methodsFor: 'accessing' stamp: 'cwp 11/27/2004 02:09'!\\nlist\\n\\tbuttons ifNil: \\n\\t\\t\\t[| labels |\\n\\t\\t\\tlabels := model perform: getListSelector.\\n\\t\\t\\tbuttons := Array new: labels size.\\n\\t\\t\\tlabels withIndexDo: \\n\\t\\t\\t\\t\\t[:label :index | \\n\\t\\t\\t\\t\\tbuttons at: index put: (OBButtonModel withLabel: label inBar: self)].\\n\\t\\t\\tselection := self getSelectionIndex.\\n\\t\\t\\tself].\\n\\t^buttons collect: [:b | b label]! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:18'!\\nisEnabled: aButton\\n\\t^ true! !\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:54'!\\nisSelected: aButton\\n\\t^ (buttons at: selection ifAbsent: [^ false]) == aButton! !\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:47'!\\npush: aButton\\n\\t| index |\\n\\tindex _ buttons indexOf: aButton.\\n\\tmodel perform: setSelectionSelector with: index.! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'constructing' stamp: 'cwp 11/27/2004 20:58'!\\nadoptPaneColor: aColor\\n\\tself submorphs do: [:ea | ea onColor: aColor darker offColor: aColor lighter]! !\\n\\n!OBRadioButtonBar methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:02'!\\nnoteNewOwner: aMorph\\n\\t| window |\\n\\twindow := aMorph containingWindow.\\n\\twindow ifNotNil: [self adoptPaneColor: window paneColor]! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'lr 3/23/2006 18:10'!\\ninitGeometry\\n\\tself\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\trubberBandCells: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 2\\n! !\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'cwp 2/22/2004 16:51'!\\nmodel: aModel\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tmodel _ aModel.\\n\\tmodel addDependent: self.! !\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'cwp 2/25/2004 00:36'!\\non: aModel list: listSelector selected: selectionGetter changeSelected: selectionSetter \\n\\tself model: aModel.\\n\\tselection _ 0.\\n\\tgetListSelector _ listSelector.\\n\\tgetSelectionSelector _ selectionGetter.\\n\\tsetSelectionSelector _ selectionSetter.\\n\\tself initGeometry.\\n\\tself updateList.! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 18:53'!\\ngetSelectionIndex\\n\\t^ model perform: getSelectionSelector! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/27/2004 17:58'!\\nupdateButtons\\n\\t| labels |\\n\\tlabels := model perform: getListSelector.\\n\\tbuttons := Array new: labels size.\\n\\tlabels withIndexDo: \\n\\t\\t\\t[:label :index | \\n\\t\\t\\tbuttons at: index put: (OBButtonModel withLabel: label inBar: self)].\\n\\tselection := self getSelectionIndex! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/27/2004 17:58'!\\nupdateList\\n\\tself \\n\\t\\tupdateButtons; \\n\\t\\tupdateMorphs! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/2/2004 01:09'!\\nupdateMorphs\\n\\tself removeAllMorphs.\\n\\tbuttons do: [:button | self addMorphBack: button morph].\\n\\tself bounds: (self bounds withHeight: submorphs first height)! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:39'!\\nupdateSelection\\n\\t| oldSelection |\\n\\toldSelection _ selection.\\n\\tselection _ self getSelectionIndex.\\n\\tself withButtonAt: oldSelection do: [:button | button selectionChanged].\\n\\tself withSelectedButtonDo: [:button | button selectionChanged]! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/25/2004 00:35'!\\nupdate: aSymbol\\n\\taSymbol = getListSelector ifTrue: [self updateList. ^ self].\\n\\taSymbol = getSelectionSelector ifTrue: [self updateSelection]! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:38'!\\nwithButtonAt: index do: aBlock\\n\\t^ (buttons at: index ifAbsent: [nil]) ifNotNilDo: aBlock! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:38'!\\nwithSelectedButtonDo: aBlock\\n\\t^ self withButtonAt: selection do: aBlock! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBRadioButtonBar class\\n\\tinstanceVariableNames: ''!\\n\\n!OBRadioButtonBar class methodsFor: 'as yet unclassified' stamp: 'cwp 2/22/2004 16:44'!\\non: aModel list: listSelector selected: selectionSelector changeSelected: changedSelector \\n\\t^ self new\\n\\t\\t\\ton: aModel\\n\\t\\t\\tlist: listSelector\\n\\t\\t\\tselected: selectionSelector\\n\\t\\t\\tchangeSelected: changedSelector! !\\nOBListBrowser subclass: #OBReferencesBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBReferencesBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBReferencesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:22'!\\ndefaultMetaNode\\n\\t| class method |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tmethod := OBMetaNode named: 'References'.\\n\\t\\n\\tclass\\n\\t\\tchildAt: #users put: method;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\t\\t\\n\\t^ class! !\\n\\n!OBReferencesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:34'!\\ntitle\\n\\t^ 'References to'! !\\nOBAnnouncement subclass: #OBRefreshRequired\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\nObject subclass: #OBRequestor\\n\\tinstanceVariableNames: 'node browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/29/2006 00:12'!\\nannounce: anObject\\n\\t^ browser announcer announce: anObject! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:41'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:43'!\\ndoesNotUnderstand: aMessage\\n\\t^ aMessage sendTo: browser! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:43'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:38'!\\nrequestNode\\n\\t^ node! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/29/2006 00:12'!\\nselect: aNode\\n\\t(self announce: OBAboutToChange)\\n\\t\\tisVetoed ifFalse: [self announce: (OBSelectingNode node: aNode)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBRequestor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBRequestor class methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:40'!\\nfor: aBrowser\\n\\t^ self new browser: aBrowser! !\\nSlider subclass: #OBScrollBar\\n\\tinstanceVariableNames: 'upButton downButton pagingArea scrollDelta pageDelta interval menuSelector timeOfMouseDown timeOfLastScroll nextPageDirection currentScrollDelay'\\n\\tclassVariableNames: 'CachedImages UpArrow UpArrow8Bit'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBScrollBar commentStamp: 'cwp 3/5/2004 12:01' prior: 0!\\nThis class is a relic. It was originally created to work around bugs in ScrollBar which prevented it from working correctly in horizontal orientation. At some point the bugs should be fixed, and ScrollBar should be used instead.!\\n\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\ninterval: d\\n\\t\\\"Supply an optional floating fraction so slider can expand to indicate range\\\"\\n\\tinterval _ d min: 1.0.\\n\\tself expandSlider.\\n\\tself computeSlider.! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\npagingArea\\n\\t^pagingArea! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 21:25'!\\nroundedScrollbarLook\\n\\t\\\"Rounded look currently only shows up in flop-out mode\\\"\\n\\t^false and: [self class alwaysShowFlatScrollbarForAlternativeLook not]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDelta\\n\\t^ scrollDelta! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDelta: d1 pageDelta: d2\\n\\t\\\"Supply optional increments for better scrolling of, eg, text\\\"\\n\\tscrollDelta _ d1.\\n\\tpageDelta _ d2.! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 16:26'!\\nsliderColor: aColor\\n\\t\\\"Change the color of the scrollbar to go with aColor.\\\"\\n\\t| buttonColor |\\n\\tsuper sliderColor: aColor.\\n\\tbuttonColor _ self thumbColor.\\n\\tupButton color: buttonColor.\\n\\tdownButton color: buttonColor.\\n\\tslider color: buttonColor.\\n\\tself roundedScrollbarLook\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[self color: Color transparent.\\n\\t\\t\\t\\tpagingArea color: aColor muchLighter.\\n\\t\\t\\t\\tself borderStyle style == #simple \\n\\t\\t\\t\\t\\tifTrue:[self borderColor: aColor darker darker]\\n\\t\\t\\t\\t\\tifFalse:[self borderStyle baseColor: aColor]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[pagingArea color: (aColor alphaMixed: 0.3 with: Color white).\\n\\t\\t\\t\\tself borderWidth: 0]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nsliderShadowColor\\n\\t^ self roundedScrollbarLook\\n\\t\\tifTrue: [self sliderColor darker]\\n\\t\\tifFalse: [super sliderShadowColor]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 16:27'!\\nthumbColor\\n\\t\\\"Problem: Part of the ScrollBar/Slider code uses 'slider' to mean the entire scrollbar/slider widget, and part of it uses 'slider' to mean only the draggable 'thumb'. This should be cleaned up so that 'thumb' is used instead of 'slider' where appropriate. For now, the meaning of thumbColor is clear, at least.\\\"\\n\\n\\t^self sliderColor alphaMixed: 0.7 with: (Color gray: 0.95).! !\\n\\n\\n!OBScrollBar methodsFor: 'accessing' stamp: 'md 2/24/2006 16:12'!\\nadoptPaneColor: aColor\\n\\t\\\"Adopt the given pane color\\\"\\n\\taColor ifNil:[^self].\\n\\tself sliderColor: aColor.! !\\n\\n!OBScrollBar methodsFor: 'accessing' stamp: 'cwp 11/23/2003 18:06'!\\ncachedImageAt: aKey ifAbsentPut: aBlock\\n\\n\\tCachedImages ifNil: [CachedImages _ Dictionary new].\\n\\t^CachedImages at: aKey ifAbsentPut: aBlock! !\\n\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nbuttonExtent\\n\\t^ bounds isWide\\n\\t\\tifTrue: [11 @ self innerBounds height]\\n\\t\\tifFalse: [self innerBounds width @ 11]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nexpandSlider\\n\\t\\\"Compute the new size of the slider (use the old sliderThickness as a minimum).\\\"\\n\\t| r |\\n\\tr _ self totalSliderArea.\\n\\tslider extent: (bounds isWide\\n\\t\\tifTrue: [((r width * interval) asInteger max: self sliderThickness) @ slider height]\\n\\t\\tifFalse: [slider width @ ((r height * interval) asInteger max: self sliderThickness)])! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nextent: p\\n p x > p y\\n ifTrue: [super extent: (p max: 42@8)]\\n ifFalse: [super extent: (p max: 8@42)]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nsliderExtent\\n\\t\\\"The sliderExtent is now stored in the slider itself, not hardcoded as it is in the superclass.\\\"\\n\\t^slider extent! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:07'!\\nsliderThickness\\n\\t^ self roundedScrollbarLook ifTrue:[15] ifFalse:[super sliderThickness]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:07'!\\ntotalSliderArea\\n\\t| upperBoundsButton |\\n\\tupperBoundsButton _ upButton.\\n\\tupButton bottom > upperBoundsButton bottom\\n\\t\\tifTrue: [upperBoundsButton _ upButton].\\n\\t^ bounds isWide\\n\\t\\tifTrue: [upperBoundsButton bounds topRight corner: downButton bounds bottomLeft]\\n\\t\\tifFalse: [upperBoundsButton bounds bottomLeft corner: downButton bounds topRight].\\n! !\\n\\n\\n!OBScrollBar methodsFor: 'initialization' stamp: 'cwp 11/23/2003 18:07'!\\ninitialize\\n\\tsuper initialize.\\n\\tscrollDelta _ 0.02.\\n\\tpageDelta _ 0.2.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tself borderStyle: ((BorderStyle complexFramed width: 2) \\\"baseColor: Color gray\\\")].! !\\n\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeDownButton\\n\\tdownButton := RectangleMorph\\n\\t\\tnewBounds: (self innerBounds bottomRight - self buttonExtent extent: self buttonExtent)\\n\\t\\tcolor: self thumbColor.\\n\\tdownButton on: #mouseDown send: #scrollDownInit to: self.\\n\\tdownButton on: #mouseUp send: #finishedScrolling to: self.\\n\\tdownButton addMorphCentered: (ImageMorph new image: \\n\\t\\t(self \\n\\t\\t\\tcachedImageAt: (bounds isWide ifTrue: ['right'] ifFalse: ['down']) \\n\\t\\t\\tifAbsentPut: [\\n\\t\\t\\t\\tself upArrow8Bit\\n\\t\\t\\t\\t\\trotateBy: (bounds isWide ifTrue: [#right] ifFalse: [#pi])\\n\\t\\t\\t\\t\\tcenterAt: 0@0\\n\\t\\t\\t]\\n\\t\\t)\\n\\t).\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tdownButton color: Color veryLightGray.\\n\\t\\tdownButton borderStyle: (BorderStyle complexRaised width: 3).\\n\\t] ifFalse:[\\n\\t\\tdownButton setBorderWidth: 1 borderColor: #raised.\\n\\t].\\n\\tself addMorph: downButton.\\n! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeEmbedded: aBool\\n\\t\\\"aBool == true => inboard scrollbar\\n\\taBool == false => flop-out scrollbar\\\"\\n\\tself roundedScrollbarLook ifFalse:[^self].\\n\\taBool ifTrue:[\\n\\t\\tself borderStyle: (BorderStyle inset width: 2).\\n\\t\\tself cornerStyle: #square.\\n\\t] ifFalse:[\\n\\t\\tself borderStyle: (BorderStyle width: 1 color: Color black).\\n\\t\\tself cornerStyle: #rounded.\\n\\t].\\n\\tself removeAllMorphs.\\n\\tself initializeSlider.! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializePagingArea\\n\\tpagingArea := RectangleMorph newBounds: self totalSliderArea\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: (Color r: 0.6 g: 0.6 b: 0.8).\\n\\tpagingArea borderWidth: 0.\\n\\tpagingArea on: #mouseDown send: #scrollPageInit: to: self.\\n\\tpagingArea on: #mouseUp send: #finishedScrolling to: self.\\n\\tself addMorph: pagingArea.\\n\\tself roundedScrollbarLook \\n\\t\\tifTrue:[pagingArea color: (Color gray: 0.9)].! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeSlider\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tself \\n\\t\\t\\tinitializeUpButton;\\n\\t\\t\\tinitializeDownButton;\\n\\t\\t\\tinitializePagingArea.\\n\\t] ifFalse:[\\n\\t\\tself initializeUpButton; \\n\\t\\t\\tinitializeDownButton; \\n\\t\\t\\tinitializePagingArea.\\n\\t].\\n\\tsuper initializeSlider.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tslider cornerStyle: #rounded.\\n\\t\\tslider borderStyle: (BorderStyle complexRaised width: 3).\\n\\t\\tsliderShadow cornerStyle: #rounded.\\n\\t].\\n\\tself sliderColor: self sliderColor.! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeUpButton\\n\\tupButton := self roundedScrollbarLook \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[RectangleMorph \\n\\t\\t\\t\\t\\t\\tnewBounds: (self innerBounds topLeft extent: self buttonExtent)]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[RectangleMorph \\n\\t\\t\\t\\t\\t\\tnewBounds: ((self innerBounds topLeft) extent: self buttonExtent)].\\n\\tupButton color: self thumbColor.\\n\\tupButton \\n\\t\\ton: #mouseDown\\n\\t\\tsend: #scrollUpInit\\n\\t\\tto: self.\\n\\tupButton \\n\\t\\ton: #mouseUp\\n\\t\\tsend: #finishedScrolling\\n\\t\\tto: self.\\n\\tupButton \\n\\t\\taddMorphCentered: (ImageMorph new image: (self \\n\\t\\t\\t\\t\\t\\tcachedImageAt: (bounds isWide ifTrue: ['left'] ifFalse: ['up'])\\n\\t\\t\\t\\t\\t\\tifAbsentPut: \\n\\t\\t\\t\\t\\t\\t\\t[bounds isWide \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [self upArrow8Bit rotateBy: #left centerAt: 0 @ 0]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [self upArrow8Bit]])).\\n\\tself roundedScrollbarLook \\n\\t\\tifTrue: \\n\\t\\t\\t[upButton color: Color veryLightGray.\\n\\t\\t\\tupButton borderStyle: (BorderStyle complexRaised width: 3)]\\n\\t\\tifFalse: [upButton setBorderWidth: 1 borderColor: #raised].\\n\\tself addMorph: upButton! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\nupArrow8Bit\\n\\n\\t\\\"convert to 8-bit and convert white to transparent to avoid gratuitous conversion every time we put one in an ImageMorph\\\"\\n\\n\\t^UpArrow8Bit ifNil: [\\n\\t\\tUpArrow8Bit _ (ColorForm mappingWhiteToTransparentFrom: UpArrow) asFormOfDepth: 8\\n\\t]! !\\n\\n\\n!OBScrollBar methodsFor: 'model access' stamp: 'cwp 11/23/2003 18:06'!\\nsetValue: newValue\\n\\t\\\"Using roundTo: instead of truncateTo: ensures that scrollUp will scroll the same distance as scrollDown.\\\"\\n\\t^ super setValue: (newValue roundTo: scrollDelta)! !\\n\\n\\n!OBScrollBar methodsFor: 'other events' stamp: 'cwp 11/23/2003 18:06'!\\nmenuButtonMouseDown: event\\n\\tevent hand showTemporaryCursor: nil.\\n\\tself use: menuSelector orMakeModelSelectorFor: 'MenuButtonPressed:'\\n\\t\\tin: [:sel | menuSelector _ sel. model perform: sel with: event]! !\\n\\n!OBScrollBar methodsFor: 'other events' stamp: 'cwp 11/23/2003 18:06'!\\nmouseDownInSlider: event\\n\\tinterval = 1.0 ifTrue:\\n\\t\\t[\\\"make the entire scrollable area visible if a full scrollbar is clicked on\\\"\\n\\t\\tself setValue: 0.\\n\\t\\tself model hideOrShowScrollBar].\\n\\tsuper mouseDownInSlider: event! !\\n\\n\\n!OBScrollBar methodsFor: 'scroll timing' stamp: 'cwp 11/23/2003 18:07'!\\nresetTimer\\n\\ttimeOfMouseDown _ Time millisecondClockValue.\\n\\ttimeOfLastScroll _ timeOfMouseDown - 1000 max: 0.\\n\\tnextPageDirection _ nil.\\n\\tcurrentScrollDelay _ nil! !\\n\\n!OBScrollBar methodsFor: 'scroll timing' stamp: 'cwp 11/23/2003 18:07'!\\nwaitForDelay1: delay1 delay2: delay2 \\n\\t\\\"Return true if an appropriate delay has passed since the last scroll operation.\\n\\tThe delay decreases exponentially from delay1 to delay2.\\\"\\n\\n\\t| now scrollDelay |\\n\\ttimeOfLastScroll isNil ifTrue: [self resetTimer].\\t\\\"Only needed for old instances\\\"\\n\\tnow := Time millisecondClockValue.\\n\\t(scrollDelay := currentScrollDelay) isNil \\n\\t\\tifTrue: [scrollDelay := delay1\\t\\\"initial delay\\\"].\\n\\tcurrentScrollDelay := scrollDelay * 9 // 10 max: delay2.\\t\\\"decrease the delay\\\"\\n\\ttimeOfLastScroll := now.\\n\\t^true! !\\n\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollByPage\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 300 delay2: 100) ifFalse: [^ self].\\n\\tnextPageDirection\\n\\t\\tifTrue: [self setValue: (value + pageDelta min: 1.0)]\\n\\t\\tifFalse: [self setValue: (value - pageDelta max: 0.0)]\\n! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollDown\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 200 delay2: 40) ifFalse: [^ self].\\n\\tself setValue: (value + scrollDelta + 0.000001 min: 1.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollUp\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 200 delay2: 40) ifFalse: [^ self].\\n\\tself setValue: (value - scrollDelta - 0.000001 max: 0.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nfinishedScrolling\\n\\tself stopStepping.\\n\\tself scrollBarAction: nil.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tupButton borderStyle: (BorderStyle complexRaised width: upButton borderWidth).\\n\\t\\tdownButton borderStyle: (BorderStyle complexRaised width: downButton borderWidth).\\n\\t] ifFalse:[\\n\\t\\tdownButton borderRaised.\\n\\t\\tupButton borderRaised.\\n\\t].\\n\\n! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollBarAction\\n\\t^self valueOfProperty: #scrollBarAction! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollBarAction: aSymbol\\n\\tself setProperty: #scrollBarAction toValue: aSymbol! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDown\\n\\tself flag: #obsolete.\\n\\tdownButton eventHandler: nil.\\n\\tdownButton on: #mouseDown send: #scrollDownInit to: self.\\n\\tdownButton on: #mouseUp send: #finishedScrolling to: self.\\n\\t^self scrollDownInit! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDownInit\\n\\tdownButton borderInset.\\n\\tself resetTimer.\\n\\tself scrollBarAction: #doScrollDown.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDown: count\\n\\tself setValue: (value + (scrollDelta * count) + 0.000001 min: 1.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollPageInit: evt\\n\\tself resetTimer.\\n\\tself setNextDirectionFromEvent: evt.\\n\\tself scrollBarAction: #doScrollByPage.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUp\\n\\tself flag: #obsolete.\\n\\tupButton eventHandler: nil.\\n\\tupButton on: #mouseDown send: #scrollUpInit to: self.\\n\\tupButton on: #mouseUp send: #finishedScrolling to: self.\\n\\t^self scrollUpInit! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUpInit\\n\\tupButton borderInset.\\n\\tself resetTimer.\\n\\tself scrollBarAction: #doScrollUp.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUp: count\\n\\tself setValue: (value - (scrollDelta * count) - 0.000001 max: 0.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nsetNextDirectionFromEvent: event\\n\\n\\tnextPageDirection _ bounds isWide ifTrue: [\\n\\t\\tevent cursorPoint x >= slider center x\\n\\t]\\n\\tifFalse: [\\n\\t\\tevent cursorPoint y >= slider center y\\n\\t]\\n\\n! !\\n\\n\\n!OBScrollBar methodsFor: 'stepping and presenter' stamp: 'cwp 11/23/2003 18:07'!\\nstep\\n\\t| action |\\n\\taction _ self scrollBarAction.\\n\\taction ifNotNil:[self perform: action].! !\\n\\n\\n!OBScrollBar methodsFor: 'testing' stamp: 'cwp 11/23/2003 18:06'!\\nstepTime\\n\\t^ currentScrollDelay ifNil: [300]! !\\n\\n!OBScrollBar methodsFor: 'testing' stamp: 'cwp 11/23/2003 18:06'!\\nwantsSteps\\n\\t^self scrollBarAction notNil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBScrollBar class\\n\\tinstanceVariableNames: ''!\\n\\n!OBScrollBar class methodsFor: 'as yet unclassified' stamp: 'cwp 11/23/2003 18:07'!\\nalwaysShowFlatScrollbarForAlternativeLook\\n\\t\\\"Set this value to true, if you want to see the flat scrollbar look in flop-out mode as well as inboard. Otherwise the flop-out scrollbar will be rounded and inboard will be flat.\\\"\\n\\t^ false! !\\n\\n\\n!OBScrollBar class methodsFor: 'class initialization' stamp: 'cwp 11/23/2003 18:07'!\\ninitialize \\\"ScrollBar initialize\\\"\\n\\n\\tUpArrow _ Form\\n\\t\\textent: 6@3\\n\\t\\tfromArray: #(2r11e28 2r1111e27 2r111111e26)\\n\\t\\toffset: 0@0.! !\\nOBAnnouncement subclass: #OBSelectingNode\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBSelectingNode methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode\\n\\t^ node! !\\n\\n!OBSelectingNode methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectingNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectingNode class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBSelectionChanged\\n\\tinstanceVariableNames: 'node column'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 4/19/2006 00:53'!\\ncolumn\\n\\t^ column! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 4/19/2006 00:52'!\\ncolumn: aColumn\\n\\tcolumn _ aColumn! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 6/4/2006 12:19'!\\nnode\\n\\t^ column \\n\\t\\tifNil: [node]\\n\\t\\tifNotNil: [column selectedNode]! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 6/4/2006 12:20'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectionChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectionChanged class methodsFor: 'instance creation' stamp: 'cwp 4/19/2006 00:51'!\\ncolumn: aColumn \\n\\t^ self new column: aColumn! !\\n\\n\\n!OBSelectionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 4/19/2006 00:31'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBCodeNode subclass: #OBSelectorNode\\n\\tinstanceVariableNames: 'selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBSelectorNode commentStamp: 'cwp 1/8/2005 13:03' prior: 0!\\nOBSelectorNode wraps an instance of Symbol. It typically serves as the root of a senders or implementors OBListBrowser, and is used when cmd-n or cmd-m is invoke from the definition panel, and so no OBMethodNode is available.!\\n\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:48'!\\nimplementors\\n\\t^ (SystemNavigation default allImplementorsOf: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 22:35'!\\nimplementorsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self implementors! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:12'!\\nname\\n\\t^ selector printString! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:12'!\\nselectorAndMessages\\n\\t^ Array with: self! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 11/1/2004 02:22'!\\nsenders\\n\\t^ (SystemNavigation default allCallsOn: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: self selector inMethodReference: ref]! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:48'!\\nsendersOfMessage\\n\\t^ (SystemNavigation default allCallsOn: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: self selector inMethodReference: ref]! !\\n\\n\\n!OBSelectorNode methodsFor: 'accessing' stamp: 'cwp 10/31/2004 01:11'!\\nselector\\n\\t^ selector! !\\n\\n!OBSelectorNode methodsFor: 'accessing' stamp: 'cwp 10/31/2004 01:10'!\\nselector: aSelector\\n\\tselector := aSelector! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectorNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectorNode class methodsFor: 'instance creation' stamp: 'cwp 10/31/2004 01:11'!\\non: aSelector\\n\\t^ self new selector: aSelector! !\\nOBListBrowser subclass: #OBSendersBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSendersBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSendersBrowser class methodsFor: 'as yet unclassified' stamp: 'cwp 3/2/2006 15:31'!\\ndefaultMetaNode\\n\\t| selector list chase |\\n\\tlist := OBMetaNode named: 'Senders'.\\n\\tlist \\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\tchase := OBMetaNode named: 'Send'.\\n\\tchase\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\tchildAt: #senders put: chase;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\tselector := OBMetaNode named: 'Selector'.\\t\\n\\tselector \\n\\t\\tchildAt: #senders labeled: 'list' put: list;\\n\\t\\tchildAt: #senders labeled: 'chase' put: chase;\\n\\t\\tfilterClass: OBModalFilter.\\n\\n\\t^ selector! !\\n\\n!OBSendersBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:36'!\\ntitle\\n\\t^ 'Senders of'! !\\nObject subclass: #OBService\\n\\tinstanceVariableNames: 'action condition announcer label keystroke icon buttonLabel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/18/2006 18:53'!\\naction\\n\\t^ action! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/18/2006 18:53'!\\naction: aValuable\\n\\taction _ aValuable! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:34'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:33'!\\nannouncer: anAnnouncer\\n\\tannouncer _ anAnnouncer! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:38'!\\nbuttonLabel\\n\\t^ buttonLabel! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:39'!\\nbuttonLabel: aString\\n\\tbuttonLabel _ aString! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:40'!\\ncondition\\n\\t^ condition! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:40'!\\ncondition: aValuable\\n\\tcondition _ aValuable! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/25/2006 00:41'!\\ndescription\\n\\t^ 'description'! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:24'!\\nicon\\n\\t^ icon! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:24'!\\nicon: anIcon\\n\\ticon _ anIcon! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nkeystroke\\n\\t^ keystroke! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nkeystroke: aCharacter\\n\\tkeystroke _ aCharacter! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nlabel\\n\\t^ label! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 18:58'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 18:46'!\\naddServiceFor: aRequestor toMenu: aMenu\\n\\taMenu\\n\\t\\tadd: self labelWithKeystroke\\n\\t\\ttarget: self \\n\\t\\tselector: #executeFor:\\n\\t\\targument: aRequestor.\\n\\taMenu lastItem isEnabled: self isEnabled.\\n\\tPreferences menuWithIcons & self icon notNil\\n\\t\\tifTrue: [aMenu lastItem icon: self icon].\\n\\taMenu addBlankIconsIfNecessary: MenuIcons blankIcon.! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:41'!\\nbuttonLabelMorph\\n\\t^ StringMorph \\n\\t\\tcontents: self buttonLabel \\n\\t\\tfont: Preferences standardButtonFont! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:41'!\\nbuttonMorph\\n\\t^ (PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: nil\\n\\t\\taction: #trigger\\n\\t\\tlabel: #buttonLabelMorph)\\t\\n\\t\\t\\tonColor: Color lightGray lighter offColor: Color lightGray twiceLighter;\\n\\t\\t\\tborderWidth: 2;\\n\\t\\t\\tborderRaised;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\tsetBalloonText: label! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:05'!\\nlabelWithKeystroke\\n\\t^keystroke\\n\\t\\tifNil: [label]\\n\\t\\tifNotNil: [label, ' (', keystroke asString, ')']! !\\n\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/29/2006 01:12'!\\ncondExecuteFor: aRequestor\\n\\t^ (self isEnabledFor: aRequestor)\\n\\t\\t ifTrue: [self executeFor: aRequestor]! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 18:15'!\\nexecute\\n\\t^ self executeFor: nil! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 18:13'!\\nexecuteFor: aRequestor\\n\\taction valueWithPossibleArgs: {aRequestor}! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 15:42'!\\ntrigger\\n\\t^ self isEnabled ifTrue: [self execute]! !\\n\\n\\n!OBService methodsFor: 'initialize-release' stamp: 'cwp 6/24/2006 19:05'!\\ninitialize\\n\\taction _ [].\\n\\tcondition _ [true].\\n\\tlabel _ 'a service'.! !\\n\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/29/2006 01:11'!\\nisEnabled\\n\\t^ self isEnabledFor: nil! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/29/2006 01:07'!\\nisEnabledFor: aRequestor\\n\\t^ condition valueWithPossibleArgs: {aRequestor}! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/25/2006 00:43'!\\nuseLineAfter\\n\\t^ false! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/24/2006 19:46'!\\nwantsButton\\n\\t^ self buttonLabel notNil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBService class\\n\\tinstanceVariableNames: ''!\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/18/2006 18:53'!\\naction: aValuable\\n\\t^ self new action: aValuable! !\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/24/2006 15:40'!\\naction: aValuable condition: cValuable\\n\\t^ self new \\n\\t\\taction: aValuable;\\n\\t\\tcondition: cValuable;\\n\\t\\tyourself! !\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/24/2006 15:43'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBAnnouncement subclass: #OBServiceScan\\n\\tinstanceVariableNames: 'services'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:31'!\\naddService: aService\\n\\tservices add: aService! !\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:31'!\\ninitialize\\n\\tservices _ OrderedCollection new! !\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:30'!\\nservices\\n\\t^ services! !\\nNotification subclass: #OBSourceFilesRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBSourceFilesRequest commentStamp: 'cwp 1/8/2005 13:09' prior: 0!\\nOBSourceFilesRequest is used to work around the fact that Squeak's source files are stored in a global array called SourceFiles. When testing OBMethodVersion and OBVersionBrowser, we don't want to use the real source files, as they are too unpredictable. Instead the test cases supply a source file array with known contents.\\n\\nTherefore, OBMethodVersion never refers directly to the SourceFiles global. Instead it raises an OBSourceFiles request. If this occurs during a test, the test catches the notification and resumes using the test source files. Otherwise, the default action resumes using the global source file array.!\\n\\n\\n!OBSourceFilesRequest methodsFor: 'exceptionDescription'!\\ndefaultAction\\n\\t^ SourceFiles! !\\n\\n!OBSourceFilesRequest methodsFor: 'exceptionDescription' stamp: 'cwp 11/27/2004 22:49'!\\nisBrowseRequest\\n\\t^ false! !\\nOBCodeBrowser subclass: #OBSystemBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBSystemBrowser commentStamp: 'cwp 1/7/2005 23:56' prior: 0!\\nThis is the basic system browser that is the work-horse of Smalltalk development tools. It presents four panes showing class categories, classes, method categories and methods.!\\n\\n\\n!OBSystemBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSystemBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:13'!\\nalphabeticalMetaNode\\n\\t^ self\\n\\t\\timageClass: #classes\\n\\t\\tcomment: #comments\\n\\t\\tmetaclass: #metaclasses\\n! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:54'!\\ndefaultMetaNode\\n\\t^self hierarchicalMetaNode! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'cwp 12/6/2004 22:02'!\\ndefaultRootNode\\n\\t^ OBEnvironmentNode forImage! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:54'!\\nhierarchicalMetaNode\\n\\t^self \\n\\t\\timageClass: #classesHierarchically\\n\\t\\tcomment: #commentsHierarchically\\n\\t\\tmetaclass: #metaclassesHierarchically! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:09'!\\nimageClass: classSel comment: commentSel metaclass: metaclassSel \\n\\t| env classCategory |\\n\\tenv := OBMetaNode named: 'Environment'.\\n\\tclassCategory := OBMetaNode named: 'ClassCategory'.\\n\\tenv childAt: #categories put: classCategory.\\n\\tself addTo: classCategory class: classSel comment: commentSel metaclass: metaclassSel.\\n\\t^env! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration'!\\ntitle\\n\\t^ 'System Browser'! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'initializing'!\\ninitialize\\n\\tself registerInOpenMenu! !\\n\\n!OBSystemBrowser class methodsFor: 'initializing'!\\nregisterInOpenMenu\\n\\tTheWorldMenu registerOpenCommand: {'Image Browser'. {self. #open}}.\\n! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'dvf 8/31/2005 13:17'!\\nonClass: aClass \\n\\t^self selection: aClass asNode! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/15/2004 21:42'!\\nonClass: aClass category: aSymbol\\n\\t^ self selection: (OBMethodCategoryNode on: aSymbol inClass: aClass)! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 17:38'!\\nonClass: aClass selector: aSelector\\n\\t^ self selection: (OBMethodNode on: aSelector inClass: aClass)! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/15/2004 21:45'!\\nonEnvironment: anEnvironment category: aSymbol\\n\\t^ self selection: (OBClassCategoryNode \\n\\t\\t\\t\\t\\t\\ton: aSymbol \\n\\t\\t\\t\\t\\t\\tinEnvironment: anEnvironment)! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 18:32'!\\nopenOnClass: aClass\\n\\t^ (self onClass: aClass) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 21:47'!\\nopenOnClass: aClass category: aSymbol\\n\\t^ (self onClass: aClass category: aSymbol) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 17:38'!\\nopenOnClass: aClass selector: aSelector\\n\\t^ (self onClass: aClass selector: aSelector) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 21:54'!\\nopenOnEnvironment: anEnvironment category: aSymbol\\n\\t^ (self onEnvironment: anEnvironment category: aSymbol) open! !\\nObject subclass: #OBSystemBrowserAdaptor\\n\\tinstanceVariableNames: 'class selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBSystemBrowserAdaptor commentStamp: 'cwp 1/8/2005 13:35' prior: 0!\\nOBSystemBrowserAdaptor implements the protocol expected by the SystemBrowser app registry, and thus allows OmniBrowser to be chosen as the default system browser. \\n\\nCaveat: because the required protocol is a little ...odd.... it can't be implemented well by OBSystemBrowser directly. OBSystemBrowserAdaptor does this reasonably well, but it has no way to provide a more natural name than its class name to the app registry menu.!\\n\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:50'!\\nlabelString\\n\\t^ 'System Browser'! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:49'!\\nopenEditString: anUndefinedObject \\n\\t^ self! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:49'!\\nsetClass: aClass selector: aSelector \\n\\tclass _ aClass.\\n\\tselector _ aSelector! !\\n\\n\\n!OBSystemBrowserAdaptor methodsFor: 'accessing' stamp: 'cwp 12/5/2004 21:55'!\\nselector\\n\\t^ selector! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'accessing' stamp: 'cwp 12/5/2004 21:55'!\\ntargetClass\\n\\t^ class! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSystemBrowserAdaptor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 12/5/2004 22:01'!\\ninitialize\\n\\tself register! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 1/8/2005 21:52'!\\nregister\\n\\tSmalltalk at: #SystemBrowser ifPresent: [:class | class register: self]! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 1/8/2005 21:53'!\\nunregister\\n\\tSmalltalk at: #SystemBrowser ifPresent: [:class | class unregister: self]! !\\n\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'lr 4/20/2006 08:48'!\\nfullOnClass: aClass selector: aSelector\\n\\t^ OBSystemBrowser \\n\\t\\topenOnClass: aClass\\n\\t\\tselector: aSelector! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'lr 3/28/2006 09:10'!\\nopen\\n\\tOBSystemBrowser open! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:59'!\\nopenBrowser\\n\\tOBSystemBrowser open! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:56'!\\nopenBrowserView: adaptor label: ignored \\n\\t^ OBSystemBrowser \\n\\t\\topenOnClass: adaptor targetClass \\n\\t\\tselector: adaptor selector! !\\nTextMorphForEditView subclass: #OBTextMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBTextMorph commentStamp: 'cwp 12/7/2004 00:07' prior: 0!\\nThis is a trivial subclass of TextMorph. It overrides editor creation to use OBTextMorphEditor rather than a regular TextMorphEditor.!\\n\\n\\n!OBTextMorph methodsFor: 'private' stamp: 'cwp 10/30/2004 23:06'!\\ninstallEditorToReplace: priorEditor\\n\\t\\\"Install an editor for my paragraph. This constitutes 'hasFocus'.\\n\\tIf priorEditor is not nil, then initialize the new editor from its state.\\n\\tWe may want to rework this so it actually uses the prior editor.\\\"\\n\\n\\t| stateArray |\\n\\tpriorEditor ifNotNil: [stateArray _ priorEditor stateArray].\\n\\teditor _ OBTextMorphEditor new morph: self.\\n\\teditor changeParagraph: self paragraph.\\n\\tpriorEditor ifNotNil: [editor stateArrayPut: stateArray].\\n\\tself selectionChanged.\\n\\t^ editor! !\\nTextMorphEditor subclass: #OBTextMorphEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBTextMorphEditor commentStamp: 'cwp 1/7/2005 23:27' prior: 0!\\nOBTextMorphEditor overrides the TextMorphEditors handling of command keys, passing them along to its model for processing, rather than hard-coding their implementations.!\\n\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 01:52'!\\nbrowseIt\\n\\t| symbol |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(symbol _ self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself send: #browseIt: toModelWith: {symbol} orDo: [super browseIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 00:40'!\\nimplementorsOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #implementorsOfIt: toModelWith: {selector} orDo: [super sendersOfIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 01:10'!\\nreferencesToIt\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #referencesToIt: toModelWith: {selector} orDo: [super referencesToIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 00:26'!\\nsendersOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #sendersOfIt: toModelWith: {selector} orDo: [super sendersOfIt]! !\\n\\n\\n!OBTextMorphEditor methodsFor: 'model access' stamp: 'cwp 10/31/2004 00:24'!\\nsend: aSelector toModelWith: args orDo: aBlock\\n\\tself terminateAndInitializeAround:\\n\\t\\t[(model respondsTo: aSelector)\\n\\t\\t\\tifTrue: [(model perform: aSelector withArguments: args)\\n\\t\\t\\t\\t\\t\\tifFalse: [view flash]]\\n\\t\\t\\tifFalse: aBlock]! !\\nOBInteractionRequest subclass: #OBTextRequest\\n\\tinstanceVariableNames: 'prompt template'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBTextRequest commentStamp: 'cwp 3/5/2004 12:35' prior: 0!\\nThis notification is used to ask the user to supply a short piece of text. Its defaultAction is to open a FillInTheBlank.\\n\\niVars:\\n\\nprompt\\t\\t- a string describing the text the user is asked to supply\\ntemplate\\t- a default reply !\\n\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:24'!\\nprompt\\n\\t^ prompt! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:23'!\\nprompt: aString\\n\\tprompt _ aString! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:00'!\\ntemplate\\n\\t^ template! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 20:59'!\\ntemplate: aString\\n\\ttemplate _ aString! !\\n\\n\\n!OBTextRequest methodsFor: 'user interaction' stamp: 'cwp 2/2/2004 21:27'!\\ndefaultAction\\n\\tself resume: self requestText! !\\n\\n!OBTextRequest methodsFor: 'user interaction' stamp: 'cwp 2/2/2004 21:27'!\\nrequestText\\n\\t^ FillInTheBlankMorph \\n\\t\\trequest: prompt\\n\\t\\tinitialAnswer: template\\n\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\tinWorld: World\\n\\t\\tonCancelReturn: nil\\n\\t\\tacceptOnCR: true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBTextRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBTextRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/2/2004 21:30'!\\nprompt: aString\\n\\t^ self new prompt: aString; template: ''! !\\n\\n!OBTextRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/5/2004 20:31'!\\nprompt: promptString template: templateString\\n\\t^ (self new prompt: promptString; template: templateString) signal! !\\nOBPanel subclass: #OBVarButtonPanel\\n\\tinstanceVariableNames: 'morph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBVarButtonPanel commentStamp: 'cwp 12/7/2004 00:21' prior: 0!\\nOBVarButtonPanel displays a horizontal row of buttons. In contrast to OBFixedButtonPanel, the buttons on display are updated to reflect the actions appropriate to the currently selected node.!\\n\\n\\n!OBVarButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 18:16'!\\nmorph\\n\\t^ morph _ (RectangleMorph new)\\n\\t\\t\\t\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\t\\t\\t\\tlistDirection: #leftToRight;\\n\\t\\t\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\t\\t\\tborderWidth: 0;\\n\\t\\t\\t\\t\\twrapCentering: #center;\\n\\t\\t\\t\\t\\tcellPositioning: #leftCenter;\\n\\t\\t\\t\\t\\trubberBandCells: true;\\n\\t\\t\\t\\t\\tyourself! !\\n\\n!OBVarButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/26/2004 22:41'!\\nmorphHeight\\n\\t^ 25! !\\n\\n\\n!OBVarButtonPanel methodsFor: 'updating' stamp: 'cwp 7/8/2006 12:54'!\\nselectionChanged: ann\\n\\t| node actions |\\n\\tmorph removeAllMorphs.\\n\\tnode _ browser currentNode ifNil: [^ self].\\n\\tactions _ (node metaNode actionsForNode: node) select: [:ea | ea wantsButton].\\n\\tactions do: [:ea | morph addMorphBack: ea buttonMorph]! !\\n\\n!OBVarButtonPanel methodsFor: 'updating' stamp: 'cwp 6/3/2006 22:30'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self! !\\nOBClassAwareNode subclass: #OBVariableNode\\n\\tinstanceVariableNames: 'name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBVariableNode commentStamp: 'cwp 1/8/2005 12:46' prior: 0!\\nOBVariableNode is an abstract superclass for the two types of variables a class can contain - class variables and instance variables. The only difference between the two subclasses is how they search for methods that refer to them.!\\n\\n\\n!OBVariableNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:38'!\\nactions\\n\\t^ {self browseAction}! !\\n\\n\\n!OBVariableNode methodsFor: 'displaying'!\\nname\\n\\t^ name! !\\n\\n\\n!OBVariableNode methodsFor: 'initializing'!\\nsetName: aString class: aClass\\n\\tname := aString.\\n\\tself theClass: aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVariableNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVariableNode class methodsFor: 'instance creation'!\\non: instVarName inClass: aClassReference \\n\\t^ self new setName: instVarName class: aClassReference! !\\nOBListBrowser subclass: #OBVariablesBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVariablesBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVariablesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:22'!\\ndefaultMetaNode\\n\\t| class method message var |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tvar := OBMetaNode named: 'Variable'.\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\tmessage := OBMetaNode named: 'Message'.\\n\\tclass\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #instanceVariables labeled: 'instance' put: var;\\n\\t\\tchildAt: #classVariables labeled: 'class' put: var;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tvar\\n\\t\\tchildAt: #accessors put: method;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #senders put: message;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tmessage\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #senders put: message;\\n\\t\\tfilterClass: OBModalFilter.\\n\\t\\n\\t^ class! !\\n\\n!OBVariablesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:35'!\\ntitle\\n\\t^ 'Variables of'! !\\nOBCodeBrowser subclass: #OBVersionBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBVersionBrowser commentStamp: 'cwp 1/7/2005 23:58' prior: 0!\\nOBVersionBrowser displays a list of OBMethodVersions, which represent versions of a method present in the source or changes files. !\\n\\n\\n!OBVersionBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightMagenta! !\\n\\n\\n!OBVersionBrowser methodsFor: 'accessing' stamp: 'cwp 11/27/2004 22:28'!\\ndefaultLabel\\n\\t^ 'Versions of ', self root name printString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVersionBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:09'!\\ndefaultMetaNode\\n\\t| version |\\n\\tversion := OBMetaNode named: 'Version'.\\n\\tversion addActor: OBNodeActor new.\\n\\t^ (OBMetaNode named: 'Method') \\n\\t\\tchildAt: #versions put: version.! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:32'!\\nmaxPanes\\n\\t^ 1! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:32'!\\nminPanes\\n\\t^ 1! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:34'!\\noptionalButtons\\n\\t^ #('browse' 'revert')! !\\n\\n\\n!OBVersionBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 15:42'!\\nopenOn: aMethodVersionNode\\n\\t^ (self root: aMethodVersionNode) open! !\\nProtoObject subclass: #Object\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DependentsFields'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!Object commentStamp: '<historical>' prior: 0!\\nObject is the root class for almost all of the other classes in the class hierarchy. The exceptions are ProtoObject (the superclass of Object) and its subclasses.\\n\\nClass Object provides default behavior common to all normal objects, such as access, copying, comparison, error handling, message sending, and reflection. Also utility messages that all objects should respond to are defined here.\\n\\nObject has no instance variables, nor should any be added. This is due to several classes of objects that inherit from Object that have special implementations (SmallInteger and UndefinedObject for example) or the VM knows about and depends on the structure and layout of certain standard classes.\\n\\nClass Variables:\\n\\tDependentsFields\\t\\tan IdentityDictionary\\n\\t\\tProvides a virtual 'dependents' field so that any object may have one\\n\\t\\tor more dependent views, synchronized by the changed:/update: protocol.\\n\\t\\tNote that class Model has a real slot for its dependents, and overrides\\n\\t\\tthe associated protocol with more efficient implementations.\\n\\tEventsFields\\t\\t\\tan IdentityDictionary that maps each object to its dependents.\\n\\t\\tRegisters a message send (consisting of a selector and a receiver object)\\n\\t\\twhich should be performed when anEventSymbol is triggered by the receiver.\\n\\t\\tPart of a new event notification framework which could eventually replace\\n\\t\\tthe existing changed/update mechanism. It is intended to be compatible\\n\\t\\twith Dolphin Smalltalk and VSE as much as possible.\\n\\nBecause Object is the root of the inheritance tree, methods are often defined in Object to give all objects special behaviors needed by certain subsystems or applications, or to respond to certain general test messages such as isMorph.!\\n\\n\\n!Object methodsFor: 'accessing' stamp: 'sw 4/30/1998 12:18'!\\naddInstanceVarNamed: aName withValue: aValue\\n\\t\\\"Add an instance variable named aName and give it value aValue\\\"\\n\\tself class addInstVarName: aName asString.\\n\\tself instVarAt: self class instSize put: aValue! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 11:39'!\\nat: index \\n\\t\\\"Primitive. Assumes receiver is indexable. Answer the value of an \\n\\tindexable element in the receiver. Fail if the argument index is not an \\n\\tInteger or is out of bounds. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 60>\\n\\tindex isInteger ifTrue:\\n\\t\\t[self class isVariable\\n\\t\\t\\tifTrue: [self errorSubscriptBounds: index]\\n\\t\\t\\tifFalse: [self errorNotIndexable]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self at: index asInteger]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nat: index modify: aBlock\\n\\t\\\"Replace the element of the collection with itself transformed by the block\\\"\\n\\t^ self at: index put: (aBlock value: (self at: index))! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 13:08'!\\nat: index put: value \\n\\t\\\"Primitive. Assumes receiver is indexable. Store the argument value in \\n\\tthe indexable element of the receiver indicated by index. Fail if the \\n\\tindex is not an Integer or is out of bounds. Or fail if the value is not of \\n\\tthe right type for this kind of collection. Answer the value that was \\n\\tstored. Essential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 61>\\n\\tindex isInteger ifTrue:\\n\\t\\t[self class isVariable\\n\\t\\t\\tifTrue: [(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]]\\n\\t\\t\\tifFalse: [self errorNotIndexable]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self at: index asInteger put: value]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 9/20/2004 10:22'!\\nbasicAddInstanceVarNamed: aName withValue: aValue\\n\\t\\\"Add an instance variable named aName and give it value aValue\\\"\\n\\tself class addInstVarName: aName asString.\\n\\tself instVarAt: self class instSize put: aValue! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicAt: index \\n\\t\\\"Primitive. Assumes receiver is indexable. Answer the value of an \\n\\tindexable element in the receiver. Fail if the argument index is not an \\n\\tInteger or is out of bounds. Essential. Do not override in a subclass. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 60>\\n\\tindex isInteger ifTrue: [self errorSubscriptBounds: index].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self basicAt: index asInteger]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicAt: index put: value \\n\\t\\\"Primitive. Assumes receiver is indexable. Store the second argument \\n\\tvalue in the indexable element of the receiver indicated by index. Fail \\n\\tif the index is not an Integer or is out of bounds. Or fail if the value is \\n\\tnot of the right type for this kind of collection. Answer the value that \\n\\twas stored. Essential. Do not override in a subclass. See Object \\n\\tdocumentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 61>\\n\\tindex isInteger\\n\\t\\tifTrue: [(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self basicAt: index asInteger put: value]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicSize\\n\\t\\\"Primitive. Answer the number of indexable variables in the receiver. \\n\\tThis value is the same as the largest legal subscript. Essential. Do not \\n\\toverride in any subclass. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 62>\\n\\t\\\"The number of indexable fields of fixed-length objects is 0\\\"\\n\\t^0\\t! !\\n\\n!Object methodsFor: 'accessing'!\\nbindWithTemp: aBlock\\n\\t^ aBlock value: self value: nil! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 10/7/2004 15:43'!\\nifNil: nilBlock ifNotNilDo: aBlock \\n\\t\\\"Evaluate aBlock with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'di 11/8/2000 21:04'!\\nifNotNilDo: aBlock\\n\\t\\\"Evaluate the given block with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 10/7/2004 15:43'!\\nifNotNilDo: aBlock ifNil: nilBlock\\n\\t\\\"Evaluate aBlock with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'ajh 1/21/2003 12:59'!\\nin: aBlock\\n\\t\\\"Evaluate the given block with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'sw 10/17/2000 11:15'!\\npresenter\\n\\t\\\"Answer the presenter object associated with the receiver. For morphs, there is in effect a clear containment hierarchy of presenters (accessed via their association with PasteUpMorphs); for arbitrary objects the hook is simply via the current world, at least at present.\\\"\\n\\n\\t^ self currentWorld presenter! !\\n\\n!Object methodsFor: 'accessing'!\\nreadFromString: aString\\n\\t\\\"Create an object based on the contents of aString.\\\"\\n\\n\\t^self readFrom: (ReadStream on: aString)! !\\n\\n!Object methodsFor: 'accessing' stamp: 'di 3/29/1999 13:10'!\\nsize\\n\\t\\\"Primitive. Answer the number of indexable variables in the receiver. \\n\\tThis value is the same as the largest legal subscript. Essential. See Object \\n\\tdocumentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 62>\\n\\tself class isVariable ifFalse: [self errorNotIndexable].\\n\\t^ 0! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 5/16/2006 12:34'!\\nyourself\\n\\t\\\"Answer self.\\\"\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'associating' stamp: 'md 7/22/2005 16:03'!\\n-> anObject\\n\\t\\\"Answer an Association between self and anObject\\\"\\n\\n\\t^Association basicNew key: self value: anObject! !\\n\\n\\n\\n!Object methodsFor: 'binding'!\\nbindingOf: aString\\n\\t^nil! !\\n\\n\\n!Object methodsFor: 'casing'!\\ncaseOf: aBlockAssociationCollection\\n\\t\\\"The elements of aBlockAssociationCollection are associations between blocks.\\n\\t Answer the evaluated value of the first association in aBlockAssociationCollection\\n\\t whose evaluated key equals the receiver. If no match is found, report an error.\\\"\\n\\n\\t^ self caseOf: aBlockAssociationCollection otherwise: [self caseError]\\n\\n\\\"| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z\\\"\\n\\\"| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z\\\"\\n\\\"The following are compiled in-line:\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}\\\"! !\\n\\n!Object methodsFor: 'casing'!\\ncaseOf: aBlockAssociationCollection otherwise: aBlock\\n\\t\\\"The elements of aBlockAssociationCollection are associations between blocks.\\n\\t Answer the evaluated value of the first association in aBlockAssociationCollection\\n\\t whose evaluated key equals the receiver. If no match is found, answer the result\\n\\t of evaluating aBlock.\\\"\\n\\n\\taBlockAssociationCollection associationsDo:\\n\\t\\t[:assoc | (assoc key value = self) ifTrue: [^assoc value value]].\\n\\t^ aBlock value\\n\\n\\\"| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]\\\"\\n\\\"| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]\\\"\\n\\\"The following are compiled in-line:\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]\\\"! !\\n\\n\\n!Object methodsFor: 'class membership'!\\nclass\\n\\t\\\"Primitive. Answer the object which is the receiver's class. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 111>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'class membership' stamp: 'sw 9/27/2001 15:51'!\\ninheritsFromAnyIn: aList\\n\\t\\\"Answer whether the receiver inherits from any class represented by any element in the list. The elements of the list can be classes, class name symbols, or strings representing possible class names. This allows speculative membership tests to be made even when some of the classes may not be known to the current image, and even when their names are not interned symbols.\\\"\\n\\n\\t| aClass |\\n\\taList do:\\n\\t\\t[:elem | Symbol hasInterned: elem asString ifTrue: \\n\\t\\t\\t[:elemSymbol | (((aClass _ Smalltalk at: elemSymbol ifAbsent: [nil]) isKindOf: Class)\\n\\t\\t\\t\\t\\t\\tand: [self isKindOf: aClass])\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[^ true]]].\\n\\t^ false\\n\\n\\n\\\"\\n{3. true. 'olive'} do:\\n\\t[:token |\\n\\t\\t {{#Number. #Boolean}. {Number. Boolean }. {'Number'. 'Boolean'}} do:\\n\\t\\t\\t[:list |\\n\\t\\t\\t\\tTranscript cr; show: token asString, ' list element provided as a ', list first class name, ' - ', (token inheritsFromAnyIn: list) asString]]\\n\\\"! !\\n\\n!Object methodsFor: 'class membership'!\\nisKindOf: aClass \\n\\t\\\"Answer whether the class, aClass, is a superclass or class of the receiver.\\\"\\n\\n\\tself class == aClass\\n\\t\\tifTrue: [^true]\\n\\t\\tifFalse: [^self class inheritsFrom: aClass]! !\\n\\n!Object methodsFor: 'class membership' stamp: 'sw 2/16/98 02:08'!\\nisKindOf: aClass orOf: anotherClass\\n\\t\\\"Answer whether either of the classes, aClass or anotherClass,, is a superclass or class of the receiver. A convenience; could be somewhat optimized\\\"\\n\\t^ (self isKindOf: aClass) or: [self isKindOf: anotherClass]! !\\n\\n!Object methodsFor: 'class membership'!\\nisMemberOf: aClass \\n\\t\\\"Answer whether the receiver is an instance of the class, aClass.\\\"\\n\\n\\t^self class == aClass! !\\n\\n!Object methodsFor: 'class membership'!\\nrespondsTo: aSymbol \\n\\t\\\"Answer whether the method dictionary of the receiver's class contains \\n\\taSymbol as a message selector.\\\"\\n\\n\\t^self class canUnderstand: aSymbol! !\\n\\n!Object methodsFor: 'class membership' stamp: 'tk 10/21/1998 12:38'!\\nxxxClass\\n\\t\\\"For subclasses of nil, such as ObjectOut\\\"\\n\\t^ self class! !\\n\\n\\n!Object methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'!\\ncloseTo: anObject\\n\\t\\\"Answer whether the receiver and the argument represent the same\\n\\tobject. If = is redefined in any subclass, consider also redefining the\\n\\tmessage hash.\\\"\\n\\n\\t| ans |\\n\\t[ans _ self = anObject] ifError: [:aString :aReceiver | ^ false].\\n\\t^ ans! !\\n\\n!Object methodsFor: 'comparing'!\\nhash\\n\\t\\\"Answer a SmallInteger whose value is related to the receiver's identity.\\n\\tMay be overridden, and should be overridden in any classes that define = \\\"\\n\\n\\t^ self identityHash! !\\n\\n!Object methodsFor: 'comparing' stamp: 'pm 9/23/97 09:36'!\\nhashMappedBy: map\\n\\t\\\"Answer what my hash would be if oops changed according to map.\\\"\\n\\n\\t^map newHashFor: self! !\\n\\n!Object methodsFor: 'comparing' stamp: 'di 9/27/97 20:23'!\\nidentityHashMappedBy: map\\n\\t\\\"Answer what my hash would be if oops changed according to map.\\\"\\n\\n\\t^map newHashFor: self! !\\n\\n!Object methodsFor: 'comparing' stamp: 'sw 8/20/1998 12:34'!\\nidentityHashPrintString\\n\\t\\\"'fred' identityHashPrintString\\\"\\n\\n\\t^ '(', self identityHash printString, ')'! !\\n\\n!Object methodsFor: 'comparing' stamp: 'ajh 2/2/2002 15:02'!\\nliteralEqual: other\\n\\n\\t^ self class == other class and: [self = other]! !\\n\\n!Object methodsFor: 'comparing'!\\n= anObject \\n\\t\\\"Answer whether the receiver and the argument represent the same \\n\\tobject. If = is redefined in any subclass, consider also redefining the \\n\\tmessage hash.\\\"\\n\\n\\t^self == anObject! !\\n\\n!Object methodsFor: 'comparing'!\\n~= anObject \\n\\t\\\"Answer whether the receiver and the argument do not represent the \\n\\tsame object.\\\"\\n\\n\\t^self = anObject == false! !\\n\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'!\\nadaptToFloat: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Float,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:14'!\\nadaptToFraction: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Fraction,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'!\\nadaptToInteger: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Integer,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'rw 4/27/2002 07:48'!\\nasActionSequence\\n\\n\\t^WeakActionSequence with: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'!\\nasActionSequenceTrappingErrors\\n\\n\\t^WeakActionSequenceTrappingErrors with: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'svp 5/16/2000 18:14'!\\nasDraggableMorph\\n\\t^(StringMorph contents: self printString)\\n\\t\\tcolor: Color white;\\n\\t\\tyourself! !\\n\\n!Object methodsFor: 'converting' stamp: 'sma 5/12/2000 17:39'!\\nasOrderedCollection\\n\\t\\\"Answer an OrderedCollection with the receiver as its only element.\\\"\\n\\n\\t^ OrderedCollection with: self! !\\n\\n!Object methodsFor: 'converting'!\\nasString\\n\\t\\\"Answer a string that represents the receiver.\\\"\\n\\n\\t^ self printString ! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 3/11/2003 10:27'!\\nasStringOrText\\n\\t\\\"Answer a string that represents the receiver.\\\"\\n\\n\\t^ self printString ! !\\n\\n!Object methodsFor: 'converting'!\\nas: aSimilarClass\\n\\t\\\"Create an object of class aSimilarClass that has similar contents to the receiver.\\\"\\n\\n\\t^ aSimilarClass newFrom: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'RAA 8/2/1999 12:41'!\\ncomplexContents\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:37'!\\nmustBeBoolean\\n\\t\\\"Catches attempts to test truth of non-Booleans. This message is sent from the VM. The sending context is rewound to just before the jump causing this exception.\\\"\\n\\n\\t^ self mustBeBooleanIn: thisContext sender! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:40'!\\nmustBeBooleanIn: context\\n\\t\\\"context is the where the non-boolean error occurred. Rewind context to before jump then raise error.\\\"\\n\\n\\t| proceedValue |\\n\\tcontext skipBackBeforeJump.\\n\\tproceedValue _ NonBooleanReceiver new\\n\\t\\tobject: self;\\n\\t\\tsignal: 'proceed for truth.'.\\n\\t^ proceedValue ~~ false! !\\n\\n!Object methodsFor: 'converting' stamp: 'sw 3/26/2001 12:12'!\\nprintDirectlyToDisplay\\n\\t\\\"For debugging: write the receiver's printString directly to the display at (0, 100); senders of this are detected by the check-for-slips mechanism.\\\"\\n\\n\\tself asString displayAt: 0@100\\n\\n\\\"StringMorph someInstance printDirectlyToDisplay\\\"! !\\n\\n!Object methodsFor: 'converting' stamp: 'RAA 3/31/1999 12:13'!\\nwithoutListWrapper\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'copying'!\\nclone\\n\\n\\t<primitive: 148>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 8/18/2001 21:25'!\\ncopy\\n\\t\\\"Answer another instance just like the receiver. Subclasses typically override postCopy; they typically do not override shallowCopy.\\\"\\n\\n\\t^self shallowCopy postCopy! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 8/20/1998 16:01'!\\ncopyAddedStateFrom: anotherObject\\n\\t\\\"Copy over the values of instance variables added by the receiver's class from anotherObject to the receiver. These will be remapped in mapUniClasses, if needed.\\\"\\n\\n\\tself class superclass instSize + 1 to: self class instSize do:\\n\\t\\t[:index | self instVarAt: index put: (anotherObject instVarAt: index)]! !\\n\\n!Object methodsFor: 'copying' stamp: 'tpr 2/14/2004 21:53'!\\ncopyFrom: anotherObject\\n\\t\\\"Copy to myself all instance variables I have in common with anotherObject. This is dangerous because it ignores an object's control over its own inst vars. \\\"\\n\\n\\t| mine his |\\n\\t<primitive: 168>\\n\\tmine _ self class allInstVarNames.\\n\\this _ anotherObject class allInstVarNames.\\n\\t1 to: (mine size min: his size) do: [:ind |\\n\\t\\t(mine at: ind) = (his at: ind) ifTrue: [\\n\\t\\t\\tself instVarAt: ind put: (anotherObject instVarAt: ind)]].\\n\\tself class isVariable & anotherObject class isVariable ifTrue: [\\n\\t\\t1 to: (self basicSize min: anotherObject basicSize) do: [:ind |\\n\\t\\t\\tself basicAt: ind put: (anotherObject basicAt: ind)]].! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 5/23/2002 00:38'!\\ncopySameFrom: otherObject\\n\\t\\\"Copy to myself all instance variables named the same in otherObject.\\n\\tThis ignores otherObject's control over its own inst vars.\\\"\\n\\n\\t| myInstVars otherInstVars match |\\n\\tmyInstVars _ self class allInstVarNames.\\n\\totherInstVars _ otherObject class allInstVarNames.\\n\\tmyInstVars doWithIndex: [:each :index |\\n\\t\\t(match _ otherInstVars indexOf: each) > 0 ifTrue:\\n\\t\\t\\t[self instVarAt: index put: (otherObject instVarAt: match)]].\\n\\t1 to: (self basicSize min: otherObject basicSize) do: [:i |\\n\\t\\tself basicAt: i put: (otherObject basicAt: i)].\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 4/20/1999 14:44'!\\ncopyTwoLevel\\n\\t\\\"one more level than a shallowCopy\\\"\\n\\n\\t| newObject class index |\\n\\tclass _ self class.\\n\\tnewObject _ self clone.\\n\\tnewObject == self ifTrue: [^ self].\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index) shallowCopy.\\n\\t\\t\\t\\t\\tindex _ index - 1]].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index) shallowCopy.\\n\\t\\t\\tindex _ index - 1].\\n\\t^newObject! !\\n\\n!Object methodsFor: 'copying'!\\ndeepCopy\\n\\t\\\"Answer a copy of the receiver with its own copy of each instance \\n\\tvariable.\\\"\\n\\n\\t| newObject class index |\\n\\tclass _ self class.\\n\\t(class == Object) ifTrue: [^self].\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\tnewObject _ class basicNew: index.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index) deepCopy.\\n\\t\\t\\t\\t\\tindex _ index - 1]]\\n\\t\\tifFalse: [newObject _ class basicNew].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index) deepCopy.\\n\\t\\t\\tindex _ index - 1].\\n\\t^newObject! !\\n\\n!Object methodsFor: 'copying' stamp: 'hg 11/23/1999 13:43'!\\ninitialDeepCopierSize\\n\\t\\\"default value is 4096; other classes may override this, esp. for smaller (=faster) sizes\\\"\\n\\n\\t^4096! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 1/27/2003 18:45'!\\npostCopy\\n\\t\\\"self is a shallow copy, subclasses should copy fields as necessary to complete the full copy\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'copying' stamp: 'jm 11/14/97 11:08'!\\nshallowCopy\\n\\t\\\"Answer a copy of the receiver which shares the receiver's instance variables.\\\"\\n\\t| class newObject index |\\n\\t<primitive: 148>\\n\\tclass _ self class.\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\tnewObject _ class basicNew: index.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index).\\n\\t\\t\\t\\t\\tindex _ index - 1]]\\n\\t\\tifFalse: [newObject _ class basicNew].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index).\\n\\t\\t\\tindex _ index - 1].\\n\\t^ newObject! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 13:58'!\\nveryDeepCopy\\n\\t\\\"Do a complete tree copy using a dictionary. An object in the tree twice is only copied once. All references to the object in the copy of the tree will point to the new copy.\\\"\\n\\n\\t| copier new |\\n\\tcopier _ DeepCopier new initialize: self initialDeepCopierSize.\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\tcopier fixDependents.\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 13:58'!\\nveryDeepCopySibling\\n\\t\\\"Do a complete tree copy using a dictionary. Substitute a clone of oldPlayer for the root. Normally, a Player or non systemDefined object would have a new class. We do not want one this time. An object in the tree twice, is only copied once. All references to the object in the copy of the tree will point to the new copy.\\\"\\n\\n\\t| copier new |\\n\\tcopier _ DeepCopier new initialize: self initialDeepCopierSize.\\n\\tcopier newUniClasses: false.\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\tcopier fixDependents.\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 5/13/2003 19:39'!\\nveryDeepCopyUsing: copier\\n\\t\\\"Do a complete tree copy using a dictionary. An object in the tree twice is only copied once. All references to the object in the copy of the tree will point to the new copy.\\n\\tSame as veryDeepCopy except copier (with dictionary) is supplied.\\n\\t** do not delete this method, even if it has no callers **\\\"\\n\\n\\t| new refs newDep newModel |\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\t\\\"Fix dependents\\\"\\n\\trefs _ copier references.\\n\\tDependentsFields associationsDo: [:pair |\\n\\t\\tpair value do: [:dep | \\n\\t\\t\\t(newDep _ refs at: dep ifAbsent: [nil]) ifNotNil: [\\n\\t\\t\\t\\tnewModel _ refs at: pair key ifAbsent: [pair key].\\n\\t\\t\\t\\tnewModel addDependent: newDep]]].\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 14:12'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. Some classes refuse to be copied. Some classes are picky about which fields get deep copied.\\\"\\n\\t| class index sub subAss new uc sup has mine |\\n\\tdeepCopier references at: self ifPresent: [:newer | ^ newer]. \\t\\\"already did him\\\"\\n\\tclass _ self class.\\n\\tclass isMeta ifTrue: [^ self].\\t\\t\\\"a class\\\"\\n\\tnew _ self clone.\\n\\t(class isSystemDefined not and: [deepCopier newUniClasses \\\"allowed\\\"]) ifTrue: [\\n\\t\\tuc _ deepCopier uniClasses at: class ifAbsent: [nil].\\n\\t\\tuc ifNil: [\\n\\t\\t\\tdeepCopier uniClasses at: class put: (uc _ self copyUniClassWith: deepCopier).\\n\\t\\t\\tdeepCopier references at: class put: uc].\\t\\\"remember\\\"\\n\\t\\tnew _ uc new.\\n\\t\\tnew copyFrom: self].\\t\\\"copy inst vars in case any are weak\\\"\\n\\tdeepCopier references at: self put: new.\\t\\\"remember\\\"\\n\\t(class isVariable and: [class isPointers]) ifTrue: \\n\\t\\t[index _ self basicSize.\\n\\t\\t[index > 0] whileTrue: \\n\\t\\t\\t[sub _ self basicAt: index.\\n\\t\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\t\\tifNil: [new basicAt: index put: (sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\t\\tifNotNil: [new basicAt: index put: subAss value].\\n\\t\\t\\tindex _ index - 1]].\\n\\t\\\"Ask each superclass if it wants to share (weak copy) any inst vars\\\"\\n\\tnew veryDeepInner: deepCopier.\\t\\t\\\"does super a lot\\\"\\n\\n\\t\\\"other superclasses want all inst vars deep copied\\\"\\n\\tsup _ class. index _ class instSize.\\n\\t[has _ sup compiledMethodAt: #veryDeepInner: ifAbsent: [nil].\\n\\thas _ has ifNil: [class isSystemDefined not \\\"is a uniClass\\\"] ifNotNil: [true].\\n\\tmine _ sup instVarNames.\\n\\thas ifTrue: [index _ index - mine size]\\t\\\"skip inst vars\\\"\\n\\t\\tifFalse: [1 to: mine size do: [:xx |\\n\\t\\t\\t\\tsub _ self instVarAt: index.\\n\\t\\t\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\t\\t\\t\\t\\\"use association, not value, so nil is an exceptional value\\\"\\n\\t\\t\\t\\t\\tifNil: [new instVarAt: index put: \\n\\t\\t\\t\\t\\t\\t\\t\\t(sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\t\\t\\tifNotNil: [new instVarAt: index put: subAss value].\\n\\t\\t\\t\\tindex _ index - 1]].\\n\\t(sup _ sup superclass) == nil] whileFalse.\\n\\tnew rehash.\\t\\\"force Sets and Dictionaries to rehash\\\"\\n\\t^ new\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 1/6/1999 17:39'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"I have no fields and no superclass. Catch the super call.\\\"\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 9/4/2001 10:30'!\\nveryDeepInner: deepCopier\\n\\t\\\"No special treatment for inst vars of my superclasses. Override when some need to be weakly copied. Object>>veryDeepCopyWith: will veryDeepCopy any inst var whose class does not actually define veryDeepInner:\\\"\\n! !\\n\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:33'!\\nasMorph\\n\\t\\\"Open a morph, as best one can, on the receiver\\\"\\n\\n\\t^ self asStringMorph\\n\\n\\t\\\"\\n234 asMorph\\n(ScriptingSystem formAtKey: #TinyMenu) asMorph\\n'fred' asMorph\\n\\\"\\n\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:35'!\\nasStringMorph\\n\\t\\\"Open a StringMorph, as best one can, on the receiver\\\"\\n\\n\\t^ self asStringOrText asStringMorph\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:35'!\\nasTextMorph\\n\\t\\\"Open a TextMorph, as best one can, on the receiver\\\"\\n\\n\\t^ TextMorph new contentsAsIs: self asStringOrText\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'sw 1/29/2002 21:45'!\\nopenAsMorph\\n\\t\\\"Open a morph, as best one can, on the receiver\\\"\\n\\n\\t^ self asMorph openInHand\\n\\n\\\"\\n234 openAsMorph\\n(ScriptingSystem formAtKey: #TinyMenu) openAsMorph\\n'fred' openAsMorph\\n\\\"! !\\n\\n\\n!Object methodsFor: 'debugging' stamp: 'md 11/24/2004 11:45'!\\nhaltIf: condition\\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. Param can be a block or expression, halt if true.\\n\\tIf the Block has one arg, the receiver is bound to that.\\n \\tIf the condition is a selector, we look up in the callchain. Halt if\\n any method's selector equals selector.\\\"\\n\\t| cntxt |\\n\\n\\tcondition isSymbol ifTrue:[\\n\\t\\t\\\"only halt if a method with selector symbol is in callchain\\\"\\n\\t\\tcntxt := thisContext.\\n\\t\\t[cntxt sender isNil] whileFalse: [\\n\\t\\t\\tcntxt := cntxt sender. \\n\\t\\t\\t(cntxt selector = condition) ifTrue: [Halt signal].\\n\\t\\t\\t].\\n\\t\\t^self.\\n\\t].\\n\\t(condition isBlock \\n\\t\\t\\tifTrue: [condition valueWithPossibleArgument: self] \\n\\t\\t\\tifFalse: [condition] \\n\\t) ifTrue: [\\n\\t\\tHalt signal\\n\\t].! !\\n\\n!Object methodsFor: 'debugging'!\\nneedsWork! !\\n\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:26'!\\ncheckHaltCountExpired\\n\\t| counter |\\n\\tcounter _ Smalltalk at: #HaltCount ifAbsent: [0].\\n\\t^counter = 0! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nclearHaltOnce\\n\\t\\\"Turn on the halt once flag.\\\"\\n\\tSmalltalk at: #HaltOnce put: false! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:30'!\\ndecrementAndCheckHaltCount\\n\\tself decrementHaltCount.\\n\\t^self checkHaltCountExpired! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:28'!\\ndecrementHaltCount\\n\\t| counter |\\n\\tcounter := Smalltalk\\n\\t\\t\\t\\tat: #HaltCount\\n\\t\\t\\t\\tifAbsent: [0].\\n\\tcounter > 0 ifTrue: [\\n\\t\\tcounter _ counter - 1.\\n\\t\\tself setHaltCountTo: counter]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:42'!\\ndoExpiredHaltCount\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself halt! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:44'!\\ndoExpiredHaltCount: aString\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself halt: aString! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:45'!\\ndoExpiredInspectCount\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself inspect! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:43'!\\nhaltOnCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\nhaltOnce\\n\\t\\\"Halt unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self halt]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nhaltOnceEnabled\\n\\t^ Smalltalk\\n\\t\\tat: #HaltOnce\\n\\t\\tifAbsent: [false]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\nhaltOnce: aString \\n\\t\\\"Halt unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self halt: aString]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:45'!\\nhalt: aString onCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount: aString]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount: aString]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:36'!\\nhasHaltCount\\n\\t^Smalltalk\\n\\t\\t\\t\\tincludesKey: #HaltCount! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:46'!\\ninspectOnCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\ninspectOnce\\n\\t\\\"Inspect unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self inspect]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 13:20'!\\ninspectUntilCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self inspect]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:49'!\\nremoveHaltCount\\n\\t(Smalltalk includesKey: #HaltCount) ifTrue: [\\n\\t\\tSmalltalk removeKey: #HaltCount]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:25'!\\nsetHaltCountTo: int\\n\\tSmalltalk at: #HaltCount put: int! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nsetHaltOnce\\n\\t\\\"Turn on the halt once flag.\\\"\\n\\tSmalltalk at: #HaltOnce put: true! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\ntoggleHaltOnce\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce]\\n\\t\\tifFalse: [self setHaltOnce]! !\\n\\n\\n!Object methodsFor: 'dependents access' stamp: 'ar 2/11/2001 01:55'!\\naddDependent: anObject\\n\\t\\\"Make the given object one of the receiver's dependents.\\\"\\n\\n\\t| dependents |\\n\\tdependents _ self dependents.\\n\\t(dependents includes: anObject) ifFalse:\\n\\t\\t[self myDependents: (dependents copyWithDependent: anObject)].\\n\\t^ anObject! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:53'!\\nbreakDependents\\n\\t\\\"Remove all of the receiver's dependents.\\\"\\n\\n\\tself myDependents: nil! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:26'!\\ncanDiscardEdits\\n\\t\\\"Answer true if none of the views on this model has unaccepted edits that matter.\\\"\\n\\n\\tself dependents\\n\\t\\tdo: [:each | each canDiscardEdits ifFalse: [^ false]]\\n\\t\\twithout: self.\\n\\t^ true! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:58'!\\ndependents\\n\\t\\\"Answer a collection of objects that are 'dependent' on the receiver;\\n\\t that is, all objects that should be notified if the receiver changes.\\\"\\n\\n\\t^ self myDependents ifNil: [#()]! !\\n\\n!Object methodsFor: 'dependents access'!\\nevaluate: actionBlock wheneverChangeIn: aspectBlock\\n\\t| viewerThenObject objectThenViewer |\\n\\tobjectThenViewer _ self.\\n\\tviewerThenObject _ ObjectViewer on: objectThenViewer.\\n\\tobjectThenViewer become: viewerThenObject.\\n\\t\\\"--- Then ---\\\"\\n\\tobjectThenViewer xxxViewedObject: viewerThenObject\\n\\t\\t\\tevaluate: actionBlock\\n\\t\\t\\twheneverChangeIn: aspectBlock! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:59'!\\nhasUnacceptedEdits\\n\\t\\\"Answer true if any of the views on this object has unaccepted edits.\\\"\\n\\n\\tself dependents\\n\\t\\tdo: [:each | each hasUnacceptedEdits ifTrue: [^ true]]\\n\\t\\twithout: self.\\n\\t^ false! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:55'!\\nmyDependents\\n\\t\\\"Private. Answer a list of all the receiver's dependents.\\\"\\n\\n\\t^ DependentsFields at: self ifAbsent: []! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:52'!\\nmyDependents: aCollectionOrNil\\n\\t\\\"Private. Set (or remove) the receiver's dependents list.\\\"\\n\\n\\taCollectionOrNil\\n\\t\\tifNil: [DependentsFields removeKey: self ifAbsent: []]\\n\\t\\tifNotNil: [DependentsFields at: self put: aCollectionOrNil]! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'reThink 2/18/2001 17:06'!\\nrelease\\n\\t\\\"Remove references to objects that may refer to the receiver. This message \\n\\tshould be overridden by subclasses with any cycles, in which case the \\n\\tsubclass should also include the expression super release.\\\"\\n\\n\\tself releaseActionMap! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 20:23'!\\nremoveDependent: anObject\\n\\t\\\"Remove the given object as one of the receiver's dependents.\\\"\\n\\n\\t| dependents |\\n\\tdependents _ self dependents reject: [:each | each == anObject].\\n\\tself myDependents: (dependents isEmpty ifFalse: [dependents]).\\n\\t^ anObject! !\\n\\n\\n!Object methodsFor: 'drag and drop' stamp: 'bh 9/16/2001 18:10'!\\nacceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph \\n\\t\\n\\t^false.! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'mir 5/16/2000 11:35'!\\ndragAnimationFor: item transferMorph: transferMorph \\n\\t\\\"Default do nothing\\\"! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:20'!\\ndragPassengerFor: item inMorph: dragSource \\n\\t^item! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:11'!\\ndragTransferType\\n\\t^nil! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:05'!\\ndragTransferTypeForMorph: dragSource \\n\\t^nil! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'mir 5/8/2000 17:19'!\\nwantsDroppedMorph: aMorph event: anEvent inMorph: destinationLM \\n\\t^false! !\\n\\n\\n!Object methodsFor: 'error handling' stamp: 'sma 5/6/2000 19:35'!\\nassert: aBlock\\n\\t\\\"Throw an assertion error if aBlock does not evaluates to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']! !\\n\\n!Object methodsFor: 'error handling' stamp: 'nk 1/15/2004 10:54'!\\nassert: aBlock descriptionBlock: descriptionBlock\\n\\t\\\"Throw an assertion error if aBlock does not evaluate to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: descriptionBlock value asString ]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'nk 10/25/2003 16:47'!\\nassert: aBlock description: aString\\n\\t\\\"Throw an assertion error if aBlock does not evaluates to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: aString ]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 10/13/2004 15:59'!\\nbackwardCompatibilityOnly: anExplanationString\\n\\t\\\"Warn that the sending method has been deprecated. Methods that are tagt with #backwardCompatibility:\\n\\t are kept for compatibility.\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: thisContext sender printString, ' has been deprecated (but will be kept for compatibility). ', anExplanationString]! !\\n\\n!Object methodsFor: 'error handling'!\\ncaseError\\n\\t\\\"Report an error from an in-line or explicit case statement.\\\"\\n\\n\\tself error: 'Case not found, and no otherwise clause'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'rbb 3/1/2005 09:26'!\\nconfirm: queryString\\n\\t\\\"Put up a yes/no menu with caption queryString. Answer true if the \\n\\tresponse is yes, false if no. This is a modal question--the user must \\n\\trespond yes or no.\\\"\\n\\n\\t\\\"nil confirm: 'Are you hungry?'\\\"\\n\\n\\t^ UIManager default confirm: queryString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'rbb 3/1/2005 09:27'!\\nconfirm: aString orCancel: cancelBlock\\n\\t\\\"Put up a yes/no/cancel menu with caption aString. Answer true if \\n\\tthe response is yes, false if no. If cancel is chosen, evaluate \\n\\tcancelBlock. This is a modal question--the user must respond yes or no.\\\"\\n\\n\\t^ UIManager default confirm: aString orCancel: cancelBlock! !\\n\\n!Object methodsFor: 'error handling' stamp: 'dew 10/6/2003 18:20'!\\ndeprecated: anExplanationString\\n\\t\\\"Warn that the sending method has been deprecated.\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: thisContext sender printString, ' has been deprecated. ', anExplanationString]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'dew 10/7/2003 00:26'!\\ndeprecated: anExplanationString block: aBlock \\n\\t \\\"Warn that the sender has been deprecated. Answer the value of aBlock on resumption. (Note that #deprecated: is usually the preferred method.)\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation\\n\\t\\t\\tsignal: thisContext sender printString, ' has been deprecated. ', anExplanationString].\\n\\t^ aBlock value.\\n! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 2/22/2006 21:21'!\\ndoesNotUnderstand: aMessage \\n\\t \\\"Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector).\\\"\\n\\t\\\"Testing: (3 activeProcess)\\\"\\n\\n\\tMessageNotUnderstood new \\n\\t\\tmessage: aMessage;\\n\\t\\treceiver: self;\\n\\t\\tsignal.\\n\\t^ aMessage sentTo: self.\\n! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 16:47'!\\ndpsTrace: reportObject \\n\\tTranscript myDependents isNil ifTrue: [^self].\\n\\tself dpsTrace: reportObject levels: 1 withContext: thisContext\\n\\t\\t\\n\\\" nil dpsTrace: 'sludder'. \\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 16:49'!\\ndpsTrace: reportObject levels: anInt\\n\\tself dpsTrace: reportObject levels: anInt withContext: thisContext\\n\\n\\\"(1 to: 3) do: [:int | nil dpsTrace: int levels: 5.]\\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 17:02'!\\ndpsTrace: reportObject levels: anInt withContext: currentContext\\n\\t| reportString context displayCount |\\n\\treportString := (reportObject respondsTo: #asString) \\n\\t\\t\\tifTrue: [reportObject asString] ifFalse: [reportObject printString].\\n\\t(Smalltalk at: #Decompiler ifAbsent: [nil]) \\n\\tifNil: \\n\\t\\t[Transcript cr; show: reportString]\\n\\tifNotNil:\\n\\t\\t[context := currentContext.\\n\\t\\tdisplayCount := anInt > 1.\\n\\t\\t1 to: anInt do:\\n\\t\\t\\t[:count |\\n\\t\\t\\tTranscript cr.\\n\\t\\t\\tdisplayCount\\n\\t\\t\\t\\tifTrue: [Transcript show: count printString, ': '].\\n\\t\\t\\t\\n\\t\\t\\treportString notNil\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[Transcript show: context home class name \\n\\t\\t\\t, '/' , context sender selector, ' (' , reportString , ')'.\\n\\t\\t\\t\\tcontext := context sender.\\n\\t\\t\\t\\treportString := nil]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[(context notNil and: [(context := context sender) notNil])\\n\\t\\t\\t\\tifTrue: [Transcript show: context receiver class name , '/' , context selector]]].\\n\\t\\t\\\"Transcript cr\\\"].! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 8/2/2005 22:17'!\\nerror\\n\\t\\\"Throw a generic Error exception.\\\"\\n\\n\\t^self error: 'Error!!'.! !\\n\\n!Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:55'!\\nerror: aString \\n\\t\\\"Throw a generic Error exception.\\\"\\n\\n\\t^Error new signal: aString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 9/16/2005 14:12'!\\nexplicitRequirement\\n\\tself error: 'Explicitly required method'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 2/13/2006 22:20'!\\nhalt\\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. It behaves like halt:, but does not call on halt: in order to \\n\\tavoid putting this message on the stack. Halt is especially useful when \\n\\tthe breakpoint message is an arbitrary one.\\\"\\n\\n\\tHalt signal! !\\n\\n!Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:59'!\\nhalt: aString \\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. It creates and schedules a Notifier with the argument, \\n\\taString, as the label.\\\"\\n\\t\\n\\tHalt new signal: aString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 1/20/2006 16:24'!\\nhandles: exception\\n\\t\\\"This method exists in case a non exception class is the first arg in an on:do: (for instance using a exception class that is not loaded). We prefer this to raising an error during error handling itself. Also, semantically it makes sense that the exception handler is not active if its exception class is not loaded\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'error handling' stamp: 'ar 9/27/2005 20:24'!\\nnotifyWithLabel: aString \\n\\t\\\"Create and schedule a Notifier with aString as the window label as well as the contents of the window, in order to request confirmation before a process can proceed.\\\"\\n\\n\\tToolSet\\n\\t\\tdebugContext: thisContext\\n\\t\\tlabel: aString\\n\\t\\tcontents: aString\\n\\n\\t\\\"nil notifyWithLabel: 'let us see if this works'\\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'hg 10/2/2001 20:49'!\\nnotify: aString \\n\\t\\\"Create and schedule a Notifier with the argument as the message in \\n\\torder to request confirmation before a process can proceed.\\\"\\n\\n\\tWarning signal: aString\\n\\n\\t\\\"nil notify: 'confirmation message'\\\"! !\\n\\n!Object methodsFor: 'error handling'!\\nnotify: aString at: location\\n\\t\\\"Create and schedule a Notifier with the argument as the message in \\n\\torder to request confirmation before a process can proceed. Subclasses can\\n\\toverride this and insert an error message at location within aString.\\\"\\n\\n\\tself notify: aString\\n\\n\\t\\\"nil notify: 'confirmation message' at: 12\\\"! !\\n\\n!Object methodsFor: 'error handling'!\\nprimitiveFailed\\n\\t\\\"Announce that a primitive has failed and there is no appropriate \\n\\tSmalltalk code to run.\\\"\\n\\n\\tself error: 'a primitive has failed'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 9/16/2005 14:12'!\\nrequirement\\n\\tself error: 'Implicitly required method'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'AFi 2/8/2003 22:52'!\\nshouldBeImplemented\\n\\t\\\"Announce that this message should be implemented\\\"\\n\\n\\tself error: 'This message should be implemented'! !\\n\\n!Object methodsFor: 'error handling'!\\nshouldNotImplement\\n\\t\\\"Announce that, although the receiver inherits this message, it should \\n\\tnot implement it.\\\"\\n\\n\\tself error: 'This message is not appropriate for this object'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 2/17/2006 12:02'!\\nsubclassResponsibility\\n\\t\\\"This message sets up a framework for the behavior of the class' subclasses.\\n\\tAnnounce that the subclass should have implemented this message.\\\"\\n\\n\\tself error: 'My subclass should have overridden ', thisContext sender selector printString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 12/16/2003 16:16'!\\ntraitConflict\\n\\tself error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.'! !\\n\\n\\n!Object methodsFor: 'evaluating' stamp: 'reThink 3/12/2001 18:14'!\\nvalue\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'evaluating' stamp: 'reThink 2/18/2001 15:23'!\\nvalueWithArguments: aSequenceOfArguments\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'!\\nactionForEvent: anEventSelector\\n \\\"Answer the action to be evaluated when <anEventSelector> has been triggered.\\\"\\n\\n\\t| actions |\\n\\tactions := self actionMap\\n\\t\\tat: anEventSelector asSymbol\\n\\t\\tifAbsent: [nil].\\n\\tactions ifNil: [^nil].\\n\\t^ actions asMinimalRepresentation! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'!\\nactionForEvent: anEventSelector\\nifAbsent: anExceptionBlock\\n \\\"Answer the action to be evaluated when <anEventSelector> has been triggered.\\\"\\n\\n\\t| actions |\\n\\tactions := self actionMap\\n\\t\\tat: anEventSelector asSymbol\\n\\t\\tifAbsent: [nil].\\n\\tactions ifNil: [^anExceptionBlock value].\\n\\t^ actions asMinimalRepresentation! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 14:43'!\\nactionMap\\n\\n\\t^EventManager actionMapFor: self! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'rw 4/27/2002 08:35'!\\nactionSequenceForEvent: anEventSelector\\n\\n ^(self actionMap\\n at: anEventSelector asSymbol\\n ifAbsent: [^WeakActionSequence new])\\n asActionSequence! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'SqR 6/28/2001 13:19'!\\nactionsDo: aBlock\\n\\n\\tself actionMap do: aBlock! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'rw 2/10/2002 13:05'!\\ncreateActionMap\\n\\n\\t^IdentityDictionary new! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'SqR 2/19/2001 14:04'!\\nhasActionForEvent: anEventSelector\\n \\\"Answer true if there is an action associated with anEventSelector\\\"\\n\\n ^(self actionForEvent: anEventSelector) notNil! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 15:29'!\\nsetActionSequence: actionSequence\\nforEvent: anEventSelector\\n\\n | action |\\n action := actionSequence asMinimalRepresentation.\\n action == nil\\n ifTrue:\\n [self removeActionsForEvent: anEventSelector]\\n ifFalse:\\n [self updateableActionMap\\n at: anEventSelector asSymbol\\n put: action]! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/25/2001 08:50'!\\nupdateableActionMap\\n\\n\\t^EventManager updateableActionMapFor: self! !\\n\\n\\n!Object methodsFor: 'events-registering' stamp: 'reThink 2/18/2001 15:04'!\\nwhen: anEventSelector evaluate: anAction \\n\\n\\t| actions |\\n\\tactions := self actionSequenceForEvent: anEventSelector.\\n\\t(actions includes: anAction)\\n\\t\\tifTrue: [^ self].\\n\\tself \\n\\t\\tsetActionSequence: (actions copyWith: anAction)\\n\\t\\tforEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector)! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\nwithArguments: anArgArray\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector\\n\\t\\targuments: anArgArray)! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\nwith: anArg\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector\\n\\t\\targuments: (Array with: anArg))! !\\n\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'!\\nreleaseActionMap\\n\\n\\tEventManager releaseActionMapFor: self! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'!\\nremoveActionsForEvent: anEventSelector\\n\\n | map |\\n map := self actionMap.\\n map removeKey: anEventSelector asSymbol ifAbsent: [].\\n map isEmpty\\n ifTrue: [self releaseActionMap]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'nk 8/25/2003 21:46'!\\nremoveActionsSatisfying: aBlock\\n\\n\\tself actionMap keys do:\\n\\t\\t[:eachEventSelector |\\n\\t\\t\\tself\\n \\t\\t\\t\\tremoveActionsSatisfying: aBlock\\n\\t\\t\\t\\tforEvent: eachEventSelector\\n\\t\\t]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'!\\nremoveActionsSatisfying: aOneArgBlock \\nforEvent: anEventSelector\\n\\n self\\n setActionSequence:\\n ((self actionSequenceForEvent: anEventSelector)\\n reject: [:anAction | aOneArgBlock value: anAction])\\n forEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'rw 7/29/2003 17:18'!\\nremoveActionsWithReceiver: anObject\\n\\n\\tself actionMap copy keysDo:\\n\\t\\t[:eachEventSelector |\\n\\t\\t\\tself\\n \\t\\t\\t\\tremoveActionsSatisfying: [:anAction | anAction receiver == anObject]\\n\\t\\t\\t\\tforEvent: eachEventSelector\\n\\t\\t]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:36'!\\nremoveActionsWithReceiver: anObject\\nforEvent: anEventSelector\\n\\n self\\n removeActionsSatisfying:\\n [:anAction |\\n anAction receiver == anObject]\\n forEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'!\\nremoveAction: anAction\\nforEvent: anEventSelector\\n\\n self\\n removeActionsSatisfying: [:action | action = anAction]\\n forEvent: anEventSelector! !\\n\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:22'!\\ntriggerEvent: anEventSelector\\n\\t\\\"Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action.\\\"\\n\\n ^(self actionForEvent: anEventSelector) value! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 17:09'!\\ntriggerEvent: anEventSelector\\nifNotHandled: anExceptionBlock\\n\\t\\\"Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action.\\\"\\n\\n ^(self \\n\\t\\tactionForEvent: anEventSelector\\n\\t\\tifAbsent: [^anExceptionBlock value]) value\\n! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'!\\ntriggerEvent: anEventSelector\\nwithArguments: anArgumentList\\n\\n ^(self actionForEvent: anEventSelector)\\n valueWithArguments: anArgumentList! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'!\\ntriggerEvent: anEventSelector\\nwithArguments: anArgumentList\\nifNotHandled: anExceptionBlock\\n\\n ^(self \\n\\t\\tactionForEvent: anEventSelector\\n\\t\\tifAbsent: [^anExceptionBlock value])\\n valueWithArguments: anArgumentList! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'!\\ntriggerEvent: anEventSelector\\nwith: anObject\\n\\n ^self \\n\\t\\ttriggerEvent: anEventSelector\\n\\t\\twithArguments: (Array with: anObject)! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'!\\ntriggerEvent: anEventSelector\\nwith: anObject\\nifNotHandled: anExceptionBlock\\n\\n ^self \\n\\t\\ttriggerEvent: anEventSelector\\n\\t\\twithArguments: (Array with: anObject)\\n\\t\\tifNotHandled: anExceptionBlock! !\\n\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:42'!\\nbyteEncode:aStream\\n\\tself flattenOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming'!\\ndrawOnCanvas:aStream\\n\\tself flattenOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:31'!\\nelementSeparator\\n\\t^nil.! !\\n\\n!Object methodsFor: 'filter streaming'!\\nencodePostscriptOn:aStream\\n\\tself byteEncode:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'!\\nflattenOnStream:aStream\\n\\tself writeOnFilterStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'mpw 6/22/1930 22:56'!\\nfullDrawPostscriptOn:aStream\\n\\t^aStream fullDraw:self.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:51'!\\nprintOnStream:aStream\\n\\tself byteEncode:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:49'!\\nputOn:aStream\\n\\t^aStream nextPut:self.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:53'!\\nstoreOnStream:aStream\\n\\tself printOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:06'!\\nwriteOnFilterStream:aStream\\n\\taStream writeObject:self.\\n! !\\n\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:26'!\\nactAsExecutor\\n\\t\\\"Prepare the receiver to act as executor for any resources associated with it\\\"\\n\\tself breakDependents! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/20/98 22:19'!\\nexecutor\\n\\t\\\"Return an object which can act as executor for finalization of the receiver\\\"\\n\\t^self shallowCopy actAsExecutor! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:10'!\\nfinalizationRegistry\\n\\t\\\"Answer the finalization registry associated with the receiver.\\\"\\n\\t^WeakRegistry default! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:27'!\\nfinalize\\n\\t\\\"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority.\\\"! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 18:38'!\\nretryWithGC: execBlock until: testBlock\\n\\t\\\"Retry execBlock as long as testBlock returns false. Do an incremental GC after the first try, a full GC after the second try.\\\"\\n\\t| blockValue |\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollectMost.\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollect.\\n\\t^execBlock value.! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:14'!\\ntoFinalizeSend: aSelector to: aFinalizer with: aResourceHandle\\n\\t\\\"When I am finalized (e.g., garbage collected) close the associated resource handle by sending aSelector to the appropriate finalizer (the guy who knows how to get rid of the resource).\\n\\tWARNING: Neither the finalizer nor the resource handle are allowed to reference me. If they do, then I will NEVER be garbage collected. Since this cannot be validated here, it is up to the client to make sure this invariant is not broken.\\\"\\n\\tself == aFinalizer ifTrue:[self error: 'I cannot finalize myself'].\\n\\tself == aResourceHandle ifTrue:[self error: 'I cannot finalize myself'].\\n\\t^self finalizationRegistry add: self executor:\\n\\t\\t(ObjectFinalizer new\\n\\t\\t\\treceiver: aFinalizer\\n\\t\\t\\tselector: aSelector\\n\\t\\t\\targument: aResourceHandle)! !\\n\\n\\n!Object methodsFor: 'flagging' stamp: 'sw 8/4/97 16:49'!\\nisThisEverCalled\\n\\t^ self isThisEverCalled: thisContext sender printString! !\\n\\n!Object methodsFor: 'flagging'!\\nisThisEverCalled: msg\\n\\t\\\"Send this message, with some useful printable argument, from methods or branches of methods which you believe are never reached. 2/5/96 sw\\\"\\n\\n\\tself halt: 'This is indeed called: ', msg printString! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'!\\nlogEntry\\n\\n\\tTranscript show: 'Entered ', thisContext sender printString; cr.\\n! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'!\\nlogExecution\\n\\n\\tTranscript show: 'Executing ', thisContext sender printString; cr.\\n! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:22'!\\nlogExit\\n\\n\\tTranscript show: 'Exited ', thisContext sender printString; cr.\\n! !\\n\\n\\n!Object methodsFor: 'graph model' stamp: 'dgd 9/18/2004 15:07'!\\naddModelYellowButtonMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph \\n\\t\\\"The receiver serves as the model for aMorph; a menu is being constructed for the morph, and here the receiver is able to add its own items\\\"\\n\\tPreferences cmdGesturesEnabled ifTrue: [ \\\"build mode\\\"\\n\\t\\taCustomMenu add: 'inspect model' translated target: self action: #inspect.\\n\\t].\\n\\n\\t^aCustomMenu\\n! !\\n\\n!Object methodsFor: 'graph model' stamp: 'nk 1/23/2004 14:35'!\\nhasModelYellowButtonMenuItems\\n\\t^Preferences cmdGesturesEnabled! !\\n\\n\\n!Object methodsFor: 'locales' stamp: 'tak 8/4/2005 14:55'!\\nlocaleChanged\\n\\tself shouldBeImplemented! !\\n\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/7/1998 23:00'!\\ncodeStrippedOut: messageString\\n\\t\\\"When a method is stripped out for external release, it is replaced by a method that calls this\\\"\\n\\n\\tself halt: 'Code stripped out -- ', messageString, '-- do not proceed.'! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 1/28/1999 17:31'!\\ncontentsChanged\\n\\tself changed: #contents! !\\n\\n!Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:03'!\\ncurrentEvent\\n\\t\\\"Answer the current Morphic event. This method never returns nil.\\\"\\n\\t^ActiveEvent ifNil:[self currentHand lastEvent]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'nk 9/1/2004 10:41'!\\ncurrentHand\\n\\t\\\"Return a usable HandMorph -- the one associated with the object's current environment. This method will always return a hand, even if it has to conjure one up as a last resort. If a particular hand is actually handling events at the moment (such as a remote hand or a ghost hand), it will be returned.\\\"\\n\\n\\t^ActiveHand ifNil: [ self currentWorld primaryHand ]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/17/2001 12:08'!\\ncurrentVocabulary\\n\\t\\\"Answer the currently-prevailing default vocabulary.\\\"\\n\\n\\t^ Smalltalk isMorphic ifTrue:\\n\\t\\t\\t[ActiveWorld currentVocabulary]\\n\\t\\tifFalse:\\n\\t\\t\\t[Vocabulary fullVocabulary]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:08'!\\ncurrentWorld\\n\\t\\\"Answer a morphic world that is the current UI focus.\\n\\t\\tIf in an embedded world, it's that world.\\n\\t\\tIf in a morphic project, it's that project's world. \\n\\t\\tIf in an mvc project, it is the topmost morphic-mvc-window's worldMorph. \\n\\t\\tIf in an mvc project that has no morphic-mvc-windows, then it's just some existing worldmorph instance.\\n\\t\\tIf in an mvc project in a Squeak that has NO WorldMorph instances, one is created.\\n\\n\\tThis method will never return nil, it will always return its best effort at returning a relevant world morph, but if need be -- if there are no worlds anywhere, it will create a new one.\\\"\\n\\n\\t| aView aSubview |\\n\\tActiveWorld ifNotNil:[^ActiveWorld].\\n\\tWorld ifNotNil:[^World].\\n\\taView _ ScheduledControllers controllerSatisfying:\\n\\t\\t[:ctrl | (aSubview _ ctrl view firstSubView) notNil and:\\n\\t\\t\\t[aSubview model isMorph and: [aSubview model isWorldMorph]]].\\n\\t^aView\\n\\t\\tifNotNil:\\n\\t\\t\\t[aSubview model]\\n\\t\\tifNil:\\n\\t\\t\\t[MVCWiWPasteUpMorph newWorldForProject: nil].! !\\n\\n!Object methodsFor: 'macpal' stamp: 'jm 5/6/1998 22:35'!\\nflash\\n\\t\\\"Do nothing.\\\"\\n! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 6/16/1998 15:07'!\\ninstanceVariableValues\\n\\t\\\"Answer a collection whose elements are the values of those instance variables of the receiver which were added by the receiver's class\\\"\\n\\t| c |\\n\\tc _ OrderedCollection new.\\n\\tself class superclass instSize + 1 to: self class instSize do:\\n\\t\\t[:i | c add: (self instVarAt: i)].\\n\\t^ c! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:29'!\\nisUniversalTiles\\n\\t\\\"Return true if I (my world) uses universal tiles. This message can be called in places where the current World is not known, such as when writing out a project. For more information about the project-writing subtlety addressed by this protocol, kindly contact Ted Kaehler.\\\"\\n\\n\\t^ Preferences universalTiles! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 10/24/2000 07:04'!\\nobjectRepresented\\n\\t\\\"most objects represent themselves; this provides a hook for aliases to grab on to\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/22/2001 18:31'!\\nrefusesToAcceptCode\\n\\t\\\"Answer whether the receiver is a code-bearing instrument which at the moment refuses to allow its contents to be submitted\\\"\\n\\n\\t^ false\\n\\t! !\\n\\n!Object methodsFor: 'macpal' stamp: 'jm 2/24/1999 12:40'!\\nscriptPerformer\\n\\n\\t^ self\\n! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:40'!\\nslotInfo\\n\\t\\\"Answer a list of slot-information objects. Initally only provides useful info for players\\\"\\n\\n\\t^ Dictionary new! !\\n\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nexecuteMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver with no args\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: #() executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol \\n\\t\\\"Send the unary selector, aSymbol, to the receiver.\\n\\tFail if the number of arguments expected by the selector is not zero.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array new: 0)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'sw 10/30/1998 18:27'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"If I wish to intercept and handle selector myself, do it; else send it to otherTarget\\\"\\n\\t^ otherTarget perform: selector! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:55'!\\nperform: selector withArguments: argArray \\n\\t\\\"Send the selector, aSymbol, to the receiver with arguments in argArray.\\n\\tFail if the number of arguments expected by the selector \\n\\tdoes not match the size of argArray.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 84>\\n\\t^ self perform: selector withArguments: argArray inSuperclass: self class! !\\n\\n!Object methodsFor: 'message handling' stamp: 'ar 4/25/2005 13:35'!\\nperform: selector withArguments: argArray inSuperclass: lookupClass\\n\\t\\\"NOTE: This is just like perform:withArguments:, except that\\n\\tthe message lookup process begins, not with the receivers's class,\\n\\tbut with the supplied superclass instead. It will fail if lookupClass\\n\\tcannot be found among the receiver's superclasses.\\n\\tPrimitive. Essential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 100>\\n\\t(selector isSymbol)\\n\\t\\tifFalse: [^ self error: 'selector argument must be a Symbol'].\\n\\t(selector numArgs = argArray size)\\n\\t\\tifFalse: [^ self error: 'incorrect number of arguments'].\\n\\t(self class == lookupClass or: [self class inheritsFrom: lookupClass])\\n\\t\\tifFalse: [^ self error: 'lookupClass is not in my inheritance chain'].\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'message handling' stamp: 'nk 4/11/2002 14:13'!\\nperform: selector withEnoughArguments: anArray\\n\\t\\\"Send the selector, aSymbol, to the receiver with arguments in argArray.\\n\\tOnly use enough arguments for the arity of the selector; supply nils for missing ones.\\\"\\n\\t| numArgs args |\\n\\tnumArgs _ selector numArgs.\\n\\tanArray size == numArgs\\n\\t\\tifTrue: [ ^self perform: selector withArguments: anArray asArray ].\\n\\n\\targs _ Array new: numArgs.\\n\\targs replaceFrom: 1\\n\\t\\tto: (anArray size min: args size)\\n\\t\\twith: anArray\\n\\t\\tstartingAt: 1.\\n\\n\\t^ self perform: selector withArguments: args! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol with: anObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with anObject as its argument.\\n\\tFail if the number of arguments expected by the selector is not one.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array with: anObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol with: firstObject with: secondObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with the given arguments.\\n\\tFail if the number of arguments expected by the selector is not two.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array with: firstObject with: secondObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:51'!\\nperform: aSymbol with: firstObject with: secondObject with: thirdObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with the given arguments.\\n\\tFail if the number of arguments expected by the selector is not three.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol\\n\\t\\twithArguments: (Array with: firstObject with: secondObject with: thirdObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'NS 1/28/2004 11:19'!\\nwithArgs: argArray executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and args in argArray\\\"\\n\\n\\t| selector |\\n\\t<primitive: 188>\\n\\tselector _ Symbol new.\\n\\tself class addSelectorSilently: selector withMethod: compiledMethod.\\n\\t^ [self perform: selector withArguments: argArray]\\n\\t\\tensure: [self class basicRemoveSelector: selector]! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1 & arg2\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 with: arg3 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1, arg2, & arg3\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2. arg3} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 with: arg3 with: arg4 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1, arg2, arg3, & arg4\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2. arg3. arg4} executeMethod: compiledMethod! !\\n\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:46'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"Normally this read-in object is exactly what we want to store. 7/26/96 tk\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'RAA 12/20/2000 16:51'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\t\\\"subclasses should implement if they wish to convert old instances to modern ones\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 11/29/2004 15:04'!\\nfixUponLoad: aProject seg: anImageSegment\\n\\n\\t\\\"change the object due to conventions that have changed on\\n\\nthe project level. (sent to all objects in the incoming project).\\n\\nSpecific classes should reimplement this.\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'RAA 1/10/2001 14:02'!\\nindexIfCompact\\n\\n\\t^0\\t\\t\\\"helps avoid a #respondsTo: in publishing\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 2/24/1999 11:08'!\\nobjectForDataStream: refStrm\\n \\\"Return an object to store on an external data stream.\\\"\\n\\n ^ self! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:05'!\\nreadDataFrom: aDataStream size: varsOnDisk\\n\\t\\\"Fill in the fields of self based on the contents of aDataStream. Return self.\\n\\t Read in the instance-variables written by Object>>storeDataOn:.\\n\\t NOTE: This method must send beginReference: before reading any objects from aDataStream that might reference it.\\n\\t Allow aDataStream to have fewer inst vars. See SmartRefStream.\\\"\\n\\t| cntInstVars cntIndexedVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\tself class isVariable\\n\\t\\tifTrue: [cntIndexedVars _ varsOnDisk - cntInstVars.\\n\\t\\t\\t\\tcntIndexedVars < 0 ifTrue: [\\n\\t\\t\\t\\t\\tself error: 'Class has changed too much. Define a convertxxx method']]\\n\\t\\tifFalse: [cntIndexedVars _ 0.\\n\\t\\t\\t\\tcntInstVars _ varsOnDisk]. \\t\\\"OK if fewer than now\\\"\\n\\n\\taDataStream beginReference: self.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | self instVarAt: i put: aDataStream next].\\n\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | self basicAt: i put: aDataStream next].\\n\\t\\\"Total number read MUST be equal to varsOnDisk!!\\\"\\n\\t^ self\\t\\\"If we ever return something other than self, fix calls \\n\\t\\t\\ton (super readDataFrom: aDataStream size: anInteger)\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'CdG 10/17/2005 20:32'!\\nsaveOnFile\\n\\t\\\"Ask the user for a filename and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. Does not file out the class of the object. tk 6/26/97 13:48\\\"\\n\\n\\t| aFileName fileStream |\\n\\taFileName := self class name asFileName.\\t\\\"do better?\\\"\\n\\taFileName := UIManager default \\n\\t\\t\\t\\trequest: 'File name?' translated initialAnswer: aFileName.\\n\\taFileName size == 0 ifTrue: [^ Beeper beep].\\n\\n\\tfileStream := FileStream newFileNamed: aFileName asFileName.\\n\\tfileStream fileOutClass: nil andObject: self.! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 8/9/2001 15:40'!\\nstoreDataOn: aDataStream\\n\\t\\\"Store myself on a DataStream. Answer self. This is a low-level DataStream/ReferenceStream method. See also objectToStoreOnDataStream. NOTE: This method must send 'aDataStream beginInstance:size:' and then (nextPut:/nextPutWeak:) its subobjects. readDataFrom:size: reads back what we write here.\\\"\\n\\t| cntInstVars cntIndexedVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\tcntIndexedVars _ self basicSize.\\n\\taDataStream\\n\\t\\tbeginInstance: self class\\n\\t\\tsize: cntInstVars + cntIndexedVars.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\n\\t\\\"Write fields of a variable length object. When writing to a dummy \\n\\t\\tstream, don't bother to write the bytes\\\"\\n\\t((aDataStream byteStream class == DummyStream) and: [self class isBits]) ifFalse: [\\n\\t\\t1 to: cntIndexedVars do:\\n\\t\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]].\\n! !\\n\\n\\n!Object methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:34'!\\ndescriptionForPartsBin\\n\\t\\\"If the receiver is a member of a class that would like to be represented in a parts bin, answer the name by which it should be known, and a documentation string to be provided, for example, as balloon help. When the 'nativitySelector' is sent to the 'globalReceiver', it is expected that some kind of Morph will result. The parameters used in the implementation below are for documentation purposes only!!\\\"\\n\\n\\t^ DescriptionForPartsBin\\n\\t\\tformalName: 'PutFormalNameHere'\\n\\t\\tcategoryList: #(PutACategoryHere MaybePutAnotherCategoryHere)\\n\\t\\tdocumentation: 'Put the balloon help here'\\n\\t\\tglobalReceiverSymbol: #PutAGlobalHere\\n\\t\\tnativitySelector: #PutASelectorHere! !\\n\\n\\n!Object methodsFor: 'printing' stamp: 'di 6/20/97 08:57'!\\nfullPrintString\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\n\\t^ String streamContents: [:s | self printOn: s]! !\\n\\n!Object methodsFor: 'printing'!\\nisLiteral\\n\\t\\\"Answer whether the receiver has a literal text form recognized by the \\n\\tcompiler.\\\"\\n\\n\\t^false! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:28'!\\nlongPrintOn: aStream\\n\\t\\\"Append to the argument, aStream, the names and values of all \\n\\tof the receiver's instance variables.\\\"\\n\\n\\tself class allInstVarNames doWithIndex:\\n\\t\\t[:title :index |\\n\\t\\taStream nextPutAll: title;\\n\\t\\t nextPut: $:;\\n\\t\\t space;\\n\\t\\t tab;\\n\\t\\t print: (self instVarAt: index);\\n\\t\\t cr]! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 10/19/2001 11:18'!\\nlongPrintOn: aStream limitedTo: sizeLimit indent: indent\\n\\t\\\"Append to the argument, aStream, the names and values of all of the receiver's instance variables. Limit is the length limit for each inst var.\\\"\\n\\n\\tself class allInstVarNames doWithIndex:\\n\\t\\t[:title :index |\\n\\t\\tindent timesRepeat: [aStream tab].\\n\\t\\taStream nextPutAll: title;\\n\\t\\t nextPut: $:;\\n\\t\\t space;\\n\\t\\t tab;\\n\\t\\t nextPutAll: \\n\\t\\t\\t((self instVarAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1));\\n\\t\\t cr]! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 10/16/2001 19:41'!\\nlongPrintString\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\t\\n\\t| str |\\n\\tstr _ String streamContents: [:aStream | self longPrintOn: aStream].\\n\\t\\\"Objects without inst vars should return something\\\"\\n\\t^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! !\\n\\n!Object methodsFor: 'printing' stamp: 'BG 11/7/2004 13:39'!\\nlongPrintStringLimitedTo: aLimitValue\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\t\\n\\t| str |\\n\\tstr _ String streamContents: [:aStream | self longPrintOn: aStream limitedTo: aLimitValue indent: 0].\\n\\t\\\"Objects without inst vars should return something\\\"\\n\\t^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 3/7/2001 13:14'!\\nnominallyUnsent: aSelectorSymbol\\n\\t\\\"From within the body of a method which is not formally sent within the system, but which you intend to have remain in the system (for potential manual invocation, or for documentation, or perhaps because it's sent by commented-out-code that you anticipate uncommenting out someday, send this message, with the selector itself as the argument.\\n\\nThis will serve two purposes:\\n\\n\\t(1) The method will not be returned by searches for unsent selectors (because it, in a manner of speaking, sends itself).\\n\\t(2)\\tYou can locate all such methods by browsing senders of #nominallyUnsent:\\\"\\n\\n\\tfalse ifTrue: [self flag: #nominallyUnsent:] \\\"So that this method itself will appear to be sent\\\"\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:31'!\\nprintOn: aStream\\n\\t\\\"Append to the argument, aStream, a sequence of characters that \\n\\tidentifies the receiver.\\\"\\n\\n\\t| title |\\n\\ttitle _ self class name.\\n\\taStream\\n\\t\\tnextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']);\\n\\t\\tnextPutAll: title! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:22'!\\nprintString\\n\\t\\\"Answer a String whose characters are a description of the receiver. \\n\\tIf you want to print without a character limit, use fullPrintString.\\\"\\n\\n\\t^ self printStringLimitedTo: 50000! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 5/7/1999 16:20'!\\nprintStringLimitedTo: limit\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\n\\tIf you want to print without a character limit, use fullPrintString.\\\"\\n\\t| limitedString |\\n\\tlimitedString _ String streamContents: [:s | self printOn: s] limitedTo: limit.\\n\\tlimitedString size < limit ifTrue: [^ limitedString].\\n\\t^ limitedString , '...etc...'! !\\n\\n!Object methodsFor: 'printing' stamp: 'MPW 1/1/1901 00:30'!\\npropertyList\\n\\t\\\"Answer a String whose characters are a property-list description of the receiver.\\\"\\n\\n\\t^ PropertyListEncoder process:self.\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 10/17/2000 11:16'!\\nreportableSize\\n\\t\\\"Answer a string that reports the size of the receiver -- useful for showing in a list view, for example\\\"\\n\\n\\t^ (self basicSize + self class instSize) printString! !\\n\\n!Object methodsFor: 'printing'!\\nstoreOn: aStream \\n\\t\\\"Append to the argument aStream a sequence of characters that is an \\n\\texpression whose evaluation creates an object similar to the receiver.\\\"\\n\\n\\taStream nextPut: $(.\\n\\tself class isVariable\\n\\t\\tifTrue: [aStream nextPutAll: '(', self class name, ' basicNew: ';\\n\\t\\t\\t\\t\\tstore: self basicSize;\\n\\t\\t\\t\\t\\tnextPutAll: ') ']\\n\\t\\tifFalse: [aStream nextPutAll: self class name, ' basicNew'].\\n\\t1 to: self class instSize do:\\n\\t\\t[:i |\\n\\t\\taStream nextPutAll: ' instVarAt: ';\\n\\t\\t\\tstore: i;\\n\\t\\t\\tnextPutAll: ' put: ';\\n\\t\\t\\tstore: (self instVarAt: i);\\n\\t\\t\\tnextPut: $;].\\n\\t1 to: self basicSize do:\\n\\t\\t[:i |\\n\\t\\taStream nextPutAll: ' basicAt: ';\\n\\t\\t\\tstore: i;\\n\\t\\t\\tnextPutAll: ' put: ';\\n\\t\\t\\tstore: (self basicAt: i);\\n\\t\\t\\tnextPut: $;].\\n\\taStream nextPutAll: ' yourself)'\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'di 6/20/97 09:12'!\\nstoreString\\n\\t\\\"Answer a String representation of the receiver from which the receiver \\n\\tcan be reconstructed.\\\"\\n\\n\\t^ String streamContents: [:s | self storeOn: s]! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 5/2/1998 13:55'!\\nstringForReadout\\n\\t^ self stringRepresentation! !\\n\\n!Object methodsFor: 'printing'!\\nstringRepresentation\\n\\t\\\"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\\\"\\n\\n\\t^ self printString ! !\\n\\n\\n!Object methodsFor: 'scripting' stamp: 'ar 3/17/2001 20:11'!\\nadaptedToWorld: aWorld\\n\\t\\\"If I refer to a world or a hand, return the corresponding items in the new world.\\\"\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 3/10/2000 13:57'!\\ndefaultFloatPrecisionFor: aGetSelector\\n\\t\\\"Answer a number indicating the default float precision to be used in a numeric readout for which the receiver is the model.\\\"\\n\\n\\t^ 1! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 3/9/2001 17:08'!\\nevaluateUnloggedForSelf: aCodeString\\n\\n\\t^Compiler evaluate:\\n\\t\\taCodeString\\n\\t\\tfor: self\\n\\t\\tlogged: false! !\\n\\n!Object methodsFor: 'scripting' stamp: 'yo 12/25/2003 16:43'!\\nmethodInterfacesForCategory: aCategorySymbol inVocabulary: aVocabulary limitClass: aLimitClass\\n\\t\\\"Return a list of methodInterfaces for the receiver in the given category, given a vocabulary. aCategorySymbol is the inherent category symbol, not necessarily the wording as expressed in the vocabulary.\\\"\\n\\n\\t| categorySymbol |\\n\\tcategorySymbol _ aCategorySymbol asSymbol.\\n\\n\\t(categorySymbol == ScriptingSystem nameForInstanceVariablesCategory) ifTrue: [\\n\\t\\t\\\"user-defined instance variables\\\"\\n\\t\\t^ self methodInterfacesForInstanceVariablesCategoryIn: aVocabulary].\\n\\t(categorySymbol == ScriptingSystem nameForScriptsCategory) ifTrue: [\\n\\t\\t\\\"user-defined scripts\\\"\\n\\t\\t^ self methodInterfacesForScriptsCategoryIn: aVocabulary].\\n\\t\\\"all others\\\"\\n\\t^ self usableMethodInterfacesIn: (aVocabulary methodInterfacesInCategory: categorySymbol\\n\\t\\tforInstance: self\\n\\t\\tofClass: self class\\n\\t\\tlimitClass: aLimitClass)\\n! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:54'!\\nmethodInterfacesForInstanceVariablesCategoryIn: aVocabulary\\n\\t\\\"Return a collection of methodInterfaces for the instance-variables category. The vocabulary parameter, at present anyway, is not used. And for non-players, the method is at present vacuous in any case\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:53'!\\nmethodInterfacesForScriptsCategoryIn: aVocabulary\\n\\t\\\"Answer a list of method interfaces for the category #scripts, as seen in a viewer or other tool. The vocabulary argument is not presently used. Also, at present, only Players really do anyting interesting here.\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsIll\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'!\\nselfWrittenAsIm\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsMe\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsMy\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'!\\nselfWrittenAsThis\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'self evaluating' stamp: 'sd 7/31/2005 21:47'!\\nisSelfEvaluating\\n\\t^ self isLiteral! !\\n\\n\\n!Object methodsFor: 'system primitives'!\\nasOop\\n\\t\\\"Primitive. Answer a SmallInteger whose value is half of the receiver's \\n\\tobject pointer (interpreting object pointers as 16-bit signed quantities). \\n\\tFail if the receiver is a SmallInteger. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 75>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'di 1/9/1999 15:19'!\\nbecomeForward: otherObject \\n\\t\\\"Primitive. All variables in the entire system that used to point\\n\\tto the receiver now point to the argument.\\n\\tFails if either argument is a SmallInteger.\\\"\\n\\n\\t(Array with: self)\\n\\t\\telementsForwardIdentityTo:\\n\\t\\t\\t(Array with: otherObject)! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'zz 3/3/2004 23:53'!\\nbecomeForward: otherObject copyHash: copyHash\\n\\t\\\"Primitive. All variables in the entire system that used to point to the receiver now point to the argument.\\n\\tIf copyHash is true, the argument's identity hash bits will be set to those of the receiver.\\n\\tFails if either argument is a SmallInteger.\\\"\\n\\n\\t(Array with: self)\\n\\t\\telementsForwardIdentityTo:\\n\\t\\t\\t(Array with: otherObject)\\n\\t\\t\\t\\tcopyHash: copyHash! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 10:59'!\\nclassName\\n\\t\\\"Answer a string characterizing the receiver's class, for use in list views for example\\\"\\n\\n\\t^ self class name asString! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:04'!\\ncreationStamp\\n\\t\\\"Answer a string which reports the creation particulars of the receiver. Intended perhaps for list views, but this is presently a feature not easily accessible\\\"\\n\\n\\t^ '<no creation stamp>'! !\\n\\n!Object methodsFor: 'system primitives'!\\ninstVarAt: index \\n\\t\\\"Primitive. Answer a fixed variable in an object. The numbering of the \\n\\tvariables corresponds to the named instance variables. Fail if the index \\n\\tis not an Integer or is not the index of a fixed variable. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 73>\\n\\t\\\"Access beyond fixed variables.\\\"\\n\\t^self basicAt: index - self class instSize\\t\\t! !\\n\\n!Object methodsFor: 'system primitives'!\\ninstVarAt: anInteger put: anObject \\n\\t\\\"Primitive. Store a value into a fixed variable in the receiver. The \\n\\tnumbering of the variables corresponds to the named instance variables. \\n\\tFail if the index is not an Integer or is not the index of a fixed variable. \\n\\tAnswer the value stored as the result. Using this message violates the \\n\\tprinciple that each object has sovereign control over the storing of \\n\\tvalues into its instance variables. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 74>\\n\\t\\\"Access beyond fixed fields\\\"\\n\\t^self basicAt: anInteger - self class instSize put: anObject! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:09'!\\ninstVarNamed: aString\\n\\t\\\"Return the value of the instance variable in me with that name. Slow and unclean, but very useful. \\\"\\n\\n\\t^ self instVarAt: (self class allInstVarNames indexOf: aString asString)\\n\\n\\n! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:10'!\\ninstVarNamed: aString put: aValue\\n\\t\\\"Store into the value of the instance variable in me of that name. Slow and unclean, but very useful. \\\"\\n\\n\\t^ self instVarAt: (self class allInstVarNames indexOf: aString asString) put: aValue\\n! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/17/2000 11:12'!\\noopString\\n\\t\\\"Answer a string that represents the oop of the receiver\\\"\\n\\n\\t^ self asOop printString! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'ar 3/2/2001 01:34'!\\nprimitiveChangeClassTo: anObject\\n\\t\\\"Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have.\\n\\tNote: The primitive will fail in most cases that you think might work. This is mostly because of a) the difference between compact and non-compact classes, and b) because of differences in the format. As an example, '(Array new: 3) primitiveChangeClassTo: Morph basicNew' would fail for three of the reasons mentioned above. Array is compact, Morph is not (failure #1). Array is variable and Morph is fixed (different format - failure #2). Morph is a fixed-field-only object and the array is too short (failure #3).\\n\\tThe facility is really provided for certain, very specific applications (mostly related to classes changing shape) and not for casual use.\\\"\\n\\n\\t<primitive: 115>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'di 3/27/1999 12:21'!\\nrootStubInImageSegment: imageSegment\\n\\n\\t^ ImageSegmentRootStub new\\n\\t\\txxSuperclass: nil\\n\\t\\tformat: nil\\n\\t\\tsegment: imageSegment! !\\n\\n!Object methodsFor: 'system primitives'!\\nsomeObject\\n\\t\\\"Primitive. Answer the first object in the enumeration of all\\n\\t objects.\\\"\\n\\n\\t<primitive: 138>\\n\\tself primitiveFailed.! !\\n\\n\\n!Object methodsFor: 'testing' stamp: 'sw 9/26/2001 11:58'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t^ #Object! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 5/3/2001 16:19'!\\nbeViewed\\n\\t\\\"Open up a viewer on the receiver. The Presenter is invited to decide just how to present this viewer\\\"\\n\\n\\tself uniqueNameForReference. \\\"So the viewer will have something nice to refer to\\\"\\n\\tself presenter viewObject: self! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/16/2000 11:01'!\\ncostumes\\n\\t\\\"Answer a list of costumes associated with the receiver. The appearance of this method in class Object serves only as a backstop, probably only transitionally\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/12/98 18:09'!\\nhaltIfNil! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 1/20/2006 17:09'!\\nhasLiteralSuchThat: testBlock\\n\\t\\\"This is the end of the imbedded structure path so return false.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 1/20/2006 17:10'!\\nhasLiteralThorough: literal\\n\\t\\\"Answer true if literal is identical to any literal in this array, even if imbedded in further structures. This is the end of the imbedded structure path so return false.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/30/2001 22:24'!\\nhaveFullProtocolBrowsed\\n\\t\\\"Open up a Lexicon on the receiver\\\"\\n\\n\\t^ self haveFullProtocolBrowsedShowingSelector: nil\\n\\n\\t\\\"(2@3) haveFullProtocolBrowsed\\\"\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 9/27/2005 21:04'!\\nhaveFullProtocolBrowsedShowingSelector: aSelector\\n\\t\\\"Open up a Lexicon on the receiver, having it open up showing aSelector, which may be nil\\\"\\n\\n\\t| aBrowser |\\n\\taBrowser := (Smalltalk at: #InstanceBrowser ifAbsent:[^nil]) new useVocabulary: Vocabulary fullVocabulary.\\n\\taBrowser openOnObject: self inWorld: ActiveWorld showingSelector: aSelector\\n\\n\\t\\\"(2@3) haveFullProtocolBrowsed\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 7/30/2005 21:21'!\\nisArray\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 7/9/1999 18:18'!\\nisBehavior\\n\\t\\\"Return true if the receiver is a behavior.\\n\\tNote: Do not override in any class except behavior.\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ajh 1/21/2003 13:15'!\\nisBlock\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'!\\nisBlockClosure\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'yo 8/28/2002 13:41'!\\nisCharacter\\n\\n\\t^ false.\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 8/17/1999 19:43'!\\nisCollection\\n\\t\\\"Return true if the receiver is some sort of Collection and responds to basic collection messages such as #size and #do:\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing'!\\nisColor\\n\\t\\\"Answer true if receiver is a Color. False by default.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 4/17/2004 19:43'!\\nisColorForm\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'!\\nisCompiledMethod\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'mk 10/27/2003 17:33'!\\nisComplex\\n\\t\\\"Answer true if receiver is a Complex number. False by default.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 8/11/2005 16:45'!\\nisDictionary\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 11/9/1998 09:38'!\\nisFloat\\n\\t\\\"Overridden to return true in Float, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 10/30/2000 23:22'!\\nisForm\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'len 1/13/98 21:18'!\\nisFraction\\n\\t\\\"Answer true if the receiver is a Fraction.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'rhi 8/14/2003 08:51'!\\nisHeap\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing'!\\nisInteger\\n\\t\\\"Overridden to return true in Integer.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'rhi 8/12/2003 09:52'!\\nisInterval\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 4/25/2002 08:04'!\\nisMessageSend\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!\\nisMethodProperties\\n\\t^false! !\\n\\n!Object methodsFor: 'testing'!\\nisMorph\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 9/13/2000 15:37'!\\nisMorphicEvent\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'gm 2/22/2003 12:56'!\\nisMorphicModel\\n\\t\\\"Return true if the receiver is a morphic model\\\"\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing'!\\nisNumber\\n\\t\\\"Overridden to return true in Number, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 11/6/1998 08:04'!\\nisPoint\\n\\t\\\"Overridden to return true in Point.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ikp 9/26/97 14:45'!\\nisPseudoContext\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 10/2/2005 21:52'!\\nisRectangle\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 6/14/2004 16:49'!\\nisSketchMorph\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'!\\nisStream\\n\\t\\\"Return true if the receiver responds to the stream protocol\\\"\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'sma 6/15/2000 15:48'!\\nisString\\n\\t\\\"Overridden to return true in String, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 4/30/2003 15:30'!\\nisSymbol\\n\\t^ false ! !\\n\\n!Object methodsFor: 'testing' stamp: 'jam 3/9/2003 15:10'!\\nisSystemWindow\\n\\\"answer whatever the receiver is a SystemWindow\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing'!\\nisText\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'pmm 7/6/2006 20:46'!\\nisTrait\\n\\t\\\"Return true if the receiver is a trait.\\n\\tNote: Do not override in any class except TraitBehavior.\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 10/21/97 12:45'!\\nisTransparent\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 8/14/2001 23:19'!\\nisVariableBinding\\n\\t\\\"Return true if I represent a literal variable binding\\\"\\n\\t^false\\n\\t! !\\n\\n!Object methodsFor: 'testing' stamp: 'ls 7/14/1998 21:45'!\\nisWebBrowser\\n\\t\\\"whether this object is a web browser. See class: Scamper\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/27/2000 06:58'!\\nknownName\\n\\t\\\"If a formal name has been handed out for this object, answer it, else nil\\\"\\n\\t\\n\\t^ Preferences capitalizedReferences\\n\\t\\tifTrue:\\n\\t\\t\\t[References keyAtValue: self ifAbsent: [nil]]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 9/27/96'!\\nname\\n\\t\\\"Answer a name for the receiver. This is used generically in the title of certain inspectors, such as the referred-to inspector, and specificially by various subsystems. By default, we let the object just print itself out.. \\\"\\n\\n\\t^ self printString! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 11/19/2001 13:28'!\\nnameForViewer\\n\\t\\\"Answer a name to be shown in a Viewer that is viewing the receiver\\\"\\n\\n\\t| aName |\\n\\t(aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName].\\n\\t(aName _ self knownName) ifNotNil: [^ aName].\\n\\n\\t^ [(self asString copyWithout: Character cr) truncateTo: 27] ifError:\\n\\t\\t[:msg :rcvr | ^ self class name printString]! !\\n\\n!Object methodsFor: 'testing'!\\nnotNil\\n\\t\\\"Coerces nil to false and everything else to true.\\\"\\n\\n\\t^true! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 9/6/2001 19:15'!\\nopenInstanceBrowserWithTiles\\n\\t\\\"Open up an instance browser on me with tiles as the code type, and with the search level as desired.\\\"\\n\\n\\t| aBrowser |\\n\\taBrowser _ InstanceBrowser new.\\n\\taBrowser useVocabulary: Vocabulary fullVocabulary.\\n\\taBrowser limitClass: self class.\\n\\taBrowser contentsSymbol: #tiles.\\t\\t\\\"preset it to make extra buttons (tile menus)\\\"\\n\\taBrowser openOnObject: self inWorld: ActiveWorld showingSelector: nil.\\n\\taBrowser contentsSymbol: #source.\\n\\taBrowser toggleShowingTiles.\\n\\n\\t\\\"\\n(2@3) openInstanceBrowserWithTiles.\\nWatchMorph new openInstanceBrowserWithTiles\\n\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 7/28/2005 04:50'!\\nrenameInternal: newName \\n\\t\\\"Change the internal name (because of a conflict) but leave the external name unchanged. Change Player class name, but do not change the names that appear in tiles. Any object that might be pointed to in the References dictionary might get this message sent to it upon reload\\\"\\n\\n\\t^ nil\\t\\\"caller will renameTo:. new name may be different\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 2/27/2002 14:55'!\\nrenameTo: newName\\n\\t\\\"If the receiver has an inherent idea about its own name, it should take action here. Any object that might be pointed to in the References dictionary might get this message sent to it upon reload\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/18/2001 13:43'!\\nshowDiffs\\n\\t\\\"Answer whether the receiver, serving as the model of a text-bearing entity, is 'showing differences' -- if it is, the editor may wish to show special feedback\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/20/1999 14:52'!\\nstepAt: millisecondClockValue in: aWindow\\n\\n\\t^ self stepIn: aWindow! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:16'!\\nstepIn: aWindow\\n\\n\\t^ self step! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:21'!\\nstepTime\\n\\t\\n\\t^ 1000 \\\"milliseconds -- default backstop for objects serving as models of system windows\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:22'!\\nstepTimeIn: aSystemWindow\\n\\t\\n\\t^ 1000 \\\"milliseconds -- default backstop for objects serving as models of system windows\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 5/3/2001 18:22'!\\nvocabularyDemanded\\n\\t\\\"Answer a vocabulary that the receiver insists be used when it is looked at in a Viewer. This allows specific classes to insist on specific custom vocabularies\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 11/13/2001 07:26'!\\nwantsDiffFeedback\\n\\t\\\"Answer whether the receiver, serving as the model of a text-bearing entity, would like for 'diffs' green pane-border feedback to be shown\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 1/8/1999 15:04'!\\nwantsSteps\\n\\t\\\"Overridden by morphic classes whose instances want to be stepped,\\n\\tor by model classes who want their morphic views to be stepped.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:26'!\\nwantsStepsIn: aSystemWindow\\n\\t\\n\\t^ self wantsSteps! !\\n\\n\\n!Object methodsFor: 'translation support'!\\ninline: inlineFlag\\n\\t\\\"For translation only; noop when running in Smalltalk.\\\"! !\\n\\n!Object methodsFor: 'translation support'!\\nvar: varSymbol declareC: declString\\n\\t\\\"For translation only; noop when running in Smalltalk.\\\"! !\\n\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'!\\ncapturedState\\n\\t\\\"May be overridden in subclasses.\\\"\\n\\n\\t^ self shallowCopy\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:29'!\\ncommandHistory\\n\\t\\\"Return the command history for the receiver\\\"\\n\\t| w |\\n\\t(w _ self currentWorld) ifNotNil: [^ w commandHistory].\\n\\t^ CommandHistory new. \\\"won't really record anything but prevent breaking things\\\"! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 12/12/2000 15:01'!\\npurgeAllCommands\\n\\t\\\"Purge all commands for this object\\\"\\n\\tPreferences useUndo ifFalse: [^ self]. \\\"get out quickly\\\"\\n\\tself commandHistory purgeAllCommandsSuchThat: [:cmd | cmd undoTarget == self].\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/12/2000 08:15'!\\nredoFromCapturedState: st \\n\\t\\\"May be overridden in subclasses. See also capturedState\\\"\\n\\n\\tself undoFromCapturedState: st \\\"Simple cases are symmetric\\\"\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'!\\nrefineRedoTarget: target selector: aSymbol arguments: arguments in: refineBlock \\n\\t\\\"Any object can override this method to refine its redo specification\\\"\\n\\n\\t^ refineBlock\\n\\t\\tvalue: target\\n\\t\\tvalue: aSymbol\\n\\t\\tvalue: arguments! !\\n\\n!Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'!\\nrefineUndoTarget: target selector: aSymbol arguments: arguments in: refineBlock \\n\\t\\\"Any object can override this method to refine its undo specification\\\"\\n\\n\\t^ refineBlock\\n\\t\\tvalue: target\\n\\t\\tvalue: aSymbol\\n\\t\\tvalue: arguments! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:30'!\\nrememberCommand: aCommand\\n\\t\\\"Remember the given command for undo\\\"\\n\\tPreferences useUndo ifFalse: [^ self]. \\\"get out quickly\\\"\\n\\t^ self commandHistory rememberCommand: aCommand! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:30'!\\nrememberUndoableAction: actionBlock named: caption\\n\\t| cmd result |\\n\\tcmd _ Command new cmdWording: caption.\\n\\tcmd undoTarget: self selector: #undoFromCapturedState: argument: self capturedState.\\n\\tresult _ actionBlock value.\\n\\tcmd redoTarget: self selector: #redoFromCapturedState: argument: self capturedState.\\n\\tself rememberCommand: cmd.\\n\\t^ result! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'!\\nundoFromCapturedState: st \\n\\t\\\"May be overridden in subclasses. See also capturedState\\\"\\n\\n\\tself copyFrom: st\\n! !\\n\\n\\n!Object methodsFor: 'updating'!\\nchanged\\n\\t\\\"Receiver changed in a general way; inform all the dependents by \\n\\tsending each dependent an update: message.\\\"\\n\\n\\tself changed: self! !\\n\\n!Object methodsFor: 'updating'!\\nchanged: aParameter \\n\\t\\\"Receiver changed. The change is denoted by the argument aParameter. \\n\\tUsually the argument is a Symbol that is part of the dependent's change \\n\\tprotocol. Inform all of the dependents.\\\"\\n\\n\\tself dependents do: [:aDependent | aDependent update: aParameter]! !\\n\\n!Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:12'!\\nchanged: anAspect with: anObject\\n\\t\\\"Receiver changed. The change is denoted by the argument anAspect. \\n\\tUsually the argument is a Symbol that is part of the dependent's change \\n\\tprotocol. Inform all of the dependents. Also pass anObject for additional information.\\\"\\n\\n\\tself dependents do: [:aDependent | aDependent update: anAspect with: anObject]! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/12/1999 18:15'!\\nhandledListVerification\\n\\t\\\"When a self-updating PluggableListMorph lazily checks to see the state of affairs, it first gives its model an opportunity to handle the list verification itself (this is appropriate for some models, such as VersionsBrowser); if a list's model has indeed handled things itself, it returns true here\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/31/1999 00:15'!\\nnoteSelectionIndex: anInteger for: aSymbol\\n\\t\\\"backstop\\\"! !\\n\\n!Object methodsFor: 'updating'!\\nokToChange\\n\\t\\\"Allows a controller to ask this of any model\\\"\\n\\t^ true! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/19/1999 14:39'!\\nupdateListsAndCodeIn: aWindow\\n\\tself canDiscardEdits ifFalse: [^ self].\\n\\taWindow updatablePanes do: [:aPane | aPane verifyContents]! !\\n\\n!Object methodsFor: 'updating' stamp: 'sma 2/29/2000 20:05'!\\nupdate: aParameter \\n\\t\\\"Receive a change notice from an object of whom the receiver is a \\n\\tdependent. The default behavior is to do nothing; a subclass might want \\n\\tto change itself in some way.\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:13'!\\nupdate: anAspect with: anObject\\n\\t\\\"Receive a change notice from an object of whom the receiver is a \\n\\tdependent. The default behavior is to call update:,\\n\\twhich by default does nothing; a subclass might want \\n\\tto change itself in some way.\\\"\\n\\n\\t^ self update: anAspect! !\\n\\n!Object methodsFor: 'updating' stamp: 'jm 8/20/1998 18:26'!\\nwindowIsClosing\\n\\t\\\"This message is used to inform a models that its window is closing. Most models do nothing, but some, such as the Debugger, must do some cleanup. Note that this mechanism must be used with care by models that support multiple views, since one view may be closed while others left open.\\\"\\n! !\\n\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/4/1999 08:13'!\\naddModelItemsToWindowMenu: aMenu\\n\\t\\\"aMenu is being constructed to be presented to the user in response to the user's pressing on the menu widget in the title bar of a morphic window. Here, the model is given the opportunity to add any model-specific items to the menu, whose default target is the SystemWindow itself.\\\"! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/5/1998 14:39'!\\naddModelMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph \\n\\t\\\"The receiver serves as the model for aMorph; a menu is being constructed for the morph, and here the receiver is able to add its own items\\\"\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:43'!\\nasExplorerString\\n\\t^ self printString! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 7/13/1999 15:53'!\\ndefaultBackgroundColor\\n\\t\\\"Answer the color to be used as the base window color for a window whose model is an object of the receiver's class\\\"\\n\\t\\n\\t^ Preferences windowColorFor: self class name! !\\n\\n!Object methodsFor: 'user interface'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\n\\t^ self class name! !\\n\\n!Object methodsFor: 'user interface' stamp: 'RAA 7/10/2000 08:11'!\\neToyStreamedRepresentationNotifying: aWidget\\n\\n\\t| outData |\\n\\t[ outData _ SmartRefStream streamedRepresentationOf: self ] \\n\\t\\ton: ProgressInitiationException\\n\\t\\tdo: [ :ex | \\n\\t\\t\\tex sendNotificationsTo: [ :min :max :curr |\\n\\t\\t\\t\\taWidget ifNotNil: [aWidget flashIndicator: #working].\\n\\t\\t\\t].\\n\\t\\t].\\n\\t^outData\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:29'!\\nexplore\\n\\t^ToolSet explore: self! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 8/15/97 17:25'!\\nfullScreenSize\\n\\t\\\"Answer the size to which a window displaying the receiver should be set\\\"\\n\\t| adj |\\n\\tadj _ (3 * Preferences scrollBarWidth) @ 0.\\n\\t^ Rectangle origin: adj extent: (DisplayScreen actualScreenSize - adj)! !\\n\\n!Object methodsFor: 'user interface' stamp: 'RAA 6/21/1999 11:27'!\\nhasContentsInExplorer\\n\\n\\t^self basicSize > 0 or: [self class allInstVarNames isEmpty not]\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'rbb 3/1/2005 09:28'!\\ninform: aString\\n\\t\\\"Display a message for the user to read and then dismiss. 6/9/96 sw\\\"\\n\\n\\taString isEmptyOrNil ifFalse: [UIManager default inform: aString]! !\\n\\n!Object methodsFor: 'user interface'!\\ninitialExtent\\n\\t\\\"Answer the desired extent for the receiver when a view on it is first opened on the screen. \\n\\t5/22/96 sw: in the absence of any override, obtain from RealEstateAgent\\\"\\n\\n\\t^ RealEstateAgent standardWindowExtent! !\\n\\n!Object methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:30'!\\ninspectWithLabel: aLabel\\n\\t\\\"Create and schedule an Inspector in which the user can examine the receiver's variables.\\\"\\n\\t^ToolSet inspect: self label: aLabel! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 6/12/2001 11:09'!\\nlaunchPartVia: aSelector\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 6/17/2004 01:47'!\\nlaunchPartVia: aSelector label: aString\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setNameTo: (ActiveWorld unusedMorphNameLike: aString).\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/16/2000 11:11'!\\nlaunchTileToRefer\\n\\t\\\"Create a tile to reference the receiver, and attach it to the hand\\\"\\n\\n\\tself currentHand attachMorph: self tileToRefer! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:26'!\\nmodelSleep\\n\\t\\\"A window with me as model is being exited or collapsed or closed.\\n\\tDefault response is no-op\\\" ! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:01'!\\nmodelWakeUp\\n\\t\\\"A window with me as model is being entered or expanded. Default response is no-op\\\" ! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/16/1999 22:45'!\\nmodelWakeUpIn: aWindow\\n\\t\\\"A window with me as model is being entered or expanded. Default response is no-op\\\" \\n\\tself modelWakeUp! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 3/8/1999 15:27'!\\nmouseUpBalk: evt\\n\\t\\\"A button I own got a mouseDown, but the user moved out before letting up. Certain kinds of objects (so-called 'radio buttons', for example, and other structures that must always have some selection, e.g. PaintBoxMorph) wish to take special action in this case; this default does nothing.\\\"\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 8/22/97 13:14'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new setLiteral: self! !\\n\\n!Object methodsFor: 'user interface' stamp: 'jcg 11/1/2001 13:13'!\\nnotYetImplemented\\n\\tself inform: 'Not yet implemented (', thisContext sender printString, ')'! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'!\\nwindowActiveOnFirstClick\\n\\t\\\"Return true if my window should be active on first click.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'!\\nwindowReqNewLabel: labelString\\n\\t\\\"My window's title has been edited.\\n\\tReturn true if this is OK, and override for further behavior.\\\"\\n\\n\\t^ true! !\\n\\n\\n!Object methodsFor: 'world hacking' stamp: 'ar 3/17/2001 23:45'!\\ncouldOpenInMorphic\\n\\n \\\"is there an obvious morphic world in which to open a new morph?\\\"\\n\\n ^World notNil or: [ActiveWorld notNil]! !\\n\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/24/2004 08:49'!\\nbeep\\n\\t\\\"Deprecated.\\\"\\n\\t\\n\\tself deprecated: 'Use Beeper class>>beep instead.'.\\n\\tBeeper beep! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/24/2004 08:50'!\\nbeepPrimitive\\n\\t\\\"Deprecated. Beep in the absence of sound support.\\\"\\n\\t\\n\\tself deprecated: 'Use Beeper class>>beep or Beeper class>>beepPrimitive instead.'.\\n\\tBeeper beepPrimitive! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 12/12/2003 17:02'!\\nbeep: soundName\\n\\t\\\"Make the given sound, unless the making of sound is disabled in Preferences.\\\"\\n\\n\\tself deprecated: 'Use SampledSound>>playSoundNamed: instead.'.\\n\\tPreferences soundsEnabled\\n\\t\\tifTrue: [self playSoundNamed: soundName]\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/19/2004 16:57'!\\ncontentsGetz: x\\n\\tself deprecated: 'there is no method named contents in object and in addition only one sender in a method not called'. \\n\\tself contents: x! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/13/2003 21:10'!\\ndeprecatedExplanation: aString\\n \\\"This method is OBSOLETE. Use #deprecated: instead.\\\"\\n\\tself deprecated: 'Use Object>>deprecated: instead of deprecatedExplanation:.'.\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})]! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/13/2003 21:11'!\\ndeprecated: aBlock explanation: aString \\n\\t \\\"This method is OBSOLETE. Use #deprecated:block: instead.\\\"\\n\\tself deprecated: 'Use Object>>deprecated:block: instead of deprecated:explanation:.'.\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation\\n\\t\\t\\tsignal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})].\\n\\t^ aBlock value.\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 12/12/2003 16:25'!\\ndoIfNotNil: aBlock\\n\\tself deprecated: 'use ifNotNilDo:'.\\n\\t^ self ifNotNilDo: aBlock\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 11/27/2004 12:20'!\\nifKindOf: aClass thenDo: aBlock\\n\\tself deprecated: 'Deprecated. Just use #isKindOf:'.\\n\\t^ (self isKindOf: aClass) ifTrue: [aBlock value: self]! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/23/2004 20:51'!\\nplaySoundNamed: soundName\\n\\t\\\"Deprecated.\\n\\tPlay the sound with the given name.\\\"\\n\\n\\tself deprecated: 'Use \\\"SoundService default playSoundNamed: aName\\\" instead.'.\\n\\tSoundService default playSoundNamed: soundName! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Object methodsFor: '*monticello' stamp: 'dvf 8/10/2004 23:25'!\\nisConflict\\n\\t^false! !\\n\\n\\n!Object methodsFor: '*services-base' stamp: 'rr 3/21/2006 11:54'!\\nrequestor\\n\\t\\\"returns the focused window's requestor\\\"\\n\\n\\t\\\"SystemWindow focusedWindow ifNotNilDo: [:w | ^ w requestor].\\\"\\n\\n\\t\\\"triggers an infinite loop\\\"\\n\\n\\t^ Requestor default! !\\n\\n\\n!Object methodsFor: '*system-support' stamp: 'dvf 8/23/2003 12:27'!\\nsystemNavigation\\n\\n\\t^ SystemNavigation default! !\\n\\n\\n!Object methodsFor: '*Tools-Explorer' stamp: 'stephaneducasse 9/17/2005 21:52'!\\nexploreAndYourself\\n\\t\\\"i.e. explore; yourself. Thisway i can peek w/o typing all the parentheses\\\"\\n\\tself explore. \\n ^self! !\\n\\n!Object methodsFor: '*Tools-Explorer' stamp: 'stephaneducasse 9/17/2005 21:48'!\\nexploreWithLabel: label\\n\\n\\t^ ObjectExplorer new openExplorerFor: self withLabel:\\nlabel! !\\n\\n\\n\\n\\n\\n!Object methodsFor: '*tools-browser' stamp: 'mu 3/6/2004 15:13'!\\nbrowse\\n\\tself systemNavigation browseClass: self class! !\\n\\n!Object methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 16:00'!\\nbrowseHierarchy\\n\\tself systemNavigation browseHierarchy: self class! !\\n\\n\\n!Object methodsFor: 'private'!\\nerrorImproperStore\\n\\t\\\"Create an error notification that an improper store was attempted.\\\"\\n\\n\\tself error: 'Improper store into indexable object'! !\\n\\n!Object methodsFor: 'private'!\\nerrorNonIntegerIndex\\n\\t\\\"Create an error notification that an improper object was used as an index.\\\"\\n\\n\\tself error: 'only integers should be used as indices'! !\\n\\n!Object methodsFor: 'private' stamp: 'yo 6/29/2004 11:37'!\\nerrorNotIndexable\\n\\t\\\"Create an error notification that the receiver is not indexable.\\\"\\n\\n\\tself error: ('Instances of {1} are not indexable' translated format: {self class name})! !\\n\\n!Object methodsFor: 'private'!\\nerrorSubscriptBounds: index \\n\\t\\\"Create an error notification that an improper integer was used as an index.\\\"\\n\\n\\tself error: 'subscript is out of bounds: ' , index printString! !\\n\\n!Object methodsFor: 'private' stamp: 'ar 2/6/2004 14:47'!\\nprimitiveError: aString \\n\\t\\\"This method is called when the error handling results in a recursion in \\n\\tcalling on error: or halt or halt:.\\\"\\n\\n\\t| context |\\n\\t(String\\n\\t\\tstreamContents: \\n\\t\\t\\t[:s |\\n\\t\\t\\ts nextPutAll: '***System error handling failed***'.\\n\\t\\t\\ts cr; nextPutAll: aString.\\n\\t\\t\\tcontext _ thisContext sender sender.\\n\\t\\t\\t20 timesRepeat: [context == nil ifFalse: [s cr; print: (context _ context sender)]].\\n\\t\\t\\ts cr; nextPutAll: '-------------------------------'.\\n\\t\\t\\ts cr; nextPutAll: 'Type CR to enter an emergency evaluator.'.\\n\\t\\t\\ts cr; nextPutAll: 'Type any other character to restart.'])\\n\\t\\tdisplayAt: 0 @ 0.\\n\\t[Sensor keyboardPressed] whileFalse.\\n\\tSensor keyboard = Character cr ifTrue: [Transcripter emergencyEvaluator].\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue: [World install \\\"init hands and redisplay\\\"]\\n\\t\\tifFalse: [ScheduledControllers searchForActiveController]! !\\n\\n!Object methodsFor: 'private'!\\nspecies\\n\\t\\\"Answer the preferred class for reconstructing the receiver. For example, \\n\\tcollections create new collections whenever enumeration messages such as \\n\\tcollect: or select: are invoked. The new kind of collection is determined by \\n\\tthe species of the original collection. Species and class are not always the \\n\\tsame. For example, the species of Interval is Array.\\\"\\n\\n\\t^self class! !\\n\\n!Object methodsFor: 'private'!\\nstoreAt: offset inTempFrame: aContext\\n\\t\\\"This message had to get sent to an expression already on the stack\\n\\tas a Block argument being accessed by the debugger.\\n\\tJust re-route it to the temp frame.\\\"\\n\\t^ aContext tempAt: offset put: self! !\\n\\n\\n!Object methodsFor: '*Morphic-NewCurve-testing''' stamp: 'wiz 12/31/2005 21:31'!\\nisNonZero\\n\\\"Overriden in Number. This returns the backstop answer for non-numbers\\\"\\n^false.! !\\n\\n\\n!Object methodsFor: 'events' stamp: 'nk 8/27/2003 16:23'!\\nactionsWithReceiver: anObject forEvent: anEventSelector\\n\\n\\t^(self actionSequenceForEvent: anEventSelector)\\n select: [:anAction | anAction receiver == anObject ]! !\\n\\n!Object methodsFor: 'events' stamp: 'nk 8/27/2003 17:45'!\\nrenameActionsWithReceiver: anObject forEvent: anEventSelector toEvent: newEvent\\n\\n\\t| oldActions newActions |\\n\\toldActions _ Set new.\\n\\tnewActions _ Set new.\\n\\t(self actionSequenceForEvent: anEventSelector) do: [ :action |\\n\\t\\taction receiver == anObject\\n\\t\\t\\tifTrue: [ oldActions add: anObject ]\\n\\t\\t\\tifFalse: [ newActions add: anObject ]].\\n\\tself setActionSequence: (ActionSequence withAll: newActions) forEvent: anEventSelector.\\n\\toldActions do: [ :act | self when: newEvent evaluate: act ].! !\\n\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:35'!\\nassureUniClass\\n\\t\\\"If the receiver is not yet an instance of a uniclass, create a uniclass for it and make the receiver become an instance of that class.\\\"\\n\\n\\t| anInstance |\\n\\tself belongsToUniClass ifTrue: [^ self].\\n\\tanInstance _ self class instanceOfUniqueClass.\\n\\tself become: (self as: anInstance class).\\n\\t^ anInstance! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:41'!\\nbelongsToUniClass\\n\\t\\\"Answer whether the receiver belongs to a uniclass. For the moment (this is not entirely satisfactory) this is precisely equated with the classname ending in a digit\\\"\\n\\n\\t^ self class name endsWithDigit! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 12/11/2000 15:37'!\\nbrowseOwnClassSubProtocol\\n\\t\\\"Open up a ProtocolBrowser on the subprotocol of the receiver\\\"\\n\\n\\tProtocolBrowser openSubProtocolForClass: self class\\n! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/4/2001 00:51'!\\ncategoriesForViewer: aViewer\\n\\t\\\"Answer a list of categories to offer in the given viewer\\\"\\n\\n\\t^ aViewer currentVocabulary categoryListForInstance: self ofClass: self class limitClass: aViewer limitClass! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/3/2001 22:08'!\\ncategoriesForVocabulary: aVocabulary limitClass: aLimitClass\\n\\t\\\"Answer a list of categories of methods for the receiver when using the given vocabulary, given that one considers only methods that are implemented not further away than aLimitClass\\\"\\n\\n\\t^ aVocabulary categoryListForInstance: self ofClass: self class limitClass: aLimitClass! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/25/2000 07:20'!\\nchooseNewNameForReference\\n\\t\\\"Offer an opportunity for the receiver, presumed already to be known in the References registry, to be renamed\\\"\\n\\n\\t| nameSym current newName |\\n\\tcurrent _ References keyAtValue: self ifAbsent: [^ self error: 'not found in References'].\\n\\n\\tnewName _ FillInTheBlank request: 'Please enter new name' initialAnswer: current.\\n\\t\\\"Want to user some better way of determining the validity of the chosen identifier, and also want to give more precise diagnostic if the string the user types in is not acceptable. Work to be done here.\\\"\\n\\n\\tnewName isEmpty ifTrue: [^ nil].\\n\\t((Scanner isLiteralSymbol: newName) and: [(newName includes: $:) not])\\n\\t\\tifTrue:\\n\\t\\t\\t[nameSym _ newName capitalized asSymbol.\\n\\t\\t\\t(((References includesKey: nameSym) not and:\\n\\t\\t\\t\\t[(Smalltalk includesKey: nameSym) not]) and:\\n\\t\\t\\t\\t\\t\\t[(ScriptingSystem allKnownClassVariableNames includes: nameSym) not])\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[(References associationAt: current) key: nameSym.\\n\\t\\t\\t\\t\\t\\tReferences rehash.\\n\\t\\t\\t\\t\\t\\t^ nameSym]].\\n\\tself inform: 'Sorry, that name is not available.'.\\n\\t^ nil! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/3/2001 21:22'!\\ndefaultLimitClassForVocabulary: aVocabulary\\n\\t\\\"Answer the class to use, by default, as the limit class on a protocol browser or viewer opened up on the receiver, within the purview of the Vocabulary provided\\\"\\n\\n\\t^ (aVocabulary isKindOf: FullVocabulary)\\n\\t\\tifTrue:\\n\\t\\t\\t [self class superclass == Object\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[self class]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[self class superclass]]\\n\\t\\tifFalse:\\n\\t\\t\\t[ProtoObject]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 2/14/2000 14:24'!\\ndefaultNameStemForInstances\\n\\t\\\"Answer a basis for names of default instances of the receiver. The default is to let the class specify, but certain instances will want to override. (PasteUpMorphs serving as Worlds come to mind\\\"\\n\\n\\t^ self class defaultNameStemForInstances! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/22/2001 16:53'!\\nelementTypeFor: aStringOrSymbol vocabulary: aVocabulary\\n\\t\\\"Answer a symbol characterizing what kind of element aStringOrSymbol represents. Realistically, at present, this always just returns #systemScript; a prototyped but not-incorporated architecture supported use of a leading colon to characterize an inst var of a system class, and for the moment we still see its remnant here.\\\"\\n\\n\\tself flag: #deferred. \\\"a loose end in the non-player case\\\"\\n\\t^ #systemScript! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:04'!\\nexternalName\\n\\t\\\"Answer an external name by which the receiver is known. Generic implementation here is a transitional backstop. probably\\\"\\n\\n\\t^ self nameForViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:06'!\\ngraphicForViewerTab\\n\\t\\\"When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Answer a form or a morph to serve that purpose. A generic image is used for arbitrary objects, but note my reimplementors\\\"\\n\\t\\n\\t^ ScriptingSystem formAtKey: 'Image'! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:08'!\\nhasUserDefinedSlots\\n\\t\\\"Answer whether the receiver has any user-defined slots, in the omniuser sense of the term. This is needed to allow Viewers to look at any object, not just at Players.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/22/2002 14:07'!\\ninfoFor: anElement inViewer: aViewer\\n\\t\\\"The user made a gesture asking for info/menu relating to me. Some of the messages dispatched here are not yet available in this image\\\"\\n\\n\\t| aMenu elementType |\\n\\telementType _ self elementTypeFor: anElement vocabulary: aViewer currentVocabulary.\\n\\t((elementType = #systemSlot) | (elementType == #userSlot))\\n\\t\\tifTrue:\\t[^ self slotInfoButtonHitFor: anElement inViewer: aViewer].\\n\\tself flag: #deferred. \\\"Use a traditional MenuMorph, and reinstate the pacify thing\\\"\\n\\taMenu _ MenuMorph new defaultTarget: aViewer.\\n\\t#(\\t('implementors'\\t\\t\\tbrowseImplementorsOf:)\\n\\t\\t('senders'\\t\\t\\t\\tbrowseSendersOf:)\\n\\t\\t('versions'\\t\\t\\t\\tbrowseVersionsOf:)\\n\\t\\t-\\n\\t\\t('browse full'\\t\\t\\tbrowseMethodFull:)\\n\\t\\t('inheritance'\\t\\t\\tbrowseMethodInheritance:)\\n\\t\\t-\\n\\t\\t('about this method'\\t\\taboutMethod:)) do:\\n\\n\\t\\t\\t[:pair |\\n\\t\\t\\t\\tpair = '-'\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[aMenu addLine]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[aMenu add: pair first target: aViewer selector: pair second argument: anElement]].\\n\\taMenu addLine.\\n\\taMenu defaultTarget: self.\\n\\t#(\\t('destroy script'\\t\\tremoveScript:)\\n\\t\\t('rename script'\\t\\trenameScript:)\\n\\t\\t('pacify script'\\t\\tpacifyScript:)) do:\\n\\t\\t\\t[:pair |\\n\\t\\t\\t\\taMenu add: pair first target: self selector: pair second argument: anElement].\\n\\n\\taMenu addLine.\\n\\taMenu add: 'show categories....' target: aViewer selector: #showCategoriesFor: argument: anElement.\\n\\taMenu items size == 0 ifTrue: \\\"won't happen at the moment a/c the above\\\"\\n\\t\\t[aMenu add: 'ok' action: nil]. \\\"in case it was a slot -- weird, transitional\\\"\\n\\n\\taMenu addTitle: anElement asString, ' (', elementType, ')'.\\n\\n\\taMenu popUpInWorld: self currentWorld.\\n ! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 9/26/2001 11:58'!\\ninitialTypeForSlotNamed: aName\\n\\t\\\"Answer the initial type to be ascribed to the given instance variable\\\"\\n\\n\\t^ #Object! !\\n\\n!Object methodsFor: 'viewer' stamp: 'ar 5/26/2001 16:13'!\\nisPlayerLike\\n\\t\\\"Return true if the receiver is a player-like object\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'viewer' stamp: 'nk 9/11/2004 16:53'!\\nmethodInterfacesInPresentationOrderFrom: interfaceList forCategory: aCategory \\n\\t\\\"Answer the interface list sorted in desired presentation order, using a \\n\\tstatic master-ordering list, q.v. The category parameter allows an \\n\\tescape in case one wants to apply different order strategies in different \\n\\tcategories, but for now a single master-priority-ordering is used -- see \\n\\tthe comment in method EToyVocabulary.masterOrderingOfPhraseSymbols\\\"\\n\\n\\t| masterOrder ordered unordered index |\\n\\tmasterOrder := Vocabulary eToyVocabulary masterOrderingOfPhraseSymbols.\\n\\tordered := SortedCollection sortBlock: [:a :b | a key < b key].\\n\\tunordered := SortedCollection sortBlock: [:a :b | a wording < b wording].\\n\\n\\tinterfaceList do: [:interface | \\n\\t\\tindex := masterOrder indexOf: interface elementSymbol.\\n\\t\\tindex isZero\\n\\t\\t\\tifTrue: [unordered add: interface]\\n\\t\\t\\tifFalse: [ordered add: index -> interface]].\\n\\n\\t^ Array\\n\\t\\tstreamContents: [:stream | \\n\\t\\t\\tordered do: [:assoc | stream nextPut: assoc value].\\n\\t\\t\\tstream nextPutAll: unordered]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/24/2000 11:36'!\\nnewScriptorAround: aPhraseTileMorph\\n\\t\\\"Sprout a scriptor around aPhraseTileMorph, thus making a new script. This is where generalized scriptors will be threaded in\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/25/2000 17:42'!\\nofferViewerMenuForEvt: anEvent morph: aMorph\\n\\t\\\"Offer the viewer's primary menu to the user. aMorph is some morph within the viewer itself, the one within which a mousedown triggered the need for this menu, and it is used only to retrieve the Viewer itself\\\"\\n\\n\\tself offerViewerMenuFor: (aMorph ownerThatIsA: StandardViewer) event: anEvent! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/11/2002 02:03'!\\nofferViewerMenuFor: aViewer event: evt\\n\\t\\\"Offer the primary Viewer menu to the user. Copied up from Player code, but most of the functions suggested here don't work for non-Player objects, many aren't even defined, some relate to exploratory sw work not yet reflected in the current corpus. We are early in the life cycle of this method...\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\taMenu title: '**CAUTION -- UNDER CONSTRUCTION!!**\\nMany things may not work!!\\n', self nameForViewer.\\n\\t(aViewer affordsUniclass and: [self belongsToUniClass not]) ifTrue:\\n\\t\\t[aMenu add: 'give me a Uniclass' action: #assureUniClass.\\n\\t\\taMenu addLine].\\n\\taMenu add: 'choose vocabulary...' target: aViewer action: #chooseVocabulary.\\n\\taMenu add: 'choose limit class...' target: aViewer action: #chooseLimitClass.\\n\\taMenu add: 'add search pane' target: aViewer action: #addSearchPane.\\n\\taMenu balloonTextForLastItem: 'Specify which class should be the most generic one to have its methods shown in this Viewer'.\\n\\taMenu addLine.\\n\\n\\tself belongsToUniClass ifTrue:\\n\\t\\t[aMenu add: 'add a new instance variable' target: self selector: #addInstanceVariableIn: argument: aViewer.\\n\\t\\taMenu add: 'add a new script' target: aViewer selector: #newPermanentScriptIn: argument: aViewer.\\n\\t\\taMenu addLine.\\n\\t\\taMenu add: 'make my class be first-class' target: self selector: #makeFirstClassClassIn: argument: aViewer.\\n\\t\\taMenu add: 'move my changes up to my superclass' target: self action: #promoteChangesToSuperclass.\\n\\t\\taMenu addLine].\\n\\n\\taMenu add: 'tear off a tile' target: self selector: #launchTileToRefer.\\n\\taMenu addLine.\\n\\n\\taMenu add: 'inspect me' target: self selector: #inspect.\\n\\taMenu add: 'inspect my class' target: self class action: #inspect.\\n\\taMenu addLine.\\n\\n\\taMenu add: 'browse vocabulary' action: #haveFullProtocolBrowsed.\\n\\taMenu add: 'inspect this Viewer' target: aViewer action: #inspect.\\n\\n\\taMenu popUpEvent: evt in: aViewer currentWorld\\n\\n\\\"\\n\\taMenu add: 'references to me' target: aViewer action: #browseReferencesToObject.\\n\\taMenu add: 'toggle scratch pane' target: aViewer selector: #toggleScratchPane.\\n\\taMenu add: 'make a nascent script for me' target: aViewer selector: #makeNascentScript.\\n\\taMenu add: 'rename me' target: aViewer selector: #chooseNewNameForReference.\\n\\taMenu add: 'browse full' action: #browseOwnClassFull.\\n\\taMenu add: 'browse hierarchy' action: #browseOwnClassHierarchy.\\n\\taMenu add: 'set user level...' target: aViewer action: #setUserLevel.\\n\\taMenu add: 'browse sub-protocol' action: #browseOwnClassSubProtocol.\\n\\taMenu addLine.\\n\\n\\\"! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 1/22/2001 15:20'!\\nrenameScript: oldSelector\\n\\t\\\"prompt the user for a new selector and apply it. Presently only works for players\\\"\\n\\n\\tself notYetImplemented! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 11:53'!\\ntilePhrasesForCategory: aCategorySymbol inViewer: aViewer\\n\\t\\\"Return a collection of phrases for the category.\\\"\\n\\n\\t| interfaces |\\n\\tinterfaces _ self methodInterfacesForCategory: aCategorySymbol inVocabulary: aViewer currentVocabulary limitClass: aViewer limitClass.\\n\\tinterfaces _ self methodInterfacesInPresentationOrderFrom: interfaces forCategory: aCategorySymbol.\\n\\t^ self tilePhrasesForMethodInterfaces: interfaces inViewer: aViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 11:53'!\\ntilePhrasesForMethodInterfaces: methodInterfaceList inViewer: aViewer\\n\\t\\\"Return a collection of ViewerLine objects corresponding to the method-interface list provided. The resulting list will be in the same order as the incoming list, but may be smaller if the viewer's vocbulary suppresses some of the methods, or if, in classic tiles mode, the selector requires more arguments than can be handled.\\\"\\n\\n\\t| toSuppress interfaces resultType itsSelector |\\n\\ttoSuppress _ aViewer currentVocabulary phraseSymbolsToSuppress.\\n\\tinterfaces _ methodInterfaceList reject: [:int | toSuppress includes: int selector].\\n\\tPreferences universalTiles ifFalse: \\\"Classic tiles have their limitations...\\\"\\n\\t\\t[interfaces _ interfaces select:\\n\\t\\t\\t[:int |\\n\\t\\t\\t\\titsSelector _ int selector.\\n\\t\\t\\t\\titsSelector numArgs < 2 or:\\n\\t\\t\\t\\t\\t\\\"The lone two-arg loophole in classic tiles\\\"\\n\\t\\t\\t\\t\\t[#(color:sees:) includes: itsSelector]]].\\n\\n\\t^ interfaces collect:\\n\\t\\t[:aMethodInterface |\\n\\t\\t\\t((resultType _ aMethodInterface resultType) notNil and: [resultType ~~ #unknown]) \\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aViewer phraseForVariableFrom: aMethodInterface]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[aViewer phraseForCommandFrom: aMethodInterface]]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 12:23'!\\ntilePhrasesForSelectorList: aList inViewer: aViewer\\n\\t\\\"Particular to the search facility in viewers. Answer a list, in appropriate order, of ViewerLine objects to put into the viewer.\\\"\\n\\n\\t| interfaces aVocab |\\n\\taVocab _ aViewer currentVocabulary.\\n\\tinterfaces _ self\\n\\t\\tmethodInterfacesInPresentationOrderFrom:\\n\\t\\t\\t(aList collect: [:aSel | aVocab methodInterfaceForSelector: aSel class: self class])\\n\\t\\tforCategory: #search.\\n\\t^ self tilePhrasesForMethodInterfaces: interfaces inViewer: aViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 04:51'!\\ntileToRefer\\n\\t\\\"Answer a reference tile that comprises an alias to me\\\"\\n\\n\\t^ TileMorph new setToReferTo: self! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sd 3/30/2005 22:04'!\\nuniqueInstanceVariableNameLike: aString excluding: takenNames\\n\\t\\\"Answer a nice instance-variable name to be added to the receiver which resembles aString, making sure it does not coincide with any element in takenNames\\\"\\n\\n\\t| okBase uniqueName usedNames |\\n\\tusedNames _ self class allInstVarNamesEverywhere.\\n\\tusedNames removeAllFoundIn: self class instVarNames.\\n\\tusedNames addAll: takenNames.\\n\\tokBase _ Scanner wellFormedInstanceVariableNameFrom: aString.\\n\\n\\tuniqueName _ Utilities keyLike: okBase satisfying: \\n\\t\\t[:aKey | (usedNames includes: aKey) not].\\n\\n\\t^ uniqueName! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 11/21/2001 15:16'!\\nuniqueNameForReference\\n\\t\\\"Answer a nice name by which the receiver can be referred to by other objects. At present this uses a global References dictionary to hold the database of references, but in due course this will need to acquire some locality\\\"\\n\\n\\t| aName nameSym stem knownClassVars |\\n\\t(aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName].\\n\\t(stem _ self knownName) ifNil:\\n\\t\\t[stem _ self defaultNameStemForInstances asString].\\n\\tstem _ stem select: [:ch | ch isLetter or: [ch isDigit]].\\n\\tstem size == 0 ifTrue: [stem _ 'A'].\\n\\tstem first isLetter ifFalse:\\n\\t\\t[stem _ 'A', stem].\\n\\tstem _ stem capitalized.\\n\\tknownClassVars _ ScriptingSystem allKnownClassVariableNames.\\n\\taName _ Utilities keyLike: stem satisfying:\\n\\t\\t[:jinaLake |\\n\\t\\t\\tnameSym _ jinaLake asSymbol.\\n\\t\\t\\t ((References includesKey: nameSym) not and:\\n\\t\\t\\t\\t[(Smalltalk includesKey: nameSym) not]) and:\\n\\t\\t\\t\\t\\t\\t[(knownClassVars includes: nameSym) not]].\\n\\n\\tReferences at: (aName _ aName asSymbol) put: self.\\n\\t^ aName! !\\n\\n!Object methodsFor: 'viewer' stamp: 'md 1/17/2006 17:58'!\\nuniqueNameForReferenceFrom: proposedName\\n\\t\\\"Answer a satisfactory symbol, similar to the proposedName but obeying the rules, to represent the receiver\\\"\\n\\n\\t| aName nameSym stem okay |\\n\\tproposedName = self uniqueNameForReferenceOrNil \\n\\t\\tifTrue: [^ proposedName]. \\\"No change\\\"\\n\\n\\tstem _ proposedName select: [:ch | ch isLetter or: [ch isDigit]].\\n\\tstem size == 0 ifTrue: [stem _ 'A'].\\n\\tstem first isLetter ifFalse:\\n\\t\\t[stem _ 'A', stem].\\n\\tstem _ stem capitalized.\\n\\taName _ Utilities keyLike: stem satisfying:\\n\\t\\t[:jinaLake |\\n\\t\\t\\tnameSym _ jinaLake asSymbol.\\n\\t\\t\\tokay _ true.\\n\\t\\t\\t(self class bindingOf: nameSym) ifNotNil: [okay _ false \\\"don't use it\\\"].\\n\\t\\t\\tokay].\\n\\t^ aName asSymbol! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 3/15/2004 23:01'!\\nuniqueNameForReferenceOrNil\\n\\t\\\"If the receiver has a unique name for reference, return it here, else return nil\\\"\\n\\n\\t^ References keyAtValue: self ifAbsent: [nil]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'ar 5/16/2001 01:40'!\\nupdateThresholdForGraphicInViewerTab\\n\\t\\\"When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Computing this graphic can take quite some time so we want to make the update frequency depending on how long it takes to compute the thumbnail. The threshold returned by this method defines that the viewer will update at most every 'threshold * timeItTakesToDraw' milliseconds. Thus, if the time for computing the receiver's thumbnail is 200 msecs and the the threshold is 10, the viewer will update at most every two seconds.\\\"\\n\\t^20 \\\"seems to be a pretty good general choice\\\"! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 3/9/2001 13:48'!\\nusableMethodInterfacesIn: aListOfMethodInterfaces\\n\\t\\\"Filter aList, returning a subset list of apt phrases\\\"\\n\\n\\t^ aListOfMethodInterfaces\\n! !\\n\\n\\n!Object methodsFor: 'inspecting' stamp: 'ar 9/27/2005 18:31'!\\nbasicInspect\\n\\t\\\"Create and schedule an Inspector in which the user can examine the \\n\\treceiver's variables. This method should not be overriden.\\\"\\n\\t^ToolSet basicInspect: self! !\\n\\n!Object methodsFor: 'inspecting' stamp: 'md 1/18/2006 19:09'!\\ninspect\\n\\t\\\"Create and schedule an Inspector in which the user can examine the receiver's variables.\\\"\\n\\tToolSet inspect: self! !\\n\\n!Object methodsFor: 'inspecting' stamp: 'apb 7/14/2004 12:19'!\\ninspectorClass\\n\\t\\\"Answer the class of the inspector to be used on the receiver. Called by inspect; \\n\\tuse basicInspect to get a normal (less useful) type of inspector.\\\"\\n\\n\\t^ Inspector! !\\n\\n\\n!Object methodsFor: 'thumbnail' stamp: 'dgd 9/25/2004 23:17'!\\niconOrThumbnailOfSize: aNumberOrPoint \\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\t^ nil! !\\n\\n\\n!Object methodsFor: 'scripts-kernel' stamp: 'nk 10/14/2004 10:55'!\\nuniversalTilesForGetterOf: aMethodInterface\\n\\t\\\"Return universal tiles for a getter on the given method interface.\\\"\\n\\n\\t| ms argTile argArray itsSelector |\\n\\titsSelector _ aMethodInterface selector.\\n\\targArray _ #().\\n\\n\\t\\\"Four gratuituous special cases...\\\"\\n\\n\\t(itsSelector == #color:sees:) ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Color.\\n\\t\\targArray _ Array with: argTile colorSwatch color with: argTile colorSwatch color copy].\\n\\n\\titsSelector == #seesColor: ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Color.\\n\\t\\targArray _ Array with: argTile colorSwatch color].\\n\\n\\t(#(touchesA: overlaps: overlapsAny:) includes: itsSelector) ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Player.\\n\\t\\targArray _ Array with: argTile actualObject].\\n\\n\\tms _ MessageSend receiver: self selector: itsSelector arguments: argArray.\\n\\t^ ms asTilesIn: self class globalNames: (self class officialClass ~~ CardPlayer)\\n\\t\\t\\t\\\"For CardPlayers, use 'self'. For others, name it, and use its name.\\\"! !\\n\\n!Object methodsFor: 'scripts-kernel' stamp: 'tk 9/28/2001 13:30'!\\nuniversalTilesForInterface: aMethodInterface\\n\\t\\\"Return universal tiles for the given method interface. Record who self is.\\\"\\n\\n\\t| ms argTile itsSelector aType argList |\\n\\titsSelector _ aMethodInterface selector.\\n\\targList _ OrderedCollection new.\\n\\taMethodInterface argumentVariables doWithIndex:\\n\\t\\t[:anArgumentVariable :anIndex | \\n\\t\\t\\targTile _ ScriptingSystem tileForArgType: (aType _ aMethodInterface typeForArgumentNumber: anIndex).\\n\\t\\t\\targList add: (aType == #Player \\n\\t\\t\\t\\tifTrue: [argTile actualObject]\\n\\t\\t\\t\\tifFalse: [argTile literal]).\\t\\\"default value for each type\\\"].\\n\\n\\tms _ MessageSend receiver: self selector: itsSelector arguments: argList asArray.\\n\\t^ ms asTilesIn: self class globalNames: (self class officialClass ~~ CardPlayer)\\n\\t\\t\\t\\\"For CardPlayers, use 'self'. For others, name it, and use its name.\\\"! !\\n\\n\\n!Object methodsFor: 'breakpoint' stamp: 'bkv 7/1/2003 12:33'!\\nbreak\\n\\t\\\"This is a simple message to use for inserting breakpoints during debugging.\\n\\tThe debugger is opened by sending a signal. This gives a chance to restore\\n\\tinvariants related to multiple processes.\\\"\\n\\n\\tBreakPoint signal.\\n\\n\\t\\\"nil break.\\\"! !\\n\\n\\n\\n!Object methodsFor: '*omnibrowser-converting' stamp: 'cwp 4/17/2006 12:16'!\\nasAnnouncement\\n\\t^ self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObject class\\n\\tinstanceVariableNames: ''!\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 02:00'!\\nflushDependents\\n\\tDependentsFields keysAndValuesDo:[:key :dep|\\n\\t\\tkey ifNotNil:[key removeDependent: nil].\\n\\t].\\n\\tDependentsFields finalizeValues.! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'rw 2/10/2002 13:09'!\\nflushEvents\\n\\t\\\"Object flushEvents\\\"\\n\\n\\tEventManager flushEvents. ! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'rww 10/2/2001 07:35'!\\ninitialize\\n\\t\\\"Object initialize\\\"\\n\\tDependentsFields ifNil:[self initializeDependentsFields].! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:41'!\\ninitializeDependentsFields\\n\\t\\\"Object initialize\\\"\\n\\tDependentsFields _ WeakIdentityKeyDictionary new.\\n! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:45'!\\nreInitializeDependentsFields\\n\\t\\\"Object reInitializeDependentsFields\\\"\\n\\t| oldFields |\\n\\toldFields _ DependentsFields.\\n\\tDependentsFields _ WeakIdentityKeyDictionary new.\\n\\toldFields keysAndValuesDo:[:obj :deps|\\n\\t\\tdeps do:[:d| obj addDependent: d]].\\n! !\\n\\n\\n!Object class methodsFor: 'documentation'!\\nhowToModifyPrimitives\\n\\t\\\"You are allowed to write methods which specify primitives, but please use \\n\\tcaution. If you make a subclass of a class which contains a primitive method, \\n\\tthe subclass inherits the primitive. The message which is implemented \\n\\tprimitively may be overridden in the subclass (E.g., see at:put: in String's \\n\\tsubclass Symbol). The primitive behavior can be invoked using super (see \\n\\tSymbol string:). \\n\\t \\n\\tA class which attempts to mimic the behavior of another class without being \\n\\tits subclass may or may not be able to use the primitives of the original class. \\n\\tIn general, if the instance variables read or written by a primitive have the \\n\\tsame meanings and are in the same fields in both classes, the primitive will \\n\\twork. \\n\\n\\tFor certain frequently used 'special selectors', the compiler emits a \\n\\tsend-special-selector bytecode instead of a send-message bytecode. \\n\\tSpecial selectors were created because they offer two advantages. Code \\n\\twhich sends special selectors compiles into fewer bytes than normal. For \\n\\tsome pairs of receiver classes and special selectors, the interpreter jumps \\n\\tdirectly to a primitive routine without looking up the method in the class. \\n\\tThis is much faster than a normal message lookup. \\n\\t \\n\\tA selector which is a special selector solely in order to save space has a \\n\\tnormal behavior. Methods whose selectors are special in order to \\n\\tgain speed contain the comment, 'No Lookup'. When the interpreter \\n\\tencounters a send-special-selector bytecode, it checks the class of the \\n\\treceiver and the selector. If the class-selector pair is a no-lookup pair, \\n\\tthen the interpreter swiftly jumps to the routine which implements the \\n\\tcorresponding primitive. (A special selector whose receiver is not of the \\n\\tright class to make a no-lookup pair, is looked up normally). The pairs are \\n\\tlisted below. No-lookup methods contain a primitive number specification, \\n\\t<primitive: xx>, which is redundant. Since the method is not normally looked \\n\\tup, deleting the primitive number specification cannot prevent this \\n\\tprimitive from running. If a no-lookup primitive fails, the method is looked \\n\\tup normally, and the expressions in it are executed. \\n\\t \\n\\tNo Lookup pairs of (class, selector) \\n\\t \\n\\tSmallInteger with any of\\t\\t+ - * / \\\\\\\\ bitOr: bitShift: bitAnd: // \\n\\tSmallInteger with any of\\t\\t= ~= > < >= <= \\n\\tAny class with\\t\\t\\t\\t\\t== \\n\\tAny class with \\t\\t\\t\\t\\t@ \\n\\tPoint with either of\\t\\t\\t\\tx y \\n\\tContextPart with\\t\\t\\t\\t\\tblockCopy: \\n\\tBlockContext with either of \\t\\tvalue value:\\n\\t\\\"\\n\\n\\tself error: 'comment only'! !\\n\\n!Object class methodsFor: 'documentation'!\\nwhatIsAPrimitive\\n\\t\\\"Some messages in the system are responded to primitively. A primitive \\n\\tresponse is performed directly by the interpreter rather than by evaluating \\n\\texpressions in a method. The methods for these messages indicate the \\n\\tpresence of a primitive response by including <primitive: xx> before the \\n\\tfirst expression in the method. \\n\\t \\n\\tPrimitives exist for several reasons. Certain basic or 'primitive' \\n\\toperations cannot be performed in any other way. Smalltalk without \\n\\tprimitives can move values from one variable to another, but cannot add two \\n\\tSmallIntegers together. Many methods for arithmetic and comparison \\n\\tbetween numbers are primitives. Some primitives allow Smalltalk to \\n\\tcommunicate with I/O devices such as the disk, the display, and the keyboard. \\n\\tSome primitives exist only to make the system run faster; each does the same \\n\\tthing as a certain Smalltalk method, and its implementation as a primitive is \\n\\toptional. \\n\\t \\n\\tWhen the Smalltalk interpreter begins to execute a method which specifies a \\n\\tprimitive response, it tries to perform the primitive action and to return a \\n\\tresult. If the routine in the interpreter for this primitive is successful, \\n\\tit will return a value and the expressions in the method will not be evaluated. \\n\\tIf the primitive routine is not successful, the primitive 'fails', and the \\n\\tSmalltalk expressions in the method are executed instead. These \\n\\texpressions are evaluated as though the primitive routine had not been \\n\\tcalled. \\n\\t \\n\\tThe Smalltalk code that is evaluated when a primitive fails usually \\n\\tanticipates why that primitive might fail. If the primitive is optional, the \\n\\texpressions in the method do exactly what the primitive would have done (See \\n\\tNumber @). If the primitive only works on certain classes of arguments, the \\n\\tSmalltalk code tries to coerce the argument or appeals to a superclass to find \\n\\ta more general way of doing the operation (see SmallInteger +). If the \\n\\tprimitive is never supposed to fail, the expressions signal an error (see \\n\\tSmallInteger asFloat). \\n\\t \\n\\tEach method that specifies a primitive has a comment in it. If the primitive is \\n\\toptional, the comment will say 'Optional'. An optional primitive that is not \\n\\timplemented always fails, and the Smalltalk expressions do the work \\n\\tinstead. \\n\\t \\n\\tIf a primitive is not optional, the comment will say, 'Essential'. Some \\n\\tmethods will have the comment, 'No Lookup'. See Object \\n\\thowToModifyPrimitives for an explanation of special selectors which are \\n\\tnot looked up. \\n\\t \\n\\tFor the primitives for +, -, *, and bitShift: in SmallInteger, and truncated \\n\\tin Float, the primitive constructs and returns a 16-bit \\n\\tLargePositiveInteger when the result warrants it. Returning 16-bit \\n\\tLargePositiveIntegers from these primitives instead of failing is \\n\\toptional in the same sense that the LargePositiveInteger arithmetic \\n\\tprimitives are optional. The comments in the SmallInteger primitives say, \\n\\t'Fails if result is not a SmallInteger', even though the implementor has the \\n\\toption to construct a LargePositiveInteger. For further information on \\n\\tprimitives, see the 'Primitive Methods' part of the chapter on the formal \\n\\tspecification of the interpreter in the Smalltalk book.\\\"\\n\\n\\tself error: 'comment only'! !\\n\\n\\n!Object class methodsFor: 'file list services' stamp: 'nk 6/12/2004 11:41'!\\nfileReaderServicesForDirectory: aFileDirectory\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n!Object class methodsFor: 'file list services' stamp: 'nk 6/12/2004 11:30'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n!Object class methodsFor: 'file list services' stamp: 'md 2/15/2006 17:20'!\\nservices\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 1/23/2003 09:45'!\\ncategoryForUniclasses\\n\\n\\t\\\"Answer the default system category into which to place unique-class instances\\\"\\n\\n\\n\\n\\t^ 'UserObjects'! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'!\\nchooseUniqueClassName\\n\\t| i className |\\n\\ti _ 1.\\n\\t[className _ (self name , i printString) asSymbol.\\n\\t Smalltalk includesKey: className]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\t^ className! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:22'!\\ninitialInstance\\n\\t\\\"Answer the first instance of the receiver, generate an error if there is one already\\\"\\n\\t\\\"self instanceCount > 0 ifTrue: [self error: 'instance(s) already exist.'].\\\"\\n\\t\\t\\\"Debugging test that is very slow\\\"\\n\\t^ self new! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 09:30'!\\ninitializedInstance\\n\\t^ self new! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 10/16/2000 10:58'!\\ninstanceOfUniqueClass\\n\\t\\\"Answer an instance of a unique subclass of the receiver\\\"\\n\\n\\t^ self instanceOfUniqueClassWithInstVarString: '' andClassInstVarString: ''! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:27'!\\ninstanceOfUniqueClassWithInstVarString: instVarString andClassInstVarString: classInstVarString\\n\\t\\\"Create a unique class for the receiver, and answer an instance of it\\\"\\n\\n\\t^ (self newUniqueClassInstVars: instVarString \\n\\t\\tclassInstVars: classInstVarString) initialInstance! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 10/23/1999 22:51'!\\nisUniClass\\n\\t^ false! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'ajh 5/23/2002 00:35'!\\nnewFrom: aSimilarObject\\n\\t\\\"Create an object that has similar contents to aSimilarObject.\\n\\tIf the classes have any instance varaibles with the same names, copy them across.\\n\\tIf this is bad for a class, override this method.\\\"\\n\\n\\t^ (self isVariable\\n\\t\\tifTrue: [self basicNew: aSimilarObject basicSize]\\n\\t\\tifFalse: [self basicNew]\\n\\t ) copySameFrom: aSimilarObject! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 6/29/1998 12:11'!\\nnewUniqueClassInstVars: instVarString classInstVars: classInstVarString\\n\\t\\\"Create a unique class for the receiver\\\"\\n\\n\\t| aName aClass |\\n\\tself isSystemDefined ifFalse:\\n\\t\\t[^ superclass newUniqueClassInstVars: instVarString classInstVars: classInstVarString].\\n\\taName _ self chooseUniqueClassName.\\n\\taClass _ self subclass: aName instanceVariableNames: instVarString \\n\\t\\tclassVariableNames: '' poolDictionaries: '' category: self categoryForUniclasses.\\n\\tclassInstVarString size > 0 ifTrue:\\n\\t\\t[aClass class instanceVariableNames: classInstVarString].\\n\\t^ aClass! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'!\\nnewUserInstance\\n\\t\\\"Answer an instance of an appropriate class to serve as a user object in the containment hierarchy\\\"\\n\\n\\t^ self instanceOfUniqueClass! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'nk 8/30/2004 07:57'!\\nreadCarefullyFrom: textStringOrStream\\n\\t\\\"Create an object based on the contents of textStringOrStream. Return an error instead of putting up a SyntaxError window.\\\"\\n\\n\\t| object |\\n\\t(Compiler couldEvaluate: textStringOrStream)\\n\\t\\tifFalse: [^ self error: 'expected String, Stream, or Text'].\\n\\tobject _ Compiler evaluate: textStringOrStream for: nil \\n\\t\\t\\t\\tnotifying: #error: \\\"signal we want errors\\\" logged: false.\\n\\t(object isKindOf: self) ifFalse: [self error: self name, ' expected'].\\n\\t^object! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'nk 8/30/2004 07:57'!\\nreadFrom: textStringOrStream\\n\\t\\\"Create an object based on the contents of textStringOrStream.\\\"\\n\\n\\t| object |\\n\\t(Compiler couldEvaluate: textStringOrStream)\\n\\t\\tifFalse: [^ self error: 'expected String, Stream, or Text'].\\n\\tobject _ Compiler evaluate: textStringOrStream.\\n\\t(object isKindOf: self) ifFalse: [self error: self name, ' expected'].\\n\\t^object! !\\n\\n\\n!Object class methodsFor: 'objects from disk' stamp: 'tk 1/8/97'!\\ncreateFrom: aSmartRefStream size: varsOnDisk version: instVarList\\n\\t\\\"Create an instance of me so objects on the disk can be read in. Tricky part is computing the size if variable. Inst vars will be filled in later. \\\"\\n\\n\\t^ self isVariable\\n\\t\\tifFalse: [self basicNew]\\n\\t\\tifTrue: [\\\"instVarList is names of old class's inst vars plus a version number\\\" \\n\\t\\t\\t\\tself basicNew: (varsOnDisk - (instVarList size - 1))]\\n! !\\n\\n\\n!Object class methodsFor: 'window color' stamp: 'nk 6/10/2004 08:10'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference.\\n\\tThis is a backstop for classes that don't otherwise define a preference.\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name\\n\\t\\twording: 'Default' brightColor: #white\\n\\t\\tpastelColor: #white\\n\\t\\thelpMessage: 'Other windows without color preferences.'! !\\n\\n\\n!Object class methodsFor: 'private' stamp: 'mir 8/22/2001 15:20'!\\nreleaseExternalSettings\\n\\t\\\"Do nothing as a default\\\"! !\\nAbstractHierarchicalList subclass: #ObjectExplorer\\n\\tinstanceVariableNames: 'rootObject inspector monitorList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Explorer'!\\n!ObjectExplorer commentStamp: '<historical>' prior: 0!\\nObjectExplorer provides a hierarchical alternative to #inspect. Simply evaluate an expression like:\\n\\nWorld explore\\n\\nand enjoy.!\\n]style[(101 13 12)f1,f3cblue;,f1!\\n\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:11'!\\ncontentsSelection\\n\\t\\\"Return the interval of text in the code pane to select when I set the pane's contents\\\"\\n\\n\\t^ 1 to: 0 \\\"null selection\\\"! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:15'!\\ndoItContext\\n\\t\\\"Answer the context in which a text selection can be evaluated.\\\"\\n\\n\\t^nil! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:19'!\\ndoItReceiver\\n\\t\\\"Answer the object that should be informed of the result of evaluating a\\n\\ttext selection.\\\"\\n\\n\\tcurrentSelection ifNil: [^rootObject].\\n\\t^currentSelection withoutListWrapper\\n! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:27'!\\nexplorerFor: anObject\\n\\t| window listMorph |\\n\\trootObject := anObject.\\n\\twindow := (SystemWindow labelled: self label) model: self.\\n\\twindow addMorph: (listMorph := SimpleHierarchicalListMorph \\n\\t\\t\\ton: self\\n\\t\\t\\tlist: #getList\\n\\t\\t\\tselected: #getCurrentSelection\\n\\t\\t\\tchangeSelected: #noteNewSelection:\\n\\t\\t\\tmenu: #genericMenu:\\n\\t\\t\\tkeystroke: #explorerKey:from:)\\n\\t\\tframe: (0@0 corner: 1@0.8).\\n\\twindow addMorph: ((PluggableTextMorph on: self text: #trash accept: #trash:\\n\\t\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:)\\n\\t\\t\\t\\t\\taskBeforeDiscardingEdits: false)\\n\\t\\tframe: (0@0.8 corner: 1@1).\\n\\tlistMorph\\n\\t\\tautoDeselect: false.\\n ^ window! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:16'!\\ngetList\\n\\n\\t^Array with: (ObjectExplorerWrapper with: rootObject name: 'root' model: self parent: nil)\\n! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'hg 9/7/2001 12:12'!\\nlabel\\n\\n\\t^ rootObject printStringLimitedTo: 32! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:43'!\\nobject\\n\\t^currentSelection ifNotNilDo: [ :cs | cs withoutListWrapper ]! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 10:02'!\\nparentObject\\n\\tcurrentSelection ifNil: [ ^nil ].\\n\\tcurrentSelection parent ifNil: [ ^rootObject ].\\n\\t^currentSelection parent withoutListWrapper! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:47'!\\nselector\\n\\t^currentSelection ifNotNilDo: [ :cs | cs selector ]! !\\n\\n\\n!ObjectExplorer methodsFor: 'error handling' stamp: 'nk 7/24/2003 09:29'!\\ndoesNotUnderstand: aMessage\\n\\tinspector ifNotNil: [ (inspector respondsTo: aMessage selector) ifTrue: [ ^inspector perform: aMessage selector withArguments: aMessage arguments ]].\\n\\t^super doesNotUnderstand: aMessage! !\\n\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nchasePointers\\n\\t\\\"Open a PointerFinder on the selected item\\\"\\n\\t| path sel savedRoot saved |\\n\\tpath := OrderedCollection new.\\n\\tsel := currentSelection.\\n\\t[ sel isNil ] whileFalse: [ path addFirst: sel asString. sel := sel parent ].\\n\\tpath addFirst: #openPath.\\n\\tpath := path asArray.\\n\\tsavedRoot := rootObject.\\n\\tsaved := self object.\\n\\t[ rootObject := nil.\\n\\tself changed: #getList.\\n\\t(Smalltalk includesKey: #PointerFinder)\\n\\t\\tifTrue: [PointerFinder on: saved]\\n\\t\\tifFalse: [self objectReferencesToSelection ]]\\n\\t\\tensure: [ rootObject := savedRoot.\\n\\t\\t\\tself changed: #getList.\\n\\t\\t\\tself changed: path.\\n\\t\\t]! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:22'!\\ncodePaneMenu: aMenu shifted: shifted\\n\\t\\\"Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items\\\"\\n\\t^ StringHolder basicNew codePaneMenu: aMenu shifted: shifted\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\ndefsOfSelection\\n\\t\\\"Open a browser on all defining references to the selected instance variable, if that's what's currently selected.\\\"\\n\\t| aClass sel |\\n\\n\\t(aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash].\\n\\tsel := self selector.\\n\\tself systemNavigation browseAllStoresInto: sel from: aClass! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nexplorerKey: aChar from: view\\n\\n\\t\\\"Similar to #genericMenu:...\\\"\\n\\t| insideObject parentObject |\\n\\tcurrentSelection ifNotNil: [\\n\\t\\tinsideObject := self object.\\n\\t\\tparentObject := self parentObject.\\n\\t\\tinspector ifNil: [inspector := Inspector new].\\n\\t\\tinspector\\n\\t\\t\\tinspect: parentObject;\\n\\t\\t\\tobject: insideObject.\\n\\n\\t\\taChar == $i ifTrue: [^ self inspectSelection].\\n\\t\\taChar == $I ifTrue: [^ self exploreSelection].\\n\\n\\t\\taChar == $b ifTrue:\\t[^ inspector browseMethodFull].\\n\\t\\taChar == $h ifTrue:\\t[^ inspector classHierarchy].\\n\\t\\taChar == $c ifTrue: [^ inspector copyName].\\n\\t\\taChar == $p ifTrue: [^ inspector browseFullProtocol].\\n\\t\\taChar == $N ifTrue: [^ inspector browseClassRefs].\\n\\t\\taChar == $t ifTrue: [^ inspector tearOffTile].\\n\\t\\taChar == $v ifTrue: [^ inspector viewerForValue]].\\n\\n\\t^ self arrowKey: aChar from: view! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'!\\nexploreSelection\\n\\t\\\"Open an ObjectExplorer on the current selection\\\"\\n\\tself object explore! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\ngenericMenu: aMenu \\n\\t\\\"Borrow a menu from my inspector\\\"\\n\\t| insideObject menu parentObject |\\n\\tcurrentSelection\\n\\t\\tifNil: [menu := aMenu.\\n\\t\\t\\tmenu\\n\\t\\t\\t\\tadd: '*nothing selected*'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #yourself]\\n\\t\\tifNotNil: [insideObject := self object.\\n\\t\\t\\tparentObject := self parentObject.\\n\\t\\t\\tinspector\\n\\t\\t\\t\\tifNil: [inspector := Inspector new].\\n\\t\\t\\tinspector inspect: parentObject;\\n\\t\\t\\t\\t object: insideObject.\\n\\t\\t\\taMenu defaultTarget: inspector.\\n\\t\\t\\tinspector fieldListMenu: aMenu.\\n\\t\\t\\taMenu items\\n\\t\\t\\t\\tdo: [:i | (#(#inspectSelection #exploreSelection #referencesToSelection #defsOfSelection #objectReferencesToSelection #chasePointers ) includes: i selector)\\n\\t\\t\\t\\t\\t\\tifTrue: [i target: self]].\\n\\t\\t\\taMenu addLine;\\n\\t\\t\\t\\tadd: 'monitor changes'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #monitor:\\n\\t\\t\\t\\targument: currentSelection].\\n\\tmonitorList isEmptyOrNil\\n\\t\\tifFalse: [aMenu addLine;\\n\\t\\t\\t\\tadd: 'stop monitoring all'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #stopMonitoring].\\n\\t^ aMenu! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'!\\ninspectSelection\\n\\t\\\"Open an Inspector on the current selection\\\"\\n\\tself object inspect! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:00'!\\nobjectReferencesToSelection\\n\\t\\\"Open a browser on all references to the selected instance variable, if that's what currently selected. \\\"\\n\\tself systemNavigation\\n\\t\\tbrowseAllObjectReferencesTo: self object\\n\\t\\texcept: (Array with: self parentObject with: currentSelection with: inspector)\\n\\t\\tifNone: [:obj | self changed: #flash].\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nreferencesToSelection\\n\\t\\\"Open a browser on all references to the selected instance variable, if that's what's currently selected.\\\"\\n\\t| aClass sel |\\n\\n\\t(aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash].\\n\\tsel := self selector.\\n\\tself systemNavigation browseAllAccessesTo: sel from: aClass! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:19'!\\nselectedClass\\n\\t\\\"Answer the class of the receiver's current selection\\\"\\n\\n\\t^self doItReceiver class\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'!\\ntrash\\n\\t\\\"What goes in the bottom pane\\\"\\n\\t^ ''! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'!\\ntrash: newText\\n\\t\\\"Don't save it\\\"\\n\\t^ true! !\\n\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nmonitorList\\n\\t^monitorList ifNil: [ monitorList := WeakIdentityKeyDictionary new ].! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:02'!\\nmonitor: anObjectExplorerWrapper\\n\\t\\\"Start stepping and watching the given wrapper for changes.\\\"\\n\\tanObjectExplorerWrapper ifNil: [ ^self ].\\n\\tself world ifNil: [ ^self ].\\n\\tself monitorList at: anObjectExplorerWrapper put: anObjectExplorerWrapper asString.\\n\\tself world startStepping: self at: Time millisecondClockValue selector: #step arguments: #() stepTime: 200.! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:01'!\\nrelease\\n\\tself world ifNotNil: [ self world stopStepping: self selector: #step ].\\n\\tsuper release.! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/12/2003 17:55'!\\nshouldGetStepsFrom: aWorld\\n\\t^self monitorList notEmpty! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nstep\\n\\t\\\"If there's anything in my monitor list, see if the strings have changed.\\\"\\n\\t| string changes |\\n\\tchanges := false.\\n\\tself monitorList keysAndValuesDo: [ :k :v |\\n\\t\\tk ifNotNil: [\\n\\t\\t\\tk refresh.\\n\\t\\t\\t(string := k asString) ~= v ifTrue: [ self monitorList at: k put: string. changes := true ].\\n\\t\\t]\\n\\t].\\n\\tchanges ifTrue: [ | sel |\\n\\t\\tsel := currentSelection.\\n\\t\\tself changed: #getList.\\n\\t\\tself noteNewSelection: sel.\\n\\t].\\n\\tself monitorList isEmpty ifTrue: [ ActiveWorld stopStepping: self selector: #step ].! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nstopMonitoring\\n\\tmonitorList := nil.\\n\\tself world stopStepping: self selector: #step! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:01'!\\nworld\\n\\t^ActiveWorld! !\\n\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'stephaneducasse 9/17/2005 21:50'!\\nexplorerFor: anObject withLabel: label \\n\\t| window listMorph |\\n\\trootObject := anObject.\\n\\twindow := (SystemWindow labelled: label) \\n\\t\\t\\t\\tmodel: self.\\n\\twindow\\n\\t\\taddMorph: (listMorph := SimpleHierarchicalListMorph\\n\\t\\t\\t\\t\\t\\ton: self\\n\\t\\t\\t\\t\\t\\tlist: #getList\\n\\t\\t\\t\\t\\t\\tselected: #getCurrentSelection\\n\\t\\t\\t\\t\\t\\tchangeSelected: #noteNewSelection:\\n\\t\\t\\t\\t\\t\\tmenu: #genericMenu:\\n\\t\\t\\t\\t\\t\\tkeystroke: nil)\\n\\t\\tframe: (0 @ 0 corner: 1 @ 0.8).\\n\\twindow\\n\\t\\taddMorph: ((PluggableTextMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\ttext: #trash\\n\\t\\t\\t\\taccept: #trash:\\n\\t\\t\\t\\treadSelection: #contentsSelection\\n\\t\\t\\t\\tmenu: #codePaneMenu:shifted:)\\n\\t\\t\\t\\taskBeforeDiscardingEdits: false)\\n\\t\\tframe: (0 @ 0.8 corner: 1 @ 1).\\n\\tlistMorph autoDeselect: false.\\n\\t^ window! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:23'!\\ninitialExtent\\n\\n\\t^300@500! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:31'!\\nopenBrowser: aClass\\n\\n\\tToolSet browse: aClass selector: nil! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:24'!\\nopenExplorerFor: anObject\\n\\\"\\nObjectExplorer new openExplorerFor: Smalltalk\\n\\\"\\n\\n (self explorerFor: anObject) openInWorld.\\n ^ self\\n! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'stephaneducasse 9/17/2005 21:51'!\\nopenExplorerFor: anObject withLabel: label \\n \\\"ObjectExplorer new openExplorerFor: Smalltalk withLabel: 'Smalltalk'\\\"\\n\\n\\t(self explorerFor: anObject withLabel: label)\\nopenInWorld! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectExplorer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectExplorer class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:55'!\\nabout\\n\\n\\tStringHolder new textContents: self comment; openLabel: 'about ',self asString! !\\nListItemWrapper subclass: #ObjectExplorerWrapper\\n\\tinstanceVariableNames: 'itemName parent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!ObjectExplorerWrapper commentStamp: '<historical>' prior: 0!\\nContributed by Bob Arning as part of the ObjectExplorer package.\\n!\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:48'!\\ncanBeDragged\\n\\n\\t^false! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nparent\\n\\t^parent! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nparent: anObject\\n\\tparent _ anObject! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:49'!\\nselector\\n\\tparent ifNil: [ ^nil ].\\n\\t^(parent withoutListWrapper class allInstVarNames includes: itemName) ifTrue: [ itemName asSymbol ]! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:49'!\\nsetItem: anObject name: aString model: aModel\\n\\n\\titem _ anObject.\\n\\tmodel _ aModel.\\n\\titemName _ aString.! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nsetItem: anObject name: aString model: aModel parent: itemParent\\n\\tparent _ itemParent.\\n\\tself setItem: anObject name: aString model: aModel! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'converting' stamp: 'edt 5/26/2003 12:36'!\\nasString\\n\\t| explorerString string |\\n\\texplorerString _ \\n\\t\\t[item asExplorerString]\\n\\t\\t\\ton: Error \\n\\t\\t\\tdo: ['<error: ', item class name, ' in asExplorerString: evaluate \\\"' , itemName , ' asExplorerString\\\" to debug>'].\\n\\tstring _ (itemName ifNotNil: [itemName , ': '] ifNil: ['']) , explorerString.\\n\\t(string includes: Character cr)\\n\\t\\tifTrue: [^ string withSeparatorsCompacted].\\n\\t^ string! !\\n\\n!ObjectExplorerWrapper methodsFor: 'converting' stamp: 'nk 7/24/2003 10:16'!\\nitemName\\n\\t^itemName! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'monitoring' stamp: 'nk 7/12/2003 18:28'!\\nrefresh\\n\\t\\\"hack to refresh item given an object and a string that is either an index or an instance variable name.\\\"\\n\\t[ | index |\\n\\t\\t(model class allInstVarNames includes: itemName)\\n\\t\\t\\tifTrue: [ item _ model instVarNamed: itemName ]\\n\\t\\t\\tifFalse: [ index _ itemName asNumber.\\n\\t\\t\\t\\t(index between: 1 and: model basicSize) ifTrue: [ item _ model basicAt: index]]\\n\\t] on: Error do: [ :ex | item _ nil ]! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:17'!\\ncontents\\n\\n\\t(item respondsTo: #explorerContents) ifTrue: [^item explorerContents].\\n\\t\\\"For all others, show named vars first, then indexed vars\\\"\\n\\t^(item class allInstVarNames asOrderedCollection withIndexCollect: [:each :index |\\n\\t\\tself class\\n\\t\\t\\twith: (item instVarAt: index)\\n\\t\\t\\tname: each\\n\\t\\t\\tmodel: item\\n\\t\\t\\tparent: self]) ,\\n\\t((1 to: item basicSize) collect: [:index |\\n\\t\\tself class\\n\\t\\t\\twith: (item basicAt: index)\\n\\t\\t\\tname: index printString\\n\\t\\t\\tmodel: item\\n\\t\\t\\tparent: self])! !\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'RAA 6/21/1999 11:27'!\\nhasContents\\n\\n\\t^item hasContentsInExplorer\\n\\t\\n! !\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:34'!\\nicon\\n\\t\\\"Answer a form to be used as icon\\\"\\n\\t^ Preferences visualExplorer\\n\\t\\tifTrue: [item iconOrThumbnailOfSize: 16]\\n\\t\\tifFalse: [nil]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectExplorerWrapper class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:50'!\\nwith: anObject name: aString model: aModel\\n\\n\\t^self new \\n\\t\\tsetItem: anObject name: aString model: aModel! !\\n\\n!ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:16'!\\nwith: anObject name: aString model: aModel parent: aParent\\n\\n\\t^self new \\n\\t\\tsetItem: anObject name: aString model: aModel parent: aParent\\n! !\\nObject subclass: #ObjectFinalizer\\n\\tinstanceVariableNames: 'receiver selector arguments'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Finalization'!\\n\\n!ObjectFinalizer methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:13'!\\nfinalize\\n\\t\\\"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority.\\\"\\n\\t[receiver perform: selector withArguments: arguments] \\n\\t\\ton: Error do:[:ex| ex return].\\n! !\\n\\n\\n!ObjectFinalizer methodsFor: 'initialize' stamp: 'ar 5/19/2003 20:12'!\\nreceiver: aReceiver selector: aSelector argument: anObject\\n\\treceiver := aReceiver.\\n\\tselector := aSelector.\\n\\targuments := Array with: anObject! !\\nTestCase subclass: #ObjectFinalizerTests\\n\\tinstanceVariableNames: 'log'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Finalization'!\\n\\n!ObjectFinalizerTests methodsFor: 'finalization handling' stamp: 'apb 9/14/2005 08:33'!\\nfinalize: anObject\\n\\tlog addLast: anObject asString, ' ', 'finalized'.! !\\n\\n\\n!ObjectFinalizerTests methodsFor: 'running' stamp: 'apb 9/14/2005 08:39'!\\nsetUp\\n\\tsuper setUp.\\n\\tlog := OrderedCollection new.! !\\n\\n\\n!ObjectFinalizerTests methodsFor: 'tests' stamp: 'stephaneducasse 10/28/2005 21:15'!\\ntestFinalization\\n\\t\\\"self run: #testFinalization\\\"\\n\\t\\n\\t| repetitions |\\n\\trepetitions := 100.\\n\\t1 to: repetitions\\n\\t\\tdo: [:i | \\n\\t\\t\\tlog addLast: 'o' , i asString , ' created'.\\n\\t\\t\\tObject new\\n\\t\\t\\t\\ttoFinalizeSend: #finalize:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twith: 'o' , i asString].\\n\\tSmalltalk garbageCollect.\\n\\tself finalizationRegistry finalizeValues.\\n\\t1 to: repetitions\\n\\t\\tdo: [:i | \\n\\t\\t\\tself assert: (log includes: 'o' , i asString , ' created').\\n\\t\\t\\tself assert: (log includes: 'o' , i asString , ' finalized')]! !\\n\\n!ObjectFinalizerTests methodsFor: 'tests' stamp: 'stephaneducasse 10/28/2005 21:15'!\\ntestFinalizationOfEquals\\n\\t\\\"self run: #testFinalizationOfEquals\\\"\\n\\t\\n\\t| bag o |\\n\\tbag := IdentityBag new.\\n\\t1 to: 5 do: [:n | o := n asString copy. bag add: n. o toFinalizeSend: #remove: to: bag with: n].\\n\\t1 to: 5 do: [:n | o := n asString copy. bag add: n. o toFinalizeSend: #remove: to: bag with: n].\\n\\tSmalltalk garbageCollect.\\n\\t1 to: 5 do: [:n | self deny: (bag includes: n)]\\n! !\\nProtoObject subclass: #ObjectOut\\n\\tinstanceVariableNames: 'url page recursionFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!ObjectOut commentStamp: '<historical>' prior: 0!\\nI am a stand-in for an object that is out on the disk. The object that is out on the disk is the head of a tree of objects that are out. See SqueakPage.\\n\\nWhen any message is sent to me, I don't understand it, and bring in my true object. I become myself with the objects and resend the message. \\n\\nI may not represent the object nil. \\nThe file is represented as a url, and that url may point at any file on the net. \\n\\npage is a SqueakPage.\\nIf the cache already has an object, widely in use, that claims to be the object for my url, what do I do? I can't become him, since others believe that he is the true object. Run through memory and replace refs to me with refs to him. Be careful not to trigger a fault. Become me to a string, then find pointers and replace?\\n\\n[[[They don't want to end up holding an ObjectOut. (would oscillate back and forth) This is a problem. A user could bring in two trees that both refer to a 3rd url. (check with cache before installing any new ObjectOut) Two trees could be written to the same url.\\nOr, I remain an ObjectOut, and keep getting notUnderstood, and keep returning the other guy.\\nOr I smash the cache, and install MY page and object. Other guy is a copy -- still in, but with no place in the cache. When we both write to the same url, there will be trouble.] No -- search and replace.]]]\\n!\\n\\n\\n!ObjectOut methodsFor: 'access' stamp: 'tk 1/15/1999 11:43'!\\nurl: aString\\n\\n\\turl _ aString! !\\n\\n!ObjectOut methodsFor: 'access' stamp: 'tk 12/18/1998 21:29'!\\nxxxReset\\n\\t\\\"mark as never brought in\\\"\\n\\trecursionFlag _ nil! !\\n\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/30/1998 15:11'!\\nisInMemory\\n\\t\\\"We are a place holder for an object that is out.\\\"\\n\\t^ false! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/21/1998 12:28'!\\nxxxClass\\n\\t\\\"Primitive. Answer the object which is the receiver's class. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 111>\\n\\tself primitiveFailed! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 15:31'!\\nxxxClone\\n\\n\\t<primitive: 148>\\n\\tself primitiveFailed! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 15:19'!\\nxxxInstVarAt: index \\n\\t\\\"Primitive. Answer a fixed variable in an object. The numbering of the \\n\\tvariables corresponds to the named instance variables. Fail if the index \\n\\tis not an Integer or is not the index of a fixed variable. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 73>\\n\\tself primitiveFailed ! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 14:39'!\\nxxxInstVarAt: anInteger put: anObject \\n\\t\\\"Primitive. Store a value into a fixed variable in the receiver. The \\n\\tnumbering of the variables corresponds to the named instance variables. \\n\\tFail if the index is not an Integer or is not the index of a fixed variable. \\n\\tAnswer the value stored as the result. Using this message violates the \\n\\tprinciple that each object has sovereign control over the storing of \\n\\tvalues into its instance variables. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 74>\\n\\tself primitiveFailed ! !\\n\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'rbb 2/18/2005 14:55'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Bring in the object, install, then resend aMessage\\\"\\n\\t| realObject oldFlag response |\\n\\toldFlag _ recursionFlag.\\n\\trecursionFlag _ true.\\n\\t\\\"fetch the object\\\"\\n\\trealObject _ self xxxFetch.\\t\\t\\\"watch out for the become!!\\\"\\n\\t\\t\\t\\\"Now we ARE the realObject\\\"\\n\\toldFlag == true ifTrue: [\\n\\t\\tresponse _ (UIManager default chooseFrom: #('proceed normally' 'debug')\\n\\t\\t\\ttitle: 'Object being fetched for a second time.\\nShould not happen, and needs to be fixed later.').\\n\\t\\tresponse = 2 ifTrue: [self halt]].\\t\\\"We are already the new object\\\"\\n\\n\\t\\\"Can't be a super message, since this is the first message sent to this object\\\"\\n\\t^ realObject perform: aMessage selector withArguments: aMessage arguments! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'tk 11/16/1998 09:57'!\\nxxxFetch\\n\\t\\\"Bring in my object and replace all references to me with references to him. First try looking up my url in the pageCache. Then try the page (and install it, under its url). Then start from scratch with the url.\\\"\\n\\n\\t| truePage object existing |\\n\\texisting _ SqueakPageCache pageCache at: url ifAbsent: [nil].\\n\\texisting ifNotNil: [existing isContentsInMemory\\n\\t\\tifTrue: [page _ truePage _ existing]].\\t\\\"This url already has an object in this image\\\"\\n\\ttruePage ifNil: [\\n\\t\\ttruePage _ SqueakPageCache atURL: url oldPage: page].\\n\\tobject _ truePage isContentsInMemory \\n\\t\\tifTrue: [truePage contentsMorph]\\n\\t\\tifFalse: [truePage fetchInformIfError].\\t\\\"contents, not the page\\\"\\n\\t\\t\\t\\\"Later, collect pointers to object and fix them up. Not scan memory\\\"\\n\\tobject ifNil: [^ 'Object could not be fetched.'].\\n\\t\\\"recursionFlag _ false.\\\" \\t\\\"while I still have a pointer to myself\\\"\\n\\ttruePage contentsMorph: object.\\n\\tpage _ truePage.\\n\\tself xxxFixup.\\n\\t^ object\\t\\\"the final object!!\\\"\\n ! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'ar 9/27/2005 18:03'!\\nxxxFixup\\n\\t\\\"There is already an object in memory for my url. All pointers to me need to be pointers to him. Can't use become, because other pointers to him must stay valid.\\\"\\n\\n\\t| real temp list |\\n\\treal := page contentsMorph.\\n\\treal == self ifTrue: [page error: 'should be converted by now'].\\n\\ttemp := self.\\n\\tlist := (Utilities pointersTo: temp) asOrderedCollection.\\n\\tlist add: thisContext. list add: thisContext sender.\\n\\tlist do: [:holder |\\n\\t\\t1 to: holder class instSize do:\\n\\t\\t\\t[:i | (holder instVarAt: i) == temp ifTrue: [holder instVarAt: i put: real]].\\n\\t\\t1 to: holder basicSize do:\\n\\t\\t\\t[:i | (holder basicAt: i) == temp ifTrue: [holder basicAt: i put: real]].\\n\\t\\t].\\n\\t^ real! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'tk 10/21/1998 13:01'!\\nxxxSetUrl: aString page: aSqkPage\\n\\n\\turl _ aString.\\n\\tpage _ aSqkPage.! !\\n\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 2/17/2000 22:21'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"Normally this read-in object is exactly what we want to store. Try to dock first. If it is here already, use that one.\\\"\\n\\n\\t| sp |\\n\\t\\\"Transcript show: 'has ref to: ', url; cr.\\\"\\n\\t(sp _ SqueakPageCache pageCache at: page ifAbsent: [nil]) ifNotNil: [\\n\\t\\tsp isContentsInMemory ifTrue: [^ sp contentsMorph]].\\n\\t^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 2/24/1999 11:14'!\\nobjectForDataStream: refStrm\\n \\\"Return an object to store on a data stream (externalize myself).\\\"\\n\\n ^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 14:37'!\\nreadDataFrom: aDataStream size: varsOnDisk\\n\\t\\\"Make self be an object based on the contents of aDataStream, which was generated by the object's storeDataOn: method. Return self.\\\"\\n\\t| cntInstVars |\\n\\tcntInstVars _ self xxxClass instSize.\\n\\tself xxxClass isVariable\\n\\t\\tifTrue: [self xxxClass error: 'needs updating']\\t\\\"assume no variable subclasses\\\"\\n\\t\\tifFalse: [cntInstVars _ varsOnDisk].\\n\\n\\taDataStream beginReference: self.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | self xxxInstVarAt: i put: aDataStream next].\\n\\\"\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | self basicAt: i put: aDataStream next].\\n\\\"\\n\\t^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 15:18'!\\nstoreDataOn: aDataStream\\n\\t\\\"Store myself on a DataStream. See also objectToStoreOnDataStream.\\n\\tmust send 'aDataStream beginInstance:size:'\\\"\\n\\t| cntInstVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\t\\\"cntIndexedVars _ self basicSize.\\\"\\n\\taDataStream\\n\\t\\tbeginInstance: self xxxClass\\n\\t\\tsize: cntInstVars \\\"+ cntIndexedVars\\\".\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self xxxInstVarAt: i)].\\n\\\"\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]\\n\\\"! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 15:29'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. Some classes refuse to be copied. Some classes are picky about which fields get deep copied.\\\"\\n\\t| class index sub subAss new absent |\\n\\tnew _ deepCopier references at: self ifAbsent: [absent _ true].\\n\\tabsent ifNil: [^ new].\\t\\\"already done\\\"\\n\\tclass _ self xxxClass.\\n\\tclass isMeta ifTrue: [^ self].\\t\\t\\\"a class\\\"\\n\\tnew _ self xxxClone.\\n\\t\\\"not a uniClass\\\"\\n\\tdeepCopier references at: self put: new.\\t\\\"remember\\\"\\n\\t\\\"class is not variable\\\"\\n\\tindex _ class instSize.\\n\\t[index > 0] whileTrue: \\n\\t\\t[sub _ self xxxInstVarAt: index.\\n\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\tifNil: [new xxxInstVarAt: index put: (sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\tifNotNil: [new xxxInstVarAt: index put: subAss value].\\n\\t\\tindex _ index - 1].\\n\\tnew rehash.\\t\\\"force Sets and Dictionaries to rehash\\\"\\n\\t^ new\\n! !\\n\\n\\n!ObjectOut methodsFor: '*MorphicExtras-access' stamp: 'tk 12/4/1998 13:01'!\\nsqkPage\\n\\t^ page! !\\n\\n!ObjectOut methodsFor: '*MorphicExtras-access' stamp: 'tk 12/4/1998 13:01'!\\nurl\\n\\t^ url! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectOut class\\n\\tinstanceVariableNames: ''!\\nGenericPropertiesMorph subclass: #ObjectPropertiesMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Experimental'!\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\nadjustTargetBorderWidth: aFractionalPoint\\n\\n\\t| n |\\n\\n\\tmyTarget borderWidth: (n _ (aFractionalPoint x * 10) rounded max: 0).\\n\\tself showSliderFeedback: n.! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\nadjustTargetGradientDirection: aFractionalPoint\\n\\n\\t| fs p |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs direction: (p _ (aFractionalPoint * myTarget extent) rounded).\\n\\tself showSliderFeedback: p.\\n\\tmyTarget changed.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:05'!\\nadjustTargetGradientOrigin: aFractionalPoint\\n\\n\\t| fs p |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs origin: (p _ myTarget topLeft + (aFractionalPoint * myTarget extent) rounded).\\n\\tself showSliderFeedback: p.\\n\\tmyTarget changed.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\nadjustTargetShadowOffset: aFractionalPoint\\n\\n\\t| n |\\n\\n\\tmyTarget changed; layoutChanged.\\n\\tmyTarget shadowOffset: (n _ (aFractionalPoint * 4) rounded).\\n\\tself showSliderFeedback: n.\\n\\tmyTarget changed; layoutChanged.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ndoEnables\\n\\n\\t| itsName fs |\\n\\n\\tfs _ myTarget fillStyle.\\n\\tself allMorphsDo: [ :each |\\n\\t\\titsName _ each knownName.\\n\\t\\titsName == #pickerForColor ifTrue: [\\n\\t\\t\\tself enable: each when: fs isSolidFill | fs isGradientFill\\n\\t\\t].\\n\\t\\titsName == #pickerForBorderColor ifTrue: [\\n\\t\\t\\tself enable: each when: (myTarget respondsTo: #borderColor:)\\n\\t\\t].\\n\\t\\titsName == #pickerForShadowColor ifTrue: [\\n\\t\\t\\tself enable: each when: myTarget hasDropShadow\\n\\t\\t].\\n\\t\\titsName == #pickerFor2ndGradientColor ifTrue: [\\n\\t\\t\\tself enable: each when: fs isGradientFill\\n\\t\\t].\\n\\t].\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\nmakeTargetGradientFill\\n\\n\\tmyTarget useGradientFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\nmakeTargetSolidFill\\n\\n\\tmyTarget useSolidFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\nnumberOneColor\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^myTarget color].\\n\\t^myTarget fillStyle colorRamp first value\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'gm 2/16/2003 20:36'!\\nnumberOneColor: aColor \\n\\tmyTarget fillStyle isGradientFill \\n\\t\\tifFalse: \\n\\t\\t\\t[^(myTarget isSystemWindow) \\n\\t\\t\\t\\tifTrue: [myTarget setWindowColor: aColor]\\n\\t\\t\\t\\tifFalse: [myTarget fillStyle: aColor]].\\n\\tmyTarget fillStyle \\n\\t\\tfirstColor: aColor\\n\\t\\tforMorph: myTarget\\n\\t\\thand: nil! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'dgd 10/8/2003 19:35'!\\nrebuild\\n\\n\\tself removeAllMorphs.\\n\\tself addARow: {\\n\\t\\tself lockedString: ('Properties for {1}' translated format: {myTarget name}).\\n\\t}.\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\tself paneForCornerRoundingToggle.\\n\\t\\t\\tself paneForStickinessToggle.\\n\\t\\t\\tself paneForLockedToggle.\\n\\t\\t}.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself paneForMainColorPicker.\\n\\t\\tself paneFor2ndGradientColorPicker.\\n\\t}.\\n\\tself addARow: {\\n\\t\\tself paneForBorderColorPicker.\\n\\t\\tself paneForShadowColorPicker.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself \\n\\t\\t\\tbuttonNamed: 'Accept' translated action: #doAccept color: color lighter \\n\\t\\t\\thelp: 'keep changes made and close panel' translated.\\n\\t\\tself \\n\\t\\t\\tbuttonNamed: 'Cancel' translated action: #doCancel color: color lighter \\n\\t\\t\\thelp: 'cancel changes made and close panel' translated.\\n\\t}, self rebuildOptionalButtons.\\n\\n\\tthingsToRevert _ Dictionary new.\\n\\t\\\"thingsToRevert at: #fillStyle: put: myTarget fillStyle.\\\"\\n\\tmyTarget isSystemWindow ifTrue: [\\n\\t\\tthingsToRevert at: #setWindowColor: put: myTarget paneColorToUse\\n\\t].\\n\\tthingsToRevert at: #hasDropShadow: put: myTarget hasDropShadow.\\n\\tthingsToRevert at: #shadowColor: put: myTarget shadowColor.\\n\\t(myTarget respondsTo: #borderColor:) ifTrue: [\\n\\t\\tthingsToRevert at: #borderColor: put: myTarget borderColor.\\n\\t].\\n\\n\\tthingsToRevert at: #borderWidth: put: myTarget borderWidth.\\n\\tthingsToRevert at: #cornerStyle: put: myTarget cornerStyle.\\n\\tthingsToRevert at: #sticky: put: myTarget isSticky.\\n\\tthingsToRevert at: #lock: put: myTarget isLocked.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'wiz 9/21/2005 22:42'!\\nrebuildOptionalButtons\\n\\n\\t| answer |\\n\\n\\tanswer _ #() .\\n\\t\\n\\tmyTarget isTextMorph ifTrue: [\\n\\t\\tanswer _ answer, {\\n\\t\\t\\tself \\n\\t\\t\\t\\tbuttonNamed: 'Text' translated action: #doTextProperties color: color lighter \\n\\t\\t\\t\\thelp: 'open a text properties panel for the morph' translated.\\n\\t\\t}.\\n\\t].\\n\\t^answer! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'ar 8/25/2001 18:30'!\\ntargetBorderColor\\n\\t^myTarget borderStyle baseColor! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/26/2001 15:29'!\\ntargetBorderColor: aColor\\n\\t\\\"Need to replace the borderStyle or BorderedMorph will not 'feel' the change\\\"\\n\\tmyTarget borderStyle: (myTarget borderStyle copy baseColor: aColor).! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\ntargetHasGradientFill\\n\\n\\t^myTarget fillStyle isGradientFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:01'!\\ntargetHasSolidFill\\n\\n\\t^myTarget fillStyle isSolidFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntargetRadial\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^false].\\n\\t^myTarget fillStyle radial! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntgt2ndGradientColor\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^Color black].\\n\\t^myTarget fillStyle colorRamp last value! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntgt2ndGradientColor: aColor\\n\\n\\tmyTarget fillStyle lastColor: aColor forMorph: myTarget hand: nil\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 2/20/2001 17:45'!\\ntoggleTargetGradientFill\\n\\n\\tself targetHasGradientFill ifTrue: [\\n\\t\\tself makeTargetSolidFill\\n\\t] ifFalse: [\\n\\t\\tself makeTargetGradientFill\\n\\t].\\n\\tself doEnables! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\ntoggleTargetRadial\\n\\n\\t| fs |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs radial: fs radial not.\\n\\tmyTarget changed.\\n\\tself doEnables.! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 2/20/2001 17:48'!\\ntoggleTargetSolidFill\\n\\n\\tself targetHasSolidFill ifTrue: [\\n\\t\\tself makeTargetGradientFill\\n\\t] ifFalse: [\\n\\t\\tself makeTargetSolidFill\\n\\t].\\n\\tself doEnables! !\\n\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ndefaultBorderColor\\n\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ self defaultColor darker! !\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 0.548\\n\\t\\tg: 0.839\\n\\t\\tb: 0.452! !\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tmyTarget\\n\\t\\tifNil: [myTarget _ RectangleMorph new openInWorld].\\n\\tself rebuild! !\\n\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'sd 11/13/2003 21:03'!\\nborderPrototype: aBorderStyle help: helpString\\n\\t| selector proto |\\n\\tselector _ BorderedMorph new.\\n\\tselector borderWidth: 0.\\n\\tselector color: Color transparent.\\n\\tproto _ Morph new extent: 16@16.\\n\\tproto color: Color transparent.\\n\\tproto borderStyle: aBorderStyle.\\n\\tselector extent: proto extent + 4.\\n\\tselector addMorphCentered: proto.\\n\\t(myTarget canDrawBorder: aBorderStyle) ifTrue:[\\n\\t\\tselector setBalloonText: helpString.\\n\\t\\tselector on: #mouseDown send: #toggleBorderStyle:with:from: to: self withValue: proto.\\n\\t\\t(myTarget borderStyle species == aBorderStyle species and:[\\n\\t\\t\\tmyTarget borderStyle style == aBorderStyle style]) ifTrue:[selector borderWidth: 1].\\n\\t] ifFalse:[\\n\\t\\tselector setBalloonText: 'This border style cannot be used here' translated.\\n\\t\\tselector on: #mouseDown send: #beep to: Beeper.\\n\\t\\tselector addMorphCentered: ((Morph new) color: (Color black alpha: 0.5); extent: selector extent).\\n\\t].\\n\\t^selector! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneFor2ndGradientColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\t(self inAColumn: {\\n\\t\\t\\t\\tself colorPickerFor: self getter: #tgt2ndGradientColor setter: #tgt2ndGradientColor:.\\n\\t\\t\\t\\tself lockedString: '2nd gradient color' translated.\\n\\t\\t\\t\\tself paneForRadialGradientToggle hResizing: #shrinkWrap.\\n\\t\\t\\t\\t(\\n\\t\\t\\t\\t\\tself inARow: {self paneForGradientOrigin. self paneForGradientDirection}\\n\\t\\t\\t\\t) hResizing: #shrinkWrap.\\n\\t\\t\\t}\\n\\t\\t\\tnamed: #pickerFor2ndGradientColor) layoutInset: 0.\\n\\t\\t\\tself paneForGradientFillToggle hResizing: #shrinkWrap \\n\\t\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:23'!\\npaneForBorderColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\tself \\n\\t\\t\\t\\tcolorPickerFor: self\\n\\t\\t\\t\\tgetter: #targetBorderColor\\n\\t\\t\\t\\tsetter: #targetBorderColor:.\\n\\t\\t\\tself lockedString: 'Border Color' translated.\\n\\t\\t\\t(self paneForBorderStyle) hResizing: #shrinkWrap; layoutInset: 5.\\n\\t\\t\\tself lockedString: 'Border style' translated.\\n\\t\\t\\tself paneForBorderWidth.\\n\\t\\t} \\n\\t\\tnamed: #pickerForBorderColor.\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:25'!\\npaneForBorderStyle\\n\\n\\t^self inARow: {\\n\\t\\tself borderPrototype: (BorderStyle width: 4 color: Color black)\\n\\t\\t\\thelp:'Click to select a simple colored border' translated.\\n\\t\\tself borderPrototype: (BorderStyle raised width: 4)\\n\\t\\t\\thelp:'Click to select a simple raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle inset width: 4)\\n\\t\\t\\thelp:'Click to select a simple inset border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexFramed width: 4)\\n\\t\\t\\thelp:'Click to select a complex framed border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexRaised width: 4)\\n\\t\\t\\thelp:'Click to select a complex raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexInset width: 4)\\n\\t\\t\\thelp:'Click to select a complex inset border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltFramed width: 4)\\n\\t\\t\\thelp:'Click to select a complex framed border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltRaised width: 4)\\n\\t\\t\\thelp:'Click to select a complex raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltInset width: 4)\\n\\t\\t\\thelp:'Click to select a complex inset border' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:29'!\\npaneForBorderWidth\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Border width' translated\\n\\t\\t\\tselector: #adjustTargetBorderWidth:\\n\\t\\t\\thelp: 'Drag in here to change the border width' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:18'!\\npaneForCornerRoundingToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #wantsRoundedCorners setter: #toggleCornerRounding\\n\\t\\t\\thelp: 'Turn rounded corners on or off' translated.\\n\\t\\tself lockedString: ' Rounded corners' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:40'!\\npaneForDropShadowToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #hasDropShadow setter: #toggleDropShadow\\n\\t\\t\\thelp: 'Turn drop shadows on or off' translated.\\n\\t\\tself lockedString: ' Drop shadow color' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:22'!\\npaneForGradientDirection\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Direction' translated\\n\\t\\t\\tselector: #adjustTargetGradientDirection:\\n\\t\\t\\thelp: 'Drag in here to change the direction of the gradient' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:22'!\\npaneForGradientFillToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetHasGradientFill\\n\\t\\t\\tsetter: #toggleTargetGradientFill\\n\\t\\t\\thelp: 'Turn gradient fill on or off' translated.\\n\\t\\tself lockedString: ' Gradient fill' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneForGradientOrigin\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Origin' translated\\n\\t\\t\\tselector: #adjustTargetGradientOrigin:\\n\\t\\t\\thelp: 'Drag in here to change the origin of the gradient' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:19'!\\npaneForLockedToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #isLocked setter: #toggleLocked\\n\\t\\t\\thelp: 'Turn lock on or off' translated.\\n\\t\\tself lockedString: ' Lock' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:20'!\\npaneForMainColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\tself \\n\\t\\t\\t\\tcolorPickerFor: self \\n\\t\\t\\t\\tgetter: #numberOneColor \\n\\t\\t\\t\\tsetter: #numberOneColor:.\\n\\t\\t\\tself lockedString: 'Color' translated.\\n\\t\\t\\t(self paneForSolidFillToggle) hResizing: #shrinkWrap.\\n\\t\\t} \\n\\t\\tnamed: #pickerForColor.\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneForRadialGradientToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetRadial setter: #toggleTargetRadial\\n\\t\\t\\thelp: 'Turn radial gradient on or off' translated.\\n\\t\\tself lockedString: ' Radial gradient' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'RAA 3/8/2001 18:03'!\\npaneForShadowColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\t(self inAColumn: {\\n\\t\\t\\t\\tself colorPickerFor: myTarget getter: #shadowColor setter: #shadowColor:.\\n\\t\\t\\t\\tself paneForShadowOffset.\\n\\t\\t\\t}\\n\\t\\t\\tnamed: #pickerForShadowColor) layoutInset: 0.\\n\\t\\t\\tself paneForDropShadowToggle hResizing: #shrinkWrap.\\n\\t\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:36'!\\npaneForShadowOffset\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Offset' translated\\n\\t\\t\\tselector: #adjustTargetShadowOffset:\\n\\t\\t\\thelp: 'Drag in here to change the offset of the shadow' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:20'!\\npaneForSolidFillToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetHasSolidFill\\n\\t\\t\\tsetter: #toggleTargetSolidFill\\n\\t\\t\\thelp: 'Turn solid fill on or off' translated.\\n\\t\\tself lockedString: ' Solid fill' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:18'!\\npaneForStickinessToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #isSticky setter: #toggleStickiness\\n\\t\\t\\thelp: 'Turn stickiness on or off' translated.\\n\\t\\tself lockedString: ' Sticky' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'ar 8/25/2001 18:35'!\\ntoggleBorderStyle: provider with: arg1 from: arg2\\n\\t| oldStyle newStyle |\\n\\toldStyle _ myTarget borderStyle.\\n\\tnewStyle _ provider borderStyle copy.\\n\\toldStyle width = 0 \\n\\t\\tifTrue:[newStyle width: 2]\\n\\t\\tifFalse:[newStyle width: oldStyle width].\\n\\tnewStyle baseColor: oldStyle baseColor.\\n\\tmyTarget borderStyle: newStyle.\\n\\tprovider owner owner submorphsDo:[:m| m borderWidth: 0].\\n\\tprovider owner borderWidth: 1.! !\\nAlignmentMorph subclass: #ObjectRepresentativeMorph\\n\\tinstanceVariableNames: 'objectRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n\\n!ObjectRepresentativeMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/1/2000 15:55'!\\nobjectRepresented: anObject\\n\\t\\\"Set the receiver's representee. This clears out any preexisting state in the receiver\\\"\\n\\n\\tobjectRepresented _ anObject.\\n\\tself removeAllMorphs.\\n\\tself hResizing: #shrinkWrap. \\n\\tself vResizing: #shrinkWrap.\\n\\tself addMorphBack: (StringMorph new contents: anObject name asString).\\n\\tself setNameTo: anObject name\\n\\t! !\\n\\n!ObjectRepresentativeMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/1/2000 15:55'!\\nobjectRepresented: anObject labelString: aLabel\\n\\t\\\"Set the receiver's representee as indicated, and use the given label to tag it\\\"\\n\\n\\tobjectRepresented _ anObject.\\n\\tself removeAllMorphs.\\n\\tself hResizing: #shrinkWrap. \\n\\tself vResizing: #shrinkWrap.\\n\\tself addMorphBack: (StringMorph new contents: aLabel asString).\\n\\tself setNameTo: aLabel asString\\n\\t! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'macpal' stamp: 'sw 10/17/2000 11:42'!\\nobjectRepresented\\n\\t\\\"Answer the object represented by the receiver\\\"\\n\\n\\t^ objectRepresented! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:22'!\\nnameOfObjectRepresented\\n\\t\\\"Answer the external name of the object represented\\\"\\n\\n\\t^ objectRepresented externalName! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'scripting' stamp: 'sw 10/17/2000 11:35'!\\ncategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer, in order\\\"\\n\\n\\t^ objectRepresented class organization categories\\n! !\\nObject subclass: #ObjectScanner\\n\\tinstanceVariableNames: 'pvt3SmartRefStrm'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Object Storage'!\\n!ObjectScanner commentStamp: '<historical>' prior: 0!\\nAn instance of this class is the compiler's context for filing in a SmartRefStream containing instance-specific classes. When the old name of a new object's class conflicts with an existing class name, install a class var in me. It has the old name but points at the new class. The compiler uses it when compiling the code in the fileIn. Fill the SmartRefStream's renamed class dictionary.\\n\\nAn object fileout:\\n!!ObjectScanner new initialize!! \\\"allow me to take control with scanFrom:\\\"\\n\\nPlayer subclass: Player23 instanceVariableNames: 'foo' classVariableNames: '' \\n\\tpoolDictionaries: nil category: 'Instance Specific'!!\\n\\t\\\"I prescan this and (self rename: #Player23 toBe: #Player30)\\\"\\n\\n!!Player23 methodsFor: 'all' stamp: 'tk 3/9/98 18:58'!!\\t\\\"actually sent to Player30\\\"\\nfoo\\n\\t^ foo!! !!\\n\\n!!self smartRefStream!!<binary representation of the objects>!!\\n\\n\\n!\\n\\n\\n!ObjectScanner methodsFor: 'accessing' stamp: 'tk 3/15/98 19:33'!\\nsmartRefStream\\n\\n\\t^ pvt3SmartRefStrm! !\\n\\n\\n!ObjectScanner methodsFor: 'initialize-release' stamp: 'tk 3/15/98 20:17'!\\nclear\\n\\t\\\"remove all old class vars. They were UniClasses being remapped to aviod a name conflict.\\\"\\n\\n\\tself class classPool keys do: [:key |\\n\\t\\tself class classPool removeKey: key].\\t\\\"brute force\\\"! !\\n\\n!ObjectScanner methodsFor: 'initialize-release' stamp: 'tk 8/15/1998 15:26'!\\ninitialize\\n\\t\\\"remove all old class vars that are not instance-specific classes being renamed\\\"\\n\\n\\tself clear.\\n\\t\\\"Most importantly, return self, so a fileIn will let ObjectScanner seize control. So UniClasses can be remapped. See the transfer of control where ReadWriteStream fileIn calls scanFrom:\\\"! !\\n\\n\\n!ObjectScanner methodsFor: 'scanning' stamp: 'yo 11/11/2002 10:27'!\\nlookAhead: aChunk\\n\\t\\\"See if this chunk is a class Definition, and if the new class name already exists and is instance-specific. Modify the chunk, and record the rename in the SmartRefStream and in me.\\\"\\n\\n\\t| pieces sup oldName existing newName newDefn |\\n\\taChunk size < 90 ifTrue: [^ aChunk].\\t\\t\\\"class defn is big!!\\\"\\n\\t(aChunk at: 1) == $!! ifTrue: [^ aChunk].\\t\\\"method def, fast exit\\\"\\n\\tpieces _ (aChunk copyFrom: 1 to: (300 min: aChunk size)) findTokens: ' #\\t\\\\' withCRs.\\n\\tpieces size < 3 ifTrue: [^ aChunk].\\t\\\"really bigger, but just took front\\\"\\n\\t(pieces at: 2) = 'subclass:' ifFalse: [^ aChunk].\\n\\tsup _ Smalltalk at: (pieces at: 1) asSymbol ifAbsent: [^ aChunk].\\n\\tsup class class == Metaclass ifFalse: [^ aChunk].\\n\\t((oldName _ pieces at: 3) at: 1) canBeGlobalVarInitial ifFalse: [^ aChunk].\\n\\toldName _ oldName asSymbol.\\n\\t(Smalltalk includesKey: oldName) ifFalse: [^ aChunk].\\t\\\"no conflict\\\"\\n\\texisting _ Smalltalk at: oldName.\\n\\t(existing isKindOf: Class) ifFalse: [^ aChunk].\\t\\\"Write over non-class global\\\"\\n\\texisting isSystemDefined ifTrue: [^ aChunk].\\t\\\"Go ahead and redefine it!!\\\"\\n\\t\\\"Is a UniClass\\\"\\n\\tnewName _ sup chooseUniqueClassName.\\n\\tnewDefn _ aChunk copyReplaceAll: oldName with: newName.\\n\\tCompiler evaluate: newDefn for: self logged: true.\\t\\\"Create the new class\\\"\\n\\tself rename: oldName toBe: newName.\\n\\t^ newName asString\\t\\t\\\"to be evaluated\\\"\\n! !\\n\\n!ObjectScanner methodsFor: 'scanning' stamp: 'tk 3/15/98 20:22'!\\nscanFrom: aByteStream\\n\\t\\\"Sieze control of the fileIn. Put myself in as the context. If any UniClasses (for just one instance) are defined, they will do it through me, and I will look for conflicting class names. If so, install the old name as a class var of me, so the compile will work. Tell my SmartRefStream about renaming the class.\\\"\\n\\n\\t| valWithOddName47 scannerNamed53 chunkNamed117 |\\n\\tpvt3SmartRefStrm _ SmartRefStream on: aByteStream.\\n\\taByteStream ascii.\\n\\t[aByteStream atEnd] whileFalse:\\n\\t\\t[aByteStream skipSeparators.\\n\\t\\tvalWithOddName47 _ (aByteStream peekFor: $!!)\\n\\t\\t\\tifTrue: [chunkNamed117 _ aByteStream nextChunk.\\t\\\"debug\\\"\\n\\t\\t\\t\\t\\tscannerNamed53 _ Compiler evaluate: chunkNamed117\\n\\t\\t\\t\\t\\t\\t\\tfor: self logged: false.\\n\\t\\t\\t\\t\\tscannerNamed53 class == self class \\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"I already am the scanner for this file\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [scannerNamed53 scanFrom: aByteStream]]\\n\\t\\t\\tifFalse: [chunkNamed117 _ aByteStream nextChunk.\\n\\t\\t\\t\\t\\tchunkNamed117 _ self lookAhead: chunkNamed117.\\n\\t\\t\\t\\t\\tCompiler evaluate: chunkNamed117 for: self logged: true].\\n\\t\\taByteStream skipStyleChunk].\\n\\t^ valWithOddName47! !\\n\\n\\n!ObjectScanner methodsFor: 'utilities' stamp: 'tk 3/15/98 20:21'!\\nrename: existingName toBe: newName\\n\\t\\\"See if there is a conflict between what the fileIn wants to call the new UniClass (Player23) and what already exists for another unique instance. If conflict, make a class variable to intercept the existingName and direct it to class newName.\\\"\\n\\n\\texistingName = newName ifFalse: [\\n\\t\\tself class ensureClassPool.\\t\\\"create the dictionary\\\"\\n\\t\\t\\\"can't use addClassVarName: because it checks for conflicts with Smalltalk\\\"\\n\\t\\t(self class classPool includesKey: existingName) ifFalse: \\n\\t\\t\\t[\\\"Pick up any refs in Undeclared\\\"\\n\\t\\t\\tself class classPool declare: existingName from: Undeclared].\\n\\t\\tself class classPool at: existingName put: (Smalltalk at: newName).\\n\\t\\tpvt3SmartRefStrm renamed at: existingName put: newName]! !\\nStream subclass: #ObjectSocket\\n\\tinstanceVariableNames: 'socket outBuf outBufIndex outBufSize inBuf inBufIndex inBufLastIndex outObjects inObjects'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n!ObjectSocket commentStamp: 'ls 2/10/2005 21:27' prior: 0!\\nThis is a socket which exchanges medium-level packets instead of low-level bytes. This class is abstract; see the subclasses for particular kinds of medium-level packets which can be used.!\\n\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ndestroy\\n\\tsocket destroy.\\n\\tsocket := nil.! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'RAA 7/20/2000 15:10'!\\nisConnected\\n\\n\\t^socket notNil and: [socket isConnected]! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'ls 1/8/1999 16:14'!\\nprocessIO\\n\\t\\\"do some as much network IO as possible\\\"\\n\\n\\tself processOutput.\\n\\tself processInput.! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'RAA 8/4/2000 15:38'!\\nremoteAddress\\n\\n\\tself isConnected ifFalse: [^nil].\\n\\t^socket remoteAddress! !\\n\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\naddToInBuf: aString\\n\\n\\t| newAlloc |\\n\\tnewAlloc := aString size * 2 max: 8000.\\n\\tinBuf ifNil: [\\n\\t\\tinBuf := String new: newAlloc.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBufLastIndex := 0.\\n\\t].\\n\\taString size > (inBuf size - inBufLastIndex) ifTrue: [\\n\\t\\tinBuf := inBuf , (String new: newAlloc)\\n\\t].\\n\\tinBuf \\n\\t\\treplaceFrom: inBufLastIndex + 1 \\n\\t\\tto: inBufLastIndex + aString size\\n\\t\\twith: aString \\n\\t\\tstartingAt: 1.\\n\\tinBufLastIndex := inBufLastIndex + aString size.\\n! !\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\nprocessOutput\\n\\t\\\"loop sending data as long as there is data to send, and the socket is ready to receive more data\\\"\\n\\t[ socket sendDone and: [ outBuf notNil or: [ outObjects isEmpty not ] ] ] whileTrue: [\\n\\t\\t| amountSent |\\n\\n\\t\\toutBuf isNil ifTrue: [\\n\\t\\t\\t| nextSize |\\n\\t\\t\\t\\\"no data in the current buffer; make a new buffer and encode some more\\\"\\n\\t\\t\\toutBuf := String new: ((self spaceToEncode: outObjects first) max: 8000).\\n\\t\\t\\toutBufIndex := 1.\\n\\t\\t\\toutBufSize := 0.\\n\\n\\t\\t\\t[\\toutObjects isEmpty not and: [\\n\\t\\t\\t\\t\\tnextSize := self spaceToEncode: outObjects first.\\n\\t\\t\\t\\t\\tnextSize <= (outBuf size - outBufSize + 1) ]\\n\\t\\t\\t] whileTrue: [\\n\\t\\t\\t\\tself encodeObject: outObjects first into: outBuf startingAt: outBufSize+1.\\n\\t\\t\\t\\toutBufSize := outBufSize + nextSize.\\n\\t\\t\\t\\toutObjects removeFirst ] ].\\n\\n\\t\\t\\\"at this point, the buffer definitely has data in it to send. Send some\\\"\\n\\t\\tamountSent := socket sendSomeData: outBuf startIndex: outBufIndex count: (outBufSize - outBufIndex + 1).\\n\\t\\toutBufIndex := outBufIndex + amountSent.\\n\\t\\toutBufIndex > outBufSize ifTrue: [ outBuf := nil ] ].\\n\\n! !\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\nshrinkInBuf\\n\\n\\tinBuf ifNil: [^self].\\n\\tinBufLastIndex < inBufIndex ifTrue: [\\n\\t\\tinBufLastIndex := 0.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBuf size > 20000 ifTrue: [inBuf := nil].\\t\\\"if really big, kill it\\\"\\n\\t\\t^self\\n\\t].\\n\\tinBuf := inBuf copyFrom: inBufIndex to: inBufLastIndex.\\n\\tinBufLastIndex := inBuf size.\\n\\tinBufIndex := 1.\\n\\n! !\\n\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnext\\n\\t^inObjects removeFirst\\t! !\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnextOrNil\\n\\tinObjects isEmpty\\n\\t\\tifTrue: [ ^nil ]\\n\\t\\tifFalse: [ ^inObjects removeFirst ]! !\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnextPut: anObject\\n\\toutObjects addLast: anObject! !\\n\\n\\n!ObjectSocket methodsFor: 'private-initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize: aSocket\\n\\tsocket := aSocket.\\n\\tinBuf := String new: 1000.\\n\\tinBufIndex := 1.\\n\\tinBufLastIndex := 0.\\n\\n\\toutBuf := nil.\\n\\n\\tinObjects := OrderedCollection new.\\n\\toutObjects := OrderedCollection new.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectSocket class methodsFor: 'as yet unclassified' stamp: 'RAA 7/20/2000 15:47'!\\non: aSocket\\n\\n\\t^self basicNew initialize: aSocket! !\\nClassTestCase subclass: #ObjectTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Objects'!\\n\\n!ObjectTest methodsFor: 'tests' stamp: 'md 11/26/2004 16:37'!\\ntestBecome\\n\\t\\\"self debug: #testBecome\\\"\\n\\t\\\"this test should that all the variables pointing to an object are pointing now to another one, and all\\n object pointing to the other are pointing to the object\\\"\\n\\n\\t| pt1 pt2 pt3 |\\n\\tpt1 := 0@0.\\n\\tpt2 := pt1.\\n\\tpt3 := 100@100.\\n\\n\\tpt1 become: pt3.\\n\\tself assert: pt2 = (100@100).\\n\\tself assert: pt3 = (0@0).\\n\\tself assert: pt1 = (100@100).! !\\n\\n!ObjectTest methodsFor: 'tests' stamp: 'md 11/26/2004 16:36'!\\ntestBecomeForward\\n\\t\\\"self debug: #testBecomeForward\\\"\\n\\t\\\"this test should that all the variables pointing to an object are pointing now to another one.\\n\\tNot that this inverse is not true. This kind of become is called oneWayBecome in VW\\\"\\n\\n\\t| pt1 pt2 pt3 |\\n\\tpt1 := 0@0.\\n\\tpt2 := pt1.\\n\\tpt3 := 100@100.\\n\\tpt1 becomeForward: pt3.\\n\\tself assert: pt2 = (100@100).\\n\\tself assert: pt3 == pt2.\\n\\tself assert: pt1 = (100@100)! !\\n\\n\\n!ObjectTest methodsFor: 'tests - debugging' stamp: 'sd 6/5/2005 09:05'!\\ntestAssert\\n\\n\\tself shouldnt: [Object assert: [true]] raise: Error.\\n\\tself shouldnt: [Object assert: true] raise: Error.\\n\\tself should: [Object assert: [false]] raise: AssertionFailure.\\n\\tself should: [Object assert: false] raise: AssertionFailure.! !\\n\\n!ObjectTest methodsFor: 'tests - debugging' stamp: 'sd 6/5/2005 09:05'!\\ntestHaltIf\\n\\n\\tself should: [self haltIf: true] raise: Halt.\\n\\tself shouldnt: [self haltIf: false] raise: Halt.\\n\\n\\tself should: [self haltIf: [true]] raise: Halt.\\n\\tself shouldnt: [self haltIf: [false]] raise: Halt.\\n\\n\\tself should: [self haltIf: #testHaltIf.] raise: Halt.\\n\\tself shouldnt: [self haltIf: #teadfasdfltIf.] raise: Halt.\\n\\n\\tself should: [self a] raise: Halt.\\n\\tself shouldnt: [self a1] raise: Halt.\\n\\n\\tself should: [self haltIf: [:o | o class = self class]] raise: Halt.\\n\\tself shouldnt: [self haltIf: [:o | o class ~= self class]] raise: Halt.\\n! !\\n\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:45'!\\na\\n\\tself b.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:46'!\\na1\\n\\tself b1.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:45'!\\nb\\n\\tself haltIf: #testHaltIf.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:46'!\\nb1\\n\\tself haltIf: #testasdasdfHaltIf.! !\\nProtoObject subclass: #ObjectTracer\\n\\tinstanceVariableNames: 'tracedObject recursionFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'.\\nObjectTracer superclass: nil!\\n!ObjectTracer commentStamp: '<historical>' prior: 0!\\nAn ObjectTracer can be wrapped around another object, and then give you a chance to inspect it whenever it receives messages from the outside. For instance...\\n\\t(ObjectTracer on: Display) flash: (50@50 extent: 50@50)\\nwill give control to a debugger just before the message flash is sent.\\nObviously this facility can be embellished in many useful ways.\\nSee also the even more perverse subclass, ObjectViewer, and its example.\\n!\\n\\n\\n!ObjectTracer methodsFor: 'very few messages' stamp: 'ar 9/27/2005 20:24'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"All external messages (those not caused by the re-send) get trapped here\\\"\\n\\t\\\"Present a dubugger before proceeding to re-send the message\\\"\\n\\n\\tToolSet debugContext: thisContext\\n\\t\\t\\t\\tlabel: 'About to perform: ', aMessage selector\\n\\t\\t\\t\\tcontents: nil.\\n\\t^ aMessage sentTo: tracedObject.\\n! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxUnTrace\\n\\n\\ttracedObject become: self! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxViewedObject\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\t^ tracedObject! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxViewedObject: anObject\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\ttracedObject _ anObject! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectTracer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectTracer class methodsFor: 'instance creation'!\\non: anObject\\n\\t^ self new xxxViewedObject: anObject! !\\nObjectTracer subclass: #ObjectViewer\\n\\tinstanceVariableNames: 'valueBlock lastValue changeBlock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!ObjectViewer commentStamp: '<historical>' prior: 0!\\nObjectViewers offers the same kind of interception of messages (via doesnotUnderstand:) as ObjectTracers, but instead of just being wrappers, they actually replace the object being viewed. This makes them a lot more dangerous to use, but one can do amazing things. For instance, the example below actually intercepts the InputSensor object, and prints the mouse coordinates asynchronously, every time they change:\\n\\tSensor evaluate: [Sensor cursorPoint printString displayAt: 0@0]\\n\\t\\twheneverChangeIn: [Sensor cursorPoint].\\nTo exit from this example, execute:\\n\\tSensor xxxUnTrace\\n!\\n\\n\\n!ObjectViewer methodsFor: 'very few messages'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Check for change after sending aMessage\\\"\\n\\t| returnValue newValue |\\n\\trecursionFlag ifTrue: [^ aMessage sentTo: tracedObject].\\n\\trecursionFlag _ true.\\n\\treturnValue _ aMessage sentTo: tracedObject.\\n\\tnewValue _ valueBlock value.\\n\\tnewValue = lastValue ifFalse:\\n\\t\\t[changeBlock value.\\n\\t\\tlastValue _ newValue].\\n\\trecursionFlag _ false.\\n\\t^ returnValue! !\\n\\n!ObjectViewer methodsFor: 'very few messages'!\\nxxxViewedObject: viewedObject evaluate: block1 wheneverChangeIn: block2\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\ttracedObject _ viewedObject.\\n\\tvalueBlock _ block2.\\n\\tchangeBlock _ block1.\\n\\trecursionFlag _ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectViewer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectViewer class methodsFor: 'instance creation'!\\non: viewedObject evaluate: block1 wheneverChangeIn: block2\\n\\t^ self new xxxViewedObject: viewedObject evaluate: block1 wheneverChangeIn: block2! !\\nObject subclass: #ObjectWithDocumentation\\n\\tinstanceVariableNames: 'authoringStamp properties elementSymbol naturalLanguageTranslations'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Kernel'!\\n!ObjectWithDocumentation commentStamp: '<historical>' prior: 0!\\nObjectWithDocumentation - an abstract superclass for objects that allows maintenance of an authoring stamp, a body of documentation, and a properties dictionary.\\nThe Properties implementation has not happened yet -- it would closely mirror the implemenation of properties in the MorphExtension, for example.!\\n\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:21'!\\ndocumentation\\n\\t\\\"Answer the receiver's documentation\\\"\\n\\n\\t^self helpMessage! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 19:33'!\\ndocumentation: somethingUsefulHopefully\\n\\t\\\"Set the receiver's documentation, in the current langauge\\\"\\n\\n\\tself helpMessage: somethingUsefulHopefully! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'sw 8/18/2004 20:23'!\\nhelpMessage\\n\\t\\\"Check if there is a getterSetterHelpMessage. \\n\\tOtherwise try the normal help message or return nil.\\\"\\n\\n\\t^ self getterSetterHelpMessage\\n\\t\\tifNil: [(self propertyAt: #helpMessage ifAbsent:\\n\\t\\t\\t[self legacyHelpMessage ifNil: [^ nil]]) translated]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 19:32'!\\nhelpMessage: somethingUsefulHopefully\\n\\t\\\"Set the receiver's documentation, in the current langauge\\\"\\n\\n\\tself propertyAt: #helpMessage put: somethingUsefulHopefully! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nlegacyHelpMessage\\n\\t\\\"If I have a help message stashed in my legacy naturalTranslations slot, answer its translated rendition, else answer nil. If I *do* come across a legacy help message, transfer it to my properties dictionary.\\\"\\n\\n\\t| untranslated |\\n\\tnaturalLanguageTranslations isEmptyOrNil \\\"only in legacy (pre-3.8) projects\\\"\\n\\t\\tifTrue: [^ nil].\\n\\tuntranslated := naturalLanguageTranslations first helpMessage ifNil: [^ nil].\\n\\tself propertyAt: #helpMessage put: untranslated.\\n\\tnaturalLanguageTranslations removeFirst.\\n\\tnaturalLanguageTranslations isEmpty ifTrue: [naturalLanguageTranslations := nil].\\n\\t^ untranslated translated! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 23:57'!\\nuntranslatedHelpMessage\\n\\t\\\"Check if there is a getterSetterHelpMessage. \\n\\tOtherwise try the normal help message or return nil.\\\"\\n\\n\\t^(self propertyAt: #getterSetterHelpMessage ifAbsent: [nil])\\n\\t\\tifNil: [(self propertyAt: #helpMessage ifAbsent: [nil])]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 23:56'!\\nuntranslatedWording\\n\\t\\\"Answer the receiver's wording\\\"\\n\\n\\t^self propertyAt: #wording ifAbsent: [nil]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:34'!\\nwording\\n\\t\\\"Answer the receiver's wording\\\"\\n\\n\\t| wording |\\n\\t(wording := self propertyAt: #wording ifAbsent: [nil])\\n\\t\\tifNotNil: [^wording translated].\\n\\n\\tself initWordingAndDocumentation.\\n\\t^self propertyAt: #wording ifAbsent: ['']! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:39'!\\nwording: aString\\n\\t\\\"Set the receiver's wording, in the current langauge\\\"\\n\\n\\tself propertyAt: #wording put: aString! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'documentation' stamp: 'rbb 3/1/2005 11:02'!\\neditDescription\\n\\t\\\"Allow the user to see and edit the documentation for this object\\\"\\n\\t| reply helpMessage |\\n\\thelpMessage := self documentation isNil\\n\\t\\t\\t\\tifTrue: [String new]\\n\\t\\t\\t\\tifFalse: [self documentation].\\n\\treply := UIManager default\\n\\t\\t\\t\\tmultiLineRequest: 'Kindly edit the description' translated\\n\\t\\t\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\t\\t\\tinitialAnswer: helpMessage\\n\\t\\t\\t\\tanswerHeight: 200.\\n\\treply isEmptyOrNil\\n\\t\\tifFalse: [self documentation: reply]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\tauthoringStamp := Utilities changeStampPerSe\\n! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'migration' stamp: 'mir 7/12/2004 23:45'!\\nmigrateWordAndHelpMessage\\n\\t\\\"Migrate the English wording and help message to the new structure\\\"\\n\\n\\t| englishElement |\\n\\tself initWordingAndDocumentation.\\n\\t(self properties includes: #wording)\\n\\t\\tifFalse: [\\n\\t\\t\\tenglishElement := self naturalLanguageTranslations\\n\\t\\t\\t\\tdetect: [:each | each language == #English] ifNone: [^nil].\\n\\t\\t\\tself wording: englishElement wording.\\n\\t\\t\\tself helpMessage: englishElement helpMessage]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'miscellaneous' stamp: 'sw 9/12/2001 23:03'!\\nelementSymbol\\n\\t\\\"Answer the receiver's element symbol\\\"\\n\\n\\t^ elementSymbol! !\\n\\n!ObjectWithDocumentation methodsFor: 'miscellaneous' stamp: 'mir 7/12/2004 23:20'!\\nnaturalLanguageTranslations\\n\\t^naturalLanguageTranslations ifNil: [OrderedCollection new]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:28'!\\ngetterSetterHelpMessage\\n\\t\\\"Returns a helpMessage that has been computed previously and needs to be translated and then formatted with the elementSymbol.\\n\\t'get value of {1}' translated format: {elSym}\\\"\\n\\n\\t^(self propertyAt: #getterSetterHelpMessage ifAbsent: [^nil])\\n\\t\\ttranslated format: {self elementSymbol}! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:29'!\\ngetterSetterHelpMessage: aString\\n\\t\\\"Sets a helpMessage that needs to be translated and then formatted with the elementSymbol.\\n\\t'get value of {1}' translated format: {elSym}\\\"\\n\\n\\tself propertyAt: #getterSetterHelpMessage put: aString! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:31'!\\ninitWordingAndDocumentation\\n\\t\\\"Initialize wording and documentation (helpMessage) for getters and setters\\\"\\n\\n\\t| elSym |\\n\\telSym := self elementSymbol.\\n\\telSym\\n\\t\\tifNil: [^self].\\n\\n\\t((elSym beginsWith: 'get')\\n\\t\\tand: [elSym size > 3])\\n\\t\\tifTrue: [\\n\\t\\t\\tself wording: (elSym allButFirst: 3) withFirstCharacterDownshifted.\\n\\t\\t\\tself getterSetterHelpMessage: 'get value of {1}']\\n\\t\\tifFalse: [\\n\\t\\t\\t((elSym beginsWith: 'set')\\n\\t\\t\\t\\tand: [elSym size > 4])\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself wording: (elSym allButFirst: 3) withFirstCharacterDownshifted.\\n\\t\\t\\t\\t\\tself getterSetterHelpMessage: 'set value of {1}']]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:30'!\\nproperties\\n\\t^properties ifNil: [properties := Dictionary new]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:30'!\\npropertyAt: key\\n\\t^self propertyAt: key ifAbsent: [nil]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:29'!\\npropertyAt: key ifAbsent: aBlock\\n\\t^properties\\n\\t\\tifNil: aBlock\\n\\t\\tifNotNil: [properties at: key ifAbsent: aBlock]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:29'!\\npropertyAt: key put: aValue\\n\\tself properties at: key put: aValue! !\\nAbstractObjectsAsMethod subclass: #ObjectsAsMethodsExample\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-ObjectsAsMethods'!\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'ar 5/17/2003 20:16'!\\nadd: a with: b\\n\\t^a + b! !\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'ar 5/17/2003 20:16'!\\nanswer42\\n\\t^42! !\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'md 3/1/2006 19:37'!\\nrun: oldSelector with: arguments in: aReceiver\\n\\t^self perform: oldSelector withArguments: arguments! !\\nAlignmentMorph subclass: #ObjectsTool\\n\\tinstanceVariableNames: 'searchString modeSymbol'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-PartsBin'!\\n!ObjectsTool commentStamp: '<historical>' prior: 0!\\nI am a Master Parts Bin that allows the user to drag out a new Morph from a voluminous iconic list.\\n\\nChoose \\\"objects\\\" from the world menu, or type Alt-o (Cmd-o on the Mac).\\n\\nTo add a new kinds of Morphs:\\nIn the class of the Morph, implement the message:\\n\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Rectangle'\\n\\t\\tcategories:\\t\\t#('Graphics' ' Basic 1 ')\\n\\t\\tdocumentation:\\t'A rectangular shape, with border and fill style'\\n\\nThe partName is the title that will show in the lower pane of the Object Tool.\\nWhen is categories mode, an object can be seen in more than one category. The list above tells which ones.\\nDocumentation is what will show in the balloon help for each object thumbnail.\\nThe message #initializeToStandAlone creates the actual instance.\\n\\nTo make a second variant object prototype coming from the same class, implement #supplementaryPartsDescriptions. In it, you get to specify the nativitySelector. It is sent to the class to get the variant objects. Often it is #authoringPrototype. (A class may supply supplementaryPartsDescriptions without implementing descriptionForPartsBin. This gives you better control.)\\n\\n!\\n\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'dgd 4/4/2006 16:43'!\\nalphabeticTabs\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of a morphic category\\\"\\n\\n\\t| buttonList aButton tabLabels |\\n\\n\\tself flag: #todo. \\\"includes non-english characters\\\"\\n\\ttabLabels _ (($a to: $z) collect: [:ch | ch asString]) asOrderedCollection.\\n\\n\\tbuttonList _ tabLabels collect:\\n\\t\\t[:catName |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: catName.\\n\\t\\t\\taButton actWhen: #buttonDown.\\n\\t\\t\\taButton target: self; actionSelector: #showAlphabeticCategory:fromButton:; arguments: {catName. aButton}].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new tabsForMorphicCategories\\\"! !\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'nk 9/3/2004 13:47'!\\ninstallQuads: quads fromButton: aButton\\n\\t\\\"Install items in the bottom pane that correspond to the given set of quads, as triggered from the given button\\\"\\n\\n\\t| aPartsBin sortedQuads oldResizing |\\n\\taPartsBin _ self partsBin.\\n\\toldResizing := aPartsBin vResizing.\\n\\taPartsBin removeAllMorphs.\\n\\tsortedQuads _ (PartsBin translatedQuads: quads)\\n\\t\\t\\t\\t\\t\\t\\tasSortedCollection: [:a :b | a third < b third].\\n\\taPartsBin listDirection: #leftToRight quadList: sortedQuads.\\n\\taButton ifNotNil: [self tabsPane highlightOnlySubmorph: aButton].\\n\\taPartsBin vResizing: oldResizing.\\n\\taPartsBin layoutChanged; fullBounds.\\n\\tself isFlap ifFalse: [ self minimizePartsBinSize ].! !\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'nk 9/3/2004 12:13'!\\nshowAlphabeticTabs\\n\\t\\\"Switch to the mode of showing alphabetic tabs\\\"\\n\\n\\tmodeSymbol == #alphabetic ifTrue: [ ^self ].\\n\\tself partsBin removeAllMorphs.\\n\\tself initializeWithTabs: self alphabeticTabs.\\n\\tself modeSymbol: #alphabetic.\\n\\tself tabsPane submorphs first doButtonAction! !\\n\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 9/3/2004 13:43'!\\nshowCategories\\n\\t\\\"Set the receiver up so that it shows tabs for each of the standard categories\\\"\\n\\n\\tmodeSymbol == #categories ifTrue: [ ^self ].\\n\\n\\tself partsBin removeAllMorphs.\\n\\tself initializeWithTabs: self tabsForCategories.\\n\\tself modeSymbol: #categories.\\n\\tself tabsPane submorphs first doButtonAction.\\n! !\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 9/3/2004 13:51'!\\nshowCategory: aCategoryName fromButton: aButton \\n\\t\\\"Project items from the given category into my lower pane\\\"\\n\\t| quads |\\n\\tself partsBin removeAllMorphs.\\n\\tCursor wait\\n\\t\\tshowWhile: [quads := OrderedCollection new.\\n\\t\\t\\tMorph withAllSubclasses\\n\\t\\t\\t\\tdo: [:aClass | aClass theNonMetaClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:aDescription | aDescription translatedCategories includes: aCategoryName]].\\n\\t\\t\\tquads := quads\\n\\t\\t\\t\\t\\t\\tasSortedCollection: [:q1 :q2 | q1 third <= q2 third].\\n\\t\\t\\tself installQuads: quads fromButton: aButton]! !\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 8/23/2004 18:18'!\\ntabsForCategories\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of a category\\\"\\n\\n\\t| buttonList aButton classes categoryList basic |\\n\\tclasses _ Morph withAllSubclasses.\\n\\tcategoryList _ Set new.\\n\\tclasses do: [:aClass |\\n\\t\\t(aClass class includesSelector: #descriptionForPartsBin) ifTrue:\\n\\t\\t\\t[categoryList addAll: aClass descriptionForPartsBin translatedCategories].\\n\\t\\t(aClass class includesSelector: #supplementaryPartsDescriptions) ifTrue:\\n\\t\\t\\t[aClass supplementaryPartsDescriptions do:\\n\\t\\t\\t\\t[:aDescription | categoryList addAll: aDescription translatedCategories]]].\\n\\n\\tcategoryList _ OrderedCollection withAll: (categoryList asSortedArray).\\n\\t\\n\\tbasic := categoryList remove: ' Basic' translated ifAbsent: [ ].\\n\\tbasic ifNotNil: [ categoryList addFirst: basic ].\\n\\n\\tbasic := categoryList remove: 'Basic' translated ifAbsent: [ ].\\n\\tbasic ifNotNil: [ categoryList addFirst: basic ].\\n\\n\\tbuttonList _ categoryList collect:\\n\\t\\t[:catName |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: catName.\\n\\t\\t\\taButton actWhen: #buttonDown.\\n\\t\\t\\taButton target: self; actionSelector: #showCategory:fromButton:; arguments: {catName. aButton}].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new tabsForCategories\\\"! !\\n\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'nk 9/3/2004 13:46'!\\ninitializeForFlap\\n\\t\\\"Initialize the receiver to operate in a flap at the top of the screen.\\\"\\n\\n\\t\\\"\\n\\tFlaps newObjectsFlap openInWorld\\n\\t\\\"\\n\\n\\t| buttonPane aBin aColor heights tabsPane |\\n\\tself basicInitialize.\\n\\n\\tself layoutInset: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #rigid;\\n\\t\\tborderWidth: 2; borderColor: Color darkGray;\\n\\t\\textent: (self minimumWidth @ self minimumHeight).\\n\\n\\t\\\"mode buttons\\\"\\n\\tbuttonPane := self paneForTabs: self modeTabs.\\n\\tbuttonPane\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tsetNameTo: 'ButtonPane';\\n\\t\\tcolor: (aColor := buttonPane color) darker;\\n\\t\\tlayoutInset: 6;\\n\\t\\twrapDirection: nil;\\n\\t\\twidth: self width;\\n\\t\\tlayoutChanged; fullBounds.\\n\\n\\t\\\"Place holder for a tabs or text pane\\\"\\n\\ttabsPane := Morph new\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\theights := { buttonPane height. 40 }.\\n\\n\\tbuttonPane vResizing: #spaceFill.\\n\\tself\\n\\t\\taddMorph: buttonPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ 0 corner: 0 @ heights first)).\\n\\n\\tself\\n\\t\\taddMorph: tabsPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ heights first corner: 0 @ (heights first + heights second))).\\n\\n\\taBin := (PartsBin newPartsBinWithOrientation: #leftToRight from: #())\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\twrapDirection: #topToBottom;\\n\\t\\tcolor: aColor lighter lighter;\\n\\t\\tsetNameTo: 'Parts';\\n\\t\\tdropEnabled: false;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\tself\\n\\t\\taddMorph: aBin\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 1)\\n\\t\\t\\t\\toffsets: (0 @ (heights first + heights second) corner: 0 @ 0)).\\n\\n\\taBin color: (Color orange muchLighter);\\n\\t\\tsetNameTo: 'Objects' translated.\\n\\n\\tself color: (Color orange muchLighter);\\n\\t\\tsetNameTo: 'Objects' translated.\\n! !\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'dgd 4/4/2006 16:47'!\\ninitializeToStandAlone\\n\\t\\\"Initialize the receiver so that it can live as a stand-alone morph\\\"\\n\\t| buttonPane aBin aColor heights tabsPane |\\n\\tself basicInitialize.\\n\\n\\tself layoutInset: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new;\\n\\t\\tuseRoundedCorners;\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #rigid;\\n\\t\\textent: (self minimumWidth @ self minimumHeight).\\n\\n\\t\\\"mode buttons\\\"\\n\\tbuttonPane := self paneForTabs: self modeTabs.\\n\\tbuttonPane color: ColorTheme current dialogColor.\\n\\tbuttonPane\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tsetNameTo: 'ButtonPane';\\n\\t\\taddMorphFront: self dismissButton;\\n\\t\\taddMorphBack: self helpButton;\\n\\t\\tcolor: (aColor := buttonPane color) darker;\\n\\t\\tlayoutInset: 5;\\n\\t\\twrapDirection: nil;\\n\\t\\twidth: self width;\\n\\t\\tlayoutChanged; fullBounds.\\n\\n\\t\\\"Place holder for a tabs or text pane\\\"\\n\\ttabsPane := Morph new.\\n\\ttabsPane\\n\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\thResizing: #spaceFill.\\n\\n\\theights := { buttonPane height. 40 }.\\n\\n\\tbuttonPane vResizing: #spaceFill.\\n\\tself\\n\\t\\taddMorph: buttonPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ 0 corner: 0 @ heights first)).\\n\\n\\tself\\n\\t\\taddMorph: tabsPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ heights first corner: 0 @ (heights first + heights second))).\\n\\n\\taBin := (PartsBin newPartsBinWithOrientation: #leftToRight from: #())\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\twrapDirection: #topToBottom;\\n\\t\\tcolor: aColor lighter lighter;\\n\\t\\tsetNameTo: 'Parts';\\n\\t\\tdropEnabled: false;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\tself\\n\\t\\taddMorph: aBin\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 1)\\n\\t\\t\\t\\toffsets: (0 @ (heights first + heights second) corner: 0 @ 0)).\\n\\n\\tself\\n\\t\\tborderWidth: ColorTheme current dialogBorderWidth;\\n\\t\\tborderColor: ColorTheme current dialogBorderColor;\\n\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\tsetNameTo: 'Objects' translated;\\n\\t\\tshowCategories.\\n! !\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'dgd 4/4/2006 16:45'!\\ntweakAppearanceAfterModeShift\\n\\t\\\"After the receiver has been put into a given mode, make an initial selection of category, if appropriate, and highlight the mode button.\\\"\\n\\n\\tself buttonPane submorphs do:\\n\\t\\t[:aButton | \\n\\t\\t\\t| aColor |\\n\\t\\t\\t\\\"aButton borderWidth: 1.\\\"\\n\\t\\t\\taColor := (aButton valueOfProperty: #modeSymbol) = modeSymbol\\n\\t\\t\\t\\tifTrue: [Color red]\\n\\t\\t\\t\\tifFalse: [Color black].\\n\\n\\t\\t\\taButton firstSubmorph color: aColor.\\n\\t\\t\\taButton borderColor: aColor.\\n\\t\\t].! !\\n\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:35'!\\nextent: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tself extent = anExtent ifTrue: [ ^self ].\\n\\tsuper extent: anExtent.\\n\\tself fixLayoutFrames.! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 13:44'!\\nfixLayoutFrames\\n\\t\\\"Adjust the boundary between the tabs or search pane and the parts bin, giving preference to the tabs.\\\"\\n\\n\\t| oldY newY tp tpHeight |\\n\\toldY := ((tp := self tabsPane\\n\\t\\t\\t\\t\\t\\tifNil: [self searchPane])\\n\\t\\t\\t\\tifNil: [^ self]) layoutFrame bottomOffset.\\n\\ttpHeight := tp hasSubmorphs\\n\\t\\t\\t\\tifTrue: [(tp submorphBounds outsetBy: tp layoutInset) height]\\n\\t\\t\\t\\tifFalse: [tp height].\\n\\tnewY := (self buttonPane\\n\\t\\t\\t\\tifNil: [^ self]) height + tpHeight.\\n\\toldY = newY\\n\\t\\tifTrue: [^ self].\\n\\ttp layoutFrame bottomOffset: newY.\\n\\t(self partsBin\\n\\t\\tifNil: [^ self]) layoutFrame topOffset: newY.\\n\\tsubmorphs\\n\\t\\tdo: [:m | m layoutChanged ]! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 13:47'!\\nminimizePartsBinSize\\n\\tself layoutChanged; fullBounds.\\n\\tself fixLayoutFrames.\\n\\tself setExtentFromHalo: (self minimumWidth @ self minimumHeight) ! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 10:35'!\\nminimumBottom\\n\\t| iconsBottom partsBin |\\n\\tpartsBin := self partsBin ifNil: [ ^self bottom ].\\n\\ticonsBottom := partsBin submorphs isEmpty\\n\\t\\tifTrue: [ partsBin top + 60 ]\\n\\t\\tifFalse: [ partsBin submorphBounds bottom + partsBin layoutInset ].\\n\\n\\t^iconsBottom + self layoutInset + self borderWidth! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 11:53'!\\nminimumHeight\\n\\t^(self minimumBottom - self top) max: 280! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:06'!\\nminimumWidth\\n\\t\\\"Answer a width that assures that the alphabet fits in two rows\\\"\\n\\n\\t^ 300! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:40'!\\nposition: aPoint\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tself position = aPoint ifTrue: [ ^self ].\\n\\tsuper position: aPoint.\\n\\tself fixLayoutFrames.! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:44'!\\nsetExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tsuper setExtentFromHalo: ((anExtent x max: self minimumWidth) @ (anExtent y max: self minimumHeight)).\\n! !\\n\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'sw 8/12/2001 16:30'!\\nmodeSymbol\\n\\t\\\"Answer the modeSymbol\\\"\\n\\n\\t^ modeSymbol! !\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'nk 9/3/2004 13:32'!\\nmodeSymbol: aSymbol\\n\\t\\\"Set the receiver's modeSymbol as indicated\\\"\\n\\n\\tmodeSymbol _ aSymbol.\\n\\tself tweakAppearanceAfterModeShift.\\n! !\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'dgd 4/4/2006 16:47'!\\nmodeTabs\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of mode of the receiver\\\"\\n\\n\\t| buttonList aButton tupleList |\\n\\ttupleList _ #(\\n\\t\\t('alphabetic'\\t\\talphabetic\\tshowAlphabeticTabs\\t'A separate tab for each letter of the alphabet')\\n\\t\\t('find'\\t\\t\\t\\tsearch\\t\\t\\tshowSearchPane\\t\\t\\t'Provides a type-in pane allowing you to match')\\n\\t\\t('categories'\\t\\tcategories\\tshowCategories\\t\\t\\t'Grouped by category')\\n\\n\\t\\t\\\"('standard'\\t\\tstandard\\t\\tshowStandardPane\\t\\t'Standard Squeak tools supplies for building')\\\"\\n\\t).\\n\\t\\t\\t\\t\\n\\tbuttonList _ tupleList collect:\\n\\t\\t[:tuple |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: tuple first translated.\\n\\t\\t\\taButton actWhen: #buttonUp.\\n\\t\\t\\taButton setProperty: #modeSymbol toValue: tuple second.\\n\\t\\t\\taButton target: self; actionSelector: tuple third.\\n\\t\\t\\taButton setBalloonText: tuple fourth translated.\\n\\t\\t\\taButton borderWidth: 0.\\n\\t\\t\\taButton].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new modeTabs\\\"! !\\n\\n\\n!ObjectsTool methodsFor: 'menu' stamp: 'dgd 8/30/2003 16:22'!\\naddCustomMenuItems: aMenu hand: aHand\\n\\t\\\"Add items to the given halo-menu, given a hand\\\"\\n\\n\\tsuper addCustomMenuItems: aMenu hand: aHand.\\n\\taMenu addLine.\\n\\taMenu add: 'alphabetic' translated target: self selector: #showAlphabeticTabs.\\n\\taMenu add: 'find' translated target: self selector: #showSearchPane.\\n\\taMenu add: 'categories' translated target: self selector: #showCategories.\\n\\taMenu addLine.\\n\\taMenu add: 'reset thumbnails' translated target: self selector: #resetThumbnails.! !\\n\\n!ObjectsTool methodsFor: 'menu' stamp: 'nk 9/7/2003 07:42'!\\nresetThumbnails\\n\\t\\\"Reset the thumbnail cache\\\"\\n\\n\\tPartsBin clearThumbnailCache.\\n\\tmodeSymbol == #categories ifTrue: [self showCategories] ifFalse: [self showAlphabeticTabs]! !\\n\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 11:20'!\\nnewSearchPane\\n\\t\\\"Answer a type-in pane for searches\\\"\\n\\n\\t| aTextMorph |\\n\\taTextMorph _ TextMorph new\\n\\t\\tsetProperty: #defaultContents toValue: ('' asText allBold addAttribute: (TextFontChange font3));\\n\\t\\tsetTextStyle: (TextStyle fontArray: { Preferences standardEToysFont });\\n\\t\\tsetDefaultContentsIfNil;\\n\\t\\ton: #keyStroke send: #searchPaneCharacter: to: self;\\n\\t\\tsetNameTo: 'SearchPane';\\n\\t\\tsetBalloonText: 'Type here and all entries that match will be shown.' translated;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tmargins: 4@6;\\n\\t\\tbackgroundColor: Color white.\\n\\t^ aTextMorph! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'sw 6/30/2001 14:26'!\\nsearchPaneCharacter: evt\\n\\t\\\"A character represented by the event handed in was typed in the search pane by the user\\\"\\n\\n\\t^ self showMorphsMatchingSearchString\\n\\n\\\"\\t| char | *** The variant below only does a new search if RETURN or ENTER is hit ***\\n\\tchar _ evt keyCharacter.\\n\\t(char == Character enter or: [char == Character cr]) ifTrue:\\n\\t\\t[self showMorphsMatchingSearchString]\\\"! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 10:39'!\\nsetSearchStringFromSearchPane\\n\\t\\\"Set the search string by obtaining its contents from the search pane, and doing a certain amount of munging\\\"\\n\\n\\tsearchString _ self searchPane text string asLowercase withBlanksTrimmed.\\n\\tsearchString _ searchString copyWithoutAll: {Character enter. Character cr}! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 13:51'!\\nshowMorphsMatchingSearchString\\n\\t\\\"Put items matching the search string into my lower pane\\\"\\n\\t| quads |\\n\\tself setSearchStringFromSearchPane.\\n\\tself partsBin removeAllMorphs.\\n\\tCursor wait\\n\\t\\tshowWhile: [quads := OrderedCollection new.\\n\\t\\t\\tMorph withAllSubclasses\\n\\t\\t\\t\\tdo: [:aClass | aClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:info | info formalName translated includesSubstring: searchString caseSensitive: false]].\\n\\t\\t\\tself installQuads: quads fromButton: nil]! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 12:13'!\\nshowSearchPane\\n\\t\\\"Set the receiver up so that it shows the search pane\\\"\\n\\n\\t| tabsPane aPane frame |\\n\\tmodeSymbol == #search ifTrue: [ ^self ].\\n\\n\\tself partsBin removeAllMorphs.\\n\\n\\ttabsPane := self tabsPane.\\n\\taPane _ self newSearchPane.\\n\\taPane layoutChanged; fullBounds.\\n\\n\\taPane layoutFrame: (frame := tabsPane layoutFrame copy).\\n\\tframe bottomOffset: (frame topOffset + aPane height).\\n\\tself replaceSubmorph: tabsPane by: aPane.\\n\\tself partsBin layoutFrame topOffset: frame bottomOffset.\\n\\n\\tself modeSymbol: #search.\\n\\tself showMorphsMatchingSearchString.\\n\\tActiveHand newKeyboardFocus: aPane! !\\n\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:06'!\\nbuttonPane\\n\\t\\\"Answer the receiver's button pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'ButtonPane' ifNone: [].! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:09'!\\npartsBin\\n\\t^self findDeeplyA: PartsBin.! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 10:40'!\\nsearchPane\\n\\t\\\"Answer the receiver's search pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'SearchPane' ifNone: [].! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 13:51'!\\nshowAlphabeticCategory: aString fromButton: aButton \\n\\t\\\"Blast items beginning with a given letter into my lower pane\\\"\\n\\t| eligibleClasses quads uc |\\n\\tself partsBin removeAllMorphs.\\n\\tuc := aString asUppercase asCharacter.\\n\\tCursor wait\\n\\t\\tshowWhile: [eligibleClasses := Morph withAllSubclasses.\\n\\t\\t\\tquads := OrderedCollection new.\\n\\t\\t\\teligibleClasses\\n\\t\\t\\t\\tdo: [:aClass | aClass theNonMetaClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:info | info formalName translated asUppercase first = uc]].\\n\\t\\t\\tself installQuads: quads fromButton: aButton]! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:06'!\\ntabsPane\\n\\t\\\"Answer the receiver's tabs pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'TabPane' ifNone: [].! !\\n\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'nk 9/3/2004 13:47'!\\ninitializeWithTabs: tabList\\n\\t\\\"Initialize the receiver to have the given tabs\\\"\\n\\t| oldPane newPane |\\n\\toldPane := self tabsPane ifNil: [ self searchPane ].\\n\\tnewPane := (self paneForTabs: tabList)\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\tyourself.\\n\\tnewPane layoutFrame: oldPane layoutFrame.\\n\\tself replaceSubmorph: oldPane by: newPane.\\n\\tnewPane layoutChanged; fullBounds.\\n\\tself fixLayoutFrames.\\n\\n! !\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'dgd 4/4/2006 16:44'!\\npaneForTabs: tabList \\n\\t\\\"Answer a pane bearing tabs for the given list\\\"\\n\\t| aPane |\\n\\ttabList do: [:t |\\n\\t\\t\\tt color: Color transparent.\\n\\t\\t\\tt borderWidth: 1;\\n\\t\\t\\t\\tborderColor: Color black].\\n\\n\\taPane := AlignmentMorph newRow\\n\\t\\t\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\t\\t\\tlistDirection: #leftToRight;\\n\\t\\t\\t\\twrapDirection: #topToBottom;\\n\\t\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\t\\tcellInset: 6;\\n\\t\\t\\t\\tlayoutInset: 4;\\n\\t\\t\\t\\tlistCentering: #center;\\n\\t\\t\\t\\tlistSpacing: #equal;\\n\\t\\t\\t\\taddAllMorphs: tabList;\\n\\t\\t\\t\\tyourself.\\n\\n\\taPane width: self layoutBounds width.\\n\\n\\t^ aPane! !\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'dgd 8/30/2003 16:09'!\\npresentHelp\\n\\t\\\"Sent when a Help button is hit; provide the user with some form of help for the tool at hand\\\"\\n\\n'The Objects tool allows you to browse through, and obtain copies of, many kinds of objects. \\n\\nYou can obtain an Objects tool by choosing \\\"Objects\\\" from the world menu, or by the shortcut of typing alt-o (cmd-o) any time the cursor is over the desktop.\\n\\nThere are three ways to use Objects, corresponding to the three tabs seen at the top:\\n\\nalphabetic - gives you separate tabs for a, b, c, etc. Click any tab, and you will see the icons of all the objects whose names begin with that letter\\n\\nsearch - gives you a type-in pane for a search string. Type any letters there, and icons of all the objects whose names match what you have typed will appear in the bottom pane.\\n\\ncategories - provides tabs representing categories of related items. Click on any tab to see the icons of all the objects in the category.\\n\\nWhen the cursor lingers over the icon of any object, you will get balloon help for the item.\\n\\nWhen you drag an icon from Objects, it will result in a new copy of it in your hand; the new object will be deposited wherever you next click.' translated\\n\\n\\topenInWorkspaceWithTitle: 'About Objects' translated! !\\n\\n\\n!ObjectsTool methodsFor: 'thumbnail' stamp: 'dgd 9/22/2004 19:28'!\\nicon\\n\\t\\\"Answer a form with an icon to represent the receiver\\\"\\n\\t^ MenuIcons objectCatalogIcon! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectsTool class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:45'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:47'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(ObjectsTool\\t\\t\\tnewStandAlone\\t\\t\\t\\t'Object Catalog'\\t\\t'A tool that lets you browse the catalog of objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ObjectsTool\\t\\tnewStandAlone\\t\\t\\t\\t'Object Catalog'\\t\\t'A tool that lets you browse the catalog of objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.]! !\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:37'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!ObjectsTool class methodsFor: 'parts bin' stamp: 'sw 8/11/2001 20:16'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Objects'\\n\\t\\tcategories:\\t\\t#('Useful')\\n\\t\\tdocumentation:\\t'A place to obtain many kinds of objects'! !\\nOldSocket subclass: #OldSimpleClientSocket\\n\\tinstanceVariableNames: 'buffer bufferPos'\\n\\tclassVariableNames: 'CR CrLf LF'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!OldSimpleClientSocket commentStamp: '<historical>' prior: 0!\\nThis class supports client for simple network protocols based on sending textual commands and responses. Examples of such protocols include POP3 (mail retrieval), SMTP (mail posting), HTTP (web browsing), and NTTP (network news). Some simple examples are presented as class methods, but a full-service client of some service should be implemented as a subclass.\\n\\nThe basic services provided by this class are:\\n\\tsendCommand:\\t\\t\\t-- sends a command line terminate with <CR><LF>\\n\\tgetResponse\\t\\t\\t\\t-- gets a single-line response to a command\\n\\tgetMultilineResponse\\t-- gets a multiple line response terminated by a period\\n\\t\\t\\t\\t\\t\\t\\t-- on a line by itself\\n\\nThere are variants of the getResponse commands that display lines on the screen as they are being received. Linefeeds are stripped out of all responses.\\n\\nThe 'get' commands above make use of an internal buffer. So intermixing these two commands and regular Socket recieve commands can cause problems.!\\n\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'di 4/13/1999 14:43'!\\ndisplayString: aString\\n\\t\\\"Display the given string on the Display. Used for testing.\\\"\\n\\n\\t| s |\\n\\taString isEmpty ifTrue: [^ self].\\n\\taString size > 60\\n\\t\\tifTrue: [s _ aString copyFrom: 1 to: 60] \\\"limit to 60 characters\\\"\\n\\t\\tifFalse: [s _ aString].\\n\\n\\ts displayOn: Display.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/15/97 15:43'!\\ngetMultilineResponse\\n\\t\\\"Get a multiple line response to the last command, filtering out LF characters. A multiple line response ends with a line containing only a single period (.) character.\\\"\\n\\n\\t^ self getMultilineResponseShowing: false.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 03:34'!\\ngetMultilineResponseShowing: showFlag\\n\\t\\\"Get a multiple line response to the last command. A multiple line response ends with a line containing only a single period (.) character. Linefeed characters are filtered out. If showFlag is true, each line is shown in the upper-left corner of the Display as it is received.\\\"\\n\\n\\t| response done chunk |\\n\\tresponse _ WriteStream on: ''.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tshowFlag\\n\\t\\t\\tifTrue: [chunk _ self getResponseShowing: true]\\n\\t\\t\\tifFalse: [chunk _ self getResponse].\\n\\t\\t(chunk beginsWith: '.')\\n\\t\\t\\tifTrue: [ response nextPutAll: (chunk copyFrom: 2 to: chunk size) ]\\n\\t\\t\\tifFalse: [ response nextPutAll: chunk ].\\n\\t\\tdone _ (chunk = ('.', String cr)) ].\\n\\n\\t^ response contents\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 02:10'!\\ngetResponse\\n\\t\\\"Get a one-line response from the server. The final LF is removed from the line, but the CR is left, so that the line is in Squeak's text format\\\"\\n\\n\\t^ self getResponseShowing: false\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 03:27'!\\ngetResponseShowing: showFlag\\n\\n\\t| line idx |\\n\\tline _ WriteStream on: String new.\\n\\n\\tbuffer ifNil: [\\n\\t\\tbuffer _ String new.\\n\\t\\tbufferPos _ 0 ].\\n\\n\\t[\\n\\t\\t\\\"look for a LF in the buffer\\\"\\n\\t\\tidx _ buffer indexOf: Character lf startingAt: bufferPos+1 ifAbsent: [ 0 ].\\n\\t\\tidx > 0 ifTrue: [\\n\\t\\t\\t\\\"found it!! we have a line\\\"\\n\\t\\t\\tline nextPutAll: (buffer copyFrom: bufferPos+1 to: idx-1).\\n\\t\\t\\tbufferPos _ idx.\\n\\t\\t\\t^line contents ].\\n\\t\\t\\n\\t\\t\\\"didn't find it. add the whole buffer to the line, and retrieve some more data\\\"\\n\\t\\tline nextPutAll: (buffer copyFrom: bufferPos+1 to: buffer size).\\n\\t\\tbufferPos _ 0.\\n\\t\\tbuffer _ String new.\\n\\t\\tself waitForDataQueryingUserEvery: 30.\\n\\t\\tbuffer _ self getData.\\n\\n\\t\\ttrue\\n\\t] whileTrue.! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/17/97 16:00'!\\nsendCommand: commandString\\n\\t\\\"Send the given command as a single line followed by a <CR><LF> terminator.\\\"\\n\\n\\tself sendData: commandString, CrLf.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/16/1998 14:37'!\\nwaitForDataQueryingUserEvery: seconds\\n\\t\\\"Wait for data to arrive, asking the user periodically if they wish to keep waiting. If they don't wish to keep waiting, destroy the socket and raise an error.\\\"\\n\\n\\t| gotData |\\n\\tgotData _ false.\\n\\t[gotData]\\n\\t\\twhileFalse: [\\n\\t\\t\\tgotData _ self waitForDataUntil: (Socket deadlineSecs: seconds).\\n\\t\\t\\tgotData ifFalse: [\\n\\t\\t\\t\\tself isConnected ifFalse: [\\n\\t\\t\\t\\t\\tself destroy.\\n\\t\\t\\t\\t\\tself error: 'server closed connection'].\\n\\t\\t\\t\\t(self confirm: 'server not responding; keep trying?')\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\tself destroy.\\n\\t\\t\\t\\t\\t\\tself error: 'no response from server']]].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOldSimpleClientSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!OldSimpleClientSocket class methodsFor: 'class initialization' stamp: 'jm 9/15/97 11:42'!\\ninitialize\\n\\t\\\"SimpleClientSocket initialize\\\"\\n\\n\\tCR _ Character cr.\\n\\tLF _ Character linefeed.\\n\\n\\t\\\"string for command line termination:\\\"\\n\\tCrLf _ String with: CR with: LF.\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'mir 5/13/2003 10:45'!\\nnntpTest\\n\\t\\\"SimpleClientSocket nntpTest\\\"\\n\\n\\t| addr s headers msgs header allNewsGroups |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 119. \\\"119 is the NNTP port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'group comp.lang.smalltalk'.\\n\\tTranscript show: s getResponse.\\n\\n\\t\\\"get all the message headers for the current newsgroup\\\"\\n\\ts sendCommand: 'xover 1-1000000'.\\n\\theaders _ s getMultilineResponseShowing: true.\\n\\n\\t\\\"print the headers of the first 10 messages of comp.lang.smalltalk\\\"\\n\\ts sendCommand: 'listgroup comp.lang.smalltalk'.\\n\\tmsgs _ self parseIntegerList: s getMultilineResponse.\\n\\tmsgs ifNotNil: [\\n\\t\\t1 to: 5 do: [:i |\\n\\t\\t\\ts sendCommand: 'head ', (msgs at: i) printString.\\n\\t\\t\\theader _ s getMultilineResponse.\\n\\t\\t\\tTranscript show: (self extractDateFromAndSubjectFromHeader: header); cr]].\\n\\n\\t\\\"get a full list of usenet newsgroups\\\"\\n\\ts sendCommand: 'newgroups 010101 000000'.\\n\\tallNewsGroups _ s getMultilineResponse.\\n\\tTranscript show: allNewsGroups size printString, ' bytes in full newsgroup list'; cr.\\n\\n\\tTranscript show: 'Sending quit...'; cr.\\n\\ts sendCommand: 'QUIT'.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n\\n\\t(headers ~~ nil and:\\n\\t [self confirm: 'show article headers from comp.lang.smalltalk?'])\\n\\t\\tifTrue: [\\n\\t\\t\\t(StringHolder new contents: (self parseHeaderList: headers))\\n\\t\\t\\t\\topenLabel: 'Newsgroup Headers'].\\n\\n\\t(allNewsGroups ~~ nil and:\\n\\t [self confirm: 'show list of all newsgroups available on your server?'])\\n\\t\\tifTrue: [\\n\\t\\t\\t(StringHolder new contents: allNewsGroups)\\n\\t\\t\\t\\topenLabel: 'All Usenet Newsgroups'].\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:25'!\\nparseHeaderList: aString\\n\\t\\\"Parse a list of newsgroup headers.\\\"\\n\\n\\t| results s lineStart |\\n\\tresults _ WriteStream on: (String new: aString size).\\n\\ts _ ReadStream on: aString.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tlineStart _ s position + 1.\\n\\t\\t\\t3 timesRepeat: [s skipTo: Character tab]. \\\"find fourth tab\\\"\\n\\t\\t\\tlineStart to: s position - 1 do: [:i | results nextPut: (aString at: i)].\\n\\t\\t\\tresults cr.\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ results contents\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:26'!\\nparseIntegerList: aString\\n\\t\\\"Parse a list of integers, each on a line by itself.\\\"\\n\\n\\t| s out |\\n\\ts _ ReadStream on: aString.\\n\\ts skipTo: Character cr. \\\"skip the first line\\\"\\n\\tout _ OrderedCollection new.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tout addLast: (Integer readFrom: s).\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ out asArray\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:26'!\\nparseNTTPMsgList: aString\\n\\t\\\"Parse a list of integers, each on a line by itself.\\\"\\n\\n\\t| s out |\\n\\ts _ ReadStream on: aString.\\n\\ts skipTo: Character cr. \\\"skip the first line\\\"\\n\\tout _ OrderedCollection new.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tout addLast: (Integer readFrom: s).\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ out asArray\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\nfinger: userName\\n\\t\\\"OldSimpleClientSocket finger: 'stp'\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 79. \\\"finger port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\ts sendCommand: userName.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\nhttpTestHost: hostName port: port url: url\\n\\t\\\"This test fetches a URL from the given host and port.\\\"\\n\\t\\\"SimpleClientSocket httpTestHost: 'www.disney.com' port: 80 url: '/'\\\"\\n\\t\\\"Tests URL fetch through a local HTTP proxie server:\\n\\t\\t(SimpleClientSocket\\n\\t\\t\\thttpTestHost: '127.0.0.1'\\n\\t\\t\\tport: 8080\\n\\t\\t\\turl: 'HTTP://www.exploratorium.edu/index.html')\\\"\\n\\n\\t| hostAddr s result buf bytes totalBytes t |\\n\\tTranscript cr; show: 'starting http test'; cr.\\n\\tSocket initializeNetwork.\\n\\thostAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\thostAddr = nil ifTrue: [^ self inform: 'Could not find an address for ', hostName].\\n\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: hostAddr port: port.\\n\\ts waitForConnectionUntil: \\\"self standardDeadline\\\" (Socket deadlineSecs: 10).\\n\\t(s isConnected) ifFalse: [\\n\\t\\ts destroy.\\n\\t\\t^ self inform: 'could not connect'].\\n\\tTranscript show: 'connection open; waiting for data'; cr.\\n\\n\\ts sendCommand: 'GET ', url, ' HTTP/1.0'.\\n\\ts sendCommand: 'User-Agent: Squeak 1.19'.\\n\\ts sendCommand: 'ACCEPT: text/html'.\\t\\\"always accept plain text\\\"\\n\\ts sendCommand: 'ACCEPT: application/octet-stream'. \\\"also accept binary data\\\"\\n\\ts sendCommand: ''. \\\"blank line\\\"\\n\\n\\tresult _ WriteStream on: (String new: 10000).\\n\\tbuf _ String new: 10000.\\n\\ttotalBytes _ 0.\\n\\tt _ Time millisecondsToRun: [\\n\\t\\t[s isConnected] whileTrue: [\\n\\t\\t\\ts waitForDataUntil: (Socket deadlineSecs: 5).\\n\\t\\t\\tbytes _ s receiveDataInto: buf.\\n\\t\\t\\t1 to: bytes do: [:i | result nextPut: (buf at: i)].\\n\\t\\t\\ttotalBytes _ totalBytes + bytes.\\n\\t\\t\\tTranscript show: totalBytes printString, ' bytes received'; cr]].\\n\\n\\ts destroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n\\tTranscript show: 'http test done; ', totalBytes printString, ' bytes read in '.\\n\\tTranscript show: ((t / 1000.0) roundTo: 0.01) printString, ' seconds'; cr.\\n\\tTranscript show: ((totalBytes asFloat / t) roundTo: 0.01) printString, ' kBytes/sec'; cr.\\n\\tTranscript endEntry.\\n\\t(StringHolder new contents: (result contents))\\n\\t\\topenLabel: 'HTTP Test Result: URL Contents'.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\ntimeTest\\n\\t\\\"SimpleClientSocket timeTest\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 13. \\\"time port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'jm 9/15/97 14:47'!\\nextractDateFromAndSubjectFromHeader: headerString\\n\\n\\t| date from subject s lineBuf c line i |\\n\\tdate _ from _ subject _ ''.\\n\\ts _ ReadStream on: headerString.\\n\\tlineBuf _ WriteStream on: ''.\\n\\t[s atEnd] whileFalse: [\\n\\t\\tc _ s next.\\n\\t\\tc = CR\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tline _ lineBuf contents.\\n\\t\\t\\t\\t(line beginsWith: 'Date: ')\\tifTrue: [date _ line copyFrom: 7 to: line size].\\n\\t\\t\\t\\t(line beginsWith: 'From: ')\\tifTrue: [from _ line copyFrom: 7 to: line size].\\n\\t\\t\\t\\t(line beginsWith: 'Subject: ')\\tifTrue: [subject _ line copyFrom: 10 to: line size].\\n\\t\\t\\t\\tlineBuf _ WriteStream on: '']\\n\\t\\t\\tifFalse: [lineBuf nextPut: c]].\\n\\n\\ti _ date indexOf: $' ifAbsent: [0].\\n\\tdate _ date copyFrom: i + 1 to: date size.\\n\\t^ (self simpleDateString: date), ', ', from, ':\\n ', subject\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'rbb 3/1/2005 11:02'!\\npopTest\\n\\t\\\"SimpleClientSocket popTest\\\"\\n\\n\\t| addr userName userPassword s msgs header |\\n\\taddr := NetNameResolver promptUserForHostAddress.\\n\\tuserName := UIManager default\\n\\t\\trequest: 'What is your email name?'\\n\\t\\tinitialAnswer: 'johnm'.\\n\\tuserPassword := UIManager default\\n\\t\\trequest: 'What is your email password?'.\\n\\n\\ts := OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 110. \\\"110 is the POP3 port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'USER ', userName.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'PASS ', userPassword.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'LIST'.\\n\\n\\t\\\"the following should be tweaked to handle an empy mailbox:\\\"\\n\\tmsgs := self parseIntegerList: s getMultilineResponse.\\n\\n\\t1 to: (msgs size min: 5) do: [ :i |\\n\\t\\ts sendCommand: 'TOP ', (msgs at: i) printString, ' 0'.\\n\\t\\theader := s getMultilineResponse.\\n\\t\\tTranscript show: (self extractDateFromAndSubjectFromHeader: header); cr].\\n\\n\\tmsgs size > 0 ifTrue: [\\n\\t\\t\\\"get the first message\\\"\\n\\t\\ts sendCommand: 'RETR 1'.\\n\\t\\tTranscript show: s getMultilineResponse].\\n\\n\\tTranscript show: 'closing connection'; cr.\\n\\ts sendCommand: 'QUIT'.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'tk 4/10/1998 06:47'!\\nsimpleDateString: dateString\\n\\n\\t| s |\\n\\ts _ ReadStream on: dateString.\\n\\ts skipTo: $,. \\\"scan thru first comma\\\"\\n\\ts atEnd ifTrue: [s reset]. \\\"no comma found; reset s\\\"\\n\\ts skipSeparators.\\n\\t^ (Date readFrom: s) mmddyyyy\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'queries' stamp: 'jm 2/26/98 09:50'!\\ncrLf\\n\\n\\t^ CrLf\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nforkingRemoteCursorSender\\n\\t\\\"This is the client side of a test that sends samples of the local input sensor state to the server, which may be running on a local or remote host. This method opens the connection, then forks a process to send the cursor data. Data is sent continuously until the user clicks in a 20x20 pixel square at the top-left corner of the display. The server should be started first. Note the server's address, since this method will prompt you for it.\\\"\\n\\t\\\"SimpleClientSocket forkingRemoteCursorSender\\\"\\n\\n\\t| sock addr stopRect |\\n\\tTranscript show: 'starting remote cursor sender'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock _ OldSimpleClientSocket new.\\n\\tsock connectTo: addr port: 54323.\\n\\tsock waitForConnectionUntil: self standardDeadline.\\n\\t(sock isConnected) ifFalse: [self error: 'sock not connected'].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\tstopRect _ 0@0 corner: 20@20. \\\"click in this rectangle to stop sending\\\"\\n\\tDisplay reverse: stopRect.\\n\\t[\\\"the sending process\\\"\\n\\t\\t[(stopRect containsPoint: Sensor cursorPoint) and:\\n\\t\\t [Sensor anyButtonPressed]]\\n\\t\\t\\twhileFalse: [\\n\\t\\t\\t\\tsock sendCommand: self sensorStateString.\\n\\t\\t\\t\\t(Delay forMilliseconds: 20) wait].\\n\\n\\t\\tsock waitForSendDoneUntil: self standardDeadline.\\n\\t\\tsock destroy.\\n\\t\\tTranscript show: 'remote cursor sender done'; cr.\\n\\t\\tDisplay reverse: stopRect.\\n\\t] fork.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'jm 9/15/97 14:49'!\\nparseSensorStateString: aString\\n\\t\\\"Parse the given sensor stat string and return an array whose first element is the cursor point and whose second is the cursor button state.\\\"\\n\\t\\\"SimpleClientSocket parseSensorStateString: SimpleClientSocket sensorStateString\\\"\\n\\n\\t| s buttons x y |\\n\\ts _ ReadStream on: aString.\\n\\tx _ Integer readFrom: s.\\n\\ts skipSeparators.\\n\\ty _ Integer readFrom: s.\\n\\ts skipSeparators.\\n\\tbuttons _ Integer readFrom: s.\\n\\t^ Array with: x@y with: buttons\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nremoteCursorReceiver\\n\\t\\\"Wait for a connection, then display data sent by the client until the client closes the stream. This server process is usually started first (optionally in a forked process), then the sender process is started (optionally on another machine). Note this machine's address, which is printed in the transcript, since the sender process will ask for it.\\\"\\n\\t\\\"[SimpleClientSocket remoteCursorReceiver] fork\\\"\\n\\n\\t| sock response |\\n\\tTranscript show: 'starting remote cursor receiver'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\tTranscript show: 'my address is ', NetNameResolver localAddressString; cr.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock _ OldSimpleClientSocket new.\\n\\tsock listenOn: 54323.\\n\\tsock waitForConnectionUntil: (Socket deadlineSecs: 60).\\n\\tsock isConnected\\n\\t\\tifFalse: [\\n\\t\\t\\t sock destroy.\\n\\t\\t\\tTranscript show: 'remote cursor receiver did not receive a connection in 60 seconds; aborting.'.\\n\\t\\t\\t^ self].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\t[sock isConnected]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsock dataAvailable\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tresponse _ sock getResponse.\\n\\t\\t\\t\\t\\tresponse displayOn: Display at: 10@10]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\\"if no data available, let other processes run for a while\\\"\\n\\t\\t\\t\\t\\t(Delay forMilliseconds: 20) wait]].\\n\\n\\tsock destroy.\\n\\tTranscript show: 'remote cursor receiver done'; cr.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nremoteCursorTest\\n\\t\\\"This version of the remote cursor test runs both the client and the server code in the same loop.\\\"\\n\\t\\\"SimpleClientSocket remoteCursorTest\\\"\\n\\n\\t| sock1 sock2 samplesToSend samplesSent done t |\\n\\tTranscript show: 'starting remote cursor test'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock1 _ OldSimpleClientSocket new.\\n\\tsock2 _ OldSimpleClientSocket new.\\n\\tsock1 listenOn: 54321.\\n\\tsock2 connectTo: (NetNameResolver localHostAddress) port: 54321.\\n\\tsock1 waitForConnectionUntil: self standardDeadline.\\n\\tsock2 waitForConnectionUntil: self standardDeadline.\\n\\t(sock1 isConnected) ifFalse: [self error: 'sock1 not connected'].\\n\\t(sock2 isConnected) ifFalse: [self error: 'sock2 not connected'].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\tsamplesToSend _ 100.\\n\\tt _ Time millisecondsToRun: [\\n\\t\\tsamplesSent _ 0.\\n\\t\\tdone _ false.\\n\\t\\t[done]\\n\\t\\t\\twhileFalse: [\\n\\t\\t\\t\\t(sock1 sendDone and: [samplesSent < samplesToSend]) ifTrue: [\\n\\t\\t\\t\\t\\tsock1 sendCommand: self sensorStateString.\\n\\t\\t\\t\\t\\tsamplesSent _ samplesSent + 1].\\n\\t\\t\\t\\tsock2 dataAvailable ifTrue: [\\n\\t\\t\\t\\t\\tsock2 getResponse displayOn: Display at: 10@10].\\n\\t\\t\\t\\tdone _ samplesSent = samplesToSend]].\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript show: 'remote cursor test done'; cr.\\n\\tTranscript show:\\n\\t\\tsamplesSent printString, ' samples sent in ',\\n\\t\\tt printString, ' milliseconds'; cr.\\n\\tTranscript show: ((samplesSent * 1000) // t) printString, ' samples/sec'; cr.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'jm 9/15/97 13:11'!\\nsensorStateString\\n\\t\\\"SimpleClientSocket sensorStateString\\\"\\n\\n\\t| pt buttons s |\\n\\tpt _ Sensor cursorPoint.\\n\\tbuttons _ Sensor primMouseButtons.\\n\\ts _ WriteStream on: (String new: 100).\\n\\ts nextPutAll: pt x printString.\\n\\ts space.\\n\\ts nextPutAll: pt y printString.\\n\\ts space.\\n\\ts nextPutAll: buttons printString.\\n\\t^ s contents\\n! !\\nObject subclass: #OldSocket\\n\\tinstanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore primitiveOnlySupportsOneSemaphore'\\n\\tclassVariableNames: 'Connected DeadServer InvalidSocket OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!OldSocket commentStamp: '<historical>' prior: 0!\\nA Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols\\n\\nSubclasses of socket provide support for network protocols such as POP, NNTP, HTTP, and FTP. Sockets also allow you to implement your own custom services and may be used to support Remote Procedure Call or Remote Method Invocation some day.\\n\\nJMM June 2nd 2000 Macintosh UDP support was added if you run open transport.\\n!\\n]style[(196 4 6 3 228)f1,f1LHTTPSocket Comment;,f1,f1LFTPSocket Comment;,f1!\\n\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\naddress\\n\\t\\\"Shortcut\\\"\\n\\t^self localAddress! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'nk 2/24/2005 14:37'!\\nlocalAddress\\n\\tself waitForConnectionUntil: self class standardDeadline.\\n\\tself isConnected ifFalse: [^ByteArray new: 4].\\n\\t^self primSocketLocalAddress: socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'nk 2/24/2005 14:37'!\\nlocalPort\\n\\tself waitForConnectionUntil: self class standardDeadline.\\n\\tself isConnected ifFalse: [^0].\\n\\t^self primSocketLocalPort: socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 3/13/98 12:11'!\\npeerName\\n\\t\\\"Return the name of the host I'm connected to, or nil if its name isn't known to the domain name server or the request times out.\\\"\\n\\t\\\"Note: Slow. Calls the domain name server, taking up to 20 seconds to time out. Even when sucessful, delays of up to 13 seconds have been observed during periods of high network load.\\\" \\n\\n\\t^ NetNameResolver\\n\\t\\tnameForAddress: self remoteAddress\\n\\t\\ttimeout: 20\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\nport\\n\\t\\\"Shortcut\\\"\\n\\t^self localPort! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 6/5/2000 10:12'!\\nprimitiveOnlySupportsOneSemaphore\\n\\t^primitiveOnlySupportsOneSemaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nreadSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^readSemaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremoteAddress\\n\\n\\t^ self primSocketRemoteAddress: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremotePort\\n\\n\\t^ self primSocketRemotePort: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/9/2000 15:32'!\\nsemaphore\\n\\t^semaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 7/16/1999 17:22'!\\nsocketHandle\\n\\t^socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nwriteSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^writeSemaphore! !\\n\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'nk 2/24/2005 14:37'!\\naccept\\n\\t\\\"Accept a connection from the receiver socket.\\n\\tReturn a new socket that is connected to the client\\\"\\n\\n\\t^self class acceptFrom: self! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 9/11/97 20:29'!\\nclose\\n\\t\\\"Close this connection gracefully. For TCP, this sends a close request, but the stream remains open until the other side also closes it.\\\"\\n\\n\\tself primSocketCloseConnection: socketHandle. \\\"close this end\\\"\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 11/4/97 07:15'!\\ncloseAndDestroy\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tself closeAndDestroy: 20.\\n\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'nk 2/24/2005 14:37'!\\ncloseAndDestroy: timeoutSeconds \\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil \\n\\t\\tifFalse: \\n\\t\\t\\t[self isConnected \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self close.\\t\\\"close this end\\\"\\n\\t\\t\\t\\t\\t(self waitForDisconnectionUntil: (self class deadlineSecs: timeoutSeconds)) \\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"if the other end doesn't close soon, just abort the connection\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tself primSocketAbortConnection: socketHandle]].\\n\\t\\t\\tself destroy]! !\\n\\n!OldSocket methodsFor: 'connection open/close'!\\nconnectTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address. This operation will return immediately; follow it with waitForConnectionUntil: to wait until the connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before opening a new connection'].\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 3/10/98 11:56'!\\ndisconnect\\n\\t\\\"Break this connection, no matter what state it is in. Data that has been sent but not received will be lost.\\\"\\n\\n\\tself primSocketAbortConnection: socketHandle.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close'!\\nlistenOn: port\\n\\t\\\"Listen for a connection on the given port. This operation will return immediately; follow it with waitForConnectionUntil: to wait until a connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\n\\tself primSocket: socketHandle listenOn: port.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'ar 7/16/1999 18:26'!\\nlistenOn: portNumber backlogSize: backlog\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'ikp 9/1/2003 20:47'!\\nlistenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog interface: ifAddr.\\n! !\\n\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 6/7/2000 14:58'!\\nreceiveDataInto: aStringOrByteArray fromHost: hostAddress port: portNumber\\n\\t| datagram |\\n\\t\\\"Receive a UDP packet from the given hostAddress/portNumber, storing the data in the given buffer, and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self receiveDataInto: aStringOrByteArray].\\n\\t[true] whileTrue: \\n\\t\\t[datagram _ self receiveUDPDataInto: aStringOrByteArray.\\n\\t\\t((datagram at: 2) = hostAddress and: [(datagram at: 3) = portNumber]) \\n\\t\\t\\tifTrue: [^datagram at: 1]\\n\\t\\t\\tifFalse: [^0]]! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 6/3/2000 21:54'!\\nreceiveUDPDataInto: aStringOrByteArray\\n\\t\\\"Receive UDP data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data. What is returned is an array, the first element is the bytes read, the second the sending bytearray address, the third the senders port, the fourth, true if more of the datagram awaits reading\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveUDPDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 5/25/2000 00:05'!\\nsendData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self sendData: aStringOrByteArray].\\n\\t^self sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'nk 2/24/2005 14:37'!\\nsendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber \\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\t| bytesToSend bytesSent count |\\n\\tbytesToSend := aStringOrByteArray size.\\n\\tbytesSent := 0.\\n\\t[bytesSent < bytesToSend] whileTrue: \\n\\t\\t\\t[(self waitForSendDoneUntil: (self class deadlineSecs: 20)) \\n\\t\\t\\t\\tifFalse: [self error: 'send data timeout; data not sent'].\\n\\t\\t\\tcount := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\tsendUDPData: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\ttoHost: hostAddress\\n\\t\\t\\t\\t\\t\\tport: portNumber\\n\\t\\t\\t\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\t\\t\\t\\tcount: bytesToSend - bytesSent.\\n\\t\\t\\tbytesSent := bytesSent + count].\\n\\t^bytesSent! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPeer: hostAddress port: port\\n\\t\\\"Set the default send/recv address.\\\"\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPort: port\\n\\t\\\"Associate a local port number with a UDP socket. Not applicable to TCP sockets.\\\"\\n\\n\\tself primSocket: socketHandle setPort: port.\\n! !\\n\\n\\n!OldSocket methodsFor: 'finalization' stamp: 'JMM 5/22/2000 22:52'!\\nfinalize\\n\\tself primSocketDestroyGently: socketHandle.\\n\\tSmalltalk unregisterExternalObject: semaphore.\\n\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n! !\\n\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:47'!\\nacceptFrom: aSocket\\n\\t\\\"Initialize a new socket handle from an accept call\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _ self primAcceptFrom: aSocket socketHandle\\n\\t\\t\\t\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\t\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\t\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\t\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\t\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:54'!\\ndestroy\\n\\t\\\"Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil ifFalse: \\n\\t\\t[self isValid ifTrue: [self primSocketDestroy: socketHandle].\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\tsocketHandle _ nil.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil.\\n\\t\\tself unregister].\\n! !\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 23:04'!\\ninitialize: socketType\\n\\t\\\"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil.\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _\\n\\t\\tself primSocketCreateNetwork: 0\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n\\n!OldSocket methodsFor: 'other' stamp: 'JMM 6/3/2000 19:39'!\\ngetOption: aName \\n\\t\\\"Get options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is an status number (0 ok, -1 read only option)\\n\\telement two is the resulting of the requested option\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [self error: 'Socket status must valid before getting an option'].\\n\\t^self primSocket: socketHandle getOption: aName\\n\\n\\\"| foo options |\\nSocket initializeNetwork.\\nfoo _ Socket newTCP.\\nfoo connectTo: (NetNameResolver addressFromString: '192.168.1.1') port: 80.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\noptions _ {\\n'SO_DEBUG'. 'SO_REUSEADDR'. 'SO_REUSEPORT'. 'SO_DONTROUTE'.\\n'SO_BROADCAST'. 'SO_SNDBUF'. 'SO_RCVBUF'. 'SO_KEEPALIVE'.\\n'SO_OOBINLINE'. 'SO_PRIORITY'. 'SO_LINGER'. 'SO_RCVLOWAT'.\\n'SO_SNDLOWAT'. 'IP_TTL'. 'IP_HDRINCL'. 'IP_RCVOPTS'.\\n'IP_RCVDSTADDR'. 'IP_MULTICAST_IF'. 'IP_MULTICAST_TTL'.\\n'IP_MULTICAST_LOOP'. 'UDP_CHECKSUM'. 'TCP_MAXSEG'.\\n'TCP_NODELAY'. 'TCP_ABORT_THRESHOLD'. 'TCP_CONN_NOTIFY_THRESHOLD'. \\n'TCP_CONN_ABORT_THRESHOLD'. 'TCP_NOTIFY_THRESHOLD'.\\n'TCP_URGENT_PTR_TYPE'}.\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\nfoo _ Socket newUDP.\\nfoo setPeer: (NetNameResolver addressFromString: '192.168.1.9') port: 7.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\\"! !\\n\\n!OldSocket methodsFor: 'other' stamp: 'nk 2/24/2005 14:37'!\\ngetResponseNoLF\\n\\t\\\"Get the response to the last command.\\\"\\n\\n\\t| buf response bytesRead c lf |\\n\\t(self waitForDataUntil: (self class deadlineSecs: 20)) \\n\\t\\tifFalse: [self error: 'getResponse timeout'].\\n\\tlf := Character lf.\\n\\tbuf := String new: 1000.\\n\\tresponse := WriteStream on: ''.\\n\\t[self dataAvailable] whileTrue: \\n\\t\\t\\t[bytesRead := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\treceiveDataInto: buf\\n\\t\\t\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\t\\t\\tcount: buf size.\\n\\t\\t\\t1 to: bytesRead\\n\\t\\t\\t\\tdo: [:i | (c := buf at: i) ~= lf ifTrue: [response nextPut: c]]].\\n\\t^response contents! !\\n\\n!OldSocket methodsFor: 'other' stamp: 'JMM 6/3/2000 19:39'!\\nsetOption: aName value: aValue \\n\\t| value |\\n\\t\\\"setup options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is the error number\\n\\telement two is the resulting of the negotiated value.\\n\\tSee getOption for list of keys\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [self error: 'Socket status must valid before setting an option'].\\n\\tvalue _ aValue asString.\\n\\taValue == true ifTrue: [value _ '1'].\\n\\taValue == false ifTrue: [value _ '0'].\\n\\t^ self primSocket: socketHandle setOption: aName value: value! !\\n\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept' module: 'SocketPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:55'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^self primAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex ! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID connectTo: hostAddress port: port\\n\\t\\\"Attempt to establish a connection to the given port of the given host. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectToPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 21:48'!\\nprimSocket: socketID getOption: aString \\n\\t\\\"Get some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the option value\\\"\\n\\n\\t<primitive: 'primitiveSocketGetOptions' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID listenOn: port\\n\\t\\\"Listen for a connection on the given port. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ikp 9/1/2003 20:55'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenOnPortBacklogInterface' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID receiveDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. Return the number of bytes read or zero if no data is available.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/24/2000 17:19'!\\nprimSocket: socketID receiveUDPDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. \\n\\tReturn an Array containing the amount read, the host address byte array, the host port, and the more flag\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID sendData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 00:08'!\\nprimSocket: socketID sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 7/18/2000 11:42'!\\nprimSocket: socketID setOption: aString value: aStringValue\\n\\t\\\"Set some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the negotiated value\\\"\\n\\n\\t<primitive: 'primitiveSocketSetOptions' module: 'SocketPlugin'>\\n\\t^nil! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID setPort: port\\n\\t\\\"Set the local port associated with a UDP socket.\\n\\tNote: this primitive is overloaded. The primitive will not fail on a TCP socket, but\\n\\tthe effects will not be what was desired. Best solution would be to split Socket into\\n\\ttwo subclasses, TCPSocket and UDPSocket.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketAbortConnection: socketID\\n\\t\\\"Terminate the connection on the given port immediately without going through the normal close sequence. This is an asynchronous call; query the socket status to discover if and when the connection is actually terminated.\\\"\\n\\n\\t<primitive: 'primitiveSocketAbortConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCloseConnection: socketID\\n\\t\\\"Close the connection on the given port. The remote end is informed that this end has closed and will do no further sends. This is an asynchronous call; query the socket status to discover if and when the connection is actually closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCloseConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketConnectionStatus: socketID\\n\\t\\\"Return an integer reflecting the connection status of this socket. For a list of possible values, see the comment in the 'initialize' method of this class. If the primitive fails, return a status indicating that the socket handle is no longer valid, perhaps because the Squeak image was saved and restored since the socket was created. (Sockets do not survive snapshots.)\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectionStatus' module: 'SocketPlugin'>\\n\\t^ InvalidSocket\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex\\n\\t\\\"Return a new socket handle for a socket of the given type and buffer sizes. Return nil if socket creation fails.\\n\\tThe netType parameter is platform dependent and can be used to encode both the protocol type (IP, Xerox XNS, etc.) and/or the physical network interface to use if this host is connected to multiple networks. A zero netType means to use IP protocols and the primary (or only) network interface.\\n\\tThe socketType parameter specifies:\\n\\t\\t0\\treliable stream socket (TCP if the protocol is IP)\\n\\t\\t1\\tunreliable datagram socket (UDP if the protocol is IP)\\n\\tThe buffer size parameters allow performance to be tuned to the application. For example, a larger receive buffer should be used when the application expects to be receiving large amounts of data, especially from a host that is far away. These values are considered requests only; the underlying implementation will ensure that the buffer sizes actually used are within allowable bounds. Note that memory may be limited, so an application that keeps many sockets open should use smaller buffer sizes. Note the macintosh implementation ignores this buffer size. Also see setOption to get/set socket buffer sizes which allows you to set/get the current buffer sizes for reading and writing.\\n \\tIf semaIndex is > 0, it is taken to be the index of a Semaphore in the external objects array to be associated with this socket. This semaphore will be signalled when the socket status changes, such as when data arrives or a send completes. All processes waiting on the semaphore will be awoken for each such event; each process must then query the socket state to figure out if the conditions they are waiting for have been met. For example, a process waiting to send some data can see if the last send has completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate' module: 'SocketPlugin'>\\n\\t^ nil \\\"socket creation failed\\\"\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:48'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"See comment in primSocketCreateNetwork: with one semaIndex. However you should know that some implementations\\n\\tignore the buffer size and this interface supports three semaphores, one for open/close/listen and the other two for\\n\\treading and writing\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^ self primSocketCreateNetwork: netType\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: rcvBufSize\\n\\t\\t\\tsendBufSize: sendBufSize\\n\\t\\t\\tsemaIndex: semaIndex! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroy: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroyGently: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\n\\tDo not fail if the receiver is already closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketError: socketID\\n\\t\\\"Return an integer encoding the most recent error on this socket. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveSocketError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalAddress: socketID\\n\\t\\\"Return the local host address for this socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalPort: socketID\\n\\t\\\"Return the local port for this socket, or zero if no port has yet been assigned.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketReceiveDataAvailable: socketID\\n\\t\\\"Return true if data may be available for reading from the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataAvailable' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemoteAddress: socketID\\n\\t\\\"Return the remote host address for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemoteAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemotePort: socketID\\n\\t\\\"Return the remote port for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemotePort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketSendDone: socketID\\n\\t\\\"Return true if there is no send in progress on the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDone' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!OldSocket methodsFor: 'printing' stamp: 'jm 11/23/1998 11:57'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '[', self statusString, ']'.\\n! !\\n\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\ndataAvailable\\n\\t\\\"Return true if this socket has unread received data.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketReceiveDataAvailable: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\nisConnected\\n\\t\\\"Return true if this socket is connected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Connected\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:15'!\\nisOtherEndClosed\\n\\t\\\"Return true if this socket had the other end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == OtherEndClosed\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:17'!\\nisThisEndClosed\\n\\t\\\"Return true if this socket had the this end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == ThisEndClosed\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnected\\n\\t\\\"Return true if this socket's state is Unconnected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Unconnected\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnectedOrInvalid\\n\\t\\\"Return true if this socket is completely disconnected or is invalid.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ true].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ (status = Unconnected) | (status = InvalidSocket)\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:51'!\\nisValid\\n\\t\\\"Return true if this socket contains a valid, non-nil socket handle.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ status ~= InvalidSocket\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisWaitingForConnection\\n\\t\\\"Return true if this socket is waiting for a connection.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == WaitingForConnection\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nsendDone\\n\\t\\\"Return true if the most recent send operation on this socket has completed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketSendDone: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/8/2000 23:24'!\\nsocketError\\n\\t^self primSocketError: socketHandle! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:56'!\\nstatusString\\n\\t\\\"Return a string describing the status of this socket.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ 'destroyed'].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tstatus = InvalidSocket ifTrue: [^ 'invalidSocketHandle'].\\n\\tstatus = Unconnected ifTrue: [^ 'unconnected'].\\n\\tstatus = WaitingForConnection ifTrue: [^ 'waitingForConnection'].\\n\\tstatus = Connected ifTrue: [^ 'connected'].\\n\\tstatus = OtherEndClosed ifTrue: [^ 'otherEndClosedButNotThisEnd'].\\n\\tstatus = ThisEndClosed ifTrue: [^ 'thisEndClosedButNotOtherEnd'].\\n\\t^ 'unknown socket status'\\n! !\\n\\n\\n!OldSocket methodsFor: 'registry' stamp: 'ar 3/21/98 17:40'!\\nregister\\n\\t^self class register: self! !\\n\\n!OldSocket methodsFor: 'registry' stamp: 'ar 3/21/98 17:41'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'jm 9/15/97 12:22'!\\ndiscardReceivedData\\n\\t\\\"Discard any data received up until now, and return the number of bytes discarded.\\\"\\n\\n\\t| buf totalBytesDiscarded |\\n\\tbuf _ String new: 10000.\\n\\ttotalBytesDiscarded _ 0.\\n\\t[self isConnected and: [self dataAvailable]] whileTrue: [\\n\\t\\ttotalBytesDiscarded _\\n\\t\\t\\ttotalBytesDiscarded + (self receiveDataInto: buf)].\\n\\t^ totalBytesDiscarded\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\ngetData\\n\\t\\\"Get some data\\\"\\n\\n\\t| buf bytesRead |\\n\\t(self waitForDataUntil: self class standardDeadline) \\n\\t\\tifFalse: [self error: 'getData timeout'].\\n\\tbuf := String new: 4000.\\n\\tbytesRead := self \\n\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: buf\\n\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\tcount: buf size.\\n\\t^buf copyFrom: 1 to: bytesRead! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\nreadInto: aStringOrByteArray startingAt: aNumber \\n\\t\\\"Read data into the given buffer starting at the given index and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t(self waitForDataUntil: self class standardDeadline) \\n\\t\\tifFalse: [self error: 'receive timeout'].\\n\\t^self \\n\\t\\tprimSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size - aNumber + 1! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'jm 9/15/97 12:21'!\\nreceiveDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'tak 3/16/2005 16:51'!\\nsendData: aStringOrByteArray\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent.\\\"\\n\\n\\t\\\"An experimental version use on slow lines: Longer timeout and smaller writes to try to avoid spurious timeouts.\\\"\\n\\n\\t| bytesSent bytesToSend count |\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneUntil: (Socket deadlineSecs: 60))\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 5000).\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ar 7/20/1999 17:23'!\\nsendData: buffer count: n\\n\\t\\\"Send the amount of data from the given buffer\\\"\\n\\t| sent |\\n\\tsent _ 0.\\n\\t[sent < n] whileTrue:[\\n\\t\\tsent _ sent + (self sendSomeData: buffer startIndex: sent+1 count: (n-sent))].! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ls 1/5/1999 15:05'!\\nsendSomeData: aStringOrByteArray\\n\\t\\\"Send as much of the given data as possible and answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: 1\\n\\t\\tcount: aStringOrByteArray size! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ls 3/3/1999 18:59'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex\\n\\t\\\"Send as much of the given data as possible starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: startIndex\\n\\t\\tcount: (aStringOrByteArray size - startIndex + 1)! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex count: count \\n\\t\\\"Send up to count bytes of the given data starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t| bytesSent |\\n\\t(self waitForSendDoneUntil: (self class deadlineSecs: 20)) \\n\\t\\tifTrue: \\n\\t\\t\\t[bytesSent := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\tstartIndex: startIndex\\n\\t\\t\\t\\t\\t\\tcount: count]\\n\\t\\tifFalse: [self error: 'send data timeout; data not sent'].\\n\\t^bytesSent! !\\n\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'ar 7/20/1999 17:21'!\\nwaitForAcceptUntil: deadLine\\n\\t\\\"Wait and accept an incoming connection\\\"\\n\\tself waitForConnectionUntil: deadLine.\\n\\t^self isConnected\\n\\t\\tifTrue:[self accept]\\n\\t\\tifFalse:[nil]! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'jm 3/2/98 18:15'!\\nwaitForConnectionUntil: deadline\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\t^ status = Connected\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/22/2000 22:04'!\\nwaitForDataUntil: deadline\\n\\t\\\"Wait up until the given deadline for data to arrive. Return true if data arrives by the deadline, false if not.\\\"\\n\\n\\t| dataArrived |\\n\\t[self isConnected & \\n\\t (dataArrived _ self primSocketReceiveDataAvailable: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ dataArrived\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/17/2000 14:52'!\\nwaitForDisconnectionUntil: deadline\\n\\t\\\"Wait up until the given deadline for the the connection to be broken. Return true if it is broken by the deadline, false if not.\\\"\\n\\t\\\"Note: The client should know the the connect is really going to be closed (e.g., because he has called 'close' to send a close request to the other end) before calling this method.\\nJMM 00/5/17 note that other end can close which will terminate wait\\\"\\n\\n\\t| extraBytes status |\\n\\textraBytes _ 0.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[((status = Connected) or: [(status = ThisEndClosed)]) and:\\n\\t [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\tself dataAvailable\\n\\t\\t\\tifTrue: [extraBytes _ extraBytes + self discardReceivedData].\\n\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\textraBytes > 0\\n\\t\\tifTrue: [self inform: 'Discarded ', extraBytes printString, ' bytes while closing connection.'].\\n\\n\\t^ status ~= Connected\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/22/2000 22:05'!\\nwaitForSendDoneUntil: deadline\\n\\t\\\"Wait up until the given deadline for the current send operation to complete. Return true if it completes by the deadline, false if not.\\\"\\n\\n\\t| sendDone |\\n\\t[self isConnected & (sendDone _ self primSocketSendDone: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself writeSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ sendDone! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOldSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!OldSocket class methodsFor: 'class initialization' stamp: 'ar 12/12/2001 19:12'!\\ninitialize\\n\\t\\\"Socket initialize\\\"\\n\\n\\t\\\"Socket Types\\\"\\n\\tTCPSocketType _ 0.\\n\\tUDPSocketType _ 1.\\n\\n\\t\\\"Socket Status Values\\\"\\n\\tInvalidSocket _ -1.\\n\\tUnconnected _ 0.\\n\\tWaitingForConnection _ 1.\\n\\tConnected _ 2.\\n\\tOtherEndClosed _ 3.\\n\\tThisEndClosed _ 4.\\n\\n\\tRegistryThreshold _ 100. \\\"# of sockets\\\"! !\\n\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nclientServerTestUDP\\n\\t\\\"Socket clientServerTestUDP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24:\\n\\t\\tclient/server UDP test done; time = 2820\\n\\t\\t2500 packets, 10000000 bytes sent (3546 kBytes/sec)\\n\\t\\t2500 packets, 10000000 bytes received (3546 kBytes/sec)\\n\\t\\t4000 bytes/packet, 886 packets/sec, 0 packets dropped\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: 'creating endpoints';\\n\\t\\tcr.\\n\\tsock1 := self newUDP.\\t\\\"the sender\\\"\\n\\tsock2 := self newUDP.\\t\\\"the recipient\\\"\\n\\tsock2 setPort: 54321.\\n\\tsock1 setPeer: NetNameResolver localHostAddress port: sock2 port.\\n\\tTranscript\\n\\t\\tshow: 'endpoints created';\\n\\t\\tcr.\\n\\tbytesToSend := 10000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (sock2 receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\tsock1 waitForSendDoneUntil: self standardDeadline.\\n\\t\\t\\t\\t\\tbytesReceived := bytesReceived + sock2 discardReceivedData].\\n\\tTranscript\\n\\t\\tshow: 'closing endpoints';\\n\\t\\tcr.\\n\\tsock1 close.\\n\\tsock2 close.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'client/server UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nclientServerTestUDP2\\n\\t\\\"Socket clientServerTestUDP2\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t datagramInfo |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: 'creating endpoints';\\n\\t\\tcr.\\n\\tsock1 := self newUDP.\\t\\\"the sender\\\"\\n\\tsock2 := self newUDP.\\t\\\"the recipient\\\"\\n\\tsock2 setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'endpoints created';\\n\\t\\tcr.\\n\\tbytesToSend := 100000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 2000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsendData: sendBuf\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttoHost: NetNameResolver localHostAddress\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tport: sock2 port)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdatagramInfo := sock2 receiveUDPDataInto: receiveBuf.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (datagramInfo at: 1)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\tsock1 waitForSendDoneUntil: self standardDeadline.\\n\\t\\t\\t\\t\\tbytesReceived := bytesReceived + sock2 discardReceivedData].\\n\\tTranscript\\n\\t\\tshow: 'closing endpoints';\\n\\t\\tcr.\\n\\tsock1 close.\\n\\tsock2 close.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'client/server UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:02'!\\nremoteTestClientTCP\\n\\t\\\"FIRST start up another image, and execute: Socket remoteTestServerTCP.\\n\\tTHEN come back to this image and execute:\\\"\\n\\n\\t\\\"Socket remoteTestClientTCP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24, both images on same CPU:\\n\\t\\tremoteClient TCP test done; time = 5680\\n\\t\\t250 packets, 1000000 bytes sent (176 kBytes/sec)\\n\\t\\t60 packets, 1000000 bytes received (176 kBytes/sec)\\\"\\n\\n\\t| socket bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newTCP.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\tport: 54321.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\tTranscript\\n\\t\\tshow: 'client endpoint created';\\n\\t\\tcr.\\n\\tbytesToSend := 1000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(socket sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (socket sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsocket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\t[bytesReceived < bytesToSend] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)]]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: 'remoteClient TCP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' bytes/sec)';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:02'!\\nremoteTestClientTCPOpenClose1000\\n\\t\\\"Socket remoteTestClientTCPOpenClose1000\\\"\\n\\n\\t| number t1 socket serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tnumber := 1000.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tt1 := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[number timesRepeat: \\n\\t\\t\\t\\t\\t\\t\\t[socket := self newTCP.\\n\\t\\t\\t\\t\\t\\t\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\t\\t\\t\\t\\t\\t\\tport: 54321.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t\\t\\t\\t\\t\\t\\tsocket closeAndDestroy]].\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'connects/close per second ' , (number / t1 * 1000.0) printString;\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\nremoteTestClientTCPOpenClosePutGet\\n\\t\\\"Socket remoteTestClientTCPOpenClosePutGet\\\"\\n\\n\\t| checkLength number bytesExpected sendBuf receiveBuf t1 socket bytesReceived serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tnumber := 1000.\\n\\tbytesExpected := 20000.\\n\\tsendBuf := String new: 80 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tt1 := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[number timesRepeat: \\n\\t\\t\\t\\t\\t\\t\\t[socket := self newTCP.\\n\\t\\t\\t\\t\\t\\t\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\t\\t\\t\\t\\t\\t\\tport: 54321.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t\\t\\t\\t\\t\\t\\tsocket sendData: sendBuf.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForSendDoneUntil: (self deadlineSecs: 5).\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForDataUntil: (self deadlineSecs: 5).\\n\\t\\t\\t\\t\\t\\t\\tbytesReceived := 0.\\n\\t\\t\\t\\t\\t\\t\\t[bytesReceived < bytesExpected] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[checkLength := socket receiveDataInto: receiveBuf.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + checkLength].\\n\\t\\t\\t\\t\\t\\t\\tsocket closeAndDestroy]].\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'connects/get/put/close per second ' \\n\\t\\t\\t\\t\\t, (number / t1 * 1000.0) printString;\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\nremoteTestClientUDP\\n\\t\\\"FIRST start up another image, and execute: Socket remoteTestServerUDP.\\n\\tTHEN come back to this image and execute:\\\"\\n\\n\\t\\\"Socket remoteTestClientUDP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24:\\n\\t\\tremoteClient UDP test done; time = 4580\\n\\t\\t2500 packets, 10000000 bytes sent (2183 kBytes/sec)\\n\\t\\t180 packets, 720000 bytes received (157 kBytes/sec)\\n\\t\\t4000 bytes/packet, 39 packets/sec, 2320 packets dropped\\\"\\n\\n\\t| socket bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tsocket := self newUDP.\\n\\tsocket setPeer: (NetNameResolver addressFromString: serverName) port: 54321.\\n\\tTranscript\\n\\t\\tshow: 'client endpoint created';\\n\\t\\tcr.\\n\\tbytesToSend := 10000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 4000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(socket sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (socket sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsocket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t[socket waitForDataUntil: (self deadlineSecs: 1).\\n\\t\\t\\t\\t\\tsocket dataAvailable] \\n\\t\\t\\t\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: 'remoteClient UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCP\\n\\t\\\"See remoteTestClientTCP for instructions on running this method.\\\"\\n\\n\\t\\\"OldSocket remoteTestServerTCP\\\"\\n\\n\\t| socket client buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetwork.\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := OldSocket newTCP.\\n\\tsocket \\n\\t\\tlistenOn: 54321\\n\\t\\tbacklogSize: 5\\n\\t\\tinterface: (NetNameResolver addressFromString: '127.0.0.1').\\t\\\"or: 0.0.0.0\\\"\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 4000.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\tclient := socket accept.\\n\\t[client isConnected] whileTrue: \\n\\t\\t\\t[client dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[n := client receiveDataInto: buffer.\\n\\t\\t\\t\\t\\tclient sendData: buffer count: n]].\\n\\tclient closeAndDestroy.\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr.\\n\\t^socket! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPOpenClose1000\\n\\t\\\"The version of #remoteTestServerTCPOpenClose1000 using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPOpenClose1000\\\"\\n\\n\\t| socket server |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 20.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\t1000 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\tsocket closeAndDestroy].\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPOpenClosePutGet\\n\\t\\\"The version of #remoteTestServerTCPOpenClosePutGet using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPOpenClosePutGet\\\"\\n\\n\\t| socket server bytesIWantToSend bytesExpected receiveBuf sendBuf checkLength |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 20.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbytesIWantToSend := 20000.\\n\\tbytesExpected := 80.\\n\\treceiveBuf := String new: 40000.\\n\\tsendBuf := String new: bytesIWantToSend withAll: $x.\\n\\t1000 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\tsocket waitForDataUntil: (self deadlineSecs: 5).\\n\\t\\t\\tcheckLength := socket receiveDataInto: receiveBuf.\\n\\t\\t\\tcheckLength ~= bytesExpected ifTrue: [self halt].\\n\\t\\t\\tsocket sendData: sendBuf.\\n\\t\\t\\tsocket waitForSendDoneUntil: (self deadlineSecs: 5).\\n\\t\\t\\tsocket closeAndDestroy].\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPUsingAccept\\n\\t\\\"The version of #remoteTestServer using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPUsingAccept\\\"\\n\\n\\t| socket buffer n server |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 4.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 40000.\\n\\t10 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\t[socket isConnected] whileTrue: \\n\\t\\t\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[n := socket receiveDataInto: buffer.\\n\\t\\t\\t\\t\\t\\t\\tsocket sendData: buffer count: n]]].\\n\\tsocket closeAndDestroy.\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerUDP\\n\\t\\\"See remoteTestClientUDP for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestServerUDP\\\"\\n\\n\\t| socket buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newUDP.\\n\\tsocket setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 4000.\\n\\t[true] whileTrue: \\n\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[n := socket receiveDataInto: buffer.\\n\\t\\t\\t\\t\\tsocket sendData: buffer count: n]]! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerUDP2\\n\\t\\\"See remoteTestClientUDP for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestServerUDP2\\\"\\n\\n\\t| socket buffer datagramInfo |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newUDP.\\n\\tsocket setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 65000.\\n\\t[true] whileTrue: \\n\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[datagramInfo := socket receiveUDPDataInto: buffer.\\n\\t\\t\\t\\t\\tTranscript\\n\\t\\t\\t\\t\\t\\tshow: datagramInfo printString;\\n\\t\\t\\t\\t\\t\\tcr.\\n\\t\\t\\t\\t\\tsocket sendData: buffer count: (datagramInfo at: 1)]]! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestSinkTCP\\n\\t\\\"See sendTest for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestSinkTCP\\\"\\n\\n\\t| socket buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newTCP.\\n\\tsocket listenOn: 9.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 64000.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t[socket isConnected] whileTrue: \\n\\t\\t\\t[socket dataAvailable ifTrue: [n := socket receiveDataInto: buffer]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'sink endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTest\\n\\t\\\"OldSocket timeTest\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self new.\\n\\tTranscript\\n\\t\\tshow: '---------- Connecting ----------';\\n\\t\\tcr.\\n\\ts connectTo: serverAddr port: 13.\\t\\\"13 is the 'daytime' port number\\\"\\n\\ts waitForConnectionUntil: (self deadlineSecs: 1).\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Connection Closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP\\n\\t\\\"Socket timeTestUDP\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\t\\\"a 'random' port number will be allocated by the system\\\"\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\t\\\"13 is the daytime service\\\"\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP2\\n\\t\\\"Socket timeTestUDP2\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\n\\t\\\"The following associates a port with the UDP socket, but does NOT create a connectable endpoint\\\"\\n\\ts setPort: 54321.\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP3\\n\\t\\\"Socket timeTestUDP3\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\n\\t\\\"The following associates a port with the UDP socket, but does NOT create a connectable endpoint\\\"\\n\\ts setPort: self wildcardPort.\\t\\\"explicitly request a default port number\\\"\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:45'!\\nacceptFrom: aSocket\\n\\t^[ super new acceptFrom: aSocket ]\\n\\t\\trepeatWithGCIf: [ :sock | sock isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:15'!\\ncreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\t\\\"Note: The default creates a TCP socket\\\"\\n\\t^self tcpCreateIfFail: failBlock! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:13'!\\nnew\\n\\t\\\"Return a new, unconnected Socket. Note that since socket creation may fail, it is safer to use the method createIfFail: to handle such failures gracefully; this method is primarily for backward compatibility and may be disallowed in a future release.\\\"\\n\\t\\\"Note: The default creates a TCP socket - this is also backward compatibility.\\\"\\n\\t^self newTCP! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 10:19'!\\nnewTCP\\n\\t\\\"Create a socket and initialise it for TCP\\\"\\n\\t^[ super new initialize: TCPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:44'!\\nnewUDP\\n\\t\\\"Create a socket and initialise it for UDP\\\"\\n\\t^[ super new initialize: UDPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:14'!\\ntcpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tsock _ super new initialize: TCPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:14'!\\nudpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tsock _ super new initialize: UDPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'nk 2/24/2005 14:38'!\\nensureNetworkConnected\\n\\t\\\"Try to ensure that an intermittent network connection, such as a dialup or ISDN line, is actually connected. This is necessary to make sure a server is visible in order to accept an incoming connection.\\\"\\n\\n\\t\\\"Socket ensureNetworkConnected\\\"\\n\\n\\tself initializeNetwork.\\n\\tUtilities informUser: 'Contacting domain name server...'\\n\\t\\tduring: \\n\\t\\t\\t[NetNameResolver addressForName: 'bogusNameToForceDNSToBeConsulted.org'\\n\\t\\t\\t\\ttimeout: 30]! !\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'mir 11/14/2002 19:36'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and the NetNameResolver. Do nothing if the network is already initialized.\\\"\\n\\t\\\"Note: The network must be re-initialized every time Squeak starts up, so applications that persist across snapshots should be prepared to re-initialize the network as needed. Such applications should call 'Socket initializeNetwork' before every network transaction. \\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'mir 11/14/2002 19:36'!\\ninitializeNetworkIfFail: failBlock\\n\\t\\\"Initialize the network drivers. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails, perhaps because this computer isn't currently connected to a network.\\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\t^RegistryThreshold! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold: aNumber\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\tRegistryThreshold _ aNumber! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:22'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\n\\n\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:54'!\\ndeadServer\\n\\n\\t^ DeadServer! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:56'!\\ndeadServer: aStringOrNil\\n\\t\\\"Keep the machine name of the most recently encoutered non-responding machine. Next time the user can move it to the last in a list of servers to try.\\\"\\n\\n\\tDeadServer _ aStringOrNil! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 9/15/97 06:56'!\\ndeadlineSecs: secs\\n\\t\\\"Return a deadline time the given number of seconds from now.\\\"\\n\\n\\t^ Time millisecondClockValue + (secs * 1000)\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 12:13'!\\nnameForWellKnownTCPPort: portNum\\n\\t\\\"Answer the name for the given well-known TCP port number. Answer a string containing the port number if it isn't well-known.\\\"\\n\\n\\t| portList entry |\\n\\tportList _ #(\\n\\t\\t(7 'echo') (9 'discard') (13 'time') (19 'characterGenerator')\\n\\t\\t(21 'ftp') (23 'telnet') (25 'smtp')\\n\\t\\t(80 'http') (110 'pop3') (119 'nntp')).\\n\\tentry _ portList detect: [:pair | pair first = portNum] ifNone: [^ 'port-', portNum printString].\\n\\t^ entry last\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\nping: hostName \\n\\t\\\"Ping the given host. Useful for checking network connectivity. The host must be running a TCP echo server.\\\"\\n\\n\\t\\\"Socket ping: 'squeak.cs.uiuc.edu'\\\"\\n\\n\\t| tcpPort sock serverAddr startTime echoTime |\\n\\ttcpPort := 7.\\t\\\"7 = echo port, 13 = time port, 19 = character generator port\\\"\\n\\tself initializeNetwork.\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [^self inform: 'Could not find an address for ' , hostName].\\n\\tsock := self new.\\n\\tsock connectTo: serverAddr port: tcpPort.\\n\\t\\n\\t[sock waitForConnectionUntil: (self deadlineSecs: 10).\\n\\tsock isConnected] \\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(self confirm: 'Continue to wait for connection to ' , hostName , '?') \\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[sock destroy.\\n\\t\\t\\t\\t\\t\\t^self]].\\n\\tsock sendData: 'echo!!'.\\n\\tstartTime := Time millisecondClockValue.\\n\\t\\n\\t[sock waitForDataUntil: (self deadlineSecs: 15).\\n\\tsock dataAvailable] \\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(self confirm: 'Packet sent but no echo yet; keep waiting?') \\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[sock destroy.\\n\\t\\t\\t\\t\\t\\t^self]].\\n\\techoTime := Time millisecondClockValue - startTime.\\n\\tsock destroy.\\n\\tself inform: hostName , ' responded in ' , echoTime printString \\n\\t\\t\\t\\t, ' milliseconds'! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\npingPorts: portList on: hostName timeOutSecs: timeOutSecs \\n\\t\\\"Attempt to connect to each of the given sockets on the given host. Wait at most timeOutSecs for the connections to be established. Answer an array of strings indicating the available ports.\\\"\\n\\n\\t\\\"Socket pingPorts: #(7 13 19 21 23 25 80 110 119) on: 'squeak.cs.uiuc.edu' timeOutSecs: 15\\\"\\n\\n\\t| serverAddr sockets sock deadline done unconnectedCount connectedCount waitingCount result |\\n\\tself initializeNetwork.\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: \\n\\t\\t\\t[self inform: 'Could not find an address for ' , hostName.\\n\\t\\t\\t^#()].\\n\\tsockets := portList collect: \\n\\t\\t\\t\\t\\t[:portNum | \\n\\t\\t\\t\\t\\tsock := self new.\\n\\t\\t\\t\\t\\tsock connectTo: serverAddr port: portNum].\\n\\tdeadline := self deadlineSecs: timeOutSecs.\\n\\tdone := false.\\n\\t[done] whileFalse: \\n\\t\\t\\t[unconnectedCount := 0.\\n\\t\\t\\tconnectedCount := 0.\\n\\t\\t\\twaitingCount := 0.\\n\\t\\t\\tsockets do: \\n\\t\\t\\t\\t\\t[:s | \\n\\t\\t\\t\\t\\ts isUnconnectedOrInvalid \\n\\t\\t\\t\\t\\t\\tifTrue: [unconnectedCount := unconnectedCount + 1]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[s isConnected ifTrue: [connectedCount := connectedCount + 1].\\n\\t\\t\\t\\t\\t\\t\\ts isWaitingForConnection ifTrue: [waitingCount := waitingCount + 1]]].\\n\\t\\t\\twaitingCount = 0 ifTrue: [done := true].\\n\\t\\t\\tconnectedCount = sockets size ifTrue: [done := true].\\n\\t\\t\\tTime millisecondClockValue > deadline ifTrue: [done := true]].\\n\\tresult := (sockets select: [:s | s isConnected]) \\n\\t\\t\\t\\tcollect: [:s | self nameForWellKnownTCPPort: s remotePort].\\n\\tsockets do: [:s | s destroy].\\n\\t^result! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\npingPortsOn: hostName \\n\\t\\\"Attempt to connect to a set of well-known sockets on the given host, and answer the names of the available ports.\\\"\\n\\n\\t\\\"Socket pingPortsOn: 'www.disney.com'\\\"\\n\\n\\t^self \\n\\t\\tpingPorts: #(7 13 19 21 23 25 80 110 119)\\n\\t\\ton: hostName\\n\\t\\ttimeOutSecs: 20! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 9/15/97 06:56'!\\nstandardDeadline\\n\\t\\\"Return a default deadline time some seconds into the future.\\\"\\n\\n\\t^ self deadlineSecs: 45\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardAddress\\n\\t\\\"Answer a don't-care address for use with UDP sockets.\\\"\\n\\n\\t^ByteArray new: 4\\t\\t\\\"0.0.0.0\\\"! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardPort\\n\\t\\\"Answer a don't-care port for use with UDP sockets. (The system will allocate an\\n\\tunused port number to the socket.)\\\"\\n\\n\\t^0! !\\nSwitch subclass: #OneOnSwitch\\n\\tinstanceVariableNames: 'connection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Menus'!\\n!OneOnSwitch commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nconnection\\n\\t\\\"Answer the object that connects the receiver to other Switches.\\\"\\n\\n\\t^connection! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nconnection: anObject \\n\\t\\\"Set anObject to be the connection among two or more Switches. Make the \\n\\treceiver a dependent of the argument, anObject.\\\"\\n\\n\\tconnection _ anObject.\\n\\tconnection addDependent: self! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nisConnectionSet\\n\\t\\\"Answer whether the receiver is connected to an object that coordinates \\n\\tupdates among switches.\\\"\\n\\n\\tconnection == nil\\n\\t\\tifTrue: [^false]\\n\\t\\tifFalse: [^true]! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nnotifyConnection\\n\\t\\\"Send the receiver's connection (if it exists) the message 'changed: self' in \\n\\torder for the connection to broadcast the change to other objects \\n\\tconnected by the connection.\\\"\\n\\t\\n\\tself isConnectionSet ifTrue: [self connection changed: self]! !\\n\\n\\n!OneOnSwitch methodsFor: 'initialize-release'!\\nrelease\\n\\n\\tsuper release.\\n\\tself isConnectionSet ifTrue: [connection removeDependent: self]! !\\n\\n\\n!OneOnSwitch methodsFor: 'state'!\\nturnOn\\n\\t\\\"Does nothing if it is already on. If it is not, it is set to 'on', its\\n\\tdependents are \\tnotified of the change, its connection is notified, and\\n\\tits action is executed.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself notifyConnection.\\n\\t\\t\\tself doAction: onAction]! !\\n\\n\\n!OneOnSwitch methodsFor: 'updating'!\\nupdate: aOneOnSwitch \\n\\t\\\"Does nothing if aOneOnSwitch is identical to this object. If it is not, this \\n\\tobject is turned off. This message is sent by the connection (an Object)\\n\\twhen some related OneOnSwitch (possibly this one) has changed. This\\n\\tallows a group of related OneOnSwitches to maintain the constraint that\\n\\tat most one will be on at any time.\\\"\\n\\n\\tself ~~ aOneOnSwitch ifTrue: [self turnOff]! !\\nURI subclass: #OpaqueURI\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-URI'!\\n\\n!OpaqueURI methodsFor: 'testing' stamp: 'mir 2/20/2002 16:55'!\\nisOpaque\\n\\t^true! !\\nSmallLandColorTheme subclass: #OrangeSmallLandColorTheme\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support'!\\n\\n!OrangeSmallLandColorTheme methodsFor: 'initialization' stamp: 'dgd 3/12/2006 13:25'!\\nbaseColors\\n\\\"\\nOrangeSmallLandColorTheme apply.\\n\\\"\\n\\t^ Array\\n\\t\\twith: (Color fromArray: #(0.8 0.4 0.0 ))\\n\\t\\twith: (Color fromArray: #(1.0 0.8 0.0 ))\\n\\t\\twith: (Color fromArray: #(1.0 1.0 0.8 ))! !\\nSequenceableCollection subclass: #OrderedCollection\\n\\tinstanceVariableNames: 'array firstIndex lastIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Sequenceable'!\\n!OrderedCollection commentStamp: '<historical>' prior: 0!\\nI represent a collection of objects ordered by the collector.!\\n\\n\\n!OrderedCollection methodsFor: 'accessing'!\\nat: anInteger \\n\\t\\\"Answer my element at index anInteger. at: is used by a knowledgeable\\n\\tclient to access an existing element\\\"\\n\\n\\t(anInteger < 1 or: [anInteger + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [self errorNoSuchElement]\\n\\t\\tifFalse: [^ array at: anInteger + firstIndex - 1]! !\\n\\n!OrderedCollection methodsFor: 'accessing'!\\nat: anInteger put: anObject \\n\\t\\\"Put anObject at element index anInteger. at:put: cannot be used to\\n\\tappend, front or back, to an ordered collection; it is used by a\\n\\tknowledgeable client to replace an element.\\\"\\n\\n\\t| index |\\n\\tindex _ anInteger asInteger.\\n\\t(index < 1 or: [index + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [self errorNoSuchElement]\\n\\t\\tifFalse: [^array at: index + firstIndex - 1 put: anObject]! !\\n\\n!OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:42'!\\ncapacity\\n\\t\\\"Answer the current capacity of the receiver.\\\"\\n\\n\\t^ array size! !\\n\\n!OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:39'!\\nsize\\n\\t\\\"Answer how many elements the receiver contains.\\\"\\n\\n\\t^ lastIndex - firstIndex + 1! !\\n\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject\\n\\n\\t^self addLast: newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject after: oldObject \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just succeeding oldObject. Answer newObject.\\\"\\n\\t\\n\\t| index |\\n\\tindex _ self find: oldObject.\\n\\tself insert: newObject before: index + 1.\\n\\t^newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'di 3/15/1999 14:01'!\\nadd: newObject afterIndex: index \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just after index. Answer newObject.\\\"\\n\\n\\tself insert: newObject before: firstIndex + index.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject before: oldObject \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just preceding oldObject. Answer newObject.\\\"\\n\\t\\n\\t| index |\\n\\tindex _ self find: oldObject.\\n\\tself insert: newObject before: index.\\n\\t^newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'BG 1/9/2004 12:30'!\\nadd: newObject beforeIndex: index \\n \\\"Add the argument, newObject, as an element of the receiver. Put it in \\n the sequence just before index. Answer newObject.\\\"\\n\\n self add: newObject afterIndex: index - 1.\\n ^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'sma 5/12/2000 11:26'!\\naddAll: aCollection \\n\\t\\\"Add each element of aCollection at my end. Answer\\taCollection.\\\"\\n\\n\\t^ self addAllLast: aCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddAllFirst: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the beginning of the \\n\\treceiver. Answer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection reverseDo: [:each | self addFirst: each].\\n\\t^anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'sw 3/1/2001 11:03'!\\naddAllFirstUnlessAlreadyPresent: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the beginning of the receiver, preserving the order, but do not add any items that are already in the receiver. Answer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection reverseDo:\\n\\t\\t[:each | (self includes: each) ifFalse: [self addFirst: each]].\\n\\t^ anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddAllLast: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the end of the receiver. \\n\\tAnswer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection do: [:each | self addLast: each].\\n\\t^anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddFirst: newObject \\n\\t\\\"Add newObject to the beginning of the receiver. Answer newObject.\\\"\\n\\n\\tfirstIndex = 1 ifTrue: [self makeRoomAtFirst].\\n\\tfirstIndex _ firstIndex - 1.\\n\\tarray at: firstIndex put: newObject.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddLast: newObject \\n\\t\\\"Add newObject to the end of the receiver. Answer newObject.\\\"\\n\\n\\tlastIndex = array size ifTrue: [self makeRoomAtLast].\\n\\tlastIndex _ lastIndex + 1.\\n\\tarray at: lastIndex put: newObject.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'ajh 5/22/2003 12:03'!\\nat: index ifAbsentPut: block\\n\\t\\\"Return value at index, however, if value does not exist (nil or out of bounds) then add block's value at index (growing self if necessary)\\\"\\n\\n\\t| v |\\n\\tindex <= self size ifTrue: [\\n\\t\\t^ (v _ self at: index)\\n\\t\\t\\tifNotNil: [v]\\n\\t\\t\\tifNil: [self at: index put: block value]\\n\\t].\\n\\t[self size < index] whileTrue: [self add: nil].\\n\\t^ self at: index put: block value! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\ngrow\\n\\t\\\"Become larger. Typically, a subclass has to override this if the subclass\\n\\tadds instance variables.\\\"\\n\\t| newArray |\\n\\tnewArray _ Array new: self size + self growSize.\\n\\tnewArray replaceFrom: 1 to: array size with: array startingAt: 1.\\n\\tarray _ newArray! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\ngrowSize\\n\\t^ array size max: 2! !\\n\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver that contains no elements.\\\"\\n\\n\\t^self species new! !\\n\\n!OrderedCollection methodsFor: 'copying' stamp: 'di 12/12/2000 10:15'!\\ncopyFrom: startIndex to: endIndex \\n\\t\\\"Answer a copy of the receiver that contains elements from position\\n\\tstartIndex to endIndex.\\\"\\n\\n\\t| targetCollection |\\n\\tendIndex < startIndex ifTrue: [^self species new: 0].\\n\\ttargetCollection _ self species new: endIndex + 1 - startIndex.\\n\\tstartIndex to: endIndex do: [:index | targetCollection addLast: (self at: index)].\\n\\t^ targetCollection! !\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyReplaceFrom: start to: stop with: replacementCollection \\n\\t\\\"Answer a copy of the receiver with replacementCollection's elements in\\n\\tplace of the receiver's start'th to stop'th elements. This does not expect\\n\\ta 1-1 map from replacementCollection to the start to stop elements, so it\\n\\twill do an insert or append.\\\"\\n\\n\\t| newOrderedCollection delta startIndex stopIndex |\\n\\t\\\"if start is less than 1, ignore stop and assume this is inserting at the front. \\n\\tif start greater than self size, ignore stop and assume this is appending. \\n\\totherwise, it is replacing part of me and start and stop have to be within my \\n\\tbounds. \\\"\\n\\tdelta _ 0.\\n\\tstartIndex _ start.\\n\\tstopIndex _ stop.\\n\\tstart < 1\\n\\t\\tifTrue: [startIndex _ stopIndex _ 0]\\n\\t\\tifFalse: [startIndex > self size\\n\\t\\t\\t\\tifTrue: [startIndex _ stopIndex _ self size + 1]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(stopIndex < (startIndex - 1) or: [stopIndex > self size])\\n\\t\\t\\t\\t\\t\\tifTrue: [self errorOutOfBounds].\\n\\t\\t\\t\\t\\tdelta _ stopIndex - startIndex + 1]].\\n\\tnewOrderedCollection _ \\n\\t\\tself species new: self size + replacementCollection size - delta.\\n\\t1 to: startIndex - 1 do: [:index | newOrderedCollection add: (self at: index)].\\n\\t1 to: replacementCollection size do: \\n\\t\\t[:index | newOrderedCollection add: (replacementCollection at: index)].\\n\\tstopIndex + 1 to: self size do: [:index | newOrderedCollection add: (self at: index)].\\n\\t^newOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyWith: newElement \\n\\t\\\"Answer a copy of the receiver that is 1 bigger than the receiver and \\n\\tincludes the argument, newElement, at the end.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self copy.\\n\\tnewCollection add: newElement.\\n\\t^newCollection! !\\n\\n!OrderedCollection methodsFor: 'copying' stamp: 'sw 1/26/96'!\\nreversed\\n\\t\\\"Answer a copy of the receiver with element order reversed. \\\"\\n\\t| newCol |\\n\\tnewCol _ self species new.\\n\\tself reverseDo:\\n\\t\\t[:elem | newCol addLast: elem].\\n\\t^ newCol\\n\\n\\\"#(2 3 4 'fred') reversed\\\"! !\\n\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'!\\ncollect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect the \\n\\tresulting values into a collection that is like me. Answer the new \\n\\tcollection. Override superclass in order to use addLast:, not at:put:.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species new: self size.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\tnewCollection addLast: (aBlock value: (array at: index))].\\n\\t^ newCollection! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/18/2000 17:34'!\\ncollect: aBlock from: fromIndex to: toIndex\\n\\t\\\"Override superclass in order to use addLast:, not at:put:.\\\"\\n\\t| result |\\n\\t(fromIndex < 1 or:[toIndex + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [^self errorNoSuchElement].\\n\\tresult _ self species new: toIndex - fromIndex + 1.\\n\\tfirstIndex + fromIndex - 1 to: firstIndex + toIndex - 1 do:\\n\\t\\t[:index | result addLast: (aBlock value: (array at: index))].\\n\\t^ result\\n! !\\n\\n!OrderedCollection methodsFor: 'enumerating'!\\ndo: aBlock \\n\\t\\\"Override the superclass for performance reasons.\\\"\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: (array at: index).\\n\\t\\t\\tindex _ index + 1]! !\\n\\n!OrderedCollection methodsFor: 'enumerating'!\\nreverseDo: aBlock \\n\\t\\\"Override the superclass for performance reasons.\\\"\\n\\t| index |\\n\\tindex _ lastIndex.\\n\\t[index >= firstIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: (array at: index).\\n\\t\\t\\tindex _ index - 1]! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:13'!\\nselect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect into\\n\\ta new collection like the receiver, only those elements for which aBlock\\n\\tevaluates to true.\\\"\\n\\n\\t| newCollection element |\\n\\tnewCollection _ self copyEmpty.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\t(aBlock value: (element _ array at: index))\\n\\t\\t\\tifTrue: [newCollection addLast: element]].\\n\\t^ newCollection! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'di 8/31/1999 13:13'!\\nwith: otherCollection collect: twoArgBlock \\n\\t\\\"Collect and return the result of evaluating twoArgBlock with \\n\\tcorresponding elements from this collection and otherCollection.\\\"\\n\\t| result |\\n\\totherCollection size = self size ifFalse: [self error: 'otherCollection must be the same size'].\\n\\tresult _ self species new: self size.\\n\\t1 to: self size do:\\n\\t\\t[:index | result addLast: (twoArgBlock value: (self at: index)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: (otherCollection at: index))].\\n\\t^ result! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/16/2000 16:30'!\\nwithIndexCollect: elementAndIndexBlock \\n\\t\\\"Just like with:collect: except that the iteration index supplies the second argument to the block. Override superclass in order to use addLast:, not at:put:.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species new: self size.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\tnewCollection addLast: (elementAndIndexBlock\\n\\t\\t\\tvalue: (array at: index)\\n\\t\\t\\tvalue: index - firstIndex + 1)].\\n\\t^ newCollection! !\\n\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremove: oldObject ifAbsent: absentBlock\\n\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[oldObject = (array at: index)\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self removeIndex: index.\\n\\t\\t\\t\\t\\t^ oldObject]\\n\\t\\t\\t\\tifFalse: [index _ index + 1]].\\n\\t^ absentBlock value! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'raok 4/27/2001 15:35'!\\nremoveAllSuchThat: aBlock \\n\\t\\\"Remove each element of the receiver for which aBlock evaluates to true.\\n\\tThe method in Collection is O(N^2), this is O(N).\\\"\\n\\n\\t| n |\\n\\tn _ firstIndex.\\n\\tfirstIndex to: lastIndex do: [:index |\\n\\t (aBlock value: (array at: index)) ifFalse: [\\n\\t\\t\\tarray at: n put: (array at: index).\\n\\t\\t\\tn _ n + 1]].\\n\\tn to: lastIndex do: [:index | array at: index put: nil].\\n\\tlastIndex _ n - 1! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ar 5/22/2000 12:19'!\\nremoveAt: index\\n\\t| removed |\\n\\tremoved _ self at: index.\\n\\tself removeIndex: index + firstIndex - 1.\\n\\t^removed! !\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremoveFirst\\n\\t\\\"Remove the first element of the receiver and answer it. If the receiver is \\n\\tempty, create an error notification.\\\"\\n\\t| firstObject |\\n\\tself emptyCheck.\\n\\tfirstObject _ array at: firstIndex.\\n\\tarray at: firstIndex put: nil.\\n\\tfirstIndex _ firstIndex + 1.\\n\\t^ firstObject! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:37'!\\nremoveFirst: n\\n\\t\\\"Remove first n object into an array\\\"\\n\\n\\t| list |\\n\\tlist _ Array new: n.\\n\\t1 to: n do: [:i |\\n\\t\\tlist at: i put: self removeFirst].\\n\\t^ list! !\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremoveLast\\n\\t\\\"Remove the last element of the receiver and answer it. If the receiver is \\n\\tempty, create an error notification.\\\"\\n\\t| lastObject |\\n\\tself emptyCheck.\\n\\tlastObject _ array at: lastIndex.\\n\\tarray at: lastIndex put: nil.\\n\\tlastIndex _ lastIndex - 1.\\n\\t^ lastObject! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:36'!\\nremoveLast: n\\n\\t\\\"Remove last n object into an array with last in last position\\\"\\n\\n\\t| list |\\n\\tlist _ Array new: n.\\n\\tn to: 1 by: -1 do: [:i |\\n\\t\\tlist at: i put: self removeLast].\\n\\t^ list! !\\n\\n\\n!OrderedCollection methodsFor: 'testing' stamp: 'bf 8/20/1999 15:08'!\\nhasContentsInExplorer\\n\\n\\t^self isEmpty not! !\\n\\n\\n!OrderedCollection methodsFor: '*Tools-Inspector' stamp: 'ar 9/27/2005 18:33'!\\ninspectorClass \\n\\t\\\"Answer the class of the inspector to be used on the receiver. Called by inspect; \\n\\tuse basicInspect to get a normal (less useful) type of inspector.\\\"\\n\\n\\t^OrderedCollectionInspector! !\\n\\n\\n!OrderedCollection methodsFor: 'private'!\\ncollector \\\"Private\\\"\\n\\t^ array! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nerrorConditionNotSatisfied\\n\\n\\tself error: 'no element satisfies condition'! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nerrorNoSuchElement\\n\\n\\tself error: 'attempt to index non-existent element in an ordered collection'! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:26'!\\nfind: oldObject\\n \\\" This method answers an index in the range firstIndex .. lastIndex, which is meant for internal use only.\\n Never use this method in your code, the methods for public use are:\\n #indexOf:\\n #indexOf:ifAbsent: \\\"\\n\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue:\\n\\t\\t\\t[(array at: index) = oldObject ifTrue: [^ index].\\n\\t\\t\\tindex _ index + 1].\\n\\tself errorNotFound: oldObject! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:29'!\\ninsert: anObject before: spot\\n\\n \\\" spot is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection. \\n Never use this method in your code, it is meant for private use by OrderedCollection only.\\n The methods for use are:\\n #add:before: to insert an object before another object\\n #add:beforeIndex: to insert an object before a given position. \\\"\\n\\t| \\\"index\\\" delta spotIndex|\\n\\tspotIndex _ spot.\\n\\tdelta _ spotIndex - firstIndex.\\n\\tfirstIndex = 1\\n\\t\\tifTrue: \\n\\t\\t\\t[self makeRoomAtFirst.\\n\\t\\t\\tspotIndex _ firstIndex + delta].\\n\\tfirstIndex _ firstIndex - 1.\\n\\tarray\\n\\t\\treplaceFrom: firstIndex\\n\\t\\tto: spotIndex - 2\\n\\t\\twith: array\\n\\t\\tstartingAt: firstIndex + 1.\\n\\tarray at: spotIndex - 1 put: anObject.\\n\\\"\\tindex _ firstIndex _ firstIndex - 1.\\n\\t[index < (spotIndex - 1)]\\n\\t\\twhileTrue: \\n\\t\\t\\t[array at: index put: (array at: index + 1).\\n\\t\\t\\tindex _ index + 1].\\n\\tarray at: index put: anObject.\\\"\\n\\t^ anObject! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nmakeRoomAtFirst\\n\\t| delta index |\\n\\tdelta _ array size - self size.\\n\\tdelta = 0 ifTrue: \\n\\t\\t\\t[self grow.\\n\\t\\t\\tdelta _ array size - self size].\\n\\tlastIndex = array size ifTrue: [^ self]. \\\"just in case we got lucky\\\"\\n\\tindex _ array size.\\n\\t[index > delta]\\n\\t\\twhileTrue: \\n\\t\\t\\t[array at: index put: (array at: index - delta + firstIndex - 1).\\n\\t\\t\\tarray at: index - delta + firstIndex - 1 put: nil.\\n\\t\\t\\tindex _ index - 1].\\n\\tfirstIndex _ delta + 1.\\n\\tlastIndex _ array size! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nmakeRoomAtLast\\n\\t| newLast delta |\\n\\tnewLast _ self size.\\n\\tarray size - self size = 0 ifTrue: [self grow].\\n\\t(delta _ firstIndex - 1) = 0 ifTrue: [^ self].\\n\\t\\\"we might be here under false premises or grow did the job for us\\\"\\n\\t1 to: newLast do:\\n\\t\\t[:index |\\n\\t\\tarray at: index put: (array at: index + delta).\\n\\t\\tarray at: index + delta put: nil].\\n\\tfirstIndex _ 1.\\n\\tlastIndex _ newLast! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:28'!\\nremoveIndex: removedIndex\\n \\\" removedIndex is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection.\\n Never use this method in your code, it is meant for private use by OrderedCollection only.\\n The method for public use is:\\n #removeAt: \\\"\\n\\n\\tarray \\n\\t\\treplaceFrom: removedIndex \\n\\t\\tto: lastIndex - 1 \\n\\t\\twith: array \\n\\t\\tstartingAt: removedIndex+1.\\n\\tarray at: lastIndex put: nil.\\n\\tlastIndex _ lastIndex - 1.! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'!\\nreset\\n\\tfirstIndex _ array size // 3 max: 1.\\n\\tlastIndex _ firstIndex - 1! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'ar 4/16/1999 07:59'!\\nresetTo: index\\n\\tfirstIndex _ index.\\n\\tlastIndex _ firstIndex - 1! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'!\\nsetCollection: anArray\\n\\tarray _ anArray.\\n\\tself reset! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'apb 10/15/2000 18:10'!\\nsetContents: anArray\\n\\tarray _ anArray.\\n\\tfirstIndex _ 1.\\n\\tlastIndex _ array size.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOrderedCollection class\\n\\tinstanceVariableNames: ''!\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:41'!\\nnew\\n\\t^ self new: 10! !\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'md 7/5/2005 15:16'!\\nnew: anInteger \\n\\t^ super basicNew setCollection: (Array new: anInteger)! !\\n\\n!OrderedCollection class methodsFor: 'instance creation'!\\nnewFrom: aCollection \\n\\t\\\"Answer an instance of me containing the same elements as aCollection.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self new: aCollection size.\\n\\tnewCollection addAll: aCollection.\\n\\t^newCollection\\n\\n\\\"\\tOrderedCollection newFrom: {1. 2. 3}\\n\\t{1. 2. 3} as: OrderedCollection\\n\\t{4. 2. 7} as: SortedCollection\\n\\\"! !\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'apb 10/15/2000 22:02'!\\nofSize: n\\n\\t\\\"Create a new collection of size n with nil as its elements.\\n\\tThis method exists because OrderedCollection new: n creates an\\n\\tempty collection, not one of size n.\\\"\\n\\t| collection |\\n\\tcollection _ self new: n.\\n\\tcollection setContents: (collection collector).\\n\\t^ collection\\n! !\\nInspector subclass: #OrderedCollectionInspector\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Inspector'!\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'dew 9/19/2001 03:27'!\\nfieldList\\n\\tobject ifNil: [ ^ OrderedCollection new].\\n\\t^ self baseFieldList ,\\n\\t\\t(object size <= (self i1 + self i2)\\n\\t\\t\\tifTrue: [(1 to: object size)\\n\\t\\t\\t\\t\\t\\tcollect: [:i | i printString]]\\n\\t\\t\\tifFalse: [(1 to: self i1) , (object size-(self i2-1) to: object size)\\n\\t\\t\\t\\t\\t\\tcollect: [:i | i printString]])\\n\\\"\\nOrderedCollection new inspect\\n(OrderedCollection newFrom: #(3 5 7 123)) inspect\\n(OrderedCollection newFrom: (1 to: 1000)) inspect\\n\\\"! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:38'!\\nreplaceSelectionValue: anObject \\n\\t\\\"The receiver has a list of variables of its inspected object. One of these \\n\\tis selected. The value of the selected variable is set to the value, anObject.\\\"\\n\\n\\t(selectionIndex - 2) <= object class instSize\\n\\t\\tifTrue: [^ super replaceSelectionValue: anObject].\\n\\tobject at: self selectedObjectIndex put: anObject! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:27'!\\nselectedObjectIndex\\n\\t\\\"Answer the index of the inspectee's collection that the current selection refers to.\\\"\\n\\n\\t| basicIndex |\\n\\tbasicIndex := selectionIndex - 2 - object class instSize.\\n\\t^ (object size <= (self i1 + self i2) or: [basicIndex <= self i1])\\n\\t\\tifTrue: [basicIndex]\\n\\t\\tifFalse: [object size - (self i1 + self i2) + basicIndex]! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:39'!\\nselection\\n\\t\\\"The receiver has a list of variables of its inspected object.\\n\\tOne of these is selected. Answer the value of the selected variable.\\\"\\n\\n\\t(selectionIndex - 2) <= object class instSize\\n\\t\\tifTrue: [^ super selection].\\n\\t^ object at: self selectedObjectIndex! !\\nClassTestCase subclass: #OrderedCollectionTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Sequenceable'!\\n!OrderedCollectionTest commentStamp: 'BG 1/10/2004 22:07' prior: 0!\\nThese test cases demonstrate addition of items into an OrderedCollection as well as item removal.\\n\\nSome of the assertions are quite complicated and use a lot of collection protocol. Such methods do not test one single method, but protocol in general.!\\n\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 19:00'!\\ntestAdd\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88.\\n\\tself assert: (l = #(1 2 3 4 88) asOrderedCollection).\\n\\tl add: 99.\\n\\tself assert: (l = #(1 2 3 4 88 99) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:52'!\\ntestAddAfter\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 after: 1.\\n\\tself assert: (l = #(1 88 2 3 4) asOrderedCollection).\\n\\tl add: 99 after: 2.\\n\\tself assert: (l = #(1 88 2 99 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:56'!\\ntestAddAfterIndex\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 afterIndex: 1.\\n\\tself assert: (l = #(1 88 2 3 4) asOrderedCollection).\\n\\tl add: 99 afterIndex: 2.\\n\\tself assert: (l = #(1 88 99 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAll\\n\\t\\\"Allows one to add each element of an orderedCollection at the end of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAll\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAll: c2.\\n\\tself assert: c1 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllFirst\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAllFirst\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc2 addAllFirst: c1.\\n\\tself assert: c2 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllFirstUnlessAlreadyPresent\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of\\n\\tanother orderedCollection preserving the order but no duplicate element\\\"\\n\\t\\\"self run:#testAddAllFirstUnlessAlreadyPresent\\\" \\n\\t\\n\\t| c1 c2 c3 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc3 := #(0 1 ) asOrderedCollection.\\n\\tc2 addAllFirstUnlessAlreadyPresent: c1.\\n\\tself assert: c2 = #(1 2 3 4 5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAllFirstUnlessAlreadyPresent: c3.\\n\\tself deny: c1 = #(0 1 1 2 3 4 ) asOrderedCollection.\\n\\tself assert: c1 = #(0 1 2 3 4 ) asOrderedCollection.\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllLast\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAllLast\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAllLast: c2.\\n\\tself assert: c1 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:57'!\\ntestAddBefore\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 before: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 before: 2.\\n\\tself assert: (l = #(88 1 99 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 13:42'!\\ntestAddBeforeAndRemove\\n\\n\\t| l initialCollection |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tinitialCollection := l shallowCopy.\\n\\tl add: 88 before: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 before: 2.\\n\\tself assert: (l = #(88 1 99 2 3 4) asOrderedCollection). \\n\\tl remove: 99.\\n\\tl remove: 88.\\n\\tself assert: l = initialCollection.\\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:57'!\\ntestAddBeforeIndex\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 beforeIndex: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 beforeIndex: 2.\\n\\tself assert: (l = #(88 99 1 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 13:43'!\\ntestAddDuplicateItem1\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection add: 'John' before: 'John'.\\n\\tself\\n\\t\\tassert: ((collection asBag occurrencesOf: 'John')\\n\\t\\t\\t\\t\\t= 2\\n\\t\\t\\t\\tand: [(collection at: (collection indexOf: 'John')\\n\\t\\t\\t\\t\\t\\t\\t+ 1)\\n\\t\\t\\t\\t\\t\\t= (collection\\n\\t\\t\\t\\t\\t\\t\\t\\tat: (collection indexOf: 'John'))])! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:58'!\\ntestAddFirst\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl addFirst: 88.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl addFirst: 99.\\n\\tself assert: (l = #(99 88 1 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 6/5/2005 09:21'!\\ntestAddItem1\\n\\n | collection size |\\n collection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n size := collection size.\\n collection add: 'James' before: 'Jim'.\\n collection add: 'Margaret' before: 'Andrew'.\\n self assert: size + 2 = collection size.\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 19:07'!\\ntestAddItem2\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection add: 'James' before: 'Jim'.\\n\\tcollection add: 'Margaret' before: 'Andrew'.\\n\\tself assert: (collection indexOf: 'James')\\n\\t\\t\\t+ 1\\n\\t\\t\\t= (collection indexOf: 'Jim').\\n\\tself assert: (collection indexOf: 'Margaret')\\n\\t\\t\\t+ 1\\n\\t\\t\\t= (collection indexOf: 'Andrew')! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:59'!\\ntestAddLast\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl addLast: 88.\\n\\tself assert: (l = #(1 2 3 4 88) asOrderedCollection).\\n\\tl addLast: 99.\\n\\tself assert: (l = #(1 2 3 4 88 99) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:37'!\\ntestAtIfAbsentPut\\n\\t\\\"Allows one to add an element at an index if no element exist at this index\\\"\\n\\t\\\"self run:#testAtIfAbsentPut\\\" \\n\\t\\n\\t| c |\\n\\tc := #(1 2 3 4 ) asOrderedCollection.\\n\\tself\\n\\t\\tshouldnt: [c at: 2 ifAbsentPut: [5]]\\n\\t\\traise: Error.\\n\\tself assert: c = #(1 2 3 4 ) asOrderedCollection.\\n\\tc at: 5 ifAbsentPut: [5].\\n\\tself assert: c = #(1 2 3 4 5 ) asOrderedCollection.\\n\\tc at: 7 ifAbsentPut: [7].\\n\\tself assert: c = #(1 2 3 4 5 nil 7 ) asOrderedCollection! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'zz 12/7/2005 18:50'!\\ntestAt\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tself assert: (collection at:1) = 'Jim'.\\n\\tself assert: (collection at:2) = 'Mary'! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:38'!\\ntestAtPut\\n\\t\\\"Allows one to replace an element but not at an off range index\\\"\\n\\t\\\"self run:#testAtPut\\\"\\n\\t| c |\\n\\tc := #(1 2 3 4 ) asOrderedCollection.\\n\\tc at: 2 put: 5.\\n\\tself assert: c = #(1 5 3 4 ) asOrderedCollection.\\n\\tself\\n\\t\\tshould: [c at: 5 put: 8]\\n\\t\\traise: Error.\\n\\tself deny: c = #(1 5 3 4 8 ) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:39'!\\ntestCapacity\\n\\t\\\"Allows one to check the current capacity of an Ordered collection\\\"\\n\\t\\\"self run:#testCapacity\\\"\\n\\t\\n\\t| c1 c2 c3 |\\n\\tc1 := #(1 2 ) asOrderedCollection.\\n\\tself assert: (c1 capacity = 2).\\n\\tc2 := OrderedCollection new: 10.\\n\\tc2 add: 3.\\n\\tself assert: (c2 capacity = 10).\\t\\n\\tc3 := OrderedCollection new.\\n\\tself deny: (c3 capacity = 0).\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:38'!\\ntestSize\\n\\t\\\"Allows one to check the size of an Ordered collection\\\"\\n\\t\\\"self run:#testSize\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 ) asOrderedCollection.\\n\\tself assert: (c1 size = 2).\\n\\t\\n\\tc2 := OrderedCollection new.\\n\\tself assert: (c2 size = 0)\\n\\t! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'sd 3/21/2006 22:41'!\\ntestCollect\\n\\t\\\"Allows one to collect some element of a collection into another collection\\\"\\n\\t\\\"self run: #testCollect\\\"\\n\\t \\n\\t| c1 c2 res |\\n\\tc1 := #(-1 2 -3 4) asOrderedCollection.\\n\\tc2 := #(1 2 3 4) asOrderedCollection.\\n\\tres := c1 collect: [:each | each abs].\\n\\tself assert: (c2 = res).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'cm 3/8/2006 09:09'!\\ntestCollectFromTo\\n\\t\\\"Allows one to collect some element of a collection into another collection between a first index and an end index for the collect\\\"\\n\\t\\\"self run: #testCollectFromTo\\\"\\n\\t\\n\\t| c1 res |\\n\\tc1 := #(-1 2 -3 4 -5 6 -7 8) asOrderedCollection.\\n\\tres := c1 collect: [:each | each abs] from: 1 to: 3.\\n\\tself assert: (res = #(1 2 3) asOrderedCollection).\\n\\tself should: [c1 collect: [:each | each abs] from: 10 to: 13] raise: Error.\\n\\tself should: [c1 collect: [:each | each abs] from: 5 to: 2] raise: Error.! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'zz 12/7/2005 19:06'!\\ntestIndexOf\\n\\t| collection indices |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tindices := collection\\n\\t\\t\\t\\tcollect: [:item | collection indexOf: item].\\n\\tself assert: (1 to: 4) asOrderedCollection = indices! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'sd 6/5/2005 09:21'!\\ntestIndexOfWithDuplicates\\n\\n | collection indices bagOfIndices |\\n collection := #('Jim' 'Mary' 'John' 'Andrew' 'Mary' 'John' 'Jim' 'Micheal') asOrderedCollection.\\n indices := collection collect: [:item | collection indexOf: item].\\n self assert: indices asSet size = collection asSet size.\\n bagOfIndices := indices asBag.\\n self assert: (indices asSet \\n allSatisfy: [:index | (bagOfIndices occurrencesOf: index)\\n\\t = (collection occurrencesOf: (collection at: index))]).\\n\\n \\\" indexOf: returns the index of the first occurrence of an item.\\n For an item with n occurrences, the index of its first occurrence\\n is found n times. \\\"! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'cm 3/8/2006 10:02'!\\ntestWithCollect\\n\\t\\\"Allows one to collect some element of two collections into another collection with element corresponding to the condition in the blocks\\\"\\n\\t\\\"self run: #testWithCollect\\\"\\n\\t\\n\\t| c1 c2 res |\\n\\tc1 := #(-1 2 -3 4 -5 6 -7 8) asOrderedCollection.\\n\\tc2 := #(-9 10 -11 12 -13 14 -15 16) asOrderedCollection.\\n\\tres := c1 with: c2 collect: [:each1 :each2 | each1 < each2\\n\\t\\tifTrue: [each1]\\n\\t\\tifFalse: [each2]].\\n\\tself assert: (res = #(-9 2 -11 4 -13 6 -15 8) asOrderedCollection).\\n\\t! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:40'!\\ntestCopyEmpty\\n\\t\\\"Allows one to create a copy of the receiver that contains no elements\\\"\\n\\t\\\"self run:#testCopyEmpty\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := c1 copyEmpty.\\n\\tself assert: (c2 size = 0).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyFromTo\\n\\t\\\"Allows one to create a copy of the receiver that contains elements from position start to end\\\"\\n\\t\\\"self run: #testCopyFromTo\\\"\\n\\t\\n\\t| c1 c2 c3 | \\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := (c1 copyFrom: 1 to: 2).\\n\\tself assert: c2 = #(1 2) asOrderedCollection.\\n\\tself should: [c1 copyFrom: 10 to: 20] raise: Error.\\n\\t\\n\\tc3 := c1 copyFrom: 4 to: 2.\\n\\tself assert: c3 isEmpty.\\n\\t\\n\\tself should: [c1 copyFrom: 4 to: 5 ] raise: Error.\\n\\t\\n\\t\\n\\t\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyReplaceFromToWith\\n\\t\\\"Allows one to create a copy from the receiver which elements between start and end of the \\treceiver being replace by \\telement of the collection after with:\\\"\\n\\t\\\"self run:#testCopyReplaceFromToWith\\\"\\n\\n\\t| c1 c2 c3 c4 |\\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9) asOrderedCollection.\\n\\tc3 := (c2 copyReplaceFrom: 1 to: 2 with: c1).\\n\\tself assert: c3 = #(1 2 3 4 7 8 9) asOrderedCollection.\\n\\tself should: [c2 copyReplaceFrom: 3 to: 1 with: c1] raise: Error.\\n\\t\\n\\tc4 := (c2 copyReplaceFrom: 10 to: 25 with: c1).\\n\\tself assert: c4 = #(5 6 7 8 9 1 2 3 4) asOrderedCollection.\\n\\t\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyWith\\n\\t\\\"Allows one to create a copy of the receiver that contains the new element at the end\\\"\\n\\t\\\"self run: #testCopyWith\\\"\\n\\t\\n\\t| c1 | \\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc1 := c1 copyWith: 6.\\n\\tself assert: c1 = #(1 2 3 4 6) asOrderedCollection.\\n\\t\\n\\t\\n\\n\\t\\n\\t\\n\\t\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'zz 12/7/2005 13:47'!\\ntestReversed\\n\\t| collection1 collection2 |\\n\\tcollection1 := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection2 := collection1 reversed.\\n\\tself assert: collection2 first = 'Andrew'.\\n\\tself assert: collection2 last = 'Jim'! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'zz 12/7/2005 19:05'!\\ntestRemoveAllSuchThat\\n\\t| collection |\\n\\tcollection := (1 to: 10) asOrderedCollection.\\n\\tcollection\\n\\t\\tremoveAllSuchThat: [:e | e even].\\n\\tself assert: collection = (1 to: 10 by: 2) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveAt\\n\\t\\\"Allows one to remove an element from a collection at an index\\\"\\n\\t\\\"self run:#testRemoveAt\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeAt: 2.\\n\\tself assert: (c1 = #(2 4 6) asOrderedCollection).\\n\\tself should: [c1 removeAt: 10] raise: Error.\\n\\tself should: [c1 removeAt: -1] raise: Error.\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveFirst\\n\\t\\\"Allows one to remove n element of a collection at the first\\\"\\n\\t\\\"self run:#testRemoveFirst\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeFirst: 1.\\n\\tself assert: (c1 = #(3 4 6) asOrderedCollection).\\n\\tc1 removeFirst: 2.\\n\\tself assert: (c1 = #(6) asOrderedCollection).\\n\\tself should: [c1 removeFirst: 10] raise: Error.\\n\\t\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveIfAbsent\\n\\t\\\"Allows one to remove an element from a collection and to copy it in another collection.\\\"\\n\\t\\\"If the element isn't in the first collection, the second collection copy the element after ifAbsent\\\"\\n\\t\\\"self run:#testRemoveIfAbsent\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := OrderedCollection new.\\n\\t\\n\\tc2 add: (c1 remove: 2 ifAbsent: [6]).\\n\\tself assert: (c1 = #(1 3 4) asOrderedCollection).\\n\\tself assert: (c2 = #(2) asOrderedCollection).\\n\\t\\n\\tc2 add: (c1 remove: 18 ifAbsent: [6]).\\n\\tself assert: (c1 = #(1 3 4) asOrderedCollection).\\n\\tself assert: (c2 = #(2 6) asOrderedCollection).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveLast\\n\\t\\\"Allows one to remove n element of a collection at the end\\\"\\n\\t\\\"self run:#testRemoveLast\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeLast: 1.\\n\\tself assert: (c1 = #(2 3 4) asOrderedCollection).\\n\\tc1 removeLast: 2.\\n\\tself assert: (c1 = #(2) asOrderedCollection).\\n\\tself should: [c1 removeLast: 10] raise: Error.! !\\nFillStyle subclass: #OrientedFillStyle\\n\\tinstanceVariableNames: 'origin direction normal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Balloon-Fills'!\\n!OrientedFillStyle commentStamp: '<historical>' prior: 0!\\nOrientedFill is an abstract superclass for fills which can be aligned appropriately.\\n\\nInstance variables:\\n\\torigin\\t<Point>\\tThe point at which to align the fill.\\n\\tdirection <Point>\\tThe direction in which the fill is defined\\n\\tnormal\\t<Point>\\tTypically, just the direction rotated by 90 degrees.!\\n\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 8/25/2001 17:03'!\\ndirection\\n\\t^direction ifNil:[direction := normal y @ normal x negated]! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:37'!\\ndirection: aPoint\\n\\tdirection := aPoint! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/14/1998 23:31'!\\nnormal\\n\\t^normal ifNil:[normal := direction y negated @ direction x]! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:37'!\\nnormal: aPoint\\n\\tnormal := aPoint! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:38'!\\norigin\\n\\t^origin! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:38'!\\norigin: aPoint\\n\\torigin := aPoint.! !\\n\\n\\n!OrientedFillStyle methodsFor: 'testing' stamp: 'ar 6/18/1999 07:57'!\\nisOrientedFill\\n\\t\\\"Return true if the receiver keeps an orientation (e.g., origin, direction, and normal)\\\"\\n\\t^true! !\\n\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'dgd 10/17/2003 22:35'!\\naddFillStyleMenuItems: aMenu hand: aHand from: aMorph\\n\\t\\\"Add the items for changing the current fill style of the receiver\\\"\\n\\taMenu add: 'change origin' translated target: self selector: #changeOriginIn:event: argument: aMorph.\\n\\taMenu add: 'change orientation' translated target: self selector: #changeOrientationIn:event: argument: aMorph.! !\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'ar 6/18/1999 07:41'!\\nchangeOrientationIn: aMorph event: evt\\n\\t\\\"Interactively change the origin of the receiver\\\"\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:pt|\\n\\t\\tself direction: pt - self origin.\\n\\t\\tself normal: nil.\\n\\t\\taMorph changed].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.! !\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'ar 6/18/1999 07:28'!\\nchangeOriginIn: aMorph event: evt\\n\\t\\\"Interactively change the origin of the receiver\\\"\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:pt|\\n\\t\\tself origin: pt.\\n\\t\\taMorph changed].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.! !\\nNotification subclass: #OutOfScopeNotification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n\\n!OutOfScopeNotification methodsFor: 'as yet unclassified' stamp: 'RAA 2/5/2001 10:41'!\\ndefaultAction\\n\\n\\tself resume: false! !\\nPBPreferenceView subclass: #PBBooleanPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBBooleanPreferenceView commentStamp: '<historical>' prior: 0!\\nI am responsible for building the visual representation of a preference that accepts true and false values. This view is aimed to be used inside a PreferenceBrowser panel.!\\n\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:23'!\\nenabledButton\\n\\t| aButton aLabel |\\n\\taButton := UpdatingThreePhaseButtonMorph checkBox\\n\\t\\ttarget: self preference;\\n\\t\\tactionSelector: #togglePreferenceValue;\\n\\t\\tgetSelector: #preferenceValue;\\n\\t\\tyourself.\\n\\taLabel := (StringMorph contents: 'enabled' translated\\n\\t\\t\\t\\tfont: (StrikeFont familyName: TextStyle defaultFont familyName\\n\\t\\t\\t\\t\\t\\t\\tsize: TextStyle defaultFont pointSize - 1)).\\n\\t^self horizontalPanel\\n\\t\\taddMorphBack: aButton;\\n\\t\\taddMorphBack: aLabel;\\n\\t\\tyourself.! !\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:27'!\\nlocalToProjectButton\\n\\t| aButton aLabel |\\n\\taButton := UpdatingThreePhaseButtonMorph checkBox\\n\\t\\ttarget: self preference;\\n\\t\\tactionSelector: #toggleProjectLocalness;\\n\\t\\tgetSelector: #localToProject;\\n\\t\\tyourself.\\n\\taLabel := (StringMorph contents: 'local' translated\\n\\t\\t\\t\\tfont: (StrikeFont familyName: TextStyle defaultFont familyName\\n\\t\\t\\t\\t\\t\\t\\tsize: TextStyle defaultFont pointSize - 1)).\\t\\t\\n\\t^self horizontalPanel\\n\\t\\taddMorphBack: aButton;\\n\\t\\taddMorphBack: aLabel;\\n\\t\\tyourself.! !\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:25'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferencesPanel\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 7;\\n\\t\\tcolor: aColor;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self horizontalFiller; \\n\\t\\taddMorphBack: self enabledButton;\\n\\t\\taddMorphBack: self localToProjectButton;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBBooleanPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBBooleanPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:47'!\\ninitialize\\n\\tPreferenceViewRegistry ofBooleanPreferences register: self.\\n! !\\n\\n!PBBooleanPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:47'!\\nunload\\n\\tPreferenceViewRegistry ofBooleanPreferences unregister: self.! !\\nPBPreferenceView subclass: #PBColorPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBColorPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/6/2004 21:24'!\\ncolorSwatch\\n\\t^UpdatingRectangleMorph new\\n\\t\\ttarget: self preference;\\n\\t\\tgetSelector: #preferenceValue;\\n\\t\\tputSelector: #preferenceValue:;\\n\\t\\textent: 22@22;\\n\\t\\tsetBalloonText: 'click here to change the color' translated;\\n\\t\\tyourself.! !\\n\\n!PBColorPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/6/2004 21:12'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self horizontalFiller;\\n\\t\\taddMorphBack: self colorSwatch;\\n\\t\\tyourself! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBColorPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/6/2004 20:49'!\\ninitialize\\n\\tPreferenceViewRegistry ofColorPreferences register: self.! !\\n\\n!PBColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/6/2004 20:49'!\\nunload\\n\\tPreferenceViewRegistry ofColorPreferences unregister: self.! !\\nPBPreferenceView subclass: #PBHaloThemePreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBHaloThemePreferenceView commentStamp: '<historical>' prior: 0!\\nI am responsible for building the button for the Halo Theme preference!\\n\\n\\n!PBHaloThemePreferenceView methodsFor: 'initialization' stamp: 'hpt 12/8/2004 18:12'!\\ninitialize\\n\\tself addActionTitled: 'edit custom halos' \\n\\t\\ttarget: Preferences \\n\\t\\tselector: #editCustomHalos \\n\\t\\targuments: {} \\n\\t\\tballoonText: 'Click here to edit the method that defines the custom halos' translated.! !\\n\\n\\n!PBHaloThemePreferenceView methodsFor: 'user interface' stamp: 'hpt 12/8/2004 18:18'!\\nhaloThemeRadioButtons\\n\\t\\\"Answer a column of butons representing the choices of halo theme\\\"\\n\\n\\t| buttonColumn aRow aRadioButton aLabel |\\n\\tbuttonColumn := self verticalPanel.\\n\\t#(\\t(iconicHaloSpecifications iconic iconicHalosInForce\\t'circular halos with icons inside')\\n\\t\\t(classicHaloSpecs\\tclassic\\tclassicHalosInForce\\t\\t'plain circular halos')\\n\\t\\t(simpleFullHaloSpecifications\\t\\tsimple\\tsimpleHalosInForce\\t'fewer, larger halos')\\n\\t\\t(customHaloSpecs\\tcustom\\tcustomHalosInForce\\t\\t'customizable halos')) do:\\n\\n\\t\\t[:quad |\\n\\t\\t\\taRadioButton := UpdatingThreePhaseButtonMorph radioButton\\n\\t\\t\\t\\ttarget: Preferences;\\n\\t\\t\\t\\tsetBalloonText: quad fourth;\\n\\t\\t\\t\\tactionSelector: #installHaloTheme:;\\n\\t\\t\\t\\tgetSelector: quad third;\\n\\t\\t\\t\\targuments: (Array with: quad first);\\n\\t\\t\\t\\tyourself.\\n\\t\\t\\taLabel := (StringMorph contents: quad second asString)\\n\\t\\t\\t\\t\\t\\tsetBalloonText: quad fourth;\\n\\t\\t\\t\\t\\t\\tyourself.\\n\\t\\t\\taRow := self horizontalPanel\\n\\t\\t\\t\\tcellInset: 4;\\n\\t\\t\\t\\taddMorphBack: aRadioButton;\\n\\t\\t\\t\\taddMorphBack: aLabel.\\n\\t\\t\\tbuttonColumn addMorphBack: aRow].\\n\\t^ buttonColumn\\n\\n\\t\\\"(Preferences preferenceAt: #haloTheme) view tearOffButton\\\"! !\\n\\n!PBHaloThemePreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:45'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferencesPanel\\n\\t| innerPanel |\\n\\tinnerPanel := self horizontalPanel\\n\\t\\taddMorphBack: (self blankSpaceOf: 10@0);\\n\\t\\taddMorphBack: self haloThemeRadioButtons;\\n\\t\\tyourself.\\n\\t^self verticalPanel\\n\\t\\tcolor: aColor;\\n\\t\\tlayoutInset: 2;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: innerPanel.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBHaloThemePreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBHaloThemePreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:48'!\\ninitialize\\n\\tPreferenceViewRegistry ofHaloThemePreferences register: self.! !\\n\\n!PBHaloThemePreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:48'!\\nunload\\n\\tPreferenceViewRegistry ofHaloThemePreferences unregister: self.! !\\nPBPreferenceView subclass: #PBNumericPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:23'!\\npreferenceValue\\n\\t^self preference preferenceValue asString! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/10/2004 22:53'!\\npreferenceValue: aTextOrString\\n\\t(aTextOrString notEmpty and: [aTextOrString asString isAllDigits])\\n\\t\\tifFalse: [^false].\\n\\tself preference preferenceValue: aTextOrString asNumber.\\n\\t^true.! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:19'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self textField;\\n\\t\\tyourself.! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:19'!\\ntextField\\n\\t^(PluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #preferenceValue\\n\\t\\taccept: #preferenceValue:)\\n\\t\\t\\thideVScrollBarIndefinitely: true;\\n\\t\\t\\tborderColor: #inset;\\n\\t\\t\\tacceptOnCR: true;\\n\\t\\t\\tcolor: Color gray veryMuchLighter;\\n\\t\\t\\tvResizing: #rigid;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\theight: TextStyle defaultFont height + 6;\\n\\t\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBNumericPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBNumericPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/9/2004 22:21'!\\ninitialize\\n\\tPreferenceViewRegistry ofNumericPreferences register: self.! !\\n\\n!PBNumericPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/9/2004 22:21'!\\nunload\\n\\tPreferenceViewRegistry ofNumericPreferences unregister: self.! !\\nMorph subclass: #PBPreferenceButtonMorph\\n\\tinstanceVariableNames: 'moreButton model preference preferenceMorphicView preferenceView'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBPreferenceButtonMorph methodsFor: 'accessing' stamp: 'hpt 12/8/2004 15:34'!\\nmodel\\n\\t^model! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 18:15'!\\nactionButtons\\n\\t^self preferenceView actions collect: [:aTuple |\\n\\t\\tself basicButton\\n\\t\\t\\t\\tlabel: aTuple first;\\n\\t\\t\\t\\ttarget: aTuple second;\\n\\t\\t\\t\\tactionSelector: aTuple third;\\n\\t\\t\\t\\targuments: aTuple fourth;\\n\\t\\t\\t\\tsetBalloonText: aTuple fifth ]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 8/24/2005 20:33'!\\naddExtraControls\\n\\t| m |\\n\\tm := self horizontalPanel\\n\\t\\tcellInset: 3;\\n\\t\\taddAllMorphs: self actionButtons;\\n\\t\\taddMorphBack: self horizontalFiller;\\n\\t\\taddMorphBack: self moreButton;\\n\\t\\tyourself.\\n\\tself \\n\\t\\taddMorphBack: (self blankSpaceOf: 2@2);\\n\\t\\taddMorphBack: self preferenceHelpTextMorph;\\n\\t\\tfullBounds; \\\"to force a layout compute needed by the textMorphs's autoFit\\\"\\n\\t\\taddMorphBack: m\\n! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 17:16'!\\nadvancedOptionsSelected\\n\\tself preferenceView offerPreferenceNameMenu: self model! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 18:17'!\\nmoreButton\\n\\t^moreButton ifNil: \\n\\t\\t[moreButton := self basicButton \\n\\t\\t\\t\\t\\t\\tlabel: 'more' translated; \\n\\t\\t\\t\\t\\t\\tsetBalloonText: \\n\\t\\t\\t\\t\\t\\t\\t'Click here for advanced options'translated;\\n\\t\\t\\t\\t\\t\\tactionSelector: #advancedOptionsSelected]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npreferenceHelpTextMorph\\n\\t| text tm |\\n\\ttext := self preferenceHelpText.\\n\\ttm := TextMorph new\\n\\t\\tcontents: text;\\n\\t\\twrapOnOff;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tlock: true;\\n\\t\\tvisible: text notEmpty;\\n\\t\\tyourself. \\\"we don't want an empty textmorph showing\\\"\\n\\ttm isAutoFit\\n\\t\\tifFalse: [tm autoFitOnOff].\\n\\t^tm.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 16:40'!\\nremoveExtraControls\\n\\tself submorphs copyWithoutFirst do: [:ea | ea delete]! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'highlighting' stamp: 'hpt 12/8/2004 15:55'!\\nhighlightOff\\n\\tself beTransparent.\\n\\tself label color: Color black.\\n\\tself removeExtraControls.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'highlighting' stamp: 'hpt 12/8/2004 17:25'!\\nhighlightOn\\n\\tself color: (Color gray alpha: 0.1).\\n\\tself label color: Color red.\\n\\tself addExtraControls.! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'initialization' stamp: 'hpt 12/8/2004 15:38'!\\ninitializeLayout\\n\\tself layoutPolicy: TableLayout new;\\n\\t\\tbeTransparent;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 0;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap.\\t\\t! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'initialization' stamp: 'hpt 12/8/2004 15:38'!\\ninitializeWithPreference: aPreference model: aModel\\n\\tpreference := aPreference.\\n\\tmodel := aModel.\\n\\tself initializeLayout.\\n\\tself addMorphBack: self preferenceMorphicView.\\n\\tself highlightOff.! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:42'!\\nlabel\\n\\t^self preferenceMorphicView firstSubmorph! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:13'!\\npreference\\n\\t^preference! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:56'!\\npreferenceHelp\\n\\t| help name |\\n\\thelp := self preference helpString withBlanksTrimmed.\\n\\tname := self preference name.\\n\\t(self caseInsensitiveBeginsWith: name in: help)\\n\\t\\tifTrue: [help := help allButFirst: name size].\\n\\t(help notEmpty and: [help first = $:])\\n\\t\\tifTrue: [help := help allButFirst].\\n\\t^help withBlanksTrimmed.\\n! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:25'!\\npreferenceHelpText\\n\\t^self preferenceHelp asText\\n\\t\\taddAttribute: TextEmphasis italic;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:48'!\\npreferenceMorphicView\\n\\t^preferenceMorphicView\\n\\t\\tifNil: \\n\\t\\t\\t[preferenceMorphicView := self preferenceView\\n\\t\\t\\t\\trepresentativeButtonWithColor: Color transparent inPanel: self model.\\n\\t\\t\\tpreferenceMorphicView hResizing: #spaceFill.\\n\\t\\t\\t^preferenceMorphicView]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npreferenceView\\n\\t^preferenceView\\n\\t\\tifNil: [preferenceView := self preference viewForPanel: self model.]! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 17:06'!\\nbasicButton\\n\\t| button |\\n\\tbutton := SimpleButtonMorph new.\\n\\tbutton\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: self paneColor;\\n\\t\\ton: #mouseEnter send: #value to: [button borderWidth: 2];\\n\\t\\ton: #mouseLeave send: #value to: [button borderWidth: 1];\\n\\t\\tvResizing: #rigid;\\n\\t\\theight: (TextStyle defaultFont height + 4);\\n\\t\\tuseSquareCorners;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: self paneColor muchLighter;\\n\\t\\ttarget: self.\\n\\t^button! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:59'!\\nbasicPanel\\n\\t^BorderedMorph new\\n\\t\\tbeTransparent;\\n\\t\\textent: 0@0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 0;\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #center;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tyourself! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:29'!\\nblankSpaceOf: aPoint\\n\\t^Morph new \\n\\t\\tbeTransparent;\\n\\t\\textent: aPoint; \\n\\t\\tyourself! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:43'!\\ncaseInsensitiveBeginsWith: prefix in: string\\n\\t^(string findString: prefix startingAt: 1 caseSensitive: false) = 1! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 16:42'!\\nhorizontalFiller\\n\\t^self horizontalPanel\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 16:42'!\\nhorizontalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #center;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npaneColor\\n\\t| browser |\\n\\tbrowser := (self ownerChain \\n\\t\\tdetect: [:ea | ea isKindOf: PreferenceBrowserMorph] \\n\\t\\tifNone: [^Color black]) .\\n\\t^browser paneColor! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:27'!\\nverticalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBPreferenceButtonMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PBPreferenceButtonMorph class methodsFor: 'instance creation' stamp: 'hpt 12/8/2004 15:20'!\\npreference: aPreference\\n\\t^self preference: aPreference model: nil! !\\n\\n!PBPreferenceButtonMorph class methodsFor: 'instance creation' stamp: 'hpt 12/8/2004 15:19'!\\npreference: aPreference model: aModel\\n\\t^self new\\n\\t\\tinitializeWithPreference: aPreference model: aModel;\\n\\t\\tyourself.! !\\nPreferenceView subclass: #PBPreferenceView\\n\\tinstanceVariableNames: 'actions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBPreferenceView commentStamp: '<historical>' prior: 0!\\nI am just a refactor of all the common method of the PreferenceBrowser preference views!\\n\\n\\n!PBPreferenceView methodsFor: 'actions' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nactions\\n\\t^actions ifNil: [actions := OrderedCollection new.]! !\\n\\n!PBPreferenceView methodsFor: 'actions' stamp: 'hpt 12/8/2004 18:13'!\\naddActionTitled: aTitle target: aTarget selector: aSelector arguments: aCollection balloonText: aText\\n\\tself actions add: { aTitle. aTarget. aSelector. aCollection. aText }! !\\n\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:42'!\\nbasicPanel\\n\\t^BorderedMorph new\\n\\t\\tbeTransparent;\\n\\t\\textent: 0@0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 2;\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #center;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tyourself! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:15'!\\nblankSpaceOf: aPoint\\n\\t^Morph new \\n\\t\\tbeTransparent;\\n\\t\\textent: aPoint; \\n\\t\\tyourself! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:13'!\\nhorizontalFiller\\n\\t^self horizontalPanel\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:43'!\\nhorizontalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #center;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:48'!\\nofferPreferenceNameMenu: aPreferenceBrowser\\n\\t\\\"the user clicked on a preference name -- put up a menu\\\"\\n\\n\\t| aMenu |\\t\\t\\t\\n\\taMenu := MenuMorph new \\n\\t\\tdefaultTarget: self preference;\\n\\t\\taddTitle: self preference name.\\n\\n\\t(Preferences okayToChangeProjectLocalnessOf: self preference name) ifTrue:\\n\\t\\t[aMenu addUpdating: #isProjectLocalString target: self preference action: #toggleProjectLocalness.\\n\\t\\taMenu balloonTextForLastItem: 'Some preferences are best applied uniformly to all projects, and others are best set by each individual project. If this item is checked, then this preference will be printed in bold and will have a separate value for each project'].\\n\\n\\taMenu add: 'browse senders' translated target: self systemNavigation selector: #browseAllCallsOn: argument: self preference name.\\n\\taMenu balloonTextForLastItem: 'This will open a method-list browser on all methods that the send the preference \\\"', self preference name, '\\\".'. \\n\\taMenu add: 'show category...' target: aPreferenceBrowser selector: #findCategoryFromPreference: argument: self preference name.\\n\\taMenu balloonTextForLastItem: 'Allows you to find out which category, or categories, this preference belongs to.'.\\n\\n\\tSmalltalk isMorphic ifTrue:\\n\\t\\t[aMenu add: 'hand me a button for this preference' target: self selector: #tearOffButton.\\n\\t\\taMenu balloonTextForLastItem: 'Will give you a button that governs this preference, which you may deposit wherever you wish'].\\n\\n\\taMenu add: 'copy this name to clipboard' target: self preference selector: #copyName.\\n\\taMenu balloonTextForLastItem: 'Copy the name of the preference to the text clipboard, so that you can paste into code somewhere'.\\n\\n\\taMenu popUpInWorld! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:43'!\\nverticalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBPreferenceView class methodsFor: 'view registry' stamp: 'hpt 9/26/2004 16:09'!\\nhandlesPanel: aPreferencePanel\\n\\t^aPreferencePanel isKindOf: PreferenceBrowser! !\\nPBPreferenceView subclass: #PBTextPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/10/2004 22:46'!\\npreferenceValue\\n\\t^self preference preferenceValue ifNil: ['']! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:38'!\\npreferenceValue: aTextOrString\\n\\tself preference preferenceValue: aTextOrString asString.\\n\\t^true.! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:41'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self textField;\\n\\t\\tyourself.! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:41'!\\ntextField\\n\\t^(PluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #preferenceValue\\n\\t\\taccept: #preferenceValue:)\\n\\t\\t\\thideVScrollBarIndefinitely: true;\\n\\t\\t\\tborderColor: #inset;\\n\\t\\t\\tacceptOnCR: true;\\n\\t\\t\\tcolor: Color gray veryMuchLighter;\\n\\t\\t\\tvResizing: #rigid;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\theight: TextStyle defaultFont height + 6;\\n\\t\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBTextPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBTextPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 17:01'!\\ninitialize\\n\\tPreferenceViewRegistry ofTextPreferences register: self.! !\\n\\n!PBTextPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 17:01'!\\nunload\\n\\tPreferenceViewRegistry ofTextPreferences unregister: self.! !\\nPBColorPreferenceView subclass: #PBWindowColorPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBWindowColorPreferenceView methodsFor: 'initialization' stamp: 'hpt 12/8/2004 18:38'!\\ninitialize\\n\\tsuper initialize.\\n\\tself addActionTitled: 'Bright' target: Preferences selector: #installBrightWindowColors arguments: {} balloonText: 'Use standard bright colors for all windows' translated.\\n\\tself addActionTitled: 'Pastel' target: Preferences selector: #installPastelWindowColors arguments: {} balloonText: 'Use standard pastel colors for all windows' translated.\\t\\n\\tself addActionTitled: 'White' target: Preferences selector: #installUniformWindowColors arguments: {} balloonText: 'Use white backgrounds for all standard windows' translated.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBWindowColorPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\ninitialize\\n\\tself viewRegistry register: self.! !\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\nunload\\n\\tself viewRegistry unregister: self.! !\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\nviewRegistry\\n\\t^(PreferenceViewRegistry registryOf: #windowColorPreferences)\\n\\t\\tviewOrder: 6;\\n\\t\\tyourself.! !\\nPrimCallControllerAbstract subclass: #PCCByCompilation\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByCompilation commentStamp: 'sr 6/16/2004 09:00' prior: 0!\\nThis class is for switching external prim calls (primitiveExternalCall) on and off.\\n\\nIt is best suited for permanently switching plugin calls off while preserving the possibility to switch them on later. For plugin testing purposes you probably should use PCCByLiterals for temporarily switch on/off them instead.\\n\\nIt works on a source code basis by compilation:\\n\\tDisabling works by putting an enabled prim call into a special comment followed by a recompile to transform it into a disabled one.\\n\\tEnabling works by pulling the disabled prim call out of the special comment followed by a recompile to transform it into an enabled one.\\n\\nAs a consequence, enabling of prims only works with method sources containing the mentioned special comment, which normally has been generated by this tool for disabling the corresponding prim.\\n\\nPlease look into superclass PrimCallControllerAbstract for more info and the user interface.\\n\\nStructure:\\n No instVars here: look into superclass.\\n\\nImplementation note:\\nTo harden it for sunit testing purposes some special accessing of the source code has been necessary: to avoid accessing different processes a sources file at once, followed by generating garbage, the process priority of actions leading to these accesses has been increased (sunit tests run in the background). A better solution would be to introduce a source file locking mechanism.!\\n]style[(107 11 138 13 5 11 62 14 3 9 124 8 245 9 36 9 26 28 26 93 20 384)f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2LPCCByLiterals Comment;,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2,f2FAccuny#12,f3FAccuny#12,f2FAccuny#12,f2,f2LPrimCallControllerAbstract Comment;,f2,FAccuny#15uf2,f2!\\n\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:30'!\\ncomment\\n\\t^ '{prim disabled by ', self className, '} '! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\ndisabledPrimStartString\\n\\t^ '\\\"', self comment, self enabledPrimStartString! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\ndisabledPrimStopChar\\n\\t\\\"end of disabling comment\\\"\\n\\t^ $\\\"! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\nenabledPrimStartString\\n\\t^ '<primitive:'! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\nenabledPrimStopChar\\n\\t^ $>! !\\n\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'sr 6/11/2004 06:33'!\\nextractCallModuleNames: aMethodRef \\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tifTrue: [self extractCallModuleNamesFromLiterals: aMethodRef]\\n\\t\\tifFalse: [| src | \\n\\t\\t\\t\\\"try source\\\"\\n\\t\\t\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t\\t\\t[src := aMethodRef sourceString]\\n\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\tself extractCallNamesFromPrimString: ((self extractDisabledPrimStringFrom: src)\\n\\t\\t\\t\\t\\tifNil: [\\\"no disabled prim string found\\\"\\n\\t\\t\\t\\t\\t\\t^ nil]) first]! !\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'sr 6/14/2004 21:38'!\\nmethodsWithCall\\n\\t\\\"Expensive!! For just querying the system unaffected by an instance of \\n\\tthis class use PCCByLiterals instead.\\\"\\n\\t^ self methodsWithCompiledCall , self methodsWithDisabledCall! !\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'md 8/27/2005 17:17'!\\nmethodsWithDisabledCall\\n\\t\\\"Answer a SortedCollection of all the methods that contain, in source \\n\\tcode, the substring indicating a disabled prim.\\\"\\n\\t\\\"The alternative implementation \\n\\t\\t^ SystemNavigation new allMethodsWithSourceString: self disabledPrimStartString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmatchCase: true \\n\\talso searches in class comments.\\\"\\n\\t| list classCount string |\\n\\tstring := self disabledPrimStartString.\\n\\tlist := Set new.\\n\\t'Searching all method source code...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: Smalltalk classNames size * 2 \\\"classes with their metaclasses\\\"\\n\\t\\tduring: [:bar |\\n\\t\\t\\tclassCount := 0.\\n\\t\\t\\tSystemNavigation default\\n\\t\\t\\t\\tallBehaviorsDo: [:class | \\n\\t\\t\\t\\t\\tbar value: (classCount := classCount + 1).\\n\\t\\t\\t\\t\\tclass\\n\\t\\t\\t\\t\\t\\tselectorsDo: [:sel | \\n\\t\\t\\t\\t\\t\\t\\t| src | \\n\\t\\t\\t\\t\\t\\t\\t\\\"higher priority to avoid source file accessing \\n\\t\\t\\t\\t\\t\\t\\terrors\\\"\\n\\t\\t\\t\\t\\t\\t\\t[src := class sourceCodeAt: sel]\\n\\t\\t\\t\\t\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\t\\t\\t\\t\\t(src\\n\\t\\t\\t\\t\\t\\t\\t\\tfindString: string\\n\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\t\\t\\t\\t\\tcaseSensitive: true) > 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [sel isDoIt ifFalse: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlist add: (MethodReference new setStandardClass: class methodSymbol: sel)]]]]].\\n\\t^ list asSortedCollection! !\\n\\n\\n!PCCByCompilation methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:26'!\\nexistsCallIn: aMethodRef \\n\\t\\\"Here existsCompiledCallIn: (see also comment there) is sufficient to \\n\\tquery for enabled and failed, but not for disabled prim calls: so check \\n\\tfor disabled ones in sources, too.\\\"\\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tor: [self existsDisabledCallIn: aMethodRef]! !\\n\\n!PCCByCompilation methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:07'!\\nexistsDisabledCallIn: aMethodRef \\n\\t| src |\\n\\t^ (self existsCompiledCallIn: aMethodRef) not\\n\\t\\tand: [\\\"higher priority to avoid source file accessing errors\\\"\\n\\t\\t\\t[src := aMethodRef sourceString]\\n\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\tself methodSourceContainsDisabledCall: src]! !\\n\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:26'!\\ndisabled2EnabledPrimMethodString: aSourceString \\n\\t| start stop primString extract |\\n\\textract := self extractDisabledPrimStringFrom: aSourceString.\\n\\tprimString := extract at: 1.\\n\\tstart := extract at: 2.\\n\\tstop := start + primString size - 1.\\n\\t^ aSourceString\\n\\t\\tcopyReplaceFrom: start\\n\\t\\tto: stop\\n\\t\\twith: (self disabled2EnabledPrimString: primString)! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:26'!\\ndisabled2EnabledPrimString: aDisabledPrimString\\n\\t\\\"remove comment quotes and comment after first comment quote\\\"\\n\\t| enabledPrimString |\\n\\tenabledPrimString := aDisabledPrimString copyFrom: self comment size + 2 to: aDisabledPrimString size - 1.\\n\\t^ enabledPrimString! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:28'!\\nenabled2DisabledPrimMethodString: aSourceString \\n\\t| start stop primString extract |\\n\\textract := self extractEnabledPrimStringFrom: aSourceString.\\n\\tprimString := extract at: 1.\\n\\tstart := extract at: 2.\\n\\tstop := start + primString size - 1.\\n\\t^ aSourceString\\n\\t\\tcopyReplaceFrom: start\\n\\t\\tto: stop\\n\\t\\twith: (self enabled2DisabledPrimString: primString)! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:28'!\\nenabled2DisabledPrimString: anEnabledPrimString \\n\\t| disabledPrimString |\\n\\tdisabledPrimString := '\\\"' , self comment , anEnabledPrimString , '\\\"'.\\n\\t^ disabledPrimString! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'stephaneducasse 2/3/2006 22:39'!\\nextractCallNamesFromPrimString: aString\\n\\t\\\"method works for both enabled and disabled prim strings\\\"\\n\\t\\\"<primitive: 'doSomething' module:'ModuleFoo'\\\"\\n\\t| tokens |\\n\\ttokens := aString findTokens: ''''.\\n\\t^ (tokens at: 2) -> (tokens at: 4 ifAbsent: [nil])! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/11/2004 07:10'!\\nextractDisabledPrimStringFrom: aSourceString \\n\\t| startString start stop |\\n\\tstartString := self disabledPrimStartString.\\n\\tstart := aSourceString findString: startString.\\n\\tstart = 0\\n\\t\\tifTrue: [^ nil].\\n\\tstop := aSourceString indexOf: self disabledPrimStopChar startingAt: start + startString size.\\n\\tstop = 0\\n\\t\\tifTrue: [^ nil].\\n\\t^ {aSourceString copyFrom: start to: stop. start}! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:29'!\\nextractEnabledPrimStringFrom: aSourceString \\n\\t| startString start stop |\\n\\tstartString := self enabledPrimStartString.\\n\\tstart := aSourceString findString: startString.\\n\\tstart = 0\\n\\t\\tifTrue: [^ nil].\\n\\tstop := aSourceString indexOf: self enabledPrimStopChar startingAt: start + startString size.\\n\\tstop = 0\\n\\t\\tifTrue: [^ nil].\\n\\t^ {aSourceString copyFrom: start to: stop. start}! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:29'!\\nhigherPriority\\n\\t\\\"this priority seems to be necessary to avoid source file accessing errors\\\"\\n\\t^ Processor userSchedulingPriority + 1! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/11/2004 07:06'!\\nmethodSourceContainsDisabledCall: methodSource \\n\\t^ (methodSource findString: self disabledPrimStartString)\\n\\t\\t~= 0! !\\n\\n\\n!PCCByCompilation methodsFor: 'private user interface' stamp: 'sr 6/14/2004 01:37'!\\nprivateDisableCallIn: aMethodRef \\n\\t\\\"Disables enabled or failed external prim call by recompiling method \\n\\twith prim call commented out, will be called by superclass.\\\"\\n\\t| src newMethodSource |\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[src := aMethodRef sourceString]\\n\\t\\tvalueAt: self higherPriority.\\n\\tnewMethodSource := self enabled2DisabledPrimMethodString: src.\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[aMethodRef actualClass\\n\\t\\tcompile: newMethodSource\\n\\t\\tclassified: (aMethodRef actualClass whichCategoryIncludesSelector: aMethodRef methodSymbol)\\n\\t\\tnotifying: nil]\\n\\t\\tvalueAt: self higherPriority! !\\n\\n!PCCByCompilation methodsFor: 'private user interface' stamp: 'sr 6/14/2004 02:10'!\\nprivateEnableCallIn: aMethodRef \\n\\t\\\"Enables disabled external prim call by recompiling method with prim \\n\\tcall taken from disabling comment, will be called by superclass.\\\"\\n\\t| src newMethodSource |\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[src := aMethodRef sourceString]\\n\\t\\tvalueAt: self higherPriority.\\n\\tnewMethodSource := self disabled2EnabledPrimMethodString: src.\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[aMethodRef actualClass\\n\\t\\tcompile: newMethodSource\\n\\t\\tclassified: (aMethodRef actualClass whichCategoryIncludesSelector: aMethodRef methodSymbol)\\n\\t\\tnotifying: nil]\\n\\t\\tvalueAt: self higherPriority! !\\nPrimCallControllerAbstractTest subclass: #PCCByCompilationTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByCompilationTest commentStamp: 'sr 6/14/2004 22:05' prior: 0!\\nPCCByCompilation tests.\\n\\nTests are in the superclass and inherited from there.!\\n\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/11/2004 05:22'!\\nclassToBeTested\\n\\t^ PCCByCompilation! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:36'!\\ndisabledCallSelectors\\n\\t^ #(#cDisabledRealExternalCall #cDisabledRealExternalCallNaked #cDisabledRealExternalCallOrPrimitiveFailed #cDisabledExternalCallWithoutModule )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:34'!\\nenabledCallSelectors\\n\\t^ #(#cRealExternalCall #cRealExternalCallNaked #cRealExternalCallOrPrimitiveFailed #cExternalCallWithoutModule )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:44'!\\nexampleModuleName\\n\\t^ 'CPCCT'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/15/2004 02:42'!\\nfailModuleName\\n\\t^ 'CFailModule'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/14/2004 00:14'!\\nfailedCallSelector\\n\\t^ #cFailedCall! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:40'!\\nmethodSelectorsToExampleModule\\n\\t^ #(#cExternalCall1 #cExternalCall2 )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameNotWithSingularCallName\\n\\t^ 'CNotOne'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameWithSingularCallName\\n\\t^ 'COne'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 09:52'!\\nnoExternalCallSelector\\n\\t^ #cNoExternalCall! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:28'!\\nrealExternalCallOrPrimitiveFailedSelector\\n\\t^ #cRealExternalCallOrPrimitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:54'!\\nsingularCallName\\n\\t\\\"occurrs exactly once as prim call name in >>cSingularExternalCall\\\"\\n\\t^ 'cSingularExternalCall'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/14/2004 23:33'!\\nsingularCallSelector\\n\\t^ #cSingularExternalCall! !\\n\\n\\n!PCCByCompilationTest methodsFor: 'example module' stamp: 'md 9/6/2005 19:39'!\\ncExternalCall1\\n\\t<primitive: 'prim1' module: 'CPCCT'>\\n! !\\n\\n!PCCByCompilationTest methodsFor: 'example module' stamp: 'md 9/6/2005 19:39'!\\ncExternalCall2\\n\\t\\t<primitive:'prim2'module:'CPCCT'>\\n\\t\\tself primitiveFailed! !\\n\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/11/2004 05:36'!\\ncDisabledExternalCallWithoutModule\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName'>\\\"\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCall\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCallNaked\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCallOrPrimitiveFailed\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"\\n\\tself primitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:48'!\\ncExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'md 9/6/2005 19:39'!\\ncFailedCall\\n\\t<primitive: 'primGetModuleName' module:'CFailModule'>\\n\\t^ 'failed call'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:48'!\\ncNoExternalCall\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\ncRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\ncRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'md 9/6/2005 19:39'!\\ncRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\tself primitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/15/2004 04:35'!\\ncSingularExternalCall\\n\\t<primitive: 'cSingularExternalCall' module:'COne'>\\n\\t^ 'Hello World!!'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCCByCompilationTest class\\n\\tinstanceVariableNames: ''!\\n\\n!PCCByCompilationTest class methodsFor: 'Testing' stamp: 'sr 6/7/2004 12:01'!\\nisAbstract\\n\\t^ false! !\\nPrimCallControllerAbstract subclass: #PCCByLiterals\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByLiterals commentStamp: 'sr 6/16/2004 09:14' prior: 0!\\nThis class is for switching external prim calls (primitiveExternalCall) on and off.\\n\\nIt is best suited for plugin testing purposes with temporarily switching plugin calls off and on. For permanently switching plugin calls off while preserving the possibility to switch them on later, you should use PCCByCompilation instead.\\n\\nIt works by manipulating literals in the CompiledMethods:\\n\\tDisabling works by changing the function index in the first literal of the CompiledMethod to a negative value (-2). This leads to a fast fail (value -2 is used for disabling to make a difference to the standard failed value of -1).\\n\\tEnabling works by changing the function index in the first literal of the CompiledMethod to 0, followed by flushing the method cache. This enforces a fresh lookup.\\n\\nPlease look into superclass PrimCallControllerAbstract for more info and the user interface.\\n\\nStructure:\\n No instVars here: look into superclass.!\\n]style[(136 11 40 11 101 16 10 1 9 2 14 8 26 9 224 8 157 28 26 91)f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2LPCCByCompilation Comment;,f2FAccuny#12,f2,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2,f2LPrimCallControllerAbstract Comment;,f2!\\n\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/11/2004 07:04'!\\nextractCallModuleNames: aMethodRef \\n\\t^ (self existsCallIn: aMethodRef)\\n\\t\\tifTrue: [self extractCallModuleNamesFromLiterals: aMethodRef]! !\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/11/2004 07:05'!\\nmethodsWithCall\\n\\t^ self methodsWithCompiledCall! !\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/14/2004 21:24'!\\nmethodsWithDisabledCall\\n\\t^ self methodsWithCompiledCall\\n\\t\\tselect: [:mRef | (mRef compiledMethod literals first at: 4)\\n\\t\\t\\t\\t= -2]! !\\n\\n\\n!PCCByLiterals methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:04'!\\nexistsCallIn: aMethodRef \\n\\t\\\"Here >>existsCompiledCallIn: (see also comment there) is sufficient to \\n\\tquery for all enabled, failed and disabled prim calls; for the by \\n\\tcompiler version it is not sufficient for disabled ones.\\\"\\n\\t^ self existsCompiledCallIn: aMethodRef! !\\n\\n!PCCByLiterals methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:30'!\\nexistsDisabledCallIn: aMethodRef \\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tand: [(aMethodRef compiledMethod literals first at: 4)\\n\\t\\t\\t\\t= -2]! !\\n\\n\\n!PCCByLiterals methodsFor: 'private user interface' stamp: 'sr 6/14/2004 01:35'!\\nprivateDisableCallIn: aMethodRef \\n\\t\\\"Disables enabled or failed external prim call by filling function ref \\n\\tliteral with special fail value, will be called by superclass.\\\"\\n\\taMethodRef compiledMethod literals first at: 4 put: -2! !\\n\\n!PCCByLiterals methodsFor: 'private user interface' stamp: 'sr 6/14/2004 02:07'!\\nprivateEnableCallIn: aMethodRef\\n\\t\\\"Enables disabled external prim call.\\\"\\n\\tself privateEnableViaLiteralIn: aMethodRef! !\\nPrimCallControllerAbstractTest subclass: #PCCByLiteralsTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByLiteralsTest commentStamp: 'sr 6/14/2004 22:05' prior: 0!\\nPCCByLiterals tests.\\n\\nTests are in the superclass and inherited from there.!\\n\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/11/2004 05:23'!\\nclassToBeTested\\n\\t^ PCCByLiterals! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:37'!\\ndisabledCallSelectors\\n\\t^ #(#lDisabledRealExternalCall #lDisabledRealExternalCallNaked #lDisabledRealExternalCallOrPrimitiveFailed #lDisabledExternalCallWithoutModule )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:34'!\\nenabledCallSelectors\\n\\t^ #(#lRealExternalCall #lRealExternalCallNaked #lRealExternalCallOrPrimitiveFailed #lExternalCallWithoutModule )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:45'!\\nexampleModuleName\\n\\t^ 'LPCCT'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/15/2004 02:42'!\\nfailModuleName\\n\\t^ 'LFailModule'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/14/2004 00:12'!\\nfailedCallSelector\\n\\t^ #lFailedCall! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:41'!\\nmethodSelectorsToExampleModule\\n\\t^ #(#lExternalCall1 #lExternalCall2 )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameNotWithSingularCallName\\n\\t^ 'LNotOne'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameWithSingularCallName\\n\\t^ 'LOne'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:16'!\\nnoExternalCallSelector\\n\\t^ #lNoExternalCall! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:29'!\\nrealExternalCallOrPrimitiveFailedSelector\\n\\t^ #lRealExternalCallOrPrimitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:54'!\\nsingularCallName\\n\\t\\\"occurrs exactly once as prim call name in >>lSingularExternalCall\\\"\\n\\t^ 'lSingularExternalCall'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/14/2004 23:32'!\\nsingularCallSelector\\n\\t^ #lSingularExternalCall! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'example module' stamp: 'sr 6/7/2004 08:39'!\\nlExternalCall1\\n\\t<primitive: 'prim1' module: 'LPCCT'>\\n! !\\n\\n!PCCByLiteralsTest methodsFor: 'example module' stamp: 'sr 6/7/2004 08:39'!\\nlExternalCall2\\n\\t\\t<primitive:'prim2'module:'LPCCT'>\\n\\t\\tself primitiveFailed! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 08:51'!\\nlDisabledExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'> \\\"primitiveExternalCall\\\" \\n\\tself primitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:59'!\\nlExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'> \\\"primitiveExternalCall\\\" \\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/15/2004 02:41'!\\nlFailedCall\\n\\t<primitive: 'primGetModuleName' module:'LFailModule'>\\n\\t^ 'failed call'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:57'!\\nlNoExternalCall\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\tself primitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 10:52'!\\nlSingularExternalCall\\n\\t<primitive: 'lSingularExternalCall' module:'LOne'>\\n\\t^ 'Hello World!!'! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'tests' stamp: 'sr 6/7/2004 11:30'!\\nsetUp\\n\\tsuper setUp.\\n\\t\\\"disable external calls\\\"\\n\\t(self class selectors\\n\\t\\tselect: [:sel | sel beginsWith: 'lDisabled'])\\n\\t\\tdo: [:sel | (self class >> sel) literals first at: 4 put: -2]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCCByLiteralsTest class\\n\\tinstanceVariableNames: ''!\\n\\n!PCCByLiteralsTest class methodsFor: 'Testing' stamp: 'sr 6/7/2004 12:01'!\\nisAbstract\\n\\t^ false! !\\nImageReadWriter subclass: #PCXReadWriter\\n\\tinstanceVariableNames: 'version encoding colorPlanes isGrayScale width height bitsPerPixel colorPalette rowByteSize'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n\\n!PCXReadWriter methodsFor: 'accessing' stamp: 'tao 10/6/97 10:11'!\\nnextImage\\n\\t\\\"Read in the next PCX image from the stream.\\\"\\n\\n\\t| bytes form |\\n\\tself readHeader.\\n\\tbytes _ self readBody.\\n\\tcolorPalette _ self readPalette.\\n\\tself close.\\n\\tform _ ColorForm extent: width@height depth: bitsPerPixel.\\n\\t(Form new hackBits: bytes) displayOn: (Form new hackBits: form bits).\\n\\tform colors: colorPalette.\\n\\t^ form\\n! !\\n\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 08:38'!\\nnextWord\\n\\t^self next + (self next bitShift: 8)! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 10:07'!\\nreadBody\\n\\n\\t| array scanLine rowBytes position byte count pad |\\n\\tpad _ #(0 3 2 1) at: (width \\\\\\\\ 4 + 1).\\n\\tarray _ ByteArray new: ((width + pad) * height * bitsPerPixel) // 8.\\n\\tscanLine _ ByteArray new: rowByteSize.\\n\\tposition _ 1.\\n\\t1 to: height do:\\n\\t\\t[:line |\\n\\t\\trowBytes _ 0.\\n\\t\\t[rowBytes < rowByteSize] whileTrue:\\n\\t\\t\\t[byte _ self next.\\n\\t\\t\\tbyte < 16rC0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[rowBytes _ rowBytes + 1.\\n\\t\\t\\t\\t\\tscanLine at: rowBytes put: byte]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[count _ byte - 16rC0.\\n\\t\\t\\t\\t\\tbyte _ self next.\\n\\t\\t\\t\\t\\t1 to: count do: [:i | scanLine at: rowBytes + i put: byte].\\n\\t\\t\\t\\t\\trowBytes _ rowBytes + count]].\\n\\t\\tarray\\n\\t\\t\\treplaceFrom: position\\n\\t\\t\\tto: position + width - 1\\n\\t\\t\\twith: scanLine\\n\\t\\t\\tstartingAt: 1.\\n\\t\\tposition _ position + width + pad].\\n\\t^ array\\n! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'md 11/14/2003 16:51'!\\nreadHeader\\n\\n\\t| xMin xMax yMin yMax |\\n\\tself next.\\t\\\"skip over manufacturer field\\\"\\n\\tversion _ self next.\\n\\tencoding _ self next.\\n\\tbitsPerPixel _ self next.\\n\\txMin _ self nextWord.\\n\\tyMin _ self nextWord.\\n\\txMax _ self nextWord.\\n\\tyMax _ self nextWord.\\n\\twidth _ xMax - xMin + 1.\\n\\theight _ yMax - yMin + 1.\\n\\tself next: 4. \\\"skip over device resolution\\\"\\n\\tself next: 49. \\\"skip over EGA color palette\\\"\\n\\tcolorPlanes _ self next.\\n\\trowByteSize _ self nextWord.\\n\\tisGrayScale _ (self next: 2) = 2.\\n\\tself next: 58. \\\"skip over filler\\\"\\n\\n\\n\\n! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 08:29'!\\nreadPalette\\n\\n\\t| r g b array |\\n\\tself next = 12 ifFalse: [self error: 'no Color Palette!!'].\\n\\tarray _ Array new: (1 bitShift: bitsPerPixel).\\n\\t1 to: array size do:\\n\\t\\t[:i |\\n\\t\\tr _ self next. g _ self next. b _ self next.\\n\\t\\tarray at: i put: (Color r: r g: g b: b range: 255)].\\n\\t^ array.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCXReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PCXReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:57'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('pcx')! !\\nObject subclass: #PHOReader\\n\\tinstanceVariableNames: 'stream phonemes events pitches time'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-Support'!\\n!PHOReader commentStamp: '<historical>' prior: 0!\\nMy instances read PHO files with lines of the form 'phoneme duration time0 pitch0 time1 pitch1 ...'. Time is in milliseconds, and pitch is in hertz. Files on this format are used as inputs for the MBROLA synthesizer, and there are lots of them available on the web. Here's an example:\\n\\n_ 120 0 105\\nm 60 33 105\\nE 70 42 102\\nr 50 20 108\\nI 50 20 125 100 142\\nk 100\\nr 50 80 137\\nI 50 80 121\\ns 70\\nm 50\\n@ 90 33 111 88 108\\ns 90\\n!\\n\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\naddPitches\\n\\t| offset |\\n\\toffset := 0.0.\\n\\tevents do: [ :each |\\n\\t\\teach pitchPoints: (self pitchesBetween: offset and: offset + each duration).\\n\\t\\toffset := offset + each duration].! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 8/29/1999 02:16'!\\nevents\\n\\t^ CompositeEvent new addAll: events; yourself! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nnextEvent\\n\\t| line phonemeName phoneme duration answer ptime pitch |\\n\\tline := ReadStream on: stream nextLine.\\n\\tphonemeName := line upTo: Character space.\\n\\tphoneme := phonemes at: phonemeName.\\n\\t[line peek isSeparator] whileTrue: [line next].\\n\\tduration := (line upTo: Character space) asNumber / 1000.0.\\n\\tanswer := PhoneticEvent new phoneme: phoneme; duration: duration; loudness: 1.0.\\n\\t[line atEnd]\\n\\t\\twhileFalse: [ptime := (line upTo: Character space) asNumber * duration / 100.0.\\n\\t\\t\\t\\t\\tpitch := (line upTo: Character space) asNumber asFloat.\\n\\t\\t\\t\\t\\tpitches add: time + ptime @ pitch].\\n\\ttime := time + duration.\\n\\t^ answer! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\npitchAt: t\\n\\t\\\"Answer the pitch of the receiver at a given time. (Do linear interpolation.)\\\"\\n\\t| xVal count x1 x2 y1 y2 |\\n\\txVal := pitches first x.\\n\\tcount := 1.\\n\\t[xVal < t]\\n\\t\\twhileTrue: [count := count + 1.\\n\\t\\t\\t\\t\\tcount > pitches size ifTrue: [^ pitches last y].\\n\\t\\t\\t\\t\\txVal := (pitches at: count) x].\\n\\txVal = t ifTrue: [^ (pitches at: count) y].\\n\\tcount = 1 ifTrue: [^ pitches first y].\\n\\tx1 := (pitches at: count - 1) x.\\n\\tx2 := (pitches at: count) x.\\n\\ty1 := (pitches at: count - 1) y.\\n\\ty2 := (pitches at: count) y.\\n\\t^ (t - x1) / (x2 - x1) * (y2 - y1) + y1! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\npitchesBetween: t1 and: t2\\n\\t| step |\\n\\tstep := (t2 - t1 / 0.035) asInteger + 1. \\\"step small enough\\\"\\n\\t^ (t1 to: t2 by: t2 - t1 / step) collect: [ :each | each - t1 @ (self pitchAt: each)]! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 6/17/1999 01:45'!\\nplotPitch\\n\\tUtilities plot: ((0 to: time by: 0.050) collect: [ :each | self pitchAt: each])! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 6/15/1999 00:40'!\\nread\\n\\tstream reset.\\n\\t[stream atEnd] whileFalse: [events add: self nextEvent].\\n\\tself addPitches! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nstream: aStream\\n\\tstream := aStream! !\\n\\n\\n!PHOReader methodsFor: 'initialization' stamp: 'stephaneducasse 2/3/2006 22:22'!\\ninitialize\\n\\tevents := OrderedCollection new.\\n\\tpitches := OrderedCollection new.\\n\\ttime := 0.0.\\n\\tphonemes := PhonemeSet sampaToArpabet! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPHOReader class\\n\\tinstanceVariableNames: ''!\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExample\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.63489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExampleFemale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 1.3].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExampleMale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.63489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceShortExample\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceShortExampleString.\\n\\tevents do: [ :each | each pitchBy: 1.3].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceShortExampleMale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceShortExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.4].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:47'!\\nmbrolaExample\\n\\t^ self eventsFromString:\\n'_ 50\\nE 40 0 102\\nm 50\\nb 50\\nr 30\\n@U 80 5 119 35 126 70 140\\nl 50\\n@ 50 50 173\\nw 100 75 133\\nV 30 85 114\\nz 60 75 101\\nd 60\\n@ 40\\nv 40 85 105\\nE 60 75 121\\nl 50 70 121\\n@ 60 60 150\\np 50\\nd 70\\nb 70 0 90\\nAI 130 85 101\\nT 70\\nj 50 0 180\\nE 120 0 185 95 131\\nr 40\\ni 90 85 135\\nd 80 60 134\\n@ 50 0 119 50 114\\nt 70\\nw 70 10 117 65 127 85 115\\nA 180 0 102 55 91 95 85\\n_ 100\\n_ 100\\nI 80 18 111\\nt 80\\ns 50\\n@ 30\\ns 70\\np 80\\ni 80 25 171 85 200\\ntS 110\\ns 70\\nI 30 35 112\\nn 40\\nT 80\\n@ 40 85 108\\ns 80\\nAI 130 80 115\\nz 70 90 125\\nr= 120 75 111\\nb 80\\nEI 80 95 133\\nz 70\\nd 50\\nA 40\\nn 30\\nD 60\\n@ 30 65 121\\nk 90\\nA 30\\nn 30 100 140\\nk 80\\n{ 70 5 170\\nt 70\\n@ 40 50 186\\nn 40 75 163\\nEI 100 90 173\\nS 130\\n@ 40\\nn 30 65 153\\nV 40\\nv 70 0 148\\nd 60\\nAI 130 5 112 80 109\\nf 110\\n@U 160 87 88\\nn 70\\nz 210 88 82\\n_ 80\\n_ 100\\nI 40 0 140\\nt 50\\nt 100\\nEI 60 50 221\\nk 70\\ns 80\\n@ 30 0 190\\nl 50\\nI 30 65 180\\ns 110\\nt 70\\nV 50 20 171\\nv 50\\nf 90\\n@U 140 25 157\\nn 30\\ni 60 66 160\\nm 50 60 130\\nz 80\\n@ 40 62 78\\nz 80\\nI 70 78 134\\nn 50 70 163\\np 120\\nU 90 15 119 75 98\\nt 90\\n_ 140\\n_ 100\\nt 60 0 111\\nu 50 80 119\\ng 70\\nE 50 90 145\\nD 50\\nr= 50 40 139 90 163\\nw 90\\nI 30 15 114\\nD 50\\n_ 40\\np 50\\nr 30 0 102\\n@ 30 65 110\\ns 120\\nA 50 90 148\\nd 80\\nI 50 50 178\\nk 80\\nI 50 66 167\\nn 60\\nf 50\\nr= 50 90 125\\nm 50\\nEI 140 95 96\\nS 140\\n@ 80 35 168\\nn 100 95 142\\n_ 190\\n{ 90 0 133\\nn 30\\nd 30\\np 80\\nr 40\\n@ 40 0 97 65 103\\nd 70\\nj 20\\nu 60 65 150\\ns 90\\nI 30 50 210\\nz 50\\ns 140\\np 70\\ni 130 0 138 95 98\\ntS 160\\n{ 70 0 127\\nt 50\\nD 50\\n@ 30 15 93\\ns 140\\n{ 30 35 127\\nm 50\\np 70\\nl 50\\nI 30 35 184\\nN 70\\nf 70\\nr 60\\ni 90 30 125\\nk 40\\nw 30\\n@ 30 15 185\\nn 30\\ns 100\\ni 50 20 148 70 142\\nV 30 5 148\\nv 40\\nD 80\\n@ 40 25 106\\nd 80\\nAI 150 95 115\\nf 90\\n@U 130 95 114\\nn 70\\nd 80\\nEI 80 80 137\\n4 50\\n@ 30\\nb 100\\nEI 120 95 78\\ns 210\\n_ 80'! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:48'!\\npushExample\\n\\t^ self eventsFromString:\\n'_ 60 0 137\\np 50 100 137\\nu 110 90 137\\nS 100 10 121\\nD 90\\n@ 70 57 114 100 102\\ns 70\\nt 50\\nA 100 57 121 64 121\\nr 40\\nt 50\\nb 110\\nV 140 21 117 57 100 92 100\\n_ 3\\nn 130 25 102 50 105\\nt 60\\nu 70 28 129 71 111\\nb 70\\ni 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93\\n_ 140 92 93 100 100'! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npushExampleFemale\\n\\t| events |\\n\\tevents := self pushExample.\\n\\tevents do: [ :each | each pitchBy: 1.93489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npushShortExample\\n\\t^ self eventsFromString:\\n'i 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93'.\\n\\\"\\n':= 3\\nn 130 25 102 50 105\\nt 60\\nu 70 28 129 71 111\\nb 70\\ni 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93\\n:= 140 92 93 100 100'\\\"! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:48'!\\nxmasExample\\n\\t^ self eventsFromString:\\n'_ 120 0 105\\nm 60 33 105\\nE 70 42 102\\nr 50 20 108\\nI 50 20 125 100 142\\nk 100\\nr 50 80 137\\nI 50 80 121\\ns 70\\nm 50\\n@ 90 33 111 88 108\\ns 90\\n{ 70\\nn 100 50 105 100 97\\nd 50 80 93\\nh 50 20 93\\n{ 50 20 102 60 114\\np 50\\ni 50 100 125\\nn 60 83 121\\nu 100\\nj 130 7 121 23 121 100 108\\nr= 250 41 102 83 97\\n_ 210 95 86 100 100'\\n! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nxmasKidExample\\n\\t| events |\\n\\tevents := self xmasExample.\\n\\tevents do: [ :each | each pitchBy: 1.6].\\n\\t^ events! !\\n\\n\\n!PHOReader class methodsFor: 'examples-private' stamp: 'len 7/27/1999 01:45'!\\naliceExampleString\\n\\t^ '_ 48 0 222\\n{ 80 40 222 90 235\\nl 72 44 250 66 250\\nI 80\\ns 88\\nw 40 80 235\\n@ 40 80 210\\nz 64 12 210 50 181 75 181\\nb 72 33 173 88 181\\nI 56 71 181\\ng 56 28 153 100 166\\nI 64 62 160\\nn 40 60 160\\nI 88 27 166\\nN 40 100 166\\nt 80 20 160\\nU 40 40 181 80 166\\ng 48 100 166\\nE 104 38 153 76 137\\nt 56\\nv 48\\nE 72 11 166 66 153\\nr 88 18 160 63 166\\ni 112.8 14 166 49 173 77 173\\nt 104.8 98 137\\nAI 178.4 21 148 70 148 92 137\\nr= 108 25 137 62 133 98 129\\nd 49\\n@ 59.2 6 137 73 133\\nv 46\\ns 89\\nI 40 40 173\\nt 40 40 166\\nI 64 62 166\\nN 72 22 160 77 153\\nb 40 40 142 100 153\\nAI 136 29 142\\nh 80 30 142 100 148\\nr= 64 62 153 100 153\\ns 125\\nI 64 37 210 100 190\\ns 72 11 190\\nt 72\\nr= 104 30 160 69 142\\nO 72\\nn 40 40 142\\nD 40 40 153\\n@ 40 40 160\\nb 40 40 153 100 160\\n{ 216 18 166 51 166 70 153 88 137 100 133\\nn 40\\nk 56\\n_ 144 94 129 100 100\\n_ 100 0 137\\n{ 40\\nn 88 9 137 36 137 72 142\\nt 40 40 137 60 133\\n@ 48 16 148 100 148\\nh 40 100 142\\n{ 48 83 148\\nv 48 16 142\\nI 56 14 148 85 137\\nN 56 71 137\\nn 64 37 137 100 142\\nO 96 41 137 83 153 100 153\\nT 64\\nI 56 42 166\\nN 64 12 160 75 153\\nt 80 30 142\\n@ 56 28 166 100 148\\nd 56 71 137\\nu 160 15 160 45 160 70 153 95 142\\nw 136 23 137 58 137 88 148\\nA 112 21 153 57 160 92 173\\nn 64 50 166 62 153\\ns 56\\nO 48 50 153\\nr 40 40 142 100 133\\nt 130\\nw 56 57 166\\nAI 168 9 173 33 166 57 153 80 148 100 148\\ns 88\\n_ 300\\nS 92\\ni 48 50 235\\nh 40 40 235 100 250\\n@ 40 60 210 100 210\\nd 40\\np 40\\ni 150\\nk 56\\nd 56\\nI 72 44 222 100 210\\nn 40 80 210\\nt 56\\n@ 48 83 181\\nD 40 39 173 99 173\\n@ 39.2 100 160\\nb 104 30 153 100 153\\nU 112 35 153 85 153 100 153\\nk 72\\nh 56\\nr= 48 50 200\\ns 136 5 181\\nI 64 25 166 87 142\\ns 56 14 137\\nt 56\\nr= 56 28 173 100 173\\nw 56 71 166\\n@ 56 42 181\\nz 48 16 181 50 173\\nr 120 73 181\\ni 104 7 190 69 190 100 181\\nd 40\\nI 112 7 166 50 137 85 129\\nN 80 30 114 50 111\\n_ 56 83 111 100 100\\n_ 140 0 153\\nb 40 60 153 100 153\\nU 64 75 148\\n4 40 80 148 100 142\\nI 40\\nt 40 40 148\\nh 40 40 142\\n{ 48 33 137\\nd 136 5 133 11 129 88 148\\nn 48 66 148\\n@U 144 16 160 44 173 72 190 100 210\\np 80\\nI 96 75 190 100 181\\nk 56\\ntS 96\\nr= 104 30 190 69 181\\nz 72 11 181 33 173\\nO 40 60 173\\nr 64 37 160 100 153\\nk 72 11 153\\nO 152 63 190 89 200\\nn 40 60 181\\nv 40 60 166\\nr= 40 60 160\\ns 104 15 142\\nEI 120 20 190 53 190 86 210\\nS 104 7 210\\n@ 56 28 181 100 160\\nn 64 62 153 100 137\\nz 40\\nI 56 14 148 85 133\\nn 40 100 133\\nI 96 41 129 83 125\\nt 80\\n_ 64 85 125 100 100\\n_ 140 0 222\\n{ 56 14 222 28 220 42 235 85 235 100 220\\nn 96 33 222 75 235 100 235\\nw 48 33 222 66 250\\nO 90\\n4 48 50 222 66 252\\nI 48 33 250\\nz 64 12 235 62 210\\nD 56\\n@ 56 71 190\\nj 104 23 166 61 166 100 181\\nu 112 35 190 42 210 71 210 100 210\\ns 150\\n@ 56 42 200\\nv 40 20 160 60 148\\n@ 64 25 153 87 142\\nb 136 23 133 47 137\\nU 96 8 160 50 173 91 181 100 181\\nk 56\\n_ 56\\nT 56\\nO 119.2 20 166 53 142 80 137\\n4 40 20 133\\n{ 136 5 137 35 129 64 125\\nl 48 16 125 100 133\\nI 80 50 153 100 181\\ns 120\\n_ 40\\n_ 40\\nw 88 9 166 54 142\\nI 40 40 142\\nD 40 40 137\\naU 62.4 38 137 63 133\\nt 80\\np 55\\nI 72 16 210 38 210\\nk 40\\ntS 75.2 99 173\\nr= 136 29 160 64 160 76 166\\nz 48\\nO 44 90 185\\nr 60 6 198 46 200 72 190\\nk 40\\nO 81.6 12 148 61 133\\nn 40 20 133\\nv 48 33 133\\nr= 56 28 181 100 181\\ns 120 6 173\\nEI 136 11 222 41 210 94 210\\nS 120\\n@ 128 12 190 43 148 75 137\\nn 64 12 129 50 125\\n_ 80 88 125 100 100'! !\\n\\n!PHOReader class methodsFor: 'examples-private' stamp: 'len 7/27/1999 01:46'!\\naliceShortExampleString\\n\\t^ '_ 48 0 222\\n{ 80 40 222 90 235\\nl 72 44 250 66 250\\nI 80\\ns 88\\nw 40 80 235\\n@ 40 80 210\\nz 64 12 210 50 181 75 181\\nb 72 33 173 88 181\\nI 56 71 181\\ng 56 28 153 100 166\\nI 64 62 160\\nn 40 60 160\\nI 88 27 166\\nN 40 100 166\\nt 80 20 160\\nU 40 40 181 80 166\\ng 48 100 166\\nE 104 38 153 76 137\\nt 56\\nv 48\\nE 72 11 166 66 153\\nr 88 18 160 63 166\\ni 112.8 14 166 49 173 77 173\\nt 104.8 98 137\\nAI 178.4 21 148 70 148 92 137\\nr= 108 25 137 62 133 98 129\\nd 49\\n@ 59.2 6 137 73 133\\nv 46\\ns 89\\nI 40 40 173\\nt 40 40 166\\nI 64 62 166\\nN 72 22 160 77 153\\nb 40 40 142 100 153\\nAI 136 29 142\\nh 80 30 142 100 148\\n@ 60 50 150\\nr= 64 62 153 100 153\\ns 125\\nI 64 37 210 100 190\\ns 72 11 190\\nt 72\\nr= 104 30 160 69 142\\nO 72\\nn 40 40 142\\nD 40 40 153\\n@ 40 40 160\\nb 40 40 153 100 160\\n{ 216 18 166 51 166 70 153 88 137 100 133\\nn 40\\nk 56\\n_ 144 94 129 100 100'! !\\n\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/15/1999 00:48'!\\neventsFromStream: aStream\\n\\t^ self new stream: aStream; read; events! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/15/1999 00:49'!\\neventsFromString: aString\\n\\t^ self eventsFromStream: (ReadStream on: aString)! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/17/1999 01:47'!\\nplotPitchFromStream: aStream\\n\\t^ self new stream: aStream; read; plotPitch! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/17/1999 01:47'!\\nplotPitchFromString: aString\\n\\t^ self plotPitchFromStream: (ReadStream on: aString)! !\\nImageReadWriter subclass: #PNGReadWriter\\n\\tinstanceVariableNames: 'chunk form width height depth backColor bitsPerChannel colorType interlaceMethod bitsPerPixel bytesPerScanline thisScanline prevScanline rowSize globalDataChunk unknownChunks palette transparentPixelValue filtersSeen swizzleMap cachedDecoderMap bigEndian'\\n\\tclassVariableNames: 'BPP BlockHeight BlockWidth Debugging StandardColors StandardSwizzleMaps'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n!PNGReadWriter commentStamp: '<historical>' prior: 0!\\nI am a subclass of ImageReadWriter that decodes Portable Network Graphics\\n(PNG) images.\\n\\nSubmitted by Duane Maxwell!\\n\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'RAA 11/7/2000 09:20'!\\ndebugging\\n\\n\\t^Debugging == true! !\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'nk 7/30/2004 17:51'!\\nnextImage\\n\\tbigEndian := SmalltalkImage current isBigEndian.\\n\\tfiltersSeen := Bag new.\\n\\tglobalDataChunk := nil.\\n\\ttransparentPixelValue := nil.\\n\\tunknownChunks := Set new.\\n\\tstream reset.\\n\\tstream binary.\\n\\tstream skip: 8.\\n\\t[stream atEnd] whileFalse: [self processNextChunk].\\n\\t\\\"Set up our form\\\"\\n\\tpalette ifNotNil: \\n\\t\\t\\t[\\\"Dump the palette if it's the same as our standard palette\\\"\\n\\n\\t\\t\\tpalette = (StandardColors copyFrom: 1 to: palette size) \\n\\t\\t\\t\\tifTrue: [palette := nil]].\\n\\t(depth <= 8 and: [palette notNil]) \\n\\t\\tifTrue: \\n\\t\\t\\t[form := ColorForm extent: width @ height depth: depth.\\n\\t\\t\\tform colors: palette]\\n\\t\\tifFalse: [form := Form extent: width @ height depth: depth].\\n\\tbackColor ifNotNil: [form fillColor: backColor].\\n\\tchunk := globalDataChunk ifNil: [self error: 'image data is missing'].\\n\\tchunk ifNotNil: [self processIDATChunk].\\n\\tunknownChunks isEmpty \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Transcript show: ' ',unknownChunks asSortedCollection asArray printString.\\\"\\n\\n\\t\\t\\t].\\n\\tself debugging \\n\\t\\tifTrue: \\n\\t\\t\\t[Transcript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'form = ' , form printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'colorType = ' , colorType printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'interlaceMethod = ' , interlaceMethod printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'filters = ' , filtersSeen sortedCounts asArray printString].\\n\\t^form! !\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'DSM 3/24/2000 01:12'!\\nunderstandsImageFormat\\n\\t#(137 80 78 71 13 10 26 10) do: [ :byte |\\n\\t\\tstream next = byte ifFalse: [^ false]].\\n\\t^ true\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/10/2004 23:55'!\\nprocessBackgroundChunk\\n\\n\\t| val red green blue max |\\n\\n\\t\\\"Transcript show: ' BACKGROUND: ',chunk printString.\\\"\\n\\tcolorType = 3 ifTrue: [\\n\\t\\tbackColor := palette at: chunk first + 1.\\n\\t\\t^self\\n\\t].\\n\\tmax _ (2 raisedTo: bitsPerChannel) - 1.\\n\\t(colorType = 0 or: [colorType = 4]) ifTrue: [\\n\\t\\tval _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\tbackColor := Color gray: val / max.\\n\\t\\t^self\\n\\t].\\n\\t(colorType = 2 or: [colorType = 6]) ifTrue: [\\n\\t\\tred _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\tgreen _ chunk unsignedShortAt: 3 bigEndian: true.\\n\\t\\tblue _ chunk unsignedShortAt: 5 bigEndian: true.\\n\\t\\tbackColor := Color r: red/max g: green/max b: blue/max.\\n\\t\\t^self\\n\\t].\\n\\\"self halt.\\\"\\n\\n\\\"====\\nThe bKGD chunk specifies a default background color to present the image against. Note that viewers are not bound to honor this chunk; a viewer can choose to use a different background. \\n\\nFor color type 3 (indexed color), the bKGD chunk contains: \\n\\n\\n Palette index: 1 byte\\n\\nThe value is the palette index of the color to be used as background. \\n\\nFor color types 0 and 4 (grayscale, with or without alpha), bKGD contains: \\n\\n\\n Gray: 2 bytes, range 0 .. (2^bitdepth)-1\\n\\n(For consistency, 2 bytes are used regardless of the image bit depth.) The value is the gray level to be used as background. \\n\\nFor color types 2 and 6 (truecolor, with or without alpha), bKGD contains: \\n\\n\\n Red: 2 bytes, range 0 .. (2^bitdepth)-1\\n Green: 2 bytes, range 0 .. (2^bitdepth)-1\\n Blue: 2 bytes, range 0 .. (2^bitdepth)-1\\n\\n(For consistency, 2 bytes per sample are used regardless of the image bit depth.) This is the RGB color to be used as background. \\n\\nWhen present, the bKGD chunk must precede the first IDAT chunk, and must follow the PLTE chunk, if any. \\n===\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/4/2000 17:00'!\\nprocessIDATChunk\\n\\n\\tinterlaceMethod = 0\\n\\t\\tifTrue: [ self processNonInterlaced ]\\n\\t\\tifFalse: [ self processInterlaced ]\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/10/2004 23:55'!\\nprocessIHDRChunk\\n\\twidth _ chunk longAt: 1 bigEndian: true.\\n\\theight _ chunk longAt: 5 bigEndian: true.\\n\\tbitsPerChannel _ chunk at: 9.\\n\\tcolorType _ chunk at: 10.\\n\\t\\\"compression _ chunk at: 11.\\\" \\\"TODO - validate compression\\\"\\n\\t\\\"filterMethod _ chunk at: 12.\\\" \\\"TODO - validate filterMethod\\\"\\n\\tinterlaceMethod _ chunk at: 13. \\\"TODO - validate interlace method\\\"\\n\\t(#(2 4 6) includes: colorType)\\n\\t\\tifTrue: [depth _ 32].\\n\\t(#(0 3) includes: colorType) ifTrue: [\\n\\t\\tdepth _ bitsPerChannel min: 8.\\n\\t\\tcolorType = 0 ifTrue: [ \\\"grayscale\\\"\\n\\t\\t\\tpalette := self grayColorsFor: depth.\\n\\t\\t].\\n\\t].\\n\\tbitsPerPixel _ (BPP at: colorType+1) at: bitsPerChannel highBit.\\n\\tbytesPerScanline _ width * bitsPerPixel + 7 // 8.\\n\\trowSize _ width * depth + 31 >> 5.\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/29/2004 04:19'!\\nprocessInterlaced\\n\\t| z filter bytesPerPass startingCol colIncrement rowIncrement startingRow cx sc temp |\\n\\tstartingCol _ #(0 4 0 2 0 1 0 ).\\n\\tcolIncrement _ #(8 8 4 4 2 2 1 ).\\n\\trowIncrement _ #(8 8 8 4 4 2 2 ).\\n\\tstartingRow _ #(0 0 4 0 2 0 1 ).\\n\\tz _ ZLibReadStream on: chunk from: 1 to: chunk size.\\n\\t1 to: 7 do: [:pass |\\n\\t\\t(self doPass: pass)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[cx _ colIncrement at: pass.\\n\\t\\t\\t\\tsc _ startingCol at: pass.\\n\\t\\t\\t\\tbytesPerPass _ width - sc + cx - 1 // cx * bitsPerPixel + 7 // 8.\\n\\t\\t\\t\\tprevScanline _ ByteArray new: bytesPerPass.\\n\\t\\t\\t\\tthisScanline _ ByteArray new: bytesPerScanline.\\n\\t\\t\\t\\t(startingRow at: pass)\\n\\t\\t\\t\\t\\tto: height - 1\\n\\t\\t\\t\\t\\tby: (rowIncrement at: pass)\\n\\t\\t\\t\\t\\tdo: [:y |\\n\\t\\t\\t\\t\\t\\tfilter _ z next.\\n\\t\\t\\t\\t\\t\\tfiltersSeen add: filter.\\n\\t\\t\\t\\t\\t\\t(filter isNil or: [(filter between: 0 and: 4) not])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\t\\tthisScanline _ z next: bytesPerPass into: thisScanline startingAt: 1.\\n\\t\\t\\t\\t\\t\\tself filterScanline: filter count: bytesPerPass.\\n\\t\\t\\t\\t\\t\\tself copyPixels: y at: sc by: cx.\\n\\t\\t\\t\\t\\t\\ttemp := prevScanline.\\n\\t\\t\\t\\t\\t\\tprevScanline := thisScanline.\\n\\t\\t\\t\\t\\t\\tthisScanline := temp.\\n\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t]\\n\\t].\\n\\tz atEnd ifFalse:[self error:'Unexpected data'].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/11/2004 12:14'!\\nprocessNextChunk\\n\\n\\t| length chunkType crc chunkCrc |\\n\\n\\tlength _ self nextLong.\\n\\n\\tchunkType _ (self next: 4) asString.\\n\\tchunk _ self next: length.\\n\\tchunkCrc := self nextLong bitXor: 16rFFFFFFFF.\\n\\tcrc := self updateCrc: 16rFFFFFFFF from: 1 to: 4 in: chunkType.\\n\\tcrc := self updateCrc: crc from: 1 to: length in: chunk.\\n\\tcrc = chunkCrc ifFalse:[\\n\\t\\tself error: 'PNGReadWriter crc error in chunk ', chunkType.\\n\\t].\\n\\n\\tchunkType = 'IEND' ifTrue: [^self\\t\\\"*should* be the last chunk\\\"].\\n\\tchunkType = 'sBIT' ifTrue: [^self processSBITChunk \\\"could indicate unusual sample depth in original\\\"].\\n\\tchunkType = 'gAMA' ifTrue: [^self \\t\\\"indicates gamma correction value\\\"].\\n\\tchunkType = 'bKGD' ifTrue: [^self processBackgroundChunk].\\n\\tchunkType = 'pHYs' ifTrue: [^self processPhysicalPixelChunk].\\n\\tchunkType = 'tRNS' ifTrue: [^self processTransparencyChunk].\\n\\n\\tchunkType = 'IHDR' ifTrue: [^self processIHDRChunk].\\n\\tchunkType = 'PLTE' ifTrue: [^self processPLTEChunk].\\n\\tchunkType = 'IDAT' ifTrue: [\\n\\t\\t\\\"---since the compressed data can span multiple\\n\\t\\tchunks, stitch them all together first. later,\\n\\t\\tif memory is an issue, we need to figure out how\\n\\t\\tto do this on the fly---\\\"\\n\\t\\tglobalDataChunk _ globalDataChunk ifNil: [chunk] ifNotNil:\\n\\t\\t\\t[globalDataChunk,chunk].\\n\\t\\t^self\\n\\t].\\n\\tunknownChunks add: chunkType.\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/29/2004 04:19'!\\nprocessNonInterlaced\\n\\t| z filter temp copyMethod debug |\\n\\tdebug := self debugging.\\n\\tcopyMethod _ #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:\\n\\t\\t copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.\\n\\tdebug ifTrue: [ Transcript cr; nextPutAll: 'NI chunk size='; print: chunk size ].\\n\\tz _ ZLibReadStream on: chunk from: 1 to: chunk size.\\n\\tprevScanline _ ByteArray new: bytesPerScanline.\\n\\tthisScanline := ByteArray new: bytesPerScanline.\\n\\t0 to: height-1 do: [ :y |\\n\\t\\tfilter _ (z next: 1) first.\\n\\t\\tdebug ifTrue:[filtersSeen add: filter].\\n\\t\\tthisScanline _ z next: bytesPerScanline into: thisScanline startingAt: 1.\\n\\t\\t(debug and: [ thisScanline size < bytesPerScanline ]) ifTrue: [ Transcript nextPutAll: ('wanted {1} but only got {2}' format: { bytesPerScanline. thisScanline size }); cr ].\\n\\t\\tfilter = 0 ifFalse:[self filterScanline: filter count: bytesPerScanline].\\n\\t\\tself perform: copyMethod with: y.\\n\\t\\ttemp := prevScanline.\\n\\t\\tprevScanline := thisScanline.\\n\\t\\tthisScanline := temp.\\n\\t\\t].\\n\\tz atEnd ifFalse:[self error:'Unexpected data'].\\n\\tdebug ifTrue: [Transcript nextPutAll: ' compressed size='; print: z position ].\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/11/2004 01:02'!\\nprocessPLTEChunk\\n\\n\\t| colorCount i |\\n\\n\\tcolorCount _ chunk size // 3. \\\"TODO - validate colorCount against depth\\\"\\n\\tpalette _ Array new: colorCount.\\n\\t0 to: colorCount-1 do: [ :index |\\n\\t\\ti _ index * 3 + 1.\\n\\t\\tpalette at: index+1 put:\\n\\t\\t\\t(Color r: (chunk at: i)/255.0 g: (chunk at: i+1)/255.0 b: (chunk at: i+2)/255.0)\\n\\t\\t].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/5/2000 11:24'!\\nprocessPhysicalPixelChunk\\n\\n\\t\\\"Transcript show: ' PHYSICAL: ',chunk printString.\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 12/12/2003 18:33'!\\nprocessSBITChunk\\n\\t| rBits gBits bBits aBits |\\n\\tcolorType = 6 ifFalse:[^self].\\n\\trBits := chunk at: 1.\\n\\tgBits := chunk at: 2.\\n\\tbBits := chunk at: 3.\\n\\taBits := chunk at: 4.\\n\\t(rBits = 5 and:[gBits = 5 and:[bBits = 5 and:[aBits = 1]]]) ifTrue:[\\n\\t\\tdepth := 16.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/4/2000 16:22'!\\nprocessTransparencyChunk\\n\\n\\t| red green blue |\\n\\n\\t\\\"Transcript show: ' TRANSPARENCY ',chunk printString.\\\"\\n\\tcolorType = 0 ifTrue: [\\n\\t\\ttransparentPixelValue _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\t^self\\n\\t].\\n\\tcolorType = 2 ifTrue: [\\n\\t\\tred _ chunk at: 2.\\n\\t\\tgreen _ chunk at: 2.\\n\\t\\tblue _ chunk at: 2.\\n\\t\\ttransparentPixelValue _ 16rFF00 + red << 8 + green << 8 + blue.\\n\\t\\t^self\\n\\t].\\n\\tcolorType = 3 ifTrue: [\\n\\t\\tchunk withIndexDo: [ :alpha :index |\\n\\t\\t\\tpalette at: index put: ((palette at: index) alpha: alpha/255)\\n\\t\\t].\\n\\t\\t^self\\n\\t].\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'RAA 11/7/2000 09:43'!\\nfilterAverage: count\\n\\t\\\"Use the average of the pixel to the left and the pixel above as a predictor\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\t1 to: delta do: [:i |\\n\\t\\tthisScanline at: i put: ((thisScanline at: i) + ((prevScanline at: i) // 2) bitAnd: 255)].\\n\\tdelta + 1 to: count do: [:i |\\n\\t\\tthisScanline at: i put:\\n\\t\\t\\t((thisScanline at: i)\\n\\t\\t\\t+ ((prevScanline at: i)\\n\\t\\t\\t+ (thisScanline at: i - delta) // 2) bitAnd: 255)]! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:54'!\\nfilterHorizontal: count\\n\\t\\\"Use the pixel to the left as a predictor\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\tdelta+1 to: count do: [ :i |\\n\\t\\tthisScanline at: i put: (((thisScanline at: i) +\\n(thisScanline at: i-delta)) bitAnd: 255) ]\\n\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:55'!\\nfilterNone: count\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'RAA 11/7/2000 09:45'!\\nfilterPaeth: count\\n\\t\\\"Select one of (the pixel to the left, the pixel above and the pixel to above left) to\\n\\tpredict the value of this pixel\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\t1 to: delta do: [ :i |\\n\\t\\tthisScanline at: i put:\\n\\t\\t\\t(((thisScanline at: i) + (prevScanline at: i)) bitAnd: 255)].\\n\\tdelta+1 to: count do: [ :i |\\n\\t\\tthisScanline\\n\\t\\t\\tat: i\\n\\t\\t\\tput: (((thisScanline at: i) + (self\\n\\t\\t\\t\\tpaethPredictLeft: (thisScanline at: i-delta)\\n\\t\\t\\t\\tabove: (prevScanline at: i)\\n\\t\\t\\t\\taboveLeft: (prevScanline at: i-delta)))\\n\\t\\t\\t\\t\\tbitAnd: 255)]\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'eat 9/11/2000 20:08'!\\nfilterScanline: filterType count: count\\n\\n\\tself\\n\\t\\tperform: (\\n\\t\\t\\t#(filterNone: filterHorizontal: filterVertical: filterAverage: filterPaeth:)\\n\\t\\t\\t\\tat: filterType+1)\\n\\t\\twith: count.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:54'!\\nfilterVertical: count\\n\\t\\\"Use the pixel above as a predictor\\\"\\n\\n\\t1 to: count do: [ :i |\\n\\t\\tthisScanline at: i put: (((thisScanline at: i) +\\n(prevScanline at: i)) bitAnd: 255) ]\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'eat 9/11/2000 20:05'!\\npaethPredictLeft: a above: b aboveLeft: c\\n\\t\\\"Predicts the value of a pixel based on nearby pixels, based on\\nPaeth (GG II, 1991)\\\"\\n\\n\\t| pa pb pc |\\n\\tpa _ b > c ifTrue: [b - c] ifFalse: [c - b].\\n\\tpb _ a > c ifTrue: [a - c] ifFalse: [c - a].\\n\\tpc _ a + b - c - c.\\n\\tpc < 0 ifTrue: [\\n\\t\\tpc := pc * -1].\\n\\t((pa <= pb) and: [pa <= pc]) ifTrue: [^ a].\\n\\t(pb <= pc) ifTrue: [^ b].\\n\\t^ c\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'miscellaneous' stamp: 'DSM 4/27/2000 13:09'!\\ndoPass: pass\\n\\t\\\"Certain interlace passes are skipped with certain small image\\ndimensions\\\"\\n\\n\\tpass = 1 ifTrue: [ ^ true ].\\n\\t((width = 1) and: [height = 1]) ifTrue: [ ^ false ].\\n\\tpass = 2 ifTrue: [ ^ width >= 5 ].\\n\\tpass = 3 ifTrue: [ ^ height >= 5 ].\\n\\tpass = 4 ifTrue: [ ^ (width >=3 ) or: [height >= 5] ].\\n\\tpass = 5 ifTrue: [ ^ height >=3 ].\\n\\tpass = 6 ifTrue: [ ^ width >=2 ].\\n\\tpass = 7 ifTrue: [ ^ height >=2 ].\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'miscellaneous' stamp: 'ar 2/11/2004 01:27'!\\ngrayColorsFor: d\\n\\t\\\"return a color table for a gray image\\\"\\n\\n\\tpalette _ Array new: 1<<d.\\n\\td = 1 ifTrue: [\\n\\t\\tpalette at: 1 put: Color black.\\n\\t\\tpalette at: 2 put: Color white.\\n\\t\\t^ palette,{Color transparent}\\n\\t\\t].\\n\\td = 2 ifTrue: [\\n\\t\\tpalette at: 1 put: Color black.\\n\\t\\tpalette at: 2 put: (Color gray: 85.0 / 255.0).\\n\\t\\tpalette at: 3 put: (Color gray: 170.0 / 255.0).\\n\\t\\tpalette at: 4 put: Color white.\\n\\t\\t^ palette,{Color transparent}.\\n\\t\\t].\\n\\td = 4 ifTrue: [\\n\\t\\t0 to: 15 do: [ :g |\\n\\t\\t\\tpalette at: g+1 put: (Color gray: (g/15) asFloat) ].\\n\\t\\t^ palette,{Color transparent}\\n\\t\\t].\\n\\td = 8 ifTrue: [\\n\\t\\t0 to: 255 do: [ :g |\\n\\t\\t\\tpalette at: g+1 put: (Color gray: (g/255) asFloat) ].\\n\\t\\t^ palette\\t\\t\\\"??transparent??\\\"\\n\\t\\t].\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'DSM 3/26/2000 21:32'!\\ncopyPixels: y\\n\\t\\\"Handle non-interlaced pixels of supported colorTypes\\\"\\n\\n\\t| s |\\n\\ts _ #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:\\n\\t\\t copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.\\n\\tself perform: s asSymbol with: y\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:08'!\\ncopyPixels: y at: startX by: incX\\n\\t\\\"Handle interlaced pixels of supported colorTypes\\\"\\n\\n\\t| s |\\n\\ts _ #(copyPixelsGray:at:by: nil copyPixelsRGB:at:by: copyPixelsIndexed:at:by:\\n\\t\\t copyPixelsGrayAlpha:at:by: nil copyPixelsRGBA:at:by:) at: colorType+1.\\n\\tself perform: s asSymbol with: y with: startX with: incX\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:12'!\\ncopyPixelsGray: y \\n\\t\\\"Handle non-interlaced grayscale color mode (colorType = 0)\\\"\\n\\t| blitter pixPerByte mask shifts pixelNumber rawByte pixel transparentIndex |\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\ttransparentIndex _ form colors size.\\n\\tbitsPerChannel = 16\\n\\t\\tifTrue: [0\\n\\t\\t\\t\\tto: width - 1\\n\\t\\t\\t\\tdo: [:x | blitter pixelAt: x @ y put: 255\\n\\t\\t\\t\\t\\t\\t\\t- (thisScanline at: x << 1 + 1)].\\n\\t\\t\\t^ self]\\n\\t\\tifFalse: [bitsPerChannel = 8\\n\\t\\t\\t\\tifTrue: [1\\n\\t\\t\\t\\t\\t\\tto: width\\n\\t\\t\\t\\t\\t\\tdo: [:x | blitter\\n\\t\\t\\t\\t\\t\\t\\t\\tpixelAt: x - 1 @ y\\n\\t\\t\\t\\t\\t\\t\\t\\tput: (thisScanline at: x)].\\n\\t\\t\\t\\t\\t^ self].\\n\\t\\t\\tbitsPerChannel = 1\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 8.\\n\\t\\t\\t\\t\\tmask _ 1.\\n\\t\\t\\t\\t\\tshifts _ #(7 6 5 4 3 2 1 0 )].\\n\\t\\t\\tbitsPerChannel = 2\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 4.\\n\\t\\t\\t\\t\\tmask _ 3.\\n\\t\\t\\t\\t\\tshifts _ #(6 4 2 0 )].\\n\\t\\t\\tbitsPerChannel = 4\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 2.\\n\\t\\t\\t\\t\\tmask _ 15.\\n\\t\\t\\t\\t\\tshifts _ #(4 0 )].\\n\\t\\t\\tpixelNumber _ 0.\\n\\t\\t\\t0 to: width - 1 do: [:x | \\n\\t\\t\\t\\trawByte _ thisScanline at: pixelNumber // pixPerByte + 1.\\n\\t\\t\\t\\tpixel _ rawByte\\n\\t\\t\\t\\t\\t\\t\\t>> (shifts at: pixelNumber \\\\\\\\ pixPerByte + 1) bitAnd: mask.\\n\\t\\t\\t\\tpixel = transparentPixelValue ifTrue: [pixel _ transparentIndex].\\n\\t\\t\\t\\tblitter pixelAt: x @ y put: pixel.\\n\\t\\t\\t\\tpixelNumber _ pixelNumber + 1\\n\\t\\t\\t]\\n\\t\\t]! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGray: y at: startX by: incX\\n\\t\\\"Handle interlaced grayscale color mode (colorType = 0)\\\"\\n\\n\\t| b offset bits w pixel mask blitter pixelNumber pixPerByte rawByte\\nshifts |\\n\\tbitsPerChannel = 16\\n\\t\\tifTrue: [\\n\\t\\t\\tb _ BitBlt current bitPokerToForm: form.\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\tb pixelAt: x@y put: 255 - (thisScanline at: (x//incX<<1)+1).\\n\\t\\t\\t\\t].\\n\\t\\t\\t^ self\\n\\t\\t\\t].\\n\\toffset _ y*rowSize+1.\\n\\tbits _ form bits.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tw _ offset + (x>>2).\\n\\t\\t\\tb _ 3- (x \\\\\\\\ 4) * 8.\\n\\t\\t\\tpixel _ (thisScanline at: x // incX + 1)<<b.\\n\\t\\t\\tmask _ (255<<b) bitInvert32.\\n\\t\\t\\tbits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)\\n\\t\\t].\\n\\t\\t^ self\\n\\t].\\n\\tbitsPerChannel = 1 ifTrue: [\\n\\t\\tpixPerByte _ 8.\\n\\t\\tmask _ 1.\\n\\t\\tshifts _ #(7 6 5 4 3 2 1 0).\\n\\t].\\n\\tbitsPerChannel = 2 ifTrue: [\\n\\t\\tpixPerByte _ 4.\\n\\t\\tmask _ 3.\\n\\t\\tshifts _ #(6 4 2 0).\\n\\t].\\n\\tbitsPerChannel = 4 ifTrue: [\\n\\t\\tpixPerByte _ 2.\\n\\t\\tmask _ 15.\\n\\t\\tshifts _ #(4 0).\\n\\t].\\n\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\tpixelNumber _ 0.\\n\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\trawByte _ thisScanline at: (pixelNumber // pixPerByte) + 1.\\n\\t\\tpixel _ (rawByte >> (shifts at: (pixelNumber \\\\\\\\ pixPerByte) + 1)) bitAnd: mask.\\n\\t\\tblitter pixelAt: (x@y) put: pixel.\\n\\t\\tpixelNumber _ pixelNumber + 1.\\n\\t].\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGrayAlpha: y\\n\\t\\\"Handle non-interlaced grayscale with alpha color mode (colorType = 4)\\\"\\n\\n\\t| i pixel gray b |\\n\\tb _ BitBlt current bitPokerToForm: form.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\t0 to: width-1 do: [ :x |\\n\\t\\t\\t\\ti _ (x << 1) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\t0 to: width-1 do: [ :x |\\n\\t\\t\\t\\ti _ (x << 2) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGrayAlpha: y at: startX by: incX\\n\\t\\\"Handle interlaced grayscale with alpha color mode (colorType = 4)\\\"\\n\\n\\t| i pixel gray b |\\n\\tb _ BitBlt current bitPokerToForm: form.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\ti _ (x // incX << 1) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\ti _ (x // incX << 2) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 1/1/1970 21:00'!\\ncopyPixelsIndexed: y\\n\\t\\\"Handle non-interlaced indexed color mode (colorType = 3)\\\"\\n\\t| hack hackBlt swizzleHack swizzleBlt scanline hackDepth |\\n\\tscanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.\\n\\tscanline replaceFrom: 1 to: thisScanline size with: thisScanline startingAt: 1.\\n\\thackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].\\n\\thack := Form extent: width@1 depth: hackDepth bits: scanline.\\n\\thackBlt := BitBlt toForm: form.\\n\\thackBlt sourceForm: hack.\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@y.\\n\\thackBlt width: width; height: 1.\\n\\n\\t(form depth < 8 and:[bigEndian not]) ifTrue:[\\n\\t\\tswizzleHack := Form new hackBits: scanline.\\n\\t\\tswizzleBlt := BitBlt toForm: swizzleHack.\\n\\t\\tswizzleBlt sourceForm: swizzleHack.\\n\\t\\tswizzleBlt combinationRule: Form over.\\n\\t\\tswizzleBlt colorMap: (StandardSwizzleMaps at: form depth).\\n\\t\\tswizzleBlt copyBits.\\n\\t].\\n\\n\\thackBlt copyBits.! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:23'!\\ncopyPixelsIndexed: y at: startX by: incX\\n\\t\\\"Handle interlaced indexed color mode (colorType = 3)\\\"\\n\\n\\t| offset b bits w pixel mask pixPerByte shifts blitter pixelNumber rawByte |\\n\\toffset _ y*rowSize+1.\\n\\tbits _ form bits.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\tw _ offset + (x>>2).\\n\\t\\t\\t\\tb _ 3 - (x \\\\\\\\ 4) * 8.\\n\\t\\t\\t\\tpixel _ (thisScanline at: x // incX + 1)<<b.\\n\\t\\t\\t\\tmask _ (255<<b) bitInvert32.\\n\\t\\t\\t\\tbits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)].\\n\\t\\t\\t^ self ].\\n\\tbitsPerChannel = 1 ifTrue: [\\n\\t\\tpixPerByte _ 8.\\n\\t\\tmask _ 1.\\n\\t\\tshifts _ #(7 6 5 4 3 2 1 0).\\n\\t].\\n\\tbitsPerChannel = 2 ifTrue: [\\n\\t\\tpixPerByte _ 4.\\n\\t\\tmask _ 3.\\n\\t\\tshifts _ #(6 4 2 0).\\n\\t].\\n\\tbitsPerChannel = 4 ifTrue: [\\n\\t\\tpixPerByte _ 2.\\n\\t\\tmask _ 15.\\n\\t\\tshifts _ #(4 0).\\n\\t].\\n\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\tpixelNumber _ 0.\\n\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\trawByte _ thisScanline at: (pixelNumber // pixPerByte) + 1.\\n\\t\\tpixel _ (rawByte >> (shifts at: (pixelNumber \\\\\\\\ pixPerByte) + 1)) bitAnd: mask.\\n\\t\\tblitter pixelAt: (x@y) put: pixel.\\n\\t\\tpixelNumber _ pixelNumber + 1.\\n\\t].\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/7/2000 09:30'!\\ncopyPixelsRGB: y\\n\\t\\\"Handle non-interlaced RGB color mode (colorType = 2)\\\"\\n\\n\\t| i pixel tempForm tempBits |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tpixel at: 4 put: 16rFF.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti := 1.\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: x put: pixel.\\n\\t\\t\\ti _ i + 3.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti := 1.\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x put: pixel.\\n\\t\\t\\ti _ i + 6.\\n\\t\\t]\\n\\t].\\n\\ttransparentPixelValue ifNotNil: [\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\t(tempBits at: x) = transparentPixelValue ifTrue: [\\n\\t\\t\\t\\ttempBits at: x put: 0.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paint.\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'nk 7/27/2004 17:18'!\\ncopyPixelsRGB: y at: startX by: incX\\n\\t\\\"Handle interlaced RGB color mode (colorType = 2)\\\"\\n\\n\\t| i pixel tempForm tempBits xx loopsToDo |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tpixel at: 4 put: 16rFF.\\n\\tloopsToDo _ width - startX + incX - 1 // incX.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti _ (startX // incX * 3) + 1.\\n\\t\\txx _ startX+1.\\n\\t\\t1 to: loopsToDo do: [ :j |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: xx put: pixel.\\n\\t\\t\\ti _ i + 3.\\n\\t\\t\\txx _ xx + incX.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti _ (startX // incX * 6) + 1.\\n\\t\\txx _ startX+1.\\n\\t\\t1 to: loopsToDo do: [ :j |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: xx put: pixel.\\n\\t\\t\\ti _ i + 6.\\n\\t\\t\\txx _ xx + incX.\\n\\t\\t].\\n\\t].\\n\\ttransparentPixelValue ifNotNil: [\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t(tempBits at: x+1) = transparentPixelValue ifTrue: [\\n\\t\\t\\t\\ttempBits at: x+1 put: 0.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paint.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 2/18/2004 23:58'!\\ncopyPixelsRGBA: y\\n\\t\\\"Handle non-interlaced RGBA color modes (colorType = 6)\\\"\\n\\n\\t| i pixel tempForm tempBits ff |\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\tff := Form extent: width@1 depth: 32 bits: thisScanline.\\n\\t\\tcachedDecoderMap \\n\\t\\t\\tifNil:[cachedDecoderMap := self rgbaDecoderMapForDepth: depth].\\n\\t\\t(BitBlt toForm: form)\\n\\t\\t\\tsourceForm: ff;\\n\\t\\t\\tdestOrigin: 0@y;\\n\\t\\t\\tcombinationRule: Form over;\\n\\t\\t\\tcolorMap: cachedDecoderMap;\\n\\t\\t\\tcopyBits.\\n\\t\\t^self.\\n\\t].\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\ti := -7.\\n\\t0 to: width-1 do: [ :x |\\n\\t\\t\\ti := i + 8.\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+6);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form over.\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'nk 7/27/2004 17:57'!\\ncopyPixelsRGBA: y at: startX by: incX\\n\\t\\\"Handle interlaced RGBA color modes (colorType = 6)\\\"\\n\\n\\t| i pixel tempForm tempBits |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti _ (startX // incX << 2) + 1.\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+3);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t\\t\\ti _ i + 4.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti _ (startX // incX << 3) +1.\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+6);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t\\t\\ti _ i + 8.\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paintAlpha.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 2/19/2004 00:10'!\\nrgbaDecoderMapForDepth: decoderDepth\\n\\tbigEndian ifTrue:[\\n\\t\\tdepth = 16 ifTrue:[\\n\\t\\t\\t\\\"Big endian, 32 -> 16 color mapping.\\\"\\n\\t\\t\\t^ColorMap\\n\\t\\t\\t\\tshifts: #(-17 -14 -11 0)\\n\\t\\t\\t\\tmasks: #(16rF8000000 16rF80000 16rF800 16r00)\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"Big endian, 32 -> 32 color mapping\\\"\\n\\t\\t\\t^ColorMap \\n\\t\\t\\t\\tshifts: #(-8 -8 -8 24) \\n\\t\\t\\t\\tmasks: #(16rFF000000 16rFF0000 16rFF00 16rFF).\\n\\t\\t].\\n\\t].\\n\\tdepth = 16 ifTrue:[\\n\\t\\t\\\"Little endian, 32 -> 16 color mapping.\\\"\\n\\t\\t^ColorMap\\n\\t\\t\\tshifts: #(7 -6 -19 0)\\n\\t\\t\\tmasks: #(16rF8 16rF800 16rF80000 0)\\n\\t] ifFalse:[\\n\\t\\t\\\"Little endian, 32 -> 32 color mapping\\\"\\n\\t\\t^ColorMap \\n\\t\\t\\tshifts: #(-16 0 16 0) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t].! !\\n\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 16:37'!\\nnextPutImage: aForm\\n\\t\\\"Write out the given form. We're keeping it simple here, no interlacing, no filters.\\\"\\n\\t^self nextPutImage: aForm interlace: 0 filter: 0. \\\"no filtering\\\"! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 7/30/2004 17:51'!\\nnextPutImage: aForm interlace: aMethod filter: aFilterType \\n\\t\\\"Note: For now we keep it simple - interlace and filtering are simply ignored\\\"\\n\\n\\t| crcStream |\\n\\tbigEndian := SmalltalkImage current isBigEndian.\\n\\tform := aForm.\\n\\twidth := aForm width.\\n\\theight := aForm height.\\n\\taForm depth <= 8 \\n\\t\\tifTrue: \\n\\t\\t\\t[bitsPerChannel := aForm depth.\\n\\t\\t\\tcolorType := 3.\\n\\t\\t\\tbytesPerScanline := (width * aForm depth + 7) // 8]\\n\\t\\tifFalse: \\n\\t\\t\\t[bitsPerChannel := 8.\\n\\t\\t\\tcolorType := 6.\\n\\t\\t\\tbytesPerScanline := width * 4].\\n\\tself writeFileSignature.\\n\\tcrcStream := WriteStream on: (ByteArray new: 1000).\\n\\tcrcStream resetToStart.\\n\\tself writeIHDRChunkOn: crcStream.\\n\\tself writeChunk: crcStream.\\n\\tform depth <= 8 \\n\\t\\tifTrue: \\n\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\tself writePLTEChunkOn: crcStream.\\n\\t\\t\\tself writeChunk: crcStream.\\n\\t\\t\\tform isColorForm \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\t\\t\\tself writeTRNSChunkOn: crcStream.\\n\\t\\t\\t\\t\\tself writeChunk: crcStream]].\\n\\tform depth = 16 \\n\\t\\tifTrue: \\n\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\tself writeSBITChunkOn: crcStream.\\n\\t\\t\\tself writeChunk: crcStream].\\n\\tcrcStream resetToStart.\\n\\tself writeIDATChunkOn: crcStream.\\n\\tself writeChunk: crcStream.\\n\\tcrcStream resetToStart.\\n\\tself writeIENDChunkOn: crcStream.\\n\\tself writeChunk: crcStream! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 2/17/2004 16:51'!\\nupdateCrc: oldCrc from: start to: stop in: aCollection\\n\\t^ZipWriteStream updateCrc: oldCrc from: start to: stop in: aCollection! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'BG 3/16/2005 08:26'!\\nwriteChunk: crcStream\\n\\t| bytes length crc debug |\\n\\tdebug _ self debugging.\\n\\tbytes := crcStream originalContents.\\n\\tlength := crcStream position.\\n\\tcrc := self updateCrc: 16rFFFFFFFF from: 1 to: length in: bytes.\\n\\tcrc := crc bitXor: 16rFFFFFFFF.\\n\\tdebug ifTrue: [ Transcript cr;\\n\\t\\tprint: stream position; space;\\n\\t\\tnextPutAll: (bytes copyFrom: 1 to: 4) asString;\\n\\t\\tnextPutAll: ' len='; print: length;\\n\\t\\tnextPutAll: ' crc=0x'; nextPutAll: crc printStringHex ].\\n\\tstream nextNumber: 4 put: length-4. \\\"exclude chunk name\\\"\\n\\tstream next: length putAll: bytes startingAt: 1.\\n\\tstream nextNumber: 4 put: crc.\\n\\tdebug ifTrue: [ Transcript nextPutAll: ' afterPos='; print: stream position ].\\n\\tcrcStream resetToStart.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 16:40'!\\nwriteFileSignature\\n\\tstream nextPutAll: #(16r89 16r50 16r4E 16r47 16r0D 16r0A 16r1A 16r0A) asByteArray! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 2/17/2004 14:57'!\\nwriteIDATChunkOn: aStream\\n\\t\\\"Write the IDAT chunk\\\"\\n\\t| z |\\n\\taStream nextPutAll: 'IDAT' asByteArray.\\n\\tz _ ZLibWriteStream on: aStream.\\n\\tform depth <= 8 \\n\\t\\tifTrue:[self writeType3DataOn: z]\\n\\t\\tifFalse:[ self writeType6DataOn: z].\\n\\tself debugging ifTrue: [\\n\\t\\tTranscript cr;\\n\\t\\t\\tnextPutAll: 'compressed size=';\\n\\t\\t\\tprint: aStream position;\\n\\t\\t\\tnextPutAll: ' uncompressed size=';\\n\\t\\t\\tprint: z position ]\\n! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:08'!\\nwriteIENDChunkOn: aStream\\n\\t\\\"Write the IEND chunk\\\"\\n\\taStream nextPutAll: 'IEND' asByteArray.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:21'!\\nwriteIHDRChunkOn: aStream\\n\\t\\\"Write the IHDR chunk\\\"\\n\\taStream nextPutAll: 'IHDR' asByteArray.\\n\\taStream nextInt32Put: width.\\n\\taStream nextInt32Put: height.\\n\\taStream nextNumber: 1 put: bitsPerChannel.\\n\\taStream nextNumber: 1 put: colorType.\\n\\taStream nextNumber: 1 put: 0. \\\"compression\\\"\\n\\taStream nextNumber: 1 put: 0. \\\"filter method\\\"\\n\\taStream nextNumber: 1 put: 0. \\\"interlace method\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 4/17/2004 19:44'!\\nwritePLTEChunkOn: aStream\\n\\t\\\"Write the PLTE chunk\\\"\\n\\t| r g b colors |\\n\\taStream nextPutAll: 'PLTE' asByteArray.\\n\\t(form isColorForm) \\n\\t\\tifTrue:[colors := form colors]\\n\\t\\tifFalse:[colors := Color indexedColors copyFrom: 1 to: (1 bitShift: form depth)].\\n\\tcolors do:[:aColor|\\n\\t\\tr := (aColor red * 255) truncated.\\n\\t\\tg := (aColor green * 255) truncated.\\n\\t\\tb := (aColor blue * 255) truncated.\\n\\t\\taStream nextPut: r; nextPut: g; nextPut: b.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 18:29'!\\nwriteSBITChunkOn: aStream\\n\\t\\\"Write the IDAT chunk\\\"\\n\\taStream nextPutAll: 'sBIT' asByteArray.\\n\\tform depth = 16 ifFalse:[self error: 'Unimplemented feature'].\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 1.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:34'!\\nwriteTRNSChunkOn: aStream\\n\\t\\\"Write out tRNS chunk\\\"\\n\\taStream nextPutAll: 'tRNS' asByteArray.\\n\\tform colors do:[:aColor|\\n\\t\\taStream nextPut: (aColor alpha * 255) truncated.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 1/1/1970 20:58'!\\nwriteType3DataOn: zStream\\n\\t\\\"Write color indexed data.\\\"\\n\\t| scanline hack hackBlt swizzleBlt swizzleHack hackDepth |\\n\\tscanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.\\n\\thackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].\\n\\thack := Form extent: width@1 depth: hackDepth bits: scanline.\\n\\thackBlt := BitBlt toForm: hack.\\n\\thackBlt sourceForm: form.\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@0.\\n\\thackBlt width: width; height: 1.\\n\\t(form depth < 8 and:[bigEndian not]) ifTrue:[\\n\\t\\tswizzleHack := Form new hackBits: scanline.\\n\\t\\tswizzleBlt := BitBlt toForm: swizzleHack.\\n\\t\\tswizzleBlt sourceForm: swizzleHack.\\n\\t\\tswizzleBlt combinationRule: Form over.\\n\\t\\tswizzleBlt colorMap: (StandardSwizzleMaps at: form depth).\\n\\t].\\n\\t0 to: height-1 do:[:i|\\n\\t\\thackBlt sourceOrigin: 0@i; copyBits.\\n\\t\\tswizzleBlt ifNotNil:[swizzleBlt copyBits].\\n\\t\\tzStream nextPut: 0. \\\"filterType\\\"\\n\\t\\tzStream next: bytesPerScanline putAll: scanline startingAt: 1.\\n\\t].\\n\\tzStream close.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 2/19/2004 00:10'!\\nwriteType6DataOn: zStream\\n\\t\\\"Write RGBA data.\\\"\\n\\t| scanline hack hackBlt cm miscBlt |\\n\\tscanline := ByteArray new: bytesPerScanline.\\n\\thack := Form extent: width@1 depth: 32 bits: scanline.\\n\\tform depth = 16 ifTrue:[\\n\\t\\t\\\"Expand 16 -> 32\\\"\\n\\t\\tmiscBlt := BitBlt toForm: hack.\\n\\t\\tmiscBlt sourceForm: form.\\n\\t\\tmiscBlt combinationRule: Form over.\\n\\t\\tmiscBlt destOrigin: 0@0.\\n\\t\\tmiscBlt width: width; height: 1.\\n\\t].\\n\\thackBlt := BitBlt toForm: hack.\\n\\thackBlt sourceForm: (miscBlt ifNil:[form] ifNotNil:[hack]).\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@0.\\n\\thackBlt width: width; height: 1.\\n\\tbigEndian ifTrue:[\\n\\t\\tcm := ColorMap \\n\\t\\t\\tshifts: #(8 8 8 -24) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t] ifFalse:[\\n\\t\\tcm := ColorMap \\n\\t\\t\\tshifts: #(-16 0 16 0) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t].\\n\\thackBlt colorMap: cm.\\n\\t0 to: height-1 do:[:i|\\n\\t\\tmiscBlt ifNil:[\\n\\t\\t\\thackBlt sourceOrigin: 0@i; copyBits.\\n\\t\\t] ifNotNil:[\\n\\t\\t\\tmiscBlt sourceOrigin: 0@i; copyBits.\\n\\t\\t\\thack fixAlpha.\\n\\t\\t\\thackBlt copyBits.\\n\\t\\t].\\n\\t\\tzStream nextPut: 0. \\\"filterType\\\"\\n\\t\\tzStream nextPutAll: scanline.\\n\\t].\\n\\tzStream close.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPNGReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'ar 2/11/2004 00:54'!\\ncomputeSwizzleMapForDepth: depth\\n\\t\\\"Answer a map that maps pixels in a word to their opposite location. Used for 'middle-endian' forms where the byte-order is different from the bit order (good joke, eh?).\\\"\\n\\t| map swizzled |\\n\\tmap := Bitmap new: 256.\\n\\tdepth = 4 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 15) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 15) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\n\\tdepth = 2 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 3) bitShift: 6).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 3) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 3) bitShift: 2).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 3) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\n\\tdepth = 1 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 1) bitShift: 7).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -1) bitAnd: 1) bitShift: 6).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 1) bitShift: 5).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -3) bitAnd: 1) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 1) bitShift: 3).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -5) bitAnd: 1) bitShift: 2).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 1) bitShift: 1).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -7) bitAnd: 1) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\tself error: 'Unrecognized depth'! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:22'!\\ncreateAFormFrom: data\\n\\n\\t| error f |\\n\\n\\terror _ ''.\\n\\tf _ [\\n\\t\\tself formFromStream: (RWBinaryOrTextStream with: data)\\n\\t] ifError: [ :a :b |\\n\\t\\terror _ a printString,' ',b printString.\\n\\t\\t(StringMorph contents: error) color: Color red; imageForm\\n\\t].\\n\\t^{f. error}! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:20'!\\ndebugging: aBoolean\\n\\n\\tDebugging _ aBoolean! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'ar 2/11/2004 00:55'!\\ninitialize\\n\\t\\\"\\n\\tPNGReadWriter initialize\\n\\t\\\"\\n\\n\\tBPP _ {\\t#(1 2 4 8 16).\\n\\t\\t\\t#(0 0 0 0 0).\\n\\t\\t\\t#(0 0 0 24 48).\\n\\t\\t\\t#(1 2 4 8 0).\\n\\t\\t\\t#(0 0 0 16 32).\\n\\t\\t\\t#(0 0 0 0 0).\\n\\t\\t\\t#(0 0 0 32 64).\\n\\t\\t\\t#(0 0 0 0 0) }.\\n\\n\\tBlockHeight _ #(8 8 4 4 2 2 1).\\n\\tBlockWidth _ #(8 4 4 2 2 1 1).\\n\\n\\tStandardColors := Color indexedColors collect:[:aColor|\\n\\t\\tColor \\n\\t\\t\\tr: (aColor red * 255) truncated / 255\\n\\t\\t\\tg: (aColor green * 255) truncated / 255\\n\\t\\t\\tb: (aColor blue * 255) truncated / 255.\\n\\t].\\n\\n\\tStandardSwizzleMaps := Array new: 4.\\n\\t#(1 2 4) do:[:i| StandardSwizzleMaps at: i put: (self computeSwizzleMapForDepth: i)].! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:15'!\\ninsertMorph: aMorph named: aString into: aBook\\n\\n\\t| newPage |\\n\\n\\taBook ifNil: [^self].\\n\\tnewPage _ aBook insertPageLabel: aString morphs: {aMorph}.\\n\\tnewPage color: Color lightYellow.\\n\\tnewPage extent: (\\n\\t\\tnewPage submorphs inject: 10@10 into: [ :ex :m |\\n\\t\\t\\tm left: 10.\\n\\t\\t\\tex max: m width @ m bottom\\n\\t\\t]\\n\\t) + (20@20).\\n! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 12/10/2000 10:11'!\\ntest1\\n\\\"PNGReadWriter test1\\\"\\n\\t| data t error d0 d1 f fileInfo book result d2 |\\n\\n\\tDebugging _ true.\\n\\t1 = 1 ifTrue: [\\n\\t\\tbook _ BookMorph new.\\n\\t\\tbook setProperty: #transitionSpec toValue: {'silence'. #none. #none}.\\n\\t].\\n\\td0 _ FileDirectory default.\\n\\td1 _ d0 directoryNamed: 'PngSuite Folder'.\\n\\td2 _ d0 directoryNamed: 'BIG PNG'.\\n\\t{d0. d1. d2}.\\t\\t\\\"keep compiler quiet\\\"\\n\\\"==\\ncitrus_none_sub.png\\ncitrus_adm7_adap.png\\ncitrus_adm7_aver.png\\ncitrus_adm7_non.png\\ncitrus_adm7_paeth.png\\npngs-img-ie5mac.png\\n==\\\"\\n\\tfileInfo _ {\\n\\t\\td2. {'citrus_adm7_adap.png'}.\\n\\t\\t\\\"d1. d1 fileNames.\\\"\\n\\t}.\\n\\tfileInfo pairsDo: [ :dir :fileNames |\\n\\t\\tfileNames do: [ :each |\\n\\t\\t\\tTranscript cr; show: each.\\n\\t\\t\\tdata _ (dir fileNamed: each) contentsOfEntireFile.\\n\\t\\t\\terror _ ''.\\n\\t\\t\\tMessageTally spyOn: [\\n\\t\\t\\t\\tt _ [\\n\\t\\t\\t\\t\\tresult _ self createAFormFrom: data.\\n\\t\\t\\t\\t\\tf_ result first.\\n\\t\\t\\t\\t\\terror _ result second.\\n\\t\\t\\t\\t] timeToRun.].\\n\\t\\t\\tself insertMorph: f asMorph named: each into: book.\\n\\t\\t\\tTranscript show: each,' ',data size printString,' = ',t printString,' ms',error; cr.\\n\\t\\t].\\n\\t].\\n\\tbook ifNotNil: [book openInWorld].\\n\\tDebugging _ false.! !\\n\\n\\n!PNGReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:57'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('png')! !\\nTestCase subclass: #PNGReadWriterTest\\n\\tinstanceVariableNames: 'fileName'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'GraphicsTests-Files'!\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/11/2004 00:42'!\\ndrawStuffOn: aForm\\n\\t\\\"Draw stuff on aForm. Avoid any symmetry.\\\"\\n\\t| canvas |\\n\\tcanvas := FormCanvas on: aForm.\\n\\tcanvas frameAndFillRectangle: (1@1 corner: aForm extent - 15) fillColor: Color red borderWidth: 3 borderColor: Color green.\\n\\tcanvas fillOval: (aForm boundingBox topRight - (15@-5) extent: 20@20) color: Color blue borderWidth: 1 borderColor: Color white.\\n\\t^aForm\\n\\t\\\"(PNGReadWriterTest new drawStuffOn: (Form extent: 32@32 depth: 16)) display\\\"! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/11/2004 00:42'!\\ndrawTransparentStuffOn: aForm\\n\\t\\\"Draw stuff on aForm. Avoid any symmetry.\\\"\\n\\t| canvas |\\n\\tcanvas := FormCanvas on: aForm.\\n\\tcanvas frameAndFillRectangle: (1@1 corner: aForm extent - 15) fillColor: (Color red alpha: 0.25) borderWidth: 3 borderColor: (Color green alpha: 0.5).\\n\\tcanvas fillOval: (aForm boundingBox topRight - (15@-5) extent: 20@20) color: (Color white alpha: 0.75) borderWidth: 1 borderColor: Color blue.\\n\\t^aForm\\n\\t\\\"(PNGReadWriterTest new drawStuffOn: (Form extent: 32@32 depth: 16)) display\\\"! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 4/17/2004 19:45'!\\nencodeAndDecode: original\\n\\t\\\"Make sure that the given form is encoded and decoded correctly\\\"\\n\\t| stream bytes decoded maxErr |\\n\\t\\\"encode\\\"\\n\\tstream := ByteArray new writeStream.\\n\\t(PNGReadWriter on: stream) nextPutImage: original; close.\\n\\tbytes := stream contents.\\n\\n\\tself writeEncoded: bytes.\\n\\n\\t\\\"decode\\\"\\n\\tstream := self readEncoded: bytes.\\n\\tdecoded := (PNGReadWriter new on: stream) nextImage.\\n\\tdecoded display.\\n\\n\\t\\\"compare\\\"\\n\\tself assert: original width = decoded width.\\n\\tself assert: original height = decoded height.\\n\\tself assert: original depth = decoded depth.\\n\\tself assert: original bits = decoded bits.\\n\\tself assert: original class == decoded class.\\n\\t(original isColorForm) ifTrue:[\\n\\t\\toriginal colors with: decoded colors do:[:c1 :c2|\\n\\t\\t\\t\\\"we must round here due to encoding errors\\\"\\n\\t\\t\\tmaxErr := 1. \\\"max. error for 8bit rgb component\\\"\\n\\t\\t\\tself assert: ((c1 red * 255) truncated - (c2 red * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 green * 255) truncated - (c2 green * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 blue * 255) truncated - (c2 blue * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 alpha * 255) truncated - (c2 alpha * 255) truncated) abs <= maxErr.\\n\\t\\t].\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:49'!\\nencodeAndDecodeAlpha: original\\n\\tfileName := 'testAlpha', original depth printString,'.png'.\\n\\tself encodeAndDecode: original.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/18/2004 23:49'!\\nencodeAndDecodeColor: aColor depth: aDepth\\n\\t| aForm |\\n\\tfileName := 'testColor', aColor name, aDepth printString,'.png'.\\n\\taForm := Form extent: 32@32 depth: aDepth.\\n\\taForm fillColor: aColor.\\n\\tself encodeAndDecode: aForm.\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:02'!\\nencodeAndDecodeDisplay: depth\\n\\t| form |\\n\\tfileName := 'testDisplay', depth printString,'.png'.\\n\\tform := Form extent: (Display extent min: 560@560) depth: depth.\\n\\tSmalltalk isMorphic \\n\\t\\tifTrue:[World fullDrawOn: form getCanvas]\\n\\t\\tifFalse:[Display displayOn: form].\\n\\tself encodeAndDecode: form.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:50'!\\nencodeAndDecodeForm: original\\n\\tfileName := 'testForm', original depth printString,'.png'.\\n\\tself encodeAndDecode: original.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 4/17/2004 19:45'!\\nencodeAndDecodeReverse: original\\n\\t\\\"Make sure that the given form is encoded and decoded correctly\\\"\\n\\t| stream bytes decoded maxErr reversed |\\n\\tfileName := 'testReverse', original depth printString,'.png'.\\n\\tself assert: original class == Form. \\\"won't work with ColorForm\\\"\\n\\t\\\"Switch pixel order\\\"\\n\\treversed := Form extent: original extent depth: original depth negated.\\n\\toriginal displayOn: reversed.\\n\\tself assert: original width = reversed width.\\n\\tself assert: original height = reversed height.\\n\\tself assert: original depth = reversed depth.\\n\\tself deny: original nativeDepth = reversed nativeDepth.\\n\\toriginal depth = 32\\n\\t\\tifTrue:[self assert: original bits = reversed bits]\\n\\t\\tifFalse:[self deny: original bits = reversed bits].\\n\\n\\t\\\"encode\\\"\\n\\tstream := ByteArray new writeStream.\\n\\t(PNGReadWriter on: stream) nextPutImage: reversed; close.\\n\\tbytes := stream contents.\\n\\tself writeEncoded: bytes.\\n\\n\\t\\\"decode\\\"\\n\\tstream := bytes readStream.\\n\\tdecoded := (PNGReadWriter new on: stream) nextImage.\\n\\tdecoded display.\\n\\n\\t\\\"compare\\\"\\n\\tself assert: original width = decoded width.\\n\\tself assert: original height = decoded height.\\n\\tself assert: original depth = decoded depth.\\n\\tself assert: original bits = decoded bits.\\n\\tself assert: original class == decoded class.\\n\\t(original isColorForm) ifTrue:[\\n\\t\\toriginal colors with: decoded colors do:[:c1 :c2|\\n\\t\\t\\t\\\"we must round here due to encoding errors\\\"\\n\\t\\t\\tmaxErr := 1. \\\"max. error for 8bit rgb component\\\"\\n\\t\\t\\tself assert: ((c1 red * 255) truncated - (c2 red * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 green * 255) truncated - (c2 green * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 blue * 255) truncated - (c2 blue * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 alpha * 255) truncated - (c2 alpha * 255) truncated) abs <= maxErr.\\n\\t\\t].\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 18:18'!\\nencodeAndDecodeStream: file\\n\\t| aForm |\\n\\tfile reset.\\n\\t(PNGReadWriter new on: file) understandsImageFormat ifFalse:[^self error: 'don''t understand format!!' ].\\n\\tfile reset.\\n\\taForm := (PNGReadWriter new on: file) nextImage.\\n\\taForm ifNil:[^self error: 'nil form' ].\\n\\taForm display.\\n\\tself encodeAndDecode: aForm.\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:36'!\\nencodeAndDecodeWithColors: aColorForm\\n\\t\\\"Screw around with aColorForm colors\\\"\\n\\t| colors nColors indexedColors max myRandom |\\n\\tfileName := 'testColors', aColorForm depth printString,'.png'.\\n\\tindexedColors := Color indexedColors.\\n\\tnColors := 1 bitShift: aColorForm depth.\\n\\tcolors := WriteStream on: Array new.\\n\\n\\t\\\"Make first half translucent\\\"\\n\\tmax := nColors // 2.\\n\\t1 to: max do:[:i|\\n\\t\\tcolors nextPut: ((indexedColors at: i) alpha: i / max asFloat).\\n\\t].\\n\\n\\t\\\"Make random choices for second half\\\"\\n\\tmyRandom := Random seed: 42315.\\n\\tmax to: nColors do:[:i|\\n\\t\\tcolors nextPut: (indexedColors atRandom: myRandom).\\n\\t].\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/29/2004 03:55'!\\nencodeAndDecodeWithError: aStream\\n\\tself should:[self encodeAndDecodeStream: aStream] raise: Error! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:10'!\\nreadEncoded: bytes\\n\\t\\\"Answer a ReadStream on the file named by fileName, if possible; else a ReadStream on bytes\\\"\\n\\n\\tfileName ifNil:[^ bytes readStream ].\\n\\t^(FileStream oldFileOrNoneNamed: fileName) ifNil: [ \\n\\t\\tTranscript nextPutAll: 'can''t open ', fileName; cr.\\n\\t\\tbytes readStream ].\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:45'!\\nsetUp\\n\\tfileName := nil.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:29'!\\ntearDown\\n\\tWorld changed.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:51'!\\nwriteEncoded: bytes\\n\\t| file |\\n\\tfileName ifNil:[^self].\\n\\tfalse ifTrue:[^self].\\n\\tfile := FileStream forceNewFileNamed: fileName.\\n\\t[file nextPutAll: bytes] ensure:[file close].! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest16Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 16))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest16BitDisplay\\n\\tself encodeAndDecodeDisplay: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest16BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 16))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest1Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:43'!\\ntest1BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest1BitDisplay\\n\\tself encodeAndDecodeDisplay: 1! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest1BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest2Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:43'!\\ntest2BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest2BitDisplay\\n\\tself encodeAndDecodeDisplay: 2! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest2BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest32Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest32BitDisplay\\n\\tself encodeAndDecodeDisplay: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest32BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest4Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:44'!\\ntest4BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest4BitDisplay\\n\\tself encodeAndDecodeDisplay: 4! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest4BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest8Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:44'!\\ntest8BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest8BitDisplay\\n\\tself encodeAndDecodeDisplay: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest8BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:49'!\\ntestAlphaCoding\\n\\tself encodeAndDecodeAlpha: (self drawTransparentStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/29/2004 03:55'!\\ntestPngSuite\\n\\t\\\"Requires the suite from \\n\\t\\tftp://swrinde.nde.swri.edu/pub/png/images/suite/PngSuite.zip\\n\\tto be present as PngSuite.zip\\\"\\n\\t| file zip entries |\\n\\t[file := FileStream readOnlyFileNamed: 'PngSuite.zip'] on: Error do:[:ex| ex return].\\n\\tfile ifNil:[^self].\\n\\t[zip := ZipArchive new readFrom: file.\\n\\tentries := zip members select:[:mbr| mbr fileName asLowercase endsWith: '.png'].\\n\\tentries do:[:mbr| \\n\\t\\t(mbr fileName asLowercase first = $x)\\n\\t\\t\\tifTrue: [self encodeAndDecodeWithError: mbr contentStream ]\\n\\t\\t\\tifFalse: [self encodeAndDecodeStream: mbr contentStream ] ].\\n\\t] ensure:[file close].! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack16\\n\\tself encodeAndDecodeColor: Color blue depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack32\\n\\tself encodeAndDecodeColor: Color blue depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack8\\n\\tself encodeAndDecodeColor: Color blue depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue16\\n\\tself encodeAndDecodeColor: Color blue depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue32\\n\\tself encodeAndDecodeColor: Color blue depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue8\\n\\tself encodeAndDecodeColor: Color blue depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestGreen16\\n\\tself encodeAndDecodeColor: Color green depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestGreen32\\n\\tself encodeAndDecodeColor: Color green depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestGreen8\\n\\tself encodeAndDecodeColor: Color green depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestRed16\\n\\tself encodeAndDecodeColor: Color red depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:48'!\\ntestRed32\\n\\tself encodeAndDecodeColor: Color red depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestRed8\\n\\tself encodeAndDecodeColor: Color red depth: 8! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:25'!\\ncoloredFiles16\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 16.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{Color red-> \\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADZJ\\nREFUeF7lziEBAAAMAjD6J8b9MRAT80uT65Af8AN+wA/4AT/gB/yAH/ADfsAP+AE/4AfmgQdc\\nz9xqBS2pdAAAAABJRU5ErkJggg=='.\\n\\tColor green->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjD6J77jMRAT80sunfIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA68HyT\\n3Gqf2I6NAAAAAElFTkSuQmCC'.\\n\\t\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjD6J77jMRAT80ty3fIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA48JxX\\n3GpYhihrAAAAAElFTkSuQmCC'.\\n\\tColor black->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjDk+xfmMRAT80ty3fIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA48LbT\\nHD3MKH3GAAAAAElFTkSuQmCC'\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:24'!\\ncoloredFiles32\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 32.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{\\n\\t\\tColor red -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANUlEQVR4XuXOIQEAAAwEoe9f\\n+hZjAoFnbfVo+QE/4Af8gB/wA37AD/gBP+AH/IAf8AN+4DlwVA34ajP6EEoAAAAASUVORK5C\\nYII='.\\n\\t\\tColor green -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAM0lEQVR4XuXOMQ0AAAACIPuX\\n1hgejAIkPfMDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA7MFfR+Grvv2BdAAAAAElFTkSuQmCC'.\\n\\n\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANElEQVR4XuXOIQEAAAACIP+f\\n1hkGAp0k7Zcf8AN+wA/4AT/gB/yAH/ADfsAP+AE/4AfOgQFblfhqnnPWHAAAAABJRU5ErkJg\\ngg=='.\\n\\t\\tColor black -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANUlEQVR4XuXOMQEAAAwCINc/\\ntIvhwcFPkuuWH/ADfsAP+AE/4Af8gB/wA37AD/gBP+AHxoEH95UAPU59TTMAAAAASUVORK5C\\nYII='\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:19'!\\ncoloredFiles8\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 8.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{Color red->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGklEQVR4XmO4cwc/YLgz8hWMfAUjX8EIVQAAbnlwLukXXkcAAAAASUVORK5CYII='.\\n\\n\\tColor green->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmPQ1cUPGHRHvoKRr2DkKxihCgBZ3bQBCq5u/AAAAABJRU5ErkJggg=='.\\n\\n\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmNwc8MPGNxGvoKRr2DkKxihCgCl7xgQRbPxcwAAAABJRU5ErkJggg=='.\\n\\n\\tColor black->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmNgZMQPGBhHvoKRr2DkKxihCgBEmAQBphO0cAAAAABJRU5ErkJggg=='\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:25'!\\ndecodeColors: colorsAndFiles depth: requiredDepth\\n\\t| color bytes form |\\n\\tcolorsAndFiles do:[:assoc|\\n\\t\\tcolor := assoc key.\\n\\t\\tbytes := Base64MimeConverter mimeDecodeToBytes: assoc value readStream.\\n\\t\\tform := PNGReadWriter formFromStream: bytes.\\n\\t\\tself assert: form depth = requiredDepth.\\n\\t\\tself assert: (form pixelValueAt: 1@1) = (color pixelValueForDepth: requiredDepth).\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:30'!\\nencodeColors: colorsAndFiles depth: requiredDepth\\n\\t| color original ff encoded |\\n\\tcolorsAndFiles do:[:assoc|\\n\\t\\tcolor := assoc key.\\n\\t\\toriginal := Base64MimeConverter mimeDecodeToBytes: assoc value readStream.\\n\\t\\tff := Form extent: 32@32 depth: requiredDepth.\\n\\t\\tff fillColor: color.\\n\\t\\tencoded := WriteStream on: ByteArray new.\\n\\t\\tPNGReadWriter putForm: ff onStream: encoded.\\n\\t\\tself assert: (encoded contents = original contents).\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors16\\n\\tself decodeColors: self coloredFiles16 depth: 16.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors32\\n\\tself decodeColors: self coloredFiles32 depth: 32.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors8\\n\\tself decodeColors: self coloredFiles8 depth: 8.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors16\\n\\tself encodeColors: self coloredFiles16 depth: 16.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors32\\n\\tself encodeColors: self coloredFiles32 depth: 32.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors8\\n\\tself encodeColors: self coloredFiles8 depth: 8.! !\\nImageReadWriter subclass: #PNMReadWriter\\n\\tinstanceVariableNames: 'first type origin cols rows depth maxValue tupleType pragma'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n!PNMReadWriter commentStamp: 'jdr 10/20/2003 17:08' prior: 0!\\nI am a subclass of ImageReadWriter that decodes portable anymap file formats\\n(pbm, pgm, ppm and pam) images.\\n\\nI accept the #origin pragma for SE files as described in:\\nAlgoritms For Image Processing And Computer Vision. J. R. Parker\\n\\nDon't work with 2 bytes samples (16 bit grays, > 32 bits color, etc...), \\npam files preliminary support.\\n\\nf _ ImageReadWriter formFromFileNamed: 'Tools:Squeak3.4:Carmen.ppm'.\\nf morphEdit\\n\\nSubmitted by Javier Diaz Reinoso, Oct/2003!\\n]style[(361 18 2 26 3 11 1 43)f1,cblack;f1,f1b,f1,f1b,f1,f1b,f1!\\n\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/16/2003 14:52'!\\norigin\\n\\t^origin! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/15/2003 15:35'!\\npragma: s\\n\\tpragma _ s! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/10/2003 18:04'!\\nstream: s\\n\\tstream _ s! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/16/2003 14:53'!\\ntupleType\\n\\t^tupleType! !\\n\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 17:19'!\\ncleanLine\\n\\t\\\"upTo LF or CR, tab as space\\\"\\n\\n\\t| line loop b |\\n\\tline _ WriteStream with: ''.\\n\\tloop _ true.\\n\\t[loop] whileTrue: [\\n\\t\\tb _ stream next.\\n\\t\\tb ifNil:[\\n\\t\\t\\tloop _ false\\t\\t\\\"EOS\\\"\\n\\t\\t]\\n\\t\\tifNotNil: [\\n\\t\\t\\t(b = (Character cr) or:[b = Character lf]) ifTrue:[\\n\\t\\t\\t\\tloop _ false.\\n\\t\\t\\t]\\n\\t\\t\\tifFalse:[\\n\\t\\t\\t\\tb = (Character tab) ifTrue:[b _ Character space].\\n\\t\\t\\t\\tline nextPut: b.\\n\\t\\t\\t]\\n\\t\\t]\\n\\t].\\n\\t^line contents! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:20'!\\ngetTokenPbm: aCollection\\n\\t\\\"get a number, return rest of collection\\\"\\n\\t| line tokens token |\\n\\ttokens _ aCollection.\\n\\ttokens size = 0 ifTrue:[\\n\\t\\t[\\n\\t\\t\\tline _ self pbmGetLine.\\n\\t\\t\\tline ifNil:[^{nil . nil}].\\n\\t\\t\\ttokens _ line findTokens: ' '.\\n\\t\\t\\ttokens size = 0\\n\\t\\t] whileTrue:[].\\n\\t].\\n\\t\\\"Transcript cr; show: tokens asString.\\\"\\n\\ttoken _ tokens removeFirst.\\n\\t^{token asInteger . tokens}\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 16:39'!\\nnextImage\\n\\t\\\"read one image\\\"\\n\\t| data p |\\n\\tfirst ifNil:[\\n\\t\\tfirst _ false.\\n\\t\\tdata _ stream contentsOfEntireFile.\\n\\t\\tstream _ (RWBinaryOrTextStream with: data) reset.\\n\\t]\\n\\tifNotNil:[\\n\\t\\ttype < 4 ifTrue:[\\n\\t\\t\\tself error:'Plain PBM, PGM or PPM have only one image'\\n\\t\\t].\\n\\t].\\n\\tstream ascii.\\n\\tp _ stream next.\\n\\ttype _ (stream next) asInteger - 48.\\n\\t(p = $P and:[type > 0 and:[type < 8]]) ifFalse:[\\n\\t\\tself error:'Not a PNM file'\\n\\t].\\n\\ttype = 7 ifTrue:[\\n\\t\\tself readHeaderPAM\\n\\t]\\n\\tifFalse: [\\n\\t\\tself readHeader\\n\\t].\\n\\ttype caseOf: {\\n\\t\\t[1] \\t->\\t[^self readPlainBW].\\n\\t\\t[2] \\t->\\t[^self readPlainGray].\\n\\t\\t[3] \\t->\\t[^self readPlainRGB].\\n\\t\\t[4] \\t->\\t[^self readBWreverse: false].\\n\\t\\t[5] \\t->\\t[^self readGray].\\n\\t\\t[6] \\t->\\t[^self readRGB].\\n\\t\\t[7] \\t->\\t[\\t\\\"PAM\\\"\\n\\t\\t\\t\\t\\t(tupleType asUppercase) caseOf: {\\n\\t\\t\\t\\t\\t\\t['BLACKANDWHITE'] \\t\\t-> [^self readBWreverse: true].\\n\\t\\t\\t\\t\\t\\t['GRAYSCALE'] \\t\\t\\t-> [^self readGray].\\n\\t\\t\\t\\t\\t\\t['RGB'] \\t\\t\\t\\t\\t-> [^self readRGB].\\n\\t\\t\\t\\t\\t\\t['RGB_ALPHA'] \\t\\t\\t-> [^self error:'Not implemented'].\\n\\t\\t\\t\\t\\t\\t['GRAYSCALE_ALPHA'] \\t-> [^self error:'Not implemented'].\\n\\t\\t\\t\\t\\t} otherwise: [^self readData].\\n\\t\\t\\t\\t]\\n\\t}! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/10/2003 15:09'!\\npbmGetLine\\n\\t\\\"Get the next non-comment line from the PBM stream\\n\\tLook for 'pragmas' - commands hidden in the comments\\\"\\n\\t\\n \\t| line |\\n\\t[\\n\\t\\tline _ self cleanLine.\\n\\t\\tline ifNil: [^nil].\\n\\t\\t(line size > 0 and:[(line at: 1) = $#]) ifTrue:[\\n\\t\\t\\tself pbmParam: line.\\n\\t\\t].\\n\\t\\t(line size = 0) or:[(line at: 1) = $#]\\n\\t]\\n \\twhileTrue: [].\\n\\t^line! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/10/2003 15:11'!\\npbmParam: line\\n\\t\\\"Look for a parameter hidden in a comment\\\"\\n\\t| key tokens |\\n\\ttokens _ line findTokens: ' '.\\n\\tkey _ (tokens at: 1) asLowercase.\\n\\t(key = '#origin' and:[tokens size = 3]) ifTrue:[\\t\\\"ORIGIN key word\\\"\\n\\t\\t\\\"This is for SE files as described in:\\n\\t\\tAlgoritms For Image Processing And Computer Vision. J. R. Parker\\\"\\n\\t\\torigin _ ((tokens at: 2) asInteger) @ ((tokens at: 3) asInteger)\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 7/18/2005 17:02'!\\nr: r g: g b: b for: aDepth\\n\\t\\\"integer value according depth\\\"\\n\\t| val |\\n\\taDepth = 16 ifTrue: [\\n\\t\\tval := (1 << 15) + (r << 10) + (g << 5) + b.\\n\\t]\\n\\tifFalse:[\\n\\t\\tval := (16rFF << 24) + (r << 16) + (g << 8) + b.\\n\\t].\\n\\t^val\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:49'!\\nreadBWreverse: flagXor\\n\\t\\\"B&W for PAM\\\"\\n\\t| val form bytesRow nBytes |\\n\\tstream binary.\\n\\tform _ Form extent: cols@rows depth: 1.\\n\\tnBytes _ (cols/8) ceiling.\\n\\tbytesRow _ (cols/32) ceiling * 4.\\n\\t0 to: rows-1 do: [:y | | i |\\n\\t\\ti _ 1 + (bytesRow*y).\\n\\t\\t0 to: nBytes-1 do: [:x |\\n\\t\\t\\tval _ stream next.\\n\\t\\t\\tflagXor ifTrue:[val _ val bitXor: 16rFF].\\n\\t\\t\\tform bits byteAt: i put: val.\\n\\t\\t\\ti _ i+1.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'md 10/20/2004 15:45'!\\nreadData\\n\\t\\\"generic data\\\"\\n\\t| data nBits nBytes val sample |\\n\\tstream binary.\\n\\tdata _ OrderedCollection new.\\n\\tnBits _ maxValue floorLog:2.\\n\\tnBytes _ (nBits+1) >> 3.\\n\\t(nBits+1 rem: 8) > 0 ifTrue:[nBytes _ nBytes+1].\\n\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ 0.\\n\\t\\t\\t1 to: nBytes do: [:n |\\n\\t\\t\\t\\tsample _ stream next.\\n\\t\\t\\t\\tval _ val << 8 + sample.\\n\\t\\t\\t].\\n\\t\\t\\tdata add: val.\\n\\t\\t]\\n\\t].\\n\\t^data\\n\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:44'!\\nreadGray\\n\\t\\\"gray form\\\"\\n\\t| val form poker |\\n\\tmaxValue > 255 ifTrue:[self error:'Gray value > 8 bits not supported in Squeak'].\\n\\tstream binary.\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ stream next.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 15:44'!\\nreadHeader\\n\\t\\\"read header for pbm, pgm or ppm\\\"\\n\\t| tokens aux d c |\\n\\ttokens _ OrderedCollection new.\\n\\taux _ self getTokenPbm: tokens.\\n\\tcols _ aux at: 1. tokens _ aux at: 2.\\n\\taux _ self getTokenPbm: tokens.\\n\\trows _ aux at: 1. tokens _ aux at: 2.\\n\\n\\t(type = 1 or:[type = 4]) ifTrue:[\\n\\t\\tmaxValue _ 1\\n\\t]\\n\\tifFalse: [\\n\\t\\taux _ self getTokenPbm: tokens.\\n\\t\\tmaxValue _ aux at: 1. tokens _ aux at: 2.\\n\\t].\\n\\td _ {1 . 2 . 4 . \\t8 . \\t\\t16 . 32}.\\n\\tc _ {2 . 4 . 16 . 256 . 32768 . 16777216}. \\n\\t(type = 3 or:[type = 6]) ifTrue: [\\n\\t\\tmaxValue >= 65536 ifTrue:[\\n\\t\\t\\tself error:'Pixmap > 48 bits not supported in PPM'\\n\\t\\t].\\n\\t\\tmaxValue >= 256 ifTrue:[\\n\\t\\t\\tself error:'Pixmap > 32 bits are not supported in Squeak'\\n\\t\\t].\\n\\t\\tmaxValue < 32 ifTrue:[depth _ 16] ifFalse:[depth _ 32].\\n\\t]\\n\\tifFalse: [\\n\\t\\tdepth _ nil.\\n\\t\\t1 to: c size do:[:i| ((c at: i) > maxValue and:[depth = nil]) ifTrue:[depth_d at: i]].\\n\\t].\\n\\tTranscript cr; show: 'PBM file class ', type asString, ' size ', cols asString, ' x ', \\n\\t\\trows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:35'!\\nreadHeaderPAM\\n\\t\\\"read pam header, not tested\\\"\\n\\t| loop line tokens key val |\\n\\ttupleType _ ''.\\n\\tloop _ true.\\n\\tloop whileTrue:[\\n\\t\\tline _ self pbmGetLine.\\n\\t\\ttokens _ line findTokens: ' '.\\n\\t\\ttokens size = 2 ifTrue:[\\n\\t\\t\\tkey _ tokens at: 1 asUppercase.\\n\\t\\t\\tval _ tokens at: 2.\\n\\t\\t\\tkey caseOf: {\\n\\t\\t\\t\\t['WIDTH'] \\t\\t-> [cols _ val asInteger].\\n\\t\\t\\t\\t['HEIGHT'] \\t\\t-> [rows _ val asInteger].\\n\\t\\t\\t\\t['DEPTH'] \\t\\t-> [depth _ val asInteger].\\n\\t\\t\\t\\t['MAXVAL']\\t\\t-> [maxValue _ val asInteger].\\n\\t\\t\\t\\t['TUPLETYPE']\\t-> [tupleType _ tupleType, ' ', val].\\n\\t\\t\\t\\t['ENDHDR']\\t\\t-> [loop _ false].\\n\\t\\t\\t}\\n\\t\\t]\\n\\t].\\n\\tTranscript cr; show: 'PAM file class ', type asString, ' size ', cols asString, ' x ', \\n\\t\\trows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 16:03'!\\nreadPlainBW\\n\\t\\\"plain BW\\\"\\n\\t| val form poker |\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\t[val _ stream next. (val = $0 or:[val = $1])] whileFalse:[\\n\\t\\t\\t\\tval ifNil:[self error:'End of file reading PBM'].\\n\\t\\t\\t].\\n\\t\\t\\tpoker pixelAt: x@y put: (val asInteger).\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:44'!\\nreadPlainGray\\n\\t\\\"plain gray\\\"\\n\\t| val form poker aux tokens |\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\ttokens _ OrderedCollection new.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\taux _ self getTokenPbm: tokens.\\n\\t\\t\\tval _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:49'!\\nreadPlainRGB\\n\\t\\\"RGB form, use 32 bits\\\"\\n\\t| val form poker tokens aux |\\n\\tmaxValue > 255 ifTrue:[self error:'RGB value > 32 bits not supported in Squeak'].\\n\\tform _ Form extent: cols@rows depth: 32.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\ttokens _ OrderedCollection new.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x | | r g b|\\n\\t\\t\\taux _ self getTokenPbm: tokens. r _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\taux _ self getTokenPbm: tokens. g _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\taux _ self getTokenPbm: tokens. b _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\tval _ self r: r g: g b: b for: depth.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 7/18/2005 16:58'!\\nreadRGB\\n\\t\\\"RGB form, use 16/32 bits\\\"\\n\\t| val form poker sample shift |\\n\\tmaxValue > 255 ifTrue:[self error:'RGB value > 32 bits not supported in Squeak'].\\n\\tstream binary.\\n\\tform := Form extent: cols@rows depth: depth.\\n\\tpoker := BitBlt current bitPokerToForm: form.\\n\\tdepth = 32 ifTrue:[shift := 8] ifFalse:[shift := 5].\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval := 16rFF.\\t\\\"no transparency\\\"\\n\\t\\t\\t1 to: 3 do: [:i |\\n\\t\\t\\t\\tsample := stream next.\\n\\t\\t\\t\\tval := val << shift + sample.\\n\\t\\t\\t].\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n\\n!PNMReadWriter methodsFor: 'testing' stamp: 'jdr 10/11/2003 14:52'!\\nunderstandsImageFormat\\n\\t\\\"P1 to P7\\\"\\n\\t| p |\\n\\tp _ stream next asCharacter.\\n\\ttype _ stream next - 48.\\n\\t^(p = $P and:[type > 0 and:[type < 8]])\\n\\t! !\\n\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutBW: aForm reverse: flagXor\\n\\t| myType val nBytes bytesRow |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\t\\\"stream position: 0.\\\"\\n\\taForm depth = 1 ifTrue:[myType _ $4] ifFalse:[myType _ $5].\\n\\tself writeHeader: myType.\\n\\tstream binary.\\n\\tnBytes _ (cols/8) ceiling.\\n\\tbytesRow _ (cols/32) ceiling * 4.\\n\\t0 to: rows-1 do: [:y | | i |\\n\\t\\ti _ 1 + (bytesRow*y).\\n\\t\\t0 to: nBytes-1 do: [:x |\\n\\t\\t\\tval _ aForm bits byteAt: i.\\n\\t\\t\\tflagXor ifTrue:[val _ val bitXor: 16rFF].\\n\\t\\t\\tstream nextPut: val.\\n\\t\\t\\ti _ i+1.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutGray: aForm\\n\\t| myType peeker val |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\t\\\"stream position: 0.\\\"\\n\\taForm depth = 1 ifTrue:[myType _ $4] ifFalse:[myType _ $5].\\n\\tself writeHeader: myType.\\n\\tpeeker _ BitBlt current bitPeekerFromForm: aForm.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ peeker pixelAt: x@y.\\n\\t\\t\\tstream nextPut: val.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 14:22'!\\nnextPutImage: aForm\\n\\taForm unhibernate.\\n\\taForm depth\\t caseOf: {\\n\\t\\t[1] \\t\\t-> [self nextPutBW: aForm reverse: false].\\n\\t\\t[16] \\t-> [self nextPutRGB: aForm].\\n\\t\\t[32] \\t-> [self nextPutRGB: aForm].\\n\\t} otherwise: [\\n\\t\\t(aForm respondsTo: #colors) ifTrue:[\\n\\t\\t\\taForm colors ifNil: [\\n\\t\\t\\t\\tself nextPutGray: aForm\\n\\t\\t\\t]\\n\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\tself nextPutRGB: aForm\\n\\t\\t\\t]\\n\\t\\t]\\n\\t\\tifFalse:[\\n\\t\\t\\tself nextPutGray: aForm\\n\\t\\t]\\n\\t]! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutRGB: aForm\\n\\t| myType peeker f shift mask |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\tf _ aForm.\\n\\tdepth < 16 ifTrue:[\\n\\t\\tf _ aForm asFormOfDepth: 32.\\n\\t\\tdepth _ 32.\\n\\t].\\n\\tmyType _ $6.\\n\\t\\\"stream position: 0.\\\"\\n\\tself writeHeader: myType.\\n\\tdepth = 32 ifTrue:[shift _ 8. mask _ 16rFF] ifFalse:[shift _ 5. mask _ 16r1F].\\n\\tpeeker _ BitBlt current bitPeekerFromForm: f.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x | | p r g b |\\n\\t\\t\\tp _ peeker pixelAt: x@y.\\n\\t\\t\\tb _ p bitAnd: mask. p _ p >> shift.\\n\\t\\t\\tg _ p bitAnd: mask. p _ p >> shift.\\n\\t\\t\\tr _ p bitAnd: mask.\\n\\t\\t\\tstream nextPut: r.\\n\\t\\t\\tstream nextPut: g.\\n\\t\\t\\tstream nextPut: b.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/15/2003 15:48'!\\nwriteHeader: myType\\n\\t\\\"this is ascii\\\"\\n\\tstream nextPut: ($P asciiValue).\\n\\tstream nextPut: (myType asciiValue).\\n\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\tpragma ifNotNil:[\\n\\t\\tstream nextPutAll: (pragma asByteArray).\\n\\t].\\n\\tstream nextPutAll: (cols printString) asByteArray.\\n\\tstream nextPut: 32.\\t\\t\\\" \\\"\\n\\tstream nextPutAll: (rows printString) asByteArray.\\n\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\tdepth > 1 ifTrue: [| d c maxV |\\n\\t\\td _ {1 . 2 . 4 . 8 . 16 . 32}.\\n\\t\\tc _ {1 . 3 . 15 . 255 . 31 . 255}. \\n\\t\\tmaxV _ nil.\\n\\t\\t1 to: d size do:[:i| ((d at: i) = depth and:[maxV = nil]) ifTrue:[maxV _ c at: i]].\\n\\t\\tstream nextPutAll: (maxV printString) asByteArray.\\n\\t\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\t]\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPNMReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PNMReadWriter class methodsFor: 'image reading/writing' stamp: 'jdr 7/18/2005 16:25'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('pbm' 'pnm' 'ppm' 'pam')! !\\n\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/11/2003 14:49'!\\ntestFromSEFile: filename\\n\\t\\\"read SE file, check origin\\n\\t\\tPNMReadWriter testFromSEFile: 'Tools:Squeak3.4:eliseSE.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw _ self new.\\n\\tprw stream: (FileStream readOnlyFileNamed: filename).\\n\\tf _ prw nextImage.\\n\\tf morphEdit.\\n\\tprw inspect! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/16/2003 17:22'!\\ntestFromString\\n\\t\\\"read SE file from string\\n\\t\\tPNMReadWriter testFromString\\n\\t\\\"\\n\\t| prw f s |\\n\\tprw _ self new.\\n\\ts _ \\n'P1\\n#origin 1 0\\n3 1\\n1\\t01'.\\n\\tprw stream: (ReadStream on: s from: 1 to: (s size)).\\n\\tf _ prw nextImage.\\n\\tf morphEdit.\\n\\tTranscript cr;show:'Origin=', prw origin asString; cr.! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 7/18/2005 17:03'!\\ntestMultiFile: filename\\n\\t\\\"write two files from user, then read\\n\\t\\tPNMReadWriter testMultiFile: 'Tools:Squeak3.6:outMulti.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw := self new.\\n\\tprw stream: ((FileStream newFileNamed: filename) binary).\\n\\tprw pragma: '#Squeak test', String lf.\\n\\tf := Form fromUser. prw nextPutImage: f. \\n\\tf := Form fromUser.prw nextPutImage: f.\\t\\n\\tprw close.\\n\\tprw stream: (StandardFileStream readOnlyFileNamed: filename).\\n\\tf := prw nextImage. (SketchMorph withForm: f) openInWorld.\\n\\tf := prw nextImage. (SketchMorph withForm: f) openInWorld.\\n! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/15/2003 15:43'!\\ntestToSEFile: filename\\n\\t\\\"write SE file with origin\\n\\t\\tPNMReadWriter testToSEFile: 'Tools:Squeak3.4:outSE.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw _ self new.\\n\\tprw stream: ((FileStream newFileNamed: filename) binary).\\n\\tprw pragma: '#origin 10 10', String lf.\\n\\tf _ Form fromUser.\\n\\tprw nextPutImage: f! !\\nProtocolClient subclass: #POP3Client\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Protocols'!\\n!POP3Client commentStamp: 'mir 5/12/2003 17:57' prior: 0!\\nThis class implements POP3 (Post Office Protocol 3) as specified in RFC 1939. (see http://www.ietf.org/rfc.html)\\n\\nYou can use it to download email from the mail server to your personal mail program.\\n\\nTo see an example of it's use, see POPSocket class>>example.!\\n\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:58'!\\napopLoginUser: userName password: password\\n\\n\\tself loginUser: userName password: password loginMethod: #APOP! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:35'!\\ndeleteMessage: num\\n\\t\\\"delete the numbered message\\\"\\n\\n\\tself ensureConnection.\\n\\tself sendCommand: 'DELE ', num printString.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:57'!\\nloginUser: userName password: password\\n\\n\\tself loginUser: userName password: password loginMethod: #clearText! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/8/2002 11:40'!\\nloginUser: userName password: password loginMethod: aLoginMethod\\n\\n\\tself user: userName.\\n\\tself password: password.\\n\\tself loginMethod: aLoginMethod.\\n\\tself login! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 4/7/2003 17:17'!\\nmessageCount\\n\\t\\\"Query the server and answer the number of messages that are in the user's mailbox.\\\"\\n\\n\\t| answerString numMessages |\\n\\tself ensureConnection.\\n\\tself sendCommand: 'STAT'.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\t[answerString _ (self lastResponse findTokens: Character separators) second.\\n\\tnumMessages _ answerString asNumber asInteger]\\n\\t\\ton: Error\\n\\t\\tdo: [:ex | (ProtocolClientError protocolInstance: self) signal: 'Invalid STAT response.'].\\n\\t^numMessages! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'len 12/14/2002 17:50'!\\nquit\\n\\t\\\"QUIT <CRLF>\\\"\\n\\n\\tself sendCommand: 'QUIT'.\\n\\tself checkResponse.! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:35'!\\nretrieveMessage: number\\n\\t\\\"retrieve the numbered message\\\"\\n\\n\\tself ensureConnection.\\n\\tself sendCommand: 'RETR ', number printString.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\t^self getMultilineResponse! !\\n\\n\\n!POP3Client methodsFor: 'private' stamp: 'mir 11/11/2002 16:20'!\\nloginMethod\\n\\t^self connectionInfo at: #loginMethod ifAbsent: [nil]! !\\n\\n!POP3Client methodsFor: 'private' stamp: 'mir 3/8/2002 11:41'!\\nloginMethod: aSymbol\\n\\t^self connectionInfo at: #loginMethod put: aSymbol! !\\n\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'BG 3/16/2005 08:27'!\\napopLogin\\n\\n\\t\\\"Attempt to authenticate ourselves to the server without sending the password as cleartext.\\\"\\n\\n\\t\\\"For secure authentication, we look for a timestamp in the initial response string we get from the server, and then try the APOP command as specified in RFC 1939. If the initial response from the server is\\n\\t+OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>\\nwe extract the timestamp\\n\\t<1896.697170952@dbc.mtview.ca.us>\\nthen form a string of the form\\n\\t<1896.697170952@dbc.mtview.ca.us>USERPASSWORD\\nand then send only the MD5 hash of that to the server. Thus the password never hits the wire\\\"\\n\\n\\t| timestamp hash |\\n\\n\\t[\\n\\t\\\"Look for a timestamp in the response we received from the server\\\"\\n\\ttimestamp _ self lastResponse findTokens: '<>' includes: '@'.\\n\\ttimestamp\\n\\t\\tifNil: [(POP3LoginError protocolInstance: self) signal: 'APOP not supported.'].\\n\\n\\t(Smalltalk includesKey: #MD5)\\n\\t\\tifTrue: [\\n\\t\\t\\thash _ ((Smalltalk at: #MD5) hashMessage: ('<', timestamp, '>', self password)) storeStringHex asLowercase.\\n\\t\\t\\t\\\"trim starting 16r and zero pad it to 32 characters if needed\\\"\\n\\t\\t\\thash _ hash padded: #left to: 32 with: $0]\\n\\t\\tifFalse: [(POP3LoginError protocolInstance: self) signal: 'APOP (MD5) not supported.'].\\n\\n\\tself sendCommand: 'APOP ', self user, ' ', hash.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse]\\n\\t\\ton: ProtocolClientError\\n\\t\\tdo: [:ex |\\n\\t\\t\\tself close.\\n\\t\\t\\t(LoginFailedException protocolInstance: self) signal: 'Login failed.']! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 4/7/2003 17:38'!\\nclearTextLogin\\n\\n\\t[self sendCommand: 'USER ', self user.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\tself sendCommand: 'PASS ', self password.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse]\\n\\t\\ton: TelnetProtocolError\\n\\t\\tdo: [:ex |\\n\\t\\t\\t\\\"Neither authentication worked. Indicate an error and close up\\\"\\n\\t\\t\\tself close.\\n\\t\\t\\tex resignalAs: ((LoginFailedException protocolInstance: self) signal: 'Login failed.')]! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 11/14/2002 17:40'!\\ngetMultilineResponse\\n\\t\\\"Get a multiple line response to the last command, filtering out LF characters. A multiple line response ends with a line containing only a single period (.) character.\\\"\\n\\n\\t| response done chunk |\\n\\tresponse _ WriteStream on: ''.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tchunk _ self stream nextLine.\\n\\t\\t(chunk beginsWith: '.')\\n\\t\\t\\tifTrue: [response nextPutAll: (chunk copyFrom: 2 to: chunk size); cr ]\\n\\t\\t\\tifFalse: [response nextPutAll: chunk; cr ].\\n\\t\\tdone _ (chunk = '.') ].\\n\\n\\t^ response contents\\n! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 4/7/2003 17:39'!\\nlogin\\n\\tself loginMethod\\n\\t\\tifNil: [^self].\\n\\tself loginMethod == #clearText\\n\\t\\tifTrue: [^self clearTextLogin].\\n\\tself loginMethod == #APOP\\n\\t\\tifTrue: [^self apopLogin].\\n\\t(POP3LoginError protocolInstance: self) signal: 'Unsupported login procedure.'! !\\n\\n\\n!POP3Client methodsFor: 'private testing' stamp: 'mir 3/7/2002 13:43'!\\nresponseIsError\\n\\t^self lastResponse beginsWith: '-'! !\\n\\n!POP3Client methodsFor: 'private testing' stamp: 'mir 11/11/2002 15:44'!\\nresponseIsWarning\\n\\t^self lastResponse beginsWith: '-'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPOP3Client class\\n\\tinstanceVariableNames: ''!\\n\\n!POP3Client class methodsFor: 'accessing' stamp: 'mir 3/7/2002 12:51'!\\ndefaultPortNumber\\n\\t^110! !\\n\\n!POP3Client class methodsFor: 'accessing' stamp: 'mir 3/7/2002 12:52'!\\nlogFlag\\n\\t^#pop! !\\n\\n\\n!POP3Client class methodsFor: 'example' stamp: 'rbb 3/1/2005 11:05'!\\nexample\\n\\t\\\"POP3Client example\\\"\\n\\t\\\"download a user's messages into an OrderedCollection and inspect the OrderedCollection\\\"\\n\\n\\t| ps messages userName password |\\n\\tuserName := (UIManager default request: 'POP username').\\n\\tpassword := (UIManager default request: 'POP password').\\n\\tps := POP3Client openOnHostNamed: (UIManager default request: 'POP server').\\n\\t[\\n\\tps loginUser: userName password: password.\\n\\tps logProgressToTranscript.\\n\\n\\tmessages := OrderedCollection new.\\n\\t1 to: ps messageCount do: [ :messageNr |\\n\\t\\tmessages add: (ps retrieveMessage: messageNr) ]]\\n\\t\\tensure: [ps close].\\n\\n\\tmessages inspect.! !\\nProtocolClientError subclass: #POP3LoginError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Protocols'!\\n!POP3LoginError commentStamp: 'mir 5/12/2003 17:58' prior: 0!\\nException for signaling POP3 login failures.!\\n\\nObject subclass: #PRServerDirectory\\n\\tinstanceVariableNames: 'server directories'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n!PRServerDirectory commentStamp: 'md 1/26/2004 12:40' prior: 0!\\nAdd support to publish or download projects from Small-Land Project\\nRepository (SLPR).\\n\\nThe SLPR has virtual folders where the projects appears. The SLPR can\\nbe acceded from the FileList or from the web interface at\\nhttp://repository.small-land.org:8080\\n\\nBasically it's a type of superswiki (but better ;)).\\n\\nThe features in SMPR not present in SuperSwiki are:\\n\\n- Both the web interface and the squeak-side interface are full\\ntranslatable. The server has translations for English and Spanish just\\nnow, but it's almost trivial to include other translations... Stef?\\nMarcus? ;)\\n\\n- The projects are categorized in \\\"virtual\\\" folder. These folders (By\\nCategory, By Author, By Language, Alphabetical, etc) give us good\\nsearching behaviour just using the FileList and mouse clicks.\\n\\n- The web interface (also full translatable) has a search a la google.\\n\\n- All the urls to query the web interface are \\\"clean enough\\\" so google\\ncan make a good job indexing our content in .pr files.\\n\\n\\nIt's planned to add \\\"editing\\\" features to the web interface to\\nre-categorize, remove, etc projects.\\n\\n\\nEnjoy it,\\n\\n-- \\nDiego Gomez Deck\\nhttp://www.small-land.org!\\n\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 07:35'!\\ndirectories\\n\\t\\\"answer the receiver's directories\\\"\\n\\t^ directories! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:44'!\\ndirectory\\n\\t\\\"answer the receiver's directory\\\"\\n\\t| result |\\n\\tresult := String new writeStream.\\n\\tself directories\\n\\t\\tdo: [:each | result nextPutAll: each]\\n\\t\\tseparatedBy: [result nextPutAll: self slash].\\n\\t^ result contents! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 21:01'!\\ndirectoryWrapperClass\\n\\t\\\"answer the class to be used as a wrapper in FileList2\\\"\\n\\t^ FileDirectoryWrapper! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:44'!\\ndownloadUrl\\n\\t\\\"The url under which files will be accessible.\\\"\\n\\t^ (self urlFromServer: self server directories: {'programmatic'})\\n\\t\\t, self slash! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/27/2003 11:06'!\\nmoniker\\n\\t\\\"a plain language name for this directory\\\"\\n\\t^ self server! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:53'!\\nrealUrl\\n\\t\\\"a fully expanded version of the url we represent.\\\"\\n\\t^self urlFromServer: self server directories: self directories! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 07:40'!\\nserver\\n\\t\\\"answer the receiver's server\\\"\\n\\t^ server! !\\n\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:25'!\\ncreateDirectory: localName \\n\\t\\\"Create a new sub directory within the current one\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:24'!\\ndeleteFileNamed: localFileName \\n\\t\\\"Delete the file with the given name in this directory.\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:45'!\\ndirectoryNamed: aString \\n\\t\\\"Return the subdirectory of this directory with the given name.\\\"\\n\\t^ self class server: self server directory: self directory , self slash, aString! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 21:30'!\\ndirectoryNames\\n\\t\\\"Return a collection of names for the subdirectories of this \\n\\tdirectory. \\\"\\n\\t^ self entries\\n\\t\\tselect: [:entry | entry isDirectory]\\n\\t\\tthenCollect: [:entry | entry name]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:40'!\\nentries\\n\\t\\\"Return a collection of directory entries for the files and \\n\\tdirectories in this directory.\\\"\\n\\t| lines |\\n\\tlines := self getLines.\\n\\t^ lines isNil\\n\\t\\tifTrue: [#()] ifFalse:[\\n\\t\\n\\tself parseLines: lines]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 21:30'!\\nfileNames\\n\\t\\\"Return a collection of names for the files (but not directories) in this directory.\\\"\\n\\t^ self entries\\n\\t\\tselect: [:entry | entry isDirectory not]\\n\\t\\tthenCollect: [:entry | entry name]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:30'!\\nfullNameFor: aString \\n\\\"Return a corrected, fully-qualified name for the given file name.\\\"\\n\\t^ self urlFromServer: self server directories: self directories , {aString}! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/27/2003 12:36'!\\ngetOnly: numberOfBytes from: fileNameOnServer \\n\\t\\\"Just capture the first numberOfBytes of the file. \\n\\t \\n\\tGoes faster for long files. Return the contents, not a stream.\\\"\\n\\t| fileName |\\n\\tself flag: #todo.\\n\\t\\\"use LRUCache\\\"\\n\\tfileName := fileNameOnServer\\n\\t\\t\\t\\tallButFirst: (fileNameOnServer lastIndexOf: self pathNameDelimiter).\\n\\t\\\"\\\"\\n\\t^ self getOnly: numberOfBytes ofProjectContents: fileName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:33'!\\noldFileNamed: aName \\\"Open the existing file with the given name in this directory.\\\"\\n\\t^ self oldFileOrNoneNamed: aName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/27/2003 11:35'!\\noldFileOrNoneNamed: fullName \\n\\t\\\"If the file exists, answer a read-only FileStream on it. If it \\n\\tdoesn't, answer nil.\\\"\\n\\t| fileName contents |\\n\\tfileName := fullName\\n\\t\\t\\t\\tallButFirst: (fullName lastIndexOf: self pathNameDelimiter).\\n\\t\\\"\\\"\\n\\tcontents := self getFullProjectContents: fileName.\\n\\tcontents isNil\\n\\t\\tifTrue: [^ nil].\\n\\t\\\"\\\"\\n\\t^ (SwikiPseudoFileStream with: contents) directory: self;\\n\\t\\t localName: fileName;\\n\\t\\t reset;\\n\\t\\t yourself! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 07:58'!\\non: fullName \\n\\t\\\"Answer another ServerDirectory on the partial path name. \\n\\tfullName is directory path, and does include the name of the \\n\\tserver.\\\"\\n\\t^ self class fullPath: fullName!\\n]style[(4 8 3 133 4 4 17 8)f3b,f3cblue;b,f3,f3c146044000,f3,f3cmagenta;,f3,f3cblue;i! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:39'!\\npathName\\\"Path name as used in reading the file. \\\"\\n\\t^ self urlFromServer: self server directories: self directories! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 08:08'!\\npathParts\\n\\t\\\"Return the path from the root of the file system to this \\n\\tdirectory as an array of directory names. On a remote server.\\\"\\n\\t^ (OrderedCollection with: self server) addAll: self directories;\\n\\t\\t yourself! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:34'!\\nreadOnlyFileNamed: aName \\n\\\"Open the existing file with the given name in this directory for read-only access.\\\"\\n\\t^ self oldFileNamed: aName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:26'!\\nrename: fullName toBe: newName \\n\\t\\\"Rename a remote file. fullName is just be a fileName, or can \\n\\tbe directory path that includes name of the server. newName \\n\\tis just a fileName\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:37'!\\nsleep\\\"Leave the FileList window. Do nothing. \\\"\\n\\t^ self! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:32'!\\nwakeUp\\\"Entering a FileList window. Do nothing.\\\"\\n\\t^ self! !\\n\\n\\n!PRServerDirectory methodsFor: 'initialization' stamp: 'dgd 12/22/2003 20:46'!\\ninitializeServer: serverString directories: directoriesCollection \\n\\t\\\"initialize the receiver's server and directories\\\"\\n\\tserver := serverString withBlanksTrimmed.\\n\\tserver last = self pathNameDelimiter\\n\\t\\tifTrue: [server := server allButLast withBlanksTrimmed].\\n\\t\\\"\\\"\\n\\tdirectories := directoriesCollection! !\\n\\n\\n!PRServerDirectory methodsFor: 'path access' stamp: 'dgd 12/22/2003 20:41'!\\npathNameDelimiter\\\"Return the delimiter character for this kind of directory.\\\"\\n\\t^ $/! !\\n\\n!PRServerDirectory methodsFor: 'path access' stamp: 'dgd 12/22/2003 20:44'!\\nslash\\n\\\"answer the recevier 'slash'\\\"\\n\\t^ self pathNameDelimiter asString! !\\n\\n\\n!PRServerDirectory methodsFor: 'squeaklets' stamp: 'dgd 3/8/2006 17:38'!\\nwriteProject: aProject inFileNamed: fileNameString fromDirectory: localDirectory \\n\\t\\\"write aProject (a file version can be found in the file named \\n\\tfileNameString in localDirectory)\\\"\\n\\t| url arguments answer string |\\n\\turl := self urlFromServer: self server directories: {'programmatic'. 'uploadproject'}.\\n\\targuments := self\\n\\t\\t\\t\\tgetPostArgsFromProject: aProject\\n\\t\\t\\t\\tfileNamed: fileNameString\\n\\t\\t\\t\\tfromDirectory: localDirectory.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPClient httpPostDocument: url args: arguments.\\n\\t\\t\\t\\\"answer := HTTPSocket httpGetDocument: url args: arguments.\\\"\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"\\\"\\n\\tself\\n\\t\\tinform: ('Server responded: {1}' translated format: {string}).\\n\\t^ false! !\\n\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/22/2003 20:39'!\\nacceptsUploads\\n\\t\\\"answer whatever the receiver accepts uploads\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/22/2003 00:42'!\\nisProjectSwiki\\n\\t\\\"answer whatever the receiver is a project swiki\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/27/2003 11:04'!\\nisRemoteDirectory\\n\\t\\\"answer whatever the receiver is a remote directory\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/21/2003 23:31'!\\nisSearchable\\n\\t\\\"answer whatever the receiver is searchable\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 8/17/2004 22:14'!\\nqueryProjectsAndShow: thingsToSearchForCollection \\n\\t\\\"query the server for all the projects that match \\n\\tthingsToSearchForCollection\\\"\\n\\t| url arguments answer string |\\n\\turl := self urlFromServer: self server directories: {'programmatic'. 'queryprojects'}.\\n\\targuments := self getPostArgsFromThingsToSearchFor: thingsToSearchForCollection.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\t\\\"answer := HTTPClient httpPostDocument: url args: \\n\\t\\t\\targs.\\\"\\n\\t\\t\\tanswer := HTTPSocket httpGetDocument: url args: arguments.\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"\\\"\\n\\tself\\n\\t\\tinform: ('Server responded: {1}' translated format: {string}).\\n\\t^ false! !\\n\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/27/2003 11:34'!\\ngetFullProjectContents: aString \\n\\t\\\"private - get the project content from the server\\\"\\n\\t^ self getOnly: nil ofProjectContents: aString! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 8/17/2004 22:23'!\\ngetLines\\n\\t\\\"private - answer a collection of lines with the server response\\\"\\n\\t| url answer string lines |\\n\\turl := self urlFromServer: self server directories: {'programmatic'} , self directories.\\n\\turl := url , self slash.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPClient httpGetDocument: url.\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifFalse: [^ nil]].\\n\\t\\\"\\\"\\n\\tlines := OrderedCollection new.\\n\\t(string allButFirst: 6)\\n\\t\\tlinesDo: [:line | lines add: line squeakToIso].\\n\\t\\\"\\\"\\n\\t^ lines! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/27/2003 12:37'!\\ngetOnly: numberOfBytes ofProjectContents: aString \\n\\t\\\"private - get numberOfBytes of the project contents\\\"\\n\\t| url answer contents args |\\n\\tself flag: #todo.\\n\\t\\\"use an LRUCache\\\"\\n\\turl := self urlFromServer: self server directories: {'programmatic'. aString}.\\n\\t\\\"\\\"\\n\\targs := numberOfBytes isNil\\n\\t\\t\\t\\tifFalse: ['numberOfBytes=' , numberOfBytes asString].\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPSocket httpGetDocument: url args: args.\\n\\t\\t\\tcontents := answer contents].\\\"\\\"\\n\\t(contents beginsWith: '--OK--')\\n\\t\\tifFalse: [^ nil].\\n\\t\\\"\\\"\\n\\t^ contents allButFirst: 6! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 4/3/2006 13:27'!\\ngetPostArgsFromProject: aProject fileNamed: fileNameString fromDirectory: localDirectory \\n\\t| args thumbnail uploader |\\n\\targs := Dictionary new.\\n\\n\\t\\\"args at: 'contents' put: {(localDirectory oldFileNamed: fileNameString) contentsOfEntireFile}.\\\"\\n\\targs at: 'contents' put: {(StandardFileStream\\n\\t\\t\\treadOnlyFileNamed: (localDirectory fullNameFor: fileNameString)) contentsOfEntireFile}.\\n\\n\\targs at: 'name' put: {aProject name isoToSqueak}.\\n\\targs at: 'version' put: {(Project parseProjectFileName: fileNameString) second asString}.\\n\\targs at: 'language' put: {aProject naturalLanguage asString}.\\n\\n\\tuploader := Utilities authorNamePerSe.\\n\\tuploader isEmptyOrNil\\n\\t\\tifTrue: [uploader := Utilities authorInitialsPerSe].\\n\\tuploader isEmptyOrNil\\n\\t\\tifFalse: [args at: 'uploader' put: {uploader}].\\n\\n\\tself putSmalltalkInfoInto: args.\\n\\n\\tthumbnail := self getProjectThumbnail: aProject.\\n\\tthumbnail isNil\\n\\t\\tifFalse: [args at: 'thumbnailcontents' put: {thumbnail}].\\n\\n\\tself putProjectDetailsFrom: aProject to: args.\\n\\n\\t^ args! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 8/17/2004 22:14'!\\ngetPostArgsFromThingsToSearchFor: thingsToSearchForCollection \\n\\t| args |\\n\\targs := Dictionary new.\\n\\t\\\"\\\"\\n\\tthingsToSearchForCollection\\n\\t\\tdo: [:each | \\n\\t\\t\\t| pos | \\n\\t\\t\\tpos := each indexOf: $:.\\n\\t\\t\\tpos isZero\\n\\t\\t\\t\\tifFalse: [| key value | \\n\\t\\t\\t\\t\\tkey := (each first: pos - 1) withBlanksTrimmed.\\n\\t\\t\\t\\t\\tvalue := (each allButFirst: pos) withBlanksTrimmed.\\n\\t\\t\\t\\t\\t(value beginsWith: '*')\\n\\t\\t\\t\\t\\t\\tifTrue: [value := value allButFirst].\\n\\t\\t\\t\\t\\t(value endsWith: '*')\\n\\t\\t\\t\\t\\t\\tifTrue: [value := value allButLast].\\n\\t\\t\\t\\t\\t\\\"\\\"\\n\\t\\t\\t\\t\\targs at: key put: {value}]].\\n\\t\\\"\\\"\\n\\t^ args! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/24/2003 11:33'!\\ngetProjectThumbnail: aProject \\n\\t\\\"private - answer a stream with the aProject's thumbnail or nil if none\\\"\\n\\t| form stream |\\n\\tform := aProject thumbnail.\\n\\tform isNil\\n\\t\\tifTrue: [^ nil].\\n\\t\\\"\\\"\\n\\tform unhibernate.\\n\\tform := form colorReduced.\\n\\t\\\"\\\"\\n\\tself flag: #todo.\\n\\t\\\"use a better image format than GIF\\\"\\n\\tstream := RWBinaryOrTextStream on: String new.\\n\\tGIFReadWriter putForm: form onStream: stream.\\n\\tstream reset.\\n\\t\\\"\\\"\\n\\t^ stream contents asString! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:34'!\\nparseLine: aString \\n\\\"private - parse a line from a server response\\\"\\n\\t| tokens |\\n\\ttokens := aString findTokens: '|'.\\n\\t\\\"\\\"\\n\\t^ tokens first = 'D'\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\tDirectoryEntry\\n\\t\\t\\t\\tname: tokens second\\n\\t\\t\\t\\tcreationTime: 0\\n\\t\\t\\t\\tmodificationTime: 0\\n\\t\\t\\t\\tisDirectory: true\\n\\t\\t\\t\\tfileSize: 0]\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\tDirectoryEntry\\n\\t\\t\\t\\tname: tokens second\\n\\t\\t\\t\\tcreationTime: tokens third asInteger\\n\\t\\t\\t\\tmodificationTime: tokens fourth asInteger\\n\\t\\t\\t\\tisDirectory: false\\n\\t\\t\\t\\tfileSize: tokens fifth asInteger]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:38'!\\nparseLines: aCollection \\n\\\"private - parse aCollection of lines from a server response\\\"\\n\\t^ aCollection\\n\\t\\tcollect: [:each | self parseLine: each]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 9/7/2004 12:16'!\\nputProjectDetailsFrom: aProject to: args \\n\\t| projectDetails |\\n\\tprojectDetails := aProject world\\n\\t\\t\\t\\tvalueOfProperty: #ProjectDetails\\n\\t\\t\\t\\tifAbsent: [^ self].\\n\\t\\\"\\\"\\n\\tself flag: #todo.\\n\\t\\\"projectname ?\\\"\\n\\tprojectDetails\\n\\t\\tat: 'projectdescription'\\n\\t\\tifPresent: [:value | args at: 'description' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectauthor'\\n\\t\\tifPresent: [:value | args at: 'author' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectcategory'\\n\\t\\tifPresent: [:value | args at: 'category' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectsubcategory'\\n\\t\\tifPresent: [:value | args at: 'subcategory' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectkeywords'\\n\\t\\tifPresent: [:value | args at: 'keywords' put: {value isoToSqueak}]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 9/7/2004 12:13'!\\nputSmalltalkInfoInto: args \\n\\t\\\"private - fills args with information from Smalltalk\\\"\\n\\tself flag: #todo.\\n\\t\\\" \\n\\tlastest small-land changeset / small-land version \\n\\t\\\"\\n\\t#(#datedVersion #osVersion #platformName #platformSubtype #vmPath #vmVersion #imageName #changesName #sourcesName #listBuiltinModules #listLoadedModules #getVMParameters )\\n\\t\\tdo: [:each | \\n\\t\\t\\t| value | \\n\\t\\t\\tvalue := SmalltalkImage current perform: each.\\n\\t\\t\\targs at: 'extra-' , each asString put: {value asString isoToSqueak}]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:47'!\\nurlFromServer: serverString directories: aCollection \\n\\t\\\"private - builds an url for server/directories\\\"\\n\\t| result |\\n\\tresult := String new writeStream.\\n\\t\\\"\\\"\\n\\t{serverString} , aCollection\\n\\t\\tdo: [:each | \\\"\\\"\\n\\t\\t\\tresult\\n\\t\\t\\t\\tnextPutAll: (each copyReplaceAll: ' ' with: '+')]\\n\\t\\tseparatedBy: [result nextPutAll: self slash].\\n\\t\\\"\\\"\\n\\t^ result contents! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPRServerDirectory class\\n\\tinstanceVariableNames: ''!\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 20:43'!\\nfullPath: fullNameString\\n\\t\\\"answer an instance of the receiver on fullName\\\"\\n\\t| pathParts |\\n\\tpathParts := self pathParts: fullNameString.\\n\\t^ self server: pathParts first directories: pathParts allButFirst! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 20:43'!\\npathParts: fullName \\n\\t\\\"private - parse fullName in server and directory\\\"\\n\\t| url slashPos server directory |\\n\\turl := fullName.\\n\\t(url beginsWith: 'http://')\\n\\t\\tifTrue: [url := url allButFirst: 7].\\n\\turl last = $/\\n\\t\\tifTrue: [url := url allButLast].\\n\\t\\\"\\\"\\n\\tslashPos := url indexOf: $/.\\n\\tslashPos isZero\\n\\t\\tifTrue: [^ {'http://' , url}].\\n\\t\\\"\\\"\\n\\tserver := url first: slashPos - 1.\\n\\tdirectory := url allButFirst: slashPos.\\n\\t\\\"\\\"\\n\\t^ {'http://' , server. directory}! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:57'!\\nserver: serverString \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self server: serverString directories: #()! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:56'!\\nserver: serverString directories: aCollection \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self new initializeServer: serverString directories: aCollection! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:58'!\\nserver: serverString directory: directoryString \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self new\\n\\t\\tinitializeServer: serverString\\n\\t\\tdirectories: (directoryString findTokens: '/')!\\n]style[(8 12 12 15 3 57 4 4 25 12 17 15 13 3 1)f3b,f3cblue;b,f3b,f3cblue;b,f3,f3c146044000,f3,f3cmagenta;,f3,f3cblue;i,f3,f3cblue;i,f3,f3c255146000b,f3! !\\nObject subclass: #PackageInfo\\n\\tinstanceVariableNames: 'packageName methodCategoryPrefix'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n!PackageInfo commentStamp: '<historical>' prior: 0!\\nSubclass this class to create new Packages.!\\n\\n\\n!PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 14:20'!\\nhash\\n\\t^ packageName hash! !\\n\\n!PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 00:09'!\\n= other\\n\\t^ other species = self species and: [other packageName = self packageName]! !\\n\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:16'!\\nexternalCallers\\n\\t^ self \\n\\t\\texternalRefsSelect: [:literal | literal isKindOf: Symbol] \\n\\t\\tthenCollect: [:l | l].! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalClasses\\n\\t| myClasses |\\n\\tmyClasses := self classesAndMetaClasses.\\n\\t^ Array streamContents:\\n\\t\\t[:s |\\n\\t\\tProtoObject withAllSubclassesDo:\\n\\t\\t\\t[:class |\\n\\t\\t\\t(myClasses includes: class) ifFalse: [s nextPut: class]]]! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalRefsSelect: selBlock thenCollect: colBlock\\n\\t| pkgMethods dependents refs extMethods otherClasses otherMethods classNames |\\n\\n\\tclassNames := self classes collect: [:c | c name].\\n\\textMethods := self extensionMethods collect: [:mr | mr methodSymbol].\\n\\totherClasses := self externalClasses difference: self externalSubclasses.\\n\\totherMethods := otherClasses gather: [:c | c selectors].\\n\\tpkgMethods := self methods asSet collect: [:mr | mr methodSymbol].\\n\\tpkgMethods removeAllFoundIn: otherMethods.\\n\\n\\tdependents := Set new.\\n\\totherClasses do: [:c |\\n\\t\\tc selectorsAndMethodsDo:\\n\\t\\t\\t[:sel :compiled |\\n\\t\\t\\t(extMethods includes: sel) ifFalse: \\n\\t\\t\\t\\t[refs := compiled literals select: selBlock thenCollect: colBlock.\\n\\t\\t\\t\\trefs do: [:ea |\\n\\t\\t\\t\\t\\t((classNames includes: ea) or: [pkgMethods includes: ea])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [dependents add: (self referenceForMethod: sel ofClass: c) -> ea]]]]].\\n\\t^ dependents! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalSubclasses\\n\\t| pkgClasses subClasses |\\n\\tpkgClasses := self classes.\\n\\tsubClasses := Set new.\\n\\tpkgClasses do: [:c | subClasses addAll: (c allSubclasses)].\\n\\t^ subClasses difference: pkgClasses\\n! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:15'!\\nexternalUsers\\n\\t^ self \\n\\t\\texternalRefsSelect: [:literal | literal isVariableBinding] \\n\\t\\tthenCollect: [:l | l key]! !\\n\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ac 5/14/2003 16:23'!\\nclasses\\n\\t^(self systemCategories gather:\\n\\t\\t[:cat |\\n\\t\\t(SystemOrganization listAtCategoryNamed: cat)\\n\\t\\t\\tcollect: [:className | Smalltalk at: className]])\\n\\t\\t\\t\\tsortBy: [:a :b | a className <= b className]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 12/14/2005 18:06'!\\nclassesAndMetaClasses\\n\\t| baseClasses |\\n\\tbaseClasses := self classes.\\n\\t^baseClasses , (baseClasses collect: [:c | c classSide])! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/13/2002 01:23'!\\ncoreMethods\\n\\t^ self classesAndMetaClasses gather: [:class | self coreMethodsForClass: class]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 3/1/2006 21:51'!\\nextensionClasses\\n\\t^ self externalBehaviors reject: [:classOrTrait | (self extensionCategoriesForClass: classOrTrait) isEmpty]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 3/1/2006 21:51'!\\nextensionMethods\\n\\t^ self externalBehaviors gather: [:classOrTrait | self extensionMethodsForClass: classOrTrait]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nforeignClasses\\n\\t| s |\\n\\ts := IdentitySet new.\\n\\tself foreignSystemCategories\\n\\t\\tdo: [:c | (SystemOrganization listAtCategoryNamed: c)\\n\\t\\t\\t\\tdo: [:cl | \\n\\t\\t\\t\\t\\t| cls | \\n\\t\\t\\t\\t\\tcls := Smalltalk at: cl. \\n\\t\\t\\t\\t\\ts add: cls;\\n\\t\\t\\t\\t\\t add: cls class]].\\n\\t^ s! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 12/3/2002 14:34'!\\nforeignSystemCategories\\n\\t^ SystemOrganization categories\\n\\t\\treject: [:cat | self includesSystemCategory: cat] ! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 10/9/2005 20:00'!\\nmethods\\n\\t^ (self extensionMethods, self coreMethods) select: [:method |\\n\\t\\tmethod isValid\\n\\t\\t\\tand: [method isLocalSelector]\\n\\t\\t\\tand: [method methodSymbol isDoIt not]]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'avi 11/10/2003 15:35'!\\noverrideMethods\\n\\t^ self extensionMethods select: [:ea | self isOvverideMethod: ea]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/14/2002 18:39'!\\nselectors\\n\\t^ self methods collect: [:ea | ea methodSymbol]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/11/2002 21:51'!\\nsystemCategories\\n\\t^ SystemOrganization categories select: [:cat | self includesSystemCategory: cat]! !\\n\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\naddCoreMethod: aMethodReference\\n\\t| category |\\n\\tcategory := self baseCategoryOfMethod: aMethodReference.\\n\\taMethodReference actualClass organization\\n\\t\\tclassify: aMethodReference methodSymbol\\n\\t\\tunder: category\\n\\t\\tsuppressIfDefault: false! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\naddExtensionMethod: aMethodReference\\n\\t| category |\\n\\tcategory := self baseCategoryOfMethod: aMethodReference.\\n\\taMethodReference actualClass organization\\n\\t\\tclassify: aMethodReference methodSymbol\\n\\t\\tunder: self methodCategoryPrefix, '-', category! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:16'!\\naddMethod: aMethodReference\\n\\t(self includesClass: aMethodReference class)\\n\\t\\tifTrue: [self addCoreMethod: aMethodReference]\\n\\t\\tifFalse: [self addExtensionMethod: aMethodReference]! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nbaseCategoryOfMethod: aMethodReference\\n\\t| oldCat oldPrefix tokens | \\n\\toldCat := aMethodReference category.\\n\\t({ 'as yet unclassified'. 'all' } includes: oldCat) ifTrue: [ oldCat := '' ].\\n\\ttokens := oldCat findTokens: '*-' keep: '*'.\\n\\n\\t\\\"Strip off any old prefixes\\\"\\n\\t((tokens at: 1 ifAbsent: [ '' ]) = '*') ifTrue: [\\n\\t\\t[ ((tokens at: 1 ifAbsent: [ '' ]) = '*') ]\\n\\t\\t\\twhileTrue: [ tokens removeFirst ].\\n\\t\\toldPrefix := tokens removeFirst asLowercase.\\n\\t\\t[ (tokens at: 1 ifAbsent: [ '' ]) asLowercase = oldPrefix ]\\n\\t\\t\\twhileTrue: [ tokens removeFirst ].\\n\\t].\\n\\n\\ttokens isEmpty ifTrue: [^ 'as yet unclassified'].\\n\\t^ String streamContents:\\n\\t\\t[ :s |\\n\\t\\ttokens\\n\\t\\t\\tdo: [ :tok | s nextPutAll: tok ]\\n\\t\\t\\tseparatedBy: [ s nextPut: $- ]]! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'al 3/1/2006 21:42'!\\nexternalBehaviors\\n\\t^self externalClasses , self externalTraits! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'al 3/1/2006 22:08'!\\nexternalTraits\\n\\t| behaviors |\\n\\t\\n\\t^ Array streamContents: [:s |\\n\\t\\tbehaviors := self classesAndMetaClasses.\\n\\t\\tSmalltalk allTraits do: [:trait |\\n\\t\\t\\t(behaviors includes: trait) ifFalse: [s nextPut: trait].\\n\\t\\t\\t(behaviors includes: trait classSide) ifFalse: [s nextPut: trait classSide]]].\\t\\t\\t! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:14'!\\nremoveMethod: aMethodReference! !\\n\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ncategoryName\\n\\t|category|\\n\\tcategory := self class category.\\n\\t^ (category endsWith: '-Info')\\n\\t\\tifTrue: [category copyUpToLast: $-]\\n\\t\\tifFalse: [category]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'ab 10/16/2002 21:22'!\\nexternalName\\n\\t^ self packageName! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nmethodCategoryPrefix\\n\\t^ methodCategoryPrefix ifNil: [methodCategoryPrefix := '*', self packageName asLowercase]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\npackageName\\n\\t^ packageName ifNil: [packageName := self categoryName]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\npackageName: aString\\n\\tpackageName := aString! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'ab 10/28/2002 10:38'!\\nsystemCategoryPrefix\\n\\t^ self packageName! !\\n\\n\\n!PackageInfo methodsFor: 'registering' stamp: 'avi 11/12/2003 23:12'!\\nregister\\n\\tPackageOrganizer default registerPackage: self! !\\n\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 3/9/2004 15:53'!\\ncategory: categoryName matches: prefix\\n\\t^ categoryName notNil and: [categoryName = prefix or: [categoryName beginsWith: prefix, '-']]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:18'!\\ncoreCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | (self isForeignClassExtension: cat) not]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'!\\ncoreMethodsForClass: aClass\\n\\t^ (aClass selectors difference:\\n\\t\\t((self foreignExtensionMethodsForClass: aClass) collect: [:r | r methodSymbol]))\\n\\t\\t\\tasArray collect: [:sel | self referenceForMethod: sel ofClass: aClass]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:20'!\\nextensionCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | self isYourClassExtension: cat]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 4/6/2004 15:16'!\\nextensionMethodsForClass: aClass\\n\\t^ (self extensionCategoriesForClass: aClass)\\n\\t\\tgather: [:cat | ((aClass organization listAtCategoryNamed: cat) ifNil: [#()])\\n\\t\\t\\t\\t\\t\\t\\tcollect: [:sel | self referenceForMethod: sel ofClass: aClass]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'!\\nextensionMethodsFromClasses: classes\\n\\t^classes\\n\\t\\tgather: [:class | self extensionMethodsForClass: class]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'!\\nforeignExtensionCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | self isForeignClassExtension: cat]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nforeignExtensionMethodsForClass: aClass\\n\\t^ (self foreignExtensionCategoriesForClass: aClass)\\n\\t\\tgather: [:cat | (aClass organization listAtCategoryNamed: cat)\\n\\t\\t\\t\\t\\t\\t collect: [:sel | self referenceForMethod: sel ofClass: aClass]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:08'!\\nincludesClassNamed: aClassName\\n\\t^ self includesSystemCategory: ((SystemOrganization categoryOfElement: aClassName) ifNil: [^false])! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nincludesClass: aClass\\n\\t^ self includesSystemCategory: aClass theNonMetaClass category! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:06'!\\nincludesMethodCategory: categoryName ofClassNamed: aClass\\n\\t^ (self isYourClassExtension: categoryName)\\n\\t\\tor: [(self includesClassNamed: aClass)\\n\\t\\t\\t\\tand: [(self isForeignClassExtension: categoryName) not]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 9/17/2002 00:18'!\\nincludesMethodCategory: categoryName ofClass: aClass\\n\\t^ (self isYourClassExtension: categoryName)\\n\\t\\tor: [(self includesClass: aClass)\\n\\t\\t\\t\\tand: [(self isForeignClassExtension: categoryName) not]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/14/2002 18:06'!\\nincludesMethodReference: aMethodRef\\n\\t^ self includesMethod: aMethodRef methodSymbol ofClass: aMethodRef actualClass! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 12/5/2002 00:16'!\\nincludesMethod: aSymbol ofClass: aClass\\n\\taClass ifNil: [^ false].\\n\\t^ self\\n\\t\\tincludesMethodCategory: ((aClass organization categoryOfElement: aSymbol)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifNil: [' '])\\n\\t\\tofClass: aClass! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nincludesSystemCategory: categoryName\\n\\t^ self category: categoryName matches: self systemCategoryPrefix! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nisForeignClassExtension: categoryName\\n\\t^ categoryName first = $* and: [(self isYourClassExtension: categoryName) not]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 11/10/2003 15:42'!\\nisOverrideMethod: aMethodReference\\n\\t^ aMethodReference category endsWith: '-override'! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 3/10/2004 12:37'!\\nisYourClassExtension: categoryName\\n\\t^ categoryName notNil and: [self category: categoryName asLowercase matches: self methodCategoryPrefix]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'!\\noutsideClasses\\n\\t^ProtoObject withAllSubclasses difference: self classesAndMetaClasses! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:25'!\\nreferenceForMethod: aSymbol ofClass: aClass\\n\\t^ MethodReference new setStandardClass: aClass methodSymbol: aSymbol! !\\n\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageInfo class\\n\\tinstanceVariableNames: ''!\\n\\n!PackageInfo class methodsFor: 'class initialization' stamp: 'avi 2/18/2004 00:46'!\\ninitialize\\n\\tself allSubclassesDo: [:ea | ea new register]! !\\n\\n\\n!PackageInfo class methodsFor: 'compatibility' stamp: 'avi 3/9/2004 16:28'!\\ndefault\\n\\t^ self allPackages detect: [:ea | ea class = self] ifNone: [self new register]! !\\n\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'nk 3/9/2004 10:49'!\\nallPackages\\n\\t^PackageOrganizer default packages! !\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'avi 11/12/2003 23:00'!\\nnamed: aString\\n\\t^ PackageOrganizer default packageNamed: aString ifAbsent: [(self new packageName: aString) register]! !\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'avi 11/11/2003 17:19'!\\nregisterPackageName: aString\\n\\t^ PackageOrganizer default registerPackageNamed: aString! !\\nObject subclass: #PackageOrganizer\\n\\tinstanceVariableNames: 'packages'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n\\n!PackageOrganizer methodsFor: 'accessing' stamp: 'avi 11/12/2003 23:01'!\\npackageNames\\n\\t^ packages keys! !\\n\\n!PackageOrganizer methodsFor: 'accessing' stamp: 'avi 11/12/2003 23:01'!\\npackages\\n\\t^ packages values! !\\n\\n\\n!PackageOrganizer methodsFor: 'initializing' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ninitialize\\n\\tpackages := Dictionary new! !\\n\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 23:01'!\\nregisterPackage: aPackageInfo\\n\\tpackages at: aPackageInfo packageName put: aPackageInfo.\\n\\tself changed: #packages; changed: #packageNames.\\n! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 21:08'!\\nregisterPackageNamed: aString\\n\\t^ self registerPackage: (PackageInfo named: aString)! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 23:08'!\\nunregisterPackage: aPackageInfo\\n\\tpackages removeKey: aPackageInfo packageName ifAbsent: [].\\t\\n\\tself changed: #packages; changed: #packageNames.\\n! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 21:10'!\\nunregisterPackageNamed: aString\\n\\tself unregisterPackage: (self packageNamed: aString ifAbsent: [^ self])! !\\n\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\nnoPackageFound\\n\\tself error: 'No package found'! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 11/12/2003 23:08'!\\npackageNamed: aString ifAbsent: errorBlock\\n\\t^ packages at: aString ifAbsent: errorBlock! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\npackageOfClass: aClass\\n\\t^ self packageOfClass: aClass ifNone: [self noPackageFound]! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:22'!\\npackageOfClass: aClass ifNone: errorBlock\\n\\t^ self packages detect: [:ea | ea includesClass: aClass] ifNone: errorBlock! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\npackageOfMethod: aMethodReference\\n\\t^ self packageOfMethod: aMethodReference ifNone: [self noPackageFound]! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:22'!\\npackageOfMethod: aMethodReference ifNone: errorBlock\\n\\t^ self packages detect: [:ea | ea includesMethodReference: aMethodReference] ifNone: errorBlock! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageOrganizer class\\n\\tinstanceVariableNames: 'default'!\\n\\n!PackageOrganizer class methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ndefault\\n\\t^ default ifNil: [default := self new]! !\\n\\n!PackageOrganizer class methodsFor: 'as yet unclassified' stamp: 'avi 10/13/2003 15:25'!\\nnew\\n\\t^ self basicNew initialize! !\\nBrowser subclass: #PackagePaneBrowser\\n\\tinstanceVariableNames: 'package packageListIndex packageList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Browser'!\\n!PackagePaneBrowser commentStamp: '<historical>' prior: 0!\\nA package browser represents a hierarchical query path through an organization of class and method information. It parses class categories into a two-level hierarchy on the first '-' character, giving \\\"packages\\\" (e.g., Magnitude, Collections, Graphics, etc.), and \\\"categories\\\" (e.g., Magnitude-General and Magnitude-Number).\\n\\nInstance Variables:\\n\\tpackage <Symbol> the \\\"category header,\\\" e.g., #Magnitudes or #Collections\\n\\tpackageListIndex <Integer> The index in the package list\\n\\tpackageList <OrderedCollection of String> the list of package names\\n!\\n\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:26'!\\nclassList\\n\\t\\\"Answer an array of the class names of the selected category. Answer an \\n\\tempty array if no selection exists.\\\"\\n\\n\\t^ self hasSystemCategorySelected \\n\\t\\tifFalse:\\n\\t\\t\\t[self packageClasses]\\n\\t\\tifTrue: [systemOrganizer listAtCategoryNumber:\\n\\t\\t\\t(systemOrganizer categories indexOf: self selectedSystemCategoryName asSymbol)]! !\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:36'!\\npackageClasses\\n\\t^ self categoryExistsForPackage\\n\\t\\tifFalse: [Array new]\\n\\t\\tifTrue:\\n\\t\\t\\t[systemOrganizer listAtCategoryNumber:\\n\\t\\t\\t\\t(systemOrganizer categories indexOf: self package asSymbol)]! !\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'md 3/3/2006 11:04'!\\nselectedClass\\n\\t\\\"Answer the class that is currently selected. Answer nil if no selection \\n\\texists.\\\"\\n\\n\\t| name envt |\\n\\t(name := self selectedClassName) ifNil: [^ nil].\\n\\t\\\"(envt := self selectedEnvironment) ifNil: [^ nil].\\\"\\n\\tenvt:= Smalltalk.\\n\\t^ envt at: name! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'dragNDrop' stamp: 'sd 11/20/2005 21:27'!\\nchangeCategoryForClass: class srcSystemCategory: srcSystemCategorySel atListMorph: dstListMorph internal: internal copy: copyFlag \\n\\t\\\"only move semantic\\\"\\n\\t| newClassCategory success |\\n\\tself flag: #stringSymbolProblem.\\n\\tsuccess := copyFlag not ifFalse: [^ false].\\n\\tnewClassCategory := self dstCategoryDstListMorph: dstListMorph internal: internal.\\n\\t(success := newClassCategory notNil & (newClassCategory ~= class category))\\n\\t\\tifTrue: \\n\\t\\t\\t[class category: newClassCategory.\\n\\t\\t\\tself changed: #classList.\\n\\t\\t\\tinternal ifFalse: [self selectClass: class]].\\n\\t^ success! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'dragNDrop util' stamp: 'sd 11/20/2005 21:27'!\\ndstCategoryDstListMorph: dstListMorph internal: internal \\n\\t| dropItem |\\n\\t^ internal & (dstListMorph getListSelector == #systemCategoryList)\\n\\t\\tifTrue: [(dropItem := dstListMorph potentialDropItem) ifNotNil: [(self package , '-' , dropItem) asSymbol]]\\n\\t\\tifFalse: [self selectedSystemCategoryName]! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'sw 1/13/2000 16:45'!\\ndefaultBrowserTitle\\n\\t^ 'Package Browser'! !\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'sd 11/20/2005 21:27'!\\nopenAsMorphEditing: editString \\n\\t\\\"Create a pluggable version of all the views for a Browser, including \\n\\tviews and controllers.\\\"\\n\\t\\\"PackagePaneBrowser openBrowser\\\"\\n\\n\\t| listHeight window |\\n\\tlistHeight := 0.4.\\n\\t(window := SystemWindow labelled: 'later') model: self.\\n\\twindow\\n\\t\\taddMorph: (PluggableListMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\tlist: #packageList\\n\\t\\t\\t\\tselected: #packageListIndex\\n\\t\\t\\t\\tchangeSelected: #packageListIndex:\\n\\t\\t\\t\\tmenu: #packageMenu:\\n\\t\\t\\t\\tkeystroke: #packageListKey:from:)\\n\\t\\tframe: (0 @ 0 extent: 0.15 @ listHeight).\\n\\twindow\\n\\t\\taddMorph: self buildMorphicSystemCatList\\n\\t\\tframe: (0.15 @ 0 extent: 0.2 @ listHeight).\\n\\tself\\n\\t\\taddClassAndSwitchesTo: window\\n\\t\\tat: (0.35 @ 0 extent: 0.25 @ listHeight)\\n\\t\\tplus: 0.\\n\\twindow\\n\\t\\taddMorph: self buildMorphicMessageCatList\\n\\t\\tframe: (0.6 @ 0 extent: 0.15 @ listHeight).\\n\\twindow\\n\\t\\taddMorph: self buildMorphicMessageList\\n\\t\\tframe: (0.75 @ 0 extent: 0.25 @ listHeight).\\n\\tself\\n\\t\\taddLowerPanesTo: window\\n\\t\\tat: (0 @ listHeight corner: 1 @ 1)\\n\\t\\twith: editString.\\n\\twindow setUpdatablePanesFrom: #(#packageList #systemCategoryList #classList #messageCategoryList #messageList ).\\n\\t^ window! !\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'stp 10/06/1998 22:02'!\\nsystemOrganizer: aSystemOrganizer \\n\\t\\\"Initialize the receiver as a perspective on the system organizer, \\n\\taSystemOrganizer. Typically there is only one--the system variable \\n\\tSystemOrganization.\\\"\\n\\n\\tsuper systemOrganizer: aSystemOrganizer .\\n\\tpackageListIndex := 0! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:35'!\\ncategoryExistsForPackage\\n\\t^ self hasPackageSelected\\n\\t\\tand: [(systemOrganizer categories indexOf: self package asSymbol) ~= 0]\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:24'!\\nhasPackageSelected\\n\\n\\t^ packageListIndex ~= 0! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'sd 11/20/2005 21:27'!\\nopenEditString: aString\\n\\t\\\"Create a pluggable version of all the views for a Browser, including views and controllers.\\\"\\n\\t\\\"PackageBrowser openBrowser\\\"\\n\\n\\t| packageListView systemCategoryListView classListView messageCategoryListView\\n\\t messageListView browserCodeView topView switchView annotationPane underPane y optionalButtonsView |\\n\\n\\tself couldOpenInMorphic ifTrue: [^ self openAsMorphEditing: aString].\\n\\n\\ttopView := StandardSystemView new model: self.\\n\\ttopView borderWidth: 1. \\\"label and minSize taken care of by caller\\\"\\n\\n\\tpackageListView := PluggableListView on: self\\n\\t\\tlist: #packageList\\n\\t\\tselected: #packageListIndex\\n\\t\\tchangeSelected: #packageListIndex:\\n\\t\\tmenu: #packageMenu:.\\n\\tpackageListView window: (0 @ 0 extent: 20 @ 70).\\n\\ttopView addSubView: packageListView.\\n\\n\\tsystemCategoryListView := PluggableListView on: self\\n\\t\\tlist: #systemCategoryList\\n\\t\\tselected: #systemCategoryListIndex\\n\\t\\tchangeSelected: #systemCategoryListIndex:\\n\\t\\tmenu: #systemCategoryMenu:.\\n\\tsystemCategoryListView window: (20 @ 0 extent: 30 @ 70).\\n\\ttopView addSubView: systemCategoryListView.\\n\\n\\tclassListView := PluggableListView on: self\\n\\t\\tlist: #classList\\n\\t\\tselected: #classListIndex\\n\\t\\tchangeSelected: #classListIndex:\\n\\t\\tmenu: #classListMenu:shifted:.\\n\\tclassListView window: (0 @ 0 extent: 50 @ 62).\\n\\ttopView addSubView: classListView toRightOf: systemCategoryListView.\\n\\n\\tswitchView := self buildInstanceClassSwitchView.\\n\\tswitchView borderWidth: 1.\\n\\ttopView addSubView: switchView below: classListView.\\n\\n\\tmessageCategoryListView := PluggableListView on: self\\n\\t\\tlist: #messageCategoryList\\n\\t\\tselected: #messageCategoryListIndex\\n\\t\\tchangeSelected: #messageCategoryListIndex:\\n\\t\\tmenu: #messageCategoryMenu:.\\n\\tmessageCategoryListView window: (0 @ 0 extent: 50 @ 70).\\n\\ttopView addSubView: messageCategoryListView toRightOf: classListView.\\n\\n\\tmessageListView := PluggableListView on: self\\n\\t\\tlist: #messageList\\n\\t\\tselected: #messageListIndex\\n\\t\\tchangeSelected: #messageListIndex:\\n\\t\\tmenu: #messageListMenu:shifted:\\n\\t\\tkeystroke: #messageListKey:from:.\\n\\tmessageListView window: (0 @ 0 extent: 50 @ 70).\\n\\ttopView addSubView: messageListView toRightOf: messageCategoryListView.\\n\\n\\tself wantsAnnotationPane\\n\\t\\tifTrue:\\n\\t\\t\\t[annotationPane := PluggableTextView on: self\\n\\t\\t\\t\\ttext: #annotation accept: nil\\n\\t\\t\\t\\treadSelection: nil menu: nil.\\n\\t\\t\\tannotationPane window: (0@0 extent: 200@self optionalAnnotationHeight).\\n\\t\\t\\ttopView addSubView: annotationPane below: packageListView.\\n\\t\\t\\tunderPane := annotationPane.\\n\\t\\t\\ty := 110 - self optionalAnnotationHeight]\\n\\t\\tifFalse:\\n\\t\\t\\t[underPane := packageListView.\\n\\t\\t\\ty := 110].\\n\\n\\tself wantsOptionalButtons ifTrue:\\n\\t\\t[optionalButtonsView := self buildOptionalButtonsView.\\n\\t\\toptionalButtonsView borderWidth: 1.\\n\\t\\ttopView addSubView: optionalButtonsView below: underPane.\\n\\t\\tunderPane := optionalButtonsView.\\n\\t\\ty := y - self optionalButtonHeight].\\n\\n\\tbrowserCodeView := MvcTextEditor default on: self \\n\\t\\t\\ttext: #contents accept: #contents:notifying:\\n\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:.\\n\\tbrowserCodeView window: (0@0 extent: 200@y).\\n\\ttopView addSubView: browserCodeView below: underPane.\\n\\taString ifNotNil: [browserCodeView editString: aString.\\n\\t\\t\\tbrowserCodeView hasUnacceptedEdits: true].\\n\\t^ topView! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:25'!\\npackage\\n\\t\\\"Answer the receiver's 'package'.\\\"\\n\\n\\t^ self hasPackageSelected\\n\\t\\tifFalse: [nil]\\n\\t\\tifTrue: [self packageList at: packageListIndex]\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 20:36'!\\npackageList\\n\\t\\\"Answer a list of the packages in the current system organization.\\\"\\n\\n\\t| str cats stream |\\n\\tstr := Set new: 100.\\n\\tstream := WriteStream on: (Array new: 100).\\n\\tsystemOrganizer categories do:\\n\\t\\t[ :categ | \\n\\t\\tcats := categ asString copyUpTo: $-.\\n\\t\\t(str includes: cats) ifFalse: \\n\\t\\t\\t[str add: cats.\\n\\t\\t\\tstream nextPut: cats]].\\n\\t^stream contents! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 19:48'!\\npackageListIndex\\n\\t\\\"Answer the index of the current package selection.\\\"\\n\\n\\t^packageListIndex! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 12/01/1998 02:46'!\\npackageListIndex: anInteger \\n\\t\\\"Set anInteger to be the index of the current package selection.\\\"\\n\\n\\tpackageListIndex := anInteger.\\n\\tanInteger = 0\\n\\t\\tifFalse: [package := self packageList at: packageListIndex].\\n\\tmessageCategoryListIndex := 0.\\n\\tsystemCategoryListIndex := 0.\\n\\tmessageListIndex := 0.\\n\\tclassListIndex := 0.\\n\\tself setClassOrganizer.\\n\\tself changed: #packageSelectionChanged.\\n\\tself changed: #packageListIndex.\\t\\\"update my selection\\\"\\n\\tself changed: #systemCategoryList.\\t\\\"update the category list\\\"\\n\\tself systemCategoryListIndex: 0.\\t\\\"update category list selection\\\"\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/06/1998 19:59'!\\npackageMenu: aMenu\\n\\t\\\"Answer a Menu of operations on class packages to be \\n\\tdisplayed when the operate menu button is pressed.\\\"\\n\\n\\t^aMenu\\n\\t\\t\\tlabels: 'find class...\\\\recent classes...\\\\reorganize\\\\update' withCRs\\n\\t\\t\\tlines: #(2)\\n\\t\\t\\tselections: #(#findClass #recent #editSystemCategories #updatePackages)! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'nk 2/14/2004 15:09'!\\nupdatePackages\\n\\t\\\"Update the contents of the package list.\\\"\\n\\n\\tself editSelection: #none.\\n\\tself changed: #packageList.\\n\\tself changed: #package.\\n\\tself packageListIndex: 0 ! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'JF 7/30/2003 12:23'!\\nhasSystemCategorySelected\\n\\t^ systemCategoryListIndex ~= 0! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'stp 01/13/2000 12:59'!\\nselectCategoryForClass: theClass\\n\\t\\\"Set the package and category lists to display the given class.\\\"\\n\\n\\t| cat |\\n\\tcat := theClass category.\\n\\tself packageListIndex: (self packageList indexOf: (cat copyUpTo: $-)).\\t\\n\\tself systemCategoryListIndex: (self systemCategoryList indexOf: \\n\\t\\t\\t(cat copyFrom: ((cat indexOf: $- ifAbsent: [0]) + 1) to: cat size)).! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/20/1999 20:16'!\\nselectedSystemCategoryName\\n\\t\\\"Answer the name of the selected system category or nil.\\\"\\n\\n\\tsystemCategoryListIndex = 0\\n\\t\\tifTrue: [^nil].\\n\\tpackageListIndex = 0\\n\\t\\tifTrue: [^ self systemCategoryList at: systemCategoryListIndex].\\n\\t^ self package , '-' , (self systemCategoryList at: systemCategoryListIndex)! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/16/1999 16:14'!\\nsystemCategoryList\\n\\t\\\"Answer the sequenceable collection containing the class categories that \\n\\tthe receiver accesses.\\\"\\n\\n\\t| prefix |\\n\\tpackageListIndex = 0 ifTrue: [^ systemOrganizer categories].\\n\\tprefix := self package, '-'.\\n\\t^ Array streamContents:\\n\\t\\t[:strm |\\n\\t\\tsystemOrganizer categories do: \\n\\t\\t\\t[ :cat | (cat beginsWith: prefix) ifTrue:\\n\\t\\t\\t\\t[strm nextPut: (cat copyFrom: prefix size + 1 to: cat size)]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackagePaneBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!PackagePaneBrowser class methodsFor: 'class initialization' stamp: 'hpt 8/5/2004 20:12'!\\nregisterInAppRegistry\\n\\t\\\"Register the receiver in the SystemBrowser AppRegistry\\\"\\n\\tSystemBrowser register: self.! !\\n\\n\\n!PackagePaneBrowser class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nprototypicalToolWindow\\n\\t\\\"Answer an example of myself seen in a tool window, for the benefit of parts-launching tools\\\"\\n\\n\\t| aWindow |\\n\\taWindow := self new openAsMorphEditing: nil.\\n\\taWindow setLabel: 'Package Browser'.\\n\\taWindow applyModelExtent.\\n\\t^ aWindow\\n! !\\n\\n\\n!PackagePaneBrowser class methodsFor: 'window color' stamp: 'sw 2/26/2002 14:39'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name wording: 'Package Browser' brightColor: #(1.0 1.0 0.6)\\t pastelColor: #(0.976 0.976 0.835) helpMessage: 'A system browser with an extra pane at top-left for module.'! !\\n\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'hpt 8/5/2004 20:12'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry;\\n\\t\\tregisterInAppRegistry.! !\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/10/2003 13:15'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(PackagePaneBrowser\\tprototypicalToolWindow\\t\\t'Packages'\\t\\t\\t'Package Browser: like a System Browser, except that if has extra level of categorization in the top-left pane, such that class-categories are further organized into groups called \\\"packages\\\"') \\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Tools']! !\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'hpt 8/5/2004 20:12'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self].\\n\\tSystemBrowser unregister: self.! !\\nObject subclass: #PackageServices\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ServiceClasses'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n\\n!PackageServices methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 14:06'!\\nseeClassSide! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageServices class\\n\\tinstanceVariableNames: ''!\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 13:01'!\\nallServices\\n\\t^ ServiceClasses gather: [:ea | ea services]! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ninitialize\\n\\tServiceClasses := Set new! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 12:59'!\\nregister: aClass\\n\\tServiceClasses add: aClass! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 12:59'!\\nunregister: aClass\\n\\tServiceClasses remove: aClass! !\\nImageMorph subclass: #PaintBoxColorPicker\\n\\tinstanceVariableNames: 'currentColor locOfCurrent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n!PaintBoxColorPicker commentStamp: 'JMM 9/13/2004 07:37' prior: 0!\\nA pop-up, 32-bit color palette used as part of a PaintBoxMorph.\\n!\\n\\n\\n!PaintBoxColorPicker methodsFor: 'accessing' stamp: 'jm 4/29/1998 20:07'!\\ncurrentColor\\n\\n\\t^ currentColor\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'accessing' stamp: 'jm 4/29/1998 20:18'!\\ncurrentColor: aColor\\n\\t\\\"Force me to select the given color.\\\"\\n\\n\\tcurrentColor _ aColor.\\n\\tlocOfCurrent _ nil. \\\"remove the marker\\\"\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'drawing' stamp: 'jm 4/29/1998 20:00'!\\ndrawOn: aCanvas\\n\\t\\\"Image plus circles for currently selected color.\\\"\\n\\n\\t| c |\\n\\tsuper drawOn: aCanvas.\\n\\tlocOfCurrent ifNotNil: [\\n\\t\\tc _ self ringColor.\\n\\t\\taCanvas\\n\\t\\t\\tfillOval: (Rectangle center: locOfCurrent + self topLeft extent: 9@9)\\n\\t\\t\\tcolor: Color transparent\\n\\t\\t\\tborderWidth: 1\\n\\t\\t\\tborderColor: c].\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'drawing' stamp: 'jm 4/29/1998 20:00'!\\nringColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\tcurrentColor isTransparent ifTrue: [^ Color red].\\n\\tcurrentColor red < 0.5 ifTrue: [^ Color red].\\n\\tcurrentColor red > (currentColor green + (currentColor blue * 0.5))\\n\\t\\tifTrue: [^ Color green]\\n\\t\\tifFalse: [^ Color red].\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'ar 10/5/2000 16:01'!\\nendColorSelection: evt\\n\\t\\\"Update current color and report it to paint box.\\\"\\n\\n\\tself selectColor: evt.\\n\\t\\\"restore mouseLeave handling\\\"\\n\\tself on: #mouseLeave send: #delete to: self.\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'ar 10/25/2000 17:49'!\\ninitMouseHandlers\\n\\n\\tself on: #mouseDown send: #startColorSelection: to: self.\\n\\tself on: #mouseMove send: #selectColor: to: self.\\n\\tself on: #mouseUp send: #endColorSelection: to: self.\\n\\tself on: #mouseLeave send: #delete to: self.\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'JMM 9/13/2004 09:08'!\\nselectColor: evt \\n\\t\\\"Update the receiver from the given event. Constrain locOfCurrent's center to lie within the color selection area. If it is partially in the transparent area, snap it entirely into it vertically.\\\"\\n\\n\\t| r |\\n\\n\\tlocOfCurrent := evt cursorPoint - self topLeft.\\n\\tr := Rectangle center: locOfCurrent extent: 9 @ 9.\\n\\tlocOfCurrent := locOfCurrent \\n\\t\\t\\t\\t+ (r amountToTranslateWithin: (8 @ 11 corner: (self image width-6) @ (self image height-6))).\\n\\tlocOfCurrent x > (self image width-(12+7)) ifTrue: [locOfCurrent := (self image width - 12) @ locOfCurrent y].\\t\\\"snap into grayscale\\\"\\n\\tcurrentColor := locOfCurrent y < 19\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[locOfCurrent := locOfCurrent x @ 11.\\t\\\"snap into transparent\\\"\\n\\t\\t\\t\\t\\tColor transparent]\\n\\t\\t\\t\\tifFalse: [image colorAt: locOfCurrent].\\n\\t(owner isKindOf: PaintBoxMorph) \\n\\t\\tifTrue: [owner takeColorEvt: evt from: self].\\n\\tself changed! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'jm 4/29/1998 21:21'!\\nstartColorSelection: evt\\n\\t\\\"Start color selection. Make me stay up as long as the mouse is down.\\\"\\n\\n\\tself on: #mouseLeave send: nil to: nil.\\n\\tself selectColor: evt.\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'initialization' stamp: 'RAA 8/15/2000 14:57'!\\nbeStatic\\n\\n\\t\\\"an aid for Nebraska: make the color chart a static image to reduce traffic\\\"\\n\\timage isStatic ifFalse: [\\n\\t\\timage _ image as: StaticForm\\n\\t].! !\\n\\n!PaintBoxColorPicker methodsFor: 'initialization' stamp: 'jm 4/29/1998 21:24'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tcurrentColor _ Color black.\\n\\tlocOfCurrent _ nil.\\n\\tself initMouseHandlers.\\n! !\\nImageMorph subclass: #PaintBoxMorph\\n\\tinstanceVariableNames: 'action tool currentCursor thumbnail currentColor currentBrush colorMemory colorPatch stampHolder rotationTabForm scaleTabForm colorMemoryThin brushes focusMorph weakDependents recentColors'\\n\\tclassVariableNames: 'AllOffImage AllOnImage AllPressedImage ColorChart OriginalBounds Prototype RecentColors'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'laza 3/24/2000 17:58'!\\naction\\n\\t^ action\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:35'!\\nactionCursor\\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\t^self\\n\\t\\tcursorFor: action\\n\\t\\toldCursor: currentCursor\\n\\t\\tcurrentNib: self getNib\\n\\t\\tcolor: currentColor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\nbrush: brushButton action: aSelector nib: aMask evt: evt \\n\\t\\\"Set the current tool and action for the paintBox. \\\"\\n\\n\\tcurrentBrush \\n\\t\\tifNotNil: [currentBrush == brushButton ifFalse: [currentBrush state: #off]].\\n\\tcurrentBrush := brushButton.\\t\\\"A ThreePhaseButtonMorph\\\"\\n\\n\\t\\\"currentBrush state: #on.\\talready done\\\"\\n\\t\\\"aSelector is like brush3:. Don't save it. Can always say (currentBrush arguments at: 2)\\n\\taMask is the brush shape. Don't save it. Can always say (currentBrush arguments at: 3)\\\"\\n\\tself notifyWeakDependentsWith: { \\n\\t\\t\\t\\t#currentNib.\\n\\t\\t\\t\\tevt.\\n\\t\\t\\t\\tcurrentBrush arguments third}.\\n\\tself brushable ifFalse: [self setAction: #paint: evt: evt]\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 10/19/97 11:12'!\\nbrushable\\n\\t\\\"Return true if the current tool uses a brush.\\\"\\n\\t^ (#(\\\"non-brushable\\\" eyedropper: fill: pickup: stamp:) indexOf: action) = 0! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:34'!\\nclear: clearButton with: clearSelector evt: evt\\n\\n\\t| ss |\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss clearPainting: self]\\n\\t\\tifNil: [self notCurrentlyPainting].\\n\\tclearButton state: #off.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/15/97 13:35'!\\ncolorable\\n\\t\\\"Return true if the current tool uses a color.\\\"\\n\\t^ (#(\\\"These use no color\\\" erase: eyedropper: \\\"fill: does\\\" pickup: stamp:) indexOf: action) = 0! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/17/2000 17:06'!\\ncurrentColor: aColor evt: evt\\n\\t\\\"Accept a color from the outside. (my colorMemoryMorph must call takeColorEvt: evt from: colorPicker instead)\\\"\\n\\n\\tcurrentColor _ aColor.\\n\\tcolorMemory currentColor: aColor.\\n\\tself notifyWeakDependentsWith: {#currentColor. evt. currentColor}.\\n\\tself showColor.\\n\\tself colorable ifFalse: [self setAction: #paint: evt: evt].\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:37'!\\ncursorFor: anAction oldCursor: oldCursor currentNib: aNibForm color: aColor \\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the \\n\\tform must be set.\\\"\\n\\n\\t| ff width co larger c box |\\n\\n\\tanAction == #paint:\\n\\t\\tifTrue: [\\\"Make a cursor from the brush and the color\\\"\\n\\t\\t\\twidth _ aNibForm width.\\n\\t\\t\\tc _ self ringColorFor: aColor.\\n\\t\\t\\tco _ oldCursor offset - (width // 4 @ 34 - (width // 6)) min: 0 @ 0.\\n\\t\\t\\tlarger _ width negated + 10 @ 0 extent: oldCursor extent + (width @ width).\\n\\t\\t\\tff _ oldCursor copy: larger.\\n\\t\\t\\tff colors at: 1 put: Color transparent.\\n\\t\\t\\tff colors at: 2 put: Color transparent.\\n\\t\\t\\tff offset: co - (width @ width // 2).\\n\\t\\t\\tff getCanvas\\n\\t\\t\\t\\tfillOval: (Rectangle center: ff offset negated extent: width @ width)\\n\\t\\t\\t\\tcolor: Color transparent\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: c.\\n\\t\\t\\t^ ff].\\n\\tanAction == #erase:\\n\\t\\tifTrue: [\\\"Make a cursor from the cursor and the color\\\"\\n\\t\\t\\twidth _ aNibForm width.\\n\\t\\t\\tco _ oldCursor offset + (width // 2 @ 4) min: 0 @ 0.\\n\\t\\t\\tlarger _ 0 @ 0 extent: oldCursor extent + (width @ width).\\n\\t\\t\\tff _ oldCursor copy: larger.\\n\\t\\t\\tff offset: co - (width @ width // 2).\\n\\t\\t\\tff\\n\\t\\t\\t\\tfill: (box _ co negated extent: width @ width)\\n\\t\\t\\t\\tfillColor: (Color r: 0.5 g: 0.5 b: 1.0).\\n\\t\\t\\tff\\n\\t\\t\\t\\tfill: (box insetBy: 1 @ 1)\\n\\t\\t\\t\\tfillColor: Color transparent.\\n\\t\\t\\t^ ff].\\n\\t^ oldCursor! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\ndeleteCurrentStamp: evt \\n\\t\\\"The trash is telling us to delete the currently selected stamp\\\"\\n\\n\\t(tool arguments second) == #stamp: \\n\\t\\tifTrue: \\n\\t\\t\\t[stampHolder remove: tool.\\n\\t\\t\\tself setAction: #paint: evt: evt]\\t\\\"no use stamping with a blank stamp\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'JMM 9/13/2004 09:47'!\\neyedropper: aButton action: aSelector cursor: aCursor evt: evt \\n\\t\\\"Take total control and pick up a color!!!!\\\"\\n\\n\\t| pt feedbackColor delay |\\n\\tdelay _ Delay forMilliseconds: 10.\\n\\taButton state: #on.\\n\\ttool ifNotNil: [tool state: #off].\\n\\tcurrentCursor := aCursor.\\n\\tevt hand showTemporaryCursor: currentCursor\\n\\t\\thotSpotOffset: 6 negated @ 4 negated.\\n\\t\\\"<<<< the form was changed a bit??\\\"\\n\\tfeedbackColor := Display colorAt: Sensor cursorPoint.\\n\\tcolorMemory align: colorMemory bounds topRight\\n\\t\\twith: colorMemoryThin bounds topRight.\\n\\tself addMorphFront: colorMemory.\\n\\n\\t\\\"Full color picker\\\"\\n\\t[Sensor anyButtonPressed] whileFalse: \\n\\t\\t\\t[pt := Sensor cursorPoint.\\n\\t\\t\\t\\\"deal with the fact that 32 bit displays may have garbage in the \\n\\t\\t\\talpha bits\\\"\\n\\t\\t\\tfeedbackColor := Display depth = 32 \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[Color colorFromPixelValue: ((Display pixelValueAt: pt) bitOr: 4278190080)\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: 32]\\n\\t\\t\\t\\t\\t\\tifFalse: [Display colorAt: pt].\\n\\t\\t\\t\\\"the hand needs to be drawn\\\"\\n\\t\\t\\tevt hand position: pt.\\n\\t\\t\\tcurrentColor ~= feedbackColor ifTrue: [\\n\\t\\t\\t\\tcurrentColor _ feedbackColor.\\n\\t\\t\\t\\tself showColor ].\\n\\t\\t\\tself world displayWorldSafely.\\n\\t\\t\\tdelay wait].\\n\\n\\t\\\"Now wait for the button to be released.\\\"\\n\\t[Sensor anyButtonPressed] whileTrue:\\n\\t\\t[ pt := Sensor cursorPoint.\\n\\t\\t\\\"the hand needs to be drawn\\\"\\n\\t\\tevt hand position: pt.\\n\\t\\tself world displayWorldSafely.\\n\\t\\tdelay wait].\\n\\n\\tevt hand showTemporaryCursor: nil hotSpotOffset: 0 @ 0.\\n\\tself currentColor: feedbackColor evt: evt.\\n\\tcolorMemory delete.\\n\\ttool ifNotNil: \\n\\t\\t\\t[tool state: #on.\\n\\t\\t\\tcurrentCursor := tool arguments third].\\n\\taButton state: #off\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 12:52'!\\ngetColor\\n\\t^ currentColor! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\ngetNib\\n\\t^currentBrush arguments third! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 13:02'!\\ngetSpecial\\n\\t^ action\\t\\t\\\"a selector like #paint:\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/21/2003 23:17'!\\ngrabFromScreen: evt \\n\\t\\\"Allow the user to grab a picture from the screen OUTSIDE THE PAINTING AREA and install it in a blank stamp. To get a stamp in the painting area, click on the stamp tool in a blank stamp.\\\"\\n\\n\\t\\\"scroll to blank stamp\\\"\\n\\n\\t| stampButton form |\\n\\tstampButton := stampHolder stampButtons first.\\n\\t[(stampHolder stampFormFor: stampButton) isNil] \\n\\t\\twhileFalse: [stampHolder scroll: 1].\\n\\tform := Form fromUser.\\n\\ttool state: #off.\\n\\ttool := stampHolder otherButtonFor: stampButton.\\n\\tstampHolder stampForm: form for: tool.\\t\\\"install it\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction: evt.\\n\\tevt hand showTemporaryCursor: (focusMorph getCursorFor: evt)! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'sw 8/29/2000 15:31'!\\nindicateColorUnderMouse\\n\\t\\\"Track the mouse with the special eyedropper cursor, and accept whatever color is under the mouse as the currently-chosen color; reflect that choice in the feedback box, and return that color.\\\"\\n\\n\\t| pt feedbackColor |\\n\\tpt _ Sensor cursorPoint.\\n\\t\\\"deal with the fact that 32 bit displays may have garbage in the alpha bits\\\"\\n\\tfeedbackColor _ Display depth = 32\\n\\t\\tifTrue: [ Color colorFromPixelValue: ((Display pixelValueAt: pt) bitOr: 16rFF000000) depth: 32] \\t\\tifFalse: [Display colorAt: pt].\\n\\n\\tself activeHand position: pt.\\n\\tself world displayWorldSafely.\\n\\tDisplay fill: colorPatch bounds fillColor: feedbackColor.\\n\\t^ feedbackColor\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:48'!\\nkeep: keepButton with: keepSelector evt: evt\\n\\t\\\"Showing of the corrent palette (viewer or noPalette) is done by the block submitted to the SketchMorphEditor, see (EToyHand makeNewDrawing) and (SketchMorph editDrawingInWorld:forBackground:).\\\"\\n\\t| ss |\\n\\towner ifNil: [^ self].\\n\\tkeepButton ifNotNil: [keepButton state: #off].\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss savePainting: self evt: evt]\\n\\t\\tifNil:\\n\\t\\t[keepSelector == #silent ifTrue: [^ self].\\n\\t\\tself notCurrentlyPainting].! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'sw 5/3/1998 18:22'!\\nnotCurrentlyPainting\\n\\tself inform: 'You are not currently painting'! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:04'!\\npickup: actionButton action: aSelector cursor: aCursor evt: evt \\n\\t\\\"Special version for pickup: and stamp:, because of these tests\\\"\\n\\n\\t| ss picker old map stamper |\\n\\tself \\n\\t\\ttool: actionButton\\n\\t\\taction: aSelector\\n\\t\\tcursor: aCursor\\n\\t\\tevt: evt.\\n\\taSelector == #stamp: \\n\\t\\tifTrue: \\n\\t\\t\\t[(stampHolder pickupButtons includes: actionButton) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[stamper := stampHolder otherButtonFor: actionButton.\\n\\t\\t\\t\\t\\t^self \\n\\t\\t\\t\\t\\t\\tpickup: stamper\\n\\t\\t\\t\\t\\t\\taction: #stamp:\\n\\t\\t\\t\\t\\t\\tcursor: (stamper arguments third)\\n\\t\\t\\t\\t\\t\\tevt: evt].\\n\\t\\t\\t(stampHolder stampFormFor: actionButton) ifNil: \\n\\t\\t\\t\\t\\t[\\\"If not stamp there, go to pickup mode\\\"\\n\\n\\t\\t\\t\\t\\tpicker := stampHolder otherButtonFor: actionButton.\\n\\t\\t\\t\\t\\tpicker state: #on.\\n\\t\\t\\t\\t\\t^self \\n\\t\\t\\t\\t\\t\\tpickup: picker\\n\\t\\t\\t\\t\\t\\taction: #pickup:\\n\\t\\t\\t\\t\\t\\tcursor: (picker arguments third)\\n\\t\\t\\t\\t\\t\\tevt: evt]\\n\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t[old := stampHolder stampFormFor: actionButton.\\n\\t\\t\\t\\t\\tcurrentCursor := ColorForm extent: old extent depth: 8.\\n\\t\\t\\t\\t\\told displayOn: currentCursor.\\n\\t\\t\\t\\t\\tmap := Color indexedColors copy.\\n\\t\\t\\t\\t\\tmap at: 1 put: Color transparent.\\n\\t\\t\\t\\t\\tcurrentCursor colors: map.\\n\\t\\t\\t\\t\\tcurrentCursor offset: currentCursor extent // -2.\\n\\t\\t\\t\\t\\t\\\"Emphisize the stamp button\\\"\\n\\t\\t\\t\\t\\tactionButton owner borderColor: (Color \\n\\t\\t\\t\\t\\t\\t\\t\\tr: 0.65\\n\\t\\t\\t\\t\\t\\t\\t\\tg: 0.599\\n\\t\\t\\t\\t\\t\\t\\t\\tb: 0.8)\\t\\\"layoutMorph\\\"\\t\\\"color: (Color r: 1.0 g: 0.645 b: 0.419);\\\"]].\\n\\taSelector == #pickup: \\n\\t\\tifTrue: \\n\\t\\t\\t[ss := self focusMorph.\\n\\t\\t\\tss ifNotNil: [currentCursor := aCursor]\\n\\t\\t\\t\\tifNil: \\n\\t\\t\\t\\t\\t[self notCurrentlyPainting.\\n\\t\\t\\t\\t\\tself setAction: #paint: evt: evt]]! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/2/97 22:13'!\\npickupForm: stampForm\\n\\t\\\"Install the new picture in this stamp\\\"\\n\\n\\t| stampButton |\\n\\tstampHolder stampForm: stampForm for: tool.\\n\\tstampButton _ action == #pickup: \\n\\t\\tifTrue: [stampHolder otherButtonFor: tool]\\n\\t\\tifFalse: [tool].\\t\\\"was a nil stampForm\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/17/2000 14:59'!\\npickupForm: stampForm evt: evt\\n\\t\\\"Install the new picture in this stamp\\\"\\n\\n\\t| stampButton |\\n\\tstampHolder stampForm: stampForm for: tool.\\n\\tstampButton _ action == #pickup: \\n\\t\\tifTrue: [stampHolder otherButtonFor: tool]\\n\\t\\tifFalse: [tool].\\t\\\"was a nil stampForm\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction: evt.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:40'!\\nplainCursor\\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\t^currentCursor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 10/10/2000 16:38'!\\nplainCursor: aCursor event: anEvent\\n\\t\\\"Set the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\tcurrentCursor _ aCursor.\\n\\tanEvent hand showTemporaryCursor: aCursor.\\n\\tself notifyWeakDependentsWith: {#currentCursor. anEvent. currentCursor}.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:30'!\\nringColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\t^self ringColorFor: currentColor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:29'!\\nringColorFor: aColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\taColor isTransparent ifTrue: [^ Color red].\\n\\taColor red < 0.5 ifTrue: [^ Color red].\\n\\taColor red > (aColor green + (aColor blue * 0.5))\\n\\t\\tifTrue: [^ Color green]\\n\\t\\tifFalse: [^ Color red].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:44'!\\nscrollStamps: actionButton action: aSelector evt: evt\\n\\t\\\"Move the stamps over\\\"\\n\\n\\taSelector == #prevStamp:\\n\\t\\tifTrue: [stampHolder scroll: -1]\\n\\t\\tifFalse: [stampHolder scroll: 1].\\n\\tactionButton state: #off.\\n\\taction == #stamp: ifTrue: [\\\"reselect the stamp and compute the cursor\\\"\\n\\t\\tself stampForm \\n\\t\\t\\tifNil: [self setAction: #paint: evt: evt]\\n\\t\\t\\tifNotNil: [tool doButtonAction: evt]].\\n\\t\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/22/2000 11:57'!\\nsetAction: aSelector evt: evt\\n\\t\\\"Find this button and turn it on. Does not work for stamps or pickups\\\"\\n\\n\\t| button |\\n\\tbutton _ self submorphNamed: aSelector.\\n \\n\\tbutton ifNotNil: [\\n\\t\\tbutton state: #on.\\n\\t\\tbutton doButtonAction: evt].\\t\\\"select it!!\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:04'!\\nshowColor\\n\\t\\\"Display the current color in all brushes, both on and off.\\\"\\n\\n\\t| offIndex onIndex center |\\n\\tcurrentColor ifNil: [^self].\\n\\t\\\"colorPatch color: currentColor.\\tMay delete later\\\"\\n\\t(brushes isNil or: [brushes first owner ~~ self]) \\n\\t\\tifTrue: \\n\\t\\t\\t[brushes := OrderedCollection new.\\n\\t\\t\\t#(#brush1: #brush2: #brush3: #brush4: #brush5: #brush6:) \\n\\t\\t\\t\\tdo: [:sel | brushes addLast: (self submorphNamed: sel)]].\\n\\tcenter := (brushes sixth) offImage extent // 2.\\n\\toffIndex := (brushes sixth) offImage pixelValueAt: center.\\n\\tonIndex := (brushes sixth) onImage pixelValueAt: center.\\n\\tbrushes do: \\n\\t\\t\\t[:bb | \\n\\t\\t\\tbb offImage colors at: offIndex + 1 put: currentColor.\\n\\t\\t\\tbb offImage clearColormapCache.\\n\\t\\t\\tbb onImage colors at: onIndex + 1 put: currentColor.\\n\\t\\t\\tbb onImage clearColormapCache.\\n\\t\\t\\tbb invalidRect: bb bounds].\\n\\tself invalidRect: (brushes first topLeft rect: brushes last bottomRight)! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 12/19/2000 19:16'!\\nshowColorPalette: evt\\n\\n\\t| w box |\\n\\tself comeToFront.\\n\\tcolorMemory align: colorMemory bounds topRight \\n\\t\\t\\twith: colorMemoryThin bounds topRight.\\n\\t\\\"make sure color memory fits or else align with left\\\"\\n\\tw _ self world.\\n\\tbox _ self bounds: colorMemory fullBounds in: w.\\n\\tbox left < 0 ifTrue:[\\n\\t\\tcolorMemory align: colorMemory bounds topLeft\\n\\t\\t\\twith: colorMemoryThin bounds topLeft].\\n\\tself addMorphFront: colorMemory.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/22/2000 11:58'!\\nstampCursorBeCursorFor: anAction\\n\\t\\\"User just chose a stamp. Take that stamp picture and make it be the cursor for the tool named.\\\"\\n\\t\\\"self stampCursorBeCursorFor: #star:.\\n\\tcurrentCursor offset: -9@-3.\\t\\t\\tHas side effect on the saved cursor.\\\"\\n\\n\\t(self submorphNamed: anAction) arguments at: 3 put: currentCursor.\\n\\t\\t\\\"Already converted to 8 bits and in the right form\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'di 5/6/1998 21:08'!\\nstampDeEmphasize\\n\\t\\\"Turn off an emphasized stamp. Was turned on in pickup:action:cursor:\\\"\\n\\n\\ttool owner class == AlignmentMorph ifTrue: [\\n\\t\\ttool \\\"actionButton\\\" owner \\\"layoutMorph\\\" color: Color transparent; \\n\\t\\t\\t\\t\\tborderColor: Color transparent].! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/2/97 14:02'!\\nstampForm\\n\\t\\\"Return the selected stamp\\\"\\n\\n\\t^ stampHolder stampFormFor: tool.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/17/97 11:47'!\\nstampHolder\\n\\n\\t^ stampHolder! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/17/97 11:48'!\\nstampHolder: newOne\\n\\n\\tstampHolder _ newOne! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 9/23/2000 20:00'!\\ntakeColor: aColor event: evt\\n\\t\\\"Accept the given color programmatically\\\"\\n\\tcurrentColor _ aColor.\\n\\tself notifyWeakDependentsWith: {#currentColor. evt. currentColor}.\\n\\tself showColor.\\n\\tself colorable ifFalse: [self setAction: #paint: evt: evt].\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 9/23/2000 20:39'!\\ntakeColorEvt: evt from: colorPicker\\n\\t\\\"Accept a new color from the colorMemory. Programs use currentColor: instead. Do not do this before the picker has a chance to set its own color!!\\\"\\n\\t^self takeColor: colorPicker currentColor event: evt! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/21/2000 16:06'!\\ntoggleShapes\\n\\t| tab sh stamps |\\n\\t\\\"The sub panel that has the shape tools on it. Rect, line...\\\"\\n\\tstamps _ self submorphNamed: 'stamps'.\\n\\ttab _ self submorphNamed: 'shapeTab'.\\n\\t(sh _ self submorphNamed: 'shapes') visible\\n\\t\\tifTrue: [sh hide. tab top: stamps bottom-1]\\n\\t\\tifFalse: [sh comeToFront. sh top: stamps bottom-9. \\n\\t\\t\\t\\tsh show. tab top: sh bottom - tab height + 10].\\n\\tself layoutChanged.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/21/2000 15:57'!\\ntoggleStamps\\n\\t| tab otherTab st shapes |\\n\\t\\\"The sub panel that has the stamps in it. For saving and moving parts of an image.\\\"\\n\\tshapes _ self submorphNamed: 'shapes'.\\n\\totherTab _ self submorphNamed: 'shapeTab'.\\n\\ttab _ self submorphNamed: 'stampTab'.\\n\\t(st _ self submorphNamed: 'stamps') visible\\n\\t\\tifTrue: [st hide. st bottom: self bottom. tab top: self bottom-1.\\n\\t\\t\\t\\tshapes top: self bottom-9.\\n\\t\\t\\t\\totherTab top: (shapes visible ifTrue: [shapes bottom - otherTab height + 10] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [self bottom-1])]\\n\\t\\tifFalse: [st top: self bottom-10. st show. tab top: st bottom-0.\\n\\t\\t\\t\\tshapes top: st bottom-9.\\n\\t\\t\\t\\totherTab top: (shapes visible ifTrue: [shapes bottom - otherTab height + 10] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [st bottom-0])].\\n\\tself layoutChanged.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 12:09'!\\ntool\\n\\t^ tool! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 12:38'!\\ntool: actionButton action: aSelector cursor: aCursor evt: evt\\n\\t\\\"Set the current tool and action for the paintBox. \\\"\\n\\n\\ttool ifNotNil: [\\n\\t\\ttool == actionButton ifFalse: [\\n\\t\\t\\ttool state: #off.\\n\\t\\t\\taction == #stamp: ifTrue: [self stampDeEmphasize]]].\\n\\ttool _ actionButton.\\t\\t\\\"A ThreePhaseButtonMorph\\\"\\n\\t\\\"tool state: #on.\\talready done\\\"\\n\\taction _ aSelector.\\t\\t\\\"paint:\\\"\\n\\tcurrentCursor _ aCursor.\\n\\tself notifyWeakDependentsWith: {#action. evt. action}.\\n\\tself notifyWeakDependentsWith: {#currentCursor. evt. currentCursor}.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:45'!\\ntoss: cancelButton with: cancelSelector evt: evt\\n\\t\\\"Reject the painting. Showing noPalette is done by the block submitted to the SketchEditorMorph\\\"\\n\\n\\t| focus |\\n\\towner ifNil: [\\\"it happens\\\" ^ self].\\n\\t(focus _ self focusMorph) \\n\\t\\tifNotNil: [focus cancelPainting: self evt: evt]\\n\\t\\tifNil:\\n\\t\\t\\t[self delete].\\n\\tcancelButton state: #off.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 11:15'!\\nundo: undoButton with: undoSelector evt: evt\\n\\t| ss |\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss undoPainting: self evt: evt]\\n\\t\\tifNil: [self notCurrentlyPainting].\\n\\tundoButton state: #off.! !\\n\\n\\n!PaintBoxMorph methodsFor: 'copying' stamp: 'di 10/14/97 10:13'!\\nupdateReferencesUsing: aDictionary\\n\\t\\\"Fix up stampHolder which is a ScrollingToolHolder, which is not a Morph\\\"\\n\\n\\tsuper updateReferencesUsing: aDictionary.\\n\\tstampHolder updateReferencesUsing: aDictionary.\\n\\tcolorMemory updateReferencesUsing: aDictionary.! !\\n\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 16:47'!\\naddWeakDependent: anObject\\n\\n\\tweakDependents ifNil: [^weakDependents _ WeakArray with: anObject].\\n\\tweakDependents _ weakDependents,{anObject} reject: [ :each | each isNil].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 14:59'!\\nbeStatic\\n\\n\\tcolorMemory ifNotNil: [colorMemory beStatic].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:53'!\\ncreateButtons\\n\\t\\\"Create buttons one at a time and let the user place them over the background. Later can move them again by turning on AuthorModeOwner in ThreePhaseButtonMorph.\\n\\tself createButtons.\\t\\\"\\n\\n\\t| rect button nib |\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: pickup: \\\"pickup: pickup: pickup:\\\" stamp: \\\"stamp: stamp: stamp:\\\" undo: keep: toss: prevStamp: nextStamp:) do: [:sel |\\n\\t\\t(self submorphNamed: sel) ifNil:\\n\\t\\t\\t[self inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ ThreePhaseButtonMorph new.\\n\\t\\t\\tbutton onImage: nil; bounds: rect.\\n\\t\\t\\tself addMorph: button.\\n\\t\\t\\tbutton actionSelector: #tool:action:cursor:evt:; arguments: (Array with: button with: sel with: nil).\\n\\t\\t\\tbutton actWhen: #buttonUp; target: self]].\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6: ) doWithIndex: [:sel :ind |\\n\\t\\t(self submorphNamed: sel) ifNil:\\n\\t\\t\\t[self inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ ThreePhaseButtonMorph new.\\n\\t\\t\\tbutton onImage: nil; bounds: rect.\\n\\t\\t\\tself addMorph: button.\\n\\t\\t\\tnib _ Form dotOfSize: (#(1 2 3 6 11 26) at: ind).\\n\\t\\t\\tbutton actionSelector: #brush:action:nib:evt:; \\n\\t\\t\\t\\t\\targuments: (Array with: button with: sel with: nib).\\n\\t\\t\\tbutton actWhen: #buttonUp; target: self]].\\n\\t\\\"stamp: Stamps are held in a ScrollingToolHolder. Pickups and stamps and brushes are id-ed by the button == with item from a list.\\\"\\n\\n\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 19:39'!\\nfixupButtons\\n\\t| changes answer newSelector |\\n\\tchanges := Dictionary new.\\n\\tchanges\\n\\t\\tat: #brush:action:nib: put: #brush:action:nib:evt:;\\n\\t\\tat: #tool:action:cursor: put: #tool:action:cursor:evt:;\\n\\t\\tat: #pickup:action:cursor: put: #pickup:action:cursor:evt:;\\n\\t\\tat: #keep:with: put: #keep:with:evt:;\\n\\t\\tat: #undo:with: put: #undo:with:evt:;\\n\\t\\tat: #scrollStamps:action: put: #scrollStamps:action:evt:;\\n\\t\\tat: #toss:with: put: #toss:with:evt:;\\n\\t\\tat: #eyedropper:action:cursor: put: #eyedropper:action:cursor:evt:;\\n\\t\\tat: #clear:with: put: #clear:with:evt:.\\n\\tanswer := WriteStream on: String new.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each isKindOf: ThreePhaseButtonMorph) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[answer nextPutAll: each actionSelector.\\n\\t\\t\\t\\t\\t(changes includesKey: each actionSelector) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[each actionSelector: (newSelector := changes at: each actionSelector).\\n\\t\\t\\t\\t\\t\\t\\tanswer nextPutAll: ' <-- ' , newSelector].\\n\\t\\t\\t\\t\\tanswer cr]].\\n\\t^answer contents\\n\\t\\\"StringHolder new\\n\\t\\tcontents: answer contents;\\n\\t\\topenLabel: 'button fixups'\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 19:03'!\\ninit3\\n\\t\\\"Just a record of how we loaded in the latest paintbox button images\\\"\\n\\n\\t| bb rect lay pic16Bit aa blt on thin |\\n\\tself loadoffImage: 'etoy_default.gif'.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:button | \\n\\t\\t\\t(button isKindOf: ThreePhaseButtonMorph) \\n\\t\\t\\t\\tifTrue: [button offImage: nil]\\n\\t\\t\\t\\tifFalse: [button position: button position + (100 @ 0)]].\\n\\t(bb := self submorphNamed: #keep:) position: bb position + (100 @ 0).\\n\\t(bb := self submorphNamed: #toss:) position: bb position + (100 @ 0).\\n\\t(bb := self submorphNamed: #undo:) position: bb position + (100 @ 0).\\n\\t\\\"Transparent is (Color r: 1.0 g: 0 b: 1.0)\\\"\\n\\tself moveButtons.\\n\\tself loadOnImage: 'etoy_in.gif'.\\n\\tAllOnImage := nil.\\n\\t'save space'.\\n\\tself loadPressedImage: 'etoy_in.gif'.\\n\\tAllPressedImage := nil.\\n\\t'save space'.\\n\\tself loadCursors.\\n\\n\\t\\\"position the stamp buttons\\\"\\n\\tstampHolder stampButtons owner last delete.\\n\\tstampHolder pickupButtons last delete.\\n\\tstampHolder stampButtons: (stampHolder stampButtons copyFrom: 1 to: 3).\\n\\tstampHolder pickupButtons: (stampHolder pickupButtons copyFrom: 1 to: 3).\\n\\t\\\"| rect |\\\"\\n\\tstampHolder pickupButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\t\\\"PopUpMenu notify: 'Rectangle for ',sel.\\\"\\n\\n\\t\\t\\trect := Rectangle fromUser.\\n\\t\\t\\tbutton bounds: rect\\t\\\"image is nil\\\"].\\n\\t\\\"| rect lay |\\\"\\n\\tstampHolder clear.\\n\\tstampHolder stampButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\tbutton\\n\\t\\t\\t\\toffImage: nil;\\n\\t\\t\\t\\tpressedImage: nil.\\n\\t\\t\\tlay := button owner.\\n\\t\\t\\t\\\"PopUpMenu notify: 'Rectangle for ',sel.\\\"\\n\\t\\t\\trect := Rectangle fromUser.\\n\\t\\t\\tbutton image: (Form fromDisplay: (rect insetBy: 2)).\\n\\t\\t\\tlay borderWidth: 2.\\n\\t\\t\\tlay bounds: rect\\t\\\"image is nil\\\"].\\n\\t\\\"| pic16Bit blt aa on |\\\"\\n\\tpic16Bit := GIFReadWriter formFromFileNamed: 'etoy_in.gif'.\\t\\\"really 8\\\"\\n\\taa := Form extent: OriginalBounds extent depth: 8.\\n\\tblt := BitBlt current toForm: aa.\\n\\tblt\\n\\t\\tsourceForm: pic16Bit;\\n\\t\\tcombinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds;\\n\\t\\tdestOrigin: 0 @ 0;\\n\\t\\tcopyBits.\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tstampHolder pickupButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\ton := ColorForm extent: button extent depth: 8.\\n\\t\\t\\ton colors: pic16Bit colors.\\n\\t\\t\\ton \\n\\t\\t\\t\\tcopy: (0 @ 0 extent: button extent)\\n\\t\\t\\t\\tfrom: button topLeft - self topLeft\\n\\t\\t\\t\\tin: aa\\n\\t\\t\\t\\trule: Form over.\\n\\t\\t\\tbutton\\n\\t\\t\\t\\timage: on;\\n\\t\\t\\t\\tpressedImage: on;\\n\\t\\t\\t\\toffImage: nil].\\n\\tself invalidRect: bounds.\\n\\t((self submorphNamed: #erase:) arguments third) offset: 12 @ 35.\\n\\t((self submorphNamed: #eyedropper:) arguments third) offset: 0 @ 0.\\n\\t((self submorphNamed: #fill:) arguments third) offset: 10 @ 44.\\n\\t((self submorphNamed: #paint:) arguments third) offset: 3 @ 3.\\t\\\"unused\\\"\\n\\t((self submorphNamed: #rect:) arguments third) offset: 6 @ 17.\\n\\t((self submorphNamed: #ellipse:) arguments third) offset: 5 @ 4.\\n\\t((self submorphNamed: #polygon:) arguments third) offset: 5 @ 4.\\n\\t((self submorphNamed: #line:) arguments third) offset: 5 @ 17.\\n\\t((self submorphNamed: #star:) arguments third) offset: 2 @ 5.\\n\\tthumbnail delete.\\n\\tthumbnail := nil.\\n\\t(submorphs select: [:e | e class == RectangleMorph]) first \\n\\t\\tbounds: Rectangle fromUser.\\n\\t((submorphs select: [:e | e class == RectangleMorph]) first)\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: Color black.\\n\\t\\\"| thin |\\\"\\n\\tsubmorphs do: [:ss | ss class == ImageMorph ifTrue: [thin := ss\\t\\\"first\\\"]].\\n\\tcolorMemoryThin := thin! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 8/22/2000 11:56'!\\ninit4\\n\\t\\\"Just a record of how Ted loaded in the paintbox button images, Feb 98\\\"\\n| bb im pp newImage pic24Bit picNewBit blt |\\n\\n\\\"self loadoffImage: 'roundedPalette3.bmp'.\\\"\\npic24Bit _ GIFReadWriter formFromServerFile: 'updates/137roundedPalette3.bmp'.\\npicNewBit _ Form extent: pic24Bit extent depth: 16.\\npic24Bit displayOn: picNewBit.\\nOriginalBounds _ picNewBit boundingBox.\\nAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\nblt _ BitBlt current toForm: AllOffImage.\\nblt sourceForm: picNewBit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\nAllOffImage mapColor: Color transparent to: Color black.\\nself image: AllOffImage.\\nself invalidRect: bounds.\\n\\nself submorphsDo: [:button | button position: button position + (10@10)].\\n(im _ submorphs at: 28) class == ImageMorph ifTrue: [\\n\\tim position: im position + (2@0)].\\t\\\"color picker\\\"\\n\\\"exercise it once\\\"\\n\\n(bb _ self submorphNamed: #keep:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #toss:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #undo:) position: bb position + (0@-25).\\n(bb _ self submorphNamed: #clear:) position: bb position + (0@-25).\\n(bb _ self submorphNamed: #undo:) position: bb position + (0@-69).\\n(bb _ self submorphNamed: #clear:) position: bb position + (0@-69).\\nself submorphsDo: [:button | \\n\\tbutton class == AlignmentMorph ifTrue: [\\n\\t\\tbutton position: button position + (0@25)].\\n\\t(button printString includesSubString: 'stamp:') ifTrue: [\\n\\t\\tbutton position: button position + (0@25)]].\\n(bb _ self submorphNamed: #prevStamp:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #nextStamp:) position: bb position + (0@25).\\n\\nbb _ self submorphNamed: #keep:.\\nnewImage _ bb pressedImage copy: (0@4 corner: (bb pressedImage boundingBox extent)).\\nbb onImage: newImage. bb pressedImage: newImage. bb extent: newImage extent.\\nbb position: bb position + (4@1).\\n\\npp _ (bb _ self submorphNamed: #toss:) pressedImage.\\nnewImage _ pp copy: (0@4 corner: (bb pressedImage extent - (3@0))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@1).\\n\\npp _ (bb _ self submorphNamed: #undo:) pressedImage.\\nnewImage _ pp copy: (0@0 corner: (bb pressedImage extent - (3@5))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@-1).\\n\\npp _ (bb _ self submorphNamed: #clear:) pressedImage.\\nnewImage _ pp copy: (0@0 corner: (bb pressedImage extent - (0@5))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@-1).\\n\\npic24Bit _ GIFReadWriter formFromServerFile: 'updates/137pencil.bmp'.\\npicNewBit _ Form extent: pic24Bit extent depth: 16.\\npic24Bit displayOn: picNewBit.\\nnewImage _ picNewBit as8BitColorForm.\\nnewImage transparentColor: (Color r: 0 g: 0 b: 0).\\n(bb _ self submorphNamed: #erase:) pressedImage: newImage; onImage: newImage;\\n\\textent: newImage extent.\\n\\nbb position: bb position + (-11@-1).\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 7/28/2000 23:26'!\\ninitialize\\n\\tsuper initialize.\\n\\tcolorMemory ifNotNil: [colorMemory on: #mouseDown send: #takeColorEvt:from: to: self].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'jm 6/18/1999 18:58'!\\nloadColorChooser\\n\\t\\\"Load Forms for ColorMemoryMorph.\\\"\\n\\n\\t| doc closedForm openForm |\\n\\tdoc _ Utilities objectStrmFromUpdates: 'colorPalClosed.obj'.\\n\\tclosedForm _ doc fileInObjectAndCode mapColor: Color transparent to: Color black.\\n\\tdoc _ Utilities objectStrmFromUpdates: 'colorPalOpen.obj'.\\n\\topenForm _ doc fileInObjectAndCode mapColor: Color transparent to: Color black.\\n\\n\\tcolorMemoryThin image: closedForm.\\n\\tcolorMemoryThin position: self position + (0@140).\\n\\n\\tcolorMemory delete.\\t\\\"delete old one\\\"\\n\\tcolorMemory _ PaintBoxColorPicker new image: openForm.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:54'!\\nloadCursors\\n\\t\\\"Display the form containing the cursors. Transparent is (Color r: 1.0 g: 0 b: 1.0). Grab the forms one at a time, and they are stored away.\\n\\tself loadCursors.\\t\\\"\\n\\n\\t| button transp cursor map |\\n\\ttransp _ Color r: 1.0 g: 0 b: 1.0.\\n\\tmap _ Color indexedColors copy.\\t\\\"just in case\\\"\\n\\t1 to: 256 do: [:ind | (map at: ind) = transp ifTrue: \\n\\t\\t\\t\\t[map at: ind put: Color transparent]].\\n\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: ) do: [:sel |\\n\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\tcursor _ ColorForm fromUser.\\n\\t\\tcursor colors: map.\\t\\\"share it\\\"\\n\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\tbutton arguments at: 3 put: cursor].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 1/13/2005 12:20'!\\nloadJapanesePaintBoxBitmaps\\n\\\"\\n\\tPaintBoxMorph new loadJapanesePaintBoxBitmaps.\\n\\\"\\n\\n\\t| formTranslator form bb |\\n\\tself position: 0@0.\\n\\tformTranslator _ NaturalLanguageFormTranslator localeID: (LocaleID isoString: 'ja').\\n\\tform _ Form fromFileNamed: 'offPaletteJapanese(children).form'.\\n\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\tbb _ (self submorphs detect: [:e | e externalName = extName]) bounds.\\n\\t\\tformTranslator name: label, '-off' form: (form copy: bb)\\n\\t].\\n\\n\\n\\tform _ Form fromFileNamed: 'pressedPaletteJapanese(children).form'.\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\tbb _ (self submorphs detect: [:e | e externalName = extName]) bounds.\\n\\t\\tformTranslator name: label, '-pressed' form: (form copy: bb)\\n\\t].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 11/4/2002 21:20'!\\nloadOffForm: pic16Bit \\n\\t\\\"Prototype loadOffForm: (Smalltalk imageImports at: #offPaletteJapanese)\\\"\\n\\n\\t| blt |\\n\\tOriginalBounds _ pic16Bit boundingBox.\\n\\tAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: AllOffImage.\\n\\tblt sourceForm: pic16Bit;\\n\\t\\t combinationRule: Form over;\\n\\t\\t sourceRect: OriginalBounds;\\n\\t\\t destOrigin: 0 @ 0;\\n\\t\\t copyBits.\\n\\tAllOffImage mapColor: Color blue to: Color transparent.\\n\\tself image: AllOffImage.\\n\\tAllOffImage _ nil.\\n\\tself invalidRect: bounds\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'ar 5/28/2000 12:10'!\\nloadOnImage: fileName\\n\\t\\\"Read in and convert the image for the paintBox with the buttons\\non. A .bmp 24-bit image. For each button, cut that chunk out and save it.\\\"\\n\\t\\\"\\tself loadOnImage: 'NoSh_on.bmp'.\\n\\t\\tAllOnImage _ nil.\\t'save space'.\\t\\\"\\n\\n\\t| pic16Bit blt aa on type |\\n\\ttype _ 'gif'. \\\" gif or bmp \\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tpic16Bit display.\\n\\taa _ AllOnImage _ Form extent: OriginalBounds extent depth: 8.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\t].\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tpic16Bit display.\\n\\taa _ AllOnImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\taa mapColor: Color transparent to: Color black.\\n\\t].\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ttype = 'gif' ifTrue: [on _ ColorForm extent: button extent depth: 8.\\n\\t\\t\\t\\t\\t on colors: pic16Bit colors]\\n\\t\\t\\t\\tifFalse: [on _ Form extent: button extent depth: 16].\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in: aa rule: Form over.\\n\\t\\t\\tbutton onImage: on]].\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 11/4/2002 21:20'!\\nloadPressedForm: pic16Bit \\n\\t\\\"Prototype loadPressedForm: (Smalltalk imageImports at: #pressedPaletteJapanese)\\\"\\n\\n\\t| blt on |\\n\\tAllPressedImage _ AllPressedImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: AllPressedImage.\\n\\tblt sourceForm: pic16Bit;\\n\\t\\t combinationRule: Form over;\\n\\t\\t sourceRect: OriginalBounds;\\n\\t\\t destOrigin: 0 @ 0;\\n\\t\\t copyBits.\\n\\tAllPressedImage mapColor: Color black to: Color transparent.\\n\\tself\\n\\t\\tallMorphsDo: [:button | (button isKindOf: ThreePhaseButtonMorph)\\n\\t\\t\\t\\tifTrue: [on _ Form extent: button extent depth: 16.\\n\\t\\t\\t\\t\\ton\\n\\t\\t\\t\\t\\t\\tcopy: (0 @ 0 extent: button extent)\\n\\t\\t\\t\\t\\t\\tfrom: button topLeft - self topLeft\\n\\t\\t\\t\\t\\t\\tin: AllPressedImage\\n\\t\\t\\t\\t\\t\\trule: Form over.\\n\\t\\t\\t\\t\\tbutton pressedImage: on]].\\n\\tAllPressedImage _ nil.\\n\\tself invalidRect: bounds\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'ar 5/28/2000 12:10'!\\nloadPressedImage: fileName\\n\\t\\\"Read in and convert the image for the paintBox with the buttons\\non. A .bmp 24-bit image. For each button, cut that chunk out and save it.\\\"\\n\\t\\\"\\tself loadPressedImage: 'NoSh_on.bmp'.\\n\\t\\tAllPressedImage _ nil.\\t'save space'.\\t\\\"\\n\\n\\t| pic16Bit blt aa on type |\\n\\ttype _ 'gif'. \\\" gif or bmp \\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tpic16Bit display.\\n\\taa _ AllPressedImage _ Form extent: OriginalBounds extent depth: 8.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\t].\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tpic16Bit display.\\n\\taa _ AllPressedImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\taa mapColor: Color transparent to: Color black.\\n\\t].\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ttype = 'gif' ifTrue: [on _ ColorForm extent: button extent depth: 8.\\n\\t\\t\\t\\t\\t on colors: pic16Bit colors]\\n\\t\\t\\t\\tifFalse: [on _ Form extent: button extent depth: 16].\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in: aa rule: Form over.\\n\\t\\t\\tbutton pressedImage: on]].\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'md 11/14/2003 16:52'!\\nloadoffImage: fileName\\n\\t\\\"Read in and convert the background image for the paintBox. All\\nbuttons off. A .bmp 24-bit image.\\\"\\n\\t\\\"\\tPrototype loadoffImage: 'roundedPalette3.bmp'\\t\\\"\\n\\n\\t| pic16Bit blt type getBounds |\\n\\ttype _ 'bmp'. \\\" gif or bmp \\\"\\n\\tgetBounds _ 'fromPic'.\\t\\\"fromUser = draw out rect of paintbox on image\\\"\\n\\t\\t\\\"fromOB = just read in new bits, keep same size and place as last time.\\\"\\n\\t\\t\\\"fromPic = picture is just the PaintBox, use its bounds\\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tgetBounds = 'fromUser' ifTrue: [\\\"Just first time, collect the bounds\\\"\\n\\t\\t\\tpic16Bit display.\\n\\t\\t\\tOriginalBounds _ Rectangle fromUser].\\n\\tgetBounds = 'fromPic' ifTrue: [OriginalBounds _ pic16Bit boundingBox].\\n\\t].\\n\\t\\t\\\"Use OriginalBounds as it was last time\\\"\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tgetBounds = 'fromUser' ifTrue: [\\\"Just first time, collect the bounds\\\"\\n\\t\\t\\tpic16Bit display.\\n\\t\\t\\tOriginalBounds _ Rectangle fromUser].\\n\\t\\t\\\"Use OriginalBounds as it was last time\\\"\\n\\t(getBounds = 'fromPic') ifTrue: [OriginalBounds _ pic16Bit boundingBox].\\n\\tAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\n\\t].\\n\\ntype = 'gif' ifTrue: [\\n\\tAllOffImage _ ColorForm extent: OriginalBounds extent depth: 8.\\n\\tAllOffImage colors: pic16Bit colors].\\n\\n\\tblt _ BitBlt current toForm: AllOffImage.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\ntype = 'bmp' ifTrue: [AllOffImage mapColor: Color transparent to: Color black].\\n\\tself image: AllOffImage.\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:54'!\\nmoveButtons\\n\\t\\\"Move buttons one at a time and let the user place them over the background. Later can move them again by turning on AuthorModeOwner in ThreePhaseButtonMorph.\\n\\tself createButtons.\\t\\\"\\n\\n\\t| rect button |\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: \\\"pickup: pickup: pickup: pickup:\\\" \\\"stamp: stamp: stamp: stamp:\\\" undo: keep: toss: prevStamp: nextStamp:) do: [:sel |\\n\\t\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\t\\tbutton bounds: rect.\\t\\\"image is nil\\\"].\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6: ) doWithIndex: [:sel :ind |\\n\\t\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\t\\tbutton bounds: rect.\\t\\\"image is nil\\\"].\\n\\t\\\"stamp: Stamps are held in a ScrollingToolHolder. Pickups and stamps and brushes are id-ed by the button == with item from a list.\\\"\\n\\n\\t\\\"\\n\\t\\\"\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 8/22/97 15:57'!\\nnoVeneer\\n\\t\\\"For a palette with a background (off) image, clear that image.\\nBut first, for each button, cut that chunk out and save it in the offImage\\npart.\\\"\\n\\t\\\"\\tself noVeneer.\\n\\t\\tAllOffImage _ nil.\\t'save space. irreversible'.\\t\\\"\\n\\n\\t| aa on |\\n\\tAllOffImage ifNil: [AllOffImage _ image].\\n\\taa _ AllOffImage.\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ton _ Form extent: button extent depth: 16.\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in:\\naa rule: Form over.\\n\\t\\t\\tbutton offImage: on]].\\n\\tself image: (Form extent: AllOffImage extent depth: 1).\\n\\tself invalidRect: bounds.\\n\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/16/2000 11:12'!\\nnotifyWeakDependentsWith: arguments\\n\\n\\tweakDependents ifNil: [^self].\\n\\tweakDependents do: [ :each |\\n\\t\\teach ifNotNil: [\\n\\t\\t\\teach paintBoxChanged: arguments.\\n\\t\\t\\teach paintBoxChanged: {#changed. arguments second. true}.\\n\\t\\t].\\n\\t].! !\\n\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'dgd 8/30/2003 21:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\t\\\"super addCustomMenuItems: aCustomMenu hand: aHandMorph.\\\"\\n\\t\\t\\\"don't want the ones from ImageMorph\\\"\\n\\taCustomMenu add: 'grab stamp from screen' translated action: #grabFromScreen:.\\n\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 14:08'!\\naddGraphicLabels\\n\\t\\\"translate button labels\\\"\\n\\n\\t| formTranslator ext pos newForm |\\n\\tformTranslator _ NaturalLanguageFormTranslator localeID: (Locale current localeID).\\n\\n\\t#('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:label |\\n\\t\\t(formTranslator translate: label, '-off') ifNil: [^ false].\\n\\t\\t(formTranslator translate: label, '-pressed') ifNil: [^ false].\\n\\t].\\n\\t\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\t| button |\\n\\t\\tbutton _ submorphs detect: [:m | m externalName = extName] ifNone: [nil].\\n\\t\\tbutton ifNotNil: [\\n\\t\\t\\tbutton removeAllMorphs.\\n\\t\\t\\text _ button extent.\\n\\t\\t\\tpos _ button position.\\n\\t\\t\\t(newForm _ formTranslator translate: label, '-off') ifNotNil: [\\n\\t\\t\\t\\tbutton offImage: newForm.\\n\\n\\t\\t\\t].\\n\\t\\t\\t(newForm _ formTranslator translate: label, '-pressed') ifNotNil: [\\n\\t\\t\\t\\tbutton pressedImage: newForm.\\n\\t\\t\\t].\\n\\t\\t\\tbutton extent: ext.\\n\\t\\t\\tbutton position: pos.\\n\\t\\t].\\n\\t].\\n\\n\\t^ true.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 14:08'!\\naddLabels\\n\\n\\tPreferences useFormsInPaintBox ifFalse: [\\n\\t\\tself addTextualLabels.\\n\\t] ifTrue: [\\n\\t\\tself addGraphicLabels ifFalse: [self addTextualLabels].\\n\\t].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 11:06'!\\naddTextualLabels\\n\\t\\\"translate button labels\\\"\\n\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\t| button |\\n\\t\\tbutton _ submorphs detect: [:m | m externalName = extName] ifNone: [nil].\\n\\t\\tbutton ifNotNil: [\\n\\t\\t\\tbutton removeAllMorphs.\\n\\t\\t\\tbutton addMorph: (TextMorph new \\n\\t\\t\\t\\tcontentsWrapped: (Text string: label translated\\n\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\tTextAlignment centered. \\n\\t\\t\\t\\t\\t\\tTextEmphasis bold.\\n\\t\\t\\t\\t\\t\\tTextFontReference toFont:\\n\\t\\t\\t\\t\\t\\t\\t(Preferences standardPaintBoxButtonFont)});\\n\\t\\t\\t\\tbounds: (button bounds translateBy: 0@3);\\n\\t\\t\\t\\tlock)]]! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 10/31/97 13:38'!\\ncolorMemory\\n\\n\\t^ colorMemory! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'di 10/14/97 10:15'!\\ncolorMemory: aMorph\\n\\n\\tcolorMemory _ aMorph! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 10/31/97 13:35'!\\ncolorPatch\\n\\t^ colorPatch! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'ar 3/23/2000 14:18'!\\nfocusMorph\\n\\t\\\"Note: For backward compatibility we search the world for a SketchEditorMorph if the current focus morph is nil\\\"\\n\\t^focusMorph ifNil:[focusMorph _ self world findA: SketchEditorMorph]! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'ar 3/23/2000 14:20'!\\nfocusMorph: newFocus\\n\\t\\\"Set the new focus morph\\\"\\n\\tfocusMorph ifNotNil:[focusMorph paletteDetached: self]. \\\"In case the morph is interested\\\"\\n\\tfocusMorph _ newFocus.\\n\\tfocusMorph ifNotNil:[focusMorph paletteAttached: self]. \\\"In case the morph is interested\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 8/22/2000 11:57'!\\nmaxBounds\\n\\t| rr |\\n\\t\\\"fullBounds if all flop-out parts of the paintBox were showing.\\\"\\n\\n\\trr _ bounds merge: colorMemory bounds.\\n\\trr _ rr merge: (self submorphNamed: 'stamps') bounds.\\n\\trr _ rr origin corner: rr corner + (0@ (self submorphNamed: 'shapes') height \\n\\t\\t\\t\\t+ 10 \\\"what is showing of (self submorphNamed: #toggleShapes) height\\\").\\n\\t^ rr! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 8/22/2000 23:48'!\\noffsetFromMaxBounds\\n\\t\\\"location of normal PaintBox within maxBounds.\\\"\\n\\n\\t^ self left - colorMemory left @ 0! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 7/17/97 16:26'!\\nrotationTabForm\\n\\t^ rotationTabForm! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 7/17/97 16:26'!\\nscaleTabForm\\n\\t^ scaleTabForm! !\\n\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 7/8/2006 20:33'!\\nfixUpColorPicker\\n\\t| chart picker |\\n\\tchart _ ColorChart ifNil:[Cursor wait showWhile:[ColorChart _ (ColorPickerMorph colorPaletteForDepth: 16 extent: 120@89)]].\\n\\tchart getCanvas frameRectangle: chart boundingBox color: Color black.\\n\\tpicker _ Form extent: (chart extent + (14@12)) depth: 16.\\n\\tpicker fillWhite.\\n\\t\\\"top\\\"\\n\\tpicker copy: (0@0 extent: picker width@6)\\n\\t\\t\\tfrom: (colorMemory image width - picker width)@0 \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"bottom\\\"\\n\\tpicker copy: (0@ (picker height-6) extent: picker width@6) \\n\\t\\t\\tfrom: (colorMemory image width - picker width)@(colorMemory image height - 7)\\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"left\\\"\\n\\tpicker copy: (0@6 corner: 8@(picker height - 6))\\n\\t\\t\\tfrom: (colorMemory image boundingBox topLeft + (0@6)) \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"right\\\"\\n\\tpicker copy: (picker width-6@6 corner: picker width@(picker height - 6))\\n\\t\\t\\tfrom: (colorMemory image boundingBox topRight - (6@-6)) \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\tchart displayOn: picker at: 8@6.\\n\\tpicker getCanvas frameRectangle: picker boundingBox color: Color black.\\n\\tcolorMemory image: picker.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'dgd 2/21/2003 23:17'!\\nfixUpRecentColors\\n\\t| inner outer border box form newImage canvas morph |\\n\\tself fixUpColorPicker.\\n\\trecentColors := WriteStream on: Array new.\\n\\tform := image.\\n\\tnewImage := Form extent: form extent + (0 @ 41) depth: form depth.\\n\\tform displayOn: newImage.\\n\\tnewImage \\n\\t\\tcopy: (0 @ (form height - 10) \\n\\t\\t\\t\\textent: form width @ (newImage height - form height + 10))\\n\\t\\tfrom: 0 @ (form height - (newImage height - form height + 10))\\n\\t\\tin: form\\n\\t\\trule: Form over.\\n\\tcanvas := newImage getCanvas.\\n\\tcanvas \\n\\t\\tline: 12 @ (form height - 10)\\n\\t\\tto: 92 @ (form height - 10)\\n\\t\\twidth: 1\\n\\t\\tcolor: Color black.\\n\\tcanvas := canvas copyOffset: 12 @ (form height - 9).\\n\\tinner := Color \\n\\t\\t\\t\\tr: 0.677\\n\\t\\t\\t\\tg: 0.71\\n\\t\\t\\t\\tb: 0.968.\\n\\touter := inner darker darker.\\n\\tborder := Color \\n\\t\\t\\t\\tr: 0.194\\n\\t\\t\\t\\tg: 0.258\\n\\t\\t\\t\\tb: 0.194.\\n\\t0 to: 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\t0 to: 3\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tbox := (x * 20) @ (y * 20) extent: 20 @ 20.\\n\\t\\t\\t\\t\\tmorph := BorderedMorph new \\n\\t\\t\\t\\t\\t\\t\\t\\tbounds: ((box insetBy: 1) translateBy: canvas origin + bounds origin).\\n\\t\\t\\t\\t\\tmorph\\n\\t\\t\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\t\\t\\tborderColor: border.\\n\\t\\t\\t\\t\\tmorph color: Color white.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\t\\t\\tsend: #mouseDownRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\t\\t\\tsend: #mouseStillDownRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseUp\\n\\t\\t\\t\\t\\t\\tsend: #mouseUpRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tself addMorphFront: morph.\\n\\t\\t\\t\\t\\trecentColors nextPut: morph.\\n\\t\\t\\t\\t\\tcanvas fillRectangle: box color: Color white.\\n\\t\\t\\t\\t\\tcanvas frameRectangle: (box insetBy: 1) color: border.\\n\\t\\t\\t\\t\\tcanvas frameRectangle: box color: inner.\\n\\t\\t\\t\\t\\tbox := box insetBy: 1.\\n\\t\\t\\t\\t\\tcanvas \\n\\t\\t\\t\\t\\t\\tline: box topRight\\n\\t\\t\\t\\t\\t\\tto: box bottomRight\\n\\t\\t\\t\\t\\t\\twidth: 1\\n\\t\\t\\t\\t\\t\\tcolor: outer.\\n\\t\\t\\t\\t\\tcanvas \\n\\t\\t\\t\\t\\t\\tline: box bottomLeft\\n\\t\\t\\t\\t\\t\\tto: box bottomRight\\n\\t\\t\\t\\t\\t\\twidth: 1\\n\\t\\t\\t\\t\\t\\tcolor: outer]].\\n\\trecentColors := recentColors contents.\\n\\t(RecentColors isNil or: [RecentColors size ~= recentColors size]) \\n\\t\\tifTrue: [RecentColors := recentColors collect: [:each | each color]]\\n\\t\\tifFalse: \\n\\t\\t\\t[RecentColors \\n\\t\\t\\t\\tkeysAndValuesDo: [:idx :aColor | (recentColors at: idx) color: aColor]].\\n\\tself image: newImage.\\n\\tself toggleStamps.\\n\\tself toggleStamps! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 19:54'!\\nmouseDownRecent: evt with: aMorph\\n\\taMorph borderColor: Color white.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 20:01'!\\nmouseStillDownRecent: evt with: aMorph\\n\\t(aMorph containsPoint: evt cursorPoint)\\n\\t\\tifTrue:[aMorph borderColor: Color white]\\n\\t\\tifFalse:[aMorph borderColor: (Color r: 0.194 g: 0.258 b: 0.194)]\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 19:59'!\\nmouseUpRecent: evt with: aMorph\\n\\taMorph borderColor: (Color r: 0.194 g: 0.258 b: 0.194).\\n\\t(aMorph containsPoint: evt cursorPoint) ifTrue:[\\n\\t\\tself takeColor: aMorph color event: evt.\\n\\t].! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'dgd 2/21/2003 23:17'!\\nrecentColor: aColor \\n\\t\\\"Remember the color as one of our recent colors\\\"\\n\\n\\t(recentColors anySatisfy: [:any | any color = aColor]) ifTrue: [^self].\\t\\\"already remembered\\\"\\n\\trecentColors size to: 2\\n\\t\\tby: -1\\n\\t\\tdo: \\n\\t\\t\\t[:i | \\n\\t\\t\\t(recentColors at: i) color: (recentColors at: i - 1) color.\\n\\t\\t\\tRecentColors at: i put: (RecentColors at: i - 1)].\\n\\t(recentColors first) color: aColor.\\n\\tRecentColors at: 1 put: aColor! !\\n\\n\\n!PaintBoxMorph methodsFor: 'user interface' stamp: 'tk 7/2/97 08:10'!\\nmouseUpBalk: evt\\n\\t\\\"A button I own got a mouseDown, but the user moved out before letting up. Prevent this for the current tool. Some tool must stay selected.\\\"\\n\\n\\ttool state: #on.\\t\\\"keep current one, even if user balked on it\\\"\\n\\tcurrentBrush ifNotNil: [currentBrush state: #on].! !\\n\\n\\n!PaintBoxMorph methodsFor: '*eToys-e-toy support' stamp: 'sw 6/30/1999 20:33'!\\nisCandidateForAutomaticViewing\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPaintBoxMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 8/21/2000 12:52'!\\nfixUpPrototype\\n\\t\\\"PaintBoxMorph fixUpPrototype\\\"\\nself error: 'who uses this?'.\\n\\tPrototype eventHandler: nil! !\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'ar 7/8/2006 20:33'!\\ninitializeColorChart\\n\\t\\\"PaintBoxMorph initializeColorChart\\\"\\n\\tColorChart _ (ColorPickerMorph colorPaletteForDepth: 32 extent: (360+10)@(180+10))! !\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 10/12/97 11:01'!\\nprototype\\n\\t\\\"Later we will be a subclass of Model, and it will have a general version of this\\\"\\n\\t^ Prototype! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'class initialization' stamp: 'tk 8/21/2000 12:58'!\\ninitialize\\n\\t\\\"PaintBoxMorph initialize\\\"\\n\\n\\tPrototype eventHandler: nil.\\n\\tPrototype focusMorph: nil.\\n\\tPrototype stampHolder clear. \\\"clear stamps\\\"\\n\\tPrototype delete. \\\"break link to world, if any\\\"\\n\\n\\tAllOnImage _ AllOffImage _ AllPressedImage _ nil.\\n\\tOriginalBounds _ nil.\\n\\n! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'instance creation' stamp: 'bf 10/11/2004 13:37'!\\nnew\\n\\n\\t| pb button dualUse formCanvas rect |\\n\\tpb _ Prototype veryDeepCopy.\\n\\t\\t\\\"Assume that the PaintBox does not contain any scripted Players!!\\\"\\n\\tpb stampHolder normalize.\\t\\\"Get the stamps to show\\\"\\n\\t\\\"Get my own copies of the brushes so I can modify them\\\"\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6:) do: [:sel |\\n\\t\\tbutton _ pb submorphNamed: sel.\\n\\t\\tbutton offImage: button offImage deepCopy.\\n\\t\\tdualUse _ button onImage == button pressedImage.\\t\\\"sometimes shared\\\"\\n\\t\\tbutton onImage: button onImage deepCopy.\\n\\t\\tdualUse\\n\\t\\t\\tifTrue: [button pressedImage: button onImage]\\n\\t\\t\\tifFalse: [button pressedImage: button pressedImage deepCopy].\\n\\t\\t\\\"force color maps for later mapping\\\"\\n\\t\\tbutton offImage.\\n\\t\\tbutton onImage.\\n\\t\\tbutton pressedImage.\\n\\t\\tformCanvas _ button onImage getCanvas.\\n\\t\\tformCanvas _ formCanvas\\n\\t\\t\\tcopyOrigin: 0@0\\n\\t\\t\\tclipRect: (rect _ 0@0 extent: button onImage extent).\\n\\t\\t(#(brush1: brush3:) includes: sel) ifTrue: [\\n\\t\\t\\trect _ rect origin corner: rect corner - (2@2)].\\n\\t\\t(#brush2: == sel) ifTrue: [\\n\\t\\t\\trect _ rect origin corner: rect corner - (2@4)].\\n\\t\\tformCanvas frameAndFillRectangle: rect fillColor: Color transparent\\n\\t\\t\\tborderWidth: 2 borderColor: (Color r: 0.599 g: 0.8 b: 1.0).\\n\\t\\t].\\n\\tpb showColor.\\n\\tpb fixUpRecentColors.\\n\\tpb addLabels.\\n\\t^ pb! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'notification' stamp: 'ar 7/8/2006 20:33'!\\nlocaleChanged\\n\\t| caption |\\n\\tcaption := ColorPickerMorph noColorCaption.\\n\\tcaption displayOn: ColorChart at: ColorChart boundingBox topCenter - (caption width // 2 @ 0)! !\\nImageMorph subclass: #PaintInvokingMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!PaintInvokingMorph commentStamp: '<historical>' prior: 0!\\nWhen this is dropped inside some appropriate place, then painting is invoked for that place.!\\n\\n\\n!PaintInvokingMorph methodsFor: 'dropping/grabbing' stamp: 'dgd 4/3/2006 14:19'!\\njustDroppedInto: aPasteUpMorph event: anEvent\\n\\t\\\"This message is sent to a dropped morph after it has been dropped on--and been accepted by--a drop-sensitive morph\\\"\\n\\taPasteUpMorph isPartsBin ifFalse:[\\n\\t\\tself removeHalo.\\n\\t\\tself delete.\\n\\t\\t^aPasteUpMorph makeNewDrawing: anEvent].\\n\\t^super justDroppedInto: aPasteUpMorph event: anEvent! !\\n\\n!PaintInvokingMorph methodsFor: 'dropping/grabbing' stamp: 'ar 3/3/2001 20:40'!\\nwantsToBeDroppedInto: aMorph\\n\\t\\\"Only into PasteUps that are not part bins\\\"\\n\\t^aMorph isPlayfieldLike! !\\n\\n\\n!PaintInvokingMorph methodsFor: 'initialization' stamp: 'sw 7/16/1998 00:02'!\\ninitialize\\n\\tsuper initialize.\\n\\tself image: (ScriptingSystem formAtKey: 'Painting')! !\\n\\n\\n!PaintInvokingMorph methodsFor: 'parts bin' stamp: 'sw 8/12/2001 17:19'!\\ninitializeToStandAlone\\n\\tsuper initializeToStandAlone.\\n\\tself image: (ScriptingSystem formAtKey: 'Painting')! !\\n\\n\\n!PaintInvokingMorph methodsFor: '*eToys-e-toy support' stamp: 'sw 6/30/1999 20:31'!\\nisCandidateForAutomaticViewing\\n\\t^ self isPartsDonor not! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPaintInvokingMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 13:16'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.! !\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:09'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Scripting']! !\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:38'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!PaintInvokingMorph class methodsFor: 'parts bin' stamp: 'nk 8/23/2004 18:11'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Paint'\\n\\t\\tcategories:\\t\\t#('Basic' 'Graphics')\\n\\t\\tdocumentation:\\t'Drop this icon to start painting a new object.'! !\\n\\n\\n!PaintInvokingMorph class methodsFor: 'scripting' stamp: 'sw 5/6/2000 02:28'!\\nauthoringPrototype\\n\\t^ self new image: (ScriptingSystem formAtKey: 'Painting'); markAsPartsDonor; setBalloonText: 'drop this into any playfield or book page to make a new painting there'; yourself! !\\nCompositeStub subclass: #PanelStub\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-SUnit'!\\nDisplayText subclass: #Paragraph\\n\\tinstanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'ST80-Support'!\\n!Paragraph commentStamp: '<historical>' prior: 0!\\nI represent displayable text that has been decoraged with margin alignment, line leading, and tab settings.!\\n\\n\\n!Paragraph methodsFor: 'accessing'!\\nbackgroundColor\\n\\tbackColor == nil ifTrue: [^ Color white].\\n\\t^ backColor! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nclippingRectangle \\n\\t\\\"Answer the rectangle, defined in absolute coordinates, whose \\n\\tintersection with the destinationForm is the area in which the characters \\n\\tare constrained to display.\\\"\\n\\n\\t^clippingRectangle! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'di 10/5/97 15:33'!\\nclippingRectangle: clipRect \\n\\tclippingRectangle _ clipRect! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ncompositionRectangle\\n\\t\\\"Answer the rectangle whose width is the dimension, modified by \\n\\tindents and tabsLevels, against which line wraparound is measured. The \\n\\theight of the compositionRectangle is reset each time recomposition is \\n\\trequired.\\\"\\n\\n\\t^compositionRectangle! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ncompositionRectangle: compRectangle \\n\\t\\\"Set the rectangle whose width is the dimension, modified by indents and \\n\\ttabsLevels, against which line wraparound is measured.\\\"\\n\\n\\tcompositionRectangle _ compRectangle.\\n\\tself composeAll! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ndestinationForm \\n\\t \\\"Answer the Form into which the characters are scanned.\\\"\\n\\n\\t^destinationForm! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nfillColor \\n\\t\\\"Answer the Form with which each character is combined by the scanner \\n\\tbefore applying the rule for display.\\\"\\n\\n\\t^mask! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nfillColor: maskForm \\n\\t\\\"Set the argument, maskForm, to be the form with which each character \\n\\tis combined by the scanner before applying the rule for display.\\\"\\n\\n\\tmask _ maskForm! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nheight \\n\\t\\\"Answer the height of the composition rectangle.\\\"\\n\\n\\t^compositionRectangle height! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nindentationOfLineIndex: lineIndex ifBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the line at lineIndex. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\n\\t If the line is word-wrap overflow, back up a line and recur.\\\"\\n\\n\\t| arrayIndex first last reader leadingTabs lastSeparator cr tab ch |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\tarrayIndex _ lineIndex.\\n\\t[first _ (lines at: arrayIndex) first.\\n\\t first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: \\\"word wrap\\\"\\n\\t\\t[arrayIndex _ arrayIndex - 1].\\n\\tlast _ (lines at: lastLine) last.\\n\\treader _ ReadStream on: text string from: first to: last.\\n\\tleadingTabs _ 0.\\n\\t[reader atEnd not and: [(ch _ reader next) == tab]]\\n\\t\\twhileTrue: [leadingTabs _ leadingTabs + 1].\\n\\tlastSeparator _ first - 1 + leadingTabs.\\n\\t[reader atEnd not and: [ch isSeparator and: [ch ~~ cr]]]\\n\\t\\twhileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next].\\n\\tlastSeparator = last | (ch == cr)\\n\\t\\tifTrue: [^aBlock value: leadingTabs].\\n\\t^leadingTabs! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nmask \\n\\t\\\"Answer the Form with which each character is combined by the scanner \\n\\tbefore applying the rule for display.\\\"\\n\\n\\t^mask! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nnumberOfLines \\n\\t\\\"Answer the number of lines of text in the receiver.\\\"\\n\\n\\t^lastLine! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'ar 5/18/2000 18:34'!\\nreplaceFrom: start to: stop with: aText displaying: displayBoolean\\n\\t\\\"Replace the receiver's text starting at position start, stopping at stop, by \\n\\tthe characters in aText. It is expected that most requirements for \\n\\tmodifications to the receiver will call this code. Certainly all cut's or \\n\\tpaste's.\\\" \\n\\n\\t| compositionScanner obsoleteLines obsoleteLastLine firstLineIndex lastLineIndex\\n\\tstartLine stopLine replacementRange visibleRectangle startIndex newLine done\\n\\tnewStop obsoleteY newY moveRectangle |\\n\\n\\ttext replaceFrom: start to: stop with: aText.\\t\\t\\\"Update the text.\\\"\\n\\tlastLine = 0 ifTrue:\\n\\t\\t[\\\"if lines have never been set up, measure them and display\\n\\t\\tall the lines falling in the visibleRectangle\\\"\\n\\t\\tself composeAll.\\n\\t\\tdisplayBoolean ifTrue: [^ self displayLines: (1 to: lastLine)]].\\n\\n\\t\\\"save -- things get pretty mashed as we go along\\\"\\n\\tobsoleteLines _ lines copy.\\n\\tobsoleteLastLine _ lastLine.\\n\\n\\t\\\"find the starting and stopping lines\\\"\\n\\tfirstLineIndex _ startLine _ self lineIndexOfCharacterIndex: start.\\n\\tstopLine _ self lineIndexOfCharacterIndex: stop.\\n\\n\\t\\\"how many characters being inserted or deleted\\n\\t\\t-- negative if aText size is < characterInterval size.\\\"\\n\\treplacementRange _ aText size - (stop - start + 1).\\n\\t\\\"Give ourselves plenty of elbow room.\\\"\\n\\tcompositionRectangle _ compositionRectangle withHeight: (textStyle lineGrid * 9999).\\n\\t\\\"build a boundingBox of the actual screen space in question -- we'll need it later\\\"\\n\\tvisibleRectangle _ (clippingRectangle intersect: compositionRectangle)\\n\\t\\t\\t\\t\\t\\t\\tintersect: destinationForm boundingBox.\\n\\tcompositionScanner _ CompositionScanner new forParagraph: self.\\t\\t\\\"Initialize a scanner.\\\"\\n\\n\\t\\\"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.\\\"\\n\\tstartIndex _ (lines at: firstLineIndex) first.\\n\\tstartLine > 1\\n\\t\\tifTrue: \\t[newLine _ compositionScanner composeLine: startLine - 1\\n\\t\\t\\t\\t\\t\\tfromCharacterIndex: (lines at: startLine - 1) first\\n\\t\\t\\t\\t\\t\\tinParagraph: self.\\n\\t\\t\\t\\t(lines at: startLine - 1) = newLine\\n\\t\\t\\t\\t\\tifFalse:\\t[\\\"start in line preceding the one with the starting character\\\"\\n\\t\\t\\t\\t\\t\\t\\tstartLine _ startLine - 1.\\n\\t\\t\\t\\t\\t\\t\\tself lineAt: startLine put: newLine.\\n\\t\\t\\t\\t\\t\\t\\tstartIndex _ newLine last + 1]].\\n\\tstartIndex > text size ifTrue:\\n\\t\\t[\\\"nil lines after a deletion -- remeasure last line below\\\"\\n\\t\\tself trimLinesTo: (firstLineIndex - 1 max: 0).\\n\\t\\ttext size = 0 ifTrue:\\n\\t\\t\\t[\\\"entire text deleted -- clear visibleRectangle and return.\\\"\\n\\t\\t\\tdisplayBoolean ifTrue: [destinationForm fill: visibleRectangle rule: rule fillColor: self backgroundColor].\\n\\t\\t\\tself updateCompositionHeight.\\n\\t\\t\\t^self]].\\n\\n\\t\\\"Now we really get to it.\\\"\\n\\tdone _ false.\\n\\tlastLineIndex _ stopLine.\\n\\t[done or: [startIndex > text size]]\\n\\t\\twhileFalse: \\n\\t\\t[self lineAt: firstLineIndex put:\\n\\t\\t\\t(newLine _ compositionScanner composeLine: firstLineIndex\\n\\t\\t\\t\\t\\t\\t\\tfromCharacterIndex: startIndex inParagraph: self).\\n\\t\\t[(lastLineIndex > obsoleteLastLine\\n\\t\\t\\tor: [\\\"no more old lines to compare with?\\\"\\n\\t\\t\\t\\tnewLine last <\\n\\t\\t\\t\\t\\t(newStop _ (obsoleteLines at: lastLineIndex) last + replacementRange)])\\n\\t\\t\\t \\tor: [done]]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t[newStop = newLine last\\n\\t\\t\\t\\tifTrue:\\t[\\\"got the match\\\"\\n\\t\\t\\t\\t\\t\\t\\\"get source and dest y's for moving the unchanged lines\\\"\\n\\t\\t\\t\\t\\t\\tobsoleteY _ self topAtLineIndex: lastLineIndex + 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tusing: obsoleteLines and: obsoleteLastLine.\\n\\t\\t\\t\\t\\t\\tnewY _ self topAtLineIndex: firstLineIndex + 1.\\n\\t\\t\\t\\t\\t\\tstopLine _ firstLineIndex.\\n\\t\\t\\t\\t\\t\\tdone _ true.\\n\\t\\t\\t\\t\\t\\t\\t\\\"Fill in the new line vector with the old unchanged lines.\\n\\t\\t\\t\\t\\t\\t\\tUpdate their starting and stopping indices on the way.\\\"\\n\\t\\t\\t\\t\\t\\t((lastLineIndex _ lastLineIndex + 1) to: obsoleteLastLine) do:\\n\\t\\t\\t\\t\\t\\t\\t[:upDatedIndex | \\n\\t\\t\\t\\t\\t\\t\\tself lineAt: (firstLineIndex _ firstLineIndex + 1) \\n\\t\\t\\t\\t\\t\\t\\t\\tput: ((obsoleteLines at: upDatedIndex)\\n\\t\\t\\t\\t\\t\\t\\t \\t\\tslide: replacementRange)].\\n\\t\\t\\t\\t\\t\\t\\t\\\"trim off obsolete lines, if any\\\"\\n\\t\\t\\t\\t\\t\\tself trimLinesTo: firstLineIndex]\\n\\t\\t\\t\\tifFalse:\\t[lastLineIndex _ lastLineIndex + 1]].\\n\\t\\tstartIndex _ newLine last + 1.\\n\\t\\tfirstLineIndex _ firstLineIndex + 1].\\n\\n\\t\\\"Now the lines are up to date -- Whew!!. What remains is to move\\n\\tthe 'unchanged' lines and display those which have changed.\\\"\\n\\tdisplayBoolean \\\"Not much to do if not displaying\\\"\\n\\t\\tifFalse: [^ self updateCompositionHeight].\\n\\tstartIndex > text size ifTrue:\\n\\t\\t[\\\"If at the end of previous lines simply display lines from the line in\\n\\t\\twhich the first character of the replacement occured through the\\n\\t\\tend of the paragraph.\\\"\\n\\t\\tself updateCompositionHeight.\\n\\t\\tself displayLines:\\n\\t\\t\\t(startLine to: (stopLine _ firstLineIndex min: lastLine)).\\n\\t\\tdestinationForm \\\"Clear out area at the bottom\\\"\\n\\t\\t\\tfill: ((visibleRectangle left @ (self topAtLineIndex: lastLine + 1)\\n\\t\\t\\t\\t\\t\\textent: visibleRectangle extent)\\n\\t\\t\\t\\t\\tintersect: visibleRectangle)\\n\\t\\t\\trule: rule fillColor: self backgroundColor]\\n\\t\\tifFalse:\\n\\t\\t[newY ~= obsoleteY ifTrue:\\n\\t\\t\\t[\\\"Otherwise first move the unchanged lines within\\n\\t\\t\\tthe visibleRectangle with a good old bitblt.\\\"\\n\\t\\t\\tmoveRectangle _\\n\\t\\t\\t\\tvisibleRectangle left @ (obsoleteY max: visibleRectangle top)\\n\\t\\t\\t\\t\\tcorner: visibleRectangle corner.\\n\\t\\t\\tdestinationForm copyBits: moveRectangle from: destinationForm\\n\\t\\t\\t\\tat: moveRectangle origin + (0 @ (newY-obsoleteY))\\n\\t\\t\\t\\tclippingBox: visibleRectangle\\n\\t\\t\\t\\trule: Form over fillColor: nil].\\n\\n\\t\\t\\\"Then display the altered lines.\\\"\\n\\t\\tself displayLines: (startLine to: stopLine).\\n\\n\\t\\tnewY < obsoleteY\\n\\t\\t\\tifTrue:\\n\\t\\t\\t[(self topAtLineIndex: obsoleteLastLine+1 using: obsoleteLines and: obsoleteLastLine) > visibleRectangle bottom\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[\\\"A deletion may have 'pulled' previously undisplayed lines\\n\\t\\t\\t\\tinto the visibleRectangle. If so, display them.\\\"\\n\\t\\t\\t\\tself displayLines:\\n\\t\\t\\t\\t\\t((self lineIndexOfTop: visibleRectangle bottom - (obsoleteY - newY))\\n\\t\\t\\t\\t\\t\\tto: (self lineIndexOfTop: visibleRectangle bottom))].\\n\\t\\t\\t\\\"Clear out obsolete material at the bottom of the visibleRectangle.\\\"\\n\\t\\t\\tdestinationForm\\n\\t\\t\\t\\tfill: ((visibleRectangle left @ ((self bottomAtLineIndex: lastLine) + 1)\\n\\t\\t\\t\\t\\t\\textent: visibleRectangle extent)\\n\\t\\t\\t\\t\\tintersect: visibleRectangle) \\\"How about just corner: ??\\\"\\n\\t\\t\\t\\trule: rule fillColor: self backgroundColor].\\n\\n\\t\\t(newY > obsoleteY and: [obsoleteY < visibleRectangle top])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[\\\"An insertion may have 'pushed' previously undisplayed lines\\n\\t\\t\\t\\tinto the visibleRectangle. If so, display them.\\\"\\n\\t\\t\\t\\tself displayLines:\\n\\t\\t\\t\\t\\t((self lineIndexOfTop: visibleRectangle top)\\n\\t\\t\\t\\t\\t\\tto: (self lineIndexOfTop: visibleRectangle top + (newY-obsoleteY)))].\\n\\n\\t\\tself updateCompositionHeight]! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nrule \\n\\t\\\"Answer the rule according to which character display behaves. For \\n\\texample, rule may equal over, under, reverse.\\\"\\n\\n\\t^rule! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nrule: ruleInteger \\n\\t\\\"Set the rule according to which character display behaves.\\\"\\n\\n\\trule _ ruleInteger! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'sw 10/29/1999 18:11'!\\nstringAtLineNumber: aNumber\\n\\t(aNumber > lastLine or: [aNumber < 1]) ifTrue: [^ nil].\\n\\t^ (text string copyFrom: (lines at: aNumber) first to: (lines at: aNumber) last) copyWithout: Character cr! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ntext: aText \\n\\t\\\"Set the argument, aText, to be the text for the receiver.\\\"\\n\\n\\ttext _ aText.\\n\\tself composeAll! !\\n\\n\\n!Paragraph methodsFor: 'alignment'!\\ncentered \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that text is centered in the composition rectangle.\\\"\\n\\n\\ttextStyle alignment: Centered! !\\n\\n!Paragraph methodsFor: 'alignment'!\\njustified \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text end on an even border in the \\n\\tcomposition rectangle.\\\"\\n\\n\\ttextStyle alignment: Justified! !\\n\\n!Paragraph methodsFor: 'alignment'!\\nleftFlush \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text begin on an even border in the \\n\\tcomposition rectangle. This is also known as ragged-right.\\\"\\n\\n\\ttextStyle alignment: LeftFlush! !\\n\\n!Paragraph methodsFor: 'alignment'!\\nrightFlush \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text end on an even border in the \\n\\tcomposition rectangle but the beginning of each line does not. This is \\n\\talso known as ragged-left.\\\"\\n\\n\\ttextStyle alignment: RightFlush! !\\n\\n!Paragraph methodsFor: 'alignment'!\\ntoggleAlignment \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that it moves from centered to justified to leftFlush to rightFlush and \\n\\tback to centered again.\\\"\\n\\n\\ttextStyle alignment: textStyle alignment + 1! !\\n\\n\\n!Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'!\\ncharacterBlockAtPoint: aPoint \\n\\t\\\"Answer a CharacterBlock for characters in the text at point aPoint. It is \\n\\tassumed that aPoint has been transformed into coordinates appropriate to \\n\\tthe receiver's destinationForm rectangle and the compositionRectangle.\\\"\\n\\n\\t^CharacterBlockScanner new characterBlockAtPoint: aPoint in: self! !\\n\\n!Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'!\\ncharacterBlockForIndex: targetIndex \\n\\t\\\"Answer a CharacterBlock for character in the text at targetIndex. The \\n\\tcoordinates in the CharacterBlock will be appropriate to the intersection \\n\\tof the destinationForm rectangle and the compositionRectangle.\\\"\\n\\n\\t^CharacterBlockScanner new characterBlockForIndex: targetIndex in: self! !\\n\\n!Paragraph methodsFor: 'character location' stamp: 'di 10/5/1998 12:59'!\\ndefaultCharacterBlock\\n\\t^ CharacterBlock new stringIndex: 1 text: text\\n\\t\\t\\ttopLeft: compositionRectangle topLeft extent: 0 @ 0! !\\n\\n\\n!Paragraph methodsFor: 'composition' stamp: 'yo 1/23/2003 22:47'!\\ncomposeAll\\n\\t\\\"Compose a collection of characters into a collection of lines.\\\"\\n\\n\\t| startIndex stopIndex lineIndex maximumRightX compositionScanner |\\n\\tlines _ Array new: 32.\\n\\tlastLine _ 0.\\n\\tmaximumRightX _ 0.\\n\\ttext size = 0\\n\\t\\tifTrue:\\n\\t\\t\\t[compositionRectangle _ compositionRectangle withHeight: 0.\\n\\t\\t\\t^maximumRightX].\\n\\tstartIndex _ lineIndex _ 1.\\n\\tstopIndex _ text size.\\n\\tcompositionScanner _ MultiCompositionScanner new forParagraph: self.\\n\\t[startIndex > stopIndex] whileFalse: \\n\\t\\t[self lineAt: lineIndex \\n\\t\\t\\t\\tput: (compositionScanner composeLine: lineIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfromCharacterIndex: startIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinParagraph: self).\\n\\t\\t maximumRightX _ compositionScanner rightX max: maximumRightX.\\n\\t\\t startIndex _ (lines at: lineIndex) last + 1.\\n\\t\\t lineIndex _ lineIndex + 1].\\n\\tself updateCompositionHeight.\\n\\tself trimLinesTo: lineIndex - 1.\\n\\t^ maximumRightX! !\\n\\n!Paragraph methodsFor: 'composition'!\\nwrappingBox: compositionRect clippingBox: clippingRect \\n\\t\\\"Set the composition rectangle for the receiver so that the lines wrap \\n\\twithin the rectangle, compositionRect, and the display of the text is \\n\\tclipped by the rectangle, clippingRect.\\\"\\n\\n\\tself compositionRectangle: compositionRect copy\\n\\t\\t\\t\\ttext: text\\n\\t\\t\\t\\tstyle: textStyle\\n\\t\\t\\t\\toffset: offset.\\n\\tclippingRectangle _ clippingRect copy! !\\n\\n\\n!Paragraph methodsFor: 'converting' stamp: 'yo 6/23/2003 19:05'!\\nasForm\\n\\t\\\"Answer a Form made up of the bits that represent the receiver's displayable text.\\\"\\n\\t| theForm oldBackColor oldForeColor |\\n\\ttextStyle isTTCStyle ifTrue: [\\n\\t\\ttheForm _ (Form extent: compositionRectangle extent depth: 32)\\n\\t\\toffset: offset.\\n\\t] ifFalse: [\\n\\t\\ttheForm _ (ColorForm extent: compositionRectangle extent)\\n\\t\\t\\toffset: offset;\\n\\t\\t\\tcolors: (Array\\n\\t\\t\\t\\twith: (backColor == nil ifTrue: [Color transparent] ifFalse: [backColor])\\n\\t\\t\\t\\twith: (foreColor == nil ifTrue: [Color black] ifFalse: [foreColor])).\\n\\t].\\n\\toldBackColor _ backColor.\\n\\toldForeColor _ foreColor.\\n\\tbackColor _ Color white.\\n\\tforeColor _ Color black.\\n\\tself displayOn: theForm\\n\\t\\tat: 0@0\\n\\t\\tclippingBox: theForm boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil.\\n\\tbackColor _ oldBackColor.\\n\\tforeColor _ oldForeColor.\\n\\t^ theForm\\n\\n\\\"Example:\\n| p |\\np _ 'Abc' asParagraph.\\np foregroundColor: Color red backgroundColor: Color black.\\np asForm displayOn: Display at: 30@30 rule: Form over\\\"\\n! !\\n\\n!Paragraph methodsFor: 'converting'!\\nasString\\n\\t\\\"Answer the string of characters of the receiver's text.\\\"\\n\\n\\t^text string! !\\n\\n!Paragraph methodsFor: 'converting'!\\nasText\\n\\t\\\"Answer the receiver's text.\\\"\\n\\n\\t^text! !\\n\\n\\n!Paragraph methodsFor: 'display box access'!\\nboundingBox\\n\\n\\t^offset extent: compositionRectangle extent! !\\n\\n!Paragraph methodsFor: 'display box access'!\\ncomputeBoundingBox\\n\\n\\t^offset extent: compositionRectangle extent! !\\n\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium\\n\\t\\\"Because Paragraphs cache so much information, computation is avoided\\n\\tand displayAt: 0@0 is not appropriate here.\\\"\\n\\n\\tself displayOn: aDisplayMedium\\n\\t\\tat: compositionRectangle topLeft\\n\\t\\tclippingBox: clippingRectangle\\n\\t\\trule: rule\\n\\t\\tfillColor: mask! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aPoint\\n\\t\\\"Use internal clippingRect; destination cliping is done during actual display.\\\"\\n\\n\\tself displayOn: aDisplayMedium at: aPoint\\n\\t\\tclippingBox: (clippingRectangle translateBy: aPoint - compositionRectangle topLeft)\\n\\t\\trule: rule fillColor: mask! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm\\n\\t\\\"Default display message when aDisplayPoint is in absolute screen\\n\\tcoordinates.\\\"\\n\\n\\trule _ ruleInteger.\\n\\tmask _ aForm.\\n\\tclippingRectangle _ clipRectangle.\\n\\tcompositionRectangle _ aDisplayPoint extent: compositionRectangle extent.\\n\\t(lastLine == nil or: [lastLine < 1]) ifTrue: [self composeAll].\\n\\tself displayOn: aDisplayMedium lines: (1 to: lastLine)! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm \\n\\n\\tself\\t\\t\\t\\t\\\"Assumes offset has been set!!!!!!!!!!\\\"\\n\\t displayOn: aDisplayMedium\\n\\t at: (offset \\n\\t\\t\\t+ (displayTransformation applyTo: relativePoint) \\n\\t\\t\\t- alignmentPoint) rounded\\n\\t clippingBox: clipRectangle\\n\\t rule: ruleInteger\\n\\t fillColor: aForm.\\n\\t! !\\n\\n\\n!Paragraph methodsFor: 'indicating'!\\nflash \\n\\t\\\"Complement twice the visible area in which the receiver displays.\\\"\\n\\n\\tDisplay flash: clippingRectangle! !\\n\\n!Paragraph methodsFor: 'indicating'!\\noutline \\n\\t\\\"Display a border around the visible area in which the receiver presents \\n\\tits text.\\\"\\n\\n\\tclippingRectangle bottom <= compositionRectangle bottom\\n\\t ifTrue: [Display \\n\\t\\t\\t\\tborder: (clippingRectangle intersect: compositionRectangle) \\n\\t\\t\\t\\twidth: 2]\\n\\t ifFalse: [Display \\n\\t\\t\\t\\tborder: (clippingRectangle intersect: destinationForm boundingBox)\\n\\t\\t\\t\\twidth: 2].\\n\\t! !\\n\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollBy: heightToMove \\n\\t^ self scrollBy: heightToMove withSelectionFrom: nil to: nil! !\\n\\n!Paragraph methodsFor: 'scrolling' stamp: 'hmm 9/16/2000 21:30'!\\nscrollBy: heightToMove withSelectionFrom: startBlock to: stopBlock \\n\\t\\\"Translate the composition rectangle up (dy<0) by heightToMove.\\n\\tRepainting text as necessary, and selection if blocks not nil.\\n\\tReturn true unless scrolling limits have been reached.\\\"\\n\\t| max min amount |\\n\\tmax _ 0 max: \\\"cant scroll up more than dist to (top of) bottom line\\\"\\n\\t\\tcompositionRectangle bottom - textStyle lineGrid - clippingRectangle top.\\n\\tmin _ 0 min: \\\"cant scroll down more than top is above clipRect\\\"\\n\\t\\tcompositionRectangle top - clippingRectangle top.\\n\\tamount _ ((heightToMove truncateTo: textStyle lineGrid) min: max) max: min.\\n\\tamount ~= 0\\n\\t\\tifTrue: [destinationForm deferUpdatesIn: clippingRectangle while: [\\n\\t\\t\\t\\t\\tself scrollUncheckedBy: amount\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: startBlock to: stopBlock].\\n\\t\\t\\t\\t^ true]\\n\\t\\tifFalse: [^ false]! !\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollDelta\\n\\t\\\"By comparing this before and after, you know if scrolling happened\\\"\\n\\t^ clippingRectangle top - compositionRectangle top! !\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollUncheckedBy: heightToMove withSelectionFrom: startBlock to: stopBlock \\n\\t\\\"Scroll by the given amount. Copy bits where possible, display the rest.\\n\\tIf selection blocks are not nil, then select the newly visible text as well.\\\"\\n\\t| savedClippingRectangle delta |\\n\\tdelta _ 0 @ (0 - heightToMove).\\n\\tcompositionRectangle _ compositionRectangle translateBy: delta.\\n\\tstartBlock == nil ifFalse:\\n\\t\\t[startBlock moveBy: delta.\\n\\t\\tstopBlock moveBy: delta].\\n\\tsavedClippingRectangle _ clippingRectangle.\\n\\tclippingRectangle _ clippingRectangle intersect: Display boundingBox.\\n\\theightToMove abs >= clippingRectangle height\\n\\t ifTrue: \\n\\t\\t[\\\"Entire visible region must be repainted\\\"\\n\\t\\tself displayLines: (1 to: lastLine) affectedRectangle: clippingRectangle]\\n\\t ifFalse:\\n\\t\\t[\\\"Copy bits where possible / display the rest\\\"\\n\\t\\tdestinationForm\\n\\t\\t\\tcopyBits: clippingRectangle from: destinationForm\\n\\t\\t\\tat: clippingRectangle topLeft + delta\\n\\t\\t\\tclippingBox: clippingRectangle\\n\\t\\t\\trule: Form over fillColor: nil.\\n\\t\\t\\\"Set clippingRectangle to 'vacated' area for lines 'pulled' into view.\\\"\\n\\t\\tclippingRectangle _ heightToMove < 0\\n\\t\\t\\tifTrue: \\\"On the top\\\"\\n\\t\\t\\t\\t[clippingRectangle topLeft corner: clippingRectangle topRight + delta]\\n\\t\\t\\tifFalse: \\\"At the bottom\\\"\\n\\t\\t\\t\\t[clippingRectangle bottomLeft + delta corner: clippingRectangle bottomRight].\\n\\t\\tself displayLines: (1 to: lastLine) \\\"Refresh vacated region\\\"\\n\\t\\t\\taffectedRectangle: clippingRectangle].\\n\\tstartBlock == nil ifFalse:\\n\\t\\t[self reverseFrom: startBlock to: stopBlock].\\n\\t\\\"And restore the clippingRectangle to its original value. \\\"\\n\\tclippingRectangle _ savedClippingRectangle! !\\n\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'ar 5/28/2000 12:10'!\\ncaretFormForDepth: depth\\n\\t\\\"Return a caret form for the given depth.\\\"\\n\\t\\\"(Paragraph new caretFormForDepth: Display depth) displayOn: Display at: 0@0 rule: Form reverse\\\"\\n\\n\\t| box f bb map |\\n\\tbox _ CaretForm boundingBox.\\n\\tf _ Form extent: box extent depth: depth.\\n\\tmap _ (Color cachedColormapFrom: CaretForm depth to: depth) copy.\\n\\tmap at: 1 put: (Color transparent pixelValueForDepth: depth).\\n\\tmap at: 2 put: (Color quickHighLight: depth) first. \\\"pixel value for reversing\\\"\\n\\tbb _ BitBlt current toForm: f.\\n\\tbb\\n\\t\\tsourceForm: CaretForm;\\n\\t\\tsourceRect: box;\\n\\t\\tdestOrigin: 0@0;\\n\\t\\tcolorMap: map;\\n \\t\\tcombinationRule: Form over;\\n\\t\\tcopyBits.\\n\\t^ f! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'dvf 10/1/2003 13:28'!\\nclickAt: clickPoint for: model controller: aController\\n\\t\\\"Give sensitive text a chance to fire. Display flash: (100@100 extent: 100@100).\\\"\\n\\t| startBlock action range box boxes |\\n\\taction _ false.\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\t(text attributesAt: startBlock stringIndex forStyle: textStyle) \\n\\t\\tdo: [:att | att mayActOnClick ifTrue:\\n\\t\\t\\t\\t[range _ text rangeOf: att startingAt: startBlock stringIndex.\\n\\t\\t\\t\\tboxes _ self selectionRectsFrom: (self characterBlockForIndex: range first) \\n\\t\\t\\t\\t\\t\\t\\tto: (self characterBlockForIndex: range last+1).\\n\\t\\t\\t\\tbox _ boxes detect: [:each | each containsPoint: clickPoint]\\n\\t\\t\\t\\t\\t\\t\\tifNone: [^ action].\\n\\t\\t\\t\\tUtilities awaitMouseUpIn: box repeating: []\\n\\t\\t\\t\\t\\tifSucceed: [aController terminateAndInitializeAround:\\n\\t\\t\\t\\t\\t\\t\\t\\t[(att actOnClickFor: model in: self at: clickPoint editor: aController) ifTrue: [action _ true]]]]].\\n\\t^ action! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nextendSelectionAt: beginBlock endBlock: endBlock \\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes.\\\"\\n\\t\\n\\t(self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock\\n\\t\\tifTrue: [^self mouseMovedFrom: beginBlock \\n\\t\\t\\t\\t\\tpivotBlock: endBlock\\n\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\tifFalse: [^self mouseMovedFrom: endBlock \\n\\t\\t\\t\\t\\tpivotBlock: beginBlock\\n\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'th 9/19/2002 17:27'!\\nextendSelectionMark: markBlock pointBlock: pointBlock \\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes.\\\"\\n\\ttrue \\n\\t\\tifTrue:[^self mouseMovedFrom: pointBlock\\n\\t\\t\\t\\t\\tpivotBlock: markBlock\\n\\t\\t\\t\\t\\tshowingCaret:(pointBlock = markBlock)]\\n\\t\\tifFalse:\\n\\t\\t[\\t| beginBlock endBlock |\\n\\t\\t\\tbeginBlock _ markBlock min: pointBlock.\\n\\t\\t\\tendBlock _ markBlock max: endBlock.\\n\\t\\n\\t\\t\\t(self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock\\n\\t\\t\\t\\tifTrue: [^self mouseMovedFrom: beginBlock \\n\\t\\t\\t\\t\\t\\t\\tpivotBlock: endBlock\\n\\t\\t\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\t\\t\\tifFalse: [^self mouseMovedFrom: endBlock \\n\\t\\t\\t\\t\\t\\t\\tpivotBlock: beginBlock\\n\\t\\t\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\t]\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'jm 7/1/1999 12:31'!\\nhiliteRect: rect\\n\\n\\t| highlightColor |\\n\\thighlightColor _ Color quickHighLight: destinationForm depth.\\n\\trect ifNotNil: [\\n\\t\\tdestinationForm\\n\\t\\t\\tfill: rect\\n\\t\\t\\trule: Form reverse\\n\\t\\t\\tfillColor: highlightColor.\\n\\t\\t\\\"destinationForm\\n\\t\\t\\tfill: (rect translateBy: 1@1)\\n\\t\\t\\trule: Form reverse\\n\\t\\t\\tfillColor: highlightColor\\\" ].\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'jm 7/8/97 12:25'!\\nmouseMovedFrom: beginBlock pivotBlock: pivotBlock showingCaret: caretOn \\n\\t| startBlock stopBlock showingCaret |\\n\\tstopBlock _ startBlock _ beginBlock.\\n\\tshowingCaret _ caretOn.\\n\\t[Sensor redButtonPressed]\\n\\t\\twhileTrue: \\n\\t\\t\\t[stopBlock _ self characterBlockAtPoint: Sensor cursorPoint.\\n\\t\\t\\tstopBlock = startBlock\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[showingCaret\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[showingCaret _ false.\\n\\t\\t\\t\\t\\t\\t\\tself reverseFrom: pivotBlock to: pivotBlock].\\n\\t\\t\\t((startBlock >= pivotBlock and: [stopBlock >= pivotBlock])\\n\\t\\t\\t\\tor: [startBlock <= pivotBlock and: [stopBlock <= pivotBlock]])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self reverseFrom: startBlock to: stopBlock.\\n\\t\\t\\t\\t\\tstartBlock _ stopBlock]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[self reverseFrom: startBlock to: pivotBlock.\\n\\t\\t\\t\\t\\tself reverseFrom: pivotBlock to: stopBlock.\\n\\t\\t\\t\\t\\tstartBlock _ stopBlock].\\n\\t\\t\\t(clippingRectangle containsRect: stopBlock) ifFalse:\\n\\t\\t\\t\\t[stopBlock top < clippingRectangle top\\n\\t\\t\\t\\tifTrue: [self scrollBy: stopBlock top - clippingRectangle top\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: pivotBlock to: stopBlock]\\n\\t\\t\\t\\tifFalse: [self scrollBy: stopBlock bottom + textStyle lineGrid - clippingRectangle bottom\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: pivotBlock to: stopBlock]]]].\\n\\tpivotBlock = stopBlock ifTrue:\\n\\t\\t[showingCaret ifFalse: \\\"restore caret\\\"\\n\\t\\t\\t[self reverseFrom: pivotBlock to: pivotBlock]].\\n\\t^ Array with: pivotBlock with: stopBlock! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nmouseSelect\\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes. Return quickly if the button is noticed up\\n\\tto make double-click more responsive.\\\"\\n\\n\\t| pivotBlock startBlock stopBlock origPoint stillDown |\\n\\tstillDown _ Sensor redButtonPressed.\\n\\tpivotBlock _ startBlock _ stopBlock _\\n\\t\\tself characterBlockAtPoint: (origPoint _ Sensor cursorPoint).\\n\\tstillDown _ stillDown and: [Sensor redButtonPressed].\\n\\tself reverseFrom: startBlock to: startBlock.\\n\\t[stillDown and: [Sensor cursorPoint = origPoint]] whileTrue:\\n\\t\\t[stillDown _ Sensor redButtonPressed].\\n\\t(stillDown and: [clippingRectangle containsPoint: Sensor cursorPoint])\\n\\t\\tifFalse: [^Array with: pivotBlock with: stopBlock].\\n\\t^ self mouseMovedFrom: startBlock \\n\\t\\tpivotBlock: pivotBlock\\n\\t\\tshowingCaret: true! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nmouseSelect: clickPoint \\n\\t\\\"Track text selection and answer with an Array of two CharacterBlocks.\\\"\\n\\t| startBlock |\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\tself reverseFrom: startBlock to: startBlock.\\n\\t^ self mouseMovedFrom: startBlock \\n\\t\\tpivotBlock: startBlock\\n\\t\\tshowingCaret: true! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nreverseFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Reverse area between the two character blocks given as arguments.\\\"\\n\\t| visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline caret |\\n\\tcharacterBlock1 = characterBlock2 ifTrue:\\n\\t\\t[lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex.\\n\\t\\tbaseline _ lineNo = 0 ifTrue: [textStyle baseline]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [(lines at: lineNo) baseline].\\n\\t\\tcaret _ self caretFormForDepth: Display depth.\\n\\t\\t^ caret \\\"Use a caret to indicate null selection\\\"\\n\\t\\t\\t\\tdisplayOn: destinationForm\\n\\t\\t\\t\\tat: characterBlock1 topLeft + (-3 @ baseline)\\n\\t\\t\\t\\tclippingBox: clippingRectangle\\n\\t\\t\\t\\trule: (false \\\"Display depth>8\\\" ifTrue: [9 \\\"not-reverse\\\"]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [Form reverse])\\n\\t\\t\\t\\tfillColor: nil].\\n\\tvisibleRectangle _ \\n\\t\\t(clippingRectangle intersect: compositionRectangle)\\n\\t\\t\\t\\\"intersect: destinationForm boundingBox\\\" \\\"not necessary\\\".\\n\\tcharacterBlock1 top = characterBlock2 top\\n\\t\\tifTrue: [characterBlock1 left < characterBlock2 left\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft corner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft corner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\tifFalse: [characterBlock1 top < characterBlock2 top\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\tcharacterBlock1 bottom = characterBlock2 top\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 bottom\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 top \\n\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\tcharacterBlock1 top = characterBlock2 bottom\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]].\\n\\tself hiliteRect: initialRectangle.\\n\\tself hiliteRect: interiorRectangle.\\n\\tself hiliteRect: finalRectangle.! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'di 12/1/97 04:43'!\\nselectionRectsFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Return an array of rectangles representing the area between the two character blocks given as arguments.\\\"\\n\\t| visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline |\\n\\tcharacterBlock1 = characterBlock2 ifTrue:\\n\\t\\t[lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex.\\n\\t\\tbaseline _ lineNo = 0 ifTrue: [textStyle baseline]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [(lines at: lineNo) baseline].\\n\\t\\t^ Array with: (characterBlock1 topLeft extent: 1 @ baseline)].\\n\\tvisibleRectangle _ clippingRectangle intersect: compositionRectangle.\\n\\tcharacterBlock1 top = characterBlock2 top\\n\\t\\tifTrue: [characterBlock1 left < characterBlock2 left\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft corner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft corner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\tifFalse: [characterBlock1 top < characterBlock2 top\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\tcharacterBlock1 bottom = characterBlock2 top\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 bottom\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 top \\n\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\tcharacterBlock1 top = characterBlock2 bottom\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]].\\n\\t^ (Array with: initialRectangle with: interiorRectangle with: finalRectangle)\\n\\t\\t\\tselect: [:rect | rect notNil]! !\\n\\n\\n!Paragraph methodsFor: 'utilities'!\\nclearVisibleRectangle \\n\\t\\\"Display the area in which the receiver presents its text so that the area \\n\\tis all one tone--in this case, all white.\\\"\\n\\n\\tdestinationForm\\n\\t fill: clippingRectangle\\n\\t rule: rule\\n\\t fillColor: self backgroundColor! !\\n\\n!Paragraph methodsFor: 'utilities'!\\ndeepCopy\\n\\t\\\"Don't want to copy the destForm (Display) or fonts in the TextStyle. 9/13/96 tk\\\"\\n\\n\\t| new |\\n\\tnew _ self copy.\\n\\tnew textStyle: textStyle copy.\\n\\tnew destinationForm: destinationForm.\\n\\tnew lines: lines copy.\\n\\tnew text: text deepCopy.\\n\\t^ new! !\\n\\n!Paragraph methodsFor: 'utilities'!\\ndestinationForm: destForm\\n\\tdestinationForm _ destForm! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nfit\\n\\t\\\"Make the bounding rectangle of the receiver contain all the text without \\n\\tchanging the width of the receiver's composition rectangle.\\\"\\n\\n\\t[(self lineIndexOfTop: clippingRectangle top) = 1]\\n\\t\\twhileFalse: [self scrollBy: (0-1)*textStyle lineGrid].\\n\\tself updateCompositionHeight.\\n\\tclippingRectangle _ clippingRectangle withBottom: compositionRectangle bottom! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nlines: lineArray\\n\\tlines _ lineArray! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nvisibleRectangle \\n\\t\\\"May be less than the clippingRectangle if text ends part way down.\\n\\tAlso some fearful history includes Display intersection;\\n\\tit shouldn't be necessary\\\"\\n\\n\\t^ (clippingRectangle intersect: compositionRectangle)\\n\\t\\tintersect: destinationForm boundingBox! !\\n\\n\\n!Paragraph methodsFor: 'private'!\\nbottomAtLineIndex: lineIndex \\n\\t\\\"Answer the bottom y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\tlastLine = 0 ifTrue: [^ y + textStyle lineGrid].\\n\\t1 to: (lineIndex min: lastLine) do:\\n\\t\\t[:i | y _ y + (lines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'tk 9/30/96'!\\ncompositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint\\n\\n\\tcompositionRectangle _ compositionRect copy.\\n\\ttext _ aText.\\n\\ttextStyle _ aTextStyle.\\n\\trule _ DefaultRule.\\n\\tmask _ nil.\\t\\t\\\"was DefaultMask \\\"\\n\\tmarginTabsLevel _ 0.\\n\\tdestinationForm _ Display.\\n\\toffset _ aPoint.\\n\\t^self composeAll! !\\n\\n!Paragraph methodsFor: 'private'!\\ncompositionRectangleDelta\\n\\t\\\"A handy number -- mostly for scrolling.\\\"\\n\\n\\t^compositionRectangle top - clippingRectangle top! !\\n\\n!Paragraph methodsFor: 'private'!\\ndisplayLines: linesInterval \\n\\t^ self displayLines: linesInterval\\n\\t\\taffectedRectangle: self visibleRectangle! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'yo 1/23/2003 22:48'!\\ndisplayLines: linesInterval affectedRectangle: affectedRectangle\\n\\t\\\"This is the first level workhorse in the display portion of the TextForm routines.\\n\\tIt checks to see which lines in the interval are actually visible, has the\\n\\tCharacterScanner display only those, clears out the areas in which display will\\n\\toccur, and clears any space remaining in the visibleRectangle following the space\\n\\toccupied by lastLine.\\\"\\n\\n\\t| lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |\\n\\n\\t\\\"Save some time by only displaying visible lines\\\"\\n\\tfirstLineIndex _ self lineIndexOfTop: affectedRectangle top.\\n\\tfirstLineIndex < linesInterval first ifTrue: [firstLineIndex _ linesInterval first].\\n\\tlastLineIndex _ self lineIndexOfTop: affectedRectangle bottom - 1.\\n\\tlastLineIndex > linesInterval last ifTrue:\\n\\t\\t\\t[linesInterval last > lastLine\\n\\t\\t \\t\\tifTrue: [lastLineIndex _ lastLine]\\n\\t\\t \\t\\tifFalse: [lastLineIndex _ linesInterval last]].\\n\\tlastLineIndexBottom _ (self bottomAtLineIndex: lastLineIndex).\\n\\t((Rectangle \\n\\t\\torigin: affectedRectangle left @ (topY _ self topAtLineIndex: firstLineIndex) \\n\\t\\tcorner: affectedRectangle right @ lastLineIndexBottom)\\n\\t intersects: affectedRectangle)\\n\\t\\tifTrue: [ \\\" . . . (skip to clear-below if no lines displayed)\\\"\\n\\t\\t\\t\\tMultiDisplayScanner new\\n\\t\\t\\t\\t\\tdisplayLines: (firstLineIndex to: lastLineIndex)\\n\\t\\t\\t\\t\\tin: self clippedBy: affectedRectangle].\\n\\tlastLineIndex = lastLine ifTrue: \\n\\t\\t [destinationForm \\\"Clear out white space below last line\\\"\\n\\t\\t \\tfill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)\\n\\t\\t\\t\\tcorner: affectedRectangle bottomRight)\\n\\t\\t \\trule: rule fillColor: self backgroundColor]! !\\n\\n!Paragraph methodsFor: 'private'!\\ndisplayOn: aDisplayMedium lines: lineInterval\\n\\n\\t| saveDestinationForm |\\n\\tsaveDestinationForm _ destinationForm.\\n\\tdestinationForm _ aDisplayMedium.\\n\\tself displayLines: lineInterval.\\n\\tdestinationForm _ saveDestinationForm! !\\n\\n!Paragraph methodsFor: 'private'!\\nleftMarginForCompositionForLine: lineIndex \\n\\t\\\"Build the left margin for composition of a line. Depends upon\\n\\tmarginTabsLevel and the indent.\\\"\\n\\n\\t| indent |\\n\\tlineIndex = 1\\n\\t\\tifTrue: [indent _ textStyle firstIndent]\\n\\t\\tifFalse: [indent _ textStyle restIndent].\\n\\t^indent + (textStyle leftMarginTabAt: marginTabsLevel)! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'ar 12/15/2001 23:29'!\\nleftMarginForDisplayForLine: lineIndex alignment: alignment\\n\\t\\\"Build the left margin for display of a line. Depends upon\\n\\tleftMarginForComposition, compositionRectangle left and the alignment.\\\"\\n\\n\\t| pad |\\n\\t(alignment = LeftFlush or: [alignment = Justified])\\n\\t\\tifTrue: \\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex)].\\n\\t\\\"When called from character location code and entire string has been cut,\\n\\tthere are no valid lines, hence following nil check.\\\"\\n\\t(lineIndex <= lines size and: [(lines at: lineIndex) notNil])\\n\\t\\tifTrue: \\n\\t\\t\\t[pad _ (lines at: lineIndex) paddingWidth]\\n\\t\\tifFalse: \\n\\t\\t\\t[pad _ \\n\\t\\t\\t\\tcompositionRectangle width - textStyle firstIndent - textStyle rightIndent].\\n\\talignment = Centered \\n\\t\\tifTrue: \\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex) + (pad // 2)].\\n\\talignment = RightFlush \\n\\t\\tifTrue:\\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex) + pad].\\n\\tself error: ['no such alignment']! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineAt: indexInteger put: aTextLineInterval \\n\\t\\\"Store a line, track last, and grow lines if necessary.\\\"\\n\\tindexInteger > lastLine ifTrue: [lastLine _ indexInteger].\\n\\tlastLine > lines size ifTrue: [lines _ lines , (Array new: lines size)].\\n\\t^lines at: indexInteger put: aTextLineInterval! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineIndexOfCharacterIndex: characterIndex \\n\\t\\\"Answer the line index for a given characterIndex.\\\"\\n\\n\\t1 to: lastLine do: \\n\\t\\t[:lineIndex | \\n\\t\\t(lines at: lineIndex) last >= characterIndex ifTrue: [^lineIndex]].\\n\\t^lastLine! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineIndexOfTop: top \\n\\t\\\"Answer the line index at a given top y.\\\"\\n\\t| y line |\\n\\tlastLine = 0 ifTrue: [^ 1].\\n\\ty _ compositionRectangle top.\\n\\t1 to: lastLine do:\\n\\t\\t[:i | line _ lines at: i.\\n\\t\\t(y _ y + line lineHeight) > top ifTrue: [^ i]].\\n\\t^ lastLine\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\nlines\\n\\n\\t^lines! !\\n\\n!Paragraph methodsFor: 'private'!\\nmoveBy: delta\\n\\tcompositionRectangle _ compositionRectangle translateBy: delta.\\n\\tclippingRectangle _ clippingRectangle translateBy: delta.\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\nrightMarginForComposition\\n\\t\\\"Build the right margin for a line. Depends upon compositionRectangle\\n\\twidth, marginTabsLevel, and right indent.\\\"\\n\\n\\t^compositionRectangle width \\n\\t\\t- (textStyle rightMarginTabAt: marginTabsLevel) \\n\\t\\t- textStyle rightIndent! !\\n\\n!Paragraph methodsFor: 'private'!\\nrightMarginForDisplay \\n\\t\\\"Build the right margin for a line. Depends upon compositionRectangle\\n\\trightSide, marginTabsLevel, and right indent.\\\"\\n\\n\\t^compositionRectangle right - \\n\\t\\ttextStyle rightIndent - (textStyle rightMarginTabAt: marginTabsLevel)! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle \\n\\t\\\"Set text and adjust bounding rectangles to fit.\\\"\\n\\n\\t| shrink compositionWidth unbounded |\\n\\tunbounded _ Rectangle origin: 0 @ 0 extent: 9999@9999.\\n\\tcompositionWidth _ self\\n\\t\\tsetWithText: aText style: aTextStyle compositionRectangle: unbounded clippingRectangle: unbounded.\\n\\tcompositionRectangle _ compositionRectangle withWidth: compositionWidth.\\n\\tclippingRectangle _ compositionRectangle copy.\\n\\tshrink _ unbounded width - compositionWidth.\\n\\t\\\"Shrink padding widths accordingly\\\"\\n\\t1 to: lastLine do:\\n\\t\\t[:i | (lines at: i) paddingWidth: (lines at: i) paddingWidth - shrink]! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect \\n\\t\\\"Set text and using supplied parameters. Answer max composition width.\\\"\\n\\n\\tclippingRectangle _ clipRect copy.\\n\\t^self\\n\\t\\tcompositionRectangle: compRect\\n\\t\\ttext: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\toffset: 0 @ 0! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: cf backColor: cb\\n\\t\\\"Set text and using supplied parameters. Answer max composition width.\\\"\\n\\n\\tclippingRectangle _ clipRect copy.\\n\\tself foregroundColor: cf backgroundColor: cb.\\n\\t^ self\\n\\t\\tcompositionRectangle: compRect\\n\\t\\ttext: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\toffset: 0 @ 0! !\\n\\n!Paragraph methodsFor: 'private'!\\ntopAtLineIndex: lineIndex \\n\\t\\\"Answer the top y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\tlastLine = 0 ifTrue: [lineIndex > 0 ifTrue: [^ y + textStyle lineGrid]. ^ y].\\n\\t1 to: (lineIndex-1 min: lastLine) do:\\n\\t\\t[:i | y _ y + (lines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\ntopAtLineIndex: lineIndex using: otherLines and: otherLastLine\\n\\t\\\"Answer the top y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\totherLastLine = 0 ifTrue: [^ y].\\n\\t1 to: (lineIndex-1 min: otherLastLine) do:\\n\\t\\t[:i | y _ y + (otherLines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\ntrimLinesTo: lastLineInteger\\n\\n\\t(lastLineInteger + 1 to: lastLine) do: [:i | lines at: i put: nil].\\n\\t(lastLine _ lastLineInteger) < (lines size // 2) \\n\\t\\tifTrue: [lines _ lines copyFrom: 1 to: lines size - (lines size // 2)]! !\\n\\n!Paragraph methodsFor: 'private'!\\nupdateCompositionHeight\\n\\t\\\"Mainly used to insure that intersections with compositionRectangle work.\\\" \\n\\n\\tcompositionRectangle _ compositionRectangle withHeight:\\n\\t\\t(self bottomAtLineIndex: lastLine) - compositionRectangle top.\\n\\t(text size ~= 0 and: [(text at: text size) = CR])\\n\\t\\tifTrue: [compositionRectangle _ compositionRectangle withHeight:\\n\\t\\t\\t\\t\\tcompositionRectangle height + (lines at: lastLine) lineHeight]! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'di 8/30/97 11:14'!\\nwithClippingRectangle: clipRect do: aBlock\\n\\t| saveClip |\\n\\tsaveClip _ clippingRectangle.\\n\\tclippingRectangle _ clipRect.\\n\\t\\taBlock value.\\n\\tclippingRectangle _ saveClip! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParagraph class\\n\\tinstanceVariableNames: ''!\\n\\n!Paragraph class methodsFor: 'examples' stamp: 'tk 9/30/96'!\\nexample\\n\\t\\\"This simple example illustrates how to display a few lines of text on the screen at the current cursor point. \\n\\tFixed. \\\"\\n\\n\\t| para point |\\n\\tpoint _ Sensor waitButton.\\n\\tpara _ 'This is the first line of characters\\nand this is the second line.' asParagraph.\\n\\tpara displayOn: Display at: point.\\n\\n\\t\\\"Paragraph example\\\"! !\\n\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nnew\\n\\t\\\"Do not allow an uninitialized view. Create with text that has no\\n\\tcharacters.\\\"\\n\\n\\t^self withText: '' asText! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText \\n\\t\\\"Answer an instance of me with text set to aText and style set to the \\n\\tsystem's default text style.\\\"\\n\\n\\t^self withText: aText style: DefaultTextStyle copy! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText style: aTextStyle \\n\\t\\\"Answer an instance of me with text set to aText and style set to \\n\\taTextStyle.\\\"\\n\\n\\t^super new setWithText: aText style: aTextStyle! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: c1 backColor: c2\\n\\t\\\"Answer an instance of me with text set to aText and style set to \\n\\taTextStyle, composition rectangle is compRect and the clipping rectangle \\n\\tis clipRect.\\\"\\n\\t| para |\\n\\tpara _ super new.\\n\\tpara setWithText: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\tcompositionRectangle: compRect\\n\\t\\tclippingRectangle: clipRect\\n\\t\\tforeColor: c1 backColor: c2.\\n\\t^para! !\\nScrollController subclass: #ParagraphEditor\\n\\tinstanceVariableNames: 'paragraph startBlock stopBlock beginTypeInBlock emphasisHere initialText selectionShowing otherInterval lastParentLocation'\\n\\tclassVariableNames: 'ChangeText CmdActions FindText Keyboard ShiftCmdActions UndoInterval UndoMessage UndoParagraph UndoSelection Undone'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Kernel-ST80 Remnants'!\\n!ParagraphEditor commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!ParagraphEditor methodsFor: 'accessing' stamp: 'tk 4/21/1998 09:55'!\\ninitialText\\n\\t^ initialText! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nreplace: oldInterval with: newText and: selectingBlock \\n\\t\\\"Replace the text in oldInterval with newText and execute selectingBlock to establish the new selection. Create an undoAndReselect:redoAndReselect: undoer to allow perfect undoing.\\\"\\n\\n\\t| undoInterval |\\n\\tundoInterval _ self selectionInterval.\\n\\tundoInterval = oldInterval ifFalse: [self selectInterval: oldInterval].\\n\\tUndoSelection _ self selection.\\n\\tself zapSelectionWith: newText.\\n\\tselectingBlock value.\\n\\totherInterval _ self selectionInterval.\\n\\tself undoer: #undoAndReselect:redoAndReselect: with: undoInterval with: otherInterval! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nreplaceSelectionWith: aText\\n\\t\\\"Remember the selection text in UndoSelection.\\n\\t Deselect, and replace the selection text by aText.\\n\\t Remember the resulting selectionInterval in UndoInterval and PriorInterval.\\n\\t Set up undo to use UndoReplace.\\\"\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [^self zapSelectionWith: aText]. \\\"called from old code\\\"\\n\\tUndoSelection _ self selection.\\n\\tself zapSelectionWith: aText.\\n\\tself undoer: #undoReplace! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nsetSearch: aString\\n\\t\\\"Set the FindText and ChangeText to seek aString; except if already seeking aString, leave ChangeText alone so again will repeat last replacement.\\\"\\n\\n\\tFindText string = aString\\n\\t\\tifFalse: [FindText _ ChangeText _ aString asText]! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\ntext\\n\\t\\\"Answer the text of the paragraph being edited.\\\"\\n\\n\\t^paragraph text! !\\n\\n!ParagraphEditor methodsFor: 'accessing' stamp: 'jm 3/18/98 20:38'!\\nuserHasEdited\\n\\t\\\"Note that the user has edited my text. Here it is just a noop so that the Character Recognizer won't fail when used with a vanilla ParagrahEditor.\\\"\\n! !\\n\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'!\\nhasCaret\\n\\t^self markBlock = self pointBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'!\\nhasSelection\\n\\t^self hasCaret not! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:13'!\\nmark\\n\\t^ self markBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\nmarkBlock\\n\\t^ stopBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\nmarkBlock: aCharacterBlock\\n\\tstopBlock _ aCharacterBlock.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'!\\nmarkIndex\\n\\t^ self markBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\npointBlock\\n\\t^ startBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\npointBlock: aCharacterBlock\\n\\tstartBlock _ aCharacterBlock.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'!\\npointIndex\\n\\t^ self pointBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'yo 7/31/2004 16:27'!\\nselection\\n\\t\\\"Answer the text in the paragraph that is currently selected.\\\"\\n\\n\\t| t |\\n\\tt _ paragraph text copyFrom: self startIndex to: self stopIndex - 1.\\n\\tt string isOctetString ifTrue: [t asOctetStringText].\\n\\t^ t.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:10'!\\nselectionAsStream\\n\\t\\\"Answer a ReadStream on the text in the paragraph that is currently \\n\\tselected.\\\"\\n\\n\\t^ReadWriteStream\\n\\t\\ton: paragraph string\\n\\t\\tfrom: self startIndex\\n\\t\\tto: self stopIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 16:18'!\\nselectionInterval\\n\\t\\\"Answer the interval that is currently selected.\\\"\\n\\n\\t^self startIndex to: self stopIndex - 1 ! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'!\\nsetMark: anIndex\\n\\tself markBlock: (paragraph characterBlockForIndex: anIndex)\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'!\\nsetPoint: anIndex\\n\\tself pointBlock: (paragraph characterBlockForIndex: anIndex)\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:10'!\\nstartBlock\\n\\t^ self pointBlock min: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'!\\nstartBlock: aCharacterBlock\\n\\tself markBlock: aCharacterBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'!\\nstartIndex\\n\\t^ self startBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:14'!\\nstopBlock\\n\\t^ self pointBlock max: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'!\\nstopBlock: aCharacterBlock\\n\\tself pointBlock: aCharacterBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'!\\nstopIndex\\n\\t^ self stopBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:23'!\\nunselect\\n\\tself markBlock: self pointBlock copy.! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:12'!\\nzapSelectionWith: aText\\n\\t\\\"Deselect, and replace the selection text by aText.\\n\\t Remember the resulting selectionInterval in UndoInterval and otherInterval.\\n\\t Do not set up for undo.\\\"\\n\\n\\t| start stop |\\n\\tself deselect.\\n\\tstart _ self startIndex.\\n\\tstop _ self stopIndex.\\n\\t(aText isEmpty and: [stop > start]) ifTrue:\\n\\t\\t[\\\"If deleting, then set emphasisHere from 1st character of the deletion\\\"\\n\\t\\temphasisHere _ (paragraph text attributesAt: start forStyle: paragraph textStyle)\\n\\t\\t\\t\\t\\tselect: [:att | att mayBeExtended]].\\n\\t(start = stop and: [aText size = 0]) ifFalse:\\n\\t\\t[paragraph\\n\\t\\t\\treplaceFrom: start\\n\\t\\t\\tto: stop - 1\\n\\t\\t\\twith: aText\\n\\t\\t\\tdisplaying: true.\\n\\t\\tself computeIntervalFrom: start to: start + aText size - 1.\\n\\t\\tUndoInterval _ otherInterval _ self selectionInterval]! !\\n\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'dvf 7/28/2003 14:54'!\\nactivateTextActions\\n\\t(paragraph text attributesAt: startBlock stringIndex) \\n\\t\\tdo: [:att | att actOnClickFor: model in: paragraph]! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'BG 6/1/2003 09:43'!\\nofferMenuFromEsc: aStream\\n sensor keyboard. \\\" consume the character \\\"\\n self yellowButtonActivity.\\n ^true \\\"tell the caller that the character was processed \\\"! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:40'!\\ntotalTextHeight\\n\\n\\t^paragraph boundingBox height! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:33'!\\nvisibleHeight\\n\\n\\t^paragraph clippingRectangle height! !\\n\\n\\n!ParagraphEditor methodsFor: 'controlling'!\\ncontrolInitialize\\n\\n\\tsuper controlInitialize.\\n\\tself recomputeInterval.\\n\\tself initializeSelection.\\n\\tbeginTypeInBlock _ nil! !\\n\\n!ParagraphEditor methodsFor: 'controlling'!\\ncontrolTerminate\\n\\n\\tself closeTypeIn. \\\"Must call to establish UndoInterval\\\"\\n\\tsuper controlTerminate.\\n\\tself deselect! !\\n\\n!ParagraphEditor methodsFor: 'controlling' stamp: 'sma 3/11/2000 15:17'!\\nnormalActivity\\n\\tself processKeyboard.\\n\\tself processMouseButtons! !\\n\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\ndeselect\\n\\t\\\"If the text selection is visible on the screen, reverse its highlight.\\\"\\n\\n\\tselectionShowing ifTrue: [self reverseSelection]! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\ninitializeSelection\\n\\t\\\"Do the initial activity when starting up the receiver. For example, in the \\n\\tParagraphEditor highlight the current selection.\\\"\\n\\n\\tself select! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/20/2002 11:41'!\\nrecomputeInterval\\n\\t\\\"The same characters are selected but their coordinates may have changed.\\\"\\n\\n\\tself computeIntervalFrom: self mark to: self pointIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\nrecomputeSelection\\n\\t\\\"Redetermine the selection according to the start and stop block indices; \\n\\tdo not highlight.\\\"\\n\\n\\tself deselect; recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'BG 12/12/2003 12:50'!\\nreverseSelection\\n\\t\\\"Reverse the valence of the current selection highlighting.\\\"\\n\\tselectionShowing _ selectionShowing not.\\n\\tparagraph reverseFrom: self pointBlock to: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\nselect\\n\\t\\\"If the text selection is visible on the screen, highlight it.\\\"\\n\\n\\tselectionShowing ifFalse: [self reverseSelection]! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:47'!\\nselectAndScroll\\n\\t\\\"Scroll until the selection is in the view and then highlight it.\\\"\\n\\t| lineHeight deltaY clippingRectangle endBlock |\\n\\tself select.\\n\\tendBlock _ self stopBlock.\\n\\tlineHeight _ paragraph textStyle lineGrid.\\n\\tclippingRectangle _ paragraph clippingRectangle.\\n\\tdeltaY _ endBlock top - clippingRectangle top.\\n\\tdeltaY >= 0 \\n\\t\\tifTrue: [deltaY _ endBlock bottom - clippingRectangle bottom max: 0].\\n\\t\\t\\t\\t\\t\\t\\\"check if stopIndex below bottom of clippingRectangle\\\"\\n\\tdeltaY ~= 0 \\n\\t\\tifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t* deltaY sign]! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:48'!\\nselectAndScrollToTop\\n\\t\\\"Scroll until the selection is in the view and then highlight it.\\\"\\n\\t| lineHeight deltaY clippingRectangle |\\n\\tself select.\\n\\tlineHeight _ paragraph textStyle lineGrid.\\n\\tclippingRectangle _ paragraph clippingRectangle.\\n\\tdeltaY _ self stopBlock top - clippingRectangle top.\\n\\tdeltaY ~= 0 \\n\\t\\tifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t* deltaY sign]! !\\n\\n\\n!ParagraphEditor methodsFor: 'displaying'!\\ndisplay\\n\\t\\\"Redisplay the paragraph.\\\"\\n\\n\\t| selectionState |\\n\\tselectionState _ selectionShowing.\\n\\tself deselect.\\n\\tparagraph foregroundColor: view foregroundColor\\n\\t\\t\\tbackgroundColor: view backgroundColor;\\n\\t\\t\\tdisplayOn: Display.\\n\\tselectionState ifTrue: [self select]! !\\n\\n!ParagraphEditor methodsFor: 'displaying'!\\nflash\\n\\t\\\"Causes the view of the paragraph to complement twice in succession.\\\"\\n\\n\\tparagraph flash! !\\n\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'md 2/13/2006 14:36'!\\ncompileSelectionFor: anObject in: evalContext\\n\\n\\t| methodNode method |\\n\\tmethodNode _ [Compiler new\\n\\t\\tcompileNoPattern: self selectionAsStream\\n\\t\\tin: anObject class\\n\\t\\tcontext: evalContext\\n\\t\\tnotifying: self\\n\\t\\tifFail: [^nil]]\\n\\t\\t\\ton: OutOfScopeNotification\\n\\t\\t\\tdo: [:ex | ex resume: true].\\n\\tmethod _ methodNode generate.\\n\\t^method copyWithTempNames: methodNode tempNames! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:38'!\\ndoIt\\n\\t\\\"Set the context to include pool vars of the model. Then evaluate.\\\"\\n\\t^ self evaluateSelection.\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'gk 3/3/2004 17:15'!\\nevaluateSelection\\n\\t\\\"Treat the current selection as an expression; evaluate it and return the result\\\"\\n\\t| result rcvr ctxt |\\n\\tself lineSelectAndEmptyCheck: [^ ''].\\n\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: [FakeClassPool adopt: model selectedClass. \\\"Include model pool vars if any\\\"\\n\\t\\t\\t\\trcvr _ model doItReceiver.\\n\\t\\t\\t\\tctxt _ model doItContext]\\n\\t\\tifFalse: [rcvr _ ctxt _ nil].\\n\\tresult _ [\\n\\t\\trcvr class evaluatorClass new \\n\\t\\t\\tevaluate: self selectionAsStream\\n\\t\\t\\tin: ctxt\\n\\t\\t\\tto: rcvr\\n\\t\\t\\tnotifying: self\\n\\t\\t\\tifFail: [FakeClassPool adopt: nil. ^ #failedDoit]\\n\\t\\t\\tlogged: true.\\n\\t] \\n\\t\\ton: OutOfScopeNotification \\n\\t\\tdo: [ :ex | ex resume: true].\\n\\tFakeClassPool adopt: nil.\\n\\t^ result! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'acg 12/7/1999 07:53'!\\nexploreIt\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [result explore].\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 9/7/1999 11:25'!\\ninspectIt\\n\\t\\\"1/13/96 sw: minor fixup\\\"\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [result inspect].\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'sd 4/16/2003 11:41'!\\nobjectsReferencingIt\\n\\t\\\"Open a list inspector on all objects that reference the object that results when the current selection is evaluated. \\\"\\n\\t| result |\\n\\tself terminateAndInitializeAround: [\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\tifTrue: [view flash]\\n\\t\\tifFalse: [self systemNavigation\\n\\t\\t\\t\\t\\tbrowseAllObjectReferencesTo: result\\n\\t\\t\\t\\t\\texcept: #()\\n\\t\\t\\t\\t\\tifNone: [:obj | view topView flash]].\\n\\t]! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:52'!\\nprintIt\\n\\t\\\"Treat the current text selection as an expression; evaluate it. Insert the \\n\\tdescription of the result of evaluation after the selection and then make \\n\\tthis description the new text selection.\\\"\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [self afterSelectionInsertAndSelect: result printString]! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'ab 3/23/2005 16:49'!\\ntallyIt\\n\\n\\t^ self tallySelection! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'ab 3/23/2005 16:49'!\\ntallySelection\\n\\t\\\"Treat the current selection as an expression; evaluate it and return the time took for this evaluation\\\"\\n\\t| result rcvr ctxt cm v valueAsString |\\n\\tself lineSelectAndEmptyCheck: [^ -1].\\n\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: [FakeClassPool adopt: model selectedClass. \\\"Include model pool vars if any\\\"\\n\\t\\t\\t\\trcvr _ model doItReceiver.\\n\\t\\t\\t\\tctxt _ model doItContext]\\n\\t\\tifFalse: [rcvr _ ctxt _ nil].\\n\\tresult _ [\\n\\t\\tcm := rcvr class evaluatorClass new \\n\\t\\t\\tcompiledMethodFor: self selectionAsStream\\n\\t\\t\\tin: ctxt\\n\\t\\t\\tto: rcvr\\n\\t\\t\\tnotifying: self\\n\\t\\t\\tifFail: [FakeClassPool adopt: nil. ^ #failedDoit]\\n\\t\\t\\tlogged: false.\\n\\t\\tTime millisecondsToRun: \\n\\t\\t\\t[v := cm valueWithReceiver: rcvr arguments: (Array with: ctxt)].\\n\\t] \\n\\t\\ton: OutOfScopeNotification \\n\\t\\tdo: [ :ex | ex resume: true].\\n\\tFakeClassPool adopt: nil.\\n\\n\\t\\\"We do not want to have large result displayed\\\"\\n\\tvalueAsString := v printString.\\n\\t(valueAsString size > 30) ifTrue: [valueAsString := (valueAsString copyFrom: 1 to: 30), '...'].\\n\\tPopUpMenu \\n\\t\\tinform: 'Time to compile and execute: ', result printString, 'ms res: ', valueAsString.\\n! !\\n\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nalign: characterStream \\n\\t\\\"Triggered by Cmd-u; cycle through alignment alternatives. 8/11/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself align.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'hpt 8/5/2004 20:21'!\\nbrowseIt: characterStream \\n\\t\\\"Triggered by Cmd-B; browse the thing represented by the current selection, if plausible. 1/18/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself browseIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nbrowseItHere: characterStream \\n\\t\\\"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\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself browseItHere.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:40'!\\ncancel: characterStream \\n\\t\\\"Cancel unsubmitted changes. Flushes typeahead. 1/12/96 sw\\n\\t 1/22/96 sw: put in control terminate/init\\\"\\n\\n\\tsensor keyboard.\\n\\tself terminateAndInitializeAround: [self cancel].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'dgd 4/4/2006 15:46'!\\nchangeEmphasis: characterStream \\n\\t\\\"Change the emphasis of the current selection or prepare to\\n\\taccept characters with the change in emphasis. Emphasis\\n\\tchange amounts to a font change. Keeps typeahead.\\\"\\n\\t\\n\\t| keyCode attribute oldAttributes index thisSel colors extras |\\n\\n\\t\\\"control 0..9 -> 0..9\\\"\\n\\tkeyCode := ('0123456789-=' indexOf: sensor keyboard ifAbsent: [1]) - 1.\\n\\n\\toldAttributes := paragraph text attributesAt: self pointIndex forStyle: paragraph textStyle.\\n\\tthisSel := self selection.\\n\\n\\t\\\"Decipher keyCodes for Command 0-9...\\\"\\n\\t(keyCode between: 1 and: 5) ifTrue: [\\n\\t\\tattribute := TextFontChange fontNumber: keyCode\\n\\t].\\n\\n\\tkeyCode = 6 ifTrue: [\\n\\t\\t| labels lines | \\n\\t\\tcolors := #(#black #magenta #red #yellow #green #blue #cyan #white ).\\n\\t\\textras := (self class name = #TextMorphEditor and: [(self morph isKindOf: TextMorphForEditView) not])\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"not a system window\\\" #()]\\n\\t\\t\\t\\t\\t\\tifFalse: [#('Link to comment of class' 'Link to definition of class' 'Link to hierarchy of class' 'Link to method' )].\\n\\n\\t\\tPreferences noviceMode ifTrue: [\\n\\t\\t\\tlabels := colors , #('choose color...' ).\\n\\t\\t\\tlines := #()\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tlabels := colors , #('choose color...' 'Do it' 'Print it' ) , extras , #('be a web URL link' 'Edit hidden info' 'Copy hidden info' ).\\n\\t\\t\\tlines := Array with: colors size + 1\\n\\t\\t].\\n\\n\\t\\t\\\"index _ (PopUpMenu labelArray: labels lines: lines) startUp. \\\"\\n\\t\\tindex := UIManager default chooseFrom: labels lines: lines.\\n\\t\\tindex = 0\\n\\t\\t\\tifTrue: [ ^ true].\\n\\t\\t\\t\\n\\t\\tindex <= colors size ifTrue: [\\n\\t\\t\\tattribute := TextColor color: (Color perform: (colors at: index))\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tindex := index - colors size - 1. \\\"Re-number!!!!!!\\\"\\n\\n\\t\\t\\tindex = 0 ifTrue: [\\n\\t\\t\\t\\tattribute := self chooseColor\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 1 ifTrue: [\\n\\t\\t\\t\\tattribute := TextDoIt new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 2 ifTrue: [\\n\\t\\t\\t\\tattribute := TextPrintIt new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\n\\t\\t\\textras size = 0 & (index > 2) ifTrue: [\\n\\t\\t\\t\\tindex := index + 4 \\\"skip those\\\"\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 3 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Comment'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 4 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Definition'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 5 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Hierarchy'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 6 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\tindex = 7 ifTrue: [\\n\\t\\t\\t\\tattribute := TextURL new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\tindex = 8 ifTrue: [\\n\\t\\t\\t\\t\\\"Edit hidden info\\\"\\n\\t\\t\\t\\tthisSel := self hiddenInfo. \\\"includes selection\\\"\\n\\t\\t\\t\\tattribute := TextEmphasis normal\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 9 ifTrue: [\\n\\t\\t\\t\\t\\\"Copy hidden info\\\"\\n\\t\\t\\t\\tself copyHiddenInfo.\\n\\t\\t\\t\\t^ true\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\t\\\"no other action\\\"\\n\\t\\t\\tthisSel\\n\\t\\t\\t\\tifNil: [ ^ true ]\\n\\t\\t]\\n\\t].\\n\\n\\t(keyCode between: 7 and: 11) ifTrue: [\\n\\t\\tsensor leftShiftDown ifTrue: [\\n\\t\\t\\tkeyCode = 10 ifTrue: [\\n\\t\\t\\t\\tattribute := TextKern kern: -1\\n\\t\\t\\t].\\n\\t\\t\\tkeyCode = 11 ifTrue: [\\n\\t\\t\\t\\tattribute := TextKern kern: 1\\n\\t\\t\\t]\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tattribute := TextEmphasis perform: (#(#bold #italic #narrow #underlined #struckOut ) at: keyCode - 6).\\n\\t\\t\\toldAttributes\\n\\t\\t\\t\\t\\t\\tdo: [:att | (att dominates: attribute) ifTrue: [attribute turnOff]]\\n\\t\\t]\\n\\t].\\n\\n\\tkeyCode = 0\\n\\t\\tifTrue: [attribute := TextEmphasis normal].\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [\\n\\t\\t\\\"only change emphasisHere while typing\\\"\\n\\t\\tself insertTypeAhead: characterStream.\\n\\t\\temphasisHere := Text addAttribute: attribute toArray: oldAttributes.\\n\\t\\t^ true\\n\\t].\\n\\n\\tself\\n\\t\\treplaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t\\t\\n\\t^ true\\n! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 11:58'!\\nchangeLfToCr: characterStream \\n\\t\\\"Replace all LFs by CRs.\\n\\tTriggered by Cmd-U -- useful when getting code from FTP sites\\\"\\n\\t| cr lf |\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tcr _ Character cr. lf _ Character linefeed.\\n\\tself replaceSelectionWith: (Text fromString:\\n\\t\\t\\t(self selection string collect: [:c | c = lf ifTrue: [cr] ifFalse: [c]])).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 09:11'!\\nchooseColor\\n\\t\\\"Make a new Text Color Attribute, let the user pick a color, and return the attribute. This is the non-Morphic version.\\\"\\n\\n\\t^ TextColor color: (Color fromUser)! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:31'!\\ncompareToClipboard: characterStream \\n\\t\\\"Compare the receiver to the text on the clipboard. Flushes typeahead. 5/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself terminateAndInitializeAround: [self compareToClipboard].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 08:47'!\\ncopyHiddenInfo\\n\\t\\\"In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden\\ninfo. Copy that to the clipboard. You can paste it and see what it is.\\nUsually enclosed in <>.\\\"\\n\\n\\t^ self clipboardTextPut: self hiddenInfo asText! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\ncopySelection: characterStream \\n\\t\\\"Copy the current text selection. Flushes typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself copySelection.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\ncut: characterStream \\n\\t\\\"Cut out the current text selection. Flushes typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself cut.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:23'!\\ndoIt: characterStream \\n\\t\\\"Called when user hits cmd-d. Select the current line, if relevant, then evaluate and execute. 2/1/96 sw.\\n\\t2/29/96 sw: don't call selectLine; it's done by doIt now\\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself terminateAndInitializeAround: [self doIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/20/2002 11:41'!\\nduplicate: characterStream\\n\\t\\\"Paste the current selection over the prior selection, if it is non-overlapping and\\n\\t legal. Flushes typeahead. Undoer & Redoer: undoAndReselect.\\\"\\n\\n\\tsensor keyboard.\\n\\tself closeTypeIn.\\n\\t(self hasSelection and: [self isDisjointFrom: otherInterval])\\n\\t\\tifTrue: \\\"Something to duplicate\\\"\\n\\t\\t\\t[self replace: otherInterval with: self selection and:\\n\\t\\t\\t\\t[self selectAt: self pointIndex]]\\n\\t\\tifFalse:\\n\\t\\t\\t[view flash].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:01'!\\nenclose: characterStream\\n\\t\\\"Insert or remove bracket characters around the current selection.\\n\\t Flushes typeahead.\\\"\\n\\n\\t| char left right startIndex stopIndex oldSelection which text |\\n\\tchar _ sensor keyboard.\\n\\tself closeTypeIn.\\n\\tstartIndex _ self startIndex.\\n\\tstopIndex _ self stopIndex.\\n\\toldSelection _ self selection.\\n\\twhich _ '([<{\\\"''' indexOf: char ifAbsent: [ ^true ].\\n\\tleft _ '([<{\\\"''' at: which.\\n\\tright _ ')]>}\\\"''' at: which.\\n\\ttext _ paragraph text.\\n\\t((startIndex > 1 and: [stopIndex <= text size])\\n\\t\\tand:\\n\\t\\t[(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])\\n\\t\\tifTrue:\\n\\t\\t\\t[\\\"already enclosed; strip off brackets\\\"\\n\\t\\t\\tself selectFrom: startIndex-1 to: stopIndex.\\n\\t\\t\\tself replaceSelectionWith: oldSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"not enclosed; enclose by matching brackets\\\"\\n\\t\\t\\tself replaceSelectionWith:\\n\\t\\t\\t\\t(Text string: (String with: left), oldSelection string ,(String with: right)\\n\\t\\t\\t\\t\\temphasis: emphasisHere).\\n\\t\\t\\tself selectFrom: startIndex+1 to: stopIndex].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nexchange: characterStream\\n\\t\\\"Exchange the current and prior selections. Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t \\\"Flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself exchange.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'acg 12/7/1999 07:56'!\\nexploreIt: characterStream \\n\\t\\\"Explore the selection -- invoked via cmd-shift-I. If there is no current selection, use the current line.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self exploreIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 4/24/2001 12:28'!\\nfileItIn: characterStream \\n\\t\\\"File in the selection; invoked via a keyboard shortcut, -- for now, cmd-shift-G.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self fileItIn].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:31'!\\nhiddenInfo\\n\\t\\\"In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden info. Return the entire string that was used by Cmd-6 to create this text attribute. Usually enclosed in < >.\\\"\\n\\n\\t| attrList |\\n\\tattrList _ paragraph text attributesAt: (self pointIndex +\\nself markIndex)//2 forStyle: paragraph textStyle.\\n\\tattrList do: [:attr |\\n\\t\\t(attr isKindOf: TextAction) ifTrue:\\n\\t\\t\\t[^ self selection asString, '<', attr info, '>']].\\n\\t\\\"If none of the above\\\"\\n\\tattrList do: [:attr |\\n\\t\\tattr class == TextColor ifTrue:\\n\\t\\t\\t[^ self selection asString, '<', attr color printString, '>']].\\n\\t^ self selection asString, '[No hidden info]'! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nimplementorsOfIt: characterStream \\n\\t\\\"Triggered by Cmd-m; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself implementorsOfIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'pk 9/10/2005 22:53'!\\ninOutdent: characterStream delta: delta\\n\\t\\\"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\\\"\\n\\n\\t| cr realStart realStop lines startLine stopLine start stop adjustStart indentation size numLines inStream newString outStream |\\n\\t\\n\\tsensor keyboard. \\\"Flush typeahead\\\"\\n\\tcr := Character cr.\\n\\n\\t\\\"Operate on entire lines, but remember the real selection for re-highlighting later\\\"\\n\\trealStart := self startIndex.\\n\\trealStop := self stopIndex - 1.\\n\\n\\t\\\"Special case a caret on a line of its own, including weird case at end of paragraph\\\"\\n\\t(realStart > realStop and:\\n\\t\\t\\t\\t[realStart < 2 or: [(paragraph string at: realStart - 1) == cr]])\\n\\t\\tifTrue:\\n\\t\\t\\t[delta < 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[view flash]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[self replaceSelectionWith: Character tab asSymbol asText.\\n\\t\\t\\t\\t\\tself selectAt: realStart + 1].\\n\\t\\t\\t^ true].\\n\\n\\tlines := paragraph lines.\\n\\tstartLine := paragraph lineIndexOfCharacterIndex: realStart.\\n\\tstopLine := paragraph lineIndexOfCharacterIndex: (realStart max: realStop).\\n\\tstart := (lines at: startLine) first.\\n\\tstop := (lines at: stopLine) last.\\n\\t\\n\\t\\\"Pin the start of highlighting unless the selection starts a line\\\"\\n\\tadjustStart := realStart > start.\\n\\n\\t\\\"Find the indentation of the least-indented non-blank line; never outdent more\\\"\\n\\tindentation := (startLine to: stopLine) inject: 1000 into:\\n\\t\\t[:m :l |\\n\\t\\tm := m min: (paragraph indentationOfLineIndex: l ifBlank: [:tabs | 1000])].\\t\\t\\t\\n\\n\\tsize := stop + 1 - start.\\n\\tnumLines := stopLine + 1 - startLine.\\n\\tinStream := ReadStream on: paragraph string from: start to: stop.\\n\\n\\tnewString := WideString new: size + ((numLines * delta) max: 0).\\n\\toutStream := ReadWriteStream on: newString.\\n\\n\\t\\\"This subroutine does the actual work\\\"\\n\\tself indent: delta fromStream: inStream toStream: outStream.\\n\\n\\t\\\"Adjust the range that will be highlighted later\\\"\\n\\tadjustStart ifTrue: [realStart := (realStart + delta) max: start].\\n\\trealStop := realStop + outStream position - size.\\n\\n\\t\\\"Prepare for another iteration\\\"\\n\\tindentation := indentation + delta.\\n\\tsize := outStream position.\\n\\tinStream := outStream setFrom: 1 to: size.\\n\\n\\toutStream == nil\\n\\t\\tifTrue: \\t\\\"tried to outdent but some line(s) were already left flush\\\"\\n\\t\\t\\t[view flash]\\n\\t\\tifFalse:\\n\\t\\t\\t[self selectInvisiblyFrom: start to: stop.\\n\\t\\t\\tsize = newString size ifFalse: [newString _ outStream contents].\\n\\t\\t\\tself replaceSelectionWith: newString asText].\\n\\tself selectFrom: realStart to: realStop. \\t\\\"highlight only the original range\\\"\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nindent: characterStream\\n\\t\\\"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\\\"\\n\\n\\t^ self inOutdent: characterStream delta: 1! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'!\\ninspectIt: characterStream \\n\\t\\\"Inspect the selection -- invoked via cmd-i. If there is no current selection, use the current line. 1/17/96 sw\\n\\t 2/29/96 sw: don't call selectLine; it's done by inspectIt now\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self inspectIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'md 1/18/2006 23:42'!\\nmakeCapitalized: characterStream \\n\\t\\\"Force the current selection to be capitalized. Triggered by Cmd-Z.\\\"\\n\\t| prev |\\n\\tsensor keyboard.\\t\\t\\\"Flush the triggering cmd-key character\\\"\\n\\tprev _ $-. \\\"not a letter\\\"\\n\\tself replaceSelectionWith: (Text fromString:\\n\\t\\t\\t(self selection string collect:\\n\\t\\t\\t\\t[:c | prev _ prev isLetter ifTrue: [c asLowercase] ifFalse: [c asUppercase]])).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 12:00'!\\nmakeLowercase: characterStream \\n\\t\\\"Force the current selection to lowercase. Triggered by Cmd-X.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tself replaceSelectionWith: (Text fromString: (self selection string asLowercase)).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:21'!\\nmakeProjectLink: characterStream \\n\\t\\\"\\\"\\n\\n\\t| attribute oldAttributes thisSel |\\n\\t\\n\\tsensor keyboard.\\n\\toldAttributes _ paragraph text attributesAt: self pointIndex forStyle: paragraph textStyle.\\n\\tthisSel _ self selection.\\n\\n\\tattribute _ TextSqkProjectLink new. \\n\\tthisSel _ attribute analyze: self selection asString.\\n\\n\\tthisSel ifNil: [^ true].\\n\\tbeginTypeInBlock ~~ nil\\n\\t\\tifTrue: \\\"only change emphasisHere while typing\\\"\\n\\t\\t\\t[self insertTypeAhead: characterStream.\\n\\t\\t\\temphasisHere _ Text addAttribute: attribute toArray: oldAttributes.\\n\\t\\t\\t^ true].\\n\\tself replaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'ls 11/10/2002 12:11'!\\nmakeUppercase: characterStream \\n\\t\\\"Force the current selection to uppercase. Triggered by Cmd-Y.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tself replaceSelectionWith: (Text fromString: (self selection string asUppercase)).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 8/1/97 15:18'!\\nmethodNamesContainingIt: characterStream \\n\\t\\\"Browse methods whose selectors containing the selection in their names\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself methodNamesContainingIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 9/9/97 16:44'!\\nmethodStringsContainingIt: characterStream \\n\\t\\\"Invoked from cmd-E -- open a browser on all methods holding string constants containing it. Flushes typeahead. \\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself methodStringsContainingit.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nnoop: characterStream \\n\\t\\\"Unimplemented keyboard command; just ignore it.\\\"\\n\\n\\tsensor keyboard.\\t \\\"flush character\\\"\\n\\t^ true\\n! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 1/19/2000 11:14'!\\nofferFontMenu\\n\\t\\\"Present a menu of available fonts, and if one is chosen, apply it to the current selection. \\n\\tUse only names of Fonts of this paragraph \\\"\\n\\n\\t| aList reply |\\n\\taList _ paragraph textStyle fontNamesWithPointSizes.\\n\\treply _ (SelectionMenu labelList: aList selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[self replaceSelectionWith:\\n\\t\\t\\t(Text string: self selection asString \\n\\t\\t\\t\\tattribute: (TextFontChange fontNumber: (aList indexOf: reply)))] ! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nofferFontMenu: characterStream \\n\\t\\\"The user typed the command key that requests a font change; Offer the font menu. 5/27/96 sw\\n\\t Keeps typeahead. (?? should flush?)\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself offerFontMenu.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\noutdent: characterStream\\n\\t\\\"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\\\"\\n\\n\\t^ self inOutdent: characterStream delta: -1! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\npaste: characterStream \\n\\t\\\"Replace the current text selection by the text in the shared buffer.\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself paste.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:48'!\\npasteInitials: characterStream \\n\\t\\\"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.\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself replace: self selectionInterval with: (Text fromString: Utilities changeStamp) and: [self selectAt: self stopIndex].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'!\\nprintIt: characterStream \\n\\t\\\"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\\n\\t 2/29/96 sw: don't call selectLine now, since it's called by doIt\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self printIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nreferencesToIt: characterStream \\n\\t\\\"Triggered by Cmd-N; browse references to the current selection\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself referencesToIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'!\\nsave: characterStream\\n\\t\\\"Submit the current text. Equivalent to 'accept' 1/18/96 sw\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself terminateAndInitializeAround: [self accept].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nsendersOfIt: characterStream \\n\\t\\\"Triggered by Cmd-n; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself sendersOfIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'yo 5/27/2004 13:56'!\\nsetEmphasis: emphasisSymbol\\n\\t\\\"Change the emphasis of the current selection.\\\"\\n\\n\\t| oldAttributes attribute |\\n\\toldAttributes _ paragraph text attributesAt: self selectionInterval first forStyle: paragraph textStyle.\\n\\n\\tattribute _ TextEmphasis perform: emphasisSymbol.\\n\\t(emphasisSymbol == #normal) \\n\\t\\tifFalse:\\t[oldAttributes do:\\t\\n\\t\\t\\t[:att | (att dominates: attribute) ifTrue: [attribute turnOff]]].\\n\\tself replaceSelectionWith: (self selection addAttribute: attribute)! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:20'!\\nshiftEnclose: characterStream\\n\\t\\\"Insert or remove bracket characters around the current selection.\\n\\t Flushes typeahead.\\\"\\n\\n\\t| char left right startIndex stopIndex oldSelection which text |\\n\\tchar _ sensor keyboard.\\n\\tchar = $9 ifTrue: [ char _ $( ].\\n\\tchar = $, ifTrue: [ char _ $< ].\\n\\tchar = $[ ifTrue: [ char _ ${ ].\\n\\tchar = $' ifTrue: [ char _ $\\\" ].\\n\\tchar asciiValue = 27 ifTrue: [ char _ ${ ].\\t\\\"ctrl-[\\\"\\n\\n\\tself closeTypeIn.\\n\\tstartIndex _ self startIndex.\\n\\tstopIndex _ self stopIndex.\\n\\toldSelection _ self selection.\\n\\twhich _ '([<{\\\"''' indexOf: char ifAbsent: [1].\\n\\tleft _ '([<{\\\"''' at: which.\\n\\tright _ ')]>}\\\"''' at: which.\\n\\ttext _ paragraph text.\\n\\t((startIndex > 1 and: [stopIndex <= text size])\\n\\t\\tand:\\n\\t\\t[(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])\\n\\t\\tifTrue:\\n\\t\\t\\t[\\\"already enclosed; strip off brackets\\\"\\n\\t\\t\\tself selectFrom: startIndex-1 to: stopIndex.\\n\\t\\t\\tself replaceSelectionWith: oldSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"not enclosed; enclose by matching brackets\\\"\\n\\t\\t\\tself replaceSelectionWith:\\n\\t\\t\\t\\t(Text string: (String with: left), oldSelection string ,(String with: right)\\n\\t\\t\\t\\t\\temphasis: emphasisHere).\\n\\t\\t\\tself selectFrom: startIndex+1 to: stopIndex].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'!\\nspawnIt: characterStream\\n\\t\\\"Triggered by Cmd-o; spawn a new code window, if it makes sense.\\\"\\n\\n\\tsensor keyboard.\\n\\tself terminateAndInitializeAround: [self spawn].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:00'!\\nswapChars: characterStream \\n\\t\\\"Triggered byCmd-Y;. Swap two characters, either those straddling the insertion point, or the two that comprise the selection. Suggested by Ted Kaehler. \\\"\\n\\n\\t| currentSelection aString chars |\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\t(chars _ self selection) size == 0\\n\\t\\tifTrue:\\n\\t\\t\\t[currentSelection _ self pointIndex.\\n\\t\\t\\tself selectMark: currentSelection - 1 point: currentSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[chars size == 2\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[view flash. ^ true]\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[currentSelection _ self pointIndex - 1]].\\n\\taString _ self selection string.\\n\\tself replaceSelectionWith: (Text string: aString reversed emphasis: emphasisHere).\\n\\tself selectAt: currentSelection + 1.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 11/2/1998 15:50'!\\ntempCommand: characterStream \\n\\t\\\"Experimental. Triggered by Cmd-t; put trial cmd-key commands here to see how they work, before hanging them on their own cmd accelerators.\\\"\\n\\tSensor keyboard.\\n\\tself experimentalCommand.\\n\\t^ true\\n\\n\\t\\\"sensor keyboard.\\n\\tself spawnWorkspace.\\n\\t^ true\\\"! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nundo: characterStream \\n\\t\\\"Undo the last edit. Keeps typeahead, so undo twice is a full redo.\\\"\\n\\n\\tsensor keyboard. \\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself undo.\\n\\t^true! !\\n\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/26/2003 22:02'!\\nexplainAnySel: symbol \\n\\t\\\"Is this any message selector?\\\"\\n\\n\\t| list reply |\\n\\tlist _ self systemNavigation allClassesImplementing: symbol.\\n\\tlist size = 0 ifTrue: [^nil].\\n\\tlist size < 12\\n\\t\\tifTrue: [reply _ ' is a message selector which is defined in these classes ' , list printString]\\n\\t\\tifFalse: [reply _ ' is a message selector which is defined in many classes'].\\n\\t^'\\\"' , symbol , reply , '.\\\"' , '\\\\' withCRs, 'SystemNavigation new browseAllImplementorsOf: #' , symbol! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'di 1/30/2002 21:09'!\\nexplainChar: string\\n\\t\\\"Does string start with a special character?\\\"\\n\\n\\t| char |\\n\\tchar _ string at: 1.\\n\\tchar = $. 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 class Float).\\\"'].\\n\\tchar = $' ifTrue: [^'\\\"The characters between two single quotes are made into an instance of class String\\\"'].\\n\\tchar = $\\\" ifTrue: [^'\\\"Double quotes enclose a comment. Smalltalk ignores everything between double quotes.\\\"'].\\n\\tchar = $# 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. It contains literal constants.\\\"'].\\n\\t(char = $( or: [char = $)]) ifTrue: [^'\\\"Expressions enclosed in parenthesis are evaluated first\\\"'].\\n\\t(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.\\\"'].\\n\\t(char = ${ or: [char = $}]) ifTrue: [^ '\\\"A sequence of expressions separated by periods, when enclosed in curly braces, are evaluated to yield the elements of a new Array\\\"'].\\n\\t(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.\\\"'].\\n\\tchar = $^ ifTrue: [^'\\\"Uparrow means return from this method. The value returned is the expression following the ^\\\"'].\\n\\tchar = $| 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.\\\"'].\\n\\tchar = $_ ifTrue: [^'\\\"Left arrow means assignment. The value of the expression after the left arrow is stored into the variable before it.\\\"'].\\n\\tchar = $; ifTrue: [^'\\\"Semicolon means cascading. The message after the semicolon is sent to the same object which received the message before the semicolon.\\\"'].\\n\\tchar = $: 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).', '\\\\\\\\' withCRs, '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).\\\"'].\\n\\tchar = $$ ifTrue: [^'\\\"The single character following a dollar sign is made into an instance of class Character\\\"'].\\n\\tchar = $- ifTrue: [^'\\\"A minus sign in front of a number means a negative number.\\\"'].\\n\\tchar = $e ifTrue: [^'\\\"An e in the middle of a number means that the exponent follows.\\\"'].\\n\\tchar = $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.\\\"'].\\n\\tchar = Character space ifTrue: [^'\\\"the space Character\\\"'].\\n\\tchar = Character tab ifTrue: [^'\\\"the tab Character\\\"'].\\n\\tchar = Character cr ifTrue: [^'\\\"the carriage return Character\\\"'].\\n\\t^nil! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/10/2004 07:02'!\\nexplainClass: symbol \\n\\t\\\"Is symbol a class variable or a pool variable?\\\"\\n\\t| class reply classes |\\n\\t(model respondsTo: #selectedClassOrMetaClass)\\n\\t\\tifFalse: [^ nil].\\n\\t(class _ model selectedClassOrMetaClass) ifNil: [^ nil].\\n\\t\\\"no class is selected\\\"\\n\\t(class isKindOf: Metaclass)\\n\\t\\tifTrue: [class _ class soleInstance].\\n\\tclasses _ (Array with: class)\\n\\t\\t\\t\\t, class allSuperclasses.\\n\\t\\\"class variables\\\"\\n\\treply _ classes detect: [:each | (each classVarNames detect: [:name | symbol = name]\\n\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t~~ nil]\\n\\t\\t\\t\\tifNone: [].\\n\\treply == nil ifFalse: [^ '\\\"is a class variable, defined in class ' , reply printString , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , reply printString , ' classPool associationAt: #' , symbol , ').'].\\n\\t\\\"pool variables\\\"\\n\\tclasses do: [:each | (each sharedPools\\n\\t\\t\\tdetect: [:pool | (pool includesKey: symbol)\\n\\t\\t\\t\\t\\tand: \\n\\t\\t\\t\\t\\t\\t[reply _ pool.\\n\\t\\t\\t\\t\\t\\ttrue]]\\n\\t\\t\\tifNone: [])\\n\\t\\t\\t~~ nil].\\n\\treply\\n\\t\\tifNil: [(Undeclared includesKey: symbol)\\n\\t\\t\\t\\tifTrue: [^ '\\\"is an undeclared variable.' , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (Undeclared associationAt: #' , symbol , ').']]\\n\\t\\tifNotNil: \\n\\t\\t\\t[classes _ WriteStream on: Array new.\\n\\t\\t\\tself systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:each | (each sharedPools\\n\\t\\t\\t\\t\\t\\tdetect: \\n\\t\\t\\t\\t\\t\\t\\t[:pool | \\n\\t\\t\\t\\t\\t\\t\\tpool == reply]\\n\\t\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t\\t~~ nil ifTrue: [classes nextPut: each]].\\n\\t\\t\\t\\\"Perhaps not print whole list of classes if too long. (unlikely)\\\"\\n\\t\\t\\t^ '\\\"is a pool variable from the pool ' , (Smalltalk keyAtIdentityValue: reply) asString , ', which is used by the following classes ' , classes contents printString , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , (Smalltalk keyAtIdentityValue: reply) asString , ' bindingOf: #' , symbol , ').'].\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'sw 5/3/1998 14:32'!\\nexplainCtxt: symbol \\n\\t\\\"Is symbol a context variable?\\\"\\n\\n\\t| reply classes text cls |\\n\\tsymbol = #nil ifTrue: [reply _ '\\\"is a constant. It is the only instance of class UndefinedObject. nil is the initial value of all variables.\\\"'].\\n\\tsymbol = #true ifTrue: [reply _ '\\\"is a constant. It is the only instance of class True and is the receiver of many control messages.\\\"'].\\n\\tsymbol = #false ifTrue: [reply _ '\\\"is a constant. It is the only instance of class False and is the receiver of many control messages.\\\"'].\\n\\tsymbol = #thisContext ifTrue: [reply _ '\\\"is a context variable. Its value is always the MethodContext which is executing this method.\\\"'].\\n\\t(model respondsTo: #selectedClassOrMetaClass) ifTrue: [\\n\\t\\tcls _ model selectedClassOrMetaClass].\\n\\tcls ifNil: [^ reply].\\t \\\"no class known\\\"\\n\\tsymbol = #self ifTrue: \\n\\t\\t\\t[classes _ cls withAllSubclasses.\\n\\t\\t\\tclasses size > 12\\n\\t\\t\\t\\tifTrue: [text _ cls printString , ' or a subclass']\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[classes _ classes printString.\\n\\t\\t\\t\\t\\ttext _ 'one of these classes' , (classes copyFrom: 4 to: classes size)].\\n\\t\\t\\treply _ '\\\"is the receiver of this message; an instance of ' , text , '\\\"'].\\n\\tsymbol = #super ifTrue: [reply _ '\\\"is just like self. Messages to super are looked up in the superclass (' , cls superclass printString , ')\\\"'].\\n\\t^reply! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/29/2003 20:07'!\\nexplainGlobal: symbol \\n\\t\\\"Is symbol a global variable?\\\"\\n\\t| reply classes |\\n\\treply _ Smalltalk at: symbol ifAbsent: [^nil].\\n\\t(reply class == Dictionary or:[reply isKindOf: SharedPool class])\\n\\t\\tifTrue: \\n\\t\\t\\t[classes _ Set new.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply]\\n\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t~~ nil ifTrue: [classes add: each]].\\n\\t\\t\\tclasses _ classes printString.\\n\\t\\t\\t^'\\\"is a global variable. It is a pool which is used by the following classes ' , (classes allButFirst: 5) , '\\\"'].\\n\\t(reply isKindOf: Behavior)\\n\\t\\tifTrue: [^'\\\"is a global variable. ' , symbol , ' is a class in category ', reply category,\\n\\t\\t\\t'.\\\"', '\\\\' withCRs, 'Browser newOnClass: ' , symbol , '.'].\\n\\tsymbol == #Smalltalk ifTrue: [^'\\\"is a global. Smalltalk is the only instance of SystemDictionary and holds all global variables.\\\"'].\\n\\t^'\\\"is a global variable. ' , symbol , ' is ' , reply printString , '\\\"'! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/12/2004 16:22'!\\nexplainInst: string \\n\\t\\\"Is string an instance variable of this class?\\\"\\n\\t| classes cls |\\n\\n\\t(model respondsTo: #selectedClassOrMetaClass) ifTrue: [\\n\\t\\tcls _ model selectedClassOrMetaClass].\\n\\tcls ifNil: [^ nil].\\t \\\"no class known\\\"\\n\\tclasses _ (Array with: cls)\\n\\t\\t\\t\\t, cls allSuperclasses.\\n\\tclasses _ classes detect: [:each | (each instVarNames\\n\\t\\t\\tdetect: [:name | name = string] ifNone: [])\\n\\t\\t\\t~~ nil] ifNone: [^nil].\\n\\tclasses _ classes printString.\\n\\t^ '\\\"is an instance variable of the receiver; defined in class ' , classes , \\n\\t\\t'\\\"\\\\' withCRs , classes , ' systemNavigation browseAllAccessesTo: ''' , string , ''' from: ', classes, '.'! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'!\\nexplainMySel: symbol \\n\\t\\\"Is symbol the selector of this method? Is it sent by this method? If \\n\\tnot, then expalin will call (explainPartSel:) to see if it is a fragment of a \\n\\tselector sent here. If not, explain will call (explainAnySel:) to catch any \\n\\tselector. \\\"\\n\\n\\t| lits classes msg |\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^nil].\\t\\\"not in a message\\\"\\n\\tclasses _ self systemNavigation allClassesImplementing: symbol.\\n\\tclasses size > 12\\n\\t\\tifTrue: [classes _ 'many classes']\\n\\t\\tifFalse: [classes _ 'these classes ' , classes printString].\\n\\tmsg = symbol\\n\\t\\tifTrue: [^ '\\\"' , symbol , ' is the selector of this very method!! It is defined in ',\\n\\t\\t\\tclasses , '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"']\\n\\t\\tifFalse: \\n\\t\\t\\t[lits _ (model selectedClassOrMetaClass compiledMethodAt:\\n\\t\\t\\t\\tmsg) messages.\\n\\t\\t\\t(lits detect: [:each | each == symbol]\\n\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t== nil ifTrue: [^nil].\\n\\t\\t\\t^ '\\\"' , symbol , ' is a message selector which is defined in ', classes , '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"'].! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'apb 1/5/2000 16:56'!\\nexplainNumber: string \\n\\t\\\"Is string a Number?\\\"\\n\\n\\t| strm c |\\n\\t(c _ string at: 1) isDigit ifFalse: [(c = $- and: [string size > 1 and: [(string at: 2) isDigit]])\\n\\t\\t\\tifFalse: [^nil]].\\n\\tstrm _ ReadStream on: string.\\n\\tc _ Number readFrom: strm.\\n\\tstrm atEnd ifFalse: [^nil].\\n\\tc printString = string\\n\\t\\tifTrue: [^'\\\"' , string , ' is a ' , c class name , '\\\"']\\n\\t\\tifFalse: [^'\\\"' , string , ' (= ' , c printString , ') is a ' , c class name , '\\\"']! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'!\\nexplainPartSel: string \\n\\t\\\"Is this a fragment of a multiple-argument selector sent in this method?\\\"\\n\\t| lits whole reply classes s msg |\\n\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^ nil]. \\\"not in a message\\\"\\n\\tstring last == $: ifFalse: [^ nil].\\n\\t\\\"Name of this method\\\"\\n\\tlits _ Array with: msg.\\n\\t(whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]\\n\\t\\t\\t\\t\\tifNone: []) ~~ nil]\\n\\t\\t\\t\\tifNone: []) ~~ nil\\n\\t\\tifTrue: [reply _ ', which is the selector of this very method!!'.\\n\\t\\t\\ts _ '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"']\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Selectors called from this method\\\"\\n\\t\\t\\tlits _ (model selectedClassOrMetaClass compiledMethodAt:\\n\\t\\t\\t\\tmsg) messages.\\n\\t\\t\\t(whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]\\n\\t\\t\\t\\t\\t\\t\\tifNone: []) ~~ nil]\\n\\t\\t\\t\\t\\t\\tifNone: []) ~~ nil\\n\\t\\t\\t\\tifFalse: [string = 'primitive:'\\n\\t\\t\\t\\t\\tifTrue: [^self explainChar: '<']\\n\\t\\t\\t\\t\\tifFalse: [^nil]].\\n\\t\\t\\treply _ '.'.\\n\\t\\t\\ts _ '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"'].\\n\\tclasses _ self systemNavigation allClassesImplementing: whole.\\n\\tclasses size > 12\\n\\t\\tifTrue: [classes _ 'many classes']\\n\\t\\tifFalse: [classes _ 'these classes ' , classes printString].\\n\\t^ '\\\"' , string , ' is one part of the message selector ' , whole, reply , ' It is defined in ' , classes , s! !\\n\\n!ParagraphEditor methodsFor: 'explain'!\\nexplainScan: string \\n\\t\\\"Remove beginning and trailing space, tab, cr.\\n\\t 1/15/96 sw: copied intact from BrowserCodeController\\\"\\n\\n\\t| c beg end |\\n\\tbeg _ 1.\\n\\tend _ string size.\\n\\t\\n\\t[beg = end ifTrue: [^string copyFrom: 1 to: 1].\\n\\t\\\"if all blank, tell about the first\\\"\\n\\tc _ string at: beg.\\n\\tc = Character space or: [c = Character tab or: [c = Character cr]]]\\n\\t\\twhileTrue: [beg _ beg + 1].\\n\\t\\n\\t[c _ string at: end.\\n\\tc = Character space or: [c = Character tab or: [c = Character cr]]]\\n\\t\\twhileTrue: [end _ end - 1].\\n\\t^string copyFrom: beg to: end\\t\\\"Return purely visible characters\\\"! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tk 4/1/98 14:19'!\\nexplainTemp: string \\n\\t\\\"Is string the name of a temporary variable (or block argument variable)?\\\"\\n\\n\\t| selectedClass tempNames i reply methodNode method msg |\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^nil].\\t\\\"not in a message\\\"\\n\\tselectedClass _ model selectedClassOrMetaClass.\\n\\ttempNames _ selectedClass parserClass new \\n\\t\\t\\tparseArgsAndTemps: model selectedMessage notifying: nil.\\n\\tmethod _ selectedClass compiledMethodAt: msg.\\n\\t(i _ tempNames findFirst: [:each | each = string]) = 0 ifTrue: [\\n\\t\\t(method numTemps > tempNames size)\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[\\\"It must be an undeclared block argument temporary\\\"\\n\\t\\t\\t\\tmethodNode _ selectedClass compilerClass new\\n\\t\\t\\t\\t\\t\\t\\tparse: model selectedMessage\\n\\t\\t\\t\\t\\t\\t\\tin: selectedClass\\n\\t\\t\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\ttempNames _ methodNode tempNames]\\n\\t\\t\\tifFalse: [^nil]].\\n\\t(i _ tempNames findFirst: [:each | each = string]) > 0 ifTrue: [i > method numArgs\\n\\t\\t\\tifTrue: [reply _ '\\\"is a temporary variable in this method\\\"']\\n\\t\\t\\tifFalse: [reply _ '\\\"is an argument to this method\\\"']].\\n\\t^reply! !\\n\\n\\n!ParagraphEditor methodsFor: 'initialize-release'!\\nchangeParagraph: aParagraph \\n\\t\\\"Install aParagraph as the one to be edited by the receiver.\\\"\\n\\n\\tUndoParagraph == paragraph ifTrue: [UndoParagraph _ nil].\\n\\tparagraph _ aParagraph.\\n\\tself resetState! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'th 10/21/2003 15:49'!\\nresetState \\n\\t\\\"Establish the initial conditions for editing the paragraph: place caret \\n\\tbefore first character, set the emphasis to that of the first character,\\n\\tand save the paragraph for purposes of canceling.\\\"\\n\\n\\tstopBlock _ paragraph defaultCharacterBlock.\\n\\tself pointBlock: stopBlock copy.\\n\\tbeginTypeInBlock _ nil.\\n\\tUndoInterval _ otherInterval _ 1 to: 0.\\n\\tself setEmphasisHere.\\n\\tselectionShowing _ false.\\n\\tinitialText _ paragraph text copy! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 5/15/2000 13:51'!\\nstateArray\\n\\t^ {ChangeText.\\n\\t\\tFindText.\\n\\t\\tUndoInterval.\\n\\t\\tUndoMessage.\\n\\t\\tUndoParagraph.\\n\\t\\tUndoSelection.\\n\\t\\tUndone.\\n\\t\\tself selectionInterval.\\n\\t\\tself startOfTyping.\\n\\t\\temphasisHere}! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 10/5/1998 17:03'!\\nstateArrayPut: stateArray\\n\\t| sel |\\n\\tChangeText _ stateArray at: 1.\\n\\tFindText _ stateArray at: 2.\\n\\tUndoInterval _ stateArray at: 3.\\n\\tUndoMessage _ stateArray at: 4.\\n\\tUndoParagraph _ stateArray at: 5.\\n\\tUndoSelection _ stateArray at: 6.\\n\\tUndone _ stateArray at: 7.\\n\\tsel _ stateArray at: 8.\\n\\tself selectFrom: sel first to: sel last.\\n\\tbeginTypeInBlock _ stateArray at: 9.\\n\\temphasisHere _ stateArray at: 10.! !\\n\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'jm 5/3/1998 19:19'!\\naccept\\n\\t\\\"Save the current text of the text being edited as the current acceptable version for purposes of canceling.\\\"\\n\\n\\tinitialText _ paragraph text copy.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nagain\\n\\t\\\"Text substitution. If the left shift key is down, the substitution is made \\n\\tthroughout the entire Paragraph. Otherwise, only the next possible \\n\\tsubstitution is made.\\n\\tUndoer & Redoer: #undoAgain:andReselect:typedKey:.\\\"\\n\\n\\t\\\"If last command was also 'again', use same keys as before\\\"\\n\\tself againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:)! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nalign\\n\\t\\\"Align text according to the next greater alignment value--cycling among \\n\\tleft flush, right flush, center, justified. No effect on the undoability of the pre\\n\\tpreceding command.\\\"\\n\\n\\tparagraph toggleAlignment.\\n\\tparagraph displayOn: Display.\\n\\tself recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 8/2/2005 20:53'!\\nbrowseClassFromIt\\n\\t\\\"Launch a browser for the class indicated by the current selection. \\n\\tIf multiple classes matching the selection exist, let the user choose among them.\\\"\\n\\t| aBrow aClass |\\n\\tself\\n\\t\\tlineSelectAndEmptyCheck: [^ self].\\n\\taClass := Utilities\\n\\t\\t\\t\\tclassFromPattern: (self selection string copyWithout: Character cr)\\n\\t\\t\\t\\twithCaption: 'choose a class to browse...'.\\n\\taClass\\n\\t\\tifNil: [^ view flash].\\n\\tself\\n\\t\\tterminateAndInitializeAround: \\n\\t\\t\\t[aBrow := SystemBrowser default new.\\n\\t\\t\\taBrow setClass: aClass selector: nil.\\n\\t\\t\\taBrow class\\n\\t\\t\\t\\topenBrowserView: (aBrow openEditString: nil) label: 'System Browser'].! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'pmm 7/6/2006 20:50'!\\nbrowseIt\\n\\t\\\"Launch a browser for the current selection, if appropriate\\\"\\n\\n\\t| aSymbol anEntry |\\n\\tself flag: #yoCharCases.\\n\\n\\tPreferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt].\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround:\\n\\t\\t[aSymbol first isUppercase\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[anEntry _ (Smalltalk\\n\\t\\t\\t\\t\\tat: aSymbol\\n\\t\\t\\t\\t\\tifAbsent:\\n\\t\\t\\t\\t\\t\\t[ self systemNavigation browseAllImplementorsOf: aSymbol.\\n\\t\\t\\t\\t\\t\\t^ nil]).\\n\\t\\t\\t\\tanEntry isNil ifTrue: [^ view flash].\\n\\t\\t\\t\\t(anEntry isBehavior or: [ anEntry isTrait ])\\n\\t\\t\\t\\t\\tifFalse: [ anEntry := anEntry class ].\\n\\t\\t\\t\\tToolSet browse: anEntry selector: nil.\\n\\t\\t] ifFalse:[ self systemNavigation browseAllImplementorsOf: aSymbol]]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 1/15/98 12:57'!\\ncancel \\n\\t\\\"Restore the text of the paragraph to be the text saved since initialization \\n\\tor the last accept. Undoer & Redoer: undoAndReselect:redoAndReselect:.\\n\\tThis used to call controlTerminate and controlInitialize but this seemed illogical.\\n\\tSure enough, nobody overrode them who had cancel in the menu, and if\\n\\tanybody really cared they could override cancel.\\\"\\n\\n\\tUndoSelection _ paragraph text.\\n\\tself undoer: #undoAndReselect:redoAndReselect: with: self selectionInterval with: (1 to: 0).\\n\\tview ifNotNil: [view clearInside].\\n\\tself changeParagraph: (paragraph text: initialText).\\n\\tUndoParagraph _ paragraph.\\n\\totherInterval _ UndoInterval _ 1 to: initialText size. \\\"so undo will replace all\\\"\\n\\tparagraph displayOn: Display.\\n\\tself selectAt: 1.\\n\\tself scrollToTop\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 2/17/2005 17:53'!\\nchangeAlignment\\n\\t| aList reply |\\n\\taList _ #(leftFlush centered justified rightFlush).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ifNil:[^self].\\n\\tself setAlignment: reply.\\n\\tparagraph composeAll.\\n\\tself recomputeSelection.\\n\\tself mvcRedisplay.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 3/14/2005 13:03'!\\nchangeEmphasis\\n\\t| aList reply |\\n\\taList _ #(normal bold italic narrow underlined struckOut).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[self setEmphasis: reply.\\n\\t\\tparagraph composeAll.\\n\\t\\tself recomputeSelection.\\n\\t\\tself mvcRedisplay].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'fc 2/19/2004 22:09'!\\nchangeEmphasisOrAlignment\\n\\t| aList reply |\\n\\taList _ #(normal bold italic narrow underlined struckOut leftFlush centered rightFlush justified).\\n\\treply _ (SelectionMenu labelList: aList lines: #(6) selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[(#(leftFlush centered rightFlush justified) includes: reply)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[paragraph perform: reply.\\n\\t\\t\\t\\tself recomputeInterval]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self setEmphasis: reply.\\n\\t\\t\\t\\tparagraph composeAll.\\n\\t\\t\\t\\tself recomputeSelection.\\n\\t\\t\\t\\tself mvcRedisplay]].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 10/22/2003 15:27'!\\nchangeStyle\\n\\t\\\"Let user change styles for the current text pane \\n\\t Moved from experimentalCommand to its own method \\\"\\n\\n\\t| aList reply style |\\n\\taList _ StrikeFont actualFamilyNames.\\n\\taList addFirst: 'DefaultTextStyle'.\\n\\treply _ (SelectionMenu labelList: aList lines: #(1) selections: aList) startUp.\\n\\treply ifNotNil:\\n\\t\\t[(style _ TextStyle named: reply) ifNil: [Beeper beep. ^ true].\\n\\t\\tparagraph textStyle: style copy.\\n\\t\\tparagraph composeAll.\\n\\t\\tself recomputeSelection.\\n\\t\\tself mvcRedisplay].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'RAA 3/15/2001 12:10'!\\nchangeStyleTo: aNewStyle\\n\\n\\tparagraph textStyle: aNewStyle.\\n\\tparagraph composeAll.\\n\\tself recomputeSelection.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 9/27/1999 11:54'!\\nchooseAlignment\\n\\tself changeAlignment! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/15/2003 22:40'!\\nclassCommentsContainingIt\\n\\t\\\"Open a browser class comments which contain the current selection somewhere in them.\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself terminateAndInitializeAround: [\\n\\t\\tself systemNavigation browseClassCommentsWithString: self selection string]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dvf 8/23/2003 11:51'!\\nclassNamesContainingIt\\n\\t\\\"Open a browser on classes whose names contain the selected string\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^self].\\n\\tself systemNavigation \\n\\t\\tbrowseClassesWithNamesContaining: self selection string\\n\\t\\tcaseSensitive: Sensor leftShiftDown! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:37'!\\nclipboardText\\n\\n\\t^ Clipboard clipboardText! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'!\\nclipboardText: text\\n\\n\\t^ Clipboard clipboardText: text! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'!\\nclipboardTextPut: text\\n\\n\\t^ Clipboard clipboardText: text! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 11/23/1998 15:21'!\\ncompareToClipboard\\n\\t\\\"Check to see if whether the receiver's text is the same as the text currently on the clipboard, and inform the user.\\\"\\n\\t| s1 s2 |\\n\\ts1 _ self clipboardText string.\\n\\ts2 _ paragraph text string.\\n\\ts1 = s2 ifTrue: [^ self inform: 'Exact match'].\\n\\n\\t(StringHolder new textContents:\\n\\t\\t(TextDiffBuilder buildDisplayPatchFrom: s1 to: s2))\\n\\t\\topenLabel: 'Comparison to Clipboard Text'! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 15:09'!\\ncopySelection\\n\\t\\\"Copy the current selection and store it in the paste buffer, unless a caret. Undoer & Redoer: undoCutCopy\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\n\\t\\\"Simulate 'substitute: self selection' without locking the controller\\\"\\n\\tUndoSelection _ self selection.\\n\\tself undoer: #undoCutCopy: with: self clipboardText.\\n\\tUndoInterval _ self selectionInterval.\\n\\tself clipboardTextPut: UndoSelection! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 16:33'!\\ncut\\n\\t\\\"Cut out the current selection and redisplay the paragraph if necessary. Undoer & Redoer: undoCutCopy:\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\n\\tself replaceSelectionWith: self nullText. \\n\\tself undoer: #undoCutCopy: with: self clipboardText.\\n\\tself clipboardTextPut: UndoSelection! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nexchange\\n\\t\\\"See comment in exchangeWith:\\\"\\n\\n\\tself exchangeWith: otherInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:34'!\\nexperimentalCommand\\n\\t\\\"Use for experimental command-key implementation. Using this, \\n\\tyou can try things out without forever needing to reinitialize the \\n\\tParagraphEditor.\\\"\\n\\n\\tself prettyPrint.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ls 10/10/1999\\n11:36'!\\nexplain\\n\\t\\\"Try to shed some light on what kind of entity the current selection\\nis. \\n\\tThe selection must be a single token or construct. Insert the answer\\nafter \\n\\tthe selection. Send private messages whose names begin with 'explain' \\n\\tthat return a string if they recognize the selection, else nil.\\\"\\n\\n\\t| string tiVars cgVars selectors delimitors numbers sorry reply symbol\\n|\\nCursor execute showWhile: \\n\\t\\t\\t[sorry _ '\\\"Sorry, I can''t explain that. Please select a single\\ntoken, construct, or special character.'.\\n\\t\\t\\tsorry _ sorry , (view canDiscardEdits\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [' Also, please cancel or accept.\\\"']\\n\\t\\t\\t\\t\\t\\t\\tifTrue: ['\\\"']).\\n\\t\\t\\t(string _ self selection asString) isEmpty\\n\\t\\t\\t\\tifTrue: [reply _ '']\\n\\t\\t\\t\\tifFalse: [string _ self explainScan: string.\\n\\t\\t\\t\\t\\t\\\"Remove space, tab, cr\\\"\\n\\t\\t\\t\\t\\t\\\"Temps and Instance vars need only test strings that are all\\nletters\\\"\\n\\t\\t\\t\\t\\t(string detect: [:char | (char isLetter or: [char isDigit]) not]\\n\\t\\t\\t\\t\\t\\tifNone: []) ifNil: \\n\\t\\t\\t\\t\\t\\t\\t[tiVars _ self explainTemp: string.\\n\\t\\t\\t\\t\\t\\t\\ttiVars == nil ifTrue: [tiVars _ self explainInst: string]].\\n\\t\\t\\t\\t\\t(tiVars == nil and: [model respondsTo: #explainSpecial:])\\n\\t\\t\\t\\t\\t\\tifTrue: [tiVars _ model explainSpecial: string].\\n\\t\\t\\t\\t\\ttiVars == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [tiVars _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [tiVars _ tiVars , '\\\\' withCRs].\\n\\t\\t\\t\\t\\t\\\"Context, Class, Pool, and Global vars, and Selectors need \\n\\t\\t\\t\\t\\tonly test symbols\\\"\\n\\t\\t\\t\\t\\t(Symbol hasInterned: string ifTrue: [:s | symbol _ s])\\n\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ self explainCtxt: symbol.\\n\\t\\t\\t\\t\\t\\t\\tcgVars == nil\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ self explainClass: symbol.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcgVars == nil ifTrue: [cgVars _ self explainGlobal: symbol]].\\n\\t\\t\\t\\t\\t\\t\\t\\\"See if it is a Selector (sent here or not)\\\"\\n\\t\\t\\t\\t\\t\\t\\tselectors _ self explainMySel: symbol.\\n\\t\\t\\t\\t\\t\\t\\tselectors == nil\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[selectors _ self explainPartSel: string.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tselectors == nil ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tselectors _ self explainAnySel: symbol]]]\\n\\t\\t\\t\\t\\t\\tifFalse: [selectors _ self explainPartSel: string].\\n\\t\\t\\t\\t\\tcgVars == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [cgVars _ cgVars , '\\\\' withCRs].\\n\\t\\t\\t\\t\\tselectors == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [selectors _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [selectors _ selectors , '\\\\' withCRs].\\n\\t\\t\\t\\t\\tstring size = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"single special characters\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelimitors _ self explainChar: string]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"matched delimitors\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelimitors _ self explainDelimitor: string].\\n\\t\\t\\t\\t\\tnumbers _ self explainNumber: string.\\n\\t\\t\\t\\t\\tnumbers == nil ifTrue: [numbers _ ''].\\n\\t\\t\\t\\t\\tdelimitors == nil ifTrue: [delimitors _ ''].\\n\\t\\t\\t\\t\\treply _ tiVars , cgVars , selectors , delimitors , numbers].\\n\\t\\t\\treply size = 0 ifTrue: [reply _ sorry].\\n\\t\\t\\tself afterSelectionInsertAndSelect: reply]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:41'!\\nfileItIn\\n\\t\\\"Make a Stream on the text selection and fileIn it.\\n\\t 1/24/96 sw: moved here from FileController; this function can be useful from any text window that shows stuff in chunk format\\\"\\n\\n\\t| selection |\\n\\tselection _ self selection.\\n\\tself terminateAndInitializeAround:\\n\\t\\t[(ReadWriteStream on: selection string from: 1 to: selection size) fileIn].\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'CdG 10/17/2005 20:49'!\\nfind\\n\\t\\\"Prompt the user for a string to search for, and search the receiver from the current selection onward for it. 1/26/96 sw\\\"\\n\\n\\t| reply |\\n\\treply := UIManager default request: 'Find what? ' translated initialAnswer: ''.\\n\\treply size == 0 ifTrue: [^ self].\\n\\tself setSearch: reply.\\n\\tChangeText := FindText. \\\"Implies no replacement to againOnce: method\\\"\\n\\tself againOrSame: true\\n\\t\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nfindAgain\\n\\t\\\"Find the text-to-find again. 1/24/96 sw\\\"\\n\\n\\tself againOrSame: true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nfit\\n\\t\\\"Make the bounding rectangle of the paragraph contain all the text while \\n\\t not changing the width of the view of the paragraph. No effect on undoability\\n\\t of the preceding command.\\\"\\n\\n\\tparagraph clearVisibleRectangle.\\n\\tparagraph fit.\\n\\tparagraph displayOn: Display; outline.\\n\\tself recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 09:42'!\\nimplementorsOfIt\\n\\t\\\"Open an implementors browser on the selected selector\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [ self systemNavigation browseAllImplementorsOf: aSelector]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:12'!\\nlineSelectAndEmptyCheck: returnBlock\\n\\t\\\"If the current selection is an insertion point, expand it to be the entire current line; if after that's done the selection is still empty, then evaluate the returnBlock, which will typically consist of '[^ self]' in the caller -- check senders of this method to understand this.\\\"\\n\\n\\tself selectLine. \\\"if current selection is an insertion point, then first select the entire line in which occurs before proceeding\\\"\\n\\tself hasSelection ifFalse: [self flash. ^ returnBlock value]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dgd 11/25/2004 18:03'!\\nmakeProjectLink\\n\\t\\n\\t| attribute thisSel |\\n\\t\\n\\tthisSel := self selection.\\n\\n\\tattribute := TextSqkProjectLink new. \\n\\tthisSel := attribute analyze: self selection asString.\\n\\n\\tthisSel ifNil: [^ true].\\n\\tself replaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:31'!\\nmethodNamesContainingIt\\n\\t\\\"Open a browser on methods names containing the selected string\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tCursor wait showWhile:\\n\\t\\t[self terminateAndInitializeAround: [self systemNavigation browseMethodsWhoseNamesContain: self selection string withBlanksTrimmed]].\\n\\tCursor normal show! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 9/6/2005 18:45'!\\nmethodSourceContainingIt\\n\\t\\\"Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source). Slow!!\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself systemNavigation browseMethodsWithSourceString: self selection string! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:28'!\\nmethodStringsContainingit\\n\\t\\\"Open a browser on methods which contain the current selection as part of a string constant.\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself terminateAndInitializeAround: [self systemNavigation browseMethodsWithString: self selection string]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 10/2/97 11:34'!\\nmvcRedisplay\\n\\t\\\"Overridable by subclasses that do their own display\\\"\\n\\tDisplay fill: paragraph clippingRectangle \\n\\t\\t\\tfillColor: view backgroundColor.\\t\\\"very brute force\\\"\\n\\tself display! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/20/2002 11:21'!\\npaste\\n\\t\\\"Paste the text from the shared buffer over the current selection and \\n\\tredisplay if necessary. Undoer & Redoer: undoAndReselect.\\\"\\n\\n\\tself replace: self selectionInterval with: self clipboardText and:\\n\\t\\t[self selectAt: self pointIndex]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:36'!\\npasteRecent\\n\\t\\\"Paste an item chose from RecentClippings.\\\"\\n\\n\\t| clipping |\\n\\t(clipping _ Clipboard chooseRecentClipping) ifNil: [^ self].\\n\\tClipboard clipboardText: clipping.\\n\\t^ self paste! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nperformMenuMessage: aSelector\\n\\t\\\"If a menu command is invoked, typeIn must be closed first, the selection\\n\\t must be unhighlighted before and rehighlighted after, and the marker\\n\\t must be updated.\\\"\\n\\n\\tself closeTypeIn.\\n\\tself deselect.\\n\\tsuper performMenuMessage: aSelector.\\n\\tself selectAndScroll.\\n\\tself updateMarker! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'rbb 2/16/2005 16:49'!\\npresentSpecialMenu\\n\\t\\\"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\\\"\\n\\n\\t| reply items |\\n\\tself terminateAndInitializeAround:\\n\\t\\t[reply _ (UIManager default chooseFrom: (items _ self specialMenuItems) lines: #()).\\n\\t\\treply = 0 ifTrue: [^ self].\\n\\t\\tCompiler new evaluate: (items at: reply) in: [] to: self]\\n\\t! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'!\\nprettyPrint\\n\\tself prettyPrint: false! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 7/13/2006 16:00'!\\nprettyPrint: decorated\\n\\t\\\"Reformat the contents of the receiver's view (a Browser).\\\"\\n\\n\\t| selectedClass newText |\\n\\tmodel selectedMessageCategoryName ifNil: [^ view flash].\\n\\tselectedClass _ model selectedClassOrMetaClass.\\n\\tnewText _ selectedClass prettyPrinterClass\\n\\t\\tformat: self text\\n\\t\\tin: selectedClass\\n\\t\\tnotifying: self\\n\\t\\tdecorated: decorated.\\n\\tnewText ifNotNil:\\n\\t\\t[self deselect; selectInvisiblyFrom: 1 to: paragraph text size.\\n\\t\\tself replaceSelectionWith: (newText asText makeSelectorBoldIn: selectedClass).\\n\\t\\tself selectAt: 1]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'!\\nprettyPrintWithColor\\n\\tself prettyPrint: true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dew 3/7/2000 21:06'!\\nprinterSetup\\n\\t\\n\\tTextPrinter defaultTextPrinter inspect\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 11:47'!\\nreferencesToIt\\n\\t\\\"Open a references browser on the selected symbol\\\"\\n\\n\\t| aSymbol |\\n\\tself selectLine.\\n\\t((aSymbol _ self selectedSymbol) == nil or:\\n\\t\\t[(Smalltalk includesKey: aSymbol) not])\\n\\t\\t\\tifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: (Smalltalk associationAt: self selectedSymbol)]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'CdG 10/17/2005 20:47'!\\nsaveContentsInFile\\n\\t\\\"Save the receiver's contents string to a file, prompting the user for a file-name. Suggest a reasonable file-name.\\\"\\n\\n\\t| fileName stringToSave parentWindow labelToUse suggestedName lastIndex |\\n\\tstringToSave := paragraph text string.\\n\\tstringToSave size == 0 ifTrue: [^ self inform: 'nothing to save.'].\\n\\tparentWindow := self model dependents\\n\\t\\t\\t\\t\\t\\tdetect: [:dep | dep isKindOf: SystemWindow orOf: StandardSystemView]\\n\\t\\t\\t\\t\\t\\tifNone: [nil].\\n\\tlabelToUse := parentWindow\\n\\t\\tifNil: \\t\\t['Untitled']\\n\\t\\tifNotNil: \\t[parentWindow label].\\n\\tsuggestedName := nil.\\n\\t#(('Decompressed contents of: '\\t\\t'.gz')) do: \\\"can add more here...\\\"\\n\\t\\t[:leaderTrailer |\\n\\t\\t\\t(labelToUse beginsWith: leaderTrailer first) ifTrue:\\n\\t\\t\\t\\t[suggestedName := labelToUse copyFrom: leaderTrailer first size + 1 to: labelToUse size.\\n\\t\\t\\t\\t(labelToUse endsWith: leaderTrailer last)\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[suggestedName := suggestedName copyFrom: 1 to: suggestedName size - leaderTrailer last size]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[lastIndex := suggestedName lastIndexOf: $. ifAbsent: [0].\\n\\t\\t\\t\\t\\t\\t(lastIndex = 0 or: [lastIndex = 1]) ifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[suggestedName := suggestedName copyFrom: 1 to: lastIndex - 1]]]].\\n\\n\\tsuggestedName ifNil:\\n\\t\\t[suggestedName := labelToUse, '.text'].\\n\\t\\t\\t\\n\\tfileName := UIManager default request: 'File name?' translated\\n\\t\\t\\tinitialAnswer: suggestedName.\\n\\tfileName isEmptyOrNil ifFalse:\\n\\t\\t[(FileStream newFileNamed: fileName) nextPutAll: stringToSave; close]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'bf 10/13/1999 09:09'!\\nselectedSelector\\n\\t\\\"Try to make a selector out of the current text selection\\\"\\n\\t^self selection string findSelector! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 7/5/2004 16:38'!\\nselectedSymbol\\n\\t\\\"Return the currently selected symbol, or nil if none. Spaces, tabs and returns are ignored\\\"\\n\\n\\t| aString |\\n\\tself hasCaret ifTrue: [^ nil].\\n\\taString _ self selection string.\\n\\taString isOctetString ifTrue: [aString _ aString asOctetString].\\n\\taString _ aString copyWithoutAll:\\n\\t\\t{Character space. Character cr. Character tab}.\\n\\taString size == 0 ifTrue: [^ nil].\\n\\tSymbol hasInterned: aString ifTrue: [:sym | ^ sym].\\n\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 2/23/2001 09:26'!\\nselectionAsTiles\\n\\t\\\"Try to make new universal tiles from the selected text\\\"\\n\\t| selection tiles |\\n\\n\\tselection _ self selection.\\n\\tself terminateAndInitializeAround:\\n\\t\\t[self currentHand attachMorph: (tiles _ Player tilesFrom: selection).\\n\\t\\tPreferences tileTranslucentDrag\\n\\t\\t\\tifTrue: [tiles lookTranslucent]\\n\\t\\t\\tifFalse: [tiles align: tiles topLeft \\n\\t\\t\\t \\t\\t\\twith: self currentHand position + tiles cursorBaseOffset]].! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'gm 2/16/2003 20:38'!\\nsendContentsToPrinter\\n\\t| textToPrint printer parentWindow |\\n\\ttextToPrint := paragraph text.\\n\\ttextToPrint size == 0 ifTrue: [^self inform: 'nothing to print.'].\\n\\tprinter := TextPrinter defaultTextPrinter.\\n\\tparentWindow := self model dependents \\n\\t\\t\\t\\tdetect: [:dep | dep isSystemWindow]\\n\\t\\t\\t\\tifNone: [nil].\\n\\tparentWindow isNil \\n\\t\\tifTrue: [printer documentTitle: 'Untitled']\\n\\t\\tifFalse: [printer documentTitle: parentWindow label].\\n\\tprinter printText: textToPrint! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:30'!\\nsendersOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: aSelector]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/18/2002 17:28'!\\nsetAlignment: aSymbol\\n\\t| attr interval |\\n\\tattr _ TextAlignment perform: aSymbol.\\n\\tinterval _ self encompassLine: self selectionInterval.\\n\\tparagraph replaceFrom: interval first to: interval last with:\\n\\t\\t((paragraph text copyFrom: interval first to: interval last) addAttribute: attr) displaying: true.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:27'!\\nsetSearchString\\n\\t\\\"Make the current selection, if any, be the current search string.\\\"\\n\\tself hasCaret ifTrue: [view flash. ^ self].\\n\\tself setSearch: self selection string! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dgd 8/28/2004 13:59'!\\nspawn\\n\\t\\\"Create and schedule a message browser for the code of the model's \\n\\tselected message. Retain any edits that have not yet been accepted.\\\"\\n\\t| code |\\n\\tcode _ paragraph text string.\\n\\tself cancel.\\n\\tmodel notNil ifTrue:[model spawn: code].\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:44'!\\nspawnWorkspace\\n\\t| toUse |\\n\\tself selectLine.\\n\\ttoUse _ self selection asString.\\n\\ttoUse size > 0 ifFalse:\\n\\t\\t[toUse _ paragraph text string.\\n\\t\\ttoUse size > 0 ifFalse: [^ self flash]].\\n\\t\\\"NB: BrowserCodeController's version does a cancel here\\\"\\n\\tself terminateAndInitializeAround:\\n\\t\\t[Utilities openScratchWorkspaceLabeled: 'Untitled' contents: toUse]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 4/29/96'!\\nspecialMenuItems\\n\\t\\\"Refer to comment under #presentSpecialMenu. .\\n\\t : added objectsReferencingIt,\\\"\\n\\n\\t^ #(\\t'Transcript cr; show: ''testing'''\\n\\t\\t\\t'view superView model inspect'\\n\\t\\t\\t'view superView model browseObjClass'\\n\\t\\t\\t'view display'\\n\\t\\t\\t'self inspect'\\n\\t\\t\\t'view backgroundColor: Color fromUser'\\n\\t\\t\\t'view topView inspect'\\n\\t\\t\\t'self compareToClipboard'\\n\\t\\t\\t'view insideColor: Form white'\\n\\t\\t\\t'self objectsReferencingIt'\\n\\t\\t) ! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'SqR 11/14/2000 12:15'!\\nundo\\n\\t\\\"Reset the state of the paragraph prior to the previous edit.\\n\\t If another ParagraphEditor instance did that edit, UndoInterval is invalid;\\n\\t just recover the contents of the undo-buffer at the start of the paragraph.\\\"\\n\\n\\tsensor flushKeyboard. \\\"a way to flush stuck keys\\\"\\n\\tself closeTypeIn.\\n\\n\\tUndoParagraph == paragraph ifFalse: \\\"Can't undo another paragraph's edit\\\"\\n\\t\\t[UndoMessage _ Message selector: #undoReplace.\\n\\t\\tUndoInterval _ 1 to: 0.\\n\\t\\tUndone _ true].\\n\\tUndoInterval ~= self selectionInterval ifTrue: \\\"blink the actual target\\\"\\n\\t\\t[self selectInterval: UndoInterval; deselect].\\n\\n\\t\\\"Leave a signal of which phase is in progress\\\"\\n\\tUndoParagraph _ Undone ifTrue: [#redoing] ifFalse: [#undoing].\\n\\tUndoMessage sentTo: self.\\n\\tUndoParagraph _ paragraph! !\\n\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:37'!\\nadjustSelection: directionBlock\\n\\t\\\"Helper function for Cursor movement. Always moves point thus allowing selections to shrink. \\\"\\n\\t\\\"See also expandSelection:\\\"\\n\\t\\\"Accepts a one argument Block that computes the new postion given an old one.\\\"\\n\\t| newPosition |\\n\\tnewPosition _ directionBlock value: self pointIndex.\\n\\tself selectMark: self markIndex point: newPosition.\\n\\t^true.! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 10/28/2003 12:11'!\\nafterSelectionInsertAndSelect: aString\\n\\n\\tself insertAndSelect: aString at: self stopIndex ! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/17/2002 16:11'!\\ncomputeIntervalFrom: start to: stop\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\tself setMark: start.\\n\\tself setPoint: stop + 1.! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:21'!\\ncorrectFrom: start to: stop with: aString\\n\\t\\\"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.\\\"\\n\\t| wasShowing userSelection delta loc |\\n\\taString = '#insert period' ifTrue:\\n\\t\\t[loc _ start.\\n\\t\\t[(loc _ loc-1)>0 and: [(paragraph text string at: loc) isSeparator]]\\n\\t\\t\\twhileTrue: [loc _ loc-1].\\n\\t\\t^ self correctFrom: loc+1 to: loc with: '.'].\\n\\t(wasShowing _ selectionShowing) ifTrue: [ self reverseSelection ].\\n\\tuserSelection _ self selectionInterval.\\n\\n\\tself selectInvisiblyFrom: start to: stop.\\n\\tself replaceSelectionWith: aString asText.\\n\\n\\tdelta _ aString size - (stop - start + 1).\\n\\tself selectInvisiblyFrom:\\n\\t\\tuserSelection first + (userSelection first > start ifFalse: [ 0 ] ifTrue: [ delta ])\\n\\t\\tto: userSelection last + (userSelection last > start ifFalse: [ 0 ] ifTrue: [ delta ]).\\n\\twasShowing ifTrue: [ self reverseSelection ].\\n! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:21'!\\nencompassLine: anInterval\\n\\t\\\"Return an interval that encompasses the entire line\\\"\\n\\t| string left right |\\n\\tstring _ paragraph text string.\\n\\tleft _ (string lastIndexOf: Character cr startingAt: anInterval first - 1 ifAbsent:[0]) + 1.\\n\\tright _ (string indexOf: Character cr startingAt: anInterval last + 1 ifAbsent: [string size + 1]) - 1.\\n\\t^left to: right! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 12/17/1998 09:41'!\\ninsertAndSelect: aString at: anInteger\\n\\n\\tself replace: (anInteger to: anInteger - 1)\\n\\t\\twith: (Text string: (' ' , aString)\\n\\t\\t\\t\\t\\tattributes: emphasisHere)\\n\\t\\tand: [self selectAndScroll]! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:25'!\\nnextTokenFrom: start direction: dir\\n\\t\\\"simple token-finder for compiler automated corrections\\\"\\n\\t| loc str |\\n\\tloc _ start + dir.\\n\\tstr _ paragraph text string.\\n\\t[(loc between: 1 and: str size) and: [(str at: loc) isSeparator]]\\n\\t\\twhileTrue: [loc _ loc + dir].\\n\\t^ loc! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/20/1998 08:31'!\\nnotify: aString at: anInteger in: aStream \\n\\t\\\"The compilation of text failed. The syntax error is noted as the argument, \\n\\taString. Insert it in the text at starting character position anInteger.\\\"\\n\\n\\tself insertAndSelect: aString at: (anInteger max: 1)! !\\n\\n!ParagraphEditor methodsFor: 'new selection'!\\nselectAt: characterIndex \\n\\t\\\"Deselect, then place the caret before the character at characterIndex.\\n\\t Be sure it is in view.\\\"\\n\\n\\tself selectFrom: characterIndex to: characterIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:50'!\\nselectFrom: start to: stop\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\t(start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse:\\n\\t\\t[self deselect.\\n\\t\\tself selectInvisiblyFrom: start to: stop].\\n\\tself selectAndScroll! !\\n\\n!ParagraphEditor methodsFor: 'new selection'!\\nselectInterval: anInterval\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\tself selectFrom: anInterval first to: anInterval last! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/9/1998 20:59'!\\nselectInvisiblyFrom: start to: stop\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\t^ self computeIntervalFrom: start to: stop! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:17'!\\nselectInvisiblyMark: mark point: point\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\t^ self computeIntervalFrom: mark to: point! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:17'!\\nselectLine\\n\\t\\\"Make the receiver's selection, if it currently consists of an insertion point only, encompass the current line.\\\"\\n\\tself hasSelection ifTrue:[^self].\\n\\tself selectInterval: (self encompassLine: self selectionInterval)! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:18'!\\nselectMark: mark point: point\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\t(mark = self markIndex and: [point + 1 = self pointIndex]) ifFalse:\\n\\t\\t[self deselect.\\n\\t\\tself selectInvisiblyMark: mark point: point].\\n\\tself selectAndScroll! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 18:49'!\\nselectPrecedingIdentifier\\n\\t\\\"Invisibly select the identifier that ends at the end of the selection, if any.\\\"\\n\\n\\t| string sep stop tok |\\n\\ttok _ false.\\n\\tstring _ paragraph text string.\\n\\tstop _ self stopIndex - 1.\\n\\t[stop > 0 and: [(string at: stop) isSeparator]] whileTrue: [stop _ stop - 1].\\n\\tsep _ stop.\\n\\t[sep > 0 and: [(string at: sep) tokenish]] whileTrue: [tok _ true. sep _ sep - 1].\\n\\ttok ifTrue: [self selectInvisiblyFrom: sep + 1 to: stop]! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:51'!\\nselectWord\\n\\t\\\"Select delimited text or word--the result of double-clicking.\\\"\\n\\n\\t| openDelimiter closeDelimiter direction match level leftDelimiters rightDelimiters\\n\\tstring here hereChar start stop |\\n\\tstring _ paragraph text string.\\n\\there _ self pointIndex.\\n\\t(here between: 2 and: string size)\\n\\t\\tifFalse: [\\\"if at beginning or end, select entire string\\\"\\n\\t\\t\\t^self selectFrom: 1 to: string size].\\n\\tleftDelimiters _ '([{<''\\\"\\n'.\\n\\trightDelimiters _ ')]}>''\\\"\\n'.\\n\\topenDelimiter _ string at: here - 1.\\n\\tmatch _ leftDelimiters indexOf: openDelimiter.\\n\\tmatch > 0\\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"delimiter is on left -- match to the right\\\"\\n\\t\\t\\tstart _ here.\\n\\t\\t\\tdirection _ 1.\\n\\t\\t\\there _ here - 1.\\n\\t\\t\\tcloseDelimiter _ rightDelimiters at: match]\\n\\t\\tifFalse: \\n\\t\\t\\t[openDelimiter _ string at: here.\\n\\t\\t\\tmatch _ rightDelimiters indexOf: openDelimiter.\\n\\t\\t\\tmatch > 0\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"delimiter is on right -- match to the left\\\"\\n\\t\\t\\t\\t\\tstop _ here - 1.\\n\\t\\t\\t\\t\\tdirection _ -1.\\n\\t\\t\\t\\t\\tcloseDelimiter _ leftDelimiters at: match]\\n\\t\\t\\t\\tifFalse: [\\\"no delimiters -- select a token\\\"\\n\\t\\t\\t\\t\\tdirection _ -1]].\\n\\tlevel _ 1.\\n\\t[level > 0 and: [direction > 0\\n\\t\\t\\tifTrue: [here < string size]\\n\\t\\t\\tifFalse: [here > 1]]]\\n\\t\\twhileTrue: \\n\\t\\t\\t[hereChar _ string at: (here _ here + direction).\\n\\t\\t\\tmatch = 0\\n\\t\\t\\t\\tifTrue: [\\\"token scan goes left, then right\\\"\\n\\t\\t\\t\\t\\thereChar tokenish\\n\\t\\t\\t\\t\\t\\tifTrue: [here = 1\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[start _ 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"go right if hit string start\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdirection _ 1]]\\n\\t\\t\\t\\t\\t\\tifFalse: [direction < 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[start _ here + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"go right if hit non-token\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdirection _ 1]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [level _ 0]]]\\n\\t\\t\\t\\tifFalse: [\\\"bracket match just counts nesting level\\\"\\n\\t\\t\\t\\t\\thereChar = closeDelimiter\\n\\t\\t\\t\\t\\t\\tifTrue: [level _ level - 1\\\"leaving nest\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [hereChar = openDelimiter \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [level _ level + 1\\\"entering deeper nest\\\"]]]].\\n\\n\\tlevel > 0 ifTrue: [\\\"in case ran off string end\\\"\\there _ here + direction].\\n\\tdirection > 0\\n\\t\\tifTrue: [self selectFrom: start to: here - 1]\\n\\t\\tifFalse: [self selectFrom: here + 1 to: stop]! !\\n\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:51'!\\ncomment\\n\\t\\\"All key actions that are neither editing nor typing actions have to\\n\\tsend closeTypeIn at first. See comment in openTypeIn closeTypeIn\\\"! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:08'!\\ncursorDown: characterStream \\n\\n\\t\\\"Private - Move cursor from position in current line to same position in\\n\\tnext line. If next line too short, put at end. If shift key down,\\n\\tselect.\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor:[:position | self\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:line | line + 1]\\n\\t\\t\\t\\tforward: true]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 10/28/2003 10:47'!\\ncursorEnd: characterStream \\n\\n\\t\\\"Private - Move cursor end of current line.\\\"\\n\\t| string |\\n\\tself closeTypeIn: characterStream.\\n\\tstring _ paragraph text string.\\n\\tself\\n\\t\\tmoveCursor:\\n\\t\\t\\t[:position | Preferences wordStyleCursorMovement\\n\\t\\t\\t\\tifTrue:[| targetLine |\\n\\t\\t\\t\\t\\ttargetLine _ paragraph lines at:(paragraph lineIndexOfCharacterIndex: position).\\n\\t\\t\\t\\t\\ttargetLine = paragraph lines last\\n\\t\\t\\t\\t\\t\\tifTrue:[targetLine last + 1]\\n\\t\\t\\t\\t\\t\\tifFalse:[targetLine last]]\\n\\t\\t\\t\\tifFalse:[\\n\\t\\t\\t\\t\\tstring\\n\\t\\t\\t\\t\\t\\tindexOf: Character cr\\n\\t\\t\\t\\t\\t\\tstartingAt: position\\n\\t\\t\\t\\t\\t\\tifAbsent:[string size + 1]]]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | string size + 1].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/20/2002 12:14'!\\ncursorHome: characterStream \\n\\n\\t\\\"Private - Move cursor from position in current line to beginning of\\n\\tcurrent line. If control key is pressed put cursor at beginning of text\\\"\\n\\n\\t| string |\\n\\n\\tstring _ paragraph text string.\\n\\tself\\n\\t\\tmoveCursor: [ :position | Preferences wordStyleCursorMovement\\n\\t\\t\\t\\tifTrue:[\\n\\t\\t\\t\\t\\t(paragraph lines at:(paragraph lineIndexOfCharacterIndex: position)) first]\\n\\t\\t\\t\\tifFalse:[\\n\\t\\t\\t\\t\\t(string\\n\\t\\t\\t\\t\\t\\tlastIndexOf: Character cr\\n\\t\\t\\t\\t\\t\\tstartingAt: position - 1\\n\\t\\t\\t\\t\\t\\tifAbsent:[0]) + 1]]\\n\\t\\tforward: false\\n\\t\\tspecialBlock: [:dummy | 1].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:07'!\\ncursorLeft: characterStream \\n\\t\\\"Private - Move cursor left one character if nothing selected, otherwise \\n\\tmove cursor to beginning of selection. If the shift key is down, start \\n\\tselecting or extending current selection. Don't allow cursor past \\n\\tbeginning of text\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor:[:position | position - 1 max: 1]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:position | self previousWord: position].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'!\\ncursorPageDown: characterStream \\n\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor: [:position |\\n\\t\\t\\tself\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:lineNo | lineNo + self pageHeight]\\n\\t\\t\\t\\tforward: true]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'!\\ncursorPageUp: characterStream \\n\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor: [:position |\\n\\t\\t\\tself\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:lineNo | lineNo - self pageHeight]\\n\\t\\t\\t\\tforward: false]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:01'!\\ncursorRight: characterStream \\n\\t\\\"Private - Move cursor right one character if nothing selected, \\n\\totherwise move cursor to end of selection. If the shift key is down, \\n\\tstart selecting characters or extending already selected characters. \\n\\tDon't allow cursor past end of text\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor: [:position | position + 1]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:position | self nextWord: position].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:15'!\\ncursorUp: characterStream \\n\\n\\\"Private - Move cursor from position in current line to same position in\\nprior line. If prior line too short, put at end\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor: [:position | self\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:line | line - 1]\\n\\t\\t\\t\\tforward: false]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'di 12/3/2001 21:49'!\\nescapeToDesktop: characterStream \\n\\t\\\"Pop up a morph to field keyboard input in the context of the desktop\\\"\\n\\n\\tSmalltalk isMorphic ifTrue: [ActiveWorld putUpWorldMenuFromEscapeKey].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'dvf 12/8/2001 00:46'!\\nraiseContextMenu: characterStream \\n\\t\\\"AFAIK, this is never called in morphic, because a subclass overrides it. Which is good, because a ParagraphEditor doesn't know about Morphic and thus duplicates the text-editing actions that really belong in the specific application, not the controller. So the context menu this would raise is likely to be out of date.\\\"\\n\\tself yellowButtonActivity.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'!\\nselectCurrentTypeIn: characterStream \\n\\t\\\"Select what would be replaced by an undo (e.g., the last typeIn).\\\"\\n\\n\\t| prior |\\n\\n\\tself closeTypeIn: characterStream.\\n\\tprior _ otherInterval.\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself selectInterval: UndoInterval.\\n\\totherInterval _ prior.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'sma 12/15/1999 11:46'!\\nselectWord: characterStream\\n\\tsensor keyboard.\\n\\tself closeTypeIn: characterStream.\\n\\tself selectWord.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'!\\nsetSearchString: characterStream\\n\\t\\\"Establish the current selection as the current search string.\\\"\\n\\n\\t| aString |\\n\\tself closeTypeIn: characterStream.\\n\\tsensor keyboard.\\n\\tself lineSelectAndEmptyCheck: [^ true].\\n\\taString _ self selection string.\\n\\taString size == 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self flash]\\n\\t\\tifFalse:\\n\\t\\t\\t[self setSearch: aString].\\n\\t^ true! !\\n\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mir 8/3/2004 13:31'!\\nblinkParenAt: parenLocation \\n\\tself text\\n\\t\\taddAttribute: TextEmphasis bold\\n\\t\\tfrom: parenLocation\\n\\t\\tto: parenLocation.\\n\\tlastParentLocation _ parenLocation.! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/7/2002 04:03'!\\nblinkPrevParen\\n\\t| openDelimiter closeDelimiter level string here hereChar |\\n\\tstring _ paragraph text string.\\n\\there _ startBlock stringIndex.\\n\\topenDelimiter _ sensor keyboardPeek.\\n\\tcloseDelimiter _ '([{' at: (')]}' indexOf: openDelimiter).\\n\\tlevel _ 1.\\n\\t[level > 0 and: [here > 2]]\\n\\t\\twhileTrue:\\n\\t\\t\\t[hereChar _ string at: (here _ here - 1).\\n\\t\\t\\thereChar = closeDelimiter\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[level _ level - 1.\\n\\t\\t\\t\\t\\tlevel = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self blinkParenAt: here]]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[hereChar = openDelimiter\\n\\t\\t\\t\\t\\t\\tifTrue: [level _ level + 1]]].! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mir 8/3/2004 13:31'!\\nclearParens\\n\\tlastParentLocation ifNotNil:\\n\\t\\t[self text string size >= lastParentLocation ifTrue: [\\n\\t\\t\\tself text\\n\\t\\t\\t\\tremoveAttribute: TextEmphasis bold\\n\\t\\t\\t\\tfrom: lastParentLocation\\n\\t\\t\\t\\tto: lastParentLocation]]\\n! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mikki 1/5/2005 14:10'!\\ndispatchOnCharacter: char with: typeAheadStream\\n\\t\\\"Carry out the action associated with this character, if any.\\n\\tType-ahead is passed so some routines can flush or use it.\\\"\\n\\n\\t| honorCommandKeys |\\n\\tself clearParens.\\n \\n\\t\\\"mikki 1/3/2005 21:31 Preference for auto-indent on return added.\\\"\\n\\tchar asciiValue = 13 ifTrue: [\\n\\t\\t^Preferences autoIndent \\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tsensor controlKeyPressed\\n\\t\\t\\t\\t\\tifTrue: [self normalCharacter: typeAheadStream]\\n\\t\\t\\t\\t\\tifFalse: [self crWithIndent: typeAheadStream]]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsensor controlKeyPressed\\n\\t\\t\\t\\t\\tifTrue: [self crWithIndent: typeAheadStream]\\n\\t\\t\\t\\t\\tifFalse: [self normalCharacter: typeAheadStream]]].\\n\\n\\t((honorCommandKeys _ Preferences cmdKeysInText) and: [char = Character enter])\\n\\t\\tifTrue: [^ self dispatchOnEnterWith: typeAheadStream].\\n\\t\\t\\n\\t\\\"Special keys overwrite crtl+key combinations - at least on Windows. To resolve this\\n\\tconflict, assume that keys other than cursor keys aren't used together with Crtl.\\\" \\n\\t((self class specialShiftCmdKeys includes: char asciiValue) and: [char asciiValue < 27])\\n\\t\\tifTrue: [^ sensor controlKeyPressed\\n\\t\\t\\tifTrue: [self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream]\\n\\t\\t\\tifFalse: [self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]].\\n\\n\\t\\\"backspace, and escape keys (ascii 8 and 27) are command keys\\\"\\n\\t((honorCommandKeys and: [sensor commandKeyPressed]) or: [self class specialShiftCmdKeys includes: char asciiValue]) ifTrue:\\n\\t\\t[^ sensor leftShiftDown\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]].\\n\\n\\t\\\"the control key can be used to invoke shift-cmd shortcuts\\\"\\n\\t(honorCommandKeys and: [sensor controlKeyPressed])\\n\\t\\tifTrue:\\n\\t\\t\\t[^ self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream].\\n\\n\\t(')]}' includes: char)\\n\\t\\tifTrue: [self blinkPrevParen].\\n\\n\\t^ self perform: #normalCharacter: with: typeAheadStream! !\\n\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\ncomputeMarkerRegion \\n\\t\\\"Refer to the comment in ScrollController|computeMarkerRegion.\\\"\\n\\n\\tparagraph compositionRectangle height = 0\\n\\t\\tifTrue:\\t[^0@0 extent: Preferences scrollBarWidth @ scrollBar inside height]\\n\\t\\tifFalse:\\t[^0@0 extent:\\n\\t\\t\\t\\t\\tPreferences scrollBarWidth \\n\\t\\t\\t\\t\\t\\t@ ((paragraph clippingRectangle height asFloat /\\n\\t\\t\\t\\t\\t\\t\\tself scrollRectangleHeight * scrollBar inside height) rounded\\n\\t\\t\\t\\t\\t\\t\\tmin: scrollBar inside height)]! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nmarkerDelta\\n\\n\\t^marker top - scrollBar top - ((paragraph clippingRectangle top -\\n\\t\\tparagraph compositionRectangle top) asFloat /\\n\\t\\t\\t(self scrollRectangleHeight max: 1) asFloat *\\n\\t\\t\\t\\tscrollBar height asFloat) rounded! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollAmount \\n\\t\\\"Refer to the comment in ScrollController|scrollAmount.\\\"\\n\\n\\t^sensor cursorPoint y - scrollBar top! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollBar\\n\\t^ scrollBar! !\\n\\n!ParagraphEditor methodsFor: 'scrolling' stamp: 'BG 12/12/2003 15:31'!\\nscrollBy: heightToMove\\n\\t\\\"Move the paragraph by heightToMove, and reset the text selection.\\\"\\n\\t^ paragraph scrollBy: heightToMove withSelectionFrom: self pointBlock to: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollRectangleHeight\\n\\n\\t^paragraph compositionRectangle height \\n\\t\\t+ paragraph lineGrid! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollToBottom\\n\\t\\\"Scroll so that the tail end of the text is visible in the view. 5/6/96 sw\\\"\\n\\n\\tself scrollView: (paragraph clippingRectangle bottom \\n\\t\\t- paragraph compositionRectangle bottom)! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollToTop\\n\\t\\\"Scroll so that the paragraph is at the top of the view.\\\"\\n\\n\\tself scrollView: (paragraph clippingRectangle top \\n\\t\\t- paragraph compositionRectangle top)! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollView: anInteger \\n\\t\\\"Paragraph scrolling uses opposite polarity\\\"\\n\\t^ self scrollBy: anInteger negated! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nupdateMarker\\n\\t\\\"A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph.\\\"\\n\\tself moveMarkerTo: self computeMarkerRegion! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nviewDelta \\n\\t\\\"Refer to the comment in ScrollController|viewDelta.\\\"\\n\\n\\t^paragraph clippingRectangle top \\n\\t\\t- paragraph compositionRectangle top \\n\\t\\t- ((marker top - scrollBar inside top) asFloat \\n\\t\\t\\t\\t/ scrollBar inside height asFloat * self scrollRectangleHeight asFloat)\\n\\t\\t\\troundTo: paragraph lineGrid! !\\n\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessBlueButton\\n\\t\\\"The user pressed the blue button on the mouse. Determine what action \\n\\tto take.\\\"\\n\\n\\t^self! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessKeyboard\\n\\t\\\"Determine whether the user pressed the keyboard. If so, read the keys.\\\"\\n\\n\\tsensor keyboardPressed ifTrue: [self readKeyboard]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessMouseButtons\\n\\t\\\"Determine whether the user pressed any mouse button. For each possible \\n\\tbutton, determine what actions to take.\\\"\\n\\n\\tsensor redButtonPressed ifTrue: [self processRedButton].\\n\\tsensor yellowButtonPressed ifTrue: [self processYellowButton].\\n\\tsensor blueButtonPressed ifTrue: [self processBlueButton]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access' stamp: 'th 9/19/2002 18:24'!\\nprocessRedButton\\n\\t\\\"The user pressed a red mouse button, meaning create a new text \\n\\tselection. Highlighting the selection is carried out by the paragraph \\n\\titself. Double clicking causes a selection of the area between the nearest \\n\\tenclosing delimitors.\\\"\\n\\n\\t| selectionBlocks clickPoint oldDelta oldInterval previousMarkBlock previousPointBlock |\\n\\n\\tclickPoint _ sensor cursorPoint.\\n\\t(view containsPoint: clickPoint) ifFalse: [^ self].\\n\\t(paragraph clickAt: clickPoint for: model controller: self) ifTrue: [^ self].\\n\\toldInterval _ self selectionInterval.\\n\\tpreviousMarkBlock _ self markBlock.\\n\\tpreviousPointBlock _ self pointBlock.\\n\\toldDelta _ paragraph scrollDelta.\\n\\tsensor leftShiftDown\\n\\t\\tifFalse:\\n\\t\\t\\t[self deselect.\\n\\t\\t\\tself closeTypeIn.\\n\\t\\t\\tselectionBlocks _ paragraph mouseSelect: clickPoint]\\n\\t\\tifTrue:\\n\\t\\t\\t[selectionBlocks _ paragraph extendSelectionMark: self markBlock pointBlock: self pointBlock.\\n\\t\\t\\tself closeTypeIn].\\n\\tselectionShowing _ true.\\n\\tself markBlock: (selectionBlocks at: 1).\\n\\tself pointBlock: (selectionBlocks at: 2).\\n\\t(self hasCaret\\n\\t\\tand: [previousMarkBlock = self markBlock and: [previousPointBlock = self pointBlock]])\\n\\t\\tifTrue: [self selectWord].\\n\\toldDelta ~= paragraph scrollDelta \\\"case of autoscroll\\\"\\n\\t\\t\\tifTrue: [self updateMarker].\\n\\tself setEmphasisHere.\\n\\t(self isDisjointFrom: oldInterval) ifTrue:\\n\\t\\t[otherInterval _ oldInterval]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessYellowButton\\n\\t\\\"User pressed the yellow button on the mouse. Determine what actions to \\n\\ttake.\\\"\\n\\n\\tself yellowButtonActivity! !\\n\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'yo 3/16/2004 13:05'!\\nbackTo: startIndex\\n\\t\\\"During typing, backspace to startIndex. Deleted characters fall into three\\n\\t clusters, from left to right in the text: (1) preexisting characters that were\\n\\t backed over; (2) newly typed characters that were backed over (excluding\\n\\t typeahead, which never even appears); (3) preexisting characters that\\n\\t were highlighted before typing began. If typing has not yet been opened,\\n\\t open it and watch for the first and third cluster. If typing has been opened,\\n\\t watch for the first and second cluster. Save characters from the first and third\\n\\t cluster in UndoSelection. Tally characters from the first cluster in UndoMessage's parameter.\\n\\t Delete all the clusters. Do not alter Undoer or UndoInterval (except via\\n\\t openTypeIn). The code is shorter than the comment.\\\"\\n\\n\\t| saveLimit newBackovers |\\n\\tsaveLimit _ beginTypeInBlock == nil\\n\\t\\tifTrue: [self openTypeIn. UndoSelection _ self nullText. self stopIndex]\\n\\t\\tifFalse: [self startOfTyping].\\n\\tself setMark: startIndex.\\n\\tstartIndex < saveLimit ifTrue:\\n\\t\\t[newBackovers _ self startOfTyping - startIndex.\\n\\t\\tbeginTypeInBlock _ self startIndex.\\n\\t\\tUndoSelection replaceFrom: 1 to: 0 with:\\n\\t\\t\\t(paragraph text copyFrom: startIndex to: saveLimit - 1).\\n\\t\\tUndoMessage argument: (UndoMessage argument ifNil: [1]) + newBackovers].\\n\\tself zapSelectionWith: self nullText.\\n\\tself unselect! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 17:40'!\\ncloseTypeIn\\n\\t\\\"See comment in openTypeIn. It is important to call closeTypeIn before executing\\n\\t any non-typing key, making a new selection, etc. It is called automatically for\\n\\t menu commands.\\n\\t Typing commands can call 'closeTypeIn: aCharacterStream' instead of this to\\n\\t save typeahead. Undoer & Redoer: undoAndReselect:redoAndReselect:.\\\"\\n\\n\\t| begin stop |\\n\\tbeginTypeInBlock == nil ifFalse:\\n\\t\\t[(UndoMessage sends: #noUndoer) ifTrue: \\\"should always be true, but just in case...\\\"\\n\\t\\t\\t[begin _ self startOfTyping.\\n\\t\\t\\tstop _ self stopIndex.\\n\\t\\t\\tself undoer: #undoAndReselect:redoAndReselect:\\n\\t\\t\\t\\twith: (begin + UndoMessage argument to: begin + UndoSelection size - 1)\\n\\t\\t\\t\\twith: (stop to: stop - 1).\\n\\t\\t\\tUndoInterval _ begin to: stop - 1].\\n\\t\\tbeginTypeInBlock _ nil]! !\\n\\n!ParagraphEditor methodsFor: 'typing support'!\\ncloseTypeIn: characterStream\\n\\t\\\"Call instead of closeTypeIn when you want typeahead to be inserted before the\\n\\t control character is executed, e.g., from Ctrl-V.\\\"\\n\\n\\tself insertTypeAhead: characterStream.\\n\\tself closeTypeIn! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 9/7/1999 11:26'!\\ndispatchOnEnterWith: typeAheadStream\\n\\t\\\"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. \\\"\\n\\n\\tsensor keyboard. \\\"consume enter key\\\"\\n\\tself terminateAndInitializeAround: [\\n\\tsensor commandKeyPressed\\n\\t\\tifTrue:\\n\\t\\t\\t[self printIt.]\\n\\t\\tifFalse: \\n\\t\\t\\t[self closeTypeIn: typeAheadStream.\\n\\t\\t\\tself accept].\\n\\t].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 6/14/1998 13:08'!\\ndoneTyping\\n\\tbeginTypeInBlock _ nil! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'!\\ninsertTypeAhead: typeAhead\\n\\ttypeAhead position = 0 ifFalse:\\n\\t\\t[self zapSelectionWith: (Text string: typeAhead contents emphasis: emphasisHere).\\n\\t\\ttypeAhead reset.\\n\\t\\tself unselect]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:48'!\\nopenTypeIn\\n\\t\\\"Set up UndoSelection to null text (to be added to by readKeyboard and backTo:),\\n\\t beginTypeInBlock to keep track of the leftmost backspace, and UndoParameter to tally\\n\\t how many deleted characters were backspaced over rather than 'cut'.\\n\\t You can't undo typing until after closeTypeIn.\\\"\\n\\n\\tbeginTypeInBlock == nil ifTrue:\\n\\t\\t[UndoSelection _ self nullText.\\n\\t\\tself undoer: #noUndoer with: 0.\\n\\t\\tbeginTypeInBlock _ self startIndex]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 18:26'!\\nreadKeyboard\\n\\t\\\"Key struck on the keyboard. Find out which one and, if special, carry \\n\\tout the associated special action. Otherwise, add the character to the \\n\\tstream of characters. Undoer & Redoer: see closeTypeIn.\\\"\\n\\n\\t| typeAhead char |\\n\\ttypeAhead _ WriteStream on: (String new: 128).\\n\\t[sensor keyboardPressed] whileTrue: \\n\\t\\t[self deselect.\\n\\t\\t [sensor keyboardPressed] whileTrue: \\n\\t\\t\\t[char _ sensor keyboardPeek.\\n\\t\\t\\t(self dispatchOnCharacter: char with: typeAhead) ifTrue:\\n\\t\\t\\t\\t[self doneTyping.\\n\\t\\t\\t\\tself setEmphasisHere.\\n\\t\\t\\t\\t^self selectAndScroll; updateMarker].\\n\\t\\t\\tself openTypeIn].\\n\\t\\tself hasSelection ifTrue: \\\"save highlighted characters\\\"\\n\\t\\t\\t[UndoSelection _ self selection]. \\n\\t\\tself zapSelectionWith: \\n\\t\\t\\t(Text string: typeAhead contents emphasis: emphasisHere).\\n\\t\\ttypeAhead reset.\\n\\t\\tself unselect.\\n\\t\\tsensor keyboardPressed ifFalse: \\n\\t\\t\\t[self selectAndScroll.\\n\\t\\t\\tsensor keyboardPressed\\n\\t\\t\\t\\tifFalse: [self updateMarker]]]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:49'!\\nsetEmphasisHere\\n\\n\\temphasisHere _ (paragraph text attributesAt: (self pointIndex - 1 max: 1) forStyle: paragraph textStyle)\\n\\t\\t\\t\\t\\tselect: [:att | att mayBeExtended]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'!\\nsimulatedKeystroke: char\\n\\t\\\"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.\\\"\\n\\n\\tself deselect.\\n\\tself openTypeIn.\\n\\tself markBlock = self pointBlock ifFalse: [UndoSelection _ self selection].\\n\\tself zapSelectionWith:\\n\\t\\t(Text string: char asString emphasis: emphasisHere).\\n\\tself userHasEdited.\\n\\tself unselect.\\n\\tself selectAndScroll.\\n\\tself updateMarker.\\n\\tview ifNotNil:\\n\\t\\t[view topView uncacheBits\\n\\t\\t\\\"in mvc, this makes sure the recognized character shows up in the pane right now; in morphic, a different mechanism is used for the same effect -- see TextMorphEditor method #recognizeCharactersWhileMouseIn:\\\"]\\n! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 10/6/1998 08:45'!\\nstartOfTyping\\n\\t\\\"Compatibility during change from characterBlock to integer\\\"\\n\\tbeginTypeInBlock == nil ifTrue: [^ nil].\\n\\tbeginTypeInBlock isNumber ifTrue: [^ beginTypeInBlock].\\n\\t\\\"Last line for compatibility during change from CharacterBlock to Integer.\\\"\\n\\t^ beginTypeInBlock stringIndex\\n\\t! !\\n\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:22'!\\nargAdvance: characterStream\\n\\t\\\"Invoked by Ctrl-a. Useful after Ctrl-q.\\n\\t Search forward from the end of the selection for a colon followed by\\n\\t\\ta space. Place the caret after the space. If none are found, place the\\n\\t\\tcaret at the end of the text. Does not affect the undoability of the \\n\\t \\tprevious command.\\\"\\n\\n\\t| start |\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tstart _ paragraph text findString: ': ' startingAt: self stopIndex.\\n\\tstart = 0 ifTrue: [start _ paragraph text size + 1].\\n\\tself selectAt: start + 2.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 10/21/2003 15:46'!\\nbackWord: characterStream \\n\\t\\\"If the selection is not a caret, delete it and leave it in the backspace buffer.\\n\\t Else if there is typeahead, delete it.\\n\\t Else, delete the word before the caret.\\\"\\n\\n\\t| startIndex |\\n\\tsensor keyboard.\\n\\tcharacterStream isEmpty\\n\\t\\tifTrue:\\n\\t\\t\\t[self hasCaret\\n\\t\\t\\t\\tifTrue: \\\"a caret, delete at least one character\\\"\\n\\t\\t\\t\\t\\t[startIndex _ 1 max: self markIndex - 1.\\n\\t\\t\\t\\t\\t[startIndex > 1 and:\\n\\t\\t\\t\\t\\t\\t[(paragraph text at: startIndex - 1) asCharacter tokenish]]\\n\\t\\t\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t\\t\\t[startIndex _ startIndex - 1]]\\n\\t\\t\\t\\tifFalse: \\\"a non-caret, just delete it\\\"\\n\\t\\t\\t\\t\\t[startIndex _ self markIndex].\\n\\t\\t\\tself backTo: startIndex]\\n\\t\\tifFalse:\\n\\t\\t\\t[characterStream reset].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:23'!\\nbackspace: characterStream \\n\\t\\\"Backspace over the last character.\\\"\\n\\n\\t| startIndex |\\n\\tsensor leftShiftDown ifTrue: [^ self backWord: characterStream].\\n\\tcharacterStream isEmpty\\n\\t\\tifTrue:\\n\\t\\t\\t[startIndex _ self markIndex +\\n\\t\\t\\t\\t(self hasCaret ifTrue: [0] ifFalse: [1]).\\n\\t\\t\\t[sensor keyboardPressed and:\\n\\t\\t\\t [sensor keyboardPeek asciiValue = 8]] whileTrue: [\\n\\t\\t\\t\\t\\\"process multiple backspaces\\\"\\n\\t\\t\\t\\tsensor keyboard.\\n\\t\\t\\t\\tstartIndex _ 1 max: startIndex - 1.\\n\\t\\t\\t].\\n\\t\\t\\tself backTo: startIndex]\\n\\t\\tifFalse:\\n\\t\\t\\t[sensor keyboard.\\n\\t\\t\\tcharacterStream skip: -1].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nchangeStyle: characterStream \\n\\t\\\"Put up the style-change menu\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself changeStyle.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:25'!\\ncrWithIndent: characterStream \\n\\t\\\"Replace the current text selection with CR followed by as many tabs\\n\\tas on the current line (+/- bracket count) -- initiated by Shift-Return.\\\"\\n\\t| char s i tabCount |\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\ts _ paragraph string.\\n\\ti _ self stopIndex.\\n\\ttabCount _ 0.\\n\\t[(i _ i-1) > 0 and: [(char _ s at: i) ~= Character cr]]\\n\\t\\twhileTrue: \\\"Count tabs and brackets (but not a leading bracket)\\\"\\n\\t\\t[(char = Character tab and: [i < s size and: [(s at: i+1) ~= $[ ]]) ifTrue: [tabCount _ tabCount + 1].\\n\\t\\tchar = $[ ifTrue: [tabCount _ tabCount + 1].\\n\\t\\tchar = $] ifTrue: [tabCount _ tabCount - 1]].\\n\\tcharacterStream crtab: tabCount. \\\"Now inject CR with tabCount tabs\\\"\\n\\t^ false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 4/30/2001 21:20'!\\ncursorTopHome: characterStream \\n\\t\\\"Put cursor at beginning of text -- invoked from cmd-H shortcut, useful for keyboards that have no home key.\\\"\\n\\t\\n\\tsensor keyboard.\\n\\tself selectAt: 1.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndisplayIfFalse: characterStream \\n\\t\\\"Replace the current text selection with the text 'ifFalse:'--initiated by \\n\\tctrl-f.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tcharacterStream nextPutAll: 'ifFalse:'.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndisplayIfTrue: characterStream \\n\\t\\\"Replace the current text selection with the text 'ifTrue:'--initiated by \\n\\tctrl-t.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tcharacterStream nextPutAll: 'ifTrue:'.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndoAgainMany: characterStream \\n\\t\\\"Do the previous thing again repeatedly. 1/26/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:) many: true.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndoAgainOnce: characterStream \\n\\t\\\"Do the previous thing again once. 1/26/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself again.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nfind: characterStream\\n\\t\\\"Prompt the user for what to find, then find it, searching from the current selection onward. 1/24/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself find.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nfindAgain: characterStream \\n\\t\\\"Find the desired text again. 1/24/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself findAgain.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/18/2002 11:39'!\\nforwardDelete: characterStream\\n\\t\\\"Delete forward over the next character.\\n\\t Make Undo work on the whole type-in, not just the one char.\\n\\twod 11/3/1998: If there was a selection use #zapSelectionWith: rather than #backspace: which was 'one off' in deleting the selection. Handling of things like undo or typeIn area were not fully considered.\\\"\\n\\t| startIndex usel upara uinterval ind stopIndex |\\n\\tstartIndex _ self mark.\\n\\tstartIndex > paragraph text size ifTrue:\\n\\t\\t[sensor keyboard.\\n\\t\\t^ false].\\n\\tself hasSelection ifTrue:\\n\\t\\t[\\\"there was a selection\\\"\\n\\t\\tsensor keyboard.\\n\\t\\tself zapSelectionWith: self nullText.\\n\\t\\t^ false].\\n\\t\\\"Null selection - do the delete forward\\\"\\n\\tbeginTypeInBlock == nil\\t\\\"no previous typing. openTypeIn\\\"\\n\\t\\tifTrue: [self openTypeIn. UndoSelection _ self nullText].\\n\\tuinterval _ UndoInterval deepCopy.\\n\\tupara _ UndoParagraph deepCopy.\\n\\tstopIndex := startIndex.\\n\\t(sensor keyboard asciiValue = 127 and: [sensor leftShiftDown])\\n\\t\\tifTrue: [stopIndex := (self nextWord: stopIndex) - 1].\\n\\tself selectFrom: startIndex to: stopIndex.\\n\\tself replaceSelectionWith: self nullText.\\n\\tself selectFrom: startIndex to: startIndex-1.\\n\\tUndoParagraph _ upara. UndoInterval _ uinterval.\\n\\tUndoMessage selector == #noUndoer ifTrue: [\\n\\t\\t(UndoSelection isText) ifTrue: [\\n\\t\\t\\tusel _ UndoSelection.\\n\\t\\t\\tind _ startIndex. \\\"UndoInterval startIndex\\\"\\n\\t\\t\\tusel replaceFrom: usel size + 1 to: usel size with:\\n\\t\\t\\t\\t(UndoParagraph text copyFrom: ind to: ind).\\n\\t\\t\\tUndoParagraph text replaceFrom: ind to: ind with:\\nself nullText]].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nnormalCharacter: characterStream \\n\\t\\\"A nonspecial character is to be added to the stream of characters.\\\"\\n\\n\\tcharacterStream nextPut: sensor keyboard.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:25'!\\nquerySymbol: characterStream\\n\\t\\\"Invoked by Ctrl-q to query the Symbol table and display alternate symbols.\\n\\t See comment in completeSymbol:lastOffering: for details.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\t\\\"keep typeahead\\\"\\n\\tself hasCaret\\n\\t\\tifTrue: \\\"Ctrl-q typed when a caret\\\"\\n\\t\\t\\t[self perform: #completeSymbol:lastOffering: withArguments:\\n\\t\\t\\t\\t((UndoParagraph == paragraph and: [UndoMessage sends: #undoQuery:lastOffering:])\\n\\t\\t\\t\\t\\tifTrue: [UndoMessage arguments] \\\"repeated Ctrl-q\\\"\\n\\t\\t\\t\\t\\tifFalse: [Array with: nil with: nil])] \\\"initial Ctrl-q\\\"\\n\\t\\tifFalse: \\\"Ctrl-q typed when statements were highlighted\\\"\\n\\t\\t\\t[view flash].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nsearch: characterStream\\n\\t\\\"Invoked by Ctrl-S. Same as 'again', but always uses the existing FindText\\n\\t and ChangeText regardless of the last edit.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself againOrSame: true. \\\"true means use same keys\\\"\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 8/29/2000 14:58'!\\nselectAll\\n\\t\\\"Make the selection be all the characters of the receiver\\\"\\n\\n\\tself selectFrom: 1 to: paragraph text string size! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nselectAll: characterStream \\n\\t\\\"select everything, invoked by cmd-a. 1/17/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself selectFrom: 1 to: paragraph text string size.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 17:34'!\\nsimulatedBackspace\\n\\t\\\"Backspace over the last character, derived from hand-char recognition. 2/5/96 sw\\\"\\n\\n\\t| startIndex |\\n\\tstartIndex _ self markIndex + (self hasSelection ifTrue: [1] ifFalse: [0]).\\n\\n\\tstartIndex _ 1 max: startIndex - 1.\\n\\tself backTo: startIndex.\\n\\t^ false! !\\n\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisDoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^(self isUndoing | self isRedoing) not! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisRedoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^UndoParagraph == #redoing! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisUndoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^UndoParagraph == #undoing! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nnoUndoer\\n\\t\\\"The Undoer to use when the command can not be undone. Checked for\\n\\t specially by readKeyboard.\\\"\\n\\n\\tUndoMessage _ Message selector: #noUndoer! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoMessage: aMessage forRedo: aBoolean\\n\\t\\\"Call this from an undoer/redoer to set up UndoMessage as the\\n\\t corresponding redoer/undoer. Also set up UndoParagraph, as well\\n\\t as the state variable Undone. It is assumed that UndoInterval has been\\n\\t established (generally by zapSelectionWith:) and that UndoSelection has been\\n\\t saved (generally by replaceSelectionWith: or replace:With:and:).\\\"\\n\\n\\tself isDoing ifTrue: [UndoParagraph _ paragraph].\\n\\tUndoMessage _ aMessage.\\n\\tUndone _ aBoolean! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has no arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has one argument, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector argument: arg1) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1 with: arg2\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has two arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2)) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1 with: arg2 with: arg3\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has three arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2 with: arg3)) forRedo: false! !\\n\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoAgain: indices andReselect: home typedKey: wasTypedKey\\n\\t\\\"The last command was again. Undo it. Redoer: itself.\\\"\\n\\n\\t| findSize substText index subject |\\n\\t(self isRedoing & wasTypedKey) ifTrue: \\\"redelete search key\\\"\\n\\t\\t[self selectInterval: home.\\n\\t\\tself zapSelectionWith: self nullText].\\n\\n\\tfindSize _ (self isRedoing ifTrue: [FindText] ifFalse: [ChangeText]) size.\\n\\tsubstText _ self isUndoing ifTrue: [FindText] ifFalse: [ChangeText].\\n\\t(self isUndoing ifTrue: [indices size to: 1 by: -1] ifFalse: [1 to: indices size]) do:\\n\\t\\t[:i |\\n\\t\\tindex _ indices at: i.\\n\\t\\t(subject _ index to: index + findSize - 1) = self selectionInterval ifFalse:\\n\\t\\t\\t[self selectInterval: subject].\\n\\t\\tFindText == ChangeText ifFalse: [self zapSelectionWith: substText]].\\n\\n\\tself isUndoing\\n\\t\\tifTrue: \\\"restore selection to where it was when 'again' was invoked\\\"\\n\\t\\t\\t[wasTypedKey\\n\\t\\t\\t\\tifTrue: \\\"search started by typing key at a caret; restore it\\\"\\n\\t\\t\\t\\t\\t[self selectAt: home first.\\n\\t\\t\\t\\t\\tself zapSelectionWith: FindText.\\n\\t\\t\\t\\t\\tself selectAt: home last + 1]\\n\\t\\t\\t\\tifFalse: [self selectInterval: home]].\\n\\n\\tself undoMessage: UndoMessage forRedo: self isUndoing! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoAndReselect: undoHighlight redoAndReselect: redoHighlight\\n\\t\\\"Undo typing, cancel, paste, and other operations that are like replaces\\n\\t but the selection is not the whole restored text after undo, redo, or both.\\n\\t undoHighlight is selected after this phase and redoHighlight after the next phase.\\n\\tRedoer: itself.\\\"\\n\\n\\tself replace: self selectionInterval with: UndoSelection and:\\n\\t\\t[self selectInterval: undoHighlight].\\n\\tself undoMessage: (UndoMessage argument: redoHighlight) forRedo: self isUndoing\\n! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoCutCopy: oldPasteBuffer\\n\\t\\\"Undo of a cut, copy, or any edit that changed CurrentSelection. Be sure\\n\\t undo-copy does not lock the model. Redoer: itself, so never isRedoing.\\\"\\n\\n\\t| recentCut |\\n\\trecentCut _ self clipboardText.\\t\\n\\tUndoSelection size = UndoInterval size\\n\\t\\tifFalse: [self replaceSelectionWith: UndoSelection].\\n\\tself clipboardTextPut: oldPasteBuffer.\\n\\tself undoer: #undoCutCopy: with: recentCut! !\\n\\n!ParagraphEditor methodsFor: 'undoers' stamp: 'th 9/19/2002 18:46'!\\nundoQuery: hintText lastOffering: selectorOrNil\\n\\t\\\"Undo ctrl-q. selectorOrNil (if not nil) is the previously offered selector.\\n\\t hintText is the original hint. Redoer: completeSymbol.\\\"\\n\\n\\tself zapSelectionWith: UndoSelection.\\n\\tself undoMessage: (Message selector: #completeSymbol:lastOffering: arguments: UndoMessage arguments) forRedo: true.\\n\\tself selectAt: self stopIndex! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoReplace\\n\\t\\\"Undo of any command that replaced a selection by other text that it left\\n\\t highlighted, and that is undone and redone by simple reversal of the\\n\\t operation. This is the most common Undoer; call replaceSelectionWith:\\n\\t to get this setup. Redoer: itself, so never isRedoing.\\\"\\n\\n\\tself replaceSelectionWith: UndoSelection! !\\n\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseChangeSetsWithSelector\\n\\t\\\"Determine which, if any, change sets have at least one change for the selected selector, independent of class\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector := self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [ChangeSorter browseChangeSetsWithSelector: aSelector]! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseItHere\\n\\t\\\"Retarget the receiver's window to look at the selected class, if appropriate. 3/1/96 sw\\\"\\n\\t| aSymbol foundClass b |\\n\\t(((b := model) isKindOf: Browser) and: [b couldBrowseAnyClass])\\n\\t\\tifFalse: [^ view flash].\\n\\tmodel okToChange ifFalse: [^ view flash].\\n\\tself selectionInterval isEmpty ifTrue: [self selectWord].\\n\\t(aSymbol := self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround:\\n\\t\\t[foundClass := (Smalltalk at: aSymbol ifAbsent: [nil]).\\n\\t\\t\\tfoundClass isNil ifTrue: [^ view flash].\\n\\t\\t\\t(foundClass isKindOf: Class)\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[model systemCategoryListIndex: \\n\\t\\t\\t\\t\\t\\t(model systemCategoryList indexOf: foundClass category).\\n\\t\\tmodel classListIndex: (model classList indexOf: foundClass name)]]! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ndebugIt\\n\\n\\t| method receiver context |\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: \\n\\t\\t\\t[FakeClassPool adopt: model selectedClass.\\n\\t\\t\\treceiver := model doItReceiver.\\n\\t\\t\\tcontext := model doItContext]\\n\\t\\tifFalse:\\n\\t\\t\\t[receiver := context := nil].\\n\\tself lineSelectAndEmptyCheck: [^self].\\n\\tmethod := self compileSelectionFor: receiver in: context.\\n\\tmethod notNil ifTrue:\\n\\t\\t[self debug: method receiver: receiver in: context].\\n\\tFakeClassPool adopt: nil! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ndebug: aCompiledMethod receiver: anObject in: evalContext\\n\\n\\t| selector guineaPig debugger context |\\n\\tselector := evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:].\\n\\tanObject class addSelectorSilently: selector withMethod: aCompiledMethod.\\n\\tguineaPig := evalContext isNil\\n\\t\\tifTrue: [[anObject DoIt] newProcess]\\n\\t\\tifFalse: [[anObject DoItIn: evalContext] newProcess].\\n\\tcontext := guineaPig suspendedContext.\\n\\tdebugger := Debugger new\\n\\t\\tprocess: guineaPig\\n\\t\\tcontroller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess])\\n\\t\\t\\t\\tifTrue: [ScheduledControllers activeController]\\n\\t\\t\\t\\tifFalse: [nil])\\n\\t\\tcontext: context\\n\\t\\tisolationHead: nil.\\n\\tdebugger openFullNoSuspendLabel: 'Debug it'.\\n\\t[debugger interruptedContext method == aCompiledMethod]\\n\\t\\twhileFalse: [debugger send].\\n\\tanObject class basicRemoveSelector: selector! !\\n\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:48'!\\nagainOnce: indices\\n\\t\\\"Find the next occurrence of FindText. If none, answer false.\\n\\tAppend the start index of the occurrence to the stream indices, and, if\\n\\tChangeText is not the same object as FindText, replace the occurrence by it.\\n\\tNote that the search is case-sensitive for replacements, otherwise not.\\\"\\n\\n\\t| where |\\n\\twhere _ paragraph text findString: FindText startingAt: self stopIndex\\n\\t\\t\\t\\tcaseSensitive: ((ChangeText ~~ FindText) or: [Preferences caseSensitiveFinds]).\\n\\twhere = 0 ifTrue: [^ false].\\n\\tself deselect; selectInvisiblyFrom: where to: where + FindText size - 1.\\n\\tChangeText ~~ FindText ifTrue: [self zapSelectionWith: ChangeText].\\n\\tindices nextPut: where.\\n\\tself selectAndScroll.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nagainOrSame: useOldKeys\\n\\t\\\"Subroutine of search: and again. If useOldKeys, use same FindText and ChangeText as before.\\n\\t 1/26/96 sw: real worked moved to againOrSame:many:\\\"\\n\\n\\t^ self againOrSame: useOldKeys many: sensor leftShiftDown! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:53'!\\nagainOrSame: useOldKeys many: many\\n\\t\\\"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.\\\"\\n\\n\\t| home indices wasTypedKey |\\n\\n\\thome _ self selectionInterval. \\\"what was selected when 'again' was invoked\\\"\\n\\n\\t\\\"If new keys are to be picked...\\\"\\n\\tuseOldKeys ifFalse: \\\"Choose as FindText...\\\"\\n\\t\\t[FindText _ UndoSelection. \\\"... the last thing replaced.\\\"\\n\\t\\t\\\"If the last command was in another paragraph, ChangeText is set...\\\"\\n\\t\\tparagraph == UndoParagraph ifTrue: \\\"... else set it now as follows.\\\"\\n\\t\\t\\t[UndoInterval ~= home ifTrue: [self selectInterval: UndoInterval]. \\\"blink\\\"\\n\\t\\t\\tChangeText _ ((UndoMessage sends: #undoCutCopy:) and: [self hasSelection])\\n\\t\\t\\t\\tifTrue: [FindText] \\\"== objects signal no model-locking by 'undo copy'\\\"\\n\\t\\t\\t\\tifFalse: [self selection]]]. \\\"otherwise, change text is last-replaced text\\\"\\n\\n\\t(wasTypedKey _ FindText size = 0)\\n\\t\\tifTrue: \\\"just inserted at a caret\\\"\\n\\t\\t\\t[home _ self selectionInterval.\\n\\t\\t\\tself replaceSelectionWith: self nullText. \\\"delete search key...\\\"\\n\\t\\t\\tFindText _ ChangeText] \\\"... and search for it, without replacing\\\"\\n\\t\\tifFalse: \\\"Show where the search will start\\\"\\n\\t\\t\\t[home last = self selectionInterval last ifFalse:\\n\\t\\t\\t\\t[self selectInterval: home]].\\n\\n\\t\\\"Find and Change, recording start indices in the array\\\"\\n\\tindices _ WriteStream on: (Array new: 20). \\\"an array to store change locs\\\"\\n\\t[(self againOnce: indices) & many] whileTrue. \\\"<-- this does the work\\\"\\n\\tindices isEmpty ifTrue: \\\"none found\\\"\\n\\t\\t[self flash.\\n\\t\\twasTypedKey ifFalse: [^self]].\\n\\n\\t(many | wasTypedKey) ifFalse: \\\"after undo, select this replacement\\\"\\n\\t\\t[home _ self startIndex to:\\n\\t\\t\\tself startIndex + UndoSelection size - 1].\\n\\n\\tself undoer: #undoAgain:andReselect:typedKey: with: indices contents with: home with: wasTypedKey! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:16'!\\ncompleteSymbol: hintText lastOffering: selectorOrNil\\n\\t\\\"Invoked by Ctrl-q when there is only a caret.\\n\\t\\tDo selector-completion, i.e., try to replace the preceding identifier by a\\n\\t\\tselector that begins with those characters & has as many keywords as possible.\\n\\t \\tLeave two spaces after each colon (only one after the last) as space for\\n\\t\\targuments. Put the caret after the space after the first keyword. If the\\n\\t\\tuser types Ctrl-q again immediately, choose a different selector.\\n\\t Undoer: #undoQuery:lastOffering:; Redoer: itself.\\n\\tIf redoing, just redisplay the last offering, selector[OrNil].\\\"\\n\\n\\t| firstTime input prior caret newStart sym kwds outStream |\\n\\tfirstTime _ self isRedoing\\n\\t\\tifTrue: [prior _ sym _ selectorOrNil. true]\\n\\t\\tifFalse: [hintText isNil].\\n\\tfirstTime\\n\\t\\tifTrue: \\\"Initial Ctrl-q (or redo)\\\"\\t\\t\\t\\t\\t\\n\\t\\t\\t[caret _ self startIndex.\\n\\t\\t\\tself selectPrecedingIdentifier.\\n\\t\\t\\tinput _ self selection]\\n\\t\\tifFalse: \\\"Repeated Ctrl-q\\\"\\n\\t\\t\\t[caret _ UndoInterval first + hintText size.\\n\\t\\t\\tself selectInvisiblyFrom: UndoInterval first to: UndoInterval last.\\n\\t\\t\\tinput _ hintText.\\n\\t\\t\\tprior _ selectorOrNil].\\n\\t(input size ~= 0 and: [sym ~~ nil or:\\n\\t\\t\\t[(sym _ Symbol thatStarts: input string skipping: prior) ~~ nil]])\\n\\t\\tifTrue: \\\"found something to offer\\\"\\n\\t\\t\\t[newStart _ self startIndex.\\n\\t\\t\\toutStream _ WriteStream on: (String new: 2 * sym size).\\n\\t\\t\\t1 to: (kwds _ sym keywords) size do:\\n\\t\\t\\t\\t[:i |\\n\\t\\t\\t\\toutStream nextPutAll: (kwds at: i).\\n\\t\\t\\t\\ti = 1 ifTrue: [caret _ newStart + outStream contents size + 1].\\n\\t\\t\\t\\toutStream nextPutAll:\\n\\t\\t\\t\\t\\t(i < kwds size ifTrue: [' '] ifFalse: [' '])].\\n\\t\\t\\tUndoSelection _ input.\\n\\t\\t\\tself deselect; zapSelectionWith: outStream contents asText.\\n\\t\\t\\tself undoer: #undoQuery:lastOffering: with: input with: sym]\\n\\t\\tifFalse: \\\"no more matches\\\"\\n\\t\\t\\t[firstTime ifFalse: \\\"restore original text & set up for a redo\\\"\\n\\t\\t\\t\\t[UndoSelection _ self selection.\\n\\t\\t\\t\\tself deselect; zapSelectionWith: input.\\n\\t\\t\\t\\tself undoer: #completeSymbol:lastOffering: with: input with: prior.\\n\\t\\t\\t\\tUndone _ true].\\n\\t\\t\\tview flash].\\n\\tself selectAt: caret! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:49'!\\nexchangeWith: prior\\n\\t\\\"If the prior selection is non-overlapping and legal, exchange the text of\\n\\t it with the current selection and leave the currently selected text selected\\n\\t in the location of the prior selection (or leave a caret after a non-caret if it was\\n\\t exchanged with a caret). If both selections are carets, flash & do nothing.\\n\\t Don't affect the paste buffer. Undoer: itself; Redoer: Undoer.\\\"\\n\\n\\t| start stop before selection priorSelection delta altInterval |\\n\\tstart _ self startIndex.\\n\\tstop _ self stopIndex - 1.\\n\\t((prior first <= prior last) | (start <= stop) \\\"Something to exchange\\\" and:\\n\\t\\t\\t[self isDisjointFrom: prior])\\n\\t\\tifTrue:\\n\\t\\t\\t[before _ prior last < start.\\n\\t\\t\\tselection _ self selection.\\n\\t\\t\\tpriorSelection _ paragraph text copyFrom: prior first to: prior last.\\n\\n\\t\\t\\tdelta _ before ifTrue: [0] ifFalse: [priorSelection size - selection size].\\n\\t\\t\\tself zapSelectionWith: priorSelection.\\n\\t\\t\\tself selectFrom: prior first + delta to: prior last + delta.\\n\\n\\t\\t\\tdelta _ before ifTrue: [stop - prior last] ifFalse: [start - prior first].\\n\\t\\t\\tself zapSelectionWith: selection.\\n\\t\\t\\taltInterval _ prior first + delta to: prior last + delta.\\n\\t\\t\\tself undoer: #exchangeWith: with: altInterval.\\n\\t\\t\\t\\\"If one was a caret, make it otherInterval & leave the caret after the other\\\"\\n\\t\\t\\tprior first > prior last ifTrue: [self selectAt: UndoInterval last + 1].\\n\\t\\t\\totherInterval _ start > stop\\n\\t\\t\\t\\tifTrue: [self selectAt: altInterval last + 1. UndoInterval]\\n\\t\\t\\t\\tifFalse: [altInterval]]\\n\\t\\tifFalse:\\n\\t\\t\\t[view flash]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'raok 11/15/2001 14:01'!\\nexplainDelimitor: string\\n\\t\\\"Is string enclosed in delimitors?\\\"\\n\\n\\t| str |\\n\\t(string at: 1) isLetter ifTrue: [^nil]. \\\"only special chars\\\"\\n\\t(string first = string last) ifTrue:\\n\\t\\t\\t[^ self explainChar: (String with: string first)]\\n\\t\\tifFalse:\\n\\t\\t\\t[(string first = $( and: [string last = $)]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $[ and: [string last = $]]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = ${ and: [string last = $}]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $< and: [string last = $>]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $# and: [string last = $)]) ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Array. The Numbers, Characters, or Symbols between the parenthesis are the elements of the Array.\\\"'].\\n\\t\\t\\tstring first = $# ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Symbol.\\\"'].\\n\\t\\t\\t(string first = $$ and: [string size = 2]) ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Character. This one is the character ', (String with: string last), '.\\\"'].\\n\\t\\t\\t(string first = $:) ifTrue:\\n\\t\\t\\t\\t[str _ string allButFirst.\\n\\t\\t\\t\\t(self explainTemp: str) ~~ nil ifTrue:\\n\\t\\t\\t\\t\\t[^'\\\"An argument to this block will be bound to the temporary variable ',\\n\\t\\t\\t\\t\\t\\tstr, '.\\\"']]].\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'tk 7/14/2000 12:15'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t| customMenu |\\n\\t^ ((view ~~ nil) and: [(customMenu _ view getMenu: shiftKeyState) notNil])\\n\\t\\tifTrue: [customMenu]\\n\\t\\tifFalse:\\n\\t\\t\\t[shiftKeyState\\n\\t\\t\\t\\tifTrue: [self class shiftedYellowButtonMenu]\\n\\t\\t\\t\\tifFalse: [self class yellowButtonMenu]]! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nindent: delta fromStream: inStream toStream: outStream\\n\\t\\\"Append the contents of inStream to outStream, adding or deleting delta or -delta\\n\\t tabs at the beginning, and after every CR except a final CR. Do not add tabs\\n\\t to totally empty lines, and be sure nothing but tabs are removed from lines.\\\"\\n\\n\\t| ch skip cr tab prev atEnd |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\tdelta > 0\\n\\t\\tifTrue: \\\"shift right\\\"\\n\\t\\t\\t[prev _ cr.\\n\\t\\t\\t [ch _ (atEnd _ inStream atEnd) ifTrue: [cr] ifFalse: [inStream next].\\n\\t\\t\\t (prev == cr and: [ch ~~ cr]) ifTrue:\\n\\t\\t\\t\\t[delta timesRepeat: [outStream nextPut: tab]].\\n\\t\\t\\t atEnd]\\n\\t\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t\\t[outStream nextPut: ch.\\n\\t\\t\\t\\t\\tprev _ ch]]\\n\\t\\tifFalse: \\\"shift left\\\"\\n\\t\\t\\t[skip _ delta. \\\"a negative number\\\"\\n\\t\\t\\t [inStream atEnd] whileFalse:\\n\\t\\t\\t\\t[((ch _ inStream next) == tab and: [skip < 0]) ifFalse:\\n\\t\\t\\t\\t\\t[outStream nextPut: ch].\\n\\t\\t\\t\\tskip _ ch == cr ifTrue: [delta] ifFalse: [skip + 1]]]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'cmm 4/9/2004 14:00'!\\nisDisjointFrom: anInterval\\n\\t\\\"Answer true if anInterval is a caret not touching or within the current\\n\\t interval, or if anInterval is a non-caret that does not overlap the current\\n\\t selection.\\\"\\n\\n\\t| fudge |\\n\\tfudge _ anInterval size = 0 ifTrue: [1] ifFalse: [0].\\n\\t^(anInterval last + fudge < self startIndex or:\\n\\t\\t\\t[anInterval first - fudge >= self stopIndex])\\n! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 11/24/2002 17:13'!\\nlines\\n\\t\\\"Other than my member paragraph i compute lines based on logical\\n\\tline breaks, not optical (which may change due to line wrapping of the editor)\\\"\\n\\t| lines string index lineIndex stringSize |\\n\\tstring _ paragraph text string.\\n\\t\\\"Empty strings have no lines at all. Think of something.\\\"\\n\\tstring isEmpty ifTrue:[^{#(1 0 0)}].\\n\\tstringSize _ string size.\\n\\tlines _ OrderedCollection new: (string size // 15).\\n\\tindex _ 0.\\n\\tlineIndex _ 0.\\n\\tstring linesDo:[:line |\\n\\t\\tlines addLast: (Array\\n\\t\\t\\twith: (index _ index + 1)\\n\\t\\t\\twith: (lineIndex _ lineIndex + 1)\\n\\t\\t\\twith: (index _ index + line size min: stringSize))].\\n\\t\\\"Special workaround for last line empty.\\\"\\n\\tstring last == Character cr\\n\\t\\\"lines last last < stringSize\\\" ifTrue:[lines addLast:{stringSize +1. lineIndex+1. stringSize}].\\n\\t^lines! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 19:57'!\\nmoveCursor: directionBlock forward: forward specialBlock: specialBlock\\n\\t\\\"Private - Move cursor.\\n\\tdirectionBlock is a one argument Block that computes the new Position from a given one.\\n\\tspecialBlock is a one argumentBlock that computes the new position from a given one under the alternate semantics.\\n\\tNote that directionBlock always is evaluated first.\\\"\\n\\t| shift indices newPosition |\\n\\tshift _ sensor leftShiftDown.\\n\\tindices _ self setIndices: shift forward: forward.\\n\\tnewPosition _ directionBlock value: (indices at: #moving).\\n\\t(sensor commandKeyPressed or:[sensor controlKeyPressed])\\n\\t\\tifTrue: [newPosition _ specialBlock value: newPosition].\\n\\tsensor keyboard.\\n\\tshift\\n\\t\\tifTrue: [self selectMark: (indices at: #fixed) point: newPosition - 1]\\n\\t\\tifFalse: [self selectAt: newPosition]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:32'!\\nnextWord: position\\n\\t| string index |\\n\\tstring _ paragraph text string.\\n\\tindex _ position.\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]]\\n\\t\\twhileTrue: [index _ index + 1].\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]]\\n\\t\\twhileTrue: [index _ index + 1].\\n\\t^ index! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nnullText\\n\\n\\t^Text string: '' emphasis: emphasisHere! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/20/2002 11:09'!\\npageHeight\\n\\t| howManyLines visibleHeight totalHeight ratio |\\n\\thowManyLines _ paragraph numberOfLines.\\n\\tvisibleHeight _ self visibleHeight.\\n\\ttotalHeight _ self totalTextHeight.\\n\\tratio _ visibleHeight / totalHeight.\\n\\t^(ratio * howManyLines) rounded - 2! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:33'!\\npreviousWord: position\\n\\t| string index |\\n\\tstring _ paragraph text string.\\n\\tindex _ position.\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]]\\n\\t\\twhileTrue: [index _ index - 1].\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]]\\n\\t\\twhileTrue: [index _ index - 1].\\n\\t^ index + 1! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'BG 4/29/2004 11:19'!\\nsameColumn: start newLine: lineBlock forward: isForward\\n\\t\\\"Private - Compute the index in my text\\n\\twith the line number derived from lineBlock,\\\"\\n\\t\\\" a one argument block accepting the old line number.\\n\\tThe position inside the line will be preserved as good as possible\\\"\\n\\t\\\"The boolean isForward is used in the border case to determine if\\n\\twe should move to the beginning or the end of the line.\\\"\\n\\t| wordStyle column currentLine offsetAtTargetLine targetEOL lines numberOfLines currentLineNumber targetLineNumber |\\n\\twordStyle _ Preferences wordStyleCursorMovement.\\n\\twordStyle\\n\\t\\tifTrue: [\\n\\t\\t\\tlines _ paragraph lines.\\n\\t\\t\\tnumberOfLines := paragraph numberOfLines.\\n\\t\\t\\tcurrentLineNumber _ paragraph lineIndexOfCharacterIndex: start.\\n\\t\\t\\tcurrentLine _ lines at: currentLineNumber]\\n\\t\\tifFalse: [\\n\\t\\t\\tlines _ self lines.\\n\\t\\t\\tnumberOfLines := lines size.\\n\\t\\t\\tcurrentLine _ lines\\n\\t\\t\\t\\tdetect:[:lineInterval | lineInterval last >= start]\\n\\t\\t\\t\\tifNone:[lines last].\\n\\t\\t\\tcurrentLineNumber _ currentLine second].\\n\\tcolumn _ start - currentLine first.\\n\\ttargetLineNumber _ ((lineBlock value: currentLineNumber) max: 1) min: numberOfLines.\\n\\toffsetAtTargetLine _ (lines at: targetLineNumber) first.\\n\\ttargetEOL _ (lines at: targetLineNumber) last + (targetLineNumber == numberOfLines ifTrue:[1]ifFalse:[0]).\\n\\ttargetLineNumber == currentLineNumber\\n\\t\\\"No movement or movement failed. Move to beginning or end of line.\\\"\\n\\t\\tifTrue:[^isForward\\n\\t\\t\\tifTrue:[targetEOL]\\n\\t\\t\\tifFalse:[offsetAtTargetLine]].\\n\\t^offsetAtTargetLine + column min: targetEOL.! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'md 2/22/2006 21:17'!\\nsetIndices: shiftPressed forward: forward\\n\\t\\\"Little helper method that sets the moving and fixed indices according to some flags.\\\"\\n\\t| indices |\\n\\tindices _ Dictionary new.\\n\\tshiftPressed ifTrue: [\\n\\t\\t\\tindices at: #moving put: self pointIndex.\\n\\t\\t\\tindices at: #fixed put: self markIndex\\n\\t\\t] ifFalse: [\\n\\t\\t\\tforward\\n\\t\\t\\t\\tifTrue:[\\n\\t\\t\\t\\t\\tindices at: #moving put: self stopIndex.\\n\\t\\t\\t\\t\\tindices at: #fixed put: self startIndex.\\n\\t\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t\\tindices at: #moving put: self startIndex.\\n\\t\\t\\t\\t\\tindices at: #fixed put: self stopIndex.\\n\\t\\t\\t\\t]\\n\\t\\t].\\n\\t^indices! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParagraphEditor class\\n\\tinstanceVariableNames: ''!\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'sw 5/27/2000 00:03'!\\nabandonChangeText\\n\\t\\\"Call this to get out of the maddening situation in which the system keeps aggressively trying to do a replacement that you no longer wish to make, every time you make choose a new method in a list.\\\"\\n\\tChangeText _ FindText\\n\\n\\t\\\"ParagraphEditor abandonChangeText\\\"\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 10/1/2004 11:00'!\\ninitialize\\n\\t\\\"Initialize the keyboard shortcut maps and the shared buffers \\n\\tfor copying text across views and managing again and undo. \\n\\tMarked this method changed to trigger reinit\\\"\\n\\t\\\"ParagraphEditor initialize\\\"\\n\\tUndoSelection := FindText := ChangeText := Text new.\\n\\tUndoMessage := Message selector: #halt.\\n\\tself initializeCmdKeyShortcuts.\\n\\tself initializeShiftCmdKeyShortcuts.! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 4/4/2006 16:07'!\\nshiftedYellowButtonMenu\\n\\t\\\"Answer the menu to be presented when the yellow button is pressed while the shift key is down\\\"\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t{'explain' translated.\\t\\t\\t\\t\\t\\t#explain}.\\n\\t\\t{'pretty print' translated.\\t\\t\\t\\t\\t#prettyPrint}.\\n\\t\\t{'pretty print with color' translated.\\t\\t#prettyPrintWithColor}.\\n\\t\\t{'file it in (G)' translated.\\t\\t\\t\\t\\t#fileItIn}.\\n\\t\\t{'tiles from it' translated.\\t\\t\\t\\t\\t#selectionAsTiles}.\\n\\t\\t{'spawn (o)' translated.\\t\\t\\t\\t\\t\\t#spawn}.\\n\\t\\t#-.\\n\\t\\t{'browse it (b)' translated.\\t\\t\\t\\t\\t#browseIt}.\\n\\t\\t{'senders of it (n)' translated.\\t\\t\\t\\t#sendersOfIt}.\\n\\t\\t{'implementors of it (m)' translated.\\t\\t#implementorsOfIt}.\\n\\t\\t{'references to it (N)' translated.\\t\\t\\t#referencesToIt}.\\n\\t\\t#-.\\n\\t\\t{'selectors containing it (W)' translated.\\t#methodNamesContainingIt}.\\n\\t\\t{'method strings with it (E)' translated.\\t#methodStringsContainingit}.\\n\\t\\t{'method source with it' translated.\\t\\t#methodSourceContainingIt}.\\n\\t\\t{'class names containing it' translated.\\t#classNamesContainingIt}.\\n\\t\\t{'class comments with it' translated.\\t\\t#classCommentsContainingIt}.\\n\\t\\t{'change sets with it' translated.\\t\\t\\t#browseChangeSetsWithSelector}.\\n\\t\\t#-.\\n\\t\\t{'save contents to file...' translated.\\t\\t#saveContentsInFile}.\\n\\t\\t{'send contents to printer' translated.\\t#sendContentsToPrinter}.\\n\\t\\t{'printer setup' translated.\\t\\t\\t\\t\\t#printerSetup}.\\n\\t\\t#-.\\n\\t\\t{'special menu...' translated.\\t\\t\\t\\t#presentSpecialMenu}.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t\\t#yellowButtonActivity}.\\n\\t}\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 9/1/2005 12:35'!\\nyellowButtonExpertMenu\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t\\t{'set font... (k)' translated.\\t\\t\\t\\t#offerFontMenu}.\\n\\t\\t\\t{'set style... (K)' translated.\\t\\t\\t\\t#changeStyle}.\\n\\t\\t\\t{'set alignment... (u)' translated.\\t\\t#chooseAlignment}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'make project link (P)' translated.\\t#makeProjectLink}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'find...(f)' translated.\\t\\t\\t\\t\\t#find}.\\n\\t\\t\\t{'find again (g)' translated.\\t\\t\\t\\t#findAgain}.\\n\\t\\t\\t{'set search string (h)' translated.\\t\\t#setSearchString}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do again (j)' translated.\\t\\t\\t\\t#again}.\\n\\t\\t\\t{'undo (z)' translated.\\t\\t\\t\\t\\t#undo}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy (c)' translated.\\t\\t\\t\\t\\t#copySelection}.\\n\\t\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t\\t#cut}.\\n\\t\\t\\t{'paste (v)' translated.\\t\\t\\t\\t\\t#paste}.\\n\\t\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do it (d)' translated.\\t\\t\\t\\t\\t#doIt}.\\n\\t\\t\\t{'print it (p)' translated.\\t\\t\\t\\t#printIt}.\\n\\t\\t\\t{'inspect it (i)' translated.\\t\\t\\t\\t#inspectIt}.\\n\\t\\t\\t{'explore it (I)' translated.\\t\\t\\t\\t#exploreIt}.\\n\\t\\t\\t{'debug it' translated.\\t\\t\\t\\t\\t#debugIt}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'accept (s)' translated.\\t\\t\\t\\t\\t#accept}.\\n\\t\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t\\t#cancel}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'show bytecodes' translated.\\t\\t\\t#showBytecodes}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy html' translated.\\t\\t\\t\\t\\t#copyHtml}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'more...' translated.\\t\\t\\t\\t\\t#shiftedTextPaneMenuRequest}.\\n\\t\\t}.\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 10/1/2004 10:59'!\\nyellowButtonMenu\\n\\n\\t^ Preferences noviceMode\\n\\t\\t\\tifTrue: [self yellowButtonNoviceMenu]\\n\\t\\t\\tifFalse: [self yellowButtonExpertMenu]\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 11/25/2004 17:33'!\\nyellowButtonNoviceMenu\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t\\t{'set font... (k)' translated.\\t\\t\\t\\t#offerFontMenu}.\\n\\t\\t\\t{'set style... (K)' translated.\\t\\t\\t\\t#changeStyle}.\\n\\t\\t\\t{'set alignment... (u)' translated.\\t\\t#chooseAlignment}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'make project link (P)' translated.\\t#makeProjectLink}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'find...(f)' translated.\\t\\t\\t\\t\\t#find}.\\n\\t\\t\\t{'find again (g)' translated.\\t\\t\\t\\t#findAgain}.\\n\\t\\t\\t{'set search string (h)' translated.\\t\\t#setSearchString}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do again (j)' translated.\\t\\t\\t\\t#again}.\\n\\t\\t\\t{'undo (z)' translated.\\t\\t\\t\\t\\t#undo}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy (c)' translated.\\t\\t\\t\\t\\t#copySelection}.\\n\\t\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t\\t#cut}.\\n\\t\\t\\t{'paste (v)' translated.\\t\\t\\t\\t\\t#paste}.\\n\\t\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'accept (s)' translated.\\t\\t\\t\\t\\t#accept}.\\n\\t\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t\\t#cancel}.\\n\\t\\t}.\\n! !\\n\\n\\n!ParagraphEditor class methodsFor: 'instance creation' stamp: 'nk 9/3/2004 14:10'!\\nnew\\n\\t\\\"Answer a new instance of me with a null Paragraph to be edited.\\\"\\n\\n\\t| aParagraphEditor |\\n\\taParagraphEditor _ super new.\\n\\taParagraphEditor changeParagraph: '' asParagraph.\\n\\t^aParagraphEditor! !\\n\\n!ParagraphEditor class methodsFor: 'instance creation'!\\nnewParagraph: aParagraph \\n\\t\\\"Answer an instance of me with aParagraph as the text to be edited.\\\"\\n\\n\\t| aParagraphEditor |\\n\\taParagraphEditor _ super new.\\n\\taParagraphEditor initialize.\\n\\taParagraphEditor changeParagraph: aParagraph.\\n\\t^aParagraphEditor! !\\n\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'dgd 4/4/2006 16:04'!\\ninitializeCmdKeyShortcuts\\n\\t\\\"Initialize the (unshifted) command-key (or alt-key) shortcut table.\\\"\\n\\n\\t\\\"NOTE: if you don't know what your keyboard generates, use Sensor kbdTest\\\"\\n\\n\\t\\\"ParagraphEditor initialize\\\"\\n\\n\\t| cmdMap |\\n\\n\\tcmdMap := Array new: 256 withAll: #noop:.\\t\\\"use temp in case of a crash\\\"\\n\\n\\tcmdMap at: 1 + 1 put: #cursorHome:.\\t\\t\\t\\\"home key\\\"\\n\\tcmdMap at: 4 + 1 put: #cursorEnd:.\\t\\t\\t\\t\\\"end key\\\"\\n\\tcmdMap at: 8 + 1 put: #backspace:.\\t\\t\\t\\t\\\"ctrl-H or delete key\\\"\\n\\tcmdMap at: 11 + 1 put: #cursorPageUp:.\\t\\t\\\"page up key\\\"\\n\\tcmdMap at: 12 + 1 put: #cursorPageDown:.\\t\\\"page down key\\\"\\n\\tcmdMap at: 13 + 1 put: #crWithIndent:.\\t\\t\\t\\\"cmd-Return\\\"\\n\\tcmdMap at: 27 + 1 put: #offerMenuFromEsc:.\\t\\\"escape key\\\"\\n\\tcmdMap at: 28 + 1 put: #cursorLeft:.\\t\\t\\t\\\"left arrow key\\\"\\n\\tcmdMap at: 29 + 1 put: #cursorRight:.\\t\\t\\t\\\"right arrow key\\\"\\n\\tcmdMap at: 30 + 1 put: #cursorUp:.\\t\\t\\t\\t\\\"up arrow key\\\"\\n\\tcmdMap at: 31 + 1 put: #cursorDown:.\\t\\t\\t\\\"down arrow key\\\"\\n\\tcmdMap at: 32 + 1 put: #selectWord:.\\t\\t\\t\\\"space bar key\\\"\\n\\tcmdMap at: 127 + 1 put: #forwardDelete:.\\t\\t\\\"del key\\\"\\n\\n\\t'0123456789-=' \\n\\t\\tdo: [:char | cmdMap at: char asciiValue + 1 put: #changeEmphasis:].\\n\\n\\t'([{''\\\"<' do: [:char | cmdMap at: char asciiValue + 1 put: #enclose:].\\n\\n\\tcmdMap at: $, asciiValue + 1 put: #shiftEnclose:.\\n\\n\\t\\\"triplet = {character. comment selector. novice appropiated}\\\"\\n\\t#(\\n\\t\\t($a\\t\\t#selectAll:\\t\\t\\t\\ttrue)\\n\\t\\t($b\\t\\t#browseIt:\\t\\t\\t\\tfalse)\\n\\t\\t($c\\t\\t#copySelection:\\t\\t\\ttrue)\\n\\t\\t($d\\t\\t#doIt:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($e\\t\\t#exchange:\\t\\t\\t\\ttrue)\\n\\t\\t($f\\t\\t#find:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($g\\t\\t#findAgain:\\t\\t\\t\\ttrue)\\n\\t\\t($h\\t\\t#setSearchString:\\t\\ttrue)\\n\\t\\t($i\\t\\t#inspectIt:\\t\\t\\t\\tfalse)\\n\\t\\t($j\\t\\t#doAgainOnce:\\t\\t\\ttrue)\\n\\t\\t($k\\t\\t#offerFontMenu:\\t\\ttrue)\\n\\t\\t($l\\t\\t#cancel:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($m\\t#implementorsOfIt:\\t\\tfalse)\\n\\t\\t($n\\t\\t#sendersOfIt:\\t\\t\\tfalse)\\n\\t\\t($o\\t\\t#spawnIt:\\t\\t\\t\\tfalse)\\n\\t\\t($p\\t\\t#printIt:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($q\\t\\t#querySymbol:\\t\\t\\tfalse)\\n\\t\\t($s\\t\\t#save:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($t\\t\\t#tempCommand:\\t\\tfalse)\\n\\t\\t($u\\t\\t#align:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($v\\t\\t#paste:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($w\\t#backWord:\\t\\t\\t\\ttrue)\\n\\t\\t($x\\t\\t#cut:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($y\\t\\t#swapChars:\\t\\t\\t\\ttrue)\\n\\t\\t($z\\t\\t#undo:\\t\\t\\t\\t\\ttrue)\\n\\t)\\n\\t\\tselect:[:triplet | Preferences noviceMode not or:[triplet third]]\\n\\t\\tthenDo:[:triplet | cmdMap at: triplet first asciiValue + 1 put: triplet second].\\n\\n\\tCmdActions := cmdMap.\\n! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'dgd 10/4/2004 13:53'!\\ninitializeShiftCmdKeyShortcuts \\n\\t\\\"Initialize the shift-command-key (or control-key) shortcut table.\\\"\\n\\t\\\"NOTE: if you don't know what your keyboard generates, use Sensor kbdTest\\\"\\n\\t\\\"wod 11/3/1998: Fix setting of cmdMap for shifted keys to actually use the \\n\\tcapitalized versions of the letters.\\n\\tTPR 2/18/99: add the plain ascii values back in for those VMs that don't return the shifted values.\\\"\\n\\n\\t| cmdMap |\\n\\n\\t\\\"shift-command and control shortcuts\\\"\\n\\tcmdMap _ Array new: 256 withAll: #noop:. \\\"use temp in case of a crash\\\"\\n\\n\\tcmdMap at: ( 1 + 1) put: #cursorHome:.\\t\\t\\t\\t\\\"home key\\\"\\n\\tcmdMap at: ( 4 + 1) put: #cursorEnd:.\\t\\t\\t\\t\\\"end key\\\"\\n\\tcmdMap at: ( 8 + 1) put: #forwardDelete:.\\t\\t\\t\\\"ctrl-H or delete key\\\"\\n\\tcmdMap at: (11 + 1) put: #cursorPageUp:.\\t\\t\\t\\\"page up key\\\"\\n\\tcmdMap at: (12 + 1) put: #cursorPageDown:.\\t\\t\\\"page down key\\\"\\n\\tcmdMap at: (13 + 1) put: #crWithIndent:.\\t\\t\\t\\\"ctrl-Return\\\"\\n\\tcmdMap at: (27 + 1) put: #offerMenuFromEsc:.\\t\\\"escape key\\\"\\n\\tcmdMap at: (28 + 1) put: #cursorLeft:.\\t\\t\\t\\t\\\"left arrow key\\\"\\n\\tcmdMap at: (29 + 1) put: #cursorRight:.\\t\\t\\t\\t\\\"right arrow key\\\"\\n\\tcmdMap at: (30 + 1) put: #cursorUp:.\\t\\t\\t\\t\\\"up arrow key\\\"\\n\\tcmdMap at: (31 + 1) put: #cursorDown:.\\t\\t\\t\\\"down arrow key\\\"\\n\\tcmdMap at: (32 + 1) put: #selectWord:.\\t\\t\\t\\t\\\"space bar key\\\"\\n\\tcmdMap at: (45 + 1) put: #changeEmphasis:.\\t\\t\\\"cmd-sh-minus\\\"\\n\\tcmdMap at: (61 + 1) put: #changeEmphasis:.\\t\\t\\\"cmd-sh-plus\\\"\\n\\tcmdMap at: (127 + 1) put: #forwardDelete:.\\t\\t\\\"del key\\\"\\n\\n\\t\\\"Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $(\\\"\\n\\t'9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ].\\t\\\"({< and double-quote\\\"\\n\\t\\\"Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command.\\\"\\n\\n\\t\\\"NB: sw 12/9/2001 commented out the idiosyncratic line just below, which was grabbing shift-esc in the text editor and hence which argued with the wish to have shift-esc be a universal gesture for escaping the local context and calling up the desktop menu.\\\" \\n\\t\\\"cmdMap at: (27 + 1) put: #shiftEnclose:.\\\" \\t\\\"ctrl-[\\\"\\n\\n\\t\\\"'\\\"\\\"''(' do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose:].\\\"\\n\\n\\t\\\"triplet = {character. comment selector. novice appropiated}\\\"\\n\\t#(\\n\\t\\t($a\\t\\targAdvance:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($b\\t\\tbrowseItHere:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($c\\t\\tcompareToClipboard:\\t\\t\\tfalse)\\n\\t\\t($d\\t\\tduplicate:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($e\\t\\tmethodStringsContainingIt:\\tfalse)\\n\\t\\t($f\\t\\tdisplayIfFalse:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($g\\t\\tfileItIn:\\t\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($h\\t\\tcursorTopHome:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($i\\t\\texploreIt:\\t\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($j\\t\\tdoAgainMany:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($k\\t\\tchangeStyle:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($l\\t\\toutdent:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($m\\tselectCurrentTypeIn:\\t\\t\\ttrue)\\n\\t\\t($n\\t\\treferencesToIt:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($p\\t\\tmakeProjectLink:\\t\\t\\t\\ttrue)\\n\\t\\t($r\\t\\tindent:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($s\\t\\tsearch:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($t\\t\\tdisplayIfTrue:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($u\\t\\tchangeLfToCr:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($v\\t\\tpasteInitials:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($w\\tmethodNamesContainingIt:\\tfalse)\\n\\t\\t($x\\t\\tmakeLowercase:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($y\\t\\tmakeUppercase:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($z\\t\\tmakeCapitalized:\\t\\t\\t\\ttrue)\\n\\t)\\n\\t\\tselect:[:triplet | Preferences noviceMode not or:[triplet third]]\\n\\t\\tthenDo:[:triplet |\\n\\t\\t\\tcmdMap at: (triplet first asciiValue + 1) put: triplet second.\\t\\t\\\"plain keys\\\"\\n\\t\\t\\tcmdMap at: (triplet first asciiValue - 32 + 1) put: triplet second.\\t\\t\\\"shifted keys\\\"\\n\\t\\t\\tcmdMap at: (triplet first asciiValue - 96 + 1) put: triplet second.\\t\\t\\\"ctrl keys\\\"\\n\\t\\t].\\n\\n\\tShiftCmdActions _ cmdMap! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sps 7/24/2003 17:25'!\\nmultiRedoOverride\\n\\\"Call this to set meta-r to perform the multilevel redo (or tweak the code below to have it bound to some other key sequence).\\\"\\n\\n\\\"\\nParagraphEditor multiRedoOverride.\\n\\\"\\n\\tCmdActions at: $r asciiValue + 1 put: #multiRedo: \\n! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sbw 10/8/1999 21:42'!\\nspecialShiftCmdKeys\\n\\n\\\"Private - return array of key codes that represent single keys acting\\nas if shift-command were also being pressed\\\"\\n\\n^#(\\n\\t1\\t\\\"home\\\"\\n\\t3\\t\\\"enter\\\"\\n\\t4\\t\\\"end\\\"\\n\\t8\\t\\\"backspace\\\"\\n\\t11\\t\\\"page up\\\"\\n\\t12\\t\\\"page down\\\"\\n\\t27\\t\\\"escape\\\"\\n\\t28\\t\\\"left arrow\\\"\\n\\t29\\t\\\"right arrow\\\"\\n\\t30\\t\\\"up arrow\\\"\\n\\t31\\t\\\"down arrow\\\"\\n\\t127\\t\\\"delete\\\"\\n\\t)! !\\nTileMorph subclass: #ParameterTile\\n\\tinstanceVariableNames: 'scriptEditor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!ParameterTile commentStamp: '<historical>' prior: 0!\\nRepresents a parameter in a user-defined script in \\\"classic\\\" tile-scripting. The type of a script's parameter is declared in the ScriptEditor for the script, and a parameter tile gets its type from the script. But because the user can change the parameter type *after* having created parameter tiles, we can later have type mismatches. Which however we at least deal with reasonably cleverly.!\\n\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 3/15/2005 21:45'!\\nisBoolean \\n\\t\\\"Answer whether the receiver's type is inherently boolean\\\"\\n\\n\\t^ self scriptEditor typeForParameter == #Boolean! !\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 3/15/2005 22:36'!\\nrowOfRightTypeFor: aLayoutMorph forActor: aPlayer\\n\\t\\\"Answer a phrase of the right type for the putative container\\\"\\n\\n\\t| aTemporaryViewer aPhrase |\\n\\taLayoutMorph demandsBoolean ifTrue:\\n\\t\\t[aTemporaryViewer _ CategoryViewer new invisiblySetPlayer: aPlayer.\\n\\t\\taPhrase _ aTemporaryViewer booleanPhraseFromPhrase: self.\\n\\t\\taPhrase justGrabbedFromViewer: false.\\n\\t\\t^ aPhrase].\\n\\t^ self! !\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 1/18/2004 22:12'!\\nscriptEditor\\n\\t\\\"Answer the receiver's script editor. The slightly strange code here is in order to contend with the unusual situation where a parameter tile obtained from one script editor is later dropped into a different script editor. As long as the parameter tile is *in* a script editor, that containing scriptEditor is the one; if it is *not*, then we use the last known one\\\"\\n\\n\\t| aScriptEditor |\\n\\t^ (aScriptEditor _ self outermostMorphThat: [:m | m isKindOf: ScriptEditorMorph])\\n\\t\\tifNotNil:\\n\\t\\t\\t[scriptEditor _ aScriptEditor]\\n\\t\\tifNil:\\n\\t\\t\\t[scriptEditor]! !\\n\\n\\n!ParameterTile methodsFor: 'accessing' stamp: 'sw 7/18/2002 02:45'!\\nresultType\\n\\t\\\"Answer the result type of the receiver\\\"\\n\\n\\t^ self scriptEditor typeForParameter! !\\n\\n\\n!ParameterTile methodsFor: 'code generation' stamp: 'yo 12/20/2003 02:49'!\\nstoreCodeOn: aStream indent: tabCount\\n\\t\\\"Store code on the stream\\\"\\n \\n\\t| myTypeString |\\n\\tmyTypeString _ self resultType.\\n\\t(self scriptEditor hasParameter and: [self scriptEditor typeForParameter = myTypeString])\\n\\t\\tifTrue:\\n\\t\\t\\t[aStream nextPutAll: 'parameter']\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"This script no longer bears a parameter, yet there's an orphaned Parameter tile in it\\\"\\n\\t\\t\\taStream nextPutAll: '(self defaultValueOfType: #', myTypeString, ')']! !\\n\\n\\n!ParameterTile methodsFor: 'initialization' stamp: 'yo 3/14/2005 08:01'!\\nforScriptEditor: aScriptEditor\\n\\t\\\"Make the receiver be associated with the given script editor\\\"\\n\\n\\tscriptEditor _ aScriptEditor.\\n\\tself line1: aScriptEditor typeForParameter translated.! !\\n\\n!ParameterTile methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:45'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself typeColor: Color red! !\\n\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 21:55'!\\nassociatedPlayer\\n\\t\\\"Answer the player with which the receiver is associated\\\"\\n\\n\\t^ self scriptEditor playerScripted! !\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 22:37'!\\nbooleanComparatorPhrase\\n\\t\\\"Answer a boolean-valued phrase derived from a retriever (e.g. 'car's heading'); this is in order to assure that tiles laid down in a TEST area will indeed produce a boolean result\\\"\\n\\n\\t| outerPhrase rel retrieverType |\\n\\tretrieverType _ self resultType.\\n\\n\\trel _ (Vocabulary vocabularyForType: retrieverType) comparatorForSampleBoolean.\\n\\touterPhrase _ PhraseTileMorph new setOperator: rel type: #Boolean rcvrType: retrieverType argType: retrieverType.\\n\\touterPhrase firstSubmorph addMorph: self.\\n\\touterPhrase submorphs last addMorph: (ScriptingSystem tileForArgType: retrieverType).\\n\\n\\touterPhrase submorphs second submorphs last setBalloonText: (ScriptingSystem helpStringForOperator: rel). \\n\\t^ outerPhrase! !\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 22:41'!\\ntileRows\\n\\t\\\"Answer a list of tile rows -- in this case exactly one row -- representing the receiver.\\\"\\n\\n\\t^ Array with: (Array with: self)! !\\n\\n\\n!ParameterTile methodsFor: 'type' stamp: 'sw 7/22/2002 17:48'!\\nassureTypeStillValid\\n\\t\\\"Consider the possibility that the parameter type of my surrounding method has changed and that hence I no longer represent a possible value for the parameter of the script. If this condition obtains, then banish me in favor of a default literal tile of the correct type\\\"\\n\\n\\t(self ownerThatIsA: TilePadMorph) ifNotNilDo:\\n\\t\\t[:aPad | aPad type = self scriptEditor typeForParameter ifFalse:\\n\\t\\t\\t[aPad setToBearDefaultLiteral]]! !\\nObject subclass: #ParseNode\\n\\tinstanceVariableNames: 'comment pc'\\n\\tclassVariableNames: 'Bfp BtpLong CodeBases CodeLimits DblExtDoAll Dup EndMethod EndRemote Jmp JmpLimit JmpLong LdFalse LdInstLong LdInstType LdLitIndType LdLitType LdMinus1 LdNil LdSelf LdSuper LdTempType LdThisContext LdTrue LoadLong LongLongDoAll NodeFalse NodeNil NodeSelf NodeSuper NodeThisContext NodeTrue Pop Send SendLimit SendLong SendLong2 SendPlus SendType ShortStoP StdLiterals StdSelectors StdVariables Store StorePop'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-ParseNodes'!\\n!ParseNode commentStamp: '<historical>' prior: 0!\\nThis 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.!\\n\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitBranchOn:\\ncondition dist: dist pop: stack on: strm\\n\\tstack pop: 1.\\n\\tdist = 0 ifTrue: [^ strm nextPut: Pop].\\n\\tcondition\\n\\t\\tifTrue: [self emitLong: dist code: BtpLong on: strm]\\n\\t\\tifFalse: [self emitShortOrLong: dist code: Bfp on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitForEffect: stack on: strm\\n\\n\\tself emitForValue: stack on: strm.\\n\\tstrm nextPut: Pop.\\n\\tstack pop: 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitForReturn: stack on: strm\\n\\n\\tself emitForValue: stack on: strm.\\n\\tstrm nextPut: EndMethod! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitJump: dist on: strm\\n\\n\\tdist = 0 ifFalse: [self emitShortOrLong: dist code: Jmp on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitLong: dist code: longCode on: aStream \\n\\t\\\"Force a two-byte jump.\\\"\\n\\t| code distance |\\n\\tcode _ longCode.\\n\\tdistance _ dist.\\n\\tdistance < 0\\n\\t\\tifTrue: \\n\\t\\t\\t[distance _ distance + 1024.\\n\\t\\t\\tcode _ code - 4]\\n\\t\\tifFalse: \\n\\t\\t\\t[distance > 1023 ifTrue: [distance _ -1]].\\n\\tdistance < 0\\n\\t\\tifTrue: \\n\\t\\t\\t[self error: 'A block compiles more than 1K bytes of code']\\n\\t\\tifFalse: \\n\\t\\t\\t[aStream nextPut: distance // 256 + code.\\n\\t\\t\\taStream nextPut: distance \\\\\\\\ 256]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitShortOrLong: dist code: shortCode on: strm\\n\\t(1 <= dist and: [dist <= JmpLimit])\\n\\t\\tifTrue: [strm nextPut: shortCode + dist - 1]\\n\\t\\tifFalse: [self emitLong: dist code: shortCode + (JmpLong-Jmp) on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation' stamp: 'nk 7/10/2004 10:04'!\\npc\\n\\t\\\"Used by encoder source mapping.\\\"\\n\\n\\t^pc ifNil: [ 0 ]\\n! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeBranchOn: condition dist: dist\\n\\tdist = 0 ifTrue: [^1].\\n\\t^ condition\\n\\t\\tifTrue: [2] \\\"Branch on true is always 2 bytes\\\"\\n\\t\\tifFalse: [self sizeShortOrLong: dist]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeForEffect: encoder\\n\\n\\t^(self sizeForValue: encoder) + 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeForReturn: encoder\\n\\n\\t^(self sizeForValue: encoder) + 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeJump: dist\\n\\n\\tdist = 0 ifTrue: [^0].\\n\\t^self sizeShortOrLong: dist! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeShortOrLong: dist\\n\\n\\t(1 <= dist and: [dist <= JmpLimit])\\n\\t\\tifTrue: [^1].\\n\\t^2! !\\n\\n\\n!ParseNode methodsFor: 'comment'!\\ncomment\\n\\n\\t^comment! !\\n\\n!ParseNode methodsFor: 'comment'!\\ncomment: newComment\\n\\n\\tcomment _ newComment! !\\n\\n\\n!ParseNode methodsFor: 'converting'!\\nasReturnNode\\n\\n\\t^ReturnNode new expr: self! !\\n\\n\\n!ParseNode methodsFor: 'encoding'!\\nencodeSelector: selector\\n\\n\\t^nil! !\\n\\n\\n!ParseNode methodsFor: 'printing' stamp: 'tk 10/16/2000 13:57'!\\nnodePrintOn: aStrm indent: nn\\n\\t| var aaStrm myLine |\\n\\t\\\"Show just the sub nodes and the code.\\\"\\n\\n\\t(aaStrm _ aStrm) ifNil: [aaStrm _ WriteStream on: (String new: 500)].\\n\\tnn timesRepeat: [aaStrm tab].\\n\\taaStrm nextPutAll: self class name; space.\\n\\tmyLine _ self printString copyWithout: Character cr.\\n\\tmyLine _ myLine copyFrom: 1 to: (myLine size min: 70).\\n\\taaStrm nextPutAll: myLine; cr.\\n\\t1 to: self class instSize do: [:ii | \\n\\t\\tvar _ self instVarAt: ii.\\n\\t\\t(var respondsTo: #asReturnNode) ifTrue: [var nodePrintOn: aaStrm indent: nn+1]].\\n\\t1 to: self class instSize do: [:ii | \\n\\t\\tvar _ self instVarAt: ii.\\n\\t\\t(var isKindOf: SequenceableCollection) ifTrue: [\\n\\t\\t\\t\\tvar do: [:aNode | \\n\\t\\t\\t\\t\\t(aNode respondsTo: #asReturnNode) ifTrue: [\\n\\t\\t\\t\\t\\t\\taNode nodePrintOn: aaStrm indent: nn+1]]]].\\n\\t^ aaStrm\\n! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'ab 7/13/2004 13:46'!\\nprintCommentOn: aStream indent: indent \\n\\t| thisComment |\\n\\tself comment == nil ifTrue: [^ self].\\n\\taStream withStyleFor: #comment\\n\\t\\tdo: [1 to: self comment size do: \\n\\t\\t\\t\\t[:index | \\n\\t\\t\\t\\tindex > 1 ifTrue: [aStream crtab: indent].\\n\\t\\t\\t\\taStream nextPut: $\\\".\\n\\t\\t\\t\\tthisComment _ self comment at: index.\\n\\t\\t\\t\\tself printSingleComment: thisComment\\n\\t\\t\\t\\t\\ton: aStream\\n\\t\\t\\t\\t\\tindent: indent.\\n\\t\\t\\t\\taStream nextPut: $\\\"]].\\n\\tself comment: nil! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'md 8/15/2005 11:02'!\\nprintOn: aStream \\n\\t\\\"Refer to the comment in Object|printOn:.\\\"\\n\\n\\taStream nextPutAll: '{'.\\n\\taStream nextPutAll: ((ColoredCodeStream contents: [:strm | self printOn: strm indent: 0])\\n\\t\\t\\t\\t\\t\\t\\tasString).\\n\\taStream nextPutAll: '}'! !\\n\\n!ParseNode methodsFor: 'printing'!\\nprintOn: aStream indent: anInteger \\n\\t\\\"If control gets here, avoid recursion loop.\\\"\\n\\n\\tsuper printOn: aStream! !\\n\\n!ParseNode methodsFor: 'printing'!\\nprintOn: aStream indent: level precedence: p\\n\\n\\tself printOn: aStream indent: level! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'ms 8/1/2006 16:47'!\\nshortPrintOn: aStream \\n\\tself printOn: aStream indent: 0! !\\n\\n\\n!ParseNode methodsFor: 'testing'!\\nassignmentCheck: encoder at: location\\n\\t\\\"For messageNodes masquerading as variables for the debugger.\\n\\tFor now we let this through - ie we allow stores ev\\n\\tinto args. Should check against numArgs, though.\\\"\\n\\t^ -1! !\\n\\n!ParseNode methodsFor: 'testing'!\\ncanBeSpecialArgument\\n\\t\\\"Can I be an argument of (e.g.) ifTrue:?\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\ncanCascade\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisArg\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisComplex\\n\\t\\\"Used for pretty printing to determine whether to start a new line\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisConstantNumber \\\"Overridden in LiteralNode\\\"\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'md 1/20/2006 16:22'!\\nisDoIt\\n\\t\\\"polymorphic with RBNodes; called by debugger\\\"\\n\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'ls 1/29/2004 21:11'!\\nisJust: node\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'di 4/5/2000 11:14'!\\nisLiteral\\n\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'md 7/27/2006 19:14'!\\nisMessage\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisMessage: selSymbol receiver: rcvrPred arguments: argsPred\\n\\t\\\"See comment in MessageNode.\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisReturnSelf\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisReturningIf\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'tk 8/2/1999 18:39'!\\nisSelfPseudoVariable\\t\\n\\t\\\"Overridden in VariableNode.\\\"\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisSpecialConstant\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'di 10/12/1999 15:28'!\\nisTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisUndefTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisUnusedTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisVariableReference\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nnowHasDef \\\"Ignored in all but VariableNode\\\"! !\\n\\n!ParseNode methodsFor: 'testing'!\\nnowHasRef \\\"Ignored in all but VariableNode\\\"! !\\n\\n!ParseNode methodsFor: 'testing'!\\ntoDoIncrement: ignored\\n\\t\\\"Only meant for Messages or Assignments - else return nil\\\"\\n\\t^ nil! !\\n\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'ab 7/13/2004 13:47'!\\naddCommentToMorph: aMorph\\n\\t| row |\\n\\t(self comment isNil or: [self comment isEmpty]) ifTrue: [^ self].\\n\\trow _ aMorph addTextRow:\\n\\t\\t(String streamContents: [:strm | self printCommentOn: strm indent: 1]).\\n\\trow firstSubmorph color: (SyntaxMorph translateColor: #comment).\\n\\trow parseNode: (self as: CommentNode).\\n! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 12:24'!\\nasMorphicSyntaxIn: parent\\n\\n\\t| morph |\\n\\t\\\"Default for missing implementations\\\"\\n\\n\\tmorph _ parent addColumn: #error on: self.\\n\\tmorph addTextRow: self class printString.\\n\\t^morph\\n\\t\\n\\n! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 13:06'!\\ncurrentValueIn: aContext\\n\\n\\t^nil! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 18:18'!\\nexplanation\\n\\n\\t^self class printString! !\\n\\n\\n!ParseNode methodsFor: 'private' stamp: 'ls 1/29/2004 21:17'!\\nifNilReceiver\\n\\t\\\"assuming this object is the receiver of an ifNil:, what object is being asked about?\\\"\\n\\t^self! !\\n\\n!ParseNode methodsFor: 'private' stamp: 'sma 5/28/2000 10:47'!\\nnextWordFrom: aStream setCharacter: aBlock\\n\\t| outStream char |\\n\\toutStream _ WriteStream on: (String new: 16).\\n\\t[(aStream peekFor: Character space) \\n\\t\\tor: [aStream peekFor: Character tab]] whileTrue.\\n\\t[aStream atEnd\\n\\t\\tor:\\n\\t\\t\\t[char _ aStream next.\\n\\t\\t\\tchar = Character cr or: [char = Character space]]]\\n\\t\\twhileFalse: [outStream nextPut: char].\\n\\taBlock value: char.\\n\\t^ outStream contents! !\\n\\n!ParseNode methodsFor: 'private' stamp: 'nk 7/11/2004 13:39'!\\nprintSingleComment: aString on: aStream indent: indent \\n\\t\\\"Print the comment string, assuming it has been indented indent tabs.\\n\\tBreak the string at word breaks, given the widths in the default\\n\\tfont, at 450 points.\\\"\\n\\n\\t| readStream word position lineBreak font wordWidth tabWidth spaceWidth lastChar |\\n\\treadStream _ ReadStream on: aString.\\n\\tfont _ TextStyle default defaultFont.\\n\\ttabWidth _ TextConstants at: #DefaultTab.\\n\\tspaceWidth _ font widthOf: Character space.\\n\\tposition _ indent * tabWidth.\\n\\tlineBreak _ 450.\\n\\t[readStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[word _ self nextWordFrom: readStream setCharacter: [:lc | lastChar _ lc].\\n\\t\\t\\twordWidth _ word inject: 0 into: [:width :char | width + (font widthOf: char)].\\n\\t\\t\\tposition _ position + wordWidth.\\n\\t\\t\\tposition > lineBreak\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[aStream skip: -1; crtab: indent.\\n\\t\\t\\t\\t\\tposition _ indent * tabWidth + wordWidth + spaceWidth.\\n\\t\\t\\t\\t\\tlastChar = Character cr\\n\\t\\t\\t\\t\\t\\tifTrue: [[readStream peekFor: Character tab] whileTrue].\\n\\t\\t\\t\\t\\tword isEmpty ifFalse: [aStream nextPutAll: word; space]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[aStream nextPutAll: word.\\n\\t\\t\\t\\t\\treadStream atEnd\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[position _ position + spaceWidth.\\n\\t\\t\\t\\t\\t\\t\\taStream space].\\n\\t\\t\\t\\t\\tlastChar = Character cr\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[aStream skip: -1; crtab: indent.\\n\\t\\t\\t\\t\\t\\t\\tposition _ indent * tabWidth.\\n\\t\\t\\t\\t\\t\\t\\t[readStream peekFor: Character tab] whileTrue]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParseNode class\\n\\tinstanceVariableNames: ''!\\n\\n!ParseNode class methodsFor: 'class initialization' stamp: 'ajh 8/12/2002 11:10'!\\nblockReturnCode\\n\\n\\t^ EndRemote! !\\n\\n!ParseNode class methodsFor: 'class initialization'!\\ninitialize\\n\\t\\\"ParseNode initialize. VariableNode initialize\\\"\\n\\tLdInstType _ 1.\\n\\tLdTempType _ 2.\\n\\tLdLitType _ 3.\\n\\tLdLitIndType _ 4.\\n\\tSendType _ 5.\\n\\tCodeBases _ #(0 16 32 64 208 ).\\n\\tCodeLimits _ #(16 16 32 32 16 ).\\n\\tLdSelf _ 112.\\n\\tLdTrue _ 113.\\n\\tLdFalse _ 114.\\n\\tLdNil _ 115.\\n\\tLdMinus1 _ 116.\\n\\tLoadLong _ 128.\\n\\tStore _ 129.\\n\\tStorePop _ 130.\\n\\tShortStoP _ 96.\\n\\tSendLong _ 131.\\n\\tDblExtDoAll _ 132.\\n\\tSendLong2 _ 134.\\n\\tLdSuper _ 133.\\n\\tPop _ 135.\\n\\tDup _ 136.\\n\\tLdThisContext _ 137.\\n\\tEndMethod _ 124.\\n\\tEndRemote _ 125.\\n\\tJmp _ 144.\\n\\tBfp _ 152.\\n\\tJmpLimit _ 8.\\n\\tJmpLong _ 164. \\\"code for jmp 0\\\"\\n\\tBtpLong _ 168.\\n\\tSendPlus _ 176.\\n\\tSend _ 208.\\n\\tSendLimit _ 16! !\\n\\n!ParseNode class methodsFor: 'class initialization' stamp: 'ajh 8/6/2002 12:04'!\\npopCode\\n\\n\\t^ Pop! !\\nObject subclass: #ParseStack\\n\\tinstanceVariableNames: 'position length'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Support'!\\n!ParseStack commentStamp: '<historical>' prior: 0!\\nI keep track of the current and high position of the stack that will be needed by code being compiled.!\\n\\n\\n!ParseStack methodsFor: 'accessing'!\\npop: n\\n\\n\\t(position _ position - n) < 0 \\n\\t\\tifTrue: [self error: 'Parse stack underflow']! !\\n\\n!ParseStack methodsFor: 'accessing'!\\npush: n\\n\\n\\t(position _ position + n) > length \\n\\t\\tifTrue: [length _ position]! !\\n\\n!ParseStack methodsFor: 'accessing'!\\nsize\\n\\n\\t^length! !\\n\\n\\n!ParseStack methodsFor: 'initialize-release'!\\ninit\\n\\n\\tlength _ position _ 0! !\\n\\n\\n!ParseStack methodsFor: 'printing'!\\nprintOn: aStream\\n\\t\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' at '; print: position; nextPutAll: ' of '; print: length! !\\n\\n\\n!ParseStack methodsFor: 'results'!\\nposition\\n\\n\\t^position! !\\nScanner subclass: #Parser\\n\\tinstanceVariableNames: 'here hereType hereMark hereEnd prevMark prevEnd encoder requestor parseNode failBlock requestorOffset tempsMark doitFlag properties category'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Kernel'!\\n!Parser commentStamp: '<historical>' prior: 0!\\nI parse Smalltalk syntax and create a MethodNode that is the root of the parse tree. I look one token ahead.!\\n\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 11:01'!\\ncorrectSelector: proposedKeyword wordIntervals: spots exprInterval: expInt ifAbort: abortAction\\n\\t\\\"Correct the proposedKeyword to some selector symbol, correcting the original text if such action is indicated. abortAction is invoked if 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.\\\"\\n\\n\\t| alternatives aStream choice correctSelector userSelection lines firstLine |\\n\\t\\\"If we can't ask the user, assume that the keyword will be defined later\\\"\\n\\tself interactive ifFalse: [ ^ proposedKeyword asSymbol ].\\n\\n\\tuserSelection _ requestor selectionInterval.\\n\\trequestor selectFrom: spots first first to: spots last last.\\n\\trequestor select.\\n\\talternatives _ Symbol possibleSelectorsFor: proposedKeyword.\\n\\tself flag: #toBeFixed.\\n\\t\\\"alternatives addAll: (MultiSymbol possibleSelectorsFor: proposedKeyword).\\\"\\n\\n\\taStream _ WriteStream on: (String new: 200).\\n\\taStream nextPutAll: (proposedKeyword contractTo: 35); cr.\\n\\tfirstLine _ 1.\\n \\talternatives do:\\n\\t\\t[:sel | aStream nextPutAll: (sel contractTo: 35); nextPut: Character cr].\\n\\taStream nextPutAll: 'cancel'.\\n\\tlines _ Array with: firstLine with: (alternatives size + firstLine).\\n\\t\\n\\tchoice _ (UIManager default \\n\\t\\t\\tchooseFrom: (aStream contents substrings)\\n\\t\\t\\tlines: lines\\n\\t\\t\\ttitle: 'Unknown selector, please\\\\confirm, correct, or cancel' withCRs).\\n\\n\\t(choice = 0) | (choice > (lines at: 2))\\n\\t\\tifTrue: [ ^ abortAction value ].\\n\\n\\trequestor deselect.\\n\\trequestor selectInvisiblyFrom: userSelection first to: userSelection last.\\n\\n\\tchoice = 1 ifTrue: [ ^ proposedKeyword asSymbol ].\\n\\tcorrectSelector _ alternatives at: choice - 1.\\n\\tself substituteSelector: correctSelector keywords wordIntervals: spots.\\n\\t((proposedKeyword last ~= $:) and: [correctSelector last == $:]) ifTrue: [\\n\\t\\t^ abortAction value].\\n\\t^ correctSelector.\\n! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:01'!\\ncorrectVariable: proposedVariable interval: spot\\n\\t\\\"Correct the proposedVariable to a known variable, or declare it as a new\\n\\tvariable if such action is requested. We support declaring lowercase\\n\\tvariables as temps or inst-vars, and uppercase variables as Globals or \\n\\tClassVars, depending on whether the context is nil (class=UndefinedObject).\\n\\tSpot is the interval within the test stream of the variable.\\n\\trr 3/4/2004 10:26 : adds the option to define a new class. \\\"\\n\\n\\t| tempIvar labels actions lines alternatives binding userSelection choice action |\\n\\n\\t\\\"Check if this is an i-var, that has been corrected already (ugly)\\\"\\n\\t(encoder classEncoding allInstVarNames includes: proposedVariable) ifTrue: [\\n\\t\\t^LiteralVariableNode new \\n\\t\\t\\tname: proposedVariable index: (encoder classEncoding allInstVarNames indexOf: proposedVariable) - 1 type: 1;\\n\\t\\t\\tyourself ].\\n\\n\\t\\\"If we can't ask the user for correction, make it undeclared\\\"\\n\\tself interactive \\n\\t\\tifFalse: [ ^encoder undeclared: proposedVariable ].\\n\\n\\t\\\"First check to see if the requestor knows anything about the variable\\\"\\n\\ttempIvar _ proposedVariable first canBeNonGlobalVarInitial.\\n\\t(tempIvar and: [ (binding _ requestor bindingOf: proposedVariable) notNil ])\\n\\t\\tifTrue: [ ^encoder global: binding name: proposedVariable ].\\n\\tuserSelection _ requestor selectionInterval.\\n\\trequestor selectFrom: spot first to: spot last.\\n\\trequestor select.\\n\\n\\t\\\"Build the menu with alternatives\\\"\\n\\tlabels _ OrderedCollection new. actions _ OrderedCollection new. lines _ OrderedCollection new.\\n\\talternatives _ encoder possibleVariablesFor: proposedVariable.\\n\\ttempIvar \\n\\t\\tifTrue: [ \\n\\t\\t\\tlabels add: 'declare temp'. \\n\\t\\t\\tactions add: [ self declareTempAndPaste: proposedVariable ].\\n\\t\\t\\tlabels add: 'declare instance'.\\n\\t\\t\\tactions add: [ self declareInstVar: proposedVariable ] ]\\n\\t\\tifFalse: [ \\n\\t\\t\\tlabels add: 'define new class'.\\n\\t\\t\\tactions add: [self defineClass: proposedVariable].\\n\\t\\t\\tlabels add: 'declare global'.\\n\\t\\t\\tactions add: [ self declareGlobal: proposedVariable ].\\n\\t\\t\\tencoder classEncoding == UndefinedObject ifFalse: [ \\n\\t\\t\\t\\tlabels add: 'declare class variable'.\\n\\t\\t\\t\\tactions add: [ self declareClassVar: proposedVariable ] ] ].\\n\\tlines add: labels size.\\n\\talternatives do: [ :each | \\n\\t\\tlabels add: each.\\n\\t\\tactions add: [ \\n\\t\\t\\tself substituteWord: each wordInterval: spot offset: 0.\\n\\t\\t\\tencoder encodeVariable: each ] fixTemps ].\\n\\tlines add: labels size.\\n\\tlabels add: 'cancel'.\\n\\n\\t\\\"Display the pop-up menu\\\"\\n\\tchoice _ (UIManager default chooseFrom: labels asArray lines: lines asArray\\n\\t\\ttitle: 'Unknown variable: ', proposedVariable, ' please correct, or cancel:').\\n\\taction _ actions at: choice ifAbsent: [ ^self fail ].\\n\\n\\t\\\"Execute the selected action\\\"\\n\\trequestor deselect.\\n\\trequestor selectInvisiblyFrom: userSelection first to: userSelection last.\\n\\t^action value! !\\n\\n!Parser methodsFor: 'error correction'!\\ndeclareClassVar: name\\n\\t| sym class |\\n\\tsym _ name asSymbol.\\n\\tclass _ encoder classEncoding.\\n\\tclass _ class theNonMetaClass.\\t\\t\\\"not the metaclass\\\"\\n\\tclass addClassVarName: name.\\n\\t^ encoder global: (class classPool associationAt: sym)\\n\\t\\t\\tname: sym! !\\n\\n!Parser methodsFor: 'error correction'!\\ndeclareGlobal: name\\n\\t| sym |\\n\\tsym _ name asSymbol.\\n\\tSmalltalk at: sym put: nil.\\n\\t^ encoder global: (Smalltalk associationAt: sym) name: sym! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rr 3/6/2004 16:07'!\\ndeclareInstVar: name\\n\\t\\\" rr 3/6/2004 16:06 : adds the line to correctly compute the index. uncommented the option in \\n\\tthe caller.\\\"\\n\\t| index |\\n\\tencoder classEncoding addInstVarName: name.\\n\\tindex _ encoder classEncoding instVarNames indexOf: name.\\n\\tencoder classEncoding allSuperclassesDo: [:cls | index := index + cls instVarNames size].\\n\\t^LiteralVariableNode new\\n\\t\\tname: name index: index - 1 type: 1;\\n\\t\\tyourself\\n\\t\\t! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'RAA 6/5/2001 11:57'!\\ndeclareTempAndPaste: name\\n\\t| insertion delta theTextString characterBeforeMark |\\n\\n\\ttheTextString _ requestor text string.\\n\\tcharacterBeforeMark _ theTextString at: tempsMark-1 ifAbsent: [$ ].\\n\\t(theTextString at: tempsMark) = $| ifTrue: [\\n \\t\\t\\\"Paste it before the second vertical bar\\\"\\n\\t\\tinsertion _ name, ' '.\\n\\t\\tcharacterBeforeMark isSeparator ifFalse: [\\finsertion _ ' ', insertion].\\n\\t\\tdelta _ 0.\\n\\t] ifFalse: [\\n\\t\\t\\\"No bars - insert some with CR, tab\\\"\\n\\t\\tinsertion _ '| ' , name , ' |',String cr.\\n\\t\\tdelta _ 2.\\t\\\"the bar and CR\\\"\\n\\t\\tcharacterBeforeMark = Character tab ifTrue: [\\n\\t\\t\\tinsertion _ insertion , String tab.\\n\\t\\t\\tdelta _ delta + 1.\\t\\\"the tab\\\"\\n\\t\\t].\\n\\t].\\n\\ttempsMark _ tempsMark +\\n\\t\\t(self substituteWord: insertion\\n\\t\\t\\twordInterval: (tempsMark to: tempsMark-1)\\n\\t\\t\\toffset: 0) - delta.\\n\\t^ encoder bindAndJuggle: name! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'DF 4/28/2006 14:31'!\\ndefineClass: className \\n\\t\\\"prompts the user to define a new class, \\n\\tasks for it's category, and lets the users edit further \\n\\tthe definition\\\"\\n\\t| sym cat def d2 |\\n\\tsym := className asSymbol.\\n\\tcat := UIManager default request: 'Enter class category : ' initialAnswer: self encoder classEncoding theNonMetaClass category.\\n\\tcat\\n\\t\\tifEmpty: [cat := 'Unknown'].\\n\\tdef := 'Object subclass: #' , sym , '\\n\\t\\tinstanceVariableNames: '''' \\n\\t\\tclassVariableNames: ''''\\n\\t\\tpoolDictionaries: ''''\\n\\t\\tcategory: ''' , cat , ''''.\\n\\td2 := UIManager default request: 'Edit class definition : ' initialAnswer: def.\\n\\td2\\n\\t\\tifEmpty: [d2 := def].\\n\\tCompiler evaluate: d2.\\n\\t^ encoder\\n\\t\\tglobal: (Smalltalk associationAt: sym)\\n\\t\\tname: sym! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:10'!\\nqueryUndefined\\n\\t| varStart varName | \\n\\tvarName _ parseNode key.\\n\\tvarStart _ self endOfLastToken + requestorOffset - varName size + 1.\\n\\trequestor selectFrom: varStart to: varStart + varName size - 1; select.\\n\\t((UIManager default \\n\\t\\tchooseFrom: #('yes' 'no') \\n\\t\\ttitle: ((varName , ' appears to be\\\\undefined at this point.Proceed anyway?') \\n\\t\\t\\t\\twithCRs asText makeBoldFrom: 1 to: varName size))\\n\\t\\t= 1) ifFalse: [^ self fail]! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:08'!\\nremoveUnusedTemps\\n\\t\\\"Scan for unused temp names, and prompt the user about the prospect of removing each one found\\\"\\n\\n\\t| str end start madeChanges | \\n\\tmadeChanges _ false.\\n\\tstr _ requestor text string.\\n\\t((tempsMark between: 1 and: str size)\\n\\t\\tand: [(str at: tempsMark) = $|]) ifFalse: [^ self].\\n\\tencoder unusedTempNames do:\\n\\t\\t[:temp |\\n\\t\\t((UIManager default \\n\\t\\t\\t\\tchooseFrom: #('yes' 'no') \\n\\t\\t\\t\\ttitle: ((temp , ' appears to be\\\\unused in this method.\\\\OK to remove it?') \\n\\t\\t\\t\\t\\t\\twithCRs asText makeBoldFrom: 1 to: temp size)) = 1)\\n\\t\\tifTrue:\\n\\t\\t[(encoder encodeVariable: temp) isUndefTemp\\n\\t\\t\\tifTrue:\\n\\t\\t\\t[end _ tempsMark.\\n\\t\\t\\t[\\\"Beginning at right temp marker...\\\"\\n\\t\\t\\tstart _ end - temp size + 1.\\n\\t\\t\\tend < temp size or: [temp = (str copyFrom: start to: end)\\n\\t\\t\\t\\t\\tand: [(str at: start-1) isAlphaNumeric not & (str at: end+1) isAlphaNumeric not]]]\\n\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t[\\\"Search left for the unused temp\\\"\\n\\t\\t\\t\\tend _ requestor nextTokenFrom: end direction: -1].\\n\\t\\t\\tend < temp size ifFalse:\\n\\t\\t\\t\\t[(str at: start-1) = $ ifTrue: [start _ start-1].\\n\\t\\t\\t\\trequestor correctFrom: start to: end with: ''.\\n\\t\\t\\t\\tstr _ str copyReplaceFrom: start to: end with: ''. \\n\\t\\t\\t\\tmadeChanges _ true.\\n\\t\\t\\t\\ttempsMark _ tempsMark - (end-start+1)]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t[self inform:\\n'You''ll first have to remove the\\nstatement where it''s stored into']]].\\n\\tmadeChanges ifTrue: [ParserRemovedUnusedTemps signal]! !\\n\\n!Parser methodsFor: 'error correction'!\\nsubstituteSelector: selectorParts wordIntervals: spots\\n\\t\\\"Substitute the correctSelector into the (presuamed interactive) receiver.\\\"\\n\\t| offset |\\n\\toffset _ 0.\\n\\tselectorParts with: spots do:\\n\\t\\t[ :word :interval |\\n\\t\\toffset _ self substituteWord: word wordInterval: interval offset: offset ]\\n! !\\n\\n!Parser methodsFor: 'error correction'!\\nsubstituteWord: correctWord wordInterval: spot offset: o\\n\\t\\\"Substitute the correctSelector into the (presuamed interactive) receiver.\\\"\\n\\n\\trequestor correctFrom: (spot first + o)\\n\\t\\t\\t\\t\\tto: (spot last + o)\\n\\t\\t\\t\\t\\twith: correctWord.\\n\\n\\trequestorOffset _ requestorOffset + correctWord size - spot size.\\n\\t^ o + correctWord size - spot size! !\\n\\n\\n!Parser methodsFor: 'error handling' stamp: 'hmm 7/18/2001 21:45'!\\nexpected: aString \\n\\t\\\"Notify a problem at token 'here'.\\\"\\n\\n\\ttokenType == #doIt ifTrue: [hereMark _ hereMark + 1].\\n\\thereType == #doIt ifTrue: [hereMark _ hereMark + 1].\\n\\t^ self notify: aString , ' expected' at: hereMark + requestorOffset! !\\n\\n!Parser methodsFor: 'error handling'!\\nfail\\n\\n\\t| exitBlock |\\n\\tencoder == nil\\n\\t\\tifFalse: [encoder release. encoder _ nil]. \\\"break cycle\\\"\\n\\texitBlock _ failBlock.\\n\\tfailBlock _ nil.\\n\\t^exitBlock value! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'stephaneducassse 11/5/2005 16:39'!\\ninteractive\\n\\t\\\"this version of the method is necessary to load code from MC else the interactive mode is one. \\n\\tThis method is really bad since it links the compiler package with the Tools\\n\\tone. The solution would be to have a real SyntaxError exception belonging to the \\n\\tcompiler package and not a subclass of StringHolder - sd Nov 2005\\\"\\n\\t\\\"the code submitted by PlusTools is ideally the one that should be used\\n\\tinteractive\\n\\n\\t ^requestor ~~ nil \\\"\\n\\t\\n\\t^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not! !\\n\\n!Parser methodsFor: 'error handling'!\\nnotify: aString \\n\\t\\\"Notify problem at token before 'here'.\\\"\\n\\n\\t^self notify: aString at: prevMark + requestorOffset! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'KLC 11/28/2005 18:01'!\\nnotify: string at: location\\n\\trequestor isNil\\n\\t\\tifTrue: [(encoder == self or: [encoder isNil]) ifTrue: [^ self fail \\\"failure setting up syntax error\\\"].\\n\\t\\t\\t\\tSyntaxErrorNotification\\n\\t\\t\\t\\t\\tinClass: encoder classEncoding\\n\\t\\t\\t\\t\\tcategory: encoder classEncoding category\\n\\t\\t\\t\\t\\twithCode: \\n\\t\\t\\t\\t\\t\\t(source contents\\n\\t\\t\\t\\t\\t\\t\\tcopyReplaceFrom: location\\n\\t\\t\\t\\t\\t\\t\\tto: location - 1\\n\\t\\t\\t\\t\\t\\t\\twith: string , ' ->')\\n\\t\\t\\t\\t\\tdoitFlag: doitFlag]\\n\\t\\tifFalse: [requestor\\n\\t\\t\\t\\t\\tnotify: string , ' ->'\\n\\t\\t\\t\\t\\tat: location\\n\\t\\t\\t\\t\\tin: source].\\n\\t^self fail! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'di 2/9/1999 15:43'!\\noffEnd: aString \\n\\t\\\"Notify a problem beyond 'here' (in lookAhead token). Don't be offEnded!!\\\"\\n\\n\\trequestorOffset == nil\\n\\t\\tifTrue: [^ self notify: aString at: mark]\\n\\t\\tifFalse: [^ self notify: aString at: mark + requestorOffset]\\n! !\\n\\n\\n!Parser methodsFor: 'expression types'!\\nargumentName\\n\\n\\thereType == #word\\n\\t\\tifFalse: [^self expected: 'Argument name'].\\n\\t^self advance! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'hmm 7/16/2001 18:47'!\\nassignment: varNode\\n\\t\\\" var '_' expression => AssignmentNode.\\\"\\n\\t| loc start |\\n\\t(loc _ varNode assignmentCheck: encoder at: prevMark + requestorOffset) >= 0\\n\\t\\tifTrue: [^self notify: 'Cannot store into' at: loc].\\n\\tstart _ self startOfNextToken.\\n\\tvarNode nowHasDef.\\n\\tself advance.\\n\\tself expression ifFalse: [^self expected: 'Expression'].\\n\\tparseNode _ AssignmentNode new\\n\\t\\t\\t\\tvariable: varNode\\n\\t\\t\\t\\tvalue: parseNode\\n\\t\\t\\t\\tfrom: encoder\\n\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken).\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'hmm 7/17/2001 21:03'!\\nblockExpression\\n\\t\\\"[ ({:var} |) (| {temps} |) (statements) ] => BlockNode.\\\"\\n\\n\\t| variableNodes temporaryBlockVariables start |\\n\\n\\tvariableNodes _ OrderedCollection new.\\n\\tstart _ prevMark + requestorOffset.\\n\\t\\\"Gather parameters.\\\"\\n\\t[self match: #colon] whileTrue: [variableNodes addLast: (encoder autoBind: self argumentName)].\\n\\t(variableNodes size > 0 & (hereType ~~ #rightBracket) and: [(self match: #verticalBar) not]) ifTrue: [^self expected: 'Vertical bar'].\\n\\n\\ttemporaryBlockVariables _ self temporaryBlockVariables.\\n\\tself statements: variableNodes innerBlock: true.\\n\\tparseNode temporaries: temporaryBlockVariables.\\n\\n\\t(self match: #rightBracket) ifFalse: [^self expected: 'Period or right bracket'].\\n\\n\\tencoder noteSourceRange: (self endOfLastToken to: self endOfLastToken) forNode: parseNode.\\n\\n\\t\\\"The scope of the parameters and temporary block variables is no longer active.\\\"\\n\\ttemporaryBlockVariables do: [:variable | variable scope: -1].\\n\\tvariableNodes do: [:variable | variable scope: -1]! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 3/8/2000 09:36'!\\nbraceExpression\\n\\t\\\" { elements } => BraceNode.\\\"\\n\\n\\t| elements locations loc more |\\n\\telements _ OrderedCollection new.\\n\\tlocations _ OrderedCollection new.\\n\\tself advance.\\n\\tmore _ hereType ~~ #rightBrace.\\n\\t[more]\\n\\t\\twhileTrue: \\n\\t\\t\\t[loc _ hereMark + requestorOffset.\\n\\t\\t\\tself expression\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[elements addLast: parseNode.\\n\\t\\t\\t\\t\\tlocations addLast: loc]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[^self expected: 'Variable or expression'].\\n\\t\\t\\t(self match: #period)\\n\\t\\t\\t\\tifTrue: [more _ hereType ~~ #rightBrace]\\n\\t\\t\\t\\tifFalse: [more _ false]].\\n\\tparseNode _ BraceNode new elements: elements sourceLocations: locations.\\n\\t(self match: #rightBrace)\\n\\t\\tifFalse: [^self expected: 'Period or right brace'].\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types'!\\ncascade\\n\\t\\\" {; message} => CascadeNode.\\\"\\n\\n\\t| rcvr msgs |\\n\\tparseNode canCascade\\n\\t\\tifFalse: [^self expected: 'Cascading not'].\\n\\trcvr _ parseNode cascadeReceiver.\\n\\tmsgs _ OrderedCollection with: parseNode.\\n\\t[self match: #semicolon]\\n\\t\\twhileTrue: \\n\\t\\t\\t[parseNode _ rcvr.\\n\\t\\t\\t(self messagePart: 3 repeat: false)\\n\\t\\t\\t\\tifFalse: [^self expected: 'Cascade'].\\n\\t\\t\\tparseNode canCascade\\n\\t\\t\\t\\tifFalse: [^self expected: '<- No special messages'].\\n\\t\\t\\tparseNode cascadeReceiver.\\n\\t\\t\\tmsgs addLast: parseNode].\\n\\tparseNode _ CascadeNode new receiver: rcvr messages: msgs! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 11/19/1999 07:43'!\\nexpression\\n\\n\\t(hereType == #word and: [tokenType == #leftArrow])\\n\\t\\tifTrue: [^ self assignment: self variable].\\n\\thereType == #leftBrace\\n\\t\\tifTrue: [self braceExpression]\\n\\t\\tifFalse: [self primaryExpression ifFalse: [^ false]].\\n\\t(self messagePart: 3 repeat: true)\\n\\t\\tifTrue: [hereType == #semicolon ifTrue: [self cascade]].\\n\\t^ true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 4/5/2000 08:27'!\\nkeylessMessagePartTest: level repeat: repeat\\n! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'yo 8/30/2002 14:41'!\\nmessagePart: level repeat: repeat\\n\\n\\t| start receiver selector args precedence words keywordStart |\\n\\t[receiver _ parseNode.\\n\\t(hereType == #keyword and: [level >= 3])\\n\\t\\tifTrue: \\n\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\tselector _ WriteStream on: (String new: 32).\\n\\t\\t\\targs _ OrderedCollection new.\\n\\t\\t\\twords _ OrderedCollection new.\\n\\t\\t\\t[hereType == #keyword]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[keywordStart _ self startOfNextToken + requestorOffset.\\n\\t\\t\\t\\t\\tselector nextPutAll: self advance.\\n\\t\\t\\t\\t\\twords addLast: (keywordStart to: self endOfLastToken + requestorOffset).\\n\\t\\t\\t\\t\\tself primaryExpression ifFalse: [^self expected: 'Argument'].\\n\\t\\t\\t\\t\\tself messagePart: 2 repeat: true.\\n\\t\\t\\t\\t\\targs addLast: parseNode].\\n\\t\\t\\t(Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym])\\n\\t\\t\\t\\tifFalse: [ selector _ self correctSelector: selector contents\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twordIntervals: words\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texprInterval: (start to: self endOfLastToken)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbort: [ ^ self fail ] ].\\n\\t\\t\\tprecedence _ 3]\\n\\t\\tifFalse: [((hereType == #binary or: [hereType == #verticalBar])\\n\\t\\t\\t\\tand: [level >= 2])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\t\\t\\tselector _ self advance asOctetString asSymbol.\\n\\t\\t\\t\\t\\tself primaryExpression ifFalse: [^self expected: 'Argument'].\\n\\t\\t\\t\\t\\tself messagePart: 1 repeat: true.\\n\\t\\t\\t\\t\\targs _ Array with: parseNode.\\n\\t\\t\\t\\t\\tprecedence _ 2]\\n\\t\\t\\t\\tifFalse: [hereType == #word\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\t\\t\\t\\t\\tselector _ self advance.\\n\\t\\t\\t\\t\\t\\t\\targs _ #().\\n\\t\\t\\t\\t\\t\\t\\twords _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset).\\n\\t\\t\\t\\t\\t\\t\\t(Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym])\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [ selector _ self correctSelector: selector\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twordIntervals: words\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texprInterval: (start to: self endOfLastToken)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbort: [ ^ self fail ] ].\\n\\t\\t\\t\\t\\t\\t\\tprecedence _ 1]\\n\\t\\t\\t\\t\\t\\tifFalse: [^args notNil]]].\\n\\tparseNode _ MessageNode new\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\targuments: args\\n\\t\\t\\t\\tprecedence: precedence\\n\\t\\t\\t\\tfrom: encoder\\n\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken).\\n\\trepeat]\\n\\t\\twhileTrue: [].\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'lr 7/3/2006 14:37'!\\nmethod: doit context: ctxt encoder: encoderToUse\\n\\t\\\" pattern [ | temporaries ] block => MethodNode.\\\"\\n\\n\\t| sap blk prim temps messageComment methodNode |\\n\\tencoder _ encoderToUse.\\n\\tsap _ self pattern: doit inContext: ctxt.\\n\\t\\\"sap={selector, arguments, precedence}\\\"\\n\\t(sap at: 2) do: [:argNode | argNode isArg: true].\\n\\tdoit ifFalse: [ self pragmaSequence ].\\n\\ttemps _ self temporariesIn: (sap at: 1)..\\n\\tmessageComment _ currentComment.\\n\\tcurrentComment _ nil.\\n\\tdoit ifFalse: [ self pragmaSequence ].\\n\\tprim := self pragmaPrimitives.\\n\\tself statements: #() innerBlock: doit.\\n\\tblk _ parseNode.\\n\\tdoit ifTrue: [blk returnLast]\\n\\t\\tifFalse: [blk returnSelfIfNoOther].\\n\\thereType == #doIt ifFalse: [^self expected: 'Nothing more'].\\n\\tself interactive ifTrue: [self removeUnusedTemps].\\n\\tmethodNode _ self newMethodNode comment: messageComment.\\n\\t^ methodNode\\n\\t\\tselector: (sap at: 1)\\n\\t\\targuments: (sap at: 2)\\n\\t\\tprecedence: (sap at: 3)\\n\\t\\ttemporaries: temps\\n\\t\\tblock: blk\\n\\t\\tencoder: encoder\\n\\t\\tprimitive: prim\\n\\t\\tproperties: properties! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 5/30/2000 21:59'!\\nnewMethodNode\\n\\n\\t^ MethodNode new! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'ar 1/2/2002 14:31'!\\npattern: fromDoit inContext: ctxt \\n\\t\\\" unarySelector | binarySelector arg | keyword arg {keyword arg} => \\n\\t{selector, arguments, precedence}.\\\"\\n\\t| args selector |\\n\\tdoitFlag _ fromDoit.\\n\\tfromDoit ifTrue:\\n\\t\\t\\t[ctxt == nil\\n\\t\\t\\t\\tifTrue: [^ {#DoIt. {}. 1}]\\n\\t\\t\\t\\tifFalse: [^ {#DoItIn:. {encoder encodeVariable: 'homeContext'}. 3}]].\\n\\n\\thereType == #word ifTrue: [^ {self advance asSymbol. {}. 1}].\\n\\n\\t(hereType == #binary or: [hereType == #verticalBar])\\n\\t\\tifTrue: \\n\\t\\t\\t[selector _ self advance asSymbol.\\n\\t\\t\\targs _ Array with: (encoder bindArg: self argumentName).\\n\\t\\t\\t^ {selector. args. 2}].\\n\\n\\thereType == #keyword\\n\\t\\tifTrue: \\n\\t\\t\\t[selector _ WriteStream on: (String new: 32).\\n\\t\\t\\targs _ OrderedCollection new.\\n\\t\\t\\t[hereType == #keyword] whileTrue:[\\n\\t\\t\\t\\tselector nextPutAll: self advance.\\n\\t\\t\\t\\targs addLast: (encoder bindArg: self argumentName).\\n\\t\\t\\t].\\n\\t\\t\\t^ {selector contents asSymbol. args. 3}].\\n\\n\\t^ self expected: 'Message pattern'! !\\n\\n!Parser methodsFor: 'expression types'!\\nprimaryExpression \\n\\thereType == #word \\n\\t\\tifTrue: \\n\\t\\t\\t[parseNode _ self variable.\\n\\t\\t\\t(parseNode isUndefTemp and: [self interactive])\\n\\t\\t\\t\\tifTrue: [self queryUndefined].\\n\\t\\t\\tparseNode nowHasRef.\\n\\t\\t\\t^ true].\\n\\thereType == #leftBracket\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tself blockExpression.\\n\\t\\t\\t^true].\\n\\thereType == #leftBrace\\n\\t\\tifTrue: \\n\\t\\t\\t[self braceExpression.\\n\\t\\t\\t^true].\\n\\thereType == #leftParenthesis\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tself expression ifFalse: [^self expected: 'expression'].\\n\\t\\t\\t(self match: #rightParenthesis)\\n\\t\\t\\t\\tifFalse: [^self expected: 'right parenthesis'].\\n\\t\\t\\t^true].\\n\\t(hereType == #string or: [hereType == #number or: [hereType == #literal]])\\n\\t\\tifTrue: \\n\\t\\t\\t[parseNode _ encoder encodeLiteral: self advance.\\n\\t\\t\\t^true].\\n\\t(here == #- and: [tokenType == #number])\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tparseNode _ encoder encodeLiteral: self advance negated.\\n\\t\\t\\t^true].\\n\\t^false! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 6/7/2000 08:45'!\\nstatements: argNodes innerBlock: inner\\n\\n\\t| stmts returns start more blockComment |\\n\\tstmts _ OrderedCollection new.\\n\\t\\\"give initial comment to block, since others trail statements\\\"\\n\\tblockComment _ currentComment.\\n\\tcurrentComment _ nil.\\n\\treturns _ false.\\n\\tmore _ hereType ~~ #rightBracket.\\n\\t[more]\\n\\t\\twhileTrue: \\n\\t\\t[start _ self startOfNextToken.\\n\\t\\t(returns _ self matchReturn)\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[self expression\\n\\t\\t\\t\\t\\tifFalse: [^self expected: 'Expression to return'].\\n\\t\\t\\t\\tself addComment.\\n\\t\\t\\t\\tstmts addLast: (parseNode isReturningIf\\n\\t\\t\\t\\t\\tifTrue: [parseNode]\\n\\t\\t\\t\\t\\tifFalse: [ReturnNode new\\n\\t\\t\\t\\t\\t\\t\\texpr: parseNode\\n\\t\\t\\t\\t\\t\\t\\tencoder: encoder\\n\\t\\t\\t\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken)])]\\n\\t\\t\\tifFalse: \\n\\t\\t\\t\\t[self expression\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[self addComment.\\n\\t\\t\\t\\t\\t\\tstmts addLast: parseNode]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[self addComment.\\n\\t\\t\\t\\t\\t\\tstmts size = 0\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[stmts addLast: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(encoder encodeVariable:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(inner ifTrue: ['nil'] ifFalse: ['self']))]]].\\n\\t\\treturns \\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[self match: #period.\\n\\t\\t\\t\\t(hereType == #rightBracket or: [hereType == #doIt])\\n\\t\\t\\t\\t\\tifFalse: [^self expected: 'End of block']].\\n\\t\\tmore _ returns not and: [self match: #period]].\\n\\tparseNode _ BlockNode new\\n\\t\\t\\t\\targuments: argNodes\\n\\t\\t\\t\\tstatements: stmts\\n\\t\\t\\t\\treturns: returns\\n\\t\\t\\t\\tfrom: encoder.\\n\\tparseNode comment: blockComment.\\n\\t^ true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'ar 1/4/2002 00:23'!\\ntemporaries\\n\\t\\\" [ '|' (variable)* '|' ]\\\"\\n\\t| vars theActualText |\\n\\t(self match: #verticalBar) ifFalse: \\n\\t\\t[\\\"no temps\\\"\\n\\t\\tdoitFlag ifTrue: [self interactive\\n\\t\\t\\t\\tifFalse: [tempsMark _ 1]\\n\\t\\t\\t\\tifTrue: [tempsMark _ requestor selectionInterval first].\\n\\t\\t\\t^ #()].\\n\\t\\ttempsMark _ (prevEnd ifNil: [0]) + 1.\\n\\t\\ttempsMark _ hereMark\\t\\\"formerly --> prevMark + prevToken\\\".\\n\\n\\t\\ttempsMark > 0 ifTrue:\\n\\t\\t\\t[theActualText _ source contents.\\n\\t\\t\\t[tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]]\\n\\t\\t\\t\\twhileTrue: [tempsMark _ tempsMark + 1]].\\n\\t\\t\\t^ #()].\\n\\tvars _ OrderedCollection new.\\n\\t[hereType == #word]\\n\\t\\twhileTrue: [vars addLast: (encoder bindTemp: self advance)].\\n\\t(self match: #verticalBar) ifTrue: \\n\\t\\t[tempsMark _ prevMark.\\n\\t\\t^ vars].\\n\\t^ self expected: 'Vertical bar'\\n! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'mir 1/17/2004 12:27'!\\ntemporariesIn: methodSelector\\n\\t\\\" [ '|' (variable)* '|' ]\\\"\\n\\t| vars theActualText |\\n\\t(self match: #verticalBar) ifFalse: \\n\\t\\t[\\\"no temps\\\"\\n\\t\\tdoitFlag ifTrue: [requestor\\n\\t\\t\\t\\tifNil: [tempsMark _ 1]\\n\\t\\t\\t\\tifNotNil: [tempsMark _ requestor selectionInterval first].\\n\\t\\t\\t^ #()].\\n\\t\\ttempsMark _ (prevEnd ifNil: [0]) + 1.\\n\\t\\ttempsMark _ hereMark\\t\\\"formerly --> prevMark + prevToken\\\".\\n\\n\\t\\ttempsMark > 0 ifTrue:\\n\\t\\t\\t[theActualText _ source contents.\\n\\t\\t\\t[tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]]\\n\\t\\t\\t\\twhileTrue: [tempsMark _ tempsMark + 1]].\\n\\t\\t\\t^ #()].\\n\\tvars _ OrderedCollection new.\\n\\t[hereType == #word]\\n\\t\\twhileTrue: [vars addLast: (encoder bindTemp: self advance in: methodSelector)].\\n\\t(self match: #verticalBar) ifTrue: \\n\\t\\t[tempsMark _ prevMark.\\n\\t\\t^ vars].\\n\\t^ self expected: 'Vertical bar'! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'crl 2/26/1999 12:22'!\\ntemporaryBlockVariables\\n\\t\\\"Scan and answer temporary block variables.\\\"\\n\\n\\t| variables |\\n\\n\\t(self match: #verticalBar) ifFalse: [\\n\\t\\t\\\"There are't any temporary variables.\\\"\\n\\t\\t^#()].\\n\\n\\tvariables _ OrderedCollection new.\\n\\t[hereType == #word] whileTrue: [variables addLast: (encoder bindBlockTemp: self advance)].\\n\\t(self match: #verticalBar) ifTrue: [^variables].\\n\\t^self expected: 'Vertical bar'! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 12/4/1999 21:04'!\\nvariable\\n\\n\\t| varName varStart varEnd |\\n\\tvarStart _ self startOfNextToken + requestorOffset.\\n\\tvarName _ self advance.\\n\\tvarEnd _ self endOfLastToken + requestorOffset.\\n\\t^ encoder encodeVariable: varName\\n\\t\\tsourceRange: (varStart to: varEnd)\\n\\t\\tifUnknown: [self correctVariable: varName interval: (varStart to: varEnd)]! !\\n\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:50'!\\naddPragma: aPragma\\n\\tself properties addPragma: aPragma.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 21:02'!\\npragmaLiteral\\n\\t\\\"Read a pragma literal.\\\"\\n\\n\\t(hereType == #string or: [ hereType == #literal or: [ hereType == #number ] ])\\n\\t\\tifTrue: [ ^ self advance ].\\n\\t(here == $# and: [ tokenType == #word ])\\n\\t\\tifTrue: [ ^ self advance ].\\n\\t(here == #- and: [ tokenType == #number ])\\n\\t\\tifTrue: [ ^ (self advance; advance) negated ].\\n\\t(here = 'true' or: [ here = 'false' or: [ here = 'nil' or: [ Smalltalk hasClassNamed: here ] ] ])\\n\\t\\tifTrue: [ ^ Compiler evaluate: self advance ].\\n\\t^ self expected: 'Literal constant'.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:23'!\\npragmaPrimitives\\n\\t| primitives |\\n\\tprimitives := self properties pragmas select: [ :each | \\n\\t\\t#( primitive: primitive:module: ) \\n\\t\\t\\tincludes: each keyword ].\\n\\tprimitives isEmpty \\n\\t\\tifTrue: [ ^ 0 ].\\n\\tprimitives size = 1 \\n\\t\\tifFalse: [ ^ self notify: 'Ambigous primitives' ].\\n\\t^ primitives first message sendTo: self.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:23'!\\npragmaSequence\\n\\t\\\"Parse a sequence of method pragmas.\\\"\\n\\t\\n\\t[ true ] whileTrue: [\\n\\t\\t(self matchToken: #<)\\n\\t\\t\\tifFalse: [ ^ self ].\\n\\t\\tself pragmaStatement.\\n\\t\\t(self matchToken: \";\n r = \"{7689049, 2109470}\";\n s = 1;\n },\n {\n l = \"instance or #class> <selector name>), and with a string to be produced as part of the error msg if any of the methods affected is reached\\\"\\n\\n\\t| aClass sel keywords codeString |\\n\\ttripletList do:\\n\\t\\t[:triplet | \\n\\t\\t\\t(aClass _ (Smalltalk at: triplet first ifAbsent: [nil])) notNil ifTrue:\\n\\t\\t\\t\\t[triplet second == #class ifTrue:\\n\\t\\t\\t\\t\\t[aClass _ aClass class].\\n\\t\\t\\t\\tsel _ triplet third.\\n\\t\\t\\t\\tkeywords _ sel keywords.\\n\\t\\t\\t\\t(keywords size == 1 and: [keywords first asSymbol isKeyword not])\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[codeString _ keywords first asString]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[codeString _ ''.\\n\\t\\t\\t\\t\\t\\tkeywords withIndexDo:\\n\\t\\t\\t\\t\\t\\t\\t[:kwd :index |\\n\\t\\t\\t\\t\\t\\t\\t\\tcodeString _ codeString, ' ', (keywords at: index), ' ',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t'arg', index printString]].\\n\\t\\t\\t\\tcodeString _ codeString, '\\n\\tself codeStrippedOut: ', (messageString surroundedBySingleQuotes).\\n\\n\\t\\t\\t\\taClass compile: codeString classified: 'stripped']]! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nextraVMMemory\\n\\t\\\"Answer the current setting of the 'extraVMMemory' VM parameter. See the comment in extraVMMemory: for details.\\\"\\n\\n\\t^ self vmParameterAt: 23\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nextraVMMemory: extraBytesToReserve\\n\\t\\\"Request that the given amount of extra memory be reserved for use by the virtual machine to leave extra C heap space available for things like plugins, network and file buffers, and so on. This request is stored when the image is saved and honored when the image is next started up. Answer the previous value of this parameter.\\\"\\n\\n\\textraBytesToReserve < 0\\n\\t\\tifTrue: [self error: 'VM memory reservation must be non-negative'].\\n\\t^ self vmParameterAt: 23 put: extraBytesToReserve\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:47'!\\ngetVMParameters\\t\\n\\t\\\"Answer an Array containing the current values of the VM's internal\\n\\tparameter/metric registers. Each value is stored in the array at the\\n\\tindex corresponding to its VM register. (See #vmParameterAt: and\\n\\t#vmParameterAt:put:.)\\\"\\n\\t\\\"SmalltalkImage current getVMParameters\\\"\\n\\t\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'tpr 4/27/2005 11:03'!\\nvmParameterAt: parameterIndex\\n\\t\\\"parameterIndex is a positive integer corresponding to one of the VM's internal\\n\\tparameter/metric registers. Answer with the current value of that register.\\n\\tFail if parameterIndex has no corresponding register.\\n\\tVM parameters are numbered as follows:\\n\\t\\t1\\tend of old-space (0-based, read-only)\\n\\t\\t2\\tend of young-space (read-only)\\n\\t\\t3\\tend of memory (read-only)\\n\\t\\t4\\tallocationCount (read-only)\\n\\t\\t5\\tallocations between GCs (read-write)\\n\\t\\t6\\tsurvivor count tenuring threshold (read-write)\\n\\t\\t7\\tfull GCs since startup (read-only)\\n\\t\\t8\\ttotal milliseconds in full GCs since startup (read-only)\\n\\t\\t9\\tincremental GCs since startup (read-only)\\n\\t\\t10\\ttotal milliseconds in incremental GCs since startup (read-only)\\n\\t\\t11\\ttenures of surving objects since startup (read-only)\\n\\t\\t12-20 specific to the translating VM\\n\\t\\t21\\troot table size (read-only)\\n\\t\\t22\\troot table overflows since startup (read-only)\\n\\t\\t23\\tbytes of extra memory to reserve for VM buffers, plugins, etc.\\n\\n\\t\\t24\\tmemory threshold above which shrinking object memory (rw)\\n\\t\\t25\\tmemory headroom when growing object memory (rw)\\n\\t\\t26 interruptChecksEveryNms - force an ioProcessEvents every N milliseconds, in case the image is not calling getNextEvent often (rw)\\n\\t\\t27\\tnumber of times mark loop iterated for current IGC/FGC (read-only) includes ALL marking\\n\\t\\t28\\tnumber of times sweep loop iterated for current IGC/FGC (read-only)\\n\\t\\t29\\tnumber of times make forward loop iterated for current IGC/FGC (read-only)\\n\\t\\t30\\tnumber of times compact move loop iterated for current IGC/FGC (read-only)\\n\\t\\t31\\tnumber of grow memory requests (read-only)\\n\\t\\t32\\tnumber of shrink memory requests (read-only)\\n\\t\\t33\\tnumber of root table entries used for current IGC/FGC (read-only)\\n\\t\\t34\\tnumber of allocations done before current IGC/FGC (read-only)\\n\\t\\t35\\tnumber of survivor objects after current IGC/FGC (read-only)\\n\\t\\t36 millisecond clock when current IGC/FGC completed (read-only)\\n\\t\\t37 number of marked objects for Roots of the world, not including Root Table entries for current IGC/FGC (read-only)\\n\\t\\t38 milliseconds taken by current IGC (read-only)\\n\\t\\t39 Number of finalization signals for Weak Objects pending when current IGC/FGC completed (read-only)\\n\\t\\t40 VM word size - 4 or 8 (read-only)\\\"\\n\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nvmParameterAt: parameterIndex put: newValue\\n\\t\\\"parameterIndex is a positive integer corresponding to one of the VM's internal\\n\\tparameter/metric registers. Store newValue (a positive integer) into that\\n\\tregister and answer with the previous value that was stored there.\\n\\tFail if newValue is out of range, if parameterIndex has no corresponding\\n\\tregister, or if the corresponding register is read-only.\\\"\\n\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\nclearProfile\\n\\t\\\"Clear the profile database.\\\"\\n\\n\\t<primitive: 250>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\ndumpProfile\\n\\t\\\"Dump the profile database to a file.\\\"\\n\\n\\t<primitive: 251>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\nprofile: aBlock\\n\\t\\\"Make a virtual machine profile of the given block.\\\"\\n\\t\\\"Note: Profiling support is provided so that VM implementors\\n\\t can better understand and improve the efficiency of the virtual\\n\\t machine. To use it, you must be running a version of the\\n\\t virtual machine compiled with profiling enabled (which\\n\\t makes it much slower than normal even when not profiling).\\n\\t You will also need the CodeWarrior profile reader application.\\\"\\n\\n\\tself stopProfiling.\\n\\tself clearProfile.\\n\\tself startProfiling.\\n\\taBlock value.\\n\\tself stopProfiling.\\n\\tself dumpProfile.! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:55'!\\nstartProfiling\\n\\t\\\"Start profiling the virtual machine.\\\"\\n\\n\\t<primitive: 252>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:55'!\\nstopProfiling\\n\\t\\\"Stop profiling the virtual machine.\\\"\\n\\n\\t<primitive: 253>\\n! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 7/2/2003 21:45'!\\ntextMarkerForShortReport\\n\\n\\t^ 'Since last view\\t'! !\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 9/30/2003 13:53'!\\nvmStatisticsReportString\\n\\t\\\"StringHolderView open: (StringHolder new contents:\\n\\t\\tSmalltalkImage current vmStatisticsReportString) label: 'VM Statistics'\\\"\\n\\n\\t| params oldSpaceEnd youngSpaceEnd memoryEnd fullGCs fullGCTime incrGCs incrGCTime tenureCount mcMisses mcHits icHits upTime sendCount tms tmSize upTime2 fullGCs2 fullGCTime2 incrGCs2 incrGCTime2 tenureCount2 str |\\n\\tparams _ self getVMParameters.\\n\\toldSpaceEnd\\t\\t\\t_ params at: 1.\\n\\tyoungSpaceEnd\\t\\t_ params at: 2.\\n\\tmemoryEnd\\t\\t\\t_ params at: 3.\\n\\tfullGCs\\t\\t\\t\\t_ params at: 7.\\n\\tfullGCTime\\t\\t\\t_ params at: 8.\\n\\tincrGCs\\t\\t\\t\\t_ params at: 9.\\n\\tincrGCTime\\t\\t\\t_ params at: 10.\\n\\ttenureCount\\t\\t\\t_ params at: 11.\\n\\tmcMisses\\t\\t\\t_ params at: 15.\\n\\tmcHits\\t\\t\\t\\t_ params at: 16.\\n\\ticHits\\t\\t\\t\\t_ params at: 17.\\n\\tupTime _ Time millisecondClockValue.\\n\\tsendCount _ mcMisses + mcHits + icHits.\\n\\ttms _ TranslatedMethod allSubInstances.\\n\\ttmSize _ tms inject: 0 into: [:sum :tm | sum + (tm size * 4)].\\n\\n\\tstr _ WriteStream on: (String new: 1000).\\n\\tstr\\tnextPutAll: 'uptime\\t\\t\\t';\\n\\t\\tprint: (upTime / 1000 / 60 // 60); nextPut: $h;\\n\\t\\tprint: (upTime / 1000 / 60 \\\\\\\\ 60) asInteger; nextPut: $m;\\n\\t\\tprint: (upTime / 1000 \\\\\\\\ 60) asInteger; nextPut: $s; cr.\\n\\n\\tstr\\tnextPutAll: 'memory\\t\\t\\t';\\n\\t\\tnextPutAll: memoryEnd asStringWithCommas; nextPutAll: ' bytes'; cr.\\n\\tstr\\tnextPutAll:\\t'\\told\\t\\t\\t';\\n\\t\\tnextPutAll: oldSpaceEnd asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tyoung\\t\\t';\\n\\t\\tnextPutAll: (youngSpaceEnd - oldSpaceEnd) asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((youngSpaceEnd - oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tused\\t\\t';\\n\\t\\tnextPutAll: youngSpaceEnd asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tfree\\t\\t';\\n\\t\\tnextPutAll: (memoryEnd - youngSpaceEnd) asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((memoryEnd - youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\n\\tstr\\tnextPutAll: 'GCs\\t\\t\\t\\t';\\n\\t\\tnextPutAll: (fullGCs + incrGCs) asStringWithCommas.\\n\\tfullGCs + incrGCs > 0 ifTrue: [\\n\\t\\tstr\\n\\t\\t\\tnextPutAll: ' ('; \\n\\t\\t\\tprint: ((upTime / (fullGCs + incrGCs)) roundTo: 1); \\n\\t\\t\\tnextPutAll: 'ms between GCs)'\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\tprint: fullGCs; nextPutAll: ' totalling '; nextPutAll: fullGCTime asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((fullGCTime / upTime * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime)'.\\n\\tfullGCs = 0 ifFalse:\\n\\t\\t[str\\tnextPutAll: ', avg '; print: ((fullGCTime / fullGCs) roundTo: 1.0); nextPutAll: 'ms'].\\n\\tstr\\tcr.\\n\\tstr\\tnextPutAll: '\\tincr\\t\\t';\\n\\t\\tprint: incrGCs; nextPutAll: ' totalling '; nextPutAll: incrGCTime asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((incrGCTime / upTime * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime), avg '; print: ((incrGCTime / incrGCs) roundTo: 1.0); nextPutAll: 'ms'; cr.\\n\\tstr\\tnextPutAll: '\\ttenures\\t\\t';\\n\\t\\tnextPutAll: tenureCount asStringWithCommas.\\n\\ttenureCount = 0 ifFalse:\\n\\t\\t[str nextPutAll: ' (avg '; print: (incrGCs / tenureCount) asInteger; nextPutAll: ' GCs/tenure)'].\\n\\tstr\\tcr.\\n\\nLastStats ifNil: [LastStats _ Array new: 6]\\nifNotNil: [\\n\\tupTime2 _ upTime - (LastStats at: 1).\\n\\tfullGCs2 _ fullGCs - (LastStats at: 2).\\n\\tfullGCTime2 _ fullGCTime - (LastStats at: 3).\\n\\tincrGCs2 _ incrGCs - (LastStats at: 4).\\n\\tincrGCTime2 _ incrGCTime - (LastStats at: 5).\\n\\ttenureCount2 _ tenureCount - (LastStats at: 6).\\n\\n\\tstr\\tnextPutAll: self textMarkerForShortReport ;\\n\\t\\tnextPutAll: (fullGCs2 + incrGCs2) asStringWithCommas.\\n\\tfullGCs2 + incrGCs2 > 0 ifTrue: [\\n\\t\\tstr\\n\\t\\t\\tnextPutAll: ' ('; \\n\\t\\t\\tprint: ((upTime2 / (fullGCs2 + incrGCs2)) roundTo: 1); \\n\\t\\t\\tnextPutAll: 'ms between GCs)'.\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\tuptime\\t\\t'; print: ((upTime2 / 1000.0) roundTo: 0.1); nextPutAll: 's'; cr.\\n\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\tprint: fullGCs2; nextPutAll: ' totalling '; nextPutAll: fullGCTime2 asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((fullGCTime2 / upTime2 * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime)'.\\n\\tfullGCs2 = 0 ifFalse:\\n\\t\\t[str\\tnextPutAll: ', avg '; print: ((fullGCTime2 / fullGCs2) roundTo: 1.0); nextPutAll: 'ms'].\\n\\tstr\\tcr.\\n\\tstr\\tnextPutAll: '\\tincr\\t\\t';\\n\\t\\tprint: incrGCs2; nextPutAll: ' totalling '; nextPutAll: incrGCTime2 asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((incrGCTime2 / upTime2 * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime), avg '.\\n\\tincrGCs2 > 0 ifTrue: [\\n\\t\\t str print: ((incrGCTime2 / incrGCs2) roundTo: 1.0); nextPutAll: 'ms'\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\ttenures\\t\\t';\\n\\t\\tnextPutAll: tenureCount2 asStringWithCommas.\\n\\ttenureCount2 = 0 ifFalse:\\n\\t\\t[str nextPutAll: ' (avg '; print: (incrGCs2 / tenureCount2) asInteger; nextPutAll: ' GCs/tenure)'].\\n\\tstr\\tcr.\\n].\\n\\tLastStats at: 1 put: upTime.\\n\\tLastStats at: 2 put: fullGCs.\\n\\tLastStats at: 3 put: fullGCTime.\\n\\tLastStats at: 4 put: incrGCs.\\n\\tLastStats at: 5 put: incrGCTime.\\n\\tLastStats at: 6 put: tenureCount.\\n\\n\\tsendCount > 0 ifTrue: [\\n\\t\\tstr\\tnextPutAll: 'sends\\t\\t\\t';\\n\\t\\t\\tnextPutAll: sendCount asStringWithCommas; cr.\\n\\t\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\t\\tnextPutAll: mcMisses asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((mcMisses / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tm-cache\\t';\\n\\t\\t\\tnextPutAll: mcHits asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((mcHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\t\\tstr\\tnextPutAll: '\\ti-cache\\t\\t';\\n\\t\\t\\tnextPutAll: icHits asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((icHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr].\\n\\n\\ticHits > 0 ifTrue: [\\n\\t\\tstr\\tnextPutAll: 'methods\\t\\t\\t';\\n\\t\\t\\tnextPutAll: tms size asStringWithCommas; nextPutAll: ' translated'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tsize\\t\\t\\t';\\n\\t\\t\\tnextPutAll: tmSize asStringWithCommas; nextPutAll: ' bytes, avg ';\\n\\t\\t\\tprint: ((tmSize / tms size) roundTo: 0.1); nextPutAll: ' bytes/method'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tmemory\\t\\t';\\n\\t\\t\\tprint: ((tmSize / youngSpaceEnd * 100) roundTo: 0.1); nextPutAll: '% of used, ';\\n\\t\\t\\tprint: ((tmSize / memoryEnd * 100) roundTo: 0.1); nextPutAll: '% of available'; cr].\\n\\n\\t^ str contents\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 9/30/2003 13:54'!\\nvmStatisticsShortString\\n\\t\\\"Convenience item for access to recent statistics only\\\"\\n\\t\\\"StringHolderView open: (StringHolder new contents: SmalltalkImage current vmStatisticsShortString)\\n\\t\\tlabel: 'VM Recent Statistics'\\\"\\n\\n\\t^ (ReadStream on: self vmStatisticsReportString) upToAll: 'Since'; upTo: Character cr; upToEnd\\n! !\\n\\n\\n!SmalltalkImage methodsFor: 'private source file' stamp: 'sd 9/24/2003 12:42'!\\nsourceFileVersionString: aString\\n\\n\\tSourceFileVersionString := aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSmalltalkImage class\\n\\tinstanceVariableNames: 'current'!\\n\\n!SmalltalkImage class methodsFor: 'class initialization' stamp: 'yo 2/18/2004 18:26'!\\ninitialize\\n\\\"\\n\\tself initialize\\n\\\"\\n\\tSmalltalk addToStartUpList: SmalltalkImage.\\n\\tSmalltalkImage startUp.\\n! !\\n\\n!SmalltalkImage class methodsFor: 'class initialization' stamp: 'yo 2/18/2004 18:25'!\\nstartUp\\n\\n\\tEndianCache _ nil.\\n! !\\n\\n\\n!SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 14:28'!\\ncurrent\\n\\t\\\"Note that this could be implemented differently to avoid the test\\\"\\n\\n\\tcurrent isNil\\n\\t\\tifTrue: [current := self basicNew].\\n\\t^ current! !\\n\\n!SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 13:39'!\\nnew\\n\\n\\tself error: 'Use current'.! !\\nReferenceStream subclass: #SmartRefStream\\n\\tinstanceVariableNames: 'structures steady reshaped renamed renamedConv superclasses progressBar objCount classInstVars'\\n\\tclassVariableNames: 'ScannedObject'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Object Storage'!\\n!SmartRefStream commentStamp: '<historical>' prior: 0!\\nOrdinary ReferenceStreams assume that the names and order of instance variables is exactly the same when an object file is written and read. \\n\\tSmartRefStream allows object files to be read even after instance variables have changed or the entire class has been renamed.\\n\\nWhen an object file is written, no one knows how the classes will change in the future. Therefore, all conversion must be done when the file is read. The key is to store enough information in the file about the names of the instance variables of all outgoing classes. \\n\\nSmartRefStream works best with only one tree of objects per file. You can nextPut: more than once, but each object tree gets its own class structure description, which is big. \\n\\nConversion of old objects is done by a method in each class called (convertToCurrentVersion: varDict refStream: smartRefStrm). At fileOut time, ChangeSet>>checkForConversionMethods creates a prototype of this method (if Preference #conversionMethodsAtFileOut is true). The programmer must edit this method to (1) test if the incoming object needs conversion, (2) put non-nil values into any new inst vars that need them, and (3) save the data of any inst vars that are being deleted. \\n\\nDetermining which old version is represented by the incoming object can be done in several ways: noticing that a current inst var is nil when it should have data, noticing that there is an older inst var name in the variable dictionary (varDict), checking kinds of objects in one or more inst vars, or retrieving the classVersion of the incoming object from the ref stream. \\n\\nIf a class is renamed, a method goes into SmartRefStream telling the new name. The conversion method of the new class must be prepared to accept instances of the old class also. If no inst var names have changed, the conversion method does nothing.\\n\\nAn example: \\n\\tSuppose we change the representation of class Rectangle from ('origin' 'corner') to ('origin' 'extent'). Suppose lots of Rectangle instances are already out on files (in .pr project files, especially). \\n\\tThe programmer changes the class definition, modifies all the methods, and filesOut. A series of dialogs appear, asking if instances Rectangle might be in an object file, if 'extent' needs to be non-nil (yes), and if the info in 'corner' needs to be preserved (yes). This method appears:\\n\\nRectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\\"These variables are automatically stored into the new instance: #('origin').\\n\\tTest for this particular conversion. Get values using expressions like (varDict at: 'foo').\\\"\\n\\n\\t\\\"New variables: #('extent'). If a non-nil value is needed, please assign it.\\\"\\n\\t\\\"These are going away #('corner'). Possibly store their info in some other variable?\\\"\\n\\t\\\"Move your code above the ^ super... Delete extra comments.\\\"\\n\\t^ super convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\nThe programmer modifies it to be:\\n\\nRectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n(varDict includesKey: 'extent') ifFalse: [\\\"old version!!\\\"\\n\\t\\\"Create the new extent, and preserve the info from the old corner\\\"\\n\\textent _ (varDict at: 'corner') - origin.\\n\\t].\\n^ super convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\tThis conversion method stays in the system and is ready to convert the old format of Rectangle whenever one is encountered in an object file. Note that the subclasses of Rectangle, (B3DViewport, CharacterBlock, and Quadrangle) do not need conversion methods. Their instances will be converted by the code in Rectangle. \\n\\n\\tFiles written by SmartRefStream are in standard fileout format. You can mix raw objects with code to be filed in. The file starts out in the normal fileOut format. Definitions of new classes on the front.\\n\\nstructures \\tDictionary of (#Rectangle -> #(<classVersionInteger> 'origin' 'corner')). Inst \\n\\t\\t\\t\\tvar names are strings.\\nsteady \\t\\tSet of Classes who have the same structure now as on the incoming file.\\n\\t\\t\\t\\tIncludes classes with same inst vars except for new ones added on the end.\\nreshaped \\tDictionary of Classes who have a different structure now from the incoming file. \\n\\t\\t\\t\\tIncludes those with same inst vars but new version number.\\n\\t\\t\\t\\t(old class name -> method selector to fill in data for version to version)\\nrenamed\\tDictionary of Classes who have a different name. Make an instance of the new\\n\\t\\t\\tclass, and send it the conversion call.\\n\\t\\t\\t\\t(old class name symbol -> new class name). \\nrenamedConv\\tDictionary of conversion selector for Classes who have a different name.\\n\\t\\t\\t\\t(old class name symbol -> conversion selector). \\ntopCall\\t\\tTells if next or nextPut: are working on the top object in the tree. \\n\\t\\t\\tnil if outside, the top object if deep inside.\\n\\nSee DataStream.typeIDFor: for where the tangle of objects is clipped, so the whole system will not be written on the file.\\n\\nNo object that is written on the file is ever a class. All class definitions are filed in. A class may be stored inside an ImageSegment that itself is stored in a SmartRefStream.\\n\\nUniClasses are classes for the instance specific behavior of just one instance. Subclasses of Player are an example. When a UniClass is read in, and a class of the same name already exists, the incoming one is renamed. ObjectScanner converts the filed-in code.\\n\\nValues in instance variables of UniClasses are stored in the array that tells the class structure. It is the fourth of the four top level objects. #(version (class-structure) the-object ((#Player25 scripts slotInfo costumeDictionary) (#Player26 scripts slotInfo costumeDictionary))).\\n\\nThere is a separate subclass for doing veryDeepCopy (in memory). Currently, any object for which objectToStoreOnDataStream return an object other than self, does this: The new object (a DiskProxy) is traced. When it comes time to go through the fields of the old object, they are not found as keys in references (DiskProxies are there instead). So the old field value is left in the new object. That is OK for StrikeFont, Class, MetaClass, DisplayScreen. But the DiskProxies are evaluated, which takes a lot of time.\\n\\nSome metaclasses are put into the structures table. This is for when a block has a receiver that is a class. See checkFatalReshape:.\\n\\nImageSegments:\\n\\tA ReferenceStream is used to enumerate objects to put inside an ImageSegment. If an instance of a UniClass is seen, the class is put in also.\\n\\tA SmartRefStream is used to store the ImageSegment. Roots are nil, and the segment is a wordArray. We are encoding the outPointers. Structures contains all classes from both places. Must filter out UniClasses for some things, and do include them for putting source code at end of file. Do not write any class inst vars in file.\\n\\n--Ted Kaehler and Bob Arning.\\n!\\n\\n\\n!SmartRefStream methodsFor: 'accessing' stamp: 'tk 5/19/1999 15:47'!\\nstructures: anObject\\n\\tstructures _ anObject! !\\n\\n!SmartRefStream methodsFor: 'accessing' stamp: 'tk 5/19/1999 15:47'!\\nsuperclasses: anObject\\n\\tsuperclasses _ anObject! !\\n\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 1/7/97'!\\ncatalogValues: instVarList size: varsOnDisk\\n\\t\\\"Create a dictionary of (name -> value) for the inst vars of this reshaped object. Indexed vars as (1 -> val) etc. \\\"\\n\\n\\t| dict sz |\\n\\tdict _ Dictionary new.\\n\\t2 to: instVarList size do: [:ind |\\n\\t\\tdict at: (instVarList at: ind) put: self next].\\n\\tsz _ varsOnDisk - (instVarList size - 1).\\n\\t1 to: sz do: [:ii | \\n\\t\\tdict at: ii put: self next].\\n\\t\\\"Total number read MUST be equal to varsOnDisk!!\\\"\\n\\tsz > 0 ifTrue: [dict at: #SizeOfVariablePart put: sz].\\n\\t^ dict! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'ar 9/27/2005 22:41'!\\nconversionMethodsFor: classList\\n\\t| oldStruct newStruct list |\\n\\t\\\"Each of these needs a conversion method. Hard part is the comment in it. Return a MessageSet.\\\"\\n\\n\\tlist _ OrderedCollection new.\\n\\tclassList do: [:cls |\\n\\t\\toldStruct _ structures at: cls name ifAbsent: [#()].\\n\\t\\tnewStruct _ (Array with: cls classVersion), (cls allInstVarNames).\\n\\t\\tself writeConversionMethodIn: cls fromInstVars: oldStruct to: newStruct \\n\\t\\t\\t\\trenamedFrom: nil.\\n\\t\\tlist add: cls name, ' convertToCurrentVersion:refStream:'.\\n\\t\\t].\\n\\n\\t^list.! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 5/26/97'!\\nstoreInstVarsIn: anObject from: dict\\n\\t\\\"For instance variables with the same names, store them in the new instance. Values in variable-length part also. This is NOT the normal inst var transfer!! See Object.readDataFrom:size:. This is for when inst var names have changed and some additional conversion is needed. Here we handle the unchanged vars. \\\"\\n\\n\\t(anObject class allInstVarNames) doWithIndex: [:varName :index |\\n\\t\\t(dict includesKey: varName) ifTrue: [\\n\\t\\t\\tanObject instVarAt: index put: (dict at: varName)]].\\n\\t\\\"variable part\\\"\\n\\t(dict includesKey: #SizeOfVariablePart) ifFalse: [^ anObject].\\n\\t1 to: (dict at: #SizeOfVariablePart) do: [:index | \\n\\t\\tanObject basicAt: index put: (dict at: index)].\\n\\t^ anObject! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 6/8/2001 09:57'!\\nwriteClassRename: newName was: oldName\\n\\t\\\"Write a method that tells which modern class to map instances to.\\\"\\n\\t| oldVer sel code |\\n\\n\\toldVer _ self versionSymbol: (structures at: oldName).\\n\\tsel _ oldName asString.\\n\\tsel at: 1 put: (sel at: 1) asLowercase.\\n\\tsel _ sel, oldVer.\\t\\\"i.e. #rectangleoc4\\\"\\n\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode nextPutAll: sel; cr.\\n\\tcode cr; tab; nextPutAll: '^ ', newName.\\t\\\"Return new class\\\"\\n\\n\\tself class compile: code contents classified: 'conversion'.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'CdG 10/17/2005 21:01'!\\nwriteClassRenameMethod: sel was: oldName fromInstVars: oldList\\n\\t\\\"The class coming is unknown. Ask the user for the existing class it maps to. If got one, write a method, and restart the obj fileIn. If none, write a dummy method and get the user to complete it later. \\\"\\n\\n| tell choice newName answ code |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\ntell := 'Reading an instance of ', oldName, '.\\nWhich modern class should it translate to?'.\\nansw := (UIManager default \\n\\t\\tchooseFrom: #('Let me type the name now' 'Let me think about it'\\n'Let me find a conversion file on the disk') \\n\\t\\ttitle: tell). \\n\\nansw = 1 ifTrue: [\\n\\ttell := 'Name of the modern class {1} should translate to:' translated format: {oldName}.\\n\\tchoice := UIManager default request: tell.\\t\\t\\\"class name\\\"\\n\\t(choice size = 0) \\n\\t\\tifTrue: [answ := 'conversion method needed']\\n\\t\\tifFalse: [newName := choice.\\n\\t\\t\\tansw := Smalltalk at: newName asSymbol \\n\\t\\t\\t\\tifAbsent: ['conversion method needed'].\\n\\t\\t\\tansw isString ifFalse: [renamed at: oldName asSymbol put: answ name]]].\\n(answ = 3) | (answ = 0) ifTrue: [self close.\\n\\t\\t^ 'conversion method needed'].\\nansw = 2 ifTrue: [answ := 'conversion method needed'].\\nansw = 'conversion method needed' ifTrue: [\\n\\t\\tself close. \\n\\t\\tnewName := 'PutNewClassHere'].\\n\\ncode := WriteStream on: (String new: 500).\\ncode nextPutAll: sel; cr.\\ncode cr; tab; nextPutAll: '^ ', newName.\\t\\\"Return new class\\\"\\n\\nself class compile: code contents classified: 'conversion'.\\n\\nnewName = 'PutNewClassHere' ifTrue: [\\n\\tself inform: 'Please complete the following method and \\nthen read-in the object file again.'.\\n\\tSystemNavigation default browseAllImplementorsOf: sel asSymbol]. \\n\\n\\t\\\"The class version number only needs to change under one specific circumstance. That is when the first letters of the instance variables have stayed the same, but their meaning has changed. A conversion method is needed, but this system does not know it. \\n\\tIf this is true for class Foo, define classVersion in Foo class. \\n\\tBeware of previous object fileouts already written after the change in meaning, but before bumping the version number. They have the old (wrong) version number, say 2. If this is true, your method must be able to test the data and successfully read files that say version 2 but are really 3.\\\"\\n\\n\\t^ answ! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 6/7/2001 13:02'!\\nwriteConversionMethod: sel class: newClass was: oldName fromInstVars: oldList to: newList\\n\\t\\\"The method convertToCurrentVersion:refStream: was not found in newClass. Write a default conversion method for the author to modify.\\\"\\n\\n\\t| code newOthers oldOthers copied |\\n\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode nextPutAll: 'convertToCurrentVersion: varDict refStream: smartRefStrm'; cr; tab.\\n\\tnewOthers _ newList asOrderedCollection \\\"copy\\\".\\n\\toldOthers _ oldList asOrderedCollection \\\"copy\\\".\\n\\tcopied _ OrderedCollection new.\\n\\tnewList do: [:instVar |\\n\\t\\t(oldList includes: instVar) ifTrue: [\\n\\t\\t\\tinstVar isInteger ifFalse: [copied add: instVar].\\n\\t\\t\\tnewOthers remove: instVar.\\n\\t\\t\\toldOthers remove: instVar]].\\n\\tcode nextPutAll: '\\\"These variables are automatically stored into the new instance '.\\n\\tcode nextPutAll: copied asArray printString; nextPut: $. .\\n\\tcode cr; tab; nextPutAll: 'This method is for additional changes.'; \\n\\t\\tnextPutAll: ' Use statements like (foo _ varDict at: ''foo'').\\\"'; cr; cr; tab.\\n\\t(newOthers size = 0) & (oldOthers size = 0) ifTrue: [^ self].\\n\\t\\t\\\"Instance variables are the same. Only the order changed. No conversion needed.\\\"\\n\\t(newOthers size > 0) ifTrue: [code nextPutAll: '\\\"New variables: ', newOthers asArray printString, ' If a non-nil value is needed, please assign it.\\\"\\\\' withCRs].\\n\\t(oldOthers size > 0) ifTrue: [code nextPutAll: '\\t\\\"These are going away ', oldOthers asArray printString, '. Possibly store their info in some other variable?\\\"'].\\n\\n\\tcode cr; tab.\\n\\tcode nextPutAll: '^ super convertToCurrentVersion: varDict refStream: smartRefStrm'.\\n\\tnewClass compile: code contents classified: 'object fileIn'.\\n\\n\\n\\t\\\"If you write a conversion method beware that the class may need a version number change. This only happens when two conversion methods in the same class have the same selector name. (A) The inst var lists of the new and old versions intials as some older set of new and old inst var lists. or (B) Twice in a row, the class needs a conversion method, but the inst vars stay the same the whole time. (For an internal format change.)\\n\\tIf either is the case, fileouts already written with the old (wrong) version number, say 2. Your method must be able to read files that say version 2 but are really 3, until you expunge the erroneous version 2 files from the universe.\\\"\\n\\n ! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'nk 7/29/2004 10:10'!\\nwriteConversionMethodIn: newClass fromInstVars: oldList to: newList renamedFrom: oldName\\n\\t\\\"The method convertToCurrentVersion:refStream: was not found in newClass. Write a default conversion method for the author to modify. If method exists, append new info into the end.\\\"\\n\\n\\t| code newOthers oldOthers copied newCode |\\n\\n\\tnewOthers _ newList asOrderedCollection \\\"copy\\\".\\n\\toldOthers _ oldList asOrderedCollection \\\"copy\\\".\\n\\tcopied _ OrderedCollection new.\\n\\tnewList do: [:instVar |\\n\\t\\t(oldList includes: instVar) ifTrue: [\\n\\t\\t\\tinstVar isInteger ifFalse: [copied add: instVar].\\n\\t\\t\\tnewOthers remove: instVar.\\n\\t\\t\\toldOthers remove: instVar]].\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode cr; cr; tab; nextPutAll: '\\\"From ', SystemVersion current version, ' [', SmalltalkImage current lastUpdateString;\\n\\t\\t\\tnextPutAll: '] on ', Date today printString, '\\\"'; cr.\\n\\tcode tab; nextPutAll: '\\\"These variables are automatically stored into the new instance: '.\\n\\tcode nextPutAll: copied asArray printString; nextPut: $.; cr.\\n\\tcode tab; nextPutAll: 'Test for this particular conversion.'; \\n\\t\\tnextPutAll: ' Get values using expressions like (varDict at: ''foo'').\\\"'; cr; cr.\\n\\t(newOthers size = 0) & (oldOthers size = 0) & (oldName == nil) ifTrue: [^ self].\\n\\t\\t\\\"Instance variables are the same. Only the order changed. No conversion needed.\\\"\\n\\t(newOthers size > 0) ifTrue: [\\n\\t\\tcode tab; nextPutAll: '\\\"New variables: ', newOthers asArray printString, \\n\\t\\t\\t'. If a non-nil value is needed, please assign it.\\\"'; cr].\\n\\t(oldOthers size > 0) ifTrue: [\\n\\t\\tcode tab; nextPutAll: '\\\"These are going away ', oldOthers asArray printString, \\n\\t\\t\\t'. Possibly store their info in some other variable?\\\"'; cr].\\n\\toldName ifNotNil: [\\n\\t\\tcode tab; nextPutAll: '\\\"Test for instances of class ', oldName, '.'; cr.\\n\\t\\tcode tab; nextPutAll: 'Instance vars with the same name have been moved here.\\\"'; cr.\\n\\t\\t].\\n\\tcode tab; nextPutAll: '\\\"Move your code above the ^ super... Delete extra comments.\\\"'; cr. \\n\\n\\t(newClass includesSelector: #convertToCurrentVersion:refStream:) \\n\\t\\tifTrue: [\\\"append to old methods\\\"\\n\\t\\t\\tnewCode _ (newClass sourceCodeAt: #convertToCurrentVersion:refStream:),\\n\\t\\t\\t\\tcode contents]\\n\\t\\tifFalse: [\\\"new method\\\"\\n\\t\\t\\tnewCode _ 'convertToCurrentVersion: varDict refStream: smartRefStrm',\\n\\t\\t\\t\\tcode contents, \\n\\t\\t\\t\\t'\\t^ super convertToCurrentVersion: varDict refStream: smartRefStrm'].\\n\\tnewClass compile: newCode classified: 'object fileIn'.\\n\\n\\n\\t\\\"If you write a conversion method beware that the class may need a version number change. This only happens when two conversion methods in the same class have the same selector name. (A) The inst var lists of the new and old versions intials as some older set of new and old inst var lists. or (B) Twice in a row, the class needs a conversion method, but the inst vars stay the same the whole time. (For an internal format change.)\\n\\tIf either is the case, fileouts already written with the old (wrong) version number, say 2. Your method must be able to read files that say version 2 but are really 3, until you expunge the erroneous version 2 files from the universe.\\\"\\n\\n ! !\\n\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/10/2005 15:44'!\\nabstractStringx0\\n\\n\\t^ String! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 7/29/2005 18:41'!\\nalansTextPlusMorphbosfcebbmsopssrsggshtt0\\n\\n\\t^ TextPlusMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 5/21/1998 06:44'!\\nbookPageMorphbosfcepcbbfgcc0\\n\\t\\\"BookPageMorph->PasteUpMorph. For reading in old BookMorphs.\\\"\\n\\n\\t^ PasteUpMorph\\n! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 5/22/1998 15:03'!\\nclippingMorphbosfcep0\\n\\t^ PasteUpMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 5/21/1998 06:44'!\\nclippingMorphbosfcepc0\\n\\t\\\"ClippingMorph->PasteUpMorph. For reading in old BookMorphs.\\\"\\n\\n\\t^ PasteUpMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 11/3/2000 18:47'!\\ndropShadowMorphbosfces0\\n\\n\\t^ Morph ! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 11/13/97 10:32'!\\ngradientFillbosfcepbbfgcc0\\n\\t^ GradientFillMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 5/21/1998 19:24'!\\nlayoutMorphbosfcepbbochvimol0\\n\\t^ AlignmentMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 5/12/1998 16:18'!\\nlayoutMorphbosfcepcbbochvimol0\\n\\t^ AlignmentMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 10/26/2000 01:55'!\\nmorphicEventtcbks0\\n\\t^ MorphicEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 10/26/2000 00:48'!\\nmorphicSoundEventtcbkss0\\n\\t^ MorphicUnknownEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/12/2005 17:38'!\\nmultiStringx0\\n\\n\\t^ WideString! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/12/2005 17:38'!\\nmultiSymbolx0\\n\\n\\t^ WideSymbol! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 7/8/2001 17:11'!\\nmyMorphbosfce0\\n\\n\\treshaped at: #MyMorph put: #convertbosfce0:bosfce0:.\\n\\t\\t\\\"Be sure to define that conversion method in class Morph\\\"\\n\\t^ Morph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'RAA 10/26/2000 09:43'!\\nnewMorphicEventts0\\n\\n\\t^ MorphicEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'mir 7/12/2002 18:03'!\\nscrollControllermvslrrsmsms0\\n\\n\\t^ MouseMenuController! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 1/14/1999 13:16'!\\ntransparentColorrcc0\\n\\t^ TranslucentColor! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 8/16/2000 16:37'!\\nworldMorphbosfcebbfgccpmcpbttloiairfidcuwhavcdsll0\\n\\t^ 'PutNewClassHere' \\\" <-- Replace this by a class name (no string quotes)\\\"! !\\n\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'tk\\n\\n11/26/2004 05:53'!\\napplyConversionMethodsTo: objectIn className: className varMap: varMap\\n\\n\\t\\\"Modify the object's instance vars to have the proper values\\n\\nfor its new shape. Mostly, fill in defaut values of new inst vars.\\n\\nCan substitute an object of a different class. (Beware: if\\n\\nsubstituted, varMap will not be correct when the new object is asked\\n\\nto convert.)\\\"\\n\\n\\t| anObject prevObject |\\n\\n\\n\\n\\tself flag: #bobconv.\\n\\n\\n\\n\\tanObject _ objectIn.\\n\\n\\t[\\n\\n\\t\\tprevObject _ anObject.\\n\\n\\t\\tanObject _ anObject convertToCurrentVersion: varMap\\n\\nrefStream: self.\\n\\n\\t\\tprevObject == anObject\\n\\n\\t] whileFalse.\\n\\n\\t^anObject\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:08'!\\ncheckFatalReshape: setOfClasses\\n\\t| suspects oldInstVars newInstVars bad className |\\n\\t\\\"Inform the user if any of these classes were reshaped. A block has a method from the old system whose receiver is of this class. The method's inst var references might be wrong. OK if inst vars were only added.\\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsetOfClasses isEmpty ifTrue: [^ self].\\n\\tsuspects _ OrderedCollection new.\\n\\tsetOfClasses do: [:aClass |\\n\\t\\tclassName _ renamed keyAtValue: aClass name ifAbsent: [aClass name].\\n\\t\\toldInstVars _ (structures at: className ifAbsent: [#(0)]) allButFirst.\\t\\t\\\"should be there\\\"\\n\\t\\tnewInstVars _ aClass allInstVarNames.\\n\\t\\toldInstVars size > newInstVars size ifTrue: [bad _ true].\\n\\t\\toldInstVars size = newInstVars size ifTrue: [\\n\\t\\t\\tbad _ oldInstVars ~= newInstVars].\\n\\t\\toldInstVars size < newInstVars size ifTrue: [\\n\\t\\t\\tbad _ oldInstVars ~= (newInstVars copyFrom: 1 to: oldInstVars size)].\\n\\t\\tbad ifTrue: [suspects add: aClass]].\\n\\n\\tsuspects isEmpty ifFalse: [\\n\\t\\tself inform: ('Imported foreign methods will run on instances of:\\\\',\\n\\t\\t\\tsuspects asArray printString, \\n\\t\\t\\t'\\\\whose shape has changed. Errors may occur.') withCRs].! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:06'!\\nconvert1: misShapenInst to: goodClass allVarMaps: allVarMaps\\n\\t\\\"Go through the normal instance conversion process and return a modern object.\\\"\\n\\n\\t| className oldInstVars anObject varMap |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tgoodClass isVariable ifTrue: [\\n\\t\\tgoodClass error: 'shape change for variable class not implemented yet'\\n\\t].\\n\\t(misShapenInst class name beginsWith: 'Fake37') ifFalse: [self error: 'why mapping?'].\\n\\tclassName _ (misShapenInst class name allButFirst: 6) asSymbol.\\n\\toldInstVars _ structures at: className.\\n\\tanObject _ goodClass basicNew.\\n\\n\\tvarMap _ Dictionary new.\\t\\\"later, indexed vars as (1 -> val) etc.\\\"\\n\\t2 to: oldInstVars size do: [:ind |\\n\\t\\tvarMap at: (oldInstVars at: ind) put: (misShapenInst instVarAt: ind-1)].\\n\\tvarMap at: #ClassName put: className.\\t\\\"original\\\"\\n\\tvarMap at: #NewClassName put: goodClass name.\\t\\\"new\\\"\\n\\tself storeInstVarsIn: anObject from: varMap. \\t\\\"ones with the same names\\\"\\n\\tallVarMaps at: misShapenInst put: varMap.\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 17:15'!\\nconvert2: partiallyCorrectInst allVarMaps: allVarMaps\\n\\t\\\"Go through the normal instance conversion process and return a modern object.\\\"\\n\\n\\t| className varMap |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tvarMap _ allVarMaps at: partiallyCorrectInst.\\n\\tclassName _ varMap at: #ClassName.\\t\\\"original\\\"\\n\\t^self applyConversionMethodsTo: partiallyCorrectInst className: className varMap: varMap.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'ar 4/12/2005 18:06'!\\nmapClass: newClass origName: originalName\\n\\t\\\"See if instances changed shape. If so, make a fake class for the old shape and return it. Remember the original class name.\\\"\\n\\n\\t| newName oldInstVars fakeClass |\\n\\tnewClass isMeta ifTrue: [^ newClass].\\n\\tnewName _ newClass name.\\n\\t(steady includes: newClass) & (newName == originalName) ifTrue: [^ newClass].\\n\\t\\t\\\"instances in the segment have the right shape\\\"\\n\\toldInstVars _ structures at: originalName ifAbsent: [\\n\\t\\t\\tself error: 'class is not in structures list'].\\t\\\"Missing in object file\\\"\\n\\n\\t\\\"Allow mapping from old to new string names\\\"\\n\\t(newName == #ByteString and:[originalName == #String]) ifTrue:[^newClass].\\n\\t(newName == #WideString and:[originalName == #MultiString]) ifTrue:[^newClass].\\n\\t(newName == #WideSymbol and:[originalName == #MultiSymbol]) ifTrue:[^newClass].\\n\\n\\tfakeClass _ Object subclass: ('Fake37', originalName) asSymbol\\n\\t\\tinstanceVariableNames: oldInstVars allButFirst\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: 'Obsolete'.\\n\\tChangeSet current removeClassChanges: fakeClass name.\\t\\\"reduce clutter\\\"\\n\\t^ fakeClass\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:09'!\\nreshapedClassesIn: outPointers\\n\\t\\\"Look for classes in the outPointer array that have changed shape. Make a fake class for the old shape. Return a dictionary mapping Fake classes to Real classes. Substitute fake classes for real ones in outPointers.\\\"\\n\\n\\t| mapFakeClassesToReal fakeCls originalName |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tmapFakeClassesToReal _ IdentityDictionary new.\\n\\toutPointers withIndexDo: [:outp :ind | \\n\\t\\toutp isBehavior ifTrue: [\\n\\t\\t\\toriginalName _ renamedConv at: ind ifAbsent: [outp name].\\n\\t\\t\\t\\t\\\"in DiskProxy>>comeFullyUpOnReload: we saved the name at the index\\\"\\n\\t\\t\\tfakeCls _ self mapClass: outp origName: originalName.\\n\\t\\t\\tfakeCls == outp ifFalse: [\\n\\t\\t\\t\\tmapFakeClassesToReal at: fakeCls put: outp.\\n\\t\\t\\t\\toutPointers at: ind put: fakeCls]]].\\n\\t^ mapFakeClassesToReal! !\\n\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/15/98 20:28'!\\nappendClassDefns\\n\\t\\\"Make this a fileOut format file. For each UniClass mentioned, prepend its source code to the file. Class name conflicts during reading will be resolved then. Assume instVarInfo: has already been done.\\\"\\n\\nbyteStream ascii.\\nbyteStream position = 0 ifTrue: [\\n\\tbyteStream setFileTypeToObject.\\n\\t\\t\\\"Type and Creator not to be text, so can attach correctly to an email msg\\\"\\n\\tbyteStream header; timeStamp].\\n\\nbyteStream cr; nextPutAll: '!!ObjectScanner new initialize!!'; cr; cr.\\nself uniClasesDo: [:class | class\\n\\t\\tclass sharedPools size > 0 ifTrue: \\\"This never happens\\\"\\n\\t\\t\\t[class shouldFileOutPools\\n\\t\\t\\t\\tifTrue: [class fileOutSharedPoolsOn: self]].\\n\\t\\tclass fileOutOn: byteStream moveSource: false toFile: 0].\\t\\n\\t\\t\\\"UniClasses are filed out normally, no special format.\\\"\\n\\n\\tbyteStream trailer.\\t\\\"Does nothing for normal files. \\n\\t\\tHTML streams will have trouble with object data\\\"\\n\\n\\t\\\"Append the object's raw data\\\"\\n\\tbyteStream cr; cr; nextPutAll: '!!self smartRefStream!!'.\\n\\tbyteStream binary.\\t\\t\\\"get ready for objects\\\"\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/19/2000 21:22'!\\ncheckCrLf\\n\\t| save isCrLf cc prev loneLf |\\n\\t\\\"Watch for a file that has had all of its Cr's converted to CrLf's. Some unpacking programs like Stuffit 5.0 do this by default!!\\\"\\n\\n\\tsave _ byteStream position.\\n\\tisCrLf _ false. loneLf _ false.\\n\\tcc _ 0.\\n\\t350 timesRepeat: [\\n\\t\\tprev _ cc.\\n\\t\\t(cc _ byteStream next) = 16r0A \\\"Lf\\\" ifTrue: [\\n\\t\\t\\tprev = 16r0D \\\"Cr\\\" ifTrue: [isCrLf _ true] ifFalse: [loneLf _ true]].\\n\\t\\t].\\n\\tisCrLf & (loneLf not) ifTrue: [\\n\\t\\tself inform: 'Carriage Returns in this file were converted to CrLfs \\nby an evil unpacking utility. Please set the preferences in \\nStuffIt Expander to \\\"do not convert file formats\\\"'].\\n\\tbyteStream position: save.\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'mir 9/12/2002 10:59'!\\ninitKnownRenames\\n\\trenamed\\n\\t\\tat: #FlasherMorph put: #Flasher;\\n\\t\\tyourself! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 19:27'!\\ninitShapeDicts\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\t\\\"These must stay constant. When structures read in, then things can change.\\\"\\n\\tsteady _ {Array. Dictionary. Association. ByteString. SmallInteger} asSet.\\n\\n\\trenamed ifNil: [\\n\\t\\trenamed _ Dictionary new. \\\"(old class name symbol -> new class name)\\\"\\n\\t\\trenamedConv _ Dictionary new \\\"(oldClassNameSymbol -> conversionSelectorInNewClass)\\\"\\n\\t].\\n\\tself initKnownRenames! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/7/2001 18:17'!\\ninstVarInfo: anObject\\n\\t\\\"Return the object to write on the outgoing file that contains the structure of each class we are about to write out. Must be an Array whose first element is 'class structure'. Its second element is a Dictionary of pairs of the form #Rectangle -> #(<classVersion> 'origin' 'corner'). \\\"\\n\\n\\t\\\"Make a pass through the objects, not writing, but recording the classes. Construct a database of their inst vars and any version info (classVersion).\\\"\\n\\n\\t| dummy refs cls newSupers |\\n\\tstructures _ Dictionary new.\\n\\tsuperclasses _ Dictionary new.\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\trefs _ dummy references.\\n\\tobjCount _ refs size.\\t\\t\\\"for progress bar\\\"\\n\\t\\t\\\"Note that Dictionary must not change its implementation!! If it does, how do we read this reading information?\\\"\\n\\t(refs includesKey: #AnImageSegment) \\n\\t\\tifFalse: [\\n\\t\\t\\tself uniClassInstVarsRefs: dummy.\\t\\\"catalog the extra objects in UniClass inst vars\\\"\\n\\t\\t\\trefs keysDo: [:each | \\n\\t\\t\\t\\tcls _ each class.\\n\\t\\t\\t\\t\\\"cls isObsolete ifTrue: [self error: 'Trying to write ', cls name].\\\"\\n\\t\\t\\t\\t(cls class ~~ Metaclass) & (cls isObsolete not) ifTrue: [\\n\\t\\t\\t\\t\\tstructures at: cls name put: false]]]\\n\\t\\tifTrue: [self recordImageSegment: refs].\\n\\t\\\"Save work by only computing inst vars once for each class\\\"\\n\\tnewSupers _ Set new.\\n\\tstructures at: #Point put: false.\\t\\\"writeRectangle: does not put out class pointer\\\"\\n\\tstructures at: #Rectangle put: false.\\n\\tstructures at: #LargePositiveInteger put: false.\\t\\\"used in slow case of WordArray\\\"\\n\\tstructures keysDo: [:nm | \\n\\t\\tcls _ (nm endsWith: ' class') \\n\\t\\t\\tifFalse: [Smalltalk at: nm]\\n\\t\\t\\tifTrue: [(Smalltalk at: nm substrings first asSymbol) class].\\n\\t\\tcls allSuperclasses do: [:aSuper |\\n\\t\\t\\tstructures at: aSuper name ifAbsent: [newSupers add: aSuper name]]].\\n\\t\\t\\t\\\"Don't modify structures during iteration\\\"\\n\\tnewSupers do: [:nm | structures at: nm put: 3].\\t\\\"Get all superclasses into list\\\"\\n\\tstructures keysDo: [:nm | \\\"Nothing added to classes during loop\\\"\\n\\t\\tcls _ (nm endsWith: ' class') \\n\\t\\t\\tifFalse: [Smalltalk at: nm]\\n\\t\\t\\tifTrue: [(Smalltalk at: nm substrings first asSymbol) class].\\n\\t\\tstructures at: nm put: \\n\\t\\t\\t((Array with: cls classVersion), (cls allInstVarNames)).\\n\\t\\tsuperclasses at: nm ifAbsent: [\\n\\t\\t\\t\\tsuperclasses at: nm put: cls superclass name]].\\n\\t(refs includesKey: #AnImageSegment) \\n\\t\\tifTrue: [classInstVars _ #()]\\n\\t\\tifFalse: [self saveClassInstVars].\\t\\\"of UniClassses\\\"\\n\\t^ (Array with: 'class structure' with: structures with: 'superclasses' with: superclasses)! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 18:52'!\\nmapClass: incoming\\n\\t\\\"See if the old class named nm exists. If so, return it. If not, map it to a new class, and save the mapping in renamed. \\\"\\n\\n\\t| cls oldVer sel nm |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tnm _ renamed at: incoming ifAbsent: [incoming].\\t\\\"allow pre-mapping around collisions\\\"\\n\\t(nm endsWith: ' class') \\n\\t\\tifFalse: [cls _ Smalltalk at: nm ifAbsent: [nil].\\n\\t\\t\\tcls ifNotNil: [^ cls]] \\t\\\"Known class. It will know how to translate the instance.\\\"\\n\\t\\tifTrue: [cls _ Smalltalk at: nm substrings first asSymbol ifAbsent: [nil].\\n\\t\\t\\tcls ifNotNil: [^ cls class]]. \\t\\\"Known class. It will know how to translate the instance.\\\"\\n\\toldVer _ self versionSymbol: (structures at: nm).\\n\\tsel _ nm asString.\\n\\tsel at: 1 put: (sel at: 1) asLowercase.\\n\\tsel _ sel, oldVer.\\t\\\"i.e. #rectangleoc4\\\"\\n\\tSymbol hasInterned: sel ifTrue: [:symb | \\n\\t\\t(self class canUnderstand: sel asSymbol) ifTrue: [\\n\\t\\t\\treshaped ifNil: [reshaped _ Dictionary new].\\n\\t\\t\\tcls _ self perform: sel asSymbol]].\\t\\\"This class will take responsibility\\\"\\n\\tcls ifNil: [cls _ self writeClassRenameMethod: sel was: nm\\n\\t\\t\\t\\t\\tfromInstVars: (structures at: nm).\\n\\t\\t\\t cls isString ifTrue: [cls _ nil]].\\n\\tcls ifNotNil: [renamed at: nm put: cls name].\\n\\t^ cls\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 5/26/1998 15:09'!\\nmoreObjects\\n\\t\\\"Return true if there appears to be another object following this one on the file.\\\"\\n\\n\\t| byte |\\n\\tbyteStream atEnd ifTrue: [^ false].\\t\\\"off end of file\\\"\\n\\t(byte _ byteStream peek) ifNil: [^ false].\\t\\\"off end of file\\\"\\n\\tbyte = 33 \\\"$!! asciiValue\\\" ifTrue: [^ false].\\n\\tbyte = 0 ifTrue: [^ false].\\n\\t^ byte <= RefTypes size\\t\\t\\\"between 1 and 16\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/19/2000 17:06'!\\nnext\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. \\\"\\n\\n\\t| version ss object |\\n\\t^ topCall == nil \\n\\t\\tifTrue: \\n\\t\\t\\t[topCall _ #marked.\\n\\t\\t\\tversion _ super next.\\n\\t\\t\\tversion class == SmallInteger ifFalse: [^ version].\\t\\n\\t\\t\\t\\t\\\"version number, else just a regular object, not in our format, \\\"\\n\\t\\t\\tself checkCrLf.\\n\\t\\t\\tss _ super next.\\n\\t\\t\\tss class == Array ifFalse: [^ ss]. \\\"just a regular object\\\"\\n\\t\\t\\t(ss at: 1) = 'class structure' ifFalse: [^ ss].\\n\\t\\t\\tstructures _ ss at: 2.\\n\\t\\t\\tsuperclasses _ (ss size > 3 and: [(ss at: 3) = 'superclasses']) \\n\\t\\t\\t\\tifTrue: [ss at: 4]\\t\\t\\\"class name -> superclass name\\\"\\n\\t\\t\\t\\tifFalse: [Dictionary new].\\n\\t\\t\\t(self verifyStructure = 'conversion method needed') ifTrue: [^ nil].\\n\\t\\t\\tobject _ super next.\\t\\\"all the action here\\\"\\n\\t\\t\\tself restoreClassInstVars.\\t\\t\\\"for UniClasses. version 4\\\"\\n\\n\\t\\t\\ttopCall _ nil.\\t\\\"reset it\\\"\\n\\t\\t\\tobject]\\n\\t\\tifFalse:\\n\\t\\t\\t[super next]\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/5/2002 09:52'!\\nnextAndClose\\n\\t\\\"Speedy way to grab one object. Only use when we are inside an object binary file. If used for the start of a SmartRefStream mixed code-and-object file, tell the user and then do the right thing.\\\"\\n\\n\\t| obj |\\n\\tbyteStream peek = ReferenceStream versionCode \\\"4\\\" ifFalse: [\\n\\t\\t\\\"OK it is a fileIn afterall...\\\"\\n\\t\\tself inform: 'Should be using fileInObjectAndCode'.\\n\\t\\tbyteStream ascii.\\n\\t\\tbyteStream fileIn.\\n\\t\\tobj _ SmartRefStream scannedObject.\\n\\t\\tSmartRefStream scannedObject: nil.\\n\\t\\t^ obj].\\n\\n\\tobj _ self next.\\n\\tself close.\\n\\t^ obj! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'md 2/24/2006 19:52'!\\nnextPut: anObject\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. If any instance-specific classes are present, prepend their source code. byteStream will be in fileOut format.\\n\\tYou can see an analysis of which objects are written out by doing: \\n\\t(SmartRefStream statsOfSubObjects: anObject)\\n\\t(SmartRefStream tallyOfSubObjects: anObject)\\n\\t(SmartRefStream subObjects: anObject ofClass: aClass)\\\"\\n\\n| info |\\ntopCall == nil \\n\\tifTrue:\\n\\t\\t[topCall _ anObject.\\n\\t\\t'Please wait while objects are counted' \\n\\t\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\t\\tfrom: 0 to: 10\\n\\t\\t\\tduring: [:bar | info _ self instVarInfo: anObject].\\n\\t\\tself appendClassDefns.\\t\\\"For instance-specific classes\\\"\\n\\t\\t'Writing an object file' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\tfrom: 0 to: objCount*4\\t\\\"estimate\\\"\\n\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\tobjCount _ 0.\\n\\t\\t\\t\\tprogressBar _ bar.\\n\\t\\t\\t\\tself setStream: byteStream reading: false.\\n\\t\\t\\t\\t\\t\\\"set basePos, but keep any class renames\\\"\\n\\t\\t\\t\\tsuper nextPut: ReferenceStream versionCode.\\n\\t\\t\\t\\tsuper nextPut: info.\\n\\t\\t\\t\\tsuper nextPut: anObject.\\t\\t\\\"<- the real writing\\\"\\n\\t\\t\\t\\tclassInstVars size > 0 ifTrue: [super nextPut: classInstVars]].\\n\\t\\t\\t\\t\\t\\\"Note: the terminator, $!!, is not doubled inside object data\\\"\\n\\t\\t\\\"references is an IDict of every object that got written\\\"\\n\\t\\tbyteStream ascii.\\n\\t\\tbyteStream nextPutAll: '!!'; cr; cr.\\n\\t\\tbyteStream padToEndWith: $ .\\t\\\"really want to truncate file, but can't\\\"\\n\\t\\ttopCall _ progressBar _ nil]\\t\\\"reset it\\\"\\n\\tifFalse:\\n\\t\\t[super nextPut: anObject.\\n\\t\\tprogressBar ifNotNil: [progressBar value: (objCount _ objCount + 1)]].\\n\\t\\t\\\"return the argument - added by kwl\\\"\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/23/1998 11:00'!\\nnextPutObjOnly: anObject\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. Not in fileOut format. No class definitions will be written for instance-specific classes. Error if find one. (Use nextPut: instead)\\\"\\n\\n\\t| info |\\n\\ttopCall == nil \\n\\t\\tifTrue:\\n\\t\\t\\t[topCall _ anObject.\\n\\t\\t\\tsuper nextPut: ReferenceStream versionCode.\\n\\t\\t\\t'Please wait while objects are counted' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\t\\tfrom: 0 to: 10\\n\\t\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\t\\tinfo _ self instVarInfo: anObject].\\n\\t\\t\\tself uniClasesDo: [:cls | cls error: 'Class defn not written out. Proceed?'].\\n\\t\\t\\t'Writing an object file' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\t\\tfrom: 0 to: objCount*4\\t\\\"estimate\\\"\\n\\t\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\t\\tobjCount _ 0.\\n\\t\\t\\t\\t\\tprogressBar _ bar.\\n\\t\\t\\t\\t\\tsuper nextPut: info.\\n\\t\\t\\t\\t\\tsuper nextPut: anObject.\\t\\\"<- the real writing\\\"\\n\\t\\t\\t\\t\\t\\\"Class inst vars not written here!!\\\"].\\n\\t\\t\\t\\\"references is an IDict of every object that got written\\n\\t\\t\\t(in case you want to take statistics)\\\"\\n\\t\\t\\t\\\"Transcript cr; show: structures keys printString.\\\"\\t\\t\\\"debug\\\"\\n\\t\\t\\ttopCall _ progressBar _ nil]\\t\\\"reset it\\\"\\n\\t\\tifFalse:\\n\\t\\t\\t[super nextPut: anObject.\\n\\t\\t\\tprogressBar ifNotNil: [progressBar value: (objCount _ objCount + 1)]].! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/23/1998 11:13'!\\nnoHeader\\n\\t\\\"Signal that we've already dealt with the version and structure array, and are now reading objects.\\\"\\n\\n\\ttopCall _ #marked.\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 11/3/2000 17:59'!\\nreadInstance\\n\\t\\\"Read the contents of an arbitrary instance.\\n\\t ASSUMES: readDataFrom:size: sends me beginReference: after it\\n\\t instantiates the new object but before reading nested objects.\\n\\t NOTE: We must restore the current reference position after\\n\\t recursive calls to next.\\nThree cases for files from older versions of the system:\\n1) Class has not changed shape, read it straight.\\n2) Class has changed instance variables (or needs fixup). Call a particular method to do it.\\n3) There is a new class instead. Find it, call a particular method to read.\\n\\tAll classes used to construct the structures dictionary *itself* need to be in 'steady' and they must not change!! See setStream:\\\"\\n\\t| instSize className refPosn |\\n\\n\\tinstSize _ (byteStream nextNumber: 4) - 1.\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self next asSymbol.\\n\\t^ self readInstanceSize: instSize clsname: className refPosn: refPosn\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'yo 1/21/2006 19:27'!\\nreadInstanceSize: instSize clsname: className refPosn: refPosn\\n\\t\\\"The common code to read the contents of an arbitrary instance.\\n\\t ASSUMES: readDataFrom:size: sends me beginReference: after it\\n\\t instantiates the new object but before reading nested objects.\\n\\t NOTE: We must restore the current reference position after\\n\\t recursive calls to next.\\nThree cases for files from older versions of the system:\\n1) Class has not changed shape, read it straight.\\n2) Class has changed instance variables (or needs fixup). Call a particular method to do it.\\n3) There is a new class instead. Find it, call a particular method to read.\\n\\tAll classes used to construct the structures dictionary *itself* need to be in 'steady' and they must not change!! See setStream:\\\"\\n\\t| anObject newName newClass dict oldInstVars isMultiSymbol |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tself setCurrentReference: refPosn. \\\"remember pos before readDataFrom:size:\\\"\\n\\tnewName _ renamed at: className ifAbsent: [className].\\n\\tisMultiSymbol _ newName = #MultiSymbol or: [newName = #WideSymbol].\\n\\t\\\"isMultiSymbol ifTrue: [self halt].\\\"\\n\\tnewClass _ Smalltalk at: newName asSymbol.\\n\\t(steady includes: newClass) & (newName == className) ifTrue: [\\n\\t \\tanObject _ newClass isVariable \\\"Create it here\\\"\\n\\t\\t\\tifFalse: [newClass basicNew]\\n\\t\\t\\tifTrue: [newClass basicNew: instSize - (newClass instSize)].\\n\\n\\t\\tanObject _ anObject readDataFrom: self size: instSize.\\n\\t\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\t\\tisMultiSymbol ifTrue: [^ Symbol intern: anObject asString].\\n\\t\\t^ anObject].\\n\\toldInstVars _ structures at: className ifAbsent: [\\n\\t\\t\\tself error: 'class is not in structures list'].\\t\\\"Missing in object file\\\"\\n\\tanObject _ newClass createFrom: self size: instSize version: oldInstVars.\\n\\t\\t\\\"only create the instance\\\"\\n\\tself beginReference: anObject.\\n\\tdict _ self catalogValues: oldInstVars size: instSize.\\n\\t\\t\\\"indexed vars as (1 -> val) etc.\\\"\\n\\tdict at: #ClassName put: className.\\t\\\"so conversion method can know it\\\"\\n\\n\\t\\\"Give each superclass a chance to make its changes\\\"\\n\\tself storeInstVarsIn: anObject from: dict.\\t\\\"ones with the same names\\\"\\n\\n\\tanObject _ self applyConversionMethodsTo: anObject className: className varMap: dict.\\n\\n\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\tisMultiSymbol ifTrue: [^ Symbol intern: anObject asString].\\n\\t^ anObject! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 11/3/2000 18:04'!\\nreadShortInst\\n\\t\\\"Instance has just one byte of size. Class symbol is encoded in two bytes of file position. See readInstance.\\\"\\n\\t| instSize className refPosn |\\n\\n\\tinstSize _ (byteStream next) - 1.\\t\\\"one byte of size\\\"\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self readShortRef.\\t\\\"class symbol in two bytes of file pos\\\"\\n\\t^ self readInstanceSize: instSize clsname: className refPosn: refPosn\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 7/25/2005 21:30'!\\nreadWordLike\\n\\t| refPosn newClass anObject className |\\n\\t\\\"Can be used by any class that is bits and not bytes (WordArray, Bitmap, SoundBuffer, etc).\\\"\\n\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self next asSymbol.\\n\\tclassName _ renamed at: className ifAbsent: [className].\\n\\tnewClass _ Smalltalk at: className.\\n\\tanObject _ newClass newFromStream: byteStream.\\n\\t\\\"Size is number of long words.\\\"\\n\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 10/10/2000 13:36'!\\nrecordImageSegment: refs\\n\\t\\\"Besides the objects being written out, record the structure of instances inside the image segment we are writing out.\\\"\\n\\n\\t| cls list |\\n\\t\\\"Do not record Player class inst vars. They are in the segement.\\\"\\n\\trefs keysDo: [:each | \\n\\t\\tcls _ each class.\\n\\t\\tcls isObsolete ifTrue: [self error: 'Trying to write ', cls name].\\n\\t\\tcls class == Metaclass \\n\\t\\t\\tifFalse: [structures at: cls name put: false.\\n\\t\\t\\t\\t(each isKindOf: ImageSegment) ifTrue: [\\n\\t\\t\\t\\t\\teach outPointers do: [:out |\\n\\t\\t\\t\\t\\t\\t(out isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tstructures at: out theNonMetaClass name put: false].\\n\\t\\t\\t\\t\\t\\tout class == DiskProxy ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tout simpleGlobalOrNil ifNotNil: [\\n\\t\\t\\t\\t\\t\\t\\t\\t(out simpleGlobalOrNil isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tstructures at: out simpleGlobalOrNil name put: false]]]].\\n\\t\\t\\t\\t\\t\\\"each arrayOfRoots do: [:rr | (rr isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tstructures at: rr theNonMetaClass name put: false]].\\\"\\n\\t\\t\\t\\t\\t \\t\\\"all classes in roots are local to seg\\\"]]].\\n\\tlist _ refs at: #BlockReceiverClasses ifAbsent: [^ self].\\n\\tlist do: [:meta | structures at: meta name put: false].\\n\\t\\t\\\"Just the metaclasses whose instances are block receivers. Otherwise metaclasses are not allowed.\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 11:08'!\\nrenamed\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\t^ renamed! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 11:10'!\\nrenamedConv\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\t^ renamedConv! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/22/2000 15:14'!\\nrestoreClassInstVars\\n\\t\\\"Install the values of the class instance variables of UniClasses\\n(i.e. scripts slotInfo). classInstVars is ((#Player25 scripts slotInfo)\\n...). Thank you Mark Wai for the bug fix.\\\"\\n\\n\\t| normal aName newName newCls trans rList start |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tself moreObjects ifFalse: [^ self]. \\t\\\"are no UniClasses with class inst vars\\\"\\n\\tclassInstVars _ super next.\\t\\\"Array of arrays\\\"\\n\\tnormal _ Object class instSize.\\t\\\"might give trouble if Player class superclass changes size\\\"\\n\\t(structures at: #Player ifAbsent: [#()]) = #(0 'dependents' 'costume') ifTrue:\\n\\t\\t[trans _ 1].\\t\\\"now (0 costume costumes). Do the conversion of Player class\\n\\t\\t\\tinst vars in Update 509.\\\"\\n\\tclassInstVars do: [:list |\\n\\t\\taName _ (list at: 1) asSymbol.\\n\\t\\trList _ list.\\n\\t\\tnewName _ renamed at: aName ifAbsent: [aName].\\n\\t\\tnewCls _ Smalltalk at: newName\\n\\t\\t\\t\\tifAbsent: [self error: 'UniClass definition missing'].\\n\\t\\t(\\\"old conversion\\\" trans == 1 and: [newCls inheritsFrom: Player]) ifTrue: [\\n\\t\\t\\t\\\"remove costumeDictionary from Player class inst vars\\\"\\n\\t\\t\\trList _ rList asOrderedCollection.\\n\\t\\t\\trList removeAt: 4].\\t\\\"costumeDictionary's value\\\"\\n\\t\\tstart _ list second = 'Update to read classPool' ifTrue: [4] ifFalse: [2].\\n\\t\\tnewCls class instSize = (normal + (rList size) - start + 1) ifFalse:\\n\\t\\t\\t[self error: 'UniClass superclass class has changed size'].\\n\\t\\t\\t\\\"Need to install a conversion method mechanism\\\"\\n\\t\\tstart = 4 ifTrue: [newCls instVarAt: normal - 1 \\\"classPool\\\" put: (list at: 3)].\\n\\t\\tstart to: rList size do: [:ii |\\n\\t\\t\\tnewCls instVarAt: normal + ii - start + 1 put: (rList at: ii)]].\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/6/2000 18:17'!\\nsaveClassInstVars\\n\\t\\\"Install the values of the instance variables of UniClasses.\\nclassInstVars is an array of arrays (#Player3 (Player3 class's inst var\\nscripts) (Player3 class's inst var slotInfo) ...) \\\"\\n\\n\\t| normal mySize list clsPoolIndex |\\n\\tclassInstVars _ OrderedCollection new: 100.\\n\\tnormal _ Object class instSize.\\n\\tclsPoolIndex _ Object class allInstVarNames indexOf: 'classPool'.\\n\\tself uniClasesDo: [:aUniClass |\\n\\t\\tlist _ OrderedCollection new.\\n\\t\\tmySize _ aUniClass class instSize.\\n\\t\\tmySize = normal ifFalse:\\n\\t\\t\\t[list add: aUniClass name.\\t\\\"a symbol\\\"\\n\\t\\t\\tlist add: 'Update to read classPool'.\\t\\\"new\\nconvention for saving the classPool\\\"\\n\\t\\t\\tlist add: (aUniClass instVarAt: clsPoolIndex)\\n\\\"classPool\\\".\\n\\t\\t\\t\\t\\t\\t\\\"write actual value of nil\\ninstead of Dictionary()\\\"\\n\\t\\t\\tnormal + 1 to: mySize do: [:ii |\\n\\t\\t\\t\\tlist addLast: (aUniClass instVarAt: ii)].\\n\\t\\t\\tclassInstVars add: list asArray]].\\n\\tclassInstVars _ classInstVars asArray.\\n\\t! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 8/18/1998 09:02'!\\nscanFrom: aByteStream\\n\\t\\\"During a code fileIn, we need to read in an object, and stash it in ScannedObject. \\\"\\n\\n\\tself setStream: aByteStream reading: true.\\n\\tScannedObject _ self next.\\n\\tbyteStream ascii.\\n\\tbyteStream next == $!! ifFalse: [\\n\\t\\tbyteStream close.\\n\\t\\tself error: 'Object did not end correctly']. \\n\\t\\\"caller will close the byteStream\\\"\\n\\t\\\"HandMorph.readMorphFile will retrieve the ScannedObject\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 16:57'!\\nsetStream: aStream\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsuper setStream: aStream.\\n\\tself initShapeDicts.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 16:57'!\\nsetStream: aStream reading: isReading\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsuper setStream: aStream reading: isReading.\\n\\tisReading ifFalse: [^ false].\\n\\tself initShapeDicts.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'read write'!\\nstructures\\n\\t^ structures! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 9/28/97 11:17'!\\nsuperclasses\\n\\t^superclasses! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/6/2000 17:15'!\\nuniClasesDo: aBlock\\n\\t\\\"Examine structures and execute the block with each instance-specific class\\\"\\n\\n\\t| cls |\\n\\tstructures keysDo: [:clsName | \\n\\t\\t(clsName endsWith: ' class') ifFalse: [\\n\\t\\t\\t(cls _ Smalltalk at: clsName) isSystemDefined ifFalse: [\\n\\t\\t\\t\\t\\taBlock value: cls]]]! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 1/18/2001 15:54'!\\nuniClassInstVarsRefs: dummy\\n\\t\\\"If some of the objects seen so far are instances UniClasses, check the UniClasses for extra class inst vars, and send them to the steam also. The new objects get added to (dummy references), where they will be noticed by the caller. They will wind up in the structures array and will be written on the disk by class.\\n\\tReturn all classes seen.\\\" \\n| uniClasses normal more aUniClass mySize allClasses |\\n\\n\\\"Note: Any classes used in the structure of classInstVars must be written out also!!\\\"\\nuniClasses _ Set new.\\nallClasses _ IdentitySet new.\\nnormal _ Object class instSize.\\nmore _ true.\\n[more] whileTrue: [\\n\\tmore _ false.\\n\\tdummy references keysDo: [:each | \\\"any faster way to do this?\\\"\\n\\t\\t(aUniClass _ each class) isSystemDefined ifFalse: [\\n\\t\\t\\t(uniClasses includes: aUniClass name) ifFalse: [\\n\\t\\t\\t\\tmySize _ aUniClass class instSize.\\n\\t\\t\\t\\tnormal+1 to: mySize do: [:ii | \\n\\t\\t\\t\\t\\tmore _ true.\\n\\t\\t\\t\\t\\tdummy nextPut: (aUniClass instVarAt: ii)].\\n\\t\\t\\t\\tuniClasses add: aUniClass name]].\\n\\t\\teach class class isMeta ifFalse: [\\\"it is a class\\\" allClasses add: each]]].\\n\\\"References dictionary is modified as the loop proceeds, but we will catch any we missed on the next cycle.\\\"\\n\\n^ allClasses! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 18:52'!\\nverifyStructure\\n\\t\\\"Compare the incoming inst var name lists with the existing classes. Prepare tables that will help to restructure those who need it (renamed, reshaped, steady). If all superclasses are recorded in the file, only compare inst vars of this class, not of superclasses. They will get their turn. \\\"\\n\\n\\n\\t| newClass newList oldList converting |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tconverting _ OrderedCollection new.\\n\\tstructures keysDo: [:nm \\\"an old className (symbol)\\\" |\\n\\t\\t\\\"For missing classes, there needs to be a method in SmartRefStream like \\n\\t\\t\\t#rectangleoc2 that returns the new class.\\\"\\n\\t\\tnewClass _ self mapClass: nm.\\t \\\"does (renamed at: nm put: newClass name)\\\"\\n\\t\\tnewClass isString ifTrue: [^ newClass]. \\\"error, fileIn needed\\\"\\n\\t\\tnewList _ (Array with: newClass classVersion), (newClass allInstVarNames).\\n\\t\\toldList _ structures at: nm.\\n\\t\\tnewList = oldList \\n\\t\\t\\tifTrue: [steady add: newClass] \\\"read it in as written\\\"\\n\\t\\t\\tifFalse: [converting add: newClass name]\\n\\t].\\n\\tfalse & converting isEmpty not ifTrue: [\\\"debug\\\" \\n\\t\\t\\tself inform: 'These classes are being converted from existing methods:\\\\' withCRs,\\n\\t\\t\\t\\tconverting asArray printString].\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 1/7/97'!\\nversionSymbol: instVarList\\n\\t\\\"Create the symbolic code (like a version number) for this class in some older version. First initials of all the inst vars, followed by the class version number. Returns a string, caller makes it into a compound selector. \\\"\\n\\n\\t| str |\\n\\tstr _ instVarList size = 1 ifFalse: [''] ifTrue: ['x'].\\t\\t\\\"at least one letter\\\"\\n\\t2 to: instVarList size do: [:ind |\\n\\t\\tstr _ str, (instVarList at: ind) first asString].\\n\\tstr _ str, instVarList first printString.\\t\\\"the number\\\"\\n\\t^ str\\n\\n\\\" | list | list _ (Array with: Paragraph classVersion), (Paragraph alistInstVarNames).\\n(SmartRefStream on: (DummyStream on: nil)) versionSymbol: list\\n\\\"! !\\n\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:35'!\\nstarLogoAntColonybosfcedppplppppttwssdlgrstta0\\n\\n\\t^ StarSqueakAntColony! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:31'!\\nstarLogoMorphbosfcedppplppppttwssdlgrstt0\\n\\n\\t^ StarSqueakMorph! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:32'!\\nstarLogoTreesbosfcedppplppppttwssdlgrsttdt0\\n\\n\\t^ StarSqueakTrees! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:32'!\\nstarLogoTurtlewwxywwhcpn0\\n\\n\\t^ StarSqueakTurtle! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSmartRefStream class\\n\\tinstanceVariableNames: ''!\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 5/20/97'!\\nscannedObject\\n\\t\\\"The most recently read in object. Watch out for read-in that is interrupted and resumed. May want to make this a dictionary? \\\"\\n\\n\\t^ ScannedObject! !\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 5/20/97'!\\nscannedObject: objOrNil\\n\\t\\\"Used to free up the last object stashed here. \\\"\\n\\n\\tScannedObject _ objOrNil! !\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 3/11/98 09:45'!\\nsubObjects: anObject ofClass: aClass\\n\\t\\\"Return a collection of all instances of aClass that would be written out with anObject. Does not actually write on the disk. Inspect the result and ask for 'references to this object'.\\\"\\n\\n\\t| dummy coll |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\tcoll _ OrderedCollection new.\\n\\tdummy references keysDo: [:each |\\n\\t\\teach class == aClass ifTrue: [coll add: each]].\\n\\t^ coll! !\\n\\n\\n!SmartRefStream class methodsFor: 'initialize-release' stamp: 'dvf 8/23/2003 12:18'!\\ncleanUpCategories\\n\\t| list valid removed newList newVers |\\n\\t\\\"Look for all conversion methods that can't be used any longer. Delete them.\\\"\\n\\t\\\" SmartRefStream cleanUpCategories \\\"\\n\\n\\t\\\"Two part selectors that begin with convert and end with a digit.\\\"\\n\\t\\\"convertasossfe0: varDict asossfeu0: smartRefStrm\\\"\\n\\tlist _ Symbol selectorsContaining: 'convert'.\\n\\tlist _ list select: [:symb | (symb beginsWith: 'convert') & (symb allButLast last isDigit)\\n\\t\\t\\t\\tifTrue: [(symb numArgs = 2)]\\n\\t\\t\\t\\tifFalse: [false]].\\n\\tvalid _ 0. removed _ 0.\\n\\tlist do: [:symb |\\n\\t\\t(self systemNavigation allClassesImplementing: symb) do: [:newClass |\\n\\t\\t\\tnewList _ (Array with: newClass classVersion), (newClass allInstVarNames).\\n\\t\\t\\tnewVers _ self new versionSymbol: newList.\\n\\t\\t\\t(symb endsWith: (':',newVers,':')) \\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\\"method is useless because can't convert to current shape\\\"\\n\\t\\t\\t\\t\\tnewClass removeSelector: symb.\\t\\\"get rid of it\\\"\\n\\t\\t\\t\\t\\tremoved _ removed + 1]\\n\\t\\t\\t\\tifTrue: [valid _ valid + 1]]].\\n\\tTranscript cr; show: 'Removed: '; print: removed; \\n\\t\\tshow: '\\t\\tKept: '; print: valid; show: ' '.! !\\n\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'RAA 7/9/2000 05:48'!\\nobjectFromStreamedRepresentation: someBytes\\n\\n\\t| file |\\n\\n\\tfile _ RWBinaryOrTextStream with: someBytes.\\n\\tfile reset.\\n\\t^file fileInObjectAndCode! !\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'tk 12/9/97 21:31'!\\nread: aByteStream withClasses: structureArray\\n\\t\\\"Read an object off the stream, but first check structureArray against the current system.\\\"\\n\\n\\t| me |\\n\\tme _ self on: aByteStream.\\n\\tme noHeader.\\n\\tme structures: (structureArray at: 2).\\n\\tme superclasses: (structureArray at: 4).\\n\\t(me verifyStructure = 'conversion method needed') ifTrue: [^ nil].\\n\\t^ super next\\n! !\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'tk 5/20/97'!\\nscanFrom: aByteStream\\n\\t\\\"During a code fileIn, we need to read in an object, and stash it in ScannedObject. \\\"\\n\\n\\t| me |\\n\\tme _ self on: aByteStream.\\n\\tScannedObject _ me next.\\n\\taByteStream ascii.\\n\\taByteStream next == $!! ifFalse: [\\n\\t\\taByteStream close.\\n\\t\\tself error: 'Object did not end correctly']. \\n\\t\\\"caller will close the byteStream\\\"\\n\\t\\\"HandMorph.readMorphFile will retrieve the ScannedObject\\\"! !\\n\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'tk 5/4/1998 17:34'!\\nstatsOfSubObjects: anObject\\n\\t\\\"Open a window with statistics on what objects would be written out with anObject. Does not actually write on the disk. Stats in the form:\\n\\tScriptEditorMorph 51\\n\\t\\tSortedCollection (21->LayoutMorph 15->SimpleButtonMorph 9->Array 4->CompoundTileMorph 2->StringMorph )\\\"\\n\\n\\t| dummy printOut |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\t\\\"(dummy references) is the raw data\\\"\\n\\tprintOut _ dummy statisticsOfRefs.\\n\\t(StringHolder new contents: printOut) \\n\\t\\topenLabel: 'ReferenceStream statistics'.! !\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'RAA 7/9/2000 05:35'!\\nstreamedRepresentationOf: anObject\\n\\n\\t| file |\\n\\tfile _ (RWBinaryOrTextStream on: (ByteArray new: 5000)).\\n\\tfile binary.\\n\\t(self on: file) nextPut: anObject.\\n\\tfile close.\\n\\t^file contents! !\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'tk 5/4/1998 17:34'!\\ntallyOfSubObjects: anObject\\n\\t\\\"Open a window with statistics on what objects would be written out with anObject. Does not actually write on the disk. Stats are simply the number of instances of each class:\\n\\t1450->Point 835->Rectangle 549->Array 300->String\\\"\\n\\n\\t| dummy bag |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\tbag _ Bag new.\\n\\tdummy references keysDo: [:key | bag add: key class name].\\n\\t\\\"(bag sortedCounts) is the SortedCollection\\\"\\n\\t(StringHolder new contents: bag sortedCounts printString) \\n\\t\\topenLabel: 'ReferenceStream statistics'.! !\\nObject subclass: #Socket\\n\\tinstanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore primitiveOnlySupportsOneSemaphore'\\n\\tclassVariableNames: 'Connected DeadServer InvalidSocket OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!Socket commentStamp: 'gk 12/13/2005 00:43' prior: 0!\\nA Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols. Sockets are the lowest level of networking object in Squeak and are not normally used directly. SocketStream is a higher level object wrapping a Socket in a stream like protocol.\\n\\nProtocolClient and subclasses are in turn wrappers around a SocketStream to provide support for specific network protocols such as POP, NNTP, HTTP, and FTP.!\\n\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\naddress\\n\\t\\\"Shortcut\\\"\\n\\t^self localAddress! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'MU 11/26/2003 16:53'!\\nlocalAddress\\n\\tself isWaitingForConnection\\n\\t\\tifFalse: [[self waitForConnectionFor: Socket standardTimeout]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | ^ ByteArray new: 4]].\\n\\t^ self primSocketLocalAddress: socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'MU 11/26/2003 16:53'!\\nlocalPort\\n\\tself isWaitingForConnection\\n\\t\\tifFalse: [[self waitForConnectionFor: Socket standardTimeout]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | ^ 0]].\\n\\t^ self primSocketLocalPort: socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 3/13/98 12:11'!\\npeerName\\n\\t\\\"Return the name of the host I'm connected to, or nil if its name isn't known to the domain name server or the request times out.\\\"\\n\\t\\\"Note: Slow. Calls the domain name server, taking up to 20 seconds to time out. Even when sucessful, delays of up to 13 seconds have been observed during periods of high network load.\\\" \\n\\n\\t^ NetNameResolver\\n\\t\\tnameForAddress: self remoteAddress\\n\\t\\ttimeout: 20\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\nport\\n\\t\\\"Shortcut\\\"\\n\\t^self localPort! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 6/5/2000 10:12'!\\nprimitiveOnlySupportsOneSemaphore\\n\\t^primitiveOnlySupportsOneSemaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nreadSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^readSemaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremoteAddress\\n\\n\\t^ self primSocketRemoteAddress: socketHandle\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremotePort\\n\\n\\t^ self primSocketRemotePort: socketHandle\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/9/2000 15:32'!\\nsemaphore\\n\\t^semaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 7/16/1999 17:22'!\\nsocketHandle\\n\\t^socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nwriteSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^writeSemaphore! !\\n\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'bolot 7/16/1999 14:36'!\\naccept\\n\\t\\\"Accept a connection from the receiver socket.\\n\\tReturn a new socket that is connected to the client\\\"\\n\\t^Socket acceptFrom: self.! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 9/11/97 20:29'!\\nclose\\n\\t\\\"Close this connection gracefully. For TCP, this sends a close request, but the stream remains open until the other side also closes it.\\\"\\n\\n\\tself primSocketCloseConnection: socketHandle. \\\"close this end\\\"\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 11/4/97 07:15'!\\ncloseAndDestroy\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tself closeAndDestroy: 20.\\n\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'gk 12/13/2005 00:05'!\\ncloseAndDestroy: timeoutSeconds\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil\\n\\t\\tifFalse: [\\n\\t\\t\\tself isConnected ifTrue: [\\n\\t\\t\\t\\tself close. \\\"close this end\\\"\\n\\t\\t\\t\\t(self waitForDisconnectionFor: timeoutSeconds)\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\\"The other end didn't close so we just abort the connection\\\"\\n\\t\\t\\t\\t\\t\\tself primSocketAbortConnection: socketHandle]].\\n\\t\\t\\tself destroy].\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/9/2003 18:13'!\\nconnectNonBlockingTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address. This operation will return immediately; follow it with waitForConnectionUntil: to wait until the connection is established.\\\"\\n\\n\\t| status |\\n\\tself initializeNetwork.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before opening a new connection'].\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/15/2003 18:29'!\\nconnectTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address.\\n\\tWaits until the connection is established or time outs.\\\"\\n\\n\\tself connectTo: hostAddress port: port waitForConnectionFor: Socket standardTimeout! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mu 8/14/2003 15:15'!\\nconnectTo: hostAddress port: port waitForConnectionFor: timeout \\n\\t\\\"Initiate a connection to the given port at the given host \\n\\taddress. Waits until the connection is established or time outs.\\\"\\n\\tself connectNonBlockingTo: hostAddress port: port.\\n\\tself\\n\\t\\twaitForConnectionFor: timeout\\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to '\\n\\t\\t\\t\\t\\t, (NetNameResolver stringFromAddress: hostAddress) , ':' , port asString]! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/8/2003 16:03'!\\nconnectToHostNamed: hostName port: portNumber\\n\\t| serverIP |\\n\\tserverIP _ NetNameResolver addressForName: hostName timeout: 20.\\n\\t^self connectTo: serverIP port: portNumber\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 3/10/98 11:56'!\\ndisconnect\\n\\t\\\"Break this connection, no matter what state it is in. Data that has been sent but not received will be lost.\\\"\\n\\n\\tself primSocketAbortConnection: socketHandle.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 16:25'!\\nlistenOn: port\\n\\t\\\"Listen for a connection on the given port. This operation will return immediately; follow it with waitForConnectionUntil: to wait until a connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\n\\tself primSocket: socketHandle listenOn: port.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 16:25'!\\nlistenOn: portNumber backlogSize: backlog\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'ikp 9/1/2003 20:32'!\\nlistenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog interface: ifAddr.\\n! !\\n\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 6/7/2000 14:58'!\\nreceiveDataInto: aStringOrByteArray fromHost: hostAddress port: portNumber\\n\\t| datagram |\\n\\t\\\"Receive a UDP packet from the given hostAddress/portNumber, storing the data in the given buffer, and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self receiveDataInto: aStringOrByteArray].\\n\\t[true] whileTrue: \\n\\t\\t[datagram _ self receiveUDPDataInto: aStringOrByteArray.\\n\\t\\t((datagram at: 2) = hostAddress and: [(datagram at: 3) = portNumber]) \\n\\t\\t\\tifTrue: [^datagram at: 1]\\n\\t\\t\\tifFalse: [^0]]! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 6/3/2000 21:54'!\\nreceiveUDPDataInto: aStringOrByteArray\\n\\t\\\"Receive UDP data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data. What is returned is an array, the first element is the bytes read, the second the sending bytearray address, the third the senders port, the fourth, true if more of the datagram awaits reading\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveUDPDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 5/25/2000 00:05'!\\nsendData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self sendData: aStringOrByteArray].\\n\\t^self sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'mir 5/15/2003 18:34'!\\nsendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\t| bytesToSend bytesSent count |\\n\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneFor: 20)\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendUDPData: aStringOrByteArray\\n\\t\\t\\ttoHost: hostAddress\\n\\t\\t\\tport: portNumber\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: bytesToSend - bytesSent.\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPeer: hostAddress port: port\\n\\t\\\"Set the default send/recv address.\\\"\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPort: port\\n\\t\\\"Associate a local port number with a UDP socket. Not applicable to TCP sockets.\\\"\\n\\n\\tself primSocket: socketHandle setPort: port.\\n! !\\n\\n\\n!Socket methodsFor: 'finalization' stamp: 'JMM 5/22/2000 22:52'!\\nfinalize\\n\\tself primSocketDestroyGently: socketHandle.\\n\\tSmalltalk unregisterExternalObject: semaphore.\\n\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n! !\\n\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:47'!\\nacceptFrom: aSocket\\n\\t\\\"Initialize a new socket handle from an accept call\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _ self primAcceptFrom: aSocket socketHandle\\n\\t\\t\\t\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\t\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\t\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\t\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\t\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:54'!\\ndestroy\\n\\t\\\"Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil ifFalse: \\n\\t\\t[self isValid ifTrue: [self primSocketDestroy: socketHandle].\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\tsocketHandle _ nil.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil.\\n\\t\\tself unregister].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 23:04'!\\ninitialize: socketType\\n\\t\\\"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil.\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _\\n\\t\\tself primSocketCreateNetwork: 0\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'mir 2/22/2002 15:48'!\\ninitializeNetwork\\n\\tself class initializeNetwork! !\\n\\n\\n!Socket methodsFor: 'other' stamp: 'mir 2/22/2002 16:25'!\\ngetOption: aName \\n\\t\\\"Get options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is an status number (0 ok, -1 read only option)\\n\\telement two is the resulting of the requested option\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [InvalidSocketStatusException signal: 'Socket status must valid before getting an option'].\\n\\t^self primSocket: socketHandle getOption: aName\\n\\n\\\"| foo options |\\nSocket initializeNetwork.\\nfoo _ Socket newTCP.\\nfoo connectTo: (NetNameResolver addressFromString: '192.168.1.1') port: 80.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\noptions _ {\\n'SO_DEBUG'. 'SO_REUSEADDR'. 'SO_REUSEPORT'. 'SO_DONTROUTE'.\\n'SO_BROADCAST'. 'SO_SNDBUF'. 'SO_RCVBUF'. 'SO_KEEPALIVE'.\\n'SO_OOBINLINE'. 'SO_PRIORITY'. 'SO_LINGER'. 'SO_RCVLOWAT'.\\n'SO_SNDLOWAT'. 'IP_TTL'. 'IP_HDRINCL'. 'IP_RCVOPTS'.\\n'IP_RCVDSTADDR'. 'IP_MULTICAST_IF'. 'IP_MULTICAST_TTL'.\\n'IP_MULTICAST_LOOP'. 'UDP_CHECKSUM'. 'TCP_MAXSEG'.\\n'TCP_NODELAY'. 'TCP_ABORT_THRESHOLD'. 'TCP_CONN_NOTIFY_THRESHOLD'. \\n'TCP_CONN_ABORT_THRESHOLD'. 'TCP_NOTIFY_THRESHOLD'.\\n'TCP_URGENT_PTR_TYPE'}.\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\nfoo _ Socket newUDP.\\nfoo setPeer: (NetNameResolver addressFromString: '192.168.1.9') port: 7.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\\"! !\\n\\n!Socket methodsFor: 'other' stamp: 'mir 2/22/2002 16:30'!\\nsetOption: aName value: aValue \\n\\t| value |\\n\\t\\\"setup options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is the error number\\n\\telement two is the resulting of the negotiated value.\\n\\tSee getOption for list of keys\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [InvalidSocketStatusException signal: 'Socket status must valid before setting an option'].\\n\\tvalue _ aValue asString.\\n\\taValue == true ifTrue: [value _ '1'].\\n\\taValue == false ifTrue: [value _ '0'].\\n\\t^ self primSocket: socketHandle setOption: aName value: value! !\\n\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept' module: 'SocketPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:55'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^self primAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex ! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID connectTo: hostAddress port: port\\n\\t\\\"Attempt to establish a connection to the given port of the given host. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectToPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 21:48'!\\nprimSocket: socketID getOption: aString \\n\\t\\\"Get some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the option value\\\"\\n\\n\\t<primitive: 'primitiveSocketGetOptions' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID listenOn: port\\n\\t\\\"Listen for a connection on the given port. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ikp 9/1/2003 20:33'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenOnPortBacklogInterface' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID receiveDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. Return the number of bytes read or zero if no data is available.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/24/2000 17:19'!\\nprimSocket: socketID receiveUDPDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. \\n\\tReturn an Array containing the amount read, the host address byte array, the host port, and the more flag\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID sendData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 00:08'!\\nprimSocket: socketID sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 7/18/2000 11:42'!\\nprimSocket: socketID setOption: aString value: aStringValue\\n\\t\\\"Set some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the negotiated value\\\"\\n\\n\\t<primitive: 'primitiveSocketSetOptions' module: 'SocketPlugin'>\\n\\t^nil! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID setPort: port\\n\\t\\\"Set the local port associated with a UDP socket.\\n\\tNote: this primitive is overloaded. The primitive will not fail on a TCP socket, but\\n\\tthe effects will not be what was desired. Best solution would be to split Socket into\\n\\ttwo subclasses, TCPSocket and UDPSocket.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketAbortConnection: socketID\\n\\t\\\"Terminate the connection on the given port immediately without going through the normal close sequence. This is an asynchronous call; query the socket status to discover if and when the connection is actually terminated.\\\"\\n\\n\\t<primitive: 'primitiveSocketAbortConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCloseConnection: socketID\\n\\t\\\"Close the connection on the given port. The remote end is informed that this end has closed and will do no further sends. This is an asynchronous call; query the socket status to discover if and when the connection is actually closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCloseConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketConnectionStatus: socketID\\n\\t\\\"Return an integer reflecting the connection status of this socket. For a list of possible values, see the comment in the 'initialize' method of this class. If the primitive fails, return a status indicating that the socket handle is no longer valid, perhaps because the Squeak image was saved and restored since the socket was created. (Sockets do not survive snapshots.)\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectionStatus' module: 'SocketPlugin'>\\n\\t^ InvalidSocket\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex\\n\\t\\\"Return a new socket handle for a socket of the given type and buffer sizes. Return nil if socket creation fails.\\n\\tThe netType parameter is platform dependent and can be used to encode both the protocol type (IP, Xerox XNS, etc.) and/or the physical network interface to use if this host is connected to multiple networks. A zero netType means to use IP protocols and the primary (or only) network interface.\\n\\tThe socketType parameter specifies:\\n\\t\\t0\\treliable stream socket (TCP if the protocol is IP)\\n\\t\\t1\\tunreliable datagram socket (UDP if the protocol is IP)\\n\\tThe buffer size parameters allow performance to be tuned to the application. For example, a larger receive buffer should be used when the application expects to be receiving large amounts of data, especially from a host that is far away. These values are considered requests only; the underlying implementation will ensure that the buffer sizes actually used are within allowable bounds. Note that memory may be limited, so an application that keeps many sockets open should use smaller buffer sizes. Note the macintosh implementation ignores this buffer size. Also see setOption to get/set socket buffer sizes which allows you to set/get the current buffer sizes for reading and writing.\\n \\tIf semaIndex is > 0, it is taken to be the index of a Semaphore in the external objects array to be associated with this socket. This semaphore will be signalled when the socket status changes, such as when data arrives or a send completes. All processes waiting on the semaphore will be awoken for each such event; each process must then query the socket state to figure out if the conditions they are waiting for have been met. For example, a process waiting to send some data can see if the last send has completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate' module: 'SocketPlugin'>\\n\\t^ nil \\\"socket creation failed\\\"\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:48'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"See comment in primSocketCreateNetwork: with one semaIndex. However you should know that some implementations\\n\\tignore the buffer size and this interface supports three semaphores, one for open/close/listen and the other two for\\n\\treading and writing\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^ self primSocketCreateNetwork: netType\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: rcvBufSize\\n\\t\\t\\tsendBufSize: sendBufSize\\n\\t\\t\\tsemaIndex: semaIndex! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroy: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroyGently: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\n\\tDo not fail if the receiver is already closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketError: socketID\\n\\t\\\"Return an integer encoding the most recent error on this socket. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveSocketError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalAddress: socketID\\n\\t\\\"Return the local host address for this socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalPort: socketID\\n\\t\\\"Return the local port for this socket, or zero if no port has yet been assigned.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketReceiveDataAvailable: socketID\\n\\t\\\"Return true if data may be available for reading from the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataAvailable' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemoteAddress: socketID\\n\\t\\\"Return the remote host address for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemoteAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemotePort: socketID\\n\\t\\\"Return the remote port for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemotePort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketSendDone: socketID\\n\\t\\\"Return true if there is no send in progress on the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDone' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!Socket methodsFor: 'printing' stamp: 'jm 11/23/1998 11:57'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '[', self statusString, ']'.\\n! !\\n\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\ndataAvailable\\n\\t\\\"Return true if this socket has unread received data.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketReceiveDataAvailable: socketHandle\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\nisConnected\\n\\t\\\"Return true if this socket is connected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Connected\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:15'!\\nisOtherEndClosed\\n\\t\\\"Return true if this socket had the other end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == OtherEndClosed\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:17'!\\nisThisEndClosed\\n\\t\\\"Return true if this socket had the this end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == ThisEndClosed\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnected\\n\\t\\\"Return true if this socket's state is Unconnected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Unconnected\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnectedOrInvalid\\n\\t\\\"Return true if this socket is completely disconnected or is invalid.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ true].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ (status = Unconnected) | (status = InvalidSocket)\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:51'!\\nisValid\\n\\t\\\"Return true if this socket contains a valid, non-nil socket handle.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ status ~= InvalidSocket\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisWaitingForConnection\\n\\t\\\"Return true if this socket is waiting for a connection.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == WaitingForConnection\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nsendDone\\n\\t\\\"Return true if the most recent send operation on this socket has completed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketSendDone: socketHandle\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/8/2000 23:24'!\\nsocketError\\n\\t^self primSocketError: socketHandle! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:56'!\\nstatusString\\n\\t\\\"Return a string describing the status of this socket.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ 'destroyed'].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tstatus = InvalidSocket ifTrue: [^ 'invalidSocketHandle'].\\n\\tstatus = Unconnected ifTrue: [^ 'unconnected'].\\n\\tstatus = WaitingForConnection ifTrue: [^ 'waitingForConnection'].\\n\\tstatus = Connected ifTrue: [^ 'connected'].\\n\\tstatus = OtherEndClosed ifTrue: [^ 'otherEndClosedButNotThisEnd'].\\n\\tstatus = ThisEndClosed ifTrue: [^ 'thisEndClosedButNotOtherEnd'].\\n\\t^ 'unknown socket status'\\n! !\\n\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 12/14/2005 10:02'!\\ndiscardReceivedData\\n\\t\\\"Discard any data received up until now, and return the number of bytes discarded.\\\"\\n\\n\\t| buf totalBytesDiscarded |\\n\\tbuf _ String new: 10000.\\n\\ttotalBytesDiscarded _ 0.\\n\\t[self isConnected] whileTrue: [\\n\\t\\ttotalBytesDiscarded _\\n\\t\\t\\ttotalBytesDiscarded + (self receiveDataInto: buf)].\\n\\t^ totalBytesDiscarded\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:52'!\\nreceiveAvailableData\\n\\t\\\"Receive all available data (if any). Do not wait.\\\"\\n \\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveAvailableDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'yo 10/10/2005 18:47'!\\nreceiveAvailableDataIntoBuffer: buffer\\n\\t\\\"Receive all available data (if any). Do not wait.\\\"\\n \\n\\t| bytesRead |\\n\\tbytesRead _ self receiveAvailableDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:52'!\\nreceiveAvailableDataInto: buffer\\n\\t\\\"Receive all available data into the given buffer and return the number of bytes received.\\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tDo not wait for data.\\\"\\n\\n\\t^self receiveAvailableDataInto: buffer startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mu 8/9/2003 18:04'!\\nreceiveAvailableDataInto: buffer startingAt: startIndex\\n\\t\\\"Receive all available data into the given buffer and return the number of bytes received.\\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tDo not wait for data.\\\"\\n\\n\\t| bufferPos bytesRead |\\n\\tbufferPos := startIndex.\\n\\t[self dataAvailable\\n\\t\\tand: [bufferPos-1 < buffer size]] \\n\\t\\twhileTrue: [\\n\\t\\t\\tbytesRead := self receiveSomeDataInto: buffer startingAt: bufferPos.\\n\\t\\t\\tbufferPos := bufferPos + bytesRead].\\n\\t^bufferPos - startIndex! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:05'!\\nreceiveData\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:05'!\\nreceiveDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t^self receiveDataInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:12'!\\nreceiveDataInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once. The answer may be zero (indicating that no data was \\n\\tavailable before the socket closed).\\\"\\n\\n\\t| bytesRead closed |\\n\\tbytesRead := 0.\\n\\tclosed := false.\\n\\t[closed not and: [bytesRead == 0]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tself waitForDataIfClosed: [closed := true].\\n\\t\\t\\tbytesRead := self primSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\t\\t\\tstartingAt: aNumber\\n\\t\\t\\t\\tcount: aStringOrByteArray size-aNumber+1].\\n\\t^bytesRead\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 2/9/2005 12:33'!\\nreceiveDataSignallingClosedInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data until something is read or the socket is closed, upon which\\n\\twe signal.\\\"\\n\\n\\t| bytesRead |\\n\\tbytesRead := 0.\\n\\t[bytesRead == 0]\\n\\t\\twhileTrue: [\\n\\t\\t\\tself waitForData.\\n\\t\\t\\tbytesRead := self primSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\t\\t\\tstartingAt: aNumber\\n\\t\\t\\t\\tcount: aStringOrByteArray size-aNumber+1].\\n\\t^bytesRead\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 2/9/2005 12:24'!\\nreceiveDataSignallingTimeout: timeout into: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWait for data once for the specified nr of seconds. This method will\\n\\tthrow exceptions on timeout or the socket closing.\\\"\\n\\n\\tself waitForDataFor: timeout.\\n\\t^self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:03'!\\nreceiveDataTimeout: timeout\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataTimeout: timeout into: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:01'!\\nreceiveDataTimeout: timeout into: aStringOrByteArray \\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t^self receiveDataTimeout: timeout into: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/22/2003 23:58'!\\nreceiveDataTimeout: timeout into: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWait for data once for the specified nr of seconds. The answer may be \\n\\tzero (indicating that there was no data available within the given timeout).\\\"\\n\\n\\tself waitForDataFor: timeout ifClosed: [] ifTimedOut: [].\\n\\t^self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:18'!\\nreceiveDataWithTimeout\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataWithTimeoutInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:18'!\\nreceiveDataWithTimeoutInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t^self receiveDataWithTimeoutInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:01'!\\nreceiveDataWithTimeoutInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t^self receiveDataTimeout: Socket standardTimeout into: aStringOrByteArray startingAt: aNumber \\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeData\\n\\t\\\"Receive currently available data (if any). Do not wait.\\\"\\n \\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveSomeDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^self receiveSomeDataInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeDataInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n\\n!Socket methodsFor: 'registry' stamp: 'ar 3/21/98 17:40'!\\nregister\\n\\t^self class register: self! !\\n\\n!Socket methodsFor: 'registry' stamp: 'ar 3/21/98 17:41'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 5/15/2003 18:33'!\\nsendData: aStringOrByteArray\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent.\\\"\\n\\n\\t\\\"An experimental version use on slow lines: Longer timeout and smaller writes to try to avoid spurious timeouts.\\\"\\n\\n\\t| bytesSent bytesToSend count |\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneFor: 60)\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 5000).\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ar 7/20/1999 17:23'!\\nsendData: buffer count: n\\n\\t\\\"Send the amount of data from the given buffer\\\"\\n\\t| sent |\\n\\tsent _ 0.\\n\\t[sent < n] whileTrue:[\\n\\t\\tsent _ sent + (self sendSomeData: buffer startIndex: sent+1 count: (n-sent))].! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ls 1/5/1999 15:05'!\\nsendSomeData: aStringOrByteArray\\n\\t\\\"Send as much of the given data as possible and answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: 1\\n\\t\\tcount: aStringOrByteArray size! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ls 3/3/1999 18:59'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex\\n\\t\\\"Send as much of the given data as possible starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: startIndex\\n\\t\\tcount: (aStringOrByteArray size - startIndex + 1)! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 5/15/2003 18:34'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send up to count bytes of the given data starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t| bytesSent |\\n\\t(self waitForSendDoneFor: 20)\\n\\t\\tifTrue: [\\n\\t\\t\\tbytesSent _ self primSocket: socketHandle\\n\\t\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\t\\tstartIndex: startIndex\\n\\t\\t\\t\\tcount: count]\\n\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 2/19/2002 18:33'!\\nsendStreamContents: stream\\n\\t\\\"Send the data in the stream. Close the stream.\\n\\tUsefull for directly sending contents of a file without reading into memory first.\\\"\\n\\n\\tself sendStreamContents: stream checkBlock: [true]! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 2/19/2002 18:31'!\\nsendStreamContents: stream checkBlock: checkBlock\\n\\t\\\"Send the data in the stream. Close the stream after you are done. After each block of data evaluate checkBlock and abort if it returns false.\\n\\tUsefull for directly sending contents of a file without reading into memory first.\\\"\\n\\n\\t| chunkSize buffer |\\n\\tchunkSize _ 5000.\\n\\tbuffer _ ByteArray new: chunkSize.\\n\\tstream binary.\\n\\t[[stream atEnd and: [checkBlock value]]\\n\\t\\twhileFalse: [\\n\\t\\t\\tbuffer _ stream next: chunkSize into: buffer.\\n\\t\\t\\tself sendData: buffer]]\\n\\t\\tensure: [stream close]! !\\n\\n\\n!Socket methodsFor: 'waiting' stamp: 'mu 8/9/2003 15:17'!\\nwaitForAcceptFor: timeout\\n\\t\\\"Wait and accept an incoming connection. Return nil if it falis\\\"\\n\\t[self waitForConnectionFor: timeout] on: ConnectionTimedOut do: [:ex | ^nil].\\n\\t^self isConnected\\n\\t\\tifTrue:[self accept]\\n\\t\\t! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:23'!\\nwaitForAcceptFor: timeout ifTimedOut: timeoutBlock\\n\\t\\\"Wait and accept an incoming connection\\\"\\n\\tself waitForConnectionFor: timeout ifTimedOut: [^timeoutBlock value].\\n\\t^self accept! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'mu 8/19/2003 02:57'!\\nwaitForConnectionFor: timeout\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t^self \\n\\t\\twaitForConnectionFor: timeout \\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Failed to connect in ', timeout asString, ' seconds']\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'gk 12/15/2005 01:09'!\\nwaitForConnectionFor: timeout ifTimedOut: timeoutBlock\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t| status deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\tstatus = Connected ifFalse: [^timeoutBlock value]\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 9/23/2003 00:09'!\\nwaitForData\\n\\t\\\"Wait for data to arrive. This method will block until\\n\\tdata is available or the socket is closed. If the socket is closed\\n\\ta ConnectionClosed exception will be signaled.\\\"\\n\\n\\t^self waitForDataIfClosed:\\n\\t\\t[ConnectionClosed signal: 'Connection close while waiting for data.']! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:18'!\\nwaitForDataFor: timeout\\n\\t\\\"Wait for the given nr of seconds for data to arrive.\\n\\tSignal a time out or connection close exception if either happens before data becomes available.\\\"\\n\\n\\t^self\\n\\t\\twaitForDataFor: timeout\\n\\t\\tifClosed: [ConnectionClosed signal: 'Connection closed while waiting for data.']\\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Data receive timed out.']\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:16'!\\nwaitForDataFor: timeout ifClosed: closedBlock ifTimedOut: timedOutBlock\\n\\t\\\"Wait for the given nr of seconds for data to arrive.\\\"\\n\\n\\t| deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\n\\t[Time millisecondClockValue < deadline]\\n\\t\\twhileTrue: [\\n\\t\\t\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\t\\t\\tifTrue: [^self].\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifFalse: [^closedBlock value].\\n\\t\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\tifFalse: [\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifTrue: [^timedOutBlock value]\\n\\t\\t\\t\\tifFalse: [^closedBlock value]]! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 9/23/2003 00:08'!\\nwaitForDataIfClosed: closedBlock\\n\\t\\\"Wait indefinitely for data to arrive. This method will block until\\n\\tdata is available or the socket is closed.\\\"\\n\\n\\t[true]\\n\\t\\twhileTrue: [\\n\\t\\t\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\t\\t\\tifTrue: [^self].\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifFalse: [^closedBlock value].\\n\\t\\t\\tself readSemaphore wait].\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'gk 12/14/2005 09:59'!\\nwaitForDisconnectionFor: timeout\\n\\t\\\"Wait for the given nr of seconds for the connection to be broken.\\n\\tReturn true if it is broken by the deadline, false if not.\\n\\tThe client should know the connection is really going to be closed\\n\\t(e.g., because he has called 'close' to send a close request to the other end)\\n\\tbefore calling this method.\\\"\\n\\n\\t| status deadline |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\t[((status == Connected) or: [(status == ThisEndClosed)]) and:\\n\\t [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\tself discardReceivedData.\\n\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\t^ status ~= Connected\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'mir 5/15/2003 18:33'!\\nwaitForSendDoneFor: timeout\\n\\t\\\"Wait up until the given deadline for the current send operation to complete. Return true if it completes by the deadline, false if not.\\\"\\n\\n\\t| sendDone deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\t[self isConnected & (sendDone _ self primSocketSendDone: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself writeSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ sendDone! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!Socket class methodsFor: 'class initialization' stamp: 'ar 12/12/2001 19:12'!\\ninitialize\\n\\t\\\"Socket initialize\\\"\\n\\n\\t\\\"Socket Types\\\"\\n\\tTCPSocketType _ 0.\\n\\tUDPSocketType _ 1.\\n\\n\\t\\\"Socket Status Values\\\"\\n\\tInvalidSocket _ -1.\\n\\tUnconnected _ 0.\\n\\tWaitingForConnection _ 1.\\n\\tConnected _ 2.\\n\\tOtherEndClosed _ 3.\\n\\tThisEndClosed _ 4.\\n\\n\\tRegistryThreshold _ 100. \\\"# of sockets\\\"! !\\n\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:45'!\\nacceptFrom: aSocket\\n\\t^[ super new acceptFrom: aSocket ]\\n\\t\\trepeatWithGCIf: [ :sock | sock isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:15'!\\ncreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\t\\\"Note: The default creates a TCP socket\\\"\\n\\t^self tcpCreateIfFail: failBlock! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:13'!\\nnew\\n\\t\\\"Return a new, unconnected Socket. Note that since socket creation may fail, it is safer to use the method createIfFail: to handle such failures gracefully; this method is primarily for backward compatibility and may be disallowed in a future release.\\\"\\n\\t\\\"Note: The default creates a TCP socket - this is also backward compatibility.\\\"\\n\\t^self newTCP! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:48'!\\nnewTCP\\n\\t\\\"Create a socket and initialise it for TCP\\\"\\n\\tself initializeNetwork.\\n\\t^[ super new initialize: TCPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\nnewUDP\\n\\t\\\"Create a socket and initialise it for UDP\\\"\\n\\tself initializeNetwork.\\n\\t^[ super new initialize: UDPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\ntcpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tself initializeNetwork.\\n\\tsock _ super new initialize: TCPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\nudpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tself initializeNetwork.\\n\\tsock _ super new initialize: UDPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n\\n!Socket class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 15:01'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and the NetNameResolver. Do nothing if the network is already initialized.\\\"\\n\\t\\\"Note: The network must be re-initialized every time Squeak starts up, so applications that persist across snapshots should be prepared to re-initialize the network as needed. Such applications should call 'Socket initializeNetwork' before every network transaction. \\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n!Socket class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 14:59'!\\nprimInitializeNetwork: resolverSemaIndex\\n\\t\\\"Initialize the network drivers on platforms that need it, such as the Macintosh, and return nil if network initialization failed or the reciever if it succeeds. Since mobile computers may not always be connected to a network, this method should NOT be called automatically at startup time; rather, it should be called when first starting a networking application. It is a noop if the network driver has already been initialized. If non-zero, resolverSemaIndex is the index of a VM semaphore to be associated with the network name resolver. This semaphore will be signalled when the resolver status changes, such as when a name lookup query is completed.\\\"\\n\\t\\\"Note: some platforms (e.g., Mac) only allow only one name lookup query at a time, so a manager process should be used to serialize resolver lookup requests.\\\"\\n\\n\\t<primitive: 'primitiveInitializeNetwork' module: 'SocketPlugin'>\\n\\t^ nil \\\"return nil if primitive fails\\\"\\n! !\\n\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\t^RegistryThreshold! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold: aNumber\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\tRegistryThreshold _ aNumber! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:22'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\n\\n\\n!Socket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:54'!\\ndeadServer\\n\\n\\t^ DeadServer! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:56'!\\ndeadServer: aStringOrNil\\n\\t\\\"Keep the machine name of the most recently encoutered non-responding machine. Next time the user can move it to the last in a list of servers to try.\\\"\\n\\n\\tDeadServer _ aStringOrNil! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 18:28'!\\ndeadlineSecs: secs\\n\\t\\\"Return a deadline time the given number of seconds from now.\\\"\\n\\n\\t^ Time millisecondClockValue + (secs * 1000) truncated\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 12:13'!\\nnameForWellKnownTCPPort: portNum\\n\\t\\\"Answer the name for the given well-known TCP port number. Answer a string containing the port number if it isn't well-known.\\\"\\n\\n\\t| portList entry |\\n\\tportList _ #(\\n\\t\\t(7 'echo') (9 'discard') (13 'time') (19 'characterGenerator')\\n\\t\\t(21 'ftp') (23 'telnet') (25 'smtp')\\n\\t\\t(80 'http') (110 'pop3') (119 'nntp')).\\n\\tentry _ portList detect: [:pair | pair first = portNum] ifNone: [^ 'port-', portNum printString].\\n\\t^ entry last\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 18:30'!\\nping: hostName\\n\\t\\\"Ping the given host. Useful for checking network connectivity. The host must be running a TCP echo server.\\\"\\n\\t\\\"Socket ping: 'squeak.cs.uiuc.edu'\\\"\\n\\n\\t| tcpPort sock serverAddr startTime echoTime |\\n\\ttcpPort _ 7. \\\"7 = echo port, 13 = time port, 19 = character generator port\\\"\\n\\n\\tserverAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil ifTrue: [\\n\\t\\t^ self inform: 'Could not find an address for ', hostName].\\n\\n\\tsock _ Socket new.\\n\\tsock connectNonBlockingTo: serverAddr port: tcpPort.\\n\\t[sock waitForConnectionFor: 10]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex |\\n\\t\\t\\t(self confirm: 'Continue to wait for connection to ', hostName, '?')\\n\\t\\t\\t\\tifTrue: [ex retry]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tsock destroy.\\n\\t\\t\\t\\t\\t^ self]].\\n\\n\\tsock sendData: 'echo!!'.\\n\\tstartTime _ Time millisecondClockValue.\\n\\t[sock waitForDataFor: 15]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | (self confirm: 'Packet sent but no echo yet; keep waiting?')\\n\\t\\t\\tifTrue: [ex retry]].\\n\\techoTime _ Time millisecondClockValue - startTime.\\n\\n\\tsock destroy.\\n\\tself inform: hostName, ' responded in ', echoTime printString, ' milliseconds'.\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 2/22/2002 15:49'!\\npingPorts: portList on: hostName timeOutSecs: timeOutSecs\\n\\t\\\"Attempt to connect to each of the given sockets on the given host. Wait at most timeOutSecs for the connections to be established. Answer an array of strings indicating the available ports.\\\"\\n\\t\\\"Socket pingPorts: #(7 13 19 21 23 25 80 110 119) on: 'squeak.cs.uiuc.edu' timeOutSecs: 15\\\"\\n\\n\\t| serverAddr sockets sock deadline done unconnectedCount connectedCount waitingCount result |\\n\\tserverAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil ifTrue: [\\n\\t\\tself inform: 'Could not find an address for ', hostName.\\n\\t\\t^ #()].\\n\\n\\tsockets _ portList collect: [:portNum |\\n\\t\\tsock _ Socket new.\\n\\t\\tsock connectTo: serverAddr port: portNum].\\n\\n\\tdeadline _ self deadlineSecs: timeOutSecs.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tunconnectedCount _ 0.\\n\\t\\tconnectedCount _ 0.\\n\\t\\twaitingCount _ 0.\\n\\t\\tsockets do: [:s |\\n\\t\\t\\ts isUnconnectedOrInvalid\\n\\t\\t\\t\\tifTrue: [unconnectedCount _ unconnectedCount + 1]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\ts isConnected ifTrue: [connectedCount _ connectedCount + 1].\\n\\t\\t\\t\\t\\ts isWaitingForConnection ifTrue: [waitingCount _ waitingCount + 1]]].\\n\\t\\twaitingCount = 0 ifTrue: [done _ true].\\n\\t\\tconnectedCount = sockets size ifTrue: [done _ true].\\n\\t\\tTime millisecondClockValue > deadline ifTrue: [done _ true]].\\n\\n\\tresult _ (sockets select: [:s | s isConnected])\\n\\t\\tcollect: [:s | self nameForWellKnownTCPPort: s remotePort].\\n\\tsockets do: [:s | s destroy].\\n\\t^ result\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 17:25'!\\npingPortsOn: hostName\\n\\t\\\"Attempt to connect to a set of well-known sockets on the given host, and answer the names of the available ports.\\\"\\n\\t\\\"Socket pingPortsOn: 'www.disney.com'\\\"\\n\\n\\t^ Socket\\n\\t\\tpingPorts: #(7 13 19 21 23 25 80 110 119)\\n\\t\\ton: hostName\\n\\t\\ttimeOutSecs: 20\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 16:17'!\\nstandardDeadline\\n\\t\\\"Return a default deadline time some seconds into the future.\\\"\\n\\n\\t^ self deadlineSecs: self standardTimeout\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 16:16'!\\nstandardTimeout\\n\\n\\t^45\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardAddress\\n\\t\\\"Answer a don't-care address for use with UDP sockets.\\\"\\n\\n\\t^ByteArray new: 4\\t\\t\\\"0.0.0.0\\\"! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardPort\\n\\t\\\"Answer a don't-care port for use with UDP sockets. (The system will allocate an\\n\\tunused port number to the socket.)\\\"\\n\\n\\t^0! !\\n\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:18'!\\nloopbackTest\\n\\t\\\"Send data from one socket to another on the local machine.\\n\\tTests most of the socket primitives.\\\"\\n\\n\\t\\\"100 timesRepeat: [Socket loopbackTest]\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived t extraBytes packetsSent packetsRead |\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'starting loopback test';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: '---------- Connecting ----------';\\n\\t\\tcr.\\n\\tself initializeNetwork.\\n\\tsock1 := self new.\\n\\tsock2 := self new.\\n\\tsock1 listenOn: 54321.\\n\\tsock2 connectTo: NetNameResolver localHostAddress port: 54321.\\n\\tsock1 waitForConnectionFor: self standardTimeout.\\n\\tsock2 waitForConnectionFor: self standardTimeout.\\n\\tsock1 isConnected ifFalse: [self error: 'sock1 not connected'].\\n\\tsock2 isConnected ifFalse: [self error: 'sock2 not connected'].\\n\\tTranscript\\n\\t\\tshow: 'connection established';\\n\\t\\tcr.\\n\\tbytesToSend := 5000000.\\n\\tsendBuf := String new: 5000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tpacketsSent := packetsRead := bytesSent := bytesReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 sendSomeData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsRead := packetsRead + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (sock2 receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend and: [bytesReceived = bytesSent]]].\\n\\tTranscript\\n\\t\\tshow: 'closing connection';\\n\\t\\tcr.\\n\\tsock1 waitForSendDoneFor: self standardTimeout.\\n\\tsock1 close.\\n\\tsock2 waitForDisconnectionFor: self standardTimeout.\\n\\textraBytes := sock2 discardReceivedData.\\n\\textraBytes > 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[Transcript\\n\\t\\t\\t\\tshow: ' *** received ' , extraBytes size printString , ' extra bytes ***';\\n\\t\\t\\t\\tcr].\\n\\tsock2 close.\\n\\tsock1 waitForDisconnectionFor: self standardTimeout.\\n\\tsock1 isUnconnectedOrInvalid ifFalse: [self error: 'sock1 not closed'].\\n\\tsock2 isUnconnectedOrInvalid ifFalse: [self error: 'sock2 not closed'].\\n\\tTranscript\\n\\t\\tshow: '---------- Connection Closed ----------';\\n\\t\\tcr.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'loopback test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesToSend asFloat / t roundTo: 0.01) printString \\n\\t\\t\\t\\t\\t, '* 1000 bytes/sec';\\n\\t\\tcr.\\n\\tTranscript endEntry! !\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:03'!\\nnewAcceptCheck\\n\\t\\\"Check if the platform has support for the BSD style accept().\\\"\\n\\n\\t\\\"Socket newAcceptCheck\\\"\\n\\t\\n\\t| socket |\\n\\tself initializeNetwork.\\n\\tsocket _ self newTCP.\\n\\tsocket listenOn: 44444 backlogSize: 4.\\n\\tsocket isValid ifTrue: [\\n\\t\\tself inform: 'Everything looks OK for the BSD style accept()'\\n\\t] ifFalse: [\\n\\t\\tself inform: 'It appears that you DO NOT have support for the BSD style accept()'].\\n\\tsocket destroy! !\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:10'!\\nsendTest\\n\\t\\\"Send data to the 'discard' socket of the given host.\\n\\tTests the speed of one-way data transfers across the\\n\\tnetwork to the given host. Note that most hosts\\n\\tdo not run a discard server.\\\"\\n\\n\\t\\\"Socket sendTest\\\"\\n\\n\\t| sock bytesToSend sendBuf bytesSent t serverName serverAddr |\\n\\tTranscript cr; show: 'starting send test'; cr.\\n\\tself initializeNetwork.\\n\\tserverName := UIManager default request: 'What is the destination server?' initialAnswer: 'create.ucsb.edu'.\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [^self inform: 'Could not find an address for ' , serverName].\\n\\tsock := self new.\\n\\tTranscript show: '---------- Connecting ----------';cr.\\n\\tsock connectTo: serverAddr port: 9.\\n\\tsock isConnected ifFalse: [\\n\\t\\tsock destroy.\\n\\t\\t^self inform: 'could not connect'].\\n\\tTranscript show: 'connection established; sending data'; cr.\\n\\tbytesToSend := 1000000.\\n\\tsendBuf := String new: 64 * 1024 withAll: $x.\\n\\tbytesSent := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[bytesSent < bytesToSend] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t[sock sendDone \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [bytesSent := bytesSent + (sock sendSomeData: sendBuf)]]].\\n\\tsock waitForSendDoneFor: self standardTimeout.\\n\\tsock destroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr;\\n\\t\\tshow: 'send test done; time = ' , t printString; cr;\\n\\t\\tshow: (bytesToSend asFloat / t roundTo: 0.01) printString, ' * 1000 bytes/sec';cr;endEntry! !\\nObject subclass: #SocketStream\\n\\tinstanceVariableNames: 'recentlyRead socket inBuffer outBuffer inNextToWrite outNextToWrite lastRead timeout autoFlush bufferSize binary shouldSignal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!SocketStream commentStamp: 'md 7/14/2006 16:32' prior: 0!\\nSocketStream is a wrapper for class Socket making it easy to write networking code by giving the programmer a stream-like protocol. A Socket is a two way communication link with two logically separate channels - input and output. The Socket class is the lowest level in Squeak for network communication and using it directly can be difficult and bug prone.\\n\\nA SocketStream can be in binary or ascii mode, ascii is the default which means you are transmitting and receiving Strings. Most Internet protocols are in clear text ascii, like for example HTTP. Another setting is what timeout you want to use - default is the standardTimeout from Socket. More settings can be found in the method category 'configuration'.\\n\\nSimplest example of connecting, sending/receiving and closing:\\n\\n| stream result |\\nstream := SocketStream openConnectionToHostNamed: 'www.squeak.org' port: 80.\\n[[stream nextPutAll: 'GET / HTTP/1.0'; crlf; crlf; flush.\\nresult := stream upToEnd. \\\"Give us all data until the socket is closed.\\\"\\nTranscript show: result; cr.]\\n\\tensure: [stream close]]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | Transcript show: ex asString;cr. ex resume]\\n\\nThere are two important things to note above:\\n\\t- The methods in category \\\"stream in\\\" can signal two exceptions (unless turned off with #shouldSignal:):\\n\\t\\tConnectionClosed and ConnectionTimedOut\\n\\t- We close the stream using #ensure:, that is to make sure it isn't left opened.\\n\\t- We use #on:do: to catch any signal. In this case we do not need to catch ConnectionClosed since #upToEnd does that for us intrinsically.\\n\\n----------------\\nSocketStream (below called SS) is a reimplementation of 'Old'-SocketStream (below called OSS) - the class that originates from the original Comanche implementation but now is included in standard Squeak. SS has the same protocol as OSS and is meant to replace it. SS is faster, more flexible, is better documented and adds a few features:\\n\\n1. #shouldSignal:, which decides if SS should signal low level Socket exceptions (true) or if it should swallow them like original OSS did. Default is true. The only reason I added this is for backwards compatibility - not signalling causes problems - see bug 4 below.\\n\\n2. #nextAllInBuffer, #nextInBuffer:, #skip:, #receiveData:, #nextPutAllFlush: and #recentlyRead are new additions to the public protocol.\\n\\n\\nIt also fixes various bugs:\\n\\n1. #isDataAvailable could theoretically answer false, when there actually is some in the buffer in OSS. If #receiveDataIfAvailable reads the last byte then the following \\\"socket dataAvailable\\\" would answer false. So the last byte would be sitting in the inStream missed.\\n\\n2. #upToAll: in OSS has several problems, for example - #positionOfSubCollection:ifAbsent: which was introduced answers one position too low. This was compensated in upToAll:, but only in the pushBack: call, not the actual result being returned which was cut short 1 byte. Amusingly this makes KomHttpServer not use \\\"Keep-Alive\\\" since the last $e in 'Alive' was cut short. :)\\n\\n3. SS doesn't inherit from PositionableStream since that just breaks various inherited messages, like for example #skip:. OSS should IMHO be changed to inherit from Object - or of course, replaced in full with SS. :)\\n\\n4. Since SocketStream by default signals closes and timeouts the SocketStreamTest now passes. The reason for SocketStream to fail is that while it does timeout on a low level (#SocketStream>>receiveData doesn't hang forever) - the callers of #receiveData sometimes loop - like in #next:, and thus eliminates the timeout. SS warns about some methods (in their method comments) not honouring timeouts if shouldSignal is false, I really don't know what they should do in that case:\\n\\t#next:, #upTo:, #upToAll: and #upToEnd (and #receiveData:)\\n\\n\\nThe primary reason for the SS implementation is optimal performance. The main differences in implementation with the old OSS are:\\n\\n1. SS uses two buffers directly (inBuffer and outBuffer) with pointers marking start and stop within the buffer. OSS instead uses two regular streams, a ReadStream and a WriteStream. Using internal buffers makes it possible to avoid copying and reallocation in various ways, it also makes SS be able to have specialized growing/buffer moving behaviour.\\n\\n2. #upTo:, #upToAll: and #peekForAll: uses selectged String messages that in turn uses fast primitives for searching. OSS used other messages that fell back on byte per byte reading.\\n\\n3. #receiveData in OSS creates a temporary buffer stream for each call!! During a long read operation, like say #upToAll: (which for example is used when uploading files using HTTP POST forms), this is devastating - especially since the default size is only 2000 bytes - and leads to a very high number of low level read operations on the Socket, typically 100 times more calls than with OSS. The buffer in OSS is held in an instvar (not recreated for each call), is larger from the start and above all - grows dynamically by doubling. OSS can also avoid a grow/reallocation by doing a \\\"move down\\\" if data has been read from the SS as it comes in and through that making room in the lower part of the inBuffer. The net result is that upToAll: for large files is about 10 times faster.\\n\\n4. The implementation of upTo: and upToAll: tries to avoid doing unnecessary find operations in the buffer and is greedy by default, which means it favors reading more data - if available - before searching for the stop sequence. If we had #findString:startingAt:stoppingAt: this wouldn't have to be greedy and we wouldn't be needlessly scanning dead buffer area. VM hackers? Also, while you are at it - make it work for ByteArrays too. :)\\n\\n\\nSS can not be run unbuffered, since that seems unneeded. The option to autoFlush is still available, with it set to true SocketStream (just like OSS) will flush on its own on each nextPut:/nextPutAll:, otherwise flushing it will have to be done manually but is done on close.\\n\\nThe first performance tests shows that, as noted above, receiving large amounts of data using #upToAll: is greatly improved - factor of 10. Serving HTTP with small payloads seemed at first not be faster at all - but this is due to the high overhead of Socket connect/close and other things. Increasing payloads show a difference and especially with keep alive on - where the new SS roughly doubles the throughput!!!\\n\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:37'!\\nascii\\n\\t\\\"Tell the SocketStream to send data\\n\\tas Strings instead of ByteArrays.\\n\\tThis is default.\\\"\\n\\n\\tbinary := false.\\n\\tself resetBuffers! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:26'!\\nautoFlush\\n\\t\\\"If autoFlush is enabled data will be sent through\\n\\tthe socket (flushed) when the bufferSize is reached\\n\\tor the SocketStream is closed. Otherwise the user\\n\\twill have to send #flush manually.\\n\\tClose will always flush. Default is false.\\\"\\n\\n\\t^autoFlush! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:27'!\\nautoFlush: aBoolean\\n\\t\\\"If autoFlush is enabled data will be sent through\\n\\tthe socket (flushed) when the bufferSize is reached\\n\\tor the SocketStream is closed. Otherwise the user\\n\\twill have to send #flush manually.\\n\\tClose will always flush. Default is false.\\\"\\n\\n\\tautoFlush := aBoolean! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:37'!\\nbinary\\n\\t\\\"Tell the SocketStream to send data\\n\\tas ByteArrays instead of Strings.\\n\\tDefault is ascii.\\\"\\n\\n\\tbinary := true.\\n\\tself resetBuffers! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:28'!\\nbufferSize\\n\\t\\\"Default buffer size is 4kb.\\n\\tincreased from earlier 2000 bytes.\\\"\\n\\t\\n\\t^bufferSize! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:28'!\\nbufferSize: anInt\\n\\t\\\"Default buffer size is 4kb.\\n\\tincreased from earlier 2000 bytes.\\\"\\n\\n\\tbufferSize := anInt! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:58'!\\ninBufferSize\\n\\t\\\"Answers the current size of data in the inBuffer.\\\"\\n\\n\\t^inNextToWrite - lastRead - 1! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:59'!\\nnoTimeout\\n\\t\\\"Do not use timeout.\\\"\\n\\n\\ttimeout := 0! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:59'!\\noutBufferSize\\n\\t\\\"Answers the current size of data in the outBuffer.\\\"\\n\\n\\t^outNextToWrite - 1! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 18:00'!\\nshouldSignal\\n\\t\\\"If shouldSignal is enabled the Socket Exceptions\\n\\tConnectionClosed and ConnectionTimedOut\\n\\twill not be swallowed. Default is true.\\n\\tFor more info, see #shouldSignal:\\\"\\n\\n\\t^shouldSignal! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 18:03'!\\nshouldSignal: aBoolean\\n\\t\\\"If shouldSignal is enabled the Socket Exceptions\\n\\tConnectionClosed and ConnectionTimedOut will not be swallowed.\\n\\tDefault is true. And please - don't set it to false - it is better to\\n\\tuse an exception handler (see below) and several methods\\n\\tin this class will not honour timeouts (says so in their method comments).\\n\\tAlso, it is quite hard to understand what for example #upToEnd\\n\\tshould return to indicate a timeout.\\n\\t\\n\\tWrap your use of SocketStream with a handler like:\\n\\t\\n\\t[stuff _ mySocketStream next: 10]\\n\\t\\ton: ConnectionClosed, ConnectionTimedOut\\n\\t\\tdo: [:ex |\\n\\t\\t\\tTranscript show: 'Oops!! Did not get my ten bytes!!;cr]\\n\\t\\\"\\n\\n\\tshouldSignal := aBoolean! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\nsocket\\n\\t^socket! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\nsocket: aSocket\\n\\tsocket _ aSocket! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/7/2005 08:41'!\\ntimeout\\n\\t\\\"Lazily initialized unless it has been set explicitly.\\\"\\n\\n\\ttimeout ifNil: [timeout := Socket standardTimeout].\\n\\t^timeout! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\ntimeout: seconds\\n\\ttimeout := seconds! !\\n\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 2/24/2005 11:55'!\\nclose\\n\\t\\\"Flush any data still not sent\\n\\tand take care of the socket.\\\"\\n\\n\\tself flush.\\n\\tsocket closeAndDestroy: 30! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 9/9/2005 09:33'!\\nflush\\n\\t\\\"If the other end is connected and we have something\\n\\tto send, then we send it and reset the outBuffer.\\\"\\n\\n\\t((outNextToWrite > 1) and: [socket isOtherEndClosed not])\\n\\t\\tifTrue: [\\n\\t\\t\\t[socket sendData: outBuffer count: outNextToWrite - 1]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | shouldSignal ifFalse: [\\\"swallow\\\"]].\\n\\t\\t\\toutNextToWrite _ 1]! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 4/14/2005 09:49'!\\nreceiveData: nBytes\\n\\t\\\"Keep reading the socket until we have nBytes\\n\\tin the inBuffer or we reach the end. This method\\n\\tdoes not return data, but can be used to make sure\\n\\tdata has been read into the buffer from the Socket\\n\\tbefore actually reading it from the FastSocketStream.\\n\\tMainly used internally. We could also adjust the buffer\\n\\tto the expected amount of data and avoiding several\\n\\tincremental grow operations.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal\\n\\tis false!! And frankly, I am not sure how to handle that\\n\\tcase or if I care - I think we should always signal.\\\"\\n\\n\\t[self atEnd not and: [nBytes > self inBufferSize]]\\n\\t\\twhileTrue: [self receiveData]! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 2/9/2005 23:08'!\\nrecentlyRead\\n\\t\\\"Return the number of bytes read\\n\\tduring the last socket operation.\\\"\\n\\t\\n\\t^recentlyRead! !\\n\\n\\n!SocketStream methodsFor: 'initialize-release' stamp: 'gk 2/25/2005 14:20'!\\ninitialize\\n\\tautoFlush _ true.\\n\\tshouldSignal _ true.\\n\\trecentlyRead _ 0.\\n\\tbufferSize _ 4096.\\n\\tself ascii! !\\n\\n\\n!SocketStream methodsFor: 'printing' stamp: 'gk 2/25/2005 14:19'!\\ndebug\\n\\t\\\"Display debug info.\\\"\\n\\n\\t| data |\\n\\tdata _ self inBufferSize.\\n\\t^String streamContents: [:s |\\n\\t\\ts\\n\\t\\t\\tnextPutAll: 'Buffer size: ', inBuffer size asString;cr;\\n\\t\\t\\tnextPutAll: 'InBuffer data size: ', data asString; cr;\\n\\t\\t\\tnextPutAll: 'In data (20):', (inBuffer copyFrom: lastRead + 1 to: lastRead + (data min: 20)); cr;\\n\\t\\t\\tnextPutAll: 'OutBuffer data size: ', (outNextToWrite - 1) asString; cr;\\n\\t\\t\\tnextPutAll: 'Out data (20):', (outBuffer copyFrom: 1 to: ((outNextToWrite - 1) min: 20)); cr]! !\\n\\n!SocketStream methodsFor: 'printing' stamp: 'md 7/14/2006 12:28'!\\nprint: anObject\\n\\tanObject printOn: self! !\\n\\n!SocketStream methodsFor: 'printing' stamp: 'gk 2/10/2005 11:44'!\\nprintOn: aStream\\n\\t\\\"Display buffer sizes.\\\"\\n\\n\\taStream nextPutAll: self class name.\\n\\tinBuffer ifNotNil: [\\n\\t\\taStream nextPutAll: '[inbuf:',\\n\\t\\t(inBuffer size / 1024) rounded asString, 'kb/outbuf:',\\n\\t\\t(outBuffer size / 1024) rounded asString, 'kb]']! !\\n\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:33'!\\nnext\\n\\t\\\"Return next byte, if inBuffer is empty\\n\\twe recieve some more data and try again.\\\"\\n\\n\\tself atEnd ifTrue: [^nil].\\n\\tself isInBufferEmpty ifTrue:\\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^nil]].\\n\\tlastRead _ lastRead + 1.\\n\\t^inBuffer at: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 21:26'!\\nnextAllInBuffer\\n\\t\\\"Return all data currently in the inBuffer,\\\"\\n\\n\\t^self nextInBuffer: inNextToWrite - lastRead - 1! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 12:51'!\\nnextInBuffer: anInteger\\n\\t\\\"Answer anInteger bytes of data at most,\\n\\tbut only from the inBuffer.\\\"\\n\\n\\t| start amount |\\n\\tamount _ anInteger min: (inNextToWrite - lastRead - 1).\\n\\tstart _ lastRead + 1.\\n\\tlastRead _ lastRead + amount.\\n\\t^inBuffer copyFrom: start to: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:17'!\\nnext: anInteger\\n\\t\\\"Answer anInteger bytes of data.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| start |\\n\\tself receiveData: anInteger.\\n\\tstart _ lastRead + 1.\\n\\tlastRead _ (lastRead + anInteger) min: inNextToWrite - 1.\\n\\t^inBuffer copyFrom: start to: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:47'!\\nnextAvailable\\n\\t\\\"Answer all the data currently available,\\n\\tin buffer or in socket.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^self nextAllInBuffer].\\n\\tself isDataAvailable ifTrue: [self receiveData].\\n\\t^self nextAllInBuffer! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:02'!\\nnextAvailable: howMany\\n\\t\\\"Answer all the data currently available,\\n\\tin buffer or in socket - but limited to <howMany>.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^self nextInBuffer: howMany].\\n\\tself isDataAvailable ifTrue: [self receiveData].\\n\\t^self nextInBuffer: howMany! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/3/2005 20:35'!\\nnextLine\\n\\t^self nextLineCrLf! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/24/2005 12:01'!\\nnextLineCrLf\\n\\t^self upToAll: String crlf! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\nnextLineLf\\n\\t| nextLine |\\n\\tnextLine := self upToAll: String lf.\\n\\t^nextLine! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:09'!\\npeek\\n\\t\\\"Return next byte, if inBuffer is empty\\n\\twe recieve some more data and try again.\\n\\tDo not consume the byte.\\\"\\n\\n\\tself atEnd ifTrue: [^nil].\\n\\tself isInBufferEmpty ifTrue:\\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^nil]].\\n\\t^inBuffer at: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 14:04'!\\npeekFor: aCharacterOrByte\\n\\t\\\"Read and return next character or byte\\n\\tif it is equal to the argument.\\n\\tOtherwise return false.\\\"\\n\\n\\t| nextObject |\\n\\tself atEnd ifTrue: [^false].\\n\\tself isInBufferEmpty ifTrue: \\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^false]].\\n\\tnextObject _ inBuffer at: lastRead.\\n\\tnextObject = aCharacterOrByte ifTrue: [\\n\\t\\tlastRead _ lastRead + 1.\\n\\t\\t^true].\\n\\t^false\\n! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\npeekForAll: aString\\n\\t\\\"Answer whether or not the next string of characters in the receiver\\n\\tmatches aString. If a match is made, advance over that string in the receiver and\\n\\tanswer true. If no match, then leave the receiver alone and answer false.\\n\\tWe use findString:startingAt: to avoid copying.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| sz start |\\n\\tsz _ aString size.\\n\\tself receiveData: sz.\\n\\t(inNextToWrite - lastRead - 1) < sz ifTrue: [^false].\\n\\tstart _ lastRead + 1.\\n\\t(inBuffer findString: aString startingAt: start) = start\\n\\t\\tifFalse: [^false].\\n\\tlastRead _ lastRead + sz.\\n\\t^true! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\npeek: anInteger\\n\\t\\\"Answer anInteger bytes of data.\\n\\tDo not consume data.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| start |\\n\\tself receiveData: anInteger.\\n\\tstart _ lastRead + 1.\\n\\t^inBuffer copyFrom: start to: ((lastRead + anInteger) min: inNextToWrite - 1).! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:15'!\\nskip: anInteger\\n\\t\\\"Skip a number of bytes.\\n\\tThis is faster than #next: since it does not\\n\\thave to copy and return a new String or ByteArray.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\tself receiveData: anInteger.\\n\\tlastRead _ (lastRead + anInteger) min: inNextToWrite - 1! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 9/9/2005 02:57'!\\nupTo: aCharacterOrByte\\n\\t\\\"Return data up to, but not including given character or byte.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\n\\t\\n\\tThis method looks a bit complicated, and this is mainly because there is no fast search method\\n\\tin String that takes a stoppingAt: argument. This means we need to ignore getting hits in the\\n\\tdead buffer area above inNextToWrite.\\n\\tAnother measure is that this implementation is greedy and will load data into the buffer\\n\\tuntil there is nothing more available, or it has loaded 100kb - and not until then we search the buffer.\\n\\n\\tA totally non greedy variant would search on every loop.\\\"\\n\\n\\t| index result lastRecentlyRead searchedSoFar |\\n\\tsearchedSoFar _ 0.\\n\\tlastRecentlyRead _ 0.\\n\\tindex _ 0.\\n\\t[self atEnd not and: [\\n\\t\\t((lastRecentlyRead = 0 and: [self isInBufferEmpty not]) or: [self inBufferSize > 100000]) ifTrue: [\\n\\t\\t\\t\\\"Data begins at lastRead + 1, we add searchedSoFar as offset.\\\"\\n\\t\\t\\tindex _ inBuffer indexOf: aCharacterOrByte startingAt: lastRead + searchedSoFar + 1.\\n\\t\\t\\tsearchedSoFar _ self inBufferSize.\\n\\t\\t\\t(index > 0 and: [(index + 1) > inNextToWrite]) ifTrue: [\\n\\t\\t\\t\\t\\\"Oops, hit in dead buffer area.\\n\\t\\t\\t\\tThis is probably due to old data, so we ignore it.\\n\\t\\t\\t\\tNo point in cleaning the dead area to avoid hits - it will still search it.\\\"\\n\\t\\t\\t\\tindex _ 0]].\\n\\t\\tindex = 0]]\\n\\t\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\t\\trecentlyRead = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"blocking call for now, we don't want to poll\\\"\\n\\t\\t\\t\\t\\t\\t\\tself receiveData]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\tself receiveAvailableData].\\n\\t\\t\\t\\t\\tlastRecentlyRead _ recentlyRead].\\n\\tindex > 0\\n\\t\\tifTrue: [\\\"found it\\\"\\n\\t\\t\\tresult _ self nextInBuffer: index - lastRead - 1.\\n\\t\\t\\tself skip: 1.\\n\\t\\t\\t^ result]\\n\\t\\tifFalse: [\\\"atEnd\\\"\\n\\t\\t\\t^ self nextAllInBuffer]! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 9/9/2005 02:55'!\\nupToAll: aStringOrByteArray\\n\\t\\\"Answer a subcollection from the current access position to the occurrence (if any, but not\\n\\tinclusive) of aStringOrByteArray. If aCollection is not in the stream, answer the entire rest of\\n\\tthe stream.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\n\\t\\n\\tThis method looks a bit complicated, and this is mainly because there is no fast search method\\n\\tin String that takes a stoppingAt: argument. This means we need to ignore getting hits in the\\n\\tdead buffer area above inNextToWrite.\\n\\tAnother measure is that this implementation is greedy and will load data into the buffer\\n\\tuntil there is nothing more available, or it has loaded 100kb - and not until then we search the buffer.\\n\\n\\tA totally non greedy variant would search on every loop.\\\"\\n\\n\\t| index sz result lastRecentlyRead searchedSoFar |\\n\\tsz _ aStringOrByteArray size.\\n\\tsearchedSoFar _ 0.\\n\\tlastRecentlyRead _ 0.\\n\\tindex _ 0.\\n\\t[self atEnd not and: [\\n\\t\\t((lastRecentlyRead = 0 and: [self isInBufferEmpty not]) or: [self inBufferSize > 100000]) ifTrue: [\\n\\t\\t\\t\\\"Data begins at lastRead + 1, we add searchedSoFar as offset and backs up sz - 1\\n\\t\\t\\tso that we can catch any borderline hits.\\\"\\n\\t\\t\\tindex _ inBuffer indexOfSubCollection: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\tstartingAt: lastRead + searchedSoFar - sz + 2.\\n\\t\\t\\tsearchedSoFar _ self inBufferSize.\\n\\t\\t\\t(index > 0 and: [(index + sz) > inNextToWrite]) ifTrue: [\\n\\t\\t\\t\\t\\\"Oops, hit partially or completely in dead buffer area.\\n\\t\\t\\t\\tThis is probably due to old data, so we ignore it.\\n\\t\\t\\t\\tNo point in cleaning the dead area to avoid hits - it will still search it.\\\"\\n\\t\\t\\t\\tindex _ 0]].\\n\\t\\tindex = 0]]\\n\\t\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\t\\trecentlyRead = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"blocking call for now, we don't want to poll\\\"\\n\\t\\t\\t\\t\\t\\t\\tself receiveData]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\tself receiveAvailableData].\\n\\t\\t\\t\\t\\tlastRecentlyRead _ recentlyRead].\\n\\tindex > 0\\n\\t\\tifTrue: [\\\"found it\\\"\\n\\t\\t\\tresult _ self nextInBuffer: index - lastRead - 1.\\n\\t\\t\\tself skip: sz.\\n\\t\\t\\t^ result]\\n\\t\\tifFalse: [\\\"atEnd\\\"\\n\\t\\t\\t^ self nextAllInBuffer]! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:14'!\\nupToEnd\\n\\t\\\"Answer all data coming in on the socket until the socket\\n\\tis closed by the other end, or we get a timeout.\\n\\tThis means this method catches ConnectionClosed by itself.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\\"\\n\\n\\t[[self atEnd] whileFalse: [self receiveData]]\\n\\t\\ton: ConnectionClosed\\n\\t\\tdo: [:ex | \\\"swallow it\\\"]. \\n\\t^self nextAllInBuffer! !\\n\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\ncr\\n\\tself nextPutAll: String cr! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\ncrlf\\n\\tself nextPutAll: String crlf! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/10/2005 11:14'!\\nnextPutAllFlush: aCollection\\n\\t\\\"Put a String or a ByteArray onto the stream.\\n\\tYou can use this if you have very large data - it avoids\\n\\tcopying into the buffer (and avoids buffer growing)\\n\\tand also flushes any other pending data first.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [aCollection asByteArray] ifFalse: [aCollection asString].\\n\\tself flush. \\\"first flush pending stuff, then directly send\\\"\\n\\tsocket isOtherEndClosed ifFalse: [\\n\\t\\t[socket sendData: toPut count: toPut size]\\n\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\tdo: [:ex | shouldSignal ifFalse: [\\\"swallow\\\"]]]! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'md 2/24/2006 19:51'!\\nnextPut: char\\n\\t\\\"Put a single Character or byte onto the stream.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [char asInteger] ifFalse: [char asCharacter].\\n\\tself adjustOutBuffer: 1.\\n\\toutBuffer at: outNextToWrite put: toPut.\\n\\toutNextToWrite _ outNextToWrite + 1.\\n\\tself checkFlush.\\n\\t\\\"return the argument - added by kwl\\\"\\n\\t^ char! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/7/2005 22:51'!\\nnextPutAll: aCollection\\n\\t\\\"Put a String or a ByteArray onto the stream.\\n\\tCurrently a large collection will allocate a large buffer.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [aCollection asByteArray] ifFalse: [aCollection asString].\\n\\tself adjustOutBuffer: toPut size.\\n\\toutBuffer replaceFrom: outNextToWrite to: outNextToWrite + toPut size - 1 with: toPut startingAt: 1.\\n\\toutNextToWrite _ outNextToWrite + toPut size.\\n\\tself checkFlush! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 9/9/2005 09:32'!\\nsendCommand: aString\\n\\t\\\"Sends a String ending it with CR LF and then flush\\n\\tcausing it to block until sent.\\\"\\n\\n\\tself nextPutAll: aString, String crlf; flush! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\nspace\\n\\tself nextPut: Character space! !\\n\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/25/2005 14:23'!\\natEnd\\n\\t\\\"There is nothing more to read when\\n\\tthere is no more data in our inBuffer, the socket\\n\\tis disconnected and there is none available on the socket.\\n\\tNote that we need to check isConnected before isDataAvailable,\\n\\totherwise data may sneak in in the meantime. But we check the\\n\\tbuffer first, because it is faster.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^false].\\n\\t^self isConnected not\\n\\t\\tand: [self isDataAvailable not]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/3/2005 20:35'!\\nisBinary\\n\\t^binary! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 12:24'!\\nisConnected\\n\\t\\\"The stream is connected if the socket is.\\\"\\n\\n\\t^socket isConnected! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/24/2005 12:23'!\\nisDataAvailable\\n\\t\\\"It the inbuffer is empty, we check the socket for data.\\n\\tIf it claims to have data available to read, we try to read\\n\\tsome once and recursively call this method again.\\n\\tIf something really was available it is now in the inBuffer.\\n\\tThis is because there has been spurious\\n\\tdataAvailable when there really is no data to get.\\\"\\n \\n\\tself isInBufferEmpty ifFalse: [^true].\\n\\t^socket dataAvailable\\n\\t\\tifFalse: [false]\\n\\t\\tifTrue: [self receiveDataIfAvailable; isDataAvailable]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 13:02'!\\nisEmpty\\n\\t\\\"Test if there are more data to read.\U0005\\\"\\n\\n\\t^self isInBufferEmpty and: [self isDataAvailable not]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 13:02'!\\nisInBufferEmpty\\n\\t\\\"Any data in the buffer?\\\"\\n \\n\\t^lastRead + 1 = inNextToWrite! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 08:59'!\\nisOtherEndConnected\\n\\t^socket isOtherEndClosed not! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/3/2005 20:35'!\\nshouldTimeout\\n\\t^self timeout > 0! !\\n\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:44'!\\nadjustInBuffer: bytesRead\\n\\t\\\"Adjust markers and possibly grow inBuffer or move data down.\\n\\tCurrently grows through doubling when less than 1024 bytes are left.\\n\\tNever shrinks. Returns the position in the buffer where any new\\n\\tdata can be found.\\\"\\n\\n\\t| old |\\n\\tbytesRead = 0 ifTrue: [^inNextToWrite].\\n\\told _ inNextToWrite.\\n\\tinNextToWrite _ inNextToWrite + bytesRead.\\n\\t(inBuffer size - inNextToWrite) < 1024\\n\\t\\tifTrue: [\\n\\t\\t\\t\\\"Hit the roof, move data down (if enough has been read) or do we grow?\\\"\\n\\t\\t\\t(lastRead > 512)\\n\\t\\t\\t\\tifTrue: [^old - self moveInBufferDown]\\n\\t\\t\\t\\tifFalse: [self growInBuffer]].\\n\\t^old! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:42'!\\nadjustOutBuffer: bytesToWrite\\n\\t\\\"Possibly grow outBuffer to accommodate the new data.\\n\\tCurrently grows through doubling when less\\n\\tthan 1024 bytes are left. If bytesToWrite is even\\n\\tlarger we double that instead. Never shrinks.\\\"\\n\\n\\t(outBuffer size - outNextToWrite - bytesToWrite) < 1024 ifTrue: [\\n\\t\\toutBuffer _ (self streamBuffer: ((outBuffer size max: bytesToWrite) * 2))\\n\\t\\t\\t\\t\\t\\treplaceFrom: 1 to: outBuffer size with: outBuffer startingAt: 1]! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/7/2005 13:09'!\\ncheckFlush\\n\\t\\\"If autoFlush is true we flush if\\n\\twe have reached the bufferSize\\n\\tof data in the outBuffer.\\\"\\n\\n\\t(autoFlush and: [outNextToWrite > bufferSize])\\n\\t\\tifTrue: [self flush]! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/7/2005 23:05'!\\ngrowInBuffer\\n\\t\\\"Grows through doubling.\\\"\\n\\n\\tself resizeInBuffer: inBuffer size * 2! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/8/2005 22:15'!\\nmoveInBufferDown\\n\\t\\\"Move down contents of inBuffer to the start.\\n\\tReturn distance moved.\\\"\\n\\n\\t| sz distanceMoved |\\n\\tsz _ inNextToWrite - lastRead - 1.\\n\\tinBuffer replaceFrom: 1 to: sz with: inBuffer startingAt: lastRead + 1.\\n\\tdistanceMoved _ lastRead.\\n\\tlastRead _ 0.\\n\\tinNextToWrite _ sz + 1.\\n\\t^distanceMoved\\n! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:36'!\\nresetBuffers\\n\\t\\\"Recreate the buffers with default start sizes.\\\"\\n\\n\\tinBuffer _ self streamBuffer: bufferSize.\\n\\tlastRead _ 0.\\n\\tinNextToWrite _ 1.\\n\\toutBuffer _ self streamBuffer: bufferSize.\\n\\toutNextToWrite _ 1! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 9/9/2005 02:29'!\\nresizeInBuffer: newSize\\n\\t\\\"Resize the inBuffer by recreating it.\\n\\tThis also has the effect of getting rid of\\n\\tdead data above inNextToWrite.\\n\\t<newSize> must >= inBuffer size!!\\\"\\n\\n\\tinBuffer _ (self streamBuffer: newSize)\\n\\t\\t\\t\\t\\treplaceFrom: 1 to: inNextToWrite - 1 with: inBuffer startingAt: 1! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:35'!\\nstreamBuffer: size\\n\\t\\\"Create a buffer of the correct class and given size.\\\"\\n\\n\\t^(self isBinary\\n\\t\\tifTrue: [ByteArray]\\n\\t\\tifFalse: [String]) new: size! !\\n\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/25/2005 14:20'!\\nreceiveAvailableData\\n\\t\\\"Receive available data (as much as fits in the inBuffer)\\n\\tbut not waiting for more to arrive.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\t\\n\\trecentlyRead _ socket receiveAvailableDataInto: inBuffer startingAt: inNextToWrite.\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/25/2005 14:20'!\\nreceiveData\\n\\t\\\"Receive data with timeout if it has been set.\\n\\tIf shouldSignal is false we use the Socket methods\\n\\tthat swallow those Exceptions, if it is true the\\n\\tcaller will have to handle those Exceptions.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\t\\n\\trecentlyRead := shouldSignal ifTrue: [\\n\\t\\tself shouldTimeout ifTrue: [\\n\\t\\t\\t\\tsocket receiveDataSignallingTimeout: timeout\\n\\t\\t\\t\\t\\tinto: inBuffer startingAt: inNextToWrite]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsocket receiveDataSignallingClosedInto: inBuffer\\n\\t\\t\\t\\t\\tstartingAt: inNextToWrite]]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\tself shouldTimeout ifTrue: [\\n\\t\\t\\t\\\"This case is tricky, if it times out and is swallowed\\n\\t\\t\\thow does other methods calling this method repeatedly\\n\\t\\t\\tget to know that? And what should they do?\\\"\\n\\t\\t\\t\\tsocket receiveDataTimeout: timeout\\n\\t\\t\\t\\t\\tinto: inBuffer startingAt: inNextToWrite]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsocket receiveDataInto: inBuffer\\n\\t\\t\\t\\t\\tstartingAt: inNextToWrite]].\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/9/2005 22:53'!\\nreceiveDataIfAvailable\\n\\t\\\"Only used to check that there really is data to read\\n\\tfrom the socket after it signals dataAvailable.\\n\\tIt has been known to signal true and then still\\n\\tnot have anything to read. See also isDataAvailable.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\n\\trecentlyRead _ socket receiveSomeDataInto: inBuffer startingAt: inNextToWrite.\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocketStream class\\n\\tinstanceVariableNames: ''!\\n\\n!SocketStream class methodsFor: 'example' stamp: 'md 8/14/2005 18:25'!\\nfinger: userName\\n\\t\\\"SocketStream finger: 'stp'\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ SocketStream openConnectionToHost: addr port: 79. \\\"finger port number\\\"\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts sendCommand: userName.\\n\\tTranscript show: s getLine.\\n\\ts close.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 22:19'!\\non: socket\\n\\t\\\"Create a socket stream on a connected server socket.\\\"\\n\\n\\t^self basicNew initialize socket: socket! !\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 20:35'!\\nopenConnectionToHost: hostIP port: portNumber\\n\\t| socket |\\n\\tsocket _ Socket new.\\n\\tsocket connectTo: hostIP port: portNumber.\\n\\t^self on: socket! !\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 20:35'!\\nopenConnectionToHostNamed: hostName port: portNumber\\n\\t| hostIP |\\n\\thostIP _ NetNameResolver addressForName: hostName timeout: 20.\\n\\t^self openConnectionToHost: hostIP port: portNumber! !\\nSocket subclass: #SocksSocket\\n\\tinstanceVariableNames: 'vers method socksIP socksPort dstPort dstIP dstName'\\n\\tclassVariableNames: 'DefaultSocksVersion'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!SocksSocket commentStamp: '<historical>' prior: 0!\\nThis class implements the socks 4 and partially socks 5 connection protocol.\\nFor backward compatibility the socks protocol is disabled by default, so subclasses still work.\\nFor further documentation check out:\\n\\nSocks4: http://spiderman.socks.nec.com/protocol/socks4.protocol\\n\\nSocks5: http://spiderman.socks.nec.com/rfc/rfc1928.txt!\\n\\n\\n!SocksSocket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 15:49'!\\nconnectTo: hostAddress port: port\\n\\tself initializeNetwork.\\n\\tself shouldUseSocks\\n\\t\\tifFalse: [^super connectTo: hostAddress port: port].\\n\\tsuper connectTo: socksIP port: socksPort.\\n\\tself waitForConnectionUntil: Socket standardDeadline.\\n\\tdstIP _ hostAddress.\\n\\tdstPort _ port.\\n\\tvers == 4\\n\\t\\tifTrue: [self connectSocks4]\\n\\t\\tifFalse: [self connectSocks5]\\n\\t! !\\n\\n!SocksSocket methodsFor: 'connection open/close' stamp: 'mir 3/6/2000 15:17'!\\nconnectToHostNamed: hostName port: port\\n\\tsuper connectTo: socksIP port: socksPort.\\n\\tself waitForConnectionUntil: Socket standardDeadline.\\n\\tdstName _ hostName.\\n\\tdstPort _ port.\\n\\tvers == 4\\n\\t\\tifTrue: [self connectSocks4]\\n\\t\\tifFalse: [self connectSocks5]\\n\\t! !\\n\\n\\n!SocksSocket methodsFor: 'initialize' stamp: 'mir 9/26/2000 00:05'!\\nsocks4\\n\\tvers _ 4.\\n\\tmethod _ nil.\\n\\tsocksIP _ self class defaultSocksHostAddress.\\n\\tsocksPort _ self class defaultSocksPort! !\\n\\n!SocksSocket methodsFor: 'initialize' stamp: 'mir 9/26/2000 00:05'!\\nsocks5\\n\\tvers _ 5.\\n\\tmethod _ self class noAutorizationMethod.\\n\\tsocksIP _ self class defaultSocksHostAddress.\\n\\tsocksPort _ self class defaultSocksPort! !\\n\\n\\n!SocksSocket methodsFor: 'methods' stamp: 'mir 3/6/2000 13:24'!\\nnoAutorizationMethod\\n\\t^0! !\\n\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 3/6/2000 15:07'!\\nconnectSocks4\\n\\tself\\n\\t\\tsendSocks4ConnectionRequestUserId: '';\\n\\t\\twaitForSocks4ConnectionReply.\\n! !\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 2/22/2002 15:49'!\\nsendSocks4ConnectionRequestUserId: userId\\n\\t\\\"The client connects to the SOCKS server and sends a CONNECT request when\\nit wants to establish a connection to an application server. The client\\nincludes in the request packet the IP address and the port number of the\\ndestination host, and userid, in the following format.\\n\\n\\t+----+----+----+----+----+----+----+----+----+----+....+----+\\n\\t| VN | CD | DSTPORT | DSTIP | USERID |NULL|\\n\\t+----+----+----+----+----+----+----+----+----+----+....+----+\\n\\t 1 1 2 4 variable 1\\n\\t\\\"\\n\\n\\t| requestString |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\tdstIP\\n\\t\\tifNil: [dstIP _ NetNameResolver addressForName: dstName].\\n\\trequestString\\n\\t\\tnextPut: 4;\\n\\t\\tnextPut: self connectCommandCode;\\n\\t\\tnextWordPut: dstPort;\\n\\t\\tnextPutAll: self dstIP;\\n\\t\\tnextPutAll: userId asByteArray;\\n\\t\\tnextPut: 0.\\n\\tself sendData: requestString contents! !\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 3/6/2000 15:11'!\\nwaitForSocks4ConnectionReply\\n\\n\\t| response |\\n\\tresponse _ self waitForReply: 8 for: self defaultTimeOutDuration.\\n\\n\\t(response at: 2) = self requestGrantedCode\\n\\t\\tifFalse: [^self socksError: 'Connection failed: ' , (response at: 2) printString].! !\\n\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:42'!\\nconnectSocks5\\n\\tself\\n\\t\\tsocks5MethodSelection;\\n\\t\\tsendSocks5ConnectionRequest;\\n\\t\\tsocks5RequestReply\\n! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:29'!\\nhostIP6Code\\n\\t^4! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:20'!\\nhostIPCode\\n\\t^1! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:15'!\\nqualifiedHostNameCode\\n\\t^3! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:25'!\\nsendSocks5ConnectionRequest\\n\\t\\\"Once the method-dependent subnegotiation has completed, the client\\n sends the request details.\\\"\\n\\n\\t| requestString |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\trequestString\\n\\t\\tnextPut: 5;\\n\\t\\tnextPut: self connectCommandCode;\\n\\t\\tnextPut: 0. \\\"Reserved slot\\\"\\n\\tdstName isNil\\n\\t\\tifTrue: [\\n\\t\\t\\trequestString\\n\\t\\t\\t\\tnextPutAll: self hostIPCode;\\n\\t\\t\\t\\tnextPutAll: dstIP]\\n\\t\\tifFalse: [\\n\\t\\t\\trequestString\\n\\t\\t\\t\\tnextPut: self qualifiedHostNameCode;\\n\\t\\t\\t\\tnextPut: dstName size;\\n\\t\\t\\t\\tnextPutAll: dstName asByteArray].\\n\\trequestString nextWordPut: dstPort.\\n\\tself sendData: requestString contents! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:35'!\\nskipQualifiedHostName\\n\\n\\t| startTime response bytesRead |\\n\\tstartTime _ Time millisecondClockValue.\\n\\tresponse _ ByteArray new: 1.\\n\\n\\t[(bytesRead _ self receiveDataInto: response) < 1\\n\\t\\tand: [(Time millisecondClockValue - startTime) < self defaultTimeOutDuration]] whileTrue.\\n\\n\\tbytesRead < 1\\n\\t\\tifTrue: [self socksError: 'Time out reading data'].\\n\\n\\tself waitForReply: (response at: 1) + 2 for: self defaultTimeOutDuration! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:16'!\\nsocks5MethodSelection\\n\\t\\\"The client connects to the server, and sends a version\\n identifier/method selection message.\\n\\tThe server selects from one of the methods given in METHODS, and\\n sends a METHOD selection message.\\\"\\n\\n\\t| requestString response |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\trequestString\\n\\t\\tnextPut: 5;\\n\\t\\tnextPut: 1;\\n\\t\\tnextPut: 0.\\n\\tself sendData: requestString contents.\\n\\n\\tresponse _ self waitForReply: 2 for: self defaultTimeOutDuration.\\n\\t(response at: 2) == 16rFF\\n\\t\\tifTrue: [self socksError: 'No acceptable methods.']\\n\\t\\tifFalse: [method _ response at: 2]! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:28'!\\nsocks5RequestReply\\n\\n\\t| response |\\n\\tresponse _ self waitForReply: 4 for: self defaultTimeOutDuration.\\n\\t\\\"Skip rest for now.\\\"\\n\\t(response at: 4) = self hostIPCode\\n\\t\\tifTrue: [self waitForReply: 6 for: self defaultTimeOutDuration].\\n\\t(response at: 4) = self qualifiedHostNameCode\\n\\t\\tifTrue: [self skipQualifiedHostName].\\n\\t(response at: 4) = self hostIP6Code\\n\\t\\tifTrue: [self waitForReply: 18 for: self defaultTimeOutDuration].\\n\\t(response at: 2) ~= 0\\n\\t\\tifTrue: [^self socksError: 'Connection failed: ', (response at: 2) printString].\\n! !\\n\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 13:34'!\\nconnectCommandCode\\n\\t^1! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:07'!\\ndefaultTimeOutDuration\\n\\t^20000! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:29'!\\ndstIP\\n\\t^dstIP! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 2/22/2002 16:23'!\\ndstPort\\n\\t^dstPort! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 14:03'!\\nrequestGrantedCode\\n\\t^90! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 9/26/2000 11:23'!\\nshouldUseSocks\\n\\t^vers notNil! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:11'!\\nsocksError: errorString\\n\\tself close; destroy.\\n\\tself error: errorString! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'len 12/14/2002 11:39'!\\nwaitForReply: replySize for: timeOutDuration\\n\\t| startTime response delay bytesRead |\\n\\tstartTime _ Time millisecondClockValue.\\n\\tresponse _ ByteArray new: replySize.\\n\\tbytesRead _ 0.\\n\\tdelay _ Delay forMilliseconds: 500.\\n\\t[bytesRead < replySize\\n\\t\\tand: [(Time millisecondClockValue - startTime) < timeOutDuration]] whileTrue: [\\n\\t\\tbytesRead _ bytesRead + (self receiveDataInto: response).\\n\\t\\tdelay wait.\\n\\t\\tTranscript show: '.'].\\n\\tbytesRead < replySize\\n\\t\\tifTrue: [self close; destroy.\\n\\t\\t\\t\\t^ (ConnectionRefused host: self dstIP port: self dstPort) signal].\\n\\t^response! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocksSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'nk 7/6/2003 07:30'!\\ndefaultSocksHostAddress\\n\\n\\t^NetNameResolver addressForName: HTTPSocket httpProxyServer! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'nk 7/6/2003 07:30'!\\ndefaultSocksPort\\n\\t^HTTPSocket httpProxyPort! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'mir 9/26/2000 00:06'!\\ndefaultSocksVersion\\n\\t\\\"nil means no socks\\\"\\n\\t^DefaultSocksVersion! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'mir 9/26/2000 00:07'!\\ndefaultSocksVersion: anInteger\\n\\t\\\"nil means no socks\\\"\\n\\tDefaultSocksVersion _ anInteger! !\\nFillStyle subclass: #SolidFillStyle\\n\\tinstanceVariableNames: 'color pixelValue32'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Balloon-Fills'!\\n!SolidFillStyle commentStamp: '<historical>' prior: 0!\\nSolidFillStyle is a fill which represents a color for the BalloonEngine.\\n\\nInstance variables:\\n\\tcolor\\t<Color>\\tThe color to use.\\n\\tpixelValue32 <Integer>\\tThe cached pixel value to use.!\\n\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 1/14/1999 15:24'!\\ncolor: aColor\\n\\tcolor := aColor.\\n\\tpixelValue32 := aColor scaledPixelValue32! !\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 11/9/1998 03:29'!\\ndisplay\\n\\t^color display! !\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 1/14/1999 15:25'!\\nscaledPixelValue32\\n\\t\\\"Return the alpha scaled pixel value for depth 32\\\"\\n\\t^pixelValue32! !\\n\\n\\n!SolidFillStyle methodsFor: 'converting' stamp: 'ar 11/9/1998 13:55'!\\nasColor\\n\\t^color! !\\n\\n\\n!SolidFillStyle methodsFor: 'printing' stamp: 'ar 11/17/1998 00:29'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut:$(; print: color; nextPut:$).! !\\n\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 11/8/1998 18:34'!\\nisSolidFill\\n\\t^true! !\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 9/2/1999 14:30'!\\nisTranslucent\\n\\t^color isTranslucent! !\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 10/26/2000 19:25'!\\nisTransparent\\n\\t^color isTransparent! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSolidFillStyle class\\n\\tinstanceVariableNames: ''!\\n\\n!SolidFillStyle class methodsFor: 'instance creation' stamp: 'ar 11/8/1998 18:31'!\\ncolor: aColor\\n\\t^self new color: aColor! !\\nImageMorph subclass: #Sonogram\\n\\tinstanceVariableNames: 'lastX scrollDelta columnForm minVal maxVal pixValMap'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!Sonogram commentStamp: '<historical>' prior: 0!\\nSonograms are imageMorphs that will repeatedly plot arrays of values as black on white columns moving to the right in time and scrolling left as necessary.!\\n\\n\\n!Sonogram methodsFor: 'all' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextent: extent minVal: min maxVal: max scrollDelta: d\\n\\tminVal := min.\\n\\tmaxVal := max.\\n\\tscrollDelta := d.\\n\\tself extent: extent.\\n\\n\\\" try following with scrolldelta = 1, 20, 200\\n\\t| s data |\\n\\ts := Sonogram new extent: 200@50\\n\\t\\t\\t\\tminVal: 0.0 maxVal: 1.0 scrollDelta: 20.\\n\\tWorld addMorph: s.\\n\\tdata := (1 to: 133) collect: [:i | 0.0].\\n\\t1 to: 300 do:\\n\\t\\t[:i | data at: (i\\\\\\\\133)+1 put: 1.0.\\n\\t\\ts plotColumn: data.\\n\\t\\tdata at: (i\\\\\\\\133)+1 put: 0.0.\\n\\t\\tWorld doOneCycleNow].\\n\\ts delete\\t\\n\\\"! !\\n\\n!Sonogram methodsFor: 'all' stamp: 'jdl 3/28/2003 09:30'!\\nplotColumn: dataArray \\n\\t| chm1 i normVal r |\\n\\tcolumnForm unhibernate.\\n\\tchm1 := columnForm height - 1.\\n\\t0 to: chm1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\ti := y * (dataArray size - 1) // chm1 + 1.\\n\\t\\t\\tnormVal := ((dataArray at: i) - minVal) / (maxVal - minVal).\\n\\t\\t\\tnormVal := normVal max: 0.0.\\n\\t\\t\\tnormVal := normVal min: 1.0.\\n\\t\\t\\tcolumnForm bits at: chm1 - y + 1\\n\\t\\t\\t\\tput: (pixValMap at: (normVal * 255.0) truncated + 1)].\\n\\t(lastX := lastX + 1) > (image width - 1) ifTrue: [self scroll].\\n\\timage \\n\\t\\tcopy: (r := lastX @ 0 extent: 1 @ image height)\\n\\t\\tfrom: (32 // image depth - 1) @ 0\\n\\t\\tin: columnForm\\n\\t\\trule: Form over.\\n\\t\\\"self changed.\\\"\\n\\tself invalidRect: (r translateBy: self position)! !\\n\\n!Sonogram methodsFor: 'all' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscroll\\n\\timage copy: (scrollDelta@0 extent: (image width-scrollDelta)@image height)\\n\\t\\t\\tfrom: image to: 0@0 rule: Form over.\\n\\tlastX := lastX - scrollDelta.\\n\\tself changed! !\\n\\n\\n!Sonogram methodsFor: 'geometry' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextent: newExtent\\n\\tsuper image: (Form extent: newExtent depth: Display depth).\\n\\tlastX := -1.\\n\\tcolumnForm := Form extent: (32//image depth)@(image height) depth: image depth.\\n\\tpixValMap := ((1 to: 256) collect:\\n\\t\\t\\t[:i | columnForm pixelValueFor: (Color gray: (256-i)/255.0)])\\n\\t\\tas: Bitmap.\\n! !\\nOrderedCollection subclass: #SortedCollection\\n\\tinstanceVariableNames: 'sortBlock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Sequenceable'!\\n!SortedCollection commentStamp: '<historical>' prior: 0!\\nI represent a collection of objects ordered by some property of the objects themselves. The ordering is specified in a BlockContext.!\\n\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'sma 4/28/2000 17:47'!\\nat: anInteger put: anObject\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'tk 3/28/1999 22:55'!\\nmedian\\n\\t\\\"Return the middle element, or as close as we can get.\\\"\\n\\n\\t^ self at: self size + 1 // 2! !\\n\\n!SortedCollection methodsFor: 'accessing'!\\nsortBlock\\n\\t\\\"Answer the blockContext which is the criterion for sorting elements of \\n\\tthe receiver.\\\"\\n\\n\\t^sortBlock! !\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'stp 12/05/1999 07:09'!\\nsortBlock: aBlock \\n\\t\\\"Make the argument, aBlock, be the criterion for ordering elements of the \\n\\treceiver.\\\"\\n\\n\\taBlock\\n\\t\\tifNotNil: [sortBlock := aBlock fixTemps]\\n\\t\\tifNil: [sortBlock := aBlock].\\n\\t\\\"The sortBlock must copy its home context, so as to avoid circularities!!\\\"\\n\\t\\\"Therefore sortBlocks with side effects may not work right\\\"\\n\\tself size > 0 ifTrue: [self reSort]! !\\n\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'go 4/27/2000 13:19'!\\nadd: newObject\\n\\t^ super insert: newObject before: (self indexForInserting: newObject)! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'sma 4/28/2000 18:35'!\\naddAll: aCollection\\n\\taCollection size > (self size // 3)\\n\\t\\tifTrue:\\n\\t\\t\\t[aCollection do: [:each | self addLast: each].\\n\\t\\t\\tself reSort]\\n\\t\\tifFalse: [aCollection do: [:each | self add: each]].\\n\\t^ aCollection! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'go 4/26/2000 17:26'!\\naddFirst: newObject\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'MPH 10/23/2000 13:31'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver without any of the receiver's elements.\\\"\\n\\n\\t^self species sortBlock: sortBlock! !\\n\\n\\n!SortedCollection methodsFor: 'comparing'!\\n= aSortedCollection\\n\\t\\\"Answer true if my and aSortedCollection's species are the same,\\n\\tand if our blocks are the same, and if our elements are the same.\\\"\\n\\n\\tself species = aSortedCollection species ifFalse: [^ false].\\n\\tsortBlock = aSortedCollection sortBlock\\n\\t\\tifTrue: [^ super = aSortedCollection]\\n\\t\\tifFalse: [^ false]! !\\n\\n\\n!SortedCollection methodsFor: 'copying'!\\ncopy\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species sortBlock: sortBlock.\\n\\tnewCollection addAll: self.\\n\\t^newCollection! !\\n\\n\\n!SortedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'!\\ncollect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect the \\n\\tresulting values into an OrderedCollection. Answer the new collection. \\n\\tOverride the superclass in order to produce an OrderedCollection instead\\n\\tof a SortedCollection.\\\"\\n\\n\\t| newCollection | \\n\\tnewCollection _ OrderedCollection new: self size.\\n\\tself do: [:each | newCollection addLast: (aBlock value: each)].\\n\\t^ newCollection! !\\n\\n\\n!SortedCollection methodsFor: 'topological sort' stamp: 'hg 1/2/2002 13:34'!\\nsortTopologically\\n\\t\\\"Plenty of room for increased efficiency in this one.\\\"\\n\\n\\t| remaining result pick |\\n\\tremaining _ self asOrderedCollection.\\n\\tresult _ OrderedCollection new.\\n\\t[remaining isEmpty] whileFalse: [\\n\\t\\tpick _ remaining select: [:item |\\n\\t\\t\\tremaining allSatisfy: [:anotherItem |\\n\\t\\t\\t\\titem == anotherItem or: [self should: item precede: anotherItem]]].\\n\\t\\tpick isEmpty ifTrue: [self error: 'bad topological ordering'].\\n\\t\\tresult addAll: pick.\\n\\t\\tremaining removeAll: pick].\\n\\t^self copySameFrom: result! !\\n\\n\\n!SortedCollection methodsFor: 'private' stamp: 'stp 04/23/1999 05:36'!\\nindexForInserting: newObject\\n\\n\\t| index low high |\\n\\tlow _ firstIndex.\\n\\thigh _ lastIndex.\\n\\tsortBlock isNil\\n\\t\\tifTrue: [[index _ high + low // 2. low > high]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[((array at: index) <= newObject)\\n\\t\\t\\t\\t\\tifTrue: [low _ index + 1]\\n\\t\\t\\t\\t\\tifFalse: [high _ index - 1]]]\\n\\t\\tifFalse: [[index _ high + low // 2. low > high]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(sortBlock value: (array at: index) value: newObject)\\n\\t\\t\\t\\t\\tifTrue: [low _ index + 1]\\n\\t\\t\\t\\t\\tifFalse: [high _ index - 1]]].\\n\\t^low! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'go 4/26/2000 17:17'!\\ninsert: anObject before: spot\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'sma 4/28/2000 17:46'!\\nreSort\\n\\tself sort: firstIndex to: lastIndex! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 19:30'!\\nshould: a precede: b\\n\\n\\t^sortBlock ifNil: [a <= b] ifNotNil: [sortBlock value: a value: b]\\n! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 20:22'!\\nsort: i to: j \\n\\t\\\"Sort elements i through j of self to be nondescending according to\\n\\tsortBlock.\\\"\\n\\n\\t| di dij dj tt ij k l n |\\n\\t\\\"The prefix d means the data at that index.\\\"\\n\\t(n _ j + 1 - i) <= 1 ifTrue: [^self].\\t\\\"Nothing to sort.\\\" \\n\\t \\\"Sort di,dj.\\\"\\n\\tdi _ array at: i.\\n\\tdj _ array at: j.\\n\\t(self should: di precede: dj)\\n\\t\\tifFalse: \\n\\t\\t\\t[array swap: i with: j.\\n\\t\\t\\t tt _ di.\\n\\t\\t\\t di _ dj.\\n\\t\\t\\t dj _ tt].\\n\\tn > 2\\n\\t\\tifTrue: \\\"More than two elements.\\\"\\n\\t\\t\\t[ij _ (i + j) // 2. \\\"ij is the midpoint of i and j.\\\"\\n\\t\\t\\t dij _ array at: ij. \\\"Sort di,dij,dj. Make dij be their median.\\\"\\n\\t\\t\\t (self should: di precede: dij)\\n\\t\\t\\t ifTrue: \\n\\t\\t\\t\\t[(self should: dij precede: dj)\\n\\t\\t\\t\\t ifFalse: \\n\\t\\t\\t\\t\\t[array swap: j with: ij.\\n\\t\\t\\t\\t\\t dij _ dj]]\\n\\t\\t\\t ifFalse:\\n\\t\\t\\t\\t[array swap: i with: ij.\\n\\t\\t\\t\\t dij _ di].\\n\\t\\t\\tn > 3\\n\\t\\t\\t ifTrue: \\\"More than three elements.\\\"\\n\\t\\t\\t\\t[\\\"Find k>i and l<j such that dk,dij,dl are in reverse order.\\n\\t\\t\\t\\tSwap k and l. Repeat this procedure until k and l pass each other.\\\"\\n\\t\\t\\t\\t k _ i.\\n\\t\\t\\t\\t l _ j.\\n\\t\\t\\t\\t [[l _ l - 1. k <= l and: [self should: dij precede: (array at: l)]]\\n\\t\\t\\t\\t whileTrue. \\\"i.e. while dl succeeds dij\\\"\\n\\t\\t\\t\\t [k _ k + 1. k <= l and: [self should: (array at: k) precede: dij]]\\n\\t\\t\\t\\t whileTrue. \\\"i.e. while dij succeeds dk\\\"\\n\\t\\t\\t\\t k <= l]\\n\\t\\t\\t\\t whileTrue:\\n\\t\\t\\t\\t\\t[array swap: k with: l]. \\n\\t\\\"Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk\\n\\tthrough dj. Sort those two segments.\\\"\\n\\t\\t\\t\\tself sort: i to: l.\\n\\t\\t\\t\\tself sort: k to: j]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSortedCollection class\\n\\tinstanceVariableNames: ''!\\n\\n!SortedCollection class methodsFor: 'instance creation' stamp: 'stp 04/23/1999 05:34'!\\nnew: anInteger \\n\\t\\\"The default sorting function is a <= comparison on elements.\\\"\\n\\n\\t^(super new: anInteger) \\\"sortBlock: [:x :y | x <= y]\\\" \\t\\t\\\"nil sortBlock OK\\\"! !\\n\\n!SortedCollection class methodsFor: 'instance creation'!\\nsortBlock: aBlock \\n\\t\\\"Answer an instance of me such that its elements are sorted according to \\n\\tthe criterion specified in aBlock.\\\"\\n\\n\\t^(super new: 10) sortBlock: aBlock! !\\nTestCase subclass: #SortedCollectionTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Unordered'!\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:27'!\\ntestAdd\\n\\t\\\"self run: #testAdd\\\"\\n\\t\\\"self debug: #testAdd\\\"\\n\\t\\n\\t| collection |\\n\\tcollection := #(10 9 8 7 5 4 4 2) asSortedCollection.\\n\\tself assert: collection first = 2.\\n\\tself assert: collection last = 10.\\n\\tself assert: (collection size = 8).\\n\\tcollection add:1.\\n\\tself assert: (collection size = 9).\\n\\tcollection add: 6.\\n\\tself assert: ((collection at: 5) = 5).\\n\\tself assert: (collection size = 10).\\n\\tcollection add: 3.\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:30'!\\ntestAddAll\\n\\t\\\"self run: #testAddAll\\\"\\n\\t\\\"self debug: #testAddAll\\\"\\n\\t\\n\\t| sorted2 sorted|\\n\\tsorted2 := SortedCollection new.\\n\\tsorted2 add: 'brochet'; add:'truitelle'.\\n\\tsorted := SortedCollection new.\\n\\tsorted addAll: sorted2.\\n\\tself assert: (sorted hasEqualElements: sorted2).\\n\\t ! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:32'!\\ntestAddAll2\\n\\t\\\"self run: #testAddAll2\\\"\\n\\t\\\"self debug: #testAddAll2\\\"\\n\\t\\n\\t| sorted2 sorted|\\n\\tsorted2 := SortedCollection new.\\n\\tsorted2 add: 'brochet'; add:'truitelle'.\\n\\tsorted := SortedCollection new.\\n\\tsorted add: 'perche'.\\n\\tsorted addAll: sorted2.\\n\\tself assert: (sorted size = (sorted2 size + 1)).\\n\\tsorted2 do: \\n\\t\\t\\t[ :each | self assert: (sorted includes: each)]\\n\\t ! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:33'!\\ntestCollect\\n\\t\\\"self run: #testCollect\\\"\\n\\t\\n\\t|result aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\tresult := OrderedCollection new.\\n\\tresult add:true ; add: true ; add: true ;add: false ; add: false.\\n\\taSortedCollection := (1 to: 5) asSortedCollection.\\n\\tself assert: (result = (aSortedCollection collect: [:each | each < 4])).\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:39'!\\ntestCopy\\n\\t\\\"self run: #testCopy\\\"\\n\\t\\\"self debug: #testCopy\\\"\\n\\t\\n\\t|aSortedCollection copySorted|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a < b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet'.\\n\\tself assert: aSortedCollection first = 'brochet'.\\n\\t\\n\\tcopySorted := aSortedCollection copy.\\n\\t\\n\\tself assert: (copySorted hasEqualElements: aSortedCollection).\\n\\tself assert: (copySorted species = aSortedCollection species).\\n\\tself assert: (copySorted sortBlock = aSortedCollection sortBlock).\\n\\tself assert: copySorted first = 'brochet'.! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:30'!\\ntestCreation\\n\\t\\\"self run: #testCreation\\\"\\n\\t\\\"self debug: #testCreation\\\"\\n\\t\\n\\t| collection |\\n\\tcollection := #(10 9 3 6 1 8 7 5 4 2) asSortedCollection.\\n\\tself assert: collection = (1 to: 10) asSortedCollection.\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:42'!\\ntestEquals\\n\\t\\\"self run: #testEquals\\\"\\n\\t\\\"self debug: #testEquals\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection add:'truite' ; add: 'brochet'.\\n\\tself assert: aSortedCollection copy = aSortedCollection.! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:43'!\\ntestMedian\\n\\t\\\"self run: #testMedian\\\"\\n\\t\\\"self debug: #testMedian\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := (1 to: 10) asSortedCollection.\\n\\tself assert: aSortedCollection median=5.\\n\\t\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection add:'truite' ; add:'porcinet' ; add:'carpe'.\\n\\tself assert: (aSortedCollection median = 'porcinet').\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:46'!\\ntestShouldPrecede\\n\\t\\\"self run: #testShouldPrecede\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\tself assert: (aSortedCollection should: 'za' precede: 'zb').\\n\\tself assert: (aSortedCollection isEmpty).\\n\\tself assert: (aSortedCollection should: 1 precede: 2).\\n\\t\\n\\taSortedCollection sortBlock: [:a :b | a > b].\\n\\taSortedCollection reSort.\\n\\tself assert: (aSortedCollection should: 'zb' precede: 'za').\\n\\tself assert: (aSortedCollection isEmpty).\\n\\tself assert: (aSortedCollection should: 2 precede: 1).\\n\\t\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:38'!\\ntestSortBlock\\n\\t\\\"self run: #testSortBlock\\\"\\n\\t\\\"self debug: #testSortBlock\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a < b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet' ; add: 'tortue'.\\n\\tself assert: aSortedCollection first = 'brochet'.\\n\\t\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a >b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet' ; add: 'tortue'.\\n\\tself assert: aSortedCollection first = 'truite'.\\n\\t\\n\\t\\n\\t! !\\nBorderedMorph subclass: #SorterTokenMorph\\n\\tinstanceVariableNames: 'morphRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Palettes'!\\n\\n!SorterTokenMorph methodsFor: 'as yet unclassified' stamp: 'sw 12/1/1998 12:38'!\\nfitContents\\n\\tsubmorphs size == 1 ifTrue: [self bounds: (submorphs first bounds insetBy: (-1 @ -1))]! !\\n\\n!SorterTokenMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/21/2003 23:16'!\\nforMorph: aMorph \\n\\t| it |\\n\\tmorphRepresented := aMorph.\\n\\taMorph submorphs notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[self addMorphBack: (it := aMorph submorphs first veryDeepCopy).\\n\\t\\t\\tit position: self position + (1 @ 1).\\n\\t\\t\\tit lock].\\n\\tself fitContents! !\\n\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color blue! !\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color transparent! !\\n\\n\\n!SorterTokenMorph methodsFor: 'thumbnail' stamp: 'sw 12/1/1998 12:27'!\\nmorphRepresented\\n\\t^ morphRepresented! !\\nArrayedCollection variableWordSubclass: #SoundBuffer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'SineTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundBuffer commentStamp: '<historical>' prior: 0!\\nSoundBuffers store 16 bit unsigned quantities. !\\n\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'tk 3/13/2000 14:46'!\\nbytesPerElement\\n\\t\\\"Number of bytes in each item. This multiplied by (self size)*8 gives the number of bits stored.\\\"\\n\\t^ 2! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:00'!\\nmonoSampleCount\\n\\t\\\"Return the number of monaural 16-bit samples that fit into this SoundBuffer.\\\"\\n\\n\\t^ super size * 2\\n! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:28'!\\nsize\\n\\t\\\"Return the number of 16-bit sound samples that fit in this sound buffer. To avoid confusion, it is better to get the size of SoundBuffer using monoSampleCount or stereoSampleCount.\\\"\\n\\n\\t^ self monoSampleCount\\n! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:01'!\\nstereoSampleCount\\n\\t\\\"Return the number of stereo slices that fit into this SoundBuffer. A stereo 'slice' consists of two 16-bit samples, one for each channel.\\\"\\n\\n\\t^ super size\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'as yet unclassified' stamp: 'RAA 7/11/2000 11:31'!\\nwriteOnGZIPByteStream: aStream \\n\\t\\n\\taStream nextPutAllWordArray: self! !\\n\\n\\n!SoundBuffer methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrestoreEndianness\\n\\t\\\"This word object was just read in from a stream. It was stored in Big Endian (Mac) format. Swap each pair of bytes (16-bit word), if the current machine is Little Endian.\\n\\tWhy is this the right thing to do? We are using memory as a byteStream. High and low bytes are reversed in each 16-bit word, but the stream of words ascends through memory. Different from a Bitmap.\\\"\\n\\n\\t| hack blt |\\n\\tSmalltalkImage current isLittleEndian ifTrue: [\\n\\t\\t\\\"The implementation is a hack, but fast for large ranges\\\"\\n\\t\\thack := Form new hackBits: self.\\n\\t\\tblt := (BitBlt toForm: hack) sourceForm: hack.\\n\\t\\tblt combinationRule: Form reverse. \\\"XOR\\\"\\n\\t\\tblt sourceY: 0; destY: 0; height: self size; width: 1.\\n\\t\\tblt sourceX: 0; destX: 1; copyBits. \\\"Exchange bytes 0 and 1\\\"\\n\\t\\tblt sourceX: 1; destX: 0; copyBits.\\n\\t\\tblt sourceX: 0; destX: 1; copyBits.\\n\\t\\tblt sourceX: 2; destX: 3; copyBits. \\\"Exchange bytes 2 and 3\\\"\\n\\t\\tblt sourceX: 3; destX: 2; copyBits.\\n\\t\\tblt sourceX: 2; destX: 3; copyBits].\\n\\n! !\\n\\n!SoundBuffer methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreverseEndianness\\n\\t\\\"Swap the bytes of each 16-bit word, using a fast BitBlt hack.\\\"\\n\\n\\t| hack blt |\\n\\thack := Form new hackBits: self.\\n\\tblt := (BitBlt toForm: hack) sourceForm: hack.\\n\\tblt combinationRule: Form reverse. \\\"XOR\\\"\\n\\tblt sourceY: 0; destY: 0; height: self size; width: 1.\\n\\tblt sourceX: 0; destX: 1; copyBits. \\\"Exchange bytes 0 and 1\\\"\\n\\tblt sourceX: 1; destX: 0; copyBits.\\n\\tblt sourceX: 0; destX: 1; copyBits.\\n\\tblt sourceX: 2; destX: 3; copyBits. \\\"Exchange bytes 2 and 3\\\"\\n\\tblt sourceX: 3; destX: 2; copyBits.\\n\\tblt sourceX: 2; destX: 3; copyBits.\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/17/97 13:03'!\\nat: index\\n\\t\\\"Return the 16-bit integer value at the given index of the receiver.\\\"\\n\\n\\t<primitive: 143>\\n\\tindex isInteger ifTrue: [self errorSubscriptBounds: index].\\n\\tindex isNumber ifTrue: [^ self at: index truncated].\\n\\tself errorNonIntegerIndex.\\n! !\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/17/97 13:03'!\\nat: index put: value\\n\\t\\\"Store the given 16-bit integer at the given index in the receiver.\\\"\\n\\n\\t<primitive: 144>\\n\\tindex isInteger\\n\\t\\tifTrue: [\\n\\t\\t\\t(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]].\\n\\tindex isNumber ifTrue: [^ self at: index truncated put: value].\\n\\tself errorNonIntegerIndex.\\n! !\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/2/97 16:07'!\\nprimFill: aPositiveInteger\\n\\t\\\"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.\\\"\\n\\t\\\"Note: Since 16-bit word arrays are not built into the virtual machine, this primitive fills by 32-bit words.\\\"\\n\\n\\t<primitive: 145>\\n\\tself errorImproperStore.\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nasByteArray\\n\\t\\\"Answer a ByteArray containing my sample data serialized in most-significant byte first order.\\\"\\n\\n\\t| sampleCount bytes dst s |\\n\\tsampleCount := self monoSampleCount.\\n\\tbytes := ByteArray new: 2 * sampleCount.\\n\\tdst := 0.\\n\\t1 to: sampleCount do: [:src |\\n\\t\\ts := self at: src.\\n\\t\\tbytes at: (dst := dst + 1) put: ((s bitShift: -8) bitAnd: 255).\\n\\t\\tbytes at: (dst := dst + 1) put: (s bitAnd: 255)].\\n\\t^ bytes\\n\\n\\t! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naverageEvery: nSamples from: anotherBuffer upTo: inCount\\n\\n\\t| fromIndex sum |\\n\\n\\tfromIndex := 1.\\n\\t1 to: inCount // nSamples do: [ :i |\\n\\t\\tsum := 0.\\n\\t\\tnSamples timesRepeat: [\\n\\t\\t\\tsum := sum + (anotherBuffer at: fromIndex).\\n\\t\\t\\tfromIndex := fromIndex + 1.\\n\\t\\t].\\n\\t\\tself at: i put: sum // nSamples.\\n\\t].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndownSampledLowPassFiltering: doFiltering\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of every other sample. If doFiltering is true, a simple low-pass filter is applied to avoid aliasing of high frequencies. Assume that receiver is monophonic.\\\"\\n\\t\\\"Details: The simple low-pass filter in the current implementation could be improved, at some additional cost.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\tdoFiltering\\n\\t\\tifTrue: [\\n\\t\\t\\t1 to: n by: 2 do: [:i |\\n\\t\\t\\t\\tresultBuf at: (j := j + 1) put:\\n\\t\\t\\t\\t\\t(((self at: i) + (self at: i + 1)) bitShift: -1)]]\\n\\t\\tifFalse: [\\n\\t\\t\\t1 to: n by: 2 do: [:i |\\n\\t\\t\\t\\tresultBuf at: (j := j + 1) put: (self at: i)]].\\n\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractLeftChannel\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of only the left channel of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t1 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (self at: i)].\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractRightChannel\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of only the right channel of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t2 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (self at: i)].\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'jhm 10/15/97 15:13'!\\nindexOfFirstSampleOver: threshold\\n\\t\\\"Return the index of the first sample whose absolute value is over the given threshold value. Return an index one greater than my size if no sample is over the threshold.\\\"\\n\\n\\t1 to: self size do: [:i |\\n\\t\\t(self at: i) abs > threshold ifTrue: [^ i]].\\n\\t^ self size + 1! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'jhm 10/15/97 15:13'!\\nindexOfLastSampleOver: threshold\\n\\t\\\"Return the index of the last sample whose absolute value is over the given threshold value. Return zero if no sample is over the threshold.\\\"\\n\\n\\tself size to: 1 by: -1 do: [:i |\\n\\t\\t(self at: i) abs > threshold ifTrue: [^ i]].\\n\\t^ 0\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nlowPassFiltered\\n\\t\\\"Answer a simple low-pass filtered copy of this buffer. Assume it is monophonic.\\\"\\n\\n\\t| sz out last this |\\n\\tsz := self monoSampleCount.\\n\\tout := self clone.\\n\\tlast := self at: 1.\\n\\t2 to: sz do: [:i |\\n\\t\\tthis := self at: i.\\n\\t\\tout at: i put: (this + last) // 2.\\n\\t\\tlast := this].\\n\\t^ out\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmergeStereo\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver that mixes the left and right stereo channels of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t1 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (((self at: i) + (self at: i + 1)) // 2)].\\n\\t^ resultBuf\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnormalized: percentOfFullVolume\\n\\t\\\"Increase my amplitudes so that the highest peak is the given percent of full volume. For example 's normalized: 50' would normalize to half of full volume.\\\"\\n\\n\\t| peak s mult |\\n\\tpeak := 0.\\n\\t1 to: self size do: [:i |\\n\\t\\ts := (self at: i) abs.\\n\\t\\ts > peak ifTrue: [peak := s]].\\n\\tmult := (32767.0 * percentOfFullVolume) / (100.0 * peak).\\n\\t1 to: self size do: [:i | self at: i put: (mult * (self at: i)) asInteger].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsaveAsAIFFFileSamplingRate: rate on: aBinaryStream\\n\\t\\\"Store this mono sound buffer in AIFF file format with the given sampling rate on the given stream.\\\"\\n\\n\\t| sampleCount s swapBytes |\\n\\tsampleCount := self monoSampleCount.\\n\\taBinaryStream nextPutAll: 'FORM' asByteArray.\\n\\taBinaryStream nextInt32Put: (2 * sampleCount) + ((7 * 4) + 18).\\n\\taBinaryStream nextPutAll: 'AIFF' asByteArray.\\n\\taBinaryStream nextPutAll: 'COMM' asByteArray.\\n\\taBinaryStream nextInt32Put: 18.\\n\\taBinaryStream nextNumber: 2 put: 1. \\\"channels\\\"\\n\\taBinaryStream nextInt32Put: sampleCount.\\n\\taBinaryStream nextNumber: 2 put: 16. \\\"bits/sample\\\"\\n\\tself storeExtendedFloat: rate on: aBinaryStream.\\n\\taBinaryStream nextPutAll: 'SSND' asByteArray.\\n\\taBinaryStream nextInt32Put: (2 * sampleCount) + 8.\\n\\taBinaryStream nextInt32Put: 0.\\n\\taBinaryStream nextInt32Put: 0.\\n\\n\\t(aBinaryStream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\t\\\"optimization: write sound buffer directly to file\\\"\\n\\t\\tswapBytes := SmalltalkImage current isLittleEndian.\\n\\t\\tswapBytes ifTrue: [self reverseEndianness]. \\\"make big endian\\\"\\n\\t\\taBinaryStream next: (self size // 2) putAll: self startingAt: 1. \\\"size in words\\\"\\n\\t\\tswapBytes ifTrue: [self reverseEndianness]. \\\"revert to little endian\\\"\\n\\t\\t^ self].\\n\\n\\t1 to: sampleCount do: [:i |\\n\\t\\ts := self at: i.\\n\\t\\taBinaryStream nextPut: ((s bitShift: -8) bitAnd: 16rFF).\\n\\t\\taBinaryStream nextPut: (s bitAnd: 16rFF)].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsplitStereo\\n\\t\\\"Answer an array of two SoundBuffers half the size of the receiver consisting of the left and right channels of the receiver (which is assumed to contain stereo sound data).\\\"\\n\\n\\t| n leftBuf rightBuf leftIndex rightIndex |\\n\\tn := self monoSampleCount.\\n\\tleftBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\trightBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tleftIndex := rightIndex := 0.\\n\\t1 to: n by: 2 do: [:i |\\n\\t\\tleftBuf at: (leftIndex := leftIndex + 1) put: (self at: i).\\n\\t\\trightBuf at: (rightIndex := rightIndex + 1) put: (self at: i + 1)].\\n\\t^ Array with: leftBuf with: rightBuf\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreExtendedFloat: aNumber on: aBinaryStream\\n\\t\\\"Store an Apple extended-precision 80-bit floating point number on the given stream.\\\"\\n\\t\\\"Details: I could not find the specification for this format, so constants were determined empirically based on assumption of 1-bit sign, 15-bit exponent, 64-bit mantissa. This format does not seem to have an implicit one before the mantissa as some float formats do.\\\"\\n\\n\\t| n isNeg exp mantissa |\\n\\tn := aNumber asFloat.\\n\\tisNeg := false.\\n\\tn < 0.0 ifTrue: [\\n\\t\\tn := 0.0 - n.\\n\\t\\tisNeg := true].\\n\\texp := (n log: 2.0) ceiling.\\n\\tmantissa := (n * (2 raisedTo: 64 - exp)) truncated.\\n\\texp := exp + 16r4000 - 2. \\\"not sure why the -2 is needed...\\\"\\n\\tisNeg ifTrue: [exp := exp bitOr: 16r8000]. \\\"set sign bit\\\"\\n\\taBinaryStream nextPut: ((exp bitShift: -8) bitAnd: 16rFF).\\n\\taBinaryStream nextPut: (exp bitAnd: 16rFF).\\n\\t8 to: 1 by: -1 do: [:i | aBinaryStream nextPut: (mantissa digitAt: i)].! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntrimmedThreshold: threshold\\n\\n\\t| start end |\\n\\tstart := self indexOfFirstSampleOver: threshold.\\n\\tend := self indexOfLastSampleOver: threshold.\\n\\tstart > end ifTrue: [^ SoundBuffer new].\\n\\tstart := (start - 200) max: 1.\\n\\tend := (end + 200) min: self size.\\n\\t^ self copyFrom: start to: end\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundBuffer class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundBuffer class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"Build a sine wave table.\\\"\\n\\t\\\"SoundBuffer initialize\\\"\\n\\n\\t| tableSize radiansPerStep peak |\\n\\ttableSize := 4000.\\n\\tSineTable := self newMonoSampleCount: tableSize.\\n\\tradiansPerStep := (2.0 * Float pi) / tableSize asFloat.\\n\\tpeak := ((1 bitShift: 15) - 1) asFloat. \\\"range is +/- (2^15 - 1)\\\"\\n\\t1 to: tableSize do: [:i |\\n\\t\\tSineTable at: i put: (peak * (radiansPerStep * (i - 1)) sin) rounded].\\n! !\\n\\n!SoundBuffer class methodsFor: 'class initialization' stamp: 'ads 7/31/2003 11:13'!\\nsineTable\\n\\t\\\"Answer a SoundBuffer containing one complete cycle of a sine wave.\\\"\\n\\n\\t^ SineTable\\n! !\\n\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'RAA 12/30/2000 18:20'!\\naverageEvery: nSamples from: anotherBuffer upTo: inCount\\n\\n\\t^(self newMonoSampleCount: inCount // nSamples)\\n\\t\\taverageEvery: nSamples \\n\\t\\tfrom: anotherBuffer \\n\\t\\tupTo: inCount! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfromArray: anArray\\n\\t\\\"Return a new SoundBuffer whose contents are copied from the given Array or ByteArray.\\\"\\n\\n\\t| new |\\n\\tnew := SoundBuffer newMonoSampleCount: anArray size.\\n\\t1 to: anArray size do: [:i | new at: i put: (anArray at: i)].\\n\\t^ new\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfromByteArray: aByteArray\\n\\t\\\"Convert the given ByteArray (stored with the most significant byte first) into 16-bit sample buffer.\\\"\\n\\n\\t| n buf src w |\\n\\tn := aByteArray size // 2.\\n\\tbuf := SoundBuffer newMonoSampleCount: n.\\n\\tsrc := 1.\\n\\t1 to: n do: [:i |\\n\\t\\tw := ((aByteArray at: src) bitShift: 8) + (aByteArray at: src + 1).\\n\\t\\tw > 32767 ifTrue: [w := w - 65536].\\n\\t\\tbuf at: i put: w.\\n\\t\\tsrc := src + 2].\\n\\t^ buf\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 13:25'!\\nnew: anInteger\\n\\t\\\"See the comment in newMonoSampleCount:. To avoid confusion, it is best to create new instances using newMonoSampleCount: or newStereoSampleCount:.\\\"\\n\\n\\t^ self newMonoSampleCount: anInteger\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 12:44'!\\nnewMonoSampleCount: anInteger\\n\\t\\\"Return a SoundBuffer large enough to hold the given number of monaural samples (i.e., 16-bit words).\\\"\\n\\t\\\"Details: The size is rounded up to an even number, since the underlying representation is in terms of 32-bit words.\\\"\\n\\n\\t^ self basicNew: (anInteger + 1) // 2\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 12:52'!\\nnewStereoSampleCount: anInteger\\n\\t\\\"Return a SoundBuffer large enough to hold the given number of stereo slices. A stereo 'slice' consists of two 16-bit samples, one for each channel.\\\"\\n\\n\\t^ self basicNew: anInteger\\n! !\\n\\n\\n!SoundBuffer class methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartUp\\n\\t\\\"Check if the word order has changed from the last save.\\\"\\n\\n\\t| la |\\n\\tla := ShortIntegerArray classPool at: #LastSaveOrder.\\n\\t((la at: 2) = 42 and: [(la at: 1) = 13]) \\n\\t\\tifTrue: [^self swapHalves]. \\\"Reverse the two 16-bit halves.\\\"\\n\\t\\t\\t\\t\\\"Another reversal happened automatically which reversed the bytes.\\\"\\n! !\\n\\n!SoundBuffer class methodsFor: 'objects from disk' stamp: 'nk 2/22/2005 15:29'!\\nstartUpFrom: anImageSegment \\n\\t\\\"In this case, do we need to swap word halves when reading this segment?\\\"\\n\\n\\t^SmalltalkImage current endianness ~~ anImageSegment endianness \\n\\t\\tifTrue: [Message selector: #swapHalves\\t\\\"will be run on each instance\\\"]\\n\\t\\tifFalse: [nil]! !\\nObject subclass: #SoundCodec\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundCodec commentStamp: '<historical>' prior: 0!\\nI am an abstract class that describes the protocol for sound codecs. Each codec (the name stems from \\\"COder/DECoder\\\") describes a particular algorithm for compressing and decompressing sound data. Most sound codecs are called 'lossy' because they lose information; the decompressed sound data is not exactly the same as the original data.\\n!\\n\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'jm 2/2/1999 16:01'!\\ncompressAndDecompress: aSound\\n\\t\\\"Compress and decompress the given sound. Useful for testing.\\\"\\n\\t\\\"(MuLawCodec new compressAndDecompress: (SampledSound soundNamed: 'camera')) play\\\"\\n\\n\\t^ (self compressSound: aSound) asSound\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncompressSound: aSound\\n\\t\\\"Compress the entirety of the given sound with this codec. Answer a CompressedSoundData.\\\"\\n\\n\\t| compressed channels |\\n\\tcompressed := CompressedSoundData new\\n\\t\\tcodecName: self class name;\\n\\t\\tsoundClassName: aSound class name.\\n\\t(aSound isKindOf: SampledSound) ifTrue: [\\n\\t\\tchannels := Array new: 1.\\n\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound samples).\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: 1;\\n\\t\\t\\tloopEnd: aSound samples size;\\n\\t\\t\\tloopLength: 0.0;\\n\\t\\t\\tperceivedPitch: 100.0;\\n\\t\\t\\tgain: aSound loudness.\\n\\t\\t^ compressed].\\n\\t(aSound isKindOf: LoopedSampledSound) ifTrue: [\\n\\t\\taSound isStereo\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tchannels := Array new: 2.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples).\\n\\t\\t\\t\\tchannels at: 2 put: (self encodeSoundBuffer: aSound rightSamples)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tchannels := Array new: 1.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples)].\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: aSound firstSample;\\n\\t\\t\\tloopEnd: aSound loopEnd;\\n\\t\\t\\tloopLength: aSound loopLength;\\n\\t\\t\\tperceivedPitch: aSound perceivedPitch;\\n\\t\\t\\tgain: aSound gain.\\n\\t\\t^ compressed].\\n\\tself error: 'you can only compress sampled sounds'.\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncompressSound: aSound atRate: desiredSampleRate\\n\\t\\\"Compress the entirety of the given sound with this codec. Answer a CompressedSoundData.\\\"\\n\\n\\t| compressed channels samples newRate ratio buffer |\\n\\n\\tcompressed := CompressedSoundData new\\n\\t\\tcodecName: self class name;\\n\\t\\tsoundClassName: aSound class name.\\n\\t(aSound isKindOf: SampledSound) ifTrue: [\\n\\t\\t(desiredSampleRate isNil or: \\n\\t\\t\\t\\t[(ratio := aSound originalSamplingRate // desiredSampleRate) <= 1]) ifTrue: [\\n\\t\\t\\tsamples := aSound samples.\\n\\t\\t\\tnewRate := aSound originalSamplingRate.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tbuffer := aSound samples.\\n\\t\\t\\tsamples := SoundBuffer \\n\\t\\t\\t\\taverageEvery: ratio \\n\\t\\t\\t\\tfrom: buffer \\n\\t\\t\\t\\tupTo: buffer monoSampleCount.\\n\\t\\t\\tnewRate := aSound originalSamplingRate / ratio.\\n\\t\\t].\\n\\n\\t\\tchannels := Array new: 1.\\n\\t\\tchannels at: 1 put: (self encodeSoundBuffer: samples).\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: newRate;\\n\\t\\t\\tfirstSample: 1;\\n\\t\\t\\tloopEnd: samples size;\\n\\t\\t\\tloopLength: 0.0;\\n\\t\\t\\tperceivedPitch: 100.0;\\n\\t\\t\\tgain: aSound loudness.\\n\\t\\t^ compressed].\\n\\t(aSound isKindOf: LoopedSampledSound) ifTrue: [\\n\\t\\taSound isStereo\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tchannels := Array new: 2.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples).\\n\\t\\t\\t\\tchannels at: 2 put: (self encodeSoundBuffer: aSound rightSamples)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tchannels := Array new: 1.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples)].\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: aSound firstSample;\\n\\t\\t\\tloopEnd: aSound loopEnd;\\n\\t\\t\\tloopLength: aSound loopLength;\\n\\t\\t\\tperceivedPitch: aSound perceivedPitch;\\n\\t\\t\\tgain: aSound gain.\\n\\t\\t^ compressed].\\n\\tself error: 'you can only compress sampled sounds'.\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecompressSound: aCompressedSound\\n\\t\\\"Decompress the entirety of the given compressed sound with this codec and answer the resulting sound.\\\"\\n\\n\\t| channels sound |\\n\\tchannels := aCompressedSound channels\\n\\t\\tcollect: [:compressed | self decodeCompressedData: compressed].\\n\\t'SampledSound' = aCompressedSound soundClassName ifTrue: [\\n\\t\\tsound := SampledSound\\n\\t\\t\\tsamples: channels first\\n\\t\\t\\tsamplingRate: (aCompressedSound samplingRate).\\n\\t\\tsound loudness: aCompressedSound gain.\\n\\t\\t^ sound].\\n\\t'LoopedSampledSound' = aCompressedSound soundClassName ifTrue: [\\n\\t\\taCompressedSound loopLength = 0\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tsound := LoopedSampledSound\\n\\t\\t\\t\\t\\tunloopedSamples: channels first\\n\\t\\t\\t\\t\\tpitch: aCompressedSound perceivedPitch\\n\\t\\t\\t\\t\\tsamplingRate: aCompressedSound samplingRate]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsound := LoopedSampledSound\\n\\t\\t\\t\\t\\tsamples: channels first\\n\\t\\t\\t\\t\\tloopEnd: aCompressedSound loopEnd\\n\\t\\t\\t\\t\\tloopLength: aCompressedSound loopLength\\n\\t\\t\\t\\t\\tpitch: aCompressedSound perceivedPitch\\n\\t\\t\\t\\t\\tsamplingRate: aCompressedSound samplingRate].\\n\\t\\tchannels size > 1 ifTrue: [sound rightSamples: channels last].\\n\\t\\tsound\\n\\t\\t\\tfirstSample: aCompressedSound firstSample;\\n\\t\\t\\tgain: aCompressedSound gain.\\n\\t\\tsound\\n\\t\\t\\tsetPitch: 100.0\\n\\t\\t\\tdur: (channels first size / aCompressedSound samplingRate)\\n\\t\\t\\tloudness: 1.0.\\n\\t\\t^ sound].\\n\\tself error: 'unknown sound class'.\\n! !\\n\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'di 2/8/1999 14:23'!\\nbytesPerEncodedFrame\\n\\t\\\"Answer the number of bytes required to hold one frame of compressed sound data. Answer zero if this codec produces encoded frames of variable size.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:38'!\\ndecodeFrames: frameCount from: srcByteArray at: srcIndex into: dstSoundBuffer at: dstIndex\\n\\t\\\"Decode the given number of monophonic frames starting at the given index in the given ByteArray of compressed sound data and storing the decoded samples into the given SoundBuffer starting at the given destination index. Answer a pair containing the number of bytes of compressed data consumed and the number of decompressed samples produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:39'!\\nencodeFrames: frameCount from: srcSoundBuffer at: srcIndex into: dstByteArray at: dstIndex\\n\\t\\\"Encode the given number of frames starting at the given index in the given monophonic SoundBuffer and storing the encoded sound data into the given ByteArray starting at the given destination index. Encode only as many complete frames as will fit into the destination. Answer a pair containing the number of samples consumed and the number of bytes of compressed data produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/4/1999 11:30'!\\nreset\\n\\t\\\"Reset my encoding and decoding state. Optional. This default implementation does nothing.\\\"\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:45'!\\nsamplesPerFrame\\n\\t\\\"Answer the number of sound samples per compression frame.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecodeCompressedData: aByteArray\\n\\t\\\"Decode the entirety of the given encoded data buffer with this codec. Answer a monophonic SoundBuffer containing the uncompressed samples.\\\"\\n\\n\\t| frameCount result increments |\\n\\tframeCount := self frameCount: aByteArray.\\n\\tresult := SoundBuffer newMonoSampleCount: frameCount * self samplesPerFrame.\\n\\tself reset.\\n\\tincrements := self decodeFrames: frameCount from: aByteArray at: 1 into: result at: 1.\\n\\t((increments first = aByteArray size) and: [increments last = result size]) ifFalse: [\\n\\t\\tself error: 'implementation problem; increment sizes should match buffer sizes'].\\n\\t^ result\\n! !\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nencodeSoundBuffer: aSoundBuffer\\n\\t\\\"Encode the entirety of the given monophonic SoundBuffer with this codec. Answer a ByteArray containing the compressed sound data.\\\"\\n\\n\\t| codeFrameSize frameSize fullFrameCount lastFrameSamples result increments finalFrame i lastIncs |\\n\\tframeSize := self samplesPerFrame.\\n\\tfullFrameCount := aSoundBuffer monoSampleCount // frameSize.\\n\\tlastFrameSamples := aSoundBuffer monoSampleCount - (fullFrameCount * frameSize).\\n\\tcodeFrameSize := self bytesPerEncodedFrame.\\n\\tcodeFrameSize = 0 ifTrue:\\n\\t\\t[\\\"Allow room for 1 byte per sample for variable-length compression\\\"\\n\\t\\tcodeFrameSize := frameSize].\\n\\tlastFrameSamples > 0\\n\\t\\tifTrue: [result := ByteArray new: (fullFrameCount + 1) * codeFrameSize]\\n\\t\\tifFalse: [result := ByteArray new: fullFrameCount * codeFrameSize].\\n\\tself reset.\\n\\tincrements := self encodeFrames: fullFrameCount from: aSoundBuffer at: 1 into: result at: 1.\\n\\tlastFrameSamples > 0 ifTrue: [\\n\\t\\tfinalFrame := SoundBuffer newMonoSampleCount: frameSize.\\n\\t\\ti := fullFrameCount * frameSize.\\n\\t\\t1 to: lastFrameSamples do: [:j |\\n\\t\\t\\tfinalFrame at: j put: (aSoundBuffer at: (i := i + 1))].\\n\\t\\tlastIncs := self encodeFrames: 1 from: finalFrame at: 1 into: result at: 1 + increments second.\\n\\t\\tincrements := Array with: increments first + lastIncs first\\n\\t\\t\\t\\t\\t\\t\\twith: increments second + lastIncs second].\\n\\tincrements second < result size\\n\\t\\tifTrue: [^ result copyFrom: 1 to: increments second]\\n\\t\\tifFalse: [^ result]\\n! !\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nframeCount: aByteArray\\n\\t\\\"Compute the frame count for this byteArray. This default computation will have to be overridden by codecs with variable frame sizes.\\\"\\n\\n\\t| codeFrameSize |\\n\\tcodeFrameSize := self bytesPerEncodedFrame.\\n\\t(aByteArray size \\\\\\\\ codeFrameSize) = 0 ifFalse:\\n\\t\\t[self error: 'encoded buffer is not an even multiple of the encoded frame size'].\\n\\t^ aByteArray size // codeFrameSize! !\\nAlignmentMorph subclass: #SoundDemoMorph\\n\\tinstanceVariableNames: 'soundColumn'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'tk 2/19/2001 17:49'!\\nmakeControls\\n\\n\\t| bb r cc |\\n\\tcc _ Color black.\\n\\tr _ AlignmentMorph newRow.\\n\\tr color: cc; borderWidth: 0; layoutInset: 0.\\n\\tr hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V1';\\t\\t\\tactionSelector: #playV1).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V2';\\t\\t\\tactionSelector: #playV2).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V3';\\t\\t\\tactionSelector: #playV3).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'All';\\t\\t\\tactionSelector: #playAll).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'Stop';\\t\\tactionSelector: #stopSound).\\n\\t^ r\\n! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:34'!\\nplayAll\\n\\t| snd |\\n\\tsoundColumn submorphs isEmpty\\n\\t\\tifTrue: [^ self].\\n\\tself setTimbreFromTile: soundColumn submorphs first.\\n\\tsnd _ SampledSound bachFugueVoice1On: SampledSound new.\\n\\tsoundColumn submorphs size >= 2\\n\\t\\tifTrue: [\\\"\\\"self setTimbreFromTile: soundColumn submorphs second.\\n\\t\\t\\tsnd _ snd\\n\\t\\t\\t\\t\\t\\t+ (AbstractSound bachFugueVoice2On: SampledSound new)].\\n\\tsoundColumn submorphs size >= 3\\n\\t\\tifTrue: [\\\"\\\"self setTimbreFromTile: soundColumn submorphs third.\\n\\t\\t\\tsnd _ snd\\n\\t\\t\\t\\t\\t\\t+ (AbstractSound bachFugueVoice3On: SampledSound new)].\\n\\tsnd play! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV1\\n\\tsoundColumn submorphs isEmpty\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs first).\\n\\t(SampledSound bachFugueVoice1On: SampledSound new) play! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV2\\n\\tsoundColumn submorphs size < 2\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs second).\\n\\t(SampledSound bachFugueVoice2On: SampledSound new) playSilentlyUntil: 4.8;\\n\\t\\t resumePlaying! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV3\\n\\tsoundColumn submorphs size < 3\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs third).\\n\\t(AbstractSound bachFugueVoice3On: SampledSound new) playSilentlyUntil: 14.4;\\n\\t\\t resumePlaying! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:09'!\\nsetTimbreFromTile: aSoundTile\\n\\n\\tSampledSound defaultSampleTable: aSoundTile sound samples.\\n\\tSampledSound nominalSamplePitch: 400.\\n! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:09'!\\nstopSound\\n\\n\\tSoundPlayer shutDown.\\n! !\\n\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGray! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:04'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\t wrapCentering: #center;\\n\\t\\t cellPositioning: #topCenter;\\n\\t\\t hResizing: #spaceFill;\\n\\t\\t vResizing: #spaceFill;\\n\\t\\t layoutInset: 3;\\n\\t\\t addMorph: self makeControls;\\n\\tinitializeSoundColumn.\\n\\tself extent: 118 @ 150! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'jam 3/9/2003 17:52'!\\ninitializeSoundColumn\\n\\\"initialize the receiver's soundColumn\\\"\\n\\tsoundColumn _ AlignmentMorph newColumn.\\n\\tsoundColumn enableDragNDrop.\\n\\tself addMorphBack: soundColumn! !\\nAbstractMediaEventMorph subclass: #SoundEventMorph\\n\\tinstanceVariableNames: 'sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundEventMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/7/2000 13:01'!\\nsound: aSound\\n\\n\\tsound _ aSound.\\n\\tself setBalloonText: 'a sound of duration ',(sound duration roundTo: 0.1) printString,' seconds'.! !\\n\\n\\n!SoundEventMorph methodsFor: 'caching' stamp: 'RAA 12/8/2000 09:52'!\\nreleaseCachedState\\n\\n\\tsuper releaseCachedState.\\n\\tsound _ sound compressWith: GSMCodec.\\n! !\\n\\n\\n!SoundEventMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGreen! !\\n\\n!SoundEventMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:39'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself height: 10! !\\n\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/7/2000 12:36'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t| startX lengthInTicks endX |\\n\\n\\tstartTimeInScore > rightTime ifTrue: [^ self]. \\n\\tlengthInTicks _ pianoRoll scorePlayer ticksForMSecs: sound duration * 1000.0.\\n\\tstartTimeInScore + lengthInTicks < leftTime ifTrue: [^ self].\\n\\tstartX _ pianoRoll xForTime: startTimeInScore.\\n\\tendX _ pianoRoll xForTime: startTimeInScore + lengthInTicks.\\n\\tmorphList add: \\n\\t\\t(self left: startX; width: endX - startX).\\n\\n! !\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/7/2000 12:29'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"hack... since we are called from within the SoundPlayer loop, the Semaphore will\\n\\tblock attempts to play directly from here\\\"\\n\\tWorldState addDeferredUIMessage: [sound play].! !\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/9/2000 18:48'!\\njustDroppedIntoPianoRoll: newOwner event: evt\\n\\t\\n\\t| startX lengthInTicks endX |\\n\\n\\tsuper justDroppedIntoPianoRoll: newOwner event: evt.\\n\\n\\tstartTimeInScore _ newOwner timeForX: self left.\\n\\tlengthInTicks _ newOwner scorePlayer ticksForMSecs: sound duration * 1000.0.\\n\\tendTimeInScore _ startTimeInScore + lengthInTicks.\\n\\n\\tendTimeInScore > newOwner scorePlayer durationInTicks ifTrue:\\n\\t\\t[newOwner scorePlayer updateDuration].\\n\\n\\tstartX _ newOwner xForTime: startTimeInScore.\\n\\tendX _ newOwner xForTime: endTimeInScore.\\n\\tself width: endX - startX.\\n\\n! !\\nSoundRecorder subclass: #SoundInputStream\\n\\tinstanceVariableNames: 'bufferSize mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundInputStream commentStamp: '<historical>' prior: 0!\\nThis subclass of SoundRecorder supports real-time processing of incoming sound data. The sound input process queues raw sound buffers, allowing them to be read and processed by the client as they become available. A semaphore is used to synchronize between the record process and the client process. Since sound data is buffered, the client process may lag behind the input process without losing data.\\n!\\n\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nbufferCount\\n\\t\\\"Answer the number of sound buffers that have been queued.\\\"\\n\\n\\t| n |\\n\\tmutex ifNil: [^ 0]. \\\"not recording\\\"\\n\\tmutex critical: [n := recordedBuffers size].\\n\\t^ n\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'jm 9/6/1999 10:36'!\\nbufferSize\\n\\n\\t^ bufferSize\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nbufferSize: aNumber\\n\\t\\\"Set the sound buffer size. Buffers of this size will be queued for the client to process.\\\"\\n\\n\\tbufferSize := aNumber truncated.\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'jm 9/8/1999 15:23'!\\nisRecording\\n\\t\\\"Answer true if the sound input process is running.\\\"\\n\\n\\t^ recordProcess ~~ nil\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnextBufferOrNil\\n\\t\\\"Answer the next input buffer or nil if no buffer is available.\\\"\\n\\n\\t| result |\\n\\tmutex ifNil: [^ nil]. \\\"not recording\\\"\\n\\tmutex critical: [\\n\\t\\trecordedBuffers size > 0\\n\\t\\t\\tifTrue: [result := recordedBuffers removeFirst]\\n\\t\\t\\tifFalse: [result := nil]].\\n\\t^ result\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tbufferSize := 1024.\\n\\tmutex := nil.\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartRecording\\n\\t\\\"Start the sound input process.\\\"\\n\\n\\trecordProcess ifNotNil: [self stopRecording].\\n\\trecordedBuffers := OrderedCollection new: 100.\\n\\tmutex := Semaphore forMutualExclusion.\\n\\tsuper startRecording.\\n\\tpaused := false.\\n! !\\n\\n!SoundInputStream methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopRecording\\n\\t\\\"Turn off the sound input process and close the driver.\\\"\\n\\n\\tsuper stopRecording.\\n\\trecordedBuffers := nil.\\n\\tmutex := nil.\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nallocateBuffer\\n\\t\\\"Allocate a new buffer and reset nextIndex. This message is sent by the sound input process.\\\"\\n\\n\\tcurrentBuffer := SoundBuffer newMonoSampleCount: bufferSize.\\n\\tnextIndex := 1.\\n! !\\n\\n!SoundInputStream methodsFor: 'private' stamp: 'jm 9/8/1999 15:24'!\\nemitBuffer: buffer\\n\\t\\\"Queue a buffer for later processing. This message is sent by the sound input process.\\\"\\n\\n\\tmutex critical: [recordedBuffers addLast: buffer].\\n! !\\nRectangleMorph subclass: #SoundLoopMorph\\n\\tinstanceVariableNames: 'samplesUntilNextControl seqSound cursor controlIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:21'!\\naddCursorMorph\\n\\tself addMorph:\\n\\t\\t(cursor _ (RectangleMorph\\n\\t\\t\\t\\tnewBounds: (self innerBounds topLeft extent: 1@self innerBounds height)\\n\\t\\t\\t\\tcolor: Color red)\\n\\t\\t\\t\\t\\t\\tborderWidth: 0)! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:11'!\\nallowSubmorphExtraction\\n\\n\\t^ true! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/5/98 17:31'!\\nbuildSound\\n\\t\\\"Build a compound sound for the next iteration of the loop.\\\"\\n\\n\\t| mixer soundMorphs startTime pan |\\n\\tmixer _ MixedSound new.\\n\\tmixer add: (RestSound dur: (self width - (2 * borderWidth)) / 128.0).\\n\\tsoundMorphs _ self submorphs select: [:m | m respondsTo: #sound].\\n\\tsoundMorphs do: [:m |\\n\\t\\tstartTime _ (m position x - (self left + borderWidth)) / 128.0.\\n\\t\\tpan _ (m position y - (self top + borderWidth)) asFloat / (self height - (2 * borderWidth) - m height).\\n\\t\\tmixer add: ((RestSound dur: startTime), m sound copy) pan: pan].\\n\\t^ mixer\\n! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:11'!\\nplay\\n\\t\\\"Play this sound to the sound ouput port in real time.\\\"\\n\\n\\tself reset.\\n\\tSoundPlayer playSound: self.\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'dropping/grabbing' stamp: 'jm 11/14/97 11:11'!\\nwantsDroppedMorph: aMorph event: evt\\n\\n\\t^ aMorph respondsTo: #sound\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'geometry' stamp: 'jm 11/14/97 11:21'!\\nextent: newExtent\\n\\tsuper extent: (newExtent truncateTo: 128@128) + (self borderWidth*2)! !\\n\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:07'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 128 @ 128 + (self defaultBorderWidth * 2)! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightBlue! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:50'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tcontrolIndex _ 0.\\n\\tself addCursorMorph! !\\n\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\ncontrolRate\\n\\t\\\"Answer the number of control changes per second.\\\"\\n\\n\\t^ 32\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\ndoControl\\n\\n\\tseqSound doControl.\\n\\tcontrolIndex _ controlIndex + 1.\\n\\tcontrolIndex >= (self controlRate * (self innerBounds width // 128))\\n\\t\\tifTrue: [controlIndex _ 0].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 1/5/98 13:40'!\\nmixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol\\n\\t\\\"Repeatedly play my sounds.\\\"\\n\\n\\t| i count samplesNeeded |\\n\\ti _ startIndex.\\n\\tsamplesNeeded _ n.\\n\\t[samplesNeeded > 0] whileTrue: [\\n\\t\\tcount _ seqSound samplesRemaining min: samplesNeeded.\\n\\t\\tcount = 0 ifTrue: [\\n\\t\\t\\tself reset.\\n\\t\\t\\tcount _ seqSound samplesRemaining min: samplesNeeded.\\n\\t\\t\\tcount = 0 ifTrue: [^ self]]. \\\"zero length sound\\\"\\n\\t\\tseqSound mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: leftVol rightVol: rightVol.\\n\\t\\ti _ i + count.\\n\\t\\tsamplesNeeded _ samplesNeeded - count].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 1/26/98 22:05'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"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.\\\"\\n\\n\\t| fullVol samplesBetweenControlUpdates pastEnd i remainingSamples count |\\n\\tfullVol _ AbstractSound scaleFactor.\\n\\tsamplesBetweenControlUpdates _ self samplingRate // self controlRate.\\n\\tpastEnd _ startIndex + n. \\\"index just index of after last sample\\\"\\n\\ti _ startIndex.\\n\\t[i < pastEnd] whileTrue: [\\n\\t\\tremainingSamples _ self samplesRemaining.\\n\\t\\tremainingSamples <= 0 ifTrue: [^ self].\\n\\t\\tcount _ pastEnd - i.\\n\\t\\tsamplesUntilNextControl < count ifTrue: [count _ samplesUntilNextControl].\\n\\t\\tremainingSamples < count ifTrue: [count _ remainingSamples].\\n\\t\\tself mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: fullVol rightVol: fullVol.\\n\\t\\tsamplesUntilNextControl _ samplesUntilNextControl - count.\\n\\t\\tsamplesUntilNextControl <= 0 ifTrue: [\\n\\t\\t\\tself doControl.\\n\\t\\t\\tsamplesUntilNextControl _ samplesBetweenControlUpdates].\\n\\t\\ti _ i + count].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\npositionCursor\\n\\t| x |\\n\\tx _ controlIndex * 128 // self controlRate.\\n\\tcursor position: self innerBounds topLeft + (x@0)\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\nreset\\n\\t\\\"Reset my internal state for a replay.\\\"\\n\\n\\tseqSound _ self buildSound reset.\\n\\tsamplesUntilNextControl _ (self samplingRate // self controlRate).\\n\\tcontrolIndex _ 0.\\n\\tself positionCursor! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:11'!\\nsamplesRemaining\\n\\n\\t^ 1000000\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:11'!\\nsamplingRate\\n\\t\\\"Answer the sampling rate in samples per second.\\\"\\n\\n\\t^ SoundPlayer samplingRate! !\\n\\n\\n!SoundLoopMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:21'!\\nstep\\n\\tself positionCursor! !\\n\\n!SoundLoopMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:11'!\\nstop\\n\\t\\\"Stop playing this sound.\\\"\\n\\n\\tSoundPlayer pauseSound: self.\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'testing' stamp: 'jm 11/14/97 11:21'!\\nstepTime\\n\\n\\t^ 50\\n! !\\nImageMorph subclass: #SoundMorph\\n\\tinstanceVariableNames: 'sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n!SoundMorph commentStamp: '<historical>' prior: 0!\\nNote: as of December 2000, this does not work. SoundMorph>>buildImage requires the sound to implement #volumeEnvelopeScaledTo: and as yet, no one does.!\\n\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:21'!\\nbuildImage\\n\\t| scale env h imageColor |\\n\\towner ifNil: [scale _ 128@128] \\\"Default is 128 pix/second, 128 pix fullscale\\\"\\n\\t\\tifNotNil: [scale _ owner soundScale].\\n\\tenv _ sound volumeEnvelopeScaledTo: scale.\\n\\tself image: (ColorForm extent: env size @ env max).\\n\\t1 to: image width do:\\n\\t\\t[:x | h _ env at: x.\\n\\t\\timage fillBlack: ((x-1)@(image height-h//2) extent: 1@h)].\\n\\timageColor _ #(black red orange green blue) atPin:\\n\\t\\t\\t\\t\\t\\t(sound pitch / 110.0) rounded highBit.\\n\\timage colors: (Array with: Color transparent with: (Color perform: imageColor)).\\n! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nreset\\n\\tsound reset! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nsound\\n\\t^ sound! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nsound: aSound\\n\\tsound _ aSound copy.\\n\\tsound reset.\\n\\tself buildImage! !\\n\\n\\n!SoundMorph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 20:05'!\\njustDroppedInto: aMorph event: anEvent\\n\\t| relPosition |\\n\\trelPosition _ self position - aMorph innerBounds topLeft.\\n\\trelPosition _ (relPosition x roundTo: 8) @ relPosition y.\\n\\tself position: aMorph innerBounds topLeft + relPosition.\\n\\tsound copy play.\\n\\t^super justDroppedInto: aMorph event: anEvent! !\\n\\n\\n!SoundMorph methodsFor: 'initialization' stamp: 'jm 12/17/97 22:43'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself sound: (FMSound pitch: 880.0 dur: 0.2 loudness: 0.8).\\n! !\\nObject subclass: #SoundPlayer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ActiveSounds Buffer BufferIndex BufferMSecs LastBuffer PlayerProcess PlayerSemaphore ReadyForBuffer ReverbState SamplingRate SoundJustStarted SoundSupported Stereo UseReadySemaphore UseReverb'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundPlayer class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'jm 8/13/1998 15:00'!\\nbufferMSecs\\n\\n\\t^ BufferMSecs\\n! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'jm 1/27/98 09:28'!\\nreverbState\\n\\n\\t^ ReverbState! !\\n\\n!SoundPlayer class methodsFor: 'accessing'!\\nsamplingRate\\n\\n\\t^ SamplingRate! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'JMM 11/6/2000 10:16'!\\nsetVolumeLeft: aLeftVolume volumeRight: aRightVolume\\n\\t\\\"Set sound pass in float 0.0-1.0 for left and right channel, with possible 2.0 or higher to overdrive sound channel \\\"\\n\\tself primSoundSetVolumeLeft: aLeftVolume volumeRight: aRightVolume! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'JMM 11/6/2000 10:17'!\\nsoundVolume\\n\\t\\\"Return sound as array of doubles left then right channel, range is 0.0 to 1.0 but may be overdriven\\\"\\n\\t^self primSoundGetVolume! !\\n\\n!SoundPlayer class methodsFor: 'accessing'!\\nstereo\\n\\n\\t^ Stereo\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundPlayer initialize; shutDown; startUp\\\"\\n\\t\\\"Details: BufferMSecs represents a tradeoff between latency and quality. If BufferMSecs is too low, the sound will not play smoothly, especially during long-running primitives such as large BitBlts. If BufferMSecs is too high, there will be a long time lag between when a sound buffer is submitted to be played and when that sound is actually heard. BufferMSecs is typically in the range 50-200.\\\"\\n\\n\\tSamplingRate := 22050.\\n\\tBufferMSecs := 120.\\n\\tStereo := true.\\n\\tUseReverb ifNil: [UseReverb := true].\\n! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'ar 1/24/2002 18:40'!\\nuseLastBuffer\\n\\t^LastBuffer notNil! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuseLastBuffer: aBool\\n\\tBuffer ifNil:[^self].\\n\\taBool \\n\\t\\tifTrue:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]\\n\\t\\tifFalse:[LastBuffer := nil]\\t! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuseShortBuffer\\n\\t\\\"Experimental support for real-time MIDI input. This only works on platforms whose hardware allows very short buffer sizes. It has been tested on a Macintosh Powerbook G3.\\\"\\n\\t\\\"SoundPlayer useShortBuffer\\\"\\n\\n\\tself shutDown.\\n\\tBufferMSecs := 15.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'jm 1/29/98 18:56'!\\nisReverbOn\\n\\n\\t^ ReverbState ~~ nil\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'ar 1/24/2002 18:41'!\\nlastPlayBuffer\\n\\t^LastBuffer! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\noldStylePlayLoop\\n\\t\\\"This version of the play loop is used if the VM does not yet support sound primitives that signal a semaphore when a sound buffer becomes available.\\\"\\n\\n\\t| bytesPerSlice count |\\n\\tbytesPerSlice := Stereo ifTrue: [4] ifFalse: [2].\\n\\t[true] whileTrue: [\\n\\t\\t[(count := self primSoundAvailableBytes // bytesPerSlice) > 100]\\n\\t\\t\\twhileFalse: [(Delay forMilliseconds: 1) wait].\\n\\n\\t\\tcount := count min: Buffer stereoSampleCount.\\n\\t\\tPlayerSemaphore critical: [\\n\\t\\t\\tActiveSounds := ActiveSounds select: [:snd | snd samplesRemaining > 0].\\n\\t\\t\\tActiveSounds do: [:snd |\\n\\t\\t\\t\\tsnd ~~ SoundJustStarted ifTrue: [\\n\\t\\t\\t\\t\\tsnd playSampleCount: count into: Buffer startingAt: 1]].\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: 1 count: count].\\n\\t\\t\\tself primSoundPlaySamples: count from: Buffer startingAt: 1.\\n\\t\\t\\tBuffer primFill: 0.\\n\\t\\t\\tSoundJustStarted := nil]].\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayLoop\\n\\t\\\"The sound player process loop.\\\"\\n\\n\\t| bytesPerSlice count willStop mayStop |\\n\\tmayStop := Preferences soundStopWhenDone.\\n\\tbytesPerSlice := Stereo ifTrue: [4] ifFalse: [2].\\n\\t[true] whileTrue: [\\n\\t\\t[(count := self primSoundAvailableBytes // bytesPerSlice) > 100]\\n\\t\\t\\twhileFalse: [ReadyForBuffer wait].\\n\\n\\t\\tcount := count min: Buffer stereoSampleCount.\\n\\t\\tPlayerSemaphore critical: [\\n\\t\\t\\tActiveSounds := ActiveSounds select: [:snd | snd samplesRemaining > 0].\\n\\t\\t\\tActiveSounds do: [:snd |\\n\\t\\t\\t\\tsnd ~~ SoundJustStarted ifTrue: [\\n\\t\\t\\t\\t\\tsnd playSampleCount: count into: Buffer startingAt: 1]].\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: 1 count: count].\\n\\t\\t\\tself primSoundPlaySamples: count from: Buffer startingAt: 1.\\n\\t\\t\\twillStop := mayStop and:[\\n\\t\\t\\t\\t\\t\\t(ActiveSounds size = 0) and:[\\n\\t\\t\\t\\t\\t\\t\\tself isAllSilence: Buffer size: count]].\\n\\t\\t\\tLastBuffer ifNotNil:[\\n\\t\\t\\t\\tLastBuffer replaceFrom: 1 to: LastBuffer size with: Buffer startingAt: 1.\\n\\t\\t\\t].\\n\\t\\t\\twillStop\\n\\t\\t\\t\\tifTrue:[self shutDown. PlayerProcess := nil]\\n\\t\\t\\t\\tifFalse:[Buffer primFill: 0].\\n\\t\\t\\tSoundJustStarted := nil].\\n\\t\\twillStop ifTrue:[^self].\\n\\t].\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'nk 2/16/2001 13:26'!\\nplayerProcess\\n\\t^PlayerProcess! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'ar 2/4/2001 18:01'!\\nstartPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag\\n\\t\\\"Start the sound player process. Terminate the old process, if any.\\\"\\n\\t\\\"SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false\\\"\\n\\t^self startPlayerProcessBufferSize: bufferSize \\n\\t\\t\\trate: samplesPerSecond \\n\\t\\t\\tstereo: stereoFlag \\n\\t\\t\\tsound: nil! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound\\n\\t\\\"Start the sound player process. Terminate the old process, if any.\\\"\\n\\t\\\"SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false\\\"\\n\\n\\tself stopPlayerProcess.\\n\\taSound\\n\\t\\tifNil:[ActiveSounds := OrderedCollection new]\\n\\t\\tifNotNil:[ActiveSounds := OrderedCollection with: aSound].\\n\\tBuffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.\\n\\tLastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].\\n\\tPlayerSemaphore := Semaphore forMutualExclusion.\\n\\tSamplingRate := samplesPerSecond.\\n\\tStereo := stereoFlag.\\n\\tReadyForBuffer := Semaphore new.\\n\\tSoundSupported := true. \\\"Assume so\\\"\\n\\tUseReadySemaphore := true. \\\"set to false if ready semaphore not supported by VM\\\"\\n\\tself primSoundStartBufferSize: Buffer stereoSampleCount\\n\\t\\trate: samplesPerSecond\\n\\t\\tstereo: Stereo\\n\\t\\tsemaIndex: (Smalltalk registerExternalObject: ReadyForBuffer).\\n\\t\\\"Check if sound start prim was successful\\\"\\n\\tSoundSupported ifFalse:[^self].\\n\\tUseReadySemaphore\\n\\t\\tifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]\\n\\t\\tifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].\\n\\tUseReverb ifTrue: [self startReverb].\\n\\n\\tPlayerProcess priority: Processor userInterruptPriority.\\n\\tPlayerProcess resume.! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartReverb\\n\\t\\\"Start a delay-line style reverb with the given tap delays and gains. Tap delays are given in samples and should be prime integers; the following comment gives an expression that generates primes.\\\"\\n\\t\\\"Integer primesUpTo: 22050\\\"\\n\\n\\tUseReverb := true.\\n\\tReverbState := ReverbSound new\\n\\t\\ttapDelays: #(1601 7919) gains: #(0.12 0.07).\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopPlayerProcess\\n\\t\\\"Stop the sound player process.\\\"\\n\\t\\\"SoundPlayer stopPlayerProcess\\\"\\n\\n\\t(PlayerProcess == nil or:[PlayerProcess == Processor activeProcess]) \\n\\t\\tifFalse:[PlayerProcess terminate].\\n\\tPlayerProcess := nil.\\n\\tself primSoundStop.\\n\\tActiveSounds := OrderedCollection new.\\n\\tBuffer := nil.\\n\\tPlayerSemaphore := Semaphore forMutualExclusion.\\n\\tReadyForBuffer ifNotNil:\\n\\t\\t[Smalltalk unregisterExternalObject: ReadyForBuffer].\\n\\tReadyForBuffer := nil.\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopReverb\\n\\n\\tUseReverb := false.\\n\\tReverbState := nil.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'ar 2/1/2001 15:20'!\\ncanStartPlayer\\n\\t\\\"Some platforms do no support simultaneous record and play. If this is one of those platforms, return false if there is a running SoundRecorder.\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifTrue: [^ true].\\n\\tSoundRecorder anyActive ifTrue:[^false].\\n\\t^ true\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'di 8/5/1998 23:08'!\\nisPlaying: aSound\\n\\t^ ActiveSounds includes: aSound! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 8/23/97 20:38'!\\npauseSound: aSound\\n\\t\\\"Stop playing the given sound. Playing can be resumed from this point later.\\\"\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\tActiveSounds remove: aSound ifAbsent: []].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'ar 2/19/2001 01:28'!\\nplaySound: aSound\\n\\t\\\"Reset and start playing the given sound from its beginning.\\\"\\n\\n\\taSound reset.\\n\\taSound samplesRemaining = 0 ifTrue:[^self].\\n\\tself resumePlaying: aSound.\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 9/8/1998 17:54'!\\nresumePlaying: aSound\\n\\t\\\"Start playing the given sound without resetting it; it will resume playing from where it last stopped.\\\"\\n\\t\\\"Implementation detail: On virtual machines that don't support the quickstart primitive, you may need to edit this method to pass false to resumePlaying:quickStart:.\\\"\\n\\n\\tself resumePlaying: aSound quickStart: true.\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nresumePlaying: aSound quickStart: quickStart\\n\\t\\\"Start playing the given sound without resetting it; it will resume playing from where it last stopped. If quickStart is true, then try to start playing the given sound immediately.\\\"\\n\\n\\t| doQuickStart |\\n\\tPreferences soundsEnabled ifFalse: [^ self].\\n\\tdoQuickStart := quickStart.\\n\\tPreferences soundQuickStart ifFalse: [doQuickStart := false].\\n\\tPlayerProcess == nil ifTrue: [\\n\\t\\tself canStartPlayer ifFalse: [^ self].\\n\\t\\t^self startUpWithSound: aSound].\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\t(ActiveSounds includes: aSound)\\n\\t\\t\\tifTrue: [doQuickStart := false]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tdoQuickStart ifFalse: [ActiveSounds add: aSound]]].\\n\\n\\t\\\"quick-start the given sound, unless the sound player has just started\\\"\\n\\tdoQuickStart ifTrue: [self startPlayingImmediately: aSound].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopPlayingAll\\n\\t\\\"Stop playing all sounds.\\\"\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\tActiveSounds := ActiveSounds species new].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 9/13/97 19:49'!\\nwaitUntilDonePlaying: aSound\\n\\t\\\"Wait until the given sound is no longer playing.\\\"\\n\\n\\t[PlayerSemaphore critical: [ActiveSounds includes: aSound]]\\n\\t\\twhileTrue: [(Delay forMilliseconds: 100) wait].\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nboinkPitch: p dur: d loudness: l waveTable: waveTable pan: pan\\n\\t\\\"Play a decaying note on the given stream using the given wave table. Used for testing only.\\\"\\n\\n\\t| decay tableSize amplitude increment cycles i |\\n\\tdecay := 0.96.\\n\\ttableSize := waveTable size.\\n\\tamplitude := l asInteger min: 1000.\\n\\tincrement := ((p asFloat * tableSize asFloat) / SamplingRate asFloat) asInteger.\\n\\tincrement := (increment max: 1) min: (tableSize // 2).\\n\\tcycles := (d * SamplingRate asFloat) asInteger.\\n\\n\\ti := 1.\\n\\t1 to: cycles do: [:cycle |\\n\\t\\t(cycle \\\\\\\\ 100) = 0\\n\\t\\t\\tifTrue: [amplitude := (decay * amplitude asFloat) asInteger].\\n\\t\\ti := (((i - 1) + increment) \\\\\\\\ tableSize) + 1.\\n\\t\\tself playTestSample: (amplitude * (waveTable at: i)) // 1000 pan: pan].\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nboinkScale\\n\\t\\\"Tests the sound output primitives by playing a scale.\\\"\\n\\t\\\"SoundPlayer boinkScale\\\"\\n\\n\\t| sineTable pan |\\n\\tself shutDown.\\n\\tSamplingRate := 11025.\\n\\tStereo := true.\\n\\tsineTable := self sineTable: 1000.\\n\\tBuffer := SoundBuffer newStereoSampleCount: 1000.\\n\\tBufferIndex := 1.\\n\\tself primSoundStartBufferSize: Buffer stereoSampleCount\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n\\tpan := 0.\\n\\t#(261.626 293.665 329.628 349.229 391.996 440.001 493.884 523.252) do: [:p |\\n\\t\\tself boinkPitch: p dur: 0.3 loudness: 300 waveTable: sineTable pan: pan.\\n\\t\\tpan := pan + 125].\\n\\n\\tself boinkPitch: 261.626 dur: 1.0 loudness: 300 waveTable: sineTable pan: 500.\\n\\tself primSoundStop.\\n\\tself shutDown.\\n\\tSoundPlayer initialize. \\\"reset sampling rate, buffer size, and stereo flag\\\"\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayTestSample: s pan: pan\\n\\t\\\"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.\\\"\\n\\n\\t| sample leftSample |\\n\\tBufferIndex >= Buffer size\\n\\t\\tifTrue: [\\n\\t\\t\\t\\\"current buffer is full; play it\\\"\\n\\t\\t\\t[self primSoundAvailableBytes > 0]\\n\\t\\t\\t\\twhileFalse. \\\"wait for space to be available\\\"\\n\\t\\t\\tself primSoundPlaySamples: Buffer stereoSampleCount from: Buffer startingAt: 1.\\n\\t\\t\\tBuffer primFill: 0.\\n\\t\\t\\tBufferIndex := 1].\\n\\n\\tsample := s.\\n\\tsample > 32767 ifTrue: [ sample := 32767 ]. \\n\\tsample < -32767 ifTrue: [ sample := -32767 ].\\n\\n\\tStereo\\n\\t\\tifTrue: [\\n\\t\\t\\tleftSample := (sample * pan) // 1000.\\n\\t\\t\\tBuffer at: BufferIndex\\t\\tput: sample - leftSample.\\n\\t\\t\\tBuffer at: BufferIndex + 1\\tput: leftSample]\\n\\t\\tifFalse: [\\n\\t\\t\\tBuffer at: BufferIndex + 1 put: sample].\\n\\tBufferIndex := BufferIndex + 2.\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsineTable: size\\n\\t\\\"Compute a sine table of the given size. Used for testing only.\\\"\\n\\n\\t| radiansPerStep table |\\n\\ttable := Array new: size.\\n\\tradiansPerStep := (2.0 * Float pi) / table size asFloat.\\n\\t1 to: table size do: [:i |\\n\\t\\ttable at: i put:\\n\\t\\t\\t(32767.0 * (radiansPerStep * i) sin) asInteger].\\n\\n\\t^ table\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nshutDown\\n\\t\\\"Stop player process, for example before snapshotting.\\\"\\n\\n\\tself stopPlayerProcess.\\n\\tReverbState := nil.\\n! !\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'jm 7/11/97 12:17'!\\nstartUp\\n\\t\\\"Start up the player process.\\\"\\n\\n\\tSoundPlayer initialize.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n! !\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'ar 2/4/2001 17:59'!\\nstartUpWithSound: aSound\\n\\t\\\"Start up the player process.\\\"\\n\\n\\tSoundPlayer initialize.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo\\n\\t\\tsound: aSound.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nisAllSilence: buffer size: count\\n\\t\\\"return true if the buffer is all silence after reverb has ended\\\"\\n\\t| value |\\n\\tvalue := buffer at: 1.\\n\\t2 to: count do:[:i| (buffer at: i) = value ifFalse:[^false]].\\n\\t^true! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundAvailableBytes\\n\\t\\\"Return the number of bytes of available space in the sound output buffer.\\\"\\n\\t\\\"Note: Squeak always uses buffers containing 4-bytes per sample (2 channels at 2 bytes per channel) regardless of the state of the Stereo flag.\\\"\\n\\n\\t<primitive: 'primitiveSoundAvailableSpace' module: 'SoundPlugin'>\\n\\t^ self primitiveFailed\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'JMM 11/6/2000 10:17'!\\nprimSoundGetVolume\\n\\t\\\"Return sound as array of doubles left then right channel, range is 0.0 to 1.0 but may be overdriven\\\"\\n\\t<primitive: 'primitiveSoundGetVolume' module: 'SoundPlugin'>\\n\\t^Array with: 1.0 with: 1.0! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundInsertSamples: count from: aSoundBuffer samplesOfLeadTime: anInteger\\n\\t\\\"Mix the given number of sample frames from the given sound buffer into the queue of samples that has already been submitted to the sound driver. This primitive is used to start a sound playing with minimum latency, even if large sound output buffers are being used to ensure smooth sound output. Returns the number of samples consumed, or zero if the primitive is not implemented or fails.\\\"\\n\\n\\t<primitive: 'primitiveSoundInsertSamples' module: 'SoundPlugin'>\\n\\t^ 0\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundPlaySamples: count from: aSampleBuffer startingAt: index\\n\\t\\\"Copy count bytes into the current sound output buffer from the given sample buffer starting at the given index.\\\"\\n\\n\\t<primitive: 'primitiveSoundPlaySamples' module: 'SoundPlugin'>\\n\\t^ self primitiveFailed\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'JMM 11/6/2000 10:14'!\\nprimSoundSetVolumeLeft: aLeftVolume volumeRight: aRightVolume\\n\\t\\\"Set sound pass in float 0.0-1.0 for left and right channel, with possible 2.0 or higher to overdrive sound channel \\\"\\n\\t<primitive: 'primitiveSoundSetLeftVolume' module: 'SoundPlugin'>\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nprimSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag\\n\\t\\\"Start double-buffered sound output with the given buffer size and sampling rate. This version has been superceded by primitive 171 (primSoundStartBufferSize:rate:stereo:semaIndex:).\\\"\\n\\t\\\"ar 12/5/1998 Turn off the sound if not supported\\\"\\n\\t<primitive: 'primitiveSoundStart' module: 'SoundPlugin'>\\n\\tSoundSupported := false.! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nprimSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag semaIndex: anInteger\\n\\t\\\"Start double-buffered sound output with the given buffer size and sampling rate. If the given semaphore index is > 0, it is taken to be the index of a Semaphore in the external objects array to be signalled when the sound driver is ready to accept another buffer of samples.\\\"\\n\\t\\\"Details: If this primitive fails, this method tries to use the older version instead.\\\"\\n\\n\\t<primitive: 'primitiveSoundStartWithSemaphore' module: 'SoundPlugin'>\\n\\tUseReadySemaphore := false.\\n\\tself primSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag.\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'tpr 2/2/2001 19:46'!\\nprimSoundStop\\n\\t\\\"Stop double-buffered sound output. Must not raise an error because it is used inside error handling and at system shutdown\\\"\\n\\n\\t<primitive: 'primitiveSoundStop' module: 'SoundPlugin'>! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartPlayingImmediately: aSound\\n\\t\\\"Private!! Start playing the given sound as soon as possible by mixing it into the sound output buffers of the underlying sound driver.\\\"\\n\\n\\t| totalSamples buf n leftover src rest |\\n\\t\\\"first, fill a double-size buffer with samples\\\"\\n\\t\\\"Note: The code below assumes that totalSamples contains two\\n\\t buffers worth of samples, and the insertSamples primitive is\\n\\t expected to consume at least one buffer's worth of these\\n\\t samples. The remaining samples are guaranteed to fit into\\n\\t a single buffer.\\\"\\n\\ttotalSamples := Buffer stereoSampleCount * 2. \\\"two buffer's worth\\\"\\n\\tbuf := SoundBuffer newStereoSampleCount: totalSamples.\\n\\taSound playSampleCount: totalSamples into: buf startingAt: 1.\\n\\tReverbState == nil ifFalse: [\\n\\t\\tReverbState applyReverbTo: buf startingAt: 1 count: totalSamples].\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\t\\\"insert as many samples as possible into the sound driver's buffers\\\"\\n\\t\\tn := self primSoundInsertSamples: totalSamples\\n\\t\\t\\tfrom: buf\\n\\t\\t\\tsamplesOfLeadTime: 1024.\\n\\t\\tn > 0 ifTrue:[\\n\\t\\t\\tleftover := totalSamples - n.\\n\\n\\t\\t\\t\\\"copy the remainder of buf into Buffer\\\"\\n\\t\\t\\t\\\"Note: the following loop iterates over 16-bit words, not two-word stereo slices\\\"\\n\\t\\t\\t\\\"assert: 0 < leftover <= Buffer stereoSampleCount\\\"\\n\\t\\t\\tsrc := 2 * n.\\n\\t\\t\\t1 to: 2 * leftover do:\\n\\t\\t\\t\\t[:dst | Buffer at: dst put: (buf at: (src := src + 1))].\\n\\n\\t\\t\\t\\\"generate enough additional samples to finish filling Buffer\\\"\\n\\t\\t\\trest := Buffer stereoSampleCount - leftover.\\n\\t\\t\\taSound playSampleCount: rest into: Buffer startingAt: leftover + 1.\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: leftover + 1 count: rest].\\n\\n\\t\\t\\t\\\"record the fact that this sound has already been played into Buffer so that we don't process it again this time around\\\"\\n\\t\\t\\tSoundJustStarted := aSound.\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"quick start failed; reset the sound so we start over\\\"\\n\\t\\t\\taSound reset.\\n\\t\\t].\\n\\t\\tActiveSounds add: aSound].\\n! !\\nStringReadoutTile subclass: #SoundReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SoundReadoutTile commentStamp: 'sw 11/24/2003 15:25' prior: 0!\\nA tile comprising a readout for a sound-valued instance variable in a Viewer. It sports up/down arrows, and a click on the sound name results in a pop-up menu, offering the user the opportunity to choose a new one.!\\n\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 1/28/2005 00:57'!\\narrowAction: delta\\n\\t\\\"Do what is appropriate when an arrow on the tile is pressed; delta will be +1 or -1\\\"\\n\\n\\t| soundChoices index |\\n\\tsoundChoices _ self soundChoices.\\n\\tindex _ soundChoices indexOf: literal.\\n\\tself literal: (soundChoices atWrap: (index + delta)).\\n\\tself playSoundNamed: literal! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 11/24/2003 14:54'!\\nhandlerForMouseDown: anEvent\\n\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event\\\"\\n\\n\\n\\n\\t^ ((self findA: UpdatingStringMorph) bounds containsPoint: anEvent cursorPoint)\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self]\\n\\n\\t\\tifFalse:\\n\\n\\t\\t\\t[super handlerForMouseDown: anEvent]! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 1/28/2005 00:56'!\\nmouseDown: evt\\n\\t\\\"Handle a mouse down event\\\"\\n\\n\\t| aPoint index isUp soundChoices adjustment |\\n\\tupArrow ifNotNil: [((isUp _ upArrow containsPoint: (aPoint _ evt cursorPoint)) or: [downArrow containsPoint: aPoint])\\n\\t\\tifTrue:\\n\\t\\t\\t[soundChoices _ self soundChoices.\\n\\t\\t\\tindex _ soundChoices indexOf: literal ifAbsent: [1].\\n\\t\\t\\tindex > 0 ifTrue:\\n\\t\\t\\t\\t[adjustment _ isUp ifTrue: [1] ifFalse: [-1].\\n\\t\\t\\t\\tself literal: (soundChoices atWrap: (index + adjustment))].\\n\\t\\t\\tself playSoundNamed: literal.\\n\\t\\t\\t^ self]].\\n\\tself soundNameFromUser ifNotNilDo:\\n\\t\\t[:aSoundName |\\n\\t\\t\\tself literal: aSoundName.\\n\\t\\t\\tself playSoundNamed: literal]! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'yo 2/11/2005 16:12'!\\nsetLiteral: aLiteral\\n\\n\\tsuper setLiteral: aLiteral.\\n\\n\\t(self findA: UpdatingStringMorph) useSymbolFormat; lock! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'yo 2/11/2005 16:08'!\\nsoundNameFromUser\\n\\t\\\"Obtain a sound from the user. Exclude the items designated as being discouraged, except that if the current selection is one of those, show it anyway\\\"\\n\\n\\t| choices |\\n\\tchoices _ self soundChoices.\\n\\t^ (SelectionMenu labels: (choices collect: [:t | t translated]) selections: self soundChoices) startUpWithCaption: 'Sounds' translated! !\\n\\n\\n!SoundReadoutTile methodsFor: 'literal' stamp: 'sw 1/28/2005 00:57'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"Set the literal and width of the tile as indicated\\\"\\n\\n\\t| soundChoices index |\\n\\tsoundChoices _ self soundChoices.\\n\\tindex _ soundChoices indexOf: anObject.\\n\\tself setLiteral: (soundChoices atWrap: index)! !\\n\\n\\n!SoundReadoutTile methodsFor: 'private' stamp: 'yo 2/11/2005 16:13'!\\nupdateLiteralLabel\\n\\n\\t\\\"Update the wording emblazoned on the tile, if needed\\\"\\n\\n\\n\\n\\tsuper updateLiteralLabel.\\n\\n\\t(self findA: UpdatingStringMorph) useSymbolFormat; lock! !\\nObject subclass: #SoundRecorder\\n\\tinstanceVariableNames: 'stereo samplingRate recordLevel recordedBuffers recordedSound recordProcess bufferAvailableSema paused meteringBuffer meterLevel soundPlaying currentBuffer nextIndex codec desiredSampleRate'\\n\\tclassVariableNames: 'CanRecordWhilePlaying RecorderActive'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncodec: aSoundCodec\\n\\n\\tcodec := aSoundCodec! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndesiredSampleRate: newRate\\n\\n\\t\\\"use of this method indicates a strong desire for the specified rate, even if\\n\\tthe OS/hardware are not cooperative\\\"\\n\\n\\tdesiredSampleRate := samplingRate := newRate \\\"Best are 44100 22050 11025\\\"\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jj 10/20/97 15:30'!\\nisActive\\n\\t\\\"Return true if I have a recordProcess running.\\\"\\n\\n\\t^ recordProcess ~~ nil\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 9/2/97 16:16'!\\nisPaused\\n\\t\\\"Return true if recording is paused.\\\"\\n\\n\\t^ paused\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 9/18/97 19:19'!\\nmeterLevel\\n\\t\\\"Return the meter level, an integer in the range [0..100] where zero is silence and 100 represents the maximum signal level possible without clipping.\\\"\\n\\n\\t^ (100 * meterLevel) // 32768\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 7/4/1998 15:03'!\\nrecordLevel\\n\\n\\t^ recordLevel\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrecordLevel: level\\n\\t\\\"Set the desired recording level to the given value in the range 0.0 to 1.0, where 0.0 is the lowest recording level and 1.0 is the maximum. Do nothing if the sound input hardware does not support changing the recording level.\\\"\\n\\t\\\"Details: On the Macintosh, the lowest possible record level attenuates the input signal, but does not silence it entirely.\\\" \\n\\n\\trecordLevel := (level asFloat min: 1.0) max: 0.0.\\n\\trecordProcess ifNotNil: [\\n\\t\\tself primSetRecordLevel: (1000.0 * recordLevel) asInteger].\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 12/15/97 14:28'!\\nsamplingRate\\n\\n\\t^ samplingRate\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplingRate: newRate\\n\\n\\tsamplingRate := newRate \\\"Best are 44100 22050 11025\\\"\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundRecorder new\\\"\\n\\n\\tstereo := false.\\n\\tsamplingRate := 11025.\\n\\trecordLevel := 0.5.\\n\\tself initializeRecordingState.\\n! !\\n\\n!SoundRecorder methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitializeRecordingState\\n\\n\\trecordProcess := nil.\\n\\tbufferAvailableSema := nil.\\n\\tpaused := true.\\n\\tmeteringBuffer := nil.\\n\\tmeterLevel := 0.\\n\\tsoundPlaying := nil.\\n\\tcurrentBuffer := nil.\\n\\tnextIndex := 1.\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimGetActualRecordingSampleRate\\n\\t\\\"Return the actual sample rate being used for recording. This primitive fails unless sound recording is currently in progress.\\\"\\n\\n\\t<primitive: 'primitiveSoundGetRecordingSampleRate' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimRecordSamplesInto: aWordArray startingAt: index\\n\\t\\\"Record a sequence of 16-bit sound samples into the given array starting at the given sample index. Return the number of samples recorded, which may be zero if no samples are currently available.\\\"\\n\\n\\t<primitive: 'primitiveSoundRecordSamples' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSetRecordLevel: anInteger\\n\\t\\\"Set the desired recording level to the given value in the range 0-1000, where 0 is the lowest recording level and 1000 is the maximum. Do nothing if the sound input hardware does not support changing the recording level.\\\"\\n\\n\\t<primitive: 'primitiveSoundSetRecordLevel' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartRecordingDesiredSampleRate: samplesPerSec stereo: stereoFlag semaIndex: anInteger\\n\\t\\\"Start sound recording with the given stereo setting. Use a sampling rate as close to the desired rate as the underlying platform will support. If the given semaphore index is > 0, it is taken to be the index of a Semaphore in the external objects array to be signalled every time a recording buffer is filled.\\\"\\n\\n\\t<primitive: 'primitiveSoundStartRecording' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'tpr 2/15/2001 17:13'!\\nprimStopRecording\\n\\t\\\"Stop sound recording. Does nothing if recording is not currently in progress. Do not fail if plugin is not available\\\"\\n\\n\\t<primitive: 'primitiveSoundStopRecording' module: 'SoundPlugin'>! !\\n\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nclearRecordedSound\\n\\t\\\"Clear the sound recorded thus far. Go into pause mode if currently recording.\\\"\\n\\n\\tpaused := true.\\n\\trecordedSound := SequentialSound new.\\n\\tself allocateBuffer.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'sw 6/10/2003 12:34'!\\nhasRecordedSound\\n\\n\\t\\\"Answer whether the receiver currently has any recorded sound\\\"\\n\\n\\n\\n\\t^ self recordedSound notNil! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npause\\n\\t\\\"Go into pause mode. The record level continues to be updated, but no sound is recorded.\\\"\\n\\n\\tpaused := true.\\n\\t((currentBuffer ~~ nil) and: [nextIndex > 1])\\n\\t\\tifTrue: [self emitPartialBuffer.\\n\\t\\t\\t\\tself allocateBuffer].\\n\\n\\tsoundPlaying ifNotNil: [\\n\\t\\tsoundPlaying pause.\\n\\t\\tsoundPlaying := nil].\\n\\t\\\"Note: there can be problems if canRecordWhilePlaying is true. Recorders which only pause will inhibit other recorders from recording. I chose to make #stopPlaying unconditional in a subclass. The same might be appropriate here at the expense of making recorders resumable\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifFalse: [self stopRecording].\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayback\\n\\t\\\"Playback the sound that has been recorded.\\\"\\n\\n\\tself pause.\\n\\tsoundPlaying := self recordedSound.\\n\\tsoundPlaying play.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nresumeRecording\\n\\t\\\"Continue recording from the point at which it was last paused.\\\"\\n\\n\\tself flag: #bob.\\n\\t\\\"Note: If canRecordWhilePlaying is true, then recordings may never get started (at least by this method). One possibility, used in a subclass, is to make the #startPlaying unconditional. Another would be to use #startPlaying instead of #resumePlaying in appropriate cases\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifFalse: [self startRecording].\\n\\tpaused := false.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartRecording\\n\\t\\\"Turn of the sound input driver and start the recording process. Initially, recording is paused.\\\"\\n\\n\\t| semaIndex |\\n\\trecordLevel ifNil: [recordLevel := 0.5]. \\\"lazy initialization\\\"\\n\\tPreferences canRecordWhilePlaying ifFalse: [SoundPlayer shutDown].\\n\\trecordProcess ifNotNil: [self stopRecording].\\n\\tpaused := true.\\n\\tmeteringBuffer := SoundBuffer newMonoSampleCount: 1024.\\n\\tmeterLevel := 0.\\n\\tself allocateBuffer.\\n\\tbufferAvailableSema := Semaphore new.\\n\\tsemaIndex := Smalltalk registerExternalObject: bufferAvailableSema.\\n\\tself primStartRecordingDesiredSampleRate: samplingRate asInteger\\n\\t\\tstereo: stereo\\n\\t\\tsemaIndex: semaIndex.\\n\\tRecorderActive := true.\\n\\tsamplingRate := self primGetActualRecordingSampleRate.\\n\\tself primSetRecordLevel: (1000.0 * recordLevel) asInteger.\\n\\trecordProcess := [self recordLoop] newProcess.\\n\\trecordProcess priority: Processor userInterruptPriority.\\n\\trecordProcess resume.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopRecording\\n\\t\\\"Stop the recording process and turn of the sound input driver.\\\"\\n\\n\\trecordProcess ifNotNil: [recordProcess terminate].\\n\\trecordProcess := nil.\\n\\tself primStopRecording.\\n\\tRecorderActive := false.\\n\\tSmalltalk unregisterExternalObject: bufferAvailableSema.\\n\\t((currentBuffer ~~ nil) and: [nextIndex > 1])\\n\\t\\tifTrue: [self emitPartialBuffer].\\n\\tself initializeRecordingState.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'sw 3/3/2004 19:49'!\\nverifyExistenceOfRecordedSound\\n\\n\\t\\\"If the receiver has a recorded sound, answer true; if not, put up an informer and answer false\\\"\\n\\n\\n\\n\\t^ self recordedSound\\n\\n\\t\\tifNotNil:\\n\\n\\t\\t\\t[true]\\n\\n\\t\\tifNil:\\n\\n\\t\\t\\t[self inform: 'please record a sound first' translated.\\n\\n\\t\\t\\tfalse]! !\\n\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncondensedSamples\\n\\t\\\"Return a single SoundBuffer that is the contatenation of all my recorded buffers.\\\"\\n\\n\\t| sz newBuf i |\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\trecordedBuffers isEmpty ifTrue: [^ SoundBuffer new: 0].\\n\\trecordedBuffers size = 1 ifTrue: [^ recordedBuffers first copy].\\n\\tsz := recordedBuffers inject: 0 into: [:tot :buff | tot + buff size].\\n\\tnewBuf := SoundBuffer newMonoSampleCount: sz.\\n\\ti := 1.\\n\\trecordedBuffers do: [:b |\\n\\t\\t1 to: b size do: [:j |\\n\\t\\t\\tnewBuf at: i put: (b at: j).\\n\\t\\t\\ti := i + 1]].\\n\\trecordedBuffers := nil.\\n\\t^ newBuf\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncondensedStereoSound\\n\\t\\\"Decompose my buffers into left and right channels and return a mixed sound consisting of the those two channels. This may be take a while, since the data must be copied into new buffers.\\\"\\n\\n\\t| sz leftBuf rightBuf leftI rightI left |\\n\\tsz := recordedBuffers inject: 0 into: [:tot :buff | tot + buff size].\\n\\tleftBuf := SoundBuffer newMonoSampleCount: (sz + 1) // 2.\\n\\trightBuf := SoundBuffer newMonoSampleCount: (sz + 1) // 2.\\n\\tleftI := rightI := 1.\\n\\tleft := true.\\n\\trecordedBuffers do: [:b |\\n\\t\\t1 to: b size do: [:j |\\n\\t\\t\\tleft\\n\\t\\t\\t\\tifTrue: [leftBuf at: leftI put: (b at: j). leftI := leftI + 1. left := false]\\n\\f\\t\\t\\t\\tifFalse: [rightBuf at: rightI put: (b at: j). rightI := rightI + 1. left := true]]].\\n\\t^ MixedSound new\\n\\t\\tadd: (SampledSound new setSamples: leftBuf samplingRate: samplingRate) pan: 0.0;\\n\\t\\tadd: (SampledSound new setSamples: rightBuf samplingRate: samplingRate) pan: 1.0\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'di 2/17/1999 11:07'!\\nrecordedSound\\n\\t\\\"Return the sound that was recorded.\\\"\\n\\n\\t^ recordedSound\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'di 2/17/1999 21:24'!\\nsoundSegments\\n\\n\\t^ self segmentsAbove: 1000 normalizedVolume: 80.0\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopyFrom: startPlace to: endPlace normalize: nFactor dcOffset: dcOffset\\n\\t\\\"Return a new SoundBuffer containing the samples in the given range.\\\"\\n\\n\\t| startBufIndex startSampleIndex endBufIndex endSampleIndex\\n\\t count resultBuf j buf firstInBuf n |\\n\\tstartBufIndex := startPlace at: 1.\\n\\tstartSampleIndex := startPlace at: 2.\\n\\tendBufIndex := endPlace at: 1.\\n\\tendSampleIndex := endPlace at: 2.\\n\\n\\tstartBufIndex = endBufIndex\\n\\t\\tifTrue: [count := endSampleIndex + 1 - startSampleIndex]\\n\\t\\tifFalse: [\\n\\t\\t\\tcount := ((recordedBuffers at: startBufIndex) size + 1 - startSampleIndex). \\\"first buffer\\\"\\n\\t\\t\\tcount := count + endSampleIndex. \\\"last buffer\\\"\\n\\t\\t\\tstartBufIndex + 1 to: endBufIndex - 1 do:\\n\\t\\t\\t\\t[:i | count := count + (recordedBuffers at: i) size]]. \\\"middle buffers\\\"\\n\\tresultBuf := SoundBuffer newMonoSampleCount: count.\\n\\n\\tj := 1. \\\"next destination index in resultBuf\\\"\\n\\tstartBufIndex to: endBufIndex do: [:i |\\n\\t\\tbuf := recordedBuffers at: i.\\n\\t\\tfirstInBuf := 1.\\n\\t \\tn := buf size.\\n\\t\\ti = startBufIndex ifTrue: [\\n\\t\\t\\tn := (recordedBuffers at: startBufIndex) size + 1 - startSampleIndex.\\n\\t\\t\\tfirstInBuf := startSampleIndex].\\n\\t\\ti = endBufIndex ifTrue: [\\n\\t\\t\\ti = startBufIndex\\n\\t\\t\\t\\tifTrue: [n := endSampleIndex + 1 - startSampleIndex]\\n\\t\\t\\t\\tifFalse: [n := endSampleIndex]].\\n\\t\\tself copyTo: resultBuf from: j to: (j + n - 1)\\n\\t\\t\\tfrom: buf startingAt: firstInBuf\\n\\t\\t\\tnormalize: nFactor dcOffset: dcOffset.\\n\\t\\tj := j + n].\\n\\t^ resultBuf\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopyTo: resultBuf from: startIndex to: endIndex from: buf startingAt: firstInBuf normalize: nFactor dcOffset: dcOffset\\n\\t\\\"Copy samples from buf to resultBuf removing the DC offset and normalizing their volume in the process.\\\"\\n\\n\\t| indexOffset |\\n\\tindexOffset := firstInBuf - startIndex.\\n\\tstartIndex to: endIndex do: [:i |\\n\\t\\tresultBuf at: i put: (((buf at: (i + indexOffset)) - dcOffset) * nFactor) // 1000].\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'di 2/16/1999 22:11'!\\nendPlace\\n\\n\\t^ Array with: recordedBuffers size with: recordedBuffers last size! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfirstSampleOverThreshold: threshold dcOffset: dcOffset startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will return the first place at which a sample exceeds the given threshold.\\\"\\n\\n\\t| buf s iStart jStart nThreshold |\\n\\tnThreshold := threshold negated.\\n\\tiStart := startPlace first.\\n\\tjStart := startPlace second.\\n\\tiStart to: recordedBuffers size do:\\n\\t\\t[:i | buf := recordedBuffers at: i.\\n\\t\\tjStart to: buf size do:\\n\\t\\t\\t[:j | s := (buf at: j) - dcOffset.\\n\\t\\t\\t(s < nThreshold or: [s > threshold]) ifTrue:\\n\\t\\t\\t\\t[\\\"found a sample over threshold\\\"\\n\\t\\t\\t\\t^ Array with: i with: j]].\\n\\t\\tjStart := 1].\\n\\t^ self endPlace! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnormalizeFactorFor: percentOfMaxVolume min: min max: max dcOffset: dcOffset\\n\\t\\\"Return a normalization factor for the range of sample values and DC offset. A normalization factor is a fixed-point number that will be divided by 1000 after multiplication with each sample value.\\\"\\n\\n\\t| peak factor |\\n\\tpeak := (max - dcOffset) max: (min - dcOffset) negated.\\n\\tpeak = 0 ifTrue: [^ 1000].\\n\\tfactor := (32767.0 * percentOfMaxVolume) / (100.0 * peak).\\n\\t^ (factor * 1000.0) asInteger\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplace: startPlace plus: nSamples\\n\\t\\\"Return the place that is nSamples (may be negative) beyond thisPlace.\\\"\\n\\n\\t| i j remaining buf |\\n\\ti := startPlace first.\\n\\tj := startPlace second.\\n\\tnSamples >= 0\\n\\tifTrue: [remaining := nSamples.\\n\\t\\t\\t[buf := recordedBuffers at: i.\\n\\t\\t\\t(j + remaining) <= buf size ifTrue: [^ Array with: i with: j + remaining].\\n\\t\\t\\ti < recordedBuffers size]\\n\\t\\t\\t\\twhileTrue: [remaining := remaining - (buf size - j + 1).\\n\\t\\t\\t\\t\\t\\t\\ti := i+1. j := 1].\\n\\t\\t\\t^ self endPlace]\\n\\tifFalse: [remaining := nSamples negated.\\n\\t\\t\\t[buf := recordedBuffers at: i.\\n\\t\\t\\t(j - remaining) >= 1 ifTrue: [^ Array with: i with: j - remaining].\\n\\t\\t\\ti > 1]\\n\\t\\t\\t\\twhileTrue: [remaining := remaining - j.\\n\\t\\t\\t\\t\\t\\t\\ti := i-1. j := (recordedBuffers at: i) size].\\n\\t\\t\\t^ #(1 1)]! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscanForEndThreshold: threshold dcOffset: dcOffset minLull: lull startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will find the last sound that exceeds threshold, such that if you look lull samples later you will not find another sound over threshold within the following block of lull samples.\\n\\tReturn the place that is lull samples beyond to that last sound.\\n\\tIf no end of sound is found, return endPlace.\\\"\\n\\n\\t| buf s iStart jStart nThreshold n |\\n\\tnThreshold := threshold negated.\\n\\tiStart := startPlace first.\\n\\tjStart := startPlace second.\\n\\tn := 0.\\n\\tiStart to: recordedBuffers size do:\\n\\t\\t[:i | buf := recordedBuffers at: i.\\n\\t\\tjStart to: buf size do:\\n\\t\\t\\t[:j | s := (buf at: j) - dcOffset.\\n\\t\\t\\t(s < nThreshold or: [s > threshold])\\n\\t\\t\\t\\tifTrue: [\\\"found a sample over threshold\\\"\\n\\t\\t\\t\\t\\t\\tn := 0]\\n\\t\\t\\t\\tifFalse: [\\\"still not over threshold\\\"\\n\\t\\t\\t\\t\\t\\tn := n + 1.\\n\\t\\t\\t\\t\\t\\tn >= lull ifTrue: [^ Array with: i with: j]]].\\n\\t\\tjStart := 1].\\n\\t^ self endPlace! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscanForStartThreshold: threshold dcOffset: dcOffset minDur: duration startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will find the first sound that exceeds threshold, such that if you look duration samples later you will find another sound over threshold within the following block of duration samples.\\n\\tReturn the place that is duration samples prior to that first sound.\\n\\tIf no sound is found, return endPlace.\\\"\\n\\n\\t| soundPlace lookPlace nextSoundPlace thirdPlace |\\n\\tsoundPlace := self firstSampleOverThreshold: threshold dcOffset: dcOffset\\n\\t\\t\\t\\t\\tstartingAt: startPlace.\\n\\t[soundPlace = self endPlace ifTrue: [^ soundPlace].\\n\\t\\\"Found a sound -- look duration later\\\"\\n\\tlookPlace := self place: soundPlace plus: duration.\\n\\tnextSoundPlace := self firstSampleOverThreshold: threshold dcOffset: dcOffset\\n\\t\\t\\t\\t\\tstartingAt: lookPlace.\\n\\tthirdPlace := self place: lookPlace plus: duration.\\n\\tnextSoundPlace first < thirdPlace first\\n\\t\\tor: [nextSoundPlace first = thirdPlace first\\n\\t\\t\\tand: [nextSoundPlace second < thirdPlace second]]]\\n\\t\\twhileFalse: [soundPlace := nextSoundPlace].\\n\\n\\t\\\"Yes, there is sound in the next interval as well\\\"\\n\\t^ self place: soundPlace plus: 0-duration\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsegmentsAbove: threshold normalizedVolume: percentOfMaxVolume\\n\\t\\\"Break the current recording up into a sequence of sound segments separated by silences.\\\"\\n\\n\\t| max min sum totalSamples bufSize s dcOffset firstPlace endPlace resultBuf nFactor lastPlace segments gapSize minDur minLull soundSize restSize |\\n\\tstereo ifTrue: [self error: 'stereo trimming is not yet supported'].\\n\\tpaused ifFalse: [self error: 'must stop recording before trimming'].\\n\\t(recordedSound == nil or: [recordedSound sounds isEmpty]) ifTrue:[^ self].\\n\\t\\\"Reconstruct buffers so old trimming code will work\\\"\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\tsoundSize := restSize := 0.\\n\\n\\tmax := min := sum := totalSamples := 0.\\n\\trecordedBuffers do: [:buf |\\n\\t\\tbufSize := buf size.\\n\\t\\ttotalSamples := totalSamples + buf size.\\n\\t\\t1 to: bufSize do: [:i |\\n\\t\\t\\ts := buf at: i.\\n\\t\\t\\ts > max ifTrue: [max := s].\\n\\t\\t\\ts < min ifTrue: [min := s].\\n\\t\\t\\tsum := sum + s]].\\n\\tdcOffset := sum // totalSamples.\\n\\n\\tminDur := (samplingRate/20.0) asInteger. \\\" 1/20 second \\\"\\n\\tminLull := (samplingRate/4.0) asInteger. \\\" 1/2 second \\\"\\n\\tsegments := SequentialSound new.\\n\\tendPlace := self endPlace.\\n\\tlastPlace := #(1 1).\\n\\t[firstPlace := self scanForStartThreshold: threshold\\n\\t\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\t\\tminDur: minDur\\n\\t\\t\\t\\t\\t\\tstartingAt: lastPlace.\\n\\tfirstPlace = endPlace]\\n\\t\\twhileFalse:\\n\\t\\t[firstPlace = lastPlace ifFalse:\\n\\t\\t\\t[\\\"Add a silence equal to the gap size\\\"\\n\\t\\t\\t\\\"Wasteful but simple way to get gap size...\\\"\\n\\t\\t\\tgapSize := (self copyFrom: lastPlace to: firstPlace\\n\\t\\t\\t\\t\\t\\tnormalize: 1000 dcOffset: dcOffset) size - 2.\\n\\t\\t\\t\\\"... -2 makes up for overlap of one sample on either end\\\"\\n\\t\\t\\tsegments add: (RestSound dur: gapSize asFloat / samplingRate).\\n\\t\\t\\trestSize := restSize + gapSize.\\n\\\"Transcript cr; print: firstPlace; space; print: lastPlace; space; print: gapSize; space; show: 'gap'.\\\"\\n\\t\\t\\t].\\n\\t\\tlastPlace := self scanForEndThreshold: threshold\\n\\t\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\t\\tminLull: minLull + minDur\\n\\t\\t\\t\\t\\t\\tstartingAt: firstPlace.\\n\\t\\t\\\"Allow room for lead time of next sound\\\"\\n\\t\\tlastPlace := self place: lastPlace plus: minDur negated.\\n\\t\\tnFactor := self normalizeFactorFor: percentOfMaxVolume\\n\\t\\t\\t\\t\\t\\tmin: min max: max dcOffset: dcOffset.\\n\\t\\tresultBuf := self copyFrom: firstPlace to: lastPlace\\n\\t\\t\\t\\t\\t\\tnormalize: nFactor dcOffset: dcOffset.\\n\\t\\tsoundSize := soundSize + resultBuf size.\\n\\\"Transcript cr; print: firstPlace; space; print: lastPlace; space; print: resultBuf size; space; show: 'sound'.\\\"\\n\\t\\tsegments add: (codec == nil\\n\\t\\t\\tifTrue: [SampledSound new setSamples: resultBuf samplingRate: samplingRate]\\n\\t\\t\\tifFalse: [codec compressSound: (SampledSound new setSamples: resultBuf samplingRate: samplingRate)])].\\n\\n\\t\\\"Final gap for consistency\\\"\\n\\tgapSize := (self copyFrom: lastPlace to: self endPlace\\n\\t\\t\\t\\tnormalize: 1000 dcOffset: dcOffset) size - 1.\\n\\tsegments add: (RestSound dur: gapSize asFloat / samplingRate).\\n\\trestSize := restSize + gapSize.\\n\\tself inform: ((soundSize+restSize/samplingRate) roundTo: 0.1) printString , ' secs reduced to ' , ((soundSize/samplingRate) roundTo: 0.1) printString.\\n\\trecordedBuffers := nil.\\n\\t^ segments! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsuppressSilence\\n\\n\\trecordedSound := self soundSegments! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntrim: threshold normalizedVolume: percentOfMaxVolume\\n\\t\\\"Remove the leading and trailing parts of this recording that are below the given threshold. Remove any DC offset and scale the recording so that its peaks are the given percent of the maximum volume.\\\"\\n\\n\\t| max min sum totalSamples bufSize s dcOffset startPlace endPlace resultBuf nFactor |\\n\\tstereo ifTrue: [self error: 'stereo trimming is not yet supported'].\\n\\tpaused ifFalse: [self error: 'must stop recording before trimming'].\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\trecordedBuffers isEmpty ifTrue: [^ self].\\n\\n\\tmax := min := sum := totalSamples := 0.\\n\\trecordedBuffers do: [:buf |\\n\\t\\tbufSize := buf size.\\n\\t\\ttotalSamples := totalSamples + buf size.\\n\\t\\t1 to: bufSize do: [:i |\\n\\t\\t\\ts := buf at: i.\\n\\t\\t\\ts > max ifTrue: [max := s].\\n\\t\\t\\ts < min ifTrue: [min := s].\\n\\t\\t\\tsum := sum + s]].\\n\\tdcOffset := sum // totalSamples.\\n\\n\\t\\\"a place is an array of <buffer index><index of sample in buffer>\\\"\\n\\tstartPlace := self scanForStartThreshold: threshold\\n\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\tminDur: (samplingRate/60.0) asInteger \\\"at least 1/60th of a second\\\"\\n\\t\\t\\t\\t\\tstartingAt: #(1 1).\\n\\tstartPlace = self endPlace ifTrue:\\n\\t\\t[\\\"no samples above threshold\\\"\\n\\t\\trecordedBuffers := nil. ^ self].\\n\\n\\tendPlace := self scanForEndThreshold: threshold\\n\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\tminLull: (samplingRate/5) asInteger\\n\\t\\t\\t\\t\\tstartingAt: startPlace.\\n\\tnFactor := self normalizeFactorFor: percentOfMaxVolume min: min max: max dcOffset: dcOffset.\\n\\tresultBuf := self copyFrom: startPlace to: endPlace normalize: nFactor dcOffset: dcOffset.\\n\\trecordedSound := SampledSound new setSamples: resultBuf samplingRate: samplingRate.\\n\\trecordedBuffers := nil\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nallocateBuffer\\n\\t\\\"Allocate a new buffer and reset nextIndex.\\\"\\n\\n\\t| bufferTime |\\n\\tbufferTime := stereo \\\"Buffer time = 1/2 second\\\"\\n\\t\\tifTrue: [self samplingRate asInteger]\\n\\t\\tifFalse: [self samplingRate asInteger // 2].\\n\\tcurrentBuffer := SoundBuffer newMonoSampleCount:\\n\\t\\t\\\"Multiple of samplesPerFrame that is approx. bufferTime long\\\"\\n\\t\\t(bufferTime truncateTo: self samplesPerFrame).\\n\\tnextIndex := 1.\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nemitBuffer: buffer\\n\\n\\t| sound ratio resultBuf |\\n\\n\\t\\\"since some sound recording devices cannot (or will not) record below a certain sample rate,\\n\\ttrim the samples down if the user really wanted fewer samples\\\"\\n\\n\\t(desiredSampleRate isNil or: [(ratio := samplingRate // desiredSampleRate) <= 1]) ifTrue: [\\n\\t\\tsound := SampledSound new setSamples: buffer samplingRate: samplingRate.\\n\\t] ifFalse: [\\n\\t\\tresultBuf := SoundBuffer \\n\\t\\t\\taverageEvery: ratio \\n\\t\\t\\tfrom: buffer \\n\\t\\t\\tupTo: buffer monoSampleCount.\\n\\t\\tsound := SampledSound new setSamples: resultBuf samplingRate: samplingRate / ratio.\\n\\t].\\n\\n\\trecordedSound add: (codec ifNil: [sound] ifNotNil: [codec compressSound: sound])! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nemitPartialBuffer\\n\\t| s |\\n\\ts := self samplesPerFrame.\\n\\tself emitBuffer: (currentBuffer copyFrom: 1 to: ((nextIndex-1) +( s-1) truncateTo: s))! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmeterFrom: start count: count in: buffer\\n\\t\\\"Update the meter level with the maximum signal level in the given range of the given buffer.\\\"\\n\\n\\t| last max sample |\\n\\tcount = 0 ifTrue: [^ self]. \\\"no new samples\\\"\\n\\tlast := start + count - 1.\\n\\tmax := 0.\\n\\tstart to: last do: [:i |\\n\\t\\tsample := buffer at: i.\\n\\t\\tsample < 0 ifTrue: [sample := sample negated].\\n\\t\\tsample > max ifTrue: [max := sample]].\\n\\tmeterLevel := max.\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'dgd 4/4/2006 16:15'!\\nrecordLoop\\n\\t\\\"Record process loop that records samples.\\\"\\n\\n\\t| n sampleCount |\\n\\n\\tn := 0.\\n\\t[true] whileTrue: [\\n\\t\\tn = 0 ifTrue: [bufferAvailableSema wait].\\n\\t\\tpaused\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tn := self primRecordSamplesInto: meteringBuffer startingAt: 1.\\n\\t\\t\\t\\tself meterFrom: 1 count: n in: meteringBuffer]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tn := self primRecordSamplesInto: currentBuffer startingAt: nextIndex.\\n\\t\\t\\t\\tself meterFrom: nextIndex count: n in: currentBuffer.\\n\\t\\t\\t\\tnextIndex := nextIndex + n.\\n\\t\\t\\t\\tstereo\\n\\t\\t\\t\\t\\tifTrue: [sampleCount := currentBuffer stereoSampleCount]\\n\\t\\t\\t\\t\\tifFalse: [sampleCount := currentBuffer monoSampleCount].\\n\\t\\t\\t\\tnextIndex > sampleCount\\n\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\tself emitBuffer: currentBuffer.\\n\\t\\t\\t\\t\\t\\tself allocateBuffer]].\\n\\n\\t\\t\\\"workaround for OSS emulation on top on ALSA (on Linux environments)\\\"\\n\\t\\t(Delay forMilliseconds: 20) wait.\\n\\t].\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'di 2/17/1999 10:39'!\\nsamplesPerFrame\\n\\t\\\"Can be overridden to quantize buffer size for, eg, fixed-frame codecs\\\"\\n\\n\\tcodec == nil\\n\\t\\tifTrue: [^ 1]\\n\\t\\tifFalse: [^ codec samplesPerFrame]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundRecorder class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundRecorder class methodsFor: 'accessing' stamp: 'ar 2/1/2001 15:20'!\\nanyActive\\n\\t\\\"Return true if any sound recorder is actively recording\\\"\\n\\t^RecorderActive == true! !\\n\\n!SoundRecorder class methodsFor: 'accessing' stamp: 'RAA 8/7/2000 19:23'!\\ncanRecordWhilePlaying\\n\\t\\\"Return true if this platform supports simultaneous sound recording and playback.\\\"\\n\\n\\t^Preferences canRecordWhilePlaying.\\t\\t\\\"now in preferences\\\"\\n! !\\n\\n\\n!SoundRecorder class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundRecorder initialize\\\"\\n\\t\\\"Details: Some computers cannot record and playback sound at the same time. If CanRecordWhilePlaying is false, then the SoundRecorder alternates between recording and playing. If it is true, sounds can be playing during recording.\\\"\\n\\n\\tCanRecordWhilePlaying := #ignoredNowInPreferences.\\n! !\\nRectangleMorph subclass: #SoundSequencerMorph\\n\\tinstanceVariableNames: 'controlPanel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'tk 2/19/2001 18:14'!\\nmakeControlPanel\\n\\t| bb cc |\\n\\tcc _ Color black.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel _ AlignmentMorph newRow.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel color: bb color; borderWidth: 0; layoutInset: 0.\\n\\tcontrolPanel hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'reset';\\tactionSelector: #reset).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'stop';\\t\\tactionSelector: #stop).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'play';\\tactionSelector: #play).\\n! !\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nplay\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m play]]! !\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nreset\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m reset]]! !\\n\\n\\n!SoundSequencerMorph methodsFor: 'initialization' stamp: 'jm 11/14/97 11:21'!\\ninitialize\\n\\tsuper initialize.\\n\\tself extent: 550@350.\\n\\tself makeControlPanel.\\n\\tself addMorph: controlPanel.\\n\\tself addMorph: ((SoundLoopMorph newBounds: (10@40 extent: 128@128)) extent: 128@128).\\n\\tself addMorph: ((SoundLoopMorph newBounds: (10@200 extent: 512@128)) extent: 512@128).! !\\n\\n\\n!SoundSequencerMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:21'!\\nstop\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m stop]].\\n\\tSoundPlayer shutDown! !\\nAppRegistry subclass: #SoundService\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\n!SoundService commentStamp: 'gk 2/24/2004 23:14' prior: 0!\\nThis is the AppRegistry class for the sound system.\\n\\nA sound system offers a small protocol for playing sounds and making beeps and works like a facade towards the rest of Squeak. A sound system is registered in this registry and can be accessed by \\\"SoundService default\\\". This way we decouple the sound system from the rest of Squeak and make it pluggable. It also is a perfect spot to check for the Preference class>>soundsEnabled.!\\n\\nTileMorph subclass: #SoundTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SoundTile commentStamp: 'sw 1/28/2005 01:42' prior: 0!\\nA scripting tile representing a 'sound' constant. Sounds are represented by their names, which are strings; the actual sounds live in SampleSound's SoundLibrary.!\\n\\n\\n!SoundTile methodsFor: 'access' stamp: 'gk 2/23/2004 21:08'!\\nsound\\n\\n\\t^ SoundService default soundNamed: literal\\n! !\\n\\n\\n!SoundTile methodsFor: 'accessing' stamp: 'sw 9/27/2001 17:28'!\\nresultType\\n\\t\\\"Answer the result type of the receiver\\\"\\n\\n\\t^ #Sound! !\\n\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'sw 1/28/2005 01:49'!\\noptions\\n\\t\\\"Answer the options of the tile for an arrow\\\"\\n\\n\\t| soundChoices |\\n\\tsoundChoices _ self soundChoices.\\n\\t^ {soundChoices. soundChoices}! !\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'tak 12/5/2004 02:09'!\\nvalue: anObject \\n\\tsuper value: anObject.\\n\\tself playSoundNamed: anObject! !\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'sw 11/3/97 02:11'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t^ false! !\\n\\n\\n!SoundTile methodsFor: 'initialization' stamp: 'yo 7/22/2005 15:51'!\\ninitialize\\n\\t\\\"Initialize the state of the receiver. Pick the croak sound\\n\\tif available, otherwise any sound.\\\"\\n\\t\\n\\t| soundChoices startingSoundName |\\n\\tsuper initialize.\\n\\tsoundChoices _ self soundChoices.\\n\\tstartingSoundName _ (soundChoices includes: 'croak')\\n\\t\\t\\t\\t\\t\\t\\tifTrue: ['croak']\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [[soundChoices anyOne] ifError: ['silence']].\\n\\tself addArrows; setLiteral: startingSoundName.\\n\\tself labelMorph useSymbolFormat! !\\n\\n!SoundTile methodsFor: 'initialization' stamp: 'yo 4/6/2005 16:34'!\\nsetLiteral: anObject\\n\\n\\tsuper setLiteral: anObject.\\n\\tself labelMorph useSymbolFormat\\n! !\\n\\n\\n!SoundTile methodsFor: 'mouse handling' stamp: 'sw 11/24/2003 14:44'!\\nhandlerForMouseDown: anEvent\\n\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event\\\"\\n\\n\\n\\n\\t^ ((self findA: UpdatingStringMorph) bounds containsPoint: anEvent cursorPoint)\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self]\\n\\n\\t\\tifFalse:\\n\\n\\t\\t\\t[super handlerForMouseDown: anEvent]! !\\nDataType subclass: #SoundType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n\\n!SoundType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ 'croak'! !\\n\\n\\n!SoundType methodsFor: 'initialization' stamp: 'sw 9/27/2001 17:24'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\tsuper initialize.\\n\\tself vocabularyName: #Sound! !\\n\\n\\n!SoundType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(1.0 0.06 0.84)\\t! !\\n\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:30'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t^ SoundTile new typeColor: self typeColor! !\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:37'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ SoundReadoutTile new typeColor: Color lightGray lighter! !\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nsetFormatForDisplayer: aDisplayer\\n\\t\\\"Set up the displayer to have the right format characteristics\\\"\\n\\n\\taDisplayer useStringFormat\\n\\t! !\\nSequenceableCollection subclass: #SourceFileArray\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-System'!\\n!SourceFileArray commentStamp: '<historical>' prior: 0!\\nThis class is an abstract superclass for source code access mechanisms. It defines the messages that need to be understood by those subclasses that store and retrieve source chunks on files, over the network or in databases.\\nThe first concrete subclass, StandardSourceFileArray, supports access to the traditional sources and changes files. Other subclasses might implement multiple source files for different applications, or access to a network source server.!\\n]style[(254 23 184)f1,f1LStandardSourceFileArray Comment;,f1!\\n\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:42'!\\nat: index\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'!\\nat: index put: aFileStream\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ncollect: aBlock\\n\\t| copy |\\n\\tcopy := self species new: self size.\\n\\t1 to: self size do:[:i| copy at: i put: (aBlock value: (self at: i))].\\n\\t^copy! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'!\\nsize\\n\\tself subclassResponsibility! !\\n\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'!\\nfileIndexFromSourcePointer: anInteger\\n\\t\\\"Return the index of a source file corresponding to the given source pointer.\\\"\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'!\\nfilePositionFromSourcePointer: anInteger\\n\\t\\\"Return the position within a source file for the given source pointer.\\\"\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:01'!\\nsourcePointerFromFileIndex: index andPosition: position\\n\\t\\\"Return a sourcePointer encoding the given file index and position\\\"\\n\\tself subclassResponsibility! !\\nObject subclass: #SpaceTally\\n\\tinstanceVariableNames: 'results'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!SpaceTally commentStamp: 'sd 6/20/2003 22:31' prior: 0!\\nI'm responsible to help getting information about system space usage. The information I compute is represented by a spaceTallyItem\\n\\ntry something like: \\n\\n((SpaceTally new spaceTally: (Array with: TextMorph with: Point)) \\n\\tasSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) \\n\\nSpaceTally new systemWideSpaceTally\\n\\n\\nThis class has been created from a part of SystemDictionary. It still deserves a nice\\nclean, such as using object instead of array having 4 slots.\\n\\nsd-20 June 2003!\\n\\n\\n!SpaceTally methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:31'!\\nresults\\n\\n\\t^ results! !\\n\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'efc 7/6/2004 00:30'!\\ncomputeSpaceUsage\\n\\n\\t| entry c instanceCount |\\n\\t1 to: results size do: [:i |\\n\\t\\tentry := results at: i.\\n\\t\\tc := self class environment at: entry analyzedClassName.\\n\\t\\tinstanceCount _ c instanceCount.\\n\\t\\tentry codeSize: c spaceUsed.\\n\\t\\tentry instanceCount: instanceCount.\\n\\t\\tentry spaceForInstances: (self spaceForInstancesOf: c withInstanceCount: instanceCount).\\n\\t\\tSmalltalk garbageCollectMost].\\n\\t\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'sd 6/20/2003 22:54'!\\npreAllocateResultsFor: classes\\n\\n\\tresults := OrderedCollection new: classes size.\\n\\tclasses do: [:cl | results add: (SpaceTallyItem analyzedClassName: cl name)].\\n\\tresults _ results asArray.\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'sd 6/20/2003 22:24'!\\nspaceTally: classes\\n\\t\\\"Answer a collection of SpaceTallyItems representing the memory space (in bytes) consumed \\tby the code and instances of each class in the system. Note that code sizes do not currently \\treport memory consumed by class variables. \\\"\\n\\n\\t\\\"((SpaceTally new spaceTally: (Array with: TextMorph with: Point)) asSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) asArray\\\"\\n\\n\\tself preAllocateResultsFor: classes.\\n\\tSmalltalk garbageCollect.\\n\\tself computeSpaceUsage.\\n\\t^ results\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'efc 7/6/2004 00:25'!\\nsystemWideSpaceTally\\n\\t\\\"Answer a collection of SpaceTallyItems representing the memory space (in bytes) consumed \\tby the code and instances of each class in the system. Note that code sizes do not currently \\treport memory consumed by class variables. \\\"\\n\\n\\t\\\"(SpaceTally new systemWideSpaceTally asSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) asArray\\\"\\n\\n\\t^self spaceTally: Smalltalk allClasses.\\n\\n! !\\n\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 22:39'!\\ncompareTallyIn: beforeFileName to: afterFileName\\n\\t\\\"SpaceTally new compareTallyIn: 'tally' to: 'tally2'\\\"\\n\\n\\t| answer s beforeDict a afterDict allKeys before after diff |\\n\\tbeforeDict _ Dictionary new.\\n\\ts _ FileDirectory default fileNamed: beforeFileName.\\n\\t[s atEnd] whileFalse: [\\n\\t\\ta _ Array readFrom: s nextLine.\\n\\t\\tbeforeDict at: a first put: a allButFirst.\\n\\t].\\n\\ts close.\\n\\tafterDict _ Dictionary new.\\n\\ts _ FileDirectory default fileNamed: afterFileName.\\n\\t[s atEnd] whileFalse: [\\n\\t\\ta _ Array readFrom: s nextLine.\\n\\t\\tafterDict at: a first put: a allButFirst.\\n\\t].\\n\\ts close.\\n\\tanswer _ WriteStream on: String new.\\n\\tallKeys _ (Set new addAll: beforeDict keys; addAll: afterDict keys; yourself) asSortedCollection.\\n\\tallKeys do: [ :each |\\n\\t\\tbefore _ beforeDict at: each ifAbsent: [#(0 0 0)].\\n\\t\\tafter _ afterDict at: each ifAbsent: [#(0 0 0)].\\n\\t\\tdiff _ before with: after collect: [ :vBefore :vAfter | vAfter - vBefore].\\n\\t\\tdiff = #(0 0 0) ifFalse: [\\n\\t\\t\\tanswer nextPutAll: each,' ',diff printString; cr.\\n\\t\\t].\\n\\t].\\n\\tStringHolder new contents: answer contents; openLabel: 'space diffs'.\\n\\t\\n\\n\\n! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:04'!\\nprintSpaceAnalysis\\t\\n\\t\\\"SpaceTally new printSpaceAnalysis\\\"\\n\\n\\t^ self printSpaceAnalysis: 0 on: 'STspace.text'! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:03'!\\nprintSpaceAnalysis: threshold on: fileName\\n\\t\\\"SpaceTally new printSpaceAnalysis: 1000 on: 'STspace.text1'\\\"\\n\\n\\t\\\"sd-This method should be rewrote to be more coherent within the rest of the class \\n\\tie using preAllocate and spaceForInstanceOf:\\\"\\n\\n\\t\\\"If threshold > 0, then only those classes with more than that number\\n\\tof instances will be shown, and they will be sorted by total instance space.\\n\\tIf threshold = 0, then all classes will appear, sorted by name.\\\"\\n\\n\\t| f codeSpace instCount instSpace totalCodeSpace totalInstCount totalInstSpace eltSize n totalPercent percent |\\n\\tSmalltalk garbageCollect.\\n\\ttotalCodeSpace _ totalInstCount _ totalInstSpace _ n _ 0.\\n\\tresults _ OrderedCollection new: Smalltalk classNames size.\\n'Taking statistics...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: Smalltalk classNames size\\n\\tduring: [:bar |\\n\\tSmalltalk allClassesDo:\\n\\t\\t[:cl | codeSpace _ cl spaceUsed.\\n\\t\\tbar value: (n _ n+1).\\n\\t\\tSmalltalk garbageCollectMost.\\n\\t\\tinstCount _ cl instanceCount.\\n\\t\\tinstSpace _ (cl indexIfCompact > 0 ifTrue: [4] ifFalse: [8])*instCount. \\\"Object headers\\\"\\n\\t\\tcl isVariable\\n\\t\\t\\tifTrue: [eltSize _ cl isBytes ifTrue: [1] ifFalse: [4].\\n\\t\\t\\t\\t\\tcl allInstancesDo: [:x | instSpace _ instSpace + (x basicSize*eltSize)]]\\n\\t\\t\\tifFalse: [instSpace _ instSpace + (cl instSize*instCount*4)].\\n\\t\\tresults add: (SpaceTallyItem analyzedClassName: cl name codeSize: codeSpace instanceCount: instCount spaceForInstances: instSpace).\\n\\t\\ttotalCodeSpace _ totalCodeSpace + codeSpace.\\n\\t\\ttotalInstCount _ totalInstCount + instCount.\\n\\t\\ttotalInstSpace _ totalInstSpace + instSpace]].\\n\\ttotalPercent _ 0.0.\\n\\n\\tf _ FileStream newFileNamed: fileName.\\n\\tf timeStamp.\\n\\tf nextPutAll: ('Class' padded: #right to: 30 with: $ );\\n\\t\\t\\tnextPutAll: ('code space' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('# instances' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('inst space' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('percent' padded: #left to: 8 with: $ ); cr.\\n\\n\\tthreshold > 0 ifTrue:\\n\\t\\t[\\\"If inst count threshold > 0, then sort by space\\\"\\n\\t\\tresults _ (results select: [:s | s instanceCount >= threshold or: [s spaceForInstances > (totalInstSpace // 500)]])\\n\\t\\t\\t\\tasSortedCollection: [:s :s2 | s spaceForInstances > s2 spaceForInstances]].\\n\\n\\tresults do:\\n\\t\\t[:s | f nextPutAll: (s analyzedClassName padded: #right to: 30 with: $ );\\n\\t\\t\\tnextPutAll: (s codeSize printString padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: (s instanceCount printString padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: (s spaceForInstances printString padded: #left to: 14 with: $ ).\\n\\t\\tpercent _ s spaceForInstances*100.0/totalInstSpace roundTo: 0.1.\\n\\t\\ttotalPercent _ totalPercent + percent.\\n\\t\\tpercent >= 0.1 ifTrue:\\n\\t\\t\\t[f nextPutAll: (percent printString padded: #left to: 8 with: $ )].\\n\\t\\tf cr].\\n\\n\\tf cr; nextPutAll: ('Total' padded: #right to: 30 with: $ );\\n\\t\\tnextPutAll: (totalCodeSpace printString padded: #left to: 12 with: $ );\\n\\t\\tnextPutAll: (totalInstCount printString padded: #left to: 12 with: $ );\\n\\t\\tnextPutAll: (totalInstSpace printString padded: #left to: 14 with: $ );\\n\\t\\tnextPutAll: ((totalPercent roundTo: 0.1) printString padded: #left to: 8 with: $ ).\\n\\tf close! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:07'!\\nprintSpaceDifferenceFrom: fileName1 to: fileName2\\n\\t\\\"For differential results, run printSpaceAnalysis twice with different fileNames,\\n\\tthen run this method...\\n\\t\\tSpaceTally new printSpaceAnalysis: 0 on: 'STspace.text1'.\\n\\t\\t\\t--- do something that uses space here ---\\n\\t\\tSpaceTally new printSpaceAnalysis: 0 on: 'STspace.text2'.\\n\\t\\tSpaceTally new printSpaceDifferenceFrom: 'STspace.text1' to: 'STspace.text2'\\n\\\"\\n\\t| f coll1 coll2 item |\\n\\tf _ FileStream readOnlyFileNamed: fileName1.\\n\\tcoll1 _ OrderedCollection new.\\n\\t[f atEnd] whileFalse: [coll1 add: (f upTo: Character cr)].\\n\\tf close.\\n\\tf _ FileStream readOnlyFileNamed: fileName2.\\n\\tcoll2 _ OrderedCollection new.\\n\\t[f atEnd] whileFalse:\\n\\t\\t[item _ (f upTo: Character cr).\\n\\t\\t((coll1 includes: item) and: [(item endsWith: 'percent') not])\\n\\t\\t\\tifTrue: [coll1 remove: item]\\n\\t\\t\\tifFalse: [coll2 add: item]].\\n\\tf close.\\n\\t(StringHolder new contents: (String streamContents: \\n\\t\\t\\t[:s | \\n\\t\\t\\ts nextPutAll: fileName1; cr.\\n\\t\\t\\tcoll1 do: [:x | s nextPutAll: x; cr].\\n\\t\\t\\ts cr; cr.\\n\\t\\t\\ts nextPutAll: fileName2; cr.\\n\\t\\t\\tcoll2 do: [:x | s nextPutAll: x; cr]]))\\n\\t\\topenLabel: 'Differential Space Analysis'.\\n! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 22:59'!\\nsaveTo: aFileName\\n\\t\\\"| st |\\n\\tst := SpaceTally new.\\n\\tst spaceTally: (Array with: TextMorph with: Point).\\n\\tst saveTo: 'spaceTally2'\\\"\\n\\t| s |\\n\\t(FileDirectory default fileExists: aFileName) ifTrue: [\\n\\t\\tFileDirectory default deleteFileNamed: aFileName].\\n\\ts _ FileDirectory default fileNamed: aFileName.\\n\\tresults do: [:each | s nextPutAll: each analyzedClassName asString ; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each codeSize printString; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each instanceCount printString; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each spaceForInstances printString; cr].\\n\\ts close! !\\n\\n\\n!SpaceTally methodsFor: 'instance size' stamp: 'efc 7/6/2004 00:30'!\\nspaceForInstancesOf: aClass withInstanceCount: instCount\\n\\t\\\"Answer the number of bytes consumed by all instances of the given class, including their object headers.\\\"\\n\\n\\t| isCompact instVarBytes bytesPerElement contentBytes headerBytes total |\\n\\tinstCount = 0 ifTrue: [^ 0].\\n\\tisCompact _ aClass indexIfCompact > 0.\\n\\tinstVarBytes _ aClass instSize * 4.\\n\\taClass isVariable\\n\\t\\tifTrue: [\\n\\t\\t\\tbytesPerElement _ aClass isBytes ifTrue: [1] ifFalse: [4].\\n\\t\\t\\ttotal _ 0.\\n\\t\\t\\taClass allInstancesDo: [:inst |\\n\\t\\t\\t\\tcontentBytes _ instVarBytes + (inst size * bytesPerElement).\\n\\t\\t\\t\\theaderBytes _\\n\\t\\t\\t\\t\\tcontentBytes > 255\\n\\t\\t\\t\\t\\t\\tifTrue: [12]\\n\\t\\t\\t\\t\\t\\tifFalse: [isCompact ifTrue: [4] ifFalse: [8]].\\n\\t\\t\\t\\ttotal _ total + headerBytes + contentBytes].\\n\\t\\t\\t^ total]\\n\\t\\tifFalse: [\\n\\t\\t\\theaderBytes _\\n\\t\\t\\t\\tinstVarBytes > 255\\n\\t\\t\\t\\t\\tifTrue: [12]\\n\\t\\t\\t\\t\\tifFalse: [isCompact ifTrue: [4] ifFalse: [8]].\\n\\t\\t\\t^ instCount * (headerBytes + instVarBytes)].\\n! !\\nObject subclass: #SpaceTallyItem\\n\\tinstanceVariableNames: 'analyzedClassName codeSize instanceCount spaceForInstances'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!SpaceTallyItem commentStamp: 'sd 6/20/2003 22:02' prior: 0!\\nI'm represent an entry in the spaceTally.!\\n\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:59'!\\nanalyzedClassName\\n\\n\\t^ analyzedClassName! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:59'!\\nanalyzedClassName: aClassName\\n\\n\\tanalyzedClassName := aClassName! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:08'!\\ncodeSize\\n\\n\\t^ codeSize! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ncodeSize: aNumber\\n\\n\\tcodeSize := aNumber! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ninstanceCount\\n\\n\\t^ instanceCount! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ninstanceCount: aNumber\\n\\n\\tinstanceCount := aNumber! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:10'!\\nspaceForInstances\\n\\n\\t^ spaceForInstances! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:10'!\\nspaceForInstances: aNumber\\n\\n\\tspaceForInstances := aNumber! !\\n\\n\\n!SpaceTallyItem methodsFor: 'printing' stamp: 'sd 6/20/2003 22:52'!\\nprintOn: aStream\\n\\n\\tanalyzedClassName isNil\\n\\t\\tifFalse: [aStream nextPutAll: analyzedClassName asString]. \\n\\taStream nextPutAll: ' ('.\\n\\tcodeSize isNil\\n\\t\\tifFalse: [aStream nextPutAll: 'code size: ' ; nextPutAll: codeSize asString]. \\n\\tinstanceCount isNil\\n\\t\\tifFalse: [aStream nextPutAll: ' instance count: ' ; nextPutAll: instanceCount asString]. \\n\\tspaceForInstances isNil\\n\\t\\tifFalse: [aStream nextPutAll: ' space for instances: ' ; nextPutAll: spaceForInstances asString]. \\n\\taStream nextPut: $).\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpaceTallyItem class\\n\\tinstanceVariableNames: ''!\\n\\n!SpaceTallyItem class methodsFor: 'instance creation' stamp: 'sd 6/20/2003 22:54'!\\nanalyzedClassName: aClassName\\n\\n\\t^ self new\\n\\t\\tanalyzedClassName: aClassName ; yourself\\n\\t\\t! !\\n\\n!SpaceTallyItem class methodsFor: 'instance creation' stamp: 'sd 6/20/2003 22:54'!\\nanalyzedClassName: aClassName codeSize: codeSize instanceCount: instanceCount spaceForInstances: spaceForInstances\\n\\n\\t^ self new\\n\\t\\tanalyzedClassName: aClassName ;\\n\\t\\tcodeSize: codeSize ;\\n\\t\\tinstanceCount: instanceCount ;\\n\\t\\tspaceForInstances: spaceForInstances ; yourself! !\\nArrayedCollection variableSubclass: #SparseLargeTable\\n\\tinstanceVariableNames: 'base size chunkSize defaultValue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Arrayed'!\\n!SparseLargeTable commentStamp: '<historical>' prior: 0!\\nDerivated from Stephan Pair's LargeArray, but to hold a sparse table, in which most of the entries are the same default value, it uses some tricks.!\\n\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\narrayClass\\n\\n\\t^(self basicAt: 1) class\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nat: index\\n\\n\\tself pvtCheckIndex: index.\\n\\t^self noCheckAt: index.\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nat: index put: value\\n\\t\\n\\tself pvtCheckIndex: index.\\n\\t^self noCheckAt: index put: value\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 17:56'!\\nbase\\n\\n\\t^ base.\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nchunkSize\\n\\n\\t^chunkSize\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'tak 12/21/2004 16:59'!\\nnoCheckAt: index\\n\\t| chunkIndex t |\\n\\n\\tchunkIndex := index - base // chunkSize + 1.\\n\\t(chunkIndex > self basicSize or: [chunkIndex < 1]) ifTrue: [^ defaultValue].\\n\\tt _ self basicAt: chunkIndex.\\n\\tt ifNil: [^ defaultValue].\\n\\t^ t at: (index - base + 1 - (chunkIndex - 1 * chunkSize))\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 19:18'!\\nnoCheckAt: index put: value\\n\\t| chunkIndex t |\\n\\n\\tchunkIndex := index - base // chunkSize + 1.\\n\\tchunkIndex > self basicSize ifTrue: [^ value].\\n\\tt _ self basicAt: chunkIndex.\\n\\tt ifNil: [^ value].\\n\\t^ t at: (index - base + 1 - (chunkIndex - 1 * chunkSize)) put: value\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nsize\\n\\n\\t^size\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 22:34'!\\nzapDefaultOnlyEntries\\n\\n\\t| lastIndex newInst |\\n\\t1 to: self basicSize do: [:i |\\n\\t\\t(self allDefaultValueSubtableAt: i) ifTrue: [self basicAt: i put: nil].\\n\\t].\\n\\n\\tlastIndex _ self findLastNonNilSubTable.\\n\\tlastIndex = 0 ifTrue: [^ self].\\n\\t\\n\\tnewInst _ self class new: lastIndex*chunkSize chunkSize: chunkSize arrayClass: (self basicAt: lastIndex) class base: base defaultValue: defaultValue.\\n\\tnewInst privateSize: self size.\\n\\tbase to: newInst size do: [:i | newInst at: i put: (self at: i)].\\n\\t1 to: newInst basicSize do: [:i |\\n\\t\\t(newInst allDefaultValueSubtableAt: i) ifTrue: [newInst basicAt: i put: nil].\\n\\t].\\n\\n\\tself becomeForward: newInst.\\n\\t^ newInst.\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'initialization' stamp: 'yo 12/1/2003 16:58'!\\ninitChunkSize: aChunkSize size: aSize arrayClass: aClass base: b defaultValue: d\\n\\n\\t| lastChunkSize |\\n\\tchunkSize := aChunkSize.\\n\\tsize := aSize.\\n\\tbase _ b.\\n\\tdefaultValue _ d.\\n\\t1 to: (self basicSize - 1) do: [ :in | self basicAt: in put: (aClass new: chunkSize withAll: defaultValue) ].\\n\\tlastChunkSize := size \\\\\\\\ chunkSize.\\n\\tlastChunkSize = 0 ifTrue: [lastChunkSize := chunkSize].\\n\\tsize = 0 \\n\\t\\tifTrue: [self basicAt: 1 put: (aClass new: 0)]\\n\\t\\tifFalse: [self basicAt: self basicSize put: (aClass new: lastChunkSize withAll: defaultValue)].\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 17:06'!\\nprintElementsOn: aStream\\n\\t| element |\\n\\taStream nextPut: $(.\\n\\tbase to: size do: [:index | element _ self at: index. aStream print: element; space].\\n\\tself isEmpty ifFalse: [aStream skip: -1].\\n\\taStream nextPut: $)\\n! !\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 15:58'!\\nprintOn: aStream\\n\\n\\t(#(String) includes: self arrayClass name) \\n\\t\\tifTrue: [^self storeOn: aStream].\\n\\t^super printOn: aStream\\n! !\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 15:59'!\\nstoreOn: aStream\\n\\n\\t| x |\\n\\t(#(String) includes: self arrayClass name) ifTrue: \\n\\t\\t[aStream nextPut: $'.\\n\\t\\t1 to: self size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\taStream nextPut: (x _ self at: i).\\n\\t\\t\\tx == $' ifTrue: [aStream nextPut: x]].\\n\\t\\taStream nextPutAll: ''' asLargeArrayChunkSize: '.\\n\\t\\taStream nextPutAll: self chunkSize asString.\\n\\t\\t^self].\\n\\t^super storeOn: aStream\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 18:58'!\\nallDefaultValueSubtableAt: index\\n\\n\\t| t |\\n\\tt _ self basicAt: index.\\n\\tt ifNil: [^ true].\\n\\tt do: [:e |\\n\\t\\te ~= defaultValue ifTrue: [^ false].\\n\\t].\\n\\t^ true.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 17:10'!\\nanalyzeSpaceSaving\\n\\n\\t| total elems tablesTotal nonNilTables |\\n\\ttotal _ size - base + 1.\\n\\telems _ 0.\\n\\tbase to: size do: [:i | (self at: i) ~= defaultValue ifTrue: [elems _ elems + 1]].\\n\\ttablesTotal _ self basicSize.\\n\\tnonNilTables _ 0.\\n\\t1 to: self basicSize do: [:i | (self basicAt: i) ifNotNil: [nonNilTables _ nonNilTables + 1]].\\n\\n\\t^ String streamContents: [:strm |\\n\\t\\tstrm nextPutAll: 'total: '.\\n\\t\\tstrm nextPutAll: total printString.\\n\\t\\tstrm nextPutAll: ' elements: '.\\n\\t\\tstrm nextPutAll: elems printString.\\n\\t\\tstrm nextPutAll: ' tables: '.\\n\\t\\tstrm nextPutAll: tablesTotal printString.\\n\\t\\tstrm nextPutAll: ' non-nil: '.\\n\\t\\tstrm nextPutAll: nonNilTables printString.\\n\\t].\\n\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'nk 8/31/2004 08:34'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver that contains no elements.\\\"\\n\\t^self speciesNew: 0\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 22:34'!\\nfindLastNonNilSubTable\\n\\n\\t(self basicAt: self basicSize) ifNotNil: [^ self basicSize].\\n\\n\\tself basicSize - 1 to: 1 by: -1 do: [:lastIndex |\\n\\t\\t(self basicAt: lastIndex) ifNotNil: [^ lastIndex].\\n\\t].\\n\\t^ 0.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 19:19'!\\nprivateSize: s\\n\\n\\tsize _ s.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 17:34'!\\npvtCheckIndex: index \\n\\n\\tindex isInteger ifFalse: [self errorNonIntegerIndex].\\n\\tindex < 1 ifTrue: [self errorSubscriptBounds: index].\\n\\tindex > size ifTrue: [self errorSubscriptBounds: index].\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarInstance\\n\\n\\t^self class\\n\\t\\tnew: self size \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarInstance: newSize\\n\\n\\t^self class\\n\\t\\tnew: newSize \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarSpeciesInstance\\n\\n\\t^self similarInstance\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nsimilarSpeciesInstance: newSize\\n\\n\\t^self similarInstance: newSize\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nspeciesNew\\n\\n\\t^self species\\n\\t\\tnew: self size \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nspeciesNew: newSize\\n\\n\\t^self species\\n\\t\\tnew: newSize \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSparseLargeTable class\\n\\tinstanceVariableNames: ''!\\n\\n!SparseLargeTable class methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:54'!\\ndefaultChunkSize\\n\\n\\t^100! !\\n\\n!SparseLargeTable class methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:54'!\\ndefaultChunkSizeForFiles\\n\\n\\t^8000! !\\n\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:06'!\\nnew: size\\n\\n\\t^self new: size chunkSize: self defaultChunkSize\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:07'!\\nnew: size chunkSize: chunkSize\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:08'!\\nnew: size chunkSize: chunkSize arrayClass: aClass\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array base: 1.\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:37'!\\nnew: size chunkSize: chunkSize arrayClass: aClass base: b\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array base: 1 defaultValue: nil.\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:37'!\\nnew: size chunkSize: chunkSize arrayClass: aClass base: b defaultValue: d\\n\\n\\t| basicSize |\\n\\t(basicSize := ((size - 1) // chunkSize) + 1) = 0\\n\\t\\tifTrue: [basicSize := 1].\\n\\t^(self basicNew: basicSize)\\n\\t\\tinitChunkSize: chunkSize size: size arrayClass: aClass base: b defaultValue: d;\\n\\t\\tyourself\\n! !\\nObject subclass: #SparseXTable\\n\\tinstanceVariableNames: 'tables xTables'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!SparseXTable methodsFor: 'as yet unclassified' stamp: 'yo 7/30/2003 17:38'!\\ntableFor: code\\n\\n\\t| div t table |\\n\\tdiv _ code // 65536.\\n\\tt _ xTables at: div ifAbsent: [table _ Array new: 65536 withAll: 0. xTables at: div put: table. table].\\n\\t^ t.\\n! !\\nObject subclass: #Speaker\\n\\tinstanceVariableNames: 'pitch range loudness speed transcriber voice visitors'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-TTS'!\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:33'!\\nloudness\\n\\t^ loudness! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nloudness: aNumber\\n\\tloudness := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/13/1999 03:02'!\\nphonemes\\n\\t\\\"Answer the phoneme set of the receiver.\\\"\\n\\t^ self transcriber phonemes! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:18'!\\npitch\\n\\t\\\"Answer the average pitch.\\\"\\n\\t^ pitch! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npitch: aNumber\\n\\t\\\"Set the average pitch.\\\"\\n\\tpitch := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:18'!\\nrange\\n\\t\\\"Answer the pitch range (variation).\\\"\\n\\t^ range! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nrange: aNumber\\n\\t\\\"Set the pitch range (variation).\\\"\\n\\trange := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:33'!\\nspeed\\n\\t^ speed! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nspeed: aNumber\\n\\tspeed := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:31'!\\ntranscriber\\n\\t^ transcriber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\ntranscriber: aPhoneticTranscriber\\n\\ttranscriber := aPhoneticTranscriber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:02'!\\nvisitors\\n\\t^ visitors! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nvisitors: aCollection\\n\\tvisitors := aCollection! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:32'!\\nvoice\\n\\t^ voice! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nvoice: aVoice\\n\\tvoice := aVoice! !\\n\\n\\n!Speaker methodsFor: 'editing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nedit\\n\\t| answer buttons |\\n\\tanswer := (self findAVoice: KlattVoice) editor.\\n\\tbuttons := AlignmentMorph new listDirection: #leftToRight; color: answer color.\\n\\tbuttons\\n\\t\\taddMorphFront: (SimpleButtonMorph new target: self; actWhen: #buttonDown; actionSelector: #newHead; labelString: 'new head');\\n\\t\\taddMorphFront: (SimpleButtonMorph new target: self; actWhen: #buttonDown; actionSelector: #saySomething; labelString: 'test').\\n\\tanswer\\n\\t\\taddSliderForParameter: #speed target: self min: 0.1 max: 2.0 description: 'Speed';\\n\\t\\taddSliderForParameter: #loudness target: self min: 0.0 max: 1.0 description: 'Loudness';\\n\\t\\taddSliderForParameter: #range target: self min: 0.0 max: 1.0 description: 'Pitch Range';\\n\\t\\taddSliderForParameter: #pitch target: self min: 20.0 max: 800.0 description: 'Pitch';\\n\\t\\taddMorphFront: buttons;\\n\\t\\topenInWorld! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:19'!\\nfindAVoice: aClass\\n\\t(self voice isKindOf: aClass) ifTrue: [^ self voice].\\n\\t(self voice isKindOf: CompositeVoice)\\n\\t\\tifTrue: [self voice do: [ :each | (each isKindOf: aClass) ifTrue: [^ each]]].\\n\\t^ nil! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:27'!\\nmakeGestural\\n\\t(self findAVoice: GesturalVoice) isNil ifFalse: [^ self].\\n\\tself voice: self voice + GesturalVoice new! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:27'!\\nnewHead\\n\\tself makeGestural.\\n\\t(self findAVoice: GesturalVoice) newHead! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/14/1999 05:24'!\\nsaySomething\\n\\tself say: #('This is my voice.' 'I am speaking.' 'Do you like my voice?' 'Listen to my voice.' 'Hello.' 'Hay. What are you doing?' 'How are you?' 'Is this my voice?' 'Are you there?' 'Help, please.' 'Howdy.' 'Ha ha he he hi.') atRandom! !\\n\\n\\n!Speaker methodsFor: 'initialization' stamp: 'len 11/27/2000 09:59'!\\ninitialize\\n\\tself pitch: 100.0; range: 0.3; loudness: 1.0; speed: 0.6; \\\"normalizer: TextNormalizer new;\\\" transcriber: PhoneticTranscriber default; visitors: {IntonationVisitor default. DurationsVisitor default. F0RenderingVisitor default}! !\\n\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/14/1999 02:13'!\\nclauseFromString: aString\\n\\t^ Clause new\\n\\t\\tstring: aString;\\n\\t\\tphrases: ((aString findTokens: '!!?.,;()') collect: [ :each | self phraseFromString: each])! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\neventsFromString: aString\\n\\t| clause |\\n\\tclause := self clauseFromString: aString.\\n\\tclause phrases do: [ :each | each lastSyllable events add: (PhoneticEvent new phoneme: self phonemes silence; duration: 0.1)].\\n\\tclause lastSyllable events last duration: 0.5.\\n\\tvisitors do: [ :each | each speaker: self. clause accept: each].\\n\\tclause eventsDo: [ :each | each loudness: self loudness].\\n\\t^ clause events! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/13/1999 03:19'!\\nphraseFromString: aString\\n\\t^ Phrase new\\n\\t\\tstring: aString;\\n\\t\\twords: ((aString findTokens: ' !!?.,;()') collect: [ :each | self wordFromString: each])! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nsyllabizationOf: phonemes\\n\\t| syllable stream last answer |\\n\\tanswer := OrderedCollection new.\\n\\tsyllable := Syllable new phonemes: (OrderedCollection new: 4).\\n\\tstream := ReadStream on: phonemes.\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [syllable phonemes add: (last := stream next).\\n\\t\\t\\t\\t\\t(stream atEnd not and: [last isConsonant not and: [stream peek isConsonant]])\\n\\t\\t\\t\\t\\t\\tifTrue: [answer add: syllable. syllable := Syllable new phonemes: (OrderedCollection new: 4)]].\\n\\tsyllable phonemes isEmpty ifFalse: [answer add: syllable].\\n\\t^ answer! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/8/1999 18:24'!\\nwordFromString: aString\\n\\t^ Word new\\n\\t\\tstring: aString;\\n\\t\\tsyllables: (self syllabizationOf: (self transcriber transcriptionOf: aString))! !\\n\\n\\n!Speaker methodsFor: 'playing' stamp: 'nk 2/19/2004 16:50'!\\nnumberSignDelay\\n\\t\\\"Answer the number of milliseconds that a # symbol in the string given to say: will generate.\\\"\\n\\t^200! !\\n\\n!Speaker methodsFor: 'playing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nsay: aString \\n\\t\\\"aString may contain characters and punctuation.\\n\\tYou may also include the # symbol in aString;\\n\\tfor each one of these, a 200msec delay will be generated.\\\"\\n\\n\\t| events stream string token delay |\\n\\n\\tstream := ReadStream\\n\\t\\t\\t\\ton: ((aString\\n\\t\\t\\t\\t\\t\\tcopyReplaceAll: '-'\\n\\t\\t\\t\\t\\t\\twith: ' '\\n\\t\\t\\t\\t\\t\\tasTokens: false)\\n\\t\\t\\t\\t\\t\\tfindTokens: '?# '\\n\\t\\t\\t\\t\\t\\tkeep: '?#').\\n\\tstring := ''.\\n\\tdelay := 0.\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [token := stream next.\\n\\t\\t\\ttoken = '#'\\n\\t\\t\\t\\tifTrue: [ self voice playSilenceMSecs: self numberSignDelay.\\n\\t\\t\\t\\t\\tdelay := delay + self numberSignDelay ]\\n\\t\\t\\t\\tifFalse: [string := string , ' ' , token.\\n\\t\\t\\t\\t\\t(token = '?' or: [stream atEnd])\\n\\t\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tevents := CompositeEvent new.\\n\\t\\t\\t\\t\\t\\t\\tevents addAll: (self eventsFromString: string).\\n\\t\\t\\t\\t\\t\\t\\tevents playOn: self voice delayed: delay.\\n\\t\\t\\t\\t\\t\\t\\tdelay := delay + (events duration * 1000).\\n\\t\\t\\t\\t\\t\\t\\tstring := '' ]]].\\n\\tself voice flush! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpeaker class\\n\\tinstanceVariableNames: ''!\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:17'!\\nbicyclic\\n\\t\\\"\\n\\tSpeaker bicyclic say: 'This is my voice. I am a woman with bicyclic voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 200.0;\\n\\t\\tvoice: (KlattVoice new diplophonia: 0.4; tract: 14.4)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:56'!\\nbigMan\\n\\t\\\"\\n\\tSpeaker bigMan say: 'I am the child? No. I am the big man speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 90.0;\\n\\t\\trange: 0.5;\\n\\t\\tvoice: (KlattVoice new tract: 20)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:19'!\\nbreathy\\n\\t\\\"\\n\\tSpeaker breathy say: 'This is my breathy voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.6; turbulence: 70)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:07'!\\nchild\\n\\t\\\"\\n\\tSpeaker child say: 'Hello. I am a child speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 320.0;\\n\\t\\tvoice: (KlattVoice new tract: 12)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:21'!\\ncreaky\\n\\t\\\"\\n\\tSpeaker creaky say: 'This is my creaky voice with hight jitter and shimmer.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 90.0;\\n\\t\\tspeed: 0.5;\\n\\t\\tvoice: (KlattVoice new jitter: 0.5; shimmer: 0.5)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 11/27/2000 10:01'!\\ndefault\\n\\t\\\"\\n\\tSpeaker default say: 'This is the default voice.'\\n\\t\\\"\\n\\n\\t^ self new voice: KlattVoice new! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:13'!\\nexorsist\\n\\t\\\"\\n\\tSpeaker exorsist say: 'This is an scary voice. Boo.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 40.0;\\n\\t\\tspeed: 0.5;\\n\\t\\tvoice: (KlattVoice new tract: 10; diplophonia: 0.4; jitter: 0.3; shimmer: 0.5; turbulence: 50)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:13'!\\nfly\\n\\t\\\"\\n\\tSpeaker fly say: 'Haaaaaalp.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 650.0;\\n\\t\\tloudness: 0.5;\\n\\t\\tspeed: 0.8;\\n\\t\\tvoice: (KlattVoice new flutter: 1.0; tract: 1)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:01'!\\nkid\\n\\t\\\"\\n\\tSpeaker kid say: 'Do you like my voice? I am the kid speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 170.0;\\n\\t\\trange: 0.4;\\n\\t\\tvoice: (KlattVoice new tract: 16)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 11/27/2000 10:01'!\\nman\\n\\t\\\"\\n\\tSpeaker man say: 'Listen to my voice. I am a man speaking.'\\n\\t\\\"\\n\\n\\t^ self default pitch: 90.0! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:26'!\\nnotPressed\\n\\t\\\"\\n\\tSpeaker notPressed say: 'This is a non pressed voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.9)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:26'!\\npressed\\n\\t\\\"\\n\\tSpeaker pressed say: 'This is a pressed voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.1)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:27'!\\nwhispery\\n\\t\\\"\\n\\tSpeaker whispery say: 'This is my whispery voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tvoice: (KlattVoice new breathiness: 1.0)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:10'!\\nwoman\\n\\t\\\"\\n\\tSpeaker woman say: 'Do you listen? I am a woman speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 230.0;\\n\\t\\trange: 0.5;\\n\\t\\tspeed: 0.7;\\n\\t\\tvoice: (KlattVoice new flutter: 0.5; ro: 0.3; ra: 0.003; tract: 14.4)! !\\n\\n\\n!Speaker class methodsFor: 'examples-others' stamp: 'len 12/2/1999 03:46'!\\nmanWithEditor\\n\\t\\\"\\n\\tSpeaker manWithEditor say: 'With this editor you can change my voice.'\\n\\t\\\"\\n\\n\\t^ self man edit! !\\n\\n!Speaker class methodsFor: 'examples-others' stamp: 'len 12/14/1999 05:10'!\\nmanWithHead\\n\\t\\\"\\n\\tSpeaker manWithHead say: 'This is my voice. Can you see my lips?'\\n\\t\\\"\\n\\n\\t^ self man newHead! !\\nMorph subclass: #SpeakerMorph\\n\\tinstanceVariableNames: 'bufferSize buffer lastConePosition sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'nk 6/12/2004 10:05'!\\naddGraphic\\n\\n\\t| graphic |\\n\\tgraphic _ World drawingClass withForm: self speakerGraphic.\\n\\tgraphic position: bounds center - (graphic extent // 2).\\n\\tself addMorph: graphic.\\n! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:51'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 1.0\\n\\t\\tg: 0.484\\n\\t\\tb: 0.258! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:51'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself addGraphic.\\n\\tbufferSize _ 5000.\\n\\tbuffer _ WriteStream\\n\\t\\t\\t\\ton: (SoundBuffer newMonoSampleCount: bufferSize).\\n\\tlastConePosition _ 0.\\n\\tsound _ SequentialSound new! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'jm 4/22/1999 22:58'!\\nspeakerGraphic\\n\\n\\t^ Form\\n\\t\\textent: 19@18\\n\\t\\tdepth: 8\\n\\t\\tfromArray: #(0 0 1493172224 2816 0 0 0 1493172224 11 0 0 138 1493172224 184549376 184549376 0 35509 2315255808 720896 720896 0 9090522 2315255808 2816 720896 0 2327173887 2315255819 2816 720896 138 3051028442 2315255819 2816 2816 1505080590 4294957786 2315255808 184549387 2816 3053453311 4292532917 1493172224 184549387 2816 1505080714 3048584629 1493172224 184549387 2816 9079434 3048584629 1493172224 184549387 2816 138 2327164341 1493172235 2816 2816 0 2324346293 1493172235 2816 720896 0 9079477 1493172224 2816 720896 0 35466 1493172224 720896 720896 0 138 0 184549376 184549376 0 0 0 11 0 0 0 0 2816 0)\\n\\t\\toffset: 0@0\\n! !\\n\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jdl 3/28/2003 09:38'!\\nappendSample: aFloat \\n\\t\\\"Append the given sample, a number between -100.0 and 100.0, to my buffer. Flush the buffer if it is full.\\\"\\n\\n\\tlastConePosition := aFloat.\\n\\tlastConePosition := lastConePosition min: 100.0.\\n\\tlastConePosition := lastConePosition max: -100.0.\\n\\tbuffer nextPut: (327.67 * lastConePosition) truncated.\\n\\tbuffer position >= bufferSize ifTrue: [self flushBuffer]\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/21/1999 10:18'!\\nconePosition\\n\\n\\t^ lastConePosition\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 16:46'!\\nconePosition: aNumber\\n\\n\\tself appendSample: aNumber asFloat. \\\"sets lastConePosition\\\"\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 13:29'!\\nflushBuffer\\n\\n\\t| buf |\\n\\tbuf _ buffer contents.\\n\\tbuffer resetContents.\\n\\tsound isPlaying ifFalse: [sound _ SequentialSound new].\\n\\tsound add: (SampledSound samples: buf samplingRate: 11025).\\n\\tsound isPlaying\\n\\t\\tifTrue: [sound pruneFinishedSounds]\\n\\t\\tifFalse: [sound play].\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 15:33'!\\nstopSound\\n\\n\\tsound pause.\\n\\tbuffer resetContents.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpeakerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SpeakerMorph class methodsFor: '*eToys-scripting' stamp: 'sw 9/26/2001 04:27'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories.\\\"\\n\\n\\t^ #((speaker\\n\\n((slot conePosition 'the position of the speaker cone' Number readWrite Player getConePosition Player setConePosition:))))\\n\\n\\n\\n! !\\nAlignmentMorph subclass: #SpectrumAnalyzerMorph\\n\\tinstanceVariableNames: 'soundInput statusLight levelMeter graphMorph sonogramMorph fft displayType'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n!SpectrumAnalyzerMorph commentStamp: '<historical>' prior: 0!\\nI am a tool for analyzing sound data from a microphone, CD, or other input source in real time. I have several display modes:\\n\\n\\tsignal\\t\\tsnapshots of the raw signal data as it arrives\\n\\tspectrum\\tfrequency spectrum of the signal data as it arrives\\n\\tsonogram\\tscrolling plot of the frequency spectrum over time,\\n\\t\\t\\t where the vertical axis is frequency, the horizontal\\n\\t\\t\\t\\t axis is time, and amount of energy at a given\\n\\t\\t\\t\\t frequency is shown as a grayscale value with\\n\\t\\t\\t\\t larger values being darker\\n\\nTo use this tool, be sure that you have selected the proper sound source using you host OS facilities. Set the desired sampling rate and FFT size (try 22050 samples/sec and an FFT size of 512) then click on the 'start' button. Use the slider to adjust the level so that the yellow level indicator peaks somewhere between the middle and the right edge at the maximum signal level.\\n\\nNote that if the level meter peaks hit the right edge, you will get 'clipping', which creates a bunch of spurious high frequency noise in the frequency spectrum. If the display is set to 'signal' mode, you can actually see the tops and bottoms of the waveform being cut off when clipping occurs.\\n\\nMany machines may not be able to perform spectrum analysis in real time, especially at higher sampling rates and larger FFT sizes. In both 'signal' and 'spectrum' modes, this tool will skip data to try to keep up with real time. However, in 'sonogram' mode it always processes all the data, even if it falls behind. This allows you to get a complete sonogram without dropouts even on a slower machine. However, as the sonogram display falls behind there will be a larger and larger time lag between when a sound is input and when it appears on the display.\\n\\nThe smaller the FFT size, the less frequency resolution you get. The lower the sampling rate, the less total frequency range you get. For an FFT size of N and a sampling rate of R, each of the N/2 'bins' of the frequency spectrum has a frequency resolution of R / N. For example, at a sampleing rate of 22050 samples/second, the total frequency range is 0 to 11025 Hz and an FFT of size 256 would divide this range into 128 bins (the output of an FFT of size N has N/2 bins), each of which covers a frequency band about 86 Hz wide.\\n\\nTo increase time resolution, increase the sampling rate and decrease the FFT size.\\n!\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:52'!\\ndefaultBorderWidth\\n\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:52'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself listDirection: #topToBottom.\\n\\tsoundInput _ SoundInputStream new samplingRate: 22050.\\n\\tfft _ FFT new: 512.\\n\\tdisplayType _ 'sonogram'.\\n\\tself hResizing: #shrinkWrap.\\n\\tself vResizing: #shrinkWrap.\\n\\tself addButtonRow.\\n\\tself addLevelSlider.\\n\\tself addMorphBack: self makeLevelMeter.\\n\\tself addMorphBack: (Morph new extent: 10 @ 10;\\n\\t\\t\\t color: Color transparent).\\n\\t\\\"spacer\\\"\\n\\tself resetDisplay! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:25'!\\ninvokeMenu\\n\\t\\\"Invoke the settings menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ CustomMenu new.\\n\\taMenu addList:\\t{\\n\\t\\t{'set sampling rate' translated.\\t\\t#setSamplingRate}.\\n\\t\\t{'set FFT size' translated.\\t\\t\\t#setFFTSize}.\\n\\t\\t{'set display type' translated.\\t\\t#setDisplayType}}.\\n\\taMenu invokeOn: self defaultSelection: nil.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'jm 9/8/1999 12:52'!\\nresetDisplay\\n\\t\\\"Recreate my display after changing some parameter such as FFT size.\\\"\\n\\n\\tdisplayType = 'signal' ifTrue: [self showSignal].\\n\\tdisplayType = 'spectrum' ifTrue: [self showSpectrum].\\n\\tdisplayType = 'sonogram' ifTrue: [self showSonogram].\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:29'!\\nsetDisplayType\\n\\t\\\"Set the display type.\\\"\\n\\n\\t| aMenu choice on |\\n\\taMenu _ CustomMenu new title: ('display type (currently {1})' translated format:{displayType}).\\n\\taMenu addList:\\t{\\n\\t\\t{'signal' translated.\\t'signal'}.\\n\\t\\t{'spectrum' translated.\\t'spectrum'}.\\n\\t\\t{'sonogram' translated.\\t'sonogram'}}.\\n\\tchoice _ aMenu startUp.\\n\\tchoice ifNil: [^ self].\\n\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tdisplayType _ choice.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:27'!\\nsetFFTSize\\n\\t\\\"Set the size of the FFT used for frequency analysis.\\\"\\n\\n\\t| aMenu sz on |\\n\\taMenu _ CustomMenu new title: ('FFT size (currently {1})' translated format:{fft n}).\\n\\t((7 to: 10) collect: [:n | 2 raisedTo: n]) do:[:r | aMenu add: r printString action: r].\\n\\tsz _ aMenu startUp.\\n\\tsz ifNil: [^ self].\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tfft _ FFT new: sz.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:26'!\\nsetSamplingRate\\n\\t\\\"Set the sampling rate to be used for incoming sound data.\\\"\\n\\n\\t| aMenu rate on |\\n\\taMenu _ CustomMenu new title:\\n\\t\\t('Sampling rate (currently {1})' translated format:{soundInput samplingRate}).\\n\\t#(11025 22050 44100) do:[:r | aMenu add: r printString action: r].\\n\\trate _ aMenu startUp.\\n\\trate ifNil: [^ self].\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tsoundInput samplingRate: rate.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 15:12'!\\nstart\\n\\t\\\"Start displaying sound data.\\\"\\n\\n\\tdisplayType = 'signal'\\n\\t\\tifTrue: [soundInput bufferSize: graphMorph width - (2 * graphMorph borderWidth)]\\n\\t\\tifFalse: [soundInput bufferSize: fft n].\\n\\tsoundInput startRecording.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 19:05'!\\nstep\\n\\t\\\"Update the record light, level meter, and display.\\\"\\n\\n\\t| w |\\n\\t\\\"update the record light and level meter\\\"\\n\\tsoundInput isRecording\\n\\t\\tifTrue: [statusLight color: Color yellow]\\n\\t\\tifFalse: [statusLight color: Color gray].\\n\\tw _ ((121 * soundInput meterLevel) // 100) max: 1.\\n\\tlevelMeter width ~= w ifTrue: [levelMeter width: w].\\n\\n\\t\\\"update the display if any data is available\\\"\\n\\tself updateDisplay.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 15:12'!\\nstop\\n\\t\\\"Stop displaying sound data.\\\"\\n\\n\\tsoundInput stopRecording.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/6/1999 12:12'!\\nstopStepping\\n\\t\\\"Turn off recording.\\\"\\n\\n\\tsuper stopStepping.\\n\\tsoundInput stopRecording.\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'submorphs-add/remove' stamp: 'jm 9/6/1999 14:40'!\\ndelete\\n\\t\\\"Turn off recording when this morph is deleted.\\\"\\n\\n\\tsuper delete.\\n\\tsoundInput stopRecording.\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'testing' stamp: 'jm 9/7/1999 22:26'!\\nstepTime\\n\\n\\t^ 0\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'dgd 9/19/2003 13:30'!\\naddButtonRow\\n\\n\\t| r |\\n\\tr _ AlignmentMorph newRow vResizing: #shrinkWrap.\\n\\tr addMorphBack: (self buttonName: 'Menu' translated action: #invokeMenu).\\n\\tr addMorphBack: (Morph new extent: 4@1; color: Color transparent).\\n\\tr addMorphBack: (self buttonName: 'Start' translated action: #start).\\n\\tr addMorphBack: (Morph new extent: 4@1; color: Color transparent).\\n\\tr addMorphBack: (self buttonName: 'Stop' translated action: #stop).\\n\\tr addMorphBack: (Morph new extent: 12@1; color: Color transparent).\\n\\tr addMorphBack: self makeStatusLight.\\n\\tself addMorphBack: r.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'ar 11/9/2000 21:23'!\\naddLevelSlider\\n\\n\\t| levelSlider r |\\n\\tlevelSlider _ SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 100@2;\\n\\t\\ttarget: soundInput;\\n\\t\\tactionSelector: #recordLevel:;\\n\\t\\tadjustToValue: soundInput recordLevel.\\n\\tr _ AlignmentMorph newRow\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #leftCenter;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #rigid;\\n\\t\\theight: 24.\\n\\tr addMorphBack: (StringMorph contents: '0 ').\\n\\tr addMorphBack: levelSlider.\\n\\tr addMorphBack: (StringMorph contents: ' 10').\\n\\tself addMorphBack: r.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jhm 10/15/97 14:30'!\\nbuttonName: aString action: aSymbol\\n\\n\\t^ SimpleButtonMorph new\\n\\t\\ttarget: self;\\n\\t\\tlabel: aString;\\n\\t\\tactionSelector: aSymbol\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 13:27'!\\nmakeLevelMeter\\n\\n\\t| outerBox |\\n\\touterBox _ RectangleMorph new extent: 125@14; color: Color lightGray.\\n\\tlevelMeter _ Morph new extent: 2@10; color: Color yellow.\\n\\tlevelMeter position: outerBox topLeft + (2@2).\\n\\touterBox addMorph: levelMeter.\\n\\t^ outerBox\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'dgd 9/19/2003 13:31'!\\nmakeStatusLight\\n\\n\\t| s |\\n\\tstatusLight _ RectangleMorph new extent: 24@19.\\n\\tstatusLight color: Color gray.\\n\\ts _ StringMorph contents: 'On' translated.\\n\\ts position: statusLight center - (s extent // 2).\\n\\tstatusLight addMorph: s.\\n\\t^ statusLight\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'gm 2/28/2003 00:11'!\\nprocessBuffer: buf \\n\\t\\\"Analyze one buffer of data.\\\"\\n\\n\\t| data |\\n\\tdata := displayType = 'signal' \\n\\t\\tifTrue: [buf]\\n\\t\\tifFalse: [fft transformDataFrom: buf startingAt: 1].\\n\\tgraphMorph ifNotNil: \\n\\t\\t\\t[graphMorph\\n\\t\\t\\t\\tdata: data;\\n\\t\\t\\t\\tchanged].\\n\\tsonogramMorph ifNotNil: \\n\\t\\t\\t[data := data collect: [:v | v sqrt].\\t\\\"square root compresses dynamic range\\\"\\n\\t\\t\\tdata /= 400.0.\\n\\t\\t\\tsonogramMorph plotColumn: (data copyFrom: 1 to: data size // 1)]! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 12:49'!\\nremoveAllDisplays\\n\\t\\\"Remove all currently showing displays.\\\"\\n\\n\\tsonogramMorph ifNotNil: [sonogramMorph delete].\\n\\tgraphMorph ifNotNil: [graphMorph delete].\\n\\tsonogramMorph _ graphMorph _ nil.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:56'!\\nshowSignal\\n\\t\\\"Display the actual signal waveform.\\\"\\n\\n\\tdisplayType _ 'signal'.\\n\\tself removeAllDisplays.\\n\\tgraphMorph _ GraphMorph new.\\n\\tgraphMorph extent: (400 + (2 * graphMorph borderWidth))@128.\\n\\tgraphMorph data: (Array new: 100 withAll: 0).\\n\\tgraphMorph color: (Color r: 0.8 g: 1.0 b: 1.0).\\n\\tself addMorphBack: graphMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:43'!\\nshowSonogram\\n\\t\\\"Display a sonogram showing the frequency spectrum versus time.\\\"\\n\\n\\t| zeros h w |\\n\\tdisplayType _ 'sonogram'.\\n\\tself removeAllDisplays.\\n\\th _ fft n // 2.\\n\\th _ h min: 512 max: 64.\\n\\tw _ 400.\\n\\tsonogramMorph _\\n\\t\\tSonogram new\\n\\t\\t\\textent: w@h\\n\\t\\t\\tminVal: 0.0\\n\\t\\t\\tmaxVal: 1.0\\n\\t\\t\\tscrollDelta: w.\\n\\tzeros _ Array new: sonogramMorph height withAll: 0.\\n\\tsonogramMorph width timesRepeat: [sonogramMorph plotColumn: zeros].\\n\\tself addMorphBack: sonogramMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 15:10'!\\nshowSpectrum\\n\\t\\\"Display the frequency spectrum.\\\"\\n\\n\\tdisplayType _ 'spectrum'.\\n\\tself removeAllDisplays.\\n\\tgraphMorph _ GraphMorph new.\\n\\tgraphMorph extent: ((fft n // 2) + (2 * graphMorph borderWidth))@128.\\n\\tgraphMorph data: (Array new: fft n // 2 withAll: 0).\\n\\tself addMorphBack: graphMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:39'!\\nupdateDisplay\\n\\t\\\"Update the display if any data is available.\\\"\\n\\n\\t| buf bufCount |\\n\\tsoundInput bufferCount = 0 ifTrue: [^ self].\\n\\n\\tgraphMorph ifNotNil: [\\n\\t\\t[soundInput bufferCount > 0] whileTrue: [\\n\\t\\t\\t\\\"skip to the most recent buffer\\\"\\n\\t\\t\\tbuf _ soundInput nextBufferOrNil].\\n\\t\\t^ self processBuffer: buf].\\n\\n\\tsonogramMorph ifNotNil: [\\n\\t\\t\\\"at small buffer sizes we have to update the sonogram in\\n\\t\\t batches or we may get behind; shoot for 8 updates/second\\\"\\n\\t\\tbufCount _ (soundInput samplingRate / (8 * soundInput bufferSize)) truncated max: 1.\\n\\t\\t[bufCount > 0 and: [soundInput bufferCount > 0]] whileTrue: [\\n\\t\\t\\tself processBuffer: (soundInput nextBufferOrNil)]].\\n! !\\nPath subclass: #Spline\\n\\tinstanceVariableNames: 'coefficients'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Paths'!\\n!Spline commentStamp: '<historical>' prior: 0!\\nI represent a collection of Points through which a cubic spline curve is fitted.!\\n\\n\\n!Spline methodsFor: 'accessing'!\\ncoefficients\\n\\t\\\"Answer an eight-element Array of Arrays each of which is the length \\n\\tof the receiver. The first four arrays are the values, first, second and \\n\\tthird derivatives, respectively, for the parametric spline in x. The last \\n\\tfour elements are for y.\\\"\\n\\n\\t^coefficients! !\\n\\n\\n!Spline methodsFor: 'displaying'!\\ncomputeCurve\\n\\t\\\"Compute an array for the coefficients.\\\"\\n\\n\\t| length extras |\\n\\tlength _ self size.\\n\\textras _ 0.\\n\\tcoefficients _ Array new: 8.\\n\\t1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].\\n\\t1 to: 5 by: 4 do: \\n\\t\\t[:k | \\n\\t\\t1 to: length do:\\n\\t\\t\\t[:i | (coefficients at: k)\\n\\t\\t\\t\\t\\tat: i put: (k = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [(self at: i) x asFloat]\\n\\t\\t\\t\\t\\t\\tifFalse: [(self at: i) y asFloat])].\\n\\t\\t\\t1 to: extras do: [:i | (coefficients at: k)\\n\\t\\t\\t\\t\\tat: length + i put: ((coefficients at: k)\\n\\t\\t\\t\\t\\t\\tat: i + 1)].\\n\\t\\t\\tself derivs: (coefficients at: k)\\n\\t\\t\\t\\tfirst: (coefficients at: k + 1)\\n\\t\\t\\t\\tsecond: (coefficients at: k + 2)\\n\\t\\t\\t\\tthird: (coefficients at: k + 3)].\\n\\textras > 0 \\n\\t\\tifTrue: [1 to: 8 do: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\tcoefficients at: i put: ((coefficients at: i)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopyFrom: 2 to: length + 1)]]! !\\n\\n!Spline methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm \\n\\t\\\"Display the receiver, a spline curve, approximated by straight line\\n\\tsegments.\\\"\\n\\n\\t| n line t x y x1 x2 x3 y1 y2 y3 |\\n\\tcollectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].\\n\\tline _ Line new.\\n\\tline form: self form.\\n\\tline beginPoint: \\n\\t\\t(x _ (coefficients at: 1) at: 1) rounded @ (y _ (coefficients at: 5) at: 1) rounded.\\n\\t1 to: (coefficients at: 1) size - 1 do: \\n\\t\\t[:i | \\n\\t\\t\\\"taylor series coefficients\\\"\\n\\t\\tx1 _ (coefficients at: 2) at: i.\\n\\t\\ty1 _ (coefficients at: 6) at: i.\\n\\t\\tx2 _ ((coefficients at: 3) at: i) / 2.0.\\n\\t\\ty2 _ ((coefficients at: 7) at: i) / 2.0.\\n\\t\\tx3 _ ((coefficients at: 4) at: i) / 6.0.\\n\\t\\ty3 _ ((coefficients at: 8) at: i) / 6.0.\\n\\t\\t\\\"guess n\\\"\\n\\t\\tn _ 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)\\n\\t\\t\\t\\t\\t\\t\\tat: i + 1) abs + ((coefficients at: 7)\\n\\t\\t\\t\\t\\t\\t\\tat: i + 1) abs / 100.0) rounded.\\n\\t\\t1 to: n - 1 do: \\n\\t\\t\\t[:j | \\n\\t\\t\\tt _ j asFloat / n.\\n\\t\\t\\tline endPoint: \\n\\t\\t\\t\\t(x3 * t + x2 * t + x1 * t + x) rounded \\n\\t\\t\\t\\t\\t\\t\\t@ (y3 * t + y2 * t + y1 * t + y) rounded.\\n\\t\\t\\tline\\n\\t\\t\\t\\tdisplayOn: aDisplayMedium\\n\\t\\t\\t\\tat: aPoint\\n\\t\\t\\t\\tclippingBox: clipRect\\n\\t\\t\\t\\trule: anInteger\\n\\t\\t\\t\\tfillColor: aForm.\\n\\t\\t\\tline beginPoint: line endPoint].\\n\\t\\tline beginPoint: \\n\\t\\t\\t\\t(x _ (coefficients at: 1) at: i + 1) rounded \\n\\t\\t\\t\\t\\t@ (y _ (coefficients at: 5) at: i + 1) rounded.\\n\\t\\tline\\n\\t\\t\\tdisplayOn: aDisplayMedium\\n\\t\\t\\tat: aPoint\\n\\t\\t\\tclippingBox: clipRect\\n\\t\\t\\trule: anInteger\\n\\t\\t\\tfillColor: aForm]! !\\n\\n!Spline methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm \\n\\t\\\"Get the scaled and translated path of newKnots.\\\"\\n\\n\\t| newKnots newSpline |\\n\\tnewKnots _ aTransformation applyTo: self.\\n\\tnewSpline _ Spline new.\\n\\tnewKnots do: [:knot | newSpline add: knot].\\n\\tnewSpline form: self form.\\n\\tnewSpline\\n\\t\\tdisplayOn: aDisplayMedium\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: clipRect\\n\\t\\trule: anInteger\\n\\t\\tfillColor: aForm! !\\n\\n\\n!Spline methodsFor: 'private'!\\nderivs: a first: point1 second: point2 third: point3\\n\\t\\\"Compute the first, second and third derivitives (in coefficients) from\\n\\tthe Points in this Path (coefficients at: 1 and coefficients at: 5).\\\"\\n\\n\\t| l v anArray |\\n\\tl _ a size.\\n\\tl < 2 ifTrue: [^self].\\n\\tl > 2\\n\\t ifTrue:\\n\\t\\t[v _ Array new: l.\\n\\t\\t v at: 1 put: 4.0.\\n\\t\\t anArray _ Array new: l.\\n\\t\\t anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))).\\n\\t\\t 2 to: l - 2 do:\\n\\t\\t\\t[:i | \\n\\t\\t\\tv at: i put: (4.0 - (1.0 / (v at: (i - 1)))).\\n\\t\\t\\tanArray\\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: (6.0 * ((a at: i) - ((a at: (i + 1)) * 2.0) + (a at: (i + 2)))\\n\\t\\t\\t\\t\\t\\t- ((anArray at: (i - 1)) / (v at: (i - 1))))].\\n\\t\\t point2 at: (l - 1) put: ((anArray at: (l - 2)) / (v at: (l - 2))).\\n\\t\\t l - 2 to: 2 by: 0-1 do: \\n\\t\\t\\t[:i | \\n\\t\\t\\tpoint2 \\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: ((anArray at: (i - 1)) - (point2 at: (i + 1)) / (v at: (i - 1)))]].\\n\\tpoint2 at: 1 put: (point2 at: l put: 0.0).\\n\\t1 to: l - 1 do:\\n\\t\\t[:i | point1 \\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: ((a at: (i + 1)) - (a at: i) - \\n\\t\\t\\t\\t\\t\\t((point2 at: i) * 2.0 + (point2 at: (i + 1)) / 6.0)).\\n\\t\\t point3 at: i put: ((point2 at: (i + 1)) - (point2 at: i))]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpline class\\n\\tinstanceVariableNames: ''!\\n\\n!Spline class methodsFor: 'examples' stamp: '6/8/97 13:55 di'!\\nexample\\n\\t\\\"Designate points on the Path by clicking the red button. Terminate by\\n\\tpressing any other button. A curve will be displayed, through the\\n\\tselected points, using a long black form.\\\"\\n\\n\\t| splineCurve aForm flag|\\n\\taForm _ Form extent: 2@2.\\n\\taForm fillBlack.\\n\\tsplineCurve _ Spline new.\\n\\tsplineCurve form: aForm.\\n\\tflag _ true.\\n\\t[flag] whileTrue:\\n\\t\\t[Sensor waitButton.\\n\\t\\t Sensor redButtonPressed\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[splineCurve add: Sensor waitButton. \\n\\t\\t\\t\\t Sensor waitNoButton.\\n\\t\\t\\t\\t aForm displayOn: Display at: splineCurve last]\\n\\t\\t\\tifFalse: [flag_false]].\\n\\tsplineCurve computeCurve.\\n\\tsplineCurve isEmpty \\n\\t\\tifFalse: [splineCurve displayOn: Display.\\n\\t\\t\\t\\tSensor waitNoButton].\\n \\n\\t\\\"Spline example\\\"! !\\nObject subclass: #SqNumberParser\\n\\tinstanceVariableNames: 'sourceStream base neg integerPart fractionPart exponent scale nDigits lastNonZero requestor failBlock'\\n\\tclassVariableNames: 'BelllerophonBase10'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Numbers'!\\n!SqNumberParser commentStamp: 'nice 4/27/2006 22:38' prior: 0!\\nThis is a class specialized in parsing and building numbers.\\nNumber syntax should follow Smalltalk syntax.\\n\\nIf you have to read foreign number syntax, create a subclass.!\\n\\n\\n!SqNumberParser methodsFor: 'error' stamp: 'nice 4/28/2006 00:20'!\\nexpected: errorString \\n\\trequestor isNil\\n\\t\\tifFalse: [requestor\\n\\t\\t\\t\\tnotify: errorString , ' ->'\\n\\t\\t\\t\\tat: sourceStream position\\n\\t\\t\\t\\tin: sourceStream].\\n\\tself fail! !\\n\\n!SqNumberParser methodsFor: 'error' stamp: 'nice 4/28/2006 00:19'!\\nfail\\n\\tfailBlock isNil ifFalse: [^failBlock value].\\n\\tself error: 'Reading a number failed'! !\\n\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 4/27/2006 22:57'!\\nexponentLetters\\n\\t\\\"answer the list of possible exponents for Numbers.\\n\\tNote: this parser will not honour precision attached to the exponent.\\n\\tdifferent exponent do not lead to different precisions.\\n\\tonly IEEE 754 floating point numbers will be created\\\"\\n\\t\\n\\t^'edq'! !\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 5/1/2006 01:58'!\\nfailBlock: aBlockOrNil\\n\\tfailBlock := aBlockOrNil! !\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 5/1/2006 01:59'!\\nrequestor: anObjectOrNil\\n\\trequestor := anObjectOrNil! !\\n\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 5/7/2006 17:33'!\\nmakeFloatFromMantissa: m exponent: k base: aRadix \\n\\t\\\"Convert infinite precision arithmetic into Floating point.\\n\\tThis alogrithm rely on correct IEEE rounding mode\\n\\tbeing implemented in Integer>>asFloat and Fraction>>asFloat\\\"\\n\\n\\t^(k positive\\n\\t\\tifTrue: [m * (aRadix raisedTo: k)]\\n\\t\\tifFalse: [Fraction numerator: m denominator: (aRadix raisedTo: k negated)]) asFloat! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 00:52'!\\nmakeIntegerOrScaledInteger\\n\\t\\\"at this point, there is no digit, nor fractionPart.\\n\\tmaybe it can be a scaled decimal with fraction omitted...\\\"\\n\\t\\n\\tneg\\n\\t\\tifTrue: [integerPart := integerPart negated].\\n\\tself readExponent\\n\\t\\tifTrue: [integerPart := integerPart\\n\\t\\t\\t\\t\\t\\t* (base raisedTo: exponent)]\\n\\t\\tifFalse: [self readScale\\n\\t\\t\\t\\tifTrue: [nil.\\n\\t\\t\\t\\t\\t^ ScaledDecimal newFromNumber: integerPart scale: scale]].\\n\\t^ integerPart! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 01:14'!\\nreadExponent\\n\\t\\\"read the exponent if any (stored in instVar).\\n\\tAnswer true if found, answer false if none.\\n\\tIf exponent letter is not followed by a digit,\\n\\tthis is not considered as an error.\\n\\tExponent are always read in base 10, though i do not see why...\\\"\\n\\t\\n\\t| eneg |\\n\\texponent := 0.\\n\\tsourceStream atEnd\\n\\t\\tifTrue: [^ false].\\n\\t(self exponentLetters includes: sourceStream next)\\n\\t\\tifFalse: [sourceStream skip: -1.\\n\\t\\t\\t^ false].\\n\\teneg := sourceStream peekFor: $-.\\n\\texponent := self\\n\\t\\t\\t\\tnextUnsignedIntegerBase: 10\\n\\t\\t\\t\\tifFail: [sourceStream\\n\\t\\t\\t\\t\\t\\tskip: (eneg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [-2]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [-1]).\\n\\t\\t\\t\\t\\t^ false].\\n\\teneg\\n\\t\\tifTrue: [exponent := exponent negated].\\n\\t^ true! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 03:08'!\\nreadScale\\n\\t\\\"read the scale if any (stored in instVar).\\n\\tAnswer true if found, answer false if none.\\n\\tIf scale letter is not followed by a digit,\\n\\tthis is not considered as an error.\\n\\tScales are always read in base 10, though i do not see why...\\\"\\n\\t\\n\\tscale := 0.\\n\\tsourceStream atEnd ifTrue: [^ false].\\n\\t('s' includes: sourceStream next)\\n\\t\\tifFalse: [sourceStream skip: -1.\\n\\t\\t\\t^ false].\\n\\tscale := self\\n\\t\\t\\t\\tnextUnsignedIntegerBase: 10\\n\\t\\t\\t\\tifFail: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\t^ false].\\n\\t^ true! !\\n\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/27/2006 23:08'!\\nnextIntegerBase: aRadix\\n\\t\\\"Form an integer with following digits\\\"\\n\\t\\n\\t| isNeg value |\\n\\tisNeg := sourceStream peekFor: $-.\\n\\tvalue := self nextUnsignedIntegerBase: aRadix.\\n\\t^isNeg\\n\\t\\tifTrue: [value negated]\\n\\t\\tifFalse: [value]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 01:12'!\\nnextIntegerBase: aRadix ifFail: aBlock\\n\\t\\\"Form an integer with following digits\\\"\\n\\t\\n\\t| isNeg value |\\n\\tisNeg := sourceStream peekFor: $-.\\n\\tvalue := self nextUnsignedIntegerBase: aRadix ifFail: [^aBlock value].\\n\\t^isNeg\\n\\t\\tifTrue: [value negated]\\n\\t\\tifFalse: [value]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 03:38'!\\nnextNumber\\n\\t\\\"main method for reading a number.\\n\\tThis one can read Float Integer and ScaledDecimal\\\"\\n\\t\\n\\t| numberOfTrailingZeroInIntegerPart numberOfNonZeroFractionDigits mantissa decimalMultiplier decimalFraction value numberOfTrailingZeroInFractionPart |\\n\\t(sourceStream nextMatchAll: 'NaN')\\n\\t\\tifTrue: [^ Float nan].\\n\\tneg := sourceStream peekFor: $-.\\n\\t(sourceStream nextMatchAll: 'Infinity')\\n\\t\\tifTrue: [^ neg\\n\\t\\t\\t\\tifTrue: [Float infinity negated]\\n\\t\\t\\t\\tifFalse: [Float infinity]].\\n\\tintegerPart := self nextUnsignedIntegerBase: base.\\n\\tnumberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.\\n\\t(sourceStream peekFor: $r)\\n\\t\\tifTrue: [\\\"<base>r<integer>\\\"\\n\\t\\t\\t(base := integerPart) < 2\\n\\t\\t\\t\\tifTrue: [^ self expected: 'an integer greater than 1 as valid radix'].\\n\\t\\t\\t(sourceStream peekFor: $-)\\n\\t\\t\\t\\tifTrue: [neg := neg not].\\n\\t\\t\\tintegerPart := self nextUnsignedIntegerBase: base.\\n\\t\\t\\tnumberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].\\n\\t^ (sourceStream peekFor: $.)\\n\\t\\tifTrue: [fractionPart := self\\n\\t\\t\\t\\t\\t\\tnextUnsignedIntegerBase: base\\n\\t\\t\\t\\t\\t\\tifFail: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\t\\t\\t^ neg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [integerPart negated]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [integerPart]].\\n\\t\\t\\tnumberOfNonZeroFractionDigits := lastNonZero.\\n\\t\\t\\tnumberOfTrailingZeroInFractionPart := nDigits - lastNonZero.\\n\\t\\t\\tself readExponent\\n\\t\\t\\t\\tifFalse: [self readScale\\n\\t\\t\\t\\t\\t\\tifTrue: [decimalMultiplier := base raisedTo: numberOfNonZeroFractionDigits.\\n\\t\\t\\t\\t\\t\\t\\tdecimalFraction := integerPart * decimalMultiplier + fractionPart / decimalMultiplier.\\n\\t\\t\\t\\t\\t\\t\\tneg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [decimalFraction := decimalFraction negated].\\n\\t\\t\\t\\t\\t\\t\\t^ ScaledDecimal newFromNumber: decimalFraction scale: scale]].\\n\\t\\t\\tfractionPart isZero\\n\\t\\t\\t\\tifTrue: [mantissa := integerPart\\n\\t\\t\\t\\t\\t\\t\\t\\t// (base raisedTo: numberOfTrailingZeroInIntegerPart).\\n\\t\\t\\t\\t\\texponent := exponent + numberOfTrailingZeroInIntegerPart]\\n\\t\\t\\t\\tifFalse: [mantissa := integerPart\\n\\t\\t\\t\\t\\t\\t\\t\\t* (base raisedTo: numberOfNonZeroFractionDigits) + (fractionPart // (base raisedTo: numberOfTrailingZeroInFractionPart)).\\n\\t\\t\\t\\t\\texponent := exponent - numberOfNonZeroFractionDigits].\\n\\t\\t\\t\\\"very naive algorithm\\\"\\n\\t\\t\\tvalue := self makeFloatFromMantissa: mantissa exponent: exponent base: base.\\n\\t\\t\\t^ neg\\n\\t\\t\\t\\tifTrue: [value isZero\\n\\t\\t\\t\\t\\t\\tifTrue: [Float negativeZero]\\n\\t\\t\\t\\t\\t\\tifFalse: [value negated]]\\n\\t\\t\\t\\tifFalse: [value]]\\n\\t\\tifFalse: [self makeIntegerOrScaledInteger]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 01:10'!\\nnextUnsignedIntegerBase: aRadix \\n\\t\\\"Form an unsigned integer with incoming digits from sourceStream.\\n\\tCount the number of digits and the lastNonZero digit and store int in\\n\\tinstVar \\\"\\n\\t\\n\\t^ self\\n\\t\\tnextUnsignedIntegerBase: aRadix\\n\\t\\tifFail: [self expected: 'a digit between 0 and 9']! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 03:14'!\\nnextUnsignedIntegerBase: aRadix ifFail: errorBlock\\n\\t\\\"Form an unsigned integer with incoming digits from sourceStream.\\n\\tCount the number of digits and the lastNonZero digit and store int in instVar\\\"\\n\\t\\n\\t| value digit |\\n\\tvalue := 0.\\n\\tnDigits := 0.\\n\\tlastNonZero := 0.\\n\\t[sourceStream atEnd\\n\\t\\tor: [digit := sourceStream next digitValue.\\n\\t\\t\\t(digit < 0\\n\\t\\t\\t\\t\\tor: [digit >= aRadix])\\n\\t\\t\\t\\tand: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\ttrue]]]\\n\\t\\twhileFalse: [nDigits := nDigits + 1.\\n\\t\\t\\tdigit isZero\\n\\t\\t\\t\\tifFalse: [lastNonZero := nDigits].\\n\\t\\t\\tvalue := value * aRadix + digit].\\n\\tnDigits = 0\\n\\t\\tifTrue: [errorBlock value].\\n\\t^value! !\\n\\n\\n!SqNumberParser methodsFor: 'initialize-release' stamp: 'nice 5/1/2006 00:41'!\\non: aStringOrStream\\n\\tsourceStream := aStringOrStream isString\\n\\t\\tifTrue: [ReadStream on: aStringOrStream]\\n\\t\\tifFalse: [aStringOrStream].\\n\\tbase := 10.\\n\\tneg := false.\\n\\tintegerPart := fractionPart := exponent := scale := 0.\\n\\trequestor := failBlock := nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqNumberParser class\\n\\tinstanceVariableNames: ''!\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 00:45'!\\non: aStringOrStream\\n\\t^self new on: aStringOrStream! !\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 02:02'!\\nparse: aStringOrStream \\n\\t^(self new)\\n\\t\\ton: aStringOrStream;\\n\\t\\tnextNumber! !\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 02:02'!\\nparse: aStringOrStream onError: failBlock \\n\\t^(self new)\\n\\t\\ton: aStringOrStream;\\n\\t\\tfailBlock: failBlock;\\n\\t\\tnextNumber! !\\nClassTestCase subclass: #SqNumberParserTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n!SqNumberParserTest commentStamp: 'nice 5/7/2006 17:54' prior: 0!\\nProvide tests for new clas aimed at parsing numbers.\\n\\nIt duplicates NumberParsingTest, with few more tests.!\\n\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatFromStreamAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs := '10r-12.3456' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -12.3456 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456e2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456e2e2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs upToEnd = 'e2'.\\n\\n\\trs := '10r-12.3456d2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '-12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '12.3456z2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 12.3456 = aFloat.\\n\\tself assert: rs upToEnd = 'z2'.\\n! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatFromStreamWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs := '1.0e-14' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '1.0e-14 1' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = ' 1'.\\n\\n\\trs := '1.0e-14eee' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = 'eee'.\\n\\n\\trs := '1.0e14e10' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e14 = aFloat.\\n\\tself assert: rs upToEnd = 'e10'.\\n\\n\\trs := '1.0e+14e' readStream. \\\"Plus sign is not parseable\\\"\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e+14e'.\\n\\n\\trs := '1.0e' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e'.! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/1/2006 00:40'!\\ntestFloatPrintString\\n\\t\\\"self debug: #testFloatPrintString\\\"\\n\\t\\n\\t| f r |\\n\\tf := Float basicNew: 2.\\n\\tr := Random new seed: 1234567.\\n\\t100\\n\\t\\ttimesRepeat: [f basicAt: 1 put: (r nextInt: 16r100000000)- 1.\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].\\n\\t\\\"test big num near infinity\\\"\\n\\t10\\n\\t\\ttimesRepeat: [f basicAt: 1 put: 16r7FE00000 + ((r nextInt: 16r100000) - 1).\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].\\n\\t\\\"test infinitesimal (gradual underflow)\\\"\\n\\t10\\n\\t\\ttimesRepeat: [f basicAt: 1 put: 0 + ((r nextInt: 16r100000) - 1).\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/1/2006 00:40'!\\ntestFloatReadError\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs num |\\n\\trs := '1e' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 'e'.\\n\\t\\n\\trs := '1s' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 's'.\\n\\n\\trs := '1.' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: num isInteger.\\n\\tself assert: rs upToEnd = '.'.\\n\\t\\n\\trs := '' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := 'foo' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\n\\trs := 'radix' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '.e0' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '-.e0' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '--1' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber := '2r1.0101e9' asNumber.\\n\\tself assert: 672.0 = aNumber.\\n\\tself assert: (SqNumberParser parse: '2r1.0101e9') = (1.3125 * (2 raisedTo: 9)).\\n\\trs := ReadStream on: '2r1.0101e9e9'.\\n\\tself assert: (SqNumberParser parse: rs) = 672.0.\\n\\tself assert: rs upToEnd = 'e9'\\n! !\\n\\n\\n!SqNumberParserTest methodsFor: 'tests - Integer' stamp: 'nice 5/7/2006 17:46'!\\ntestIntegerReadFrom\\n\\t\\\"Ensure remaining characters in a stream are not lost when parsing an integer.\\\"\\n\\n\\t| rs i s |\\n\\trs := ReadStream on: '123s could be confused with a ScaledDecimal'.\\n\\ti := SqNumberParser parse: rs.\\n\\tself assert: i == 123.\\n\\ts := rs upToEnd.\\n\\tself assert: 's could be confused with a ScaledDecimal' = s.\\n\\trs := ReadStream on: '123.s could be confused with a ScaledDecimal'.\\n\\ti := SqNumberParser parse: rs.\\n\\tself assert: i == 123.\\n\\ts := rs upToEnd.\\n\\tself assert: '.s could be confused with a ScaledDecimal' = s\\n! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Integer' stamp: 'nice 5/7/2006 17:46'!\\ntestIntegerReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber := '2r1e26' asNumber.\\n\\tself assert: 67108864 = aNumber.\\n\\tself assert: (SqNumberParser parse: '2r1e26') = (2 raisedTo: 26).\\n\\trs := '2r1e26eee' readStream.\\n\\tself assert: (SqNumberParser parse: rs) = 67108864.\\n\\tself assert: rs upToEnd = 'eee'\\n! !\\nObject subclass: #SqueakPage\\n\\tinstanceVariableNames: 'url title comment thumbnail contentsMorph creationTime creationAuthor lastChangeTime lastChangeAuthor policy dirty'\\n\\tclassVariableNames: 'MaxThumbnailWidthOrHeight RecentMaxNum RecentStem'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n!SqueakPage commentStamp: '<historical>' prior: 0!\\nA SqueakPage is holder for a page of morphs that live on the disk or on a server.\\nA URLMorph is a thumbnail sized stand-in for the page. Clicking on it gets the page.\\nAn ObjectOut is a fake object that stands for an object that is out on the disk. (Like ObjectTracer or ObjectViewer.)\\nA MorphObjectOut is a subclass that stands for a Morph that is out on the disk.\\n\\nTo find out how to make the pages of any BookMorph go out to the disk (or a server), see \\thttp://minnow.cc.gatech.edu/SqueakDoc.1 then go to 'SqueakPages'.\\n\\nA SqueakPage is always in-memory. Its contentsMorph will be 'become-ed' to a MorphObjectOut tombstone when it goes out. (A page may or may not be in the cache. First put it in, then ask it for the data.) Sending any message to the contentsMorph triggers the fetch. Many URLMorphs may hold onto one page. A page has a thumbnail. A URLMorph points at its page object.\\n\\nStates of a SqueakPage, and the transitions to another state:\\n1) have a url as a string. Then: (URLMorph grabURL: 'file://Ted''s/books/tryThis/p1'). \\n\\tDrop it into any morph.\\n2) have a URLMorph, with page==nil. Click it. (makes an empty page, installs \\n\\tit in the global page cache)\\n3) have a URLMorph with a SqueakPage, with contentsMorph==nil, \\n\\tbut page is not in the cache (this is a rare case). ask page contentsMorph.\\n4) OUT: have a URLMorph with a SqueakPage, with contentsMorph being a MorphObjectOut, \\n\\tand its page is in the cache. Sending the contentsMorph any message brings it in and\\n\\tbecomes it to the morph. (fix up morph's pointer to the page.)\\n5) Totally IN: a morph, owned by a SqueakPage, has a page in the cache. \\n\\tThe morph is clean. \\n\\tWhenever someone triggers a purge (when?), contentsMorph is becomed\\n\\tto a MorphObjectOut. (go to 4)\\n\\tCausing the morph to execute layoutChanged marks the morph as dirty.\\n\\t(morph's property #pageDirty is set to true) (go to 6)\\n6) Totally IN and dirty. \\n\\tWhenever any other page is fetched from the disk or the net, all other \\n\\tdirty pages are written and marked clean. (go to 5)\\n\\nNote that the entire tree of submorphs goes out -- hundreds of objects. Bringing the object back in brings in the SqueakPage, installs it in the cache. Classes other than PasteUpMorph can easily be made to send their contents out if there is any need.\\n\\nNote that every book is now automatically a WebBook. We simply give a page a url and tell it to purge.\\n\\nurl\\t\\ta string\\ntitle\\t\\t\\ncomment\\t\\t\\nthumbnail\\t\\t\\ncontentsMorph\\t\\t(1) a pasteUpMorph with other morphs in it.\\n\\t\\t\\t\\t\\t(2) a MorphObjectOut. Sending any message brings it in. \\n\\t\\t\\t\\t\\t(3) nil if the page has never been in this image.\\ncreationTime\\t\\t\\ncreationAuthor\\t\\t\\nlastChangeTime\\t\\t\\nlastChangeAuthor \\npolicy\\t\\t#alwaysWrite, #neverWrite, #ask. (cache can override with a global policy)\\n\\t\\t\\t(Explicit writing by user has policy #neverWrite)\\ndirty \\t\\t(Morph>>layoutChanged sends changed: #SqueakPage. If policy==#check, \\n\\t\\t\\t\\tthen the page sets dirty_true.)\\n\\t\\t\\t(If policy==#alwaysWrite, then set dirty when the page is retrieved from the cache.)\\n\\nClass MorphObjectOut has an instance variable called page.\\nAll messages to an MorphObjectOut cause it to be brought in. Except the messages needed to write the MorphObjectOut on the disk as part of a parent's being sent out. (size, class, instSize, instVar:at:. Can rename these and call from its own version of the writing routine.)\\n\\tTo purge, go through the clean pages, and any that have world not equal to this world, entomb them. \\n\\t(If an object in the subtree is held by an object outside the tree, it will remain, And will be duplicated when the tree comes back in. This is a problem already in normal uses of SmartRefStream.)\\n\\n\\n!\\n\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/5/1999 16:47'!\\nasMorph\\n\\t^ self fetchContents! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 13:47'!\\ncomment\\n\\n\\tcomment ifNil: [^ ''] ifNotNil: [^ comment].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 18:12'!\\ncomment: aString\\n\\n\\taString isEmpty\\n\\t\\tifTrue: [comment _ nil]\\n\\t\\tifFalse: [comment _ aString].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/2/1998 11:27'!\\ncontentsMorph\\n\\t\\\"Return what it is now. If the morph is out on the disk, return nil. Use fetchContents to get the data for sure.\\\"\\n\\n\\t^ contentsMorph\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 11/11/1998 12:54'!\\ncontentsMorph: aPasteUpMorph\\n\\n\\tcontentsMorph _ aPasteUpMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/23/1999 14:39'!\\ncopyForSaving\\n\\t\\\"Make a copy and configure me to be put out on the disk. When it is brought in and touched, it will turn into the object at the url.\\\"\\n\\n\\t| forDisk holder |\\n\\tforDisk _ self clone.\\n\\tholder _ MorphObjectOut new xxxSetUrl: url page: forDisk.\\n\\tforDisk contentsMorph: holder.\\n\\t^ holder\\t\\t\\\"directly representing the object\\\"! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/30/1998 15:08'!\\nfetchContents\\n\\t\\\"Make every effort to get contentsMorph.\\\"\\n\\n\\tself isContentsInMemory ifTrue: [^ contentsMorph].\\n\\t^ self fetchInformIfError! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'ar 4/10/2005 18:52'!\\nfetchContentsIfAbsent: failBlock\\n\\t\\\"Make every effort to get contentsMorph. Assume I am in the cache already.\\\"\\n\\t| strm page temp temp2 |\\n\\tSqueakPageCache write.\\t\\t\\\"sorry about the pause\\\"\\n\\tCursor wait showWhile: [\\n\\t\\tstrm _ (ServerFile new fullPath: url) asStream].\\n\\tstrm isString ifTrue: [^ failBlock value].\\t\\t\\n\\tpage _ strm fileInObjectAndCode.\\n\\tpage isMorph ifTrue: [contentsMorph _ page].\\t\\\"may be a bare morph\\\"\\n\\t\\\"copy over the state\\\"\\n\\ttemp _ url.\\n\\ttemp2 _ policy.\\n\\tself copyAddedStateFrom: page.\\n\\turl _ temp.\\t\\\"don't care what it says\\\"\\n\\ttemp2 ifNotNil: [policy _ temp2].\\t\\t\\\"use mine\\\"\\n\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\tself dirty: false.\\n\\t^ contentsMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'ar 4/10/2005 18:52'!\\nfetchInformIfError\\n\\t\\\"Make every effort to get contentsMorph. Put up a good notice if can't get it. Assume page is in the cache already. Overwrite the contentsMorph no matter what.\\\"\\n\\t| strm page temp temp2 |\\n\\n\\tSqueakPageCache write.\\t\\t\\\"sorry about the pause\\\"\\n\\tCursor wait showWhile: [\\n\\t\\tstrm _ (ServerFile new fullPath: url) asStream].\\n\\tstrm isString ifTrue: [self inform: 'Sorry, ',strm. ^ nil].\\t\\\"<<<<< Note Diff\\\"\\n\\t(url beginsWith: 'file:') ifTrue: [Transcript show: 'Fetching ', url; cr].\\t\\n\\tpage _ strm fileInObjectAndCode.\\n\\tpage isMorph \\n\\t\\tifTrue: [contentsMorph _ page]\\t\\\"may be a bare morph\\\"\\n\\t\\tifFalse: [\\\"copy over the state\\\"\\n\\t\\t\\ttemp _ url.\\n\\t\\t\\ttemp2 _ policy.\\n\\t\\t\\tself copyFrom: page.\\t\\\"including contentsMorph\\\"\\n\\t\\t\\turl _ temp.\\t\\\"I know best!!\\\"\\n\\t\\t\\ttemp2 ifNotNil: [policy _ temp2]].\\t\\t\\\"use mine\\\"\\n\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\tcontentsMorph setProperty: #SqueakPage toValue: self.\\n\\tself dirty: false.\\n\\t^ contentsMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/30/1998 15:08'!\\nisContentsInMemory\\n\\t\\\"Is my contentsMorph in memory, or is it an ObjectOut tombstone? Be careful not to send it any message.\\\"\\n\\n\\t^ (contentsMorph xxxClass inheritsFrom: Object) and: [(contentsMorph == nil) not]! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 12/4/1998 01:00'!\\nlastChangeTime\\n\\t^ lastChangeTime! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/24/1999 12:06'!\\nsaveMorph: aMorph author: authorString\\n\\t\\\"Save the given morph as this page's contents. Update its thumbnail and inform references to this URL that the page has changed.\\\"\\n\\t\\\"Details: updateThumbnail releases the cached state of the saved page contents after computing the thumbnail.\\\"\\n\\n\\t| n |\\n\\tcontentsMorph _ aMorph.\\n\\tn _ aMorph knownName.\\n\\tn ifNotNil: [self title: n].\\n\\tcreationAuthor ifNil: [\\n\\t\\tcreationAuthor _ authorString.\\n\\t\\tcreationTime _ Time totalSeconds].\\n\\\"\\tlastChangeAuthor _ authorString.\\n\\tlastChangeTime _ Time totalSeconds.\\tdo it when actually write\\\"\\n\\tself computeThumbnail.\\n\\tself postChangeNotification.\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 17:45'!\\nthumbnail\\n\\n\\t^ thumbnail\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 13:47'!\\ntitle\\n\\n\\ttitle ifNil: [^ ''] ifNotNil: [^ title].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 18:12'!\\ntitle: aString\\n\\n\\taString isEmpty\\n\\t\\tifTrue: [title _ nil]\\n\\t\\tifFalse: [title _ aString].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 11/4/1998 20:34'!\\nurl\\n\\n\\t^ url! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 1/14/1999 23:50'!\\nurl: aString\\n\\n\\t| sd |\\n\\taString isEmpty ifTrue: [url _ nil. ^ self].\\n\\n\\t\\\"Expand ./ and store as an absolute url\\\"\\n\\tsd _ ServerFile new.\\n\\tsd fullPath: aString.\\n\\turl _ sd realUrl.! !\\n\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 9/30/1998 22:40'!\\ndirty: aBool\\n\\tdirty _ aBool! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 10/8/1998 13:18'!\\npolicy\\n\\t^ policy! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 9/30/1998 22:39'!\\npolicy: aSymbol\\n\\tpolicy _ aSymbol! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'ar 3/17/2001 23:36'!\\nprePurge\\n\\t\\\"Return self if ready to be purged, or nil if not\\\"\\n\\n\\tself isContentsInMemory ifFalse: [^ nil].\\n\\tcontentsMorph ifNil: [^ nil]. \\\"out already\\\"\\n\\turl ifNil: [^ nil].\\t\\\"just to be safe\\\"\\n\\t^ (World ~~ nil and: [contentsMorph world == World]) \\n\\t\\tifTrue: [nil \\\"showing now\\\"] ifFalse: [self]! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 12/16/1998 08:24'!\\npurge\\n\\t\\\"Replace my morph with a tombstone, if I am not in a world that is being shown.\\\"\\n\\n\\t(self prePurge) ifNotNil: [\\n\\t\\tcontentsMorph become: (MorphObjectOut new xxxSetUrl: url page: self)].\\n\\t\\t\\\"Simple, isn't it!!\\\"! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 1/23/1999 13:19'!\\nurlNoOverwrite: suggested\\n\\t\\\"Look in the directory. If there is a file of this name, create a new name. Keep track of highest numbers used as a hint.\\\"\\n\\n\\t| dir ll stem num local trial suffix |\\n\\t(suggested endsWith: '.sp') ifTrue: [suffix _ '.sp'].\\n\\t(suggested endsWith: '.bo') ifTrue: [suffix _ '.bo'].\\n\\tsuffix ifNil: [self error: 'unknown suffix'].\\n\\tdir _ ServerFile new fullPath: suggested.\\n\\t(dir includesKey: dir fileName) ifFalse: [^ url _ suggested].\\n\\t\\\"File already exists!! Create a new name\\\"\\n\\t\\\"Find the stem file name\\\"\\n\\tstem _ SqueakPage stemUrl: suggested.\\n\\tnum _ stem = RecentStem ifTrue: [RecentMaxNum+1] ifFalse: [1].\\n\\n\\tlocal _ dir fileName.\\t\\\"ugh, take stem again...\\\"\\n\\tll _ local findLast: [:char | char == $.].\\n\\tll = 0 ifFalse: [local _ local copyFrom: 1 to: ll-1].\\t\\\"remove .sp\\\"\\n\\tlocal _ (local splitInteger) at: 1.\\t\\t\\\"remove trailing number\\\"\\n\\tlocal last == $x ifFalse: [local _ local , 'x'].\\n\\t[trial _ local, num printString, suffix.\\n\\t\\tdir includesKey: trial] whileTrue: [num _ num + 1].\\n\\tRecentStem _ stem. RecentMaxNum _ num.\\n\\t^ url _ stem, 'x', num printString, suffix! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'RAA 8/30/2000 11:43'!\\nwrite\\n\\t\\\"Decide whether to write this page on the disk.\\\"\\n\\t| sf remoteFile |\\n\\tpolicy == #neverWrite ifTrue: [^ self].\\n\\t\\t\\\"demo mode, or write only when user explicitly orders it\\\"\\n\\n\\t\\\"All other policies do write: #now\\\"\\n\\tcontentsMorph ifNil: [^ self].\\n\\tdirty _ dirty | ((contentsMorph valueOfProperty: #pageDirty) == true).\\n\\t\\t\\\"set by layoutChanged\\\"\\n\\tdirty == true ifTrue: [ \\n\\t\\tsf _ ServerDirectory new fullPath: url.\\n\\t\\t\\\"check for shared password\\\"\\n\\t\\t\\\"contentsMorph allMorphsDo: [:m | m prepareToBeSaved].\\n\\t\\t\\t\\tdone in objectToStoreOnDataStream\\\"\\n\\t\\tlastChangeAuthor _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\t\\tlastChangeTime _ Time totalSeconds.\\n\\t\\tCursor wait showWhile: [\\n\\t\\t\\tremoteFile _ sf fileNamed: url.\\t\\\"no notification when overwriting\\\"\\n\\t\\t\\tremoteFile dataIsValid.\\n\\t\\t\\tremoteFile fileOutClass: nil andObject: self.\\n\\t\\t\\t\\\"remoteFile close\\\"].\\n\\t\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\t\\tdirty _ false].! !\\n\\n\\n!SqueakPage methodsFor: 'private' stamp: 'tk 2/25/1999 09:13'!\\ncomputeThumbnail\\n\\t\\\"Make a thumbnail from my morph.\\\"\\n\\n\\t(contentsMorph isKindOf: PasteUpMorph) \\n\\t\\tifTrue: [thumbnail _ contentsMorph smallThumbnailForPageSorter]\\n\\t\\tifFalse: [self updateThumbnail]! !\\n\\n!SqueakPage methodsFor: 'private' stamp: 'tk 6/24/1999 11:42'!\\npostChangeNotification\\n\\t\\\"Inform all thumbnails and books that this page has been updated.\\\"\\n\\n\\tURLMorph allSubInstancesDo: [:m | m pageHasChanged: self].\\n! !\\n\\n!SqueakPage methodsFor: 'private' stamp: 'jm 6/18/1998 11:31'!\\nupdateThumbnail\\n\\t\\\"Update my thumbnail from my morph.\\\"\\n\\n\\t| f scale scaleX scaleY shrunkF |\\n\\tcontentsMorph ifNil: [thumbnail _ nil. ^ self].\\n\\tf _ contentsMorph imageForm.\\n\\tscaleX _ MaxThumbnailWidthOrHeight asFloat / f height.\\n\\tscaleY _ MaxThumbnailWidthOrHeight asFloat/ f width.\\n\\tscale _ scaleX min: scaleY. \\\"choose scale that maintains aspect ratio\\\"\\n\\tshrunkF _ (f magnify: f boundingBox by: scale@scale smoothing: 2).\\n\\tthumbnail _ Form extent: shrunkF extent depth: 8. \\\"force depth to be 8\\\"\\n\\tshrunkF displayOn: thumbnail.\\n\\tcontentsMorph allMorphsDo: [:m | m releaseCachedState].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqueakPage class\\n\\tinstanceVariableNames: ''!\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'jm 6/18/1998 11:15'!\\ninitialize\\n\\t\\\"SqueakPage initialize\\\"\\n\\n\\tMaxThumbnailWidthOrHeight _ 60.\\n! !\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'sw 7/6/1998 11:49'!\\nnewURLAndPageFor: aMorph\\n\\t\\\"Create a new SqueakPage whose contents is the given morph. Assign a URL for that page, record it in the page cache, and answer its URL.\\\"\\n\\n\\t| pg newURL stamp |\\n\\tpg _ self new.\\n\\tstamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: aMorph author: stamp.\\n\\tnewURL _ SqueakPageCache generateURL.\\n\\tSqueakPageCache atURL: newURL put: pg.\\n\\t^ newURL \\n! !\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'tk 1/15/1999 08:13'!\\nstemUrl: aUrlString\\n\\t\\\"Peel off the 'x5.sp' or '.bo' from the end of a url of a SqueakPage or a BookMorph index file\\\"\\n\\n\\t| ll aUrl |\\n\\tll _ aUrlString findLast: [:char | char == $.].\\n\\tll = 0 \\n\\t\\tifTrue: [aUrl _ aUrlString]\\n\\t\\tifFalse: [aUrl _ aUrlString copyFrom: 1 to: ll-1].\\t\\\"remove .sp\\\"\\n\\taUrl _ (aUrl stemAndNumericSuffix) at: 1.\\n\\t\\t\\t\\\"remove trailing number\\\"\\n\\taUrl size = 0 ifTrue: [^ aUrl].\\t\\\"empty\\\"\\n\\t[aUrl last == $x] whileTrue: [aUrl _ aUrl allButLast].\\n\\t^ aUrl! !\\nObject subclass: #SqueakPageCache\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'GlobalPolicy PageCache'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n!SqueakPageCache commentStamp: '<historical>' prior: 0!\\nA global cache of web pages known to this Squeak image. Since there is a single, global page cache, it is implemented entirely as class methods.\\n\\nOnce a page has an entry, keep it. (url string -> A SqueakPage) The SqueakPage has a thumbnail and other info, but may not have the contentsMorph. The morph is purged when space is needed, and fetched from the server as needed.\\n\\nSee SqueakPage's comment for the stages of in/out.!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqueakPageCache class\\n\\tinstanceVariableNames: ''!\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'jm 6/25/1998 11:06'!\\nallURLs\\n\\t\\\"Answer a collection of URLs for all pages in the cache.\\\"\\n\\n\\t^ PageCache keys\\n\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/2/1998 12:07'!\\natURL: aURLString\\n\\t\\\"Answer the page corresponding to this URL. Evaluate the given block if there is no entry for the given URL.\\\"\\n\\n\\t| pg |\\n\\t^ PageCache at: aURLString ifAbsent: [\\n\\t\\tpg _ SqueakPage new.\\n\\t\\t\\\"stamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\\"\\n\\t\\t\\\"pg author: stamp.\\\"\\n\\t\\t\\\"Need to deal with inst vars if we turn out to be new!!\\\"\\n\\t\\t\\\"pg url: aURLString. \\tdone by atURL:put:\\\"\\n\\t\\tself atURL: aURLString put: pg.\\n\\t\\tpg]\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/2/1998 12:06'!\\natURL: aURLString ifAbsent: failBlock\\n\\t\\\"Answer the page corresponding to this URL. Evaluate the given block if there is no entry for the given URL.\\\"\\n\\n\\tself halt. \\\"use atURL:\\\"\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/20/1998 15:51'!\\natURL: aURLString oldPage: aPage\\n\\t\\\"Bring in page and return the object. First try looking up my url in the pageCache. Then try the page (and install it, under its url). Then start from scratch with the url.\\\"\\n\\n\\t| myPage |\\n\\t(myPage _ PageCache at: aURLString ifAbsent: [nil]) ifNotNil: [\\n\\t\\t^ myPage].\\n\\taPage url: aURLString.\\t\\\"for consistancy\\\"\\n\\tPageCache at: aPage url put: aPage.\\n\\t^ aPage! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 12/8/1998 21:51'!\\natURL: aURLString put: aSqueakPage\\n\\t\\\"Store the given page in the cache entry for the given URL.\\\"\\n\\n\\taSqueakPage url: aURLString.\\n\\taSqueakPage contentsMorph isInMemory ifTrue: [\\n\\t\\taSqueakPage contentsMorph ifNotNil: [\\n\\t\\t\\taSqueakPage contentsMorph setProperty: #SqueakPage \\n\\t\\t\\t\\ttoValue: aSqueakPage]].\\n\\tPageCache at: aURLString put: aSqueakPage.\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/30/1998 15:08'!\\ndoPagesInMemory: aBlock\\n\\t\\\"Evaluate aBlock for each page whose contentsMorph is in-memory. Don't add or remove pages while in this loop.\\\"\\n\\n\\tPageCache do: [:sqkPage |\\n\\t\\tsqkPage isContentsInMemory ifTrue: [aBlock value: sqkPage]].! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 11/24/1998 14:52'!\\ngenerateURL\\n\\t\\\"Generate an unused URL for an in-memory page.\\\"\\n\\t\\\"SqueakPageCache generateURL\\\"\\n\\n\\t| sd |\\n\\tsd _ ServerFile new on: 'file:./'.\\n\\tsd fileName: 'page1.sp'.\\n\\t^ SqueakPage new urlNoOverwrite: sd pathForFile\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/1/1998 13:02'!\\nincludesMorph: aPasteUp\\n\\n\\tPageCache do: [:squeakPage |\\n\\t\\tsqueakPage contentsMorph == aPasteUp ifTrue: [^ true]].\\n\\t^ false! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/20/1998 15:11'!\\npageCache\\n\\n\\t^ PageCache! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/1/1998 13:04'!\\npageForMorph: aPasteUp\\n\\n\\tPageCache do: [:squeakPage |\\n\\t\\tsqueakPage contentsMorph == aPasteUp ifTrue: [^ squeakPage]].\\n\\t^ nil! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 12/16/1998 08:30'!\\npurge\\n\\t\\\"Replace morphs with tombstones in all pages that are clean and not being shown. Write any dirty ones first, if allowed to.\\\"\\n\\n\\t| list |\\n\\tlist _ OrderedCollection new.\\n\\tGlobalPolicy == #neverWrite \\n\\t\\tifTrue: [PageCache doPagesInMemory: [:aPage | list add: aPage prePurge]]\\n\\t\\t\\t\\\"Writing only done by user's command\\\"\\n\\t\\tifFalse: [\\n\\t\\t\\tPageCache doPagesInMemory: [:aPage | aPage write\\n\\t\\t\\t\\t\\t list add: aPage prePurge]].\\n\\tlist _ list select: [:each | each notNil].\\n\\t\\\"do bulk become:\\\"\\n\\t(list collect: [:each | each contentsMorph])\\n\\t\\telementsExchangeIdentityWith:\\n\\t\\t\\t(list collect: [:pg | MorphObjectOut new xxxSetUrl: pg url page: pg])\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/21/1998 13:28'!\\npurge: megs\\n\\t\\\"Replace morphs with tombstones in all pages that are clean and not being shown. Do this until megs of new memory have been recovered. Write any dirty ones first, if allowed to.\\\"\\n\\n\\t| goal |\\n\\tgoal _ Smalltalk garbageCollect + (megs * 1000000) asInteger.\\n\\tPageCache doPagesInMemory: [:aPage | \\n\\t\\tGlobalPolicy == #neverWrite ifFalse: [aPage write].\\n\\t\\taPage purge.\\n\\t\\tSmalltalk garbageCollect > goal ifTrue: [^ true]].\\t\\\"got enough\\\"\\n\\t^ false\\t\\\"caller may want to tell the user to write out more pages\\\"! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'jm 6/16/1998 18:12'!\\nremoveURL: aURLString\\n\\t\\\"Remove the cache entry for the given URL. Do nothing if it has no cache entry.\\\"\\n\\n\\tPageCache removeKey: aURLString ifAbsent: [].\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/22/1998 11:07'!\\nwrite\\n\\t\\\"Write out all dirty pages\\\"\\n\\tGlobalPolicy == #neverWrite ifTrue: [^ self].\\n\\tself doPagesInMemory: [:aPage | aPage write].! !\\n\\n\\n!SqueakPageCache class methodsFor: 'class initialization' stamp: 'tk 11/24/1998 14:53'!\\ninitialize\\n\\t\\\"SqueakPageCache initialize\\\"\\n\\n\\tGlobalPolicy _ #neverWrite.\\n\\tPageCache _ Dictionary new: 100.\\n\\t\\t\\\"forgets urls of pages, but ObjectOuts still remember them\\\"\\n! !\\n\\n\\n!SqueakPageCache class methodsFor: 'housekeeping' stamp: 'tk 6/24/1999 11:42'!\\ndeleteUnreferencedPages\\n\\t\\\"Remove any pages that are not current referred to by any book or URL morph.\\\"\\n\\t\\\"Details: Since unreferenced pages could refer to other pages, this process is iterated until no unreferenced pages can be found. It currently does not collect cycles.\\\"\\n\\t\\\"SqueakPageCache deleteUnreferencedPages\\\"\\n\\n\\t| unreferenced |\\n\\t[true] whileTrue: [\\n\\t\\tSmalltalk garbageCollect.\\n\\t\\tunreferenced _ PageCache keys.\\n\\t\\tURLMorph allSubInstancesDo: [:m | unreferenced remove: m url ifAbsent: []].\\n\\t\\tMorphObjectOut allInstancesDo: [:ticklish |\\n\\t\\t\\tunreferenced remove: ticklish url ifAbsent: []].\\n\\t\\tunreferenced size = 0 ifTrue: [^ self].\\n\\t\\tunreferenced do: [:url | PageCache removeKey: url ifAbsent: []]].\\n! !\\n\\n!SqueakPageCache class methodsFor: 'housekeeping' stamp: 'jm 6/25/1998 13:00'!\\nreleaseCachedStateOfPages\\n\\t\\\"Note: This shouldn't be necessary if we are doing a good job of releasing cached state as we go. If running this doesn't do very much, we're doing well!!\\\"\\n\\t\\\"SqueakPageCache releaseCachedStateOfPages\\\"\\n\\n\\t| memBytes |\\n\\tmemBytes _ Smalltalk garbageCollect.\\n\\tPageCache do: [:pg |\\n\\t\\tpg contentsMorph allMorphsDo: [:m | m releaseCachedState]].\\n\\t^ (Smalltalk garbageCollect - memBytes) printString, ' bytes recovered'\\n! !\\nMorph subclass: #SquishedNameMorph\\n\\tinstanceVariableNames: 'target getSelector setSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Navigators'!\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:19'!\\ncolorAroundName\\n\\n\\t^Color gray: 0.8! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:18'!\\nfontForName\\n\\n\\t| pickem |\\n\\tpickem _ 3.\\n\\n\\tpickem = 1 ifTrue: [\\n\\t\\t^(((TextStyle named: #Helvetica) ifNil: [TextStyle default]) fontOfSize: 13) emphasized: 1.\\n\\t].\\n\\tpickem = 2 ifTrue: [\\n\\t\\t^(((TextStyle named: #Palatino) ifNil: [TextStyle default]) fontOfSize: 12) emphasized: 1.\\n\\t].\\n\\t^((TextStyle default) fontAt: 1) emphasized: 1\\n! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:17'!\\nisEditingName\\n\\n\\t^((self findA: UpdatingStringMorph) ifNil: [^false]) hasFocus\\n! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:32'!\\nstringToShow\\n\\n\\t(target isNil or: [getSelector isNil]) ifTrue: [^'????'].\\n\\t^target perform: getSelector! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:31'!\\ntarget: aTarget getSelector: symbol1 setSelector: symbol2\\n\\n\\ttarget _ aTarget.\\n\\tgetSelector _ symbol1.\\n\\tsetSelector _ symbol2.! !\\n\\n\\n!SquishedNameMorph methodsFor: 'drawing' stamp: 'RAA 11/11/2000 23:17'!\\ndrawOn: aCanvas\\n\\n\\t| font stringToShow nameForm rectForName |\\n\\n\\tsuper drawOn: aCanvas.\\n\\tself isEditingName ifTrue: [^self].\\n\\n\\tfont _ self fontForName.\\n\\tstringToShow _ self stringToShow.\\n\\tnameForm _ (StringMorph contents: stringToShow font: font) imageForm.\\n\\tnameForm _ nameForm scaledToSize: (self extent - (4@2) min: nameForm extent).\\n\\trectForName _ self bottomLeft + \\n\\t\\t\\t(self width - nameForm width // 2 @ (nameForm height + 2) negated)\\n\\t\\t\\t\\textent: nameForm extent.\\n\\trectForName topLeft eightNeighbors do: [ :pt |\\n\\t\\taCanvas\\n\\t\\t\\tstencil: nameForm \\n\\t\\t\\tat: pt\\n\\t\\t\\tcolor: self colorAroundName.\\n\\t].\\n\\taCanvas\\n\\t\\tstencil: nameForm \\n\\t\\tat: rectForName topLeft \\n\\t\\tcolor: Color black.\\n\\n\\n\\t\\n! !\\nObject subclass: #Stack\\n\\tinstanceVariableNames: 'linkedList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Stack'!\\n!Stack commentStamp: 'dc 7/24/2005 15:41' prior: 0!\\nI implement a simple Stack. #push: adds a new object of any kind on top of the stack. #pop returns the first element and remove it from the stack. #top answer the first element of the stack without removing it.!\\n\\n\\n!Stack methodsFor: 'accessing' stamp: 'dc 7/25/2005 10:04'!\\nsize\\n\\t\\\"How many objects in me ?\\\"\\n\\t^ self linkedList size! !\\n\\n!Stack methodsFor: 'accessing' stamp: 'sd 3/25/2006 15:05'!\\ntop\\n\\t\\\"Answer the first element of the stack without removing it.\\\"\\n\\tself notEmptyCheck.\\n\\t^ self linkedList first element! !\\n\\n\\n!Stack methodsFor: 'adding' stamp: 'dc 7/25/2005 10:22'!\\npush: anObject \\n\\t\\\"Adds a new object of any kind on top of the stack.\\\"\\n\\tself linkedList\\n\\t\\taddFirst: (StackLink with: anObject).\\n\\t^ anObject.! !\\n\\n\\n!Stack methodsFor: 'initialize-release' stamp: 'dc 7/25/2005 11:39'!\\ninitialize\\n\\tsuper initialize.\\n\\tlinkedList := LinkedList new! !\\n\\n\\n!Stack methodsFor: 'removing' stamp: 'dc 7/24/2005 16:16'!\\npop\\n\\t\\\"Returns the first element and remove it from the stack.\\\"\\n\\n\\tself notEmptyCheck.\\n\\t^self linkedList removeFirst element! !\\n\\n\\n!Stack methodsFor: 'testing' stamp: 'dc 7/25/2005 10:05'!\\nisEmpty\\n\\t^ self linkedList isEmpty! !\\n\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:05'!\\nerrorEmptyStack\\n\\tself error: 'this stack is empty'! !\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:20'!\\nlinkedList\\n\\t\\\"The stack is implemented with a LinkedList. Do NOT call this function, it \\n\\tis for private use !!\\\"\\n\\t^ linkedList! !\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:05'!\\nnotEmptyCheck\\n\\t\\\"Ensure the stack is not empty.\\\"\\n\\tself isEmpty\\n\\t\\tifTrue: [self errorEmptyStack]! !\\nLink subclass: #StackLink\\n\\tinstanceVariableNames: 'element'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Stack'!\\n!StackLink commentStamp: '<historical>' prior: 0!\\nI implement an element of a stack. I'm a container for any type of object, saved into the 'element' variable. My superclass Link allows me to be part of a LinkedList.!\\n\\n\\n!StackLink methodsFor: 'accessing' stamp: 'dc 7/24/2005 15:34'!\\nelement\\n\\t^element! !\\n\\n!StackLink methodsFor: 'accessing' stamp: 'dc 7/25/2005 10:16'!\\nelement: anObject \\n\\t\\\"Any kind of Object.\\\"\\n\\telement := anObject! !\\n\\n\\n!StackLink methodsFor: 'printing' stamp: 'dc 7/25/2005 10:15'!\\nprintOn: aStream \\n\\taStream nextPutAll: self class printString;\\n\\t\\t nextPutAll: ' with: ';\\n\\t\\t nextPutAll: self element printString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackLink class\\n\\tinstanceVariableNames: ''!\\n\\n!StackLink class methodsFor: 'instance creation' stamp: 'dc 7/25/2005 10:15'!\\nwith: anObject \\n\\t^ self new element: anObject! !\\nBookMorph subclass: #StackMorph\\n\\tinstanceVariableNames: 'cards'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Stacks'!\\n!StackMorph commentStamp: '<historical>' prior: 0!\\nA book that is very much like a HyperCard stack. \\n\\nEach book page represents a different background. The page stays while different cards are projected onto it. \\n\\tThe data for a single card is stored in a CardPlayer. There is a list of objects that only appear on this card (privateMorphs) and the card-specific text to be inserted into the background fields.\\n\\nItem\\t\\t\\t\\t\\tHow it is stored\\na background\\t\\t\\ta page of the StackMorph\\na card\\t\\t\\t\\t\\tdata is in an instance of a subclass of CardPlayer.\\n\\t\\t\\t\\t\\t\\tA list of CardPlayers is in the 'cards' inst var of the StackMorph.\\na background field\\t\\ta TextMorph on a page of the StackMorph\\na background picture\\ta morph of any kind on a page of the StackMorph\\nscript for bkgnd button\\t\\tmethod in Player. Button is its costume.\\ntext in a background field\\t\\tvalue of inst var 'field1' in a CardPlayer.\\n\\t\\t\\t\\t\\t\\t\\t\\t(The CardPlayer is also pointed at by the #cardInstance \\n\\t\\t\\t\\t\\t\\t\\t\\tproperty of the bkgnd field (TextMorph))\\ntext in a card field\\t\\tin the TextMorph in privateMorphs in the CardPlayer.\\npicture on a card\\t\\ta morph of any kind in privateMorphs in the CardPlayer.\\nscript for card button\\tmethod in the CardPlayer. Button is its costume.\\n\\nSee VariableDock.!\\n\\n\\n!StackMorph methodsFor: 'accessing' stamp: 'sw 11/2/2002 15:51'!\\ncardNumberOf: aPlayer\\n\\t\\\"Answer the card-number of the given player, in the which-card-of-the-stack sense.\\\"\\n\\n\\t^ self cards identityIndexOf: aPlayer ifAbsent: [0]! !\\n\\n!StackMorph methodsFor: 'accessing' stamp: 'sw 3/18/2002 02:09'!\\ncardsOrPages\\n\\t\\\"The turnable and printable entities\\\"\\n\\n\\t^ self cards! !\\n\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 10/23/2000 16:27'!\\ncommitCardData\\n\\t\\\"Make certain that the player data are written back to the player instance\\\"\\n\\n\\t^ self currentCard commitCardPlayerData \\n! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'em 3/31/2005 10:56'!\\ninsertCardOfBackground\\n\\t\\\"Prompt the user for choice of a background, and insert a new card of that background\\\"\\n\\n\\t| bgs aMenu aBackground |\\n\\t(bgs _ self backgrounds) size == 1 ifTrue:\\n\\t\\t[self inform: \\n'At this time, there IS only one kind of\\nbackground in this stack, so that''s\\nwhat you''ll get' translated.\\n\\t\\t^ self insertCard].\\n\\taMenu _ SelectionMenu\\n\\t\\tlabels: \\t\\t(bgs collect: [:bg | bg externalName])\\n\\t\\tselections: \\tbgs.\\n\\t(aBackground _ aMenu startUp) ifNotNil:\\n\\t\\t[self insertCardOfBackground: aBackground]! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 3/18/2002 02:02'!\\ninsertCardOfBackground: aBackground\\n\\t\\\"Insert a new card of the given background and have it become the current card\\\"\\n\\n\\t| newCard |\\n\\tnewCard _ aBackground newCard.\\n\\tself privateCards add: newCard after: self currentCard.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 10/30/2000 10:08'!\\nopenInsideLook\\n\\t\\\"Open an inside-look at the current page. This is a previously-demoed feature not presently incorporated in released code,\\\"\\n\\n\\ttrue ifTrue: [self notYetImplemented] ifFalse: [self currentPage openInsideLook]\\n! !\\n\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromAFile\\n\\t\\\"Using the current background, create new cards by reading in data from a fileThe data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\t| aFileStream |\\n\\t(aFileStream _ FileList2 modalFileSelector) ifNil: [^ Beeper beep].\\n\\tself addCardsFromString: aFileStream contentsOfEntireFile.\\n\\taFileStream close! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromClipboardData\\n\\t\\\"Using the current background, paste data from the (textual) clipboard to create new records. The data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\t| clip |\\n\\t(clip _ Clipboard clipboardText) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: clip! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromClipboardDataForInstanceVariables: slotNames\\n\\t\\\"Using the current background, paste data from the (textual) clipboard to create new records. No senders, but can be usefully called manually for selectively bringing in data in oddball format.\\\"\\n\\n\\t| clip |\\n\\t(clip _ Clipboard clipboardText) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: clip slotNames: slotNames! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromFile: fileStream\\n\\t\\\"Using the current background, take tab delimited data from the file to create new records.\\\"\\n\\n\\t| aString |\\n\\t(aString _ fileStream contentsOfEntireFile) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: aString! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/18/2001 11:35'!\\naddCardsFromString: aString\\n\\t\\\"Using the current background, add cards from a string, which is expected be tab- and return-delimited. The data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\tself addCardsFromString: aString slotNames: self currentCard slotNames\\n \\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'em 3/31/2005 10:23'!\\naddCardsFromString: aString slotNames: slotNames \\n\\t\\\"Using the current background, add cards from a string, which is expected be tab- and return-delimited\\\"\\n\\n\\t| count |\\n\\tcount := 0.\\n\\taString asString linesDo: \\n\\t\\t\\t[:aLine | \\n\\t\\t\\taLine notEmpty \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[count := count + 1.\\n\\t\\t\\t\\t\\tself \\n\\t\\t\\t\\t\\t\\tinsertCardOfBackground: self currentPage\\n\\t\\t\\t\\t\\t\\twithDataFrom: aLine\\n\\t\\t\\t\\t\\t\\tforInstanceVariables: slotNames]].\\n\\tself inform: count asString , ' card(s) added' translated! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 10/26/2000 14:41'!\\nbackgroundWithCard: aCard\\n\\t\\\"Answer the background which contains aCard.\\\"\\n\\n\\t^ self backgrounds detect:\\n\\t\\t[:aBackground | aBackground containsCard: aCard] ifNone: [nil]! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 10/30/2000 10:04'!\\nbackgrounds\\n\\t\\\"Answer the list of backgrounds available in the receiver\\\"\\n\\n\\t^ self pages! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/6/2001 21:26'!\\nbeDefaultsForNewCards\\n\\t\\\"Make the values that I see here all be accepted as defaults for new cards\\\"\\n\\n\\tself currentPage submorphs do:\\n\\t\\t[:aMorph | aMorph holdsSeparateDataForEachInstance ifTrue:\\n\\t\\t\\t[aMorph setAsDefaultValueForNewCard]]! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 11/2/2002 17:56'!\\nchangeInstVarOrder\\n\\t\\\"Change the order of the receiver's instance variables\\\"\\n\\n\\t| reply |\\n\\treply _ FillInTheBlank request: 'rearrange, then accept; or cancel' initialAnswer:\\n\\t\\t((self currentPage player class instVarNames asArray collect: [:v | v asSymbol]) storeString copyWithoutAll: #($# $( $))) asString.\\n\\treply isEmptyOrNil ifTrue: [^ self].\\n\\tself flag: #deferred. \\\"Error checking and graceful escape wanted\\\"\\n\\tself currentPage player class resortInstanceVariables: (Compiler evaluate:\\n\\t\\t('#(', reply, ')'))! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'em 3/30/2005 14:47'!\\ninsertAsBackground: newPage resize: doResize\\n\\t\\\"Make a new background for the stack. Obtain a name for it from the user. It starts out life empty\\\"\\n\\n\\t| aName |\\n\\taName _ FillInTheBlank request: 'What should we call this new background?' translated initialAnswer: 'alternateBackground' translated.\\n\\taName isEmptyOrNil ifTrue: [^ self].\\n\\tnewPage beSticky.\\n\\tdoResize ifTrue: [newPage extent: currentPage extent].\\n\\tnewPage beAStackBackground.\\n\\tnewPage setNameTo: aName.\\n\\tnewPage vResizeToFit: false.\\n\\tpages isEmpty\\n\\t\\tifTrue: [pages add: newPage]\\n\\t\\tifFalse: [pages add: newPage after: currentPage].\\n\\tself privateCards add: newPage currentDataInstance after: currentPage currentDataInstance.\\n\\tself nextPage.\\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'tk 10/30/2001 19:01'!\\nmakeNewBackground\\n\\t\\\"Make a new background for the stack. Obtain a name for it from the user. It starts out life empty\\\"\\n\\n\\t| newPage |\\n\\t(newPage _ PasteUpMorph newSticky) color: self color muchLighter.\\n\\tnewPage borderWidth: currentPage borderWidth; borderColor: currentPage borderColor.\\n\\tself insertAsBackground: newPage resize: true. \\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 3/18/2002 02:14'!\\nsortByField: varName\\n\\t\\\"Perform a simple reordering of my cards, sorting by the given field name. If there are multiple backgrounds, then sort the current one, placing all its cards first, followed by all others in unchanged order\\\"\\n\\n\\t| holdCards thisClassesInstances sortedList |\\n\\tholdCards _ self privateCards copy.\\n\\n\\tthisClassesInstances _ self privateCards select: [:c | c isKindOf: self currentCard class].\\n\\tsortedList _ thisClassesInstances asSortedCollection:\\n\\t\\t[:a :b | (a instVarNamed: varName) asString <= (b instVarNamed: varName) asString].\\n\\tsortedList _ sortedList asOrderedCollection.\\n\\tholdCards removeAllFoundIn: sortedList.\\n\\tself privateCards: (sortedList asOrderedCollection, holdCards).\\n\\tself goToFirstCardOfStack\\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/6/2001 22:08'!\\nsortCards\\n\\t\\\"Let the user provide an inst var on which to sort the cards of a background.\\\"\\n\\n\\t| names aMenu |\\n\\tnames _ self currentPage player class instVarNames.\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Choose field by which to sort:'.\\n\\tnames do: [:n | aMenu add: n selector: #sortByField: argument: n].\\n\\taMenu popUpInWorld! !\\n\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 10/23/2000 16:24'!\\nbrowseCardClass\\n\\t\\\"Browse the class of the current card\\\"\\n\\n\\t| suffix |\\n\\tsuffix _ self currentCard class name numericSuffix.\\n\\tHierarchyBrowser newFor: self currentCard class labeled: 'Background ', suffix asString\\n! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:20'!\\ncardIndexOf: aCard\\n\\t\\\"Answer the ordinal position of aCard in the receiver's list\\\"\\n\\n\\t^ self privateCards indexOf: aCard ifAbsent: [nil]! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:12'!\\ncards\\n\\t\\\"Answer a list of the cards of the receiver, in order\\\"\\n\\n\\t^ self privateCards copy! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 10/23/2000 16:27'!\\ncurrentCard\\n\\t\\\"Answer the current card of the current background of the receiver\\\"\\n\\n\\t^ currentPage currentDataInstance! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'em 3/31/2005 10:24'!\\ndeleteAllCardsExceptThisOne\\n\\t\\\"Delete all cards except the current one\\\"\\n\\n\\tself privateCards size <= 1 ifTrue: [^ Beeper beep].\\n\\t(self confirm: 'Really delete ' translated, self privateCards size asString, ' card(s) and all of their data?' translated) ifTrue:\\n\\t\\t[self privateCards: (OrderedCollection with: self currentCard)].! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sd 11/13/2003 21:03'!\\ndeleteCard\\n\\t\\\"Delete the current card from the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards size = 1 ifTrue: [^ Beeper beep].\\n\\t(self confirm: 'Really delete this card and all of its data?' translated) ifTrue:\\n\\t\\t[self goToNextCardInStack.\\n\\t\\tself privateCards remove: aCard].! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ndeleteCard: aCard\\n\\t\\\"Delete the current card from the stack.\\\"\\n\\n\\tself privateCards size = 1 ifTrue: [^ Beeper beep].\\n\\t(aCard == self currentCard) ifTrue: [^ self deleteCard].\\n\\n\\tself privateCards remove: aCard ifAbsent: []! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'em 3/31/2005 10:23'!\\ngoToCard\\n\\t\\\"prompt the user for an ordinal number, and use that as a basis for choosing a new card to install in the receiver\\\"\\n\\n\\t| reply index |\\n\\treply _ FillInTheBlank request: 'Which card number? ' translated initialAnswer: '1'.\\n\\treply isEmptyOrNil ifTrue: [^ self].\\n\\t((index _ reply asNumber) > 0 and: [index <= self privateCards size])\\n\\t\\tifFalse: [^ self inform: 'no such card'].\\n\\tself goToCard: (self privateCards at: index)! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 11/8/2002 15:15'!\\ngoToCard: destinationCard\\n\\t\\\"Install the indicated destinationCard as the current card in the receiver. Any viewer currently open on the current card will get retargeted to look at the new one.\\\"\\n\\n\\t| aBackground existingCard oldViewers |\\n\\tdestinationCard == self currentCard ifTrue: [^ self].\\n\\tself currentPlayerDo:\\n\\t\\t[:aPlayer | aPlayer runAllClosingScripts]. \\\"Like HyperCard 'on closeCard'\\\"\\n\\n\\taBackground _ self backgroundWithCard: destinationCard.\\n\\texistingCard _ aBackground currentDataInstance.\\n\\toldViewers _ existingCard ifNil: [#()] ifNotNil: [existingCard allOpenViewers].\\n\\n\\taBackground installAsCurrent: destinationCard.\\n\\taBackground setProperty: #myStack toValue: self.\\t\\\"pointer cardMorph -> stack\\\"\\n\\n\\taBackground ~~ currentPage ifTrue:\\n\\t\\t[self goToPageMorph: aBackground runTransitionScripts: false].\\n\\tself currentPlayerDo:\\n\\t\\t[:aPlayer | aPlayer runAllOpeningScripts] . \\\"Like HyperCard 'on opencard'\\\"\\n\\n\\toldViewers do: [:aViewer | aViewer retargetFrom: existingCard to: destinationCard]! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 11/11/2002 03:07'!\\ngoToCardNumber: aCardNumber\\n\\t\\\"Install the card whose ordinal number is provided as the current card in the stack\\\"\\n\\n\\tself goToCard: (self privateCards atWrap: aCardNumber)! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ngoToFirstCardInBackground\\n\\t\\\"Install the initial card in the current background as the current card in the stack\\\"\\n\\n\\t| kind |\\n\\tkind _ currentPage player class baseUniclass.\\n\\tself goToCard: (self privateCards detect: [:aCard | aCard isKindOf: kind] ifNone: [^ Beeper beep])! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:01'!\\ngoToFirstCardOfStack\\n\\t\\\"Install the initial card in the stack as the current card\\\"\\n\\n\\tself goToCard: self privateCards first! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ngoToLastCardInBackground\\n\\t\\\"Install the final card in the current background as the current card\\\"\\n\\n\\t| kind |\\n\\tkind _ currentPage player class baseUniclass.\\n\\tself goToCard: (self privateCards reversed detect: [:aCard | aCard isKindOf: kind] ifNone: [^ Beeper beep])! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:09'!\\ngoToLastCardOfStack\\n\\t\\\"Install the final card in the stack as the current card\\\"\\n\\n\\tself goToCard: self privateCards last! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:03'!\\ninsertCardOfBackground: aBackground withDataFrom: aLine forInstanceVariables: slotNames\\n\\t\\\"Insert a new card of the given background and have it become the current card. \\\"\\n\\n\\t| newCard |\\n\\tnewCard _ aBackground newCard.\\n\\tself privateCards add: newCard after: self currentCard.\\n\\tnewCard absorbBackgroundDataFrom: aLine forInstanceVariables: slotNames.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 01:57'!\\nmakeCurrentCardFirstInStack\\n\\t\\\"Move the current card such that it becomes the first card in the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards remove: aCard ifAbsent: [];\\n\\t\\taddFirst: aCard.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:03'!\\nmakeCurrentCardLastInStack\\n\\t\\\"Move the current card such that it becomes the last card in the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards remove: aCard ifAbsent: [];\\n\\t\\taddLast: aCard.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:08'!\\nmoveCardOnePositionEarlier\\n\\t\\\"Move the current card such that its ordinal position is one fewer than it formerly was. If the current card is already the first one one in the stack, then do nothing\\\"\\n\\n\\t| aCard aPosition |\\n\\taCard _ self currentCard.\\n\\taCard == self privateCards first ifTrue: [^ self].\\n\\taPosition _ self privateCards indexOf: aCard.\\n\\tself privateCards remove: aCard;\\n\\t\\tadd: aCard afterIndex: (aPosition - 2).\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:05'!\\nmoveCardOnePositionLater\\n\\t\\\"Move the current card such that its ordinal position is one greater than it formerly was. If the current card is already the last one one in the stack, then do nothing\\\"\\n\\n\\t| aCard aPosition privateCards |\\n\\taCard _ self currentCard.\\n\\tprivateCards _ self privateCards.\\n\\taCard == privateCards last ifTrue: [^ self].\\n\\taPosition _ privateCards indexOf: aCard.\\n\\tprivateCards remove: aCard.\\n\\tprivateCards add: aCard afterIndex: aPosition.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 01:56'!\\nprivateCards\\n\\t\\\"Private - answer the collection object that sits in my cards instance variable\\\"\\n\\n\\t^ cards! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:51'!\\nprivateCards: aCollection\\n\\t\\\"Private - Make my cards be te given colllection\\\"\\n\\n\\tcards _ aCollection! !\\n\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:03'!\\nexplainDesignations\\n\\t\\\"Give the user an explanation of what the designations mean\\\"\\n\\n\\tself currentPage explainDesignations\\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 3/18/2002 02:03'!\\ngoToNextCardInStack\\n\\t\\\"Make the card *after* the current card become the current card\\\"\\n\\n\\t| anIndex newCard |\\n\\tanIndex _ self privateCards indexOf: currentPage currentDataInstance.\\n\\tnewCard _ self privateCards atWrap: anIndex + 1.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 3/18/2002 02:01'!\\ngoToPreviousCardInStack\\n\\t\\\"Install the previous card as my current one\\\"\\n\\n\\t| anIndex newCard |\\n\\tanIndex _ self privateCards indexOf: currentPage currentDataInstance.\\n\\tnewCard _ self privateCards atWrap: anIndex - 1.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 16:02'!\\ninsertCard\\n\\t\\\"Create a new card of the current background and make it become the current card\\\"\\n\\n\\tself insertCardOfBackground: currentPage! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'tk 10/5/2001 06:27'!\\nreassessBackgroundShape\\n\\t\\\"Have the current page reconsider its cards' instance structure\\\"\\n\\n\\tcurrentPage setProperty: #myStack toValue: self. \\t\\\"pointer cardMorph -> stack\\\"\\n\\t^ self currentPage reassessBackgroundShape \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:04'!\\nrelaxGripOnVariableNames\\n\\t\\\"Have the current background relax its grip on existing variable name\\\"\\n\\n\\t^ self currentPage relaxGripOnVariableNames \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:15'!\\nreshapeBackground\\n\\t\\\"Abandon any memory of variable-name preferences for the current background, and reassess its instance structure\\\"\\n\\n\\t^ self currentPage reshapeBackground \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:10'!\\nshowDesignationsOfObjects\\n\\t\\\"Momentarily show which objects on the current card belong to which designation category\\\"\\n\\n\\tself currentPage showDesignationsOfObjects\\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 17:37'!\\nstackDo: aBlock\\n\\t\\\"Evaluate aBlock on behalf of the receiver stack\\\"\\n\\n\\t^ aBlock value: self! !\\n\\n\\n!StackMorph methodsFor: 'controls' stamp: 'sw 10/30/2000 16:31'!\\npageControlsMorphFrom: controlSpecs\\n\\t\\\"Answer a controls morph derived from the spec supplied\\\"\\n\\n\\t| controls |\\n\\tcontrols _ super pageControlsMorphFrom: controlSpecs.\\n\\tcontrols eventHandler: nil. \\\"not grabbable\\\"\\n\\t^ controls! !\\n\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/30/2000 10:13'!\\ninspectCurrentBackground\\n\\t\\\"Open an inspector on the corrent background. Ideally should put include the background name in the inspector's title.\\\"\\n\\n\\t^ self currentPage inspectWithLabel: 'A Background'\\n! !\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/23/2000 16:37'!\\ninspectCurrentCard\\n\\t\\\"For debugging: open an Inspector on the receiver's current card\\\"\\n\\n\\t^ self currentCard inspectWithLabel: 'A Card'\\n! !\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/30/2000 10:09'!\\ninspectCurrentStack\\n\\t\\\"Triggered from the stack-debug menu, open an Inspector on the receiver\\\"\\n\\n\\t^ self inspectWithLabel: 'A Stack'\\n! !\\n\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 6/5/2003 04:04'!\\naddPane: aPane paneType: aType\\n\\n\\t| anIndex |\\n\\n\\tanIndex _ self insertionIndexForPaneOfType: aType.\\n\\n\\tself privateAddMorph: aPane atIndex: anIndex! !\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 3/18/2002 02:12'!\\ninitialize\\n\\t\\\"Initialize the stack\\\"\\n\\n\\t| initialBackground |\\n\\tsuper initialize.\\n\\tinitialBackground _ pages first.\\n\\tinitialBackground extent: (640@480); beSticky.\\n\\tinitialBackground beAStackBackground.\\n\\tself beUnsticky.\\n\\tself setProperty: #controlsAtBottom toValue: true.\\n\\tself privateCards: (OrderedCollection with: initialBackground currentDataInstance).\\n\\n\\\"self currentHand attachMorph: StackMorph authoringPrototype\\\"! !\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 3/18/2002 02:13'!\\ninitializeWith: aCardMorph\\n\\t\\\"Install the card inside a new stack. Make no border or controls, so I the card's look is unchanged. Card already has a CardPlayer.\\\"\\n\\t\\n\\t| wld |\\n\\twld _ aCardMorph world.\\n\\tself initialize.\\n\\tself pageSize: aCardMorph extent.\\n\\tself borderWidth: 0; layoutInset: 0; color: Color transparent.\\n\\tpages _ Array with: aCardMorph.\\n\\tcurrentPage _ aCardMorph.\\n\\tself privateCards: (OrderedCollection with: currentPage currentDataInstance).\\n\\tcurrentPage beAStackBackground.\\n\\tself position: aCardMorph position.\\n\\tsubmorphs last delete.\\n\\tself addMorph: currentPage.\\t\\n\\tself showPageControls: self fullControlSpecs.\\n\\twld addMorph: self.\\n! !\\n\\n\\n!StackMorph methodsFor: 'insert and delete' stamp: 'sw 10/30/2000 10:10'!\\ndefaultNameStemForNewPages\\n\\t\\\"Answer the stem to use as the default for names of cards in the stack\\\"\\n\\n\\t^ 'card'\\n! !\\n\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:14'!\\naddBookMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Add book-related items to the given menu\\\"\\n\\n\\t| controlsShowing subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'previous card' translated action: #goToPreviousCardInStack.\\n\\tsubMenu add: 'next card' translated action: #goToNextCardInStack.\\n\\tsubMenu add: 'go to card...' translated action: #goToCard.\\n\\tsubMenu add: 'insert a card' translated action: #insertCard.\\n\\tsubMenu add: 'delete this card' translated action: #deleteCard.\\n\\n\\tcontrolsShowing _ self hasSubmorphWithProperty: #pageControl.\\n\\tcontrolsShowing\\n\\t\\tifTrue:\\n\\t\\t\\t[subMenu add: 'hide card controls' translated action: #hidePageControls.\\n\\t\\t\\tsubMenu add: 'fewer card controls' translated action: #fewerPageControls]\\n\\t\\tifFalse:\\n\\t\\t\\t[subMenu add: 'show card controls' translated action: #showPageControls].\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'sound effect for all backgrounds' translated action: #menuPageSoundForAll:.\\n\\tsubMenu add: 'sound effect this background only' translated action: #menuPageSoundForThisPage:.\\n\\tsubMenu add: 'visual effect for all backgrounds' translated action: #menuPageVisualForAll:.\\n\\tsubMenu add: 'visual effect this background only' translated action: #menuPageVisualForThisPage:.\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'sort pages' translated action: #sortPages:.\\n\\tsubMenu add: 'uncache page sorter' translated action: #uncachePageSorter.\\n\\t(self hasProperty: #dontWrapAtEnd)\\n\\t\\tifTrue: [subMenu add: 'wrap after last page' translated selector: #setWrapPages: argument: true]\\n\\t\\tifFalse: [subMenu add: 'stop at last page' translated selector: #setWrapPages: argument: false].\\n\\n\\tsubMenu addUpdating: #showingFullScreenString action: #toggleFullScreen.\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'search for text' translated action: #textSearch.\\n\\t(self primaryHand pasteBuffer class isKindOf: PasteUpMorph class) ifTrue:\\n\\t\\t[subMenu add: 'paste book page' translated action: #pasteBookPage].\\n\\n\\tsubMenu add: 'send all pages to server' translated action: #savePagesOnURL.\\n\\tsubMenu add: 'send this page to server' translated action: #saveOneOnURL.\\n\\tsubMenu add: 'reload all from server' translated action: #reload.\\n\\tsubMenu add: 'copy page url to clipboard' translated action: #copyUrl.\\n\\tsubMenu add: 'keep in one file' translated action: #keepTogether.\\n\\tsubMenu add: 'save as new-page prototype' translated action: #setNewPagePrototype.\\n\\tnewPagePrototype ifNotNil:\\n\\t\\t[subMenu add: 'clear new-page prototype' translated action: #clearNewPagePrototype].\\n\\n\\taMenu add: 'book...' translated subMenu: subMenu\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:06'!\\nfindText: wants\\n\\t\\\"Turn to the next card that has all of the strings mentioned on it. Highlight where it is found. allText and allTextUrls have been set. Case insensitive search.\\n\\tResuming a search. If container's text is still in the list and secondary keys are still in the page, (1) search rest of that container. (2) search rest of containers on that page (3) pages till end of book, (4) from page 1 to this page again.\\\"\\n\\n\\t\\\"Later sort wants so longest key is first\\\"\\n\\t| allText good thisWord here fromHereOn startToHere oldContainer oldIndex otherKeys strings |\\n\\tallText _ self valueOfProperty: #allText ifAbsent: [#()].\\n\\there _ self privateCards identityIndexOf: self currentCard ifAbsent: [1].\\n\\tfromHereOn _ here+1 to: self privateCards size.\\n\\tstartToHere _ 1 to: here.\\t\\t\\\"repeat this page\\\"\\n\\t(self valueOfProperty: #searchKey ifAbsent: [#()]) = wants ifTrue: [\\n\\t\\t\\\"does page have all the other keys? No highlight if found!!\\\"\\n\\t\\totherKeys _ wants allButFirst.\\n\\t\\tstrings _ allText at: here.\\n\\t\\tgood _ true.\\n\\t\\totherKeys do: [:searchString | \\\"each key\\\"\\n\\t\\t\\tgood ifTrue: [thisWord _ false.\\n\\t\\t\\t\\tstrings do: [:longString |\\n\\t\\t\\t\\t\\t(longString findWordStart: searchString startingAt: 1) > 0 ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tthisWord _ true]].\\n\\t\\t\\t\\tgood _ thisWord]].\\n\\t\\tgood ifTrue: [\\\"all are on this page. Look in rest for string again.\\\"\\n\\t\\t\\toldContainer _ self valueOfProperty: #searchContainer.\\n\\t\\t\\toldIndex _ self valueOfProperty: #searchOffset.\\n\\t\\t\\t(self findText: (OrderedCollection with: wants first) inStrings: strings\\t\\n\\t\\t\\t\\tstartAt: oldIndex+1 container: oldContainer \\n\\t\\t\\t\\tcardNum: here) ifTrue: [\\n\\t\\t\\t\\t\\tself setProperty: #searchKey toValue: wants.\\n\\t\\t\\t\\t\\t^ true]]]\\n\\t\\tifFalse: [fromHereOn _ here to: self privateCards size].\\t\\\"do search this page\\\"\\n\\t\\\"other pages\\\"\\n\\tfromHereOn do: [:cardNum |\\n\\t\\t(self findText: wants inStrings: (allText at: cardNum) startAt: 1 container: nil \\n\\t\\t\\t\\tcardNum: cardNum) \\n\\t\\t\\t\\t\\tifTrue: [^ true]].\\n\\tstartToHere do: [:cardNum |\\n\\t\\t(self findText: wants inStrings: (allText at: cardNum) startAt: 1 container: nil \\n\\t\\t\\t\\tcardNum: cardNum) \\n\\t\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"if fail\\\"\\n\\tself setProperty: #searchContainer toValue: nil.\\n\\tself setProperty: #searchOffset toValue: nil.\\n\\tself setProperty: #searchKey toValue: nil.\\n\\t^ false! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'gm 2/22/2003 13:13'!\\nfindText: keys inStrings: rawStrings startAt: startIndex container: oldContainer cardNum: cardNum \\n\\t\\\"Call once to search a card of the stack. Return true if found and highlight the text. oldContainer should be NIL. \\n\\t(oldContainer is only non-nil when (1) doing a 'search again' and (2) the page is in memory and (3) keys has just one element. oldContainer is a TextMorph.)\\\"\\n\\n\\t| good thisWord index insideOf place container start strings old |\\n\\tgood := true.\\n\\tstart := startIndex.\\n\\tstrings := oldContainer ifNil: \\n\\t\\t\\t\\t\\t[\\\"normal case\\\"\\n\\n\\t\\t\\t\\t\\trawStrings]\\n\\t\\t\\t\\tifNotNil: [self currentPage allStringsAfter: oldContainer text].\\n\\tkeys do: \\n\\t\\t\\t[:searchString | \\n\\t\\t\\t\\\"each key\\\"\\n\\n\\t\\t\\tgood \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[thisWord := false.\\n\\t\\t\\t\\t\\tstrings do: \\n\\t\\t\\t\\t\\t\\t\\t[:longString | \\n\\t\\t\\t\\t\\t\\t\\t(index := longString findWordStart: searchString startingAt: start) > 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[thisWord not & (searchString == keys first) \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[insideOf := longString.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tplace := index].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthisWord := true].\\n\\t\\t\\t\\t\\t\\t\\tstart := 1].\\t\\\"only first key on first container\\\"\\n\\t\\t\\t\\t\\tgood := thisWord]].\\n\\tgood \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"all are on this page\\\"\\n\\n\\t\\t\\t\\\"wasIn _ (pages at: pageNum) isInMemory.\\\"\\n\\n\\t\\t\\tself goToCardNumber: cardNum\\n\\t\\t\\t\\\"wasIn ifFalse: ['search again, on the real current text. Know page is in.'.\\n\\t\\t\\t^ self findText: keys \\n\\t\\t\\t\\tinStrings: ((pages at: pageNum) allStringsAfter: nil) recompute it\\t\\n\\t\\t\\t\\tstartAt: startIndex container: oldContainer \\n\\t\\t\\t\\tpageNum: pageNum]\\\"].\\n\\t(old := self valueOfProperty: #searchContainer) ifNotNil: \\n\\t\\t\\t[(old respondsTo: #editor) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[old editor selectFrom: 1 to: 0.\\t\\\"trying to remove the previous selection!!\\\"\\n\\t\\t\\t\\t\\told changed]].\\n\\tgood \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"have the exact string object\\\"\\n\\n\\t\\t\\t(container := oldContainer) ifNil: \\n\\t\\t\\t\\t\\t[container := self \\n\\t\\t\\t\\t\\t\\t\\t\\thighlightText: keys first\\n\\t\\t\\t\\t\\t\\t\\t\\tat: place\\n\\t\\t\\t\\t\\t\\t\\t\\tin: insideOf]\\n\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t[container userString == insideOf \\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[container := self \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thighlightText: keys first\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tat: place\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: insideOf]\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[(container isTextMorph) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[container editor selectFrom: place to: keys first size - 1 + place.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcontainer changed]]].\\n\\t\\t\\tself setProperty: #searchContainer toValue: container.\\n\\t\\t\\tself setProperty: #searchOffset toValue: place.\\n\\t\\t\\tself setProperty: #searchKey toValue: keys.\\t\\\"override later\\\"\\n\\t\\t\\tActiveHand newKeyboardFocus: container.\\n\\t\\t\\t^true].\\n\\t^false! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'em 3/31/2005 10:20'!\\nfindViaTemplate\\n\\t| list pl cardInst |\\n\\t\\\"Current card is the template. Only search cards in this background. Look at cards directly (not allText). Key must be found in the same field as in the template. HyperCard style (multiple starts of words). \\n\\tPut results in a list, outside the stack.\\\"\\n\\n\\tlist _ self templateMatches.\\n\\tlist isEmpty ifTrue: [^ self inform: 'No matches were found.\\nBe sure the current card is mostly blank\\nand only has text you want to match.' translated]. \\n\\t\\\"put up a PluggableListMorph\\\"\\n\\tcardInst _ self currentCard.\\n\\tcardInst matchIndex: 0.\\t\\\"establish entries\\\"\\n\\tcardInst results at: 1 put: list.\\n\\tself currentPage setProperty: #myStack toValue: self.\\t\\\"way to get back\\\"\\n\\n\\tpl _ PluggableListMorph new\\n\\t\\t\\ton: cardInst list: #matchNames\\n\\t\\t\\tselected: #matchIndex changeSelected: #matchIndex:\\n\\t\\t\\tmenu: nil \\\"#matchMenu:shifted:\\\" keystroke: nil.\\n\\tActiveHand attachMorph: (self formatList: pl).\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'tk 6/2/2001 11:40'!\\nformatList: pl\\n\\t| rr ff |\\n\\t\\\"Turn this plugglable list into a good looking morph.\\\"\\n\\n\\tpl color: Color transparent; borderWidth: 0.\\n\\tpl font: ((TextStyle named: #Palatino) fontOfSize: 14).\\n\\tpl toggleCornerRounding; width: 252; retractableOrNot; hResizing: #spaceFill.\\n\\trr _ (RectangleMorph new) toggleCornerRounding; extent: pl extent + (30@30).\\n\\trr color: self currentPage color; fillStyle: (ff _ self currentPage fillStyle copy).\\n\\tff isGradientFill ifTrue: [\\n\\t\\trr fillStyle direction: (ff direction * self currentPage extent / rr extent) rounded.\\n\\t\\trr fillStyle origin: rr bounds origin].\\n\\trr addMorph: pl.\\n\\trr layoutPolicy: TableLayout new.\\n\\trr layoutInset: 10@15; cellInset: 10@15; wrapDirection: #leftToRight.\\n\\trr listCentering: #center; borderWidth: 5; borderColor: #raised.\\n\\t\\\"Up and down buttons on left with arrows in a holder.\\\"\\n\\t\\\"lb _ (RectangleMorph new) color: transparent; borderWidth: 0.\\\"\\n\\t^ rr! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:07'!\\ngetAllText\\n\\t\\\"Collect the text for each card. Just point at strings so don't have to recopy them. (Parallel array of urls for ID of cards. Remote cards not working yet.)\\n\\tallText = Array (cards size) of arrays (fields in it) of strings of text.\\n\\tallTextUrls = Array (cards size) of urls or card numbers.\\\"\\n\\n\\t| oldUrls oldStringLists allText allTextUrls aUrl which |\\n\\tself writeSingletonData.\\n\\toldUrls _ self valueOfProperty: #allTextUrls ifAbsent: [#()].\\n\\toldStringLists _ self valueOfProperty: #allText ifAbsent: [#()].\\n\\tallText _ self privateCards collect: [:pg | OrderedCollection new].\\n\\tallTextUrls _ Array new: self privateCards size.\\n\\tself privateCards doWithIndex: [:aCard :ind | aUrl _ aCard url. aCard isInMemory \\n\\t\\tifTrue: [(allText at: ind) addAll: (aCard allStringsAfter: nil).\\n\\t\\t\\taUrl ifNil: [aUrl _ ind].\\n\\t\\t\\tallTextUrls at: ind put: aUrl]\\n\\t\\tifFalse: [\\\"Order of cards on server may be different. (later keep up to date?)\\\"\\n\\t\\t\\t\\\"*** bug in this algorithm if delete a page?\\\"\\n\\t\\t\\twhich _ oldUrls indexOf: aUrl.\\n\\t\\t\\tallTextUrls at: ind put: aUrl.\\n\\t\\t\\twhich = 0 ifFalse: [allText at: ind put: (oldStringLists at: which)]]].\\n\\tself setProperty: #allText toValue: allText.\\n\\tself setProperty: #allTextUrls toValue: allTextUrls.\\n\\t^ allText! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 9/29/2004 20:47'!\\ninvokeBookMenu\\n\\t\\\"Invoke the book's control panel menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack' translated.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList: {\\n\\t\\t{'find...' translated.\\t\\t\\t\\t\\t#textSearch}.\\n\\t\\t{'find via this template' translated.\\t\\t\\t#findViaTemplate}.\\n\\t\\t{'show designations' translated. \\t\\t\\t#showDesignationsOfObjects}.\\n\\t\\t{'explain designations' translated.\\t\\t\\t#explainDesignations}.\\n\\t\\t#-.\\n\\t\\t{'previous card' translated. \\t\\t\\t\\t#goToPreviousCardInStack}.\\n\\t\\t{'next card' translated. \\t\\t\\t\\t#goToNextCardInStack}.\\n\\t\\t{'first card' translated. \\t\\t\\t\\t#goToFirstCardOfStack}.\\n\\t\\t{'last card' translated. \\t\\t\\t\\t#goToLastCardOfStack}.\\n\\t\\t{'go to card...' translated. \\t\\t\\t\\t#goToCard}.\\n\\t\\t#-.\\n\\t\\t{'add a card of this background' translated. \\t\\t#insertCard}.\\n\\t\\t{'add a card of background...' translated.\\t\\t#insertCardOfBackground}.\\n\\t\\t{'make a new background...' translated. \\t\\t#makeNewBackground}.\\n\\t\\t#-.\\n\\t\\t{'insert cards from clipboard data' translated.\\t\\t#addCardsFromClipboardData.\\t'Create new cards from a formatted string on the clipboard' translated}.\\n\\t\\t{'insert cards from a file...' translated.\\t\\t#addCardsFromAFile.\\t\\t'Create new cards from data in a file' translated}.\\n\\t\\t#-.\\n\\t\\t{'instance variable order...' translated.\\t\\t#changeInstVarOrder.\\t\\t'Caution -- DANGER. Change the order of the variables on the cards' translated}.\\n\\t\\t{'be defaults for new cards' translated. \\t\\t#beDefaultsForNewCards.\\t\\t'Make these current field values be the defaults for their respective fields on new cards' translated}.\\n\\t\\t {'sort cards by...' translated.\\t\\t\\t#sortCards.\\t\\t\\t'Sort all the cards of the current background using some field as the sort key' translated}.\\n\\t\\t#-.\\n\\t\\t{'delete this card' translated. \\t\\t\\t#deleteCard}.\\n\\t\\t{'delete all cards *except* this one' translated.\\t#deleteAllCardsExceptThisOne}.\\n\\t\\t#-.\\n\\t\\t{'move card to front of stack' translated.\\t\\t#makeCurrentCardFirstInStack}.\\n\\t\\t{'move card to back of stack' translated.\\t\\t#makeCurrentCardLastInStack}.\\n\\t\\t{'move card one position earlier' translated.\\t\\t#moveCardOnePositionEarlier}.\\n\\t\\t{'move card one position later' translated.\\t\\t#moveCardOnePositionLater}.\\n\\t\\t#-.\\n\\t\\t{'scripts for this background' translated.\\t\\t#browseCardClass}.\\n\\t\\t#-.\\n\\t\\t{'debug...' translated.\\t\\t\\t\\t\\t#offerStackDebugMenu}.\\n\\t\\t{'bookish items...' translated. \\t\\t\\t#offerBookishMenu}}.\\n\\n\\taMenu addUpdating: #showingPageControlsString action: #toggleShowingOfPageControls.\\n\\taMenu addUpdating: #showingFullScreenString action: #toggleFullScreen.\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 4/4/2006 16:49'!\\nofferBookishMenu\\n\\t\\\"Offer a menu with book-related items in it\\\"\\n\\n\\t| aMenu |\\n\\taMenu := MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack / Book' translated.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList:\\n\\t\\t#(('sort pages' sortPages)\\n\\t\\t('uncache page sorter' uncachePageSorter)).\\n\\t(self hasProperty: #dontWrapAtEnd)\\n\\t\\tifTrue: [aMenu add: 'wrap after last page' translated selector: #setWrapPages: argument: true]\\n\\t\\tifFalse: [aMenu add: 'stop at last page' translated selector: #setWrapPages: argument: false].\\n\\taMenu addList:\\n\\t\\t#(('make bookmark'\\t bookmarkForThisPage)\\n\\t\\t('make thumbnail' thumbnailForThisPage)).\\n\\n\\taMenu addLine.\\n\\taMenu add: 'sound effect for all pages' translated action: #menuPageSoundForAll:.\\n\\taMenu add: 'sound effect this page only' translated action: #menuPageSoundForThisPage:.\\n\\taMenu add: 'visual effect for all pages' translated action: #menuPageVisualForAll:.\\n\\taMenu add: 'visual effect this page only' translated action: #menuPageVisualForThisPage:.\\n\\n\\taMenu addLine.\\n\\t(self primaryHand pasteBuffer class isKindOf: PasteUpMorph class) ifTrue:\\n\\t\\t[aMenu add: 'paste book page' translated action: #pasteBookPage].\\n\\n\\taMenu add: 'save as new-page prototype' translated action: #setNewPagePrototype.\\n\\tnewPagePrototype ifNotNil: [\\n\\t\\taMenu add: 'clear new-page prototype' translated action: #clearNewPagePrototype].\\n\\n\\taMenu add: (self dragNDropEnabled ifTrue: ['close' translated ] ifFalse: ['open' translated]) , ' dragNdrop' translated\\n\\t\\t\\taction: #toggleDragNDrop.\\n\\taMenu addLine.\\n\\taMenu add: 'make all pages this size' translated action: #makeUniformPageSize.\\n\\taMenu addUpdating: #keepingUniformPageSizeString target: self action: #toggleMaintainUniformPageSize.\\n\\taMenu addLine.\\n\\taMenu add: 'send all pages to server' translated action: #savePagesOnURL.\\n\\taMenu add: 'send this page to server' translated action: #saveOneOnURL.\\n\\taMenu add: 'reload all from server' translated action: #reload.\\n\\taMenu add: 'copy page url to clipboard' translated action: #copyUrl.\\n\\taMenu add: 'keep in one file' translated action: #keepTogether.\\n\\n\\taMenu addLine.\\n\\taMenu add: 'load PPT images from slide #1' translated action: #loadImagesIntoBook.\\n\\taMenu add: 'background color for all pages...' translated action: #setPageColor.\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 9/29/2004 20:47'!\\nofferStackDebugMenu\\n\\t\\\"Put up a menu offering debugging items for the stack\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack debugging'.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList: #(\\n\\t\\t('reassess'\\t\\t\\t\\t\\t\\t\\t\\treassessBackgroundShape)\\n\\t\\t('relax grip on variable names'\\t\\t\\trelaxGripOnVariableNames)\\n\\t\\t('commit card data'\\t\\t\\t\\t\\t\\tcommitCardData)\\n\\t\\t-\\n\\t\\t('browse card uniclass'\\t\\t\\t\\t\\tbrowseCardClass)\\n\\t\\t('inspect card'\\t\\t\\t\\t\\t\\t\\tinspectCurrentCard)\\n\\t\\t('inspect background'\\t\\t\\t\\t\\tinspectCurrentBackground)\\n\\t\\t('inspect stack'\\t\\t\\t\\t\\t\\t\\tinspectCurrentStack)).\\n\\taMenu popUpInWorld: (self world ifNil: [self currentWorld])\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 01:58'!\\ntemplateMatches\\n\\t| template docks keys bkg |\\n\\t\\\"Current card is the template. Only search cards in this background. Look at cards directly (not allText). Key must be found in the same field as in the template. HyperCard style (multiple starts of words). \\n\\tPut results in a list, outside the stack.\\\"\\n\\n\\ttemplate _ self currentCard.\\n\\ttemplate commitCardPlayerData.\\n\\tdocks _ template class variableDocks.\\n\\t(keys _ template asKeys) ifNil: [^ #()]. \\\"nothing to match against\\\"\\n\\tbkg _ self currentPage.\\n\\t^ self privateCards select: [:cardPlayer | \\n\\t\\t(((cardPlayer == template) not) and: [cardPlayer costume == bkg]) \\n\\t\\t\\tand: [cardPlayer match: keys fields: docks]].\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:00'!\\nwriteSingletonData\\n\\t\\\"Backgrounds that have just one card, may never get their data written into a CardPlayer. Make sure we do it.\\\"\\n\\n\\t| sieve |\\n\\tsieve _ IdentityDictionary new.\\n\\tpages do: [:pp | sieve at: pp put: 0].\\n\\tself privateCards do: [:cc | sieve at: cc costume put: (sieve at: cc costume) + 1].\\n\\tsieve associationsDo: [:ass | \\n\\t\\tass value = 1 ifTrue:\\n\\t\\t\\t[ass key player commitCardPlayerDataFrom: ass key]].\\n\\t\\t\\t\\\"If currently showing card, may be some trouble... <- tk note 5/01\\\"! !\\n\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'sw 6/6/2003 13:59'!\\naddPageControlMorph: aMorph\\n\\n\\t\\\"Add the given morph as a page-control, at the appropriate place\\\"\\n\\n\\n\\n\\taMorph setProperty: #pageControl toValue: true.\\n\\n\\tself addPane: aMorph paneType: #pageControl! !\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'tk 11/5/2001 08:21'!\\nfullControlSpecs\\n\\t\\\"Answer specifications for the long form of iconic stack/book controls\\\"\\n\\n\\t^ #(\\n\\t\\tspacer\\n\\t\\tvariableSpacer\\n\\t\\t('-'\\t\\t\\tdeleteCard\\t\\t\\t\\t\\t'Delete this card')\\n\\t\\tspacer\\n\\t\\t( '\\U00ab'\\t\\tgoToFirstCardOfStack\\t\\t\\t'First card')\\n\\t\\tspacer\\n\\t\\t( '<' \\t\\tgoToPreviousCardInStack\\t\\t'Previous card')\\n\\t\\tspacer\\n\\t\\t('\\U00b7'\\t\\t\\tinvokeBookMenu \\t\\t\\t'Click here to get a menu of options for this stack.')\\n\\t\\t\\\"spacer\\t('\\U00b6'\\t\\t\\treshapeBackground \\t\\t'Reshape')\\t\\\"\\n\\n\\t\\tspacer\\n\\t\\t('\\U00a7'\\t\\t\\tshowDesignationsOfObjects \\t'Show designations')\\n\\t\\tspacer\\n\\t\\t('>'\\t\\t\\tgoToNextCardInStack\\t\\t\\t'Next card')\\n\\t\\tspacer\\n\\t\\t( '\\U00bb'\\t\\tgoToLastCardOfStack\\t\\t\\t'Final card')\\n\\t\\tspacer\\n\\t\\t('+'\\t\\t\\tinsertCard\\t\\t\\t\\t\\t'Add a new card after this one')\\n\\t\\tvariableSpacer\\n\\t\\t('\\U00b3'\\t\\t\\tfewerPageControls\\t\\t\\t'Fewer controls\\n(if shift key pressed,\\ndeletes controls)')\\n)! !\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'sw 10/30/2000 10:09'!\\nshortControlSpecs\\n\\t\\\"Answer specficiations for the shorter form of stack controls\\\"\\n\\n\\t^ #(\\n\\t\\tspacer\\n\\t\\tvariableSpacer\\n\\t\\t( '<'\\t\\tgoToPreviousCardInStack\\t\\t'Previous card')\\n\\t\\tspacer\\n\\t\\t('\\U00b7'\\t\\tinvokeBookMenu \\t\\t\\t'Click here to get a menu for this stack.')\\n\\t\\tspacer\\n\\t\\t('>'\\t\\tgoToNextCardInStack\\t\\t\\t'Next card')\\n\\t\\tvariableSpacer\\n\\t\\t('\\U00b3'\\tshowMoreControls\\t\\t\\t\\t'More controls\\n(if shift key pressed,\\ndeletes controls)'))! !\\n\\n\\n!StackMorph methodsFor: 'parts bin' stamp: 'sw 8/2/2001 18:14'!\\ninitializeToStandAlone\\n\\t\\n\\tself initialize.\\n\\tself pageSize: (480 @ 320); color: (Color gray: 0.7).\\n\\tself borderWidth: 1; borderColor: Color black.\\n\\tself currentPage extent: self pageSize.\\n\\tself showPageControls: self fullControlSpecs.\\n\\t^ self\\n\\n\\\"StackMorph initializedInstance openInHand\\\"! !\\n\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 3/18/2002 02:20'!\\nallNonSubmorphMorphs\\n\\t\\\"Return a collection containing all morphs in this morph which are not currently in the submorph containment hierarchy. Especially the non-showing pages in BookMorphs.\\\"\\n\\n\\t| coll |\\n\\tcoll _ OrderedCollection new.\\n\\tself privateCards do: [:cd | \\n\\t\\tcd privateMorphs ifNotNil: [coll addAll: cd privateMorphs]].\\n\\t^ coll! !\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 6/5/2003 04:01'!\\ninsertionIndexForPaneOfType: aType\\n\\n\\t| naturalIndex insertionIndex |\\n\\n\\tnaturalIndex _ self naturalPaneOrder indexOf: aType.\\n\\n\\tinsertionIndex _ 1.\\n\\n\\t(self naturalPaneOrder copyFrom: 1 to: (naturalIndex - 1)) do: \\\"guys that would precede\\\"\\n\\n\\t\\t[:sym | (self hasSubmorphWithProperty: sym)\\n\\n\\t\\t\\tifTrue:\\n\\n\\t\\t\\t\\t[insertionIndex _ insertionIndex + 1]].\\n\\n\\t^ insertionIndex! !\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 6/5/2003 04:02'!\\nnaturalPaneOrder\\n\\n\\t^ #(header pageControl retrieve search index content)! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StackMorph class methodsFor: 'authoring prototype' stamp: 'nk 7/12/2003 08:59'!\\ndesignationsExplainer\\n\\t\\\"Answer a morph that contains designation explanation\\\"\\n\\n\\t| aMorph aSwatch aTextMorph |\\n\\taMorph _ AlignmentMorph newColumn color: Color black; layoutInset: 1.\\n\\t#((green\\t\\t\\n'Shared items on\\nBackground.\\nExact same item\\nshared by every card')\\n\\t(orange\\n'Data items on\\nBackground\\nEach card has its\\nown data')\\n\\t(red\\n'Instance-specific\\nitems\\nunique\\nto this card')) do:\\n\\n\\t[:aPair |\\n\\t\\taSwatch _ AlignmentMorph new extent: 132 @80; color: (Color perform: aPair first); lock.\\n\\t\\taSwatch hResizing: #rigid; vResizing: #rigid; layoutInset: 0.\\n\\t\\taSwatch borderColor: Color black.\\n\\t\\taTextMorph _ TextMorph new string: aPair second fontName: Preferences standardEToysFont familyName size: 18.\\n\\t\\taTextMorph width: 130.\\n\\t\\taTextMorph centered.\\n\\t\\taSwatch addMorphBack: aTextMorph.\\n\\t\\taMorph addMorphBack: aSwatch].\\n\\taMorph hResizing: #shrinkWrap; vResizing: #shrinkWrap.\\n\\n\\t^ aMorph\\n\\n\\t\\\"StackMorph designationsExplainer openInHand\\\"\\n! !\\n\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:30'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:36'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StackMorph\\tauthoringPrototype\\t'Stack'\\t\\t'A multi-card data base'\\t)\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Scripting'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tauthoringPrototype\\t'Stack'\\t\\t'A multi-card data base'\\t)\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tstackHelpWindow\\t'Stack Help'\\t'Some hints about how to use Stacks')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tpreviousCardButton\\t'Previous Card'\\t'A button that takes the user to the previous card in the stack')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tnextCardButton\\t'Next Card'\\t\\t'A button that takes the user to the next card in the stack')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools']! !\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:40'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!StackMorph class methodsFor: 'misc' stamp: 'tk 12/14/2001 19:23'!\\ndiscoverSlots: aMorph\\n\\t\\\"Examine the parts of the morph for ones that couldHoldSeparateData. Return a pair of lists: Named morphs, and unnamed morphs (which may be labels, and non-data). Examine all submorphs.\\\"\\n\\n\\t| named unnamed got sn generic |\\n\\tnamed _ OrderedCollection new.\\n\\tunnamed _ OrderedCollection new.\\n\\taMorph submorphsDo: [:direct | \\n\\t\\tgot _ false.\\n\\t\\tdirect allMorphsDo: [:sub |\\n\\t\\t\\tsub couldHoldSeparateDataForEachInstance ifTrue: [\\n\\t\\t\\t\\t(sn _ sub knownName) ifNotNil: [\\n\\t\\t\\t\\t\\tgeneric _ (#('Number (fancy)' 'Number (mid)' 'Number (bare)')\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tincludes: sn).\\n\\t\\t\\t\\t\\t(sn beginsWith: 'shared' \\\"label\\\") | generic ifFalse: [\\n\\t\\t\\t\\t\\t\\tnamed add: sub.\\n\\t\\t\\t\\t\\t\\tgot _ true]]]].\\n\\t\\tgot ifFalse: [unnamed add: direct]].\\n\\t^ Array with: named with: unnamed\\n\\t\\t! !\\n\\n\\n!StackMorph class methodsFor: 'navigation buttons' stamp: 'sw 10/27/2000 10:53'!\\nnextCardButton\\n\\t\\\"Answer a button that advances the user to the next card in the stack\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton target: aButton; actionSelector: #goToNextCardInStack; label: '>'; color: Color yellow; borderWidth: 0.\\n\\taButton setNameTo: 'next'.\\n\\t^ aButton! !\\n\\n!StackMorph class methodsFor: 'navigation buttons' stamp: 'sw 10/27/2000 10:53'!\\npreviousCardButton\\n\\t\\\"Answer a button that will take the user to the preceding card in the stack\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton target: aButton; actionSelector: #goToPreviousCardInStack; label: '<'; color: Color yellow ; borderWidth: 0.\\n\\taButton setNameTo: 'previous'.\\n\\t^ aButton! !\\n\\n\\n!StackMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:52'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Stack'\\n\\t\\tcategories:\\t\\t#('Presentation')\\n\\t\\tdocumentation:\\t'A database of any sort -- slide show, rolodex, and any point in between'! !\\n\\n!StackMorph class methodsFor: 'parts bin' stamp: 'sw 4/8/2002 09:30'!\\nstackHelpWindow\\n\\t^ (Workspace new contents: 'A \\\"stack\\\" is a place where you can create, store, view and retrieve data \\\"fields\\\" from a set of \\\"cards\\\". Data that you want to occur on every card (such as a name and an address in an Address Stack) are represented by objects such as \\\"Simple Text\\\", \\\"Fancy Text\\\", and \\\"Scrolling Text\\\" that you obtain from the Stack Tools flap.\\n\\nWhen you look at a card in a Stack, you may be seeing three different kinds of material. Press the \\U00a7 button in the stack''s controls to see the current designations, and use the \\\"explain designations\\\" to get a reminder of what the three different colors mean.\\n\\U00b7 Things that are designated to be seen on every card, and have the same contents whichever card is being shown. (green)\\n\\U00b7 Things that are designated to be seen on every card, with each card having its own value for them. (orange)\\n\\U00b7 Things that are designated to occur only on the particular card at hand. (red)\\n\\nUse the \\\"stack/cards\\\" menu (in an object''s halo menu) to change the designation of any object. For example, if you have an object that is private to just one card, and you want to make it visible on all cards, use \\\"place onto background\\\". If you further want it to hold a separate value for each separate card, use \\\"start holding separate data for each instance\\\".\\n\\nThe normal sequence to define a Stack''s structure is to obtain a blank Stack, then create your fields by grabbing what you want from the Stack Tools flap and dropping it where you want it in the stack. For easiest use, give a name to each field (by editing the name in its halo) *before* you put it onto the background.. Those fields that you want to represent the basic data of the stack need to be given names, placed on the background, and then told to hold separate data.\\n\\nWhen you hit the + button in a stack''s controls, a new card is created with default values in all the fields. You can arrange for a particular default value to be used in a field -- do this either for one field at a time with \\\"be default value on new card\\\", or you can request that the all the values seen on a particular card serve as default by choosing \\\"be defaults for new cards\\\" from the stack''s \\U00b7 menu.\\n\\nIt is also possible to have multiple \\\"backgrounds\\\" in the same stack -- each different background defines a different data structure, and cards from multiple backgrounds can be freely mixed in the same stack.\\n\\nBesides text fields, it is also possible to have picture-valued fields -- and potentially fields with data values of any other type as well.')\\n\\n\\tembeddedInMorphicWindowLabeled: 'Stack Help'\\n\\n\\t\\\"StackMorph stackHelpWindow\\\"! !\\n\\n\\n!StackMorph class methodsFor: 'scripting' stamp: 'sw 11/2/2002 15:47'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories.\\\"\\n\\n\\t^ # ((#'stack navigation'\\n\\t\\t\\t((command goToNextCardInStack 'Go to the next card')\\n\\t\\t\\t(command goToPreviousCardInStack 'Go to the previous card')\\n\\t\\t\\t(command goToFirstCardInBackground 'Go to the first card of the current background')\\n\\t\\t\\t(command goToFirstCardOfStack 'Go to the first card of the entire stack')\\n\\t\\t\\t(command goToLastCardInBackground 'Go to the last card of the current background')\\n\\t\\t\\t(command goToLastCardOfStack 'Go to the last card of the entire stack')\\n\\t\\t\\t(command deleteCard 'Delete the current card')\\n\\t\\t\\t(command insertCard 'Create a new card')\\n\\t\\t\\t(slot cardNumber 'The ordinal number of the current card' Number readWrite Player getCardNumber Player setCardNumber:))))! !\\n\\n!StackMorph class methodsFor: 'scripting' stamp: 'sw 10/9/2000 07:43'!\\nauthoringPrototype\\n\\t\\\"Answer an instance of the receiver suitable for placing in a parts bin for authors\\\"\\n\\t\\n\\t| book |\\n\\tbook _ self new markAsPartsDonor.\\n\\tbook pageSize: (480 @ 320); color: (Color gray: 0.7).\\n\\tbook borderWidth: 1; borderColor: Color black.\\n\\tbook currentPage extent: book pageSize.\\n\\tbook showPageControls: book fullControlSpecs.\\n\\t^ book\\n\\n\\\"self currentHand attachMorph: StackMorph authoringPrototype\\\"! !\\nTestCase subclass: #StackTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Stack'!\\n\\n!StackTest methodsFor: 'test' stamp: 'dc 6/21/2006 10:55'!\\ntestEmptyError\\n\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself should: [ aStack top ] raise: Error.\\n\\tself should: [ aStack pop] raise: Error.\\n\\t\\n\\taStack push: 'element'.\\n\\t\\n\\tself shouldnt: [ aStack top ] raise: Error.\\n\\tself shouldnt: [ aStack pop] raise: Error.\\n\\t\\n\\t\\n\\t\\\"The stack is empty again due to previous pop\\\"\\n\\tself should: [ aStack top ] raise: Error.\\n\\tself should: [ aStack pop] raise: Error.! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestPop\\n\\n\\t| aStack res elem |\\n\\telem := 'anElement'.\\t\\n\\taStack := Stack new.\\n\\tself assert: aStack isEmpty.\\n\\t\\n\\taStack push: 'a'.\\n\\taStack push: elem.\\n\\tres := aStack pop.\\t\\n\\tself assert: res = elem.\\n\\tself assert: res == elem.\\n\\t\\n\\tself assert: aStack size = 1.\\n\\taStack pop.\\n\\tself assert: aStack isEmpty.\\n\\n! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestPush\\n\\t\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\taStack push: 'a'.\\n\\tself assert: aStack size = 1.\\t\\n\\taStack push: 'b'.\\n\\tself assert: aStack size = 2.\\n\\t! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestSize\\n\\t\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself assert: aStack size = 0.\\n\\taStack push: 'a'.\\n\\tself assert: aStack size = 1.\\n\\taStack push: 'b'.\\n\\tself assert: aStack size = 2.\\n\\taStack pop.\\n\\tself assert: aStack size = 1.\\n\\taStack pop.\\n\\tself assert: aStack size = 0.\\n\\n \\n\\t\\n\\n\\n! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestTop\\n\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself assert: aStack isEmpty.\\n\\taStack push: 'a'.\\n\\taStack push: 'b'.\\n\\tself assert: aStack top = 'b'.\\n\\tself assert: aStack top = 'b'.\\n\\tself assert: aStack size = 2.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackTest class\\n\\tinstanceVariableNames: 'testSize'!\\nSelectionMenu subclass: #StandardFileMenu\\n\\tinstanceVariableNames: 'canTypeFileName pattern'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n!StandardFileMenu commentStamp: 'mp 8/15/2005 18:44' prior: 0!\\nI represent a SelectionMenu which operates like a modal dialog for selecting files, somewhat similar to the StandardFile dialogs in MacOS and Java Swing.\\n\\nTry for example, the following:\\n\\n\\tStandardFileMenu oldFile inspect\\n\\n\\tStandardFileMenu oldFileStream inspect\\n\\n\\tStandardFileMenu newFile inspect\\n\\n\\tStandardFileMenu newFileStream inspect\\n\\t\\n\\t(StandardFileMenu oldFileMenu: FileDirectory default withPattern: '*') startUpWithCaption: 'Select a file:'\\n\\t\\n\\t(StandardFileMenu oldFileMenu: (FileDirectory default) withPatternList: {'*.txt'. '*.changes'}) startUpWithCaption: 'Select a file:'\\n!\\n\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'rbb 2/16/2005 16:59'!\\nconfirmExistingFiles: aResult\\n\\n\\t|choice|\\n\\t(aResult directory fileExists: aResult name) ifFalse: [^aResult].\\n\\t\\n\\tchoice _ (UIManager default chooseFrom: #('overwrite that file' 'choose another name'\\n 'cancel')\\n\\t\\ttitle: aResult name, '\\nalready exists.').\\n\\n\\tchoice = 1 ifTrue: [\\n\\t\\taResult directory \\n\\t\\t\\tdeleteFileNamed: aResult name\\n\\t\\t\\tifAbsent: \\n\\t\\t\\t\\t[^self startUpWithCaption: \\n'Can''t delete ', aResult name, '\\nSelect another file'].\\n\\t\\t^aResult].\\n\\tchoice = 2 ifTrue: [^self startUpWithCaption: 'Select Another File'].\\n\\t^nil\\n ! !\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'rbb 3/1/2005 11:14'!\\ngetTypedFileName: aResult\\n\\n\\t| name |\\n\\tname := UIManager default \\n\\t\\trequest: 'Enter a new file name' \\n\\t\\tinitialAnswer: ''.\\n\\tname = '' ifTrue: [^self startUpWithCaption: 'Select a File:' translated].\\n\\tname := aResult directory fullNameFor: name.\\n\\t^ StandardFileMenuResult\\n\\t\\t\\tdirectory: (FileDirectory forFileName: name)\\n\\t\\t\\tname: (FileDirectory localNameFor: name)\\n! !\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'acg 9/28/1999 23:34'!\\nstartUpWithCaption: aString at: location\\n\\n\\t|result|\\n\\tresult _ super startUpWithCaption: aString at: location.\\n\\tresult ifNil: [^nil].\\n\\tresult isDirectory ifTrue:\\n\\t\\t[self makeFileMenuFor: result directory.\\n\\t\\t self computeForm.\\n\\t\\t ^self startUpWithCaption: aString at: location].\\n\\tresult isCommand ifTrue: \\n\\t\\t[result _ self getTypedFileName: result.\\n\\t\\tresult ifNil: [^nil]].\\n\\tcanTypeFileName ifTrue: [^self confirmExistingFiles: result].\\n\\t^result\\n\\t! !\\n\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'di 5/12/2000 10:31'!\\ndirectoryNamesString: aDirectory\\n\\\"Answer a string concatenating the directory name strings in aDirectory, each string followed by a '[...]' indicator, and followed by a cr.\\\"\\n\\n\\t^ String streamContents:\\n\\t\\t[:s | aDirectory directoryNames do: \\n\\t\\t\\t\\t[:dn | s nextPutAll: dn withBlanksTrimmed , ' [...]'; cr]]\\n\\n! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 17:33'!\\nfileNamesString: aDirectory\\n\\\"Answer a string concatenating the file name strings in aDirectory, each string followed by a cr.\\\"\\n\\n\\t^String streamContents:\\n\\t\\t[:s | \\n\\t\\t\\taDirectory fileNames do: \\n\\t\\t\\t\\t[:fn |\\n\\t\\t\\t\\t\\tpattern do:[:each | (each match: fn) ifTrue: [\\n\\t\\t\\t\\t\\t\\ts nextPutAll: fn withBlanksTrimmed; cr]]]]\\n\\t\\t! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 16:28'!\\nmakeFileMenuFor: aDirectory\\n\\\"Initialize an instance of me to operate on aDirectory\\\"\\n\\n\\t| theMenu |\\n\\tpattern ifNil: [pattern := {'*'}].\\n\\tCursor wait showWhile: \\n\\t\\t[self \\n\\t\\t\\tlabels: \\t(self menuLabelsString: aDirectory)\\n\\t\\t\\tfont: \\t(MenuStyle fontAt: 1) \\n\\t\\t\\tlines: \\t(self menuLinesArray: aDirectory).\\n\\t\\ttheMenu := self selections: (self menuSelectionsArray: aDirectory)].\\n\\t^theMenu! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:57'!\\nmenuLabelsString: aDirectory\\n\\\"Answer a menu labels object corresponding to aDirectory\\\"\\n\\n\\t^ String streamContents: \\n\\t\\t[:s | \\n\\t\\t\\tcanTypeFileName ifTrue: \\n\\t\\t\\t\\t[s nextPutAll: 'Enter File Name...'; cr].\\n\\t\\t\\ts nextPutAll: (self pathPartsString: aDirectory).\\n\\t\\t\\ts nextPutAll: (self directoryNamesString: aDirectory).\\n\\t\\t\\ts nextPutAll: (self fileNamesString: aDirectory).\\n\\t\\t\\ts skip: -1]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'tpr 11/28/2003 15:12'!\\nmenuLinesArray: aDirectory\\n\\\"Answer a menu lines object corresponding to aDirectory\\\"\\n\\n\\t| typeCount nameCnt dirDepth|\\n\\ttypeCount _ canTypeFileName \\n\\t\\tifTrue: [1] \\n\\t\\tifFalse: [0].\\n\\tnameCnt _ aDirectory directoryNames size.\\n\\tdirDepth _ aDirectory pathParts size.\\n\\t^Array streamContents: [:s |\\n\\t\\tcanTypeFileName ifTrue: [s nextPut: 1].\\n\\t\\ts nextPut: dirDepth + typeCount + 1.\\n\\t\\ts nextPut: dirDepth + nameCnt + typeCount + 1]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 18:18'!\\nmenuSelectionsArray: aDirectory\\n\\\"Answer a menu selections object corresponding to aDirectory. The object is an array corresponding to each item, each element itself constituting a two-element array, the first element of which contains a selector to operate on and the second element of which contains the parameters for that selector.\\\"\\n\\n\\t|dirSize|\\n\\tdirSize := aDirectory pathParts size.\\n\\t^Array streamContents: [:s |\\n\\t\\tcanTypeFileName ifTrue:\\n\\t\\t\\t[s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\tdirectory: aDirectory\\n\\t\\t\\t\\tname: nil)].\\n\\t\\ts nextPut: (StandardFileMenuResult\\n\\t\\t\\tdirectory: (FileDirectory root)\\n\\t\\t\\tname: '').\\n\\t\\taDirectory pathParts doWithIndex: \\n\\t\\t\\t[:d :i | s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\tdirectory: (self \\n\\t\\t\\t\\t\\t\\tadvance: dirSize - i\\n\\t\\t\\t\\t\\t\\tcontainingDirectoriesFrom: aDirectory)\\n\\t\\t\\t\\t\\tname: '')].\\n\\t\\taDirectory directoryNames do: \\n\\t\\t\\t[:dn | s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\t\\tdirectory: (FileDirectory on: (aDirectory fullNameFor: dn))\\n\\t\\t\\t\\t\\t\\tname: '')].\\n\\t\\taDirectory fileNames do: \\n\\t\\t\\t[:fn | pattern do: [:pat | (pat match: fn) ifTrue: [\\n\\t\\t\\t\\t\\ts nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\t\\tdirectory: aDirectory\\n\\t\\t\\t\\t\\t\\tname: fn)]]]]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:03'!\\npathPartsString: aDirectory\\n\\\"Answer a string concatenating the path parts strings in aDirectory, each string followed by a cr.\\\"\\n\\n\\t^String streamContents:\\n\\t\\t[:s | \\n\\t\\t\\ts nextPutAll: '[]'; cr.\\n\\t\\t\\taDirectory pathParts asArray doWithIndex: \\n\\t\\t\\t\\t[:part :i |\\n\\t\\t\\t\\t\\ts next: i put: $ .\\n\\t\\t\\t\\t\\ts nextPutAll: part withBlanksTrimmed; cr]]! !\\n\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 00:32'!\\nadvance: anInteger containingDirectoriesFrom: aDirectory\\n\\n\\t| theDirectory |\\n\\ttheDirectory _ aDirectory.\\n\\t1 to: anInteger do: [:i | theDirectory _ theDirectory containingDirectory].\\n\\t^theDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 20:50'!\\ncomputeLabelParagraph\\n\\t\\\"Answer a Paragraph containing this menu's labels, one per line and centered.\\\"\\n\\n\\t^ Paragraph withText: labelString asText style: (MenuStyle leftFlush)! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'!\\nnewFileFrom: aDirectory\\n\\n\\tcanTypeFileName _ true.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 18:25'!\\nnewFileFrom: aDirectory withPatternList: aPatternList\\n\\n\\tcanTypeFileName := true.\\n\\tpattern := aPatternList.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:29'!\\nnewFileFrom: aDirectory withPattern: aPattern\\n\\n\\tcanTypeFileName := true.\\n\\tpattern := {aPattern}.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'!\\noldFileFrom: aDirectory\\n\\n\\tcanTypeFileName _ false.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 17:28'!\\noldFileFrom: aDirectory withPatternList: aPatternList\\n\\n\\tcanTypeFileName := false.\\n\\tpattern := aPatternList.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:28'!\\noldFileFrom: aDirectory withPattern: aPattern\\n\\n\\tcanTypeFileName := false.\\n\\tpattern := {aPattern}.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 17:29'!\\npatternList: aPatternList\\n\\n\\tpattern := aPatternList! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:31'!\\npattern: aPattern\\n\\t\\\" * for all files, or '*.cs' for changeSets, etc. Just like fileLists\\\"\\n\\n\\tpattern := {aPattern}! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileMenu class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:14'!\\nnewFileMenu: aDirectory\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'zz 8/15/2005 18:21'!\\nnewFileMenu: aDirectory withPatternList: aPatternList\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory withPatternList: aPatternList! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'rww 9/23/2001 09:56'!\\nnewFileMenu: aDirectory withPattern: aPattern\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory withPattern: aPattern! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:15'!\\noldFileMenu: aDirectory\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList oldFileMenu: aDirectory].\\n\\t^ super new oldFileFrom: aDirectory! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'zz 8/15/2005 17:41'!\\noldFileMenu: aDirectory withPatternList: aPatternList\\n\\n\\tSmalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory].\\n\\t^super new oldFileFrom: aDirectory withPatternList: aPatternList! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'RAA 5/25/2000 09:30'!\\noldFileMenu: aDirectory withPattern: aPattern\\n\\n\\tSmalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory].\\n\\t^super new oldFileFrom: aDirectory withPattern: aPattern! !\\n\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\nnewFile\\n\\n\\t^self newFileFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'!\\nnewFileFrom: aDirectory\\n\\n\\t^(self newFileMenu: aDirectory)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:18'!\\nnewFileStream\\n\\n\\t^self newFileStreamFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\nnewFileStreamFrom: aDirectory\\n\\n\\t| sfmResult fileStream |\\n\\tsfmResult _ self newFileFrom: aDirectory.\\n\\tsfmResult ifNil: [^nil].\\n\\tfileStream _ sfmResult directory newFileNamed: sfmResult name.\\n\\t[fileStream isNil] whileTrue:\\n\\t\\t[sfmResult _ self newFileFrom: aDirectory.\\n\\t\\tsfmResult ifNil: [^nil].\\n\\t\\tfileStream _ sfmResult directory newFileNamed: sfmResult name].\\n\\t^fileStream\\n! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\noldFile\\n\\n\\t^self oldFileFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'!\\noldFileFrom: aDirectory\\n\\n\\t^(self oldFileMenu: aDirectory)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'MM 4/6/2004 22:56'!\\noldFileFrom: aDirectory withPattern: aPattern\\n\\\"\\nSelect an existing file from a selection conforming to aPattern.\\n\\\"\\n\\t^(self oldFileMenu: aDirectory withPattern: aPattern)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:17'!\\noldFileStream\\n\\n\\t^self oldFileStreamFrom: (FileDirectory default)\\n! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:27'!\\noldFileStreamFrom: aDirectory\\n\\n\\t| sfmResult fileStream |\\n\\tsfmResult _ self oldFileFrom: aDirectory.\\n\\tsfmResult ifNil: [^nil].\\n\\tfileStream _ sfmResult directory oldFileNamed: sfmResult name.\\n\\t[fileStream isNil] whileTrue:\\n\\t\\t[sfmResult _ self oldFileFrom: aDirectory.\\n\\t\\tsfmResult ifNil: [^nil].\\n\\t\\tfileStream _ sfmResult directory oldFileNamed: sfmResult name].\\n\\t^fileStream\\n! !\\nObject subclass: #StandardFileMenuResult\\n\\tinstanceVariableNames: 'directory name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\ndirectory\\n\\n\\t^directory! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\ndirectory: aDirectory\\n\\n\\t^directory _ aDirectory! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\nname\\n\\n\\t^name! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\nname: aString\\n\\n\\t^name _ aString! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'sw 6/9/1999 11:50'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' with directory: '.\\n\\tdirectory printOn: aStream.\\n\\taStream nextPutAll: ' name: '.\\n\\tname printOn: aStream\\n\\n\\\"StandardFileMenu oldFile\\\"! !\\n\\n\\n!StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 09:05'!\\nisCommand\\n\\n\\t^name isNil! !\\n\\n!StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 20:57'!\\nisDirectory\\n\\n\\t^name = ''! !\\n\\n\\n!StandardFileMenuResult methodsFor: 'private' stamp: 'acg 4/15/1999 08:42'!\\ndirectory: aDirectory name: aString\\n\\n\\tdirectory _ aDirectory.\\n\\tname _ aString.\\n\\t^self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileMenuResult class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileMenuResult class methodsFor: 'instance creation' stamp: 'acg 4/15/1999 08:42'!\\ndirectory: aDirectory name: aString\\n\\n\\t^super new directory: aDirectory name: aString! !\\nFileStream subclass: #StandardFileStream\\n\\tinstanceVariableNames: 'name fileID buffer1'\\n\\tclassVariableNames: 'Registry'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-Kernel'!\\n!StandardFileStream commentStamp: '<historical>' prior: 0!\\nProvides 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!\\n\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:16'!\\ndirectory\\n\\t\\\"Return the directory containing this file.\\\"\\n\\n\\t^ FileDirectory forFileName: self fullName\\n! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'tk 3/14/2000 23:31'!\\ndirectoryUrl\\n\\n\\t^ self directory url! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nfile\\n\\t\\\"Answer the object representing the receiver's file. Need for compatibility with some calls -- check senders. 2/14/96 sw\\\"\\n\\n\\t^ self! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'!\\nfullName\\n\\t\\\"Answer this file's full path name.\\\"\\n\\n\\t^ name\\n! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nisDirectory\\n\\t\\\"Answer whether the receiver represents a directory. For the post-transition case, uncertain what to do. 2/14/96 sw\\\"\\n\\t^ false! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'ar 11/24/1998 14:00'!\\nlocalName\\n\\t^ name ifNotNil: [(name findTokens: FileDirectory pathNameDelimiter asString) last]! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'!\\nname\\n\\t\\\"Answer this file's full path name.\\\"\\n\\n\\t^ name\\n! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npeekFor: item \\n\\t\\\"Answer false and do not advance if the next element is not equal to item, or if this stream is at the end. If the next element is equal to item, then advance over it and return true\\\"\\n\\t| next |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\t(next := self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tself skip: -1.\\n\\t^ false! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nprintOn: aStream\\n\\t\\\"Put a printed version of the receiver onto aStream. 1/31/96 sw\\\"\\n\\n\\taStream nextPutAll: self class name; nextPutAll: ': '; print: name! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'ar 6/16/2002 18:58'!\\nreset\\n\\tself ensureOpen.\\n\\tself position: 0.! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nsize\\n\\t\\\"Answer the size of the file in characters. 2/12/96 sw\\\"\\n\\n\\t^ self primSize: fileID! !\\n\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 1/11/2000 10:44'!\\ndefaultBrowserReadyWait\\n\\t^5000! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npost: data target: target url: url ifError: errorBlock\\n\\t\\\"Post data to the given URL. The returned file stream contains the reply of the server.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLPost: url target: target data: data semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tresult ifTrue:[fileID := self primURLRequestFileHandle: request].\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 2/2/2001 14:22'!\\npost: data url: url ifError: errorBlock\\n\\n\\tself post: data target: nil url: url ifError: errorBlock! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'ar 2/26/2001 15:58'!\\nprimBrowserReady\\n\\t<primitive:'primitivePluginBrowserReady'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 9/21/2000 16:58'!\\nprimURLPost: url data: contents semaIndex: index\\n\\t^self primURLPost: url target: nil data: contents semaIndex: index! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 9/21/2000 16:58'!\\nprimURLPost: url target: target data: contents semaIndex: index\\n\\t\\\"Post the data (url might be 'mailto:' etc)\\\"\\n\\t<primitive:'primitivePluginPostURL'>\\n\\t^nil\\n ! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequest: url semaIndex: index\\n\\t<primitive:'primitivePluginRequestURLStream'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nprimURLRequest: url target: target semaIndex: index\\n\\t\\\"target - String (frame, also ':=top', ':=parent' etc)\\\"\\n\\t<primitive:'primitivePluginRequestURL'>\\n\\t^nil\\n ! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestDestroy: request\\n\\t<primitive:'primitivePluginDestroyRequest'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestFileHandle: request\\n\\t<primitive: 'primitivePluginRequestFileHandle'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestState: request\\n\\t<primitive:'primitivePluginRequestState'>\\n\\t^false! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 2/29/2000 11:22'!\\nrequestURL: url target: target\\n\\t^self requestURL: url target: target ifError: [nil]! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestURL: url target: target ifError: errorBlock\\n\\t\\\"Request to go to the target for the given URL.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLRequest: url target: target semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nrequestURLStream: url\\n\\t\\\"FileStream requestURLStream:'http://www.squeak.org'\\\"\\n\\t^self requestURLStream: url ifError:[nil]! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestURLStream: url ifError: errorBlock\\n\\t\\\"Request a FileStream for the given URL.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\t\\\"FileStream requestURLStream:'http://www.squeak.org'\\\"\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLRequest: url semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tresult ifTrue:[fileID := self primURLRequestFileHandle: request].\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nwaitBrowserReadyFor: timeout ifFail: errorBlock\\n\\t| startTime delay okay |\\n\\tokay := self primBrowserReady.\\n\\tokay ifNil:[^errorBlock value].\\n\\tokay ifTrue: [^true].\\n\\tstartTime := Time millisecondClockValue.\\n\\tdelay := Delay forMilliseconds: 100.\\n\\t[(Time millisecondsSince: startTime) < timeout]\\n\\t\\twhileTrue: [\\n\\t\\t\\tdelay wait.\\n\\t\\t\\tokay := self primBrowserReady.\\n\\t\\t\\tokay ifNil:[^errorBlock value].\\n\\t\\t\\tokay ifTrue: [^true]].\\n\\t^errorBlock value! !\\n\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'ar 1/10/2001 20:01'!\\nprimDropRequestFileHandle: dropIndex\\n\\t\\\"Primitive. Return the (read-only) file handle for some file that was just dropped onto Squeak.\\n\\tFail if dropIndex is out of range or the primitive is not supported.\\\"\\n\\t<primitive: 'primitiveDropRequestFileHandle' module:'DropPlugin'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'ar 1/10/2001 20:01'!\\nprimDropRequestFileName: dropIndex\\n\\t\\\"Primitive. Return the file name for some file that was just dropped onto Squeak.\\n\\tFail if dropIndex is out of range or the primitive is not supported.\\\"\\n\\t<primitive: 'primitiveDropRequestFileName' module:'DropPlugin'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestDropStream: dropIndex\\n\\t\\\"Return a read-only stream for some file the user has just dropped onto Squeak.\\\"\\n\\tname := self primDropRequestFileName: dropIndex.\\n\\tfileID := self primDropRequestFileHandle: dropIndex.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.\\n\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'finalization' stamp: 'ar 3/21/98 18:16'!\\nactAsExecutor\\n\\tsuper actAsExecutor.\\n\\tname := nil.! !\\n\\n!StandardFileStream methodsFor: 'finalization' stamp: 'ar 10/7/1998 15:44'!\\nfinalize\\n\\tself primCloseNoError: fileID.! !\\n\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nclose\\n\\t\\\"Close this file.\\\"\\n\\n\\tfileID ifNotNil: [\\n\\t\\tself primClose: fileID.\\n\\t\\tself unregister.\\n\\t\\tfileID := nil].\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 2/6/2002 08:33'!\\nclosed\\n\\t\\\"Answer true if this file is closed.\\\"\\n\\n\\t^ fileID isNil or: [(self primSizeNoError: fileID) isNil]\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 16:20'!\\nensureOpen\\n\\t\\\"Make sure that this file really is open.\\\"\\n\\n\\tself closed ifTrue: [^ self reopen].\\n\\t(self primSizeNoError: fileID) ifNotNil: [^ self].\\n\\tself reopen.\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close'!\\nopen\\n\\t\\\"For compatibility with a few existing things. 2/14/96 sw\\\"\\n\\n\\t^ self reopen! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nopen: fileName forWrite: writeMode \\n\\t\\\"Open the file with the given name. If writeMode is true, allow writing, otherwise open the file in read-only mode.\\\"\\n\\t\\\"Changed to do a GC and retry before failing ar 3/21/98 17:25\\\"\\n\\t| f |\\n\\tf := fileName asVmPathName.\\n\\n\\tfileID := StandardFileStream retryWithGC:[self primOpen: f writable: writeMode] \\n\\t\\t\\t\\t\\tuntil:[:id| id notNil] \\n\\t\\t\\t\\t\\tforFileNamed: fileName.\\n\\tfileID ifNil: [^ nil]. \\\"allows sender to detect failure\\\"\\n\\tself register.\\n\\tname := fileName.\\n\\trwmode := writeMode.\\n\\tbuffer1 := String new: 1.\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close'!\\nopenReadOnly\\n\\t\\\"Open the receiver as a read-only file. 1/31/96 sw\\\"\\n\\n\\t^ self open: name forWrite: false! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 13:58'!\\nreopen\\n\\t\\\"Close and reopen this file. The file position is reset to zero.\\\"\\n\\t\\\"Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened.\\\"\\n\\n\\tfileID ifNotNil: [self primCloseNoError: fileID].\\n\\tself open: name forWrite: rwmode.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAtEnd: id\\n\\t\\\"Answer true if the file position is at the end of the file.\\\"\\n\\n\\t<primitive: 'primitiveFileAtEnd' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimClose: id\\n\\t\\\"Close this file.\\\"\\n\\n\\t<primitive: 'primitiveFileClose' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimCloseNoError: id\\n\\t\\\"Close this file. Don't raise an error if the primitive fails.\\\"\\n\\n\\t<primitive: 'primitiveFileClose' module: 'FilePlugin'>\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nprimFlush: id\\n\\t\\\"Flush pending changes to the disk\\\"\\n\\t| p |\\n\\t<primitive: 'primitiveFileFlush' module: 'FilePlugin'>\\n\\t\\\"In some OS's seeking to 0 and back will do a flush\\\"\\n\\tp := self position.\\n\\tself position: 0; position: p! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimGetPosition: id\\n\\t\\\"Get this files current position.\\\"\\n\\n\\t<primitive: 'primitiveFileGetPosition' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimOpen: fileName writable: writableFlag\\n\\t\\\"Open a file of the given name, and return the file ID obtained.\\n\\tIf writableFlag is true, then\\n\\t\\tif there is none with this name, then create one\\n\\t\\telse prepare to overwrite the existing from the beginning\\n\\totherwise\\n\\t\\tif the file exists, open it read-only\\n\\t\\telse return nil\\\"\\n\\n\\t<primitive: 'primitiveFileOpen' module: 'FilePlugin'>\\n\\t^ nil\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimRead: id into: byteArray startingAt: startIndex count: count\\n\\t\\\"Read up to count bytes of data from this file into the given string or byte array starting at the given index. Answer the number of bytes actually read.\\\"\\n\\n\\t<primitive: 'primitiveFileRead' module: 'FilePlugin'>\\n\\tself closed ifTrue: [^ self error: 'File is closed'].\\n\\tself error: 'File read failed'.\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSetPosition: id to: anInteger\\n\\t\\\"Set this file to the given position.\\\"\\n\\n\\t<primitive: 'primitiveFileSetPosition' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSize: id\\n\\t\\\"Answer the size of this file.\\\"\\n\\n\\t<primitive: 'primitiveFileSize' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSizeNoError: id\\n\\t\\\"Answer the size of this file. Answer nil if the primitive fails; this indicates that the file handle has become stale.\\\"\\n\\n\\t<primitive: 'primitiveFileSize' module: 'FilePlugin'>\\n\\t^ nil\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'JMM 5/24/2001 21:55'!\\nprimTruncate: id to: anInteger\\n\\t\\\"Truncate this file to the given position.\\\"\\n\\n\\t<primitive: 'primitiveFileTruncate' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimWrite: id from: stringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Write count bytes onto this file from the given string or byte array starting at the given index. Answer the number of bytes written.\\\"\\n\\n\\t<primitive: 'primitiveFileWrite' module: 'FilePlugin'>\\n\\tself closed ifTrue: [^ self error: 'File is closed'].\\n\\tself error: 'File write failed'.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'properties-setting'!\\nasHtml\\n\\t\\\"Convert me in to an HtmlFileStream. 4/11/96 tk\\\"\\n\\n\\t^ self as: HtmlFileStream \\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nascii\\n\\t\\\"opposite of binary\\\"\\n\\tbuffer1 := String new: 1! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nbinary\\n\\tbuffer1 := ByteArray new: 1! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'JMM 1/28/2001 18:44'!\\ngetFileType\\n\\t\\\"On the Macintosh, get the file type and creator of this file. On other platforms, do nothing.\\\"\\n\\n\\t^FileDirectory default\\n\\t\\tgetMacFileTypeAndCreator: self fullName\\n\\t\\t\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninsertLineFeeds\\n\\t\\\"(FileStream oldFileNamed: 'BBfix2.st') insertLineFeeds\\\"\\n\\t| s crLf f |\\n\\tcrLf := String with: Character cr with: (Character value: 10).\\n\\ts := ReadStream on: (self next: self size).\\n\\tself close.\\n\\tf := FileStream newFileNamed: self name.\\n\\t[s atEnd] whileFalse: \\n\\t\\t[f nextPutAll: (s upTo: Character cr); nextPutAll: crLf].\\n\\tf close! !\\n\\n!StandardFileStream methodsFor: 'properties-setting'!\\nisBinary\\n\\t^ buffer1 class == ByteArray! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'tk 11/4/1998 19:17'!\\nisReadOnly\\n\\n\\t^ rwmode not\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnly\\n\\t\\\"Make this file read-only.\\\"\\n\\n\\trwmode := false.\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadWrite\\n\\t\\\"Make this file writable.\\\"\\n\\n\\trwmode := true.\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'jm 12/5/97 15:14'!\\nsetFileTypeToObject\\n\\t\\\"On the Macintosh, set the file type and creator of this file to be a Squeak object file. On other platforms, do nothing. Setting the file type allows Squeak object files to be sent as email attachments and launched by double-clicking. On other platforms, similar behavior is achieved by creating the file with the '.sqo' file name extension.\\\"\\n\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: self fullName\\n\\t\\ttype: 'SOBJ'\\n\\t\\tcreator: 'FAST'.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'sw 2/12/96'!\\natEnd\\n\\t\\\"Answer whether the receiver is at its end. \\\"\\n\\t^ self primAtEnd: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nbasicNext\\n\\t\\\"Answer the next byte from this file, or nil if at the end of the file.\\\"\\n\\n\\t| count |\\n\\tcount := self primRead: fileID into: buffer1 startingAt: 1 count: 1.\\n\\tcount = 1\\n\\t\\tifTrue: [^ buffer1 at: 1]\\n\\t\\tifFalse: [^ nil].\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ncompressFile\\n\\t\\\"Write a new file that has the data in me compressed in GZip format.\\\"\\n\\t| zipped buffer |\\n\\n\\tself readOnly; binary.\\n\\tzipped := self directory newFileNamed: (self name, FileDirectory dot, 'gz').\\n\\tzipped binary; setFileTypeToObject.\\n\\t\\t\\\"Type and Creator not to be text, so can be enclosed in an email\\\"\\n\\tzipped := GZipWriteStream on: zipped.\\n\\tbuffer := ByteArray new: 50000.\\n\\t'Compressing ', self fullName displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: self size\\n\\t\\tduring: [:bar |\\n\\t\\t\\t[self atEnd] whileFalse: [\\n\\t\\t\\t\\tbar value: self position.\\n\\t\\t\\t\\tzipped nextPutAll: (self nextInto: buffer)].\\n\\t\\t\\tzipped close.\\n\\t\\t\\tself close].\\n\\t^zipped! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfindString: string\\n\\t\\\"Fast version of #upToAll: to find a String in a file starting from the beginning.\\n\\tReturns the position and also sets the position there.\\n\\tIf string is not found 0 is returned and position is unchanged.\\\"\\n\\n\\t| pos buffer count oldPos sz |\\n\\toldPos := self position.\\n\\tself reset.\\n\\tsz := self size.\\n\\tpos := 0.\\n\\tbuffer := String new: 2000.\\n\\t[ buffer := self nextInto: buffer.\\n\\t(count := buffer findString: string) > 0\\n\\t\\tifTrue: [\\\"Found the string part way into buffer\\\"\\n\\t\\t\\tself position: pos.\\n\\t\\t\\tself next: count - 1.\\n\\t\\t\\t^self position ].\\n\\tpos := ((pos + 2000 - string size) min: sz).\\n\\tself position: pos.\\n\\tpos = sz] whileFalse.\\n\\t\\\"Never found it, and hit end of file\\\"\\n\\tself position: oldPos.\\n\\t^0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfindStringFromEnd: string\\n\\t\\\"Fast version to find a String in a file starting from the end.\\n\\tReturns the position and also sets the position there.\\n\\tIf string is not found 0 is returned and position is unchanged.\\\"\\n\\n\\t| pos buffer count oldPos |\\n\\toldPos := self position.\\n\\tself setToEnd.\\n\\tpos := self position.\\n\\t[ pos := ((pos - 2000 + string size) max: 0). \\\"the [+ string size] allows for the case where the end of the search string is at the beginning of the current buffer\\\"\\n\\tself position: pos.\\n\\tbuffer := self next: 2000.\\n\\t(count := buffer findString: string) > 0\\n\\t\\tifTrue: [\\\"Found the string part way into buffer\\\"\\n\\t\\t\\tself position: pos.\\n\\t\\t\\tself next: count-1. \\\"use next instead of position:, so that CrLfFileStream can do its magic if it is being used\\\"\\n\\t\\t\\t^self position].\\n\\tpos = 0] whileFalse.\\n\\t\\\"Never found it, and hit beginning of file\\\"\\n\\tself position: oldPos.\\n\\t^0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 2/6/2001 17:59'!\\nflush\\n\\t\\\"Flush pending changes\\\"\\n\\t^self primFlush: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'mir 2/25/2000 12:37'!\\nnext\\n\\t\\\"Answer the next byte from this file, or nil if at the end of the file.\\\"\\n\\n\\t^ self basicNext! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nnext: n\\n\\t\\\"Return a string with the next n characters of the filestream in it. 1/31/96 sw\\\"\\n\\t^ self nextInto: (buffer1 class new: n)! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nnext: n into: aString startingAt: startIndex\\n\\t\\\"Read n bytes into the given string.\\n\\tReturn aString or a partial copy if less than\\n\\tn elements have been read.\\\"\\n\\t| count |\\n\\tcount := self primRead: fileID into: aString\\n\\t\\t\\t\\tstartingAt: startIndex count: n.\\n\\tcount = n\\n\\t\\tifTrue:[^aString]\\n\\t\\tifFalse:[^aString copyFrom: 1 to: startIndex+count-1]! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 1/2/2000 15:33'!\\nnext: anInteger putAll: aString startingAt: startIndex\\n\\t\\\"Store the next anInteger elements from the given collection.\\\"\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tself primWrite: fileID from: aString startingAt: startIndex count: anInteger.\\n\\t^aString! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'jm 9/21/1998 13:55'!\\nnextPut: char\\n\\t\\\"Write the given character to this file.\\\"\\n\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tbuffer1 at: 1 put: char.\\n\\tself primWrite: fileID from: buffer1 startingAt: 1 count: 1.\\n\\t^ char\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:43'!\\nnextPutAll: aString\\n\\t\\\"Write all the characters of the given string to this file.\\\"\\n\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tself primWrite: fileID from: aString startingAt: 1 count: aString basicSize.\\n\\t^ aString\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:58'!\\nnextWordsInto: aBitmap\\n\\t\\\"Note: The file primitives automatically adjust for word based objects.\\\"\\n\\n\\tself next: aBitmap basicSize into: aBitmap startingAt: 1.\\n\\taBitmap restoreEndianness.\\n\\t^ aBitmap! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npadToEndWith: aChar\\n\\t\\\"On the Mac, files do not truncate. One can delete the old file and write a new one, but sometime deletion fails (file still open? file stale?). This is a sad compromise. Just let the file be the same length but pad it with a harmless character.\\\"\\n\\n\\t| pad |\\n\\tself atEnd ifTrue: [^ self].\\n\\tpad := self isBinary \\n\\t\\tifTrue: [aChar asCharacter asciiValue]\\t\\\"ok for char or number\\\"\\n\\t\\tifFalse: [aChar asCharacter].\\n\\tself nextPutAll: (buffer1 class new: ((self size - self position) min: 20000) \\n\\t\\t\\t\\t\\t\\t\\twithAll: pad).! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\t| next |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tnext := self basicNext.\\n\\tself position: self position - 1.\\n\\t^ next! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 10/19/2001 11:29'!\\npeekLast\\n\\t\\\"Return that item just put at the end of the stream\\\"\\n\\n\\t^ buffer1 size > 0 \\n\\t\\tifTrue: [buffer1 last]\\n\\t\\tifFalse: [nil]\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nposition\\n\\t\\\"Return the receiver's current file position. 2/12/96 sw\\\"\\n\\n\\t^ self primGetPosition: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nposition: pos\\n\\t\\\"Set the receiver's position as indicated. 2/12/96 sw\\\"\\n\\n\\t^ self primSetPosition: fileID to: pos! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nreadInto: byteArray startingAt: startIndex count: count\\n\\t\\\"Read into the given array as specified, and return the count\\n\\tactually transferred. index and count are in units of bytes or\\n\\tlongs depending on whether the array is Bitmap, String or ByteArray\\\"\\n\\t^ self primRead: fileID into: byteArray\\n\\t\\t\\tstartingAt: startIndex count: count\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'yo 10/31/2002 22:33'!\\nreadOnlyCopy\\n\\n\\t^ self class readOnlyFileNamed: self name.\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nsetToEnd\\n\\t\\\"Set the position of the receiver to the end of file. 1/31/96 sw\\\"\\n\\n\\tself position: self size! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nskip: n\\n\\t\\\"Set the character position to n characters from the current position.\\n\\tError if not enough characters left in the file. 1/31/96 sw\\\"\\n\\n\\tself position: self position + n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'JMM 5/24/2001 22:00'!\\ntruncate\\n\\t\\\"Truncate to zero\\\"\\n\\n\\t^ self truncate: 0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'JMM 5/24/2001 22:47'!\\ntruncate: pos\\n\\t\\\"Truncate to this position\\\"\\n\\n\\tself position: pos.\\n\\t^self primTruncate: fileID to: pos! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nupTo: delim \\n\\t\\\"Fast version to speed up nextChunk\\\"\\n\\t| pos buffer count |\\n\\tpos := self position.\\n\\tbuffer := self next: 2000.\\n\\t(count := buffer indexOf: delim) > 0 ifTrue: \\n\\t\\t[\\\"Found the delimiter part way into buffer\\\"\\n\\t\\tself position: pos + count.\\n\\t\\t^ buffer copyFrom: 1 to: count - 1].\\n\\tself atEnd ifTrue:\\n\\t\\t[\\\"Never found it, and hit end of file\\\"\\n\\t\\t^ buffer].\\n\\t\\\"Never found it, but there's more...\\\"\\n\\t^ buffer , (self upTo: delim)! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nupToEnd\\n\\t\\\"Answer a subcollection from the current access position through the last element of the receiver.\\\"\\n\\n\\t| newStream buffer |\\n\\tbuffer := buffer1 species new: 1000.\\n\\tnewStream := WriteStream on: (buffer1 species new: 100).\\n\\t[self atEnd] whileFalse: [newStream nextPutAll: (self nextInto: buffer)].\\n\\t^ newStream contents! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'jm 9/21/1998 13:56'!\\nverbatim: aString\\n\\t\\\"A version of nextPutAll that can be called knowing it won't call nextPut: \\\"\\n\\n\\t^ self nextPutAll: aString\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'!\\nregister\\n\\t^self class register: self! !\\n\\n!StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileStream class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileStream class methodsFor: 'browser requests' stamp: 'mir 3/8/2001 16:28'!\\nisRunningAsBrowserPlugin\\n\\tself new waitBrowserReadyFor: 1000 ifFail: [^false].\\n\\t^true! !\\n\\n!StandardFileStream class methodsFor: 'browser requests' stamp: 'mir 9/7/2000 16:08'!\\nprivateCheckForBrowserPrimitives\\n\\t<primitive:'primitivePluginBrowserReady'>\\n\\t^false! !\\n\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileDoesNotExistUserHandling: fullFileName\\n\\n\\t| selection newName |\\n\\tselection := (PopUpMenu labels:\\n'create a new file\\nchoose another name\\ncancel')\\n\\t\\t\\tstartUpWithCaption: (FileDirectory localNameFor: fullFileName) , '\\ndoes not exist.'.\\n\\tselection = 1 ifTrue:\\n\\t\\t[^ self new open: fullFileName forWrite: true].\\n\\tselection = 2 ifTrue:\\n\\t\\t[ newName := FillInTheBlank request: 'Enter a new file name'\\n\\t\\t\\t\\t\\t\\tinitialAnswer: fullFileName.\\n\\t\\t^ self oldFileNamed:\\n\\t\\t\\t(self fullName: newName)].\\n\\tself halt! !\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileExistsUserHandling: fullFileName\\n\\t| dir localName choice newName newFullFileName |\\n\\tdir := FileDirectory forFileName: fullFileName.\\n\\tlocalName := FileDirectory localNameFor: fullFileName.\\n\\tchoice := (PopUpMenu\\n\\t\\tlabels:\\n'overwrite that file\\\\choose another name\\\\cancel' withCRs)\\n\\t\\tstartUpWithCaption: localName, '\\nalready exists.'.\\n\\n\\tchoice = 1 ifTrue: [\\n\\t\\tdir deleteFileNamed: localName\\n\\t\\t\\tifAbsent: [self error: 'Could not delete the old version of that file'].\\n\\t\\t^ self new open: fullFileName forWrite: true].\\n\\n\\tchoice = 2 ifTrue: [\\n\\t\\tnewName := FillInTheBlank request: 'Enter a new file name' initialAnswer: fullFileName.\\n\\t\\tnewFullFileName := self fullName: newName.\\n\\t\\t^ self newFileNamed: newFullFileName].\\n\\n\\tself error: 'Please close this to abort file opening'! !\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnlyFileDoesNotExistUserHandling: fullFileName\\n\\n\\t| dir files choices selection newName fileName |\\n\\tdir := FileDirectory forFileName: fullFileName.\\n\\tfiles := dir fileNames.\\n\\tfileName := FileDirectory localNameFor: fullFileName.\\n\\tchoices := fileName correctAgainst: files.\\n\\tchoices add: 'Choose another name'.\\n\\tchoices add: 'Cancel'.\\n\\tselection := (PopUpMenu labelArray: choices lines: (Array with: 5) )\\n\\t\\tstartUpWithCaption: (FileDirectory localNameFor: fullFileName), '\\ndoes not exist.'.\\n\\tselection = choices size ifTrue:[\\\"cancel\\\" ^ nil \\\"should we raise another exception here?\\\"].\\n\\tselection < (choices size - 1) ifTrue: [\\n\\t\\tnewName := (dir pathName , FileDirectory slash , (choices at: selection))].\\n\\tselection = (choices size - 1) ifTrue: [\\n\\t\\tnewName := FillInTheBlank \\n\\t\\t\\t\\t\\t\\t\\trequest: 'Enter a new file name' \\n\\t\\t\\t\\t\\t\\t\\tinitialAnswer: fileName].\\n\\tnewName = '' ifFalse: [^ self readOnlyFileNamed: (self fullName: newName)].\\n\\t^ self error: 'Could not open a file'! !\\n\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'TPR 8/13/1999 21:22'!\\nfileNamed: fileName\\n\\t\\\"Open a file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close.\\\"\\n\\n\\t^ self new open: (self fullName: fileName) forWrite: true\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nforceNewFileNamed: fileName \\n\\t\\\"Create a new file with the given name, and answer a stream opened \\n\\tfor writing on that file. If the file already exists, delete it without \\n\\tasking before creating the new file.\\\"\\n\\t| dir localName fullName f |\\n\\tfullName := self fullName: fileName.\\n\\t(self isAFileNamed: fullName)\\n\\t\\tifFalse: [f := self new open: fullName forWrite: true.\\n\\t\\t\\t^ f isNil\\n\\t\\t\\t\\tifTrue: [\\\"Failed to open the file\\\"\\n\\t\\t\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]\\n\\t\\t\\t\\tifFalse: [f]].\\n\\tdir := FileDirectory forFileName: fullName.\\n\\tlocalName := FileDirectory localNameFor: fullName.\\n\\tdir\\n\\t\\tdeleteFileNamed: localName\\n\\t\\tifAbsent: [(CannotDeleteFileException new\\n\\t\\t\\tmessageText: 'Could not delete the old version of file ' , fullName) signal].\\n\\tf := self new open: fullName forWrite: true.\\n\\t^ f isNil\\n\\t\\tifTrue: [\\\"Failed to open the file\\\"\\n\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]\\n\\t\\tifFalse: [f]! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nisAFileNamed: fileName\\n\\t\\\"Answer true if a file of the given name exists.\\\"\\n\\n\\t| f |\\n\\tf := self new open: fileName forWrite: false.\\n\\tf ifNil: [^ false].\\n\\tf close.\\n\\t^ true\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nnewFileNamed: fileName\\n \\t\\\"Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, ask the user what to do.\\\"\\n\\n\\t| fullName |\\n\\tfullName := self fullName: fileName.\\n\\n\\t^(self isAFileNamed: fullName)\\n\\t\\tifTrue: [\\\"file already exists:\\\"\\n\\t\\t\\t(FileExistsException fileName: fullName fileClass: self) signal]\\n\\t\\tifFalse: [self new open: fullName forWrite: true]\\n\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\noldFileNamed: fileName\\n\\t\\\"Open an existing file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close.\\\"\\n\\n\\t| fullName |\\n\\tfullName := self fullName: fileName.\\n\\n\\t^(self isAFileNamed: fullName)\\n\\t\\tifTrue: [self new open: fullName forWrite: true]\\n\\t\\tifFalse: [\\\"File does not exist...\\\"\\n\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnlyFileNamed: fileName \\n\\t\\\"Open an existing file with the given name for reading.\\\"\\n\\n\\t| fullName f |\\n\\tfullName := self fullName: fileName.\\n\\tf := self new open: fullName forWrite: false.\\n\\t^ f isNil\\n\\t\\tifFalse: [f]\\n\\t\\tifTrue: [\\\"File does not exist...\\\"\\n\\t\\t\\t((FileDoesNotExistException fileName: fullName) readOnly: true) signal].\\n\\n\\t\\\"StandardFileStream readOnlyFileNamed: 'kjsd.txt' \\\"! !\\n\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nretryWithGC: execBlock until: testBlock forFileNamed: fullName\\n\\t\\\"Re-implemented to only force GC if a file with the given name exists\\\"\\n\\t| blockValue foundIt |\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\t\\\"See if we have a file with the given name\\\"\\n\\tfoundIt := Registry keys \\\"hold on strongly for now\\\" \\n\\t\\tanySatisfy:[:file| file name sameAs: fullName].\\n\\tfoundIt ifFalse:[^blockValue].\\n\\tSmalltalk garbageCollectMost.\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollect.\\n\\t^execBlock value.! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:23'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\nObject subclass: #StandardScriptingSystem\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ClassVarNamesInUse FormDictionary HelpStrings StandardPartsBin'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Refactoring Candidates'!\\n!StandardScriptingSystem commentStamp: '<historical>' prior: 0!\\nAn instance of this is installed as the value of the global variable \\\"ScriptingSystem\\\". Client subclasses are invited, such as one used internally by squeak team for ongoing internal work.!\\n\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:45'!\\ndeletePrivateGraphics\\n\\t\\\"ScriptingSystem deletePrivateGraphics\\\"\\n\\tself deletePrivateGraphics: self privateGraphics\\n\\t\\tafterStoringToFileNamed: 'disGraphics'! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'di 2/3/2001 20:10'!\\ndeletePrivateGraphics: nameList afterStoringToFileNamed: aFileName\\n\\t\\\"This method is used to strip private graphics from the FormDictionary and store them on a file of the given name\\\"\\n\\n\\t| replacement toRemove aReferenceStream keySymbol |\\n\\ttoRemove _ Dictionary new.\\n\\treplacement _ FormDictionary at: #Gets.\\n\\n\\tnameList do:\\n\\t\\t[:aKey |\\n\\t\\t\\tkeySymbol _ aKey asSymbol.\\n\\t\\t\\t(toRemove at: keySymbol put: (self formAtKey: keySymbol)).\\n\\t\\t\\tFormDictionary at: keySymbol put: replacement].\\n\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\taReferenceStream nextPut: toRemove.\\n\\taReferenceStream close! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 2/24/2003 16:28'!\\nformAtKey: aString\\n\\t\\\"Answer the form saved under the given key\\\"\\n\\n\\tSymbol hasInterned: aString ifTrue:\\n\\t\\t[:aKey | ^ FormDictionary at: aKey ifAbsent: [nil]].\\n\\t^ nil! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:46'!\\nformAtKey: aKey extent: extent depth: depth\\n\\t\\\"ScriptingSystem saveForm: (TileMorph downPicture) atKey: 'downArrow'\\\"\\n\\t^ FormDictionary at: aKey asSymbol ifAbsent: [Form extent: extent depth: depth]! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:49'!\\nformDictionary\\n\\t^FormDictionary! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sd 5/11/2003 21:32'!\\ninspectFormDictionary\\n\\t\\\"ScriptingSystem inspectFormDictionary\\\"\\n\\t\\n\\tGraphicalDictionaryMenu openOn: FormDictionary withLabel: 'Testing One Two Three'! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:44'!\\nprivateGraphics\\n\\t\\\"ScriptingSystem deletePrivateGraphics\\\"\\n\\t^#(#BadgeMiniPic #BadgePic #Broom #CedarPic #CollagePic #CoverMain #CoverSpiral #CoverTexture #Fred #ImagiPic #KayaPic #StudioPic)! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 10/6/1999 20:57'!\\nsaveForm: aForm atKey: aKey\\n\\tFormDictionary at: aKey asSymbol put: aForm! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 10/24/1998 14:12'!\\nsqueakyMouseForm\\n\\t^ self formAtKey: 'squeakyMouse'\\n\\n\\\"\\n\\tScriptingSystem saveForm: (Form\\n\\textent: 30@29\\n\\tdepth: 16\\n\\tfromArray: #( 1811114995 1878286257 2012637171 1811180532 1811180533 1811179508 1811180532 1811179508 1744006133 1878289396 1811180533 1878289396 1744007156 1674736630 1744006132 1811114995 1811181556 1744006131 1811246068 1811180532 1811179508 1811180532 1744071668 1811113972 1811180532 1811180532 1811179507 1878288338 1945529332 1744071668 1743941620 1811112945 1811179506 1811114995 1744006131 1744006130 1744005106 1811048434 1811113969 1743939570 1811179506 1743939571 1676833782 1676765171 1811047410 1744006131 1811048435 1811116020 1811180531 1743939571 1811048435 1743939570 1743939570 1743939570 1743940594 1744005106 1811181556 1811180532 1676766196 1743939570 1878420468 1676963830 1189896082 1811245044 1744137204 1744070644 1811179508 1811113971 1743939571 1811179508 1811246070 1811309524 1811302093 1811310580 1811246068 1674867703 1744049472 1120606594 1118465013 1744137205 1811179508 1811180532 1744071667 1744006132 1811112947 1811247095 1605584589 358761132 289435638 1676830707 1741975543 1462778473 1811312631 702891724 1811310548 1945528308 1811178450 1945528307 1878288372 1878353875 1878421494 1051471335 1809213397 1118524175 1811246068 1945659348 1185698607 1878486005 1672694510 1118531574 1607626741 1878420467 1811180533 1743942645 1744072693 1811301035 1185770487 1878486006 1324239597 1811180533 1811116019 1120623438 1878352818 1945462739 704868339 1878289395 1811049459 1878221808 1878223859 1743876083 1811162563 1945463796 1811181556 1464746666 1811116018 1809019893 1120551562 1945464821 1741844468 1466842760 1878289395 1811048434 1811050483 1811050483 1878223859 1049188174 1741910004 1811181556 1256998634 1811114994 1878289396 1466840647 1744007156 1744006131 1676877216 1743940596 1878222835 1743938545 1878351792 1676833781 358641652 1743940596 1811050484 845566798 1811113970 1811114995 1811163652 1811112913 1878420468 1878282028 1811179506 1607560178 1878289395 1676900342 1878351825 1466853330 1811113971 1811116019 635659217 1811179506 1811245045 1676942754 1744137206 1744201717 1676962806 1676962805 1811310581 1676896245 1744199635 1811376117 1744072695 1744005109 1811244019 499279861 1811310581 1811244020 1811293668 1399943159 1605528567 1744136181 982063522 986342388 1744070645 1744189066 430063308 1744071669 1744070644 1744067504 566519797 1744136181 1744137205 1743999854 912813044 1811311606 1742162607 4195488 283139922 1945531382 1253113857 144710948 1601400791 1811246069 1811167879 1464821747 1744136180 1674799094 1811178482 843473875 1811311606 1878533542 2106790 2080066222 1876193270 696845376 627472380 1185772536 1878355957 1743990309 1744007157 1676898294 1744006132 1811114996 1743941620 1811180533 1809204941 4194368 4217681 1878290421 1252982848 4194336 1670540278 1739811795 1878353906 1744006131 1811179506 1744007157 1744005106 1945462771 1811182582 1811311574 1393641133 1462856629 2012638196 1876382449 1112301394 1742041045 1945596917 1676833781 1811113970 1811179507 1811180532 1672705014 1674735606 1672697648 1945725943 1878551479 1809215479 1811312629 1809216504 1809215479 1809215478 1462853490 1878487029 1744007158 1744005075 1811239726 704979363 495004132 700789287 562372997 631646663 1739998892 4194400 1116497846 698688932 562375109 770124262 633609569 495070758 1257010166 562315916 1809279958 2012894002 1047280171 980237901 910966381 1668677696 4194400 6314867 1047281260 908804749 910968495 1393719290 1809279959 1185750370 1809214455 1878469062 423836236 1532188466 1601592148 1462986647 1672937568 4194368 6319062 1603622706 1601525554 1601522417 1047336194 770206679 1878487031 1878409899 977955830 1809145716 1118586509 980105834 980045584 1811372914 980104778 1605526483 1395605131 910769804 1118651052 1534358520 1809136234 1118596053 1532059506 1878485973 1326456163 1945660374 1742106615 1811311607 1945725942 1742107641 1744072693 1811311605 1744203767 1878551543 564478604 1878553591 1603428242 1811048433 1811049459 1051290611 1744006131 1811049459 1878156273 1743874034 1744007156 1743874033 1811048434 1811113970 1743939571 1743933228 1603301363 1743875059 1811049458 1945461745 1811181556 1811113971 1811049458 1811048434 1811116020 1878287346 1878223857 1743940594 1744006130 1744007157 1945395153 1945400309 1811048434 1743810547 1676765170 1878353906 1811113970 1743874032 1810983921 1743874033 1811113971 1676765169 1743874034 1743940593 1743939569 1811047409 1676765168 1743940595 1810981872 1945397235 1607560179 1743941620 1810982897 1810983921 1811048433 1744007155 1743875059 1811048434 1743875058 1743939568 1676832754 1811116019 1811114994 1811244019 1676962805 1677029367 1811244020 1744005106 1743940594 1811246068 1744070645 1676961781 1744004084 1676897269 1811180533 1878353908 1744004083 1744070645)\\n\\toffset: 0@0) atKey: 'squeakyMouse'\\\"! !\\n\\n\\n!StandardScriptingSystem methodsFor: 'help dictionary' stamp: 'dgd 9/1/2003 14:25'!\\nhelpStringOrNilFor: aSymbol \\n\\t\\\"If my HelpStrings dictionary has an entry at the given symbol, \\n\\tanswer that entry's value, else answer nil\\\"\\n\\tHelpStrings\\n\\t\\tat: aSymbol\\n\\t\\tifPresent:[:string | ^ string translated].\\n^ nil! !\\n\\n!StandardScriptingSystem methodsFor: 'help dictionary' stamp: 'sw 6/15/1999 17:03'!\\ninitializeHelpStrings\\n\\t\\\"Initialize the data structure that determines, for the etoy system, help messages for various scripting elements. The structure is built up by letting every Morph subclass contribute elements simply by implementing method #helpContributions. Consult implementors of #helpContributions for examples of how this goes.\\\"\\n\\n\\t\\\"ScriptingSystem initializeHelpStrings\\\"\\n\\n\\t| aDictionary |\\n\\taDictionary _ IdentityDictionary new. \\n\\t\\\"For safety, the new copy is built up in this temp first, so that if an error occurs during the creation of the structure, the old version will remain remain in place\\\"\\n\\n\\tMorph withAllSubclasses do:\\n\\t\\t[:aClass | (aClass class selectors includes: #helpContributions)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[aClass helpContributions do:\\n\\t\\t\\t\\t\\t[:pair | aDictionary at: pair first put: pair second]]].\\n\\n\\t\\tHelpStrings _ aDictionary! !\\n\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 10/30/2000 16:33'!\\nallClassVarNamesInSystem\\n\\t\\\"Compute and answer a set of all the class variable names known to the sytem from any class\\\"\\n\\n\\t| aList |\\n\\taList _ OrderedCollection new.\\n\\tObject withAllSubclasses do:\\n\\t\\t[:c | aList addAll: c allClassVarNames].\\n\\t^ aList asSet\\n\\n\\t\\\"ScriptingSystem allClassVarNamesInSystem\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 6/16/2005 01:35'!\\ncustomizeForEToyUsers: aBoolean\\n\\t\\\"If aBoolean is true, set things up for etoy users. If it's false, unset some of those things. Some things are set when switching into etoy mode but not reversed when switching out of etoy mode.\\\"\\n \\n\\t#(\\t\\n\\t\\t(allowEtoyUserCustomEvents\\tno\\t\\treverse)\\n\\t\\t(balloonHelpEnabled\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(debugHaloHandle\\t\\t\\tno\\t\\treverse)\\n\\t\\t(modalColorPickers\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(oliveHandleForScriptedObjects\\tno\\tdontReverse)\\n\\t\\t(uniqueNamesInHalos\\t\\tyes\\t\\treverse)\\n\\t\\t(useUndo\\t\\t\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(infiniteUndo\\t\\t\\t\\tno\\t\\tdontReverse)\\n\\t\\t(warnIfNoChangesFile\\t\\tno\\t\\treverse)\\n\\t\\t(warnIfNoSourcesFile\\t\\tno\\t\\treverse)) do:\\n\\t\\t\\t[:trip |\\n\\t\\t\\t\\t(aBoolean or: [trip third == #reverse]) ifTrue:\\n\\t\\t\\t\\t\\t[Preferences enableOrDisable: trip first asPer:\\n\\t\\t\\t\\t\\t\\t((trip second == #yes) & aBoolean) | ((trip second == #no) & aBoolean not)]]! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 4/6/2005 09:30'!\\nsoundNamesToSuppress\\n\\t\\\"Answer a list of sound-names that are not to be offered in sound-choice pop-ups unless they are the current choice\\\"\\n\\n\\t^ #('scrape' 'scritch' 'peaks')! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 11/26/1999 15:44'!\\nstripGraphicsForExternalRelease\\n\\t\\\"ScriptingSystem stripGraphicsForExternalRelease\\\"\\n\\n\\t| replacement |\\n\\treplacement _ FormDictionary at: #Gets.\\n\\n\\t#('BadgeMiniPic' 'BadgePic' 'Broom' 'CedarPic' 'CollagePic' 'CoverMain' 'CoverSpiral' 'CoverTexture' 'Fred' 'ImagiPic' 'KayaPic' 'StudioPic')\\n\\t\\tdo:\\n\\t\\t\\t[:aKey | FormDictionary at: aKey asSymbol put: replacement]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 07:47'!\\naddCustomEventFor: registrantClass named: aSymbol help: helpString targetMorphClass: targetClass\\n\\t| registration |\\n\\tregistration _ self customEventsRegistry at: aSymbol ifAbsentPut: [ IdentityDictionary new ].\\n\\tregistration at: registrantClass put: { helpString. targetClass }.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:23'!\\naddUserCustomEventNamed: aSymbol help: helpString\\n\\tself currentWorld addUserCustomEventNamed: aSymbol help: helpString.\\n\\t\\\"Vocabulary addStandardVocabulary: UserCustomEventNameType new.\\\"\\n\\tVocabulary customEventsVocabulary.\\n\\tSymbolListTile updateAllTilesForVocabularyNamed: #CustomEvents! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 08:19'!\\ncustomEventNamesAndHelpStringsFor: aPlayer\\n\\t| retval help helpStrings morph |\\n\\tmorph := aPlayer costume renderedMorph.\\n\\tretval := SortedCollection sortBlock: [ :a :b | a first < b first ].\\n\\tself customEventsRegistry\\n\\t\\tkeysAndValuesDo: [ :k :v |\\n\\t\\t\\thelpStrings := Array streamContents: [ :hsStream |\\n\\t\\t\\t\\tv keysAndValuesDo: [ :registrant :array |\\n\\t\\t\\t\\t\\t(morph isKindOf: array second) ifTrue: [\\n\\t\\t\\t\\t\\t\\thelp := String streamContents: [ :stream |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv size > 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [ stream nextPut: $(;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnextPutAll: array second name;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnextPut: $);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspace ].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstream nextPutAll: array first ].\\n\\t\\t\\t\\t\\t\\thsStream nextPut: help ]]].\\n\\t\\t\\thelpStrings isEmpty ifFalse: [retval add: { k. helpStrings } ]].\\n\\t^ retval! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:31'!\\ncustomEventStati\\n\\t^self globalCustomEventNames,\\n\\tself userCustomEventNames! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 10/12/2003 13:14'!\\ncustomEventsRegistry\\n\\t^Smalltalk at: #CustomEventsRegistry ifAbsentPut: [ IdentityDictionary new ].! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:30'!\\nglobalCustomEventNames\\n\\t^self customEventsRegistry keys asArray sort! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 07:56'!\\nglobalCustomEventNamesFor: aPlayer\\n\\t| morph names |\\n\\tmorph := aPlayer costume renderedMorph.\\n\\tnames := SortedCollection new.\\n\\tself customEventsRegistry keysAndValuesDo: [ :k :v |\\n\\t\\t(v anySatisfy: [ :array | morph isKindOf: array second ])\\n\\t\\t\\tifTrue: [ names add: k ]].\\n\\t^names asArray! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 7/20/2003 12:37'!\\nremoveCustomEventNamed: aSymbol for: registrant\\n\\t| registration helpString |\\n\\tregistration _ self customEventsRegistry at: aSymbol ifAbsent: [ ^nil ].\\n\\thelpString _ registration removeKey: registrant ifAbsent: [].\\n\\tregistration isEmpty ifTrue: [ self customEventsRegistry removeKey: aSymbol ].\\n\\t^helpString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:26'!\\nremoveUserCustomEventNamed: eventName\\n\\t| retval |\\n\\tretval _ self currentWorld removeUserCustomEventNamed: eventName.\\n\\t\\\"Vocabulary addStandardVocabulary: UserCustomEventNameType new.\\\"\\n\\tVocabulary customEventsVocabulary.\\n\\tSymbolListTile updateAllTilesForVocabularyNamed: #CustomEvents.\\n\\t^retval! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 6/30/2004 18:16'!\\nstandardEventStati\\n\\t\\\"Answer the events that can be directed to a particular morph by its event handler.\\\"\\n\\t^ #(mouseDown\\t\\\"run when mouse goes down on me\\\"\\n\\t\\tmouseStillDown\\t\\\"while mouse still down\\\"\\n\\t\\tmouseUp\\t\\t\\\"when mouse comes back up\\\"\\n\\t\\tmouseEnter\\t\\\"when mouse enters my bounds, button up\\\"\\n\\t\\tmouseLeave\\t\\\"when mouse exits my bounds, button up\\\"\\n\\t\\tmouseEnterDragging\\t\\\"when mouse enters my bounds, button down\\\"\\n\\t\\tmouseLeaveDragging\\t\\\"when mouse exits my bounds, button down\\\"\\n\\t\\t\\\"keyStroke\\\"\\n\\t\\t\\\"gesture\\\"\\n\\t)\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:22'!\\nuserCustomEventNames\\n\\t^ self currentWorld userCustomEventNames! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-help dictionary' stamp: 'nk 11/1/2004 08:21'!\\nstatusHelpStringFor: aPlayer\\n\\t^String streamContents: [ :stream |\\n\\t\\tstream nextPutAll: 'normal -- run when called\\npaused -- ready to run all the time\\nticking -- run all the time\\nmouseDown -- run when mouse goes down on me\\nmouseStillDown -- while mouse still down\\nmouseUp -- when mouse comes back up\\nmouseEnter -- when mouse enters my bounds, button up\\nmouseLeave -- when mouse exits my bounds, button up\\nmouseEnterDragging -- when mouse enters my bounds, button down\\nmouseLeaveDragging -- when mouse exits my bounds, button down\\nopening -- when I am being opened\\nclosing -- when I am being closed' translated.\\n\\n\\\"'keyStroke -- run when user hits a key' \\\"\\n\\n\\tstream cr; cr; nextPutAll: 'More events:' translated; cr.\\n\\n\\t(self customEventNamesAndHelpStringsFor: aPlayer) do: [ :array |\\n\\t\\tstream cr;\\n\\t\\tnextPutAll: array first;\\n\\t\\tnextPutAll: ' -- '.\\n\\t\\tarray second do: [ :help | stream nextPutAll: help translated ]\\n\\t\\t\\tseparatedBy: [ stream nextPutAll: ' or ' translated ]].\\n\\n\\t(Preferences allowEtoyUserCustomEvents) ifTrue: [\\n\\tself userCustomEventNames isEmpty ifFalse: [\\n\\t\\tstream cr; cr; nextPutAll: 'User custom events:' translated; cr.\\n\\t\\tself currentWorld userCustomEventsRegistry keysAndValuesDo: [ :key :value |\\n\\t\\t\\tstream cr; nextPutAll: key; nextPutAll: ' -- '; nextPutAll: value ]]]]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 5/2/1998 14:26'!\\ncolorBehindTiles\\n\\t^ Color r: 0.903 g: 1.0 b: 0.903! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'dgd 7/12/2003 12:06'!\\nfontForNameEditingInScriptor\\n\\t^ Preferences standardEToysFont! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'dgd 7/12/2003 12:05'!\\nfontForTiles\\n\\t^ Preferences standardEToysFont! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'nk 7/12/2003 08:59'!\\nsmallBoldFont\\n\\t\\\"Answer a small bold font for use in some standard scripting-support structures\\\"\\n\\n\\t^ StrikeFont familyName: Preferences standardEToysFont familyName size: 12! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 9/14/1998 14:41'!\\nstatusColorSymbolFor: statusSymbol\\n\\t#(\\t(normal\\t\\t\\t\\t\\tgreen)\\n\\t\\t(ticking\\t\\t\\t\\t\\tblue)\\n\\t\\t(paused\\t\\t\\t\\t\\tred)\\n\\t\\t(mouseDown\\t\\t\\t\\tyellow)\\n\\t\\t(mouseStillDown\\t\\t\\tlightYellow)\\n\\t\\t(mouseUp\\t\\t\\t\\tlightBlue)\\n\\t\\t(mouseEnter\\t\\t\\t\\tlightBrown)\\n\\t\\t(mouseLeave\\t\\t\\tlightRed)\\n\\t\\t(mouseEnterDragging\\tlightGray)\\n\\t\\t(mouseLeaveDragging\\tdarkGray)\\n\\t\\t(keyStroke\\t\\t\\t\\tlightGreen)) do:\\n\\n\\t\\t\\t[:pair | statusSymbol == pair first ifTrue: [^ pair second]].\\n\\n\\t\\t^ #blue! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 5/2/1998 14:23'!\\nuniformTileInteriorColor\\n\\t^ Color r: 0.806 g: 1.0 b: 0.806! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/12/1999 10:09'!\\ninstallSolidMenuForm\\n\\t\\\"ScriptingSystem installSolidMenuForm\\\"\\n\\tself saveForm:\\n\\t\\t(Form extent: 14@16 depth: 16\\n\\tfromArray: #( 1 0 0 0 0 0 0 65537 65536 0 0 0 65537 0 65537 65537 65537 65537 65537 65537 65536 65537 65537 65537 65537 65537 1600061441 65536 65537 1600085855 1600085855 1600085855 1600085855 1600061441 65536 65537 1600085855 65537 65537 65537 65537 65536 65537 1600085855 65537 65537 65537 1600061441 65536 65537 1600085855 1600085855 1600085855 1600085855 1600085855 65537 65537 1600085855 65537 65537 65537 1600085855 65537 65537 1600085855 1600061441 65537 65537 89951 65537 65537 1600085855 1600085855 1600085855 1600085855 1600085855 65537 65537 1600085855 1600061441 65537 65537 65537 65537 65537 1600085855 65537 65537 65537 65536 65537 65537 65537 65537 65537 65537 65537 65537 1 65537 65537 65537 65537 65537 65536 0 65536 0 0 0 0 0) offset: 0@0)\\n\\t\\tatKey: 'SolidMenu'! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 11/26/1999 15:37'!\\nmergeGraphicsFrom: aDictionary\\n\\t\\\"aDictionary is assumed to hold associations of the form <formName> -> <form>. Merge the graphics held by that dictionary into the internal FormDictionary, overlaying any existing entries with the ones found in aDictionary\\\"\\n\\n\\taDictionary associationsDo:\\n\\t\\t[:assoc | self saveForm: assoc value atKey: assoc key]\\n\\n\\t\\t\\\"works ok even if keys in aDictionary are strings rather than symbols\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 2/20/2002 01:09'!\\npatchInNewStandardPlayerForm\\n\\t\\\"Patch in a darker and larger representation of a Dot. No senders -- called from the postscript of an update\\\"\\n\\n\\t\\\"ScriptingSystem patchInNewStandardPlayerForm\\\"\\n\\n\\tFormDictionary at: #standardPlayer put:\\n\\t\\t(Form\\n\\textent: 13@13\\n\\tdepth: 16\\n\\tfromArray: #( 0 0 0 65536 0 0 0 0 0 65537 65537 65536 0 0 0 65537 65537 65537 65537 65536 0 0 65537 65537 65537 65537 65536 0 1 65537 65537 65537 65537 65537 0 1 65537 65537 65537 65537 65537 0 65537 65537 65537 65537 65537 65537 65536 1 65537 65537 65537 65537 65537 0 1 65537 65537 65537 65537 65537 0 0 65537 65537 65537 65537 65536 0 0 65537 65537 65537 65537 65536 0 0 0 65537 65537 65536 0 0 0 0 0 65536 0 0 0)\\n\\toffset: 0@0)! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/2/1998 14:01'!\\nreadFormsFromFileNamed: aFileName\\n\\t\\\"Read the entire FormDictionary in from a designated file on disk\\\"\\n\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\tFormDictionary _ aReferenceStream next.\\n\\taReferenceStream close\\n\\n\\t\\\"ScriptingSystem readFormsFromFileNamed: 'EToyForms22Apr'\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 9/14/2000 21:29'!\\nreadFormsFromFileNamed: aFileName andStoreIntoGlobal: globalName\\n\\t\\\"Read the a FormDictionary in from a designated file on disk and save it in the designated global\\\"\\n\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\tSmalltalk at: globalName put: aReferenceStream next.\\n\\taReferenceStream close\\n\\n\\t\\\"ScriptingSystem readFormsFromFileNamed: 'SystemFormsFromFwdF.forms' andStoreIntoGlobal: #FormsTemp\\\"\\n\\n\\t\\\"ScriptingSystem saveForm: (FormsTemp at: #StackElementDesignationHelp) atKey: #StackElementDesignationHelp\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 4/23/1999 11:24'!\\nrestorePrivateGraphics\\n\\t\\\"ScriptingSystem restorePrivateGraphics\\\"\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: 'disGraphics'.\\n\\tself mergeGraphicsFrom: aReferenceStream next.\\n\\taReferenceStream close.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/6/1998 17:46'!\\nsaveFormsToFileNamed: aFileName\\n\\t\\\"Save the current state of form dictionary to disk for possible later retrieval\\\"\\n \\t (ReferenceStream fileNamed: aFileName) nextPut: FormDictionary; close\\n\\n\\t\\\"ScriptingSystem saveFormsToFileNamed: 'SystemForms06May98.forms'\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 12/7/1998 16:47'!\\nstandardForms\\n\\t\\\"ScriptingSystem standardForms\\\"\\n\\t^ FormDictionary collect: [:f | f]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'tk 10/20/2004 15:52'!\\nanyButtonPressedTiles\\n\\t\\\"Answer tiles representing the query 'is any button pressed?'\\\"\\n\\n\\t^ self tilesForQuery: '(ActiveHand anyButtonPressed)' label: 'button down?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 11/16/2004 13:56'!\\nnoButtonPressedTiles\\n\\t\\\"Answer tiles representing the query 'is no button pressed?'\\\"\\n\\n\\t^ self tilesForQuery: '(ActiveHand noButtonPressed)' label: 'button up?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 5/3/1999 22:40'!\\nprototypicalHolder\\n\\t| aHolder |\\n\\taHolder _ PasteUpMorph authoringPrototype color: Color orange muchLighter; borderColor: Color orange lighter.\\n\\taHolder setNameTo: 'holder'; extent: 160 @ 110.\\n\\t^ aHolder behaveLikeHolder.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 10/27/1998 13:35'!\\nresetStandardPartsBin\\n\\t\\\"ScriptingSystem resetStandardPartsBin\\\"\\n\\n\\tStandardPartsBin _ nil! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 7/3/2001 08:01'!\\ntilesForQuery: expressionString label: aLabel\\n\\t\\\"Answer scripting tiles that represent the query,\\\"\\n\\n\\t| aPhrase aTile |\\n\\taPhrase _ SystemQueryPhrase new.\\n\\taTile _ BooleanTile new.\\n\\taTile setExpression: expressionString label: aLabel.\\n\\taPhrase addMorph: aTile.\\n\\t^ aPhrase\\n! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:40'!\\ngoButton\\n\\t| aButton |\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\taButton image: (ScriptingSystem formAtKey: 'GoPicOn');\\n\\t\\t\\toffImage: (ScriptingSystem formAtKey: 'GoPic');\\n\\t\\t\\tpressedImage: (ScriptingSystem formAtKey: 'GoPicOn');\\n\\t\\t\\tactionSelector: #goUp:with:; \\n\\t\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\t\\tactWhen: #buttonUp;\\n\\t\\t\\ttarget: self;\\n\\t\\t\\tsetNameTo: 'Go Button';\\n\\t\\t\\tsetBalloonText:\\n'Resume running all paused scripts' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 11/11/1998 15:24'!\\ngoUp: evt with: aGoButton\\n\\taGoButton presenter startRunningScriptsFrom: aGoButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 1/23/2001 11:39'!\\nscriptControlButtons\\n\\t\\\"Answer a composite object that serves to control the stop/stop/go status of a Presenter\\\"\\n\\n\\t| wrapper |\\n\\twrapper _ AlignmentMorph newRow setNameTo: 'script controls'.\\n\\twrapper vResizing: #shrinkWrap.\\n\\twrapper hResizing: #shrinkWrap.\\n\\twrapper addMorph: self stopButton.\\n\\twrapper addMorphBack: self stepButton.\\n\\twrapper addMorphBack: self goButton.\\n\\twrapper beTransparent.\\n\\t^ wrapper! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:41'!\\nstepButton\\n\\t| aButton |\\n\\tself flag: #deferred. \\\"ambiguity about recipients\\\"\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\t\\taButton\\n\\t\\t\\timage: (ScriptingSystem formAtKey: 'StepPicOn');\\n\\t\\t\\toffImage: (ScriptingSystem formAtKey: 'StepPic');\\n\\t\\t\\tpressedImage: (ScriptingSystem formAtKey: 'StepPicOn');\\n\\t\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\t \\tactionSelector: #stepStillDown:with:; \\n\\t\\t\\ttarget: self;\\n\\t\\t\\tsetNameTo: 'Step Button'; \\n\\t\\t\\tactWhen: #whilePressed;\\n\\t\\t\\ton: #mouseDown send: #stepDown:with: to: self;\\n\\t\\t\\ton: #mouseStillDown send: #stepStillDown:with: to: self;\\n\\t\\t\\ton: #mouseUp send: #stepUp:with: to: self;\\n\\t\\t\\tsetBalloonText:\\n'Run every paused script exactly once. Keep the mouse button down over \\\"Step\\\" and everything will keep running until you release it' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:33'!\\nstepDown: evt with: aMorph\\n\\taMorph presenter stopRunningScripts! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:35'!\\nstepStillDown: dummy with: theButton\\n\\ttheButton presenter stepStillDown: dummy with: theButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:35'!\\nstepUp: evt with: aMorph\\n\\taMorph presenter stepUp: evt with: aMorph! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:41'!\\nstopButton\\n\\t\\\"Answer a new button that can serve as a stop button\\\"\\n\\t| aButton |\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\taButton\\n\\t\\timage: (ScriptingSystem formAtKey: 'StopPic');\\n\\t\\toffImage: (ScriptingSystem formAtKey: 'StopPic');\\n\\t\\tpressedImage: (ScriptingSystem formAtKey: 'StopPicOn').\\n\\t\\taButton actionSelector: #stopUp:with:; \\n\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\tactWhen: #buttonUp;\\n\\t\\ttarget: self;\\n\\t\\tsetNameTo: 'Stop Button'; \\n\\t\\tsetBalloonText: 'Pause all ticking scripts.' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 11/11/1998 15:16'!\\nstopUp: dummy with: theButton\\n\\t| aPresenter |\\n\\t(aPresenter _ theButton presenter) flushPlayerListCache. \\\"catch guys not in cache but who're running\\\"\\n\\taPresenter stopRunningScriptsFrom: theButton! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 8/28/2004 15:19'!\\ncolorForType: typeSymbol\\n\\t\\\"Answer the color to use to represent the given type symbol\\\"\\n\\n\\ttrue ifTrue:\\n\\t\\t[^ self standardTileBorderColor].\\n\\n\\ttypeSymbol capitalized = #Command ifTrue:\\n\\t\\t[^ Color fromRgbTriplet: #(0.065 0.258 1.0)].\\n\\t\\\"Command is historical and idiosyncratic and should be regularized\\\"\\n\\n\\t^ (Vocabulary vocabularyForType: typeSymbol) typeColor! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 10/29/1998 16:18'!\\ncolorFudge\\n\\t^ 0.4! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 8/28/2004 20:31'!\\nstandardTileBorderColor\\n\\t\\\"Answer the color to use for tile borders\\\"\\n\\n\\t^ Color r: 0.804 g: 0.76 b: 0.564! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'sw 1/4/2005 02:20'!\\nacceptableSlotNameFrom: originalString forSlotCurrentlyNamed: currentName asSlotNameIn: aPlayer world: aWorld\\n\\t\\\"Produce an acceptable slot name, derived from the current name, for aPlayer. This method will always return a valid slot name that will be suitable for use in the given situation, though you might not like its beauty sometimes.\\\"\\n\\n\\t| aString stemAndSuffix proscribed stem suffix putative |\\n\\taString _ originalString asIdentifier: false. \\\"get an identifier not lowercase\\\"\\n\\tstemAndSuffix _ aString stemAndNumericSuffix.\\n\\tproscribed _ #(self super thisContext costume costumes dependents #true #false size), aPlayer class allInstVarNames.\\n\\n\\tstem _ stemAndSuffix first.\\n\\tsuffix _ stemAndSuffix last.\\n\\tputative _ aString asSymbol.\\n\\t\\n\\t[(putative ~~ currentName) and: [(proscribed includes: putative)\\n\\t\\tor:\\t[(aPlayer respondsTo: putative)\\n\\t\\tor:\\t[Smalltalk includesKey: putative]]]]\\n\\twhileTrue:\\n\\t\\t[suffix _ suffix + 1.\\n\\t\\tputative _ (stem, suffix printString) asSymbol].\\n\\t^ putative! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'kfr 9/23/2003 09:29'!\\ndoesOperatorWantArrows: aSymbol\\n\\taSymbol = #, ifTrue:[^ false].\\n\\t^ aSymbol isInfix or: [#(isDivisibleBy:) includes: aSymbol]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'sw 9/27/2001 04:08'!\\nsystemSlotNamesOfType: aType\\n\\t\\\"Answer the type of the slot name, or nil if not found.\\\"\\n\\t\\n\\t| aList |\\n\\tself flag: #deferred. \\\"Hard-coded etoyVocabulary needed here to make this work.\\\"\\n\\taList _ OrderedCollection new.\\n\\tVocabulary eToyVocabulary methodInterfacesDo:\\n\\t\\t [:anInterface |\\n\\t\\t\\tanInterface resultType = aType ifTrue:\\n\\t\\t\\t\\t[aList add: anInterface selector]].\\n\\t^ aList! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:37'!\\nallKnownClassVariableNames\\n\\t\\\"Answer a set of all the knwon class variable names in the system. This normally retrieves them from a cache, and at present there is no organized mechanism for invalidating the cache. The idea is to avoid, in the References scheme, names that may create a conflict\\\"\\n\\n\\t^ ClassVarNamesInUse ifNil: [ClassVarNamesInUse _ self allClassVarNamesInSystem]\\n\\n\\t\\\"ClassVarNamesInUse _ nil.\\n\\tTime millisecondsToRun: [ScriptingSystem allKnownClassVariableNames]\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'kfr 9/23/2003 09:44'!\\narithmeticalOperatorsAndHelpStrings\\n\\t\\\"Answer an array consisting of lists of the standard arithmetical operator tiles and of the corresponding balloon help for them\\\"\\n\\n\\t^ #((+ - * / // \\\\\\\\ max: min:)\\n\\t \\t('add' 'subtract' 'multiply' 'divide' 'divide & truncate' 'remainder when divided by' 'larger value' 'smaller value' ))! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 10/20/2004 15:52'!\\nbuttonDownTile\\n\\t\\\"Answer a boolean-valued tile which reports whether the button is down\\\"\\n\\n\\t^ self systemQueryPhraseWithActionString: '(ActiveHand anyButtonPressed)' labelled: 'button down?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 10/20/2004 15:52'!\\nbuttonUpTile\\n\\t\\\"Answer a boolean-valued tile which reports whether the button is up\\\"\\n\\n\\t^ self systemQueryPhraseWithActionString: '(ActiveHand noButtonPressed)' labelled: 'button up?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 8/21/2000 12:59'!\\ncleanupsForRelease\\n\\t\\\"Miscellaneous space cleanups to do before a release.\\\"\\n\\t\\\"EToySystem cleanupsForRelease\\\"\\n\\n\\tSocket deadServer: ''. \\\"Don't reveal any specific server name\\\"\\n\\tHandMorph initialize. \\\"free cached ColorChart\\\"\\n\\tPaintBoxMorph initialize.\\t\\\"forces Prototype to let go of extra things it might hold\\\"\\n\\tSmalltalk removeKey: #AA ifAbsent: [].\\n\\tSmalltalk removeKey: #BB ifAbsent: [].\\n\\tSmalltalk removeKey: #CC ifAbsent: [].\\n\\tSmalltalk removeKey: #DD ifAbsent: [].\\n\\tSmalltalk removeKey: #Temp ifAbsent: [].\\n\\n\\tScriptingSystem reclaimSpace.\\n\\tSmalltalk cleanOutUndeclared.\\n\\tSmalltalk reclaimDependents.\\n\\tSmalltalk forgetDoIts.\\n\\tSmalltalk removeEmptyMessageCategories.\\n\\tSymbol rehash! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 3/10/2004 23:24'!\\nhelpStringForOperator: anOperator\\n\\t\\\"Answer the help string associated with the given operator. If none found, return a standard no-help-available reply\\\"\\n\\n\\t^ (self helpStringOrNilForOperator: anOperator) ifNil:\\n\\t\\t['Sorry, no help available here' translated] \\\"This should never be seen, but is provided as a backstop\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 6/27/2004 11:11'!\\nhelpStringOrNilForOperator: anOperator\\n\\t\\\"Answer the help string associated with the given operator, nil if none found.\\\"\\n\\n\\t| anIndex opsAndHelp |\\n\\t(anIndex _ (opsAndHelp _ self arithmeticalOperatorsAndHelpStrings) first indexOf: anOperator) > 0\\n\\t\\tifTrue:\\t[^ (opsAndHelp second at: anIndex) translated].\\n\\n\\t(anIndex _ (opsAndHelp _ self numericComparitorsAndHelpStrings) first indexOf: anOperator) > 0\\n\\t\\tifTrue:\\t[^ (opsAndHelp second at: anIndex) translated].\\n\\n\\tanOperator = #, ifTrue:\\n\\t\\t[^ 'Concatenate two Strings' translated].\\n\\n\\t^ nil! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'nk 7/12/2003 08:59'!\\nholderWithAlphabet\\n\\t\\\"Answer a fully instantiated Holder that has submorphs that represent the letters of the uppercase alphabet, with each one having an 'index' slot which bears the letter's index in the alphabet -- 1 for A, 2 for B, etc. A few special characters are provided as per ack request 10/00; for these the index provided is rather arbitrarily assigned\\\"\\n\\n\\t| aMorph aPlayer newMorph oneCharString aContainer aWrapper |\\n\\n\\t\\\"ScriptingSystem holderWithAlphabet openInHand\\\"\\n\\n\\taContainer _ self prototypicalHolder useRoundedCorners.\\n\\taContainer borderColor: Color blue lighter.\\n\\n\\taWrapper _ AlignmentMorph new hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutInset: 0.\\n\\taWrapper addMorphBack: (aMorph _ TextMorph new contents: 'A').\\n\\taMorph beAllFont: ((TextStyle named: Preferences standardEToysFont familyName) fontOfSize: 24).\\n\\taMorph width: 14; lock.\\n\\taWrapper beTransparent; setNameTo: 'A'.\\n\\taPlayer _ aWrapper assuredPlayer.\\n\\taPlayer addInstanceVariableNamed: #index type: #Number value: 1.\\n\\taContainer addMorphBack: aWrapper.\\n\\t2 to: 26 do:\\n\\t\\t[:anIndex |\\n\\t\\t\\tnewMorph _ aWrapper usableSiblingInstance.\\n\\t\\t\\tnewMorph player perform: #setIndex: with: anIndex.\\n\\t\\t\\tnewMorph firstSubmorph contents: (oneCharString _ ($A asciiValue + anIndex - 1) asCharacter asString).\\n\\t\\t\\tnewMorph setNameTo: oneCharString.\\n\\n\\t\\t\\taContainer addMorphBack: newMorph].\\n\\n\\t#(' ' '.' '#') with: #(27 28 29) do:\\n\\t\\t[:aString :anIndex |\\n\\t\\t\\tnewMorph _ aWrapper usableSiblingInstance.\\n\\t\\t\\tnewMorph player perform: #setIndex: with: anIndex.\\n\\t\\t\\tnewMorph firstSubmorph contents: aString.\\n\\t\\t\\taString = ' '\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[newMorph setNameTo: 'space'.\\n\\t\\t\\t\\t\\tnewMorph color: (Color gray alpha: 0.2)]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[newMorph setNameTo: aString].\\n\\t\\t\\taContainer addMorphBack: newMorph].\\n\\n\\taContainer setNameTo: 'alphabet'.\\n\\taContainer isPartsBin: true.\\n\\taContainer enableDrop: false.\\n\\taContainer indicateCursor: false; width: 162.\\n\\taContainer color: (Color r: 0.839 g: 1.0 b: 1.0). \\\"Color fromUser\\\"\\n\\t^ aContainer! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/15/2000 06:24'!\\ninformScriptingUser: aString\\n\\t\\\"This provides a hook for logging messages that the user or the developer may wish to see; at present it simply logs the message to the Transcript, with a standard prefix to signal their provenance. Such messages will fall on the floor if there is no Transcript window open\\\"\\n\\n\\tTranscript cr; show: 'SCRIPT NOTE: ', aString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/26/2003 22:44'!\\nnameForInstanceVariablesCategory\\n\\t\\\"Answer the name to use for the viewer category that contains instance variables\\\"\\n\\n\\t^ #variables \\n\\t\\\"^ #'instance variables'\\\"\\n\\n\\\"ScriptingSystem nameForInstanceVariablesCategory\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/6/2003 18:00'!\\nnameForScriptsCategory\\n\\t\\\"Answer the name to use for the viewer category that contains scripts\\\"\\n\\n\\t^ #scripts! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/18/2001 17:50'!\\nnewScriptingSpace\\n\\t\\\"Answer a complete scripting space - raa 19 sept 2000 - experiment for Alan, a variant *not* in a window, now adopted as the only true scripting space\\\"\\n\\n\\t^ self newScriptingSpace2! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 11/13/2001 14:41'!\\nnewScriptingSpace2\\n\\t\\\"Answer a complete scripting space\\\"\\n\\n\\t| aTemplate aPlayfield aControl |\\n\\t\\n\\t(aTemplate _ PasteUpMorph new)\\n\\t\\tsetNameTo: 'etoy';\\n\\t\\textent: 638 @ 470;\\n\\t\\tcolor: Color white;\\n\\t\\timpartPrivatePresenter;\\n\\t\\tsetProperty: #automaticPhraseExpansion toValue: true;\\n\\t\\tbeSticky.\\n\\taTemplate useRoundedCorners; borderWidth: 2. \\n\\taControl _ ScriptingSystem scriptControlButtons setToAdhereToEdge: #bottomLeft.\\n\\taControl beSticky; borderWidth: 0; beTransparent.\\n\\taTemplate addMorphBack: aControl.\\n\\taTemplate presenter addTrashCan.\\n\\n\\taTemplate addMorph: (aPlayfield _ PasteUpMorph new).\\n\\taPlayfield\\n\\t\\tsetNameTo: 'playfield';\\n\\t\\tuseRoundedCorners;\\n\\t\\tsetToAdhereToEdge: #topLeft;\\n\\t\\textent: 340@300;\\n\\t\\tposition: aTemplate topRight - (400@0);\\n\\t\\tbeSticky;\\n\\t\\tautomaticViewing: true;\\n\\t\\twantsMouseOverHalos: true.\\n\\taTemplate presenter standardPlayfield: aPlayfield.\\n\\t\\n\\t^ aTemplate\\n\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/21/2000 22:39'!\\nnumericComparitorsAndHelpStrings\\n\\t\\\"Answer an array whose first element is the list of comparitors, and whose second element is a list of the corresponding help strings\\\"\\n\\n\\t^ #((< <= = ~= > >= isDivisibleBy:)\\n\\t \\t('less than' 'less than or equal' 'equal' 'not equal' 'greater than' 'greater than or equal' 'divisible by' ))! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities'!\\nprepareForExternalReleaseNamed: aReleaseName\\n\\t\\\"ScriptingSystem prepareForExternalReleaseNamed: '2.2Beta'\\\"\\n\\n\\tEToySystem stripMethodsForExternalRelease.\\n\\n\\tScriptingSystem saveFormsToFileNamed: aReleaseName, '.Dis.Forms'.\\n\\tScriptingSystem stripGraphicsForExternalRelease.\\n\\tScriptingSystem cleanupsForRelease.\\n\\tScreenController initialize.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 5/2/1998 14:17'!\\nreclaimSpace\\n\\t\\\"Reclaim space from the scripting system, and report the result in an informer\\\"\\n\\t\\\"ScriptingSystem reclaimSpace\\\"\\n\\n\\t| reclaimed |\\n\\t(reclaimed _ self spaceReclaimed) > 0\\n\\t\\tifTrue:\\t[self inform: reclaimed printString, ' bytes reclaimed']\\n\\t\\tifFalse:\\t[self inform: 'Hmm... Nothing gained this time.']! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 09:08'!\\nreferenceAt: aSymbol\\n\\t\\\"Answer the object referred to by aSymbol in the 'References' scheme of things, or nil if none\\\"\\n\\n\\t^ References at: aSymbol ifAbsent: [nil]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 09:33'!\\nreferenceAt: aSymbol put: anObject\\n\\t\\\"Store a reference to anObject at the given symbol in the References directory\\\"\\n\\n\\t^ References at: aSymbol put: anObject! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 6/9/2000 18:44'!\\nreinvigorateThumbnailsInViewerFlapTabs\\n\\t\\\"It has happened that the thumbnail in a viewer flap tab will go solid gray because it got associated with some passing and disused player temporarily created during the initial painting process. This method takes a sledge hammer to repair such thumbnails. At its genesis, this method is called only from the postscript of its defining fileout.\\\"\\n\\t| vwr thumbnail |\\n\\tViewerFlapTab allInstancesDo:\\n\\t\\t[:aTab | \\n\\t\\t\\tvwr _ aTab referent findA: StandardViewer.\\n\\t\\t\\tthumbnail _ aTab findA: ThumbnailMorph.\\n\\t\\t\\t(vwr notNil and: [thumbnail notNil]) ifTrue:\\n\\t\\t\\t\\t[thumbnail objectToView: vwr scriptedPlayer]]\\n\\n\\t\\\"ScriptingSystem reinvigorateThumbnailsInViewerFlapTabs\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 12/20/2003 18:02'!\\nreportToUser: aString\\n\\t\\\"Make a message accessible to the user. For the moment, we simply defer to the Transcript mechanism\\\"\\n\\n\\tTranscript cr; show: aString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:47'!\\nresetAllScriptingReferences\\n\\t\\\"Clear out all the elements in the References directory\\\"\\n\\t\\n\\tSmalltalk at: #References put: IdentityDictionary new\\n\\n\\t\\\"ScriptingSystem resetAllScriptingReferences\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:45'!\\nresetStaleScriptingReferences\\n\\t\\\"Remove all scripting references that are no longer needed\\\"\\n\\n\\tReferences removeUnreferencedKeys\\n\\n\\t\\\"ScriptingSystem resetStaleScriptingReferences\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 7/25/2004 17:27'!\\nrestoreClassicEToyLook\\n\\t\\\"Restore classic EToy look, as closely as possible. If ComicBold is present, restore it as the standard etoy and button font. Substitute ComicSansMS and Accuny as respective alternatives if the classic fonts are absent. If those also aren't available, do nothing.\\\"\\n\\n\\t| aTextStyle aFont | \\n\\t(aTextStyle _ TextStyle named: #ComicBold)\\n\\t\\tifNotNil:\\n\\t\\t\\t[aFont _ aTextStyle fontOfSize: 16.\\n\\t\\t\\tPreferences setEToysFontTo: aFont.\\n\\t\\t\\tPreferences setButtonFontTo: aFont]\\n\\t\\tifNil:\\n\\t\\t\\t[(aTextStyle _ TextStyle named: #ComicSansMS) ifNotNil:\\n\\t\\t\\t\\t[Preferences setEToysFontTo: (aTextStyle fontOfSize: 18)].\\n\\t\\t\\t(aTextStyle _ TextStyle named: #Accuny) ifNotNil:\\n\\t\\t\\t\\t[Preferences setButtonFontTo: (aTextStyle fontOfSize: 12)]].\\n\\n\\t(aTextStyle _ TextStyle named: #NewYork)\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences setSystemFontTo: (aTextStyle fontOfSize: 12)]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 5/16/2001 12:58'!\\nsetterSelectorForGetter: aGetterSymbol\\n\\t\\\"Answer the setter selector corresponding to a given getter\\\"\\n\\n\\t^ (('s', (aGetterSymbol copyFrom: 2 to: aGetterSymbol size)), ':') asSymbol\\n\\n\\t\\\"ScriptingSystem setterSelectorForGetter: #getCursor\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'di 3/3/2001 08:47'!\\nspaceReclaimed\\n\\t\\\"Reclaim space from the EToy system, and return the number of bytes reclaimed\\\"\\n\\t\\\"ScriptingSystem spaceReclaimed\\\"\\n\\n\\t| oldFree |\\n\\toldFree _ Smalltalk garbageCollect.\\n\\tThumbnailMorph recursionReset.\\n\\tPlayer removeUninstantiatedSubclassesSilently.\\n\\tSmalltalk cleanOutUndeclared.\\n\\tSmalltalk reclaimDependents.\\n\\t^ Smalltalk garbageCollect - oldFree.! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/27/2001 13:28'!\\ntileForArgType: aType\\n\\t\\\"Anwer a default tile to represent a datum of the given argument type, which may be either a symbol (e.g. #Color) or a class\\\"\\n\\n\\t(aType isKindOf: Class) \\\"Allowed in Ted's work\\\"\\n\\t\\tifTrue:\\n\\t\\t\\t[^ aType name asString newTileMorphRepresentative typeColor: Color gray].\\n\\n\\t^ (Vocabulary vocabularyForType: aType) defaultArgumentTile! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'dgd 7/12/2003 12:05'!\\ntryButtonFor: aPhraseTileMorph \\n\\t| aButton |\\n\\taButton := SimpleButtonMorph new.\\n\\taButton target: aPhraseTileMorph;\\n\\t\\t actionSelector: #try;\\n\\t\\t\\n\\t\\tlabel: '!!'\\n\\t\\tfont: Preferences standardEToysFont;\\n\\t\\t color: Color yellow;\\n\\t\\t borderWidth: 0.\\n\\taButton actWhen: #whilePressed.\\n\\taButton balloonTextSelector: #try.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'nk 10/14/2004 11:19'!\\nwordingForOperator: aString\\n\\t\\\"Answer the wording to be seen by the user for the given operator symbol/string\\\"\\n\\n\\t| toTest |\\n\\ttoTest _ aString asString.\\n\\t#(\\t(append:\\t\\t\\t\\t'include at end')\\n\\t\\t(arrowheadsOnAllPens\\t'arrowheads on all pens')\\n\\t\\t(beep:\\t\\t\\t\\t\\t'make sound')\\n\\t\\t(bounce:\\t\\t\\t\\t'bounce')\\n\\t\\t(clearTurtleTrails\\t\\t'clear pen trails')\\n\\t\\t(clearOwnersPenTrails\\t'clear all pen trails')\\n\\t\\t(colorSees\\t\\t\\t\\t'color sees')\\n\\t\\t(color:sees:\\t\\t\\t\\t'color sees')\\n\\t\\t(doMenuItem:\\t\\t\\t'do menu item')\\n\\t\\t(doScript:\\t\\t\\t\\t'do')\\n\\t\\t(forward:\\t\\t\\t\\t'forward by')\\n\\t\\t(goToRightOf:\\t\\t\\t'align after')\\n\\t\\t(includeAtCursor:\\t\\t'include at cursor')\\n\\t\\t(isDivisibleBy:\\t\\t\\t'is divisible by')\\n\\t\\t(liftAllPens\\t\\t\\t\\t'lift all pens')\\n\\t\\t(lowerAllPens\\t\\t\\t'lower all pens')\\n\\t\\t(makeNewDrawingIn:\\t'start painting in')\\n\\t\\t(max:\\t\\t\\t\\t\\t'max')\\n\\t\\t(min:\\t\\t\\t\\t\\t'min')\\n\\t\\t(moveToward:\\t\\t\\t'move toward')\\n\\t\\t(noArrowheadsOnAllPens\\t'no arrowheads on pens')\\n\\t\\t(overlapsAny\\t\\t\\t'overlaps any')\\n\\t\\t(pauseAll:\\t\\t\\t\\t'pause all')\\n\\t\\t(pauseScript:\\t\\t\\t'pause script')\\n\\t\\t(prepend:\\t\\t\\t\\t'include at beginning')\\n\\t\\t(seesColor:\\t\\t\\t\\t'is over color')\\n\\t\\t(startAll:\\t\\t\\t\\t'start all')\\n\\t\\t(startScript:\\t\\t\\t\\t'start script')\\n\\t\\t(stopProgramatically\\t'stop')\\n\\t\\t(stopAll:\\t\\t\\t\\t\\t'stop all')\\n\\t\\t(stopScript:\\t\\t\\t\\t'stop script')\\n\\t\\t(tellAllSiblings:\\t\\t\\t'tell all siblings')\\n\\t\\t(tellSelfAndAllSiblings:\\t'send to all')\\n\\t\\t(turn:\\t\\t\\t\\t\\t'turn by')\\n\\t\\t(turnToward:\\t\\t\\t\\t'turn toward')\\n\\t\\t(wearCostumeOf:\\t\\t'look like'))\\n\\n\\tdo:\\n\\t\\t[:pair | toTest = pair first ifTrue: [^ pair second]].\\n\\n\\t^ toTest\\n\\n\\t\\\"StandardScriptingSystem initialize\\\"\\n\\n! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-viewer' stamp: 'sw 10/30/2000 09:07'!\\nuniqueNameForReference\\n\\t\\\"Answer a more-or-less global name by which the receiver can be referred to in scripts\\\"\\n\\n\\t^ #ScriptingSystem! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardScriptingSystem class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardScriptingSystem class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 19:04'!\\ninitialize\\n\\t\\\"Initialize the scripting system. Sometimes this method is vacuously changed just to get it in a changeset so that its invocation will occur as part of an update\\\"\\n\\n\\t(self environment at: #ScriptingSystem ifAbsent: [nil]) ifNil:\\n\\t\\t[self environment at: #ScriptingSystem put: self new].\\n\\n\\tScriptingSystem\\n\\t\\tinitializeHelpStrings.\\n\\n\\tself registerInFlapsRegistry.\\n\\n\\\"StandardScriptingSystem initialize\\\"! !\\n\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'nk 9/1/2004 10:53'!\\napplyNewEToyLook\\n\\t\\\"Apply the new EToy look based on free fonts, approximating the classic look as closely as possible.\\\"\\n\\n\\t\\\"StandardScriptingSystem applyNewEToyLook\\\"\\n\\n\\\"\\t| aTextStyle aFont | \\n\\taTextStyle _ TextStyle named: #BitstreamVeraSansMono.\\n\\taFont _ aTextStyle fontOfSize: 12.\\n\\taFont _ aFont emphasis: 1.\\n\\tPreferences setEToysFontTo: aFont.\\n\\tPreferences setButtonFontTo: aFont.\\n\\n\\taTextStyle _ TextStyle named: #Accushi.\\n\\taFont _ aTextStyle fontOfSize: 12.\\n\\tPreferences setFlapsFontTo: aFont.\\n\\n\\t(aTextStyle _ TextStyle named: #Accuny)\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences setSystemFontTo: (aTextStyle fontOfSize: 12)]\\\"\\n\\n\\tPreferences setDefaultFonts: #(\\n\\t\\t(setEToysFontTo:\\t\\t\\tBitstreamVeraSansBold\\t10)\\n\\t\\t(setButtonFontTo:\\t\\tBitstreamVeraSansMono\\t9)\\n\\t\\t(setFlapsFontTo:\\t\\t\\tAccushi\\t\\t\\t\\t12)\\n\\t\\t(setSystemFontTo:\\t\\tAccuny\\t\\t\\t\\t10)\\n\\t\\t(setWindowTitleFontTo:\\tBitstreamVeraSansBold\\t12)\\n\\t)\\n! !\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'mir 11/26/2004 16:14'!\\nremovePlayersIn: project\\n\\t\\\"Remove existing player references for project\\\"\\n\\n\\tReferences keys do: \\n\\t\\t[:key | (References at: key) costume pasteUpMorph == project world\\n\\t\\t\\tifTrue: [References removeKey: key]].\\n! !\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'mir 11/25/2004 19:01'!\\nremoveUnreferencedPlayers\\n\\t\\\"Remove existing but unreferenced player references\\\"\\n\\t\\\"StandardScriptingSystem removeUnreferencedPlayers\\\"\\n\\tReferences keys do: \\n\\t\\t[:key | (References at: key) costume pasteUpMorph\\n\\t\\t\\tifNil: [References removeKey: key]].\\n! !\\n\\n\\n!StandardScriptingSystem class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/11/2003 19:08'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(ScriptingSystem\\tprototypicalHolder\\t'Holder'\\t\\t'A place for storing alternative pictures in an animation, etc.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tprototypicalHolder\\t'Holder'\\t\\t'A place for storing alternative pictures in an animation, etc.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tnewScriptingSpace\\t'Scripting'\\t'A confined place for drawing and scripting, with its own private stop/step/go buttons.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tholderWithAlphabet\\t'Alphabet'\\t'A source for single-letter objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.]! !\\n\\n!StandardScriptingSystem class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/12/2003 14:38'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: ScriptingSystem] ! !\\n\\n\\n\\n!StandardScriptingSystem class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/8/2004 19:06'!\\nnoteAddedSelector: aSelector meta: isMeta\\n\\taSelector == #wordingForOperator: ifTrue:\\n\\t\\t[Vocabulary changeMadeToViewerAdditions].\\n\\tsuper noteAddedSelector: aSelector meta: isMeta! !\\n\\n!StandardScriptingSystem class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/15/2004 12:41'!\\nnoteCompilationOf: aSelector meta: isMeta\\n\\t\\\"This method does nothing and should be removed.\\\"\\n\\n\\t^ super noteCompilationOf: aSelector meta: isMeta! !\\nSourceFileArray subclass: #StandardSourceFileArray\\n\\tinstanceVariableNames: 'files'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-System'!\\n!StandardSourceFileArray commentStamp: '<historical>' prior: 0!\\nThis class implements the source file management behavior of traditional Squeak, with a sources file and a changes file. File positions are mapped such that those files can be up to 32MBytes in size.\\n\\nStructure:\\n files\\t\\tArray -- storing the actual source files\\n!\\n\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nat: index\\n\\t^files at: index! !\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nat: index put: aFile\\n\\tfiles at: index put: aFile! !\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nsize\\n\\t^files size! !\\n\\n\\n!StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninitialize\\n\\tfiles := Array new: 2.\\n\\tfiles at: 1 put: (SourceFiles at: 1).\\n\\tfiles at: 2 put: (SourceFiles at: 2)! !\\n\\n!StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninitialize: nFiles\\n\\tfiles := Array new: nFiles! !\\n\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileIndexFromSourcePointer: anInteger\\n\\t\\\"Return the index of the source file which contains the source chunk addressed by anInteger\\\"\\n\\t\\\"This implements the recent 32M source file algorithm\\\"\\n\\n\\t| hi |\\n\\thi := anInteger // 16r1000000.\\n\\t^hi < 3\\n\\t\\tifTrue: [hi]\\n\\t\\tifFalse: [hi - 2]! !\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfilePositionFromSourcePointer: anInteger\\n\\t\\\"Return the position of the source chunk addressed by anInteger\\\"\\n\\t\\\"This implements the recent 32M source file algorithm\\\"\\n\\n\\t| hi lo |\\n\\thi := anInteger // 16r1000000.\\n\\tlo := anInteger \\\\\\\\ 16r1000000.\\n\\t^hi < 3\\n\\t\\tifTrue: [lo]\\n\\t\\tifFalse: [lo + 16r1000000]! !\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nsourcePointerFromFileIndex: index andPosition: position\\n\\t| hi lo |\\n\\t\\\"Return a source pointer according to the new 32M algorithm\\\"\\n\\t((index between: 1 and: 2) and: [position between: 0 and: 16r1FFFFFF])\\n\\t\\tifFalse: [self error: 'invalid source code pointer'].\\n\\thi := index.\\n\\tlo := position.\\n\\tlo >= 16r1000000 ifTrue: [\\n\\t\\thi := hi+2.\\n\\t\\tlo := lo - 16r1000000].\\n\\t^hi * 16r1000000 + lo! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSourceFileArray class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'nk 7/30/2004 21:50'!\\ninstall\\n\\t\\\"Replace SourceFiles by an instance of me with the standard sources and changes files.\\n\\tThis only works if SourceFiles is either an Array or an instance of this class\\\"\\n\\n\\t\\\"StandardSourceFileArray install\\\"\\n\\n\\tSourceFiles := self new! !\\n\\n!StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'ar 5/17/2000 18:27'!\\nnew: nFiles\\n\\t^self new initialize: nFiles.! !\\nMouseMenuController subclass: #StandardSystemController\\n\\tinstanceVariableNames: 'status'\\n\\tclassVariableNames: 'HBorderCursor ScheduledBlueButtonMenu ScheduledBlueButtonMessages VBorderCursor'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StandardSystemController commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StandardSystemController methodsFor: 'basic control sequence' stamp: 'sw 10/20/1999 09:52'!\\ncontrolInitialize\\n\\tview displayEmphasized.\\n\\tview uncacheBits. \\\"Release cached bitmap while active\\\"\\n\\tmodel windowActiveOnFirstClick ifFalse: [sensor waitNoButton].\\n\\tstatus _ #active.\\n\\tview isCollapsed ifFalse: [model modelWakeUpIn: view]! !\\n\\n!StandardSystemController methodsFor: 'basic control sequence' stamp: 'di 5/11/1999 22:05'!\\ncontrolTerminate\\n\\tstatus == #closed\\n\\t\\tifTrue: \\n\\t\\t\\t[view ~~ nil ifTrue: [view release].\\n\\t\\t\\tScheduledControllers unschedule: self.\\n\\t\\t\\t^self].\\n\\tview deEmphasize; cacheBits.\\n\\tview isCollapsed ifFalse: [model modelSleep].! !\\n\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:45'!\\nadjustPaneBorders \\n\\t| side sub newRect outerFrame |\\n\\touterFrame _ view displayBox.\\n\\tside _ #none.\\n\\tVBorderCursor showWhile:\\n\\t\\t[ [sub _ view subviewWithLongestSide: [:s | side _ s]\\n\\t\\t\\t\\t\\t\\tnear: sensor cursorPoint.\\n\\t\\t self cursorOnBorder and: [(side = #left) | (side = #right)]]\\n\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\tself interActivityPause.\\n\\t\\t\\t\\tsensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[side = #left ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withLeft: sensor cursorPoint x)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tside = #right ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withRight: sensor cursorPoint x)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tview reframePanesAdjoining: sub along: side to: newRect]]].\\n\\tHBorderCursor showWhile:\\n\\t\\t[ [sub _ view subviewWithLongestSide: [:s | side _ s]\\n\\t\\t\\t\\t\\t\\tnear: sensor cursorPoint.\\n\\t\\t self cursorOnBorder and: [(side = #top) | (side = #bottom)]]\\n\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\tself interActivityPause.\\n\\t\\t\\t\\tsensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[side = #top ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withTop: sensor cursorPoint y)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tside = #bottom ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withBottom: sensor cursorPoint y)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tview reframePanesAdjoining: sub along: side to: newRect]]]! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:22'!\\nadjustWindowBorders \\n\\t| side noClickYet |\\n\\tnoClickYet _ true.\\n\\tVBorderCursor showWhile:\\n\\t\\t[ [side _ view displayBox sideNearestTo: sensor cursorPoint.\\n\\t\\t self cursorOnBorder\\n\\t\\t\\tand: [(side = #left) | (side = #right)\\n\\t\\t\\tand: [noClickYet or: [sensor redButtonPressed]]]]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[sensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[noClickYet _ false.\\n\\t\\t\\t\\tside = #left ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withLeft: sensor cursorPoint x]].\\n\\t\\t\\t\\tside = #right ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withRight: sensor cursorPoint x]]].\\n\\t\\t\\tself interActivityPause]].\\n\\tHBorderCursor showWhile:\\n\\t\\t[ [side _ view displayBox sideNearestTo: sensor cursorPoint.\\n\\t\\t self cursorOnBorder\\n\\t\\t\\tand: [(side = #top) | (side = #bottom)\\n\\t\\t\\tand: [noClickYet or: [sensor redButtonPressed]]]]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[sensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[noClickYet _ false.\\n\\t\\t\\t\\tside = #top ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withTop: sensor cursorPoint y]].\\n\\t\\t\\t\\tside = #bottom ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withBottom: sensor cursorPoint y]]].\\n\\t\\t self interActivityPause]]! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:38'!\\nadjustWindowCorners \\n\\t| box cornerBox p clicked f2 |\\n\\tbox _ view windowBox.\\n\\tclicked _ false.\\n\\t#(topLeft topRight bottomRight bottomLeft)\\n\\t\\tdo: [:readCorner |\\n\\t\\t\\tcornerBox _ ((box insetBy: 2) perform: readCorner) - (10@10) extent: 20@20.\\n\\t\\t\\t(cornerBox containsPoint: sensor cursorPoint)\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[\\\"Display reverse: cornerBox.\\\"\\n\\t\\t\\t\\t(Cursor perform: readCorner) showWhile:\\n\\t\\t\\t\\t\\t[[(cornerBox containsPoint: (p _ sensor cursorPoint))\\n\\t\\t\\t\\t\\t\\tand: [(clicked _ sensor anyButtonPressed) not]]\\n\\t\\t\\t\\t\\t\\twhileTrue: [ self interActivityPause ].\\n\\t\\t\\t\\t\\\"Display reverse: cornerBox.\\\"\\n\\t\\t\\t\\tclicked ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame:\\n\\t\\t\\t\\t\\t\\t[:f | p _ sensor cursorPoint.\\n\\t\\t\\t\\t\\t\\treadCorner = #topLeft ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ p corner: f bottomRight].\\n\\t\\t\\t\\t\\t\\treadCorner = #bottomLeft ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ (f withBottom: p y) withLeft: p x].\\n\\t\\t\\t\\t\\t\\treadCorner = #bottomRight ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ f topLeft corner: p].\\n\\t\\t\\t\\t\\t\\treadCorner = #topRight ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ (f withTop: p y) withRight: p x].\\n\\t\\t\\t\\t\\t\\tf2]]]]].\\n\\t^ clicked! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:30'!\\ncheckForReframe\\n\\t| cp |\\n\\tview isCollapsed ifTrue: [^ self].\\n\\tcp _ sensor cursorPoint.\\n\\t((view closeBoxFrame expandBy: 2) containsPoint: cp)\\n\\t\\t| ((view growBoxFrame expandBy: 2) containsPoint: cp)\\n\\t\\tifTrue: [^ self]. \\\"Dont let reframe interfere with close/grow\\\"\\n\\tself adjustWindowCorners.\\n\\tself cursorOnBorder ifFalse: [^ self].\\n\\t((view insetDisplayBox insetBy: 2@2) containsPoint: cp)\\n\\t\\tifFalse: [^ self adjustWindowBorders].\\n\\tview subViews size <= 1 ifTrue: [^ self].\\n\\t(view subviewWithLongestSide: [:s | ] near: cp) == nil\\n\\t\\tifFalse: [^ self adjustPaneBorders].! !\\n\\n!StandardSystemController methodsFor: 'borders'!\\ncursorOnBorder \\n\\t| cp i box |\\n\\tview isCollapsed ifTrue: [^ false].\\n\\tcp _ sensor cursorPoint.\\n\\t((view labelDisplayBox insetBy: (0@2 corner: 0@-2)) containsPoint: cp)\\n\\t\\tifTrue: [^ false].\\n\\t(i _ view subViews findFirst: [:v | v displayBox containsPoint: cp]) = 0\\n\\t\\tifTrue: [box _ view windowBox]\\n\\t\\tifFalse: [box _ (view subViews at: i) insetDisplayBox].\\n\\t^ ((box insetBy: 3) containsPoint: cp) not\\n\\t\\tand: [(box expandBy: 4) containsPoint: cp]! !\\n\\n!StandardSystemController methodsFor: 'borders'!\\nfullScreen\\n\\t\\\"Make the receiver's window occupy jes' about the full screen. 6/10/96 sw\\\"\\n\\n\\tview fullScreen! !\\n\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:01'!\\nblueButtonActivity\\n\\tScheduledBlueButtonMenu ifNil: [^ super controlActivity].\\n\\tScheduledBlueButtonMenu invokeOn: self! !\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:20'!\\ncontrolActivity\\n\\tself checkForReframe.\\n\\t^ super controlActivity! !\\n\\n!StandardSystemController methodsFor: 'control defaults'!\\nisControlActive\\n\\tstatus == #active ifFalse: [^ false].\\n\\tsensor anyButtonPressed ifFalse: [^ true].\\n\\tself viewHasCursor\\n\\t\\tifTrue: [^ true]\\n\\t\\tifFalse: [ScheduledControllers noteNewTop.\\n\\t\\t\\t\\t^ false]! !\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/15/2000 22:19'!\\nredButtonActivity\\n\\t\\\"If cursor is in label of a window when red button is pushed,\\n\\tcheck for closeBox or growBox, else drag the window frame\\n\\tor edit the label.\\\"\\n\\n\\t| box p |\\n\\tp _ sensor cursorPoint.\\n\\tself labelHasCursor ifFalse: [super redButtonActivity. ^ self].\\n\\t((box _ view closeBoxFrame) containsPoint: p)\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed: [self close. ^ self].\\n\\t\\t\\t^ self].\\n\\t((box _ view growBoxFrame) containsPoint: p)\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed:\\n\\t\\t\\t\\t\\t[Sensor controlKeyPressed ifTrue: [^ self expand; fullScreen].\\n\\t\\t\\t\\t\\t^ view isCollapsed\\n\\t\\t\\t\\t\\t\\tifTrue: [self expand]\\n\\t\\t\\t\\t\\t\\tifFalse: [self collapse]].\\n\\t\\t\\t^ self].\\n\\t(((box _ view labelTextRegion expandBy: 1) containsPoint: p)\\n\\t\\t\\tand: [Preferences clickOnLabelToEdit or: [sensor leftShiftDown]])\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed: [^ self label].\\n\\t\\t\\t^ self].\\n\\tself move! !\\n\\n\\n!StandardSystemController methodsFor: 'cursor'!\\nlabelHasCursor\\n\\t\\\"Answer true if the cursor is within the window's label\\\"\\n\\t^view labelContainsPoint: sensor cursorPoint! !\\n\\n\\n!StandardSystemController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 11:48'!\\ninitialize\\n\\tsuper initialize.\\n\\tstatus _ #inactive! !\\n\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nchooseColor\\n\\t\\\"Allow the user to specify a new background color for the receiver's window. 5/6/96 sw.\\n\\t 7/31/96 sw: use Color fromUser\\\"\\n\\n\\tview backgroundColor: Color fromUser; uncacheBits; display! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nclose\\n\\t\\\"The receiver's view should be removed from the screen and from the \\n\\tcollection of scheduled views.\\\"\\n\\n\\tmodel okToChange ifFalse: [^self].\\n\\tstatus _ #closed.\\n\\tview erase! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\ncollapse\\n\\t\\\"Get the receiver's view to change to a collapsed view on the screen.\\\"\\n\\tview collapseToPoint: view chooseCollapsePoint! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nexpand\\n\\t\\\"The receiver's view was collapsed; open it again and ask the user to \\n\\tdesignate its rectangular area.\\\"\\n\\tview expand; emphasize! !\\n\\n!StandardSystemController methodsFor: 'menu messages' stamp: 'rbb 3/1/2005 11:14'!\\nlabel\\n\\n\\t| newLabel |\\n\\tnewLabel := UIManager default\\n\\t\\trequest: 'Edit the label, then type RETURN'\\n\\t\\tinitialAnswer: view label.\\n\\tnewLabel isEmpty ifFalse: [view relabel: newLabel].\\n! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nmove\\n\\t\\\"Ask the user to designate a new origin position for the receiver's view.\\n\\t6/10/96 sw: tell the view that it has moved\\\"\\n\\n\\t| oldBox | \\n\\toldBox _ view windowBox.\\n\\tview uncacheBits.\\n\\tview align: view windowBox topLeft\\n\\t\\twith: view chooseMoveRectangle topLeft.\\n\\tview displayEmphasized.\\n\\tview moved. \\\"In case its model wishes to take note.\\\"\\n\\t(oldBox areasOutside: view windowBox) do:\\n\\t\\t[:rect | ScheduledControllers restore: rect]! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nreframe\\n\\t^ view reframeTo: view getFrame! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\ntoggleTwoTone\\n\\t(view isMemberOf: StandardSystemView) ifTrue:\\n\\t\\t[^ view become: (view as: ColorSystemView)].\\n\\t(view isMemberOf: ColorSystemView) ifTrue:\\n\\t\\t[^ view become: (view as: StandardSystemView)].\\n! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nunder\\n\\t\\\"Deactive the receiver's scheduled view and pass control to any view that \\n\\tmight be positioned directly underneath it and the cursor.\\\"\\n\\n\\tstatus _ #inactive! !\\n\\n\\n!StandardSystemController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 15:12'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t^ nil! !\\n\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'sw 9/30/97 22:04'!\\ncloseAndUnschedule\\n\\t\\\"Erase the receiver's view and remove it from the collection of scheduled \\n\\tviews.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview erase.\\n\\tview release.\\n\\tScheduledControllers unschedule: self; searchForActiveController\\n! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\ncloseAndUnscheduleNoErase\\n\\t\\\"Remove the scheduled view from the collection of scheduled views. Set \\n\\tits status to closed but do not erase.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview release.\\n\\tScheduledControllers unschedule: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'jm 3/18/98 19:21'!\\ncloseAndUnscheduleNoTerminate\\n\\t\\\"Erase the receiver's view and remove it from the collection of scheduled views, but do not terminate the current process.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview erase.\\n\\tview release.\\n\\tScheduledControllers unschedule: self.\\n! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopen\\n\\t\\\"Create an area on the screen in which the receiver's scheduled view can \\n\\tbe displayed. Make it the active view.\\\"\\n\\n\\tview resizeInitially.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActive: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopenDisplayAt: aPoint \\n\\t\\\"Create an area with origin aPoint in which the receiver's scheduled \\n\\tview can be displayed. Make it the active view.\\\"\\n\\n\\tview align: view viewport center with: aPoint.\\n\\tview translateBy:\\n\\t\\t(view displayBox amountToTranslateWithin: Display boundingBox).\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActive: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'jm 10/22/97 08:16'!\\nopenNoTerminate\\n\\t\\\"Create an area in which the receiver's scheduled view can be displayed. \\n\\tMake it the active view. Do not terminate the currently active process.\\\"\\n\\n\\tview resizeInitially.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActiveNoTerminate: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopenNoTerminateDisplayAt: aPoint \\n\\t\\\"Create an area with origin aPoint in which the receiver's scheduled \\n\\tview can be displayed. Make it the active view. Do not terminate the \\n\\tcurrently active process.\\\"\\n\\n\\tview resizeMinimumCenteredAt: aPoint.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActiveNoTerminate: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nstatus: aSymbol\\n\\tstatus _ aSymbol! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSystemController class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSystemController class methodsFor: 'class initialization' stamp: 'sma 3/11/2000 11:57'!\\ninitialize\\n\\t\\\"StandardSystemController initialize\\\"\\n\\n\\tScheduledBlueButtonMenu _ SelectionMenu\\n\\t\\tlabels:\\n'edit label\\nchoose color...\\ntwo-tone/full color\\nmove\\nframe\\nfull screen\\ncollapse\\nclose'\\n\\tlines: #(3 7)\\n\\tselections: #(label chooseColor toggleTwoTone move reframe fullScreen collapse close).\\n\\n\\tVBorderCursor _ Cursor extent: 16@16 fromArray: #(\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010010000100000\\n\\t\\t2r1010110000110000\\n\\t\\t2r1011111111111000\\n\\t\\t2r1010110000110000\\n\\t\\t2r1010010000100000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000)\\n\\t\\t\\toffset: 0@0.\\n\\tHBorderCursor _ Cursor extent: 16@16 fromArray: #(\\n\\t\\t2r1111111111111111\\n\\t\\t2r0000000000000000\\n\\t\\t2r1111111111111111\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000001110000000\\n\\t\\t2r0000011111000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000011111000000\\n\\t\\t2r0000001110000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000000000000\\n\\t\\t2r0000000000000000\\n\\t\\t2r0000000000000000)\\n\\t\\t\\toffset: 0@0.! !\\nTestCase subclass: #StandardSystemFontsTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support-Tests'!\\n\\n!StandardSystemFontsTest methodsFor: 'testing' stamp: 'bp 11/6/2004 23:15'!\\ntestRestoreDefaultFonts\\n\\n\\tself saveStandardSystemFontsDuring: [\\n\\t\\tPreferences restoreDefaultFonts.\\n\\t\\tself assert: #standardDefaultTextFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardListFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardFlapFont familyName: 'Accushi' pointSize: 12.\\n\\t\\tself assert: #standardEToysFont familyName: 'BitstreamVeraSans' pointSize: 9.\\n\\t\\tself assert: #standardMenuFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #windowTitleFont familyName: 'BitstreamVeraSans' pointSize: 12.\\n\\t\\tself assert: #standardBalloonHelpFont familyName: 'Accujen' pointSize: 9.\\n\\t\\tself assert: #standardCodeFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardButtonFont familyName: 'BitstreamVeraSansMono' pointSize: 9]! !\\n\\n\\n!StandardSystemFontsTest methodsFor: 'utilities' stamp: 'bp 6/13/2004 18:22'!\\nassert: selector familyName: aString pointSize: anInteger\\n\\n\\t| font |\\n\\tfont _ Preferences perform: selector.\\n\\tself assert: font familyName = aString.\\n\\tself assert: font pointSize = anInteger\\n\\t! !\\n\\n!StandardSystemFontsTest methodsFor: 'utilities' stamp: 'bp 6/13/2004 21:51'!\\nsaveStandardSystemFontsDuring: aBlock\\n\\n\\t| standardDefaultTextFont standardListFont standardEToysFont standardMenuFont \\n\\twindowTitleFont standardBalloonHelpFont standardCodeFont standardButtonFont |\\n\\n\\tstandardDefaultTextFont _ Preferences standardDefaultTextFont.\\n\\tstandardListFont _ Preferences standardListFont.\\n\\tstandardEToysFont _ Preferences standardEToysFont.\\n\\tstandardMenuFont _ Preferences standardMenuFont.\\n\\twindowTitleFont _ Preferences windowTitleFont.\\n\\tstandardBalloonHelpFont _ Preferences standardBalloonHelpFont.\\n\\tstandardCodeFont _ Preferences standardCodeFont.\\n\\tstandardButtonFont _ Preferences standardButtonFont.\\n\\t[aBlock value] ensure: [\\n\\t\\tPreferences setSystemFontTo: standardDefaultTextFont.\\n\\t\\tPreferences setListFontTo: standardListFont.\\n\\t\\tPreferences setEToysFontTo: standardEToysFont.\\n\\t\\tPreferences setMenuFontTo: standardMenuFont.\\n\\t\\tPreferences setWindowTitleFontTo: windowTitleFont.\\n\\t\\tPreferences setBalloonHelpFontTo: standardBalloonHelpFont.\\n\\t\\tPreferences setCodeFontTo: standardCodeFont.\\n\\t\\tPreferences setButtonFontTo: standardButtonFont].\\n! !\\nView subclass: #StandardSystemView\\n\\tinstanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes'\\n\\tclassVariableNames: 'CacheBits LabelStyle'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StandardSystemView commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StandardSystemView methodsFor: 'clipping box access'!\\nclippingBox\\n\\t\\\"Answer the rectangular area in which the receiver can show its label.\\\"\\n\\n\\t^self isTopView\\n\\t\\tifTrue: [self labelDisplayBox]\\n\\t\\tifFalse: [super insetDisplayBox]! !\\n\\n!StandardSystemView methodsFor: 'clipping box access' stamp: 'BG 12/5/2003 11:13'!\\nconstrainFrame: aRectangle\\n\\t\\\"Constrain aRectangle, to the minimum and maximum size\\n\\tfor this window\\\"\\n\\n | adjustmentForLabel |\\n adjustmentForLabel := 0 @ (labelFrame height - labelFrame borderWidth).\\n\\t^ aRectangle origin extent:\\n\\t\\t((aRectangle extent max: minimumSize + adjustmentForLabel)\\n\\t\\t min: maximumSize + adjustmentForLabel).! !\\n\\n\\n!StandardSystemView methodsFor: 'controller access'!\\ndefaultControllerClass \\n\\t\\\"Refer to the comment in View|defaultControllerClass.\\\"\\n\\n\\t^StandardSystemController! !\\n\\n\\n!StandardSystemView methodsFor: 'deEmphasizing'!\\ndeEmphasizeView \\n\\t\\\"Refer to the comment in View|deEmphasizeView.\\\"\\n\\n\\tisLabelComplemented ifTrue:\\n\\t\\t[self deEmphasizeLabel.\\n\\t\\tisLabelComplemented _ false]! !\\n\\n!StandardSystemView methodsFor: 'deEmphasizing'!\\nemphasizeView \\n\\t\\\"Refer to the comment in View|emphasizeView.\\\"\\n\\n\\tself emphasizeLabel! !\\n\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBits\\n\\t| oldLabelState |\\n\\tCacheBits ifFalse: [^ self uncacheBits].\\n\\t(oldLabelState _ isLabelComplemented) ifTrue: [ self deEmphasize ].\\n\\tself cacheBitsAsIs.\\n\\t(isLabelComplemented _ oldLabelState) ifTrue: [ self emphasize ].\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBitsAsIs\\n\\tCacheBits ifFalse: [^ self uncacheBits].\\n\\twindowBits _ (self cacheBitsAsTwoTone and: [Display depth > 1])\\n\\t\\tifTrue: [ColorForm\\n\\t\\t\\t\\t\\ttwoToneFromDisplay: self windowBox\\n\\t\\t\\t\\t\\tusing: windowBits\\n\\t\\t\\t\\t\\tbackgroundColor: self backgroundColor]\\n\\t\\tifFalse: [Form fromDisplay: self windowBox using: windowBits].\\n\\tbitsValid _ true.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBitsAsTwoTone\\n\\t^ true! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndeEmphasizeForDebugger\\n\\t\\\"Carefully de-emphasis this window because a debugger is being opened. Care must be taken to avoid invoking potentially buggy window display code that could cause a recursive chain of errors eventually resulting in a virtual machine crash. In particular, do not de-emphasize the subviews.\\\"\\n\\n\\tself deEmphasizeView. \\\"de-emphasize this top-level view\\\"\\n\\tself uncacheBits.\\n\\tSmalltalk garbageCollectMost > 1000000 ifTrue: [\\n\\t\\t\\\"if there is enough space, cache current window screen bits\\\"\\n\\t\\tself cacheBitsAsIs].\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'!\\ndeEmphasizeLabel\\n\\t\\\"Un-Highlight the label.\\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayLabelBackground: false.\\n\\tself displayLabelText.! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplay\\n\\tisLabelComplemented\\n\\t\\tifTrue: [self displayEmphasized]\\n\\t\\tifFalse: [self displayDeEmphasized]! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'hmm 7/21/1999 07:37'!\\ndisplayDeEmphasized \\n\\t\\\"Display this view with emphasis off.\\n\\tIf windowBits is not nil, then simply BLT if possible,\\n\\t\\tbut force full display for top window so color is preserved.\\\"\\n\\t(bitsValid and: [controller ~~ ScheduledControllers activeController])\\n\\t\\tifTrue: [self lock.\\n\\t\\t\\t\\twindowBits displayAt: self windowOrigin]\\n\\t\\tifFalse: [Display deferUpdates: true.\\n\\t\\t\\t\\tsuper display.\\n\\t\\t\\t\\tDisplay deferUpdates: false; forceToScreen: self windowBox.\\n\\t\\t\\t\\tCacheBits ifTrue: [self cacheBitsAsIs]]\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplayEmphasized\\n\\t\\\"Display with label highlighted to indicate that it is active.\\\"\\n\\n\\tself displayDeEmphasized; emphasize.\\n\\tisLabelComplemented _ true! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 5/15/1998 21:55'!\\ndisplayLabelBackground: emphasized\\n\\t\\\"Clear or emphasize the inner region of the label\\\"\\n\\t| r1 r2 r3 c3 c2 c1 |\\n\\temphasized ifFalse:\\n\\t\\t[\\\"Just clear the label if not emphasized\\\"\\n\\t\\t^ Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor].\\n\\tr1 _ self labelDisplayBox insetBy: 2.\\n\\tr2 _ r1 insetBy: 0@2.\\n\\tr3 _ r2 insetBy: 0@3.\\n\\tc3 _ self labelColor.\\n\\tc2 _ c3 dansDarker.\\n\\tc1 _ c2 dansDarker.\\n\\tDisplay fill: r1 fillColor: c1.\\n\\tDisplay fill: r2 fillColor: c2.\\n\\tDisplay fill: r3 fillColor: c3.\\n \\n\\\"\\tHere is the Mac racing stripe code\\n\\tstripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth)\\n\\t\\t\\t\\t\\twith: (Form black pixelWordForDepth: Display depth).\\n\\tself windowOrigin y even ifTrue: [stripes swap: 1 with: 2].\\n\\tDisplay fill: (self labelDisplayBox insetBy: 3) fillColor: stripes.\\n\\\"! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplayLabelBoxes\\n\\t\\\"closeBox, growBox.\\\"\\n\\t| aRect smallRect backColor |\\n\\taRect _ self closeBoxFrame.\\n\\tbackColor _ self labelColor.\\n\\tDisplay fill: (aRect insetBy: -2) fillColor: backColor.\\n\\tDisplay fillBlack: aRect.\\n\\tDisplay fill: (aRect insetBy: 1) fillColor: backColor.\\n\\n\\taRect _ self growBoxFrame.\\n\\tsmallRect _ aRect origin extent: 7@7.\\n\\tDisplay fill: (aRect insetBy: -2) fillColor: backColor.\\n\\taRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0.\\n\\tDisplay fillBlack: aRect.\\n\\tDisplay fill: (aRect insetBy: 1) fillColor: backColor.\\n\\tDisplay fillBlack: smallRect.\\n\\tDisplay fill: (smallRect insetBy: 1) fillColor: backColor! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 9/10/1998 09:43'!\\ndisplayLabelText\\n\\t\\\"The label goes in the center of the window\\\"\\n\\t| labelRect |\\n\\tlabelText foregroundColor: self foregroundColor\\n\\t\\t\\tbackgroundColor: self labelColor.\\n\\tlabelRect _ self labelTextRegion.\\n\\tDisplay fill: (labelRect expandBy: 3@0) fillColor: self labelColor.\\n\\tlabelText displayOn: Display at: labelRect topLeft clippingBox: labelRect\\n\\t\\t\\trule: labelText rule fillColor: labelText fillColor.\\n\\tlabelText destinationForm: nil! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 8/29/97 18:57'!\\ndisplayOn: aPort\\n\\tbitsValid ifFalse:\\n\\t\\t[^ Display clippingTo: aPort clipRect do: [super display]].\\n\\twindowBits displayOnPort: aPort at: self windowOrigin! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'ar 5/14/2001 23:40'!\\ndisplayRacingStripes\\n\\t\\\"Display Racing Stripes in the label\\\"\\n\\t| labelDisplayBox stripes top bottom left box right |\\n\\tlabelDisplayBox _ self labelDisplayBox.\\n\\ttop _ labelDisplayBox top + 3.\\n\\tbottom _ labelDisplayBox bottom - 3.\\n\\tstripes _ Bitmap with: (Display pixelWordFor: self labelColor)\\n\\t\\t\\twith: (Display pixelWordFor: Color black).\\n\\ttop even ifFalse: [stripes swap: 1 with: 2].\\n\\n\\tleft _ labelDisplayBox left + 3.\\n\\n\\tbox _ self closeBoxFrame.\\n\\tright _ box left - 2.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tbox _ self labelTextRegion.\\n\\tright _ box left - 3.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tbox _ self growBoxFrame.\\n\\tright _ box left - 2.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tright _ labelDisplayBox right - 3.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:14'!\\ndisplayView\\n\\t\\\"Refer to the comment in View|displayView. \\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayBox width = labelFrame width ifFalse:\\n\\t\\t[\\\"recompute label width when window changes size\\\"\\n\\t\\tself setLabelRegion].\\n\\t(labelFrame align: labelFrame topLeft with: self windowOrigin)\\n\\t\\tinsideColor: self labelColor;\\n\\t\\tdisplayOn: Display.\\n\\tself displayLabelText! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'!\\nemphasizeLabel\\n\\t\\\"Highlight the label.\\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayLabelBackground: true.\\n\\tself displayLabelBoxes.\\n\\tself displayLabelText.! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 8/30/97 11:07'!\\nerase\\n\\t\\\"Clear the display box of the receiver to be gray, as the screen background.\\\"\\n\\t| oldValid |\\n\\tCacheBits\\n\\t\\tifTrue:\\n\\t\\t\\t[oldValid _ bitsValid.\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tScheduledControllers restore: self windowBox without: self.\\n\\t\\t\\tbitsValid _ oldValid]\\n\\t\\tifFalse:\\n\\t\\t\\t[ScheduledControllers restore: self windowBox without: self]! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'RAA 6/14/2000 17:27'!\\nmakeMeVisible\\n\\n | newLoc portRect |\\n ((Display boundingBox insetBy: (0@0 corner: self labelHeight asPoint))\\n containsPoint: self displayBox topLeft) ifTrue: [^ self \\\"OK -- my top left is visible\\\"].\\n\\n \\\"window not on screen (probably due to reframe) -- move it now\\\"\\n newLoc _ self isCollapsed\\n ifTrue: [RealEstateAgent assignCollapsePointFor: self]\\n ifFalse: [(RealEstateAgent initialFrameFor: self world: nil) topLeft].\\n portRect _ newLoc + self labelOffset\\n extent: self windowBox extent - self labelOffset.\\n self resizeTo: portRect.\\n self setLabelRegion.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\nuncacheBits\\n\\twindowBits _ nil.\\n\\tbitsValid _ false.! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\nwindowBits\\n\\t^ windowBits! !\\n\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sr 3/26/2000 03:47'!\\nchooseCollapsePoint\\n\\t\\\"Answer the point at which to place the collapsed window.\\\"\\n\\t| pt labelForm beenDown offset |\\n\\tlabelForm _ Form fromDisplay: self labelDisplayBox.\\n\\tself uncacheBits.\\n\\tself erase.\\n\\tbeenDown _ Sensor anyButtonPressed.\\n\\tself isCollapsed ifTrue:\\n\\t\\t[offset _ self labelDisplayBox topLeft - self growBoxFrame topLeft.\\n\\t\\tlabelForm follow: [pt _ (Sensor cursorPoint + offset max: 0@0) truncateTo: 8]\\n\\t\\t\\t\\twhile: [Sensor anyButtonPressed\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [beenDown _ true]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [beenDown not]].\\n\\t\\t^ pt].\\n\\t^ (RealEstateAgent assignCollapseFrameFor: self) origin.\\n! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nchooseFrame\\n\\t\\\"Answer a new frame, depending on whether the view is currently \\n\\tcollapsed or not.\\\"\\n\\t| labelForm f |\\n\\tself isCollapsed & expandedViewport notNil\\n\\t\\tifTrue:\\n\\t\\t\\t[labelForm _ bitsValid\\n\\t\\t\\t\\tifTrue: [windowBits]\\n\\t\\t\\t\\tifFalse: [Form fromDisplay: self labelDisplayBox].\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tself erase.\\n\\t\\t\\tlabelForm slideFrom: self labelDisplayBox origin\\n\\t\\t\\t\\t\\tto: expandedViewport origin-self labelOffset\\n\\t\\t\\t\\t\\tnSteps: 10.\\n\\t\\t\\t^ expandedViewport]\\n\\t\\tifFalse:\\n\\t\\t\\t[f _ self getFrame.\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tself erase.\\n\\t\\t\\t^ f topLeft + self labelOffset extent: f extent]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nchooseMoveRectangle\\n\\t\\\"Ask the user to designate a new window rectangle.\\\"\\n\\t| offset p |\\n\\toffset _ Sensor anyButtonPressed \\\"Offset if draggin, eg, label\\\"\\n\\t\\tifTrue: [self windowBox topLeft - Sensor cursorPoint]\\n\\t\\tifFalse: [0@0].\\n\\tself isCollapsed\\n\\t\\tifTrue: [^ self labelDisplayBox newRectFrom:\\n\\t\\t\\t\\t\\t[:f | p _ Sensor cursorPoint + offset.\\n\\t\\t\\t\\t\\tp _ (p max: 0@0) truncateTo: 8.\\n\\t\\t\\t\\t\\tp extent: f extent]]\\n\\t\\tifFalse: [^ self windowBox newRectFrom:\\n\\t\\t\\t\\t\\t[:f | p _ Sensor cursorPoint + offset.\\n\\t\\t\\t\\t\\tself constrainFrame: (p extent: f extent)]]! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 5/11/1999 22:09'!\\ncollapse\\n\\t\\\"If the receiver is not already collapsed, change its view to be that of its \\n\\tlabel only.\\\"\\n\\n\\tself isCollapsed ifFalse:\\n\\t\\t\\t[model modelSleep.\\n\\t\\t\\t(subViews ~~ nil and: [subViews size = 1 and: [subViews first isKindOf: MorphWorldView]])\\n\\t\\t\\t\\tifTrue: [subViews first deEmphasizeView].\\n\\t\\t\\texpandedViewport _ self viewport.\\n\\t\\t\\tsavedSubViews _ subViews.\\n\\t\\t\\tself resetSubViews.\\n\\t\\t\\tlabelText isNil ifTrue: [self label: nil. bitsValid _ false.].\\n\\t\\t\\tself window: (self inverseDisplayTransform:\\n\\t\\t\\t\\t\\t((self labelDisplayBox topLeft extent: (labelText extent x + 70) @ self labelHeight)\\n\\t\\t\\t\\t\\t\\t intersect: self labelDisplayBox))]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ncollapseToPoint: collapsePoint\\n\\tself collapse.\\n\\tself align: self displayBox topLeft with: collapsePoint.\\n\\tcollapsedViewport _ self viewport.\\n\\tself displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ncollapsedFrame\\n\\t\\\"Answer the rectangle occupied by this window when collapsed.\\\"\\n\\t^ collapsedViewport \\\"NOTE may be nil\\\"! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 10/20/1999 09:46'!\\nexpand\\n\\t\\\"If the receiver is collapsed, change its view to be that of all of its subviews, not its label alone.\\\"\\n\\t| newFrame |\\n\\tself isCollapsed\\n\\t\\tifTrue:\\n\\t\\t\\t[newFrame _ self chooseFrame expandBy: borderWidth.\\n\\t\\t\\tcollapsedViewport _ self viewport.\\n\\t\\t\\tsubViews _ savedSubViews.\\n\\t\\t\\tlabelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\t\\t\\tsavedSubViews _ nil.\\n\\t\\t\\tself setWindow: nil.\\n\\t\\t\\tself resizeTo: newFrame.\\n\\t\\t\\tself displayDeEmphasized.\\n\\t\\t\\tmodel modelWakeUpIn: self]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nexpandedFrame\\n\\t\\\"Answer the rectangle occupied by this window when expanded.\\\"\\n\\t^ expandedViewport \\\"NOTE may be nil\\\"! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 8/15/97 17:18'!\\nfullScreen\\n\\t\\\"Expand the receiver to fill the screen. Let the model decide how big is full -- allows for flop-out scrollbar on left if desired\\\"\\n\\n\\tself isCollapsed ifFalse:\\n\\t\\t[self reframeTo: model fullScreenSize]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ngetFrame\\n\\t\\\"Ask the user to designate a rectangular area in which\\n\\tthe receiver should be displayed.\\\"\\n\\t| minFrame |\\n\\tminFrame _ Cursor origin showWhile: \\n\\t\\t[(Sensor cursorPoint extent: self minimumSize) newRectFrom:\\n\\t\\t\\t[:f | Sensor cursorPoint extent: self minimumSize]].\\n\\tself maximumSize <= self minimumSize ifTrue: [^ minFrame].\\n\\t^ Cursor corner showWhile:\\n\\t\\t[minFrame newRectFrom:\\n\\t\\t\\t[:f | self constrainFrame: (f origin corner: Sensor cursorPoint)]]! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 1/22/96'!\\ninitialExtent\\n\\t\\\"Answer the desired extent for the receiver when it is first opened on the screen. \\\"\\n\\n\\t^ model initialExtent min: maximumSize max: minimumSize! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'RAA 6/14/2000 17:27'!\\ninitialFrame\\n \\\"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\\\"\\n\\n ^ RealEstateAgent initialFrameFor: self world: nil! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nmoved\\n\\t\\\"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\\\" ! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nnewFrame: frameChangeBlock\\n\\tself reframeTo: (self windowBox newRectFrom:\\n\\t\\t[:f | self constrainFrame: (frameChangeBlock value: f)])! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 10/22/1998 16:15'!\\nreframePanesAdjoining: subView along: side to: aDisplayBox \\n\\t| newBox delta newRect minDim theMin |\\n\\tnewRect _ aDisplayBox.\\n\\ttheMin _ 16.\\n\\t\\\"First check that this won't make any pane smaller than theMin screen dots\\\"\\n\\tminDim _ ((subViews select: [:sub | sub displayBox bordersOn: subView displayBox along: side])\\n\\t\\tcollect: [:sub | sub displayBox adjustTo: newRect along: side])\\n\\t\\t\\tinject: 999 into: [:was :rect | (was min: rect width) min: rect height].\\n\\t\\\"If so, amend newRect as required\\\"\\n\\tminDim < theMin ifTrue:\\n\\t\\t[delta _ minDim - theMin.\\n\\t\\tnewRect _ newRect withSide: side setTo: \\n\\t\\t\\t\\t((newRect perform: side) > (subView displayBox perform: side)\\n\\t\\t\\t\\t\\tifTrue: [(newRect perform: side) + delta]\\n\\t\\t\\t\\t\\tifFalse: [(newRect perform: side) - delta])].\\n\\t\\\"Now adjust all adjoining panes for real\\\"\\n\\tsubViews do:\\n\\t\\t[:sub | (sub displayBox bordersOn: subView displayBox along: side) ifTrue:\\n\\t\\t\\t[newBox _ sub displayBox adjustTo: newRect along: side.\\n\\t\\t\\tsub window: sub window viewport:\\n\\t\\t\\t\\t(sub transform: (sub inverseDisplayTransform: newBox)) rounded]].\\n\\t\\\"And adjust the growing pane itself\\\"\\n\\tsubView window: subView window viewport:\\n\\t\\t\\t(subView transform: (subView inverseDisplayTransform: newRect)) rounded.\\n\\n\\t\\\"Finally force a recomposition of the whole window\\\"\\n\\tviewport _ nil.\\n\\tself resizeTo: self viewport.\\n\\tself uncacheBits; displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'BG 12/4/2003 13:14'!\\nreframeTo: newFrame\\n\\t\\\"Reframe the receiver to the given screen rectangle. \\n\\tRepaint difference after the change. \\\"\\n\\t| oldBox newBox portRect |\\n\\tself uncacheBits.\\n\\toldBox _ self windowBox.\\n\\tportRect _ newFrame topLeft + self labelOffset\\n\\t\\t\\t\\tcorner: newFrame corner.\\n\\tself setWindow: nil.\\n\\tself resizeTo: portRect.\\n\\tself setLabelRegion.\\n\\tnewBox _ self windowBox.\\n\\t(oldBox areasOutside: newBox) do:\\n\\t\\t[:rect | ScheduledControllers restore: rect].\\n\\tself displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nresize\\n\\t\\\"Determine the rectangular area for the receiver, adjusted to the \\n\\tminimum and maximum sizes.\\\"\\n\\t| f |\\n\\tf _ self getFrame.\\n\\tself resizeTo: (f topLeft + self labelOffset extent: f extent)\\n! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nresizeInitially\\n\\t\\\"Determine the rectangular area for the receiver, adjusted to the \\n\\tminimum and maximum sizes.\\\"\\n\\tself resizeTo: self initialFrame\\n! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:12'!\\nresizeMinimumCenteredAt: aPoint \\n\\t\\\"Determine the rectangular area for the receiver, adjusted so that it is \\n\\tcentered a position, aPoint.\\\"\\n\\t| aRectangle |\\n\\taRectangle _ 0 @ 0 extent: self minimumSize.\\n\\taRectangle _ aRectangle align: aRectangle center with: aPoint.\\n\\tself resizeTo: aRectangle! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:29'!\\nresizeTo: aRectangle\\n\\t\\\"Resize this view to aRectangle\\\"\\n\\n\\t\\\"First get scaling right inside borders\\\"\\n\\tself window: (self window insetBy: borderWidth)\\n\\t\\tviewport: (aRectangle insetBy: borderWidth).\\n\\n\\t\\\"Then ensure window maps to aRectangle\\\"\\n\\twindow _ transformation applyInverseTo: aRectangle! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nstandardWindowOffset\\n\\t^ Preferences standardWindowOffset! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nwindowBox\\n\\t^ self displayBox merge: self labelDisplayBox! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 10/3/97 14:19'!\\nwindowOrigin\\n\\t^ (self isCollapsed or: [labelFrame height = 0 \\\"no label\\\"])\\n\\t\\tifTrue: [self displayBox topLeft]\\n\\t\\tifFalse: [self displayBox topLeft - self labelOffset]! !\\n\\n\\n!StandardSystemView methodsFor: 'initialize-release' stamp: 'sw 10/29/1999 12:58'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\tsuper initialize.\\n\\tlabelFrame _ Quadrangle new.\\n\\tlabelFrame region: (Rectangle origin: 0 @ 0 extent: 50 @ self labelHeight).\\n\\tlabelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\tself label: nil.\\n\\tisLabelComplemented _ false.\\n\\tminimumSize _ 50 @ 50.\\n\\tmaximumSize _ Display extent.\\n\\tcollapsedViewport _ nil.\\n\\texpandedViewport _ nil.\\n\\tbitsValid _ false.\\n\\tupdatablePanes _ #()! !\\n\\n!StandardSystemView methodsFor: 'initialize-release'!\\nmodel: aModel\\n\\t\\\"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\\\"\\n\\tsuper model: aModel.\\n\\tself setDefaultBackgroundColor! !\\n\\n!StandardSystemView methodsFor: 'initialize-release' stamp: 'jm 8/20/1998 18:29'!\\nrelease\\n\\n\\tmodel windowIsClosing.\\n\\tself isCollapsed ifTrue: [savedSubViews do: [:v | v release]].\\n\\tsuper release.\\n! !\\n\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:30'!\\ncloseBoxFrame\\n\\t^ Rectangle origin: (self labelDisplayBox leftCenter + (10@-5)) extent: (11@11)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:29'!\\ngrowBoxFrame\\n\\t^ Rectangle origin: (self labelDisplayBox rightCenter + (-22@-5)) extent: (11@11)! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabel\\n\\t\\\"Answer the string that appears in the receiver's label.\\\"\\n\\tlabelText isNil\\n\\t\\tifTrue: [^ 'Untitled' copy]\\n\\t\\tifFalse: [^ labelText asString]! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:44'!\\nlabel: aString \\n\\t\\\"Set aString to be the receiver's label.\\\"\\n\\tlabelText _ Paragraph\\n\\t\\t\\twithText: (Text string: ((aString == nil or: [aString isEmpty])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: ['Untitled' copy]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [aString])\\n\\t\\t\\t\\t\\t\\t\\tattributes: (Array with: TextEmphasis bold))\\n\\t\\t\\tstyle: LabelStyle.\\n\\tinsetDisplayBox == nil ifTrue: [^ self]. \\\"wait for further initialization\\\"\\n\\tself setLabelRegion! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelColor\\n\\t\\\"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\\\"\\n\\n\\t^ self backgroundColor! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelDisplayBox\\n\\t\\\"Answer the rectangle that borders the visible parts of the receiver's label \\n\\ton the display screen.\\\"\\n\\n\\t^ labelFrame region\\n\\t\\talign: labelFrame topLeft\\n\\t\\twith: self windowOrigin! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelFrame\\n\\t^labelFrame! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:47'!\\nlabelHeight\\n\\t^ ((LabelStyle fontAt: 1) height + 4) max: 20! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelOffset\\n\\t^ 0 @ (self labelHeight-2)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sr 3/26/2000 04:26'!\\nlabelText\\n\\t^labelText! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelTextRegion\\n\\tlabelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0].\\n\\t^ (labelText boundingBox\\n\\t\\t\\talign: labelText boundingBox center\\n\\t\\t\\twith: self labelDisplayBox center)\\n\\t\\tintersect: (self labelDisplayBox insetBy: 35@0)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 14:20'!\\nnoLabel\\n\\t\\\"A label of zero height indicates no label\\\"\\n\\tlabelFrame height > 0\\n\\t\\tifTrue: [labelFrame region: (labelFrame bottomLeft + (0@1) extent: labelFrame width@0).\\n\\t\\t\\t\\tlabelFrame borderWidth: 0.\\n\\t\\t\\t\\tself uncacheBits]! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/10/1998 13:18'!\\nrelabel: aString \\n\\t\\\"A new string for the label. Window is assumed to be active.\\n\\tWindow will redisplay only if label bar has to grow.\\\"\\n\\t| oldRegion oldWidth |\\n\\t(model windowReqNewLabel: aString) ifFalse: [^ self].\\n\\toldRegion _ self labelTextRegion.\\n\\toldWidth _ self insetDisplayBox width.\\n\\tself label: aString.\\n\\tDisplay fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0)\\n\\t\\t\\tfillColor: self labelColor.\\n\\tself insetDisplayBox width = oldWidth\\n\\t\\tifTrue: [self displayLabelText; emphasizeLabel]\\n\\t\\tifFalse: [self uncacheBits; displayEmphasized].\\n! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 1/19/2001 20:13'!\\nsetLabel: aLabel\\n\\t\\\"For compatibility with morphic\\\"\\n\\n\\tself relabel: aLabel! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 13:35'!\\nsetLabelRegion\\n\\t\\\"Always follows view width\\\"\\n\\n\\tlabelFrame region: (0 @ 0 extent: self displayBox width @ self labelHeight).\\n\\tlabelFrame borderWidth: 2! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sumim 2/8/2002 14:36'!\\nsetLabelTo: aString \\n\\t\\\"Force aString to be the new label of the receiver, bypassing any logic about whether it is acceptable and about propagating information about the change.\\\"\\n\\n\\t| oldRegion oldWidth |\\n\\tself label: aString.\\n\\tself controller isControlActive ifFalse: [^ self].\\n\\toldRegion _ self labelTextRegion.\\n\\toldWidth _ self insetDisplayBox width.\\n\\tDisplay fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0)\\n\\t\\t\\tfillColor: self labelColor.\\n\\tself insetDisplayBox width = oldWidth\\n\\t\\tifTrue: [self displayLabelText; emphasizeLabel]\\n\\t\\tifFalse: [self uncacheBits; displayEmphasized]! !\\n\\n\\n!StandardSystemView methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:49'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\tupdatablePanes ifNil: [updatablePanes _ #()].\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n! !\\n\\n\\n!StandardSystemView methodsFor: 'size'!\\nmaximumSize\\n\\t\\\"Answer a point representing the maximum width and height of the \\n\\treceiver.\\\"\\n\\n\\t^maximumSize! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nmaximumSize: aPoint \\n\\t\\\"Set the argument, aPoint, to be the maximum width and height of the \\n\\treceiver.\\\"\\n\\n\\tmaximumSize _ aPoint! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nminimumSize\\n\\t\\\"Answer a point representing the minimum width and height of the \\n\\treceiver.\\\"\\n\\n\\t^minimumSize! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nminimumSize: aPoint \\n\\t\\\"Set the argument, aPoint, to be the minimum width and height of the \\n\\treceiver.\\\"\\n\\n\\tminimumSize _ aPoint! !\\n\\n\\n!StandardSystemView methodsFor: 'testing'!\\ncontainsPoint: aPoint \\n\\t\\\"Refer to the comment in View|containsPoint:.\\\"\\n\\n\\t^(super containsPoint: aPoint) | (self labelContainsPoint: aPoint)! !\\n\\n!StandardSystemView methodsFor: 'testing'!\\nisCollapsed\\n\\t\\\"Answer whether the receiver is collapsed (true) or expanded (false).\\\"\\n\\n\\t^savedSubViews ~~ nil! !\\n\\n!StandardSystemView methodsFor: 'testing'!\\nlabelContainsPoint: aPoint \\n\\t\\\"Answer TRUE if aPoint is in the label box.\\\"\\n\\n\\t^self labelDisplayBox containsPoint: aPoint! !\\n\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 12:57'!\\nsetUpdatablePanesFrom: getSelectors\\n\\t| aList aPane |\\n\\t\\\"Set my updatablePanes inst var to the list of panes which are list panes with the given get-list selectors. Order is important here!! Note that the method is robust in the face of panes not found, but a warning is printed in the transcript in each such case\\\"\\n\\n\\taList _ OrderedCollection new.\\n\\tgetSelectors do:\\n\\t\\t[:sel | aPane _ self subViewSatisfying:\\n\\t\\t\\t\\t[:pane | (pane isKindOf: PluggableListView) and: [pane getListSelector == sel]].\\n\\t\\t\\taPane\\n\\t\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t\\t[aList add: aPane]\\n\\t\\t\\t\\tifNil:\\n\\t\\t\\t\\t\\t[Transcript cr; show: 'Warning: view ', sel, ' not found.']].\\n\\tupdatablePanes _ aList asArray! !\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:20'!\\nupdatablePanes\\n\\t\\\"Answer the list of panes, in order, which might be sent the #verifyContents message upon window activation or expansion.\\\"\\n\\t^ updatablePanes ifNil: [updatablePanes _ #()]! !\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 1/11/2000 15:30'!\\nupdate: aSymbol\\n\\taSymbol = #relabel\\n\\t\\tifTrue: [^ self setLabelTo: model labelString].\\n\\t^ super update: aSymbol! !\\n\\n\\n!StandardSystemView methodsFor: 'private'!\\nsetTransformation: aTransformation \\n\\t\\\"Override to support label size changes \\\"\\n\\tsuper setTransformation: aTransformation.\\n\\tself label: self label! !\\n\\n!StandardSystemView methodsFor: 'private' stamp: 'di 10/21/1998 16:12'!\\nsubviewWithLongestSide: sideBlock near: aPoint \\n\\t| theSub theSide theLen box |\\n\\ttheLen _ 0.\\n\\tsubViews do:\\n\\t\\t[:sub | box _ sub insetDisplayBox.\\n\\t\\tbox forPoint: aPoint closestSideDistLen:\\n\\t\\t\\t[:side :dist :len |\\n\\t\\t\\t(dist <= 5 and: [len > theLen]) ifTrue:\\n\\t\\t\\t\\t[theSub _ sub.\\n\\t\\t\\t\\ttheSide _ side.\\n\\t\\t\\t\\ttheLen _ len]]].\\n\\tsideBlock value: theSide.\\n\\t^ theSub! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSystemView class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ncachingBits\\n\\t^ CacheBits! !\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ndoCacheBits\\n\\t\\\"StandardSystemView doCacheBits - Enable fast window repaint feature\\\"\\n\\tCacheBits _ true.\\n\\tScheduledControllers unCacheWindows.\\n\\tScheduledControllers restore! !\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ndontCacheBits\\n\\t\\\"StandardSystemView dontCacheBits - Disable fast window repaint feature.\\n\\tReturn true iff bits were cached, ie if space was been recovered\\\"\\n\\tCacheBits ifFalse: [^ false].\\n\\tCacheBits _ false.\\n\\tScheduledControllers unCacheWindows.\\n\\t^ true! !\\n\\n!StandardSystemView class methodsFor: 'class initialization' stamp: 'sw 12/6/1999 23:42'!\\ninitialize\\t\\t\\\"StandardSystemView initialize\\\"\\n\\tself doCacheBits.\\n\\tself setLabelStyle! !\\n\\n!StandardSystemView class methodsFor: 'class initialization' stamp: 'nk 9/1/2004 10:26'!\\nsetLabelStyle\\n\\t| aFont |\\n\\t\\\"StandardSystemView setLabelStyle\\\"\\n\\taFont _ Preferences windowTitleFont.\\n\\tLabelStyle _ TextStyle fontArray: { aFont }.\\n\\tLabelStyle gridForFont: 1 withLead: 0! !\\nObject subclass: #StandardToolSet\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Base'!\\n!StandardToolSet commentStamp: '<historical>' prior: 0!\\nMain comment stating the purpose of this class and relevant relationship to other classes.\\n\\nPossible useful expressions for doIt or printIt.\\n\\nStructure:\\n instVar1\\t\\ttype -- comment about the purpose of instVar1\\n instVar2\\t\\ttype -- comment about the purpose of instVar2\\n\\nAny further useful comments about the general approach of this implementation.!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardToolSet class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/16/2005 15:20'!\\nbrowseChangeSetsWithClass: aClass selector: aSelector\\n\\t\\\"Browse all the change sets with the given class/selector\\\"\\n\\t^ChangeSorter browseChangeSetsWithClass: aClass selector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'md 3/10/2006 21:42'!\\nbrowseHierarchy: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\t| newBrowser |\\n\\t(aClass == nil) ifTrue: [^ self].\\n\\t(newBrowser := SystemBrowser default new) setClass: aClass selector: aSelector.\\n\\tnewBrowser spawnHierarchy.! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:12'!\\nbrowseMessageNames: aString\\n\\t^(MessageNames methodBrowserSearchingFor: aString) openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:13'!\\nbrowseMessageSet: messageList name: title autoSelect: autoSelectString\\n\\t\\\"Open a message set browser\\\"\\n\\t^MessageSet\\n\\t\\topenMessageList: messageList \\n\\t\\tname: title \\n\\t\\tautoSelect: autoSelectString! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:35'!\\nbrowseVersionsOf: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\tVersionsBrowser\\n\\t\\tbrowseVersionsOf: (aClass compiledMethodAt: aSelector)\\n\\t\\tclass: aClass theNonMetaClass\\n\\t\\tmeta: aClass isMeta\\n\\t\\tcategory: (aClass organization categoryOfElement: aSelector)\\n\\t\\tselector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'md 3/10/2006 21:43'!\\nbrowse: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\t^SystemBrowser default fullOnClass: aClass selector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/15/2005 18:58'!\\nopenChangedMessageSet: aChangeSet\\n\\t\\\"Open a ChangedMessageSet for aChangeSet\\\"\\n\\tChangedMessageSet openFor: aChangeSet! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/15/2005 18:58'!\\nopenClassListBrowser: anArray title: aString\\n\\t\\\"Open a class list browser\\\"\\n\\t^ClassListBrowser new initForClassesNamed: anArray title: aString\\n! !\\n\\n\\n!StandardToolSet class methodsFor: 'class initialization' stamp: 'ar 7/17/2005 01:04'!\\ninitialize\\n\\tToolSet register: self.\\n\\tPreferences installMissingWindowColors.! !\\n\\n!StandardToolSet class methodsFor: 'class initialization' stamp: 'ar 7/16/2005 16:18'!\\nunload\\n\\tToolSet unregister: self.! !\\n\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/15/2005 19:15'!\\ndebugContext: aContext label: aString contents: contents\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\t^Debugger openContext: aContext label: aString contents: contents! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/17/2005 11:16'!\\ndebugError: anError\\n\\t\\\"Handle an otherwise unhandled error\\\"\\n\\t^Processor activeProcess\\n\\t\\tdebug: anError signalerContext\\n\\t\\ttitle: anError description! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 9/27/2005 19:18'!\\ndebugSyntaxError: anError\\n\\t\\\"Handle a syntax error\\\"\\n\\t| notifier |\\n\\tnotifier := SyntaxError new\\n\\t\\tsetClass: anError errorClass\\n\\t\\tcode: anError errorCode\\n\\t\\tdebugger: (Debugger context: anError signalerContext)\\n\\t\\tdoitFlag: anError doitFlag.\\n\\tnotifier category: anError category.\\n\\tSyntaxError open: notifier.! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/15/2005 18:57'!\\ndebug: aProcess context: aContext label: aString contents: contents fullView: aBool\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\t^Debugger openOn: aProcess context: aContext label: aString contents: contents fullView: aBool! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/17/2005 11:16'!\\ninterrupt: aProcess label: aString\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\tDebugger\\n\\t\\topenInterrupt: aString\\n\\t\\tonProcess: aProcess! !\\n\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 18:57'!\\nbasicInspect: anObject\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^BasicInspector openOn: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:34'!\\nexplore: anObject\\n\\t\\\"Open an explorer on the given object.\\\"\\n\\t^ObjectExplorer new openExplorerFor: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:54'!\\ninspectorClassOf: anObject\\n\\t\\\"Answer the inspector class for the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t| map |\\n\\tmap := Dictionary new.\\n\\t#(\\n\\t\\t(CompiledMethod\\t\\tCompiledMethodInspector)\\n\\t\\t(CompositeEvent\\t\\tOrderedCollectionInspector)\\n\\t\\t(Dictionary\\t\\t\\tDictionaryInspector)\\n\\t\\t(ExternalStructure\\tExternalStructureInspector)\\n\\t\\t(FloatArray\\t\\t\\tOrderedCollectionInspector)\\n\\t\\t(OrderedCollection\\tOrderedCollectionInspector)\\n\\t\\t(Set\\t\\t\\t\\t\\tSetInspector)\\n\\t\\t(WeakSet\\t\\t\\tWeakSetInspector)\\n\\t) do:[:spec|\\n\\t\\tmap at: spec first put: spec last.\\n\\t].\\n\\tanObject class withAllSuperclassesDo:[:cls|\\n\\t\\tmap at: cls name ifPresent:[:inspectorName| ^Smalltalk classNamed: inspectorName].\\n\\t].\\n\\t^Inspector! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 18:58'!\\ninspect: anObject\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^(self inspectorClassOf: anObject) openOn: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:57'!\\ninspect: anObject label: aString\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^(self inspectorClassOf: anObject) openOn: anObject withEvalPane: true withLabel: aString! !\\n\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:19'!\\nmenuItems\\n\\t\\\"Answer the menu items available for this tool set\\\"\\n\\t^#(\\n\\t\\t('class browser' \\t\\t\\t#openClassBrowser)\\n\\t\\t('workspace'\\t\\t\\t\\t#openWorkspace)\\n\\t\\t('file list'\\t\\t\\t\\t\\t#openFileList)\\n\\t\\t('package pane browser' \\t#openPackagePaneBrowser)\\n\\t\\t('process browser' \\t\\t\\t#openProcessBrowser)\\n\\t\\t-\\n\\t\\t('method finder'\\t\\t\\t\\t#openSelectorBrowser)\\n\\t\\t('message names'\\t\\t\\t#openMessageNames)\\n\\t\\t-\\n\\t\\t('simple change sorter'\\t\\t#openChangeSorter)\\n\\t\\t('dual change sorter'\\t\\t#openDualChangeSorter)\\n\\t)\\n! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:05'!\\nopenChangeSorter\\n\\tChangeSorter new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 3/10/2006 21:47'!\\nopenClassBrowser\\n\\tSystemBrowser default open! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:05'!\\nopenDualChangeSorter\\n\\tDualChangeSorter new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 2/24/2006 15:21'!\\nopenFileList\\n\\tFileList2 prototypicalToolWindow openInWorld.! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 12:59'!\\nopenMessageNames\\n\\t\\\"Bring a MessageNames tool to the front\\\"\\n\\tMessageNames openMessageNames! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:04'!\\nopenPackagePaneBrowser\\n\\tPackagePaneBrowser openBrowser.! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 12:59'!\\nopenProcessBrowser\\n\\tProcessBrowser open! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:00'!\\nopenSelectorBrowser\\n\\tSelectorBrowser new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 1/18/2006 19:08'!\\nopenWorkspace\\n\\tWorkspace open! !\\nViewer subclass: #StandardViewer\\n\\tinstanceVariableNames: 'firstPanel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n!StandardViewer commentStamp: 'sw 8/17/2002 02:04' prior: 0!\\nA structure that allows you to view state and behavior of an object; it consists of a header and then any number of CategoryViewers.!\\n\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 12/28/1998 15:22'!\\naddCategoryViewer\\t\\n\\tself addCategoryViewerFor: self likelyCategoryToShow! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:50'!\\naddCategoryViewerFor: categoryInfo\\n\\t\\\"Add a category viewer for the given category info\\\"\\n\\n\\tself addCategoryViewerFor: categoryInfo atEnd: true! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:56'!\\naddCategoryViewerFor: categoryInfo atEnd: atEnd\\n\\t\\\"Add a category viewer for the given category info. If atEnd is true, add it at the end, else add it just after the header morph\\\"\\n\\n\\t| aViewer |\\n\\taViewer _ self categoryViewerFor: categoryInfo.\\n\\tatEnd\\n\\t\\tifTrue:\\n\\t\\t\\t[self addMorphBack: aViewer]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorph: aViewer after: submorphs first].\\n\\taViewer establishContents.\\n\\tself world ifNotNil: [self world startSteppingSubmorphsOf: aViewer].\\n\\tself fitFlap! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:18'!\\naddSearchPane\\n\\t\\\"Add a search pane\\\"\\n\\n\\tself addCategoryViewerFor: #(search '') atEnd: false! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 11/18/1999 16:00'!\\ncategoriesCurrentlyShowing\\n\\t^ self categoryMorphs collect: [:m | m currentCategory]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 10/30/1998 18:38'!\\ncategoryMorphs\\n\\t^ self submorphsSatisfying: [:m | m isKindOf: CategoryViewer]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'gm 2/22/2003 13:01'!\\ncategoryViewerFor: categoryInfo \\n\\t\\\"Answer a category viewer for the given category info\\\"\\n\\n\\t| aViewer |\\n\\taViewer := ((categoryInfo isCollection) \\n\\t\\t\\t\\tand: [categoryInfo first == #search]) \\n\\t\\t\\t\\t\\tifFalse: [CategoryViewer new]\\n\\t\\t\\t\\t\\tifTrue: [SearchingViewer new].\\n\\taViewer initializeFor: scriptedPlayer categoryChoice: categoryInfo.\\n\\t^aViewer! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:22'!\\nchooseLimitClass\\n\\t\\\"Put up a menu allowing the user to choose the most generic class to show\\\"\\n\\n\\t| aMenu limitClass |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\tlimitClass _ self limitClass.\\n\\tscriptedPlayer class withAllSuperclasses do:\\n\\t\\t[:aClass | \\n\\t\\t\\taClass == ProtoObject\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aMenu addLine].\\n\\t\\t\\taMenu add: aClass name selector: #setLimitClass: argument: aClass.\\n\\t\\t\\taClass == limitClass ifTrue:\\n\\t\\t\\t\\t[aMenu lastItem color: Color red].\\n\\t\\t\\taClass == limitClass ifTrue: [aMenu addLine]].\\n\\taMenu addTitle: 'Show only methods\\nimplemented at or above...'. \\\"heh heh -- somebody please find nice wording here!!\\\"\\n\\taMenu popUpInWorld: self currentWorld! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'ka 11/29/2005 20:53'!\\nlikelyCategoryToShow\\n\\t\\\"Choose a category to show based on what's already showing and on some predefined heuristics\\\"\\n\\n\\t| possible all aCat currVocab |\\n\\tall := (scriptedPlayer categoriesForViewer: self) asOrderedCollection.\\n\\tpossible _ all copy.\\n\\n\\tcurrVocab := self currentVocabulary.\\n\\tself categoryMorphs do: \\n\\t\\t\\t[:m | \\n\\t\\t\\taCat := currVocab categoryWhoseTranslatedWordingIs: m currentCategory.\\n\\t\\t\\taCat ifNotNil: [possible remove: aCat wording ifAbsent: []]].\\n\\n\\t(possible includes: ScriptingSystem nameForInstanceVariablesCategory translated) ifTrue:\\n\\t\\t[^ ScriptingSystem nameForInstanceVariablesCategory].\\n\\n\\t(currVocab isEToyVocabulary) \\n\\t\\tifTrue: \\n\\t\\t\\t[(possible includes: ScriptingSystem nameForScriptsCategory translated) \\n\\t\\t\\t\\tifTrue: [^ ScriptingSystem nameForScriptsCategory]].\\n\\t{'kedama' translated. #basic translated} \\n\\t\\tdo: [:preferred | (possible includes: preferred) ifTrue: [^ preferred]].\\n\\t((scriptedPlayer isPlayerLike) \\n\\t\\tand: [scriptedPlayer hasOnlySketchCostumes]) \\n\\t\\t\\tifTrue: [(possible includes: #tests translated) ifTrue: [^#tests translated]].\\n\\t{#'color & border' translated. #tests translated. #color translated. #flagging translated. #comparing translated.} \\n\\t\\tdo: [:preferred | (possible includes: preferred) ifTrue: [^ preferred]].\\n\\t^ possible isEmpty ifFalse: [possible first] ifTrue: [all first]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:17'!\\nlimitClass\\n\\t\\\"Answer the limit class to use in this viewer\\\"\\n\\n\\t| aClass |\\n\\t(aClass _ self valueOfProperty: #limitClass) ifNotNil:\\n\\t\\t[^ aClass].\\n\\n\\taClass _ scriptedPlayer defaultLimitClassForVocabulary: self currentVocabulary.\\n\\tself setProperty: #limitClass toValue: aClass.\\n\\t^ aClass! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:31'!\\nlimitClass: aClass\\n\\t\\\"Set aClass as the limit class for this viewer, without side effects\\\"\\n\\n\\tself setProperty: #limitClass toValue: aClass\\n! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 12/11/2000 10:51'!\\nouterViewer\\n\\t\\\"Answer the StandardViewer or equivalent that contains this object\\\"\\n\\n\\t^ self! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'di 2/19/2001 10:39'!\\nrecreateCategories\\n\\t\\\"To change from old to new tiles\\\"\\n\\t| cats |\\n\\tcats _ self categoriesCurrentlyShowing.\\n\\tself removeAllMorphsIn: self categoryMorphs.\\n\\tcats do: [:cat | self addCategoryViewerFor: cat]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'yo 4/4/2005 14:42'!\\nsearchingViewerMorphs\\n\\t^ self submorphsSatisfying: [:m | m isKindOf: SearchingViewer].! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:31'!\\nsetLimitClass: aClass\\n\\t\\\"Set aClass as the limit class for this viewer\\\"\\n\\n\\tself limitClass: aClass.\\n\\tself relaunchViewer\\n! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 5/29/2001 22:43'!\\nsymbolsOfCategoriesCurrentlyShowing\\n\\t\\\"Answer the category symbols of my categoryMorphs\\\"\\n\\n\\t^ self categoryMorphs collect: [:m | m chosenCategorySymbol]! !\\n\\n\\n!StandardViewer methodsFor: 'classification' stamp: 'ar 6/30/2001 13:13'!\\nisStandardViewer\\n\\t^true! !\\n\\n\\n!StandardViewer methodsFor: 'debug and other' stamp: 'sw 6/20/2001 12:47'!\\nviewMorphDirectly\\n\\t\\\"Launch a new viewer to replace the receiver.\\\"\\n\\n\\tself delete.\\n\\tself presenter viewObjectDirectly: scriptedPlayer costume renderedMorph! !\\n\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 9/2/2004 11:30'!\\naddHeaderMorphWithBarHeight: anInteger includeDismissButton: aBoolean\\n\\t\\\"Add the header morph to the receiver, using anInteger as a guide for its height, and if aBoolean is true, include a dismiss buton for it\\\"\\n\\n\\t| header aFont aButton aTextMorph nail wrpr costs headWrapper |\\n\\theader _ AlignmentMorph newRow color: self color muchLighter; wrapCentering: #center; cellPositioning: #leftCenter.\\n\\taFont _ Preferences standardButtonFont.\\n\\taBoolean ifTrue:\\n\\t\\t[aButton _ self tanOButton.\\n\\t\\theader addMorph: aButton.\\n\\t\\taButton target: self;\\n\\t\\t\\t\\tactionSelector: #dismiss;\\n\\t\\t\\t\\tsetBalloonText: 'remove this entire Viewer from the screen\\ndon''t worry -- nothing will be lost!!.' translated.\\n\\t\\theader addTransparentSpacerOfSize: 4@1].\\n\\n\\taButton _ IconicButton new borderWidth: 0;\\n\\t\\t\\tlabelGraphic: (ScriptingSystem formAtKey: #AddCategoryViewer); color: Color transparent; \\n\\t\\t\\tactWhen: #buttonDown;\\n\\t\\t\\ttarget: self;\\n\\t\\t\\tactionSelector: #addCategoryViewer;\\n\\t\\t\\tsetBalloonText: 'click here to add\\nanother category pane' translated;\\n\\t\\t\\tshedSelvedge.\\n\\theader addMorphBack: aButton.\\n\\theader addTransparentSpacerOfSize: 4@1.\\n\\n\\tcosts _ scriptedPlayer costumes.\\n\\tcosts ifNotNil:\\n\\t[(costs size > 1 or: [costs size = 1 and: [costs first ~~ scriptedPlayer costume]]) ifTrue:\\n\\t\\t[header addUpDownArrowsFor: self.\\n\\t\\t(wrpr _ header submorphs last) submorphs second setBalloonText: 'switch to previous costume' translated.\\t\\n\\t\\twrpr submorphs first setBalloonText: 'switch to next costume' translated]].\\t\\n\\n\\tnail _ (self hasProperty: #noInteriorThumbnail)\\n\\t\\tifFalse:\\n\\t\\t\\t[ThumbnailMorph new objectToView: scriptedPlayer viewSelector: #costume]\\n\\t\\tifTrue:\\n\\t\\t\\t[ImageMorph new image: Cursor menu].\\n\\tnail on: #mouseDown send: #offerViewerMenuForEvt:morph: to: scriptedPlayer.\\n\\theader addMorphBack: nail.\\n\\tnail setBalloonText: 'click here to get a menu\\nthat will allow you to\\nadd a variable,\\ntear off a tile, etc..' translated.\\n\\t(self hasProperty: #noInteriorThumbnail)\\n\\t\\tifFalse:\\n\\t\\t\\t[nail borderWidth: 3; borderColor: #raised].\\n\\n\\theader addTransparentSpacerOfSize: 5@5.\\n\\n\\\"\\taButton _ SimpleButtonMorph new target: self; actionSelector: #newEmptyScript; label: 'S' translated font: (aFont _ StrikeFont familyName: #ComicBold size: 16); color: Color transparent; borderWidth: 0; actWhen: #buttonDown.\\n\\taButton setBalloonText: 'drag from here to\\ncreate a new script\\nfor this object' translated.\\t\\n\\theader addMorphBack: aButton.\\n\\n\\theader addTransparentSpacerOfSize: 8@5.\\\"\\n\\t\\n\\taButton _ SimpleButtonMorph new target: scriptedPlayer; actionSelector: #addInstanceVariable; label: 'v' translated font: (aFont emphasized: 1); color: Color transparent; borderWidth: 1; actWhen: #buttonUp.\\n\\t\\\"aButton firstSubmorph color: Color gray.\\\"\\n\\taButton setBalloonText: 'click here to add a variable\\nto this object.' translated.\\n\\theader addMorphBack: aButton.\\n\\n\\theader addTransparentSpacerOfSize: 5@5.\\n\\tself viewsMorph ifTrue: [scriptedPlayer costume assureExternalName].\\n\\taTextMorph _ UpdatingStringMorph new\\n\\t\\tuseStringFormat;\\n\\t\\ttarget: scriptedPlayer;\\n\\t\\tgetSelector: #nameForViewer;\\n\\t\\tsetNameTo: 'name';\\n\\t\\tfont: ScriptingSystem fontForNameEditingInScriptor.\\n\\tself viewsMorph ifTrue:\\n\\t\\t[aTextMorph putSelector: #setName:.\\n\\t\\taTextMorph setProperty: #okToTextEdit toValue: true].\\n\\taTextMorph step.\\n\\theader addMorphBack: aTextMorph.\\n\\taTextMorph setBalloonText: 'Click here to edit the player''s name.' translated.\\t\\n\\n\\theader beSticky.\\n\\tanInteger > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[headWrapper _ AlignmentMorph newColumn color: self color.\\n\\t\\t\\theadWrapper addTransparentSpacerOfSize: (0 @ anInteger).\\n\\t\\t\\theadWrapper addMorphBack: header.\\n\\t\\t\\tself addMorph: headWrapper]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorph: header]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'gm 2/22/2003 13:44'!\\naffordsUniclass\\n\\t\\\"Answer true iff the receiver operates on behalf of an object that is, or could become, a member of a Uniclass\\\"\\n\\n\\t| viewee |\\n\\t^(viewee := self objectViewed) belongsToUniClass or: \\n\\t\\t\\t[((viewee isInteger) not and: [viewee isBehavior not]) \\n\\t\\t\\t\\tand: [self userLevel > 0]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'ar 6/30/2001 13:23'!\\nfitFlap\\n\\t(owner notNil and:[owner isFlap]) ifTrue:[\\n\\t\\towner width < self fullBounds width ifTrue:[\\n\\t\\t\\towner assureFlapWidth: self fullBounds width + 25.\\n\\t\\t].\\n\\t].! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 12/23/1998 23:26'!\\ninitialHeightToAllow\\n\\t^ 300! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/25/1999 23:04'!\\ninitializeFor: aPlayer barHeight: anInteger\\n\\t^ self initializeFor: aPlayer barHeight: anInteger includeDismissButton: true! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 8/4/2000 13:02'!\\ninitializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean\\n\\tself initializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean showCategories: nil! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'yo 8/18/2005 13:43'!\\ninitializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean showCategories: categoryInfo\\n\\t\\\"Initialize the receiver to be a look inside the given Player. The categoryInfo, if present, describes which categories should be present in it, in which order\\\"\\n\\n\\tscriptedPlayer _ aPlayer.\\n\\tself listDirection: #topToBottom;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tborderWidth: 1.\\n\\tself color: self standardViewerColor.\\n\\tself addHeaderMorphWithBarHeight: anInteger includeDismissButton: aBoolean.\\n\\n\\tcategoryInfo isEmptyOrNil\\n\\t\\tifFalse: \\\"Reincarnating an pre-existing list\\\"\\n\\t\\t\\t[categoryInfo do:\\n\\t\\t\\t\\t[:aCat | self addCategoryViewerFor: aCat]]\\n\\t\\tifTrue: \\\"starting fresh\\\"\\n\\t\\t\\t[self addSearchPane. \\n\\t\\t\\tself addCategoryViewer.\\n\\t\\t\\tself addCategoryViewer.\\n\\t\\t\\t(scriptedPlayer costume isMemberOf: KedamaMorph) ifTrue: [self addCategoryViewer].\\n\\t\\t].! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/4/2001 18:06'!\\nrawVocabulary: aVocabulary\\n\\t\\\"Mark the receiver as having aVocabulary as its vocabulary\\\"\\n\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocabulary vocabularyName! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 8/29/2004 17:18'!\\nswitchToVocabulary: aVocabulary\\n\\t\\\"Make the receiver show categories and methods as dictated by aVocabulary. If this constitutes a switch, then wipe out existing category viewers, which may be showing the wrong thing.\\\"\\n\\n\\tself adoptVocabulary: aVocabulary. \\\"for benefit of submorphs\\\"\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocabulary vocabularyName.\\n\\t((scriptedPlayer isPlayerLike) and: [self isUniversalTiles not]) ifTrue:\\n\\t\\t[scriptedPlayer allScriptEditors do:\\n\\t\\t\\t[:aScriptEditor |\\n\\t\\t\\t\\taScriptEditor adoptVocabulary: aVocabulary]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/4/2001 19:40'!\\nuseVocabulary: aVocabulary\\n\\t\\\"Make the receiver show categories and methods as dictated by aVocabulary\\\"\\n\\n\\t| itsName |\\n\\t((self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil]) == (itsName _ aVocabulary vocabularyName)) ifFalse:\\n\\t\\t[self setProperty: #currentVocabularySymbol toValue: itsName.\\n\\t\\tself removeProperty: #currentVocabulary. \\\"grandfathered\\\"\\n\\t\\t(self submorphs select: [:m | m isKindOf: CategoryViewer]) do: [:m | m delete]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 10/26/2000 09:42'!\\nuserLevel\\n\\t\\\"Answer the user level for this viewer, which can be used in figuring out what to display in the viewer. Initially, we make little use of this, but in past prototypes, and in future deployments, it may be handy.\\\"\\n\\n\\t^ self valueOfProperty: #userLevel ifAbsent: [1]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 8/29/2004 17:18'!\\nviewsMorph\\n\\t\\\"Answer whether the receiver views a morph. Traditional viewers up until late 2000 *all* viewed morphs (as per the morph/player architecture), but viewers on non-morph/players have now become possible\\\"\\n\\n\\t^ scriptedPlayer isPlayerLike! !\\n\\n\\n!StandardViewer methodsFor: 'macpal' stamp: 'sw 6/4/2001 18:05'!\\ncurrentVocabulary\\n\\t\\\"Answer the vocabulary currently associated with the receiver\\\"\\n\\n\\t| aSym aVocab |\\n\\taSym _ self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil].\\n\\taSym ifNil:\\n\\t\\t[aVocab _ self valueOfProperty: #currentVocabulary ifAbsent: [nil].\\n\\t\\taVocab ifNotNil:\\n\\t\\t\\t[aSym _ aVocab vocabularyName.\\n\\t\\t\\tself removeProperty: #currentVocabulary.\\n\\t\\t\\tself setProperty: #currentVocabularySymbol toValue: aSym]].\\n\\t^ aSym\\n\\t\\tifNotNil:\\n\\t\\t\\t[Vocabulary vocabularyNamed: aSym]\\n\\t\\tifNil:\\n\\t\\t\\t[(self world ifNil: [ActiveWorld]) currentVocabularyFor: scriptedPlayer]! !\\n\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/25/1999 22:08'!\\ndismiss\\n\\t| aFlapTab |\\n\\t\\\"User hit the dismiss button.\\\"\\n\\t(owner isKindOf: TabbedPalette)\\n\\t\\tifTrue:\\n\\t\\t\\t[^ owner showNoPalette].\\n\\t(aFlapTab _ self pasteUpMorph correspondingFlapTab) ifNotNil:\\n\\t\\t[^ aFlapTab dismissViaHalo].\\n\\tself topRendererOrSelf delete! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/24/1998 14:34'!\\ndownArrowHit\\n\\tself nextCostume! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/26/1999 01:07'!\\nhasDismissButton\\n\\tsubmorphs isEmptyOrNil ifTrue: [^ false].\\n\\t^ (submorphs first allMorphs detect:\\n\\t\\t[:possible | (possible isKindOf: SimpleButtonMorph) and: [possible actionSelector == #dismiss]]\\n\\t\\t\\tifNone: [nil]) notNil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 5/18/2001 10:46'!\\nopenLexicon\\n\\t\\\"Open a lexicon browser on the receiver, showing its current vocabulary\\\"\\n\\n\\t| littleHim | \\n\\tlittleHim _ scriptedPlayer assureUniClass.\\n\\n\\t(InstanceBrowser new useVocabulary: self currentVocabulary) openOnObject: littleHim inWorld: ActiveWorld showingSelector: nil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 4/20/2001 21:22'!\\nrelaunchViewer\\n\\t\\\"Launch a new viewer to replace the receiver.\\\"\\n\\n\\tself presenter updateViewer: self forceToShow: nil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 12/23/1998 22:45'!\\nstandardViewerColor\\n\\t ^ Color r: 0.572 g: 0.883 b: 0.572! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/24/1998 14:33'!\\nupArrowHit\\n\\tself previousCostume! !\\nPolygonMorph subclass: #StarMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!StarMorph commentStamp: 'wiz 9/6/2005 12:30' prior: 0!\\nI am a very flexible star..\\n\\nGrab me from the supplies flap or from the graphic objects.\\nAdd my handles and you can move and resize me.\\nThe up and down arrows increase or reduce the number of my sides.\\nThe right and left arrows cycle thru different amounts of pointiness.\\n\\n\\nUse the arrows right and left of my center or get stars with a specific amount of pointyness. The left side goes from fat to thin and then cycles around again. The right goes from thin to fat. Hold down the shift key if you wish to stop the cycling at the extremes.\\n\\nUse the arrows up and down to change the number of sides if you would like a different number of points.\\n\\nTo add or remove just one side hold the shift key down as you use the arrows or use the menu items for that purpose.\\n\\n\\nIf you add or remove just one point I will have an odd number of sides. When that happens I can only look like a regular polygon. The right and left arrows will have no effect. Add or remove just one more side and you can shift drag the outer handle or use the arrows to restore my pointiness. \\n\\nThat was too complicated. It is gone. You can get regular polygon shapes by adjusting my pointiness. For example the extreme of a five pointed star is a dodecahedron (10 sided regular polygon) and one step less extreme is a pentagon (5 sided regular polygon).\\n\\n\\nAt some time you will probably shift drag the outer handle thru the center handle.\\nWhile I looked round as you shrunk me, I will look very much like an asterisk as you pull me away. What happens is that inside bend shrunk on the way down because it can never be larger than the outer point (or it wouldn't be the innerbend would it).\\nBut on the way out it is perfectly happy to remain small. So I look like an asterisk.\\n\\nTo fatten me up (if you haven't already figured this out by fooling around) hold the shift down an move the outer handle towards the center (but not quite all the way) then let the shift up and move the outer handle away. A couple of cycles like this and I'll be looking fat and jolly again. Or you can now just use the right arrow to make me fatter.\\n\\nThis is also the reason I don't let the inside bend get larger than the outer point.\\nIf I did the same process that fattened me when I was an asterisk would also grow an asterisk so large squeak would complain about not having enough memory.\\n\\nHistorical note:\\n\\nThe former star had two bugs that are fixed here.\\nThe outer handle now no longer jumps from one point to another.\\nThe other bug prevented some higher order stars from looking right. \\nWhich is why the former star didn't allow you to change the number of points. !\\n\\n\\n!StarMorph methodsFor: 'access' stamp: 'wiz 1/11/2005 03:58'!\\nskipRatios\\n\\\"Return an array of ratios of the inner radius to the outer radius.\\nRatios are in ascending order from 0.0 to 1.0.\\\"\\n\\\"Assume we have at least one vertex.\\nAll ways return a number <= 1.0\\\"\\n\\n| n alpha |\\n\\\"Odd vertices sizes can not be stars only regular polygons\\\"\\nn:= vertices size . n odd ifTrue: [ ^ #( 1.0) ] .\\n\\nalpha := Float pi / (n//2) asFloat .\\n\\n^ (((( Float halfPi -alpha to: alpha /2.0 by: alpha negated ) \\n\\tcollect: [:angle |( (angle) sin )/\\n\\t\\t\\t\\t\\t(angle + alpha ) sin ]\\n\\t) copyWith: 0.0) copyWithFirst: 1.0) reversed .! !\\n\\n!StarMorph methodsFor: 'access' stamp: 'wiz 1/4/2005 20:14'!\\nstarRatio\\n\\\"Return the ratio of the inner radius to the outer radius.\\\"\\n\\\"Assume we have at least one vertex.\\nAll ways return a number <= 1.0\\\"\\n| r c |\\nc := vertices average rounded .\\nr := (c dist: vertices last) / (c dist: vertices first) .\\n^ r > 1.0 ifTrue: [ r reciprocal ] ifFalse: [r ] .! !\\n\\n\\n!StarMorph methodsFor: 'accessing' stamp: 'wiz 1/4/2005 19:47'!\\nstarRatio: r\\n\\\"Set the star s.t. the ratio of the inner radius to the outer radius is r.\\nIf r is > 1 use the reciprocal to keep the outer radius first.\\\"\\n\\\"Assume we have at least one vertex.\\nset\\nAll ways return a number <= 1.0\\\"\\nself makeVertices: vertices size starRatio:( r > 1.0 ifTrue: [ r reciprocal ] ifFalse: [r ] ).! !\\n\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 12/15/2004 00:59'!\\naddHandles\\n\\tself addStarHandles! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/15/2005 00:20'!\\naddStarHandles\\n\\t\\\"Outer handle must not be blocked so it comes first. \\n\\tThe editing routine expects to find the center handle second.\\n\\tThe side and shape changing handles follow these.\\\"\\n\\t| center |\\n\\tself removeHandles.\\n\\t\\\"Check for old stars and correct order of vertices.\\\"\\n\\tself insureCompatability .\\n\\thandles := OrderedCollection new.\\n\\tcenter := vertices average rounded.\\n\\tself withCenterOuterHandles; withUpDownLeftRightHandlesAround: 6 center: center.\\n\\tself placeHandles.\\n\\tself changed.\\n\\t! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 9/5/2005 23:12'!\\nchangeVertices: label event: evt fromHandle: handle \\n\\t| |\\n\\tlabel == #more\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self moreVertices \\\"not oneMoreVertex\\\"]\\n\\t\\t\\t\\tifFalse: [self moreVertices]].\\n\\tlabel == #less\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self lessVertices \\\"not oneLessVertex\\\"]\\n\\t\\t\\t\\tifFalse: [self lessVertices]].\\n\\tlabel == #next\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self makeVertices: vertices size starRatio: self nextSkip]\\n\\t\\t\\t\\tifFalse: [self makeVertices: vertices size starRatio: self nextTwinkleSkip]].\\n\\tlabel == #prev\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self makeVertices: vertices size starRatio: self prevSkip]\\n\\t\\t\\t\\tifFalse: [self makeVertices: vertices size starRatio: self prevTwinkleSkip]].\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/20/2005 19:07'!\\ndragVertex: label event: evt fromHandle: handle \\n\\t| center r1 rN rNext a1 rTotal |\\n\\tlabel == #outside\\n\\t\\tifTrue: [center := handles second center.\\n\\t\\t\\tr1 := center dist: vertices first.\\n\\t\\t\\t\\\"Rounding and what happens as the outer handle\\n\\t\\t\\tapproached the center, \\n\\t\\t\\trequires we guard the inner radius \\n\\t\\t\\tfrom becoming larger than the outer radius.\\\"\\n\\t\\t\\trN := r1\\n\\t\\t\\t\\t\\t\\tmin: (center dist: vertices last).\\n\\t\\t\\trNext := 1\\n\\t\\t\\t\\t\\t\\tmax: (center dist: evt cursorPoint).\\n\\t\\t\\ta1 := 270.0\\n\\t\\t\\t\\t\\t\\t+ (center bearingToPoint: evt cursorPoint).\\n\\t\\t\\trTotal := vertices size even\\n\\t\\t\\t\\t\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [r1 + rN * rNext / r1]]\\n\\t\\t\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\t\\t\\trNext := rTotal - rNext.\\n\\t\\t\\tvertices := ((a1 to: a1 + 359.999 by: 360.0 / vertices size)\\n\\t\\t\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)]) .\\n\\t\\t\\thandle align: handle center with: evt cursorPoint].\\n\\tlabel == #center\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self updateFormFromUser]\\n\\t\\t\\t\\tifFalse: [self position: self position + (evt cursorPoint - handle center)]].\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/15/2005 00:19'!\\nplaceHandles\\n\\t\\\"Add the handles to my submorphs.\\\"\\n\\thandles reverseDo: [:each | self addMorphFront: each ] .\\n\\t\\n\\t! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'di 9/26/97 11:11'!\\nupdateHandles! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/11/2005 19:39'!\\nwithCenterOuterHandles\\n\\t\\\"Add to our handles the center positioning and outer resizing\\n\\thandles. Outer handle must not be blocked so it comes first. \\n\\tThe editing routine expects to find the center handle second.\\n\\tThe side and shape changing handles follow these.\\\"\\n\\t| center v1 hExtent holder |\\n\\tcenter := vertices average rounded.\\n\\thExtent := 8 @ 8.\\n\\tv1 := vertices first.\\n\\tholder := {(EllipseMorph\\n\\t\\t\\t\\tnewBounds: (Rectangle center: v1 extent: hExtent)\\n\\t\\t\\t\\tcolor: Color yellow)\\n\\t\\t\\t\\tsetBalloonText: 'Move me to adjust size. Shift move to adjust pointiness'. (EllipseMorph\\n\\t\\t\\t\\tnewBounds: (Rectangle center: center extent: hExtent)\\n\\t\\t\\t\\tcolor: Color yellow)\\n\\t\\t\\t\\tsetBalloonText: 'Move me to adjust position'}.\\n\\tholder\\n\\t\\twith: {#outside. #center}\\n\\t\\tdo: [:handle :which | handle\\n\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\tsend: #dragVertex:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which;\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\tsend: #dragVertex:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which].\\n\\thandles addAll: holder! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/11/2005 19:47'!\\nwithUpDownLeftRightHandlesAround: radius center: center\\n\\t\\\"Add to our handles the side and shape changing handles.\\\"\\n\\t| tri above holder triAbove triBelow triRight triLeft |\\n\\tabove := 0 @ radius negated.\\n\\t\\n\\ttri := Array\\n\\t\\t\\t\\twith: 0 @ -5\\n\\t\\t\\t\\twith: 4 @ 3\\n\\t\\t\\t\\twith: -4 @ 3.\\n\\ttriAbove := tri + (center + above).\\n\\ttriBelow := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #pi centerAt: center].\\n\\ttriRight := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #right centerAt: center].\\n\\ttriLeft := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #left centerAt: center].\\n\\t\\t\\t\\t\\n\\tholder := { (PolygonMorph\\n\\t\\t\\t\\tvertices: triAbove\\n\\t\\t\\t\\tcolor: Color green\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'More points.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triBelow\\n\\t\\t\\t\\tcolor: Color magenta\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Fewer points.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triRight\\n\\t\\t\\t\\tcolor: Color green\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Twinkle fatter.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triLeft\\n\\t\\t\\t\\tcolor: Color magenta\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Twinkle thinner.'}.\\n\\t\\n\\tholder\\n\\t\\twith: {#more. #less. #next. #prev}\\n\\t\\tdo: [:handle :which | handle\\n\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\tsend: #changeVertices:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which;\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\tsend: #changeVertices:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which].\\n\\t^ handles addAll: holder! !\\n\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:34'!\\nnextSkip\\n\\t\\\"Set starRatio to next skip wrapping if needed.\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := (c dist: vertices first) truncated asFloat.\\n\\trN := c dist: vertices last.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindFirst: [:r | r > (rN + 1.0)].\\n\\t\\\"n = 0\\n\\t\\tifTrue: [n := skips size].\\\"\\n\\t^ skips atWrap: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:42'!\\nnextTwinkleSkip\\n\\t\\\"Set starRatio to next skip wrapping if needed.\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := (c dist: vertices first) truncated asFloat.\\n\\trN := c dist: vertices last.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindFirst: [:r | r > (rN + 1.0)].\\n\\tn = 0\\n\\t\\tifTrue: [ n := 1].\\n\\t^ skips atWrap: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:41'!\\nprevSkip\\n\\t\\\"Set starRatio to next skip wrapping if necessary\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := c dist: vertices first.\\n\\trN := (c dist: vertices last) truncated asFloat.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindLast: [:r | r + 1.0 < rN].\\n\\tn = 0\\n\\t\\tifTrue: [n := 1].\\n\\t^ skips at: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:19'!\\nprevTwinkleSkip\\n\\t\\\"Set starRatio to next skip wrapping if necessary\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := c dist: vertices first.\\n\\trN := (c dist: vertices last) truncated asFloat.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindLast: [:r | r + 1.0 < rN].\\n\\t\\\"n = 0\\n\\tifTrue: [^ oldR].\\\"\\n\\t^ skips atWrap: n! !\\n\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:33'!\\ndefaultCenter\\n\\t\\\"answer the default center for the receiver\\\"\\n\\t^ 0 asPoint! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightBlue! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:33'!\\ndefaultFirstVertex\\n\\t\\\"answer the default first outer point for the receiver.\\n\\tThis with the center determines the angle and size of the outer radius.\\\"\\n\\t^ 10 asPoint! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:28'!\\ndefaultSides\\n\\t\\\"answer the default number of sides for the receiver\\\"\\n\\t^ 10! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:29'!\\ndefaultStarRatio\\n\\t\\\"answer the default ratio of outer radius to inner radius for the receiver\\\"\\n\\t^ 5.0 / 12.0! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:36'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tself\\n\\t\\tmakeVertices: self defaultSides\\n\\t\\tstarRatio: self defaultStarRatio\\n\\t\\twithCenter: self defaultCenter\\n\\t\\twithPoint: self defaultFirstVertex.\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/9/2005 20:15'!\\ninsureCompatability\\n\\\"The old stars had the point on the second not the first vertex. So we need to check for this special case.\\\"\\n | c v1 v2 |\\nc := vertices average rounded.\\n v1 := vertices first .\\n v2 := vertices second .\\n(c dist: v1) + 0.001 < (c dist: v2) ifTrue: [vertices := vertices allButFirst copyWith: v1]\\n\\n! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 12/30/2004 02:57'!\\nmakeVertices: nSides \\n\\t\\\"Assuming vertices has at least one point, make a new star \\n\\tor regular polygon (for odd sided polygons).\\n\\tThe center of the polygon and the first vertex remain in\\n\\tplace. The inner distances for stars remain the same also if\\n\\tpossible.\\\"\\n\\t| center r1 rN rNext a1 rTotal |\\n\\tcenter := vertices average rounded.\\n\\tr1 := center dist: vertices first.\\n\\trN := center dist: vertices last.\\n\\trNext := 1 max: r1.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: vertices first).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed .\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/4/2005 19:31'!\\nmakeVertices: nSides starRatio: fraction\\n\\t\\\"Assuming vertices has at least one point, make a new star \\n\\tor regular polygon (for odd sided polygons).\\n\\tThe center of the polygon and the first vertex remain in\\n\\tplace. The inner distances for stars remain the same also if\\n\\tpossible.\\\"\\n\\t| center r1 rN rNext a1 rTotal |\\n\\tcenter := vertices average rounded.\\n\\tr1 := center dist: vertices first.\\n\\trNext := 1 max: r1.\\n\\trN := (1.0 min: fraction) * rNext.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: vertices first).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed .\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 21:36'!\\nmakeVertices: nSides starRatio: fraction withCenter: center withPoint: aPoint \\n\\t\\\"Make a new star or regular polygon (for odd sided polygons).\\n\\tThis makes star vertices from scratch without any feedback from existing vertices.\\\"\\n\\t| r1 rN rNext a1 rTotal |\\n\\tr1 := center dist: aPoint.\\n\\trNext := 1 max: r1.\\n\\trN := (1.0 min: fraction)\\n\\t\\t\\t\\t* rNext.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: aPoint).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed.\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 9/5/2005 23:08'!\\naddChangeSidesMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Menu items to change number of sides.\\\"\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'more sides' translated action: #moreVertices.\\n\\taCustomMenu add: 'fewer sides' translated action: #lessVertices.\\n\\\"\\tRegular polygons can be simulated with the one of the skip stars \\n\\tand it would confuse users to have stars be limited to Regular polygons.\\n\\tSo we've removed those menu items - wiz\\\"\\n\\\"\\taCustomMenu add: 'one more side' translated action: #oneMoreVertex.\\n\\taCustomMenu add: 'one fewer side' translated action: #oneLessVertex\\\"! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 1/11/2005 14:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph \\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\nself addChangeSidesMenuItems: aCustomMenu hand: aHandMorph.\\nself addTwinkleMenuItems: aCustomMenu hand: aHandMorph.\\n\\t! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 1/11/2005 20:38'!\\naddTwinkleMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Menu items to change the sharpness of the star.\\\"\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'twinkle fatter' translated action: #nextTwinkle.\\n\\taCustomMenu add: 'twinkle thinner' translated action: #prevTwinkle.\\n\\\"\\taCustomMenu add: 'fatter star' translated action: #nextFatter.\\n\\taCustomMenu add: 'thinner star' translated action: #prevThinner\\\"\\n\\t\\n\\t\\n\\n\\n! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 12/11/2004 16:45'!\\noneLessVertex\\n\\tself\\n\\t\\tmakeVertices: (3 max: 1 negated + vertices size)! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 12/11/2004 16:46'!\\noneMoreVertex\\n\\tself makeVertices: 1 + vertices size! !\\n\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 12/12/2004 16:43'!\\nlessVertices\\n\\\"Reduce the number of points by one until we are a diamond. If odd reduce the number of sides by two until we become a triangle. See class comment.\\\"\\n\\t| nVerts |\\n\\t( nVerts := 2 negated + vertices size) < 3 ifFalse: [\\n\\tself\\n\\t\\tmakeVertices: nVerts]! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 12/11/2004 16:45'!\\nmoreVertices\\n\\tself makeVertices: 2+ vertices size! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/11/2005 20:37'!\\nnextTwinkle\\n\\tself makeVertices: vertices size starRatio: self nextTwinkleSkip .\\n\\tself computeBounds.! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/11/2005 20:37'!\\nprevTwinkle\\n\\tself makeVertices: vertices size starRatio: self prevTwinkleSkip .\\n\\tself computeBounds.! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/15/2005 02:26'!\\nupdateFormFromUser\\n\\\"Does nothing here. Overridden in subclasses e.g. Kaleidoscope.\\\"\\n^ self.! !\\n\\n\\n!StarMorph methodsFor: 'parts bin' stamp: 'sw 7/2/2001 11:07'!\\ninitializeToStandAlone\\n\\t^ self initialize removeHandles! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:37'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:39'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StarMorph\\t\\tauthoringPrototype\\t'Star'\\t'A star')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StarMorph\\tauthoringPrototype\\t'Star'\\t'A star')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.]! !\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:41'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!StarMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 16:22'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Star'\\n\\t\\tcategories:\\t\\t#('Graphics')\\n\\t\\tdocumentation:\\t'A symmetrical polygon in the shape of a star'! !\\nStarSqueakMorph subclass: #StarSqueakAntColony\\n\\tinstanceVariableNames: 'antCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakAntColony methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tantCount := 50.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'menu' stamp: 'jm 2/7/2001 18:41'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(antCount 10 500 'The number of ants searching for food.'))\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 1/19/2001 10:30'!\\ndiffusePheromone\\n\\n\\tself diffusePatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 1/19/2001 18:02'!\\nevaporatePheromone\\n\\n\\tself decayPatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 2/7/2001 08:03'!\\nsetupFood: aPatch\\n\\t\\\"Create several food caches.\\\"\\n\\n\\taPatch set: 'food' to: 0. \\\"patch default is no food\\\"\\n\\n\\t((aPatch distanceTo: 15@15) <= 1 or:\\n\\t [(aPatch distanceTo: 80@20) <= 1 or:\\n\\t [(aPatch distanceTo: 25@80) <= 1 or:\\n\\t [(aPatch distanceTo: 70@70) <= 1]]]) ifTrue: [\\n\\t\\taPatch set: 'food' to: 10.\\n\\t\\taPatch color: Color red].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'sd 11/20/2005 21:26'!\\nsetupNest: aPatch\\n\\t\\\"Create a nest of radius 5 centered at 50@50.\\\"\\n\\n\\t| distanceToNest |\\n\\tdistanceToNest := aPatch distanceTo: 50@50.\\n\\tdistanceToNest <= 4\\n\\t\\tifTrue: [\\n\\t\\t\\taPatch set: 'isNest' to: 1.\\n\\t\\t\\taPatch color: Color brown lighter]\\n\\t\\tifFalse: [aPatch set: 'isNest' to: 0].\\n\\n\\t\\\"create a 'hill' of nest scent centered on the nest\\\"\\n\\tdistanceToNest > 0 ifTrue: [\\n\\t\\taPatch set: 'nestScent' to: 10000.0 // distanceToNest].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 3/8/2001 14:23'!\\nsetupPatches\\n\\t\\\"Create patch variables for sensing the nest and food caches. The nestScent variable is diffused so that it forms a 'hill' of scent over the entire world with its peak at the center of the nest. That way, the ants always know which way the nest is.\\\"\\n\\n\\tself createPatchVariable: 'food'.\\t\\t\\t\\\"greater than zero if patch has food\\\"\\n\\tself createPatchVariable: 'isNest'.\\t\\t\\\"greater than zero if patch is nest\\\"\\n\\tself createPatchVariable: 'nestScent'.\\t\\\"circular gradient with peak centered on nest\\\"\\n\\tself createPatchVariable: 'pheromone'.\\t\\\"dropped by ants when carrying food\\\"\\n\\tself displayPatchVariable: 'pheromone'.\\n\\tself patchesDo: [:p |\\n\\t\\tp color: self backgroundColor.\\n\\t\\tself setupNest: p.\\n\\t\\tself setupFood: p].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 3/8/2001 14:24'!\\nsetupTurtles\\n\\n\\tself makeTurtles: antCount class: AntColonyTurtle.\\n\\tturtles do: [:t |\\n\\t\\tt goto: 50@50.\\n\\t\\tt color: Color black.\\n\\t\\tt isCarryingFood: false.\\n\\t\\tt pheromoneDropSize: 100].\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'jm 2/7/2001 14:45'!\\nantCount\\n\\n\\t^ antCount\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\nantCount: aNumber\\n\\n\\tantCount := aNumber.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'jm 3/11/2001 17:10'!\\nbackgroundColor\\n\\n\\t^ Color brown lighter lighter lighter! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself setupPatches.\\n\\tself setupTurtles.\\n\\tturtleDemons := #(searchForFood pickUpFood returnToNest dropFoodInNest).\\n\\tworldDemons := #(evaporatePheromone diffusePheromone).\\n! !\\nStarSqueakMorph subclass: #StarSqueakDiffusion\\n\\tinstanceVariableNames: 'waterCount dyeCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakDiffusion methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tdyeCount := 200.\\n\\twaterCount := 2000.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'menu' stamp: 'jm 3/8/2001 14:08'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(dyeCount 50 1000 'The number of dye particles.')\\n\\t\\t(waterCount 100 4000 'The number of water particles.'))\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'other' stamp: 'sd 11/20/2005 21:26'!\\nsetupTurtles\\n\\n\\t| radius t |\\n\\tdyeCount ifNil: [dyeCount := 200].\\n\\twaterCount ifNil: [waterCount := 2000].\\n\\tradius := 10.\\n\\tself makeTurtles: waterCount class: DiffusionTurtle.\\n\\tturtles do: [:each |\\n\\t\\teach color: (Color gray: 0.7).\\n\\t\\t(each distanceTo: 50@50) < radius ifTrue: [each die]].\\n\\n\\tself makeTurtles: dyeCount class: DiffusionTurtle.\\n\\tturtles size - (dyeCount - 1) to: turtles size do: [:i |\\n\\t\\tt := turtles at: i.\\n\\t\\tt goto: 50@50.\\n\\t\\tt forward: (self random: radius).\\n\\t\\tt color: Color green darker darker].\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'jm 3/8/2001 14:07'!\\ndyeCount\\n\\n\\t^ dyeCount\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ndyeCount: aNumber\\n\\n\\tdyeCount := aNumber asInteger max: 1.\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'jm 3/8/2001 14:07'!\\nwaterCount\\n\\n\\t^ waterCount\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\nwaterCount: aNumber\\n\\n\\twaterCount := aNumber asInteger max: 1.\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself patchesDo: [:p | p color: (Color gray: 0.9)].\\n\\tself setupTurtles.\\n\\tturtleDemons := #(move bounce).\\n! !\\nStarSqueakMorph subclass: #StarSqueakForestFire\\n\\tinstanceVariableNames: 'treePercentage'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakForestFire methodsFor: 'demons' stamp: 'sd 11/20/2005 21:26'!\\nconsumeFuel\\n\\n\\t| level |\\n\\tself patchesDo: [:p |\\n\\t\\tlevel := p get: #flameLevel.\\n\\t\\tlevel > 0 ifTrue: [\\n\\t\\t\\tlevel := (level - 15) max: 0.\\n\\t\\t\\tp set: #flameLevel to: level.\\n\\t\\t\\tp brightness: level]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'demons' stamp: 'jm 1/28/2001 16:33'!\\nspreadFire\\n\\n\\tself patchesDo: [:p |\\n\\t\\t(p get: #isUnburnt) > 0 ifTrue: [\\n\\t\\t\\t((p neighborN get: #flameLevel) +\\n\\t\\t\\t (p neighborS get: #flameLevel) +\\n\\t\\t\\t (p neighborE get: #flameLevel) +\\n\\t\\t\\t (p neighborW get: #flameLevel)) > 0 ifTrue: [\\n\\t\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\t\\tp set: #flameLevel to: 100.\\n\\t\\t\\t\\tp color: Color red]]].\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\ttreePercentage := 70.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'menu' stamp: 'jm 3/10/2001 11:06'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(treePercentage 0 100 'The probability of that a given patch has a tree.'))\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'parameters' stamp: 'jm 3/10/2001 11:06'!\\ntreePercentage\\n\\n\\t^ treePercentage\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ntreePercentage: aNumber\\n\\n\\ttreePercentage := aNumber.\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself createPatchVariable: #isUnburnt.\\n\\tself createPatchVariable: #flameLevel.\\n\\tself setupTrees.\\n\\tself setupFire.\\n\\tself setupBorder.\\n\\tworldDemons := #(spreadFire consumeFuel).\\n\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 1/28/2001 16:32'!\\nsetupBorder\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp isLeftEdge | p isRightEdge |\\n\\t\\tp isTopEdge | p isBottomEdge ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\tp color: Color blue]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 1/28/2001 16:32'!\\nsetupFire\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp neighborW isLeftEdge ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\tp set: #flameLevel to: 100.\\n\\t\\t\\tp color: Color red]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 3/10/2001 11:09'!\\nsetupTrees\\n\\t\\\"Setup a forest with treePercentage of trees.\\\"\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp set: #isUnburnt to: 0.\\n\\t\\tp set: #flameLevel to: 0.\\n\\t\\t(10 * treePercentage) > (self random: 1000) ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 1.\\n\\t\\t\\tp color: Color green]].\\n! !\\nMorph subclass: #StarSqueakMorph\\n\\tinstanceVariableNames: 'dimensions pixelsPerPatch patchVariables patchVariableToDisplay logPatchVariableScale patchVarDisplayForm patchForm patchColorSetter patchColorGetter turtles turtleDemons worldDemons sniffRange scaledEvaporationRate diffusionRate lastTurtleID generation running stepTime turtlesAtPatchCache turtlesAtPatchCacheValid'\\n\\tclassVariableNames: 'RandomSeed'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakMorph commentStamp: '<historical>' prior: 0!\\nI implement a StarSqueak simulation. StarSqueak is a Squeak version of Mitchel Resnick's Star Logo, a simulation environment designed to explore massively parallel simulations with hundreds or thousands of turtles. See the excellent book \\\"Turtles, Termites, and Traffic Jams: Explorations in Massively Parallel Microworlds\\\" by Mitchel Resnick, MIT Press, 1994.\\n!\\n\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 2/7/2001 13:48'!\\ndiffusionRate\\n\\n\\t^ diffusionRate\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ndiffusionRate: newRate\\n\\t\\\"Set the diffusion rate to an integer between 0 and 10. The diffusion rate gives the number of patches on one size of the area averaged to compute the next value of the variable for a given patch. Larger numbers cause faster diffusion. Zero means no diffusion.\\\"\\n\\n\\tdiffusionRate := (newRate rounded max: 0) min: 10.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 2/7/2001 18:59'!\\nevaporationRate\\n\\n\\t^ 1024 - scaledEvaporationRate! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nevaporationRate: newRate\\n\\t\\\"Set the evaporation rate. The useful range is 0 to 25 or so. Larger numbers cause faster evaporation. Zero means no evaporization.\\\"\\n\\n\\tscaledEvaporationRate := ((1024 - newRate truncated) max: 1) min: 1024.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 3/3/2001 12:50'!\\npixelsPerPatch\\n\\n\\t^ pixelsPerPatch\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\npixelsPerPatch: anInteger\\n\\t\\\"Set the width of one patch in pixels. Larger numbers scale up this StarSqueak world, but numbers larger than 2 or 3 result in a blocky look. The useful range is 1 to 10.\\\"\\n\\n\\tpixelsPerPatch := (anInteger rounded max: 1) min: 10.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'jm 3/3/2001 12:55'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"Drawing optimization. Since I completely fill my bounds with opaque pixels, this method tells Morphic that it isn't necessary to draw any morphs covered by me.\\\"\\n\\t\\n\\t^ aRectangle areasOutside: self bounds\\n! !\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\ndisplay\\n\\t\\\"Display this world on the Display. Used for debugging.\\\"\\n\\n\\t| c |\\n\\tc := FormCanvas extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tc := c copyOffset: bounds origin negated.\\n\\tself drawOn: c.\\n\\tc form display.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\ndrawOn: aCanvas\\n\\t\\\"Display this StarSqueak world.\\\"\\n\\n\\t| tmpForm bitBlt t |\\n\\t\\\"copy the patches form\\\"\\n\\ttmpForm := patchForm deepCopy.\\n\\n\\t\\\"draw patchVariableToDisplay on top of tmpForm as translucent color\\\"\\n\\tself displayPatchVariableOn: tmpForm color: Color yellow shift: logPatchVariableScale.\\n\\n\\t\\\"draw turtles on top of tmpForm\\\"\\n\\tbitBlt := (BitBlt toForm: tmpForm)\\n\\t\\tclipRect: tmpForm boundingBox;\\n\\t\\tcombinationRule: Form over.\\n\\t1 to: turtles size do: [:i |\\n\\t\\tt := turtles at: i.\\n\\t\\tbitBlt\\n\\t\\t\\tdestX: (pixelsPerPatch * t x truncated)\\n\\t\\t\\tdestY: (pixelsPerPatch * t y truncated)\\n\\t\\t\\twidth: pixelsPerPatch\\n\\t\\t\\theight: pixelsPerPatch.\\n\\t\\tbitBlt\\n\\t\\t\\tfillColor: t color;\\n\\t\\t\\tcopyBits].\\n\\n\\t\\\"display tmpForm\\\"\\n\\taCanvas paintImage: tmpForm at: bounds origin.\\n\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'geometry' stamp: 'jm 2/7/2001 13:31'!\\nextent: aPoint\\n\\t\\\"Do nothing; my extent is determined by my StarSqueak world dimensions and pixelsPerPatch.\\\"\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tdimensions := self starSqueakDimensions. \\\"dimensions of this StarSqueak world in patches\\\"\\n\\tpixelsPerPatch := 2.\\n\\tsuper extent: dimensions * pixelsPerPatch.\\n\\tself evaporationRate: 6.\\n\\tself diffusionRate: 1.\\n\\tself clearAll. \\\"be sure this is done once in case setup fails to do it\\\"\\n\\tself setup.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'start' translated action: #startRunning.\\n\\taCustomMenu add: 'stop' translated action: #stopRunning.\\n\\taCustomMenu add: 'step' translated action: #singleStep.\\n\\taCustomMenu add: 'start over' translated action: #startOver.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'full speed' translated action: #fullSpeed.\\n\\taCustomMenu add: 'slow speed' translated action: #slowSpeed.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'set scale' translated action: #setScale.\\n\\taCustomMenu add: 'make parameter slider' translated action: #makeParameterSlider.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nfullSpeed\\n\\t\\\"Run at maximum speed.\\\"\\n\\n\\tstepTime := 0.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'dgd 2/21/2003 22:53'!\\nmakeParameterSlider\\n\\t| menu choice s |\\n\\tmenu := CustomMenu new title: 'Parameter?'.\\n\\tself sliderParameters do: [:rec | menu add: rec first action: rec].\\n\\tchoice := menu startUp.\\n\\tchoice ifNil: [^self].\\n\\ts := self \\n\\t\\t\\t\\tnewSliderForParameter: choice first\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tmin: (choice second)\\n\\t\\t\\t\\tmax: (choice third)\\n\\t\\t\\t\\tdescription: (choice fourth).\\n\\tself world activeHand attachMorph: s! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nsetScale\\n\\n\\t| reply |\\n\\treply := FillInTheBlank\\n\\t\\trequest: 'Set the number of pixels per patch (a number between 1 and 10)?'\\n\\t\\t initialAnswer: pixelsPerPatch printString.\\n\\treply isEmpty ifTrue: [^ self].\\n\\tpixelsPerPatch := ((reply asNumber rounded) max: 1) min: 10.\\n\\tself changed.\\n\\tsuper extent: dimensions * pixelsPerPatch.\\n\\tself clearAll. \\\"be sure this is done once in case setup fails to do it\\\"\\n\\tself setup.\\n\\tself startOver.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/5/2001 17:52'!\\nsingleStep\\n\\t\\\"Take one step and redisplay.\\\"\\n\\n\\tself oneStep.\\n\\tself changed.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/7/2001 19:07'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ #((evaporationRate 0 40\\n\\t\\t\\t'The rate at which chemicals evaporate in this world. Larger numbers give faster evaporation.')\\n\\t\\t(diffusionRate 0 5\\n\\t\\t\\t'The rate of chemical diffusion. Larger numbers give quicker diffusion.'))\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nslowSpeed\\n\\t\\\"Run at slow speed.\\\"\\n\\n\\tstepTime := 250.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/6/2001 22:04'!\\nstartOver\\n\\t\\\"Restart this StarSqueak simulation from its initial conditions.\\\"\\n\\n\\tself clearAll.\\n\\tself setup.\\n\\tself changed.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nstartRunning\\n\\t\\\"Start running this StarSqueak simulation.\\\"\\n\\n\\trunning := true.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nstopRunning\\n\\t\\\"STop running this StarSqueak simulation.\\\"\\n\\n\\trunning := false.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'parts bin' stamp: 'sw 7/13/2001 22:22'!\\ninitializeToStandAlone\\n\\tself initialize.\\n\\tself startRunning! !\\n\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'jm 3/8/2001 13:47'!\\nclearPatches\\n\\t\\\"Clear patch colors, including turtle trails.\\\"\\n\\n\\tpatchForm fill: patchForm boundingBox fillColor: Color black.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'jm 1/22/2001 16:52'!\\ncreatePatchVariable: patchVarName\\n\\t\\\"Create a patch variable of the given name. It is initialized to a value of zero for every patch.\\\"\\n\\n\\tpatchVariables\\n\\t\\tat: patchVarName\\n\\t\\tput: (Bitmap new: (dimensions x * dimensions y) withAll: 0).\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\ndecayPatchVariable: patchVarName\\n\\t\\\"Decay the values of the patch variable of the given name. That is, the value of each patch is replaced by a fraction of its former value, resulting in an expontial decay each patch's value over time. This can be used to model evaporation of a pheromone.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tself primEvaporate: patchVar rate: scaledEvaporationRate.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\ndiffusePatchVariable: patchVarName\\n\\t\\\"Diffuse the patch variable of the given name.\\\"\\n\\n\\t| v newV |\\n\\tdiffusionRate = 0 ifTrue: [^ self]. \\\"no diffusion\\\"\\n\\tv := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tnewV := Bitmap new: v size.\\n\\tself primDiffuseFrom: v\\n\\t\\tto: newV\\n\\t\\twidth: dimensions x\\n\\t\\theight: dimensions y\\n\\t\\tdelta: diffusionRate truncated.\\n\\tpatchVariables at: patchVarName put: newV.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\npatchesDo: aBlock\\n\\t\\\"Evaluate the given block for every patch in this world.\\\"\\n\\n\\t| patch |\\n\\tpatch := StarSqueakPatch new world: self.\\n\\t0 to: dimensions y - 1 do: [:y |\\n\\t\\tpatch y: y.\\n\\t\\t0 to: dimensions x - 1 do: [:x |\\n\\t\\t\\tpatch x: x.\\n\\t\\t\\taBlock value: patch]].\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\naddTurtleDemon: aSelector\\n\\t\\\"Add the given selector to the list of selectors sent to every turtle on every step.\\\"\\n\\n\\tturtleDemons := turtleDemons copyWith: aSelector.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\naddWorldDemon: aSelector\\n\\t\\\"Add the given selector to the list of selectors sent to the world on every step.\\\"\\n\\n\\tworldDemons := worldDemons copyWith: aSelector.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nclearAll\\n\\t\\\"Reset this StarSqueak world. All patch variables are cleared, all turtles are removed, and all demons are turned off.\\\"\\n\\n\\tpatchVariables := Dictionary new: 10.\\n\\tpatchVariableToDisplay := nil.\\n\\tlogPatchVariableScale := 0.\\n\\tpatchForm := Form extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tself createPatchFormGetterAndSetter.\\n\\tpatchVarDisplayForm := nil.\\n\\tself clearPatches.\\n\\tturtles := #().\\n\\tturtleDemons := #().\\n\\tworldDemons := #().\\n\\tsniffRange := 1.\\n\\tlastTurtleID := -1.\\n\\tgeneration := 0.\\n\\trunning := false.\\n\\tstepTime := 0. \\\"full speed\\\"\\n\\tturtlesAtPatchCache := nil.\\n\\tturtlesAtPatchCacheValid := false.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 1/24/2001 12:42'!\\ndisplayPatchVariable: patchVarName\\n\\t\\\"Make this StarSqueak world display the patch variable of the given name. Only one patch variable can be displayed at any given time.\\\"\\n\\n\\tself displayPatchVariable: patchVarName logScale: -2.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\ndisplayPatchVariable: patchVarName logScale: logBase2OfScaleFactor\\n\\t\\\"Make this StarSqueak world display the patch variable of the given name. Only one patch variable can be displayed at any given time. Values are scaled by 2^logBase2OfScaleFactor. For example, a value of 5 scales by 32 and a value of -2 scales by 1/4.\\\"\\n\\n\\t(patchVariables includesKey: patchVarName) ifFalse: [\\n\\t\\tpatchVariableToDisplay := nil.\\n\\t\\tpatchVarDisplayForm := nil.\\n\\t\\t^ self].\\n\\tpatchVariableToDisplay := patchVarName.\\n\\tpatchVarDisplayForm := Form extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tlogPatchVariableScale := logBase2OfScaleFactor.\\n\\tself clearPatches.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nrandom: range\\n\\t\\\"Answer a random integer between 0 and range.\\\"\\n\\n\\tRandomSeed := ((RandomSeed * 1309) + 13849) bitAnd: 65535.\\n\\t^ (RandomSeed * (range + 1)) // 65536\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 1/23/2001 07:24'!\\nsetup\\n\\t\\\"Subclasses should override this to setup the initial conditions of this StarSqueak world. The method should start with 'self clearAll'.\\\"\\n\\n\\tself clearAll.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 3/3/2001 12:54'!\\nstarSqueakDimensions\\n\\t\\\"Answer the dimensions of this StarSqueak simulation. Subclasses can override this method to define their own world size.\\\"\\n\\n\\t^ 100@100\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'stepping and presenter' stamp: 'dgd 2/21/2003 22:53'!\\noneStep\\n\\t\\\"Perform one step of the StarSqueak world. Execute all turtle and world demons.\\\"\\n\\n\\t\\\"run demons in random order and increment the generation counter\\\"\\n\\n\\t| currentTurtles |\\n\\tturtleDemons notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Note: Make a copy of turtles list that won't change if turtles are created/deleted.\\\"\\n\\n\\t\\t\\tcurrentTurtles := turtles copy.\\n\\t\\t\\tturtleDemons shuffled \\n\\t\\t\\t\\tdo: [:sel | 1 to: currentTurtles size do: [:i | (currentTurtles at: i) perform: sel]]].\\n\\tworldDemons shuffled do: [:sel | self perform: sel].\\n\\tgeneration := generation + 1.\\n\\tturtlesAtPatchCacheValid := false! !\\n\\n!StarSqueakMorph methodsFor: 'stepping and presenter' stamp: 'jm 1/26/2001 17:21'!\\nstep\\n\\n\\trunning ifTrue: [\\n\\t\\tself oneStep.\\n\\t\\tself changed].\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'testing' stamp: 'jm 1/22/2001 17:52'!\\nstepTime\\n\\n\\t^ stepTime\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 3/12/2001 09:44'!\\nmakeTurtles: count\\n\\t\\\"Create the given number of generic turtles.\\\"\\n\\n\\tself makeTurtles: count class: StarSqueakTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'sd 11/20/2005 21:26'!\\nmakeTurtles: count class: turtleClass\\n\\t\\\"Create the given number of turtles of the given turtle class.\\\"\\n\\n\\tturtles := turtles,\\n\\t\\t((1 to: count) collect: [:i |\\n\\t\\t\\tturtleClass new\\n\\t\\t\\t\\tinitializeWorld: self\\n\\t\\t\\t\\twho: (lastTurtleID := lastTurtleID + 1)]).\\n\\tself changed.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 1/28/2001 10:55'!\\nturtles\\n\\n\\t^ turtles\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'dgd 2/21/2003 22:53'!\\nturtlesAtX: x y: y do: aBlock \\n\\t\\\"Evaluate the given block for each turtle at the given location.\\\"\\n\\n\\t| t |\\n\\tt := self firstTurtleAtX: x y: y.\\n\\t[t isNil] whileFalse: \\n\\t\\t\\t[aBlock value: t.\\n\\t\\t\\tt := t nextTurtle]! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 3/3/2001 18:08'!\\nturtlesDo: aBlock\\n\\t\\\"Evaluate the given block for every turtle. For example:\\n\\t\\tw turtlesDo: [:t | t forward: 1]\\n\\twill tell every turtle to go forward by one turtle step.\\\"\\n\\n\\tturtles do: aBlock.\\n\\tself changed.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ncreatePatchFormGetterAndSetter\\n\\t\\\"Create BitBlt's for getting and setting patch colors.\\\"\\n\\n\\tpatchColorGetter := BitBlt bitPeekerFromForm: patchForm.\\n\\tpatchColorSetter :=\\n\\t\\t(BitBlt toForm: patchForm)\\n\\t\\t\\tcombinationRule: Form over;\\n\\t\\t\\tclipRect: patchForm boundingBox;\\n\\t\\t\\twidth: pixelsPerPatch;\\n\\t\\t\\theight: pixelsPerPatch.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ndeleteTurtle: aTurtle\\n\\t\\\"Delete the given turtle from this world.\\\"\\n\\n\\tturtles := turtles copyWithout: aTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 1/22/2001 16:58'!\\ndimensions\\n\\n\\t^ dimensions\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:32'!\\ndisplayPatchVariableOn: aForm color: aColor shift: shiftAmount \\n\\t\\\"Display patchVariableToDisplay in the given color. The opacity (alpha) of of each patch is determined by the patch variable value for that patch and shiftAmount. If shiftAmount is zero, the source value is unscaled. Positive shiftAmount values result in right shifting the source value by the given number of bits (That is, multiplying by 2^N. Negative values perform right shifts, dividing by 2^N).\\\"\\n\\n\\t| patchVar bitBlt w rowOffset alpha |\\n\\tpatchVariableToDisplay ifNil: [^self].\\n\\tpatchVar := patchVariables at: patchVariableToDisplay ifAbsent: [^self].\\n\\n\\t\\\"set up the BitBlt\\\"\\n\\tbitBlt := (BitBlt toForm: aForm)\\n\\t\\t\\t\\tsourceRect: (0 @ 0 extent: pixelsPerPatch);\\n\\t\\t\\t\\tfillColor: aColor;\\n\\t\\t\\t\\tcombinationRule: 30.\\n\\tw := dimensions x.\\n\\t0 to: dimensions y - 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\trowOffset := y * w + 1.\\n\\t\\t\\t0 to: w - 1\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\talpha := (patchVar at: rowOffset + x) bitShift: shiftAmount.\\n\\t\\t\\t\\t\\talpha := alpha min: 255.\\n\\t\\t\\t\\t\\talpha > 1 \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"if not transparent, fill using the given alpha\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tbitBlt destOrigin: (x * pixelsPerPatch) @ (y * pixelsPerPatch).\\n\\t\\t\\t\\t\\t\\t\\tbitBlt copyBitsTranslucent: alpha]]]! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nfirstTurtleAtX: xPos y: yPos \\n\\n\\t| w t x y index |\\n\\t\\\"create turtlesAtPatchCache if necessary\\\"\\n\\tturtlesAtPatchCache ifNil: [\\n\\t\\tturtlesAtPatchCache := Array new: (dimensions x * dimensions y) withAll: nil.\\n\\t\\tturtlesAtPatchCacheValid := false].\\n\\n\\tw := dimensions y.\\n\\tturtlesAtPatchCacheValid ifFalse: [\\n\\t\\tturtlesAtPatchCache atAllPut: nil.\\n\\t\\t\\\"cache not yet computed for this step; make linked list of turtles for each patch\\\"\\n\\t\\t1 to: turtles size do: [:i |\\n\\t\\t\\tt := turtles at: i.\\n\\t\\t\\tx := t x truncated.\\n\\t\\t\\ty := t y truncated.\\n\\t\\t\\tindex := (w * y) + x + 1.\\n\\t\\t\\tt nextTurtle: (turtlesAtPatchCache at: index).\\n\\t\\t\\tturtlesAtPatchCache at: index put: t].\\n\\t\\tturtlesAtPatchCacheValid := true].\\n\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\tindex := (w * y) + x + 1.\\n\\t^ turtlesAtPatchCache at: index\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchBrightnessAtX: x y: y\\n\\t\\\"Answer the brightness of the patch at the given location, a number from 0 to 100.\\\"\\n\\n\\t| c |\\n\\tc := self getPatchColorAtX: x y: y.\\n\\t^ (c brightness * 100.0) rounded\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchColorAtX: x y: y\\n\\t\\\"Answer the color of the patch at the given location.\\\"\\n\\n\\t| pixel |\\n\\tpixel := patchColorGetter pixelAt:\\n\\t\\t(pixelsPerPatch * x truncated)@(pixelsPerPatch * y truncated).\\n\\t^ Color colorFromPixelValue: pixel depth: patchForm depth\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchVariable: patchVarName atX: xPos y: yPos\\n\\t\\\"Answer the value of the given patch variable at the given turtle. Answer zero if the turtle is out of bounds.\\\"\\n\\n\\t| x y i |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ 0].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ 0].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\t^ (patchVariables at: patchVarName ifAbsent: [^ 0]) at: i\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nincrementPatchVariable: patchVarName atX: xPos y: yPos by: amount\\n\\t\\\"Increment the value of the given patch variable at the given location by the given amount. Do nothing if the location is out of bounds.\\\"\\n\\n\\t| x y i var |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ self].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ self].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\tvar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tvar at: i put: ((var at: i) + amount).\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nnewSliderForParameter: parameter target: target min: min max: max description: description\\n\\n\\t| c slider r s |\\n\\tc := (AlignmentMorph newColumn)\\n\\t\\tcolor: Color lightBlue;\\n\\t\\tborderWidth: 2;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tuseRoundedCorners.\\n\\tslider := SimpleSliderMorph new\\n\\t\\tcolor: (Color r: 0.065 g: 0.548 b: 0.645);\\n\\t\\textent: 150@2;\\n\\t\\ttarget: target;\\n\\t\\tactionSelector: (parameter, ':') asSymbol;\\n\\t\\tminVal: min;\\n\\t\\tmaxVal: max;\\n\\t\\tadjustToValue: (target perform: parameter asSymbol).\\n\\tc addMorphBack: slider.\\n\\tr := (AlignmentMorph newRow)\\n\\t\\tcolor: Color lightBlue;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill.\\n\\ts := StringMorph new contents: parameter, ': '.\\n\\tr addMorphBack: s.\\n\\ts := UpdatingStringMorph new\\n\\t\\ttarget: target;\\n\\t\\tgetSelector: parameter asSymbol;\\n\\t\\tputSelector: (parameter, ':') asSymbol;\\n\\t\\tfloatPrecision: (10.0 raisedTo: (((max - min) / 150.0) log: 10) floor);\\n\\t\\tstep.\\n\\tr addMorphBack: s.\\n\\tc addMorphBack: r.\\n\\tc setBalloonText: description.\\n\\t^ c\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 1/18/2001 21:58'!\\npatchVariable: patchVarName ifAbsent: aBlock\\n\\t\\\"Answer the patch variable array of the given name. If no such patch variables exists, answer the result of evaluating the given block.\\\"\\n\\n\\t^ patchVariables at: patchVarName ifAbsent: aBlock\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nreplicateTurtle: aTurtle\\n\\t\\\"Create an exact copy of the given turtle and add it to this world.\\\"\\n\\n\\t| newTurtle |\\n\\tnewTurtle := aTurtle clone who: (lastTurtleID := lastTurtleID + 1).\\n\\tturtles := turtles copyWith: newTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:34'!\\nsetPatchBrightnessAtX: x y: y to: percent \\n\\t\\\"Set the brightness of the patch at the given location to the given level, where 0 is black and 100 is full brightness.\\\"\\n\\n\\t| c brightness |\\n\\tc := self getPatchColorAtX: x y: y.\\n\\tbrightness := percent / 100.0.\\n\\tbrightness := brightness max: 0.03125.\\n\\tself \\n\\t\\tsetPatchColorAtX: x\\n\\t\\ty: y\\n\\t\\tto: (Color \\n\\t\\t\\t\\th: c hue\\n\\t\\t\\t\\ts: c saturation\\n\\t\\t\\t\\tv: brightness)! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 2/7/2001 07:20'!\\nsetPatchColorAtX: x y: y to: aColor\\n\\t\\\"Paint the patch at the given location with the given color.\\\"\\n\\n\\tpatchColorSetter\\n\\t\\tfillColor: aColor;\\n\\t\\tdestX: (pixelsPerPatch * x truncated);\\n\\t\\tdestY: (pixelsPerPatch * y truncated);\\n\\t\\tcopyBits.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nsetPatchVariable: patchVarName atX: xPos y: yPos to: newValue\\n\\t\\\"Set the value of the given patch variable below the given turtle to the given value. Do nothing if the turtle is out of bounds.\\\"\\n\\n\\t| x y i var |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ self].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ self].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\tvar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tvar at: i put: newValue.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nsumPatchVariable: patchVarName neighborsAtX: xPos y: yPos\\n\\t\\\"Answer the sum of the given patch variable for the eight neighbors of the patch at the given location. Answer zero if the location is out of bounds.\\\"\\n\\n\\t| patchVar x y w h xLeft xRight rowOffset sum |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^ 0].\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\tw := dimensions x.\\n\\th := dimensions y.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ 0].\\n\\t((x >= w) or: [y >= h]) ifTrue: [^ 0].\\n\\txLeft := (x - 1) \\\\\\\\ w. \\\"column before x, wrapped\\\"\\n\\txRight := (x + 1) \\\\\\\\ w. \\\"column after x, wrapped\\\"\\n\\trowOffset := y * w.\\n\\tsum :=\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\trowOffset := ((y - 1) \\\\\\\\ h) * w. \\\"row above y, wrapped\\\"\\n\\tsum := sum +\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + x) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\trowOffset := ((y + 1) \\\\\\\\ h) * w. \\\"row below y, wrapped\\\"\\n\\tsum := sum +\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + x) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\t^ sum\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:36'!\\nuphillOf: patchVarName forTurtle: aTurtle \\n\\t\\\"Answer the heading the points in the direction of increasing value for the given patch variable. If there is no gradient, or if the turtle is outside the world bounds, answer the turtles current heading.\\\"\\n\\n\\t| patchVar turtleX turtleY startX endX startY endY maxVal rowOffset thisVal maxValX maxValY |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^aTurtle heading].\\n\\tturtleX := aTurtle x truncated + 1.\\n\\tturtleY := aTurtle y truncated + 1.\\n\\tturtleX := turtleX max: 1.\\n\\tturtleY := turtleY max: 1.\\n\\tturtleX := turtleX min: dimensions x.\\n\\tturtleY := turtleY min: dimensions y.\\n\\tstartX := turtleX - sniffRange max: 1.\\n\\tendX := turtleX + sniffRange min: dimensions x.\\n\\tstartY := turtleY - sniffRange max: 1.\\n\\tendY := turtleY + sniffRange min: dimensions y.\\n\\tmaxVal := patchVar at: (turtleY - 1) * dimensions x + turtleX.\\n\\tmaxValX := nil.\\n\\tstartY to: endY\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\trowOffset := (y - 1) * dimensions x.\\n\\t\\t\\tstartX to: endX\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tthisVal := patchVar at: rowOffset + x.\\n\\t\\t\\t\\t\\tthisVal > maxVal \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[maxValX := x.\\n\\t\\t\\t\\t\\t\\t\\tmaxValY := y.\\n\\t\\t\\t\\t\\t\\t\\tmaxVal := thisVal]]].\\n\\tnil = maxValX ifTrue: [^aTurtle heading].\\n\\t^(((maxValX - turtleX) @ (maxValY - turtleY)) degrees + 90.0) \\\\\\\\ 360.0! !\\n\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'jdl 3/28/2003 09:46'!\\nprimDiffuseFrom: srcBitmap to: dstBitmap width: width height: height delta: delta \\n\\t\\\"Diffuse the integer values of the source patch variable Bitmap into the output Bitmap. Each cell of the output is the average of the NxN area around it in the source, where N = (2 * delta) + 1.\\\"\\n\\n\\t| area startY endY startX endX sum rowStart |\\n\\t<primitive: 'primitiveDiffuseFromToWidthHeightDelta' module: 'StarSqueakPlugin'>\\n\\tarea := (2 * delta + 1) * (2 * delta + 1).\\n\\t1 to: height\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\tstartY := y - delta.\\n\\t\\t\\tstartY := startY max: 1.\\n\\t\\t\\tendY := y + delta.\\n\\t\\t\\tendY := endY min: height.\\n\\t\\t\\t1 to: width\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tstartX := x - delta.\\n\\t\\t\\t\\t\\tstartX := startX max: 1.\\n\\t\\t\\t\\t\\tendX := x + delta.\\n\\t\\t\\t\\t\\tendX := endX min: width.\\n\\t\\t\\t\\t\\tsum := 0.\\n\\t\\t\\t\\t\\tstartY to: endY\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:y2 | \\n\\t\\t\\t\\t\\t\\t\\trowStart := (y2 - 1) * width.\\n\\t\\t\\t\\t\\t\\t\\tstartX to: endX do: [:x2 | sum := sum + (srcBitmap at: rowStart + x2)]].\\n\\t\\t\\t\\t\\tdstBitmap at: (y - 1) * width + x put: sum // area]]! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'jm 3/12/2001 09:45'!\\nprimEvaporate: aBitmap rate: rate\\n\\t\\\"Evaporate the integer values of the source Bitmap at the given rate, an integer between 0 and 1024, where 1024 is a scale factor of 1.0 (i.e., no evaporation). That is, replace each integer element v with (rate * v) / 1024.\\\"\\n\\n\\t<primitive: 'primitiveEvaporateRate' module: 'StarSqueakPlugin'>\\n\\t1 to: aBitmap size do: [:i |\\n\\t\\taBitmap at: i put: (((aBitmap at: i) * rate) bitShift: -10)].\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\nprimMapFrom: srcBitmap to: dstBitmap width: w height: h patchSize: patchSize rgbFlags: rgbFlags shift: shiftAmount \\n\\t\\\"Map values in the source bitmap (interpreted as unsigned 32-bit integers) to 2x2 patches of color in the destination bitmap. The color brightness level is determined by the source value and the color hue is determined by the bottom three bits of the rgbFlags value. For example, if rgbFlags is 1, you get shades of blue, if it is 6 you get shades of yellow, and if it is 7, you get shades of gray. The shiftAmount is used to scale the source data values by a power of two. If shiftAmount is zero, the data is unscaled. Positive shiftAmount values result in right shifting the source data by the given number of bits (multiplying by 2^N, negative values perform right shifts (dividing by 2^N). The width parameter gives the width of the Form that owns the destination bitmap.\\\"\\n\\n\\t| rgbMult srcIndex level pixel offset |\\n\\t<primitive: 'primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift' module: 'StarSqueakPlugin'>\\n\\trgbMult := 0.\\n\\t(rgbFlags bitAnd: 4) > 0 ifTrue: [rgbMult := rgbMult + 65536].\\n\\t(rgbFlags bitAnd: 2) > 0 ifTrue: [rgbMult := rgbMult + 256].\\n\\t(rgbFlags bitAnd: 1) > 0 ifTrue: [rgbMult := rgbMult + 1].\\n\\tsrcIndex := 0.\\n\\t0 to: h // patchSize - 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\t0 to: w // patchSize - 1\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tlevel := (srcBitmap at: (srcIndex := srcIndex + 1)) bitShift: shiftAmount.\\n\\t\\t\\t\\t\\tlevel := level min: 255.\\n\\t\\t\\t\\t\\tpixel := level <= 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"non-transparent black\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t1]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [level * rgbMult].\\n\\n\\t\\t\\t\\t\\t\\\"fill a patchSize x patchSize square with the pixel value\\\"\\n\\t\\t\\t\\t\\toffset := (y * w + x) * patchSize.\\n\\t\\t\\t\\t\\toffset to: offset + ((patchSize - 1) * w)\\n\\t\\t\\t\\t\\t\\tby: w\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:rowStart | \\n\\t\\t\\t\\t\\t\\t\\trowStart + 1 to: rowStart + patchSize\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:dstIndex | dstBitmap at: dstIndex put: pixel]]]]! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\ntestDiffusePrim\\n\\t\\\"This test should diffuse the initial value in the center cell so that each cell has 1000.\\\"\\n\\t\\\"StarSqueakMorph new testDiffusePrim\\\"\\n\\n\\t| src dst |\\n\\tsrc := Bitmap new: 49.\\n\\tsrc at: 25 put: 49000.\\n\\tdst := Bitmap new: 49.\\n\\tself primDiffuseFrom: src to: dst width: 7 height: 7 delta: 3.\\n\\t^ dst asArray\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\ntestEvaporatePrim\\n\\t\\\"This test should result in reducing each element of the array to 75% of its initial value.\\\"\\n\\t\\\"StarSqueakMorph new testEvaporatePrim\\\"\\n\\n\\t| data |\\n\\tdata := Bitmap new: 10.\\n\\t1 to: data size do: [:i | data at: i put: (10000 * i)].\\n\\tself primEvaporate: data rate: (75 * 1024) // 100.\\n\\t^ data asArray\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakMorph class methodsFor: 'class initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\t\\\"StarSqueakMorph initialize\\\"\\n\\n\\tRandomSeed := 17.\\n! !\\nObject subclass: #StarSqueakPatch\\n\\tinstanceVariableNames: 'world worldWidth worldHeight x y'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakPatch commentStamp: '<historical>' prior: 0!\\nI represent a patch in a StarSqueak world. Patch objects are not retained, but are created as needed, such as in patchesDo:.\\n!\\n\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/27/2001 08:59'!\\nasPoint\\n\\n\\t^ x @ y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/19/2001 08:28'!\\nworld\\n\\n\\t^ world\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nworld: aStarSqueakMorph\\n\\t\\\"Set the world for this patch. Also record the world's width and height.\\\"\\n\\n\\t| dims |\\n\\tworld := aStarSqueakMorph.\\n\\tdims := world dimensions.\\n\\tworldWidth := dims x.\\n\\tworldHeight := dims y.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/18/2001 21:27'!\\nx\\n\\n\\t^ x\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nx: anInteger\\n\\n\\tx := anInteger.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/18/2001 21:27'!\\ny\\n\\n\\t^ y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ny: anInteger\\n\\n\\ty := anInteger.\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisBottomEdge\\n\\n\\t^ y = (worldHeight - 1)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisLeftEdge\\n\\n\\t^ x = 0\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisRightEdge\\n\\n\\t^ x = (worldWidth - 1)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisTopEdge\\n\\n\\t^ y = 0\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone x: ((x + 1) \\\\\\\\ worldWidth)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborN\\n\\t\\\"Answer the neightboring patch directly north of (above) this patch.\\\"\\n\\n\\t^ self clone y: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborNE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x + 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborNW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x - 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborS\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone y: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborSE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x + 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:04'!\\nneighborSW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x - 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone x: ((x - 1) \\\\\\\\ worldWidth)\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:57'!\\nbrightness\\n\\t\\\"Answer the brightness of this patch, a number from 0 to 100.\\\"\\n\\n\\t^ world getPatchBrightnessAtX: x y: y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:56'!\\nbrightness: percent\\n\\t\\\"Set the brightness of this patch to the given level, where 0 is nearly black and 100 is full brightness.\\\"\\n\\n\\tworld setPatchBrightnessAtX: x y: y to: percent.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:58'!\\ncolor\\n\\t\\\"Answer the color of this patch.\\\"\\n\\n\\t^ world getPatchColorAtX: x y: y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:58'!\\ncolor: aColor\\n\\t\\\"Paint this patch the given color.\\\"\\n\\n\\tworld setPatchColorAtX: x y: y to: aColor.\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'jm 1/18/2001 21:31'!\\ndistanceTo: aPoint\\n\\t\\\"Answer the distance from this patch to the given point.\\\"\\n\\n\\t^ ((x - aPoint x) squared + (y - aPoint y) squared) sqrt\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'sd 11/20/2005 21:26'!\\nget: patchVarName\\n\\t\\\"Answer the value of the given patch variable for this patch.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := world patchVariable: patchVarName ifAbsent: [^ 0].\\n\\t^ patchVar at: (y * world dimensions x) + x + 1\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'sd 11/20/2005 21:26'!\\nset: patchVarName to: newValue\\n\\t\\\"Set the value of the given patch variable for this patch to the given value.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := world patchVariable: patchVarName ifAbsent: [^ self].\\n\\tpatchVar at: (y * world dimensions x) + x + 1 put: newValue.\\n! !\\nStarSqueakMorph subclass: #StarSqueakSlimeMold\\n\\tinstanceVariableNames: 'cellCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakSlimeMold methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tcellCount := 200.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'menu' stamp: 'jm 2/7/2001 19:51'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(cellCount 50 2000 'The number of slime mold cells.'))\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'other' stamp: 'jm 1/19/2001 18:36'!\\ndiffusePheromone\\n\\n\\tself diffusePatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakSlimeMold methodsFor: 'other' stamp: 'jm 1/19/2001 18:36'!\\nevaporatePheromone\\n\\n\\tself decayPatchVariable: 'pheromone'.\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'parameters' stamp: 'jm 2/7/2001 19:28'!\\ncellCount\\n\\n\\t^ cellCount\\n! !\\n\\n!StarSqueakSlimeMold methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ncellCount: aNumber\\n\\n\\tcellCount := aNumber asInteger.\\n\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself makeTurtles: cellCount class: SlimeMoldTurtle.\\n\\tself createPatchVariable: 'pheromone'. \\\"emitted by slime mold cells\\\"\\n\\tturtleDemons := #(dropPheromone followPheromone breakLoose).\\n\\tworldDemons := #(evaporatePheromone diffusePheromone).\\n\\tself displayPatchVariable: 'pheromone'.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakSlimeMold class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakSlimeMold class methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:36'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName:\\t'SlimeMold'\\n\\t\\tcategories:\\t\\t#('StarSqueak')\\n\\t\\tdocumentation:\\t'A slime-mold simulation using StarSqueak'\\n\\t\\tsampleImageForm: (Form\\n\\textent: 92@96\\n\\tdepth: 8\\n\\tfromArray: #( 673720360 676154664 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1398364499 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1396729208 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1294477352 674900008 673720360 673720360 673720360 673720360 673720360 673729869 1918072946 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 674900008 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 673720360 1296921202 1920103026 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1296902184 673720360 673720360 673720397 1296921239 2021169010 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296921202 1917668685 1296911656 673720360 673720360 673720397 1299346040 1701148786 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729832 673720360 673720360 673720360 673720360 673720360 673729869 1299355580 2543284850 1296911656 673720360 673720360 673720397 1296921276 2122234994 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920121883 3784808306 1296911656 673720360 673720360 673720397 1296921202 2543294322 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922530886 3787233138 1296911656 673720360 673720360 673720397 1296911730 1920103026 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1918442267 3784808306 1296911656 673720360 673720360 673720397 1296911693 1920093517 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299365052 3164041842 1296911656 673720360 673720360 673720397 1296911693 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296902184 673720360 673720360 673720360 673720360 673720397 1299346034 2540859981 1296911656 673720360 673720360 673720397 1296911693 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1294477352 673720360 673720360 673720360 673720397 1296911730 1920093517 1296911656 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 673720360 673720360 673720360 673720360 1296911693 1296911693 1296911656 673720360 673720360 676154701 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1299336525 1296911693 673720360 673720360 673720360 673720360 1296911693 1296911693 1296911656 673720360 673720360 1296911693 1296911693 1294477352 673720360 1179002920 673720360 673720360 673720360 673720360 673720360 673720360 1296911730 1920103026 1917668685 1296902184 673720360 673720360 673720360 676154701 1296911693 1296911656 673720360 673720397 1296911693 1179471181 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296921202 2543294359 1920093517 1296911693 1294477352 673720360 673720360 673729869 1296911693 1296911656 673720360 673720397 1296462450 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921177 1189199036 2540850509 1296911693 1296911656 673720360 673720360 673729869 1296911693 1296911693 673720360 673720397 1299346071 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921276 3779479228 2540859981 1296911693 1296911693 673720360 673720360 673729869 1296921202 1917668685 1294477352 673720397 1299334726 1179471181 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346108 1179050465 2543284850 1920103026 1917668685 1294477352 673720360 673729869 1299346034 1920093517 1294477352 673720397 1299346071 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921276 3779518908 2540860018 1920103001 1500663117 1294477352 673720360 673729869 1920112454 2540859981 1296902184 673720397 1296921202 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921239 3166485692 1920103026 1920104537 1501065805 1296902184 673720360 673729869 1922530886 2123854413 1296902184 673720360 1296911693 1296911656 673720360 673720360 975710248 673720360 673720360 673720360 673720360 673720360 673720397 1296921202 1920103026 1920093554 1920104549 1702392397 1296902184 673720360 673729869 1922530886 1503097421 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673721896 673720360 673720360 673720360 673720360 1296911693 1920103026 1296911693 1920103032 2020756813 1296902184 673720360 673729869 1920121945 2540859981 1294477352 673720360 673720360 673720360 673720360 774383656 673720360 673720360 673721896 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 1299346040 2020756813 1294477352 673720360 673729869 1299346034 1500663117 1294477352 673720360 673720360 673720360 673720360 774383656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1296911699 1397574989 1294477352 673720360 673729869 1296911693 877481293 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 774776872 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 1296911693 673720360 673720360 673720397 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 774776872 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296902184 673720360 673720360 673720397 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299346034 1920102989 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299355580 3164041842 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1922546845 2646382450 1296911656 673720360 673720360 673720360 674900008 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1924981019 454777202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920917787 454777202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920122044 3166466674 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920103001 1180267085 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1299346034 1920093517 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911730 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673724968 673720360 673720397 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 676154701 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1296902184 673720360 673720360 673720360 673720360 673720397 1296921202 1499024717 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296921239 2540850509 1294477352 673720360 673720360 673720360 673720360 675686440 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673729869 1296914758 1180257613 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296462450 1917668685 1294477352 673720360 673720360 673720360 673720360 673729869 1299346009 1500663117 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112535 2540850509 1294477352 673720360 673720360 673720360 673720360 676154701 1296921202 1920093517 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112454 2539205709 1294477352 673720360 673720360 673720360 673720360 676154701 1296921202 1917668685 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922516550 3161607501 1294477352 673720360 673720360 673720360 673720360 1296911693 1299345997 1296911693 1294477352 673720360 673720360 673720360 673720390 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299339609 2540850509 1294477352 673720360 673720360 673720360 673720360 1296911730 1920093517 1296911693 1294477352 673729832 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299346009 1917668685 1294477352 673720360 673720360 673720360 673720360 1296921202 1500672589 1296911693 673720397 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911705 1296911693 673720360 673720360 673720360 673720360 673720397 1296914839 1181905491 1397574989 673729869 1296911668 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 1296914802 1181896019 1397574952 676154701 1296921177 1917668685 1294477352 673720360 673720360 673720366 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 1296911730 1181896013 1296902184 673729869 1299346009 1397969741 1296902184 673720360 673720360 673720366 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674900008 673720360 673720360 676154701 877481293 1294477352 673729869 1296914777 1397969741 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674900008 673720360 673720360 673729869 1296911693 673720360 673720397 1296914802 1917668685 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911705 1296911693 1294477352 673729844 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154676 1296911656 673720360 673729844 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673729869 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674113576 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1294477352 673720360 673720360 673720360 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674113576 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1296902184 673724986 673720360 673720397 1296921202 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921202 1920103026 1296911656 673720360 673720360 673720397 1299355543 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346071 2543294322 1917668648 673720360 673720360 673720397 1299334726 1498238285 673720360 673720360 673720360 673720360 673720360 673720360 673720378 975710248 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1920112572 3789676988 1917668648 673720360 673720360 673720397 1299339609 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922546913 3779518908 1920093480 673720360 673720360 673720397 1296921202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922516705 3779468121 1499024717 673720360 673720360 673720360 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922546913 3779518908 1920093480 673720360 673720360 673720360 676154701 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112572 3789676988 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674904616 673720397 1299334726 2543294322 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346034 1920103026 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673724986 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911730 1920093517 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1294477352 673720360 673720360 673720360 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676148294 877471784 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 675686440 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911668 877013032 673720360 673720360 673720360 673720360 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911656 673720360 673720360 676154701 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1397968205 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1497387853 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1497387853 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1397968205 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911668 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720378 673720360 673720360 673720360 673720360 673720360 673720360 673721896 673720360 673720360 673720360)\\n\\toffset: 152@256)! !\\nStarSqueakMorph subclass: #StarSqueakTermites\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakTermites methodsFor: 'all' stamp: 'jm 1/24/2001 08:50'!\\nsetupPatches\\n\\t\\\"Create patch variables for sensing the nest and food caches. The nestScent variable is diffused so that it forms a 'hill' of scent over the entire world with its peak at the center of the nest. That way, the ants always know which way the nest is.\\\"\\n\\n\\tself createPatchVariable: 'woodChips'. \\\"number of wood chips on patch\\\"\\n\\tself displayPatchVariable: 'woodChips' logScale: 5.\\n\\tself patchesDo: [:p |\\n\\t\\t(self random: 8) = 0\\n\\t\\t\\tifTrue: [p set: 'woodChips' to: 1]\\n\\t\\t\\tifFalse: [p set: 'woodChips' to: 0]].\\n! !\\n\\n!StarSqueakTermites methodsFor: 'all' stamp: 'jm 1/28/2001 15:35'!\\nsetupTurtles\\n\\t\\\"Create an initialize my termites.\\\"\\n\\n\\tself makeTurtles: 400 class: TermiteTurtle.\\n\\tself turtlesDo: [:t | t isCarryingChip: false].\\n! !\\n\\n\\n!StarSqueakTermites methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself setupPatches.\\n\\tself setupTurtles.\\n\\tturtleDemons := #(walk wiggle lookForChip lookForPile).\\n! !\\nStarSqueakMorph subclass: #StarSqueakTrees\\n\\tinstanceVariableNames: 'depth treeTypeSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakTrees methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tdepth := 8.\\n\\ttreeTypeSelector := #tree1.\\n\\tself setup.\\n! !\\n\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'set tree depth' translated action: #setTreeDepth.\\n\\taCustomMenu add: 'set tree type' translated action: #setTreeType.\\n! !\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'rbb 3/1/2005 11:15'!\\nsetTreeDepth\\n\\n\\t| reply |\\n\\treply := UIManager default\\n\\t\\trequest: 'Tree depth (a number between 1 and 12)?'\\n\\t\\tinitialAnswer: depth printString.\\n\\treply isEmpty ifTrue: [^ self].\\n\\tdepth := ((reply asNumber rounded) max: 1) min: 12.\\n\\tself startOver.\\n! !\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nsetTreeType\\n\\n\\t| menu choice |\\n\\tmenu := CustomMenu new title: 'Choose tree type:'.\\n\\tmenu add: 'tree1' action: #tree1.\\n\\tmenu add: 'tree2' action: #tree2.\\n\\tchoice := menu startUp.\\n\\tchoice ifNotNil: [\\n\\t\\ttreeTypeSelector := choice.\\n\\t\\tself startOver].\\n! !\\n\\n\\n!StarSqueakTrees methodsFor: 'parts bin' stamp: 'sd 11/20/2005 21:26'!\\ninitializeToStandAlone\\n\\tself initialize.\\n\\ttreeTypeSelector := #tree2.\\n\\tself setup. \\\"Run earlier, but need to run again to get the #tree2 used\\\"\\n\\tself startRunning! !\\n\\n\\n!StarSqueakTrees methodsFor: 'setup' stamp: 'jm 3/12/2001 09:59'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself makeTurtles: 1 class: TreeTurtle.\\n\\tself turtlesDo: [:t |\\n\\t\\tt goto: 50@90.\\n\\t\\tt penDown.\\n\\t\\tt color: Color red.\\n\\t\\tt heading: 0.\\n\\t\\tt length: 15.\\n\\t\\tt depth: depth].\\n\\tself addTurtleDemon: treeTypeSelector.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakTrees class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakTrees class methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:37'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName:\\t'Trees'\\n\\t\\tcategories:\\t\\t#('StarSqueak')\\n\\t\\tdocumentation:\\t'A tree-growing simulation using StarSqueak'\\n\\t\\tsampleImageForm: (Form\\n\\textent: 70@72\\n\\tdepth: 8\\n\\tfromArray: #( 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 681453608 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 681453608 673720360 673720360 673720360 673710080 673720360 673720360 673720360 1313744936 2661165134 2655922216 673720360 676241054 673720360 673720360 673720360 673720360 2653431848 1311284776 673720398 673720360 673720360 673710080 673720360 673720360 673720398 1313744936 2661195342 1311254568 673720360 676241054 2653431848 673750686 2661174862 2653431848 2655931944 1318987816 673720398 681453608 673720360 673710080 673720360 673720360 673750686 1313754664 2661195342 1311254568 673750606 673750686 673720360 673750686 2655931982 1318987816 2655922254 2653462174 673720398 2653431848 673720360 673710080 673720360 673720360 681453646 1319018024 2653431966 1311254568 673750686 1311284894 673720360 673720478 2661174862 2661165096 2653441694 2661195422 673720398 673750568 673720360 673710080 673720360 673720360 2661195342 676220574 2653431886 1313775262 681483934 1311284776 2653441576 673720478 681463374 2653431848 3257421470 2653462174 1311264334 681453726 673720360 673710080 673720360 673720398 2661195342 673730206 2653431848 1318997662 2661174862 3262300712 2653462174 1311254722 683852402 673720514 683843230 2661195422 1311264334 2661195304 673720360 673710080 673720360 673720360 2661195342 1313754782 2661165096 1920093854 2653441614 3262300712 681483854 1313744936 3262300786 673720514 3257411662 2661195304 673730206 673720360 673720360 673710080 673720360 673720398 681483934 2661195422 2661165096 1319018142 2653462094 678609448 681463454 2655922216 3262280232 673759938 3257421470 3267504286 676220456 673750568 673720360 673710080 673720360 673730206 673750606 2655922370 673759902 2661174942 3257421352 678570024 683852366 673720360 3245437224 683786792 683831848 1915264670 1316123176 673750686 673720360 673710080 673720360 673720360 2661165134 678589122 673750686 3267514049 2663524392 678504488 683812904 673720360 683766056 683747368 3267543746 2661195304 3262261288 2661165214 1311254568 673710080 673720360 673720360 673750606 673739304 3265175118 2661174977 3267504168 678504488 3240634408 673720360 678504488 1898496449 673720433 3265175198 3267543746 2661195422 1311254568 673710080 673720360 673730206 673720398 673720514 3257411742 2663563969 683812904 673759681 3240634408 673720360 678504488 1908484136 673720433 1898487490 1915234344 673720360 673720360 673710080 673720360 676241054 673720434 3262261288 3257441832 673739458 683747368 673759528 673720360 673720360 678504561 1898457128 673720433 1908484136 673720360 2661165096 673720360 673710080 673720360 676220456 2661195304 1920084008 3250661416 673720513 3250661416 673759528 673720360 673720360 678504561 1898457128 673739121 1898457128 673720360 2661195422 673720360 673710080 673720360 673730206 2653432002 3267523112 673759528 673720360 3250661416 673759528 673720360 673720360 678523249 673720360 673739201 1898457128 673720360 2661195304 673720360 673710080 673720360 676154958 1311254642 1920103025 1898496296 673720360 3245428008 676163880 673720360 673720360 681341261 673720360 676163953 1294477352 673720397 1313754702 673720360 673710080 673720360 676154664 673720360 673729905 1903280461 673720360 3240653133 678504488 673720360 673720360 681332008 673720360 681341224 673720360 676164253 676220574 673720360 673710080 673720360 673720360 673720360 673720360 678523292 1294477352 3240653212 1299261480 673720360 673720360 1903241256 673720360 681332008 673720360 1302109554 1319018142 673720360 673710080 673720360 673720360 673720360 673720360 673720433 1903250728 3240643996 1903241256 673720360 673720360 3243059240 673720360 1900881960 673720433 1903250728 1313775262 673720360 673710080 673720360 673720360 673720360 673720360 673720360 1299280168 3240634445 1906059304 673720360 673720360 3223857192 673720433 1898457165 1903260097 1898457128 1917754958 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673739121 1903241256 1302079528 673720360 673720360 3223857192 673739121 1903260017 1903260017 1903260274 1917734440 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673729905 1908484136 678504488 673720360 673720360 3223857192 678543729 1903259981 673720360 1299280498 1917724712 1296902184 673710080 673720360 673720360 673720360 673720360 673720360 673720360 1908418600 678504488 673720360 673720360 3223857192 1287680369 673720360 673720360 673720360 1922977358 1313679400 673710080 673720360 673720360 673720360 673720360 673720360 673720360 678513704 678504488 673720360 673720360 3223857228 1903241256 673720360 673720360 673720360 676240974 1313679400 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673739084 678504488 673720360 673720433 1898466417 1277700136 673720360 673720360 673720360 673750606 1296902184 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673739163 1282484264 673720360 673720512 676098380 673720360 673720360 673720360 673720360 673730206 1294477352 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673729691 1903241256 673720360 673720512 1903250472 673720360 673720360 673720360 673720360 673720478 1294477352 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720396 1905993768 673720360 673720512 1900816424 673720360 673720360 673720360 673720360 673720398 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1285236776 673720360 673739200 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 678504488 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 678504488 673720360 673759272 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676098344 673720360 676098344 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673739121 673720360 678504488 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720512 673720360 1282484264 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720433 1898457128 1903241256 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 3223857192 1903241256 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 3223857228 1900816424 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1903241329 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 683681905 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 683681905 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673739121 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080)\\n\\toffset: 478@345)! !\\nObject subclass: #StarSqueakTurtle\\n\\tinstanceVariableNames: 'world who x y wrapX wrapY headingRadians color penDown nextTurtle'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakTurtle commentStamp: '<historical>' prior: 0!\\nI represent a \\\"creature\\\" that can move about on the surface of a StarSqueak world. I have a position and a heading (direction), and respond commands such as \\\"turnRight:\\\" and \\\"forward:\\\" by turning or moving. I also have an imaginary pen that can draw a trail as I move. In StarSqueak, turtles are born with random positions and headings.\\n\\nHere are some expressions to try in a workspace:\\n\\tw _ StarSqueakMorph new openInWorld.\\t\\\"make an empty world\\\"\\n\\tw makeTurtles: 100.\\t\\t\\t\\t\\t\\t\\\"create 100 turtles\\\"\\n\\tw turtlesDo: [:t | t forward: 1].\\t\\t\\t\\\"tell all turtles to take a step\\\"\\n\\tw turtlesDo: [:t | t goto: 50@50].\\t\\t\\t\\\"tell all turtles to go to 50@50\\\"\\n\\tw turtlesDo: [:t | t forward: 10].\\t\\t\\t\\\"tell all turtles to take 10 steps\\\"\\n\\nStructure:\\n world\\t\\t\\t\\tStarSqueakMorph\\t\\tthe world that owns this turtle\\n who\\t\\t\\t\\tinteger\\t\\t\\t\\t\\tunique id\\n x\\t\\t\\t\\t\\tnumber\\t\\t\\t\\t\\tx position in world\\n y\\t\\t\\t\\t\\tnumber\\t\\t\\t\\t\\ty position in world\\n wrapX\\t\\t\\t\\tfloat\\t\\t\\t\\t\\tprivate; used for wrapping in x\\n wrapY\\t\\t\\tfloat\\t\\t\\t\\t\\tprivate; used for wrapping in y\\n headingRadians\\tfloat\\t\\t\\t\\t\\theading in radians\\n color\\t\\t\\t\\tcolor\\t\\t\\t\\t\\tturtle color and its pen color\\n penDown\\t\\t\\tboolean\\t\\t\\t\\t\\ttrue if drawing a pen trail\\n nextTurtle\\t\\t\\tStarSqueaktTurtle\\t\\tprivate; used to make linked list of turtles\\n!\\n\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 1/27/2001 08:59'!\\nasPoint\\n\\n\\t^ x truncated @ y truncated\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:03'!\\ncolor\\n\\n\\t^ color\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ncolor: aColor\\n\\n\\tcolor := aColor.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nheading\\n\\t\\\"Answer my heading in degrees.\\\"\\n\\n\\t| degrees |\\n\\tdegrees := 90.0 - headingRadians radiansToDegrees.\\n\\t^ degrees >= 0.0 ifTrue: [degrees] ifFalse: [degrees + 360.0].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nheading: angleInDegrees\\n\\t\\\"Set my heading in degrees. Like a compass, up or north is 0 degrees and right or east is 90 degrees.\\\"\\n\\n\\theadingRadians := ((90.0 - angleInDegrees) \\\\\\\\ 360.0) degreesToRadians.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 3/3/2001 17:49'!\\nnextTurtle\\n\\t\\\"The nextTurtle slot is used to make a linked list of turtles at a given patch.\\\"\\n\\n\\t^ nextTurtle\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nnextTurtle: aStarSqueakTurtle\\n\\t\\\"The nextTurtle slot is used to make a linked list of turtles at a given patch.\\\"\\n\\n\\tnextTurtle := aStarSqueakTurtle.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 1/26/2001 17:36'!\\nwho\\n\\n\\t^ who\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nwho: anInteger\\n\\n\\twho := anInteger.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:02'!\\nx\\n\\n\\t^ x\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nx: aNumber\\n\\n\\tx := aNumber.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:02'!\\ny\\n\\n\\t^ y\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ny: aNumber\\n\\n\\ty := aNumber.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/26/2001 17:39'!\\ndie\\n\\t\\\"Delete this turtle at the end of the current cycle. The turtle will finish running all demons for the current cycle before it dies.\\\"\\n\\n\\tworld deleteTurtle: self.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/23/2001 17:26'!\\nforward: dist\\n\\t\\\"Move the given distance in the direction of my heading.\\\"\\n\\n\\t1 to: dist do: [:i | self forwardOne].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\nforwardOne\\n\\t\\\"Move one turtle step in the direction of my heading.\\\"\\n\\n\\tpenDown ifTrue: [world setPatchColorAtX: x y: y to: color].\\n\\tx := x + headingRadians cos.\\n\\ty := y - headingRadians sin.\\n\\tx < 0.0 ifTrue: [x := x + wrapX].\\n\\ty < 0.0 ifTrue: [y := y + wrapY].\\n\\tx >= wrapX ifTrue: [x := x - wrapX].\\n\\ty >= wrapY ifTrue: [y := y - wrapY].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\ngoto: aPoint\\n\\t\\\"Jump to the given location.\\\"\\n\\n\\tx := aPoint x.\\n\\ty := aPoint y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\npenDown\\n\\t\\\"Put down this turtle's pen. That is, the turtle will leave a trail the same color as itself when it moves.\\\"\\n\\n\\tpenDown := true.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\npenUp\\n\\t\\\"Lift this turtle's pen. The turtle will stop leaving a trail.\\\"\\n\\n\\tpenDown := false.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/19/2001 19:20'!\\nrandom: range\\n\\t\\\"Answer a random integer between 0 and range.\\\"\\n\\n\\t^ world random: range\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/27/2001 08:47'!\\nreplicate\\n\\t\\\"Add an exact replica of this turtle to the world. The new turtle does not become active until the next cycle.\\\"\\n\\t\\\"Note: We call this operation 'replicate' instead of Mitch Resnick's term 'clone' because Squeak already used the message 'clone' for cloning a generic object.\\\"\\n\\n\\tworld replicateTurtle: self.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/29/2001 10:11'!\\nstop\\n\\t\\\"Stop running.\\\"\\n\\n\\tworld stopRunning.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/19/2001 19:14'!\\nturnLeft: degrees\\n\\t\\\"Turn left by the given number of degrees.\\\"\\n\\n\\tself heading: (self heading - degrees).\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 2/27/2000 18:19'!\\nturnRight: degrees\\n\\t\\\"Turn right by the given number of degrees.\\\"\\n\\n\\tself heading: (self heading + degrees).\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\nturnTowards: aPointTurtleOrPatch\\n\\t\\\"Turn to face the given point, turtle, or patch.\\\"\\n\\n\\t| degrees |\\n\\tdegrees := (aPointTurtleOrPatch asPoint - self asPoint) degrees.\\n\\theadingRadians := (0.0 - degrees) degreesToRadians.\\n\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/27/2001 08:58'!\\nturnTowardsStrongest: patchVarName\\n\\t\\\"Turn to point toward the nearby patch having the highest value of the given patch variable. This command uses only local information. In particular, it only considers patches within 'sniffRange' of this turtles location. For example, with the default 'sniffRange' of 1, it only considers the immediate neighbors of the patch this turtle is on.\\\"\\n\\n\\tself heading: (world uphillOf: patchVarName forTurtle: self).\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitializeWorld: aStarSqueakWorld who: anInteger\\n\\n\\t| dims |\\n\\tdims := aStarSqueakWorld dimensions.\\n\\tworld := aStarSqueakWorld.\\n\\twho := anInteger.\\n\\tx := world random: dims x - 1.\\n\\ty := world random: dims y - 1.\\n\\twrapX := dims x asFloat.\\n\\twrapY := dims y asFloat.\\n\\theadingRadians := ((self random: 36000) / 100.0) degreesToRadians.\\n\\tcolor := Color blue.\\n\\tpenDown := false.\\n\\tnextTurtle := nil.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/19/2001 19:08'!\\nget: patchVar\\n\\t\\\"Answer the value of the given patch variable below this turtle.\\\"\\n\\n\\t^ world getPatchVariable: patchVar atX: x y: y\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/27/2001 08:49'!\\nincrement: patchVar by: delta\\n\\t\\\"Increment the value of the given patch variable below this turtle by the given amount (positive or negative).\\\"\\n\\n\\t world incrementPatchVariable: patchVar atX: x y: y by: delta.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'hh 8/26/2001 19:49'!\\npatchBrightness\\n\\t\\\"Answer the brightness of the patch below this turtle, where 0 is black and 100 is full brightness.\\\"\\n\\n\\t^world getPatchBrightnessAtX: x y: y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/24/2001 13:28'!\\npatchBrightness: percent\\n\\t\\\"Set the brightness of the patch below this turtle to the given value, where 0 is black and 100 is full brightness.\\\"\\n\\n\\tworld setPatchBrightnessAtX: x y: y to: percent.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/23/2001 17:17'!\\npatchColor\\n\\t\\\"Answer the color of the patch below this turtle.\\\"\\n\\n\\t^ world getPatchColorAtX: x y: y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/24/2001 13:37'!\\npatchColor: aColor\\n\\t\\\"Paint the patch below this turtle with the given color.\\\"\\n\\n\\tworld setPatchColorAtX: x y: y to: aColor.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/19/2001 19:09'!\\nset: patchVar to: newValue\\n\\t\\\"Set the value of the given patch variable below this turtle to the given value.\\\"\\n\\n\\t world setPatchVariable: patchVar atX: x y: y to: newValue.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'sensing' stamp: 'jm 2/5/2001 19:42'!\\ndistanceTo: aPoint\\n\\t\\\"Answer the distance from this turtle to the given point.\\\"\\n\\n\\t^ ((x - aPoint x) squared + (y - aPoint y) squared) sqrt\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'sensing' stamp: 'sd 11/20/2005 21:26'!\\nturtleCountHere\\n\\t\\\"Answer a collection of turtles at this turtle's current location, including this turtle itself.\\\"\\n\\n\\t| n |\\n\\tn := 0.\\n\\tworld turtlesAtX: x y: y do: [:t | n := n + 1].\\n\\t^ n\\n! !\\nChangeSetCategory subclass: #StaticChangeSetCategory\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Changes'!\\n!StaticChangeSetCategory commentStamp: '<historical>' prior: 0!\\nStaticChangeSetCategory is a user-defined change-set category that has in it only those change sets specifically placed there.!\\n\\n\\n!StaticChangeSetCategory methodsFor: 'add' stamp: 'sw 4/11/2001 15:58'!\\naddChangeSet: aChangeSet\\n\\t\\\"Add the change set manually\\\"\\n\\n\\tself elementAt: aChangeSet name put: aChangeSet! !\\n\\n\\n!StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:10'!\\nacceptsManualAdditions\\n\\t\\\"Answer whether the user is allowed manually to manipulate the contents of the change-set-category.\\\"\\n\\n\\t^ true! !\\n\\n!StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:00'!\\nincludesChangeSet: aChangeSet\\n\\t\\\"Answer whether the receiver includes aChangeSet in its retrieval list\\\"\\n\\n\\t^ elementDictionary includesKey: aChangeSet name! !\\n\\n\\n!StaticChangeSetCategory methodsFor: 'updating' stamp: 'sd 11/20/2005 21:27'!\\nreconstituteList\\n\\t\\\"Reformulate the list. Here, since we have a manually-maintained list, at this juncture we only make sure change-set-names are still up to date, and we purge moribund elements\\\"\\n\\n\\t| survivors |\\n\\tsurvivors := elementDictionary select: [:aChangeSet | aChangeSet isMoribund not].\\n\\tself clear.\\n\\t(survivors asSortedCollection: [:a :b | a name <= b name]) reverseDo:\\n\\t\\t[:aChangeSet | self addChangeSet: aChangeSet]! !\\nForm subclass: #StaticForm\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Display Objects'!\\n!StaticForm commentStamp: '<historical>' prior: 0!\\nAn optimization for Nebraska - a StaticForm does not change once created so it may be cached on the remote end.!\\n\\n\\n!StaticForm methodsFor: 'as yet unclassified' stamp: 'RAA 8/14/2000 09:59'!\\nisStatic\\n\\n\\t^true! !\\nMorphicAlarm subclass: #StepMessage\\n\\tinstanceVariableNames: 'stepTime'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!StepMessage methodsFor: 'accessing' stamp: 'ar 10/22/2000 16:56'!\\nstepTime: aNumber\\n\\t\\\"Set the step time for this message. If nil, the receiver of the message will be asked for its #stepTime.\\\"\\n\\tstepTime _ aNumber! !\\n\\n\\n!StepMessage methodsFor: 'printing' stamp: 'ar 10/22/2000 15:59'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream \\n\\t\\tnextPut: $(;\\n\\t\\tprint: receiver;\\n\\t\\tspace;\\n\\t\\tprint: selector;\\n\\t\\tspace;\\n\\t\\tprint: scheduledTime;\\n\\t\\tnextPut: $).! !\\n\\n\\n!StepMessage methodsFor: 'testing' stamp: 'ar 10/22/2000 16:56'!\\nstepTime\\n\\t\\\"Return the step time for this message. If nil, the receiver of the message will be asked for its #stepTime.\\\"\\n\\t^stepTime! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStepMessage class\\n\\tinstanceVariableNames: ''!\\n\\n!StepMessage class methodsFor: 'instance creation' stamp: 'ar 10/22/2000 15:48'!\\nscheduledAt: scheduledTime stepTime: stepTime receiver: aTarget selector: aSelector arguments: argArray\\n\\t^(self receiver: aTarget selector: aSelector arguments: argArray)\\n\\t\\tscheduledTime: scheduledTime;\\n\\t\\tstepTime: stepTime! !\\nRectangleMorph subclass: #StickyPadMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'Colors LastColorIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n!StickyPadMorph commentStamp: 'sw 3/3/2004 13:31' prior: 0!\\nA custom item for the Squeakland Supplies bin, as defined by Kim Rose and BJ Con.A parts bin will deliver up translucent, borderless Rectangles in a sequence of 6 colors. It offers some complication to the parts-bin protocols in two ways::\\n* The multi-colored icon seen in the parts bin is not a thumbnail of any actual instance, all of which are monochrome\\n* New instances need to be given default names that are not the same as the name seen in the parts bin.!\\n\\n\\n!StickyPadMorph methodsFor: 'visual properties' stamp: 'dgd 9/18/2004 18:52'!\\ncanHaveFillStyles\\n\\t\\\"Return true if the receiver can have general fill styles; not just \\n\\tcolors. This method is for gradually converting old morphs.\\\"\\n\\t^ true! !\\n\\n\\n!StickyPadMorph methodsFor: 'parts bin' stamp: 'sw 4/3/2003 15:25'!\\ninitializeToStandAlone\\n\\t\\\"Initialize the receiver to stand alone. Use the next color in the standard sequence.\\\"\\n\\n\\tColors ifNil: [self initialize].\\n\\tLastColorIndex _ \\n\\t\\tLastColorIndex\\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[1]\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[(LastColorIndex \\\\\\\\ Colors size) + 1].\\n\\tsuper initializeToStandAlone.\\n\\tself assureExternalName.\\n\\tself color: (Colors at: LastColorIndex).\\n\\tself extent: 100@80.\\n\\tself borderWidth: 0\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStickyPadMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StickyPadMorph class methodsFor: 'as yet unclassified' stamp: 'sw 3/3/2004 13:42'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\t\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StickyPadMorph\\t\\tnewStandAlone\\t\\t\\t'Sticky Pad'\\t\\t\\t'Each time you obtain one of these pastel, translucent, borderless rectangles, it will be a different color from the previous time.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.\\n\\t\\t\\t\\tcl registerQuad: #(StickyPadMorph\\t\\tnewStandAlone\\t\\t\\t'Sticky Pad'\\t\\t\\t'Each time you obtain one of these pastel, translucent, borderless rectangles, it will be a different color from the previous time.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.]! !\\n\\n\\n!StickyPadMorph class methodsFor: 'class initialization' stamp: 'sw 3/3/2004 13:44'!\\ninitialize\\n\\t\\\"Class initialization\\\"\\n\\n\\tLastColorIndex _ 0.\\n\\tColors _ {\\n\\t\\tTranslucentColor r: 0.0 g: 0.0 b: 0.839 alpha: 0.267.\\n\\t\\tTranslucentColor r: 0.484 g: 1.0 b: 0.452 alpha: 0.706.\\n\\t\\tTranslucentColor r: 1.0 g: 0.355 b: 0.71 alpha: 0.569.\\n\\t\\tTranslucentColor r: 1.0 g: 1.0 b: 0.03 alpha: 0.561.\\n\\t\\tTranslucentColor r: 0.484 g: 0.161 b: 1.0 alpha: 0.529.\\n\\t\\tTranslucentColor r: 0.097 g: 0.097 b: 0.097 alpha: 0.192.\\n\\t}.\\n\\t\\n\\tself registerInFlapsRegistry.\\t\\n\\n\\\"StickyPadMorph initialize\\\"! !\\n\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 4/3/2003 14:26'!\\ndefaultNameStemForInstances\\n\\t\\\"Answer the default name stem to use\\\"\\n\\n\\t^ 'tear off'! !\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 4/4/2003 11:12'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName: \\t'Sticky Pad'\\n\\t\\tcategories:\\t\\t#('Graphics')\\n\\t\\tdocumentation:\\t'A translucent, borderless rectangle of a standard size, delivered in a predictable sequence of pastel colors'\\n\\t\\tsampleImageForm: (Form extent: 50@40 depth: 16\\n\\tfromArray: #( 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1796762392 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1796762392 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1599692633 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1599692633 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1662149394 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1662149394 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1389318863 1389318863 1389318863 1460426508 1460426508 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521903284 1389318863 1389318863 1389317938 1460426508 1460426508 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1723098804 1389318863 1389318863 1328697138 1460426508 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521903284 1723098804 1389318863 1389317938 1328697138 1460426508 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1723098804 1723098804 1389318863 1328697138 1328697138 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521903284 1723098804 1723098804 1389317938 1328697138 1328697138 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1723098804 1723098804 1723098804 1328697138 1328697138 1328697138 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461414680 1723098804 1723098804 1723096921 1328697138 1328697138 1328702226 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1796762392 1723098804 1723098804 1599692633 1328697138 1328697138 1662149394 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461414680 1796762392 1723098804 1723096921 1599692633 1328697138 1328702226 1662149394 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1796762392 1796762392 1723098804 1599692633 1599692633 1328697138 1662149394 1662149394 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461414680 1796762392 1796762392 1723096921 1599692633 1599692633 1328702226 1662149394 1662149394 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741)\\n\\toffset: 0@0)! !\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 7/5/2004 18:09'!\\nlaunchPartVia: aSelector label: aString\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins. Overridden here so that all instances will be given the name, unlike the prevailing convention for other object types\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setNameTo: self defaultNameStemForInstances. \\\"i.e., circumvent uniqueness in this case\\\"\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\nSketchMorph subclass: #StickySketchMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Support'!\\n\\n!StickySketchMorph methodsFor: 'e-toy support' stamp: 'sw 4/16/1998 13:44'!\\nmustBeBackmost\\n\\t^ true! !\\n\\n\\n!StickySketchMorph methodsFor: 'halos and balloon help' stamp: 'sw 9/18/97 15:37'!\\nwantsHalo\\n\\t^ false! !\\n\\n\\n!StickySketchMorph methodsFor: 'thumbnail' stamp: 'sw 6/16/1999 11:32'!\\npermitsThumbnailing\\n\\t^ false! !\\nObject subclass: #Stopwatch\\n\\tinstanceVariableNames: 'timespans state'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Chronology'!\\n!Stopwatch commentStamp: '<historical>' prior: 0!\\nA Stopwatch maintains a collection of timespans.!\\n\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:12'!\\nactivate\\n\\n\\tself isSuspended ifTrue:\\n\\t\\t[self timespans add: \\n\\t\\t\\t(Timespan starting: DateAndTime now duration: Duration zero).\\n\\t\\tself state: #active]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:45'!\\nduration\\n\\n\\t| ts last |\\n\\tself isSuspended \\n\\t\\tifTrue:\\n\\t\\t\\t[ (ts _ self timespans) isEmpty ifTrue: \\n\\t\\t\\t\\t[ ts _ { Timespan starting: DateAndTime now duration: Duration zero } ] ]\\n\\t\\tifFalse:\\n\\t\\t\\t[ last _ self timespans last.\\n\\t\\t\\tts _ self timespans allButLast\\n\\t\\t\\t\\tadd: (last duration: (DateAndTime now - last start); yourself);\\n\\t\\t\\t\\tyourself ].\\n\\t\\t\\n\\t^ (ts collect: [ :t | t duration ]) sum\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:21'!\\nend\\n\\n\\t^ self timespans last next\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'!\\nisActive\\n\\n\\t^ self state = #active\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'!\\nisSuspended\\n\\n\\t^ self state = #suspended\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 13:25'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPut: $(;\\n\\t\\tnextPutAll: self state;\\n\\t\\tnextPut: $:;\\n\\t\\tprint: self duration;\\n\\t\\tnextPut: $).\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 12:03'!\\nreActivate\\n\\n\\tself \\n\\t\\tsuspend;\\n\\t\\tactivate.\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:54'!\\nreset\\n\\n\\tself suspend.\\n\\ttimespans _ nil.\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:18'!\\nstart\\n\\n\\t^ self timespans first start\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:47'!\\nstate\\n\\n\\t^ state ifNil: [ state _ #suspended ]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:46'!\\nstate: aSymbol\\n\\n\\tstate _ aSymbol\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:13'!\\nsuspend\\n\\n\\t| ts |\\n\\tself isActive ifTrue:\\n\\t\\t[ ts _ self timespans last.\\n\\t\\tts duration: (DateAndTime now - ts start).\\n\\t\\tself state: #suspended]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:44'!\\ntimespans\\n\\n\\t^ timespans ifNil: [ timespans _ OrderedCollection new ]\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStopwatch class\\n\\tinstanceVariableNames: ''!\\nClassTestCase subclass: #StopwatchTest\\n\\tinstanceVariableNames: 'aStopwatch aDelay'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Chronology'!\\n\\n!StopwatchTest methodsFor: 'Coverage' stamp: 'brp 9/24/2003 22:49'!\\nclassToBeTested\\n\\n\\t^ Stopwatch\\n\\n! !\\n\\n!StopwatchTest methodsFor: 'Coverage' stamp: 'brp 9/24/2003 23:01'!\\nselectorsToBeIgnored\\n\\n\\t| private | \\n\\tprivate := #( #printOn: #state: ).\\n\\n\\t^ super selectorsToBeIgnored, private\\n! !\\n\\n\\n!StopwatchTest methodsFor: 'running' stamp: 'brp 1/21/2004 18:49'!\\nsetUp\\n\\taStopwatch := Stopwatch new.\\n\\taDelay := Delay forMilliseconds: 1.! !\\n\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 11:45'!\\ntestActive\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw activate.\\n\\t\\n\\t1 seconds asDelay wait.\\n\\tself \\n\\t\\tassert: (sw duration >= 1 seconds).\\n\\n\\t2 seconds asDelay wait.\\n\\tself \\n\\t\\tassert: (sw duration >= 3 seconds).\\n\\n\\tsw suspend.! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/24/2003 22:56'!\\ntestNew\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\t\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tassert: (sw state = #suspended);\\n\\t\\tdeny: (sw isActive);\\n\\t\\tassert: (sw timespans isEmpty)\\n\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 12:02'!\\ntestReActivate\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw \\n\\t\\tactivate;\\n\\t\\tsuspend;\\n\\t\\treActivate.\\n\\t\\n\\tself \\n\\t\\tassert: (sw isActive).\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 11:56'!\\ntestReset\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw activate.\\n\\t\\n\\tsw reset.\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tassert: (sw timespans isEmpty)\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/26/2004 19:36'!\\ntestStartStop\\n\\n\\t| sw t1 t2 t3 t4 |\\n\\tsw := Stopwatch new.\\n\\tt1 := DateAndTime now.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tsw activate; activate.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt2 := DateAndTime now.\\n\\t\\n\\tself \\n\\t\\tdeny: (sw isSuspended);\\n\\t\\tassert: (sw isActive);\\n\\t\\tassert: (sw timespans size = 1);\\n\\t\\tassert: (t1 <= sw start);\\n\\t\\tassert: (sw start <= t2).\\n\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt3 := DateAndTime now.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tsw suspend; suspend.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt4 := DateAndTime now.\\n\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tdeny: (sw isActive);\\n\\t\\tassert: (sw timespans size = 1);\\n\\t\\tassert: (sw end between: t3 and: t4);\\n\\t\\tassert: (t3 <= sw end);\\n\\t\\tassert: (sw end <= t4).\\n! !\\n\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestChangingStatus\\n\\taStopwatch activate.\\n\\tself assert: aStopwatch isActive.\\n\\tself assert: aStopwatch timespans size = 1.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch isSuspended.\\n\\tself assert: aStopwatch timespans size = 1.\\n\\taStopwatch activate.\\n\\taStopwatch reActivate.\\n\\tself assert: aStopwatch isActive.\\n\\tself assert: aStopwatch timespans size = 3.\\n\\taStopwatch reset.\\n\\tself assert: aStopwatch isSuspended.\\n\\tself assert: aStopwatch timespans size = 0.! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestInitialStatus\\n\\tself assert: aStopwatch isSuspended.\\n\\tself deny: aStopwatch isActive.\\n\\tself assert: aStopwatch duration = 0 seconds! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 9/26/2004 19:32'!\\ntestMultipleTimings\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch timespans size = 2. \\n\\tself assert: aStopwatch timespans first asDateAndTime <= \\n\\t\\t\\t\\t\\taStopwatch timespans last asDateAndTime.\\n! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestPrintOn\\n\\t| cs rw |\\n\\tcs := ReadStream on: 'a Stopwatch(suspended:0:00:00:00)'.\\n\\trw := ReadWriteStream on: ''.\\n\\taStopwatch printOn: rw.\\n\\tself assert: rw contents = cs contents! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 9/26/2004 19:32'!\\ntestSingleTiming\\n\\t| timeBefore |\\n\\ttimeBefore := DateAndTime now.\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch timespans size = 1. \\n\\tself assert: aStopwatch timespans first asDateAndTime >= timeBefore. \\n\\tself assert: aStopwatch timespans first asDateAndTime <= aStopwatch end.\\n! !\\nPrintableEncoder subclass: #StoreEncoder\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Postscript Filters'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStoreEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!StoreEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 01:52'!\\nfilterSelector\\n ^#storeOnStream:.\\n! !\\nBookMorph subclass: #StoryboardBookMorph\\n\\tinstanceVariableNames: 'alansSliders panAndTiltFactor zoomFactor zoomController'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Books'!\\n!StoryboardBookMorph commentStamp: '<historical>' prior: 0!\\nA BookMorph variant whose pages are instances of ZoomAndScrollMorph. I have a control area where the user may pan, tilt and zoom over the image shown in the page.\\n\\n- drag up and down to zoom in and out\\n- drag left and right to pan\\n- shift-drag up and down to tilt.!\\n\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:37'!\\nchangeTiltFactor: x\\n\\n\\tcurrentPage changeTiltFactor: x.\\n\\tpanAndTiltFactor _ x.\\n\\n! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:37'!\\nchangeZoomFactor: x\\n\\n\\tcurrentPage changeZoomFactor: x.\\n\\tzoomFactor _ x.! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:38'!\\ngetTiltFactor\\n\\n\\t^panAndTiltFactor ifNil: [panAndTiltFactor _ 0.5].! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:38'!\\ngetZoomFactor\\n\\n\\t^zoomFactor ifNil: [zoomFactor _ 0.5]! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetX\\n\\n\\t^currentPage offsetX! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetX: aNumber\\n\\n\\tcurrentPage offsetX: aNumber! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetY\\n\\n\\t^currentPage offsetY! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetY: aNumber\\n\\n\\tcurrentPage offsetY: aNumber! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:35'!\\nscale\\n\\n\\t^currentPage scale! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:26'!\\nscale: aValue\\n\\n\\tcurrentPage scale: aValue! !\\n\\n\\n!StoryboardBookMorph methodsFor: 'initialization' stamp: 'RAA 12/1/2000 15:22'!\\ninitialize\\n\\n\\tnewPagePrototype _ ZoomAndScrollMorph new extent: Display extent // 3.\\n\\tzoomController _ ZoomAndScrollControllerMorph new\\n\\t\\t\\tsetBalloonText: 'Drag in here to zoom, tilt and pan the page above'.\\n\\n\\tsuper initialize.\\n\\n\\tself addMorphBack: zoomController.\\n\\n\\talansSliders _ {\\n\\t\\t{#changeTiltFactor: . #getTiltFactor . 'Pan and tilt sensitivity'}.\\n\\t\\t{#changeZoomFactor: . #getZoomFactor . 'Zoom sensitivity'}.\\n\\t} collect: [ :sData |\\n\\t\\t{\\n\\t\\t\\tSimpleSliderMorph new\\n\\t\\t\\t\\textent: 150@10;\\n\\t\\t\\t\\tcolor: Color orange;\\n\\t\\t\\t\\tsliderColor: Color gray;\\n\\t\\t\\t\\ttarget: self; \\n\\t\\t\\t\\tactionSelector: sData first;\\n\\t\\t\\t\\tsetBalloonText: sData third;\\n\\t\\t\\t\\tadjustToValue: (self perform: sData second).\\n\\t\\t\\tsData second\\n\\t\\t}\\n\\t].\\n\\talansSliders do: [ :each | self addMorphBack: each first]\\n! !\\n\\n\\n!StoryboardBookMorph methodsFor: 'navigation' stamp: 'sw 7/25/2003 16:47'!\\ninsertPageMorphInCorrectSpot: aPageMorph\\n\\t\\\"Insert the page morph at the correct spot\\\"\\n\\t\\n\\t| place |\\n\\tplace _ submorphs size > 1 ifTrue: [submorphs second] ifFalse: [submorphs first].\\n\\t\\\"Old architecture had a tiny spacer morph as the second morph; now architecture does not\\\"\\n\\tself addMorph: (currentPage _ aPageMorph) behind: place.\\n\\tself changeTiltFactor: self getTiltFactor.\\n\\tself changeZoomFactor: self getZoomFactor.\\n\\tzoomController target: currentPage.\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStoryboardBookMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StoryboardBookMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:53'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Storyboard'\\n\\t\\tcategories:\\t\\t#('Presentation')\\n\\t\\tdocumentation:\\t'A storyboard authoring tool'! !\\nObject subclass: #Stream\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Streams'!\\n!Stream commentStamp: '<historical>' prior: 0!\\nI am an abstract class that represents an accessor for a sequence of objects. This sequence is referred to as my \\\"contents\\\".!\\n\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNext\\n\\n\\t^ self next.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNextPut: anObject \\n\\n\\t^ self nextPut: anObject! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNextPutAll: aCollection \\n\\n\\t^ self nextPutAll: aCollection.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 2/24/2001 17:31'!\\nbinary! !\\n\\n!Stream methodsFor: 'accessing'!\\ncontents\\n\\t\\\"Answer all of the contents of the receiver.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:07'!\\nflush\\n\\t\\\"Do nothing by default\\\"! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:38'!\\nlocalName\\n\\t^'a stream'! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext\\n\\t\\\"Answer the next object accessible by the receiver.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext: anInteger \\n\\t\\\"Answer the next anInteger number of objects accessible by the receiver.\\\"\\n\\n\\t| aCollection |\\n\\taCollection _ OrderedCollection new.\\n\\tanInteger timesRepeat: [aCollection addLast: self next].\\n\\t^aCollection! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext: anInteger put: anObject \\n\\t\\\"Make anObject be the next anInteger number of objects accessible by the \\n\\treceiver. Answer anObject.\\\"\\n\\n\\tanInteger timesRepeat: [self nextPut: anObject].\\n\\t^anObject! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextMatchAll: aColl\\n \\\"Answer true if next N objects are the ones in aColl,\\n else false. Advance stream of true, leave as was if false.\\\"\\n | save |\\n save _ self position.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n self position: save.\\n ^ false]\\n ].\\n ^ true! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextMatchFor: anObject \\n\\t\\\"Gobble the next object and answer whether it is equal to the argument, \\n\\tanObject.\\\"\\n\\n\\t^anObject = self next! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextPut: anObject \\n\\t\\\"Insert the argument, anObject, as the next object accessible by the \\n\\treceiver. Answer anObject.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextPutAll: aCollection \\n\\t\\\"Append the elements of aCollection to the sequence of objects accessible \\n\\tby the receiver. Answer aCollection.\\\"\\n\\n\\taCollection do: [:v | self nextPut: v].\\n\\t^aCollection! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:40'!\\nopenReadOnly\\n\\t^self! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'ajh 7/31/2001 20:34'!\\nprintOn: stream\\n\\n\\tsuper printOn: stream.\\n\\tstream space.\\n\\tself contents printOn: stream.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:41'!\\nreadOnly\\n\\t^self! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'ls 9/12/1998 20:55'!\\nupToEnd\\n\\t\\\"answer the remaining elements in the string\\\"\\n\\t| elements |\\n\\telements _ OrderedCollection new.\\n\\t[ self atEnd ] whileFalse: [ \\n\\t\\telements add: self next ].\\n\\t^elements! !\\n\\n\\n!Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:52'!\\ndialect\\n\\n\\t^#ST80\\t\\t\\\"in case a regular stream is used to print parse nodes\\\"! !\\n\\n!Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:54'!\\nwithStyleFor: elementType do: aBlock\\n\\n\\t^aBlock value\\t\\t\\\"in case a regular stream is used to print parse nodes\\\"\\n\\\">>\\n(Compiler new compile: 'blah ^self' in: String notifying: nil ifFail: []) printString\\n<<\\\"! !\\n\\n\\n!Stream methodsFor: 'as yet unclassified' stamp: 'RAA 9/11/2000 19:12'!\\nsleep\\n\\n\\t\\\"an FTP-based stream might close the connection here\\\"! !\\n\\n\\n!Stream methodsFor: 'enumerating'!\\ndo: aBlock \\n\\t\\\"Evaluate aBlock for each of the objects accessible by receiver.\\\"\\n\\n\\t[self atEnd]\\n\\t\\twhileFalse: [aBlock value: self next]! !\\n\\n\\n!Stream methodsFor: 'file open/close' stamp: 'mir 8/10/1999 12:04'!\\nclose! !\\n\\n\\n!Stream methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:48'!\\nwrite:encodedObject\\n\\t^encodedObject putOn:self.\\n! !\\n\\n\\n!Stream methodsFor: 'printing' stamp: 'sma 6/1/2000 09:56'!\\nprint: anObject\\n\\t\\\"Have anObject print itself on the receiver.\\\"\\n\\n\\tanObject printOn: self! !\\n\\n!Stream methodsFor: 'printing' stamp: 'djp 7/21/1998 17:13'!\\nprintHtml: anObject\\n\\tanObject printHtmlOn: self! !\\n\\n\\n!Stream methodsFor: 'testing'!\\natEnd\\n\\t\\\"Answer whether the receiver can access any more objects.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ab 8/28/2003 18:30'!\\nclosed\\n\\t^ false! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'!\\nisStream\\n\\t\\\"Return true if the receiver responds to the stream protocol\\\"\\n\\t^true! !\\n\\n!Stream methodsFor: 'testing' stamp: 'mir 11/10/2003 18:22'!\\nisTypeHTTP\\n\\n\\t^false! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ar 5/17/2001 19:07'!\\nnextWordsPutAll: aCollection\\n\\t\\\"Write the argument a word-like object in big endian format on the receiver.\\n\\tMay be used to write other than plain word-like objects (such as ColorArray).\\\"\\n\\taCollection class isPointers | aCollection class isWords not \\n\\t\\tifTrue: [^self error: aCollection class name,' is not word-like'].\\n\\t1 to: aCollection basicSize do:[:i|\\n\\t\\tself nextNumber: 4 put: (aCollection basicAt: i).\\n\\t].\\n\\t^aCollection! !\\n\\n\\n!Stream methodsFor: '*monticello' stamp: 'cwp 8/9/2003 12:02'!\\nisMessageStream\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStream class\\n\\tinstanceVariableNames: ''!\\n\\n!Stream class methodsFor: 'instance creation'!\\nnew\\n\\n\\tself error: 'Streams are created with on: and with:'! !\\nTestCase subclass: #StreamBugz\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-Bugs'!\\n\\n!StreamBugz methodsFor: 'as yet unclassified' stamp: 'ar 8/5/2003 02:25'!\\ntestReadWriteStreamNextNBug\\n\\t| aStream |\\n\\taStream := ReadWriteStream on: String new.\\n\\taStream nextPutAll: 'Hello World'.\\n\\tself shouldnt:[aStream next: 5] raise: Error.\\n! !\\nAbstractSound subclass: #StreamingMP3Sound\\n\\tinstanceVariableNames: 'volume repeat mpegFile mpegStreamIndex totalSamples streamSamplingRate mixer lastBufferMSecs mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Kernel'!\\n!StreamingMP3Sound commentStamp: '<historical>' prior: 0!\\nI implement a streaming player for MPEG or MP3 files.\\nExample of use:\\n\\t(StreamingMP3Sound onFileNamed: 'song.mp3') play.\\n!\\n\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:16'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t^ totalSamples asFloat / streamSamplingRate\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nrepeat\\n\\t\\\"Answer the repeat flag.\\\"\\n\\n\\trepeat ifNil: [repeat := false].\\n\\t^ repeat\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nrepeat: aBoolean\\n\\t\\\"Set the repeat flag. If true, this sound will loop back to the beginning when it gets to the end.\\\"\\n\\n\\trepeat := aBoolean.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 16:18'!\\nsoundPosition\\n\\t\\\"Answer the relative position of sound playback as a number between 0.0 and 1.0.\\\"\\n\\n\\tself mpegFileIsOpen ifFalse: [^ 0.0].\\n\\tmpegFile hasAudio ifFalse: [^ 0.0].\\n\\t^ (mpegFile audioGetSample: 0) asFloat / totalSamples\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsoundPosition: fraction\\n\\t\\\"Jump to the position the given fraction through the sound file. The argument is a number between 0.0 and 1.0.\\\"\\n\\n\\t| sampleIndex |\\n\\tself mpegFileIsOpen ifFalse: [^ self].\\n\\tmpegFile hasAudio ifTrue: [\\n\\t\\tsampleIndex := ((totalSamples * fraction) truncated max: 0) min: totalSamples.\\n\\t\\tmpegFile audioSetSample: 0 stream: 0. \\\"work around for library bug: first seek to zero\\\"\\n\\t\\tmpegFile audioSetSample: sampleIndex stream: 0].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 15:34'!\\nstreamSamplingRate\\n\\t\\\"Answer the sampling rate of the MP3 stream.\\\"\\n\\n\\t^ streamSamplingRate\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 9/26/2000 07:49'!\\nvolume\\n\\t\\\"Answer my volume.\\\"\\n\\n\\t^ volume\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nvolume: aNumber\\n\\t\\\"Set my volume to the given number between 0.0 and 1.0.\\\"\\n\\n\\tvolume := aNumber.\\n\\tself createMixer.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsaveAsFileNamed: newFileName compressionType: compressionTypeString\\n\\t\\\"Store this MP3 sound in a SunAudio file with the given name using the given compression type.\\\"\\n\\n\\t| outFile |\\n\\toutFile := (FileStream newFileNamed: newFileName) binary.\\n\\tself storeSunAudioOn: outFile compressionType: compressionTypeString.\\n\\toutFile close.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstoreSunAudioOn: aBinaryStream compressionType: compressionName\\n\\t\\\"Store myself on the given stream as a monophonic sound compressed with the given type of compression. The sampling rate is reduced to 22050 samples/second if it is higher.\\\"\\n\\n\\t| fmt inBufSize samplesPerFrame codec inBuf compressed outSamplingRate audioWriter samplesRemaining outBuf counts byteCount |\\n\\tself pause; reset. \\\"stop playing and return to beginning\\\"\\n\\n\\tfmt := SunAudioFileWriter formatCodeForCompressionType: compressionName.\\n\\tinBufSize := 64000.\\n\\tsamplesPerFrame := 1.\\n\\tcodec := SunAudioFileWriter codecForFormatCode: fmt.\\n\\tcodec ifNotNil: [\\n\\t\\tsamplesPerFrame := codec samplesPerFrame.\\n\\t\\tinBufSize := inBufSize roundUpTo: (2 * samplesPerFrame).\\n\\t\\tcompressed := ByteArray new:\\n\\t\\t\\t(inBufSize // samplesPerFrame) * codec bytesPerEncodedFrame].\\n\\tinBuf := SoundBuffer newMonoSampleCount: inBufSize.\\n\\toutSamplingRate := streamSamplingRate.\\n\\tstreamSamplingRate > 22050 ifTrue: [\\n\\t\\tstreamSamplingRate = 44100 ifFalse: [self error: 'unexpected MP3 sampling rate'].\\n\\t\\toutSamplingRate := 22050].\\n\\n\\t\\\"write audio header\\\"\\n\\taudioWriter := SunAudioFileWriter onStream: aBinaryStream.\\n\\taudioWriter writeHeaderSamplingRate: outSamplingRate format: fmt.\\n\\n\\t\\\"convert and write sound data\\\"\\n\\t'Storing audio...' displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: totalSamples during: [:bar |\\n\\t\\t\\tsamplesRemaining := totalSamples.\\n\\t\\t\\t[samplesRemaining > 0] whileTrue: [\\n\\t\\t\\t\\tbar value: totalSamples - samplesRemaining.\\n\\t\\t\\t\\tsamplesRemaining < inBuf monoSampleCount ifTrue: [\\n\\t\\t\\t\\t\\tinBuf := SoundBuffer newMonoSampleCount:\\n\\t\\t\\t\\t\\t\\t(samplesRemaining roundUpTo: 2 * samplesPerFrame)].\\n\\t\\t\\t\\tmpegFile audioReadBuffer: inBuf stream: 0 channel: 0.\\n\\t\\t\\t\\toutSamplingRate < streamSamplingRate\\n\\t\\t\\t\\t\\tifTrue: [outBuf := inBuf downSampledLowPassFiltering: true]\\n\\t\\t\\t\\t\\tifFalse: [outBuf := inBuf].\\n\\t\\t\\t\\tcodec\\n\\t\\t\\t\\t\\tifNil: [audioWriter appendSamples: outBuf]\\n\\t\\t\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\t\\t\\tcounts := codec\\n\\t\\t\\t\\t\\t\\t\\tencodeFrames: (outBuf size // samplesPerFrame)\\n\\t\\t\\t\\t\\t\\t\\tfrom: outBuf at: 1\\n\\t\\t\\t\\t\\t\\t\\tinto: compressed at: 1.\\n\\t\\t\\t\\t\\t\\tbyteCount := counts last.\\n\\t\\t\\t\\t\\t\\tbyteCount = compressed size\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [audioWriter appendBytes: compressed]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [audioWriter appendBytes: (compressed copyFrom: 1 to: byteCount)]].\\n\\t\\t\\t\\tsamplesRemaining := samplesRemaining - inBuf monoSampleCount]].\\n\\n\\t\\\"update audio header\\\"\\n\\taudioWriter updateHeaderDataSize.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'file ops' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncloseFile\\n\\t\\\"Close the MP3 or MPEG file.\\\"\\n\\n\\tself pause.\\n\\tmpegFile ifNil: [^ self].\\n\\tmpegFile closeFile.\\n\\tmpegFile := nil.\\n\\tmixer := nil.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'file ops' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmpegFileIsOpen\\n\\t\\\"Answer true if I have an open, valid MPEG file handle. If the handle is not valid, try to re-open the file.\\\"\\n\\n\\tmpegFile ifNil: [^ false].\\n\\tmpegFile fileHandle ifNil: [\\n\\t\\t\\\"try to reopen the file, which may have been saved in a snapshot\\\"\\n\\t\\tmpegFile openFile: mpegFile fileName.\\n\\t\\tmpegFile fileHandle ifNil: [mpegFile := nil]].\\n\\t^ mpegFile notNil\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ninitMPEGFile: anMPEGFile streamIndex: anInteger\\n\\t\\\"Initialize for playing the given stream of the given MPEG or MP3 file.\\\"\\n\\n\\tvolume := 0.3.\\n\\trepeat := false.\\n\\tmpegFile := anMPEGFile.\\n\\tmpegStreamIndex := anInteger.\\n\\ttotalSamples := mpegFile audioSamples: mpegStreamIndex.\\n\\tself reset.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmillisecondsSinceStart\\n\\t\\\"Answer the number of milliseconds since this sound started playing.\\\"\\n\\n\\t| i mSecs |\\n\\tmpegFile ifNil: [^ 0].\\n\\tmpegFile fileHandle ifNil: [^ 0]. \\\"mpeg file not open\\\"\\n\\ti := mpegFile audioGetSample: mpegStreamIndex.\\n\\ti < 0 ifTrue: [^ 0]. \\\"movie file has no audio\\\"\\n\\tmSecs := i * 1000 // streamSamplingRate.\\n\\t(self isPlaying and: [lastBufferMSecs > 0]) ifTrue: [\\n\\t\\t\\\"adjust mSecs by the milliseconds since the last buffer\\\"\\n\\t\\tmutex critical: [\\n\\t\\t\\tmSecs := i * 1000 // streamSamplingRate.\\n\\t\\t\\tmSecs := mSecs + ((Time millisecondClockValue - lastBufferMSecs) max: 0)]].\\n\\t^ mSecs + 350 - (2 * SoundPlayer bufferMSecs)\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"Mix the next n samples of this sound into the given buffer starting at the given index\\\"\\n\\n\\t| current |\\n\\tself repeat ifTrue: [ \\\"loop if necessary\\\"\\n\\t\\tcurrent := mpegFile audioGetSample: mpegStreamIndex.\\n\\t\\t(totalSamples - current) < n ifTrue: [\\n\\t\\t\\tmpegFile audioSetSample: 0 stream: mpegStreamIndex]].\\n\\n\\tmutex critical: [\\n\\t\\tlastBufferMSecs := Time millisecondClockValue.\\n\\t\\tself loadBuffersForSampleCount: (n * streamSamplingRate) // SoundPlayer samplingRate.\\n\\t\\tmixer playSampleCount: n into: aSoundBuffer startingAt: startIndex].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nreset\\n\\n\\tsuper reset.\\n\\tself createMixer.\\n\\tmpegFile audioSetSample: 0 stream: mpegStreamIndex.\\n\\tlastBufferMSecs := 0.\\n\\tmutex := Semaphore forMutualExclusion.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsamplesRemaining\\n\\n\\t| samplesPlayed |\\n\\tmpegFile ifNil: [^ 0].\\n\\tself repeat ifTrue: [^ 1000000].\\n\\tsamplesPlayed := mpegFile audioGetSample: mpegStreamIndex.\\n\\tsamplesPlayed > totalSamples ifTrue: [^ 0].\\n\\t^ totalSamples - samplesPlayed\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncreateMixer\\n\\t\\\"Create a mixed sound consisting of sampled sounds with one sound buffer's worth of samples. The sound has the same sampling rate and number of channels as the MPEG or MP3 file.\\\"\\n\\n\\t| channels pan snd |\\n\\tmpegFile ifNil: [^ self error: 'No MPEG or MP3 file'].\\n\\tchannels := mpegFile audioChannels: mpegStreamIndex.\\n\\tstreamSamplingRate := mpegFile audioSampleRate: mpegStreamIndex.\\n\\tmixer := MixedSound new.\\n\\t1 to: channels do: [:c |\\n\\t\\tchannels = 1\\n\\t\\t\\tifTrue: [pan := 0.5]\\n\\t\\t\\tifFalse: [pan := (c - 1) asFloat / (channels - 1)].\\n\\t\\tsnd := SampledSound\\n\\t\\t\\tsamples: (SoundBuffer newMonoSampleCount: 2) \\\"buffer size will be adjusted dynamically\\\"\\n\\t\\t\\tsamplingRate: streamSamplingRate.\\n\\t\\tmixer add: snd pan: pan volume: volume].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nloadBuffersForSampleCount: count\\n \\\"Load the sound buffers for all tracks with the next count\\nsamples from the MPEG\\nfile sound track.\\\"\\n\\n | snd buf |\\n 1 to: mixer sounds size do: [:i |\\n snd := mixer sounds at: i.\\n buf := snd samples.\\n buf monoSampleCount = count ifFalse: [\\n buf := SoundBuffer newMonoSampleCount: count.\\n snd setSamples: buf samplingRate:\\nstreamSamplingRate].\\n i = 1 ifTrue: [ \\\"first channel\\\"\\n mpegFile\\n audioReadBuffer: buf\\n stream: mpegStreamIndex\\n channel: 0]\\n ifFalse: [ \\\"all other channels\\\"\\n mpegFile\\n audioReReadBuffer: buf\\n stream: mpegStreamIndex\\n channel: 1]].\\n mixer reset.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStreamingMP3Sound class\\n\\tinstanceVariableNames: ''!\\n\\n!StreamingMP3Sound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me for playing the sound track of the MPEG or MP3 file with the given name. Answer nil the file is not a valid MPEG or MP3 file.\\\"\\n\\n\\t| mpegFile |\\n\\t(MPEGFile isFileValidMPEG: fileName) ifFalse: [^ nil].\\n\\tmpegFile := MPEGFile openFile: fileName.\\n\\t^ self new initMPEGFile: mpegFile streamIndex: 0 \\\"assume sound track is in stream 0\\\"\\n! !\\nAbstractSound subclass: #StreamingMonoSound\\n\\tinstanceVariableNames: 'stream volume repeat headerStart audioDataStart streamSamplingRate totalSamples codec mixer leftoverSamples lastBufferMSecs mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!StreamingMonoSound commentStamp: '<historical>' prior: 0!\\nI implement a streaming player for monophonic Sun (.au) and AIFF (.aif) audio files.\\nExample of use:\\n\\t(StreamingMonoSound onFileNamed: 'song.aif') play.\\n!\\n\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:12'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t^ totalSamples asFloat / streamSamplingRate\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 10/18/2001 15:46'!\\nrepeat\\n\\t\\\"Answer the repeat flag.\\\"\\n\\n\\t^ repeat\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrepeat: aBoolean\\n\\t\\\"Set the repeat flag. If true, this sound will loop back to the beginning when it gets to the end.\\\"\\n\\n\\trepeat := aBoolean.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:05'!\\nsoundPosition\\n\\t\\\"Answer the relative position of sound playback as a number between 0.0 and 1.0.\\\"\\n\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0.0].\\n\\t^ self currentSampleIndex asFloat / totalSamples\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsoundPosition: fraction\\n\\t\\\"Jump to the position the given fraction through the sound file. The argument is a number between 0.0 and 1.0.\\\"\\n\\n\\t| desiredSampleIndex |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ self].\\n\\tdesiredSampleIndex := ((totalSamples * fraction) truncated max: 0) min: totalSamples.\\n\\tcodec\\n\\t\\tifNil: [stream position: audioDataStart + (desiredSampleIndex * 2)]\\n\\t\\tifNotNil: [self positionCodecTo: desiredSampleIndex].\\n\\tleftoverSamples := SoundBuffer new.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/20/2001 16:59'!\\nstreamSamplingRate\\n\\t\\\"Answer the sampling rate of the MP3 stream.\\\"\\n\\n\\t^ streamSamplingRate\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 9/26/2000 07:49'!\\nvolume\\n\\t\\\"Answer my volume.\\\"\\n\\n\\t^ volume\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nvolume: aNumber\\n\\t\\\"Set my volume to the given number between 0.0 and 1.0.\\\"\\n\\n\\tvolume := aNumber.\\n\\tself createMixer.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsaveAsFileNamed: newFileName compressionType: compressionTypeString\\n\\t\\\"Store this sound in a new file with the given name using the given compression type. Useful for converting between compression formats.\\\"\\n\\n\\t| outFile |\\n\\toutFile := (FileStream newFileNamed: newFileName) binary.\\n\\tself storeSunAudioOn: outFile compressionType: compressionTypeString.\\n\\toutFile close.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreSunAudioOn: aBinaryStream compressionType: compressionName\\n\\t\\\"Store myself on the given stream as a monophonic sound compressed with the given type of compression. The sampling rate is reduced to 22050 samples/second if it is higher.\\\"\\n\\n\\t| fmt inBufSize samplesPerFrame outCodec compressed outSamplingRate audioWriter samplesRemaining inBuf outBuf counts byteCount |\\n\\tself pause; reset. \\\"stop playing and return to beginning\\\"\\n\\n\\tfmt := SunAudioFileWriter formatCodeForCompressionType: compressionName.\\n\\tinBufSize := 64000.\\n\\tsamplesPerFrame := 1.\\n\\toutCodec := SunAudioFileWriter codecForFormatCode: fmt.\\n\\toutCodec ifNotNil: [\\n\\t\\tsamplesPerFrame := outCodec samplesPerFrame.\\n\\t\\tinBufSize := inBufSize roundUpTo: (2 * samplesPerFrame).\\n\\t\\tcompressed := ByteArray new:\\n\\t\\t\\t(inBufSize // samplesPerFrame) * outCodec bytesPerEncodedFrame].\\n\\toutSamplingRate := streamSamplingRate.\\n\\tstreamSamplingRate > 22050 ifTrue: [\\n\\t\\tstreamSamplingRate = 44100 ifFalse: [self error: 'unexpected MP3 sampling rate'].\\n\\t\\toutSamplingRate := 22050].\\n\\n\\t\\\"write audio header\\\"\\n\\taudioWriter := SunAudioFileWriter onStream: aBinaryStream.\\n\\taudioWriter writeHeaderSamplingRate: outSamplingRate format: fmt.\\n\\n\\t\\\"convert and write sound data\\\"\\n\\t'Storing audio...' displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: totalSamples during: [:bar |\\n\\t\\t\\tsamplesRemaining := totalSamples.\\n\\t\\t\\t[samplesRemaining > 0] whileTrue: [\\n\\t\\t\\t\\tbar value: totalSamples - samplesRemaining.\\n\\t\\t\\t\\tself loadBuffersForSampleCount: (inBufSize min: samplesRemaining).\\n\\t\\t\\t\\tinBuf := mixer sounds first samples.\\n\\t\\t\\t\\toutSamplingRate < streamSamplingRate\\n\\t\\t\\t\\t\\tifTrue: [outBuf := inBuf downSampledLowPassFiltering: true]\\n\\t\\t\\t\\t\\tifFalse: [outBuf := inBuf].\\n\\t\\t\\t\\toutCodec\\n\\t\\t\\t\\t\\tifNil: [audioWriter appendSamples: outBuf]\\n\\t\\t\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\t\\t\\tcounts := outCodec\\n\\t\\t\\t\\t\\t\\t\\tencodeFrames: (outBuf size // samplesPerFrame)\\n\\t\\t\\t\\t\\t\\t\\tfrom: outBuf at: 1\\n\\t\\t\\t\\t\\t\\t\\tinto: compressed at: 1.\\n\\t\\t\\t\\t\\t\\tbyteCount := counts last.\\n\\t\\t\\t\\t\\t\\tbyteCount = compressed size\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [audioWriter appendBytes: compressed]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [audioWriter appendBytes: (compressed copyFrom: 1 to: byteCount)]].\\n\\t\\t\\t\\tsamplesRemaining := samplesRemaining - inBuf monoSampleCount]].\\n\\n\\t\\\"update audio header\\\"\\n\\taudioWriter updateHeaderDataSize.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitStream: aStream headerStart: anInteger\\n\\t\\\"Initialize for streaming from the given stream. The audio file header starts at the given stream position.\\\"\\n\\n\\tstream := aStream.\\n\\tvolume := 1.0.\\n\\trepeat := false.\\n\\theaderStart := anInteger.\\n\\tself reset.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncloseFile\\n\\t\\\"Close my stream, if it responds to close.\\\"\\n\\n\\tstream ifNotNil: [\\n\\t\\t(stream respondsTo: #close) ifTrue: [stream close]].\\n\\tmixer := nil.\\n\\tcodec := nil.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractFrom: startSecs to: endSecs\\n\\t\\\"Extract a portion of this sound between the given start and end times. The current implementation only works if the sound is uncompressed.\\\"\\n\\n\\t| emptySound first last sampleCount byteStream sndBuf |\\n\\tcodec ifNotNil: [^ self error: 'only works on uncompressed sounds'].\\n\\temptySound := SampledSound samples: SoundBuffer new samplingRate: streamSamplingRate.\\n\\tfirst := (startSecs * streamSamplingRate) truncated max: 0.\\n\\tlast := ((endSecs * streamSamplingRate) truncated min: totalSamples) - 1.\\n\\tfirst >= last ifTrue: [^ emptySound].\\n\\tcodec ifNotNil: [self error: 'extracting from compressed sounds is not supported'].\\n\\tsampleCount := last + 1 - first.\\n\\tstream position: audioDataStart + (2 * first).\\n\\tbyteStream := ReadStream on: (stream next: 2 * sampleCount).\\n\\tsndBuf := SoundBuffer newMonoSampleCount: sampleCount.\\n\\t1 to: sampleCount do: [:i | sndBuf at: i put: byteStream int16].\\n\\t^ SampledSound samples: sndBuf samplingRate: streamSamplingRate\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmillisecondsSinceStart\\n\\t\\\"Answer the number of milliseconds of this sound started playing.\\\"\\n\\n\\t| mSecs |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0].\\n\\tmSecs := self currentSampleIndex * 1000 // streamSamplingRate.\\n\\t(self isPlaying and: [lastBufferMSecs > 0]) ifTrue: [\\n\\t\\t\\\"adjust mSecs by the milliseconds since the last buffer\\\"\\n\\t\\tmutex critical: [\\n\\t\\t\\tmSecs := self currentSampleIndex * 1000 // streamSamplingRate.\\n\\t\\t\\tmSecs := mSecs + ((Time millisecondClockValue - lastBufferMSecs) max: 0)]].\\n\\t^ mSecs + 350 - (2 * SoundPlayer bufferMSecs)\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"Mix the next n samples of this sound into the given buffer starting at the given index\\\"\\n\\n\\tself repeat ifTrue: [ \\\"loop if necessary\\\"\\n\\t\\t(totalSamples - self currentSampleIndex) < n ifTrue: [self startOver]].\\n\\n\\tmutex critical: [\\n\\t\\tlastBufferMSecs := Time millisecondClockValue.\\n\\t\\tself loadBuffersForSampleCount: (n * streamSamplingRate) // SoundPlayer samplingRate.\\n\\t\\tmixer playSampleCount: n into: aSoundBuffer startingAt: startIndex].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'jm 10/21/2001 09:45'!\\nreset\\n\\n\\tsuper reset.\\n\\tself startOver.\\n\\tself createMixer.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplesRemaining\\n\\t\\\"Answer the number of samples remaining to be played.\\\"\\n\\n\\t| result |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0].\\n\\tself repeat ifTrue: [^ 1000000].\\n\\tresult := (totalSamples - self currentSampleIndex) max: 0.\\n\\tresult <= 0 ifTrue: [self closeFile].\\n\\t^ result\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncreateMixer\\n\\t\\\"Create a mixed sound consisting of sampled sounds with one sound buffer's worth of samples.\\\"\\n\\n\\t| snd |\\n\\tmixer := MixedSound new.\\n\\tsnd := SampledSound\\n\\t\\tsamples: (SoundBuffer newMonoSampleCount: 2) \\\"buffer size will be adjusted dynamically\\\"\\n\\t\\tsamplingRate: streamSamplingRate.\\n\\tmixer add: snd pan: 0.5 volume: volume.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncurrentSampleIndex\\n\\t\\\"Answer the index of the current sample.\\\"\\n\\n\\t| bytePosition frameIndex |\\n\\tbytePosition := stream position - audioDataStart.\\n\\tcodec\\n\\t\\tifNil: [^ bytePosition // 2]\\n\\t\\tifNotNil: [\\n\\t\\t\\tframeIndex := bytePosition // codec bytesPerEncodedFrame.\\n\\t\\t\\t^ (frameIndex * codec samplesPerFrame) - leftoverSamples monoSampleCount].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadBuffer: aSoundBuffer compressedSampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the compressed sample stream.\\\"\\n\\t\\\"Details: Most codecs decode in multi-sample units called 'frames'. Since the requested sampleCount is typically not an even multiple of the frame size, we need to deal with partial frames. The unused samples from a partial frame are retained until the next call to this method.\\\"\\n\\n\\t| n samplesNeeded frameCount encodedBytes r decodedCount buf j |\\n\\t\\\"first, use any leftover samples\\\"\\n\\tn := self loadFromLeftovers: aSoundBuffer sampleCount: sampleCount.\\n\\tsamplesNeeded := sampleCount - n.\\n\\tsamplesNeeded <= 0 ifTrue: [^ self].\\n\\n\\t\\\"decode an integral number of full compression frames\\\"\\n\\tframeCount := samplesNeeded // codec samplesPerFrame.\\n\\tencodedBytes := stream next: (frameCount * codec bytesPerEncodedFrame).\\n\\tr := codec decodeFrames: frameCount from: encodedBytes at: 1 into: aSoundBuffer at: n + 1.\\n\\tdecodedCount := r last.\\n\\tdecodedCount >= samplesNeeded ifTrue: [^ self].\\n\\n\\t\\\"decode one last compression frame to finish filling the buffer\\\"\\n\\tbuf := SoundBuffer newMonoSampleCount: codec samplesPerFrame.\\n\\tencodedBytes := stream next: codec bytesPerEncodedFrame.\\n\\tcodec decodeFrames: 1 from: encodedBytes at: 1 into: buf at: 1.\\n\\tj := 0.\\n\\t(n + decodedCount + 1) to: sampleCount do: [:i |\\n\\t\\taSoundBuffer at: i put: (buf at: (j := j + 1))].\\n\\n\\t\\\"save the leftover samples\\\"\\n\\tleftoverSamples := buf copyFrom: (j + 1) to: buf monoSampleCount.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'jm 11/21/2001 08:03'!\\nloadBuffer: aSoundBuffer uncompressedSampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the uncompressed sample stream.\\\"\\n\\n\\t\\\"read directly into the sample buffer; count is in 32-bit words\\\"\\n\\tstream next: sampleCount // 2 into: aSoundBuffer startingAt: 1.\\n\\taSoundBuffer restoreEndianness.\\n\\n\\t\\\"read the final sample if sampleCount is odd:\\\"\\n\\tsampleCount odd ifTrue: [aSoundBuffer at: sampleCount put: stream int16].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadBuffersForSampleCount: count\\n\\t\\\"Load the sound buffers from the stream.\\\"\\n\\n\\t| snd buf sampleCount |\\n\\tsnd := mixer sounds first.\\n\\tbuf := snd samples.\\n\\tbuf monoSampleCount = count ifFalse: [\\n\\t\\tbuf := SoundBuffer newMonoSampleCount: count.\\n\\t\\tsnd setSamples: buf samplingRate: streamSamplingRate].\\n\\tsampleCount := count min: (totalSamples - self currentSampleIndex).\\n\\tsampleCount < count ifTrue: [buf primFill: 0].\\n\\n\\tcodec\\n\\t\\tifNil: [self loadBuffer: buf uncompressedSampleCount: sampleCount]\\n\\t\\tifNotNil: [self loadBuffer: buf compressedSampleCount: sampleCount].\\n\\n\\tmixer reset.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadFromLeftovers: aSoundBuffer sampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the samples leftover from the last frame. Answer the number of samples loaded, which typically is less than sampleCount.\\\"\\n\\n\\t| leftoverCount n |\\n\\tleftoverCount := leftoverSamples monoSampleCount.\\n\\tleftoverCount = 0 ifTrue: [^ 0].\\n\\n\\tn := leftoverCount min: sampleCount.\\n\\t1 to: n do: [:i | aSoundBuffer at: i put: (leftoverSamples at: i)].\\n\\tn < sampleCount\\n\\t\\tifTrue: [leftoverSamples := SoundBuffer new]\\n\\t\\tifFalse: [leftoverSamples := leftoverSamples copyFrom: n + 1 to: leftoverSamples size].\\n\\t^ n\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npositionCodecTo: desiredSampleIndex\\n\\t\\\"Position to the closest frame before the given sample index when using a codec. If using the ADPCM codec, try to ensure that it is in sync with the compressed sample stream.\\\"\\n\\n\\t| desiredFrameIndex desiredPosition tmpStream tmpCodec byteBuf bufFrames sampleBuf frameCount n startOffset |\\n\\t(codec isKindOf: ADPCMCodec) ifFalse: [\\n\\t\\t\\\"stateless codecs (or relatively stateless ones, like GSM: just jump to frame boundary\\\"\\n\\t\\tdesiredFrameIndex := desiredSampleIndex // codec samplesPerFrame.\\n\\t\\tstream position: audioDataStart + (desiredFrameIndex * codec bytesPerEncodedFrame).\\n\\t\\tcodec reset.\\n\\t\\t^ self].\\n\\n\\t\\\"compute the desired stream position\\\"\\n\\tdesiredFrameIndex := desiredSampleIndex // codec samplesPerFrame.\\n\\tdesiredPosition := audioDataStart + (desiredFrameIndex * codec bytesPerEncodedFrame).\\n\\n\\t\\\"copy stream and codec\\\"\\n\\t(stream isKindOf: FileStream)\\n\\t\\tifTrue: [tmpStream := (FileStream readOnlyFileNamed: stream name) binary]\\n\\t\\tifFalse: [tmpStream := stream deepCopy].\\n\\ttmpCodec := codec copy reset.\\n\\n\\t\\\"reset the codec and start back about 30 seconds to try to get codec in sync\\\"\\n\\tstartOffset := ((desiredFrameIndex - 80000) max: 0) * codec bytesPerEncodedFrame.\\n\\ttmpStream position: audioDataStart + startOffset.\\n\\n\\t\\\"decode forward to the desired position\\\"\\n\\tbyteBuf := ByteArray new: (32000 roundTo: codec bytesPerEncodedFrame).\\n\\tbufFrames := byteBuf size // codec bytesPerEncodedFrame.\\n\\tsampleBuf := SoundBuffer newMonoSampleCount: bufFrames * codec samplesPerFrame.\\n\\tframeCount := (desiredPosition - tmpStream position) // codec bytesPerEncodedFrame.\\n\\t[frameCount > 0] whileTrue: [\\n\\t\\tn := bufFrames min: frameCount.\\n\\t\\ttmpStream next: n * codec bytesPerEncodedFrame into: byteBuf startingAt: 1.\\n\\t\\ttmpCodec decodeFrames: n from: byteBuf at: 1 into: sampleBuf at: 1.\\n\\t\\tframeCount := frameCount - n].\\n\\n\\tcodec := tmpCodec.\\n\\tstream position: tmpStream position.\\n\\t(tmpStream isKindOf: FileStream) ifTrue: [tmpStream close].! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadAIFFHeader\\n\\t\\\"Read an AIFF file header from stream.\\\"\\n\\n\\t| aiffReader |\\n\\taiffReader := AIFFFileReader new.\\n\\taiffReader readFromStream: stream mergeIfStereo: false skipDataChunk: true.\\n\\taiffReader channelCount = 1 ifFalse: [self error: 'not monophonic'].\\n\\taiffReader bitsPerSample = 16 ifFalse: [self error: 'not 16-bit'].\\n\\n\\taudioDataStart := headerStart + aiffReader channelDataOffset.\\n\\tstreamSamplingRate := aiffReader samplingRate.\\n\\ttotalSamples := aiffReader frameCount min: (stream size - audioDataStart) // 2.\\n\\tcodec := nil.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadHeader\\n\\t\\\"Read the sound file header from my stream.\\\"\\n\\n\\t| id |\\n\\tstream position: headerStart.\\n\\tid := (stream next: 4) asString.\\n\\tstream position: headerStart.\\n\\tid = '.snd' ifTrue: [^ self readSunAudioHeader].\\n\\tid = 'FORM' ifTrue: [^ self readAIFFHeader].\\n\\tself error: 'unrecognized sound file format'.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadSunAudioHeader\\n\\t\\\"Read a Sun audio file header from my stream.\\\"\\n\\n\\t| id headerBytes dataBytes format channelCount |\\n\\tid := (stream next: 4) asString.\\n\\theaderBytes := stream uint32. \\\"header bytes\\\"\\n\\tdataBytes := stream uint32.\\n\\tformat := stream uint32.\\n\\tstreamSamplingRate := stream uint32.\\n\\tchannelCount := stream uint32.\\n\\n\\tid = '.snd' ifFalse: [self error: 'not Sun audio format'].\\n\\tdataBytes := dataBytes min: (stream size - headerBytes).\\n\\tchannelCount = 1 ifFalse: [self error: 'not monophonic'].\\n\\taudioDataStart := headerStart + headerBytes.\\n\\tcodec := nil.\\n\\tformat = 1 ifTrue: [ \\\"8-bit u-LAW\\\"\\n\\t\\tcodec := MuLawCodec new.\\n\\t\\ttotalSamples := dataBytes.\\n\\t\\t^ self].\\n\\tformat = 3 ifTrue: [ \\\"16-bit linear\\\"\\n\\t\\ttotalSamples := dataBytes // 2.\\n\\t\\t^ self].\\n\\tformat = 23 ifTrue: [ \\\"ADPCM-4 bit (CCITT G.721)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 4 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 4) * 8.\\n\\t\\t^ self].\\n\\tformat = 25 ifTrue: [ \\\"ADPCM-3 bit (CCITT G.723)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 3 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 3) * 8.\\n\\t\\t^ self].\\n\\tformat = 26 ifTrue: [ \\\"ADPCM-5 bit (CCITT G.723)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 5 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 5) * 8.\\n\\t\\t^ self].\\n\\tformat = 610 ifTrue: [ \\\"GSM 06.10 (this format was added by Squeak)\\\"\\n\\t\\tcodec := GSMCodec new.\\n\\t\\ttotalSamples := (dataBytes // 33) * 160.\\n\\t\\t^ self].\\n\\tself error: 'unsupported Sun audio format ', format printString\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartOver\\n\\t\\\"Jump back to the first sample.\\\"\\n\\n\\tstream reopen; binary.\\n\\tself readHeader.\\n\\tstream position: audioDataStart.\\n\\tleftoverSamples := SoundBuffer new.\\n\\tlastBufferMSecs := 0.\\n\\tmutex := Semaphore forMutualExclusion.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStreamingMonoSound class\\n\\tinstanceVariableNames: ''!\\n\\n!StreamingMonoSound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me for playing the file with the given name.\\\"\\n\\n\\t| f |\\n\\tf := FileDirectory default readOnlyFileNamed: fileName.\\n\\tf ifNil: [^ self error: 'could not open ', fileName].\\n\\t^ self new initStream: f headerStart: 0\\n! !\\n\\n!StreamingMonoSound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName headerStart: anInteger\\n\\t\\\"Answer an instance of me for playing audio data starting at the given position in the file with the given name.\\\"\\n\\n\\t| f |\\n\\tf := FileDirectory default readOnlyFileNamed: fileName.\\n\\tf ifNil: [^ self error: 'could not open ', fileName].\\n\\t^ self new initStream: f headerStart: anInteger\\n! !\\nAlignmentMorphBob1 subclass: #StretchyImageMorph\\n\\tinstanceVariableNames: 'form cache'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Experimental'!\\n!StretchyImageMorph commentStamp: '<historical>' prior: 0!\\nI draw a form to fill whatever bounds I have.!\\n\\n\\n!StretchyImageMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 16:20'!\\nform: aForm\\n\\n\\tform _ aForm! !\\n\\n\\n!StretchyImageMorph methodsFor: 'drawing' stamp: 'nk 1/3/2004 17:40'!\\ndrawOn: aCanvas\\n| t |\\n\\\"\\nSmalltalk at: #Q4 put: OrderedCollection new.\\n\\\"\\n\\tform ifNil: [form _ (Form extent: 32@32 depth: 8) fillColor: Color green].\\n\\t(cache isNil or: [cache extent ~= bounds extent]) ifTrue: [\\n\\t\\tt _ [cache _ Form extent: bounds extent depth: form depth.\\n\\t\\tform displayInterpolatedIn: cache boundingBox on: cache.\\n\\t\\tcache _ cache asFormOfDepth: aCanvas depth] timeToRun.\\n\\t\\t\\\"Q4 add: {t. form. cache}.\\\"\\n\\t].\\n\\taCanvas paintImage: cache at: bounds origin.\\n! !\\n\\n\\n!StretchyImageMorph methodsFor: 'initialization' stamp: 'ar 10/30/2000 15:31'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself hResizing: #spaceFill.\\n\\tself vResizing: #spaceFill.\\n! !\\nAbstractFont subclass: #StrikeFont\\n\\tinstanceVariableNames: 'characterToGlyphMap xTable glyphs name type minAscii maxAscii maxWidth strikeLength ascent descent xOffset raster subscript superscript emphasis derivativeFonts pointSize fallbackFont charIndex'\\n\\tclassVariableNames: 'DefaultStringScanner'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Graphics-Fonts'!\\n!StrikeFont commentStamp: '<historical>' prior: 0!\\nI 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 glyphs. Characters are mapped to glyphs by using the characterToGyphMap.\\n\\nSubclasses can have non-trivial mapping rules as well as different representations for glyphs sizes (e.g., not using an xTable). If so, these classes should return nil when queried for xTable and/or the characterToGlyphMap. This will cause the CharacterScanner primitive to fail and query the font for the width of a character (so that a more programatical approach can be implemented).\\n\\nFor display, fonts need to implement two messages:\\n\\t#installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor\\nThis method installs the receiver (a font) on the given DisplayContext (which may be an instance of BitBlt or Canvas (or any of it's subclasses). The font should take the appropriate action to initialize the display context so that further display operations can be optimized.\\n\\t#displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta\\nThis method is called for each subsequent run of characters in aString which is to be displayed with the (previously installed) settings.\\n!\\n\\n\\n!StrikeFont methodsFor: 'accessing'!\\nascent\\n\\t\\\"Answer the receiver's maximum extent of characters above the baseline.\\\"\\n\\n\\t^ascent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/2/2000 13:06'!\\nascentKern\\n\\t\\\"Return the kern delta for ascenders.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ (self ascent-5+4)//4 max: 0 \\\"See makeItalicGlyphs\\\"\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nascentOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont ascentOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self ascent.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/1/2000 17:17'!\\nbaseKern\\n\\t\\\"Return the base kern value to be used for all characters.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ ((self height-1-self ascent+4)//4 max: 0) \\\"See makeItalicGlyphs\\\"\\n\\t\\t+ (((self ascent-5+4)//4 max: 0))\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 5/23/2000 12:52'!\\ncharacterToGlyphMap\\n\\t^characterToGlyphMap ifNil:[characterToGlyphMap _ self createCharacterToGlyphMap].! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 5/23/2000 12:52'!\\ncharacterToGlyphMap: anArray\\n\\tcharacterToGlyphMap _ anArray.! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'nk 3/15/2004 18:57'!\\nderivativeFonts\\n\\t^derivativeFonts copyWithout: nil! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\ndescent\\n\\t\\\"Answer the receiver's maximum extent of characters below the baseline.\\\"\\n\\n\\t^descent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/2/2000 13:06'!\\ndescentKern\\n\\t\\\"Return the kern delta for descenders.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ (self height-1-self ascent+4)//4 max: 0 \\\"See makeItalicGlyphs\\\"\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\ndescentOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont descentOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self descent.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'tak 12/22/2004 01:25'!\\nfallbackFont\\n\\t^ fallbackFont\\n\\t\\tifNil: [fallbackFont _ FixedFaceFont new errorFont fontSize: self height]! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 5/20/2004 11:01'!\\nfallbackFont: aFontSetOrNil\\n\\n\\tfallbackFont _ aFontSetOrNil.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nfamilyName\\n\\t^self name withoutTrailingDigits.\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'tk 6/26/1998 16:45'!\\nfamilySizeFace\\n\\t\\\"Answer an array with familyName, a String, pointSize, an Integer, and\\n\\tfaceCode, an Integer.\\\"\\n\\n\\t^Array with: name\\n\\t\\twith: self height\\n\\t\\twith: emphasis\\n\\n\\t\\\"(1 to: 12) collect: [:x | (TextStyle default fontAt: x) familySizeFace]\\\"! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 9/21/2000 11:53'!\\nfontNameWithPointSize\\n\\t^self name withoutTrailingDigits, ' ', self pointSize printString! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/7/2005 11:15'!\\nglyphInfoOf: aCharacter into: glyphInfoArray\\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\n\\t| code |\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont glyphInfoOf: aCharacter into: glyphInfoArray.\\n\\t\\t].\\n\\t\\tcode _ 0.\\n\\t] ifTrue: [\\n\\t\\tcode _ aCharacter charCode.\\n\\t].\\n\\tglyphInfoArray at: 1 put: glyphs;\\n\\t\\tat: 2 put: (xTable at: code + 1);\\n\\t\\tat: 3 put: (xTable at: code + 2);\\n\\t\\tat: 4 put: (self ascentOf: aCharacter);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nglyphOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\n\\t| code |\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont glyphOf: aCharacter.\\n\\t\\t].\\n\\t\\t^ (Form extent: 1@self height) fillColor: Color white\\n\\t].\\n\\tcode _ aCharacter charCode.\\n\\t^ glyphs copy: (((xTable at: code + 1)@0) corner: (xTable at: code +2)@self height).\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nglyphs\\n\\t\\\"Answer a Form containing the bits representing the characters of the \\n\\treceiver.\\\"\\n\\n\\t^glyphs! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nheight\\n\\t\\\"Answer the height of the receiver, total of maximum extents of \\n\\tcharacters above and below the baseline.\\\"\\n\\n\\t^self ascent + self descent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nheightOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont heightOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self height.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nlineGrid\\n\\t^ ascent + descent! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nmaxAscii\\n\\t\\\"Answer the integer that is the last Ascii character value of the receiver.\\\"\\n\\n\\t^maxAscii! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nmaxWidth\\n\\t\\\"Answer the integer that is the width of the receiver's widest character.\\\"\\n\\n\\t^maxWidth! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nminAscii\\n\\t\\\"Answer the integer that is the first Ascii character value of the receiver.\\\"\\n\\n\\t^minAscii! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ls 3/27/2000 19:54'!\\nname\\n\\t\\\"Answer the receiver's name.\\\"\\n\\n\\t^name ifNil: ['(unnamed)']! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nname: aString\\n\\t\\\"Set the receiver's name.\\\"\\n\\n\\tname _ aString! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'sw 1/18/2000 20:54'!\\npointSize\\n\\t^ pointSize! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'sma 5/5/2000 14:21'!\\npointSize: anInteger\\n\\tpointSize _ anInteger! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nraster\\n\\t\\\"Answer an integer that specifies the layout of the glyphs' form.\\\"\\n\\n\\t^raster! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsetGlyphs: newGlyphs\\n\\t\\\"Replace the glyphs form. Used to make a synthetic bold or italic font quickly.\\\"\\n\\n\\tglyphs _ newGlyphs! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsubscript\\n\\t\\\"Answer an integer that is the further vertical offset relative to the \\n\\tbaseline for positioning characters as subscripts.\\\"\\n\\n\\t^subscript! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsuperscript\\n\\t\\\"Answer an integer that is the further vertical offset relative to the \\n\\tbaseline for positioning characters as superscripts.\\\"\\n\\n\\t^superscript! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'nk 6/17/2003 14:26'!\\ntextStyle\\n\\t^ TextStyle actualTextStyles detect:\\n\\t\\t[:aStyle | aStyle fontArray includes: self] ifNone: [nil]! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:12'!\\nwidthOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\t| code |\\n\\tcode := aCharacter charCode.\\n\\t((code < minAscii or: [maxAscii < code]) \\n\\t\\tor: [(xTable at: code + 1) < 0])\\n\\t\\t\\tifTrue: [^ self fallbackFont widthOf: aCharacter].\\n\\t^ (xTable at: code + 2) - (xTable at: code + 1)! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nxTable\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^xTable! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 8/28/2002 16:33'!\\nxTable: anObject\\n\\n\\txTable _ anObject.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'character shapes'!\\nalter: char formBlock: formBlock\\n\\tself characterFormAt: char \\n\\t\\tput: (formBlock value: (self characterFormAt: char))! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'yo 12/28/2002 22:37'!\\ncharacterFormAtMulti: character \\n\\t\\\"Answer a Form copied out of the glyphs for the argument, character.\\\"\\n\\t| ascii leftX rightX |\\n\\tascii _ character charCode.\\n\\t(ascii between: minAscii and: maxAscii) ifFalse: [ascii _ maxAscii + 1].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\t^ glyphs copy: (leftX @ 0 corner: rightX @ self height)! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'yo 12/1/2003 17:01'!\\ncharacterFormAt: character \\n\\t\\\"Answer a Form copied out of the glyphs for the argument, character.\\\"\\n\\t| ascii leftX rightX |\\n\\tascii _ character charCode.\\n\\t(ascii between: minAscii and: maxAscii) ifFalse: [ascii _ maxAscii + 1].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\tleftX < 0 ifTrue: [^ glyphs copy: (0@0 corner: 0@self height)].\\n\\t^ glyphs copy: (leftX @ 0 corner: rightX @ self height)! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 8/30/2000 10:00'!\\ncharacterFormAt: character put: characterForm\\n\\t\\\"Copy characterForm over the glyph for the argument, character.\\\"\\n\\t| ascii leftX rightX widthDif newGlyphs |\\n\\tascii _ character asciiValue.\\n\\tascii < minAscii ifTrue: [^ self error: 'Cant store characters below min ascii'].\\n\\tascii > maxAscii ifTrue:\\n\\t\\t[(self confirm:\\n'This font does not accomodate ascii values higher than ' , maxAscii printString , '.\\nDo you wish to extend it permanently to handle values up to ' , ascii printString)\\n\\t\\t\\tifTrue: [self extendMaxAsciiTo: ascii]\\n\\t\\t\\tifFalse: [^ self error: 'No change made']].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\twidthDif _ characterForm width - (rightX - leftX).\\n\\twidthDif ~= 0 ifTrue:\\n\\t\\t[\\\"Make new glyphs with more or less space for this char\\\"\\n\\t\\tnewGlyphs _ Form extent: (glyphs width + widthDif) @ glyphs height.\\n\\t\\tnewGlyphs copy: (0@0 corner: leftX@glyphs height)\\n\\t\\t\\tfrom: 0@0 in: glyphs rule: Form over.\\n\\t\\tnewGlyphs copy: ((rightX+widthDif)@0 corner: newGlyphs width@glyphs height)\\n\\t\\t\\tfrom: rightX@0 in: glyphs rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\t\\\"adjust further entries on xTable\\\"\\n\\t\\txTable _ xTable copy.\\n\\t\\tascii+2 to: xTable size\\n\\t\\t\\tdo: [:i | xTable at: i put: (xTable at: i) + widthDif]].\\n\\tglyphs copy: (leftX @ 0 extent: characterForm extent)\\n\\t\\tfrom: 0@0 in: characterForm rule: Form over\\n\\\"\\n| f | f _ TextStyle defaultFont.\\nf characterFormAt: $ put: (Form extent: (f widthOf: $ )+10@f height)\\n\\\"! !\\n\\n!StrikeFont methodsFor: 'character shapes'!\\ncharacterForm: char pixelValueAt: pt put: val\\n\\t| f |\\n\\tf _ self characterFormAt: char.\\n\\tf pixelAt: pt put: val.\\n\\tself characterFormAt: char put: val! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'btr 11/18/2002 15:00'!\\nedit: character \\n\\t\\\"Open a Bit Editor on the given character. Note that you must do an accept \\n\\t(in the option menu of the bit editor) if you want this work. \\n\\tAccepted edits will not take effect in the font until you leave or close the bit editor. \\n\\tAlso note that unaccepted edits will be lost when you leave or close.\\\"\\n\\t\\\"Note that BitEditor only works in MVC currently.\\\"\\n\\n\\t\\\"(TextStyle default fontAt: 1) edit: $_\\\"\\n\\n\\t| charForm editRect scaleFactor bitEditor savedForm r |\\n\\tcharForm _ self characterFormAt: character.\\n\\teditRect _ BitEditor locateMagnifiedView: charForm scale: (scaleFactor _ 8 @ 8).\\n\\tbitEditor _ BitEditor\\n\\t\\t\\t\\tbitEdit: charForm\\n\\t\\t\\t\\tat: editRect topLeft\\n\\t\\t\\t\\tscale: scaleFactor\\n\\t\\t\\t\\tremoteView: nil.\\n\\tsavedForm _ Form fromDisplay: (r _ bitEditor displayBox\\n\\t\\t\\t\\t\\t\\t\\texpandBy: (0 @ 23 corner: 0 @ 0)).\\n\\tbitEditor controller startUp.\\n\\tbitEditor release.\\n\\tsavedForm displayOn: Display at: r topLeft.\\n\\tself characterFormAt: character put: charForm! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'BG 12/6/2004 19:22'!\\nensureCleanBold\\n\\t\\\"This ensures that all character glyphs have at least one pixel of white space on the right\\n\\tso as not to cause artifacts in neighboring characters in bold or italic.\\\"\\n\\n\\t| newGlyphs newXTable newGlyphPos startPos newWidth widthOfGlyph increment lastCol |\\n\\temphasis = 0 ifFalse: [^ self].\\n newWidth := glyphs width + maxAscii - minAscii + 1.\\n lastCol := Form extent: 1@ glyphs height.\\n newGlyphs := Form extent: newWidth @ glyphs height.\\n newXTable := Array new: xTable size.\\n 1 to: minAscii do: [:idx | newXTable at: idx put: (xTable at: idx)].\\n \\n newGlyphPos := startPos := 0.\\n minAscii to: maxAscii do:\\n [:idx | \\n newXTable at: idx + 1 put: newGlyphPos.\\n widthOfGlyph := (xTable at: idx + 2 ) - (xTable at: idx + 1).\\n widthOfGlyph > 0\\n ifTrue:\\n [newGlyphs copy: (newGlyphPos @ 0 extent: widthOfGlyph @ glyphs height)\\n from: startPos@0 in: glyphs rule: Form over.\\n lastCol copy: (0 @ 0 extent: 1 @ glyphs height)\\n from: startPos + widthOfGlyph - 1 @0 in: glyphs rule: Form over.\\n increment := lastCol isAllWhite ifTrue: [0] ifFalse: [1].\\n startPos := startPos + widthOfGlyph.\\n newGlyphPos := newGlyphPos + widthOfGlyph + increment.\\n ].\\n ].\\n maxAscii + 2 to: newXTable size do: [:idx | newXTable at: idx put: newGlyphPos.].\\n glyphs := Form extent: newGlyphPos @ glyphs height.\\n glyphs copy: (0 @ 0 extent: glyphs extent)\\n from: 0@0 in: newGlyphs rule: Form over.\\n xTable := newXTable.\\n\\\"\\nStrikeFont allInstancesDo: [:f | f ensureCleanBold].\\n(StrikeFont familyName: 'NewYork' size: 21) ensureCleanBold.\\nStrikeFont shutDown. 'Flush synthetic fonts'.\\n\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'ar 5/23/2000 12:48'!\\nextendMaxAsciiTo: newMax\\n\\t\\\"Extend the range of this font so that it can display glyphs up to newMax.\\\"\\n\\n\\t(newMax+3) <= xTable size ifTrue: [^ self]. \\\"No need to extend.\\\"\\n\\txTable size = (maxAscii+3) ifFalse:\\n\\t\\t[^ self error: 'This font is not well-formed.'].\\n\\n\\t\\\"Insert a bunch of zero-width characters...\\\"\\n\\txTable _ (xTable copyFrom: 1 to: maxAscii+2) ,\\n\\t\\t\\t((maxAscii+1 to: newMax) collect: [:i | xTable at: maxAscii+2]) ,\\n\\t\\t\\t{ xTable at: maxAscii+3 }.\\n\\tmaxAscii _ newMax.\\n\\tself fillZeroWidthSlots.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 3/27/2000 16:10'!\\nfillZeroWidthSlots\\n\\t| nullGlyph |\\n\\t\\\"Note: this is slow because it copies the font once for every replacement.\\\"\\n\\n\\tnullGlyph _ (Form extent: 1@glyphs height) fillGray.\\n\\t\\\"Now fill the empty slots with narrow box characters.\\\"\\n\\tminAscii to: maxAscii do:\\n\\t\\t[:i | (self widthOf: (Character value: i)) = 0 ifTrue:\\n\\t\\t\\t[self characterFormAt: (Character value: i) put: nullGlyph]].\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 4/28/2000 16:10'!\\nfixOneWideChars \\n\\t\\\"This fixes all 1-wide characters to be 2 wide with blank on the right\\n\\tso as not to cause artifacts in neighboring characters in bold or italic.\\\"\\n\\t| twoWide |\\n\\tminAscii to: maxAscii do:\\n\\t\\t[:i | (self widthOf: (Character value: i)) = 1 ifTrue:\\n\\t\\t\\t[twoWide _ Form extent: 2@glyphs height.\\n\\t\\t\\t(self characterFormAt: (Character value: i)) displayOn: twoWide at: 0@0.\\n\\t\\t\\tself characterFormAt: (Character value: i) put: twoWide]].\\n\\\"\\nStrikeFont allInstancesDo: [:f | f fixOneWideChars].\\nStrikeFont shutDown. 'Flush synthetic fonts'.\\n\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'RAA 7/6/2000 16:50'!\\nmakeCarriageReturnsWhite\\n\\t| crForm |\\n\\t\\\"Some larger fonts have a gray carriage return (from the zero wide fixup) make it white so it doesn't show\\\"\\n\\n\\tcrForm _ self characterFormAt: 13 asCharacter.\\n\\tcrForm fillWhite.\\n\\tself characterFormAt: 13 asCharacter put: crForm.\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes'!\\nwiden: char by: delta\\n\\t| newForm |\\n\\t^ self alter: char formBlock: \\\"Make a new form, wider or narrower...\\\"\\n\\t\\t[:charForm | newForm _ Form extent: charForm extent + (delta@0).\\n\\t\\tcharForm displayOn: newForm. \\\"Copy this image into it\\\"\\n\\t\\tnewForm] \\\"and substitute it in the font\\\"! !\\n\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'BG 12/9/2004 17:27'!\\ndeepCopy\\n \\\" there is a circular reference from the derivative fonts back to the receiver. It is therefore not possible to make a deep copy. We make a sahllow copy. The method postCopy can be used to modify the shallow copy. \\\" \\n ^self copy! !\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'BG 12/9/2004 17:35'!\\npostCopy\\n \\\" the receiver is a just created shallow copy. This method gives it the final touch. \\\" \\n \\n glyphs := glyphs copy.\\n xTable := xTable copy.\\n characterToGlyphMap := characterToGlyphMap copy.\\n \\n self reset. \\\" takes care of the derivative fonts \\\"! !\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'tk 8/19/1998 16:15'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I am shared. Do not record me.\\\"! !\\n\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:34'!\\ncharacters: anInterval in: sourceString displayAt: aPoint clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm kernDelta: kernDelta on: aBitBlt\\n\\t\\\"Simple, slow, primitive method for displaying a line of characters.\\n\\tNo wrap-around is provided.\\\"\\n\\t| ascii destPoint leftX rightX sourceRect |\\n\\tdestPoint _ aPoint.\\n\\tanInterval do: \\n\\t\\t[:i |\\n\\t\\tself flag: #yoDisplay.\\n\\t\\t\\\"if the char is not supported, fall back to the specified fontset.\\\"\\n\\t\\tascii _ (sourceString at: i) charCode.\\n\\t\\t(ascii < minAscii or: [ascii > maxAscii])\\n\\t\\t\\tifTrue: [ascii _ maxAscii].\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\tsourceRect _ leftX@0 extent: (rightX-leftX) @ self height.\\n\\t\\taBitBlt copyFrom: sourceRect in: glyphs to: destPoint.\\n\\t\\tdestPoint _ destPoint + ((rightX-leftX+kernDelta)@0).\\n\\t\\t\\\"destPoint printString displayAt: 0@(i*20)\\\"].\\n\\t^ destPoint! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:36'!\\ndisplayLine: aString at: aPoint \\n\\t\\\"Display the characters in aString, starting at position aPoint.\\\"\\n\\n\\tself characters: (1 to: aString size)\\n\\t\\tin: aString\\n\\t\\tdisplayAt: aPoint\\n\\t\\tclippedBy: Display boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil\\n\\t\\tkernDelta: 0\\n\\t\\ton: (BitBlt current toForm: Display).\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 1/7/2005 15:16'!\\ndisplayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo char displayInfo destY |\\n\\tdestPoint _ aPoint.\\n\\tcharIndex _ startIndex.\\n\\tglyphInfo _ Array new: 5.\\n\\t[charIndex <= stopIndex] whileTrue: [\\n\\t\\tchar _ aString at: charIndex.\\n\\t\\t(self hasGlyphOf: char) not ifTrue: [\\n\\t\\t\\t\\tdisplayInfo _ self fallbackFont displayString: aString on: aBitBlt from: charIndex to: stopIndex at: destPoint kern: kernDelta from: self baselineY: baselineY.\\n\\t\\t\\t\\tcharIndex _ displayInfo first.\\n\\t\\t\\t\\tdestPoint _ displayInfo second.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tself glyphInfoOf: char into: glyphInfo.\\n\\t\\t\\tleftX _ glyphInfo second.\\n\\t\\t\\trightX _ glyphInfo third.\\n\\t\\t\\t(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\t\\tglyphInfo fifth installOn: aBitBlt.\\n\\t\\t\\t].\\n\\t\\t\\taBitBlt sourceForm: glyphInfo first.\\n\\t\\t\\tdestY _ baselineY - glyphInfo fourth. \\n\\t\\t\\taBitBlt destX: destPoint x.\\n\\t\\t\\taBitBlt destY: destY.\\n\\t\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\t\\taBitBlt width: rightX - leftX.\\n\\t\\t\\taBitBlt height: self height.\\n\\t\\t\\taBitBlt copyBits.\\n\\t\\t\\tdestPoint _ destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t\\t\\tcharIndex _ charIndex + 1.\\n\\t\\t].\\n\\t].\\n\\t^ Array with: charIndex with: destPoint.\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 12/20/2002 18:54'!\\ndisplayStringR2L: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta\\n\\t\\\"You are screwed if you reach this method.\\\"\\n\\tself halt.\\n\\taBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 4/10/2005 18:06'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t(aString isByteString) ifFalse: [^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: aPoint y + self ascent.].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 4/10/2005 18:06'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t(aString isByteString) ifFalse:[^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY.].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'BG 3/16/2005 08:27'!\\nfontDisplay\\n\\t\\\"TextStyle default defaultFont fontDisplay.\\\"\\n\\n\\tDisplay restoreAfter:\\n\\t\\t[(Form extent: 440@400) displayAt: 90@90.\\n\\t\\t 0 to: 15 do:\\n\\t\\t\\t[:i |\\n\\t\\t\\ti storeStringHex displayAt: 100 @ (20 * i + 100).\\n\\t\\t\\t0 to: 15 do:\\n\\t\\t\\t\\t[:j |\\n\\t\\t\\t\\t((16*i+j) between: 1 and: (self xTable size - 2)) ifTrue:\\n\\t\\t\\t\\t\\t[(self characterFormAt: (16 * i + j) asCharacter)\\n\\t\\t\\t\\t\\t\\tdisplayAt: (20 * j + 150) @ (20 * i + 100)]]].\\n\\t\\t\\t'Click to continue...' asDisplayText displayAt: 100@450]! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 1/5/2005 13:59'!\\ninstallOn: aDisplayContext\\n\\n\\t^aDisplayContext installStrikeFont: self.\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 15:08'!\\ninstallOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor\\n\\t^aDisplayContext \\n\\t\\tinstallStrikeFont: self\\n\\t\\tforegroundColor: foregroundColor \\n\\t\\tbackgroundColor: backgroundColor! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'tak 1/11/2005 18:03'!\\nwidthOfString: aString from: firstIndex to: lastIndex\\n\\t| resultX |\\n\\tresultX _ 0.\\n\\tfirstIndex to: lastIndex do:[:i | \\n\\t\\tresultX _ resultX + (self widthOf: (aString at: i))].\\n\\t^ resultX.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 12/18/2003 23:30'!\\nbonk: glyphForm with: bonkForm\\n\\t\\\"Bonking means to run through the glyphs clearing out black pixels\\n\\tbetween characters to prevent them from straying into an adjacent\\n\\tcharacter as a result of, eg, bolding or italicizing\\\"\\n\\t\\\"Uses the bonkForm to erase at every character boundary in glyphs.\\\"\\n\\t| bb offset x |\\n\\toffset _ bonkForm offset x.\\n\\tbb _ BitBlt current toForm: glyphForm.\\n\\tbb sourceForm: bonkForm; sourceRect: bonkForm boundingBox;\\n\\t\\tcombinationRule: Form erase; destY: 0.\\n\\tx _ self xTable.\\n\\t(x isMemberOf: SparseLargeTable) ifTrue: [\\n\\t\\tx base to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t] ifFalse: [\\n\\t\\t1 to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis'!\\nemphasis\\n\\t\\\"Answer the integer code for synthetic bold, italic, underline, and \\n\\tstrike-out.\\\"\\n\\n\\t^emphasis! !\\n\\n!StrikeFont methodsFor: 'emphasis'!\\nemphasis: code \\n\\t\\\"Set the integer code for synthetic bold, itallic, underline, and strike-out, \\n\\twhere bold=1, italic=2, underlined=4, and struck out=8.\\\"\\n\\n\\temphasis _ code! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'di 9/3/2000 13:22'!\\nemphasized: code \\n\\t\\\"Answer a copy of the receiver with emphasis set to include code.\\\"\\n\\t| derivative addedEmphasis base safeCode |\\n\\tcode = 0 ifTrue: [^ self].\\n\\t(derivativeFonts == nil or: [derivativeFonts size = 0]) ifTrue: [^ self].\\n\\tderivative _ derivativeFonts at: (safeCode _ code min: derivativeFonts size).\\n\\tderivative == nil ifFalse: [^ derivative]. \\\"Already have this style\\\"\\n\\n\\t\\\"Dont have it -- derive from another with one with less emphasis\\\"\\n\\taddedEmphasis _ 1 bitShift: safeCode highBit - 1.\\n\\tbase _ self emphasized: safeCode - addedEmphasis. \\\"Order is Bold, Ital, Under, Narrow\\\"\\n\\taddedEmphasis = 1 ifTrue: \\\"Compute synthetic bold version of the font\\\"\\n\\t\\t[derivative _ (base copy ensureCleanBold name: base name , 'B') makeBoldGlyphs].\\n\\taddedEmphasis = 2 ifTrue: \\\"Compute synthetic italic version of the font\\\"\\n\\t\\t[ derivative _ (base copy name: base name , 'I') makeItalicGlyphs].\\n\\taddedEmphasis = 4 ifTrue: \\\"Compute underlined version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'U') makeUnderlinedGlyphs].\\n\\taddedEmphasis = 8 ifTrue: \\\"Compute narrow version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'N') makeCondensedGlyphs].\\n\\taddedEmphasis = 16 ifTrue: \\\"Compute struck-out version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'X') makeStruckOutGlyphs].\\n\\tderivative emphasis: safeCode.\\n\\tderivativeFonts at: safeCode put: derivative.\\n\\t^ derivative! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeBoldGlyphs\\n\\t\\\"Make a bold set of glyphs with same widths by ORing 1 bit to the right\\n\\t\\t(requires at least 1 pixel of intercharacter space)\\\"\\n\\t| g bonkForm |\\n\\tg _ glyphs deepCopy.\\n\\tbonkForm _ (Form extent: 1@16) fillBlack offset: -1@0.\\n\\tself bonk: g with: bonkForm.\\n\\tg copyBits: g boundingBox from: g at: (1@0)\\n\\t\\tclippingBox: g boundingBox rule: Form under fillColor: nil.\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 1\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:51'!\\nmakeCondensedGlyphs\\n\\t\\\"Make a condensed set of glyphs with same widths.\\n\\tNOTE: this has been superceded by kerning -- should not get called\\\"\\n\\t| g newXTable x x1 w |\\n\\tg _ glyphs deepCopy.\\n\\tnewXTable _ Array new: xTable size.\\n\\tnewXTable at: 1 put: (x _ xTable at: 1).\\n\\t1 to: xTable size-1 do:\\n\\t\\t[:i | x1 _ xTable at: i. w _ (xTable at: i+1) - x1.\\n\\t\\tw > 1 ifTrue: [w _ w-1]. \\\"Shrink every character wider than 1\\\"\\n\\t\\tg copy: (x@0 extent: w@g height) from: x1@0 in: glyphs rule: Form over.\\n\\t\\tnewXTable at: i+1 put: (x _ x + w)].\\n\\txTable _ newXTable.\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont emphasized: 8\\n\\t].\\n\\n\\\"\\n(TextStyle default fontAt: 1) copy makeCondensedGlyphs\\n\\tdisplayLine: 'The quick brown fox jumps over the lazy dog'\\n\\tat: Sensor cursorPoint\\n\\\"! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeItalicGlyphs\\n\\t\\\"Make an italic set of glyphs with same widths by skewing left and right.\\n\\tIn the process, characters would overlap, so we widen them all first.\\n\\t\\\"\\n\\t| extraWidth newGlyphs newXTable x newX w extraOnLeft | \\n\\textraOnLeft _ (self height-1-self ascent+4)//4 max: 0.\\n\\textraWidth _ ((self ascent-5+4)//4 max: 0) + extraOnLeft.\\n\\tnewGlyphs _ Form extent: (glyphs width + (maxAscii + 1 - minAscii*extraWidth)) @ glyphs height.\\n\\tnewXTable _ xTable copy.\\n\\n\\t\\\"Copy glyphs into newGlyphs with room on left and right for overlap.\\\"\\n\\tminAscii to: maxAscii+1 do:\\n\\t\\t[:ascii | x _ xTable at: ascii+1. w _ (xTable at: ascii+2) - x.\\n\\t\\tnewX _ newXTable at: ascii+1.\\n\\t\\tnewGlyphs copy: ((newX + extraOnLeft) @ 0 extent: w @ glyphs height)\\n\\t\\t\\tfrom: x @ 0 in: glyphs rule: Form over.\\n\\t\\tnewXTable at: ascii+2 put: newX + w + extraWidth].\\t\\t\\n\\tglyphs _ newGlyphs. \\n\\txTable _ newXTable.\\n\\t\\\"Slide the bitmaps left and right for synthetic italic effect.\\\"\\n\\t4 to: self ascent-1 by: 4 do:\\n\\t\\t[:y | \\t\\t\\\"Slide ascenders right...\\\"\\n\\t\\tglyphs copy: (1@0 extent: glyphs width @ (self ascent - y))\\n\\t\\t\\tfrom: 0@0 in: glyphs rule: Form over].\\n\\tself ascent to: self height-1 by: 4 do:\\n\\t\\t[:y | \\t\\t\\\"Slide descenders left...\\\"\\n\\t\\tglyphs copy: (0@y extent: glyphs width @ glyphs height)\\n\\t\\t\\tfrom: 1@y in: glyphs rule: Form over].\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 2\\n\\t].\\n\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeStruckOutGlyphs\\n\\t\\\"Make a struck-out set of glyphs with same widths\\\"\\n\\t| g |\\n\\tg _ glyphs deepCopy.\\n\\tg fillBlack: (0 @ (self ascent - (self ascent//3)) extent: g width @ 1).\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 16\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeUnderlinedGlyphs\\n\\t\\\"Make an underlined set of glyphs with same widths\\\"\\n\\t| g |\\n\\tg _ glyphs deepCopy.\\n\\tg fillBlack: (0 @ (self ascent+1) extent: g width @ 1).\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 4\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'nk 3/15/2004 18:46'!\\nreleaseCachedState\\n\\n\\tself reset.! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'tak 3/11/2005 17:09'!\\nreset\\n\\t\\\"Reset the cache of derivative emphasized fonts\\\"\\n\\n\\t| style font |\\n\\tfallbackFont class = FixedFaceFont\\n\\t\\tifTrue: [fallbackFont _ nil].\\n\\tderivativeFonts _ Array new: 32.\\n\\t#('B' 'I' 'BI') doWithIndex:\\n\\t\\t[:tag :index | \\n\\t\\t(style _ TextStyle named: self familyName) ifNotNil:\\n\\t\\t\\t[(font _ style fontArray\\n\\t\\t\\t\\tdetect: [:each | each name = (self name , tag)]\\n\\t\\t\\t\\tifNone: [nil]) ifNotNil: [derivativeFonts at: index put: font]]]! !\\n\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:50'!\\nbuildfontNamed: nm fromForms: forms startingAtAscii: startAscii\\n\\tascent: a descent: d maxWid: m\\n\\t\\\"This builds a StrikeFont instance from existing forms.\\\"\\n\\n\\t| lastAscii width ascii charForm missingForm tempGlyphs |\\n\\tname _ nm.\\n\\tascent _ 11.\\n\\tdescent _ 3.\\n\\tmaxWidth _ 16.\\n\\tpointSize _ 8.\\n\\tname _ (name copyWithout: Character space) ,\\n\\t\\t\\t\\t(pointSize < 10\\n\\t\\t\\t\\t\\tifTrue: ['0' , pointSize printString]\\n\\t\\t\\t\\t\\tifFalse: [pointSize printString]).\\n\\tminAscii _ 258.\\n\\tmaxAscii _ 0.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\ttype _ 0. \\\"ignored for now\\\"\\n\\n\\ttempGlyphs _ Form extent: (maxWidth*257) @ self height.\\n\\txTable _ (Array new: 258) atAllPut: 0.\\n\\txTable at: 1 put: 0.\\n\\n\\t\\\"Read character forms and blt into tempGlyphs\\\"\\n\\tlastAscii _ -1.\\n\\t1 to: forms size do:\\n\\t\\t[:i | charForm _ forms at: i. width _ charForm width.\\n\\t\\tascii _ startAscii-1+i.\\n\\t\\tself displayChar: ascii form: charForm.\\n\\t\\tascii = 256\\n\\t\\t\\tifTrue: [missingForm _ charForm deepCopy]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t[minAscii _ minAscii min: ascii.\\n\\t\\t\\tmaxAscii _ maxAscii max: ascii.\\n\\t\\t\\tlastAscii+1 to: ascii-1 do: [:as | xTable at: as+2 put: (xTable at: as+1)].\\n\\t\\t\\ttempGlyphs copy: ((xTable at: ascii+1)@0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\textent: charForm extent)\\n\\t\\t\\t\\t\\t\\tfrom: 0@0 in: charForm rule: Form over.\\n\\t\\t\\txTable at: ascii+2 put: (xTable at: ascii+1) + width.\\n\\t\\t\\tlastAscii _ ascii]].\\n\\tlastAscii+1 to: maxAscii+1 do: [:as | xTable at: as+2 put: (xTable at: as+1)].\\n\\tmissingForm == nil ifFalse:\\n\\t\\t[tempGlyphs copy: missingForm boundingBox from: missingForm\\n\\t\\t\\t\\tto: (xTable at: maxAscii+2)@0 rule: Form over.\\n\\t\\txTable at: maxAscii+3 put: (xTable at: maxAscii+2) + missingForm width].\\n\\tglyphs _ Form extent: (xTable at: maxAscii+3) @ self height.\\n\\tglyphs copy: glyphs boundingBox from: 0@0 in: tempGlyphs rule: Form over.\\n\\txTable _ xTable copyFrom: 1 to: maxAscii+3.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\ndisplayChar: ascii form: charForm\\n\\t\\\"Convenience utility used during conversion of BitFont files\\\"\\n\\t| m bigForm |\\n\\tDisplay fillBlack: (0@0 extent: 20@14).\\n\\tascii printString displayAt: 0@2.\\n\\tcharForm width > 0 ifTrue:\\n\\t\\t[m _ 5.\\n\\t\\tbigForm _ charForm magnify: charForm boundingBox by: m@m.\\n\\t\\tDisplay border: ((bigForm boundingBox expandBy: m) translateBy: 50@2) width: m.\\n\\t\\tbigForm displayAt: 50@2.\\n\\t\\tDisplay fillBlack: ((50@2)+((m*charForm width)@0) extent: 1@(m*self height))].! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'md 11/14/2003 17:25'!\\nnewFromStrike: fileName\\n\\t\\\"Build an instance from the strike font file name. The '.strike' extension\\n\\tis optional.\\\"\\n\\n\\t| strike startName raster16 |\\n\\tname _ fileName copyUpTo: $..\\t\\\"assumes extension (if any) is '.strike'\\\"\\n\\tstrike _ FileStream readOnlyFileNamed: name, '.strike.'.\\n\\tstrike binary.\\n\\n\\t\\\"strip off direcory name if any\\\"\\n\\tstartName _ name size.\\n\\t[startName > 0 and: [((name at: startName) ~= $>) & ((name at: startName) ~= $])]]\\n\\t\\twhileTrue: [startName _ startName - 1].\\n\\tname _ name copyFrom: startName+1 to: name size.\\n\\n\\ttype\\t\\t\\t_\\t\\tstrike nextWord.\\t\\t\\\"type is ignored now -- simplest\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tassumed. Kept here to make\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twriting and consistency more\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstraightforward.\\\"\\n\\tminAscii\\t\\t_\\t\\tstrike nextWord.\\n\\tmaxAscii\\t\\t_\\t\\tstrike nextWord.\\n\\tmaxWidth\\t\\t_\\t\\tstrike nextWord.\\n\\tstrikeLength\\t_\\t\\tstrike nextWord.\\n\\tascent\\t\\t\\t_\\t\\tstrike nextWord.\\n\\tdescent\\t\\t\\t_\\t\\tstrike nextWord.\\n\\t\\\"xOffset\\t\\t\\t_\\\"\\t\\tstrike nextWord. \\t\\n\\traster16\\t\\t\\t_\\t\\tstrike nextWord.\\t\\n\\tsuperscript\\t\\t_\\t\\tascent - descent // 3.\\t\\n\\tsubscript\\t\\t_\\t\\tdescent - ascent // 3.\\t\\n\\temphasis\\t\\t_\\t\\t0.\\n\\tglyphs\\t\\t\\t_\\tForm extent: (raster16 * 16) @ (self height) \\n\\t\\t\\t\\t\\t\\t\\toffset: 0@0.\\n\\t\\tglyphs bits fromByteStream: strike.\\n\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | xTable at: index put: strike nextWord].\\n\\n\\t\\\"Set up space character\\\"\\n\\t((xTable at: (Space asciiValue + 2)) = 0 or:\\n\\t\\t\\t[(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))])\\n\\t\\tifTrue:\\t[(Space asciiValue + 2) to: xTable size do:\\n\\t\\t\\t\\t\\t[:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]].\\n\\tstrike close.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'tk 9/28/2000 15:50'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to a known Font in the other system instead. \\\"\\n\\n\\t\\\"A path to me\\\"\\n\\t(TextConstants at: #forceFontWriting ifAbsent: [false]) ifTrue: [^ self].\\n\\t\\t\\\"special case for saving the default fonts on the disk. See collectionFromFileNamed:\\\"\\n\\n\\tdp _ DiskProxy global: #StrikeFont selector: #familyName:size:emphasized:\\n\\t\\t\\targs: (Array with: self familyName with: self height\\n\\t\\t\\t\\t\\twith: self emphasis).\\n\\trefStrm replace: self with: dp.\\n\\t^ dp! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'sma 6/1/2000 09:32'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPut: $(;\\n\\t\\tnextPutAll: self name;\\n\\t\\tspace;\\n\\t\\tprint: self height;\\n\\t\\tnextPut: $)! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 10/25/2005 00:21'!\\nreadBDFFromFile: fileName name: aString \\n\\t\\\"This builds a StrikeFont instance by reading the X11 Binary \\n\\tDistribution Format font source file. See the BDFFontReader class\\n\\tcomment.\\\"\\n\\n\\t\\\"StrikeFont new readBDFFromFile: 'helvR12' name: 'Helvetica12'.\\\"\\n\\n\\t| fontReader stream |\\n\\tfontReader := BDFFontReader openFileNamed: fileName.\\n\\tstream := ReadStream on: fontReader read.\\n\\txTable := stream next.\\n\\tglyphs := stream next.\\n\\tminAscii := stream next.\\n\\tmaxAscii := stream next.\\n\\tmaxWidth := stream next.\\n\\tascent := stream next.\\n\\tdescent := stream next.\\n\\tpointSize := stream next.\\n\\tname := aString.\\n\\\"\\txTable size <= 256 ifTrue: [self setStopConditions].\\\"\\n\\ttype := 0.\\t\\\"no one see this\\\"\\n\\tsuperscript := (ascent - descent) // 3.\\n\\tsubscript := (descent - ascent) // 3.\\n\\temphasis := 0.\\n\\tself reset! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\nreadBFHeaderFrom: f\\n\\tname _ self restOfLine: 'Font name = ' from: f.\\n\\tascent _ (self restOfLine: 'Ascent = ' from: f) asNumber.\\n\\tdescent _ (self restOfLine: 'Descent = ' from: f) asNumber.\\n\\tmaxWidth _ (self restOfLine: 'Maximum width = ' from: f) asNumber.\\n\\tpointSize _ (self restOfLine: 'Font size = ' from: f) asNumber.\\n\\tname _ (name copyWithout: Character space) ,\\n\\t\\t\\t\\t(pointSize < 10\\n\\t\\t\\t\\t\\tifTrue: ['0' , pointSize printString]\\n\\t\\t\\t\\t\\tifFalse: [pointSize printString]).\\n\\tminAscii _ 258.\\n\\tmaxAscii _ 0.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\ttype _ 0. \\\"ignored for now\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 11/30/2003 17:08'!\\nreadEFontBDFForJapaneseFromFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: fontReader rangesForJapanese overrideWith: otherFileName otherRanges: {Array with: 8481 with: 12320} additionalOverrideRange: fontReader additionalRangesForJapanese).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 1/15/2004 16:48'!\\nreadEFontBDFForKoreanFromFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: fontReader rangesForKorean overrideWith: otherFileName otherRanges: {Array with: 8481 with: 12320} additionalOverrideRange: fontReader additionalRangesForKorean).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 12/28/2002 21:02'!\\nreadEFontBDFFromFile: fileName name: aString rangeFrom: startRange to: endRange\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReader readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readFrom: startRange to: endRange).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 1/19/2005 11:22'!\\nreadEFontBDFFromFile: fileName name: aString ranges: ranges\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: ranges).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 9/23/2002 16:30'!\\nreadF12FromStream: aStream\\n\\n\\t| box blt |\\n\\tminAscii _ 0.\\n\\tmaxAscii _ 94*94.\\n\\tascent _ 12.\\n\\tdescent _ 0.\\n\\tpointSize _ 12.\\n\\tsuperscript _ 0.\\n\\tsubscript _ 0.\\n\\temphasis _ 0.\\n\\tmaxWidth _ 12.\\n\\t\\n\\tbox _ Form extent: 12@12.\\n\\tglyphs _ Form extent: (94*94*12)@12.\\n\\tblt _ BitBlt toForm: glyphs. \\n\\txTable _ XTableForFixedFont new.\\n\\txTable maxAscii: maxAscii + 3.\\n\\txTable width: 12.\\n\\t1 to: 256 do: [:index | \\n\\t\\t1 to: 12 do: [:i |\\n\\t\\t\\taStream next.\\n\\t\\t].\\n\\t].\\n\\t(minAscii + 1 to: 94*94) do: [:index | \\n\\t\\tself readCharacter: (box bits) from: aStream.\\n\\t\\tblt copy: ((12*(index-1))@0 extent: 12@12) from: 0@0 in: box.\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:50'!\\nreadFromBitFont: fileName\\n\\t\\\"This builds a StrikeFont instance by reading the data file format\\n\\tproduced by BitFont, a widely available font conversion utility\\n\\twritten by Peter DiCamillo at Brown University\\\"\\n\\t\\\"StrikeFont new readFromBitFont: 'Palatino10.BF' \\\"\\n\\t| f lastAscii charLine width ascii charForm line missingForm tempGlyphs iRect p rectLine left tokens right |\\n\\tf _ FileStream readOnlyFileNamed: fileName.\\n\\tself readBFHeaderFrom: f.\\n\\n\\t\\\"NOTE: if font has been scaled (and in any case),\\n\\tthe REAL bitmap dimensions come after the header.\\\"\\n\\tself restOfLine: 'Extent information for entire font' from: f.\\n\\t\\\"Parse the following line (including mispelling!!)\\\"\\n\\t\\\"Image rectange: left = -2, right = 8, bottom = -2, top = 7\\\"\\n\\ttokens _ (f upTo: Character cr) findTokens: ' '.\\n\\tiRect _ Rectangle left: (tokens at: 5) asNumber right: (tokens at: 8) asNumber\\n\\t\\t\\t\\ttop: (tokens at: 14) asNumber bottom: (tokens at: 11) asNumber.\\n\\tascent _ iRect top.\\n\\tdescent _ iRect bottom negated.\\n\\t\\n\\ttempGlyphs _ Form extent: (maxWidth*257) @ self height.\\n\\txTable _ (Array new: 258) atAllPut: 0.\\n\\txTable at: 1 put: 0.\\n\\n\\t\\\"Read character forms and blt into tempGlyphs\\\"\\n\\tlastAscii _ -1.\\n\\t[charLine _ self restOfLine: 'Character: ' from: f.\\n\\tcharLine == nil ifFalse:\\n\\t\\t[p _ f position.\\n\\t\\trectLine _ f upTo: Character cr.\\n\\t\\t(rectLine beginsWith: 'Image rectange: left = ')\\n\\t\\t\\tifTrue: [tokens _ rectLine findTokens: ' '.\\n\\t\\t\\t\\t\\tleft _ (tokens at: 5) asNumber. right _ (tokens at: 8) asNumber]\\n\\t\\t\\tifFalse: [left _ right _ 0. f position: p].\\n\\t\\twidth_ (self restOfLine: 'Width (final pen position) = ' from: f) asNumber - left\\n\\t\\t\\t\\t\\tmax: (right-left+1).\\n\\t\\t(charLine beginsWith: 'Missing character') ifTrue: [ascii _ 256].\\n\\t\\t('x''*' match: charLine) ifTrue:\\n\\t\\t\\t[ascii _ Number readFrom: (charLine copyFrom: 3 to: 4) asUppercase base: 16].\\n\\t\\tcharForm _ Form extent: width@self height.\\n\\t\\t('*[all blank]' match: charLine) ifFalse:\\n\\t\\t\\t[self restOfLine: ' +' from: f.\\n\\t\\t\\t1 to: self height do:\\n\\t\\t\\t\\t[:y | line _ f upTo: Character cr.\\n\\t\\t\\t\\t4 to: (width + 3 min: line size + iRect left - left) do:\\n\\t\\t\\t\\t\\t[:x | (line at: x - iRect left + left) = $*\\n\\t\\t\\t\\t\\t\\tifTrue: [charForm pixelValueAt: (x-4)@(y-1) put: 1]]]]].\\n\\tcharLine == nil]\\n\\t\\twhileFalse:\\n\\t\\t\\t[self displayChar: ascii form: charForm.\\n\\t\\t\\tascii = 256\\n\\t\\t\\t\\tifTrue: [missingForm _ charForm deepCopy]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[minAscii _ minAscii min: ascii.\\n\\t\\t\\t\\tmaxAscii _ maxAscii max: ascii.\\n\\t\\t\\t\\tlastAscii+1 to: ascii-1 do: [:a | xTable at: a+2 put: (xTable at: a+1)].\\n\\t\\t\\t\\ttempGlyphs copy: ((xTable at: ascii+1)@0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\textent: charForm extent)\\n\\t\\t\\t\\t\\t\\t\\tfrom: 0@0 in: charForm rule: Form over.\\n\\t\\t\\t\\txTable at: ascii+2 put: (xTable at: ascii+1) + width.\\n\\t\\t\\t\\tlastAscii _ ascii]].\\n\\tf close.\\n\\tlastAscii+1 to: maxAscii+1 do: [:a | xTable at: a+2 put: (xTable at: a+1)].\\n\\tmissingForm == nil ifFalse:\\n\\t\\t[tempGlyphs copy: missingForm boundingBox from: missingForm\\n\\t\\t\\t\\tto: (xTable at: maxAscii+2)@0 rule: Form over.\\n\\t\\txTable at: maxAscii+3 put: (xTable at: maxAscii+2) + missingForm width].\\n\\tglyphs _ Form extent: (xTable at: maxAscii+3) @ self height.\\n\\tglyphs copy: glyphs boundingBox from: 0@0 in: tempGlyphs rule: Form over.\\n\\txTable _ xTable copyFrom: 1 to: maxAscii+3.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:53'!\\nreadFromStrike2Stream: file \\n\\t\\\"Build an instance from the supplied binary stream on data in strike2 format\\\"\\n\\ttype _ file nextInt32. type = 2 ifFalse: [file close. self error: 'not strike2 format'].\\n\\tminAscii _ file nextInt32.\\n\\tmaxAscii _ file nextInt32.\\n\\tmaxWidth _ file nextInt32.\\n\\tascent _ file nextInt32.\\n\\tdescent _ file nextInt32.\\n\\tpointSize _ file nextInt32.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ file nextInt32.\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | xTable at: index put: file nextInt32].\\n\\tglyphs _ Form new readFrom: file.\\n\\n\\t\\\"Set up space character\\\"\\n\\t((xTable at: (Space asciiValue + 2)) = 0 or:\\n\\t\\t\\t[(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))])\\n\\t\\tifTrue:\\t[(Space asciiValue + 2) to: xTable size do:\\n\\t\\t\\t\\t\\t[:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]].\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'sma 12/30/1999 14:20'!\\nreadFromStrike2: fileName \\\"StrikeFont new readFromStrike2: 'Palatino14.sf2'\\\"\\n\\t\\\"Build an instance from the strike font stored in strike2 format.\\n\\tfileName is of the form: <family name><pointSize>.sf2\\\"\\n\\t| file |\\n\\t('*.sf2' match: fileName) ifFalse: [self halt. \\\"likely incompatible\\\"].\\n\\tname _ fileName copyUpTo: $. . \\\"Drop filename extension\\\"\\n\\tfile _ FileStream readOnlyFileNamed: fileName.\\n\\tfile binary.\\n\\t[self readFromStrike2Stream: file] ensure: [file close]! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\nrestOfLine: leadString from: file\\n\\t\\\"Utility method to assist reading of BitFont data files\\\"\\n\\t| line |\\n\\t[line _ file upTo: Character cr.\\n\\tline size < leadString size or: [leadString ~= (line copyFrom: 1 to: leadString size)]]\\n\\twhileTrue: [file atEnd ifTrue: [^ nil]].\\n\\t^ line copyFrom: leadString size+1 to: line size! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ls 4/11/2000 18:57'!\\nwriteAsStrike2named: fileName\\n\\t\\\"Write me onto a file in strike2 format.\\n\\tfileName should be of the form: <family name><pointSize>.sf2\\\"\\n\\t| file |\\n\\tfile _ FileStream fileNamed: fileName.\\n\\tself writeAsStrike2On: file.\\n\\tfile close.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ls 3/27/2000 17:43'!\\nwriteAsStrike2On: file\\n\\t\\\"Write me onto a file in strike2 format.\\n\\tfileName should be of the form: <family name><pointSize>.sf2\\\"\\n\\tfile binary.\\n\\tfile nextInt32Put: 2.\\n\\tfile nextInt32Put: minAscii.\\n\\tfile nextInt32Put: maxAscii.\\n\\tfile nextInt32Put: maxWidth.\\n\\tfile nextInt32Put: ascent.\\n\\tfile nextInt32Put: descent.\\n\\tfile nextInt32Put: pointSize.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\tfile nextInt32Put: emphasis.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | file nextInt32Put: (xTable at: index)].\\n\\tglyphs writeOn: file.\\n\\tfile close.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\naComment\\n\\t\\\"To read Mac font resources. \\n1) 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).\\n2) Open the FOND resource and scroll down to the list of sizes and resource numbers. Note the resource number of the size you want.\\n3) Open the NFNT resource. Click on the number you have noted.\\n4) Choose 'Open Using Hex Editor' from the resource editor.\\n5) 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).\\n6) Enter the fileName below and execute: \\n\\nTextStyle default fontAt: 8 put: (StrikeFont new readMacFontHex: 'fileName').\\n\\nSelect text and type Command-7 to change it to your new font.\\n\\n(There is some problem in the ParagraphEditor with the large size of Cairo 18. Its line heights are not the right.)\\n\\t\\\"! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nfixKerning: extraWidth\\n\\t\\\"Insert one pixel (extraWidth) between each character. And add the bits for the space character\\\"\\n\\t\\\"Create a space character Form. Estimate width by ascent / 2 - 1\\\"\\n\\t| characterForm char leftX |\\n\\tcharacterForm _ Form extent: (ascent//2 - 1) @ self height.\\n\\tself characterFormAt: $ put: characterForm.\\n\\n\\t\\\"Put one pixel of space after every character. Mac fonts have no space in the bitmap.\\\"\\n\\textraWidth <= 0 ifTrue: [^ self].\\n\\tminAscii to: maxAscii do: [:ascii |\\n\\t\\tchar _ Character value: ascii.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\tcharacterForm _ Form extent: \\n\\t\\t\\t((self widthOf: char) + extraWidth) @ self height.\\n\\t\\tcharacterForm \\n\\t\\t\\tcopy: (characterForm boundingBox extendBy: \\n\\t\\t\\t\\t(0-extraWidth@0))\\n\\t\\t\\tfrom: leftX@0 in: glyphs rule: Form over.\\n\\t\\tself characterFormAt: char put: characterForm.\\n\\t\\t].\\t! !\\n\\n!StrikeFont methodsFor: 'Mac reader' stamp: 'ar 5/23/2000 12:49'!\\nreadMacFontHex: fileName\\n\\t\\\"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\\\"\\n\\t| file hh fRectWidth |\\n\\tname _ fileName.\\t\\\"Palatino 12\\\"\\n\\tfile _ FileStream readOnlyFileNamed: fileName, ' hex'.\\n\\n\\t\\\"See Inside Macintosh page IV-42 for this record\\\"\\n\\t\\\"FontType _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\temphasis\\t\\t_\\t\\t0.\\n\\tminAscii _ Number readFrom: (file next: 4) base: 16.\\n\\tmaxAscii _ Number readFrom: (file next: 4) base: 16.\\n\\tmaxWidth\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"kernMax _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\t\\\"NDescent _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\tfRectWidth _ Number readFrom: (file next: 4) base: 16.\\n\\thh _ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"OWTLoc _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\tascent\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\tdescent\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"leading _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\txOffset\\t\\t\\t_\\t\\t0. \\t\\n\\traster\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\n\\tstrikeLength\\t_\\t\\traster*16.\\n\\tsuperscript\\t\\t_\\t\\tascent - descent // 3.\\t\\n\\tsubscript\\t\\t_\\t\\tdescent - ascent // 3.\\t\\n\\tself strikeFromHex: file width: raster height: hh.\\n\\tself xTableFromHex: file.\\n\\tfile close.\\n\\n\\t\\\"Insert one pixel between each character. And add space character.\\\"\\n\\tself fixKerning: (fRectWidth - maxWidth).\\t\\n\\n\\t\\\"Recompute character to glyph mapping\\\"\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nstrikeFromHex: file width: w height: h\\n\\t\\\"read in just the raw strike bits from a hex file. No spaces or returns. W is in words (2 bytes), h in pixels.\\\" \\n\\t| newForm theBits offsetX offsetY str num cnt |\\n\\toffsetX _ 0.\\n\\toffsetY _ 0.\\n\\toffsetX > 32767 ifTrue: [offsetX _ offsetX - 65536]. \\\"stored two's-complement\\\"\\n\\toffsetY > 32767 ifTrue: [offsetY _ offsetY - 65536]. \\\"stored two's-complement\\\"\\n\\tnewForm _ Form extent: strikeLength @ h offset: offsetX @ offsetY.\\n\\ttheBits _ newForm bits.\\n\\tcnt _ 0.\\t\\t\\\"raster may be 16 bits, but theBits width is 32\\\" \\n\\t1 to: theBits size do: [:i | \\n\\t\\t(cnt _ cnt + 32) > strikeLength \\n\\t\\t ifTrue: [cnt _ 0.\\n\\t\\t\\tnum _ Number readFrom: (str _ file next: 4) base: 16]\\n\\t\\t ifFalse: [\\n\\t\\t\\tcnt = strikeLength ifTrue: [cnt _ 0].\\n\\t\\t\\tnum _ Number readFrom: (str _ file next: 8) base: 16].\\n\\t\\ttheBits at: i put: num].\\n\\tglyphs _ newForm.! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nxTableFromHex: file\\n\\n\\t| strike num str wid |\\n\\tstrike _ file.\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | \\n\\t\\t\\tnum _ Number readFrom: (str _ strike next: 4) base: 16. \\n\\t\\t\\txTable at: index put: num].\\n\\n\\t1 to: xTable size - 1 do: [:ind |\\n\\t\\twid _ (xTable at: ind+1) - (xTable at: ind).\\n\\t\\t(wid < 0) | (wid > 40) ifTrue: [\\n\\t\\t\\tfile close.\\n\\t\\t\\tself error: 'illegal character width']].\\n! !\\n\\n\\n!StrikeFont methodsFor: 'make arrows' stamp: 'sps 10/15/2003 17:06'!\\nmakeAssignArrow\\n\\\"Replace the underline character with an arrow for this font\\\"\\n\\n\\t| arrowForm arrowCanvas arrowY arrowLeft arrowRight arrowHeadLength |\\n\\n\\tarrowForm _ (self characterFormAt: $_) copy.\\n\\tarrowCanvas _ arrowForm getCanvas.\\n\\tarrowCanvas fillColor: Color white.\\n\\tarrowY _ arrowForm height // 2.\\n\\tarrowLeft _ 0. \\n\\tarrowRight _ arrowForm width - 2.\\n\\tarrowHeadLength _ (arrowRight - arrowLeft) * 2 // 5.\\n\\t\\\"Draw the lines\\\"\\n\\tarrowCanvas line: (arrowLeft@arrowY) to: (arrowRight@arrowY) color: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowLeft@arrowY) \\n\\t\\tto: ((arrowLeft + arrowHeadLength)@(arrowY - arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowLeft@arrowY) \\n\\t\\tto: ((arrowLeft + arrowHeadLength)@(arrowY + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\n\\t\\\"Replace the glyph\\\"\\n\\tself characterFormAt: $_ put: arrowForm.\\n\\n! !\\n\\n!StrikeFont methodsFor: 'make arrows' stamp: 'sps 10/15/2003 17:06'!\\nmakeReturnArrow\\n\\\"Replace the caret character with an arrow\\\"\\n\\n\\t| arrowForm arrowCanvas arrowHeadLength arrowX arrowTop arrowBottom |\\n\\n\\tarrowForm _ (self characterFormAt: $^) copy.\\n\\tarrowCanvas _ arrowForm getCanvas.\\n\\tarrowCanvas fillColor: Color white.\\n\\n\\tarrowHeadLength _ ((arrowForm width - 2)// 2).\\n\\tarrowX _ (arrowHeadLength max: (arrowForm width // 2)).\\n\\tarrowTop _ arrowForm height // 4. \\n\\tarrowBottom _ (arrowTop + (arrowForm width * 4 // 5 )).\\n\\tarrowBottom _ (arrowBottom min: arrowForm height) max: (arrowForm height * 2 // 3).\\n\\n\\t\\\"Draw the lines\\\"\\n\\tarrowCanvas line: (arrowX@arrowTop) to: (arrowX@arrowBottom) color: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowX@arrowTop) \\n\\t\\tto: ((arrowX - arrowHeadLength)@(arrowTop + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowX@arrowTop) \\n\\t\\tto: ((arrowX + arrowHeadLength)@(arrowTop + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\n\\t\\\"Replace the glyph\\\"\\n\\tself characterFormAt: $^ put: arrowForm.\\n\\n! !\\n\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 3/18/2004 00:10'!\\nfixAccuISO8859From: aStrikeFont\\n\\n\\t| f |\\n\\tself reset.\\n\\txTable _ aStrikeFont xTable copy.\\n\\tglyphs _ Form extent: aStrikeFont glyphs extent.\\n\\tmaxAscii _ 255.\\n\\tminAscii _ 0.\\n\\t\\\"stopConditions _ nil.\\\"\\n\\n\\t0 to: 127 do: [:i |\\n\\t\\tf _ aStrikeFont characterFormAt: (Character value: i) isoToSqueak.\\n\\t\\tf width = 0 ifTrue: [f _ Form extent: 1@f height].\\n\\t\\t\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t128 to: 159 do: [:i |\\n\\t\\tf _ Form extent: 1@f height.\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t160 to: 255 do: [:i |\\n\\t\\tf _ aStrikeFont characterFormAt: (Character value: i) isoToSqueak.\\n\\t\\tf width = 0 ifTrue: [f _ Form extent: 1@f height].\\n\\t\\t\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t\\t\\n\\t^ self.\\t\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 11/12/2002 12:56'!\\nfixAscent: a andDescent: d head: h\\n\\n\\t| bb newGlyphs |\\n\\t\\\"(a + d) = (ascent + descent) ifTrue: [\\\"\\n\\t\\tascent _ a.\\n\\t\\tdescent _ d.\\n\\t\\tnewGlyphs _ Form extent: (glyphs width@(h + glyphs height)).\\n\\t\\tbb _ BitBlt toForm: newGlyphs.\\n\\t\\tbb copy: (0@h extent: (glyphs extent)) from: 0@0 in: glyphs\\n\\t\\t\\tfillColor: nil rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\\"].\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 9/16/2002 15:07'!\\nfixForISO8859From: aStrikeFont\\n\\n\\t| fixer m mappingTable |\\n\\tfixer _ StrikeFontFixer newOn: aStrikeFont.\\n\\tself reset.\\n\\txTable _ aStrikeFont xTable copy.\\n\\tglyphs _ Form extent: aStrikeFont glyphs extent.\\n\\tmaxAscii _ 255.\\n\\tminAscii _ 0.\\n\\tmappingTable _ fixer mappingTable.\\n\\t\\\"stopConditions _ nil.\\\"\\n\\n\\t0 to: 255 do: [:i |\\n\\t\\t(m _ mappingTable at: i+1) ~= nil ifTrue: [\\n\\t\\t\\tself characterFormAt: (Character value: i)\\n\\t\\t\\t\\tput: (aStrikeFont characterFormAt: (Character value: m)).\\n\\t\\t] ifFalse: [\\n\\t\\t\\tself characterFormAt: (Character value: i)\\n\\t\\t\\t\\tput: (aStrikeFont characterFormAt: (Character space)).\\n\\t\\t]\\n\\t].\\n\\t^self.\\t\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 8/28/2002 16:35'!\\nfixXTable\\n\\n\\t| newXTable val |\\n\\txTable size >= 258 ifTrue: [\\n\\t\\t^ self.\\n\\t].\\n\\n\\tnewXTable _ Array new: 258.\\n\\t1 to: xTable size do: [:i |\\n\\t\\tnewXTable at: i put: (xTable at: i).\\n\\t].\\n\\n\\tval _ xTable at: (xTable size).\\n\\t\\n\\txTable size + 1 to: 258 do: [:i |\\n\\t\\tnewXTable at: i put: val.\\n\\t].\\n\\tminAscii _ 0.\\n\\tmaxAscii _ 255.\\n\\txTable _ newXTable.\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 1/6/2005 04:18'!\\nhasGlyphOf: aCharacter\\n\\n\\t| code |\\n\\tcode _ aCharacter charCode.\\n\\t((code between: self minAscii and: self maxAscii) not) ifTrue: [\\n\\t\\t^ false.\\n\\t].\\n\\t(xTable at: code + 1) < 0 ifTrue: [\\n\\t\\t^ false.\\n\\t].\\n\\t^ true.\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 8/28/2002 16:37'!\\nreadCharacter: aBits from: aStream\\n\\n\\t| pos |\\n\\tpos _ 0.\\n\\t12 timesRepeat: [\\n\\t\\t1 to: 2 do: [ :w |\\n\\t\\t\\taBits byteAt: (pos+w) put: (aStream next ). \\n\\t\\t].\\n\\t\\tpos _ pos + 4.\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 5/24/2004 23:11'!\\nsetupDefaultFallbackFont\\n\\n\\t| fonts f |\\n\\tfonts _ TextStyle default fontArray.\\n\\tf _ fonts first.\\n\\t1 to: fonts size do: [:i |\\n\\t\\tself height > (fonts at: i) height ifTrue: [f _ fonts at: i].\\n\\t].\\n\\tself fallbackFont: f.\\n\\tself reset.\\n\\n! !\\n\\n\\n!StrikeFont methodsFor: 'testing'!\\ncheckCharacter: character \\n\\t\\\"Answer a Character that is within the ascii range of the receiver--either \\n\\tcharacter or the last character in the receiver.\\\"\\n\\n\\t| ascii | \\n\\tascii _ character asciiValue.\\n\\t((ascii < minAscii) or: [ascii > maxAscii])\\n\\t\\t\\tifTrue: [^maxAscii asCharacter]\\n\\t\\t\\tifFalse:\\t[^character]\\n! !\\n\\n\\n!StrikeFont methodsFor: '*nebraska-file in/out' stamp: 'yo 12/17/2005 20:36'!\\nencodedForRemoteCanvas\\n\\n\\t| stream |\\n\\tstream := RWBinaryOrTextStream on: ''.\\n\\tstream nextPutAll: self familyName.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self name.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self height.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self emphasis asString.\\n\\t^ stream contents asString.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'private' stamp: 'yo 3/11/2005 07:38'!\\ncreateCharacterToGlyphMap\\n \\\"Private. Create the character to glyph mapping for a font that didn't have any before. This is basically equivalent to what the former setStopCondition did, only based on indexes.\\\"\\n\\n maxAscii < 256 ifTrue: [^ (1 to: 256) collect: [:i | i - 1]].\\n ^ nil.\\n! !\\n\\n!StrikeFont methodsFor: 'private' stamp: 'yo 5/20/2004 10:51'!\\nleftAndRighOrNilFor: char\\n\\n\\t| code leftX |\\n\\tcode _ char charCode.\\n\\t((code between: self minAscii and: self maxAscii) not) ifTrue: [\\n\\t\\tcode _ $? charCode.\\n\\t].\\n\\tleftX _ xTable at: code + 1.\\n\\tleftX < 0 ifTrue: [\\n\\t\\tcode _ $? charCode.\\n\\t\\tleftX _ xTable at: code + 1.\\n\\t].\\n\\t^ Array with: leftX with: (xTable at: code + 2).\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFont class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'nk 9/1/2004 11:00'!\\nactualFamilyNames\\n\\t\\\"Answer a sorted list of actual family names, without the Default aliases\\\"\\n\\n\\t^(self familyNames copyWithoutAll: TextStyle defaultFamilyNames) asOrderedCollection! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'ar 2/3/2002 23:04'!\\nfamilyName: aName pointSize: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\n\\t^ ((TextStyle named: aName asSymbol) ifNil: [TextStyle default]) fontOfPointSize: aSize! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'ar 11/25/2004 15:19'!\\nfamilyName: aName size: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\t| style |\\n\\tstyle := TextStyle named: aName asSymbol.\\n\\tstyle ifNil: [^(FontSubstitutionDuringLoading forFamilyName: aName pixelSize: aSize)\\n\\t\\t\\tsignal: 'missing font' ].\\n\\t^style fontOfSize: aSize! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'sma 12/30/1999 13:48'!\\nfamilyNames\\n\\t^ (TextConstants select: [:each | each isKindOf: TextStyle]) keys asSortedCollection! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'tak 11/11/2004 21:14'!\\nsetupDefaultFallbackFont\\n\\\"\\n\\tStrikeFont setupDefaultFallbackFont\\n\\\"\\n\\n\\t(#(#Accuat #Accujen #Accula #Accumon #Accusf #Accushi #Accuve #Atlanta) collect: [:e | TextStyle named: e]) do: [:style |\\n\\t\\tstyle fontArray do: [:e |\\n\\t\\t\\te reset.\\n\\t\\t\\te setupDefaultFallbackFont.\\n\\t\\t].\\n\\t].\\n\\tTTCFont allSubInstances\\n\\t\\tdo: [:font | font reset.\\n\\t\\t\\tfont setupDefaultFallbackFont]\\n\\n! !\\n\\n\\n!StrikeFont class methodsFor: 'derivative font caching' stamp: 'tak 3/11/2005 16:27'!\\nshutDown \\\"StrikeFont shutDown\\\"\\n\\t\\\"Deallocate synthetically derived copies of base fonts to save space\\\"\\n\\tself allSubInstancesDo: [:sf | sf reset].\\n\\tStrikeFontSet allSubInstancesDo: [:sf | sf reset].\\n\\tDefaultStringScanner _ nil.\\n! !\\n\\n\\n!StrikeFont class methodsFor: 'examples'!\\nconvertFontsNamed: familyName \\\" StrikeFont convertFontsNamed: 'NewYork' \\\"\\n\\t\\\"This utility is for use after you have used BitFont to produce data files \\n\\tfor the fonts you wish to use. It will read the BitFont files and then \\n\\twrite them out in strike2 (*.sf2) format which is much more compact,\\n\\tand which can be read in again very quickly.\\\"\\n\\t\\\"For this utility to work as is, the BitFont data files must be named\\n\\t'familyNN.BF', and must reside in the same directory as the image.\\\"\\n\\t| f |\\n\\t(FileDirectory default fileNamesMatching: familyName , '*.BF') do:\\n\\t\\t[:fname | Transcript cr; show: fname.\\n\\t\\tf _ StrikeFont new readFromBitFont: fname.\\n\\t\\tf writeAsStrike2named: f name , '.sf2']! !\\n\\n!StrikeFont class methodsFor: 'examples'!\\nexample\\n\\t\\\"Displays a line of text on the display screen at the location of the cursor.\\n\\tExample depends on the strike font file, 'TimesRoman10.strike'. existing.\\\"\\n\\n\\t(StrikeFont new readFromStrike2: 'NewYork12.sf2')\\n\\t\\tdisplayLine: 'A line of 12-pt text in New York style' at: Sensor cursorPoint\\n\\t \\n\\t\\\"StrikeFont example.\\\"! !\\n\\n!StrikeFont class methodsFor: 'examples' stamp: 'tpr 6/10/2005 16:07'!\\nreadStrikeFont2Family: familyName \\n\\t\\\"StrikeFont readStrikeFont2Family: 'Lucida'\\\"\\n\\t^self readStrikeFont2Family: familyName fromDirectory: FileDirectory default! !\\n\\n!StrikeFont class methodsFor: 'examples' stamp: 'tpr 6/10/2005 16:07'!\\nreadStrikeFont2Family: familyName fromDirectory: aDirectory\\n\\t\\\"StrikeFont readStrikeFont2Family: 'Lucida' fromDirectory: FileDirectory default\\\"\\n\\t\\\"This utility reads all available .sf2 StrikeFont files for a given family from \\n\\tthe current directory. It returns an Array, sorted by size, suitable for handing \\n\\tto TextStyle newFontArray: .\\\"\\n\\t\\\"For this utility to work as is, the .sf2 files must be named 'familyNN.sf2'.\\\"\\n\\t| fileNames strikeFonts fontArray |\\n\\tfileNames _ aDirectory fileNamesMatching: familyName , '##.sf2'.\\n\\tstrikeFonts _ fileNames collect: [:fname | StrikeFont new readFromStrike2: fname].\\n\\tstrikeFonts do: [ :font | font reset ].\\n\\tstrikeFonts _ strikeFonts asSortedCollection: [:a :b | a height < b height].\\n\\tfontArray _ strikeFonts asArray.\\n\\t^ fontArray\\n\\n\\\"TextConstants at: #Lucida put: (TextStyle fontArray: (StrikeFont \\n\\treadStrikeFont2Family: 'Lucida')).\\\"! !\\n\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:27'!\\nfromHostFont: fontName size: fontSize flags: fontFlags weight: fontWeight\\n\\t\\\"\\n\\t\\t^StrikeFont fromHostFont: (StrikeFont hostFontFromUser)\\n\\t\\t\\t\\t\\tsize: 12 flags: 0 weight: 4.\\n\\t\\\"\\n\\t| fontHandle glyphs xTable xStart maxWidth w glyphForm ascent descent fontHeight |\\n\\tfontHandle _ self primitiveCreateFont: fontName size: fontSize flags: fontFlags weight: fontWeight.\\n\\tascent _ self primitiveFontAscent: fontHandle.\\n\\tdescent _ self primitiveFontDescent: fontHandle.\\n\\tfontHeight _ ascent + descent.\\n\\txTable _ Array new: 258.\\n\\txStart _ maxWidth _ 0.\\n\\t0 to: 255 do:[:i|\\n\\t\\txTable at: i+1 put: xStart.\\n\\t\\tw _ self primitiveFont: fontHandle widthOfChar: i.\\n\\t\\tw > maxWidth ifTrue:[maxWidth _ w].\\n\\t\\txStart _ xStart + w].\\n\\txTable at: 256 put: xStart.\\n\\txTable at: 257 put: xStart.\\n\\txTable at: 258 put: xStart.\\n\\tglyphs _ Form extent: xTable last @ fontHeight depth: 1.\\n\\tglyphForm _ Form extent: maxWidth @ fontHeight depth: 1.\\n\\t0 to: 255 do:[:i|\\n\\t\\tglyphForm fillWhite.\\n\\t\\tself primitiveFont: fontHandle glyphOfChar: i into: glyphForm.\\n\\t\\txStart _ xTable at: i+1.\\n\\t\\tglyphForm displayOn: glyphs at: xStart@0.\\n\\t\\tglyphForm displayOn: Display at: xStart@0.\\n\\t].\\n\\tself primitiveDestroyFont: fontHandle.\\n\\t^Array with: glyphs with: xTable! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'rbb 2/18/2005 13:21'!\\nhostFontFromUser\\n\\t\\\"StrikeFont hostFontFromUser\\\"\\n\\t| fontNames index labels |\\n\\tfontNames _ self listFontNames asSortedCollection.\\n\\tlabels _ WriteStream on: (String new: 100).\\n\\tfontNames do:[:fn| labels nextPutAll: fn] separatedBy:[labels cr].\\n\\tindex _ (UIManager default chooseFrom: (labels contents substrings) \\n\\t\\t\\t\\ttitle: 'Choose your font').\\n\\tindex = 0 ifTrue:[^nil].\\n\\t^fontNames at: index! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:12'!\\nlistFont: index\\n\\t<primitive:'primitiveListFont' module:'FontPlugin'>\\n\\t^nil! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:12'!\\nlistFontNames\\n\\t\\\"StrikeFont listFontNames\\\"\\n\\t\\\"List all the OS font names\\\"\\n\\t| font fontNames index |\\n\\tfontNames _ WriteStream on: Array new.\\n\\tindex _ 0.\\n\\t[font _ self listFont: index.\\n\\tfont == nil] whileFalse:[\\n\\t\\tfontNames nextPut: font.\\n\\t\\tindex _ index + 1].\\n\\t^fontNames contents! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'tak 8/3/2005 21:11'!\\nlocaleChanged\\n\\tself setupDefaultFallbackFont! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:13'!\\nprimitiveCreateFont: fontName size: fontSize flags: fontFlags weight: fontWeight\\n\\t<primitive:'primitiveCreateFont' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:13'!\\nprimitiveDestroyFont: fontHandle\\n\\t<primitive:'primitiveDestroyFont' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:14'!\\nprimitiveFont: fontHandle glyphOfChar: charIndex into: glyphForm\\n\\t<primitive:'primitiveFontGlyphOfChar' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:15'!\\nprimitiveFont: fontHandle widthOfChar: charIndex\\n\\t<primitive:'primitiveFontWidthOfChar' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:25'!\\nprimitiveFontAscent: fontHandle\\n\\t<primitive:'primitiveFontAscent' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:25'!\\nprimitiveFontDescent: fontHandle\\n\\t<primitive:'primitiveFontDescent' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:14'!\\nprimitiveFontEncoding: fontHandle\\n\\t<primitive:'primitiveFontEncoding' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'ar 2/3/2002 23:06'!\\nfamilyName: aName pointSize: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName pointSize: aSize) emphasized: emphasisCode! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'tk 1/28/1999 11:31'!\\nfamilyName: aName size: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName size: aSize) emphasized: emphasisCode! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 3/18/2004 00:10'!\\nfixAccuISO8859From: aStrikeFont\\n\\n\\t^aStrikeFont copy fixAccuISO8859From: aStrikeFont.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 9/16/2002 15:55'!\\nfixForISO8859From: aStrikeFont\\n\\n\\t^aStrikeFont copy fixForISO8859From: aStrikeFont.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation'!\\nfromStrike: fileName \\n\\t\\\"Read a font from disk in the old ST-80 'strike' format.\\n\\tNote: this is an old format; use strike2 format instead\\\"\\n\\n\\t^self new newFromStrike: fileName! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'ar 1/5/2002 21:41'!\\nfromUser\\n\\t\\\"StrikeFont fromUser\\\"\\n\\t^self fromUser: TextStyle defaultFont! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nk 9/1/2004 14:29'!\\nfromUser: priorFont\\n\\t^self fromUser: priorFont allowKeyboard: true! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nk 9/1/2004 14:28'!\\nfromUser: priorFont allowKeyboard: aBoolean\\n\\t\\\"rr 3/23/2004 10:02 : made the menu invoked modally, thus allowing\\n\\tkeyboard control\\\" \\n\\t\\\"StrikeFont fromUser\\\"\\n\\t\\\"Present a menu of available fonts, and if one is chosen, return it.\\n\\tOtherwise return nil.\\\"\\n\\n\\t| fontList fontMenu style active ptMenu label spec font |\\n\\tfontList _ StrikeFont actualFamilyNames.\\n\\tfontMenu _ MenuMorph new defaultTarget: self.\\n\\tfontList do: [:fontName |\\n\\t\\tstyle _ TextStyle named: fontName.\\n\\t\\tactive _ priorFont familyName sameAs: fontName.\\n\\t\\tptMenu _ MenuMorph new defaultTarget: self.\\n\\t\\tstyle pointSizes do: [:pt |\\n\\t\\t\\t(active and:[pt = priorFont pointSize]) \\n\\t\\t\\t\\tifTrue:[label _ '<on>'] \\n\\t\\t\\t\\tifFalse:[label _ '<off>'].\\n\\t\\t\\tlabel _ label, pt printString, ' pt'.\\n\\t\\t\\tptMenu add: label \\n\\t\\t\\t\\ttarget: fontMenu\\n\\t\\t\\t\\tselector: #modalSelection:\\n\\t\\t\\t\\targument: {fontName. pt}].\\n\\t\\tstyle isTTCStyle ifTrue: [\\n\\t\\t\\tptMenu add: 'new size'\\n\\t\\t\\t\\ttarget: style selector: #addNewFontSizeDialog: argument: {fontName. fontMenu}.\\n\\t\\t].\\n\\t\\tactive ifTrue:[label _ '<on>'] ifFalse:[label _ '<off>'].\\n\\t\\tlabel _ label, fontName.\\n\\t\\tfontMenu add: label subMenu: ptMenu].\\n\\tspec _ fontMenu invokeModalAt: ActiveHand position in: ActiveWorld allowKeyboard: aBoolean.\\n\\tspec ifNil: [^ nil].\\n\\tstyle _ TextStyle named: spec first.\\n\\tstyle ifNil: [^ self].\\n\\tfont _ style fonts detect: [:any | any pointSize = spec last] ifNone: [nil].\\n\\t^ font! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 8/5/2003 13:11'!\\nnewForJapaneseFromEFontBDFFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFForJapaneseFromFile: fileName name: aString overrideWith: otherFileName.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 1/15/2004 16:48'!\\nnewForKoreanFromEFontBDFFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFForKoreanFromFile: fileName name: aString overrideWith: otherFileName.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nop 1/23/2000 19:21'!\\nnewFromBDFFile: aFileName name: aString \\\"StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'\\\"\\n\\t\\\"Read a font from disk in the X11 Bitmap Distribution Format.\\\"\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readBDFFromFile: aFileName name: aString.\\n\\t^n.\\n\\n\\t\\\"TextConstants at: #Helvetica put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'})\\\"\\n\\t\\\"TextConstants at: #Lucida put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'luRS12.bdf' name: 'Lucida'})\\\"\\n\\t\\\"TextStyle default fontAt: 5 put: (StrikeFont new readFromStrike2: 'helv12.sf2').\\\"\\n\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 1/19/2005 11:22'!\\nnewFromEFontBDFFile: fileName name: aString ranges: ranges\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFFromFile: fileName name: aString ranges: ranges.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 12/27/2002 16:57'!\\nnewFromEFontBDFFile: aFileName name: aString startRange: start endRange: end\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFFromFile: aFileName name: aString rangeFrom: start to: end.\\n\\t^n.\\n\\n\\t\\\"TextConstants at: #Helvetica put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'})\\\"\\n\\t\\\"TextConstants at: #Lucida put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'luRS12.bdf' name: 'Lucida'})\\\"\\n\\t\\\"TextStyle default fontAt: 5 put: (StrikeFont new readFromStrike2: 'helv12.sf2').\\\"\\n\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 9/23/2002 16:28'!\\nnewFromF12File: aFileName\\n\\t\\\"StrikeFont newFromF12File: 'kaname.f12'\\\"\\n\\n\\t| file n |\\n\\t('*.F12' match: aFileName) ifFalse: [\\\"self halt. \\\" \\\"likely incompatible\\\"].\\n\\tfile _ FileStream readOnlyFileNamed: aFileName.\\n\\tfile binary.\\n\\tn _ self new.\\n\\tn name: (FileDirectory baseNameFor: (FileDirectory localNameFor: aFileName)).\\n\\tn readF12FromStream: file.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'tak 12/20/2004 10:23'!\\npasswordFontSize: aSize \\n\\t^ FixedFaceFont new passwordFont fontSize: aSize! !\\n\\n\\n!StrikeFont class methodsFor: '*nebraska-instance creation' stamp: 'yo 12/17/2005 22:41'!\\ndecodedFromRemoteCanvas: aString\\n\\n\\t| array style base |\\n\\tarray _ aString findTokens: #($ ).\\n\\tstyle _ TextStyle named: (array at: 1) asSymbol.\\n\\tstyle ifNil: [^ TextStyle defaultFont].\\n\\t(style fontArray first name = style fontArray first name withoutTrailingDigits) ifTrue: [\\n\\t\\t\\t^ self familyName: (array at: 1) size: (array at: 3) asNumber emphasized: (array at: 4) asNumber].\\n\\tbase _ style fontArray detect: [:f | (array at: 2) beginsWith: f name].\\n\\t^ base emphasized: (array at: 4) asNumber.\\n\\n\\t\\\"^ self familyName: (array at: 1) size: (array at: 2) asNumber emphasized: (array at: 3) asNumber.\\\"\\n! !\\nObject subclass: #StrikeFontFixer\\n\\tinstanceVariableNames: 'strikeFont charForms newFont'\\n\\tclassVariableNames: 'MappingTable NoFontTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\ncharacterFormAt: aCharacter at: aPoint\\n\\n\\t| f |\\n\\tf _ charForms at: aCharacter asciiValue + 1.\\n\\t(f magnifyBy: 3) displayAt: aPoint.\\n\\t^ f.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\ndisplayOn: aDisplayObject at: aPoint magnifyBy: aNumber\\n\\n\\t| form hStep vStep bb source nextPoint |\\n\\thStep _ (strikeFont maxWidth * aNumber * 1.2) asInteger.\\n\\tvStep _ (strikeFont height * aNumber * 1.2) asInteger.\\n\\t\\n\\tform _ Form extent: (hStep * 16)@(vStep * 16).\\n\\tbb _ BitBlt toForm: form.\\n\\t0 to: 15 do: [:i |\\n\\t\\t1 to: 16 do: [:j |\\n\\t\\t\\tsource _ ((charForms at: (i * 16 + j)) magnifyBy: aNumber).\\n\\t\\t\\tnextPoint _ (hStep * (j - 1)@(vStep * i)).\\n\\t\\t\\tbb copy: ((nextPoint+((hStep@vStep - source extent) // 2)) extent: source extent)\\n\\t\\t\\t\\tfrom: 0@0 in: source fillColor: Color black rule: Form over.\\n\\t\\t].\\n\\t].\\n\\tform displayOn: aDisplayObject at: aPoint.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\nfont: aStrikeFont\\n\\n\\tstrikeFont _ aStrikeFont.\\n\\tself forms.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nforms\\n\\n\\t1 to: 256 do: [:i |\\n\\t\\tcharForms at: i put: (strikeFont characterFormAt: (Character value: (i - 1)))\\n\\t].\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\ninitialize\\n\\n\\tcharForms _ Array new: 256.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nmappingTable\\n\\n\\t^ MappingTable.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nstoreEditedGlyphsOn: aStream\\n\\n\\t| n |\\n\\tNoFontTable do: [:i |\\n\\t\\tn _ strikeFont name.\\n\\t\\t(n beginsWith: 'NewYork') ifTrue: [n _ 'NewYork'].\\n\\t\\taStream nextPutAll: '((StrikeFont familyName: ''', n, ''' size: ',\\n\\t\\t\\tstrikeFont height asString, ')'.\\n\\t\\taStream nextPutAll: ' characterFormAt: '.\\n\\t\\taStream nextPutAll: '(Character value: ', i asString, ')'.\\n\\t\\taStream nextPutAll: ' put: '.\\n\\t\\t(strikeFont characterFormAt: (Character value: i)) storeOn: aStream base: 2.\\n\\t\\taStream nextPutAll: ')!!'.\\n\\t\\taStream nextPut: Character cr.\\n\\t\\taStream nextPut: Character cr.\\n\\t].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFontFixer class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:06'!\\ninitialize\\n\\\"\\n\\tStrikeFontFixer initialize\\n\\\"\\n\\n\\t| d |\\n\\tself initializeNoFontTable.\\n\\td _ Array new: 256.\\n\\t0 to: 127 do: [:i | d at: i+1 put: i].\\n\\t16r80 to: 16r9F do: [:i | d at: i+1 put: nil].\\n\\td at: 16rA0+1 put: 16r20.\\n\\td at: 16rA1+1 put: 16rC1.\\n\\td at: 16rA2+1 put: 16rA2.\\n\\td at: 16rA3+1 put: 16rA3.\\n\\td at: 16rA4+1 put: 16rA9. \\\"CURRENCY SIGN\\\"\\n\\td at: 16rA5+1 put: 16rB4.\\n\\td at: 16rA6+1 put: 16r7C. \\\"BROKEN BAR\\\"\\n\\td at: 16rA7+1 put: 16rA4.\\n\\td at: 16rA8+1 put: 16r80. \\\"DIAERESIS\\\"\\n\\td at: 16rA9+1 put: 16rA9.\\n\\td at: 16rAA+1 put: 16rBB.\\n\\td at: 16rAB+1 put: 16rC7.\\n\\td at: 16rAC+1 put: 16rD1. \\\"NOT SIGN\\\"\\n\\td at: 16rAD+1 put: 16rD0.\\n\\td at: 16rAE+1 put: 16rA8.\\n\\td at: 16rAF+1 put: 16rD1. \\\"MACRON\\\"\\n\\td at: 16rB0+1 put: 16rA1.\\n\\td at: 16rB1+1 put: 16r2B. \\\"PLUS-MINUS SIGN\\\"\\n\\td at: 16rB2+1 put: 16rAB. \\\"SUPERSCRIPT TWO\\\"\\n\\td at: 16rB3+1 put: 16rAB. \\\"SUPERSCRIPT THREE\\\"\\n\\td at: 16rB4+1 put: 16rAB.\\n\\td at: 16rB5+1 put: 16r75. \\\"MICRO SIGN\\\"\\n\\td at: 16rB6+1 put: 16rA6.\\n\\td at: 16rB7+1 put: 16rA5.\\n\\td at: 16rB8+1 put: 16r82. \\\"CEDILLA\\\"\\n\\td at: 16rB9+1 put: 16rAB. \\\"SUPERSCRIPT ONE\\\"\\n\\td at: 16rBA+1 put: 16rBC.\\n\\td at: 16rBB+1 put: 16rC8.\\n\\td at: 16rBC+1 put: 16r4D. \\\"VULGAR FRACTION ONE QUARTER\\\"\\n\\td at: 16rBD+1 put: 16r4D. \\\"VULGAR FRACTIOIN ONE HALF\\\"\\n\\td at: 16rBE+1 put: 16r4D. \\\"VALGAR FRACTION THREE QUARTERS\\\"\\n\\td at: 16rBF+1 put: 16rC0.\\n\\td at: 16rC0+1 put: 16rCB.\\n\\td at: 16rC1+1 put: 16rCB. \\\"CAPITAL A WITH ACUTE\\\"\\n\\td at: 16rC2+1 put: 16rCB. \\\"CAPITAL A WITH CIRCUMFLEX\\\"\\n\\td at: 16rC3+1 put: 16rCC.\\n\\td at: 16rC4+1 put: 16r80.\\n\\td at: 16rC5+1 put: 16r81.\\n\\td at: 16rC6+1 put: 16rAE.\\n\\td at: 16rC7+1 put: 16r82.\\n\\td at: 16rC8+1 put: 16r83. \\\"CAPITAL E WITH GRAVE\\\"\\n\\td at: 16rC9+1 put: 16r83.\\n\\td at: 16rCA+1 put: 16r83. \\\"CAPITAL E WITH CIRCUMFLEX\\\"\\n\\td at: 16rCB+1 put: 16r83. \\\"CAPITAL E WITH DIAERESIS\\\"\\n\\td at: 16rCC+1 put: 16r49. \\\"CAPITAL I WITH GRAVE\\\"\\n\\td at: 16rCD+1 put: 16r49. \\\"CAPITAL I WITH ACUTE\\\"\\n\\td at: 16rCE+1 put: 16r49. \\\"CAPITAL I WITH CIRCUMFLEX\\\"\\n\\td at: 16rCF+1 put: 16r49. \\\"CAPITAL I WITH DIAERESIS\\\"\\n\\td at: 16rD0+1 put: 16r44. \\\"CAPITAL ETH\\\"\\n\\td at: 16rD1+1 put: 16r84.\\n\\td at: 16rD2+1 put: 16rCD. \\\"CAPITAL O WITH GRAVE\\\"\\n\\td at: 16rD3+1 put: 16rCD. \\\"CAPITAL O WITH ACUTE\\\"\\n\\td at: 16rD4+1 put: 16rCD. \\\"CAPITAL O WITH CIRCUMFLEX\\\"\\n\\td at: 16rD5+1 put: 16rCD.\\n\\td at: 16rD6+1 put: 16r85.\\n\\td at: 16rD7+1 put: 16r2B. \\\"MULTIPLICATION SIGN\\\"\\n\\td at: 16rD8+1 put: 16rBF.\\n\\td at: 16rD9+1 put: 16r86. \\\"CAPITAL U WITH GRAVE\\\"\\n\\td at: 16rDA+1 put: 16r86. \\\"CAPITAL U WITH ACUTE\\\"\\n\\td at: 16rDB+1 put: 16r86. \\\"CAPITAL U WITH CIRCUMFLEX\\\"\\n\\td at: 16rDC+1 put: 16r86. \\\"CAPTIAL U WITH DIAERESIS\\\"\\n\\td at: 16rDD+1 put: 16r59. \\\"CAPITAL Y WITH ACUTE\\\"\\n\\td at: 16rDE+1 put: 16r50. \\\"CAPITAL THORN\\\"\\n\\td at: 16rDF+1 put: 16rA7.\\n\\td at: 16rE0+1 put: 16r88.\\n\\td at: 16rE1+1 put: 16r87.\\n\\td at: 16rE2+1 put: 16r89.\\n\\td at: 16rE3+1 put: 16r8B.\\n\\td at: 16rE4+1 put: 16r8A.\\n\\td at: 16rE5+1 put: 16r8C.\\n\\td at: 16rE6+1 put: 16rBE.\\n\\td at: 16rE7+1 put: 16r8D.\\n\\td at: 16rE8+1 put: 16r8F.\\n\\td at: 16rE9+1 put: 16r8E.\\n\\td at: 16rEA+1 put: 16r90.\\n\\td at: 16rEB+1 put: 16r91.\\n\\td at: 16rEC+1 put: 16r93.\\n\\td at: 16rED+1 put: 16r92.\\n\\td at: 16rEE+1 put: 16r94.\\n\\td at: 16rEF+1 put: 16r95.\\n\\td at: 16rF0+1 put: 16r64. \\\"SMALL ETH\\\"\\n\\td at: 16rF1+1 put: 16r96.\\n\\td at: 16rF2+1 put: 16r98.\\n\\td at: 16rF3+1 put: 16r97.\\n\\td at: 16rF4+1 put: 16r99.\\n\\td at: 16rF5+1 put: 16r9B.\\n\\td at: 16rF6+1 put: 16r9A.\\n\\td at: 16rF7+1 put: 16r2D. \\\"DIVISION SIGN\\\"\\n\\td at: 16rF8+1 put: 16rBF.\\n\\td at: 16rF9+1 put: 16r9D.\\n\\td at: 16rFA+1 put: 16r9C.\\n\\td at: 16rFB+1 put: 16r9E.\\n\\td at: 16rFC+1 put: 16r9F.\\n\\td at: 16rFD+1 put: 16rD8. \\\"SMALL Y WITH ACUTE\\\"\\n\\td at: 16rFE+1 put: 16r70. \\\"SMALL THORN\\\"\\n\\td at: 16rFF+1 put: 16rD8.\\n\\n\\tMappingTable _ d.\\n! !\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:05'!\\ninitializeNoFontTable\\n\\n\\t| n |\\n\\tn _ #(\\n\\t16rA4 \\\"CURRENCY SIGN\\\"\\n\\t16rA6 \\\"BROKEN BAR\\\"\\n\\t16rA8 \\\"DIAERESIS\\\"\\n\\t16rAC \\\"NOT SIGN\\\"\\n\\t16rAF \\\"MACRON\\\"\\n\\t16rB1 \\\"PLUS-MINUS SIGN\\\"\\n\\t16rB2 \\\"SUPERSCRIPT TWO\\\"\\n\\t16rB3 \\\"SUPERSCRIPT THREE\\\"\\n\\t16rB5 \\\"MICRO SIGN\\\"\\n\\t16rB8 \\\"CEDILLA\\\"\\n\\t16rB9 \\\"SUPERSCRIPT ONE\\\"\\n\\t16rBC \\\"VULGAR FRACTION ONE QUARTER\\\"\\n\\t16rBD \\\"VULGAR FRACTIOIN ONE HALF\\\"\\n\\t16rBE \\\"VALGAR FRACTION THREE QUARTERS\\\"\\n\\t16rC1 \\\"CAPITAL A WITH ACUTE\\\"\\n\\t16rC2 \\\"CAPITAL A WITH CIRCUMFLEX\\\"\\n\\t16rC8 \\\"CAPITAL E WITH GRAVE\\\"\\n\\t16rCA \\\"CAPITAL E WITH CIRCUMFLEX\\\"\\n\\t16rCB \\\"CAPITAL E WITH DIAERESIS\\\"\\n\\t16rCC \\\"CAPITAL I WITH GRAVE\\\"\\n\\t16rCD \\\"CAPITAL I WITH ACUTE\\\"\\n\\t16rCE \\\"CAPITAL I WITH CIRCUMFLEX\\\"\\n\\t16rCF \\\"CAPITAL I WITH DIAERESIS\\\"\\n\\t16rD0 \\\"CAPITAL ETH\\\"\\n\\t16rD2 \\\"CAPITAL O WITH GRAVE\\\"\\n\\t16rD3 \\\"CAPITAL O WITH ACUTE\\\"\\n\\t16rD4 \\\"CAPITAL O WITH CIRCUMFLEX\\\"\\n\\t16rD7 \\\"MULTIPLICATION SIGN\\\"\\n\\t16rD9 \\\"CAPITAL U WITH GRAVE\\\"\\n\\t16rDA \\\"CAPITAL U WITH ACUTE\\\"\\n\\t16rDB \\\"CAPITAL U WITH CIRCUMFLEX\\\"\\n\\t16rDD \\\"CAPITAL Y WITH ACUTE\\\"\\n\\t16rDE \\\"CAPITAL THORN\\\"\\n\\t16rF0 \\\"SMALL ETH\\\"\\n\\t16rF7 \\\"DIVISION SIGN\\\"\\n\\t16rFD \\\"SMALL Y WITH ACUTE\\\"\\n\\t16rFE \\\"SMALL THORN\\\"\\n\\t).\\n\\tNoFontTable _ n.\\n\\n! !\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'nk 7/30/2004 18:09'!\\nnewOn: aStrikeFont \\n\\t^self new font: aStrikeFont! !\\nAbstractFont subclass: #StrikeFontSet\\n\\tinstanceVariableNames: 'fontArray emphasis derivativeFonts name rIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nascentOf: aCharacter\\n\\t^(self fontOf: aCharacter) ascent! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\ndescentOf: aCharacter\\n\\t^(self fontOf: aCharacter) descent! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 9/23/2002 20:08'!\\nfontArray\\n\\n\\t^ fontArray\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nfontOf: aCharacter\\n\\t\\\"Answer the actual font to use for aCharacter\\\"\\n\\t^self fontOf: aCharacter ifAbsent:[fontArray at: 1]! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nfontOf: aCharacter ifAbsent: aBlock\\n\\t\\\"Answer the actual font to use for aCharacter\\\"\\n\\t| encoding font |\\n\\tencoding := aCharacter leadingChar + 1.\\n\\tencoding <= fontArray size \\n\\t\\tifTrue:[font := fontArray at: encoding].\\n\\tfont ifNil:[^aBlock value].\\n\\t^font\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\nheightOf: aCharacter\\n\\t^(self fontOf: aCharacter) height! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'tak 12/21/2004 16:43'!\\nlatin1\\n\\t\\\"Answer primary font\\\"\\n\\t^ fontArray at: 1! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 11/15/2002 14:22'!\\nmaxAsciiFor: encoding\\n\\n\\t| f |\\n\\tf _ (fontArray at: encoding+1).\\n\\tf ifNotNil: [^ f maxAscii].\\n\\t^ 0.\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 8/5/2003 15:31'!\\ntextStyle\\n\\n\\t^ TextStyle actualTextStyles detect: [:aStyle | (aStyle fontArray collect: [:s | s name]) includes: self name]\\n\\t\\tifNone: [].\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\nwidthOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\t^(self fontOf: aCharacter) widthOf: aCharacter! !\\n\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:43'!\\nascent\\n\\n\\t^ fontArray first ascent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:49'!\\nascentKern\\n\\n\\t^ fontArray first ascentKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:49'!\\nbaseKern\\n\\n\\t^ fontArray first baseKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 12/1/2003 18:00'!\\nbonk: glyphForm with: bonkForm at: j\\n\\t\\\"Bonking means to run through the glyphs clearing out black pixels\\n\\tbetween characters to prevent them from straying into an adjacent\\n\\tcharacter as a result of, eg, bolding or italicizing\\\"\\n\\t\\\"Uses the bonkForm to erase at every character boundary in glyphs.\\\"\\n\\n\\t| bb offset font x |\\n\\tfont _ (fontArray at: j).\\n\\toffset _ bonkForm offset x.\\n\\tbb _ BitBlt toForm: glyphForm.\\n\\tbb sourceForm: bonkForm; sourceRect: bonkForm boundingBox;\\n\\t\\tcombinationRule: Form erase; destY: 0.\\n\\tx _ font xTable.\\n\\t(x isMemberOf: SparseLargeTable) ifTrue: [\\n\\t\\tx base to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t] ifFalse: [\\n\\t\\t1 to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:15'!\\ncopy\\n\\n\\t| s a |\\n\\ts _ self class new.\\n\\ts name: self name.\\n\\ts emphasis: self emphasis.\\n\\ts reset.\\n\\ta _ Array new: fontArray size.\\n\\t1 to: a size do: [:i |\\n\\t\\ta at: i put: (fontArray at: i) copy.\\n\\t].\\n\\ts fontArray: a.\\n\\t^ s.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'nk 9/1/2004 12:06'!\\nderivativeFonts\\n\\t^derivativeFonts copyWithout: nil! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:02'!\\ndescent\\n\\n\\t^ fontArray first descent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:02'!\\ndescentKern\\n\\n\\t^ fontArray first descentKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 5/19/2004 11:36'!\\ndisplayLine: aString at: aPoint \\n\\t\\\"Display the characters in aString, starting at position aPoint.\\\"\\n\\n\\tself characters: (1 to: aString size)\\n\\t\\tin: aString\\n\\t\\tdisplayAt: aPoint\\n\\t\\tclippedBy: Display boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil\\n\\t\\tkernDelta: 0\\n\\t\\ton: (BitBlt current toForm: Display).\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:06'!\\nemphasis\\n\\t\\\"Answer the integer code for synthetic bold, italic, underline, and \\n\\tstrike-out.\\\"\\n\\n\\t^ emphasis.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:07'!\\nemphasis: code \\n\\t\\\"Set the integer code for synthetic bold, itallic, underline, and strike-out, \\n\\twhere bold=1, italic=2, underlined=4, and struck out=8.\\\"\\n\\n\\temphasis _ code.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:15'!\\nemphasized: code \\n\\n\\t\\\"Answer a copy of the receiver with emphasis set to include code.\\\"\\n\\t| derivative addedEmphasis base safeCode |\\n\\tcode = 0 ifTrue: [^ self].\\n\\t(derivativeFonts == nil or: [derivativeFonts size = 0]) ifTrue: [^ self].\\n\\tderivative _ derivativeFonts at: (safeCode _ code min: derivativeFonts size).\\n\\tderivative == nil ifFalse: [^ derivative]. \\\"Already have this style\\\"\\n\\n\\t\\\"Dont have it -- derive from another with one with less emphasis\\\"\\n\\taddedEmphasis _ 1 bitShift: safeCode highBit - 1.\\n\\tbase _ self emphasized: safeCode - addedEmphasis. \\\"Order is Bold, Ital, Under, Narrow\\\"\\n\\taddedEmphasis = 1 ifTrue: \\\"Compute synthetic bold version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'B') makeBoldGlyphs].\\n\\taddedEmphasis = 2 ifTrue: \\\"Compute synthetic italic version of the font\\\"\\n\\t\\t[ derivative _ (base copy name: base name , 'I') makeItalicGlyphs].\\n\\taddedEmphasis = 4 ifTrue: \\\"Compute underlined version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'U') makeUnderlinedGlyphs].\\n\\taddedEmphasis = 8 ifTrue: \\\"Compute narrow version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'N') makeCondensedGlyphs].\\n\\taddedEmphasis = 16 ifTrue: \\\"Compute struck-out version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'X') makeStruckOutGlyphs].\\n\\tderivative emphasis: safeCode.\\n\\tderivativeFonts at: safeCode put: derivative.\\n\\t^ derivative\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 20:59'!\\nfamilyName\\n\\n\\t^ fontArray first familyName.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:38'!\\nfamilySizeFace\\n\\n\\t^ Array\\n\\t\\twith: fontArray first name\\n\\t\\twith: self height\\n\\t\\twith: fontArray first emphasis\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:49'!\\nfontArray: anArray\\n\\n\\tfontArray _ anArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:49'!\\nfontNameWithPointSize\\n\\n\\t^ fontArray first fontNameWithPointSize.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nglyphs\\n\\n\\t^ fontArray first glyphs\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nglyphsEncoding: anInteger\\n\\n\\t^ (fontArray at: (anInteger+1)) glyphs.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nheight\\n\\n\\t^ fontArray first height.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'tak 12/16/2004 19:15'!\\ninitializeWithFontArray: anArray \\n\\t\\\"Initialize with given font array, the ascent of primary font is modified \\n\\tif another font has higher size\\\"\\n\\t| primaryFont maxHeight newFont |\\n\\tfontArray := anArray.\\n\\tprimaryFont := anArray first.\\n\\temphasis := 0.\\n\\tname := primaryFont name.\\n\\tmaxHeight := anArray\\n\\t\\t\\t\\tinject: 0\\n\\t\\t\\t\\tinto: [:theHeight :font | (font notNil\\n\\t\\t\\t\\t\\t\\t\\tand: [theHeight < font height])\\n\\t\\t\\t\\t\\t\\tifTrue: [font height]\\n\\t\\t\\t\\t\\t\\tifFalse: [theHeight]].\\n\\tprimaryFont height < maxHeight\\n\\t\\tifTrue: [newFont := primaryFont copy\\n\\t\\t\\t\\t\\t\\tfixAscent: primaryFont ascent + (maxHeight - primaryFont height)\\n\\t\\t\\t\\t\\t\\tandDescent: primaryFont descent\\n\\t\\t\\t\\t\\t\\thead: 0.\\n\\t\\t\\tfontArray at: 1 put: newFont].\\n\\tself reset! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 1/5/2005 13:59'!\\ninstallOn: aDisplayContext\\n\\n\\t^ aDisplayContext installStrikeFont: self.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\ninstallOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor \\n\\n\\t^ aDisplayContext\\n\\t\\tinstallStrikeFont: self\\n\\t\\tforegroundColor: foregroundColor\\n\\t\\tbackgroundColor: backgroundColor.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nlineGrid\\n\\n\\t| f |\\n\\tf _ fontArray first.\\n\\t^ f ascent + f descent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nmaxEncoding\\n\\n\\t^ fontArray size.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 2/24/2005 15:45'!\\nmaxWidth\\n\\n\\t^ (fontArray at: 1) maxWidth.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nname\\n\\n\\t^ name\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nname: aString\\n\\n\\tname _ aString\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 21:17'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to a known Font in the other system instead. \\\"\\n\\n\\t\\\"A path to me\\\"\\n\\t(TextConstants at: #forceFontWriting ifAbsent: [false]) ifTrue: [^ self].\\n\\t\\t\\\"special case for saving the default fonts on the disk. See collectionFromFileNamed:\\\"\\n\\n\\tdp _ DiskProxy global: #StrikeFontSet selector: #familyName:size:emphasized:\\n\\t\\t\\targs: (Array with: self familyName with: self pointSize\\n\\t\\t\\t\\t\\twith: self emphasis).\\n\\trefStrm replace: self with: dp.\\n\\t^ dp.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\npointSize\\n\\n\\t^ fontArray first pointSize.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '(' , self name.\\n\\taStream space.\\n\\tself height printOn: aStream.\\n\\taStream nextPut: $).\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nreset\\n\\t\\\"Reset the cache of derivative emphasized fonts\\\"\\n\\n\\tderivativeFonts _ Array new: 32.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nsubscript\\n\\n\\t^ fontArray first subscript\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nsuperscript\\n\\n\\t^ fontArray first superscript\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 18:53'!\\nwidthOfString: aString\\n\\n\\taString ifNil:[^0].\\n\\t\\\"Optimizing\\\"\\n\\t(aString isByteString) ifTrue: [\\n\\t\\t^ self fontArray first widthOfString: aString from: 1 to: aString size].\\n\\t^ self widthOfString: aString from: 1 to: aString size.\\n\\\"\\n\\tTextStyle default defaultFont widthOfString: 'zort' 21\\n\\\"\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'tak 1/11/2005 17:59'!\\nwidthOfString: aString from: startIndex to: stopIndex\\n\\t\\\"Measure the length of the given string between start and stop index\\\"\\n\\n\\t| resultX |\\n\\tresultX _ 0.\\n\\tstartIndex to: stopIndex do:[:i | \\n\\t\\tresultX _ resultX + (self widthOf: (aString at: i))].\\n\\t^ resultX.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:56'!\\nxTable\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^ fontArray first xTable.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:56'!\\nxTableEncoding: anInteger\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^(fontArray at: anInteger + 1) xTable.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'character shapes' stamp: 'yo 12/27/2002 04:35'!\\ncharacterFormAt: character \\n\\n\\t| encoding ascii xTable leftX rightX |\\n\\tencoding _ character leadingChar + 1.\\n\\tascii _ character charCode.\\n\\t(ascii < (fontArray at: encoding) minAscii or: [ascii > (fontArray at: encoding) maxAscii])\\n\\t\\tifTrue: [ascii _ (fontArray at: encoding) maxAscii].\\n\\txTable _ (fontArray at: encoding) xTable.\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\t^ (fontArray at: encoding) glyphs copy: (leftX @ 0 corner: rightX @ self height).\\n! !\\n\\n!StrikeFontSet methodsFor: 'character shapes' stamp: 'yo 12/27/2002 04:35'!\\ncharacterFormAt: character put: characterForm \\n\\n\\t| ascii leftX rightX widthDif newGlyphs encoding xTable glyphs |\\n\\tencoding _ character leadingChar + 1.\\n\\tascii _ character charCode.\\n\\tascii < (fontArray at: encoding) minAscii ifTrue: [\\n\\t\\t^ self error: 'Cant store characters below min ascii'\\n\\t].\\n\\tascii > (fontArray at: encoding) maxAscii ifTrue: [\\n\\t\\t^ self error: 'No change made'\\n\\t].\\n\\txTable _ (fontArray at: encoding) xTable.\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\tglyphs _ (fontArray at: encoding) glyphs.\\n\\twidthDif _ characterForm width - (rightX - leftX).\\n\\twidthDif ~= 0 ifTrue: [\\n\\t\\tnewGlyphs _ Form extent: glyphs width + widthDif @ glyphs height.\\n\\t\\tnewGlyphs copy: (0 @ 0 corner: leftX @ glyphs height) from: 0 @ 0\\n\\t\\t\\tin: glyphs rule: Form over.\\n\\t\\tnewGlyphs\\n\\t\\t\\t\\tcopy: (rightX + widthDif @ 0 corner: newGlyphs width @ glyphs height)\\n\\t\\t\\t\\tfrom: rightX @ 0 in: glyphs rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\t\\\"adjust further entries on xTable\\\"\\n\\t\\txTable _ xTable copy.\\n\\t\\tascii + 2 to: xTable size do: [:i |\\n\\t\\t\\txTable at: i put: (xTable at: i) + widthDif]].\\n\\tglyphs copy: (leftX @ 0 extent: characterForm extent) from: 0 @ 0 in: characterForm rule: Form over.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:35'!\\ncharacters: anInterval in: sourceString displayAt: aPoint clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm kernDelta: kernDelta on: aBitBlt\\n\\t\\\"Simple, slow, primitive method for displaying a line of characters.\\n\\tNo wrap-around is provided.\\\"\\n\\n\\t| ascii encoding destPoint leftX rightX sourceRect xTable noFont f |\\n\\tdestPoint _ aPoint.\\n\\tanInterval do: \\n\\t\\t[:i |\\n\\t\\tencoding _ (sourceString at: i) leadingChar + 1.\\n\\t\\tnoFont _ false.\\n\\t\\t[f _ fontArray at: encoding]\\n\\t\\t\\ton: Exception do: [:ex | noFont _ true. f _ fontArray at: 1].\\n\\t\\tf ifNil: [noFont _ true. f _ fontArray at: 1].\\n\\t\\tascii _ noFont ifTrue: [$?] ifFalse: [(sourceString at: i) charCode].\\n\\t\\t(ascii < f minAscii\\n\\t\\t\\tor: [ascii > f maxAscii])\\n\\t\\t\\tifTrue: [ascii _ f maxAscii].\\n\\t\\txTable _ f xTable.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\tsourceRect _ leftX@0 extent: (rightX-leftX) @ self height.\\n\\t\\taBitBlt copyFrom: sourceRect in: f glyphs to: destPoint.\\n\\t\\tdestPoint _ destPoint + ((rightX-leftX+kernDelta)@0).\\n\\t\\t\\\"destPoint printString displayAt: 0@(i*20).\\\"\\n\\t].\\n\\t^ destPoint.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'efc 8/6/2005 11:45'!\\ndisplayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo g destY |\\n\\tdestPoint := aPoint.\\n\\tglyphInfo := Array new: 5.\\n\\tstartIndex to: stopIndex do: [:charIndex |\\n\\t\\tself glyphInfoOf: (aString at: charIndex) into: glyphInfo.\\n\\t\\tg := glyphInfo at:1.\\n\\t\\tleftX := glyphInfo at:2.\\n\\t\\trightX := glyphInfo at:3.\\n\\t\\t((glyphInfo at:5) ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\t(glyphInfo at:5) installOn: aBitBlt.\\n\\t\\t].\\n\\t\\taBitBlt sourceForm: g.\\n\\t\\tdestY := baselineY - (glyphInfo at:4).\\n\\t\\taBitBlt destX: (destPoint x) destY: destY width: (rightX - leftX) height: (self height).\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint := destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t].\\n\\t^ destPoint.! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 12/27/2002 04:35'!\\ndisplayStringR2L: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta \\n\\n\\t| destPoint font |\\n\\tdestPoint _ aPoint.\\n\\tstartIndex to: stopIndex do: [:charIndex | \\n\\t\\t| encoding ascii xTable leftX rightX | \\n\\t\\tencoding _ (aString at: charIndex) leadingChar + 1.\\n\\t\\tascii _ (aString at: charIndex) charCode.\\n\\t\\tfont _ fontArray at: encoding.\\n\\t\\t((ascii between: font minAscii and: font maxAscii) not) ifTrue: [\\n\\t\\t\\tascii _ font maxAscii].\\n\\t\\txTable _ font xTable.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\taBitBlt sourceForm: font glyphs.\\n\\t\\taBitBlt destX: destPoint x - (rightX - leftX).\\n\\t\\taBitBlt destY: destPoint y.\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt width: rightX - leftX.\\n\\t\\taBitBlt height: self height.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint _ destPoint - (rightX - leftX + kernDelta @ 0).\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 1/7/2005 12:04'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta \\n\\n\\t^ self displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: aPoint y + self ascent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'efc 8/6/2005 13:35'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t\\\"Assume this is a wide string\\\"\\n\\t| isMulti |\\n\\tisMulti _ true.\\n\\n\\t\\\"Look for an excuse to use the fast primitive\\\"\\n \\t(aString isKindOf: ByteString) \\n\\t\\tifTrue:[ isMulti _ false]\\n\\t\\tifFalse:[ (aString isKindOf: Text) \\n\\t\\t\\tifTrue:[ (aString string isKindOf: ByteString) \\n\\t\\t\\t\\tifTrue:[ isMulti _ false ] \\n\\t]].\\n\\n\\tisMulti ifTrue:[^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 1/7/2005 15:17'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta from: fromFont baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo g tag char destY |\\n\\tdestPoint _ aPoint.\\n\\trIndex _ startIndex.\\n\\ttag _ (aString at: rIndex) leadingChar.\\n\\tglyphInfo _ Array new: 5.\\n\\t[rIndex <= stopIndex] whileTrue: [\\n\\t\\tchar _ aString at: rIndex.\\n\\t\\t((fromFont hasGlyphOf: char) or: [char leadingChar ~= tag]) ifTrue: [^ Array with: rIndex with: destPoint].\\n\\t\\tself glyphInfoOf: char into: glyphInfo.\\n\\t\\tg _ glyphInfo first.\\n\\t\\tleftX _ glyphInfo second.\\n\\t\\trightX _ glyphInfo third.\\n\\t\\t(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\tglyphInfo fifth installOn: aBitBlt.\\n\\t\\t].\\n\\t\\taBitBlt sourceForm: g.\\n\\t\\tdestY _ baselineY - glyphInfo fourth. \\n\\t\\taBitBlt destX: destPoint x.\\n\\t\\taBitBlt destY: destY.\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt width: rightX - leftX.\\n\\t\\taBitBlt height: self height.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint _ destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t\\trIndex _ rIndex + 1.\\n\\t].\\n\\t^ Array with: rIndex with: destPoint.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'BG 3/16/2005 08:27'!\\nfontDisplay\\n\\t\\\"TextStyle default defaultFont fontDisplay.\\\"\\n\\n\\tDisplay restoreAfter:\\n\\t\\t[(Form extent: 440@400) displayAt: 90@90.\\n\\t\\t 0 to: 15 do:\\n\\t\\t\\t[:i |\\n\\t\\t\\ti storeStringHex displayAt: 100 @ (20 * i + 100).\\n\\t\\t\\t0 to: 15 do:\\n\\t\\t\\t\\t[:j |\\n\\t\\t\\t\\t((16*i+j) between: 1 and: (self xTable size - 2)) ifTrue:\\n\\t\\t\\t\\t\\t[(self characterFormAt: (16 * i + j) asCharacter)\\n\\t\\t\\t\\t\\t\\tdisplayAt: (20 * j + 150) @ (20 * i + 100)]]].\\n\\t\\t\\t'Click to continue...' asDisplayText displayAt: 100@450]! !\\n\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:52'!\\nmakeBoldGlyphs\\n\\t\\\"Make a bold set of glyphs with same widths by ORing 1 bit to the right\\n\\t\\t(requires at least 1 pixel of intercharacter space)\\\"\\n\\n\\t| g bonkForm font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ fontArray at: i.\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tbonkForm _ (Form extent: 1@16) fillBlack offset: -1@0.\\n\\t\\t\\tself bonk: g with: bonkForm at: i.\\n\\t\\t\\tg copyBits: g boundingBox from: g at: (1@0)\\n\\t\\t\\t\\tclippingBox: g boundingBox rule: Form under fillColor: nil.\\n\\t\\t\\t(fontArray at: i) setGlyphs: g.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:51'!\\nmakeItalicGlyphs\\n\\t\\\"Make an italic set of glyphs with same widths by skewing left and right\\n\\t\\t(may require more intercharacter space)\\\"\\n\\n\\t| g bonkForm bc font |\\n\\t1 to: fontArray size do: [:j |\\n\\t\\tfont _ (fontArray at: j).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\t\\\"BonkForm will have bits where slanted characters overlap their neighbors.\\\"\\n\\t\\t\\tbonkForm _ Form extent: (self height//4+2) @ self height.\\n\\t\\t\\tbc _ font descent//4 + 1. \\\"Bonker x-coord corresponding to char boundary.\\\"\\n\\t\\t\\tbonkForm fill: (0 @ 0 corner: (bc+1) @ font ascent) fillColor: Color black.\\n\\t\\t\\t4 to: font ascent-1 by: 4 do:\\n\\t\\t\\t\\t[:y | \\t\\t\\\"Slide ascenders right...\\\"\\n\\t\\t\\t\\tg copy: (1@0 extent: g width @ (font ascent - y))\\n\\t\\t\\t\\t\\tfrom: 0@0 in: g rule: Form over.\\n\\t\\t\\t\\tbonkForm copy: (1@0 extent: bonkForm width @ (font ascent - y))\\n\\t\\t\\t\\t\\tfrom: 0@0 in: bonkForm rule: Form over].\\n\\t\\t\\tbonkForm fill: (0 @ 0 corner: (bc+1) @ font ascent) fillColor: Color white.\\n\\t\\t\\tbonkForm fill: (bc @ font ascent corner: bonkForm extent) fillColor: Color black.\\n\\t\\t\\tfont ascent to: font height-1 by: 4 do:\\n\\t\\t\\t\\t[:y | \\t\\t\\\"Slide descenders left...\\\"\\n\\t\\t\\t\\tg copy: (0@y extent: g width @ g height)\\n\\t\\t\\t\\t\\tfrom: 1@y in: g rule: Form over.\\n\\t\\t\\t\\tbonkForm copy: (0@0 extent: bonkForm width @ bonkForm height)\\n\\t\\t\\t\\t\\tfrom: 1@0 in: bonkForm rule: Form over].\\n\\t\\t\\tbonkForm fill: (bc @ font ascent corner: bonkForm extent) fillColor: Color white.\\n\\t\\t\\t\\\"Now use bonkForm to erase at every character boundary in glyphs.\\\"\\n\\t\\t\\tbonkForm offset: (0-bc) @ 0.\\n\\t\\t\\tfont bonk: g with: bonkForm.\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:53'!\\nmakeStruckOutGlyphs\\n\\t\\\"Make a struck-out set of glyphs with same widths\\\"\\n\\n\\t| g font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ (fontArray at: i).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tg fillBlack: (0 @ (font ascent - (font ascent//3)) extent: g width @ 1).\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:51'!\\nmakeUnderlinedGlyphs\\n\\t\\\"Make an underlined set of glyphs with same widths\\\"\\n\\n\\t| g font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ (fontArray at: i).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tg fillBlack: (0 @ (font ascent+1) extent: g width @ 1).\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n\\n!StrikeFontSet methodsFor: '*nebraska-as yet unclassified' stamp: 'yo 12/17/2005 20:19'!\\nencodedForRemoteCanvas\\n\\n\\t| stream |\\n\\tstream := RWBinaryOrTextStream on: ''.\\n\\tstream nextPutAll: self familyName.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self pointSize asString.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self emphasis asString.\\n\\t^ stream contents asString.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 12/27/2002 13:39'!\\naddNewFont: aFont at: encodingIndex\\n\\n\\t| newArray |\\n\\tencodingIndex > fontArray size ifTrue: [\\n\\t\\tnewArray _ Array new: encodingIndex.\\n\\t\\tnewArray replaceFrom: 1 to: fontArray size with: fontArray startingAt: 1.\\n\\t] ifFalse: [\\n\\t\\tnewArray _ fontArray.\\n\\t].\\n\\n\\tnewArray at: encodingIndex put: aFont.\\n\\n\\tself initializeWithFontArray: newArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 1/7/2005 11:16'!\\nglyphInfoOf: aCharacter into: glyphInfoArray\\n\\n\\t| index f code leftX |\\n\\tindex _ aCharacter leadingChar + 1.\\n\\tfontArray size < index ifTrue: [^ self questionGlyphInfoInto: glyphInfoArray].\\n\\t(f _ fontArray at: index) ifNil: [^ self questionGlyphInfoInto: glyphInfoArray].\\n\\n\\tcode _ aCharacter charCode.\\n\\t((code between: f minAscii and: f maxAscii) not) ifTrue: [\\n\\t\\t^ self questionGlyphInfoInto: glyphInfoArray.\\n\\t].\\n\\tleftX _ f xTable at: code + 1.\\n\\tleftX < 0 ifTrue: [\\n\\t\\t^ self questionGlyphInfoInto: glyphInfoArray.\\n\\t].\\n\\tglyphInfoArray at: 1 put: f glyphs;\\n\\t\\tat: 2 put: leftX;\\n\\t\\tat: 3 put: (f xTable at: code + 2);\\n\\t\\tat: 4 put: (f ascentOf: aCharacter);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 1/13/2005 16:43'!\\nquestionGlyphInfoInto: glyphInfoArray\\n\\n\\t| f ascii |\\n\\tf _ fontArray at: 1.\\n\\tascii _ $? asciiValue.\\n\\tglyphInfoArray at: 1 put: f glyphs;\\n\\t\\tat: 2 put: (f xTable at: ascii + 1);\\n\\t\\tat: 3 put: (f xTable at: ascii + 2);\\n\\t\\tat: 4 put: (self ascentOf: $?);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFontSet class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 1/19/2005 11:25'!\\ncreateExternalFontFileForLatin2: fileName\\n\\\"\\n\\tStrikeFontSet createExternalFontFileForLatin2: 'latin2.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b10.bdf' name: 'LatinTwo9' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'LatinTwo10' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'LatinTwo12' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b16.bdf' name: 'LatingTwo14' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'LatinTwo20' ranges: EFontBDFFontReaderForRanges rangesForLatin2).\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 5/25/2004 11:05'!\\ncreateExternalFontFileForUnicodeJapanese: fileName\\n\\\"\\n\\tStrikeFontSet createExternalFontFileForUnicodeJapanese: 'uJapaneseFont.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'Japanese10' overrideWith: 'shnmk12.bdf')\\n\\t\\t\\t\\twith: ((StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'Japanese12' overrideWith: 'shnmk14.bdf') \\\"fixAscent: 14 andDescent: 1 head: 1\\\")\\n\\t\\t\\t\\twith: ((StrikeFont newForJapaneseFromEFontBDFFile: 'b16.bdf' name: 'Japanese14' overrideWith: 'shnmk16.bdf') \\\"fixAscent: 16 andDescent: 4 head: 4\\\")\\n\\t\\t\\t\\twith: (StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'Japanese18' overrideWith: 'kanji24.bdf').\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 1/15/2004 16:58'!\\ncreateExternalFontFileForUnicodeKorean: fileName\\n\\\"\\n\\tSmalltalk garbageCollect.\\n\\tStrikeFontSet createExternalFontFileForUnicodeKorean: 'uKoreanFont.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'Japanese10' overrideWith: 'shnmk12.bdf')\\n\\t\\t\\t\\twith: ((StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'Japanese12' overrideWith: 'shnmk14.bdf') \\\"fixAscent: 14 andDescent: 1 head: 1\\\")\\n\\t\\t\\t\\twith: ((StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b16.bdf' name: 'Japanese14' overrideWith: 'hanglg16.bdf') fixAscent: 16 andDescent: 4 head: 4)\\n\\t\\t\\t\\twith: (StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'Japanese18' overrideWith: 'hanglm24.bdf').\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 22:42'!\\ndecodedFromRemoteCanvas: aString\\n\\n\\t| array |\\n\\tarray _ aString findTokens: #($ ).\\n\\t^ self familyName: (array at: 1) size: (array at: 2) asNumber emphasized: (array at: 3) asNumber.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 12/27/2002 14:08'!\\nduplicateArrayElementsForLeadingCharShift\\n\\\"\\n\\tself duplicateArrayElementsForLeadingCharShift\\n\\\"\\n\\t| array font |\\n\\tself allInstances do: [:s |\\n\\t\\ts emphasis = 0 ifTrue: [\\n\\t\\t\\tarray _ s fontArray.\\n\\t\\t\\t2 to: (4 min: array size) do: [:i |\\n\\t\\t\\t\\tfont _ array at: i.\\n\\t\\t\\t\\ts addNewFont: font at: ((i - 1) << 2) + 1.\\n\\t\\t\\t].\\n\\t\\t] ifFalse: [\\n\\t\\t\\ts reset\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 8/19/2003 13:04'!\\nfamilyName: aName size: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\n\\t| collection |\\n\\tcollection _ self allInstances select: [:inst | (inst name beginsWith: aName) and: [inst emphasis = 0]].\\n\\tcollection isEmpty ifTrue: [\\n\\t\\t(aName = 'DefaultMultiStyle') ifTrue: [\\n\\t\\t\\tcollection _ (TextConstants at: #DefaultMultiStyle) fontArray.\\n\\t\\t] ifFalse: [\\n\\t\\t\\t^ TextStyle defaultFont\\n\\t\\t]\\n\\t].\\n\\tcollection _ collection asSortedCollection: [:a :b | a pointSize <= b pointSize].\\n\\tcollection do: [:s | (s pointSize >= aSize) ifTrue: [^ s]].\\n\\t^ TextStyle defaultFont.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 21:03'!\\nfamilyName: aName size: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName size: aSize) emphasized: emphasisCode\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 5/25/2004 14:32'!\\nfindMaximumLessThan: f in: array\\n\\n\\tarray size to: 1 by: -1 do: [:i |\\n\\t\\tf height >= (array at: i) height ifTrue: [^ array at: i].\\n\\t].\\n\\t^ array first.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 9/23/2002 16:32'!\\nnewFontArray: anArray\\n \\n\\t^super new initializeWithFontArray: anArray\\n! !\\n\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 1/18/2005 16:00'!\\ninstallExternalFontFileName6: fileName encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t^ self installExternalFontFileName6: fileName inDir: FileDirectory default encoding: encoding encodingName: aString textStyleName: styleName.\\n\\n\\\"\\nStrikeFontSet createExternalFontFileForCyrillic: 'cyrillicFont.out'.\\n\\nStrikeFontSet installExternalFontFileName6: 'latin2.out' encoding: Latin2Environment leadingChar encodingName: #Latin2 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName6: 'uJapaneseFont.out' encoding: JapaneseEnvironment leadingChar encodingName: #Japanese textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName6: 'uKoreanFont.out' encoding: UnicodeKorean leadingChar encodingName: #Korean textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet removeFontsForEncoding: 2 encodingName: #Gb2312.\\nself halt.\\nStrikeFontSet removeFontsForEncoding: 3 encodingName: #KsX1001.\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/3/2005 17:40'!\\ninstallExternalFontFileName6: fileName inDir: dir encoding: encoding encodingName: aString textStyleName: styleName \\n\\t| aStream |\\n\\taStream := dir readOnlyFileNamed: fileName.\\n\\t[self\\n\\t\\tinstallExternalFontOn: aStream\\n\\t\\tencoding: encoding\\n\\t\\tencodingName: aString\\n\\t\\ttextStyleName: styleName]\\n\\t\\tensure: [aStream close]! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 3/17/2004 10:32'!\\ninstallExternalFontFileName: fileName encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t^ self installExternalFontFileName: fileName inDir: FileDirectory default encoding: encoding encodingName: aString textStyleName: styleName.\\n\\n\\\"\\nStrikeFontSet createExternalFontFileForCyrillic: 'cyrillicFont.out'.\\n\\nStrikeFontSet installExternalFontFileName: 'chineseFont.out' encoding: 2 encodingName: #Gb2312 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'japaneseFont.out' encoding: 1 encodingName: #JisX0208 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'defaultFont.out' encoding: 0 encodingName: #Latin1 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'cyrillicFont.out' encoding: UnicodeCyrillic leadingChar encodingName: #Cyrillic textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'extendedLatinFont.out' encoding: UnicodeLatinExtendedAB leadingChar encodingName: #ExtendedLatin textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'ipaExtensionsFont.out' encoding: UnicodeIPA leadingChar encodingName: #IPAExtensions textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'armenianFont.out' encoding: UnicodeArmenian leadingChar encodingName: #Armenian textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'greekFont.out' encoding: UnicodeGreek leadingChar encodingName: #Greek textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'arrowFont.out' encoding: UnicodeArrows leadingChar encodingName: #Arrow textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'uJapaneseFont.out' indir: FileDirectory default encoding: JapaneseEnvironment leadingChar encodingName: #Japanese textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'uKoreanFont.out' encoding: UnicodeKorean leadingChar encodingName: #Korean textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet removeFontsForEncoding: 2 encodingName: #Gb2312.\\nself halt.\\nStrikeFontSet removeFontsForEncoding: 3 encodingName: #KsX1001.\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 8/19/2003 00:32'!\\ninstallExternalFontFileName: fileName inDir: dir encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t| array arrayFour oldStyle arrayOfFS fs fonts newFonts |\\n\\tarray _ (ReferenceStream on: (dir readOnlyFileNamed: fileName)) next.\\n\\n\\tarrayFour _ Array new: 4 withAll: array last.\\n\\tarrayFour replaceFrom: 1 to: array size with: array startingAt: 1.\\n\\tTextConstants at: aString asSymbol put: arrayFour.\\n\\n\\toldStyle _ TextConstants at: styleName asSymbol.\\n\\tarrayOfFS _ oldStyle fontArray.\\n\\tarrayOfFS _ (1 to: 4) collect: [:i |\\n\\t\\tfs _ arrayOfFS at: i.\\n\\t\\tfonts _ fs fontArray.\\n\\t\\tencoding + 1 > fonts size ifTrue: [\\n\\t\\t\\tnewFonts _ Array new: encoding + 1.\\n\\t\\t\\tnewFonts replaceFrom: 1 to: fonts size with: fonts startingAt: 1.\\n\\t\\t\\tnewFonts at: encoding + 1 put: (arrayFour at: i).\\n\\t\\t\\tfs initializeWithFontArray: newFonts.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tfonts at: encoding + 1 put: (arrayFour at: i).\\n\\t\\t].\\n\\t\\tfs.\\n\\t].\\n\\n\\tTextConstants at: styleName asSymbol put: (TextStyle fontArray: arrayOfFS).\\n\\toldStyle becomeForward: (TextConstants at: styleName asSymbol).\\n\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/5/2005 10:34'!\\ninstallExternalFontOn: aStream encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t| array fonts encodingIndex textStyle |\\n\\n\\tarray _ aStream\\n\\t\\tuntilEndWithFork: [(ReferenceStream on: aStream) next]\\n\\t\\tdisplayingProgress: 'Font reading...'. \\n\\t\\n\\tTextConstants at: aString asSymbol put: array.\\n\\n\\ttextStyle _ TextConstants at: styleName asSymbol.\\n\\tencodingIndex _ encoding + 1.\\n\\ttextStyle fontArray do: [:fs |\\n\\t\\tfonts _ fs fontArray.\\n\\t\\tencodingIndex > fonts size\\n\\t\\t\\tifTrue: [fonts _ (Array new: encodingIndex)\\n\\t\\t\\t\\treplaceFrom: 1 to: fonts size with: fonts startingAt: 1].\\n\\t\\tfonts at: encodingIndex put: (self findMaximumLessThan: fs fontArray first in: array).\\n\\t\\tfs initializeWithFontArray: fonts.\\n\\t].\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/4/2005 11:03'!\\ninstallExternalFontOn: aStream forLocale: locale \\n\\tself\\n\\t\\tinstallExternalFontOn: aStream\\n\\t\\tencoding: locale languageEnvironment leadingChar\\n\\t\\tencodingName: locale languageEnvironment fontEncodingName\\n\\t\\ttextStyleName: #DefaultMultiStyle! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 1/15/2004 16:06'!\\ninstallNewFontAtIndex: newIndex fromOld: oldIndex\\n\\n\\t| fontArray newArray |\\n\\tself allInstances do: [:set |\\n\\t\\tfontArray _ set fontArray.\\n\\t\\tnewIndex + 1 > fontArray size ifTrue: [\\n\\t\\t\\tnewArray _ Array new: newIndex + 1.\\n\\t\\t\\tnewArray replaceFrom: 1 to: fontArray size with: fontArray startingAt: 1.\\n\\t\\t\\tnewArray at: newIndex + 1 put: (fontArray at: oldIndex + 1).\\n\\t\\t\\tset initializeWithFontArray: newArray.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tfontArray at: newIndex + 1 put: (fontArray at: oldIndex + 1).\\n\\t\\t].\\n\\t].\\n\\n\\\"\\nStrikeFontSet installNewFontAtIndex: UnicodeSimplifiedChinese leadingChar fromOld: UnicodeJapanese leadingChar\\nStrikeFontSet installNewFontAtIndex: UnicodeKorean leadingChar fromOld: UnicodeJapanese leadingChar\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/4/2005 14:41'!\\nremoveFontsForEncoding: leadingChar encodingName: encodingSymbol\\n\\n\\t| insts fonts newFonts index |\\n\\tleadingChar = 0 ifTrue: [^ self error: 'you cannot delete the intrinsic fonts'].\\n\\tinsts _ self allInstances.\\n\\tinsts do: [:inst |\\n\\t\\tfonts _ inst fontArray.\\n\\t\\tfonts size >= (leadingChar + 1) ifTrue: [\\n\\t\\t\\tleadingChar + 1 = fonts size ifTrue: [\\n\\t\\t\\t\\tnewFonts _ fonts copyFrom: 1 to: fonts size - 1.\\n\\t\\t\\t\\tindex _ newFonts indexOf: nil.\\n\\t\\t\\t\\tindex > 0 ifTrue: [newFonts _ newFonts copyFrom: 1 to: index - 1].\\n\\t\\t\\t\\tinst initializeWithFontArray: newFonts.\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\tfonts at: leadingChar + 1 put: nil.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\n\\tTextConstants removeKey: encodingSymbol asSymbol ifAbsent: [].\\n! !\\nArrayedCollection subclass: #String\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'AsciiOrder CSLineEnders CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder HtmlEntities LowercasingTable Tokenish UppercasingTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Strings'!\\n!String commentStamp: '<historical>' prior: 0!\\nA String is an indexed collection of Characters. Class String provides the abstract super class for ByteString (that represents an array of 8-bit Characters) and WideString (that represents an array of 32-bit characters). In the similar manner of LargeInteger and SmallInteger, those subclasses are chosen accordingly for a string; namely as long as the system can figure out so, the String is used to represent the given string.\\n\\nStrings support a vast array of useful methods, which can best be learned by browsing and trying out examples as you find them in the code.\\n\\nHere are a few useful methods to look at...\\n\\tString match:\\n\\tString contractTo:\\n\\nString also inherits many useful methods from its hierarchy, such as\\n\\tSequenceableCollection ,\\n\\tSequenceableCollection copyReplaceAll:with:\\n!\\n]style[(55 376 188 13 2 18 72 24 2 44)f1,f2,f1,f1LString match:;,f1,f1LString contractTo:;,f1,f1LSequenceableCollection ,;,f1,f1LSequenceableCollection copyReplaceAll:with:;!\\n\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteAt: index\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteAt: index put: value\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteSize\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\ndo: aBlock toFieldNumber: aNumber\\n\\t\\\"Considering the receiver as a holder of tab-delimited fields, evaluate aBlock on behalf of a field in this string\\\"\\n\\n\\t| start end index |\\n\\tstart _ 1.\\n\\tindex _ 1.\\n\\t[start <= self size] whileTrue: \\n\\t\\t[end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1].\\n\\t\\tend _ end - 1.\\n\\t\\taNumber = index ifTrue:\\n\\t\\t\\t[aBlock value: (self copyFrom: start to: end).\\n\\t\\t\\t^ self].\\n\\t\\tindex _ index + 1.\\n\\t\\tstart _ end + 2]\\n\\n\\\"\\n1 to: 6 do:\\n\\t[:aNumber |\\n\\t\\t'fred\\tcharlie\\telmo\\t\\twimpy\\tfriml' do:\\n\\t\\t\\t[:aField | Transcript cr; show: aField] toFieldNumber: aNumber]\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nendsWithDigit\\n\\t\\\"Answer whether the receiver's final character represents a digit. 3/11/96 sw\\\"\\n\\n\\t^ self size > 0 and: [self last isDigit]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 17:12'!\\nfindAnySubStr: delimiters startingAt: start \\n\\t\\\"Answer the index of the character within the receiver, starting at start, that begins a substring matching one of the delimiters. delimiters is an Array of Strings (Characters are permitted also). If the receiver does not contain any of the delimiters, answer size + 1.\\\"\\n\\n\\t| min ind |\\n\\tmin _ self size + 1.\\n\\tdelimiters do: [:delim |\\t\\\"May be a char, a string of length 1, or a substring\\\"\\n\\t\\tdelim isCharacter \\n\\t\\t\\tifTrue: [ind _ self indexOfSubCollection: (String with: delim) \\n\\t\\t\\t\\t\\t\\tstartingAt: start ifAbsent: [min]]\\n\\t\\t\\tifFalse: [ind _ self indexOfSubCollection: delim \\n\\t\\t\\t\\t\\t\\tstartingAt: start ifAbsent: [min]].\\n\\t\\t\\tmin _ min min: ind].\\n\\t^ min! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindBetweenSubStrs: delimiters\\n\\t\\\"Answer the collection of String tokens that result from parsing self. Tokens are separated by 'delimiters', which can be a collection of Strings, or a collection of Characters. Several delimiters in a row are considered as just one separation.\\\"\\n\\n\\t| tokens keyStart keyStop |\\n\\ttokens _ OrderedCollection new.\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipAnySubStr: delimiters startingAt: keyStop.\\n\\t\\tkeyStop _ self findAnySubStr: delimiters startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindCloseParenthesisFor: startIndex\\n\\t\\\"assume (self at: startIndex) is $(. Find the matching $), allowing parentheses to nest.\\\"\\n\\t\\\" '(1+(2-3))-3.14159' findCloseParenthesisFor: 1 \\\"\\n\\t\\\" '(1+(2-3))-3.14159' findCloseParenthesisFor: 4 \\\"\\n\\t| pos nestLevel |\\n\\tpos := startIndex+1.\\n\\tnestLevel := 1.\\n\\t[ pos <= self size ] whileTrue: [\\n\\t\\t(self at: pos) = $( ifTrue: [ nestLevel := nestLevel + 1 ].\\n\\t\\t(self at: pos) = $) ifTrue: [ nestLevel := nestLevel - 1 ].\\n\\t\\tnestLevel = 0 ifTrue: [ ^pos ].\\n\\t\\tpos := pos + 1.\\n\\t].\\n\\t^self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindDelimiters: delimiters startingAt: start \\n\\t\\\"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.\\\"\\n\\n\\tstart to: self size do: [:i |\\n\\t\\tdelimiters do: [:delim | delim = (self at: i) ifTrue: [^ i]]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 10/15/2003 15:32'!\\nfindLastOccuranceOfString: subString startingAt: start \\n\\t\\\"Answer the index of the last occurance of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\n\\t| last now |\\n\\tlast _ self findSubstring: subString in: self startingAt: start matchTable: CaseSensitiveOrder.\\n\\tlast = 0 ifTrue: [^ 0].\\n\\t[last > 0] whileTrue: [\\n\\t\\tnow _ last.\\n\\t\\tlast _ self findSubstring: subString in: self startingAt: last + subString size matchTable: CaseSensitiveOrder.\\n\\t].\\n\\n\\t^ now.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: subString\\n\\t\\\"Answer the index of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\t^self findString: subString startingAt: 1.! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: subString startingAt: start \\n\\t\\\"Answer the index of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\n\\t^ self findSubstring: subString in: self startingAt: start matchTable: CaseSensitiveOrder! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: key startingAt: start caseSensitive: caseSensitive\\n\\t\\\"Answer the index in this String at which the substring key first occurs, at or beyond start. The match can be case-sensitive or not. If no match is found, zero will be returned.\\\"\\n\\n\\tcaseSensitive\\n\\tifTrue: [^ self findSubstring: key in: self startingAt: start matchTable: CaseSensitiveOrder]\\n\\tifFalse: [^ self findSubstring: key in: self startingAt: start matchTable: CaseInsensitiveOrder]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 17:13'!\\nfindTokens: delimiters\\n\\t\\\"Answer the collection of tokens that result from parsing self. Return strings between the delimiters. Any character in the Collection delimiters marks a border. Several delimiters in a row are considered as just one separation. Also, allow delimiters to be a single character.\\\"\\n\\n\\t| tokens keyStart keyStop separators |\\n\\n\\ttokens _ OrderedCollection new.\\n\\tseparators _ delimiters isCharacter \\n\\t\\tifTrue: [Array with: delimiters]\\n\\t\\tifFalse: [delimiters].\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipDelimiters: separators startingAt: keyStop.\\n\\t\\tkeyStop _ self findDelimiters: separators startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'dtl 8/14/2004 11:27'!\\nfindTokens: delimiters escapedBy: quoteDelimiters \\n\\t\\\"Answer a collection of Strings separated by the delimiters, where \\n\\tdelimiters is a Character or collection of characters. Two delimiters in a \\n\\trow produce an empty string (compare this to #findTokens, which \\n\\ttreats sequential delimiters as one). \\n\\t \\n\\tThe characters in quoteDelimiters are treated as quote characters, such \\n\\tthat any delimiter within a pair of matching quoteDelimiter characters \\n\\tis treated literally, rather than as a delimiter. \\n\\t \\n\\tThe quoteDelimiter characters may be escaped within a quoted string. \\n\\tTwo sequential quote characters within a quoted string are treated as \\n\\ta single character. \\n\\t \\n\\tThis method is useful for parsing comma separated variable strings for \\n\\tspreadsheet import and export.\\\"\\n\\n\\t| tokens rs activeEscapeCharacter ts char token delimiterChars quoteChars |\\n\\tdelimiterChars _ (delimiters isNil\\n\\t\\t\\t\\tifTrue: ['']\\n\\t\\t\\t\\tifFalse: [delimiters]) asString.\\n\\tquoteChars _ (quoteDelimiters isNil\\n\\t\\t\\t\\tifTrue: ['']\\n\\t\\t\\t\\tifFalse: [quoteDelimiters]) asString.\\n\\ttokens _ OrderedCollection new.\\n\\trs _ ReadStream on: self.\\n\\tactiveEscapeCharacter _ nil.\\n\\tts _ WriteStream on: ''.\\n\\t[rs atEnd]\\n\\t\\twhileFalse: [char _ rs next.\\n\\t\\t\\tactiveEscapeCharacter isNil\\n\\t\\t\\t\\tifTrue: [(quoteChars includes: char)\\n\\t\\t\\t\\t\\t\\tifTrue: [activeEscapeCharacter _ char]\\n\\t\\t\\t\\t\\t\\tifFalse: [(delimiterChars includes: char)\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [token _ ts contents.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttokens add: token.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tts _ WriteStream on: '']\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [ts nextPut: char]]]\\n\\t\\t\\t\\tifFalse: [char == activeEscapeCharacter\\n\\t\\t\\t\\t\\t\\tifTrue: [rs peek == activeEscapeCharacter\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [ts nextPut: rs next]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [activeEscapeCharacter _ nil]]\\n\\t\\t\\t\\t\\t\\tifFalse: [ts nextPut: char]]].\\n\\ttoken _ ts contents.\\n\\t(tokens isEmpty and: [token isEmpty])\\n\\t\\tifFalse: [tokens add: token].\\n\\t^ tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindTokens: delimiters includes: subString\\n\\t\\\"Divide self into pieces using delimiters. Return the piece that includes subString anywhere in it. Is case sensitive (say asLowercase to everything beforehand to make insensitive).\\\"\\n\\n^ (self findTokens: delimiters) \\n\\tdetect: [:str | (str includesSubString: subString)] \\n\\tifNone: [nil]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindTokens: delimiters keep: keepers\\n\\t\\\"Answer the collection of tokens that result from parsing self. The tokens are seperated by delimiters, any of a string of characters. If a delimiter is also in keepers, make a token for it. (Very useful for carriage return. A sole return ends a line, but is also saved as a token so you can see where the line breaks were.)\\\"\\n\\n\\t| tokens keyStart keyStop |\\n\\ttokens _ OrderedCollection new.\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipDelimiters: delimiters startingAt: keyStop.\\n\\t\\tkeyStop to: keyStart-1 do: [:ii | \\n\\t\\t\\t(keepers includes: (self at: ii)) ifTrue: [\\n\\t\\t\\t\\ttokens add: (self copyFrom: ii to: ii)]].\\t\\\"Make this keeper be a token\\\"\\n\\t\\tkeyStop _ self findDelimiters: delimiters startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindWordStart: key startingAt: start\\n\\t| ind |\\n\\t\\\"HyperCard style searching. Answer the index in self of the substring key, when that key is preceeded by a separator character. Must occur at or beyond start. The match is case-insensitive. If no match is found, zero will be returned.\\\"\\n\\n\\tind _ start.\\n\\t[ind _ self findSubstring: key in: self startingAt: ind matchTable: CaseInsensitiveOrder.\\n\\tind = 0 ifTrue: [^ 0].\\t\\\"not found\\\"\\n\\tind = 1 ifTrue: [^ 1].\\t\\\"First char is the start of a word\\\"\\n\\t(self at: ind-1) isSeparator] whileFalse: [ind _ ind + 1].\\n\\t^ ind\\t\\\"is a word start\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nincludesSubString: subString\\n\\t^ (self findString: subString startingAt: 1) > 0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nincludesSubstring: aString caseSensitive: caseSensitive\\n\\t\\n\\t^ (self findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/28/2002 16:45'!\\nindexOf: aCharacter\\n\\n\\taCharacter isCharacter ifFalse: [^ 0].\\n\\t^ self class\\n\\t\\tindexOfAscii: aCharacter asciiValue\\n\\t\\tinString: self\\n\\t\\tstartingAt: 1.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:31'!\\nindexOf: aCharacter startingAt: start\\n\\n\\t(aCharacter isCharacter) ifFalse: [^ 0].\\n\\t^ self class indexOfAscii: aCharacter asciiValue inString: self startingAt: start! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:31'!\\nindexOf: aCharacter startingAt: start ifAbsent: aBlock\\n\\t| ans |\\n\\t(aCharacter isCharacter) ifFalse: [ ^ aBlock value ].\\n\\tans _ self class indexOfAscii: aCharacter asciiValue inString: self startingAt: start.\\n\\tans = 0\\n\\t\\tifTrue: [ ^ aBlock value ]\\n\\t\\tifFalse: [ ^ ans ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet\\n\\t\\\"returns the index of the first character in the given set. Returns 0 if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet ifAbsent: aBlock\\n\\t\\\"returns the index of the first character in the given set. Returns the evaluation of aBlock if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: 1 ifAbsent: aBlock! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet startingAt: start\\n\\t\\\"returns the index of the first character in the given set, starting from start. Returns 0 if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: start ifAbsent: [ 0 ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 16:22'!\\nindexOfAnyOf: aCharacterSet startingAt: start ifAbsent: aBlock\\n\\t\\\"returns the index of the first character in the given set, starting from start\\\"\\n\\n\\t| ans |\\n\\tans _ self class findFirstInString: self inSet: aCharacterSet byteArrayMap startingAt: start.\\n\\n\\tans = 0 \\n\\t\\tifTrue: [ ^aBlock value ]\\n\\t\\tifFalse: [ ^ans ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfSubCollection: sub \\n\\t#Collectn.\\n\\t\\\"Added 2000/04/08 For ANSI <sequenceReadableCollection> protocol.\\\"\\n\\t^ self\\n\\t\\tindexOfSubCollection: sub\\n\\t\\tstartingAt: 1\\n\\t\\tifAbsent: [0]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfSubCollection: sub startingAt: start ifAbsent: exceptionBlock\\n\\t| index |\\n\\tindex _ self findSubstring: sub in: self startingAt: start matchTable: CaseSensitiveOrder.\\n\\tindex = 0 ifTrue: [^ exceptionBlock value].\\n\\t^ index! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nlastIndexOfPKSignature: aSignature\\n\\t\\\"Answer the last index in me where aSignature (4 bytes long) occurs, or 0 if not found\\\"\\n\\t| a b c d |\\n\\ta _ aSignature first.\\n\\tb _ aSignature second.\\n\\tc _ aSignature third.\\n\\td _ aSignature fourth.\\n\\t(self size - 3) to: 1 by: -1 do: [ :i |\\n\\t\\t(((self at: i) = a)\\n\\t\\t\\tand: [ ((self at: i + 1) = b)\\n\\t\\t\\t\\tand: [ ((self at: i + 2) = c)\\n\\t\\t\\t\\t\\tand: [ ((self at: i + 3) = d) ]]])\\n\\t\\t\\t\\t\\t\\tifTrue: [ ^i ]\\n\\t].\\n\\t^0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 12/17/2002 16:56'!\\nleadingCharRunLengthAt: index\\n\\n\\t| leadingChar |\\n\\tleadingChar _ (self at: index) leadingChar.\\n\\tindex to: self size do: [:i |\\n\\t\\t(self at: i) leadingChar ~= leadingChar ifTrue: [^ i - index].\\n\\t].\\n\\t^ self size - index + 1.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:33'!\\nlineCorrespondingToIndex: anIndex\\n\\t\\\"Answer a string containing the line at the given character position. 1/15/96 sw: Inefficient first stab at this\\\"\\n\\n\\t| cr aChar answer |\\n\\tcr _ Character cr.\\n\\tanswer _ ''.\\n\\t1 to: self size do:\\n\\t\\t[:i | \\n\\t\\t\\taChar _ self at: i.\\n\\t\\t\\taChar = cr\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[i > anIndex\\n\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[^ answer]\\n\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[answer _ '']]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[answer _ answer copyWith: aChar]].\\n\\t^ answer! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:34'!\\nlineCount\\n\\t\\\"Answer the number of lines represented by the receiver, where every cr adds one line. 5/10/96 sw\\\"\\n\\n\\t| cr count |\\n\\tcr _ Character cr.\\n\\tcount _ 1 min: self size..\\n\\t1 to: self size do:\\n\\t\\t[:i | (self at: i) = cr ifTrue: [count _ count + 1]].\\n\\t^ count\\n\\n\\\"\\n'Fred\\nthe\\nBear' lineCount\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:34'!\\nlineNumber: anIndex\\n\\t\\\"Answer a string containing the characters in the given line number. 5/10/96 sw\\\"\\n\\n\\t| crString pos finalPos |\\n\\tcrString _ String with: Character cr.\\n\\tpos _ 0.\\n\\t1 to: anIndex - 1 do:\\n\\t\\t[:i | pos _ self findString: crString startingAt: pos + 1.\\n\\t\\t\\tpos = 0 ifTrue: [^ nil]].\\n\\tfinalPos _ self findString: crString startingAt: pos + 1.\\n\\tfinalPos = 0 ifTrue: [finalPos _ self size + 1].\\n\\t^ self copyFrom: pos + 1 to: finalPos - 1\\n\\n\\\"\\n'Fred\\nthe\\nBear' lineNumber: 3\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nlinesDo: aBlock\\n\\t\\\"execute aBlock with each line in this string. The terminating CR's are not included in what is passed to aBlock\\\"\\n\\t| start end |\\n\\tstart _ 1.\\n\\t[ start <= self size ] whileTrue: [\\n\\t\\tend _ self indexOf: Character cr startingAt: start ifAbsent: [ self size + 1 ].\\n\\t\\tend _ end - 1.\\n\\n\\t\\taBlock value: (self copyFrom: start to: end).\\n\\t\\tstart _ end + 2. ].! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/28/2002 14:28'!\\nskipAnySubStr: delimiters startingAt: start \\n\\t\\\"Answer the index of the last character within the receiver, starting at start, that does NOT match one of the delimiters. delimiters is a Array of substrings (Characters also allowed). If the receiver is all delimiters, answer size + 1.\\\"\\n\\n\\t| any this ind ii |\\n\\tii _ start-1.\\n\\t[(ii _ ii + 1) <= self size] whileTrue: [ \\\"look for char that does not match\\\"\\n\\t\\tany _ false.\\n\\t\\tdelimiters do: [:delim |\\n\\t\\t\\tdelim isCharacter \\n\\t\\t\\t\\tifTrue: [(self at: ii) == delim ifTrue: [any _ true]]\\n\\t\\t\\t\\tifFalse: [\\\"a substring\\\"\\n\\t\\t\\t\\t\\tdelim size > (self size - ii + 1) ifFalse: \\\"Here's where the one-off error was.\\\"\\n\\t\\t\\t\\t\\t\\t[ind _ 0.\\n\\t\\t\\t\\t\\t\\tthis _ true.\\n\\t\\t\\t\\t\\t\\tdelim do: [:dd | \\n\\t\\t\\t\\t\\t\\t\\tdd == (self at: ii+ind) ifFalse: [this _ false].\\n\\t\\t\\t\\t\\t\\t\\tind _ ind + 1].\\n\\t\\t\\t\\t\\t\\tthis ifTrue: [ii _ ii + delim size - 1. any _ true]]\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [any _ false] \\\"if the delim is too big, it can't match\\\"]].\\n\\t\\tany ifFalse: [^ ii]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nskipDelimiters: delimiters startingAt: start \\n\\t\\\"Answer the index of the character within the receiver, starting at start, that does NOT match 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.\\\"\\n\\n\\tstart to: self size do: [:i |\\n\\t\\tdelimiters detect: [:delim | delim = (self at: i)]\\n\\t\\t\\t\\tifNone: [^ i]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nstartsWithDigit\\n\\t\\\"Answer whether the receiver's first character represents a digit\\\"\\n\\n\\t^ self size > 0 and: [self first isDigit]! !\\n\\n!String methodsFor: 'accessing' stamp: 'md 5/26/2005 13:35'!\\nstring\\n\\t^self! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\ntabDelimitedFieldsDo: aBlock\\n\\t\\\"Considering the receiver as a holder of tab-delimited fields, evaluate execute aBlock with each field in this string. The separatilng tabs are not included in what is passed to aBlock\\\"\\n\\n\\t| start end |\\n\\t\\\"No senders but was useful enough in earlier work that it's retained for the moment.\\\"\\n\\tstart _ 1.\\n\\t[start <= self size] whileTrue: \\n\\t\\t[end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1].\\n\\t\\tend _ end - 1.\\n\\t\\taBlock value: (self copyFrom: start to: end).\\n\\t\\tstart _ end + 2]\\n\\n\\\"\\n'fred\\tcharlie\\telmo\\t\\t2' tabDelimitedFieldsDo: [:aField | Transcript cr; show: aField]\\n\\\"! !\\n\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n* arg\\n\\n\\t^ arg adaptToString: self andSend: #*! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n+ arg\\n\\n\\t^ arg adaptToString: self andSend: #+! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n- arg\\n\\n\\t^ arg adaptToString: self andSend: #-! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n/ arg\\n\\n\\t^ arg adaptToString: self andSend: #/! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n// arg\\n\\n\\t^ arg adaptToString: self andSend: #//! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n\\\\\\\\ arg\\n\\n\\t^ arg adaptToString: self andSend: #\\\\\\\\! !\\n\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:19'!\\n< aString \\n\\t\\\"Answer whether the receiver sorts before aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 1! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:20'!\\n<= aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\t\\n\\t^ (self compare: self with: aString collated: AsciiOrder) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n= aString \\n\\t\\\"Answer whether the receiver sorts equally as aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\t\\n\\taString isString ifFalse: [ ^ false ].\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n> aString \\n\\t\\\"Answer whether the receiver sorts after aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 3! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n>= aString \\n\\t\\\"Answer whether the receiver sorts after or equal to aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) >= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nalike: aString \\n\\t\\\"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.\\\"\\n\\n\\t| i j k minSize bonus |\\n\\tminSize _ (j _ self size) min: (k _ aString size).\\n\\tbonus _ (j - k) abs < 2 ifTrue: [ 1 ] ifFalse: [ 0 ].\\n\\ti _ 1.\\n\\t[(i <= minSize) and: [((super at: i) bitAnd: 16rDF) = ((aString at: i) asciiValue bitAnd: 16rDF)]]\\n\\t\\twhileTrue: [ i _ i + 1 ].\\n\\t[(j > 0) and: [(k > 0) and:\\n\\t\\t[((super at: j) bitAnd: 16rDF) = ((aString at: k) asciiValue bitAnd: 16rDF)]]]\\n\\t\\t\\twhileTrue: [ j _ j - 1. k _ k - 1. ].\\n\\t^ i - 1 + self size - j + bonus. ! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nbeginsWith: prefix\\n\\t\\\"Answer whether the receiver begins with the given prefix string.\\n\\tThe comparison is case-sensitive.\\\"\\n\\n\\tself size < prefix size ifTrue: [^ false].\\n\\t^ (self findSubstring: prefix in: self startingAt: 1\\n\\t\\t\\tmatchTable: CaseSensitiveOrder) = 1\\n! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:39'!\\ncaseInsensitiveLessOrEqual: aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is case insensitive.\\\"\\n\\t^(self compare: aString caseSensitive: false) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:39'!\\ncaseSensitiveLessOrEqual: aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is case sensitive.\\\"\\n\\t^(self compare: aString caseSensitive: true) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 8/27/2002 14:15'!\\ncharactersExactlyMatching: aString\\n\\t\\\"Do a character-by-character comparison between the receiver and aString. Return the index of the final character that matched exactly.\\\"\\n\\n\\t| count |\\n\\tcount _ self size min: aString size.\\n\\t1 to: count do: [:i | \\n\\t\\t(self at: i) = (aString at: i) ifFalse: [\\n\\t\\t\\t^ i - 1]].\\n\\t^ count! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:38'!\\ncompare: aString \\n\\t\\\"Answer a comparison code telling how the receiver sorts relative to aString:\\n\\t\\t1 - before\\n\\t\\t2 - equal\\n\\t\\t3 - after.\\n\\tThe collation sequence is ascii with case differences ignored.\\n\\tTo get the effect of a <= b, but ignoring case, use (a compare: b) <= 2.\\\"\\n\\t^self compare: aString caseSensitive: false! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:42'!\\ncompare: aString caseSensitive: aBool\\n\\t\\\"Answer a comparison code telling how the receiver sorts relative to aString:\\n\\t\\t1 - before\\n\\t\\t2 - equal\\n\\t\\t3 - after.\\n\\t\\\"\\n\\t| map |\\n\\tmap := aBool ifTrue:[CaseSensitiveOrder] ifFalse:[CaseInsensitiveOrder].\\n\\t^self compare: self with: aString collated: map! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 12/15/2005 14:28'!\\ncompare: string1 with: string2 collated: order\\n\\n\\t(string1 isByteString and: [string2 isByteString]) ifTrue: [\\n\\t\\t^ ByteString compare: string1 with: string2 collated: order\\n\\t].\\n \\\"Primitive does not fail properly right now\\\"\\n ^ String compare: string1 with: string2 collated: order\\n\\n\\\"\\nself assert: 'abc' = 'abc' asWideString.\\nself assert: 'abc' asWideString = 'abc'.\\nself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString ~= 'a000' asWideString).\\nself assert: ('a000' asWideString ~= (ByteArray with: 97 with: 0 with: 0 with: 0) asString).\\n\\nself assert: ('abc' sameAs: 'aBc' asWideString).\\nself assert: ('aBc' asWideString sameAs: 'abc').\\nself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString sameAs: 'Abcd' asWideString) not.\\nself assert: ('a000' asWideString sameAs: (ByteArray with: 97 with: 0 with: 0 with: 0) asString) not.\\n\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 17:27'!\\ncrc16\\n\\t\\\"Compute a 16 bit cyclic redundancy check.\\\"\\n\\n\\t| crc |\\n\\tcrc := 0.\\n\\t1 to: self byteSize do: [:i |\\n\\t\\tcrc := (crc bitShift: -8) bitXor: (\\n\\t\\t #(\\t16r0000\\t16rC0C1\\t16rC181\\t16r0140\\t16rC301\\t16r03C0\\t16r0280\\t16rC241\\n\\t\\t\\t16rC601\\t16r06C0\\t16r0780\\t16rC741\\t16r0500\\t16rC5C1\\t16rC481\\t16r0440\\n\\t\\t\\t16rCC01\\t16r0CC0\\t16r0D80\\t16rCD41\\t16r0F00\\t16rCFC1\\t16rCE81\\t16r0E40\\n\\t\\t\\t16r0A00\\t16rCAC1\\t16rCB81\\t16r0B40\\t16rC901\\t16r09C0\\t16r0880\\t16rC841\\n\\t\\t\\t16rD801\\t16r18C0\\t16r1980\\t16rD941\\t16r1B00\\t16rDBC1\\t16rDA81\\t16r1A40\\n\\t\\t\\t16r1E00\\t16rDEC1\\t16rDF81\\t16r1F40\\t16rDD01\\t16r1DC0\\t16r1C80\\t16rDC41\\n\\t\\t\\t16r1400\\t16rD4C1\\t16rD581\\t16r1540\\t16rD701\\t16r17C0\\t16r1680\\t16rD641\\n\\t\\t\\t16rD201\\t16r12C0\\t16r1380\\t16rD341\\t16r1100\\t16rD1C1\\t16rD081\\t16r1040\\n\\t\\t\\t16rF001\\t16r30C0\\t16r3180\\t16rF141\\t16r3300\\t16rF3C1\\t16rF281\\t16r3240\\n\\t\\t\\t16r3600\\t16rF6C1\\t16rF781\\t16r3740\\t16rF501\\t16r35C0\\t16r3480\\t16rF441\\n\\t\\t\\t16r3C00\\t16rFCC1\\t16rFD81\\t16r3D40\\t16rFF01\\t16r3FC0\\t16r3E80\\t16rFE41\\n\\t\\t\\t16rFA01\\t16r3AC0\\t16r3B80\\t16rFB41\\t16r3900\\t16rF9C1\\t16rF881\\t16r3840\\n\\t\\t\\t16r2800\\t16rE8C1\\t16rE981\\t16r2940\\t16rEB01\\t16r2BC0\\t16r2A80\\t16rEA41\\n\\t\\t\\t16rEE01\\t16r2EC0\\t16r2F80\\t16rEF41\\t16r2D00\\t16rEDC1\\t16rEC81\\t16r2C40\\n\\t\\t\\t16rE401\\t16r24C0\\t16r2580\\t16rE541\\t16r2700\\t16rE7C1\\t16rE681\\t16r2640\\n\\t\\t\\t16r2200\\t16rE2C1\\t16rE381\\t16r2340\\t16rE101\\t16r21C0\\t16r2080\\t16rE041\\n\\t\\t\\t16rA001\\t16r60C0\\t16r6180\\t16rA141\\t16r6300\\t16rA3C1\\t16rA281\\t16r6240\\n\\t\\t\\t16r6600\\t16rA6C1\\t16rA781\\t16r6740\\t16rA501\\t16r65C0\\t16r6480\\t16rA441\\n\\t\\t\\t16r6C00\\t16rACC1\\t16rAD81\\t16r6D40\\t16rAF01\\t16r6FC0\\t16r6E80\\t16rAE41\\n\\t\\t\\t16rAA01\\t16r6AC0\\t16r6B80\\t16rAB41\\t16r6900\\t16rA9C1\\t16rA881\\t16r6840\\n\\t\\t\\t16r7800\\t16rB8C1\\t16rB981\\t16r7940\\t16rBB01\\t16r7BC0\\t16r7A80\\t16rBA41\\n\\t\\t\\t16rBE01\\t16r7EC0\\t16r7F80\\t16rBF41\\t16r7D00\\t16rBDC1\\t16rBC81\\t16r7C40\\n\\t\\t\\t16rB401\\t16r74C0\\t16r7580\\t16rB541\\t16r7700\\t16rB7C1\\t16rB681\\t16r7640\\n\\t\\t\\t16r7200\\t16rB2C1\\t16rB381\\t16r7340\\t16rB101\\t16r71C0\\t16r7080\\t16rB041\\n\\t\\t\\t16r5000\\t16r90C1\\t16r9181\\t16r5140\\t16r9301\\t16r53C0\\t16r5280\\t16r9241\\n\\t\\t\\t16r9601\\t16r56C0\\t16r5780\\t16r9741\\t16r5500\\t16r95C1\\t16r9481\\t16r5440\\n\\t\\t\\t16r9C01\\t16r5CC0\\t16r5D80\\t16r9D41\\t16r5F00\\t16r9FC1\\t16r9E81\\t16r5E40\\n\\t\\t\\t16r5A00\\t16r9AC1\\t16r9B81\\t16r5B40\\t16r9901\\t16r59C0\\t16r5880\\t16r9841\\n\\t\\t\\t16r8801\\t16r48C0\\t16r4980\\t16r8941\\t16r4B00\\t16r8BC1\\t16r8A81\\t16r4A40\\n\\t\\t\\t16r4E00\\t16r8EC1\\t16r8F81\\t16r4F40\\t16r8D01\\t16r4DC0\\t16r4C80\\t16r8C41\\n\\t\\t\\t16r4400\\t16r84C1\\t16r8581\\t16r4540\\t16r8701\\t16r47C0\\t16r4680\\t16r8641\\n\\t\\t\\t16r8201\\t16r42C0\\t16r4380\\t16r8341\\t16r4100\\t16r81C1\\t16r8081\\t16r4040)\\n\\t\\t\\t at: ((crc bitXor: (self byteAt: i)) bitAnd: 16rFF) + 1) ].\\n\\t^crc! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nendsWith: suffix\\n\\t\\\"Answer whether the tail end of the receiver is the same as suffix.\\n\\tThe comparison is case-sensitive.\\\"\\n\\t| extra |\\n\\t(extra _ self size - suffix size) < 0 ifTrue: [^ false].\\n\\t^ (self findSubstring: suffix in: self startingAt: extra + 1\\n\\t\\t\\tmatchTable: CaseSensitiveOrder) > 0\\n\\\"\\n 'Elvis' endsWith: 'vis'\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nendsWithAnyOf: aCollection\\n\\taCollection do:[:suffix|\\n\\t\\t(self endsWith: suffix) ifTrue:[^true].\\n\\t].\\n\\t^false! !\\n\\n!String methodsFor: 'comparing' stamp: 'md 2/16/2006 17:49'!\\nhash\\n\\t\\\"#hash is implemented, because #= is implemented\\\"\\n\\t\\\"ar 4/10/2005: I had to change this to use ByteString hash as initial \\n\\thash in order to avoid having to rehash everything and yet compute\\n\\tthe same hash for ByteString and WideString.\\n\\tmd 16/10/2006: use identityHash as initialHash, as behavior hash will \\n use String hash (name) to have a better hash soon\\\"\\n\\t^ self class stringHash: self initialHash: ByteString identityHash! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nhashMappedBy: map\\n\\t\\\"My hash is independent of my oop.\\\"\\n\\n\\t^self hash! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nhowManyMatch: string \\n\\t\\\"Count the number of characters that match up in self and aString.\\\"\\n\\t| count shorterLength |\\n\\t\\n\\tcount _ 0 .\\n\\tshorterLength _ ((self size ) min: (string size ) ) .\\n\\t(1 to: shorterLength do: [:index |\\n\\t\\t (((self at: index ) = (string at: index ) ) ifTrue: [count _ (count + 1 ) .\\n\\t\\t\\t] ).\\n\\t\\t] ).\\n\\t^ count \\n\\t\\n\\t! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nmatch: text\\n\\t\\\"Answer whether text matches the pattern in this string.\\n\\tMatching ignores upper/lower case differences.\\n\\tWhere this string contains #, text may contain any character.\\n\\tWhere this string contains *, text may contain any sequence of characters.\\\"\\n\\n\\t^ self startingAt: 1 match: text startingAt: 1\\n\\\"\\n\\t'*'\\t\\t\\tmatch: 'zort' true\\n\\t'*baz'\\t\\tmatch: 'mobaz' true\\n\\t'*baz'\\t\\tmatch: 'mobazo' false\\n\\t'*baz*'\\t\\tmatch: 'mobazo' true\\n\\t'*baz*'\\t\\tmatch: 'mozo' false\\n\\t'foo*'\\t\\tmatch: 'foozo' true\\n\\t'foo*'\\t\\tmatch: 'bozo' false\\n\\t'foo*baz'\\tmatch: 'foo23baz' true\\n\\t'foo*baz'\\tmatch: 'foobaz' true\\n\\t'foo*baz'\\tmatch: 'foo23bazo' false\\n\\t'foo'\\t\\tmatch: 'Foo' true\\n\\t'foo*baz*zort' match: 'foobazort' false\\n\\t'foo*baz*zort' match: 'foobazzort' false\\n\\t'*foo#zort'\\tmatch: 'afoo3zortthenfoo3zort' true\\n\\t'*foo*zort'\\tmatch: 'afoodezortorfoo3zort' true\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 17:35'!\\nsameAs: aString \\n\\t\\\"Answer whether the receiver sorts equal to aString. The \\n\\tcollation sequence is ascii with case differences ignored.\\\"\\n\\t^(self compare: aString caseSensitive: false) = 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nstartingAt: keyStart match: text startingAt: textStart\\n\\t\\\"Answer whether text matches the pattern in this string.\\n\\tMatching ignores upper/lower case differences.\\n\\tWhere this string contains #, text may contain any character.\\n\\tWhere this string contains *, text may contain any sequence of characters.\\\"\\n\\t| anyMatch matchStart matchEnd i matchStr j ii jj |\\n\\ti _ keyStart.\\n\\tj _ textStart.\\n\\n\\t\\\"Check for any #'s\\\"\\n\\t[i > self size ifTrue: [^ j > text size \\\"Empty key matches only empty string\\\"].\\n\\t(self at: i) = $#] whileTrue:\\n\\t\\t[\\\"# consumes one char of key and one char of text\\\"\\n\\t\\tj > text size ifTrue: [^ false \\\"no more text\\\"].\\n\\t\\ti _ i+1. j _ j+1].\\n\\n\\t\\\"Then check for *\\\"\\n\\t(self at: i) = $*\\n\\t\\tifTrue: [i = self size ifTrue:\\n\\t\\t\\t\\t\\t[^ true \\\"Terminal * matches all\\\"].\\n\\t\\t\\t\\t\\\"* means next match string can occur anywhere\\\"\\n\\t\\t\\t\\tanyMatch _ true.\\n\\t\\t\\t\\tmatchStart _ i + 1]\\n\\t\\tifFalse: [\\\"Otherwise match string must occur immediately\\\"\\n\\t\\t\\t\\tanyMatch _ false.\\n\\t\\t\\t\\tmatchStart _ i].\\n\\n\\t\\\"Now determine the match string\\\"\\n\\tmatchEnd _ self size.\\n\\t(ii _ self indexOf: $* startingAt: matchStart) > 0 ifTrue:\\n\\t\\t[ii = 1 ifTrue: [self error: '** not valid -- use * instead'].\\n\\t\\tmatchEnd _ ii-1].\\n\\t(ii _ self indexOf: $# startingAt: matchStart) > 0 ifTrue:\\n\\t\\t[ii = 1 ifTrue: [self error: '*# not valid -- use #* instead'].\\n\\t\\tmatchEnd _ matchEnd min: ii-1].\\n\\tmatchStr _ self copyFrom: matchStart to: matchEnd.\\n\\n\\t\\\"Now look for the match string\\\"\\n\\t[jj _ text findString: matchStr startingAt: j caseSensitive: false.\\n\\tanyMatch ifTrue: [jj > 0] ifFalse: [jj = j]]\\n\\t\\twhileTrue:\\n\\t\\t[\\\"Found matchStr at jj. See if the rest matches...\\\"\\n\\t\\t(self startingAt: matchEnd+1 match: text startingAt: jj + matchStr size) ifTrue:\\n\\t\\t\\t[^ true \\\"the rest matches -- success\\\"].\\n\\t\\t\\\"The rest did not match.\\\"\\n\\t\\tanyMatch ifFalse: [^ false].\\n\\t\\t\\\"Preceded by * -- try for a later match\\\"\\n\\t\\tj _ j+1].\\n\\t^ false \\\"Failed to find the match string\\\"! !\\n\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToCollection: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a collection, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToNumber: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a number, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToPoint: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a point, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToString: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a string, convert us both to\\n\\tnumbers, and return the printString of the result.\\\"\\n\\n\\t^ (rcvr asNumber perform: selector with: self asNumber) printString! !\\n\\n!String methodsFor: 'converting' stamp: 'mw 1/30/2004 11:53'!\\nasAlphaNumeric: totalSize extraChars: additionallyAllowed mergeUID: minimalSizeOfRandomPart\\n\\t\\\"Generates a String with unique identifier ( UID ) qualities, the difference to a\\n\\t UUID is that its beginning is derived from the receiver, so that it has a meaning\\n\\t for a human reader.\\n\\n\\t Answers a String of totalSize, which consists of 3 parts\\n\\t 1.part: the beginning of the receiver only consisting of\\n\\t\\ta-z, A-Z, 0-9 and extraChars in Collection additionallyAllowed ( which can be nil )\\n\\t 2.part: a single _\\n\\t 3.part: a ( random ) UID of size >= minimalSizeOfRandomPart consisting of\\n\\t\\ta-z, A-Z, 0-9\\n\\n\\t Starting letters are capitalized. \\n\\t TotalSize must be at least 1.\\n\\t Exactly 1 occurrence of $_ is guaranteed ( unless additionallyAllowed includes $_ ).\\n\\t The random part has even for small sizes good UID qualitites for many practical purposes.\\n\\t If only lower- or uppercase letters are demanded, simply convert the answer with\\n\\t say #asLowercase. The probability of a duplicate will rise only moderately ( see below ).\\n\\n\\t Example: \\n\\t\\tsize of random part = 10\\n\\t\\tin n generated UIDs the chance p of having non-unique UIDs is\\n\\t\\t\\tn = 10000 -> p < 1e-10\\t\\tif answer is reduced to lowerCase: p < 1.4 e-8\\n\\t\\t\\tn = 100000 -> p < 1e-8\\n\\t\\tat the bottom is a snippet for your own calculations \\n\\t\\tNote: the calculated propabilites are theoretical,\\n\\t\\t\\tfor the actually used random generator they may be much worse\\\"\\n\\n\\t| stream out sizeOfFirstPart index ascii ch skip array random |\\n\\ttotalSize > minimalSizeOfRandomPart \\n\\t\\tifFalse: [ self errorOutOfBounds ].\\n\\tstream := ReadStream on: self.\\n\\tout := WriteStream on: ( String new: totalSize ).\\n\\tindex := 0.\\n\\tskip := true.\\n\\tsizeOfFirstPart := totalSize - minimalSizeOfRandomPart - 1.\\n\\t[ stream atEnd or: [ index >= sizeOfFirstPart ]]\\n\\twhileFalse: [\\n\\t\\t((( ascii := ( ch := stream next ) asciiValue ) >= 65 and: [ ascii <= 90 ]) or: [\\n\\t\\t\\t( ascii >= 97 and: [ ascii <= 122 ]) or: [\\t\\t\\t \\n\\t\\t\\tch isDigit or: [\\n\\t\\t\\tadditionallyAllowed notNil and: [ additionallyAllowed includes: ch ]]]])\\n\\t\\tifTrue: [\\n\\t\\t\\tskip\\n\\t\\t\\t\\tifTrue: [ out nextPut: ch asUppercase ]\\n\\t\\t\\t\\tifFalse: [ out nextPut: ch ].\\n\\t\\t\\tindex := index + 1.\\n\\t\\t\\tskip := false ]\\n\\t\\tifFalse: [ skip := true ]].\\n\\tout nextPut: $_.\\n\\tarray := Array new: 62.\\n\\t1 to: 26 do: [ :i |\\n\\t\\tarray at: i put: ( i + 64 ) asCharacter.\\n\\t\\tarray at: i + 26 put: ( i + 96 ) asCharacter ].\\n\\t53 to: 62 do: [ :i |\\n\\t\\tarray at: i put: ( i - 5 ) asCharacter ].\\n\\trandom := UUIDGenerator default randomGenerator. \\n\\ttotalSize - index - 1 timesRepeat: [\\n\\t\\tout nextPut: ( array atRandom: random )].\\n\\t^out contents\\n\\n\\t\\\"\\tcalculation of probability p for failure of uniqueness in n UIDs\\n\\t\\tNote: if answer will be converted to upper or lower case replace 62 with 36\\n\\t| n i p all |\\n\\tall := 62 raisedTo: sizeOfRandomPart.\\n\\ti := 1.\\n\\tp := 0.0 .\\n\\tn := 10000.\\n\\t[ i <= n ]\\n\\twhileTrue: [\\n\\t\\tp := p + (( i - 1 ) / all ).\\n\\t\\ti := i + 1 ].\\n\\tp \\n\\n\\tapproximation formula: n squared / ( 62.0 raisedTo: sizeOfRandomPart ) / 2 \\n\\t\\\" \\n\\n\\t\\\"'Crop SketchMorphs and Grab Screen Rect to JPG' \\n\\t\\t\\tasAlphaNumeric: 31 extraChars: nil mergeUID: 10 \\n\\t \\t\\t\\t'CropSketchMorphsAndG_iOw94jquN6'\\n\\t 'Monticello' \\n\\t\\t\\tasAlphaNumeric: 31 extraChars: nil mergeUID: 10 \\n\\t\\t\\t\\t'Monticello_kp6aV2l0IZK9uBULGOeG' \\n\\t 'version-', ( '1.1.2' replaceAll: $. with: $- )\\n\\t\\t\\tasAlphaNumeric: 31 extraChars: #( $- ) mergeUID: 10 \\n\\t\\t\\t\\t'Version-1-1-2_kuz2tMg2xX9iRLDVR'\\\"\\n\\t\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:18'!\\nasByteArray\\n\\t\\\"Convert to a ByteArray with the ascii values of the string.\\\"\\n\\t| b |\\n\\tb _ ByteArray new: self byteSize.\\n\\t1 to: self size * 4 do: [:i |\\n\\t\\tb at: i put: (self byteAt: i).\\n\\t].\\n\\t^ b.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 16:22'!\\nasByteString\\n\\t\\\"Convert the receiver into a ByteString\\\"\\n\\t^self asOctetString! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:03'!\\nasCharacter\\n\\t\\\"Answer the receiver's first character, or '*' if none. Idiosyncratic, provisional.\\\"\\n\\n\\t^ self size > 0 ifTrue: [self first] ifFalse:[$\\U00b7]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDate\\n\\t\\\"Many allowed forms, see Date>>#readFrom:\\\"\\n\\n\\t^ Date fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDateAndTime\\n\\n\\n\\n\\t\\\"Convert from UTC format\\\" \\t^ DateAndTime fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 10/22/2002 17:38'!\\nasDefaultDecodedString\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDisplayText\\n\\t\\\"Answer a DisplayText whose text string is the receiver.\\\"\\n\\n\\t^DisplayText text: self asText! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDuration\\n\\n\\t\\\"convert from [nnnd]hh:mm:ss[.nanos] format. [] implies optional elements\\\"\\n\\n\\n\\n\\t^ Duration fromString: self\\n\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 13:55'!\\nasFileName\\n\\t\\\"Answer a String made up from the receiver that is an acceptable file \\n\\tname.\\\"\\n\\n\\t| string checkedString |\\n\\tstring _ FileDirectory checkName: self fixErrors: true.\\n\\tcheckedString _ (FilePath pathName: string) asVmPathName.\\n\\t^ (FilePath pathName: checkedString isEncoded: true) asSqueakPathName.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:38'!\\nasFourCode\\n\\n\\t| result |\\n\\tself size = 4 ifFalse: [^self error: 'must be exactly four characters'].\\n\\tresult _ self inject: 0 into: [:val :each | 256 * val + each asciiValue].\\n\\t(result bitAnd: 16r80000000) = 0 \\n\\t\\tifFalse: [self error: 'cannot resolve fourcode'].\\n\\t(result bitAnd: 16r40000000) = 0 ifFalse: [^result - 16r80000000].\\n\\t^ result\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/26/2002 23:06'!\\nasHex\\n\\t| stream |\\n\\tstream _ WriteStream on: (String new: self size * 4).\\n\\tself do: [ :ch | stream nextPutAll: ch hex ].\\n\\t^stream contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasHtml\\n\\t\\\"Do the basic character conversion for HTML. Leave all original return \\n\\tand tabs in place, so can conver back by simply removing bracked \\n\\tthings. 4/4/96 tk\\\"\\n\\t| temp |\\n\\ttemp _ self copyReplaceAll: '&' with: '&'.\\n\\tHtmlEntities keysAndValuesDo:\\n\\t\\t[:entity :char |\\n\\t\\tchar = $& ifFalse:\\n\\t\\t\\t[temp _ temp copyReplaceAll: char asString with: '&' , entity , ';']].\\n\\ttemp _ temp copyReplaceAll: '\\t' with: '\\t<IMG SRC=\\\"tab.gif\\\" ALT=\\\" \\\">'.\\n\\ttemp _ temp copyReplaceAll: '\\n' with: '\\n<BR>'.\\n\\t^ temp\\n\\n\\\"\\n\\t'A<&>B' asHtml\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasIRCLowercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tlowercase, where 'lowercase' is by IRC's definition\\\"\\n\\n\\t^self collect: [ :c | c asIRCLowercase ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasIdentifier: shouldBeCapitalized\\n\\t\\\"Return a legal identifier, with first character in upper case if shouldBeCapitalized is true, else lower case. This will always return a legal identifier, even for an empty string\\\"\\n\\n\\t| aString firstChar firstLetterPosition |\\n\\taString _ self select: [:el | el isAlphaNumeric].\\n\\tfirstLetterPosition _ aString findFirst: [:ch | ch isLetter].\\n\\taString _ firstLetterPosition == 0\\n\\t\\tifFalse:\\n\\t\\t\\t[aString copyFrom: firstLetterPosition to: aString size]\\n\\t\\tifTrue:\\n\\t\\t\\t['a', aString].\\n\\tfirstChar _ shouldBeCapitalized ifTrue: [aString first asUppercase] ifFalse: [aString first asLowercase].\\n\\n\\t^ firstChar asString, (aString copyFrom: 2 to: aString size)\\n\\\"\\n'234Fred987' asIdentifier: false\\n'235Fred987' asIdentifier: true\\n'' asIdentifier: true\\n'()87234' asIdentifier: false\\n'())z>=PPve889 U >' asIdentifier: false\\n\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 09:55'!\\nasInteger \\n\\t^self asSignedInteger\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasLegalSelector\\n\\t| toUse |\\n\\ttoUse _ ''.\\n\\tself do:\\n\\t\\t[:char | char isAlphaNumeric ifTrue: [toUse _ toUse copyWith: char]].\\n\\t(self size == 0 or: [self first isLetter not])\\n\\t\\tifTrue:\\t\\t[toUse _ 'v', toUse].\\n\\n\\t^ toUse withFirstCharacterDownshifted\\n\\n\\\"'234znak 43 ) 2' asLegalSelector\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasLowercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tlowercase.\\\"\\n\\n\\t^ self copy asString translateToLowercase! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasNumber \\n\\t\\\"Answer the Number created by interpreting the receiver as the string \\n\\trepresentation of a number.\\\"\\n\\n\\t^Number readFromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 20:55'!\\nasOctetString\\n\\t\\\"Convert the receiver into an octet string\\\"\\n\\t| string |\\n\\tstring _ String new: self size.\\n\\t1 to: self size do: [:i | string at: i put: (self at: i)].\\n\\t^string! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:39'!\\nasPacked\\n\\t\\\"Convert to a longinteger that describes the string\\\"\\n\\n\\t^ self inject: 0 into: [ :pack :next | pack _ pack * 256 + next asInteger ].! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasParagraph\\n\\t\\\"Answer a Paragraph whose text string is the receiver.\\\"\\n\\n\\t^Paragraph withText: self asText! !\\n\\n!String methodsFor: 'converting' stamp: 'dew 9/13/2001 01:17'!\\nasPluralBasedOn: aNumberOrCollection\\n\\t\\\"Append an 's' to this string based on whether aNumberOrCollection is 1 or of size 1.\\\"\\n\\n\\t^ (aNumberOrCollection = 1 or:\\n\\t\\t[aNumberOrCollection isCollection and: [aNumberOrCollection size = 1]])\\n\\t\\t\\tifTrue: [self]\\n\\t\\t\\tifFalse: [self, 's']\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 09:54'!\\nasSignedInteger \\n\\t\\\"Returns the first signed integer it can find or nil.\\\"\\n\\n\\t| start stream |\\n\\tstart := self findFirst: [:char | char isDigit].\\n\\tstart isZero ifTrue: [^nil].\\n\\tstream := (ReadStream on: self) position: start.\\n\\tstream back = $- ifTrue: [stream back].\\n\\t^Integer readFrom: stream! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasSmalltalkComment\\n\\t\\\"return this string, munged so that it can be treated as a comment in Smalltalk code. Quote marks are added to the beginning and end of the string, and whenever a solitary quote mark appears within the string, it is doubled\\\"\\n\\n\\t^String streamContents: [ :str |\\n\\t\\t| quoteCount first |\\n\\n\\t\\tstr nextPut: $\\\".\\n\\t\\n\\t\\tquoteCount := 0.\\n\\t\\tfirst := true.\\n\\t\\tself do: [ :char |\\n\\t\\t\\tchar = $\\\"\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tfirst ifFalse: [\\n\\t\\t\\t\\t\\t\\tstr nextPut: char.\\n\\t\\t\\t\\t\\t\\tquoteCount := quoteCount + 1 ] ]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tquoteCount odd ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\\"add a quote to even the number of quotes in a row\\\"\\n\\t\\t\\t\\t\\t\\tstr nextPut: $\\\" ].\\n\\t\\t\\t\\t\\tquoteCount := 0.\\n\\t\\t\\t\\t\\tstr nextPut: char ].\\n\\t\\t\\tfirst := false ]. \\n\\n\\t\\tquoteCount odd ifTrue: [\\n\\t\\t\\t\\\"check at the end\\\"\\n\\t\\t\\tstr nextPut: $\\\". ].\\n\\n\\t\\tstr nextPut: $\\\".\\n\\t].\\n\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 12/19/2003 21:16'!\\nasSqueakPathName\\n\\n\\t^ self.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasString\\n\\t\\\"Answer this string.\\\"\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasStringOrText\\n\\t\\\"Answer this string.\\\"\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 19:24'!\\nasSymbol\\n\\t\\\"Answer the unique Symbol whose characters are the characters of the \\n\\tstring.\\\"\\n\\t^Symbol intern: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasText\\n\\t\\\"Answer a Text whose string is the receiver.\\\"\\n\\n\\t^Text fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasTime\\n\\t\\\"Many allowed forms, see Time>>readFrom:\\\"\\n\\n\\t^ Time fromString: self.! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasTimeStamp\\n\\t\\\"Convert from obsolete TimeStamp format\\\"\\n\\n\\n\\t^ TimeStamp fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:05'!\\nasUnHtml\\n\\t\\\"Strip out all Html stuff (commands in angle brackets <>) and convert\\nthe characters &<> back to their real value. Leave actual cr and tab as\\nthey were in text.\\\"\\n\\t| in out char rest did |\\n\\tin _ ReadStream on: self.\\n\\tout _ WriteStream on: (String new: self size).\\n\\t[in atEnd] whileFalse:\\n\\t\\t[in peek = $<\\n\\t\\t\\tifTrue: [in unCommand] \\t\\\"Absorb <...><...>\\\"\\n\\t\\t\\tifFalse: [(char _ in next) = $&\\n\\t\\t\\t\\t\\t\\tifTrue: [rest _ in upTo: $;.\\n\\t\\t\\t\\t\\t\\t\\t\\tdid _ out position.\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'lt' ifTrue: [out nextPut: $<].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'gt' ifTrue: [out nextPut: $>].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'amp' ifTrue: [out nextPut: $&].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'deg' ifTrue: [out nextPut: $\\U00b0].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'quot' ifTrue: [out nextPut: $\\\"].\\n\\t\\t\\t\\t\\t\\t\\t\\tdid = out position ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tself error: 'unknown encoded HTML char'.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"Please add it to this method\\\"]]\\n\\t\\t\\t\\t\\t\\tifFalse: [out nextPut: char]].\\n\\t\\t].\\n\\t^ out contents! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 10:02'!\\nasUnsignedInteger \\n\\t\\\"Returns the first integer it can find or nil.\\\"\\n\\n\\t| start stream |\\n\\tstart := self findFirst: [:char | char isDigit].\\n\\tstart isZero ifTrue: [^nil].\\n\\tstream := (ReadStream on: self) position: start - 1.\\n\\t^Integer readFrom: stream! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUppercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tuppercase.\\\"\\n\\n\\t^self copy asString translateToUppercase! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUrl\\n\\t\\\"convert to a Url\\\"\\n\\t\\\"'http://www.cc.gatech.edu/' asUrl\\\"\\n\\t\\\"msw://chaos.resnet.gatech.edu:9000/' asUrl\\\"\\n\\t^Url absoluteFromText: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUrlRelativeTo: aUrl\\n\\t^aUrl newFromRelativeText: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 2/24/2005 18:33'!\\nasVmPathName\\n\\n\\t^ (FilePath pathName: self) asVmPathName.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\naskIfAddStyle: priorMethod req: requestor\\n\\t^ self \\\"we are a string with no text style\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 17:36'!\\nasWideString \\n\\tself isWideString\\n\\t\\tifTrue:[^self]\\n\\t\\tifFalse:[^WideString from: self]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncapitalized\\n\\t\\\"Return a copy with the first letter capitalized\\\"\\n\\t| cap |\\n\\tself isEmpty ifTrue: [ ^self copy ].\\n\\tcap _ self copy.\\n\\tcap at: 1 put: (cap at: 1) asUppercase.\\n\\t^ cap! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncompressWithTable: tokens\\n\\t\\\"Return a string with all substrings that occur in tokens replaced\\n\\tby a character with ascii code = 127 + token index.\\n\\tThis will work best if tokens are sorted by size.\\n\\tAssumes this string contains no characters > 127, or that they\\n\\tare intentionally there and will not interfere with this process.\\\"\\n\\t| str null finalSize start result ri c ts |\\n\\tnull _ Character value: 0.\\n\\tstr _ self copyFrom: 1 to: self size. \\\"Working string will get altered\\\"\\n\\tfinalSize _ str size.\\n\\ttokens doWithIndex:\\n\\t\\t[:token :tIndex |\\n\\t\\tstart _ 1.\\n\\t\\t[(start _ str findString: token startingAt: start) > 0]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[ts _ token size.\\n\\t\\t\\t((start + ts) <= str size\\n\\t\\t\\t\\tand: [(str at: start + ts) = $ and: [tIndex*2 <= 128]])\\n\\t\\t\\t\\tifTrue: [ts _ token size + 1. \\\"include training blank\\\"\\n\\t\\t\\t\\t\\t\\tstr at: start put: (Character value: tIndex*2 + 127)]\\n\\t\\t\\t\\tifFalse: [str at: start put: (Character value: tIndex + 127)].\\n\\t\\t\\tstr at: start put: (Character value: tIndex + 127).\\n\\t\\t\\t1 to: ts-1 do: [:i | str at: start+i put: null].\\n\\t\\t\\tfinalSize _ finalSize - (ts - 1).\\n\\t\\t\\tstart _ start + ts]].\\n\\tresult _ String new: finalSize.\\n\\tri _ 0.\\n\\t1 to: str size do:\\n\\t\\t[:i | (c _ str at: i) = null ifFalse: [result at: (ri _ ri+1) put: c]].\\n\\t^ result! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncontractTo: smallSize\\n\\t\\\"return myself or a copy shortened by ellipsis to smallSize\\\"\\n\\t| leftSize |\\n\\tself size <= smallSize\\n\\t\\tifTrue: [^ self]. \\\"short enough\\\"\\n\\tsmallSize < 5\\n\\t\\tifTrue: [^ self copyFrom: 1 to: smallSize]. \\\"First N characters\\\"\\n\\tleftSize _ smallSize-2//2.\\n\\t^ self copyReplaceFrom: leftSize+1\\t\\t\\\"First N/2 ... last N/2\\\"\\n\\t\\tto: self size - (smallSize - leftSize - 3)\\n\\t\\twith: '...'\\n\\\"\\n\\t'A clear but rather long-winded summary' contractTo: 18\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:47'!\\nconvertFromEncoding: encodingName\\n\\t^self convertFromWithConverter: (TextConverter newForEncoding: encodingName)! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:47'!\\nconvertFromSuperSwikiServerString\\n\\t^self convertFromEncoding: 'shift_jis'! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/8/2004 12:02'!\\nconvertFromWithConverter: converter\\n\\n\\t| readStream writeStream c |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tc _ converter nextFromStream: readStream.\\n\\t\\tc ifNotNil: [writeStream nextPut: c] ifNil: [^ writeStream contents]\\n\\t].\\n\\t^ writeStream contents\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:49'!\\nconvertToEncoding: encodingName\\n\\t^self convertToWithConverter: (TextConverter newForEncoding: encodingName).! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:50'!\\nconvertToSuperSwikiServerString\\n\\t^self convertToEncoding: 'shift_jis'! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 14:01'!\\nconvertToSystemString\\n\\n\\t| readStream writeStream converter |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter _ LanguageEnvironment defaultSystemConverter.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tconverter nextPut: readStream next toStream: writeStream\\n\\t].\\n\\tconverter emitSequenceToResetStateIfNeededOn: writeStream.\\n\\t^ writeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/8/2004 12:01'!\\nconvertToWithConverter: converter\\n\\n\\t| readStream writeStream |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tconverter nextPut: readStream next toStream: writeStream\\n\\t].\\n\\tconverter emitSequenceToResetStateIfNeededOn: writeStream.\\n\\t^ writeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainst: wordList\\n\\t\\\"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:\\\"\\n\\t| results |\\n\\tresults _ self correctAgainst: wordList continuedFrom: nil.\\n\\tresults _ self correctAgainst: nil continuedFrom: results.\\n\\t^ results! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainst: wordList continuedFrom: oldCollection\\n\\t\\\"Like correctAgainst:. Use when you want to correct against several lists, give nil as the first oldCollection, and nil as the last wordList.\\\"\\n\\n\\t^ wordList isNil\\n\\t\\tifTrue: [ self correctAgainstEnumerator: nil\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]\\n\\t\\tifFalse: [ self correctAgainstEnumerator: [ :action | wordList do: action without: nil]\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainstDictionary: wordDict continuedFrom: oldCollection\\n\\t\\\"Like correctAgainst:continuedFrom:. Use when you want to correct against a dictionary.\\\"\\n\\n\\t^ wordDict isNil\\n\\t\\tifTrue: [ self correctAgainstEnumerator: nil\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]\\n\\t\\tifFalse: [ self correctAgainstEnumerator: [ :action | wordDict keysDo: action ]\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:04'!\\nencodeForHTTP\\n\\t\\\"change dangerous characters to their %XX form, for use in HTTP transactions\\\"\\n\\n\\t^ self encodeForHTTPWithTextEncoding: 'utf-8' conditionBlock: [:c | c isSafeForHTTP].\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:04'!\\nencodeForHTTPWithTextEncoding: encodingName\\n\\n\\t^ self encodeForHTTPWithTextEncoding: encodingName conditionBlock: [:c | c isSafeForHTTP].\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:03'!\\nencodeForHTTPWithTextEncoding: encodingName conditionBlock: conditionBlock\\n\\t\\\"change dangerous characters to their %XX form, for use in HTTP transactions\\\"\\n\\n\\t| httpSafeStream encodedStream cont |\\n\\thttpSafeStream _ WriteStream on: (String new).\\n\\tencodedStream _ MultiByteBinaryOrTextStream on: (String new: 6).\\n\\tencodedStream converter: (TextConverter newForEncoding: encodingName).\\n\\tself do: [:c |\\n\\t\\t(conditionBlock value: c)\\n\\t\\t\\tifTrue: [httpSafeStream nextPut: (Character value: c charCode)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tencodedStream text; reset.\\n\\t\\t\\t\\tencodedStream nextPut: c.\\n\\t\\t\\t\\tencodedStream position: 0.\\n\\t\\t\\t\\tencodedStream binary.\\n\\t\\t\\t\\tcont _ encodedStream contents.\\n\\t\\t\\t\\tcont do: [:byte |\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: $%.\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: (byte // 16) asHexDigit.\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: (byte \\\\\\\\ 16) asHexDigit.\\n\\t\\t\\t\\t].\\n\\t\\t\\t].\\n\\t].\\n\\t^ httpSafeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/5/2004 16:48'!\\nfindSelector\\n\\t\\\"Dan's code for hunting down selectors with keyword parts; while this doesn't give a true parse, in most cases it does what we want, in where it doesn't, we're none the worse for it.\\\"\\n\\t| sel possibleParens level n |\\n\\tsel _ self withBlanksTrimmed.\\n\\t(sel includes: $:) ifTrue:\\n\\t\\t[sel _ sel copyReplaceAll: ':' with: ': '.\\t\\\"for the style (aa max:bb) with no space\\\"\\n\\t\\tpossibleParens _ sel findTokens: Character separators.\\n\\t\\tsel _ self class streamContents:\\n\\t\\t\\t[:s | level _ 0.\\n\\t\\t\\tpossibleParens do:\\n\\t\\t\\t\\t[:token |\\n\\t\\t\\t\\t(level = 0 and: [token endsWith: ':'])\\n\\t\\t\\t\\t\\tifTrue: [s nextPutAll: token]\\n\\t\\t\\t\\t\\tifFalse: [(n _ token occurrencesOf: $( ) > 0 ifTrue: [level _ level + n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $[ ) > 0 ifTrue: [level _ level + n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $] ) > 0 ifTrue: [level _ level - n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $) ) > 0 ifTrue: [level _ level - n]]]]].\\n\\n\\tsel isEmpty ifTrue: [^ nil].\\n\\tsel isOctetString ifTrue: [sel _ sel asOctetString].\\n\\tSymbol hasInterned: sel ifTrue:\\n\\t\\t[:aSymbol | ^ aSymbol].\\n\\t^ nil! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ninitialIntegerOrNil\\n\\t\\\"Answer the integer represented by the leading digits of the receiver, or nil if the receiver does not begin with a digit\\\"\\n\\t| firstNonDigit |\\n\\t(self size == 0 or: [self first isDigit not]) ifTrue: [^ nil].\\n\\tfirstNonDigit _ (self findFirst: [:m | m isDigit not]).\\n\\tfirstNonDigit = 0 ifTrue: [firstNonDigit _ self size + 1].\\n\\t^ (self copyFrom: 1 to: (firstNonDigit - 1)) asNumber\\n\\\"\\n'234Whoopie' initialIntegerOrNil\\n'wimpy' initialIntegerOrNil\\n'234' initialIntegerOrNil\\n'2N' initialIntegerOrNil\\n'2' initialIntegerOrNil\\n' 89Ten ' initialIntegerOrNil\\n'78 92' initialIntegerOrNil\\n\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nkeywords\\n\\t\\\"Answer an array of the keywords that compose the receiver.\\\"\\n\\t| kwd char keywords |\\n\\tkeywords _ Array streamContents:\\n\\t\\t[:kwds | kwd _ WriteStream on: (String new: 16).\\n\\t\\t1 to: self size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\tkwd nextPut: (char _ self at: i).\\n\\t\\t\\tchar = $: ifTrue: \\n\\t\\t\\t\\t\\t[kwds nextPut: kwd contents.\\n\\t\\t\\t\\t\\tkwd reset]].\\n\\t\\tkwd isEmpty ifFalse: [kwds nextPut: kwd contents]].\\n\\t(keywords size >= 1 and: [(keywords at: 1) = ':']) ifTrue:\\n\\t\\t[\\\"Has an initial keyword, as in #:if:then:else:\\\"\\n\\t\\tkeywords _ keywords allButFirst].\\n\\t(keywords size >= 2 and: [(keywords at: keywords size - 1) = ':']) ifTrue:\\n\\t\\t[\\\"Has a final keyword, as in #nextPut::andCR\\\"\\n\\t\\tkeywords _ keywords copyReplaceFrom: keywords size - 1\\n\\t\\t\\t\\t\\t\\t\\t\\tto: keywords size with: {':' , keywords last}].\\n\\t^ keywords! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nnumericSuffix\\n\\t^ self stemAndNumericSuffix last\\n\\n\\\"\\n'abc98' numericSuffix\\n'98abc' numericSuffix\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nonlyLetters\\n\\t\\\"answer the receiver with only letters\\\"\\n\\t^ self select:[:each | each isLetter]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nromanNumber\\n\\t| value v1 v2 |\\n\\tvalue _ v1 _ v2 _ 0.\\n\\tself reverseDo:\\n\\t\\t[:each |\\n\\t\\tv1 _ #(1 5 10 50 100 500 1000) at: ('IVXLCDM' indexOf: each).\\n\\t\\tv1 >= v2\\n\\t\\t\\tifTrue: [value _ value + v1]\\n\\t\\t\\tifFalse: [value _ value - v1].\\n\\t\\tv2 _ v1].\\n\\t^ value! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsansPeriodSuffix\\n\\t\\\"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. \\\"\\n\\n\\t| likely |\\n\\tlikely _ self copyUpTo: $..\\n\\t^ likely size == 0\\n\\t\\tifTrue:\\t[self]\\n\\t\\tifFalse:\\t[likely]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 11:13'!\\nsplitInteger\\n\\t\\\"Answer an array that is a splitting of self into a string and an integer.\\n\\t'43Sam' ==> #(43 'Sam'). 'Try90' ==> #('Try' 90)\\n\\tBUT NOTE: 'Sam' ==> #('Sam' 0), and '90' ==> #('' 90) ie, (<string> <integer>).\\\"\\n\\n\\t| pos |\\n\\t(pos _ self findFirst: [:d | d isDigit not]) = 0 ifTrue: [^ Array with: '' with: self asNumber].\\n\\tself first isDigit ifTrue: [\\n\\t\\t^ Array with: (self copyFrom: 1 to: pos - 1) asNumber \\n\\t\\t\\t\\twith: (self copyFrom: pos to: self size)].\\n\\t(pos _ self findFirst: [:d | d isDigit]) = 0 ifTrue: [^ Array with: self with: 0].\\n\\t^ Array with: (self copyFrom: 1 to: pos - 1)\\n\\t\\t\\twith: (self copyFrom: pos to: self size) asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nstemAndNumericSuffix\\n\\t\\\"Parse the receiver into a string-valued stem and a numeric-valued suffix. 6/7/96 sw\\\"\\n\\n\\t| stem suffix position |\\n\\n\\tstem _ self.\\n\\tsuffix _ 0.\\n\\tposition _ 1.\\n\\t[stem endsWithDigit and: [stem size > 1]] whileTrue:\\n\\t\\t[suffix _ stem last digitValue * position + suffix.\\n\\t\\tposition _ position * 10.\\n\\t\\tstem _ stem copyFrom: 1 to: stem size - 1].\\n\\t^ Array with: stem with: suffix\\n\\n\\\"'Fred2305' stemAndNumericSuffix\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsubStrings\\n\\t\\\"Answer an array of the substrings that compose the receiver.\\\"\\n\\t#Collectn.\\n\\t\\\"Added 2000/04/08 For ANSI <readableString> protocol.\\\"\\n\\t^ self substrings! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 16:32'!\\nsubStrings: separators \\n\\t\\\"Answer an array containing the substrings in the receiver separated \\n\\tby the elements of separators.\\\"\\n\\t| char result sourceStream subString |\\n\\t#Collectn.\\n\\t\\\"Changed 2000/04/08 For ANSI <readableString> protocol.\\\"\\n\\t(separators isString or:[separators allSatisfy: [:element | element isKindOf: Character]])\\n\\t\\tifFalse: [^ self error: 'separators must be Characters.'].\\n\\tsourceStream := ReadStream on: self.\\n\\tresult := OrderedCollection new.\\n\\tsubString := String new.\\n\\t[sourceStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[char := sourceStream next.\\n\\t\\t\\t(separators includes: char)\\n\\t\\t\\t\\tifTrue: [subString notEmpty\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[result add: subString copy.\\n\\t\\t\\t\\t\\t\\t\\tsubString := String new]]\\n\\t\\t\\t\\tifFalse: [subString := subString , (String with: char)]].\\n\\tsubString notEmpty ifTrue: [result add: subString copy].\\n\\t^ result asArray! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsubstrings\\n\\t\\\"Answer an array of the substrings that compose the receiver.\\\"\\n\\t| result end beginning |\\n\\n\\tresult _ WriteStream on: (Array new: 10).\\n\\n\\n\\n\\tend _ 0.\\n\\t\\\"find one substring each time through this loop\\\"\\n\\t[ \\n\\t\\t\\\"find the beginning of the next substring\\\"\\n\\t\\tbeginning _ self indexOfAnyOf: CSNonSeparators startingAt: end+1 ifAbsent: [ nil ].\\n\\t\\tbeginning ~~ nil ] \\n\\twhileTrue: [\\n\\t\\t\\\"find the end\\\"\\n\\t\\tend _ self indexOfAnyOf: CSSeparators startingAt: beginning ifAbsent: [ self size + 1 ].\\n\\t\\tend _ end - 1.\\n\\n\\t\\tresult nextPut: (self copyFrom: beginning to: end).\\n\\n\\t].\\n\\n\\n\\t^result contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsurroundedBySingleQuotes\\n\\t\\\"Answer the receiver with leading and trailing quotes. \\\"\\n\\n\\t^ $' asString, self, $' asString! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/28/2002 15:14'!\\ntranslateFrom: start to: stop table: table\\n\\t\\\"translate the characters in the string by the given table, in place\\\"\\n\\tself class translate: self from: start to: stop table: table! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntranslateToLowercase\\n\\t\\\"Translate all characters to lowercase, in place\\\"\\n\\n\\tself translateWith: LowercasingTable! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntranslateToUppercase\\n\\t\\\"Translate all characters to lowercase, in place\\\"\\n\\n\\tself translateWith: UppercasingTable! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/28/2002 15:13'!\\ntranslateWith: table\\n\\t\\\"translate the characters in the string by the given table, in place\\\"\\n\\t^ self translateFrom: 1 to: self size table: table! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntruncateTo: smallSize\\n\\t\\\"return myself or a copy shortened to smallSize. 1/18/96 sw\\\"\\n\\n\\t^ self size <= smallSize\\n\\t\\tifTrue:\\n\\t\\t\\t[self]\\n\\t\\tifFalse:\\n\\t\\t\\t[self copyFrom: 1 to: smallSize]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntruncateWithElipsisTo: maxLength\\n\\t\\\"Return myself or a copy suitably shortened but with elipsis added\\\"\\n\\n\\t^ self size <= maxLength\\n\\t\\tifTrue:\\n\\t\\t\\t[self]\\n\\t\\tifFalse:\\n\\t\\t\\t[(self copyFrom: 1 to: (maxLength - 3)), '...']\\n\\n\\n\\t\\\"'truncateWithElipsisTo:' truncateWithElipsisTo: 20\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 9/22/2005 23:06'!\\nunescapePercents\\n\\t\\\"decode %xx form. This is the opposite of #encodeForHTTP\\\"\\n\\t^ self unescapePercentsWithTextEncoding: 'utf-8'.! !\\n\\n!String methodsFor: 'converting' stamp: 'ky 7/8/2006 17:56'!\\nunescapePercentsWithTextEncoding: encodingName \\n\\t\\\"decode string including %XX form\\\"\\n\\t| unescaped char asciiVal specialChars oldPos pos converter |\\n\\tunescaped := ReadWriteStream on: String new.\\n\\tspecialChars := '+%' asCharacterSet.\\n\\toldPos := 1.\\n\\t[pos := self indexOfAnyOf: specialChars startingAt: oldPos.\\n\\tpos > 0]\\n\\t\\twhileTrue: [unescaped\\n\\t\\t\\t\\tnextPutAll: (self copyFrom: oldPos to: pos - 1).\\n\\t\\t\\tchar := self at: pos.\\n\\t\\t\\t(char = $%\\n\\t\\t\\t\\t\\tand: [pos + 2 <= self size])\\n\\t\\t\\t\\tifTrue: [asciiVal := (self at: pos + 1) asUppercase digitValue * 16 + (self at: pos + 2) asUppercase digitValue.\\n\\t\\t\\t\\t\\tasciiVal > 255\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\tunescaped\\n\\t\\t\\t\\t\\t\\tnextPut: (Character value: asciiVal).\\n\\t\\t\\t\\t\\tpos := pos + 3.\\n\\t\\t\\t\\t\\tpos <= self size\\n\\t\\t\\t\\t\\t\\tifFalse: [char := nil].\\n\\t\\t\\t\\t\\toldPos := pos]\\n\\t\\t\\t\\tifFalse: [char = $+\\n\\t\\t\\t\\t\\t\\tifTrue: [unescaped nextPut: Character space]\\n\\t\\t\\t\\t\\t\\tifFalse: [unescaped nextPut: char].\\n\\t\\t\\t\\t\\toldPos := pos + 1]].\\n\\toldPos <= self size\\n\\t\\tifTrue: [unescaped\\n\\t\\t\\t\\tnextPutAll: (self copyFrom: oldPos to: self size)].\\n\\tconverter := (TextConverter newForEncoding: encodingName)\\n\\t\\t\\t\\tifNil: [TextConverter newForEncoding: nil].\\n\\t^ [unescaped contents convertFromWithConverter: converter]\\n\\t\\ton: Error\\n\\t\\tdo: [\\\"the contents may be squeak-encoded\\\"\\n\\t\\t\\tunescaped contents]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 11:20'!\\nunparenthetically\\n\\t\\\"If the receiver starts with (..( and ends with matching )..), strip them\\\"\\n\\n\\t| curr |\\n\\tcurr _ self.\\n\\t[((curr first = $() and: [curr last = $)])] whileTrue:\\n\\t\\t[curr _ curr copyFrom: 2 to: (curr size - 1)].\\n\\n\\t^ curr\\n\\n\\\"\\n\\n'((fred the bear))' unparenthetically\\n\\n\\\"\\n\\t\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nunzipped\\n\\t| magic1 magic2 |\\n\\tmagic1 _ (self at: 1) asInteger.\\n\\tmagic2 _ (self at: 2) asInteger.\\n\\t(magic1 = 16r1F and:[magic2 = 16r8B]) ifFalse:[^self].\\n\\t^(GZipReadStream on: self) upToEnd! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithBlanksCondensed\\n\\t\\\"Return a copy of the receiver with leading/trailing blanks removed\\n\\t and consecutive white spaces condensed.\\\"\\n\\n\\t| trimmed lastBlank |\\n\\ttrimmed _ self withBlanksTrimmed.\\n\\t^String streamContents: [:stream |\\n\\t\\tlastBlank _ false.\\n\\t\\ttrimmed do: [:c | (c isSeparator and: [lastBlank]) ifFalse: [stream nextPut: c].\\n\\t\\t\\tlastBlank _ c isSeparator]].\\n\\n\\t\\\" ' abc d ' withBlanksCondensed\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/5/2004 16:43'!\\nwithBlanksTrimmed\\n\\t\\\"Return a copy of the receiver from which leading and trailing blanks have been trimmed.\\\"\\n\\n\\t| first result |\\n\\tfirst _ self findFirst: [:c | c isSeparator not].\\n\\tfirst = 0 ifTrue: [^ '']. \\\"no non-separator character\\\"\\n\\tresult _ self\\n\\t\\tcopyFrom: first\\n\\t\\tto: (self findLast: [:c | c isSeparator not]).\\n\\tresult isOctetString ifTrue: [^ result asOctetString] ifFalse: [^ result].\\n\\n\\t\\\" ' abc d ' withBlanksTrimmed\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'md 9/19/2004 15:19'!\\nwithFirstCharacterDownshifted\\n\\t\\\"Return a copy with the first letter downShifted\\\"\\n\\t\\n\\t| answer |\\n\\t\\n\\tself ifEmpty: [^ self copy].\\n\\tanswer _ self copy.\\n\\tanswer at: 1 put: (answer at: 1) asLowercase.\\n\\t^ answer. ! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithNoLineLongerThan: aNumber\\n\\t\\\"Answer a string with the same content as receiver, but rewrapped so that no line has more characters than the given number\\\"\\n\\t| listOfLines currentLast currentStart resultString putativeLast putativeLine crPosition |\\n\\taNumber isNumber not | (aNumber < 1) ifTrue: [self error: 'too narrow'].\\n\\tlistOfLines _ OrderedCollection new.\\n\\tcurrentLast _ 0.\\n\\t[currentLast < self size] whileTrue:\\n\\t\\t[currentStart _ currentLast + 1.\\n\\t\\tputativeLast _ (currentStart + aNumber - 1) min: self size.\\n\\t\\tputativeLine _ self copyFrom: currentStart to: putativeLast.\\n\\t\\t(crPosition _ putativeLine indexOf: Character cr) > 0 ifTrue:\\n\\t\\t\\t[putativeLast _ currentStart + crPosition - 1.\\n\\t\\t\\tputativeLine _ self copyFrom: currentStart to: putativeLast].\\n\\t\\tcurrentLast _ putativeLast == self size\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[putativeLast]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[currentStart + putativeLine lastSpacePosition - 1].\\n\\t\\tcurrentLast <= currentStart ifTrue:\\n\\t\\t\\t[\\\"line has NO spaces; baleout!!\\\"\\n\\t\\t\\tcurrentLast _ putativeLast].\\n\\t\\tlistOfLines add: (self copyFrom: currentStart to: currentLast) withBlanksTrimmed].\\n\\n\\tlistOfLines size > 0 ifFalse: [^ ''].\\n\\tresultString _ listOfLines first.\\n\\t2 to: listOfLines size do:\\n\\t\\t[:i | resultString _ resultString, String cr, (listOfLines at: i)].\\n\\t^ resultString\\n\\n\\\"#(5 7 20) collect:\\n\\t[:i | 'Fred the bear went down to the brook to read his book in silence' withNoLineLongerThan: i]\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'md 10/5/2005 11:01'!\\nwithoutLeadingBlanks\\n\\t\\n\\t\\\"Return a copy of the receiver from which leading blanks have been\\ntrimmed.\\\"\\n\\n\\t\\n\\t| first |\\n\\t\\n\\tfirst := self findFirst: [:c | c isSeparator not ].\\n\\n\\tfirst = 0 ifTrue: [^ '']. \\n\\t\\n\\t\\\"no non-separator character\\\"\\n\\t\\n\\t^ self copyFrom: first to: self size\\n\\n\\t\\n\\t\\t\\n\\t\\\" ' abc d' withoutLeadingBlanks\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'tak 4/25/2004 12:57'!\\nwithSeparatorsCompacted\\n\\t\\\"replace each sequences of whitespace by a single space character\\\"\\n\\t\\\"' test ' withSeparatorsCompacted = ' test '\\\"\\n\\t\\\"' test test' withSeparatorsCompacted = ' test test'\\\"\\n\\t\\\"'test test\\t\\t' withSeparatorsCompacted = 'test test '\\\"\\n\\n\\t| out in next isSeparator |\\n\\tself isEmpty ifTrue: [^ self].\\n\\n\\tout _ WriteStream on: (String new: self size).\\n\\tin _ self readStream.\\n\\tisSeparator _ [:char | char asciiValue < 256\\n\\t\\t\\t\\tand: [CSSeparators includes: char]].\\n\\t[in atEnd] whileFalse: [\\n\\t\\tnext _ in next.\\n\\t\\t(isSeparator value: next)\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tout nextPut: $ .\\n\\t\\t\\t\\t[in atEnd or:\\n\\t\\t\\t\\t\\t[next _ in next.\\n\\t\\t\\t\\t\\t(isSeparator value: next)\\n\\t\\t\\t\\t\\t\\tifTrue: [false]\\n\\t\\t\\t\\t\\t\\tifFalse: [out nextPut: next. true]]] whileFalse]\\n\\t\\t\\tifFalse: [out nextPut: next]].\\n\\t^ out contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:06'!\\nwithoutLeadingDigits\\n\\t\\\"Answer the portion of the receiver that follows any leading series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string\\\"\\n\\t| firstNonDigit |\\n\\tfirstNonDigit _ (self findFirst: [:m | m isDigit not and: [m ~= $ ]]).\\n\\t^ firstNonDigit > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self copyFrom: firstNonDigit to: self size]\\n\\t\\tifFalse:\\n\\t\\t\\t['']\\n\\n\\\"\\n'234Whoopie' withoutLeadingDigits\\n' 4321 BlastOff!!' withoutLeadingDigits\\n'wimpy' withoutLeadingDigits\\n' 89Ten ' withoutLeadingDigits\\n'78 92' withoutLeadingDigits\\n\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithoutTrailingBlanks\\n\\t\\\"Return a copy of the receiver from which trailing blanks have been trimmed.\\\"\\n\\n\\t| last |\\n\\tlast _ self findLast: [:c | c isSeparator not].\\n\\tlast = 0 ifTrue: [^ '']. \\\"no non-separator character\\\"\\n\\t^ self copyFrom: 1 to: last\\n\\n\\t\\\" ' abc d ' withoutTrailingBlanks\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:06'!\\nwithoutTrailingDigits\\n\\t\\\"Answer the portion of the receiver that precedes any trailing series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string\\\"\\n\\t| firstDigit |\\n\\tfirstDigit _ (self findFirst: [:m | m isDigit or: [m = $ ]]).\\n\\t^ firstDigit > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self copyFrom: 1 to: firstDigit-1]\\n\\t\\tifFalse:\\n\\t\\t\\t[self]\\n\\n\\\"\\n'Whoopie234' withoutTrailingDigits\\n' 4321 BlastOff!!' withoutLeadingDigits\\n'wimpy' withoutLeadingDigits\\n' 89Ten ' withoutLeadingDigits\\n'78 92' withoutLeadingDigits\\n\\\"\\n! !\\n\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\ncopyReplaceTokens: oldSubstring with: newSubstring \\n\\t\\\"Replace all occurrences of oldSubstring that are surrounded\\n\\tby non-alphanumeric characters\\\"\\n\\t^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: true\\n\\t\\\"'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Snick'\\\"! !\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\ndeepCopy\\n\\t\\\"DeepCopy would otherwise mean make a copy of the character; since \\n\\tcharacters are unique, just return a shallowCopy.\\\"\\n\\n\\t^self shallowCopy! !\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\npadded: leftOrRight to: length with: char\\n\\tleftOrRight = #left ifTrue:\\n\\t\\t[^ (String new: (length - self size max: 0) withAll: char) , self].\\n\\tleftOrRight = #right ifTrue:\\n\\t\\t[^ self , (String new: (length - self size max: 0) withAll: char)].! !\\n\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayAt: aPoint \\n\\t\\\"Display the receiver as a DisplayText at aPoint on the display screen.\\\"\\n\\n\\tself displayOn: Display at: aPoint! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium\\n\\t\\\"Display the receiver on the given DisplayMedium. 5/16/96 sw\\\"\\n\\n\\tself displayOn: aDisplayMedium at: 0 @ 0! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium at: aPoint \\n\\t\\\"Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, using black-colored text.\\\"\\n\\n\\tself displayOn: aDisplayMedium at: aPoint textColor: Color black! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium at: aPoint textColor: aColor\\n\\t\\\"Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, rendering the text in the designated color\\\"\\n\\n\\t(self asDisplayText foregroundColor: (aColor ifNil: [Color black]) backgroundColor: Color white)\\n\\t\\tdisplayOn: aDisplayMedium at: aPoint! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayProgressAt: aPoint from: minVal to: maxVal during: workBlock \\n\\t\\\"Display this string as a caption over a progress bar while workBlock is evaluated.\\n\\nEXAMPLE (Select next 6 lines and Do It)\\n'Now here''s some Real Progress'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: 10\\n\\tduring: [:bar |\\n\\t1 to: 10 do: [:x | bar value: x.\\n\\t\\t\\t(Delay forMilliseconds: 500) wait]].\\n\\nHOW IT WORKS (Try this in any other language :-)\\nSince your code (the last 2 lines in the above example) is in a block,\\nthis method gets control to display its heading before, and clean up \\nthe screen after, its execution.\\nThe key, though, is that the block is supplied with an argument,\\nnamed 'bar' in the example, which will update the bar image every \\nit is sent the message value: x, where x is in the from:to: range.\\n\\\"\\n\\t^ProgressInitiationException \\n\\t\\tdisplay: self\\n\\t\\tat: aPoint \\n\\t\\tfrom: minVal \\n\\t\\tto: maxVal \\n\\t\\tduring: workBlock! !\\n\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:16'!\\ngetInteger32: location\\n\\t| integer |\\n\\t<primitive: 'getInteger' module: 'IntegerPokerPlugin'>\\n\\t\\\"^IntegerPokerPlugin doPrimitive: #getInteger\\\"\\n\\n\\t\\\"the following is about 7x faster than interpreting the plugin if not compiled\\\"\\n\\n\\tinteger := \\n\\t\\t((self at: location) asInteger bitShift: 24) +\\n\\t\\t((self at: location+1) asInteger bitShift: 16) +\\n\\t\\t((self at: location+2) asInteger bitShift: 8) +\\n\\t\\t(self at: location+3) asInteger.\\n\\n\\tinteger > 1073741824 ifTrue: [^1073741824 - integer ].\\n\\t^integer\\n! !\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:17'!\\nputInteger32: anInteger at: location\\n\\t| integer |\\n\\t<primitive: 'putInteger' module: 'IntegerPokerPlugin'>\\n\\t\\\"IntegerPokerPlugin doPrimitive: #putInteger\\\"\\n\\n\\t\\\"the following is close to 20x faster than the above if the primitive is not compiled\\\"\\n\\t\\\"PUTCOUNTER _ PUTCOUNTER + 1.\\\"\\n\\tinteger _ anInteger.\\n\\tinteger < 0 ifTrue: [integer := 1073741824 - integer. ].\\n\\tself at: location+3 put: (Character value: (integer \\\\\\\\ 256)).\\n\\tself at: location+2 put: (Character value: (integer bitShift: -8) \\\\\\\\ 256).\\n\\tself at: location+1 put: (Character value: (integer bitShift: -16) \\\\\\\\ 256).\\n\\tself at: location put: (Character value: (integer bitShift: -24) \\\\\\\\ 256).\\n\\n\\\"Smalltalk at: #PUTCOUNTER put: 0\\\"! !\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:18'!\\nwriteLeadingCharRunsOn: stream\\n\\n\\t| runLength runValues runStart leadingChar |\\n\\tself isEmpty ifTrue: [^ self].\\n\\n\\trunLength _ OrderedCollection new.\\n\\trunValues _ OrderedCollection new.\\n\\trunStart _ 1.\\n\\tleadingChar _ (self at: runStart) leadingChar.\\n\\t2 to: self size do: [:index |\\n\\t\\t(self at: index) leadingChar = leadingChar ifFalse: [\\n\\t\\t\\trunValues add: leadingChar.\\n\\t\\t\\trunLength add: (index - runStart).\\n\\t\\t\\tleadingChar _ (self at: index) leadingChar.\\n\\t\\t\\trunStart _ index.\\n\\t\\t].\\n\\t].\\n\\trunValues add: (self last) leadingChar.\\n\\trunLength add: self size + 1 - runStart.\\n\\n\\tstream nextPut: $(.\\n\\trunLength do: [:rr | rr printOn: stream. stream space].\\n\\tstream skip: -1; nextPut: $).\\n\\trunValues do: [:vv | vv printOn: stream. stream nextPut: $,].\\n\\tstream skip: -1.\\n! !\\n\\n\\n!String methodsFor: 'filter streaming' stamp: 'yo 8/26/2002 22:31'!\\nbyteEncode:aStream\\n\\n\\t^aStream writeString: self.\\n! !\\n\\n!String methodsFor: 'filter streaming' stamp: 'yo 8/26/2002 22:31'!\\nputOn:aStream\\n\\n\\t^aStream nextPutAll: self.\\n! !\\n\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacros\\n\\t^self expandMacrosWithArguments: #()! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWithArguments: anArray \\n\\t| newStream readStream char index |\\n\\tnewStream := WriteStream on: (String new: self size).\\n\\treadStream := ReadStream on: self.\\n\\t[readStream atEnd] whileFalse: \\n\\t\\t\\t[char := readStream next.\\n\\t\\t\\tchar == $< \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[| nextChar |\\n\\t\\t\\t\\t\\tnextChar := readStream next asUppercase.\\n\\t\\t\\t\\t\\tnextChar == $N ifTrue: [newStream cr].\\n\\t\\t\\t\\t\\tnextChar == $T ifTrue: [newStream tab].\\n\\t\\t\\t\\t\\tnextChar isDigit \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[index := nextChar digitValue.\\n\\t\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t\\t[readStream atEnd \\n\\t\\t\\t\\t\\t\\t\\t\\tor: [(nextChar := readStream next asUppercase) isDigit not]] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twhileFalse: [index := index * 10 + nextChar digitValue]].\\n\\t\\t\\t\\t\\tnextChar == $? \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[| trueString falseString |\\n\\t\\t\\t\\t\\t\\t\\ttrueString := readStream upTo: $:.\\n\\t\\t\\t\\t\\t\\t\\tfalseString := readStream upTo: $>.\\n\\t\\t\\t\\t\\t\\t\\treadStream position: readStream position - 1.\\n\\t\\t\\t\\t\\t\\t\\tnewStream \\n\\t\\t\\t\\t\\t\\t\\t\\tnextPutAll: ((anArray at: index) ifTrue: [trueString] ifFalse: [falseString])].\\n\\t\\t\\t\\t\\tnextChar == $P \\n\\t\\t\\t\\t\\t\\tifTrue: [newStream nextPutAll: (anArray at: index) printString].\\n\\t\\t\\t\\t\\tnextChar == $S ifTrue: [newStream nextPutAll: (anArray at: index)].\\n\\t\\t\\t\\t\\treadStream skipTo: $>]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[newStream nextPut: (char == $% ifTrue: [readStream next] ifFalse: [char])]].\\n\\t^newStream contents! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject \\n\\t^self expandMacrosWithArguments: (Array with: anObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject \\n\\t^self \\n\\t\\texpandMacrosWithArguments: (Array with: anObject with: anotherObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject with: thirdObject \\n\\t^self expandMacrosWithArguments: (Array \\n\\t\\t\\t\\twith: anObject\\n\\t\\t\\t\\twith: anotherObject\\n\\t\\t\\t\\twith: thirdObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject with: thirdObject with: fourthObject \\n\\t^self expandMacrosWithArguments: (Array \\n\\t\\t\\t\\twith: anObject\\n\\t\\t\\t\\twith: anotherObject\\n\\t\\t\\t\\twith: thirdObject\\n\\t\\t\\t\\twith: fourthObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'yo 11/3/2004 19:24'!\\nformat: aCollection \\n\\t\\\"format the receiver with aCollection \\n\\t \\n\\tsimplest example: \\n\\t'foo {1} bar' format: {Date today}.\\n\\t \\n\\tcomplete example: \\n\\t'\\\\{ \\\\} \\\\\\\\ foo {1} bar {2}' format: {12. 'string'}. \\n\\t\\\"\\n\\t| result stream |\\n\\tresult := String new writeStream.\\n\\tstream := self readStream.\\n\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [| currentChar | \\n\\t\\t\\tcurrentChar := stream next.\\n\\t\\t\\tcurrentChar == ${\\n\\t\\t\\t\\tifTrue: [| expression | \\n\\t\\t\\t\\t\\texpression := self getEnclosedExpressionFrom: stream.\\n\\t\\t\\t\\t\\tresult\\n\\t\\t\\t\\t\\t\\tnextPutAll: (self evaluateExpression: expression parameters: aCollection)]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tcurrentChar == $\\\\\\n\\t\\t\\t\\t\\t\\tifTrue: [stream atEnd\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [result nextPut: stream next]]\\n\\t\\t\\t\\t\\t\\tifFalse: [result nextPut: currentChar]]].\\n\\n\\t^ result contents! !\\n\\n!String methodsFor: 'formatting' stamp: 'yo 11/3/2004 19:24'!\\nwithCRs\\n\\t\\\"Return a copy of the receiver in which backslash (\\\\) characters have been replaced with carriage returns.\\\"\\n\\n\\t^ self collect: [ :c | c = $\\\\ ifTrue: [ Character cr ] ifFalse: [ c ]].! !\\n\\n\\n!String methodsFor: 'internet' stamp: 'yo 12/28/2003 01:17'!\\ndecodeMimeHeader\\n\\t\\\"See RFC 2047, MIME Part Three: Message Header Extension for Non-ASCII \\n\\tText. Text containing non-ASCII characters is encoded by the sequence \\n\\t=?character-set?encoding?encoded-text?= \\n\\tEncoding is Q (quoted printable) or B (Base64), handled by \\n\\tBase64MimeConverter / RFC2047MimeConverter.\\n\\n\\tThanks to Yokokawa-san, it works in m17n package. Try the following:\\n\\n\\t'=?ISO-2022-JP?B?U1dJS0lQT1AvGyRCPUJDKyVpJXMlQRsoQi8=?= =?ISO-2022-JP?B?GyRCJVElRiUjJSobKEIoUGF0aW8p?=' decodeMimeHeader.\\n\\\"\\n\\t| input output temp charset decoder encodedStream encoding pos |\\n\\tinput _ ReadStream on: self.\\n\\toutput _ WriteStream on: String new.\\n\\t[output\\n\\t\\tnextPutAll: (input upTo: $=).\\n\\t\\\"ASCII Text\\\"\\n\\tinput atEnd]\\n\\t\\twhileFalse: [(temp _ input next) = $?\\n\\t\\t\\t\\tifTrue: [charset _ input upTo: $?.\\n\\t\\t\\t\\t\\tencoding _ (input upTo: $?) asUppercase.\\n\\t\\t\\t\\t\\ttemp _ input upTo: $?.\\n\\t\\t\\t\\t\\tinput next.\\n\\t\\t\\t\\t\\t\\\"Skip final =\\\"\\n\\t\\t\\t\\t\\t(charset isNil or: [charset size = 0]) ifTrue: [charset _ 'LATIN-1'].\\n\\t\\t\\t\\t\\tencodedStream _ MultiByteBinaryOrTextStream on: String new encoding: charset.\\n\\t\\t\\t\\t\\tdecoder _ encoding = 'B'\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [Base64MimeConverter new]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [RFC2047MimeConverter new].\\n\\t\\t\\t\\t\\tdecoder\\n\\t\\t\\t\\t\\t\\tmimeStream: (ReadStream on: temp);\\n\\t\\t\\t\\t\\t\\t dataStream: encodedStream;\\n\\t\\t\\t\\t\\t\\t mimeDecode.\\n\\t\\t\\t\\t\\toutput nextPutAll: encodedStream reset contents.\\n\\t\\t\\t\\t\\tpos _ input position.\\n\\t\\t\\t\\t\\tinput skipSeparators.\\n\\t\\t\\t\\t\\t\\\"Delete spaces if followed by =\\\"\\n\\t\\t\\t\\t\\tinput peek = $=\\n\\t\\t\\t\\t\\t\\tifFalse: [input position: pos]]\\n\\t\\t\\t\\tifFalse: [output nextPut: $=;\\n\\t\\t\\t\\t\\t\\t nextPut: temp]].\\n\\t^ output contents! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\ndecodeQuotedPrintable\\n\\t\\\"Assume receiver is in MIME 'quoted-printable' encoding, and decode it.\\\"\\n \\n\\t^QuotedPrintableMimeConverter mimeDecode: self as: self class! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/9/2005 22:16'!\\nisoToSqueak\\n\\t^self \\\"no longer needed\\\"! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nisoToUtf8\\n\\t\\\"Convert ISO 8559-1 to UTF-8\\\"\\n\\t| s v |\\n\\ts _ WriteStream on: (String new: self size).\\n\\n\\tself do: [:c |\\n\\t\\tv _ c asciiValue.\\n\\t\\t(v > 128)\\n\\t\\t\\tifFalse: [s nextPut: c]\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\ts nextPut: (192+(v >> 6)) asCharacter.\\n\\t\\t\\t\\ts nextPut: (128+(v bitAnd: 63)) asCharacter]].\\n\\t^s contents. \\n! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/10/2005 15:58'!\\nmacToSqueak\\n\\t\\\"Convert the receiver from MacRoman to Squeak encoding\\\"\\n\\t^ self collect: [:each | each macToSqueak]! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/9/2005 22:16'!\\nsqueakToIso\\n\\t^self \\\"no longer needed\\\"! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/10/2005 15:55'!\\nsqueakToMac\\n\\t\\\"Convert the receiver from Squeak to MacRoman encoding\\\"\\n\\t^ self collect: [:each | each squeakToMac]! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nutf8ToIso\\n\\t\\\"Only UTF-8 characters that maps to 8-bit ISO-8559-1 values are converted. Others raises an error\\\"\\n\\t| s i c v c2 v2 |\\n\\ts _ WriteStream on: (String new: self size).\\n\\t\\n\\ti _ 1.\\n\\t[i <= self size] whileTrue: [\\n\\t\\tc _ self at: i. i_i+1.\\n\\t\\tv _ c asciiValue.\\n\\t\\t(v > 128)\\n\\t\\t\\tifFalse: [ s nextPut: c ]\\n\\t\\t\\tifTrue: [((v bitAnd: 252) == 192)\\n\\t\\t\\t\\tifFalse: [self error: 'illegal UTF-8 ISO character']\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t(i > self size) ifTrue: [ self error: 'illegal end-of-string, expected 2nd byte of UTF-8'].\\n\\t\\t\\t\\t\\tc2 _ self at: i. i_i+1.\\n\\t\\t\\t\\t\\tv2 _ c2 asciiValue.\\n\\t\\t\\t\\t\\t((v2 bitAnd: 192) = 128) ifFalse: [self error: 'illegal 2nd UTF-8 char']. \\n\\t\\t\\t\\t\\ts nextPut: ((v2 bitAnd: 63) bitOr: ((v << 6) bitAnd: 192)) asCharacter]]].\\n\\t^s contents. \\n! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithInternetLineEndings\\n\\t\\\"change line endings from CR's to CRLF's. This is probably in\\nprepration for sending a string over the Internet\\\"\\n\\t| cr lf |\\n\\tcr _ Character cr.\\n\\tlf _ Character linefeed.\\n\\t^self class streamContents: [ :stream |\\n\\t\\tself do: [ :c |\\n\\t\\t\\tstream nextPut: c.\\n\\t\\t\\tc = cr ifTrue:[ stream nextPut: lf ]. ] ].! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithSqueakLineEndings\\n\\t\\\"assume the string is textual, and that CR, LF, and CRLF are all \\n\\tvalid line endings. Replace each occurence with a single CR\\\"\\n\\t| cr lf input c crlf inPos outPos outString lineEndPos newOutPos |\\n\\tcr _ Character cr.\\n\\tlf _ Character linefeed.\\n\\tcrlf _ CharacterSet new.\\n\\tcrlf add: cr; add: lf.\\n\\n\\tinPos _ 1.\\n\\toutPos _ 1.\\n\\toutString _\\n String new: self size.\\n\\n\\t[ lineEndPos _ self indexOfAnyOf: crlf startingAt: inPos ifAbsent: [0].\\n\\t\\tlineEndPos ~= 0 ] whileTrue: [\\n\\t\\t\\tnewOutPos _ outPos + (lineEndPos - inPos + 1).\\n\\t\\t\\toutString replaceFrom: outPos to: newOutPos - 2 with: self startingAt: inPos.\\n\\t\\t\\toutString at: newOutPos-1 put: cr.\\n\\t\\t\\toutPos _ newOutPos.\\n\\n\\t\\t\\t((self at: lineEndPos) = cr and: [ lineEndPos < self size and: [ (self at: lineEndPos+1) = lf ] ]) ifTrue: [\\n\\t\\t\\t\\t\\\"CRLF ending\\\"\\n\\t\\t\\t\\tinPos _ lineEndPos + 2 ]\\n\\t\\t\\tifFalse: [ \\n\\t\\t\\t\\t\\\"CR or LF ending\\\"\\n\\t\\t\\t\\tinPos _ lineEndPos + 1 ]. ].\\n\\n\\t\\\"no more line endings. copy the rest\\\"\\n\\tnewOutPos _ outPos + (self size - inPos + 1).\\n\\toutString replaceFrom: outPos to: newOutPos-1 with: self startingAt: inPos.\\n\\n\\t^outString copyFrom: 1 to: newOutPos-1\\n\\t! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithoutQuoting\\n\\t\\\"remove the initial and final quote marks, if present\\\"\\n\\t\\\"'''h''' withoutQuoting\\\"\\n\\t| quote |\\n\\tself size < 2 ifTrue: [ ^self ].\\n\\tquote _ self first.\\n\\t(quote = $' or: [ quote = $\\\" ])\\n\\t\\tifTrue: [ ^self copyFrom: 2 to: self size - 1 ]\\n\\t\\tifFalse: [ ^self ].! !\\n\\n\\n!String methodsFor: 'paragraph support' stamp: 'yo 8/26/2002 22:19'!\\nindentationIfBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the receiver. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\\"\\n\\n\\t| reader leadingTabs lastSeparator cr tab ch |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\treader _ ReadStream on: self.\\n\\tleadingTabs _ 0.\\n\\t[reader atEnd not and: [(ch _ reader next) = tab]]\\n\\t\\twhileTrue: [leadingTabs _ leadingTabs + 1].\\n\\tlastSeparator _ leadingTabs + 1.\\n\\t[reader atEnd not and: [ch isSeparator and: [ch ~= cr]]]\\n\\t\\twhileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next].\\n\\tlastSeparator = self size | (ch = cr)\\n\\t\\tifTrue: [^aBlock value: leadingTabs].\\n\\t^ leadingTabs.\\n! !\\n\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t\\\"Number String Boolean player collection sound color etc\\\"\\n\\t^ #String! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 8/26/2002 22:57'!\\nencodeDoublingQuoteOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n\\t| x |\\n\\taStream print: $'.\\n\\t1 to: self size do:\\n\\t\\t[:i |\\n\\t\\taStream print: (x _ self at: i).\\n\\t\\tx = $' ifTrue: [aStream print: x]].\\n\\taStream print: $'! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nisLiteral\\n\\n\\t^true! !\\n\\n!String methodsFor: 'printing' stamp: 'sd 7/8/2006 18:06'!\\nprintOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n \\n\\tself storeOn: aStream! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 8/26/2002 22:58'!\\nstoreOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n\\t| x |\\n\\taStream nextPut: $'.\\n\\t1 to: self size do:\\n\\t\\t[:i |\\n\\t\\taStream nextPut: (x _ self at: i).\\n\\t\\tx = $' ifTrue: [aStream nextPut: x]].\\n\\taStream nextPut: $'! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nstringRepresentation\\n\\t\\\"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\\\"\\n\\n\\t^ self ! !\\n\\n\\n!String methodsFor: 'system primitives' stamp: 'sw 10/20/2004 17:51'!\\nendsWithAColon \\n\\t\\\"Answer whether the final character of the receiver is a colon\\\"\\n\\n\\t^ self size > 0 and: [self last == $:]\\n\\n\\\"\\n#fred: endsWithAColon\\n'fred' endsWithAColon\\n\\\"! !\\n\\n!String methodsFor: 'system primitives' stamp: 'ar 4/10/2005 16:55'!\\nfindSubstring: key in: body startingAt: start matchTable: matchTable\\n\\t\\\"Answer the index in the string body at which the substring key first occurs, at or beyond start. The match is determined using matchTable, which can be used to effect, eg, case-insensitive matches. If no match is found, zero will be returned.\\\"\\n\\t| index c1 c2 |\\n\\tmatchTable == nil ifTrue: [\\n\\t\\tkey size = 0 ifTrue: [^ 0].\\n\\t\\tstart to: body size - key size + 1 do:\\n\\t\\t\\t[:startIndex |\\n\\t\\t\\tindex _ 1.\\n\\t\\t\\t\\t[(body at: startIndex+index-1)\\n\\t\\t\\t\\t\\t= (key at: index)]\\n\\t\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t[index = key size ifTrue: [^ startIndex].\\n\\t\\t\\t\\t\\tindex _ index+1]].\\n\\t\\t^ 0\\n\\t].\\n\\n\\tkey size = 0 ifTrue: [^ 0].\\n\\tstart to: body size - key size + 1 do:\\n\\t\\t[:startIndex |\\n\\t\\tindex _ 1.\\n\\t\\t[c1 _ body at: startIndex+index-1.\\n\\t\\tc2 _ key at: index.\\n\\t\\t((c1 leadingChar = 0) ifTrue: [(matchTable at: c1 asciiValue + 1)]\\n\\t\\t\\t\\t\\t\\tifFalse: [c1 asciiValue + 1])\\n\\t\\t\\t= ((c2 leadingChar = 0) ifTrue: [(matchTable at: c2 asciiValue + 1)]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [c2 asciiValue + 1])]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t[index = key size ifTrue: [^ startIndex].\\n\\t\\t\\t\\tindex _ index+1]].\\n\\t^ 0\\n! !\\n\\n!String methodsFor: 'system primitives' stamp: 'yo 11/3/2004 19:24'!\\nnumArgs \\n\\t\\\"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.\\\"\\n\\n\\t| firstChar numColons excess start ix |\\n\\tself size = 0 ifTrue: [^ -1].\\n\\tfirstChar _ self at: 1.\\n\\t(firstChar isLetter or: [firstChar = $:]) ifTrue:\\n\\t\\t[\\\"Fast reject if any chars are non-alphanumeric\\\"\\n\\t\\t(self findSubstring: '~' in: self startingAt: 1 matchTable: Tokenish) > 0 ifTrue: [^ -1].\\n\\t\\t\\\"Fast colon count\\\"\\n\\t\\tnumColons _ 0. start _ 1.\\n\\t\\t[(ix _ self findSubstring: ':' in: self startingAt: start matchTable: CaseSensitiveOrder) > 0]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t[numColons _ numColons + 1.\\n\\t\\t\\t\\tstart _ ix + 1].\\n\\t\\tnumColons = 0 ifTrue: [^ 0].\\n\\t\\tfirstChar = $:\\n\\t\\t\\tifTrue: [excess _ 2 \\\"Has an initial keyword, as #:if:then:else:\\\"]\\n\\t\\t\\tifFalse: [excess _ 0].\\n\\t\\tself last = $:\\n\\t\\t\\tifTrue: [^ numColons - excess]\\n\\t\\t\\tifFalse: [^ numColons - excess - 1 \\\"Has a final keywords as #nextPut::andCR\\\"]].\\n\\tfirstChar isSpecial ifTrue:\\n\\t\\t[self size = 1 ifTrue: [^ 1].\\n\\t\\t2 to: self size do: [:i | (self at: i) isSpecial ifFalse: [^ -1]].\\n\\t\\t^ 1].\\n\\t^ -1.! !\\n\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nhasContentsInExplorer\\n\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 16:49'!\\nincludesUnifiedCharacter\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisAllDigits\\n\\t\\\"whether the receiver is composed entirely of digits\\\"\\n\\tself do: [:c | c isDigit ifFalse: [^ false]].\\n\\t^ true! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisAllSeparators\\n\\t\\\"whether the receiver is composed entirely of separators\\\"\\n\\tself do: [ :c | c isSeparator ifFalse: [ ^false ] ].\\n\\t^true! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 8/4/2003 12:26'!\\nisAsciiString\\n\\n\\t| c |\\n\\tc _ self detect: [:each | each asciiValue > 127] ifNone: [nil].\\n\\t^ c isNil.\\n! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 16:23'!\\nisByteString\\n\\t\\\"Answer whether the receiver is a ByteString\\\"\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 23:25'!\\nisOctetString\\n\\t\\\"Answer whether the receiver can be represented as a byte string. \\n\\tThis is different from asking whether the receiver *is* a ByteString \\n\\t(i.e., #isByteString)\\\"\\n\\t1 to: self size do: [:pos |\\n\\t\\t(self at: pos) asInteger >= 256 ifTrue: [^ false].\\n\\t].\\n\\t^ true.\\n! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisString\\n\\t^ true! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/12/2005 19:52'!\\nisWideString\\n\\t\\\"Answer whether the receiver is a WideString\\\"\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nlastSpacePosition\\n\\t\\\"Answer the character position of the final space or other separator character in the receiver, and 0 if none\\\"\\n\\tself size to: 1 by: -1 do:\\n\\t\\t[:i | ((self at: i) isSeparator) ifTrue: [^ i]].\\n\\t^ 0\\n\\n\\\"\\n'fred the bear' lastSpacePosition\\n'ziggie' lastSpacePosition\\n'elvis ' lastSpacePosition\\n'wimpy ' lastSpacePosition\\n'' lastSpacePosition\\n\\\"! !\\n\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/24/2004 19:42'!\\ntranslated\\n\\t\\\"answer the receiver translated to the default language\\\"\\n\\t^ NaturalLanguageTranslator current translate: self! !\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/27/2004 18:43'!\\ntranslatedIfCorresponds\\n\\t\\\"answer the receiver translated to the default language only if \\n\\tthe receiver begins and ends with an underscore (_)\\\"\\n\\t^ ('_*_' match: self)\\n\\t\\tifTrue: [(self copyFrom: 2 to: self size - 1) translated]\\n\\t\\tifFalse: [self]! !\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/24/2004 19:38'!\\ntranslatedTo: localeID \\n\\t\\\"answer the receiver translated to the given locale id\\\"\\n\\t^ localeID translator translate: self! !\\n\\n\\n!String methodsFor: 'user interface' stamp: 'md 7/28/2005 20:42'!\\nasExplorerString\\n\\n\\t^ self printString! !\\n\\n!String methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:02'!\\nopenInWorkspaceWithTitle: aTitle\\n\\t\\\"Open up a workspace with the receiver as its contents, with the given title\\\"\\n\\tUIManager default edit: self label: aTitle! !\\n\\n\\n!String methodsFor: '*eToys-*Morphic' stamp: 'ar 4/10/2005 17:06'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new setLiteral: self;addSuffixIfCan! !\\n\\n\\n!String methodsFor: '*Morphic' stamp: 'ar 4/10/2005 17:07'!\\nasMorph \\n\\t\\\"Answer the receiver as a StringMorph\\\"\\n\\n\\t^ StringMorph contents: self\\n\\n\\\"'bugs black blood' asMorph openInHand\\\"! !\\n\\n!String methodsFor: '*Morphic' stamp: 'ar 4/10/2005 17:07'!\\nasStringMorph \\n\\t\\\"Answer the receiver as a StringMorph\\\"\\n\\n\\t^ StringMorph contents: self\\n\\n\\\"'bugs black blood' asStringMorph openInHand\\\"! !\\n\\n\\n!String methodsFor: '*MorphicExtras-*morphic-Postscript Canvases' stamp: 'yo 11/3/2004 19:24'!\\nasPostscript\\n\\n\\t| temp |\\n\\ttemp _ self asString copyReplaceAll: '(' with: '\\\\('.\\n\\ttemp _ temp copyReplaceAll: ')' with: '\\\\)'.\\n\\ttemp _ temp copyReplaceAll: '\\n' \\n\\t\\t\\twith: ''.\\n\\t^ PostscriptEncoder mapMacStringToPS: temp! !\\n\\n\\n!String methodsFor: '*Morphic-converting' stamp: 'yo 11/3/2004 19:24'!\\nopenAsMorph\\n\\t\\\"Open the receiver as a morph\\\"\\n\\n\\t^ self asMorph openInHand ! !\\n\\n\\n!String methodsFor: '*monticello' stamp: 'avi 2/4/2004 14:14'!\\nextractNumber\\n\\t^ ('0', self select: [:ea | ea isDigit]) asNumber! !\\n\\n\\n!String methodsFor: '*network-uri' stamp: 'mir 2/26/2002 14:59'!\\nasURI\\n\\t\\\"convert to a Url\\\"\\n\\t\\\"'http://www.cc.gatech.edu/' asURI\\\"\\n\\t\\\"'msw://chaos.resnet.gatech.edu:9000/' asURI\\\"\\n\\t^URI fromString: self! !\\n\\n\\n!String methodsFor: '*packageinfo-base' stamp: 'nk 8/30/2004 09:02'!\\nescapeEntities\\n\\t^ self species streamContents: [:s | self do: [:c | s nextPutAll: c escapeEntities]]\\n! !\\n\\n\\n!String methodsFor: '*services-base' stamp: 'rr 3/21/2006 12:00'!\\nservice\\n\\t^ self serviceOrNil ifNil: [ServiceCategory new id: self asSymbol]! !\\n\\n!String methodsFor: '*services-base' stamp: 'rr 3/21/2006 12:00'!\\nserviceOrNil\\n\\t^ ServiceRegistry current serviceWithId: self asSymbol! !\\n\\n\\n!String methodsFor: '*versionnumber' stamp: 'yo 11/3/2004 19:24'!\\nasVersion\\n\\n\\t\\\"Answer a VersionNumber\\\"\\n\\n\\n\\n\\t^VersionNumber fromString: self! !\\n\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainstEnumerator: wordBlock continuedFrom: oldCollection\\n\\t\\\"The guts of correction, instead of a wordList, there is a block that should take another block and enumerate over some list with it.\\\"\\n\\n\\t| choices scoreMin results score maxChoices |\\n\\tscoreMin _ self size // 2 min: 3.\\n\\tmaxChoices _ 10.\\n\\toldCollection isNil\\n\\t\\tifTrue: [ choices _ SortedCollection sortBlock: [ :x :y | x value > y value ] ]\\n\\t\\tifFalse: [ choices _ oldCollection ].\\n\\twordBlock isNil\\n\\t\\tifTrue:\\n\\t\\t\\t[ results _ OrderedCollection new.\\n\\t\\t\\t1 to: (maxChoices min: choices size) do: [ :i | results add: (choices at: i) key ] ]\\n\\t\\tifFalse:\\n\\t\\t\\t[ wordBlock value: [ :word |\\n\\t\\t\\t\\t(score _ self alike: word) >= scoreMin ifTrue:\\n\\t\\t\\t\\t\\t[ choices add: (Association key: word value: score).\\n\\t\\t\\t\\t\\t\\t(choices size >= maxChoices) ifTrue: [ scoreMin _ (choices at: maxChoices) value] ] ].\\n\\t\\t\\tresults _ choices ].\\n\\t^ results! !\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\nevaluateExpression: aString parameters: aCollection \\n\\t\\\"private - evaluate the expression aString with \\n\\taCollection as the parameters and answer the \\n\\tevaluation result as an string\\\"\\n\\t| index |\\n\\tindex := ('0' , aString) asNumber.\\n\\n\\tindex isZero\\n\\t\\tifTrue: [^ '[invalid subscript: {1}]' format: {aString}].\\n\\n\\tindex > aCollection size\\n\\t\\tifTrue: [^ '[subscript is out of bounds: {1}]' format: {aString}].\\n\\n\\t^ (aCollection at: index) asString! !\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\ngetEnclosedExpressionFrom: aStream \\n\\t\\\"private - get the expression enclosed between '{' and \\n\\t'}' and remove all the characters from the stream\\\"\\n\\t| result currentChar |\\n\\tresult := String new writeStream.\\n\\n\\t[aStream atEnd \\n\\t\\tor: [(currentChar := aStream next) == $}]]\\n\\t\\twhileFalse: [result nextPut: currentChar].\\n\\n\\t^ result contents withBlanksTrimmed! !\\n\\n!String methodsFor: 'private' stamp: 'yo 8/26/2002 22:53'!\\nreplaceFrom: start to: stop with: replacement startingAt: repStart \\n\\t\\\"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.\\\"\\n\\t<primitive: 105>\\n\\tsuper replaceFrom: start to: stop with: replacement startingAt: repStart! !\\n\\n!String methodsFor: 'private' stamp: 'yo 8/28/2002 15:22'!\\nstringhash\\n\\n\\t^ self hash.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nString class\\n\\tinstanceVariableNames: ''!\\n\\n!String class methodsFor: 'examples' stamp: 'yo 11/3/2004 19:24'!\\nexample\\n\\t\\\"To see the string displayed at the cursor point, execute this expression\\n\\tand select a point by pressing a mouse button.\\\"\\n\\n\\t'this is some text' displayOn: Display at: Sensor waitButton! !\\n\\n\\n!String class methodsFor: 'formatting' stamp: 'md 6/5/2005 07:49'!\\nexpandMacro: macroType argument: argument withExpansions: expansions \\n\\tmacroType = $s ifTrue: [^expansions at: argument].\\n\\tmacroType = $p ifTrue: [^(expansions at: argument) printString].\\n\\tmacroType = $n ifTrue: [^String cr].\\n\\tmacroType = $t ifTrue: [^String tab].\\n\\tself error: 'unknown expansion type'! !\\n\\n\\n!String class methodsFor: 'initialization' stamp: 'ar 4/9/2005 22:37'!\\ninitialize \\\"self initialize\\\"\\n\\n\\t| order |\\n\\tAsciiOrder _ (0 to: 255) as: ByteArray.\\n\\n\\tCaseInsensitiveOrder _ AsciiOrder copy.\\n\\t($a to: $z) do:\\n\\t\\t[:c | CaseInsensitiveOrder at: c asciiValue + 1\\n\\t\\t\\t\\tput: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)].\\n\\n\\t\\\"Case-sensitive compare sorts space, digits, letters, all the rest...\\\"\\n\\tCaseSensitiveOrder _ ByteArray new: 256 withAll: 255.\\n\\torder _ -1.\\n\\t' 0123456789' do: \\\"0..10\\\"\\n\\t\\t[:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].\\n\\t($a to: $z) do: \\\"11-64\\\"\\n\\t\\t[:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order _ order+1).\\n\\t\\tCaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].\\n\\t1 to: CaseSensitiveOrder size do:\\n\\t\\t[:i | (CaseSensitiveOrder at: i) = 255 ifTrue:\\n\\t\\t\\t[CaseSensitiveOrder at: i put: (order _ order+1)]].\\n\\torder = 255 ifFalse: [self error: 'order problem'].\\n\\n\\t\\\"a table for translating to lower case\\\"\\n\\tLowercasingTable _ String withAll: (Character allByteCharacters collect: [:c | c asLowercase]).\\n\\n\\t\\\"a table for translating to upper case\\\"\\n\\tUppercasingTable _ String withAll: (Character allByteCharacters collect: [:c | c asUppercase]).\\n\\n\\t\\\"a table for testing tokenish (for fast numArgs)\\\"\\n\\tTokenish _ String withAll: (Character allByteCharacters collect:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[:c | c tokenish ifTrue: [c] ifFalse: [$~]]).\\n\\n\\t\\\"CR and LF--characters that terminate a line\\\"\\n\\tCSLineEnders _ CharacterSet empty.\\n\\tCSLineEnders add: Character cr.\\n\\tCSLineEnders add: Character lf.\\n\\n \\t\\\"separators and non-separators\\\"\\n\\tCSSeparators _ CharacterSet separators.\\n\\tCSNonSeparators _ CSSeparators complement.! !\\n\\n!String class methodsFor: 'initialization' stamp: 'yo 8/11/2003 21:11'!\\ninitializeHtmlEntities\\n\\t\\\"self initializeHtmlEntities\\\"\\n\\n\\tHtmlEntities _ (Dictionary new: 128)\\n\\t\\tat: 'amp'\\tput: $&;\\n\\t\\tat: 'lt'\\t\\tput: $<;\\n\\t\\tat: 'gt'\\t\\tput: $>;\\n\\t\\tat: 'quot'\\tput: $\\\";\\n\\t\\tat: 'euro'\\tput: Character euro;\\n\\t\\tyourself.\\n\\t#('nbsp' 'iexcl' 'cent' 'pound' 'curren' 'yen' 'brvbar' 'sect' 'uml' 'copy' 'ordf' 'laquo' 'not' 'shy' 'reg' 'hibar' 'deg' 'plusmn' 'sup2' 'sup3' 'acute' 'micro' 'para' 'middot' 'cedil' 'sup1' 'ordm' 'raquo' 'frac14' 'frac12' 'frac34' 'iquest' 'Agrave' 'Aacute' 'Acirc' 'Atilde' 'Auml' 'Aring' 'AElig' 'Ccedil' 'Egrave' 'Eacute' 'Ecirc' 'Euml' 'Igrave' 'Iacute' 'Icirc' 'Iuml' 'ETH' 'Ntilde' 'Ograve' 'Oacute' 'Ocirc' 'Otilde' 'Ouml' 'times' 'Oslash' 'Ugrave' 'Uacute' 'Ucirc' 'Uuml' 'Yacute' 'THORN' 'szlig' 'agrave' 'aacute' 'acirc' 'atilde' 'auml' 'aring' 'aelig' 'ccedil' 'egrave' 'eacute' 'ecirc' 'euml' 'igrave' 'iacute' 'icirc' 'iuml' 'eth' 'ntilde' 'ograve' 'oacute' 'ocirc' 'otilde' 'ouml' 'divide' 'oslash' 'ugrave' 'uacute' 'ucirc' 'uuml' 'yacute' 'thorn' 'yuml' ) withIndexDo: [:each :index | HtmlEntities at: each put: (index + 159) asCharacter]! !\\n\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncr\\n\\t\\\"Answer a string containing a single carriage return character.\\\"\\n\\n\\t^ self with: Character cr\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncrlf\\n\\t\\\"Answer a string containing a carriage return and a linefeed.\\\"\\n\\n\\t^ self with: Character cr with: Character lf\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncrlfcrlf\\n\\t^self crlf , self crlf.\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 16:24'!\\nfromByteArray: aByteArray\\n\\n\\t^ aByteArray asString\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nfromPacked: aLong\\n\\t\\\"Convert from a longinteger to a String of length 4.\\\"\\n\\n\\t| s |\\n\\ts _ self new: 4.\\n\\ts at: 1 put: (aLong digitAt: 4) asCharacter.\\n\\ts at: 2 put: (aLong digitAt: 3) asCharacter.\\n\\ts at: 3 put: (aLong digitAt: 2) asCharacter.\\n\\ts at: 4 put: (aLong digitAt: 1) asCharacter.\\n\\t^s\\n\\n\\\"String fromPacked: 'TEXT' asPacked\\\"\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nfromString: aString \\n\\t\\\"Answer an instance of me that is a copy of the argument, aString.\\\"\\n\\t\\n\\t^ aString copyFrom: 1 to: aString size! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nlf\\n\\t\\\"Answer a string containing a single carriage return character.\\\"\\n\\n\\t^ self with: Character lf! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 23:26'!\\nnew: sizeRequested \\n\\t\\\"Answer an instance of this class with the number of indexable\\n\\tvariables specified by the argument, sizeRequested.\\\"\\n\\tself == String \\n\\t\\tifTrue:[^ByteString new: sizeRequested]\\n\\t\\tifFalse:[^self basicNew: sizeRequested].! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 13:27'!\\nreadFrom: inStream\\n\\t\\\"Answer an instance of me that is determined by reading the stream, \\n\\tinStream. Embedded double quotes become the quote Character.\\\"\\n\\n\\t| outStream char done |\\n\\toutStream _ WriteStream on: (self new: 16).\\n\\t\\\"go to first quote\\\"\\n\\tinStream skipTo: $'.\\n\\tdone _ false.\\n\\t[done or: [inStream atEnd]]\\n\\t\\twhileFalse: \\n\\t\\t\\t[char _ inStream next.\\n\\t\\t\\tchar = $'\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[char _ inStream next.\\n\\t\\t\\t\\t\\tchar = $'\\n\\t\\t\\t\\t\\t\\tifTrue: [outStream nextPut: char]\\n\\t\\t\\t\\t\\t\\tifFalse: [done _ true]]\\n\\t\\t\\t\\tifFalse: [outStream nextPut: char]].\\n\\t^outStream contents! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ntab\\n\\t\\\"Answer a string containing a single tab character.\\\"\\n\\n\\t^ self with: Character tab\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 13:29'!\\nvalue: anInteger\\n\\n\\t^ self with: (Character value: anInteger).\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/12/2005 17:34'!\\nwith: aCharacter\\n\\t| newCollection |\\n\\taCharacter asInteger < 256\\n\\t\\tifTrue:[newCollection _ ByteString new: 1]\\n\\t\\tifFalse:[newCollection _ WideString new: 1].\\n\\tnewCollection at: 1 put: aCharacter.\\n\\t^newCollection! !\\n\\n\\n!String class methodsFor: 'primitives' stamp: 'yo 12/15/2005 13:41'!\\ncompare: string1 with: string2 collated: order\\n\\t\\\"Return 1, 2 or 3, if string1 is <, =, or > string2, with the collating order of characters given by the order array.\\\"\\n\\n\\t| len1 len2 c1 c2 |\\n\\torder == nil ifTrue: [\\n\\t\\tlen1 _ string1 size.\\n\\t\\tlen2 _ string2 size.\\n\\t\\t1 to: (len1 min: len2) do:[:i |\\n\\t\\t\\tc1 _ (string1 at: i) asInteger.\\n\\t\\t\\tc2 _ (string2 at: i) asInteger.\\n\\t\\t\\tc1 = c2 ifFalse: [c1 < c2 ifTrue: [^ 1] ifFalse: [^ 3]].\\n\\t\\t].\\n\\t\\tlen1 = len2 ifTrue: [^ 2].\\n\\t\\tlen1 < len2 ifTrue: [^ 1] ifFalse: [^ 3].\\n\\t].\\n\\tlen1 _ string1 size.\\n\\tlen2 _ string2 size.\\n\\t1 to: (len1 min: len2) do:[:i |\\n\\t\\tc1 _ (string1 at: i) asInteger.\\n\\t\\tc2 _ (string2 at: i) asInteger.\\n\\t\\tc1 < 256 ifTrue: [c1 _ order at: c1 + 1].\\n\\t\\tc2 < 256 ifTrue: [c2 _ order at: c2 + 1].\\n\\t\\tc1 = c2 ifFalse:[c1 < c2 ifTrue: [^ 1] ifFalse: [^ 3]].\\n\\t].\\n\\tlen1 = len2 ifTrue: [^ 2].\\n\\tlen1 < len2 ifTrue: [^ 1] ifFalse: [^ 3].\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\nfindFirstInString: aString inSet: inclusionMap startingAt: start\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| i stringSize ascii more |\\n\\tinclusionMap size ~= 256 ifTrue: [^ 0].\\n\\tstringSize _ aString size.\\n\\tmore _ true.\\n\\ti _ start - 1.\\n\\t[more and: [i + 1 <= stringSize]] whileTrue: [\\n\\t\\ti _ i + 1.\\n\\t\\tascii _ (aString at: i) asciiValue.\\n\\t\\tmore _ ascii < 256 ifTrue: [(inclusionMap at: ascii + 1) = 0] ifFalse: [true].\\n\\t].\\n\\n\\ti + 1 > stringSize ifTrue: [^ 0].\\n\\t^ i! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\nindexOfAscii: anInteger inString: aString startingAt: start\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| stringSize |\\n\\tstringSize _ aString size.\\n\\tstart to: stringSize do: [:pos |\\n\\t\\t(aString at: pos) asInteger = anInteger ifTrue: [^ pos]].\\n\\t^ 0\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:29'!\\nstringHash: aString initialHash: speciesHash\\n\\t| stringSize hash low |\\n\\tstringSize _ aString size.\\n\\thash _ speciesHash bitAnd: 16rFFFFFFF.\\n\\t1 to: stringSize do: [:pos |\\n\\t\\thash _ hash + (aString at: pos) asInteger.\\n\\t\\t\\\"Begin hashMultiply\\\"\\n\\t\\tlow _ hash bitAnd: 16383.\\n\\t\\thash _ (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF.\\n\\t].\\n\\t^ hash.\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\ntranslate: aString from: start to: stop table: table\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| char |\\n\\tstart to: stop do: [:i |\\n\\t\\tchar _ (aString at: i) asInteger.\\n\\t\\tchar < 256 ifTrue: [aString at: i put: (table at: char+1)].\\n\\t].\\n! !\\nStringMorph subclass: #StringButtonMorph\\n\\tinstanceVariableNames: 'target actionSelector arguments actWhen oldColor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\nactionSelector\\n\\n\\t^ actionSelector\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\nactionSelector: aSymbolOrString\\n\\n\\t(nil = aSymbolOrString or:\\n\\t ['nil' = aSymbolOrString or:\\n\\t [aSymbolOrString isEmpty]])\\n\\t\\tifTrue: [^ actionSelector _ nil].\\n\\n\\tactionSelector _ aSymbolOrString asSymbol.\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\narguments\\n\\n\\t^ arguments\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\narguments: aCollection\\n\\n\\targuments _ aCollection asArray copy.\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\ntarget\\n\\n\\t^ target\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\ntarget: anObject\\n\\n\\ttarget _ anObject\\n! !\\n\\n\\n!StringButtonMorph methodsFor: 'button' stamp: 'dgd 2/22/2003 18:45'!\\ndoButtonAction\\n\\t\\\"Perform the action of this button. Subclasses may override this method. The default behavior is to send the button's actionSelector to its target object with its arguments.\\\"\\n\\n\\t(target notNil and: [actionSelector notNil]) \\n\\t\\tifTrue: \\n\\t\\t\\t[Cursor normal \\n\\t\\t\\t\\tshowWhile: [target perform: actionSelector withArguments: arguments]]! !\\n\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'jm 7/28/97 11:55'!\\nupdateReferencesUsing: aDictionary\\n\\t\\\"If the arguments array points at a morph we are copying, then point at the new copy. And also copies the array, which is important!!\\\"\\n\\n\\tsuper updateReferencesUsing: aDictionary.\\n\\targuments _ arguments collect:\\n\\t\\t[:old | aDictionary at: old ifAbsent: [old]].\\n! !\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'tk 1/8/1999 09:47'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If target and arguments fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\nsuper veryDeepFixupWith: deepCopier.\\ntarget _ deepCopier references at: target ifAbsent: [target].\\narguments _ arguments collect: [:each |\\n\\tdeepCopier references at: each ifAbsent: [each]].\\n! !\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'tk 1/8/1999 09:46'!\\nveryDeepInner: deepCopier\\n\\t\\\"Copy all of my instance variables. Some need to be not copied at all, but shared. \\tWarning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.\\\"\\n\\nsuper veryDeepInner: deepCopier.\\n\\\"target _ target.\\t\\tWeakly copied\\\"\\n\\\"actionSelector _ actionSelector.\\t\\ta Symbol\\\"\\n\\\"arguments _ arguments.\\t\\tAll weakly copied\\\"\\nactWhen _ actWhen veryDeepCopyWith: deepCopier.\\noldColor _ oldColor veryDeepCopyWith: deepCopier.! !\\n\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nhandlesMouseDown: evt\\n\\n\\t^ true\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:14'!\\nhandlesMouseStillDown: evt\\n\\t^actWhen == #whilePressed! !\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nmouseDown: evt\\n\\n\\toldColor _ color.\\n\\tactWhen == #buttonDown\\n\\t\\tifTrue: [self doButtonAction].\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:15'!\\nmouseMove: evt\\n\\tactWhen == #buttonDown ifTrue: [^ self].\\n\\t(self containsPoint: evt cursorPoint)\\n\\t\\tifTrue:[self color: (oldColor alphaMixed: 1/2 with: Color white)]\\n\\t\\tifFalse: [self color: oldColor].\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:15'!\\nmouseStillDown: evt\\n\\tactWhen == #whilePressed ifFalse: [^ self].\\n\\t(self containsPoint: evt cursorPoint) ifTrue:[self doButtonAction].! !\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nmouseUp: evt\\n\\n\\tself color: oldColor.\\n\\t(actWhen == #buttonUp and: [self containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [self doButtonAction].\\n! !\\n\\n\\n!StringButtonMorph methodsFor: 'e-toy support' stamp: 'ar 3/17/2001 20:17'!\\nadaptToWorld: aWorld\\n\\tsuper adaptToWorld: aWorld.\\n\\ttarget _ target adaptedToWorld: aWorld.! !\\n\\n\\n!StringButtonMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:44'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\ttarget _ nil.\\n\\tactionSelector _ #flash.\\n\\targuments _ EmptyArray.\\n\\tactWhen _ #buttonUp.\\n\\tself contents: 'Flash' ! !\\n\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:57'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'change label' translated action: #setLabel.\\n\\taCustomMenu add: 'change action selector' translated action: #setActionSelector.\\n\\taCustomMenu add: 'change arguments' translated action: #setArguments.\\n\\taCustomMenu add: 'change when to act' translated action: #setActWhen.\\n\\tself addTargetingMenuItems: aCustomMenu hand: aHandMorph .! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:56'!\\naddTargetingMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Add targeting menu items\\\"\\n\\taCustomMenu addLine.\\n\\n\\taCustomMenu add: 'set target' translated action: #targetWith:.\\n\\taCustomMenu add: 'sight target' translated action: #sightTargets:.\\n\\ttarget\\n\\t\\tifNotNil: [aCustomMenu add: 'clear target' translated action: #clearTarget]! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:55'!\\nclearTarget\\n\\n\\ttarget _ nil.\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/16/2005 21:02'!\\nsetActWhen\\n\\n\\t| selections |\\n\\tselections _ #(buttonDown buttonUp whilePressed).\\n\\tactWhen _ (SelectionMenu labelList: (selections collect: [:t | t translated]) selections: selections)\\n\\t\\tstartUpWithCaption: 'Choose one of the following conditions' translated.\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/16/2005 20:54'!\\nsetActionSelector\\n\\n\\t| newSel |\\n\\tnewSel _ FillInTheBlank\\n\\t\\trequest:\\n'Please type the selector to be sent to\\nthe target when this button is pressed' translated\\n\\t\\tinitialAnswer: actionSelector.\\n\\tnewSel isEmpty ifFalse: [self actionSelector: newSel].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/14/2005 13:09'!\\nsetArguments\\n\\n\\t| s newArgs newArgsArray |\\n\\ts _ WriteStream on: ''.\\n\\targuments do: [:arg | arg printOn: s. s nextPutAll: '. '].\\n\\tnewArgs _ FillInTheBlank\\n\\t\\trequest:\\n'Please type the arguments to be sent to the target\\nwhen this button is pressed separated by periods' translated\\n\\t\\tinitialAnswer: s contents.\\n\\tnewArgs isEmpty ifFalse: [\\n\\t\\tnewArgsArray _ Compiler evaluate: '{', newArgs, '}' for: self logged: false.\\n\\t\\tself arguments: newArgsArray].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu'!\\nsetLabel\\n\\n\\t| newLabel |\\n\\tnewLabel _ FillInTheBlank\\n\\t\\trequest:\\n'Please type a new label for this button'\\n\\t\\tinitialAnswer: self contents.\\n\\tnewLabel isEmpty ifFalse: [self contents: newLabel].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 18:55'!\\nsetTarget: evt \\n\\t| rootMorphs |\\n\\trootMorphs _ self world rootMorphsAt: evt hand targetOffset.\\n\\ttarget _ rootMorphs size > 1\\n\\t\\tifTrue: [rootMorphs second]\\n\\t\\tifFalse: [nil]! !\\n\\n\\n!StringButtonMorph methodsFor: 'submorphs-add/remove'!\\nactWhen: aSymbol\\n\\t\\\"Set the condition under which to invoke my action to one of: #buttonDown, #buttonUp, and #whilePressed.\\\"\\n\\n\\tactWhen _ aSymbol.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringButtonMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StringButtonMorph class methodsFor: 'printing' stamp: 'sw 2/16/98 03:02'!\\ndefaultNameStemForInstances\\n\\t^ 'SButton'! !\\nModel subclass: #StringHolder\\n\\tinstanceVariableNames: 'contents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Kernel-Remnants'!\\n!StringHolder commentStamp: '<historical>' prior: 0!\\nI am a kind of Model that includes a piece of text. In some cases, the text can be edited, and in some the text is a method.\\n\\nCategories 'code pane menu' and 'message list menu' are messages that may be called by my menus when the text is a method, and when some pane is a list of methods. Other of my subclasses may ignore these two catagories altogether.!\\n\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'di 5/19/1998 15:34'!\\nacceptContents: aString \\n\\t\\\"Set aString to be the contents of the receiver. Return true cuz happy\\\"\\n\\n\\tself contents: aString.\\n\\t^ true! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'nk 4/29/2004 12:32'!\\nclassCommentIndicated\\n\\t\\\"Answer true iff we're viewing the class comment.\\\"\\n\\t^false! !\\n\\n!StringHolder methodsFor: 'accessing'!\\ncontents\\n\\t\\\"Answer the contents that the receiver is holding--presumably a string.\\\"\\n\\n\\t^contents! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 1/12/1999 11:47'!\\ncontents: textOrString \\n\\t\\\"Set textOrString to be the contents of the receiver.\\\"\\n\\n\\tcontents _ textOrString \\\"asString\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/3/98 22:50'!\\ncontentsSelection\\n\\t\\\"Return the interval of text in the code pane to select when I set the pane's contents\\\"\\n\\n\\t^ 1 to: 0 \\\"null selection\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/9/2000 23:59'!\\nnoteAcceptanceOfCodeFor: aSelector\\n\\t\\\"A method has possibly been submitted for the receiver with aSelector as its selector; If the receiver wishes to take soem action here is a chance for it to do so\\\"\\n! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/1/2000 11:04'!\\nreformulateList\\n\\t\\\"If the receiver has a way of reformulating its message list, here is a chance for it to do so\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/6/2000 17:48'!\\nreformulateListNoting: newSelector\\n\\t\\\"A method has possibly been submitted for the receiver with newSelector as its selector; If the receiver has a way of reformulating its message list, here is a chance for it to do so\\\"\\n\\n\\t^ self reformulateList! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 14:59'!\\nselectedClassName\\n\\t\\\"I may know what class is currently selected\\\"\\n\\n\\tself selectedClass ifNotNil: [^ self selectedClass name].\\n\\t^ nil! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:01'!\\nselectedClassOrMetaClass\\n\\n\\t^ self selectedClass\\t\\\"I don't know any better\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:22'!\\nselectedMessageName\\n\\n\\t^ nil! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'di 11/23/1998 15:21'!\\ntextContents: aStringOrText \\n\\t\\\"Set aStringOrText to be the contents of the receiver.\\\"\\n\\n\\tcontents _ aStringOrText! !\\n\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'dgd 10/1/2004 13:43'!\\ncodePaneMenu: aMenu shifted: shifted \\n\\t\\\"Note that unless we override perform:orSendTo:, \\n\\tPluggableTextController will respond to all menu items in a \\n\\ttext pane\\\"\\n\\t| donorMenu |\\n\\tdonorMenu := shifted\\n\\t\\t\\t\\tifTrue: [ParagraphEditor shiftedYellowButtonMenu]\\n\\t\\t\\t\\tifFalse: [ParagraphEditor yellowButtonMenu].\\n\\t^ aMenu addAllFrom: donorMenu! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'wod 5/29/1998 16:35'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"Selector was just chosen from a menu by a user. If can respond, then\\nperform it on myself. If not, send it to otherTarget, presumably the\\neditPane from which the menu was invoked.\\\"\\n\\n\\t(self respondsTo: selector)\\n\\t\\tifTrue: [^ self perform: selector]\\n\\t\\tifFalse: [^ otherTarget perform: selector]! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'tk 4/6/98 11:43'!\\nshowBytecodes\\n\\t\\\"We don't know how to do this\\\"\\n\\n\\t^ self changed: #flash! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'ar 9/27/2005 20:47'!\\nspawn: contentsString\\n\\n\\tUIManager default edit: contentsString label: 'Workspace'\\n! !\\n\\n\\n!StringHolder methodsFor: 'evaluation'!\\ndoItContext\\n\\t\\\"Answer the context in which a text selection can be evaluated.\\\"\\n\\n\\t^nil! !\\n\\n!StringHolder methodsFor: 'evaluation'!\\ndoItReceiver\\n\\t\\\"Answer the object that should be informed of the result of evaluating a \\n\\ttext selection.\\\"\\n\\n\\t^nil! !\\n\\n\\n!StringHolder methodsFor: 'initialize-release'!\\ndefaultContents\\n\\n\\t^''! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 10/16/1998 11:36'!\\nembeddedInMorphicWindowLabeled: labelString\\n\\t| window |\\n\\twindow _ (SystemWindow labelled: labelString) model: self.\\n\\twindow addMorph: (PluggableTextMorph on: self text: #contents accept: #acceptContents:\\n\\t\\t\\treadSelection: nil menu: #codePaneMenu:shifted:)\\n\\t\\tframe: (0@0 corner: 1@1).\\n\\t^ window! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'jm 3/24/98 17:56'!\\ninitialize\\n\\t\\\"Initialize the state of the receiver with its default contents.\\\"\\n\\n\\tcontents _ self defaultContents.\\n! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 10/16/1998 11:37'!\\nopenAsMorphLabel: labelString \\n\\t\\\"Workspace new openAsMorphLabel: 'Workspace'\\\"\\n\\t(self embeddedInMorphicWindowLabeled: labelString) openInWorld! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 12/22/1998 00:16'!\\nopenLabel: aString \\n\\t\\\"Create a standard system view of the model, me, a StringHolder and open it. If in mvc, terminate the active controller so that the new window will immediately be activated.\\\"\\n\\tself openLabel: aString andTerminate: true! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sma 4/30/2000 10:15'!\\nopenLabel: aString andTerminate: terminateBoolean\\n\\t\\\"Create a standard system view of the model, me, a StringHolder and open it.; do not terminate the active process if in mvc\\\"\\n\\t| topView codeView |\\n\\n\\tSmalltalk isMorphic ifTrue: [^ self openAsMorphLabel: aString].\\n\\n\\ttopView _ (StandardSystemView new) model: self.\\n\\ttopView borderWidth: 1.\\n\\ttopView label: aString.\\n\\ttopView minimumSize: 100 @ 50.\\n\\n\\tcodeView _ PluggableTextView on: self \\n\\t\\t\\ttext: #contents accept: #acceptContents:\\n\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:.\\n\\tcodeView window: (0@0 extent: 200@200).\\n\\ttopView addSubView: codeView.\\n\\t\\\"self contents size > 0 ifTrue: [\\n\\t\\t\\tcodeView hasUnacceptedEdits: true]. Is it already saved or not??\\\"\\n\\tterminateBoolean\\n\\t\\tifTrue:\\n\\t\\t\\t[topView controller open]\\n\\t\\tifFalse:\\n\\t\\t\\t[topView controller openNoTerminate]! !\\n\\n\\n!StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 21:25'!\\nwantsAnnotationPane\\n\\t\\\"Answer whether the receiver, seen in some browser window, would like to have the so-called annotationpane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary.\\\"\\n\\n\\t^ Preferences annotationPanes! !\\n\\n!StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 18:57'!\\nwantsOptionalButtons\\n\\t\\\"Answer whether the receiver, seen in some browser window, would like to have the so-called optional button pane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary.\\\"\\n\\n\\t^ Preferences optionalButtons! !\\n\\n\\n!StringHolder methodsFor: 'tiles' stamp: 'di 11/4/2000 11:07'!\\nopenSyntaxView\\n\\t\\\"Open a syntax view on the current method\\\"\\n\\n\\t| class selector |\\n\\n\\t(selector _ self selectedMessageName) ifNotNil: [\\n\\t\\tclass _ self selectedClassOrMetaClass.\\n\\t\\tSyntaxMorph testClass: class andMethod: selector.\\n\\t]! !\\n\\n\\n!StringHolder methodsFor: 'toolbuilder' stamp: 'ar 2/11/2005 20:36'!\\nbuildWith: builder\\n\\t| windowSpec textSpec |\\n\\twindowSpec := builder pluggableWindowSpec new.\\n\\twindowSpec model: self.\\n\\twindowSpec label: 'Workspace'.\\n\\twindowSpec children: OrderedCollection new.\\n\\ttextSpec := builder pluggableTextSpec new.\\n\\ttextSpec \\n\\t\\tmodel: self;\\n\\t\\tgetText: #contents; \\n\\t\\tsetText: #acceptContents:; \\n\\t\\tselection: nil; \\n\\t\\tmenu: #codePaneMenu:shifted:;\\n\\t\\tframe: (0@0corner: 1@1).\\n\\twindowSpec children add: textSpec.\\n\\n\\t^builder build: windowSpec! !\\n\\n\\n!StringHolder methodsFor: 'user edits' stamp: 'di 4/21/1998 11:30'!\\nclearUserEditFlag\\n\\t\\\"Clear the hasUnacceptedEdits flag in all my dependent views.\\\"\\n\\n\\tself changed: #clearUserEdits! !\\n\\n!StringHolder methodsFor: 'user edits' stamp: 'tk 4/13/1998 23:07'!\\nokToChange\\n\\n\\tself canDiscardEdits ifTrue: [^ true].\\n\\tself changed: #wantToChange. \\\"Solicit cancel from view\\\"\\n\\t^ self canDiscardEdits\\n! !\\n\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 3/15/2004 09:17'!\\ncodeTextMorph\\n\\t^ self dependents\\n\\t\\tdetect: [:dep | (dep isKindOf: PluggableTextMorph)\\n\\t\\t\\t\\tand: [dep getTextSelector == #contents]]\\n\\t\\tifNone: []! !\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 6/9/2005 10:47'!\\nrequestor\\n\\t^ (TextRequestor new) model: self; yourself! !\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 3/15/2004 09:17'!\\nselectedInterval\\n\\t^self codeTextMorph selectionInterval! !\\n\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseAllMessages\\n\\t\\\"Create and schedule a message set browser on all implementors of all the messages sent by the current method.\\\"\\n\\n\\t| aClass aName method filteredList |\\n\\t(aName := self selectedMessageName) ifNotNil: [\\n\\t\\tmethod := (aClass := self selectedClassOrMetaClass) compiledMethodAt: aName.\\n\\t\\tfilteredList := method messages reject: \\n\\t\\t\\t[:each | #(new initialize = ) includes: each].\\n\\t\\tself systemNavigation browseAllImplementorsOfList: filteredList asSortedCollection\\n\\t\\t\\t title: 'All messages sent in ', aClass name, '.', aName]\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/18/1998 16:11'!\\nbrowseClass\\n\\t\\\"Open an class browser on this class and method\\\"\\n\\n\\tself selectedClassOrMetaClass ifNotNil: [\\n\\t\\tBrowser newOnClass: self selectedClassOrMetaClass \\n\\t\\t\\tselector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 08:42'!\\nbrowseLocalImplementors\\n\\t\\\"Present a menu of all messages sent by the currently selected message. \\n\\tOpen a message set browser of all implementors of the message chosen in or below\\n\\tthe selected class.\\n\\tDo nothing if no message is chosen.\\\"\\n\\tself getSelectorAndSendQuery: #browseAllImplementorsOf:localTo:\\n\\t\\tto: self systemNavigation\\n\\t\\twith: { self selectedClass }! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 20:41'!\\nbrowseLocalSendersOfMessages\\n\\t\\\"Present a menu of the currently selected message, as well as all\\n\\tmessages sent by it. Open a message set browser of all implementors\\n\\tof the message chosen in or below the selected class\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllCallsOn:localTo:\\n\\t\\tto: self systemNavigation\\n\\t\\twith: { self selectedClass }! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 08:45'!\\nbrowseMessages\\n\\t\\\"Present a menu of all messages sent by the currently selected message. \\n\\tOpen a message set browser of all implementors of the message chosen.\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseMethodFull\\n\\t\\\"Create and schedule a full Browser and then select the current class and message.\\\"\\n\\n\\t| myClass |\\n\\t(myClass := self selectedClassOrMetaClass) ifNotNil:\\n\\t\\t[Browser fullOnClass: myClass selector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 20:40'!\\nbrowseSendersOfMessages\\n\\t\\\"Present a menu of the currently selected message, as well as all messages sent by it. Open a message set browser of all senders of the selector chosen.\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseUnusedMethods\\n\\t| classes unsent messageList cls |\\n\\t(cls := self selectedClass)\\n\\t\\tifNil: [^ self].\\n\\tclasses := Array with: cls with: cls class.\\n\\tunsent := Set new.\\n\\tclasses\\n\\t\\tdo: [:c | unsent addAll: c selectors].\\n\\tunsent := self systemNavigation allUnSentMessagesIn: unsent.\\n\\tmessageList := OrderedCollection new.\\n\\tclasses\\n\\t\\tdo: [:c | (c selectors\\n\\t\\t\\t\\tselect: [:s | unsent includes: s]) asSortedCollection\\n\\t\\t\\t\\tdo: [:sel | messageList add: c name , ' ' , sel]].\\n\\tself systemNavigation browseMessageList: messageList name: 'Unsent Methods in ' , cls name! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseVersions\\n\\t\\\"Create and schedule a Versions Browser, showing all versions of the \\n\\tcurrently selected message. Answer the browser or nil.\\\"\\n\\t| selector class | \\n\\tself classCommentIndicated\\n\\t\\tifTrue: [ ClassCommentVersionsBrowser browseCommentOf: self selectedClass.\\n\\t\\t\\t^nil ].\\n\\n\\t(selector := self selectedMessageName)\\n\\t\\tifNil:[ self inform: 'Sorry, only actual methods have retrievable versions.'. ^nil ]\\n\\t\\tifNotNil: [\\n\\t\\t\\tclass := self selectedClassOrMetaClass.\\n\\t\\t\\t^VersionsBrowser\\n\\t\\t\\t\\tbrowseVersionsOf: (class compiledMethodAt: selector)\\n\\t\\t\\t\\tclass: self selectedClass\\n\\t\\t\\t\\tmeta: class isMeta\\n\\t\\t\\t\\tcategory: (class organization categoryOfElement: selector)\\n\\t\\t\\t\\tselector: selector]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/28/1998 19:14'!\\nbuildMessageBrowser\\n\\t\\\"Create and schedule a message browser.\\\"\\n\\n\\tself selectedMessageName ifNil: [^ self].\\n\\tBrowser openMessageBrowserForClass: self selectedClassOrMetaClass \\n\\t\\tselector: self selectedMessageName editString: nil! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 1/16/2004 21:14'!\\nclassHierarchy\\n\\t\\\"Create and schedule a class list browser on the receiver's hierarchy.\\\"\\n\\n\\tself systemNavigation\\n\\t\\tspawnHierarchyForClass: self selectedClassOrMetaClass \\\"OK if nil\\\"\\n\\t\\tselector: self selectedMessageName\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 5/8/2000 02:16'!\\nclassListKey: aChar from: view \\n\\t\\\"Respond to a Command key. I am a model with a list of classes and a \\n\\tcode pane, and I also have a listView that has a list of methods. The \\n\\tview knows how to get the list and selection.\\\"\\n\\n\\taChar == $f ifTrue: [^ self findMethod].\\n\\taChar == $r ifTrue: [^ self recent].\\n\\taChar == $h ifTrue: [^ self spawnHierarchy].\\n\\taChar == $x ifTrue: [^ self removeClass].\\n\\t^ self messageListKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ncopyName\\n\\t\\\"Copy the current selector to the clipboard\\\"\\n\\t| selector |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[Clipboard clipboardText: selector asString asText]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ncopySelector\\n\\t\\\"Copy the selected selector to the clipboard\\\"\\n\\n\\t| selector |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[Clipboard clipboardText: selector asString]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 7/1/2001 08:24'!\\nfileOutMessage\\n\\t\\\"Put a description of the selected message on a file\\\"\\n\\n\\tself selectedMessageName ifNotNil:\\n\\t\\t[Cursor write showWhile:\\n\\t\\t\\t[self selectedClassOrMetaClass fileOutMethod: self selectedMessageName]]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nfindMethodInChangeSets\\n\\t\\\"Find and open a changeSet containing the current method.\\\"\\n\\n\\t| aName |\\n\\t(aName := self selectedMessageName) ifNotNil: [\\n\\t\\tChangeSorter browseChangeSetsWithClass: self selectedClassOrMetaClass\\n\\t\\t\\t\\t\\tselector: aName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ninspectInstances\\n\\t\\\"Inspect all instances of the selected class.\\\"\\n\\n\\t| myClass |\\n\\t(myClass := self selectedClassOrMetaClass) ifNotNil:\\n\\t\\t[myClass theNonMetaClass inspectAllInstances]. \\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ninspectSubInstances\\n\\t\\\"Inspect all instances of the selected class and all its subclasses\\\"\\n\\n\\t| aClass |\\n\\t(aClass := self selectedClassOrMetaClass) ifNotNil: [\\n\\t\\taClass theNonMetaClass inspectSubInstances].\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmakeIsolatedCodePane\\n\\t| msgName |\\n\\n\\t(msgName := self selectedMessageName) ifNil: [^ Beeper beep].\\n\\tMethodHolder makeIsolatedCodePaneForClass: self selectedClassOrMetaClass selector: msgName! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmessageListKey: aChar from: view\\n\\t\\\"Respond to a Command key. I am a model with a code pane, and I also\\n\\thave a listView that has a list of methods. The view knows how to get\\n\\tthe list and selection.\\\"\\n\\n\\t| sel class |\\n\\taChar == $D ifTrue: [^ self toggleDiffing].\\n\\n\\tsel := self selectedMessageName.\\n\\taChar == $m ifTrue: \\\"These next two put up a type in if no message selected\\\"\\n\\t\\t[^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation].\\n\\taChar == $n ifTrue: \\n\\t\\t[^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation].\\n\\n\\t\\\"The following require a class selection\\\"\\n\\t(class := self selectedClassOrMetaClass) ifNil: [^ self arrowKey: aChar from: view].\\n\\taChar == $b ifTrue: [^ Browser fullOnClass: class selector: sel].\\n\\taChar == $N ifTrue: [^ self browseClassRefs].\\n\\taChar == $i ifTrue: [^ self methodHierarchy].\\n\\taChar == $h ifTrue: [^ self classHierarchy].\\n\\taChar == $p ifTrue: [^ self browseFullProtocol].\\n\\n\\t\\\"The following require a method selection\\\"\\n\\tsel ifNotNil: \\n\\t\\t[aChar == $o ifTrue: [^ self fileOutMessage].\\n\\t\\taChar == $c ifTrue: [^ self copySelector].\\n\\t\\taChar == $v ifTrue: [^ self browseVersions].\\n\\t\\taChar == $O ifTrue: [^ self openSingleMessageBrowser].\\n\\t\\taChar == $x ifTrue: [^ self removeMessage]].\\n\\n\\t^ self arrowKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmessageListSelectorTitle\\n\\t| selector aString aStamp aSize |\\n\\n\\t(selector := self selectedMessageName)\\n\\t\\tifNil:\\n\\t\\t\\t[aSize := self messageList size.\\n\\t\\t\\t^ (aSize == 0 ifTrue: ['no'] ifFalse: [aSize printString]), ' message', (aSize == 1 ifTrue: [''] ifFalse: ['s'])]\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences timeStampsInMenuTitles\\n\\t\\t\\t\\tifFalse:\\t[^ nil].\\n\\t\\t\\taString := selector truncateWithElipsisTo: 28.\\n\\t\\t\\t^ (aStamp := self timeStamp) size > 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aString, String cr, aStamp]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[aString]]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 1/16/2004 21:10'!\\nmethodHierarchy\\n\\t\\\"Create and schedule a method browser on the hierarchy of implementors.\\\"\\n\\n\\tself systemNavigation \\n\\t\\t\\tmethodHierarchyBrowserForClass: self selectedClassOrMetaClass \\n\\t\\t\\tselector: self selectedMessageName\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nofferDurableMenuFrom: menuRetriever shifted: aBoolean\\n\\t\\\"Pop up (morphic only) a menu whose target is the receiver and whose contents are provided by sending the menuRetriever to the receiver. The menuRetriever takes two arguments: a menu, and a boolean representing the shift state; put a stay-up item at the top of the menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu := MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\taMenu popUpInWorld! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nofferMenuFrom: menuRetriever shifted: aBoolean\\n\\t\\\"Pop up, in morphic or mvc as the case may be, a menu whose target is the receiver and whose contents are provided by sending the menuRetriever to the receiver. The menuRetriever takes two arguments: a menu, and a boolean representing the shift state.\\\"\\n\\n\\t| aMenu |\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue:\\n\\t\\t\\t[aMenu := MenuMorph new defaultTarget: self.\\n\\t\\t\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\t\\taMenu popUpInWorld]\\n\\t\\tifFalse:\\n\\t\\t\\t[aMenu := CustomMenu new.\\n\\t\\t\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\t\\taMenu invokeOn: self]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nopenSingleMessageBrowser\\n\\t| msgName mr |\\n\\t\\\"Create and schedule a message list browser populated only by the currently selected message\\\"\\n\\n\\t(msgName := self selectedMessageName) ifNil: [^ self].\\n\\n\\tmr := MethodReference new\\n\\t\\tsetStandardClass: self selectedClassOrMetaClass\\n\\t\\tmethodSymbol: msgName.\\n\\n\\tself systemNavigation \\n\\t\\tbrowseMessageList: (Array with: mr)\\n\\t\\tname: mr asStringOrText\\n\\t\\tautoSelect: nil! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'RAA 12/10/1999 09:36'!\\npackageListKey: aChar from: view\\n\\t\\\"Respond to a Command key in the package pane in the PackageBrowser\\\"\\n\\taChar == $f ifTrue: [^ self findClass].\\n\\t^ self classListKey: aChar from: view\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/28/1998 18:16'!\\nprintOutMessage\\n\\t\\\"Write a file with the text of the selected message, for printing by a web browser\\\"\\n\\n\\tself selectedMessageName ifNotNil: [\\n\\t\\tself selectedClassOrMetaClass fileOutMethod: self selectedMessageName\\n\\t\\t\\t\\t\\t\\t\\tasHtml: true]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 5/23/2003 14:42'!\\nremoveFromCurrentChanges\\n\\t\\\"Tell the changes mgr to forget that the current msg was changed.\\\"\\n\\n\\tChangeSet current removeSelectorChanges: self selectedMessageName \\n\\t\\t\\tclass: self selectedClassOrMetaClass.\\n\\tself changed: #annotation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 1/28/1999 12:34'!\\nrevertAndForget\\n\\t\\\"Revert to the previous version of the current method, and tell the changes mgr to forget that it was ever changed. Danger!! Use only if you really know what you're doing!!\\\"\\n\\n\\tself okToChange ifFalse: [^ self].\\n\\tself revertToPreviousVersion.\\n\\tself removeFromCurrentChanges.\\n\\tself contentsChanged\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nrevertToPreviousVersion\\n\\t\\\"Revert to the previous version of the current method\\\"\\n\\t| aClass aSelector changeRecords |\\n\\tself okToChange ifFalse: [^ self].\\n\\taClass := self selectedClassOrMetaClass.\\n\\taClass ifNil: [^ self changed: #flash].\\n\\taSelector := self selectedMessageName.\\n\\tchangeRecords := aClass changeRecordsAt: aSelector.\\n\\t(changeRecords == nil or: [changeRecords size <= 1]) ifTrue: [self changed: #flash. ^ Beeper beep].\\n\\tchangeRecords second fileIn.\\n\\tself contentsChanged\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nselectMessageAndEvaluate: aBlock\\n\\t\\\"Allow the user to choose one selector, chosen from the currently selected message's selector, as well as those of all messages sent by it, and evaluate aBlock on behalf of chosen selector. If there is only one possible choice, simply make it; if there are multiple choices, put up a menu, and evaluate aBlock on behalf of the the chosen selector, doing nothing if the user declines to choose any\\\"\\n\\n\\t| selector method messages |\\n\\t(selector := self selectedMessageName) ifNil: [^ self].\\n\\tmethod := (self selectedClassOrMetaClass ifNil: [^ self])\\n\\t\\tcompiledMethodAt: selector\\n\\t\\tifAbsent: [].\\n\\t(method isNil or: [(messages := method messages) size == 0])\\n\\t\\t ifTrue: [^ aBlock value: selector].\\n\\t(messages size == 1 and: [messages includes: selector])\\n\\t\\tifTrue:\\n\\t\\t\\t[^ aBlock value: selector]. \\\"If only one item, there is no choice\\\"\\n\\n\\tself systemNavigation \\n\\t\\tshowMenuOf: messages\\n\\t\\twithFirstItem: selector\\n\\t\\tifChosenDo: [:sel | aBlock value: sel]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'nk 11/15/2002 12:23'!\\nsystemCatListKey: aChar from: view\\n\\t\\\"Respond to a Command key. I am a model with a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection.\\\"\\n\\n\\taChar == $f ifTrue: [^ self findClass].\\n\\taChar == $x ifTrue: [^ self removeSystemCategory].\\n\\t^ self classListKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ntimeStamp\\n\\t\\\"Answer the time stamp for the chosen class and method, if any, else an empty string\\\"\\n\\n\\t| selector aMethod |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[self selectedClassOrMetaClass \\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[^ String new]\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[aMethod := self selectedClassOrMetaClass compiledMethodAt: selector ifAbsent: [nil].\\n\\t\\t\\t\\taMethod ifNotNil: [^ Utilities timeStampForMethod: aMethod]]].\\n\\t^ String new! !\\n\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:22'!\\nbrowseClassRefs\\n\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseAllCallsOnClass: cls theNonMetaClass]\\n! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:22'!\\nbrowseClassVariables\\n\\t\\\"Browse the class variables of the selected class. 2/5/96 sw\\\"\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseClassVariables: cls]\\n! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:23'!\\nbrowseClassVarRefs\\n\\t\\\"1/17/96 sw: devolve responsibility to the class, so that the code that does the real work can be shared\\\"\\n\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseClassVarRefs: cls]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:23'!\\nbrowseFullProtocol\\n\\t\\\"Open up a protocol-category browser on the value of the receiver's current selection. If in mvc, an old-style protocol browser is opened instead. Someone who still uses mvc might wish to make the protocol-category-browser work there too, thanks.\\\"\\n\\n\\t| aClass |\\n\\n\\t(Smalltalk isMorphic and: [Smalltalk includesKey: #Lexicon]) ifFalse: [^ self spawnFullProtocol].\\n\\t((aClass := self selectedClassOrMetaClass) notNil and: [aClass isTrait not]) ifTrue:\\n\\t\\t[(Smalltalk at: #Lexicon) new openOnClass: aClass inWorld: ActiveWorld showingSelector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:24'!\\nbrowseInstVarDefs \\n\\n\\t| cls |\\n\\tcls := self selectedClassOrMetaClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseInstVarDefs: cls]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:24'!\\nbrowseInstVarRefs\\n\\t\\\"1/26/96 sw: real work moved to class, so it can be shared\\\"\\n\\t| cls |\\n\\tcls := self selectedClassOrMetaClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseInstVarRefs: cls]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringHolder class\\n\\tinstanceVariableNames: ''!\\n\\n!StringHolder class methodsFor: 'class initialization'!\\ninitialize\\n\\t\\\"The class variables were initialized once, and subsequently filled with\\n\\tinformation. Re-executing this method is therefore dangerous.\\\" \\n\\t \\n\\t\\\"workSpace _ StringHolder new\\\"\\n\\n\\t\\\"StringHolder initialize\\\"! !\\n\\n\\n!StringHolder class methodsFor: 'instance creation' stamp: 'ar 9/27/2005 20:48'!\\nopen\\n\\t(Smalltalk at: #Workspace ifAbsent:[self]) new openLabel: 'Workspace'\\n\\t\\t\\\"Not to be confused with our own class var 'Workspace'\\\"! !\\n\\n!StringHolder class methodsFor: 'instance creation' stamp: 'tk 5/4/1998 16:41'!\\nopenLabel: aString\\n\\n\\tself new openLabel: aString! !\\n\\n\\n!StringHolder class methodsFor: 'window color' stamp: 'sw 2/26/2002 14:44'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name wording: 'Workspace' brightColor: #lightYellow pastelColor: #paleYellow helpMessage: 'A place for text in a window.'! !\\nParagraphEditor subclass: #StringHolderController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'CodeYellowButtonMenu CodeYellowButtonMessages'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StringHolderController commentStamp: '<historical>' prior: 0!\\nI 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.\\n\\tdoIt\\tevaluate the text selection as an expression\\n\\tprintIt\\tsame as doIt but insert a description of the result after the selection\\n\\taccept\\tstore the contents of the StringHolder into the model\\n\\tcancel\\tstore the contents of the model into the StringHolder!\\n\\n\\n!StringHolderController methodsFor: 'accessing' stamp: 'di 6/21/2001 10:32'!\\nchangeText: aText\\n\\t\\\"The paragraph to be edited is changed to aText.\\\"\\n\\tparagraph text: aText.\\n\\tself resetState.\\n\\tself selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size.\\n\\tself selectAndScroll.\\n\\tself deselect! !\\n\\n!StringHolderController methodsFor: 'accessing'!\\nmodel: aModel\\n\\n\\tsuper model: aModel.\\n\\tview displayContents == nil\\n\\t\\tifFalse: [self changeParagraph: view displayContents]! !\\n\\n\\n!StringHolderController methodsFor: 'compiler access'!\\nbindingOf: aString\\n\\t^model bindingOf: aString! !\\n\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'di 10/9/1998 15:41'!\\nhasUnacceptedEdits: aBoolean\\n\\t^ view hasUnacceptedEdits: aBoolean! !\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:09'!\\nuserHasEdited\\n\\t\\\"Note that the user has edited my text.\\\"\\n\\n\\tview hasUnacceptedEdits: true\\n! !\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:08'!\\nuserHasNotEdited\\n\\t\\\"Note that my text is free of user edits.\\\"\\n\\n\\tmodel clearUserEditFlag\\n! !\\n\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:53'!\\naccept \\n\\t\\\"Refer to the comment in ParagraphEditor|accept.\\\"\\n\\n\\tsuper accept.\\n\\tmodel contents: paragraph string.\\n\\tself userHasNotEdited.\\n! !\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:54'!\\ncancel \\n\\t\\\"Refer to the comment in ParagraphEditor|cancel.\\\"\\n\\n\\tsuper cancel.\\n\\tself userHasNotEdited.\\n! !\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:14'!\\nperformMenuMessage: aSelector\\n\\t\\\"Intercept #again so the model does not get locked by keying the search text.\\\"\\n\\n\\t| hadEdits |\\n\\thadEdits _ view canDiscardEdits not.\\n\\tsuper performMenuMessage: aSelector.\\n\\t(hadEdits not and:\\n\\t [aSelector == #again and:\\n\\t [(UndoMessage sends: #undoAgain:andReselect:typedKey:) and:\\n\\t [UndoMessage arguments at: 3]]])\\n\\t\\tifTrue: [self userHasNotEdited].\\n! !\\n\\n\\n!StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:43'!\\ncloseTypeIn\\n\\t\\\"Note edit if something actually was typed.\\\"\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [self userHasEdited].\\n\\tsuper closeTypeIn.\\n! !\\n\\n!StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:45'!\\nzapSelectionWith: aText\\n\\t\\\"Note edit except during typeIn, which notes edits at close.\\\"\\n\\n\\tsuper zapSelectionWith: aText.\\n\\tbeginTypeInBlock == nil ifTrue: [self userHasEdited].\\n! !\\nView subclass: #StringHolderView\\n\\tinstanceVariableNames: 'displayContents hasUnacceptedEdits askBeforeDiscardingEdits'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StringHolderView commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndefaultController \\n\\t\\\"Refer to the comment in View|defaultController.\\\"\\n\\n\\t^self defaultControllerClass newParagraph: displayContents! !\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndefaultControllerClass \\n\\t\\\"Refer to the comment in View|defaultControllerClass.\\\"\\n\\n\\t^StringHolderController! !\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndisplayContents\\n\\n\\t^displayContents! !\\n\\n\\n!StringHolderView methodsFor: 'deEmphasizing'!\\ndeEmphasizeView \\n\\t\\\"Refer to the comment in View|deEmphasizeView.\\\"\\n\\n\\t(self controller isKindOf: ParagraphEditor)\\n\\t \\tifTrue: [controller deselect]! !\\n\\n\\n!StringHolderView methodsFor: 'displaying'!\\ndisplay \\n\\t\\\"Refer to the comment in View.display.\\\"\\n\\t(self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])\\n\\t\\tifTrue: \\\"Recompose the text if the window changed\\\"\\n\\t\\t\\t\\t[self positionDisplayContents. \\n\\t\\t\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\t\\t\\tifTrue: [controller recomputeSelection]].\\n\\tsuper display! !\\n\\n!StringHolderView methodsFor: 'displaying' stamp: 'hmm 6/18/2000 19:24'!\\ndisplayView \\n\\t\\\"Refer to the comment in View|displayView.\\\"\\n\\n\\tDisplay deferUpdatesIn: self displayBox while: [\\n\\t\\tself clearInside.\\n\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\tifTrue: [controller display]\\n\\t\\t\\tifFalse: [displayContents display]]! !\\n\\n!StringHolderView methodsFor: 'displaying'!\\nlock\\n\\t\\\"Refer to the comment in view|lock. Must do at least what display would do to lock the view.\\\"\\n\\t(self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])\\n\\t\\tifTrue: \\\"Recompose the text if the window changed\\\"\\n\\t\\t\\t\\t[self positionDisplayContents. \\n\\t\\t\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\t\\t\\tifTrue: [controller recomputeSelection]].\\n\\tsuper lock! !\\n\\n!StringHolderView methodsFor: 'displaying'!\\npositionDisplayContents\\n\\t\\\"Presumably the text being displayed changed so that the wrapping box \\n\\tand clipping box should be reset.\\\"\\n\\n\\tdisplayContents \\n\\t\\twrappingBox: (self insetDisplayBox insetBy: 6 @ 0)\\n\\t\\tclippingBox: self insetDisplayBox! !\\n\\n\\n!StringHolderView methodsFor: 'initialize-release' stamp: 'jm 3/24/98 14:39'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\n\\tsuper initialize.\\n\\tdisplayContents _ '' asParagraph.\\n\\thasUnacceptedEdits _ false.\\n\\taskBeforeDiscardingEdits _ true.\\n! !\\n\\n\\n!StringHolderView methodsFor: 'model access'!\\neditString: aString \\n\\t\\\"The paragraph to be displayed is created from the characters in aString.\\\"\\n\\n\\tdisplayContents _ Paragraph withText: aString asText\\n\\t\\tstyle: TextStyle default copy\\n\\t\\tcompositionRectangle: (self insetDisplayBox insetBy: 6 @ 0)\\n\\t\\tclippingRectangle: self insetDisplayBox\\n\\t\\tforeColor: self foregroundColor backColor: self backgroundColor.\\n\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\tifTrue: [controller changeParagraph: displayContents]! !\\n\\n!StringHolderView methodsFor: 'model access' stamp: 'sma 5/28/2000 23:25'!\\ngetMenu: shiftKeyState\\n\\t^ nil! !\\n\\n!StringHolderView methodsFor: 'model access'!\\nmodel: aLockedModel \\n\\t\\\"Refer to the comment in View|model:.\\\"\\n \\n\\tsuper model: aLockedModel.\\n\\tself editString: model contents! !\\n\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 14:38'!\\naskBeforeDiscardingEdits: aBoolean\\n\\t\\\"Set the flag that determines whether the user should be asked before discarding unaccepted edits.\\\"\\n\\n\\taskBeforeDiscardingEdits _ aBoolean.\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 22:58'!\\ncanDiscardEdits\\n\\t\\\"Return true if this view either has no text changes or does not care.\\\"\\n\\n\\t^ (hasUnacceptedEdits & askBeforeDiscardingEdits) not\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 17:49'!\\nhasUnacceptedEdits\\n\\t\\\"Return true if this view has unaccepted edits.\\\"\\n\\n\\t^ hasUnacceptedEdits\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 17:17'!\\nhasUnacceptedEdits: aBoolean\\n\\t\\\"Set the hasUnacceptedEdits flag to the given value.\\\"\\n\\n\\thasUnacceptedEdits _ aBoolean.\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'dgd 9/21/2003 17:42'!\\npromptForCancel\\n\\t\\\"Ask if it is OK to cancel changes to text\\\"\\n\\t| okToCancel stripes |\\n\\tself topView isCollapsed ifTrue:\\n\\t\\t[(self confirm: 'Changes have not been saved.\\nIs it OK to cancel those changes?' translated) ifTrue: [model clearUserEditFlag].\\n\\t\\t^ self].\\n\\tstripes _ (Form extent: 16@16 fromStipple: 16r36C9) bits.\\n\\tDisplay border: self insetDisplayBox width: 4\\n\\t\\t\\trule: Form reverse fillColor: stripes.\\n\\tokToCancel _ self confirm: 'Changes have not been saved.\\nIs it OK to cancel those changes?' translated.\\n\\tDisplay border: self insetDisplayBox width: 4\\n\\t\\t\\trule: Form reverse fillColor: stripes.\\n\\tokToCancel ifTrue:\\n\\t\\t[self updateDisplayContents.\\n\\t\\tmodel clearUserEditFlag].\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'di 4/21/1998 11:30'!\\nupdate: aSymbol\\n\\t\\\"Refer to the comment in View|update:.\\\"\\n\\taSymbol == #wantToChange ifTrue: [^ self promptForCancel].\\n\\taSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false].\\n\\taSymbol == #flash ifTrue: [^ controller flash].\\n\\tself updateDisplayContents! !\\n\\n!StringHolderView methodsFor: 'updating'!\\nupdateDisplayContents\\n\\t\\\"Make the text that is displayed be the contents of the receiver's model.\\\"\\n\\n\\tself editString: model contents.\\n\\tself displayView! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringHolderView class\\n\\tinstanceVariableNames: ''!\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\ncontainer\\n\\t\\\"Answer an instance of me with a new instance of StringHolder as the \\n\\tmodel.\\\"\\n\\n\\t^self container: StringHolder new! !\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\ncontainer: aContainer \\n\\t\\\"Answer an instance of me whose model is aContainer. Give it a 2-dot \\n\\tborder.\\\"\\n\\n\\t| aCodeView |\\n\\taCodeView _ self new model: aContainer.\\n\\taCodeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\t^aCodeView! !\\n\\n!StringHolderView class methodsFor: 'instance creation' stamp: 'ar 9/27/2005 20:48'!\\nopen\\n\\t\\\"Create a standard system view of a workspace on the screen.\\\"\\n\\n\\tself open: StringHolder new label: 'Workspace'! !\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\nopen: aStringHolder \\n\\t\\\"Create a standard system view of the argument, aStringHolder, as viewed \\n\\tby an instance of me. The view has label 'StringHolder'.\\\"\\n\\n\\tself open: aStringHolder label: 'StringHolder'! !\\n\\n!StringHolderView class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:15'!\\nopen: aStringHolder label: labelString \\n\\t\\\"NOTE this should be in the model class, and all senders so redirected,\\n\\tin order that the view class can be discarded in a morphic world.\\\"\\n\\n\\t\\\"Create a standard system view of the model, aStringHolder, as viewed by \\n\\tan instance of me. The label of the view is aString.\\\"\\n\\t| aStringHolderView topView |\\n\\n\\tSmalltalk isMorphic ifTrue: [^ aStringHolder openAsMorphLabel: labelString].\\n\\n\\taStringHolderView _ self container: aStringHolder.\\n\\ttopView _ StandardSystemView new.\\n\\ttopView model: aStringHolderView model.\\n\\ttopView addSubView: aStringHolderView.\\n\\ttopView label: labelString.\\n\\ttopView minimumSize: 100 @ 50.\\n\\ttopView controller open! !\\nMorph subclass: #StringMorph\\n\\tinstanceVariableNames: 'font emphasis contents hasFocus'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic'!\\n!StringMorph commentStamp: 'efc 3/7/2003 17:34' prior: 0!\\nStringMorph is a \\\"lightweight\\\" Morph to display a String. It supports only a single font, color, and emphasis combination. For multiple text styles, use TextMorph.\\n\\nStructure:\\ninstance var \\tType Description \\nfont \\t\\t\\tStrikeFont \\t\\t(normally nil; then the accessor #font gives back TextStyle \\n\\t\\t\\t\\tor nil\\t\\t\\tdefaultFont) \\nemphasis \\t\\tSmallInteger\\tbitmask determining character attributes (underline, bold, \\t\\t\\t\\t\\t\\t\\t\\titalics, narrow, struckout) \\ncontents \\t\\tString \\t\\t\\tThe text that will be displayed. \\nhasFocus \\t\\tBoolean \\t\\tDo I have the keyboard focus or not? \\n\\nIf you shift-click on a StringMorph you can edit its string. This is accomplished the following way: StringMorph can launch a StringMorphEditor if it receives a #mouseDown event.\\n\\nA StringMorph may also be used like a SimpleButtonMorph to do an action when clicked. Use the menu 'extras' / 'add mouseUpAction'.\\n\\nThe following propery will be defined:\\naStringMorph valueOfProperty: #mouseUpCodeToRun!\\n]style[(11 20 5 14 6 97 9 14 47 9 10 53 9 40 12 108 6 49 7 168 17 75 17 163)f1LStringMorph Hierarchy;,f1,f1LMorph Comment;,f1,f1LString Comment;,f1,f1LTextMorph Comment;,f1,f1i,f1,f1LStrikeFont Comment;,f1,f1LTextStyle Comment;,f1,f1LSmallInteger Comment;,f1,f1LString Comment;,f1,f1LBoolean Comment;,f1,f1LStringMorphEditor Comment;,f1,f1LSimpleButtonMorph Comment;,f1!\\n\\n\\n!StringMorph methodsFor: 'accessing'!\\ncontents\\n\\n\\t^ contents! !\\n\\n!StringMorph methodsFor: 'accessing'!\\ncontentsClipped: aString\\n\\t\\\"Change my text, but do not change my size as a result\\\"\\n\\tcontents = aString ifTrue: [^ self]. \\\"No substantive change\\\"\\n\\tcontents _ aString.\\n\\tself changed! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:15'!\\ncontents: newContents \\n\\t| scanner |\\n\\tcontents := newContents isText\\n\\t\\t\\t\\tifTrue: [scanner := StringMorphAttributeScanner new initializeFromStringMorph: self.\\n\\t\\t\\t\\t\\t(newContents attributesAt: 1 forStyle: self font textStyle)\\n\\t\\t\\t\\t\\t\\tdo: [:attr | attr emphasizeScanner: scanner].\\n\\t\\t\\t\\t\\temphasis := scanner emphasis.\\n\\t\\t\\t\\t\\tfont := scanner font emphasis: emphasis.\\n\\t\\t\\t\\t\\tcolor := scanner textColor.\\n\\t\\t\\t\\t\\tnewContents string]\\n\\t\\t\\t\\tifFalse: [contents = newContents\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\t\\\"no substantive change\\\"\\n\\t\\t\\t\\t\\tnewContents].\\n\\tself fitContents! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 12/12/2001 02:44'!\\nfitContents\\n\\n\\t| newBounds boundsChanged |\\n\\tnewBounds _ self measureContents.\\n\\tboundsChanged _ bounds extent ~= newBounds.\\n\\tself extent: newBounds.\\t\\t\\\"default short-circuits if bounds not changed\\\"\\n\\tboundsChanged ifFalse: [self changed]! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 1/31/2001 19:33'!\\nfont\\n\\t\\\"who came up with #fontToUse rather than font?!!\\\"\\n\\t^self fontToUse! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'tk 8/28/2000 13:59'!\\nfontName: fontName size: fontSize\\n\\n\\t^ self font: (StrikeFont familyName: fontName size: fontSize) \\n\\t\\t\\temphasis: 0! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'dgd 2/21/2003 23:07'!\\nfontToUse\\n\\t| fontToUse |\\n\\tfontToUse := font isNil ifTrue: [TextStyle defaultFont] ifFalse: [font].\\n\\t(emphasis isNil or: [emphasis = 0]) \\n\\t\\tifTrue: [^fontToUse]\\n\\t\\tifFalse: [^fontToUse emphasized: emphasis]! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'di 4/2/1999 16:11'!\\nfont: aFont emphasis: emphasisCode\\n\\tfont _ aFont.\\n\\temphasis _ emphasisCode.\\n\\tself fitContents.\\n\\\"\\nin inspector say,\\n\\t self font: (TextStyle default fontAt: 2) emphasis: 1\\n\\\"! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/8/1999 11:10'!\\ninterimContents: aString\\n\\t\\\"The receiver is under edit and aString represents the string the user sees as she edits, which typically will not have been accepted and indeed may be abandoned\\\"\\n\\n\\tself contents: aString! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 12/30/2001 20:45'!\\nmeasureContents\\n\\t| f |\\n\\tf _ self fontToUse.\\n\\t^(((f widthOfString: contents) max: self minimumWidth) @ f height).! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/8/1999 13:44'!\\nminimumWidth\\n\\t\\\"Answer the minimum width that the receiver can have. A nonzero value here keeps the receiver from degenerating into something that cannot ever be seen or touched again!! Obeyed by fitContents.\\\"\\n\\n\\t^ 3! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 12/6/1999 13:16'!\\nsetWidth: width\\n\\n\\tself extent: width @ (font ifNil: [TextStyle defaultFont]) height! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'tk 12/16/1998 11:55'!\\nuserString\\n\\t\\\"Do I have a text string to be searched on?\\\"\\n\\n\\t^ contents! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/16/1999 22:57'!\\nvalueFromContents\\n\\t\\\"Return a new value from the current contents string.\\\"\\n\\t^ contents! !\\n\\n\\n!StringMorph methodsFor: 'connectors-layout' stamp: 'dgd 2/16/2003 21:52'!\\nminHeight\\n\\\"answer the receiver's minHeight\\\"\\n\\t^ self fontToUse height! !\\n\\n\\n!StringMorph methodsFor: 'drawing' stamp: 'ar 12/31/2001 02:38'!\\ndrawOn: aCanvas\\n\\n\\taCanvas drawString: contents in: bounds font: self fontToUse color: color.! !\\n\\n!StringMorph methodsFor: 'drawing' stamp: 'tk 8/1/2001 14:15'!\\nlookTranslucent\\n\\n\\t\\\"keep the text the same color (black)\\\"! !\\n\\n\\n!StringMorph methodsFor: 'editing'!\\nacceptContents\\n\\t\\\"The message is sent when the user hits enter or Cmd-S. Accept the current contents and end editing. This default implementation does nothing.\\\"\\n! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/8/1999 17:04'!\\nacceptValue: aValue\\n\\t| val |\\n\\tself contents: (val _ aValue asString).\\n\\t^ val! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/17/1999 13:27'!\\ncancelEdits\\n\\n\\tself doneWithEdits! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'di 9/6/1999 22:44'!\\ndoneWithEdits\\n\\n\\thasFocus _ false! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'nk 2/24/2005 20:11'!\\nlaunchMiniEditor: evt\\n\\n\\t| textMorph |\\n\\thasFocus _ true. \\\"Really only means edit in progress for this morph\\\"\\n\\ttextMorph _ StringMorphEditor new contentsAsIs: contents.\\n\\ttextMorph beAllFont: self fontToUse.\\n\\ttextMorph bounds: (self bounds expandBy: 0@2).\\n\\tself addMorphFront: textMorph.\\n\\tevt hand newKeyboardFocus: textMorph.\\n\\ttextMorph editor selectFrom: 1 to: textMorph paragraph text string size! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/8/1999 10:42'!\\nlostFocusWithoutAccepting\\n\\t\\\"The message is sent when the user, having been in an editing episode on the receiver, changes the keyboard focus -- typically by clicking on some editable text somewhere else -- without having accepted the current edits.\\\"\\n\\n\\tself acceptContents! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 7/21/1999 14:59'!\\nwantsKeyboardFocusOnShiftClick\\n\\t^ owner topRendererOrSelf wantsKeyboardFocusFor: self\\n! !\\n\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'ar 10/6/2000 00:16'!\\nhandlesMouseDown: evt\\n\\t^ (evt shiftPressed and: [self wantsKeyboardFocusOnShiftClick])\\n\\t\\tifTrue: [true]\\n\\t\\tifFalse: [super handlesMouseDown: evt].\\n! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'sw 9/8/1999 11:26'!\\nhasFocus\\n\\t^ hasFocus! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'di 9/5/1999 17:25'!\\nmouseDown: evt\\n\\t\\\"If the shift key is pressed, make this string the keyboard input focus.\\\"\\n\\n\\t(evt shiftPressed and: [self wantsKeyboardFocusOnShiftClick])\\n\\t\\tifTrue: [self launchMiniEditor: evt]\\n\\t\\tifFalse: [super mouseDown: evt].\\n! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'sw 5/6/1998 15:45'!\\nwouldAcceptKeyboardFocus\\n\\t^ self isLocked not! !\\n\\n\\n!StringMorph methodsFor: 'font' stamp: 'efc 2/22/2003 21:35'!\\nemphasis: aNumber\\n\\t\\\"Set the receiver's emphasis as indicated. aNumber is a bitmask with the following format:\\n\\n\\tbit\\tattribute\\n\\t1\\tbold\\n\\t2\\titalic\\n\\t4\\tunderlined\\n\\t8\\tnarrow\\n\\t16\\tstruckOut\\\"\\n\\n\\t\\\"examples: 0 -> plain. \\n\\t1 -> bold. 2 -> italic. 3 -> bold italic. 4 -> underlined \\n\\t5 -> bold underlined. 6 -> italic underlined. 7 -> bold italic underlined \\n\\tetc...\\\"\\n\\n\\temphasis _ aNumber.\\n\\t^ self font: font emphasis: emphasis! !\\n\\n\\n!StringMorph methodsFor: 'halos and balloon help' stamp: 'sw 6/15/1998 15:34'!\\naddOptionalHandlesTo: aHalo box: box\\n\\tself flag: #deferred.\\n\\n\\t\\\"Eventually...\\n\\tself addFontHandlesTo: aHalo box: box\\\"! !\\n\\n!StringMorph methodsFor: 'halos and balloon help' stamp: 'sw 6/6/2001 13:34'!\\nboundsForBalloon\\n\\t\\\"Some morphs have bounds that are way too big. This is a contorted way of making things work okay in PluggableListMorphs, whose list elements historically have huge widths\\\"\\n\\n\\t| ownerOwner |\\n\\t^ ((owner notNil and: [(ownerOwner _ owner owner) notNil]) and:\\n\\t\\t\\t[ownerOwner isKindOf: PluggableListMorph])\\n\\t\\tifTrue:\\n\\t\\t\\t[self boundsInWorld intersect: ownerOwner boundsInWorld]\\n\\t\\tifFalse:\\n\\t\\t\\t[super boundsForBalloon]! !\\n\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:42'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tfont _ nil.\\n\\temphasis _ 0.\\n\\thasFocus _ false! !\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:57'!\\ninitWithContents: aString font: aFont emphasis: emphasisCode \\n\\tsuper initialize.\\n\\t\\n\\tfont _ aFont.\\n\\temphasis _ emphasisCode.\\n\\thasFocus _ false.\\n\\tself contents: aString! !\\n\\n\\n!StringMorph methodsFor: 'layout' stamp: 'nk 5/11/2001 09:33'!\\nfullBounds\\n\\tself contents ifNil: [ self contents: 'String Morph' ].\\n\\t^super fullBounds! !\\n\\n\\n!StringMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'change font' translated action: #changeFont.\\n\\taCustomMenu add: 'change emphasis' translated action: #changeEmphasis.\\n! !\\n\\n!StringMorph methodsFor: 'menu' stamp: 'yo 3/14/2005 13:03'!\\nchangeEmphasis\\n\\n\\t| reply aList |\\n\\taList _ #(normal bold italic narrow underlined struckOut).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ifNotNil:[\\n\\t\\tself emphasis: (TextEmphasis perform: reply) emphasisCode.\\n\\t].\\n! !\\n\\n!StringMorph methodsFor: 'menu' stamp: 'ar 1/5/2002 21:45'!\\nchangeFont\\n\\t| newFont |\\n\\tnewFont _ StrikeFont fromUser: self fontToUse.\\n\\tnewFont ifNotNil:[self font: newFont].! !\\n\\n\\n!StringMorph methodsFor: 'objects from disk' stamp: 'tk 11/29/2004 16:52'!\\nfixUponLoad: aProject seg: anImageSegment\\n\\n\\t\\\"We are in an old project that is being loaded from disk.\\n\\nFix up conventions that have changed.\\\"\\n\\n\\n\\n\\t| substituteFont |\\n\\n\\tsubstituteFont _ aProject projectParameters at:\\n\\n#substitutedFont ifAbsent: [#none].\\n\\n\\t(substituteFont ~~ #none and: [self font == substituteFont])\\n\\n\\t\\t\\tifTrue: [ self fitContents ].\\n\\n\\n\\n\\t^ super fixUponLoad: aProject seg: anImageSegment! !\\n\\n\\n!StringMorph methodsFor: 'parts bin' stamp: 'dgd 2/14/2003 21:58'!\\ninitializeToStandAlone\\n\\tsuper initializeToStandAlone.\\n\\t\\n\\tfont _ nil.\\n\\temphasis _ 0.\\n\\thasFocus _ false.\\n\\tself contents: 'String: Shift-click on me to edit'! !\\n\\n\\n!StringMorph methodsFor: 'printing' stamp: 'efc 2/22/2003 21:35'!\\nfont: aFont \\n\\t\\\"Set the font my text will use. The emphasis remains unchanged.\\\"\\n\\n\\tfont _ aFont.\\n\\t^ self font: font emphasis: emphasis! !\\n\\n!StringMorph methodsFor: 'printing' stamp: 'jm 11/3/97 16:52'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream print: contents.\\n! !\\n\\n\\n!StringMorph methodsFor: '*MorphicExtras-accessing' stamp: 'sw 2/18/2003 02:55'!\\ngetCharacters\\n\\t\\\"obtain a string value from the receiver.\\\"\\n\\n\\t^ self contents! !\\n\\n!StringMorph methodsFor: '*MorphicExtras-accessing' stamp: 'sw 9/9/1999 18:09'!\\nhandsWithMeForKeyboardFocus\\n\\t| foc |\\n\\t\\\"Answer the hands that have me as their keyboard focus\\\"\\n\\n\\thasFocus ifFalse: [^ #()].\\n\\t^ self currentWorld hands select:\\n\\t\\t[:aHand | (foc _ aHand keyboardFocus) notNil and: [foc owner == self]]! !\\n\\n\\n!StringMorph methodsFor: '*MorphicExtras-printing'!\\nfullPrintOn: aStream\\n\\n\\taStream nextPutAll: '('.\\n\\tsuper fullPrintOn: aStream.\\n\\taStream nextPutAll: ') contents: '; print: contents! !\\n\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForClassAndMethodString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as an encoding of the form\\n\\t\\t<className> [ class ] <selector>\\\"\\n\\n\\t| aComment |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\tMessageSet parse: self contents asString toClassAndSelector:\\n\\t\\t[:aClass :aSelector |\\n\\t\\t\\t(aClass notNil and: [aSelector notNil]) ifTrue:\\n\\t\\t\\t\\t[aComment := aClass precodeCommentOrInheritedCommentFor: aSelector]].\\n\\t^ aComment\\n! !\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForLexiconString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as an encoding (used in Lexicons) of the form\\n\\t\\t<selector> <spaces> (<className>>)\\\"\\n\\n\\t| aComment contentsString aSelector aClassName |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\tcontentsString := self contents asString.\\n\\taSelector := contentsString upTo: $ .\\n\\taClassName := contentsString copyFrom: ((contentsString indexOf: $() + 1) to: ((contentsString indexOf: $)) - 1).\\n\\tMessageSet parse: (aClassName, ' dummy') toClassAndSelector:\\n\\t\\t[:cl :sel | cl ifNotNil:\\n\\t\\t\\t[aComment := cl precodeCommentOrInheritedCommentFor: aSelector]].\\n\\t^ aComment\\n! !\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForMethodString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as a method belonging to the currently-selected class of a browser tool.\\\"\\n\\n\\t| aWindow aCodeHolder aClass |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\taWindow := self ownerThatIsA: SystemWindow.\\n\\t(aWindow isNil or: [((aCodeHolder := aWindow model) isKindOf: CodeHolder) not])\\n\\t\\tifTrue:\\t[^ nil].\\n\\t((aClass := aCodeHolder selectedClassOrMetaClass) isNil or:\\n\\t\\t[(aClass includesSelector: contents asSymbol) not])\\n\\t\\t\\tifTrue: [^ nil].\\n\\t^ aClass precodeCommentOrInheritedCommentFor: contents asSymbol\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'sw 8/22/97 22:19'!\\ncontents: aString\\n\\t\\\" 'StringMorph contents: str' is faster than 'StringMorph new contents: str' \\\"\\n\\t^ self contents: aString font: nil! !\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'di 4/1/1999 17:15'!\\ncontents: aString font: aFont\\n\\t^ self basicNew initWithContents: aString font: aFont emphasis: 0! !\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'di 4/1/1999 17:15'!\\ncontents: aString font: aFont emphasis: emphasisCode\\n\\t^ self basicNew initWithContents: aString font: aFont emphasis: emphasisCode! !\\n\\n\\n!StringMorph class methodsFor: 'scripting' stamp: 'sw 5/6/1998 14:00'!\\nauthoringPrototype\\n\\t^ super authoringPrototype contents: 'String'! !\\n\\n\\n!StringMorph class methodsFor: 'testing' stamp: 'di 5/6/1998 21:07'!\\ntest\\n\\t\\\"Return a morph with lots of strings for testing display speed.\\\"\\n\\t| c |\\n\\tc _ AlignmentMorph newColumn.\\n\\tSystemOrganization categories do:\\n\\t\\t[:cat | c addMorph: (StringMorph new contents: cat)].\\n\\t^ c! !\\n\\n!StringMorph class methodsFor: 'testing' stamp: 'di 5/6/1998 21:08'!\\ntest2\\n\\t\\\"Return a morph with lots of strings for testing display speed.\\\"\\n\\t| c r |\\n\\tc _ AlignmentMorph newColumn.\\n\\tSystemOrganization categories reverseDo:\\n\\t\\t[:cat | c addMorph: (StringMorph new contents: cat)].\\n\\tr _ RectangleMorph new extent: c fullBounds extent.\\n\\tc submorphsDo: [:m | r addMorph: m].\\n\\t^ r\\n! !\\nObject subclass: #StringMorphAttributeScanner\\n\\tinstanceVariableNames: 'fontNumber textColor emphasis alignment actualFont indent kern'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!StringMorphAttributeScanner commentStamp: '<historical>' prior: 0!\\nA StringMorphAttributeScanner provides the interface of a CharacterScanner so that text attributes may be collected from a Text and used elsewhere, like in setting the attributes of a StringMorph.\\n!\\n]style[(2 195)cblack;,f3cblack;!\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:12'!\\nactualFont\\n\\t\\\"Answer the value of actualFont\\\"\\n\\n\\t^ actualFont ifNil: [ TextStyle defaultFont ]! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nalignment\\n\\t\\\"Answer the value of alignment\\\"\\n\\n\\t^ alignment! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nemphasis\\n\\t\\\"Answer the value of emphasis\\\"\\n\\n\\t^ emphasis! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:14'!\\nfont\\n\\t\\\"Answer the value of font\\\"\\n\\n\\t^self textStyle fontAt: self fontNumber! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:11'!\\nfontNumber\\n\\t\\\"Answer the value of font\\\"\\n\\n\\t^ fontNumber! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nindent\\n\\t\\\"Answer the value of indent\\\"\\n\\n\\t^ indent! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nkern\\n\\t\\\"Answer the value of kern\\\"\\n\\n\\t^ kern! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\ntextColor\\n\\t\\\"Answer the value of textColor\\\"\\n\\n\\t^ textColor! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:12'!\\ntextStyle\\n\\t^self actualFont textStyle ifNil: [ TextStyle default ]! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'initialize-release' stamp: 'nk 2/26/2004 13:10'!\\ninitialize\\n\\temphasis _ 0.\\n\\tindent _ 0.\\n\\tkern _ 0.\\n\\tfontNumber _ 1.\\n\\tactualFont _ TextStyle defaultFont! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:40'!\\naddEmphasis: anInteger\\n\\t\\\"Set the value of emphasis\\\"\\n\\n\\temphasis _ emphasis bitOr: anInteger! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:41'!\\naddKern: kernDelta\\n\\t\\\"Set the current kern amount.\\\"\\n\\tkern _ kern + kernDelta! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:37'!\\nindentationLevel: anInteger\\n\\t\\\"Set the value of indent\\\"\\n\\n\\tindent _ anInteger! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 13:09'!\\nsetActualFont: aFont\\n\\t\\\"Set the value of actualFont, from a TextFontReference\\\"\\n\\n\\tactualFont _ aFont.\\n\\taFont textStyle ifNotNilDo: [ :ts | fontNumber _ ts fontIndexOf: aFont ]! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:39'!\\nsetAlignment: aSymbol\\n\\t\\\"Set the value of alignment\\\"\\n\\n\\talignment _ aSymbol! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 13:10'!\\nsetFont: fontNum\\n\\t\\\"Set the value of font\\\"\\n\\n\\tfontNumber _ fontNum! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:34'!\\ntextColor: anObject\\n\\t\\\"Set the value of textColor\\\"\\n\\n\\ttextColor _ anObject! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'string morph' stamp: 'nk 2/26/2004 13:09'!\\ninitializeFromStringMorph: aStringMorph\\n\\t| style |\\n\\tactualFont _ aStringMorph font ifNil: [ TextStyle defaultFont ].\\n\\tstyle _ actualFont textStyle.\\n\\temphasis _ actualFont emphasis.\\n\\tfontNumber _ (style fontIndexOf: actualFont) ifNil: [ 1 ].\\n\\ttextColor _ aStringMorph color.\\n! !\\nTextMorph subclass: #StringMorphEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!StringMorphEditor commentStamp: '<historical>' prior: 0!\\nI am a textMorph used as a pop-up editor for StringMorphs. I present a yellow background and I go away when a CR is typed or when the user clicks elsewhere.!\\n\\n\\n!StringMorphEditor methodsFor: 'display' stamp: 'sw 4/20/2003 15:46'!\\ninitialize\\n\\n\\t\\\"Initialize the receiver. Give it a white background\\\"\\n\\n\\n\\n\\tsuper initialize.\\n\\n\\tself backgroundColor: Color white.\\n\\n\\tself color: Color red! !\\n\\n\\n!StringMorphEditor methodsFor: 'drawing' stamp: 'sw 9/7/1999 16:22'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds color: Color yellow muchLighter.\\n\\t^ super drawOn: aCanvas! !\\n\\n\\n!StringMorphEditor methodsFor: 'event handling' stamp: 'nk 6/12/2004 22:07'!\\nkeyStroke: evt\\n\\t\\\"This is hugely inefficient, but it seems to work, and it's unlikely it will ever need\\n\\tto be any more efficient -- it's only intended to edit single-line strings.\\\"\\n\\n\\t| char priorEditor newSel |\\n\\t(((char _ evt keyCharacter) = Character enter) or: [(char = Character cr)\\n\\t\\t\\tor: [char = $s and: [evt commandKeyPressed]]])\\n\\t\\t\\t\\tifTrue: [owner doneWithEdits; acceptContents.\\n\\tself flag: #arNote. \\\"Probably unnecessary\\\"\\n\\t\\t\\t\\t\\t\\tevt hand releaseKeyboardFocus.\\n\\t\\t\\t\\t\\t\\t^ self delete].\\n\\t\\n\\t(char = $l and: [evt commandKeyPressed]) ifTrue: \\\"cancel\\\"\\n\\t\\t[owner cancelEdits.\\n\\t\\tevt hand releaseKeyboardFocus.\\n\\t\\t^ self delete].\\n\\n\\tsuper keyStroke: evt.\\n\\towner interimContents: self contents asString.\\n\\tnewSel _ self editor selectionInterval.\\n\\n\\tpriorEditor _ self editor. \\\"Save editor state\\\"\\n\\tself releaseParagraph. \\\"Release paragraph so it will grow with selection.\\\"\\n\\tself paragraph. \\\"Re-instantiate to set new bounds\\\"\\n\\tself installEditorToReplace: priorEditor. \\\"restore editor state\\\"\\n\\tself editor selectFrom: newSel first to: newSel last.\\n! !\\n\\n!StringMorphEditor methodsFor: 'event handling' stamp: 'nk 1/23/2004 13:18'!\\nkeyboardFocusChange: aBoolean\\n\\t| hadFocus |\\n\\towner ifNil: [ ^self ].\\n\\thadFocus _ owner hasFocus.\\n\\tsuper keyboardFocusChange: aBoolean.\\n\\taBoolean ifFalse:\\n\\t\\t[hadFocus ifTrue:\\n\\t\\t\\t[owner lostFocusWithoutAccepting; doneWithEdits].\\n\\t\\t^ self delete]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringMorphEditor class\\n\\tinstanceVariableNames: ''!\\n\\n!StringMorphEditor class methodsFor: 'new-morph participation' stamp: 'kfr 5/1/2000 13:41'!\\nincludeInNewMorphMenu\\n\\t\\\"Not to be instantiated from the menu\\\"\\n\\t^ false! !\\nTileMorph subclass: #StringReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n\\n!StringReadoutTile methodsFor: 'accessing' stamp: 'sw 11/1/97 13:15'!\\nliteral: anObject\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last informTarget! !\\n\\n\\n!StringReadoutTile methodsFor: 'literal' stamp: 'sw 9/15/1999 15:14'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"like literal:width: but does not inform the target\\\"\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last setWidth: w.\\n\\tself updateLiteralLabel! !\\n\\n\\n!StringReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:01'!\\nbasicWidth\\n\\t^ 26! !\\n\\n\\n!StringReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 18:20'!\\nhandlesMouseDown: evt \\n\\t^ true! !\\n\\n!StringReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 23:38'!\\nmouseStillDown: evt \\n\\t(self labelMorph notNil\\n\\t\\t\\tand: [self labelMorph containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [^ self labelMorph mouseDown: evt].\\n\\t^ super mouseStillDown: evt! !\\nObjectSocket subclass: #StringSocket\\n\\tinstanceVariableNames: 'numStringsInNextArray stringsForNextArray nextStringSize files startTime stringCounter socketWriterProcess outputQueue bytesInOutputQueue extraUnsentBytes transmissionError readBuffer'\\n\\tclassVariableNames: 'MaxRatesSeen RecentSendHistory RunningSendCount'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n!StringSocket commentStamp: 'ls 8/4/2004 15:15' prior: 0!\\nThis is a socket which sends arrays of strings back and forth. This is less convenient than ObjectSockets, but it is more secure and it makes it easier to reason about updates to the protocol.\\n\\nAn array of strings is represented on the network as:\\n\\n\\t4-bytes\\t\\tnumber of strings in the array\\n\\t4-byte\\t\\tnumber of bytes in the first string\\n\\tn1-bytes\\t\\tcharacters in the first string\\n\\t4-bytes\\t\\tnumber of bytes in the second string\\n\\tn2-bytes\\tcharacters in the second string\\n\\t...\\n\\n!\\n\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ndestroy\\n\\n\\tsocketWriterProcess ifNotNil: [socketWriterProcess terminate. socketWriterProcess := nil].\\n\\toutputQueue := nil.\\n\\tbytesInOutputQueue := 0.\\n\\tsocket ifNotNil: [socket destroy. socket := nil.].\\n! !\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ninitialize: aSocket\\n\\n\\ttransmissionError := false.\\n\\tsuper initialize: aSocket.\\n\\toutputQueue := SharedQueue new.\\n\\textraUnsentBytes := bytesInOutputQueue := 0.\\n\\tsocketWriterProcess := [\\n\\t\\t[self transmitQueueNext] whileTrue.\\n\\t\\tsocketWriterProcess := nil.\\n\\t\\toutputQueue := nil.\\n\\t\\tbytesInOutputQueue := 0.\\n\\t] forkAt: Processor lowIOPriority.! !\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'yo 10/10/2005 18:47'!\\nreadBuffer\\n\\n\\t^ readBuffer ifNil: [readBuffer _ String new: 20000].\\n! !\\n\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'yo 10/10/2005 18:49'!\\naddToInBuf: aString\\n\\n\\t| newAlloc |\\n\\tnewAlloc _ aString size * 2 max: 80000.\\n\\tinBuf ifNil: [\\n\\t\\tinBuf _ String new: newAlloc.\\n\\t\\tinBufIndex _ 1.\\n\\t\\tinBufLastIndex _ 0.\\n\\t].\\n\\taString size > (inBuf size - inBufLastIndex) ifTrue: [\\n\\t\\tinBuf _ inBuf , (String new: newAlloc)\\n\\t].\\n\\tinBuf \\n\\t\\treplaceFrom: inBufLastIndex + 1 \\n\\t\\tto: inBufLastIndex + aString size\\n\\t\\twith: aString \\n\\t\\tstartingAt: 1.\\n\\tinBufLastIndex _ inBufLastIndex + aString size.\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\naddToOutBuf: arrayToWrite\\n\\n\\t| size newAlloc |\\n\\tsize := self spaceToEncode: arrayToWrite.\\n\\tnewAlloc := size * 2 max: 8000.\\t\\\"gives us room to grow\\\"\\n\\toutBuf ifNil: [\\n\\t\\toutBuf := String new: newAlloc.\\n\\t\\toutBufIndex := 1.\\n\\t].\\n\\toutBuf size - outBufIndex + 1 < size ifTrue: [\\n\\t\\toutBuf := outBuf , (String new: newAlloc).\\n\\t].\\n\\tCanvasEncoder at: 1 count: arrayToWrite size + 1.\\n\\toutBuf putInteger32: arrayToWrite size at: outBufIndex.\\n\\toutBufIndex := outBufIndex + 4.\\n\\tarrayToWrite do: [ :each |\\n\\t\\toutBuf putInteger32: each size at: outBufIndex.\\n\\t\\toutBufIndex := outBufIndex + 4.\\n\\t\\toutBuf \\n\\t\\t\\treplaceFrom: outBufIndex \\n\\t\\t\\tto: outBufIndex + each size - 1 \\n\\t\\t\\twith: each \\n\\t\\t\\tstartingAt: 1.\\n\\t\\toutBufIndex := outBufIndex + each size.\\n\\t].\\n\\t^size! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/13/2000 08:29'!\\nbacklog\\n\\n\\t^bytesInOutputQueue + extraUnsentBytes! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ngotSomething\\n\\n\\tnumStringsInNextArray ifNil: [^self tryForNumStringsInNextArray ].\\n\\tnumStringsInNextArray = 0 ifTrue: [\\n\\t\\tinObjects add: #().\\n\\t\\tnumStringsInNextArray := nil.\\n\\t\\t^true ].\\n\\tnextStringSize ifNil: [^ self tryForNextStringSize ].\\n\\t^self tryForString\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ninBufNext: anInteger\\n\\t\\n\\t| answer |\\n\\tanswer := inBuf copyFrom: inBufIndex to: inBufIndex + anInteger - 1.\\n\\tinBufIndex := inBufIndex + anInteger.\\n\\t^answer! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 7/20/2000 15:55'!\\ninBufSize\\n\\n\\tinBuf ifNil: [^0].\\n\\t^inBufLastIndex - inBufIndex + 1! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/14/2000 09:54'!\\nisConnected\\n\\n\\t^super isConnected and: [socketWriterProcess notNil]! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'md 2/24/2006 19:51'!\\nnextPut: anObject\\n\\n\\tsocketWriterProcess ifNil: [^self].\\n\\toutObjects addLast: anObject.\\n\\t\\\"return the argument - added by kwl\\\"\\n\\t^ anObject! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/14/2000 09:46'!\\nprocessIO\\n\\t\\\"do some as much network IO as possible\\\"\\n\\n\\tsocketWriterProcess ifNil: [^self].\\n\\tself processOutput.\\n\\tself processInput.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'yo 10/10/2005 18:47'!\\nprocessInput\\n\\t| totalReceived chunkOfData |\\n\\t\\\"do as much input as possible\\\"\\n\\n\\tself flag: #XXX. \\\"should have resource limits here--no more than X objects and Y bytes\\\"\\n\\n\\tchunkOfData _ socket receiveAvailableDataIntoBuffer: self readBuffer.\\n\\tself addToInBuf: chunkOfData.\\n\\ttotalReceived _ chunkOfData size.\\n\\n\\ttotalReceived > 0 ifTrue: [\\n\\t\\tNebraskaDebug at: #SendReceiveStats add: {'GET'. totalReceived}.\\n\\t].\\n\\n\\t[ self gotSomething ] whileTrue: [].\\t\\t\\\"decode as many string arrays as possible\\\"\\n\\n\\tself shrinkInBuf.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nprocessOutput\\n\\n\\t| arrayToWrite size bytesSent timeStartSending t itemsSent now timeSlot bucketAgeInMS bytesThisSlot |\\n\\n\\toutBufIndex := 1.\\n\\titemsSent := bytesSent := 0.\\n\\ttimeStartSending := Time millisecondClockValue.\\n\\t[outObjects isEmpty not and: [self isConnected]] whileTrue: [\\n\\t\\tarrayToWrite := outObjects removeFirst.\\n\\t\\tsize := self addToOutBuf: arrayToWrite.\\n\\t\\tbytesSent := bytesSent + size.\\n\\t\\titemsSent := itemsSent + 1.\\n\\t\\toutBufIndex > 10000 ifTrue: [self queueOutBufContents].\\n\\t].\\n\\toutBufIndex > 1 ifTrue: [self queueOutBufContents].\\n\\tbytesSent > 0 ifTrue: [\\n\\t\\tMaxRatesSeen ifNil: [MaxRatesSeen := Dictionary new].\\n\\t\\tnow := Time millisecondClockValue.\\n\\t\\tt := now - timeStartSending.\\n\\t\\ttimeSlot := now // 10000.\\t\\\"ten second buckets\\\"\\n\\t\\tbucketAgeInMS := now \\\\\\\\ 10.\\n\\t\\tbytesThisSlot := (MaxRatesSeen at: timeSlot ifAbsent: [0]) + bytesSent.\\n\\t\\tMaxRatesSeen \\n\\t\\t\\tat: timeSlot \\n\\t\\t\\tput: bytesThisSlot.\\n\\t\\tNebraskaDebug \\n\\t\\t\\tat: #SendReceiveStats \\n\\t\\t\\tadd: {'put'. bytesSent. t. itemsSent. bytesThisSlot // (bucketAgeInMS max: 100)}.\\n\\t].\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\npurgeOutputQueue\\n\\n\\tbytesInOutputQueue := 0.\\n\\t[outputQueue nextOrNil notNil] whileTrue.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nqueueOutBufContents\\n\\n\\tbytesInOutputQueue := bytesInOutputQueue + outBufIndex - 1.\\n\\toutputQueue nextPut: {outBuf. outBufIndex - 1}.\\n\\tNebraskaDebug at: #queuedbufferSizes add: {outBufIndex - 1}.\\n\\toutBufIndex := 1.\\n\\toutBuf := String new: 11000.\\n\\t\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nsendDataCautiously: aStringOrByteArray bytesToSend: bytesToSend\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent. Try not to send too much at once since this seemed to cause problems talking to a port on the same machine\\\"\\n\\n\\t| bytesSent count |\\n\\n\\tbytesSent := 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\textraUnsentBytes := bytesToSend - bytesSent.\\n\\t\\tcount := socket \\n\\t\\t\\tsendSomeData: aStringOrByteArray \\n\\t\\t\\tstartIndex: bytesSent + 1 \\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 6000).\\n\\t\\tbytesSent := bytesSent + count.\\n\\t\\t(Delay forMilliseconds: 1) wait.\\n\\t].\\n\\textraUnsentBytes := 0.\\n\\t^ bytesSent\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nshrinkInBuf\\n\\n\\tinBuf ifNil: [^self].\\n\\tinBufLastIndex < inBufIndex ifTrue: [\\n\\t\\tinBufLastIndex := 0.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBuf size > 20000 ifTrue: [inBuf := nil].\\t\\\"if really big, kill it\\\"\\n\\t\\t^self\\n\\t].\\n\\tinBuf := inBuf copyFrom: inBufIndex to: inBufLastIndex.\\n\\tinBufLastIndex := inBuf size.\\n\\tinBufIndex := 1.\\n\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'ls 4/25/2000 18:36'!\\nspaceToEncode: anArray\\n\\t\\\"return the number of characters needed to encode the given string array\\\"\\n\\t^anArray inject: 4 into: [ :sum :array |\\n\\t\\tsum + (array size + 4) ].! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntransmitQueueNext\\n\\n\\t| bufTuple |\\n\\n\\tbufTuple := outputQueue next.\\n\\tbytesInOutputQueue := bytesInOutputQueue - bufTuple second max: 0.\\n\\t[\\n\\t\\tself \\n\\t\\t\\tsendDataCautiously: bufTuple first \\n\\t\\t\\tbytesToSend: bufTuple second.\\n\\t]\\n\\t\\ton: Error\\n\\t\\tdo: [ :ex |\\n\\t\\t\\ttransmissionError := true.\\n\\t\\t].\\n\\t^transmissionError not\\n\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForNextStringSize\\n\\t\\\"grab the size of the next string, if it's available\\\"\\n\\n\\tself inBufSize >= 4 ifFalse: [^false].\\n\\n\\tnextStringSize := inBuf getInteger32: inBufIndex.\\n\\t\\\"nextStringSize > 100000 ifTrue: [self barf].\\\"\\n\\tinBufIndex := inBufIndex + 4.\\n\\t\\n\\tnextStringSize < 0 ifTrue: [\\n\\t\\tsocket disconnect.\\n\\t\\t^false ].\\n\\t\\n\\t^true\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForNumStringsInNextArray\\n\\t\\\"input numStringsInNextARray, if 4 bytes are available\\\"\\n\\n\\tself inBufSize >= 4 ifFalse: [^false].\\n\\n\\tnumStringsInNextArray := inBuf getInteger32: inBufIndex.\\n\\t\\\"(numStringsInNextArray > 100 or: [numStringsInNextArray < 1]) ifTrue: [self barf].\\\"\\n\\tinBufIndex := inBufIndex + 4.\\n\\n\\tnumStringsInNextArray < 0 ifTrue: [\\n\\t\\tsocket disconnect.\\n\\t\\t^false ].\\n\\t\\n\\tstringsForNextArray := Array new: numStringsInNextArray.\\n\\tstringCounter := 0.\\n\\tnextStringSize := nil. \\n\\t^true! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForString\\n\\t\\\"try to grab an actual string\\\"\\n\\n\\tself inBufSize >= nextStringSize ifFalse: [^false].\\n\\n\\tstringsForNextArray \\n\\t\\tat: (stringCounter := stringCounter + 1)\\n\\t\\tput: (self inBufNext: nextStringSize) asString.\\n\\n\\tstringCounter = numStringsInNextArray ifTrue: [\\t\\\"we have finished another array!!\\\"\\n\\t\\tinObjects addLast: stringsForNextArray.\\n\\t\\tstringCounter := stringsForNextArray := numStringsInNextArray := nextStringSize := nil.\\n\\t] ifFalse: [\\t\\\"still need more strings for this array\\\"\\n\\t\\tnextStringSize := nil.\\n\\t].\\n\\n\\t^true\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nclearRatesSeen\\n\\\"\\nStringSocket clearRatesSeen\\n\\\"\\n\\tMaxRatesSeen := nil ! !\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ncompareFiles\\n\\\"\\nStringSocket compareFiles\\n\\\"\\n\\t| data1 data2 |\\n\\n\\tdata1 := (FileStream fileNamed: 'Macintosh HD:bob:nebraska test:58984048.1')\\n\\t\\t\\tcontentsOfEntireFile.\\n\\tdata2 := (FileStream fileNamed: 'BobsG3:squeak:dsqueak:DSqueak2.7 folder:58795431.3')\\n\\t\\t\\tcontentsOfEntireFile.\\n\\t1 to: (data1 size min: data2 size) do: [ :i |\\n\\t\\t(data1 at: i) = (data2 at: i) ifFalse: [self halt].\\n\\t].\\n! !\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowRatesSeen\\n\\\"\\nStringSocket showRatesSeen\\n\\\"\\n\\t| answer |\\n\\n\\tMaxRatesSeen ifNil: [^Beeper beep].\\n\\tanswer := WriteStream on: String new.\\n\\tMaxRatesSeen keys asSortedCollection do: [ :key |\\n\\t\\tanswer nextPutAll: key printString,' ',((MaxRatesSeen at: key) // 10000) printString; cr\\n\\t].\\n\\tStringHolder new contents: answer contents; openLabel: 'send rates at 10 second intervals'.! !\\nTestCase subclass: #StringSocketTestCase\\n\\tinstanceVariableNames: 'socket1 socket2 end1 end2'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\nsetUp\\n\\t\\\"it would be nice to have an in-image loopback socket, so that the tests do not need the underlying platform's sockets to behave nicely\\\"\\n\\tsocket1 := Socket newTCP.\\n\\tsocket2 := Socket newTCP.\\n\\t\\n\\tsocket1 listenOn: 9999.\\n\\tsocket2 connectTo: (NetNameResolver localHostAddress) port: 9999.\\n\\n\\tsocket1 waitForConnectionFor: 60.\\t\\n\\tsocket2 waitForConnectionFor: 60.\\n\\t\\n\\tend1 := StringSocket on: socket1.\\n\\tend2 := StringSocket on: socket2.\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'ls 8/4/2004 15:22'!\\ntearDown\\n\\tend1 destroy.\\n\\tend2 destroy.\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'ls 8/4/2004 15:21'!\\ntestBasics\\n\\tend1 nextPut: #().\\n\\tend1 nextPut: #('').\\n\\tend1 nextPut: #('hello' 'world').\\n\\tend1 processIO.\\n\\t\\n\\tend2 processIO.\\n\\n\\tself should: [ end2 next = #() ].\\n\\tself should: [ end2 next = #('') ].\\n\\tself should: [ end2 next = #('hello' 'world') ].\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\ntestBogusInput1\\n\\t| negString |\\n\\tnegString := String new: 4.\\n\\tnegString putInteger32: -10 at: 1.\\n\\tsocket1 sendData: negString.\\n\\tend2 processIO.\\n\\t\\n\\tself should: [ end2 isConnected not ].\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\ntestBogusInput2\\n\\t| bogoString |\\n\\tbogoString := String new: 8.\\n\\tbogoString putInteger32: 2 at: 1.\\n\\tbogoString putInteger32: -10 at: 5.\\n\\tsocket1 sendData: bogoString.\\n\\tend2 processIO.\\n\\t\\n\\tself should: [ end2 isConnected not ].\\n\\t! !\\nClassTestCase subclass: #StringTest\\n\\tinstanceVariableNames: 'string'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Text'!\\n!StringTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class String. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!StringTest methodsFor: 'initialize-release' stamp: 'md 4/18/2003 10:00'!\\nsetUp\\n\\tstring := 'Hi, I am a String'! !\\n\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy01\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test\\\"'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:20'!\\ntestFindTokensEscapedBy02\\n\\n\\t| tokens |\\n\\tstring := ''.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens isEmpty! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy03\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 4! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy04\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a\\\",\\\" test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy05\\n\\n\\t| tokens |\\n\\tstring := 'this, /is, a\\\",\\\" test/'.\\n\\ttokens := string findTokens: ',#' escapedBy: '\\\"/'.\\n\\tself assert: tokens size = 2.\\n\\tself assert: tokens first = 'this'.\\n\\tself assert: tokens second = ' is, a\\\",\\\" test'.! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy06\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy07\\n\\n\\t| tokens |\\n\\tstring := 'a:b::c'.\\n\\ttokens := string findTokens: ':' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 4.\\n\\tself assert: tokens first = 'a'.\\n\\tself assert: tokens second = 'b'.\\n\\tself assert: tokens third = ''.\\n\\tself assert: tokens fourth = 'c'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy08\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ##a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 4.\\n\\tself assert: tokens third = ' a'.\\n\\tself assert: tokens fourth = ' test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy09\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ###a, test#'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' #a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy10\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ###a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' #a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy11\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"\\\"\\\"a, test\\\"'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' \\\"a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy12\\n\\n\\t| tokens |\\n\\tstring := 'one, two# three; four. five'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 5.\\n\\tself assert: tokens third = ' three'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy13\\n\\n\\t| tokens |\\n\\tstring := 'one, two# three; four. five'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: nil.\\n\\tself assert: tokens size == 5.\\n\\tself assert: tokens third = ' three'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy14\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: '\\\"&'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens second = ' two# three'.\\n\\tself assert: tokens third = ' four. five'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy15\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: nil escapedBy: '\\\"&'.\\n\\tself assert: tokens size = 1.\\n\\tself assert: tokens first = 'one, two# three; four. five'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy16\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: nil escapedBy: nil.\\n\\tself assert: tokens size = 1.\\n\\tself assert: tokens first = string! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy21\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test\\\"'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy22\\n\\n\\t| tokens |\\n\\tstring := ''.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size = 0! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy23\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a, test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 4! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy24\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a\\\",\\\" test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy25\\n\\n\\t| tokens |\\n\\tstring := 'this, /is, a\\\",\\\" test/'.\\n\\ttokens := string findTokens: $, escapedBy: $/.\\n\\tself assert: tokens size = 2.\\n\\tself assert: tokens first = 'this'.\\n\\tself assert: tokens second = ' is, a\\\",\\\" test'.! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy26\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n\\n!StringTest methodsFor: 'tests - accessing' stamp: 'sd 6/5/2005 09:27'!\\ntestAt\\n\\n\\tself assert: (string at: 1) = $H.! !\\n\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:26'!\\ntestAsInteger\\n\\n\\tself assert: '1796exportFixes-tkMX' asInteger = 1796.\\n\\tself assert: 'donald' asInteger isNil.\\n\\tself assert: 'abc234def567' asInteger = 234.\\n\\tself assert: '-94' asInteger = -94.\\n\\tself assert: 'foo-bar-92' asInteger = -92! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestAsSmalltalkComment\\n\\n\\t| exampleStrings |\\n\\texampleStrings := #(\\n\\t\\t''\\n\\t\\t' '\\n\\t\\t'\\\"'\\n\\t\\t'\\\"\\\"'\\n\\t\\t'\\\"\\\"\\\"'\\n\\t\\t'abc\\\"abc'\\n\\t\\t'abc\\\"\\\"abc'\\n\\t\\t'abc\\\"hello\\\"abc'\\n\\t\\t'abc\\\"'\\n\\t\\t'\\\"abc' ).\\n\\n\\t\\\"check that the result of scanning the comment is empty\\\"\\n\\texampleStrings do: [ :s |\\n\\t\\t| tokens |\\n\\t\\ttokens := Scanner new scanTokens: s asSmalltalkComment.\\n\\t\\tself assert: (tokens isEmpty) ].\\n\\n\\t\\\"check that the result has the same non-quote characters as the original\\\"\\n\\texampleStrings do: [ :s |\\n\\t\\tself assert: ( (s copyWithout: $\\\") = (s asSmalltalkComment copyWithout: $\\\"))].\\n\\n\\t\\\"finnaly, test for some common kinds of inputs\\\"\\n\\tself assert: ( 'abc' asSmalltalkComment = '\\\"abc\\\"').\\n\\tself assert: ( 'abc\\\"abc' asSmalltalkComment = '\\\"abc\\\"\\\"abc\\\"').\\n\\tself assert: ('abc\\\"\\\"abc' asSmalltalkComment = '\\\"abc\\\"\\\"abc\\\"' ).\\n\\t\\t! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestCapitalized\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := 'MElViN'.\\n\\tlc := 'mElViN'.\\n\\tempty := ' '.\\n\\tself assert: lc capitalized = uc.\\n\\tself assert: uc capitalized = uc.\\n\\t\\\"the string gets copied\\\"\\n\\tself deny: uc capitalized == uc.\\n\\tself deny: empty capitalized == empty.! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'ky 7/8/2006 15:28'!\\ntestUnescapePercents\\n\\tself assert: '' unescapePercents = ''.\\n\\tself assert: 'x' unescapePercents = 'x'.\\n\\n\\tself assert: '+' unescapePercents = ' '.\\n\\tself assert: 'x+' unescapePercents = 'x '.\\n\\tself assert: '+x' unescapePercents = ' x'.\\n\\tself assert: 'x+x' unescapePercents = 'x x'.\\n\\n\\tself assert: '%' unescapePercents = '%'.\\n\\tself assert: '%3' unescapePercents = '%3'.\\n\\tself assert: '%3C' unescapePercents = '<'.\\n\\t\\n\\tself assert: '%3Cx%3E4%3C%2Fx%3E' unescapePercents = '<x>4</x>'.\\n\\t\\n\\tself assert: '!!@#$%25%5E&*()%7B%7D%5B%5D=:/;?+''%22' unescapePercents = '!!@#$%^&*(){}[]=:/;? ''\\\"'.\\n\\tself assert: '!!%40%23%24%25%5E%26*()%7B%7D%5B%5D%3D%3A%2F%3B%3F%2B''%22' unescapePercents = '!!@#$%^&*(){}[]=:/;?+''\\\"'.\\n\\tself assert: '%21@%23%24%25%5E%26*%28%29%7B%7D%5B%5D%3D%3A/%3B%3F+%27%22' unescapePercents = '!!@#$%^&*(){}[]=:/;? ''\\\"'! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'ky 7/8/2006 18:01'!\\ntestUnescapePercentsWithTextEncoding\\n\\t| leading kataTe kataSu kataTo |\\n\\tleading := JapaneseEnvironment leadingChar.\\n\\t\\\"Katakana letter Te\\\"\\n\\tkataTe := (Character leadingChar: leading code: 12486) asString.\\n\\t\\\"Katakana letter Su\\\"\\n\\tkataSu := (Character leadingChar: leading code: 12473) asString.\\n\\t\\\"Katakana letter To\\\"\\n\\tkataTo := (Character leadingChar: leading code: 12488) asString.\\n\\tself assert: ('%83e%83X%83g' unescapePercentsWithTextEncoding: 'shift_jis')\\n\\t\\t\\t= (kataTe , kataSu , kataTo).\\n\\tself assert: ('%83e%83X%83g%20and%20%83e%83X%83g' unescapePercentsWithTextEncoding: 'shift_jis')\\n\\t\\t\\t= (kataTe , kataSu , kataTo , ' and ' , kataTe , kataSu , kataTo)! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestWithFirstCharacterDownshifted\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := 'MElViN'.\\n\\tlc := 'mElViN'.\\n\\tempty := ' '.\\n\\tself assert: uc withFirstCharacterDownshifted = lc.\\n\\tself assert: lc withFirstCharacterDownshifted = lc.\\n\\t\\\"the string gets copied\\\"\\n\\tself deny: lc withFirstCharacterDownshifted == lc.\\n\\tself deny: empty withFirstCharacterDownshifted == empty.! !\\n\\n\\n!StringTest methodsFor: 'as yet unclassified' stamp: 'md 3/16/2006 22:12'!\\ntestEquality\\n\\n\\tself assert: 'abc' = 'abc' asWideString.\\n\\tself assert: 'abc' asWideString = 'abc'.\\n\\tself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString ~= 'a000' asWideString).\\n\\tself assert: ('a000' asWideString ~= (ByteArray with: 97 with: 0 with: 0 with: 0) asString).\\n\\n\\tself assert: ('abc' sameAs: 'aBc' asWideString).\\n\\tself assert: ('aBc' asWideString sameAs: 'abc').\\n\\tself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString \\n\\t\\t\\t\\t\\t\\tsameAs: 'Abcd' asWideString) not.\\n\\tself assert: ('a000' asWideString sameAs: \\n\\t\\t\\t\\t\\t(ByteArray with: 97 with: 0 with: 0 with: 0) asString) not.! !\\n\\n\\n!StringTest methodsFor: 'test-comparing' stamp: 'lr 7/7/2006 11:32'!\\ntestComparing\\n\\tself assert: 'foo' < 'foo:'.\\n\\tself assert: 'foo' < 'fooBar'.\\n\\tself assert: 'foo' <= 'foo:'.\\n\\tself assert: 'foo' <= 'fooBar'.\\n\\tself assert: 'foo:' > 'foo'.\\n\\tself assert: 'fooBar' > 'foo'.\\n\\tself assert: 'foo:' >= 'foo'.\\n\\tself assert: 'fooBar' >= 'foo'! !\\n\\n\\n!StringTest methodsFor: 'testing - converting' stamp: 'KR 06/24/2005 11:21'!\\ntestPercentEncodingJa\\n\\t| leading hiraA hiraO hiraAO encodedHiraA encodedHiraO encodedHiraAO |\\n\\n \\\"Make Japanese String from unicode. see http://www.unicode.org/charts/PDF/U3040.pdf\\\"\\n leading _ JapaneseEnvironment leadingChar.\\n\\thiraA _ (Character leadingChar: leading code: 16r3042) asString. \\\"HIRAGANA LETTER A\\\"\\n\\thiraO _ (Character leadingChar: leading code: 16r304A) asString. \\\"HIRAGANA LETTER O\\\"\\n\\thiraAO _ hiraA, hiraO.\\n\\n\\t\\\"Percent Encoded Japanese String\\\"\\n\\tencodedHiraA _ hiraA encodeForHTTP.\\n\\tself assert: encodedHiraA = '%E3%81%82'.\\n\\tencodedHiraO _ hiraO encodeForHTTP.\\n\\tself assert: encodedHiraO = '%E3%81%8A'.\\n\\tencodedHiraAO _ hiraAO encodeForHTTP.\\n\\tself assert: encodedHiraAO = '%E3%81%82%E3%81%8A'.\\n\\n \\\"without percent encoded string\\\"\\n\\tself assert: '' unescapePercents = ''.\\n\\tself assert: 'abc' unescapePercents = 'abc'.\\t\\\"latin1 character\\\"\\n\\tself assert: hiraAO unescapePercents = hiraAO. \\\"multibyte character\\\"\\n\\n\\t\\\"encoded latin1 string\\\"\\n\\tself assert: '%61' unescapePercents = 'a'.\\n\\tself assert: '%61%62%63' unescapePercents = 'abc'.\\n\\n\\t\\\"encoded multibyte string\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: encodedHiraA unescapePercents = hiraA.\\n\\t\\tself assert: encodedHiraAO unescapePercents = hiraAO].\\n\\n\\t\\\"mixed string\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: (encodedHiraAO,'a') unescapePercents = (hiraAO, 'a').\\n\\t\\tself assert: ('a', encodedHiraA) unescapePercents = ('a', hiraA).\\n\\t\\tself assert: ('a', encodedHiraA, 'b') unescapePercents = ('a', hiraA, 'b').\\n\\t\\tself assert: ('a', encodedHiraA, 'b', encodedHiraO) unescapePercents = ('a', hiraA, 'b', hiraO).\\n\\t\\tself assert: (encodedHiraA, encodedHiraO, 'b', encodedHiraA) unescapePercents = (hiraA, hiraO, 'b', hiraA)].\\n\\n\\n\\t\\\"for Seaside\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: (encodedHiraA, '+', encodedHiraO) unescapePercents = (hiraA, ' ', hiraO)].\\n\\n! !\\n\\n\\n!StringTest methodsFor: 'tests - indexOf' stamp: 'nice 5/9/2006 23:55'!\\ntestIndexOf\\n\\t\\n\\t\\\"test for http://bugs.impara.de/view.php?id=3574\\\"\\n\\tself assert: ('abc-' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 4.\\n\\tself assert: ('ab7' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 3.\\n\\tself assert: ('a2c' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 2.\\n\\tself assert: ('3bc' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 1.\\n\\tself assert: ('abc' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 0.\\n\\t\\n\\t\\\"extension to wide characters\\\"\\n\\tself assert: ((String with: 803 asCharacter with: 811 asCharacter) indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: 812 asCharacter))) = 2.\\n\\t\\n\\tself assert: ('abc' indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: 812 asCharacter))) = 0.\\n\\t\\n\\tself assert: ('abc' indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: $c))) = 3.! !\\nDataType subclass: #StringType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n\\n!StringType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ 'abc'! !\\n\\n\\n!StringType methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\t| aMethodCategory aMethodInterface |\\n\\tsuper initialize.\\n\\tself vocabularyName: #String.\\n\\n#((accessing \\t\\t\\t'The basic info'\\n\\t\\t(at: at:put: size endsWithDigit findString: findTokens: includesSubString: indexOf: indexOf:startingAt: indexOf:startingAt:ifAbsent: lineCorrespondingToIndex: lineCount lineNumber: startsWithDigit numArgs))\\n(#'more accessing' \\t\\t'More basic info'\\n\\t\\t(allButFirst allButFirst: allButLast allButLast: at:ifAbsent: atAllPut: atPin: atRandom: atWrap: atWrap:put: fifth first first: fourth from:to:put: last last: lastIndexOf: lastIndexOf:ifAbsent: middle replaceAll:with: replaceFrom:to:with: replaceFrom:to:with:startingAt: second sixth third))\\n(comparing\\t\\t\\t\\t'Determining which comes first alphabeticly'\\n\\t\\t(< <= = > >= beginsWith: endsWith: endsWithAnyOf: howManyMatch: match:))\\n(testing \\t\\t\\t\\t'Testing'\\n\\t\\t(includes: isEmpty ifNil: ifNotNil: isAllDigits isAllSeparators isString lastSpacePosition))\\n(converting \\t\\t\\t'Converting it to another form'\\n\\t\\t(asCharacter asDate asInteger asLowercase asNumber asString asStringOrText asSymbol asText asTime asUppercase asUrl capitalized keywords numericSuffix romanNumber reversed splitInteger surroundedBySingleQuotes withBlanksTrimmed withSeparatorsCompacted withoutTrailingBlanks withoutTrailingDigits asSortedCollection))\\n(copying \\t\\t\\t\\t'Make another one like me'\\n\\t\\t(copy copyFrom:to: copyUpTo: copyUpToLast: shuffled))\\n(enumerating\\t\\t'Passing over the letters'\\n\\t\\t(collect: collectWithIndex: do: from:to:do: reverseDo: select: withIndexDo: detect: detect:ifNone:))\\n) do: [:item | \\n\\t\\t\\taMethodCategory := ElementCategory new categoryName: item first.\\n\\t\\t\\taMethodCategory documentation: item second.\\n\\t\\t\\titem third do:\\n\\t\\t\\t\\t[:aSelector | \\n\\t\\t\\t\\t\\taMethodInterface := MethodInterface new initializeFor: aSelector.\\n\\t\\t\\t\\t\\tself atKey: aSelector putMethodInterface: aMethodInterface.\\n\\t\\t\\t\\t\\taMethodCategory elementAt: aSelector put: aMethodInterface].\\n\\t\\t\\tself addCategory: aMethodCategory].\\n! !\\n\\n\\n!StringType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(0.0 0.0 1.0)\\t! !\\n\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'yo 3/14/2005 21:27'!\\ndefaultArgumentTile\\n \\\"Answer a tile to represent the type\\\"\\n\\n ^ 'abc' translated newTileMorphRepresentative typeColor: self typeColor! !\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nsetFormatForDisplayer: aDisplayer\\n\\t\\\"Set up the displayer to have the right format characteristics\\\"\\n\\n\\taDisplayer useStringFormat\\n\\t! !\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nwantsArrowsOnTiles\\n\\t\\\"Answer whether this data type wants up/down arrows on tiles representing its values\\\"\\n\\n\\t^ false! !\\nMorph subclass: #SubpaneDividerMorph\\n\\tinstanceVariableNames: 'resizingEdge'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Windows'!\\n!SubpaneDividerMorph commentStamp: '<historical>' prior: 0!\\nA morph which presents a visible separator between subpanes of a SystemWindow which have zero edgeWidth. Subpanes are submorphs of a SystemWindow's paneMorphs.\\n\\nA SubpaneDividerMorph may also initiate reframe handles for the subpanes. For resizing, it is expected that the main paneMorph has a ProportionalLayout LayoutPolicy, and that the subpanes to be resized have LayoutFrames with equal topFractions and bottomFractions, but different topOffsets and bottomOffsets. It is the offsets that are changed, and the change is propagated through sibling morphs up to the first resizable morph (with different nominal frame fractions).\\n\\nThe direction of propagation is determined by the value of resizingEdge, which is one of: nil (for non-adjustible subpane divisions), #bottom or #top (which acts a though the divider is the corresponding edge of the subpane directly above or below it). Does not currently support #left or #right binding, or subpanes in a TableLayout.\\n!\\n\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'sw 5/18/2001 11:27'!\\nborderColor\\n\\t\\\"I behave like a border for the purpose of browser beautifying, so I obey this protocol, to advantage\\\"\\n\\n\\t^ self color! !\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'sw 5/18/2001 11:26'!\\nborderColor: aColor\\n\\t\\\"I behave like a border for the purpose of browser beautifying, so I obey this protocol, to advantage\\\"\\n\\n\\tself color: aColor! !\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'JW 2/3/2001 09:39'!\\nresizingEdge\\n\\n\\t^resizingEdge\\n! !\\n\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:53'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:26'!\\nfirstEnter: evt\\n\\t\\\"The first time this divider is activated, find its window and redirect further interaction there.\\\"\\n\\t| window |\\n\\n\\twindow := self firstOwnerSuchThat: [:m | m respondsTo: #secondaryPaneTransition:divider:].\\n\\twindow ifNil: [ self suspendEventHandler. ^ self ]. \\\"not working out\\\"\\n\\twindow secondaryPaneTransition: evt divider: self.\\n\\tself on: #mouseEnter send: #secondaryPaneTransition:divider: to: window.\\n! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:07'!\\nhorizontal\\n\\n\\tself hResizing: #spaceFill.! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:53'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself extent: 1 @ 1! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:12'!\\nresizingEdge: edgeSymbol\\n\\n\\t(#(top bottom) includes: edgeSymbol) ifFalse:\\n\\t\\t[ self error: 'resizingEdge must be #top or #bottom' ].\\n\\tresizingEdge := edgeSymbol.\\n\\tself on: #mouseEnter send: #firstEnter: to: self.\\n! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:07'!\\nvertical\\n\\n\\tself vResizing: #spaceFill.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSubpaneDividerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:35'!\\nforBottomEdge\\n\\t^self new horizontal resizingEdge: #bottom! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:35'!\\nforTopEdge\\n\\t^self new horizontal resizingEdge: #top! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:31'!\\nhorizontal\\n\\t^self new horizontal! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:31'!\\nvertical\\n\\t^self new vertical! !\\nObject subclass: #SunAudioFileWriter\\n\\tinstanceVariableNames: 'stream headerStart'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SunAudioFileWriter commentStamp: '<historical>' prior: 0!\\nI encode monophonic sampled sounds in Sun audio (.au) file format. Sun audio files have a very simple format but can store both compressed and uncompressed sample data. I can write this format either directly into a file or onto any writable binary stream.\\n!\\n\\n\\n!SunAudioFileWriter methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsetStream: aBinaryStream\\n\\t\\\"Initialize myself for writing on the given stream.\\\"\\n\\n\\tstream := aBinaryStream.\\n\\theaderStart := aBinaryStream position.\\n! !\\n\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 18:02'!\\nappendBytes: aByteArray\\n\\t\\\"Append the given sample data to my stream.\\\"\\n\\n\\tstream nextPutAll: aByteArray.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nappendSamples: aSoundBuffer\\n\\t\\\"Append the given SoundBuffer to my stream.\\\"\\n\\n\\t| swapBytes s |\\n\\t(stream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\t\\\"optimization: write sound buffer directly to file\\\"\\n\\t\\tswapBytes := SmalltalkImage current isLittleEndian.\\n\\t\\tswapBytes ifTrue: [aSoundBuffer reverseEndianness]. \\\"make big endian\\\"\\n\\t\\tstream next: (aSoundBuffer size // 2) putAll: aSoundBuffer startingAt: 1. \\\"size in words\\\"\\n\\t\\tswapBytes ifTrue: [aSoundBuffer reverseEndianness]. \\\"revert to little endian\\\"\\n\\t\\t^ self].\\n\\n\\t\\\"for non-file streams:\\\"\\n\\ts := WriteStream on: (ByteArray new: 2 * aSoundBuffer monoSampleCount).\\n\\t1 to: aSoundBuffer monoSampleCount do: [:i | s int16: (aSoundBuffer at: i)].\\n\\tself appendBytes: s contents.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 22:09'!\\ncloseFile\\n\\t\\\"Update the Sun audio file header to reflect the final size of the sound data. If my stream is a file stream, close it and, on a Macintosh, set the file type and creator to that used by SoundApp for Sun Audio files. (This does nothing on other platforms.)\\\"\\n\\n\\tself ensureOpen.\\n\\tself updateHeaderDataSize.\\n\\t(stream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\tstream close.\\n\\t\\tFileDirectory default setMacFileNamed: stream name type: 'ULAW' creator: 'SCPL'].\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'sd 1/30/2004 15:23'!\\nensureOpen\\n\\t\\\"Ensure that my stream is open.\\\"\\n\\n\\tstream closed ifTrue: [stream reopen; binary].\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nupdateHeaderDataSize\\n\\t\\\"Update the Sun audio file header to reflect the final size of the sound data.\\\"\\n\\n\\t| byteCount |\\n\\tbyteCount := stream position - (headerStart + 24).\\n\\tstream position: headerStart + 8.\\n\\tstream uint32: byteCount.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 17:55'!\\nwriteHeaderSamplingRate: samplingRate\\n\\t\\\"Write a Sun audio file header for 16-bit linear format.\\\"\\n\\n\\tself writeHeaderSamplingRate: samplingRate format: 3.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 22:10'!\\nwriteHeaderSamplingRate: samplingRate format: audioFormat\\n\\t\\\"Write a Sun audio file header for the given sampling rate and format. Currently, only monophonic files are supported.\\\"\\n\\n\\tself ensureOpen.\\n\\tstream position: headerStart.\\n\\tstream nextPutAll: '.snd' asByteArray.\\n\\tstream uint32: 24.\\t\\\"header size in bytes\\\"\\n\\tstream uint32: 0.\\t\\\"sample data size in bytes; fill in later\\\"\\n\\tstream uint32: audioFormat.\\n\\tstream uint32: samplingRate truncated.\\n\\tstream uint32: 1.\\t\\\"channel count\\\"\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSunAudioFileWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!SunAudioFileWriter class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me on a newly created file with the given name.\\\"\\n\\n\\t| file |\\n\\tfile := (FileStream newFileNamed: fileName) binary.\\n\\t^ self new setStream: file\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'instance creation' stamp: 'jm 11/16/2001 17:50'!\\nonStream: aBinaryStream\\n\\t\\\"Answer an instance of me on the given binary stream.\\\"\\n\\n\\t^ self new setStream: aBinaryStream\\n! !\\n\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'jm 11/21/2001 15:42'!\\ncodecForFormatCode: formatCode\\n\\t\\\"Answer the codec for the given Sun audio file format number.\\\"\\n\\n\\tformatCode = 1 ifTrue: [^ MuLawCodec new].\\n\\tformatCode = 3 ifTrue: [^ nil]. \\\"uncompressed\\\"\\n\\tformatCode = 23 ifTrue: [^ ADPCMCodec newBitsPerSample: 4].\\n\\tformatCode = 25 ifTrue: [^ ADPCMCodec newBitsPerSample: 3].\\n\\tformatCode = 26 ifTrue: [^ ADPCMCodec newBitsPerSample: 5].\\n\\tformatCode = 610 ifTrue: [^ GSMCodec new].\\n\\tself error: 'unsupported Sun audio format'\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nformatCodeForCompressionType: aString\\n\\t\\\"Answer the Sun audio file format number for the given compression type name.\\\"\\n\\n\\t| lowercase |\\n\\tlowercase := aString asLowercase.\\n\\t'mulaw' = lowercase ifTrue: [^ 1].\\n\\t'none' = lowercase ifTrue: [^ 3].\\n\\t'adpcm3' = lowercase ifTrue: [^ 25].\\n\\t'adpcm4' = lowercase ifTrue: [^ 23].\\n\\t'adpcm5' = lowercase ifTrue: [^ 26].\\n\\t'gsm' = lowercase ifTrue: [^ 610].\\n\\tself error: 'unknown compression style'\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreSampledSound: aSampledSound onFileNamed: fileName compressionType: aString\\n\\t\\\"Store the samples of the given sampled sound on a file with the given name using the given type of compression. See formatCodeForCompressionType: for the list of compression types.\\\"\\n\\n\\t| fmt codec f compressed |\\n\\tfmt := self formatCodeForCompressionType: aString.\\n\\tcodec := self codecForFormatCode: fmt.\\n\\tf := self onFileNamed: fileName.\\n\\tf writeHeaderSamplingRate: aSampledSound originalSamplingRate format: fmt.\\n\\tcodec\\n\\t\\tifNil: [f appendSamples: aSampledSound samples]\\n\\t\\tifNotNil: [\\n\\t\\t\\tcompressed := codec encodeSoundBuffer: aSampledSound samples.\\n\\t\\t\\tf appendBytes: compressed].\\n\\tf closeFile.\\n! !\\nFileDirectoryWrapper subclass: #SuperSwikiDirectoryWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!SuperSwikiDirectoryWrapper commentStamp: '<historical>' prior: 0!\\nThe super swiki does not at present have subdirectories!\\n\\n\\n!SuperSwikiDirectoryWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 2/2/2001 08:28'!\\ncontents\\n\\n\\t^#()\\t\\t\\\"we have no sundirectories\\\"! !\\n\\n!SuperSwikiDirectoryWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 2/2/2001 08:28'!\\nhasContents\\n\\n\\t^false\\t\\t\\\"we have no sundirectories\\\"! !\\nProjectSwikiServer subclass: #SuperSwikiServer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n\\n!SuperSwikiServer methodsFor: 'accessing' stamp: 'KR 2/1/2006 13:07'!\\nencodingName\\n\\t(super encodingName) ifNil: [ ^SuperSwikiServer defaultEncodingName ] ifNotNil: [^super encodingName].! !\\n\\n!SuperSwikiServer methodsFor: 'accessing' stamp: 'mir 6/25/2001 17:17'!\\ntypeForPrefs\\n\\n\\t^'bss'! !\\n\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'mir 8/23/2001 22:15'!\\nallEntries\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: listallprojects'.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [^#()].\\n\\t^self parseListEntries: answer! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'ar 3/2/2001 14:36'!\\ndirectoryNames\\n\\n\\t^self entries select:[:each| each isDirectory] thenCollect: [ :each | each name]! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 2/2/2001 08:29'!\\ndirectoryWrapperClass\\n\\n\\t^SuperSwikiDirectoryWrapper! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'mir 8/23/2001 22:16'!\\nentries\\n\\n\\t^self allEntries! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 21:59'!\\nfastParseEntriesFrom: aString\\n\\n\\t| c first strm xEntryName xCreationTime xModificationTime xIsDirectory xFileSize ch |\\n\\n\\tc _ OrderedCollection new.\\n\\tfirst _ true.\\n\\taString linesDo: [ :x |\\n\\t\\tfirst ifFalse: [\\n\\t\\t\\tstrm _ ReadStream on: x.\\n\\t\\t\\t(strm upTo: $ ) = '(DirectoryEntry' ifFalse: [^nil].\\n\\t\\t\\t(strm upTo: $ ) = 'name:' ifFalse: [^nil].\\n\\t\\t\\txEntryName _ WriteStream on: String new.\\n\\t\\t\\tstrm next = $' ifFalse: [^nil].\\n\\t\\t\\t[\\n\\t\\t\\t\\tch _ strm next.\\n\\t\\t\\t\\tch = $' and: [(strm peekFor: $') not]\\n\\t\\t\\t] whileFalse: [\\n\\t\\t\\t\\txEntryName nextPut: ch.\\n\\t\\t\\t].\\n\\t\\t\\txEntryName _ xEntryName contents.\\n\\t\\t\\tstrm skipSeparators.\\n\\t\\t\\t(strm upTo: $ ) = 'creationTime:' ifFalse: [^nil].\\n\\t\\t\\txCreationTime _ (strm upTo: $ ) asNumber.\\n\\t\\t\\t(strm upTo: $ ) = 'modificationTime:' ifFalse: [^nil].\\n\\t\\t\\txModificationTime _ (strm upTo: $ ) asNumber.\\n\\t\\t\\t(strm upTo: $ ) = 'isDirectory:' ifFalse: [^nil].\\n\\t\\t\\txIsDirectory _ (strm upTo: $ ) = 'true'.\\n\\t\\t\\t(strm upTo: $ ) = 'fileSize:' ifFalse: [^nil].\\n\\t\\t\\txFileSize _ (strm upTo: $ ) asNumber.\\n\\n\\t\\t\\tc add: (DirectoryEntry \\n\\t\\t\\t\\tname: (xEntryName convertFromEncoding: self encodingName)\\n\\t\\t\\t\\tcreationTime: xCreationTime \\n\\t\\t\\t\\tmodificationTime: xModificationTime \\n\\t\\t\\t\\tisDirectory: xIsDirectory \\n\\t\\t\\t\\tfileSize: xFileSize\\n\\t\\t\\t)\\n\\t\\t].\\n\\t\\tfirst _ false.\\n\\t].\\n\\t^c\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'ar 3/2/2001 14:36'!\\nfileNames\\n\\n\\t^self entries select:[:each| each isDirectory not] thenCollect: [ :each | each name]! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/17/2000 12:49'!\\ngetOnly: numberOfBytes from: aName\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',aName.\\n\\t\\t'bytestoread: ',numberOfBytes printString.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [ ^nil].\\n\\t^answer allButFirst: 3\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'md 11/14/2003 17:28'!\\nmatchingEntries: criteria\\n\\t| result |\\n\\teToyUserListUrl ifNil:[^self entries].\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: listmatchingprojects'.\\n\\t} , criteria.\\n\\t(result beginsWith: 'OK')\\n\\t\\tifFalse: [^self entries]. \\\"If command not supported\\\"\\n\\t^self parseListEntries: result! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 22:02'!\\noldFileNamed: aName\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',aName convertToEncoding: self encodingName.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [ ^nil].\\n\\t^(SwikiPseudoFileStream with: (answer allButFirst: 3))\\n\\t\\treset;\\n\\t\\tdirectory: self;\\n\\t\\tlocalName: (aName convertToEncoding: self encodingName);\\n\\t\\tyourself\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/17/2000 14:54'!\\noldFileOrNoneNamed: fullName\\n\\n\\t| answer aName |\\n\\n\\tself flag: #bob.\\t\\t\\\"fix this up for full names\\\"\\n\\n\\taName _ fullName.\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',(self localNameFor: aName).\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [^nil].\\n\\t^(SwikiPseudoFileStream with: (answer allButFirst: 3))\\n\\t\\treset;\\n\\t\\tdirectory: self;\\n\\t\\tlocalName: aName;\\n\\t\\tyourself\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 21:57'!\\nputFile: fileStream named: fileNameOnServer\\n\\n\\t\\n\\t^(\\n\\t\\tself sendToSwikiProjectServer: {\\n\\t\\t\\t'uploadproject: ',fileNameOnServer convertToEncoding: self encodingName.\\n\\t\\t\\t'password: ',ProjectPasswordNotification signal.\\n\\t\\t\\tfileStream contentsOfEntireFile.\\n\\t\\t}\\n\\t) beginsWith: 'OK'\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/13/2000 16:53'!\\nreadOnlyFileNamed: aName\\n\\n\\t^self oldFileNamed: aName\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 2/16/2001 18:22'!\\nsendToSwikiProjectServer: anArray\\n\\n\\t| argsDict answer buildStream |\\n\\n\\tbuildStream _ WriteStream on: String new.\\n\\tanArray do: [ :each | \\n\\t\\tbuildStream \\n\\t\\t\\tnextPutAll: each size printString;\\n\\t\\t\\tspace;\\n\\t\\t\\tnextPutAll: each\\n\\t].\\n\\t(argsDict _ Dictionary new)\\n\\t\\tat: 'swikicommands'\\n\\t\\tput: {buildStream contents}.\\n\\tanswer _ HTTPSocket \\n\\t\\thttpPostToSuperSwiki: self url\\n\\t\\targs: argsDict\\n\\t\\taccept: 'application/octet-stream' \\n\\t\\trequest: ''.\\n\\t^(answer isKindOf: MIMEDocument) ifTrue: [answer content] ifFalse: [answer]\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 2/20/2006 12:50'!\\nupdateProjectInfoFor: aProject\\n\\n\\t| data details projectLinks linkString uploader |\\n\\n\\tdata _ OrderedCollection new.\\n\\tdata add: 'action: updatepage'.\\n\\tdata add: 'password: ',ProjectPasswordNotification signal.\\n\\tdata add: 'projectimage: ', (aProject name convertToEncoding: self encodingName) , '.gif'.\\n\\tuploader _ Utilities authorNamePerSe.\\n\\tuploader isEmptyOrNil ifTrue: [uploader _ Utilities authorInitialsPerSe].\\n\\tuploader isEmptyOrNil ifFalse: [\\n\\t\\tdata add: ('submittedBy: ',uploader convertToEncoding: self encodingName).\\n\\t].\\n\\tprojectLinks _ Set new.\\n\\taProject world allMorphsDo: [ :each |\\n\\t\\t(each isKindOf: ProjectViewMorph) ifTrue: [\\n\\t\\t\\tprojectLinks add: each safeProjectName.\\n\\t\\t].\\n\\t].\\n\\tdetails _ aProject world valueOfProperty: #ProjectDetails ifAbsent: [Dictionary new].\\n\\tdetails at: 'projectname' ifAbsentPut: [aProject name].\\n\\tprojectLinks isEmpty ifTrue: [\\n\\t\\tdetails removeKey: 'projectlinks' ifAbsent: []\\n\\t] ifFalse: [\\n\\t\\tlinkString _ String streamContents: [ :strm |\\n\\t\\t\\tprojectLinks asSortedCollection do: [ :each |\\n\\t\\t\\t\\tstrm nextPutAll: each\\n\\t\\t\\t] separatedBy: [\\n\\t\\t\\t\\tstrm nextPut: $.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tdetails at: 'projectlinks' put: linkString\\n\\t].\\n\\tdetails keysAndValuesDo: [ :k :v |\\n\\t\\tdata add: k , ': ' , (v convertToEncoding: self encodingName). self flag: #yoFlag.\\n\\t].\\n\\t^self sendToSwikiProjectServer: data! !\\n\\n\\n\\n!SuperSwikiServer methodsFor: 'squeaklets' stamp: 'KR 1/30/2006 22:15'!\\nupLoadProject: projectName members: archiveMembers retry: aBool\\n\\t| answer |\\n\\tarchiveMembers do:[:entry|\\n\\t\\tProgressNotification signal: '4:uploadingFile' extra:'(uploading ' translated, entry fileName convertFromSystemString , '...)' translated.\\n\\t\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t\\t'uploadproject2: ', entry fileName convertFromSystemString convertToEncoding: self encodingName.\\n\\t\\t\\t'password: ',ProjectPasswordNotification signal.\\n\\t\\t\\tentry contents.\\n\\t\\t}.\\n\\t\\tanswer = 'OK' ifFalse:[\\n\\t\\t\\tself inform:'Server responded ' translated, answer.\\n\\t\\t\\t^false].\\n\\t].\\n\\tProgressNotification signal: '4:uploadingFile' extra:''.\\n\\t^true! !\\n\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'mir 11/14/2001 16:25'!\\nisSearchable\\n\\t^true! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'ar 8/24/2001 15:12'!\\nparseQueryResult: resultStream\\n\\n\\t| projectInfos projectName downloadUrl |\\n\\tprojectInfos _ OrderedCollection new.\\n\\tdownloadUrl _ self downloadUrl.\\n\\tresultStream reset; nextLine.\\n\\t[resultStream atEnd] whileFalse: [\\n\\t\\tprojectName _ resultStream nextLine.\\n\\t\\tprojectInfos add: projectName.\\n\\t\\t\\\"Transcript show: projectName; cr.\\\"\\n\\t\\t].\\n\\t\\\"Transcript show: 'done'; cr.\\\"\\n\\t^projectInfos\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/17/2000 16:10'!\\nqueryAllProjects\\n\\n\\\"answer a collection of DirectoryEntry objects for each file on server\\\"\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki queryAllProjects\\\"\\n\\n\\t^self sendToSwikiProjectServer: {\\n\\t\\t'action: listallprojects'.\\n\\t}! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'md 11/14/2003 17:28'!\\nqueryProjects: criteria\\n\\t| result |\\n\\t\\\"SuperSwikiServer defaultSuperSwiki queryProjects: #('submittedBy: mir' )\\\"\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t} , criteria.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\t^self parseQueryResult: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/17/2000 19:23'!\\nqueryProjectsAndShow\\n\\t| result |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t\\t\\\"'projectname: *proj*'.\\\"\\n\\t}.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\tself showQueryAsPVM: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/18/2000 12:23'!\\nqueryProjectsAndShow: thingsToSearchFor\\n\\t| result |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t}, thingsToSearchFor.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\tself showQueryAsPVM: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/12/2000 17:01'!\\nqueryPythagoras\\n\\\"SuperSwikiServer testOnlySuperSwiki queryPythagoras\\\"\\n\\n\\t^self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t\\t'projectsubcategory: *geometry*'.\\n\\t\\t\\\"'projectname: *pythagoras*'.\\\"\\n\\t}! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'KR 1/30/2006 21:59'!\\nshowQueryAsPVM: resultStream\\n\\t| answer gif whatToShow projectName fileName firstURL wrapper currX currY maxX maxY rawProjectName |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresultStream reset; nextLine.\\n\\tanswer _ RectangleMorph new\\n\\t\\tuseRoundedCorners;\\n\\t\\tborderWidth: 0;\\n\\t\\tborderColor: Color blue;\\n\\t\\tcolor: Color paleBlue.\\n\\tcurrX _ currY _ maxX _ maxY _ 10.\\n\\t[resultStream atEnd] whileFalse: [\\n\\t\\trawProjectName _ resultStream nextLine.\\n\\t\\tprojectName _ rawProjectName convertFromEncoding: self encodingName.\\n\\t\\tfileName _ resultStream nextLine convertFromEncoding: self encodingName.\\n\\t\\tgif _ self oldFileOrNoneNamed: rawProjectName,'.gif'.\\n\\t\\tgif ifNotNil: [gif _ GIFReadWriter formFromStream: gif].\\n\\t\\tcurrX > 600 ifTrue: [\\n\\t\\t\\tcurrX _ 10.\\n\\t\\t\\tcurrY _ maxY + 10.\\n\\t\\t].\\n\\t\\tgif ifNil: [\\n\\t\\t\\tgif _ AlignmentMorph newColumn\\n\\t\\t\\t\\thResizing: #shrinkWrap;\\n\\t\\t\\t\\tvResizing: #shrinkWrap;\\n\\t\\t\\t\\tborderWidth: 8;\\n\\t\\t\\t\\tborderColor: Color red;\\n\\t\\t\\t\\tcolor: Color lightRed;\\n\\t\\t\\t\\taddMorph: (StringMorph contents: 'No GIF for ',projectName);\\n\\t\\t\\t\\tfullBounds;\\n\\t\\t\\t\\timageForm\\n\\t\\t].\\n\\t\\tfirstURL _ self url.\\n\\t\\tfirstURL last == $/ ifFalse: [firstURL _ firstURL, '/'].\\n\\n\\t\\twhatToShow _ ProjectViewMorph new\\n\\t\\t\\timage: (gif asFormOfDepth: Display depth);\\n\\t\\t\\tlastProjectThumbnail: gif;\\n\\t\\t\\tsetProperty: #SafeProjectName toValue: projectName;\\n\\t\\t\\tproject: (DiskProxy \\n\\t\\t\\t\\tglobal: #Project \\n\\t\\t\\t\\tselector: #namedUrl: \\n\\t\\t\\t\\targs: {firstURL,fileName}\\n\\t\\t\\t).\\n\\n\\t\\tanswer addMorphBack: (whatToShow position: currX @ currY).\\n\\t\\tcurrX _ currX + whatToShow width + 10.\\n\\t\\tmaxX _ maxX max: currX.\\n\\t\\tmaxY _ maxY max: currY + whatToShow height.\\n\\t].\\n\\tmaxX = 10 ifTrue: [\\n\\t\\t^self inform: 'No projects found for your criteria'\\n\\t].\\n\\tanswer extent: (maxX @ maxY) + (0@10).\\n\\twrapper _ ScrollPane new extent: (answer width + 10) @ (answer height min: 400).\\n\\twrapper color: Color white.\\n\\twrapper scroller addMorph: answer.\\n\\twrapper \\n\\t\\tbecomeModal;\\n\\t\\topenCenteredInWorld;\\n\\t\\tuseRoundedCorners;\\n\\t\\tsetScrollDeltas.! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/25/2000 12:14'!\\nspeedTest1\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki speedTest1\\\"\\n\\n\\t| answer t totalTime |\\n\\n\\ttotalTime _ [\\n\\t\\tanswer _ (1 to: 10) collect: [ :x |\\n\\t\\t\\tt _ [answer _ self sendToSwikiProjectServer: {\\n\\t\\t\\t\\t'action: readnamedfile'.\\n\\t\\t\\t\\t'projectname: xyz.002.pr'.\\n\\t\\t\\t}] timeToRun.\\n\\t\\t\\t{t. answer size}\\n\\t\\t].\\n\\t] timeToRun.\\n\\t^{totalTime. answer}\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'ar 7/8/2001 17:06'!\\nspeedTest2\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki speedTest2\\\"\\n\\n\\\"==observed results\\n10 forks of 10 reads of 88K in 12.7 seconds\\n100 * 88110 / 12.7 ===> 693779 bytes per second\\n---\\n10 forks of 10 reads of 88K in 10.7 seconds\\n100 * 88110 / 10.7 ===> 823457 bytes per second\\n---at priority 5\\n10 forks of 10 reads of 88K in 9.8 seconds\\n100 * 88110 / 9.8 ===> 899081 bytes per second\\n===\\\"\\n\\n\\t| answer bigAnswer tRealBegin tRealEnd |\\n\\n\\tbigAnswer _ SharedQueue new.\\n\\ttRealBegin _ tRealEnd _ Time millisecondClockValue.\\n\\t10 timesRepeat: [\\n\\t\\t[\\n\\t\\t\\tanswer _ SuperSwikiServer testOnlySuperSwiki speedTest1.\\n\\t\\t\\ttRealEnd _ Time millisecondClockValue.\\n\\t\\t\\tbigAnswer nextPut: {\\n\\t\\t\\t\\t{tRealBegin. tRealEnd. tRealEnd - tRealBegin}.\\n\\t\\t\\t\\tanswer\\n\\t\\t\\t}.\\n\\t\\t] forkAt: Processor userInterruptPriority.\\n\\t].\\n\\tbigAnswer inspect.\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/7/2000 16:12'!\\ntest1\\n\\n\\t| localDirectory localFileName local resp |\\n\\n\\tlocalDirectory _ FileDirectory default.\\n\\tlocalFileName _ 'superTest1.07Oct1611.cs'.\\n\\tlocal _ localDirectory oldFileNamed: localFileName.\\n\\tresp _ self putFile: local named: localFileName retry: false.\\n\\tlocal close.\\n\\t^resp\\n! !\\n\\n\\n!SuperSwikiServer methodsFor: 'private' stamp: 'mir 8/23/2001 22:04'!\\nparseListEntries: listResult\\n\\n\\t| c first |\\n\\tc _ self fastParseEntriesFrom: listResult.\\n\\tc ifNotNil: [^c].\\n\\tc _ OrderedCollection new.\\n\\tfirst _ true.\\n\\tlistResult linesDo: [ :x |\\n\\t\\tfirst ifFalse: [c add: (Compiler evaluate: x)].\\n\\t\\tfirst _ false.\\n\\t].\\n\\t^c\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSuperSwikiServer class\\n\\tinstanceVariableNames: ''!\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/7/2000 17:47'!\\ncurrentSuperSwiki\\n\\n\\t\\\"make this return nil to disable SuperSwiki hack\\\"\\n\\n\\t^self defaultSuperSwiki\\n\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'KR 2/1/2006 13:18'!\\ndefaultEncodingName\\n\\tLocale current isoLanguage = 'ja' ifTrue: [^'shift_jis' copy] ifFalse: [^'latin1' copy].\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 19:11'!\\ndefaultSuperSwiki\\n\\n\\t^SuperSwikiServer new \\n\\t\\ttype: #http;\\n\\t\\tserver: self defaultSuperSwikiIPAddress;\\n\\t\\tdirectory: '/super/SuperSwikiProj'\\n\\t\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/19/2000 11:05'!\\ndefaultSuperSwikiIPAddress\\n\\n\\t^'209.143.91.36'\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 19:11'!\\ntestOnlySuperSwiki\\n\\n\\t^SuperSwikiServer new \\n\\t\\ttype: #http;\\n\\t\\tserver: self defaultSuperSwikiIPAddress;\\n\\t\\tdirectory: '/super/SuperSwikiProj'\\n\\t\\n! !\\nRWBinaryOrTextStream subclass: #SwikiPseudoFileStream\\n\\tinstanceVariableNames: 'directoryUrl localName directory'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:53'!\\ndirectory\\n\\n\\t^directory url! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:53'!\\ndirectory: x\\n\\n\\tdirectory _ x! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 15:00'!\\ndirectoryObject\\n\\n\\t^directory! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 15:00'!\\ndirectoryUrl\\n\\n\\t^directory url! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\ndirectoryUrl: x\\n\\n\\tdirectoryUrl _ x! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 13:59'!\\nfileName\\n\\n\\t^localName! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:01'!\\nisTypeHTTP\\n\\n\\t^true! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\nlocalName\\n\\n\\t^localName! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\nlocalName: x\\n\\n\\tlocalName _ x! !\\nModel subclass: #Switch\\n\\tinstanceVariableNames: 'on onAction offAction'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Menus'!\\n!Switch commentStamp: '<historical>' prior: 0!\\nI 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.\\n1/24/96 sw: made this a subclass of Model, for faster dependents handling!\\n\\n\\n!Switch methodsFor: 'action'!\\ndoAction: anAction \\n\\t\\\"Execute anAction if it is non-nil.\\\"\\n\\n\\tanAction == nil ifFalse: [anAction value]! !\\n\\n!Switch methodsFor: 'action'!\\noffAction: anAction \\n\\t\\\"Set the off action of the receiver to anAction.\\\"\\n\\n\\toffAction _ anAction fixTemps! !\\n\\n!Switch methodsFor: 'action'!\\nonAction: anAction \\n\\t\\\"Set the on action of the receiver to anAction.\\\"\\n\\n\\tonAction _ anAction fixTemps! !\\n\\n\\n!Switch methodsFor: 'converting' stamp: 'md 9/18/2004 19:51'!\\nprintOn: aStream\\n\\tself isOn\\n\\t\\tifTrue: [aStream nextPutAll: 'ON-Switch']\\n\\t\\tifFalse: [aStream nextPutAll: 'OFF-Switch']! !\\n\\n\\n!Switch methodsFor: 'state'!\\nclear\\n\\t\\\"Set the state of the receiver to 'off'. If the state of the receiver was \\n\\tpreviously 'on', then 'self change' is sent. The receiver's off action is \\n\\tNOT executed.\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ false.\\n\\t\\t\\tself changed]! !\\n\\n!Switch methodsFor: 'state'!\\nisOff\\n\\t\\\"Answer whether the receiver is set off or not.\\\"\\n\\n\\t^on not! !\\n\\n!Switch methodsFor: 'state'!\\nisOn\\n\\t\\\"Answer whether the receiver is set on or not.\\\"\\n\\n\\t^on! !\\n\\n!Switch methodsFor: 'state'!\\nset\\n\\t\\\"Set the state of the receiver to 'on'. If the state of the receiver was \\n\\tpreviously 'off', then 'self change' is sent. The receiver's on action is \\n\\tNOT executed.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed]! !\\n\\n!Switch methodsFor: 'state'!\\nswitch\\n\\t\\\"Change the state of the receiver from 'on' to 'off' or from 'off' to 'on' (see \\n\\tSwitch|turnOn, Switch|turnOff).\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: [self turnOff]\\n\\t\\tifFalse: [self turnOn]! !\\n\\n!Switch methodsFor: 'state'!\\nturnOff\\n\\t\\\"Set the state of the receiver to 'off'. If the state of the receiver was \\n\\tpreviously 'on', then 'self change' is sent and the receiver's off action is \\n\\texecuted.\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ false.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself doAction: offAction]! !\\n\\n!Switch methodsFor: 'state'!\\nturnOn\\n\\t\\\"Set the state of the receiver to 'on'. If the state of the receiver was \\n\\tpreviously 'off', then 'self change' is sent and the receiver's on action is \\n\\texecuted.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself doAction: onAction]! !\\n\\n\\n!Switch methodsFor: 'private'!\\ninitializeOff\\n\\n\\ton _ false. \\n\\tonAction _ nil.\\n\\toffAction _ nil! !\\n\\n!Switch methodsFor: 'private'!\\ninitializeOn\\n\\n\\ton _ true. \\n\\tonAction _ nil.\\n\\toffAction _ nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSwitch class\\n\\tinstanceVariableNames: ''!\\n\\n!Switch class methodsFor: 'instance creation'!\\nnew\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil\\n\\t('no action'), and the state is set to 'off'.\\\"\\n\\n\\t^self newOff! !\\n\\n!Switch class methodsFor: 'instance creation'!\\nnewOff\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil \\n\\t('no action'), and the state is set to 'off'.\\\"\\n\\n\\t^super new initializeOff! !\\n\\n!Switch class methodsFor: 'instance creation'!\\nnewOn\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil \\n\\t('no action'), and the state is set to 'on'.\\\"\\n\\n\\t^super new initializeOn! !\\nObject subclass: #Syllable\\n\\tinstanceVariableNames: 'phonemes accent events'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-TTS'!\\n!Syllable commentStamp: '<historical>' prior: 0!\\nMy instances are syllables. They can carry a pitch accent: 'H*', 'L*', etc.!\\n\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/11/1999 13:03'!\\naccent\\n\\t^ accent! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naccent: aString\\n\\taccent := aString! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 17:47'!\\naccept: anObject\\n\\tanObject syllable: self! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nevents\\n\\t^ events ifNil: [events := CompositeEvent new addAll: (self phonemes collect: [ :each | PhoneticEvent new phoneme: each; duration: 0.080]); yourself]! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 02:55'!\\nphonemes\\n\\t^ phonemes! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nphonemes: aCollection\\n\\tphonemes := aCollection! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 02:54'!\\nstress\\n\\tself phonemes do: [ :each | each stress > 0 ifTrue: [^ each stress]].\\n\\t^ 0! !\\n\\n\\n!Syllable methodsFor: 'enumarating' stamp: 'len 12/13/1999 01:20'!\\neventsDo: aBlock\\n\\tself events do: aBlock! !\\n\\n\\n!Syllable methodsFor: 'printing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nprintOn: aStream\\n\\t| first |\\n\\taStream nextPut: $[.\\n\\tfirst := true.\\n\\tself phonemes do: [ :each |\\n\\t\\tfirst ifFalse: [aStream space].\\n\\t\\taStream print: each.\\n\\t\\tfirst := false].\\n\\taStream nextPut: $]! !\\n\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/8/1999 19:03'!\\nhasPrimaryStress\\n\\t^ self stress = 1! !\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/8/1999 19:03'!\\nhasSecondaryStress\\n\\t^ self stress = 2! !\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/11/1999 13:11'!\\nisAccented\\n\\t^ self accent notNil! !\\nString subclass: #Symbol\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'NewSymbols OneCharacterSymbols SymbolTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Strings'!\\n!Symbol commentStamp: '<historical>' prior: 0!\\nI represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol.!\\n\\n\\n!Symbol methodsFor: 'accessing'!\\nat: anInteger put: anObject \\n\\t\\\"You cannot modify the receiver.\\\"\\n\\n\\tself errorNoModification! !\\n\\n!Symbol methodsFor: 'accessing' stamp: 'sma 2/5/2000 12:32'!\\nprecedence\\n\\t\\\"Answer the receiver's precedence, assuming it is a valid Smalltalk\\n\\tmessage selector or 0 otherwise. The numbers are 1 for unary,\\n\\t2 for binary and 3 for keyword selectors.\\\"\\n\\n\\tself size = 0 ifTrue: [^ 0].\\n\\tself first isLetter ifFalse: [^ 2].\\n\\tself last = $: ifTrue: [^ 3].\\n\\t^ 1! !\\n\\n!Symbol methodsFor: 'accessing'!\\nreplaceFrom: start to: stop with: replacement startingAt: repStart\\n\\n\\tself errorNoModification! !\\n\\n\\n!Symbol methodsFor: 'comparing' stamp: 'ar 4/10/2005 23:45'!\\n= aSymbol\\n\\t\\\"Compare the receiver and aSymbol.\\\" \\n\\tself == aSymbol ifTrue: [^ true].\\n\\tself class == aSymbol class ifTrue: [^ false].\\n\\t\\\"Use String comparison otherwise\\\"\\n\\t^ super = aSymbol! !\\n\\n\\n!Symbol methodsFor: 'converting' stamp: 'st 11/22/2004 17:26'!\\nasMutator\\n\\t\\\"Return a setter message from a getter message. For example,\\n\\t#name asMutator returns #name:\\\"\\n\\t^ (self copyWith: $:) asSymbol! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'ar 4/10/2005 22:42'!\\nasString \\n\\t\\\"Refer to the comment in String|asString.\\\"\\n\\t| newString |\\n\\tnewString _ self species new: self size.\\n\\tnewString replaceFrom: 1 to: newString size with: self startingAt: 1.\\n\\t^newString! !\\n\\n!Symbol methodsFor: 'converting'!\\nasSymbol \\n\\t\\\"Refer to the comment in String|asSymbol.\\\"! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'sw 1/28/98 18:18'!\\ncapitalized\\n\\t^ self asString capitalized asSymbol! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'md 8/10/2004 10:54'!\\nwithFirstCharacterDownshifted\\n\\t\\\"Answer an object like the receiver but with first character downshifted if necesary\\\"\\n\\n\\t^self asString withFirstCharacterDownshifted asSymbol.! !\\n\\n\\n!Symbol methodsFor: 'copying' stamp: 'tk 6/26/1998 11:35'!\\nclone\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying'!\\ncopy\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying'!\\nshallowCopy\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying' stamp: 'tk 8/19/1998 16:05'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I am immutable in the Morphic world. Do not record me.\\\"! !\\n\\n\\n!Symbol methodsFor: 'filter streaming' stamp: 'mpw 1/1/1901 00:20'!\\nbyteEncode:aStream\\n\\t^aStream writeSymbol:self.\\n! !\\n\\n\\n!Symbol methodsFor: 'printing' stamp: 'sw 8/19/1999 11:30'!\\nisOrientedFill\\n\\t\\\"Needs to be implemented here because symbols can occupy 'color' slots of morphs.\\\"\\n\\n\\t^ false! !\\n\\n!Symbol methodsFor: 'printing' stamp: 'di 4/25/2000 12:32'!\\nstoreOn: aStream \\n\\n\\taStream nextPut: $#.\\n\\t(Scanner isLiteralSymbol: self)\\n\\t\\tifTrue: [aStream nextPutAll: self]\\n\\t\\tifFalse: [super storeOn: aStream]! !\\n\\n\\n!Symbol methodsFor: 'system primitives' stamp: 'di 1/2/1999 17:00'!\\nflushCache\\n\\t\\\"Tell the interpreter to remove all entries with this symbol as a selector from its method lookup cache, if it has one. This primitive must be called whenever a method is defined or removed.\\n\\tNOTE: Only one of the two selective flush methods needs to be used.\\n\\tSqueak 2.3 and later uses 116 (See CompiledMethod flushCache).\\\"\\n\\n\\t<primitive: 119>\\n! !\\n\\n!Symbol methodsFor: 'system primitives' stamp: 'md 2/16/2006 17:17'!\\nnumArgs: n\\n\\t\\\"Answer a string that can be used as a selector with n arguments.\\n\\t TODO: need to be extended to support shrinking and for selectors like #+ \\\" \\n\\n\\t| selector numArgs aStream offs |\\n\\t\\n\\tselector := self.\\n\\t(numArgs := selector numArgs) >= n ifTrue: [^self].\\t\\n\\taStream := WriteStream on: (String new: 16).\\n\\taStream nextPutAll: self.\\n\\t\\n\\t(numArgs = 0) ifTrue: [aStream nextPutAll: ':'. offs := 0] ifFalse: [offs := 1].\\n\\t2 to: n - numArgs + offs do: [:i | aStream nextPutAll: 'with:'].\\t\\n\\t^aStream contents asSymbol\\n\\t\\n! !\\n\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 1/20/2006 16:16'!\\nincludesKey: sym\\n\\t^self == sym.! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 8/27/2005 16:33'!\\nisDoIt\\n\\n\\t^ (self == #DoIt) or: [self == #DoItIn:].! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:32'!\\nisInfix\\n\\t\\\"Answer whether the receiver is an infix message selector.\\\"\\n\\n\\t^ self precedence == 2! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'!\\nisKeyword\\n\\t\\\"Answer whether the receiver is a message keyword.\\\"\\n\\n\\t^ self precedence == 3! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'di 4/25/2000 12:32'!\\nisLiteral\\n\\t\\\"Answer whether the receiver is a valid Smalltalk literal.\\\"\\n\\n\\t^ true! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:13'!\\nisPvtSelector\\n\\t\\\"Answer whether the receiver is a private message selector, that is,\\n\\tbegins with 'pvt' followed by an uppercase letter, e.g. pvtStringhash.\\\"\\n\\n\\t^ (self beginsWith: 'pvt') and: [self size >= 4 and: [(self at: 4) isUppercase]]! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 4/30/2003 15:31'!\\nisSymbol\\n\\t^ true ! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'!\\nisUnary\\n\\t\\\"Answer whether the receiver is an unary message selector.\\\"\\n\\n\\t^ self precedence == 1! !\\n\\n\\n!Symbol methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:46'!\\nasExplorerString\\n\\t^ self printString! !\\n\\n\\n!Symbol methodsFor: 'private'!\\nerrorNoModification\\n\\n\\tself error: 'symbols can not be modified.'! !\\n\\n!Symbol methodsFor: 'private'!\\nstring: aString\\n\\n\\t1 to: aString size do: [:j | super at: j put: (aString at: j)].\\n\\t^self ! !\\n\\n\\n!Symbol methodsFor: 'evaluating' stamp: 'md 3/24/2006 12:09'!\\nvalue: anObject \\n\\t^anObject perform: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSymbol class\\n\\tinstanceVariableNames: ''!\\n\\n!Symbol class methodsFor: 'access' stamp: 'ar 4/10/2005 22:49'!\\nallSymbols\\n\\t\\\"Answer all interned symbols\\\"\\n\\t^Array streamContents:[:s|\\n\\t\\ts nextPutAll: NewSymbols.\\n\\t\\ts nextPutAll: OneCharacterSymbols.\\n\\t\\ts nextPutAll: SymbolTable.\\n\\t].\\n! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'yo 11/3/2004 19:24'!\\nselectorsContaining: aString\\n\\t\\\"Answer a list of selectors that contain aString within them. Case-insensitive. Does return symbols that begin with a capital letter.\\\"\\n\\n\\t| size selectorList ascii |\\n\\n\\tselectorList _ OrderedCollection new.\\n\\t(size _ aString size) = 0 ifTrue: [^selectorList].\\n\\n\\taString size = 1 ifTrue:\\n\\t\\t[\\n\\t\\t\\tascii _ aString first asciiValue.\\n\\t\\t\\tascii < 128 ifTrue: [selectorList add: (OneCharacterSymbols at: ascii+1)]\\n\\t\\t].\\n\\n\\taString first isLetter ifFalse:\\n\\t\\t[\\n\\t\\t\\taString size == 2 ifTrue: \\n\\t\\t\\t\\t[Symbol hasInterned: aString ifTrue:\\n\\t\\t\\t\\t\\t[:s | selectorList add: s]].\\n\\t\\t\\t^selectorList\\n\\t\\t].\\n\\n\\tselectorList _ selectorList copyFrom: 2 to: selectorList size.\\n\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\teach size >= size ifTrue:\\n\\t\\t\\t[(each findSubstring: aString in: each startingAt: 1 \\n\\t\\t\\t\\tmatchTable: CaseInsensitiveOrder) > 0\\n\\t\\t\\t\\t\\t\\tifTrue: [selectorList add: each]]].\\n\\n\\t^selectorList reject: [:each | \\\"reject non-selectors, but keep ones that begin with an uppercase\\\"\\n\\t\\teach numArgs < 0 and: [each asString withFirstCharacterDownshifted numArgs < 0]].\\n\\n\\\"Symbol selectorsContaining: 'scon'\\\"! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'tween 9/13/2004 10:09'!\\nthatStartsCaseSensitive: leadingCharacters skipping: skipSym\\n\\t\\\"Same as thatStarts:skipping: but caseSensitive\\\"\\n\\t| size firstMatch key |\\n\\n\\tsize := leadingCharacters size.\\n\\tsize = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]].\\n\\tfirstMatch := leadingCharacters at: 1.\\n\\tsize > 1 ifTrue: [key := leadingCharacters copyFrom: 2 to: size].\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\t\\teach size >= size ifTrue:\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t((each at: 1) == firstMatch and:\\n\\t\\t\\t\\t\\t\\t[key == nil or:\\n\\t\\t\\t\\t\\t\\t\\t[(each findString: key startingAt: 2 caseSensitive: true) = 2]])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^each]\\n\\t\\t\\t\\t]\\n\\t\\t] after: skipSym.\\n\\n\\t^nil\\n! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'RAA 5/29/2001 14:35'!\\nthatStarts: leadingCharacters skipping: skipSym\\n\\t\\\"Answer a selector symbol that starts with leadingCharacters.\\n\\tSymbols beginning with a lower-case letter handled directly here.\\n\\tIgnore case after first char.\\n\\tIf skipSym is not nil, it is a previous answer; start searching after it.\\n\\tIf no symbols are found, answer nil.\\n\\tUsed by Alt-q (Command-q) routines\\\"\\n\\n\\t| size firstMatch key |\\n\\n\\tsize _ leadingCharacters size.\\n\\tsize = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]].\\n\\n\\tfirstMatch _ leadingCharacters at: 1.\\n\\tsize > 1 ifTrue: [key _ leadingCharacters copyFrom: 2 to: size].\\n\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\t\\teach size >= size ifTrue:\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t((each at: 1) == firstMatch and:\\n\\t\\t\\t\\t\\t\\t[key == nil or:\\n\\t\\t\\t\\t\\t\\t\\t[(each findString: key startingAt: 2 caseSensitive: false) = 2]])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^each]\\n\\t\\t\\t\\t]\\n\\t\\t] after: skipSym.\\n\\n\\t^nil\\n\\n\\\"Symbol thatStarts: 'sf' skipping: nil\\\"\\n\\\"Symbol thatStarts: 'sf' skipping: #sfpGetFile:with:with:with:with:with:with:with:with:\\\"\\n\\\"Symbol thatStarts: 'candidate' skipping: nil\\\"\\n! !\\n\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 08:21'!\\nallSymbolTablesDo: aBlock\\n\\n\\tNewSymbols do: aBlock.\\n\\tSymbolTable do: aBlock.! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 14:35'!\\nallSymbolTablesDo: aBlock after: aSymbol\\n\\n\\tNewSymbols do: aBlock after: aSymbol.\\n\\tSymbolTable do: aBlock after: aSymbol.! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 12/17/2000 18:05'!\\ncompactSymbolTable\\n\\t\\\"Reduce the size of the symbol table so that it holds all existing symbols + 25% (changed from 1000 since sets like to have 25% free and the extra space would grow back in a hurry)\\\"\\n\\n\\t| oldSize |\\n\\n\\tSmalltalk garbageCollect.\\n\\toldSize _ SymbolTable array size.\\n\\tSymbolTable growTo: SymbolTable size * 4 // 3 + 100.\\n\\t^oldSize printString,' ',(oldSize - SymbolTable array size) printString, ' slot(s) reclaimed'! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 09:04'!\\ninitialize\\n\\n\\t\\\"Symbol initialize\\\"\\n\\n\\tSymbol rehash.\\n\\tOneCharacterSymbols _ nil.\\n\\tOneCharacterSymbols _ (1 to: 256) collect: [ :i | (i - 1) asCharacter asSymbol].\\n\\tSmalltalk addToShutDownList: self.\\n! !\\n\\n\\n!Symbol class methodsFor: 'instance creation'!\\nfindInterned:aString\\n\\n\\tself hasInterned:aString ifTrue:[:symbol| ^symbol].\\n\\t^nil.! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 23:04'!\\ninternCharacter: aCharacter\\n\\taCharacter asciiValue > 256 ifTrue:[^self intern: aCharacter asString].\\n\\tOneCharacterSymbols ifNil: [^self intern: aCharacter asString].\\n\\t^OneCharacterSymbols at: aCharacter asciiValue + 1\\n! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'ar 4/12/2005 17:37'!\\nintern: aStringOrSymbol \\n\\n\\t^(self lookup: aStringOrSymbol) ifNil:[\\n\\t\\t| aClass aSymbol |\\n\\t\\taStringOrSymbol isSymbol ifTrue:[\\n\\t\\t\\taSymbol _ aStringOrSymbol.\\n\\t\\t] ifFalse:[\\n\\t\\t\\taClass := aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol].\\n\\t\\t\\taSymbol := aClass new: aStringOrSymbol size.\\n\\t\\t\\taSymbol string: aStringOrSymbol.\\n\\t\\t].\\n\\t\\tNewSymbols add: aSymbol.\\n\\t\\taSymbol].! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'RAA 5/29/2001 08:09'!\\nlookup: aStringOrSymbol\\n\\n\\t^(SymbolTable like: aStringOrSymbol) ifNil: [\\n\\t\\tNewSymbols like: aStringOrSymbol\\n\\t]! !\\n\\n!Symbol class methodsFor: 'instance creation'!\\nnewFrom: aCollection \\n\\t\\\"Answer an instance of me containing the same elements as aCollection.\\\"\\n\\n\\t^ (aCollection as: String) asSymbol\\n\\n\\\"\\tSymbol newFrom: {$P. $e. $n}\\n\\t{$P. $e. $n} as: Symbol\\n\\\"! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'di 10/11/1999 00:02'!\\nreadFrom: strm \\\"Symbol readFromString: '#abc'\\\"\\n\\n\\tstrm peek = $# ifFalse: [self error: 'Symbols must be introduced by #'].\\n\\t^ (Scanner new scan: strm) advance \\\"Just do what the code scanner does\\\"! !\\n\\n\\n!Symbol class methodsFor: 'private' stamp: 'ar 4/10/2005 22:43'!\\nhasInterned: aString ifTrue: symBlock \\n\\t\\\"Answer with false if aString hasnt been interned (into a Symbol), \\n\\totherwise supply the symbol to symBlock and return true.\\\"\\n\\n\\t| symbol |\\n\\t^ (symbol _ self lookup: aString)\\n\\t\\tifNil: [false]\\n\\t\\tifNotNil: [symBlock value: symbol.\\n\\t\\t\\ttrue]! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 14:33'!\\npossibleSelectorsFor: misspelled \\n\\t\\\"Answer an ordered collection of possible corrections\\n\\tfor the misspelled selector in order of likelyhood\\\"\\n\\n\\t| numArgs candidates lookupString best binary short long first ss |\\n\\tlookupString _ misspelled asLowercase. \\\"correct uppercase selectors to lowercase\\\"\\n\\tnumArgs _ lookupString numArgs.\\n\\t(numArgs < 0 or: [lookupString size < 2]) ifTrue: [^ OrderedCollection new: 0].\\n\\tfirst _ lookupString first.\\n\\tshort _ lookupString size - (lookupString size // 4 max: 3) max: 2.\\n\\tlong _ lookupString size + (lookupString size // 4 max: 3).\\n\\n\\t\\\"First assemble candidates for detailed scoring\\\"\\n\\tcandidates _ OrderedCollection new.\\n\\tself allSymbolTablesDo: [:s | (((ss _ s size) >= short\\t\\\"not too short\\\"\\n\\t\\t\\tand: [ss <= long\\t\\t\\t\\\"not too long\\\"\\n\\t\\t\\t\\t\\tor: [(s at: 1) = first]])\\t\\\"well, any length OK if starts w/same letter\\\"\\n\\t\\t\\tand: [s numArgs = numArgs])\\t\\\"and numArgs is the same\\\"\\n\\t\\t\\tifTrue: [candidates add: s]].\\n\\n\\t\\\"Then further prune these by correctAgainst:\\\"\\n\\tbest _ lookupString correctAgainst: candidates.\\n\\t((misspelled last ~~ $:) and: [misspelled size > 1]) ifTrue: [\\n\\t\\tbinary _ misspelled, ':'.\\t\\t\\\"try for missing colon\\\"\\n\\t\\tSymbol hasInterned: binary ifTrue: [:him | best addFirst: him]].\\n\\t^ best! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'ar 9/27/2005 20:01'!\\nrehash\\t\\t\\\"Symbol rehash\\\"\\n\\t\\\"Rebuild the hash table, reclaiming unreferenced Symbols.\\\"\\n\\n\\tSymbolTable := WeakSet withAll: self allSubInstances.\\n\\tNewSymbols := WeakSet new.! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 09:04'!\\nshutDown: aboutToQuit\\n\\n\\tSymbolTable addAll: NewSymbols.\\n\\tNewSymbols _ WeakSet new.! !\\nKeyboardInputInterpreter subclass: #SymbolInputInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!SymbolInputInterpreter methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 16:10'!\\nnextCharFrom: sensor firstEvt: evtBuf\\n\\n\\t| keyValue |\\n\\tkeyValue := evtBuf third.\\n\\tevtBuf fifth > 1 ifTrue: [^ keyValue asCharacter macToSqueak].\\n\\t^ (self symbolKeyValueToUnicode: keyValue) asCharacter.\\n! !\\n\\n!SymbolInputInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 11/8/2004 18:53'!\\nsymbolKeyValueToUnicode: keyValue\\n\\n\\tkeyValue = 127 ifTrue: [^ 127].\\n\\tkeyValue < 32 ifTrue: [^ keyValue].\\n\\tkeyValue > 255 ifTrue: [^ 0].\\n\\t^ #(0 0 0 0 0 0 0 0 0 61472 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 61472 61473 61474 61475 61476 61477 61478 61479 61480 61481 61482 61483 61484 61485 61486 61487 61488 61489 61490 61491 61492 61493 61494 61495 61496 61497 61498 61499 61500 61501 61502 61503 61504 61505 61506 61507 61508 61509 61510 61511 61512 61513 61514 61515 61516 61517 61518 61519 61520 61521 61522 61523 61524 61525 61526 61527 61528 61529 61530 61531 61532 61533 61534 61535 61536 61537 61538 61539 61540 61541 61542 61543 61544 61545 61546 61547 61548 61549 61550 61551 61552 61553 61554 61555 61556 61557 61558 61559 61560 61561 61562 61563 61564 61565 61566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 61601 61602 61603 61604 61605 61606 61607 61608 61609 61610 61611 61612 61613 61614 61615 61616 61617 61618 61619 61620 61621 61622 61623 61624 61625 61626 61627 61628 61629 61630 61631 61632 61633 61634 61635 61636 61637 61638 61639 61640 61641 61642 61643 61644 61645 61646 61647 61648 61649 61650 61651 61652 61653 61654 61655 61656 61657 61658 61659 61660 61661 61662 61663 61664 61665 61666 61667 61668 61669 61670 61671 61672 61673 61674 61675 61676 61677 61678 61679 0 61681 61682 61683 61684 61685 61686 61687 61688 61689 61690 61691 61692 61693 61694 0) at: keyValue + 1.\\n! !\\nTileMorph subclass: #SymbolListTile\\n\\tinstanceVariableNames: 'choices dataType'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SymbolListTile commentStamp: '<historical>' prior: 0!\\nInstances of SymbolListTile are literal tiles whose literals are choosable from a finite list.!\\n\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'yo 7/2/2004 21:27'!\\nliteral: anObject\\n\\t\\\"Set the receiver's literal as indicated\\\"\\n\\tself flag: #yo.\\n\\n\\tliteral _ anObject asSymbol.\\n\\tself updateLiteralLabel.\\n\\\"\\n\\tkey _ Vocabulary eToyVocabulary translationKeyFor: literal.\\n\\tkey isNil ifFalse: [literal _ key].\\n\\\"\\n\\tself flag: #deferred. \\\"The below formerly was necessary but now is problematical, leading to low-space condition etc. May need to revisit, since as I comment this out now I am uncertain what if anything this may break\\\"\\n\\t\\\"self labelMorph informTarget\\\"\\n\\n! !\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'tak 12/6/2004 01:58'!\\noptions\\n\\t^ {self choices. self choices\\n\\t\\tcollect: [:each | ScriptingSystem helpStringForOperator: literal]}! !\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'tak 12/7/2004 14:42'!\\nvalue: anObject \\n\\tself acceptNewLiteral: anObject! !\\n\\n\\n!SymbolListTile methodsFor: 'customevents-accessing' stamp: 'nk 7/21/2003 22:02'!\\ndataType\\n\\t^dataType! !\\n\\n\\n!SymbolListTile methodsFor: 'customevents-initialization' stamp: 'nk 7/21/2003 22:14'!\\nupdateChoices\\n\\tchoices _ (Vocabulary vocabularyNamed: dataType) choices.\\n\\t(choices includes: literal) ifFalse: [ literal _ choices first. self changed ]! !\\n\\n\\n!SymbolListTile methodsFor: 'event handling' stamp: 'sw 12/3/2001 21:30'!\\nhandlesMouseDown: evt\\n\\t\\\"Answer whether the receiver handles mouse-down\\\"\\n\\n\\t^ true! !\\n\\n!SymbolListTile methodsFor: 'event handling' stamp: 'sw 11/16/2001 07:31'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t\\\"Answer whether a plain mouse click on aSubmorph, a text-edit-capable thing, should result in a text selection there\\\"\\n\\n\\t^ false! !\\n\\n\\n!SymbolListTile methodsFor: 'events-processing' stamp: 'sw 12/3/2001 20:45'!\\nmouseDownPriority\\n\\t\\\"Higher-priority than parts donor, so that the tile can offer a popup even when it is in a larger structure, such as a PhraseTileMorph, that itself behaves as a parts donor\\\"\\n\\n\\t^ 75! !\\n\\n\\n!SymbolListTile methodsFor: 'initialization' stamp: 'sw 10/30/2000 09:04'!\\nchoices: choiceList dataType: aDataType\\n\\t\\\"Initialize the receiver with the given choice-list and data type\\\"\\n\\n\\tchoices _ choiceList.\\n\\tdataType _ aDataType.\\n\\tliteral _ choiceList first! !\\n\\n!SymbolListTile methodsFor: 'initialization' stamp: 'tak 12/6/2004 01:38'!\\ninitialize\\n\\tsuper initialize.\\n\\tliteral _ #nothing! !\\n\\n\\n!SymbolListTile methodsFor: 'misc' stamp: 'sw 11/6/2001 13:30'!\\nsetLiteralInitially: anObject\\n\\t\\\"Establish the initial literal. Get the label correct, but do *not* send the value back to the target via the setter (unlike #literal:)\\\"\\n\\n\\tliteral _ anObject ifNotNil: [anObject asSymbol].\\n\\tself updateLiteralLabel! !\\n\\n\\n!SymbolListTile methodsFor: 'player viewer' stamp: 'yo 1/12/2005 14:28'!\\nupdateLiteralLabel\\n\\t\\\"Update the wording emblazoned on the tile, if needed. Copied down, for jimmying, unfortunately\\\"\\n\\n\\t| myLabel |\\n\\t(myLabel _ self labelMorph) ifNil: [^ self].\\n\\tmyLabel useSymbolFormat.\\n\\tmyLabel acceptValue: literal asString.\\n\\tself changed.! !\\n\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'yo 1/12/2005 14:38'!\\nacceptNewLiteral: aLiteral\\n\\t\\\"Accept the new literal\\\"\\n\\n\\tself labelMorph useSymbolFormat.\\n\\tself literal: aLiteral.\\n\\tself adjustHelpMessage.\\n\\tself acceptNewLiteral. \\\"so tile scriptor can recompile if necessary\\\"\\n\\tself labelMorph informTarget\\n! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 3/10/2004 23:24'!\\nadjustHelpMessage\\n\\t\\\"Adjust the help message to reflect the new literal\\\"\\n\\n\\t(ScriptingSystem helpStringOrNilForOperator: literal) ifNotNilDo:\\n\\t\\t[:aString |\\n\\t\\t\\tself labelMorph setBalloonText: aString]! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 12/21/2003 00:07'!\\nchoices\\n\\t\\\"Answer the list of current choices for the receiver's symbol\\\"\\n\\n\\tdataType == #ScriptName ifTrue: \\\"Backward compatibility with old tiles\\\"\\n\\t\\t[^ ActiveWorld presenter allKnownUnaryScriptSelectors].\\n\\t^ choices! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 1/4/2005 00:16'!\\nofferAllChoicesInAPopUp\\n\\t\\\"Retained in deference to pre-existing content that may have event handlers that send this message.\\\"\\n\\n\\t! !\\n\\n\\n!SymbolListTile methodsFor: 'private' stamp: 'yo 1/12/2005 14:28'!\\nline1: line1\\n\\t\\\"Emblazon the receiver with the requested label. If the receiver already has a label, make the new label be of the same class\\\"\\n\\n\\tsuper line1: line1.\\n\\tself labelMorph useSymbolFormat! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSymbolListTile class\\n\\tinstanceVariableNames: ''!\\n\\n!SymbolListTile class methodsFor: 'customevents-updating' stamp: 'nk 7/21/2003 22:16'!\\nupdateAllTilesForVocabularyNamed: aVocabularyName\\n\\t\\\"The choices in the Vocabulary named aVocabularyName may have changed.\\n\\tUpdate my subinstances if necessary to reflect the changes.\\\"\\n\\n\\t (self allSubInstances select: [ :ea | ea dataType = aVocabularyName ])\\n\\t\\tdo: [ :ea | ea updateChoices ] ! !\\nDataType subclass: #SymbolListType\\n\\tinstanceVariableNames: 'symbols'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n!SymbolListType commentStamp: 'sw 1/6/2005 17:52' prior: 0!\\nA type whose values range across a finite set of symbols, which are held in the \\\"symbols\\\" instance variable.!\\n\\n\\n!SymbolListType methodsFor: 'initial value' stamp: 'sw 12/3/2001 19:27'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ self choices first! !\\n\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'sw 12/3/2001 19:14'!\\nchoices\\n\\t\\\"answer the list of choices to offer as variant values\\\"\\n\\n\\t^ symbols copy! !\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'sw 1/6/2005 17:24'!\\nrepresentsAType\\n\\t\\\"Answer whether this vocabulary represents an end-user-sensible data type\\\"\\n\\n\\t^ #(BorderStyle ButtonPhase TrailStyle) includes: vocabularyName! !\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nsymbols: symbolList\\n\\t\\\"Set the receiver's list of symbols as indicated\\\"\\n\\n\\tsymbols := symbolList! !\\n\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 1/12/2005 10:13'!\\naffordsCoercionToBoolean\\n\\t\\\"Answer true if a tile of this data type, when dropped into a pane that demands a boolean, could plausibly be expanded into a comparison (of the form frog < toad or frog = toad) to provide a boolean expression\\\"\\n\\n\\t\\\"Formerly this had been disabled (9/27/01) but from today's perspective I don't see any reason to disable it...\\\"\\n\\n\\t^ true! !\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 12/3/2001 19:15'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t| aTile choices |\\n\\taTile _ SymbolListTile new choices: (choices _ self choices) dataType: self vocabularyName.\\n\\taTile addArrows.\\n\\taTile setLiteral: choices first.\\n\\t^ aTile! !\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 12/3/2001 21:00'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ SymbolListTile new choices: self choices dataType: self vocabularyName\\n! !\\nClassTestCase subclass: #SymbolTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Text'!\\n!SymbolTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class Symbol. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'md 9/6/2005 20:02'!\\ntestAsMutator\\n\\n\\tself assert: #x asMutator = #x:.\\n\\tself assert: #x asMutator isSymbol! !\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'sd 6/5/2005 09:29'!\\ntestCapitalized\\n\\n\\t| uc lc |\\t\\t\\n\\tuc := #MElViN.\\n\\tlc := #mElViN.\\n\\tself assert: lc capitalized = uc.\\n\\tself assert: uc capitalized = uc.\\n! !\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'sd 6/5/2005 09:29'!\\ntestWithFirstCharacterDownshifted\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := #MElViN.\\n\\tlc := #mElViN.\\n\\tempty := #' '.\\n\\tself assert: uc withFirstCharacterDownshifted = lc.\\n\\tself assert: lc withFirstCharacterDownshifted = lc.\\n\\t\\n! !\\n\\n\\n!SymbolTest methodsFor: 'as yet unclassified' stamp: 'md 2/16/2006 17:17'!\\ntestNumArgs2\\n \\\"TODO: need to be extended to support shrinking and for selectors like #+ \\\" \\n\\t\\n\\tself assert: (#test numArgs: 0) = #test.\\n\\tself assert: (#test numArgs: 1) = #test:.\\n\\tself assert: (#test numArgs: 2) = #test:with:.\\n\\tself assert: (#test numArgs: 3) = #test:with:with:.\\n\\t\\n\\n\\tself assert: (#test: numArgs: 0) = #test:.\\n\\tself assert: (#test: numArgs: 1) = #test:.\\n\\tself assert: (#test: numArgs: 2) = #test:with:.\\n\\tself assert: (#test: numArgs: 3) = #test:with:with:.\\n\\t\\n\\tself assert: (#test:with: numArgs: 0) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 1) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 2) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 3) = #test:with:with:.\\n\\tself assert: (#test:with: numArgs: 4) = #test:with:with:with:.\\n\\t\\n\\tself assert: (#test:with:with: numArgs: 0) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 1) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 2) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 3) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 4) = #test:with:with:with:.! !\\nObject subclass: #SyntaxAttribute\\n\\tinstanceVariableNames: 'color emphasis attributeList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Support'!\\n!SyntaxAttribute commentStamp: '<historical>' prior: 0!\\nRepresents a color and possibly a style attribute to be applied to a syntactic element for pretty-printing. The attributeList inst var is a cache.!\\n\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/17/1999 15:04'!\\nattributeList\\n\\t\\\"Answer a list of text attributes that characterize the receiver\\\"\\n\\tattributeList ifNil:\\n\\t\\t[attributeList _ OrderedCollection new: 2.\\n\\t\\tcolor ifNotNil: [attributeList add: (TextColor color: color)].\\n\\t\\temphasis ifNotNil: [attributeList add: (TextEmphasis perform: emphasis)]].\\n\\t^ attributeList! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'djp 11/7/1999 14:52'!\\ncolor\\n\\n\\t^ color! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/16/1999 16:21'!\\ncolor: aTextColor\\n\\tcolor _ aTextColor.\\n\\tattributeList _ nil! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'djp 11/7/1999 14:52'!\\nemphasis\\n\\n\\t^ emphasis! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/16/1999 16:22'!\\nemphasis: aTextEmphasis\\n\\temphasis _ aTextEmphasis.\\n\\tattributeList _ nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxAttribute class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxAttribute class methodsFor: 'as yet unclassified' stamp: 'sw 11/16/1999 12:01'!\\ncolor: aColor emphasis: anEmphasis\\n\\t^ self new color: aColor; emphasis: anEmphasis; yourself! !\\nStringHolder subclass: #SyntaxError\\n\\tinstanceVariableNames: 'class selector category debugger doitFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Debugger'!\\n!SyntaxError commentStamp: '<historical>' prior: 0!\\nI represent syntax error report for syntax errors encountered when filing in class descriptions from a non-interactive source such as an external file. As a StringHolder, the string to be viewed is the method code or expression containing the error.\\n\\nThe user may fix the error and accept the method to continue the fileIn.\\n!\\n\\n\\n!SyntaxError methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:27'!\\ncategory: aSymbol\\n\\t\\\"Record the message category of method being compiled. This is used when the user corrects the error and accepts.\\\"\\n\\n\\tcategory := aSymbol.\\n! !\\n\\n!SyntaxError methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:30'!\\nsetClass: aClass code: aString debugger: aDebugger doitFlag: flag\\n\\n\\t| types printables badChar |\\n\\tclass := aClass.\\n\\tdebugger := aDebugger.\\n\\tselector := aClass parserClass new parseSelector: aString.\\n\\ttypes := Scanner classPool at: #TypeTable.\\t\\\"dictionary\\\"\\n\\tprintables := '!!@#$%&*-_=+<>{}?/\\\\,\\U00b7\\U00a3\\U00a2\\U00a7\\U00b6\\U00aa\\U00ba\\U0096\\U0097\\U0093\\U0091\\U0094\\U0092\\U0085\\U00da\\U00e6\\U00da\\U00af\\U00d7\\U00bf\\U00ab\\U00bb`~`' asSet.\\n\\tbadChar := aString detect: [:aChar | (types at: aChar asciiValue ifAbsent: [#xLetter]) == #xBinary and: [\\n\\t\\t\\t(printables includes: aChar) not]] ifNone: [nil].\\n\\tcontents := badChar \\n\\t\\tifNil: [aString]\\n\\t\\tifNotNil: ['<<<This string contains a character (ascii value ', \\n\\t\\t\\tbadChar asciiValue printString,\\n\\t\\t\\t') that is not normally used in code>>> ', aString].\\n\\tcategory ifNil: [category := aClass organization categoryOfElement: selector].\\n\\tcategory ifNil: [category := ClassOrganizer default].\\n\\tdoitFlag := flag! !\\n\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'RAA 12/1/2000 14:24'!\\ndebug\\n\\t\\\"Show the stack of the process leading to this syntax editor, typically showing the stack of the compiler as called from fileIn.\\\"\\n\\n\\tdebugger openFullNoSuspendLabel: 'Stack of the Syntax Error'.\\n\\tSmalltalk isMorphic ifFalse: [Processor terminateActive].\\n! !\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'jm 5/3/1998 14:22'!\\nlistMenu: aMenu\\n\\n\\t^ aMenu labels:\\n'proceed\\ndebug calling process\\nbrowse full'\\n\\tlines: #()\\n\\tselections: #(proceed debug browseMethodFull)\\n! !\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'di 5/5/1998 00:06'!\\nproceed\\n\\t\\\"The user has has edited and presumably fixed the syntax error and the filein can now proceed.\\\"\\n\\n\\tdebugger proceed: self topView.\\n! !\\n\\n\\n!SyntaxError methodsFor: 'message list' stamp: 'tk 4/19/1999 08:08'!\\nlist\\n\\t\\\"Answer an array of one element made up of the class name, message category, and message selector in which the syntax error was found. This is the single item in the message list of a view/browser on the receiver.\\\"\\n\\n\\tselector ifNil: [^ Array with: (class name, ' ', category, ' ', '<none>')].\\n\\t^ Array with: (class name, ' ', category, ' ', selector)\\n! !\\n\\n!SyntaxError methodsFor: 'message list' stamp: 'jm 5/3/1998 13:48'!\\nlistIndex\\n\\t\\\"There is always exactly one element in my list and it is always selected.\\\"\\n\\n\\t^ 1\\n! !\\n\\n\\n!SyntaxError methodsFor: 'other' stamp: 'di 10/9/1998 16:36'!\\ncontents: aString notifying: aController\\n\\t\\\"Compile the code in aString and notify aController of any errors. If there are no errors, then automatically proceed.\\\"\\n\\n\\tdoitFlag\\n\\tifTrue: [Compiler new evaluate: aString in: nil to: nil\\n\\t\\t\\t\\t\\t\\tnotifying: aController ifFail: [^ false]]\\n\\tifFalse: [(class compile: aString classified: category\\n\\t\\t\\t\\t\\t\\tnotifying: aController) ifNil: [^ false]].\\n\\n\\taController hasUnacceptedEdits: false.\\n\\tself proceed! !\\n\\n!SyntaxError methodsFor: 'other' stamp: 'sd 11/20/2005 21:27'!\\nnotify: error at: location in: source\\n\\t\\\"Open a syntax error view, inserting the given error message into the given source at the given location. This message is sent to the 'requestor' when the parser or compiler finds a syntax error.\\\"\\n\\n\\t| aClass aString |\\n\\taClass := thisContext sender receiver encoder classEncoding.\\n\\taString :=\\n\\t\\tsource contents\\n\\t\\t\\tcopyReplaceFrom: location\\n\\t\\t\\tto: location - 1\\n\\t\\t\\twith: error.\\n\\tself setClass: aClass\\n\\t\\tcode: aString\\n\\t\\tdebugger: (Debugger context: thisContext)\\n\\t\\tdoitFlag: false.\\n\\tself class open: self.\\n! !\\n\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:15'!\\nselectedClass\\n\\t\\\"Answer the class in which the syntax error occurred.\\\"\\n\\n\\t^ class\\n! !\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:33'!\\nselectedClassOrMetaClass\\n\\t\\\"Answer the class of the method being compiled.\\\"\\n\\n\\t^ class\\n! !\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:17'!\\nselectedMessageName\\n\\t\\\"Answer the selector of the method being compiled.\\\"\\n\\n\\t^ selector\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxError class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nbuildMVCViewOn: aSyntaxError\\n\\t\\\"Answer an MVC view on the given SyntaxError.\\\"\\n\\n\\t| topView aListView aCodeView |\\n\\ttopView := StandardSystemView new\\n\\t\\tmodel: aSyntaxError;\\n\\t\\tlabel: 'Syntax Error';\\n\\t\\tminimumSize: 380@220.\\n\\n\\taListView := PluggableListView on: aSyntaxError\\n\\t\\tlist: #list\\n\\t\\tselected: #listIndex\\n\\t\\tchangeSelected: nil\\n\\t\\tmenu: #listMenu:.\\n\\taListView window: (0@0 extent: 380@20).\\n\\ttopView addSubView: aListView.\\n\\n\\taCodeView := PluggableTextView on: aSyntaxError\\n\\t\\ttext: #contents\\n\\t\\taccept: #contents:notifying:\\n\\t\\treadSelection: #contentsSelection\\n\\t\\tmenu: #codePaneMenu:shifted:.\\n\\taCodeView window: (0@0 extent: 380@200).\\n\\ttopView addSubView: aCodeView below: aListView.\\n\\n\\t^ topView\\n! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nbuildMorphicViewOn: aSyntaxError\\n\\t\\\"Answer an Morphic view on the given SyntaxError.\\\"\\n\\t| window |\\n\\twindow := (SystemWindow labelled: 'Syntax Error') model: aSyntaxError.\\n\\n\\twindow addMorph: (PluggableListMorph on: aSyntaxError list: #list\\n\\t\\t\\tselected: #listIndex changeSelected: nil menu: #listMenu:)\\n\\t\\tframe: (0@0 corner: 1@0.15).\\n\\n\\twindow addMorph: (PluggableTextMorph on: aSyntaxError text: #contents\\n\\t\\t\\taccept: #contents:notifying: readSelection: #contentsSelection\\n\\t\\t\\tmenu: #codePaneMenu:shifted:)\\n\\t\\tframe: (0@0.15 corner: 1@1).\\n\\n\\t^ window openInWorldExtent: 380@220! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'di 9/14/2001 07:46'!\\nerrorInClass: aClass withCode: codeString doitFlag: doit\\n\\t\\\"Open a view whose model is a syntax error. The error occurred when trying to add the given method code to the given class.\\\"\\n\\n\\tself open:\\n\\t\\t(self new setClass: aClass\\n\\t\\t\\tcode: codeString\\n\\t\\t\\tdebugger: (Debugger context: thisContext)\\n\\t\\t\\tdoitFlag: doit).\\n! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nopen: aSyntaxError\\n\\t\\\"Answer a standard system view whose model is an instance of me.\\\"\\n\\t| topView |\\n\\t<primitive: 19> \\\"Simulation guard\\\"\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue:\\n\\t\\t\\t[self buildMorphicViewOn: aSyntaxError.\\n\\t\\t\\tProject spawnNewProcessIfThisIsUI: Processor activeProcess.\\n\\t\\t\\t^ Processor activeProcess suspend].\\n\\ttopView := self buildMVCViewOn: aSyntaxError.\\n\\ttopView controller openNoTerminateDisplayAt: Display extent // 2.\\n\\tCursor normal show.\\n\\tProcessor activeProcess suspend.\\n! !\\nNotification subclass: #SyntaxErrorNotification\\n\\tinstanceVariableNames: 'inClass code category doitFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Extensions'!\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:17'!\\ncategory\\n\\t^category! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:11'!\\ndoitFlag\\n\\t^doitFlag! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:10'!\\nerrorClass\\n\\t^inClass! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:10'!\\nerrorCode\\n\\t^code! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:14'!\\nmessageText\\n\\t^ super messageText\\n\\t\\tifNil: [messageText := code]! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:15'!\\nsetClass: aClass category: aCategory code: codeString doitFlag: aBoolean\\n\\tinClass := aClass.\\n\\tcategory := aCategory.\\n\\tcode := codeString.\\n\\tdoitFlag := aBoolean ! !\\n\\n\\n!SyntaxErrorNotification methodsFor: 'exceptionDescription' stamp: 'ar 9/27/2005 19:13'!\\ndefaultAction\\n\\t^ToolSet debugSyntaxError: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxErrorNotification class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxErrorNotification class methodsFor: 'exceptionInstantiator' stamp: 'ar 9/27/2005 19:15'!\\ninClass: aClass category: aCategory withCode: codeString doitFlag: doitFlag \\n\\t^ (self new\\n\\t\\tsetClass: aClass\\n\\t\\tcategory: aCategory \\n\\t\\tcode: codeString\\n\\t\\tdoitFlag: doitFlag) signal! !\\nAlignmentMorph subclass: #SyntaxMorph\\n\\tinstanceVariableNames: 'parseNode markerMorph'\\n\\tclassVariableNames: 'AllSpecs ContrastFactor DownRightArrow SelfTile SizeScaleFactor'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Tile Scriptors'!\\n!SyntaxMorph commentStamp: '<historical>' prior: 0!\\nA single class of morph that holds any piece of Smalltalk syntax, and allows it to be a tile. Tiles can be dragged in or out of a method. \\n\\nIn the message list pane of a Browser, choose 'tile scriptor'. Bring up a second one to steal parts from. If you use a Protocol Browser, and choose tiles, there will be two buttons that bring up menus with many tiles on them.\\n\\nClicking multiple times selects enclosing phrases of code. Dragging lets you take away a copy. Any tile may be replaced by dropping on it. Shift-click to edit the text of any tile. Change variable and message names, but do not change the part-of-speech (objects to selector).\\n\\nEach SyntaxMorph holds a ParseNode. After editing, the parseNode is only good as a part-of-speech indicator. Only the Class of a parseNode is important. It's state is not kept up to date with the tile edits (but maybe it should be). (For MessageNodes, whether the receiver slot is nil is significant.)\\n\\nThe correspondence between SyntaxMorphs and parseNodes in the real parse tree is not one-to-one. Several extra levels of SyntaxMorph were added as aligners to make the horizontal and vertical layout right. These sometimes have nil for the parseNode.\\n\\nWhen accept the method, we pass over the tree of SyntaxMorphs, gathering their printStrings and inserting punctuation. See (SyntaxMorph>>printOn:indent:). We send the result to the compiler. (We do not use the parse tree we already have.)\\n\\nTo turn on type checking: \\nPreferences enable: #eToyFriendly\\nor for testing: World project projectParameters at: #fullCheck put: true.\\n\\nColors of tiles: Each tile has a current color (inst car color) and a deselectedColor (a property). The deselectedColor may be governed by the part of speech, or not. (translateColor: is only used when a tile is created, to set deselectedColor.) From deselectedColor (set by #setDeselectedColor), the color changes to:\\n\\tlightBrown when selected (not the submorphs) in #select\\n\\ttranslucent when held in the hand (allMorphs) in #lookTranslucent\\n\\tgreen when a drop target (allMorphs) (change the owners back) #dropColor, \\n\\t\\t#trackDropZones \\ndeselectedColor is moderated by the darkness setting, #scaleColorByUserPref:. (as it is put into color in #color:)\\n\\nCode to produce an individual tile is: \\n\\t(SyntaxMorph new) attachTileForCode: '''abc''' nodeType: LiteralNode.\\nsee offerTilesMenuFor:in: for many other phrases that produce useful tiles.\\n\\nAssignmentNode: If three submorphs, is a statement, and is a noun. If one submorph, is just the left arrow. When dropped on a variable, it creates a new assignment statement. !\\n\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 8/21/2001 09:36'!\\nactualObject\\n\\t| sub |\\n\\t\\\"Who is self in these tiles? Usually a Player.\\\"\\n\\n\\n\\t(self nodeClassIs: LiteralVariableNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t\\\"Need to decompile here for odd synonyms of 'self' ?\\\"\\n\\t\\t^ Compiler evaluate: sub contents for: Player logged: false].\\n\\n\\t(self nodeClassIs: VariableNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t^ References at: (self cleanUpString: sub) asSymbol ifAbsent: [nil]].\\n\\n\\t(self nodeClassIs: LiteralNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t^ Compiler evaluate: sub contents for: nil logged: false].\\n\\n\\t(sub _ self findA: SyntaxMorph) ifNil: [^ nil].\\n\\t^ sub actualObject\\t\\\"receiver\\\"! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/20/2001 13:21'!\\nargumentNodes\\n\\t\\\"Return a collection of this message's argument nodes. \\\"\\n\\n\\t| cls coll rec |\\n\\tparseNode ifNil: [^ #()].\\n\\tcls _ parseNode class.\\n\\tcls == SelectorNode ifTrue: [^ #()].\\n\\tcls == KeyWordNode ifTrue: [^ #()].\\n\\n\\tcoll _ OrderedCollection new.\\n\\trec _ self receiverNode.\\n\\tsubmorphs do: [:sub | \\n\\t\\t(sub isSyntaxMorph and: [sub ~~ rec]) ifTrue: [\\n\\t\\t\\tsub isNoun ifTrue: [coll addLast: sub]\\t\\\"complete arg\\\"\\n\\t\\t\\t\\tifFalse: [coll _ coll, sub argumentNodes]]].\\t\\\"MessagePartNode, MessageNode with no receiver\\\"\\n\\t^ coll! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/24/1999 17:57'!\\nballoonText\\n\\n\\t^(('Value: ',(self getCurrentValue ifNil: [^nil])) \\n\\t\\twithNoLineLongerThan: 35) truncateWithElipsisTo: 300! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'di 12/13/2000 15:25'!\\nborderColor: colorOrSymbolOrNil\\n\\n\\tborderColor = colorOrSymbolOrNil ifFalse: [\\n\\t\\tborderColor _ colorOrSymbolOrNil.\\n\\t\\tself bounds area < 40000\\n\\t\\t\\tifTrue: [self invalidRect: self bounds]\\n\\t\\t\\tifFalse: [(self bounds areasOutside: (self bounds insetBy: self borderWidth))\\n\\t\\t\\t\\t\\t\\tdo: [:r | self invalidRect: r]]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 4/4/2001 12:36'!\\ncleanUpString: stringSubMorph\\n\\n\\t| style rawData |\\n\\t^ stringSubMorph \\n\\t\\tvalueOfProperty: #syntacticallyCorrectContents \\n\\t\\tifAbsent: [\\n\\t\\t\\tstyle _ stringSubMorph valueOfProperty: #syntacticReformatting.\\n\\t\\t\\trawData _ stringSubMorph contents.\\n\\t\\t\\t (#(unary tempVariableDeclaration blockarg2 methodHeader1 tempVariable variable) includes: style) ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: nil.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #keywordGetz ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: 'Getz:'.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #keywordSetter ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: 'set ',rawData appending: ':'.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #unaryGetter ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: 'get ',rawData appending: nil.\\n\\t\\t\\t].\\n\\t\\t\\t(#(keyword2 methodHeader2) includes: style) ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: ':'.\\n\\t\\t\\t].\\n\\t\\t\\trawData\\n\\t\\t]\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 7/19/2001 20:04'!\\ncolor: aColorOrSymbol\\n\\n\\t| deselectedColor cc |\\n\\taColorOrSymbol isColor ifTrue: [\\n\\t\\tself valueOfProperty: #deselectedColor ifAbsent: [\\\"record my color the first time\\\"\\n\\t\\t\\tself setProperty: #deselectedColor toValue: aColorOrSymbol.\\n\\t\\t\\t^ super color: (self scaleColorByUserPref: aColorOrSymbol)].\\n\\t\\t^ super color: aColorOrSymbol].\\n\\n\\tdeselectedColor _ self valueOfProperty: #deselectedColor ifAbsent: [nil].\\n\\tdeselectedColor ifNotNil: [^ super color: (self scaleColorByUserPref: deselectedColor)].\\n\\n\\taColorOrSymbol == #comment ifTrue: [^ self color: Color blue lighter].\\n\\tSyntaxMorph noTileColor ifTrue: [\\t\\\"override\\\"\\n\\t\\t^ self color: Color transparent].\\t\\\"Fix this to be real color!!\\\"\\n\\n\\t(cc _ self class translateColor: aColorOrSymbol) isColor\\n\\t\\tifTrue: [^ self color: cc]\\n\\t\\tifFalse: [Transcript show: aColorOrSymbol, ' needs to be handled in translateColor:'; cr.\\n\\t\\t\\t^ self color: Color transparent].\\t\\\"help!!\\\"! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/20/2001 12:43'!\\ndissectMessage\\n\\t\\\"I am a MessageNode. Return {receiverNode or nil, selector, (keyword nodes), (argument nodes)}. Ignore all spacing morphs.\\\"\\n\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'sw 2/3/2001 01:40'!\\neditor\\n\\t\\\"In parallel with the interface for text morphs, we respond to this, but in our case we are our own editor\\\"\\n\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/19/2001 15:39'!\\nenclosingPane\\n\\t\\\"The object that owns this script layout\\\"\\n\\n\\t| oo higher |\\n\\too _ self owner.\\n\\t[higher _ oo isSyntaxMorph.\\n\\thigher _ higher or: [oo class == TransformMorph].\\n\\thigher _ higher or: [oo class == TwoWayScrollPane].\\n\\thigher ifFalse: [^ oo].\\n\\thigher] whileTrue: [oo _ oo owner].\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/7/2001 16:13'!\\ngetCurrentValue\\n\\n\\tparseNode ifNil: [^nil].\\n\\tparseNode class == Symbol ifTrue: [^nil].\\t\\\"special\\\"\\n\\t^parseNode currentValueIn: self hostContext! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'dgd 2/22/2003 18:48'!\\nmessageNode\\n\\t\\\"Return the enclosing messageNode that is the full message. It has a receiver.\\\"\\n\\n\\t^self orOwnerSuchThat: [:oo | oo receiverNode notNil]! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/15/1999 16:23'!\\nparseNode\\n\\t\\n\\t^parseNode\\n\\t\\t\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/15/1999 16:11'!\\nparseNode: x\\n\\t\\n\\tparseNode _ x\\n\\t\\t\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'di 11/17/2000 08:07'!\\nparsedInClass\\n\\n\\t^ self rootTile parseNode encoder classEncoding! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/15/2000 14:39'!\\nparsedInClass: x\\n\\n\\tself parsedInClass == x ifFalse: [self error: 'inconsistent value']! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/25/2001 11:28'!\\nreadOut\\n\\t\\\"Find and return an UpdatingStringMorph, possibly in a NumericReadoutTile\\\"\\n\\n\\t^ ((self findA: NumericReadoutTile) ifNil: [^ nil]) findA: UpdatingStringMorph! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 7/23/2001 18:04'!\\nreceiverNode\\n\\t\\\"If I am (have) a MessageNode, return the node of the receiver. Watch out for foolish noise words.\\\"\\n\\n\\tparseNode class == MessageNode ifFalse: [^ nil].\\n\\tparseNode receiver ifNil: [^ nil].\\n\\tsubmorphs do: [:ss | \\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode ifNotNil: [\\\"not noise word\\\"\\n\\t\\t\\t\\tss isNoun ifTrue: [^ ss] \\n\\t\\t\\t\\t\\tifFalse: [^ nil \\\"found selector\\\"]]]].\\n\\t^ nil! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/23/2001 00:27'!\\nreceiverObject\\n\\t\\\"Return some object that could be the receiver to me (a selector). Either the actual object who is the receiver in this message, or a guy of the right class.\\\"\\n\\n\\t| rec value mm |\\n\\t(rec _ owner) isSyntaxMorph ifFalse: [^ nil].\\n\\trec _ rec receiverNode.\\n\\trec ifNil: [(rec _ owner owner) isSyntaxMorph ifFalse: [^ nil].\\n\\t\\t\\t\\trec _ rec receiverNode].\\t\\n\\trec ifNil: [(rec _ owner owner owner) isSyntaxMorph ifFalse: [^ nil].\\n\\t\\t\\t\\trec _ rec receiverNode].\\n\\trec isSelfTile ifTrue: [\\n\\t\\t^ ((mm _ self containingWindow model) respondsTo: #targetObject) \\n\\t\\t\\tifTrue: [mm targetObject]\\n\\t\\t\\tifFalse: [mm selectedClassOrMetaClass new]].\\n\\tvalue _ rec ifNotNil: [rec try].\\n\\tvalue class == Error ifTrue: [\\n\\t\\tvalue _ Vocabulary instanceWhoRespondsTo: self selector].\\n\\t^ value! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 1/13/2001 20:08'!\\nrename: newSelector\\n\\t| keywords mainSel list last |\\n\\t\\\"Attempt to change the name as listed in my tiles. Can change the number of argumtents. MethodNode (SelectorNode (SelectorNode (string))) or MethodNode (SelectorNode (SelectorNode (string) TempVarNode() SelectorNode (string) TempVarNode()))\\\"\\n\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile rename: newSelector \\\"always do at the root\\\"].\\n\\n\\tkeywords _ newSelector keywords.\\n\\tmainSel _ self findA: SelectorNode.\\n\\tlist _ mainSel submorphs select: [:mm | \\n\\t\\tmm isSyntaxMorph and: [mm parseNode class == SelectorNode]].\\n\\t1 to: (list size min: keywords size) do: [:ind |\\n\\t\\t((list at: ind) findA: UpdatingStringMorph) contents: (keywords at: ind)].\\n\\tkeywords size + 1 to: list size do: [:ind | \\\"removing keywords\\\"\\n\\t\\t[last _ mainSel submorphs last.\\n\\t\\t (last isSyntaxMorph and: [last parseNode class == TempVariableNode])] whileFalse: [\\n\\t\\t\\t\\tlast delete].\\n\\t\\t[last _ mainSel submorphs last.\\n\\t\\t (last isSyntaxMorph and: [last parseNode class == SelectorNode])] whileFalse: [\\n\\t\\t\\t\\tlast delete].\\t\\\"the TempVariableNode and others\\\"\\n\\t\\tmainSel submorphs last delete.\\t\\\"the SelectorNode\\\"\\n\\t\\t].\\n\\tlist size + 1 to: keywords size do: [:ind | \\\"adding keywords\\\"\\n\\t\\t\\\"add a SelectorNode, add a spacer, add a TempVarNode\\\"\\n\\t\\tmainSel addToken: (keywords at: ind) type: #keyword1 \\n\\t\\t\\ton: (SelectorNode new key: (keywords at: ind) code: nil).\\n\\t\\tmainSel addMorphBack: (mainSel transparentSpacerOfSize: 4@4).\\n\\t\\t(TempVariableNode new name: 'arg', ind printString index: ind type: nil scope: nil)\\n\\t\\t\\t asMorphicSyntaxIn: mainSel].! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'dgd 2/22/2003 13:41'!\\nselector\\n\\t\\\"Find the selector I represent, or have inside of me. My parseNode is a SelectorNode or a MessageNode.\\\"\\n\\n\\t| sel cnt |\\n\\tparseNode class == SelectorNode \\n\\t\\tifTrue: [^self decompile asString asSymbol].\\n\\tparseNode class == KeyWordNode ifTrue: [^self decompile asString asSymbol].\\n\\tparseNode class == MessageNode | (parseNode class == MessagePartNode) \\n\\t\\tifFalse: [^nil].\\n\\t\\\"Must be one of those to have a selector\\\"\\n\\t\\\"Beware of messageParts. If MessagePartNode, only returns this one keyword.\\\"\\n\\tsel := ''.\\n\\tcnt := 0.\\n\\tsubmorphs do: \\n\\t\\t\\t[:mm | \\n\\t\\t\\tmm isSyntaxMorph \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[cnt := cnt + 1.\\n\\t\\t\\t\\t\\t(mm nodeClassIs: SelectorNode) ifTrue: [^mm selector].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: MessagePartNode) ifTrue: [sel := sel , mm selector].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: KeyWordNode) ifTrue: [sel := sel , mm decompile asString].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: ReturnNode) ifTrue: [cnt := cnt - 1].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: MessageNode) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[parseNode receiver ifNil: [sel := mm selector].\\n\\t\\t\\t\\t\\t\\t\\tcnt = 2 & (sel isEmpty) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"not the receiver. Selector and arg\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tsel := mm selector]]]].\\n\\tsel ifNil: [^nil].\\n\\tsel notEmpty ifTrue: [^sel asSymbol].\\n\\t^nil! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'aoy 2/15/2003 21:31'!\\nunSpaceAndUpShift: aString appending: extraChars \\n\\t| answer upShiftNext |\\n\\tanswer := WriteStream on: String new.\\n\\tupShiftNext := false.\\n\\taString do: \\n\\t\\t\\t[:ch | \\n\\t\\t\\tupShiftNext :=( ch == Character space) \\n\\t\\t\\t\\tifTrue: [ true]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[answer nextPut: (upShiftNext ifTrue: [ch asUppercase] ifFalse: [ch]).\\n\\t\\t\\t\\t\\t false]].\\n\\tanswer := answer contents.\\n\\textraChars isEmptyOrNil ifTrue: [^answer].\\n\\t(answer endsWith: extraChars) ifFalse: [answer := answer , extraChars].\\n\\t^answer! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/12/2000 14:42'!\\nuserScriptSelector\\n\\t\\\"user wrote this script\\\"\\n\\n\\t^ self valueOfProperty: #userScriptSelector! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/12/2000 14:41'!\\nuserScriptSelector: sel\\n\\t\\\"user wrote this script\\\"\\n\\n\\tself setProperty: #userScriptSelector toValue: sel.! !\\n\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 16:03'!\\naSimpleStringMorphWith: aString\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t^StringMorph contents: aString font: self alansCurrentFontPreference\\n\\t].\\n\\n\\t^StringMorph contents: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:24'!\\nalansCurrentFontPreference\\n\\n\\t^nil\\t\\t\\\"StrikeFont familyName: 'ComicBold' size: 16\\\"! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:38'!\\nalansTemplateStyleFor: key\\n\\n\\t(#(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:) includes: key) ifTrue: [^1].\\n\\t(#(do: collect:) includes: key) ifTrue: [^2].\\n\\t(#(if:do:) includes: key) ifTrue: [^3].\\n\\t^0\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 13:46'!\\nanUpdatingStringMorphWith: aString special: aBoolean\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t^(aBoolean ifTrue: [SyntaxUpdatingStringMorph] ifFalse: [UpdatingStringMorph])\\n\\t\\t\\t contents: aString\\n\\t\\t\\tfont: self alansCurrentFontPreference\\n\\t].\\n\\t^UpdatingStringMorph contents: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:39'!\\nconstructSelfVariant: receiver and: key\\n\\n\\t| wordy |\\n\\t(receiver isKindOf: VariableNode) ifFalse: [^nil].\\n\\treceiver name = 'self' ifFalse: [^nil].\\n\\t(wordy _ self translateFromWordySelfVariant: key) ifNil: [^nil].\\n\\t^wordy\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:20'!\\ndarkerColor\\n\\n\\t^(Color r: 1.0 g: 0.839 b: 0.613)\\t\\\"Color lightBrown lighter lighter.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:23'!\\nfontToUseForSpecialWord: aString\\n\\n\\t^(#('Yes' 'No' 'Test') includes: aString) ifTrue: [\\n\\t\\t(StrikeFont familyName: 'Helvetica' size: 14)\\n\\t] ifFalse: [\\n\\t\\tnil\\t\\\"(StrikeFont familyName: 'ComicBold' size: 16)\\\"\\n\\t]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 09:35'!\\nlighterColor\\n\\n\\t^Color gray: 0.9\\t\\t\\n\\\"(Color r: 0.935 g: 0.935 b: 0.935)\\\"\\n\\\"paleGreen lighter\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 8/7/2001 23:15'!\\nnoiseBeforeBlockArg\\n\\n\\t^ self alansTest1 ifTrue: [' Use'] ifFalse: [' from']! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 3/25/2001 17:16'!\\nnoiseStringMorph: aNoiseString\\n\\n\\t| sMorph |\\n\\n\\tsMorph _ self aSimpleStringMorphWith: aNoiseString.\\n\\tsMorph \\n\\t\\tfont: (self fontToUseForSpecialWord: aNoiseString); \\n\\t\\tsetProperty: #noiseWord toValue: true.\\n\\n\\t^sMorph\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 8/7/2001 23:12'!\\nnoiseWordBeforeVariableNode: aNode string: aString\\n\\n\\t(#('self' 'nil') includes: aString) ifFalse: [\\n\\t\\taNode code ifNil: [^'my'].\\n\\t\\taNode type < 4 ifTrue: [^'my']\\n\\t].\\n\\t^nil! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetConditionalPartStyle\\n\\n\\tself specialColor: self lighterColor andBorder: self darkerColor.\\n\\tself useRoundedCorners.\\n\\tself borderWidth: 1.\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/27/2001 07:34'!\\nsetSpecialOuterTestFormat\\n\\n\\tself \\n\\t\\tspecialColor: self darkerColor \\n\\t\\tandBorder: self lighterColor.\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetSpecialTempDeclarationFormat1\\n\\n\\t\\\"the outer template for temp defs\\\"\\n\\n\\tself \\n\\t\\tspecialColor: self darkerColor \\n\\t\\tandBorder: self lighterColor.\\n\\t\\\"self \\n\\t\\tspecialColor: (Color lightYellow) \\n\\t\\tandBorder: (Color r: 0.581 g: 0.774 b: 0.903).\\\"\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\tself cellPositioning: #center.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetSpecialTempDeclarationFormat2\\n\\n\\t\\\"the inner template for temp defs\\\"\\n\\n\\tself \\n\\t\\tspecialColor: self lighterColor \\n\\t\\tandBorder: self darkerColor.\\n\\t\\\"self \\n\\t\\tspecialColor: (Color r: 1.0 g: 1.0 b: 0.548) \\n\\t\\tandBorder: (Color r: 0.581 g: 0.774 b: 0.903).\\\"\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/27/2001 16:53'!\\nshouldBeBrokenIntoWords: aSymbol\\n\\n\\t^#(methodHeader1 methodHeader2 keyword2 upArrow \\n\\t\\ttempVariable tempVariableDeclaration blockarg2 variable\\n\\t\\tkeywordGetz keywordSetter unaryGetter\\n\\t\\tassignmentArrow) includes: aSymbol! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:44'!\\nspecialColor: c1 andBorder: c2\\n\\n\\tself color: (self scaleColorByUserPref: c1).\\n\\tself setProperty: #deselectedColor toValue: c1.\\n\\tself borderColor: (self scaleColorByUserPref: c2).\\n\\tself setProperty: #deselectedBorderColor toValue: c2.\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'yo 11/11/2002 10:32'!\\nsplitAtCapsAndDownshifted: aString\\n\\n\\tself flag: #yoCharCases.\\n\\n\\t^String streamContents: [ :strm |\\n\\t\\taString do: [ :each | \\n\\t\\t\\teach = $: ifFalse: [\\n\\t\\t\\t\\teach isUppercase ifTrue: [strm nextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t \\tnextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t \\tnextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t\\tnextPut: each asLowercase]\\n\\t\\t\\t\\t\\tifFalse: [strm nextPut: each]\\n\\t\\t\\t].\\n\\t\\t]\\n\\t].! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:01'!\\nstandardCellPositioning\\n\\n\\t^ self alansTest1 ifTrue: [#leftCenter] ifFalse: [#topLeft]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/25/2001 17:33'!\\nstandardInset\\n\\n\\tparseNode class == BlockNode ifTrue: [^ 5@1].\\n\\t\\t\\\"allow pointing beside a line so can replace it\\\"\\n\\t^ self alansTest1 ifTrue: [1] ifFalse: [-1]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 4/4/2001 13:12'!\\nsubstituteKeywordFor: aString\\n\\n\\taString isEmpty ifTrue: [^aString asString].\\n\\taString asString = '^ ' ifTrue: [^'answer'].\\n\\taString asString = 'ifTrue:' ifTrue: [^'Yes'].\\n\\taString asString = 'ifFalse:' ifTrue: [^'No'].\\n\\taString asString = 'self' ifTrue: [^'self'].\\n\\taString first isUppercase ifTrue: [^aString asString].\\n\\n\\t^self splitAtCapsAndDownshifted: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 15:03'!\\ntokenVerticalSeparator\\n\\n\\t^Morph new \\n\\t\\tcolor: Color transparent;\\n\\t\\textent: 3@3;\\n\\t\\tlock\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:45'!\\ntranslateFromWordySelfVariant: key\\n\\n\\t#selfWrittenAsMe == key ifTrue: [^'me'].\\n\\t#selfWrittenAsMy == key ifTrue: [^'my'].\\n\\t#selfWrittenAsIll == key ifTrue: [^'I''ll'].\\n\\t#selfWrittenAsIm == key ifTrue: [^'I''m'].\\n\\t#selfWrittenAsThis == key ifTrue: [^'this'].\\n\\t^nil\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/28/2001 09:05'!\\ntranslateToWordyGetter: key\\n\\t\\\" setBlob: becomes 's blob _ \\\"\\n\\n\\t^ '''s ', \\n\\t (self splitAtCapsAndDownshifted: (key asString allButFirst: 3) \\n\\t\\t\\twithFirstCharacterDownshifted)! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:45'!\\ntranslateToWordySelfVariant: aString\\n\\n\\t| lc |\\n\\tlc _ aString asLowercase.\\n\\tlc = 'me' ifTrue: [^#selfWrittenAsMe].\\n\\tlc = 'my' ifTrue: [^#selfWrittenAsMy].\\n\\tlc = 'i''ll' ifTrue: [^#selfWrittenAsIll].\\n\\tlc = 'i''m' ifTrue: [^#selfWrittenAsIm].\\n\\tlc = 'this' ifTrue: [^#selfWrittenAsThis].\\n\\t^nil\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/27/2001 17:26'!\\ntranslateToWordySetter: key\\n\\t\\\" setBlob: becomes 's blob _ \\\"\\n\\n\\t^ '''s ', \\n\\t (self splitAtCapsAndDownshifted: (key asString allButFirst: 3) allButLast \\n\\t\\t\\twithFirstCharacterDownshifted), \\n\\t ' _'! !\\n\\n\\n!SyntaxMorph methodsFor: 'card in a stack' stamp: 'tk 9/25/2001 11:46'!\\ncouldHoldSeparateDataForEachInstance\\n\\t\\\"Answer whether this type of morph is inherently capable of holding separate data for each instance ('card data')\\\"\\n\\n\\t^ true! !\\n\\n\\n!SyntaxMorph methodsFor: 'card & stack' stamp: 'tk 9/25/2001 11:41'!\\nsetNewContentsFrom: stringOrNumberOrNil\\n\\t\\\"Using stringOrNumberOrNil as a guide, set the receiver's contents afresh. If the input parameter is nil, the a default value stored in a property of the receiver, if any, will supply the new initial content. This method is only called when a VariableDock is attempting to put a new value.\\\"\\n\\n\\t(self readOut ifNil: [^ self]) setNewContentsFrom: stringOrNumberOrNil.! !\\n\\n!SyntaxMorph methodsFor: 'card & stack' stamp: 'tk 11/4/2001 21:47'!\\nsetTarget: aPlayer\\n\\t\\\"Find my UpdatingStringMorph and set its getSelector, putSelector, and target\\\"\\n\\n\\t| updatingString |\\n\\t(updatingString _ self readOut) ifNil: [^ self].\\n\\tupdatingString putSelector: (Utilities setterSelectorFor: self knownName).\\n\\tupdatingString getSelector: (Utilities getterSelectorFor: self knownName).\\n\\tupdatingString target: aPlayer. ! !\\n\\n\\n!SyntaxMorph methodsFor: 'change reporting' stamp: 'tk 9/28/2001 13:36'!\\ncolorChangedForSubmorph: colorPatch\\n\\t| sel newSel cc ms phrase completeMsg |\\n\\t\\\"reporting a color change\\\"\\n\\n\\t(self nodeClassIs: MessageNode) ifFalse: [^ nil].\\n\\t(sel _ self selector) ifNil: [^ nil].\\n\\t(Color colorNames includes: sel) | (sel == #r:g:b:) ifFalse: [^ nil].\\n\\t\\t\\\"a standard color name\\\"\\n\\t\\\"replace self with new tiles from the color\\\"\\n\\t(newSel _ (cc _ colorPatch color) name) \\n\\t\\tifNil: [ms _ MessageSend receiver: Color selector: #r:g:b: arguments: \\n\\t\\t\\t\\t(Array with: cc red with: cc green with: cc blue).\\n\\t\\t\\tphrase _ ms asTilesIn: Color globalNames: true]\\n\\t\\tifNotNil: [ms _ MessageSend receiver: Color selector: newSel arguments: #().\\n\\t\\t\\tphrase _ ms asTilesIn: Color globalNames: true].\\n\\tself deletePopup.\\n\\tcompleteMsg _ self isNoun ifTrue: [self] ifFalse: [owner].\\n\\tcompleteMsg owner replaceSubmorph: completeMsg by: phrase.\\n\\t\\\"rec setSelection: {rec. nil. rec}.\\\"\\n\\tphrase acceptIfInScriptor.! !\\n\\n\\n!SyntaxMorph methodsFor: 'classification' stamp: 'di 11/2/2000 13:25'!\\nisSyntaxMorph\\n\\t^ true! !\\n\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'di 11/17/2000 07:59'!\\ndebugger\\n\\n\\t^ self rootTile valueOfProperty: #debugger! !\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'di 11/17/2000 07:59'!\\ndebugger: x\\n\\n\\tself rootTile setProperty: #debugger toValue: x! !\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'RAA 8/24/1999 12:35'!\\nhostContext\\n\\n\\t^nil\\t\\t\\\"we don't have one\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'drawing' stamp: 'RAA 3/25/2001 16:16'!\\ndrawOn: aCanvas\\n\\n\\tsuper drawOn: aCanvas.\\n\\tself isBlockNode ifFalse: [^self].\\n\\tself alansTest1 ifTrue: [^self].\\n\\n\\tself immediatelyBelowTheMethodNode ifTrue: [\\n\\t\\taCanvas fillRectangle: (self topLeft + (0@-1) extent: self width@1) color: Color gray\\n\\t] ifFalse: [\\n\\t\\taCanvas fillRectangle: (self topLeft + (1@1) extent: 2@(self height-2)) color: Color gray.\\n\\t\\taCanvas fillRectangle: (self topLeft + (1@1) extent: 4@1) color: Color gray.\\n\\t\\taCanvas fillRectangle: (self bottomLeft + (1@-1) extent: 4@1) color: Color gray\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'drawing' stamp: 'tk 9/13/2001 15:13'!\\nlookTranslucent\\n\\n\\tself setDeselectedColor.\\n\\tsuper color: (self color alpha: 0.25).\\n\\tsubmorphs do: [:mm | (mm respondsTo: #lookTranslucent) \\n\\t\\tifTrue: [mm lookTranslucent]\\n\\t\\tifFalse: [\\\"mm color: color\\\"]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'di 1/29/2001 16:23'!\\ncleanupAfterItDroppedOnMe\\n\\t\\\"A tile just dropped into me. Clean up\\\"\\n\\n\\tself layoutChanged. \\\"** Isn't this already implied by the addMorph: ?\\\"\\n\\t\\\"Auto-accept on drop if in a scriptor\\\"\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'di 5/4/2001 13:16'!\\nhighlightForDrop: evt\\n\\n\\t(self wantsDroppedMorph: evt hand firstSubmorph event: evt)\\n\\t\\tifTrue: [self color: self dropColor].! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 7/19/2001 19:04'!\\njustDroppedInto: aMorph event: evt\\n\\taMorph isSyntaxMorph ifFalse:\\n\\t\\t[Preferences tileTranslucentDrag\\n\\t\\t\\tifTrue: [self setDeselectedColor]\\n\\t\\t\\tifFalse: [self align: self topLeft with: self topLeft - self cursorBaseOffset]].\\n\\tself removeProperty: #beScript.\\n\\t^ super justDroppedInto: aMorph event: evt! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 9/30/2001 11:09'!\\nmorphToDropInPasteUp: aPasteUp\\n\\t\\\"If property #beScript is true, create a scriptor around me.\\\"\\n\\n\\t| actualObject itsSelector aScriptor adjustment handy tw blk |\\n\\t(self valueOfProperty: #beScript ifAbsent: [false]) ifFalse: [^ self].\\n\\tself removeProperty: #beScript.\\n\\tactualObject _ self actualObject ifNil: [\\n\\t\\t\\t\\t\\tself valueOfProperty: #scriptedPlayer ifAbsent: [nil]].\\n\\tactualObject ifNil: [^ self].\\n\\tself removeProperty: #scriptedPlayer.\\n\\tactualObject assureUniClass.\\n\\n\\titsSelector _ self userScriptSelector.\\n\\taScriptor _ itsSelector isEmptyOrNil\\n\\t\\tifFalse:\\n\\t\\t\\t[adjustment _ 0@0.\\n\\t\\t\\tactualObject scriptEditorFor: itsSelector]\\n\\t\\tifTrue:\\n\\t\\t\\t[adjustment _ 60 @ 20.\\n\\t\\t\\tactualObject newScriptorAround: self].\\n\\taScriptor ifNil: [^self].\\n\\thandy _ aPasteUp primaryHand.\\n\\n\\taScriptor position: handy position - adjustment.\\n\\taPasteUp addMorphFront: aScriptor.\\t\\\"do this early so can find World\\\"\\n\\taScriptor showingMethodPane ifFalse: [\\n\\t\\t\\\"(tw _ aScriptor findA: TwoWayScrollPane) ifNil:\\n\\t\\t\\t[itsSelector ifNil: ['blank script'.\\n\\t\\t\\t\\ttw _ aScriptor findA: TwoWayScrollPane.\\n\\t\\t\\t\\tblk _ (tw scroller findA: SyntaxMorph \\\"\\\"MethodNode\\\"\\\") findA: BlockNode.\\n\\t\\t\\t\\tblk addMorphFront: self]].\\n\\t\\t\\\"\\n\\t\\tSyntaxMorph setSize: nil andMakeResizable: aScriptor.\\n\\t\\t].\\n\\t^ aScriptor\\n! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 9/24/2001 10:04'!\\nstructureMatchWith: aMorph\\n\\t| meNoun itNoun |\\n\\t\\\"Return true if the node types would allow aMorph to replace me. This tests the gross structure of the method only.\\\"\\n\\n\\tmeNoun _ self isNoun.\\n\\titNoun _ aMorph isNoun.\\n\\n\\t\\\"Consider these nouns to be equal: TempVariableNode, LiteralNode, VariableNode, (MessageNode with receiver), CascadeNode, AssignmentNode\\\"\\n\\tmeNoun & itNoun ifTrue: [^ true].\\n\\tmeNoun & aMorph isBlockNode ifTrue: [^ true].\\n\\n\\t\\\"If I am a BlockNode, and it is a TempVariableNode, add it into list\\\"\\n\\t\\\"If I am a BlockNode, and it is a noun, add it as a new line\\\"\\n\\tself isBlockNode ifTrue:\\n\\t\\t[itNoun ifTrue: [^ true].\\n\\t\\t(aMorph nodeClassIs: ReturnNode) ifTrue:\\n\\t\\t\\t[^ (self submorphs\\n\\t\\t\\t\\tdetect: [:mm | ((mm isSyntaxMorph) and: [mm nodeClassIs: ReturnNode])]\\n\\t\\t\\t\\tifNone: [nil]) isNil].\\t\\\"none already in this block\\\"\\n\\t\\t\\t\\t\\\"If I am a BlockNode, and it is a ReturnNode, add to end\\\"\\n\\t\\t(aMorph nodeClassIs: CommentNode) ifTrue: [^ true]].\\n\\n\\t(self isMethodNode) ifTrue: [^ false].\\t\\\"Later add args and keywords\\\"\\n\\t\\t\\\"Later allow comments to be dropped in\\\"\\n\\t\\t\\\"Add MethodTemps by dropping into the main block\\\"\\n\\n\\t(self nodeClassIs: ReturnNode) & (aMorph parseNode class == MessageNode) \\n\\t\\tifTrue: [^ true].\\t\\t\\\"Command replace Return\\\"\\n\\t(self nodeClassIs: MessageNode) & (aMorph parseNode class == ReturnNode) ifTrue: [\\n\\t\\t(owner submorphs select: [:ss | ss isSyntaxMorph]) last == self\\n\\t\\t\\tifTrue: [^ true]].\\t\\\"Return replace last command\\\"\\n\\n\\t(aMorph nodeClassIs: AssignmentNode) ifTrue: [\\n\\t\\titNoun ifFalse: [\\\"create a new assignment\\\"\\n\\t\\t\\t^ self isAVariable & self isDeclaration not]].\\t\\\"only assign to a variable\\\"\\n\\n\\t\\\"If nodes are of equal class, replace me with new one.\\\"\\n\\t(self nodeClassIs: aMorph parseNode class) ifTrue: [\\n\\t\\t(self nodeClassIs: MessageNode) \\n\\t\\t\\t\\tifFalse: [^ true]\\t\\\"normal match\\\"\\n\\t\\t\\t\\tifTrue: [^ self receiverNode == aMorph receiverNode]].\\t\\\"both nil\\\"\\n\\n\\t^ false \\\"otherwise reject\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'gm 2/22/2003 12:49'!\\nwantsDroppedMorph: aMorph event: evt \\n\\t\\\"For the moment, you have to drop it the right place. We do not look at enclosing morphs\\\"\\n\\n\\t\\\"Two ways to do this: Must always destroy old node, then drag in new one.\\n\\t\\tOr, drop replaces what you drop on. Nasty with blocks.\\\"\\n\\n\\t(aMorph isSyntaxMorph) ifFalse: [^false].\\n\\t(self structureMatchWith: aMorph) ifFalse: [^false].\\t\\\"gross structure\\\"\\n\\n\\t\\\"Only look at types if NoviceMode -- building EToys\\\"\\n\\t^self okToBeReplacedBy: aMorph\\t\\\"test the types\\\"\\n\\n\\t\\\"^ true\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/8/2000 22:05'!\\ncursorBaseOffset\\n\\n\\t^ 7@14\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/6/2000 16:20'!\\nhandlesKeyboard: evt\\n\\t^ evt keyCharacter = Character backspace! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 13:39'!\\nhandlesMouseDown: evt \\n\\tevt yellowButtonPressed ifTrue: [^true].\\n\\tparseNode isNil ifTrue: [^false].\\n\\towner isSyntaxMorph \\n\\t\\tifTrue: [(owner isMethodNode and: [self isBlockNode not]) ifTrue: [^false]].\\t\\\"Can only take block out of a MethodNode\\\"\\n\\t^true! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 10/26/2000 16:58'!\\nhandlesMouseOver: evt\\n\\t\\\"Am I a tile that could be picked up?\\\"\\n\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/6/2000 08:21'!\\nhandlesMouseOverDragging: evt\\n\\n\\t^ evt hand hasSubmorphs\\n\\t\\tand: [evt hand firstSubmorph isSyntaxMorph]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/17/2000 08:21'!\\nkeyStroke: evt\\n\\t\\\"Handle a keystroke event.\\\"\\n\\t| spacer |\\n\\tevt keyCharacter = Character backspace ifTrue:\\n\\t\\t[(owner notNil and: [owner isSyntaxMorph]) ifTrue:\\n\\t\\t\\t[owner isBlockNode ifTrue:\\n\\t\\t\\t\\t[\\\"Delete a statement.\\\"\\n\\t\\t\\t\\t(spacer _ self submorphAfter) class == AlignmentMorph\\n\\t\\t\\t\\t\\t\\tifTrue: [spacer delete].\\n\\t\\t\\t\\tself delete].\\n\\t\\t\\t]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 9/26/2001 05:56'!\\nmouseDown: evt \\n\\t| dup rootTile |\\n\\tevt yellowButtonPressed ifTrue: [^ self showMenu: evt].\\n\\t(rootTile _ self rootTile) isMethodNode ifTrue:\\n\\t\\t[self currentSelectionDo:\\n\\t\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\t\\t(outerMorph notNil and: [self == innerMorph])\\n\\t\\t\\t\\tifTrue: [\\\"Click on prior selection -- record click point.\\\"\\n\\t\\t\\t\\t\\t\\tself setSelection: {self. evt cursorPoint. outerMorph}]\\n\\t\\t\\t\\tifFalse: [\\\"A new selection sequence.\\\"\\n\\t\\t\\t\\t\\t\\tself setSelection: {self. evt cursorPoint. nil}]].\\n\\t\\t^ self].\\n\\n\\t\\\"Out in the world -- treat as a unit\\\"\\n\\trootTile isSticky ifTrue: [^ self].\\t\\\"later may allow to be selected\\\"\\n\\trootTile isPartsDonor \\n\\t\\tifTrue: [dup _ rootTile duplicate.\\n\\t\\t\\t\\tdup setProperty: #beScript toValue: true]\\n\\t\\tifFalse: [dup _ rootTile].\\n\\tevt hand attachMorph: dup.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [^ dup lookTranslucent]\\n\\t\\tifFalse: [^ dup align: dup topLeft with: evt hand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 7/19/2001 20:21'!\\nmouseEnter: evt\\n\\t\\\"Highlight this level as a potential grab target\\\"\\n\\n\\\"Transcript cr; print: self; show: ' enter'.\\\"\\n\\tself rootTile isMethodNode ifFalse: [^ self]. \\t\\\"not in a script\\\"\\n\\tself unhighlightOwnerBorder.\\n\\tself highlightForGrab: evt.\\n\\tevt hand newKeyboardFocus: self.\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 7/25/2001 10:09'!\\nmouseEnterDragging: evt\\n\\t\\\"Highlight this level as a potential drop target\\\"\\n\\n\\\"self isBlockNode ifTrue: [Transcript cr; print: self; show: ' enterDragging'].\\\"\\n\\tself rootTile isMethodNode ifFalse: [^ self]. \\t\\\"not in a script\\\"\\n\\n\\tevt hand hasSubmorphs ifFalse: [^ self]. \\\"Don't react to empty hand\\\"\\n\\tself unhighlightOwnerBorder.\\n\\tself isBlockNode ifFalse: [self highlightForDrop: evt.\\n\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m color = self dropColor]])\\n\\t\\t\\tifNotNilDo: [:m | m unhighlight]].\\n\\n\\tself isBlockNode ifTrue:\\n\\t\\t[(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]])\\n\\t\\t\\tifNotNilDo: [:m | \\\"Suspend outer block.\\\"\\n\\t\\t\\t\\t\\t\\tm stopStepping; removeDropZones].\\n\\t\\tself startStepping]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 18:48'!\\nmouseLeave: evt \\n\\t\\\"Move grab highlight back out a level\\\"\\n\\n\\t\\\"Transcript cr; print: self; show: ' leave'.\\\"\\n\\n\\tself rootTile isMethodNode ifFalse: [^self].\\t\\\"not in a script\\\"\\n\\tself unhighlightBorder.\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner highlightForGrab: evt]! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 18:48'!\\nmouseLeaveDragging: evt \\n\\t\\\"Transcript cr; print: self; show: ' leaveDragging'.\\\"\\n\\n\\tself rootTile isMethodNode ifFalse: [^self].\\t\\\"not in a script\\\"\\n\\tself isBlockNode \\n\\t\\tifTrue: \\n\\t\\t\\t[self\\n\\t\\t\\t\\tstopStepping;\\n\\t\\t\\t\\tremoveDropZones.\\n\\t\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]]) \\n\\t\\t\\t\\tifNotNilDo: [:m | m startStepping].\\t\\\"Activate outer block.\\\"\\n\\t\\t\\tself submorphs do: \\n\\t\\t\\t\\t\\t[:ss | \\n\\t\\t\\t\\t\\t\\\"cancel drop color in line beside mouse\\\"\\n\\n\\t\\t\\t\\t\\tss color = self dropColor ifTrue: [ss setDeselectedColor]]].\\n\\n\\t\\\"Move drop highlight back out a level\\\"\\n\\tself unhighlight.\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner isBlockNode ifFalse: [owner highlightForDrop: evt]]! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 10/17/2001 13:41'!\\nmouseMove: evt\\n\\t| dup selection |\\n\\towner isSyntaxMorph ifFalse: [^ self].\\n\\nfalse ifTrue: [\\\"for now, do not drag off a tile\\\"\\n\\tself currentSelectionDo:\\n\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tmouseDownLoc ifNotNil: [\\n\\t\\t\\t(evt cursorPoint dist: mouseDownLoc) > 4 ifTrue:\\n\\t\\t\\t\\t[\\\"If drag 5 pixels, then tear off a copy of outer selection.\\\"\\n\\t\\t\\t\\tselection _ outerMorph ifNil: [self].\\n\\t\\t\\t\\tselection deletePopup.\\n\\t\\t\\t\\tevt hand attachMorph: (dup _ selection duplicate).\\n\\t\\t\\t\\tPreferences tileTranslucentDrag\\n\\t\\t\\t\\t\\tifTrue: [dup lookTranslucent]\\n\\t\\t\\t\\t\\tifFalse: [dup align: dup topLeft\\n\\t\\t\\t\\t\\t\\t\\t\\twith: evt hand position + self cursorBaseOffset].\\n\\t\\t\\t\\tself setSelection: nil.\\t\\\"Why doesn't this deselect?\\\"\\n\\t\\t\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]])\\n\\t\\t\\t\\t\\tifNotNilDo: [:m | \\\"Activate enclosing block.\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tm startStepping]]]].\\n\\t].! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/17/2000 08:13'!\\nmouseUp: evt\\n\\t| newSel |\\n\\tself rootTile isMethodNode ifFalse: [^ self].\\n\\tself currentSelectionDo:\\n\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tnewSel _ outerMorph\\n\\t\\t\\tifNil: [self \\\"first click\\\"]\\n\\t\\t\\tifNotNil: [(outerMorph firstOwnerSuchThat:\\n\\t\\t\\t\\t\\t\\t\\t[:m | m isSyntaxMorph and: [m isSelectable]]) ifNil: [self]].\\n\\t\\tnewSel isMethodNode ifTrue: [^ self setSelection: nil].\\n\\t\\tself setSelection: {self. nil. newSel}]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 12/1/2000 15:42'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t| doEdit |\\n\\t\\\"only let strings edit on shift-click. Editing on ordinary click defeats the brown selection and tile dragging.\\\"\\n\\n\\tdoEdit _ self world primaryHand lastEvent shiftPressed.\\n\\tdoEdit ifTrue: [\\\"remove the arrows during editing\\\"\\n\\t\\tself valueOfProperty: #myPopup ifPresentDo: [:panel |\\n\\t\\t\\tpanel delete. self removeProperty: #myPopup]].\\n\\t^ doEdit! !\\n\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'di 2/21/2001 11:42'!\\nalansTest1\\n\\t\\n\\t| root |\\n\\n\\troot _ self rootTile ifNil: [self].\\n\\t^root valueOfProperty: #alansNewStyle ifAbsent: [self usingClassicTiles not]! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:02'!\\ncontrolContrast2: evt\\n\\n\\t| origin scale startingContrastX |\\n\\n\\tevt isMouseUp ifTrue: [\\n\\t\\t^self removeProperty: #startingPointForSomeAdjustment\\n\\t].\\n\\tevt isMouseDown ifTrue: [\\n\\t\\t^self setProperty: #startingPointForSomeAdjustment toValue: evt cursorPoint\\n\\t].\\n\\tContrastFactor ifNil: [ContrastFactor _ 0.5].\\n\\tscale _ 200.0.\\n\\tstartingContrastX _ ContrastFactor * scale.\\n\\torigin _ self valueOfProperty: #startingPointForSomeAdjustment.\\n\\tContrastFactor _ (evt cursorPoint x - origin x + startingContrastX) / scale min: 1.0 max: 0.0.\\n\\tself finalAppearanceTweaks.\\n! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:07'!\\ncontrolContrast: evt\\n\\n\\t\\\"old version. may be some scripts saved with me, so don't crash\\\"\\n\\t^self! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 5/11/2001 07:41'!\\ncontrolSpacing2: evt\\n\\n\\t| origin scale startingContrastX |\\n\\n\\tevt isMouseUp ifTrue: [\\n\\t\\t^self removeProperty: #startingPointForSomeAdjustment\\n\\t].\\n\\tevt isMouseDown ifTrue: [\\n\\t\\t^self setProperty: #startingPointForSomeAdjustment toValue: evt cursorPoint\\n\\t].\\n\\tSizeScaleFactor ifNil: [SizeScaleFactor _ 0.15].\\n\\tscale _ 200.0.\\n\\tstartingContrastX _ SizeScaleFactor * scale.\\n\\torigin _ self valueOfProperty: #startingPointForSomeAdjustment.\\n\\tSizeScaleFactor _ (evt cursorPoint x - origin x + startingContrastX) / scale min: 1.0 max: 0.0.\\n\\tself finalAppearanceTweaks.\\n! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:07'!\\ncontrolSpacing: evt\\n\\n\\t\\\"old version. may be some scripts saved with me, so don't crash\\\"\\n\\t^self! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'di 2/21/2001 12:30'!\\nlookClassic\\n\\tself isLeafTile ifTrue: [self layoutInset: 2@4]! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'tk 7/18/2001 16:00'!\\nusingClassicTiles \\n\\n\\t^ Preferences uniTilesClassic! !\\n\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/30/2001 14:48'!\\ncompoundBorderColor \\n\\n\\t^ self valueOfProperty: #deselectedBorderColor ifAbsent: [Color veryLightGray]\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 11/5/2000 07:26'!\\ndropColor\\n\\t^ Color green darker! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/23/2001 18:28'!\\ngrabColor\\n\\n\\t\\\"Not the select color, but the mouseOver border color. Means it could be grabbed\\\"\\n\\t^ Color paleOrange mixed: 0.5 with: Color brown! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 11/6/2000 09:22'!\\nhighlightForGrab: evt\\n\\n\\tself borderColor: self grabColor.! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/19/2001 19:09'!\\nstdBorderColor \\n\\n\\t\\\"put choices of how to do the border here\\\"\\n\\t^ self valueOfProperty: #deselectedBorderColor ifAbsent: [Color transparent]! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/19/2001 19:50'!\\nunhighlight\\n\\n\\tself setDeselectedColor.\\n\\n\\nfalse ifTrue: [\\n\\tself currentSelectionDo: [:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tself color: ( false\\n\\t\\t\\t\\\"(self == outerMorph or: [owner notNil and: [owner isSyntaxMorph not]])\\\"\\n\\t\\t\\t\\tifTrue: [self valueOfProperty: #deselectedBorderColor ifAbsent: [#raised]]\\n\\t\\t\\t\\tifFalse: [self color: Color transparent]\\n\\t\\t)\\n\\t]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 5/4/2001 13:21'!\\nunhighlightBorder\\n\\n\\tself currentSelectionDo: [:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tself borderColor: (\\n\\t\\t\\t(self == outerMorph or: [owner notNil and: [owner isSyntaxMorph not]])\\n\\t\\t\\t\\tifTrue: [self valueOfProperty: #deselectedBorderColor ifAbsent: [#raised]]\\n\\t\\t\\t\\tifFalse: [self stdBorderColor]\\n\\t\\t)\\n\\t]\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'dgd 2/22/2003 18:48'!\\nunhighlightOwner\\n\\t\\\"Unhighlight my owner\\\"\\n\\n\\t(owner notNil and: [owner isSyntaxMorph]) ifTrue: [owner unhighlight]! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'dgd 2/22/2003 18:49'!\\nunhighlightOwnerBorder\\n\\t\\\"Unhighlight my owner's border\\\"\\n\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner unhighlightBorder]! !\\n\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'sw 3/6/2001 11:26'!\\ninAPluggableScrollPane\\n\\t\\\"Answer a PluggableTileScriptorMorph that holds the receiver\\\"\\n\\n\\t| widget |\\n\\twidget _ PluggableTileScriptorMorph new.\\n\\twidget extent: 10@10; borderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget hResizing: #spaceFill; vResizing: #spaceFill.\\n\\t^ widget\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'sw 6/26/2001 10:58'!\\ninAScrollPane\\n\\t\\\"Answer a scroll pane in which the receiver is scrollable\\\"\\n\\n\\t^ self inATwoWayScrollPane! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'di 1/31/2001 10:14'!\\nopenInWindow\\n\\n\\t| window widget sel |\\n\\tsel _ ''.\\n\\tself firstSubmorph allMorphs do: [:rr | \\n\\t\\t\\t(rr isKindOf: StringMorph) ifTrue: [sel _ sel, rr contents]].\\n\\twindow _ (SystemWindow labelled: 'Tiles for ', self parsedInClass printString, '>>',sel).\\n\\twidget _ self inAScrollPane.\\n\\twidget color: Color paleOrange.\\n\\twindow\\n\\t\\taddMorph: widget\\n\\t\\tframe: (0@0 extent: 1.0@1.0).\\n\\twindow openInWorldExtent: (\\n\\t\\tself extent + (20@40) min: (Display boundingBox extent * 0.8) rounded\\n\\t)\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'FBS 2/24/2004 14:21'!\\nreturnNode: aNode expression: expr\\n\\n\\t| row expMorph sMorph aNoiseString |\\n\\trow _ self addRow: #return on: aNode.\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t\\taNoiseString _ ' Reply '.\\n\\t\\tsMorph _ self aSimpleStringMorphWith: aNoiseString.\\n\\t\\tsMorph \\n\\t\\t\\temphasis: TextEmphasis bold emphasisCode;\\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: '^'.\\n\\n\\t\\trow addMorphBack: sMorph.\\n\\t] ifFalse: [\\n\\t\\trow addToken: '^ ' type: #upArrow on: aNode.\\n\\t].\\n\\texpMorph _ expr asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [\\n\\t\\t(expMorph hasProperty: #deselectedColor) ifFalse: [expMorph setConditionalPartStyle].\\n\\t].\\n\\texpr addCommentToMorph: row.\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'tk 1/19/2001 13:29'!\\nsample: arg1\\n\\\"a comment\\\"\\n| temp1 |\\ntemp1 _ 5.\\ntemp1 yourself.\\ntemp1 min: arg1.! !\\n\\n\\n!SyntaxMorph methodsFor: 'insertion drop zones' stamp: 'di 1/30/2001 21:00'!\\nremoveDropZones\\n\\t\\\"Remove the insertion drop-zone morphs.\\\"\\n\\n\\tself submorphsDo:\\n\\t\\t[:mm | (mm isMemberOf: BorderedMorph) ifTrue: [mm delete]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'insertion drop zones' stamp: 'tk 9/13/2001 15:24'!\\ntrackDropZones\\n\\t| hand i localPt insertion insHt ii prevBot nxtHt d c1 c2 ht2 spacer1 spacer2 wid ht1 dc each |\\n\\thand _ self primaryHand.\\n\\t(\\\"hand lastEvent redButtonPressed &\\\" hand hasSubmorphs\\n\\t\\tand: [(self hasOwner: hand) not]) ifFalse: [^ self].\\n\\n\\tinsertion _ hand firstSubmorph renderedMorph.\\n\\tinsertion isSyntaxMorph ifFalse: [^ self].\\n\\tinsertion isNoun ifFalse: [(insertion nodeClassIs: CommentNode) ifFalse: [^ self]].\\n\\tlocalPt _ self globalPointToLocal: hand position.\\n\\tinsHt _ insertion height. \\\"**just use standard line height here\\\"\\n\\tself removeDropZones. \\\"Maybe first check if in right place, then just tweak heights.\\\"\\n\\ti _ (ii _ self indexOfMorphAbove: localPt) min: submorphs size-1.\\n\\tprevBot _ i <= 0 ifTrue: [(self innerBounds) top]\\n\\t\\t\\t\\t\\tifFalse: [(self submorphs at: i) bottom].\\n\\tnxtHt _ (submorphs isEmpty\\n\\t\\tifTrue: [insertion]\\n\\t\\tifFalse: [self submorphs at: i+1]) height.\\n\\td _ ii > i ifTrue: [nxtHt \\\"for consistent behavior at bottom\\\"]\\n\\t\\t\\tifFalse: [0 max: (localPt y - prevBot min: nxtHt)].\\n\\n\\t\\\"Top and bottom spacer heights cause continuous motion...\\\"\\n\\tc1 _ Color transparent. c2 _ Color transparent.\\n\\tht2 _ d*insHt//nxtHt. ht1 _ insHt - ht2.\\n\\twid _ self width - (2*borderWidth) - (2*self layoutInset).\\n\\twid isPoint ifTrue: [wid _ wid x].\\n\\t(spacer1 _ BorderedMorph newBounds: (0@0 extent: wid@ht1)\\n\\t\\t\\t\\tcolor: (ht1 > (insHt//2) ifTrue: [c1] ifFalse: [c2]))\\n\\t\\t\\t\\t\\tborderWidth: 1; borderColor: spacer1 color.\\n\\tself privateAddMorph: spacer1 atIndex: (i+1 max: 1).\\n\\t(spacer2 _ BorderedMorph newBounds: (0@0 extent: wid@ht2)\\n\\t\\t\\t\\tcolor: (ht2 > (insHt//2+1) ifTrue: [c1] ifFalse: [c2]))\\n\\t\\t\\t\\t\\tborderWidth: 1; borderColor: spacer2 color.\\n\\tspacer1 setProperty: #dropZone toValue: true.\\n\\tspacer2 setProperty: #dropZone toValue: true.\\n\\tself privateAddMorph: spacer2 atIndex: (i+3 min: submorphs size+1).\\n\\tself fullBounds. \\\"Force layout prior to testing for cursor containment\\\"\\n\\n\\t\\\"Maintain the drop target highlight -- highlight spacer if hand is in it.\\\"\\n\\t{spacer1. spacer2} do:\\n\\t\\t[:spacer | (spacer containsPoint: localPt) ifTrue:\\n\\t\\t\\t[spacer color: self dropColor.\\n\\t\\t\\t\\\"Ignore border color. Maybe do it later.\\n\\t\\t\\tself borderColor = self dropColor\\n\\t\\t\\t\\tifTrue: [self borderColor: self stdBorderColor]\\\"]].\\n\\t\\\"If no submorph (incl spacers) highlighted, then re-highlight the block.\\\"\\n\\t\\\"Ignore border color. Maybe do it later.\\n\\t((self wantsDroppedMorph: insertion event: hand lastEvent) and:\\n\\t\\t[(self submorphs anySatisfy: [:m | m containsPoint: localPt]) not])\\n\\t\\t\\tifTrue: [self borderColor: self dropColor].\\n\\t\\\"\\n\\n\\t\\\"Dragging a tile within a Block, if beside a tile, color it a dropzone\\\"\\n\\t\\\"Transcript show: localPt y printString; space; show: submorphs first top \\n\\t\\tprintString; space; show: submorphs last top printString; cr.\\\"\\n\\tdc _ self dropColor.\\n\\t1 to: ((ii+4 min: submorphs size) max: 1) do: [:ind | \\n\\t\\teach _ submorphs at: ind.\\n\\t\\teach isSyntaxMorph ifTrue: [\\n\\t\\t\\tlocalPt y >= each top \\n\\t\\t\\t\\tifTrue: [\\\"in this one or beyond\\\"\\n\\t\\t\\t\\t\\t(localPt y < each bottom) \\n\\t\\t\\t\\t\\t\\tifTrue: [(each submorphs anySatisfy: [:m | \\n\\t\\t\\t\\t\\t\\t\\t\\tm containsPoint: localPt])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [each setDeselectedColor]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [each color: dc]]\\n\\t\\t\\t\\t\\t\\tifFalse: [each color = dc ifTrue: [each setDeselectedColor]]]\\n\\t\\t\\t\\tifFalse: [each color = dc ifTrue: [each setDeselectedColor]]]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 9/13/2001 15:28'!\\nacceptDroppingMorph: aMorph event: evt\\n\\t| itNoun old |\\n\\t\\\"Two cases: 1) a phrase being dropped into a block. Add a new line.\\n\\t\\t2) aMorph is replacing self by dropping on it.\\n\\tFor the moment, you have to drop it the right place (the end of a tile if it is complex). We do not look at enclosing morphs\\\"\\n\\n\\titNoun _ aMorph isNoun.\\n\\tself withAllOwnersDo:\\n\\t\\t[:m | (m isSyntaxMorph and: [m isBlockNode])\\n\\t\\t\\t\\tifTrue: [m stopStepping; removeDropZones]].\\n\\tself isBlockNode & itNoun ifTrue:\\n\\t\\t[(aMorph nodeClassIs: TempVariableNode) ifTrue:\\n\\t\\t\\t\\t[\\\"If I am a BlockNode, and it is a TempVariableNode, add it into list\\\"\\n\\t\\t\\t\\t(self addBlockArg: aMorph)].\\n\\t\\t\\\"If I am a BlockNode and it is a noun add it as a new line\\\"\\n\\t\\t^ self addToBlock: aMorph event: evt].\\n\\t\\t\\t\\t\\n\\tself isBlockNode ifTrue: [\\n\\t\\t (aMorph nodeClassIs: CommentNode) ifTrue: [^ self addToBlock: aMorph event: evt].\\n\\t\\t (aMorph nodeClassIs: ReturnNode) ifTrue: [^ self addToBlock: aMorph event: evt]].\\n\\n\\t\\\"Later add args and keywords. later allow comments to be dropped\\\"\\n\\n\\t\\\"Can't put statement, literal, assignment, or cascade into left side of assignment\\\"\\n\\t(owner isSyntaxMorph) ifTrue:\\n\\t\\t[(owner nodeClassIs: AssignmentNode) ifTrue:\\n\\t\\t\\t[(owner submorphIndexOf: self) = 1 ifTrue:\\n\\t\\t\\t\\t[aMorph isAVariable ifFalse: [ ^ self]]]].\\n\\n\\t(aMorph nodeClassIs: AssignmentNode) ifTrue: [\\n\\t\\titNoun ifFalse: [\\\"create a new assignment\\\"\\n\\t\\t\\tself isAVariable ifTrue: [^ self newAssignment]\\n\\t\\t\\t\\t\\tifFalse: [^ self]]].\\t\\\"only assign to a variable\\\"\\n\\n\\taMorph deselect.\\n\\t(old _ owner) replaceSubmorph: self by: aMorph.\\t\\\"do the normal replacement\\\"\\n\\t(old isSyntaxMorph) ifTrue: [old cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:24'!\\naddBlockArg: aMorph\\n\\t\\\"Add a temporary to a block or the method. Return true if succeed\\\"\\n\\t\\\"(aMorph nodeClassIs: TempVariableNode) is known to be true.\\\"\\n\\t\\\"***NOTE: This method should be combined with addTempVar:\\\"\\n\\n\\t| tempHolder tt var nn |\\n\\towner isMethodNode ifTrue: [\\n\\t\\t^ (self addTempVar: aMorph)].\\t\\\"Node for them is not inside the block\\\"\\n\\t\\t\\\"If exists, drop the temp in this block and let user extend it.\\\"\\n\\tnn _ aMorph decompile string.\\t\\\"name\\\"\\n\\t(self isKnownVarName: nn) ifTrue: [^ false].\\t\\\"already defined\\\"\\n\\n\\ttt _ self firstSubmorph.\\n\\ttempHolder _ tt firstSubmorph isSyntaxMorph \\n\\t\\t\\t\\tifTrue: [(tt nodeClassIs: BlockArgsNode) \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [tt] ifFalse: [nil]]\\n\\t\\t\\t\\tifFalse: [nil].\\n\\n\\ttempHolder ifNil: [\\\"make new row\\\"\\n\\t\\ttempHolder _ self addRow: #blockarg1 on: (BlockArgsNode new).\\n\\t\\ttempHolder addNoiseString: self noiseBeforeBlockArg.\\n\\t\\ttempHolder submorphs last firstSubmorph emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttempHolder useRoundedCorners.\\n\\n\\t\\tself addMorphFront: tempHolder.\\n\\t\\taMorph parseNode name: nn key: nn code: nil.\\n\\t\\taMorph parseNode asMorphicSyntaxIn: tempHolder.\\n\\t\\ttempHolder cleanupAfterItDroppedOnMe.\\n\\t\\t^ true].\\n\\n\\t\\\"Know this variable is not present, so add it\\\"\\n\\n\\taMorph parseNode name: nn key: nn code: nil.\\n\\ttempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4).\\n\\tvar _ tempHolder addRow: #tempVariable on: aMorph parseNode.\\n\\tvar layoutInset: 1.\\n\\tvar addMorphBack: (self aSimpleStringMorphWith: nn).\\n\\tvar cleanupAfterItDroppedOnMe.\\n\\t^ true\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 16:15'!\\naddColumn: aColorOrSymbol on: aNode\\n\\t| col |\\n\\tself addMorphBack: (col _ self class column: aColorOrSymbol on: aNode).\\n\\n\\\"col setProperty: #howCreated toValue: thisContext longStack.\\\"\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t(aColorOrSymbol == #block and: [self isMethodNode not]) ifTrue: [\\n\\t\\t\\tcol setConditionalPartStyle.\\n\\t\\t].\\n\\t].\\n\\t^ col\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:44'!\\naddNoiseString: aNoiseString\\n\\n\\t^self addNoiseString: aNoiseString emphasis: TextEmphasis normal emphasisCode.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 16:17'!\\naddNoiseString: aNoiseString emphasis: anInteger\\n\\n\\tself alansTest1 ifFalse: [^self].\\n\\t^(self addColumn: #keyword1 on: nil)\\n\\t\\tlayoutInset: 1;\\n\\t\\taddMorphBack: ((self noiseStringMorph: aNoiseString) emphasis: anInteger)\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/15/2001 19:22'!\\naddRow: aColorOrSymbol on: aNode\\n\\n\\t| row |\\n\\tself addMorphBack: (row _ self class row: aColorOrSymbol on: aNode).\\n\\n\\\"row setProperty: #howCreated toValue: thisContext longStack.\\\"\\n\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/24/2001 15:15'!\\naddSingleKeywordRow: aStringLikeItem\\n\\n\\t| row sMorph modifiedString |\\n\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\n\\tmodifiedString _ self substituteKeywordFor: aStringLikeItem.\\n\\tsMorph _ self addString: modifiedString special: true.\\n\\tsMorph font: (self fontToUseForSpecialWord: modifiedString).\\n\\tmodifiedString = aStringLikeItem ifFalse: [\\n\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem].\\n\\n\\trow addMorph: sMorph.\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 4/4/2001 13:15'!\\naddString: literalOrVarName special: aBoolean\\n\\n\\t| answer |\\n\\t\\\"Create and return an UpdatingStringMorph containing the value. Use an UpdatingStringMorph, so it can inform its owner when it has been edited. Keep the getSelector being nil\\\"\\n\\n\\tanswer _ (self anUpdatingStringMorphWith: literalOrVarName special: aBoolean)\\n\\t\\ttarget: self;\\n\\t\\tputSelector: #acceptIgnoring:;\\n\\t\\tuseStringFormat.\\n\\n\\t^answer\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:23'!\\naddTempVar: aMorph \\n\\t\\\"know we are a block inside a MethodNode\\\" \\n\\t\\\"(aMorph nodeClassIs: TempVariableNode) is known to be true.\\\"\\n\\t| tempHolder ii tt var nn |\\n\\tnn _ aMorph decompile string.\\t\\\"name\\\"\\n\\t(self isKnownVarName: nn) ifTrue: [^ false].\\t\\\"already defined\\\"\\n\\n\\ttempHolder _ nil.\\n\\t(ii _ owner submorphIndexOf: self) = 1 ifFalse: [\\n\\t\\ttt _ owner submorphs at: ii - 1.\\n\\t\\ttt isSyntaxMorph ifTrue: [\\n\\t\\t\\t(tt nodeClassIs: MethodTempsNode) ifTrue: [tempHolder _ tt].\\n\\t\\t\\t(tt nodeClassIs: UndefinedObject) ifTrue: [tempHolder _ tt findA: MethodTempsNode]]].\\n\\n\\ttempHolder ifNil: [\\n\\t\\ttempHolder _ owner addRow: #tempVariable on: MethodTempsNode new.\\n\\t\\ttempHolder addNoiseString: self noiseBeforeBlockArg.\\n\\t\\ttempHolder submorphs last firstSubmorph emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttempHolder useRoundedCorners.\\n\\n\\t\\towner addMorph: tempHolder inFrontOf: self.\\n\\t\\taMorph parseNode name: nn key: nn code: nil.\\n\\t\\taMorph parseNode asMorphicSyntaxIn: tempHolder.\\n\\t\\ttempHolder cleanupAfterItDroppedOnMe.\\n\\t\\t^ true].\\n\\n\\taMorph parseNode name: nn key: nn code: nil.\\n\\ttempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4).\\n\\tvar _ tempHolder addRow: #tempVariable on: aMorph parseNode.\\n\\tvar layoutInset: 1.\\n\\tvar addMorphBack: (self addString: nn special: false).\\n\\tvar cleanupAfterItDroppedOnMe.\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/10/2001 09:57'!\\naddTextRow: aStringLikeItem\\n\\n\\t| row tt |\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\t(tt _ TextMorph new) contents: aStringLikeItem.\\n\\trow addMorph: tt.\\n\\t\\\"row addMorph: (self addString: (aStringLikeItem copyWithout: Character cr) special: false).\\\"\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 7/25/2001 10:01'!\\naddToBlock: aMorph event: evt\\n\\t\\\"Insert a new line of code. Figure out who it goes before. If evt Y is within an existing line (to the right of a tile), then replace that tile.\\\"\\n\\n\\t| whereDropped dropBefore replace |\\n\\twhereDropped _ \\\"self pointFromWorld:\\\" evt cursorPoint.\\n\\tdropBefore _ self submorphs \\n\\t\\tdetect: [:each | each isSyntaxMorph ifTrue: [\\n\\t\\t\\twhereDropped y < each top ifTrue: [true]\\t\\\"before this one\\\"\\n\\t\\t\\t\\tifFalse: [whereDropped y < each bottom \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [replace _ true]\\t\\\"replace this one\\\"\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [false]]]] \\\"try next line\\\"\\n\\t\\tifNone: [nil].\\n\\t(aMorph nodeClassIs: ReturnNode) ifTrue: [dropBefore _ nil].\\n\\t\\t\\\"Returns are always at the end. (Watch out for comments)\\\"\\n\\n\\tdropBefore \\n\\t\\tifNil: [self addMorphBack: aMorph]\\n\\t\\tifNotNil: [\\n\\t\\t\\treplace ifNotNil: [aMorph deselect.\\n\\t\\t\\t\\tself replaceSubmorph: dropBefore by: aMorph.\\t\\\"replace it!!\\\"\\n\\t\\t\\t\\t^ dropBefore cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n\\t\\t\\tself addMorph: aMorph inFrontOf: dropBefore].\\n\\tself cleanupAfterItDroppedOnMe.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:22'!\\naddToken: aString type: aColorOrSymbol on: aNode\\n\\n\\t| sMorph modifiedString noiseWord row |\\n\\n\\trow _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1.\\n\\tself alansTest1 ifFalse: [\\n\\t\\tsMorph _ self addString: aString special: false.\\n\\t\\trow addMorphBack: sMorph.\\n\\t\\t^row\\n\\t].\\n\\n\\tnoiseWord _ [ :w |\\n\\t\\tw ifNotNil: [\\n\\t\\t\\trow \\n\\t\\t\\t\\taddMorphBack: (self noiseStringMorph: w);\\n\\t\\t\\t\\taddMorphBack: (self tokenVerticalSeparator)\\n\\t\\t].\\n\\t].\\n\\t(self shouldBeBrokenIntoWords: aColorOrSymbol) ifTrue: [\\n\\t\\tmodifiedString _ self substituteKeywordFor: aString.\\n\\t\\tsMorph _ self addString: modifiedString special: (aColorOrSymbol ~= #assignmentArrow).\\n\\t\\t\\t\\\"(#(unary keywordGetz keywordSetter unaryGetter) includes: aColorOrSymbol)\\\"\\n\\t\\tmodifiedString = aString ifFalse: [\\n\\t\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aString].\\n\\t\\tsMorph setProperty: #syntacticReformatting toValue: aColorOrSymbol;\\n\\t\\t\\tcontents: modifiedString.\\n\\t] ifFalse: [\\n\\t\\tsMorph _ self addString: (modifiedString _ aString) special: false.\\n\\t].\\n\\t(#(keyword2 upArrow) includes: aColorOrSymbol) ifTrue: [\\n\\t\\tsMorph \\n\\t\\t\\tfont: (self fontToUseForSpecialWord: modifiedString).\\n\\t].\\n\\t(#(keyword2 unary assignmentArrow methodHeader1 methodHeader2) includes: aColorOrSymbol) ifTrue: [\\n\\t\\tsMorph emphasis: TextEmphasis bold emphasisCode.\\n\\t].\\n\\taColorOrSymbol == #blockarg1 ifTrue: [\\n\\t].\\n\\t(aColorOrSymbol == #variable or: [aColorOrSymbol == #tempVariable]) ifTrue: [\\n\\t\\taString = 'self' ifTrue: [\\n\\t\\t\\tsMorph setProperty: #wordyVariantOfSelf toValue: true.\\n\\t\\t].\\n\\t\\tnoiseWord value: (self noiseWordBeforeVariableNode: aNode string: aString).\\n\\t].\\n\\n\\trow addMorphBack: sMorph.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 17:22'!\\naddTokenSpecialCase: aString type: aColorOrSymbol on: aNode\\n\\n\\t| sMorph modifiedString noiseWord col |\\n\\n\\tnoiseWord _ nil.\\n\\tsMorph _ self addString: aString special: false.\\n\\t(aColorOrSymbol == #keyword2) ifTrue: [\\n\\t\\tmodifiedString _ aString = 'if:' ifTrue: ['Test'] ifFalse: ['Yes'].\\n\\t\\tsMorph \\n\\t\\t\\tfont: (self fontToUseForSpecialWord: modifiedString); \\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: aString;\\n\\t\\t\\tcontents: modifiedString.\\n\\t].\\n\\n\\tcol _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1.\\n\\tnoiseWord ifNotNil: [\\n\\t\\tcol \\n\\t\\t\\taddMorphBack: (self noiseStringMorph: noiseWord);\\n\\t\\t\\taddMorphBack: (self transparentSpacerOfSize: 3@1)\\n\\t].\\n\\tcol addMorphBack: sMorph.\\n\\t^col! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/24/2001 15:21'!\\naddUnaryRow: aStringLikeItem style: aSymbol\\n\\n\\t| row sMorph modifiedString fontToUse |\\n\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\tmodifiedString _ self substituteKeywordFor: aStringLikeItem.\\n\\tsMorph _ self addString: modifiedString special: true.\\n\\tfontToUse _ self fontToUseForSpecialWord: modifiedString.\\n\\n\\tsMorph \\n\\t\\tfont: fontToUse emphasis: 1;\\n\\t\\tsetProperty: #syntacticReformatting toValue: #unary.\\n\\tmodifiedString = aStringLikeItem ifFalse: [\\n\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem].\\n\\trow addMorph: sMorph.\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/15/2001 19:43'!\\nfoldMessage\\n\\t\\\"I am a message whose receiver is wide, and whose message part is a column.\\n\\tRearrange me so that the message part appears indented under the receiver part.\\\"\\n\\t| messageRow node2 |\\n\\tnode2 _ parseNode copy receiver: nil.\\n\\tmessageRow _ SyntaxMorph row: #keyword1 on: node2.\\n\\n\\tmessageRow \\n\\t\\taddMorph: (self transparentSpacerOfSize: 20@10);\\n\\t\\taddMorphBack: submorphs last.\\t\\t\\\"<<handle noise words better\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\taddMorphBack: (self transparentSpacerOfSize: 4@4);\\n\\t\\taddMorphBack: messageRow.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 1/15/2001 11:15'!\\nfoldMessageOneArg\\n\\t\\\"I am a message that is wide, a row with receiver and a row with selector and arg.\\n\\tRearrange me so that the message part appears indented under the receiver part.\\\"\\n\\t| messageRow node2 |\\n\\tnode2 _ parseNode copy receiver: nil.\\n\\tmessageRow _ SyntaxMorph row: #keyword1 on: node2.\\n\\tmessageRow addMorph: (self transparentSpacerOfSize: 20@10);\\n\\t\\t\\taddMorphBack: submorphs second;\\n\\t\\t\\taddMorphBack: submorphs second. \\\"was the third\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\taddMorphBack: messageRow.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/22/2001 16:30'!\\nisKnownVarName: newVarName\\n\\t\\\"Return true if this variable is already known, as an argument, temp var, block temp, or instance variable.\\\"\\n\\n\\t| syntLevel |\\n\\t(self parsedInClass allInstVarNames includes: newVarName) ifTrue: [^ true].\\n\\tsyntLevel _ self.\\n\\t[syntLevel tempVarNodesDo: [:node | \\n\\t\\tnode decompile string = newVarName ifTrue: [^ true]].\\n\\t (syntLevel _ syntLevel owner) isSyntaxMorph] whileTrue.\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/1/2001 13:06'!\\nremoveReturnNode\\n\\t| blk |\\n\\t\\\"If last line is ^ self, remove it. I am a methodNode. Keep if no other tiles in the block.\\\"\\n\\n\\tblk _ self findA: BlockNode.\\n\\tblk submorphs last decompile string = '^self ' ifTrue: [\\n\\t\\t(blk submorphs count: [:ss | ss isSyntaxMorph]) > 1 ifTrue: [\\n\\t\\t\\tblk submorphs last delete]].! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/22/2001 16:35'!\\ntempVarNodesDo: aBlock\\n\\t\\\"Execute the block for any block temporary variables, method temps, or method args we have\\\"\\n\\n\\t| tempHolder argsHolder |\\n\\t((self parseNode class == MethodNode) or: [self parseNode class == BlockNode]) ifTrue: [\\n\\t\\tself submorphsDoIfSyntax: [:sub | \\n\\t\\t\\t\\t(sub nodeClassIs: MethodTempsNode) ifTrue: [tempHolder _ sub].\\n\\t\\t\\t\\t((sub nodeClassIs: UndefinedObject) and: [tempHolder isNil]) ifTrue: [\\n\\t\\t\\t\\t\\ttempHolder _ sub findA: MethodTempsNode].\\n\\t\\t\\t\\t(sub nodeClassIs: BlockArgsNode) ifTrue: [tempHolder _ sub].\\n\\t\\t\\t\\t(sub nodeClassIs: SelectorNode) ifTrue: [argsHolder _ sub].\\n\\t\\t\\t\\t]\\n\\t\\t\\tifString: [:sub | ].\\n\\t\\ttempHolder ifNotNil: [\\\"Temp variables\\\"\\n\\t\\t\\ttempHolder submorphsDoIfSyntax: [:sm | \\n\\t\\t\\t\\t\\t(sm nodeClassIs: TempVariableNode) ifTrue: [aBlock value: sm]]\\n\\t\\t\\t\\tifString: [:sm | ]].\\n\\t\\targsHolder ifNotNil: [\\\"arguments\\\"\\n\\t\\t\\targsHolder submorphsDoIfSyntax: [:sm | \\n\\t\\t\\t\\t\\t(sm nodeClassIs: TempVariableNode) ifTrue: [aBlock value: sm]]\\n\\t\\t\\t\\tifString: [:sm | ]].\\n\\t\\t].\\n\\t\\\"otherwise do nothing\\\"! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 2/12/2001 14:39'!\\ntry\\n\\t\\\"Evaluate me once\\\"\\n\\n\\t(#(MessageNode LiteralNode VariableNode) includes: parseNode class name) \\n\\t\\tifFalse: [^ Error new].\\n\\t^ [Compiler evaluate: self decompile\\n\\t\\t\\t\\tfor: self actualObject\\n\\t\\t\\t\\tlogged: false.\\t\\\"should do something to the player\\\"\\n\\t\\t] ifError: [ :a :b | Error new].! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'ar 8/10/2003 18:19'!\\nunfoldMessage\\n\\t\\\"I am a message whose message part is a column.\\n\\tRearrange me so that the entire message is one row.\\\"\\n\\t| messageRow |\\n\\tmessageRow _ self submorphs last.\\n\\tself removeMorph: messageRow.\\n\\tmessageRow submorphs do: [:m | self addMorphBack: m].\\n\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'macpal' stamp: 'sw 6/4/2001 19:26'!\\ncurrentVocabulary\\n\\t\\\"Answer the current vocabulary associated with the receiver. If none is yet set, determine an appropriate vocabulary and cache it within my properties dictionary.\\\"\\n\\n\\t| aVocab aSym |\\n\\taSym _ self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil].\\n\\taSym ifNil:\\n\\t\\t[aVocab _ self valueOfProperty: #currentVocabulary ifAbsent: [nil].\\n\\t\\taVocab ifNotNil:\\n\\t\\t\\t[aSym _ aVocab vocabularyName.\\n\\t\\t\\tself removeProperty: #currentVocabulary.\\n\\t\\t\\tself setProperty: #currentVocabularySymbol toValue: aSym]].\\n\\n\\taSym ifNotNil:\\n\\t\\t[^ Vocabulary vocabularyNamed: aSym].\\n\\taVocab _ super currentVocabulary.\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocab vocabularyName.\\n\\t^ aVocab! !\\n\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 19:09'!\\naccept\\n\\t\\\"Turn my current state into the text of a method. Compile it in my class.\\\"\\n\\n\\t^ self acceptInCategory: ClassOrganizer default! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 11/21/2000 16:35'!\\nacceptIfInScriptor\\n\\t| root |\\n\\t\\\"If I am in a ScriptEditorMorph, tell my root to accept the new changes.\\\"\\n\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNotNil: [\\n\\t\\troot _ self rootTile.\\n\\t\\troot ifNotNil: [root accept]]. ! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'RAA 2/14/2001 15:40'!\\nacceptIgnoring: aString\\n\\t\\\"If I am inside a ScriptEditorMorph, tell my root to accept the new changes. Ignore the argument, which is the string whose conents just changed.\\\"\\n\\n\\tthisContext sender receiver removeProperty: #syntacticallyCorrectContents.\\n\\tself acceptIfInScriptor! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 17:15'!\\nacceptInCategory: categoryString\\n\\t\\\"Turn my current state into the text of a method. Compile it in my class.\\\"\\n\\t| cls sc sel |\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile accept \\\"always accept at the root\\\"].\\n\\t(cls _ self parsedInClass) ifNil: [^ self].\\n\\tsel _ cls compile: self decompile classified: categoryString.\\n\\t(sc _ self firstOwnerSuchThat: [:mm | mm class == ScriptEditorMorph]) \\n\\t\\tifNotNil: [sc hibernate; unhibernate].\\t\\\"rebuild the tiles\\\"\\n\\t^ sel! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 19:12'!\\nacceptSilently\\n\\t\\\"Turn my current state into the text of a method.\\n\\tCompile it in my class. Don't rebuild the tiles.\\\"\\n\\t| cls |\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ false]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile acceptSilently \\\"always accept at the root\\\"].\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNil: [^ false].\\n\\t(cls _ self parsedInClass) ifNil: [^ false].\\n\\tcls compile: self decompile classified: 'scripts'.\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 5/4/2001 12:14'!\\nacceptUnlogged\\n\\t\\\"This is an exact copy of acceptSilently, except it does not log to the source file.\\n\\tUsed for all but the last of scrolling number changes.\\\"\\n\\t| cls |\\n\\tself isMethodNode ifFalse:\\n\\t\\t[self rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile acceptUnlogged \\\"always accept at the root\\\"].\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNil: [^ self].\\n\\t(cls _ self parsedInClass) ifNil: [^ self].\\n\\tcls compile: self decompile\\n\\t\\tclassified: ClassOrganizer default\\n\\t\\twithStamp: nil\\n\\t\\tnotifying: nil\\n\\t\\tlogSource: false.\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'md 8/15/2005 11:02'!\\ndecompile\\n\\t| stream |\\n\\t\\\"Produce Smalltalk code. We have a tree of SyntaxMorphs, but not a tree of ParseNodes. The user has dragged in many SyntaxMorphs, each with its own parseNode, but those nodes are not sewn together in a tree. The only data we get from a ParseNode is its class.\\n\\tWe produce really ugly code. But we compile it and decompile (prettyPrint) again for user to see.\\\"\\n\\n\\tstream _ ColoredCodeStream on: (Text new: 400).\\n\\tself printOn: stream indent: 1.\\t\\\"Tree walk and produce text of the code\\\"\\n\\t^ stream contents! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 11/13/2000 20:23'!\\ngetMenuBlock\\n\\n\\t^ nil! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/23/2001 02:05'!\\nofferTilesMenuFor: aReceiver in: aLexiconModel\\n\\t\\\"Offer a menu of tiles for assignment and constants\\\"\\n\\n\\t| menu |\\n\\tmenu _ MenuMorph new addTitle: 'Hand me a tile for...'.\\n\\tmenu addLine.\\n\\tmenu add: '(accept method now)' target: aLexiconModel selector: #acceptTiles.\\n\\tmenu submorphs last color: Color red darker.\\n\\tmenu addLine.\\n\\n\\tmenu add: 'me, by name' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'<me by name>'. aReceiver}.\\n\\tmenu add: 'self' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'self'. VariableNode}.\\n\\tmenu add: '_ (assignment)' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'<assignment>'. nil}.\\n\\tmenu add: '\\\"a Comment\\\"' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'\\\"a comment\\\"\\\\' withCRs. CommentNode}.\\n\\tmenu submorphs last color: Color blue.\\n\\tmenu add: 'a Number' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'5'. LiteralNode}.\\n\\tmenu add: 'a Character' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'$z'. LiteralNode}.\\n\\tmenu add: '''abc''' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'''abc'''. LiteralNode}.\\n\\tmenu add: 'a Symbol constant' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'#next'. LiteralNode}.\\n\\tmenu add: 'true' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'true'. VariableNode}.\\n\\tmenu add: 'a Test' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'true ifTrue: [self] ifFalse: [self]'. MessageNode}.\\n\\tmenu add: 'a Loop' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'1 to: 10 do: [:index | self]'. MessageNode}.\\n\\tmenu add: 'a Block' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'[self]'. BlockNode}.\\n\\tmenu add: 'a Class or Global' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'Character'. LiteralVariableNode}.\\n\\tmenu add: 'a Reply' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'| temp | temp'. ReturnNode}.\\n\\tmenu popUpAt: ActiveHand position forHand: ActiveHand in: World.\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/17/2001 13:38'!\\nofferVarsMenuFor: aReceiver in: aLexiconModel\\n\\t\\\"Offer a menu of tiles for assignment and constants\\\"\\n\\n\\t| menu instVarList cls |\\n\\tmenu _ MenuMorph new addTitle: 'Hand me a tile for...'.\\n\\tmenu addLine.\\n\\tmenu add: '(accept method now)' target: aLexiconModel selector: #acceptTiles.\\n\\tmenu submorphs last color: Color red darker.\\n\\tmenu addLine.\\n\\tmenu add: 'new temp variable' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'| temp | temp'. TempVariableNode}.\\n\\n\\tinstVarList _ OrderedCollection new.\\n\\tcls _ aReceiver class.\\n\\t[instVarList addAllFirst: cls instVarNames.\\n\\t cls == aLexiconModel limitClass] whileFalse: [cls _ cls superclass].\\n\\tinstVarList do: [:nn |\\n\\t\\tmenu add: nn target: self selector: #instVarTile: argument: nn].\\n\\tmenu popUpAt: ActiveHand position forHand: ActiveHand in: World.\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 12/14/2001 11:58'!\\nputOnBackground\\n\\t\\\"Place the receiver, formerly private to its card, onto the shared background. If the receiver needs data carried on its behalf by the card, such data will be represented on every card.\\\"\\n\\n\\t| updStr |\\n\\t(updStr _ self readOut) ifNotNil: [\\\"If has a place to put per-card data, set that up.\\\"\\n\\t\\tupdStr getSelector ifNotNil: [\\n\\t\\t\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true]].\\n\\tsuper putOnBackground.! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 11/17/2000 09:00'!\\nshowCode\\n\\t\\\"Turn my current state into the text of a method. Put it in a window.\\\"\\n\\n\\t(Workspace new contents: self rootTile decompile) openLabel: self printString,' code'\\n\\n\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 12/10/2001 17:48'!\\nshowMenu: evt\\n\\t| menu |\\n\\tmenu _ MenuMorph new.\\n\\tself rootTile isMethodNode ifTrue:\\n\\t\\t[menu add: 'accept method' target: self selector: #accept.\\n\\t\\tmenu addLine.\\n\\n\\t\\tmenu add: 'new temp variable' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\t\\targumentList: {'| temp | temp'. TempVariableNode}.\\n\\t\\tmenu addLine.\\n\\n\\t\\tself parsedInClass allInstVarNames do: [:nn |\\n\\t\\t\\tmenu add: nn,' tile' target: self selector: #instVarTile: argument: nn].\\n\\t\\tmenu addLine.\\n\\n\\t\\tmenu add: 'show code' target: self selector: #showCode.\\n\\t\\tmenu add: 'try out' target: self selector: #try.\\n\\t\\tmenu popUpAt: evt hand position forHand: evt hand in: World].\\n\\n\\n\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'FBS 2/24/2004 14:32'!\\nattachTileForCode: expression nodeType: nodeClass\\n\\t| nn master tile |\\n\\t\\\"create a new tile for a part of speech, and put it into the hand\\\"\\n\\n\\t\\\"a few special cases\\\"\\n\\texpression = 'self' ifTrue: [\\n\\t\\t^ (((self string: expression toTilesIn: Object) \\n\\t\\t\\t\\tfindA: ReturnNode) findA: nodeClass) attachToHand].\\n\\n\\texpression = '<me by name>' ifTrue: [\\\"Tile for the variable in References\\\"\\n\\t\\tnn _ nodeClass knownName ifNil: [#+].\\n\\t\\t(References at: nn asSymbol ifAbsent: [nil]) == nodeClass ifTrue: [\\n\\t\\t\\t^ self attachTileForCode: nn nodeType: LiteralVariableNode].\\n\\t\\t\\\"otherwise just give a tile for self\\\"\\n\\t\\t^ self attachTileForCode: 'self' nodeType: VariableNode].\\n\\n\\texpression = '<assignment>' ifTrue: [\\\"do something really special\\\"\\n\\t\\tmaster _ self class new.\\n\\t\\tmaster addNoiseString: ' _ ' emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttile _ master firstSubmorph.\\n\\t\\t^ (tile parseNode: AssignmentNode new) attachToHand].\\t\\\"special marker\\\"\\n\\t\\t\\\"When this is dropped on a variable, enclose it in \\n\\t\\t\\ta new assignment statement\\\"\\n\\n\\t\\\"general case -- a tile for a whole line of code is returned\\\"\\n\\t^ ((self string: expression toTilesIn: Object) \\n\\t\\t\\t\\tfindA: nodeClass) attachToHand.! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 9/7/2001 11:21'!\\nattachToHand\\n\\t\\\"Adjust my look and attach me to the hand\\\"\\n\\n\\tself roundedCorners.\\n\\tActiveHand attachMorph: self.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [self lookTranslucent.\\n\\t\\t\\tself align: self center with: ActiveHand position \\\"+ self cursorBaseOffset\\\"]\\n\\t\\tifFalse: [self align: self topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 8/30/2001 06:22'!\\ninstVarTile: aName\\n\\t\\\"Make and put into hand a tile for an instance variable\\\"\\n\\n\\t| sm |\\n\\tsm _ ((VariableNode new\\n\\t\\t\\t\\t\\tname: aName\\n\\t\\t\\t\\t\\tindex: 1\\n\\t\\t\\t\\t\\ttype: 1 \\\"LdInstType\\\") asMorphicSyntaxIn: SyntaxMorph new).\\n\\tsm roundedCorners.\\n\\tActiveHand attachMorph: sm.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [sm lookTranslucent.\\n\\t\\t\\tsm align: sm center with: ActiveHand position \\\"+ self cursorBaseOffset\\\"]\\n\\t\\tifFalse: [sm align: sm topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 9/13/2001 13:44'!\\nstring: anExpression toTilesIn: playerClass\\n\\t| code tree methodNode |\\n\\t\\\"Construct SyntaxMorph tiles for some code. Returns the main BlockNode of a doIt.\\\"\\n\\n\\t\\\"This is really cheating!! Make a true parse tree later. -tk\\\"\\n\\tcode _ String streamContents: [:strm | \\n\\t\\tstrm nextPutAll: 'doIt'; cr; tab; nextPutAll: anExpression].\\n\\t\\\"decompile to tiles\\\"\\n\\ttree _ Compiler new \\n\\t\\tparse: code \\n\\t\\tin: playerClass\\n\\t\\tnotifying: nil.\\n\\tmethodNode _ tree asMorphicSyntaxUsing: SyntaxMorph.\\n\\tanExpression first == $\\\" ifTrue: [\\\"a comment\\\" \\n\\t\\t\\\"(methodNode findA: CommentNode) firstSubmorph color: Color blue.\\\"\\n\\t\\t^ methodNode].\\n\\t^ methodNode submorphs detect: [:mm | \\n\\t\\t(mm respondsTo: #parseNode) \\n\\t\\t\\tifTrue: [mm parseNode class == BlockNode] \\n\\t\\t\\tifFalse: [false]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:23'!\\naddTemporaries: temporaries \\n\\t| tempMorph outerMorph w2 |\\n\\ttemporaries notEmpty ifFalse: [^self].\\n\\tself alansTest1 \\n\\t\\tifFalse: \\n\\t\\t\\t[tempMorph := self addRow: #tempVariable on: MethodTempsNode new.\\n\\t\\t\\ttemporaries do: [:temp | temp asMorphicSyntaxIn: tempMorph]\\n\\t\\t\\t\\tseparatedBy: \\n\\t\\t\\t\\t\\t[tempMorph addMorphBack: (tempMorph transparentSpacerOfSize: 4 @ 4)].\\n\\t\\t\\t^self].\\n\\touterMorph := self addRow: #tempVariable on: nil.\\n\\touterMorph setSpecialTempDeclarationFormat1.\\n\\touterMorph \\n\\t\\taddMorphBack: (w2 := self noiseStringMorph: self noiseBeforeBlockArg).\\n\\tw2 emphasis: TextEmphasis bold emphasisCode.\\n\\ttempMorph := outerMorph addRow: #tempVariable on: MethodTempsNode new.\\n\\ttempMorph setSpecialTempDeclarationFormat2.\\n\\ttemporaries do: \\n\\t\\t\\t[:temp | \\n\\t\\t\\ttempMorph \\n\\t\\t\\t\\taddToken: temp name\\n\\t\\t\\t\\ttype: #tempVariableDeclaration\\n\\t\\t\\t\\ton: temp]\\n\\t\\tseparatedBy: [tempMorph addMorphBack: self tokenVerticalSeparator]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/31/2001 17:27'!\\naddTemporaryControls\\n\\n\\t| row stdSize |\\n\\t\\n\\tstdSize _ 8@8.\\n\\trow _ AlignmentMorph newRow\\n\\t\\tcolor: Color transparent;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tself addMorphBack: row.\\n\\n\\t{\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color paleBlue darker;\\n\\t\\t\\tsetBalloonText: 'Change the contrast';\\n\\t\\t\\ton: #mouseUp send: #controlContrast2: to: self;\\n\\t\\t\\ton: #mouseMove send: #controlContrast2: to: self;\\n\\t\\t\\ton: #mouseDown send: #controlContrast2: to: self.\\n\\n\\t\\\"Removed because it's default is giant tiles, which no one wants. --tk\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color green;\\n\\t\\t\\tsetBalloonText: 'Change basic spacing';\\n\\t\\t\\ton: #mouseUp send: #controlSpacing2: to: self;\\n\\t\\t\\ton: #mouseMove send: #controlSpacing2: to: self;\\n\\t\\t\\ton: #mouseDown send: #controlSpacing2: to: self.\\n\\t\\\"\\n\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color lightRed;\\n\\t\\t\\tsetBalloonText: 'Change basic style';\\n\\t\\t\\ton: #mouseUp send: #changeBasicStyle to: self.\\n\\n\\t} do: [ :each |\\n\\t\\trow addMorphBack: each.\\n\\t\\trow addMorphBack: (self transparentSpacerOfSize: stdSize).\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 12/3/2004 17:01'!\\nalanBinaryPostRcvr: aNode key: key args: args\\n\\n\\t| nodeWithNilReceiver row |\\n\\n\\\"==\\nRepeat for collection [ collect ( from foo. blah blah foo blah) ]\\nRepeat for 1 to 50 [ do ( from i. blah blab i blah ) ]\\n==\\\"\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\trow addToken: key asString\\n\\t\\ttype: #binary\\n\\t\\ton: (SelectorNode new key: key asString code: nil \\\"fill this in?\\\").\\n\\targs first asMorphicSyntaxIn: row.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/30/2001 14:52'!\\nalanKeywordMessage: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver column keywords row onlyOne |\\n\\n\\t(key == #collect: and: [args first isKindOf: BlockNode]) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdCollect: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tkey == #repeatFor:doing: ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdRepeatForDoing: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tkey == #if:do: ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdIfDo: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\t(args size = 1 and: [key endsWith: 'Getz:']) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdSetter: aNode \\n\\t\\t\\tisAConditional: 0 \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\t(args size = 1 and: [self isStandardSetterKeyword: key]) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdSetter2: aNode \\n\\t\\t\\tisAConditional: 0 \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\ttemplate = 1 ifTrue: [\\n\\t\\tself listDirection: #topToBottom.\\n\\t].\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\tkeywords _ key keywords.\\n\\tonlyOne _ args size = 1.\\n\\tonlyOne ifFalse: [\\\"necessary for three keyword messages!!\\\"\\n\\t\\tcolumn setProperty: #deselectedBorderColor toValue: column compoundBorderColor].\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\ttemplate = 1 ifTrue: [\\n\\t\\t\\t\\tcolumn addMorphBack: (column transparentSpacerOfSize: 3@3).\\n\\t\\t\\t].\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: \\n\\t\\t\\t\\t\\t\\t(onlyOne ifTrue: [MessageNode] ifFalse: [MessagePartNode]));\\n\\t\\t\\t\\tborderColor: row stdBorderColor.\\n\\t\\t\\ttemplate = 1 ifTrue: [row addMorphBack: (row transparentSpacerOfSize: 20@6)].\\n\\t\\t\\trow addToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: (onlyOne ifTrue: [SelectorNode new key: kwd code: nil \\\"fill this in?\\\"]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [KeyWordNode new]).\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n\\tonlyOne ifTrue: [\\n\\t\\tself replaceSubmorph: column by: row.\\n\\t\\tcolumn _ row.\\n\\t].\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 3/25/2001 16:31'!\\nalanKwdCollect: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row kwdHolder |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\tkwdHolder _ row\\n\\t\\taddToken: key\\n\\t\\ttype: #keyword2\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString;\\n\\t\\tcontents: ''.\\n\\n\\targs first asMorphicCollectSyntaxIn: row.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/30/2001 14:52'!\\nalanKwdIfDo: aNode isAConditional: template key: key args: args\\n\\t\\\"(know it has more than one arg)\\\"\\n\\t| nodeWithNilReceiver column keywords row |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\t\\\"column borderColor: column compoundBorderColor.\\\"\\n\\tkeywords _ key keywords.\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: MessagePartNode).\\n\\t\\t\\tkwd = 'do:' ifTrue: [\\n\\t\\t\\t\\trow addMorphBack: (row transparentSpacerOfSize: 26@6).\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\trow addMorphBack: (row transparentSpacerOfSize: 10@6).\\n\\t\\t\\t].\\n\\t\\t\\trow addTokenSpecialCase: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: KeyWordNode new.\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:16'!\\nalanKwdRepeatForDoing: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row column keywords |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\tkeywords _ key keywords.\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: MessagePartNode).\\n\\t\\t\\trow addToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: KeyWordNode new.\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:22'!\\nalanKwdSetter2: aNode isAConditional: template key: key args: args\\n\\t\\\"translates\\n\\t\\tfoo setHeading: 0\\n\\tto\\n\\t\\tfoo's heading _ 0\\n\\t\\\"\\n\\t| kwdHolder wordy |\\n\\tkwdHolder _ self\\n\\t\\taddToken: key\\n\\t\\ttype: #keywordSetter\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\twordy _ self translateToWordySetter: key.\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticReformatting toValue: #keywordSetter;\\n\\t\\tcontents: wordy;\\n\\t\\temphasis: TextEmphasis bold emphasisCode.\\n\\twordy = key asString ifFalse: [\\n\\t\\tkwdHolder firstSubmorph \\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString].\\n\\n\\t(args first asMorphicSyntaxIn: self) setConditionalPartStyle\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:22'!\\nalanKwdSetter: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row kwdHolder |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\trow addNoiseString: '''s' emphasis: TextEmphasis bold emphasisCode.\\n\\tkwdHolder _ row\\n\\t\\taddToken: key\\n\\t\\ttype: #keywordGetz\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticReformatting toValue: #keywordGetz;\\n\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString;\\n\\t\\tcontents: (self splitAtCapsAndDownshifted: (key asString allButLast: 5));\\n\\t\\temphasis: TextEmphasis bold emphasisCode.\\n\\trow addNoiseString: '_' emphasis: TextEmphasis bold emphasisCode.\\n\\n\\t(args first asMorphicSyntaxIn: row) setConditionalPartStyle\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:21'!\\nalanUnaryGetter: aNode key: key\\n\\t\\\"I am a MessageNode. Fill me with a SelectorNode {getX} whose string is {'s x}. All on one level.\\\"\\n\\n\\t| selSyn usm wordy |\\n\\tselSyn _ self\\n\\t\\taddToken: key\\n\\t\\ttype: #unaryGetter\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tusm _ selSyn firstSubmorph.\\n\\tusm setProperty: #syntacticReformatting toValue: #unaryGetter.\\n\\twordy _ self translateToWordyGetter: key.\\n\\twordy = key asString ifFalse: [\\n\\t\\tusm setProperty: #syntacticallyCorrectContents toValue: key asString].\\n\\tusm contents: wordy; emphasis: TextEmphasis bold emphasisCode.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 4/4/2001 12:49'!\\nalanUnaryPostRcvr: aNode key: key selector: selector\\n\\n\\t| row |\\n\\n\\t(self isStandardGetterSelector: key) ifTrue: [\\n\\t\\t^self alanUnaryGetter: aNode key: key\\n\\t].\\n\\trow _ (self addUnaryRow: key style: #unary) layoutInset: 1.\\n\\t^ row parseNode: selector\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:38'!\\nalansMessageNode: aNode receiver: receiver selector: selector keywords: key arguments: args \\n\\t| receiverMorph testAndReceiver anotherSelf wordyMorph template |\\n\\ttemplate := self alansTemplateStyleFor: key.\\n\\treceiver ifNotNil: \\n\\t\\t\\t[\\\"i.e. not a cascade\\\"\\n\\n\\t\\t\\tanotherSelf := self constructSelfVariant: receiver and: key.\\n\\t\\t\\tanotherSelf ifNotNil: \\n\\t\\t\\t\\t\\t[wordyMorph := self addString: anotherSelf special: false.\\n\\t\\t\\t\\t\\twordyMorph setProperty: #wordyVariantOfSelf toValue: true.\\n\\t\\t\\t\\t\\tself addMorph: wordyMorph.\\n\\t\\t\\t\\t\\tself layoutInset: 1.\\n\\t\\t\\t\\t\\t^self].\\n\\t\\t\\ttestAndReceiver := self.\\n\\t\\t\\ttemplate = 1 \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[testAndReceiver := self addRow: #keyword1 on: nil.\\n\\t\\t\\t\\t\\tself setSpecialOuterTestFormat.\\n\\t\\t\\t\\t\\ttestAndReceiver addNoiseString: 'Test'].\\n\\t\\t\\tfalse \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"template = 2\\\"\\n\\n\\t\\t\\t\\t\\ttestAndReceiver := self addRow: #keyword1 on: nil.\\n\\t\\t\\t\\t\\t\\\"self setSpecialOuterTestFormat.\\\"\\n\\t\\t\\t\\t\\ttestAndReceiver addNoiseString: 'Repeat for'].\\n\\t\\t\\treceiverMorph := receiver asMorphicSyntaxIn: testAndReceiver.\\n\\t\\t\\ttemplate = 1 ifTrue: [receiverMorph setConditionalPartStyle]].\\n\\n\\t\\\"unary messages\\\"\\n\\targs isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talanUnaryPostRcvr: aNode\\n\\t\\t\\t\\tkey: key\\n\\t\\t\\t\\tselector: selector].\\n\\n\\t\\\"binary messages\\\"\\n\\tkey last = $: \\n\\t\\tifFalse: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talanBinaryPostRcvr: aNode\\n\\t\\t\\t\\tkey: key\\n\\t\\t\\t\\targs: args].\\n\\n\\t\\\"keyword messages\\\"\\n\\treceiverMorph ifNotNil: [receiverMorph setConditionalPartStyle].\\n\\tself setSpecialOuterTestFormat.\\n\\tself \\n\\t\\talanKeywordMessage: aNode\\n\\t\\tisAConditional: template\\n\\t\\tkey: key\\n\\t\\targs: args! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/27/2001 14:19'!\\nassignmentNode: aNode variable: variable value: value\\n\\n\\t| row v expMorph |\\n\\n\\trow _ self addRow: #assignment on: aNode.\\n\\tv _ variable asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [v setConditionalPartStyle; layoutInset: 2].\\n\\trow addToken: ' _ ' type: #assignmentArrow on: aNode.\\n\\texpMorph _ value asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t\\t(expMorph hasProperty: #deselectedColor) ifFalse: [expMorph setConditionalPartStyle].\\n\\t].\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:39'!\\nblockNode: aNode arguments: arguments statements: statements \\n\\t| row column |\\n\\tcolumn := self addColumn: #block on: aNode.\\n\\tself alansTest1 ifFalse: [column layoutInset: 5 @ -1].\\n\\tself alansTest1 \\n\\t\\tifTrue: \\n\\t\\t\\t[column setProperty: #deselectedBorderColor toValue: self lighterColor].\\n\\taNode addCommentToMorph: column.\\n\\targuments notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := column addRow: #blockarg1 on: BlockArgsNode new.\\n\\t\\t\\trow addNoiseString: self noiseBeforeBlockArg.\\n\\t\\t\\targuments do: \\n\\t\\t\\t\\t\\t[:arg | \\n\\t\\t\\t\\t\\trow \\n\\t\\t\\t\\t\\t\\taddToken: arg name\\n\\t\\t\\t\\t\\t\\ttype: #blockarg2\\n\\t\\t\\t\\t\\t\\ton: arg]].\\n\\tstatements do: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(row := each asMorphicSyntaxIn: column) borderWidth: 1.\\n\\t\\t\\tself alansTest1 ifTrue: [row setSpecialOuterTestFormat].\\n\\t\\t\\teach addCommentToMorph: column].\\n\\t^column! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:32'!\\nblockNodeCollect: aNode arguments: arguments statements: statements \\n\\t| row column c2 r2 r3 |\\n\\tcolumn := self addColumn: #blockCollectOnly on: aNode.\\n\\tself alansTest1 ifFalse: [column layoutInset: 5 @ -1].\\n\\taNode addCommentToMorph: column.\\n\\targuments notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := column addRow: #blockarg1 on: BlockArgsNode new.\\n\\t\\t\\trow addNoiseString: 'collect using' emphasis: TextEmphasis bold emphasisCode.\\n\\t\\t\\tr3 := row addRow: #blockarg1b on: nil.\\t\\\"aNode\\\"\\n\\t\\t\\tr3 setConditionalPartStyle.\\n\\t\\t\\targuments do: \\n\\t\\t\\t\\t\\t[:arg | \\n\\t\\t\\t\\t\\tr3 \\n\\t\\t\\t\\t\\t\\taddToken: arg name\\n\\t\\t\\t\\t\\t\\ttype: #blockarg2\\n\\t\\t\\t\\t\\t\\ton: arg]].\\n\\tr2 := column addRow: #block on: aNode.\\n\\tr2 setProperty: #ignoreNodeWhenPrinting toValue: true.\\n\\tr2 addNoiseString: self noiseBeforeBlockArg emphasis: TextEmphasis bold emphasisCode.\\n\\tc2 := r2 addColumn: #block on: aNode.\\n\\tc2 setProperty: #ignoreNodeWhenPrinting toValue: true.\\n\\tstatements do: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each asMorphicSyntaxIn: c2) borderWidth: 1.\\n\\t\\t\\teach addCommentToMorph: c2].\\n\\t^column! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/22/2001 17:00'!\\ncascadeNode: aNode receiver: receiver messages: messages\\n\\t| row |\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow _ self addColumn: #cascade on: aNode.\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t] ifFalse: [\\n\\t\\trow _ self addRow: #cascade on: aNode\\n\\t].\\n\\treceiver asMorphicSyntaxIn: row.\\n\\tmessages do: [:m | m asMorphicSyntaxIn: row].\\n\\t^ row\\n\\n\\\"\\t(node2 _ aNode copy) receiver: nil messages: messages.\\n\\tcascadeMorph _ row addColumn: #cascade2 on: node2.\\n\\tmessages do: [ :m | m asMorphicSyntaxIn: cascadeMorph].\\n\\t^row\\n\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/16/2001 16:34'!\\nchangeBasicStyle\\n\\n\\tself removeAllMorphs.\\n\\tself setProperty: #alansNewStyle toValue: self alansTest1 not.\\n\\tself methodNodeOuter: parseNode\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'gm 2/22/2003 13:42'!\\nfinalAppearanceTweaks\\n\\t| deletes lw |\\n\\tSizeScaleFactor ifNil: [SizeScaleFactor := 0.15].\\n\\tSizeScaleFactor := 0.0.\\t\\\"disable this feature. Default was for giant tiles\\\"\\n\\tself usingClassicTiles \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tallMorphsDo: [:each | (each isSyntaxMorph) ifTrue: [each lookClassic]].\\n\\t\\t\\t^self].\\n\\tdeletes := OrderedCollection new.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each respondsTo: #setDeselectedColor) ifTrue: [each setDeselectedColor].\\n\\t\\t\\t\\\"(each hasProperty: #variableInsetSize) ifTrue: [\\n\\t\\t\\teach layoutInset: \\n\\t\\t\\t\\t((each valueOfProperty: #variableInsetSize) * SizeScaleFactor) rounded].\\\"\\n\\t\\t\\teach isSyntaxMorph \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[lw := each layoutInset.\\n\\t\\t\\t\\t\\tlw isPoint ifTrue: [lw := lw x].\\n\\t\\t\\t\\t\\teach layoutInset: lw @ 0\\t\\\"(6 * SizeScaleFactor) rounded\\\"]].\\n\\tdeletes do: [:each | each delete]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 11/11/2002 10:30'!\\nisStandardGetterSelector: key\\n\\n\\tself flag: #yoCharCases.\\n\\n\\tkey size > 3 ifFalse: [^false].\\n\\t(key beginsWith: 'get') ifFalse: [^false].\\n\\tkey fourth isUppercase ifFalse: [^false].\\n\\t^true\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 11/11/2002 10:31'!\\nisStandardSetterKeyword: key\\n\\n\\tself flag: #yoCharCases.\\n\\n\\tkey size > 4 ifFalse: [^false].\\n\\t(key endsWith: ':') ifFalse: [^false].\\n\\t(key beginsWith: 'set') ifFalse: [^false].\\n\\tkey fourth isUppercase ifFalse: [^false].\\n\\t^true\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:39'!\\nmessageNode: aNode receiver: receiver selector: selector keywords: key arguments: args \\n\\t| keywords column row receiverMorph receiverWidth messageWidth onlyOne nodeWithNilReceiver isAConditional |\\n\\tself alansTest1 \\n\\t\\tifTrue: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talansMessageNode: aNode\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\tkeywords: key\\n\\t\\t\\t\\targuments: args].\\n\\tisAConditional := #(#ifTrue: #ifFalse: #ifTrue:ifFalse: #ifFalse:ifTrue:) \\n\\t\\t\\t\\tincludes: key.\\n\\treceiver ifNotNil: \\n\\t\\t\\t[\\\"i.e. not a cascade\\\"\\n\\n\\t\\t\\treceiverMorph := receiver asMorphicSyntaxIn: self].\\n\\tkeywords := key keywords.\\n\\targs isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := (self addSingleKeywordRow: key) layoutInset: 1.\\n\\t\\t\\t^row parseNode: selector].\\n\\treceiverWidth := receiver ifNil: [0]\\n\\t\\t\\t\\tifNotNil: [receiverMorph fullBounds width].\\n\\tonlyOne := args size = 1.\\n\\t(receiverWidth <= 80 and: [onlyOne]) \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tmessageOneArg: key\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\targs: args.\\n\\t\\t\\t^self].\\n\\tnodeWithNilReceiver := aNode copy receiver: nil.\\n\\tcolumn := self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\t\\\"onlyOne ifTrue: [column parseNode: nil].\\tis a spacer\\\"\\n\\tmessageWidth := 0.\\n\\tkeywords with: (args copyFrom: 1 to: keywords size)\\n\\t\\tdo: \\n\\t\\t\\t[:kwd :arg | \\n\\t\\t\\tisAConditional \\n\\t\\t\\t\\tifTrue: [column addMorphBack: (column transparentSpacerOfSize: 3 @ 3)].\\n\\t\\t\\t(row := column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver \\n\\t\\t\\t\\t\\t\\t\\tas: (onlyOne ifTrue: [MessageNode] ifFalse: [MessagePartNode]));\\n\\t\\t\\t\\tborderColor: row stdBorderColor.\\n\\t\\t\\tisAConditional \\n\\t\\t\\t\\tifTrue: [row addMorphBack: (row transparentSpacerOfSize: 20 @ 6)].\\n\\t\\t\\trow \\n\\t\\t\\t\\taddToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: (onlyOne \\n\\t\\t\\t\\t\\t\\tifTrue: [SelectorNode new key: kwd code: nil\\t\\\"fill this in?\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [KeyWordNode new]).\\n\\t\\t\\targ asMorphicSyntaxIn: row.\\n\\t\\t\\tmessageWidth := messageWidth + row fullBounds width].\\n\\tonlyOne \\n\\t\\tifTrue: \\n\\t\\t\\t[self replaceSubmorph: column by: row.\\n\\t\\t\\tcolumn := row].\\n\\treceiverMorph ifNil: [^self].\\n\\treceiverWidth + messageWidth < 350 \\n\\t\\tifTrue: \\n\\t\\t\\t[isAConditional ifFalse: [self unfoldMessage].\\n\\t\\t\\t^self].\\n\\t((receiverWidth > 200 \\n\\t\\tor: [receiverWidth > 80 and: [column fullBounds height > 20]]) or: \\n\\t\\t\\t\\t[receiverMorph fullBounds width > 30 \\n\\t\\t\\t\\t\\tand: [column fullBounds height > 100 or: [column fullBounds width > 250]]]) \\n\\t\\tifTrue: [^self foldMessage]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/26/2001 14:04'!\\nmessageOneArg: key receiver: receiver selector: selector args: args\\n\\n\\t| row firstArgMorph |\\n\\n\\trow _ (self addSingleKeywordRow: key) layoutInset: 1.\\n\\trow parseNode: selector.\\n\\tfirstArgMorph _ args first asMorphicSyntaxIn: self.\\n\\treceiver ifNil: [^ self].\\n\\t(firstArgMorph fullBounds height > 100\\n\\t\\t\\tor: [firstArgMorph fullBounds width > 250])\\n\\t\\tifTrue: [self foldMessageOneArg].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/26/2001 17:12'!\\nmethodNodeInner: aNode selectorOrFalse: selectorOrFalse precedence: precedence arguments: arguments temporaries: temporaries primitive: primitive block: block\\n\\t| header selNode |\\n\\n\\tselNode _ selectorOrFalse class == SelectorNode \\n\\t\\tifTrue: [selectorOrFalse] \\n\\t\\tifFalse: [SelectorNode new key: selectorOrFalse code: nil].\\n\\theader _ self addRow: Color white on: selNode.\\n\\tprecedence = 1\\n\\t\\tifTrue: [header addToken: aNode selector type: #methodHeader1 on: selNode]\\n\\t\\tifFalse: [aNode selector keywords with: arguments do:\\n\\t\\t\\t\\t\\t[:kwd :arg | \\n\\t\\t\\t\\t\\theader addToken: kwd type: #methodHeader2 on: selNode.\\n\\t\\t\\t\\t\\t(arg asMorphicSyntaxIn: header) color: #blockarg2]].\\n\\taNode addCommentToMorph: self.\\n\\tself addTemporaries: temporaries.\\n\\t(primitive > 0 and: [(primitive between: 255 and: 519) not]) ifTrue:\\n\\t\\t[\\\"Dont decompile <prim> for, eg, ^ self \\\"\\n\\t\\tself addTextRow: (String streamContents: [ :strm | aNode printPrimitiveOn: strm])].\\n\\tblock asMorphicSyntaxIn: self.\\n\\t^ self\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/31/2001 17:37'!\\nmethodNodeOuter: aNode\\n\\n\\t| block |\\n\\t\\n\\tself borderWidth: 0.\\n\\taNode asMorphicSyntaxIn: self.\\n\\tself alansTest1 ifTrue: [self addTemporaryControls].\\n\\tself finalAppearanceTweaks.\\n\\t\\t\\\"self setProperty: #deselectedColor toValue: Color transparent.\\\"\\n\\tblock _ self findA: BlockNode.\\n\\t\\t\\\"block setProperty: #deselectedColor toValue: Color transparent.\\\"\\n\\tblock submorphs size = 1 ifTrue: [^ self].\\t\\\"keep '^ self' if that is the only thing in method\\\"\\n\\tblock submorphs last decompile string = '^ self ' ifTrue: [\\n\\t\\tblock submorphs last delete].\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/15/2001 19:49'!\\nvanillaMessageNode: aNode receiver: receiver selector: selector arguments: arguments\\n\\n\\t| substitute row sel |\\n\\tsel _ #message.\\n\\t((self nodeClassIs: CascadeNode) and: [self parseNode receiver ~~ aNode]) ifTrue: [\\n\\t\\tsel _ #keyword2.\\n\\t\\treceiver ifNotNil: [self inform: 'receiver should be nil']].\\n\\trow _ self addRow: sel on: aNode.\\n\\tsubstitute _ aNode as: TileMessageNode.\\n\\t(aNode macroPrinter == #printCaseOn:indent:) ifTrue: [\\n\\t\\taNode asMorphicCaseOn: row indent: nil.\\n\\t\\t^ self].\\n\\taNode macroPrinter\\n\\t\\tifNotNil: \\n\\t\\t\\t[substitute perform: aNode macroPrinter with: row with: nil]\\n\\t\\tifNil: \\n\\t\\t\\t[substitute \\n\\t\\t\\t\\tprintKeywords: selector key\\n\\t\\t\\t\\targuments: arguments\\n\\t\\t\\t\\ton: row\\n\\t\\t\\t\\tindent: nil].\\n\\t^ row addTransparentSpacerOfSize: 3@0.\\t\\\"horizontal spacing only\\\"\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'RAA 2/14/2001 20:34'!\\nimmediatelyBelowTheMethodNode\\n\\n\\t^(owner respondsTo: #isMethodNode) and: [owner isMethodNode]! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 8/24/2001 15:41'!\\nisAVariable\\n\\t\\\"There are three kinds of variable nodes\\\"\\n\\n\\t((parseNode class == TempVariableNode) or: [\\n\\t\\t(parseNode class == LiteralVariableNode) or: [\\n\\t\\t\\tparseNode class == VariableNode]]) ifFalse: [^ false].\\n\\t^ (ClassBuilder new reservedNames includes: \\n\\t\\t\\tself decompile string withoutTrailingBlanks) not! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/17/2000 08:31'!\\nisBlockNode\\n\\t^ parseNode class == BlockNode! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/26/2001 05:50'!\\nisDeclaration\\n\\t\\\"Return true if I am a TempVarNode inside a declaration of some kind, including a method arg\\\"\\n\\n\\t| opc |\\n\\towner isSyntaxMorph ifFalse: [^ false].\\n\\topc _ owner parseNode class.\\n\\topc == BlockArgsNode ifTrue: [^ true].\\n\\topc == MethodTempsNode ifTrue: [^ true].\\n\\topc == SelectorNode ifTrue: [^ true].\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'gm 2/22/2003 12:30'!\\nisLeafTile\\n\\tself hasSubmorphs ifFalse: [^false].\\n\\t(self firstSubmorph isSyntaxMorph) ifTrue: [^false].\\n\\t(self firstSubmorph isMemberOf: Morph) ifTrue: [^false].\\n\\t^true! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/17/2000 08:31'!\\nisMethodNode\\n\\t^ parseNode class == MethodNode! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/13/2001 15:28'!\\nisNoun\\n\\t\\\"Consider these to be nouns: MessageNode with receiver, CascadeNode with receiver, AssignmentNode, TempVariableNode, LiteralNode, VariableNode, LiteralVariableNode.\\\"\\n\\n\\t(#(TempVariableNode LiteralNode VariableNode LiteralVariableNode) includes:\\n\\t\\t(parseNode class name)) ifTrue: [^ true].\\n\\n\\t(self nodeClassIs: MessageNode) ifTrue: [^ parseNode receiver notNil].\\n\\t(self nodeClassIs: CascadeNode) ifTrue: [^ parseNode receiver notNil].\\n\\t(self nodeClassIs: AssignmentNode) ifTrue: [^ submorphs size >= 3].\\n\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/23/2001 00:17'!\\nisSelfTile\\n\\n\\t^ parseNode class == VariableNode and: [self decompile asString = 'self ']\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/6/2000 15:26'!\\nnodeClassIs: aParseNodeClass\\n\\t\\\"Test the class of my parseNode\\\"\\n\\n\\t^ parseNode class == aParseNodeClass! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'dgd 2/22/2003 13:40'!\\nrootTile\\n\\t^self \\n\\t\\torOwnerSuchThat: [:m | m owner isNil or: [m owner isSyntaxMorph not]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'player' stamp: 'tk 9/26/2001 06:05'!\\ncurrentDataValue\\n\\t\\\"Answer the current data value held by the receiver\\\"\\n\\n\\t^ self readOut valueFromContents! !\\n\\n!SyntaxMorph methodsFor: 'player' stamp: 'tk 2/15/2002 13:03'!\\nvariableDocks\\n\\t\\\"Answer a list of VariableDock objects for docking up my data with an instance held in my containing playfield. For a numeric-readout tile.\\\"\\n\\n\\t\\\"Is CardPlayer class holding my variableDock, or should I be using the caching mechanism in Morph>>variableDocks?\\\"\\n\\t| updatingString lab nn aGetter |\\n\\t(updatingString _ self readOut) ifNil: [^ #()].\\n\\tupdatingString getSelector ifNil: [\\n\\t\\tlab _ self submorphNamed: 'label' ifNone: [self defaultName].\\n\\t\\tnn _ lab contents asString.\\n\\t\\t\\\"nn at: 1 put: nn first asUppercase.\\\"\\n\\t\\tupdatingString getSelector: (aGetter _ 'get',nn) asSymbol;\\n\\t\\t\\tputSelector: (ScriptingSystem setterSelectorForGetter: aGetter).\\n\\t\\t].\\n\\t^ Array with: (VariableDock new \\n\\t\\t\\tvariableName: (updatingString getSelector allButFirst: 3) withFirstCharacterDownshifted \\n\\t\\t\\ttype: #number \\n\\t\\t\\tdefiningMorph: updatingString \\n\\t\\t\\tmorphGetSelector: #valueFromContents \\n\\t\\t\\tmorphPutSelector: #acceptValue:)! !\\n\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'aoy 2/15/2003 21:30'!\\naddArg: index \\n\\t\\\"I rep a SelectorNode. My string has been replaced. Append an argument to my owner.\\\"\\n\\n\\t\\\"See if any sample args are recorded\\\"\\n\\n\\t| sel rec aVocabulary mi sample descrip mthNode tiles |\\n\\tsel := self decompile asString asSymbol.\\n\\trec := self receiverObject.\\n\\tsample := rec class == Error \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[aVocabulary := self vocabularyToUseWith: rec.\\n\\t\\t\\t\\t\\tmi := aVocabulary methodInterfaceAt: sel ifAbsent: [nil].\\n\\t\\t\\t\\t\\tmi ifNil: [5]\\n\\t\\t\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[descrip := mi argumentVariables at: index.\\n\\t\\t\\t\\t\\t\\t\\tdescrip sample]]\\n\\t\\t\\t\\tifTrue: [5]. \\n\\tmthNode := self string: sample storeString toTilesIn: sample class.\\n\\ttiles := mthNode submorphs at: mthNode submorphs size - 1.\\t\\\"before the ^ self\\\"\\n\\tself owner addMorphBack: tiles! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:24'!\\nassignmentArrow\\n\\t\\\"Offer to embed this variable in a new assignment statement. (Don't confuse this with upDownAssignment:, which runs the up and down arrows that rotate among assignment types.)\\\"\\n\\t| rr |\\n\\n\\tself isAVariable ifFalse: [^ nil].\\n\\tself isDeclaration ifTrue: [^ nil].\\n\\t^ (rr _ RectangleMorph new)\\n\\t\\textent: 11@13; borderWidth: 1; color: Color lightGreen;\\n\\t\\tborderColor: Color gray;\\n\\t\\taddMorph: ((self noiseStringMorph: '_') topLeft: rr topLeft + (3@0));\\n\\t\\ton: #mouseUp send: #newAssignment to: self\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'gk 2/23/2004 21:08'!\\nchangeSound: upDown\\n\\t| ind arg st soundChoices index it current |\\n\\t\\\"move in the list of sounds. Adjust arg tile after me\\\"\\n\\n\\tind _ owner submorphs indexOf: self.\\n\\targ _ owner submorphs atWrap: ind+1.\\n\\targ isSyntaxMorph ifFalse: [^ self].\\n\\tst _ arg submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\tsoundChoices _ SoundService default sampledSoundChoices.\\n\\tcurrent _ st contents copyFrom: 2 to: st contents size-1.\\t\\\"remove string quotes\\\"\\n\\tindex _ soundChoices indexOf: current.\\n\\tindex > 0 ifTrue:\\n\\t\\t[st contents: (it _ soundChoices atWrap: index + upDown) printString.\\n\\t\\tself playSoundNamed: it].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/26/2001 14:31'!\\ncolorPatch\\n\\t\\\"Return a color patch button that lets the user choose a color and modifies the code\\\"\\n\\t| cc patch sel completeMsg |\\n\\t\\n\\t\\n\\t((self nodeClassIs: MessageNode) \\\"or: [self nodeClassIs: SelectorNode]\\\") ifFalse: [^ nil].\\n\\t(sel _ self selector) ifNil: [^ nil].\\n\\t(Color colorNames includes: sel) | (sel == #r:g:b:) ifFalse: [^ nil].\\n\\t\\t\\\"a standard color name\\\"\\n\\tcompleteMsg _ self isNoun ifTrue: [self] \\n\\t\\t\\t\\tifFalse: [owner isNoun ifTrue: [owner] ifFalse: [owner owner]].\\n\\n\\t(cc _ completeMsg try) class == Color ifFalse: [^ nil].\\n\\tpatch _ ColorTileMorph new colorSwatchColor: cc.\\n\\t\\t\\\"sends colorChangedForSubmorph: to the messageNode\\\"\\n\\tpatch color: Color transparent; borderWidth: 0. patch submorphs last delete.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 2/21/2001 16:37'!\\ndeleteLine\\n\\t| temp |\\n\\ttemp _ owner.\\n\\tself deletePopup.\\n\\tself delete.\\n\\ttemp setSelection: nil.\\n\\ttemp acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 12/13/2000 13:05'!\\ndeletePopup\\n\\n\\tself valueOfProperty: #myPopup ifPresentDo:\\n\\t\\t[:panel | panel delete. self removeProperty: #myPopup]! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 2/21/2001 13:09'!\\ndismisser\\n\\t\\\"Return the icon to delete this line of tiles. I am an entire line in a block.\\\"\\n\\t| handle handleSpec colorToUse iconName form |\\n\\n\\t(owner isSyntaxMorph and: [owner nodeClassIs: BlockNode]) ifFalse: [^ nil].\\n\\thandleSpec _ Preferences haloSpecifications fourth.\\t\\\"dismiss\\\"\\n\\thandle _ EllipseMorph\\n\\t\\t\\tnewBounds: (Rectangle center: 10@10 extent: 16 asPoint)\\n\\t\\t\\tcolor: (colorToUse _ Color colorFrom: handleSpec color).\\n\\ticonName _ handleSpec iconSymbol.\\n\\tform _ ScriptingSystem formAtKey: iconName.\\t\\\"#'Halo-Dismiss'\\\"\\n\\thandle addMorphCentered: (ImageMorph new\\n\\t\\t\\t\\timage: form; \\n\\t\\t\\t\\tcolor: colorToUse makeForegroundColor;\\n\\t\\t\\t\\tlock).\\n\\thandle on: #mouseDown send: #deleteLine to: self.\\n\\t^ handle! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 10/17/2001 13:38'!\\ndupTile: evt\\n\\n\\t| dup |\\n\\tself deletePopup.\\n\\t\\\"self deselect.\\\"\\n\\tdup _ self duplicateMorph: evt.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [dup align: dup center with: evt hand position.\\n\\t\\t\\t\\tdup lookTranslucent]\\n\\t\\tifFalse: [dup align: dup topLeft\\n\\t\\t\\t\\t\\twith: evt hand position + self cursorBaseOffset].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 10/17/2001 13:29'!\\nduplicator\\n\\t\\\"Return the icon to duplicate this tile.\\\"\\n\\t| handle handleSpec colorToUse iconName form |\\n\\n\\thandleSpec _ Preferences haloSpecifications at: 11.\\t\\\"duplicate\\\"\\n\\thandle _ EllipseMorph\\n\\t\\t\\tnewBounds: (Rectangle center: 10@10 extent: 16 asPoint)\\n\\t\\t\\tcolor: (colorToUse _ Color colorFrom: handleSpec color).\\n\\ticonName _ handleSpec iconSymbol.\\n\\tform _ ScriptingSystem formAtKey: iconName.\\t\\\"#'Halo-Dup'\\\"\\n\\thandle addMorphCentered: (ImageMorph new\\n\\t\\t\\t\\timage: form; \\n\\t\\t\\t\\tcolor: colorToUse makeForegroundColor;\\n\\t\\t\\t\\tlock).\\n\\thandle on: #mouseDown send: #dupTile: to: self.\\n\\t^ handle! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'ar 3/18/2001 17:28'!\\nevent: arg1 arrow: arg2 upDown: arg3\\n\\t\\\"Reorder the arguments for existing event handlers\\\"\\n\\t(arg3 isMorph and:[arg3 eventHandler notNil]) ifTrue:[arg3 eventHandler fixReversedValueMessages].\\n\\t^self upDown: arg1 event: arg2 arrow: arg3! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 13:38'!\\nextend\\n\\t| messageNodeMorph first |\\n\\t\\\"replace this noun with a new message like (arg + 1). If type is not known, ask the user to type in a selector. Use nil as arg. Let user drag something to it afterwards.\\\"\\n\\n\\t\\\"Later do evaluation of self to see what type and offer right selector\\\"\\n\\tself deselect.\\n\\tmessageNodeMorph _ (MessageSend receiver: 1 selector: #+ arguments: #(1))\\n\\t\\t\\t\\t\\t\\t\\t\\tasTilesIn: Player globalNames: false.\\n\\towner replaceSubmorph: self by: messageNodeMorph.\\n\\tfirst _ messageNodeMorph submorphs detect: [:mm | mm isSyntaxMorph].\\n\\tmessageNodeMorph replaceSubmorph: first by: self.\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:14'!\\nextendArrow\\n\\t\\\"Return the extend arrow button. It replaces the argument with a new message.\\n\\tI am a number or getter messageNode.\\\"\\n\\t| patch |\\n\\t\\n\\tself isNoun ifFalse: [^ nil].\\n\\tself isDeclaration ifTrue: [^ nil].\\n\\tpatch _ (ImageMorph new image: (TileMorph classPool at: #SuffixPicture)).\\n\\tpatch on: #mouseDown send: #extend to: self.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 11:35'!\\nnewAssignment\\n\\t\\\"I am a variableNode. Place me inside an assignment statement.\\\"\\n\\n\\t| new old |\\n\\tparseNode name: self decompile.\\t\\\"in case user changed name\\\"\\n\\tnew _ owner assignmentNode: AssignmentNode new variable: parseNode \\n\\t\\t\\t\\t\\tvalue: parseNode copy.\\n\\tself deselect.\\n\\t(old _ owner) replaceSubmorph: self by: new.\\t\\\"do the normal replacement\\\"\\n\\t(old isSyntaxMorph) ifTrue: [old cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'dgd 2/22/2003 13:40'!\\nofferPopUp\\n\\t\\\"Put up a halo to allow user to change\\n\\t\\tLiterals (Integer, true),\\n\\t\\tSelector (beep: sound, +,-,*,//,\\\\\\\\, r:g:b:, setX: incX: decX: for any X,),\\n\\t\\tVariable (Color),\\n\\t\\tnot AssignmentNode (_ inc dec),\\n\\tExtend arrows on each literal, variable, and message, (block that is by itself).\\n\\tRetract arrows on each literal or variable, or message or block that is an argument.\\n\\tAny literal can be changed by Shift-clicking and typing.\\\"\\n\\n\\t| panel any upDown retract extend colorPatch edge dismiss rr duplicate |\\n\\t(self hasProperty: #myPopup) ifTrue: [^self].\\t\\\"already has one\\\"\\n\\tany := false.\\n\\t(upDown := self upDownArrows) ifNotNil: [any := true].\\t\\\"includes menu of selectors\\\"\\n\\t(retract := self retractArrow) ifNotNil: [any := true].\\n\\t(extend := self extendArrow) ifNotNil: [any := true].\\n\\t(dismiss := self dismisser) ifNotNil: [any := true].\\n\\t(duplicate := self duplicator) ifNotNil: [any := true].\\n\\t\\\"(assign _ self assignmentArrow) ifNotNil: [any _ true].\\n\\t\\t\\tget from menu or any other assignment\\\"\\n\\tsubmorphs last class == ColorTileMorph \\n\\t\\tifFalse: [(colorPatch := self colorPatch) ifNotNil: [any := true]].\\n\\tany ifFalse: [^self].\\n\\t\\\"Transcript cr; print: parseNode class; space; \\n\\t\\tprint: (self hasProperty: #myPopup); endEntry.\\\"\\n\\tpanel := (RectangleMorph new)\\n\\t\\t\\t\\tcolor: Color transparent;\\n\\t\\t\\t\\tborderWidth: 0.\\n\\tupDown ifNotNil: \\n\\t\\t\\t[panel addMorphBack: upDown first.\\n\\t\\t\\tupDown first align: upDown first topLeft with: panel topLeft + (0 @ 0).\\n\\t\\t\\tpanel addMorphBack: upDown second.\\n\\t\\t\\tupDown second align: upDown second topLeft\\n\\t\\t\\t\\twith: upDown first bottomLeft + (0 @ 1).\\n\\t\\t\\tupDown size > 2 \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[panel addMorphBack: upDown third.\\n\\t\\t\\t\\t\\tupDown third align: upDown third topLeft\\n\\t\\t\\t\\t\\t\\twith: upDown first topRight + (2 @ 3)]].\\n\\trr := self right.\\n\\tcolorPatch ifNotNil: \\n\\t\\t\\t[rr := rr + colorPatch submorphs first width + 1.\\n\\t\\t\\tself addMorphBack: colorPatch\\t\\\"always in tile\\\"\\n\\t\\t\\t\\\"colorPatch align: colorPatch topLeft \\n\\t\\t\\t\\t\\twith: panel topLeft + (1@1)\\\"].\\n\\tretract ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: retract.\\n\\t\\t\\tretract align: retract topLeft with: (edge + 2) @ (panel top + 3)].\\n\\textend ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: extend.\\n\\t\\t\\textend align: extend topLeft with: (edge + 2) @ (panel top + 3)].\\n\\tduplicate ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: duplicate.\\n\\t\\t\\tduplicate align: duplicate topLeft with: (edge + 2) @ (panel top + 1)].\\n\\tdismiss ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: dismiss.\\n\\t\\t\\tdismiss align: dismiss topLeft with: (edge + 2) @ (panel top + 1)].\\n\\t\\\"\\tassign ifNotNil: [\\n\\t\\tedge _ panel submorphs isEmpty \\n\\t\\t\\tifTrue: [panel left] \\n\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\tpanel addMorphBack: assign.\\n\\t\\tassign align: assign topLeft with: (edge+2) @ (panel top + 2)].\\n\\\"\\n\\tpanel align: panel topLeft with: rr @ (self top - 2).\\n\\tpanel extent: panel submorphs last bottomRight - panel topLeft.\\n\\tself setProperty: #myPopup toValue: panel.\\n\\tself addMorphBack: panel\\t\\\"Any reason ever to have panel below?\\\"\\n\\t\\\"(owner listDirection = #topToBottom and: [self listDirection = #leftToRight])\\n\\t\\tifTrue: [self addMorphBack: panel]\\n\\t\\tifFalse: [owner addMorph: panel after: self].\\\"! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 13:39'!\\nreplaceKeyWord: evt menuItem: stringMorph\\n\\t\\\"Replace my entire message (which may be multi-part) with the one specified. Preserve all argument tiles, either in the new message or in the world outside the scriptor. I am a SelectorNode or KeyWordNode.\\\"\\n\\n\\t| menu new news newSel mm newTree newRec newArgs top oldArgNodes share ctrY |\\n\\t(menu _ stringMorph owner owner) class == RectangleMorph ifTrue: [\\n\\t\\tmenu delete].\\n\\tnew _ stringMorph contents.\\n\\tnew first = $( ifTrue: [^ self].\\t\\\"Cancel\\\"\\n\\tnew first = $ ifTrue: [^ self].\\t\\\"nothing\\\"\\n\\tnews _ String streamContents: [:strm | \\\"remove fake args\\\"\\n\\t\\t(new findBetweenSubStrs: #(' 5' $ )) do: [:part | strm nextPutAll: part]].\\n\\tnewSel _ stringMorph valueOfProperty: #syntacticallyCorrectContents.\\n\\tnewSel ifNil: [newSel _ news].\\n\\tmm _ MessageSend receiver: 5 selector: newSel \\n\\t\\t\\targuments: ((Array new: newSel numArgs) atAllPut: 5).\\n\\tnewTree _ mm asTilesIn: Object globalNames: false.\\n\\tnewRec _ newTree receiverNode.\\n\\tnewArgs _ newTree argumentNodes.\\n\\tctrY _ self fullBoundsInWorld center y.\\n\\ttop _ self messageNode.\\n\\tnewRec owner replaceSubmorph: newRec by: top receiverNode.\\n\\toldArgNodes _ top argumentNodes.\\n\\tshare _ newArgs size min: oldArgNodes size.\\n\\t(newArgs first: share) with: (oldArgNodes first: share) do: [:newNode :oldNode | \\n\\t\\tnewNode owner replaceSubmorph: newNode by: oldNode].\\n\\t\\\"later get nodes for objects of the right type for new extra args\\\"\\n\\n\\ttop owner replaceSubmorph: top by: newTree.\\n\\n\\t\\\"Deposit extra args in the World\\\"\\n\\t(oldArgNodes copyFrom: share+1 to: oldArgNodes size) do: [:leftOver |\\n\\t\\t(leftOver parseNode class == LiteralNode and: [leftOver decompile asString = '5']) \\n\\t\\t\\tifFalse: [newTree pasteUpMorph addMorphFront: leftOver.\\n\\t\\t\\t\\tleftOver position: newTree enclosingPane fullBoundsInWorld right - 20 @ ctrY.\\n\\t\\t\\t\\tctrY _ ctrY + 26]\\n\\t\\t\\tifTrue: [leftOver delete]].\\n\\tnewTree acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/19/2001 21:32'!\\nreplaceSel: evt menuItem: stringMorph\\n\\t\\\"I rep a SelectorNode. Replace my selector with new one that was just chosen from a menu\\\"\\n\\n\\t| menu new old newSel ms oa na case news |\\n\\t(menu _ stringMorph owner owner) class == RectangleMorph ifTrue: [\\n\\t\\tmenu delete].\\n\\tnew _ stringMorph contents.\\n\\tnew first = $( ifTrue: [^ self].\\t\\\"Cancel\\\"\\n\\tnew first = $ ifTrue: [^ self].\\t\\\"nothing\\\"\\n\\tnews _ String streamContents: [:strm | \\\"remove fake args\\\"\\n\\t\\t(new findBetweenSubStrs: #(' 5' $ )) do: [:part | strm nextPutAll: part]].\\n\\tnewSel _ stringMorph valueOfProperty: #syntacticallyCorrectContents.\\n\\tnewSel ifNil: [newSel _ news].\\n\\told _ (ms _ self findA: StringMorph) valueOfProperty: #syntacticallyCorrectContents.\\n\\told ifNil: [old _ (self findA: StringMorph) contents].\\n\\toa _ old numArgs. na _ newSel numArgs. case _ 5.\\n\\t(oa = 1) & (na = 1) ifTrue: [case _ 1]. \\n\\t(oa = 0) & (na = 0) ifTrue: [case _ 2].\\n\\t(oa = 1) & (na = 0) ifTrue: [case _ 3].\\n\\t(oa = 0) & (na = 1) ifTrue: [case _ 4].\\n\\tcase <= 4 ifTrue: [\\\"replace the selector\\\"\\n\\t\\tms contents: news.\\t\\\"not multi-part\\\"\\n\\t\\tms setProperty: #syntacticallyCorrectContents toValue: newSel].\\n\\tcase = 3 ifTrue: [owner tossOutArg: 1].\\n\\tcase = 4 ifTrue: [self addArg: 1].\\n\\t\\\"more cases here. Rebuild the entire MessageNode\\\"\\n\\t\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 10:06'!\\nretract\\n\\t\\\"replace this message with its receiver. I am the message node.\\\"\\n\\t| rec cascade msg |\\n\\t(self nodeClassIs: CascadeNode) ifTrue:\\n\\t\\t[\\\"This is a piece of a cascaded message -- just delete it\\\"\\n\\t\\tself deletePopup.\\n\\t\\tcascade _ owner.\\n\\t\\tself delete.\\n\\t\\tcascade setSelection: {cascade. nil. cascade}.\\n\\t\\t^ cascade acceptIfInScriptor].\\n\\tself deletePopup.\\n\\t(rec _ self receiverNode)\\n\\t\\tifNil: [msg _ owner.\\n\\t\\t\\trec _ owner receiverNode.\\n\\t\\t\\tmsg owner replaceSubmorph: msg by: rec]\\n\\t\\tifNotNil: [owner replaceSubmorph: self by: rec].\\n\\trec setSelection: {rec. nil. rec}.\\n\\trec acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 12/13/2000 12:57'!\\nretractArrow\\n\\t\\\"Return the retract arrow button. It replaces the current message with its receiver.\\n\\tI am in a MessageNode whose first subnode is not a MessagePartNode. I did not encounter a block on the way up to it. I am the last subnode in every owner up to it.\\\"\\n\\t| patch |\\n\\n\\t(self nodeClassIs: MessageNode) ifFalse: [^ nil].\\n\\t(owner isSyntaxMorph and: [owner parseNode == parseNode]) ifTrue: [^ nil].\\n\\n\\tpatch _ (ImageMorph new image: (TileMorph classPool at: #RetractPicture)).\\n\\tpatch on: #mouseDown send: #retract to: self.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/18/2001 16:27'!\\nselectorMenu\\n\\t\\\"Put up a menu of all selectors that my receiver could be sent. Replace me with the one chosen. (If fewer args, put the tiles for the extra arg to the side, in script's owner (world?).)\\n\\tGo ahead and eval receiver to find out its type. Later, mark selectors for side effects, and don't eval those.\\n\\tPut up a table. Each column is a viewer category.\\\"\\n\\n\\t| cats value catNames interfaces list setter wording all words ind aVocabulary limitClass |\\n\\tcats _ #().\\n\\tall _ Set new.\\n\\tvalue _ self receiverObject.\\n\\tvalue class == Error ifTrue: [^ nil].\\n\\t\\n\\taVocabulary _ self vocabularyToUseWith: value.\\n\\tlimitClass _ self limitClassToUseWith: value vocabulary: aVocabulary.\\n\\tcatNames _ value categoriesForVocabulary: aVocabulary limitClass: limitClass.\\n\\tcats _ catNames collect: [:nn | \\n\\t\\tlist _ OrderedCollection new.\\n\\t\\tinterfaces _ value methodInterfacesForCategory: nn \\n\\t\\t\\t\\t\\t\\tinVocabulary: aVocabulary limitClass: limitClass.\\n\\t\\tinterfaces do: [:mi | \\n\\t\\t\\t(all includes: mi selector) ifFalse: [\\n\\t\\t\\t\\t\\\"list add: (self aSimpleStringMorphWith: mi elementWording). Expensive\\\"\\n\\t\\t\\t\\twords _ mi selector.\\n\\t\\t\\t\\t(words beginsWith: 'get ') ifTrue: [words _ words allButFirst: 4].\\n\\t\\t\\t\\tmi selector last == $: ifTrue: [\\n\\t\\t\\t\\t\\twords _ String streamContents: [:strm | \\\"add fake args\\\"\\n\\t\\t\\t\\t\\t\\t(words findTokens: $:) do: [:part | strm nextPutAll: part; nextPutAll: ' 5 ']].\\n\\t\\t\\t\\t\\twords _ words allButLast].\\n\\t\\t\\t\\tmi selector isInfix ifTrue: [words _ words, ' 5'].\\n\\t\\t\\t\\twords _ self splitAtCapsAndDownshifted: words.\\t\\n\\t\\t\\t\\tlist add: (self anUpdatingStringMorphWith: words special: true).\\n\\t\\t\\t\\twords = mi selector ifFalse: [\\n\\t\\t\\t\\t\\tlist last setProperty: #syntacticallyCorrectContents toValue: mi selector].\\n\\t\\t\\t\\tall add: mi selector].\\n\\t\\t\\tsetter _ mi companionSetterSelector asString.\\n\\t\\t\\t(setter = 'nil') | (all includes: setter) ifFalse: [\\\"need setters also\\\"\\n\\t\\t\\t\\twording _ (self translateToWordySetter: setter).\\n\\t\\t\\t\\tlist add: (self aSimpleStringMorphWith: wording, ' 5').\\n\\t\\t\\t\\twording = setter ifFalse: [\\n\\t\\t\\t\\t\\tlist last setProperty: #syntacticallyCorrectContents \\n\\t\\t\\t\\t\\t\\ttoValue: setter].\\n\\t\\t\\t\\tall add: setter]].\\n\\t\\tlist].\\n\\t(ind _ catNames indexOf: 'scripts') > 0 ifTrue: [\\n\\t\\t(cats at: ind) first contents = 'empty script' ifTrue: [(cats at: ind) removeFirst]].\\n\\tcats first addFirst: (self aSimpleStringMorphWith: ' ').\\t\\\"spacer\\\"\\n\\tcats first addFirst: (self aSimpleStringMorphWith: '( from ', value class name, ' )').\\n\\tcats first first color: (Color green mixed: 0.25 with: Color black).\\n\\tself selectorMenuAsk: cats.\\t\\\"The method replaceSel:menuItem: does the work. \\n\\t\\tand replaces the selector.\\\"\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/20/2001 16:04'!\\nselectorMenuAsk: listOfLists\\n\\t\\\"I represent a SelectorNode to be replaced by one of the selectors in one of the category lists. Each list has pre-built StringMorphs in it.\\\"\\n\\n\\t| menu col |\\n\\tlistOfLists isEmpty ifTrue: [^ nil].\\n\\tlistOfLists first addFirst: (self aSimpleStringMorphWith: '( Cancel )').\\n\\tlistOfLists first first color: Color red.\\n\\tmenu _ RectangleMorph new.\\n\\tmenu listDirection: #leftToRight; layoutInset: 3; cellInset: 1@0.\\n\\tmenu layoutPolicy: TableLayout new; hResizing: #shrinkWrap; \\n\\t\\tvResizing: #shrinkWrap; color: (Color r: 0.767 g: 1.0 b: 0.767);\\n\\t\\tuseRoundedCorners; cellPositioning: #topLeft.\\n\\tlistOfLists do: [:ll |\\n\\t\\tcol _ Morph new.\\n\\t \\tcol listDirection: #topToBottom; layoutInset: 0; cellInset: 0@0.\\n\\t\\tcol layoutPolicy: TableLayout new; hResizing: #shrinkWrap.\\n\\t\\tcol color: Color transparent; vResizing: #shrinkWrap.\\n\\t\\tmenu addMorphBack: col.\\n\\t\\tll do: [:ss | \\n\\t\\t\\tcol addMorphBack: ss.\\n\\t\\t\\tss on: #mouseUp send: #replaceKeyWord:menuItem: to: self]\\n\\t\\t].\\n\\tself world addMorph: menu.\\n\\tmenu setConstrainedPosition: (owner localPointToGlobal: self topRight) + (10@-30) \\n\\t\\t\\thangOut: false.\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'sw 3/18/2004 00:35'!\\nsetSelector: stringLike in: stringMorph\\n\\t\\\"Store the new selector and accept method.\\\"\\n\\n\\t| aSymbol myType str |\\n\\taSymbol _ stringLike asSymbol.\\n\\t(ScriptingSystem helpStringOrNilFor: aSymbol) ifNotNilDo:\\n\\t\\t[:aString |\\n\\t\\t\\tself setBalloonText: aString translated].\\n\\tmyType _ stringMorph valueOfProperty: #syntacticReformatting ifAbsent: [#none].\\n\\tstr _ aSymbol.\\n\\t(self isStandardSetterKeyword: str) ifTrue: [str _ self translateToWordySetter: str].\\n\\t(self isStandardGetterSelector: str) ifTrue: [str _ self translateToWordyGetter: str].\\n\\t(self shouldBeBrokenIntoWords: myType) \\n\\t\\tifTrue: [str _ self substituteKeywordFor: str].\\n\\tstringMorph contents: str.\\n\\t\\\"parseNode key: aSymbol code: nil.\\\"\\n\\tstr = stringLike ifFalse:\\n\\t\\t[stringMorph setProperty: #syntacticallyCorrectContents toValue: aSymbol].\\n\\tself acceptSilently! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/19/2001 15:47'!\\ntossOutArg: extras\\n\\n\\t\\\"Remove the tiles for the last N keywords and arguments. Place the tiles beside the current window. I am a SyntaxMorph for a MessageNode.\\\"\\n\\n\\t| cnt ctr |\\n\\tcnt _ 0.\\n\\t submorphs copy reverseDo: [:sub |\\n\\t\\tctr _ sub fullBoundsInWorld center.\\n\\t\\tsub delete.\\n\\t\\t(sub isSyntaxMorph and: [sub parseNode notNil]) ifTrue: [\\n\\t\\t\\tsub isNoun ifTrue: [\\n\\t\\t\\t\\tself pasteUpMorph addMorphFront: sub.\\n\\t\\t\\t\\tsub position: self enclosingPane fullBoundsInWorld right - 20 @ ctr y].\\n\\t\\t\\t(cnt _ cnt + 1) >= extras ifTrue: [^ self]]].! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:35'!\\nupDown: delta event: evt arrow: arrowMorph\\n\\n\\t| st |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: LiteralNode) ifTrue:\\n\\t\\t[ \\\"+/- 1\\\"\\n\\t\\tst contents: (self decompile asNumber + delta) printString.\\n\\t\\t^ self acceptUnlogged].\\n\\t(self nodeClassIs: VariableNode) ifTrue:\\n\\t\\t[ \\\"true/false\\\"\\n\\t\\tst contents: (self decompile string = 'true') not printString.\\n\\t\\t^ self acceptSilently ifFalse: [self changed].\\n\\t\\t\\t\\\"maybe set parseNode's key\\\"].\\n\\n\\t(self upDownArithOp: delta) ifTrue: [^ self].\\t\\\"+ - // * < > <= = beep:\\\"\\n\\n\\t(self upDownAssignment: delta) ifTrue: [^ self].\\n\\t\\t\\\"Handle assignment -- increaseBy: <- multiplyBy:\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 7/24/2001 17:54'!\\nupDownArithOp: delta\\n\\t\\\"Change a + into a -. Also do sounds (change the arg to the beep:).\\\"\\n\\n\\t| aList index st |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: SelectorNode) ifTrue:\\n\\t\\t[aList _ #(+ - * / // \\\\\\\\ min: max:).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\taList _ #(= ~= > >= isDivisibleBy: < <=).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\taList _ #(== ~~).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\t'beep:' = self decompile asString ifTrue:\\n\\t\\t\\t[\\\"replace sound arg\\\"\\n\\t\\t\\tself changeSound: delta.\\n\\t\\t\\tself acceptSilently. ^ true].\\n\\t\\t].\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/20/2001 16:33'!\\nupDownArrows\\n\\t\\\"Return an array of two up/down arrow buttons.\\n\\tIt replaces the selector or arg with a new one.\\n\\tI am a number or boolean or a selector (beep:, +,-,*,//,\\\\\\\\, or setX: incX: decX: for any X.\\\"\\n\\t| patch any noMenu |\\n\\tany _ (self nodeClassIs: LiteralNode) and: [parseNode key isNumber].\\n\\tany _ any or: [(self nodeClassIs: VariableNode) and:\\n\\t\\t\\t\\t\\t\\t[(#('true' 'false') includes: self decompile asString)]].\\n\\tnoMenu _ any.\\n\\n\\tany _ any or: [self nodeClassIs: SelectorNode].\\t\\\"arrows and menu of selectors\\\"\\n\\tany _ any or: [self nodeClassIs: KeyWordNode].\\n\\tany ifFalse: [^ nil].\\n\\n\\tpatch _ {(ImageMorph new image: TileMorph upPicture)\\n\\t\\t\\t\\ton: #mouseDown send: #upDown:event:arrow: to: self withValue: 1;\\n\\t\\t\\t\\ton: #mouseStillDown send: #upDownMore:event:arrow: \\n\\t\\t\\t\\t\\tto: self withValue: 1;\\n\\t\\t\\t\\ton: #mouseUp send: #upDownDone to: self.\\n\\t\\t\\t(ImageMorph new image: TileMorph downPicture)\\n\\t\\t\\t\\ton: #mouseDown send: #upDown:event:arrow: to: self withValue: -1;\\n\\t\\t\\t\\ton: #mouseStillDown send: #upDownMore:event:arrow: \\n\\t\\t\\t\\t\\tto: self withValue: -1;\\n\\t\\t\\t\\ton: #mouseUp send: #upDownDone to: self}.\\n\\tnoMenu ifFalse: [patch _ patch, {(RectangleMorph new)\\n\\t\\t\\t\\t\\t\\textent: 6@10; borderWidth: 1;\\n\\t\\t\\t\\t\\t\\tborderColor: Color gray;\\n\\t\\t\\t\\t\\t\\ton: #mouseUp send: #selectorMenu to: self}.\\n\\t\\t\\t\\t\\tpatch last color: ((self nodeClassIs: SelectorNode) \\n\\t\\t\\t\\t\\t\\tifTrue: [Color lightGreen] ifFalse: [Color red darker])].\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 12:33'!\\nupDownAssignment: delta\\n\\t\\\"Rotate between increaseBy: decreaseBy: _ multiplyBy:\\\"\\n\\n\\t| st now want instVar |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: SelectorNode) ifTrue:\\n\\t\\t[\\\"kinds of assignment\\\"\\n\\t\\t((now _ self decompile asString) beginsWith: 'set') ifTrue:\\n\\t\\t\\t[\\\"a setX: 3\\\"\\n\\t\\t\\twant _ 1+delta. instVar _ (now allButFirst: 3) allButLast].\\n\\t\\t(now endsWith: 'IncreaseBy:') ifTrue:\\n\\t\\t\\t[\\\"a xIncreaseBy: 3 a setX: (a getX +3).\\\"\\n\\t\\t\\twant _ 2+delta. instVar _ now allButLast: 11].\\n\\t\\t(now endsWith: 'DecreaseBy:') ifTrue:\\n\\t\\t\\t[\\\"a xDecreaseBy: 3 a setX: (a getX -3).\\\"\\n\\t\\t\\twant _ 3+delta. instVar _ now allButLast: 11].\\n\\t\\t(now endsWith: 'MultiplyBy:') ifTrue:\\n\\t\\t\\t[\\\"a xMultiplyBy: 3 a setX: (a getX *3).\\\"\\n\\t\\t\\twant _ 4+delta. instVar _ now allButLast: 11].\\n\\t\\twant ifNil: [^ false].\\n\\t\\tinstVar _ instVar asLowercase.\\n\\t\\twant _ #(1 2 3 4) atWrap: want.\\n\\t\\twant = 1 ifTrue:\\n\\t\\t\\t[\\\"setter method is present\\\"\\n\\t\\t\\tself setSelector: ('set', instVar capitalized, ':') in: st. ^ true].\\n\\t\\twant = 2 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'IncreaseBy:' in: st. ^ true].\\n\\t\\twant = 3 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'DecreaseBy:' in: st. ^ true].\\n\\t\\twant = 4 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'MultiplyBy:' in: st. ^ true].\\n\\t\\t].\\n\\t^ false\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 5/4/2001 11:49'!\\nupDownDone\\n\\n\\t(self nodeClassIs: LiteralNode) ifTrue:\\n\\t\\t[self acceptSilently. \\\"Final compilation logs source\\\"\\n\\t\\tself removeProperty: #timeOfLastTick;\\n\\t\\t\\tremoveProperty: #currentDelay].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 5/4/2001 12:26'!\\nupDownMore: delta event: evt arrow: arrowMorph\\n\\n\\t| st delay1 delay2 now timeOfLastTick currentDelay |\\n\\t(self nodeClassIs: LiteralNode) ifFalse: [^ self].\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\tdelay1 _ 300. \\\"ms\\\"\\n\\tdelay2 _ 50. \\\"ms\\\"\\n\\tnow _ Time millisecondClockValue.\\n\\ttimeOfLastTick _ (self valueOfProperty: #timeOfLastTick) ifNil: [now - delay1].\\n\\tcurrentDelay _ (self valueOfProperty: #currentDelay) ifNil: [delay1].\\n\\tnow >= (timeOfLastTick + currentDelay) ifTrue:\\n\\t\\t[self setProperty: #timeOfLastTick toValue: now.\\n\\t\\t\\\"decrease the delay\\\"\\n\\t\\tself setProperty: #currentDelay toValue: (currentDelay*8//10 max: delay2).\\n\\t\\tst contents: (self decompile asNumber + delta) printString.\\n\\t\\t^ self acceptUnlogged].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:33'!\\ngetHeader: strm\\n\\t| se |\\n\\t\\\"We are in an EToy scriptor and the method header line has been removed. Try to recover the method name. Fail if method has args (deal with this later).\\\"\\n\\n\\t(se _ self ownerThatIsA: ScriptEditorMorph) ifNotNil: [\\n\\t\\tse scriptName numArgs > 0 ifTrue: [^ false].\\t\\\"abort\\\"\\n\\t\\tstrm nextPutAll: se scriptName].\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'dgd 2/22/2003 13:40'!\\nownerPrecedence\\n\\t\\\"Return the selector precedence of my owner. 1 for unary (asInteger), 2 for binary arithmetic (+), and 3 for keyword selectors (from:to:). Subtract 0.5 if self is an arg, not the receiver (the case of a + (b + c))\\\"\\n\\n\\t| oo below sel pp |\\n\\too := owner.\\n\\tbelow := self.\\n\\t\\n\\t[oo isSyntaxMorph ifFalse: [^10].\\t\\\"I do not need parens\\\"\\n\\too parseNode isNil] \\n\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t[below := oo.\\n\\t\\t\\t\\too := oo owner].\\n\\t(sel := oo selector) ifNil: [^10].\\n\\t(pp := sel precedence) = 3 ifTrue: [^2.5].\\t\\\"keyword messages need parens\\\"\\n\\t^oo receiverNode == below ifTrue: [pp] ifFalse: [pp - 0.5]! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 02:11'!\\nprintAssignmentNodeOn: strm indent: level\\n\\t\\\"sometimes an assignment is in parens\\\"\\n\\t| parens above |\\n\\n\\tparens _ submorphs size >= 3.\\n\\tparens ifTrue: [\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ above <= 3].\\t\\\"assignment is a noun inside a message\\\"\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tstrm ensureNoSpace. \\t\\\"_ will have a leading space\\\"\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 12:19'!\\nprintBlockArgsNodeOn: strm indent: level\\n\\n\\t| argString |\\n\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\t(argString _ sub decompile) isEmpty ifFalse: [\\n\\t\\t\\t\\tstrm \\n\\t\\t\\t\\t\\tnextPut: $:;\\n\\t\\t\\t\\t\\tnextPutAll: argString;\\n\\t\\t\\t\\t\\tspace\\n\\t\\t\\t].\\n\\t\\t] \\n\\t\\tifString: [ :sub |\\n\\t\\t\\t\\\"self printSimpleStringMorph: sub on: strm\\t<<<< do we need this??\\\"\\n\\t\\t].\\n\\tstrm nextPut: $|; crtab: level.\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:17'!\\nprintBlockNodeOn: strm indent: level\\n\\n\\t| lev inASyntaxButNotOutermost subNodeClass |\\n\\n\\tlev _ level.\\n\\tinASyntaxButNotOutermost _ owner isSyntaxMorph and: [ owner isMethodNode not].\\n\\tinASyntaxButNotOutermost ifTrue: [strm nextPut: $[. lev _ lev+1].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: lev.\\n\\t\\t\\tsubNodeClass _ sub parseNode class.\\n\\t\\t\\t(#(BlockArgsNode ReturnNode CommentNode) includes: subNodeClass name) ifFalse: [\\n\\t\\t\\t\\tstrm ensureNoSpace; nextPut: $.].\\n\\t\\t\\tsubNodeClass == BlockArgsNode\\n\\t\\t\\t\\tifTrue: [strm space]\\n\\t\\t\\t\\tifFalse: [strm crtab: lev].\\n\\t\\t] \\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tinASyntaxButNotOutermost ifTrue: [strm nextPut: $] ].\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:19'!\\nprintCascadeNodeOn: strm indent: level\\n\\n\\t| parens cnt me above |\\n\\n\\tparens _ parseNode receiver notNil.\\n\\tparens ifTrue: [me _ self selector precedence.\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ me > above].\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tcnt _ 0.\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tcnt _ cnt + 1.\\n\\t\\t\\t\\\"maybe we want to test sub isCascadePart for the following???\\\"\\n\\t\\t\\tcnt > 2 ifTrue: [strm nextPutAll: '; '].\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:17'!\\nprintMessageNodeOn: strm indent: level\\n\\n\\t| parens me above |\\n\\n\\tparens _ parseNode receiver notNil.\\n\\tparens ifTrue: [me _ self selector precedence.\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ me > above].\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 02:12'!\\nprintMethodNodeOn: strm indent: level\\n\\n\\t(self findA: SelectorNode) ifNil: [\\n\\t\\t(self getHeader: strm) ifFalse: [^ self].\\t\\t\\\"might fail\\\"\\n\\t\\tstrm crtab: level].\\n\\tself \\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm crtab: level.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t]. \\n\\tstrm last == $. ifTrue: [strm skip: -1]. \\\"ugh!! erase duplicate final period\\\"! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 12:08'!\\nprintMethodTempsNodeOn: strm indent: level\\n\\n\\tstrm nextPut: $|; space.\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm space.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tstrm nextPut: $|; crtab: level.\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 10/22/2000 20:43'!\\nprintOn: strm\\n\\n\\tsuper printOn: strm.\\n\\tstrm space; nextPutAll: parseNode class name.! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/14/2001 13:52'!\\nprintOn: strm indent: level\\n\\n\\t| nodeClass |\\n\\n\\t(self hasProperty: #ignoreNodeWhenPrinting) ifFalse: [\\n\\t\\tnodeClass _ parseNode class.\\n\\t\\tnodeClass == VariableNode ifTrue: [^self printVariableNodeOn: strm indent: level].\\n\\t\\tnodeClass == LiteralVariableNode ifTrue: [^self printVariableNodeOn: strm indent: level].\\n\\t\\tnodeClass == MessageNode ifTrue: [^self printMessageNodeOn: strm indent: level].\\n\\t\\tnodeClass == BlockNode ifTrue: [^self printBlockNodeOn: strm indent: level].\\n\\t\\tnodeClass == BlockArgsNode ifTrue: [^self printBlockArgsNodeOn: strm indent: level].\\n\\t\\tnodeClass == MethodNode ifTrue: [^self printMethodNodeOn: strm indent: level].\\n\\t\\tnodeClass == MethodTempsNode ifTrue: [^self printMethodTempsNodeOn: strm indent: level].\\n\\t\\tnodeClass == CascadeNode ifTrue: [^self printCascadeNodeOn: strm indent: level].\\n\\t\\tnodeClass == AssignmentNode ifTrue: [^self printAssignmentNodeOn: strm indent: level].\\n\\t].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 2/16/2001 18:16'!\\nprintSimpleStringMorph: aMorph on: strm\\n\\n\\t| trialContents |\\n\\n\\t(aMorph hasProperty: #wordyVariantOfSelf) ifTrue: [\\n\\t\\tstrm nextPutAll: 'self '.\\n\\t\\tstrm nextPutAll: ((self translateToWordySelfVariant: aMorph contents) ifNil: [^self]).\\n\\t\\t^self\\n\\t].\\n\\t(aMorph hasProperty: #noiseWord) ifFalse: [\\n\\t\\ttrialContents _ self cleanUpString: aMorph.\\n\\t\\tstrm nextPutAll: trialContents\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 2/13/2001 23:10'!\\nprintStatementsOn: aStream indent: indent\\n\\n\\t\\\"seemed to be necessary to see top node in explorer\\\"\\n\\n\\t^parseNode printStatementsOn: aStream indent: indent! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'ar 8/16/2001 13:29'!\\nprintVariableNodeOn: strm indent: level\\n\\n\\t\\\"nil out any old association\\\"\\n\\tparseNode key isVariableBinding ifTrue: [\\n\\t\\tparseNode \\n\\t\\t\\tname: parseNode name \\n\\t\\t\\tkey: nil \\n\\t\\t\\tcode: parseNode code\\n\\t].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'di 11/13/2000 07:43'!\\nstructure\\n\\t\\\"Print my structure from inner to outer.\\\"\\n\\t^ String streamContents: [:s |\\n\\t\\tself withAllOwnersDo:\\n\\t\\t\\t[:m | m isSyntaxMorph ifTrue:\\n\\t\\t\\t\\t[s cr; print: m parseNode class.\\n\\t\\t\\t\\t((m nodeClassIs: MessageNode) or: [m nodeClassIs: TileMessageNode]) ifTrue:\\n\\t\\t\\t\\t\\t[s space; nextPutAll: m parseNode selector key]]]]! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 11:55'!\\nsubmorphsDoIfSyntax: block1 ifString: block2 \\n\\n\\t^self submorphsDoIfSyntax: block1 ifString: block2 otherwise: [ :sub | ]\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'gm 2/22/2003 12:34'!\\nsubmorphsDoIfSyntax: block1 ifString: block2 otherwise: block3 \\n\\tsubmorphs do: \\n\\t\\t\\t[:sub | \\n\\t\\t\\tsub isSyntaxMorph \\n\\t\\t\\t\\tifTrue: [block1 value: sub]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(sub isKindOf: StringMorph) \\n\\t\\t\\t\\t\\t\\tifTrue: [block2 value: sub]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sub isTextMorph) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [block2 value: sub]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [block3 value: sub]]]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'scripting' stamp: 'tk 9/26/2001 06:01'!\\ntearOffTile\\n\\t\\\"For a SyntaxMorph, this means give a copy of me\\\"\\n\\n\\t| dup |\\n\\tdup _ self duplicate.\\n\\tActiveHand attachMorph: dup.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [^ dup lookTranslucent]\\n\\t\\tifFalse: [^ dup align: dup topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'di 11/17/2000 08:10'!\\ncurrentSelectionDo: blockForSelection\\n\\t| rootTile |\\n\\t(rootTile _ self rootTile) isMethodNode ifFalse:\\n\\t\\t [^ blockForSelection value: nil value: nil value: nil].\\n\\trootTile valueOfProperty: #selectionSpec ifPresentDo:\\n\\t\\t[:selectionSpec | ^ blockForSelection\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec first\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec second\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec third].\\n\\t^ blockForSelection value: nil value: nil value: nil! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'RAA 2/14/2001 11:33'!\\ndeselect\\n\\tself allMorphsDo:\\n\\t\\t[:m | m isSyntaxMorph ifTrue: [m setDeselectedColor]].\\n\\n\\t\\\"Note following is wasteful because we do a deselect before each select, and it is often the same morph.\\\"\\n\\tself deletePopup! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 1/17/2001 15:07'!\\nisSelectable\\n\\t| ss |\\n\\t\\\"Spacer morphs enclose other morphs with the same parseNode\\\"\\n\\tself submorphs size > 1 ifTrue: [\\n\\t\\tss _ self submorphs second.\\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode == parseNode ifTrue: [\\n\\t\\t\\t\\t^ self submorphs first class ~~ Morph]]].\\n\\t\\t\\n\\\"\\t(self nodeClassIs: SelectorNode) ifTrue: [^ false].\\n\\t(self nodeClassIs: KeyWordNode) ifTrue: [^ false].\\n\\\"\\n\\tself isMethodNode ifTrue: [^ false].\\n\\tparseNode ifNil: [^ false].\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/31/2001 17:18'!\\nscaleColorByUserPref: aColor\\n\\t\\n\\t| myRoot underLyingColor |\\n\\n\\tmyRoot _ self rootTile.\\n\\tunderLyingColor _ myRoot ifNil: [Color transparent] ifNotNil: [myRoot color].\\n\\t[underLyingColor isTransparent and: [(myRoot _ myRoot owner) notNil]] whileTrue: [\\n\\t\\tunderLyingColor _ myRoot color.\\n\\t].\\n\\t\\n\\t\\\"rude hack to get the desired effect before we have an owner\\\"\\n\\n\\tunderLyingColor isTransparent ifTrue: [underLyingColor _ Color r: 0.903 g: 1.0 b: 0.903].\\n\\t^aColor mixed: (ContrastFactor ifNil: [0.3]) with: underLyingColor\\n\\n\\\"Would like to be able to make MethodNode and outer Block be transparent. This method does not allow that. Consider (^ myRoot color) inside the whileTrue. Consider setting underLyingColor to (myRoot valueOfProperty: #deselectedBorderColor ifAbsent: [myRoot color]) in second line.\\\"! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/23/2001 18:31'!\\nselect\\n\\tself deselect.\\n\\t\\\"Outer block is not colored and has no popup\\\"\\n\\t(owner isSyntaxMorph and: [owner nodeClassIs: MethodNode]) \\n\\t\\tifTrue: [self setDeselectedColor \\\"normal\\\"]\\n\\t\\tifFalse: [self color: Color lightBrown].\\n\\tself borderColor: #raised.\\n\\tself offerPopUp.! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/19/2001 17:52'!\\nsetDeselectedColor\\n\\t\\\"The normal color of the tile, stored with the tile\\\"\\n\\t| deselectedColor deselectedBorderColor |\\n\\n\\tdeselectedColor _ self valueOfProperty: #deselectedColor ifAbsent: [nil].\\n\\tdeselectedBorderColor _ self valueOfProperty: #deselectedBorderColor ifAbsent: [nil].\\n\\tdeselectedColor ifNotNil: [\\n\\t\\tdeselectedColor _ self scaleColorByUserPref: deselectedColor].\\n\\tdeselectedBorderColor ifNotNil: [\\n\\t\\tdeselectedBorderColor _ self scaleColorByUserPref: deselectedBorderColor].\\n\\tself \\n\\t\\tcolor: (deselectedColor ifNil: [Color transparent]);\\n\\t\\tborderColor: (deselectedBorderColor ifNil: [Color transparent])! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'dgd 2/22/2003 13:41'!\\nsetSelection: newSpec \\n\\t\\\"A selectionSpec is {Inner morph. Where clicked. Outer morph}.\\n\\tFirst mouseDown starts a selection (with outerMorph isNil).\\n\\tDragging more than 4 pixels means to grab a copy of the current outer selection.\\n\\t\\tThe current selection is the outerMorph, or the inner if it is nil.\\n\\tEach mouseUp extends the selection to the next outer morph that is selectable.\\n\\t\\tExcept if this is the first click.\\\"\\n\\n\\t| rootTile |\\n\\t(rootTile := self rootTile) valueOfProperty: #selectionSpec\\n\\t\\tifPresentDo: [:oldSpec | oldSpec third ifNotNilDo: [:m | m deselect]].\\n\\t(newSpec isNil or: [newSpec third isNil and: [self isMethodNode]]) \\n\\t\\tifTrue: \\n\\t\\t\\t[self deselect.\\n\\t\\t\\t^rootTile removeProperty: #selectionSpec].\\n\\n\\t\\\"Select outer morph of the new selection\\\"\\n\\tnewSpec third isNil \\n\\t\\tifTrue: [self select\\t\\\"first click down\\\"]\\n\\t\\tifFalse: [newSpec third select\\t\\\"subsequent clicks\\\"].\\n\\trootTile setProperty: #selectionSpec toValue: newSpec! !\\n\\n\\n!SyntaxMorph methodsFor: 'stepping and presenter' stamp: 'tk 7/25/2001 11:26'!\\nstep\\n\\tsuper step.\\n\\tself isBlockNode ifTrue: [self trackDropZones].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'submorphs-accessing' stamp: 'tk 1/13/2001 20:41'!\\nfindA: aClass\\n\\t| ans |\\n\\t\\\"Allow finding on the class of the parseNode\\\"\\n\\n\\t(ans _ super findA: aClass) ifNotNil: [^ ans].\\n\\tsubmorphs do: [:ss | \\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode class == aClass ifTrue: [^ ss]]].\\n\\t^ nil! !\\n\\n\\n!SyntaxMorph methodsFor: 'testing' stamp: 'di 11/3/2000 08:03'!\\nstepTime\\n\\n\\t^ 50! !\\n\\n!SyntaxMorph methodsFor: 'testing' stamp: 'di 1/30/2001 11:22'!\\nwantsSteps\\n\\t\\\"Only step this morph if we explicitly send startStepping\\\"\\n\\n\\t^ false! !\\n\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'di 11/6/2000 10:47'!\\ntest\\n\\t3 > 4 ifTrue: [].\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'gm 2/22/2003 12:35'!\\ntestForNode: targetNode andDo: aBlock \\n\\ttargetNode == parseNode ifTrue: [aBlock value: self].\\n\\tself submorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each isSyntaxMorph) \\n\\t\\t\\t\\tifTrue: [each testForNode: targetNode andDo: aBlock]]! !\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'di 11/14/2000 14:54'!\\ntoDo\\n\\\"\\nBiggies...\\n[ ]\\tIntegrate with EToy scriptors\\n\\treleaseCachedState can discard all morphic structure.\\n\\n[ ]\\tOptions:\\n\\tShow / hide syntax markers (like [], (), ., :, ;, etc)\\n\\tNo color / color-in-focus / full color\\n\\tTiles / textiles / text\\n\\n[ ]\\tParsedTextMorph -- looks like text but has all same substructure\\n\\n[ ]\\tIntroduce notion of an UnParsedNode -- maybe a flag in ParseNode\\n\\tText -> UnParsed -> Parsed -> CodeGen\\n\\n[ ]\\tNeed DnD evaluator, or some sort of '!!' button on any entity (halo?)\\n\\tAlso inspector / browser\\n\\n[ ]\\tAll the type help we can get\\n\\nDetails ...\\n[ ]\\tOpen up the parse of BraceNodes\\n\\n[ ]\\tVerify that all pastes are OK\\n\\n[ ]\\tColors not yet right for colored version.\\n\\n[ ]\\tStart work on show / hide of syntax markers -- (), [], etc.\\n\\n[ ]\\tStart work on textiles (grabable entites in 'normal' text)\\n\\n[ ]\\tNeed autoscroll during drag for drop\\n\\n[ ]\\tUse, eg, shift-drag to move, del to delete\\n\\n[ ]\\tWhat about invalid drops -- stick on cursor?\\n\\nSystem...\\n[ ]\\tOnly keep history 7 deep; option to clear on quit\\n\\tclear command above spaceLeft\\n\\n[ ]\\tCompute each page of prefs viewer on demand instead of as now.\\n\\n[ ]\\tOffer a search command that will gather up all preferences that match a given string (name or help string)\\n\\nPreferences enable: #noTileColor.\\nPreferences disable: #noTileColor.\\nSmalltalk browseAllSelect: [:cm | cm size > 600]\\nSyntaxMorph testAll\\n\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/23/2001 23:40'!\\nargTypeFor: aSelector\\n\\t\\\"Answer the type of the argument of this selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\taSelector numArgs = 0 \\n\\t\\tifTrue: [self inform: aSelector, ' does not take an argument'. ^ #error \\\"7\\\"].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface typeForArgumentNumber: 1! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/15/2001 14:25'!\\nokToBeReplacedBy: aSyntaxMorph\\n\\t\\\"Return true if it is OK to replace me with aSyntaxMorph. Enforce the type rules in the old EToy green tiles.\\\"\\n\\n\\t| itsType myType |\\n\\t(Preferences eToyFriendly or: [Preferences typeCheckingInTileScripting])\\n\\t\\tifFalse: [^ true].\\t\\\"not checking unless one of those prefs is true\\\"\\n\\t(parseNode class == BlockNode and: [aSyntaxMorph parseNode class == BlockNode]) \\n\\t\\tifTrue: [^ true].\\n\\t(parseNode class == ReturnNode and: [aSyntaxMorph parseNode class == ReturnNode]) \\n\\t\\tifTrue: [^ true].\\n\\tparseNode class == KeyWordNode ifTrue: [^ false].\\n\\taSyntaxMorph parseNode class == KeyWordNode ifTrue: [^ false].\\n\\tparseNode class == SelectorNode ifTrue: [^ false].\\n\\taSyntaxMorph parseNode class == SelectorNode ifTrue: [^ false].\\n\\towner isSyntaxMorph ifFalse: [^ true].\\t\\\"only within a script\\\"\\n\\t\\t\\\"Transcript show: aSyntaxMorph resultType printString, ' dropped on ', \\n\\t\\t\\tself receiverOrArgType printString; cr.\\n\\t\\t\\\"\\n\\t(itsType _ aSyntaxMorph resultType) == #unknown ifTrue: [^ true].\\n\\t(myType _ self receiverOrArgType) == #unknown ifTrue: [^ true].\\n\\t\\t\\\"my type in enclosing message\\\"\\n\\t^ myType = itsType! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'tk 2/9/2001 15:56'!\\nreceiverOrArgType\\n\\t| ty |\\n\\t\\\"Return my type in my role as a receiver or as an argument. Ask my enclosing message first, then ask myself. (If owner accepts any #object, and I am a #point, do return #object.)\\\"\\n\\n\\t^ (ty _ self receiverOrArgTypeAbove) == #unknown\\n\\t\\tifTrue: [self resultType]\\n\\t\\tifFalse: [ty]! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'dgd 2/22/2003 18:48'!\\nreceiverOrArgTypeAbove\\n\\t\\\"Return the type for me according to the message that encloses me.\\\"\\n\\n\\t| enclosing sub list |\\n\\t(self nodeClassIs: BlockNode) ifTrue: [^#command].\\n\\tenclosing := owner.\\n\\tsub := self.\\n\\t\\n\\t[enclosing isSyntaxMorph ifFalse: [^#unknown].\\n\\t(enclosing nodeClassIs: MessageNode) \\n\\t\\tifTrue: \\n\\t\\t\\t[list := enclosing submorphs \\n\\t\\t\\t\\t\\t\\tselect: [:ss | ss isSyntaxMorph and: [ss parseNode notNil]].\\n\\t\\t\\tlist size = 1 \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[^(list indexOf: sub) = 1 \\n\\t\\t\\t\\t\\t\\tifTrue: [enclosing receiverTypeFor: enclosing selector]\\n\\t\\t\\t\\t\\t\\tifFalse: [enclosing argTypeFor: enclosing selector]]].\\n\\t(enclosing nodeClassIs: BlockNode) ifTrue: [^#command].\\n\\tsub := enclosing.\\n\\tenclosing := enclosing owner.\\n\\ttrue] \\n\\t\\t\\twhileTrue! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/27/2001 09:11'!\\nreceiverTypeFor: aSelector\\n\\t\\\"Answer the type of the receiver of this selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\n\\taSelector ifNil: [^ #unknown].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface receiverType! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'yo 7/22/2005 16:43'!\\nresultType\\n\\t\\\"Look up my result type. If I am a constant, use that class. If I am a message, look up the selector.\\\"\\n\\n\\t| list value soundChoices |\\n\\tparseNode class == BlockNode ifTrue: [^#blockContext].\\n\\tparseNode class == AssignmentNode ifTrue: [^#command].\\n\\tparseNode class == ReturnNode ifTrue: [^#command].\\t\\\"Need more restriction than this\\\"\\n\\tlist := submorphs \\n\\t\\t\\t\\tselect: [:ss | ss isSyntaxMorph and: [ss parseNode notNil]].\\n\\tlist size > 1 ifTrue: [^self resultTypeFor: self selector].\\n\\tlist size = 1 \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"test for levels that are just for spacing in layout\\\"\\n\\n\\t\\t\\t(list first isSyntaxMorph and: [list first nodeClassIs: MessageNode]) \\n\\t\\t\\t\\tifTrue: [^list first resultType]].\\t\\\"go down one level\\\"\\n\\tvalue := self try.\\n\\tvalue class == Error ifTrue: [^#unknown].\\n\\t(value isNumber) ifTrue: [^#Number].\\n\\t(value isKindOf: Boolean) ifTrue: [^#Boolean].\\n\\t(value isForm) ifTrue: [^#Graphic].\\n\\t(value isPlayerLike and: [value costume renderedMorph isMemberOf: KedamaPatchMorph]) ifTrue: [^#Patch].\\n\\tvalue isString\\n\\t\\tifTrue: \\n\\t\\t\\t[soundChoices := #('silence').\\t\\\"default, if no SampledSound class\\\"\\n\\t\\t\\tSmalltalk at: #SampledSound\\n\\t\\t\\t\\tifPresent: [:sampledSound | soundChoices := sampledSound soundNames].\\n\\t\\t\\t(soundChoices includes: value) ifTrue: [^#Sound]].\\n\\t(value isPlayerLike) ifTrue: [^#Player].\\n\\t^value class name asLowercase\\t\\\"asSymbol (not needed)\\\"! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/24/2001 12:13'!\\nresultTypeFor: aSelector\\n\\t\\\"Answer the result type of selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\taSelector ifNil: [self inform: 'Please tell Ted how you caused this'.\\n\\t\\t^ #abs \\\"a bogus type\\\"].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface resultType! !\\n\\n\\n!SyntaxMorph methodsFor: 'updating' stamp: 'di 11/13/2000 20:30'!\\nupdate: aSymbol\\n\\n\\t| bingo saveOwner newMorph db |\\n\\n\\t(db _ self debugger) ifNil: [^super update: aSymbol].\\n\\taSymbol == #contents ifTrue: [\\n\\t\\tsaveOwner _ owner.\\n\\t\\tdb removeDependent: self.\\n\\t\\tmarkerMorph ifNotNil: [markerMorph delete. markerMorph _ nil].\\n\\t\\tnewMorph _ db createSyntaxMorph.\\n\\t\\tself delete.\\n\\t\\tsaveOwner addMorph: newMorph.\\n\\t\\tsaveOwner owner setScrollDeltas.\\n\\t\\tnewMorph update: #contentsSelection.\\n\\t].\\n\\taSymbol == #contentsSelection ifTrue: [\\n\\t\\tmarkerMorph ifNil: [\\n\\t\\t\\tmarkerMorph _ RectangleMorph new.\\n\\t\\t\\tmarkerMorph\\n\\t\\t\\t\\tcolor: Color transparent;\\n\\t\\t\\t\\tborderWidth: 2;\\n\\t\\t\\t\\tborderColor: Color red;\\n\\t\\t\\t\\tlock.\\n\\t\\t\\towner addMorphFront: markerMorph.\\n\\t\\t].\\n\\t\\tbingo _ parseNode rawSourceRanges keyAtValue: db pcRange ifAbsent: [nil].\\n\\t\\tself testForNode: bingo andDo: [ :foundMorph | \\n\\t\\t\\tmarkerMorph\\n\\t\\t\\t\\tposition: foundMorph position;\\n\\t\\t\\t\\textent: foundMorph extent.\\n\\t\\t\\towner owner scrollIntoView: foundMorph bounds extra: 0.5.\\n\\t\\t\\t^self\\n\\t\\t].\\n\\t].\\n\\tsuper update: aSymbol! !\\n\\n\\n!SyntaxMorph methodsFor: 'viewer' stamp: 'tk 11/5/2001 08:32'!\\nexternalName\\n\\n\\t^ self knownName ifNil: [\\n\\t\\tparseNode ifNil: ['Syntax -- (extra layer)']\\n\\t\\t\\t\\tifNotNil: [self parseNode class printString]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'visual properties' stamp: 'tk 7/31/2001 16:53'!\\nfillStyle: aFillStyle\\n\\n\\taFillStyle isColor \\n\\t\\tifTrue: [self color: aFillStyle]\\t\\\"so we will process it\\\"\\n\\t\\tifFalse: [super fillStyle: aFillStyle].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'vocabulary' stamp: 'gm 2/22/2003 12:31'!\\nlimitClassToUseWith: aValue vocabulary: aVocabulary \\n\\t\\\"Answer the most generic whose method should be shown in a selector pop-up in the receiver that is put up on behalf of aValue\\\"\\n\\n\\t(aValue isNumber) ifTrue: [^Number].\\n\\t\\\"Ted: This hook allows you to intervene as suits your purposes here if you don't like the defaults.\\\"\\n\\t^aValue defaultLimitClassForVocabulary: aVocabulary! !\\n\\n!SyntaxMorph methodsFor: 'vocabulary' stamp: 'gm 2/22/2003 12:48'!\\nvocabularyToUseWith: aValue \\n\\t\\\"Answer a vocabulary to use with the given value\\\"\\n\\n\\t(aValue isNumber) ifTrue: [^Vocabulary numberVocabulary].\\n\\t(aValue isKindOf: Time) ifTrue: [^Vocabulary vocabularyForClass: Time].\\n\\t(aValue isString) ifTrue: [^Vocabulary vocabularyForClass: String].\\n\\taValue class isUniClass ifTrue: [^Vocabulary eToyVocabulary].\\n\\t^self currentVocabulary! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxMorph class methodsFor: 'accessing' stamp: 'tk 9/18/2001 16:10'!\\nsourceCodeTemplate\\n\\t\\\"Return the default tile method template\\\"\\n\\n\\t^ 'anEmpty: input1 method: input2\\n\\t\\\"Edit the name above and the code below to make your own method\\\"\\n\\t3 + 4.\\n\\t\\\"Drag tiles in here. Use the ''tiles'' and ''vars'' menus to get new tiles\\\"\\n\\t^ ''this is a statement'' sort' \\n! !\\n\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 22:59'!\\ncolumn: aColor on: aParseNode\\n\\n\\t| c color |\\n\\tcolor _ self translateColor: aColor.\\n\\t(c _ self newColumn)\\n\\t\\tparseNode: aParseNode;\\n\\t\\tlayoutInset: c standardInset;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcolor: color;\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: c stdBorderColor;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\tcellPositioning: c standardCellPositioning.\\n\\t^c\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/16/2001 15:37'!\\nmethodNodeOuter: aNode\\n\\n\\t^(self column: #method on: aNode) methodNodeOuter: aNode\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 11/13/2000 21:12'!\\nnoTileColor\\n\\n\\t^ true! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 23:00'!\\nrow: aColor on: aParseNode\\n\\n\\t| r color |\\n\\tcolor _ self translateColor: aColor.\\n\\t(r _ self newRow)\\n\\t\\tparseNode: aParseNode;\\n\\t\\tlayoutInset: r standardInset;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcolor: color;\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: r stdBorderColor;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\tcellPositioning: r standardCellPositioning.\\n\\t^r! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 5/2/2001 09:59'!\\nsetSize: oldExtent andMakeResizable: outerMorph\\n\\t| tw |\\n\\t(tw _ outerMorph findA: TwoWayScrollPane) ifNil: [^self].\\n\\ttw hResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tcolor: Color transparent;\\n\\t\\tsetProperty: #hideUnneededScrollbars toValue: true.\\n\\touterMorph \\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcellPositioning: #topLeft.\\n\\touterMorph fullBounds.\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 22:56'!\\nstandardInset\\n\\n\\t^ self alansTest1 ifTrue: [1] ifFalse: [-1@-1]! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 8/24/1999 11:59'!\\ntest\\n\\n\\\"\\nSyntaxMorph test\\n\\\"\\n\\tself testClass: MessageNode andMethod: #asMorphicSyntaxIn:.\\n\\t\\\"self testClass: MethodNode andMethod: #asMorphicSyntaxIn:.\\\"\\n\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'dvf 8/23/2003 12:20'!\\ntestAll\\n\\n\\t| source tree total count systNav|\\n\\\"\\nSyntaxMorph testAll\\n\\\"\\n\\tsystNav _ self systemNavigation.\\n\\tcount _ total _ 0.\\n\\tsystNav allBehaviorsDo: [ :aClass | total _ total + 1].\\n'Testing all behaviors'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: total\\n\\tduring: [ :bar |\\n\\t\\tsystNav allBehaviorsDo: [ :aClass |\\n\\t\\t\\tbar value: (count _ count + 1).\\n\\t\\t\\taClass selectors do: [ :aSelector |\\n\\t\\t\\t\\tsource _ (aClass compiledMethodAt: aSelector) getSourceFromFile.\\n\\t\\t\\t\\ttree _ Compiler new \\n\\t\\t\\t\\t\\tparse: source \\n\\t\\t\\t\\t\\tin: aClass \\n\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\ttree asMorphicSyntaxUsing: SyntaxMorph.\\n\\t\\t\\t].\\n\\t\\t].\\t].\\n\\n\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'dvf 8/23/2003 12:20'!\\ntestAllMethodsOver: methodSize \\n\\t\\\"MessageTally spyOn: [SyntaxMorph testAllMethodsOver: 600]\\\"\\n\\t\\\"Add up the total layout area for syntax morphs representing all \\n\\tmethods over the given size. This is a stress-test for SyntaxMorph \\n\\tlayout. A small value for the total area is also a figure of merit in the \\n\\tpresentation of Squeak source code in general.\\\"\\n\\t\\\"Results: \\n\\t#(69 600 180820874 103700) 11/4 \\n\\t70% build morphs, 12% get source, 9% layout, 8% parse, 1% roundoff \\n\\tFolded wide receivers, don't center keywords any more. \\n\\t#(68 600 160033784 127727) 11/9 \\n\\t76% build morphs, 8% get source, 8% layout, 8% parse, 0% roundoff \\n\\tFolded more messages, dropped extra vertical spacing in blocks. \\n\\t#(68 600 109141704 137308) 11/10 \\n\\t79% build morphs, 6% get source, 8% layout, 7% parse \\n\\tFolded more messages, dropped extra horizontal spacing. \\n\\t#(68 600 106912968 132171) 11/10 \\n\\t80% build morphs, ??% get source, 11% layout, 7% parse \\n\\tUnfolded keyword messages that will fit on one line. \\n\\t#(68 600 96497372 132153) 11/10 \\n\\t81% build morphs, ??% get source, 8% layout, 8% parse \\n\\tAfter alignment rewrite... \\n\\t#(74 600 101082316 244799) 11/12 \\n\\t76% build morphs, 4% get source, 15% layout, 5% parse \\n\\tAfter alignment rewrite... \\n\\t#(74 600 101250620 204972) 11/15 \\n\\t74% build morphs, 6% get source, 13% layout, 7% parse \\n\\t\\\"\\n\\t| tree source biggies morph stats time area |\\n\\tbiggies _ self systemNavigation \\n\\t\\t\\t\\tallMethodsSelect: [:cm | cm size > methodSize].\\n\\tstats _ OrderedCollection new.\\n\\t'Laying out all ' , biggies size printString , ' methods over ' , methodSize printString , ' bytes...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 1\\n\\t\\tto: biggies size\\n\\t\\tduring: [:bar | biggies\\n\\t\\t\\t\\twithIndexDo: [:methodRef :i | \\n\\t\\t\\t\\t\\tbar value: i.\\n\\t\\t\\t\\t\\tUtilities\\n\\t\\t\\t\\t\\t\\tsetClassAndSelectorFrom: methodRef\\n\\t\\t\\t\\t\\t\\tin: [:aClass :aSelector | \\n\\t\\t\\t\\t\\t\\t\\tsource _ (aClass compiledMethodAt: aSelector) getSourceFromFile.\\n\\t\\t\\t\\t\\t\\t\\ttime _ Time\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmillisecondsToRun: [tree _ Compiler new\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparse: source\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: aClass\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmorph _ tree asMorphicSyntaxUsing: SyntaxMorph.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tarea _ morph fullBounds area]].\\n\\t\\t\\t\\t\\tstats add: {methodRef. area. time}]].\\n\\t^ {{biggies size. methodSize. stats\\n\\t\\tdetectSum: [:a | a second]. stats\\n\\t\\tdetectSum: [:a | a third]}. (stats\\n\\t\\tasSortedCollection: [:x :y | x third >= y third]) asArray}! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 7/30/2001 16:29'!\\ntestClass: aClass andMethod: aSelector\\n\\t| tree |\\n\\ttree _ Compiler new \\n\\t\\tparse: (aClass sourceCodeAt: aSelector) \\n\\t\\tin: aClass \\n\\t\\tnotifying: nil.\\n\\t(tree asMorphicSyntaxUsing: SyntaxMorph)\\n\\t\\tparsedInClass: aClass;\\n\\t\\topenInWindow! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 7/19/2001 20:06'!\\ntranslateColor: aColorOrSymbol\\n\\n\\taColorOrSymbol isColor ifTrue: [^ aColorOrSymbol].\\n\\taColorOrSymbol == #comment ifTrue: [^ Color blue lighter].\\n\\taColorOrSymbol == #block ifTrue: [^ Color r: 0.903 g: 1.0 b: 0.903].\\n\\taColorOrSymbol == #method ifTrue: [^ Color r: 0.903 g: 1.0 b: 0.903].\\n\\taColorOrSymbol == #text ifTrue: [^ Color r: 0.9 g: 0.9 b: 0.9].\\n\\n\\tself noTileColor ifTrue: [^ Color r: 1.0 g: 0.839 b: 0.613].\\t\\\"override\\\"\\n\\n\\taColorOrSymbol == #assignment ifTrue: [^ Color paleGreen].\\n\\taColorOrSymbol == #keyword1 ifTrue: [^ Color paleBuff].\\t\\\"binary\\\"\\n\\taColorOrSymbol == #keyword2 ifTrue: [^ Color paleBuff lighter].\\t\\\"multipart\\\" \\n\\taColorOrSymbol == #cascade ifTrue: [^ Color paleYellow darker].\\t\\\"has receiver\\\"\\n\\taColorOrSymbol == #cascade2 ifTrue: [^ Color paleOrange].\\t\\\"one send in the cascade\\\"\\n\\taColorOrSymbol == #literal ifTrue: [^ Color paleMagenta].\\n\\taColorOrSymbol == #message ifTrue: [^ Color paleYellow].\\n\\taColorOrSymbol == #method ifTrue: [^ Color white].\\n\\taColorOrSymbol == #error ifTrue: [^ Color red].\\n\\taColorOrSymbol == #return ifTrue: [^ Color lightGray].\\n\\taColorOrSymbol == #variable ifTrue: [^ Color paleTan].\\n\\taColorOrSymbol == #brace ifTrue: [^ Color paleOrange].\\n\\taColorOrSymbol == #tempVariable ifTrue: [^ Color paleYellow mixed: 0.75 with: Color paleGreen\\n\\t\\t\\\"Color yellow lighter lighter\\\"].\\n\\taColorOrSymbol == #blockarg2 ifTrue: [\\n\\t\\t\\t^ Color paleYellow mixed: 0.75 with: Color paleGreen].\\t\\\"arg itself\\\"\\n\\taColorOrSymbol == #blockarg1 ifTrue: [^ Color paleRed].\\t\\\"container\\\"\\n\\t\\t\\\"yellow mixed: 0.5 with: Color white\\\"\\n\\n\\t^ Color tan\\t\\\"has to be something!!\\\"! !\\n\\n\\n!SyntaxMorph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-accessing' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nallSpecs\\n\\t\\\"Return all specs that the Viewer knows about. Cache them.\\\"\\n\\t\\\"SyntaxMorph allSpecs\\\"\\n\\n\\t^AllSpecs ifNil: [\\n\\t\\tAllSpecs := Dictionary new.\\n\\t\\t(EToyVocabulary morphClassesDeclaringViewerAdditions)\\n\\t\\t\\tdo: [:cls | cls allAdditionsToViewerCategories keysAndValuesDo: [ :k :v | \\n\\t\\t\\t\\t(AllSpecs at: k ifAbsentPut: [ OrderedCollection new ]) addAll: v ] ].\\n\\t\\tAllSpecs\\n\\t]! !\\n\\n!SyntaxMorph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-accessing' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nclearAllSpecs\\n\\t\\\"Clear the specs that the Viewer knows about.\\\"\\n\\t\\\"SyntaxMorph clearAllSpecs\\\"\\n\\n\\tAllSpecs := nil.! !\\nUpdatingStringMorph subclass: #SyntaxUpdatingStringMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Tile Scriptors'!\\n\\n!SyntaxUpdatingStringMorph methodsFor: 'drawing' stamp: 'tk 1/31/2002 09:53'!\\ndrawOn: aCanvas\\n\\n\\t| tempForm strm where chars wid spaceWidth putLigature topOfLigature sizeOfLigature colorOfLigature dots charZero canvas f |\\n\\n\\ttempForm _ Form extent: self extent depth: aCanvas depth.\\n\\tcanvas _ tempForm getCanvas.\\n\\tf _ self fontToUse.\\n\\tspaceWidth _ f widthOf: Character space.\\n\\tstrm _ ReadStream on: contents.\\n\\tcharZero _ Character value: 0.\\t\\\"a marker for center dot \\U00b7\\\"\\n\\twhere _ 0@0.\\n\\ttopOfLigature _ self height // 2 - 1.\\n\\tsizeOfLigature _ (spaceWidth-2)@(spaceWidth-2).\\n\\tcolorOfLigature _ Color black alpha: 0.45\\t\\\"veryLightGray\\\".\\n\\tdots _ OrderedCollection new.\\n\\tputLigature _ [\\n\\t\\tdots add: ((where x + 1) @ topOfLigature extent: sizeOfLigature).\\n\\t\\twhere _ where + (spaceWidth@0)].\\n\\tstrm peek = charZero ifTrue: [\\n\\t\\tstrm next.\\n\\t\\tputLigature value].\\n\\t[strm peek = charZero] whileTrue: [strm next].\\n\\t[strm atEnd] whileFalse: [\\n\\t\\tchars _ strm upTo: charZero.\\n\\t\\twid _ f widthOfString: chars.\\n\\t\\tcanvas drawString: chars at: where.\\n\\t\\twhere _ where + (wid@0).\\n\\t\\tstrm atEnd ifFalse: [putLigature value.\\n\\t\\t\\t[strm peek = charZero] whileTrue: [strm next]].\\n\\t].\\n\\taCanvas paintImage: tempForm at: self topLeft.\\n\\tdots do: [ :each |\\n\\t\\taCanvas \\n\\t\\t\\tfillRectangle: (each translateBy: self topLeft) \\n\\t\\t\\tfillStyle: colorOfLigature.\\n\\t].\\n! !\\nAppRegistry subclass: #SystemBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Base'!\\n!SystemBrowser commentStamp: '<historical>' prior: 0!\\nThis is the AppRegistry class for class browsing!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSystemBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!SystemBrowser class methodsFor: 'class initialization' stamp: 'sd 11/20/2005 21:28'!\\ninitialize\\n\\t| pref |\\n\\tpref := Preferences preferenceAt: #browserShowsPackagePane.\\n\\tPreferences\\n\\t\\taddPreference: #browserShowsPackagePane\\n\\t\\tcategories: pref categoryList\\n\\t\\tdefault: pref defaultValue\\n\\t\\tballoonHelp: pref helpString\\n\\t\\tprojectLocal: pref localToProject\\n\\t\\tchangeInformee: self\\n\\t\\tchangeSelector: #packagePanePreferenceChanged\\n\\t\\t! !\\n\\n\\n!SystemBrowser class methodsFor: 'events' stamp: 'sd 11/20/2005 21:28'!\\npackagePanePreferenceChanged\\n\\t| theOtherOne |\\n\\tself registeredClasses size = 2\\n\\t\\tifTrue: [theOtherOne := (self registeredClasses copyWithout: PackagePaneBrowser) first]\\n\\t\\tifFalse: [theOtherOne := nil].\\n\\t(Preferences valueOfFlag: #browserShowsPackagePane ifAbsent: [false])\\n\\t\\tifTrue: [self default: PackagePaneBrowser]\\n\\t\\tifFalse: [self default: theOtherOne].\\n\\tSystemNavigation default browserClass: self default.! !\\n\\n\\n!SystemBrowser class methodsFor: 'initialize-release' stamp: 'sd 11/20/2005 21:28'!\\nunload\\n\\t| pref |\\n\\tpref := Preferences preferenceAt: #browserShowsPackagePane.\\n\\tPreferences\\n\\t\\taddPreference: #browserShowsPackagePane\\n\\t\\tcategories: pref categoryList\\n\\t\\tdefault: pref defaultValue\\n\\t\\tballoonHelp: pref helpString\\n\\t\\tprojectLocal: pref localToProject\\n\\t\\tchangeInformee: nil\\n\\t\\tchangeSelector: nil\\n\\t\\t! !\\n\\n\\n!SystemBrowser class methodsFor: 'instance creation' stamp: 'hpt 8/5/2004 20:27'!\\ndefaultOpenBrowser\\n\\t^self default openBrowser! !\\n\\n\\n!SystemBrowser class methodsFor: 'registration' stamp: 'hpt 9/30/2004 20:53'!\\naddRegistryMenuItemsTo: aMenu inAccountOf: aBrowser \\n\\t\\\"Add some useful options related Browser registry to the\\n\\tbrowsers windows menu\\\"\\n\\taMenu addLine;\\n\\t\\tadd: 'Register this Browser as default'\\n\\t\\ttarget: [self default: aBrowser class]\\n\\t\\taction: #value;\\n\\t\\tadd: 'Choose new default Browser'\\n\\t\\ttarget: self\\n\\t\\taction: #askForDefault! !\\nSystemChangeTestRoot subclass: #SystemChangeErrorHandling\\n\\tinstanceVariableNames: 'capturedEvents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeErrorHandling commentStamp: 'rw 4/3/2006 17:21' prior: 0!\\nThis class tests the error handing of the notification mechanism to ensure that one client that receives a system change cannot lock up the complete system.\\\"!\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nhandleEventWithError: event\\n\\n\\tself error: 'Example of event handling code that throws an error.'! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 18:07'!\\nhandleEventWithHalt: event\\n\\n\\tself halt: 'Example of event handling code that contains a halt.'! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent1: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent2: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent3: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Running' stamp: 'rw 4/3/2006 17:51'!\\nsetUp\\n\\n\\tsuper setUp.\\n\\tcapturedEvents := OrderedCollection new! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Running' stamp: 'rw 4/3/2006 17:56'!\\ntearDown\\n\\n\\tcapturedEvents := nil.\\n\\tsuper tearDown! !\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestErrorOperation\\n\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent1:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent2:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #handleEventWithError:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: Error do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestHaltOperation\\n\\t\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent1:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent2:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #handleEventWithHalt:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: Halt do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestUnhandledEventOperation\\n\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent1:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent2:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #zork:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: MessageNotUnderstood do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\nObject subclass: #SystemChangeNotifier\\n\\tinstanceVariableNames: 'eventSource silenceLevel'\\n\\tclassVariableNames: 'UniqueInstance'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!SystemChangeNotifier methodsFor: 'initialize' stamp: 'NS 1/26/2004 20:41'!\\ninitialize\\n\\n\\teventSource := SystemEventManager new.\\n\\tsilenceLevel _ 0.! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/28/2004 11:29'!\\ndoSilently: aBlock\\n\\t\\\"Perform the block, and ensure that no system notification are broadcasted while doing so.\\\"\\n\\n\\t| result |\\n\\tsilenceLevel := silenceLevel + 1.\\n\\t[result := aBlock value] ensure: [silenceLevel > 0 ifTrue: [silenceLevel := silenceLevel - 1]].\\n\\t^ result.! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/26/2004 20:41'!\\nisBroadcasting\\n\\n\\t^ silenceLevel = 0! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/29/2003 17:01'!\\nnoMoreNotificationsFor: anObject\\n\\t\\\"Stop sending system notifications to an object.\\\"\\n\\n\\teventSource removeActionsWithReceiver: anObject! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/10/2003 12:00'!\\nnotify: anObject ofAllSystemChangesUsing: oneArgumentSelector \\n\\t\\\"Notifies an object of any system changes.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: self allSystemEvents\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfChange: changeKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified changeKind (#added, #removed, ...). Evaluate 'AbstractEvent allChangeKinds' to get the complete list.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (self systemEventsForChange: changeKind)\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfItem: itemKind change: changeKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified itemKind (#class, #category, ...) and changeKind (#added, #removed, ...). This is the finest granularity possible.\\n\\tEvaluate 'AbstractEvent allChangeKinds' to get the complete list of change kinds, and 'AbstractEvent allItemKinds to get all the possible item kinds supported.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (Bag with: (self systemEventsForItem: itemKind change: changeKind))\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfItem: itemKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified itemKind (#class, #method, #protocol, ...). Evaluate 'AbstractEvent allItemKinds' to get the complete list.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (self systemEventsForItem: itemKind)\\n\\t\\tusing: oneArgumentSelector! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:32'!\\nclassCategoryAdded: aClassCategoryName\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\t\\tclassCategory: aClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:35'!\\nclassCategoryRemoved: aClassCategoryName\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\t\\tclassCategory: aClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:44'!\\nclassCategoryRenamedFrom: anOldClassCategoryName to: aNewClassCategoryName\\n\\n\\tself trigger: (RenamedEvent\\n\\t\\t\\t\\t\\tclassCategoryRenamedFrom: anOldClassCategoryName \\n\\t\\t\\t\\t\\tto: aNewClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:12'!\\nclass: aClass recategorizedFrom: oldCategory to: newCategory \\n\\tself trigger: (RecategorizedEvent \\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\tcategory: newCategory\\n\\t\\t\\t\\toldCategory: oldCategory)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:11'!\\nclassAdded: aClass inCategory: aCategoryName \\n\\tself trigger: (AddedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/26/2004 09:37'!\\nclassCommented: aClass\\n\\t\\\"A class with the given name was commented in the system.\\\"\\n\\n\\tself trigger: (CommentedEvent class: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:11'!\\nclassCommented: aClass inCategory: aCategoryName \\n\\t\\\"A class with the given name was commented in the system.\\\"\\n\\n\\tself trigger: (CommentedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/20/2004 19:37'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\tself trigger: (ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/16/2004 15:10'!\\nclassRemoved: aClass fromCategory: aCategoryName \\n\\tself trigger: (RemovedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:19'!\\nclassRenamed: aClass from: oldClassName to: newClassName inCategory: aCategoryName \\n\\tself trigger: (RenamedEvent \\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\tcategory: aCategoryName\\n\\t\\t\\t\\toldName: oldClassName\\n\\t\\t\\t\\tnewName: newClassName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:48'!\\nclassReorganized: aClass\\n\\tself trigger: (ReorganizedEvent class: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/19/2004 09:48'!\\nevaluated: textOrStream\\n\\t^ self evaluated: textOrStream context: nil.! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/19/2004 09:47'!\\nevaluated: expression context: aContext\\n\\tself trigger: (DoItEvent \\n\\t\\t\\t\\texpression: expression\\n\\t\\t\\t\\tcontext: aContext)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inClass: aClass \\n\\t\\\"A method with the given selector was added to aClass, but not put in a protocol.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\t\\\"A method with the given selector was added to aClass, but not put in a protocol.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inProtocol: aCategoryName class: aClass \\n\\t\\\"A method with the given selector was added to aClass in protocol aCategoryName.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod\\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: aCategoryName\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inProtocol: aCategoryName class: aClass requestor: requestor\\n\\t\\\"A method with the given selector was added to aClass in protocol aCategoryName.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod\\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: aCategoryName\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:41'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass\\n\\tself trigger: (ModifiedEvent\\n\\t\\t\\t\\t\\tmethodChangedFrom: oldMethod\\n\\t\\t\\t\\t\\tto: newMethod\\n\\t\\t\\t\\t\\tselector: aSymbol \\n\\t\\t\\t\\t\\tinClass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:41'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\tself trigger: (ModifiedEvent\\n\\t\\t\\t\\t\\tmethodChangedFrom: oldMethod\\n\\t\\t\\t\\t\\tto: newMethod\\n\\t\\t\\t\\t\\tselector: aSymbol \\n\\t\\t\\t\\t\\tinClass: aClass\\n\\t\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/28/2004 11:12'!\\nmethodRemoved: aMethod selector: aSymbol class: aClass \\n\\t\\\"A method with the given selector was removed from the class.\\\"\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/28/2004 11:11'!\\nmethodRemoved: aMethod selector: aSymbol inProtocol: protocol class: aClass \\n\\t\\\"A method with the given selector was removed from the class.\\\"\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: protocol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 4/7/2004 13:35'!\\nselector: selector recategorizedFrom: oldCategory to: newCategory inClass: aClass\\n\\n\\tself trigger: (RecategorizedEvent \\n\\t\\t\\t\\tmethod: (aClass compiledMethodAt: selector ifAbsent: [nil])\\n\\t\\t\\t\\tprotocol: newCategory\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\toldProtocol: oldCategory)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'al 7/18/2004 10:48'!\\ntraitDefinitionChangedFrom: oldTrait to: newTrait\\n\\tself trigger: (ModifiedTraitDefinitionEvent traitDefinitionChangedFrom: oldTrait to: newTrait)! !\\n\\n\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'rw 7/10/2003 15:15'!\\nnotify: anObject ofEvents: eventsCollection using: oneArgumentSelector\\n\\t\\\"Notifies an object of any events in the eventsCollection. Send it back a message #oneArgumentSelector, with as argument the particular system event instance.\\\"\\n\\n\\teventsCollection do: [:eachEvent |\\n\\t\\teventSource when: eachEvent send: oneArgumentSelector to: anObject]! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'rw 7/29/2003 17:05'!\\nreleaseAll\\n\\t\\\"Release all the dependents so that nobody receives notifications anymore.\\\"\\n\\n\\t\\\"Done for cleaning up the system.\\\"\\n\\t\\\"self uniqueInstance releaseAll\\\"\\n\\n\\teventSource releaseActionMap! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'NS 1/26/2004 20:43'!\\nsetBroadcasting\\n\\tsilenceLevel := 0.! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'NS 1/26/2004 20:41'!\\ntrigger: event\\n\\n\\tself isBroadcasting ifTrue: [event trigger: eventSource]\\n\\n\\\"\\t| caughtExceptions |\\n\\tcaughtExceptions := OrderedCollection new.\\n\\tself isBroadcasting ifTrue: [\\n\\t\\t[(eventSource actionForEvent: event eventSelector) valueWithArguments: (Array with: event)] on: Exception do: [:exc | caughtExceptions add: exc]].\\n\\tcaughtExceptions do: [:exc | exc resignalAs: exc class new]\\\"! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nallSystemEvents\\n\\t^AbstractEvent systemEvents! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForChange: changeKind \\n\\t| selectorBlock |\\n\\tselectorBlock := AbstractEvent eventSelectorBlock.\\n\\t^AbstractEvent allItemKinds \\n\\t\\tcollect: [:itemKind | selectorBlock value: itemKind value: changeKind]! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForItem: itemKind \\n\\t| selectorBlock |\\n\\tselectorBlock := AbstractEvent eventSelectorBlock.\\n\\t^AbstractEvent allChangeKinds \\n\\t\\tcollect: [:changeKind | selectorBlock value: itemKind value: changeKind]! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForItem: itemKind change: changeKind \\n\\t^AbstractEvent eventSelectorBlock value: itemKind value: changeKind! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSystemChangeNotifier class\\n\\tinstanceVariableNames: ''!\\n\\n!SystemChangeNotifier class methodsFor: 'instance creation' stamp: 'rw 6/28/2003 09:41'!\\nnew\\n\\n\\t^self error: self instanceCreationErrorString! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\ncategoryKind\\n\\n\\t^ AbstractEvent categoryKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\nclassKind\\n\\n\\t^ AbstractEvent classKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'!\\nexpressionKind\\n\\t^ AbstractEvent expressionKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\nmethodKind\\n\\n\\t^ AbstractEvent methodKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'!\\nprotocolKind\\n\\t^ AbstractEvent protocolKind! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'public' stamp: 'NS 1/27/2004 16:23'!\\nuniqueInstance\\n\\n\\tUniqueInstance ifNil: [UniqueInstance := self createInstance].\\n\\t^UniqueInstance! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'NS 1/27/2004 16:23'!\\ncreateInstance\\n\\n\\t^self basicNew initialize! !\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'rw 6/28/2003 09:41'!\\ninstanceCreationErrorString\\n\\n\\t^'This is a singleton implementation, so you are not allowed to create instances yourself. Use #uniqueInstance to access the instance.'! !\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'rw 7/11/2003 14:36'!\\nresetUniqueInstance\\n\\t\\\"self resetUniqueInstance\\\"\\n\\n\\tUniqueInstance\\n\\t\\tifNotNilDo: [:u | UniqueInstance releaseAll.\\n\\t\\t\\tUniqueInstance _ nil]! !\\nSystemChangeTestRoot subclass: #SystemChangeNotifierTest\\n\\tinstanceVariableNames: 'capturedEvent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeNotifierTest commentStamp: 'rw 4/3/2006 17:19' prior: 0!\\nA SystemChangeNotifierTest is a test class that tests whether the triggering of changes indeed results in the intended changes to be sent to registered object. The basic mechanism for each test is fairly simple:\\n\\t- register the receiver as the one to get the change notifier.\\n\\t- manually trigger a change (so the system is not polluted just to see whether we get the needed event).\\n\\t- the method #event: is invoked and remembers the change event.\\n\\t- the change event is checked to see whether it was the intended one.\\n\\nInstance Variables\\n\\tcapturedEvent:\\t\\tRemembers the captured event!\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:34'!\\ncapturedEvent: eventOrNil\\n\\t\\\"Remember the event being sent.\\\"\\n\\n\\tcapturedEvent := eventOrNil! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:36'!\\ncheckEventForClass: aClass category: cat change: changeKind \\n\\n\\tself assert: (capturedEvent perform: ('is' , changeKind) asSymbol).\\n\\tself assert: capturedEvent item = aClass.\\n\\tself assert: capturedEvent itemKind = AbstractEvent classKind.\\n\\tself assert: capturedEvent itemClass = aClass.\\n\\tself assert: capturedEvent itemCategory = cat! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:43'!\\ncheckEventForMethod: aMethod protocol: prot change: changeKind \\n\\n\\tself assert: (capturedEvent perform: ('is' , changeKind) asSymbol).\\n\\tself assert: capturedEvent item = aMethod.\\n\\tself assert: capturedEvent itemKind = AbstractEvent methodKind.\\n\\tself assert: capturedEvent itemClass = self class.\\n\\tself assert: capturedEvent itemMethod = aMethod.\\n\\tself assert: capturedEvent itemProtocol = prot! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:43'!\\ncheckEventForMethod: aMethod protocol: prot change: changeKind oldMethod: oldMethod\\n\\n\\tself checkEventForMethod: aMethod protocol: prot change: changeKind.\\n\\tself assert: capturedEvent oldItem == oldMethod\\n\\t! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:50'!\\nevent: event\\n\\t\\\"The notification message being sent to me when an event is captured. Remember it.\\\"\\n\\n\\\"\\tcapturedEvent isNil ifTrue: [\\tself capturedEvent: event] ifFalse: [self assert: false]\\\"\\n\\n\\tself capturedEvent: event! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Running' stamp: 'rw 4/3/2006 17:55'!\\ntearDown\\n\\n\\tself capturedEvent: nil.\\n\\tsuper tearDown! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassAddedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classAdded: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassAddedEvent2\\n\\n\\tself systemChangeNotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #event:.\\n\\tself systemChangeNotifier classAdded: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassCommentedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classCommented: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Commented! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRecategorizedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tclass: self class\\n\\t\\trecategorizedFrom: #FooCat\\n\\t\\tto: #FooBar.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooBar\\n\\t\\tchange: #Recategorized.\\n\\tself assert: capturedEvent oldCategory = #FooCat! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRemovedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classRemoved: self class fromCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Removed! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRenamedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tclassRenamed: self class\\n\\t\\tfrom: #OldFooClass\\n\\t\\tto: #NewFooClass\\n\\t\\tinCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Renamed.\\n\\\"\\tself assert: capturedEvent oldName = #OldFooClass.\\n\\tself assert: capturedEvent newName = #NewFooClass\\\"! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestDoItEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tevaluated: '1 + 2'\\n\\t\\tcontext: self.\\n\\tself assert: capturedEvent isDoIt.\\n\\tself assert: capturedEvent item = '1 + 2'.\\n\\tself assert: capturedEvent itemKind = AbstractEvent expressionKind.\\n\\tself assert: capturedEvent itemClass = nil.\\n\\tself assert: capturedEvent itemMethod = nil.\\n\\tself assert: capturedEvent itemProtocol = nil.\\n\\tself assert: capturedEvent itemExpression = '1 + 2'.\\n\\tself assert: capturedEvent context = self.! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent1\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodAdded: self class >> #testMethodAddedEvent1\\n\\t\\tselector: #testMethodAddedEvent1\\n\\t\\tinProtocol: #FooCat\\n\\t\\tclass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent1\\n\\t\\tprotocol: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent2\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodAdded: self class >> #testMethodAddedEvent1\\n\\t\\tselector: #testMethodAddedEvent1\\n\\t\\tinClass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent1\\n\\t\\tprotocol: nil\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent3\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodChangedFrom: self class >> #testMethodAddedEvent1\\n\\t\\tto: self class >> #testMethodAddedEvent2\\n\\t\\tselector: #testMethodAddedEvent2\\n\\t\\tinClass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent2\\n\\t\\tprotocol: nil\\n\\t\\tchange: #Modified\\n\\t\\toldMethod: self class >> #testMethodAddedEvent1.! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodRemovedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodRemoved: self class>> #testMethodRemovedEvent\\n\\t\\tselector: #testMethodRemovedEvent\\n\\t\\tinProtocol: #FooCat\\n\\t\\tclass: self class.\\n\\tself\\n\\t\\tcheckEventForMethod: self class>> #testMethodRemovedEvent\\n\\t\\tprotocol: #FooCat\\n\\t\\tchange: #Removed.! !\\nTestCase subclass: #SystemChangeTestRoot\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeTestRoot commentStamp: 'rw 4/5/2006 17:28' prior: 0!\\nThe Root test class for the System Change Notification tests.!\\n\\n\\n!SystemChangeTestRoot methodsFor: 'Private' stamp: 'rw 4/3/2006 17:48'!\\nsystemChangeNotifier\\n\\t\\\"The notifier to use. Use the one for the system.\\\"\\n\\n\\t^SystemChangeNotifier uniqueInstance! !\\n\\n\\n!SystemChangeTestRoot methodsFor: 'Running' stamp: 'rw 4/3/2006 17:59'!\\ntearDown\\n\\n\\tself unhook.\\n\\tsuper tearDown! !\\n\\n!SystemChangeTestRoot methodsFor: 'Running' stamp: 'rw 4/3/2006 17:23'!\\nunhook\\n\\n\\tself systemChangeNotifier noMoreNotificationsFor: self! !\\nIdentityDictionary subclass: #SystemDictionary\\n\\tinstanceVariableNames: 'cachedClassNames'\\n\\tclassVariableNames: 'LastImageName LastQuitLogPosition LowSpaceProcess LowSpaceSemaphore MemoryHogs ShutDownList SpecialSelectors StartUpList StartupStamp SystemChanges'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support'!\\n!SystemDictionary commentStamp: '<historical>' prior: 0!\\nI represent a special dictionary that supports protocol for asking questions about the structure of the system. Other than class names, I contain (print this)...\\n\\tSmalltalk keys select: [:k | ((Smalltalk at: k) isKindOf: Class) not]\\n\\t\\t\\tthenCollect: [:k | k -> (Smalltalk at: k) class]\\n!\\n\\n\\n!SystemDictionary methodsFor: 'accessing' stamp: 'ar 7/11/1999 21:56'!\\norganization\\n\\t\\\"Return the organizer for the receiver\\\"\\n\\t^SystemOrganization! !\\n\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:59'!\\nallClassesAndTraits\\n\\t\\\"Return all the classes and traits defined in the Smalltalk SystemDictionary\\\"\\n\\n\\t^ self classNames , self traitNames collect: [:each | self at: each]! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/13/2006 00:15'!\\nallClassesAndTraitsDo: aBlock\\n\\t^self allClassesAndTraits do: aBlock! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:57'!\\nclassNamed: className \\n\\t^self classOrTraitNamed: className.! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/13/2006 00:51'!\\nclassNames\\n\\t\\\"Answer a SortedCollection of all class names.\\\"\\n\\t| names |\\n\\tcachedClassNames == nil ifTrue:\\n\\t\\t[names _ OrderedCollection new: self size.\\n\\t\\tself do: \\n\\t\\t\\t[:cl | (cl isInMemory\\n\\t\\t\\t\\tand: [(cl isKindOf: Class)\\n\\t\\t\\t\\t\\tand: [(cl name beginsWith: 'AnObsolete') not]])\\n\\t\\t\\t\\tifTrue: [names add: cl name]].\\n\\t\\tcachedClassNames _ names asSortedCollection].\\n\\t^ cachedClassNames! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:56'!\\nclassOrTraitNamed: aString \\n\\t\\\"aString is either a class or trait name or a class or trait name followed by ' class' or 'classTrait' respectively.\\n\\tAnswer the class or metaclass it names.\\\"\\n\\n\\t| meta baseName baseClass |\\n\\t(aString endsWith: ' class')\\n\\t\\tifTrue: [meta _ true.\\n\\t\\t\\t\\tbaseName _ aString copyFrom: 1 to: aString size - 6]\\n\\t\\tifFalse: [\\n\\t\\t\\t(aString endsWith: ' classTrait')\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tmeta _ true.\\n\\t\\t\\t\\t\\tbaseName _ aString copyFrom: 1 to: aString size - 11]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tmeta _ false.\\n\\t\\t\\t\\t\\tbaseName _ aString]].\\n\\tbaseClass _ Smalltalk at: baseName asSymbol ifAbsent: [^ nil].\\n\\tmeta\\n\\t\\tifTrue: [^ baseClass classSide]\\n\\t\\tifFalse: [^ baseClass]! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'di 2/16/2000 10:28'!\\nflushClassNameCache\\n\\t\\\"Smalltalk flushClassNameCache\\\"\\n\\t\\\"Forse recomputation of the cached list of class names.\\\"\\n\\n\\tcachedClassNames _ nil! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'NS 1/27/2004 12:08'!\\nforgetClass: aClass logged: aBool \\n\\t\\\"Delete the class, aClass, from the system.\\n\\tNote that this doesn't do everything required to dispose of a class - to do that use Class>>removeFromSystem.\\\"\\n\\n\\taBool ifTrue: [SystemChangeNotifier uniqueInstance classRemoved: aClass fromCategory: aClass category].\\t\\t\\n\\tSystemOrganization removeElement: aClass name.\\n\\tself removeFromStartUpList: aClass.\\n\\tself removeFromShutDownList: aClass.\\n\\tself removeKey: aClass name ifAbsent: [].\\n\\tself flushClassNameCache! !\\n\\n!SystemDictionary methodsFor: 'class and trait names'!\\nhasClassNamed: aString\\n\\t\\\"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\\\"\\n\\n\\tSymbol hasInterned: aString ifTrue: \\n\\t\\t[:aSymbol | ^ (self at: aSymbol ifAbsent: [nil]) isKindOf: Class].\\n\\t^ false! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'sw 9/5/97 18:30'!\\nremoveClassNamed: aName\\n\\t\\\"Invoked from fileouts: if there is currently a class in the system named aName, then remove it. If anything untoward happens, report it in the Transcript. \\\"\\n\\n\\t| oldClass |\\n\\t(oldClass _ self at: aName asSymbol ifAbsent: [nil]) == nil\\n\\t\\tifTrue:\\n\\t\\t\\t[Transcript cr; show: 'Removal of class named ', aName, ' ignored because ', aName, ' does not exist.'.\\n\\t\\t\\t^ self].\\n\\n\\toldClass removeFromSystem! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'sw 10/28/96'!\\nrenameClassNamed: oldName as: newName\\n\\t\\\"Invoked from fileouts: if there is currently a class in the system named oldName, then rename it to newName. If anything untoward happens, report it in the Transcript. \\\"\\n\\n\\t| oldClass |\\n\\t(oldClass _ self at: oldName asSymbol ifAbsent: [nil]) == nil\\n\\t\\tifTrue:\\n\\t\\t\\t[Transcript cr; show: 'Class-rename for ', oldName, ' ignored because ', oldName, ' does not exist.'.\\n\\t\\t\\t^ self].\\n\\n\\toldClass rename: newName! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'rr 3/11/2004 15:18'!\\nrenameClass: aClass as: newName \\n\\t\\\"Rename the class, aClass, to have the title newName.\\\"\\n\\t| oldref i oldName category |\\n\\toldName := aClass name.\\n\\tcategory := aClass category.\\n\\tSystemOrganization classify: newName under: aClass category.\\n\\tSystemOrganization removeElement: aClass name.\\n\\toldref _ self associationAt: aClass name.\\n\\tself removeKey: aClass name.\\n\\toldref key: newName.\\n\\tself add: oldref. \\\"Old association preserves old refs\\\"\\n\\t(Array with: StartUpList with: ShutDownList) do:\\n\\t\\t[:list | i _ list indexOf: aClass name ifAbsent: [0].\\n\\t\\ti > 0 ifTrue: [list at: i put: newName]].\\n\\tself flushClassNameCache.\\n\\tSystemChangeNotifier uniqueInstance classRenamed: aClass from: oldName to: newName inCategory: category! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:54'!\\ntraitNames\\n\\t\\\"Answer a SortedCollection of all traits (not including class-traits) names.\\\"\\n\\t| names |\\n\\tnames := OrderedCollection new.\\n\\tself do: \\n\\t\\t[:cl | (cl isInMemory\\n\\t\\t\\tand: [(cl isKindOf: Trait)\\n\\t\\t\\tand: [(cl name beginsWith: 'AnObsolete') not]])\\n\\t\\t\\t\\tifTrue: [names add: cl name]].\\n\\t^ names! !\\n\\n\\n!SystemDictionary methodsFor: 'copying' stamp: 'tk 10/20/2000 11:35'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I can't be copied. Do not record me.\\\"! !\\n\\n\\n!SystemDictionary methodsFor: 'dictionary access' stamp: 'md 3/2/2006 22:01'!\\nassociationOrUndeclaredAt: key \\n\\t\\\"return an association or install in undeclared. Used for mating up ImageSegments.\\\"\\n\\n\\t^ self associationAt: key ifAbsent: [\\n\\t\\tUndeclared at: key put: nil.\\n\\t\\tUndeclared associationAt: key]! !\\n\\n!SystemDictionary methodsFor: 'dictionary access'!\\nat: aKey put: anObject \\n\\t\\\"Override from Dictionary to check Undeclared and fix up\\n\\treferences to undeclared variables.\\\"\\n\\t| index element |\\n\\t(self includesKey: aKey) ifFalse: \\n\\t\\t[self declare: aKey from: Undeclared.\\n\\t\\tself flushClassNameCache].\\n\\tsuper at: aKey put: anObject.\\n\\t^ anObject! !\\n\\n\\n!SystemDictionary methodsFor: 'housekeeping'!\\ncleanOutUndeclared \\n\\tUndeclared removeUnreferencedKeys! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'md 1/5/2004 18:05'!\\ncompressSources\\t\\n\\t\\\"Copy all the source file to a compressed file. Usually preceded by Smalltalk condenseSources.\\\"\\n\\t\\\"The new file will be created in the default directory, and the code in openSources\\n\\twill try to open it if it is there, otherwise it will look for normal sources.\\\"\\n\\t\\\"Smalltalk compressSources\\\"\\n\\n\\t| f cfName cf |\\n\\tf _ SourceFiles first.\\n\\t(SmalltalkImage current sourcesName endsWith: 'sources')\\n\\t\\tifTrue: [cfName _ (SmalltalkImage current sourcesName allButLast: 7) , 'stc']\\n\\t\\tifFalse: [self error: 'Hey, I thought the sources name ended with ''.sources''.'].\\n\\tcf _ (CompressedSourceStream on: (FileStream newFileNamed: cfName))\\n\\t\\t\\t\\tsegmentSize: 20000 maxSize: f size.\\n\\n\\t\\\"Copy the sources\\\"\\n'Compressing Sources File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: f size\\n\\tduring:\\n\\t\\t[:bar | f position: 0.\\n\\t\\t[f atEnd] whileFalse:\\n\\t\\t\\t[cf nextPutAll: (f next: 20000).\\n\\t\\t\\tbar value: f position]].\\n\\tcf close.\\n\\tself setMacFileInfoOn: cfName.\\n\\tself inform: 'You now have a compressed sources file!!\\nSqueak will use it the next time you start.'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'al 1/13/2006 00:17'!\\ncondenseChanges\\n\\t\\\"Move all the changes onto a compacted sources file.\\\"\\n\\t\\\"Smalltalk condenseChanges\\\"\\n\\t| f oldChanges count |\\n\\tf := FileStream fileNamed: 'ST80.temp'.\\n\\tf header; timeStamp.\\n\\t'Condensing Changes File...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: self classNames size + self traitNames size\\n\\t\\tduring: [:bar | \\n\\t\\t\\tcount := 0.\\n\\t\\t\\tself\\n\\t\\t\\t\\tallClassesAndTraitsDo: [:classOrTrait | \\n\\t\\t\\t\\t\\tbar value: (count := count + 1).\\n\\t\\t\\t\\t\\tclassOrTrait moveChangesTo: f.\\n\\t\\t\\t\\t\\tclassOrTrait putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\t\\t\\tclassOrTrait classSide moveChangesTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges := SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default deleteFileNamed: oldChanges name , '.old';\\n\\t\\t rename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\t rename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles\\n\\t\\tat: 2\\n\\t\\tput: (StandardFileStream oldFileNamed: oldChanges name)! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'md 3/1/2006 00:02'!\\ncondenseSources\\t\\n\\t\\\"Move all the changes onto a compacted sources file.\\\"\\n\\t\\\"Smalltalk condenseSources\\\"\\n\\n\\t| f dir newVersionString count |\\n\\tUtilities fixUpProblemsWithAllCategory.\\n\\t\\\"The above removes any concrete, spurious '-- all --' categories, which mess up the process.\\\"\\n\\tdir := FileDirectory default.\\n\\tnewVersionString := UIManager default request: 'Please designate the version\\nfor the new source code file...' initialAnswer: SmalltalkImage current sourceFileVersionString.\\n\\tnewVersionString ifNil: [^ self].\\n\\tnewVersionString = SmalltalkImage current sourceFileVersionString ifTrue:\\n\\t\\t[^ self error: 'The new source file must not be the same as the old.'].\\n\\tSmalltalkImage current sourceFileVersionString: newVersionString.\\n\\n\\t\\\"Write all sources with fileIndex 1\\\"\\n\\tf := FileStream newFileNamed: SmalltalkImage current sourcesName.\\n\\tf header; timeStamp.\\n'Condensing Sources File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: self classNames size + self traitNames size\\n\\tduring:\\n\\t\\t[:bar | count := 0.\\n\\t\\tSmalltalk allClassesAndTraitsDo:\\n\\t\\t\\t[:classOrTrait | bar value: (count := count + 1).\\n\\t\\t\\tclassOrTrait fileOutOn: f moveSource: true toFile: 1]].\\n\\tf trailer; close.\\n\\n\\t\\\"Make a new empty changes file\\\"\\n\\tSmalltalkImage current closeSourceFiles.\\n\\tdir rename: SmalltalkImage current changesName\\n\\t\\ttoBe: SmalltalkImage current changesName , '.old'.\\n\\t(FileStream newFileNamed: SmalltalkImage current changesName)\\n\\t\\theader; timeStamp; close.\\n\\tSmalltalkImage current lastQuitLogPosition: 0.\\n\\n\\tself setMacFileInfoOn: SmalltalkImage current changesName.\\n\\tself setMacFileInfoOn: SmalltalkImage current sourcesName.\\n\\tSmalltalkImage current openSourceFiles.\\n\\tself inform: 'Source files have been rewritten!!\\nCheck that all is well,\\nand then save/quit.'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 4/17/2003 20:59'!\\nforgetDoIts\\t\\n\\t\\\"Smalltalk forgetDoIts\\\"\\n\\t \\\"get rid of old DoIt methods\\\"\\n\\n\\tself systemNavigation allBehaviorsDo:\\n\\t\\t[:cl | cl forgetDoIts]\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'ar 9/27/2005 21:45'!\\nmakeExternalRelease\\n\\t\\\"Smalltalk makeExternalRelease\\\"\\n\\t(self confirm: SystemVersion current version , '\\nIs this the correct version designation?\\nIf not, choose no, and fix it.')\\n\\t\\tifFalse: [^ self].\\n\\t\\\"Object classPool at: #DependentsFields\\\"\\n\\tself reclaimDependents.\\n\\tPreferences enable: #mvcProjectsAllowed.\\n\\tPreferences enable: #fastDragWindowForMorphic.\\n\\tSmalltalk at: #Browser ifPresent:[:br| br initialize].\\n\\tUndeclared isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tScriptingSystem deletePrivateGraphics.\\n\\t#(#Helvetica #Palatino #Courier )\\n\\t\\tdo: [:n | TextConstants\\n\\t\\t\\t\\tremoveKey: n\\n\\t\\t\\t\\tifAbsent: []].\\n\\t(Utilities classPool at: #UpdateUrlLists) copy\\n\\t\\tdo: [:pair | (pair first includesSubstring: 'Disney' caseSensitive: false)\\n\\t\\t\\t\\tifTrue: [(Utilities classPool at: #UpdateUrlLists)\\n\\t\\t\\t\\t\\t\\tremove: pair]].\\n\\t(ServerDirectory serverNames copyWithoutAll: #('UCSBCreateArchive' 'UIUCArchive' 'UpdatesExtUIUC' 'UpdatesExtWebPage' ))\\n\\t\\tdo: [:sn | ServerDirectory removeServerNamed: sn].\\n\\tself garbageCollect.\\n\\tself obsoleteClasses isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tSymbol rehash.\\n\\tself halt: 'Ready to condense changes or sources'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'ar 9/27/2005 21:45'!\\nmakeInternalRelease\\n\\t\\\"Smalltalk makeInternalRelease\\\"\\n\\t(self confirm: SystemVersion current version , '\\nIs this the correct version designation?\\nIf not, choose no, and fix it.')\\n\\t\\tifFalse: [^ self].\\n\\t(Object classPool at: #DependentsFields) size > 1\\n\\t\\tifTrue: [self halt].\\n\\tSmalltalk at: #Browser ifPresent:[:br| br initialize].\\n\\tUndeclared isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tself garbageCollect.\\n\\tself obsoleteClasses isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tSymbol rehash.\\n\\tself halt: 'Ready to condense changes'.\\n\\tself condenseChanges! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 9/29/2004 18:15'!\\nreclaimDependents\\n\\t\\\"No-opped due to weak dictionary in use\\\"\\n\\tself garbageCollect! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'al 1/13/2006 00:19'!\\nreconstructChanges\\t\\n\\t\\\"Move all the changes and its histories onto another sources file.\\\"\\n\\t\\\"Smalltalk reconstructChanges\\\"\\n\\n\\t| f oldChanges classCount |\\n\\tf _ FileStream fileNamed: 'ST80.temp'.\\n\\tf header; timeStamp.\\n'Condensing Changes File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: self classNames size + self traitNames size\\n\\tduring:\\n\\t\\t[:bar | classCount _ 0.\\n\\t\\tSmalltalk allClassesAndTraitsDo:\\n\\t\\t\\t[:classOrTrait | bar value: (classCount _ classCount + 1).\\n\\t\\t\\tclassOrTrait moveChangesWithVersionsTo: f.\\n\\t\\t\\tclassOrTrait putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\tclassOrTrait classSide moveChangesWithVersionsTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges _ SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default \\n\\t\\tdeleteFileNamed: oldChanges name , '.old';\\n\\t\\trename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\trename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles at: 2\\n\\t\\t\\tput: (FileStream oldFileNamed: oldChanges name)! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'yo 2/24/2005 18:01'!\\nreformatChangesToUTF8\\n\\t\\\"Smalltalk reformatChangesToUTF8\\\"\\n\\n\\t| f oldChanges classCount |\\n\\tf _ FileStream fileNamed: 'ST80.temp'.\\n\\tf converter: (UTF8TextConverter new).\\n\\tf header; timeStamp.\\n'Condensing Changes File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: Smalltalk classNames size\\n\\tduring:\\n\\t\\t[:bar | classCount _ 0.\\n\\t\\tSmalltalk allClassesDo:\\n\\t\\t\\t[:class | bar value: (classCount _ classCount + 1).\\n\\t\\t\\tclass moveChangesTo: f.\\n\\t\\t\\tclass putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\tclass class moveChangesTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges _ SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default \\n\\t\\tdeleteFileNamed: oldChanges name , '.old';\\n\\t\\trename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\trename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles at: 2\\n\\t\\t\\tput: (FileStream oldFileNamed: oldChanges name).\\n\\tMultiByteFileStream codeConverterClass: UTF8TextConverter.\\n\\t(SourceFiles at: 2) converter: (UTF8TextConverter new).\\n! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 10:22'!\\nremoveAllLineFeeds\\n\\t\\\"Smalltalk removeAllLineFeeds\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tWhen done, offers to display an Inspector containing the message\\n\\tnames grouped by author initials.\\n\\tIn this dictionary, the key 'OK' contains the methods that had literals that contained <LF> characters.\\\"\\n\\t| n authors totalStripped totalOK |\\n\\t'Scanning sources for LineFeeds.\\nThis will take a few minutes...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: [:bar | \\n\\t\\t\\tn _ 0.\\n\\t\\t\\tauthors _ self\\n\\t\\t\\t\\t\\t\\tremoveAllLineFeedsQuietlyCalling: [:cls :sel | (n _ n + 1) \\\\\\\\ 100 = 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [bar value: n]]].\\n\\ttotalStripped _ authors\\n\\t\\t\\t\\tinject: 1\\n\\t\\t\\t\\tinto: [:sum :set | sum + set size].\\n\\ttotalOK _ (authors at: 'OK') size.\\n\\ttotalStripped _ totalStripped - totalOK.\\n\\tTranscript cr; show: totalStripped printString , ' methods stripped of LFs.'.\\n\\tTranscript cr; show: totalOK printString , ' methods still correctly contain LFs.'.\\n\\t(self confirm: 'Do you want to see the affected methods?')\\n\\t\\tifTrue: [authors inspect]! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 08:35'!\\nremoveAllLineFeedsQuietly\\n\\t\\\"Smalltalk removeAllLineFeedsQuietly\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tAnswer a Dictionary keyed by author name containing sets of affected method names,\\n\\tas well as (at the key 'OK') a list of methods that still contain LF characters inside literal strings or characters.\\\"\\n\\t^self removeAllLineFeedsQuietlyCalling: [ :cls :sel | ].! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 09:22'!\\nremoveAllLineFeedsQuietlyCalling: aBlock\\n\\t\\\"Smalltalk removeAllLineFeedsQuietly\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tAnswer a Dictionary keyed by author name containing sets of affected method names,\\n\\tas well as (at the key 'OK') a list of methods that still contain LF characters inside literal strings or characters.\\n\\tEvaluate aBlock for each method so that status can be updated.\\\"\\n\\t| oldCodeString newCodeString oldStamp oldCategory authors nameString |\\n\\tself forgetDoIts.\\n\\tauthors _ Dictionary new.\\n\\tauthors at: 'OK' put: Set new.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:cls | cls selectors\\n\\t\\t\\t\\tdo: [:selector | \\n\\t\\t\\t\\t\\taBlock value: cls value: selector.\\n\\t\\t\\t\\t\\toldCodeString _ cls sourceCodeAt: selector.\\n\\t\\t\\t\\t\\t(oldCodeString includes: Character lf)\\n\\t\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString _ oldCodeString withSqueakLineEndings.\\n\\t\\t\\t\\t\\t\\t\\tnameString _ cls name , '>>' , selector.\\n\\t\\t\\t\\t\\t\\t\\t((cls compiledMethodAt: selector) hasLiteralSuchThat: [ :lit | lit asString includes: Character lf ])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [(authors at: 'OK')\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tadd: nameString]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [oldStamp _ (Utilities\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttimeStampForMethod: (cls compiledMethodAt: selector))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopy replaceAll: Character cr\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twith: Character space.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(authors\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tat: (oldStamp copyFrom: 1 to: (oldStamp findFirst: [ :c | c isAlphaNumeric not ]))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [Set new])\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tadd: nameString.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\toldCategory _ cls whichCategoryIncludesSelector: selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompile: newCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclassified: oldCategory\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twithStamp: oldStamp\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil ]]]].\\n\\t^ authors! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 9/29/2004 18:15'!\\nremoveEmptyMessageCategories\\n\\t\\\"Smalltalk removeEmptyMessageCategories\\\"\\n\\tself garbageCollect.\\n\\t(ClassOrganizer allInstances copyWith: SystemOrganization)\\n\\t\\tdo: [:org | org removeEmptyCategories]! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 2/23/2005 18:00'!\\ntestFormatter\\n\\t\\\"Smalltalk testFormatter\\\"\\n\\n\\t\\\"Reformats the source for every method in the system, and\\n\\tthen compiles that source and verifies that it generates\\n\\tidentical code. The formatting used will be either classic\\n\\tmonochrome or fancy polychrome, depending on the setting\\n\\tof the preference #colorWhenPrettyPrinting.\\\"\\n\\n\\t| newCodeString methodNode oldMethod newMethod badOnes n |\\n\\tbadOnes := OrderedCollection new.\\n\\tself forgetDoIts.\\n\\t'Formatting all classes...' \\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: \\n\\t\\t\\t[:bar | \\n\\t\\t\\tn := 0.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: \\n\\t\\t\\t\\t\\t[:cls | \\n\\t\\t\\t\\t\\t\\\"Transcript cr; show: cls name.\\\"\\n\\n\\t\\t\\t\\t\\tcls selectors do: \\n\\t\\t\\t\\t\\t\\t\\t[:selector | \\n\\t\\t\\t\\t\\t\\t\\t(n := n + 1) \\\\\\\\ 100 = 0 ifTrue: [bar value: n].\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString := cls prettyPrinterClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: (cls sourceCodeAt: selector)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecorated: Preferences colorWhenPrettyPrinting.\\n\\t\\t\\t\\t\\t\\t\\tmethodNode := cls compilerClass new \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompile: newCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifFail: [].\\n\\t\\t\\t\\t\\t\\t\\tnewMethod := methodNode generate: #(0 0 0 0).\\n\\t\\t\\t\\t\\t\\t\\toldMethod := cls compiledMethodAt: selector.\\n\\t\\t\\t\\t\\t\\t\\toldMethod = newMethod \\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[Transcript\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcr;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshow: '***' , cls name , ' ' , selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbadOnes add: cls name , ' ' , selector]]]].\\n\\tself systemNavigation browseMessageList: badOnes asSortedCollection\\n\\t\\tname: 'Formatter Discrepancies'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 2/23/2005 18:00'!\\ntestFormatter2\\n\\t\\\"Smalltalk testFormatter2\\\"\\n\\n\\t\\\"Reformats the source for every method in the system, and\\n\\tthen verifies that the order of source tokens is unchanged.\\n\\tThe formatting used will be either classic monochrome or\\n\\tfancy polychrome, depending on the setting of the preference\\n\\t#colorWhenPrettyPrinting. \\\"\\n\\n\\t| newCodeString badOnes n oldCodeString oldTokens newTokens |\\n\\tbadOnes := OrderedCollection new.\\n\\tself forgetDoIts.\\n\\t'Formatting all classes...' \\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: \\n\\t\\t\\t[:bar | \\n\\t\\t\\tn := 0.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: \\n\\t\\t\\t\\t\\t[:cls | \\n\\t\\t\\t\\t\\t\\\"Transcript cr; show: cls name.\\\"\\n\\n\\t\\t\\t\\t\\tcls selectors do: \\n\\t\\t\\t\\t\\t\\t\\t[:selector | \\n\\t\\t\\t\\t\\t\\t\\t(n := n + 1) \\\\\\\\ 100 = 0 ifTrue: [bar value: n].\\n\\t\\t\\t\\t\\t\\t\\toldCodeString := (cls sourceCodeAt: selector) asString.\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString := cls prettyPrinterClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: oldCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecorated: Preferences colorWhenPrettyPrinting.\\n\\t\\t\\t\\t\\t\\t\\toldTokens := oldCodeString findTokens: Character separators.\\n\\t\\t\\t\\t\\t\\t\\tnewTokens := newCodeString findTokens: Character separators.\\n\\t\\t\\t\\t\\t\\t\\toldTokens = newTokens \\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[Transcript\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcr;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshow: '***' , cls name , ' ' , selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbadOnes add: cls name , ' ' , selector]]]].\\n\\tself systemNavigation browseMessageList: badOnes asSortedCollection\\n\\t\\tname: 'Formatter Discrepancies'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 4/17/2003 21:01'!\\nverifyChanges\\t\\t\\\"Smalltalk verifyChanges\\\"\\n\\t\\\"Recompile all methods in the changes file.\\\"\\n\\tself systemNavigation allBehaviorsDo: [:class | class recompileChanges].\\n! !\\n\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimImageName\\n\\t\\\"Answer the full path name for the current image.\\\"\\n\\t\\\"Smalltalk imageName\\\"\\n\\n\\t<primitive: 121>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimImageName: newName\\n\\t\\\"Set the the full path name for the current image. All further snapshots will use this.\\\"\\n\\n\\t<primitive: 121>\\n\\t^ self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimVmPath\\n\\t\\\"Answer the path for the directory containing the Smalltalk virtual machine. Return the empty string if this primitive is not implemented.\\\"\\n\\t\\\"Smalltalk vmPath\\\"\\n\\n\\t<primitive: 142>\\n\\t^ ''! !\\n\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nbytesLeft\\n\\t\\\"Answer the number of bytes of space available. Does a full garbage collection.\\\"\\n\\n\\t^ self garbageCollect\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 18:00'!\\nbytesLeftString\\n\\t\\\"Return a string describing the amount of memory available\\\"\\n\\t| availInternal availPhysical availTotal |\\n\\tself garbageCollect.\\n\\tavailInternal _ self primBytesLeft.\\n\\tavailPhysical _ self bytesLeft: false.\\n\\tavailTotal _ self bytesLeft: true.\\n\\t(availTotal > (availInternal + 10000)) \\\"compensate for mini allocations inbetween\\\"\\n\\t\\tifFalse:[^availInternal asStringWithCommas, ' bytes available'].\\n\\t^String streamContents:[:s|\\n\\t\\ts nextPutAll: availInternal asStringWithCommas, \\t' bytes (internal) '; cr.\\n\\t\\ts nextPutAll: availPhysical asStringWithCommas,\\t' bytes (physical) '; cr.\\n\\t\\ts nextPutAll: availTotal asStringWithCommas, \\t' bytes (total) '].! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 17:55'!\\nbytesLeft: aBool\\n\\t\\\"Return the amount of available space. If aBool is true, include possibly available swap space. If aBool is false, include possibly available physical memory. For a report on the largest free block currently availabe within Squeak memory but not counting extra memory use #primBytesLeft.\\\"\\n\\t<primitive: 112>\\n\\t^self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ncreateStackOverflow\\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; createStackOverflow\\\"\\n\\n\\tself createStackOverflow. \\\"infinite recursion\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 13:23'!\\nforceTenure\\n\\t\\\"Primitive. Tell the GC logic to force a tenure on the next increment GC.\\\"\\n\\t<primitive: 'primitiveForceTenure'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:36'!\\ngarbageCollect\\n\\t\\\"Primitive. Reclaims all garbage and answers the number of bytes of available space.\\\"\\n\\tObject flushDependents.\\n\\tObject flushEvents.\\n\\t^self primitiveGarbageCollect! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ngarbageCollectMost\\n\\t\\\"Primitive. Reclaims recently created garbage (which is usually most of it) fairly quickly and answers the number of bytes of available space.\\\"\\n\\n\\t<primitive: 131>\\n\\t^ self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ninstallLowSpaceWatcher\\n\\t\\\"Start a process to watch for low-space conditions.\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher\\\"\\n\\n\\tself primSignalAtBytesLeft: 0. \\\"disable low-space interrupts\\\"\\n\\tLowSpaceProcess == nil ifFalse: [LowSpaceProcess terminate].\\n\\tLowSpaceProcess _ [self lowSpaceWatcher] newProcess.\\n\\tLowSpaceProcess priority: Processor lowIOPriority.\\n\\tLowSpaceProcess resume.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:46'!\\nisRoot: oop\\n\\t\\\"Primitive. Answer whether the object is currently a root for youngSpace.\\\"\\n\\t<primitive: 'primitiveIsRoot'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:47'!\\nisYoung: oop\\n\\t\\\"Primitive. Answer whether the object currently resides in youngSpace.\\\"\\n\\t<primitive: 'primitiveIsYoung'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:49'!\\nlowSpaceThreshold \\n\\t\\\"Return the low space threshold. When the amount of free memory (after garbage collection) falls below this limit, the system is in serious danger of completely exhausting memory and crashing. This limit should be made high enough to allow the user open a debugger to diagnose a problem or to save the image.\\\"\\n\\n\\tthisContext isPseudoContext\\n\\t\\tifTrue: [^ 400000 \\\"Enough for JIT compiler\\\"]\\n\\t\\tifFalse: [^ 200000 \\\"Enough for interpreter\\\"]! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'dtl 10/3/2005 06:12'!\\nlowSpaceWatcher\\n\\t\\\"Wait until the low space semaphore is signalled, then take appropriate actions.\\\"\\n\\n\\t| free preemptedProcess |\\n\\tself garbageCollectMost <= self lowSpaceThreshold\\n\\t\\tifTrue: [self garbageCollect <= self lowSpaceThreshold\\n\\t\\t\\t\\tifTrue: [\\\"free space must be above threshold before\\n\\t\\t\\t\\t\\tstarting low space watcher\\\"\\n\\t\\t\\t\\t\\t^ Beeper beep]].\\n\\n\\tSmalltalk specialObjectsArray at: 23 put: nil. \\\"process causing low space will be saved here\\\"\\n\\tLowSpaceSemaphore _ Semaphore new.\\n\\tself primLowSpaceSemaphore: LowSpaceSemaphore.\\n\\tself primSignalAtBytesLeft: self lowSpaceThreshold. \\\"enable low space interrupts\\\"\\n\\n\\tLowSpaceSemaphore wait. \\\"wait for a low space condition...\\\"\\n\\n\\tself primSignalAtBytesLeft: 0. \\\"disable low space interrupts\\\"\\n\\tself primLowSpaceSemaphore: nil.\\n\\tLowSpaceProcess _ nil.\\n\\n\\t\\\"The process that was active at the time of the low space interrupt.\\\"\\n\\tpreemptedProcess _ Smalltalk specialObjectsArray at: 23.\\n\\tSmalltalk specialObjectsArray at: 23 put: nil.\\n\\n\\t\\\"Note: user now unprotected until the low space watcher is re-installed\\\"\\n\\n\\tself memoryHogs isEmpty\\n\\t\\tifFalse: [free := self bytesLeft.\\n\\t\\t\\tself memoryHogs\\n\\t\\t\\t\\tdo: [ :hog | hog freeSomeSpace ].\\n\\t\\t\\tself bytesLeft > free\\n\\t\\t\\t\\tifTrue: [ ^ self installLowSpaceWatcher ]].\\n\\tself isMorphic\\n\\t\\tifTrue: [CurrentProjectRefactoring\\n\\t\\t\\t\\tcurrentInterruptName: 'Space is low'\\n\\t\\t\\t\\tpreemptedProcess: preemptedProcess]\\n\\t\\tifFalse: [ScheduledControllers\\n\\t\\t\\t\\tinterruptName: 'Space is low'\\n\\t\\t\\t\\tpreemptedProcess: preemptedProcess]\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'nk 10/28/2000 20:37'!\\nlowSpaceWatcherProcess\\n\\t^LowSpaceProcess! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'sma 4/22/2000 19:03'!\\nmemoryHogs\\n\\t\\\"Answer the list of objects to notify with #freeSomeSpace if memory gets full.\\\"\\n\\n\\t^ MemoryHogs ifNil: [MemoryHogs _ OrderedCollection new]! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nokayToProceedEvenIfSpaceIsLow\\n\\t\\\"Return true if either there is enough memory to do so safely or if the user gives permission after being given fair warning.\\\"\\n\\n\\tself garbageCollectMost > self lowSpaceThreshold ifTrue: [^ true]. \\\"quick\\\"\\n\\tself garbageCollect > self lowSpaceThreshold ifTrue: [^ true]. \\\"work harder\\\"\\n\\n\\t^ self confirm:\\n'WARNING: There is not enough space to start the low space watcher.\\nIf you proceed, you will not be warned again, and the system may\\nrun out of memory and crash. If you do proceed, you can start the\\nlow space notifier when more space becomes available simply by\\nopening and then closing a debugger (e.g., by hitting Cmd-period.)\\nDo you want to proceed?'\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimBytesLeft\\n\\t\\\"Primitive. Answer the number of bytes available for new object data.\\n\\tNot accurate unless preceded by\\n\\t\\tSmalltalk garbageCollectMost (for reasonable accuracy), or\\n\\t\\tSmalltalk garbageCollect (for real accuracy).\\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 112>\\n\\t^ 0! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:16'!\\nprimitiveGarbageCollect\\n\\t\\\"Primitive. Reclaims all garbage and answers the number of bytes of available space.\\\"\\n\\n\\t<primitive: 130>\\n\\t^ self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimLowSpaceSemaphore: aSemaphore\\n\\t\\\"Primitive. Register the given Semaphore to be signalled when the\\n\\tnumber of free bytes drops below some threshold. Disable low-space\\n\\tinterrupts if the argument is nil.\\\"\\n\\n\\t<primitive: 124>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimSignalAtBytesLeft: numBytes\\n\\t\\\"Tell the interpreter the low-space threshold in bytes. When the free\\n\\tspace falls below this threshold, the interpreter will signal the low-space\\n\\tsemaphore, if one has been registered. Disable low-space interrupts if the\\n\\targument is zero. Fail if numBytes is not an Integer.\\\"\\n\\n\\t<primitive: 125>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:48'!\\nrootTable\\n\\t\\\"Primitive. Answer a snapshot of the VMs root table. \\n\\tKeep in mind that the primitive may itself cause GC.\\\"\\n\\t<primitive: 'primitiveRootTable'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:49'!\\nrootTableAt: index\\n\\t\\\"Primitive. Answer the nth element of the VMs root table\\\"\\n\\t<primitive: 'primitiveRootTableAt'>\\n\\t^nil! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 12:27'!\\nsetGCBiasToGrowGCLimit: aNumber\\n\\t\\\"Primitive. Indicate that the bias to grow logic should do a GC after aNumber Bytes\\\"\\n\\t<primitive: 'primitiveSetGCBiasToGrowGCLimit'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\tSmalltalk setGCBiasToGrowGCLimit: 16*1024*1024.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 13:12'!\\nsetGCBiasToGrow: aNumber\\n\\t\\\"Primitive. Indicate that the GC logic should be bias to grow\\\"\\n\\t<primitive: 'primitiveSetGCBiasToGrow'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\tSmalltalk setGCBiasToGrowGCLimit: 16*1024*1024.\\n\\tSmalltalk setGCBiasToGrow: 1.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:54'!\\nsetGCSemaphore: semaIndex\\n\\t\\\"Primitive. Indicate the GC semaphore index to be signaled on GC occurance.\\\"\\n\\t<primitive: 'primitiveSetGCSemaphore'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\n\\t| index sema process |\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\tSmalltalk setGCSemaphore: index.\\n\\tprocess := [\\n\\t\\t[[true] whileTrue:[\\n\\t\\t\\tsema wait.\\n\\t\\t\\tSmalltalk beep.\\n\\t\\t]] ensure:[\\n\\t\\t\\tSmalltalk setGCSemaphore: 0.\\n\\t\\t\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t].\\n\\t] fork.\\n\\tprocess inspect.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nsignalLowSpace\\n\\t\\\"Signal the low-space semaphore to alert the user that space is running low.\\\"\\n\\n\\tLowSpaceSemaphore signal.! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'apb 10/3/2000 16:40'!\\nuseUpMemory\\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemory\\\"\\n\\n\\t| lst |\\n\\tlst _ nil.\\n\\t[true] whileTrue: [\\n\\t\\tlst _ Link nextLink: lst.\\n\\t].! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 21:15'!\\nuseUpMemoryWithArrays \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithArrays\\\"\\n\\n\\t| b | \\\"First use up most of memory.\\\"\\n\\tb _ String new: self bytesLeft - self lowSpaceThreshold - 100000.\\n\\tb _ b. \\\"Avoid unused value warning\\\"\\n\\t(1 to: 10000) collect: [:i | Array new: 10000]! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:49'!\\nuseUpMemoryWithContexts \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithContexts\\\"\\n\\n\\tself useUpMemoryWithContexts! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:50'!\\nuseUpMemoryWithTinyObjects \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithTinyObjects\\\"\\n\\n\\t| b | \\\"First use up most of memory.\\\"\\n\\tb _ String new: self bytesLeft - self lowSpaceThreshold - 100000.\\n\\tb _ b. \\\"Avoid unused value warning\\\"\\n\\t(1 to: 10000) collect: [:i | BitBlt new]! !\\n\\n\\n!SystemDictionary methodsFor: 'miscellaneous'!\\nexitToDebugger\\n\\t\\\"Primitive. Enter the machine language debugger, if one exists. Essential.\\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 114>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'dao 10/1/2004 13:33'!\\nhandleUserInterrupt\\n\\tPreferences cmdDotEnabled ifTrue:\\n\\t\\t[Smalltalk isMorphic\\n\\t\\t\\tifTrue: [[Project interruptName: 'User Interrupt'] fork]\\n\\t\\t\\tifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] fork]]! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'sd 9/29/2004 18:17'!\\nhasMorphic\\n\\t\\\"Answer whether the Morphic classes are available in the\\n\\tsystem (they may have been stripped, such as by a call to\\n\\tSmalltalk removeMorphic\\\"\\n\\t^ (self\\n\\t\\tat: #Morph\\n\\t\\tifAbsent: [])\\n\\t\\tisKindOf: Class! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'tk 10/16/2001 19:24'!\\nlogError: errMsg inContext: aContext to: aFilename\\n\\t\\\"Log the error message and a stack trace to the given file.\\\"\\n\\n\\t| ff |\\n\\tFileDirectory default deleteFileNamed: aFilename ifAbsent: [].\\n\\t(ff _ FileStream fileNamed: aFilename) ifNil: [^ self \\\"avoid recursive errors\\\"].\\n\\n \\tff nextPutAll: errMsg; cr.\\n\\taContext errorReportOn: ff.\\n\\tff close.! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'yo 7/2/2004 13:32'!\\nm17nVersion\\n\\n\\t^ 'M17n 5.0' copy\\n! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'yo 7/2/2004 13:32'!\\nnihongoVersion\\n\\n\\t^ 'Nihongo7.0' copy\\n! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'MPH 10/24/2000 14:27'!\\nsetMacFileInfoOn: aString\\n\\t\\\"On Mac, set the file type and creator (noop on other platforms)\\\"\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: aString\\n\\t\\ttype: 'STch'\\n\\t\\tcreator: 'FAST'.! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'nb 6/17/2003 12:25'!\\nverifyMorphicAvailability\\n\\t\\\"If Morphic is available, return true; if not, put up an informer and return false\\\"\\n\\tself hasMorphic ifFalse:\\n\\t\\t[Beeper beep.\\n\\t\\tself inform: 'Sorry, Morphic must\\nbe present to use this feature'.\\n\\t\\t^ false].\\n\\t^ true! !\\n\\n\\n!SystemDictionary methodsFor: 'objects from disk' stamp: 'tk 9/28/2000 15:50'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to Smalltalk instead.\\\"\\n\\n\\tdp _ DiskProxy global: #Smalltalk selector: #yourself\\n\\t\\t\\targs: #().\\n\\trefStrm replace: self with: dp.\\n\\t^ dp! !\\n\\n!SystemDictionary methodsFor: 'objects from disk' stamp: 'tk 3/7/2000 18:40'!\\nstoreDataOn: aDataStream\\n\\t\\\"I don't get stored. Use a DiskProxy\\\"\\n\\n\\tself error: 'use a DiskProxy to store me'! !\\n\\n\\n!SystemDictionary methodsFor: 'printing' stamp: 'sma 6/1/2000 09:53'!\\nprintElementsOn: aStream\\n\\taStream nextPutAll:'(lots of globals)'! !\\n\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:15'!\\nallClasses \\n\\t\\\"Return all the class defines in the Smalltalk SystemDictionary\\\"\\n\\t\\\"Smalltalk allClasses\\\"\\n\\n\\t^ self classNames collect: [:name | self at: name]! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:18'!\\nallClassesDo: aBlock\\n\\t\\\"Evaluate the argument, aBlock, for each class in the system.\\\"\\n\\n\\t(self classNames collect: [:name | self at: name]) do: aBlock! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'al 2/23/2006 21:39'!\\nallTraits\\n\\t\\\"Return all traits defined in the Smalltalk SystemDictionary\\\"\\n\\n\\t^ self traitNames collect: [:each | self at: each]! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 9/29/2004 18:17'!\\npoolUsers\\n\\t\\\"Answer a dictionary of pool name -> classes that refer to it.\\n\\tAlso includes any globally know dictionaries (such as\\n\\tSmalltalk, Undeclared etc) which although not strictly\\n\\taccurate is potentially useful information\\\"\\n\\t\\\"Smalltalk poolUsers\\\"\\n\\t| poolUsers pool refs |\\n\\tpoolUsers := Dictionary new.\\n\\tself keys\\n\\t\\tdo: [:k | \\\"yes, using isKindOf: is tacky but for reflective code like\\n\\t\\t\\tthis it is very useful. If you really object you can:-\\n\\t\\t\\ta) go boil your head.\\n\\t\\t\\tb) provide a better answer.\\n\\t\\t\\tyour choice.\\\"\\n\\t\\t\\t(((pool := self at: k) isKindOf: Dictionary)\\n\\t\\t\\t\\t\\tor: [pool isKindOf: SharedPool class])\\n\\t\\t\\t\\tifTrue: [refs := self systemNavigation allClasses\\n\\t\\t\\t\\t\\t\\t\\t\\tselect: [:c | c sharedPools identityIncludes: pool]\\n\\t\\t\\t\\t\\t\\t\\t\\tthenCollect: [:c | c name].\\n\\t\\t\\t\\t\\trefs\\n\\t\\t\\t\\t\\t\\tadd: (self systemNavigation\\n\\t\\t\\t\\t\\t\\t\\t\\tallCallsOn: (self associationAt: k)).\\n\\t\\t\\t\\t\\tpoolUsers at: k put: refs]].\\n\\t^ poolUsers! !\\n\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:18'!\\nabandonSources\\n\\t\\\"Smalltalk abandonSources\\\"\\n\\t\\\"Replaces every method by a copy with the 4-byte source\\n\\tpointer \\n\\treplaced by a string of all arg and temp names, followed by its\\n\\tlength. These names can then be used to inform the\\n\\tdecompiler. See stats below\\\"\\n\\t\\\"wod 11/3/1998: zap the organization before rather than after\\n\\tcondensing changes.\\\"\\n\\t| oldCodeString argsAndTemps oldMethods newMethods m bTotal bCount |\\n\\t(self confirm: 'This method will preserve most temp names\\n(up to about 400 characters) while allowing\\nthe sources file to be discarded.\\n-- CAUTION --\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nabandoning source code files, choose Yes.\\nIf you have any doubts, you may choose No\\nto back out with no harm done.')\\n\\t\\t\\t== true\\n\\t\\tifFalse: [^ self inform: 'Okay - no harm done'].\\n\\tself forgetDoIts.\\n\\toldMethods := OrderedCollection new: CompiledMethod instanceCount.\\n\\tnewMethods := OrderedCollection new: CompiledMethod instanceCount.\\n\\tbTotal := 0.\\n\\tbCount := 0.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:b | bTotal := bTotal + 1].\\n\\t'Saving temp names for better decompilation...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: bTotal\\n\\t\\tduring: [:bar | self systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:cl | \\n\\t\\t\\t\\t\\t\\\"for test: (Array with: Arc with: Arc class) do:\\\"\\n\\t\\t\\t\\t\\tbar value: (bCount := bCount + 1).\\n\\t\\t\\t\\t\\tcl selectors\\n\\t\\t\\t\\t\\t\\tdo: [:selector | \\n\\t\\t\\t\\t\\t\\t\\tm := cl compiledMethodAt: selector.\\n\\t\\t\\t\\t\\t\\t\\tm fileIndex > 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [oldCodeString := cl sourceCodeAt: selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\targsAndTemps := (cl compilerClass new\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparse: oldCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cl\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil) tempNames.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\toldMethods addLast: m.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tnewMethods\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddLast: (m copyWithTempNames: argsAndTemps)]]]].\\n\\toldMethods asArray elementsExchangeIdentityWith: newMethods asArray.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:b | b zapOrganization].\\n\\tself condenseChanges.\\n\\tPreferences disable: #warnIfNoSourcesFile! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:18'!\\nabandonTempNames\\n\\t\\\"Replaces every method by a copy with no source pointer or\\n\\tencoded temp names.\\\"\\n\\t\\\"Smalltalk abandonTempNames\\\"\\n\\t| continue oldMethods newMethods n m |\\n\\tcontinue := self confirm: '-- CAUTION --\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nabandoning all source code, hit Yes.\\nIf you have any doubts, hit No,\\nto back out with no harm done.'.\\n\\tcontinue\\n\\t\\tifFalse: [^ self inform: 'Okay - no harm done'].\\n\\tself forgetDoIts; garbageCollect.\\n\\toldMethods := OrderedCollection new.\\n\\tnewMethods := OrderedCollection new.\\n\\tn := 0.\\n\\t'Removing temp names to save space...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: [:bar | self systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:cl | cl selectors\\n\\t\\t\\t\\t\\t\\tdo: [:sel | \\n\\t\\t\\t\\t\\t\\t\\tbar value: (n := n + 1).\\n\\t\\t\\t\\t\\t\\t\\tm := cl compiledMethodAt: sel.\\n\\t\\t\\t\\t\\t\\t\\toldMethods addLast: m.\\n\\t\\t\\t\\t\\t\\t\\tnewMethods\\n\\t\\t\\t\\t\\t\\t\\t\\taddLast: (m copyWithTrailerBytes: #(0 ))]]].\\n\\toldMethods asArray elementsExchangeIdentityWith: newMethods asArray.\\n\\tSmalltalkImage current closeSourceFiles.\\n\\tself flag: #shouldUseAEnsureBlockToBeSureThatTheFileIsClosed.\\n\\t\\\"sd: 17 April 2003\\\"\\n\\tPreferences disable: #warnIfNoChangesFile.\\n\\tPreferences disable: #warnIfNoSourcesFile! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'di 3/3/2001 08:31'!\\ncleanUpUndoCommands\\n\\t\\\"Smalltalk cleanUpUndoCommands\\\" \\\"<== print this to get classes involved\\\"\\n\\n\\t| classes i p |\\n\\tclasses _ Bag new.\\n\\t'Ferreting out obsolete undo commands'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: Morph withAllSubclasses size\\n\\t\\tduring:\\n\\t[:bar | i _ 0.\\n\\tMorph withAllSubclassesDo:\\n\\t\\t[:c | bar value: (i _ i+1).\\n\\t\\tc allInstancesDo:\\n\\t\\t\\t[:m | (p _ m otherProperties) ifNotNil:\\n\\t\\t\\t\\t[p keys do:\\n\\t\\t\\t\\t\\t[:k | (p at: k) class == Command ifTrue:\\n\\t\\t\\t\\t\\t\\t[classes add: c name.\\n\\t\\t\\t\\t\\t\\tm removeProperty: k]]]]]].\\n\\t^ classes! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:40'!\\ncomputeImageSegmentation\\n\\t\\\"Smalltalk computeImageSegmentation\\\"\\n\\t\\\"Here's how the segmentation works:\\n\\tFor each partition, we collect the classes involved, and also all\\n\\tmessages no longer used in the absence of this partition. We\\n\\tstart by computing a 'Miscellaneous' segment of all the\\n\\tunused classes in the system as is.\\\"\\n\\t| partitions unusedCandM newClasses expandedCandM |\\n\\tpartitions := Dictionary new.\\n\\tunusedCandM := self unusedClassesAndMethodsWithout: {{}. {}}.\\n\\tpartitions at: 'Miscellaneous' put: unusedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'VMConstruction-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'VMConstruction' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'ST80-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'ST80' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Morphic-Games')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Games' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Morphic-Remote')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Nebraska' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | ((SystemOrganization categoriesMatching: 'Network-*')\\n\\t\\t\\t\\t\\t\\tcopyWithoutAll: #('Network-Kernel' 'Network-Url' 'Network-Protocols' 'Network-ObjectSocket' ))\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := Smalltalk unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Network' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon3D-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Balloon3D' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'FFI-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'FFI' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Genie-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Genie' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Speech-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Speech' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | #('Morphic-Components' )\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses copyWithoutAll: #(#ComponentLikeModel ).\\n\\texpandedCandM := Smalltalk unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Components' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | #('Sound-Scores' 'Sound-Interface' )\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses , #(#WaveletCodec #Sonogram #FWT #AIFFFileReader ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Sound' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | ((SystemOrganization categoriesMatching: 'Tools-*')\\n\\t\\t\\t\\t\\t\\tcopyWithout: 'Tools-Menus')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses copyWithoutAll: #(#Debugger #Inspector #ContextVariablesInspector #SyntaxError #ChangeSet #ChangeRecord #ClassChangeRecord #ChangeList #VersionsBrowser ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Tools' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon-MMFlash*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses , #(#ADPCMCodec ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Flash' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon-TrueType*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'TrueType' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Graphics-Files')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'GraphicFiles' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\t#(#AliceConstants 'Balloon3D' #B3DEngineConstants 'Balloon3D' #WonderlandConstants 'Balloon3D' #FFIConstants 'FFI' #KlattResonatorIndices 'Speech' )\\n\\t\\tpairsDo: [:poolName :part | (partitions at: part) first add: poolName].\\n\\tpartitions\\n\\t\\tkeysDo: [:k | k = 'Miscellaneous'\\n\\t\\t\\t\\tifFalse: [(partitions at: 'Miscellaneous') first removeAllFoundIn: (partitions at: k) first]].\\n\\t^ partitions! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sma 6/18/2000 12:32'!\\ndiscardDiscards\\n\\t\\\"Discard all discard* methods - including this one.\\\"\\n\\n\\t(self class selectors select: [:each | each beginsWith: 'discard']) \\n\\t\\tdo: [:each | self class removeSelector: each].\\n\\t#(lastRemoval majorShrink zapMVCprojects)\\n\\t\\tdo: [:each | self class removeSelector: each]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:20'!\\ndiscardFFI\\n\\t\\\"Discard the complete foreign function interface.\\n\\tNOTE: Recreates specialObjectsArray to prevent obsolete\\n\\treferences. Has to specially remove external structure\\n\\thierarchy before ExternalType\\\"\\n\\tself\\n\\t\\tat: #ExternalStructure\\n\\t\\tifPresent: [:cls | (ChangeSet superclassOrder: cls withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\tSystemOrganization removeCategoriesMatching: 'FFI-*'.\\n\\tself recreateSpecialObjectsArray.\\n\\t\\\"Remove obsolete refs\\\"\\n\\tByteArray removeSelector: #asExternalPointer.\\n\\tByteArray removeSelector: #pointerAt:! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/5/2000 01:32'!\\ndiscardFlash\\n\\t\\\"Discard Flash support.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-MMFlash*'\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'RAA 12/17/2000 16:50'!\\ndiscardMIDI\\n\\n\\t\\\"this seems to have gone away\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:21'!\\ndiscardMorphic\\n\\t\\\"Discard Morphic.\\n\\tUpdated for 2.8 TPR\\\"\\n\\t\\\"Smalltalk discardMorphic\\\"\\n\\t\\\"Check that we are in an MVC Project and that there are no\\n\\tMorphic Projects\\n\\tor WorldMorphViews.\\\"\\n\\t| subs |\\n\\tFlaps clobberFlapTabList.\\n\\tself discardFlash.\\n\\tself discardTrueType.\\n\\tsubs := OrderedCollection new.\\n\\tMorph\\n\\t\\tallSubclassesWithLevelDo: [:c :i | subs addFirst: c]\\n\\t\\tstartingLevel: 0.\\n\\tsubs\\n\\t\\tdo: [:c | c removeFromSystem].\\n\\tself removeClassNamed: #CornerRounder.\\n\\tself\\n\\t\\tremoveKey: #BalloonEngineConstants\\n\\t\\tifAbsent: [].\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-*'.\\n\\tSystemOrganization removeCategoriesMatching: 'Morphic-*'.\\n\\tSystemOrganization removeSystemCategory: 'Graphics-Transformations'.\\n\\tSystemOrganization removeSystemCategory: 'ST80-Morphic'.\\n\\tScriptingSystem := nil! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:21'!\\ndiscardMVC\\n\\t\\\"After suitable checks, strip out much of MVC from the system\\\"\\n\\t\\\"Smalltalk discardMVC\\\"\\n\\t| keepers |\\n\\tself flag: #bob.\\n\\t\\\"zapping projects\\\"\\n\\tself isMorphic\\n\\t\\tifFalse: [self inform: 'You must be in a Morphic project to discard MVC.'.\\n\\t\\t\\t^ self].\\n\\t\\\"Check that there are no MVC Projects\\\"\\n\\t(Project allProjects\\n\\t\\t\\tallSatisfy: [:proj | proj isMorphic])\\n\\t\\tifFalse: [(self confirm: 'Would you like a chance to remove your\\nMVC projects in an orderly manner?')\\n\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t(self confirm: 'If you wish, I can remove all MVC projects,\\nmake this project be the top project, and place\\nall orphaned sub-projects of MVC parents here.\\nWould you like be to do this\\nand proceed to discard all MVC classes?')\\n\\t\\t\\t\\tifTrue: [self zapMVCprojects]\\n\\t\\t\\t\\tifFalse: [^ self]].\\n\\tself reclaimDependents.\\n\\t\\\"Remove old Paragraph classes and View classes.\\\"\\n\\tself\\n\\t\\tat: #Paragraph\\n\\t\\tifPresent: [:paraClass | (ChangeSet superclassOrder: paraClass withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\tself\\n\\t\\tat: #View\\n\\t\\tifPresent: [:viewClass | (ChangeSet superclassOrder: viewClass withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\t\\\"Get rid of ParagraphEditor's ScrollController dependence\\\"\\n\\t#(#markerDelta #viewDelta #scrollAmount #scrollBar #computeMarkerRegion )\\n\\t\\tdo: [:sel | ParagraphEditor removeSelector: sel].\\n\\tParagraphEditor compile: 'updateMarker'.\\n\\t\\\"Reshape to MouseMenuController\\\"\\n\\tCompiler\\n\\t\\tevaluate: (ParagraphEditor definition copyReplaceAll: 'ScrollController' with: 'MouseMenuController').\\n\\t\\\"Get rid of all Controller classes not needed by\\n\\tParagraphEditor and ScreenController\\\"\\n\\tkeepers := TextMorphEditor withAllSuperclasses copyWith: ScreenController.\\n\\t(ChangeSet superclassOrder: Controller withAllSubclasses asArray)\\n\\t\\treverseDo: [:c | (keepers includes: c)\\n\\t\\t\\t\\tifFalse: [c removeFromSystem]].\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Paths'.\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Symbols'.\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Pluggable Views'.\\n\\tself removeClassNamed: 'FormButtonCache'.\\n\\tself removeClassNamed: 'WindowingTransformation'.\\n\\tself removeClassNamed: 'ControlManager'.\\n\\tself removeClassNamed: 'DisplayTextView'.\\n\\tScheduledControllers := nil.\\n\\tUndeclared removeUnreferencedKeys.\\n\\tSystemOrganization removeEmptyCategories.\\n\\tSymbol rehash! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'cwp 11/8/2002 13:38'!\\ndiscardNetworking\\n\\t\\\"Discard the support for TCP/IP networking.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Network-*'.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'md 7/29/2005 16:00'!\\ndiscardOddsAndEnds\\n\\t\\\"This method throws out lots of classes that are not frequently\\n\\tused.\\\"\\n\\t\\\"Smalltalk discardOddsAndEnds\\\"\\n\\tself organization removeSystemCategory: 'System-Serial Port'.\\n\\tself organization removeSystemCategory: 'ST80-Symbols'.\\n\\tself organization removeSystemCategory: 'Tools-File Contents Browser'.\\n\\tself organization removeSystemCategory: 'System-Compression'.\\n\\tself organization removeSystemCategory: 'Tools-Explorer'.\\n\\tself organization removeSystemCategory: 'System-Digital Signatures'.\\n\\tForm removeSelector: #edit.\\n\\tself\\n\\t\\tat: #FormView\\n\\t\\tifPresent: [:c | c compile: 'defaultControllerClass ^ NoController' classified: 'controller access'].\\n\\tself removeClassNamed: #FormEditorView.\\n\\tself removeClassNamed: #FormEditor.\\n\\tself organization removeSystemCategory: 'ST80-Paths'.\\n\\t\\\"bit editor (remove Form editor first):\\\"\\n\\tForm removeSelector: #bitEdit.\\n\\tForm removeSelector: #bitEditAt:scale:.\\n\\tStrikeFont removeSelector: #edit:.\\n\\tself removeClassNamed: #FormButtonCache.\\n\\tself removeClassNamed: #FormMenuController.\\n\\tself removeClassNamed: #FormMenuView.\\n\\tself removeClassNamed: #BitEditor.\\n\\t\\\"inspector for Dictionaries of Forms\\\"\\n\\tDictionary removeSelector: #inspectFormsWithLabel:.\\n\\tSystemDictionary removeSelector: #viewImageImports.\\n\\tScreenController removeSelector: #viewImageImports.\\n\\tself removeClassNamed: #FormHolderView.\\n\\tself removeClassNamed: #FormInspectView.\\n\\t\\\"experimental updating object viewer:\\\"\\n\\tObject removeSelector: #evaluate:wheneverChangeIn:.\\n\\tself removeClassNamed: #ObjectViewer.\\n\\tself removeClassNamed: #ObjectTracer.\\n\\t\\\"miscellaneous classes:\\\"\\n\\tself removeClassNamed: #Array2D.\\n\\tself removeClassNamed: #DriveACar.\\n\\tself removeClassNamed: #EventRecorder.\\n\\tself removeClassNamed: #FindTheLight.\\n\\tself removeClassNamed: #PluggableTest.\\n\\tself removeClassNamed: #SystemMonitor.\\n\\tself removeClassNamed: #ProtocolBrowser.\\n\\tself removeClassNamed: #ObjectExplorerWrapper.\\n\\tself removeClassNamed: #HierarchyBrowser.\\n\\tself removeClassNamed: #LinkedMessageSet.\\n\\tself removeClassNamed: #ObjectExplorer.\\n\\tself removeClassNamed: #PackageBrowser.\\n\\tself removeClassNamed: #AbstractHierarchicalList.\\n\\tself removeClassNamed: #ChangeList.\\n\\tself removeClassNamed: #VersionsBrowser.\\n\\tself removeClassNamed: #ChangeRecord.\\n\\tself removeClassNamed: #SelectorBrowser.\\n\\tself removeClassNamed: #HtmlFileStream.\\n\\tself removeClassNamed: #CrLfFileStream.\\n\\tself removeClassNamed: #FXGrafPort.\\n\\tself removeClassNamed: #FXBlt.\\n\\tself\\n\\t\\tat: #SampledSound\\n\\t\\tifPresent: [:c | c initialize].\\n\\t#(#Helvetica #Palatino #Courier #ComicBold #ComicPlain )\\n\\t\\tdo: [:k | TextConstants\\n\\t\\t\\t\\tremoveKey: k\\n\\t\\t\\t\\tifAbsent: []].\\n\\tPreferences\\n\\t\\tsetButtonFontTo: (StrikeFont familyName: #NewYork size: 12).\\n\\tPreferences\\n\\t\\tsetFlapsFontTo: (StrikeFont familyName: #NewYork size: 12).\\n\\t#(#GZipConstants #ZipConstants #KlattResonatorIndices )\\n\\t\\tdo: [:k | self\\n\\t\\t\\t\\tremoveKey: k\\n\\t\\t\\t\\tifAbsent: []]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:23'!\\ndiscardSoundSynthesis\\n\\t\\\"Discard the sound synthesis facilities, and the methods and\\n\\tclasses that use it. This also discards MIDI.\\\"\\n\\tself discardMIDI.\\n\\tself discardSpeech.\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Interface'.\\n\\tself\\n\\t\\tat: #GraphMorph\\n\\t\\tifPresent: [:graphMorph | #(#playOnce #readDataFromFile )\\n\\t\\t\\t\\tdo: [:sel | graphMorph removeSelector: sel]].\\n\\tself\\n\\t\\tat: #TrashCanMorph\\n\\t\\tifPresent: [:trashMorph | \\n\\t\\t\\ttrashMorph class removeSelector: #samplesForDelete.\\n\\t\\t\\ttrashMorph class removeSelector: #samplesForMouseEnter.\\n\\t\\t\\ttrashMorph class removeSelector: #samplesForMouseLeave].\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Synthesis'.\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Scores'! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/3/2000 19:21'!\\ndiscardSpeech\\n\\t\\\"Discard support for speech synthesis\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Speech*'.\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:23'!\\ndiscardSUnit\\n\\t\\\"Smalltalk discardSUnit\\\"\\n\\t| oc |\\n\\toc := OrderedCollection new.\\n\\t(self\\n\\t\\tat: #TestCase\\n\\t\\tifAbsent: [^ self])\\n\\t\\tallSubclassesWithLevelDo: [:c :i | oc addFirst: c]\\n\\t\\tstartingLevel: 0.\\n\\toc\\n\\t\\tdo: [:c | c removeFromSystem].\\n\\tSystemOrganization removeCategoriesMatching: 'SUnit-*'! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/5/2000 01:32'!\\ndiscardTrueType\\n\\t\\\"Discard TrueType support.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-TrueType*'.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:24'!\\nlastRemoval\\n\\t\\\"Smalltalk lastRemoval\\\"\\n\\t\\\"Some explicit removals - add unwanted methods keeping\\n\\tother methods.\\\"\\n\\t| oldDicts newDicts |\\n\\t#(#abandonSources )\\n\\t\\tdo: [:each | self class removeSelector: each].\\n\\t\\\"Get rid of all unsent methods.\\\"\\n\\t[self removeAllUnSentMessages > 0] whileTrue.\\n\\t\\\"Shrink method dictionaries.\\\"\\n\\tself garbageCollect.\\n\\toldDicts := MethodDictionary allInstances.\\n\\tnewDicts := Array new: oldDicts size.\\n\\toldDicts\\n\\t\\twithIndexDo: [:d :index | newDicts at: index put: d rehashWithoutBecome].\\n\\toldDicts elementsExchangeIdentityWith: newDicts.\\n\\toldDicts := newDicts := nil.\\n\\tself\\n\\t\\tallClassesDo: [:c | c zapOrganization].\\n\\tSystemOrganization := nil.\\n\\tChangeSet current initialize! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'md 2/24/2006 15:42'!\\nmajorShrink\\n\\t\\\"Undertake a major shrinkage of the image.\\n\\tThis method throws out lots of the system that is not needed\\n\\tfor, eg, operation in a hand-held PC. majorShrink produces a\\n\\t999k image in Squeak 2.8\\n\\tSmalltalk majorShrink; abandonSources; lastRemoval\\\"\\n\\t| oldDicts newDicts |\\n\\tself isMorphic\\n\\t\\tifTrue: [^ self error: 'You can only run majorShrink in MVC'].\\n\\tProject current isTopProject\\n\\t\\tifFalse: [^ self error: 'You can only run majorShrink in the top project'].\\n\\t(self confirm: 'All sub-projects will be deleted from this image.\\nYou should already have made a backup copy,\\nor you must save with a different name after shrinking.\\nShall we proceed to discard most of the content in this image?')\\n\\t\\tifFalse: [^ self inform: 'No changes have been made.'].\\n\\t\\\"Remove all projects but the current one. - saves 522k\\\"\\n\\tProjectView\\n\\t\\tallInstancesDo: [:pv | pv controller closeAndUnscheduleNoTerminate].\\n\\tProject current setParent: Project current.\\n\\tMorphWorldView\\n\\t\\tallInstancesDo: [:pv | pv topView controller closeAndUnscheduleNoTerminate].\\n\\tself\\n\\t\\tat: #Wonderland\\n\\t\\tifPresent: [:cls | cls removeActorPrototypesFromSystem].\\n\\tPlayer freeUnreferencedSubclasses.\\n\\tMorphicModel removeUninstantiatedModels.\\n\\tUtilities classPool at: #ScrapsBook put: nil.\\n\\tUtilities zapUpdateDownloader.\\n\\tProjectHistory currentHistory initialize.\\n\\tProject rebuildAllProjects.\\n\\t\\\"Smalltalk discardVMConstruction.\\\"\\n\\t\\\"755k\\\"\\n\\tself discardSoundSynthesis.\\n\\t\\\"544k\\\"\\n\\tself discardOddsAndEnds.\\n\\t\\\"227k\\\"\\n\\tself discardNetworking.\\n\\t\\\"234k\\\"\\n\\t\\\"Smalltalk discard3D.\\\"\\n\\t\\\"407k\\\"\\n\\tself discardFFI.\\n\\t\\\"33k\\\"\\n\\tself discardMorphic.\\n\\t\\\"1372k\\\"\\n\\tSymbol rehash.\\n\\t\\\"40k\\\"\\n\\t\\\"Above by itself saves about 4,238k\\\"\\n\\t\\\"Remove references to a few classes to be deleted, so that they\\n\\twon't leave obsolete versions around.\\\"\\n\\tChangeSet class compile: 'defaultName\\n\\t\\t^ ''Changes'' ' classified: 'initialization'.\\n\\tScreenController removeSelector: #openChangeManager.\\n\\tScreenController removeSelector: #exitProject.\\n\\tScreenController removeSelector: #openProject.\\n\\tScreenController removeSelector: #viewImageImports.\\n\\t\\\"Now delete various other classes..\\\"\\n\\tSystemOrganization removeSystemCategory: 'Graphics-Files'.\\n\\tSystemOrganization removeSystemCategory: 'System-Object Storage'.\\n\\tself removeClassNamed: #ProjectController.\\n\\tself removeClassNamed: #ProjectView.\\n\\t\\\"Smalltalk removeClassNamed: #Project.\\\"\\n\\tself removeClassNamed: #Component1.\\n\\tself removeClassNamed: #FormSetFont.\\n\\tself removeClassNamed: #FontSet.\\n\\tself removeClassNamed: #InstructionPrinter.\\n\\tself removeClassNamed: #ChangeSorter.\\n\\tself removeClassNamed: #DualChangeSorter.\\n\\tself removeClassNamed: #EmphasizedMenu.\\n\\tself removeClassNamed: #MessageTally.\\n\\tStringHolder class removeSelector: #originalWorkspaceContents.\\n\\tCompiledMethod removeSelector: #symbolic.\\n\\tRemoteString removeSelector: #makeNewTextAttVersion.\\n\\tUtilities class removeSelector: #absorbUpdatesFromServer.\\n\\tself removeClassNamed: #PenPointRecorder.\\n\\tself removeClassNamed: #Path.\\n\\tself removeClassNamed: #Base64MimeConverter.\\n\\t\\\"Smalltalk removeClassNamed: #EToySystem. Dont bother - its\\n\\tvery small and used for timestamps etc\\\"\\n\\tself removeClassNamed: #RWBinaryOrTextStream.\\n\\tself removeClassNamed: #AttributedTextStream.\\n\\tself removeClassNamed: #WordNet.\\n\\tself removeClassNamed: #SelectorBrowser.\\n\\tTextStyle\\n\\t\\tallSubInstancesDo: [:ts | ts\\n\\t\\t\\t\\tnewFontArray: (ts fontArray\\n\\t\\t\\t\\t\\t\\tcopyFrom: 1\\n\\t\\t\\t\\t\\t\\tto: (2 min: ts fontArray size))].\\n\\tListParagraph initialize.\\n\\tPopUpMenu initialize.\\n\\tStandardSystemView initialize.\\n\\tChangeSet noChanges.\\n\\tChangeSet classPool\\n\\t\\tat: #AllChangeSets\\n\\t\\tput: (OrderedCollection with: ChangeSet current).\\n\\tSystemDictionary removeSelector: #majorShrink.\\n\\t[self removeAllUnSentMessages > 0]\\n\\t\\twhileTrue: [Smalltalk unusedClasses\\n\\t\\t\\t\\tdo: [:c | (Smalltalk at: c) removeFromSystem]].\\n\\tSystemOrganization removeEmptyCategories.\\n\\tself\\n\\t\\tallClassesDo: [:c | c zapOrganization].\\n\\tself garbageCollect.\\n\\t'Rehashing method dictionaries . . .'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: MethodDictionary instanceCount\\n\\t\\tduring: [:bar | \\n\\t\\t\\toldDicts := MethodDictionary allInstances.\\n\\t\\t\\tnewDicts := Array new: oldDicts size.\\n\\t\\t\\toldDicts\\n\\t\\t\\t\\twithIndexDo: [:d :index | \\n\\t\\t\\t\\t\\tbar value: index.\\n\\t\\t\\t\\t\\tnewDicts at: index put: d rehashWithoutBecome].\\n\\t\\t\\toldDicts elementsExchangeIdentityWith: newDicts].\\n\\toldDicts := newDicts := nil.\\n\\tProject rebuildAllProjects.\\n\\tChangeSet current initialize.\\n\\t\\\"seems to take more than one try to gc all the weak refs in\\n\\tSymbolTable \\\"\\n\\t3\\n\\t\\ttimesRepeat: [self garbageCollect.\\n\\t\\t\\tSymbol compactSymbolTable]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'nk 4/28/2004 10:24'!\\npresumedSentMessages | sent |\\n\\\"Smalltalk presumedSentMessages\\\"\\n\\n\\t\\\"The following should be preserved for doIts, etc\\\"\\n\\tsent _ IdentitySet new.\\n\\t#( rehashWithoutBecome compactSymbolTable rebuildAllProjects\\n\\t\\tbrowseAllSelect: lastRemoval\\n\\t\\tscrollBarValue: vScrollBarValue: scrollBarMenuButtonPressed: \\n\\t\\twithSelectionFrom: to: removeClassNamed:\\n\\t\\tdragon: hilberts: mandala: web test3 factorial tinyBenchmarks benchFib\\n\\t\\tnewDepth: restoreAfter: forgetDoIts zapAllMethods obsoleteClasses\\n\\t\\tremoveAllUnSentMessages abandonSources removeUnreferencedKeys\\n\\t\\treclaimDependents zapOrganization condenseChanges browseObsoleteReferences\\n\\t\\tsubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:\\n\\t\\tmethodsFor:stamp: methodsFor:stamp:prior: instanceVariableNames:\\n\\t\\tstartTimerInterruptWatcher unusedClasses) do:\\n\\t\\t[:sel | sent add: sel].\\n\\t\\\"The following may be sent by perform: in dispatchOnChar...\\\"\\n\\t(ParagraphEditor classPool at: #CmdActions) asSet do:\\n\\t\\t[:sel | sent add: sel].\\n\\t(ParagraphEditor classPool at: #ShiftCmdActions) asSet do:\\n\\t\\t[:sel | sent add: sel].\\n\\t^ sent! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'nk 4/28/2004 10:24'!\\nremoveAllUnSentMessages\\n\\t\\\"Smalltalk removeAllUnSentMessages\\\"\\n\\t\\\"[Smalltalk unusedClasses do: [:c | (Smalltalk at: c) removeFromSystem]. \\n\\tSmalltalk removeAllUnSentMessages > 0] whileTrue.\\\"\\n\\t\\\"Remove all implementations of unsent messages.\\\"\\n\\t| sels n |\\n\\tsels _ self systemNavigation allUnSentMessages.\\n\\t\\\"The following should be preserved for doIts, etc\\\"\\n\\t\\\"needed even after #majorShrink is pulled\\\"\\n\\t#(#rehashWithoutBecome #compactSymbolTable #rebuildAllProjects #browseAllSelect: #lastRemoval #scrollBarValue: vScrollBarValue: #scrollBarMenuButtonPressed: #withSelectionFrom: #to: #removeClassNamed: #dragon: #hilberts: #mandala: #web #test3 #factorial #tinyBenchmarks #benchFib #newDepth: #restoreAfter: #forgetDoIts #zapAllMethods #obsoleteClasses #removeAllUnSentMessages #abandonSources #removeUnreferencedKeys #reclaimDependents #zapOrganization #condenseChanges #browseObsoleteReferences #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: #methodsFor:stamp: #methodsFor:stamp:prior: #instanceVariableNames: #startTimerInterruptWatcher #unusedClasses )\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\t\\\"The following may be sent by perform: in dispatchOnChar...\\\"\\n\\t(ParagraphEditor classPool at: #CmdActions) asSet\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\t(ParagraphEditor classPool at: #ShiftCmdActions) asSet\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\tsels size = 0\\n\\t\\tifTrue: [^ 0].\\n\\tn _ 0.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:x | n _ n + 1].\\n\\t'Removing ' , sels size printString , ' messages . . .'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: n\\n\\t\\tduring: [:bar | \\n\\t\\t\\tn _ 0.\\n\\t\\t\\tself systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:class | \\n\\t\\t\\t\\t\\tbar value: (n _ n + 1).\\n\\t\\t\\t\\t\\tsels\\n\\t\\t\\t\\t\\t\\tdo: [:sel | class basicRemoveSelector: sel]]].\\n\\t^ sels size! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:26'!\\nremoveNormalCruft\\n\\t\\\"Remove various graphics, uniclasses, references. Caution: see\\n\\tcomment at bottom of method\\\"\\n\\t\\\"Smalltalk removeNormalCruft\\\"\\n\\tScriptingSystem stripGraphicsForExternalRelease.\\n\\tScriptingSystem spaceReclaimed.\\n\\tReferences keys\\n\\t\\tdo: [:k | References removeKey: k].\\n\\tself classNames\\n\\t\\tdo: [:cName | #('Player' 'CardPlayer' 'Component' 'WonderlandActor' 'MorphicModel' 'PlayWithMe' )\\n\\t\\t\\t\\tdo: [:superName | ((cName ~= superName\\n\\t\\t\\t\\t\\t\\t\\t\\tand: [cName beginsWith: superName])\\n\\t\\t\\t\\t\\t\\t\\tand: [(cName allButFirst: superName size)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tallSatisfy: [:ch | ch isDigit]])\\n\\t\\t\\t\\t\\t\\tifTrue: [self removeClassNamed: cName]]].\\n\\tself\\n\\t\\tat: #Wonderland\\n\\t\\tifPresent: [:cls | cls removeActorPrototypesFromSystem].\\n\\tChangeSet current clear\\n\\t\\\"Caution: if any worlds in the image happen to have uniclass\\n\\tplayers associated with them, running this method would\\n\\tlikely compromise their functioning and could cause errors,\\n\\tespecially if the uniclass player of the current world had any\\n\\tscripts set to ticking. If that happens to you somehow, you will\\n\\tprobably want to find a way to reset the offending world's\\n\\tplayer to be an UnscriptedCardPlayer, or perhaps nil\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:26'!\\nremoveSelector: descriptor \\n\\t\\\"Safely remove a selector from a class (or metaclass). If the\\n\\tclass or the method doesn't exist anymore, never mind and\\n\\tanswer nil.\\n\\tThis method should be used instead of 'Class removeSelector:\\n\\t#method' to omit global class references.\\\"\\n\\t| class sel |\\n\\tclass := self\\n\\t\\t\\t\\tat: descriptor first\\n\\t\\t\\t\\tifAbsent: [^ nil].\\n\\t(descriptor size > 2\\n\\t\\t\\tand: [descriptor second == #class])\\n\\t\\tifTrue: [class := class class.\\n\\t\\t\\tsel := descriptor third]\\n\\t\\tifFalse: [sel := descriptor second].\\n\\t^ class removeSelector: sel! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'di 2/25/2001 22:34'!\\nreportClassAndMethodRemovalsFor: collectionOfClassNames\\n\\t| initialClassesAndMethods finalClassesAndMethods |\\n\\t\\\"Smalltalk reportClassAndMethodRemovalsFor: #(Celeste Scamper MailMessage)\\\"\\n\\n\\tinitialClassesAndMethods _ self unusedClassesAndMethodsWithout: {{}. {}}.\\n\\tfinalClassesAndMethods _ self unusedClassesAndMethodsWithout: {collectionOfClassNames. {}}.\\n\\t^ {finalClassesAndMethods first copyWithoutAll: initialClassesAndMethods first.\\n\\t\\tfinalClassesAndMethods second copyWithoutAll: initialClassesAndMethods second}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 4/29/2003 19:06'!\\nunusedClasses\\n\\t\\\"Enumerates all classes in the system and returns a list of those that are \\n\\tapparently unused. A class is considered in use if it (a) has subclasses \\n\\tor (b) is referred to by some method or (c) has its name in use as a \\n\\tliteral. \\\"\\n\\t\\\"Smalltalk unusedClasses asSortedCollection\\\"\\n\\t^ self systemNavigation allUnusedClassesWithout: {{}. {}}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'edc 11/8/2005 10:11'!\\nunusedClassesAndMethodsWithout: classesAndMessagesPair \\n\\t\\\"Accepts and returns a pair: {set of class names. set of selectors}. \\n\\tIt is expected these results will be diff'd with the normally unused \\n\\tresults. \\\"\\n\\t| classRemovals messageRemovals nClasses nMessages |\\n\\t(classRemovals _ IdentitySet new) addAll: classesAndMessagesPair first.\\n\\t(messageRemovals _ IdentitySet new) addAll: classesAndMessagesPair second.\\n\\tnClasses _ nMessages _ -1.\\n\\t[\\\"As long as we keep making progress...\\\"\\n\\tclassRemovals size > nClasses\\n\\t\\tor: [messageRemovals size > nMessages]]\\n\\t\\twhileTrue: [\\\"...keep trying for bigger sets of unused classes and selectors.\\\"\\n\\t\\t\\tnClasses _ classRemovals size.\\n\\t\\t\\tnMessages _ messageRemovals size.\\n\\t\\t\\tUtilities\\n\\t\\t\\t\\tinformUser: 'Iterating removals '\\n\\t\\t\\t\\t\\t\\t, (classesAndMessagesPair first isEmpty\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: ['for baseline...']\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: ['for ' , classesAndMessagesPair first first , ' etc...']) , Character cr asString , nClasses printString , ' classes, ' , nMessages printString , ' messages.\\n|\\n|'\\n\\t\\t\\t\\tduring: [\\\"spacers move menu off cursor\\\"\\n\\t\\t\\t\\t\\tclassRemovals\\n\\t\\t\\t\\t\\t\\taddAll: (self systemNavigation allUnusedClassesWithout: {classRemovals. messageRemovals}).\\n\\t\\t\\t\\t\\tmessageRemovals\\n\\t\\t\\t\\t\\t\\taddAll: (self systemNavigation allUnSentMessagesWithout: {classRemovals. messageRemovals})]].\\n\\t^ {classRemovals. self systemNavigation allUnSentMessagesWithout: {classRemovals. messageRemovals}}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'dao 10/1/2004 13:51'!\\nwriteImageSegmentsFrom: segmentDictionary withKernel: kernel\\n\\t\\\"segmentDictionary is associates segmentName -> {classNames. methodNames},\\n\\tand kernel is another set of classNames determined to be essential.\\n\\tAdd a partition, 'Secondary' with everything not in partitions and not in the kernel.\\n\\tThen write segments based on this partitioning of classes.\\\"\\n\\n\\t| metas secondary dups segDict overlaps classes n symbolHolder |\\n\\t\\\"First, put all classes that are in no other partition, and not in kernel into a new partition called 'Secondary'. Also remove any classes in kernel from putative partitions.\\\"\\n\\tsecondary _ Smalltalk classNames asIdentitySet.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName |\\n\\t\\tsecondary removeAllFoundIn: (segmentDictionary at: segName) first.\\n\\t\\t(segmentDictionary at: segName) first removeAllFoundIn: kernel].\\n\\tsecondary removeAllFoundIn: kernel.\\n\\tsecondary removeAllFoundIn: #(PseudoContext TranslatedMethod Utilities Preferences OutOfScopeNotification FakeClassPool BlockCannotReturn FormSetFont ExternalSemaphoreTable NetNameResolver ScreenController InterpreterPlugin Command WeakSet).\\n\\tFileDirectory allSubclassesDo: [:c | secondary remove: c name ifAbsent: []].\\n\\tsegmentDictionary at: 'Secondary' put: {secondary. {}}.\\n\\n\\t\\\"Now build segDict giving className -> segName, and report any duplicates.\\\"\\n\\tdups _ Dictionary new.\\n\\tsegDict _ IdentityDictionary new: 3000.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | (segmentDictionary at: segName) first do:\\n\\t\\t\\t[:className |\\n\\t\\t\\t(segDict includesKey: className) ifTrue:\\n\\t\\t\\t\\t[(dups includesKey: className) ifFalse: [dups at: className put: Array new].\\n\\t\\t\\t\\tdups at: className put: (dups at: className) , {segName}].\\n\\t\\t\\tsegDict at: className put: segName]].\\n\\tdups size > 0 ifTrue: [dups inspect. ^ self error: 'Duplicate entries'].\\n\\n\\t\\\"Then for every class in every partition, make sure that neither it\\n\\tnor any of its superclasses are in any other partition. If they are,\\n\\tenter them in a dictionary of overlaps.\\n\\tIf the dictionary is not empty, then stop and report it.\\\"\\n\\toverlaps _ Dictionary new.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | \\n\\t\\tclasses _ (segmentDictionary at: segName) first asArray collect: [:k | Smalltalk at: k].\\n\\t\\tclasses do:\\n\\t\\t\\t[:c | (c isKindOf: Class) ifTrue:\\n\\t\\t\\t\\t[c withAllSuperclasses do:\\n\\t\\t\\t\\t\\t[:sc | n _ segDict at: sc name ifAbsent: [segName].\\n\\t\\t\\t\\t\\tn ~= segName ifTrue:\\n\\t\\t\\t\\t\\t\\t[n = 'Secondary'\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [(segmentDictionary at: 'Secondary') first\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tremove: sc name ifAbsent: []]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [overlaps at: c name put: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(c withAllSuperclasses collect: [:cc | segDict associationAt: cc name ifAbsent: [cc name -> 'Kernel']])]]]]]].\\n\\toverlaps size > 0 ifTrue: [overlaps inspect. ^ self error: 'Superclasses in separate segments'].\\n\\n\\t\\\"If there are no overlaps, then proceed to write the partitioned classes.\\\"\\n\\tsymbolHolder _ Symbol allInstances.\\t\\\"Hold onto Symbols with strong pointers, \\n\\t\\tso they will be in outPointers\\\"\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | Utilities informUser: segName during:\\n\\t\\t\\t[classes _ (segmentDictionary at: segName) first asArray collect: [:k | Smalltalk at: k].\\n\\t\\t\\tmetas _ classes select: [:c | c isKindOf: Class] thenCollect: [:c | c class].\\n\\t\\t\\t(ImageSegment new copyFromRoots: classes , metas sizeHint: 0) extract; \\n\\t\\t\\t\\t\\twriteToFile: segName]].\\n\\tsymbolHolder. \\\"Keep compiler for getting uppity.\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'ar 9/27/2005 20:12'!\\nzapAllOtherProjects \\n\\t\\\"Smalltalk zapAllOtherProjects\\\"\\n\\\"Note: as of this writing, the only reliable way to get rid of all but the current project is te execute the following, one line at a time...\\n\\t\\tSmalltalk zapAllOtherProjects.\\n\\t\\tProjectHistory currentHistory initialize.\\n\\t\\tSmalltalk garbageCollect.\\n\\t\\tProject rebuildAllProjects.\\n\\\"\\n\\n\\t\\n\\tProject allInstancesDo: [:p | p setParent: nil].\\n\\tProject current setParent: Project current.\\n\\tProject current isMorphic ifTrue: [ScheduledControllers := nil].\\n\\tTheWorldMenu allInstancesDo: [:m | 1 to: m class instSize do: [:i | m instVarAt: i put: nil]].\\n\\tChangeSet classPool at: #AllChangeSets put: nil.\\n\\tProject classPool at: #AllProjects put: nil.\\n\\tProjectHistory currentHistory initialize.\\n\\tChangeSet initialize.\\n\\tProject rebuildAllProjects. \\\"Does a GC\\\"\\n\\tProject allProjects size > 1 ifTrue: [Project allProjects inspect]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'dao 10/1/2004 13:30'!\\nzapMVCprojects\\n\\t\\\"Smalltalk zapMVCprojects\\\"\\n\\t| window |\\n\\n\\tself flag: #bob. \\\"zapping projects\\\"\\n\\n\\tSmalltalk garbageCollect.\\n\\t\\\"So allInstances is precise\\\"\\n\\tProject\\n\\t\\tallSubInstancesDo: [:proj | proj isTopProject\\n\\t\\t\\t\\tifTrue: [proj isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Root project is MVC -- we must become the root\\\"\\n\\t\\t\\t\\t\\t\\t\\tProject current setParent: Project current.]]\\n\\t\\t\\t\\tifFalse: [proj parent isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [proj isMorphic\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [\\\"Remove Morphic projects from MVC \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tviews \\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"... and add them back here.\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow _ (SystemWindow labelled: proj name)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodel: proj.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddMorph: (ProjectViewMorph on: proj)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframe: (0 @ 0 corner: 1.0 @ 1.0).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow openInWorld.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tproj setParent: Project current]].\\n\\t\\t\\t\\t\\tproj isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Remove MVC projects from Morphic views\\\"\\n\\t\\t\\t\\t\\t\\t\\tProject deletingProject: proj]]]! !\\n\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:38'!\\naddToShutDownList: aClass\\n\\t\\\"This will add a ref to this class at the BEGINNING of the shutDown list.\\\"\\n\\n\\tself addToShutDownList: aClass after: nil! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'!\\naddToShutDownList: aClass after: predecessor\\n\\n\\tself add: aClass toList: ShutDownList after: predecessor! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:37'!\\naddToStartUpList: aClass\\n\\t\\\"This will add a ref to this class at the END of the startUp list.\\\"\\n\\n\\tself addToStartUpList: aClass after: nil! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'!\\naddToStartUpList: aClass after: predecessor\\n\\n\\tself add: aClass toList: StartUpList after: predecessor! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/19/1999 22:36'!\\nadd: aClass toList: startUpOrShutDownList after: predecessor\\n\\t\\\"Add the name of aClass to the startUp or shutDown list.\\n\\tAdd it after the name of predecessor, or at the end if predecessor is nil.\\\"\\n\\n\\t| name earlierName |\\n\\tname _ aClass name.\\n\\t(self at: name ifAbsent: [nil]) == aClass ifFalse:\\n\\t\\t[self error: name , ' cannot be found in Smalltalk dictionary.'].\\n\\tpredecessor == nil\\n\\t\\tifTrue: [\\\"No-op if alredy in the list.\\\"\\n\\t\\t\\t\\t(startUpOrShutDownList includes: name) ifFalse:\\n\\t\\t\\t\\t\\t[startUpOrShutDownList == StartUpList\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"Add to end of startUp list\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tstartUpOrShutDownList addLast: name]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Add to front of shutDown list\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tstartUpOrShutDownList addFirst: name]]]\\n\\t\\tifFalse: [\\\"Add after predecessor, moving it if already there.\\\"\\n\\t\\t\\t\\tearlierName _ predecessor name.\\n\\t\\t\\t\\t(self at: earlierName) == predecessor ifFalse:\\n\\t\\t\\t\\t\\t[self error: earlierName , ' cannot be found in Smalltalk dictionary.'].\\n\\t\\t\\t\\t(startUpOrShutDownList includes: earlierName) ifFalse:\\n\\t\\t\\t\\t\\t[self error: earlierName , ' cannot be found in the list.'].\\n\\t\\t\\t\\tstartUpOrShutDownList remove: name ifAbsent:[].\\n\\t\\t\\t\\tstartUpOrShutDownList add: name after: earlierName]! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'RAA 6/14/2000 17:21'!\\nisMorphic\\n \\\"Answer true if the user interface is running in Morphic rathern than \\n MVC. By convention the gloabl variable World is set to nil when MVC is \\n running. ScheduledControllers could be set to nil when Morphic is \\n running, but this symmetry is not yet in effect.\\\"\\n\\n ^ World ~~ nil \\\"or: [RequestCurrentWorldNotification signal notNil]\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'!\\nprocessShutDownList: quitting\\n\\t\\\"Send #shutDown to each class that needs to wrap up before a snapshot.\\\"\\n\\n\\tself send: #shutDown: toClassesNamedIn: ShutDownList with: quitting.\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'!\\nprocessStartUpList: resuming\\n\\t\\\"Send #startUp to each class that needs to run initialization after a snapshot.\\\"\\n\\n\\tself send: #startUp: toClassesNamedIn: StartUpList with: resuming.\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit'!\\nquitPrimitive\\n\\t\\\"Primitive. Exit to another operating system on the host machine, if one\\n\\texists. All state changes in the object space since the last snapshot are lost.\\n\\tEssential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 113>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'!\\nremoveFromShutDownList: aClass\\n\\n\\tShutDownList remove: aClass name ifAbsent: []! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'!\\nremoveFromStartUpList: aClass\\n\\n\\tStartUpList remove: aClass name ifAbsent: []! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 3/7/2001 01:26'!\\nsend: startUpOrShutDown toClassesNamedIn: startUpOrShutDownList with: argument\\n\\t\\\"Send the message #startUp: or #shutDown: to each class named in the list.\\n\\tThe argument indicates if the system is about to quit (for #shutDown:) or if\\n\\tthe image is resuming (for #startUp:).\\n\\tIf any name cannot be found, then remove it from the list.\\\"\\n\\n\\t| removals class |\\n\\tremovals _ OrderedCollection new.\\n\\tstartUpOrShutDownList do:\\n\\t\\t[:name |\\n\\t\\tclass _ self at: name ifAbsent: [nil].\\n\\t\\tclass == nil\\n\\t\\t\\tifTrue: [removals add: name]\\n\\t\\t\\tifFalse: [class isInMemory ifTrue:\\n\\t\\t\\t\\t\\t\\t[class perform: startUpOrShutDown with: argument]]].\\n\\n\\t\\\"Remove any obsolete entries, but after the iteration\\\"\\n\\tstartUpOrShutDownList removeAll: removals! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 9/30/2003 13:47'!\\nsetGCParameters\\n\\t\\\"Adjust the VM's default GC parameters to avoid premature tenuring.\\\"\\n\\n\\tSmalltalkImage current vmParameterAt: 5 put: 4000. \\\"do an incremental GC after this many allocations\\\"\\n\\tSmalltalkImage current vmParameterAt: 6 put: 2000. \\\"tenure when more than this many objects survive the GC\\\"\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 13:14'!\\nshutDown\\n\\t^ SmalltalkImage current closeSourceFiles! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'gk 2/23/2004 20:51'!\\nshutDownSound\\n\\t\\\"No longer used in the release, but retained for backward compatibility.\\\"\\n\\n\\tSoundService default shutDown\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'JMM 11/21/2000 21:02'!\\nsnapshotEmbeddedPrimitive\\n\\t<primitive: 247>\\n\\t^nil \\\"indicates error writing embedded image file\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 7/22/2000 14:34'!\\nsnapshotPrimitive\\n\\t\\\"Primitive. Write the current state of the object memory on a file in the\\n\\tsame format as the Smalltalk-80 release. The file can later be resumed,\\n\\treturning you to this exact state. Return normally after writing the file.\\n\\tEssential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 97>\\n\\t^nil \\\"indicates error writing image file\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'nk 11/12/2003 10:32'!\\nunbindExternalPrimitives\\n\\t\\\"Primitive. Force all external primitives to be looked up again afterwards. Since external primitives that have not found are bound for fast failure this method will force the lookup of all primitives again so that after adding some plugin the primitives may be found.\\\"\\n\\t^ self deprecated: 'Use SmalltalkImage unbindExternalPrimitives'\\n\\t\\tblock: [SmalltalkImage unbindExternalPrimitives].\\n\\t\\\"Do nothing if the primitive fails for compatibility with older VMs\\\"! !\\n\\n\\n!SystemDictionary methodsFor: 'sources, change log'!\\ncopyright\\n\\t\\\"The Smalltalk copyright.\\\"\\n\\n\\t^'Copyright (c) Xerox Corp. 1981, 1982 All rights reserved.\\nCopyright (c) Apple Computer, Inc. 1985-1996 All rights reserved.'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'em 3/31/2005 11:48'!\\ncurrentChangeSetString\\n\\t\\\"Smalltalk currentChangeSetString\\\"\\n\\t^ 'Current Change Set: ' translated, ChangeSet current name! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 9/29/2004 18:27'!\\ncurrentProjectDo: aBlock \\n\\t\\\"So that code can work after removal of Projects\\\"\\n\\tself\\n\\t\\tat: #Project\\n\\t\\tifPresent: [:projClass | aBlock value: projClass current]! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\nexternalizeSources \\n\\t\\\"Write the sources and changes streams onto external files.\\\"\\n \\t\\\"Smalltalk externalizeSources\\\"\\n\\t\\\"the logic of this method is complex because it uses changesName and self changesName\\n\\tmay be this is normal - sd\\\"\\n\\t\\n\\t| sourcesName changesName aFile |\\n\\tsourcesName _ SmalltalkImage current sourcesName.\\n\\t(FileDirectory default fileExists: sourcesName)\\n\\t\\tifTrue: [^ self inform:\\n'Sorry, you must first move or remove the\\nfile named ', sourcesName].\\n\\tchangesName _ SmalltalkImage current changesName.\\n\\t(FileDirectory default fileExists: changesName)\\n\\t\\tifTrue: [^ self inform:\\n'Sorry, you must first move or remove the\\nfile named ', changesName].\\n\\n\\taFile _ FileStream newFileNamed: sourcesName.\\n\\taFile nextPutAll: SourceFiles first originalContents.\\n\\taFile close.\\n\\tself setMacFileInfoOn: sourcesName.\\n\\tSourceFiles at: 1 put: (FileStream readOnlyFileNamed: sourcesName).\\n\\n\\taFile _ FileStream newFileNamed: SmalltalkImage current changesName.\\n\\taFile nextPutAll: SourceFiles last contents.\\n\\taFile close.\\n\\t\\\"On Mac, set the file type and creator (noop on other platforms)\\\"\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: SmalltalkImage current changesName\\n\\t\\ttype: 'STch'\\n\\t\\tcreator: 'FAST'.\\n\\tSourceFiles at: 2 put: (FileStream oldFileNamed: changesName).\\n\\n\\tself inform: 'Sources successfully externalized'.\\n! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'ar 2/6/2001 18:42'!\\nforceChangesToDisk\\n\\t\\\"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.\\\"\\n\\n\\t| changesFile |\\n\\tchangesFile _ SourceFiles at: 2.\\n\\t(changesFile isKindOf: FileStream) ifTrue: [\\n\\t\\tchangesFile flush.\\n\\t\\tSecurityManager default hasFileAccess ifTrue:[\\n\\t\\t\\tchangesFile close.\\n\\t\\t\\tchangesFile open: changesFile name forWrite: true].\\n\\t\\tchangesFile setToEnd.\\n\\t].\\n! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\ninternalizeChangeLog \\n\\t\\t\\\"Smalltalk internalizeChangeLog\\\"\\n\\t\\\"Bring the changes file into a memory-resident filestream, for faster access and freedom from external file system. 1/31/96 sw\\\"\\n\\n\\t| reply aName aFile |\\n\\treply _ self confirm: 'CAUTION -- do not undertake this lightly!!\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nthe requested internalization of sources,\\nhit Yes. If you have any doubts, hit No\\nto back out with no harm done.'.\\n\\n\\t(reply == true) ifFalse:\\n\\t\\t[^ self inform: 'Okay - abandoned'].\\n\\n\\taName _ SmalltalkImage current changesName.\\n\\t(aFile _ SourceFiles last) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\tself inform: 'Okay, changes file internalized'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\ninternalizeSources \\n\\t\\t\\\"Smalltalk internalizeSources\\\"\\n\\t\\\"Bring the sources and changes files into memory-resident filestreams, for faster access and freedom from file-system interface. 1/29/96 sw\\\"\\n\\n\\t| reply aName aFile |\\n\\treply _ self confirm: 'CAUTION -- do not undertake this lightly!!\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nthe requested internalization of sources,\\nhit Yes. If you have any doubts, hit No\\nto back out with no harm done.'.\\n\\n\\t(reply == true) ifFalse:\\n\\t\\t[^ self inform: 'Okay - abandoned'].\\n\\n\\taName _ SmalltalkImage current sourcesName.\\n\\t(aFile _ SourceFiles first) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 1 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\taName _ SmalltalkImage current changesName.\\n\\t(aFile _ SourceFiles last) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\tself inform: 'Okay, sources internalized'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sw 2/3/2000 15:59'!\\nrecover: nCharacters\\n\\t\\\"Schedule an editable text view on the last n characters of changes.\\\"\\n\\tself writeRecentCharacters: nCharacters toFileNamed: 'st80.recent'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'md 5/16/2006 12:34'!\\nversion\\n\\t\\\"Answer the version of this release.\\\"\\n\\n\\t^SystemVersion current version! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'JMM 4/13/2005 20:35'!\\nwordSize\\n\\t\\\"Answer the size (in bytes) of an object pointer.\\\"\\n\\t\\\"Smalltalk wordSize\\\"\\n\\n\\t^[SmalltalkImage current vmParameterAt: 40] on: Error do: [4]! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'nk 8/21/2004 15:55'!\\nwriteRecentCharacters: nCharacters toFileNamed: aFilename\\n\\t\\\"Schedule an editable text view on the last n characters of changes.\\\"\\n\\t| changes |\\n\\tchanges _ SourceFiles at: 2.\\n\\tchanges setToEnd; skip: nCharacters negated.\\n\\t(StandardFileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'ar 9/27/2005 22:38'!\\nwriteRecentToFile\\n\\t\\\"Smalltalk writeRecentToFile\\\"\\n\\t| numChars aDirectory aFileName |\\n\\taDirectory := FileDirectory default.\\n\\taFileName := Utilities\\n\\t\\t\\t\\tkeyLike: 'squeak-recent.01'\\n\\t\\t\\t\\twithTrailing: '.log'\\n\\t\\t\\t\\tsatisfying: [:aKey | (aDirectory includesKey: aKey) not].\\n\\tnumChars := ChangeSet getRecentLocatorWithPrompt: 'copy logged source as far back as...'.\\n\\tnumChars\\n\\t\\tifNotNil: [self writeRecentCharacters: numChars toFileNamed: aFileName]! !\\n\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 20:36'!\\nclearExternalObjects\\n\\t\\\"Clear the array of objects that have been registered for use in non-Smalltalk code.\\\"\\n\\t\\\"Smalltalk clearExternalObjects\\\"\\n\\n\\tExternalSemaphoreTable clearExternalObjects\\n! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'sd 9/29/2004 18:30'!\\ncompactClassesArray\\n\\t\\\"Smalltalk compactClassesArray\\\"\\n\\t\\\"Return the array of 31 classes whose instances may be\\n\\trepresented compactly\\\"\\n\\t^ self specialObjectsArray at: 29! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 21:01'!\\nexternalObjects\\n\\t\\\"Return an array of objects that have been registered for use in non-Smalltalk code. Smalltalk objects should be referrenced by external code only via indirection through this array, thus allowing the objects to move during compaction. This array can be cleared when the VM re-starts, since variables in external code do not survive snapshots. Note that external code should not attempt to access a Smalltalk object, even via this mechanism, while garbage collection is in progress.\\\"\\n\\t\\\"Smalltalk externalObjects\\\"\\n\\n\\t^ ExternalSemaphoreTable externalObjects\\n! !\\n\\n!SystemDictionary methodsFor: 'special objects'!\\nhasSpecialSelector: aLiteral ifTrueSetByte: aBlock\\n\\n\\t1 to: self specialSelectorSize do:\\n\\t\\t[:index | \\n\\t\\t(self specialSelectorAt: index) == aLiteral\\n\\t\\t\\tifTrue: [aBlock value: index + 16rAF. ^true]].\\n\\t^false! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'dtl 10/3/2005 05:56'!\\nrecreateSpecialObjectsArray\\n\\t\\\"Smalltalk recreateSpecialObjectsArray\\\"\\n\\t\\\"The Special Objects Array is an array of object pointers used\\n\\tby the\\n\\tSqueak virtual machine. Its contents are critical and\\n\\tunchecked, so don't even think of playing here unless you\\n\\tknow what you are doing.\\\"\\n\\t| newArray |\\n\\tnewArray := Array new: 50.\\n\\t\\\"Nil false and true get used throughout the interpreter\\\"\\n\\tnewArray at: 1 put: nil.\\n\\tnewArray at: 2 put: false.\\n\\tnewArray at: 3 put: true.\\n\\t\\\"This association holds the active process (a ProcessScheduler)\\\"\\n\\tnewArray\\n\\t\\tat: 4\\n\\t\\tput: (self associationAt: #Processor).\\n\\t\\\"Numerous classes below used for type checking and\\n\\tinstantiation\\\"\\n\\tnewArray at: 5 put: Bitmap.\\n\\tnewArray at: 6 put: SmallInteger.\\n\\tnewArray at: 7 put: ByteString.\\n\\tnewArray at: 8 put: Array.\\n\\tnewArray at: 9 put: Smalltalk.\\n\\tnewArray at: 10 put: Float.\\n\\tnewArray at: 11 put: MethodContext.\\n\\tnewArray at: 12 put: BlockContext.\\n\\tnewArray at: 13 put: Point.\\n\\tnewArray at: 14 put: LargePositiveInteger.\\n\\tnewArray at: 15 put: Display.\\n\\tnewArray at: 16 put: Message.\\n\\tnewArray at: 17 put: CompiledMethod.\\n\\tnewArray\\n\\t\\tat: 18\\n\\t\\tput: (self specialObjectsArray at: 18).\\n\\t\\\"(low space Semaphore)\\\"\\n\\tnewArray at: 19 put: Semaphore.\\n\\tnewArray at: 20 put: Character.\\n\\tnewArray at: 21 put: #doesNotUnderstand:.\\n\\tnewArray at: 22 put: #cannotReturn:.\\n\\t\\\"The process that signaled the low space semaphore.\\\"\\n\\tnewArray at: 23 put: nil.\\n\\t\\\"An array of the 32 selectors that are compiled as special\\n\\tbytecodes, paired alternately with the number of arguments\\n\\teach takes.\\\"\\n\\tnewArray at: 24 put: #(#+ 1 #- 1 #< 1 \";\n r = \"{13490630, 1448950}\";\n s = 1;\n }\n );\n r = \"{0, 17583493}\";\n s = 0;\n}"; sepNavIntBoundsRect = "{{0, 0}, {3988, 3.06823e+06}}"; sepNavSelRange = "{1340, 0}"; sepNavVisRange = "{0, 2724}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/vm/RoarVMOnIPad.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 0A040E2213B7526D007E172E /* performance_counters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A040E2013B7526D007E172E /* performance_counters.cpp */; }; 0A4EFFDC13317C0D004BC399 /* iPhone.changes in Resources */ = {isa = PBXBuildFile; fileRef = 0A4EFFD913317C0D004BC399 /* iPhone.changes */; }; 0A4EFFDD13317C0D004BC399 /* iPhone.image in Resources */ = {isa = PBXBuildFile; fileRef = 0A4EFFDA13317C0D004BC399 /* iPhone.image */; }; 0A4EFFDE13317C0D004BC399 /* SqueakV3-minimum-MVC.sources in Resources */ = {isa = PBXBuildFile; fileRef = 0A4EFFDB13317C0D004BC399 /* SqueakV3-minimum-MVC.sources */; }; 0A5D7CAC135E37A900D13E53 /* externals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CAA135E37A900D13E53 /* externals.cpp */; }; 0A5D7D6A135E37CB00D13E53 /* abstract_mark_sweep_collector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CAF135E37CB00D13E53 /* abstract_mark_sweep_collector.cpp */; }; 0A5D7D6B135E37CB00D13E53 /* abstract_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CB1135E37CB00D13E53 /* abstract_object_heap.cpp */; }; 0A5D7D6C135E37CB00D13E53 /* memory_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CB8135E37CB00D13E53 /* memory_system.cpp */; }; 0A5D7D6D135E37CB00D13E53 /* multicore_object_heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CBB135E37CB00D13E53 /* multicore_object_heap.cpp */; }; 0A5D7D6E135E37CB00D13E53 /* multicore_object_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CBE135E37CB00D13E53 /* multicore_object_table.cpp */; }; 0A5D7D72135E37CB00D13E53 /* squeak_image_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CCB135E37CB00D13E53 /* squeak_image_reader.cpp */; }; 0A5D7D73135E37CB00D13E53 /* at_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CCF135E37CB00D13E53 /* at_cache.cpp */; }; 0A5D7D74135E37CB00D13E53 /* interpreter_bytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CD2135E37CB00D13E53 /* interpreter_bytecodes.cpp */; }; 0A5D7D75135E37CB00D13E53 /* interpreter_primitives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CD4135E37CB00D13E53 /* interpreter_primitives.cpp */; }; 0A5D7D76135E37CB00D13E53 /* method_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CD6135E37CB00D13E53 /* method_cache.cpp */; }; 0A5D7D77135E37CB00D13E53 /* obsolete_indexed_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CD8135E37CB00D13E53 /* obsolete_indexed_primitive_table.cpp */; }; 0A5D7D78135E37CB00D13E53 /* obsolete_named_primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CDA135E37CB00D13E53 /* obsolete_named_primitive_table.cpp */; }; 0A5D7D79135E37CB00D13E53 /* primitive_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CDC135E37CB00D13E53 /* primitive_table.cpp */; }; 0A5D7D7A135E37CB00D13E53 /* squeak_interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CDE135E37CB00D13E53 /* squeak_interpreter.cpp */; }; 0A5D7D7B135E37CB00D13E53 /* abstract_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CE1135E37CB00D13E53 /* abstract_message.cpp */; }; 0A5D7D7C135E37CB00D13E53 /* deferred_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CE3135E37CB00D13E53 /* deferred_request.cpp */; }; 0A5D7D7D135E37CB00D13E53 /* interactions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CE5135E37CB00D13E53 /* interactions.cpp */; }; 0A5D7D7E135E37CB00D13E53 /* interpreter_subset_for_control_transfer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CE7135E37CB00D13E53 /* interpreter_subset_for_control_transfer.cpp */; }; 0A5D7D7F135E37CB00D13E53 /* message_classes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CE9135E37CB00D13E53 /* message_classes.cpp */; }; 0A5D7D80135E37CB00D13E53 /* message_or_ack_request.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CEB135E37CB00D13E53 /* message_or_ack_request.cpp */; }; 0A5D7D81135E37CB00D13E53 /* message_statics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CED135E37CB00D13E53 /* message_statics.cpp */; }; 0A5D7D82135E37CB00D13E53 /* message_stats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CEF135E37CB00D13E53 /* message_stats.cpp */; }; 0A5D7D83135E37CB00D13E53 /* receive_marker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CF2135E37CB00D13E53 /* receive_marker.cpp */; }; 0A5D7D84135E37CB00D13E53 /* header_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CF7135E37CB00D13E53 /* header_type.cpp */; }; 0A5D7D85135E37CB00D13E53 /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CF9135E37CB00D13E53 /* object.cpp */; }; 0A5D7D86135E37CB00D13E53 /* process_field_locator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7CFF135E37CB00D13E53 /* process_field_locator.cpp */; }; 0A5D7D87135E37CB00D13E53 /* roots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D01135E37CB00D13E53 /* roots.cpp */; }; 0A5D7D88135E37CB00D13E53 /* oop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D07135E37CB00D13E53 /* oop.cpp */; }; 0A5D7D89135E37CB00D13E53 /* abstract_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D0F135E37CB00D13E53 /* abstract_os_interface.cpp */; }; 0A5D7D8A135E37CB00D13E53 /* dummy_cpu_coordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D13135E37CB00D13E53 /* dummy_cpu_coordinate.cpp */; }; 0A5D7D8B135E37CB00D13E53 /* ilib_message_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D15135E37CB00D13E53 /* ilib_message_queue.cpp */; }; 0A5D7D8C135E37CB00D13E53 /* ilib_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D17135E37CB00D13E53 /* ilib_os_interface.cpp */; }; 0A5D7D8D135E37CB00D13E53 /* logical_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D19135E37CB00D13E53 /* logical_core.cpp */; }; 0A5D7D8E135E37CB00D13E53 /* osx_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D1E135E37CB00D13E53 /* osx_os_interface.cpp */; }; 0A5D7D8F135E37CB00D13E53 /* posix_os_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D20135E37CB00D13E53 /* posix_os_interface.cpp */; }; 0A5D7D90135E37CB00D13E53 /* process_memory_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D22135E37CB00D13E53 /* process_memory_semantics.cpp */; }; 0A5D7D91135E37CB00D13E53 /* shared_memory_message_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D24135E37CB00D13E53 /* shared_memory_message_queue.cpp */; }; 0A5D7D92135E37CB00D13E53 /* shared_memory_message_queue_per_sender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D26135E37CB00D13E53 /* shared_memory_message_queue_per_sender.cpp */; }; 0A5D7D93135E37CB00D13E53 /* thread_memory_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D28135E37CB00D13E53 /* thread_memory_semantics.cpp */; }; 0A5D7D94135E37CB00D13E53 /* tile_cpu_coordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D2A135E37CB00D13E53 /* tile_cpu_coordinate.cpp */; }; 0A5D7D95135E37CB00D13E53 /* RVMPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D2D135E37CB00D13E53 /* RVMPlugin.cpp */; }; 0A5D7D96135E37CB00D13E53 /* abstract_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D30135E37CB00D13E53 /* abstract_mutex.cpp */; }; 0A5D7D97135E37CB00D13E53 /* abstract_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D32135E37CB00D13E53 /* abstract_tracer.cpp */; }; 0A5D7D98135E37CB00D13E53 /* bytemap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D34135E37CB00D13E53 /* bytemap.cpp */; }; 0A5D7D99135E37CB00D13E53 /* core_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D36135E37CB00D13E53 /* core_tracer.cpp */; }; 0A5D7D9A135E37CB00D13E53 /* debug_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D38135E37CB00D13E53 /* debug_helper.cpp */; }; 0A5D7D9C135E37CB00D13E53 /* error_handling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D3D135E37CB00D13E53 /* error_handling.cpp */; }; 0A5D7D9D135E37CB00D13E53 /* execution_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D3F135E37CB00D13E53 /* execution_tracer.cpp */; }; 0A5D7D9E135E37CB00D13E53 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D42135E37CB00D13E53 /* main.cpp */; }; 0A5D7D9F135E37CB00D13E53 /* measurements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D43135E37CB00D13E53 /* measurements.cpp */; }; 0A5D7DA0135E37CB00D13E53 /* my_rank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D45135E37CB00D13E53 /* my_rank.cpp */; }; 0A5D7DA1135E37CB00D13E53 /* oop_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D47135E37CB00D13E53 /* oop_tracer.cpp */; }; 0A5D7DA2135E37CB00D13E53 /* printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D49135E37CB00D13E53 /* printer.cpp */; }; 0A5D7DA3135E37CB00D13E53 /* profiling_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D4B135E37CB00D13E53 /* profiling_tracer.cpp */; }; 0A5D7DA4135E37CB00D13E53 /* rank_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D4D135E37CB00D13E53 /* rank_set.cpp */; }; 0A5D7DA5135E37CB00D13E53 /* rvm_bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D50135E37CB00D13E53 /* rvm_bitmap.cpp */; }; 0A5D7DA6135E37CB00D13E53 /* rvm_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D52135E37CB00D13E53 /* rvm_config.cpp */; }; 0A5D7DA7135E37CB00D13E53 /* safepoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D54135E37CB00D13E53 /* safepoint.cpp */; }; 0A5D7DA8135E37CB00D13E53 /* safepoint_ability.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D56135E37CB00D13E53 /* safepoint_ability.cpp */; }; 0A5D7DA9135E37CB00D13E53 /* safepoint_request_queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D58135E37CB00D13E53 /* safepoint_request_queue.cpp */; }; 0A5D7DAA135E37CB00D13E53 /* scheduler_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D5A135E37CB00D13E53 /* scheduler_mutex.cpp */; }; 0A5D7DAB135E37CB00D13E53 /* semaphore_mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D5C135E37CB00D13E53 /* semaphore_mutex.cpp */; }; 0A5D7DAC135E37CB00D13E53 /* squeak_adapters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D5E135E37CB00D13E53 /* squeak_adapters.cpp */; }; 0A5D7DAD135E37CB00D13E53 /* timeout_deferral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D60135E37CB00D13E53 /* timeout_deferral.cpp */; }; 0A5D7DAE135E37CB00D13E53 /* timeout_timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D62135E37CB00D13E53 /* timeout_timer.cpp */; }; 0A5D7DAF135E37CB00D13E53 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D7D66135E37CB00D13E53 /* utils.cpp */; }; 0A890E9A13FDA46400067C04 /* Squeak72x72.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A890E9913FDA46400067C04 /* Squeak72x72.png */; }; 0AA32BAA135EC5EE00B97FB8 /* sqFilePluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B32135EC5EE00B97FB8 /* sqFilePluginBasicPrims.c */; }; 0AA32BAB135EC5EE00B97FB8 /* Error.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B38135EC5EE00B97FB8 /* Error.c */; }; 0AA32BAC135EC5EE00B97FB8 /* jcapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B39135EC5EE00B97FB8 /* jcapimin.c */; }; 0AA32BAD135EC5EE00B97FB8 /* jcapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B3A135EC5EE00B97FB8 /* jcapistd.c */; }; 0AA32BAE135EC5EE00B97FB8 /* jccoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B3B135EC5EE00B97FB8 /* jccoefct.c */; }; 0AA32BAF135EC5EE00B97FB8 /* jccolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B3C135EC5EE00B97FB8 /* jccolor.c */; }; 0AA32BB0135EC5EE00B97FB8 /* jcdctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B3D135EC5EE00B97FB8 /* jcdctmgr.c */; }; 0AA32BB1135EC5EE00B97FB8 /* jchuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B3E135EC5EE00B97FB8 /* jchuff.c */; }; 0AA32BB2135EC5EE00B97FB8 /* jcinit.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B40135EC5EE00B97FB8 /* jcinit.c */; }; 0AA32BB3135EC5EE00B97FB8 /* jcmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B41135EC5EE00B97FB8 /* jcmainct.c */; }; 0AA32BB4135EC5EE00B97FB8 /* jcmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B42135EC5EE00B97FB8 /* jcmarker.c */; }; 0AA32BB5135EC5EE00B97FB8 /* jcmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B43135EC5EE00B97FB8 /* jcmaster.c */; }; 0AA32BB6135EC5EE00B97FB8 /* jcomapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B44135EC5EE00B97FB8 /* jcomapi.c */; }; 0AA32BB7135EC5EE00B97FB8 /* jcparam.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B46135EC5EE00B97FB8 /* jcparam.c */; }; 0AA32BB8135EC5EE00B97FB8 /* jcphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B47135EC5EE00B97FB8 /* jcphuff.c */; }; 0AA32BB9135EC5EE00B97FB8 /* jcprepct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B48135EC5EE00B97FB8 /* jcprepct.c */; }; 0AA32BBA135EC5EE00B97FB8 /* jcsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B49135EC5EE00B97FB8 /* jcsample.c */; }; 0AA32BBB135EC5EE00B97FB8 /* jctrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4A135EC5EE00B97FB8 /* jctrans.c */; }; 0AA32BBC135EC5EE00B97FB8 /* jdapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4B135EC5EE00B97FB8 /* jdapimin.c */; }; 0AA32BBD135EC5EE00B97FB8 /* jdapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4C135EC5EE00B97FB8 /* jdapistd.c */; }; 0AA32BBE135EC5EE00B97FB8 /* jdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4D135EC5EE00B97FB8 /* jdatadst.c */; }; 0AA32BBF135EC5EE00B97FB8 /* jdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4E135EC5EE00B97FB8 /* jdatasrc.c */; }; 0AA32BC0135EC5EE00B97FB8 /* jdcoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B4F135EC5EE00B97FB8 /* jdcoefct.c */; }; 0AA32BC1135EC5EE00B97FB8 /* jdcolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B50135EC5EE00B97FB8 /* jdcolor.c */; }; 0AA32BC2135EC5EE00B97FB8 /* jddctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B52135EC5EE00B97FB8 /* jddctmgr.c */; }; 0AA32BC3135EC5EE00B97FB8 /* jdhuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B53135EC5EE00B97FB8 /* jdhuff.c */; }; 0AA32BC4135EC5EE00B97FB8 /* jdinput.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B55135EC5EE00B97FB8 /* jdinput.c */; }; 0AA32BC5135EC5EE00B97FB8 /* jdmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B56135EC5EE00B97FB8 /* jdmainct.c */; }; 0AA32BC6135EC5EE00B97FB8 /* jdmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B57135EC5EE00B97FB8 /* jdmarker.c */; }; 0AA32BC7135EC5EE00B97FB8 /* jdmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B58135EC5EE00B97FB8 /* jdmaster.c */; }; 0AA32BC8135EC5EE00B97FB8 /* jdmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B59135EC5EE00B97FB8 /* jdmerge.c */; }; 0AA32BC9135EC5EE00B97FB8 /* jdphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B5A135EC5EE00B97FB8 /* jdphuff.c */; }; 0AA32BCA135EC5EE00B97FB8 /* jdpostct.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B5B135EC5EE00B97FB8 /* jdpostct.c */; }; 0AA32BCB135EC5EE00B97FB8 /* jdsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B5C135EC5EE00B97FB8 /* jdsample.c */; }; 0AA32BCC135EC5EE00B97FB8 /* jdtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B5D135EC5EE00B97FB8 /* jdtrans.c */; }; 0AA32BCD135EC5EE00B97FB8 /* jerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B5E135EC5EE00B97FB8 /* jerror.c */; }; 0AA32BCE135EC5EE00B97FB8 /* jfdctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B60135EC5EE00B97FB8 /* jfdctflt.c */; }; 0AA32BCF135EC5EE00B97FB8 /* jfdctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B61135EC5EE00B97FB8 /* jfdctfst.c */; }; 0AA32BD0135EC5EE00B97FB8 /* jfdctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B62135EC5EE00B97FB8 /* jfdctint.c */; }; 0AA32BD1135EC5EE00B97FB8 /* jidctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B63135EC5EE00B97FB8 /* jidctflt.c */; }; 0AA32BD2135EC5EE00B97FB8 /* jidctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B64135EC5EE00B97FB8 /* jidctfst.c */; }; 0AA32BD3135EC5EE00B97FB8 /* jidctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B65135EC5EE00B97FB8 /* jidctint.c */; }; 0AA32BD4135EC5EE00B97FB8 /* jidctred.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B66135EC5EE00B97FB8 /* jidctred.c */; }; 0AA32BD5135EC5EE00B97FB8 /* jmemdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B68135EC5EE00B97FB8 /* jmemdatadst.c */; }; 0AA32BD6135EC5EE00B97FB8 /* jmemdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B69135EC5EE00B97FB8 /* jmemdatasrc.c */; }; 0AA32BD7135EC5EE00B97FB8 /* jmemmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B6A135EC5EE00B97FB8 /* jmemmgr.c */; }; 0AA32BD8135EC5EE00B97FB8 /* jmemnobs.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B6B135EC5EE00B97FB8 /* jmemnobs.c */; }; 0AA32BD9135EC5EE00B97FB8 /* jquant1.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B71135EC5EE00B97FB8 /* jquant1.c */; }; 0AA32BDA135EC5EE00B97FB8 /* jquant2.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B72135EC5EE00B97FB8 /* jquant2.c */; }; 0AA32BDB135EC5EE00B97FB8 /* jutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B73135EC5EE00B97FB8 /* jutils.c */; }; 0AA32BDC135EC5EE00B97FB8 /* ReadMe.txt in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32B75135EC5EE00B97FB8 /* ReadMe.txt */; }; 0AA32BDD135EC5EE00B97FB8 /* chartables.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B7F135EC5EE00B97FB8 /* chartables.c */; }; 0AA32BDE135EC5EE00B97FB8 /* get.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B81135EC5EE00B97FB8 /* get.c */; }; 0AA32BDF135EC5EE00B97FB8 /* pcre.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B84135EC5EE00B97FB8 /* pcre.c */; }; 0AA32BE0135EC5EE00B97FB8 /* RePlugin3-Fixes.1.cs in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32B87135EC5EE00B97FB8 /* RePlugin3-Fixes.1.cs */; }; 0AA32BE1135EC5EE00B97FB8 /* RePlugin3-Fixes2.1.cs in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32B88135EC5EE00B97FB8 /* RePlugin3-Fixes2.1.cs */; }; 0AA32BE2135EC5EE00B97FB8 /* RePlugin3.3.1.cs in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32B89135EC5EE00B97FB8 /* RePlugin3.3.1.cs */; }; 0AA32BE3135EC5EE00B97FB8 /* study.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B8A135EC5EE00B97FB8 /* study.c */; }; 0AA32BE4135EC5EE00B97FB8 /* SocketPrims.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32B8F135EC5EE00B97FB8 /* SocketPrims.pdf */; }; 0AA32BE5135EC5EE00B97FB8 /* sqSoundCodecPluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B92135EC5EE00B97FB8 /* sqSoundCodecPluginBasicPrims.c */; }; 0AA32BE6135EC5EE00B97FB8 /* b3dAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B99135EC5EE00B97FB8 /* b3dAlloc.c */; }; 0AA32BE7135EC5EE00B97FB8 /* b3dDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B9B135EC5EE00B97FB8 /* b3dDraw.c */; }; 0AA32BE8135EC5EE00B97FB8 /* b3dInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B9C135EC5EE00B97FB8 /* b3dInit.c */; }; 0AA32BE9135EC5EE00B97FB8 /* b3dMain.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B9D135EC5EE00B97FB8 /* b3dMain.c */; }; 0AA32BEA135EC5EE00B97FB8 /* b3dRemap.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32B9E135EC5EE00B97FB8 /* b3dRemap.c */; }; 0AA32BEB135EC5EE00B97FB8 /* sqManualSurface.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BA2135EC5EE00B97FB8 /* sqManualSurface.c */; }; 0AA32BEC135EC5EE00B97FB8 /* SurfacePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BA6135EC5EE00B97FB8 /* SurfacePlugin.c */; }; 0AA32BF2135EC61300B97FB8 /* sqNamedPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BF0135EC61300B97FB8 /* sqNamedPrims.c */; }; 0AA32BF3135EC61300B97FB8 /* sqVirtualMachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BF1135EC61300B97FB8 /* sqVirtualMachine.c */; }; 0AA32C00135EC69F00B97FB8 /* drawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BF7135EC69F00B97FB8 /* drawing.m */; }; 0AA32C01135EC69F00B97FB8 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32BF8135EC69F00B97FB8 /* Info.plist */; }; 0AA32C02135EC69F00B97FB8 /* PDColoredProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BFA135EC69F00B97FB8 /* PDColoredProgressView.m */; }; 0AA32C03135EC69F00B97FB8 /* SqueakObjectiveC.xcodeproj.zip in Resources */ = {isa = PBXBuildFile; fileRef = 0AA32BFB135EC69F00B97FB8 /* SqueakObjectiveC.xcodeproj.zip */; }; 0AA32C04135EC69F00B97FB8 /* squeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BFD135EC69F00B97FB8 /* squeakProxy.m */; }; 0AA32C05135EC69F00B97FB8 /* squeakSUnitTester.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32BFF135EC69F00B97FB8 /* squeakSUnitTester.m */; }; 0AA32C0B135EC6D900B97FB8 /* sqUnixAsynchFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C09135EC6D900B97FB8 /* sqUnixAsynchFile.c */; }; 0AA32C0F135EC6F400B97FB8 /* dummyFFI.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C0D135EC6F400B97FB8 /* dummyFFI.c */; }; 0AA32C17135EC70F00B97FB8 /* sqMacSecurity.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C11135EC70F00B97FB8 /* sqMacSecurity.c */; }; 0AA32C18135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C14135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.m */; }; 0AA32C19135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C16135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.m */; }; 0AA32C7B135ECFDD00B97FB8 /* sqUnixExternalPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AA32C1B135EC76600B97FB8 /* sqUnixExternalPrims.c */; }; 0ABEA92513C26C7A003108B9 /* gc_debugging_tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0ABEA92313C26C7A003108B9 /* gc_debugging_tracer.cpp */; }; 0ADE8A8F135F38B200D37EAD /* AsynchFilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A7C135F38B200D37EAD /* AsynchFilePlugin.c */; }; 0ADE8A90135F38B200D37EAD /* B2DPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A7E135F38B200D37EAD /* B2DPlugin.c */; }; 0ADE8A91135F38B200D37EAD /* BitBltPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A80135F38B200D37EAD /* BitBltPlugin.c */; }; 0ADE8A92135F38B200D37EAD /* BMPReadWriterPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A82135F38B200D37EAD /* BMPReadWriterPlugin.c */; }; 0ADE8A93135F38B200D37EAD /* DSAPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A84135F38B200D37EAD /* DSAPrims.c */; }; 0ADE8A94135F38B200D37EAD /* FFTPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A86135F38B200D37EAD /* FFTPlugin.c */; }; 0ADE8A95135F38B200D37EAD /* FilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A88135F38B200D37EAD /* FilePlugin.c */; }; 0ADE8A96135F38B200D37EAD /* FloatArrayPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A8A135F38B200D37EAD /* FloatArrayPlugin.c */; }; 0ADE8A97135F38B200D37EAD /* GeniePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A8C135F38B200D37EAD /* GeniePlugin.c */; }; 0ADE8A98135F38B200D37EAD /* HostWindowPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A8E135F38B200D37EAD /* HostWindowPlugin.c */; }; 0ADE8AB5135F38FE00D37EAD /* JPEGReaderPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A9A135F38FE00D37EAD /* JPEGReaderPlugin.c */; }; 0ADE8AB6135F38FE00D37EAD /* JPEGReadWriter2Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A9C135F38FE00D37EAD /* JPEGReadWriter2Plugin.c */; }; 0ADE8AB7135F38FE00D37EAD /* Klatt.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8A9E135F38FE00D37EAD /* Klatt.c */; }; 0ADE8AB8135F38FE00D37EAD /* LargeIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AA0135F38FE00D37EAD /* LargeIntegers.c */; }; 0ADE8AB9135F38FE00D37EAD /* Matrix2x3Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AA2135F38FE00D37EAD /* Matrix2x3Plugin.c */; }; 0ADE8ABA135F38FE00D37EAD /* MiscPrimitivePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AA4135F38FE00D37EAD /* MiscPrimitivePlugin.c */; }; 0ADE8ABB135F38FE00D37EAD /* ObjectiveCPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AA6135F38FE00D37EAD /* ObjectiveCPlugin.c */; }; 0ADE8ABC135F38FE00D37EAD /* RePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AA8135F38FE00D37EAD /* RePlugin.c */; }; 0ADE8ABD135F38FE00D37EAD /* SecurityPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AAA135F38FE00D37EAD /* SecurityPlugin.c */; }; 0ADE8ABE135F38FE00D37EAD /* SocketPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AAC135F38FE00D37EAD /* SocketPlugin.c */; }; 0ADE8ABF135F38FE00D37EAD /* SoundCodecPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AAE135F38FE00D37EAD /* SoundCodecPrims.c */; }; 0ADE8AC0135F38FE00D37EAD /* SoundGenerationPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AB0135F38FE00D37EAD /* SoundGenerationPlugin.c */; }; 0ADE8AC1135F38FE00D37EAD /* SoundPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AB2135F38FE00D37EAD /* SoundPlugin.c */; }; 0ADE8AC2135F38FE00D37EAD /* Squeak3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AB4135F38FE00D37EAD /* Squeak3D.c */; }; 0ADE8ACC135F392E00D37EAD /* StarSqueakPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AC6135F392E00D37EAD /* StarSqueakPlugin.c */; }; 0ADE8ACD135F392E00D37EAD /* UUIDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8AC8135F392E00D37EAD /* UUIDPlugin.c */; }; 0ADE8ACE135F392E00D37EAD /* ZipPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 0ADE8ACA135F392E00D37EAD /* ZipPlugin.c */; }; 0ADE8ACF135F399D00D37EAD /* sqUnixSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 940BE57B1239F10000674A11 /* SqueakUIViewCALayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 940BE57A1239F10000674A11 /* SqueakUIViewCALayer.m */; }; 940BE5E91239F50100674A11 /* SqueakUIViewOpenGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 940BE5E81239F50100674A11 /* SqueakUIViewOpenGL.m */; }; 940BE5F91239F70D00674A11 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 940BE5F81239F70D00674A11 /* OpenGLES.framework */; }; 9412CAB30E6C037B00DB8625 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 9412CAB20E6C037B00DB8625 /* Settings.bundle */; }; 9412CAE60E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */; }; 9424FF760DDCB271009912BF /* osExports.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF750DDCB271009912BF /* osExports.c */; }; 942F75D30E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */; }; 942F76320E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */; }; 9452D5E50E044A9D000AD792 /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D80E044A9D000AD792 /* Queue.m */; }; 9452D5E60E044A9D000AD792 /* sqMacV2Time.c in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */; }; 9452D5E70E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */; }; 9452D5E80E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; }; 9452D5E90E044A9D000AD792 /* sqSqueakMainApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */; }; 9452D5EA0E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */; }; 9452D5EB0E044A9D000AD792 /* sqSqueakMainApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */; }; 9452D6030E044CB3000AD792 /* sqSqueakAttributesAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */; }; 9452D6080E044D2F000AD792 /* sqSqueakEventsAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */; }; 945550010DF1BC6A00FB176B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 945550000DF1BC6A00FB176B /* AudioToolbox.framework */; }; 94577FBD10684D5E0020840A /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FBC10684D5E0020840A /* CoreAudio.framework */; }; 94577FBF10684D5E0020840A /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FBE10684D5E0020840A /* CoreLocation.framework */; }; 94577FC510684D7E0020840A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FC410684D7E0020840A /* SystemConfiguration.framework */; }; 9458525610F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; }; 9458525C10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */; }; 945C95FF0E97084C00529DC1 /* aio.c in Sources */ = {isa = PBXBuildFile; fileRef = 94883B2A0E0C2A5E005A4738 /* aio.c */; }; 9471D2730E04703B00703D45 /* sqSqueakScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */; }; 9471D2E10E04743F00703D45 /* sqSqueakAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; }; 9484F8DB10B0E09B0038BDC0 /* sqiPhoneScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */; }; 9484F8DC10B0E0C60038BDC0 /* sqSqueakIPhoneApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */; }; 9484F8DD10B0E0C70038BDC0 /* sqSqueakIPhoneApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */; }; 9484F8DE10B0E0C90038BDC0 /* sqSqueakIPhoneApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */; }; 9484F8DF10B0E0CB0038BDC0 /* sqSqueakIPhoneApplication+Network.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */; }; 9484F8E010B0E0CE0038BDC0 /* sqSqueakiPhoneApplication+sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */; }; 9484F8E110B0E0CE0038BDC0 /* sqSqueakIPhoneApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */; }; 9484F8E210B0E0D10038BDC0 /* sqSqueakIPhoneFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */; }; 9484F8E310B0E0D30038BDC0 /* sqSqueakIPhoneInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */; }; 9484F8E410B0E0ED0038BDC0 /* Squeak.png in Resources */ = {isa = PBXBuildFile; fileRef = 94F3A9690E6BFA7C00E0B12A /* Squeak.png */; }; 9484F8E510B0E0F00038BDC0 /* SqueakNoOGLIPhoneAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */; }; 9484F8E610B0E0FD0038BDC0 /* SqueakUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */; }; 9484F8E710B0E0FE0038BDC0 /* SqueakUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; }; 9484F8E810B0E1050038BDC0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 9484F8EF10B0E1580038BDC0 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 945550910DF2041100FB176B /* Default.png */; }; 9484F99010B13D470038BDC0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; }; 9484F9AF10B13DA50038BDC0 /* sqMacHostWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */; }; 948EC3901155312600B08A4F /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */; }; 94A0E8850DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */; }; 94A0E9840DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */; }; 94A1B0070E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */; }; 94A1B02D0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */; }; 94A1B0320E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */; }; 94A3488E0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */; }; 94B6E9DD10BC777A00333E9E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94B6E9DC10BC777A00333E9E /* Localizable.strings */; }; 94BCE78C0DDDF61200F38F31 /* sqUnixUUID.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */; }; 94D2A24C112B8ED000B6E459 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94C208F810AF7262002F4160 /* QuartzCore.framework */; }; BC6CC8E9134B045100B9B2B0 /* RoarVMMouseEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6CC8E8134B045100B9B2B0 /* RoarVMMouseEvent.m */; }; BC6CC8ED134B138300B9B2B0 /* RoarVMSwipeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6CC8EC134B138300B9B2B0 /* RoarVMSwipeEvent.m */; }; BC82F912135697D000EC2309 /* UIGestureRecognizer+RoarVMEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = BC82F911135697CE00EC2309 /* UIGestureRecognizer+RoarVMEvents.m */; }; BC82F9151356A4C400EC2309 /* RoarVMMouseUpEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = BC82F9141356A4C300EC2309 /* RoarVMMouseUpEvent.m */; }; BCAB989D134B0139004AB528 /* RoarVMAbstractEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = BCAB989C134B0139004AB528 /* RoarVMAbstractEvent.m */; }; BCCC348E1349603100063417 /* Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = BCCC348D1349603100063417 /* Entitlements.plist */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0A040E2013B7526D007E172E /* performance_counters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = performance_counters.cpp; sourceTree = "<group>"; }; 0A040E2113B7526D007E172E /* performance_counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = performance_counters.h; sourceTree = "<group>"; }; 0A4EFFD913317C0D004BC399 /* iPhone.changes */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = iPhone.changes; path = iPhone/iPhone.changes; sourceTree = "<group>"; }; 0A4EFFDA13317C0D004BC399 /* iPhone.image */ = {isa = PBXFileReference; lastKnownFileType = file; name = iPhone.image; path = iPhone/iPhone.image; sourceTree = "<group>"; }; 0A4EFFDB13317C0D004BC399 /* SqueakV3-minimum-MVC.sources */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "SqueakV3-minimum-MVC.sources"; path = "iPhone/SqueakV3-minimum-MVC.sources"; sourceTree = "<group>"; }; 0A5D7CAA135E37A900D13E53 /* externals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = externals.cpp; sourceTree = "<group>"; }; 0A5D7CAB135E37A900D13E53 /* externals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = externals.h; sourceTree = "<group>"; }; 0A5D7CAF135E37CB00D13E53 /* abstract_mark_sweep_collector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_mark_sweep_collector.cpp; sourceTree = "<group>"; }; 0A5D7CB0135E37CB00D13E53 /* abstract_mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_mark_sweep_collector.h; sourceTree = "<group>"; }; 0A5D7CB1135E37CB00D13E53 /* abstract_object_heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_object_heap.cpp; sourceTree = "<group>"; }; 0A5D7CB2135E37CB00D13E53 /* abstract_object_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_heap.h; sourceTree = "<group>"; }; 0A5D7CB3135E37CB00D13E53 /* abstract_object_heap.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_heap.inline.h; sourceTree = "<group>"; }; 0A5D7CB4135E37CB00D13E53 /* abstract_object_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_object_table.h; sourceTree = "<group>"; }; 0A5D7CB5135E37CB00D13E53 /* gc_oop_stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gc_oop_stack.h; sourceTree = "<group>"; }; 0A5D7CB6135E37CB00D13E53 /* indirect_oop_mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indirect_oop_mark_sweep_collector.h; sourceTree = "<group>"; }; 0A5D7CB7135E37CB00D13E53 /* mark_sweep_collector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mark_sweep_collector.h; sourceTree = "<group>"; }; 0A5D7CB8135E37CB00D13E53 /* memory_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_system.cpp; sourceTree = "<group>"; }; 0A5D7CB9135E37CB00D13E53 /* memory_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_system.h; sourceTree = "<group>"; }; 0A5D7CBA135E37CB00D13E53 /* memory_system.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_system.inline.h; sourceTree = "<group>"; }; 0A5D7CBB135E37CB00D13E53 /* multicore_object_heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multicore_object_heap.cpp; sourceTree = "<group>"; }; 0A5D7CBC135E37CB00D13E53 /* multicore_object_heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_heap.h; sourceTree = "<group>"; }; 0A5D7CBD135E37CB00D13E53 /* multicore_object_heap.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_heap.inline.h; sourceTree = "<group>"; }; 0A5D7CBE135E37CB00D13E53 /* multicore_object_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multicore_object_table.cpp; sourceTree = "<group>"; }; 0A5D7CBF135E37CB00D13E53 /* multicore_object_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_table.h; sourceTree = "<group>"; }; 0A5D7CC0135E37CB00D13E53 /* multicore_object_table.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multicore_object_table.inline.h; sourceTree = "<group>"; }; 0A5D7CC1135E37CB00D13E53 /* oop_closure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop_closure.h; sourceTree = "<group>"; }; 0A5D7CCB135E37CB00D13E53 /* squeak_image_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_image_reader.cpp; sourceTree = "<group>"; }; 0A5D7CCC135E37CB00D13E53 /* squeak_image_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_image_reader.h; sourceTree = "<group>"; }; 0A5D7CCE135E37CB00D13E53 /* abstract_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_primitive_table.h; sourceTree = "<group>"; }; 0A5D7CCF135E37CB00D13E53 /* at_cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = at_cache.cpp; sourceTree = "<group>"; }; 0A5D7CD0135E37CB00D13E53 /* at_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at_cache.h; sourceTree = "<group>"; }; 0A5D7CD1135E37CB00D13E53 /* external_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = external_primitive_table.h; sourceTree = "<group>"; }; 0A5D7CD2135E37CB00D13E53 /* interpreter_bytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_bytecodes.cpp; sourceTree = "<group>"; }; 0A5D7CD3135E37CB00D13E53 /* interpreter_bytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_bytecodes.h; sourceTree = "<group>"; }; 0A5D7CD4135E37CB00D13E53 /* interpreter_primitives.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_primitives.cpp; sourceTree = "<group>"; }; 0A5D7CD5135E37CB00D13E53 /* interpreter_primitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_primitives.h; sourceTree = "<group>"; }; 0A5D7CD6135E37CB00D13E53 /* method_cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = method_cache.cpp; sourceTree = "<group>"; }; 0A5D7CD7135E37CB00D13E53 /* method_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = method_cache.h; sourceTree = "<group>"; }; 0A5D7CD8135E37CB00D13E53 /* obsolete_indexed_primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = obsolete_indexed_primitive_table.cpp; sourceTree = "<group>"; }; 0A5D7CD9135E37CB00D13E53 /* obsolete_indexed_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = obsolete_indexed_primitive_table.h; sourceTree = "<group>"; }; 0A5D7CDA135E37CB00D13E53 /* obsolete_named_primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = obsolete_named_primitive_table.cpp; sourceTree = "<group>"; }; 0A5D7CDB135E37CB00D13E53 /* obsolete_named_primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = obsolete_named_primitive_table.h; sourceTree = "<group>"; }; 0A5D7CDC135E37CB00D13E53 /* primitive_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = primitive_table.cpp; sourceTree = "<group>"; }; 0A5D7CDD135E37CB00D13E53 /* primitive_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = primitive_table.h; sourceTree = "<group>"; }; 0A5D7CDE135E37CB00D13E53 /* squeak_interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_interpreter.cpp; sourceTree = "<group>"; }; 0A5D7CDF135E37CB00D13E53 /* squeak_interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_interpreter.h; sourceTree = "<group>"; }; 0A5D7CE1135E37CB00D13E53 /* abstract_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_message.cpp; sourceTree = "<group>"; }; 0A5D7CE2135E37CB00D13E53 /* abstract_message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_message.h; sourceTree = "<group>"; }; 0A5D7CE3135E37CB00D13E53 /* deferred_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deferred_request.cpp; sourceTree = "<group>"; }; 0A5D7CE4135E37CB00D13E53 /* deferred_request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deferred_request.h; sourceTree = "<group>"; }; 0A5D7CE5135E37CB00D13E53 /* interactions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interactions.cpp; sourceTree = "<group>"; }; 0A5D7CE6135E37CB00D13E53 /* interactions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interactions.h; sourceTree = "<group>"; }; 0A5D7CE7135E37CB00D13E53 /* interpreter_subset_for_control_transfer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_subset_for_control_transfer.cpp; sourceTree = "<group>"; }; 0A5D7CE8135E37CB00D13E53 /* interpreter_subset_for_control_transfer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_subset_for_control_transfer.h; sourceTree = "<group>"; }; 0A5D7CE9135E37CB00D13E53 /* message_classes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_classes.cpp; sourceTree = "<group>"; }; 0A5D7CEA135E37CB00D13E53 /* message_classes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_classes.h; sourceTree = "<group>"; }; 0A5D7CEB135E37CB00D13E53 /* message_or_ack_request.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_or_ack_request.cpp; sourceTree = "<group>"; }; 0A5D7CEC135E37CB00D13E53 /* message_or_ack_request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_or_ack_request.h; sourceTree = "<group>"; }; 0A5D7CED135E37CB00D13E53 /* message_statics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_statics.cpp; sourceTree = "<group>"; }; 0A5D7CEE135E37CB00D13E53 /* message_statics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_statics.h; sourceTree = "<group>"; }; 0A5D7CEF135E37CB00D13E53 /* message_stats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message_stats.cpp; sourceTree = "<group>"; }; 0A5D7CF0135E37CB00D13E53 /* message_stats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_stats.h; sourceTree = "<group>"; }; 0A5D7CF1135E37CB00D13E53 /* message_templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_templates.h; sourceTree = "<group>"; }; 0A5D7CF2135E37CB00D13E53 /* receive_marker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = receive_marker.cpp; sourceTree = "<group>"; }; 0A5D7CF3135E37CB00D13E53 /* receive_marker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = receive_marker.h; sourceTree = "<group>"; }; 0A5D7CF5135E37CB00D13E53 /* chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chunk.h; sourceTree = "<group>"; }; 0A5D7CF6135E37CB00D13E53 /* chunk.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chunk.inline.h; sourceTree = "<group>"; }; 0A5D7CF7135E37CB00D13E53 /* header_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = header_type.cpp; sourceTree = "<group>"; }; 0A5D7CF8135E37CB00D13E53 /* header_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = header_type.h; sourceTree = "<group>"; }; 0A5D7CF9135E37CB00D13E53 /* object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = object.cpp; sourceTree = "<group>"; }; 0A5D7CFA135E37CB00D13E53 /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.h; sourceTree = "<group>"; }; 0A5D7CFB135E37CB00D13E53 /* object.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.inline.h; sourceTree = "<group>"; }; 0A5D7CFC135E37CB00D13E53 /* object_indices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object_indices.h; sourceTree = "<group>"; }; 0A5D7CFD135E37CB00D13E53 /* object_p.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object_p.h; sourceTree = "<group>"; }; 0A5D7CFE135E37CB00D13E53 /* preheader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preheader.h; sourceTree = "<group>"; }; 0A5D7CFF135E37CB00D13E53 /* process_field_locator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = process_field_locator.cpp; sourceTree = "<group>"; }; 0A5D7D00135E37CB00D13E53 /* process_field_locator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process_field_locator.h; sourceTree = "<group>"; }; 0A5D7D01135E37CB00D13E53 /* roots.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = roots.cpp; sourceTree = "<group>"; }; 0A5D7D02135E37CB00D13E53 /* roots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = roots.h; sourceTree = "<group>"; }; 0A5D7D03135E37CB00D13E53 /* special_indices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = special_indices.h; sourceTree = "<group>"; }; 0A5D7D04135E37CB00D13E53 /* word_containing_object_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = word_containing_object_type.h; sourceTree = "<group>"; }; 0A5D7D06135E37CB00D13E53 /* abstract_oop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_oop.h; sourceTree = "<group>"; }; 0A5D7D07135E37CB00D13E53 /* oop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oop.cpp; sourceTree = "<group>"; }; 0A5D7D08135E37CB00D13E53 /* oop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop.h; sourceTree = "<group>"; }; 0A5D7D09135E37CB00D13E53 /* oop.inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop.inline.h; sourceTree = "<group>"; }; 0A5D7D0A135E37CB00D13E53 /* tags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tags.h; sourceTree = "<group>"; }; 0A5D7D0C135E37CB00D13E53 /* abstract_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_cpu_coordinate.h; sourceTree = "<group>"; }; 0A5D7D0D135E37CB00D13E53 /* abstract_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_memory_semantics.h; sourceTree = "<group>"; }; 0A5D7D0E135E37CB00D13E53 /* abstract_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_message_queue.h; sourceTree = "<group>"; }; 0A5D7D0F135E37CB00D13E53 /* abstract_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_os_interface.cpp; sourceTree = "<group>"; }; 0A5D7D10135E37CB00D13E53 /* abstract_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_os_interface.h; sourceTree = "<group>"; }; 0A5D7D11135E37CB00D13E53 /* cacheline_aligned.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cacheline_aligned.h; sourceTree = "<group>"; }; 0A5D7D12135E37CB00D13E53 /* cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_coordinate.h; sourceTree = "<group>"; }; 0A5D7D13135E37CB00D13E53 /* dummy_cpu_coordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dummy_cpu_coordinate.cpp; sourceTree = "<group>"; }; 0A5D7D14135E37CB00D13E53 /* dummy_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummy_cpu_coordinate.h; sourceTree = "<group>"; }; 0A5D7D15135E37CB00D13E53 /* ilib_message_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ilib_message_queue.cpp; sourceTree = "<group>"; }; 0A5D7D16135E37CB00D13E53 /* ilib_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ilib_message_queue.h; sourceTree = "<group>"; }; 0A5D7D17135E37CB00D13E53 /* ilib_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ilib_os_interface.cpp; sourceTree = "<group>"; }; 0A5D7D18135E37CB00D13E53 /* ilib_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ilib_os_interface.h; sourceTree = "<group>"; }; 0A5D7D19135E37CB00D13E53 /* logical_core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logical_core.cpp; sourceTree = "<group>"; }; 0A5D7D1A135E37CB00D13E53 /* logical_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logical_core.h; sourceTree = "<group>"; }; 0A5D7D1B135E37CB00D13E53 /* memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_semantics.h; sourceTree = "<group>"; }; 0A5D7D1C135E37CB00D13E53 /* message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_queue.h; sourceTree = "<group>"; }; 0A5D7D1D135E37CB00D13E53 /* os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_interface.h; sourceTree = "<group>"; }; 0A5D7D1E135E37CB00D13E53 /* osx_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osx_os_interface.cpp; sourceTree = "<group>"; }; 0A5D7D1F135E37CB00D13E53 /* osx_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osx_os_interface.h; sourceTree = "<group>"; }; 0A5D7D20135E37CB00D13E53 /* posix_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = posix_os_interface.cpp; sourceTree = "<group>"; }; 0A5D7D21135E37CB00D13E53 /* posix_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = posix_os_interface.h; sourceTree = "<group>"; }; 0A5D7D22135E37CB00D13E53 /* process_memory_semantics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = process_memory_semantics.cpp; sourceTree = "<group>"; }; 0A5D7D23135E37CB00D13E53 /* process_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process_memory_semantics.h; sourceTree = "<group>"; }; 0A5D7D24135E37CB00D13E53 /* shared_memory_message_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_message_queue.cpp; sourceTree = "<group>"; }; 0A5D7D25135E37CB00D13E53 /* shared_memory_message_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_memory_message_queue.h; sourceTree = "<group>"; }; 0A5D7D26135E37CB00D13E53 /* shared_memory_message_queue_per_sender.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_message_queue_per_sender.cpp; sourceTree = "<group>"; }; 0A5D7D27135E37CB00D13E53 /* shared_memory_message_queue_per_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared_memory_message_queue_per_sender.h; sourceTree = "<group>"; }; 0A5D7D28135E37CB00D13E53 /* thread_memory_semantics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_memory_semantics.cpp; sourceTree = "<group>"; }; 0A5D7D29135E37CB00D13E53 /* thread_memory_semantics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread_memory_semantics.h; sourceTree = "<group>"; }; 0A5D7D2A135E37CB00D13E53 /* tile_cpu_coordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tile_cpu_coordinate.cpp; sourceTree = "<group>"; }; 0A5D7D2B135E37CB00D13E53 /* tile_cpu_coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tile_cpu_coordinate.h; sourceTree = "<group>"; }; 0A5D7D2D135E37CB00D13E53 /* RVMPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RVMPlugin.cpp; sourceTree = "<group>"; }; 0A5D7D2E135E37CB00D13E53 /* RVMPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RVMPlugin.h; sourceTree = "<group>"; }; 0A5D7D30135E37CB00D13E53 /* abstract_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_mutex.cpp; sourceTree = "<group>"; }; 0A5D7D31135E37CB00D13E53 /* abstract_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_mutex.h; sourceTree = "<group>"; }; 0A5D7D32135E37CB00D13E53 /* abstract_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_tracer.cpp; sourceTree = "<group>"; }; 0A5D7D33135E37CB00D13E53 /* abstract_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abstract_tracer.h; sourceTree = "<group>"; }; 0A5D7D34135E37CB00D13E53 /* bytemap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bytemap.cpp; sourceTree = "<group>"; }; 0A5D7D35135E37CB00D13E53 /* bytemap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytemap.h; sourceTree = "<group>"; }; 0A5D7D36135E37CB00D13E53 /* core_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core_tracer.cpp; sourceTree = "<group>"; }; 0A5D7D37135E37CB00D13E53 /* core_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core_tracer.h; sourceTree = "<group>"; }; 0A5D7D38135E37CB00D13E53 /* debug_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_helper.cpp; sourceTree = "<group>"; }; 0A5D7D39135E37CB00D13E53 /* debug_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_helper.h; sourceTree = "<group>"; }; 0A5D7D3A135E37CB00D13E53 /* debug_store_checks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_store_checks.h; sourceTree = "<group>"; }; 0A5D7D3D135E37CB00D13E53 /* error_handling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = error_handling.cpp; sourceTree = "<group>"; }; 0A5D7D3E135E37CB00D13E53 /* error_handling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error_handling.h; sourceTree = "<group>"; }; 0A5D7D3F135E37CB00D13E53 /* execution_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = execution_tracer.cpp; sourceTree = "<group>"; }; 0A5D7D40135E37CB00D13E53 /* execution_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = execution_tracer.h; sourceTree = "<group>"; }; 0A5D7D41135E37CB00D13E53 /* headers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = headers.h; sourceTree = "<group>"; }; 0A5D7D42135E37CB00D13E53 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; 0A5D7D43135E37CB00D13E53 /* measurements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = measurements.cpp; sourceTree = "<group>"; }; 0A5D7D44135E37CB00D13E53 /* measurements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = measurements.h; sourceTree = "<group>"; }; 0A5D7D45135E37CB00D13E53 /* my_rank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = my_rank.cpp; sourceTree = "<group>"; }; 0A5D7D46135E37CB00D13E53 /* my_rank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = my_rank.h; sourceTree = "<group>"; }; 0A5D7D47135E37CB00D13E53 /* oop_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oop_tracer.cpp; sourceTree = "<group>"; }; 0A5D7D48135E37CB00D13E53 /* oop_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oop_tracer.h; sourceTree = "<group>"; }; 0A5D7D49135E37CB00D13E53 /* printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = printer.cpp; sourceTree = "<group>"; }; 0A5D7D4A135E37CB00D13E53 /* printer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printer.h; sourceTree = "<group>"; }; 0A5D7D4B135E37CB00D13E53 /* profiling_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profiling_tracer.cpp; sourceTree = "<group>"; }; 0A5D7D4C135E37CB00D13E53 /* profiling_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profiling_tracer.h; sourceTree = "<group>"; }; 0A5D7D4D135E37CB00D13E53 /* rank_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rank_set.cpp; sourceTree = "<group>"; }; 0A5D7D4E135E37CB00D13E53 /* rank_set.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rank_set.h; sourceTree = "<group>"; }; 0A5D7D4F135E37CB00D13E53 /* runtime_tester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime_tester.h; sourceTree = "<group>"; }; 0A5D7D50135E37CB00D13E53 /* rvm_bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rvm_bitmap.cpp; sourceTree = "<group>"; }; 0A5D7D51135E37CB00D13E53 /* rvm_bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rvm_bitmap.h; sourceTree = "<group>"; }; 0A5D7D52135E37CB00D13E53 /* rvm_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rvm_config.cpp; sourceTree = "<group>"; }; 0A5D7D53135E37CB00D13E53 /* rvm_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rvm_config.h; sourceTree = "<group>"; }; 0A5D7D54135E37CB00D13E53 /* safepoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint.cpp; sourceTree = "<group>"; }; 0A5D7D55135E37CB00D13E53 /* safepoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint.h; sourceTree = "<group>"; }; 0A5D7D56135E37CB00D13E53 /* safepoint_ability.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint_ability.cpp; sourceTree = "<group>"; }; 0A5D7D57135E37CB00D13E53 /* safepoint_ability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint_ability.h; sourceTree = "<group>"; }; 0A5D7D58135E37CB00D13E53 /* safepoint_request_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = safepoint_request_queue.cpp; sourceTree = "<group>"; }; 0A5D7D59135E37CB00D13E53 /* safepoint_request_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safepoint_request_queue.h; sourceTree = "<group>"; }; 0A5D7D5A135E37CB00D13E53 /* scheduler_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scheduler_mutex.cpp; sourceTree = "<group>"; }; 0A5D7D5B135E37CB00D13E53 /* scheduler_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scheduler_mutex.h; sourceTree = "<group>"; }; 0A5D7D5C135E37CB00D13E53 /* semaphore_mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = semaphore_mutex.cpp; sourceTree = "<group>"; }; 0A5D7D5D135E37CB00D13E53 /* semaphore_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = semaphore_mutex.h; sourceTree = "<group>"; }; 0A5D7D5E135E37CB00D13E53 /* squeak_adapters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = squeak_adapters.cpp; sourceTree = "<group>"; }; 0A5D7D5F135E37CB00D13E53 /* squeak_adapters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeak_adapters.h; sourceTree = "<group>"; }; 0A5D7D60135E37CB00D13E53 /* timeout_deferral.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timeout_deferral.cpp; sourceTree = "<group>"; }; 0A5D7D61135E37CB00D13E53 /* timeout_deferral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeout_deferral.h; sourceTree = "<group>"; }; 0A5D7D62135E37CB00D13E53 /* timeout_timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timeout_timer.cpp; sourceTree = "<group>"; }; 0A5D7D63135E37CB00D13E53 /* timeout_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeout_timer.h; sourceTree = "<group>"; }; 0A5D7D64135E37CB00D13E53 /* tracked_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tracked_ptr.h; sourceTree = "<group>"; }; 0A5D7D65135E37CB00D13E53 /* tracked_ptr_registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tracked_ptr_registry.h; sourceTree = "<group>"; }; 0A5D7D66135E37CB00D13E53 /* utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cpp; sourceTree = "<group>"; }; 0A5D7D67135E37CB00D13E53 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; }; 0A5D7D69135E37CB00D13E53 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; }; 0A68E005153CB66B00C850D2 /* buffered_channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buffered_channel.cpp; sourceTree = "<group>"; }; 0A68E006153CB66B00C850D2 /* buffered_channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffered_channel.h; sourceTree = "<group>"; }; 0A68E007153CB66B00C850D2 /* buffered_channel_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffered_channel_debug.h; sourceTree = "<group>"; }; 0A68E008153CB66B00C850D2 /* synced_queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_queue.cpp; sourceTree = "<group>"; }; 0A68E009153CB66B00C850D2 /* synced_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = synced_queue.h; sourceTree = "<group>"; }; 0A68E00C153CB6B700C850D2 /* tmc_os_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tmc_os_interface.cpp; sourceTree = "<group>"; }; 0A68E00D153CB6B700C850D2 /* tmc_os_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tmc_os_interface.h; sourceTree = "<group>"; }; 0A890E9913FDA46400067C04 /* Squeak72x72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Squeak72x72.png; sourceTree = "<group>"; }; 0AA32B2D135EC5EE00B97FB8 /* AsynchFilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsynchFilePlugin.h; sourceTree = "<group>"; }; 0AA32B2F135EC5EE00B97FB8 /* FileCopyPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileCopyPlugin.h; sourceTree = "<group>"; }; 0AA32B31135EC5EE00B97FB8 /* FilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePlugin.h; sourceTree = "<group>"; }; 0AA32B32135EC5EE00B97FB8 /* sqFilePluginBasicPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqFilePluginBasicPrims.c; sourceTree = "<group>"; }; 0AA32B34135EC5EE00B97FB8 /* HostWindowPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostWindowPlugin.h; sourceTree = "<group>"; }; 0AA32B38135EC5EE00B97FB8 /* Error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Error.c; sourceTree = "<group>"; }; 0AA32B39135EC5EE00B97FB8 /* jcapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapimin.c; sourceTree = "<group>"; }; 0AA32B3A135EC5EE00B97FB8 /* jcapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapistd.c; sourceTree = "<group>"; }; 0AA32B3B135EC5EE00B97FB8 /* jccoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccoefct.c; sourceTree = "<group>"; }; 0AA32B3C135EC5EE00B97FB8 /* jccolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccolor.c; sourceTree = "<group>"; }; 0AA32B3D135EC5EE00B97FB8 /* jcdctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcdctmgr.c; sourceTree = "<group>"; }; 0AA32B3E135EC5EE00B97FB8 /* jchuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jchuff.c; sourceTree = "<group>"; }; 0AA32B3F135EC5EE00B97FB8 /* jchuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jchuff.h; sourceTree = "<group>"; }; 0AA32B40135EC5EE00B97FB8 /* jcinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcinit.c; sourceTree = "<group>"; }; 0AA32B41135EC5EE00B97FB8 /* jcmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmainct.c; sourceTree = "<group>"; }; 0AA32B42135EC5EE00B97FB8 /* jcmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmarker.c; sourceTree = "<group>"; }; 0AA32B43135EC5EE00B97FB8 /* jcmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmaster.c; sourceTree = "<group>"; }; 0AA32B44135EC5EE00B97FB8 /* jcomapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcomapi.c; sourceTree = "<group>"; }; 0AA32B45135EC5EE00B97FB8 /* jconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jconfig.h; sourceTree = "<group>"; }; 0AA32B46135EC5EE00B97FB8 /* jcparam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcparam.c; sourceTree = "<group>"; }; 0AA32B47135EC5EE00B97FB8 /* jcphuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcphuff.c; sourceTree = "<group>"; }; 0AA32B48135EC5EE00B97FB8 /* jcprepct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcprepct.c; sourceTree = "<group>"; }; 0AA32B49135EC5EE00B97FB8 /* jcsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcsample.c; sourceTree = "<group>"; }; 0AA32B4A135EC5EE00B97FB8 /* jctrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jctrans.c; sourceTree = "<group>"; }; 0AA32B4B135EC5EE00B97FB8 /* jdapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapimin.c; sourceTree = "<group>"; }; 0AA32B4C135EC5EE00B97FB8 /* jdapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapistd.c; sourceTree = "<group>"; }; 0AA32B4D135EC5EE00B97FB8 /* jdatadst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatadst.c; sourceTree = "<group>"; }; 0AA32B4E135EC5EE00B97FB8 /* jdatasrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatasrc.c; sourceTree = "<group>"; }; 0AA32B4F135EC5EE00B97FB8 /* jdcoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcoefct.c; sourceTree = "<group>"; }; 0AA32B50135EC5EE00B97FB8 /* jdcolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcolor.c; sourceTree = "<group>"; }; 0AA32B51135EC5EE00B97FB8 /* jdct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdct.h; sourceTree = "<group>"; }; 0AA32B52135EC5EE00B97FB8 /* jddctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jddctmgr.c; sourceTree = "<group>"; }; 0AA32B53135EC5EE00B97FB8 /* jdhuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdhuff.c; sourceTree = "<group>"; }; 0AA32B54135EC5EE00B97FB8 /* jdhuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdhuff.h; sourceTree = "<group>"; }; 0AA32B55135EC5EE00B97FB8 /* jdinput.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdinput.c; sourceTree = "<group>"; }; 0AA32B56135EC5EE00B97FB8 /* jdmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmainct.c; sourceTree = "<group>"; }; 0AA32B57135EC5EE00B97FB8 /* jdmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmarker.c; sourceTree = "<group>"; }; 0AA32B58135EC5EE00B97FB8 /* jdmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmaster.c; sourceTree = "<group>"; }; 0AA32B59135EC5EE00B97FB8 /* jdmerge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmerge.c; sourceTree = "<group>"; }; 0AA32B5A135EC5EE00B97FB8 /* jdphuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdphuff.c; sourceTree = "<group>"; }; 0AA32B5B135EC5EE00B97FB8 /* jdpostct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdpostct.c; sourceTree = "<group>"; }; 0AA32B5C135EC5EE00B97FB8 /* jdsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdsample.c; sourceTree = "<group>"; }; 0AA32B5D135EC5EE00B97FB8 /* jdtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdtrans.c; sourceTree = "<group>"; }; 0AA32B5E135EC5EE00B97FB8 /* jerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jerror.c; sourceTree = "<group>"; }; 0AA32B5F135EC5EE00B97FB8 /* jerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jerror.h; sourceTree = "<group>"; }; 0AA32B60135EC5EE00B97FB8 /* jfdctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctflt.c; sourceTree = "<group>"; }; 0AA32B61135EC5EE00B97FB8 /* jfdctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctfst.c; sourceTree = "<group>"; }; 0AA32B62135EC5EE00B97FB8 /* jfdctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctint.c; sourceTree = "<group>"; }; 0AA32B63135EC5EE00B97FB8 /* jidctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctflt.c; sourceTree = "<group>"; }; 0AA32B64135EC5EE00B97FB8 /* jidctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctfst.c; sourceTree = "<group>"; }; 0AA32B65135EC5EE00B97FB8 /* jidctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctint.c; sourceTree = "<group>"; }; 0AA32B66135EC5EE00B97FB8 /* jidctred.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctred.c; sourceTree = "<group>"; }; 0AA32B67135EC5EE00B97FB8 /* jinclude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jinclude.h; sourceTree = "<group>"; }; 0AA32B68135EC5EE00B97FB8 /* jmemdatadst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemdatadst.c; sourceTree = "<group>"; }; 0AA32B69135EC5EE00B97FB8 /* jmemdatasrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemdatasrc.c; sourceTree = "<group>"; }; 0AA32B6A135EC5EE00B97FB8 /* jmemmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemmgr.c; sourceTree = "<group>"; }; 0AA32B6B135EC5EE00B97FB8 /* jmemnobs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemnobs.c; sourceTree = "<group>"; }; 0AA32B6C135EC5EE00B97FB8 /* jmemsys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmemsys.h; sourceTree = "<group>"; }; 0AA32B6D135EC5EE00B97FB8 /* jmorecfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmorecfg.h; sourceTree = "<group>"; }; 0AA32B6E135EC5EE00B97FB8 /* jpegint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpegint.h; sourceTree = "<group>"; }; 0AA32B6F135EC5EE00B97FB8 /* jpeglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpeglib.h; sourceTree = "<group>"; }; 0AA32B70135EC5EE00B97FB8 /* JPEGReadWriter2Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEGReadWriter2Plugin.h; sourceTree = "<group>"; }; 0AA32B71135EC5EE00B97FB8 /* jquant1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant1.c; sourceTree = "<group>"; }; 0AA32B72135EC5EE00B97FB8 /* jquant2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant2.c; sourceTree = "<group>"; }; 0AA32B73135EC5EE00B97FB8 /* jutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jutils.c; sourceTree = "<group>"; }; 0AA32B74135EC5EE00B97FB8 /* jversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jversion.h; sourceTree = "<group>"; }; 0AA32B75135EC5EE00B97FB8 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; }; 0AA32B77135EC5EE00B97FB8 /* LocalePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalePlugin.h; sourceTree = "<group>"; }; 0AA32B79135EC5EE00B97FB8 /* MIDIPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIPlugin.h; sourceTree = "<group>"; }; 0AA32B7B135EC5EE00B97FB8 /* PseudoTTYPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoTTYPlugin.h; sourceTree = "<group>"; }; 0AA32B7D135EC5EE00B97FB8 /* QuicktimePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuicktimePlugin.h; sourceTree = "<group>"; }; 0AA32B7F135EC5EE00B97FB8 /* chartables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = chartables.c; sourceTree = "<group>"; }; 0AA32B80135EC5EE00B97FB8 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; }; 0AA32B81135EC5EE00B97FB8 /* get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = get.c; sourceTree = "<group>"; }; 0AA32B82135EC5EE00B97FB8 /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; 0AA32B83135EC5EE00B97FB8 /* oldInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oldInternal.h; sourceTree = "<group>"; }; 0AA32B84135EC5EE00B97FB8 /* pcre.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcre.c; sourceTree = "<group>"; }; 0AA32B85135EC5EE00B97FB8 /* pcre.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pcre.h; sourceTree = "<group>"; }; 0AA32B86135EC5EE00B97FB8 /* rePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rePlugin.h; sourceTree = "<group>"; }; 0AA32B87135EC5EE00B97FB8 /* RePlugin3-Fixes.1.cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "RePlugin3-Fixes.1.cs"; sourceTree = "<group>"; }; 0AA32B88135EC5EE00B97FB8 /* RePlugin3-Fixes2.1.cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "RePlugin3-Fixes2.1.cs"; sourceTree = "<group>"; }; 0AA32B89135EC5EE00B97FB8 /* RePlugin3.3.1.cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RePlugin3.3.1.cs; sourceTree = "<group>"; }; 0AA32B8A135EC5EE00B97FB8 /* study.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = study.c; sourceTree = "<group>"; }; 0AA32B8C135EC5EE00B97FB8 /* SecurityPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityPlugin.h; sourceTree = "<group>"; }; 0AA32B8E135EC5EE00B97FB8 /* SocketPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketPlugin.h; sourceTree = "<group>"; }; 0AA32B8F135EC5EE00B97FB8 /* SocketPrims.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = SocketPrims.pdf; sourceTree = "<group>"; }; 0AA32B91135EC5EE00B97FB8 /* SoundCodecPrims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundCodecPrims.h; sourceTree = "<group>"; }; 0AA32B92135EC5EE00B97FB8 /* sqSoundCodecPluginBasicPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqSoundCodecPluginBasicPrims.c; sourceTree = "<group>"; }; 0AA32B94135EC5EE00B97FB8 /* SoundGenerationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundGenerationPlugin.h; sourceTree = "<group>"; }; 0AA32B96135EC5EE00B97FB8 /* SoundPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundPlugin.h; sourceTree = "<group>"; }; 0AA32B98135EC5EE00B97FB8 /* b3d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3d.h; sourceTree = "<group>"; }; 0AA32B99135EC5EE00B97FB8 /* b3dAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dAlloc.c; sourceTree = "<group>"; }; 0AA32B9A135EC5EE00B97FB8 /* b3dAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3dAlloc.h; sourceTree = "<group>"; }; 0AA32B9B135EC5EE00B97FB8 /* b3dDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dDraw.c; sourceTree = "<group>"; }; 0AA32B9C135EC5EE00B97FB8 /* b3dInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dInit.c; sourceTree = "<group>"; }; 0AA32B9D135EC5EE00B97FB8 /* b3dMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dMain.c; sourceTree = "<group>"; }; 0AA32B9E135EC5EE00B97FB8 /* b3dRemap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dRemap.c; sourceTree = "<group>"; }; 0AA32B9F135EC5EE00B97FB8 /* b3dTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3dTypes.h; sourceTree = "<group>"; }; 0AA32BA1135EC5EE00B97FB8 /* sqFFI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqFFI.h; sourceTree = "<group>"; }; 0AA32BA2135EC5EE00B97FB8 /* sqManualSurface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqManualSurface.c; sourceTree = "<group>"; }; 0AA32BA4135EC5EE00B97FB8 /* SqueakSSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakSSL.h; sourceTree = "<group>"; }; 0AA32BA6135EC5EE00B97FB8 /* SurfacePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SurfacePlugin.c; sourceTree = "<group>"; }; 0AA32BA7135EC5EE00B97FB8 /* SurfacePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SurfacePlugin.h; sourceTree = "<group>"; }; 0AA32BA9135EC5EE00B97FB8 /* UUIDPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UUIDPlugin.h; sourceTree = "<group>"; }; 0AA32BEE135EC61300B97FB8 /* sq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sq.h; sourceTree = "<group>"; }; 0AA32BEF135EC61300B97FB8 /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMemoryAccess.h; sourceTree = "<group>"; }; 0AA32BF0135EC61300B97FB8 /* sqNamedPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqNamedPrims.c; sourceTree = "<group>"; }; 0AA32BF1135EC61300B97FB8 /* sqVirtualMachine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqVirtualMachine.c; sourceTree = "<group>"; }; 0AA32BF7135EC69F00B97FB8 /* drawing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = drawing.m; sourceTree = "<group>"; }; 0AA32BF8135EC69F00B97FB8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 0AA32BF9135EC69F00B97FB8 /* PDColoredProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDColoredProgressView.h; sourceTree = "<group>"; }; 0AA32BFA135EC69F00B97FB8 /* PDColoredProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDColoredProgressView.m; sourceTree = "<group>"; }; 0AA32BFB135EC69F00B97FB8 /* SqueakObjectiveC.xcodeproj.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = SqueakObjectiveC.xcodeproj.zip; sourceTree = "<group>"; }; 0AA32BFC135EC69F00B97FB8 /* squeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeakProxy.h; sourceTree = "<group>"; }; 0AA32BFD135EC69F00B97FB8 /* squeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = squeakProxy.m; sourceTree = "<group>"; }; 0AA32BFE135EC69F00B97FB8 /* squeakSUnitTester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeakSUnitTester.h; sourceTree = "<group>"; }; 0AA32BFF135EC69F00B97FB8 /* squeakSUnitTester.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = squeakSUnitTester.m; sourceTree = "<group>"; }; 0AA32C09135EC6D900B97FB8 /* sqUnixAsynchFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixAsynchFile.c; sourceTree = "<group>"; }; 0AA32C0A135EC6D900B97FB8 /* sqUnixAsynchFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqUnixAsynchFile.h; sourceTree = "<group>"; }; 0AA32C0D135EC6F400B97FB8 /* dummyFFI.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dummyFFI.c; sourceTree = "<group>"; }; 0AA32C0E135EC6F400B97FB8 /* dummyFFI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummyFFI.h; sourceTree = "<group>"; }; 0AA32C11135EC70F00B97FB8 /* sqMacSecurity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacSecurity.c; sourceTree = "<group>"; }; 0AA32C13135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakSoundCoreAudio.h; sourceTree = "<group>"; }; 0AA32C14135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakSoundCoreAudio.m; sourceTree = "<group>"; }; 0AA32C15135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakSoundCoreAudioAPI.h; sourceTree = "<group>"; }; 0AA32C16135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakSoundCoreAudioAPI.m; sourceTree = "<group>"; }; 0AA32C1B135EC76600B97FB8 /* sqUnixExternalPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqUnixExternalPrims.c; path = ../../unix/vm/sqUnixExternalPrims.c; sourceTree = "<group>"; }; 0AB173FB135F2A2F0095BF89 /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqVirtualMachine.h; sourceTree = "<group>"; }; 0ABEA92313C26C7A003108B9 /* gc_debugging_tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gc_debugging_tracer.cpp; sourceTree = "<group>"; }; 0ABEA92413C26C7A003108B9 /* gc_debugging_tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gc_debugging_tracer.h; sourceTree = "<group>"; }; 0ADE8A7C135F38B200D37EAD /* AsynchFilePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = AsynchFilePlugin.c; sourceTree = "<group>"; }; 0ADE8A7E135F38B200D37EAD /* B2DPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = B2DPlugin.c; sourceTree = "<group>"; }; 0ADE8A80135F38B200D37EAD /* BitBltPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BitBltPlugin.c; sourceTree = "<group>"; }; 0ADE8A82135F38B200D37EAD /* BMPReadWriterPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BMPReadWriterPlugin.c; sourceTree = "<group>"; }; 0ADE8A84135F38B200D37EAD /* DSAPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DSAPrims.c; sourceTree = "<group>"; }; 0ADE8A86135F38B200D37EAD /* FFTPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FFTPlugin.c; sourceTree = "<group>"; }; 0ADE8A88135F38B200D37EAD /* FilePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FilePlugin.c; sourceTree = "<group>"; }; 0ADE8A8A135F38B200D37EAD /* FloatArrayPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FloatArrayPlugin.c; sourceTree = "<group>"; }; 0ADE8A8C135F38B200D37EAD /* GeniePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GeniePlugin.c; sourceTree = "<group>"; }; 0ADE8A8E135F38B200D37EAD /* HostWindowPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HostWindowPlugin.c; sourceTree = "<group>"; }; 0ADE8A9A135F38FE00D37EAD /* JPEGReaderPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = JPEGReaderPlugin.c; sourceTree = "<group>"; }; 0ADE8A9C135F38FE00D37EAD /* JPEGReadWriter2Plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = JPEGReadWriter2Plugin.c; sourceTree = "<group>"; }; 0ADE8A9E135F38FE00D37EAD /* Klatt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Klatt.c; sourceTree = "<group>"; }; 0ADE8AA0135F38FE00D37EAD /* LargeIntegers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LargeIntegers.c; sourceTree = "<group>"; }; 0ADE8AA2135F38FE00D37EAD /* Matrix2x3Plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Matrix2x3Plugin.c; sourceTree = "<group>"; }; 0ADE8AA4135F38FE00D37EAD /* MiscPrimitivePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MiscPrimitivePlugin.c; sourceTree = "<group>"; }; 0ADE8AA6135F38FE00D37EAD /* ObjectiveCPlugin.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = ObjectiveCPlugin.c; sourceTree = "<group>"; }; 0ADE8AA8135F38FE00D37EAD /* RePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RePlugin.c; sourceTree = "<group>"; }; 0ADE8AAA135F38FE00D37EAD /* SecurityPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecurityPlugin.c; sourceTree = "<group>"; }; 0ADE8AAC135F38FE00D37EAD /* SocketPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SocketPlugin.c; sourceTree = "<group>"; }; 0ADE8AAE135F38FE00D37EAD /* SoundCodecPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundCodecPrims.c; sourceTree = "<group>"; }; 0ADE8AB0135F38FE00D37EAD /* SoundGenerationPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundGenerationPlugin.c; sourceTree = "<group>"; }; 0ADE8AB2135F38FE00D37EAD /* SoundPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundPlugin.c; sourceTree = "<group>"; }; 0ADE8AB4135F38FE00D37EAD /* Squeak3D.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Squeak3D.c; sourceTree = "<group>"; }; 0ADE8AC4135F392E00D37EAD /* SqueakFFIPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SqueakFFIPrims.c; sourceTree = "<group>"; }; 0ADE8AC6135F392E00D37EAD /* StarSqueakPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = StarSqueakPlugin.c; sourceTree = "<group>"; }; 0ADE8AC8135F392E00D37EAD /* UUIDPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UUIDPlugin.c; sourceTree = "<group>"; }; 0ADE8ACA135F392E00D37EAD /* ZipPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ZipPlugin.c; sourceTree = "<group>"; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakNoOGLIPhoneAppDelegate.h; sourceTree = "<group>"; }; 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakNoOGLIPhoneAppDelegate.m; sourceTree = "<group>"; }; 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 1D6058910D05DD3D006BFB54 /* RoarVM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RoarVM.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = vm/Common/main.m; sourceTree = "<group>"; }; 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqDummyaio.h; sourceTree = "<group>"; }; 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqDummyaio.c; sourceTree = "<group>"; }; 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqViewBitmapConversion.h; path = vm/OSX/SqViewBitmapConversion.h; sourceTree = "<group>"; }; 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqViewBitmapConversion.m; path = vm/OSX/SqViewBitmapConversion.m; sourceTree = "<group>"; }; 9402DD6F10CE0E91005C2102 /* SqViewClut.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqViewClut.m; path = vm/OSX/SqViewClut.m; sourceTree = "<group>"; }; 940BE5791239F10000674A11 /* SqueakUIViewCALayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIViewCALayer.h; sourceTree = "<group>"; }; 940BE57A1239F10000674A11 /* SqueakUIViewCALayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIViewCALayer.m; sourceTree = "<group>"; }; 940BE5E71239F50100674A11 /* SqueakUIViewOpenGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIViewOpenGL.h; sourceTree = "<group>"; }; 940BE5E81239F50100674A11 /* SqueakUIViewOpenGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIViewOpenGL.m; sourceTree = "<group>"; }; 940BE5F81239F70D00674A11 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIController.h; sourceTree = "<group>"; }; 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIController.m; sourceTree = "<group>"; }; 9412CAB20E6C037B00DB8625 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; }; 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakInfoPlistInterface.h; path = vm/Common/Classes/sqSqueakInfoPlistInterface.h; sourceTree = "<group>"; }; 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakInfoPlistInterface.m; path = vm/Common/Classes/sqSqueakInfoPlistInterface.m; sourceTree = "<group>"; }; 9414421E10BC89440088F8AC /* Squeak.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Squeak.icns; path = OSX/Squeak.icns; sourceTree = "<group>"; }; 9414421F10BC89440088F8AC /* SqueakChanges.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakChanges.icns; path = OSX/SqueakChanges.icns; sourceTree = "<group>"; }; 9414422010BC89440088F8AC /* SqueakGeneric.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakGeneric.icns; path = OSX/SqueakGeneric.icns; sourceTree = "<group>"; }; 9414422110BC89440088F8AC /* SqueakImage.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakImage.icns; path = OSX/SqueakImage.icns; sourceTree = "<group>"; }; 9414422210BC89440088F8AC /* SqueakPlugin.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakPlugin.icns; path = OSX/SqueakPlugin.icns; sourceTree = "<group>"; }; 9414422310BC89440088F8AC /* SqueakProject.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakProject.icns; path = OSX/SqueakProject.icns; sourceTree = "<group>"; }; 9414422410BC89440088F8AC /* SqueakScript.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakScript.icns; path = OSX/SqueakScript.icns; sourceTree = "<group>"; }; 9414422510BC89440088F8AC /* SqueakSources.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakSources.icns; path = OSX/SqueakSources.icns; sourceTree = "<group>"; }; 9424FF5B0DDCB1C7009912BF /* sqGnu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = vm/sqGnu.h; sourceTree = "<group>"; }; 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqPlatformSpecific.h; sourceTree = "<group>"; }; 9424FF650DDCB1EF009912BF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; }; 9424FF660DDCB1EF009912BF /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqConfig.h; sourceTree = "<group>"; }; 9424FF670DDCB202009912BF /* sqMacV2Memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacV2Memory.c; sourceTree = "<group>"; }; 9424FF680DDCB202009912BF /* sqMacV2Memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacV2Memory.h; sourceTree = "<group>"; }; 9424FF750DDCB271009912BF /* osExports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = osExports.c; sourceTree = "<group>"; }; 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXClipboardAPI.h; path = vm/OSX/sqSqueakOSXClipboardAPI.h; sourceTree = "<group>"; }; 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXClipboardAPI.m; path = vm/OSX/sqSqueakOSXClipboardAPI.m; sourceTree = "<group>"; }; 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+clipboard.h"; path = "vm/OSX/sqSqueakOSXApplication+clipboard.h"; sourceTree = "<group>"; }; 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+clipboard.m"; path = "vm/OSX/sqSqueakOSXApplication+clipboard.m"; sourceTree = "<group>"; }; 942ABE6E10AA23E20086D908 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; }; 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakVmAndImagePathAPI.h; path = vm/Common/Classes/sqSqueakVmAndImagePathAPI.h; sourceTree = "<group>"; }; 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakVmAndImagePathAPI.m; path = vm/Common/Classes/sqSqueakVmAndImagePathAPI.m; sourceTree = "<group>"; }; 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneApplication.h; sourceTree = "<group>"; }; 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneApplication.m; sourceTree = "<group>"; }; 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+attributes.m"; path = "vm/Common/Classes/sqSqueakMainApplication+attributes.m"; sourceTree = "<group>"; }; 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+attributes.h"; sourceTree = "<group>"; }; 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneFileDirectoryInterface.h; sourceTree = "<group>"; }; 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneFileDirectoryInterface.m; sourceTree = "<group>"; }; 94329ECA12275FFA0090298B /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 943B9C9E1235C5120056205E /* sqMacHostWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqMacHostWindow.m; sourceTree = "<group>"; }; 943B9C9F1235C5120056205E /* sqMacHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacHostWindow.h; sourceTree = "<group>"; }; 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+Network.h"; sourceTree = "<group>"; }; 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+Network.m"; sourceTree = "<group>"; }; 9452D5D70E044A9D000AD792 /* Queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = vm/Common/Classes/Queue.h; sourceTree = "<group>"; }; 9452D5D80E044A9D000AD792 /* Queue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Queue.m; path = vm/Common/Classes/Queue.m; sourceTree = "<group>"; }; 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqMacV2Time.c; path = vm/Common/Classes/sqMacV2Time.c; sourceTree = "<group>"; }; 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqMacV2Time.h; path = vm/Common/Classes/sqMacV2Time.h; sourceTree = "<group>"; }; 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakFileDirectoryAPI.h; path = vm/Common/Classes/sqSqueakFileDirectoryAPI.h; sourceTree = "<group>"; }; 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakFileDirectoryAPI.m; path = vm/Common/Classes/sqSqueakFileDirectoryAPI.m; sourceTree = "<group>"; }; 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakFileDirectoryInterface.h; path = vm/Common/Classes/sqSqueakFileDirectoryInterface.h; sourceTree = "<group>"; }; 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakFileDirectoryInterface.m; path = vm/Common/Classes/sqSqueakFileDirectoryInterface.m; sourceTree = "<group>"; }; 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakMainApp.m; path = vm/Common/Classes/sqSqueakMainApp.m; sourceTree = "<group>"; }; 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakMainApp.h; path = vm/Common/Classes/sqSqueakMainApp.h; sourceTree = "<group>"; }; 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+vmAndImagePath.h"; path = "vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.h"; sourceTree = "<group>"; }; 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+vmAndImagePath.m"; path = "vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.m"; sourceTree = "<group>"; }; 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakMainApplication.h; path = vm/Common/Classes/sqSqueakMainApplication.h; sourceTree = "<group>"; }; 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakMainApplication.m; path = vm/Common/Classes/sqSqueakMainApplication.m; sourceTree = "<group>"; }; 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakAttributesAPI.h; path = vm/Common/Classes/sqSqueakAttributesAPI.h; sourceTree = "<group>"; }; 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakAttributesAPI.m; path = vm/Common/Classes/sqSqueakAttributesAPI.m; sourceTree = "<group>"; }; 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakEventsAPI.h; path = vm/Common/Classes/sqSqueakEventsAPI.h; sourceTree = "<group>"; }; 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakEventsAPI.m; path = vm/Common/Classes/sqSqueakEventsAPI.m; sourceTree = "<group>"; }; 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqiPhoneScreenAndWindow.h; sourceTree = "<group>"; }; 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqiPhoneScreenAndWindow.m; sourceTree = "<group>"; }; 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+sound.h"; sourceTree = "<group>"; }; 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakiPhoneApplication+sound.m"; sourceTree = "<group>"; }; 945550000DF1BC6A00FB176B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; }; 945550910DF2041100FB176B /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; }; 94577FBC10684D5E0020840A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; }; 94577FBE10684D5E0020840A /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = /System/Library/Frameworks/CoreLocation.framework; sourceTree = "<absolute>"; }; 94577FC410684D7E0020840A /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; }; 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneClipboardAPI.h; sourceTree = "<group>"; }; 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneClipboardAPI.m; sourceTree = "<group>"; }; 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+clipboard.h"; sourceTree = "<group>"; }; 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+clipboard.m"; sourceTree = "<group>"; }; 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXDropAPI.h; path = vm/OSX/sqSqueakOSXDropAPI.h; sourceTree = "<group>"; }; 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXDropAPI.m; path = vm/OSX/sqSqueakOSXDropAPI.m; sourceTree = "<group>"; }; 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqMacUnixExternalPrims.m; path = vm/OSX/sqMacUnixExternalPrims.m; sourceTree = "<group>"; }; 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakScreenAndWindow.h; path = vm/Common/Classes/sqSqueakScreenAndWindow.h; sourceTree = "<group>"; }; 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakScreenAndWindow.m; path = vm/Common/Classes/sqSqueakScreenAndWindow.m; sourceTree = "<group>"; }; 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakAppDelegate.h; path = vm/Common/Classes/sqSqueakAppDelegate.h; sourceTree = "<group>"; }; 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakAppDelegate.m; path = vm/Common/Classes/sqSqueakAppDelegate.m; sourceTree = "<group>"; }; 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakPureObjc_Prefix.pch; sourceTree = "<group>"; }; 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SqueakPureObjc-Info.plist"; sourceTree = "<group>"; }; 947E61C210AA03C300D3B69E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 947E61C410AA03DC00D3B69E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqMacV2Browser.h; path = vm/OSX/sqMacV2Browser.h; sourceTree = "<group>"; }; 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqMacV2Browser.m; path = vm/OSX/sqMacV2Browser.m; sourceTree = "<group>"; }; 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqueakOSXAppDelegate.h; path = vm/OSX/SqueakOSXAppDelegate.h; sourceTree = "<group>"; }; 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqueakOSXAppDelegate.m; path = vm/OSX/SqueakOSXAppDelegate.m; sourceTree = "<group>"; }; 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXApplication.h; path = vm/OSX/sqSqueakOSXApplication.h; sourceTree = "<group>"; }; 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXApplication.m; path = vm/OSX/sqSqueakOSXApplication.m; sourceTree = "<group>"; }; 947E64DD10AA18FE00D3B69E /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; }; 948774B110C64DD800E4AEC5 /* SqueakPureObjc-Info 64x64.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SqueakPureObjc-Info 64x64.plist"; sourceTree = "<group>"; }; 94883B2A0E0C2A5E005A4738 /* aio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aio.c; path = ../iOS/vm/Common/aio.c; sourceTree = "<group>"; }; 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixSocket.c; sourceTree = "<group>"; }; 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = "<group>"; }; 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqueakOSXApplication.h; path = vm/OSX/SqueakOSXApplication.h; sourceTree = "<group>"; }; 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqueakOSXApplication.m; path = vm/OSX/SqueakOSXApplication.m; sourceTree = "<group>"; }; 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIView.h; sourceTree = "<group>"; }; 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIView.m; sourceTree = "<group>"; }; 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+attributes.h"; path = "vm/Common/Classes/sqSqueakMainApplication+attributes.h"; sourceTree = "<group>"; }; 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+attributes.m"; sourceTree = "<group>"; }; 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+imageReadWrite.h"; path = "vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+imageReadWrite.m"; path = "vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+screen.h"; path = "vm/Common/Classes/sqSqueakMainApplication+screen.h"; sourceTree = "<group>"; }; 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+screen.m"; path = "vm/Common/Classes/sqSqueakMainApplication+screen.m"; sourceTree = "<group>"; }; 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+events.h"; path = "vm/Common/Classes/sqSqueakMainApplication+events.h"; sourceTree = "<group>"; }; 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+events.m"; path = "vm/Common/Classes/sqSqueakMainApplication+events.m"; sourceTree = "<group>"; }; 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakSoundAPI.h; path = vm/Common/Classes/sqSqueakSoundAPI.h; sourceTree = "<group>"; }; 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakSoundAPI.m; path = vm/Common/Classes/sqSqueakSoundAPI.m; sourceTree = "<group>"; }; 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+sound.h"; path = "vm/Common/Classes/sqSqueakMainApplication+sound.h"; sourceTree = "<group>"; }; 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+sound.m"; path = "vm/Common/Classes/sqSqueakMainApplication+sound.m"; sourceTree = "<group>"; }; 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyBoardStrokeDetails.h; path = vm/OSX/keyBoardStrokeDetails.h; sourceTree = "<group>"; }; 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = keyBoardStrokeDetails.m; path = vm/OSX/keyBoardStrokeDetails.m; sourceTree = "<group>"; }; 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakScreenAPI.h; path = vm/Common/Classes/sqSqueakScreenAPI.h; sourceTree = "<group>"; }; 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakScreenAPI.m; path = vm/Common/Classes/sqSqueakScreenAPI.m; sourceTree = "<group>"; }; 94B6E9D910BC775E00333E9E /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = vm/Common/English.lproj/Localizable.strings; sourceTree = "<group>"; }; 94B8F54E10CF677800F0DD6B /* SqViewClut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqViewClut.h; path = vm/OSX/SqViewClut.h; sourceTree = "<group>"; }; 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXFileDirectoryInterface.h; path = vm/OSX/sqSqueakOSXFileDirectoryInterface.h; sourceTree = "<group>"; }; 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXFileDirectoryInterface.m; path = vm/OSX/sqSqueakOSXFileDirectoryInterface.m; sourceTree = "<group>"; }; 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+attributes.h"; path = "vm/OSX/sqSqueakOSXApplication+attributes.h"; sourceTree = "<group>"; }; 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+attributes.m"; path = "vm/OSX/sqSqueakOSXApplication+attributes.m"; sourceTree = "<group>"; }; 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXInfoPlistInterface.h; path = vm/OSX/sqSqueakOSXInfoPlistInterface.h; sourceTree = "<group>"; }; 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXInfoPlistInterface.m; path = vm/OSX/sqSqueakOSXInfoPlistInterface.m; sourceTree = "<group>"; }; 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacHostWindow.h; sourceTree = "<group>"; }; 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixUUID.c; sourceTree = "<group>"; }; 94BCE7A60DDDF8F800F38F31 /* sqaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqaio.h; path = vm/sqaio.h; sourceTree = "<group>"; }; 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+events.h"; sourceTree = "<group>"; }; 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+events.m"; sourceTree = "<group>"; }; 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacHostWindow.c; sourceTree = "<group>"; }; 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXNSView.h; path = vm/OSX/sqSqueakOSXNSView.h; sourceTree = "<group>"; }; 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXNSView.m; path = vm/OSX/sqSqueakOSXNSView.m; sourceTree = "<group>"; }; 94C208F810AF7262002F4160 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = "<absolute>"; }; 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+cursor.h"; path = "vm/OSX/sqSqueakOSXApplication+cursor.h"; sourceTree = "<group>"; }; 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+cursor.m"; path = "vm/OSX/sqSqueakOSXApplication+cursor.m"; sourceTree = "<group>"; }; 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakCursorAPI.h; path = vm/Common/Classes/sqSqueakCursorAPI.h; sourceTree = "<group>"; }; 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakCursorAPI.m; path = vm/Common/Classes/sqSqueakCursorAPI.m; sourceTree = "<group>"; }; 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+cursor.h"; path = "vm/Common/Classes/sqSqueakMainApplication+cursor.h"; sourceTree = "<group>"; }; 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+cursor.m"; path = "vm/Common/Classes/sqSqueakMainApplication+cursor.m"; sourceTree = "<group>"; }; 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+events.h"; path = "vm/OSX/sqSqueakOSXApplication+events.h"; sourceTree = "<group>"; }; 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+events.m"; path = "vm/OSX/sqSqueakOSXApplication+events.m"; sourceTree = "<group>"; }; 94C36C9710B0CF290041953A /* Info-iPhone.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iPhone.plist"; sourceTree = "<group>"; }; 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXSoundCoreAudio.h; path = vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.h; sourceTree = "<group>"; }; 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXSoundCoreAudio.m; path = vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.m; sourceTree = "<group>"; }; 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+imageReadWrite.h"; path = "vm/OSX/sqSqueakOSXApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+imageReadWrite.m"; path = "vm/OSX/sqSqueakOSXApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXScreenAndWindow.h; path = vm/OSX/sqSqueakOSXScreenAndWindow.h; sourceTree = "<group>"; }; 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXScreenAndWindow.m; path = vm/OSX/sqSqueakOSXScreenAndWindow.m; sourceTree = "<group>"; }; 94D16CAF10BCF96B00A69A89 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = Credits.rtf; path = OSX/Credits.rtf; sourceTree = "<group>"; }; 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitMapConversionLogicFromX11.h; path = vm/OSX/BitMapConversionLogicFromX11.h; sourceTree = "<group>"; }; 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BitMapConversionLogicFromX11.c; path = vm/OSX/BitMapConversionLogicFromX11.c; sourceTree = "<group>"; }; 94E658DE0DDD03FE00358328 /* plugins.int */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = plugins.int; sourceTree = "<group>"; }; 94E658E00DDD03FE00358328 /* interp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 1; path = interp.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; }; 94E658E10DDD03FE00358328 /* interp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interp.h; sourceTree = "<group>"; }; 94E659200DDD03FE00358328 /* sqNamedPrims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqNamedPrims.h; sourceTree = "<group>"; }; 94F3A9690E6BFA7C00E0B12A /* Squeak.png */ = {isa = PBXFileReference; explicitFileType = image.png; path = Squeak.png; sourceTree = "<group>"; }; 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneInfoPlistInterface.h; sourceTree = "<group>"; }; 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneInfoPlistInterface.m; sourceTree = "<group>"; }; BC4F78761358D2870081FC27 /* SqueakV3-minimum-MVC.sources */ = {isa = PBXFileReference; lastKnownFileType = text; name = "SqueakV3-minimum-MVC.sources"; path = "iPhone/SqueakV3-minimum-MVC.sources"; sourceTree = "<group>"; }; BC6CC8E7134B045000B9B2B0 /* RoarVMMouseEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoarVMMouseEvent.h; sourceTree = "<group>"; }; BC6CC8E8134B045100B9B2B0 /* RoarVMMouseEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoarVMMouseEvent.m; sourceTree = "<group>"; }; BC6CC8EB134B138300B9B2B0 /* RoarVMSwipeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RoarVMSwipeEvent.h; path = ../../RoarVMSwipeEvent.h; sourceTree = "<group>"; }; BC6CC8EC134B138300B9B2B0 /* RoarVMSwipeEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RoarVMSwipeEvent.m; path = ../../RoarVMSwipeEvent.m; sourceTree = "<group>"; }; BC82F910135697CD00EC2309 /* UIGestureRecognizer+RoarVMEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIGestureRecognizer+RoarVMEvents.h"; sourceTree = "<group>"; }; BC82F911135697CE00EC2309 /* UIGestureRecognizer+RoarVMEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIGestureRecognizer+RoarVMEvents.m"; sourceTree = "<group>"; }; BC82F9131356A4C200EC2309 /* RoarVMMouseUpEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoarVMMouseUpEvent.h; sourceTree = "<group>"; }; BC82F9141356A4C300EC2309 /* RoarVMMouseUpEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoarVMMouseUpEvent.m; sourceTree = "<group>"; }; BCAB989B134B0139004AB528 /* RoarVMAbstractEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoarVMAbstractEvent.h; sourceTree = "<group>"; }; BCAB989C134B0139004AB528 /* RoarVMAbstractEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoarVMAbstractEvent.m; sourceTree = "<group>"; }; BCCC348D1349603100063417 /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 94D2A24C112B8ED000B6E459 /* QuartzCore.framework in Frameworks */, 9484F99010B13D470038BDC0 /* CoreGraphics.framework in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 945550010DF1BC6A00FB176B /* AudioToolbox.framework in Frameworks */, 94577FBD10684D5E0020840A /* CoreAudio.framework in Frameworks */, 94577FBF10684D5E0020840A /* CoreLocation.framework in Frameworks */, 94577FC510684D7E0020840A /* SystemConfiguration.framework in Frameworks */, 9484F8E810B0E1050038BDC0 /* UIKit.framework in Frameworks */, 940BE5F91239F70D00674A11 /* OpenGLES.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( BC6CC8EB134B138300B9B2B0 /* RoarVMSwipeEvent.h */, BC6CC8EC134B138300B9B2B0 /* RoarVMSwipeEvent.m */, 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */, 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */, 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */, 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */, 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */, 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */, 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */, 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */, 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */, 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */, 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */, 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */, 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */, 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */, 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */, 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */, 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */, 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */, 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */, 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */, 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */, 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */, 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */, 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */, 940BE5791239F10000674A11 /* SqueakUIViewCALayer.h */, 940BE57A1239F10000674A11 /* SqueakUIViewCALayer.m */, 940BE5E71239F50100674A11 /* SqueakUIViewOpenGL.h */, 940BE5E81239F50100674A11 /* SqueakUIViewOpenGL.m */, 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */, 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */, 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */, 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */, BCAB989B134B0139004AB528 /* RoarVMAbstractEvent.h */, BC6CC8E7134B045000B9B2B0 /* RoarVMMouseEvent.h */, BC82F9131356A4C200EC2309 /* RoarVMMouseUpEvent.h */, BC82F9141356A4C300EC2309 /* RoarVMMouseUpEvent.m */, BC6CC8E8134B045100B9B2B0 /* RoarVMMouseEvent.m */, BCAB989C134B0139004AB528 /* RoarVMAbstractEvent.m */, BC82F910135697CD00EC2309 /* UIGestureRecognizer+RoarVMEvents.h */, BC82F911135697CE00EC2309 /* UIGestureRecognizer+RoarVMEvents.m */, ); path = Classes; sourceTree = "<group>"; }; 0A5D7CA9135E37A900D13E53 /* externals */ = { isa = PBXGroup; children = ( 0A5D7CAA135E37A900D13E53 /* externals.cpp */, 0A5D7CAB135E37A900D13E53 /* externals.h */, ); name = externals; path = ../../../../../externals; sourceTree = "<group>"; }; 0A5D7CAE135E37CB00D13E53 /* heap */ = { isa = PBXGroup; children = ( 0A5D7CAF135E37CB00D13E53 /* abstract_mark_sweep_collector.cpp */, 0A5D7CB0135E37CB00D13E53 /* abstract_mark_sweep_collector.h */, 0A5D7CB1135E37CB00D13E53 /* abstract_object_heap.cpp */, 0A5D7CB2135E37CB00D13E53 /* abstract_object_heap.h */, 0A5D7CB3135E37CB00D13E53 /* abstract_object_heap.inline.h */, 0A5D7CB4135E37CB00D13E53 /* abstract_object_table.h */, 0A5D7CB5135E37CB00D13E53 /* gc_oop_stack.h */, 0A5D7CB6135E37CB00D13E53 /* indirect_oop_mark_sweep_collector.h */, 0A5D7CB7135E37CB00D13E53 /* mark_sweep_collector.h */, 0A5D7CB8135E37CB00D13E53 /* memory_system.cpp */, 0A5D7CB9135E37CB00D13E53 /* memory_system.h */, 0A5D7CBA135E37CB00D13E53 /* memory_system.inline.h */, 0A5D7CBB135E37CB00D13E53 /* multicore_object_heap.cpp */, 0A5D7CBC135E37CB00D13E53 /* multicore_object_heap.h */, 0A5D7CBD135E37CB00D13E53 /* multicore_object_heap.inline.h */, 0A5D7CBE135E37CB00D13E53 /* multicore_object_table.cpp */, 0A5D7CBF135E37CB00D13E53 /* multicore_object_table.h */, 0A5D7CC0135E37CB00D13E53 /* multicore_object_table.inline.h */, 0A5D7CC1135E37CB00D13E53 /* oop_closure.h */, ); name = heap; path = ../../../../../heap; sourceTree = "<group>"; }; 0A5D7CCA135E37CB00D13E53 /* image_readers */ = { isa = PBXGroup; children = ( 0A5D7CCB135E37CB00D13E53 /* squeak_image_reader.cpp */, 0A5D7CCC135E37CB00D13E53 /* squeak_image_reader.h */, ); name = image_readers; path = ../../../../../image_readers; sourceTree = "<group>"; }; 0A5D7CCD135E37CB00D13E53 /* interpreter */ = { isa = PBXGroup; children = ( 0A5D7CCE135E37CB00D13E53 /* abstract_primitive_table.h */, 0A5D7CCF135E37CB00D13E53 /* at_cache.cpp */, 0A5D7CD0135E37CB00D13E53 /* at_cache.h */, 0A5D7CD1135E37CB00D13E53 /* external_primitive_table.h */, 0A5D7CD2135E37CB00D13E53 /* interpreter_bytecodes.cpp */, 0A5D7CD3135E37CB00D13E53 /* interpreter_bytecodes.h */, 0A5D7CD4135E37CB00D13E53 /* interpreter_primitives.cpp */, 0A5D7CD5135E37CB00D13E53 /* interpreter_primitives.h */, 0A5D7CD6135E37CB00D13E53 /* method_cache.cpp */, 0A5D7CD7135E37CB00D13E53 /* method_cache.h */, 0A5D7CD8135E37CB00D13E53 /* obsolete_indexed_primitive_table.cpp */, 0A5D7CD9135E37CB00D13E53 /* obsolete_indexed_primitive_table.h */, 0A5D7CDA135E37CB00D13E53 /* obsolete_named_primitive_table.cpp */, 0A5D7CDB135E37CB00D13E53 /* obsolete_named_primitive_table.h */, 0A5D7CDC135E37CB00D13E53 /* primitive_table.cpp */, 0A5D7CDD135E37CB00D13E53 /* primitive_table.h */, 0A5D7CDE135E37CB00D13E53 /* squeak_interpreter.cpp */, 0A5D7CDF135E37CB00D13E53 /* squeak_interpreter.h */, ); name = interpreter; path = ../../../../../interpreter; sourceTree = "<group>"; }; 0A5D7CE0135E37CB00D13E53 /* messages */ = { isa = PBXGroup; children = ( 0A5D7CE1135E37CB00D13E53 /* abstract_message.cpp */, 0A5D7CE2135E37CB00D13E53 /* abstract_message.h */, 0A5D7CE3135E37CB00D13E53 /* deferred_request.cpp */, 0A5D7CE4135E37CB00D13E53 /* deferred_request.h */, 0A5D7CE5135E37CB00D13E53 /* interactions.cpp */, 0A5D7CE6135E37CB00D13E53 /* interactions.h */, 0A5D7CE7135E37CB00D13E53 /* interpreter_subset_for_control_transfer.cpp */, 0A5D7CE8135E37CB00D13E53 /* interpreter_subset_for_control_transfer.h */, 0A5D7CE9135E37CB00D13E53 /* message_classes.cpp */, 0A5D7CEA135E37CB00D13E53 /* message_classes.h */, 0A5D7CEB135E37CB00D13E53 /* message_or_ack_request.cpp */, 0A5D7CEC135E37CB00D13E53 /* message_or_ack_request.h */, 0A5D7CED135E37CB00D13E53 /* message_statics.cpp */, 0A5D7CEE135E37CB00D13E53 /* message_statics.h */, 0A5D7CEF135E37CB00D13E53 /* message_stats.cpp */, 0A5D7CF0135E37CB00D13E53 /* message_stats.h */, 0A5D7CF1135E37CB00D13E53 /* message_templates.h */, 0A5D7CF2135E37CB00D13E53 /* receive_marker.cpp */, 0A5D7CF3135E37CB00D13E53 /* receive_marker.h */, ); name = messages; path = ../../../../../messages; sourceTree = "<group>"; }; 0A5D7CF4135E37CB00D13E53 /* objects */ = { isa = PBXGroup; children = ( 0A5D7CF5135E37CB00D13E53 /* chunk.h */, 0A5D7CF6135E37CB00D13E53 /* chunk.inline.h */, 0A5D7CF7135E37CB00D13E53 /* header_type.cpp */, 0A5D7CF8135E37CB00D13E53 /* header_type.h */, 0A5D7CF9135E37CB00D13E53 /* object.cpp */, 0A5D7CFA135E37CB00D13E53 /* object.h */, 0A5D7CFB135E37CB00D13E53 /* object.inline.h */, 0A5D7CFC135E37CB00D13E53 /* object_indices.h */, 0A5D7CFD135E37CB00D13E53 /* object_p.h */, 0A5D7CFE135E37CB00D13E53 /* preheader.h */, 0A5D7CFF135E37CB00D13E53 /* process_field_locator.cpp */, 0A5D7D00135E37CB00D13E53 /* process_field_locator.h */, 0A5D7D01135E37CB00D13E53 /* roots.cpp */, 0A5D7D02135E37CB00D13E53 /* roots.h */, 0A5D7D03135E37CB00D13E53 /* special_indices.h */, 0A5D7D04135E37CB00D13E53 /* word_containing_object_type.h */, ); name = objects; path = ../../../../../objects; sourceTree = "<group>"; }; 0A5D7D05135E37CB00D13E53 /* oops */ = { isa = PBXGroup; children = ( 0A5D7D06135E37CB00D13E53 /* abstract_oop.h */, 0A5D7D07135E37CB00D13E53 /* oop.cpp */, 0A5D7D08135E37CB00D13E53 /* oop.h */, 0A5D7D09135E37CB00D13E53 /* oop.inline.h */, 0A5D7D0A135E37CB00D13E53 /* tags.h */, ); name = oops; path = ../../../../../oops; sourceTree = "<group>"; }; 0A5D7D0B135E37CB00D13E53 /* platform */ = { isa = PBXGroup; children = ( 0A5D7D0C135E37CB00D13E53 /* abstract_cpu_coordinate.h */, 0A5D7D0D135E37CB00D13E53 /* abstract_memory_semantics.h */, 0A5D7D0E135E37CB00D13E53 /* abstract_message_queue.h */, 0A5D7D0F135E37CB00D13E53 /* abstract_os_interface.cpp */, 0A5D7D10135E37CB00D13E53 /* abstract_os_interface.h */, 0A5D7D11135E37CB00D13E53 /* cacheline_aligned.h */, 0A5D7D12135E37CB00D13E53 /* cpu_coordinate.h */, 0A5D7D13135E37CB00D13E53 /* dummy_cpu_coordinate.cpp */, 0A5D7D14135E37CB00D13E53 /* dummy_cpu_coordinate.h */, 0A5D7D15135E37CB00D13E53 /* ilib_message_queue.cpp */, 0A5D7D16135E37CB00D13E53 /* ilib_message_queue.h */, 0A5D7D17135E37CB00D13E53 /* ilib_os_interface.cpp */, 0A5D7D18135E37CB00D13E53 /* ilib_os_interface.h */, 0A5D7D19135E37CB00D13E53 /* logical_core.cpp */, 0A5D7D1A135E37CB00D13E53 /* logical_core.h */, 0A5D7D1B135E37CB00D13E53 /* memory_semantics.h */, 0A5D7D1C135E37CB00D13E53 /* message_queue.h */, 0A5D7D1D135E37CB00D13E53 /* os_interface.h */, 0A5D7D1E135E37CB00D13E53 /* osx_os_interface.cpp */, 0A5D7D1F135E37CB00D13E53 /* osx_os_interface.h */, 0A5D7D20135E37CB00D13E53 /* posix_os_interface.cpp */, 0A5D7D21135E37CB00D13E53 /* posix_os_interface.h */, 0A5D7D22135E37CB00D13E53 /* process_memory_semantics.cpp */, 0A5D7D23135E37CB00D13E53 /* process_memory_semantics.h */, 0A5D7D24135E37CB00D13E53 /* shared_memory_message_queue.cpp */, 0A5D7D25135E37CB00D13E53 /* shared_memory_message_queue.h */, 0A5D7D26135E37CB00D13E53 /* shared_memory_message_queue_per_sender.cpp */, 0A5D7D27135E37CB00D13E53 /* shared_memory_message_queue_per_sender.h */, 0A5D7D28135E37CB00D13E53 /* thread_memory_semantics.cpp */, 0A5D7D29135E37CB00D13E53 /* thread_memory_semantics.h */, 0A5D7D2A135E37CB00D13E53 /* tile_cpu_coordinate.cpp */, 0A5D7D2B135E37CB00D13E53 /* tile_cpu_coordinate.h */, 0A68E00C153CB6B700C850D2 /* tmc_os_interface.cpp */, 0A68E00D153CB6B700C850D2 /* tmc_os_interface.h */, ); name = platform; path = ../../../../../platform; sourceTree = "<group>"; }; 0A5D7D2C135E37CB00D13E53 /* primitives */ = { isa = PBXGroup; children = ( 0A5D7D2D135E37CB00D13E53 /* RVMPlugin.cpp */, 0A5D7D2E135E37CB00D13E53 /* RVMPlugin.h */, ); name = primitives; path = ../../../../../primitives; sourceTree = "<group>"; }; 0A5D7D2F135E37CB00D13E53 /* runtime */ = { isa = PBXGroup; children = ( 0A5D7D30135E37CB00D13E53 /* abstract_mutex.cpp */, 0A5D7D31135E37CB00D13E53 /* abstract_mutex.h */, 0A5D7D32135E37CB00D13E53 /* abstract_tracer.cpp */, 0A5D7D33135E37CB00D13E53 /* abstract_tracer.h */, 0A5D7D34135E37CB00D13E53 /* bytemap.cpp */, 0A5D7D35135E37CB00D13E53 /* bytemap.h */, 0A5D7D36135E37CB00D13E53 /* core_tracer.cpp */, 0A5D7D37135E37CB00D13E53 /* core_tracer.h */, 0A5D7D38135E37CB00D13E53 /* debug_helper.cpp */, 0A5D7D39135E37CB00D13E53 /* debug_helper.h */, 0A5D7D3A135E37CB00D13E53 /* debug_store_checks.h */, 0ABEA92313C26C7A003108B9 /* gc_debugging_tracer.cpp */, 0ABEA92413C26C7A003108B9 /* gc_debugging_tracer.h */, 0A5D7D3D135E37CB00D13E53 /* error_handling.cpp */, 0A5D7D3E135E37CB00D13E53 /* error_handling.h */, 0A5D7D3F135E37CB00D13E53 /* execution_tracer.cpp */, 0A5D7D40135E37CB00D13E53 /* execution_tracer.h */, 0A5D7D41135E37CB00D13E53 /* headers.h */, 0A5D7D42135E37CB00D13E53 /* main.cpp */, 0A5D7D43135E37CB00D13E53 /* measurements.cpp */, 0A5D7D44135E37CB00D13E53 /* measurements.h */, 0A5D7D45135E37CB00D13E53 /* my_rank.cpp */, 0A5D7D46135E37CB00D13E53 /* my_rank.h */, 0A5D7D47135E37CB00D13E53 /* oop_tracer.cpp */, 0A5D7D48135E37CB00D13E53 /* oop_tracer.h */, 0A040E2013B7526D007E172E /* performance_counters.cpp */, 0A040E2113B7526D007E172E /* performance_counters.h */, 0A5D7D49135E37CB00D13E53 /* printer.cpp */, 0A5D7D4A135E37CB00D13E53 /* printer.h */, 0A5D7D4B135E37CB00D13E53 /* profiling_tracer.cpp */, 0A5D7D4C135E37CB00D13E53 /* profiling_tracer.h */, 0A5D7D4D135E37CB00D13E53 /* rank_set.cpp */, 0A5D7D4E135E37CB00D13E53 /* rank_set.h */, 0A5D7D4F135E37CB00D13E53 /* runtime_tester.h */, 0A5D7D50135E37CB00D13E53 /* rvm_bitmap.cpp */, 0A5D7D51135E37CB00D13E53 /* rvm_bitmap.h */, 0A5D7D52135E37CB00D13E53 /* rvm_config.cpp */, 0A5D7D53135E37CB00D13E53 /* rvm_config.h */, 0A5D7D54135E37CB00D13E53 /* safepoint.cpp */, 0A5D7D55135E37CB00D13E53 /* safepoint.h */, 0A5D7D56135E37CB00D13E53 /* safepoint_ability.cpp */, 0A5D7D57135E37CB00D13E53 /* safepoint_ability.h */, 0A5D7D58135E37CB00D13E53 /* safepoint_request_queue.cpp */, 0A5D7D59135E37CB00D13E53 /* safepoint_request_queue.h */, 0A5D7D5A135E37CB00D13E53 /* scheduler_mutex.cpp */, 0A5D7D5B135E37CB00D13E53 /* scheduler_mutex.h */, 0A5D7D5C135E37CB00D13E53 /* semaphore_mutex.cpp */, 0A5D7D5D135E37CB00D13E53 /* semaphore_mutex.h */, 0A5D7D5E135E37CB00D13E53 /* squeak_adapters.cpp */, 0A5D7D5F135E37CB00D13E53 /* squeak_adapters.h */, 0A5D7D60135E37CB00D13E53 /* timeout_deferral.cpp */, 0A5D7D61135E37CB00D13E53 /* timeout_deferral.h */, 0A5D7D62135E37CB00D13E53 /* timeout_timer.cpp */, 0A5D7D63135E37CB00D13E53 /* timeout_timer.h */, 0A5D7D64135E37CB00D13E53 /* tracked_ptr.h */, 0A5D7D65135E37CB00D13E53 /* tracked_ptr_registry.h */, 0A5D7D66135E37CB00D13E53 /* utils.cpp */, 0A5D7D67135E37CB00D13E53 /* utils.h */, ); name = runtime; path = ../../../../../runtime; sourceTree = "<group>"; }; 0A5D7D68135E37CB00D13E53 /* types */ = { isa = PBXGroup; children = ( 0A5D7D69135E37CB00D13E53 /* types.h */, ); name = types; path = ../../../../../types; sourceTree = "<group>"; }; 0A68E004153CB66B00C850D2 /* message_buffers */ = { isa = PBXGroup; children = ( 0A68E005153CB66B00C850D2 /* buffered_channel.cpp */, 0A68E006153CB66B00C850D2 /* buffered_channel.h */, 0A68E007153CB66B00C850D2 /* buffered_channel_debug.h */, 0A68E008153CB66B00C850D2 /* synced_queue.cpp */, 0A68E009153CB66B00C850D2 /* synced_queue.h */, ); name = message_buffers; path = ../../../../../message_buffers; sourceTree = "<group>"; }; 0AA32B28135EC55400B97FB8 /* from_squeak */ = { isa = PBXGroup; children = ( 0ADE8A79135F389000D37EAD /* intplugins */, 0AA32C06135EC6BF00B97FB8 /* unix */, 0AA32BF4135EC68800B97FB8 /* iOS */, 0AA32B2A135EC5B700B97FB8 /* Cross */, ); name = from_squeak; sourceTree = SOURCE_ROOT; }; 0AA32B2A135EC5B700B97FB8 /* Cross */ = { isa = PBXGroup; children = ( 0AA32B2B135EC5C300B97FB8 /* plugins */, 0AA32BED135EC61300B97FB8 /* vm */, ); name = Cross; sourceTree = SOURCE_ROOT; }; 0AA32B2B135EC5C300B97FB8 /* plugins */ = { isa = PBXGroup; children = ( 0AA32B2C135EC5EE00B97FB8 /* AsynchFilePlugin */, 0AA32B2E135EC5EE00B97FB8 /* FileCopyPlugin */, 0AA32B30135EC5EE00B97FB8 /* FilePlugin */, 0AA32B33135EC5EE00B97FB8 /* HostWindowPlugin */, 0AA32B37135EC5EE00B97FB8 /* JPEGReadWriter2Plugin */, 0AA32B76135EC5EE00B97FB8 /* LocalePlugin */, 0AA32B78135EC5EE00B97FB8 /* MIDIPlugin */, 0AA32B7A135EC5EE00B97FB8 /* PseudoTTYPlugin */, 0AA32B7C135EC5EE00B97FB8 /* QuicktimePlugin */, 0AA32B7E135EC5EE00B97FB8 /* RePlugin */, 0AA32B8B135EC5EE00B97FB8 /* SecurityPlugin */, 0AA32B8D135EC5EE00B97FB8 /* SocketPlugin */, 0AA32B90135EC5EE00B97FB8 /* SoundCodecPrims */, 0AA32B93135EC5EE00B97FB8 /* SoundGenerationPlugin */, 0AA32B95135EC5EE00B97FB8 /* SoundPlugin */, 0AA32B97135EC5EE00B97FB8 /* Squeak3D */, 0AA32BA0135EC5EE00B97FB8 /* SqueakFFIPrims */, 0AA32BA3135EC5EE00B97FB8 /* SqueakSSL */, 0AA32BA5135EC5EE00B97FB8 /* SurfacePlugin */, 0AA32BA8135EC5EE00B97FB8 /* UUIDPlugin */, ); name = plugins; sourceTree = SOURCE_ROOT; }; 0AA32B2C135EC5EE00B97FB8 /* AsynchFilePlugin */ = { isa = PBXGroup; children = ( 0AA32B2D135EC5EE00B97FB8 /* AsynchFilePlugin.h */, ); name = AsynchFilePlugin; path = ../../Cross/plugins/AsynchFilePlugin; sourceTree = "<group>"; }; 0AA32B2E135EC5EE00B97FB8 /* FileCopyPlugin */ = { isa = PBXGroup; children = ( 0AA32B2F135EC5EE00B97FB8 /* FileCopyPlugin.h */, ); name = FileCopyPlugin; path = ../../Cross/plugins/FileCopyPlugin; sourceTree = "<group>"; }; 0AA32B30135EC5EE00B97FB8 /* FilePlugin */ = { isa = PBXGroup; children = ( 0AA32B31135EC5EE00B97FB8 /* FilePlugin.h */, 0AA32B32135EC5EE00B97FB8 /* sqFilePluginBasicPrims.c */, ); name = FilePlugin; path = ../../Cross/plugins/FilePlugin; sourceTree = "<group>"; }; 0AA32B33135EC5EE00B97FB8 /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 0AA32B34135EC5EE00B97FB8 /* HostWindowPlugin.h */, ); name = HostWindowPlugin; path = ../../Cross/plugins/HostWindowPlugin; sourceTree = "<group>"; }; 0AA32B37135EC5EE00B97FB8 /* JPEGReadWriter2Plugin */ = { isa = PBXGroup; children = ( 0AA32B38135EC5EE00B97FB8 /* Error.c */, 0AA32B39135EC5EE00B97FB8 /* jcapimin.c */, 0AA32B3A135EC5EE00B97FB8 /* jcapistd.c */, 0AA32B3B135EC5EE00B97FB8 /* jccoefct.c */, 0AA32B3C135EC5EE00B97FB8 /* jccolor.c */, 0AA32B3D135EC5EE00B97FB8 /* jcdctmgr.c */, 0AA32B3E135EC5EE00B97FB8 /* jchuff.c */, 0AA32B3F135EC5EE00B97FB8 /* jchuff.h */, 0AA32B40135EC5EE00B97FB8 /* jcinit.c */, 0AA32B41135EC5EE00B97FB8 /* jcmainct.c */, 0AA32B42135EC5EE00B97FB8 /* jcmarker.c */, 0AA32B43135EC5EE00B97FB8 /* jcmaster.c */, 0AA32B44135EC5EE00B97FB8 /* jcomapi.c */, 0AA32B45135EC5EE00B97FB8 /* jconfig.h */, 0AA32B46135EC5EE00B97FB8 /* jcparam.c */, 0AA32B47135EC5EE00B97FB8 /* jcphuff.c */, 0AA32B48135EC5EE00B97FB8 /* jcprepct.c */, 0AA32B49135EC5EE00B97FB8 /* jcsample.c */, 0AA32B4A135EC5EE00B97FB8 /* jctrans.c */, 0AA32B4B135EC5EE00B97FB8 /* jdapimin.c */, 0AA32B4C135EC5EE00B97FB8 /* jdapistd.c */, 0AA32B4D135EC5EE00B97FB8 /* jdatadst.c */, 0AA32B4E135EC5EE00B97FB8 /* jdatasrc.c */, 0AA32B4F135EC5EE00B97FB8 /* jdcoefct.c */, 0AA32B50135EC5EE00B97FB8 /* jdcolor.c */, 0AA32B51135EC5EE00B97FB8 /* jdct.h */, 0AA32B52135EC5EE00B97FB8 /* jddctmgr.c */, 0AA32B53135EC5EE00B97FB8 /* jdhuff.c */, 0AA32B54135EC5EE00B97FB8 /* jdhuff.h */, 0AA32B55135EC5EE00B97FB8 /* jdinput.c */, 0AA32B56135EC5EE00B97FB8 /* jdmainct.c */, 0AA32B57135EC5EE00B97FB8 /* jdmarker.c */, 0AA32B58135EC5EE00B97FB8 /* jdmaster.c */, 0AA32B59135EC5EE00B97FB8 /* jdmerge.c */, 0AA32B5A135EC5EE00B97FB8 /* jdphuff.c */, 0AA32B5B135EC5EE00B97FB8 /* jdpostct.c */, 0AA32B5C135EC5EE00B97FB8 /* jdsample.c */, 0AA32B5D135EC5EE00B97FB8 /* jdtrans.c */, 0AA32B5E135EC5EE00B97FB8 /* jerror.c */, 0AA32B5F135EC5EE00B97FB8 /* jerror.h */, 0AA32B60135EC5EE00B97FB8 /* jfdctflt.c */, 0AA32B61135EC5EE00B97FB8 /* jfdctfst.c */, 0AA32B62135EC5EE00B97FB8 /* jfdctint.c */, 0AA32B63135EC5EE00B97FB8 /* jidctflt.c */, 0AA32B64135EC5EE00B97FB8 /* jidctfst.c */, 0AA32B65135EC5EE00B97FB8 /* jidctint.c */, 0AA32B66135EC5EE00B97FB8 /* jidctred.c */, 0AA32B67135EC5EE00B97FB8 /* jinclude.h */, 0AA32B68135EC5EE00B97FB8 /* jmemdatadst.c */, 0AA32B69135EC5EE00B97FB8 /* jmemdatasrc.c */, 0AA32B6A135EC5EE00B97FB8 /* jmemmgr.c */, 0AA32B6B135EC5EE00B97FB8 /* jmemnobs.c */, 0AA32B6C135EC5EE00B97FB8 /* jmemsys.h */, 0AA32B6D135EC5EE00B97FB8 /* jmorecfg.h */, 0AA32B6E135EC5EE00B97FB8 /* jpegint.h */, 0AA32B6F135EC5EE00B97FB8 /* jpeglib.h */, 0AA32B70135EC5EE00B97FB8 /* JPEGReadWriter2Plugin.h */, 0AA32B71135EC5EE00B97FB8 /* jquant1.c */, 0AA32B72135EC5EE00B97FB8 /* jquant2.c */, 0AA32B73135EC5EE00B97FB8 /* jutils.c */, 0AA32B74135EC5EE00B97FB8 /* jversion.h */, 0AA32B75135EC5EE00B97FB8 /* ReadMe.txt */, ); name = JPEGReadWriter2Plugin; path = ../../Cross/plugins/JPEGReadWriter2Plugin; sourceTree = "<group>"; }; 0AA32B76135EC5EE00B97FB8 /* LocalePlugin */ = { isa = PBXGroup; children = ( 0AA32B77135EC5EE00B97FB8 /* LocalePlugin.h */, ); name = LocalePlugin; path = ../../Cross/plugins/LocalePlugin; sourceTree = "<group>"; }; 0AA32B78135EC5EE00B97FB8 /* MIDIPlugin */ = { isa = PBXGroup; children = ( 0AA32B79135EC5EE00B97FB8 /* MIDIPlugin.h */, ); name = MIDIPlugin; path = ../../Cross/plugins/MIDIPlugin; sourceTree = "<group>"; }; 0AA32B7A135EC5EE00B97FB8 /* PseudoTTYPlugin */ = { isa = PBXGroup; children = ( 0AA32B7B135EC5EE00B97FB8 /* PseudoTTYPlugin.h */, ); name = PseudoTTYPlugin; path = ../../Cross/plugins/PseudoTTYPlugin; sourceTree = "<group>"; }; 0AA32B7C135EC5EE00B97FB8 /* QuicktimePlugin */ = { isa = PBXGroup; children = ( 0AA32B7D135EC5EE00B97FB8 /* QuicktimePlugin.h */, ); name = QuicktimePlugin; path = ../../Cross/plugins/QuicktimePlugin; sourceTree = "<group>"; }; 0AA32B7E135EC5EE00B97FB8 /* RePlugin */ = { isa = PBXGroup; children = ( 0AA32B7F135EC5EE00B97FB8 /* chartables.c */, 0AA32B80135EC5EE00B97FB8 /* config.h */, 0AA32B81135EC5EE00B97FB8 /* get.c */, 0AA32B82135EC5EE00B97FB8 /* internal.h */, 0AA32B83135EC5EE00B97FB8 /* oldInternal.h */, 0AA32B84135EC5EE00B97FB8 /* pcre.c */, 0AA32B85135EC5EE00B97FB8 /* pcre.h */, 0AA32B86135EC5EE00B97FB8 /* rePlugin.h */, 0AA32B87135EC5EE00B97FB8 /* RePlugin3-Fixes.1.cs */, 0AA32B88135EC5EE00B97FB8 /* RePlugin3-Fixes2.1.cs */, 0AA32B89135EC5EE00B97FB8 /* RePlugin3.3.1.cs */, 0AA32B8A135EC5EE00B97FB8 /* study.c */, ); name = RePlugin; path = ../../Cross/plugins/RePlugin; sourceTree = "<group>"; }; 0AA32B8B135EC5EE00B97FB8 /* SecurityPlugin */ = { isa = PBXGroup; children = ( 0AA32B8C135EC5EE00B97FB8 /* SecurityPlugin.h */, ); name = SecurityPlugin; path = ../../Cross/plugins/SecurityPlugin; sourceTree = "<group>"; }; 0AA32B8D135EC5EE00B97FB8 /* SocketPlugin */ = { isa = PBXGroup; children = ( 0AA32B8E135EC5EE00B97FB8 /* SocketPlugin.h */, 0AA32B8F135EC5EE00B97FB8 /* SocketPrims.pdf */, ); name = SocketPlugin; path = ../../Cross/plugins/SocketPlugin; sourceTree = "<group>"; }; 0AA32B90135EC5EE00B97FB8 /* SoundCodecPrims */ = { isa = PBXGroup; children = ( 0AA32B91135EC5EE00B97FB8 /* SoundCodecPrims.h */, 0AA32B92135EC5EE00B97FB8 /* sqSoundCodecPluginBasicPrims.c */, ); name = SoundCodecPrims; path = ../../Cross/plugins/SoundCodecPrims; sourceTree = "<group>"; }; 0AA32B93135EC5EE00B97FB8 /* SoundGenerationPlugin */ = { isa = PBXGroup; children = ( 0AA32B94135EC5EE00B97FB8 /* SoundGenerationPlugin.h */, ); name = SoundGenerationPlugin; path = ../../Cross/plugins/SoundGenerationPlugin; sourceTree = "<group>"; }; 0AA32B95135EC5EE00B97FB8 /* SoundPlugin */ = { isa = PBXGroup; children = ( 0AA32B96135EC5EE00B97FB8 /* SoundPlugin.h */, ); name = SoundPlugin; path = ../../Cross/plugins/SoundPlugin; sourceTree = "<group>"; }; 0AA32B97135EC5EE00B97FB8 /* Squeak3D */ = { isa = PBXGroup; children = ( 0AA32B98135EC5EE00B97FB8 /* b3d.h */, 0AA32B99135EC5EE00B97FB8 /* b3dAlloc.c */, 0AA32B9A135EC5EE00B97FB8 /* b3dAlloc.h */, 0AA32B9B135EC5EE00B97FB8 /* b3dDraw.c */, 0AA32B9C135EC5EE00B97FB8 /* b3dInit.c */, 0AA32B9D135EC5EE00B97FB8 /* b3dMain.c */, 0AA32B9E135EC5EE00B97FB8 /* b3dRemap.c */, 0AA32B9F135EC5EE00B97FB8 /* b3dTypes.h */, ); name = Squeak3D; path = ../../Cross/plugins/Squeak3D; sourceTree = "<group>"; }; 0AA32BA0135EC5EE00B97FB8 /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 0AA32BA1135EC5EE00B97FB8 /* sqFFI.h */, 0AA32BA2135EC5EE00B97FB8 /* sqManualSurface.c */, ); name = SqueakFFIPrims; path = ../../Cross/plugins/SqueakFFIPrims; sourceTree = "<group>"; }; 0AA32BA3135EC5EE00B97FB8 /* SqueakSSL */ = { isa = PBXGroup; children = ( 0AA32BA4135EC5EE00B97FB8 /* SqueakSSL.h */, ); name = SqueakSSL; path = ../../Cross/plugins/SqueakSSL; sourceTree = "<group>"; }; 0AA32BA5135EC5EE00B97FB8 /* SurfacePlugin */ = { isa = PBXGroup; children = ( 0AA32BA6135EC5EE00B97FB8 /* SurfacePlugin.c */, 0AA32BA7135EC5EE00B97FB8 /* SurfacePlugin.h */, ); name = SurfacePlugin; path = ../../Cross/plugins/SurfacePlugin; sourceTree = "<group>"; }; 0AA32BA8135EC5EE00B97FB8 /* UUIDPlugin */ = { isa = PBXGroup; children = ( 0AA32BA9135EC5EE00B97FB8 /* UUIDPlugin.h */, ); name = UUIDPlugin; path = ../../Cross/plugins/UUIDPlugin; sourceTree = "<group>"; }; 0AA32BED135EC61300B97FB8 /* vm */ = { isa = PBXGroup; children = ( 0AA32BEE135EC61300B97FB8 /* sq.h */, 0AA32BEF135EC61300B97FB8 /* sqMemoryAccess.h */, 0AA32BF0135EC61300B97FB8 /* sqNamedPrims.c */, 0AB173FB135F2A2F0095BF89 /* sqVirtualMachine.h */, 0AA32BF1135EC61300B97FB8 /* sqVirtualMachine.c */, ); name = vm; path = ../../Cross/vm; sourceTree = "<group>"; }; 0AA32BF4135EC68800B97FB8 /* iOS */ = { isa = PBXGroup; children = ( 0AA32C1D135EC7DF00B97FB8 /* vm */, 0AA32BF5135EC69200B97FB8 /* plugins */, ); name = iOS; sourceTree = "<group>"; }; 0AA32BF5135EC69200B97FB8 /* plugins */ = { isa = PBXGroup; children = ( 0AA32C10135EC70F00B97FB8 /* SecurityPlugin */, 0AA32C12135EC70F00B97FB8 /* SoundPlugin */, 0AA32C0C135EC6F400B97FB8 /* SqueakFFIPrims */, 0AA32BF6135EC69F00B97FB8 /* SqueakObjectiveC */, ); name = plugins; sourceTree = "<group>"; }; 0AA32BF6135EC69F00B97FB8 /* SqueakObjectiveC */ = { isa = PBXGroup; children = ( 0AA32BF7135EC69F00B97FB8 /* drawing.m */, 0AA32BF8135EC69F00B97FB8 /* Info.plist */, 0AA32BF9135EC69F00B97FB8 /* PDColoredProgressView.h */, 0AA32BFA135EC69F00B97FB8 /* PDColoredProgressView.m */, 0AA32BFB135EC69F00B97FB8 /* SqueakObjectiveC.xcodeproj.zip */, 0AA32BFC135EC69F00B97FB8 /* squeakProxy.h */, 0AA32BFD135EC69F00B97FB8 /* squeakProxy.m */, 0AA32BFE135EC69F00B97FB8 /* squeakSUnitTester.h */, 0AA32BFF135EC69F00B97FB8 /* squeakSUnitTester.m */, ); name = SqueakObjectiveC; path = ../plugins/SqueakObjectiveC; sourceTree = "<group>"; }; 0AA32C06135EC6BF00B97FB8 /* unix */ = { isa = PBXGroup; children = ( 0AA32C1A135EC74C00B97FB8 /* vm */, 0AA32C07135EC6CC00B97FB8 /* plugins */, ); name = unix; sourceTree = "<group>"; }; 0AA32C07135EC6CC00B97FB8 /* plugins */ = { isa = PBXGroup; children = ( 0AA32C08135EC6D900B97FB8 /* AsynchFilePlugin */, ); name = plugins; sourceTree = "<group>"; }; 0AA32C08135EC6D900B97FB8 /* AsynchFilePlugin */ = { isa = PBXGroup; children = ( 0AA32C09135EC6D900B97FB8 /* sqUnixAsynchFile.c */, 0AA32C0A135EC6D900B97FB8 /* sqUnixAsynchFile.h */, ); name = AsynchFilePlugin; path = ../../unix/plugins/AsynchFilePlugin; sourceTree = "<group>"; }; 0AA32C0C135EC6F400B97FB8 /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 0AA32C0D135EC6F400B97FB8 /* dummyFFI.c */, 0AA32C0E135EC6F400B97FB8 /* dummyFFI.h */, ); name = SqueakFFIPrims; path = ../plugins/SqueakFFIPrims; sourceTree = "<group>"; }; 0AA32C10135EC70F00B97FB8 /* SecurityPlugin */ = { isa = PBXGroup; children = ( 0AA32C11135EC70F00B97FB8 /* sqMacSecurity.c */, ); name = SecurityPlugin; path = ../plugins/SecurityPlugin; sourceTree = "<group>"; }; 0AA32C12135EC70F00B97FB8 /* SoundPlugin */ = { isa = PBXGroup; children = ( 0AA32C13135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.h */, 0AA32C14135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.m */, 0AA32C15135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.h */, 0AA32C16135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.m */, ); name = SoundPlugin; path = ../plugins/SoundPlugin; sourceTree = "<group>"; }; 0AA32C1A135EC74C00B97FB8 /* vm */ = { isa = PBXGroup; children = ( 0AA32C1B135EC76600B97FB8 /* sqUnixExternalPrims.c */, ); name = vm; sourceTree = "<group>"; }; 0AA32C1D135EC7DF00B97FB8 /* vm */ = { isa = PBXGroup; children = ( 0AA32C77135ECEBF00B97FB8 /* iPhone */, ); name = vm; sourceTree = "<group>"; }; 0AA32C77135ECEBF00B97FB8 /* iPhone */ = { isa = PBXGroup; children = ( ); name = iPhone; sourceTree = "<group>"; }; 0ADE8A79135F389000D37EAD /* intplugins */ = { isa = PBXGroup; children = ( 0ADE8A99135F38FE00D37EAD /* JPEGReaderPlugin */, 0ADE8A9B135F38FE00D37EAD /* JPEGReadWriter2Plugin */, 0ADE8A9D135F38FE00D37EAD /* Klatt */, 0ADE8A9F135F38FE00D37EAD /* LargeIntegers */, 0ADE8AA1135F38FE00D37EAD /* Matrix2x3Plugin */, 0ADE8AA3135F38FE00D37EAD /* MiscPrimitivePlugin */, 0ADE8AA5135F38FE00D37EAD /* ObjectiveCPlugin */, 0ADE8AA7135F38FE00D37EAD /* RePlugin */, 0ADE8AA9135F38FE00D37EAD /* SecurityPlugin */, 0ADE8AAB135F38FE00D37EAD /* SocketPlugin */, 0ADE8AAD135F38FE00D37EAD /* SoundCodecPrims */, 0ADE8AAF135F38FE00D37EAD /* SoundGenerationPlugin */, 0ADE8AB1135F38FE00D37EAD /* SoundPlugin */, 0ADE8AB3135F38FE00D37EAD /* Squeak3D */, 0ADE8A7B135F38B200D37EAD /* AsynchFilePlugin */, 0ADE8A7D135F38B200D37EAD /* B2DPlugin */, 0ADE8A7F135F38B200D37EAD /* BitBltPlugin */, 0ADE8A81135F38B200D37EAD /* BMPReadWriterPlugin */, 0ADE8A83135F38B200D37EAD /* DSAPrims */, 0ADE8A85135F38B200D37EAD /* FFTPlugin */, 0ADE8A87135F38B200D37EAD /* FilePlugin */, 0ADE8A89135F38B200D37EAD /* FloatArrayPlugin */, 0ADE8A8B135F38B200D37EAD /* GeniePlugin */, 0ADE8A8D135F38B200D37EAD /* HostWindowPlugin */, 0ADE8AC3135F392E00D37EAD /* SqueakFFIPrims */, 0ADE8AC5135F392E00D37EAD /* StarSqueakPlugin */, 0ADE8AC7135F392E00D37EAD /* UUIDPlugin */, 0ADE8AC9135F392E00D37EAD /* ZipPlugin */, ); name = intplugins; sourceTree = "<group>"; }; 0ADE8A7B135F38B200D37EAD /* AsynchFilePlugin */ = { isa = PBXGroup; children = ( 0ADE8A7C135F38B200D37EAD /* AsynchFilePlugin.c */, ); name = AsynchFilePlugin; path = ../../intplugins/AsynchFilePlugin; sourceTree = "<group>"; }; 0ADE8A7D135F38B200D37EAD /* B2DPlugin */ = { isa = PBXGroup; children = ( 0ADE8A7E135F38B200D37EAD /* B2DPlugin.c */, ); name = B2DPlugin; path = ../../intplugins/B2DPlugin; sourceTree = "<group>"; }; 0ADE8A7F135F38B200D37EAD /* BitBltPlugin */ = { isa = PBXGroup; children = ( 0ADE8A80135F38B200D37EAD /* BitBltPlugin.c */, ); name = BitBltPlugin; path = ../../intplugins/BitBltPlugin; sourceTree = "<group>"; }; 0ADE8A81135F38B200D37EAD /* BMPReadWriterPlugin */ = { isa = PBXGroup; children = ( 0ADE8A82135F38B200D37EAD /* BMPReadWriterPlugin.c */, ); name = BMPReadWriterPlugin; path = ../../intplugins/BMPReadWriterPlugin; sourceTree = "<group>"; }; 0ADE8A83135F38B200D37EAD /* DSAPrims */ = { isa = PBXGroup; children = ( 0ADE8A84135F38B200D37EAD /* DSAPrims.c */, ); name = DSAPrims; path = ../../intplugins/DSAPrims; sourceTree = "<group>"; }; 0ADE8A85135F38B200D37EAD /* FFTPlugin */ = { isa = PBXGroup; children = ( 0ADE8A86135F38B200D37EAD /* FFTPlugin.c */, ); name = FFTPlugin; path = ../../intplugins/FFTPlugin; sourceTree = "<group>"; }; 0ADE8A87135F38B200D37EAD /* FilePlugin */ = { isa = PBXGroup; children = ( 0ADE8A88135F38B200D37EAD /* FilePlugin.c */, ); name = FilePlugin; path = ../../intplugins/FilePlugin; sourceTree = "<group>"; }; 0ADE8A89135F38B200D37EAD /* FloatArrayPlugin */ = { isa = PBXGroup; children = ( 0ADE8A8A135F38B200D37EAD /* FloatArrayPlugin.c */, ); name = FloatArrayPlugin; path = ../../intplugins/FloatArrayPlugin; sourceTree = "<group>"; }; 0ADE8A8B135F38B200D37EAD /* GeniePlugin */ = { isa = PBXGroup; children = ( 0ADE8A8C135F38B200D37EAD /* GeniePlugin.c */, ); name = GeniePlugin; path = ../../intplugins/GeniePlugin; sourceTree = "<group>"; }; 0ADE8A8D135F38B200D37EAD /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 0ADE8A8E135F38B200D37EAD /* HostWindowPlugin.c */, ); name = HostWindowPlugin; path = ../../intplugins/HostWindowPlugin; sourceTree = "<group>"; }; 0ADE8A99135F38FE00D37EAD /* JPEGReaderPlugin */ = { isa = PBXGroup; children = ( 0ADE8A9A135F38FE00D37EAD /* JPEGReaderPlugin.c */, ); name = JPEGReaderPlugin; path = ../../intplugins/JPEGReaderPlugin; sourceTree = "<group>"; }; 0ADE8A9B135F38FE00D37EAD /* JPEGReadWriter2Plugin */ = { isa = PBXGroup; children = ( 0ADE8A9C135F38FE00D37EAD /* JPEGReadWriter2Plugin.c */, ); name = JPEGReadWriter2Plugin; path = ../../intplugins/JPEGReadWriter2Plugin; sourceTree = "<group>"; }; 0ADE8A9D135F38FE00D37EAD /* Klatt */ = { isa = PBXGroup; children = ( 0ADE8A9E135F38FE00D37EAD /* Klatt.c */, ); name = Klatt; path = ../../intplugins/Klatt; sourceTree = "<group>"; }; 0ADE8A9F135F38FE00D37EAD /* LargeIntegers */ = { isa = PBXGroup; children = ( 0ADE8AA0135F38FE00D37EAD /* LargeIntegers.c */, ); name = LargeIntegers; path = ../../intplugins/LargeIntegers; sourceTree = "<group>"; }; 0ADE8AA1135F38FE00D37EAD /* Matrix2x3Plugin */ = { isa = PBXGroup; children = ( 0ADE8AA2135F38FE00D37EAD /* Matrix2x3Plugin.c */, ); name = Matrix2x3Plugin; path = ../../intplugins/Matrix2x3Plugin; sourceTree = "<group>"; }; 0ADE8AA3135F38FE00D37EAD /* MiscPrimitivePlugin */ = { isa = PBXGroup; children = ( 0ADE8AA4135F38FE00D37EAD /* MiscPrimitivePlugin.c */, ); name = MiscPrimitivePlugin; path = ../../intplugins/MiscPrimitivePlugin; sourceTree = "<group>"; }; 0ADE8AA5135F38FE00D37EAD /* ObjectiveCPlugin */ = { isa = PBXGroup; children = ( 0ADE8AA6135F38FE00D37EAD /* ObjectiveCPlugin.c */, ); name = ObjectiveCPlugin; path = ../../intplugins/ObjectiveCPlugin; sourceTree = "<group>"; }; 0ADE8AA7135F38FE00D37EAD /* RePlugin */ = { isa = PBXGroup; children = ( 0ADE8AA8135F38FE00D37EAD /* RePlugin.c */, ); name = RePlugin; path = ../../intplugins/RePlugin; sourceTree = "<group>"; }; 0ADE8AA9135F38FE00D37EAD /* SecurityPlugin */ = { isa = PBXGroup; children = ( 0ADE8AAA135F38FE00D37EAD /* SecurityPlugin.c */, ); name = SecurityPlugin; path = ../../intplugins/SecurityPlugin; sourceTree = "<group>"; }; 0ADE8AAB135F38FE00D37EAD /* SocketPlugin */ = { isa = PBXGroup; children = ( 0ADE8AAC135F38FE00D37EAD /* SocketPlugin.c */, ); name = SocketPlugin; path = ../../intplugins/SocketPlugin; sourceTree = "<group>"; }; 0ADE8AAD135F38FE00D37EAD /* SoundCodecPrims */ = { isa = PBXGroup; children = ( 0ADE8AAE135F38FE00D37EAD /* SoundCodecPrims.c */, ); name = SoundCodecPrims; path = ../../intplugins/SoundCodecPrims; sourceTree = "<group>"; }; 0ADE8AAF135F38FE00D37EAD /* SoundGenerationPlugin */ = { isa = PBXGroup; children = ( 0ADE8AB0135F38FE00D37EAD /* SoundGenerationPlugin.c */, ); name = SoundGenerationPlugin; path = ../../intplugins/SoundGenerationPlugin; sourceTree = "<group>"; }; 0ADE8AB1135F38FE00D37EAD /* SoundPlugin */ = { isa = PBXGroup; children = ( 0ADE8AB2135F38FE00D37EAD /* SoundPlugin.c */, ); name = SoundPlugin; path = ../../intplugins/SoundPlugin; sourceTree = "<group>"; }; 0ADE8AB3135F38FE00D37EAD /* Squeak3D */ = { isa = PBXGroup; children = ( 0ADE8AB4135F38FE00D37EAD /* Squeak3D.c */, ); name = Squeak3D; path = ../../intplugins/Squeak3D; sourceTree = "<group>"; }; 0ADE8AC3135F392E00D37EAD /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 0ADE8AC4135F392E00D37EAD /* SqueakFFIPrims.c */, ); name = SqueakFFIPrims; path = ../../intplugins/SqueakFFIPrims; sourceTree = "<group>"; }; 0ADE8AC5135F392E00D37EAD /* StarSqueakPlugin */ = { isa = PBXGroup; children = ( 0ADE8AC6135F392E00D37EAD /* StarSqueakPlugin.c */, ); name = StarSqueakPlugin; path = ../../intplugins/StarSqueakPlugin; sourceTree = "<group>"; }; 0ADE8AC7135F392E00D37EAD /* UUIDPlugin */ = { isa = PBXGroup; children = ( 0ADE8AC8135F392E00D37EAD /* UUIDPlugin.c */, ); name = UUIDPlugin; path = ../../intplugins/UUIDPlugin; sourceTree = "<group>"; }; 0ADE8AC9135F392E00D37EAD /* ZipPlugin */ = { isa = PBXGroup; children = ( 0ADE8ACA135F392E00D37EAD /* ZipPlugin.c */, ); name = ZipPlugin; path = ../../intplugins/ZipPlugin; sourceTree = "<group>"; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 1D6058910D05DD3D006BFB54 /* RoarVM.app */, ); name = Products; sourceTree = "<group>"; }; 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( 0A890E9913FDA46400067C04 /* Squeak72x72.png */, 9412CAB20E6C037B00DB8625 /* Settings.bundle */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 948EC38E1155311D00B08A4F /* Resources-iPad */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, BCCC348D1349603100063417 /* Entitlements.plist */, 94C36C9710B0CF290041953A /* Info-iPhone.plist */, 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */, 948774B110C64DD800E4AEC5 /* SqueakPureObjc-Info 64x64.plist */, ); name = CustomTemplate; sourceTree = "<group>"; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( 0AA32B28135EC55400B97FB8 /* from_squeak */, 94E658DF0DDD03FE00358328 /* vm */, 9424FF570DDCB17F009912BF /* platforms */, 94E658DC0DDD03FE00358328 /* src */, 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */, ); name = "Other Sources"; sourceTree = "<group>"; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( BC4F78761358D2870081FC27 /* SqueakV3-minimum-MVC.sources */, 94B6E9DC10BC777A00333E9E /* Localizable.strings */, 947E64DC10AA18FE00D3B69E /* MainMenu.xib */, 0A4EFFD913317C0D004BC399 /* iPhone.changes */, 0A4EFFDA13317C0D004BC399 /* iPhone.image */, 0A4EFFDB13317C0D004BC399 /* SqueakV3-minimum-MVC.sources */, 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 945550910DF2041100FB176B /* Default.png */, 94F3A9690E6BFA7C00E0B12A /* Squeak.png */, 9414421E10BC89440088F8AC /* Squeak.icns */, 9414421F10BC89440088F8AC /* SqueakChanges.icns */, 9414422010BC89440088F8AC /* SqueakGeneric.icns */, 9414422110BC89440088F8AC /* SqueakImage.icns */, 9414422210BC89440088F8AC /* SqueakPlugin.icns */, 9414422310BC89440088F8AC /* SqueakProject.icns */, 9414422410BC89440088F8AC /* SqueakScript.icns */, 9414422510BC89440088F8AC /* SqueakSources.icns */, 94D16CAF10BCF96B00A69A89 /* Credits.rtf */, ); name = Resources; sourceTree = "<group>"; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( 947E61C410AA03DC00D3B69E /* AppKit.framework */, 947E61C210AA03C300D3B69E /* Cocoa.framework */, 945550000DF1BC6A00FB176B /* AudioToolbox.framework */, 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */, 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, 94577FBC10684D5E0020840A /* CoreAudio.framework */, 94577FBE10684D5E0020840A /* CoreLocation.framework */, 94577FC410684D7E0020840A /* SystemConfiguration.framework */, 942ABE6E10AA23E20086D908 /* ApplicationServices.framework */, 94C208F810AF7262002F4160 /* QuartzCore.framework */, 94329ECA12275FFA0090298B /* OpenGL.framework */, 940BE5F81239F70D00674A11 /* OpenGLES.framework */, ); name = Frameworks; sourceTree = "<group>"; }; 9424FF570DDCB17F009912BF /* platforms */ = { isa = PBXGroup; children = ( 94BCE77E0DDDF61200F38F31 /* unix */, 94BCE6880DDDECC200F38F31 /* Cross */, 9424FF590DDCB198009912BF /* iOS */, ); name = platforms; path = ../..; sourceTree = "<group>"; }; 9424FF590DDCB198009912BF /* iOS */ = { isa = PBXGroup; children = ( 947E642610AA0E1100D3B69E /* OSX */, 9452D5EF0E044AC2000AD792 /* Common */, 9424FF5B0DDCB1C7009912BF /* sqGnu.h */, 9424FF5A0DDCB19F009912BF /* iPhone */, ); path = iOS; sourceTree = "<group>"; }; 9424FF5A0DDCB19F009912BF /* iPhone */ = { isa = PBXGroup; children = ( 94BCE6640DDDEB5000F38F31 /* plugins */, 080E96DDFE201D6D7F000001 /* Classes */, 9424FF650DDCB1EF009912BF /* config.h */, 9424FF750DDCB271009912BF /* osExports.c */, 9424FF660DDCB1EF009912BF /* sqConfig.h */, 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */, 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */, 9424FF670DDCB202009912BF /* sqMacV2Memory.c */, 9424FF680DDCB202009912BF /* sqMacV2Memory.h */, 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */, ); name = iPhone; path = vm/iPhone; sourceTree = "<group>"; }; 943B9C9D1235C5120056205E /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 943B9C9E1235C5120056205E /* sqMacHostWindow.m */, 943B9C9F1235C5120056205E /* sqMacHostWindow.h */, ); name = HostWindowPlugin; path = vm/OSX/plugins/HostWindowPlugin; sourceTree = "<group>"; }; 9452D5EF0E044AC2000AD792 /* Common */ = { isa = PBXGroup; children = ( 29B97316FDCFA39411CA2CEA /* main.m */, 9452D5F00E044AD1000AD792 /* Classes */, ); name = Common; sourceTree = "<group>"; }; 9452D5F00E044AD1000AD792 /* Classes */ = { isa = PBXGroup; children = ( 9452D5D70E044A9D000AD792 /* Queue.h */, 9452D5D80E044A9D000AD792 /* Queue.m */, 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */, 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */, 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */, 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */, 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */, 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */, 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */, 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */, 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */, 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */, 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */, 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */, 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */, 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */, 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */, 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */, 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */, 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */, 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */, 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */, 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */, 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */, 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */, 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */, 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */, 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */, 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */, 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */, 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */, 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */, 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */, 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */, 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */, 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */, 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */, 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */, 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */, 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */, 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */, 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */, 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */, 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */, ); name = Classes; sourceTree = "<group>"; }; 947E642610AA0E1100D3B69E /* OSX */ = { isa = PBXGroup; children = ( 94C4B82C10C06F0D00CD4F90 /* plugins */, 947E647610AA0FF200D3B69E /* Classes */, ); name = OSX; sourceTree = "<group>"; }; 947E647610AA0FF200D3B69E /* Classes */ = { isa = PBXGroup; children = ( 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */, 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */, 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */, 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */, 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */, 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */, 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */, 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */, 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */, 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */, 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */, 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */, 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */, 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */, 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */, 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */, 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */, 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */, 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */, 9402DD6F10CE0E91005C2102 /* SqViewClut.m */, 94B8F54E10CF677800F0DD6B /* SqViewClut.h */, 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */, 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */, 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */, 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */, 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */, 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */, 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */, 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */, 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */, 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */, 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */, 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */, 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */, 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */, 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */, 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */, 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */, 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */, ); name = Classes; sourceTree = "<group>"; }; 94883B3F0E0C2B9C005A4738 /* SocketPlugin */ = { isa = PBXGroup; children = ( 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */, ); path = SocketPlugin; sourceTree = "<group>"; }; 948EC38E1155311D00B08A4F /* Resources-iPad */ = { isa = PBXGroup; children = ( 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */, ); name = "Resources-iPad"; sourceTree = "<group>"; }; 94BCE6640DDDEB5000F38F31 /* plugins */ = { isa = PBXGroup; children = ( 94BCE6650DDDEB5000F38F31 /* HostWindowPlugin */, ); path = plugins; sourceTree = "<group>"; }; 94BCE6650DDDEB5000F38F31 /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */, 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */, ); path = HostWindowPlugin; sourceTree = "<group>"; }; 94BCE6880DDDECC200F38F31 /* Cross */ = { isa = PBXGroup; children = ( ); path = Cross; sourceTree = "<group>"; }; 94BCE77E0DDDF61200F38F31 /* unix */ = { isa = PBXGroup; children = ( 94883B2A0E0C2A5E005A4738 /* aio.c */, 94BCE7A60DDDF8F800F38F31 /* sqaio.h */, 94BCE77F0DDDF61200F38F31 /* plugins */, ); path = unix; sourceTree = "<group>"; }; 94BCE77F0DDDF61200F38F31 /* plugins */ = { isa = PBXGroup; children = ( 94883B3F0E0C2B9C005A4738 /* SocketPlugin */, 94BCE7840DDDF61200F38F31 /* UUIDPlugin */, ); path = plugins; sourceTree = "<group>"; }; 94BCE7840DDDF61200F38F31 /* UUIDPlugin */ = { isa = PBXGroup; children = ( 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */, ); path = UUIDPlugin; sourceTree = "<group>"; }; 94C4B82C10C06F0D00CD4F90 /* plugins */ = { isa = PBXGroup; children = ( 943B9C9D1235C5120056205E /* HostWindowPlugin */, 94C4B82D10C06F1800CD4F90 /* SoundPlugin */, ); name = plugins; sourceTree = "<group>"; }; 94C4B82D10C06F1800CD4F90 /* SoundPlugin */ = { isa = PBXGroup; children = ( 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */, 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */, ); name = SoundPlugin; sourceTree = "<group>"; }; 94E658DC0DDD03FE00358328 /* src */ = { isa = PBXGroup; children = ( 94E658DE0DDD03FE00358328 /* plugins.int */, ); path = src; sourceTree = "<group>"; }; 94E658DF0DDD03FE00358328 /* vm */ = { isa = PBXGroup; children = ( 0A68E004153CB66B00C850D2 /* message_buffers */, 0A5D7CAE135E37CB00D13E53 /* heap */, 0A5D7CCA135E37CB00D13E53 /* image_readers */, 0A5D7CCD135E37CB00D13E53 /* interpreter */, 0A5D7CE0135E37CB00D13E53 /* messages */, 0A5D7CF4135E37CB00D13E53 /* objects */, 0A5D7D05135E37CB00D13E53 /* oops */, 0A5D7D0B135E37CB00D13E53 /* platform */, 0A5D7D2C135E37CB00D13E53 /* primitives */, 0A5D7D2F135E37CB00D13E53 /* runtime */, 0A5D7D68135E37CB00D13E53 /* types */, 0A5D7CA9135E37A900D13E53 /* externals */, 94E658E00DDD03FE00358328 /* interp.c */, 94E658E10DDD03FE00358328 /* interp.h */, 94E659200DDD03FE00358328 /* sqNamedPrims.h */, ); name = vm; path = src/vm; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 1D6058900D05DD3D006BFB54 /* RoarVMIPad */ = { isa = PBXNativeTarget; buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "RoarVMIPad" */; buildPhases = ( 1D60588D0D05DD3D006BFB54 /* Resources */, 1D60588E0D05DD3D006BFB54 /* Sources */, 1D60588F0D05DD3D006BFB54 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = RoarVMIPad; productName = SqueakNoOGLIPhone; productReference = 1D6058910D05DD3D006BFB54 /* RoarVM.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0420; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "RoarVMOnIPad" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; targets = ( 1D6058900D05DD3D006BFB54 /* RoarVMIPad */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 1D60588D0D05DD3D006BFB54 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 0A4EFFDE13317C0D004BC399 /* SqueakV3-minimum-MVC.sources in Resources */, 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 9412CAB30E6C037B00DB8625 /* Settings.bundle in Resources */, 9484F8E410B0E0ED0038BDC0 /* Squeak.png in Resources */, 9484F8EF10B0E1580038BDC0 /* Default.png in Resources */, 94B6E9DD10BC777A00333E9E /* Localizable.strings in Resources */, 948EC3901155312600B08A4F /* MainWindow-iPad.xib in Resources */, 0A4EFFDC13317C0D004BC399 /* iPhone.changes in Resources */, 0A4EFFDD13317C0D004BC399 /* iPhone.image in Resources */, BCCC348E1349603100063417 /* Entitlements.plist in Resources */, 0AA32BDC135EC5EE00B97FB8 /* ReadMe.txt in Resources */, 0AA32BE0135EC5EE00B97FB8 /* RePlugin3-Fixes.1.cs in Resources */, 0AA32BE1135EC5EE00B97FB8 /* RePlugin3-Fixes2.1.cs in Resources */, 0AA32BE2135EC5EE00B97FB8 /* RePlugin3.3.1.cs in Resources */, 0AA32BE4135EC5EE00B97FB8 /* SocketPrims.pdf in Resources */, 0AA32C01135EC69F00B97FB8 /* Info.plist in Resources */, 0AA32C03135EC69F00B97FB8 /* SqueakObjectiveC.xcodeproj.zip in Resources */, 0A890E9A13FDA46400067C04 /* Squeak72x72.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 1D60588E0D05DD3D006BFB54 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 9424FF760DDCB271009912BF /* osExports.c in Sources */, 94A3488E0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m in Sources */, 94BCE78C0DDDF61200F38F31 /* sqUnixUUID.c in Sources */, 94A0E8850DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m in Sources */, 94A0E9840DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m in Sources */, 9452D5E50E044A9D000AD792 /* Queue.m in Sources */, 9452D5E60E044A9D000AD792 /* sqMacV2Time.c in Sources */, 9452D5E70E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m in Sources */, 9452D5E80E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m in Sources */, 9452D5E90E044A9D000AD792 /* sqSqueakMainApp.m in Sources */, 9452D5EA0E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m in Sources */, 9452D5EB0E044A9D000AD792 /* sqSqueakMainApplication.m in Sources */, 9452D6030E044CB3000AD792 /* sqSqueakAttributesAPI.m in Sources */, 9452D6080E044D2F000AD792 /* sqSqueakEventsAPI.m in Sources */, 9471D2730E04703B00703D45 /* sqSqueakScreenAndWindow.m in Sources */, 9471D2E10E04743F00703D45 /* sqSqueakAppDelegate.m in Sources */, 942F75D30E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m in Sources */, 942F76320E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m in Sources */, 94A1B0070E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m in Sources */, 94A1B02D0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m in Sources */, 94A1B0320E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m in Sources */, 9412CAE60E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m in Sources */, 945C95FF0E97084C00529DC1 /* aio.c in Sources */, 9484F8DB10B0E09B0038BDC0 /* sqiPhoneScreenAndWindow.m in Sources */, 9484F8DC10B0E0C60038BDC0 /* sqSqueakIPhoneApplication+attributes.m in Sources */, 9484F8DD10B0E0C70038BDC0 /* sqSqueakIPhoneApplication+events.m in Sources */, 9484F8DE10B0E0C90038BDC0 /* sqSqueakIPhoneApplication+imageReadWrite.m in Sources */, 9484F8DF10B0E0CB0038BDC0 /* sqSqueakIPhoneApplication+Network.m in Sources */, 9484F8E010B0E0CE0038BDC0 /* sqSqueakiPhoneApplication+sound.m in Sources */, 9484F8E110B0E0CE0038BDC0 /* sqSqueakIPhoneApplication.m in Sources */, 9484F8E210B0E0D10038BDC0 /* sqSqueakIPhoneFileDirectoryInterface.m in Sources */, 9484F8E310B0E0D30038BDC0 /* sqSqueakIPhoneInfoPlistInterface.m in Sources */, 9484F8E510B0E0F00038BDC0 /* SqueakNoOGLIPhoneAppDelegate.m in Sources */, 9484F8E610B0E0FD0038BDC0 /* SqueakUIController.m in Sources */, 9484F8E710B0E0FE0038BDC0 /* SqueakUIView.m in Sources */, 9484F9AF10B13DA50038BDC0 /* sqMacHostWindow.c in Sources */, 9458525610F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m in Sources */, 9458525C10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m in Sources */, 940BE57B1239F10000674A11 /* SqueakUIViewCALayer.m in Sources */, 940BE5E91239F50100674A11 /* SqueakUIViewOpenGL.m in Sources */, BCAB989D134B0139004AB528 /* RoarVMAbstractEvent.m in Sources */, BC6CC8E9134B045100B9B2B0 /* RoarVMMouseEvent.m in Sources */, BC6CC8ED134B138300B9B2B0 /* RoarVMSwipeEvent.m in Sources */, BC82F912135697D000EC2309 /* UIGestureRecognizer+RoarVMEvents.m in Sources */, BC82F9151356A4C400EC2309 /* RoarVMMouseUpEvent.m in Sources */, 0A5D7CAC135E37A900D13E53 /* externals.cpp in Sources */, 0A5D7D6A135E37CB00D13E53 /* abstract_mark_sweep_collector.cpp in Sources */, 0A5D7D6B135E37CB00D13E53 /* abstract_object_heap.cpp in Sources */, 0A5D7D6C135E37CB00D13E53 /* memory_system.cpp in Sources */, 0A5D7D6D135E37CB00D13E53 /* multicore_object_heap.cpp in Sources */, 0A5D7D6E135E37CB00D13E53 /* multicore_object_table.cpp in Sources */, 0A5D7D72135E37CB00D13E53 /* squeak_image_reader.cpp in Sources */, 0A5D7D73135E37CB00D13E53 /* at_cache.cpp in Sources */, 0A5D7D74135E37CB00D13E53 /* interpreter_bytecodes.cpp in Sources */, 0A5D7D75135E37CB00D13E53 /* interpreter_primitives.cpp in Sources */, 0A5D7D76135E37CB00D13E53 /* method_cache.cpp in Sources */, 0A5D7D77135E37CB00D13E53 /* obsolete_indexed_primitive_table.cpp in Sources */, 0A5D7D78135E37CB00D13E53 /* obsolete_named_primitive_table.cpp in Sources */, 0A5D7D79135E37CB00D13E53 /* primitive_table.cpp in Sources */, 0A5D7D7A135E37CB00D13E53 /* squeak_interpreter.cpp in Sources */, 0A5D7D7B135E37CB00D13E53 /* abstract_message.cpp in Sources */, 0A5D7D7C135E37CB00D13E53 /* deferred_request.cpp in Sources */, 0A5D7D7D135E37CB00D13E53 /* interactions.cpp in Sources */, 0A5D7D7E135E37CB00D13E53 /* interpreter_subset_for_control_transfer.cpp in Sources */, 0A5D7D7F135E37CB00D13E53 /* message_classes.cpp in Sources */, 0A5D7D80135E37CB00D13E53 /* message_or_ack_request.cpp in Sources */, 0A5D7D81135E37CB00D13E53 /* message_statics.cpp in Sources */, 0A5D7D82135E37CB00D13E53 /* message_stats.cpp in Sources */, 0A5D7D83135E37CB00D13E53 /* receive_marker.cpp in Sources */, 0A5D7D84135E37CB00D13E53 /* header_type.cpp in Sources */, 0A5D7D85135E37CB00D13E53 /* object.cpp in Sources */, 0A5D7D86135E37CB00D13E53 /* process_field_locator.cpp in Sources */, 0A5D7D87135E37CB00D13E53 /* roots.cpp in Sources */, 0A5D7D88135E37CB00D13E53 /* oop.cpp in Sources */, 0A5D7D89135E37CB00D13E53 /* abstract_os_interface.cpp in Sources */, 0A5D7D8A135E37CB00D13E53 /* dummy_cpu_coordinate.cpp in Sources */, 0A5D7D8B135E37CB00D13E53 /* ilib_message_queue.cpp in Sources */, 0A5D7D8C135E37CB00D13E53 /* ilib_os_interface.cpp in Sources */, 0A5D7D8D135E37CB00D13E53 /* logical_core.cpp in Sources */, 0A5D7D8E135E37CB00D13E53 /* osx_os_interface.cpp in Sources */, 0A5D7D8F135E37CB00D13E53 /* posix_os_interface.cpp in Sources */, 0A5D7D90135E37CB00D13E53 /* process_memory_semantics.cpp in Sources */, 0A5D7D91135E37CB00D13E53 /* shared_memory_message_queue.cpp in Sources */, 0A5D7D92135E37CB00D13E53 /* shared_memory_message_queue_per_sender.cpp in Sources */, 0A5D7D93135E37CB00D13E53 /* thread_memory_semantics.cpp in Sources */, 0A5D7D94135E37CB00D13E53 /* tile_cpu_coordinate.cpp in Sources */, 0A5D7D95135E37CB00D13E53 /* RVMPlugin.cpp in Sources */, 0A5D7D96135E37CB00D13E53 /* abstract_mutex.cpp in Sources */, 0A5D7D97135E37CB00D13E53 /* abstract_tracer.cpp in Sources */, 0A5D7D98135E37CB00D13E53 /* bytemap.cpp in Sources */, 0A5D7D99135E37CB00D13E53 /* core_tracer.cpp in Sources */, 0A5D7D9A135E37CB00D13E53 /* debug_helper.cpp in Sources */, 0A5D7D9C135E37CB00D13E53 /* error_handling.cpp in Sources */, 0A5D7D9D135E37CB00D13E53 /* execution_tracer.cpp in Sources */, 0A5D7D9E135E37CB00D13E53 /* main.cpp in Sources */, 0A5D7D9F135E37CB00D13E53 /* measurements.cpp in Sources */, 0A5D7DA0135E37CB00D13E53 /* my_rank.cpp in Sources */, 0A5D7DA1135E37CB00D13E53 /* oop_tracer.cpp in Sources */, 0A5D7DA2135E37CB00D13E53 /* printer.cpp in Sources */, 0A5D7DA3135E37CB00D13E53 /* profiling_tracer.cpp in Sources */, 0A5D7DA4135E37CB00D13E53 /* rank_set.cpp in Sources */, 0A5D7DA5135E37CB00D13E53 /* rvm_bitmap.cpp in Sources */, 0A5D7DA6135E37CB00D13E53 /* rvm_config.cpp in Sources */, 0A5D7DA7135E37CB00D13E53 /* safepoint.cpp in Sources */, 0A5D7DA8135E37CB00D13E53 /* safepoint_ability.cpp in Sources */, 0A5D7DA9135E37CB00D13E53 /* safepoint_request_queue.cpp in Sources */, 0A5D7DAA135E37CB00D13E53 /* scheduler_mutex.cpp in Sources */, 0A5D7DAB135E37CB00D13E53 /* semaphore_mutex.cpp in Sources */, 0A5D7DAC135E37CB00D13E53 /* squeak_adapters.cpp in Sources */, 0A5D7DAD135E37CB00D13E53 /* timeout_deferral.cpp in Sources */, 0A5D7DAE135E37CB00D13E53 /* timeout_timer.cpp in Sources */, 0A5D7DAF135E37CB00D13E53 /* utils.cpp in Sources */, 0AA32BAA135EC5EE00B97FB8 /* sqFilePluginBasicPrims.c in Sources */, 0AA32BAB135EC5EE00B97FB8 /* Error.c in Sources */, 0AA32BAC135EC5EE00B97FB8 /* jcapimin.c in Sources */, 0AA32BAD135EC5EE00B97FB8 /* jcapistd.c in Sources */, 0AA32BAE135EC5EE00B97FB8 /* jccoefct.c in Sources */, 0AA32BAF135EC5EE00B97FB8 /* jccolor.c in Sources */, 0AA32BB0135EC5EE00B97FB8 /* jcdctmgr.c in Sources */, 0AA32BB1135EC5EE00B97FB8 /* jchuff.c in Sources */, 0AA32BB2135EC5EE00B97FB8 /* jcinit.c in Sources */, 0AA32BB3135EC5EE00B97FB8 /* jcmainct.c in Sources */, 0AA32BB4135EC5EE00B97FB8 /* jcmarker.c in Sources */, 0AA32BB5135EC5EE00B97FB8 /* jcmaster.c in Sources */, 0AA32BB6135EC5EE00B97FB8 /* jcomapi.c in Sources */, 0AA32BB7135EC5EE00B97FB8 /* jcparam.c in Sources */, 0AA32BB8135EC5EE00B97FB8 /* jcphuff.c in Sources */, 0AA32BB9135EC5EE00B97FB8 /* jcprepct.c in Sources */, 0AA32BBA135EC5EE00B97FB8 /* jcsample.c in Sources */, 0AA32BBB135EC5EE00B97FB8 /* jctrans.c in Sources */, 0AA32BBC135EC5EE00B97FB8 /* jdapimin.c in Sources */, 0AA32BBD135EC5EE00B97FB8 /* jdapistd.c in Sources */, 0AA32BBE135EC5EE00B97FB8 /* jdatadst.c in Sources */, 0AA32BBF135EC5EE00B97FB8 /* jdatasrc.c in Sources */, 0AA32BC0135EC5EE00B97FB8 /* jdcoefct.c in Sources */, 0AA32BC1135EC5EE00B97FB8 /* jdcolor.c in Sources */, 0AA32BC2135EC5EE00B97FB8 /* jddctmgr.c in Sources */, 0AA32BC3135EC5EE00B97FB8 /* jdhuff.c in Sources */, 0AA32BC4135EC5EE00B97FB8 /* jdinput.c in Sources */, 0AA32BC5135EC5EE00B97FB8 /* jdmainct.c in Sources */, 0AA32BC6135EC5EE00B97FB8 /* jdmarker.c in Sources */, 0AA32BC7135EC5EE00B97FB8 /* jdmaster.c in Sources */, 0AA32BC8135EC5EE00B97FB8 /* jdmerge.c in Sources */, 0AA32BC9135EC5EE00B97FB8 /* jdphuff.c in Sources */, 0AA32BCA135EC5EE00B97FB8 /* jdpostct.c in Sources */, 0AA32BCB135EC5EE00B97FB8 /* jdsample.c in Sources */, 0AA32BCC135EC5EE00B97FB8 /* jdtrans.c in Sources */, 0AA32BCD135EC5EE00B97FB8 /* jerror.c in Sources */, 0AA32BCE135EC5EE00B97FB8 /* jfdctflt.c in Sources */, 0AA32BCF135EC5EE00B97FB8 /* jfdctfst.c in Sources */, 0AA32BD0135EC5EE00B97FB8 /* jfdctint.c in Sources */, 0AA32BD1135EC5EE00B97FB8 /* jidctflt.c in Sources */, 0AA32BD2135EC5EE00B97FB8 /* jidctfst.c in Sources */, 0AA32BD3135EC5EE00B97FB8 /* jidctint.c in Sources */, 0AA32BD4135EC5EE00B97FB8 /* jidctred.c in Sources */, 0AA32BD5135EC5EE00B97FB8 /* jmemdatadst.c in Sources */, 0AA32BD6135EC5EE00B97FB8 /* jmemdatasrc.c in Sources */, 0AA32BD7135EC5EE00B97FB8 /* jmemmgr.c in Sources */, 0AA32BD8135EC5EE00B97FB8 /* jmemnobs.c in Sources */, 0AA32BD9135EC5EE00B97FB8 /* jquant1.c in Sources */, 0AA32BDA135EC5EE00B97FB8 /* jquant2.c in Sources */, 0AA32BDB135EC5EE00B97FB8 /* jutils.c in Sources */, 0AA32BDD135EC5EE00B97FB8 /* chartables.c in Sources */, 0AA32BDE135EC5EE00B97FB8 /* get.c in Sources */, 0AA32BDF135EC5EE00B97FB8 /* pcre.c in Sources */, 0AA32BE3135EC5EE00B97FB8 /* study.c in Sources */, 0AA32BE5135EC5EE00B97FB8 /* sqSoundCodecPluginBasicPrims.c in Sources */, 0AA32BE6135EC5EE00B97FB8 /* b3dAlloc.c in Sources */, 0AA32BE7135EC5EE00B97FB8 /* b3dDraw.c in Sources */, 0AA32BE8135EC5EE00B97FB8 /* b3dInit.c in Sources */, 0AA32BE9135EC5EE00B97FB8 /* b3dMain.c in Sources */, 0AA32BEA135EC5EE00B97FB8 /* b3dRemap.c in Sources */, 0AA32BEB135EC5EE00B97FB8 /* sqManualSurface.c in Sources */, 0AA32BEC135EC5EE00B97FB8 /* SurfacePlugin.c in Sources */, 0AA32BF2135EC61300B97FB8 /* sqNamedPrims.c in Sources */, 0AA32BF3135EC61300B97FB8 /* sqVirtualMachine.c in Sources */, 0AA32C00135EC69F00B97FB8 /* drawing.m in Sources */, 0AA32C02135EC69F00B97FB8 /* PDColoredProgressView.m in Sources */, 0AA32C04135EC69F00B97FB8 /* squeakProxy.m in Sources */, 0AA32C05135EC69F00B97FB8 /* squeakSUnitTester.m in Sources */, 0AA32C0B135EC6D900B97FB8 /* sqUnixAsynchFile.c in Sources */, 0AA32C0F135EC6F400B97FB8 /* dummyFFI.c in Sources */, 0AA32C17135EC70F00B97FB8 /* sqMacSecurity.c in Sources */, 0AA32C18135EC70F00B97FB8 /* sqSqueakSoundCoreAudio.m in Sources */, 0AA32C19135EC70F00B97FB8 /* sqSqueakSoundCoreAudioAPI.m in Sources */, 0AA32C7B135ECFDD00B97FB8 /* sqUnixExternalPrims.c in Sources */, 0ADE8A8F135F38B200D37EAD /* AsynchFilePlugin.c in Sources */, 0ADE8A90135F38B200D37EAD /* B2DPlugin.c in Sources */, 0ADE8A91135F38B200D37EAD /* BitBltPlugin.c in Sources */, 0ADE8A92135F38B200D37EAD /* BMPReadWriterPlugin.c in Sources */, 0ADE8A93135F38B200D37EAD /* DSAPrims.c in Sources */, 0ADE8A94135F38B200D37EAD /* FFTPlugin.c in Sources */, 0ADE8A95135F38B200D37EAD /* FilePlugin.c in Sources */, 0ADE8A96135F38B200D37EAD /* FloatArrayPlugin.c in Sources */, 0ADE8A97135F38B200D37EAD /* GeniePlugin.c in Sources */, 0ADE8A98135F38B200D37EAD /* HostWindowPlugin.c in Sources */, 0ADE8AB5135F38FE00D37EAD /* JPEGReaderPlugin.c in Sources */, 0ADE8AB6135F38FE00D37EAD /* JPEGReadWriter2Plugin.c in Sources */, 0ADE8AB7135F38FE00D37EAD /* Klatt.c in Sources */, 0ADE8AB8135F38FE00D37EAD /* LargeIntegers.c in Sources */, 0ADE8AB9135F38FE00D37EAD /* Matrix2x3Plugin.c in Sources */, 0ADE8ABA135F38FE00D37EAD /* MiscPrimitivePlugin.c in Sources */, 0ADE8ABB135F38FE00D37EAD /* ObjectiveCPlugin.c in Sources */, 0ADE8ABC135F38FE00D37EAD /* RePlugin.c in Sources */, 0ADE8ABD135F38FE00D37EAD /* SecurityPlugin.c in Sources */, 0ADE8ABE135F38FE00D37EAD /* SocketPlugin.c in Sources */, 0ADE8ABF135F38FE00D37EAD /* SoundCodecPrims.c in Sources */, 0ADE8AC0135F38FE00D37EAD /* SoundGenerationPlugin.c in Sources */, 0ADE8AC1135F38FE00D37EAD /* SoundPlugin.c in Sources */, 0ADE8AC2135F38FE00D37EAD /* Squeak3D.c in Sources */, 0ADE8ACC135F392E00D37EAD /* StarSqueakPlugin.c in Sources */, 0ADE8ACD135F392E00D37EAD /* UUIDPlugin.c in Sources */, 0ADE8ACE135F392E00D37EAD /* ZipPlugin.c in Sources */, 0ADE8ACF135F399D00D37EAD /* sqUnixSocket.c in Sources */, 0A040E2213B7526D007E172E /* performance_counters.cpp in Sources */, 0ABEA92513C26C7A003108B9 /* gc_debugging_tracer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 947E64DC10AA18FE00D3B69E /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( 947E64DD10AA18FE00D3B69E /* English */, ); name = MainMenu.xib; sourceTree = "<group>"; }; 94B6E9DC10BC777A00333E9E /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( 94B6E9D910BC775E00333E9E /* English */, ); name = Localizable.strings; path = ..; sourceTree = "<group>"; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 947E5F3610A9FD0400D3B69E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; CODE_SIGN_IDENTITY = "iPhone Developer: Engineer Bainomugisha (882W55QM4Q)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Engineer Bainomugisha (882W55QM4Q)"; CODE_SIGN_RESOURCE_RULES_PATH = "$(SDKROOT)/ResourceRules.plist"; GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = SQUEAK_BUILTIN_PLUGIN; GCC_VERSION = 4.2; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/uuid; ONLY_ACTIVE_ARCH = YES; PROVISIONING_PROFILE = "9A3C6CEC-E313-4BB0-B855-DBFA91037171"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "9A3C6CEC-E313-4BB0-B855-DBFA91037171"; SDKROOT = iphoneos; }; name = Debug; }; 947E5F3710A9FD0400D3B69E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CODE_SIGN_ENTITLEMENTS = ""; CODE_SIGN_IDENTITY = "iPhone Developer: David Ungar (X77TU3SX7E)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: David Ungar (X77TU3SX7E)"; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ../../../runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( USE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, "ISQUEAK_IMAGE=\"iPhone\"", "ISQUEAK_SOURCES=\"SqueakV3-minimum-MVC\"", TARGET_OS_IS_FOR_IPHONE, "Extra_Preheader_Word_Experiment=1", ); GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvmgcc42; HEADER_SEARCH_PATHS = ( /usr/include/uuid, ../../../runtime, ../../../from_squeak/iOS/vm/src/vm, ../../../from_squeak/iOS/vm/iPhone, ../../../from_squeak/Cross/vm/, ); INFOPLIST_FILE = "Info-iPhone.plist"; IPHONEOS_DEPLOYMENT_TARGET = 4.3; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-DROAR_VM", "-DHAVE_DLOPEN=1", ); PRODUCT_NAME = Squeak; PROVISIONING_PROFILE = "91607298-9968-43DA-98FC-32C6D6712CD6"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "91607298-9968-43DA-98FC-32C6D6712CD6"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = 2; }; name = Debug; }; 9480CD150E5C7D9300C32178 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; CODE_SIGN_RESOURCE_RULES_PATH = "$(SDKROOT)/ResourceRules.plist"; GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = SQUEAK_BUILTIN_PLUGIN; GCC_VERSION = 4.2; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/uuid; ONLY_ACTIVE_ARCH = YES; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "4D1323CE-3998-4FF8-AB83-49838083E965"; SDKROOT = iphoneos; }; name = Distribution; }; 9480CD160E5C7D9300C32178 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; CODE_SIGN_ENTITLEMENTS = Entitlements.plist; CODE_SIGN_IDENTITY = "iPhone Developer: David Ungar (X77TU3SX7E)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: David Ungar (X77TU3SX7E)"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ../../../runtime/rvm_config.h; GCC_PREPROCESSOR_DEFINITIONS = ( USE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, "ISQUEAK_IMAGE=\"iPhone\"", "ISQUEAK_SOURCES=\"SqueakV3-minimum-MVC\"", TARGET_OS_IS_FOR_IPHONE, "Extra_Preheader_Word_Experiment=1", ); GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvmgcc42; HEADER_SEARCH_PATHS = ( /usr/include/uuid, ../../../runtime, ../../../from_squeak/iOS/vm/src/vm, ../../../from_squeak/iOS/vm/iPhone, ../../../from_squeak/Cross/vm/, ); INFOPLIST_FILE = "Info-iPhone.plist"; IPHONEOS_DEPLOYMENT_TARGET = 4.3; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-fno-cse-follow-jumps", "-finline-functions", "-O3", "-fno-gcse", "-fomit-frame-pointer", "-DHAVE_DLOPEN=1", "-DROAR_VM", ); PRODUCT_NAME = Squeak; PROVISIONING_PROFILE = "91607298-9968-43DA-98FC-32C6D6712CD6"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "91607298-9968-43DA-98FC-32C6D6712CD6"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = 2; }; name = Distribution; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "RoarVMIPad" */ = { isa = XCConfigurationList; buildConfigurations = ( 947E5F3710A9FD0400D3B69E /* Debug */, 9480CD160E5C7D9300C32178 /* Distribution */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "RoarVMOnIPad" */ = { isa = XCConfigurationList; buildConfigurations = ( 947E5F3610A9FD0400D3B69E /* Debug */, 9480CD150E5C7D9300C32178 /* Distribution */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } ================================================ FILE: vm/src/from_squeak/iOS/vm/RoarVMSwipeEvent.h ================================================ // // RoarVMSwipeEvent.h // RoarVMOnIPad // #import <Foundation/Foundation.h> #import "RoarVMMouseEvent.h" @interface RoarVMSwipeEvent : RoarVMAbstractEvent { UISwipeGestureRecognizerDirection direction; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/RoarVMSwipeEvent.m ================================================ // // RoarVMSwipeEvent.m // RoarVMOnIPad // #import "RoarVMSwipeEvent.h" #import "sq.h" @implementation RoarVMSwipeEvent -(void) initFrom: (UISwipeGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where { [super initFrom: recognizer view: view where: where]; direction = recognizer.direction; } - (void) processInto: (sqInputEvent*)evt { [super processInto: evt]; // placeholder } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/Settings.bundle/Root.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Title</key> <string>RoarVM</string> <key>StringsTable</key> <string>Root</string> <key>PreferenceSpecifiers</key> <array> <dict> <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Startup</string> </dict> <dict> <key>Type</key> <string>PSToggleSwitchSpecifier</string> <key>Title</key> <string>Make Image writeable</string> <key>Key</key> <string>writeable_preference</string> <key>DefaultValue</key> <string>YES</string> <key>TrueValue</key> <string>YES</string> <key>FalseValue</key> <string>NO</string> </dict> <dict> <key>Type</key> <string>PSToggleSwitchSpecifier</string> <key>Title</key> <string>Use Scrolling View</string> <key>Key</key> <string>scrollableView_preference</string> <key>DefaultValue</key> <string>NO</string> <key>TrueValue</key> <string>YES</string> <key>FalseValue</key> <string>NO</string> </dict> <dict> <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Memory 20 MB to 132 MB (limited)</string> </dict> <dict> <key>Type</key> <string>PSSliderSpecifier</string> <key>Title</key> <string>Memory Size</string> <key>Key</key> <string>memorySize_preference</string> <key>DefaultValue</key> <integer>33554432</integer> <key>MinimumValue</key> <integer>20971520</integer> <key>MaximumValue</key> <integer>138412032</integer> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakNoOGLIPhone_Prefix.pch ================================================ // // Prefix header for all source files of the 'SqueakNoOGLIPhone' target in the 'SqueakNoOGLIPhone' project // #ifdef __OBJC__ #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #endif ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc-Info 64x64.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array> <string>image</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakImage.icns</string> <key>CFBundleTypeName</key> <string>Squeak Image File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STim</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sources</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakSources.icns</string> <key>CFBundleTypeName</key> <string>Squeak Sources File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STso</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>changes</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakChanges.icns</string> <key>CFBundleTypeName</key> <string>Squeak Changes File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STch</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sobj</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakScript.icns</string> <key>CFBundleTypeName</key> <string>Squeak Script File</string> <key>CFBundleTypeOSTypes</key> <array> <string>SOBJ</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>pr</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakProject.icns</string> <key>CFBundleTypeName</key> <string>Squeak Project File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STpr</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeName</key> <string>JPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>JPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TEXT</string> <key>CFBundleTypeOSTypes</key> <array> <string>TEXT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ttro</string> <key>CFBundleTypeOSTypes</key> <array> <string>ttro</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HTML</string> <key>CFBundleTypeOSTypes</key> <array> <string>HTML</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>RTF </string> <key>CFBundleTypeOSTypes</key> <array> <string>RTF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TIFF </string> <key>CFBundleTypeOSTypes</key> <array> <string>TIFF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PICT </string> <key>CFBundleTypeOSTypes</key> <array> <string>PICT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>URL </string> <key>CFBundleTypeOSTypes</key> <array> <string>URL</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ZIP </string> <key>CFBundleTypeOSTypes</key> <array> <string>ZIP</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>zip </string> <key>CFBundleTypeOSTypes</key> <array> <string>zip</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>BINA</string> <key>CFBundleTypeOSTypes</key> <array> <string>BINA</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>GIFf</string> <key>CFBundleTypeOSTypes</key> <array> <string>GIFf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PNGf</string> <key>CFBundleTypeOSTypes</key> <array> <string>PNGf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3 </string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>mp3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG2</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG2</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG3</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG </string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Mp3</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>M3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>M3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>SRCS</string> <key>CFBundleTypeOSTypes</key> <array> <string>SRCS</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Chng</string> <key>CFBundleTypeOSTypes</key> <array> <string>Chng</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HPS5</string> <key>CFBundleTypeOSTypes</key> <array> <string>HPS5</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> </array> <key>UTExportedTypeDeclarations</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Image File</string> <key>UTTypeIdentifier</key> <string>org.squeak.image</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STim</string> <key>public.filename-extension</key> <array> <string>image</string> </array> <key>public.mime-type</key> <string>application/squeak-image</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Sources File</string> <key>UTTypeIdentifier</key> <string>org.squeak.sources</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STso</string> <key>public.filename-extension</key> <array> <string>sources</string> </array> <key>public.mime-type</key> <string>application/squeak-sources</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Changes File</string> <key>UTTypeIdentifier</key> <string>org.squeak.changes</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STch</string> <key>public.filename-extension</key> <array> <string>changes</string> </array> <key>public.mime-type</key> <string>application/squeak-changes</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Script File</string> <key>UTTypeIdentifier</key> <string>org.squeak.script</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>SOBJ</string> <key>public.filename-extension</key> <array> <string>sobj</string> </array> <key>public.mime-type</key> <string>application/squeak-script</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Project File</string> <key>UTTypeIdentifier</key> <string>org.squeak.project</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STpr</string> <key>public.filename-extension</key> <array> <string>pr</string> </array> <key>public.mime-type</key> <string>application/x-squeak-project</string> </dict> </dict> </array> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleName</key> <string>Squeak VM Host 64/64bits</string> <key>CFBundleGetInfoString</key> <string>Squeak VM 5.7b3 64/64 bits http://www.squeak.org</string> <key>CFBundleIconFile</key> <string>Squeak.icns</string> <key>CFBundleIdentifier</key> <string>org.squeak.${PRODUCT_NAME:rfc1034identifier}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>5.7b3</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>21.0</string> <key>LSBackgroundOnly</key> <false/> <key>LSMinimumSystemVersion</key> <string>${MACOSX_DEPLOYMENT_TARGET}</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> <string>SqueakOSXApplication</string> <key>SqueakBrowserMouseCmdButton1</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton2</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton3</key> <integer>2</integer> <key>SqueakBrowserMouseControlButton1</key> <integer>1</integer> <key>SqueakBrowserMouseControlButton2</key> <integer>3</integer> <key>SqueakBrowserMouseControlButton3</key> <integer>2</integer> <key>SqueakBrowserMouseNoneButton1</key> <integer>1</integer> <key>SqueakBrowserMouseNoneButton2</key> <integer>3</integer> <key>SqueakBrowserMouseNoneButton3</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton1</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton2</key> <integer>3</integer> <key>SqueakBrowserMouseOptionButton3</key> <integer>2</integer> <key>SqueakDebug</key> <integer>0</integer> <key>SqueakExplicitWindowOpenNeeded</key> <false/> <key>SqueakImageName</key> <string>Squeak.image</string> <key>SqueakMaxHeapSize</key> <integer>536870912</integer> <key>SqueakMouseCmdButton1</key> <integer>3</integer> <key>SqueakMouseCmdButton2</key> <integer>3</integer> <key>SqueakMouseCmdButton3</key> <integer>2</integer> <key>SqueakMouseControlButton1</key> <integer>1</integer> <key>SqueakMouseControlButton2</key> <integer>3</integer> <key>SqueakMouseControlButton3</key> <integer>2</integer> <key>SqueakMouseNoneButton1</key> <integer>1</integer> <key>SqueakMouseNoneButton2</key> <integer>3</integer> <key>SqueakMouseNoneButton3</key> <integer>2</integer> <key>SqueakMouseOptionButton1</key> <integer>2</integer> <key>SqueakMouseOptionButton2</key> <integer>3</integer> <key>SqueakMouseOptionButton3</key> <integer>2</integer> <key>SqueakPluginsBuiltInOrLocalOnly</key> <true/> <key>SqueakQuitOnQuitAppleEvent</key> <false/> <key>SqueakResourceDirectory</key> <string></string> <key>SqueakTrustedDirectory</key> <string>/foobar/tooBar/forSqueak/bogus/</string> <key>SqueakUIFlushPrimaryDeferNMilliseconds</key> <integer>20</integer> <key>SqueakUnTrustedDirectory</key> <string>~/Library/Preferences/Squeak/Internet/My Squeak/</string> <key>SqueakUseFileMappedMMAP</key> <false/> <key>SqueakUIFadeForFullScreenInSeconds</key> <real>1.5</real> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc-Info.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array> <string>image</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakImage.icns</string> <key>CFBundleTypeName</key> <string>Squeak Image File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STim</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sources</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakSources.icns</string> <key>CFBundleTypeName</key> <string>Squeak Sources File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STso</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>changes</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakChanges.icns</string> <key>CFBundleTypeName</key> <string>Squeak Changes File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STch</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sobj</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakScript.icns</string> <key>CFBundleTypeName</key> <string>Squeak Script File</string> <key>CFBundleTypeOSTypes</key> <array> <string>SOBJ</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>pr</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakProject.icns</string> <key>CFBundleTypeName</key> <string>Squeak Project File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STpr</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeName</key> <string>JPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>JPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TEXT</string> <key>CFBundleTypeOSTypes</key> <array> <string>TEXT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ttro</string> <key>CFBundleTypeOSTypes</key> <array> <string>ttro</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HTML</string> <key>CFBundleTypeOSTypes</key> <array> <string>HTML</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>RTF </string> <key>CFBundleTypeOSTypes</key> <array> <string>RTF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TIFF </string> <key>CFBundleTypeOSTypes</key> <array> <string>TIFF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PICT </string> <key>CFBundleTypeOSTypes</key> <array> <string>PICT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>URL </string> <key>CFBundleTypeOSTypes</key> <array> <string>URL</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ZIP </string> <key>CFBundleTypeOSTypes</key> <array> <string>ZIP</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>zip </string> <key>CFBundleTypeOSTypes</key> <array> <string>zip</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>BINA</string> <key>CFBundleTypeOSTypes</key> <array> <string>BINA</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>GIFf</string> <key>CFBundleTypeOSTypes</key> <array> <string>GIFf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PNGf</string> <key>CFBundleTypeOSTypes</key> <array> <string>PNGf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3 </string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>mp3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG2</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG2</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG3</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG </string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Mp3</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>M3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>M3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>SRCS</string> <key>CFBundleTypeOSTypes</key> <array> <string>SRCS</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Chng</string> <key>CFBundleTypeOSTypes</key> <array> <string>Chng</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HPS5</string> <key>CFBundleTypeOSTypes</key> <array> <string>HPS5</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> </array> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleGetInfoString</key> <string>Squeak VM 5.7b3 http://www.squeak.org</string> <key>CFBundleIconFile</key> <string>Squeak.icns</string> <key>CFBundleIdentifier</key> <string>org.squeak.${PRODUCT_NAME:rfc1034identifier}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>Squeak VM Host 64/32bits</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>5.7b3</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>21.0</string> <key>LSBackgroundOnly</key> <false/> <key>LSMinimumSystemVersion</key> <string>${MACOSX_DEPLOYMENT_TARGET}</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> <string>SqueakOSXApplication</string> <key>SqueakBrowserMouseCmdButton1</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton2</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton3</key> <integer>2</integer> <key>SqueakBrowserMouseControlButton1</key> <integer>1</integer> <key>SqueakBrowserMouseControlButton2</key> <integer>3</integer> <key>SqueakBrowserMouseControlButton3</key> <integer>2</integer> <key>SqueakBrowserMouseNoneButton1</key> <integer>1</integer> <key>SqueakBrowserMouseNoneButton2</key> <integer>3</integer> <key>SqueakBrowserMouseNoneButton3</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton1</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton2</key> <integer>3</integer> <key>SqueakBrowserMouseOptionButton3</key> <integer>2</integer> <key>SqueakDebug</key> <integer>0</integer> <key>SqueakExplicitWindowOpenNeeded</key> <false/> <key>SqueakImageName</key> <string>rvm-base.image</string> <key>SqueakMaxHeapSize</key> <integer>536870912</integer> <key>SqueakMouseCmdButton1</key> <integer>3</integer> <key>SqueakMouseCmdButton2</key> <integer>3</integer> <key>SqueakMouseCmdButton3</key> <integer>2</integer> <key>SqueakMouseControlButton1</key> <integer>1</integer> <key>SqueakMouseControlButton2</key> <integer>3</integer> <key>SqueakMouseControlButton3</key> <integer>2</integer> <key>SqueakMouseNoneButton1</key> <integer>1</integer> <key>SqueakMouseNoneButton2</key> <integer>3</integer> <key>SqueakMouseNoneButton3</key> <integer>2</integer> <key>SqueakMouseOptionButton1</key> <integer>2</integer> <key>SqueakMouseOptionButton2</key> <integer>3</integer> <key>SqueakMouseOptionButton3</key> <integer>2</integer> <key>SqueakPluginsBuiltInOrLocalOnly</key> <false/> <key>SqueakQuitOnQuitAppleEvent</key> <false/> <key>SqueakResourceDirectory</key> <string></string> <key>SqueakTrustedDirectory</key> <string>/foobar/tooBar/forSqueak/bogus/</string> <key>SqueakUIFadeForFullScreenInSeconds</key> <real>0.5</real> <key>SqueakUIFlushPrimaryDeferNMilliseconds</key> <integer>20</integer> <key>SqueakUnTrustedDirectory</key> <string>~/Library/Preferences/Squeak/Internet/My Squeak/</string> <key>SqueakUseFileMappedMMAP</key> <false/> <key>UTExportedTypeDeclarations</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Image File</string> <key>UTTypeIdentifier</key> <string>org.squeak.image</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STim</string> <key>public.filename-extension</key> <array> <string>image</string> </array> <key>public.mime-type</key> <string>application/squeak-image</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Sources File</string> <key>UTTypeIdentifier</key> <string>org.squeak.sources</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STso</string> <key>public.filename-extension</key> <array> <string>sources</string> </array> <key>public.mime-type</key> <string>application/squeak-sources</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Changes File</string> <key>UTTypeIdentifier</key> <string>org.squeak.changes</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STch</string> <key>public.filename-extension</key> <array> <string>changes</string> </array> <key>public.mime-type</key> <string>application/squeak-changes</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Script File</string> <key>UTTypeIdentifier</key> <string>org.squeak.script</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>SOBJ</string> <key>public.filename-extension</key> <array> <string>sobj</string> </array> <key>public.mime-type</key> <string>application/squeak-script</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Project File</string> <key>UTTypeIdentifier</key> <string>org.squeak.project</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STpr</string> <key>public.filename-extension</key> <array> <string>pr</string> </array> <key>public.mime-type</key> <string>application/x-squeak-project</string> </dict> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc-InfoCOG.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array> <string>image</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakImage.icns</string> <key>CFBundleTypeName</key> <string>Squeak Image File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STim</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sources</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakSources.icns</string> <key>CFBundleTypeName</key> <string>Squeak Sources File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STso</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>changes</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakChanges.icns</string> <key>CFBundleTypeName</key> <string>Squeak Changes File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STch</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>sobj</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakScript.icns</string> <key>CFBundleTypeName</key> <string>Squeak Script File</string> <key>CFBundleTypeOSTypes</key> <array> <string>SOBJ</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeExtensions</key> <array> <string>pr</string> </array> <key>CFBundleTypeIconFile</key> <string>SqueakProject.icns</string> <key>CFBundleTypeName</key> <string>Squeak Project File</string> <key>CFBundleTypeOSTypes</key> <array> <string>STpr</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> <dict> <key>CFBundleTypeName</key> <string>JPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>JPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TEXT</string> <key>CFBundleTypeOSTypes</key> <array> <string>TEXT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ttro</string> <key>CFBundleTypeOSTypes</key> <array> <string>ttro</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HTML</string> <key>CFBundleTypeOSTypes</key> <array> <string>HTML</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>RTF </string> <key>CFBundleTypeOSTypes</key> <array> <string>RTF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>TIFF </string> <key>CFBundleTypeOSTypes</key> <array> <string>TIFF</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PICT </string> <key>CFBundleTypeOSTypes</key> <array> <string>PICT</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>URL </string> <key>CFBundleTypeOSTypes</key> <array> <string>URL</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>ZIP </string> <key>CFBundleTypeOSTypes</key> <array> <string>ZIP</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>zip </string> <key>CFBundleTypeOSTypes</key> <array> <string>zip</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>BINA</string> <key>CFBundleTypeOSTypes</key> <array> <string>BINA</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>GIFf</string> <key>CFBundleTypeOSTypes</key> <array> <string>GIFf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>PNGf</string> <key>CFBundleTypeOSTypes</key> <array> <string>PNGf</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3 </string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MP3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>MP3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPEG</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPEG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>mp3!</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3!</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG2</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG2</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG3</string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>MPG </string> <key>CFBundleTypeOSTypes</key> <array> <string>MPG</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Mp3</string> <key>CFBundleTypeOSTypes</key> <array> <string>mp3</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>M3U</string> <key>CFBundleTypeOSTypes</key> <array> <string>M3U</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>SRCS</string> <key>CFBundleTypeOSTypes</key> <array> <string>SRCS</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Chng</string> <key>CFBundleTypeOSTypes</key> <array> <string>Chng</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> <dict> <key>CFBundleTypeName</key> <string>HPS5</string> <key>CFBundleTypeOSTypes</key> <array> <string>HPS5</string> </array> <key>CFBundleTypeRole</key> <string>Viewer</string> </dict> </array> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleGetInfoString</key> <string>Squeak VM 5.8b12 http://www.squeak.org</string> <key>CFBundleIconFile</key> <string>Squeak.icns</string> <key>CFBundleIdentifier</key> <string>org.squeak.${PRODUCT_NAME:rfc1034identifier}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>Squeak VM Cog 32bits</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>5.8b12</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>30.0</string> <key>LSBackgroundOnly</key> <false/> <key>LSMinimumSystemVersion</key> <string>${MACOSX_DEPLOYMENT_TARGET}</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> <string>SqueakOSXApplication</string> <key>SqueakBrowserMouseCmdButton1</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton2</key> <integer>3</integer> <key>SqueakBrowserMouseCmdButton3</key> <integer>2</integer> <key>SqueakBrowserMouseControlButton1</key> <integer>1</integer> <key>SqueakBrowserMouseControlButton2</key> <integer>3</integer> <key>SqueakBrowserMouseControlButton3</key> <integer>2</integer> <key>SqueakBrowserMouseNoneButton1</key> <integer>1</integer> <key>SqueakBrowserMouseNoneButton2</key> <integer>3</integer> <key>SqueakBrowserMouseNoneButton3</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton1</key> <integer>2</integer> <key>SqueakBrowserMouseOptionButton2</key> <integer>3</integer> <key>SqueakBrowserMouseOptionButton3</key> <integer>2</integer> <key>SqueakDebug</key> <integer>0</integer> <key>SqueakExplicitWindowOpenNeeded</key> <false/> <key>SqueakImageName</key> <string>Squeak.image</string> <key>SqueakMaxHeapSize</key> <integer>536870912</integer> <key>SqueakMouseCmdButton1</key> <integer>3</integer> <key>SqueakMouseCmdButton2</key> <integer>3</integer> <key>SqueakMouseCmdButton3</key> <integer>2</integer> <key>SqueakMouseControlButton1</key> <integer>1</integer> <key>SqueakMouseControlButton2</key> <integer>3</integer> <key>SqueakMouseControlButton3</key> <integer>2</integer> <key>SqueakMouseNoneButton1</key> <integer>1</integer> <key>SqueakMouseNoneButton2</key> <integer>3</integer> <key>SqueakMouseNoneButton3</key> <integer>2</integer> <key>SqueakMouseOptionButton1</key> <integer>2</integer> <key>SqueakMouseOptionButton2</key> <integer>3</integer> <key>SqueakMouseOptionButton3</key> <integer>2</integer> <key>SqueakPluginsBuiltInOrLocalOnly</key> <true/> <key>SqueakQuitOnQuitAppleEvent</key> <false/> <key>SqueakResourceDirectory</key> <string></string> <key>SqueakTrustedDirectory</key> <string>/foobar/tooBar/forSqueak/bogus/</string> <key>SqueakUIFlushPrimaryDeferNMilliseconds</key> <integer>20</integer> <key>SqueakUnTrustedDirectory</key> <string>/foobar/tooBar/forSqueak/bogus/</string> <key>SqueakUseFileMappedMMAP</key> <false/> <key>SqueakUIFadeForFullScreenInSeconds</key> <real>0.75</real> <key>UTExportedTypeDeclarations</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Image File</string> <key>UTTypeIdentifier</key> <string>org.squeak.image</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STim</string> <key>public.filename-extension</key> <array> <string>image</string> </array> <key>public.mime-type</key> <string>application/squeak-image</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Sources File</string> <key>UTTypeIdentifier</key> <string>org.squeak.sources</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STso</string> <key>public.filename-extension</key> <array> <string>sources</string> </array> <key>public.mime-type</key> <string>application/squeak-sources</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.utf8-plain-text</string> </array> <key>UTTypeDescription</key> <string>Squeak Changes File</string> <key>UTTypeIdentifier</key> <string>org.squeak.changes</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STch</string> <key>public.filename-extension</key> <array> <string>changes</string> </array> <key>public.mime-type</key> <string>application/squeak-changes</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Script File</string> <key>UTTypeIdentifier</key> <string>org.squeak.script</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>SOBJ</string> <key>public.filename-extension</key> <array> <string>sobj</string> </array> <key>public.mime-type</key> <string>application/squeak-script</string> </dict> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.data</string> </array> <key>UTTypeDescription</key> <string>Squeak Project File</string> <key>UTTypeIdentifier</key> <string>org.squeak.project</string> <key>UTTypeTagSpecification</key> <dict> <key>com.apple.ostype</key> <string>STpr</string> <key>public.filename-extension</key> <array> <string>pr</string> </array> <key>public.mime-type</key> <string>application/x-squeak-project</string> </dict> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc.xcodeproj/MAC.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>043223C712D3706400260293</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 445}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 463}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>208 222 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>MyNewFile14.java</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>MyNewFile14.java</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {580, 277}}</string> <key>RubberWindowFrame</key> <string>208 222 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>277pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 282}, {580, 181}}</string> <key>RubberWindowFrame</key> <string>208 222 788 504 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>181pt</string> </dict> </array> <key>Proportion</key> <string>580pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>043223C512D3706400260293</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>043223C612D3706400260293</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>043223C812D3706400260293</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/SqueakPureObjc.xcodeproj</string> </array> <key>WindowString</key> <string>208 222 788 504 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {500, 218}}</string> <key>RubberWindowFrame</key> <string>267 201 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>218pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 223}, {500, 236}}</string> <key>RubberWindowFrame</key> <string>267 201 500 500 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>459pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>043223C812D3706400260293</string> <string>043223C912D3706400260293</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>267 201 500 500 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>043223C812D3706400260293</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugger</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {317, 164}}</string> <string>{{317, 0}, {377, 164}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 164}}</string> <string>{{0, 164}, {694, 216}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleDrawerSize</key> <string>{100, 120}</string> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 380}}</string> <key>RubberWindowFrame</key> <string>321 238 694 422 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C0AD2AB069F1E9B00FABCE6</string> <string>1C162984064C10D400B95A72</string> <string>1C0AD2AC069F1E9B00FABCE6</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>321 238 694 422 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.find</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528D0623707200166675</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 167}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>50%</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{8, 0}, {773, 254}}</string> <key>RubberWindowFrame</key> <string>62 385 781 470 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>50%</string> </dict> </array> <key>Proportion</key> <string>428pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>1C530D58069F1CE1000CFCEE</string> <string>1C530D59069F1CE1000CFCEE</string> <string>1CDD528C0622207200134675</string> <string>1C530D5A069F1CE1000CFCEE</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>62 385 781 470 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {650, 250}}</string> <key>RubberWindowFrame</key> <string>516 632 650 250 0 0 1680 1027 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>1C78EAAE065D492600B07095</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>650 41 650 250 0 0 1280 1002 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc.xcodeproj/MAC.pbxuser ================================================ // !$*UTF8*$! { 043223A412D3705C00260293 /* SqueakNoOGLIPhone */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakNoOGLIPhone; showTypeColumn = 0; sourceDirectories = ( ); }; 043223A512D3705C00260293 /* SqueakPureObjc */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakPureObjc; showTypeColumn = 0; sourceDirectories = ( ); }; 043223A612D3705C00260293 /* SqueakPureObjc64*64 */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = "SqueakPureObjc64*64"; showTypeColumn = 0; sourceDirectories = ( ); }; 043223CA12D3706500260293 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; }; 043223CB12D3706500260293 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */ = { activeExec = 0; executables = ( 043223A412D3705C00260293 /* SqueakNoOGLIPhone */, ); }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeBuildConfigurationName = Debug; activeExecutable = 043223A412D3705C00260293 /* SqueakNoOGLIPhone */; activeTarget = 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */; codeSenseManager = 043223CB12D3706500260293 /* Code sense */; executables = ( 043223A412D3705C00260293 /* SqueakNoOGLIPhone */, 043223A512D3705C00260293 /* SqueakPureObjc */, 043223A612D3705C00260293 /* SqueakPureObjc64*64 */, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 341, 20, 48.16259765625, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 315846749; PBXWorkspaceStateSaveDate = 315846749; }; sourceControlManager = 043223CA12D3706500260293 /* Source Control */; userBuildSettings = { }; }; 947E626F10AA098300D3B69E /* SqueakPureObjc */ = { activeExec = 0; executables = ( 043223A512D3705C00260293 /* SqueakPureObjc */, ); }; 948773F910C64DD800E4AEC5 /* SqueakPureObjc64*64 */ = { activeExec = 0; executables = ( 043223A612D3705C00260293 /* SqueakPureObjc64*64 */, ); }; } ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/MAC.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>04F521BB12B78AF70063E79B</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>29B97315FDCFA39411CA2CEA</string> <string>9424FF570DDCB17F009912BF</string> <string>94BCE77E0DDDF61200F38F31</string> <string>94BCE77F0DDDF61200F38F31</string> <string>94883B3F0E0C2B9C005A4738</string> <string>94BCE7840DDDF61200F38F31</string> <string>94BCE6880DDDECC200F38F31</string> <string>9424FF580DDCB18C009912BF</string> <string>9424FF590DDCB198009912BF</string> <string>9424FF5A0DDCB19F009912BF</string> <string>94E658DC0DDD03FE00358328</string> <string>94E658DF0DDD03FE00358328</string> <string>94E658E20DDD03FE00358328</string> <string>94584F6010F020BD001401E7</string> <string>29B97323FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>85</integer> <integer>55</integer> <integer>48</integer> <integer>46</integer> <integer>2</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 645}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 663}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>149 68 948 704 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>203pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>squeakProxy.m</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>squeakProxy.m</string> <key>history</key> <array> <string>04F521C112B78B350063E79B</string> <string>0477FABF12C188A200EB4B40</string> <string>0477FB1112C1969D00EB4B40</string> <string>0477FB1212C1969D00EB4B40</string> <string>0477FB1E12C1977D00EB4B40</string> <string>0477FB2112C1977D00EB4B40</string> <string>0477FB2212C1977D00EB4B40</string> <string>0477FB2312C1977D00EB4B40</string> <string>0477FB2512C1977D00EB4B40</string> <string>0477FB2612C1977D00EB4B40</string> <string>0477FB2712C1977D00EB4B40</string> <string>0477FB2812C1977D00EB4B40</string> <string>0477FB2912C1977D00EB4B40</string> <string>0477FB2A12C1977D00EB4B40</string> <string>0477FB2B12C1977D00EB4B40</string> <string>0477FB2C12C1977D00EB4B40</string> <string>0477FB2D12C1977D00EB4B40</string> <string>0477FB2E12C1977D00EB4B40</string> <string>0477FB2F12C1977D00EB4B40</string> <string>0477FB3012C1977D00EB4B40</string> <string>0477FB3112C1977D00EB4B40</string> <string>0477FB3212C1977D00EB4B40</string> <string>0477FB3312C1977D00EB4B40</string> <string>0477FB3412C1977D00EB4B40</string> <string>0477FB3512C1977D00EB4B40</string> <string>0477FB3612C1977D00EB4B40</string> <string>0477FB3712C1977D00EB4B40</string> <string>0477FB3812C1977D00EB4B40</string> <string>0477FB3912C1977D00EB4B40</string> <string>0477FB3A12C1977D00EB4B40</string> <string>04E0703B12C2D04C007397EE</string> <string>04E0703C12C2D04C007397EE</string> <string>04E0703E12C2D04C007397EE</string> <string>04E0703F12C2D04C007397EE</string> <string>04E0704012C2D04C007397EE</string> <string>04E0704112C2D04C007397EE</string> <string>04E0704212C2D04C007397EE</string> <string>043F2D5E12C2D42F003DD14E</string> <string>043F2D5F12C2D42F003DD14E</string> <string>043F2D6012C2D42F003DD14E</string> <string>043F2D6112C2D42F003DD14E</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {740, 353}}</string> <key>RubberWindowFrame</key> <string>149 68 948 704 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>353pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 358}, {740, 305}}</string> <key>RubberWindowFrame</key> <string>149 68 948 704 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>305pt</string> </dict> </array> <key>Proportion</key> <string>740pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>043F438612C38D8700503AE6</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>043F438712C38D8700503AE6</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>04F521BC12B78AF70063E79B</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/SqueakPureObjcCogVM.xcodeproj</string> </array> <key>WindowString</key> <string>149 68 948 704 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {832, 306}}</string> <key>RubberWindowFrame</key> <string>267 113 832 588 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>306pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 311}, {832, 236}}</string> <key>RubberWindowFrame</key> <string>267 113 832 588 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>547pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>04F521BC12B78AF70063E79B</string> <string>043F438812C38D8700503AE6</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>267 113 832 588 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>04F521BC12B78AF70063E79B</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {316, 198}}</string> <string>{{316, 0}, {378, 198}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 198}}</string> <string>{{0, 198}, {694, 183}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 381}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>120</real> <string>Value</string> <real>85</real> <string>Summary</string> <real>148</real> </array> <key>Frame</key> <string>{{316, 0}, {378, 198}}</string> <key>RubberWindowFrame</key> <string>194 312 694 422 0 0 1280 778 </string> </dict> <key>RubberWindowFrame</key> <string>194 312 694 422 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>381pt</string> </dict> </array> <key>Proportion</key> <string>381pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>04E0702C12C2D04C007397EE</string> <string>1C162984064C10D400B95A72</string> <string>04E0702D12C2D04C007397EE</string> <string>04E0702E12C2D04C007397EE</string> <string>04E0702F12C2D04C007397EE</string> <string>04E0703012C2D04C007397EE</string> <string>04E0703112C2D04C007397EE</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>194 312 694 422 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>sqNamedPrims.h</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>39 297 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>212pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 217}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>39 297 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>429pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>043F2D5812C2D3D6003DD14E</string> <string>043F2D5912C2D3D6003DD14E</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>39 297 781 470 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {650, 209}}</string> <key>RubberWindowFrame</key> <string>170 499 650 250 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Proportion</key> <string>209pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>0477FB4C12C1992500EB4B40</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>170 499 650 250 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/MAC.mode1v3~esteban_master ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>04F521BB12B78AF70063E79B</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array/> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>212</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>29B97315FDCFA39411CA2CEA</string> <string>9424FF570DDCB17F009912BF</string> <string>94BCE77E0DDDF61200F38F31</string> <string>94BCE77F0DDDF61200F38F31</string> <string>94E658DC0DDD03FE00358328</string> <string>94EF6CB911E55947003BA64D</string> <string>94EF6CBC11E55947003BA64D</string> <string>29B97323FDCFA39411CA2CEA</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {212, 604}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {229, 622}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>212</real> </array> <key>RubberWindowFrame</key> <string>224 98 889 663 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>229pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info-iPhone.plist</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Info-iPhone.plist</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>043FE5E912FD7CB60094027A</string> <key>history</key> <array> <string>0477FABF12C188A200EB4B40</string> <string>0477FB1212C1969D00EB4B40</string> <string>0477FB2112C1977D00EB4B40</string> <string>0477FB2212C1977D00EB4B40</string> <string>0477FB2312C1977D00EB4B40</string> <string>0477FB2512C1977D00EB4B40</string> <string>0477FB2612C1977D00EB4B40</string> <string>0477FB2712C1977D00EB4B40</string> <string>0477FB2812C1977D00EB4B40</string> <string>0477FB2912C1977D00EB4B40</string> <string>0477FB2A12C1977D00EB4B40</string> <string>0477FB2C12C1977D00EB4B40</string> <string>0477FB2D12C1977D00EB4B40</string> <string>0477FB2E12C1977D00EB4B40</string> <string>0477FB3012C1977D00EB4B40</string> <string>0477FB3112C1977D00EB4B40</string> <string>0477FB3212C1977D00EB4B40</string> <string>0477FB3312C1977D00EB4B40</string> <string>0477FB3412C1977D00EB4B40</string> <string>0477FB3512C1977D00EB4B40</string> <string>0477FB3612C1977D00EB4B40</string> <string>0477FB3712C1977D00EB4B40</string> <string>0477FB3812C1977D00EB4B40</string> <string>0477FB3912C1977D00EB4B40</string> <string>04E0703C12C2D04C007397EE</string> <string>04E0703F12C2D04C007397EE</string> <string>04E0704212C2D04C007397EE</string> <string>043F2D5E12C2D42F003DD14E</string> <string>043F2D5F12C2D42F003DD14E</string> <string>043F2D6112C2D42F003DD14E</string> <string>043F43E412C3976600503AE6</string> <string>040F1E9412CD2832008BA0CB</string> <string>040F1E9712CD2832008BA0CB</string> <string>040F1E9812CD2832008BA0CB</string> <string>040F1E9912CD2832008BA0CB</string> <string>040F1E9A12CD2832008BA0CB</string> <string>040F201112CD3625008BA0CB</string> <string>040F201312CD3625008BA0CB</string> <string>040F201412CD3625008BA0CB</string> <string>040F201512CD3625008BA0CB</string> <string>040F201612CD3625008BA0CB</string> <string>040F205412CD42D2008BA0CB</string> <string>040F207212CD525C008BA0CB</string> <string>040F20BC12CE0DE6008BA0CB</string> <string>040F20C412CE1042008BA0CB</string> <string>040F20EE12CE1309008BA0CB</string> <string>040F22EC12CE15A3008BA0CB</string> <string>040F232A12CE2C03008BA0CB</string> <string>040F232F12D0970F008BA0CB</string> <string>043223E412D3709700260293</string> <string>043223F212D3CC4700260293</string> <string>04F8801012D5055200C22208</string> <string>04F8801112D5055200C22208</string> <string>04B3FC0112F367E000666210</string> <string>04B3FC0212F367E000666210</string> <string>04B3FC8812F374A800666210</string> <string>043FE54A12FD6C160094027A</string> <string>043FE5E112FD7C830094027A</string> <string>043FE5E712FD7CB60094027A</string> <string>043FE5E812FD7CB60094027A</string> <string>043223F312D3CC4700260293</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {655, 380}}</string> <key>RubberWindowFrame</key> <string>224 98 889 663 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>380pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 385}, {655, 237}}</string> <key>RubberWindowFrame</key> <string>224 98 889 663 0 0 1280 778 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>237pt</string> </dict> </array> <key>Proportion</key> <string>655pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>043FE5E412FD7C830094027A</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>043FE5E512FD7C830094027A</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>0.0</real> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>1</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>04F521BC12B78AF70063E79B</string> <string>/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/SqueakPureObjcCogVM.xcodeproj</string> </array> <key>WindowString</key> <string>224 98 889 663 0 0 1280 778 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {832, 306}}</string> <key>RubberWindowFrame</key> <string>267 113 832 588 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>306pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1011</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 311}, {832, 236}}</string> <key>RubberWindowFrame</key> <string>267 113 832 588 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>236pt</string> </dict> </array> <key>Proportion</key> <string>547pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>04F521BC12B78AF70063E79B</string> <string>043FE5E612FD7C830094027A</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowContentMinSize</key> <string>486 300</string> <key>WindowString</key> <string>267 113 832 588 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>04F521BC12B78AF70063E79B</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {316, 203}}</string> <string>{{316, 0}, {378, 203}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {694, 203}}</string> <string>{{0, 203}, {694, 178}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {694, 381}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>120</real> <string>Value</string> <real>85</real> <string>Summary</string> <real>148</real> </array> <key>Frame</key> <string>{{316, 0}, {378, 203}}</string> <key>RubberWindowFrame</key> <string>194 312 694 422 0 0 1280 778 </string> </dict> <key>RubberWindowFrame</key> <string>194 312 694 422 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>381pt</string> </dict> </array> <key>Proportion</key> <string>381pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>04F87FAF12D4E63100C22208</string> <string>1C162984064C10D400B95A72</string> <string>04F87FB012D4E63100C22208</string> <string>04F87FB112D4E63100C22208</string> <string>04F87FB212D4E63100C22208</string> <string>04F87FB312D4E63100C22208</string> <string>04F87FB412D4E63100C22208</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>194 312 694 422 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>229 298 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>781pt</string> </dict> </array> <key>Proportion</key> <string>212pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 217}, {781, 212}}</string> <key>RubberWindowFrame</key> <string>229 298 781 470 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>212pt</string> </dict> </array> <key>Proportion</key> <string>429pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>04B3FC8612F3749200666210</string> <string>04B3FC8712F3749200666210</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>229 298 781 470 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {981, 441}}</string> <key>RubberWindowFrame</key> <string>276 284 981 482 0 0 1280 778 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>441pt</string> </dict> </array> <key>Proportion</key> <string>441pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>04F87FB512D4E63100C22208</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>276 284 981 482 0 0 1280 778 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <true/> </dict> <dict> <key>Identifier</key> <string>windowTool.snapshots</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <string>Yes</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>315 824 300 550 0 0 1440 878 </string> <key>WindowToolIsVisible</key> <string>Yes</string> </dict> <dict> <key>Identifier</key> <string>windowTool.scm</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string><No Editor></string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB3065D492600B07095</string> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <integer>1</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {452, 0}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>0pt</string> </dict> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ConsoleFrame</key> <string>{{0, 259}, {452, 0}}</string> <key>Frame</key> <string>{{0, 7}, {452, 259}}</string> <key>RubberWindowFrame</key> <string>743 379 452 308 0 0 1280 1002 </string> <key>TableConfiguration</key> <array> <string>Status</string> <real>30</real> <string>FileName</string> <real>199</real> <string>Path</string> <real>197.0950012207031</real> </array> <key>TableFrame</key> <string>{{0, 0}, {452, 250}}</string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>262pt</string> </dict> </array> <key>Proportion</key> <string>266pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1C78EAB4065D492600B07095</string> <string>1C78EAB5065D492600B07095</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>743 379 452 308 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>168</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {168, 350}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>0</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {185, 368}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>168</real> </array> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>185pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{190, 0}, {554, 368}}</string> <key>RubberWindowFrame</key> <string>315 424 744 409 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>554pt</string> </dict> </array> <key>Proportion</key> <string>368pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>TableOfContents</key> <array> <string>1CDDB66807F98D9800BB5817</string> <string>1CDDB66907F98D9800BB5817</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>315 424 744 409 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1CDDB66807F98D9800BB5817</string> <key>WindowToolIsVisible</key> <integer>1</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, all classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - NSObject</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {374, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {630, 331}}</string> <key>MembersFrame</key> <string>{{0, 105}, {374, 395}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>97</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>PBXModuleWindowStatusBarHidden2</key> <integer>1</integer> <key>RubberWindowFrame</key> <string>385 179 630 352 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Proportion</key> <string>332pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>1C0AD2B0069F1E9B00FABCE6</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>385 179 630 352 0 0 1440 878 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <integer>0</integer> </dict> <dict> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{0, 0}, {500, 335}</string> <key>RubberWindowFrame</key> <string>{0, 0}, {500, 335}</string> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>WindowString</key> <string>200 200 500 356 0 0 1920 1200 </string> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/MAC.pbxuser ================================================ // !$*UTF8*$! { 040F1E9412CD2832008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658F20DDD03FE00358328 /* FFTPlugin.c */; name = "FFTPlugin.c: 13"; rLen = 0; rLoc = 364; rType = 0; vrLen = 707; vrLoc = 0; }; 040F1E9712CD2832008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659970DDD053900358328 /* b3d.h */; name = "b3d.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 577; vrLoc = 0; }; 040F1E9812CD2832008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9494927E11E5178D0019BC29 /* cogit.h */; name = "cogit.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 928; vrLoc = 0; }; 040F1E9912CD2832008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9494928111E5178D0019BC29 /* cointerp.h */; name = "cointerp.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 949; vrLoc = 0; }; 040F1E9A12CD2832008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659980DDD053900358328 /* b3dAlloc.c */; name = "b3dAlloc.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 729; vrLoc = 0; }; 040F201112CD3625008BA0CB /* PlistBookmark */ = { isa = PlistBookmark; fRef = 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakBrowserMouseCmdButton3, ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/SqueakPureObjc-Info.plist"; rLen = 0; rLoc = 9223372036854775808; }; 040F201312CD3625008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */; name = "sqMacExtendedClipboard.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1076; vrLoc = 0; }; 040F201412CD3625008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */; name = "sqExternalSemaphores.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1011; vrLoc = 0; }; 040F201512CD3625008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E20F90EB2826C007957D0 /* sqFFI.h */; name = "sqFFI.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1057; vrLoc = 0; }; 040F201612CD3625008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */; name = "sqSoundCodecPluginBasicPrims.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 631; vrLoc = 0; }; 040F205412CD42D2008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */; name = "sqMacUnixExternalPrims.m: 295"; rLen = 0; rLoc = 10957; rType = 0; vrLen = 1163; vrLoc = 10140; }; 040F207212CD525C008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */; name = "sqSqueakAppDelegate.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1774; vrLoc = 0; }; 040F20BC12CE0DE6008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */; name = "UUIDPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 727; vrLoc = 0; }; 040F20C112CE0FFB008BA0CB /* UnixOSProcessPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {684, 60112}}"; sepNavSelRange = "{1263, 0}"; sepNavVisRange = "{921, 748}"; }; }; 040F20C412CE1042008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6591F0DDD03FE00358328 /* ZipPlugin.c */; name = "ZipPlugin.c: 1686"; rLen = 0; rLoc = 54016; rType = 0; vrLen = 624; vrLoc = 792; }; 040F20D412CE118B008BA0CB /* NSObjCRuntime.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObjCRuntime.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h; sourceTree = "<absolute>"; }; 040F20E212CE1283008BA0CB /* ObjectiveCPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 27157}}"; sepNavSelRange = "{822, 0}"; sepNavVisRange = "{0, 1355}"; }; }; 040F20EE12CE1309008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F20D412CE118B008BA0CB /* NSObjCRuntime.h */; name = "NSObjCRuntime.h: 132"; rLen = 0; rLoc = 4203; rType = 0; vrLen = 1570; vrLoc = 3767; }; 040F22EC12CE15A3008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F20E212CE1283008BA0CB /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 29"; rLen = 0; rLoc = 822; rType = 0; vrLen = 1355; vrLoc = 0; }; 040F230612CE1AE2008BA0CB /* SqueakFFIPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {785, 37284}}"; sepNavSelRange = "{772, 0}"; sepNavVisRange = "{67, 1233}"; }; }; 040F230D12CE1B28008BA0CB /* HostWindowPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {594, 5148}}"; sepNavSelRange = "{439, 0}"; sepNavVisRange = "{0, 806}"; sepNavWindowFrame = "{{15, 93}, {847, 680}}"; }; }; 040F232A12CE2C03008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F230612CE1AE2008BA0CB /* SqueakFFIPrims.c */; name = "SqueakFFIPrims.c: 28"; rLen = 0; rLoc = 772; rType = 0; vrLen = 1233; vrLoc = 67; }; 040F232F12D0970F008BA0CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */; name = "gcc3x-cointerp.c: 26017"; rLen = 0; rLoc = 821119; rType = 0; vrLen = 1528; vrLoc = 820039; }; 043223E412D3709700260293 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */; name = "sqMemoryAccess.h: 77"; rLen = 0; rLoc = 2378; rType = 0; vrLen = 2191; vrLoc = 1517; }; 043223F212D3CC4700260293 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */; name = "sqSqueakIPhoneApplication+attributes.m: 59"; rLen = 0; rLoc = 2444; rType = 0; vrLen = 1194; vrLoc = 1304; }; 043223F312D3CC4700260293 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94C36C9710B0CF290041953A /* Info-iPhone.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/Info-iPhone.plist"; rLen = 0; rLoc = 9223372036854775808; }; 043F2D5E12C2D42F003DD14E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */; name = "sqSqueakIPhoneInfoPlistInterface.m: 54"; rLen = 0; rLoc = 2264; rType = 0; vrLen = 1060; vrLoc = 2069; }; 043F2D5F12C2D42F003DD14E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6599A0DDD053900358328 /* b3dDraw.c */; name = "b3dDraw.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1031; vrLoc = 0; }; 043F2D6112C2D42F003DD14E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */; name = "sqNamedPrims.c: 9"; rLen = 0; rLoc = 327; rType = 0; vrLen = 647; vrLoc = 0; }; 043F43E412C3976600503AE6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659990DDD053900358328 /* b3dAlloc.h */; name = "b3dAlloc.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 735; vrLoc = 0; }; 043FE54A12FD6C160094027A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F230D12CE1B28008BA0CB /* HostWindowPlugin.c */; name = "HostWindowPlugin.c: 16"; rLen = 0; rLoc = 439; rType = 0; vrLen = 806; vrLoc = 0; }; 043FE5E112FD7C830094027A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94EF6CC011E55947003BA64D /* interp.h */; name = "interp.h: 12"; rLen = 0; rLoc = 319; rType = 0; vrLen = 620; vrLoc = 0; }; 043FE5E712FD7CB60094027A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */; name = "gcc3x-interp.c: 36497"; rLen = 0; rLoc = 1086798; rType = 0; vrLen = 1046; vrLoc = 1086749; }; 043FE5E812FD7CB60094027A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */; name = "ADPCMCodecPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 766; vrLoc = 0; }; 043FE5E912FD7CB60094027A /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94C36C9710B0CF290041953A /* Info-iPhone.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/Info-iPhone.plist"; rLen = 0; rLoc = 9223372036854775807; }; 0477FABF12C188A200EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 0477FAC012C188A200EB4B40 /* stdio.h */; name = "stdio.h: 75"; rLen = 14; rLoc = 3209; rType = 0; vrLen = 590; vrLoc = 2723; }; 0477FAC012C188A200EB4B40 /* stdio.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stdio.h; path = /Developer/SDKs/MacOSX10.5.sdk/usr/include/stdio.h; sourceTree = "<absolute>"; }; 0477FB1212C1969D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E659100DDD03FE00358328 /* SocketPlugin.c */; name = "SocketPlugin.c: 810"; rLen = 71; rLoc = 23631; rType = 0; vrLen = 941; vrLoc = 23153; }; 0477FB2112C1977D00EB4B40 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9414421E10BC89440088F8AC /* Squeak.icns */; }; 0477FB2212C1977D00EB4B40 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 94F3A9690E6BFA7C00E0B12A /* Squeak.png */; }; 0477FB2312C1977D00EB4B40 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9414421F10BC89440088F8AC /* SqueakChanges.icns */; }; 0477FB2512C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */; name = "SqueakNoOGLIPhoneAppDelegate.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1328; vrLoc = 0; }; 0477FB2612C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */; name = "SqueakNoOGLIPhoneAppDelegate.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1328; vrLoc = 0; }; 0477FB2712C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */; name = "SqueakOSXAppDelegate.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1318; vrLoc = 0; }; 0477FB2812C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */; name = "SqueakOSXAppDelegate.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1288; vrLoc = 0; }; 0477FB2912C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */; name = "SqueakOSXApplication.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1316; vrLoc = 0; }; 0477FB2A12C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */; name = "SqueakOSXApplication.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1316; vrLoc = 0; }; 0477FB2C12C1977D00EB4B40 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9414422310BC89440088F8AC /* SqueakProject.icns */; }; 0477FB2D12C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941724430F36624C0031AF33 /* squeakProxy.h */; name = "squeakProxy.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1227; vrLoc = 0; }; 0477FB2E12C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941724420F36624C0031AF33 /* squeakProxy.m */; name = "squeakProxy.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1008; vrLoc = 0; }; 0477FB3012C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */; name = "SqueakPureObjc_Prefix.pch: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 149; vrLoc = 0; }; 0477FB3112C1977D00EB4B40 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9414422410BC89440088F8AC /* SqueakScript.icns */; }; 0477FB3212C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */; name = "squeakSUnitTester.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1319; vrLoc = 0; }; 0477FB3312C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */; name = "SqueakUIController.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1373; vrLoc = 0; }; 0477FB3412C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */; name = "SqueakUIView.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1313; vrLoc = 0; }; 0477FB3512C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; name = "SqueakUIView.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1313; vrLoc = 0; }; 0477FB3612C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F48FA123C1C0C002B05DF /* SqueakUIViewCALayer.h */; name = "SqueakUIViewCALayer.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1307; vrLoc = 0; }; 0477FB3712C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */; name = "SqueakUIViewCALayer.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1277; vrLoc = 0; }; 0477FB3812C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F48FC123C1C0C002B05DF /* SqueakUIViewOpenGL.h */; name = "SqueakUIViewOpenGL.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1306; vrLoc = 0; }; 0477FB3912C1977D00EB4B40 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */; name = "SqueakUIViewOpenGL.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1306; vrLoc = 0; }; 04B3FC0112F367E000666210 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 949AD14911E542E8006D6BF4 /* SqueakPureObjc-InfoCOG.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleName, ); name = "/Users/MAC/Desktop/Dev/VM/cog-osx/platforms/iOS/vm/SqueakPureObjc-InfoCOG.plist"; rLen = 0; rLoc = 9223372036854775808; }; 04B3FC0212F367E000666210 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE7A60DDDF8F800F38F31 /* sqaio.h */; name = "sqaio.h: 39"; rLen = 73; rLoc = 1631; rType = 0; vrLen = 1103; vrLoc = 861; }; 04B3FC8812F374A800666210 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 040F20C112CE0FFB008BA0CB /* UnixOSProcessPlugin.c */; name = "UnixOSProcessPlugin.c: 46"; rLen = 0; rLoc = 1263; rType = 0; vrLen = 748; vrLoc = 921; }; 04E0703C12C2D04C007397EE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */; name = "SecurityPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 801; vrLoc = 0; }; 04E0703F12C2D04C007397EE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; name = "sqSqueakAppDelegate.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1152; vrLoc = 0; }; 04E0704212C2D04C007397EE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; name = "sqMacV2Memory.c: 150"; rLen = 0; rLoc = 5414; rType = 0; vrLen = 879; vrLoc = 6126; }; 04F521B312B78AED0063E79B /* SqueakNoOGLIPhone */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakNoOGLIPhone; showTypeColumn = 0; sourceDirectories = ( ); }; 04F521B412B78AED0063E79B /* SqueakPureObjc */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakPureObjc; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); variableFormatDictionary = { }; }; 04F521BE12B78AF70063E79B /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryNamesForRoots = { "" = ""; }; }; }; 04F521BF12B78AF70063E79B /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 04F8801012D5055200C22208 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */; name = "sqSqueakMainApp.m: 57"; rLen = 0; rLoc = 2273; rType = 0; vrLen = 681; vrLoc = 1967; }; 04F8801112D5055200C22208 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 29B97316FDCFA39411CA2CEA /* main.m */; name = "main.m: 40"; rLen = 0; rLoc = 1834; rType = 0; vrLen = 946; vrLoc = 1321; }; 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {796, 923}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1328}"; }; }; 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {796, 3432}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1328}"; }; }; 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */ = { activeExec = 0; executables = ( 04F521B312B78AED0063E79B /* SqueakNoOGLIPhone */, ); }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeBuildConfigurationName = Distribution; activeExecutable = 04F521B412B78AED0063E79B /* SqueakPureObjc */; activeTarget = 947E626F10AA098300D3B69E /* SqueakPureObjc */; addToTargets = ( 947E626F10AA098300D3B69E /* SqueakPureObjc */, ); codeSenseManager = 04F521BF12B78AF70063E79B /* Code sense */; executables = ( 04F521B312B78AED0063E79B /* SqueakNoOGLIPhone */, 04F521B412B78AED0063E79B /* SqueakPureObjc */, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 416, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 467, 60, 20, 48.16259765625, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 318602357; PBXWorkspaceStateSaveDate = 318602357; }; perUserProjectItems = { 040F1E9412CD2832008BA0CB /* PBXTextBookmark */ = 040F1E9412CD2832008BA0CB /* PBXTextBookmark */; 040F1E9712CD2832008BA0CB /* PBXTextBookmark */ = 040F1E9712CD2832008BA0CB /* PBXTextBookmark */; 040F1E9812CD2832008BA0CB /* PBXTextBookmark */ = 040F1E9812CD2832008BA0CB /* PBXTextBookmark */; 040F1E9912CD2832008BA0CB /* PBXTextBookmark */ = 040F1E9912CD2832008BA0CB /* PBXTextBookmark */; 040F1E9A12CD2832008BA0CB /* PBXTextBookmark */ = 040F1E9A12CD2832008BA0CB /* PBXTextBookmark */; 040F201112CD3625008BA0CB /* PlistBookmark */ = 040F201112CD3625008BA0CB /* PlistBookmark */; 040F201312CD3625008BA0CB /* PBXTextBookmark */ = 040F201312CD3625008BA0CB /* PBXTextBookmark */; 040F201412CD3625008BA0CB /* PBXTextBookmark */ = 040F201412CD3625008BA0CB /* PBXTextBookmark */; 040F201512CD3625008BA0CB /* PBXTextBookmark */ = 040F201512CD3625008BA0CB /* PBXTextBookmark */; 040F201612CD3625008BA0CB /* PBXTextBookmark */ = 040F201612CD3625008BA0CB /* PBXTextBookmark */; 040F205412CD42D2008BA0CB /* PBXTextBookmark */ = 040F205412CD42D2008BA0CB /* PBXTextBookmark */; 040F207212CD525C008BA0CB /* PBXTextBookmark */ = 040F207212CD525C008BA0CB /* PBXTextBookmark */; 040F20BC12CE0DE6008BA0CB /* PBXTextBookmark */ = 040F20BC12CE0DE6008BA0CB /* PBXTextBookmark */; 040F20C412CE1042008BA0CB /* PBXTextBookmark */ = 040F20C412CE1042008BA0CB /* PBXTextBookmark */; 040F20EE12CE1309008BA0CB /* PBXTextBookmark */ = 040F20EE12CE1309008BA0CB /* PBXTextBookmark */; 040F22EC12CE15A3008BA0CB /* PBXTextBookmark */ = 040F22EC12CE15A3008BA0CB /* PBXTextBookmark */; 040F232A12CE2C03008BA0CB /* PBXTextBookmark */ = 040F232A12CE2C03008BA0CB /* PBXTextBookmark */; 040F232F12D0970F008BA0CB /* PBXTextBookmark */ = 040F232F12D0970F008BA0CB /* PBXTextBookmark */; 043223E412D3709700260293 /* PBXTextBookmark */ = 043223E412D3709700260293 /* PBXTextBookmark */; 043223F212D3CC4700260293 /* PBXTextBookmark */ = 043223F212D3CC4700260293 /* PBXTextBookmark */; 043223F312D3CC4700260293 /* PlistBookmark */ = 043223F312D3CC4700260293 /* PlistBookmark */; 043F2D5E12C2D42F003DD14E /* PBXTextBookmark */ = 043F2D5E12C2D42F003DD14E /* PBXTextBookmark */; 043F2D5F12C2D42F003DD14E /* PBXTextBookmark */ = 043F2D5F12C2D42F003DD14E /* PBXTextBookmark */; 043F2D6112C2D42F003DD14E /* PBXTextBookmark */ = 043F2D6112C2D42F003DD14E /* PBXTextBookmark */; 043F43E412C3976600503AE6 /* PBXTextBookmark */ = 043F43E412C3976600503AE6 /* PBXTextBookmark */; 043FE54A12FD6C160094027A /* PBXTextBookmark */ = 043FE54A12FD6C160094027A /* PBXTextBookmark */; 043FE5E112FD7C830094027A /* PBXTextBookmark */ = 043FE5E112FD7C830094027A /* PBXTextBookmark */; 043FE5E712FD7CB60094027A /* PBXTextBookmark */ = 043FE5E712FD7CB60094027A /* PBXTextBookmark */; 043FE5E812FD7CB60094027A /* PBXTextBookmark */ = 043FE5E812FD7CB60094027A /* PBXTextBookmark */; 043FE5E912FD7CB60094027A /* PlistBookmark */ = 043FE5E912FD7CB60094027A /* PlistBookmark */; 0477FABF12C188A200EB4B40 /* PBXTextBookmark */ = 0477FABF12C188A200EB4B40 /* PBXTextBookmark */; 0477FB1212C1969D00EB4B40 /* PBXTextBookmark */ = 0477FB1212C1969D00EB4B40 /* PBXTextBookmark */; 0477FB2112C1977D00EB4B40 /* PBXBookmark */ = 0477FB2112C1977D00EB4B40 /* PBXBookmark */; 0477FB2212C1977D00EB4B40 /* PBXBookmark */ = 0477FB2212C1977D00EB4B40 /* PBXBookmark */; 0477FB2312C1977D00EB4B40 /* PBXBookmark */ = 0477FB2312C1977D00EB4B40 /* PBXBookmark */; 0477FB2512C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2512C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2612C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2612C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2712C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2712C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2812C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2812C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2912C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2912C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2A12C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2A12C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2C12C1977D00EB4B40 /* PBXBookmark */ = 0477FB2C12C1977D00EB4B40 /* PBXBookmark */; 0477FB2D12C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2D12C1977D00EB4B40 /* PBXTextBookmark */; 0477FB2E12C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB2E12C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3012C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3012C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3112C1977D00EB4B40 /* PBXBookmark */ = 0477FB3112C1977D00EB4B40 /* PBXBookmark */; 0477FB3212C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3212C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3312C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3312C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3412C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3412C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3512C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3512C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3612C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3612C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3712C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3712C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3812C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3812C1977D00EB4B40 /* PBXTextBookmark */; 0477FB3912C1977D00EB4B40 /* PBXTextBookmark */ = 0477FB3912C1977D00EB4B40 /* PBXTextBookmark */; 04B3FC0112F367E000666210 /* PlistBookmark */ = 04B3FC0112F367E000666210 /* PlistBookmark */; 04B3FC0212F367E000666210 /* PBXTextBookmark */ = 04B3FC0212F367E000666210 /* PBXTextBookmark */; 04B3FC8812F374A800666210 /* PBXTextBookmark */ = 04B3FC8812F374A800666210 /* PBXTextBookmark */; 04E0703C12C2D04C007397EE /* PBXTextBookmark */ = 04E0703C12C2D04C007397EE /* PBXTextBookmark */; 04E0703F12C2D04C007397EE /* PBXTextBookmark */ = 04E0703F12C2D04C007397EE /* PBXTextBookmark */; 04E0704212C2D04C007397EE /* PBXTextBookmark */ = 04E0704212C2D04C007397EE /* PBXTextBookmark */; 04F8801012D5055200C22208 /* PBXTextBookmark */ = 04F8801012D5055200C22208 /* PBXTextBookmark */; 04F8801112D5055200C22208 /* PBXTextBookmark */ = 04F8801112D5055200C22208 /* PBXTextBookmark */; }; sourceControlManager = 04F521BE12B78AF70063E79B /* Source Control */; userBuildSettings = { }; }; 29B97316FDCFA39411CA2CEA /* main.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 819}}"; sepNavSelRange = "{1834, 0}"; sepNavVisRange = "{1321, 946}"; }; }; 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {922, 1339}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1373}"; }; }; 941724420F36624C0031AF33 /* squeakProxy.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 2561}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1008}"; }; }; 941724430F36624C0031AF33 /* squeakProxy.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1248}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1227}"; }; }; 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {880, 2223}}"; sepNavSelRange = "{2378, 0}"; sepNavVisRange = "{1517, 2191}"; sepNavWindowFrame = "{{84, 30}, {847, 680}}"; }; }; 9424FF5D0DDCB1C7009912BF /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 7085}}"; sepNavSelRange = "{1104, 0}"; sepNavVisRange = "{818, 2005}"; sepNavWindowFrame = "{{38, 72}, {847, 680}}"; }; }; 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {789, 6799}}"; sepNavSelRange = "{327, 0}"; sepNavVisRange = "{0, 647}"; }; }; 9424FF610DDCB1C7009912BF /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {999, 4186}}"; sepNavSelRange = "{7199, 37}"; sepNavVisRange = "{6543, 962}"; }; }; 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1202, 2236}}"; sepNavSelRange = "{3898, 0}"; sepNavVisRange = "{3195, 1054}"; }; }; 9424FF650DDCB1EF009912BF /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 2158}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1222}"; }; }; 9424FF660DDCB1EF009912BF /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 301}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 302}"; }; }; 9424FF670DDCB202009912BF /* sqMacV2Memory.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {720, 2769}}"; sepNavSelRange = "{6099, 24}"; sepNavVisRange = "{5847, 420}"; }; }; 942F48FA123C1C0C002B05DF /* SqueakUIViewCALayer.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 624}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1307}"; }; }; 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1677}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1277}"; }; }; 942F48FC123C1C0C002B05DF /* SqueakUIViewOpenGL.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 975}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1306}"; }; }; 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 2613}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1306}"; }; }; 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1076, 1417}}"; sepNavSelRange = "{2038, 0}"; sepNavVisRange = "{1943, 548}"; }; }; 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 23036}}"; sepNavSelRange = "{1004, 45}"; sepNavVisRange = "{769, 348}"; }; }; 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 2145}}"; sepNavSelRange = "{2197, 24}"; sepNavVisRange = "{1974, 342}"; sepNavWindowFrame = "{{38, 72}, {847, 680}}"; }; }; 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 533}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1076}"; }; }; 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {950, 4108}}"; sepNavSelRange = "{10242, 69}"; sepNavVisRange = "{10427, 618}"; }; }; 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 702}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1774}"; }; }; 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1443}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1152}"; }; }; 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 2301}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1319}"; }; }; 947E20F90EB2826C007957D0 /* sqFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 507}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1057}"; }; }; 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 365}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 149}"; }; }; 947E626F10AA098300D3B69E /* SqueakPureObjc */ = { activeExec = 0; executables = ( 04F521B412B78AED0063E79B /* SqueakPureObjc */, ); }; 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 741}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1318}"; }; }; 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 2353}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1288}"; }; }; 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {788, 18616}}"; sepNavSelRange = "{207, 0}"; sepNavVisRange = "{0, 1781}"; sepNavWindowFrame = "{{61, 51}, {847, 680}}"; }; }; 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 559}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1316}"; }; }; 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 754}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1316}"; }; }; 9494927E11E5178D0019BC29 /* cogit.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1547}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 928}"; }; }; 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {894, 540826}}"; sepNavSelRange = "{1290722, 0}"; sepNavVisRange = "{1103611, 288}"; }; }; 9494928111E5178D0019BC29 /* cointerp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 2431}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 949}"; }; }; 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 3055}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1011}"; }; }; 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {720, 9204}}"; sepNavSelRange = "{8515, 16}"; sepNavVisRange = "{8291, 302}"; }; }; 949493BF11E52ADE0019BC29 /* aio.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {656, 5109}}"; sepNavSelRange = "{6270, 0}"; sepNavVisRange = "{5730, 631}"; }; }; 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 689}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1313}"; }; }; 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {803, 2509}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1313}"; }; }; 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1495}}"; sepNavSelRange = "{2069, 51}"; sepNavVisRange = "{1771, 393}"; }; }; 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1006, 3536}}"; sepNavSelRange = "{2776, 24}"; sepNavVisRange = "{2412, 415}"; }; }; 94BCE7A60DDDF8F800F38F31 /* sqaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {771, 1326}}"; sepNavSelRange = "{1704, 0}"; sepNavVisRange = "{1253, 586}"; }; }; 94E658E10DDD03FE00358328 /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 325}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 634}"; }; }; 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {852, 12480}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 680}"; }; }; 94E658E60DDD03FE00358328 /* B2DPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {859, 166426}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 931}"; }; }; 94E658F20DDD03FE00358328 /* FFTPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {782, 6539}}"; sepNavSelRange = "{364, 0}"; sepNavVisRange = "{0, 707}"; }; }; 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {817, 4368}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 801}"; }; }; 94E659100DDD03FE00358328 /* SocketPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1125, 21853}}"; sepNavSelRange = "{23836, 0}"; sepNavVisRange = "{23440, 462}"; sepNavWindowFrame = "{{15, 93}, {847, 680}}"; }; }; 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {810, 2080}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 727}"; }; }; 94E6591F0DDD03FE00358328 /* ZipPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 22061}}"; sepNavSelRange = "{54016, 0}"; sepNavVisRange = "{792, 624}"; }; }; 94E659200DDD03FE00358328 /* sqNamedPrims.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 988}}"; sepNavSelRange = "{1029, 24}"; sepNavVisRange = "{637, 895}"; }; }; 94E659970DDD053900358328 /* b3d.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1495}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 577}"; }; }; 94E659980DDD053900358328 /* b3dAlloc.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1716}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 729}"; }; }; 94E659990DDD053900358328 /* b3dAlloc.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 1989}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 735}"; }; }; 94E6599A0DDD053900358328 /* b3dDraw.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {679, 6552}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1031}"; }; }; 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {685, 50531}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 631}"; }; }; 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1307, 472901}}"; sepNavSelRange = "{1086798, 0}"; sepNavVisRange = "{1086749, 1046}"; }; }; 94EF6CC011E55947003BA64D /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {677, 348}}"; sepNavSelRange = "{319, 0}"; sepNavVisRange = "{0, 620}"; }; }; 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 1430}}"; sepNavSelRange = "{2264, 0}"; sepNavVisRange = "{2069, 1060}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/johnmci.mode1v3 ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ActivePerspectiveName</key> <string>Project</string> <key>AllowedModules</key> <array> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Name</key> <string>Groups and Files Outline View</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Name</key> <string>Editor</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCTaskListModule</string> <key>Name</key> <string>Task List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDetailModule</string> <key>Name</key> <string>File and Smart Group Detail Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Name</key> <string>Detailed Build Results Viewer</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXProjectFindModule</string> <key>Name</key> <string>Project Batch Find Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Name</key> <string>Project Format Conflicts List</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXBookmarksModule</string> <key>Name</key> <string>Bookmarks Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Name</key> <string>Class Browser</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXCVSModule</string> <key>Name</key> <string>Source Code Control Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXDebugBreakpointsModule</string> <key>Name</key> <string>Debug Breakpoints Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCDockableInspector</string> <key>Name</key> <string>Inspector</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>PBXOpenQuicklyModule</string> <key>Name</key> <string>Open Quickly Tool</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Name</key> <string>Debugger</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>1</string> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Name</key> <string>Debug Console</string> </dict> <dict> <key>BundleLoadPath</key> <string></string> <key>MaxInstances</key> <string>n</string> <key>Module</key> <string>XCSnapshotModule</string> <key>Name</key> <string>Snapshots Tool</string> </dict> </array> <key>BundlePath</key> <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string> <key>Description</key> <string>DefaultDescriptionKey</string> <key>DockingSystemVisible</key> <false/> <key>Extension</key> <string>mode1v3</string> <key>FavBarConfig</key> <dict> <key>PBXProjectModuleGUID</key> <string>9424FF4A0DDC8675009912BF</string> <key>XCBarModuleItemNames</key> <dict/> <key>XCBarModuleItems</key> <array/> </dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>com.apple.perspectives.project.mode1v3</string> <key>MajorVersion</key> <integer>33</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Default</string> <key>Notifications</key> <array> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusErrorsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusWarningsKey</key> <integer>2</integer> </dict> </dict> <dict> <key>XCObserverAutoDisconnectKey</key> <true/> <key>XCObserverDefintionKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>0</integer> </dict> <key>XCObserverFactoryKey</key> <string>XCPerspectivesSpecificationIdentifier</string> <key>XCObserverGUIDKey</key> <string>XCObserverProjectIdentifier</string> <key>XCObserverNotificationKey</key> <string>PBXStatusBuildStateMessageNotification</string> <key>XCObserverTargetKey</key> <string>XCMainBuildResultsModuleGUID</string> <key>XCObserverTriggerKey</key> <string>awakenModuleWithObserver:</string> <key>XCObserverValidationKey</key> <dict> <key>PBXStatusAnalyzerResultsKey</key> <integer>2</integer> </dict> </dict> </array> <key>OpenEditors</key> <array/> <key>PerspectiveWidths</key> <array> <integer>-1</integer> <integer>-1</integer> </array> <key>Perspectives</key> <array> <dict> <key>ChosenToolbarItems</key> <array> <string>active-combo-popup</string> <string>action</string> <string>NSToolbarFlexibleSpaceItem</string> <string>debugger-enable-breakpoints</string> <string>build-and-go</string> <string>com.apple.ide.PBXToolbarStopButton</string> <string>get-info</string> <string>NSToolbarFlexibleSpaceItem</string> <string>com.apple.pbx.toolbar.searchfield</string> </array> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProjectWithEditor</string> <key>Identifier</key> <string>perspective.project</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>22</real> <real>386</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>SCMStatusColumn</string> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>9412CAB20E6C037B00DB8625</string> <string>29B97315FDCFA39411CA2CEA</string> <string>9424FF570DDCB17F009912BF</string> <string>94BCE77E0DDDF61200F38F31</string> <string>9494932B11E527180019BC29</string> <string>94BCE77F0DDDF61200F38F31</string> <string>94883B3F0E0C2B9C005A4738</string> <string>94BCE6880DDDECC200F38F31</string> <string>9424FF580DDCB18C009912BF</string> <string>94BCE6890DDDECD600F38F31</string> <string>94E659420DDD04FA00358328</string> <string>946DA8EE10C0C38600F26F56</string> <string>94E659440DDD04FA00358328</string> <string>94BCE6860DDDECB800F38F31</string> <string>94E659510DDD053900358328</string> <string>94E65A280DDD053900358328</string> <string>94E6594C0DDD053900358328</string> <string>94E6599F0DDD053900358328</string> <string>94E659A20DDD053900358328</string> <string>94E6594E0DDD053900358328</string> <string>94E659920DDD053900358328</string> <string>9463943C0E95845000015851</string> <string>94E659960DDD053900358328</string> <string>947E20F80EB2826C007957D0</string> <string>94E659480DDD053900358328</string> <string>94E659900DDD053900358328</string> <string>9424FF590DDCB198009912BF</string> <string>947E642610AA0E1100D3B69E</string> <string>94C4B82C10C06F0D00CD4F90</string> <string>943B9B271235BD960056205E</string> <string>94584FD810F02378001401E7</string> <string>94B9528410E6B79E00DC476A</string> <string>94C4B82D10C06F1800CD4F90</string> <string>947E647610AA0FF200D3B69E</string> <string>9452D5EF0E044AC2000AD792</string> <string>9478E0220EC8D957007096A7</string> <string>9478E0270EC8D957007096A7</string> <string>9452D5F00E044AD1000AD792</string> <string>9424FF5A0DDCB19F009912BF</string> <string>94BCE6640DDDEB5000F38F31</string> <string>94BCE6650DDDEB5000F38F31</string> <string>080E96DDFE201D6D7F000001</string> <string>94E658DC0DDD03FE00358328</string> <string>94E658DD0DDD03FE00358328</string> <string>94E658DF0DDD03FE00358328</string> <string>94E658E20DDD03FE00358328</string> <string>94E658E30DDD03FE00358328</string> <string>94E658E50DDD03FE00358328</string> <string>94E658E90DDD03FE00358328</string> <string>94E658EB0DDD03FE00358328</string> <string>94584F6010F020BD001401E7</string> <string>946DA8D110C0C30D00F26F56</string> <string>94E658EF0DDD03FE00358328</string> <string>94E658F10DDD03FE00358328</string> <string>94E658F30DDD03FE00358328</string> <string>94E658F50DDD03FE00358328</string> <string>94E658F70DDD03FE00358328</string> <string>94E658F90DDD03FE00358328</string> <string>94E658FD0DDD03FE00358328</string> <string>94E658FF0DDD03FE00358328</string> <string>94E659010DDD03FE00358328</string> <string>94E659030DDD03FE00358328</string> <string>944069CC10E6B63200353B27</string> <string>94E659050DDD03FE00358328</string> <string>94E659070DDD03FE00358328</string> <string>94E659090DDD03FE00358328</string> <string>94210B270E956AC200C1A314</string> <string>94E6590B0DDD03FE00358328</string> <string>94E6590D0DDD03FE00358328</string> <string>94E6590F0DDD03FE00358328</string> <string>94E659110DDD03FE00358328</string> <string>94E659130DDD03FE00358328</string> <string>94E659150DDD03FE00358328</string> <string>94E659170DDD03FE00358328</string> <string>947E20F40EB281C5007957D0</string> <string>94E659190DDD03FE00358328</string> <string>94E6591B0DDD03FE00358328</string> <string>94E6591C0DDD03FE00358328</string> <string>94E6591E0DDD03FE00358328</string> <string>94EF6CB911E55947003BA64D</string> <string>94EF6CBC11E55947003BA64D</string> <string>29B97317FDCFA39411CA2CEA</string> <string>29B97323FDCFA39411CA2CEA</string> <string>19C28FACFE9D520D11CA2CBB</string> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>436</integer> <integer>435</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {408, 918}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <true/> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {425, 936}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>SCMStatusColumn</string> <real>22</real> <string>MainColumn</string> <real>386</real> </array> <key>RubberWindowFrame</key> <string>217 51 1243 977 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>425pt</string> </dict> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMacV2Memory.c</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>sqMacV2Memory.c</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> <string>949C3B171262C9C900F4EF15</string> <key>history</key> <array> <string>94547F160DE0AC7D00DD588F</string> <string>945481A60DE2A79200DD588F</string> <string>94B1514E0DE2CE530059F208</string> <string>945E9D7C0DE525E100CDF01E</string> <string>94F8E42E0DE6129D003F4F53</string> <string>94E297D10DECA72F009CF73A</string> <string>94E297D30DECA72F009CF73A</string> <string>94E297D50DECA72F009CF73A</string> <string>94E297D70DECA72F009CF73A</string> <string>94554E670DF1171500FB176B</string> <string>94554E690DF1171500FB176B</string> <string>94554EB80DF1A86A00FB176B</string> <string>94F5C1870DF26EF200099B11</string> <string>94F5C25F0DF42C7600099B11</string> <string>94F5C2600DF42C7600099B11</string> <string>94AB2E6A0E003879006A79E4</string> <string>94AB2E6C0E003879006A79E4</string> <string>945F30FC0E0C763800CFF3DC</string> <string>948704AE0E12CABF00D565C3</string> <string>9487071F0E132B1000D565C3</string> <string>94ED7EFA0E6C2ABE00F4DD03</string> <string>94B88C560E81500200C98131</string> <string>94F155570E83EA1F001657CE</string> <string>94F155580E83EA1F001657CE</string> <string>947332EE0EA70E8C003F9084</string> <string>942B77330EA7E642004B266D</string> <string>942B77380EA7E642004B266D</string> <string>942B779B0EA7F2E0004B266D</string> <string>942B779C0EA7F2E0004B266D</string> <string>942B77B90EA800E1004B266D</string> <string>942B77BB0EA800E1004B266D</string> <string>942B77C00EA800E1004B266D</string> <string>94638CEA0EB16F1100A3F155</string> <string>947E210C0EB28486007957D0</string> <string>9478E13D0EC8EB46007096A7</string> <string>94E2DAD40ED2351B00012E92</string> <string>94E2DB270ED2355F00012E92</string> <string>946D973B0FE165B70038846B</string> <string>9421AB550FF1807D008F54E9</string> <string>947E61D610AA049300D3B69E</string> <string>947E61DA10AA049300D3B69E</string> <string>947E61DC10AA049300D3B69E</string> <string>942ABEC510AA34820086D908</string> <string>94BCAD4A10AB981B00F87527</string> <string>94BCAE9010ACA3A300F87527</string> <string>94BCAFC710ACC89100F87527</string> <string>94C887D410ADCC0D007CB39E</string> <string>94C888B710ADE75B007CB39E</string> <string>94C88B6810AF26F8007CB39E</string> <string>94C2074310AF5FB7002F4160</string> <string>94C2091210AF7413002F4160</string> <string>94C2092A10AF769A002F4160</string> <string>94C2092D10AF769A002F4160</string> <string>94C367C010AF9C0A0041953A</string> <string>94C367C210AF9C0A0041953A</string> <string>94C367D110AF9C830041953A</string> <string>94C3696410AFB7550041953A</string> <string>94C3698D10B082DF0041953A</string> <string>94C3699110B082DF0041953A</string> <string>9484F86210B0DCC60038BDC0</string> <string>9484F86510B0DCC60038BDC0</string> <string>9484F8FC10B0E1770038BDC0</string> <string>9456C24F10B2F268000BF3DE</string> <string>9456C25A10B2F2C9000BF3DE</string> <string>9456C32210B32F43000BF3DE</string> <string>9456C34E10B33618000BF3DE</string> <string>9456C3CB10B341F9000BF3DE</string> <string>94F89AFE10B4997900556475</string> <string>94F89BDE10B4B77400556475</string> <string>94F89BE010B4B77400556475</string> <string>94F89C9110B4C0B800556475</string> <string>94D73E5210B5B9CE00F8C034</string> <string>94D73E5410B5B9CE00F8C034</string> <string>94D73E5610B5B9CE00F8C034</string> <string>94D73E5810B5B9CE00F8C034</string> <string>94D73E5A10B5B9CE00F8C034</string> <string>94D73E5C10B5B9CE00F8C034</string> <string>94D73E5E10B5B9CE00F8C034</string> <string>94D73E6010B5B9CE00F8C034</string> <string>94D73E6210B5B9CE00F8C034</string> <string>94D73E6410B5B9CE00F8C034</string> <string>94D73E6810B5B9CE00F8C034</string> <string>94D73E6A10B5B9CE00F8C034</string> <string>94D73EE610B5CF8400F8C034</string> <string>94D73F4910B5DA4E00F8C034</string> <string>94D73FA010B5E5A200F8C034</string> <string>94D73FAD10B5E69900F8C034</string> <string>94D73FB510B5E6DA00F8C034</string> <string>94D7401510B5F8AF00F8C034</string> <string>94D7403810B5FDDB00F8C034</string> <string>94D7403A10B5FDDB00F8C034</string> <string>94D740B210B6242000F8C034</string> <string>9406E7E210B663F4002F81F2</string> <string>9406E87110B66A74002F81F2</string> <string>9406E8CC10B67499002F81F2</string> <string>94D715CB10B723B200F69A71</string> <string>94D7174110B72FDF00F69A71</string> <string>94D7177D10B73A3800F69A71</string> <string>94D7178410B73A3800F69A71</string> <string>94D7178610B73A3800F69A71</string> <string>94D7178810B73A3800F69A71</string> <string>94D7178A10B73A3800F69A71</string> <string>94D7178C10B73A3800F69A71</string> <string>94D7179110B73A3800F69A71</string> <string>94D717BE10B73DD900F69A71</string> <string>94D717F810B743B800F69A71</string> <string>94D7183810B74BF300F69A71</string> <string>94D7183A10B74BF300F69A71</string> <string>94A1B2AA10B9E92A00C64473</string> <string>94A1B41E10BA05E600C64473</string> <string>94862F8310BA182500CAA2EB</string> <string>94862F9E10BA1A0100CAA2EB</string> <string>9486302A10BA247200CAA2EB</string> <string>9492450510BA42EF00E726F5</string> <string>9492450710BA42EF00E726F5</string> <string>9492450910BA42EF00E726F5</string> <string>949245B210BA4A6200E726F5</string> <string>945C4D7C10BB0A8500548CC1</string> <string>945C4EAC10BB348300548CC1</string> <string>9428BBAD10BB50E200DAD287</string> <string>9428BC5510BB74BF00DAD287</string> <string>9428BC5710BB74BF00DAD287</string> <string>9428BF3810BBC2ED00DAD287</string> <string>9428BF4F10BBCAAC00DAD287</string> <string>9473A34810BBD84100ED7D00</string> <string>94F5F29110BC518B00847EEE</string> <string>94F5F29210BC518B00847EEE</string> <string>94F5F29410BC518B00847EEE</string> <string>94F5F29510BC518B00847EEE</string> <string>94F5F2A810BC539700847EEE</string> <string>941441FD10BC817D0088F8AC</string> <string>9414420110BC817D0088F8AC</string> <string>949198B010BC8DFC00C629D1</string> <string>949198C910BC8FBB00C629D1</string> <string>94D16BFC10BCEFEE00A69A89</string> <string>94D16BFE10BCEFEE00A69A89</string> <string>94D16C2A10BCF28A00A69A89</string> <string>94D16C4010BCF3E100A69A89</string> <string>94D16CA310BCF93000A69A89</string> <string>9430325510BD0B6D0045D33B</string> <string>9430329A10BD103B0045D33B</string> <string>9430329B10BD103B0045D33B</string> <string>94E4930310BD32D00011AC75</string> <string>94CFE6A910BE63A900847DF5</string> <string>94CFE6B810BE63A900847DF5</string> <string>94CFE6B910BE63A900847DF5</string> <string>94CFE6C010BE63A900847DF5</string> <string>94CFE70110BE683800847DF5</string> <string>9475F4DB10BEF4100047A24B</string> <string>9475F56B10BF20A00047A24B</string> <string>9475F5A710BF25A10047A24B</string> <string>94E583DB10BF43970073FD63</string> <string>94E584AE10BF6EE30073FD63</string> <string>94E584FF10BF79AB0073FD63</string> <string>94E5850010BF79AB0073FD63</string> <string>948FAA0310BF855500BE88CF</string> <string>948FAB5B10BFAD3C00BE88CF</string> <string>946DA7E010C0A7A400F26F56</string> <string>946DA8D910C0C32800F26F56</string> <string>946DA8DA10C0C32800F26F56</string> <string>946DA8DB10C0C32800F26F56</string> <string>946DAA3810C0D8B700F26F56</string> <string>946DAA3A10C0D8B700F26F56</string> <string>946DAA3C10C0D8B700F26F56</string> <string>94F1F5C910C30C22008DB9CF</string> <string>947713D410C45E5F00890A9B</string> <string>94B7898910C4F95E005EA70D</string> <string>9402DDB610CE12A5005C2102</string> <string>94D3660B10CEE03900805023</string> <string>9493E98F10EE90BC000C4FB3</string> <string>9448940B10F3E8FF00FB3EC8</string> <string>947923FE1102BE53007C87F8</string> <string>9473A95A1102F70B00D135CB</string> <string>9473A9701103BE0A00D135CB</string> <string>948C0820112DE98D0017EE7F</string> <string>94E8EEEA11C94D5D0049D853</string> <string>949DDD6D11D141080017F79B</string> <string>949AD35211E54A81006D6BF4</string> <string>949AD36211E54AAA006D6BF4</string> <string>94EE1DAA11E57FAB00DC6E8C</string> <string>94E1BDAB11E5A9F400D5B92B</string> <string>941A331D11E63E1A004796BA</string> <string>941A331F11E63E1A004796BA</string> <string>9441DB7111E6805300345F6C</string> <string>9441DB7211E6805300345F6C</string> <string>9475A83511E6B5D50010FB38</string> <string>94238E5E11E7B0EB004401BE</string> <string>94F1F15C11EB8AB5004B3AE3</string> <string>9406B4DF11EC314E002670B7</string> <string>949F254511EC33FA00A34245</string> <string>949F254611EC33FA00A34245</string> <string>949F254811EC33FA00A34245</string> <string>94977E7C11EE46BC002BC5E9</string> <string>940E86A31220A8D200AAB6F5</string> <string>940E86EE1220AF3D00AAB6F5</string> <string>94AF3A1F12231A7200691409</string> <string>942807EE1224862A0000DCFE</string> <string>942807EF1224862A0000DCFE</string> <string>942807F01224862A0000DCFE</string> <string>94E8FA3C12258ED500EECD29</string> <string>940125A81228E3FC002883F0</string> <string>948034A9122A264A00C42504</string> <string>94059113122AFF8C009939CE</string> <string>943C0AC7122DF3710086B6AD</string> <string>943C0AC8122DF3710086B6AD</string> <string>943C0ACA122DF3710086B6AD</string> <string>943C0AE0122DF5E70086B6AD</string> <string>943C0AE2122DF5E70086B6AD</string> <string>943C0AE5122DF5E70086B6AD</string> <string>943C0AE7122DF5E70086B6AD</string> <string>94FE53951230323500BA17E1</string> <string>9415C07412306BDD0067CD8E</string> <string>946C240C1230A80A004938A1</string> <string>94CAE0ED1230DE6C00AFE487</string> <string>94C7480712333A2900B1F982</string> <string>9453F58A1234AF8A00C91CF7</string> <string>9453F58C1234AF8A00C91CF7</string> <string>9453F58D1234AF8A00C91CF7</string> <string>9453F5911234AF8A00C91CF7</string> <string>9453F5931234AF8A00C91CF7</string> <string>9453F5951234AF8A00C91CF7</string> <string>943B9B151235BB080056205E</string> <string>943B9B1E1235BD150056205E</string> <string>943B9BD31235C1120056205E</string> <string>943B9BD41235C1120056205E</string> <string>943B9C041235C1EE0056205E</string> <string>943B9C311235C3D70056205E</string> <string>943B9C331235C3D70056205E</string> <string>943B9D621235C79C0056205E</string> <string>94C3CD4E1235C80200A4E319</string> <string>94E7F6B812373EB800A03A11</string> <string>94AC16D912395FF10067037A</string> <string>94AC16DA12395FF10067037A</string> <string>94AC16DC12395FF10067037A</string> <string>94AC16DE12395FF10067037A</string> <string>94C16B42123D72AE00A8622A</string> <string>94C16B43123D72AE00A8622A</string> <string>94C16B5A123D735F00A8622A</string> <string>94BE8B9C123DA0C900C89FDD</string> <string>94BE8BAD123DA0EB00C89FDD</string> <string>94BE8BD5123DA32300C89FDD</string> <string>94BE8BF5123DA42700C89FDD</string> <string>94700A50123DF62D00874318</string> <string>94700A51123DF62D00874318</string> <string>94700AAD123DFCEA00874318</string> <string>94C8D197123EDAD30019544B</string> <string>94C8D19A123EDAD30019544B</string> <string>94C8D19B123EDAD30019544B</string> <string>94C8D19C123EDAD30019544B</string> <string>9451E64F123F0E9200B4119F</string> <string>948127E812444F7800BD1543</string> <string>948127E912444F7800BD1543</string> <string>948127EA12444F7800BD1543</string> <string>948127EB12444F7800BD1543</string> <string>947E9920125D73FD0048E783</string> <string>947E9964125D756D0048E783</string> <string>947E9967125D756D0048E783</string> <string>947E9969125D756D0048E783</string> <string>947E996B125D756D0048E783</string> <string>947E996D125D756D0048E783</string> <string>947E996F125D756D0048E783</string> <string>947E9971125D756D0048E783</string> <string>947E9994125D76820048E783</string> <string>947E99A0125D76BB0048E783</string> <string>947E99FA125D7B850048E783</string> <string>9427E35512626DFB002DCA6D</string> <string>9427E37B12626EE6002DCA6D</string> <string>9427E3F612627C61002DCA6D</string> <string>9427E3F812627C61002DCA6D</string> <string>9427E3F912627C61002DCA6D</string> <string>9427E44B12628333002DCA6D</string> <string>9427E44C12628333002DCA6D</string> <string>9427E44D12628333002DCA6D</string> <string>9427E46212629AE3002DCA6D</string> <string>9427E46312629AE3002DCA6D</string> <string>9427E4D11262B997002DCA6D</string> <string>9427E4D21262B997002DCA6D</string> <string>94EF43151262BFC100817F37</string> <string>949C3A281262C1F700F4EF15</string> <string>949C3A441262C2D200F4EF15</string> <string>949C3AFE1262C91300F4EF15</string> <string>949C3AFF1262C91300F4EF15</string> </array> </dict> <key>SplitCount</key> <string>1</string> </dict> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {813, 734}}</string> <key>RubberWindowFrame</key> <string>217 51 1243 977 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>734pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CE0B20506471E060097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 739}, {813, 197}}</string> <key>RubberWindowFrame</key> <string>217 51 1243 977 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>197pt</string> </dict> </array> <key>Proportion</key> <string>813pt</string> </dict> </array> <key>Name</key> <string>Project</string> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> <string>XCModuleDock</string> <string>PBXNavigatorGroup</string> <string>XCDetailModule</string> </array> <key>TableOfContents</key> <array> <string>949C3AE31262C82500F4EF15</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>949C3AE41262C82500F4EF15</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> <key>ToolbarConfigUserDefaultsMinorVersion</key> <string>2</string> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.defaultV3</string> </dict> <dict> <key>ControllerClassBaseName</key> <string></string> <key>IconName</key> <string>WindowOfProject</string> <key>Identifier</key> <string>perspective.morph</string> <key>IsVertical</key> <integer>0</integer> <key>Layout</key> <array> <dict> <key>BecomeActive</key> <integer>1</integer> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> <string>1C08E77C0454961000C914BD</string> <string>1C37FABC05509CD000000102</string> <string>1C37FABC05539CD112110102</string> <string>E2644B35053B69B200211256</string> <string>1C37FABC04509CD000100104</string> <string>1CC0EA4004350EF90044410B</string> <string>1CC0EA4004350EF90041110B</string> </array> <key>PBXProjectModuleGUID</key> <string>11E0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>yes</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>186</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>29B97314FDCFA39411CA2CEA</string> <string>1C37FABC05509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {186, 337}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <integer>1</integer> <key>XCSharingToken</key> <string>com.apple.Xcode.GFSharingToken</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {203, 355}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>186</real> </array> <key>RubberWindowFrame</key> <string>373 269 690 397 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Morph</string> <key>PreferredWidth</key> <integer>300</integer> <key>ServiceClasses</key> <array> <string>XCModuleDock</string> <string>PBXSmartGroupTreeModule</string> </array> <key>TableOfContents</key> <array> <string>11E0B1FE06471DED0097A5F4</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.default.shortV3</string> </dict> </array> <key>PerspectivesBarVisible</key> <false/> <key>ShelfIsVisible</key> <false/> <key>SourceDescription</key> <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string> <key>StatusbarIsVisible</key> <true/> <key>TimeStamp</key> <real>308464073.06916898</real> <key>ToolbarDisplayMode</key> <integer>1</integer> <key>ToolbarIsVisible</key> <true/> <key>ToolbarSizeMode</key> <integer>2</integer> <key>Type</key> <string>Perspectives</string> <key>UpdateMessage</key> <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string> <key>WindowJustification</key> <integer>5</integer> <key>WindowOrderList</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>1C530D57069F1CE1000CFCEE</string> <string>9424FF6E0DDCB226009912BF</string> <string>/Volumes/330GB Photos/Cog/platforms/iOS/vm/SqueakPureObjcCogVM.xcodeproj</string> </array> <key>WindowString</key> <string>217 51 1243 977 0 0 1680 1028 </string> <key>WindowToolsV3</key> <array> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.build</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>gcc3x-cointerp.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1332, 678}}</string> <key>RubberWindowFrame</key> <string>297 105 1332 919 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>678pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>XCMainBuildResultsModuleGUID</string> <key>PBXProjectModuleLabel</key> <string>Build Results</string> <key>XCBuildResultsTrigger_Collapse</key> <integer>1021</integer> <key>XCBuildResultsTrigger_Open</key> <integer>1013</integer> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 683}, {1332, 195}}</string> <key>RubberWindowFrame</key> <string>297 105 1332 919 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXBuildResultsModule</string> <key>Proportion</key> <string>195pt</string> </dict> </array> <key>Proportion</key> <string>878pt</string> </dict> </array> <key>Name</key> <string>Build Results</string> <key>ServiceClasses</key> <array> <string>PBXBuildResultsModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9424FF6E0DDCB226009912BF</string> <string>949C3AC11262C59600F4EF15</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.buildV3</string> <key>WindowString</key> <string>297 105 1332 919 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9424FF6E0DDCB226009912BF</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debugger</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>Debugger</key> <dict> <key>HorizontalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {150, 491}}</string> <string>{{150, 0}, {1226, 491}}</string> </array> </dict> <key>VerticalSplitView</key> <dict> <key>_collapsingFrameDimension</key> <real>0.0</real> <key>_indexOfCollapsedView</key> <integer>0</integer> <key>_percentageOfCollapsedView</key> <real>0.0</real> <key>isCollapsed</key> <string>yes</string> <key>sizes</key> <array> <string>{{0, 0}, {1376, 491}}</string> <string>{{0, 491}, {1376, 436}}</string> </array> </dict> </dict> <key>LauncherConfigVersion</key> <string>8</string> <key>PBXProjectModuleGUID</key> <string>1C162984064C10D400B95A72</string> <key>PBXProjectModuleLabel</key> <string>Debug - GLUTExamples (Underwater)</string> </dict> <key>GeometryConfiguration</key> <dict> <key>DebugConsoleVisible</key> <string>None</string> <key>DebugConsoleWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>DebugSTDIOWindowFrame</key> <string>{{200, 200}, {500, 300}}</string> <key>Frame</key> <string>{{0, 0}, {1376, 927}}</string> <key>PBXDebugSessionStackFrameViewKey</key> <dict> <key>DebugVariablesTableConfiguration</key> <array> <string>Name</string> <real>243</real> <string>Value</string> <real>245</real> <string>Summary</string> <real>713</real> </array> <key>Frame</key> <string>{{150, 0}, {1226, 491}}</string> <key>RubberWindowFrame</key> <string>304 60 1376 968 0 0 1680 1028 </string> </dict> <key>RubberWindowFrame</key> <string>304 60 1376 968 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugSessionModule</string> <key>Proportion</key> <string>927pt</string> </dict> </array> <key>Proportion</key> <string>927pt</string> </dict> </array> <key>Name</key> <string>Debugger</string> <key>ServiceClasses</key> <array> <string>PBXDebugSessionModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> <string>949C3B061262C99F00F4EF15</string> <string>1C162984064C10D400B95A72</string> <string>949C3B071262C99F00F4EF15</string> <string>949C3B081262C99F00F4EF15</string> <string>949C3B091262C99F00F4EF15</string> <string>949C3B0A1262C99F00F4EF15</string> <string>949C3B0B1262C99F00F4EF15</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> <key>WindowString</key> <string>304 60 1376 968 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.find</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> <string>gcc3x-cointerp.c</string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1387, 597}}</string> <key>RubberWindowFrame</key> <string>293 12 1387 982 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>1387pt</string> </dict> </array> <key>Proportion</key> <string>597pt</string> </dict> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528E0623707200166675</string> <key>PBXProjectModuleLabel</key> <string>Project Find</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 602}, {1387, 339}}</string> <key>RubberWindowFrame</key> <string>293 12 1387 982 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXProjectFindModule</string> <key>Proportion</key> <string>339pt</string> </dict> </array> <key>Proportion</key> <string>941pt</string> </dict> </array> <key>Name</key> <string>Project Find</string> <key>ServiceClasses</key> <array> <string>PBXProjectFindModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> <string>949C3AEA1262C87A00F4EF15</string> <string>949C3AEB1262C87A00F4EF15</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> <key>WindowString</key> <string>293 12 1387 982 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>MENUSEPARATOR</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.debuggerConsole</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAAC065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string>Debugger Console</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1619, 787}}</string> <key>RubberWindowFrame</key> <string>61 137 1619 828 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXDebugCLIModule</string> <key>Proportion</key> <string>787pt</string> </dict> </array> <key>Proportion</key> <string>787pt</string> </dict> </array> <key>Name</key> <string>Debugger Console</string> <key>ServiceClasses</key> <array> <string>PBXDebugCLIModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> <string>9427E36F12626E8F002DCA6D</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.consoleV3</string> <key>WindowString</key> <string>61 137 1619 828 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C78EAAD065D492600B07095</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.snapshots</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>945480600DE1484B00DD588F</string> <key>PBXProjectModuleLabel</key> <string>Snapshots</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1593, 926}}</string> <key>RubberWindowFrame</key> <string>-19 61 1593 967 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCSnapshotModule</string> <key>Proportion</key> <string>926pt</string> </dict> </array> <key>Proportion</key> <string>926pt</string> </dict> </array> <key>Name</key> <string>Snapshots</string> <key>ServiceClasses</key> <array> <string>XCSnapshotModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>945480610DE1484B00DD588F</string> <string>94F7102110C332830095BDD8</string> <string>945480600DE1484B00DD588F</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.snapshots</string> <key>WindowString</key> <string>-19 61 1593 967 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>945480610DE1484B00DD588F</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.scm</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1C78EAB2065D492600B07095</string> <key>PBXProjectModuleLabel</key> <string></string> <key>StatusBarVisibility</key> <true/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1582, 298}}</string> <key>RubberWindowFrame</key> <string>98 4 1582 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>298pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXCVSModuleFilterTypeKey</key> <integer>1031</integer> <key>PBXCVSModuleTreeModuleColumnData</key> <dict> <key>PBXCVSModuleTreeModuleColumnWidthsKey</key> <array> <real>1000</real> <real>56</real> <real>63</real> <real>60</real> <real>63</real> <real>139</real> </array> <key>PBXCVSModuleTreeModuleColumnsKey</key> <array> <string>Name</string> <string>Status</string> <string>Update</string> <string>Revision</string> <string>Author</string> <string>Date</string> </array> </dict> <key>PBXProjectModuleGUID</key> <string>1CD052920623707200166675</string> <key>PBXProjectModuleLabel</key> <string>SCM Results</string> <key>SCMActivityViewerShowingDefaultKey</key> <string>{{0, 576}, {1582, 104}}</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 303}, {1582, 680}}</string> <key>RubberWindowFrame</key> <string>98 4 1582 1024 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXCVSModule</string> <key>Proportion</key> <string>680pt</string> </dict> </array> <key>Proportion</key> <string>983pt</string> </dict> </array> <key>Name</key> <string>SCM</string> <key>ServiceClasses</key> <array> <string>PBXCVSModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>9488792B0E0F2F8000555242</string> <string>9427E4FD1262BB49002DCA6D</string> <string>1C78EAB2065D492600B07095</string> <string>1CD052920623707200166675</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.scm</string> <key>WindowString</key> <string>98 4 1582 1024 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>9488792B0E0F2F8000555242</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.breakpoints</string> <key>IsVertical</key> <false/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXBottomSmartGroupGIDs</key> <array> <string>1C77FABC04509CD000000102</string> </array> <key>PBXProjectModuleGUID</key> <string>1CE0B1FE06471DED0097A5F4</string> <key>PBXProjectModuleLabel</key> <string>Files</string> <key>PBXProjectStructureProvided</key> <string>no</string> <key>PBXSmartGroupTreeModuleColumnData</key> <dict> <key>PBXSmartGroupTreeModuleColumnWidthsKey</key> <array> <real>275</real> </array> <key>PBXSmartGroupTreeModuleColumnsKey_v4</key> <array> <string>MainColumn</string> </array> </dict> <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key> <dict> <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key> <array> <string>1C77FABC04509CD000000102</string> <string>1C3E0DCA080725EA00A55177</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <string>{{0, 0}, {275, 829}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> <key>XCIncludePerspectivesSwitch</key> <false/> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {292, 847}}</string> <key>GroupTreeTableConfiguration</key> <array> <string>MainColumn</string> <real>275</real> </array> <key>RubberWindowFrame</key> <string>19 140 1661 888 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> <key>Proportion</key> <string>292pt</string> </dict> <dict> <key>BecomeActive</key> <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CA1AED706398EBD00589147</string> <key>PBXProjectModuleLabel</key> <string>Detail</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{297, 0}, {1364, 847}}</string> <key>RubberWindowFrame</key> <string>19 140 1661 888 0 0 1680 1028 </string> </dict> <key>Module</key> <string>XCDetailModule</string> <key>Proportion</key> <string>1364pt</string> </dict> </array> <key>Proportion</key> <string>847pt</string> </dict> </array> <key>MajorVersion</key> <integer>3</integer> <key>MinorVersion</key> <integer>0</integer> <key>Name</key> <string>Breakpoints</string> <key>ServiceClasses</key> <array> <string>PBXSmartGroupTreeModule</string> <string>XCDetailModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>94CAA4DB123DC8AD00651F54</string> <string>94CAA4DC123DC8AD00651F54</string> <string>1CE0B1FE06471DED0097A5F4</string> <string>1CA1AED706398EBD00589147</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.breakpointsV3</string> <key>WindowString</key> <string>19 140 1661 888 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>94CAA4DB123DC8AD00651F54</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>Identifier</key> <string>windowTool.debugAnimator</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXNavigatorGroup</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Debug Visualizer</string> <key>ServiceClasses</key> <array> <string>PBXNavigatorGroup</string> </array> <key>StatusbarIsVisible</key> <integer>1</integer> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugAnimatorV3</string> <key>WindowString</key> <string>100 100 700 500 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.bookmarks</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>PBXBookmarksModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Bookmarks</string> <key>ServiceClasses</key> <array> <string>PBXBookmarksModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowString</key> <string>538 42 401 187 0 0 1280 1002 </string> </dict> <dict> <key>Identifier</key> <string>windowTool.projectFormatConflicts</string> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>Module</key> <string>XCProjectFormatConflictsModule</string> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Proportion</key> <string>100%</string> </dict> </array> <key>Name</key> <string>Project Format Conflicts</string> <key>ServiceClasses</key> <array> <string>XCProjectFormatConflictsModule</string> </array> <key>StatusbarIsVisible</key> <integer>0</integer> <key>WindowContentMinSize</key> <string>450 300</string> <key>WindowString</key> <string>50 850 472 307 0 0 1440 877</string> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.classBrowser</string> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>OptionsSetName</key> <string>Hierarchy, project classes</string> <key>PBXProjectModuleGUID</key> <string>1CA6456E063B45B4001379D8</string> <key>PBXProjectModuleLabel</key> <string>Class Browser - sqiPhoneScreenAndWindow</string> </dict> <key>GeometryConfiguration</key> <dict> <key>ClassesFrame</key> <string>{{0, 0}, {464, 96}}</string> <key>ClassesTreeTableConfiguration</key> <array> <string>PBXClassNameColumnIdentifier</string> <real>208</real> <string>PBXClassBookColumnIdentifier</string> <real>22</real> </array> <key>Frame</key> <string>{{0, 0}, {716, 601}}</string> <key>MembersFrame</key> <string>{{0, 101}, {464, 500}}</string> <key>MembersTreeTableConfiguration</key> <array> <string>PBXMemberTypeIconColumnIdentifier</string> <real>22</real> <string>PBXMemberNameColumnIdentifier</string> <real>216</real> <string>PBXMemberTypeColumnIdentifier</string> <real>187</real> <string>PBXMemberBookColumnIdentifier</string> <real>22</real> </array> <key>RubberWindowFrame</key> <string>831 328 716 621 0 0 1680 1028 </string> </dict> <key>Module</key> <string>PBXClassBrowserModule</string> <key>Proportion</key> <string>601pt</string> </dict> </array> <key>Proportion</key> <string>601pt</string> </dict> </array> <key>Name</key> <string>Class Browser</string> <key>ServiceClasses</key> <array> <string>PBXClassBrowserModule</string> </array> <key>StatusbarIsVisible</key> <false/> <key>TableOfContents</key> <array> <string>1C0AD2AF069F1E9B00FABCE6</string> <string>942EF6B610C6F21E006DF917</string> <string>1CA6456E063B45B4001379D8</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.classbrowser</string> <key>WindowString</key> <string>831 328 716 621 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>1C0AD2AF069F1E9B00FABCE6</string> <key>WindowToolIsVisible</key> <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> <false/> <key>Identifier</key> <string>windowTool.refactoring</string> <key>IncludeInToolsMenu</key> <integer>0</integer> <key>IsVertical</key> <true/> <key>Layout</key> <array> <dict> <key>Dock</key> <array> <dict> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>949E5F260DE3F297007388E0</string> </dict> <key>GeometryConfiguration</key> <dict> <key>Frame</key> <string>{{0, 0}, {1293, 860}}</string> <key>RubberWindowFrame</key> <string>268 92 1293 901 0 0 1680 1028 </string> <key>XCRefactoringSplitViewLowerHeight</key> <real>383</real> <key>XCRefactoringSplitViewTotalHeight</key> <real>777</real> </dict> <key>Module</key> <string>XCRefactoringModule</string> <key>Proportion</key> <string>860pt</string> </dict> </array> <key>Proportion</key> <string>860pt</string> </dict> </array> <key>Name</key> <string>Refactoring</string> <key>ServiceClasses</key> <array> <string>XCRefactoringModule</string> </array> <key>StatusbarIsVisible</key> <true/> <key>TableOfContents</key> <array> <string>949E5F270DE3F297007388E0</string> <string>9402DD2B10CE0815005C2102</string> <string>949E5F260DE3F297007388E0</string> </array> <key>WindowString</key> <string>268 92 1293 901 0 0 1680 1028 </string> <key>WindowToolGUID</key> <string>949E5F270DE3F297007388E0</string> <key>WindowToolIsVisible</key> <false/> </dict> </array> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/johnmci.pbxuser ================================================ // !$*UTF8*$! { 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 858}}"; sepNavSelRange = "{3089, 12}"; sepNavVisRange = "{656, 2653}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {943, 3341}}"; sepNavSelRange = "{5386, 0}"; sepNavVisRange = "{5229, 1794}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */ = { activeExec = 0; executables = ( 9424FF3E0DDC8654009912BF /* Squeak */, ); }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeArchitecturePreference = armv6; activeBuildConfigurationName = Distribution; activeExecutable = 947E62FD10AA098300D3B69E /* SqueakPureObjc */; activeSDKPreference = macosx10.5; activeTarget = 947E626F10AA098300D3B69E /* SqueakPureObjc */; addToTargets = ( 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */, ); breakpoints = ( 9458511410F03996001401E7 /* sqMacExtendedClipboard.m:101 */, 9458523210F040A0001401E7 /* sqMacExtendedClipboard.m:37 */, 9458523410F040A1001401E7 /* sqMacExtendedClipboard.m:45 */, 9458523610F040A2001401E7 /* sqMacExtendedClipboard.m:50 */, 9458523A10F040AF001401E7 /* sqMacExtendedClipboard.m:72 */, 9458524810F04272001401E7 /* sqMacExtendedClipboard.m:88 */, 9458527F10F045FB001401E7 /* sqSqueakIPhoneClipboardAPI.m:31 */, 9458528110F045FC001401E7 /* sqSqueakIPhoneClipboardAPI.m:24 */, 9458528310F045FD001401E7 /* sqSqueakIPhoneClipboardAPI.m:17 */, 944F6D171224D7B300DFC0CD /* sqSqueakOSXApplication+imageReadWrite.m:64 */, 94E8FA6512258FDF00EECD29 /* sqMacV2Memory.c:191 */, 9415C06312306B660067CD8E /* SqueakUIView.m:118 */, 9415C06512306B6F0067CD8E /* SqueakUIView.m:126 */, 9415C11412306FCC0067CD8E /* sqiPhoneScreenAndWindow.m:63 */, 94C748E012333EE900B1F982 /* sqMacUIEventsUniversal.c:1113 */, 943B9AF71235B9FD0056205E /* sqSqueakOSXNSWindowController.m:18 */, 943B9B9E1235BE580056205E /* sqMacHostWindow.m:58 */, 94AC16D512395FE40067037A /* sqSqueakOSXNSView.m:551 */, 94C8D195123EDACE0019544B /* SqueakUIViewOpenGL.m:135 */, 947E99CB125D78FB0048E783 /* NSLOG */, 947E99CC125D78FE0048E783 /* NSlog */, 947E99D0125D79050048E783 /* NSLog */, 947E99F8125D7B1C0048E783 /* cl */, 9427E42E12627E6A002DCA6D /* sqSqueakIPhoneApplication+imageReadWrite.m:95 */, ); codeSenseManager = 9424FF430DDC8673009912BF /* Code sense */; executables = ( 9424FF3E0DDC8654009912BF /* Squeak */, 947E62FD10AA098300D3B69E /* SqueakPureObjc */, ); expressions = ( pluginExports, ); ignoreBreakpointsInProjectsDict = { SqueakVMUNIXPATHS = Ignored; }; perUserDictionary = { "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 401, 20, 301, 301, 232, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXBreakpointsDataSource_ActionID, PBXBreakpointsDataSource_TypeID, PBXBreakpointsDataSource_BreakpointID, PBXBreakpointsDataSource_UseID, PBXBreakpointsDataSource_LocationID, PBXBreakpointsDataSource_ConditionID, PBXBreakpointsDataSource_IgnoreCountID, PBXBreakpointsDataSource_ContinueID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXBookmarksDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXBookmarksDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 200, 200, 481, ); PBXFileTableDataSourceColumnsKey = ( PBXBookmarksDataSource_LocationID, PBXBookmarksDataSource_NameID, PBXBookmarksDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 300, 734, ); PBXFileTableDataSourceColumnsKey = ( PBXErrorsWarningsDataSource_TypeID, PBXErrorsWarningsDataSource_MessageID, PBXErrorsWarningsDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 829.58349609375, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 574, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID; PBXFileTableDataSourceColumnWidthsKey = ( 278, 913, ); PBXFileTableDataSourceColumnsKey = ( PBXFindDataSource_MessageID, PBXFindDataSource_LocationID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolTypeIconID; PBXFileTableDataSourceColumnWidthsKey = ( 16, 200, 50, 534.20849609375, ); PBXFileTableDataSourceColumnsKey = ( PBXSymbolsDataSource_SymbolTypeIconID, PBXSymbolsDataSource_SymbolNameID, PBXSymbolsDataSource_SymbolTypeID, PBXSymbolsDataSource_ReferenceNameID, ); }; PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 839, 20, 48.16259765625, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_SCM_ColumnID, PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 534, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 308462977; PBXWorkspaceStateSaveDate = 308462977; }; perUserProjectItems = { 940125A81228E3FC002883F0 /* PBXTextBookmark */ = 940125A81228E3FC002883F0 /* PBXTextBookmark */; 9402DDB610CE12A5005C2102 /* PBXTextBookmark */ = 9402DDB610CE12A5005C2102 /* PBXTextBookmark */; 94059113122AFF8C009939CE /* PBXTextBookmark */ = 94059113122AFF8C009939CE /* PBXTextBookmark */; 9406B4DF11EC314E002670B7 /* PBXTextBookmark */ = 9406B4DF11EC314E002670B7 /* PBXTextBookmark */; 9406E7E210B663F4002F81F2 /* PBXTextBookmark */ = 9406E7E210B663F4002F81F2 /* PBXTextBookmark */; 9406E87110B66A74002F81F2 /* PBXTextBookmark */ = 9406E87110B66A74002F81F2 /* PBXTextBookmark */; 9406E8CC10B67499002F81F2 /* PBXTextBookmark */ = 9406E8CC10B67499002F81F2 /* PBXTextBookmark */; 940E86A31220A8D200AAB6F5 /* PBXTextBookmark */ = 940E86A31220A8D200AAB6F5 /* PBXTextBookmark */; 940E86EE1220AF3D00AAB6F5 /* PBXTextBookmark */ = 940E86EE1220AF3D00AAB6F5 /* PBXTextBookmark */; 941441FD10BC817D0088F8AC /* PBXTextBookmark */ = 941441FD10BC817D0088F8AC /* PBXTextBookmark */; 9414420110BC817D0088F8AC /* PBXTextBookmark */ = 9414420110BC817D0088F8AC /* PBXTextBookmark */; 9415C07412306BDD0067CD8E /* PBXTextBookmark */ = 9415C07412306BDD0067CD8E /* PBXTextBookmark */; 941A331D11E63E1A004796BA /* PBXTextBookmark */ = 941A331D11E63E1A004796BA /* PBXTextBookmark */; 941A331F11E63E1A004796BA /* PBXTextBookmark */ = 941A331F11E63E1A004796BA /* PBXTextBookmark */; 9421AB550FF1807D008F54E9 /* PBXTextBookmark */ = 9421AB550FF1807D008F54E9 /* PBXTextBookmark */; 94238E5E11E7B0EB004401BE /* PBXTextBookmark */ = 94238E5E11E7B0EB004401BE /* PBXTextBookmark */; 9427E35512626DFB002DCA6D /* PBXTextBookmark */ = 9427E35512626DFB002DCA6D /* PBXTextBookmark */; 9427E37B12626EE6002DCA6D /* PBXTextBookmark */ = 9427E37B12626EE6002DCA6D /* PBXTextBookmark */; 9427E3F612627C61002DCA6D /* PBXTextBookmark */ = 9427E3F612627C61002DCA6D /* PBXTextBookmark */; 9427E3F812627C61002DCA6D /* PlistBookmark */ = 9427E3F812627C61002DCA6D /* PlistBookmark */; 9427E3F912627C61002DCA6D /* PlistBookmark */ = 9427E3F912627C61002DCA6D /* PlistBookmark */; 9427E44B12628333002DCA6D /* PBXTextBookmark */ = 9427E44B12628333002DCA6D /* PBXTextBookmark */; 9427E44C12628333002DCA6D /* PBXTextBookmark */ = 9427E44C12628333002DCA6D /* PBXTextBookmark */; 9427E44D12628333002DCA6D /* PlistBookmark */ = 9427E44D12628333002DCA6D /* PlistBookmark */; 9427E46212629AE3002DCA6D /* PBXBookmark */ = 9427E46212629AE3002DCA6D /* PBXBookmark */; 9427E46312629AE3002DCA6D /* PlistBookmark */ = 9427E46312629AE3002DCA6D /* PlistBookmark */; 9427E4D11262B997002DCA6D /* PBXTextBookmark */ = 9427E4D11262B997002DCA6D /* PBXTextBookmark */; 9427E4D21262B997002DCA6D /* PBXTextBookmark */ = 9427E4D21262B997002DCA6D /* PBXTextBookmark */; 942807EE1224862A0000DCFE /* PBXTextBookmark */ = 942807EE1224862A0000DCFE /* PBXTextBookmark */; 942807EF1224862A0000DCFE /* PBXTextBookmark */ = 942807EF1224862A0000DCFE /* PBXTextBookmark */; 942807F01224862A0000DCFE /* PBXTextBookmark */ = 942807F01224862A0000DCFE /* PBXTextBookmark */; 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */ = 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */; 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */ = 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */; 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */ = 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */; 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */ = 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */; 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */ = 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */; 942ABEC510AA34820086D908 /* PBXTextBookmark */ = 942ABEC510AA34820086D908 /* PBXTextBookmark */; 942B77330EA7E642004B266D /* PBXTextBookmark */ = 942B77330EA7E642004B266D /* PBXTextBookmark */; 942B77380EA7E642004B266D /* PBXTextBookmark */ = 942B77380EA7E642004B266D /* PBXTextBookmark */; 942B779B0EA7F2E0004B266D /* PBXTextBookmark */ = 942B779B0EA7F2E0004B266D /* PBXTextBookmark */; 942B779C0EA7F2E0004B266D /* PBXTextBookmark */ = 942B779C0EA7F2E0004B266D /* PBXTextBookmark */; 942B77B90EA800E1004B266D /* PBXTextBookmark */ = 942B77B90EA800E1004B266D /* PBXTextBookmark */; 942B77BB0EA800E1004B266D /* PBXTextBookmark */ = 942B77BB0EA800E1004B266D /* PBXTextBookmark */; 942B77C00EA800E1004B266D /* PBXTextBookmark */ = 942B77C00EA800E1004B266D /* PBXTextBookmark */; 9430325510BD0B6D0045D33B /* PBXTextBookmark */ = 9430325510BD0B6D0045D33B /* PBXTextBookmark */; 9430329A10BD103B0045D33B /* PBXTextBookmark */ = 9430329A10BD103B0045D33B /* PBXTextBookmark */; 9430329B10BD103B0045D33B /* PBXTextBookmark */ = 9430329B10BD103B0045D33B /* PBXTextBookmark */; 943B9B151235BB080056205E /* PBXTextBookmark */ = 943B9B151235BB080056205E /* PBXTextBookmark */; 943B9B1E1235BD150056205E /* PBXTextBookmark */ = 943B9B1E1235BD150056205E /* PBXTextBookmark */; 943B9BD31235C1120056205E /* PBXTextBookmark */ = 943B9BD31235C1120056205E /* PBXTextBookmark */; 943B9BD41235C1120056205E /* PBXTextBookmark */ = 943B9BD41235C1120056205E /* PBXTextBookmark */; 943B9C041235C1EE0056205E /* PBXTextBookmark */ = 943B9C041235C1EE0056205E /* PBXTextBookmark */; 943B9C311235C3D70056205E /* PBXTextBookmark */ = 943B9C311235C3D70056205E /* PBXTextBookmark */; 943B9C331235C3D70056205E /* PBXTextBookmark */ = 943B9C331235C3D70056205E /* PBXTextBookmark */; 943B9D621235C79C0056205E /* PBXTextBookmark */ = 943B9D621235C79C0056205E /* PBXTextBookmark */; 943C0AC7122DF3710086B6AD /* PBXTextBookmark */ = 943C0AC7122DF3710086B6AD /* PBXTextBookmark */; 943C0AC8122DF3710086B6AD /* PBXTextBookmark */ = 943C0AC8122DF3710086B6AD /* PBXTextBookmark */; 943C0ACA122DF3710086B6AD /* PBXTextBookmark */ = 943C0ACA122DF3710086B6AD /* PBXTextBookmark */; 943C0AE0122DF5E70086B6AD /* PBXTextBookmark */ = 943C0AE0122DF5E70086B6AD /* PBXTextBookmark */; 943C0AE2122DF5E70086B6AD /* PBXTextBookmark */ = 943C0AE2122DF5E70086B6AD /* PBXTextBookmark */; 943C0AE5122DF5E70086B6AD /* PBXTextBookmark */ = 943C0AE5122DF5E70086B6AD /* PBXTextBookmark */; 943C0AE7122DF5E70086B6AD /* PBXTextBookmark */ = 943C0AE7122DF5E70086B6AD /* PBXTextBookmark */; 9441DB7111E6805300345F6C /* PBXTextBookmark */ = 9441DB7111E6805300345F6C /* PBXTextBookmark */; 9441DB7211E6805300345F6C /* PBXTextBookmark */ = 9441DB7211E6805300345F6C /* PBXTextBookmark */; 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */ = 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */; 9451E64F123F0E9200B4119F /* PlistBookmark */ = 9451E64F123F0E9200B4119F /* PlistBookmark */; 9453F58A1234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F58A1234AF8A00C91CF7 /* PBXTextBookmark */; 9453F58C1234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F58C1234AF8A00C91CF7 /* PBXTextBookmark */; 9453F58D1234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F58D1234AF8A00C91CF7 /* PBXTextBookmark */; 9453F5911234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F5911234AF8A00C91CF7 /* PBXTextBookmark */; 9453F5931234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F5931234AF8A00C91CF7 /* PBXTextBookmark */; 9453F5951234AF8A00C91CF7 /* PBXTextBookmark */ = 9453F5951234AF8A00C91CF7 /* PBXTextBookmark */; 94547F160DE0AC7D00DD588F /* PBXTextBookmark */ = 94547F160DE0AC7D00DD588F /* PBXTextBookmark */; 945481A60DE2A79200DD588F /* PBXTextBookmark */ = 945481A60DE2A79200DD588F /* PBXTextBookmark */; 94554E670DF1171500FB176B /* PBXTextBookmark */ = 94554E670DF1171500FB176B /* PBXTextBookmark */; 94554E690DF1171500FB176B /* PBXTextBookmark */ = 94554E690DF1171500FB176B /* PBXTextBookmark */; 94554EB80DF1A86A00FB176B /* PBXTextBookmark */ = 94554EB80DF1A86A00FB176B /* PBXTextBookmark */; 9456C24F10B2F268000BF3DE /* PBXTextBookmark */ = 9456C24F10B2F268000BF3DE /* PBXTextBookmark */; 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */ = 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */; 9456C32210B32F43000BF3DE /* PBXTextBookmark */ = 9456C32210B32F43000BF3DE /* PBXTextBookmark */; 9456C34E10B33618000BF3DE /* PBXTextBookmark */ = 9456C34E10B33618000BF3DE /* PBXTextBookmark */; 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */ = 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */; 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */ = 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */; 945C4EAC10BB348300548CC1 /* PBXTextBookmark */ = 945C4EAC10BB348300548CC1 /* PBXTextBookmark */; 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */ = 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */; 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */ = 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */; 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */ = 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */; 946C240C1230A80A004938A1 /* PBXTextBookmark */ = 946C240C1230A80A004938A1 /* PBXTextBookmark */; 946D973B0FE165B70038846B /* PBXTextBookmark */ = 946D973B0FE165B70038846B /* PBXTextBookmark */; 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */ = 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */; 946DA8D910C0C32800F26F56 /* PBXTextBookmark */ = 946DA8D910C0C32800F26F56 /* PBXTextBookmark */; 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */ = 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */; 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */ = 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */; 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */; 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */; 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */ = 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */; 94700A50123DF62D00874318 /* PBXTextBookmark */ = 94700A50123DF62D00874318 /* PBXTextBookmark */; 94700A51123DF62D00874318 /* PBXTextBookmark */ = 94700A51123DF62D00874318 /* PBXTextBookmark */; 94700AAD123DFCEA00874318 /* PBXTextBookmark */ = 94700AAD123DFCEA00874318 /* PBXTextBookmark */; 947332EE0EA70E8C003F9084 /* PBXTextBookmark */ = 947332EE0EA70E8C003F9084 /* PBXTextBookmark */; 9473A34810BBD84100ED7D00 /* PBXTextBookmark */ = 9473A34810BBD84100ED7D00 /* PBXTextBookmark */; 9473A95A1102F70B00D135CB /* PBXTextBookmark */ = 9473A95A1102F70B00D135CB /* PBXTextBookmark */; 9473A9701103BE0A00D135CB /* PBXTextBookmark */ = 9473A9701103BE0A00D135CB /* PBXTextBookmark */; 9475A83511E6B5D50010FB38 /* PBXTextBookmark */ = 9475A83511E6B5D50010FB38 /* PBXTextBookmark */; 9475F4DB10BEF4100047A24B /* PBXTextBookmark */ = 9475F4DB10BEF4100047A24B /* PBXTextBookmark */; 9475F56B10BF20A00047A24B /* PBXTextBookmark */ = 9475F56B10BF20A00047A24B /* PBXTextBookmark */; 9475F5A710BF25A10047A24B /* PBXTextBookmark */ = 9475F5A710BF25A10047A24B /* PBXTextBookmark */; 947713D410C45E5F00890A9B /* PBXTextBookmark */ = 947713D410C45E5F00890A9B /* PBXTextBookmark */; 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */ = 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */; 947923FE1102BE53007C87F8 /* PBXTextBookmark */ = 947923FE1102BE53007C87F8 /* PBXTextBookmark */; 947E210C0EB28486007957D0 /* PBXTextBookmark */ = 947E210C0EB28486007957D0 /* PBXTextBookmark */; 947E61D610AA049300D3B69E /* PBXTextBookmark */ = 947E61D610AA049300D3B69E /* PBXTextBookmark */; 947E61DA10AA049300D3B69E /* PBXTextBookmark */ = 947E61DA10AA049300D3B69E /* PBXTextBookmark */; 947E61DC10AA049300D3B69E /* PBXTextBookmark */ = 947E61DC10AA049300D3B69E /* PBXTextBookmark */; 947E9920125D73FD0048E783 /* PBXTextBookmark */ = 947E9920125D73FD0048E783 /* PBXTextBookmark */; 947E9964125D756D0048E783 /* PBXTextBookmark */ = 947E9964125D756D0048E783 /* PBXTextBookmark */; 947E9967125D756D0048E783 /* PBXTextBookmark */ = 947E9967125D756D0048E783 /* PBXTextBookmark */; 947E9969125D756D0048E783 /* PBXTextBookmark */ = 947E9969125D756D0048E783 /* PBXTextBookmark */; 947E996B125D756D0048E783 /* PBXTextBookmark */ = 947E996B125D756D0048E783 /* PBXTextBookmark */; 947E996D125D756D0048E783 /* PBXTextBookmark */ = 947E996D125D756D0048E783 /* PBXTextBookmark */; 947E996F125D756D0048E783 /* PBXTextBookmark */ = 947E996F125D756D0048E783 /* PBXTextBookmark */; 947E9971125D756D0048E783 /* PBXTextBookmark */ = 947E9971125D756D0048E783 /* PBXTextBookmark */; 947E9994125D76820048E783 /* PBXTextBookmark */ = 947E9994125D76820048E783 /* PBXTextBookmark */; 947E99A0125D76BB0048E783 /* PBXTextBookmark */ = 947E99A0125D76BB0048E783 /* PBXTextBookmark */; 947E99FA125D7B850048E783 /* PBXTextBookmark */ = 947E99FA125D7B850048E783 /* PBXTextBookmark */; 948034A9122A264A00C42504 /* PBXTextBookmark */ = 948034A9122A264A00C42504 /* PBXTextBookmark */; 948127E812444F7800BD1543 /* PBXTextBookmark */ = 948127E812444F7800BD1543 /* PBXTextBookmark */; 948127E912444F7800BD1543 /* PBXTextBookmark */ = 948127E912444F7800BD1543 /* PBXTextBookmark */; 948127EA12444F7800BD1543 /* PBXTextBookmark */ = 948127EA12444F7800BD1543 /* PBXTextBookmark */; 948127EB12444F7800BD1543 /* PBXTextBookmark */ = 948127EB12444F7800BD1543 /* PBXTextBookmark */; 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */ = 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */; 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */ = 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */; 9484F8FC10B0E1770038BDC0 /* PBXBookmark */ = 9484F8FC10B0E1770038BDC0 /* PBXBookmark */; 94862F8310BA182500CAA2EB /* PBXTextBookmark */ = 94862F8310BA182500CAA2EB /* PBXTextBookmark */; 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */ = 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */; 9486302A10BA247200CAA2EB /* PBXTextBookmark */ = 9486302A10BA247200CAA2EB /* PBXTextBookmark */; 948704AE0E12CABF00D565C3 /* PBXTextBookmark */ = 948704AE0E12CABF00D565C3 /* PBXTextBookmark */; 9487071F0E132B1000D565C3 /* PBXTextBookmark */ = 9487071F0E132B1000D565C3 /* PBXTextBookmark */; 948C0820112DE98D0017EE7F /* PBXTextBookmark */ = 948C0820112DE98D0017EE7F /* PBXTextBookmark */; 948FAA0310BF855500BE88CF /* PBXTextBookmark */ = 948FAA0310BF855500BE88CF /* PBXTextBookmark */; 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */ = 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */; 949198B010BC8DFC00C629D1 /* PBXTextBookmark */ = 949198B010BC8DFC00C629D1 /* PBXTextBookmark */; 949198C910BC8FBB00C629D1 /* PBXTextBookmark */ = 949198C910BC8FBB00C629D1 /* PBXTextBookmark */; 9492450510BA42EF00E726F5 /* PBXTextBookmark */ = 9492450510BA42EF00E726F5 /* PBXTextBookmark */; 9492450710BA42EF00E726F5 /* PBXTextBookmark */ = 9492450710BA42EF00E726F5 /* PBXTextBookmark */; 9492450910BA42EF00E726F5 /* PBXTextBookmark */ = 9492450910BA42EF00E726F5 /* PBXTextBookmark */; 949245B210BA4A6200E726F5 /* PBXTextBookmark */ = 949245B210BA4A6200E726F5 /* PBXTextBookmark */; 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */ = 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */; 94977E7C11EE46BC002BC5E9 /* PBXTextBookmark */ = 94977E7C11EE46BC002BC5E9 /* PBXTextBookmark */; 949AD35211E54A81006D6BF4 /* PBXTextBookmark */ = 949AD35211E54A81006D6BF4 /* PBXTextBookmark */; 949AD36211E54AAA006D6BF4 /* PBXTextBookmark */ = 949AD36211E54AAA006D6BF4 /* PBXTextBookmark */; 949C3A281262C1F700F4EF15 /* PBXTextBookmark */ = 949C3A281262C1F700F4EF15 /* PBXTextBookmark */; 949C3A441262C2D200F4EF15 /* PBXTextBookmark */ = 949C3A441262C2D200F4EF15 /* PBXTextBookmark */; 949C3AFE1262C91300F4EF15 /* PBXTextBookmark */ = 949C3AFE1262C91300F4EF15 /* PBXTextBookmark */; 949C3AFF1262C91300F4EF15 /* PBXTextBookmark */ = 949C3AFF1262C91300F4EF15 /* PBXTextBookmark */; 949C3B171262C9C900F4EF15 /* PBXTextBookmark */ = 949C3B171262C9C900F4EF15 /* PBXTextBookmark */; 949DDD6D11D141080017F79B /* PBXTextBookmark */ = 949DDD6D11D141080017F79B /* PBXTextBookmark */; 949F254511EC33FA00A34245 /* PBXTextBookmark */ = 949F254511EC33FA00A34245 /* PBXTextBookmark */; 949F254611EC33FA00A34245 /* PBXTextBookmark */ = 949F254611EC33FA00A34245 /* PBXTextBookmark */; 949F254811EC33FA00A34245 /* PBXTextBookmark */ = 949F254811EC33FA00A34245 /* PBXTextBookmark */; 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */ = 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */; 94A1B41E10BA05E600C64473 /* PBXTextBookmark */ = 94A1B41E10BA05E600C64473 /* PBXTextBookmark */; 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */ = 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */; 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */ = 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */; 94AC16D912395FF10067037A /* PBXTextBookmark */ = 94AC16D912395FF10067037A /* PBXTextBookmark */; 94AC16DA12395FF10067037A /* PBXTextBookmark */ = 94AC16DA12395FF10067037A /* PBXTextBookmark */; 94AC16DC12395FF10067037A /* PBXTextBookmark */ = 94AC16DC12395FF10067037A /* PBXTextBookmark */; 94AC16DE12395FF10067037A /* PBXTextBookmark */ = 94AC16DE12395FF10067037A /* PBXTextBookmark */; 94AF3A1F12231A7200691409 /* PBXTextBookmark */ = 94AF3A1F12231A7200691409 /* PBXTextBookmark */; 94B1514E0DE2CE530059F208 /* PBXTextBookmark */ = 94B1514E0DE2CE530059F208 /* PBXTextBookmark */; 94B7898910C4F95E005EA70D /* PBXTextBookmark */ = 94B7898910C4F95E005EA70D /* PBXTextBookmark */; 94B88C560E81500200C98131 /* PBXTextBookmark */ = 94B88C560E81500200C98131 /* PBXTextBookmark */; 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */ = 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */; 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */ = 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */; 94BCAFC710ACC89100F87527 /* PBXTextBookmark */ = 94BCAFC710ACC89100F87527 /* PBXTextBookmark */; 94BE8B9C123DA0C900C89FDD /* PBXTextBookmark */ = 94BE8B9C123DA0C900C89FDD /* PBXTextBookmark */; 94BE8BAD123DA0EB00C89FDD /* PBXTextBookmark */ = 94BE8BAD123DA0EB00C89FDD /* PBXTextBookmark */; 94BE8BD5123DA32300C89FDD /* PBXTextBookmark */ = 94BE8BD5123DA32300C89FDD /* PBXTextBookmark */; 94BE8BF5123DA42700C89FDD /* PBXTextBookmark */ = 94BE8BF5123DA42700C89FDD /* PBXTextBookmark */; 94C16B42123D72AE00A8622A /* PBXTextBookmark */ = 94C16B42123D72AE00A8622A /* PBXTextBookmark */; 94C16B43123D72AE00A8622A /* PBXTextBookmark */ = 94C16B43123D72AE00A8622A /* PBXTextBookmark */; 94C16B5A123D735F00A8622A /* PBXTextBookmark */ = 94C16B5A123D735F00A8622A /* PBXTextBookmark */; 94C2074310AF5FB7002F4160 /* PBXTextBookmark */ = 94C2074310AF5FB7002F4160 /* PBXTextBookmark */; 94C2091210AF7413002F4160 /* PBXTextBookmark */ = 94C2091210AF7413002F4160 /* PBXTextBookmark */; 94C2092A10AF769A002F4160 /* PBXTextBookmark */ = 94C2092A10AF769A002F4160 /* PBXTextBookmark */; 94C2092D10AF769A002F4160 /* PBXTextBookmark */ = 94C2092D10AF769A002F4160 /* PBXTextBookmark */; 94C367C010AF9C0A0041953A /* PBXTextBookmark */ = 94C367C010AF9C0A0041953A /* PBXTextBookmark */; 94C367C210AF9C0A0041953A /* PBXTextBookmark */ = 94C367C210AF9C0A0041953A /* PBXTextBookmark */; 94C367D110AF9C830041953A /* PBXTextBookmark */ = 94C367D110AF9C830041953A /* PBXTextBookmark */; 94C3696410AFB7550041953A /* PBXTextBookmark */ = 94C3696410AFB7550041953A /* PBXTextBookmark */; 94C3698D10B082DF0041953A /* PBXTextBookmark */ = 94C3698D10B082DF0041953A /* PBXTextBookmark */; 94C3699110B082DF0041953A /* PBXTextBookmark */ = 94C3699110B082DF0041953A /* PBXTextBookmark */; 94C3CD4E1235C80200A4E319 /* PBXTextBookmark */ = 94C3CD4E1235C80200A4E319 /* PBXTextBookmark */; 94C7480712333A2900B1F982 /* PBXTextBookmark */ = 94C7480712333A2900B1F982 /* PBXTextBookmark */; 94C887D410ADCC0D007CB39E /* PBXTextBookmark */ = 94C887D410ADCC0D007CB39E /* PBXTextBookmark */; 94C888B710ADE75B007CB39E /* PBXTextBookmark */ = 94C888B710ADE75B007CB39E /* PBXTextBookmark */; 94C88B6810AF26F8007CB39E /* PBXTextBookmark */ = 94C88B6810AF26F8007CB39E /* PBXTextBookmark */; 94C8D197123EDAD30019544B /* PBXTextBookmark */ = 94C8D197123EDAD30019544B /* PBXTextBookmark */; 94C8D19A123EDAD30019544B /* PBXTextBookmark */ = 94C8D19A123EDAD30019544B /* PBXTextBookmark */; 94C8D19B123EDAD30019544B /* PBXTextBookmark */ = 94C8D19B123EDAD30019544B /* PBXTextBookmark */; 94C8D19C123EDAD30019544B /* PBXTextBookmark */ = 94C8D19C123EDAD30019544B /* PBXTextBookmark */; 94CAE0ED1230DE6C00AFE487 /* PBXTextBookmark */ = 94CAE0ED1230DE6C00AFE487 /* PBXTextBookmark */; 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */; 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */; 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */; 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */ = 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */; 94CFE70110BE683800847DF5 /* PBXTextBookmark */ = 94CFE70110BE683800847DF5 /* PBXTextBookmark */; 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */ = 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */; 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */ = 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */; 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */ = 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */; 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */ = 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */; 94D16CA310BCF93000A69A89 /* PBXTextBookmark */ = 94D16CA310BCF93000A69A89 /* PBXTextBookmark */; 94D3660B10CEE03900805023 /* PBXTextBookmark */ = 94D3660B10CEE03900805023 /* PBXTextBookmark */; 94D715CB10B723B200F69A71 /* PBXTextBookmark */ = 94D715CB10B723B200F69A71 /* PBXTextBookmark */; 94D7174110B72FDF00F69A71 /* PBXTextBookmark */ = 94D7174110B72FDF00F69A71 /* PBXTextBookmark */; 94D7177D10B73A3800F69A71 /* PBXTextBookmark */ = 94D7177D10B73A3800F69A71 /* PBXTextBookmark */; 94D7178410B73A3800F69A71 /* PBXTextBookmark */ = 94D7178410B73A3800F69A71 /* PBXTextBookmark */; 94D7178610B73A3800F69A71 /* PBXTextBookmark */ = 94D7178610B73A3800F69A71 /* PBXTextBookmark */; 94D7178810B73A3800F69A71 /* PBXTextBookmark */ = 94D7178810B73A3800F69A71 /* PBXTextBookmark */; 94D7178A10B73A3800F69A71 /* PBXTextBookmark */ = 94D7178A10B73A3800F69A71 /* PBXTextBookmark */; 94D7178C10B73A3800F69A71 /* PBXTextBookmark */ = 94D7178C10B73A3800F69A71 /* PBXTextBookmark */; 94D7179110B73A3800F69A71 /* PBXTextBookmark */ = 94D7179110B73A3800F69A71 /* PBXTextBookmark */; 94D717BE10B73DD900F69A71 /* PBXTextBookmark */ = 94D717BE10B73DD900F69A71 /* PBXTextBookmark */; 94D717F810B743B800F69A71 /* PBXTextBookmark */ = 94D717F810B743B800F69A71 /* PBXTextBookmark */; 94D7183810B74BF300F69A71 /* PBXTextBookmark */ = 94D7183810B74BF300F69A71 /* PBXTextBookmark */; 94D7183A10B74BF300F69A71 /* PBXTextBookmark */ = 94D7183A10B74BF300F69A71 /* PBXTextBookmark */; 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */; 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */ = 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */; 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */ = 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */; 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */ = 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */; 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */ = 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */; 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */ = 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */; 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */ = 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */; 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */ = 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */; 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */ = 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */; 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */ = 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */; 94D740B210B6242000F8C034 /* PBXTextBookmark */ = 94D740B210B6242000F8C034 /* PBXTextBookmark */; 94E1BDAB11E5A9F400D5B92B /* PBXTextBookmark */ = 94E1BDAB11E5A9F400D5B92B /* PBXTextBookmark */; 94E297D10DECA72F009CF73A /* PBXTextBookmark */ = 94E297D10DECA72F009CF73A /* PBXTextBookmark */; 94E297D30DECA72F009CF73A /* PBXTextBookmark */ = 94E297D30DECA72F009CF73A /* PBXTextBookmark */; 94E297D50DECA72F009CF73A /* PBXTextBookmark */ = 94E297D50DECA72F009CF73A /* PBXTextBookmark */; 94E297D70DECA72F009CF73A /* PBXTextBookmark */ = 94E297D70DECA72F009CF73A /* PBXTextBookmark */; 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */ = 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */; 94E2DB270ED2355F00012E92 /* PBXTextBookmark */ = 94E2DB270ED2355F00012E92 /* PBXTextBookmark */; 94E4930310BD32D00011AC75 /* PBXTextBookmark */ = 94E4930310BD32D00011AC75 /* PBXTextBookmark */; 94E583DB10BF43970073FD63 /* PBXTextBookmark */ = 94E583DB10BF43970073FD63 /* PBXTextBookmark */; 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */ = 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */; 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */ = 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */; 94E5850010BF79AB0073FD63 /* PBXTextBookmark */ = 94E5850010BF79AB0073FD63 /* PBXTextBookmark */; 94E7F6B812373EB800A03A11 /* PBXTextBookmark */ = 94E7F6B812373EB800A03A11 /* PBXTextBookmark */; 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */ = 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */; 94E8FA3C12258ED500EECD29 /* PBXTextBookmark */ = 94E8FA3C12258ED500EECD29 /* PBXTextBookmark */; 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */ = 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */; 94EE1DAA11E57FAB00DC6E8C /* PBXTextBookmark */ = 94EE1DAA11E57FAB00DC6E8C /* PBXTextBookmark */; 94EF43151262BFC100817F37 /* PBXTextBookmark */ = 94EF43151262BFC100817F37 /* PBXTextBookmark */; 94F155570E83EA1F001657CE /* PBXTextBookmark */ = 94F155570E83EA1F001657CE /* PBXTextBookmark */; 94F155580E83EA1F001657CE /* PBXTextBookmark */ = 94F155580E83EA1F001657CE /* PBXTextBookmark */; 94F1F15C11EB8AB5004B3AE3 /* PBXTextBookmark */ = 94F1F15C11EB8AB5004B3AE3 /* PBXTextBookmark */; 94F1F5C910C30C22008DB9CF /* PBXTextBookmark */ = 94F1F5C910C30C22008DB9CF /* PBXTextBookmark */; 94F5C1870DF26EF200099B11 /* PBXTextBookmark */ = 94F5C1870DF26EF200099B11 /* PBXTextBookmark */; 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */ = 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */; 94F5C2600DF42C7600099B11 /* PBXTextBookmark */ = 94F5C2600DF42C7600099B11 /* PBXTextBookmark */; 94F5F29110BC518B00847EEE /* PBXTextBookmark */ = 94F5F29110BC518B00847EEE /* PBXTextBookmark */; 94F5F29210BC518B00847EEE /* PBXTextBookmark */ = 94F5F29210BC518B00847EEE /* PBXTextBookmark */; 94F5F29410BC518B00847EEE /* PBXTextBookmark */ = 94F5F29410BC518B00847EEE /* PBXTextBookmark */; 94F5F29510BC518B00847EEE /* PBXTextBookmark */ = 94F5F29510BC518B00847EEE /* PBXTextBookmark */; 94F5F2A810BC539700847EEE /* PBXTextBookmark */ = 94F5F2A810BC539700847EEE /* PBXTextBookmark */; 94F89AFE10B4997900556475 /* PBXTextBookmark */ = 94F89AFE10B4997900556475 /* PBXTextBookmark */; 94F89BDE10B4B77400556475 /* PBXTextBookmark */ = 94F89BDE10B4B77400556475 /* PBXTextBookmark */; 94F89BE010B4B77400556475 /* PBXTextBookmark */ = 94F89BE010B4B77400556475 /* PBXTextBookmark */; 94F89C9110B4C0B800556475 /* PBXTextBookmark */ = 94F89C9110B4C0B800556475 /* PBXTextBookmark */; 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */ = 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */; 94FE53951230323500BA17E1 /* PBXTextBookmark */ = 94FE53951230323500BA17E1 /* PBXTextBookmark */; }; sourceControlManager = 9424FF420DDC8673009912BF /* Source Control */; userBookmarkGroup = 94B8F4B910CF5BFF00F0DD6B /* PBXBookmarkGroup */; userBuildSettings = { }; }; 29B97316FDCFA39411CA2CEA /* main.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1327, 728}}"; sepNavSelRange = "{1872, 0}"; sepNavVisRange = "{278, 1871}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1208, 824}}"; sepNavSelRange = "{1850, 8}"; sepNavVisRange = "{0, 1878}"; sepNavWindowFrame = "{{483, 4}, {694, 1008}}"; }; }; 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 1040}}"; sepNavSelRange = "{2139, 0}"; sepNavVisRange = "{2081, 171}"; sepNavWindowFrame = "{{483, -9}, {694, 1008}}"; }; }; 940125A81228E3FC002883F0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94845C211228E29F00BEB880 /* macvideo.cpp */; name = "macvideo.cpp: 883"; rLen = 30; rLoc = 41143; rType = 0; vrLen = 3284; vrLoc = 40081; }; 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {2070, 1053}}"; sepNavSelRange = "{1161, 6}"; sepNavVisRange = "{0, 2416}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {2077, 3523}}"; sepNavSelRange = "{6138, 14}"; sepNavVisRange = "{6017, 1887}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DD6F10CE0E91005C2102 /* SqViewClut.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 1066}}"; sepNavSelRange = "{343, 0}"; sepNavVisRange = "{0, 2832}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9402DDB610CE12A5005C2102 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9402DDB710CE12A5005C2102 /* SqView.h */; name = "SqView.h: 50"; rLen = 33; rLoc = 1358; rType = 0; vrLen = 1671; vrLoc = 0; }; 9402DDB710CE12A5005C2102 /* SqView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqView.h; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqView.h"; sourceTree = "<absolute>"; }; 9402F2AE0F3F9BB900F3D637 /* PDColoredProgressView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 546}}"; sepNavSelRange = "{1081, 6}"; sepNavVisRange = "{31, 1299}"; }; }; 9402F2AF0F3F9BB900F3D637 /* PDColoredProgressView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {964, 1547}}"; sepNavSelRange = "{3465, 0}"; sepNavVisRange = "{2282, 1236}"; sepNavWindowFrame = "{{204, 6}, {1346, 974}}"; }; }; 9402F2C50F3F9C5600F3D637 /* drawing.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1492, 897}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1669}"; }; }; 94059106122AFB60009939CE /* ucontext.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ucontext.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/ucontext.h; sourceTree = "<absolute>"; }; 94059113122AFF8C009939CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94059106122AFB60009939CE /* ucontext.h */; name = "ucontext.h: 42"; rLen = 0; rLoc = 1410; rType = 0; vrLen = 1545; vrLoc = 0; }; 9406B4DF11EC314E002670B7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406B4E011EC314E002670B7 /* mach_time.h */; name = "mach_time.h: 46"; rLen = 18; rLoc = 1660; rType = 0; vrLen = 1731; vrLoc = 0; }; 9406B4E011EC314E002670B7 /* mach_time.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mach_time.h; path = /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/mach_time.h; sourceTree = "<absolute>"; }; 9406E7E210B663F4002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36A6D10B091BB0041953A /* NSCursor.h */; name = "NSCursor.h: 75"; rLen = 41; rLoc = 3288; rType = 0; vrLen = 1499; vrLoc = 1836; }; 9406E87110B66A74002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87210B66A74002F81F2 /* SqueakInterpreterEventSensor.h */; name = "SqueakInterpreterEventSensor.h: 11"; rLen = 8; rLoc = 416; rType = 0; vrLen = 555; vrLoc = 0; }; 9406E87210B66A74002F81F2 /* SqueakInterpreterEventSensor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakInterpreterEventSensor.h; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakInterpreterEventSensor.h"; sourceTree = "<absolute>"; }; 9406E87510B66A74002F81F2 /* SqueakInterpreterEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreterEventSensor.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakInterpreterEventSensor.m"; sourceTree = "<absolute>"; }; 9406E87710B66A74002F81F2 /* SqViewEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewEventSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewEventSensor.m"; sourceTree = "<absolute>"; }; 9406E8CC10B67499002F81F2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E8CD10B67499002F81F2 /* NSTextStorageScripting.h */; name = "NSTextStorageScripting.h: 21"; rLen = 25; rLoc = 417; rType = 0; vrLen = 620; vrLoc = 0; }; 9406E8CD10B67499002F81F2 /* NSTextStorageScripting.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextStorageScripting.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextStorageScripting.h; sourceTree = "<absolute>"; }; 9406E8D110B67499002F81F2 /* NSRange.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSRange.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRange.h; sourceTree = "<absolute>"; }; 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 754}}"; sepNavSelRange = "{95, 1688}"; sepNavVisRange = "{0, 1839}"; }; }; 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {922, 1365}}"; sepNavSelRange = "{3914, 0}"; sepNavVisRange = "{2585, 1552}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 940E86A31220A8D200AAB6F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */; name = "SqueakOSXAppDelegate.h: 49"; rLen = 8; rLoc = 2151; rType = 0; vrLen = 1827; vrLoc = 645; }; 940E86EE1220AF3D00AAB6F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF5B0DDCB1C7009912BF /* sqGnu.h */; name = "sqGnu.h: 165"; rLen = 0; rLoc = 10975; rType = 0; vrLen = 2508; vrLoc = 9372; }; 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 749}}"; sepNavSelRange = "{2019, 23}"; sepNavVisRange = "{0, 2070}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {965, 887}}"; sepNavSelRange = "{1814, 43}"; sepNavVisRange = "{0, 2410}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 941441FD10BC817D0088F8AC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941441FE10BC817D0088F8AC /* NSSavePanel.h */; name = "NSSavePanel.h: 207"; rLen = 23; rLoc = 10442; rType = 0; vrLen = 3994; vrLoc = 8956; }; 941441FE10BC817D0088F8AC /* NSSavePanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSavePanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSavePanel.h; sourceTree = "<absolute>"; }; 9414420010BC817D0088F8AC /* NSPanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPanel.h; sourceTree = "<absolute>"; }; 9414420110BC817D0088F8AC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9414420210BC817D0088F8AC /* NSOpenPanel.h */; name = "NSOpenPanel.h: 43"; rLen = 24; rLoc = 877; rType = 0; vrLen = 1896; vrLoc = 0; }; 9414420210BC817D0088F8AC /* NSOpenPanel.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSOpenPanel.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSOpenPanel.h; sourceTree = "<absolute>"; }; 9415BF3F123065640067CD8E /* dtraceOperationsPerSecond.d */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.dtrace; name = dtraceOperationsPerSecond.d; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/OSX/dtraceOperationsPerSecond.d; sourceTree = "<absolute>"; }; 9415C06312306B660067CD8E /* SqueakUIView.m:118 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; functionName = "-drawImageUsingClip:"; hitCount = 0; ignoreCount = 0; lineNumber = 118; location = Squeak; modificationTime = 308445394.271715; originalNumberOfMultipleMatches = 1; state = 1; }; 9415C06512306B6F0067CD8E /* SqueakUIView.m:126 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; functionName = "-drawThelayers"; hitCount = 0; ignoreCount = 0; lineNumber = 126; location = Squeak; modificationTime = 308445394.299481; originalNumberOfMultipleMatches = 1; state = 1; }; 9415C07412306BDD0067CD8E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9415BF3F123065640067CD8E /* dtraceOperationsPerSecond.d */; name = "dtraceOperationsPerSecond.d: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1560; vrLoc = 0; }; 9415C11412306FCC0067CD8E /* sqiPhoneScreenAndWindow.m:63 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */; functionName = "-ioForceDisplayUpdateActual"; hitCount = 0; ignoreCount = 0; lineNumber = 63; location = Squeak; modificationTime = 308445394.388573; originalNumberOfMultipleMatches = 1; state = 1; }; 941724420F36624C0031AF33 /* squeakProxy.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 2431}}"; sepNavSelRange = "{1931, 11}"; sepNavVisRange = "{493, 2138}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 941724430F36624C0031AF33 /* squeakProxy.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 1274}}"; sepNavSelRange = "{3018, 6}"; sepNavVisRange = "{2526, 1527}"; }; }; 941A331D11E63E1A004796BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941A331E11E63E1A004796BA /* ia64.c */; name = "ia64.c: 7278"; rLen = 1; rLoc = 208277; rType = 0; vrLen = 2659; vrLoc = 207667; }; 941A331E11E63E1A004796BA /* ia64.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ia64.c; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/ia64/ia64.c"; sourceTree = "<absolute>"; }; 941A331F11E63E1A004796BA /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941A332011E63E1A004796BA /* gatomic.c */; name = "gatomic.c: 522"; rLen = 18; rLoc = 14250; rType = 0; vrLen = 1827; vrLoc = 13448; }; 941A332011E63E1A004796BA /* gatomic.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = gatomic.c; path = "/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_devel_glib2-devel/work/glib-2.15.6/glib/gatomic.c"; sourceTree = "<absolute>"; }; 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */ = { uiCtxt = { sepNavWindowFrame = "{{15, 166}, {1288, 857}}"; }; }; 94210B280E956AC200C1A314 /* ObjectiveCPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 27248}}"; sepNavSelRange = "{53186, 9}"; sepNavVisRange = "{52405, 1628}"; sepNavWindowFrame = "{{710, 97}, {901, 833}}"; }; }; 9421AB550FF1807D008F54E9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949EFD7D0FF17FED00F540EB /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1049; vrLoc = 0; }; 94238E5E11E7B0EB004401BE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */; name = "sqMacV2Time.h: 6"; rLen = 0; rLoc = 72; rType = 0; vrLen = 1791; vrLoc = 0; }; 9424FF3E0DDC8654009912BF /* Squeak */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; commandLineArgs = ( ); displayName = "Executable Runner"; environment = { }; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 0; environmentEntries = ( { active = NO; name = NSAutoreleaseHaltOnFreedObject; value = YES; }, { active = NO; name = NSZombieEnabled; value = YES; }, { active = NO; name = NSAutoreleaseFreedObjectCheckEnabled; value = YES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = Squeak; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); startupPath = "<<ProductDirectory>>"; variableFormatDictionary = { $cpsr = 1; $cs = 1; $d0 = 1; $d1 = 1; $d10 = 1; $d11 = 1; $d12 = 1; $d13 = 1; $d14 = 1; $d15 = 1; $d2 = 1; $d3 = 1; $d4 = 1; $d5 = 1; $d6 = 1; $d7 = 1; $d8 = 1; $d9 = 1; $ds = 1; $eax = 1; $ebp = 1; $ebx = 1; $ecx = 1; $edi = 1; $edx = 1; $eflags = 1; $eip = 1; $es = 1; $esi = 1; $esp = 1; $fs = 1; $gs = 1; $ip = 1; $lr = 1; $mxcsr = 1; $pc = 1; $r0 = 1; $r1 = 1; $r10 = 1; $r11 = 1; $r12 = 1; $r2 = 1; $r3 = 1; $r4 = 1; $r5 = 1; $r6 = 1; $r7 = 1; $r8 = 1; $r9 = 1; $s0 = 1; $s1 = 1; $s10 = 1; $s11 = 1; $s12 = 1; $s13 = 1; $s14 = 1; $s15 = 1; $s16 = 1; $s17 = 1; $s18 = 1; $s19 = 1; $s2 = 1; $s20 = 1; $s21 = 1; $s22 = 1; $s23 = 1; $s24 = 1; $s25 = 1; $s26 = 1; $s27 = 1; $s28 = 1; $s29 = 1; $s3 = 1; $s30 = 1; $s31 = 1; $s4 = 1; $s5 = 1; $s6 = 1; $s7 = 1; $s8 = 1; $s9 = 1; $sl = 1; $sp = 1; $ss = 1; "*buffer-short int-primitiveNSInvocationGetShortType" = 1; "_return_value-sqInt-primitiveNSInvocationGetShortType" = 1; "actually-void *-sqAllocateMemoryMac" = 2; "data-id-primitiveNSInvocationGetObjectType" = 1; "data-short int-primitiveNSInvocationGetShortType" = 1; "dateDifference-sqInt-convertToSqueakTime" = 1; "fileSize-off_t-sqAllocateMemoryMac" = 2; "integerValue-sqInt-positive32BitIntegerFor" = 1; "mFormatID-UInt32--[sqSqueakSoundCoreAudio snd_StartRecording:stereo:semaIndex:]" = 5; "possibleLocation-void *-sqAllocateMemoryMac" = 2; "returnValue-struct objc_object * volatile-primitivePerformSelector" = 2; "startOfAnonymousMemory-void *-sqAllocateMemoryMac" = 1; "startOfAnonymousMemoryPageSize-size_t-sqAllocateMemoryMac" = 1; "unsignedData-long long unsigned int-primitiveNSInvocationGetLongLongType" = 1; "what-long int--[SqueakProxy forwardInvocation:]" = 1; "why-int-aioPoll" = 1; }; }; 9424FF420DDC8673009912BF /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { repositoryName = "http://svn.isqueak.org/"; repositoryNamesForRoots = { "" = SqueakVM; }; }; }; 9424FF430DDC8673009912BF /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; 9424FF5B0DDCB1C7009912BF /* sqGnu.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2730}}"; sepNavSelRange = "{10975, 0}"; sepNavVisRange = "{9372, 2508}"; sepNavWindowFrame = "{{15, 4}, {1194, 1019}}"; }; }; 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1327, 2171}}"; sepNavSelRange = "{2839, 0}"; sepNavVisRange = "{0, 0}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9424FF5D0DDCB1C7009912BF /* sq.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1027, 6916}}"; sepNavSelRange = "{18266, 35}"; sepNavVisRange = "{17190, 2307}"; sepNavWindowFrame = "{{73, 4}, {1326, 1010}}"; }; }; 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {800, 6890}}"; sepNavSelRange = "{660, 33}"; sepNavVisRange = "{0, 1563}"; sepNavWindowFrame = "{{15, 38}, {847, 985}}"; }; }; 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 6500}}"; sepNavSelRange = "{14571, 22}"; sepNavVisRange = "{13799, 1509}"; }; }; 9424FF610DDCB1C7009912BF /* sqVirtualMachine.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1391, 3835}}"; sepNavSelRange = "{6672, 30}"; sepNavVisRange = "{5691, 1846}"; sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 2158}}"; sepNavSelRange = "{3458, 89}"; sepNavVisRange = "{2732, 1658}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 9424FF650DDCB1EF009912BF /* config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2912}}"; sepNavSelRange = "{3660, 0}"; sepNavVisRange = "{3240, 1112}"; sepNavWindowFrame = "{{38, 17}, {847, 985}}"; }; }; 9424FF660DDCB1EF009912BF /* sqConfig.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 807}}"; sepNavSelRange = "{88, 25}"; sepNavVisRange = "{0, 302}"; sepNavWindowFrame = "{{15, 4}, {1385, 1024}}"; }; }; 9424FF670DDCB202009912BF /* sqMacV2Memory.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1069, 2522}}"; sepNavSelRange = "{2861, 16}"; sepNavVisRange = "{2252, 1746}"; sepNavWindowFrame = "{{497, 1}, {905, 983}}"; }; }; 9424FF680DDCB202009912BF /* sqMacV2Memory.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 820}}"; sepNavSelRange = "{2075, 15}"; sepNavVisRange = "{0, 2098}"; sepNavWindowFrame = "{{15, 40}, {905, 983}}"; }; }; 9424FF710DDCB234009912BF /* macintoshextra.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 689}}"; sepNavSelRange = "{235, 11}"; sepNavVisRange = "{172, 1750}"; sepNavWindowFrame = "{{539, 15}, {905, 983}}"; }; }; 9424FF720DDCB234009912BF /* macintoshextra.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 629}}"; sepNavSelRange = "{183, 15}"; sepNavVisRange = "{0, 198}"; }; }; 9424FF750DDCB271009912BF /* osExports.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {802, 587}}"; sepNavSelRange = "{389, 0}"; sepNavVisRange = "{0, 571}"; }; }; 9427E35512626DFB002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; name = "sqSqueakOSXNSView.m: 293"; rLen = 0; rLoc = 10089; rType = 0; vrLen = 2715; vrLoc = 6392; }; 9427E37B12626EE6002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638B260EAFB77B00A3F155 /* iPhone.changes */; name = "iPhone.changes: 134722"; rLen = 0; rLoc = 5548785; rType = 0; vrLen = 2552; vrLoc = 5075399; }; 9427E3F612627C61002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */; name = "sqSqueakOSXApplication+imageReadWrite.m: 64"; rLen = 0; rLoc = 2709; rType = 0; vrLen = 1821; vrLoc = 1953; }; 9427E3F812627C61002DCA6D /* PlistBookmark */ = { isa = PlistBookmark; fRef = 949AD14911E542E8006D6BF4 /* SqueakPureObjc-InfoCOG.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( CFBundleGetInfoString, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc-InfoCOG.plist"; rLen = 0; rLoc = 9223372036854775808; }; 9427E3F912627C61002DCA6D /* PlistBookmark */ = { isa = PlistBookmark; fRef = 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( SqueakUIFadeForFullScreenInSeconds, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjc-Info.plist"; rLen = 0; rLoc = 9223372036854775808; }; 9427E3FC12627C61002DCA6D /* Root.plist */ = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Root.plist; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Settings.bundle/Root.plist; sourceTree = "<absolute>"; }; 9427E42E12627E6A002DCA6D /* sqSqueakIPhoneApplication+imageReadWrite.m:95 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */; functionName = "-findImageViaBundleOrPreferences"; hitCount = 1; ignoreCount = 0; lineNumber = 95; location = Squeak; modificationTime = 308445400.27705; originalNumberOfMultipleMatches = 1; state = 1; }; 9427E44B12628333002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */; name = "sqSqueakIPhoneInfoPlistInterface.m: 56"; rLen = 0; rLoc = 2332; rType = 0; vrLen = 2389; vrLoc = 1214; }; 9427E44C12628333002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */; name = "sqSqueakIPhoneApplication+imageReadWrite.m: 54"; rLen = 15; rLoc = 2235; rType = 0; vrLen = 2631; vrLoc = 2815; }; 9427E44D12628333002DCA6D /* PlistBookmark */ = { isa = PlistBookmark; fRef = 9427E3FC12627C61002DCA6D /* Root.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( PreferenceSpecifiers, 2, TrueValue, ); name = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Settings.bundle/Root.plist; rLen = 0; rLoc = 9223372036854775808; }; 9427E46212629AE3002DCA6D /* PBXBookmark */ = { isa = PBXBookmark; fRef = 94F3A9690E6BFA7C00E0B12A /* Squeak.png */; }; 9427E46312629AE3002DCA6D /* PlistBookmark */ = { isa = PlistBookmark; fRef = 94C36C9710B0CF290041953A /* Info-iPhone.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( UIFileSharingEnabled, ); name = "/Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Info-iPhone.plist"; rLen = 0; rLoc = 9223372036854775808; }; 9427E4D11262B997002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; name = "sqSqueakFileDirectoryInterface.m: 140"; rLen = 37; rLoc = 4849; rType = 0; vrLen = 2369; vrLoc = 3923; }; 9427E4D21262B997002DCA6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE7A60DDDF8F800F38F31 /* sqaio.h */; name = "sqaio.h: 95"; rLen = 16; rLoc = 4027; rType = 0; vrLen = 2290; vrLoc = 1798; }; 942807EE1224862A0000DCFE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */; name = "sqMacExtendedClipboard.m: 101"; rLen = 40; rLoc = 3679; rType = 0; vrLen = 2397; vrLoc = 1736; }; 942807EF1224862A0000DCFE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; name = "sqMacExtendedClipboard.m: 88"; rLen = 111; rLoc = 3036; rType = 0; vrLen = 2240; vrLoc = 1524; }; 942807F01224862A0000DCFE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; name = "sqSqueakIPhoneClipboardAPI.m: 17"; rLen = 28; rLoc = 398; rType = 0; vrLen = 1345; vrLoc = 0; }; 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 623}}"; sepNavSelRange = "{0, 1814}"; sepNavVisRange = "{0, 1814}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 871}}"; sepNavSelRange = "{2148, 13}"; sepNavVisRange = "{787, 2052}"; sepNavWindowFrame = "{{16, 4}, {878, 1019}}"; }; }; 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 623}}"; sepNavSelRange = "{184, 2018}"; sepNavVisRange = "{0, 2202}"; }; }; 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 1092}}"; sepNavSelRange = "{2664, 37}"; sepNavVisRange = "{1451, 2157}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9428BBAD10BB50E200DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBAE10BB50E200DAD287 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1028"; rLen = 9; rLoc = 28100; rType = 0; vrLen = 1398; vrLoc = 27330; }; 9428BBAE10BB50E200DAD287 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakIA32ABIPlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9428BBE210BB565100DAD287 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm-display-Quartz/zzz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9428BBE510BB565100DAD287 /* NSPasteboard.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPasteboard.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPasteboard.h; sourceTree = "<absolute>"; }; 9428BC5510BB74BF00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFC410ACC89100F87527 /* string.h */; name = "string.h: 83"; rLen = 44; rLoc = 3369; rType = 0; vrLen = 1928; vrLoc = 2407; }; 9428BC5710BB74BF00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBE510BB565100DAD287 /* NSPasteboard.h */; name = "NSPasteboard.h: 138"; rLen = 50; rLoc = 9563; rType = 0; vrLen = 3372; vrLoc = 7682; }; 9428BF3810BBC2ED00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC3710AB79DA00F87527 /* NSArray.h */; name = "NSArray.h: 91"; rLen = 15; rLoc = 4609; rType = 0; vrLen = 2275; vrLoc = 3251; }; 9428BF4F10BBCAAC00DAD287 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC3C10AB79DA00F87527 /* NSDictionary.h */; name = "NSDictionary.h: 75"; rLen = 19; rLoc = 3192; rType = 0; vrLen = 2430; vrLoc = 1218; }; 942ABD9410AA1F8E0086D908 /* CGGeometry.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGGeometry.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGGeometry.h; sourceTree = "<absolute>"; }; 942ABE0910AA21270086D908 /* NSView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSView.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSView.h; sourceTree = "<absolute>"; }; 942ABEC510AA34820086D908 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABEC610AA34820086D908 /* sqMacHostWindow.h */; name = "sqMacHostWindow.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 845; vrLoc = 0; }; 942ABEC610AA34820086D908 /* sqMacHostWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqMacHostWindow.h; path = "/Volumes/pm/Mail/IMAP-johnmci@smalltalkconsulting.com@imap.gmail.com/[Gmail]/Sent Mail.imapmbox/Attachments/2958644/8/sqMacHostWindow.h"; sourceTree = "<absolute>"; }; 942B77300EA7E642004B266D /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = "/Users/johnmci/Documents/Squeak/Squeak3.8.1-6747-basic#2/src32iPhone/vm/interp.c"; sourceTree = "<absolute>"; }; 942B77330EA7E642004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77340EA7E642004B266D /* sqWin32Prefs.c */; name = "sqWin32Prefs.c: 184"; rLen = 15; rLoc = 6379; rType = 0; vrLen = 1782; vrLoc = 5482; }; 942B77340EA7E642004B266D /* sqWin32Prefs.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Prefs.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Prefs.c; sourceTree = "<absolute>"; }; 942B77380EA7E642004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E6D0DF1171500FB176B /* sqWin32Window.c */; name = "sqWin32Window.c: 65"; rLen = 19; rLoc = 2258; rType = 0; vrLen = 2119; vrLoc = 1403; }; 942B778B0EA7EF0B004B266D /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakQuicktimePlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 942B779B0EA7F2E0004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E640DF1171500FB176B /* sqUnixX11.c */; name = "sqUnixX11.c: 1316"; rLen = 6; rLoc = 37289; rType = 0; vrLen = 1058; vrLoc = 36631; }; 942B779C0EA7F2E0004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B778B0EA7EF0B004B266D /* sqUnixX11.c */; name = "sqUnixX11.c: 1332"; rLen = 6; rLoc = 37592; rType = 0; vrLen = 1035; vrLoc = 36654; }; 942B77B90EA800E1004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77BA0EA800E1004B266D /* sqWin32Alloc.c */; name = "sqWin32Alloc.c: 55"; rLen = 10; rLoc = 2096; rType = 0; vrLen = 1633; vrLoc = 2014; }; 942B77BA0EA800E1004B266D /* sqWin32Alloc.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Alloc.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Alloc.c; sourceTree = "<absolute>"; }; 942B77BB0EA800E1004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77BC0EA800E1004B266D /* sqWin32Alloc.h */; name = "sqWin32Alloc.h: 15"; rLen = 18; rLoc = 487; rType = 0; vrLen = 955; vrLoc = 0; }; 942B77BC0EA800E1004B266D /* sqWin32Alloc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqWin32Alloc.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Alloc.h; sourceTree = "<absolute>"; }; 942B77C00EA800E1004B266D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942B77300EA7E642004B266D /* interp.c */; name = "interp.c: 21810"; rLen = 14; rLoc = 688282; rType = 0; vrLen = 1337; vrLoc = 687512; }; 942CF43710BFCD52008F9BB7 /* sqGnu.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/SqueakNoOGLIPhoneOSX/platforms/unix/vm/sqGnu.h; sourceTree = "<absolute>"; }; 942CF46B10BCE44B009BD905 /* NSWindowController.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindowController.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindowController.h; sourceTree = "<absolute>"; }; 942F48FA123C1C0C002B05DF /* SqueakUIViewCALayer.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2008}"; }; }; 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1440, 1651}}"; sepNavSelRange = "{3940, 0}"; sepNavVisRange = "{2106, 2714}"; sepNavWindowFrame = "{{501, 9}, {1140, 1019}}"; }; }; 942F48FC123C1C0C002B05DF /* SqueakUIViewOpenGL.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1123, 1092}}"; sepNavSelRange = "{2817, 0}"; sepNavVisRange = "{445, 2344}"; sepNavWindowFrame = "{{15, 18}, {1170, 1005}}"; }; }; 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {943, 2691}}"; sepNavSelRange = "{7522, 0}"; sepNavVisRange = "{4086, 1804}"; }; }; 942F6FFC1102F5A300A0A349 /* NSNull.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSNull.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNull.h; sourceTree = "<absolute>"; }; 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1169, 764}}"; sepNavSelRange = "{1777, 0}"; sepNavVisRange = "{0, 1781}"; sepNavWindowFrame = "{{913, 18}, {694, 1008}}"; }; }; 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1053}}"; sepNavSelRange = "{3050, 9}"; sepNavVisRange = "{1935, 1304}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 654}}"; sepNavSelRange = "{1955, 0}"; sepNavVisRange = "{0, 1955}"; sepNavWindowFrame = "{{15, 4}, {1573, 1024}}"; }; }; 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1014}}"; sepNavSelRange = "{2308, 12}"; sepNavVisRange = "{1439, 1670}"; }; }; 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1287}}"; sepNavSelRange = "{2326, 7}"; sepNavVisRange = "{1642, 1332}"; sepNavWindowFrame = "{{577, 27}, {997, 998}}"; }; }; 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 654}}"; sepNavSelRange = "{1913, 14}"; sepNavVisRange = "{0, 1953}"; }; }; 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1819, 94}"; sepNavVisRange = "{0, 1919}"; sepNavWindowFrame = "{{337, 21}, {1288, 857}}"; }; }; 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1716}}"; sepNavSelRange = "{2350, 0}"; sepNavVisRange = "{3722, 1639}"; sepNavWindowFrame = "{{38, 24}, {1017, 978}}"; }; }; 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1810, 0}"; sepNavVisRange = "{0, 1951}"; }; }; 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 884}}"; sepNavSelRange = "{2025, 19}"; sepNavVisRange = "{1339, 1475}"; sepNavWindowFrame = "{{38, 4}, {1274, 998}}"; }; }; 9430325510BD0B6D0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAB0410AB6DC000F87527 /* NSApplication.h */; name = "NSApplication.h: 314"; rLen = 11; rLoc = 14168; rType = 0; vrLen = 2745; vrLoc = 14077; }; 9430329A10BD103B0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAF7D10ACC0D900F87527 /* NSPathUtilities.h */; name = "NSPathUtilities.h: 26"; rLen = 25; rLoc = 696; rType = 0; vrLen = 1577; vrLoc = 0; }; 9430329B10BD103B0045D33B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC0310AB759300F87527 /* NSURL.h */; name = "NSURL.h: 36"; rLen = 5; rLoc = 1448; rType = 0; vrLen = 2612; vrLoc = 0; }; 943198450DDF4D9800EB8E60 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94360A8C10E84CC90060221A /* NSException.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSException.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSException.h; sourceTree = "<absolute>"; }; 943B9AF21235B94D0056205E /* sqSqueakOSXNSWindowController.m */ = { isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXNSWindowController.m; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/OSX/sqSqueakOSXNSWindowController.m; sourceTree = "<absolute>"; }; 943B9AF71235B9FD0056205E /* sqSqueakOSXNSWindowController.m:18 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 943B9AF21235B94D0056205E /* sqSqueakOSXNSWindowController.m */; functionName = "-windowShouldClose:"; hitCount = 0; ignoreCount = 0; lineNumber = 18; modificationTime = 308445393.436679; originalNumberOfMultipleMatches = 1; state = 0; }; 943B9B151235BB080056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */; name = "sqSqueakOSXScreenAndWindow.h: 42"; rLen = 8; rLoc = 1876; rType = 0; vrLen = 2111; vrLoc = 0; }; 943B9B1E1235BD150056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E658FA0DDD03FE00358328 /* HostWindowPlugin.c */; name = "HostWindowPlugin.c: 45"; rLen = 10; rLoc = 1148; rType = 0; vrLen = 1576; vrLoc = 410; }; 943B9B281235BDD20056205E /* sqMacHostWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 2587}}"; sepNavSelRange = "{2304, 11}"; sepNavVisRange = "{1951, 552}"; sepNavWindowFrame = "{{61, 7}, {1206, 974}}"; }; }; 943B9B291235BDD20056205E /* sqMacHostWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 962}}"; sepNavSelRange = "{7, 17}"; sepNavVisRange = "{3, 717}"; sepNavWindowFrame = "{{15, 49}, {1206, 974}}"; }; }; 943B9B9E1235BE580056205E /* sqMacHostWindow.m:58 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 943B9B281235BDD20056205E /* sqMacHostWindow.m */; hitCount = 0; ignoreCount = 0; lineNumber = 58; modificationTime = 308445393.436735; originalNumberOfMultipleMatches = 1; state = 0; }; 943B9BD31235C1120056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */; name = "sqMacHostWindow.c: 57"; rLen = 11; rLoc = 2260; rType = 0; vrLen = 1911; vrLoc = 1052; }; 943B9BD41235C1120056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */; name = "sqMacHostWindow.h: 26"; rLen = 0; rLoc = 852; rType = 0; vrLen = 2396; vrLoc = 266; }; 943B9C041235C1EE0056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943B9B291235BDD20056205E /* sqMacHostWindow.h */; name = "sqMacHostWindow.h: 67"; rLen = 21; rLoc = 2445; rType = 0; vrLen = 2417; vrLoc = 279; }; 943B9C311235C3D70056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943B9B281235BDD20056205E /* sqMacHostWindow.m */; name = "sqMacHostWindow.m: 59"; rLen = 0; rLoc = 2358; rType = 0; vrLen = 1772; vrLoc = 1480; }; 943B9C331235C3D70056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; name = "sqSqueakAppDelegate.m: 45"; rLen = 0; rLoc = 1875; rType = 0; vrLen = 1533; vrLoc = 1777; }; 943B9D621235C79C0056205E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */; name = "sqMacV2Browser.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1518; vrLoc = 0; }; 943C0AC7122DF3710086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */; name = "SqViewBitmapConversion.h: 23"; rLen = 6; rLoc = 1161; rType = 0; vrLen = 2416; vrLoc = 0; }; 943C0AC8122DF3710086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */; name = "BitMapConversionLogicFromX11.c: 42"; rLen = 84; rLoc = 1749; rType = 0; vrLen = 1795; vrLoc = 1650; }; 943C0ACA122DF3710086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */; name = "BitMapConversionLogicFromX11.h: 18"; rLen = 14; rLoc = 581; rType = 0; vrLen = 1092; vrLoc = 0; }; 943C0AE0122DF5E70086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C0AE1122DF5E70086B6AD /* nextdemo4.m */; name = "nextdemo4.m: 86"; rLen = 12; rLoc = 3085; rType = 0; vrLen = 1904; vrLoc = 2365; }; 943C0AE1122DF5E70086B6AD /* nextdemo4.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = nextdemo4.m; path = "/Users/johnmci/Work In Progress/stx/support/MESA/Mesa-3.0/OpenStep/Old_NeXT/nextdemo4.m"; sourceTree = "<absolute>"; }; 943C0AE2122DF5E70086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C0AE3122DF5E70086B6AD /* CGLMacro.h */; name = "CGLMacro.h: 35"; rLen = 27; rLoc = 1169; rType = 0; vrLen = 2295; vrLoc = 0; }; 943C0AE3122DF5E70086B6AD /* CGLMacro.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGLMacro.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/CGLMacro.h; sourceTree = "<absolute>"; }; 943C0AE5122DF5E70086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C0AE6122DF5E70086B6AD /* Texturing.m */; name = "Texturing.m: 14"; rLen = 0; rLoc = 486; rType = 0; vrLen = 2764; vrLoc = 0; }; 943C0AE6122DF5E70086B6AD /* Texturing.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Texturing.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/LayerBackedOpenGLView/Texturing.m"; sourceTree = "<absolute>"; }; 943C0AE7122DF5E70086B6AD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943C0AE8122DF5E70086B6AD /* NeonTexture.m */; name = "NeonTexture.m: 21"; rLen = 0; rLoc = 300; rType = 0; vrLen = 1130; vrLoc = 0; }; 943C0AE8122DF5E70086B6AD /* NeonTexture.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NeonTexture.m; path = "/Volumes/pm/Mail Downloads/iProPutt/NeonEngine/NeonTexture.m"; sourceTree = "<absolute>"; }; 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 22763}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 902}"; }; }; 9441DB7111E6805300345F6C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5D80E044A9D000AD792 /* Queue.m */; name = "Queue.m: 117"; rLen = 2; rLoc = 3624; rType = 0; vrLen = 893; vrLoc = 2784; }; 9441DB7211E6805300345F6C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */; name = "sqSqueakOSXDropAPI.m: 53"; rLen = 45; rLoc = 2070; rType = 0; vrLen = 2385; vrLoc = 718; }; 9448940B10F3E8FF00FB3EC8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 943198450DDF4D9800EB8E60 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 406"; rLen = 36; rLoc = 11460; rType = 0; vrLen = 1419; vrLoc = 10879; }; 944895AD10F4081300FB3EC8 /* PharoV10.sources */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1209, 3.55314e+06}}"; sepNavSelRange = "{1830818, 7}"; sepNavVisRange = "{1829163, 2429}"; }; }; 944F6D171224D7B300DFC0CD /* sqSqueakOSXApplication+imageReadWrite.m:64 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */; functionName = "-attempToOpenImageFromOpenPanel"; hitCount = 0; ignoreCount = 0; lineNumber = 64; modificationTime = 308445393.4364201; originalNumberOfMultipleMatches = 1; state = 0; }; 9451E64F123F0E9200B4119F /* PlistBookmark */ = { isa = PlistBookmark; fRef = 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/Entitlements.plist; rLen = 0; rLoc = 9223372036854775808; }; 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{409, 0}"; sepNavVisRange = "{0, 562}"; }; }; 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 845}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1067}"; }; }; 9452D5D70E044A9D000AD792 /* Queue.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 845}}"; sepNavSelRange = "{2692, 0}"; sepNavVisRange = "{1337, 1516}"; sepNavWindowFrame = "{{15, 4}, {1593, 1019}}"; }; }; 9452D5D80E044A9D000AD792 /* Queue.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {970, 1612}}"; sepNavSelRange = "{2961, 27}"; sepNavVisRange = "{2763, 914}"; sepNavWindowFrame = "{{38, 12}, {1017, 978}}"; }; }; 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1394, 2392}}"; sepNavSelRange = "{3709, 1378}"; sepNavVisRange = "{3710, 1377}"; sepNavWindowFrame = "{{510, 30}, {1441, 887}}"; }; }; 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 762}}"; sepNavSelRange = "{72, 0}"; sepNavVisRange = "{0, 1791}"; }; }; 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 572}}"; sepNavSelRange = "{1792, 10}"; sepNavVisRange = "{3, 1942}"; }; }; 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 2691}}"; sepNavSelRange = "{7520, 20}"; sepNavVisRange = "{5747, 1848}"; sepNavWindowFrame = "{{15, 43}, {1379, 980}}"; }; }; 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1170}}"; sepNavSelRange = "{2012, 19}"; sepNavVisRange = "{1284, 1422}"; sepNavWindowFrame = "{{909, 13}, {1012, 1015}}"; }; }; 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1076, 4108}}"; sepNavSelRange = "{4849, 37}"; sepNavVisRange = "{3923, 2369}"; sepNavWindowFrame = "{{101, 4}, {1064, 1024}}"; }; }; 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1327, 2210}}"; sepNavSelRange = "{3692, 0}"; sepNavVisRange = "{3261, 489}"; }; }; 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {936, 741}}"; sepNavSelRange = "{1322, 449}"; sepNavVisRange = "{0, 1868}"; }; }; 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{2087, 0}"; sepNavVisRange = "{0, 2202}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1378}}"; sepNavSelRange = "{2343, 37}"; sepNavVisRange = "{1830, 1334}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1157}}"; sepNavSelRange = "{3075, 23}"; sepNavVisRange = "{2009, 1532}"; sepNavWindowFrame = "{{888, 14}, {694, 1008}}"; }; }; 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 3094}}"; sepNavSelRange = "{4926, 259}"; sepNavVisRange = "{4926, 701}"; sepNavWindowFrame = "{{685, 38}, {905, 983}}"; }; }; 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {936, 766}}"; sepNavSelRange = "{88, 1700}"; sepNavVisRange = "{0, 1790}"; }; }; 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 754}}"; sepNavSelRange = "{2248, 12}"; sepNavVisRange = "{776, 1571}"; }; }; 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{78, 0}"; sepNavVisRange = "{0, 1785}"; }; }; 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1538, 1118}}"; sepNavSelRange = "{2380, 11}"; sepNavVisRange = "{1887, 1135}"; sepNavWindowFrame = "{{668, 4}, {1012, 1015}}"; }; }; 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 606}}"; sepNavSelRange = "{1909, 23}"; sepNavVisRange = "{0, 1943}"; sepNavWindowFrame = "{{15, 50}, {1346, 974}}"; }; }; 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 871}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 2225}"; sepNavWindowFrame = "{{802, 9}, {878, 1019}}"; }; }; 9453F58A1234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9453F58B1234AF8A00C91CF7 /* SqueakView.m */; name = "SqueakView.m: 57"; rLen = 14; rLoc = 1275; rType = 0; vrLen = 1163; vrLoc = 328; }; 9453F58B1234AF8A00C91CF7 /* SqueakView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakView.m; path = "/Users/johnmci/Documents/SqueakHydraZBaseCheck/HydraVM-src/platforms/unix/vm-display-Quartz/SqueakView.m"; sourceTree = "<absolute>"; }; 9453F58C1234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C540E81500200C98131 /* SqView.m */; name = "SqView.m: 409"; rLen = 10; rLoc = 11118; rType = 0; vrLen = 1528; vrLoc = 10567; }; 9453F58D1234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9453F58E1234AF8A00C91CF7 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1989"; rLen = 12; rLoc = 52050; rType = 0; vrLen = 1183; vrLoc = 51017; }; 9453F58E1234AF8A00C91CF7 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakSpellingPlugin/platforms/unix/vm-display-Quartz/zzz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9453F5911234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9453F5921234AF8A00C91CF7 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 155"; rLen = 23; rLoc = 5053; rType = 0; vrLen = 1549; vrLoc = 35560; }; 9453F5921234AF8A00C91CF7 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Volumes/330GB Photos/Cog Before Aug 2010 changes/platforms/unix/vm-display-Quartz/zzz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 9453F5931234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9453F5941234AF8A00C91CF7 /* image.c */; name = "image.c: 1511"; rLen = 12; rLoc = 46495; rType = 0; vrLen = 1885; vrLoc = 0; }; 9453F5941234AF8A00C91CF7 /* image.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = image.c; path = "/Users/johnmci/Work In Progress/stx/support/MESA/Mesa-3.0/src/image.c"; sourceTree = "<absolute>"; }; 9453F5951234AF8A00C91CF7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9453F5961234AF8A00C91CF7 /* OpenGLScreenReader.m */; name = "OpenGLScreenReader.m: 22"; rLen = 0; rLoc = 939; rType = 0; vrLen = 2744; vrLoc = 0; }; 9453F5961234AF8A00C91CF7 /* OpenGLScreenReader.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OpenGLScreenReader.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/OpenGLScreenSnapshot/OpenGLScreenReader.m"; sourceTree = "<absolute>"; }; 94547F160DE0AC7D00DD588F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94547F170DE0AC7D00DD588F /* sqMacMain.c */; name = "sqMacMain.c: 486"; rLen = 37; rLoc = 19144; rType = 0; vrLen = 1112; vrLoc = 18071; }; 94547F170DE0AC7D00DD588F /* sqMacMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacMain.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/vm/sqMacMain.c"; sourceTree = "<absolute>"; }; 9454809B0DE2945300DD588F /* sqMacUnixFileInterface.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUnixFileInterface.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/plugins/FilePlugin/sqMacUnixFileInterface.c"; sourceTree = "<absolute>"; }; 945481A60DE2A79200DD588F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9454809B0DE2945300DD588F /* sqMacUnixFileInterface.c */; name = "sqMacUnixFileInterface.c: 512"; rLen = 40; rLoc = 16278; rType = 0; vrLen = 1679; vrLoc = 15123; }; 94554E640DF1171500FB176B /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakSpellingPlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 94554E670DF1171500FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E680DF1171500FB176B /* sqUnixX11.c */; name = "sqUnixX11.c: 2319"; rLen = 12; rLoc = 63841; rType = 0; vrLen = 1057; vrLoc = 63650; }; 94554E680DF1171500FB176B /* sqUnixX11.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixX11.c; path = "/Users/johnmci/Documents/SqueakServicesPlugin/platforms/unix/vm-display-X11/sqUnixX11.c"; sourceTree = "<absolute>"; }; 94554E690DF1171500FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E6A0DF1171500FB176B /* sqMacWindow.c */; name = "sqMacWindow.c: 797"; rLen = 17; rLoc = 29608; rType = 0; vrLen = 994; vrLoc = 29083; }; 94554E6A0DF1171500FB176B /* sqMacWindow.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindow.c; path = "/Users/johnmci/Documents/SqueakServicesPlugin/platforms/Mac OS/vm/sqMacWindow.c"; sourceTree = "<absolute>"; }; 94554E6D0DF1171500FB176B /* sqWin32Window.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Window.c; path = /Users/johnmci/Documents/SqueakServicesPlugin/platforms/win32/vm/sqWin32Window.c; sourceTree = "<absolute>"; }; 94554E7F0DF1171500FB176B /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 94554EB80DF1A86A00FB176B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94554E7F0DF1171500FB176B /* sqUnixMain.c */; name = "sqUnixMain.c: 526"; rLen = 12; rLoc = 12689; rType = 0; vrLen = 1587; vrLoc = 12009; }; 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 572}}"; sepNavSelRange = "{1902, 6}"; sepNavVisRange = "{3, 1912}"; sepNavWindowFrame = "{{15, 22}, {1064, 1001}}"; }; }; 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1001}}"; sepNavSelRange = "{2882, 22}"; sepNavVisRange = "{1657, 1632}"; }; }; 9456C24F10B2F268000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABD9410AA1F8E0086D908 /* CGGeometry.h */; name = "CGGeometry.h: 29"; rLen = 16; rLoc = 429; rType = 0; vrLen = 1403; vrLoc = 0; }; 9456C25A10B2F2C9000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C25B10B2F2C9000BF3DE /* types.h */; name = "types.h: 83"; rLen = 25; rLoc = 3624; rType = 0; vrLen = 1820; vrLoc = 2321; }; 9456C25B10B2F2C9000BF3DE /* types.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = types.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/i386/types.h; sourceTree = "<absolute>"; }; 9456C2F910B32D2A000BF3DE /* NSString.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSString.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSString.h; sourceTree = "<absolute>"; }; 9456C32210B32F43000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C32310B32F43000BF3DE /* NSClipView.h */; name = "NSClipView.h: 22"; rLen = 9; rLoc = 509; rType = 0; vrLen = 2046; vrLoc = 0; }; 9456C32310B32F43000BF3DE /* NSClipView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSClipView.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSClipView.h; sourceTree = "<absolute>"; }; 9456C34E10B33618000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C34F10B33618000BF3DE /* CALayer.h */; name = "CALayer.h: 169"; rLen = 35; rLoc = 5389; rType = 0; vrLen = 2280; vrLoc = 4266; }; 9456C34F10B33618000BF3DE /* CALayer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CALayer.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CALayer.h; sourceTree = "<absolute>"; }; 9456C3CB10B341F9000BF3DE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C3CC10B341F9000BF3DE /* NSAffineTransform.h */; name = "NSAffineTransform.h: 39"; rLen = 8; rLoc = 933; rType = 0; vrLen = 1411; vrLoc = 0; }; 9456C3CC10B341F9000BF3DE /* NSAffineTransform.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSAffineTransform.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSAffineTransform.h; sourceTree = "<absolute>"; }; 94584F6110F020BD001401E7 /* ClipboardExtendedPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3107}}"; sepNavSelRange = "{4263, 0}"; sepNavVisRange = "{3941, 851}"; }; }; 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 1469}}"; sepNavSelRange = "{3679, 40}"; sepNavVisRange = "{1736, 2397}"; sepNavWindowFrame = "{{242, 4}, {1438, 968}}"; }; }; 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 507}}"; sepNavSelRange = "{1388, 0}"; sepNavVisRange = "{336, 1542}"; sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 9458511410F03996001401E7 /* sqMacExtendedClipboard.m:101 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */; functionName = "sqPasteboardCopyItemFlavorDataformatformatLength()"; hitCount = 0; ignoreCount = 0; lineNumber = 101; location = Squeak; modificationTime = 308445393.435976; originalNumberOfMultipleMatches = 1; state = 1; }; 945851EE10F03E60001401E7 /* sqMacExtendedClipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1331, 873}}"; sepNavSelRange = "{7, 24}"; sepNavVisRange = "{0, 1878}"; sepNavWindowFrame = "{{15, 4}, {1378, 1024}}"; }; }; 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 1352}}"; sepNavSelRange = "{3036, 111}"; sepNavVisRange = "{1524, 2240}"; sepNavWindowFrame = "{{61, 13}, {1438, 968}}"; }; }; 9458523210F040A0001401E7 /* sqMacExtendedClipboard.m:37 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 37; location = Squeak; modificationTime = 308445393.842733; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523410F040A1001401E7 /* sqMacExtendedClipboard.m:45 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 45; location = Squeak; modificationTime = 308445393.890903; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523610F040A2001401E7 /* sqMacExtendedClipboard.m:50 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 50; location = Squeak; modificationTime = 308445393.953986; originalNumberOfMultipleMatches = 1; state = 1; }; 9458523A10F040AF001401E7 /* sqMacExtendedClipboard.m:72 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 72; location = Squeak; modificationTime = 308445393.982063; originalNumberOfMultipleMatches = 1; state = 1; }; 9458524810F04272001401E7 /* sqMacExtendedClipboard.m:88 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; hitCount = 0; ignoreCount = 0; lineNumber = 88; location = Squeak; modificationTime = 308445394.050499; originalNumberOfMultipleMatches = 1; state = 1; }; 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 769}}"; sepNavSelRange = "{58, 44}"; sepNavVisRange = "{0, 1817}"; }; }; 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 808}}"; sepNavSelRange = "{398, 28}"; sepNavVisRange = "{0, 1345}"; }; }; 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 624}}"; sepNavSelRange = "{1956, 0}"; sepNavVisRange = "{799, 1415}"; }; }; 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 654}}"; sepNavSelRange = "{695, 37}"; sepNavVisRange = "{0, 1522}"; }; }; 9458527F10F045FB001401E7 /* sqSqueakIPhoneClipboardAPI.m:31 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 31; location = Squeak; modificationTime = 308445394.104406; originalNumberOfMultipleMatches = 1; state = 1; }; 9458528110F045FC001401E7 /* sqSqueakIPhoneClipboardAPI.m:24 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 24; location = Squeak; modificationTime = 308445394.164388; originalNumberOfMultipleMatches = 1; state = 1; }; 9458528310F045FD001401E7 /* sqSqueakIPhoneClipboardAPI.m:17 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; hitCount = 0; ignoreCount = 0; lineNumber = 17; location = Squeak; modificationTime = 308445394.211606; originalNumberOfMultipleMatches = 1; state = 1; }; 945BA53B10B218F700C2020C /* math.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = math.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/architecture/i386/math.h; sourceTree = "<absolute>"; }; 945C4D7C10BB0A8500548CC1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945C4D7D10BB0A8500548CC1 /* OSTypes.h */; name = "OSTypes.h: 73"; rLen = 35; rLoc = 2233; rType = 0; vrLen = 1245; vrLoc = 1528; }; 945C4D7D10BB0A8500548CC1 /* OSTypes.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OSTypes.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/libkern/OSTypes.h; sourceTree = "<absolute>"; }; 945C4EAC10BB348300548CC1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAAE810AB6C3500F87527 /* NSFileManager.h */; name = "NSFileManager.h: 162"; rLen = 14; rLoc = 11455; rType = 0; vrLen = 4578; vrLoc = 9506; }; 945E9D7C0DE525E100CDF01E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945E9D7D0DE525E100CDF01E /* npsqueak.c */; name = "npsqueak.c: 1113"; rLen = 21; rLoc = 33897; rType = 0; vrLen = 2274; vrLoc = 32164; }; 945E9D7D0DE525E100CDF01E /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak/npsqueak.c"; sourceTree = "<absolute>"; }; 945F30620E0C6A5000CFF3DC /* SqueakApplication.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakApplication.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/SqueakApplication.m"; sourceTree = "<absolute>"; }; 945F30670E0C6A5000CFF3DC /* SqueakInterpreter.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreter.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreter.m"; sourceTree = "<absolute>"; }; 945F30FC0E0C763800CFF3DC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945F30670E0C6A5000CFF3DC /* SqueakInterpreter.m */; name = "SqueakInterpreter.m: 200"; rLen = 13; rLoc = 5497; rType = 0; vrLen = 1593; vrLoc = 2040; }; 94638B260EAFB77B00A3F155 /* iPhone.changes */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 1.75974e+06}}"; sepNavSelRange = "{5549550, 0}"; sepNavVisRange = "{6141, 671}"; }; }; 94638CEA0EB16F1100A3F155 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638CEB0EB16F1100A3F155 /* unxMapMemory.h */; name = "unxMapMemory.h: 270"; rLen = 6; rLoc = 8341; rType = 0; vrLen = 1425; vrLoc = 0; }; 94638CEB0EB16F1100A3F155 /* unxMapMemory.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = unxMapMemory.h; path = "/Users/johnmci/Work In Progress/cincom/VWSourceCode/bkup621/src-51.4/plat/unxMapMemory.h"; sourceTree = "<absolute>"; }; 94638CF50EB16F1100A3F155 /* sqUnixMemory.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMemory.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqUnixMemory.c; sourceTree = "<absolute>"; }; 9463943D0E95845000015851 /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1219, 2646}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1036}"; }; }; 9463943E0E95845000015851 /* squeakSUnitTester.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6762}}"; sepNavSelRange = "{4085, 11}"; sepNavVisRange = "{3547, 944}"; }; }; 9468DA7511EC31F6000ECA16 /* main time.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "main time.c"; path = "/Users/johnmci/Documents/temp/time_foobar/main time.c"; sourceTree = "<absolute>"; }; 946C240C1230A80A004938A1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */; name = "sqSqueakAppDelegate.h: 55"; rLen = 12; rLoc = 2271; rType = 0; vrLen = 2324; vrLoc = 0; }; 946D973B0FE165B70038846B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946D973C0FE165B70038846B /* sqSqueakEventsAPI.m */; name = "sqSqueakEventsAPI.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 989; vrLoc = 2044; }; 946D973C0FE165B70038846B /* sqSqueakEventsAPI.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqSqueakEventsAPI.m; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/platforms/Mac OSObjC/vm/Common/Classes/sqSqueakEventsAPI.m"; sourceTree = "<absolute>"; }; 946DA77210C09A8C00F26F56 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakPrintJobPlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 946DA7D710C0A6C700F26F56 /* NSWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindow.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h; sourceTree = "<absolute>"; }; 946DA7E010C0A7A400F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA7E110C0A7A400F26F56 /* NSView.h */; name = "NSView.h: 327"; rLen = 23; rLoc = 10791; rType = 0; vrLen = 2404; vrLoc = 9657; }; 946DA7E110C0A7A400F26F56 /* NSView.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSView.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSView.h; sourceTree = "<absolute>"; }; 946DA8D210C0C30D00F26F56 /* DropPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2496}}"; sepNavSelRange = "{2324, 0}"; sepNavVisRange = "{1835, 1278}"; sepNavWindowFrame = "{{254, 4}, {1426, 1019}}"; }; }; 946DA8D910C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA7D710C0A6C700F26F56 /* NSWindow.h */; name = "NSWindow.h: 580"; rLen = 23; rLoc = 22568; rType = 0; vrLen = 2638; vrLoc = 21350; }; 946DA8DA10C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA77210C09A8C00F26F56 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2093"; rLen = 0; rLoc = 54353; rType = 0; vrLen = 1177; vrLoc = 53870; }; 946DA8DB10C0C32800F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DA8DC10C0C32800F26F56 /* NSDragging.h */; name = "NSDragging.h: 56"; rLen = 64; rLoc = 1665; rType = 0; vrLen = 2094; vrLoc = 0; }; 946DA8DC10C0C32800F26F56 /* NSDragging.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDragging.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSDragging.h; sourceTree = "<absolute>"; }; 946DA8EF10C0C38600F26F56 /* DropPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 169}}"; sepNavSelRange = "{300, 21}"; sepNavVisRange = "{0, 490}"; }; }; 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 507}}"; sepNavSelRange = "{7, 20}"; sepNavVisRange = "{0, 400}"; }; }; 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1027}}"; sepNavSelRange = "{2218, 8}"; sepNavVisRange = "{1320, 1285}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 4056}}"; sepNavSelRange = "{2314, 23}"; sepNavVisRange = "{1497, 1319}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 946DAA3810C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3910C0D8B700F26F56 /* sqUnixMain.c */; name = "sqUnixMain.c: 709"; rLen = 12; rLoc = 18115; rType = 0; vrLen = 1874; vrLoc = 17010; }; 946DAA3910C0D8B700F26F56 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakExuperyPlugin/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 946DAA3A10C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3B10C0D8B700F26F56 /* sqMacMain.c */; name = "sqMacMain.c: 473"; rLen = 13; rLoc = 17090; rType = 0; vrLen = 2581; vrLoc = 14967; }; 946DAA3B10C0D8B700F26F56 /* sqMacMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacMain.c; path = "/Users/johnmci/Documents/SqueakExuperyPlugin/platforms/Mac OS/vm/sqMacMain.c"; sourceTree = "<absolute>"; }; 946DAA3C10C0D8B700F26F56 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 946DAA3D10C0D8B700F26F56 /* sqUnixExternalPrims.c */; name = "sqUnixExternalPrims.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1365; vrLoc = 4834; }; 946DAA3D10C0D8B700F26F56 /* sqUnixExternalPrims.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixExternalPrims.c; path = "/Users/johnmci/Documents/SqueakHydraZBaseCheck/HydraVM-src/platforms/unix/vm/sqUnixExternalPrims.c"; sourceTree = "<absolute>"; }; 94700A50123DF62D00874318 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */; name = "sqSqueakIPhoneApplication.m: 43"; rLen = 12; rLoc = 1918; rType = 0; vrLen = 1878; vrLoc = 1325; }; 94700A51123DF62D00874318 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */; name = "sqSqueakIPhoneApplication+attributes.m: 102"; rLen = 0; rLoc = 4729; rType = 0; vrLen = 2560; vrLoc = 2120; }; 94700AAD123DFCEA00874318 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */; name = "SqueakNoOGLIPhoneAppDelegate.h: 60"; rLen = 12; rLoc = 3089; rType = 0; vrLen = 2653; vrLoc = 656; }; 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1299, 988}}"; sepNavSelRange = "{1903, 56}"; sepNavVisRange = "{446, 2520}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1496, 2678}}"; sepNavSelRange = "{3533, 13}"; sepNavVisRange = "{2713, 1763}"; sepNavWindowFrame = "{{496, 9}, {1131, 1019}}"; }; }; 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1331, 896}}"; sepNavSelRange = "{2271, 12}"; sepNavVisRange = "{0, 2324}"; sepNavWindowFrame = "{{15, 4}, {1378, 1024}}"; }; }; 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1482}}"; sepNavSelRange = "{2932, 32}"; sepNavVisRange = "{2325, 1128}"; sepNavWindowFrame = "{{264, 7}, {1416, 1021}}"; }; }; 947332EE0EA70E8C003F9084 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947332EF0EA70E8C003F9084 /* sqWin32Stubs.c */; name = "sqWin32Stubs.c: 18"; rLen = 18; rLoc = 607; rType = 0; vrLen = 2348; vrLoc = 0; }; 947332EF0EA70E8C003F9084 /* sqWin32Stubs.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Stubs.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/sqWin32Stubs.c; sourceTree = "<absolute>"; }; 9473A34810BBD84100ED7D00 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCACE310AB8AE300F87527 /* NSObject.h */; name = "NSObject.h: 74"; rLen = 3; rLoc = 1310; rType = 0; vrLen = 1170; vrLoc = 936; }; 9473A95A1102F70B00D135CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942F6FFC1102F5A300A0A349 /* NSNull.h */; name = "NSNull.h: 9"; rLen = 0; rLoc = 159; rType = 0; vrLen = 184; vrLoc = 0; }; 9473A9701103BE0A00D135CB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942CF43710BFCD52008F9BB7 /* sqGnu.h */; name = "sqGnu.h: 187"; rLen = 0; rLoc = 11295; rType = 0; vrLen = 2361; vrLoc = 9051; }; 9475A83511E6B5D50010FB38 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9478E02B0EC8D957007096A7 /* squeakSUnitTester.m */; name = "squeakSUnitTester.m: 126"; rLen = 19; rLoc = 3571; rType = 0; vrLen = 843; vrLoc = 2970; }; 9475F4DB10BEF4100047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E4936F10BD39E20011AC75 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2177"; rLen = 0; rLoc = 56455; rType = 0; vrLen = 1151; vrLoc = 55829; }; 9475F56B10BF20A00047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9475F56C10BF20A00047A24B /* AudioQueue.h */; name = "AudioQueue.h: 1116"; rLen = 66; rLoc = 56155; rType = 0; vrLen = 2628; vrLoc = 54742; }; 9475F56C10BF20A00047A24B /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 9475F58210BF227D0047A24B /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 9475F5A710BF25A10047A24B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9475F58210BF227D0047A24B /* NSApplication.h */; name = "NSApplication.h: 18"; rLen = 21; rLoc = 470; rType = 0; vrLen = 1966; vrLoc = 0; }; 947713C410C45DD700890A9B /* NSDebug.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDebug.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDebug.h; sourceTree = "<absolute>"; }; 947713D410C45E5F00890A9B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947713C410C45DD700890A9B /* NSDebug.h */; name = "NSDebug.h: 53"; rLen = 36; rLoc = 2244; rType = 0; vrLen = 2334; vrLoc = 74; }; 9478E0250EC8D957007096A7 /* dummyFFI.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2652}}"; sepNavSelRange = "{3356, 8}"; sepNavVisRange = "{2987, 642}"; }; }; 9478E0260EC8D957007096A7 /* dummyFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {899, 548}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1760}"; sepNavWindowFrame = "{{15, 166}, {1288, 857}}"; }; }; 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {964, 2535}}"; sepNavSelRange = "{1808, 17}"; sepNavVisRange = "{0, 2274}"; }; }; 9478E02B0EC8D957007096A7 /* squeakSUnitTester.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1327, 6136}}"; sepNavSelRange = "{3608, 0}"; sepNavVisRange = "{2696, 1348}"; }; }; 9478E0320EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 720}}"; sepNavSelRange = "{103, 1666}"; sepNavVisRange = "{0, 1809}"; }; }; 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 1157}}"; sepNavSelRange = "{2223, 98}"; sepNavVisRange = "{1767, 2249}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 9478E05E0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1062, 1404}}"; sepNavSelRange = "{2883, 135}"; sepNavVisRange = "{1833, 2636}"; sepNavWindowFrame = "{{52, 4}, {997, 998}}"; }; }; 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1540, 5941}}"; sepNavSelRange = "{11445, 29}"; sepNavVisRange = "{10202, 2807}"; sepNavWindowFrame = "{{38, 4}, {1587, 998}}"; }; }; 9478E13D0EC8EB46007096A7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9478E13E0EC8EB46007096A7 /* AudioQueue.h */; name = "AudioQueue.h: 2"; rLen = 10; rLoc = 19; rType = 0; vrLen = 1351; vrLoc = 0; }; 9478E13E0EC8EB46007096A7 /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 947923FE1102BE53007C87F8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947923FF1102BE53007C87F8 /* sqUnixMain.c */; name = "sqUnixMain.c: 176"; rLen = 281; rLoc = 5149; rType = 0; vrLen = 1173; vrLoc = 4547; }; 947923FF1102BE53007C87F8 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Volumes/px2/business/SqueakiPhone/archivesOLDSTUFF/platformsOLDDrawing/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 947E20F50EB281C5007957D0 /* SqueakFFIPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 37440}}"; sepNavSelRange = "{75408, 0}"; sepNavVisRange = "{75315, 897}"; sepNavWindowFrame = "{{15, 4}, {1385, 1024}}"; }; }; 947E20F90EB2826C007957D0 /* sqFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2210}}"; sepNavSelRange = "{2071, 8}"; sepNavVisRange = "{1307, 1682}"; }; }; 947E210C0EB28486007957D0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94638CF50EB16F1100A3F155 /* sqUnixMemory.c */; name = "sqUnixMemory.c: 214"; rLen = 6; rLoc = 6843; rType = 0; vrLen = 1296; vrLoc = 6040; }; 947E21310EB2868A007957D0 /* dummyFFI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 494}}"; sepNavSelRange = "{87, 0}"; sepNavVisRange = "{0, 1201}"; }; }; 947E21320EB2868A007957D0 /* dummyFFI.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2587}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 891}"; }; }; 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 277}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 149}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {972, 7812}}"; sepNavSelRange = "{13195, 0}"; sepNavVisRect = "{{0, 7107}, {972, 697}}"; sepNavWindowFrame = "{{15, 18}, {1170, 1005}}"; }; }; 947E61D610AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61D710AA049300D3B69E /* Availability.h */; name = "Availability.h: 124"; rLen = 11; rLoc = 5703; rType = 0; vrLen = 2202; vrLoc = 4378; }; 947E61D710AA049300D3B69E /* Availability.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Availability.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/Availability.h; sourceTree = "<absolute>"; }; 947E61DA10AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61DB10AA049300D3B69E /* AudioFileStream.h */; name = "AudioFileStream.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 805; vrLoc = 0; }; 947E61DB10AA049300D3B69E /* AudioFileStream.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioFileStream.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioFileStream.h; sourceTree = "<absolute>"; }; 947E61DC10AA049300D3B69E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E61DD10AA049300D3B69E /* AudioFormat.h */; name = "AudioFormat.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 779; vrLoc = 0; }; 947E61DD10AA049300D3B69E /* AudioFormat.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioFormat.h; path = /System/Library/Frameworks/AudioToolbox.framework/Headers/AudioFormat.h; sourceTree = "<absolute>"; }; 947E626F10AA098300D3B69E /* SqueakPureObjc */ = { activeExec = 0; executables = ( 947E62FD10AA098300D3B69E /* SqueakPureObjc */, ); }; 947E62FD10AA098300D3B69E /* SqueakPureObjc */ = { isa = PBXExecutable; activeArgIndices = ( NO, NO, NO, NO, NO, ); argumentStrings = ( "-memory 52m", "-help", bork.image, 232, 242, ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( { active = NO; name = NSAutoreleaseHaltOnFreedObject; value = YES; }, { active = NO; name = NSDebugEnabled; value = YES; }, { active = NO; name = NSAutoreleaseFreedObjectCheckEnabled; value = YES; }, { active = NO; name = NSZombieEnabled; value = YES; }, { active = NO; name = DYLD_INSERT_LIBRARIES; value = /usr/lib/libMallocDebug.A.dylib; }, { active = NO; name = MallocPreScribble; value = YES; }, { active = NO; name = MallocScribble; value = YES; }, { active = NO; name = MallocGuardEdges; value = YES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = SqueakPureObjc; savedGlobals = { }; showTypeColumn = 0; sourceDirectories = ( ); variableFormatDictionary = { $cs = 1; $ds = 1; $eflags = 1; $es = 1; $fs = 1; $gs = 1; $r10 = 1; $r11 = 1; $r12 = 1; $r13 = 1; $r14 = 1; $r15 = 1; $r8 = 1; $r9 = 1; $rax = 1; $rbp = 1; $rbx = 1; $rcx = 1; $rdi = 1; $rdx = 1; $rip = 1; $rsi = 1; $rsp = 1; $ss = 1; "*from-short unsigned int-copyImage16To32" = 3; "_return_value-sqInt-primitiveGetMenuHandle" = 1; "actually-void *-sqAllocateMemoryMac" = 2; "b-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "bits-NSInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; "currentVMEncoding-NSInteger-\U0001\U0000-[sqSqueakMainApplication(attributes) getAttribute:]" = 1; "endAddr-long unsigned int-sqMakeMemoryNotExecutableFromTo" = 1; "firstPage-long unsigned int-sqMakeMemoryNotExecutableFromTo" = 1; "g-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "inCommandID-MenuCommand-GetIndMenuItemWithCommandID" = 5; "inputCommandID-OSType-GetIndMenuItemWithCommandID" = 5; "keyBoardModifiers-NSUInteger--[sqSqueakOSXApplication(events) translateCocoaModifiersToCarbonModifiers:]" = 3; "mask-NSInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; memory = 1; "modifierFlags-NSUInteger--[sqSqueakOSXNSView doCommandBySelector:]" = 3; "modifierFlags-NSUInteger--[sqSqueakOSXNSView fakeKeyDownUp:]" = 1; "oop-usqInt-pointerForOop" = 1; "oop-usqInt-sweepPhase" = 2; "ptr-char *-longAtPointerput" = 2; "r-unsigned char--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "rgb-short int--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "rgb-short unsigned int--[sqSqueakOSXNSView(BitmapConversion) extractPixels_16_to_32:srcPixelWidth:left:right:top:bottom:position:]" = 3; "shift-NSUInteger-\U0001\U0000-[sqSqueakOSXApplication(cursor) setCursor:withMask:offsetX:offsetY:]" = 3; "squeakModifiers-int--[sqSqueakOSXApplication(events) translateCocoaModifiersToSqueakModifiers:]" = 3; "startAddr-long unsigned int-sqMakeMemoryNotExecutableFromTo" = 1; "to1-int-copyImage16To32" = 3; "to2-int-copyImage16To32" = 1; }; }; 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 756}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1518}"; }; }; 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {802, 780}}"; sepNavSelRange = "{1504, 0}"; sepNavVisRange = "{492, 1556}"; }; }; 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {970, 850}}"; sepNavSelRange = "{2101, 17}"; sepNavVisRange = "{0, 2472}"; sepNavWindowFrame = "{{522, 48}, {1017, 978}}"; }; }; 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 2431}}"; sepNavSelRange = "{6384, 120}"; sepNavVisRange = "{5242, 1273}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1379, 891}}"; sepNavSelRange = "{2392, 0}"; sepNavVisRange = "{0, 2397}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 3315}}"; sepNavSelRange = "{3879, 23}"; sepNavVisRange = "{3183, 1249}"; sepNavWindowFrame = "{{522, 48}, {1017, 978}}"; }; }; 947E9920125D73FD0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94210B280E956AC200C1A314 /* ObjectiveCPlugin.c */; name = "ObjectiveCPlugin.c: 1915"; rLen = 9; rLoc = 53186; rType = 0; vrLen = 1628; vrLoc = 52405; }; 947E9964125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B8F54E10CF677800F0DD6B /* SqViewClut.h */; name = "SqViewClut.h: 1"; rLen = 12; rLoc = 3; rType = 0; vrLen = 254; vrLoc = 0; }; 947E9967125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E9968125D756D0048E783 /* renderer.cpp */; name = "renderer.cpp: 58"; rLen = 16; rLoc = 2694; rType = 0; vrLen = 1974; vrLoc = 1631; }; 947E9968125D756D0048E783 /* renderer.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = renderer.cpp; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/ConditionalRendering/renderer.cpp"; sourceTree = "<absolute>"; }; 947E9969125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E996A125D756D0048E783 /* EAGLView.m */; name = "EAGLView.m: 277"; rLen = 7; rLoc = 7216; rType = 0; vrLen = 1635; vrLoc = 6438; }; 947E996A125D756D0048E783 /* EAGLView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = EAGLView.m; path = /Users/johnmci/Shared/RayPicking/Classes/EAGLView.m; sourceTree = "<absolute>"; }; 947E996B125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E996C125D756D0048E783 /* ES1Renderer.m */; name = "ES1Renderer.m: 155"; rLen = 7; rLoc = 4891; rType = 0; vrLen = 2162; vrLoc = 4012; }; 947E996C125D756D0048E783 /* ES1Renderer.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ES1Renderer.m; path = /Users/johnmci/Shared/CubeExample/Classes/ES1Renderer.m; sourceTree = "<absolute>"; }; 947E996D125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E996E125D756D0048E783 /* OpenGLRenderer.m */; name = "OpenGLRenderer.m: 55"; rLen = 7; rLoc = 2620; rType = 0; vrLen = 2657; vrLoc = 0; }; 947E996E125D756D0048E783 /* OpenGLRenderer.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OpenGLRenderer.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/Mac/GLEssentials/Classes/OpenGLRenderer.m"; sourceTree = "<absolute>"; }; 947E996F125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E9970125D756D0048E783 /* OpenGLRenderer.m */; name = "OpenGLRenderer.m: 55"; rLen = 7; rLoc = 2620; rType = 0; vrLen = 2657; vrLoc = 0; }; 947E9970125D756D0048E783 /* OpenGLRenderer.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OpenGLRenderer.m; path = "/Volumes/330GB Photos/WWDC10-SampleCode/iOS/GLEssentials/Classes/OpenGLRenderer.m"; sourceTree = "<absolute>"; }; 947E9971125D756D0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E9972125D756D0048E783 /* PVRTexture.m */; name = "PVRTexture.m: 206"; rLen = 7; rLoc = 6278; rType = 0; vrLen = 1238; vrLoc = 5527; }; 947E9972125D756D0048E783 /* PVRTexture.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PVRTexture.m; path = /Users/johnmci/Shared/CubeExample/Classes/PVRTexture.m; sourceTree = "<absolute>"; }; 947E9976125D756D0048E783 /* Shader.mm */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = Shader.mm; path = "/Volumes/330GB Photos/temp/oolongengine-read-only/Oolong Engine2/Renderer/Core/GraphicsDevice/Shader.mm"; sourceTree = "<absolute>"; }; 947E9994125D76820048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E9976125D756D0048E783 /* Shader.mm */; name = "Shader.mm: 207"; rLen = 7; rLoc = 7361; rType = 0; vrLen = 1797; vrLoc = 6302; }; 947E99A0125D76BB0048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E99A1125D76BB0048E783 /* CGLMacro.h */; name = "CGLMacro.h: 34"; rLen = 8; rLoc = 1128; rType = 0; vrLen = 2254; vrLoc = 12519; }; 947E99A1125D76BB0048E783 /* CGLMacro.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGLMacro.h; path = "/Volumes/330GB Photos/Developer42/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/CGLMacro.h"; sourceTree = "<absolute>"; }; 947E99CB125D78FB0048E783 /* NSLOG */ = { isa = PBXSymbolicBreakpoint; actions = ( ); breakpointStyle = 1; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; hitCount = 0; ignoreCount = 0; location = ""; modificationTime = 308445393.439781; originalNumberOfMultipleMatches = 1; state = 0; symbolName = NSLOG; }; 947E99CC125D78FE0048E783 /* NSlog */ = { isa = PBXSymbolicBreakpoint; actions = ( ); breakpointStyle = 1; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; hitCount = 0; ignoreCount = 0; location = ""; modificationTime = 308445393.4398431; originalNumberOfMultipleMatches = 1; state = 0; symbolName = NSlog; }; 947E99D0125D79050048E783 /* NSLog */ = { isa = PBXSymbolicBreakpoint; actions = ( ); breakpointStyle = 1; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; hitCount = 0; ignoreCount = 0; location = Foundation; modificationTime = 308445393.439915; originalNumberOfMultipleMatches = 1; state = 2; symbolName = NSLog; }; 947E99F8125D7B1C0048E783 /* cl */ = { isa = PBXSymbolicBreakpoint; actions = ( ); breakpointStyle = 1; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; hitCount = 0; ignoreCount = 0; location = ""; modificationTime = 308445393.43997; originalNumberOfMultipleMatches = 1; state = 0; symbolName = cl; }; 947E99FA125D7B850048E783 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */; name = "sqSqueakOSXNSView.h: 79"; rLen = 6; rLoc = 3309; rType = 0; vrLen = 1954; vrLoc = 1747; }; 948034A9122A264A00C42504 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948034AA122A264A00C42504 /* sqWin32Window.c */; name = "sqWin32Window.c: 1856"; rLen = 17; rLoc = 59293; rType = 0; vrLen = 1429; vrLoc = 53896; }; 948034AA122A264A00C42504 /* sqWin32Window.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqWin32Window.c; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/win32/vm/sqWin32Window.c; sourceTree = "<absolute>"; }; 948127E812444F7800BD1543 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; name = "SqueakUIView.m: 65"; rLen = 13; rLoc = 2580; rType = 0; vrLen = 1684; vrLoc = 2490; }; 948127E912444F7800BD1543 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */; name = "sqiPhoneScreenAndWindow.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2225; vrLoc = 0; }; 948127EA12444F7800BD1543 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */; name = "SqueakUIView.h: 40"; rLen = 218; rLoc = 1791; rType = 0; vrLen = 2259; vrLoc = 0; }; 948127EB12444F7800BD1543 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */; name = "SqueakUIController.h: 6"; rLen = 1688; rLoc = 95; rType = 0; vrLen = 1839; vrLoc = 0; }; 94845C211228E29F00BEB880 /* macvideo.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = macvideo.cpp; path = /opt/intel/Compiler/11.1/076/Frameworks/tbb/examples/common/gui/macvideo.cpp; sourceTree = "<absolute>"; }; 9484F7B910B0D3600038BDC0 /* SystemConfiguration.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemConfiguration.h; path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/Headers/SystemConfiguration.h; sourceTree = "<absolute>"; }; 9484F86210B0DCC60038BDC0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9484F7B910B0D3600038BDC0 /* SystemConfiguration.h */; name = "SystemConfiguration.h: 109"; rLen = 30; rLoc = 4596; rType = 0; vrLen = 1985; vrLoc = 3539; }; 9484F86510B0DCC60038BDC0 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9484F86610B0DCC60038BDC0 /* ABGlobals.h */; name = "ABGlobals.h: 162"; rLen = 6; rLoc = 6912; rType = 0; vrLen = 2845; vrLoc = 5737; }; 9484F86610B0DCC60038BDC0 /* ABGlobals.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ABGlobals.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AddressBook.framework/Versions/A/Headers/ABGlobals.h; sourceTree = "<absolute>"; }; 9484F8FC10B0E1770038BDC0 /* PBXBookmark */ = { isa = PBXBookmark; fRef = 945550910DF2041100FB176B /* Default.png */; }; 94862F8310BA182500CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3696610AFB7550041953A /* NSBitmapImageRep.h */; name = "NSBitmapImageRep.h: 100"; rLen = 24; rLoc = 4439; rType = 0; vrLen = 3020; vrLoc = 3019; }; 94862F9E10BA1A0100CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAD0410AB922600F87527 /* NSObjCRuntime.h */; name = "NSObjCRuntime.h: 193"; rLen = 5; rLoc = 6827; rType = 0; vrLen = 1591; vrLoc = 6049; }; 9486302A10BA247200CAA2EB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3696310AFB7550041953A /* NSGraphics.h */; name = "NSGraphics.h: 92"; rLen = 159; rLoc = 2874; rType = 0; vrLen = 3496; vrLoc = 1601; }; 948704AE0E12CABF00D565C3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948704AF0E12CABF00D565C3 /* BitBlt.java */; name = "BitBlt.java: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1739; vrLoc = 0; }; 948704AF0E12CABF00D565C3 /* BitBlt.java */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.java; name = BitBlt.java; path = /Users/johnmci/Shared/JSqueak/BitBlt.java; sourceTree = "<absolute>"; }; 9487071F0E132B1000D565C3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948707200E132B1000D565C3 /* sqGnu.h */; name = "sqGnu.h: 3"; rLen = 1318; rLoc = 43; rType = 0; vrLen = 1999; vrLoc = 0; }; 948707200E132B1000D565C3 /* sqGnu.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqGnu.h; sourceTree = "<absolute>"; }; 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {957, 28496}}"; sepNavSelRange = "{56411, 0}"; sepNavVisRange = "{6842, 1375}"; sepNavWindowFrame = "{{38, 14}, {799, 988}}"; }; }; 948C0820112DE98D0017EE7F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948C0821112DE98D0017EE7F /* interp.c */; name = "interp.c: 4824"; rLen = 58; rLoc = 159330; rType = 0; vrLen = 1795; vrLoc = 158125; }; 948C0821112DE98D0017EE7F /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/src/vm/interp.c; sourceTree = "<absolute>"; }; 948FAA0310BF855500BE88CF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 948FAA0410BF855500BE88CF /* string.h */; name = "string.h: 85"; rLen = 35; rLoc = 3458; rType = 0; vrLen = 2317; vrLoc = 3588; }; 948FAA0410BF855500BE88CF /* string.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = string.h; path = /Developer/SDKs/MacOSX10.5.sdk/usr/include/string.h; sourceTree = "<absolute>"; }; 948FAB5B10BFAD3C00BE88CF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5838E10BF3E080073FD63 /* AudioQueue.h */; name = "AudioQueue.h: 695"; rLen = 0; rLoc = 34190; rType = 0; vrLen = 3087; vrLoc = 33171; }; 949198B010BC8DFC00C629D1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88C0E10AF4196007CB39E /* NSGeometry.h */; name = "NSGeometry.h: 100"; rLen = 74; rLoc = 2081; rType = 0; vrLen = 1067; vrLoc = 1388; }; 949198C910BC8FBB00C629D1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9456C2F910B32D2A000BF3DE /* NSString.h */; name = "NSString.h: 103"; rLen = 7; rLoc = 4785; rType = 0; vrLen = 3169; vrLoc = 3123; }; 9492450510BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492450610BA42EF00E726F5 /* SqueakApplication.h */; name = "SqueakApplication.h: 12"; rLen = 17; rLoc = 192; rType = 0; vrLen = 237; vrLoc = 0; }; 9492450610BA42EF00E726F5 /* SqueakApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakApplication.h; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/SqueakApplication.h"; sourceTree = "<absolute>"; }; 9492450710BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492450810BA42EF00E726F5 /* SqueakApplication.m */; name = "SqueakApplication.m: 2"; rLen = 17; rLoc = 7; rType = 0; vrLen = 1109; vrLoc = 0; }; 9492450810BA42EF00E726F5 /* SqueakApplication.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakApplication.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/SqueakApplication.m"; sourceTree = "<absolute>"; }; 9492450910BA42EF00E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945F30620E0C6A5000CFF3DC /* SqueakApplication.m */; name = "SqueakApplication.m: 12"; rLen = 611; rLoc = 185; rType = 0; vrLen = 797; vrLoc = 0; }; 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 674}}"; sepNavSelRange = "{1872, 0}"; sepNavVisRange = "{0, 1877}"; }; }; 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 806}}"; sepNavSelRange = "{2023, 13}"; sepNavVisRange = "{99, 2329}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 9492455D10BA462B00E726F5 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakHydra/SqueakVMMAker/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 949245B210BA4A6200E726F5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492455D10BA462B00E726F5 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1937"; rLen = 17; rLoc = 51207; rType = 0; vrLen = 1549; vrLoc = 51264; }; 9493E98F10EE90BC000C4FB3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94360A8C10E84CC90060221A /* NSException.h */; name = "NSException.h: 67"; rLen = 9; rLoc = 2116; rType = 0; vrLen = 2363; vrLoc = 1177; }; 9494927D11E5178D0019BC29 /* cogit.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1356, 164385}}"; sepNavSelRange = "{325, 38}"; sepNavVisRange = "{0, 1577}"; sepNavWindowFrame = "{{15, 18}, {1170, 1005}}"; }; }; 9494927E11E5178D0019BC29 /* cogit.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1559, 1430}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 3035}"; }; }; 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 540995}}"; sepNavSelRange = "{1165452, 40}"; sepNavVisRange = "{1164453, 1395}"; sepNavWindowFrame = "{{295, 4}, {1385, 1024}}"; }; }; 9494928111E5178D0019BC29 /* cointerp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 2275}}"; sepNavSelRange = "{3374, 7}"; sepNavVisRange = "{2366, 2130}"; }; }; 949492C011E51C6B0019BC29 /* dispdbg.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 1781}}"; sepNavSelRange = "{306, 11}"; sepNavVisRange = "{269, 1550}"; }; }; 949492C111E51C6B0019BC29 /* sqAssert.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 644}}"; sepNavSelRange = "{505, 6}"; sepNavVisRange = "{0, 1133}"; sepNavWindowFrame = "{{15, 24}, {1661, 999}}"; }; }; 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 2925}}"; sepNavSelRange = "{2737, 7}"; sepNavVisRange = "{0, 2031}"; }; }; 949492C411E51C6B0019BC29 /* sqAtomicOps.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 2574}}"; sepNavSelRange = "{2283, 19}"; sepNavVisRange = "{1497, 1558}"; sepNavWindowFrame = "{{107, 4}, {1573, 1024}}"; }; }; 949492C511E51C6B0019BC29 /* sqHeapMap.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1352}}"; sepNavSelRange = "{2420, 27}"; sepNavVisRange = "{1461, 1192}"; }; }; 949492C611E51C6B0019BC29 /* sqTicker.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 3250}}"; sepNavSelRange = "{7347, 0}"; sepNavVisRange = "{6448, 1506}"; sepNavWindowFrame = "{{15, 4}, {1385, 1024}}"; }; }; 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1327, 9100}}"; sepNavSelRange = "{18414, 0}"; sepNavVisRange = "{17993, 851}"; sepNavWindowFrame = "{{966, 4}, {714, 1024}}"; }; }; 9494932D11E527180019BC29 /* sqUnixThreads.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 676}}"; sepNavSelRange = "{428, 13}"; sepNavVisRange = "{0, 1103}"; }; }; 9494932E11E527180019BC29 /* sqUnixVMProfile.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 5252}}"; sepNavSelRange = "{7363, 3}"; sepNavVisRange = "{6688, 1339}"; sepNavWindowFrame = "{{15, 4}, {1573, 1024}}"; }; }; 9494935011E527AB0019BC29 /* sqMemoryFence.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 780}}"; sepNavSelRange = "{2337, 16}"; sepNavVisRange = "{386, 1997}"; sepNavWindowFrame = "{{15, 4}, {1573, 1024}}"; }; }; 949493BF11E52ADE0019BC29 /* aio.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 5330}}"; sepNavSelRange = "{5142, 7}"; sepNavVisRange = "{4481, 1294}"; sepNavWindowFrame = "{{61, 148}, {901, 833}}"; }; }; 94977E7C11EE46BC002BC5E9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949F254D11EC33FA00A34245 /* mach_absolute_time.s */; name = "mach_absolute_time.s: 32"; rLen = 24; rLoc = 1144; rType = 0; vrLen = 1169; vrLoc = 0; }; 949AD14911E542E8006D6BF4 /* SqueakPureObjc-InfoCOG.plist */ = { uiCtxt = { sepNavWindowFrame = "{{15, 20}, {1185, 1003}}"; }; }; 949AD35211E54A81006D6BF4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF660DDCB1EF009912BF /* sqConfig.h */; name = "sqConfig.h: 4"; rLen = 25; rLoc = 88; rType = 0; vrLen = 302; vrLoc = 0; }; 949AD36211E54AAA006D6BF4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF650DDCB1EF009912BF /* config.h */; name = "config.h: 162"; rLen = 0; rLoc = 3660; rType = 0; vrLen = 1112; vrLoc = 3240; }; 949C3A281262C1F700F4EF15 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF5D0DDCB1C7009912BF /* sq.h */; name = "sq.h: 480"; rLen = 35; rLoc = 18266; rType = 0; vrLen = 2307; vrLoc = 17190; }; 949C3A441262C2D200F4EF15 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */; name = "gcc3x-cointerp.c: 40714"; rLen = 0; rLoc = 1213691; rType = 0; vrLen = 1834; vrLoc = 1212988; }; 949C3AFE1262C91300F4EF15 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */; name = "gcc3x-interp.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1341; vrLoc = 50; }; 949C3AFF1262C91300F4EF15 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; rLen = 16; rLoc = 2861; rType = 0; }; 949C3B171262C9C900F4EF15 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; name = "sqMacV2Memory.c: 83"; rLen = 16; rLoc = 2861; rType = 0; vrLen = 1746; vrLoc = 2252; }; 949DDD4811D13F630017F79B /* NSDateFormatter.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDateFormatter.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDateFormatter.h; sourceTree = "<absolute>"; }; 949DDD6D11D141080017F79B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949DDD4811D13F630017F79B /* NSDateFormatter.h */; name = "NSDateFormatter.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2173; vrLoc = 0; }; 949E5B970DE3623B007388E0 /* sqUnixMain.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixMain.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/unix/vm/sqUnixMain.c; sourceTree = "<absolute>"; }; 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 754}}"; sepNavSelRange = "{1791, 218}"; sepNavVisRange = "{0, 2259}"; sepNavWindowFrame = "{{21, 20}, {694, 1008}}"; }; }; 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1202, 2587}}"; sepNavSelRange = "{2580, 13}"; sepNavVisRange = "{2490, 1684}"; sepNavWindowFrame = "{{152, 50}, {1040, 978}}"; }; }; 949EFD7D0FF17FED00F540EB /* ObjectiveCPlugin.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ObjectiveCPlugin.c; path = /Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/WikiWikiServer/src/vm/intplugins/ObjectiveCPlugin/ObjectiveCPlugin.c; sourceTree = "<absolute>"; }; 949F254511EC33FA00A34245 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9468DA7511EC31F6000ECA16 /* main time.c */; name = "main time.c: 10"; rLen = 18; rLoc = 158; rType = 0; vrLen = 1061; vrLoc = 0; }; 949F254611EC33FA00A34245 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949F254711EC33FA00A34245 /* mach_absolute_time.s */; name = "mach_absolute_time.s: 26"; rLen = 18; rLoc = 976; rType = 0; vrLen = 1080; vrLoc = 0; }; 949F254711EC33FA00A34245 /* mach_absolute_time.s */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.asm; name = mach_absolute_time.s; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/Libc/ppc/mach/mach_absolute_time.s"; sourceTree = "<absolute>"; }; 949F254811EC33FA00A34245 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949F254911EC33FA00A34245 /* mach_absolute_time.c */; name = "mach_absolute_time.c: 40"; rLen = 18; rLoc = 1355; rType = 0; vrLen = 1650; vrLoc = 0; }; 949F254911EC33FA00A34245 /* mach_absolute_time.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mach_absolute_time.c; path = "/Users/johnmci/Shared/docs/Computer/Libc-391.2.5/i386/mach/mach_absolute_time.c"; sourceTree = "<absolute>"; }; 949F254D11EC33FA00A34245 /* mach_absolute_time.s */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.asm; name = mach_absolute_time.s; path = "/Users/johnmci/Shared/docs/Computer/Libc-391.2.5/ppc/mach/mach_absolute_time.s"; sourceTree = "<absolute>"; }; 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 654}}"; sepNavSelRange = "{1987, 14}"; sepNavVisRange = "{0, 2027}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 1417}}"; sepNavSelRange = "{4729, 0}"; sepNavVisRange = "{2120, 2560}"; sepNavWindowFrame = "{{812, 34}, {818, 994}}"; }; }; 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {850, 778}}"; sepNavSelRange = "{1898, 31}"; sepNavVisRange = "{0, 1966}"; }; }; 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 793}}"; sepNavSelRange = "{2342, 35}"; sepNavVisRange = "{589, 1890}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1169, 764}}"; sepNavSelRange = "{1779, 0}"; sepNavVisRange = "{0, 1983}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {905, 767}}"; sepNavSelRange = "{1924, 15}"; sepNavVisRange = "{0, 2171}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A0EBB20DE608350071C8B9 /* squeakAudioVideoPipeLineSignalInterface.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = squeakAudioVideoPipeLineSignalInterface.c; path = "/Volumes/pm/Mail Downloads/squeakAudioVideoPipeLineSignalInterface.c"; sourceTree = "<absolute>"; }; 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 598}}"; sepNavSelRange = "{2009, 11}"; sepNavVisRange = "{3, 2024}"; sepNavWindowFrame = "{{312, -14}, {1416, 1021}}"; }; }; 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1053}}"; sepNavSelRange = "{1907, 2}"; sepNavVisRange = "{841, 1729}"; sepNavWindowFrame = "{{437, 4}, {847, 985}}"; }; }; 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {854, 738}}"; sepNavSelRange = "{7, 16}"; sepNavVisRange = "{0, 1798}"; sepNavWindowFrame = "{{15, 15}, {694, 1008}}"; }; }; 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 676}}"; sepNavSelRange = "{1926, 6}"; sepNavVisRange = "{252, 1760}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1878, 6}"; sepNavVisRange = "{0, 1891}"; sepNavWindowFrame = "{{38, 145}, {1288, 857}}"; }; }; 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 559}}"; sepNavSelRange = "{868, 1033}"; sepNavVisRange = "{3, 1898}"; }; }; 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 859}}"; sepNavSelRange = "{1866, 25}"; sepNavVisRange = "{0, 2034}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 723}}"; sepNavSelRange = "{1867, 0}"; sepNavVisRange = "{0, 1908}"; }; }; 94A1B2AA10B9E92A00C64473 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B2AB10B9E92A00C64473 /* NSCache.h */; name = "NSCache.h: 25"; rLen = 52; rLoc = 427; rType = 0; vrLen = 1024; vrLoc = 0; }; 94A1B2AB10B9E92A00C64473 /* NSCache.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCache.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSCache.h; sourceTree = "<absolute>"; }; 94A1B41E10BA05E600C64473 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B41F10BA05E600C64473 /* objc.h */; name = "objc.h: 64"; rLen = 46; rLoc = 1748; rType = 0; vrLen = 1238; vrLoc = 1195; }; 94A1B41F10BA05E600C64473 /* objc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = objc.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/objc/objc.h; sourceTree = "<absolute>"; }; 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1169, 764}}"; sepNavSelRange = "{78, 0}"; sepNavVisRange = "{0, 1806}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1048, 1872}}"; sepNavSelRange = "{3724, 21}"; sepNavVisRange = "{2363, 1770}"; sepNavWindowFrame = "{{21, 20}, {694, 1008}}"; }; }; 94A349B50DDCDBE200D1D4A9 /* iPhone.image */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {807273, 3.9741e+06}}"; sepNavSelRange = "{18277000, 0}"; sepNavVisRange = "{1158, 1564}"; }; }; 94AB2E6A0E003879006A79E4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AB2E6B0E003879006A79E4 /* npsqueak.c */; name = "npsqueak.c: 984"; rLen = 1; rLoc = 28701; rType = 0; vrLen = 2346; vrLoc = 28415; }; 94AB2E6B0E003879006A79E4 /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak copy 1/npsqueak.c"; sourceTree = "<absolute>"; }; 94AB2E6C0E003879006A79E4 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94AB2E6D0E003879006A79E4 /* npsqueak.c */; name = "npsqueak.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1371; vrLoc = 0; }; 94AB2E6D0E003879006A79E4 /* npsqueak.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = npsqueak.c; path = "/Users/johnmci/Documents/SqueakBrowserPlugin/platforms/Mac OS/vm/npsqueak copy/npsqueak.c"; sourceTree = "<absolute>"; }; 94AC16D512395FE40067037A /* sqSqueakOSXNSView.m:551 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; functionName = "-doCommandBySelector:"; hitCount = 0; ignoreCount = 0; lineNumber = 551; modificationTime = 308445393.4367589; originalNumberOfMultipleMatches = 1; state = 0; }; 94AC16D912395FF10067037A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */; name = "sqSqueakOSXApplication+cursor.m: 90"; rLen = 18; rLoc = 3586; rType = 0; vrLen = 1505; vrLoc = 2779; }; 94AC16DA12395FF10067037A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */; name = "sqSqueakOSXApplication.m: 249"; rLen = 0; rLoc = 7873; rType = 0; vrLen = 1607; vrLoc = 6761; }; 94AC16DC12395FF10067037A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */; name = "sqSqueakOSXScreenAndWindow.m: 70"; rLen = 17; rLoc = 2578; rType = 0; vrLen = 1864; vrLoc = 786; }; 94AC16DE12395FF10067037A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */; name = "SqueakOSXApplication.m: 48"; rLen = 13; rLoc = 2023; rType = 0; vrLen = 2329; vrLoc = 99; }; 94AF3A1F12231A7200691409 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */; name = "sqSqueakMainApplication+events.h: 42"; rLen = 14; rLoc = 1878; rType = 0; vrLen = 2005; vrLoc = 0; }; 94B1514E0DE2CE530059F208 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B1514F0DE2CE530059F208 /* sqMacWindowUniversal.c */; name = "sqMacWindowUniversal.c: 580"; rLen = 14; rLoc = 21540; rType = 0; vrLen = 1552; vrLoc = 21405; }; 94B1514F0DE2CE530059F208 /* sqMacWindowUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacWindowUniversal.c; path = "/Users/johnmci/Documents/SqueakHydra/platforms/Mac OS/vm/sqMacWindowUniversal.c"; sourceTree = "<absolute>"; }; 94B6E9D910BC775E00333E9E /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 807}}"; sepNavSelRange = "{238, 0}"; sepNavVisRange = "{0, 238}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 94B7898910C4F95E005EA70D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94CFE6BD10BE63A900847DF5 /* SqViewEventSensor.m */; name = "SqViewEventSensor.m: 80"; rLen = 22; rLoc = 2119; rType = 0; vrLen = 1922; vrLoc = 499; }; 94B88C540E81500200C98131 /* SqView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqView.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/SqueakAppKit/SqView.m"; sourceTree = "<absolute>"; }; 94B88C560E81500200C98131 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C570E81500200C98131 /* MsgContext.m */; name = "MsgContext.m: 97"; rLen = 26; rLoc = 3007; rType = 0; vrLen = 2255; vrLoc = 4983; }; 94B88C570E81500200C98131 /* MsgContext.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MsgContext.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/MsgContext.m"; sourceTree = "<absolute>"; }; 94B88C640E81500200C98131 /* SqueakObjcBridge.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakObjcBridge.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/Squeak/SqueakObjcBridge.m"; sourceTree = "<absolute>"; }; 94B8F4B910CF5BFF00F0DD6B /* PBXBookmarkGroup */ = { isa = PBXBookmarkGroup; children = ( 94B8F54210CF675200F0DD6B /* PBXBookmark */, ); name = Root; }; 94B8F54210CF675200F0DD6B /* PBXBookmark */ = { isa = PBXBookmark; fRef = 9402DD6F10CE0E91005C2102 /* SqViewClut.m */; }; 94B8F54E10CF677800F0DD6B /* SqViewClut.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {764, 742}}"; sepNavSelRange = "{3, 12}"; sepNavVisRange = "{0, 254}"; }; }; 94B9528510E6B79E00DC476A /* MacMenubarPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3354}}"; sepNavSelRange = "{1194, 0}"; sepNavVisRange = "{1043, 535}"; sepNavWindowFrame = "{{602, 4}, {1078, 1014}}"; }; }; 94B9533310E6BD7100DC476A /* MacMenuOS9ToOSX.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 537}}"; sepNavSelRange = "{201, 0}"; sepNavVisRange = "{0, 201}"; sepNavWindowFrame = "{{554, 14}, {1078, 1014}}"; }; }; 94B9533410E6BD7100DC476A /* MacMenuOS9ToOSX.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 3614}}"; sepNavSelRange = "{5489, 0}"; sepNavVisRange = "{4856, 1272}"; sepNavWindowFrame = "{{15, 9}, {1078, 1014}}"; }; }; 94BCAAE810AB6C3500F87527 /* NSFileManager.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSFileManager.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFileManager.h; sourceTree = "<absolute>"; }; 94BCAB0410AB6DC000F87527 /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {996, 793}}"; sepNavSelRange = "{2017, 0}"; sepNavVisRange = "{0, 2022}"; }; }; 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1227, 1482}}"; sepNavSelRange = "{2641, 19}"; sepNavVisRange = "{2047, 2077}"; sepNavWindowFrame = "{{562, 20}, {1274, 998}}"; }; }; 94BCAC0310AB759300F87527 /* NSURL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSURL.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURL.h; sourceTree = "<absolute>"; }; 94BCAC3710AB79DA00F87527 /* NSArray.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSArray.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSArray.h; sourceTree = "<absolute>"; }; 94BCAC3C10AB79DA00F87527 /* NSDictionary.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDictionary.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDictionary.h; sourceTree = "<absolute>"; }; 94BCAC4E10AB7A2B00F87527 /* NSProcessInfo.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSProcessInfo.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSProcessInfo.h; sourceTree = "<absolute>"; }; 94BCACE310AB8AE300F87527 /* NSObject.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObject.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObject.h; sourceTree = "<absolute>"; }; 94BCAD0410AB922600F87527 /* NSObjCRuntime.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSObjCRuntime.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObjCRuntime.h; sourceTree = "<absolute>"; }; 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 749}}"; sepNavSelRange = "{109, 1692}"; sepNavVisRange = "{0, 1897}"; }; }; 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 2145}}"; sepNavSelRange = "{3001, 3}"; sepNavVisRange = "{2826, 1075}"; sepNavWindowFrame = "{{622, 43}, {1017, 978}}"; }; }; 94BCAD4A10AB981B00F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAC4E10AB7A2B00F87527 /* NSProcessInfo.h */; name = "NSProcessInfo.h: 20"; rLen = 13; rLoc = 437; rType = 0; vrLen = 861; vrLoc = 0; }; 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1066}}"; sepNavSelRange = "{2066, 0}"; sepNavVisRange = "{1327, 2847}"; sepNavWindowFrame = "{{29, 4}, {1326, 1010}}"; }; }; 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 3523}}"; sepNavSelRange = "{2248, 0}"; sepNavVisRange = "{1325, 1573}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94BCAE9010ACA3A300F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE9110ACA3A300F87527 /* NSUserDefaults.h */; name = "NSUserDefaults.h: 13"; rLen = 14; rLoc = 365; rType = 0; vrLen = 2118; vrLoc = 0; }; 94BCAE9110ACA3A300F87527 /* NSUserDefaults.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSUserDefaults.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSUserDefaults.h; sourceTree = "<absolute>"; }; 94BCAE9D10ACA3A300F87527 /* NSBundle.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSBundle.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSBundle.h; sourceTree = "<absolute>"; }; 94BCAEDF10ACAE2500F87527 /* NSValue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSValue.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValue.h; sourceTree = "<absolute>"; }; 94BCAF7D10ACC0D900F87527 /* NSPathUtilities.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSPathUtilities.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSPathUtilities.h; sourceTree = "<absolute>"; }; 94BCAFC410ACC89100F87527 /* string.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = string.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/string.h; sourceTree = "<absolute>"; }; 94BCAFC710ACC89100F87527 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFC810ACC89100F87527 /* CFBundle.h */; name = "CFBundle.h: 113"; rLen = 33; rLoc = 4376; rType = 0; vrLen = 2277; vrLoc = 2928; }; 94BCAFC810ACC89100F87527 /* CFBundle.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFBundle.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFBundle.h; sourceTree = "<absolute>"; }; 94BCAFCA10ACC89100F87527 /* CFURL.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFURL.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFURL.h; sourceTree = "<absolute>"; }; 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1279, 936}}"; sepNavSelRange = "{1980, 27}"; sepNavVisRange = "{50, 2646}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94BCE6870DDDECB800F38F31 /* HostWindowPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 1040}}"; sepNavSelRange = "{970, 21}"; sepNavVisRange = "{0, 2546}"; sepNavWindowFrame = "{{15, 59}, {1394, 964}}"; }; }; 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 633}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 275}"; }; }; 94BCE7A60DDDF8F800F38F31 /* sqaio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {764, 1287}}"; sepNavSelRange = "{4027, 16}"; sepNavVisRange = "{1798, 2290}"; sepNavWindowFrame = "{{84, 127}, {901, 833}}"; }; }; 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 637}}"; sepNavSelRange = "{32, 7}"; sepNavVisRange = "{0, 2199}"; sepNavWindowFrame = "{{73, 45}, {905, 983}}"; }; }; 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {999, 3237}}"; sepNavSelRange = "{2125, 0}"; sepNavVisRange = "{1301, 1753}"; sepNavWindowFrame = "{{310, 45}, {905, 983}}"; }; }; 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 2756}}"; sepNavSelRange = "{2260, 11}"; sepNavVisRange = "{1052, 1911}"; sepNavWindowFrame = "{{775, 4}, {905, 983}}"; }; }; 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {858, 3341}}"; sepNavSelRange = "{2225, 50}"; sepNavVisRange = "{647, 2896}"; sepNavWindowFrame = "{{15, 40}, {905, 983}}"; }; }; 94BD816F11C8A58D00556751 /* sqManualSurface.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1093, 2119}}"; sepNavSelRange = "{360, 20}"; sepNavVisRange = "{0, 2458}"; sepNavWindowFrame = "{{15, 4}, {1140, 1019}}"; }; }; 94BE8B9C123DA0C900C89FDD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */; name = "sqSqueakOSXApplication+attributes.m: 85"; rLen = 0; rLoc = 2975; rType = 0; vrLen = 2556; vrLoc = 2475; }; 94BE8BAD123DA0EB00C89FDD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */; name = "sqSqueakOSXInfoPlistInterface.h: 53"; rLen = 0; rLoc = 2297; rType = 0; vrLen = 2619; vrLoc = 1560; }; 94BE8BD5123DA32300C89FDD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */; name = "sqSqueakOSXInfoPlistInterface.m: 79"; rLen = 0; rLoc = 3185; rType = 0; vrLen = 1921; vrLoc = 2825; }; 94BE8BF5123DA42700C89FDD /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */; name = "sqSqueakOSXApplication+events.m: 186"; rLen = 0; rLoc = 7917; rType = 0; vrLen = 1653; vrLoc = 6896; }; 94C16B42123D72AE00A8622A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */; name = "sqSqueakOSXApplication+clipboard.m: 60"; rLen = 37; rLoc = 2664; rType = 0; vrLen = 2157; vrLoc = 1451; }; 94C16B43123D72AE00A8622A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */; name = "sqSqueakIPhoneApplication+clipboard.m: 24"; rLen = 37; rLoc = 695; rType = 0; vrLen = 1522; vrLoc = 0; }; 94C16B5A123D735F00A8622A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */; name = "sqSqueakMainApplication+vmAndImagePath.m: 87"; rLen = 37; rLoc = 3354; rType = 0; vrLen = 1651; vrLoc = 2190; }; 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1157}}"; sepNavSelRange = "{3309, 6}"; sepNavVisRange = "{1747, 1954}"; sepNavWindowFrame = "{{120, 18}, {1326, 1010}}"; }; }; 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 9997}}"; sepNavSelRange = "{10089, 0}"; sepNavVisRange = "{6392, 2715}"; sepNavWindowFrame = "{{452, 7}, {1076, 1021}}"; }; }; 94C206AA10AF5107002F4160 /* NSImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSImageRep.h; sourceTree = "<absolute>"; }; 94C206D210AF5536002F4160 /* CGImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGImage.h; sourceTree = "<absolute>"; }; 94C206D810AF5536002F4160 /* NSGraphicsContext.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGraphicsContext.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphicsContext.h; sourceTree = "<absolute>"; }; 94C206DA10AF5536002F4160 /* CGContext.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGContext.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGContext.h; sourceTree = "<absolute>"; }; 94C2070610AF5A9E002F4160 /* NSImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSImage.h; sourceTree = "<absolute>"; }; 94C2074310AF5FB7002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206AA10AF5107002F4160 /* NSImageRep.h */; name = "NSImageRep.h: 45"; rLen = 33; rLoc = 1303; rType = 0; vrLen = 1800; vrLoc = 0; }; 94C207E910AF66D7002F4160 /* NSWindow.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSWindow.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h; sourceTree = "<absolute>"; }; 94C2091010AF7413002F4160 /* CIImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIImage.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIImage.h; sourceTree = "<absolute>"; }; 94C2091210AF7413002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2091310AF7413002F4160 /* NSCIImageRep.h */; name = "NSCIImageRep.h: 29"; rLen = 26; rLoc = 776; rType = 0; vrLen = 841; vrLoc = 0; }; 94C2091310AF7413002F4160 /* NSCIImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCIImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSCIImageRep.h; sourceTree = "<absolute>"; }; 94C2092A10AF769A002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2091010AF7413002F4160 /* CIImage.h */; name = "CIImage.h: 98"; rLen = 15; rLoc = 3526; rType = 0; vrLen = 1904; vrLoc = 2714; }; 94C2092D10AF769A002F4160 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206D810AF5536002F4160 /* NSGraphicsContext.h */; name = "NSGraphicsContext.h: 59"; rLen = 39; rLoc = 2654; rType = 0; vrLen = 1997; vrLoc = 2593; }; 94C367C010AF9C0A0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C367C110AF9C0A0041953A /* Aliases.h */; name = "Aliases.h: 286"; rLen = 34; rLoc = 9594; rType = 0; vrLen = 1442; vrLoc = 8779; }; 94C367C110AF9C0A0041953A /* Aliases.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Aliases.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/Aliases.h; sourceTree = "<absolute>"; }; 94C367C210AF9C0A0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C367C310AF9C0A0041953A /* LSInfo.h */; name = "LSInfo.h: 257"; rLen = 22; rLoc = 9965; rType = 0; vrLen = 1369; vrLoc = 9104; }; 94C367C310AF9C0A0041953A /* LSInfo.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LSInfo.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSInfo.h; sourceTree = "<absolute>"; }; 94C367D110AF9C830041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAFCA10ACC89100F87527 /* CFURL.h */; name = "CFURL.h: 636"; rLen = 20; rLoc = 30806; rType = 0; vrLen = 2114; vrLoc = 29706; }; 94C3682410AFA39A0041953A /* macintoshosxextra.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {996, 770}}"; sepNavSelRange = "{192, 0}"; sepNavVisRange = "{0, 192}"; }; }; 94C3682510AFA39A0041953A /* macintoshosxextra.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 572}}"; sepNavSelRange = "{244, 11}"; sepNavVisRange = "{0, 1286}"; sepNavWindowFrame = "{{15, 18}, {1170, 1005}}"; }; }; 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 585}}"; sepNavSelRange = "{1874, 6}"; sepNavVisRange = "{0, 2040}"; sepNavWindowFrame = "{{38, 24}, {1017, 978}}"; }; }; 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 2041}}"; sepNavSelRange = "{3586, 18}"; sepNavVisRange = "{2779, 1505}"; sepNavWindowFrame = "{{299, 9}, {1426, 1019}}"; }; }; 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 616}}"; sepNavSelRange = "{9, 12}"; sepNavVisRange = "{0, 1788}"; }; }; 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 858}}"; sepNavSelRange = "{2250, 19}"; sepNavVisRange = "{640, 2163}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 585}}"; sepNavSelRange = "{1949, 6}"; sepNavVisRange = "{0, 2021}"; }; }; 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 624}}"; sepNavSelRange = "{1961, 6}"; sepNavVisRange = "{62, 1980}"; }; }; 94C368F610AFAEA60041953A /* QuickdrawTypes.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QuickdrawTypes.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/Headers/QuickdrawTypes.h; sourceTree = "<absolute>"; }; 94C368F910AFAEA60041953A /* CFByteOrder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CFByteOrder.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFByteOrder.h; sourceTree = "<absolute>"; }; 94C3696310AFB7550041953A /* NSGraphics.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGraphics.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphics.h; sourceTree = "<absolute>"; }; 94C3696410AFB7550041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C368F610AFAEA60041953A /* QuickdrawTypes.h */; name = "QuickdrawTypes.h: 262"; rLen = 16; rLoc = 8337; rType = 0; vrLen = 1520; vrLoc = 7208; }; 94C3696610AFB7550041953A /* NSBitmapImageRep.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSBitmapImageRep.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSBitmapImageRep.h; sourceTree = "<absolute>"; }; 94C3698D10B082DF0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C368F910AFAEA60041953A /* CFByteOrder.h */; name = "CFByteOrder.h: 78"; rLen = 20; rLoc = 1887; rType = 0; vrLen = 1136; vrLoc = 1325; }; 94C3699110B082DF0041953A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C3699210B082DF0041953A /* NSColor.h */; name = "NSColor.h: 65"; rLen = 7; rLoc = 3749; rType = 0; vrLen = 2379; vrLoc = 2696; }; 94C3699210B082DF0041953A /* NSColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSColor.h; sourceTree = "<absolute>"; }; 94C36A6D10B091BB0041953A /* NSCursor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSCursor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSCursor.h; sourceTree = "<absolute>"; }; 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 728}}"; sepNavSelRange = "{1980, 16}"; sepNavVisRange = "{108, 2800}"; sepNavWindowFrame = "{{149, 4}, {905, 983}}"; }; }; 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1412, 5291}}"; sepNavSelRange = "{7917, 0}"; sepNavVisRange = "{6896, 1653}"; sepNavWindowFrame = "{{385, 4}, {1131, 1019}}"; }; }; 94C36AD910B0AF960041953A /* NSEvent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSEvent.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSEvent.h; sourceTree = "<absolute>"; }; 94C36C9710B0CF290041953A /* Info-iPhone.plist */ = { uiCtxt = { sepNavWindowFrame = "{{15, 55}, {1438, 968}}"; }; }; 94C3CD4E1235C80200A4E319 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9402DD6F10CE0E91005C2102 /* SqViewClut.m */; name = "SqViewClut.m: 13"; rLen = 0; rLoc = 343; rType = 0; vrLen = 2832; vrLoc = 0; }; 94C4B80F10C06C4700CD4F90 /* configx.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {994, 799}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1946}"; }; }; 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1109, 724}}"; sepNavSelRange = "{1876, 22}"; sepNavVisRange = "{0, 1939}"; }; }; 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 793}}"; sepNavSelRange = "{1951, 5}"; sepNavVisRange = "{1559, 486}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 94C7480712333A2900B1F982 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */; name = "keyBoardStrokeDetails.m: 42"; rLen = 0; rLoc = 1867; rType = 0; vrLen = 1908; vrLoc = 0; }; 94C748E012333EE900B1F982 /* sqMacUIEventsUniversal.c:1113 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 94C748E112333EE900B1F982 /* sqMacUIEventsUniversal.c */; functionName = "recordKeyboardEventCarbon()"; hitCount = 0; ignoreCount = 0; lineNumber = 1113; modificationTime = 308445393.436654; originalNumberOfMultipleMatches = 1; state = 0; }; 94C748E112333EE900B1F982 /* sqMacUIEventsUniversal.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUIEventsUniversal.c; path = "/Volumes/330GB Photos/Cog Before Aug 2010 changes/platforms/Mac OS/vm/sqMacUIEventsUniversal.c"; sourceTree = "<absolute>"; }; 94C887D410ADCC0D007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C887D510ADCC0D007CB39E /* NSThread.h */; name = "NSThread.h: 75"; rLen = 96; rLoc = 1964; rType = 0; vrLen = 2073; vrLoc = 503; }; 94C887D510ADCC0D007CB39E /* NSThread.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSThread.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSThread.h; sourceTree = "<absolute>"; }; 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {908, 585}}"; sepNavSelRange = "{1939, 0}"; sepNavVisRange = "{47, 1963}"; }; }; 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {838, 1820}}"; sepNavSelRange = "{2709, 0}"; sepNavVisRange = "{1953, 1821}"; sepNavWindowFrame = "{{685, 4}, {878, 1019}}"; }; }; 94C888B710ADE75B007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAE9D10ACA3A300F87527 /* NSBundle.h */; name = "NSBundle.h: 11"; rLen = 8; rLoc = 335; rType = 0; vrLen = 2317; vrLoc = 0; }; 94C88B6810AF26F8007CB39E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C88B6910AF26F8007CB39E /* squeakProxy.m */; name = "squeakProxy.m: 124"; rLen = 22; rLoc = 3876; rType = 0; vrLen = 1083; vrLoc = 3252; }; 94C88B6910AF26F8007CB39E /* squeakProxy.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = squeakProxy.m; path = "/Volumes/px2/business/SqueakiPhone/SqueakObjCBasedForOSXAndIPhone/Blob/platforms/Mac OSObjC/plugins/SqueakObjectiveC/squeakProxy.m"; sourceTree = "<absolute>"; }; 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1345, 891}}"; sepNavSelRange = "{1866, 43}"; sepNavVisRange = "{0, 2111}"; sepNavWindowFrame = "{{15, 4}, {1392, 1019}}"; }; }; 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 962}}"; sepNavSelRange = "{2578, 17}"; sepNavVisRange = "{786, 1864}"; sepNavWindowFrame = "{{15, 49}, {1346, 974}}"; }; }; 94C88C0E10AF4196007CB39E /* NSGeometry.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSGeometry.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSGeometry.h; sourceTree = "<absolute>"; }; 94C8D195123EDACE0019544B /* SqueakUIViewOpenGL.m:135 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */; functionName = "-layoutSubviews"; hitCount = 0; ignoreCount = 0; lineNumber = 135; location = Squeak; modificationTime = 308445394.455894; originalNumberOfMultipleMatches = 1; state = 1; }; 94C8D197123EDAD30019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */; name = "sqiPhoneScreenAndWindow.h: 42"; rLen = 23; rLoc = 1909; rType = 0; vrLen = 1943; vrLoc = 0; }; 94C8D19A123EDAD30019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */; name = "sqSqueakIPhoneApplication+events.m: 51"; rLen = 0; rLoc = 2125; rType = 0; vrLen = 1753; vrLoc = 1301; }; 94C8D19B123EDAD30019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */; name = "SqueakNoOGLIPhoneAppDelegate.m: 138"; rLen = 0; rLoc = 5386; rType = 0; vrLen = 1794; vrLoc = 5229; }; 94C8D19C123EDAD30019544B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */; name = "SqueakUIController.m: 94"; rLen = 0; rLoc = 3914; rType = 0; vrLen = 1552; vrLoc = 2585; }; 94CAE0ED1230DE6C00AFE487 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 941724420F36624C0031AF33 /* squeakProxy.m */; name = "squeakProxy.m: 49"; rLen = 11; rLoc = 1931; rType = 0; vrLen = 2138; vrLoc = 493; }; 94CFE6A910BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C207E910AF66D7002F4160 /* NSWindow.h */; name = "NSWindow.h: 453"; rLen = 8; rLoc = 19650; rType = 0; vrLen = 2322; vrLoc = 18630; }; 94CFE6B810BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87510B66A74002F81F2 /* SqueakInterpreterEventSensor.m */; name = "SqueakInterpreterEventSensor.m: 54"; rLen = 8; rLoc = 1477; rType = 0; vrLen = 1077; vrLoc = 1241; }; 94CFE6B910BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89AED10B497F400556475 /* NSResponder.h */; name = "NSResponder.h: 31"; rLen = 12; rLoc = 957; rType = 0; vrLen = 1492; vrLoc = 0; }; 94CFE6BD10BE63A900847DF5 /* SqViewEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewEventSensor.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/SqueakAppKit/SqViewEventSensor.m"; sourceTree = "<absolute>"; }; 94CFE6C010BE63A900847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 945BA53B10B218F700C2020C /* math.h */; name = "math.h: 379"; rLen = 8; rLoc = 15491; rType = 0; vrLen = 1479; vrLoc = 14505; }; 94CFE70110BE683800847DF5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C36AD910B0AF960041953A /* NSEvent.h */; name = "NSEvent.h: 246"; rLen = 6; rLoc = 8572; rType = 0; vrLen = 1801; vrLoc = 7114; }; 94D16BFC10BCEFEE00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16BFD10BCEFEE00A69A89 /* Document.m */; name = "Document.m: 35"; rLen = 32; rLoc = 1133; rType = 0; vrLen = 1663; vrLoc = 14; }; 94D16BFD10BCEFEE00A69A89 /* Document.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Document.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/Document.m"; sourceTree = "<absolute>"; }; 94D16BFE10BCEFEE00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942CF46B10BCE44B009BD905 /* NSWindowController.h */; name = "NSWindowController.h: 13"; rLen = 18; rLoc = 224; rType = 0; vrLen = 2830; vrLoc = 0; }; 94D16C2A10BCF28A00A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9428BBE210BB565100DAD287 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 1031"; rLen = 1; rLoc = 27820; rType = 0; vrLen = 1184; vrLoc = 27288; }; 94D16C4010BCF3E100A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16C4110BCF3E100A69A89 /* CGDirectDisplay.h */; name = "CGDirectDisplay.h: 336"; rLen = 22; rLoc = 13802; rType = 0; vrLen = 2189; vrLoc = 12694; }; 94D16C4110BCF3E100A69A89 /* CGDirectDisplay.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGDirectDisplay.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGDirectDisplay.h; sourceTree = "<absolute>"; }; 94D16C6510BCF5B700A69A89 /* NSApplication.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSApplication.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h; sourceTree = "<absolute>"; }; 94D16CA310BCF93000A69A89 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16C6510BCF5B700A69A89 /* NSApplication.h */; name = "NSApplication.h: 269"; rLen = 43; rLoc = 10310; rType = 0; vrLen = 2825; vrLoc = 9201; }; 94D16CAF10BCF96B00A69A89 /* Credits.rtf */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1140, 649}}"; sepNavSelRange = "{269, 0}"; sepNavVisRect = "{{0, 0}, {1140, 649}}"; sepNavWindowFrame = "{{175, 9}, {878, 1019}}"; }; }; 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 804}}"; sepNavSelRange = "{581, 14}"; sepNavVisRange = "{0, 1092}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 3029}}"; sepNavSelRange = "{1749, 84}"; sepNavVisRange = "{1650, 1795}"; sepNavWindowFrame = "{{715, -46}, {1326, 1010}}"; }; }; 94D3660B10CEE03900805023 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D3660C10CEE03900805023 /* CIImage.h */; name = "CIImage.h: 32"; rLen = 4; rLoc = 826; rType = 0; vrLen = 2058; vrLoc = 0; }; 94D3660C10CEE03900805023 /* CIImage.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIImage.h; path = /System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIImage.h; sourceTree = "<absolute>"; }; 94D715CB10B723B200F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D715CC10B723B200F69A71 /* NSData.h */; name = "NSData.h: 45"; rLen = 6; rLoc = 1410; rType = 0; vrLen = 1584; vrLoc = 0; }; 94D715CC10B723B200F69A71 /* NSData.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSData.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSData.h; sourceTree = "<absolute>"; }; 94D7173610B72F8800F69A71 /* FunctionKeyNames.strings */ = { isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = FunctionKeyNames.strings; path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/FunctionKeyNames.strings; sourceTree = "<absolute>"; }; 94D7174110B72FDF00F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7173610B72F8800F69A71 /* FunctionKeyNames.strings */; name = "FunctionKeyNames.strings: 2"; rLen = 9; rLoc = 29; rType = 0; vrLen = 802; vrLoc = 0; }; 94D7177D10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7177E10B73A3800F69A71 /* SqueakEventQueue.m */; name = "SqueakEventQueue.m: 90"; rLen = 17; rLoc = 2396; rType = 0; vrLen = 1483; vrLoc = 736; }; 94D7177E10B73A3800F69A71 /* SqueakEventQueue.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakEventQueue.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakEventQueue.m"; sourceTree = "<absolute>"; }; 94D7178010B73A3800F69A71 /* SqueakInterpreterEventSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakInterpreterEventSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreterEventSensor.m"; sourceTree = "<absolute>"; }; 94D7178310B73A3800F69A71 /* SqViewInputSensor.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewInputSensor.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewInputSensor.m"; sourceTree = "<absolute>"; }; 94D7178410B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178510B73A3800F69A71 /* SqueakController.m */; name = "SqueakController.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1497; vrLoc = 370; }; 94D7178510B73A3800F69A71 /* SqueakController.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqueakController.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/CocoaSqueak/SqueakController.m"; sourceTree = "<absolute>"; }; 94D7178610B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178710B73A3800F69A71 /* SqViewBitmapConversion.m */; name = "SqViewBitmapConversion.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1336; vrLoc = 7040; }; 94D7178710B73A3800F69A71 /* SqViewBitmapConversion.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqViewBitmapConversion.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqViewBitmapConversion.m"; sourceTree = "<absolute>"; }; 94D7178810B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178910B73A3800F69A71 /* SqView.m */; name = "SqView.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2292; vrLoc = 6209; }; 94D7178910B73A3800F69A71 /* SqView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqView.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqView.m"; sourceTree = "<absolute>"; }; 94D7178A10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178B10B73A3800F69A71 /* SqClipboardHandler.m */; name = "SqClipboardHandler.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1588; vrLoc = 0; }; 94D7178B10B73A3800F69A71 /* SqClipboardHandler.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SqClipboardHandler.m; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/SqClipboardHandler.m"; sourceTree = "<absolute>"; }; 94D7178C10B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178D10B73A3800F69A71 /* CarbonSound.c */; name = "CarbonSound.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2068; vrLoc = 1940; }; 94D7178D10B73A3800F69A71 /* CarbonSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = CarbonSound.c; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/SqueakAppKit/CarbonSound.c"; sourceTree = "<absolute>"; }; 94D7178F10B73A3800F69A71 /* SqueakInterpreterEventSensor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SqueakInterpreterEventSensor.h; path = "/Users/johnmci/Documents/Squeak/CocoaSqueak-3.0.4/src/Squeak/SqueakInterpreterEventSensor.h"; sourceTree = "<absolute>"; }; 94D7179110B73A3800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7179210B73A3800F69A71 /* FScriptTextView.m */; name = "FScriptTextView.m: 126"; rLen = 138; rLoc = 4464; rType = 0; vrLen = 1701; vrLoc = 4066; }; 94D7179210B73A3800F69A71 /* FScriptTextView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FScriptTextView.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/FScriptTextView.m"; sourceTree = "<absolute>"; }; 94D717BE10B73DD900F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E8D110B67499002F81F2 /* NSRange.h */; name = "NSRange.h: 12"; rLen = 23; rLoc = 213; rType = 0; vrLen = 1181; vrLoc = 0; }; 94D717E610B7421F00F69A71 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/SqueakSparklePlugin/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94D717F810B743B800F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D717E610B7421F00F69A71 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2301"; rLen = 18; rLoc = 59489; rType = 0; vrLen = 1347; vrLoc = 59154; }; 94D7183810B74BF300F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7183910B74BF300F69A71 /* NSInputManager.h */; name = "NSInputManager.h: 21"; rLen = 68; rLoc = 621; rType = 0; vrLen = 1979; vrLoc = 0; }; 94D7183910B74BF300F69A71 /* NSInputManager.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSInputManager.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSInputManager.h; sourceTree = "<absolute>"; }; 94D7183A10B74BF300F69A71 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7183B10B74BF300F69A71 /* NSTextInputClient.h */; name = "NSTextInputClient.h: 32"; rLen = 20; rLoc = 1358; rType = 0; vrLen = 2207; vrLoc = 0; }; 94D7183B10B74BF300F69A71 /* NSTextInputClient.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextInputClient.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextInputClient.h; sourceTree = "<absolute>"; }; 94D73E5210B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5310B5B9CE00F8C034 /* cl.h */; name = "cl.h: 118"; rLen = 0; rLoc = 4914; rType = 0; vrLen = 2396; vrLoc = 3357; }; 94D73E5310B5B9CE00F8C034 /* cl.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cl.h; path = /System/Library/Frameworks/OpenCL.framework/Versions/A/Headers/cl.h; sourceTree = "<absolute>"; }; 94D73E5410B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5510B5B9CE00F8C034 /* float-i32.h */; name = "float-i32.h: 20"; rLen = 35; rLoc = 653; rType = 0; vrLen = 2227; vrLoc = 0; }; 94D73E5510B5B9CE00F8C034 /* float-i32.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i32.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i32.h"; sourceTree = "<absolute>"; }; 94D73E5610B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5710B5B9CE00F8C034 /* float-i128.h */; name = "float-i128.h: 19"; rLen = 11; rLoc = 649; rType = 0; vrLen = 2262; vrLoc = 0; }; 94D73E5710B5B9CE00F8C034 /* float-i128.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i128.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i128.h"; sourceTree = "<absolute>"; }; 94D73E5810B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5910B5B9CE00F8C034 /* float-i386.h */; name = "float-i386.h: 20"; rLen = 11; rLoc = 670; rType = 0; vrLen = 2261; vrLoc = 0; }; 94D73E5910B5B9CE00F8C034 /* float-i386.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i386.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i386.h"; sourceTree = "<absolute>"; }; 94D73E5A10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5B10B5B9CE00F8C034 /* float-m68k.h */; name = "float-m68k.h: 20"; rLen = 11; rLoc = 677; rType = 0; vrLen = 2268; vrLoc = 0; }; 94D73E5B10B5B9CE00F8C034 /* float-m68k.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-m68k.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-m68k.h"; sourceTree = "<absolute>"; }; 94D73E5C10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5D10B5B9CE00F8C034 /* float-sh.h */; name = "float-sh.h: 19"; rLen = 11; rLoc = 642; rType = 0; vrLen = 2198; vrLoc = 0; }; 94D73E5D10B5B9CE00F8C034 /* float-sh.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-sh.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-sh.h"; sourceTree = "<absolute>"; }; 94D73E5E10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E5F10B5B9CE00F8C034 /* float-sparc.h */; name = "float-sparc.h: 20"; rLen = 11; rLoc = 729; rType = 0; vrLen = 2320; vrLoc = 0; }; 94D73E5F10B5B9CE00F8C034 /* float-sparc.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-sparc.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-sparc.h"; sourceTree = "<absolute>"; }; 94D73E6010B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6110B5B9CE00F8C034 /* float-vax.h */; name = "float-vax.h: 6"; rLen = 0; rLoc = 173; rType = 0; vrLen = 2188; vrLoc = 0; }; 94D73E6110B5B9CE00F8C034 /* float-vax.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-vax.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-vax.h"; sourceTree = "<absolute>"; }; 94D73E6210B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6310B5B9CE00F8C034 /* float-i64.h */; name = "float-i64.h: 20"; rLen = 35; rLoc = 660; rType = 0; vrLen = 2261; vrLoc = 0; }; 94D73E6310B5B9CE00F8C034 /* float-i64.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "float-i64.h"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/config/float-i64.h"; sourceTree = "<absolute>"; }; 94D73E6410B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6510B5B9CE00F8C034 /* dummyFFI.c */; name = "dummyFFI.c: 116"; rLen = 19; rLoc = 2641; rType = 0; vrLen = 813; vrLoc = 2018; }; 94D73E6510B5B9CE00F8C034 /* dummyFFI.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dummyFFI.c; path = /Users/johnmci/Shared/plugins/SqueakFFIPrims/dummyFFI.c; sourceTree = "<absolute>"; }; 94D73E6810B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6910B5B9CE00F8C034 /* c90-float-1.c */; name = "c90-float-1.c: 47"; rLen = 11; rLoc = 855; rType = 0; vrLen = 1089; vrLoc = 0; }; 94D73E6910B5B9CE00F8C034 /* c90-float-1.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "c90-float-1.c"; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/testsuite/gcc.dg/c90-float-1.c"; sourceTree = "<absolute>"; }; 94D73E6A10B5B9CE00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73E6B10B5B9CE00F8C034 /* enquire.c */; name = "enquire.c: 1232"; rLen = 48; rLoc = 38198; rType = 0; vrLen = 1282; vrLoc = 37320; }; 94D73E6B10B5B9CE00F8C034 /* enquire.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = enquire.c; path = "/Users/johnmci/Documents/Files from Lamie/Documents/Darwin/gcc3-1151/gcc/enquire.c"; sourceTree = "<absolute>"; }; 94D73EE610B5CF8400F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89C5A10B4BF2800556475 /* NSRunLoop.h */; name = "NSRunLoop.h: 30"; rLen = 8; rLoc = 714; rType = 0; vrLen = 1899; vrLoc = 0; }; 94D73F4910B5DA4E00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 942ABE0910AA21270086D908 /* NSView.h */; name = "NSView.h: 219"; rLen = 8; rLoc = 7448; rType = 0; vrLen = 2783; vrLoc = 6088; }; 94D73FA010B5E5A200F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73FA110B5E5A200F8C034 /* CIColor.h */; name = "CIColor.h: 50"; rLen = 16; rLoc = 1220; rType = 0; vrLen = 1382; vrLoc = 0; }; 94D73FA110B5E5A200F8C034 /* CIColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CIColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CIColor.h; sourceTree = "<absolute>"; }; 94D73FA410B5E5A200F8C034 /* CGColor.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGColor.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGColor.h; sourceTree = "<absolute>"; }; 94D73FAD10B5E69900F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D73FA410B5E5A200F8C034 /* CGColor.h */; name = "CGColor.h: 44"; rLen = 68; rLoc = 1614; rType = 0; vrLen = 2485; vrLoc = 0; }; 94D73FB510B5E6DA00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206DA10AF5536002F4160 /* CGContext.h */; name = "CGContext.h: 402"; rLen = 62; rLoc = 14416; rType = 0; vrLen = 511; vrLoc = 14175; }; 94D7401510B5F8AF00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C2070610AF5A9E002F4160 /* NSImage.h */; name = "NSImage.h: 187"; rLen = 103; rLoc = 8443; rType = 0; vrLen = 6322; vrLoc = 6281; }; 94D7402810B5FA6100F8C034 /* CGDataProvider.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGDataProvider.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGDataProvider.h; sourceTree = "<absolute>"; }; 94D7403810B5FDDB00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94C206D210AF5536002F4160 /* CGImage.h */; name = "CGImage.h: 56"; rLen = 17; rLoc = 1989; rType = 0; vrLen = 2464; vrLoc = 1345; }; 94D7403A10B5FDDB00F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7402810B5FA6100F8C034 /* CGDataProvider.h */; name = "CGDataProvider.h: 114"; rLen = 79; rLoc = 4291; rType = 0; vrLen = 2286; vrLoc = 4217; }; 94D740B210B6242000F8C034 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D740B310B6242000F8C034 /* mman.h */; name = "mman.h: 161"; rLen = 64; rLoc = 6016; rType = 0; vrLen = 1386; vrLoc = 5938; }; 94D740B310B6242000F8C034 /* mman.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mman.h; path = /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h; sourceTree = "<absolute>"; }; 94E1BDAB11E5A9F400D5B92B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */; name = "sqSqueakMainApp.m: 167"; rLen = 0; rLoc = 4906; rType = 0; vrLen = 1514; vrLoc = 3460; }; 94E297D10DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D20DECA72F009CF73A /* config.h */; name = "config.h: 154"; rLen = 60; rLoc = 3675; rType = 0; vrLen = 993; vrLoc = 2863; }; 94E297D20DECA72F009CF73A /* config.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = /Users/johnmci/Documents/SqueakGStreamer/platforms/unix/bld/config.h; sourceTree = "<absolute>"; }; 94E297D30DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D40DECA72F009CF73A /* version.c */; name = "version.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 65; vrLoc = 0; }; 94E297D40DECA72F009CF73A /* version.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = version.c; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/version.c; sourceTree = "<absolute>"; }; 94E297D50DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E297D60DECA72F009CF73A /* version.h */; name = "version.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 89; vrLoc = 0; }; 94E297D60DECA72F009CF73A /* version.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = /Users/johnmci/Documents/SqueakHydra/platforms/win32/vm/version.h; sourceTree = "<absolute>"; }; 94E297D70DECA72F009CF73A /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 949E5B970DE3623B007388E0 /* sqUnixMain.c */; name = "sqUnixMain.c: 417"; rLen = 15; rLoc = 10250; rType = 0; vrLen = 1200; vrLoc = 9269; }; 94E2DAD40ED2351B00012E92 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E2DAD50ED2351B00012E92 /* sqMacUnixInterfaceSound.c */; name = "sqMacUnixInterfaceSound.c: 46"; rLen = 29; rLoc = 774; rType = 0; vrLen = 808; vrLoc = 382; }; 94E2DAD50ED2351B00012E92 /* sqMacUnixInterfaceSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacUnixInterfaceSound.c; path = "/Users/johnmci/Documents/SqueakSpellingPlugin/platforms/Mac OS/plugins/SoundPlugin/sqMacUnixInterfaceSound.c"; sourceTree = "<absolute>"; }; 94E2DADE0ED2351B00012E92 /* sqUnixSound.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqUnixSound.c; path = /Users/johnmci/Documents/SqueakServicesPlugin/platforms/unix/plugins/SoundPlugin/sqUnixSound.c; sourceTree = "<absolute>"; }; 94E2DB270ED2355F00012E92 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E2DADE0ED2351B00012E92 /* sqUnixSound.c */; name = "sqUnixSound.c: 114"; rLen = 0; rLoc = 4098; rType = 0; vrLen = 922; vrLoc = 3342; }; 94E4930310BD32D00011AC75 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9414420010BC817D0088F8AC /* NSPanel.h */; name = "NSPanel.h: 43"; rLen = 165; rLoc = 3279; rType = 0; vrLen = 3883; vrLoc = 0; }; 94E4936F10BD39E20011AC75 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/Squeak3.8.0.0CLosureWithEncryption/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94E5838A10BF3E080073FD63 /* NSTextInputClient.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTextInputClient.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextInputClient.h; sourceTree = "<absolute>"; }; 94E5838E10BF3E080073FD63 /* AudioQueue.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioQueue.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/Headers/AudioQueue.h; sourceTree = "<absolute>"; }; 94E583DB10BF43970073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5838A10BF3E080073FD63 /* NSTextInputClient.h */; name = "NSTextInputClient.h: 20"; rLen = 75; rLoc = 497; rType = 0; vrLen = 2725; vrLoc = 0; }; 94E5846510BF67600073FD63 /* NSResponder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSResponder.h; path = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSResponder.h; sourceTree = "<absolute>"; }; 94E584AE10BF6EE30073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E5846510BF67600073FD63 /* NSResponder.h */; name = "NSResponder.h: 99"; rLen = 46; rLoc = 3759; rType = 0; vrLen = 2139; vrLoc = 2704; }; 94E584FF10BF79AB0073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178310B73A3800F69A71 /* SqViewInputSensor.m */; name = "SqViewInputSensor.m: 34"; rLen = 22; rLoc = 478; rType = 0; vrLen = 1359; vrLoc = 0; }; 94E5850010BF79AB0073FD63 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9406E87710B66A74002F81F2 /* SqViewEventSensor.m */; name = "SqViewEventSensor.m: 29"; rLen = 7; rLoc = 449; rType = 0; vrLen = 1509; vrLoc = 0; }; 94E658E10DDD03FE00358328 /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 565}}"; sepNavSelRange = "{161, 5}"; sepNavVisRange = "{0, 685}"; sepNavWindowFrame = "{{38, 14}, {799, 988}}"; }; }; 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1533, 10348}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 410}"; }; }; 94E658E60DDD03FE00358328 /* B2DPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1482, 166114}}"; sepNavSelRange = "{238472, 12}"; sepNavVisRange = "{237846, 1064}"; }; }; 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1405, 85475}}"; sepNavSelRange = "{52607, 0}"; sepNavVisRange = "{52196, 1366}"; }; }; 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 2860}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E658F00DDD03FE00358328 /* DSAPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 8112}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E658F20DDD03FE00358328 /* FFTPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 4641}}"; sepNavSelRange = "{8267, 0}"; sepNavVisRange = "{8149, 272}"; }; }; 94E658F40DDD03FE00358328 /* FilePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 14144}}"; sepNavSelRange = "{27580, 7}"; sepNavVisRange = "{26914, 1464}"; sepNavWindowFrame = "{{21, 20}, {694, 1008}}"; }; }; 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 7592}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 192}"; }; }; 94E658F80DDD03FE00358328 /* GeniePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 5044}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 192}"; }; }; 94E658FA0DDD03FE00358328 /* HostWindowPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 5330}}"; sepNavSelRange = "{9579, 21}"; sepNavVisRange = "{9090, 1206}"; }; }; 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 17043}}"; sepNavSelRange = "{9474, 0}"; sepNavVisRange = "{9324, 406}"; }; }; 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1195, 9100}}"; sepNavSelRange = "{21135, 17}"; sepNavVisRange = "{19526, 1968}"; }; }; 94E659020DDD03FE00358328 /* Klatt.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 19500}}"; sepNavSelRange = "{44049, 0}"; sepNavVisRange = "{43900, 200}"; sepNavWindowFrame = "{{15, 4}, {1426, 1019}}"; }; }; 94E659040DDD03FE00358328 /* LargeIntegers.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1342, 30290}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 869}"; }; }; 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 8814}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E659080DDD03FE00358328 /* MIDIPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1867, 4784}}"; sepNavSelRange = "{3309, 0}"; sepNavVisRange = "{3006, 515}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 10621}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 850}"; }; }; 94E6590C0DDD03FE00358328 /* RePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {3113, 6032}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 871}"; }; }; 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4238}}"; sepNavSelRange = "{5714, 21}"; sepNavVisRange = "{5088, 1429}"; sepNavWindowFrame = "{{15, 45}, {1017, 978}}"; }; }; 94E659100DDD03FE00358328 /* SocketPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1377, 23166}}"; sepNavSelRange = "{5715, 37}"; sepNavVisRange = "{4742, 1976}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94E659120DDD03FE00358328 /* SoundCodecPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 2886}}"; sepNavSelRange = "{2059, 0}"; sepNavVisRange = "{1965, 173}"; }; }; 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 9087}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 261}"; }; }; 94E659160DDD03FE00358328 /* SoundPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 6084}}"; sepNavSelRange = "{5833, 13}"; sepNavVisRange = "{5241, 1174}"; sepNavWindowFrame = "{{38, 28}, {1346, 974}}"; }; }; 94E659180DDD03FE00358328 /* Squeak3D.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1440, 39338}}"; sepNavSelRange = "{3704, 6}"; sepNavVisRange = "{2895, 2373}"; }; }; 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1412, 4316}}"; sepNavSelRange = "{4752, 0}"; sepNavVisRange = "{4329, 952}"; }; }; 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 2041}}"; sepNavSelRange = "{2745, 19}"; sepNavVisRange = "{2105, 1164}"; sepNavWindowFrame = "{{38, 17}, {847, 985}}"; }; }; 94E6591F0DDD03FE00358328 /* ZipPlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1104, 17446}}"; sepNavSelRange = "{1700, 11}"; sepNavVisRange = "{710, 2153}"; sepNavWindowFrame = "{{15, 22}, {1064, 1001}}"; }; }; 94E659200DDD03FE00358328 /* sqNamedPrims.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1144}}"; sepNavSelRange = "{2312, 0}"; sepNavVisRange = "{1591, 929}"; sepNavWindowFrame = "{{15, 9}, {1078, 1014}}"; }; }; 94E659430DDD04FA00358328 /* AsynchFilePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 501}}"; sepNavSelRange = "{404, 19}"; sepNavVisRange = "{0, 659}"; }; }; 94E659450DDD04FA00358328 /* FilePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 767}}"; sepNavSelRange = "{1735, 10}"; sepNavVisRange = "{440, 1866}"; sepNavWindowFrame = "{{15, 25}, {997, 998}}"; }; }; 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 5850}}"; sepNavSelRange = "{11068, 11}"; sepNavVisRange = "{10580, 897}"; sepNavWindowFrame = "{{38, 19}, {905, 983}}"; }; }; 94E659490DDD053900358328 /* SurfacePlugin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {784, 2990}}"; sepNavSelRange = "{2333, 0}"; sepNavVisRange = "{1279, 2223}"; }; }; 94E6594A0DDD053900358328 /* SurfacePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {784, 1716}}"; sepNavSelRange = "{27, 0}"; sepNavVisRange = "{0, 2637}"; }; }; 94E6594D0DDD053900358328 /* SecurityPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 481}}"; sepNavSelRange = "{290, 3}"; sepNavVisRange = "{117, 443}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94E6594F0DDD053900358328 /* SoundGenerationPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{299, 3}"; sepNavVisRange = "{0, 360}"; }; }; 94E659530DDD053900358328 /* jcapimin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3822}}"; sepNavSelRange = "{7008, 3}"; sepNavVisRange = "{5989, 1240}"; }; }; 94E659550DDD053900358328 /* jccoefct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5863}}"; sepNavSelRange = "{9819, 3}"; sepNavVisRange = "{8276, 1834}"; }; }; 94E659560DDD053900358328 /* jccolor.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5889}}"; sepNavSelRange = "{9842, 3}"; sepNavVisRange = "{9173, 1109}"; }; }; 94E659570DDD053900358328 /* jcdctmgr.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4966}}"; sepNavSelRange = "{6549, 3}"; sepNavVisRange = "{5884, 1542}"; }; }; 94E659580DDD053900358328 /* jchuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 11778}}"; sepNavSelRange = "{22307, 3}"; sepNavVisRange = "{21622, 1607}"; }; }; 94E6595B0DDD053900358328 /* jcmainct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3783}}"; sepNavSelRange = "{7591, 3}"; sepNavVisRange = "{6975, 964}"; }; }; 94E6595C0DDD053900358328 /* jcmarker.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8866}}"; sepNavSelRange = "{10933, 3}"; sepNavVisRange = "{10271, 1095}"; }; }; 94E6595D0DDD053900358328 /* jcmaster.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 7553}}"; sepNavSelRange = "{10789, 3}"; sepNavVisRange = "{10099, 1218}"; }; }; 94E6595E0DDD053900358328 /* jcomapi.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 1512}}"; sepNavSelRange = "{2136, 7}"; sepNavVisRange = "{1428, 1392}"; }; }; 94E659600DDD053900358328 /* jcparam.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8164}}"; sepNavSelRange = "{18163, 3}"; sepNavVisRange = "{17732, 1161}"; }; }; 94E659610DDD053900358328 /* jcphuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 10920}}"; sepNavSelRange = "{18752, 3}"; sepNavVisRange = "{17946, 1058}"; }; }; 94E659620DDD053900358328 /* jcprepct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4628}}"; sepNavSelRange = "{9095, 3}"; sepNavVisRange = "{8327, 1337}"; }; }; 94E659630DDD053900358328 /* jcsample.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6994}}"; sepNavSelRange = "{7407, 3}"; sepNavVisRange = "{6537, 1530}"; }; }; 94E659640DDD053900358328 /* jctrans.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5187}}"; sepNavSelRange = "{13272, 3}"; sepNavVisRange = "{12530, 1091}"; }; }; 94E659650DDD053900358328 /* jdapimin.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5135}}"; sepNavSelRange = "{7807, 3}"; sepNavVisRange = "{7168, 1550}"; }; }; 94E659690DDD053900358328 /* jdcoefct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 9451}}"; sepNavSelRange = "{21428, 3}"; sepNavVisRange = "{20759, 1160}"; }; }; 94E6596A0DDD053900358328 /* jdcolor.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5057}}"; sepNavSelRange = "{8235, 3}"; sepNavVisRange = "{7573, 1344}"; }; }; 94E6596B0DDD053900358328 /* jdct.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2275}}"; sepNavSelRange = "{693, 3}"; sepNavVisRange = "{0, 1654}"; }; }; 94E6596D0DDD053900358328 /* jdhuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8229}}"; sepNavSelRange = "{15652, 3}"; sepNavVisRange = "{14578, 1143}"; }; }; 94E6596E0DDD053900358328 /* jdhuff.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2574}}"; sepNavSelRange = "{4464, 3}"; sepNavVisRange = "{2783, 1780}"; }; }; 94E6596F0DDD053900358328 /* jdinput.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4810}}"; sepNavSelRange = "{6703, 3}"; sepNavVisRange = "{5969, 1701}"; }; }; 94E659700DDD053900358328 /* jdmainct.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6149}}"; sepNavSelRange = "{7953, 3}"; sepNavVisRange = "{7137, 1484}"; }; }; 94E659710DDD053900358328 /* jdmarker.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 17706}}"; sepNavSelRange = "{40391, 3}"; sepNavVisRange = "{38997, 1561}"; }; }; 94E659720DDD053900358328 /* jdmaster.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 7085}}"; sepNavSelRange = "{14890, 3}"; sepNavVisRange = "{14181, 1516}"; }; }; 94E659730DDD053900358328 /* jdmerge.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5187}}"; sepNavSelRange = "{10331, 3}"; sepNavVisRange = "{9363, 1315}"; }; }; 94E659740DDD053900358328 /* jdphuff.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 8606}}"; sepNavSelRange = "{15744, 3}"; sepNavVisRange = "{14845, 1126}"; }; }; 94E659760DDD053900358328 /* jdsample.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 6409}}"; sepNavSelRange = "{11463, 3}"; sepNavVisRange = "{10845, 1368}"; }; }; 94E659770DDD053900358328 /* jdtrans.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2002}}"; sepNavSelRange = "{995, 7}"; sepNavVisRange = "{0, 1708}"; }; }; 94E659790DDD053900358328 /* jerror.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 4095}}"; sepNavSelRange = "{11163, 7}"; sepNavVisRange = "{10252, 1759}"; }; }; 94E6597C0DDD053900358328 /* jfdctint.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3809}}"; sepNavSelRange = "{5901, 3}"; sepNavVisRange = "{5152, 1247}"; }; }; 94E6597D0DDD053900358328 /* jidctflt.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 3094}}"; sepNavSelRange = "{7928, 3}"; sepNavVisRange = "{6879, 1380}"; }; }; 94E6597E0DDD053900358328 /* jidctfst.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 4706}}"; sepNavSelRange = "{9786, 3}"; sepNavVisRange = "{8848, 1431}"; }; }; 94E6597F0DDD053900358328 /* jidctint.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5044}}"; sepNavSelRange = "{11723, 3}"; sepNavVisRange = "{10788, 1464}"; }; }; 94E659800DDD053900358328 /* jidctred.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{11209, 3}"; sepNavVisRange = "{10458, 1488}"; }; }; 94E659810DDD053900358328 /* jinclude.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 1248}}"; sepNavSelRange = "{1563, 7}"; sepNavVisRange = "{935, 1320}"; }; }; 94E659820DDD053900358328 /* jmemdatadst.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1924}}"; sepNavSelRange = "{4506, 0}"; sepNavVisRange = "{4026, 877}"; }; }; 94E659830DDD053900358328 /* jmemdatasrc.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2639}}"; sepNavSelRange = "{8018, 0}"; sepNavVisRange = "{7282, 942}"; sepNavWindowFrame = "{{15, 13}, {1326, 1010}}"; }; }; 94E659840DDD053900358328 /* jmemmgr.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 14313}}"; sepNavSelRange = "{20872, 3}"; sepNavVisRange = "{20200, 1407}"; }; }; 94E659860DDD053900358328 /* jmemsys.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2730}}"; sepNavSelRange = "{1380, 7}"; sepNavVisRange = "{578, 1969}"; }; }; 94E659870DDD053900358328 /* jmorecfg.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{4500, 3}"; sepNavVisRange = "{3819, 1298}"; }; }; 94E659880DDD053900358328 /* jpegint.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5135}}"; sepNavSelRange = "{8138, 3}"; sepNavVisRange = "{6999, 1671}"; }; }; 94E659890DDD053900358328 /* jpeglib.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 14287}}"; sepNavSelRange = "{44121, 3}"; sepNavVisRange = "{43159, 1631}"; }; }; 94E6598A0DDD053900358328 /* JPEGReadWriter2Plugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{400, 3}"; sepNavVisRange = "{0, 606}"; }; }; 94E6598B0DDD053900358328 /* jquant1.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 10946}}"; sepNavSelRange = "{23424, 3}"; sepNavVisRange = "{22008, 1505}"; }; }; 94E6598C0DDD053900358328 /* jquant2.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 17212}}"; sepNavSelRange = "{35564, 3}"; sepNavVisRange = "{34161, 1581}"; }; }; 94E6598D0DDD053900358328 /* jutils.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 2379}}"; sepNavSelRange = "{709, 3}"; sepNavVisRange = "{0, 1126}"; }; }; 94E659910DDD053900358328 /* UUIDPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1357, 141}}"; sepNavSelRange = "{224, 0}"; sepNavVisRange = "{0, 247}"; }; }; 94E659930DDD053900358328 /* SoundPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 891}}"; sepNavSelRange = "{209, 89}"; sepNavVisRange = "{0, 1762}"; sepNavWindowFrame = "{{15, 4}, {878, 1019}}"; }; }; 94E659970DDD053900358328 /* b3d.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 1547}}"; sepNavSelRange = "{1163, 18}"; sepNavVisRange = "{725, 933}"; }; }; 94E659990DDD053900358328 /* b3dAlloc.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1196, 2044}}"; sepNavSelRange = "{2615, 7}"; sepNavVisRange = "{1909, 1488}"; }; }; 94E6599A0DDD053900358328 /* b3dDraw.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 6643}}"; sepNavSelRange = "{13439, 0}"; sepNavVisRange = "{12902, 1039}"; }; }; 94E6599B0DDD053900358328 /* b3dInit.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {725, 9529}}"; sepNavSelRange = "{7571, 26}"; sepNavVisRange = "{6648, 1585}"; sepNavWindowFrame = "{{15, 4}, {772, 1019}}"; }; }; 94E6599C0DDD053900358328 /* b3dMain.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 19396}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 931}"; }; }; 94E6599D0DDD053900358328 /* b3dRemap.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 3718}}"; sepNavSelRange = "{7538, 0}"; sepNavVisRange = "{6829, 1035}"; }; }; 94E6599E0DDD053900358328 /* b3dTypes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 4420}}"; sepNavSelRange = "{4491, 13}"; sepNavVisRange = "{3977, 898}"; }; }; 94E659A00DDD053900358328 /* SocketPlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1601, 1118}}"; sepNavSelRange = "{3647, 30}"; sepNavVisRange = "{757, 4070}"; }; }; 94E659A30DDD053900358328 /* SoundCodecPrims.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 527}}"; sepNavSelRange = "{3, 10}"; sepNavVisRange = "{0, 401}"; }; }; 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1368, 50453}}"; sepNavSelRange = "{10030, 6}"; sepNavVisRange = "{9384, 1276}"; }; }; 94E65A290DDD053900358328 /* chartables.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 2457}}"; sepNavSelRange = "{489, 0}"; sepNavVisRange = "{0, 1280}"; }; }; 94E65A2B0DDD053900358328 /* get.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1338, 2730}}"; sepNavSelRange = "{2039, 7}"; sepNavVisRange = "{1268, 1649}"; }; }; 94E65A2C0DDD053900358328 /* internal.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1283, 5629}}"; sepNavSelRange = "{1665, 0}"; sepNavVisRange = "{1415, 1340}"; }; }; 94E65A2E0DDD053900358328 /* pcre.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {950, 66339}}"; sepNavSelRange = "{1763, 31}"; sepNavVisRange = "{781, 2030}"; sepNavWindowFrame = "{{683, 16}, {997, 998}}"; }; }; 94E65A2F0DDD053900358328 /* pcre.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 1495}}"; sepNavSelRange = "{2990, 3}"; sepNavVisRange = "{1856, 1482}"; }; }; 94E65A300DDD053900358328 /* rePlugin.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1010, 637}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 1259}"; }; }; 94E65A340DDD053900358328 /* study.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1215, 5096}}"; sepNavSelRange = "{3001, 3}"; sepNavVisRange = "{2296, 1397}"; }; }; 94E7F6B812373EB800A03A11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E7F6B912373EB800A03A11 /* sqMacLocaleCarbon.c */; name = "sqMacLocaleCarbon.c: 104"; rLen = 21; rLoc = 2979; rType = 0; vrLen = 1607; vrLoc = 2451; }; 94E7F6B912373EB800A03A11 /* sqMacLocaleCarbon.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqMacLocaleCarbon.c; path = "/Users/johnmci/Documents/Squeak3.8.0/platforms/Mac OS/plugins/LocalePlugin/sqMacLocaleCarbon.c"; sourceTree = "<absolute>"; }; 94E8EEEA11C94D5D0049D853 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94E8EEEB11C94D5D0049D853 /* sqUnixQuartz.m */; name = "sqUnixQuartz.m: 2113"; rLen = 12; rLoc = 55330; rType = 0; vrLen = 1130; vrLoc = 54733; }; 94E8EEEB11C94D5D0049D853 /* sqUnixQuartz.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = sqUnixQuartz.m; path = "/Users/johnmci/Documents/Squeak3.8.0/History/4.2.4b1/platforms/unix/vm-display-Quartz/sqUnixQuartz.m"; sourceTree = "<absolute>"; }; 94E8FA3C12258ED500EECD29 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D16CAF10BCF96B00A69A89 /* Credits.rtf */; name = "Credits.rtf: 9"; rLen = 0; rLoc = 269; rType = 0; vrLen = 425; vrLoc = 0; }; 94E8FA6512258FDF00EECD29 /* sqMacV2Memory.c:191 */ = { isa = PBXFileBreakpoint; actions = ( ); breakpointStyle = 0; continueAfterActions = 0; countType = 0; delayBeforeContinue = 0; fileReference = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; functionName = "sqMakeMemoryExecutableFromTo()"; hitCount = 0; ignoreCount = 0; lineNumber = 191; location = Squeak; modificationTime = 308445393.436468; originalNumberOfMultipleMatches = 1; state = 0; }; 94ED7EFA0E6C2ABE00F4DD03 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94ED7EFB0E6C2ABE00F4DD03 /* Document.m */; name = "Document.m: 75"; rLen = 20; rLoc = 2275; rType = 0; vrLen = 1332; vrLoc = 1613; }; 94ED7EFB0E6C2ABE00F4DD03 /* Document.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Document.m; path = "/Users/johnmci/Work In Progress/smalltalk/CocoaSqueakSource/CocoaSqueak/Document.m"; sourceTree = "<absolute>"; }; 94EE1DAA11E57FAB00DC6E8C /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 9424FF680DDCB202009912BF /* sqMacV2Memory.h */; name = "sqMacV2Memory.h: 47"; rLen = 15; rLoc = 2075; rType = 0; vrLen = 2098; vrLoc = 0; }; 94EF43151262BFC100817F37 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */; name = "sqUnixSocket.c: 2129"; rLen = 0; rLoc = 56411; rType = 0; vrLen = 1375; vrLoc = 6842; }; 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {852, 472550}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{50, 1341}"; sepNavWindowFrame = "{{512, 195}, {901, 833}}"; }; }; 94EF6CC011E55947003BA64D /* interp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1132, 597}}"; sepNavSelRange = "{134, 7}"; sepNavVisRange = "{0, 586}"; }; }; 94F155570E83EA1F001657CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94B88C640E81500200C98131 /* SqueakObjcBridge.m */; name = "SqueakObjcBridge.m: 291"; rLen = 0; rLoc = 8126; rType = 0; vrLen = 2591; vrLoc = 6567; }; 94F155580E83EA1F001657CE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F155590E83EA1F001657CE /* FSNSProxy.m */; name = "FSNSProxy.m: 24"; rLen = 26; rLoc = 737; rType = 0; vrLen = 1622; vrLoc = 0; }; 94F155590E83EA1F001657CE /* FSNSProxy.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FSNSProxy.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/FSNSProxy.m"; sourceTree = "<absolute>"; }; 94F1F15C11EB8AB5004B3AE3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F1F15D11EB8AB5004B3AE3 /* project.pbxproj */; name = "project.pbxproj: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 7554; vrLoc = 0; }; 94F1F15D11EB8AB5004B3AE3 /* project.pbxproj */ = { isa = PBXFileReference; lastKnownFileType = text.pbxproject; name = project.pbxproj; path = /Users/johnmci/Documents/Squeak3.8.0/platforms/iOS/vm/SqueakPureObjcCogVM.xcodeproj/project.pbxproj; sourceTree = "<absolute>"; }; 94F1F5C910C30C22008DB9CF /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F1F5CA10C30C22008DB9CF /* mpeg3io.c */; name = "mpeg3io.c: 5"; rLen = 1155; rLoc = 45; rType = 0; vrLen = 1995; vrLoc = 0; }; 94F1F5CA10C30C22008DB9CF /* mpeg3io.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mpeg3io.c; path = /Users/johnmci/Documents/SqueakmpegFullSource/libmpeg/mpeg3io.c; sourceTree = "<absolute>"; }; 94F3A9690E6BFA7C00E0B12A /* Squeak.png */ = { uiCtxt = { sepNavWindowFrame = "{{61, 124}, {1288, 857}}"; }; }; 94F5C1870DF26EF200099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1880DF26EF200099B11 /* interp.c */; name = "interp.c: 5170"; rLen = 7; rLoc = 155552; rType = 0; vrLen = 1874; vrLoc = 154817; }; 94F5C1880DF26EF200099B11 /* interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = interp.c; path = /Users/johnmci/Documents/SqueakSquatSpoon/src/vm/interp.c; sourceTree = "<absolute>"; }; 94F5C1910DF26EF200099B11 /* gnu-interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "gnu-interp.c"; path = "/Volumes/pm/Mail Downloads/gnu-interp.c"; sourceTree = "<absolute>"; }; 94F5C1930DF26EF200099B11 /* gnu-interp.c */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "gnu-interp.c"; path = "/Users/johnmci/Work In Progress/squeak Bugs/unixcompiletoomanyinstructions]/memoryAllocationNotes/gnu-interp.c"; sourceTree = "<absolute>"; }; 94F5C25F0DF42C7600099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1930DF26EF200099B11 /* gnu-interp.c */; name = "gnu-interp.c: 5409"; rLen = 7; rLoc = 161001; rType = 0; vrLen = 1782; vrLoc = 160256; }; 94F5C2600DF42C7600099B11 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5C1910DF26EF200099B11 /* gnu-interp.c */; name = "gnu-interp.c: 5916"; rLen = 7; rLoc = 193171; rType = 0; vrLen = 1899; vrLoc = 192393; }; 94F5F29110BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178F10B73A3800F69A71 /* SqueakInterpreterEventSensor.h */; name = "SqueakInterpreterEventSensor.h: 10"; rLen = 8; rLoc = 322; rType = 0; vrLen = 461; vrLoc = 0; }; 94F5F29210BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F29310BC518B00847EEE /* macXCanvas.m */; name = "macXCanvas.m: 174"; rLen = 8; rLoc = 3716; rType = 0; vrLen = 1886; vrLoc = 3759; }; 94F5F29310BC518B00847EEE /* macXCanvas.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = macXCanvas.m; path = "/Users/johnmci/Work In Progress/cincom/VWSourceCode/721/src/plat/macXCanvas.m"; sourceTree = "<absolute>"; }; 94F5F29410BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94D7178010B73A3800F69A71 /* SqueakInterpreterEventSensor.m */; name = "SqueakInterpreterEventSensor.m: 40"; rLen = 8; rLoc = 1108; rType = 0; vrLen = 1744; vrLoc = 0; }; 94F5F29510BC518B00847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F29610BC518B00847EEE /* ShellView.m */; name = "ShellView.m: 121"; rLen = 8; rLoc = 4069; rType = 0; vrLen = 2026; vrLoc = 3111; }; 94F5F29610BC518B00847EEE /* ShellView.m */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ShellView.m; path = "/Users/johnmci/Work In Progress/smalltalk/FScriptSources-20031020/FScript/FScriptFramework/ShellView.m"; sourceTree = "<absolute>"; }; 94F5F2A810BC539700847EEE /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F5F2A910BC539700847EEE /* NSSet.h */; name = "NSSet.h: 58"; rLen = 69; rLoc = 2031; rType = 0; vrLen = 1982; vrLoc = 721; }; 94F5F2A910BC539700847EEE /* NSSet.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSet.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSSet.h; sourceTree = "<absolute>"; }; 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1036, 652}}"; sepNavSelRange = "{1834, 26}"; sepNavVisRange = "{0, 2025}"; sepNavWindowFrame = "{{896, 50}, {1017, 978}}"; }; }; 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {831, 1443}}"; sepNavSelRange = "{2332, 0}"; sepNavVisRange = "{1214, 2389}"; sepNavWindowFrame = "{{15, 8}, {1012, 1015}}"; }; }; 94F89AED10B497F400556475 /* NSResponder.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSResponder.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSResponder.h; sourceTree = "<absolute>"; }; 94F89AFE10B4997900556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89AFF10B4997900556475 /* IOLLEvent.h */; name = "IOLLEvent.h: 384"; rLen = 79; rLoc = 14824; rType = 0; vrLen = 2433; vrLoc = 0; }; 94F89AFF10B4997900556475 /* IOLLEvent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IOLLEvent.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/IOKit.framework/Versions/A/Headers/hidsystem/IOLLEvent.h; sourceTree = "<absolute>"; }; 94F89BDE10B4B77400556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89BDF10B4B77400556475 /* CGBase.h */; name = "CGBase.h: 105"; rLen = 30; rLoc = 2998; rType = 0; vrLen = 1747; vrLoc = 1331; }; 94F89BDF10B4B77400556475 /* CGBase.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CGBase.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGBase.h; sourceTree = "<absolute>"; }; 94F89BE010B4B77400556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94BCAEDF10ACAE2500F87527 /* NSValue.h */; name = "NSValue.h: 52"; rLen = 27; rLoc = 1223; rType = 0; vrLen = 1478; vrLoc = 0; }; 94F89C5A10B4BF2800556475 /* NSRunLoop.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSRunLoop.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRunLoop.h; sourceTree = "<absolute>"; }; 94F89C9110B4C0B800556475 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94F89C9210B4C0B800556475 /* NSTimer.h */; name = "NSTimer.h: 14"; rLen = 30; rLoc = 564; rType = 0; vrLen = 1132; vrLoc = 0; }; 94F89C9210B4C0B800556475 /* NSTimer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSTimer.h; path = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSTimer.h; sourceTree = "<absolute>"; }; 94F8E42E0DE6129D003F4F53 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 94A0EBB20DE608350071C8B9 /* squeakAudioVideoPipeLineSignalInterface.c */; name = "squeakAudioVideoPipeLineSignalInterface.c: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 2018; vrLoc = 0; }; 94FE53951230323500BA17E1 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */; name = "sqSqueakOSXApplication.h: 58"; rLen = 0; rLoc = 2392; rType = 0; vrLen = 1496; vrLoc = 918; }; 94FFF7A40EBE2B9C00C69C79 /* SqueakV39.sources */ = { uiCtxt = { sepNavFolds = "{\n c = (\n {\n l = \"123>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\t\\n\\tself should: [ self compile: '<foo bar>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo 1>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo bar zork>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo bar 1>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\t\\nself should: [ self compile: '<foo: bar:>' selector: #zork ] raise: SyntaxErrorNotification.\\n\\tself should: [ self compile: '<foo: #bar: zork:>' selector: #zork ] raise: SyntaxErrorNotification.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileNumber\\n\\tself assertPragma: 'foo: 123' givesKeyword: #foo: arguments: #( 123 ).\\n\\tself assertPragma: 'foo: -123' givesKeyword: #foo: arguments: #( -123 ).\\n\\tself assertPragma: 'foo: 12.3' givesKeyword: #foo: arguments: #( 12.3 ).\\n\\tself assertPragma: 'foo: -12.3' givesKeyword: #foo: arguments: #( -12.3 ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileString\\n\\tself assertPragma: 'foo: ''''' givesKeyword: #foo: arguments: #( '' ).\\n\\tself assertPragma: 'foo: ''bar''' givesKeyword: #foo: arguments: #( 'bar' ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 1/20/2006 02:25'!\\ntestCompileSymbol\\n\\tself assertPragma: 'foo: #bar' givesKeyword: #foo: arguments: #( bar ).\\n\\tself assertPragma: 'foo: #bar:' givesKeyword: #foo: arguments: #( bar: ).\\n\\tself assertPragma: 'foo: #bar:zork:' givesKeyword: #foo: arguments: #( bar:zork: ).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 7/3/2006 15:00'!\\ntestCompileTemps\\n\\t\\\"Pragmas should be placeable before and after temps.\\\"\\n\\t\\n\\tself \\n\\t\\tshouldnt: [\\n\\t\\t\\tself assert: (self compile: '| temps | <foo>' selector: #zork) \\n\\t\\t\\t\\tpragmas notEmpty ]\\n\\t\\traise: SyntaxErrorNotification.\\n\\tself \\n\\t\\tshouldnt: [\\n\\t\\t\\tself assert: (self compile: '<foo> | temps |' selector: #zork) \\n\\t\\t\\t\\tpragmas notEmpty ]\\n\\t\\traise: SyntaxErrorNotification.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-compiler' stamp: 'lr 2/6/2006 21:04'!\\ntestCompileValue\\n\\tself assertPragma: 'foo: true' givesKeyword: #foo: arguments: #( true ).\\n\\tself assertPragma: 'foo: false' givesKeyword: #foo: arguments: #( false ).\\n\\tself assertPragma: 'foo: nil' givesKeyword: #foo: arguments: #( nil ).\\n\\t\\n\\tself assertPragma: 'foo: String' givesKeyword: #foo: arguments: { String }.\\n\\tself assertPragma: 'foo: Pragma' givesKeyword: #foo: arguments: { Pragma }.! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'lr 1/20/2006 07:54'!\\ntestMethod\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma method == (self class >> #bar).! !\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'md 2/18/2006 19:59'!\\ntestMethodClass\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma methodClass == self class.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-method' stamp: 'lr 1/20/2006 07:54'!\\ntestSelector\\n\\t| pragma |\\n\\tpragma := self pragma: 'foo' selector: #bar.\\n\\tself assert: pragma selector == #bar.! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-compiled' stamp: 'lr 2/6/2006 21:03'!\\ntestNoPragma\\n\\t| method |\\n\\tmethod := self compile: '' selector: #foo.\\n\\tself assert: method pragmas = #().! !\\n\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:31'!\\ntestPrimitiveIndexed1\\n\\t\\\"This test useses the #instVarAt: primitive.\\\"\\n\\t\\n\\tself compile: '<primitive: 74> ^ #inst' selector: #inst.\\n\\tself assert: self inst = #inst.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:31'!\\ntestPrimitiveIndexed2\\n\\t\\\"This test useses the #asOop primitive.\\\"\\n\\n\\tself compile: '<primitive: 75> ^ #oop' selector: #oop.\\n\\tself assert: self oop = self asOop.! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:42'!\\ntestPrimitiveNamed1\\n\\t\\\"This test useses the #primitiveDirectoryLookup primitive.\\\"\\n\\n\\tself compile: '<primitive: ''primitiveDirectoryLookup'' module: ''FilePlugin''> ^ #lookup' selector: #lookup.\\n\\tself assert: self lookup = #lookup.\\n\\t\\n! !\\n\\n!MethodPragmaTest methodsFor: 'testing-primitives' stamp: 'lr 1/20/2006 02:41'!\\ntestPrimitiveNamed2\\n\\t\\\"This test useses the #primPathNameDelimiter primitive.\\\"\\n\\n\\tself compile: '<primitive: ''primitiveDirectoryDelimitor'' module: ''FilePlugin''> ^ #delim' selector: #delim.\\n\\tself assert: self delim = FileDirectory primPathNameDelimiter.\\n\\t\\n! !\\nObject subclass: #MethodProperties\\n\\tinstanceVariableNames: 'properties pragmas selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Methods'!\\n!MethodProperties commentStamp: 'lr 2/6/2006 19:31' prior: 0!\\nI am class holding state for compiled methods. All my instance variables should be actually part of the CompiledMethod itself, but the current implementation of the VM doesn't allow this.\\n\\nI am a compact class and optimized for size and speed, since every CompiledMethod points onto an instance of myself. I am mostly polymorphic to the protocol of an identity-dictionary, so that key-value pairs can be easily stored and retreived without the need to add new variables. However keep in mind that instantiating a dictionary consumes much more memory than adding an instance-variable, so it might be clever to add a new variable if the property is going to be used by every compiled method.!\\n\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'lr 2/6/2006 19:11'!\\npragmas\\n\\t^ pragmas! !\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!\\nselector\\n\\t^selector! !\\n\\n!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!\\nselector: aSymbol\\n\\tselector := aSymbol! !\\n\\n\\n!MethodProperties methodsFor: 'initialization' stamp: 'lr 2/6/2006 19:12'!\\ninitialize\\n\\tsuper initialize.\\n\\tpragmas := #().! !\\n\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:04'!\\nat: aKey\\n\\t\\\"Answer the property value associated with aKey.\\\"\\n\\t\\n\\t^ self at: aKey ifAbsent: [ self error: 'Property not found' ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:47'!\\nat: aKey ifAbsentPut: aBlock\\n\\t\\\"Answer the property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value.\\\"\\n\\t\\n\\t^ self at: aKey ifAbsent: [ self at: aKey put: aBlock value ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!\\nat: aKey ifAbsent: aBlock\\n\\t\\\"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock.\\\"\\n\\t\\n\\tproperties isNil ifTrue: [ ^ aBlock value ].\\n\\t^ properties at: aKey ifAbsent: aBlock.! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:06'!\\nat: aKey put: anObject\\n\\t\\\"Set the property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject.\\\"\\n\\n\\tproperties ifNil: [ properties := IdentityDictionary new ].\\n\\t^ properties at: aKey put: anObject.! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:11'!\\nincludesKey: aKey\\n\\t\\\"Test if the property aKey is present.\\\"\\n\\t\\n\\t^ properties notNil and: [ properties includesKey: aKey ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:48'!\\nremoveKey: aKey\\n\\t\\\"Remove the property with aKey. Answer the property or raise an error if aKey isn't found.\\\"\\n\\t\\n\\t^ self removeKey: aKey ifAbsent: [ self error: 'Property not found' ].! !\\n\\n!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!\\nremoveKey: aKey ifAbsent: aBlock\\n\\t\\\"Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock.\\\"\\n\\t\\n\\t| answer |\\n\\tproperties isNil ifTrue: [ ^ aBlock value ].\\n\\tanswer := properties removeKey: aKey ifAbsent: aBlock.\\n\\tproperties isEmpty ifTrue: [ properties := nil ].\\n\\t^ answer.! !\\n\\n\\n!MethodProperties methodsFor: 'private' stamp: 'lr 2/6/2006 20:36'!\\naddPragma: aPragma\\n\\tpragmas := pragmas copyWith: aPragma.! !\\n\\n\\n!MethodProperties methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!\\nisMethodProperties\\n\\t^true! !\\n\\n\\n!MethodProperties methodsFor: 'copying' stamp: 'md 3/1/2006 15:30'!\\npostCopy\\n\\tproperties := properties copy.\\n\\tpragmas := pragmas copy.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMethodProperties class\\n\\tinstanceVariableNames: ''!\\n\\n!MethodProperties class methodsFor: 'class initialization' stamp: 'lr 2/6/2006 22:06'!\\ninitialize\\n\\tself becomeCompact.! !\\nTestCase subclass: #MethodPropertiesTest\\n\\tinstanceVariableNames: 'method'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Methods'!\\n\\n!MethodPropertiesTest methodsFor: 'private' stamp: 'lr 2/6/2006 20:43'!\\npropertyDictionaryFor: aMethod\\n\\t^ aMethod properties instVarNamed: 'properties'.! !\\n\\n\\n!MethodPropertiesTest methodsFor: 'running' stamp: 'lr 1/20/2006 19:16'!\\nsetUp\\n\\tmethod := Object >> #halt.! !\\n\\n!MethodPropertiesTest methodsFor: 'running' stamp: 'lr 1/20/2006 19:20'!\\ntearDown\\n\\tObject recompile: #halt from: Object.! !\\n\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'kwl 7/26/2006 11:41'!\\ntestAllMethodsHaveMethodClass\\n\\tSmalltalk garbageCollect.\\n\\tself assert: (CompiledMethod allInstances\\n\\t\\t\\treject: [:cm | cm literals last isVariableBinding\\n\\t\\t\\t\\t\\tand: [cm literals last value isBehavior\\n\\t\\t\\t\\t\\t\\t\\tor: [cm literals last value isTrait]]]) isEmpty\\n\\t\\t\\tdescription: 'CompiledMethods must have methodClass literal'! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'kwl 7/26/2006 11:40'!\\ntestAllMethodsHaveNewPropertyFormat\\n\\tSmalltalk garbageCollect.\\n\\tself assert: (CompiledMethod allInstances\\n\\t\\t\\treject: [:cm | cm hasNewPropertyFormat]) isEmpty\\n\\t\\tdescription: 'CompiledMethods must have new property format'! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:21'!\\ntestAt\\n\\tself should: [ method properties at: #zork ] raise: Error.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself assert: (method properties at: #zork) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtIfAbsent\\n\\tself assert: (method properties at: #zork ifAbsent: [ 'hello' ]) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 'hi'.\\n\\tself assert: (method properties at: #zork ifAbsent: [ 'hello' ]) = 'hi'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtIfAbsentPut\\n\\tself assert: (method properties at: #zork ifAbsentPut: [ 'hello' ]) = 'hello'.\\n\\tself assert: (method properties at: #zork ifAbsentPut: [ 'hi' ]) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestAtPut\\n\\tself assert: (method properties at: #zork put: 'hello') = 'hello'.\\n\\tself assert: (method properties at: #zork) = 'hello'.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:19'!\\ntestIncludesKey\\n\\tself deny: (method properties includesKey: #zork).\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tmethod properties at: #zork put: 123.\\n\\tself assert: (method properties includesKey: #zork).! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestRemoveKey\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself should: [ method properties removeKey: #halt ] raise: Error.\\n\\tself assert: (method properties removeKey: #zork) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tself should: [ method properties removeKey: #zork ] raise: Error.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.! !\\n\\n!MethodPropertiesTest methodsFor: 'testing' stamp: 'lr 2/6/2006 22:18'!\\ntestRemoveKeyifAbsent\\n\\tmethod properties at: #zork put: 'hello'.\\n\\tself assert: (method properties removeKey: #halt ifAbsent: [ 'hi' ]) = 'hi'.\\n\\tself assert: (method properties removeKey: #zork ifAbsent: [ 'hi' ]) = 'hello'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.\\n\\tself should: (method properties removeKey: #zork ifAbsent: [ 'hi' ]) = 'hi'.\\n\\tself assert: (self propertyDictionaryFor: method) isNil.! !\\nObject subclass: #MethodReference\\n\\tinstanceVariableNames: 'classSymbol classIsMeta methodSymbol stringVersion'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!MethodReference commentStamp: 'tlk 5/9/2006 18:43' prior: 0!\\nA MethodReference is is a lightweight proxy for a CompiledMethod. Has methods for pointed to the CompileMethod's source statements, byte codes. Is heavily used my Tools.\\n\\nInstance Variables\\n\\tclassIsMeta:\\t\\t Boolean class vs. instance\\n\\tclassSymbol:\\t\\tSymbol for method's class (without class keyword if meta)\\n\\tmethodSymbol:\\t\\tSymbol for method's selector\\n\\tstringVersion:\\t\\t'Class>>selector:' format\\n\\n!\\n\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/8/2003 11:54'!\\nhash\\n\\t\\\"Answer a SmallInteger whose value is related to the receiver's \\n\\tidentity.\\\"\\n\\t^ (self species hash bitXor: self classSymbol hash)\\n\\t\\tbitXor: self methodSymbol hash! !\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'RAA 5/28/2001 11:56'!\\n<= anotherMethodReference\\n\\n\\tclassSymbol < anotherMethodReference classSymbol ifTrue: [^true].\\n\\tclassSymbol > anotherMethodReference classSymbol ifTrue: [^false].\\n\\tclassIsMeta = anotherMethodReference classIsMeta ifFalse: [^classIsMeta not].\\n\\t^methodSymbol <= anotherMethodReference methodSymbol\\n! !\\n\\n!MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/7/2003 13:18'!\\n= anotherMethodReference \\n\\t\\\"Answer whether the receiver and the argument represent the \\n\\tsame object.\\\"\\n\\t^ self species == anotherMethodReference species\\n\\t\\tand: [self classSymbol = anotherMethodReference classSymbol]\\n\\t\\tand: [self classIsMeta = anotherMethodReference classIsMeta]\\n\\t\\tand: [self methodSymbol = anotherMethodReference methodSymbol]! !\\n\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 06:19'!\\nasStringOrText\\n\\n\\t^stringVersion! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:11'!\\nclassIsMeta\\n\\n\\t^classIsMeta! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'!\\nclassSymbol\\n\\n\\t^classSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'md 8/27/2005 17:17'!\\nisValid\\n\\t\\\"Answer whether the receiver represents a current selector or Comment\\\"\\n\\n\\t| aClass |\\n\\tmethodSymbol isDoIt ifTrue: [^ false].\\n\\t(aClass _ self actualClass) ifNil: [^ false].\\n\\t^ (aClass includesSelector: methodSymbol) or:\\n\\t\\t[methodSymbol == #Comment]! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'!\\nmethodSymbol\\n\\n\\t^methodSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'sw 11/5/2001 00:53'!\\nprintOn: aStream\\n\\t\\\"Print the receiver on a stream\\\"\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' ', self actualClass name, ' >> ', methodSymbol! !\\n\\n!MethodReference methodsFor: 'queries' stamp: 'sr 6/4/2004 01:55'!\\nsourceString\\n\\t^ (self actualClass sourceCodeAt: self methodSymbol) asString! !\\n\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 07:34'!\\nsetClassAndSelectorIn: csBlock\\n\\n\\t^csBlock value: self actualClass value: methodSymbol! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 06:04'!\\nsetClassSymbol: classSym classIsMeta: isMeta methodSymbol: methodSym stringVersion: aString \\n\\n\\tclassSymbol _ classSym.\\n\\tclassIsMeta _ isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aString.! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 08:06'!\\nsetClass: aClass methodSymbol: methodSym stringVersion: aString \\n\\n\\tclassSymbol _ aClass theNonMetaClass name.\\n\\tclassIsMeta _ aClass isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aString.! !\\n\\n!MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 11:34'!\\nsetStandardClass: aClass methodSymbol: methodSym\\n\\n\\tclassSymbol _ aClass theNonMetaClass name.\\n\\tclassIsMeta _ aClass isMeta.\\n\\tmethodSymbol _ methodSym.\\n\\tstringVersion _ aClass name , ' ' , methodSym.! !\\n\\n\\n!MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'!\\nstringVersion\\n\\n\\t^stringVersion! !\\n\\n!MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'!\\nstringVersion: aString\\n\\n\\tstringVersion _ aString! !\\n\\n\\n!MethodReference methodsFor: '*fixUnderscores' stamp: 'cmm 5/1/2006 19:38'!\\nfixUnderscores\\n\\t\\\"Replace underscores with :=. Answer true if fixed or no fix necessary, false if manual fix required\\\"\\n\\n\\t| src cm ts |\\n\\t\\\"Check if we do need to do anything\\\"\\n\\tsrc := self actualClass sourceCodeAt: methodSymbol.\\n\\t(src includes: $_) ifFalse: [^true].\\n\\n\\t\\\"Chicken out if there is a literal underscore\\\"\\n\\tcm := self actualClass compiledMethodAt: methodSymbol.\\n\\t(cm hasLiteralSuchThat: [:lit | \\n\\t\\tlit = $_ or: [lit isString and: [lit includes: $_]]]) ifTrue: [^false].\\n\\n\\t\\\"Otherwise, replace underscores with :=\\\"\\n\\tsrc := src copyReplaceAll: '_' with: ':='.\\n\\tts := self timeStamp.\\n\\tts = '' ifTrue: [ts := nil].\\n\\tself actualClass \\n\\t\\tcompile: src\\n\\t\\tclassified: ClassOrganizer default\\n\\t\\twithStamp: ts \\n\\t\\tnotifying: nil.\\n\\n\\t^true\\n! !\\n\\n\\n!MethodReference methodsFor: '*Kernel-Traits' stamp: 'md 3/3/2006 09:25'!\\nactualClass \\n\\n\\t| actualClass |\\n\\n\\tactualClass _ Smalltalk at: classSymbol ifAbsent: [^nil].\\n\\tclassIsMeta ifTrue: [^actualClass classSide].\\n\\t^actualClass\\n\\n! !\\n\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:55'!\\nasMethodDefinition\\n\\t^ MCMethodDefinition forMethodReference: self! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ncategory\\n\\t^ self actualClass organization categoryOfElement: methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ncompiledMethod\\n\\t^ self actualClass compiledMethodAt: methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'al 10/9/2005 20:05'!\\nisLocalSelector\\n\\t^self actualClass\\n\\t\\tincludesLocalSelector: self methodSymbol! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:59'!\\nsource\\n\\t^ (self actualClass sourceCodeAt: methodSymbol) asString withSqueakLineEndings! !\\n\\n!MethodReference methodsFor: '*monticello' stamp: 'ab 8/22/2003 17:58'!\\ntimeStamp\\n\\t^ self compiledMethod timeStamp! !\\n\\n\\n!MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'!\\nsourceCode\\n\\t^ self actualClass sourceCodeAt: methodSymbol! !\\n\\n\\n!MethodReference methodsFor: '*OB-Standard' stamp: 'dvf 8/19/2005 17:16'!\\nasNode\\n\\t^OBMethodNode on: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMethodReference class\\n\\tinstanceVariableNames: ''!\\n\\n!MethodReference class methodsFor: 'instance creation' stamp: 'ab 2/6/2005 16:22'!\\nclass: aClass selector: aSelector\\n\\t^ self new setStandardClass: aClass methodSymbol: aSelector! !\\nClassTestCase subclass: #MethodReferenceTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Browser-Tests'!\\n\\n!MethodReferenceTest methodsFor: 'Running' stamp: 'sd 11/20/2005 21:27'!\\ntestEquals\\n\\t| aMethodReference anotherMethodReference |\\n\\taMethodReference := MethodReference new.\\n\\tanotherMethodReference := MethodReference new.\\n\\t\\\" \\n\\ttwo fresh instances should be equals between them\\\"\\n\\tself\\n\\t\\tshould: [aMethodReference = anotherMethodReference].\\n\\tself\\n\\t\\tshould: [aMethodReference hash = anotherMethodReference hash].\\n\\t\\\" \\n\\ttwo instances representing the same method (same class and \\n\\tsame selector) should be equals\\\"\\n\\taMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tanotherMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tself\\n\\t\\tshould: [aMethodReference = anotherMethodReference].\\n\\tself\\n\\t\\tshould: [aMethodReference hash = anotherMethodReference hash] ! !\\n\\n!MethodReferenceTest methodsFor: 'Running' stamp: 'sd 11/20/2005 21:27'!\\ntestNotEquals\\n\\t| aMethodReference anotherMethodReference |\\n\\taMethodReference := MethodReference new.\\n\\tanotherMethodReference := MethodReference new.\\n\\t\\\"\\\"\\n\\taMethodReference setStandardClass: String methodSymbol: #foo.\\n\\tanotherMethodReference setStandardClass: String class methodSymbol: #foo.\\n\\t\\\" \\n\\tdifferente classes, same selector -> no more equals\\\"\\n\\tself\\n\\t\\tshouldnt: [aMethodReference = anotherMethodReference].\\n\\t\\\" \\n\\tsame classes, diferente selector -> no more equals\\\"\\n\\tanotherMethodReference setStandardClass: String methodSymbol: #bar.\\n\\tself\\n\\t\\tshouldnt: [aMethodReference = anotherMethodReference] ! !\\nParseNode subclass: #MethodTempsNode\\n\\tinstanceVariableNames: 'temporaries'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-ParseNodes'!\\nMethodInterface subclass: #MethodWithInterface\\n\\tinstanceVariableNames: 'playerClass'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n!MethodWithInterface commentStamp: '<historical>' prior: 0!\\nA MethodInterface bound to an actual class.\\n\\n\\tselector\\t\\t\\t\\t\\tA symbol - the selector being described\\n\\targumentSpecifications\\tA list of specifications for the formal arguments of the method\\n\\tresultSpecification \\t\\tA characterization of the return value of the method\\n\\tuserLevel\\t\\t\\t\\t\\n\\tattributeKeywords\\t\\tA list of symbols, comprising keywords that the user wishes to\\n\\t\\t\\t\\t\\t\\t\\t\\tassociate with this method\\n\\tdefaultStatus\\t\\t\\tThe status to apply to new instances of the class by default\\n\\tdefaultFiresPerTick\\t\\tHow many fires per tick, by default, should be allowed if ticking.\\n\\tplayerClass\\t\\t\\t\\tThe actual class with which this script is associated!\\n\\n\\n!MethodWithInterface methodsFor: 'access' stamp: 'sw 3/28/2001 16:25'!\\nplayerClass\\n\\t\\\"Answer the playerClass associated with the receiver. Note: fixes up cases where the playerClass slot was a Playerxxx object because of an earlier bug\\\"\\n\\n\\t^ (playerClass isKindOf: Class)\\n\\t\\tifTrue:\\n\\t\\t\\t[playerClass]\\n\\t\\tifFalse:\\n\\t\\t\\t[playerClass _ playerClass class]! !\\n\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 1/30/2001 11:37'!\\nconvertFromUserScript: aUserScript\\n\\t\\\"The argument represents an old UserScript object. convert it over\\\"\\n\\n\\tdefaultStatus _ aUserScript status.! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 1/26/2001 16:44'!\\ninitialize\\n\\t\\\"Initialize the receiver by setting its inst vars to default values\\\"\\n\\n\\tsuper initialize.\\n\\tdefaultStatus _ #normal! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 2/20/2001 03:29'!\\nisTextuallyCoded\\n\\t\\\"Answer whether the receiver is in a textually-coded state. A leftover from much earlier times, this is a vacuous backstop\\\"\\n\\n\\t^ false! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'sw 9/12/2001 11:59'!\\nplayerClass: aPlayerClass selector: aSelector\\n\\t\\\"Set the playerClass and selector of the receiver\\\"\\n\\n\\tplayerClass _ aPlayerClass.\\n\\tselector _ aSelector.! !\\n\\n!MethodWithInterface methodsFor: 'initialization' stamp: 'nk 7/2/2004 07:18'!\\nstatus\\n\\t^defaultStatus\\n! !\\n\\n\\n!MethodWithInterface methodsFor: 'rename' stamp: 'sw 2/17/2001 04:10'!\\nokayToRename\\n\\t\\\"Answer whether the receiver is in a state to be renamed.\\\"\\n\\n\\t^ true! !\\n\\n!MethodWithInterface methodsFor: 'rename' stamp: 'sw 3/11/2003 00:01'!\\nrenameScript: newSelector fromPlayer: aPlayer\\n\\n\\t\\\"The receiver's selector has changed to the new selector. Get various things right, including the physical appearance of any Scriptor open on this method\\\"\\n\\n\\n\\n\\tself allScriptEditors do:\\n\\n\\t\\t[:aScriptEditor | aScriptEditor renameScriptTo: newSelector].\\n\\n\\n\\n\\t(selector numArgs = 0 and: [newSelector numArgs = 1])\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self argumentVariables: (OrderedCollection with:\\n\\n\\t\\t\\t\\t(Variable new name: #parameter type: #Number))].\\n\\n\\t(selector numArgs = 1 and: [newSelector numArgs = 0])\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self argumentVariables: OrderedCollection new].\\n\\n\\n\\n\\tselector _ newSelector asSymbol.\\n\\n\\tself bringUpToDate.\\n\\n\\tself playerClass atSelector: selector putScript: self.\\n\\n\\tself allScriptActivationButtons do:\\n\\n\\t\\t[:aButton | aButton bringUpToDate].\\n\\n\\n\\n! !\\n\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/10/2003 23:58'!\\nallScriptActivationButtons\\n\\n\\t\\\"Answer all the script-activation buttons that exist for this interface\\\"\\n\\n\\n\\n\\t^ ScriptActivationButton allInstances select: \\n\\n\\t\\t[:aButton | aButton uniclassScript == self]! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/28/2001 16:26'!\\nallScriptEditors\\n\\t\\\"Answer all the script editors that exist for the class and selector of this interface\\\"\\n\\n\\t^ ScriptEditorMorph allInstances select: \\n\\t\\t[:aScriptEditor | aScriptEditor playerScripted class == self playerClass and:\\n\\t\\t\\t[aScriptEditor scriptName == selector]]! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 2/17/2001 03:28'!\\ncurrentScriptEditor: anEditor\\n\\t\\\"Set the receiver's currentScriptEditor as indicated, if I care. MethodWithInterface does not care, since it does not hold on to a ScriptEditor. A subclass of mine, however does, or did, care\\\"! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 3/28/2001 16:26'!\\ninstantiatedScriptEditorForPlayer: aPlayer\\n\\t\\\"Return a new script editor for the player and selector\\\"\\n\\n\\t| aScriptEditor |\\n\\taScriptEditor _ (self playerClass includesSelector: selector) \\n\\t\\t\\tifTrue: [ScriptEditorMorph new \\n\\t\\t\\t\\tfromExistingMethod: selector \\n\\t\\t\\t\\tforPlayer: aPlayer]\\n\\t\\t\\tifFalse: [ScriptEditorMorph new\\n\\t\\t\\t\\tsetMorph: aPlayer costume\\n\\t\\t\\t\\tscriptName: selector].\\n\\t\\tdefaultStatus == #ticking ifTrue:\\n\\t\\t\\t[aPlayer costume arrangeToStartStepping].\\n\\t\\n\\t^ aScriptEditor! !\\n\\n!MethodWithInterface methodsFor: 'script editor' stamp: 'sw 7/28/2001 01:00'!\\nrecompileScriptFromTilesUnlessTextuallyCoded\\n\\t\\\"Recompile Script From Tiles Unless Textually Coded. For the universal-tiles MethodWithInterface case, this is moot. Used only in support of a reintegration of Open-school forked projects from Sept 2000 in 7/01\\\"! !\\n\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 3/28/2001 16:26'!\\nbringUpToDate\\n\\t\\\"Bring all scriptors related to this method up to date. Note that this will not change the senders of this method if the selector changed -- that's something still ahead.\\\"\\n\\n\\t(ScriptEditorMorph allInstances select:\\n\\t\\t[:m | (m playerScripted isMemberOf: self playerClass) and: [m scriptName == selector]])\\n\\t\\t\\tdo:\\n\\t\\t\\t\\t[:m | m bringUpToDate]! !\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 2/20/2001 03:43'!\\nrevertToLastSavedTileVersionFor: anEditor\\n\\t\\\"revert to the last saved tile version. Only for universal tiles.\\\"\\n\\n\\tanEditor removeAllButFirstSubmorph.\\n\\tanEditor insertUniversalTiles.\\n\\tanEditor showingMethodPane: false! !\\n\\n!MethodWithInterface methodsFor: 'updating' stamp: 'sw 2/20/2001 03:41'!\\nsaveScriptVersion: timeStamp\\n\\t\\\"Save the tile script version if I do that sort of thing\\\"! !\\nAlignmentMorph subclass: #MidiInputMorph\\n\\tinstanceVariableNames: 'midiPortNumber midiSynth instrumentSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Scores'!\\n!MidiInputMorph commentStamp: '<historical>' prior: 0!\\nI am the user interface for a simple software MIDI synthesizer that is driven by external MIDI input. I come with controls for a single MIDI channel (channel 1), but allow channel controls for additional MIDI channels to be added by the user. The volume, pan, and instrument of each channel can be controlled independently.\\n!\\n\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naddChannel\\n\\t\\\"Add a set of controls for another channel. Prompt the user for the channel number.\\\"\\n\\n\\t| menu existingChannels newChannel |\\n\\tmenu := CustomMenu new.\\n\\texistingChannels := Set new.\\n\\t1 to: 16 do: [:ch | (instrumentSelector at: ch) ifNotNil: [existingChannels add: ch]].\\n\\t1 to: 16 do: [:ch |\\n\\t\\t(existingChannels includes: ch) ifFalse: [\\n\\t\\t\\tmenu add: ch printString action: ch]].\\n\\tnewChannel := menu startUp.\\n\\tnewChannel ifNotNil: [self addChannelControlsFor: newChannel].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naddChannelControlsFor: channelIndex\\n\\n\\t| r divider col |\\n\\tr := self makeRow\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tr addMorphBack: (self channelNumAndMuteButtonFor: channelIndex).\\n\\tr addMorphBack: (Morph new extent: 10@5; color: color). \\\"spacer\\\"\\n\\tr addMorphBack: (self panAndVolControlsFor: channelIndex).\\n\\n\\tdivider := AlignmentMorph new\\n\\t\\textent: 10@1;\\n\\t\\tborderWidth: 1;\\n\\t\\tlayoutInset: 0;\\n\\t\\tborderColor: #raised;\\n\\t\\tcolor: color;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #rigid.\\n\\n\\tcol := self lastSubmorph.\\n\\tcol addMorphBack: divider.\\n\\tcol addMorphBack: r.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'gm 2/28/2003 00:00'!\\natChannel: channelIndex from: aPopUpChoice selectInstrument: selection \\n\\t| oldSnd name snd instSelector |\\n\\toldSnd := midiSynth instrumentForChannel: channelIndex.\\n\\t(selection beginsWith: 'edit ') \\n\\t\\tifTrue: \\n\\t\\t\\t[name := selection copyFrom: 6 to: selection size.\\n\\t\\t\\taPopUpChoice contentsClipped: name.\\n\\t\\t\\t(oldSnd isKindOf: FMSound) | (oldSnd isKindOf: LoopedSampledSound) \\n\\t\\t\\t\\tifTrue: [EnvelopeEditorMorph openOn: oldSnd title: name].\\n\\t\\t\\t(oldSnd isKindOf: SampledInstrument) \\n\\t\\t\\t\\tifTrue: [EnvelopeEditorMorph openOn: oldSnd allNotes first title: name].\\n\\t\\t\\t^self].\\n\\tsnd := nil.\\n\\t1 to: instrumentSelector size\\n\\t\\tdo: \\n\\t\\t\\t[:i | \\n\\t\\t\\t(channelIndex ~= i and: \\n\\t\\t\\t\\t\\t[(instSelector := instrumentSelector at: i) notNil \\n\\t\\t\\t\\t\\t\\tand: [selection = instSelector contents]]) \\n\\t\\t\\t\\tifTrue: [snd := midiSynth instrumentForChannel: i]].\\t\\\"use existing instrument prototype\\\"\\n\\tsnd ifNil: \\n\\t\\t\\t[snd := (selection = 'clink' \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[(SampledSound samples: SampledSound coffeeCupClink samplingRate: 11025)]\\n\\t\\t\\t\\t\\t\\tifFalse: [(AbstractSound soundNamed: selection) ])copy ].\\n\\tmidiSynth instrumentForChannel: channelIndex put: snd.\\n\\t(instrumentSelector at: channelIndex) contentsClipped: selection! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nchannelNumAndMuteButtonFor: channelIndex\\n\\n\\t| muteButton instSelector r |\\n\\tmuteButton := SimpleSwitchMorph new\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\toffColor: color;\\n\\t\\tcolor: color;\\n\\t\\tlabel: 'Mute';\\n\\t\\ttarget: midiSynth;\\n\\t\\tactionSelector: #mutedForChannel:put:;\\n\\t\\targuments: (Array with: channelIndex).\\n\\tinstSelector := PopUpChoiceMorph new\\n\\t\\textent: 95@14;\\n\\t\\tcontentsClipped: 'oboe1';\\n\\t\\ttarget: self;\\n\\t\\tactionSelector: #atChannel:from:selectInstrument:;\\n\\t\\tgetItemsSelector: #instrumentChoicesForChannel:;\\n\\t\\tgetItemsArgs: (Array with: channelIndex).\\n\\tinstSelector arguments:\\n\\t\\t(Array with: channelIndex with: instSelector).\\n\\tinstrumentSelector at: channelIndex put: instSelector.\\n\\n\\tr := self makeRow\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\textent: 70@10.\\n\\tr addMorphBack:\\n\\t\\t(StringMorph\\n\\t\\t\\tcontents: channelIndex printString\\n\\t\\t\\tfont: (TextStyle default fontOfSize: 24)).\\n\\tchannelIndex < 10\\n\\t\\tifTrue: [r addMorphBack: (Morph new color: color; extent: 19@8)] \\\"spacer\\\"\\n\\t\\tifFalse: [r addMorphBack: (Morph new color: color; extent: 8@8)]. \\\"spacer\\\"\\n\\tr addMorphBack: instSelector.\\n\\tr addMorphBack: (AlignmentMorph newRow color: color). \\\"spacer\\\"\\n\\tr addMorphBack: muteButton.\\n\\t^ r\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/13/1999 07:33'!\\ncloseMIDIPort\\n\\n\\tmidiSynth isOn ifTrue: [midiSynth stopMIDITracking].\\n\\tmidiSynth closeMIDIPort.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/6/1999 07:55'!\\ndisableReverb: aBoolean\\n\\n\\taBoolean\\n\\t\\tifTrue: [SoundPlayer stopReverb]\\n\\t\\tifFalse: [SoundPlayer startReverb].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninstrumentChoicesForChannel: channelIndex\\n\\n\\t| names inst |\\n\\tnames := AbstractSound soundNames asOrderedCollection.\\n\\tnames := names collect: [:n |\\n\\t\\tinst := AbstractSound soundNamed: n.\\n\\t\\t(inst isKindOf: UnloadedSound)\\n\\t\\t\\tifTrue: [n, '(out)']\\n\\t\\t\\tifFalse: [n]].\\n\\tnames add: 'clink'.\\n\\tnames add: 'edit ', (instrumentSelector at: channelIndex) contents.\\n\\t^ names asArray\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninvokeMenu\\n\\t\\\"Invoke a menu of additonal commands.\\\"\\n\\n\\t| aMenu |\\n\\taMenu := CustomMenu new.\\n\\taMenu add: 'add channel' translated action: #addChannel.\\n\\taMenu add: 'reload instruments' translated target: AbstractSound selector: #updateScorePlayers.\\n\\tmidiSynth isOn ifFalse: [\\n\\t\\taMenu add: 'set MIDI port' translated action: #setMIDIPort.\\n\\t\\tmidiSynth midiPort\\n\\t\\t\\tifNotNil: [aMenu add: 'close MIDI port' translated action: #closeMIDIPort]].\\t\\n\\taMenu invokeOn: self defaultSelection: nil.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmakeControls\\n\\n\\t| bb r reverbSwitch onOffSwitch |\\n\\tbb := SimpleButtonMorph new\\n\\t\\ttarget: self;\\n\\t\\tborderColor: #raised;\\n\\t\\tborderWidth: 2;\\n\\t\\tcolor: color.\\n\\tr := AlignmentMorph newRow.\\n\\tr color: bb color; borderWidth: 0; layoutInset: 0.\\n\\tr hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tr addMorphBack: (\\n\\t\\tbb label: '<>';\\n\\t\\t\\tactWhen: #buttonDown;\\n\\t\\t\\tactionSelector: #invokeMenu).\\n\\tonOffSwitch := SimpleSwitchMorph new\\n\\t\\toffColor: color;\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\tborderWidth: 2;\\n\\t\\tlabel: 'On';\\n\\t\\tactionSelector: #toggleOnOff;\\n\\t\\ttarget: self;\\n\\t\\tsetSwitchState: false.\\n\\tr addMorphBack: onOffSwitch.\\n\\treverbSwitch := SimpleSwitchMorph new\\n\\t\\toffColor: color;\\n\\t\\tonColor: (Color r: 1.0 g: 0.6 b: 0.6);\\n\\t\\tborderWidth: 2;\\n\\t\\tlabel: 'Reverb Disable';\\n\\t\\tactionSelector: #disableReverb:;\\n\\t\\ttarget: self;\\n\\t\\tsetSwitchState: SoundPlayer isReverbOn not.\\n\\tr addMorphBack: reverbSwitch.\\n\\t^ r\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/9/2000 21:19'!\\nmakeRow\\n\\n\\t^ AlignmentMorph newRow\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #leftCenter;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npanAndVolControlsFor: channelIndex\\n\\n\\t| volSlider panSlider c r middleLine |\\n\\tvolSlider := SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 101@2;\\n\\t\\ttarget: midiSynth;\\n\\t\\targuments: (Array with: channelIndex);\\n\\t\\tactionSelector: #volumeForChannel:put:;\\n\\t\\tminVal: 0.0;\\n\\t\\tmaxVal: 1.0;\\n\\t\\tadjustToValue: (midiSynth volumeForChannel: channelIndex).\\n\\tpanSlider := SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 101@2;\\n\\t\\ttarget: midiSynth;\\n\\t\\targuments: (Array with: channelIndex);\\n\\t\\tactionSelector: #panForChannel:put:;\\n\\t\\tminVal: 0.0;\\n\\t\\tmaxVal: 1.0;\\t\\t\\n\\t\\tadjustToValue: (midiSynth panForChannel: channelIndex).\\n\\tc := AlignmentMorph newColumn\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #topCenter;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tmiddleLine := Morph new \\\"center indicator for pan slider\\\"\\n\\t\\tcolor: (Color r: 0.4 g: 0.4 b: 0.4);\\n\\t\\textent: 1@(panSlider height - 4);\\n\\t\\tposition: panSlider center x@(panSlider top + 2).\\n\\tpanSlider addMorphBack: middleLine.\\n\\tr := self makeRow.\\n\\tr addMorphBack: (StringMorph contents: '0').\\n\\tr addMorphBack: volSlider.\\n\\tr addMorphBack: (StringMorph contents: '10').\\n\\tc addMorphBack: r.\\n\\tr := self makeRow.\\n\\tr addMorphBack: (StringMorph contents: 'L').\\n\\tr addMorphBack: panSlider.\\n\\tr addMorphBack: (StringMorph contents: 'R').\\n\\tc addMorphBack: r.\\n\\t^ c\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsetMIDIPort\\n\\n\\t| portNum |\\n\\tportNum := SimpleMIDIPort outputPortNumFromUser.\\n\\tportNum ifNil: [^ self].\\n\\tmidiPortNumber := portNum.\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntoggleOnOff\\n\\n\\tmidiSynth isOn\\n\\t\\tifTrue: [\\n\\t\\t\\tmidiSynth stopMIDITracking]\\n\\t\\tifFalse: [\\n\\t\\t\\tmidiPortNumber ifNil: [self setMIDIPort].\\n\\t\\t\\tmidiPortNumber ifNil: [midiPortNumber := 0].\\n\\t\\t\\tmidiSynth midiPort: (SimpleMIDIPort openOnPortNumber: midiPortNumber).\\n\\t\\t\\tmidiSynth startMIDITracking].\\n! !\\n\\n!MidiInputMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nupdateInstrumentsFromLibraryExcept: soundsBeingEdited\\n\\t\\\"The instrument library has been modified. Update my instruments with the new versions from the library. Use a single instrument prototype for all parts with the same name; this allows the envelope editor to edit all the parts by changing a single sound prototype.\\\"\\n\\n\\t\\\"soundsBeingEdited is a collection of sounds being edited (by an EnvelopeEditor). If any of my instruments share one of these, then they will be left alone so as not to disturb that dynamic linkage.\\\"\\n\\n\\t| unloadPostfix myInstruments name displaysAsUnloaded isUnloaded |\\n\\tunloadPostfix := '(out)'.\\n\\tmyInstruments := Dictionary new.\\n\\t1 to: instrumentSelector size do: [:i |\\n\\t\\tname := (instrumentSelector at: i) contents.\\n\\t\\tdisplaysAsUnloaded := name endsWith: unloadPostfix.\\n\\t\\tdisplaysAsUnloaded ifTrue: [\\n\\t\\t\\tname := name copyFrom: 1 to: name size - unloadPostfix size].\\n\\t\\t(myInstruments includesKey: name) ifFalse: [\\n\\t\\t\\tmyInstruments at: name put:\\n\\t\\t\\t\\t(name = 'clink'\\n\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t(SampledSound\\n\\t\\t\\t\\t\\t\\t\\tsamples: SampledSound coffeeCupClink\\n\\t\\t\\t\\t\\t\\t\\tsamplingRate: 11025) copy]\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t(AbstractSound\\n\\t\\t\\t\\t\\t\\t\\tsoundNamed: name\\n\\t\\t\\t\\t\\t\\t\\tifAbsent: [\\n\\t\\t\\t\\t\\t\\t\\t\\t(instrumentSelector at: i) contentsClipped: 'default'.\\n\\t\\t\\t\\t\\t\\t\\t\\tFMSound default]) copy])].\\n\\t\\t(soundsBeingEdited includes: (midiSynth instrumentForChannel: i)) ifFalse:\\n\\t\\t\\t[\\\"Do not update any instrument that is currently being edited\\\"\\n\\t\\t\\tmidiSynth instrumentForChannel: i put: (myInstruments at: name)].\\n\\n\\t\\t\\\"update loaded/unloaded status in instrumentSelector if necessary\\\"\\n\\t\\tisUnloaded := (myInstruments at: name) isKindOf: UnloadedSound.\\n\\t\\t(displaysAsUnloaded and: [isUnloaded not])\\n\\t\\t\\tifTrue: [(instrumentSelector at: i) contentsClipped: name].\\n\\t\\t(displaysAsUnloaded not and: [isUnloaded])\\n\\t\\t\\tifTrue: [(instrumentSelector at: i) contentsClipped: name, unloadPostfix]].\\n! !\\n\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:38'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryLightGray! !\\n\\n!MidiInputMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself listDirection: #topToBottom;\\n\\t wrapCentering: #center;\\n\\t\\t cellPositioning: #topCenter;\\n\\t hResizing: #spaceFill;\\n\\t vResizing: #spaceFill;\\n\\t layoutInset: 3.\\n\\tmidiPortNumber := nil.\\n\\tmidiSynth := MIDISynth new.\\n\\tinstrumentSelector := Array new: 16.\\n\\tself removeAllMorphs.\\n\\tself addMorphBack: self makeControls.\\n\\tself addMorphBack: (AlignmentMorph newColumn color: color;\\n\\t\\t\\t layoutInset: 0).\\n\\tself addChannelControlsFor: 1.\\n\\tself extent: 20 @ 20! !\\nObject subclass: #MidiPrimTester\\n\\tinstanceVariableNames: 'port'\\n\\tclassVariableNames: 'CanSetClock CanUseSemaphore ClockTicksPerSec EchoOn EventsAvailable FlushDriver HasBuffer HasDurs HasInputClock Installed UseControllerCache Version'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Serial Port'!\\n!MidiPrimTester commentStamp: '<historical>' prior: 0!\\nThis class simply demonstrates and tests the MIDI primitives. MIDI applications should use Stephen Pope's MIDIPort class, which will replace this one.\\n\\nThe Macintosh, and perhaps some other platforms, can send and receive MIDI data over a serial port by using an external clock signal supplied by an external MIDI adapter to generate the correct MIDI baud rate. Typical clock speeds of such adapters are 1, 2, or 0.5 MHz. This clock speed can be specified when a MIDI port is opened. On other platforms, this clock speed parameter is ignored.\\n!\\n\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIClosePort: portNum\\n\\n\\t<primitive: 'primitiveMIDIClosePort' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetClock\\n\\n\\t<primitive: 'primitiveMIDIGetClock' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortCount\\n\\n\\t<primitive: 'primitiveMIDIGetPortCount' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortDirectionality: portNum\\n\\n\\t<primitive: 'primitiveMIDIGetPortDirectionality' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIGetPortName: portNum\\n\\n\\t<primitive: 'primitiveMIDIGetPortName' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIOpenPort: portNum readSemaIndex: readSemaIndex interfaceClockRate: interfaceClockRate\\n\\t\\\"Open the given MIDI port. If non-zero, readSemaIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Not all platforms support signalling the read semaphore. InterfaceClockRate specifies the clock rate of the external MIDI interface adaptor on Macintosh computers; it is ignored on other platforms.\\\"\\n\\n\\t<primitive: 'primitiveMIDIOpenPort' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIParameterGet: whichParameter\\n\\n\\t<primitive: 'primitiveMIDIParameterGetOrSet' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIParameterSet: whichParameter to: newValue\\n\\n\\t<primitive: 'primitiveMIDIParameterGetOrSet' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIReadPort: portNum into: byteArray\\n\\n\\t<primitive: 'primitiveMIDIRead' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n!MidiPrimTester methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimMIDIWritePort: portNum from: byteArray at: midiClockValue\\n\\n\\t<primitive: 'primitiveMIDIWrite' module: 'MIDIPlugin'>\\n\\tself primitiveFailed.\\n! !\\n\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 10:30'!\\ngetDriverParameters\\n\\t\\\"Return a string that describes this platform's MIDI parameters.\\\"\\n\\t\\\"MidiPrimTester new getDriverParameters\\\"\\n\\n\\t| s parameterNames v |\\n\\tparameterNames _ #(Installed Version HasBuffer HasDurs CanSetClock CanUseSemaphore EchoOn UseControllerCache EventsAvailable FlushDriver ClockTicksPerSec HasInputClock).\\n\\n\\ts _ WriteStream on: String new.\\n\\ts cr.\\n\\t1 to: parameterNames size do: [:i |\\n\\t\\tv _ self primMIDIParameterGet: i.\\n\\t\\ts nextPutAll: (parameterNames at: i).\\n\\t\\ts nextPutAll: ' = '.\\n\\t\\ts print: v; cr].\\n\\n\\ts nextPutAll: 'MIDI Echoing is '.\\n\\t(self canTurnOnParameter: EchoOn)\\n\\t\\tifTrue: [s nextPutAll: 'supported.'; cr]\\n\\t\\tifFalse: [s nextPutAll: 'not supported.'; cr].\\n\\n\\ts nextPutAll: 'Controller Caching is '.\\n\\t(self canTurnOnParameter: UseControllerCache)\\n\\t\\tifTrue: [s nextPutAll: 'supported.'; cr]\\n\\t\\tifFalse: [s nextPutAll: 'not supported.'; cr].\\n\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:33'!\\ngetInputForSeconds: seconds onPort: portNum\\n\\t\\\"Collect MIDI input from the given port for the given number of seconds, and answer a string describing the data read.\\\"\\n\\t\\\"MidiPrimTester new getInputForSeconds: 5 onPort: 0\\\"\\n\\n\\t| buf bufList endTime n midiStartTime s t |\\n\\t\\\"collect the data\\\"\\n\\tself openPort: portNum andDo: [\\n\\t\\tbuf _ ByteArray new: 1000.\\n\\t\\tbufList _ OrderedCollection new.\\n\\t\\tmidiStartTime _ self primMIDIGetClock.\\n\\t\\tendTime _ Time millisecondClockValue + (seconds * 1000).\\n\\t\\t[Time millisecondClockValue < endTime] whileTrue: [\\n\\t\\t\\tn _ self primMIDIReadPort: portNum into: buf.\\n\\t\\t\\tn > 0 ifTrue: [bufList add: (buf copyFrom: 1 to: n)].\\n\\t\\t\\t(Delay forMilliseconds: 5) wait]].\\n\\n\\t\\\"format the data into a string\\\"\\n\\ts _ WriteStream on: String new.\\n\\ts cr.\\n\\tbufList do: [:b |\\n\\t\\tt _ (self bufferTimeStampFrom: b) - midiStartTime.\\n\\t\\ts print: t.\\n\\t\\ts nextPutAll: ': '.\\n\\t\\t5 to: b size do: [:i | s print: (b at: i); space].\\n\\t\\ts cr].\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 10:05'!\\ngetPortList\\n\\t\\\"Return a string that describes this platform's MIDI ports.\\\"\\n\\t\\\"MidiPrimTester new getPortList\\\"\\n\\n\\t| s portCount dir directionString |\\n\\ts _ WriteStream on: String new.\\n\\ts cr; nextPutAll: 'MIDI Ports:'; cr.\\n\\tportCount _ self primMIDIGetPortCount.\\n\\t0 to: portCount - 1 do: [:i |\\n\\t\\ts tab.\\n\\t\\ts print: i; nextPutAll: ': '. \\n\\t\\ts nextPutAll: (self primMIDIGetPortName: i).\\n\\t\\tdir _ self primMIDIGetPortDirectionality: i.\\n\\t\\tdirectionString _ dir printString. \\\"default\\\"\\n\\t\\tdir = 1 ifTrue: [directionString _ '(in)'].\\n\\t\\tdir = 2 ifTrue: [directionString _ '(out)'].\\n\\t\\tdir = 3 ifTrue: [directionString _ '(in/out)'].\\n\\t\\ts space; nextPutAll: directionString; cr].\\n\\t^ s contents\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 11:24'!\\nplayDrumRoll: mSecsBetweenNotes count: tapCount onPort: portNum\\n\\t\\\"MidiPrimTester new playDrumRoll: 75 count: 64 onPort: 0\\\"\\n\\t\\\"Play middle-C tapCount times with the given space between notes. This example works best with a short percussive voice, like a drum.\\\"\\n\\t\\\"Details: This test can be used to investigate the real-time performance of your system. On a 110 MHz PowerPC Mac, this method can genererate very fast and smooth drum rolls up to about 100 beats/sec (10 mSecs between notes). However, many factors can prevent one from seeing this level of performance including a slow CPU, lack of a level-2 cache, networking or other background processes stealing chunks of processor time from Squeak, or a sluggish MIDI synthesizer.\\\"\\n\\t\\\"Details: By default, this method does an incremental GC on every note. While not really needed for this example, it illustrates a useful technique for real-time processing in Squeak: do an incremental GC when you know you have a few milliseconds of idle time to avoid triggering one during a time-critical task. In this case, we're also using the GC time to provide a small delay between the note-on and note-off events. If the GC time is too short, as it could be on a fast machine, the note may not sound at all unless you add a few milliseconds of additional delay!!\\\"\\n\\t\\\"Note: This example works best if the VM's millisecond clock has 1 millisecond resolution.\\\"\\n\\n\\t| gcDuringNote noteOn noteOff endTime waitTime |\\n\\tgcDuringNote _ true.\\n\\t\\\"these events use running status, so the command byte is omitted\\\"\\n\\tnoteOn _ #(60 100) as: ByteArray.\\n\\tnoteOff _ #(60 0) as: ByteArray.\\n\\tself primMIDIOpenPort: portNum readSemaIndex: 0 interfaceClockRate: 1000000.\\n\\n\\t\\\"send an initial event with command byte to initiate running status\\\"\\n\\tself primMIDIWritePort: portNum from: (#(144 60 0) as: ByteArray) at: 0.\\n\\n\\t1 to: tapCount do: [:i |\\n\\t\\tendTime _ Time millisecondClockValue + mSecsBetweenNotes.\\n\\t\\tself primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\tgcDuringNote\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\\"do quick GC; takes a few milliseconds and provides the note-down time\\\"\\n\\t\\t\\t\\t\\\"Note: if GC is too fast on your machine, you need to add a few mSecs delay!!\\\"\\n\\t\\t\\t\\tSmalltalk garbageCollectMost]\\n\\t\\t\\tifFalse: [(Delay forMilliseconds: 3) wait].\\n\\n\\t\\tself primMIDIWritePort: portNum from: noteOff at: 0.\\n\\t\\twaitTime _ endTime - Time millisecondClockValue.\\n\\t\\twaitTime > 0 ifTrue: [(Delay forMilliseconds: waitTime) wait]].\\n\\n\\tself primMIDIClosePort: portNum.\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:16'!\\nplayNoteOnPort: portNum\\n\\t\\\"MidiPrimTester new playNoteOnPort: 0\\\"\\n\\n\\t| noteOn noteOff bytesWritten |\\n\\tnoteOn _ #(144 60 100) as: ByteArray.\\n\\tnoteOff _ #(144 60 0) as: ByteArray.\\n\\tself openPort: portNum andDo: [\\n\\t\\tbytesWritten _ self primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\t(Delay forMilliseconds: 500) wait.\\n\\t\\tbytesWritten _ bytesWritten + (self primMIDIWritePort: portNum from: noteOff at: 0)].\\n\\n\\tbytesWritten = 6 ifFalse: [self error: 'not all bytes were sent'].\\n! !\\n\\n!MidiPrimTester methodsFor: 'tests' stamp: 'jm 5/18/1998 15:17'!\\nplayScale: mSecsPerNote onPort: portNum\\n\\t\\\"MidiPrimTester new playScale: 130 onPort: 0\\\"\\n\\n\\t| noteOn noteOff |\\n\\tnoteOn _ #(144 0 100) as: ByteArray.\\n\\tnoteOff _ #(144 0 0) as: ByteArray.\\n\\tself openPort: portNum andDo: [\\n\\t\\t#(60 62 64 65 67 69 71 72 74 72 71 69 67 65 64 62 60) do: [:midiKey | \\n\\t\\t\\tnoteOn at: 2 put: midiKey.\\n\\t\\t\\tnoteOff at: 2 put: midiKey.\\n\\t\\t\\tself primMIDIWritePort: portNum from: noteOn at: 0.\\n\\t\\t\\t(Delay forMilliseconds: mSecsPerNote - 10) wait.\\n\\t\\t\\tself primMIDIWritePort: portNum from: noteOff at: 0.\\n\\t\\t\\t(Delay forMilliseconds: 10) wait]].\\n! !\\n\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 12:48'!\\nbufferTimeStampFrom: aByteArray\\n\\t\\\"Return the timestamp from the given MIDI input buffer. Assume the given buffer is at least 4 bytes long.\\\"\\n\\n\\t^ ((aByteArray at: 1) bitShift: 24) +\\n\\t ((aByteArray at: 2) bitShift: 16) +\\n\\t ((aByteArray at: 3) bitShift: 8) +\\n\\t (aByteArray at: 4)\\n! !\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 12:48'!\\ncanTurnOnParameter: whichParameter\\n\\t\\\"Return true if the given MIDI parameter can be turned on. Leave the parameter in its orginal state.\\\"\\n\\n\\t| old canSet |\\n\\told _ self primMIDIParameterGet: whichParameter.\\n\\tself primMIDIParameterSet: whichParameter to: 1.\\n\\tcanSet _ (self primMIDIParameterGet: whichParameter) = 1.\\n\\tself primMIDIParameterSet: whichParameter to: old.\\n\\t^ canSet\\n! !\\n\\n!MidiPrimTester methodsFor: 'private' stamp: 'jm 5/18/1998 15:32'!\\nopenPort: portNum andDo: aBlock\\n\\t\\\"Open the given MIDI port, evaluate the block, and close the port again. Answer the value of the block.\\\"\\n\\n\\t| result |\\n\\tself primMIDIClosePort: portNum.\\n\\tself primMIDIOpenPort: portNum readSemaIndex: 0 interfaceClockRate: 1000000.\\n\\tresult _ aBlock value.\\n\\tself primMIDIClosePort: portNum.\\n\\t^ result\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMidiPrimTester class\\n\\tinstanceVariableNames: ''!\\n\\n!MidiPrimTester class methodsFor: 'class initialization' stamp: 'yo 12/3/2004 17:05'!\\ninitialize\\n\\t\\\"Initialize the MIDI parameter constants.\\\"\\n\\t\\\"MidiPrimTester initialize\\\"\\n\\n\\tInstalled _ 1.\\n\\t\\t\\\"Read-only. Return 1 if a MIDI driver is installed, 0 if not.\\n\\t\\t On OMS-based MIDI drivers, this returns 1 only if the OMS\\n\\t\\t system is properly installed and configured.\\\"\\n\\n\\tVersion _ 2.\\n\\t\\t\\\"Read-only. Return the integer version number of this MIDI driver.\\n\\t\\t The version numbering sequence is relative to a particular driver.\\n\\t\\t That is, version 3 of the Macintosh MIDI driver is not necessarily\\n\\t\\t related to version 3 of the Win95 MIDI driver.\\\"\\n\\n\\tHasBuffer _ 3.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver has a time-stamped output\\n\\t\\t buffer, 0 otherwise. Such a buffer allows the client to schedule\\n\\t\\t MIDI output packets to be sent later. This can allow more precise\\n\\t\\t timing, since the driver uses timer interrupts to send the data\\n\\t\\t at the right time even if the processor is in the midst of a\\n\\t\\t long-running Squeak primitive or is running some other application\\n\\t\\t or system task.\\\"\\n\\n\\tHasDurs _ 4.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver supports an extended\\n\\t\\t primitive for note-playing that includes the note duration and\\n\\t\\t schedules both the note-on and the note-off messages in the\\n\\t\\t driver. Otherwise, return 0.\\\"\\n\\n\\tCanSetClock _ 5.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver's clock can be set\\n\\t\\t via an extended primitive, 0 if not.\\\"\\n\\n\\tCanUseSemaphore _ 6.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver can signal a semaphore\\n\\t\\t when MIDI input arrives. Otherwise, return 0. If this driver\\n\\t\\t supports controller caching and it is enabled, then incoming\\n\\t\\t controller messages will not signal the semaphore.\\\"\\n\\n\\tEchoOn _ 7.\\n\\t\\t\\\"Read-write. If this flag is set to a non-zero value, and if\\n\\t\\t the driver supports echoing, then incoming MIDI events will\\n\\t\\t be echoed immediately. If this driver does not support echoing,\\n\\t\\t then queries of this parameter will always return 0 and\\n\\t\\t attempts to change its value will do nothing.\\\"\\n\\n\\tUseControllerCache _ 8.\\n\\t\\t\\\"Read-write. If this flag is set to a non-zero value, and if\\n\\t\\t the driver supports a controller cache, then the driver will\\n\\t\\t maintain a cache of the latest value seen for each MIDI controller,\\n\\t\\t and control update messages will be filtered out of the incoming\\n\\t\\t MIDI stream. An extended MIDI primitive allows the client to\\n\\t\\t poll the driver for the current value of each controller. If\\n\\t\\t this driver does not support a controller cache, then queries\\n\\t\\t of this parameter will always return 0 and attempts to change\\n\\t\\t its value will do nothing.\\\"\\n\\n\\tEventsAvailable _ 9.\\n\\t\\t\\\"Read-only. Return the number of MIDI packets in the input queue.\\\"\\n\\n\\tFlushDriver _ 10.\\n\\t\\t\\\"Write-only. Setting this parameter to any value forces the driver\\n\\t\\t to flush its I/0 buffer, discarding all unprocessed data. Reading\\n\\t\\t this parameter returns 0. Setting this parameter will do nothing\\n\\t\\t if the driver does not support buffer flushing.\\\"\\n\\n\\tClockTicksPerSec _ 11.\\n\\t\\t\\\"Read-only. Return the MIDI clock rate in ticks per second.\\\"\\n\\n\\tHasInputClock _ 12.\\n\\t\\t\\\"Read-only. Return 1 if this MIDI driver timestamps incoming\\n\\t\\t MIDI data with the current value of the MIDI clock, 0 otherwise.\\n\\t\\t If the driver does not support such timestamping, then the\\n\\t\\t client must read input data frequently and provide its own\\n\\t\\t timestamping.\\\"\\n! !\\nObject subclass: #MimeConverter\\n\\tinstanceVariableNames: 'dataStream mimeStream'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Streams'!\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:55'!\\ndataStream\\n\\t^dataStream! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!\\ndataStream: anObject\\n\\tdataStream _ anObject! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:53'!\\nmimeStream\\n\\t^mimeStream! !\\n\\n!MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!\\nmimeStream: anObject\\n\\tmimeStream _ anObject! !\\n\\n\\n!MimeConverter methodsFor: 'conversion' stamp: 'bf 11/12/1998 13:30'!\\nmimeDecode\\n\\t\\\"Do conversion reading from mimeStream writing to dataStream\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!MimeConverter methodsFor: 'conversion' stamp: 'bf 11/12/1998 13:31'!\\nmimeEncode\\n\\t\\\"Do conversion reading from dataStream writing to mimeStream\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMimeConverter class\\n\\tinstanceVariableNames: ''!\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:47'!\\nforEncoding: encodingString\\n\\t\\\"Answer a converter class for the given encoding or nil if unknown\\\"\\n\\tencodingString ifNil: [^nil].\\n\\t^ encodingString asLowercase caseOf: \\n\\t\\t{ ['base64'] -> [Base64MimeConverter].\\n\\t\\t ['quoted-printable'] -> [QuotedPrintableMimeConverter]}\\n\\t\\totherwise: [].\\n! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:43'!\\nmimeDecode: aStringOrStream as: contentsClass\\n\\t^ contentsClass streamContents: [:out |\\n\\t\\tself mimeDecode: aStringOrStream to: out]! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeDecode: aStringOrStream to: outStream\\n\\tself new\\n\\t\\tmimeStream: (aStringOrStream isStream\\n\\t\\t\\tifTrue: [aStringOrStream]\\n\\t\\t\\tifFalse: [ReadStream on: aStringOrStream]);\\n\\t\\tdataStream: outStream;\\n\\t\\tmimeDecode! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeEncode: aCollectionOrStream\\n\\t^ String streamContents: [:out |\\n\\t\\tself mimeEncode: aCollectionOrStream to: out]! !\\n\\n!MimeConverter class methodsFor: 'convenience' stamp: 'bf 3/10/2000 14:40'!\\nmimeEncode: aCollectionOrStream to: outStream\\n\\tself new\\n\\t\\tdataStream: (aCollectionOrStream isStream\\n\\t\\t\\tifTrue: [aCollectionOrStream]\\n\\t\\t\\tifFalse: [ReadStream on: aCollectionOrStream]);\\n\\t\\tmimeStream: outStream;\\n\\t\\tmimeEncode! !\\nPolygonMorph subclass: #MixedCurveMorph\\n\\tinstanceVariableNames: 'slopeClamps'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic-NewCurve'!\\n!MixedCurveMorph commentStamp: '<historical>' prior: 0!\\nA MixedCurveMorph is Curve that can be broken up into separately curved segments. It allows for the creation of matching edges( e. g. for jigsaw puzzle pieces).\\n\\nInstance Variables\\n\\tslopeClamps:\\t\\t<Array>\\n\\nslopeClamps\\n\\t- elements of array are either 0 or nil. Indicating whether slope for the corresponding vertex is 0@0 or unknown and therefore to be calculated. There is one element for each vertex.\\n\\t\\n\\t\\n!\\n\\n\\n!MixedCurveMorph methodsFor: 'access' stamp: 'wiz 2/8/2006 18:59'!\\nclamps\\n\\\" Return a collection of clamps the same size as vertices.\\n\\tIf necessary default to unclamped slopes.\\n\\\"\\n\\nslopeClamps \\n\\tifNil: [ ^ slopeClamps := Array new: vertices size ] .\\nslopeClamps size = vertices size\\n\\tifFalse: [ ^ slopeClamps := Array new: vertices size ] . \\n\\t^ slopeClamps ! !\\n\\n!MixedCurveMorph methodsFor: 'access' stamp: 'wiz 2/8/2006 17:44'!\\nhandleColorAt: vertIndex\\n \\\" clamped handles are cyan and \\n\\tunclamped handles are yellow.\\\"\\n\\n(self clamps at: vertIndex ) ifNil: [ ^ Color yellow ] .\\n^ Color cyan \\n! !\\n\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 17:50'!\\nclickVertex: ix event: evt fromHandle: handle\\n\\\" Toggle the state of the clamp. \\\"\\n\\\"Note: self clamps assures slopeClamps will be same size as vertices\\\"\\n\\n(self clamps at: ix) \\n\\tifNil:\\t [ slopeClamps at: ix put: 0 ]\\n\\tifNotNil: [ slopeClamps at: ix put: nil ] .\\n\\tself setVertices: vertices .\\n\\t\\n! !\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 18:01'!\\ndeleteVertexAt: anIndex\\n\\t\\t\\t(slopeClamps :=\\n\\t\\t\\t\\t\\t\\tslopeClamps\\n\\t\\t\\t\\t\\t\\tcopyReplaceFrom: anIndex\\n\\t\\t\\t\\t\\t\\tto: anIndex\\n\\t\\t\\t\\t\\t\\twith: Array new) .\\n\\t\\t\\tself\\n\\t\\t\\t\\tsetVertices: (vertices\\n\\t\\t\\t\\t\\t\\tcopyReplaceFrom: anIndex\\n\\t\\t\\t\\t\\t\\tto: anIndex\\n\\t\\t\\t\\t\\t\\twith: Array new).\\n\\t\\t\\t\\t\\t\\t! !\\n\\n!MixedCurveMorph methodsFor: 'editing' stamp: 'wiz 2/8/2006 18:29'!\\ninsertVertexAt: anIndex put: aValue\\n\\t\\\"New vertexs are unclamped.\\\"\\n\\t\\\"Note: order is important. \\n\\tThe clamps array must match vertex size before setVertices: is performed.\\\"\\n\\tslopeClamps := slopeClamps \\n\\t\\tcopyReplaceFrom: anIndex + 1 to: anIndex with: (Array with: nil).\\n\\tself setVertices: (vertices copyReplaceFrom: anIndex + 1 to: anIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twith: (Array with: aValue)).! !\\n\\n\\n!MixedCurveMorph methodsFor: 'initialization' stamp: 'wiz 2/12/2006 05:59'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tself extent: 32@20 .\\n\\n\\tself rectOval.\\n\\tself clamps . \\\"This initializes slopeClamps.\\\"\\n\\tslopeClamps at: 1 put: 0 .\\n\\tslopeClamps at: 4 put: 0 .\\n\\t\\n\\tclosed _ true.\\n\\tsmoothCurve _ true.\\n\\tarrows _ #none.\\n\\tself computeBounds! !\\n\\n\\n!MixedCurveMorph methodsFor: 'smoothing' stamp: 'wiz 2/18/2006 12:53'!\\nslopes: knots \\n\\t\\\"Choose slopes according to state of polygon and preferences\\\"\\n\\tself isCurvy\\n\\t\\tifFalse: [^ knots segmentedSlopes].\\n\\t^ (closed\\n\\t\\t\\tand: [self isCurvier])\\n\\t\\tifTrue: [ knots closedCubicSlopes: self clamps ]\\n\\t\\tifFalse: [knots naturalCubicSlopes: self clamps ]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMixedCurveMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MixedCurveMorph class methodsFor: 'as yet unclassified' stamp: 'wiz 2/12/2006 17:12'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Mixed'\\n\\t\\tcategories:\\t\\t#('Graphics' 'Basic')\\n\\t\\tdocumentation:\\t'A Curve with optional bends and segments. Shift click to get handles.\\n\\t\\t\\tClick handles to change bends. Move handles to move the points.'! !\\nAbstractSound subclass: #MixedSound\\n\\tinstanceVariableNames: 'sounds leftVols rightVols soundDone'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t| dur |\\n\\tdur := 0.\\n\\tsounds do: [:snd | dur := dur max: snd duration].\\n\\t^ dur\\n! !\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'jm 12/16/2001 20:23'!\\nisStereo\\n\\n\\t^ true\\n! !\\n\\n!MixedSound methodsFor: 'accessing' stamp: 'jm 2/4/98 13:37'!\\nsounds\\n\\n\\t^ sounds\\n! !\\n\\n\\n!MixedSound methodsFor: 'composition'!\\n+ aSound\\n\\t\\\"Return the mix of the receiver and the argument sound.\\\"\\n\\n\\t^ self add: aSound\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'jm 1/5/98 13:47'!\\nadd: aSound\\n\\t\\\"Add the given sound with a pan setting of centered and no attenuation.\\\"\\n\\n\\tself add: aSound pan: 0.5 volume: 1.0.\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'jm 1/5/98 13:47'!\\nadd: aSound pan: leftRightPan\\n\\t\\\"Add the given sound with the given left-right panning and no attenuation.\\\"\\n\\n\\tself add: aSound pan: leftRightPan volume: 1.0.\\n! !\\n\\n!MixedSound methodsFor: 'composition' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nadd: aSound pan: leftRightPan volume: volume\\n\\t\\\"Add the given sound with the given left-right pan, where 0.0 is full left, 1.0 is full right, and 0.5 is centered. The loudness of the sound will be scaled by volume, which ranges from 0 to 1.0.\\\"\\n\\n\\t| pan vol |\\n\\tpan := ((leftRightPan * ScaleFactor) asInteger max: 0) min: ScaleFactor.\\n\\tvol := ((volume * ScaleFactor) asInteger max: 0) min: ScaleFactor.\\n\\tsounds := sounds copyWith: aSound.\\n\\tleftVols := leftVols copyWith: ((ScaleFactor - pan) * vol) // ScaleFactor.\\n\\trightVols := rightVols copyWith: (pan * vol) // ScaleFactor.\\n! !\\n\\n\\n!MixedSound methodsFor: 'copying' stamp: 'jm 12/15/97 19:13'!\\ncopy\\n\\t\\\"Copy my component sounds.\\\"\\n\\n\\t^ super copy copySounds\\n! !\\n\\n!MixedSound methodsFor: 'copying' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopySounds\\n\\t\\\"Private!! Support for copying. Copy my component sounds and settings array.\\\"\\n\\n\\tsounds := sounds collect: [:s | s copy].\\n\\tleftVols := leftVols copy.\\n\\trightVols := rightVols copy.\\n! !\\n\\n\\n!MixedSound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tsounds := Array new.\\n\\tleftVols := Array new.\\n\\trightVols := Array new.\\n! !\\n\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'jm 11/25/97 13:40'!\\ndoControl\\n\\n\\tsuper doControl.\\n\\t1 to: sounds size do: [:i | (sounds at: i) doControl].\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol\\n\\t\\\"Play a number of sounds concurrently. The level of each sound can be set independently for the left and right channels.\\\"\\n\\n\\t| snd left right |\\n\\t1 to: sounds size do: [:i |\\n\\t\\t(soundDone at: i) ifFalse: [\\n\\t\\t\\tsnd := sounds at: i.\\n\\t\\t\\tleft := (leftVol * (leftVols at: i)) // ScaleFactor.\\n\\t\\t\\tright := (rightVol * (rightVols at: i)) // ScaleFactor.\\n\\t\\t\\tsnd samplesRemaining > 0\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tsnd mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: left rightVol: right]\\n\\t\\t\\t\\tifFalse: [soundDone at: i put: true]]].\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreset\\n\\n\\tsuper reset.\\n\\tsounds do: [:snd | snd reset].\\n\\tsoundDone := (Array new: sounds size) atAllPut: false.\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplesRemaining\\n\\n\\t| remaining r |\\n\\tremaining := 0.\\n\\t1 to: sounds size do: [:i |\\n\\t\\tr := (sounds at: i) samplesRemaining.\\n\\t\\tr > remaining ifTrue: [remaining := r]].\\n\\n\\t^ remaining\\n! !\\n\\n!MixedSound methodsFor: 'sound generation' stamp: 'jm 1/10/1999 08:45'!\\nstopGracefully\\n\\t\\\"End this note with a graceful decay. If the note has envelopes, determine the decay time from its envelopes.\\\"\\n\\n\\tsuper stopGracefully.\\n\\tsounds do: [:s | s stopGracefully].\\n! !\\nStream subclass: #MockSocketStream\\n\\tinstanceVariableNames: 'atEnd inStream outStream'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'NetworkTests-Kernel'!\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 12:51'!\\natEnd: aBoolean\\n\\tatEnd := aBoolean.! !\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 13:29'!\\ninStream\\n\\t^inStream! !\\n\\n!MockSocketStream methodsFor: 'accessing' stamp: 'fbs 3/22/2004 13:08'!\\noutStream\\n\\t^outStream! !\\n\\n\\n!MockSocketStream methodsFor: 'initialize-release' stamp: 'fbs 3/22/2004 13:29'!\\ninitialize\\n\\tself resetInStream.\\n\\tself resetOutStream.! !\\n\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:10'!\\nnextLine\\n\\t^self nextLineCrLf! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:09'!\\nnextLineCrLf\\n\\t^(self upToAll: String crlf).! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:28'!\\nresetInStream\\n\\tinStream := WriteStream on: ''.! !\\n\\n!MockSocketStream methodsFor: 'stream in' stamp: 'fbs 3/22/2004 13:09'!\\nupToAll: delims\\n\\t^self inStream upToAll: delims.! !\\n\\n\\n!MockSocketStream methodsFor: 'stream out' stamp: 'fbs 3/22/2004 13:28'!\\nresetOutStream\\n\\toutStream := WriteStream on: ''.! !\\n\\n!MockSocketStream methodsFor: 'stream out' stamp: 'fbs 3/22/2004 13:07'!\\nsendCommand: aString\\n\\tself outStream\\n\\t\\tnextPutAll: aString;\\n\\t\\tnextPutAll: String crlf.! !\\n\\n\\n!MockSocketStream methodsFor: 'testing' stamp: 'fbs 3/22/2004 13:08'!\\natEnd\\n\\t^self inStream atEnd.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMockSocketStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MockSocketStream class methodsFor: 'instance creation' stamp: 'fbs 3/22/2004 12:46'!\\non: socket\\n\\t^self basicNew initialize! !\\nController subclass: #ModalController\\n\\tinstanceVariableNames: 'modeActive'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Framework'!\\n!ModalController commentStamp: '<historical>' prior: 0!\\nI am a controller that puts the poor user into a mode by not relinquishing control. However, I do pass control onto my underlings. Some underling is expected to end the mode by sending me 'close'. Watch out Larry Tesler, the mode lives on...\\n!\\n\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:05'!\\nclose\\n\\t\\\"This is how we leave the mode.\\\" \\n\\n\\tmodeActive _ false.\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:02'!\\ncontrolInitialize\\n\\n\\tmodeActive _ true.\\n\\t^ super controlInitialize\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'!\\nisControlActive\\n\\n\\t^ modeActive\\n! !\\n\\n!ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'!\\nisControlWanted\\n\\n\\t^ modeActive\\n! !\\nStandardSystemView subclass: #ModalSystemWindowView\\n\\tinstanceVariableNames: 'modalBorder'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n!ModalSystemWindowView commentStamp: '<historical>' prior: 0!\\nI am a view for a Modal System Window. I vary from StandardSystemView, of which I am a subclass in a few ways:\\n\\n\\t(1) I use ModalController as my default controller;\\n\\t(2) When asked to update with the symbol #close, I direct the controller to close;\\n\\t(3) I display a slightly different title bar with no control boxes.!\\n\\n\\n!ModalSystemWindowView methodsFor: 'controller access' stamp: 'acg 2/9/2000 00:58'!\\ndefaultControllerClass\\n\\n\\t^ModalController! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/18/2000 20:24'!\\ndisplay\\n\\n\\tsuper display.\\n\\tself displayLabelBackground: false.\\n\\tself displayLabelText.\\n! !\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/19/2000 00:59'!\\ndisplayBorder\\n\\t\\\"Display the receiver's border (using the receiver's borderColor).\\\"\\n\\n\\tmodalBorder ifFalse: [^super displayBorder].\\n\\n\\tDisplay\\n\\t\\tborder: self displayBox\\n\\t\\twidthRectangle: (1@1 corner: 2@2)\\n\\t\\trule: Form over\\n\\t\\tfillColor: Color black.\\n\\tDisplay\\n\\t\\tborder: (self displayBox insetBy: (1@1 corner: 2@2))\\n\\t\\twidthRectangle: (4@4 corner: 3@3)\\n\\t\\trule: Form over\\n\\t\\tfillColor: (Color r: 16rEA g: 16rEA b: 16rEA).\\n! !\\n\\n!ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/9/2000 07:21'!\\ndisplayLabelBoxes\\n\\t\\\"Modal dialogs don't have closeBox or growBox.\\\"\\n! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/18/2000 20:41'!\\nborderWidth: anObject\\n\\n\\tmodalBorder _ false.\\n\\t^super borderWidth: anObject! !\\n\\n!ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/19/2000 00:50'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\tsuper initialize.\\n\\tself borderWidth: 5.\\n\\tself noLabel.\\n\\tmodalBorder _ true.! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'label access' stamp: 'acg 2/9/2000 08:35'!\\nbackgroundColor\\n\\t^Color lightYellow! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'modal dialog' stamp: 'BG 12/13/2002 11:33'!\\ndoModalDialog\\n\\n\\t| savedArea |\\n\\tself resizeInitially.\\n\\tself resizeTo: \\n\\t\\t((self windowBox)\\n\\t\\t\\talign: self windowBox center\\n\\t\\t\\twith: Display boundingBox aboveCenter).\\n\\tsavedArea _ Form fromDisplay: self windowBox.\\n\\tself displayEmphasized.\\n\\tself controller startUp.\\n\\tself release.\\n\\tsavedArea displayOn: Display at: self windowOrigin.\\n! !\\n\\n\\n!ModalSystemWindowView methodsFor: 'model access' stamp: 'acg 2/9/2000 00:57'!\\nupdate: aSymbol\\n\\taSymbol = #close\\n\\t\\tifTrue: [^self controller close].\\n\\t^super update: aSymbol! !\\nObject subclass: #Model\\n\\tinstanceVariableNames: 'dependents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!Model commentStamp: '<historical>' prior: 0!\\nProvides a superclass for classes that function as models. The only behavior provided is fast dependents maintenance, which bypasses the generic DependentsFields mechanism. 1/23/96 sw!\\n\\n\\n!Model methodsFor: 'copying' stamp: 'tk 10/21/2002 12:59'!\\nveryDeepFixupWith: deepCopier \\n\\t\\\"See if the dependents are being copied also. If so, point at the new copies. (The dependent has self as its model.)\\n\\tDependents handled in class Object, when the model is not a Model, are fixed up in Object veryDeepCopy.\\\"\\n\\n\\t| originalDependents refs newDependent |\\n\\tsuper veryDeepFixupWith: deepCopier.\\n\\toriginalDependents _ dependents.\\n\\toriginalDependents ifNil: [\\n\\t\\t^self.\\n\\t\\t].\\n\\tdependents _ nil.\\n\\trefs _ deepCopier references.\\n\\toriginalDependents\\n\\t\\tdo: [:originalDependent | \\n\\t\\t\\tnewDependent _ refs\\n\\t\\t\\t\\t\\t\\tat: originalDependent\\n\\t\\t\\t\\t\\t\\tifAbsent: [].\\n\\t\\t\\tnewDependent\\n\\t\\t\\t\\tifNotNil: [self addDependent: newDependent]]!\\n]style[(29 206 19 395)f1b,f1,f1LObject veryDeepCopy;,f1! !\\n\\n!Model methodsFor: 'copying' stamp: 'RB 9/20/2001 16:25'!\\nveryDeepInner: deepCopier\\n\\t\\\"Shallow copy dependents and fix them later\\\"\\n! !\\n\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:26'!\\ncanDiscardEdits\\n\\t\\\"Answer true if none of the views on this model has unaccepted edits that matter.\\\"\\n\\n\\tdependents ifNil: [^ true].\\n\\t^ super canDiscardEdits\\n! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sw 2/6/2001 04:13'!\\ncontainingWindow\\n\\t\\\"Answer the window that holds the receiver. The dependents technique is odious and may not be airtight, if multiple windows have the same model.\\\"\\n\\n\\t^ self dependents detect:\\n\\t\\t[:d | ((d isKindOf: SystemWindow orOf: StandardSystemView) or: [d isKindOf: MVCWiWPasteUpMorph]) and: [d model == self]] ifNone: [nil]! !\\n\\n!Model methodsFor: 'dependents' stamp: 'jm 3/24/98 15:12'!\\nhasUnacceptedEdits\\n\\t\\\"Answer true if any of the views on this model has unaccepted edits.\\\"\\n\\n\\tdependents == nil ifTrue: [^ false].\\n\\t^ super hasUnacceptedEdits\\n! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'!\\nmyDependents\\n\\t^ dependents! !\\n\\n!Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'!\\nmyDependents: aCollectionOrNil\\n\\tdependents _ aCollectionOrNil! !\\n\\n!Model methodsFor: 'dependents' stamp: 'gm 2/16/2003 20:37'!\\ntopView\\n\\t\\\"Find the first top view on me. Is there any danger of their being two with the same model? Any danger from ungarbage collected old views? Ask if schedulled?\\\"\\n\\n\\tdependents ifNil: [^nil].\\n\\tSmalltalk isMorphic \\n\\t\\tifTrue: \\n\\t\\t\\t[dependents \\n\\t\\t\\t\\tdo: [:v | ((v isSystemWindow) and: [v isInWorld]) ifTrue: [^v]].\\n\\t\\t\\t^nil].\\n\\tdependents do: [:v | v superView ifNil: [v model == self ifTrue: [^v]]].\\n\\t^nil! !\\n\\n\\n!Model methodsFor: 'keyboard' stamp: 'nk 6/29/2004 14:46'!\\narrowKey: aChar from: view\\n\\t\\\"backstop; all the PluggableList* classes actually handle arrow keys, and the models handle other keys.\\\"\\n\\t^false! !\\n\\n\\n!Model methodsFor: 'menus' stamp: 'di 4/11/98 11:34'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked.\\\" \\n\\n\\t\\\"default is that the editor does all\\\"\\n\\t^ otherTarget perform: selector.! !\\n\\n!Model methodsFor: 'menus' stamp: 'tk 4/17/1998 17:28'!\\nselectedClass\\n\\t\\\"All owners of TextViews are asked this during a doIt\\\"\\n\\t^ nil! !\\n\\n!Model methodsFor: 'menus' stamp: 'zz 3/2/2004 23:49'!\\nstep\\n\\t\\\"Default for morphic models is no-op\\\"! !\\n\\n!Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'!\\ntrash\\n\\t\\\"What should be displayed if a trash pane is restored to initial state\\\"\\n\\n\\t^ ''! !\\n\\n!Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'!\\ntrash: ignored\\n\\t\\\"Whatever the user submits to the trash, it need not be saved.\\\"\\n\\n\\t^ true! !\\n\\n\\n!Model methodsFor: '*services-base' stamp: 'rr 3/21/2006 11:54'!\\nrequestor\\n\\t^ Requestor default! !\\n\\n\\n!Model methodsFor: '*Tools' stamp: 'ar 9/27/2005 20:59'!\\naddItem: classAndMethod\\n\\t\\\"Make a linked message list and put this method in it\\\"\\n\\t| list |\\n\\n\\tself flag: #mref.\\t\\\"classAndMethod is a String\\\"\\n\\n\\tMessageSet \\n\\t\\tparse: classAndMethod \\n\\t\\ttoClassAndSelector: [ :class :sel |\\n\\t\\t\\tclass ifNil: [^self].\\n\\t\\t\\tlist := OrderedCollection with: (\\n\\t\\t\\t\\tMethodReference new\\n\\t\\t\\t\\t\\tsetClass: class \\n\\t\\t\\t\\t\\tmethodSymbol: sel \\n\\t\\t\\t\\t\\tstringVersion: classAndMethod\\n\\t\\t\\t).\\n\\t\\t\\tMessageSet \\n\\t\\t\\t\\topenMessageList: list \\n\\t\\t\\t\\tname: 'Linked by HyperText'.\\n\\t\\t]\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModel class\\n\\tinstanceVariableNames: ''!\\n\\n!Model class methodsFor: 'toolbuilder' stamp: 'ar 2/11/2005 16:26'!\\nbuildWith: toolBuilder\\n\\t^self new buildWith: toolBuilder! !\\nObject subclass: #ModelExtension\\n\\tinstanceVariableNames: 'interests lock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Traits-LocalSends'!\\n\\n!ModelExtension methodsFor: 'access to cache' stamp: 'dvf 9/14/2005 11:27'!\\nhaveInterestsIn: aClass \\n\\tlock critical: [^interests includes: aClass]\\n! !\\n\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/14/2005 11:11'!\\nlostInterest: client inAll: classes\\n\\tlock critical: [interests removeAll: classes]! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/2/2005 11:43'!\\nlostInterest: client in: class\\n\\tself lostInterest: client inAll: {class}! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/14/2005 11:28'!\\nnoteInterestOf: client inAll: classes\\n\\tlock critical: [interests addAll: classes].! !\\n\\n!ModelExtension methodsFor: 'interests' stamp: 'dvf 9/2/2005 11:44'!\\nnoteInterestOf: client in: class\\n\\tself noteInterestOf: client inAll: {class}! !\\n\\n\\n!ModelExtension methodsFor: 'invalidation' stamp: 'dvf 9/14/2005 11:11'!\\ninitialize\\n\\tlock := Semaphore forMutualExclusion. \\n\\tinterests := IdentityBag new.\\n\\tSystemChangeNotifier uniqueInstance \\n\\t\\tnotify: self\\n\\t\\tofSystemChangesOfItem: #class\\n\\t\\tusing: #classChanged:.\\n\\tSystemChangeNotifier uniqueInstance \\n\\t\\tnotify: self\\n\\t\\tofSystemChangesOfItem: #method\\n\\t\\tusing: #classChanged:.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModelExtension class\\n\\tinstanceVariableNames: 'current'!\\n\\n!ModelExtension class methodsFor: 'accessing' stamp: 'dvf 9/1/2005 21:16'!\\ncurrent\\n\\t^current! !\\n\\n!ModelExtension class methodsFor: 'accessing' stamp: 'dvf 9/1/2005 21:16'!\\ncurrent: anObject\\n\\t^current := anObject! !\\n\\n\\n!ModelExtension class methodsFor: 'initialize-release' stamp: 'dvf 9/2/2005 12:20'!\\ninitialize\\n\\tself isAbstract not ifTrue:\\n\\t\\t[self current: self new]! !\\n\\n!ModelExtension class methodsFor: 'initialize-release' stamp: 'dvf 9/2/2005 12:20'!\\nisAbstract\\n\\t^self == ModelExtension! !\\n\\n\\n!ModelExtension class methodsFor: 'instance creation' stamp: 'dvf 9/1/2005 21:16'!\\ndoWithTemporaryInstance: aBlock \\n\\t| singleton |\\n\\tsingleton := self current.\\n\\t\\n\\t[self current: self new.\\n\\taBlock value] ensure: [self current: singleton]! !\\nModifiedEvent subclass: #ModifiedClassDefinitionEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'!\\nclassVarNames\\n\\t^ item classVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'!\\ninstVarNames\\n\\t^ item instVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'!\\noldClassVarNames\\n\\t^ oldItem classVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'!\\noldInstVarNames\\n\\t^ oldItem instVarNames asSet! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'!\\noldSharedPools\\n\\t^ oldItem sharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:28'!\\noldSuperclass\\n\\t^ oldItem superclass! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'!\\nsharedPools\\n\\t^ item sharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:28'!\\nsuperclass\\n\\t^ item superclass! !\\n\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:31'!\\nareClassVarsModified\\n\\t^ self classVarNames ~= self oldClassVarNames! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:30'!\\nareInstVarsModified\\n\\t^ self instVarNames ~= self oldInstVarNames! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:32'!\\nareSharedPoolsModified\\n\\t^ self sharedPools ~= self oldSharedPools! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:29'!\\nisSuperclassModified\\n\\t^ item superclass ~~ oldItem superclass! !\\n\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:48'!\\nanyChanges\\n\\t^ self isSuperclassModified or: [self areInstVarsModified or: [self areClassVarsModified or: [self areSharedPoolsModified or: [self isTraitCompositionModified]]]]! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:59'!\\nisTraitCompositionModified\\n\\t^self traitComposition printString ~= self oldTraitComposition printString! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:50'!\\noldTraitComposition\\n\\t^ oldItem traitComposition! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/18/2004 10:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' Super: ';\\n\\t\\tprint: self isSuperclassModified;\\n\\t\\tnextPutAll: ' TraitComposition: ';\\n\\t\\tprint: self isTraitCompositionModified;\\n\\t\\tnextPutAll: ' InstVars: ';\\n\\t\\tprint: self areInstVarsModified;\\n\\t\\tnextPutAll: ' ClassVars: ';\\n\\t\\tprint: self areClassVarsModified;\\n\\t\\tnextPutAll: ' SharedPools: ';\\n\\t\\tprint: self areSharedPoolsModified.! !\\n\\n!ModifiedClassDefinitionEvent methodsFor: '*Kernel-Classes' stamp: 'al 7/17/2004 21:50'!\\ntraitComposition\\n\\t^ item traitComposition! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedClassDefinitionEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedClassDefinitionEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:26'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind! !\\n\\n\\n!ModifiedClassDefinitionEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 11:52'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\t| instance |\\n\\tinstance := self item: newClass kind: self classKind.\\n\\tinstance oldItem: oldClass.\\n\\t^instance! !\\nAbstractEvent subclass: #ModifiedEvent\\n\\tinstanceVariableNames: 'oldItem'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedEvent methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:08'!\\noldItem\\n\\t^ oldItem! !\\n\\n\\n!ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 15:10'!\\nprintEventKindOn: aStream\\n\\n\\taStream nextPutAll: 'Modified'! !\\n\\n!ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 17:57'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' oldItem: ';\\n\\t\\tprint: oldItem.! !\\n\\n\\n!ModifiedEvent methodsFor: 'testing' stamp: 'NS 1/19/2004 15:09'!\\nisModified\\n\\n\\t^true! !\\n\\n\\n!ModifiedEvent methodsFor: 'private-accessing' stamp: 'NS 1/19/2004 15:08'!\\noldItem: anItem\\n\\toldItem _ anItem! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:10'!\\nchangeKind\\n\\n\\t^#Modified! !\\n\\n!ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:25'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind with: self methodKind with: self categoryKind with: self protocolKind! !\\n\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 19:37'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\t^ ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass! !\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 11:40'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass\\n\\t| instance |\\n\\tinstance := self method: newMethod selector: aSymbol class: aClass.\\n\\tinstance oldItem: oldMethod.\\n\\t^ instance! !\\n\\n!ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 11:40'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\t| instance |\\n\\tinstance := self method: newMethod selector: aSymbol class: aClass requestor: requestor.\\n\\tinstance oldItem: oldMethod.\\n\\t^ instance! !\\nModifiedEvent subclass: #ModifiedTraitDefinitionEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'testing' stamp: 'al 7/18/2004 11:08'!\\nanyChanges\\n\\t^ self isTraitCompositionModified! !\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'testing' stamp: 'al 7/18/2004 10:43'!\\nisTraitCompositionModified\\n\\t^self traitComposition printString ~= self oldTraitComposition printString! !\\n\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\noldTraitComposition\\n\\t^ oldItem traitComposition! !\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\ntraitComposition\\n\\t^ item traitComposition! !\\n\\n\\n!ModifiedTraitDefinitionEvent methodsFor: 'printing' stamp: 'al 7/18/2004 10:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPutAll: ' TraitComposition: ';\\n\\t\\tprint: self isTraitCompositionModified! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nModifiedTraitDefinitionEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!ModifiedTraitDefinitionEvent class methodsFor: 'accessing' stamp: 'al 7/18/2004 10:43'!\\nsupportedKinds\\n\\t\\\"All the kinds of items that this event can take.\\\"\\n\\t\\n\\t^ Array with: self classKind! !\\n\\n\\n!ModifiedTraitDefinitionEvent class methodsFor: 'instance creation' stamp: 'al 7/18/2004 10:50'!\\ntraitDefinitionChangedFrom: oldTrait to: newTrait\\n\\t| instance |\\n\\tinstance _ self item: newTrait kind: self classKind.\\n\\tinstance oldItem: oldTrait.\\n\\t^instance! !\\nObject subclass: #Monitor\\n\\tinstanceVariableNames: 'mutex ownerProcess nestingLevel defaultQueue queueDict queuesMutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!Monitor commentStamp: 'md 3/3/2006 09:19' prior: 0!\\nA monitor provides process synchronization that is more high level than the one provided by a Semaphore. Similar to the classical definition of a Monitor it has the following properties:\\n\\n1) At any time, only one process can execute code inside a critical section of a monitor.\\n2) A monitor is reentrant, which means that the active process in a monitor never gets blocked when it enters a (nested) critical section of the same monitor.\\n3) Inside a critical section, a process can wait for an event that may be coupled to a certain condition. If the condition is not fulfilled, the process leaves the monitor temporarily (in order to let other processes enter) and waits until another process signals the event. Then, the original process checks the condition again (this is often necessary because the state of the monitor could have changed in the meantime) and continues if it is fulfilled.\\n4) The monitor is fair, which means that the process that is waiting on a signaled condition the longest gets activated first.\\n5) The monitor allows you to define timeouts after which a process gets activated automatically.\\n\\n\\nBasic usage:\\n\\nMonitor>>critical: aBlock\\nCritical section.\\nExecutes aBlock as a critical section. At any time, only one process can execute code in a critical section.\\nNOTE: All the following synchronization operations are only valid inside the critical section of the monitor!!\\n\\nMonitor>>wait\\nUnconditional waiting for the default event.\\nThe current process gets blocked and leaves the monitor, which means that the monitor allows another process to execute critical code. When the default event is signaled, the original process is resumed.\\n\\nMonitor>>waitWhile: aBlock\\nConditional waiting for the default event.\\nThe current process gets blocked and leaves the monitor only if the argument block evaluates to true. This means that another process can enter the monitor. When the default event is signaled, the original process is resumed, which means that the condition (argument block) is checked again. Only if it evaluates to false, does execution proceed. Otherwise, the process gets blocked and leaves the monitor again...\\n\\nMonitor>>waitUntil: aBlock\\nConditional waiting for the default event.\\nSee Monitor>>waitWhile: aBlock.\\n\\nMonitor>>signal\\nOne process waiting for the default event is woken up.\\n\\nMonitor>>signalAll\\nAll processes waiting for the default event are woken up.\\n\\n\\nUsing non-default (specific) events:\\n\\nMonitor>>waitFor: aSymbol\\nUnconditional waiting for the non-default event represented by the argument symbol.\\nSame as Monitor>>wait, but the process gets only reactivated by the specific event and not the default event.\\n\\nMonitor>>waitWhile: aBlock for: aSymbol\\nConfitional waiting for the non-default event represented by the argument symbol.\\nSame as Monitor>>waitWhile:for:, but the process gets only reactivated by the specific event and not the default event.\\n\\nMonitor>>waitUntil: aBlock for: aSymbol\\nConfitional waiting for the non-default event represented by the argument symbol.\\nSee Monitor>>waitWhile:for: aBlock.\\n\\nMonitor>>signal: aSymbol\\nOne process waiting for the given event is woken up. If there is no process waiting for this specific event, a process waiting for the default event gets resumed.\\n\\nMonitor>>signalAll: aSymbol\\nAll process waiting for the given event or the default event are woken up.\\n\\nMonitor>>signalReallyAll\\nAll processes waiting for any events (default or specific) are woken up.\\n\\n\\nUsing timeouts\\n\\nMonitor>>waitMaxMilliseconds: anInteger\\nMonitor>>waitFor: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>wait (resp. Monitor>>waitFor:), but the process gets automatically woken up when the specified time has passed.\\n\\nMonitor>>waitWhile: aBlock maxMilliseconds: anInteger\\nMonitor>>waitWhile: aBlock for: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>waitWhile: (resp. Monitor>>waitWhile:for:), but the process gets automatically woken up when the specified time has passed.\\n\\nMonitor>>waitUntil: aBlock maxMilliseconds: anInteger\\nMonitor>>waitUntil: aBlock for: aSymbol maxMilliseconds: anInteger\\nSame as Monitor>>waitUntil: (resp. Monitor>>waitUntil:for:), but the process gets automatically woken up when the specified time has passed.!\\n\\n\\n!Monitor methodsFor: 'accessing' stamp: 'NS 7/1/2002 20:02'!\\ncleanup\\n\\tself checkOwnerProcess.\\n\\tself critical: [self privateCleanup].! !\\n\\n\\n!Monitor methodsFor: 'initialize-release' stamp: 'NS 4/13/2004 16:12'!\\ninitialize\\n\\tmutex _ Semaphore forMutualExclusion.\\n\\tqueuesMutex _ Semaphore forMutualExclusion.\\n\\tnestingLevel _ 0.! !\\n\\n\\n!Monitor methodsFor: 'signaling-default' stamp: 'NS 7/1/2002 21:57'!\\nsignal\\n\\t\\\"One process waiting for the default event is woken up.\\\"\\n\\n\\t^ self signal: nil! !\\n\\n!Monitor methodsFor: 'signaling-default' stamp: 'NS 7/1/2002 21:57'!\\nsignalAll\\n\\t\\\"All processes waiting for the default event are woken up.\\\"\\n\\n\\t^ self signalAll: nil! !\\n\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 4/13/2004 15:12'!\\nsignal: aSymbolOrNil\\n\\t\\\"One process waiting for the given event is woken up. If there is no process waiting \\n\\tfor this specific event, a process waiting for the default event gets resumed.\\\"\\n\\n\\t| queue |\\n\\tself checkOwnerProcess.\\n\\tqueue _ self queueFor: aSymbolOrNil.\\n\\tqueue isEmpty ifTrue: [queue _ self defaultQueue].\\n\\tself signalQueue: queue.! !\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 7/1/2002 22:02'!\\nsignalAll: aSymbolOrNil\\n\\t\\\"All process waiting for the given event or the default event are woken up.\\\"\\n\\n\\t| queue |\\n\\tself checkOwnerProcess.\\n\\tqueue _ self queueFor: aSymbolOrNil.\\n\\tself signalAllInQueue: self defaultQueue.\\n\\tqueue ~~ self defaultQueue ifTrue: [self signalAllInQueue: queue].! !\\n\\n!Monitor methodsFor: 'signaling-specific' stamp: 'NS 7/1/2002 22:02'!\\nsignalReallyAll\\n\\t\\\"All processes waiting for any events (default or specific) are woken up.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself signalAll.\\n\\tself queueDict valuesDo: [:queue |\\n\\t\\tself signalAllInQueue: queue].! !\\n\\n\\n!Monitor methodsFor: 'synchronization' stamp: 'NS 4/14/2004 13:13'!\\ncritical: aBlock\\n\\t\\\"Critical section.\\n\\tExecutes aBlock as a critical section. At any time, only one process can be executing code \\n\\tin a critical section.\\n\\tNOTE: All the following synchronization operations are only valid inside the critical section \\n\\tof the monitor!!\\\"\\n\\n\\t| result |\\n\\t[self enter.\\n\\tresult _ aBlock value] ensure: [self exit].\\n\\t^ result.! !\\n\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'NS 7/1/2002 21:55'!\\nwait\\n\\t\\\"Unconditional waiting for the default event.\\n\\tThe current process gets blocked and leaves the monitor, which means that the monitor\\n\\tallows another process to execute critical code. When the default event is signaled, the\\n\\toriginal process is resumed.\\\"\\n\\n\\t^ self waitMaxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'NS 7/1/2002 21:56'!\\nwaitUntil: aBlock\\n\\t\\\"Conditional waiting for the default event.\\n\\tSee Monitor>>waitWhile: aBlock.\\\"\\n\\n\\t^ self waitUntil: aBlock for: nil! !\\n\\n!Monitor methodsFor: 'waiting-basic' stamp: 'fbs 3/24/2004 14:39'!\\nwaitWhile: aBlock\\n\\t\\\"Conditional waiting for the default event.\\n\\tThe current process gets blocked and leaves the monitor only if the argument block\\n\\tevaluates to true. This means that another process can enter the monitor. When the \\n\\tdefault event is signaled, the original process is resumed, which means that the condition\\n\\t(argument block) is checked again. Only if it evaluates to false, does execution proceed.\\n\\tOtherwise, the process gets blocked and leaves the monitor again...\\\"\\n\\n\\t^ self waitWhile: aBlock for: nil! !\\n\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 21:58'!\\nwaitFor: aSymbolOrNil\\n\\t\\\"Unconditional waiting for the non-default event represented by the argument symbol.\\n\\tSame as Monitor>>wait, but the process gets only reactivated by the specific event and \\n\\tnot the default event.\\\"\\n\\n\\t^ self waitFor: aSymbolOrNil maxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 22:01'!\\nwaitUntil: aBlock for: aSymbolOrNil\\n\\t\\\"Confitional waiting for the non-default event represented by the argument symbol.\\n\\tSee Monitor>>waitWhile:for: aBlock.\\\"\\n\\n\\t^ self waitUntil: aBlock for: aSymbolOrNil maxMilliseconds: nil! !\\n\\n!Monitor methodsFor: 'waiting-specific' stamp: 'NS 7/1/2002 22:01'!\\nwaitWhile: aBlock for: aSymbolOrNil\\n\\t\\\"Confitional waiting for the non-default event represented by the argument symbol.\\n\\tSame as Monitor>>waitWhile:for:, but the process gets only reactivated by the specific \\n\\tevent and not the default event.\\\"\\n\\n\\t^ self waitWhile: aBlock for: aSymbolOrNil maxMilliseconds: nil! !\\n\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:03'!\\nwaitFor: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitFor:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself waitInQueue: (self queueFor: aSymbolOrNil) maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:04'!\\nwaitFor: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitFor:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitFor: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:04'!\\nwaitMaxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>wait, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitFor: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitMaxSeconds: aNumber\\n\\t\\\"Same as Monitor>>wait, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitMaxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock for: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitUntil:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: [aBlock value not] for: aSymbolOrNil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock for: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitUntil:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock for: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:05'!\\nwaitUntil: aBlock maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitUntil:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock for: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitUntil: aBlock maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitUntil:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitUntil: aBlock maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock for: aSymbolOrNil maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitWhile:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\tself checkOwnerProcess.\\n\\tself waitWhile: aBlock inQueue: (self queueFor: aSymbolOrNil) maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock for: aSymbolOrNil maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitWhile:for:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock for: aSymbolOrNil maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock maxMilliseconds: anIntegerOrNil\\n\\t\\\"Same as Monitor>>waitWhile:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock for: nil maxMilliseconds: anIntegerOrNil! !\\n\\n!Monitor methodsFor: 'waiting-timeout' stamp: 'NS 7/1/2002 22:06'!\\nwaitWhile: aBlock maxSeconds: aNumber\\n\\t\\\"Same as Monitor>>waitWhile:, but the process gets automatically woken up when the \\n\\tspecified time has passed.\\\"\\n\\n\\t^ self waitWhile: aBlock maxMilliseconds: (aNumber * 1000) asInteger! !\\n\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:40'!\\ncheckOwnerProcess\\n\\tself isOwnerProcess\\n\\t\\tifFalse: [self error: 'Monitor access violation'].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:06'!\\ndefaultQueue\\n\\tdefaultQueue ifNil: [defaultQueue _ OrderedCollection new].\\n\\t^ defaultQueue! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:37'!\\nenter\\n\\tself isOwnerProcess ifTrue: [\\n\\t\\tnestingLevel _ nestingLevel + 1.\\n\\t] ifFalse: [\\n\\t\\tmutex wait.\\n\\t\\townerProcess _ Processor activeProcess.\\n\\t\\tnestingLevel _ 1.\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 13:38'!\\nexit\\n\\tnestingLevel _ nestingLevel - 1.\\n\\tnestingLevel < 1 ifTrue: [\\n\\t\\townerProcess _ nil.\\n\\t\\tmutex signal\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:32'!\\nexitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\t| lock delay |\\n\\tqueuesMutex \\n\\t\\tcritical: [lock _ anOrderedCollection addLast: Semaphore new].\\n\\tself exit.\\n\\tanIntegerOrNil isNil ifTrue: [\\n\\t\\tlock wait\\n\\t] ifFalse: [\\n\\t\\tdelay _ MonitorDelay signalLock: lock afterMSecs: anIntegerOrNil inMonitor: self queue: anOrderedCollection.\\n\\t\\tlock wait.\\n\\t\\tdelay unschedule.\\n\\t].\\n\\tself enter.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:42'!\\nisOwnerProcess\\n\\t^ Processor activeProcess == ownerProcess! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:14'!\\nprivateCleanup\\n\\tqueuesMutex critical: [\\n\\t\\tdefaultQueue isEmpty ifTrue: [defaultQueue _ nil].\\n\\t\\tqueueDict ifNotNil: [\\n\\t\\t\\tqueueDict copy keysAndValuesDo: [:id :queue | \\n\\t\\t\\t\\tqueue isEmpty ifTrue: [queueDict removeKey: id]].\\n\\t\\t\\tqueueDict isEmpty ifTrue: [queueDict _ nil].\\n\\t\\t].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:10'!\\nqueueDict\\n\\tqueueDict ifNil: [queueDict _ IdentityDictionary new].\\n\\t^ queueDict.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 15:12'!\\nqueueFor: aSymbol\\n\\taSymbol ifNil: [^ self defaultQueue].\\n\\t^ self queueDict \\n\\t\\tat: aSymbol \\n\\t\\tifAbsent: [self queueDict at: aSymbol put: OrderedCollection new].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:10'!\\nsignalAllInQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\tanOrderedCollection do: [:lock | lock signal].\\n\\t\\tanOrderedCollection removeAllSuchThat: [:each | true].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:34'!\\nsignalLock: aSemaphore inQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\taSemaphore signal.\\n\\t\\tanOrderedCollection remove: aSemaphore ifAbsent: [].\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 4/13/2004 16:10'!\\nsignalQueue: anOrderedCollection\\n\\tqueuesMutex critical: [\\n\\t\\tanOrderedCollection isEmpty ifTrue: [^ self].\\n\\t\\tanOrderedCollection removeFirst signal.\\n\\t].! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 13:17'!\\nwaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\tself exitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil.! !\\n\\n!Monitor methodsFor: 'private' stamp: 'NS 7/1/2002 13:17'!\\nwaitWhile: aBlock inQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil\\n\\t[aBlock value] whileTrue: [self exitAndWaitInQueue: anOrderedCollection maxMilliseconds: anIntegerOrNil].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonitor class\\n\\tinstanceVariableNames: ''!\\nDelay subclass: #MonitorDelay\\n\\tinstanceVariableNames: 'monitor queue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!MonitorDelay commentStamp: 'NS 4/13/2004 16:51' prior: 0!\\nThis is a specialization of the class Delay that is used for the implementation of the class Monitor.!\\n\\n\\n!MonitorDelay methodsFor: 'private' stamp: 'NS 4/13/2004 16:26'!\\nsetDelay: anInteger forSemaphore: aSemaphore monitor: aMonitor queue: anOrderedCollection\\n\\tmonitor _ aMonitor.\\n\\tqueue _ anOrderedCollection.\\n\\tself setDelay: anInteger forSemaphore: aSemaphore.! !\\n\\n!MonitorDelay methodsFor: 'private' stamp: 'NS 4/13/2004 16:22'!\\nsignalWaitingProcess\\n\\t\\\"The delay time has elapsed; signal the waiting process.\\\"\\n\\n\\tbeingWaitedOn _ false.\\n\\tmonitor signalLock: delaySemaphore inQueue: queue.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonitorDelay class\\n\\tinstanceVariableNames: ''!\\n\\n!MonitorDelay class methodsFor: 'instance creation' stamp: 'NS 4/13/2004 16:25'!\\nsignalLock: aSemaphore afterMSecs: anInteger inMonitor: aMonitor queue: anOrderedCollection\\n\\tanInteger < 0 ifTrue: [self error: 'delay times cannot be negative'].\\n\\t^ (self new setDelay: anInteger forSemaphore: aSemaphore monitor: aMonitor queue: anOrderedCollection) schedule! !\\nTestCase subclass: #MonitorTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Processes'!\\n\\n!MonitorTest methodsFor: 'examples' stamp: 'md 3/19/2006 21:15'!\\ntestExample1\\n\\n\\t| producer1 producer2 monitor goal work counter goalReached finished |\\n\\tgoal _ (1 to: 1000) asOrderedCollection.\\n\\twork _ OrderedCollection new.\\n\\tcounter := 0.\\n\\tgoalReached := false.\\n\\tfinished := Semaphore new.\\n\\tmonitor := Monitor new.\\n\\n\\tproducer1 := [\\n [monitor critical:\\n [monitor waitUntil: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal\\n ].\\n goalReached\\n ]\\n whileFalse.\\n finished signal.\\n\\t].\\n\\n\\tproducer2 := [\\n [monitor critical:\\n [monitor waitWhile: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal].\\n goalReached\\n ] whileFalse.\\n finished signal\\n\\t].\\n\\n\\tproducer1 forkAt: Processor userBackgroundPriority.\\n\\tproducer2 forkAt: Processor userBackgroundPriority.\\n\\n\\tfinished wait; wait.\\n\\tself assert: goal = work! !\\n\\n!MonitorTest methodsFor: 'examples' stamp: 'md 3/19/2006 21:19'!\\ntestExample2\\n\\t\\\"Here is a second version that does not use a semaphore to inform the \\n\\tforking process about termination of both forked processes\\\"\\n\\n\\t| producer1 producer2 monitor goal work counter goalReached activeProducers|\\n\\tgoal _ (1 to: 1000) asOrderedCollection.\\n\\twork _ OrderedCollection new.\\n\\tcounter := 0.\\n\\tgoalReached := false.\\n\\tactiveProducers := 0.\\n\\tmonitor := Monitor new.\\n\\n producer1 :=\\n [ monitor critical: [activeProducers := activeProducers + 1].\\n [monitor critical:\\n [monitor waitUntil: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n \\\" Transcript show: 'P1 '; show: counter printString; show: ' ';\\n show: activeProducers printString; cr.\\\"\\n goalReached := counter >= goal size.\\n monitor signal\\n ].\\n goalReached\\n ]\\n whileFalse.\\n monitor critical: [activeProducers := activeProducers - 1.\\n monitor signal: #finish].\\n ] .\\n\\n producer2 :=\\n [monitor critical: [activeProducers := activeProducers + 1].\\n\\n [monitor critical:\\n [monitor waitWhile: [counter \\\\\\\\5 = 0].\\n goalReached or: [work add: (counter := counter + 1)].\\n goalReached := counter >= goal size.\\n monitor signal].\\n goalReached ] whileFalse.\\n monitor critical: [\\n\\t\\tactiveProducers := activeProducers - 1. \\n\\t\\tmonitor signal: #finish].\\n\\t].\\n\\n\\tproducer1 forkAt: Processor userBackgroundPriority.\\n\\tproducer2 forkAt: Processor userBackgroundPriority.\\n\\n\\n\\tmonitor critical: [\\n\\t\\tmonitor waitUntil: [activeProducers = 0 & (goalReached)]\\n\\t\\t\\t\\tfor: #finish.\\n \\t].\\n\\n\\tself assert: goal = work\\n! !\\nTimespan subclass: #Month\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'ChronologyConstants'\\n\\tcategory: 'Kernel-Chronology'!\\n!Month commentStamp: 'brp 5/13/2003 09:48' prior: 0!\\nI represent a month.!\\n\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:04'!\\nasMonth\\n\\n\\t^ self\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\ndaysInMonth\\n\\n\\t^ self duration days.! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nindex\\n\\n\\t^ self monthIndex\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nname\\n\\n\\n\\t^ self monthName\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nprevious\\n\\n\\n\\t^ self class starting: (self start - 1)\\n! !\\n\\n!Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'!\\nprintOn: aStream\\n\\n\\n\\taStream nextPutAll: self monthName, ' ', self year printString.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMonth class\\n\\tinstanceVariableNames: ''!\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:27'!\\ndaysInMonth: indexOrName forYear: yearInteger \\n\\n\\t| index |\\n\\tindex _ indexOrName isInteger \\n\\t\\t\\t\\tifTrue: [indexOrName]\\n\\t\\t\\t\\tifFalse: [self indexOfMonth: indexOrName].\\n\\t^ (DaysInMonth at: index)\\n\\t\\t\\t+ ((index = 2\\n\\t\\t\\t\\t\\tand: [Year isLeapYear: yearInteger])\\n\\t\\t\\t\\t\\t\\tifTrue: [1] ifFalse: [0])! !\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 09:29'!\\nindexOfMonth: aMonthName\\n\\n\\n\\t1 to: 12 do: [ :i | (aMonthName, '*' match: (MonthNames at: i)) ifTrue: [^i] ].\\n\\n\\tself error: aMonthName , ' is not a recognized month name'.! !\\n\\n!Month class methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 09:02'!\\nnameOfMonth: anIndex\\n\\n\\t^ MonthNames at: anIndex.! !\\n\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:22'!\\nmonth: month year: year\\n\\t\\\"Create a Month for the given <year> and <month>.\\n\\t<month> may be a number or a String with the\\n\\tname of the month. <year> should be with 4 digits.\\\"\\n\\n\\t^ self starting: (DateAndTime year: year month: month day: 1)\\n! !\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:21'!\\nreadFrom: aStream\\n\\n\\t| m y c |\\n\\n\\tm _ (ReadWriteStream with: '') reset.\\n\\n\\t[(c _ aStream next) isSeparator] whileFalse: [m nextPut: c].\\n\\n\\t[(c _ aStream next) isSeparator] whileTrue.\\n\\n\\ty _ (ReadWriteStream with: '') reset.\\n\\n\\ty nextPut: c.\\n\\n\\t[aStream atEnd] whileFalse: [y nextPut: aStream next].\\n\\n\\n\\t^ self \\n\\t\\tmonth: m contents\\n\\t\\tyear: y contents\\n\\n\\\"Month readFrom: 'July 1998' readStream\\\"\\n! !\\n\\n!Month class methodsFor: 'squeak protocol' stamp: 'brp 7/1/2003 13:59'!\\nstarting: aDateAndTime duration: aDuration \\n\\t\\\"Override - a each month has a defined duration\\\"\\n\\t| start adjusted days |\\n\\tstart _ aDateAndTime asDateAndTime.\\n\\tadjusted _ DateAndTime\\n\\t\\t\\t\\tyear: start year\\n\\t\\t\\t\\tmonth: start month\\n\\t\\t\\t\\tday: 1.\\n\\tdays _ self daysInMonth: adjusted month forYear: adjusted year.\\n\\t^ super\\n\\t\\tstarting: adjusted\\n\\t\\tduration: (Duration days: days)! !\\nClassTestCase subclass: #MonthTest\\n\\tinstanceVariableNames: 'month'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Chronology'!\\n!MonthTest commentStamp: 'brp 7/26/2003 22:44' prior: 0!\\nThis is the unit test for the class Month.\\n!\\n\\n\\n!MonthTest methodsFor: 'Coverage' stamp: 'brp 7/27/2003 12:42'!\\nclassToBeTested\\n\\n\\t^ Month! !\\n\\n!MonthTest methodsFor: 'Coverage' stamp: 'brp 7/26/2003 23:29'!\\nselectorsToBeIgnored\\n\\n\\t| deprecated private special |\\n\\tdeprecated := #().\\n\\tprivate := #( #printOn: ).\\n\\tspecial := #( #next ).\\n\\n\\t^ super selectorsToBeIgnored, deprecated, private, special.! !\\n\\n\\n!MonthTest methodsFor: 'Running' stamp: 'brp 8/6/2003 19:37'!\\nsetUp\\n\\n\\tsuper setUp.\\n\\tmonth _ Month month: 7 year: 1998.! !\\n\\n!MonthTest methodsFor: 'Running' stamp: 'brp 8/6/2003 19:37'!\\ntearDown\\n\\n\\tsuper tearDown.\\n\\tmonth _ nil.! !\\n\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:52'!\\ntestConverting\\n\\n\\tself assert: month asDate = '1 July 1998' asDate! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 1/30/2005 09:35'!\\ntestEnumerating\\n\\t| weeks |\\n\\tweeks := OrderedCollection new.\\n\\tmonth weeksDo: [ :w | weeks add: w start ].\\n\\t0 to: 4 do: [ :i | weeks remove: (Week starting: ('29 June 1998' asDate addDays: i * 7)) start ].\\n\\tself assert: weeks isEmpty! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 8/23/2003 16:08'!\\ntestInquiries\\n\\n\\tself \\n\\t\\tassert: month index = 7;\\n\\t\\tassert: month name = #July;\\n\\t\\tassert: month duration = (31 days).\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'nk 7/30/2004 17:52'!\\ntestInstanceCreation\\n\\t| m1 m2 |\\n\\tm1 := Month starting: '4 July 1998' asDate.\\n\\tm2 := Month month: #July year: 1998.\\n\\tself\\n\\t\\tassert: month = m1;\\n\\t\\tassert: month = m2! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 23:02'!\\ntestPreviousNext\\n\\t| n p |\\n\\tn := month next.\\n\\tp := month previous.\\n\\n\\tself\\n\\t\\tassert: n year = 1998;\\n\\t\\tassert: n index = 8;\\n\\t\\tassert: p year = 1998;\\n\\t\\tassert: p index = 6.\\n\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:50'!\\ntestPrinting\\n\\n\\tself \\n\\t\\tassert: month printString = 'July 1998'.\\n! !\\n\\n!MonthTest methodsFor: 'Tests' stamp: 'brp 7/26/2003 22:46'!\\ntestReadFrom\\n\\n\\t| m |\\n\\tm := Month readFrom: 'July 1998' readStream.\\n\\tself \\n\\t\\tassert: m = month! !\\nGesturalEvent subclass: #MoodGesturalEvent\\n\\tinstanceVariableNames: 'state'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-Events'!\\n\\n!MoodGesturalEvent methodsFor: 'accessing' stamp: 'len 9/7/1999 02:22'!\\nstate\\n\\t^ state! !\\n\\n!MoodGesturalEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nstate: aSymbol\\n\\tstate := aSymbol asSymbol! !\\n\\n\\n!MoodGesturalEvent methodsFor: 'playing' stamp: 'len 9/7/1999 02:23'!\\nactOn: aHeadMorph\\n\\taHeadMorph face perform: self state! !\\n\\n\\n!MoodGesturalEvent methodsFor: 'printing' stamp: 'len 9/7/1999 02:26'!\\nprintOn: aStream\\n\\taStream nextPutAll: 'set ', self state, ' mood'! !\\nObject subclass: #Morph\\n\\tinstanceVariableNames: 'bounds owner submorphs fullBounds color extension'\\n\\tclassVariableNames: 'EmptyArray'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!Morph commentStamp: 'efc 2/26/2003 20:01' prior: 0!\\nA Morph (from the Greek \\\"shape\\\" or \\\"form\\\") is an interactive graphical object. General information on the Morphic system can be found at http://minnow.cc.gatech.edu/squeak/30. \\n\\nMorphs exist in a tree, rooted at a World (generally a PasteUpMorph). The morphs owned by a morph are its submorphs. Morphs are drawn recursively; if a Morph has no owner it never gets drawn. To hide a Morph and its submorphs, set its #visible property to false using the #visible: method. \\n\\nThe World (screen) coordinate system is used for most coordinates, but can be changed if there is a TransformMorph somewhere in the owner chain. \\n\\nMy instance variables have accessor methods (e.g., #bounds, #bounds:). Most users should use the accessor methods instead of using the instance variables directly.\\n\\nStructure:\\ninstance var \\tType \\t\\t\\tDescription \\nbounds \\t\\t\\tRectangle \\t\\tA Rectangle indicating my position and a size that will enclose \\t\\t\\t\\t\\t\\t\\t\\t\\tme. \\nowner \\t\\t\\tMorph\\t\\t \\tMy parent Morph, or nil for the top-level Morph, which is a\\n \\t\\t\\t\\tor nil\\t\\t\\tworld, typically a PasteUpMorph.\\nsubmorphs \\t\\tArray \\t\\t\\tMy child Morphs. \\nfullBounds \\t\\tRectangle \\t\\tA Rectangle minimally enclosing me and my submorphs. \\ncolor \\t\\t\\tColor \\t\\t\\tMy primary color. Subclasses can use this in different ways. \\nextension \\t\\tMorphExtension Allows extra properties to be stored without adding a\\n\\t\\t\\t\\tor nil \\t\\t\\t\\tstorage burden to all morphs. \\n\\nBy default, Morphs do not position their submorphs. Morphs may position their submorphs directly or use a LayoutPolicy to automatically control their submorph positioning.\\n\\nAlthough Morph has some support for BorderStyle, most users should use BorderedMorph if they want borders.!\\n]style[(2 5 130 37 59 12 325 14 209 12 2 4 4 11 1 11 9 90 5 123 5 35 9 66 5 78 14 209 12 91 11 24 13 22)f1,f1LMorph Hierarchy;,f1,f1Rhttp://minnow.cc.gatech.edu/squeak/30;,f1,f1LPasteUpMorph Comment;,f1,f1LTransformMorph Comment;,f1,f1u,f1,f1u,f1,f1u,f1i,f1,f1LRectangle Comment;,f1,f1LMorph Comment;,f1,f1LArray Comment;,f1,f1LRectangle Comment;,f1,f1LColor Comment;,f1,f1LMorphExtension Comment;,f1,f1LLayoutPolicy Comment;,f1,f1LBorderStyle Comment;,f1,f1LBorderedMorph Comment;,f1!\\n\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/11/1998 16:46'!\\nactorState\\n\\t\\\"This method instantiates actorState as a side-effect.\\n\\tFor simple queries, use actorStateOrNil\\\"\\n\\t| state |\\n\\tstate _ self actorStateOrNil.\\n\\tstate ifNil:\\n\\t\\t[state _ ActorState new initializeFor: self assuredPlayer.\\n\\t\\tself actorState: state].\\n\\t^ state! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:51'!\\nactorStateOrNil\\n\\t\\\"answer the redeiver's actorState\\\"\\n\\t^ extension ifNotNil: [extension actorState]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:52'!\\nactorState: anActorState \\n\\t\\\"change the receiver's actorState\\\"\\n\\tself assureExtension actorState: anActorState! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/18/2001 20:09'!\\nadoptPaneColor: paneColor\\n\\tself submorphsDo:[:m| m adoptPaneColor: paneColor].! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:51'!\\nballoonText\\n\\t\\\"Answer balloon help text or nil, if no help is available. \\n\\tNB: subclasses may override such that they programatically \\n\\tconstruct the text, for economy's sake, such as model phrases in \\n\\ta Viewer\\\"\\n\\n\\t| text balloonSelector aString |\\n\\textension ifNil: [^nil].\\n\\t(text := extension balloonText) ifNotNil: [^text].\\n\\t(balloonSelector := extension balloonTextSelector) ifNotNil: \\n\\t\\t\\t[aString := ScriptingSystem helpStringOrNilFor: balloonSelector.\\n\\t\\t\\t(aString isNil and: [balloonSelector == #methodComment]) \\n\\t\\t\\t\\tifTrue: [aString := self methodCommentAsBalloonHelp].\\n\\t\\t\\t((aString isNil and: [balloonSelector numArgs = 0]) \\n\\t\\t\\t\\tand: [self respondsTo: balloonSelector]) \\n\\t\\t\\t\\t\\tifTrue: [aString := self perform: balloonSelector]].\\n\\t^aString ifNotNil: \\n\\t\\t\\t[aString asString \\n\\t\\t\\t\\twithNoLineLongerThan: Preferences maxBalloonHelpLineLength]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:52'!\\nballoonTextSelector\\n\\t\\\"Answer balloon text selector item in the extension, nil if none\\\"\\n\\t^ extension ifNotNil: [extension balloonTextSelector]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:50'!\\nballoonTextSelector: aSelector \\n\\t\\\"change the receiver's balloonTextSelector\\\"\\n\\tself assureExtension balloonTextSelector: aSelector! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/31/2001 21:06'!\\nbeFlap: aBool\\n\\t\\\"Mark the receiver with the #flap property, or unmark it\\\"\\n\\n\\taBool\\n\\t\\tifTrue:\\n\\t\\t\\t[self setProperty: #flap toValue: true.\\n\\t\\t\\tself hResizing: #rigid.\\n\\t\\t\\tself vResizing: #rigid]\\n\\t\\tifFalse:\\n\\t\\t\\t[self removeProperty: #flap]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:57'!\\nbeSticky\\n\\t\\\"make the receiver sticky\\\"\\n\\tself assureExtension sticky: true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:52'!\\nbeUnsticky\\n\\t\\\"If the receiver is marked as sticky, make it now be unsticky\\\"\\n\\textension ifNotNil: [extension sticky: false]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/25/2001 18:28'!\\nborderColor\\n\\t^self borderStyle color! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/15/2004 10:55'!\\nborderColor: aColorOrSymbolOrNil \\n\\t\\\"Unfortunately, the argument to borderColor could be more than \\tjust a color. \\n\\tIt could also be a symbol, in which case it is to be interpreted as a style identifier.\\n\\tBut I might not be able to draw that kind of border, so it may have to be ignored.\\n\\tOr it could be nil, in which case I should revert to the default border.\\\"\\n\\n\\t| style newStyle |\\n\\tstyle := self borderStyle.\\n\\tstyle baseColor = aColorOrSymbolOrNil\\n\\t\\tifTrue: [^ self].\\n\\n\\taColorOrSymbolOrNil isColor\\n\\t\\tifTrue: [style style = #none \\\"default border?\\\"\\n\\t\\t\\t\\tifTrue: [self borderStyle: (SimpleBorder width: 0 color: aColorOrSymbolOrNil)]\\n\\t\\t\\t\\tifFalse: [style baseColor: aColorOrSymbolOrNil.\\n\\t\\t\\t\\t\\tself changed].\\n\\t\\t\\t^ self].\\n\\n\\tself\\n\\t\\tborderStyle: ( ({ nil. #none } includes: aColorOrSymbolOrNil)\\n\\t\\t\\t\\tifTrue: [BorderStyle default]\\n\\t\\t\\t\\tifFalse: [ \\\"a symbol\\\"\\n\\t\\t\\t\\t\\tself doesBevels ifFalse: [ ^self ].\\n\\t\\t\\t\\t\\tnewStyle := (BorderStyle perform: aColorOrSymbolOrNil)\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: style color;\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: style width;\\n\\t\\t\\t\\t\\t\\t\\t\\tyourself.\\n\\t\\t\\t\\t\\t(self canDrawBorder: newStyle)\\n\\t\\t\\t\\t\\t\\tifTrue: [newStyle]\\n\\t\\t\\t\\t\\t\\tifFalse: [style]])! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 11/26/2001 14:53'!\\nborderStyle\\n\\t^(self valueOfProperty: #borderStyle ifAbsent:[BorderStyle default]) trackColorFrom: self! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/26/2001 16:18'!\\nborderStyleForSymbol: aStyleSymbol\\n\\t\\\"Answer a suitable BorderStyle for me of the type represented by a given symbol\\\"\\n\\n\\t| aStyle existing |\\n\\taStyle _ BorderStyle borderStyleForSymbol: aStyleSymbol asSymbol.\\n\\taStyle ifNil: [self error: 'bad style'].\\n\\texisting _ self borderStyle.\\n\\taStyle width: existing width;\\n\\t\\tbaseColor: existing baseColor.\\n\\t^ (self canDrawBorder: aStyle)\\n\\t\\tifTrue:\\n\\t\\t\\t[aStyle]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/11/2001 22:14'!\\nborderStyle: newStyle\\n\\tnewStyle = self borderStyle ifFalse:[\\n\\t\\t(self canDrawBorder: newStyle) ifFalse:[\\n\\t\\t\\t\\\"Replace the suggested border with a simple one\\\"\\n\\t\\t\\t^self borderStyle: (BorderStyle width: newStyle width color: (newStyle trackColorFrom: self) color)].\\n\\t\\tself setProperty: #borderStyle toValue: newStyle.\\n\\t\\tself changed].! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/25/2001 18:28'!\\nborderWidth\\n\\t^self borderStyle width! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 2/6/2001 14:02'!\\nborderWidthForRounding\\n\\n\\t^ self borderWidth! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/14/2004 17:48'!\\nborderWidth: aNumber\\n\\t| style |\\n\\tstyle _ self borderStyle.\\n\\tstyle width = aNumber ifTrue: [ ^self ].\\n\\n\\tstyle style = #none\\n\\t\\tifTrue: [ self borderStyle: (SimpleBorder width: aNumber color: Color transparent) ]\\n\\t\\tifFalse: [ style width: aNumber. self changed ].\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/1/2004 16:10'!\\nclearArea\\n\\t\\\"Answer the clear area of the receiver. It means the area free \\n\\tof docking bars.\\\"\\n\\t| visTop visBottom visLeft visRight |\\n\\n\\tvisTop := self top.\\n\\tvisBottom := self bottom.\\n\\tvisLeft := self left.\\n\\tvisRight := self right.\\n\\n\\tself dockingBars\\n\\t\\tdo: [:each | \\n\\t\\t\\t(each isAdheringToTop and: [each bottom > visTop])\\n\\t\\t\\t\\tifTrue: [visTop := each bottom].\\n\\n\\t\\t\\t(each isAdheringToBottom and: [each top < visBottom])\\n\\t\\t\\t\\tifTrue: [visBottom := each top].\\n\\n\\t\\t\\t(each isAdheringToLeft and: [each right > visLeft])\\n\\t\\t\\t\\tifTrue: [visLeft := each right].\\n\\n\\t\\t\\t(each isAdheringToRight and: [each left < visRight])\\n\\t\\t\\t\\tifTrue: [visRight := each left]\\n\\t\\t].\\n\\n\\t^ Rectangle\\n\\t\\tleft: visLeft\\n\\t\\tright: visRight\\n\\t\\ttop: visTop\\n\\t\\tbottom: visBottom\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 2/15/2001 15:55'!\\ncolor\\n\\n\\t^ color \\t\\\"has already been set to ((self valueOfProperty: #fillStyle) asColor)\\\"! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/15/2001 22:40'!\\ncolorForInsets\\n\\t\\\"Return the color to be used for shading inset borders. The default is my own color, but it might want to be, eg, my owner's color. Whoever's color ends up prevailing, the color itself gets the last chance to determine, so that when, for example, an InfiniteForm serves as the color, callers won't choke on some non-Color object being returned\\\"\\n\\t(color isColor and:[color isTransparent and:[owner notNil]]) ifTrue:[^owner colorForInsets].\\n\\t^ color colorForInsets\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 8/6/2001 09:03'!\\ncolor: aColor\\n\\t\\\"Set the receiver's color. Directly set the color if appropriate, else go by way of fillStyle\\\"\\n\\n\\t(aColor isColor or: [aColor isKindOf: InfiniteForm]) ifFalse:[^ self fillStyle: aColor].\\n\\tcolor = aColor ifFalse:\\n\\t\\t[self removeProperty: #fillStyle.\\n\\t\\tcolor _ aColor.\\n\\t\\tself changed]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:14'!\\nconnections\\n\\t\\\"Empty method in absence of connectors\\\"\\n\\t^ #()! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 12/27/2001 17:56'!\\ncouldHaveRoundedCorners\\n\\t^ true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 4/15/2004 07:50'!\\ndoesBevels\\n\\t\\\"To return true means that this object can show bevelled borders, and\\n\\ttherefore can accept, eg, #raised or #inset as valid borderColors.\\n\\tMust be overridden by subclasses that do not support bevelled borders.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:53'!\\neventHandler\\n\\t\\\"answer the receiver's eventHandler\\\"\\n\\t^ extension ifNotNil: [extension eventHandler] ! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 19:25'!\\neventHandler: anEventHandler \\n\\t\\\"Note that morphs can share eventHandlers and all is OK. \\\"\\n\\tself assureExtension eventHandler: anEventHandler! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 9/22/2000 13:36'!\\nforwardDirection\\n\\t\\\"Return the receiver's forward direction (in eToy terms)\\\"\\n\\t^self valueOfProperty: #forwardDirection ifAbsent:[0.0]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 1/3/1999 12:25'!\\nhasTranslucentColor\\n\\t\\\"Answer true if this any of this morph is translucent but not transparent.\\\"\\n\\n\\t^ color isColor and: [color isTranslucentColor]\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/30/1998 12:44'!\\nhighlight\\n\\t\\\"The receiver is being asked to appear in a highlighted state. Mostly used for textual morphs\\\"\\n\\tself color: self highlightColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/6/1999 02:09'!\\nhighlightColor\\n\\t\\n\\t| val |\\n\\t^ (val _ self valueOfProperty: #highlightColor)\\n\\t\\tifNotNil:\\n\\t\\t\\t[val ifNil: [self error: 'nil highlightColor']]\\n\\t\\tifNil:\\n\\t\\t\\t[owner ifNil: [self color] ifNotNil: [owner highlightColor]]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 7/2/1998 13:51'!\\nhighlightColor: aColor\\n\\tself setProperty: #highlightColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 1/31/2002 10:25'!\\ninsetColor\\n\\towner ifNil:[^self color].\\n\\t^ self colorForInsets! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 6/13/2001 01:04'!\\nisFlap\\n\\t\\\"Answer whether the receiver claims to be a flap\\\"\\n\\n\\t^ self hasProperty: #flap! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:53'!\\nisLocked\\n\\t\\\"answer whether the receiver is Locked\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension locked! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/27/2000 17:42'!\\nisShared\\n\\t\\\"Answer whether the receiver has the #shared property. This property allows it to be treated as a 'background' item\\\"\\n\\n\\t^ self hasProperty: #shared! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:57'!\\nisSticky\\n\\t\\\"answer whether the receiver is Sticky\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension sticky! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/4/97 12:05'!\\nlock\\n\\tself lock: true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:58'!\\nlock: aBoolean \\n\\t\\\"change the receiver's lock property\\\"\\n\\t(extension isNil and: [aBoolean not]) ifTrue: [^ self].\\n\\tself assureExtension locked: aBoolean! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 6/20/2001 15:45'!\\nmethodCommentAsBalloonHelp\\n\\t\\\"Given that I am a morph that is associated with an object and a method, answer a suitable method comment relating to that object & method if possible\\\"\\n\\n\\t| inherentSelector actual |\\n\\t(inherentSelector _ self valueOfProperty: #inherentSelector)\\n\\t\\tifNotNil:\\n\\t\\t\\t[(actual _ (self ownerThatIsA: PhraseTileMorph orA: SyntaxMorph) actualObject) ifNotNil:\\n\\t\\t\\t\\t[^ actual class precodeCommentOrInheritedCommentFor: inherentSelector]].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 10/23/1999 22:35'!\\nmodelOrNil\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 09:54'!\\nplayer\\n\\t\\\"answer the receiver's player\\\"\\n\\t^ extension ifNotNil: [extension player]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:18'!\\nplayerRepresented\\n\\t\\\"Answer the player represented by the receiver. Morphs that serve as references to other morphs reimplement this; be default a morph represents its own player.\\\"\\n\\n\\t^ self player! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:53'!\\nplayer: anObject \\n\\t\\\"change the receiver's player\\\"\\n\\tself assureExtension player: anObject! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/3/1999 13:08'!\\npresenter\\n\\t^ owner ifNotNil: [owner presenter] ifNil: [self currentWorld presenter]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 3/7/2003 15:24'!\\nraisedColor\\n\\t\\\"Return the color to be used for shading raised borders. The \\n\\tdefault is my own color, but it might want to be, eg, my \\n\\towner's color. Whoever's color ends up prevailing, the color \\n\\titself gets the last chance to determine, so that when, for \\n\\texample, an InfiniteForm serves as the color, callers won't choke \\n\\ton some non-Color object being returned\\\"\\n\\t(color isColor\\n\\t\\t\\tand: [color isTransparent\\n\\t\\t\\t\\t\\tand: [owner notNil]])\\n\\t\\tifTrue: [^ owner raisedColor].\\n\\t^ color asColor raisedColor!\\n]style[(11 2 355 3 5 18 5 26 5 24 5 18 5 20)f2b,f2,f2c145043000,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2,f2cmagenta;,f2! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 3/6/1999 02:09'!\\nregularColor\\n\\t\\n\\t| val |\\n\\t^ (val _ self valueOfProperty: #regularColor)\\n\\t\\tifNotNil:\\n\\t\\t\\t[val ifNil: [self error: 'nil regularColor']]\\n\\t\\tifNil:\\n\\t\\t\\t[owner ifNil: [self color] ifNotNil: [owner regularColor]]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 7/2/1998 13:51'!\\nregularColor: aColor\\n\\tself setProperty: #regularColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/29/2000 14:56'!\\nrememberedColor\\n\\t\\\"Answer a rememberedColor, or nil if none\\\"\\n\\n\\t^ self valueOfProperty: #rememberedColor ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/29/2000 15:47'!\\nrememberedColor: aColor\\n\\t\\\"Place aColor in a property so I can retrieve it later. A tortuous but expedient flow of data\\\"\\n\\n\\t^ self setProperty: #rememberedColor toValue: aColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 16:33'!\\nresistsRemoval\\n\\t\\\"Answer whether the receiver is marked as resisting removal\\\"\\n\\n\\t^ self hasProperty: #resistsRemoval! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 16:33'!\\nresistsRemoval: aBoolean\\n\\t\\\"Set the receiver's resistsRemoval property as indicated\\\"\\n\\n\\taBoolean\\n\\t\\tifTrue:\\n\\t\\t\\t[self setProperty: #resistsRemoval toValue: true]\\n\\t\\tifFalse:\\n\\t\\t\\t[self removeProperty: #resistsRemoval]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'nk 9/4/2004 10:49'!\\nscaleFactor\\n\\t^self valueOfProperty: #scaleFactor ifAbsent: [ 1.0 ]\\n! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/26/2001 16:16'!\\nsetBorderStyle: aSymbol\\n\\t\\\"Set the border style of my costume\\\"\\n\\n\\t| aStyle |\\n\\taStyle _ self borderStyleForSymbol: aSymbol.\\n\\taStyle ifNil: [^ self].\\n\\t(self canDrawBorder: aStyle)\\n\\t\\tifTrue:\\n\\t\\t\\t[self borderStyle: aStyle]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 12/4/1998 13:06'!\\nsqkPage\\n\\t^ self valueOfProperty: #SqueakPage! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 08:33'!\\nsticky: aBoolean \\n\\t\\\"change the receiver's sticky property\\\"\\n\\textension sticky: aBoolean! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'RAA 2/19/2001 17:38'!\\ntoggleLocked\\n\\t\\n\\tself lock: self isLocked not! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/15/2001 12:21'!\\ntoggleResistsRemoval\\n\\t\\\"Toggle the resistsRemoval property\\\"\\n\\n\\tself resistsRemoval\\n\\t\\tifTrue:\\n\\t\\t\\t[self removeProperty: #resistsRemoval]\\n\\t\\tifFalse:\\n\\t\\t\\t[self setProperty: #resistsRemoval toValue: true]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'md 2/27/2006 08:53'!\\ntoggleStickiness\\n\\t\\\"togle the receiver's Stickiness\\\"\\n\\textension ifNil: [^ self beSticky].\\n\\textension sticky: extension sticky not! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 11/30/1998 12:44'!\\nunHighlight\\n\\tself color: self regularColor! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'di 8/11/1998 12:33'!\\nunlock\\n\\tself lock: false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'sw 8/15/97 23:59'!\\nunlockContents\\n\\tself submorphsDo:\\n\\t\\t[:m | m unlock]! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 2/17/1999 11:45'!\\nurl\\n\\t\\\"If I have been assigned a url, return it. For PasteUpMorphs mostly.\\\"\\n\\t| sq |\\n\\t(sq _ self sqkPage) ifNotNil: [^ sq url].\\n\\t^ self valueOfProperty: #url\\n\\t\\t! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'tk 12/16/1998 11:54'!\\nuserString\\n\\t\\\"Do I have a text string to be searched on?\\\"\\n\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/27/2004 11:45'!\\nviewBox\\n\\t^ self pasteUpMorph viewBox! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 9/1/2004 16:14'!\\nvisibleClearArea\\n\\t\\\"Answer the receiver visible clear area. The intersection \\n\\tbetween the clear area and the viewbox.\\\"\\n\\t^ self viewBox intersect: self clearArea! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 4/4/2006 17:14'!\\nwantsEmbeddingsVocabulary\\n\\t\\\"Empty method in absence of connectors\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'ar 6/23/2001 16:06'!\\nwantsToBeCachedByHand\\n\\t\\\"Return true if the receiver wants to be cached by the hand when it is dragged around.\\n\\tNote: The default implementation queries all submorphs since subclasses may have shapes that do not fill the receiver's bounds completely.\\\"\\n\\tself hasTranslucentColor ifTrue:[^false].\\n\\tself submorphsDo:[:m|\\n\\t\\tm wantsToBeCachedByHand ifFalse:[^false].\\n\\t].\\n\\t^true! !\\n\\n!Morph methodsFor: 'accessing' stamp: 'dgd 8/31/2004 16:21'!\\nwantsToBeTopmost\\n\\t\\\"Answer if the receiver want to be one of the topmost objects in its owner\\\"\\n\\t^ self isFlapOrTab! !\\n\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:46'!\\nassureExtension\\n\\t\\\"creates an extension for the receiver if needed\\\"\\n\\textension ifNil: [self initializeExtension].\\n\\t^ extension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'dgd 2/16/2003 19:22'!\\nextension\\n\\t\\\"answer the recevier's extension\\\"\\n\\t^ extension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:31'!\\nhasExtension\\n\\t\\\"answer whether the receiver has extention\\\"\\n\\t^ extension notNil! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:35'!\\ninitializeExtension\\n\\t\\\"private - initializes the receiver's extension\\\"\\n\\textension := MorphExtension new! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:46'!\\nprivateExtension: aMorphExtension\\n\\t\\\"private - change the receiver's extension\\\"\\n\\textension := aMorphExtension! !\\n\\n!Morph methodsFor: 'accessing - extension' stamp: 'md 2/27/2006 08:47'!\\nresetExtension\\n\\t\\\"reset the extension slot if it is not needed\\\"\\n\\t(extension notNil and: [extension isDefault]) ifTrue: [extension := nil] ! !\\n\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:47'!\\nhasProperty: aSymbol \\n\\t\\\"Answer whether the receiver has the property named aSymbol\\\"\\n\\textension ifNil: [^ false].\\n\\t^extension hasProperty: aSymbol! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:47'!\\notherProperties\\n\\t\\\"answer the receiver's otherProperties\\\"\\n\\t^ extension ifNotNil: [extension otherProperties]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:48'!\\nremoveProperty: aSymbol \\n\\t\\\"removes the property named aSymbol if it exists\\\"\\n\\textension ifNil: [^ self].\\n\\textension removeProperty: aSymbol! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'tk 10/9/2002 08:30'!\\nsetProperties: aList\\n\\t\\\"Set many properties at once from a list of prop, value, prop, value\\\"\\n\\n\\t1 to: aList size by: 2 do: [:ii |\\n\\t\\tself setProperty: (aList at: ii) toValue: (aList at: ii+1)].! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 09:48'!\\nsetProperty: aSymbol toValue: anObject \\n\\t\\\"change the receiver's property named aSymbol to anObject\\\"\\n\\tanObject ifNil: [^ self removeProperty: aSymbol].\\n\\tself assureExtension setProperty: aSymbol toValue: anObject! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:53'!\\nvalueOfProperty: aSymbol \\n\\t\\\"answer the value of the receiver's property named aSymbol\\\"\\n\\t^ extension ifNotNil: [extension valueOfProperty: aSymbol]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'dgd 2/16/2003 20:55'!\\nvalueOfProperty: aSymbol ifAbsentPut: aBlock \\n\\t\\\"If the receiver possesses a property of the given name, answer \\n\\tits value. If not, then create a property of the given name, give \\n\\tit the value obtained by evaluating aBlock, then answer that \\n\\tvalue\\\"\\n\\t^ self assureExtension valueOfProperty: aSymbol ifAbsentPut: aBlock! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:50'!\\nvalueOfProperty: aSymbol ifAbsent: aBlock \\n\\t\\\"if the receiver possesses a property of the given name, answer \\n\\tits value. If not then evaluate aBlock and answer the result of \\n\\tthis block evaluation\\\"\\n\\t^ extension \\n\\t\\tifNotNil: [extension valueOfProperty: aSymbol ifAbsent: aBlock]\\n\\t\\tifNil: [aBlock value]! !\\n\\n!Morph methodsFor: 'accessing - properties' stamp: 'md 2/27/2006 08:49'!\\nvalueOfProperty: aSymbol ifPresentDo: aBlock \\n\\t\\\"If the receiver has a property of the given name, evaluate \\n\\taBlock on behalf of the value of that property\\\"\\n\\textension ifNil: [^ self].\\n\\t^ aBlock value: (extension valueOfProperty: aSymbol ifAbsent: [^ self])! !\\n\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:35'!\\nfullLoadCachedState\\n\\t\\\"Load the cached state of the receiver and its full submorph tree.\\\"\\n\\n\\tself allMorphsDo: [:m | m loadCachedState].\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:34'!\\nfullReleaseCachedState\\n\\t\\\"Release the cached state of the receiver and its full submorph tree.\\\"\\n\\n\\tself allMorphsDo: [:m | m releaseCachedState].\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'jm 11/13/97 16:37'!\\nloadCachedState\\n\\t\\\"Load the cached state of this morph. This method may be called to pre-load the cached state of a morph to avoid delays when it is first used. (Cached state can always be recompued on demand, so a morph should not rely on this method being called.) Implementations of this method should do 'super loadCachedState'. This default implementation does nothing.\\\"\\n! !\\n\\n!Morph methodsFor: 'caching' stamp: 'md 4/3/2006 12:02'!\\nreleaseCachedState\\n\\t\\\"Release any state that can be recomputed on demand, such as the pixel values for a color gradient or the editor state for a TextMorph. This method may be called to save space when a morph becomes inaccessible. Implementations of this method should do 'super releaseCachedState'.\\\"\\n\\tself borderStyle releaseCachedState. \\n! !\\n\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sd 3/30/2005 22:04'!\\nabstractAModel\\n\\t\\\"Find data-containing fields in me. Make a new class, whose instance variables are named for my fields, and whose values are the values I am showing. Use a CardPlayer for now. Force the user to name the fields. Make slots for text, Number Watchers, SketchMorphs, and ImageMorphs.\\\"\\n\\n\\t| instVarNames unnamed ans player twoListsOfMorphs holdsSepData docks oldPlayer iVarName |\\n\\t(oldPlayer := self player) ifNotNil: \\n\\t\\t\\t[oldPlayer belongsToUniClass \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Player\\\"\\n\\n\\t\\t\\t\\t\\toldPlayer class instVarNames notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[self \\n\\t\\t\\t\\t\\t\\t\\t\\tinform: 'I already have a regular Player, so I can''t have a CardPlayer'.\\n\\t\\t\\t\\t\\t\\t\\t^true]]].\\n\\ttwoListsOfMorphs := StackMorph discoverSlots: self.\\n\\tholdsSepData := twoListsOfMorphs first.\\n\\tinstVarNames := ''.\\n\\tholdsSepData do: \\n\\t\\t\\t[:ea | \\n\\t\\t\\tiVarName := Scanner wellFormedInstanceVariableNameFrom: ea knownName.\\n\\t\\t\\tiVarName = ea knownName ifFalse: [ea name: iVarName].\\n\\t\\t\\tinstVarNames := instVarNames , iVarName , ' '].\\n\\tunnamed := twoListsOfMorphs second.\\t\\\"have default names\\\"\\n\\tinstVarNames isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tinform: 'No named fields were found.\\nPlease get a halo on each field and give it a name.\\nLabels or non-data fields should be named \\\"shared xxx\\\".'.\\n\\t\\t\\t^false].\\n\\tunnamed notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[ans := PopUpMenu \\n\\t\\t\\t\\t\\t\\tconfirm: 'Data fields are ' , instVarNames printString \\n\\t\\t\\t\\t\\t\\t\\t\\t, ('\\\\Some fields are not named. Are they labels or non-data fields?' \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t, '\\\\Please get a halo on each data field and give it a name.') withCRs\\n\\t\\t\\t\\t\\t\\ttrueChoice: 'All other fields are non-data fields'\\n\\t\\t\\t\\t\\t\\tfalseChoice: 'Stop. Let me give a name to some more fields'.\\n\\t\\t\\tans ifFalse: [^false]].\\n\\tunnamed \\n\\t\\twithIndexDo: [:mm :ind | mm setName: 'shared label ' , ind printString].\\n\\t\\\"Make a Player with instVarNames. Make me be the costume\\\"\\n\\tplayer := CardPlayer instanceOfUniqueClassWithInstVarString: instVarNames\\n\\t\\t\\t\\tandClassInstVarString: ''.\\n\\tself player: player.\\n\\tplayer costume: self.\\n\\t\\\"Fill in the instance values. Make docks first.\\\"\\n\\tdocks := OrderedCollection new.\\n\\tholdsSepData do: \\n\\t\\t\\t[:morph | \\n\\t\\t\\tmorph setProperty: #shared toValue: true.\\t\\\"in case it is deeply embedded\\\"\\n\\t\\t\\tmorph setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\t\\t\\tplayer class compileInstVarAccessorsFor: morph knownName.\\n\\t\\t\\tmorph isSyntaxMorph ifTrue: [morph setTarget: player].\\t\\\"hookup the UpdatingString!!\\\"\\n\\t\\t\\tdocks addAll: morph variableDocks].\\n\\tplayer class newVariableDocks: docks.\\n\\tdocks do: [:dd | dd storeMorphDataInInstance: player].\\n\\t\\\"oldPlayer class mdict do: [:assoc | move to player].\\tmove methods to new class?\\\"\\n\\t\\\"oldPlayer become: player.\\\"\\n\\t^true\\t\\\"success\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:31'!\\nbeAStackBackground\\n\\t\\\"Transform the receiver into one that has stack-background behavior. If just becoming a stack, allocate a uniclass to represent the cards (if one does not already exist\\\"\\n\\n\\tself assuredCardPlayer assureUniClass.\\n\\tself setProperty: #tabAmongFields toValue: true.\\n\\tself setProperty: #stackBackground toValue: true.\\n\\t\\\"put my submorphs onto the background\\\"\\n\\tsubmorphs do: [:mm | mm setProperty: #shared toValue: true].\\n\\tself reassessBackgroundShape! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 11/8/2002 14:57'!\\nbecomeSharedBackgroundField\\n\\t\\\"Mark the receiver as holding separate data for each instance (i.e., like a 'background field') and reassess the shape of the corresponding background so that it will be able to accommodate this arrangement.\\\"\\n\\n\\t((self hasProperty: #shared) and: [self hasProperty: #holdsSeparateDataForEachInstance])\\n\\t\\tifFalse: \\n\\t\\t\\t[self setProperty: #shared toValue: true.\\n\\t\\t\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\t\\t\\tself stack reassessBackgroundShape]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 18:54'!\\ncontainsCard: aCard\\n\\t\\\"Answer whether the given card belongs to the uniclass representing the receiver\\\"\\n\\n\\t^ self isStackBackground and: [aCard isKindOf: self player class baseUniclass]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/27/2000 17:36'!\\ncouldHoldSeparateDataForEachInstance\\n\\t\\\"Answer whether this type of morph is inherently capable of holding separate data for each instance ('card data')\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:32'!\\ncurrentDataInstance\\n\\t\\\"Answer the current data instance\\\"\\n\\n\\t^ self player! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:33'!\\nexplainDesignations\\n\\t\\\"Hand the user an object that contains explanations for the designation feedback used\\\"\\n\\n\\tStackMorph designationsExplainer openInHand\\n\\n\\t\\\"self currentWorld explainDesignations\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:49'!\\ngoToNextCardInStack\\n\\t\\\"Tell my stack to advance to the next page\\\"\\n\\n\\tself stackDo: [:aStack | aStack goToNextCardInStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:52'!\\ngoToPreviousCardInStack\\n\\t\\\"Tell my stack to advance to the previous card\\\"\\n\\t\\n\\tself stackDo: [:aStack | aStack goToPreviousCardInStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/27/2000 17:41'!\\nholdsSeparateDataForEachInstance\\n\\t\\\"Answer whether the receiver is currently behaving as a 'background field', i.e., whether it is marked as shared (viz. occurring on the background of a stack) *and* is marked as holding separate data for each instance\\\"\\n\\n\\t^ self isShared and: [self hasProperty: #holdsSeparateDataForEachInstance]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'yo 2/17/2005 17:47'!\\ninsertAsStackBackground\\n\\t\\\"I am not yet in a stack. Find a Stack that my reference point (center) overlaps, and insert me as a new background.\\\"\\n\\n\\t| aMorph |\\n\\tself isStackBackground ifTrue: [^ Beeper beep].\\t\\n\\t\\t\\\"already in a stack. Must clear flags when remove.\\\"\\n\\\"\\tself potentialEmbeddingTargets do: [:mm | No, force user to choose a stack. \\n\\t\\t(mm respondsTo: #insertAsBackground:resize:) ifTrue: [\\n\\t\\t\\t^ mm insertAsBackground: self resize: false]].\\n\\\"\\n\\t\\\"None found, ask user\\\"\\n\\tself inform: 'Please click on a Stack' translated.\\n\\tSensor waitNoButton.\\n\\taMorph _ self world chooseClickTarget.\\n\\taMorph ifNil: [^ self].\\n\\t(aMorph ownerThatIsA: StackMorph) insertAsBackground: self resize: false.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:35'!\\ninsertCard\\n\\t\\\"Insert a new card in the stack, with the receiver as its background, and have it become the current card of the stack\\\"\\n\\n\\tself stackDo: [:aStack | aStack insertCardOfBackground: self]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 11/8/2002 15:16'!\\ninstallAsCurrent: anInstance\\n\\t\\\"Install anInstance as the one currently viewed in the receiver. Dock up all the morphs in the receiver which contain data rooted in the player instance to the instance data. Run any 'opening' scripts that pertain.\\\"\\n\\n\\t| fieldList itsFocus |\\n\\tself player == anInstance ifTrue: [^ self].\\n\\tfieldList _ self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]].\\n\\tself currentWorld hands do:\\n\\t\\t[:aHand | (itsFocus _ aHand keyboardFocus) notNil ifTrue:\\n\\t\\t\\t[(fieldList includes: itsFocus) ifTrue: [aHand newKeyboardFocus: nil]]].\\n\\n\\tself player uninstallFrom: self. \\\"out with the old\\\"\\n\\n\\tanInstance installPrivateMorphsInto: self.\\n\\tself changed.\\n\\tanInstance costume: self.\\n\\tself player: anInstance.\\n\\tself player class variableDocks do:\\n\\t\\t[:aVariableDock | aVariableDock dockMorphUpToInstance: anInstance].\\n\\tself currentWorld startSteppingSubmorphsOf: self! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:42'!\\nisStackBackground\\n\\t\\\"Answer whether the receiver serves as a background of a stack\\\"\\n\\n\\t^ ((owner isKindOf: StackMorph) and: [owner currentPage == self]) or:\\n\\t\\t[self hasProperty: #stackBackground]\\n\\n\\t\\\"This odd property-based check is because when a paste-up-morph is not the *current* background of a stack, it is maddeningly ownerlyess\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:38'!\\nmakeHoldSeparateDataForEachInstance\\n\\t\\\"Mark the receiver as holding separate data for each instance (i.e., like a 'background field') and reassess the shape of the corresponding background so that it will be able to accommodate this arrangement.\\\"\\n\\n\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true.\\n\\tself stack reassessBackgroundShape.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'nb 6/17/2003 12:25'!\\nnewCard\\n\\t\\\"Create a new card for the receiver and return it\\\"\\n\\n\\t| aNewInstance |\\n\\tself isStackBackground ifFalse: [^ Beeper beep]. \\\"bulletproof against deconstruction\\\"\\n\\taNewInstance _ self player class baseUniclass new.\\n\\t^ aNewInstance! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'md 10/22/2003 15:52'!\\nreassessBackgroundShape\\n\\t\\\"A change has been made which may affect the instance structure of the Card uniclass that holds the instance state, which can also be thought of as the 'card data'.\\\"\\n\\n\\t\\\"Caution: still to be done: the mechanism so that when a new instance variable is added, it gets initialized in all subinstances of the receiver's player, which are the cards of this shape. One needs to take into account here the instance variable names coming in; those that are unchanged should keep their values, but those that have newly arrived should obtain their default values from the morphs on whose behalf they are being maintained in the model\\\"\\n\\n\\t| takenNames uniqueName requestedName variableDocks docks sepDataMorphs sorted existing name1 name2 |\\n\\tself isStackBackground ifFalse: [^Beeper beep].\\t\\\"bulletproof against deconstruction\\\"\\n\\tCursor wait showWhile: \\n\\t\\t\\t[variableDocks := OrderedCollection new.\\t\\\"This will be stored in the uniclass's \\n\\t\\t\\tclass-side inst var #variableDocks\\\"\\n\\t\\t\\ttakenNames := OrderedCollection new.\\n\\t\\t\\tsepDataMorphs := OrderedCollection new.\\t\\\"fields, holders of per-card data\\\"\\n\\t\\t\\tself submorphs do: \\n\\t\\t\\t\\t\\t[:aMorph | \\n\\t\\t\\t\\t\\taMorph renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\t\\t\\tifTrue: [sepDataMorphs add: aMorph renderedMorph]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"look for buried fields, inside a frame\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\taMorph renderedMorph isShared \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[aMorph allMorphs do: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:mm | \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmm renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [sepDataMorphs add: mm renderedMorph]]]]].\\n\\t\\t\\tsorted := SortedCollection new \\n\\t\\t\\t\\t\\t\\tsortBlock: [:a :b | (a valueOfProperty: #cardInstance) notNil].\\t\\\"puts existing ones first\\\"\\n\\t\\t\\tsorted addAll: sepDataMorphs.\\n\\t\\t\\tsorted do: \\n\\t\\t\\t\\t\\t[:aMorph | \\n\\t\\t\\t\\t\\tdocks := aMorph variableDocks.\\n\\t\\t\\t\\t\\t\\\"Each morph can request multiple variables. \\n\\tThis complicates matters somewhat but creates a generality for Fabrk-like uses.\\n\\tEach spec is an instance of VariableDock, and it provides a point of departure\\n\\tfor the negotiation between the PasteUp and its constitutent morphs\\\"\\n\\t\\t\\t\\t\\tdocks do: \\n\\t\\t\\t\\t\\t\\t\\t[:aVariableDock | \\n\\t\\t\\t\\t\\t\\t\\tuniqueName := self player \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniqueInstanceVariableNameLike: (requestedName := aVariableDock \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvariableName)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texcluding: takenNames.\\n\\t\\t\\t\\t\\t\\t\\tuniqueName ~= requestedName \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[aVariableDock variableName: uniqueName.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taMorph noteNegotiatedName: uniqueName for: requestedName].\\n\\t\\t\\t\\t\\t\\t\\ttakenNames add: uniqueName].\\n\\t\\t\\t\\t\\tvariableDocks addAll: docks].\\n\\t\\t\\texisting := self player class instVarNames.\\n\\t\\t\\tvariableDocks := (variableDocks asSortedCollection: \\n\\t\\t\\t\\t\\t\\t\\t[:dock1 :dock2 | \\n\\t\\t\\t\\t\\t\\t\\tname1 := dock1 variableName.\\n\\t\\t\\t\\t\\t\\t\\tname2 := dock2 variableName.\\n\\t\\t\\t\\t\\t\\t\\t(existing indexOf: name1 ifAbsent: [0]) \\n\\t\\t\\t\\t\\t\\t\\t\\t< (existing indexOf: name2 ifAbsent: [variableDocks size])]) \\n\\t\\t\\t\\t\\t\\tasOrderedCollection.\\n\\t\\t\\tself player class setNewInstVarNames: (variableDocks \\n\\t\\t\\t\\t\\t\\tcollect: [:info | info variableName asString]).\\n\\t\\t\\t\\\"NB: sets up accessors, and removes obsolete ones\\\"\\n\\t\\t\\tself player class newVariableDocks: variableDocks]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:46'!\\nrelaxGripOnVariableNames\\n\\t\\\"Abandon any memory of specific variable names that should be preserved. The overall situation here is not yet completely understood, and this relaxation is basically always done on each reassessment of the background shape nowadays. But this doesn't feel quite right, because if the user has somehow intervened to specify certain name preference we should perhaps honored it. Or perhaps that is no longer relevant. ????\\\"\\n\\n\\tself submorphs do:\\n\\t\\t[:m | m removeProperty: #variableName.\\n\\t\\tm removeProperty: #setterSelector].\\n\\tself reassessBackgroundShape\\n! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:47'!\\nreshapeBackground\\n\\t\\\"Abandon any memory of variable-name preferences, and reassess the shape of the background\\\"\\n\\n\\tself relaxGripOnVariableNames.\\n\\t\\\"self reassessBackgroundShape.\\talready done there\\\"! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/24/2000 06:30'!\\nsetAsDefaultValueForNewCard\\n\\t\\\"Set the receiver's current value as the one to be used to supply the default value for a variable on a new card. This implementation does not support multiple variables per morph, which is problematical\\\"\\n\\n\\tself setProperty: #defaultValue toValue: self currentDataValue deepCopy! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:48'!\\nshowBackgroundObjects\\n\\t\\\"Momentarily highlight just the background objects on the current playfield\\\"\\n\\n\\tself isStackBackground ifFalse: [^ self].\\n\\tself invalidRect: self bounds.\\n\\tself currentWorld doOneCycle.\\n\\tDisplay restoreAfter:\\n\\t\\t[self submorphsDo:\\n\\t\\t\\t[:aMorph | (aMorph renderedMorph hasProperty: #shared)\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[Display border: (aMorph fullBoundsInWorld insetBy: -6) \\n\\t\\t\\t\\t\\t\\t\\twidth: 6 rule: Form over fillColor: Color blue]]]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'aoy 2/15/2003 21:50'!\\nshowDesignationsOfObjects\\n\\t\\\"Momentarily show the designations of objects on the receiver\\\"\\n\\n\\t| colorToUse aLabel |\\n\\tself isStackBackground ifFalse: [^self].\\n\\tself submorphsDo: \\n\\t\\t\\t[:aMorph | \\n\\t\\t\\taLabel :=aMorph renderedMorph holdsSeparateDataForEachInstance \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[colorToUse := Color orange.\\n\\t\\t\\t\\t\\t aMorph externalName]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[colorToUse := aMorph isShared ifFalse: [Color red] ifTrue: [Color green].\\n\\t\\t\\t\\t\\t nil].\\n\\t\\t\\tDisplay \\n\\t\\t\\t\\tborder: (aMorph fullBoundsInWorld insetBy: -6)\\n\\t\\t\\t\\twidth: 6\\n\\t\\t\\t\\trule: Form over\\n\\t\\t\\t\\tfillColor: colorToUse.\\n\\t\\t\\taLabel ifNotNil: \\n\\t\\t\\t\\t\\t[aLabel asString \\n\\t\\t\\t\\t\\t\\tdisplayOn: Display\\n\\t\\t\\t\\t\\t\\tat: aMorph fullBoundsInWorld bottomLeft + (0 @ 5)\\n\\t\\t\\t\\t\\t\\ttextColor: Color blue]].\\n\\tSensor anyButtonPressed \\n\\t\\tifTrue: [Sensor waitNoButton]\\n\\t\\tifFalse: [Sensor waitButton].\\n\\tWorld fullRepaintNeeded! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 10/30/2001 13:50'!\\nshowForegroundObjects\\n\\t\\\"Temporarily highlight the foreground objects\\\"\\n\\n\\tself isStackBackground ifFalse: [^ self].\\n\\tDisplay restoreAfter:\\n\\t\\t[self submorphsDo:\\n\\t\\t\\t[:aMorph | aMorph renderedMorph isShared\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[Display border: (aMorph fullBoundsInWorld insetBy: -6) \\n\\t\\t\\t\\t\\t\\twidth: 6 rule: Form over fillColor: Color orange]]]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:53'!\\nstack\\n\\t\\\"Answer the nearest containing Stack, or, if none, a stack in the current project, and if still none, nil. The extra messiness is because uninstalled backgrounds don't have an owner pointers to their stack.\\\"\\n\\n\\t| aStack bkgnd |\\n\\tbkgnd _ self orOwnerSuchThat: [:oo | oo hasProperty: #myStack].\\n\\tbkgnd ifNotNil: [^ bkgnd valueOfProperty: #myStack].\\n\\n\\t\\\"fallbacks\\\"\\n\\t(aStack _ self ownerThatIsA: StackMorph) ifNotNil: [^ aStack].\\n\\t^ Project current currentStack! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 14:38'!\\nstackDo: aBlock\\n\\t\\\"If the receiver has a stack, evaluate aBlock on its behalf\\\"\\n\\n\\t| aStack |\\n\\t(aStack _ self ownerThatIsA: StackMorph) ifNotNil:\\n\\t\\t[^ aBlock value: aStack]! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/2/2001 13:38'!\\nstopHoldingSeparateDataForEachInstance\\n\\t\\\"Make the receiver no longer hold separate data for each instance\\\"\\n\\n\\tself removeProperty: #holdsSeparateDataForEachInstance.\\n\\tself stack reassessBackgroundShape.! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'dgd 8/28/2004 19:15'!\\ntabHitWithEvent: anEvent\\n\\t\\\"The tab key was hit. The keyboard focus has referred this event to me, though this perhaps seems rather backwards. Anyway, the assumption is that I have the property #tabAmongFields, so now the task is to tab to the next field.\\\"\\n\\n\\t| currentFocus fieldList anIndex itemToHighlight variableBearingMorphs otherAmenableMorphs |\\n\\tcurrentFocus _ anEvent hand keyboardFocus.\\n\\tfieldList _ self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]].\\n\\n\\tfieldList isEmpty ifTrue:[^ self].\\n\\n\\tvariableBearingMorphs _ self player isNil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue:[#()]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse:[self player class variableDocks collect: [:vd | vd definingMorph] thenSelect: [:m | m isInWorld]].\\n\\totherAmenableMorphs _ (self allMorphs select:\\n\\t\\t[:aMorph | (aMorph wouldAcceptKeyboardFocusUponTab) and: [aMorph isLocked not]])\\n\\t\\t\\tcopyWithoutAll: variableBearingMorphs.\\n\\tfieldList _ variableBearingMorphs, otherAmenableMorphs.\\n\\n\\tanIndex _ fieldList indexOf: currentFocus ifAbsent: [nil].\\n\\titemToHighlight _ fieldList atWrap: \\n\\t\\t(anIndex ifNotNil: [anEvent shiftPressed ifTrue: [anIndex - 1] ifFalse: [anIndex + 1]]\\n\\t\\t\\t\\tifNil: [1]).\\n\\tanEvent hand newKeyboardFocus: itemToHighlight. self flag: #arNote. \\\"really???\\\"\\n\\titemToHighlight editor selectAll.\\n\\titemToHighlight invalidRect: itemToHighlight bounds ! !\\n\\n!Morph methodsFor: 'card in a stack' stamp: 'tk 11/4/2001 20:57'!\\nwrapWithAStack\\n\\t\\\"Install me as a card inside a new stack. The stack has no border or controls, so I my look is unchanged. If I don't already have a CardPlayer, find my data fields and make one. Be ready to make new cards in the stack that look like me, but hold different field data.\\\"\\n\\n\\tself player class officialClass == CardPlayer ifFalse: [\\n\\t\\tself abstractAModel ifFalse: [^ false]].\\n\\tStackMorph new initializeWith: self.\\n\\tself stack addHalo.\\t\\\"Makes it easier for the user\\\"! !\\n\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 8/12/2003 21:50'!\\naddedMorph: aMorph\\n\\t\\\"Notify the receiver that the given morph was just added.\\\"\\n! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'sw 9/10/1998 08:18'!\\ncolorChangedForSubmorph: aSubmorph\\n\\t\\\"The color associated with aSubmorph was changed through the UI; react if needed\\\"! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 11/12/2000 18:50'!\\ninvalidRect: damageRect\\n\\t^self invalidRect: damageRect from: self! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'md 4/3/2006 11:52'!\\ninvalidRect: aRectangle from: aMorph\\n\\t| damageRect |\\n\\taRectangle hasPositiveExtent ifFalse: [ ^self ].\\n\\tdamageRect _ aRectangle.\\n\\taMorph == self ifFalse:[\\n\\t\\t\\\"Clip to receiver's clipping bounds if the damage came from a child\\\"\\n\\t\\tself clipSubmorphs \\n\\t\\t\\tifTrue:[damageRect _ aRectangle intersect: self clippingBounds]].\\n\\towner ifNotNil: [owner invalidRect: damageRect from: self].! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'sw 7/8/1998 13:21'!\\nownerChanged\\n\\t\\\"The receiver's owner, some kind of a pasteup, has changed its layout.\\\"\\n\\n\\tself snapToEdgeIfAppropriate! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'ar 8/12/2003 22:26'!\\nprivateInvalidateMorph: aMorph\\n\\t\\\"Private. Invalidate the given morph after adding or removing.\\n\\tThis method is private because a) we're invalidating the morph 'remotely'\\n\\tand b) it forces a fullBounds computation which should not be necessary\\n\\tfor a general morph c) the morph may or may not actually invalidate\\n\\tanything (if it's not in the world nothing will happen) and d) the entire\\n\\tmechanism should be rewritten.\\\"\\n\\taMorph fullBounds.\\n\\taMorph changed! !\\n\\n!Morph methodsFor: 'change reporting' stamp: 'tk 8/24/2001 22:07'!\\nuserSelectedColor: aColor\\n\\t\\\"The user, via the UI, chose aColor to be the color for the receiver; set it, and tell my owner in case he wishes to react\\\"\\n\\tself color: aColor.\\n\\tself world ifNotNil: [owner colorChangedForSubmorph: self]! !\\n\\n\\n!Morph methodsFor: 'classification' stamp: 'sw 2/26/2002 23:29'!\\ndemandsBoolean\\n\\t\\\"Answer whether the receiver will only accept a drop if it is boolean-valued. Particular to tile-scripting.\\\"\\n\\n\\t^ self hasProperty: #demandsBoolean! !\\n\\n!Morph methodsFor: 'classification' stamp: 'di 5/7/1998 01:21'!\\nisAlignmentMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/15/2000 17:56'!\\nisBalloonHelp\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/28/2000 13:54'!\\nisFlapOrTab\\n\\t^self isFlap or:[self isFlapTab]! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 9/28/2000 13:53'!\\nisFlapTab\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'jm 4/17/1998 00:44'!\\nisFlexMorph\\n\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'classification'!\\nisHandMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 10/3/2000 18:11'!\\nisModalShell\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'sw 1/29/98 21:51'!\\nisPlayfieldLike\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'jm 5/7/1998 13:45'!\\nisRenderer\\n\\t\\\"A *renderer* morph transforms the appearance of its submorph in some manner. For example, it might supply a drop shadow or scale and rotate the morph it encases. Answer true if this morph acts as a renderer. This default implementation returns false.\\\"\\n\\t\\\"Details: A renderer is assumed to have a single submorph. Renderers may be nested to concatenate their transformations. It is useful to be able to find the outer-most renderer. This can be done by ascending the owner chain from the rendered morph. To find the morph being rendered, one can descend through the (singleton) submorph lists of the renderer chain until a non-renderer is encountered.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 6/30/2001 13:13'!\\nisStandardViewer\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'di 11/2/2000 13:24'!\\nisSyntaxMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification' stamp: 'ar 12/16/2001 18:28'!\\nisTextMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'classification'!\\nisWorldMorph\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'classification'!\\nisWorldOrHandMorph\\n\\n\\t^ self isWorldMorph or: [self isHandMorph]! !\\n\\n\\n!Morph methodsFor: 'connectors-scripting' stamp: 'nk 9/10/2004 11:37'!\\nwantsConnectorVocabulary\\n\\t\\\"Answer true if I want to show a 'connector' vocabulary\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'converting'!\\nasDraggableMorph\\n\\t^self! !\\n\\n!Morph methodsFor: 'converting' stamp: 'wiz 2/19/2006 19:01'!\\nasSnapshotThumbnail\\n\\t^(ThumbnailImageMorph new newImage: self imageForm ) extent: 90 asPoint .! !\\n\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/19/2001 18:21'!\\ncopy\\n\\n\\t^ self veryDeepCopy! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/14/2001 12:47'!\\ndeepCopy\\n\\n\\tself error: 'Please use veryDeepCopy'.\\n! !\\n\\n!Morph methodsFor: 'copying' stamp: 'sw 4/19/2005 17:02'!\\nduplicate\\n\\t\\\"Make and return a duplicate of the receiver\\\"\\n\\n\\t| newMorph aName w aPlayer topRend |\\n\\t((topRend _ self topRendererOrSelf) ~~ self) ifTrue: [^ topRend duplicate].\\n\\n\\tself okayToDuplicate ifFalse: [^ self].\\n\\taName _ (w _ self world) ifNotNil:\\n\\t\\t[w nameForCopyIfAlreadyNamed: self].\\n\\tnewMorph _ self veryDeepCopy.\\n\\taName ifNotNil: [newMorph setNameTo: aName].\\n\\n\\tnewMorph arrangeToStartStepping.\\n\\tnewMorph privateOwner: nil. \\\"no longer in world\\\"\\n\\tnewMorph isPartsDonor: false. \\\"no longer parts donor\\\"\\n\\t(aPlayer _ newMorph player) belongsToUniClass ifTrue:\\n\\t\\t[aPlayer class bringScriptsUpToDate].\\n\\taPlayer ifNotNil: [ActiveWorld presenter flushPlayerListCache].\\n\\t^ newMorph! !\\n\\n!Morph methodsFor: 'copying' stamp: 'nk 3/12/2001 17:07'!\\nduplicateMorphCollection: aCollection\\n\\t\\\"Make and return a duplicate of the receiver\\\"\\n\\n\\t| newCollection names |\\n\\n\\tnames _ aCollection collect: [ :ea | | newMorph w |\\n\\t\\t(w _ ea world) ifNotNil:\\n\\t\\t\\t[w nameForCopyIfAlreadyNamed: ea].\\n\\t].\\n\\n\\tnewCollection _ aCollection veryDeepCopy.\\n\\n\\tnewCollection with: names do: [ :newMorph :name |\\n\\t\\tname ifNotNil: [ newMorph setNameTo: name ].\\n\\t\\tnewMorph arrangeToStartStepping.\\n\\t\\tnewMorph privateOwner: nil. \\\"no longer in world\\\"\\n\\t\\tnewMorph isPartsDonor: false. \\\"no longer parts donor\\\"\\n\\t].\\n\\n\\t^newCollection! !\\n\\n!Morph methodsFor: 'copying' stamp: 'sw 2/16/2001 16:30'!\\nfullCopy\\n\\t\\\"Deprecated, but maintained for backward compatibility with existing code (no senders in the base 3.0 image). Calls are revectored to #veryDeepCopy, but note that #veryDeepCopy does not do exactly the same thing that the original #fullCopy did, so beware!!\\\"\\n\\n\\t^ self veryDeepCopy! !\\n\\n!Morph methodsFor: 'copying' stamp: 'md 2/27/2006 08:53'!\\nupdateReferencesUsing: aDictionary \\n\\t\\\"Update intra-morph references within a composite morph that \\n\\thas been copied. For example, if a button refers to morph X in \\n\\tthe orginal \\n\\tcomposite then the copy of that button in the new composite \\n\\tshould refer to \\n\\tthe copy of X in new composite, not the original X. This default \\n\\timplementation updates the contents of any morph-bearing slot. \\n\\tIt may be \\n\\toverridden to avoid this behavior if so desired.\\\"\\n\\t| old |\\n\\tMorph instSize + 1\\n\\t\\tto: self class instSize\\n\\t\\tdo: [:i | \\n\\t\\t\\told _ self instVarAt: i.\\n\\t\\t\\told isMorph\\n\\t\\t\\t\\tifTrue: [self\\n\\t\\t\\t\\t\\t\\tinstVarAt: i\\n\\t\\t\\t\\t\\t\\tput: (aDictionary\\n\\t\\t\\t\\t\\t\\t\\t\\tat: old\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsent: [old])]].\\n\\textension ifNotNil: [extension updateReferencesUsing: aDictionary]! !\\n\\n!Morph methodsFor: 'copying' stamp: 'nk 10/11/2003 16:59'!\\nusableSiblingInstance\\n\\t\\\"Return another similar morph whose Player is of the same class as mine.\\n\\tDo not open it in the world.\\\"\\n\\n\\t| aName usedNames newPlayer newMorph topRenderer |\\n\\t(topRenderer := self topRendererOrSelf) == self \\n\\t\\tifFalse: [^topRenderer usableSiblingInstance].\\n\\tself assuredPlayer assureUniClass.\\n\\tnewMorph := self veryDeepCopySibling.\\n\\tnewPlayer := newMorph player.\\n\\tnewPlayer resetCostumeList.\\n\\t(aName := self knownName) isNil \\n\\t\\tifTrue: [self player notNil ifTrue: [aName := newMorph innocuousName]].\\n\\t\\\"Force a difference here\\\"\\n\\taName notNil \\n\\t\\tifTrue: \\n\\t\\t\\t[usedNames := (self world ifNil: [OrderedCollection new]\\n\\t\\t\\t\\t\\t\\tifNotNil: [self world allKnownNames]) copyWith: aName.\\n\\t\\t\\tnewMorph setNameTo: (Utilities keyLike: aName\\n\\t\\t\\t\\t\\t\\tsatisfying: [:f | (usedNames includes: f) not])].\\n\\tnewMorph privateOwner: nil.\\n\\tnewPlayer assureEventHandlerRepresentsStatus.\\n\\tself presenter flushPlayerListCache.\\n\\t^newMorph! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 1/6/1999 17:27'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. See veryDeepInner:, veryDeepFixupWith:\\\"\\n\\n\\tself prepareToBeSaved.\\n\\t^ super veryDeepCopyWith: deepCopier! !\\n\\n!Morph methodsFor: 'copying' stamp: 'tk 2/3/2001 14:29'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If some fields were weakly copied, fix new copy here.\\\"\\n\\n\\t\\\"super veryDeepFixupWith: deepCopier.\\tObject has no fixups, so don't call it\\\"\\n\\n\\t\\\"If my owner is being duplicated too, then store his duplicate.\\n\\t If I am owned outside the duplicated tree, then I am no longer owned!!\\\"\\n\\towner _ deepCopier references at: owner ifAbsent: [nil].\\n\\n! !\\n\\n!Morph methodsFor: 'copying' stamp: 'md 2/27/2006 08:47'!\\nveryDeepInner: deepCopier \\n\\t\\\"The inner loop, so it can be overridden when a field should not \\n\\tbe traced.\\\"\\n\\t\\\"super veryDeepInner: deepCopier.\\tknow Object has no inst vars\\\"\\n\\tbounds _ bounds clone.\\n\\t\\\"Points are shared with original\\\"\\n\\t\\\"owner _ owner.\\tspecial, see veryDeepFixupWith:\\\"\\n\\tsubmorphs _ submorphs veryDeepCopyWith: deepCopier.\\n\\t\\\"each submorph's fixup will install me as the owner\\\"\\n\\t\\\"fullBounds _ fullBounds.\\tfullBounds is shared with original!!\\\"\\n\\tcolor _ color veryDeepCopyWith: deepCopier.\\n\\t\\\"color, if simple, will return self. may be complex\\\"\\n\\textension := (extension veryDeepCopyWith: deepCopier)! !\\n\\n\\n!Morph methodsFor: 'creation' stamp: 'tk 2/6/1999 22:43'!\\nasMorph\\n\\t^ self! !\\n\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 8/30/2003 20:36'!\\naddDebuggingItemsTo: aMenu hand: aHandMorph\\n\\taMenu add: 'debug...' translated subMenu: (self buildDebugMenu: aHandMorph)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 1/19/2001 07:51'!\\naddMouseActionIndicatorsWidth: anInteger color: aColor\\n\\n\\tself deleteAnyMouseActionIndicators.\\n\\n\\tself changed.\\n\\tself hasRolloverBorder: true.\\n\\tself setProperty: #rolloverWidth toValue: anInteger@anInteger.\\n\\tself setProperty: #rolloverColor toValue: aColor.\\n\\tself layoutChanged.\\n\\tself changed.\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 4/25/2004 14:23'!\\naddMouseUpAction\\n\\t| codeToRun oldCode |\\n\\toldCode := self\\n\\t\\t\\t\\tvalueOfProperty: #mouseUpCodeToRun\\n\\t\\t\\t\\tifAbsent: [''].\\n\\tcodeToRun := FillInTheBlank request: 'MouseUp expression:' translated initialAnswer: oldCode.\\n\\tself addMouseUpActionWith: codeToRun! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 2/22/2003 13:41'!\\naddMouseUpActionWith: codeToRun \\n\\t((codeToRun isMessageSend) not and: [codeToRun isEmptyOrNil]) \\n\\t\\tifTrue: [^self].\\n\\tself setProperty: #mouseUpCodeToRun toValue: codeToRun.\\n\\tself \\n\\t\\ton: #mouseUp\\n\\t\\tsend: #programmedMouseUp:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseDown\\n\\t\\tsend: #programmedMouseDown:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseEnter\\n\\t\\tsend: #programmedMouseEnter:for:\\n\\t\\tto: self.\\n\\tself \\n\\t\\ton: #mouseLeave\\n\\t\\tsend: #programmedMouseLeave:for:\\n\\t\\tto: self! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 1/3/2001 06:42'!\\naddViewingItemsTo: aMenu\\n\\t\\\"Add viewing-related items to the given menu. If any are added, this method is also responsible for adding a line after them\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 2/22/2003 14:27'!\\nallStringsAfter: aSubmorph \\n\\t\\\"return an OrderedCollection of strings of text in my submorphs. If aSubmorph is non-nil, begin with that container.\\\"\\n\\n\\t| list string ok |\\n\\tlist := OrderedCollection new.\\n\\tok := aSubmorph isNil.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:sub | \\n\\t\\t\\tok ifFalse: [ok := sub == aSubmorph].\\t\\\"and do this one too\\\"\\n\\t\\t\\tok \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[(string := sub userString) ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[string isString ifTrue: [list add: string] ifFalse: [list addAll: string]]]].\\n\\t^list! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:27'!\\naltSpecialCursor0\\n\\t\\\"an arrow\\\"\\n\\t^(Form\\n\\textent: 16@16\\n\\tdepth: 8\\n\\tfromArray: #( 0 0 0 0 14869218 3806520034 3806520034 3791650816 14848144 2425393296 2425393378 0 14848144 2425393296 2425414144 0 14848144 2425393296 2430730240 0 14848144 2425393296 3791650816 0 14848144 2425393378 3791650816 0 14848144 2425414370 3806461952 0 14848144 2430788322 3806519808 0 14848144 3791651042 3806520034 0 14848226 0 3806520034 3791650816 14868992 0 14869218 3806461952 14811136 0 58082 3806519808 0 0 226 3806520034 0 0 0 3806520034 0 0 0 14869218)\\n\\toffset: 0@0)\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:28'!\\naltSpecialCursor1\\n\\t\\\"a star and an arrow\\\"\\n\\t^(Form\\n\\textent: 31@26\\n\\tdepth: 8\\n\\tfromArray: #( 14417920 0 0 0 0 0 0 0 3705461980 3705461980 3705405440 0 0 0 0 0 3705461980 3705461980 3705461760 0 0 0 0 0 14474460 3705461980 3705405440 0 0 0 0 0 56540 3705461980 3690987520 0 0 3690987520 0 0 220 3705461980 3705461760 0 0 3690987520 0 0 220 3705405440 3705461980 0 0 3705405440 0 0 0 3705461760 56540 3690987520 220 3705405440 0 0 0 3705405440 220 3705461760 220 3705405440 0 0 0 0 0 14474460 220 3705461760 0 0 0 0 0 56540 3691044060 3705461760 0 0 0 0 0 220 3705461980 3705461760 0 0 0 0 56540 3705461980 3705461980 3705461980 3705461980 3705461760 0 0 220 3705461980 3705461980 3705461980 3705461980 3705461760 0 0 0 3705461980 3705461980 3705461980 3705461980 3705405440 0 0 0 14474460 3705461980 3705461980 3705461980 3690987520 0 0 0 56540 3705461980 3705461980 3705461760 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 0 3705461980 3705461980 3690987520 0 0 0 0 0 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 3705461980 3705405440 0 0 0 0 220 3705461980 14474460 3705405440 0 0 0 0 220 3705405440 220 3705461760 0 0 0 0 56540 3690987520 0 3705461760 0 0 0 0 56540 0 0 14474240 0)\\n\\toffset: 0@0)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:41'!\\naltSpecialCursor2\\n\\t| f |\\n\\t\\\"a blue box with transparent center\\\"\\n\\tf _ Form extent: 32@32 depth: 32.\\n\\tf offset: (f extent // 2) negated.\\n\\tf fill: f boundingBox rule: Form over fillColor: (Color blue alpha: 0.5).\\n\\tf fill: (f boundingBox insetBy: 4) rule: Form over fillColor: Color transparent.\\n\\t^f\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:42'!\\naltSpecialCursor3\\n\\t\\n\\t^self altSpecialCursor3: Color blue! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:41'!\\naltSpecialCursor3: aColor\\n\\t| f box |\\n\\t\\\"a bulls-eye pattern in this color\\\"\\n\\tf _ Form extent: 32@32 depth: 32.\\n\\tf offset: (f extent // 2) negated.\\n\\tbox _ f boundingBox.\\n\\t[ box width > 0] whileTrue: [\\n\\t\\tf fill: box rule: Form over fillColor: aColor.\\n\\t\\tf fill: (box insetBy: 2) rule: Form over fillColor: Color transparent.\\n\\t\\tbox _ box insetBy: 4.\\n\\t].\\n\\t^f\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'nk 6/14/2004 16:14'!\\nbuildDebugMenu: aHand\\n\\t\\\"Answer a debugging menu for the receiver. The hand argument is seemingly historical and plays no role presently\\\"\\n\\n\\t| aMenu aPlayer |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\t(self hasProperty: #errorOnDraw) ifTrue:\\n\\t\\t[aMenu add: 'start drawing again' translated action: #resumeAfterDrawError.\\n\\t\\taMenu addLine].\\n\\t(self hasProperty: #errorOnStep) ifTrue:\\n\\t\\t[aMenu add: 'start stepping again' translated action: #resumeAfterStepError.\\n\\t\\taMenu addLine].\\n\\n\\taMenu add: 'inspect morph' translated action: #inspectInMorphic:.\\n\\taMenu add: 'inspect owner chain' translated action: #inspectOwnerChain.\\n\\tSmalltalk isMorphic ifFalse:\\n\\t\\t[aMenu add: 'inspect morph (in MVC)' translated action: #inspect].\\n\\n\\tself isMorphicModel ifTrue:\\n\\t\\t[aMenu add: 'inspect model' translated target: self model action: #inspect].\\n\\t(aPlayer _ self player) ifNotNil:\\n\\t\\t[aMenu add: 'inspect player' translated target: aPlayer action: #inspect].\\n\\n aMenu add: 'explore morph' translated target: self selector: #explore.\\n\\n\\taMenu addLine.\\n\\taPlayer ifNotNil:\\n\\t\\t[ aMenu add: 'viewer for Player' translated target: self player action: #beViewed.\\n\\taMenu balloonTextForLastItem: 'Opens a viewer on my Player -- this is the same thing you get if you click on the cyan \\\"View\\\" halo handle' translated ].\\n\\n\\taMenu add: 'viewer for Morph' translated target: self action: #viewMorphDirectly.\\n\\taMenu balloonTextForLastItem: 'Opens a Viewer on this Morph, rather than on its Player' translated.\\n\\taMenu addLine.\\n\\n\\taPlayer ifNotNil:\\n\\t\\t[aPlayer class isUniClass ifTrue: [\\n\\t\\t\\taMenu add: 'browse player class' translated target: aPlayer action: #browseHierarchy]].\\n\\taMenu add: 'browse morph class' translated target: self selector: #browseHierarchy.\\n\\t(self isMorphicModel)\\n\\t\\tifTrue: [aMenu\\n\\t\\t\\t\\tadd: 'browse model class'\\n\\t\\t\\t\\ttarget: self model\\n\\t\\t\\t\\tselector: #browseHierarchy].\\n\\taMenu addLine.\\n\\n\\taPlayer ifNotNil:\\n\\t\\t[aMenu add: 'player protocol (tiles)' translated target: aPlayer action: #openInstanceBrowserWithTiles\\n\\t\\t\\t\\\"#browseProtocolForPlayer\\\"].\\n\\taMenu add: 'morph protocol (text)' translated target: self selector: #haveFullProtocolBrowsed.\\n\\taMenu add: 'morph protocol (tiles)' translated target: self selector: #openInstanceBrowserWithTiles.\\n\\taMenu addLine.\\n\\n\\tself addViewingItemsTo: aMenu.\\n\\taMenu \\n\\t\\tadd: 'make own subclass' translated action: #subclassMorph;\\n\\t\\tadd: 'internal name ' translated action: #choosePartName;\\n\\t\\tadd: 'save morph in file' translated action: #saveOnFile;\\n\\t\\taddLine;\\n\\t\\tadd: 'call #tempCommand' translated action: #tempCommand;\\n\\t\\tadd: 'define #tempCommand' translated action: #defineTempCommand;\\n\\t\\taddLine;\\n\\n\\t\\tadd: 'control-menu...' translated target: self selector: #invokeMetaMenu:;\\n\\t\\tadd: 'edit balloon help' translated action: #editBalloonHelpText.\\n\\n\\t^ aMenu! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'ar 9/27/2005 20:29'!\\ndefineTempCommand\\n\\t\\\"To use this, comment out what's below here, and substitute your own code.\\nYou will then be able to invoke it from the standard debugging menus. If invoked from the world menu, you'll always get it invoked on behalf of the world, but if invoked from an individual morph's meta-menu, it will be invoked on behalf of that individual morph.\\n\\nNote that you can indeed reimplement tempCommand in an individual morph's class if you wish\\\"\\n\\n\\tToolSet browse: Morph\\n\\t\\tselector: #tempCommand! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 1/19/2001 07:51'!\\ndeleteAnyMouseActionIndicators\\n\\n\\tself changed.\\n\\t(self valueOfProperty: #mouseActionIndicatorMorphs ifAbsent: [#()]) do: [ :each |\\n\\t\\teach deleteWithSiblings\\t\\t\\\"one is probably enough, but be safe\\\"\\n\\t].\\n\\tself removeProperty: #mouseActionIndicatorMorphs.\\n\\tself hasRolloverBorder: false.\\n\\tself removeProperty: #rolloverWidth.\\n\\tself removeProperty: #rolloverColor.\\n\\tself layoutChanged.\\n\\tself changed.\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 7/17/2001 19:08'!\\nhandMeTilesToFire \\n\\t\\\"Construct a phrase of tiles comprising a line of code that will 'fire' this object, and hand it to the user\\\"\\n\\n\\tActiveHand attachMorph: (self assuredPlayer tilesToCall: MethodInterface firingInterface)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'ar 10/5/2000 17:38'!\\ninspectArgumentsPlayerInMorphic: evt\\n\\tevt hand attachMorph: ((Inspector openAsMorphOn: self player) extent: 300@200)! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 11/5/1998 20:31'!\\ninspectOwnerChain\\n\\tself ownerChain inspectWithLabel: 'Owner chain for ', self printString! !\\n\\n!Morph methodsFor: 'debug and other'!\\ninstallModelIn: ignored\\n\\t\\\"Simple morphs have no model\\\"\\n\\t\\\"See MorphicApp for other behavior\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 2/6/2001 22:35'!\\nmouseUpCodeOrNil\\n\\t\\\"If the receiver has a mouseUpCodeToRun, return it, else return nil\\\"\\n\\n\\t^ self valueOfProperty: #mouseUpCodeToRun ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 2/22/2003 19:05'!\\nownerChain\\n\\t\\\"Answer a list of objects representing the receiver and all of its owners. The first element is the receiver, and the last one is typically the world in which the receiver resides\\\"\\n\\n\\t| c next |\\n\\tc := OrderedCollection with: self.\\n\\tnext := self.\\n\\t[(next := next owner) notNil] whileTrue: [c add: next].\\n\\t^c asArray! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:16'!\\nprogrammedMouseDown: anEvent for: aMorph\\n\\n\\taMorph addMouseActionIndicatorsWidth: 15 color: (Color blue alpha: 0.7).\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:16'!\\nprogrammedMouseEnter: anEvent for: aMorph\\n\\n\\taMorph addMouseActionIndicatorsWidth: 10 color: (Color blue alpha: 0.3).\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/12/2000 11:10'!\\nprogrammedMouseLeave: anEvent for: aMorph\\n\\n\\tself deleteAnyMouseActionIndicators.\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'gm 2/22/2003 13:41'!\\nprogrammedMouseUp: anEvent for: aMorph \\n\\t| aCodeString |\\n\\tself deleteAnyMouseActionIndicators.\\n\\taCodeString := self valueOfProperty: #mouseUpCodeToRun ifAbsent: [^self].\\n\\t(self fullBounds containsPoint: anEvent cursorPoint) ifFalse: [^self].\\n\\t\\n\\t[(aCodeString isMessageSend) \\n\\t\\tifTrue: [aCodeString value]\\n\\t\\tifFalse: \\n\\t\\t\\t[Compiler \\n\\t\\t\\t\\tevaluate: aCodeString\\n\\t\\t\\t\\tfor: self\\n\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\tlogged: false]] \\n\\t\\t\\ton: ProgressTargetRequestNotification\\n\\t\\t\\tdo: [:ex | ex resume: self]\\t\\\"in case a save/load progress display needs a home\\\"! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 7/7/2000 16:43'!\\nremoveMouseUpAction\\n\\n\\tself primaryHand showTemporaryCursor: nil.\\n\\tself removeProperty: #mouseUpCodeToRun.\\n\\t#(mouseUp mouseEnter mouseLeave mouseDown) do: [ :sym |\\n\\t\\tself\\n\\t\\t\\ton: sym \\n\\t\\t\\tsend: #yourself \\n\\t\\t\\tto: nil.\\n\\t]\\n\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 5/24/2000 18:20'!\\nresumeAfterDrawError\\n\\n\\tself changed.\\n\\tself removeProperty:#errorOnDraw.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'RAA 5/24/2000 18:20'!\\nresumeAfterStepError\\n\\t\\\"Resume stepping after an error has occured.\\\"\\n\\n\\tself startStepping. \\\"Will #step\\\"\\n\\tself removeProperty:#errorOnStep. \\\"Will remove prop only if #step was okay\\\"\\n! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'dgd 8/30/2003 20:43'!\\ntempCommand\\n\\t\\\"Generic backstop. If you care to, you can comment out what's below here, and substitute your own code, though the intention of design of the feature is that you leave this method as it is, and instead reimplement tempCommand in the class of whatever individual morph you care to. In any case, once you have your own #tempCommand in place, you will then be able to invoke it from the standard debugging menus.\\\"\\n\\n\\tself inform: 'Before calling tempCommand, you\\nshould first give it a definition. To\\ndo this, choose \\\"define tempCommand\\\"\\nfrom the debug menu.' translated! !\\n\\n!Morph methodsFor: 'debug and other' stamp: 'sw 8/4/2001 00:33'!\\nviewMorphDirectly\\n\\t\\\"Open a Viewer directly on the Receiver, i.e. no Player involved\\\"\\n\\n\\tself presenter viewObjectDirectly: self renderedMorph\\n\\n\\t! !\\n\\n\\n!Morph methodsFor: 'dispatching' stamp: 'nk 2/15/2004 09:16'!\\ndisableSubmorphFocusForHand: aHandMorph\\n\\t\\\"Check whether this morph or any of its submorph has the Genie focus.\\n\\tIf yes, disable it.\\\"\\n! !\\n\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 6/24/1998 14:10'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"May be overridden by any subclasses with opaque regions\\\"\\n\\n\\t^ Array with: aRectangle! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 6/4/2000 22:02'!\\nboundingBoxOfSubmorphs\\n\\t| aBox |\\n\\taBox _ bounds origin extent: self minimumExtent. \\\"so won't end up with something empty\\\"\\n\\tsubmorphs do:\\n\\t\\t[:m | m visible ifTrue: [aBox _ aBox quickMerge: m fullBounds]].\\n\\t^ aBox\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 2/15/2001 14:51'!\\nboundsWithinCorners\\n\\n\\t^ CornerRounder rectWithinCornersOf: self bounds! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/4/2000 23:39'!\\nchangeClipSubmorphs\\n\\tself clipSubmorphs: self clipSubmorphs not.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 2/16/2003 20:02'!\\nclipLayoutCells\\n\\t\\\"Drawing/layout specific. If this property is set, clip the \\n\\tsubmorphs of the receiver by its cell bounds.\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #clipLayoutCells\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 10/29/2000 19:22'!\\nclipLayoutCells: aBool\\n\\t\\\"Drawing/layout specific. If this property is set, clip the submorphs of the receiver by its cell bounds.\\\"\\n\\taBool == false\\n\\t\\tifTrue:[self removeProperty: #clipLayoutCells]\\n\\t\\tifFalse:[self setProperty: #clipLayoutCells toValue: aBool].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 10/29/2000 19:16'!\\nclippingBounds\\n\\t\\\"Return the bounds to which any submorphs should be clipped if the property is set\\\"\\n\\t^self innerBounds! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 4/3/2006 11:53'!\\nclipSubmorphs\\n\\t\\\"Drawing specific. If this property is set, clip the receiver's \\n\\tsubmorphs to the receiver's clipping bounds.\\\"\\n\\t\\n\\textension ifNil: [^false].\\n\\t^ self\\n\\t\\tvalueOfProperty: #clipSubmorphs\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/12/2000 18:47'!\\nclipSubmorphs: aBool\\n\\t\\\"Drawing specific. If this property is set, clip the receiver's submorphs to the receiver's clipping bounds.\\\"\\n\\tself invalidRect: self fullBounds.\\n\\taBool == false\\n\\t\\tifTrue:[self removeProperty: #clipSubmorphs]\\n\\t\\tifFalse:[self setProperty: #clipSubmorphs toValue: aBool].\\n\\tself invalidRect: self fullBounds.! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'tk 8/2/1998 14:33'!\\ndoesOwnRotation\\n\\t\\\"Some morphs don't want to TransformMorph to rotate their images, but we do\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'panda 4/28/2000 11:59'!\\ndrawDropHighlightOn: aCanvas\\n\\tself highlightedForDrop ifTrue: [\\n\\t\\taCanvas frameRectangle: self fullBounds color: self dropHighlightColor].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 12/30/2001 19:17'!\\ndrawDropShadowOn: aCanvas\\n\\n\\taCanvas \\n\\t\\ttranslateBy: self shadowOffset \\n\\t\\tduring: [ :shadowCanvas |\\n\\t\\t\\tshadowCanvas shadowColor: self shadowColor.\\n\\t\\t\\tshadowCanvas roundCornersOf: self during: [ \\n\\t\\t\\t\\t(shadowCanvas isVisible: self bounds) ifTrue:[shadowCanvas drawMorph: self ]]\\n\\t\\t].\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 4/2/1999 13:13'!\\ndrawErrorOn: aCanvas\\n\\t\\\"The morph (or one of its submorphs) had an error in its drawing method.\\\"\\n\\taCanvas\\n\\t\\tframeAndFillRectangle: bounds\\n\\t\\tfillColor: Color red\\n\\t\\tborderWidth: 1\\n\\t\\tborderColor: Color yellow.\\n\\taCanvas line: bounds topLeft to: bounds bottomRight width: 1 color: Color yellow.\\n\\taCanvas line: bounds topRight to: bounds bottomLeft width: 1 color: Color yellow.! !\\n\\n!Morph methodsFor: 'drawing' stamp: ' 9/3/2000 13:55'!\\ndrawMouseDownHighlightOn: aCanvas\\n\\tself highlightedForMouseDown ifTrue: [\\n\\t\\taCanvas frameRectangle: self fullBounds color: self color darker darker].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 8/25/2001 17:31'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds fillStyle: self fillStyle borderStyle: self borderStyle.\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'wiz 3/21/2006 20:44'!\\ndrawRolloverBorderOn: aCanvas \\n\\t| colorToUse offsetToUse myShadow newForm f |\\n\\tcolorToUse := self\\n\\t\\t\\t\\tvalueOfProperty: #rolloverColor\\n\\t\\t\\t\\tifAbsent: [Color blue alpha: 0.5].\\n\\toffsetToUse := self\\n\\t\\t\\t\\tvalueOfProperty: #rolloverWidth\\n\\t\\t\\t\\tifAbsent: [10 @ 10].\\n\\tself hasRolloverBorder: false.\\n\\tmyShadow := self shadowForm.\\n\\tself hasRolloverBorder: true.\\n\\tmyShadow offset: 0 @ 0.\\n\\tf := ColorForm extent: myShadow extent depth: 1.\\n\\tmyShadow displayOn: f.\\n\\tf colors: {Color transparent. colorToUse}.\\n\\tnewForm := Form extent: offsetToUse * 2 + myShadow extent depth: 32.\\n\\t(WarpBlt current toForm: newForm) sourceForm: f;\\n\\t\\t cellSize: 1;\\n\\t\\t combinationRule: 3;\\n\\t\\t copyQuad: f boundingBox innerCorners toRect: newForm boundingBox.\\n\\taCanvas\\n\\t\\ttranslateBy: offsetToUse negated\\n\\t\\tduring: [:shadowCanvas | \\n\\t\\t\\tshadowCanvas shadowColor: colorToUse.\\n\\t\\t\\tshadowCanvas paintImage: newForm at: self position]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 2/22/2003 14:31'!\\ndrawSubmorphsOn: aCanvas \\n\\t\\\"Display submorphs back to front\\\"\\n\\n\\t| drawBlock |\\n\\tsubmorphs isEmpty ifTrue: [^self].\\n\\tdrawBlock := [:canvas | submorphs reverseDo: [:m | canvas fullDrawMorph: m]].\\n\\tself clipSubmorphs \\n\\t\\tifTrue: [aCanvas clipBy: self clippingBounds during: drawBlock]\\n\\t\\tifFalse: [drawBlock value: aCanvas]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'RAA 1/6/2001 22:12'!\\nexpandFullBoundsForDropShadow: aRectangle\\n\\t\\\"Return an expanded rectangle for an eventual drop shadow\\\"\\n\\t| delta box |\\n\\n\\tbox _ aRectangle.\\n\\tdelta _ self shadowOffset.\\n\\tbox _ delta x >= 0 \\n\\t\\tifTrue:[box right: aRectangle right + delta x]\\n\\t\\tifFalse:[box left: aRectangle left + delta x].\\n\\tbox _ delta y >= 0\\n\\t\\tifTrue:[box bottom: aRectangle bottom + delta y]\\n\\t\\tifFalse:[box top: aRectangle top + delta y].\\n\\t^box! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 11/8/2000 19:29'!\\nexpandFullBoundsForRolloverBorder: aRectangle\\n\\t| delta |\\n\\tdelta _ self valueOfProperty: #rolloverWidth ifAbsent: [10@10].\\n\\t^aRectangle expandBy: delta.\\n\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 11/26/2003 17:43'!\\nflashBounds\\n\\t\\\"Flash the receiver's bounds -- does not use the receiver's color, thus works with StringMorphs and SketchMorphs, etc., for which #flash is useless. No senders initially, but useful to send this from a debugger or inspector\\\"\\n\\n\\t5 timesRepeat:\\n\\t\\t[Display flash: self boundsInWorld andWait: 120]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 12/30/2001 15:22'!\\nfullDrawOn: aCanvas\\n\\t\\\"Draw the full Morphic structure on the given Canvas\\\"\\n\\n\\tself visible ifFalse: [^ self].\\n\\t(aCanvas isVisible: self fullBounds) ifFalse:[^self].\\n\\t(self hasProperty: #errorOnDraw) ifTrue:[^self drawErrorOn: aCanvas].\\n\\t\\\"Note: At some point we should generalize this into some sort of \\n\\tmulti-canvas so that we can cross-optimize some drawing operations.\\\"\\n\\t\\\"Pass 1: Draw eventual drop-shadow\\\"\\n\\tself hasDropShadow ifTrue: [self drawDropShadowOn: aCanvas].\\n\\t(self hasRolloverBorder and: [(aCanvas seesNothingOutside: self bounds) not])\\n\\t\\tifTrue: [self drawRolloverBorderOn: aCanvas].\\n\\n\\t\\\"Pass 2: Draw receiver itself\\\"\\n\\taCanvas roundCornersOf: self during:[\\n\\t\\t(aCanvas isVisible: self bounds) ifTrue:[aCanvas drawMorph: self].\\n\\t\\tself drawSubmorphsOn: aCanvas.\\n\\t\\tself drawDropHighlightOn: aCanvas.\\n\\t\\tself drawMouseDownHighlightOn: aCanvas].! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'dgd 8/30/2003 20:20'!\\nhasClipSubmorphsString\\n\\t\\\"Answer a string that represents the clip-submophs checkbox\\\"\\n\\t^ (self clipSubmorphs\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'provide clipping' translated! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/30/1998 18:27'!\\nhide\\n\\towner ifNil: [^ self].\\n\\tself visible ifTrue: [self visible: false. self changed]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'LC 5/18/2000 08:48'!\\nhighlightedForMouseDown\\n\\t^(self valueOfProperty: #highlightedForMouseDown) == true! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'LC 5/18/2000 08:51'!\\nhighlightForMouseDown\\n\\tself highlightForMouseDown: true! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 3/17/2001 15:56'!\\nhighlightForMouseDown: aBoolean\\n\\taBoolean \\n\\t\\tifTrue:[self setProperty: #highlightedForMouseDown toValue: aBoolean]\\n\\t\\tifFalse:[self removeProperty: #highlightedForMouseDown. self resetExtension].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'jm 6/11/97 17:21'!\\nimageForm\\n\\n\\t^ self imageFormForRectangle: self fullBounds\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 7/8/1998 12:42'!\\nimageFormDepth: depth\\n\\n\\t^ self imageForm: depth forRectangle: self fullBounds\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'di 9/9/1998 22:25'!\\nimageFormForRectangle: rect\\n\\n\\t^ self imageForm: Display depth forRectangle: rect\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 9/1/2000 14:23'!\\nimageFormWithout: stopMorph andStopThere: stopThere\\n\\t\\\"Like imageForm, except it does not display stopMorph,\\n\\tand it will not display anything above it if stopThere is true.\\n\\tReturns a pair of the imageForm and a boolean that is true\\n\\t\\tif it has hit stopMorph, and display should stop.\\\"\\n\\t| canvas rect |\\n\\trect _ self fullBounds.\\n\\tcanvas _ ColorPatchCanvas extent: rect extent depth: Display depth.\\n\\tcanvas stopMorph: stopMorph.\\n\\tcanvas doStop: stopThere.\\n\\tcanvas translateBy: rect topLeft negated during:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ Array with: (canvas form offset: rect topLeft)\\n\\t\\t\\twith: canvas foundMorph! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'nk 9/1/2004 15:08'!\\nimageForm: depth backgroundColor: aColor forRectangle: rect\\n\\t| canvas |\\n\\tcanvas _ Display defaultCanvasClass extent: rect extent depth: depth.\\n\\tcanvas translateBy: rect topLeft negated\\n\\t\\tduring:[:tempCanvas| \\n\\t\\t\\ttempCanvas fillRectangle: rect color: aColor.\\n\\t\\t\\ttempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: rect topLeft! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'ar 9/1/2000 14:23'!\\nimageForm: depth forRectangle: rect\\n\\t| canvas |\\n\\tcanvas _ Display defaultCanvasClass extent: rect extent depth: depth.\\n\\tcanvas translateBy: rect topLeft negated\\n\\t\\tduring:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: rect topLeft! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/10/1999 23:25'!\\nrefreshWorld\\n\\t| aWorld |\\n\\t(aWorld _ self world) ifNotNil: [aWorld displayWorldSafely]\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'JW 7/12/2005 20:12'!\\nshadowForm\\n\\t\\\"Return a form representing the 'shadow' of the receiver - e.g., all pixels that are occupied by the receiver are one, all others are zero.\\\"\\n\\t| canvas |\\n\\tcanvas := (Display defaultCanvasClass extent: self fullBounds extent depth: 1)\\n\\t\\t\\t\\tasShadowDrawingCanvas: Color black. \\\"Color black represents one for 1bpp\\\"\\n\\tcanvas translateBy: bounds topLeft negated\\n\\t\\tduring:[:tempCanvas| tempCanvas fullDrawMorph: self].\\n\\t^ canvas form offset: bounds topLeft\\n! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'sw 10/22/1998 20:29'!\\nshow\\n\\t\\\"Make sure this morph is on-stage.\\\"\\n\\tself visible ifFalse: [self visible: true. self changed]! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 2/27/2006 08:49'!\\nvisible\\n\\t\\\"answer whether the receiver is visible\\\"\\n\\textension ifNil: [^ true].\\n\\t^ extension visible! !\\n\\n!Morph methodsFor: 'drawing' stamp: 'md 2/27/2006 08:49'!\\nvisible: aBoolean \\n\\t\\\"set the 'visible' attribute of the receiver to aBoolean\\\"\\n\\t(extension isNil and:[aBoolean]) ifTrue: [^ self].\\n\\tself visible == aBoolean ifTrue: [^ self].\\n\\tself assureExtension visible: aBoolean.\\n\\tself changed! !\\n\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'RAA 1/19/2001 07:51'!\\naddDropShadow\\n\\n\\tself hasDropShadow ifTrue:[^self].\\n\\tself changed.\\n\\tself hasDropShadow: true.\\n\\tself shadowOffset: 3@3.\\n\\tself layoutChanged.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 8/30/2003 16:48'!\\naddDropShadowMenuItems: aMenu hand: aHand\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu\\n\\t\\taddUpdating: #hasDropShadowString\\n\\t\\taction: #toggleDropShadow.\\n\\tmenu addLine.\\n\\tmenu add: 'shadow color...' translated target: self selector: #changeShadowColor.\\n\\tmenu add: 'shadow offset...' translated target: self selector: #setShadowOffset:.\\n\\taMenu add: 'drop shadow' translated subMenu: menu.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:22'!\\nchangeShadowColor\\n\\t\\\"Change the shadow color of the receiver -- triggered, e.g. from a menu\\\"\\n\\n\\tColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: self activeHand;\\n\\t\\ttarget: self;\\n\\t\\tselector: #shadowColor:;\\n\\t\\toriginalColor: self shadowColor;\\n\\t\\tputUpFor: self near: self fullBoundsInWorld! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 2/16/2003 21:42'!\\nhasDropShadow\\n\\t\\\"answer whether the receiver has DropShadow\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #hasDropShadow\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 8/30/2003 16:49'!\\nhasDropShadowString\\n\\t^ (self hasDropShadow\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'show shadow' translated! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 19:03'!\\nhasDropShadow: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasDropShadow toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasDropShadow]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'dgd 2/16/2003 21:58'!\\nhasRolloverBorder\\n\\t\\\"answer whether the receiver has RolloverBorder\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #hasRolloverBorder\\n\\t\\tifAbsent: [false]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'RAA 11/7/2000 15:54'!\\nhasRolloverBorder: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasRolloverBorder toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasRolloverBorder]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 11/12/2000 18:57'!\\nremoveDropShadow\\n\\tself hasDropShadow ifFalse:[^self].\\n\\tself changed.\\n\\tself hasDropShadow: false.\\n\\tfullBounds ifNotNil:[fullBounds _ self privateFullBounds].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:58'!\\nsetShadowOffset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:\\n\\t\\t[:newPoint | self shadowPoint: newPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:59'!\\nshadowColor\\n\\t^self valueOfProperty: #shadowColor ifAbsent:[Color black]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:22'!\\nshadowColor: aColor\\n\\tself shadowColor = aColor ifFalse:[self changed].\\n\\tself setProperty: #shadowColor toValue: aColor.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 18:57'!\\nshadowOffset\\n\\t\\\"Return the current shadow offset\\\"\\n\\t^self valueOfProperty: #shadowOffset ifAbsent:[0@0]! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 19:00'!\\nshadowOffset: aPoint\\n\\t\\\"Set the current shadow offset\\\"\\n\\t(aPoint isNil or:[(aPoint x isZero) & (aPoint y isZero)])\\n\\t\\tifTrue:[self removeProperty: #shadowOffset]\\n\\t\\tifFalse:[self setProperty: #shadowOffset toValue: aPoint].! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 11/12/2000 18:58'!\\nshadowPoint: newPoint\\n\\tself changed.\\n\\tself shadowOffset: newPoint - self center // 5.\\n\\tfullBounds ifNotNil:[fullBounds _ self privateFullBounds].\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'drop shadows' stamp: 'ar 10/26/2000 20:16'!\\ntoggleDropShadow\\n\\tself hasDropShadow\\n\\t\\tifTrue:[self removeDropShadow]\\n\\t\\tifFalse:[self addDropShadow].! !\\n\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 20:00'!\\naboutToBeGrabbedBy: aHand\\n\\t\\\"The receiver is being grabbed by a hand.\\n\\tPerform necessary adjustments (if any) and return the actual morph\\n\\tthat should be added to the hand.\\\"\\n\\t| extentToHandToHand cmd |\\n\\tself formerOwner: owner.\\n\\tself formerPosition: self position.\\n\\tcmd _ self undoGrabCommand.\\n\\tcmd ifNotNil:[self setProperty: #undoGrabCommand toValue: cmd].\\n\\t(extentToHandToHand _ self valueOfProperty: #expandedExtent)\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[self removeProperty: #expandedExtent.\\n\\t\\t\\t\\tself extent: extentToHandToHand].\\n\\t^self \\\"Grab me\\\"! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:41'!\\ndisableDragNDrop\\n\\tself enableDragNDrop: false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:50'!\\ndragEnabled\\n\\t\\\"Get this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\t^(self valueOfProperty: #dragEnabled) == true\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:18'!\\ndragEnabled: aBool\\n\\t^self enableDrag: aBool! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:20'!\\ndragNDropEnabled\\n\\t\\\"Note: This method is only useful for dragEnabled == dropEnabled at all times\\\"\\n\\tself separateDragAndDrop.\\n\\t^self dragEnabled and:[self dropEnabled]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 18:36'!\\ndragSelectionColor\\n\\t^ Color magenta! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:51'!\\ndropEnabled\\n\\t\\\"Get this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\t^(self valueOfProperty: #dropEnabled) == true\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:18'!\\ndropEnabled: aBool\\n\\t^self enableDrop: aBool! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 10:52'!\\ndropHighlightColor\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 18:08'!\\ndropSuccessColor\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:41'!\\nenableDragNDrop\\n\\tself enableDragNDrop: true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:21'!\\nenableDragNDrop: aBoolean\\n\\t\\\"Set both properties at once\\\"\\n\\tself separateDragAndDrop.\\n\\tself enableDrag: aBoolean.\\n\\tself enableDrop: aBoolean.! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:50'!\\nenableDrag: aBoolean\\n\\tself setProperty: #dragEnabled toValue: aBoolean! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:51'!\\nenableDrop: aBoolean\\n\\tself setProperty: #dropEnabled toValue: aBoolean! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:13'!\\nformerOwner\\n\\t^self valueOfProperty: #formerOwner! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 2/22/2003 14:31'!\\nformerOwner: aMorphOrNil \\n\\taMorphOrNil isNil \\n\\t\\tifTrue: [self removeProperty: #formerOwner]\\n\\t\\tifFalse: [self setProperty: #formerOwner toValue: aMorphOrNil]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:13'!\\nformerPosition\\n\\t^self valueOfProperty: #formerPosition! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 2/22/2003 14:31'!\\nformerPosition: formerPosition \\n\\tformerPosition isNil \\n\\t\\tifTrue: [self removeProperty: #formerPosition]\\n\\t\\tifFalse: [self setProperty: #formerPosition toValue: formerPosition]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/6/2000 15:13'!\\ngrabTransform\\n\\t\\\"Return the transform for the receiver which should be applied during grabbing\\\"\\n\\t^owner ifNil:[IdentityTransform new] ifNotNil:[owner grabTransform]! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 10:53'!\\nhighlightedForDrop\\n\\t^(self valueOfProperty: #highlightedForDrop) == true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 11:51'!\\nhighlightForDrop\\n\\tself highlightForDrop: true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 12:01'!\\nhighlightForDrop: aBoolean\\n\\tself setProperty: #highlightedForDrop toValue: aBoolean.\\n\\tself changed! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 9/10/2004 13:42'!\\njustDroppedInto: aMorph event: anEvent\\n\\t\\\"This message is sent to a dropped morph after it has been dropped on -- and been accepted by -- a drop-sensitive morph\\\"\\n\\n\\t| aWindow partsBinCase cmd aStack |\\n\\t(self formerOwner notNil and: [self formerOwner ~~ aMorph])\\n\\t\\tifTrue: [self removeHalo].\\n\\tself formerOwner: nil.\\n\\tself formerPosition: nil.\\n\\tcmd _ self valueOfProperty: #undoGrabCommand.\\n\\tcmd ifNotNil:[aMorph rememberCommand: cmd.\\n\\t\\t\\t\\tself removeProperty: #undoGrabCommand].\\n\\t(partsBinCase _ aMorph isPartsBin) ifFalse:\\n\\t\\t[self isPartsDonor: false].\\n\\t(aWindow _ aMorph ownerThatIsA: SystemWindow) ifNotNil:\\n\\t\\t[aWindow isActive ifFalse:\\n\\t\\t\\t[aWindow activate]].\\n\\t(self isInWorld and: [partsBinCase not]) ifTrue:\\n\\t\\t[self world startSteppingSubmorphsOf: self].\\n\\t\\\"Note an unhappy inefficiency here: the startStepping... call will often have already been called in the sequence leading up to entry to this method, but unfortunately the isPartsDonor: call often will not have already happened, with the result that the startStepping... call will not have resulted in the startage of the steppage.\\\"\\n\\n\\t\\\"An object launched by certain parts-launcher mechanisms should end up fully visible...\\\"\\n\\t(self hasProperty: #beFullyVisibleAfterDrop) ifTrue:\\n\\t\\t[aMorph == ActiveWorld ifTrue:\\n\\t\\t\\t[self goHome].\\n\\t\\tself removeProperty: #beFullyVisibleAfterDrop].\\n\\n\\t(self holdsSeparateDataForEachInstance and: [(aStack _ self stack) notNil])\\n\\t\\tifTrue:\\n\\t\\t\\t[aStack reassessBackgroundShape]\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 2/6/2001 22:12'!\\njustGrabbedFrom: formerOwner\\n\\t\\\"The receiver was just grabbed from its former owner and is now attached to the hand. By default, we pass this message on if we're a renderer.\\\"\\n\\t(self isRenderer and:[self hasSubmorphs]) \\n\\t\\tifTrue:[self firstSubmorph justGrabbedFrom: formerOwner].! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 3/27/2001 11:52'!\\nnameForUndoWording\\n\\t\\\"Return wording appropriate to the receiver for use in an undo-related menu item (and perhaps elsewhere)\\\"\\n\\n\\t| aName |\\n\\taName _ self knownName ifNil: [self renderedMorph class name].\\n\\t^ aName truncateTo: 24! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'di 12/12/2000 14:35'!\\nrejectDropMorphEvent: evt\\n\\t\\\"The receiver has been rejected, and must be put back somewhere. There are three cases:\\n\\t(1) It remembers its former owner and position, and goes right back there\\n\\t(2) It remembers its former position only, in which case it was torn off from a parts bin, and the UI is that it floats back to its donor position and then vanishes.\\n\\t(3) Neither former owner nor position is remembered, in which case it is whisked to the Trash\\\"\\n\\n\\tself removeProperty: #undoGrabCommand.\\n\\t(self formerOwner notNil and: [self formerOwner isPartsBin not]) ifTrue:\\n\\t\\t[^ self slideBackToFormerSituation: evt].\\n\\n\\tself formerPosition ifNotNil: \\\"Position but no owner -- can just make it vanish\\\"\\n\\t\\t[^ self vanishAfterSlidingTo: self formerPosition event: evt].\\n\\t\\t\\n\\tself slideToTrash: evt! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 1/11/1999 20:07'!\\nrepelsMorph: aMorph event: ev\\n\\t^ false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/28/2000 12:02'!\\nresetHighlightForDrop\\n\\tself highlightForDrop: false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:24'!\\nseparateDragAndDrop\\n\\t\\\"Conversion only. Separate the old #dragNDropEnabled into #dragEnabled and #dropEnabled and remove the old property.\\\"\\n\\t| dnd |\\n\\t(self hasProperty: #dragNDropEnabled) ifFalse:[^self].\\n\\tdnd _ (self valueOfProperty: #dragNDropEnabled) == true.\\n\\tself dragEnabled: dnd.\\n\\tself dropEnabled: dnd.\\n\\tself removeProperty: #dragNDropEnabled.\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 8/12/2003 23:35'!\\nslideBackToFormerSituation: evt \\n\\t| slideForm formerOwner formerPosition aWorld startPoint endPoint trans |\\n\\tformerOwner := self formerOwner.\\n\\tformerPosition := self formerPosition.\\n\\taWorld := evt hand world.\\n\\ttrans := formerOwner transformFromWorld.\\n\\tslideForm := trans isPureTranslation \\n\\t\\t\\t\\tifTrue: [self imageForm offset: 0 @ 0]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[((TransformationMorph new asFlexOf: self) transform: trans) imageForm \\n\\t\\t\\t\\t\\t\\toffset: 0 @ 0]. \\n\\tstartPoint := evt hand fullBounds origin.\\n\\tendPoint := trans localPointToGlobal: formerPosition.\\n\\towner removeMorph: self.\\n\\taWorld displayWorld.\\n\\tslideForm \\n\\t\\tslideFrom: startPoint\\n\\t\\tto: endPoint\\n\\t\\tnSteps: 12\\n\\t\\tdelay: 15.\\n\\tformerOwner addMorph: self.\\n\\tself position: formerPosition.\\n\\tself justDroppedInto: formerOwner event: evt! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 4/3/2006 14:12'!\\nslideToTrash: evt\\n\\t\\\"Perhaps slide the receiver across the screen to a trash can and make it disappear into it. In any case, remove the receiver from the screen.\\\"\\n\\n\\t| aForm trash startPoint endPoint morphToSlide |\\n\\t((self renderedMorph == Utilities scrapsBook) or: [self renderedMorph isKindOf: TrashCanMorph]) ifTrue:\\n\\t\\t[self dismissMorph. ^ self].\\n\\tPreferences slideDismissalsToTrash ifTrue:\\n\\t\\t[morphToSlide _ self representativeNoTallerThan: 200 norWiderThan: 200 thumbnailHeight: 100.\\n\\t\\taForm _ morphToSlide imageForm offset: (0@0).\\n\\t\\ttrash _ ActiveWorld\\n\\t\\t\\tfindDeepSubmorphThat:\\n\\t\\t\\t\\t[:aMorph | (aMorph isKindOf: TrashCanMorph) and:\\n\\t\\t\\t\\t\\t[aMorph topRendererOrSelf owner == ActiveWorld]]\\n\\t\\t\\tifAbsent:\\n\\t\\t\\t\\t[trash _ TrashCanMorph new.\\n\\t\\t\\t\\ttrash bottomLeft: ActiveWorld bottomLeft - (-10@10).\\n\\t\\t\\t\\ttrash openInWorld.\\n\\t\\t\\t\\ttrash].\\n\\t\\tendPoint _ trash fullBoundsInWorld center.\\n\\t\\tstartPoint _ self topRendererOrSelf fullBoundsInWorld center - (aForm extent // 2)].\\n\\tself dismissMorph.\\n\\tActiveWorld displayWorld.\\n\\tPreferences slideDismissalsToTrash ifTrue:\\n\\t\\t[aForm slideFrom: startPoint to: endPoint nSteps: 12 delay: 15].\\n\\tUtilities addToTrash: self! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'mir 1/4/2001 11:02'!\\nstartDrag: anItem with: anObject\\n\\tself currentHand attachMorph: anObject! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'panda 4/25/2000 15:46'!\\ntoggleDragNDrop\\n\\t\\\"Toggle this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\t\\tself enableDragNDrop: self dragNDropEnabled not.\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing'!\\ntransportedMorph\\n\\t^self! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'dgd 8/26/2003 21:44'!\\nundoGrabCommand\\n\\t\\\"Return an undo command for grabbing the receiver\\\"\\n\\n\\t| cmd |\\n\\towner ifNil:\\n\\t\\t[^ nil]. \\\"no owner - no undo\\\"\\n\\t^ (cmd _ Command new)\\n\\t\\tcmdWording: 'move ' translated, self nameForUndoWording;\\n\\t\\tundoTarget: self\\n\\t\\tselector: #undoMove:redo:owner:bounds:predecessor:\\n\\t\\targuments: {cmd. false. owner. self bounds. (owner morphPreceding: self)};\\n\\t\\tyourself! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'bf 1/5/2000 19:11'!\\nvanishAfterSlidingTo: aPosition event: evt\\n\\n\\t| aForm aWorld startPoint endPoint |\\n\\taForm _ self imageForm offset: 0@0.\\n\\taWorld _ self world.\\n\\tstartPoint _ evt hand fullBounds origin.\\n\\tself delete.\\n\\taWorld displayWorld.\\n\\tendPoint _ aPosition.\\n\\taForm slideFrom: startPoint to: endPoint nSteps: 12 delay: 15.\\n\\tPreferences soundsEnabled ifTrue: [TrashCanMorph playDeleteSound].\\n! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 10/11/2000 18:24'!\\nwantsDroppedMorph: aMorph event: evt\\n\\t\\\"Return true if the receiver wishes to accept the given morph, which is being dropped by a hand in response to the given event. Note that for a successful drop operation both parties need to agree. The symmetric check is done automatically via aMorph wantsToBeDroppedInto: self.\\\"\\n\\n\\t^self dropEnabled! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 9/18/2000 18:34'!\\nwantsToBeDroppedInto: aMorph\\n\\t\\\"Return true if it's okay to drop the receiver into aMorph. This check is symmetric to #wantsDroppedMorph:event: to give both parties a chance of figuring out whether they like each other.\\\"\\n\\t^true! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'ar 2/10/1999 05:44'!\\nwantsToBeOpenedInWorld\\n\\t\\\"Return true if the receiver wants to be put into the World directly,\\n\\trather than allowing the user to place it (e.g., prevent attaching me\\n\\tto the hand after choosing 'new morph' in the world menu)\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'dropping/grabbing' stamp: 'sw 8/15/2000 16:58'!\\nwillingToBeDiscarded\\n\\t^ true! !\\n\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 9/6/2000 12:42'!\\nclick\\n\\t\\\"Pretend the user clicked on me.\\\"\\n\\n\\t(self handlesMouseDown: nil) ifTrue: [\\n\\t\\tself mouseDown: nil.\\n\\t\\tself mouseUp: nil].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'LC 5/18/2000 09:54'!\\nclick: evt\\n\\t\\\"Handle a single-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\n\\tLC 2/14/2000 08:32 - added: EventHandler notification\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler click: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 3/8/1999 00:17'!\\ncursorPoint\\n\\t^ self currentHand lastEvent cursorPoint! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'jcg 10/2/2001 09:26'!\\ndoubleClickTimeout: evt\\n\\t\\\"Handle a double-click timeout event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler doubleClickTimeout: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'LC 5/18/2000 09:54'!\\ndoubleClick: evt\\n\\t\\\"Handle a double-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\n\\tLC 2/14/2000 08:32 - added: EventHandler notification\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler doubleClick: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 1/10/2001 21:28'!\\ndropFiles: anEvent\\n\\t\\\"Handle a number of files dropped from the OS\\\"\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'RAA 2/12/2001 15:26'!\\nfirstClickTimedOut: evt\\n\\t\\\"Useful for double-click candidates who want to know whether or not the click is a single or double. In this case, ignore the #click: and wait for either this or #doubleClick:\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'nk 3/10/2004 19:48'!\\nhandlerForYellowButtonDown: anEvent \\n\\t\\\"Return the (prospective) handler for a mouse down event with the yellow button pressed.\\n\\tThe \\thandler is temporarily installed and can be used for morphs further \\n\\tdown the hierarchy to negotiate whether the inner or the outer \\n\\tmorph should finally handle the event.\\\"\\n\\n\\t(self hasYellowButtonMenu or: [ self handlesMouseDown: anEvent ])\\n\\t\\tifFalse: [ ^ nil].\\t\\\"Not interested.\\\"\\n\\n\\tanEvent handler\\n\\t\\tifNil: [^ self].\\t\\\"Nobody else was interested\\\"\\n\\n\\t\\\"Same priority but I am innermost.\\\"\\n\\t^ self mouseDownPriority >= anEvent handler mouseDownPriority\\n\\t\\tifFalse: [nil ]\\n\\t\\tifTrue: [self]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/28/2000 22:18'!\\nhandlesKeyboard: evt\\n\\t\\\"Return true if the receiver wishes to handle the given keyboard event\\\"\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesKeyboard: evt].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'nk 2/14/2004 18:42'!\\nhandlesMouseDown: evt\\n\\t\\\"Do I want to receive mouseDown events (mouseDown:, mouseMove:, mouseUp:)?\\\"\\n\\t\\\"NOTE: The default response is false, except if you have added sensitivity to mouseDown events using the on:send:to: mechanism. Subclasses that implement these messages directly should override this one to return true.\\\" \\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseDown: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:31'!\\nhandlesMouseOverDragging: evt\\n\\t\\\"Return true if I want to receive mouseEnterDragging: and mouseLeaveDragging: when the hand drags something over me (button up or button down), or when the mouse button is down but there is no mouseDown recipient. The default response is false, except if you have added sensitivity to mouseEnterLaden: or mouseLeaveLaden:, using the on:send:to: mechanism.\\\"\\n\\t\\\"NOTE: If the hand state matters in these cases, it may be tested by constructs such as\\n\\t\\tevent anyButtonPressed\\n\\t\\tevent hand hasSubmorphs\\\"\\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseOverDragging: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:31'!\\nhandlesMouseOver: evt\\n\\t\\\"Do I want to receive mouseEnter: and mouseLeave: when the button is up and the hand is empty? The default response is false, except if you have added sensitivity to mouseEnter: or mouseLeave:, using the on:send:to: mechanism.\\\" \\n\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseOver: evt].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/22/2000 17:06'!\\nhandlesMouseStillDown: evt\\n\\t\\\"Return true if the receiver wants to get repeated #mouseStillDown: messages between #mouseDown: and #mouseUp\\\"\\n\\tself eventHandler ifNotNil: [^ self eventHandler handlesMouseStillDown: evt].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 4/2/98 14:16'!\\nhasFocus\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling'!\\nkeyboardFocusChange: aBoolean\\n\\t\\\"The message is sent to a morph when its keyboard focus change. The given argument indicates that the receiver is gaining keyboard focus (versus losing) the keyboard focus. Morphs that accept keystrokes should change their appearance in some way when they are the current keyboard focus. This default implementation does nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 9/14/2000 18:23'!\\nkeyDown: anEvent\\n\\t\\\"Handle a key down event. The default response is to do nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:05'!\\nkeyStroke: anEvent\\n\\t\\\"Handle a keystroke event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler keyStroke: anEvent fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'KTT 6/1/2004 11:41'!\\nkeyUp: anEvent\\n\\t\\\"Handle a key up event. The default response is to do nothing.\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 9/19/2004 13:14'!\\nmouseDown: evt \\n\\t\\\"Handle a mouse down event. The default response is to let my \\n\\teventHandler, if any, handle it.\\\"\\n\\tevt yellowButtonPressed\\n\\t\\tifTrue: [\\\"First check for option (menu) click\\\"\\n\\t\\t\\t^ self yellowButtonActivity: evt shiftPressed].\\n\\tself eventHandler\\n\\t\\tifNotNil: [self eventHandler mouseDown: evt fromMorph: self]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:33'!\\nmouseEnterDragging: evt\\n\\t\\\"Handle a mouseEnterDragging event, meaning the mouse just entered my bounds with a button pressed or laden with submorphs. The default response is to let my eventHandler, if any, handle it, or else to do nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[^ self eventHandler mouseEnterDragging: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:00'!\\nmouseEnter: evt\\n\\t\\\"Handle a mouseEnter event, meaning the mouse just entered my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseEnter: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/1998 07:38'!\\nmouseLeaveDragging: evt\\n\\t\\\"Handle a mouseLeaveLaden event, meaning the mouse just left my bounds with a button pressed or laden with submorphs. The default response is to let my eventHandler, if any, handle it; else to do nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseLeaveDragging: evt fromMorph: self]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:01'!\\nmouseLeave: evt\\n\\t\\\"Handle a mouseLeave event, meaning the mouse just left my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseLeave: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:04'!\\nmouseMove: evt\\n\\t\\\"Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseMove: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:02'!\\nmouseStillDownThreshold\\n\\t\\\"Return the number of milliseconds after which mouseStillDown: should be sent\\\"\\n\\t^200! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 10/22/2000 17:08'!\\nmouseStillDown: evt\\n\\t\\\"Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseStillDown: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:05'!\\nmouseUp: evt\\n\\t\\\"Handle a mouse up event. The default response is to let my eventHandler, if any, handle it.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler mouseUp: evt fromMorph: self].\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 8/28/2004 18:20'!\\nmoveOrResizeFromKeystroke: anEvent \\n\\t\\\"move or resize the receiver based on a keystroke\\\"\\n\\t| dir | \\n\\n\\tanEvent keyValue = 28 ifTrue: [dir := -1 @ 0].\\n\\tanEvent keyValue = 29 ifTrue: [dir := 1 @ 0].\\n\\tanEvent keyValue = 30 ifTrue: [dir := 0 @ -1].\\n\\tanEvent keyValue = 31 ifTrue: [dir := 0 @ 1].\\n\\n\\tdir notNil\\n\\t\\tifTrue:[\\n\\t\\t\\tanEvent controlKeyPressed ifTrue: [dir := dir * 10].\\n\\n\\t\\t\\tanEvent shiftPressed\\n\\t\\t\\t\\tifTrue: [self extent: self extent + dir]\\n\\t\\t\\t\\tifFalse: [self position: self position + dir].\\n\\n\\t\\t\\t\\\"anEvent wasHandled: true.\\\"\\n\\t]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:01'!\\non: eventName send: selector to: recipient\\n\\tself eventHandler ifNil: [self eventHandler: EventHandler new].\\n\\tself eventHandler on: eventName send: selector to: recipient! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 3/18/2001 17:21'!\\non: eventName send: selector to: recipient withValue: value\\n\\t\\\"NOTE: selector must take 3 arguments, of which value will be the *** FIRST ***\\\"\\n\\n\\tself eventHandler ifNil: [self eventHandler: EventHandler new].\\n\\tself eventHandler on: eventName send: selector to: recipient withValue: value\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'fbs 1/7/2005 15:43'!\\npreferredKeyboardBounds\\n\\n\\t^ self bounds: self bounds in: World.\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'fbs 1/7/2005 15:42'!\\npreferredKeyboardPosition\\n\\n\\t^ (self bounds: self bounds in: World) topLeft.\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'tk 8/10/1998 16:02'!\\nremoveLink: actionCode\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler on: actionCode send: nil to: nil]! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/16/1998 08:06'!\\nrestoreSuspendedEventHandler\\n\\t| savedHandler |\\n\\t(savedHandler _ self valueOfProperty: #suspendedEventHandler) ifNotNil:\\n\\t\\t[self eventHandler: savedHandler].\\n\\tsubmorphs do: [:m | m restoreSuspendedEventHandler]\\n! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'mir 5/23/2000 17:43'!\\nstartDrag: evt\\n\\t\\\"Handle a double-click event. This message is only sent to clients that request it by sending #waitForClicksOrDrag:event: to the initiating hand in their mouseDown: method. This default implementation does nothing.\\\"\\n\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler startDrag: evt fromMorph: self].! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/16/1998 08:07'!\\nsuspendEventHandler\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self setProperty: #suspendedEventHandler toValue: self eventHandler.\\n\\t\\tself eventHandler: nil].\\n\\tsubmorphs do: [:m | m suspendEventHandler]. \\\"All those rectangles\\\"! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 8/28/2004 18:42'!\\ntabAmongFields\\n\\t^ Preferences tabAmongFields\\n\\t\\tor: [self hasProperty: #tabAmongFields] ! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'RAA 6/19/2000 07:13'!\\ntransformFromOutermostWorld\\n\\t\\\"Return a transform to map world coordinates into my local coordinates\\\"\\n\\n\\t\\\"self isWorldMorph ifTrue: [^ MorphicTransform identity].\\\"\\n\\t^ self transformFrom: self outermostWorldMorph! !\\n\\n!Morph methodsFor: 'event handling'!\\ntransformFromWorld\\n\\t\\\"Return a transform to map world coordinates into my local coordinates\\\"\\n\\n\\t^ self transformFrom: nil! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 14:36'!\\ntransformFrom: uberMorph \\n\\t\\\"Return a transform to be used to map coordinates in a morph above me into my childrens coordinates, or vice-versa. This is used to support scrolling, scaling, and/or rotation. This default implementation just returns my owner's transform or the identity transform if my owner is nil. \\n\\tNote: This method cannot be used to map into the receiver's coordinate system!!\\\"\\n\\n\\t(self == uberMorph or: [owner isNil]) ifTrue: [^IdentityTransform new].\\n\\t^owner transformFrom: uberMorph! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'ar 1/10/2001 21:28'!\\nwantsDropFiles: anEvent\\n\\t\\\"Return true if the receiver wants files dropped from the OS.\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'di 9/14/2000 11:46'!\\nwantsEveryMouseMove\\n\\t\\\"Unless overridden, this method allows processing to skip mouse move events\\n\\twhen processing is lagging. No 'significant' event (down/up, etc) will be skipped.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 11/3/97 02:11'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t\\\"Answer whether a plain mouse click on aSubmorph, a text-edit-capable thing, should result in a text selection there\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 5/6/1998 12:54'!\\nwouldAcceptKeyboardFocus\\n\\t\\\"Answer whether a plain mouse click on the receiver should result in a text selection there\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'sw 8/29/2000 14:57'!\\nwouldAcceptKeyboardFocusUponTab\\n\\t\\\"Answer whether the receiver is in the running as the new keyboard focus if the tab key were hit at a meta level. This provides the leverage for tabbing among fields of a card, for example.\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'event handling' stamp: 'dgd 7/28/2005 13:02'!\\nyellowButtonActivity: shiftState \\n\\t\\\"Find me or my outermost owner that has items to add to a \\n\\tyellow button menu. \\n\\tshiftState is true if the shift was pressed. \\n\\tOtherwise, build a menu that contains the contributions from \\n\\tmyself and my interested submorphs, \\n\\tand present it to the user.\\\"\\n\\t| menu |\\n\\tself isWorldMorph\\n\\t\\tifFalse: [| outerOwner | \\n\\t\\t\\touterOwner := self outermostOwnerWithYellowButtonMenu.\\n\\t\\t\\touterOwner\\n\\t\\t\\t\\tifNil: [^ self].\\n\\t\\t\\touterOwner == self\\n\\t\\t\\t\\tifFalse: [^ outerOwner yellowButtonActivity: shiftState]].\\n\\tmenu := self buildYellowButtonMenu: ActiveHand.\\n\\tmenu\\n\\t\\taddTitle: self externalName\\n\\t\\ticon: (self iconOrThumbnailOfSize: (Preferences tinyDisplay ifTrue: [16] ifFalse: [28])).\\n\\tmenu popUpInWorld: self currentWorld! !\\n\\n\\n!Morph methodsFor: 'events-accessing' stamp: 'rw 4/25/2002 07:18'!\\nactionMap\\n\\t\\\"Answer an action map\\\"\\n\\n\\t| actionMap |\\n\\tactionMap := self valueOfProperty: #actionMap.\\n\\tactionMap ifNil:\\n\\t\\t[actionMap _ self createActionMap].\\n\\t^ actionMap! !\\n\\n!Morph methodsFor: 'events-accessing' stamp: 'rw 4/25/2002 07:17'!\\nupdateableActionMap\\n\\t\\\"Answer an updateable action map, saving it in my #actionMap property\\\"\\n\\t\\n\\t| actionMap |\\n\\tactionMap := self valueOfProperty: #actionMap.\\n\\tactionMap ifNil:\\n\\t\\t[actionMap _ self createActionMap.\\n\\t\\tself setProperty: #actionMap toValue: actionMap].\\n\\t^ actionMap! !\\n\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: #() after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: #() at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector withArguments: args after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: args at: Time millisecondClockValue + delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:15'!\\naddAlarm: aSelector withArguments: args at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler addAlarm: aSelector withArguments: args for: self at: scheduledTime].! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1) after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1) at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 with: arg2 after: delayTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1 with: arg2) after: delayTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:35'!\\naddAlarm: aSelector with: arg1 with: arg2 at: scheduledTime\\n\\t\\\"Add an alarm (that is an action to be executed once) with the given set of parameters\\\"\\n\\t^self addAlarm: aSelector withArguments: (Array with: arg1 with: arg2) at: scheduledTime! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/11/2000 16:34'!\\nalarmScheduler\\n\\t\\\"Return the scheduler being responsible for triggering alarms\\\"\\n\\t^self world! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:14'!\\nremoveAlarm: aSelector\\n\\t\\\"Remove the given alarm\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler removeAlarm: aSelector for: self].! !\\n\\n!Morph methodsFor: 'events-alarms' stamp: 'ar 9/14/2000 12:15'!\\nremoveAlarm: aSelector at: scheduledTime\\n\\t\\\"Remove the given alarm\\\"\\n\\t| scheduler |\\n\\tscheduler _ self alarmScheduler.\\n\\tscheduler ifNotNil:[scheduler removeAlarm: aSelector at: scheduledTime for: self].! !\\n\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 17:58'!\\ncontainsPoint: aPoint event: anEvent\\n\\t\\\"Return true if aPoint is considered to be inside the receiver for the given event.\\n\\tThe default implementation treats locked children as integral part of their owners.\\\"\\n\\t(self fullBounds containsPoint: aPoint) ifFalse:[^false].\\n\\t(self containsPoint: aPoint) ifTrue:[^true].\\n\\tself submorphsDo:[:m|\\n\\t\\t(m isLocked and:[m fullContainsPoint: \\n\\t\\t\\t((m transformedFrom: self) globalPointToLocal: aPoint)]) ifTrue:[^true]].\\n\\t^false! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 14:51'!\\ndefaultEventDispatcher\\n\\t\\\"Return the default event dispatcher to use with events that are directly sent to the receiver\\\"\\n\\t^MorphicEventDispatcher new! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 1/10/2001 21:35'!\\nhandleDropFiles: anEvent\\n\\t\\\"Handle a drop from the OS.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t(self wantsDropFiles: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself dropFiles: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'di 12/12/2000 14:39'!\\nhandleDropMorph: anEvent\\n\\t\\\"Handle a dropping morph.\\\"\\n\\t| aMorph localPt |\\n\\taMorph _ anEvent contents.\\n\\t\\\"Do a symmetric check if both morphs like each other\\\"\\n\\t((self wantsDroppedMorph: aMorph event: anEvent)\\t\\\"I want her\\\"\\n\\t\\tand: [aMorph wantsToBeDroppedInto: self])\\t\\t\\\"she wants me\\\"\\n\\t\\tifFalse: [aMorph removeProperty: #undoGrabCommand.\\n\\t\\t\\t\\t^ self].\\n\\tanEvent wasHandled: true.\\n\\t\\\"Transform the morph into the receiver's coordinate frame. This is currently incomplete since it only takes the offset into account where it really should take the entire transform.\\\"\\n\\tlocalPt _ (self transformedFrom: anEvent hand world) \\\"full transform down\\\"\\n\\t\\t\\t\\tglobalPointToLocal: aMorph referencePosition.\\n\\taMorph referencePosition: localPt.\\n\\tself acceptDroppingMorph: aMorph event: anEvent.\\n\\taMorph justDroppedInto: self event: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 21:13'!\\nhandleEvent: anEvent\\n\\t\\\"Handle the given event\\\"\\n\\t^anEvent sentTo: self.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/4/2000 18:48'!\\nhandleFocusEvent: anEvent\\n\\t\\\"Handle the given event. This message is sent if the receiver currently has the focus and is therefore receiving events directly from some hand.\\\"\\n\\t^self handleEvent: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 23:01'!\\nhandleKeyDown: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\t^self keyDown: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 23:01'!\\nhandleKeyUp: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\t^self keyUp: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'md 8/2/2006 18:57'!\\nhandleKeystroke: anEvent \\n\\t\\\"System level event handling.\\\"\\n\\t\\n\\tanEvent wasHandled\\n\\t\\tifTrue: [^ self].\\n\\t(self handlesKeyboard: anEvent)\\n\\t\\tifFalse: [^ self].\\n\\tanEvent wasHandled: true.\\n\\t^ self keyStroke: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/16/2000 14:22'!\\nhandleListenEvent: anEvent\\n\\t\\\"Handle the given event. This message is sent if the receiver is a registered listener for the given event.\\\"\\n\\t^anEvent sentTo: self.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'dgd 9/10/2004 13:36'!\\nhandleMouseDown: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent wasHandled: true.\\n\\n\\t(anEvent controlKeyPressed\\n\\t\\t\\tand: [Preferences cmdGesturesEnabled])\\n\\t\\tifTrue: [^ self invokeMetaMenu: anEvent].\\n\\n\\t\\\"Make me modal during mouse transitions\\\"\\n\\tanEvent hand newMouseFocus: self event: anEvent.\\n\\tanEvent blueButtonChanged ifTrue:[^self blueButtonDown: anEvent].\\n\\t\\n\\t\\\"this mouse down could be the start of a gesture, or the end of a gesture focus\\\"\\n\\t(self isGestureStart: anEvent)\\n\\t\\tifTrue: [^ self gestureStart: anEvent].\\n\\n\\tself mouseDown: anEvent.\\n\\n\\tPreferences maintainHalos\\n\\t\\tifFalse:[ anEvent hand removeHaloFromClick: anEvent on: self ].\\n\\n\\t(self handlesMouseStillDown: anEvent) ifTrue:[\\n\\t\\tself startStepping: #handleMouseStillDown: \\n\\t\\t\\tat: Time millisecondClockValue + self mouseStillDownThreshold\\n\\t\\t\\targuments: {anEvent copy resetHandlerFields}\\n\\t\\t\\tstepTime: self mouseStillDownStepRate ].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 8/8/2001 15:29'!\\nhandleMouseEnter: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\t(anEvent isDraggingEvent) ifTrue:[\\n\\t\\t(self handlesMouseOverDragging: anEvent) ifTrue:[\\n\\t\\t\\tanEvent wasHandled: true.\\n\\t\\t\\tself mouseEnterDragging: anEvent].\\n\\t\\t^self].\\n\\tself wantsHalo \\\"If receiver wants halo and balloon, trigger balloon after halo\\\"\\n\\t\\tifTrue:[anEvent hand triggerHaloFor: self after: self haloDelayTime]\\n\\t\\tifFalse:[self wantsBalloon\\n\\t\\t\\tifTrue:[anEvent hand triggerBalloonFor: self after: self balloonHelpDelayTime]].\\n\\t(self handlesMouseOver: anEvent) ifTrue:[\\n\\t\\tanEvent wasHandled: true.\\n\\t\\tself mouseEnter: anEvent.\\n\\t].! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/6/2000 00:15'!\\nhandleMouseLeave: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent isDraggingEvent ifTrue:[\\n\\t\\t(self handlesMouseOverDragging: anEvent) ifTrue:[\\n\\t\\t\\tanEvent wasHandled: true.\\n\\t\\t\\tself mouseLeaveDragging: anEvent].\\n\\t\\t^self].\\n\\t(self handlesMouseOver: anEvent) ifTrue:[\\n\\t\\tanEvent wasHandled: true.\\n\\t\\tself mouseLeave: anEvent.\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'nk 6/13/2004 09:16'!\\nhandleMouseMove: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t\\\"Rules say that by default a morph gets #mouseMove iff\\n\\t\\t* the hand is not dragging anything,\\n\\t\\t\\t+ and some button is down,\\n\\t\\t\\t+ and the receiver is the current mouse focus.\\\"\\n\\t(anEvent hand hasSubmorphs) ifTrue:[^self].\\n\\t(anEvent anyButtonPressed and:[anEvent hand mouseFocus == self]) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself mouseMove: anEvent.\\n\\t(self handlesMouseStillDown: anEvent) ifTrue:[\\n\\t\\t\\\"Step at the new location\\\"\\n\\t\\tself startStepping: #handleMouseStillDown: \\n\\t\\t\\tat: Time millisecondClockValue\\n\\t\\t\\targuments: {anEvent copy resetHandlerFields}\\n\\t\\t\\tstepTime: self mouseStillDownStepRate ].\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 4/23/2001 17:24'!\\nhandleMouseOver: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent hand mouseFocus == self ifTrue:[\\n\\t\\t\\\"Got this directly through #handleFocusEvent: so check explicitly\\\"\\n\\t\\t(self containsPoint: anEvent position event: anEvent) ifFalse:[^self]].\\n\\tanEvent hand noticeMouseOver: self event: anEvent! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/22/2000 17:11'!\\nhandleMouseStillDown: anEvent\\n\\t\\\"Called from the stepping mechanism for morphs wanting continuously repeated 'yes the mouse is still down, yes it is still down, yes it has not changed yet, no the mouse is still not up, yes the button is down' etc messages\\\"\\n\\t(anEvent hand mouseFocus == self) \\n\\t\\tifFalse:[^self stopSteppingSelector: #handleMouseStillDown:].\\n\\tself mouseStillDown: anEvent.\\n! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/22/2000 17:09'!\\nhandleMouseUp: anEvent\\n\\t\\\"System level event handling.\\\"\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand mouseFocus == self ifFalse:[^self]. \\\"Not interested in other parties\\\"\\n\\tanEvent hand releaseMouseFocus: self.\\n\\tanEvent wasHandled: true.\\n\\tanEvent blueButtonChanged\\n\\t\\tifTrue:[self blueButtonUp: anEvent]\\n\\t\\tifFalse:[self mouseUp: anEvent.\\n\\t\\t\\t\\tself stopSteppingSelector: #handleMouseStillDown:].! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'md 10/22/2003 15:55'!\\nhandleUnknownEvent: anEvent\\n\\t\\\"An event of an unknown type was sent to the receiver. What shall we do?!!\\\"\\n\\tBeeper beep. \\n\\tanEvent printString displayAt: 0@0.\\n\\tanEvent wasHandled: true.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'sw 10/5/2002 01:47'!\\nmouseDownPriority\\n\\t\\\"Return the default mouse down priority for the receiver\\\"\\n\\n\\t^ (self isPartsDonor or: [self isPartsBin])\\n\\t\\tifTrue:\\t[50]\\n\\t\\tifFalse:\\t[0]\\n\\n\\t\\\"The above is a workaround for the complete confusion between parts donors and parts bins. Morphs residing in a parts bin may or may not have the parts donor property set; if they have they may or may not actually handle events. To work around this, parts bins get an equal priority to parts donors so that when a morph in the parts bin does have the property set but does not handle the event we still get a copy from picking it up through the parts bin. Argh. This just *cries* for a cleanup.\\\"\\n\\t\\\"And the above comment is Andreas's from 10/2000, which was formerly retrievable by a #flag: call which however caused a problem when trying to recompile the method from decompiled source.\\\"! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/13/2000 17:14'!\\nprocessEvent: anEvent\\n\\t\\\"Process the given event using the default event dispatcher.\\\"\\n\\t^self processEvent: anEvent using: self defaultEventDispatcher! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/18/2000 19:14'!\\nprocessEvent: anEvent using: defaultDispatcher\\n\\t\\\"This is the central entry for dispatching events in morphic. Given some event and a default dispatch strategy, find the right receiver and let him handle it.\\n\\tWARNING: This is a powerful hook. If you want to use a different event dispatcher from the default, here is the place to hook it in. Depending on how the dispatcher is written (e.g., whether it calls simply #processEvent: or #processEvent:using:) you can change the dispatch strategy for entire trees of morphs. Similarly, you can disable entire trees of morphs from receiving any events whatsoever. Read the documentation in class MorphicEventDispatcher before playing with it. \\\"\\n\\t(self rejectsEvent: anEvent) ifTrue:[^#rejected].\\n\\t^defaultDispatcher dispatchEvent: anEvent with: self! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 10/5/2000 19:25'!\\nrejectDropEvent: anEvent\\n\\t\\\"This hook allows the receiver to repel a drop operation currently executed. The method is called prior to checking children so the receiver must validate that the event was really designated for it.\\n\\tNote that the ordering of the tests below is designed to avoid a (possibly expensive) #fullContainsPoint: test. If the receiver doesn't want to repel the morph anyways we don't need to check after all.\\\"\\n\\t(self repelsMorph: anEvent contents event: anEvent) ifFalse:[^self]. \\\"not repelled\\\"\\n\\t(self fullContainsPoint: anEvent position) ifFalse:[^self]. \\\"not for me\\\"\\n\\t\\\"Throw it away\\\"\\n\\tanEvent wasHandled: true.\\n\\tanEvent contents rejectDropMorphEvent: anEvent.! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/12/2000 23:40'!\\nrejectsEvent: anEvent\\n\\t\\\"Return true to reject the given event. Rejecting an event means neither the receiver nor any of it's submorphs will be given any chance to handle it.\\\"\\n\\t^self isLocked or:[self visible not]! !\\n\\n!Morph methodsFor: 'events-processing' stamp: 'ar 9/15/2000 21:09'!\\ntransformedFrom: uberMorph\\n\\t\\\"Return a transform to map coordinates of uberMorph, a morph above me in my owner chain, into the coordinates of MYSELF not any of my children.\\\"\\n\\tself flag: #arNote. \\\"rename this method\\\"\\n\\towner ifNil:[^IdentityTransform new].\\n\\t^ (owner transformFrom: uberMorph)! !\\n\\n\\n!Morph methodsFor: 'events-removing' stamp: 'rw 4/25/2002 07:18'!\\nreleaseActionMap\\n\\t\\\"Release the action map\\\"\\n\\t\\n \\tself removeProperty: #actionMap! !\\n\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 08:35'!\\nattachToResource\\n\\t\\\"Produce a morph from a file -- either a saved .morph file or a graphics file\\\"\\n\\n\\t| pathName |\\n\\tpathName _ Utilities chooseFileWithSuffixFromList: (#('.morph'), Utilities graphicsFileSuffixes)\\n\\t\\t\\twithCaption: 'Choose a file\\nto load'.\\n\\tpathName ifNil: [^ self]. \\\"User made no choice\\\"\\n\\tpathName == #none ifTrue: [^ self inform: \\n'Sorry, no suitable files found\\n(names should end with .morph, .gif,\\n.bmp, .jpeg, .jpe, .jp, or .form)'].\\n\\n\\tself setProperty: #resourceFilePath toValue: pathName! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tak 2/10/2006 02:24'!\\nprepareToBeSaved\\n\\t\\\"Prepare this morph to be saved to disk. Subclasses should nil out any instance variables that holds state that should not be saved, such as cached Forms. Note that this operation may take more drastic measures than releaseCachedState; for example, it might discard the transcript of an interactive chat session.\\\"\\n\\n\\tself releaseCachedState.\\n\\tself formerOwner: nil.\\n\\tself formerPosition: nil.\\n\\tself removeProperty: #undoGrabCommand.\\n\\tfullBounds _ nil! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 2/17/1999 17:50'!\\nreserveUrl: urlString\\n\\t\\\"Write a dummy object to the server to hold a name and place for this object.\\\"\\n\\n\\t| dummy ext str |\\n\\tdummy _ PasteUpMorph new.\\n\\tdummy borderWidth: 2.\\n\\tdummy setProperty: #initialExtent toValue: (ext _ 300@100).\\n\\tdummy topLeft: 50@50; extent: ext.\\t\\\"reset when comes in\\\"\\n\\tstr _ (TextMorph new) topLeft: dummy topLeft + (10@10); \\n\\t\\textent: dummy width - 15 @ 30.\\n\\tdummy addMorph: str.\\n\\tstr contents: 'This is a place holder only. Please \\\\find the original page and choose \\\\\\\"send this page to server\\\"' withCRs.\\n\\tstr extent: dummy width - 15 @ 30.\\n\\tdummy saveOnURL: urlString.\\n\\n\\t\\\"Claim that url myself\\\"\\n\\tself setProperty: #SqueakPage toValue: dummy sqkPage.\\n\\t(dummy sqkPage) contentsMorph: self; dirty: true.\\n\\t^ self url! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 08:52'!\\nsaveAsResource\\n\\n\\t| pathName |\\n\\t(self hasProperty: #resourceFilePath) ifFalse: [^ self].\\n\\tpathName _ self valueOfProperty: #resourceFilePath.\\n\\t(pathName asLowercase endsWith: '.morph') ifFalse:\\n\\t\\t[^ self error: 'Can only update morphic resources'].\\n\\t(FileStream newFileNamed: pathName) fileOutClass: nil andObject: self.! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'ar 9/27/2005 21:02'!\\nsaveDocPane\\n\\n\\tSmalltalk at: #DocLibrary ifPresent:[:dl| dl external saveDocCheck: self]! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'yo 7/2/2004 13:14'!\\nsaveOnFile\\n\\t\\\"Ask the user for a filename and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| aFileName fileStream ok |\\n\\taFileName _ ('my {1}' translated format: {self class name}) asFileName.\\t\\\"do better?\\\"\\n\\taFileName _ FillInTheBlank request: 'File name? (\\\".morph\\\" will be added to end)' translated \\n\\t\\t\\tinitialAnswer: aFileName.\\n\\taFileName isEmpty ifTrue: [^ Beeper beep].\\n\\tself allMorphsDo: [:m | m prepareToBeSaved].\\n\\n\\tok _ aFileName endsWith: '.morph'.\\t\\\"don't double them\\\"\\n\\tok _ ok | (aFileName endsWith: '.sp').\\n\\tok ifFalse: [aFileName _ aFileName,'.morph'].\\n\\tfileStream _ FileStream newFileNamed: aFileName asFileName.\\n\\tfileStream fileOutClass: nil andObject: self.\\t\\\"Puts UniClass definitions out anyway\\\"! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 7/16/1999 13:03'!\\nsaveOnURL\\n\\t\\\"Ask the user for a url and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| um pg |\\n\\t(pg _ self saveOnURLbasic) == #cancel ifTrue: [^ self].\\n\\tum _ URLMorph newForURL: pg url.\\n\\tum setURL: pg url page: pg.\\n\\tpg isContentsInMemory ifTrue: [pg computeThumbnail].\\n\\tum isBookmark: true.\\n\\tum removeAllMorphs.\\n\\tum color: Color transparent.\\n\\tself primaryHand attachMorph: um.! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'dgd 2/22/2003 14:35'!\\nsaveOnURLbasic\\n\\t\\\"Ask the user for a url and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| url pg stamp pol |\\n\\t(pg := self valueOfProperty: #SqueakPage) ifNil: [pg := SqueakPage new]\\n\\t\\tifNotNil: \\n\\t\\t\\t[pg contentsMorph ~~ self \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self inform: 'morph''s SqueakPage property is out of date'.\\n\\t\\t\\t\\t\\tpg := SqueakPage new]].\\n\\t(url := pg url) ifNil: \\n\\t\\t\\t[url := ServerDirectory defaultStemUrl , '1.sp'.\\t\\\"A new legal place\\\"\\n\\t\\t\\turl := FillInTheBlank \\n\\t\\t\\t\\t\\t\\trequest: 'url of a place to store this object.\\nMust begin with file:// or ftp://'\\n\\t\\t\\t\\t\\t\\tinitialAnswer: url.\\n\\t\\t\\turl isEmpty ifTrue: [^#cancel]].\\n\\tstamp := Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: self author: stamp.\\n\\tSqueakPageCache atURL: url put: pg.\\t\\\"setProperty: #SqueakPage\\\"\\n\\t(pol := pg policy) ifNil: [pol := #neverWrite].\\n\\tpg\\n\\t\\tpolicy: #now;\\n\\t\\tdirty: true.\\n\\tpg write.\\t\\\"force the write\\\"\\n\\tpg policy: pol.\\n\\t^pg! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'tk 11/20/1998 11:47'!\\nsaveOnURL: suggestedUrlString\\n\\t\\\"Save myself on a SmartReferenceStream file. If I don't already have a url, use the suggested one. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out.\\\"\\n\\n\\t| url pg stamp pol |\\n\\t(pg _ self valueOfProperty: #SqueakPage) ifNil: [pg _ SqueakPage new]\\n\\t\\tifNotNil: [pg contentsMorph ~~ self ifTrue: [\\n\\t\\t\\t\\tself inform: 'morph''s SqueakPage property is out of date'.\\n\\t\\t\\t\\tpg _ SqueakPage new]].\\n\\t(url _ pg url) ifNil: [url _ pg urlNoOverwrite: suggestedUrlString].\\n\\tstamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: self author: stamp.\\n\\tSqueakPageCache atURL: url put: pg.\\t\\\"setProperty: #SqueakPage\\\"\\n\\t(pol _ pg policy) ifNil: [pol _ #neverWrite].\\n\\tpg policy: #now; dirty: true. pg write.\\t\\\"force the write\\\"\\n\\tpg policy: pol.\\n\\t^ pg! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'di 11/18/1999 09:15'!\\nupdateAllFromResources\\n\\n\\tself allMorphsDo: [:m | m updateFromResource]! !\\n\\n!Morph methodsFor: 'fileIn/out' stamp: 'nk 1/6/2004 12:38'!\\nupdateFromResource\\n\\t| pathName newMorph f |\\n\\t(pathName := self valueOfProperty: #resourceFilePath) ifNil: [^self].\\n\\t(pathName asLowercase endsWith: '.morph') \\n\\t\\tifTrue: \\n\\t\\t\\t[newMorph := (FileStream readOnlyFileNamed: pathName) fileInObjectAndCode.\\n\\t\\t\\t(newMorph isMorph) \\n\\t\\t\\t\\tifFalse: [^self error: 'Resource not a single morph']]\\n\\t\\tifFalse: \\n\\t\\t\\t[f := Form fromFileNamed: pathName.\\n\\t\\t\\tf ifNil: [^self error: 'unrecognized image file format'].\\n\\t\\t\\tnewMorph := World drawingClass withForm: f].\\n\\tnewMorph setProperty: #resourceFilePath toValue: pathName.\\n\\tself owner replaceSubmorph: self by: newMorph! !\\n\\n\\n!Morph methodsFor: 'filter streaming' stamp: 'ar 10/26/2000 19:55'!\\ndrawOnCanvas: aCanvas\\n\\t^aCanvas fullDraw: self.\\n! !\\n\\n\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 7/24/97 11:55'!\\nalign: aPoint1 with: aPoint2\\n\\t\\\"Translate by aPoint2 - aPoint1.\\\"\\n\\n\\t^ self position: self position + (aPoint2 - aPoint1)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:17'!\\nbottom\\n\\t\\\" Return the y-coordinate of my bottom side \\\"\\n\\n\\t^ bounds bottom! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nbottomCenter\\n\\n\\t^ bounds bottomCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'tk 9/8/97 10:44'!\\nbottomLeft\\n\\n\\t^ bounds bottomLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:08'!\\nbottomLeft: aPoint\\n\\t\\\" Move me so that my bottom left corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x) @ (aPoint y - self height)).\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 6/12/97 11:17'!\\nbottomRight\\n\\n\\t^ bounds bottomRight! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:09'!\\nbottomRight: aPoint\\n\\t\\\" Move me so that my bottom right corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x - bounds width) @ (aPoint y - self height))\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:14'!\\nbottom: aNumber\\n\\t\\\" Move me so that my bottom is at the y-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (bounds left @ (aNumber - self height))! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'jm 8/3/97 15:50'!\\nbounds\\n\\t\\\"Return the bounds of this morph.\\\"\\n\\t\\\"Note: It is best not to override this method because many methods in Morph and its subclasses use the instance variable directly rather than 'self bounds'. Instead, subclasses should be sure that the bounds instance variable is correct.\\\"\\n\\n\\t^ bounds\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:05'!\\nboundsInWorld\\n\\t^self bounds: self bounds in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nboundsIn: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\t^self bounds: self bounds in: referenceMorph! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 12/14/2000 13:48'!\\nbounds: newBounds\\n\\t| oldExtent newExtent |\\n\\toldExtent _ self extent.\\n\\tnewExtent _ newBounds extent.\\n\\t(oldExtent dotProduct: oldExtent) <= (newExtent dotProduct: newExtent) ifTrue:[\\n\\t\\t\\\"We're growing. First move then resize.\\\"\\n\\t\\tself position: newBounds topLeft; extent: newExtent.\\n\\t] ifFalse:[\\n\\t\\t\\\"We're shrinking. First resize then move.\\\"\\n\\t\\tself extent: newExtent; position: newBounds topLeft.\\n\\t].! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nbounds: aRectangle from: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\towner ifNil: [^ aRectangle].\\n\\t^(owner transformFrom: referenceMorph) globalBoundsToLocal: aRectangle\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:04'!\\nbounds: aRectangle in: referenceMorph\\n\\t\\\"Return the receiver's bounds as seen by aMorphs coordinate frame\\\"\\n\\towner ifNil: [^ aRectangle].\\n\\t^(owner transformFrom: referenceMorph) localBoundsToGlobal: aRectangle\\n! !\\n\\n!Morph methodsFor: 'geometry'!\\ncenter\\n\\n\\t^ bounds center! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/11/1999 18:48'!\\ncenter: aPoint\\n\\tself position: (aPoint - (self extent // 2))! !\\n\\n!Morph methodsFor: 'geometry'!\\nextent\\n\\n\\t^ bounds extent! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'laza 3/25/2004 21:31'!\\nextent: aPoint\\n\\n\\tbounds extent = aPoint ifTrue: [^ self].\\n\\tself changed.\\n\\tbounds _ (bounds topLeft extent: aPoint) rounded.\\n\\tself layoutChanged.\\n\\tself changed.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:06'!\\nfullBoundsInWorld\\n\\t^self bounds: self fullBounds in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:06'!\\nglobalPointToLocal: aPoint\\n\\t^self point: aPoint from: nil! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 9/15/2000 14:21'!\\ngriddedPoint: ungriddedPoint\\n\\n\\t| griddingContext |\\n\\tself flag: #arNote. \\\"Used by event handling - should transform to pasteUp for gridding\\\"\\n\\t(griddingContext _ self pasteUpMorph) ifNil: [^ ungriddedPoint].\\n\\t^ griddingContext gridPoint: ungriddedPoint! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 8/25/2000 00:35'!\\ngridPoint: ungriddedPoint\\n\\n\\t^ ungriddedPoint! !\\n\\n!Morph methodsFor: 'geometry'!\\nheight\\n\\n\\t^ bounds height! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:22'!\\nheight: aNumber\\n\\t\\\" Set my height; my position (top-left corner) and width will remain the same \\\"\\n\\n\\tself extent: self width@aNumber asInteger.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 12/22/2001 22:43'!\\ninnerBounds\\n\\t\\\"Return the inner rectangle enclosed by the bounds of this morph excluding the space taken by its borders. For an unbordered morph, this is just its bounds.\\\"\\n\\n\\t^ self bounds insetBy: self borderWidth! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:16'!\\nleft\\n\\t\\\" Return the x-coordinate of my left side \\\"\\n\\n\\t^ bounds left! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nleftCenter\\n\\n\\t^ bounds leftCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:15'!\\nleft: aNumber\\n\\t\\\" Move me so that my left side is at the x-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (aNumber @ bounds top)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:07'!\\nlocalPointToGlobal: aPoint\\n\\t^self point: aPoint in: nil! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/4/2000 21:59'!\\nminimumExtent\\n\\t| ext |\\n\\t\\\"This returns the minimum extent that the morph may be shrunk to. Not honored in too many places yet, but respected by the resizeToFit feature, at least. copied up from SystemWindow 6/00\\\"\\n\\t(ext _ self valueOfProperty: #minimumExtent)\\n\\t\\tifNotNil:\\n\\t\\t\\t[^ ext].\\n\\t^ 100 @ 80! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 6/4/2000 22:00'!\\nminimumExtent: aPoint\\n\\t\\\"Remember a minimumExtent, for possible future use\\\"\\n\\n\\tself setProperty: #minimumExtent toValue: aPoint\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 7/10/1999 17:26'!\\nnextOwnerPage\\n\\t\\\"Tell my container to advance to the next page\\\"\\n\\t| targ |\\n\\ttarg _ self ownerThatIsA: BookMorph.\\n\\ttarg ifNotNil: [targ nextPage]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 11/12/2000 22:06'!\\nouterBounds\\n\\t\\\"Return the 'outer' bounds of the receiver, e.g., the bounds that need to be invalidated when the receiver changes.\\\"\\n\\t| box |\\n\\tbox _ self bounds.\\n\\tself hasDropShadow ifTrue:[box _ self expandFullBoundsForDropShadow: box].\\n\\tself hasRolloverBorder ifTrue:[box _ self expandFullBoundsForRolloverBorder: box].\\n\\t^box! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'nk 5/19/2003 20:39'!\\noverlapsShadowForm: itsShadow bounds: itsBounds\\n\\t\\\"Answer true if itsShadow and my shadow overlap at all\\\"\\n\\t| andForm overlapExtent |\\n\\toverlapExtent _ (itsBounds intersect: self fullBounds) extent.\\n\\toverlapExtent > (0 @ 0)\\n\\t\\tifFalse: [^ false].\\n\\tandForm _ self shadowForm.\\n\\toverlapExtent ~= self fullBounds extent\\n\\t\\tifTrue: [andForm _ andForm\\n\\t\\t\\t\\t\\t\\tcontentsOfArea: (0 @ 0 extent: overlapExtent)].\\n\\tandForm _ andForm\\n\\t\\t\\t\\tcopyBits: (self fullBounds translateBy: itsShadow offset negated)\\n\\t\\t\\t\\tfrom: itsShadow\\n\\t\\t\\t\\tat: 0 @ 0\\n\\t\\t\\t\\tclippingBox: (0 @ 0 extent: overlapExtent)\\n\\t\\t\\t\\trule: Form and\\n\\t\\t\\t\\tfillColor: nil.\\n\\t^ andForm bits\\n\\t\\tanySatisfy: [:w | w ~= 0]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:02'!\\npointFromWorld: aPoint\\n\\t^self point: aPoint from: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:03'!\\npointInWorld: aPoint\\n\\t^self point: aPoint in: self world! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:01'!\\npoint: aPoint from: aReferenceMorph\\n\\n\\towner ifNil: [^ aPoint].\\n\\t^ (owner transformFrom: aReferenceMorph) globalPointToLocal: aPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/25/2000 15:01'!\\npoint: aPoint in: aReferenceMorph\\n\\n\\towner ifNil: [^ aPoint].\\n\\t^ (owner transformFrom: aReferenceMorph) localPointToGlobal: aPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry'!\\nposition\\n\\n\\t^ bounds topLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 9/30/1998 12:11'!\\npositionInWorld\\n\\n\\t^ self pointInWorld: self position.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 10/9/1998 08:56'!\\npositionSubmorphs\\n\\tself submorphsDo:\\n\\t\\t[:aMorph | aMorph snapToEdgeIfAppropriate]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'wiz 11/25/2004 12:54'!\\nposition: aPoint \\n\\t\\\"Change the position of this morph and and all of its\\n\\tsubmorphs. \\\"\\n\\t| delta box |\\n\\tdelta := aPoint asNonFractionalPoint - bounds topLeft.\\n\\t(delta x = 0\\n\\t\\t\\tand: [delta y = 0])\\n\\t\\tifTrue: [^ self].\\n\\t\\\"Null change\\\"\\n\\tbox := self fullBounds.\\n\\t(delta dotProduct: delta)\\n\\t\\t\\t> 100\\n\\t\\tifTrue: [\\\"e.g., more than 10 pixels moved\\\"\\n\\t\\t\\tself invalidRect: box.\\n\\t\\t\\tself\\n\\t\\t\\t\\tinvalidRect: (box translateBy: delta)]\\n\\t\\tifFalse: [self\\n\\t\\t\\t\\tinvalidRect: (box\\n\\t\\t\\t\\t\\t\\tmerge: (box translateBy: delta))].\\n\\tself privateFullMoveBy: delta.\\n\\towner\\n\\t\\tifNotNil: [owner layoutChanged]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 7/10/1999 17:27'!\\npreviousOwnerPage\\n\\t\\\"Tell my container to advance to the previous page\\\"\\n\\t| targ |\\n\\ttarg _ self ownerThatIsA: BookMorph.\\n\\ttarg ifNotNil: [targ previousPage]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:16'!\\nright\\n\\t\\\" Return the x-coordinate of my right side \\\"\\n\\t^ bounds right! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\nrightCenter\\n\\n\\t^ bounds rightCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:15'!\\nright: aNumber\\n\\t\\\" Move me so that my right side is at the x-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aNumber - bounds width) @ bounds top)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'bf 1/5/2000 19:08'!\\nscreenLocation\\n\\t\\\"For compatibility only\\\"\\n\\n\\t^ self fullBounds origin! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sma 2/5/2000 13:58'!\\nscreenRectangle\\n\\t\\\"For compatibility only\\\"\\n\\n\\t^ self fullBounds! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'tk 7/14/2001 11:11'!\\nsetConstrainedPosition: aPoint hangOut: partiallyOutside\\n\\t\\\"Change the position of this morph and and all of its submorphs to aPoint, but don't let me go outside my owner's bounds. Let me go within two pixels of completely outside if partiallyOutside is true.\\\"\\n\\n\\t| trialRect delta boundingMorph bRect |\\n\\towner ifNil:[^self].\\n\\ttrialRect _ aPoint extent: self bounds extent.\\n\\tboundingMorph _ self topRendererOrSelf owner.\\n\\tdelta _ boundingMorph\\n\\t\\t\\tifNil: [0@0]\\n\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\tbRect _ partiallyOutside \\n\\t\\t\\t\\t\\tifTrue: [boundingMorph bounds insetBy: \\n\\t\\t\\t\\t\\t\\t\\t\\tself extent negated + boundingMorph borderWidth + (2@2)]\\n\\t\\t\\t\\t\\tifFalse: [boundingMorph bounds].\\n\\t\\t\\t\\ttrialRect amountToTranslateWithin: bRect].\\n\\tself position: aPoint + delta.\\n\\tself layoutChanged \\\"So that, eg, surrounding text will readjust\\\"\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 2/16/1999 22:05'!\\nshiftSubmorphsOtherThan: listNotToShift by: delta\\n\\t| rejectList |\\n\\trejectList _ listNotToShift ifNil: [OrderedCollection new].\\n\\t(submorphs copyWithoutAll: rejectList) do:\\n\\t\\t[:m | m position: (m position + delta)]! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:17'!\\ntop\\n\\t\\\" Return the y-coordinate of my top side \\\"\\n\\n\\t^ bounds top! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 3/6/2002 13:06'!\\ntopCenter\\n\\n\\t^ bounds topCenter! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 6/12/97 11:07'!\\ntopLeft\\n\\n\\t^ bounds topLeft! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:10'!\\ntopLeft: aPoint\\n\\t\\\" Move me so that my top left corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: aPoint\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'sw 8/20/97 23:04'!\\ntopRight\\n\\n\\t^ bounds topRight! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:12'!\\ntopRight: aPoint\\n\\t\\\" Move me so that my top right corner is at aPoint. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: ((aPoint x - bounds width) @ (aPoint y))\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:14'!\\ntop: aNumber\\n\\t\\\" Move me so that my top is at the y-coordinate aNumber. My extent (width & height) are unchanged \\\"\\n\\n\\tself position: (bounds left @ aNumber)! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'ar 10/22/2000 18:03'!\\ntransformedBy: aTransform\\n\\taTransform isIdentity ifTrue:[^self].\\n\\taTransform isPureTranslation ifTrue:[\\n\\t\\t^self position: (aTransform localPointToGlobal: self position).\\n\\t].\\n\\t^self addFlexShell transformedBy: aTransform! !\\n\\n!Morph methodsFor: 'geometry'!\\nwidth\\n\\n\\t^ bounds width! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'efc 2/13/2003 18:22'!\\nwidth: aNumber\\n\\t\\\" Set my width; my position (top-left corner) and height will remain the same \\\"\\n\\n\\tself extent: aNumber asInteger@self height.\\n! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'di 2/23/98 11:36'!\\nworldBounds\\n\\t^ self world bounds! !\\n\\n!Morph methodsFor: 'geometry' stamp: 'dgd 9/10/2004 12:37'!\\nworldBoundsForHalo\\n\\t\\\"Answer the rectangle to be used as the inner dimension of my halos.\\n\\tAllow for showing either bounds or fullBounds, and compensate for the optional bounds rectangle.\\\"\\n\\n\\t| r |\\n\\tr _ (Preferences haloEnclosesFullBounds)\\n\\t\\tifFalse: [ self boundsIn: nil ]\\n\\t\\tifTrue: [ self fullBoundsInWorld ].\\n\\tPreferences showBoundsInHalo ifTrue: [ ^r outsetBy: 2 ].\\n\\t^r! !\\n\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 12:00'!\\naddTransparentSpacerOfSize: aPoint\\n\\tself addMorphBack: (self transparentSpacerOfSize: aPoint)! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 12:01'!\\nbeTransparent\\n\\tself color: Color transparent! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'RAA 11/8/2000 18:29'!\\ncartesianBoundsTopLeft\\n\\t\\\"Answer the origin of this morph relative to it's container's cartesian origin. \\n\\tNOTE: y DECREASES toward the bottom of the screen\\\"\\n\\n\\t| w container |\\n\\n\\tw _ self world ifNil: [^ bounds origin].\\n\\tcontainer _ self referencePlayfield ifNil: [w].\\n\\t^ (bounds left - container cartesianOrigin x) @\\n\\t\\t(container cartesianOrigin y - bounds top)! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 1/17/2000 20:55'!\\ncartesianXY: coords\\n\\t^ self x: coords x y: coords y\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 9/9/1998 22:49'!\\ncolorUnder\\n\\t\\\"Return the color of under the receiver's center.\\\"\\n\\n\\tself isInWorld\\n\\t\\tifTrue: [^ self world colorAt: (self pointInWorld: self referencePosition) belowMorph: self]\\n\\t\\tifFalse: [^ Color black].\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 7/7/2003 17:18'!\\ncolor: sensitiveColor sees: soughtColor \\n\\t\\\"Return true if any of my pixels of sensitiveColor intersect with pixels of soughtColor.\\\"\\n\\n\\t\\\"Make a mask with black where sensitiveColor is, white elsewhere\\\"\\n\\n\\t| myImage sensitivePixelMask map patchBelowMe tfm morphAsFlexed i1 pasteUp |\\n\\tpasteUp _ self world ifNil: [ ^false ].\\n\\ttfm := self transformFrom: pasteUp.\\n\\tmorphAsFlexed := tfm isIdentity \\n\\t\\t\\t\\tifTrue: [self]\\n\\t\\t\\t\\tifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].\\n\\tmyImage := morphAsFlexed imageForm offset: 0 @ 0.\\n\\tsensitivePixelMask := Form extent: myImage extent depth: 1.\\n\\t\\\"ensure at most a 16-bit map\\\"\\n\\tmap := Bitmap new: (1 bitShift: (myImage depth - 1 min: 15)).\\n\\tmap at: (i1 := sensitiveColor indexInMap: map) put: 1.\\n\\tsensitivePixelMask \\n\\t\\tcopyBits: sensitivePixelMask boundingBox\\n\\t\\tfrom: myImage form\\n\\t\\tat: 0 @ 0\\n\\t\\tcolorMap: map.\\n\\n\\t\\\"get an image of the world below me\\\"\\n\\tpatchBelowMe := pasteUp \\n\\t\\t\\t\\tpatchAt: morphAsFlexed fullBounds\\n\\t\\t\\t\\twithout: self\\n\\t\\t\\t\\tandNothingAbove: false.\\n\\t\\\"\\nsensitivePixelMask displayAt: 0@0.\\npatchBelowMe displayAt: 100@0.\\n\\\"\\n\\t\\\"intersect world pixels of the color we're looking for with the sensitive pixels\\\"\\n\\tmap at: i1 put: 0.\\t\\\"clear map and reuse it\\\"\\n\\tmap at: (soughtColor indexInMap: map) put: 1.\\n\\tsensitivePixelMask \\n\\t\\tcopyBits: patchBelowMe boundingBox\\n\\t\\tfrom: patchBelowMe\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: patchBelowMe boundingBox\\n\\t\\trule: Form and\\n\\t\\tfillColor: nil\\n\\t\\tmap: map.\\n\\t\\\"\\nsensitivePixelMask displayAt: 200@0.\\n\\\"\\n\\t^(sensitivePixelMask tallyPixelValues second) > 0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 10/1/2000 11:54'!\\ndegreesOfFlex\\n\\t\\\"Return any rotation due to flexing\\\"\\n\\t\\\"NOTE: because renderedMorph, which is used by the halo to set heading, goes down through dropShadows as well as transformations, we need this method (and its other implems) to come back up through such a chain.\\\"\\n\\t^ 0.0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 14:29'!\\nforwardDirection: newDirection\\n\\t\\\"Set the receiver's forward direction (in eToy terms)\\\"\\n\\tself setProperty: #forwardDirection toValue: newDirection.! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 9/8/2000 16:35'!\\ngetIndexInOwner\\n\\t\\\"Answer which position the receiver holds in its owner's hierarchy\\\"\\n\\n\\t\\\"NB: There is some concern about submorphs that aren't really to be counted, such as a background morph of a playfield.\\\"\\n\\n\\t| container topRenderer |\\n\\tcontainer _ (topRenderer _ self topRendererOrSelf) owner.\\n\\t^ container submorphIndexOf: topRenderer.! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 9/20/2004 14:15'!\\ngoHome\\n\\t| box fb |\\n\\towner isInMemory ifFalse: [^ self].\\n\\towner isNil ifTrue: [^ self].\\n\\tself visible ifFalse: [^ self].\\n\\n\\tbox := owner visibleClearArea.\\n\\tfb := self fullBounds.\\n\\n\\tfb left < box left\\n\\t\\tifTrue: [self left: box left - fb left + self left].\\n\\tfb right > box right\\n\\t\\tifTrue: [self right: box right - fb right + self right].\\n\\n\\tfb top < box top\\n\\t\\tifTrue: [self top: box top - fb top + self top].\\n\\tfb bottom > box bottom\\n\\t\\tifTrue: [self bottom: box bottom - fb bottom + self bottom].\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'di 10/1/2000 11:50'!\\nheading\\n\\t\\\"Return the receiver's heading (in eToy terms)\\\"\\n\\towner ifNil: [^ self forwardDirection].\\n\\t^ self forwardDirection + owner degreesOfFlex! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 13:37'!\\nheading: newHeading\\n\\t\\\"Set the receiver's heading (in eToy terms)\\\"\\n\\tself isFlexed ifFalse:[self addFlexShell].\\n\\towner rotationDegrees: (newHeading - self forwardDirection).! !\\n\\n!Morph methodsFor: 'geometry eToy'!\\nmove: aMorph toPosition: aPointOrNumber\\n\\t\\\"Support for e-toy demo. Move the given submorph to the given position. Allows the morph's owner to determine the policy for motion. For example, moving forward through a table might mean motion only in the x-axis with wrapping modulo the table size.\\\"\\n\\n\\taMorph position: aPointOrNumber asPoint.\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:12'!\\nreferencePosition\\n\\t\\\"Return the current reference position of the receiver\\\"\\n\\t| box |\\n\\tbox _ self bounds.\\n\\t^box origin + (self rotationCenter * box extent).\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/25/1999 16:49'!\\nreferencePositionInWorld\\n\\n\\t^ self pointInWorld: self referencePosition\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/25/1999 23:33'!\\nreferencePositionInWorld: aPoint\\n\\t| localPosition |\\n\\tlocalPosition _ owner\\n\\t\\tifNil: [aPoint]\\n\\t\\tifNotNil: [(owner transformFrom: self world) globalPointToLocal: aPoint].\\n\\n\\tself referencePosition: localPosition\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/27/2000 14:04'!\\nreferencePosition: aPosition\\n\\t\\\"Move the receiver to match its reference position with aPosition\\\"\\n\\t| newPos intPos |\\n\\tnewPos _ self position + (aPosition - self referencePosition).\\n\\tintPos _ newPos asIntegerPoint.\\n\\tnewPos = intPos \\n\\t\\tifTrue:[self position: intPos]\\n\\t\\tifFalse:[self position: newPos].! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:10'!\\nrotationCenter\\n\\t\\\"Return the rotation center of the receiver. The rotation center defines the relative offset inside the receiver's bounds for locating the reference position.\\\"\\n\\t^self valueOfProperty: #rotationCenter ifAbsent:[0.5@0.5]\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 9/22/2000 20:11'!\\nrotationCenter: aPointOrNil\\n\\t\\\"Set the new rotation center of the receiver. The rotation center defines the relative offset inside the receiver's bounds for locating the reference position.\\\"\\n\\taPointOrNil isNil\\n\\t\\tifTrue:[self removeProperty: #rotationCenter]\\n\\t\\tifFalse:[self setProperty: #rotationCenter toValue: aPointOrNil]\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 9/4/2004 11:04'!\\nscaleFactor: newScale \\n\\t\\\"Backstop for morphs that don't have to do something special to set their \\n\\tscale \\\"\\n\\t| toBeScaled |\\n\\ttoBeScaled := self.\\n\\tnewScale = 1.0\\n\\t\\tifTrue: [(self heading isZero\\n\\t\\t\\t\\t\\tand: [self isFlexMorph])\\n\\t\\t\\t\\tifTrue: [toBeScaled := self removeFlexShell]]\\n\\t\\tifFalse: [self isFlexMorph\\n\\t\\t\\t\\tifFalse: [toBeScaled := self addFlexShellIfNecessary]].\\n\\n\\ttoBeScaled scale: newScale.\\n\\n\\ttoBeScaled == self ifTrue: [\\n\\t\\tnewScale = 1.0\\n\\t\\t\\tifTrue: [ self removeProperty: #scaleFactor ]\\n\\t\\t\\tifFalse: [ self setProperty: #scaleFactor toValue: newScale ]]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 9/4/2004 11:00'!\\nscale: newScale\\n\\t\\\"Backstop for morphs that don't have to do something special to set their scale\\\"\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'ar 6/12/2001 05:23'!\\nsetDirectionFrom: aPoint\\n\\t| delta degrees |\\n\\tdelta _ (self transformFromWorld globalPointToLocal: aPoint) - self referencePosition.\\n\\tdegrees _ delta degrees + 90.0.\\n\\tself forwardDirection: (degrees \\\\\\\\ 360) rounded.\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 8/31/2000 11:18'!\\nsetIndexInOwner: anInteger\\n\\t\\\"Answer which position the receiver holds in its owner's hierarchy\\\"\\n\\n\\t\\\"There is some concern about submorphs that aren't really to be counted, such as a background morph of a playfield.\\\"\\n\\t| container topRenderer indexToUse |\\n\\tcontainer _ (topRenderer _ self topRendererOrSelf) owner.\\n\\tindexToUse _ (anInteger min: container submorphCount) max: 1.\\n\\tcontainer addMorph: topRenderer asElementNumber: indexToUse! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'wiz 11/6/2005 17:10'!\\nsimplySetVisible: aBoolean\\n\\t\\\"Set the receiver's visibility property. This mild circumlocution is because my TransfomationMorph #visible: method would also set the visibility flag of my flexee, which in this case is pointless because it's the flexee that calls this.\\n\\tThis appears in morph as a backstop for morphs that don't inherit from TFMorph\\\"\\n\\n\\tself visible: aBoolean! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'nk 7/7/2003 17:19'!\\ntouchesColor: soughtColor \\n\\t\\\"Return true if any of my pixels overlap pixels of soughtColor.\\\"\\n\\n\\t\\\"Make a shadow mask with black in my shape, white elsewhere\\\"\\n\\n\\t| map patchBelowMe shadowForm tfm morphAsFlexed pasteUp |\\n\\tpasteUp := self world ifNil: [ ^false ].\\n\\n\\ttfm := self transformFrom: pasteUp.\\n\\tmorphAsFlexed := tfm isIdentity \\n\\t\\t\\t\\tifTrue: [self]\\n\\t\\t\\t\\tifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].\\n\\tshadowForm := morphAsFlexed shadowForm offset: 0 @ 0.\\n\\n\\t\\\"get an image of the world below me\\\"\\n\\tpatchBelowMe := (pasteUp \\n\\t\\t\\t\\tpatchAt: morphAsFlexed fullBounds\\n\\t\\t\\t\\twithout: self\\n\\t\\t\\t\\tandNothingAbove: false) offset: 0 @ 0.\\n\\t\\\"\\nshadowForm displayAt: 0@0.\\npatchBelowMe displayAt: 100@0.\\n\\\"\\n\\t\\\"intersect world pixels of the color we're looking for with our shape.\\\"\\n\\t\\\"ensure a maximum 16-bit map\\\"\\n\\tmap := Bitmap new: (1 bitShift: (patchBelowMe depth - 1 min: 15)).\\n\\tmap at: (soughtColor indexInMap: map) put: 1.\\n\\tshadowForm \\n\\t\\tcopyBits: patchBelowMe boundingBox\\n\\t\\tfrom: patchBelowMe\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: patchBelowMe boundingBox\\n\\t\\trule: Form and\\n\\t\\tfillColor: nil\\n\\t\\tmap: map.\\n\\t\\\"\\nshadowForm displayAt: 200@0.\\n\\\"\\n\\t^(shadowForm tallyPixelValues second) > 0! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 10/23/1998 11:50'!\\ntransparentSpacerOfSize: aPoint\\n\\t^ (Morph new extent: aPoint) color: Color transparent! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'tk 7/8/1998 23:47'!\\nwrap\\n\\n\\t| myBox box newX newY wrapped |\\n\\towner ifNil: [^ self].\\n\\tmyBox _ self fullBounds.\\n\\tmyBox corner < (50000@50000) ifFalse: [\\n\\t\\tself inform: 'Who is trying to wrap a hidden object?'. ^ self].\\n\\tbox _ owner bounds.\\n\\tnewX _ self position x.\\n\\tnewY _ self position y.\\n\\twrapped _ false.\\n\\t((myBox right < box left) or: [myBox left > box right]) ifTrue: [\\n\\t\\tnewX _ box left + ((self position x - box left) \\\\\\\\ box width).\\n\\t\\twrapped _ true].\\n\\t((myBox bottom < box top) or: [myBox top > box bottom]) ifTrue: [\\n\\t\\tnewY _ box top + ((self position y - box top) \\\\\\\\ box height).\\n\\t\\twrapped _ true].\\n\\tself position: newX@newY.\\n\\t(wrapped and: [owner isPlayfieldLike])\\n\\t\\tifTrue: [owner changed]. \\\"redraw all turtle trails if wrapped\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 2/22/2003 14:37'!\\nx\\n\\t\\\"Return my horizontal position relative to the cartesian origin of a relevant playfield\\\"\\n\\n\\t| aPlayfield |\\n\\taPlayfield := self referencePlayfield.\\n\\t^aPlayfield isNil \\n\\t\\tifTrue: [self referencePosition x]\\n\\t\\tifFalse: [self referencePosition x - aPlayfield cartesianOrigin x]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'aoy 2/17/2003 01:00'!\\nx: aNumber \\n\\t\\\"Set my horizontal position relative to the cartesian origin of the playfield or the world.\\\"\\n\\n\\t| offset aPlayfield newX |\\n\\taPlayfield := self referencePlayfield.\\n\\toffset := self left - self referencePosition x.\\n\\tnewX := aPlayfield isNil\\n\\t\\t\\t\\tifTrue: [aNumber + offset]\\n\\t\\t\\t\\tifFalse: [aPlayfield cartesianOrigin x + aNumber + offset].\\n\\tself position: newX @ bounds top! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'sw 1/17/2000 20:04'!\\nx: xCoord y: yCoord\\n\\t| aWorld xyOffset delta aPlayfield |\\n\\t(aWorld _ self world) ifNil: [^ self position: xCoord @ yCoord].\\n\\txyOffset _ self topLeft - self referencePosition.\\n\\tdelta _ (aPlayfield _ self referencePlayfield)\\n\\t\\tifNil:\\n\\t\\t\\t[xCoord @ (aWorld bottom - yCoord)]\\n\\t\\tifNotNil:\\n\\t\\t\\t[aPlayfield cartesianOrigin + (xCoord @ (yCoord negated))].\\n\\tself position: (xyOffset + delta)\\n! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'dgd 2/22/2003 14:37'!\\ny\\n\\t\\\"Return my vertical position relative to the cartesian origin of the playfield or the world. Note that larger y values are closer to the top of the screen.\\\"\\n\\n\\t| w aPlayfield |\\n\\tw := self world.\\n\\tw ifNil: [^bounds top].\\n\\taPlayfield := self referencePlayfield.\\n\\t^aPlayfield isNil \\n\\t\\tifTrue: [w cartesianOrigin y - self referencePosition y]\\n\\t\\tifFalse: [aPlayfield cartesianOrigin y - self referencePosition y]! !\\n\\n!Morph methodsFor: 'geometry eToy' stamp: 'aoy 2/17/2003 01:00'!\\ny: aNumber \\n\\t\\\"Set my vertical position relative to the cartesian origin of the playfield or the world. Note that larger y values are closer to the top of the screen.\\\"\\n\\n\\t| w offset newY aPlayfield |\\n\\tw := self world.\\n\\tw ifNil: [^self position: bounds left @ aNumber].\\n\\taPlayfield := self referencePlayfield.\\n\\toffset := self top - self referencePosition y.\\n\\tnewY := aPlayfield isNil\\n\\t\\t\\t\\tifTrue: [w bottom - aNumber + offset]\\n\\t\\t\\t\\tifFalse: [aPlayfield cartesianOrigin y - aNumber + offset].\\n\\tself position: bounds left @ newY! !\\n\\n\\n!Morph methodsFor: 'geometry testing'!\\ncontainsPoint: aPoint\\n\\n\\t^ self bounds containsPoint: aPoint! !\\n\\n!Morph methodsFor: 'geometry testing' stamp: 'di 5/3/2000 19:05'!\\nfullContainsPoint: aPoint\\n\\n\\t(self fullBounds containsPoint: aPoint) ifFalse: [^ false]. \\\"quick elimination\\\"\\n\\t(self containsPoint: aPoint) ifTrue: [^ true]. \\\"quick acceptance\\\"\\n\\tsubmorphs do: [:m | (m fullContainsPoint: aPoint) ifTrue: [^ true]].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'geometry testing' stamp: 'dgd 2/22/2003 14:33'!\\nobtrudesBeyondContainer\\n\\t\\\"Answer whether the receiver obtrudes beyond the bounds of its container\\\"\\n\\n\\t| top |\\n\\ttop := self topRendererOrSelf.\\n\\t(top owner isNil or: [top owner isHandMorph]) ifTrue: [^false].\\n\\t^(top owner bounds containsRect: top bounds) not! !\\n\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/7/1999 18:57'!\\naddHalo\\n\\t\\\"Invoke a halo programatically (e.g., not from a meta gesture)\\\"\\n\\t^self addHalo: nil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/10/2000 19:03'!\\naddHalo: evt\\n\\t| halo prospectiveHaloClass |\\n\\tprospectiveHaloClass _ Smalltalk at: self haloClass ifAbsent: [HaloMorph].\\n\\thalo _ prospectiveHaloClass new bounds: self worldBoundsForHalo.\\n\\thalo popUpFor: self event: evt.\\n\\t^halo! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/7/1999 21:55'!\\naddHalo: evt from: formerHaloOwner\\n\\t\\\"Transfer a halo from the former halo owner to the receiver\\\"\\n\\t^self addHalo: evt! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/30/2004 02:53'!\\naddHandlesTo: aHaloMorph box: box\\n\\t\\\"Add halo handles to the halo. Apply the halo filter if appropriate\\\"\\n\\n\\t| wantsIt aSelector |\\n\\taHaloMorph haloBox: box.\\n\\tPreferences haloSpecifications do:\\n\\t\\t[:aSpec | \\n\\t\\t\\taSelector _ aSpec addHandleSelector.\\n\\t\\t\\twantsIt _ Preferences selectiveHalos\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[self wantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[true].\\n\\t\\t\\twantsIt ifTrue:\\n\\t\\t\\t\\t[(#(addMakeSiblingHandle: addDupHandle:) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t[wantsIt _ self preferredDuplicationHandleSelector = aSelector].\\n\\t\\t\\twantsIt ifTrue:\\n\\t\\t\\t\\t[aHaloMorph perform: aSelector with: aSpec]]].\\n\\n\\taHaloMorph innerTarget addOptionalHandlesTo: aHaloMorph box: box! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 8/8/2001 17:31'!\\naddMagicHaloFor: aHand\\n\\t| halo prospectiveHaloClass |\\n\\taHand halo ifNotNil:[\\n\\t\\taHand halo target == self ifTrue:[^self].\\n\\t\\taHand halo isMagicHalo ifFalse:[^self]].\\n\\tprospectiveHaloClass _ Smalltalk at: self haloClass ifAbsent: [HaloMorph].\\n\\thalo _ prospectiveHaloClass new bounds: self worldBoundsForHalo.\\n\\thalo popUpMagicallyFor: self hand: aHand.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/22/2000 20:41'!\\naddOptionalHandlesTo: aHalo box: box\\n\\taHalo addDirectionHandles! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/21/1999 17:52'!\\naddSimpleHandlesTo: aHaloMorph box: aBox\\n\\t^ aHaloMorph addSimpleHandlesTo: aHaloMorph box: aBox! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/26/2000 19:37'!\\naddWorldHandlesTo: aHaloMorph box: box\\n\\taHaloMorph haloBox: box.\\n\\tPreferences haloSpecificationsForWorld do:\\n\\t\\t[:aSpec | \\n\\t\\t\\taHaloMorph perform: aSpec addHandleSelector with: aSpec].\\n\\taHaloMorph innerTarget addOptionalHandlesTo: aHaloMorph box: box! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 14:54'!\\nballoonColor\\n\\t^ self\\n\\t\\tvalueOfProperty: #balloonColor\\n\\t\\tifAbsent: [self defaultBalloonColor]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 14:55'!\\nballoonColor: aColor\\n\\t^ self\\n\\t\\tsetProperty: #balloonColor\\n\\t\\ttoValue: aColor! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:29'!\\nballoonFont\\n\\t^ self\\n\\t\\tvalueOfProperty: #balloonFont\\n\\t\\tifAbsent: [self defaultBalloonFont]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:30'!\\nballoonFont: aFont \\n\\t^ self setProperty: #balloonFont toValue: aFont! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 2/7/2000 11:27'!\\nballoonHelpAligner\\n\\t\\\"Answer the morph to which the receiver's balloon help should point\\\"\\n\\t^ (self valueOfProperty: #balloonTarget) ifNil: [self]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/7/2004 18:35'!\\nballoonHelpDelayTime\\n\\t\\\"Return the number of milliseconds before a balloon help should be put up on the receiver. The balloon help will only be put up if the receiver responds to #wantsBalloon by returning true.\\\"\\n\\t^ Preferences balloonHelpDelayTime! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 4/3/2006 14:15'!\\nballoonHelpTextForHandle: aHandle\\n\\t\\\"Answer a string providing balloon help for the given halo handle\\\"\\n\\n\\t| itsSelector |\\n\\titsSelector _ aHandle eventHandler firstMouseSelector.\\n\\n\\t(itsSelector == #doRecolor:with:) ifTrue:\\n\\t\\t[^ Preferences propertySheetFromHalo\\n\\t\\t\\tifTrue: ['Open a property sheet.']\\n\\t\\t\\tifFalse: ['Change color']].\\n\\n\\t(itsSelector == #mouseDownInDimissHandle:with:) ifTrue:\\n\\t\\t[^ Preferences preserveTrash\\n\\t\\t\\tifTrue: ['Move to trash']\\n\\t\\t\\tifFalse: ['Remove from screen']].\\n\\n\\t#(\\t(addFullHandles\\t\\t\\t\\t\\t\\t\\t'More halo handles')\\n\\t\\t(addSimpleHandles\\t\\t\\t\\t\\t\\t'Fewer halo handles')\\n\\t\\t(chooseEmphasisOrAlignment\\t\\t\\t\\t'Emphasis & alignment')\\n\\t\\t(chooseFont\\t\\t\\t\\t\\t\\t\\t\\t'Change font')\\n\\t\\t(chooseNewGraphicFromHalo\\t\\t\\t\\t'Choose a new graphic')\\n\\t\\t(chooseStyle\\t\\t\\t\\t\\t\\t\\t\\t'Change style')\\n\\t\\t(dismiss\\t\\t\\t\\t\\t\\t\\t\\t\\t'Remove')\\n\\t\\t(doDebug:with:\\t\\t\\t\\t\\t\\t\\t'Debug')\\n\\t\\t(doDirection:with:\\t\\t\\t\\t\\t\\t'Choose forward direction')\\n\\t\\t(doDup:with:\\t\\t\\t\\t\\t\\t\\t'Duplicate')\\n\\t\\t(doMakeSibling:with: \\t\\t\\t\\t\\t'Make a sibling')\\n\\t\\t(doMenu:with:\\t\\t\\t\\t\\t\\t\\t'Menu')\\n\\t\\t(doGrab:with:\\t\\t\\t\\t\\t\\t\\t'Pick up')\\n\\t\\t(editButtonsScript\\t\\t\\t\\t\\t\\t'See the script for this button')\\n\\t\\t(editDrawing\\t\\t\\t\\t\\t\\t\\t'Repaint')\\n\\t\\t(maybeDoDup:with:\\t\\t\\t\\t\\t\\t'Duplicate')\\n\\t\\t(makeNascentScript\\t\\t\\t\\t\\t\\t'Make a scratch script')\\n\\t\\t(makeNewDrawingWithin\\t\\t\\t\\t'Paint new object')\\n\\t\\t(mouseDownInCollapseHandle:with:\\t\\t'Collapse')\\n\\t\\t(mouseDownOnHelpHandle:\\t\\t\\t\\t'Help')\\n\\t\\t(openViewerForArgument\\t\\t\\t\\t'Open a Viewer for me. Press shift for a snapshot.')\\n\\t\\t(openViewerForTarget:with:\\t\\t\\t\\t'Open a Viewer for me. Press shift for a snapshot.')\\n\\t\\t(paintBackground\\t\\t\\t\\t\\t\\t'Paint background')\\n\\t\\t(prepareToTrackCenterOfRotation:with:\\t'Move object or set center of rotation')\\n\\t\\t(presentViewMenu\\t\\t\\t\\t\\t\\t'Present the Viewing menu')\\n\\t\\t(startDrag:with:\\t\\t\\t\\t\\t\\t\\t'Move')\\n\\t\\t(startGrow:with:\\t\\t\\t\\t\\t\\t\\t'Change size') \\n\\t\\t(startRot:with:\\t\\t\\t\\t\\t\\t\\t'Rotate')\\n\\t\\t(startScale:with:\\t\\t\\t\\t\\t\\t\\t'Change scale') \\n\\t\\t(tearOffTile\\t\\t\\t\\t\\t\\t\\t\\t'Make a tile representing this object')\\n\\t\\t(tearOffTileForTarget:with:\\t\\t\\t\\t'Make a tile representing this object')\\n\\t\\t(trackCenterOfRotation:with:\\t\\t\\t\\t'Set center of rotation')\\n\\t) \\n\\tdo:\\n\\t\\t[:pair | itsSelector == pair first ifTrue: [^ pair last]].\\n\\n\\t^ 'unknown halo handle'! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'RAA 7/21/2000 11:10'!\\nboundsForBalloon\\n\\n\\t\\\"some morphs have bounds that are way too big\\\"\\n\\t^self boundsInWorld! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 3/1/2000 11:39'!\\ncomeToFrontAndAddHalo\\n\\tself comeToFront.\\n\\tself addHalo! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 11/11/2000 16:15'!\\ndefaultBalloonColor\\n\\t^ Display depth <= 2\\n\\t\\tifTrue: [Color white]\\n\\t\\tifFalse: [BalloonMorph balloonColor]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sd 12/5/2001 20:23'!\\ndefaultBalloonFont\\n\\t^ BalloonMorph balloonFont! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/11/2000 18:24'!\\ndefersHaloOnClickTo: aSubMorph\\n\\t\\\"If a cmd-click on aSubMorph would make it a preferred recipient of the halo, answer true\\\"\\n\\t\\\"May want to add a way (via a property) for morphs to assert true here -- this would let certain kinds of morphs that are unusually reluctant to take the halo on initial click\\\"\\n\\n\\t^ false\\n\\t! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:03'!\\ndeleteBalloon\\n\\t\\\"If I am showing a balloon, delete it.\\\"\\n\\t| w |\\n\\tw _ self world ifNil:[^self].\\n\\tw deleteBalloonTarget: self.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'em 3/24/2005 10:02'!\\neditBalloonHelpContent: aString\\n\\t| reply |\\n\\treply _ FillInTheBlank\\n\\t\\tmultiLineRequest: 'Edit the balloon help text for ' translated, self externalName\\n\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\tinitialAnswer: (aString ifNil: [self noHelpString] ifNotNil: [aString])\\n\\t\\tanswerHeight: 200.\\n\\treply ifNil: [^ self]. \\\"User cancelled out of the dialog\\\"\\n\\t(reply isEmpty or: [reply asString = self noHelpString])\\n\\t\\tifTrue: [self setBalloonText: nil]\\n\\t\\tifFalse: [self setBalloonText: reply]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 12/23/1999 13:24'!\\neditBalloonHelpText\\n\\t\\\"Modify the receiver's balloon help text.\\\"\\n\\n\\tself editBalloonHelpContent: self balloonText! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 3/17/2001 13:19'!\\nhalo\\n\\n\\t(self outermostWorldMorph ifNil: [^nil]) haloMorphs do: [:h | h target == self ifTrue: [^ h]].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/15/2000 16:13'!\\nhaloClass\\n\\t\\\"Answer the name of the desired kind of HaloMorph to launch on behalf of the receiver\\\"\\n\\n\\t^ #HaloMorph\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 8/8/2001 15:40'!\\nhaloDelayTime\\n\\t\\\"Return the number of milliseconds before a halo should be put up on the receiver. The halo will only be put up if the receiver responds to #wantsHalo by returning true.\\\"\\n\\t^800! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/15/2000 16:16'!\\nhasHalo\\n\\t^self hasProperty: #hasHalo.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 9/28/2000 17:54'!\\nhasHalo: aBool\\n\\taBool\\n\\t\\tifTrue:[self setProperty: #hasHalo toValue: true]\\n\\t\\tifFalse:[self removeProperty: #hasHalo]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 2/22/2003 19:05'!\\nisLikelyRecipientForMouseOverHalos\\n\\t^self player notNil! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:05'!\\nmouseDownOnHelpHandle: anEvent\\n\\t\\\"The mouse went down in the show-balloon handle\\\"\\n\\t\\n\\t| str |\\n\\tanEvent shiftPressed ifTrue: [^ self editBalloonHelpText].\\n\\tstr _ self balloonText.\\n\\tstr ifNil: [str _ self noHelpString].\\n\\tself showBalloon: str hand: anEvent hand.\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'em 3/24/2005 10:05'!\\nnoHelpString\\n\\t^ 'Help not yet supplied' translated! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/15/2001 12:23'!\\nokayToAddDismissHandle\\n\\t\\\"Answer whether a halo on the receiver should offer a dismiss handle. This provides a hook for making it harder to disassemble some strucures even momentarily\\\"\\n\\n\\t^ self holdsSeparateDataForEachInstance not and:\\n\\t\\t[self resistsRemoval not]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/26/2000 12:11'!\\nokayToAddGrabHandle\\n\\t\\\"Answer whether a halo on the receiver should offer a grab handle. This provides a hook for making it harder to deconstruct some strucures even momentarily\\\"\\n\\n\\t^ self holdsSeparateDataForEachInstance not ! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:50'!\\nokayToBrownDragEasily\\n\\t\\\"Answer whether it it okay for the receiver to be brown-dragged easily -- i.e. repositioned within its container without extracting it. At present this is just a hook -- nobody declines.\\\"\\n\\n\\t^ true\\n\\n\\n\\n\\\"\\n\\t^ (self topRendererOrSelf owner isKindOf: PasteUpMorph) and:\\n\\t\\t[self layoutPolicy isNil]\\\"! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 15:02'!\\nokayToExtractEasily\\n\\t\\\"Answer whether it it okay for the receiver to be extracted easily. Not yet hooked up to the halo-permissions mechanism.\\\"\\n\\n\\t^ self topRendererOrSelf owner dragNDropEnabled! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/29/2001 06:29'!\\nokayToResizeEasily\\n\\t\\\"Answer whether it is appropriate to have the receiver be easily resized by the user from the halo\\\"\\n\\n\\t^ true\\n\\n\\t\\\"This one was too jarring, not that it didn't most of the time do the right thing but because some of the time it didn't, such as in a holder. If we pursue this path, the test needs to be airtight, obviously...\\n\\t^ (self topRendererOrSelf owner isKindOf: PasteUpMorph) and:\\n\\t\\t[self layoutPolicy isNil]\\\"! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:44'!\\nokayToRotateEasily\\n\\t\\\"Answer whether it is appropriate for a rotation handle to be shown for the receiver. This is a hook -- at present nobody declines.\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 12/31/2004 03:30'!\\npreferredDuplicationHandleSelector\\n\\t\\\"Answer the selector, either #addMakeSiblingHandle: or addDupHandle:, to be offered as the default in a halo open on me\\\"\\n\\n\\tPreferences oliveHandleForScriptedObjects ifFalse:\\n\\t\\t[^ #addDupHandle:].\\n\\t^ self renderedMorph valueOfProperty: #preferredDuplicationHandleSelector ifAbsent:\\n\\t\\t[self player class isUniClass\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[#addMakeSiblingHandle:]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[#addDupHandle:]]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/9/2004 22:43'!\\nremoveHalo\\n\\t\\\"remove the surrounding halo (if any)\\\"\\n\\tself halo isNil\\n\\t\\tifFalse: [self primaryHand removeHalo]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sma 12/23/1999 13:32'!\\nsetBalloonText: stringOrText\\n\\t\\\"Set receiver's balloon help text. Pass nil to remove the help.\\\"\\n\\n\\tself setBalloonText: stringOrText maxLineLength: Preferences maxBalloonHelpLineLength! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'md 2/27/2006 09:54'!\\nsetBalloonText: stringOrText maxLineLength: aLength \\n\\t\\\"Set receiver's balloon help text. Pass nil to remove the help.\\\"\\n\\t(extension isNil and: [stringOrText isNil]) ifTrue: [^ self].\\n\\tself assureExtension balloonText: \\n\\t\\t(stringOrText ifNotNil: [stringOrText asString withNoLineLongerThan: aLength])! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/29/1999 17:38'!\\nsetCenteredBalloonText: aString\\n\\tself setBalloonText: aString.\\n\\tself setProperty: #helpAtCenter toValue: true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 10/3/2000 17:06'!\\nshowBalloon: msgString\\n\\t\\\"Pop up a balloon containing the given string,\\n\\tfirst removing any existing BalloonMorphs in the world.\\\"\\n\\t| w |\\n\\tself showBalloon: msgString hand: ((w _ self world) ifNotNil:[w activeHand]).! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'bf 11/1/2000 15:58'!\\nshowBalloon: msgString hand: aHand\\n\\t\\\"Pop up a balloon containing the given string,\\n\\tfirst removing any existing BalloonMorphs in the world.\\\"\\n\\n\\t| w balloon h |\\n\\t(w _ self world) ifNil: [^ self].\\n\\th _ aHand.\\n\\th ifNil:[\\n\\t\\th _ w activeHand].\\n\\tballoon _ BalloonMorph string: msgString for: self balloonHelpAligner.\\n\\tballoon popUpFor: self hand: h.! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 9/10/2004 13:59'!\\ntransferHalo: event from: formerHaloOwner\\n\\t\\\"Progressively transfer the halo to the next likely recipient\\\"\\n\\t| localEvt w target |\\n\\n\\tself flag: #workAround. \\\"For halo's distinction between 'target' and 'innerTarget' we need to bypass any renderers.\\\"\\n\\t(formerHaloOwner == self and:[self isRenderer and:[self wantsHaloFromClick not]]) ifTrue:[\\n\\t\\tevent shiftPressed ifTrue:[\\n\\t\\t\\ttarget _ owner.\\n\\t\\t\\tlocalEvt _ event transformedBy: (self transformedFrom: owner).\\n\\t\\t] ifFalse:[\\n\\t\\t\\ttarget _ self renderedMorph.\\n\\t\\t\\tlocalEvt _ event transformedBy: (target transformedFrom: self).\\n\\t\\t].\\n\\t\\t^target transferHalo: localEvt from: target].\\n\\n\\\"\\tformerHaloOwner == self ifTrue:[^ self removeHalo].\\\"\\n\\n\\t\\\"Never transfer halo to top-most world\\\"\\n\\t(self isWorldMorph and:[owner isNil]) ifFalse:[\\n\\t\\t(self wantsHaloFromClick and:[formerHaloOwner ~~ self]) \\n\\t\\t\\tifTrue:[^self addHalo: event from: formerHaloOwner]].\\n\\n\\tevent shiftPressed ifTrue:[\\n\\t\\t\\\"Pass it outwards\\\"\\n\\t\\towner ifNotNil:[^owner transferHalo: event from: formerHaloOwner].\\n\\t\\t\\\"We're at the top level; throw the event back in to find recipient\\\"\\n\\t\\tformerHaloOwner removeHalo.\\n\\t\\t^self processEvent: event copy resetHandlerFields.\\n\\t].\\n\\tself submorphsDo:[:m|\\n\\t\\tlocalEvt _ event transformedBy: (m transformedFrom: self).\\n\\t\\t(m fullContainsPoint: localEvt position) \\n\\t\\t\\tifTrue:[^m transferHalo: event from: formerHaloOwner].\\n\\t].\\n\\t\\\"We're at the bottom most level; throw the event back up to the root to find recipient\\\"\\n\\tformerHaloOwner removeHalo.\\n\\n\\tPreferences maintainHalos ifFalse:[\\n\\t\\t(w _ self world) ifNil: [ ^self ].\\n\\t\\tlocalEvt _ event transformedBy: (self transformedFrom: w) inverseTransformation.\\n\\t\\t^w processEvent: localEvt resetHandlerFields.\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'rhi 10/5/2001 20:49'!\\nwantsBalloon\\n\\t\\\"Answer true if receiver wants to show a balloon help text is a few moments.\\\"\\n\\n\\t^ (self balloonText notNil) and: [Preferences balloonHelpEnabled]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/29/2001 19:50'!\\nwantsDirectionHandles\\n\\t^self valueOfProperty: #wantsDirectionHandles ifAbsent:[Preferences showDirectionHandles]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'ar 11/29/2001 19:52'!\\nwantsDirectionHandles: aBool\\n\\taBool == Preferences showDirectionHandles\\n\\t\\tifTrue:[self removeProperty: #wantsDirectionHandles]\\n\\t\\tifFalse:[self setProperty: #wantsDirectionHandles toValue: aBool].\\n! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'dgd 2/22/2003 19:06'!\\nwantsHalo\\n\\t| topOwner |\\n\\t^(topOwner := self topRendererOrSelf owner) notNil \\n\\t\\tand: [topOwner wantsHaloFor: self]! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 4/8/98 13:26'!\\nwantsHaloFor: aSubMorph\\n\\t^ false! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 1/25/2000 17:43'!\\nwantsHaloFromClick\\n\\t^ true! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 11/27/2001 14:49'!\\nwantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph\\n\\t\\\"Answer whether the receiver would like to offer the halo handle with the given selector (e.g. #addCollapseHandle:)\\\"\\n\\n\\t(#(addDismissHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self resistsRemoval not].\\n\\n\\t(#( addDragHandle: ) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToBrownDragEasily].\\n\\n\\t(#(addGrowHandle: addScaleHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToResizeEasily].\\n\\n\\t(#( addRotateHandle: ) includes: aSelector) ifTrue:\\n\\t\\t[^ self okayToRotateEasily].\\n\\n\\t(#(addRecolorHandle:) includes: aSelector) ifTrue:\\n\\t\\t[^ self renderedMorph wantsRecolorHandle].\\n\\n\\ttrue ifTrue: [^ true]\\n\\t! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'sw 10/9/2000 16:56'!\\nwantsScriptorHaloHandle\\n\\t\\\"Answer whether the receiver would like to have a Scriptor halo handle put up on its behalf. Initially, only the ScriptableButton says yes\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'halos and balloon help' stamp: 'nk 6/12/2004 09:32'!\\nwantsSimpleSketchMorphHandles\\n\\t\\\"Answer true if my halo's simple handles should include the simple sketch morph handles.\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:00'!\\nbasicInitialize\\n\\t\\\"Do basic generic initialization of the instance variables: \\n\\tSet up the receiver, created by a #basicNew and now ready to \\n\\tbe initialized, by placing initial values in the instance variables \\n\\tas appropriate\\\"\\nowner _ nil.\\n\\tsubmorphs _ EmptyArray.\\n\\tbounds _ self defaultBounds.\\n\\t\\n\\tcolor _ self defaultColor! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:06'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 50 @ 40! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color blue! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'fbs 1/5/2005 09:17'!\\ninAScrollPane\\n\\t\\\"Answer a scroll pane that allows the user to scroll the receiver in either direction. It will have permanent scroll bars unless you take some special action.\\\"\\n\\n\\t| widget |\\n\\twidget _ ScrollPane new.\\n\\twidget extent: ((self width min: 300 max: 100) @ (self height min: 150 max: 100));\\n\\t\\tborderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget color: self color darker darker.\\n\\t^ widget! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 6/26/2001 10:56'!\\ninATwoWayScrollPane\\n\\t\\\"Answer a two-way scroll pane that allows the user to scroll the receiver in either direction. It will have permanent scroll bars unless you take some special action.\\\"\\n\\n\\t| widget |\\n\\twidget _ TwoWayScrollPane new.\\n\\twidget extent: ((self width min: 300 max: 100) @ (self height min: 150 max: 100));\\n\\t\\tborderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget color: self color darker darker.\\n\\t^ widget! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 17:30'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\nowner _ nil.\\n\\tsubmorphs _ EmptyArray.\\n\\tbounds _ self defaultBounds.\\n\\t\\n\\tcolor _ self defaultColor! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 1/31/2001 13:57'!\\nintoWorld: aWorld\\n\\t\\\"The receiver has just appeared in a new world. Note:\\n\\t\\t* aWorld can be nil (due to optimizations in other places)\\n\\t\\t* owner is already set\\n\\t\\t* owner's submorphs may not include receiver yet.\\n\\tImportant: Keep this method fast - it is run whenever morphs are added.\\\"\\n\\taWorld ifNil:[^self].\\n\\tself wantsSteps ifTrue:[aWorld startStepping: self].\\n\\tself submorphsDo:[:m| m intoWorld: aWorld].\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 10/18/2000 12:33'!\\nopenCenteredInWorld\\n\\n\\tself \\n\\t\\tfullBounds;\\n\\t\\tposition: Display extent - self extent // 2;\\n\\t\\topenInWorld.! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 3/21/2000 14:46'!\\nopenInHand\\n\\t\\\"Attach the receiver to the current hand in the current morphic world\\\"\\n\\n\\tself currentHand attachMorph: self! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'jm 7/5/1998 12:40'!\\nopenInMVC\\n\\n\\tMorphWorldView\\n\\t\\topenWorldWith: self\\n\\t\\tlabelled: self defaultLabelForInspector.\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'djp 10/24/1999 17:13'!\\nopenInWindow\\n\\n\\t^self openInWindowLabeled: self defaultLabelForInspector\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sma 4/22/2000 20:28'!\\nopenInWindowLabeled: aString\\n\\n\\t^self openInWindowLabeled: aString inWorld: self currentWorld! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 5/25/2000 08:12'!\\nopenInWindowLabeled: aString inWorld: aWorld\\n\\n\\t| window extent |\\n\\n\\twindow _ (SystemWindow labelled: aString) model: nil.\\n\\twindow \\n\\t\\t\\\" guess at initial extent\\\"\\n\\t\\tbounds: (RealEstateAgent initialFrameFor: window initialExtent: self fullBounds extent world: aWorld);\\n\\t\\taddMorph: self frame: (0@0 extent: 1@1);\\n\\t\\tupdatePaneColors.\\n\\t\\\" calculate extent after adding in case any size related attributes were changed. Use\\n\\tfullBounds in order to trigger re-layout of layout morphs\\\"\\n\\textent _ self fullBounds extent + \\n\\t\\t\\t(window borderWidth@window labelHeight) + window borderWidth.\\n\\twindow extent: extent.\\n\\taWorld addMorph: window.\\n\\twindow activate.\\n\\taWorld startSteppingSubmorphsOf: window.\\n\\t^window\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'RAA 6/14/2000 18:09'!\\nopenInWorld\\n \\\"Add this morph to the world. If in MVC, then provide a Morphic window for it.\\\"\\n\\n self couldOpenInMorphic\\n ifTrue: [self openInWorld: self currentWorld]\\n ifFalse: [self openInMVC]! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'dgd 9/1/2004 16:12'!\\nopenInWorld: aWorld\\n\\t\\\"Add this morph to the requested World.\\\"\\n\\t(aWorld visibleClearArea origin ~= (0@0) and: [self position = (0@0)]) ifTrue:\\n\\t\\t[self position: aWorld visibleClearArea origin].\\n\\taWorld addMorph: self.\\n\\taWorld startSteppingSubmorphsOf: self! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 1/31/2001 13:58'!\\noutOfWorld: aWorld\\n\\t\\\"The receiver has just appeared in a new world. Notes:\\n\\t\\t* aWorld can be nil (due to optimizations in other places)\\n\\t\\t* owner is still valid\\n\\tImportant: Keep this method fast - it is run whenever morphs are removed.\\\"\\n\\taWorld ifNil:[^self].\\n\\t\\\"ar 1/31/2001: We could explicitly stop stepping the receiver here but for the sake of speed I'm for now relying on the lazy machinery in the world itself.\\\"\\n\\t\\\"aWorld stopStepping: self.\\\"\\n\\tself submorphsDo:[:m| m outOfWorld: aWorld].\\n! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'ar 3/3/2001 15:28'!\\nresourceJustLoaded\\n\\t\\\"In case resource relates to me\\\"\\n\\tself releaseCachedState.! !\\n\\n!Morph methodsFor: 'initialization' stamp: 'sw 9/11/1998 11:13'!\\nstandardPalette\\n\\t\\\"Answer a standard palette forced by some level of enclosing presenter, or nil if none\\\"\\n\\t| pal aPresenter itsOwner |\\n\\t(aPresenter _ self presenter) ifNil: [^ nil].\\n\\t^ (pal _ aPresenter ownStandardPalette)\\n\\t\\tifNotNil: [pal]\\n\\t\\tifNil:\\t[(itsOwner _ aPresenter associatedMorph owner)\\n\\t\\t\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t\\t\\t[itsOwner standardPalette]\\n\\t\\t\\t\\t\\tifNil:\\n\\t\\t\\t\\t\\t\\t[nil]]! !\\n\\n\\n!Morph methodsFor: 'latter day support' stamp: 'sw 1/6/2005 01:26'!\\nisEtoyReadout\\n\\t\\\"Answer whether the receiver can serve as an etoy readout\\\"\\n\\n\\t^ false! !\\n\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:33'!\\nacceptDroppingMorph: aMorph event: evt\\n\\t\\\"This message is sent when a morph is dropped onto a morph that has agreed to accept the dropped morph by responding 'true' to the wantsDroppedMorph:Event: message. This default implementation just adds the given morph to the receiver.\\\"\\n\\t| layout |\\n\\tlayout _ self layoutPolicy.\\n\\tlayout ifNil:[^self addMorph: aMorph].\\n\\tself privateAddMorph: aMorph \\n\\t\\tatIndex: (layout indexForInserting: aMorph at: evt position in: self).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:34'!\\nadjustLayoutBounds\\n\\t\\\"Adjust the receivers bounds depending on the resizing strategy imposed\\\"\\n\\t| hFit vFit box myExtent extent |\\n\\thFit _ self hResizing.\\n\\tvFit _ self vResizing.\\n\\t(hFit == #shrinkWrap or:[vFit == #shrinkWrap]) ifFalse:[^self]. \\\"not needed\\\"\\n\\tbox _ self layoutBounds.\\n\\tmyExtent _ box extent.\\n\\textent _ self submorphBounds corner - box origin.\\n\\thFit == #shrinkWrap ifTrue:[myExtent _ extent x @ myExtent y].\\n\\tvFit == #shrinkWrap ifTrue:[myExtent _ myExtent x @ extent y].\\n\\t\\\"Make sure we don't get smaller than minWidth/minHeight\\\"\\n\\tmyExtent x < self minWidth ifTrue:[\\n\\t\\tmyExtent _ (myExtent x max: \\n\\t\\t\\t(self minWidth - self bounds width + self layoutBounds width)) @ myExtent y].\\n\\tmyExtent y < self minHeight ifTrue:[\\n\\t\\tmyExtent _ myExtent x @ (myExtent y max:\\n\\t\\t\\t(self minHeight - self bounds height + self layoutBounds height))].\\n\\tself layoutBounds: (box origin extent: myExtent).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:31'!\\ndoLayoutIn: layoutBounds \\n\\t\\\"Compute a new layout based on the given layout bounds.\\\"\\n\\n\\t\\\"Note: Testing for #bounds or #layoutBounds would be sufficient to\\n\\tfigure out if we need an invalidation afterwards but #outerBounds\\n\\tis what we need for all leaf nodes so we use that.\\\"\\n\\n\\t| layout box priorBounds |\\n\\tpriorBounds := self outerBounds.\\n\\tsubmorphs isEmpty ifTrue: [^fullBounds := priorBounds].\\n\\t\\\"Send #ownerChanged to our children\\\"\\n\\tsubmorphs do: [:m | m ownerChanged].\\n\\tlayout := self layoutPolicy.\\n\\tlayout ifNotNil: [layout layout: self in: layoutBounds].\\n\\tself adjustLayoutBounds.\\n\\tfullBounds := self privateFullBounds.\\n\\tbox := self outerBounds.\\n\\tbox = priorBounds \\n\\t\\tifFalse: [self invalidRect: (priorBounds quickMerge: box)]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 1/1/2002 20:00'!\\nfullBounds\\n\\t\\\"Return the bounding box of the receiver and all its children. Recompute the layout if necessary.\\\"\\n\\tfullBounds ifNotNil:[^fullBounds].\\n\\t\\\"Errors at this point can be critical so make sure we catch 'em all right\\\"\\n\\t[self doLayoutIn: self layoutBounds] on: Error do:[:ex|\\n\\t\\t\\\"This should do it unless you don't screw up the bounds\\\"\\n\\t\\tfullBounds _ bounds.\\n\\t\\tex pass].\\n\\t^fullBounds! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 23:10'!\\nlayoutBounds\\n\\t\\\"Return the bounds for laying out children of the receiver\\\"\\n\\t| inset box |\\n\\tinset _ self layoutInset.\\n\\tbox _ self innerBounds.\\n\\tinset isZero ifTrue:[^box].\\n\\t^box insetBy: inset.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 10/31/2000 21:09'!\\nlayoutBounds: aRectangle\\n\\t\\\"Set the bounds for laying out children of the receiver.\\n\\tNote: written so that #layoutBounds can be changed without touching this method\\\"\\n\\t| outer inner |\\n\\touter _ self bounds.\\n\\tinner _ self layoutBounds.\\n\\tbounds _ aRectangle origin + (outer origin - inner origin) corner:\\n\\t\\t\\t\\taRectangle corner + (outer corner - inner corner).! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 1/27/2001 14:41'!\\nlayoutChanged\\n\\t| layout |\\n\\tfullBounds ifNil:[^self]. \\\"layout will be recomputed so don't bother\\\"\\n\\tfullBounds _ nil.\\n\\tlayout _ self layoutPolicy.\\n\\tlayout ifNotNil:[layout flushLayoutCache].\\n\\towner ifNotNil: [owner layoutChanged].\\n\\t\\\"note: does not send #ownerChanged here - we'll do this when computing the new layout\\\"! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 8/6/2001 09:55'!\\nlayoutInBounds: cellBounds\\n\\t\\\"Layout specific. Apply the given bounds to the receiver after being layed out in its owner.\\\"\\n\\t| box aSymbol delta |\\n\\tfullBounds ifNil:[\\\"We are getting new bounds here but we haven't computed the receiver's layout yet. Although the receiver has reported its minimal size before the actual size it has may differ from what would be after the layout. Normally, this isn't a real problem, but if we have #shrinkWrap constraints then the receiver's bounds may be larger than the cellBounds. THAT is a problem because the centering may not work correctly if the receiver shrinks after the owner layout has been computed. To avoid this problem, we compute the receiver's layout now. Note that the layout computation is based on the new cell bounds rather than the receiver's current bounds.\\\"\\n\\t\\tcellBounds origin = self bounds origin ifFalse:[\\n\\t\\t\\tbox _ self outerBounds.\\n\\t\\t\\tdelta _ cellBounds origin - self bounds origin.\\n\\t\\t\\tself invalidRect: (box merge: (box translateBy: delta)).\\n\\t\\t\\tself privateFullMoveBy: delta]. \\\"sigh...\\\"\\n\\t\\tbox _ cellBounds origin extent: \\\"adjust for #rigid receiver\\\"\\n\\t\\t\\t(self hResizing == #rigid ifTrue:[self bounds extent x] ifFalse:[cellBounds extent x]) @\\n\\t\\t\\t(self vResizing == #rigid ifTrue:[self bounds extent y] ifFalse:[cellBounds extent y]).\\n\\t\\t\\\"Compute inset of layout bounds\\\"\\n\\t\\tbox _ box origin - (self bounds origin - self layoutBounds origin) corner:\\n\\t\\t\\t\\t\\tbox corner - (self bounds corner - self layoutBounds corner).\\n\\t\\t\\\"And do the layout within the new bounds\\\"\\n\\t\\tself layoutBounds: box.\\n\\t\\tself doLayoutIn: box].\\n\\tcellBounds = self fullBounds ifTrue:[^self]. \\\"already up to date\\\"\\n\\tcellBounds extent = self fullBounds extent \\\"nice fit\\\"\\n\\t\\tifTrue:[^self position: cellBounds origin].\\n\\tbox _ bounds.\\n\\t\\\"match #spaceFill constraints\\\"\\n\\tself hResizing == #spaceFill \\n\\t\\tifTrue:[box _ box origin extent: cellBounds width @ box height].\\n\\tself vResizing == #spaceFill\\n\\t\\tifTrue:[box _ box origin extent: box width @ cellBounds height].\\n\\t\\\"align accordingly\\\"\\n\\taSymbol _ (owner ifNil:[self]) cellPositioning.\\n\\tbox _ box align: (box perform: aSymbol) with: (cellBounds perform: aSymbol).\\n\\t\\\"and install new bounds\\\"\\n\\tself bounds: box.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/12/2000 17:35'!\\nlayoutProportionallyIn: newBounds\\n\\t\\\"Layout specific. Apply the given bounds to the receiver.\\\"\\n\\t| box frame |\\n\\tframe _ self layoutFrame ifNil:[^self].\\n\\t\\\"before applying the proportional values make sure the receiver's layout is computed\\\"\\n\\tself fullBounds. \\\"sigh...\\\"\\n\\t\\\"compute the cell size the receiver has given its layout frame\\\"\\n\\tbox _ frame layout: self bounds in: newBounds.\\n\\t(box = self bounds) ifTrue:[^self]. \\\"no change\\\"\\n\\t^self layoutInBounds: box.! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminExtent\\n\\t\\\"Layout specific. Return the minimum size the receiver can be represented in.\\n\\tImplementation note: When this message is sent from an owner trying to lay out its children it will traverse down the morph tree and recompute the minimal arrangement of the morphs based on which the minimal extent is returned. When a morph with some layout strategy is encountered, the morph will ask its strategy to compute the new arrangement. However, since the final size given to the receiver is unknown at the point of the query, the assumption is made that the current bounds of the receiver are the base on which the layout should be computed. This scheme prevents strange layout changes when for instance, a table is contained in another table. Unless the inner table has been resized manually (which means its bounds are already enlarged) the arrangement of the inner table will not change here. Thus the entire layout computation is basically an iterative process which may have different results depending on the incremental changes applied.\\\"\\n\\n\\t| layout minExtent extra hFit vFit |\\n\\thFit := self hResizing.\\n\\tvFit := self vResizing.\\n\\t(hFit == #spaceFill or: [vFit == #spaceFill]) \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"The receiver will not adjust to parents layout by growing or shrinking,\\n\\t\\twhich means that an accurate layout defines the minimum size.\\\"\\n\\n\\t\\t\\t^self fullBounds extent].\\n\\n\\t\\\"An exception -- a receiver with #shrinkWrap constraints but no children is being treated #rigid (the equivalent to a #spaceFill receiver in a non-layouting owner)\\\"\\n\\tself hasSubmorphs \\n\\t\\tifFalse: \\n\\t\\t\\t[hFit == #shrinkWrap ifTrue: [hFit := #rigid].\\n\\t\\t\\tvFit == #shrinkWrap ifTrue: [vFit := #rigid]].\\n\\tlayout := self layoutPolicy.\\n\\tlayout isNil \\n\\t\\tifTrue: [minExtent := 0 @ 0]\\n\\t\\tifFalse: [minExtent := layout minExtentOf: self in: self layoutBounds].\\n\\thFit == #rigid \\n\\t\\tifTrue: [minExtent := self fullBounds extent x @ minExtent y]\\n\\t\\tifFalse: \\n\\t\\t\\t[extra := self bounds width - self layoutBounds width.\\n\\t\\t\\tminExtent := (minExtent x + extra) @ minExtent y].\\n\\tminExtent := vFit == #rigid \\n\\t\\t\\t\\tifTrue: [minExtent x @ self fullBounds extent y]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[extra := self bounds height - self layoutBounds height.\\n\\t\\t\\t\\t\\tminExtent x @ (minExtent y + extra)].\\n\\tminExtent := minExtent max: self minWidth @ self minHeight.\\n\\t^minExtent! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/16/2003 21:52'!\\nminHeight\\n\\t\\\"answer the receiver's minHeight\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #minHeight\\n\\t\\tifAbsent: [2]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminHeight: aNumber \\n\\taNumber isNil \\n\\t\\tifTrue: [self removeProperty: #minHeight]\\n\\t\\tifFalse: [self setProperty: #minHeight toValue: aNumber].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/16/2003 21:54'!\\nminWidth\\n\\t\\\"answer the receiver's minWidth\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #minWidth\\n\\t\\tifAbsent: [2]! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:32'!\\nminWidth: aNumber \\n\\taNumber isNil \\n\\t\\tifTrue: [self removeProperty: #minWidth]\\n\\t\\tifFalse: [self setProperty: #minWidth toValue: aNumber].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'layout' stamp: 'dgd 2/22/2003 14:33'!\\nprivateFullBounds\\n\\t\\\"Private. Compute the actual full bounds of the receiver\\\"\\n\\n\\t| box |\\n\\tsubmorphs isEmpty ifTrue: [^self outerBounds].\\n\\tbox := self outerBounds copy.\\n\\tbox := box quickMerge: (self clipSubmorphs \\n\\t\\t\\t\\t\\t\\tifTrue: [self submorphBounds intersect: self clippingBounds]\\n\\t\\t\\t\\t\\t\\tifFalse: [self submorphBounds]).\\n\\t^box origin asIntegerPoint corner: box corner asIntegerPoint! !\\n\\n!Morph methodsFor: 'layout' stamp: 'ar 11/2/2000 17:42'!\\nsubmorphBounds\\n\\t\\\"Private. Compute the actual full bounds of the receiver\\\"\\n\\t| box subBox |\\n\\tsubmorphs do: [:m | \\n\\t\\t(m visible) ifTrue: [\\n\\t\\t\\tsubBox _ m fullBounds.\\n\\t\\t\\tbox \\n\\t\\t\\t\\tifNil:[box _ subBox copy]\\n\\t\\t\\t\\tifNotNil:[box _ box quickMerge: subBox]]].\\n\\tbox ifNil:[^self bounds]. \\\"e.g., having submorphs but not visible\\\"\\n\\t^ box origin asIntegerPoint corner: box corner asIntegerPoint\\n! !\\n\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:57'!\\naddCellLayoutMenuItems: aMenu hand: aHand\\n\\t\\\"Cell (e.g., child) related items\\\"\\n\\t| menu sub |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\t\\tmenu addUpdating: #hasDisableTableLayoutString action: #changeDisableTableLayout.\\n\\t\\tmenu addLine.\\n\\n\\t\\tsub _ MenuMorph new defaultTarget: self.\\n\\t\\t#(rigid shrinkWrap spaceFill) do:[:sym|\\n\\t\\t\\tsub addUpdating: #hResizingString: target: self selector: #hResizing: argumentList: (Array with: sym)].\\n\\t\\tmenu add:'horizontal resizing' translated subMenu: sub.\\n\\n\\t\\tsub _ MenuMorph new defaultTarget: self.\\n\\t\\t#(rigid shrinkWrap spaceFill) do:[:sym|\\n\\t\\t\\tsub addUpdating: #vResizingString: target: self selector: #vResizing: argumentList: (Array with: sym)].\\n\\t\\tmenu add:'vertical resizing' translated subMenu: sub.\\n\\n\\taMenu ifNotNil:[aMenu add: 'child layout' translated subMenu: menu].\\n\\t^menu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:51'!\\naddLayoutMenuItems: topMenu hand: aHand\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addUpdating: #hasNoLayoutString action: #changeNoLayout.\\n\\taMenu addUpdating: #hasProportionalLayoutString action: #changeProportionalLayout.\\n\\taMenu addUpdating: #hasTableLayoutString action: #changeTableLayout.\\n\\taMenu addLine.\\n\\taMenu add: 'change layout inset...' translated action: #changeLayoutInset:.\\n\\taMenu addLine.\\n\\tself addCellLayoutMenuItems: aMenu hand: aHand.\\n\\tself addTableLayoutMenuItems: aMenu hand: aHand.\\n\\ttopMenu ifNotNil:[topMenu add: 'layout' translated subMenu: aMenu].\\n\\t^aMenu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:07'!\\naddTableLayoutMenuItems: aMenu hand: aHand\\n\\t| menu sub |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addUpdating: #hasReverseCellsString action: #changeReverseCells.\\n\\tmenu addUpdating: #hasClipLayoutCellsString action: #changeClipLayoutCells.\\n\\tmenu addUpdating: #hasRubberBandCellsString action: #changeRubberBandCells.\\n\\tmenu addLine.\\n\\tmenu add: 'change cell inset...' translated action: #changeCellInset:.\\n\\tmenu add: 'change min cell size...' translated action: #changeMinCellSize:.\\n\\tmenu add: 'change max cell size...' translated action: #changeMaxCellSize:.\\n\\tmenu addLine.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(leftToRight rightToLeft topToBottom bottomToTop) do:[:sym|\\n\\t\\tsub addUpdating: #listDirectionString: target: self selector: #changeListDirection: argumentList: (Array with: sym)].\\n\\tmenu add: 'list direction' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none leftToRight rightToLeft topToBottom bottomToTop) do:[:sym|\\n\\t\\tsub addUpdating: #wrapDirectionString: target: self selector: #wrapDirection: argumentList: (Array with: sym)].\\n\\tmenu add: 'wrap direction' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(center topLeft topRight bottomLeft bottomRight topCenter leftCenter rightCenter bottomCenter) do:[:sym|\\n\\t\\tsub addUpdating: #cellPositioningString: target: self selector: #cellPositioning: argumentList: (Array with: sym)].\\n\\tmenu add: 'cell positioning' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(topLeft bottomRight center justified) do:[:sym|\\n\\t\\tsub addUpdating: #listCenteringString: target: self selector: #listCentering: argumentList: (Array with: sym)].\\n\\tmenu add: 'list centering' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(topLeft bottomRight center justified) do:[:sym|\\n\\t\\tsub addUpdating: #wrapCenteringString: target: self selector: #wrapCentering: argumentList: (Array with: sym)].\\n\\tmenu add: 'wrap centering' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none equal) do:[:sym|\\n\\t\\tsub addUpdating: #listSpacingString: target: self selector: #listSpacing: argumentList: (Array with: sym)].\\n\\tmenu add: 'list spacing' translated subMenu: sub.\\n\\n\\tsub _ MenuMorph new defaultTarget: self.\\n\\t#(none localRect localSquare globalRect globalSquare) do:[:sym|\\n\\t\\tsub addUpdating: #cellSpacingString: target: self selector: #cellSpacing: argumentList: (Array with: sym)].\\n\\tmenu add: 'cell spacing' translated subMenu: sub.\\n\\n\\taMenu ifNotNil:[aMenu add: 'table layout' translated subMenu: menu].\\n\\t^menu! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:08'!\\nchangeCellInset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself cellInset: (newPoint - evt cursorPoint) asIntegerPoint // 5].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 18:54'!\\nchangeClipLayoutCells\\n\\tself invalidRect: self fullBounds.\\n\\tself clipLayoutCells: self clipLayoutCells not.\\n\\tself invalidRect: self fullBounds.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeDisableTableLayout\\n\\tself disableTableLayout: self disableTableLayout not.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:09'!\\nchangeLayoutInset: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself layoutInset: (newPoint - evt cursorPoint) asIntegerPoint // 5].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeListDirection: aSymbol\\n\\t| listDir wrapDir |\\n\\tself listDirection: aSymbol.\\n\\t(self wrapDirection == #none) ifTrue:[^self].\\n\\t\\\"otherwise automatically keep a valid table layout\\\"\\n\\tlistDir _ self listDirection.\\n\\twrapDir _ self wrapDirection.\\n\\t(listDir == #leftToRight or:[listDir == #rightToLeft]) ifTrue:[\\n\\t\\twrapDir == #leftToRight ifTrue:[^self wrapDirection: #topToBottom].\\n\\t\\twrapDir == #rightToLeft ifTrue:[^self wrapDirection: #bottomToTop].\\n\\t] ifFalse:[\\n\\t\\twrapDir == #topToBottom ifTrue:[^self wrapDirection: #leftToRight].\\n\\t\\twrapDir == #bottomToTop ifTrue:[^self wrapDirection: #rightToLeft].\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeMaxCellSize: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself maxCellSize: (newPoint - evt cursorPoint) asIntegerPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeMinCellSize: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:newPoint |\\n\\t\\tself minCellSize: (newPoint - evt cursorPoint) asIntegerPoint].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeNoLayout\\n\\tself layoutPolicy ifNil:[^self]. \\\"already no layout\\\"\\n\\tself layoutPolicy: nil.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:19'!\\nchangeProportionalLayout\\n\\t| layout |\\n\\t((layout _ self layoutPolicy) notNil and:[layout isProportionalLayout])\\n\\t\\tifTrue:[^self]. \\\"already proportional layout\\\"\\n\\tself layoutPolicy: ProportionalLayout new.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeReverseCells\\n\\tself reverseTableCells: self reverseTableCells not.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 11/13/2000 19:10'!\\nchangeRubberBandCells\\n\\tself rubberBandCells: self rubberBandCells not.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'ar 10/31/2000 19:20'!\\nchangeTableLayout\\n\\t| layout |\\n\\t((layout _ self layoutPolicy) notNil and:[layout isTableLayout])\\n\\t\\tifTrue:[^self]. \\\"already table layout\\\"\\n\\tself layoutPolicy: TableLayout new.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:09'!\\nhasClipLayoutCellsString\\n\\t^ (self clipLayoutCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'clip to cell size' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:58'!\\nhasDisableTableLayoutString\\n\\t^ (self disableTableLayout\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'disable layout in tables' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 10/8/2003 19:23'!\\nhasNoLayoutString\\n\\t^ (self layoutPolicy isNil\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'no layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:55'!\\nhasProportionalLayoutString\\n\\t| layout |\\n\\t^ (((layout := self layoutPolicy) notNil\\n\\t\\t\\tand: [layout isProportionalLayout])\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'proportional layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:08'!\\nhasReverseCellsString\\n\\t^ (self reverseTableCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'reverse table cells' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 20:09'!\\nhasRubberBandCellsString\\n\\t^ (self rubberBandCells\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'rubber band cells' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 8/30/2003 16:59'!\\nhasTableLayoutString\\n\\t| layout |\\n\\t^ (((layout := self layoutPolicy) notNil\\n\\t\\t\\tand: [layout isTableLayout])\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'table layout' translated! !\\n\\n!Morph methodsFor: 'layout-menu' stamp: 'dgd 10/19/2003 11:23'!\\nlayoutMenuPropertyString: aSymbol from: currentSetting \\n\\t| onOff wording |\\n\\tonOff := aSymbol == currentSetting\\n\\t\\t\\t\\tifTrue: ['<on>']\\n\\t\\t\\t\\tifFalse: ['<off>'].\\n\\t\\\"\\\"\\n\\twording := String\\n\\t\\t\\t\\tstreamContents: [:stream | \\n\\t\\t\\t\\t\\t| index | \\n\\t\\t\\t\\t\\tindex := 1.\\n\\t\\t\\t\\t\\taSymbol\\n\\t\\t\\t\\t\\t\\tkeysAndValuesDo: [:idx :ch | ch isUppercase\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [\\\"\\\"stream nextPutAll: (aSymbol copyFrom: index to: idx - 1) asLowercase.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tstream nextPutAll: ' '.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tindex := idx]].\\n\\t\\t\\t\\t\\tindex < aSymbol size\\n\\t\\t\\t\\t\\t\\tifTrue: [stream nextPutAll: (aSymbol copyFrom: index to: aSymbol size) asLowercase]].\\n\\t\\\"\\\"\\n\\t^ onOff , wording translated! !\\n\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:56'!\\nassureLayoutProperties\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\tprops == self ifTrue:[props _ nil].\\n\\tprops ifNil:[\\n\\t\\tprops _ LayoutProperties new initializeFrom: self.\\n\\t\\tself layoutProperties: props].\\n\\t^props! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:57'!\\nassureTableProperties\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\tprops == self ifTrue:[props _ nil].\\n\\tprops ifNil:[\\n\\t\\tprops _ TableLayoutProperties new initializeFrom: self.\\n\\t\\tself layoutProperties: props].\\n\\tprops includesTableProperties \\n\\t\\tifFalse:[self layoutProperties: (props _ props asTableLayoutProperties)].\\n\\t^props! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellInset\\n\\t\\\"Layout specific. This property specifies an extra inset for each cell in the layout.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props cellInset].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellInset: aNumber\\n\\t\\\"Layout specific. This property specifies an extra inset for each cell in the layout.\\\"\\n\\tself assureTableProperties cellInset: aNumber.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:54'!\\ncellPositioning\\n\\t\\\"Layout specific. This property describes how the receiver should be layed out in its owner when the bounds of the cell assigned to the receiver do not exactly match its bounds. Possible values are:\\n\\t\\t#topLeft, #topRight, #bottomLeft, #bottomRight, #topCenter, #leftCenter, #rightCenter, #bottomCenter, #center \\n\\twhich align the receiver's bounds with the cell at the given point.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#center] ifNotNil:[props cellPositioning].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:48'!\\ncellPositioningString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self cellPositioning! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:39'!\\ncellPositioning: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be layed out in its owner when the bounds of the cell assigned to the receiver do not exactly match its bounds. Possible values are:\\n\\t\\t#topLeft, #topRight, #bottomLeft, #bottomRight, #topCenter, #leftCenter, #rightCenter, #bottomCenter, #center \\n\\twhich align the receiver's bounds with the cell at the given point.\\\"\\n\\tself assureTableProperties cellPositioning: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:55'!\\ncellSpacing\\n\\t\\\"Layout specific. This property describes how the cell size for each element in a list should be computed.\\n\\t\\t#globalRect - globally equal rectangular cells\\n\\t\\t#globalSquare - globally equal square cells\\n\\t\\t#localRect - locally (e.g., per row/column) equal rectangular cells\\n\\t\\t#localSquare - locally (e.g., per row/column) equal square cells\\n\\t\\t#none - cells are sized based on available row/column constraints\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props cellSpacing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\ncellSpacingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self cellSpacing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:56'!\\ncellSpacing: aSymbol\\n\\t\\\"Layout specific. This property describes how the cell size for each element in a list should be computed.\\n\\t\\t#globalRect - globally equal rectangular cells\\n\\t\\t#globalSquare - globally equal square cells\\n\\t\\t#localRect - locally (e.g., per row/column) equal rectangular cells\\n\\t\\t#localSquare - locally (e.g., per row/column) equal square cells\\n\\t\\t#none - cells are sized based on available row/column constraints\\n\\t\\\"\\n\\tself assureTableProperties cellSpacing: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:56'!\\ndisableTableLayout\\n\\t\\\"Layout specific. Disable laying out the receiver in table layout\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props disableTableLayout].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:06'!\\ndisableTableLayout: aBool\\n\\t\\\"Layout specific. Disable laying out the receiver in table layout\\\"\\n\\tself assureLayoutProperties disableTableLayout: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:57'!\\nhResizing\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#rigid] ifNotNil:[props hResizing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/31/2000 20:45'!\\nhResizingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self hResizing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:06'!\\nhResizing: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\tself assureLayoutProperties hResizing: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 09:59'!\\nlayoutFrame\\n\\t\\\"Layout specific. Return the layout frame describing where the \\n\\treceiver should appear in a proportional layout\\\"\\n\\t^ extension ifNotNil: [extension layoutFrame]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:20'!\\nlayoutFrame: aLayoutFrame\\n\\t\\\"Layout specific. Return the layout frame describing where the receiver should appear in a proportional layout\\\"\\n\\tself layoutFrame == aLayoutFrame ifTrue:[^self].\\n\\tself assureExtension layoutFrame: aLayoutFrame.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 16:38'!\\nlayoutInset\\n\\t\\\"Return the extra inset for layouts\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props layoutInset].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 16:38'!\\nlayoutInset: aNumber\\n\\t\\\"Return the extra inset for layouts\\\"\\n\\tself assureTableProperties layoutInset: aNumber.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 10:00'!\\nlayoutPolicy\\n\\t\\\"Layout specific. Return the layout policy describing how children \\n\\tof the receiver should appear.\\\"\\n\\t^ extension ifNotNil: [ extension layoutPolicy]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:21'!\\nlayoutPolicy: aLayoutPolicy\\n\\t\\\"Layout specific. Return the layout policy describing how children of the receiver should appear.\\\"\\n\\tself layoutPolicy == aLayoutPolicy ifTrue:[^self].\\n\\tself assureExtension layoutPolicy: aLayoutPolicy.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'md 2/27/2006 09:58'!\\nlayoutProperties\\n\\t\\\"Return the current layout properties associated with the \\n\\treceiver\\\"\\n\\t^ extension ifNotNil: [ extension layoutProperties]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/14/2000 17:21'!\\nlayoutProperties: newProperties\\n\\t\\\"Return the current layout properties associated with the receiver\\\"\\n\\tself layoutProperties == newProperties ifTrue:[^self].\\n\\tself assureExtension layoutProperties: newProperties.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:58'!\\nlistCentering\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of primary direction\\n\\t\\t#bottomRight - center at end of primary direction\\n\\t\\t#center - center in the middle of primary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topLeft] ifNotNil:[props listCentering].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistCenteringString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listCentering! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:05'!\\nlistCentering: aSymbol\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of primary direction\\n\\t\\t#bottomRight - center at end of primary direction\\n\\t\\t#center - center in the middle of primary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\tself assureTableProperties listCentering: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nlistDirection\\n\\t\\\"Layout specific. This property describes the direction in which a list-like layout should be applied. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\tindicating the direction in which any layout should take place\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topToBottom] ifNotNil:[props listDirection].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistDirectionString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listDirection! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nlistDirection: aSymbol\\n\\t\\\"Layout specific. This property describes the direction in which a list-like layout should be applied. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\tindicating the direction in which any layout should take place\\\"\\n\\tself assureTableProperties listDirection: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nlistSpacing\\n\\t\\\"Layout specific. This property describes how the heights for different rows in a table layout should be handled.\\n\\t\\t#equal - all rows have the same height\\n\\t\\t#none - all rows may have different heights\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props listSpacing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 02:47'!\\nlistSpacingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self listSpacing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nlistSpacing: aSymbol\\n\\t\\\"Layout specific. This property describes how the heights for different rows in a table layout should be handled.\\n\\t\\t#equal - all rows have the same height\\n\\t\\t#none - all rows may have different heights\\n\\t\\\"\\n\\tself assureTableProperties listSpacing: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 19:59'!\\nmaxCellSize\\n\\t\\\"Layout specific. This property specifies the maximum size of a table cell.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[SmallInteger maxVal] ifNotNil:[props maxCellSize].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nmaxCellSize: aPoint\\n\\t\\\"Layout specific. This property specifies the maximum size of a table cell.\\\"\\n\\tself assureTableProperties maxCellSize: aPoint.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:00'!\\nminCellSize\\n\\t\\\"Layout specific. This property specifies the minimal size of a table cell.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[0] ifNotNil:[props minCellSize].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nminCellSize: aPoint\\n\\t\\\"Layout specific. This property specifies the minimal size of a table cell.\\\"\\n\\tself assureTableProperties minCellSize: aPoint.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:01'!\\nreverseTableCells\\n\\t\\\"Layout specific. This property describes if the cells should be treated in reverse order of submorphs.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props reverseTableCells].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nreverseTableCells: aBool\\n\\t\\\"Layout specific. This property describes if the cells should be treated in reverse order of submorphs.\\\"\\n\\tself assureTableProperties reverseTableCells: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:01'!\\nrubberBandCells\\n\\t\\\"Layout specific. This property describes if a parent that is #shrinkWrapped around its children should ignore any #spaceFill children. E.g., when #rubberBandCells is true, the compound layout will always stay at the smallest available size, even though some child may be able to grow.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[false] ifNotNil:[props rubberBandCells].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:04'!\\nrubberBandCells: aBool\\n\\t\\\"Layout specific. This property describes if a parent that is #shrinkWrapped around its children should ignore any #spaceFill children. E.g., when #rubberBandCells is true, the compound layout will always stay at the smallest available size, even though some child may be able to grow.\\\"\\n\\tself assureTableProperties rubberBandCells: aBool.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'dgd 2/16/2003 20:02'!\\nspaceFillWeight\\n\\t\\\"Layout specific. This property describes the relative weight that \\n\\tshould be given to the receiver when extra space is distributed \\n\\tbetween different #spaceFill cells.\\\"\\n\\n\\t^ self\\n\\t\\tvalueOfProperty: #spaceFillWeight\\n\\t\\tifAbsent: [1]! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/15/2000 14:16'!\\nspaceFillWeight: aNumber\\n\\t\\\"Layout specific. This property describes the relative weight that should be given to the receiver when extra space is distributed between different #spaceFill cells.\\\"\\n\\taNumber = 1\\n\\t\\tifTrue:[self removeProperty: #spaceFillWeight]\\n\\t\\tifFalse:[self setProperty: #spaceFillWeight toValue: aNumber].\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'tk 10/30/2001 18:39'!\\nvResizeToFit: aBoolean\\n\\taBoolean ifTrue:[\\n\\t\\tself vResizing: #shrinkWrap.\\n\\t] ifFalse:[\\n\\t\\tself vResizing: #rigid.\\n\\t].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:02'!\\nvResizing\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#rigid] ifNotNil:[props vResizing].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/31/2000 20:45'!\\nvResizingString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self vResizing! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nvResizing: aSymbol\\n\\t\\\"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:\\n\\t\\t#rigid\\t\\t\\t-\\tdo not resize the receiver\\n\\t\\t#spaceFill\\t\\t-\\tresize to fill owner's available space\\n\\t\\t#shrinkWrap\\t- resize to fit children\\n\\t\\\"\\n\\tself assureLayoutProperties vResizing: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:02'!\\nwrapCentering\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of secondary direction\\n\\t\\t#bottomRight - center at end of secondary direction\\n\\t\\t#center - center in the middle of secondary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#topLeft] ifNotNil:[props wrapCentering].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 03:00'!\\nwrapCenteringString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self wrapCentering! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapCentering: aSymbol\\n\\t\\\"Layout specific. This property describes how the rows/columns in a list-like layout should be centered.\\n\\t\\t#topLeft - center at start of secondary direction\\n\\t\\t#bottomRight - center at end of secondary direction\\n\\t\\t#center - center in the middle of secondary direction\\n\\t\\t#justified - insert extra space inbetween rows/columns\\n\\t\\\"\\n\\tself assureTableProperties wrapCentering: aSymbol.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapDirection\\n\\t\\\"Layout specific. This property describes the direction along which a list-like layout should be wrapped. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\t\\t#none\\n\\tindicating in which direction wrapping should occur. This direction must be orthogonal to the list direction, that is if listDirection is #leftToRight or #rightToLeft then wrapDirection must be #topToBottom or #bottomToTop and vice versa.\\\"\\n\\t| props |\\n\\tprops _ self layoutProperties.\\n\\t^props ifNil:[#none] ifNotNil:[props wrapDirection].! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 10/29/2000 03:00'!\\nwrapDirectionString: aSymbol\\n\\t^self layoutMenuPropertyString: aSymbol from: self wrapDirection ! !\\n\\n!Morph methodsFor: 'layout-properties' stamp: 'ar 11/13/2000 20:03'!\\nwrapDirection: aSymbol\\n\\t\\\"Layout specific. This property describes the direction along which a list-like layout should be wrapped. Possible values are:\\n\\t\\t#leftToRight\\n\\t\\t#rightToLeft\\n\\t\\t#topToBottom\\n\\t\\t#bottomToTop\\n\\t\\t#none\\n\\tindicating in which direction wrapping should occur. This direction must be orthogonal to the list direction, that is if listDirection is #leftToRight or #rightToLeft then wrapDirection must be #topToBottom or #bottomToTop and vice versa.\\\"\\n\\tself assureTableProperties wrapDirection: aSymbol.\\n\\tself layoutChanged.\\n! !\\n\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 5/17/2001 17:57'!\\ncurrentVocabulary\\n\\t\\\"Answer the receiver's current vocabulary\\\"\\n\\n\\t| outer |\\n\\t^ (outer _ self ownerThatIsA: StandardViewer orA: ScriptEditorMorph) \\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[outer currentVocabulary]\\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[super currentVocabulary]! !\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 10/10/1999 10:23'!\\nflash\\n\\t| c w |\\n\\tc _ self color.\\n\\tself color: Color black.\\n\\t(w _ self world) ifNotNil: [w displayWorldSafely].\\n\\tself color: c\\n! !\\n\\n!Morph methodsFor: 'macpal' stamp: 'sw 7/20/1999 08:13'!\\nscriptPerformer\\n\\t^ self topRendererOrSelf player ifNil: [self]! !\\n\\n\\n!Morph methodsFor: 'menu' stamp: 'sw 11/27/2001 15:21'!\\naddBorderStyleMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Probably one could offer border-style items even if it's not a borderedMorph, so this remains a loose end for the moment\\\"\\n! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 2/15/2004 09:08'!\\naddGestureMenuItems: aMenu hand: aHandMorph\\n\\t\\\"If the receiver wishes the Genie menu items, add a line to the menu and then those Genie items, else do nothing\\\"! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 6/15/2004 07:11'!\\naddGraphModelYellowButtonItemsTo: aCustomMenu event: evt\\n\\t^aCustomMenu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 17:47'!\\naddModelYellowButtonItemsTo: aCustomMenu event: evt \\n\\t\\\"Give my models a chance to add their context-menu items to \\n\\taCustomMenu.\\\"\\n\\tself model\\n\\t\\tifNotNilDo: [:mod |\\n\\t\\t\\tmod\\n\\t\\t\\t\\taddModelYellowButtonMenuItemsTo: aCustomMenu\\n\\t\\t\\t\\tforMorph: self\\n\\t\\t\\t\\thand: evt hand]! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 3/10/2004 19:49'!\\naddMyYellowButtonMenuItemsToSubmorphMenus\\n\\t\\\"Answer true if I have items to add to the context menus of my submorphs\\\"\\n\\n\\t^true! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/13/2004 19:23'!\\naddNestedYellowButtonItemsTo: aMenu event: evt \\n\\t\\\"Add items to aMenu starting with me and proceeding down \\n\\tthrough my submorph chain, \\n\\tletting any submorphs that include the event position \\n\\tcontribute their items to the bottom of the menu, separated by \\n\\ta line.\\\"\\n\\t| underMouse |\\n\\n\\tself addYellowButtonMenuItemsTo: aMenu event: evt.\\n\\n\\tunderMouse := self\\n\\t\\t\\t\\tsubmorphThat: [:each | each containsPoint: evt position]\\n\\t\\t\\t\\tifNone: [^ self].\\n\\n\\t(underMouse addMyYellowButtonMenuItemsToSubmorphMenus\\n\\t\\t\\tand: [underMouse hasYellowButtonMenu])\\n\\t\\tifTrue: [| submenu |\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\tsubmenu := MenuMorph new defaultTarget: underMouse.\\n\\t\\t\\tunderMouse addNestedYellowButtonItemsTo: submenu event: evt.\\n\\t\\t\\taMenu\\n\\t\\t\\t\\tadd: underMouse externalName\\n\\t\\t\\t\\ticon: (underMouse iconOrThumbnailOfSize: 16)\\n\\t\\t\\t\\tsubMenu: submenu\\n\\t\\t]\\n! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 7/28/2005 13:02'!\\naddTitleForHaloMenu: aMenu \\n\\taMenu\\n\\t\\taddTitle: self externalName\\n\\t\\ticon: (self iconOrThumbnailOfSize: (Preferences tinyDisplay ifFalse:[28] ifTrue:[16]))! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 10/13/2004 13:47'!\\naddYellowButtonMenuItemsTo: aMenu event: evt \\n\\t\\\"Populate aMenu with appropriate menu items for a \\n\\tyellow-button (context menu) click.\\\"\\n\\taMenu defaultTarget: self.\\n\\t\\\"\\\"\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\t\\\"\\\"\\n\\tself addModelYellowButtonItemsTo: aMenu event: evt.\\n\\t\\\"\\\"\\n\\tPreferences generalizedYellowButtonMenu\\n\\t\\tifFalse: [^ self].\\n\\t\\\"\\\"\\n\\tPreferences cmdGesturesEnabled\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'inspect' translated action: #inspect].\\n\\t\\\"\\\"\\n\\taMenu addLine.\\n\\tself world selectedObject == self\\n\\t\\tifTrue: [aMenu add: 'deselect' translated action: #removeHalo]\\n\\t\\tifFalse: [aMenu add: 'select' translated action: #addHalo].\\n\\t\\\"\\\"\\n\\t(self isWorldMorph\\n\\t\\t\\tor: [self mustBeBackmost]\\n\\t\\t\\tor: [self wantsToBeTopmost])\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'send to back' translated action: #goBehind.\\n\\t\\t\\taMenu add: 'bring to front' translated action: #comeToFront.\\n\\t\\t\\tself addEmbeddingMenuItemsTo: aMenu hand: evt hand].\\n\\t\\\"\\\"\\n\\tself isWorldMorph\\n\\t\\tifFalse: [\\\"\\\"\\n\\tSmalltalk\\n\\t\\tat: #NCAAConnectorMorph\\n\\t\\tifPresent: [:connectorClass | \\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'connect to' translated action: #startWiring.\\n\\t\\t\\taMenu addLine].\\n\\t\\\"\\\"\\n\\n\\t\\t\\tself isFullOnScreen\\n\\t\\t\\t\\tifFalse: [aMenu add: 'move onscreen' translated action: #goHome]].\\n\\t\\\"\\\"\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\tself addLayoutMenuItems: aMenu hand: evt hand.\\n\\t\\t\\t(owner notNil\\n\\t\\t\\t\\t\\tand: [owner isTextMorph])\\n\\t\\t\\t\\tifTrue: [self addTextAnchorMenuItems: aMenu hand: evt hand]].\\n\\t\\\"\\\"\\n\\tself isWorldMorph\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\tself addToggleItemsToHaloMenu: aMenu].\\n\\t\\\"\\\"\\n\\taMenu addLine.\\n\\tself isWorldMorph\\n\\t\\tifFalse: [aMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:].\\n\\t(self allStringsAfter: nil) isEmpty\\n\\t\\tifFalse: [aMenu add: 'copy text' translated action: #clipText].\\n\\t\\\"\\\"\\n\\tself addExportMenuItems: aMenu hand: evt hand.\\n\\t\\\"\\\"\\n\\t(Preferences noviceMode not\\n\\t\\t\\tand: [self isWorldMorph not])\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\taMenu addLine.\\n\\t\\t\\taMenu add: 'adhere to edge...' translated action: #adhereToEdge].\\n\\t\\\"\\\"\\n\\tself addCustomMenuItems: aMenu hand: evt hand! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 17:23'!\\nbuildYellowButtonMenu: aHand \\n\\t\\\"build the morph menu for the yellow button\\\"\\n\\t| menu |\\n\\tmenu := MenuMorph new defaultTarget: self.\\n\\tself addNestedYellowButtonItemsTo: menu event: ActiveEvent.\\n\\tMenuIcons decorateMenu: menu.\\n\\t^ menu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 4/4/2006 14:43'!\\nhasYellowButtonMenu\\n\\t\\\"Answer true if I have any items at all for a context (yellow \\n\\tbutton) menu.\\\"\\n\\t^ self wantsYellowButtonMenu\\n\\t\\t\\tor: [self models anySatisfy: [:each | each hasModelYellowButtonMenuItems]]! !\\n\\n!Morph methodsFor: 'menu' stamp: 'tak 7/17/2004 18:20'!\\nofferCostumeViewerMenu: aMenu\\n\\t\\\"do nothing\\\"! !\\n\\n!Morph methodsFor: 'menu' stamp: 'nk 3/10/2004 19:51'!\\noutermostOwnerWithYellowButtonMenu\\n\\t\\\"Answer me or my outermost owner that is willing to contribute menu items to a context menu.\\n\\tDon't include the world.\\\"\\n\\n\\t| outermost |\\n\\toutermost _ self outermostMorphThat: [ :ea |\\n\\t\\tea isWorldMorph not and: [ ea hasYellowButtonMenu ]].\\n\\t^outermost ifNil: [ self hasYellowButtonMenu ifTrue: [ self ] ifFalse: []] ! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/29/2004 13:26'!\\nstartWiring\\n\\tSmalltalk\\n\\t\\tat: #NCAAConnectorMorph\\n\\t\\tifPresent: [:connectorClass | connectorClass newCurvyArrow startWiringFrom: self] ! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 18:20'!\\nwantsYellowButtonMenu\\n\\t\\\"Answer true if the receiver wants a yellow button menu\\\"\\n\\tself\\n\\t\\tvalueOfProperty: #wantsYellowButtonMenu\\n\\t\\tifPresentDo: [:value | ^ value].\\n\\t\\\"\\\"\\n\\tself isInSystemWindow\\n\\t\\tifTrue: [^ false].\\\"\\\"\\n\\t(Preferences noviceMode\\n\\t\\t\\tand: [self isInDockingBar])\\n\\t\\tifTrue: [^ false].\\\"\\\"\\n\\t^ Preferences generalizedYellowButtonMenu! !\\n\\n!Morph methodsFor: 'menu' stamp: 'dgd 9/18/2004 18:35'!\\nwantsYellowButtonMenu: aBoolean \\n\\t\\\"Change the receiver to wants or not a yellow button menu\\\"\\n\\tself setProperty: #wantsYellowButtonMenu toValue: aBoolean! !\\n\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/6/2004 11:38'!\\nabsorbStateFromRenderer: aRenderer \\n\\t\\\"Transfer knownName, actorState, visible, and player info over from aRenderer, which was formerly imposed above me as a transformation shell but is now going away.\\\"\\n\\n\\t| current |\\n\\t(current _ aRenderer actorStateOrNil) ifNotNil:\\n\\t\\t[self actorState: current.\\n\\t\\taRenderer actorState: nil].\\n\\n\\t(current _ aRenderer knownName) ifNotNil:\\n\\t\\t[self setNameTo: current.\\n\\t\\taRenderer setNameTo: nil].\\n\\n\\t(current _ aRenderer player) ifNotNil:\\n\\t\\t[self player: current.\\n\\t\\tcurrent rawCostume: self.\\n\\t\\taRenderer player: nil].\\n\\n\\tself visible: aRenderer visible! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/27/2001 14:36'!\\naddAddHandMenuItemsForHalo: aMenu hand: aHandMorph\\n\\t\\\"The former charter of this method was to add halo menu items that pertained specifically to the hand. Over time this charter has withered, and most morphs reimplement this method simply to add their morph-specific menu items. So in the latest round, all other implementors in the standard image have been removed. However, this is left here as a hook for the benefit of existing code in client uses.\\\"\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 11/15/2003 19:25'!\\naddCopyItemsTo: aMenu\\n\\t\\\"Add copy-like items to the halo menu\\\"\\n\\n\\t| subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:.\\n\\tsubMenu add: 'copy text' translated action: #clipText.\\n\\tsubMenu add: 'copy Postscript' translated action: #clipPostscript.\\n\\tsubMenu add: 'print Postscript to file...' translated target: self selector: #printPSToFile.\\n\\taMenu add: 'copy & print...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/27/1998 03:44'!\\naddCustomHaloMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Add morph-specific items to the given menu which was invoked by the given hand from the halo. To get started, we defer to the counterpart method used with the option-menu, but in time we can have separate menu choices for halo-menus and for option-menus\\\"\\n\\n\\tself addCustomMenuItems: aMenu hand: aHandMorph! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/27/2001 07:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\t\\\"Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.\\\"\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 2/16/2004 13:29'!\\naddExportMenuItems: aMenu hand: aHandMorph\\n\\t\\\"Add export items to the menu\\\"\\n\\n\\taMenu ifNotNil:\\n\\t\\t[ | aSubMenu |\\n\\t\\taSubMenu _ MenuMorph new defaultTarget: self.\\n\\t\\taSubMenu add: 'BMP file' translated action: #exportAsBMP.\\n\\t\\taSubMenu add: 'GIF file' translated action: #exportAsGIF.\\n\\t\\taSubMenu add: 'JPEG file' translated action: #exportAsJPEG.\\n\\t\\taSubMenu add: 'PNG file' translated action: #exportAsPNG.\\n\\t\\taMenu add: 'export...' translated subMenu: aSubMenu]\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 16:44'!\\naddFillStyleMenuItems: aMenu hand: aHand\\n\\t\\\"Add the items for changing the current fill style of the Morph\\\"\\n\\t| menu |\\n\\tself canHaveFillStyles ifFalse:[^aMenu add: 'change color...' translated target: self action: #changeColor].\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tself fillStyle addFillStyleMenuItems: menu hand: aHand from: self.\\n\\tmenu addLine.\\n\\tmenu add: 'solid fill' translated action: #useSolidFill.\\n\\tmenu add: 'gradient fill' translated action: #useGradientFill.\\n\\tmenu add: 'bitmap fill' translated action: #useBitmapFill.\\n\\tmenu add: 'default fill' translated action: #useDefaultFill.\\n\\taMenu add: 'fill style' translated subMenu: menu.\\n\\t\\\"aMenu add: 'change color...' translated action: #changeColor\\\"! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/12/2005 23:13'!\\naddHaloActionsTo: aMenu\\n\\t\\\"Add items to aMenu representing actions requestable via halo\\\"\\n\\n\\t| subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu addTitle: self externalName.\\n\\tsubMenu addStayUpItemSpecial.\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'delete' translated action: #dismissViaHalo.\\n\\tsubMenu balloonTextForLastItem: 'Delete this object -- warning -- can be destructive!!' translated.\\n\\n\\tself maybeAddCollapseItemTo: subMenu.\\n\\tsubMenu add: 'grab' translated action: #openInHand.\\n\\tsubMenu balloonTextForLastItem: 'Pick this object up -- warning, since this removes it from its container, it can have adverse effects.' translated.\\n\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'resize' translated action: #resizeFromMenu.\\n\\tsubMenu balloonTextForLastItem: 'Change the size of this object' translated.\\n\\n\\tsubMenu add: 'duplicate' translated action: #maybeDuplicateMorph.\\n\\tsubMenu balloonTextForLastItem: 'Hand me a copy of this object' translated.\\n\\t\\\"Note that this allows access to the non-instancing duplicate even when this is a uniclass instance\\\"\\n\\n\\tself couldMakeSibling ifTrue:\\n\\t\\t[subMenu add: 'make a sibling' translated action: #handUserASibling.\\n\\t\\tsubMenu balloonTextForLastItem: 'Make a new sibling of this object and hand it to me' translated].\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'property sheet' translated target: self renderedMorph action: #openAPropertySheet.\\n\\tsubMenu balloonTextForLastItem: 'Open a property sheet for me. Allows changing lots of stuff at once.' translated.\\n\\n\\tsubMenu add: 'set color' translated target: self renderedMorph action: #changeColor.\\n\\tsubMenu balloonTextForLastItem: 'Change the color of this object' translated.\\n\\n\\tsubMenu add: 'viewer' translated target: self action: #beViewed.\\n\\tsubMenu balloonTextForLastItem: 'Open a Viewer that will allow everything about this object to be seen and controlled.' translated.\\n\\n\\tsubMenu add: 'tile browser' translated target: self action: #openInstanceBrowserWithTiles.\\n\\tsubMenu balloonTextForLastItem: 'Open a tool that will facilitate tile scripting of this object.' translated.\\n\\n\\tsubMenu add: 'hand me a tile' translated target: self action: #tearOffTile.\\n\\tsubMenu balloonTextForLastItem: 'Hand me a tile represting this object' translated.\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'inspect' translated target: self action: #inspect.\\n\\tsubMenu balloonTextForLastItem: 'Open an Inspector on this object' translated.\\n\\n\\taMenu add: 'halo actions...' translated subMenu: subMenu\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 3/2/2004 22:11'!\\naddMiscExtrasTo: aMenu\\n\\n\\t\\\"Add a submenu of miscellaneous extra items to the menu.\\\"\\n\\n\\n\\n\\t| realOwner realMorph subMenu |\\n\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\n\\t(self isWorldMorph not and: [(self renderedMorph isSystemWindow) not])\\n\\n\\t\\tifTrue: [subMenu add: 'put in a window' translated action: #embedInWindow].\\n\\n\\n\\n\\tself isWorldMorph ifFalse:\\n\\n\\t\\t[subMenu add: 'adhere to edge...' translated action: #adhereToEdge.\\n\\n\\t\\tsubMenu addLine].\\n\\n\\n\\n\\trealOwner _ (realMorph _ self topRendererOrSelf) owner.\\n\\n\\t(realOwner isKindOf: TextPlusPasteUpMorph) ifTrue:\\n\\n\\t\\t[subMenu add: 'GeeMail stuff...' translated subMenu: (realOwner textPlusMenuFor: realMorph)].\\n\\n\\n\\n\\tsubMenu\\n\\n\\t\\tadd: 'add mouse up action' translated action: #addMouseUpAction;\\n\\n\\t\\tadd: 'remove mouse up action' translated action: #removeMouseUpAction;\\n\\n\\t\\tadd: 'hand me tiles to fire this button' translated action: #handMeTilesToFire.\\n\\n\\tsubMenu addLine.\\n\\n\\tsubMenu add: 'arrowheads on pen trails...' translated action: #setArrowheads.\\n\\n\\tsubMenu addLine.\\n\\n\\n\\n\\tsubMenu defaultTarget: self topRendererOrSelf.\\n\\n\\tsubMenu add: 'draw new path' translated action: #definePath.\\n\\n\\tsubMenu add: 'follow existing path' translated action: #followPath.\\n\\n\\tsubMenu add: 'delete existing path' translated action: #deletePath.\\n\\n\\tsubMenu addLine.\\n\\n\\n\\n\\tself addGestureMenuItems: subMenu hand: ActiveHand.\\n\\n\\n\\n\\taMenu add: 'extras...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 1/6/2004 12:53'!\\naddPaintingItemsTo: aMenu hand: aHandMorph \\n\\t| subMenu movies |\\n\\tsubMenu := MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'repaint' translated action: #editDrawing.\\n\\tsubMenu add: 'set rotation center' translated action: #setRotationCenter.\\n\\tsubMenu add: 'reset forward-direction' translated\\n\\t\\taction: #resetForwardDirection.\\n\\tsubMenu add: 'set rotation style' translated action: #setRotationStyle.\\n\\tsubMenu add: 'erase pixels of color' translated\\n\\t\\taction: #erasePixelsOfColor:.\\n\\tsubMenu add: 'recolor pixels of color' translated\\n\\t\\taction: #recolorPixelsOfColor:.\\n\\tsubMenu add: 'reduce color palette' translated action: #reduceColorPalette:.\\n\\tsubMenu add: 'add a border around this shape...' translated\\n\\t\\taction: #addBorderToShape:.\\n\\tmovies := (self world rootMorphsAt: aHandMorph targetOffset) \\n\\t\\t\\t\\tselect: [:m | (m isKindOf: MovieMorph) or: [m isSketchMorph]].\\n\\tmovies size > 1 \\n\\t\\tifTrue: \\n\\t\\t\\t[subMenu add: 'insert into movie' translated action: #insertIntoMovie:].\\n\\taMenu add: 'painting...' translated subMenu: subMenu! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 4/12/2005 23:12'!\\naddPlayerItemsTo: aMenu\\n\\t\\\"Add player-related items to the menu if appropriate\\\"\\n\\n\\t| aPlayer subMenu |\\n\\tself couldMakeSibling ifFalse: [^ self].\\n\\taPlayer _ self topRendererOrSelf player.\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'make a sibling instance' translated target: self action: #makeNewPlayerInstance:.\\n\\tsubMenu balloonTextForLastItem: 'Makes another morph whose player is of the same class as this one. Both siblings will share the same scripts' translated.\\n\\n\\tsubMenu add: 'make multiple siblings...' translated target: self action: #makeMultipleSiblings:.\\n\\tsubMenu balloonTextForLastItem: 'Make any number of sibling instances all at once' translated.\\n\\n\\t(aPlayer belongsToUniClass and: [aPlayer class instanceCount > 1]) ifTrue:\\n\\t\\t[subMenu addLine.\\n\\t\\tsubMenu add: 'make all siblings look like me' translated target: self action: #makeSiblingsLookLikeMe:.\\n\\t\\tsubMenu balloonTextForLastItem: 'make all my sibling instances look like me.' translated.\\n\\n\\t\\tsubMenu add: 'bring all siblings to my location' translated target: self action: #bringAllSiblingsToMe:.\\n\\t\\tsubMenu balloonTextForLastItem: 'find all sibling instances and bring them to me' translated.\\n\\n\\t\\tsubMenu add: 'apply status to all siblngs' translated target: self action: #applyStatusToAllSiblings:.\\n\\t\\tsubMenu balloonTextForLastItem: 'apply the current status of all of my scripts to the scripts of all my siblings' translated].\\n\\n\\t\\tsubMenu add: 'indicate all siblings' translated target: self action: #indicateAllSiblings.\\n\\t\\tsubMenu balloonTextForLastItem: 'momentarily show, by flashing , all of my visible siblings.'.\\n\\n\\t\\taMenu add: 'siblings...' translated subMenu: subMenu\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:34'!\\naddStackItemsTo: aMenu\\n\\t\\\"Add stack-related items to the menu\\\"\\n\\n\\t| stackSubMenu |\\n\\tstackSubMenu _ MenuMorph new defaultTarget: self.\\n\\t(owner notNil and: [owner isStackBackground]) ifTrue:\\n\\t\\t[self isShared\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self couldHoldSeparateDataForEachInstance\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'Background field, shared value' translated target: self action: #putOnBackground.\\n\\t\\t\\t\\t\\t\\tstackSubMenu add: 'Background field, individual values' translated target: self action: #becomeSharedBackgroundField]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'put onto Background' translated target: self action: #putOnBackground]]\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[stackSubMenu add: 'remove from Background' translated target: self action: #putOnForeground.\\n\\t\\t\\t\\tself couldHoldSeparateDataForEachInstance ifTrue:\\n\\t\\t\\t\\t\\t[self holdsSeparateDataForEachInstance\\n\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'start holding separate data for each instance' translated target: self action: #makeHoldSeparateDataForEachInstance]\\n\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'stop holding separate data for each instance' translated target: self action: #stopHoldingSeparateDataForEachInstance].\\n\\t\\t\\t\\t\\t\\t\\tstackSubMenu add: 'be default value on new card' translated target: self action: #setAsDefaultValueForNewCard.\\n\\t\\t\\t\\t\\t\\t\\t(self hasProperty: #thumbnailImage)\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'stop using for reference thumbnail' translated target: self action: #stopUsingForReferenceThumbnail]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[stackSubMenu add: 'start using for reference thumbnail' translated target: self action: #startUsingForReferenceThumbnail]]].\\n\\t\\t\\t\\tstackSubMenu addLine].\\n\\n\\t(self isStackBackground) ifFalse:\\n\\t\\t[stackSubMenu add: 'be a card in an existing stack...' translated action: #insertAsStackBackground].\\n\\tstackSubMenu add: 'make an instance for my data' translated action: #abstractAModel.\\n\\t(self isStackBackground) ifFalse:\\n\\t\\t[stackSubMenu add: 'become a stack of cards' translated action: #wrapWithAStack].\\n\\taMenu add: 'stacks and cards...' translated subMenu: stackSubMenu\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 2/15/2004 08:19'!\\naddStandardHaloMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Add standard halo items to the menu\\\"\\n\\n\\t| unlockables |\\n\\n\\tself isWorldMorph ifTrue:\\n\\t\\t[^ self addWorldHaloMenuItemsTo: aMenu hand: aHandMorph].\\n\\n\\tself mustBeBackmost ifFalse:\\n\\t\\t[aMenu add: 'send to back' translated action: #goBehind.\\n\\t\\taMenu add: 'bring to front' translated action: #comeToFront.\\n\\t\\tself addEmbeddingMenuItemsTo: aMenu hand: aHandMorph.\\n\\t\\taMenu addLine].\\n\\n\\tself addFillStyleMenuItems: aMenu hand: aHandMorph.\\n\\tself addBorderStyleMenuItems: aMenu hand: aHandMorph.\\n\\tself addDropShadowMenuItems: aMenu hand: aHandMorph.\\n\\tself addLayoutMenuItems: aMenu hand: aHandMorph.\\n\\tself addHaloActionsTo: aMenu.\\n\\towner isTextMorph ifTrue:[self addTextAnchorMenuItems: aMenu hand: aHandMorph].\\n\\taMenu addLine.\\n\\tself addToggleItemsToHaloMenu: aMenu.\\n\\taMenu addLine.\\n\\tself addCopyItemsTo: aMenu.\\n\\tself addPlayerItemsTo: aMenu.\\n\\tself addExportMenuItems: aMenu hand: aHandMorph.\\n\\tself addStackItemsTo: aMenu.\\n\\tself addMiscExtrasTo: aMenu.\\n\\tPreferences noviceMode ifFalse:\\n\\t\\t[self addDebuggingItemsTo: aMenu hand: aHandMorph].\\n\\n\\taMenu addLine.\\n\\taMenu defaultTarget: self.\\n\\n\\taMenu addLine.\\n\\n\\tunlockables _ self submorphs select:\\n\\t\\t[:m | m isLocked].\\n\\tunlockables size == 1 ifTrue:\\n\\t\\t[aMenu\\n\\t\\t\\tadd: ('unlock \\\"{1}\\\"' translated format: unlockables first externalName)\\n\\t\\t\\taction: #unlockContents].\\n\\tunlockables size > 1 ifTrue:\\n\\t\\t[aMenu add: 'unlock all contents' translated action: #unlockContents.\\n\\t\\taMenu add: 'unlock...' translated action: #unlockOneSubpart].\\n\\n\\taMenu defaultTarget: aHandMorph.\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 4/3/2006 14:11'!\\naddToggleItemsToHaloMenu: aMenu\\n\\t\\\"Add standard true/false-checkbox items to the memu\\\"\\n\\n\\t#(\\n\\t\\t(resistsRemovalString toggleResistsRemoval 'whether I should be reistant to easy deletion via the pink X handle' true)\\n\\t\\t(stickinessString toggleStickiness 'whether I should be resistant to a drag done by mousing down on me' true)\\n\\t\\t(lockedString lockUnlockMorph 'when \\\"locked\\\", I am inert to all user interactions' true)\\n\\t\\t(hasClipSubmorphsString changeClipSubmorphs 'whether the parts of objects within me that are outside my bounds should be masked.' false)\\n\\t\\t(hasDirectionHandlesString changeDirectionHandles 'whether direction handles are shown with the halo' false)\\n\\t\\t(hasDragAndDropEnabledString changeDragAndDrop 'whether I am open to having objects dropped into me' false)\\n\\t)\\n\\t\\tselect:[:each | Preferences noviceMode not or:[each fourth]]\\n\\t\\tthenDo:\\n\\t\\t[:each |\\n\\t\\t\\taMenu addUpdating: each first action: each second.\\n\\t\\t\\taMenu balloonTextForLastItem: each third translated].\\n\\n\\tself couldHaveRoundedCorners ifTrue:\\n\\t\\t[aMenu addUpdating: #roundedCornersString action: #toggleCornerRounding.\\n\\t\\taMenu balloonTextForLastItem: 'whether my corners should be rounded' translated]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'wiz 2/14/2006 18:54'!\\naddWorldTargetSightingItems: aCustomMenu hand: aHandMorph\\n\\\"Use cursor to select a point on screen.\\nSet target from all possible morphs under cursor sight.\\\" \\n\\t\\n\\taCustomMenu addLine.\\n\\t\\n\\taCustomMenu add: 'sight target' translated action: #sightWorldTargets:.\\n\\t! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 10/17/2003 22:51'!\\nadhereToEdge\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\t#(top right bottom left - center - topLeft topRight bottomRight bottomLeft - none)\\n\\t\\tdo: [:each |\\n\\t\\t\\teach == #-\\n\\t\\t\\t\\tifTrue: [menu addLine]\\n\\t\\t\\t\\tifFalse: [menu add: each asString translated selector: #setToAdhereToEdge: argument: each]].\\n\\tmenu popUpEvent: self currentEvent in: self world! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 2/22/2003 14:26'!\\nadhereToEdge: edgeSymbol \\n\\t(owner isNil or: [owner isHandMorph]) ifTrue: [^self].\\n\\tself perform: (edgeSymbol , ':') asSymbol\\n\\t\\twithArguments: (Array with: (owner perform: edgeSymbol))! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/3/2000 00:14'!\\nadjustedCenter\\n\\t\\\"Provides a hook for objects to provide a reference point other than the receiver's center,for the purpose of centering a submorph under special circumstances, such as BalloonMorph\\\"\\n\\n\\t^ self center! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/3/2000 00:12'!\\nadjustedCenter: c\\n\\t\\\"Set the receiver's position based on the #adjustedCenter protocol for adhereToEdge. By default this simply sets the receiver's center. Though there are (at its inception anyway) no other implementors of this method, it is required in use with the #adhereToEdge when the centering of a submorph is to be with reference to a rectangle other than the receiver's center.\\\"\\n\\n\\tself center: c! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 10/5/2000 17:20'!\\nallMenuWordings\\n\\t| tempMenu |\\n\\ttempMenu _ self buildHandleMenu: self currentHand.\\n\\ttempMenu allMorphsDo: [:m | m step]. \\\"Get wordings current\\\"\\n\\t^ tempMenu allWordings! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 9/6/2000 18:45'!\\nchangeColor\\n\\t\\\"Change the color of the receiver -- triggered, e.g. from a menu\\\"\\n\\n\\tColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: self activeHand;\\n\\t\\ttarget: self;\\n\\t\\tselector: #fillStyle:;\\n\\t\\toriginalColor: self color;\\n\\t\\tputUpFor: self near: self fullBoundsInWorld! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 11/29/2001 19:57'!\\nchangeDirectionHandles\\n\\t^self wantsDirectionHandles: self wantsDirectionHandles not! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 11/2/2000 15:04'!\\nchangeDragAndDrop\\n\\t^self enableDragNDrop: self dragNDropEnabled not! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 12/17/1998 12:09'!\\nchooseNewGraphic\\n\\t\\\"Used by any morph that can be represented by a graphic\\\"\\n\\tself chooseNewGraphicCoexisting: false\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 09:58'!\\nchooseNewGraphicCoexisting: aBoolean \\n\\t\\\"Allow the user to choose a different form for her form-based morph\\\"\\n\\t| replacee aGraphicalMenu |\\n\\taGraphicalMenu := GraphicalMenu new\\n\\t\\t\\t\\tinitializeFor: self\\n\\t\\t\\t\\twithForms: self reasonableForms\\n\\t\\t\\t\\tcoexist: aBoolean.\\n\\taBoolean\\n\\t\\tifTrue: [self primaryHand attachMorph: aGraphicalMenu]\\n\\t\\tifFalse: [replacee := self topRendererOrSelf.\\n\\t\\t\\treplacee owner replaceSubmorph: replacee by: aGraphicalMenu]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/27/2000 17:34'!\\nchooseNewGraphicFromHalo\\n\\t\\\"Allow the user to select a changed graphic to replace the one in the receiver\\\"\\n\\n\\tself currentWorld abandonAllHalos.\\n\\tself chooseNewGraphicCoexisting: true\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 2/21/2000 15:21'!\\ncollapse\\n\\tCollapsedMorph new beReplacementFor: self! !\\n\\n!Morph methodsFor: 'menus'!\\ndefaultArrowheadSize\\n\\t\\n\\t^ self class defaultArrowheadSize! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 10/25/2000 23:17'!\\ndoMenuItem: menuString\\n\\t| aMenu anItem aNominalEvent aHand |\\n\\taMenu _ self buildHandleMenu: (aHand _ self currentHand).\\n\\taMenu allMorphsDo: [:m | m step]. \\\"Get wordings current\\\"\\n\\tanItem _ aMenu itemWithWording: menuString.\\n\\tanItem ifNil:\\n\\t\\t[^ self player scriptingError: 'Menu item not found: ', menuString].\\n\\taNominalEvent _ MouseButtonEvent new\\n\\t\\tsetType: #mouseDown\\n\\t\\tposition: anItem bounds center\\n\\t\\twhich: 4 \\\"red\\\"\\n\\t\\tbuttons: 4 \\\"red\\\"\\n\\t\\thand: aHand\\n\\t\\tstamp: nil.\\n\\tanItem invokeWithEvent: aNominalEvent! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:50'!\\nexportAsBMP\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.bmp'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tself imageForm writeBMPfileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:50'!\\nexportAsGIF\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.gif'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tGIFReadWriter putForm: self imageForm onFileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:51'!\\nexportAsJPEG\\n\\t\\\"Export the receiver's image as a JPEG\\\"\\n\\n\\t| fName |\\n\\tfName _ FillInTheBlank request: 'Please enter the name' translated initialAnswer: self externalName,'.jpeg'.\\n\\tfName isEmpty ifTrue: [^ self].\\n\\tself imageForm writeJPEGfileNamed: fName! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 17:51'!\\nexportAsPNG\\n\\t| fName |\\n\\tfName _ FillInTheBlank request:'Please enter the name' translated initialAnswer: self externalName,'.png'.\\n\\tfName isEmpty ifTrue:[^self].\\n\\tPNGReadWriter putForm: self imageForm onFileNamed: fName.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:23'!\\nhasDirectionHandlesString\\n\\t^ (self wantsDirectionHandles\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'direction handles' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:24'!\\nhasDragAndDropEnabledString\\n\\t\\\"Answer a string to characterize the drag & drop status of the \\n\\treceiver\\\"\\n\\t^ (self dragNDropEnabled\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'accept drops' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 4/3/2006 14:09'!\\nhelpButton\\n\\t\\\"Answer a button whose action would be to put up help concerning the receiver\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton\\n\\t\\ttarget: self;\\n\\t\\tcolor: ColorTheme current helpColor;\\n\\t\\tborderColor: ColorTheme current helpColor muchDarker;\\n\\t\\tborderWidth: 1;\\n\\t\\tlabel: '?' translated font: Preferences standardButtonFont;\\n\\t\\tactionSelector: #presentHelp;\\n\\t\\tsetBalloonText: 'click here for help' translated.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/27/2005 21:01'!\\ninspectInMorphic\\n\\tself currentHand attachMorph: ((ToolSet inspect: self) extent: 300@200)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/27/2005 21:01'!\\ninspectInMorphic: evt\\n\\tevt hand attachMorph: ((ToolSet inspect: self) extent: 300@200)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:20'!\\nlockedString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\t'locked' status\\\"\\n\\t^ (self isLocked\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'be locked' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 9/21/2000 22:50'!\\nlockUnlockMorph\\n\\t\\\"If the receiver is locked, unlock it; if unlocked, lock it\\\"\\n\\n\\tself isLocked ifTrue: [self unlock] ifFalse: [self lock]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/29/1999 15:34'!\\nmakeNascentScript\\n\\t^ self notYetImplemented! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:15'!\\nmaybeAddCollapseItemTo: aMenu\\n\\t\\\"If appropriate, add a collapse item to the given menu\\\"\\n\\n\\t| anOwner |\\n\\t(anOwner _ self topRendererOrSelf owner) ifNotNil:\\n\\t\\t\\t[anOwner isWorldMorph ifTrue:\\n\\t\\t\\t\\t[aMenu add: 'collapse' translated target: self action: #collapse]]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/22/1999 12:13'!\\nmenuItemAfter: menuString\\n\\t| allWordings |\\n\\tallWordings _ self allMenuWordings.\\n\\t^ allWordings atWrap: ((allWordings indexOf: menuString) + 1)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 11/22/1999 12:14'!\\nmenuItemBefore: menuString\\n\\t| allWordings |\\n\\tallWordings _ self allMenuWordings.\\n\\t^ allWordings atWrap: ((allWordings indexOf: menuString) - 1)! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 9/22/2004 20:30'!\\nmodel\\n\\t^ nil ! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 6/12/2001 21:08'!\\npresentHelp\\n\\t\\\"Present a help message if there is one available\\\"\\n\\n\\tself inform: 'Sorry, no help has been\\nprovided here yet.'! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 18:03'!\\nprintPSToFileNamed: aString \\n\\t\\\"Ask the user for a filename and print this morph as postscript.\\\"\\n\\t| fileName rotateFlag psCanvasType psExtension |\\n\\tfileName := aString asFileName.\\n\\tpsCanvasType _ PostscriptCanvas defaultCanvasType.\\n\\tpsExtension _ psCanvasType defaultExtension.\\n\\tfileName := FillInTheBlank request: (String streamContents: [ :s |\\n\\t\\ts nextPutAll: ('File name? (\\\"{1}\\\" will be added to end)' translated format: {psExtension})])\\n\\t\\t\\tinitialAnswer: fileName.\\n\\tfileName isEmpty\\n\\t\\tifTrue: [^ Beeper beep].\\n\\t(fileName endsWith: psExtension)\\n\\t\\tifFalse: [fileName := fileName , psExtension].\\n\\trotateFlag := ((PopUpMenu labels: 'portrait (tall)\\nlandscape (wide)' translated)\\n\\t\\t\\t\\tstartUpWithCaption: 'Choose orientation...' translated)\\n\\t\\t\\t\\t= 2.\\n\\t((FileStream newFileNamed: fileName asFileName) converter: TextConverter defaultSystemConverter)\\n\\t\\tnextPutAll: (psCanvasType morphAsPostscript: self rotated: rotateFlag);\\n\\t\\t close! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/27/2000 06:39'!\\nputOnBackground\\n\\t\\\"Place the receiver, formerly private to its card, onto the shared background. If the receiver needs data carried on its behalf by the card, such data will be represented on every card.\\\"\\n\\n\\t(self hasProperty: #shared) ifTrue: [^ self]. \\\"Already done\\\"\\n\\n\\tself setProperty: #shared toValue: true.\\n\\tself stack ifNotNil: [self stack reassessBackgroundShape]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 9/5/2003 18:25'!\\nputOnForeground\\n\\t\\\"Place the receiver, formerly on the background, onto the foreground. If the receiver needs data carried on its behalf by the card, those data will be lost, so in this case get user confirmation before proceeding.\\\"\\n\\n\\tself holdsSeparateDataForEachInstance \\\"later add the refinement of not putting up the following confirmer if only a single instance of the current background's uniclass exists\\\"\\n\\t\\tifTrue:\\n\\t\\t\\t[self confirm: 'Caution -- every card of this background\\nformerly had its own value for this\\nitem. If you put it on the foreground,\\nthe values of this item on all other\\ncards will be lost' translated\\n\\t\\t\\t\\torCancel: [^ self]].\\n\\n\\tself removeProperty: #shared.\\n\\tself stack reassessBackgroundShape.\\n\\t\\\"still work to be done here!!\\\"! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 22:42'!\\nreasonableBitmapFillForms\\n\\t\\\"Answer an OrderedCollection of forms that could be used to replace my bitmap fill, with my current form first.\\\"\\n\\t| reasonableForms myGraphic |\\n\\treasonableForms := self class allSketchMorphForms.\\n\\treasonableForms addAll: Imports default images.\\n\\treasonableForms addAll: (BitmapFillStyle allSubInstances collect:[:f| f form]).\\n\\treasonableForms\\n\\t\\tremove: (myGraphic := self fillStyle form)\\n\\t\\tifAbsent: [].\\n\\treasonableForms := reasonableForms asOrderedCollection.\\n\\treasonableForms addFirst: myGraphic.\\n\\t^reasonableForms! !\\n\\n!Morph methodsFor: 'menus' stamp: 'nk 6/12/2004 09:55'!\\nreasonableForms\\n\\t\\\"Answer an OrderedCollection of forms that could be used to replace my form, with my current form first.\\\"\\n\\t| reasonableForms myGraphic |\\n\\treasonableForms := self class allSketchMorphForms.\\n\\treasonableForms addAll: Imports default images.\\n\\treasonableForms\\n\\t\\tremove: (myGraphic := self form)\\n\\t\\tifAbsent: [].\\n\\treasonableForms := reasonableForms asOrderedCollection.\\n\\treasonableForms addFirst: myGraphic.\\n\\t^reasonableForms! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:36'!\\nresetForwardDirection\\n\\tself forwardDirection: 0.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:18'!\\nresistsRemovalString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\t'resistsRemoval' status\\\"\\n\\t^ (self resistsRemoval\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>']), 'resist being deleted' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'yo 2/17/2005 16:58'!\\nsetArrowheads\\n\\t\\\"Let the user edit the size of arrowheads for this object\\\"\\n\\n\\t| aParameter result |\\n\\taParameter _ self renderedMorph valueOfProperty: #arrowSpec ifAbsent:\\n\\t\\t[Preferences parameterAt: #arrowSpec ifAbsent: [5 @ 4]].\\n\\tresult _ Morph obtainArrowheadFor: 'Head size for arrowheads: ' translated defaultValue: aParameter asString.\\n\\tresult ifNotNil:\\n\\t\\t\\t[self renderedMorph setProperty: #arrowSpec toValue: result]\\n\\t\\tifNil:\\n\\t\\t\\t[Beeper beep]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:15'!\\nsetRotationCenter\\n\\t| p |\\n\\tself world displayWorld.\\n\\tCursor crossHair showWhile:\\n\\t\\t[p _ Sensor waitButton].\\n\\tSensor waitNoButton.\\n\\tself setRotationCenterFrom: (self transformFromWorld globalPointToLocal: p).\\n\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'ar 9/22/2000 20:14'!\\nsetRotationCenterFrom: aPoint\\n\\tself rotationCenter: (aPoint - self bounds origin) / self bounds extent asFloatPoint.! !\\n\\n!Morph methodsFor: 'menus' stamp: 'di 12/21/2000 17:18'!\\nsetToAdhereToEdge: anEdge\\n\\tanEdge ifNil: [^ self].\\n\\tanEdge == #none ifTrue: [^ self removeProperty: #edgeToAdhereTo].\\n\\tself setProperty: #edgeToAdhereTo toValue: anEdge.\\n! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 8/30/1998 09:42'!\\nsnapToEdgeIfAppropriate\\n\\t| edgeSymbol oldBounds aWorld |\\n\\t(edgeSymbol _ self valueOfProperty: #edgeToAdhereTo) ifNotNil:\\n\\t\\t[oldBounds _ bounds.\\n\\t\\tself adhereToEdge: edgeSymbol.\\n\\t\\tbounds ~= oldBounds ifTrue: [(aWorld _ self world) ifNotNil: [aWorld viewBox ifNotNil:\\n\\t\\t\\t[aWorld displayWorld]]]]! !\\n\\n!Morph methodsFor: 'menus' stamp: 'dgd 8/30/2003 20:19'!\\nstickinessString\\n\\t\\\"Answer the string to be shown in a menu to represent the \\n\\tstickiness status\\\"\\n\\t^ (self isSticky\\n\\t\\tifTrue: ['<yes>']\\n\\t\\tifFalse: ['<no>'])\\n\\t\\t, 'resist being picked up' translated! !\\n\\n!Morph methodsFor: 'menus' stamp: 'sw 10/6/2004 12:16'!\\ntransferStateToRenderer: aRenderer\\n\\t\\\"Transfer knownName, actorState, visible, and player info over to aRenderer, which is being imposed above me as a transformation shell\\\"\\n\\n\\t| current |\\n\\t(current _ self actorStateOrNil) ifNotNil:\\n\\t\\t[aRenderer actorState: current.\\n\\t\\tself actorState: nil].\\n\\n\\t(current _ self knownName) ifNotNil:\\n\\t\\t[aRenderer setNameTo: current.\\n\\t\\tself setNameTo: nil].\\n\\n\\t(current _ self player) ifNotNil:\\n\\t\\t[aRenderer player: current.\\n\\t\\tself player rawCostume: aRenderer.\\n\\t\\t\\\"NB player is redundantly pointed to in the extension of both the renderer and the rendee; this is regrettable but many years ago occasionally people tried to make that clean but always ran into problems iirc\\\"\\n\\t\\t\\\"self player: nil\\\"].\\n\\n\\taRenderer simplySetVisible: self visible\\n\\n\\n\\n \\n\\n\\t\\t! !\\n\\n!Morph methodsFor: 'menus' stamp: 'RAA 11/14/2000 13:46'!\\nuncollapseSketch\\n\\n\\t| uncollapsedVersion w whomToDelete |\\n\\n\\t(w _ self world) ifNil: [^self].\\n\\tuncollapsedVersion _ self valueOfProperty: #uncollapsedMorph.\\n\\tuncollapsedVersion ifNil: [^self].\\n\\twhomToDelete _ self valueOfProperty: #collapsedMorphCarrier.\\n\\tuncollapsedVersion setProperty: #collapsedPosition toValue: whomToDelete position.\\n\\n\\twhomToDelete delete.\\n\\tw addMorphFront: uncollapsedVersion.\\n\\n! !\\n\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 9/18/2004 16:24'!\\naddEmbeddingMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Construct a menu offerring embed targets for the receiver. If the incoming menu is is not degenerate, add the constructed menu as a submenu; in any case, answer the embed-target menu\\\"\\n\\n\\t| menu potentialEmbeddingTargets |\\n\\n\\tpotentialEmbeddingTargets := self potentialEmbeddingTargets.\\n\\tpotentialEmbeddingTargets size > 1 ifFalse:[^ self].\\n\\n\\tmenu := MenuMorph new defaultTarget: self.\\n\\n\\tpotentialEmbeddingTargets reverseDo: [:m | \\n\\t\\t\\tmenu\\n\\t\\t\\t\\tadd: (m knownName ifNil:[m class name asString])\\n\\t\\t\\t\\ttarget: m\\n\\t\\t\\t\\tselector: #addMorphFrontFromWorldPosition:\\n\\t\\t\\t\\targument: self topRendererOrSelf.\\n\\n\\t\\t\\tmenu lastItem icon: (m iconOrThumbnailOfSize: 16).\\n\\n\\t\\t\\tself owner == m ifTrue:[menu lastItem emphasis: 1].\\n\\t\\t].\\n\\n\\taMenu add:'embed into' translated subMenu: menu.\\n\\n\\t^ menu! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/29/2001 02:50'!\\napplyStatusToAllSiblings: evt\\n\\t\\\"Apply the statuses of all my scripts to the script status of all my siblings\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPlayer instantiatedUserScriptsDo: \\n\\t\\t[:aScriptInstantiation | aScriptInstantiation assignStatusToAllSiblings]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:51'!\\nbeThisWorldsModel\\n\\n\\tself world setModel: self.\\n\\tself model: nil slotName: nil.\\t\\\"A world's model cannot have another model\\\"! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'yo 3/15/2005 14:45'!\\nblueButtonDown: anEvent\\n\\t\\\"Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph.\\\"\\n\\t| h tfm doNotDrag |\\n\\th _ anEvent hand halo.\\n\\t\\\"Prevent wrap around halo transfers originating from throwing the event back in\\\"\\n\\tdoNotDrag _ false.\\n\\th ifNotNil:[\\n\\t\\t(h innerTarget == self) ifTrue:[doNotDrag _ true].\\n\\t\\t(h innerTarget hasOwner: self) ifTrue:[doNotDrag _ true].\\n\\t\\t(self hasOwner: h target) ifTrue:[doNotDrag _ true]].\\n\\n\\ttfm _ (self transformedFrom: nil) inverseTransformation.\\n\\n\\t\\\"cmd-drag on flexed morphs works better this way\\\"\\n\\th _ self addHalo: (anEvent transformedBy: tfm).\\n\\th ifNil: [^ self].\\n\\tdoNotDrag ifTrue:[^self].\\n\\t\\\"Initiate drag transition if requested\\\"\\n\\tanEvent hand \\n\\t\\twaitForClicksOrDrag: h\\n\\t\\tevent: (anEvent transformedBy: tfm)\\n\\t\\tselectors: { nil. nil. nil. #dragTarget:. }\\n\\t\\tthreshold: 5.\\n\\t\\\"Pass focus explicitly here\\\"\\n\\tanEvent hand newMouseFocus: h.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 9/15/2000 20:25'!\\nblueButtonUp: anEvent\\n\\t\\\"Ignored. Theoretically we should never get here since control is transferred to the halo on #blueButtonDown: but subclasses may implement this differently.\\\"! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/19/2001 18:10'!\\nbringAllSiblingsToMe: evt\\n\\t\\\"bring all siblings of the receiver's player found in the same container to the receiver's location.\\\"\\n\\n\\t| aPlayer aPosition aContainer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPosition _ self topRendererOrSelf position.\\n\\taContainer _ self topRendererOrSelf owner.\\n\\t(aPlayer class allInstances copyWithout: aPlayer) do:\\n\\t\\t[:each |\\n\\t\\t\\t(aContainer submorphs includes: each costume) ifTrue:\\n\\t\\t\\t\\t[each costume position: aPosition]]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 9/18/2004 17:23'!\\nbuildHandleMenu: aHand\\n\\t\\\"Build the morph menu for the given morph's halo's menu handle. This menu has two sections. The first section contains commands that are interpreted by the hand; the second contains commands provided by the target morph. This method allows the morph to decide which items should be included in the hand's section of the menu.\\\"\\n\\n\\t| menu |\\n\\n\\t(Preferences generalizedYellowButtonMenu\\n\\t\\t\\tand: [Preferences noviceMode])\\n\\t\\tifTrue: [^ self buildYellowButtonMenu: aHand].\\n\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addStayUpItem.\\n\\tmenu addLine.\\n\\tself addStandardHaloMenuItemsTo: menu hand: aHand.\\n\\tmenu defaultTarget: aHand.\\n\\tself addAddHandMenuItemsForHalo: menu hand: aHand.\\n\\tmenu defaultTarget: self.\\n\\tself addCustomHaloMenuItems: menu hand: aHand.\\n\\tmenu defaultTarget: aHand.\\n\\t^ menu\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'dgd 11/15/2003 19:29'!\\nbuildMetaMenu: evt\\n\\t\\\"Build the morph menu. This menu has two sections. The first section contains commands that are handled by the hand; the second contains commands handled by the argument morph.\\\"\\n\\t| menu |\\n\\tmenu _ MenuMorph new defaultTarget: self.\\n\\tmenu addStayUpItem.\\n\\tmenu add: 'grab' translated action: #grabMorph:.\\n\\tmenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:.\\n\\tself maybeAddCollapseItemTo: menu.\\n\\tmenu add: 'delete' translated action: #dismissMorph:.\\n\\tmenu addLine.\\n\\tmenu add: 'copy text' translated action: #clipText.\\n\\tmenu add: 'copy Postscript' translated action: #clipPostscript.\\n\\tmenu add: 'print Postscript to file...' translated action: #printPSToFile.\\n\\tmenu addLine.\\n\\tmenu add: 'go behind' translated action: #goBehind.\\n\\tmenu add: 'add halo' translated action: #addHalo:.\\n\\tmenu add: 'duplicate' translated action: #maybeDuplicateMorph:.\\n\\n\\tself addEmbeddingMenuItemsTo: menu hand: evt hand.\\n\\n\\tmenu add: 'resize' translated action: #resizeMorph:.\\n\\t\\\"Give the argument control over what should be done about fill styles\\\"\\n\\tself addFillStyleMenuItems: menu hand: evt hand.\\n\\tself addDropShadowMenuItems: menu hand: evt hand.\\n\\tself addLayoutMenuItems: menu hand: evt hand.\\n\\tmenu addUpdating: #hasClipSubmorphsString target: self selector: #changeClipSubmorphs argumentList: #().\\n\\tmenu addLine.\\n\\n\\t(self morphsAt: evt position) size > 1 ifTrue:\\n\\t\\t[menu add: 'submorphs...' translated\\n\\t\\t\\ttarget: self\\n\\t\\t\\tselector: #invokeMetaMenuAt:event:\\n\\t\\t\\targument: evt position].\\n\\tmenu addLine.\\n\\tmenu add: 'inspect' translated selector: #inspectAt:event: argument: evt position.\\n\\tmenu add: 'explore' translated action: #explore.\\n\\tmenu add: 'browse hierarchy' translated action: #browseHierarchy.\\n\\tmenu add: 'make own subclass' translated action: #subclassMorph.\\n\\tmenu addLine.\\n\\tmenu add: 'set variable name...' translated action: #choosePartName.\\n\\t(self isMorphicModel) ifTrue:\\n\\t\\t[menu add: 'save morph as prototype' translated action: #saveAsPrototype.\\n\\t\\t(self ~~ self world modelOrNil) ifTrue:\\n\\t\\t\\t [menu add: 'become this world''s model' translated action: #beThisWorldsModel]].\\n\\tmenu add: 'save morph in file' translated action: #saveOnFile.\\n\\t(self hasProperty: #resourceFilePath)\\n\\t\\tifTrue: [((self valueOfProperty: #resourceFilePath) endsWith: '.morph')\\n\\t\\t\\t\\tifTrue: [menu add: 'save as resource' translated action: #saveAsResource].\\n\\t\\t\\t\\tmenu add: 'update from resource' translated action: #updateFromResource]\\n\\t\\tifFalse: [menu add: 'attach to resource' translated action: #attachToResource].\\n\\tmenu add: 'show actions' translated action: #showActions.\\n\\tmenu addLine.\\n\\tself addDebuggingItemsTo: menu hand: evt hand.\\n\\n\\tself addCustomMenuItems: menu hand: evt hand.\\n\\t^ menu\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 18:54'!\\nchangeColorTarget: anObject selector: aSymbol originalColor: aColor hand: aHand\\n\\t\\\"Put up a color picker for changing some kind of color. May be modal or modeless, depending on #modalColorPickers setting\\\"\\n\\tself flag: #arNote. \\\"Simplify this due to anObject == self for almost all cases\\\"\\n\\t^ ColorPickerMorph new\\n\\t\\tchoseModalityFromPreference;\\n\\t\\tsourceHand: aHand;\\n\\t\\ttarget: anObject;\\n\\t\\tselector: aSymbol;\\n\\t\\toriginalColor: aColor;\\n\\t\\tputUpFor: anObject near: (anObject isMorph\\n\\t\\t\\t\\t\\tifTrue:\\t [Rectangle center: self position extent: 20]\\n\\t\\t\\t\\t\\tifFalse: [anObject == self world\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [anObject viewBox bottomLeft + (20@-20) extent: 200]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [anObject fullBoundsInWorld]]);\\n\\t\\tyourself! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:44'!\\ncopyToPasteBuffer: evt\\n\\tself okayToDuplicate ifTrue:[evt hand copyToPasteBuffer: self].! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'mir 3/17/2006 18:02'!\\ndismissMorph\\n\\t\\\"This is called from an explicit halo destroy/delete action.\\\"\\n\\n\\t| w |\\n\\tw _ self world ifNil:[^self].\\n\\tw abandonAllHalos; stopStepping: self.\\n\\tself delete! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'mir 3/17/2006 18:01'!\\ndismissMorph: evt\\n\\tself dismissMorph! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 2/19/2006 12:41'!\\nduplicateMorphImage: evt \\n\\t\\\"Make and return a imageMorph of the receiver's argument imageForm\\\"\\n\\t| dup |\\n\\tdup := self asSnapshotThumbnail withSnapshotBorder.\\n\\tdup bounds: self bounds.\\n\\tevt hand grabMorph: dup from: owner.\\n\\t\\\"duplicate was ownerless so use #grabMorph:from: here\\\"\\n\\t^ dup! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 11/4/2000 17:56'!\\nduplicateMorph: evt\\n\\t\\\"Make and return a duplicate of the receiver's argument\\\"\\n\\t| dup |\\n\\tdup _ self duplicate.\\n\\tevt hand grabMorph: dup from: owner. \\\"duplicate was ownerless so use #grabMorph:from: here\\\"\\n\\t^dup! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/7/2000 20:53'!\\nembedInto: evt\\n\\t\\\"Embed the receiver into some other morph\\\"\\n\\t| menu target |\\n\\tmenu _ CustomMenu new.\\n\\tself potentialEmbeddingTargets do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUpWithCaption: ('Place ', self externalName, ' in...').\\n\\ttarget ifNil:[^self].\\n\\ttarget addMorphFront: self fromWorldPosition: self positionInWorld.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/6/2000 16:37'!\\ngrabMorph: evt\\n\\n\\tevt hand grabMorph: self! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/7/2000 18:44'!\\nhandlerForBlueButtonDown: anEvent\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event.\\n\\tNote: Halos handle blue button events themselves so we will only be asked if there is currently no halo on top of us.\\\"\\n\\tself wantsHaloFromClick ifFalse:[^nil].\\n\\tanEvent handler ifNil:[^self].\\n\\tanEvent handler isPlayfieldLike ifTrue:[^self]. \\\"by default exclude playfields\\\"\\n\\t(anEvent shiftPressed)\\n\\t\\tifFalse:[^nil] \\\"let outer guy have it\\\"\\n\\t\\tifTrue:[^self] \\\"let me have it\\\"\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/12/2000 17:07'!\\nhandlerForMetaMenu: evt\\n\\t\\\"Return the prospective handler for invoking the meta menu. By default, the top-most morph in the innermost world gets this menu\\\"\\n\\tself isWorldMorph ifTrue:[^self].\\n\\tevt handler ifNotNil:[evt handler isWorldMorph ifTrue:[^self]].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'yo 2/12/2005 15:25'!\\nindicateAllSiblings\\n\\t\\\"Indicate all the receiver and all its siblings by flashing momentarily.\\\"\\n\\n\\t| aPlayer allBoxes |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [^ self \\\"error: 'not uniclass'\\\"].\\n\\tallBoxes _ aPlayer class allInstances\\n\\t\\tselect: [:m | m costume world == ActiveWorld]\\n\\t\\tthenCollect: [:m | m costume boundsInWorld].\\n\\n\\t5 timesRepeat:\\n\\t\\t[Display flashAll: allBoxes andWait: 120]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/10/2000 14:09'!\\ninspectAt: aPoint event: evt\\n\\t| menu morphs target |\\n\\tmenu _ CustomMenu new.\\n\\tmorphs _ self morphsAt: aPoint.\\n\\t(morphs includes: self) ifFalse:[morphs _ morphs copyWith: self].\\n\\tmorphs do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUpWithCaption: ('inspect whom?\\n(deepest at top)').\\n\\ttarget ifNil:[^self].\\n\\ttarget inspectInMorphic: evt! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/10/2000 14:26'!\\ninvokeMetaMenuAt: aPoint event: evt\\n\\t| menu morphs target |\\n\\tmenu _ CustomMenu new.\\n\\tmorphs _ self morphsAt: aPoint.\\n\\t(morphs includes: self) ifFalse:[morphs _ morphs copyWith: self].\\n\\tmorphs size = 1 ifTrue:[morphs first invokeMetaMenu: evt].\\n\\tmorphs do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\ttarget _ menu startUp.\\n\\ttarget ifNil:[^self].\\n\\ttarget invokeMetaMenu: evt! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'fc 4/27/2004 21:54'!\\ninvokeMetaMenu: evt\\n\\t| menu |\\n\\tmenu _ self buildMetaMenu: evt.\\n\\tmenu addTitle: self externalName.\\n\\tself world ifNotNil: [\\n\\t\\tmenu popUpEvent: evt in: self world\\n\\t]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 4/12/2005 23:09'!\\nmakeMultipleSiblings: evt\\n\\t\\\"Make multiple siblings, first prompting the user for how many\\\"\\n\\n\\t| result |\\n\\tself topRendererOrSelf couldMakeSibling ifFalse: [^ Beeper beep].\\n\\tresult _ FillInTheBlank request: 'how many siblings do you want?' translated initialAnswer: '2'.\\n\\tresult isEmptyOrNil ifTrue: [^ self].\\n\\tresult first isDigit ifFalse: [^ Beeper beep].\\n\\tself topRendererOrSelf makeSiblings: result asInteger.! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 19:20'!\\nmakeNewPlayerInstance: evt\\n\\t\\\"Make a duplicate of the receiver's argument. This is called only where the argument has an associated Player as its costumee, and the intent here is to make another instance of the same uniclass as the donor Player itself. Much works, but there are flaws so this shouldn't be used without recognizing the risks\\\"\\n\\n\\tevt hand attachMorph: self usableSiblingInstance! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/12/2001 22:47'!\\nmakeSiblingsLookLikeMe: evt\\n\\t\\\"Make all my siblings wear the same costume that I am wearing.\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self topRendererOrSelf player) belongsToUniClass ifFalse: [self error: 'not uniclass'].\\n\\taPlayer class allInstancesDo:\\n\\t\\t[:anInstance | anInstance == aPlayer ifFalse:\\n\\t\\t\\t[anInstance wearCostumeOf: aPlayer]]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 1/29/2001 17:11'!\\nmakeSiblings: count\\n\\t\\\"Make multiple sibling, and return the list\\\"\\n\\n\\t| aPosition anInstance listOfNewborns |\\n\\taPosition _ self position.\\n\\tlistOfNewborns _ (1 to: count asInteger) asArray collect: \\n\\t\\t[:anIndex |\\n\\t\\t\\tanInstance _ self usableSiblingInstance.\\n\\t\\t\\towner addMorphFront: anInstance.\\n\\t\\t\\taPosition _ aPosition + (10@10).\\n\\t\\t\\tanInstance position: aPosition.\\n\\t\\t\\tanInstance].\\n\\tself currentWorld startSteppingSubmorphsOf: self topRendererOrSelf owner.\\n\\t^ listOfNewborns! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 4/19/2005 14:55'!\\nmaybeDuplicateMorph\\n\\t\\\"Maybe duplicate the morph\\\"\\n\\n\\tself okayToDuplicate ifTrue:\\n\\t\\t[self topRendererOrSelf duplicate openInHand]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 17:32'!\\nmaybeDuplicateMorph: evt\\n\\tself okayToDuplicate ifTrue:[^self duplicateMorph: evt]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'RAA 2/19/2001 16:52'!\\nopenAPropertySheet\\n\\n\\tObjectPropertiesMorph basicNew\\n\\t\\ttargetMorph: self;\\n\\t\\tinitialize;\\n\\t\\topenNearTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'RAA 3/15/2001 12:56'!\\nopenATextPropertySheet\\n\\n\\t\\\"should only be sent to morphs that are actually supportive\\\"\\n\\n\\tTextPropertiesMorph basicNew\\n\\t\\ttargetMorph: self;\\n\\t\\tinitialize;\\n\\t\\topenNearTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 1/2/2005 01:06'!\\npotentialEmbeddingTargets\\n\\t\\\"Return the potential targets for embedding the receiver\\\"\\n\\n\\t| oneUp topRend |\\n\\t(oneUp _ (topRend _ self topRendererOrSelf) owner) ifNil:[^#()].\\n\\t^ (oneUp morphsAt: topRend referencePosition behind: topRend unlocked: true) select:\\n\\t\\t[:m | m isFlexMorph not]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/17/2004 22:17'!\\npotentialTargets\\n\\t\\\"Return the potential targets for the receiver.\\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\towner ifNil:[^#()].\\n\\t^owner morphsAt: self referencePosition behind: self unlocked: true not! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 02:46'!\\npotentialTargetsAt: aPoint \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\towner\\n\\t\\tifNil: [^ #()].\\n\\t^ owner\\n\\t\\tmorphsAt: aPoint\\n\\t\\t! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'sw 11/27/2001 14:59'!\\nresizeFromMenu\\n\\t\\\"Commence an interaction that will resize the receiver\\\"\\n\\n\\tself resizeMorph: ActiveEvent! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'st 9/14/2004 12:30'!\\nresizeMorph: evt\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo: [:newPoint | \\n\\t\\tself extent: (self griddedPoint: newPoint) - self bounds topLeft].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:50'!\\nsaveAsPrototype\\n\\t(SelectionMenu confirm: 'Make this morph the prototype for ', self class printString, '?')\\n\\t\\tifFalse: [^ self].\\n\\tself class prototype: self.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 9/27/2005 20:29'!\\nshowActions\\n\\t\\\"Put up a message list browser of all the code that this morph \\n\\twould run for mouseUp, mouseDown, mouseMove, mouseEnter, \\n\\tmouseLeave, and \\n\\tmouseLinger. tk 9/13/97\\\"\\n\\t| list cls selector adder |\\n\\tlist := SortedCollection new.\\n\\tadder := [:mrClass :mrSel | list\\n\\t\\t\\t\\tadd: (MethodReference new setStandardClass: mrClass methodSymbol: mrSel)].\\n\\t\\\"the eventHandler\\\"\\n\\tself eventHandler\\n\\t\\tifNotNil: [list := self eventHandler methodRefList.\\n\\t\\t\\t(self eventHandler handlesMouseDown: nil)\\n\\t\\t\\t\\tifFalse: [adder value: HandMorph value: #grabMorph:]].\\n\\t\\\"If not those, then non-default raw events\\\"\\n\\t#(#keyStroke: #mouseDown: #mouseEnter: #mouseLeave: #mouseMove: #mouseUp: #doButtonAction )\\n\\t\\tdo: [:sel | \\n\\t\\t\\tcls := self class whichClassIncludesSelector: sel.\\n\\t\\t\\tcls\\n\\t\\t\\t\\tifNotNil: [\\\"want more than default behavior\\\"\\n\\t\\t\\t\\t\\tcls == Morph\\n\\t\\t\\t\\t\\t\\tifFalse: [adder value: cls value: sel]]].\\n\\t\\\"The mechanism on a Button\\\"\\n\\t(self respondsTo: #actionSelector)\\n\\t\\tifTrue: [\\\"A button\\\"\\n\\t\\t\\tselector := self actionSelector.\\n\\t\\t\\tcls := self target class whichClassIncludesSelector: selector.\\n\\t\\t\\tcls\\n\\t\\t\\t\\tifNotNil: [\\\"want more than default behavior\\\"\\n\\t\\t\\t\\t\\tcls == Morph\\n\\t\\t\\t\\t\\t\\tifFalse: [adder value: cls value: selector]]].\\n\\tToolSet openMessageList: list name: 'Actions of ' , self printString autoSelect: false! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 19:21'!\\nshowHiders\\n\\tself allMorphsDo:[:m | m show]! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/13/2006 22:09'!\\nsightTargets: event \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\t| bullseye |\\n\\towner\\n\\t\\tifNil: [^ #()].\\n\\tbullseye := Point fromUserWithCursor: Cursor target.\\n\\tself targetFromMenu: (self potentialTargetsAt: bullseye) asKnownNameMenu popupAt: bullseye! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/13/2006 22:10'!\\nsightWorldTargets: event \\n\\t\\\"Return the potential targets for the receiver. \\n\\tThis is derived from Morph>>potentialEmbeddingTargets.\\\"\\n\\t| bullseye myWorld |\\n\\tmyWorld := self world\\n\\t\\tifNil: [^ #()].\\n\\tbullseye := Point fromUserWithCursor: Cursor target.\\n\\tself targetFromMenu: ( myWorld morphsAt: bullseye) asKnownNameMenu popupAt: bullseye! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'ar 10/5/2000 16:50'!\\nsubclassMorph\\n\\t\\\"Create a new subclass of this morph's class and make this morph be an instance of it.\\\"\\n\\n\\t| oldClass newClassName newClass newMorph |\\n\\toldClass _ self class.\\n\\tnewClassName _ FillInTheBlank\\n\\t\\trequest: 'Please give this new class a name'\\n\\t\\tinitialAnswer: oldClass name.\\n\\tnewClassName = '' ifTrue: [^ self].\\n\\t(Smalltalk includesKey: newClassName)\\n\\t\\tifTrue: [^ self inform: 'Sorry, there is already a class of that name'].\\n\\n\\tnewClass _ oldClass subclass: newClassName asSymbol\\n\\t\\tinstanceVariableNames: ''\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: oldClass category asString.\\n\\tnewMorph _ self as: newClass.\\n\\tself become: newMorph.\\n! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 01:25'!\\ntargetFromMenu: aMenu \\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| newTarget |\\n\\t\\n\\tnewTarget := aMenu startUpWithCaption: self externalName , ' targets...'.\\n\\tnewTarget\\n\\t\\tifNil: [^ self].\\n\\tself target: newTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/20/2004 12:22'!\\ntargetFromMenu: aMenu popupAt: aPoint \\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| newTarget |\\n\\tnewTarget := aMenu startUpWithCaption: self externalName , ' targets... '\\n\\tat: aPoint .\\n\\t\\\"self halt .\\\"\\n\\tnewTarget\\n\\t\\tifNil: [^ self].\\n\\tself target: newTarget! !\\n\\n!Morph methodsFor: 'meta-actions' stamp: 'wiz 7/17/2004 23:27'!\\ntargetWith: evt\\n\\t\\\"Some other morph become target of the receiver\\\"\\n\\t| menu newTarget |\\n\\tmenu _ CustomMenu new.\\n\\tself potentialTargets do: [:m | \\n\\t\\tmenu add: (m knownName ifNil:[m class name asString]) action: m].\\n\\tnewTarget _ menu startUpWithCaption: ( self externalName, ' targets...').\\n\\tnewTarget ifNil:[^self].\\n\\tself target: newTarget.! !\\n\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'dgd 9/27/2004 12:12'!\\nroundUpStrays\\n\\tself submorphs\\n\\t\\tdo: [:each | each roundUpStrays]! !\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'sw 7/20/2001 00:15'!\\nsetExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\n\\tself extent: anExtent! !\\n\\n!Morph methodsFor: 'miscellaneous' stamp: 'sw 2/2/2006 00:43'!\\nsetFlexExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed. Set the extent of the top renderer as indicated.\\\"\\n\\n\\tself addFlexShellIfNecessary.\\n\\tself topRendererOrSelf extent: anExtent! !\\n\\n\\n!Morph methodsFor: 'naming' stamp: 'fc 4/27/2004 21:58'!\\nchoosePartName\\n\\t\\\"Pick an unused name for this morph.\\\"\\n\\t| className |\\n\\tself world ifNil: [^nil].\\n\\t(self world model isKindOf: Component) ifTrue:\\n\\t\\t[self knownName ifNil: [^ self nameMeIn: self world]\\n\\t\\t\\t\\t\\tifNotNil: [^ self renameMe]].\\n\\tclassName _ self class name.\\n\\t(className size > 5 and: [className endsWith: 'Morph'])\\n\\t\\tifTrue: [className _ className copyFrom: 1 to: className size - 5].\\n\\t^ self world model addPartNameLike: className withValue: self! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:28'!\\ndownshiftedNameOfObjectRepresented\\n\\t\\\"Answer the downshiped version of the external name of the object represented\\\"\\n\\n\\t^ self nameOfObjectRepresented asLowercase! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 8/30/2003 15:52'!\\ninnocuousName\\n\\t\\\"Choose an innocuous name for the receiver -- one that does not end in the word Morph\\\"\\n\\n\\t| className allKnownNames |\\n\\tclassName _ self defaultNameStemForInstances.\\n\\t(className size > 5 and: [className endsWith: 'Morph'])\\n\\t\\tifTrue: [className _ className copyFrom: 1 to: className size - 5].\\n\\tclassName _ className asString translated.\\n\\tallKnownNames _ self world ifNil: [OrderedCollection new] ifNotNil: [self world allKnownNames].\\n\\t^ Utilities keyLike: className asString satisfying:\\n\\t\\t[:aName | (allKnownNames includes: aName) not]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 9/21/2000 13:18'!\\nnameForFindWindowFeature\\n\\t\\\"Answer the name to show in a list of windows-and-morphs to represent the receiver\\\"\\n\\n\\t^ self knownName ifNil: [self class name]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 2/22/2003 14:33'!\\nnameInModel\\n\\t\\\"Return the name for this morph in the underlying model or nil.\\\"\\n\\n\\t| w |\\n\\tw := self world.\\n\\tw isNil ifTrue: [^nil] ifFalse: [^w model nameFor: self]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:24'!\\nnameOfObjectRepresented\\n\\t\\\"Answer the external name of the object represented\\\"\\n\\n\\t^ self externalName! !\\n\\n!Morph methodsFor: 'naming' stamp: 'gm 2/22/2003 13:16'!\\nname: aName \\n\\t(aName isString) ifTrue: [self setNameTo: aName]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'dgd 2/16/2003 21:57'!\\nsetNamePropertyTo: aName \\n\\t\\\"change the receiver's externalName\\\"\\n\\tself assureExtension externalName: aName! !\\n\\n!Morph methodsFor: 'naming' stamp: 'yo 12/3/2004 17:02'!\\nsetNameTo: aName \\n\\t| nameToUse nameString |\\n\\tnameToUse := aName ifNotNil: \\n\\t\\t\\t\\t\\t[(nameString := aName asString) notEmpty ifTrue: [nameString] ifFalse: ['*']].\\n\\tself setNamePropertyTo: nameToUse\\t\\\"no Texts here!!\\\"! !\\n\\n!Morph methodsFor: 'naming' stamp: 'gm 2/22/2003 13:16'!\\nspecialNameInModel\\n\\t\\\"Return the name for this morph in the underlying model or nil.\\\"\\n\\n\\t\\\"Not an easy problem. For now, take the first part of the mouseDownSelector symbol in my eventHandler (fillBrushMouseUp:morph: gives 'fillBrush'). 5/26/97 tk\\\"\\n\\n\\t| hh |\\n\\t(self isMorphicModel) \\n\\t\\tifTrue: [^self slotName]\\n\\t\\tifFalse: \\n\\t\\t\\t[self eventHandler ifNotNil: \\n\\t\\t\\t\\t\\t[self eventHandler mouseDownSelector ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[hh := self eventHandler mouseDownSelector indexOfSubCollection: 'Mouse'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1.\\n\\t\\t\\t\\t\\t\\t\\thh > 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^self eventHandler mouseDownSelector copyFrom: 1 to: hh - 1]].\\n\\t\\t\\t\\t\\tself eventHandler mouseUpSelector ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[hh := self eventHandler mouseUpSelector indexOfSubCollection: 'Mouse'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1.\\n\\t\\t\\t\\t\\t\\t\\thh > 0 ifTrue: [^self eventHandler mouseUpSelector copyFrom: 1 to: hh - 1]]]].\\n\\n\\t\\\"\\t(self eventHandler mouseDownRecipient respondsTo: #nameFor:) ifTrue: [\\n\\t\\t\\t\\t\\t^ self eventHandler mouseDownRecipient nameFor: self]]].\\t\\\"\\n\\t\\\"myModel _ self findA: MorphicModel.\\n\\t\\t\\tmyModel ifNotNil: [^ myModel slotName]\\\"\\n\\t^self world specialNameInModelFor: self! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 10/27/2000 17:47'!\\ntryToRenameTo: aName\\n\\t\\\"A new name has been submited; make sure it's appropriate, and react accordingly. This circumlocution provides the hook by which the simple renaming of a field can result in a change to variable names in a stack, etc. There are some problems to worry about here.\\\"\\n\\n\\t| aStack |\\n\\t(self holdsSeparateDataForEachInstance and: [(aStack _ self stack) notNil])\\n\\t\\tifTrue:\\n\\t\\t\\t[self topRendererOrSelf setNameTo: aName.\\n\\t\\t\\taStack reassessBackgroundShape]\\n\\t\\tifFalse:\\n\\t\\t\\t[self renameTo: aName]! !\\n\\n!Morph methodsFor: 'naming' stamp: 'sw 1/29/2001 02:49'!\\nupdateAllScriptingElements\\n\\t\\\"A sledge-hammer sweep from the world down to make sure that all live scripting elements are up to date. Presently in eclipse, not sent at the moment.\\\"\\n\\n\\t| aPasteUp |\\n\\t(aPasteUp _ self topPasteUp) ifNotNil:\\n\\t\\t[aPasteUp allTileScriptingElements do: [:m | m bringUpToDate]]! !\\n\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'tk 11/26/2004 06:02'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\n\\n\\t(varDict at: #ClassName) == #DropShadowMorph ifTrue: [\\n\\n\\t\\tvarDict at: #ClassName put: #Morph.\\t\\\"so we don't\\n\\nrepeat this\\\"\\n\\n\\t\\t^ self convertNovember2000DropShadow: varDict using:\\n\\nsmartRefStrm\\n\\n\\t\\t\\t\\\"always returns a new object of a different class\\\"\\n\\n\\t].\\n\\n\\tvarDict at: 'costumee' ifPresent: [ :x |\\n\\n\\t\\tself convertAugust1998: varDict using: smartRefStrm].\\n\\n\\t\\t\\\"never returns a different object\\\"\\n\\n\\n\\n\\t\\\"5/18/2000\\\"\\n\\n\\tvarDict at: 'openToDragNDrop' ifPresent: [ :x | self\\n\\nenableDragNDrop: x ].\\n\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n\\n\\n\\n\\n! !\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'dgd 2/22/2003 14:33'!\\nobjectForDataStream: refStrm \\n\\t\\\"I am being written out on an object file\\\"\\n\\n\\t| dp |\\n\\tself sqkPage ifNotNil: \\n\\t\\t\\t[refStrm rootObject == self | (refStrm rootObject == self sqkPage) \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[self url notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[dp := self sqkPage copyForSaving.\\t\\\"be careful touching this object!!\\\"\\n\\t\\t\\t\\t\\t\\t\\trefStrm replace: self with: dp.\\n\\t\\t\\t\\t\\t\\t\\t^dp]]].\\n\\tself prepareToBeSaved.\\t\\\"Amen\\\"\\n\\t^self! !\\n\\n!Morph methodsFor: 'objects from disk' stamp: 'tk 7/11/1998 18:53'!\\nstoreDataOn: aDataStream\\n\\t\\\"Let all Morphs be written out. All owners are weak references. They only go out if the owner is in the tree being written.\\\"\\n\\t| cntInstVars cntIndexedVars ti localInstVars |\\n\\n\\t\\\"block my owner unless he is written out by someone else\\\"\\n\\tcntInstVars _ self class instSize.\\n\\tcntIndexedVars _ self basicSize.\\n\\tlocalInstVars _ Morph instVarNames.\\n\\tti _ 2. \\n\\t((localInstVars at: ti) = 'owner') & (Morph superclass == Object) ifFalse:\\n\\t\\t\\t[self error: 'this method is out of date'].\\n\\taDataStream\\n\\t\\tbeginInstance: self class\\n\\t\\tsize: cntInstVars + cntIndexedVars.\\n\\t1 to: ti-1 do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\taDataStream nextPutWeak: owner.\\t\\\"owner only written if in our tree\\\"\\n\\tti+1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]! !\\n\\n\\n!Morph methodsFor: 'other events' stamp: 'sw 8/1/2001 14:08'!\\nmenuButtonMouseEnter: event\\n\\t\\\"The mouse entered a menu-button area; show the menu cursor temporarily\\\"\\n\\n\\tevent hand showTemporaryCursor: Cursor menu! !\\n\\n!Morph methodsFor: 'other events' stamp: 'sw 8/1/2001 14:09'!\\nmenuButtonMouseLeave: event\\n\\t\\\"The mouse left a menu-button area; restore standard cursor\\\"\\n\\n\\tevent hand showTemporaryCursor: nil! !\\n\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 8/12/2001 02:07'!\\ninitializeToStandAlone\\n\\t\\\"Set up the receiver, created by a #basicNew and now ready to be initialized, as a fully-formed morph suitable for providing a graphic for a parts bin surrogate, and, when such a parts-bin surrogate is clicked on, for attaching to the hand as a viable stand-alone morph. Because of historical precedent, #initialize has been expected to handle this burden, though a great number of morphs actually cannot stand alone. In any case, by default we call the historical #initialize, though unhappily, so that all existing morphs will work no worse than before when using this protocol.\\\"\\n\\n\\tself initialize! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'di 11/13/2000 00:49'!\\ninPartsBin\\n\\n\\tself isPartsDonor ifTrue: [^ true].\\n\\tself allOwnersDo: [:m | m isPartsBin ifTrue: [^ true]].\\n\\t^ false\\n! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 8/12/97 14:16'!\\nisPartsBin\\n\\t^ false! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'md 2/27/2006 09:53'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\textension ifNil: [^ false].\\n\\t^ extension isPartsDonor! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'md 2/27/2006 09:59'!\\nisPartsDonor: aBoolean \\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\t(extension isNil and: [aBoolean not]) ifTrue: [^ self].\\n\\tself assureExtension isPartsDonor: aBoolean! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'di 8/11/1998 13:02'!\\nmarkAsPartsDonor\\n\\t\\\"Mark the receiver specially so that mouse actions on it are interpreted as 'tearing off a copy'\\\"\\n\\n\\tself isPartsDonor: true! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'ar 10/6/2000 22:45'!\\npartRepresented\\n\\t^self! !\\n\\n!Morph methodsFor: 'parts bin' stamp: 'sw 4/22/1998 14:45'!\\nresidesInPartsBin\\n\\t\\\"Answer true if the receiver is, or has some ancestor owner who is, a parts bin\\\"\\n\\t^ owner ifNotNil: [owner residesInPartsBin] ifNil: [false]! !\\n\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nchoosePenColor: evt\\n\\tself assuredPlayer choosePenColor: evt! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nchoosePenSize\\n\\tself assuredPlayer choosePenSize! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenColor\\n\\t^ self player ifNotNil: [self actorState getPenColor] ifNil: [Color green]! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenDown\\n\\tself player ifNil: [^ false].\\n\\t^ self actorState getPenDown! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:53'!\\ngetPenSize\\n\\tself player ifNil: [^ 1].\\n\\t^ self actorState getPenSize! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nliftPen\\n\\tself assuredPlayer liftPen! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\nlowerPen\\n\\tself assuredPlayer lowerPen! !\\n\\n!Morph methodsFor: 'pen' stamp: 'sw 8/11/1998 16:46'!\\npenColor: aColor\\n\\tself assuredPlayer penColor: aColor! !\\n\\n!Morph methodsFor: 'pen' stamp: 'di 9/3/1998 10:38'!\\npenUpWhile: changeBlock \\n\\t\\\"Suppress any possible pen trail during the execution of changeBlock\\\"\\n\\tself getPenDown\\n\\t\\tifTrue: [\\\"If this is a costume for a player with its pen down, suppress any line.\\\"\\n\\t\\t\\t\\tself liftPen.\\n\\t\\t\\t\\tchangeBlock value.\\n\\t\\t\\t\\tself lowerPen]\\n\\t\\tifFalse: [\\\"But usually, just do it.\\\"\\n\\t\\t\\t\\tchangeBlock value]! !\\n\\n!Morph methodsFor: 'pen' stamp: 'dgd 2/22/2003 14:36'!\\ntrailMorph\\n\\t\\\"You can't draw trails on me, but try my owner.\\\"\\n\\n\\towner isNil ifTrue: [^nil].\\n\\t^owner trailMorph! !\\n\\n\\n!Morph methodsFor: 'printing' stamp: 'bf 7/17/2003 12:53'!\\nclipText\\n\\t\\\"Copy the text in the receiver or in its submorphs to the clipboard\\\"\\n\\t| content |\\n\\t\\\"My own text\\\"\\n\\tcontent _ self userString.\\n\\t\\\"Or in my submorphs\\\"\\n\\tcontent ifNil: [\\n\\t\\t| list |\\n\\t\\tlist _ self allStringsAfter: nil.\\n\\t\\tlist notEmpty ifTrue: [\\n\\t\\t\\tcontent _ String streamContents: [:stream |\\n\\t\\t\\t\\tlist do: [:each | stream nextPutAll: each; cr]]]].\\n\\t\\\"Did we find something?\\\"\\n\\tcontent\\n\\t\\tifNil: [self flash \\\"provide feedback\\\"]\\n\\t\\tifNotNil: [Clipboard clipboardText: content].! !\\n\\n!Morph methodsFor: 'printing' stamp: 'dgd 2/22/2003 14:27'!\\ncolorString: aColor \\n\\taColor isNil ifTrue: [^'nil'].\\n\\tColor colorNames \\n\\t\\tdo: [:colorName | aColor = (Color perform: colorName) ifTrue: [^'Color ' , colorName]].\\n\\t^aColor storeString! !\\n\\n!Morph methodsFor: 'printing'!\\nconstructorString\\n\\n\\t^ String streamContents: [:s | self printConstructorOn: s indent: 0].\\n! !\\n\\n!Morph methodsFor: 'printing'!\\nfullPrintOn: aStream\\n\\n\\taStream nextPutAll: self class name , ' newBounds: (';\\n\\t\\tprint: bounds;\\n\\t\\tnextPutAll: ') color: ' , (self colorString: color)! !\\n\\n!Morph methodsFor: 'printing'!\\ninitString\\n\\n\\t^ String streamContents: [:s | self fullPrintOn: s]! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/26/2001 07:22'!\\nmorphReport\\n\\n\\t^self morphReportFor: #(hResizing vResizing bounds)! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/25/2001 17:47'!\\nmorphReportFor: attributeList\\n\\n\\t| s |\\n\\n\\ts _ WriteStream on: String new.\\n\\tself\\n\\t\\tmorphReportFor: attributeList \\n\\t\\ton: s \\n\\t\\tindent: 0.\\n\\tStringHolder new contents: s contents; openLabel: 'morph report'! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/25/2001 17:48'!\\nmorphReportFor: attributeList on: aStream indent: anInteger\\n\\n\\tanInteger timesRepeat: [aStream tab].\\n\\taStream print: self; space.\\n\\tattributeList do: [ :a | aStream print: (self perform: a); space].\\n\\taStream cr.\\n\\tsubmorphs do: [ :sub |\\n\\t\\tsub morphReportFor: attributeList on: aStream indent: anInteger + 1\\n\\t].! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 2/1/2001 17:42'!\\npagesHandledAutomatically\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'printing'!\\nprintConstructorOn: aStream indent: level\\n\\n\\t^ self printConstructorOn: aStream indent: level nodeDict: IdentityDictionary new\\n! !\\n\\n!Morph methodsFor: 'printing'!\\nprintConstructorOn: aStream indent: level nodeDict: nodeDict\\n\\t| nodeString |\\n\\t(nodeString _ nodeDict at: self ifAbsent: [nil])\\n\\t\\tifNotNil: [^ aStream nextPutAll: nodeString].\\n\\tsubmorphs isEmpty ifFalse: [aStream nextPutAll: '('].\\n\\taStream nextPutAll: '('.\\n\\tself fullPrintOn: aStream.\\n\\taStream nextPutAll: ')'.\\n\\tsubmorphs isEmpty ifTrue: [^ self].\\n\\tsubmorphs size <= 4\\n\\tifTrue:\\n\\t\\t[aStream crtab: level+1;\\n\\t\\t\\tnextPutAll: 'addAllMorphs: (Array'.\\n\\t\\t1 to: submorphs size do:\\n\\t\\t\\t[:i | aStream crtab: level+1; nextPutAll: 'with: '.\\n\\t\\t\\t(submorphs at: i) printConstructorOn: aStream indent: level+1 nodeDict: nodeDict].\\n\\t\\taStream nextPutAll: '))']\\n\\tifFalse:\\n\\t\\t[aStream crtab: level+1;\\n\\t\\t\\tnextPutAll: 'addAllMorphs: ((Array new: ', submorphs size printString, ')'.\\n\\t\\t1 to: submorphs size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\taStream crtab: level+1; nextPutAll: 'at: ', i printString, ' put: '.\\n\\t\\t\\t(submorphs at: i) printConstructorOn: aStream indent: level+1 nodeDict: nodeDict.\\n\\t\\t\\taStream nextPutAll: ';'].\\n\\t\\taStream crtab: level+1; nextPutAll: 'yourself))']! !\\n\\n!Morph methodsFor: 'printing' stamp: 'dgd 2/22/2003 19:05'!\\nprintOn: aStream \\n\\t| aName |\\n\\tsuper printOn: aStream.\\n\\t(aName := self knownName) notNil \\n\\t\\tifTrue: [aStream nextPutAll: '<' , aName , '>'].\\n\\taStream nextPutAll: '('.\\n\\taStream\\n\\t\\tprint: self identityHash;\\n\\t\\tnextPutAll: ')'! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 9/18/2000 10:22'!\\nprintSpecs\\n\\n\\t| printSpecs |\\n\\n\\tprintSpecs _ self valueOfProperty: #PrintSpecifications.\\n\\tprintSpecs ifNil: [\\n\\t\\tprintSpecs _ PrintSpecifications defaultSpecs.\\n\\t\\tself printSpecs: printSpecs.\\n\\t].\\n\\t^printSpecs! !\\n\\n!Morph methodsFor: 'printing' stamp: 'RAA 9/18/2000 10:21'!\\nprintSpecs: aPrintSecification\\n\\n\\tself setProperty: #PrintSpecifications toValue: aPrintSecification.\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'jm 5/28/1998 18:00'!\\nprintStructureOn: aStream indent: tabCount\\n\\n\\ttabCount timesRepeat: [aStream tab].\\n\\tself printOn: aStream.\\n\\taStream cr.\\n\\tself submorphsDo: [:m | m printStructureOn: aStream indent: tabCount + 1].\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'sw 10/27/2000 17:45'!\\nreportableSize\\n\\t\\\"Answer a size worth reporting as the receiver's size in a list view\\\"\\n\\n\\t| total |\\n\\ttotal _ super reportableSize.\\n\\tsubmorphs do:\\n\\t\\t[:m | total _ total + m reportableSize].\\n\\t^ total! !\\n\\n!Morph methodsFor: 'printing' stamp: 'jm 5/28/1998 17:58'!\\nstructureString\\n\\t\\\"Return a string that showing this morph and all its submorphs in an indented list that reflects its structure.\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: (String new: 1000).\\n\\tself printStructureOn: s indent: 0.\\n\\t^ s contents\\n! !\\n\\n!Morph methodsFor: 'printing' stamp: 'sw 10/27/2000 17:47'!\\ntextToPaste\\n\\t\\\"If the receiver has text to offer pasting, answer it, else answer nil\\\"\\n\\n\\t^ nil! !\\n\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'sw 3/30/2005 03:44'!\\naddFlexShell\\n\\t\\\"Wrap a rotating and scaling shell around this morph.\\\"\\n\\n\\t| oldHalo flexMorph myWorld anIndex |\\n\\n\\tmyWorld _ self world.\\n\\toldHalo _ self halo.\\n\\tanIndex _ self owner submorphIndexOf: self.\\n\\tself owner addMorph: (flexMorph _ self newTransformationMorph asFlexOf: self)\\n\\t\\tasElementNumber: anIndex.\\n\\tself transferStateToRenderer: flexMorph.\\n\\toldHalo ifNotNil: [oldHalo setTarget: flexMorph].\\n\\tmyWorld ifNotNil: [myWorld startSteppingSubmorphsOf: flexMorph].\\n\\n\\t^ flexMorph! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'di 11/28/2001 18:22'!\\naddFlexShellIfNecessary\\n\\t\\\"If this morph requires a flex shell to scale or rotate,\\n\\t\\tthen wrap it in one and return it.\\n\\tPolygons, eg, may override to return themselves.\\\"\\n\\n\\t^ self addFlexShell! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'ar 11/24/1998 14:19'!\\nkeepsTransform\\n\\t\\\"Return true if the receiver will keep it's transform while being grabbed by a hand.\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'ar 2/16/1999 18:59'!\\nnewTransformationMorph\\n\\t^TransformationMorph new! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'mu 3/29/2004 17:33'!\\nremoveFlexShell\\n\\tself isFlexed\\n\\t\\tifTrue: [self owner removeFlexShell]! !\\n\\n!Morph methodsFor: 'rotate scale and flex' stamp: 'jm 4/25/1998 05:19'!\\nrotationDegrees\\n\\t\\\"Default implementation.\\\"\\n\\n\\t^ 0.0\\n! !\\n\\n\\n!Morph methodsFor: 'rounding' stamp: 'mk 8/7/2005 10:03'!\\ncornerStyle: aSymbol\\n\\t\\\"This method makes it possible to set up desired corner style. aSymbol has to be one of:\\n\\t\\t#square\\n\\t\\t#rounded\\\"\\n\\n\\taSymbol == #square\\n\\t\\tifTrue:[self removeProperty: #cornerStyle]\\n\\t\\tifFalse:[self setProperty: #cornerStyle toValue: aSymbol].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'mk 8/14/2005 13:31'!\\nroundedCorners\\n\\t\\\"Return a list of those corners to round.\\n\\n\\t\\t1-4\\n\\t\\t| |\\n\\t\\t2-3\\n\\n\\tReturned array contains `codes' of those corners, which should be rounded.\\n\\n\\t1 denotes top-left corner\\n\\t2 denotes bottom-left corner\\n\\t3 denotes bottom-right corner\\n\\t4 denotes top-right corner.\\n\\n\\tThus, if this method returned #(2 3) that would mean that bottom (left and right)\\n\\tcorners would be rounded whereas top (left and right) corners wouldn't be rounded.\\n\\n\\tThis method returns #(1 2 3 4) and that means that all the corners should be rounded.\\\"\\n\\n\\t^ #(1 2 3 4)! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'dgd 9/6/2003 18:27'!\\nroundedCornersString\\n\\t\\\"Answer the string to put in a menu that will invite the user to \\n\\tswitch to the opposite corner-rounding mode\\\"\\n\\t^ (self wantsRoundedCorners\\n\\t\\tifTrue: ['<yes>']\\n\\t\\tifFalse: ['<no>'])\\n\\t\\t, 'round corners' translated! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'ar 12/25/2001 19:44'!\\ntoggleCornerRounding\\n\\tself cornerStyle == #rounded\\n\\t\\tifTrue: [self cornerStyle: #square]\\n\\t\\tifFalse: [self cornerStyle: #rounded].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'rounding' stamp: 'ar 12/22/2001 22:45'!\\nwantsRoundedCorners\\n\\t\\\"Return true if the receiver wants its corners rounded\\\"\\n\\t^ self cornerStyle == #rounded! !\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: 'scripting' stamp: 'dgd 7/4/2004 12:41'!\\narrowDeltaFor: aGetSelector \\n\\t\\\"Answer a number indicating the default arrow delta to be \\n\\tused in a numeric readout with the given get-selector. This is \\n\\ta hook that subclasses of Morph can reimplement.\\\"\\n\\taGetSelector == #getScaleFactor\\n\\t\\tifTrue: [^ 0.1].\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'ar 1/25/2001 12:50'!\\nasEmptyPermanentScriptor\\n\\t\\\"Answer a new empty permanent scriptor derived from info deftly secreted in the receiver. Good grief\\\"\\n\\n\\t| aScriptor aPlayer |\\n\\taPlayer _ self valueOfProperty: #newPermanentPlayer.\\n\\taPlayer assureUniClass.\\n\\taScriptor _ aPlayer newScriptorAround: nil.\\n\\taScriptor position: (self world primaryHand position - (10 @ 10)).\\n\\taPlayer updateAllViewersAndForceToShow: #scripts.\\n\\t^ aScriptor! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 10/17/2001 09:46'!\\nbringTileScriptingElementsUpToDate\\n\\t\\\"Send #bringUpToDate to every tile-scripting element of the receiver, including possibly the receiver itself\\\"\\n\\n\\t(self allMorphs select: [:s | s isTileScriptingElement]) do:\\n\\t\\t[:el | el bringUpToDate]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'RAA 3/9/2001 11:39'!\\nbringUpToDate\\n\\n\\t(self buttonProperties ifNil: [^self]) bringUpToDate! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 7/19/2005 01:55'!\\ndefaultFloatPrecisionFor: aGetSelector\\n\\t\\\"Answer a number indicating the default float precision to be used in a numeric readout for which the receiver provides the data. Individual morphs can override this. Showing fractional values for readouts of getCursor was in response to an explicit request from ack\\\"\\n\\n\\t(self renderedMorph decimalPlacesForGetter: aGetSelector) ifNotNilDo: [:places | ^ (Utilities floatPrecisionForDecimalPlaces: places)].\\n\\n\\t(#(getCursor getNumericValue getNumberAtCursor getCursorWrapped getScaleFactor getUnitVector getAlpha) includes: aGetSelector)\\n\\t\\tifTrue:\\n\\t\\t\\t[^ 0.01].\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/12/2005 13:26'!\\nfilterViewerCategoryDictionary: dict\\n\\t\\\"dict has keys of categories and values of priority.\\n\\tYou can re-order or remove categories here.\\\"\\n\\n\\tself wantsConnectionVocabulary\\n\\t\\tifFalse: [ dict removeKey: #'connections to me' ifAbsent: [].\\n\\t\\t\\tdict removeKey: #connection ifAbsent: []].\\n\\tself wantsConnectorVocabulary\\n\\t\\tifFalse: [ dict removeKey: #connector ifAbsent: [] ].\\n\\tself wantsEmbeddingsVocabulary\\n\\t\\tifFalse: [dict removeKey: #embeddings ifAbsent: []].\\n\\tPreferences eToyFriendly\\n\\t\\tifTrue:\\n\\t\\t\\t[dict removeKey: #layout ifAbsent: []].\\n\\t(Preferences eToyFriendly or: [self isWorldMorph not]) ifTrue:\\n\\t\\t[dict removeKey: #preferences ifAbsent: []].! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'tk 10/1/97 18:23'!\\nisTileLike\\n\\t\\\"Cannot be dropped into a script\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'RAA 3/9/2001 11:47'!\\nisTileScriptingElement\\n\\n\\t^ self hasButtonProperties and: [self buttonProperties isTileScriptingElement]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:53'!\\njettisonScripts\\n\\tself player ifNotNil: [self player class jettisonScripts]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'LC 9/28/1999 21:57'!\\nmakeAllTilesColored\\n\\tself allMorphsDo: \\n\\t\\t[:m | m restoreTypeColor]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'LC 9/28/1999 21:57'!\\nmakeAllTilesGreen\\n\\tself allMorphsDo: \\n\\t\\t[:m | m useUniformTileColor]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:59'!\\nrestoreTypeColor\\n\\tself player ifNotNil: [self player allScriptEditors do:\\n\\t\\t[:anEditor | anEditor allMorphsDo:\\n\\t\\t\\t[:m | m restoreTypeColor]]]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:46'!\\nscriptEditorFor: aScriptName\\n\\t^ self assuredPlayer scriptEditorFor: aScriptName! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 7/5/2005 00:31'!\\ntearOffTile\\n\\t\\\"Tear off a tile representing the player associated with the receiver. This is obtained from the top renderer\\\"\\n\\n\\t^ self topRendererOrSelf assuredPlayer tearOffTileForSelf! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'nk 8/21/2004 12:17'!\\ntriggerScript: aSymbol\\n\\t\\\"Have my player perform the script of the given name, which is guaranteed to exist.\\\"\\n\\n\\t^self assuredPlayer triggerScript: aSymbol! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 8/11/1998 16:55'!\\nuseUniformTileColor\\n\\tself player ifNotNil:\\n\\t\\t[self player allScriptEditors do:\\n\\t\\t\\t[:anEditor | anEditor allMorphsDo:\\n\\t\\t\\t\\t[:m | m useUniformTileColor]]]! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'sw 10/18/2000 10:32'!\\nviewAfreshIn: aPasteUp showingScript: aScriptName at: aPosition\\n\\t\\\"Obtain a smartly updated ScriptEditor for the given script name and zap it into place at aPosition\\\"\\n\\n\\t| anEditor |\\n\\tself player updateAllViewersAndForceToShow: #scripts.\\n\\tanEditor _ self player scriptEditorFor: aScriptName.\\n\\taPasteUp ifNotNil: [aPasteUp addMorph: anEditor].\\n\\tanEditor position: aPosition.\\n\\tanEditor currentWorld startSteppingSubmorphsOf: anEditor! !\\n\\n!Morph methodsFor: 'scripting' stamp: 'nk 8/21/2004 08:39'!\\nwantsConnectionVocabulary\\n\\tsubmorphs ifNil: [ ^true ].\\t\\\"called from EToyVocabulary>>initialize after basicNew\\\"\\n\\n\\t^ (Preferences valueOfFlag: #alwaysShowConnectionVocabulary)\\n\\t\\tor: [ self connections isEmpty not ]! !\\n\\n\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:27'!\\narrangeToStartStepping\\n\\t\\\"Arrange to start getting sent the 'step' message, but don't do that initial #step call that startStepping does\\\"\\n\\n\\tself arrangeToStartSteppingIn: self world! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:26'!\\narrangeToStartSteppingIn: aWorld\\n\\t\\\"Start getting sent the 'step' message in aWorld. Like startSteppingIn:, but without the initial one to get started'\\\"\\n\\taWorld ifNotNil:\\n\\t\\t[aWorld startStepping: self.\\n\\t\\tself changed]! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 3/22/2000 14:28'!\\nisStepping\\n\\t\\\"Return true if the receiver is currently stepping in its world\\\"\\n\\t| aWorld |\\n\\t^ (aWorld _ self world)\\n\\t\\tifNil:\\t\\t[false]\\n\\t\\tifNotNil:\\t[aWorld isStepping: self]! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:43'!\\nisSteppingSelector: aSelector\\n\\t\\\"Return true if the receiver is currently stepping in its world\\\"\\n\\t| aWorld |\\n\\t^ (aWorld _ self world)\\n\\t\\tifNil:\\t\\t[false]\\n\\t\\tifNotNil:\\t[aWorld isStepping: self selector: aSelector]! !\\n\\n!Morph methodsFor: 'stepping and presenter'!\\nstart\\n\\t\\\"Start running my script. For ordinary morphs, this means start stepping.\\\"\\n\\n\\tself startStepping.\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 1/31/2001 13:07'!\\nstartStepping\\n\\t\\\"Start getting sent the 'step' message.\\\"\\n\\tself startStepping: #stepAt: at: Time millisecondClockValue arguments: nil stepTime: nil.! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 7/19/1998 11:51'!\\nstartSteppingIn: aWorld\\n\\t\\\"Start getting sent the 'step' message in aWorld\\\"\\n\\n\\tself step. \\\"one to get started!!\\\"\\n\\taWorld ifNotNil: [aWorld startStepping: self].\\n\\tself changed! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:42'!\\nstartSteppingSelector: aSelector\\n\\t\\\"Start getting sent the 'step' message.\\\"\\n\\tself startStepping: aSelector at: Time millisecondClockValue arguments: nil stepTime: nil.! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 10/22/2000 16:36'!\\nstartStepping: aSelector at: scheduledTime arguments: args stepTime: stepTime\\n\\t\\\"Start stepping the receiver\\\"\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [\\n\\t\\tw startStepping: self at: scheduledTime selector: aSelector arguments: args stepTime: stepTime.\\n\\t\\tself changed].! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 2/12/2001 17:04'!\\nstep\\n\\t\\\"Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.\\\"\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 2/12/2001 18:05'!\\nstepAt: millisecondClockValue\\n\\t\\\"Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message.\\n\\tThe millisecondClockValue parameter gives the value of the millisecond clock at the moment of dispatch.\\n\\tDefault is to dispatch to the parameterless step method for the morph, but this protocol makes it possible for some morphs to do differing things depending on the clock value\\\"\\n\\tself player ifNotNilDo:[:p| p stepAt: millisecondClockValue].\\n\\tself step\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter'!\\nstop\\n\\t\\\"Stop running my script. For ordinary morphs, this means stop stepping.\\\"\\n\\n\\tself stopStepping.\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 12/15/2000 00:00'!\\nstopStepping\\n\\t\\\"Stop getting sent the 'step' message.\\\"\\n\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [w stopStepping: self].\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'ar 12/15/2000 00:00'!\\nstopSteppingSelector: aSelector\\n\\t\\\"Stop getting sent the given message.\\\"\\n\\t| w |\\n\\tw _ self world.\\n\\tw ifNotNil: [w stopStepping: self selector: aSelector].\\n! !\\n\\n!Morph methodsFor: 'stepping and presenter' stamp: 'sw 10/11/1999 12:59'!\\nstopSteppingSelfAndSubmorphs\\n\\tself allMorphsDo: [:m | m stopStepping]\\n! !\\n\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 3/18/2001 00:11'!\\nactiveHand\\n\\t^ActiveHand! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 01:00'!\\nallOwners\\n\\t\\\"Return the owners of the reciever\\\"\\n\\n\\t^ Array streamContents: [:strm | self allOwnersDo: [:m | strm nextPut: m]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 9/14/2000 16:47'!\\nallOwnersDo: aBlock\\n\\t\\\"Evaluate aBlock with all owners of the receiver\\\"\\n\\towner ifNotNil:[^owner withAllOwnersDo: aBlock].! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:48'!\\nfirstOwnerSuchThat: conditionBlock\\n\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [^ m]].\\n\\t^ nil\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 10/3/2000 15:36'!\\nhasOwner: aMorph\\n\\t\\\"Return true if the receiver has aMorph in its owner chain\\\"\\n\\taMorph ifNil:[^true].\\n\\tself allOwnersDo:[:m| m = aMorph ifTrue:[^true]].\\n\\t^false! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 9/1/2004 17:17'!\\nisInDockingBar\\n\\t\\\"answer if the receiver is in a menu bar\\\"\\n\\t^ (owner notNil) and: [owner isDockingBar]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 9/18/2004 15:56'!\\nisInSystemWindow\\n\\t\\\"answer if the receiver is in a system window\\\"\\n\\t^ owner isMorph and:[owner isSystemWindow or:[owner isInSystemWindow]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 19:05'!\\nisInWorld\\n\\t\\\"Return true if this morph is in a world.\\\"\\n\\n\\t^self world notNil! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 8/29/2000 14:55'!\\nmorphPreceding: aSubmorph\\n\\t\\\"Answer the morph immediately preceding aSubmorph, or nil if none\\\"\\n\\n\\t| anIndex |\\n\\tanIndex _ submorphs indexOf: aSubmorph ifAbsent: [^ nil].\\n\\t^ anIndex > 1\\n\\t\\tifTrue:\\n\\t\\t\\t[submorphs at: (anIndex - 1)]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:13'!\\nnearestOwnerThat: conditionBlock\\n\\t\\\"Return the first enclosing morph for which aBlock evaluates to true, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: conditionBlock\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:49'!\\norOwnerSuchThat: conditionBlock\\n\\n\\t(conditionBlock value: self) ifTrue: [^ self].\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [^ m]].\\n\\t^ nil\\n\\n! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:50'!\\noutermostMorphThat: conditionBlock\\n\\t\\\"Return the outermost containing morph for which aBlock is true, or nil if none\\\"\\n\\n\\t| outermost |\\n\\tself allOwnersDo: [:m | (conditionBlock value: m) ifTrue: [outermost _ m]].\\n\\t^ outermost! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 3/18/2001 00:12'!\\noutermostWorldMorph\\n\\n\\t| outer |\\n\\tWorld ifNotNil:[^World].\\n\\tself flag: #arNote. \\\"stuff below is really only for MVC\\\"\\n\\touter _ self outermostMorphThat: [ :x | x isWorldMorph].\\n\\touter ifNotNil: [^outer].\\n\\tself isWorldMorph ifTrue: [^self].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'structure'!\\nowner\\n\\t\\\"Returns the owner of this morph, which may be nil.\\\"\\n\\n\\t^ owner! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:18'!\\nownerThatIsA: aClass\\n\\t\\\"Return the first enclosing morph that is a kind of aClass, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: [:m | m isKindOf: aClass]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/12/2000 16:20'!\\nownerThatIsA: firstClass orA: secondClass\\n\\t\\\"Return the first enclosing morph that is a kind of one of the two classes given, or nil if none\\\"\\n\\n\\t^ self firstOwnerSuchThat: [:m | (m isKindOf: firstClass) or: [m isKindOf: secondClass]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 7/1/1998 18:02'!\\npasteUpMorph\\n\\t\\\"Answer the closest containing morph that is a PasteUp morph\\\"\\n\\t^ self ownerThatIsA: PasteUpMorph! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 8/28/2004 18:43'!\\npasteUpMorphHandlingTabAmongFields\\n\\t\\\"Answer the nearest PasteUpMorph in my owner chain that has the tabAmongFields property, or nil if none\\\"\\n\\n\\t| aPasteUp |\\n\\taPasteUp _ self owner.\\n\\t[aPasteUp notNil] whileTrue:\\n\\t\\t[aPasteUp tabAmongFields ifTrue:\\n\\t\\t\\t[^ aPasteUp].\\n\\t\\taPasteUp _ aPasteUp owner].\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'structure' stamp: 'RAA 6/13/2000 15:01'!\\nprimaryHand\\n\\n | outer |\\n outer _ self outermostWorldMorph ifNil: [^ nil].\\n ^ outer activeHand ifNil: [outer firstHand]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:34'!\\nrenderedMorph\\n\\t\\\"If the receiver is a renderer morph, answer the rendered morph. Otherwise, answer the receiver. A renderer morph with no submorphs answers itself. See the comment in Morph>isRenderer.\\\"\\n\\n\\tself isRenderer ifFalse: [^self].\\n\\tsubmorphs isEmpty ifTrue: [^self].\\n\\t^self firstSubmorph renderedMorph! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:34'!\\nroot\\n\\t\\\"Return the root of the composite morph containing the receiver. The owner of the root is either nil, a WorldMorph, or a HandMorph. If the receiver's owner is nil, the root is the receiver itself. This method always returns a morph.\\\"\\n\\n\\t(owner isNil or: [owner isWorldOrHandMorph]) ifTrue: [^self].\\n\\t^owner root! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 8/4/1999 15:41'!\\nrootAt: location\\n\\t\\\"Just return myself, unless I am a WorldWindow.\\n\\tIf so, then return the appropriate root in that world\\\"\\n\\n\\t^ self! !\\n\\n!Morph methodsFor: 'structure' stamp: 'sw 8/30/1998 09:47'!\\ntopPasteUp\\n\\t\\\"If the receiver is in a world, return that; otherwise return the outermost pasteup morph\\\"\\n\\t^ self outermostMorphThat: [:m | m isKindOf: PasteUpMorph]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 19:06'!\\ntopRendererOrSelf\\n\\t\\\"Answer the topmost renderer for this morph, or this morph itself if it has no renderer. See the comment in Morph>isRenderer.\\\"\\n\\n\\t| top topsOwner |\\n\\towner ifNil: [^self].\\n\\tself isWorldMorph ifTrue: [^self].\\t\\\"ignore scaling of this world\\\"\\n\\ttop := self.\\n\\ttopsOwner := top owner.\\n\\t[topsOwner notNil and: [topsOwner isRenderer]] whileTrue: \\n\\t\\t\\t[top := topsOwner.\\n\\t\\t\\ttopsOwner := top owner].\\n\\t^top! !\\n\\n!Morph methodsFor: 'structure' stamp: 'di 11/13/2000 00:59'!\\nwithAllOwners\\n\\t\\\"Return the receiver and all its owners\\\"\\n\\n\\t^ Array streamContents: [:strm | self withAllOwnersDo: [:m | strm nextPut: m]]! !\\n\\n!Morph methodsFor: 'structure' stamp: 'ar 9/14/2000 16:48'!\\nwithAllOwnersDo: aBlock\\n\\t\\\"Evaluate aBlock with the receiver and all of its owners\\\"\\n\\taBlock value: self.\\n\\towner ifNotNil:[^owner withAllOwnersDo: aBlock].! !\\n\\n!Morph methodsFor: 'structure' stamp: 'dgd 2/22/2003 14:36'!\\nworld\\n\\t^owner isNil ifTrue: [nil] ifFalse: [owner world]! !\\n\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/14/2001 12:50'!\\nallKnownNames\\n\\t\\\"Return a list of all known names based on the scope of the receiver. Does not include the name of the receiver itself. Items in parts bins are excluded. Reimplementors (q.v.) can extend the list\\\"\\n\\n\\t^ Array streamContents:\\n\\t\\t[:s | self allSubmorphNamesDo: [:n | s nextPut: n]]\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nallMorphs\\n\\t\\\"Return a collection containing all morphs in this composite morph (including the receiver).\\\"\\n\\n\\t| all |\\n\\tall _ OrderedCollection new: 100.\\n\\tself allMorphsDo: [: m | all add: m].\\n\\t^ all! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:27'!\\nallMorphsDo: aBlock \\n\\t\\\"Evaluate the given block for all morphs in this composite morph (including the receiver).\\\"\\n\\n\\tsubmorphs do: [:m | m allMorphsDo: aBlock].\\n\\taBlock value: self! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 10/31/97 20:05'!\\nallNonSubmorphMorphs\\n\\t\\\"Return a collection containing all morphs in this morph which are not currently in the submorph containment hierarchy (put in primarily for bookmorphs)\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/14/2001 12:44'!\\nallSubmorphNamesDo: nameBlock\\n\\t\\\"Return a list of all known names of submorphs and nested submorphs of the receiver, based on the scope of the receiver. Items in parts bins are excluded\\\"\\n\\n\\tself isPartsBin ifTrue: [^ self]. \\\"Don't report names from parts bins\\\"\\n\\tself submorphsDo: \\n\\t\\t[:m | m knownName ifNotNilDo: [:n | nameBlock value: n].\\n\\t\\tm allSubmorphNamesDo: nameBlock].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 8/31/2004 16:53'!\\ndockingBars\\n\\t\\\"Answer the receiver's dockingBars\\\"\\n\\t^ self submorphs\\n\\t\\tselect: [:each | each isDockingBar]\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'rhi 9/10/2000 12:12'!\\nfindA: aClass\\n\\t\\\"Return the first submorph of the receiver that is descended from the given class. Return nil if there is no such submorph. Clients of this code should always check for a nil return value so that the code will be robust if the user takes the morph apart.\\\"\\n\\n\\t^self submorphs\\n\\t\\tdetect: [:p | p isKindOf: aClass]\\n\\t\\tifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 1/9/2001 12:30'!\\nfindDeeplyA: aClass\\n\\t\\\"Return a morph in the submorph tree of the receiver that is descended from the given class. Return nil if there is no such morph. Clients of this code should always check for a nil return value so that the code will be robust if the user takes the morph apart.\\\"\\n\\n\\t^ (self allMorphs copyWithout: self)\\n\\t\\tdetect: [:p | p isKindOf: aClass]\\n\\t\\tifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'LC 9/28/1999 19:12'!\\nfindDeepSubmorphThat: block1 ifAbsent: block2 \\n\\tself\\n\\t\\tallMorphsDo: [:m | (block1 value: m)\\n\\t\\t\\t\\t== true ifTrue: [^ m]].\\n\\t^ block2 value! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 3/17/2001 15:32'!\\nfindSubmorphBinary: aBlock\\n\\t\\\"Use binary search for finding a specific submorph of the receiver. Caller must be certain that the ordering holds for the submorphs.\\\"\\n\\t^submorphs findBinary: aBlock ifNone:[nil].! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:31'!\\nfirstSubmorph\\n\\t^submorphs first! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nhasSubmorphs\\n\\t^submorphs notEmpty! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 7/3/1998 17:11'!\\nhasSubmorphWithProperty: aSymbol\\n\\tsubmorphs detect: [:m | m hasProperty: aSymbol] ifNone: [^ false].\\n\\t^ true! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/31/2000 11:04'!\\nindexOfMorphAbove: aPoint\\n\\t\\\"Return index of lowest morph whose bottom is above aPoint.\\n\\tWill return 0 if the first morph is not above aPoint.\\\"\\n\\n\\tsubmorphs withIndexDo: [:mm :ii | \\n\\t\\tmm fullBounds bottom >= aPoint y ifTrue: [^ ii - 1]].\\n\\t^ submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nlastSubmorph\\n\\t^submorphs last! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 9/6/2004 14:17'!\\nmainDockingBars\\n\\t\\\"Answer the receiver's main dockingBars\\\"\\n\\t^ self dockingBars\\n\\t\\tselect: [:each | each hasProperty: #mainDockingBarTimeStamp]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:40'!\\nmorphsAt: aPoint\\n\\t\\\"Return a collection of all morphs in this morph structure that contain the given point, possibly including the receiver itself. The order is deepest embedding first.\\\"\\n\\t^self morphsAt: aPoint unlocked: false! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:32'!\\nmorphsAt: aPoint behind: aMorph unlocked: aBool \\n\\t\\\"Return all morphs at aPoint that are behind frontMorph; if aBool is true return only unlocked, visible morphs.\\\"\\n\\n\\t| isBack found all tfm |\\n\\tall := (aMorph isNil or: [owner isNil]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Traverse down\\\"\\n\\n\\t\\t\\t\\t\\t(self fullBounds containsPoint: aPoint) ifFalse: [^#()].\\n\\t\\t\\t\\t\\t(aBool and: [self isLocked or: [self visible not]]) ifTrue: [^#()].\\n\\t\\t\\t\\t\\tnil]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[\\\"Traverse up\\\"\\n\\n\\t\\t\\t\\t\\ttfm := self transformedFrom: owner.\\n\\t\\t\\t\\t\\tall := owner \\n\\t\\t\\t\\t\\t\\t\\t\\tmorphsAt: (tfm localPointToGlobal: aPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tbehind: self\\n\\t\\t\\t\\t\\t\\t\\t\\tunlocked: aBool.\\n\\t\\t\\t\\t\\tWriteStream with: all].\\n\\tisBack := aMorph isNil.\\n\\tself submorphsDo: \\n\\t\\t\\t[:m | \\n\\t\\t\\tisBack \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[tfm := m transformedFrom: self.\\n\\t\\t\\t\\t\\tfound := m \\n\\t\\t\\t\\t\\t\\t\\t\\tmorphsAt: (tfm globalPointToLocal: aPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tbehind: nil\\n\\t\\t\\t\\t\\t\\t\\t\\tunlocked: aBool.\\n\\t\\t\\t\\t\\tfound notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[all ifNil: [all := WriteStream on: #()].\\n\\t\\t\\t\\t\\t\\t\\tall nextPutAll: found]].\\n\\t\\t\\tm == aMorph ifTrue: [isBack := true]].\\n\\t(isBack and: [self containsPoint: aPoint]) \\n\\t\\tifTrue: \\n\\t\\t\\t[all ifNil: [^Array with: self].\\n\\t\\t\\tall nextPut: self].\\n\\t^all ifNil: [#()] ifNotNil: [all contents]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:40'!\\nmorphsAt: aPoint unlocked: aBool\\n\\t\\\"Return a collection of all morphs in this morph structure that contain the given point, possibly including the receiver itself. The order is deepest embedding first.\\\"\\n\\t| mList |\\n\\tmList _ WriteStream on: #().\\n\\tself morphsAt: aPoint unlocked: aBool do:[:m| mList nextPut: m].\\n\\t^mList contents! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:37'!\\nmorphsAt: aPoint unlocked: aBool do: aBlock\\n\\t\\\"Evaluate aBlock with all the morphs starting at the receiver which appear at aPoint. If aBool is true take only visible, unlocked morphs into account.\\\"\\n\\t| tfm |\\n\\t(self fullBounds containsPoint: aPoint) ifFalse:[^self].\\n\\t(aBool and:[self isLocked or:[self visible not]]) ifTrue:[^self].\\n\\tself submorphsDo:[:m|\\n\\t\\ttfm _ m transformedFrom: self.\\n\\t\\tm morphsAt: (tfm globalPointToLocal: aPoint) unlocked: aBool do: aBlock].\\n\\t(self containsPoint: aPoint) ifTrue:[aBlock value: self].! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOf: someMorph overlapping: aRectangle do: aBlock\\n\\t\\\"Evaluate aBlock with all top-level morphs in front of someMorph that overlap with the given rectangle. someMorph is either an immediate child of the receiver or nil (in which case all submorphs of the receiver are enumerated).\\\"\\n\\tself submorphsDo:[:m|\\n\\t\\tm == someMorph ifTrue:[\\\"Try getting out quickly\\\"\\n\\t\\t\\towner ifNil:[^self].\\n\\t\\t\\t^owner morphsInFrontOf: self overlapping: aRectangle do: aBlock].\\n\\t\\t(m fullBoundsInWorld intersects: aRectangle)\\n\\t\\t\\tifTrue:[aBlock value: m]].\\n\\towner ifNil:[^self].\\n\\t^owner morphsInFrontOf: self overlapping: aRectangle do: aBlock.! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOverlapping: aRectangle\\n\\t\\\"Return all top-level morphs in front of someMorph that overlap with the given rectangle.\\\"\\n\\t| morphList |\\n\\tmorphList _ WriteStream on: Array new.\\n\\tself morphsInFrontOf: nil overlapping: aRectangle do:[:m | morphList nextPut: m].\\n\\t^morphList contents! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 9/9/2000 17:31'!\\nmorphsInFrontOverlapping: aRectangle do: aBlock\\n\\t\\\"Evaluate aBlock with all top-level morphs in front of someMorph that overlap with the given rectangle.\\\"\\n\\t^self morphsInFrontOf: nil overlapping: aRectangle do: aBlock! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 8/13/2003 11:32'!\\nnoteNewOwner: aMorph\\n\\t\\\"I have just been added as a submorph of aMorph\\\"! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'RAA 6/11/2000 20:41'!\\nrootMorphsAtGlobal: aPoint\\n\\t\\\"Return the list of root morphs containing the given point, excluding the receiver.\\n\\tar 11/8/1999: Moved into morph for an incredibly ugly hack in 3D worlds\\\"\\n\\n\\t^ self rootMorphsAt: (self pointFromWorld: aPoint)! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'ar 10/8/2000 15:44'!\\nrootMorphsAt: aPoint\\n\\t\\\"Return the list of root morphs containing the given point, excluding the receiver.\\n\\tar 11/8/1999: Moved into morph for an incredibly ugly hack in 3D worlds\\\"\\nself flag: #arNote. \\\"check this at some point\\\"\\n\\t^ self submorphs select:\\n\\t\\t[:m | (m fullContainsPoint: aPoint) and: [m isLocked not]]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:35'!\\nshuffleSubmorphs\\n\\t\\\"Randomly shuffle the order of my submorphs. Don't call this method lightly!!\\\"\\n\\n\\t| bg |\\n\\tself invalidRect: self fullBounds.\\n\\t(submorphs notEmpty and: [submorphs last mustBeBackmost]) \\n\\t\\tifTrue: \\n\\t\\t\\t[bg := submorphs last.\\n\\t\\t\\tbg privateDelete].\\n\\tsubmorphs := submorphs shuffled.\\n\\tbg ifNotNil: [self addMorphBack: bg].\\n\\tself layoutChanged! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/20/2000 13:12'!\\nsubmorphAfter\\n\\t\\\"Return the submorph after (behind) me, or nil\\\"\\n\\t| ii |\\n\\towner ifNil: [^ nil].\\n\\t^ (ii _ owner submorphIndexOf: self) = owner submorphs size \\n\\t\\tifTrue: [nil]\\n\\t\\tifFalse: [owner submorphs at: ii+1].\\n\\t\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'tk 10/20/2000 13:13'!\\nsubmorphBefore\\n\\t\\\"Return the submorph after (behind) me, or nil\\\"\\n\\t| ii |\\n\\towner ifNil: [^ nil].\\n\\t^ (ii _ owner submorphIndexOf: self) = 1 \\n\\t\\tifTrue: [nil]\\n\\t\\tifFalse: [owner submorphs at: ii-1].\\n\\t\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nsubmorphCount\\n\\n\\t^ submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 4/9/98 14:26'!\\nsubmorphNamed: aName\\n\\t^ self submorphNamed: aName ifNone: [nil]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'gm 2/22/2003 13:16'!\\nsubmorphNamed: aName ifNone: aBlock \\n\\t\\\"Find the first submorph with this name, or a button with an action selector of that name\\\"\\n\\n\\t| sub args |\\n\\tself submorphs do: [:p | p knownName = aName ifTrue: [^p]].\\n\\tself submorphs do: \\n\\t\\t\\t[:button | \\n\\t\\t\\t(button respondsTo: #actionSelector) \\n\\t\\t\\t\\tifTrue: [button actionSelector == aName ifTrue: [^button]].\\n\\t\\t\\t((button respondsTo: #arguments) and: [(args := button arguments) notNil]) \\n\\t\\t\\t\\tifTrue: [(args at: 2 ifAbsent: [nil]) == aName ifTrue: [^button]].\\n\\t\\t\\t(button isAlignmentMorph) \\n\\t\\t\\t\\tifTrue: [(sub := button submorphNamed: aName ifNone: [nil]) ifNotNil: [^sub]]].\\n\\t^aBlock value! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'rhi 9/10/2000 12:12'!\\nsubmorphOfClass: aClass\\n\\n\\t^self findA: aClass! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'efc 8/6/2005 11:35'!\\nsubmorphs\\n\\t\\\"This method returns my actual submorphs collection. Modifying the collection directly could be dangerous; make a copy if you need to alter it.\\\"\\n\\t^ submorphs ! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/4/97 14:30'!\\nsubmorphsBehind: aMorph do: aBlock\\n\\t| behind |\\n\\tbehind _ false.\\n\\tsubmorphs do:\\n\\t\\t[:m | m == aMorph ifTrue: [behind _ true]\\n\\t\\t\\t\\t\\t\\tifFalse: [behind ifTrue: [aBlock value: m]]].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 14:35'!\\nsubmorphsDo: aBlock \\n\\tsubmorphs do: aBlock! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'di 11/4/97 14:29'!\\nsubmorphsInFrontOf: aMorph do: aBlock\\n\\t| behind |\\n\\tbehind _ false.\\n\\tsubmorphs do:\\n\\t\\t[:m | m == aMorph ifTrue: [behind _ true]\\n\\t\\t\\t\\t\\t\\tifFalse: [behind ifFalse: [aBlock value: m]]].\\n! !\\n\\n!Morph methodsFor: 'submorphs-accessing'!\\nsubmorphsReverseDo: aBlock\\n\\n\\tsubmorphs reverseDo: aBlock.! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 8/15/97 22:03'!\\nsubmorphsSatisfying: aBlock\\n\\t^ submorphs select: [:m | (aBlock value: m) == true]! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 10/26/1999 23:42'!\\nsubmorphThat: block1 ifNone: block2\\n\\t^ submorphs detect: [:m | (block1 value: m) == true] ifNone: [block2 value]\\n\\t! !\\n\\n!Morph methodsFor: 'submorphs-accessing' stamp: 'sw 7/3/1998 18:47'!\\nsubmorphWithProperty: aSymbol\\n\\t^ submorphs detect: [:aMorph | aMorph hasProperty: aSymbol] ifNone: [nil]! !\\n\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'tk 12/15/1998 14:23'!\\nabandon\\n\\t\\\"Like delete, but we really intend not to use this morph again. Clean up a few things.\\\"\\n\\n\\tself delete! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/28/2001 08:39'!\\nactWhen\\n\\t\\\"Answer when the receiver, probably being used as a button, should have its action triggered\\\"\\n\\n\\t^ self valueOfProperty: #actWhen ifAbsentPut: [#buttonDown]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/25/2001 10:23'!\\nactWhen: aButtonPhase\\n\\t\\\"Set the receiver's actWhen trait\\\"\\n\\n\\tself setProperty: #actWhen toValue: aButtonPhase! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 23:28'!\\naddAllMorphs: aCollection\\n\\t^self privateAddAllMorphs: aCollection atIndex: submorphs size! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 23:29'!\\naddAllMorphs: aCollection after: anotherMorph\\n\\t^self privateAddAllMorphs: aCollection \\n\\t\\t\\tatIndex: (submorphs indexOf: anotherMorph ifAbsent: [submorphs size])! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:55'!\\naddMorphBack: aMorph\\n\\t^self privateAddMorph: aMorph atIndex: submorphs size+1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'RAA 12/15/2000 19:34'!\\naddMorphCentered: aMorph\\n\\n\\taMorph position: bounds center - (aMorph extent // 2).\\n\\tself addMorphFront: aMorph.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 12/16/2001 21:08'!\\naddMorphFrontFromWorldPosition: aMorph\\n\\t^self addMorphFront: aMorph fromWorldPosition: aMorph positionInWorld.! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:54'!\\naddMorphFront: aMorph\\n\\t^self privateAddMorph: aMorph atIndex: 1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 11/15/1998 23:42'!\\naddMorphFront: aMorph fromWorldPosition: wp\\n\\n\\tself addMorphFront: aMorph.\\n\\taMorph position: (self transformFromWorld globalPointToLocal: wp)! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 2/22/2003 14:26'!\\naddMorphNearBack: aMorph \\n\\t| bg |\\n\\t(submorphs notEmpty and: [submorphs last mustBeBackmost]) \\n\\t\\tifTrue: \\n\\t\\t\\t[bg := submorphs last.\\n\\t\\t\\tbg privateDelete].\\n\\tself addMorphBack: aMorph.\\n\\tbg ifNotNil: [self addMorphBack: bg]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove'!\\naddMorph: aMorph\\n\\n\\tself addMorphFront: aMorph.! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:54'!\\naddMorph: newMorph after: aMorph\\n\\t\\\"Add the given morph as one of my submorphs, inserting it after anotherMorph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: (submorphs indexOf: aMorph)+1! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/7/2000 08:29'!\\naddMorph: aMorph asElementNumber: aNumber\\n\\t\\\"Add the given morph so that it becomes the aNumber'th element of my submorph list. If aMorph is already one of my submorphs, reposition it\\\"\\n\\n\\t(submorphs includes: aMorph) ifTrue:\\n\\t\\t[aMorph privateDelete].\\n\\t(aNumber <= submorphs size)\\n\\t\\tifTrue:\\n\\t\\t\\t[self addMorph: aMorph inFrontOf: (submorphs at: aNumber)]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorphBack: aMorph]\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:44'!\\naddMorph: newMorph behind: aMorph\\n\\t\\\"Add a morph to the list of submorphs behind the specified morph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: (submorphs indexOf: aMorph) + 1.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'JW 2/1/2001 12:52'!\\naddMorph: aMorph fullFrame: aLayoutFrame\\n\\n\\taMorph layoutFrame: aLayoutFrame.\\n\\taMorph hResizing: #spaceFill; vResizing: #spaceFill.\\n\\tself addMorph: aMorph.\\n\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 1/31/2001 12:45'!\\naddMorph: newMorph inFrontOf: aMorph\\n\\t\\\"Add a morph to the list of submorphs in front of the specified morph\\\"\\n\\t^self privateAddMorph: newMorph atIndex: ((submorphs indexOf: aMorph) max: 1).! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 4/4/2006 17:17'!\\nallMorphsWithPlayersDo: aTwoArgumentBlock \\n\\t\\\"Evaluate the given block for all morphs in this composite morph that have non-nil players.\\n\\tAlso evaluate the block for the receiver if it has a player.\\\"\\n\\n\\tsubmorphs do: [:m | m allMorphsWithPlayersDo: aTwoArgumentBlock ].\\n\\tself playerRepresented ifNotNilDo: [ :p | aTwoArgumentBlock value: self value: p ].\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 2/22/2003 14:30'!\\ncomeToFront\\n\\t| outerMorph |\\n\\touterMorph := self topRendererOrSelf.\\n\\t(outerMorph owner isNil or: [outerMorph owner hasSubmorphs not]) \\n\\t\\tifTrue: [^self].\\n\\touterMorph owner firstSubmorph == outerMorph \\n\\t\\tifFalse: [outerMorph owner addMorphFront: outerMorph]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'di 10/27/97 23:26'!\\ncopyWithoutSubmorph: sub\\n\\t\\\"Needed to get a morph to draw without one of its submorphs.\\n\\tNOTE: This must be thrown away immediately after use.\\\"\\n\\t^ self clone privateSubmorphs: (submorphs copyWithout: sub)! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 9/10/2004 19:02'!\\ndelete\\n\\t\\\"Remove the receiver as a submorph of its owner and make its \\n\\tnew owner be nil.\\\"\\n\\n\\t| aWorld |\\n\\tself removeHalo.\\n\\taWorld := self world ifNil: [World].\\n\\t\\\"Terminate genie recognition focus\\\"\\n\\t\\\"I encountered a case where the hand was nil, so I put in a little \\n\\tprotection - raa \\\"\\n\\t\\\" This happens when we are in an MVC project and open\\n\\t a morphic window. - BG \\\"\\n\\taWorld ifNotNil:\\n\\t [self disableSubmorphFocusForHand: self activeHand.\\n\\t self activeHand releaseKeyboardFocus: self;\\n\\t\\t releaseMouseFocus: self.].\\n\\towner ifNotNil:[ self privateDelete.\\n\\t\\tself player ifNotNilDo: [ :player |\\n\\t\\t\\t\\\"Player must be notified\\\"\\n\\t\\t\\tplayer noteDeletionOf: self fromWorld: aWorld]].! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'dgd 9/1/2004 16:26'!\\ndeleteDockingBars\\n\\t\\\"Delete the receiver's docking bars\\\"\\n\\tself dockingBars\\n\\t\\tdo: [:each | each delete]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 7/3/1998 11:02'!\\ndeleteSubmorphsWithProperty: aSymbol\\n\\tsubmorphs copy do:\\n\\t\\t[:m | (m hasProperty: aSymbol) ifTrue: [m delete]]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 2/2/2006 02:39'!\\ndismissViaHalo\\n\\t\\\"The user has clicked in the delete halo-handle. This provides a hook in case some concomitant action should be taken, or if the particular morph is not one which should be put in the trash can, for example.\\\"\\n\\n\\t| cmd |\\n\\tself setProperty: #lastPosition toValue: self positionInWorld.\\n\\tself dismissMorph.\\n\\tPreferences preserveTrash ifTrue: [ \\n\\t\\tPreferences slideDismissalsToTrash\\n\\t\\t\\tifTrue:[self slideToTrash: nil]\\n\\t\\t\\tifFalse:[TrashCanMorph moveToTrash: self].\\n\\t].\\n\\n\\tcmd _ Command new cmdWording: 'dismiss ' translated, self externalName.\\n\\tcmd undoTarget: ActiveWorld selector: #reintroduceIntoWorld: argument: self.\\n\\tcmd redoTarget: ActiveWorld selector: #onceAgainDismiss: argument: self.\\n\\tActiveWorld rememberCommand: cmd! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 4/9/98 22:44'!\\ngoBehind\\n\\n\\towner addMorphNearBack: self.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/10/2003 18:31'!\\nprivateDelete\\n\\t\\\"Remove the receiver as a submorph of its owner\\\"\\n\\towner ifNotNil:[owner removeMorph: self].! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'nk 10/16/2003 14:08'!\\nremoveAllMorphs\\n\\t| oldMorphs myWorld |\\n\\tmyWorld _ self world.\\n\\t(fullBounds notNil or:[myWorld notNil]) ifTrue:[self invalidRect: self fullBounds].\\n\\tsubmorphs do: [:m | myWorld ifNotNil: [ m outOfWorld: myWorld ]. m privateOwner: nil].\\n\\toldMorphs _ submorphs.\\n\\tsubmorphs _ EmptyArray.\\n\\toldMorphs do: [ :m | self removedMorph: m ].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'nk 10/16/2003 14:02'!\\nremoveAllMorphsIn: aCollection\\n\\t\\\"greatly speeds up the removal of *lots* of submorphs\\\"\\n\\t| set myWorld |\\n\\tset _ IdentitySet new: aCollection size * 4 // 3.\\n\\taCollection do: [:each | each owner == self ifTrue: [ set add: each]].\\n\\tmyWorld _ self world.\\n\\t(fullBounds notNil or:[myWorld notNil]) ifTrue:[self invalidRect: self fullBounds].\\n\\tset do: [:m | myWorld ifNotNil: [ m outOfWorld: myWorld ]. m privateOwner: nil].\\n\\tsubmorphs _ submorphs reject: [ :each | set includes: each].\\n\\tset do: [ :m | self removedMorph: m ].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/12/2003 22:01'!\\nremovedMorph: aMorph\\n\\t\\\"Notify the receiver that aMorph was just removed from its children\\\"\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'di 10/18/2004 21:50'!\\nremoveMorph: aMorph\\n\\t\\\"Remove the given morph from my submorphs\\\"\\n\\t| aWorld |\\n\\taMorph owner == self ifFalse:[^self].\\n\\taWorld := self world.\\n\\taWorld ifNotNil:[\\n\\t\\taMorph outOfWorld: aWorld.\\n\\t\\tself privateInvalidateMorph: aMorph.\\n\\t].\\n\\tself privateRemove: aMorph.\\n\\taMorph privateOwner: nil.\\n\\tself removedMorph: aMorph.\\n! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 10/25/1999 23:34'!\\nreplaceSubmorph: oldMorph by: newMorph\\n\\t| index itsPosition w |\\n\\toldMorph stopStepping.\\n\\titsPosition _ oldMorph referencePositionInWorld.\\n\\tindex _ submorphs indexOf: oldMorph.\\n\\toldMorph privateDelete.\\n\\tself privateAddMorph: newMorph atIndex: index.\\n\\tnewMorph referencePositionInWorld: itsPosition.\\n\\t(w _ newMorph world) ifNotNil:\\n\\t\\t[w startSteppingSubmorphsOf: newMorph]! !\\n\\n!Morph methodsFor: 'submorphs-add/remove' stamp: 'sw 9/1/2000 10:16'!\\nsubmorphIndexOf: aMorph\\n\\t\\\"Assuming aMorph to be one of my submorphs, answer where it occurs in my submorph list\\\"\\n\\n\\t^ submorphs indexOf: aMorph ifAbsent: [nil]! !\\n\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 12/4/2000 10:44'!\\ncanDrawAtHigherResolution\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 8/25/2001 19:14'!\\ncanDrawBorder: aBorderStyle\\n\\t\\\"Return true if the receiver can be drawn with the given border style.\\\"\\n\\t^true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 10/20/2000 14:47'!\\ncompleteModificationHash\\n\\n\\\"World completeModificationHash\\\"\\n\\n\\t| resultSize result here i |\\n\\tresultSize _ 10.\\n\\tresult _ ByteArray new: resultSize.\\n\\tself allMorphsDo: [ :each | \\n\\t\\there _ each modificationHash.\\n\\t\\there withIndexDo: [ :ch :index |\\n\\t\\t\\ti _ index \\\\\\\\ resultSize + 1.\\n\\t\\t\\tresult at: i put: ((result at: i) bitXor: ch asciiValue)\\n\\t\\t].\\n\\t].\\n\\t^result! !\\n\\n!Morph methodsFor: 'testing' stamp: 'sw 3/30/2005 04:17'!\\ncouldMakeSibling\\n\\t\\\"Answer whether it is appropriate to ask the receiver to make a sibling\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dgd 8/31/2004 15:00'!\\nisDockingBar\\n\\t\\\"Return true if the receiver is a docking bar\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 9/22/2000 13:44'!\\nisFlexed\\n\\t\\\"Return true if the receiver is currently flexed\\\"\\n\\towner ifNil:[^false].\\n\\t^owner isFlexMorph! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dgd 9/20/2004 14:31'!\\nisFullOnScreen\\n\\t\\\"Answer if the receiver is full contained in the owner visible \\n\\tarea.\\\"\\n\\towner isInMemory\\n\\t\\tifFalse: [^ true].\\n\\towner isNil\\n\\t\\tifTrue: [^ true].\\n\\tself visible\\n\\t\\tifFalse: [^ true].\\n\\t^ owner clearArea containsRect: self fullBounds! !\\n\\n!Morph methodsFor: 'testing' stamp: 'nk 10/13/2003 18:36'!\\nisLineMorph\\n\\t^false! !\\n\\n!Morph methodsFor: 'testing'!\\nisMorph\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'testing' stamp: 'nk 6/12/2004 09:17'!\\nisSketchMorph\\n\\t^self class isSketchMorphClass! !\\n\\n!Morph methodsFor: 'testing' stamp: 'md 2/27/2006 09:59'!\\nknownName\\n\\t\\\"answer a name by which the receiver is known, or nil if none\\\"\\n\\t^ extension ifNotNil: [extension externalName]! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 10/20/2000 14:47'!\\nmodificationHash\\n\\n\\t^String \\n\\t\\tstreamContents: [ :strm |\\n\\t\\t\\tself longPrintOn: strm\\n\\t\\t]\\n\\t\\tlimitedTo: 25\\n! !\\n\\n!Morph methodsFor: 'testing' stamp: 'tk 7/28/2005 04:46'!\\nrenameInternal: aName \\n\\t\\\"Change the internal name (because of a conflict) but leave the external name unchanged. Change Player class name, but do not change the names that appear in tiles. When coming in from disk, and have name conflict, References will already have the new name. \\\"\\n\\n\\tself knownName = aName ifTrue: [^ aName].\\n\\tself topRendererOrSelf setNameTo: aName.\\n\\t\\n\\t\\\"References dictionary already has key aName\\\"\\n\\n\\t\\\"If this player has a viewer flap, it will remain present\\\"\\n\\n\\t\\\"Tiles in scripts all stay the same\\\"\\n\\n\\t\\\"Compiled methods for scripts have been fixed up because the same association was reused\\\"\\n\\t\\n\\t^ aName! !\\n\\n!Morph methodsFor: 'testing' stamp: 'dvf 8/23/2003 11:50'!\\nrenameTo: aName \\n\\t\\\"Set Player name in costume. Update Viewers. Fix all tiles (old style). fix \\n\\tReferences. New tiles: recompile, and recreate open scripts. If coming in \\n\\tfrom disk, and have name conflict, References will already have new \\n\\tname. \\\"\\n\\n\\t| aPresenter putInViewer aPasteUp renderer oldKey assoc classes oldName |\\n\\toldName := self knownName.\\n\\t(renderer := self topRendererOrSelf) setNameTo: aName.\\n\\tputInViewer := false.\\n\\t((aPresenter := self presenter) isNil or: [renderer player isNil]) \\n\\t\\tifFalse: \\n\\t\\t\\t[putInViewer := aPresenter currentlyViewing: renderer player.\\n\\t\\t\\tputInViewer ifTrue: [renderer player viewerFlapTab hibernate]].\\n\\t\\\"empty it temporarily\\\"\\n\\t(aPasteUp := self topPasteUp) \\n\\t\\tifNotNil: [aPasteUp allTileScriptingElements do: [:m | m bringUpToDate]].\\n\\t\\\"Fix References dictionary. See restoreReferences to know why oldKey is \\n\\talready aName, but oldName is the old name.\\\"\\n\\toldKey := References keyAtIdentityValue: renderer player ifAbsent: [].\\n\\toldKey ifNotNil: \\n\\t\\t\\t[assoc := References associationAt: oldKey.\\n\\t\\t\\toldKey = aName \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[\\\"normal rename\\\"\\n\\n\\t\\t\\t\\t\\tassoc key: (renderer player uniqueNameForReferenceFrom: aName).\\n\\t\\t\\t\\t\\tReferences rehash]].\\n\\tputInViewer ifTrue: [aPresenter viewMorph: self].\\n\\t\\\"recreate my viewer\\\"\\n\\toldKey ifNil: [^aName].\\n\\t\\\"Force strings in tiles to be remade with new name. New tiles only.\\\"\\n\\tPreferences universalTiles ifFalse: [^aName].\\n\\tclasses := (self systemNavigation allCallsOn: assoc) \\n\\t\\t\\t\\tcollect: [:each | each classSymbol].\\n\\tclasses asSet \\n\\t\\tdo: [:clsName | (Smalltalk at: clsName) replaceSilently: oldName to: aName].\\n\\t\\\"replace in text body of all methods. Can be wrong!!\\\"\\n\\t\\\"Redo the tiles that are showing. This is also done in caller in \\n\\tunhibernate. \\\"\\n\\taPasteUp ifNotNil: \\n\\t\\t\\t[aPasteUp allTileScriptingElements do: \\n\\t\\t\\t\\t\\t[:mm | \\n\\t\\t\\t\\t\\t\\\"just ScriptEditorMorphs\\\"\\n\\n\\t\\t\\t\\t\\tnil.\\n\\t\\t\\t\\t\\t(mm isKindOf: ScriptEditorMorph) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[((mm playerScripted class compiledMethodAt: mm scriptName) \\n\\t\\t\\t\\t\\t\\t\\t\\thasLiteral: assoc) \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[mm\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thibernate;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tunhibernate]]]].\\n\\t^aName! !\\n\\n!Morph methodsFor: 'testing' stamp: 'ar 12/3/2001 12:33'!\\nshouldDropOnMouseUp\\n\\t| former |\\n\\tformer _ self formerPosition ifNil:[^false].\\n\\t^(former dist: self position) > 10! !\\n\\n!Morph methodsFor: 'testing' stamp: 'RAA 1/16/2001 17:20'!\\nstepTime\\n\\t\\\"Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.\\\"\\n\\n\\t^ self topRendererOrSelf player ifNotNil: [10] ifNil: [1000]! !\\n\\n!Morph methodsFor: 'testing' stamp: 'sw 10/24/2004 15:28'!\\nwantsSteps\\n\\t\\\"Return true if the receiver overrides the default Morph step method.\\\"\\n\\t\\\"Details: Find first class in superclass chain that implements #step and return true if it isn't class Morph.\\\"\\n\\n\\t| c |\\n\\tself isPartsDonor ifTrue: [^ false].\\n\\t(self == self topRendererOrSelf) ifTrue: [self player wantsSteps ifTrue: [^ true]].\\n\\tc _ self class.\\n\\t[c includesSelector: #step] whileFalse: [c _ c superclass].\\n\\t^ c ~= Morph! !\\n\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/17/2001 12:45'!\\naddTextAnchorMenuItems: topMenu hand: aHand\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addUpdating: #hasInlineAnchorString action: #changeInlineAnchor.\\n\\taMenu addUpdating: #hasParagraphAnchorString action: #changeParagraphAnchor.\\n\\taMenu addUpdating: #hasDocumentAnchorString action: #changeDocumentAnchor.\\n\\ttopMenu ifNotNil:[topMenu add: 'text anchor' subMenu: aMenu].\\n\\t^aMenu! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:47'!\\nchangeDocumentAnchor\\n\\t\\\"Change the anchor from/to document anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #document \\n\\t\\tifTrue: [#paragraph]\\n\\t\\tifFalse: [ #document].\\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:48'!\\nchangeInlineAnchor\\n\\t\\\"Change the anchor from/to line anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #inline \\n\\t\\t\\t\\tifTrue: [#paragraph]\\n\\t\\t\\t\\tifFalse: [#inline]. \\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'aoy 2/15/2003 21:48'!\\nchangeParagraphAnchor\\n\\t\\\"Change the anchor from/to paragraph anchoring\\\"\\n\\n\\t| newType |\\n\\tnewType := self textAnchorType == #paragraph \\n\\t\\tifTrue: [#document]\\n\\t\\tifFalse: [#paragraph].\\n\\towner isTextMorph \\n\\t\\tifTrue: \\n\\t\\t\\t[owner \\n\\t\\t\\t\\tanchorMorph: self\\n\\t\\t\\t\\tat: self position\\n\\t\\t\\t\\ttype: newType]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasDocumentAnchorString\\n\\t^ (self textAnchorType == #document\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Document' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasInlineAnchorString\\n\\t^ (self textAnchorType == #inline\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Inline' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'dgd 9/6/2003 18:14'!\\nhasParagraphAnchorString\\n\\t^ (self textAnchorType == #paragraph\\n\\t\\tifTrue: ['<on>']\\n\\t\\tifFalse: ['<off>'])\\n\\t\\t, 'Paragraph' translated! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 19:47'!\\nrelativeTextAnchorPosition\\n\\t^self valueOfProperty: #relativeTextAnchorPosition! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 19:22'!\\nrelativeTextAnchorPosition: aPoint\\n\\t^self setProperty: #relativeTextAnchorPosition toValue: aPoint! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 18:36'!\\ntextAnchorType\\n\\t^self valueOfProperty: #textAnchorType ifAbsent:[#document]! !\\n\\n!Morph methodsFor: 'text-anchor' stamp: 'ar 12/16/2001 18:37'!\\ntextAnchorType: aSymbol\\n\\taSymbol == #document\\n\\t\\tifTrue:[^self removeProperty: #textAnchorType]\\n\\t\\tifFalse:[^self setProperty: #textAnchorType toValue: aSymbol].! !\\n\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 10/26/2000 08:32'!\\ndemandsThumbnailing\\n\\t\\\"Answer whether the receiver, if in a thumbnailable parts bin, wants to be thumbnailed whether or not size requires it\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/12/2004 21:12'!\\nicon\\n\\t\\\"Answer a form with an icon to represent the receiver\\\"\\n\\t^ self valueOfProperty: #icon! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/12/2004 20:33'!\\niconOrThumbnail\\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\n\\t^ self icon\\n\\t\\tifNil: [ | maxExtent fb |maxExtent := 320 @ 240.\\n\\t\\t\\tfb := self fullBounds.\\n\\t\\t\\tfb area <= (maxExtent x * maxExtent y)\\n\\t\\t\\t\\tifTrue: [self imageForm]\\n\\t\\t\\t\\tifFalse: [self imageFormForRectangle: (fb topLeft extent: maxExtent)]\\n\\t\\t]\\n! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'dgd 9/13/2004 12:43'!\\niconOrThumbnailOfSize: aNumberOrPoint \\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\n\\t^ self iconOrThumbnail scaledIntoFormOfSize: aNumberOrPoint\\n! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 8/16/2000 17:40'!\\nmorphRepresented\\n\\t\\\"If the receiver is an alias, answer the morph it represents; else answer self\\\"\\n\\n\\t^ self! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 6/16/1999 11:29'!\\npermitsThumbnailing\\n\\t^ true! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'ar 11/9/2000 20:42'!\\nreadoutForField: fieldSym\\n\\t\\\"Provide a readout that will show the value of the slot/pseudoslot of the receiver generated by sending fieldSym to the receiver\\\"\\n\\n\\t| aContainer |\\n\\t\\\"still need to get this right\\\"\\n\\taContainer _ AlignmentMorph newColumn.\\n\\taContainer layoutInset: 0; hResizing: #rigid; vResizing: #shrinkWrap.\\n\\taContainer addMorphBack: (StringMorph new contents: (self perform: fieldSym) asString).\\n\\t^ aContainer! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'sw 12/6/2000 21:28'!\\nrepresentativeNoTallerThan: maxHeight norWiderThan: maxWidth thumbnailHeight: thumbnailHeight\\n\\t\\\"Return a morph representing the receiver but which is no taller than aHeight. If the receiver is already small enough, just return it, else return a MorphThumbnail companioned to the receiver, enforcing the maxWidth. If the receiver personally *demands* thumbnailing, do it even if there is no size-related reason to do it.\\\"\\n\\n\\tself demandsThumbnailing ifFalse:\\n\\t\\t[self permitsThumbnailing ifFalse: [^ self].\\n\\t\\t(self fullBounds height <= maxHeight and: [self fullBounds width <= maxWidth]) ifTrue: [^ self]].\\n\\n\\t^ MorphThumbnail new extent: maxWidth @ (thumbnailHeight min: self fullBounds height); morphRepresented: self! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'tk 3/28/2000 11:08'!\\nupdateThumbnailUrl\\n\\t\\\"If I have a cached thumbnail, then update it's urls.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail pageMorph: self url inBook: owner url]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\t\\\"Test and removal are because the thumbnail is being replaced \\n\\t\\t\\tby another Morph. We don't know why. Need to fix that at \\n\\t\\t\\tthe source.\\\"! !\\n\\n!Morph methodsFor: 'thumbnail' stamp: 'tk 3/28/2000 21:55'!\\nupdateThumbnailUrlInBook: bookUrl\\n\\t\\\"If I have a cached thumbnail, then update it's urls.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail pageMorph: self url inBook: bookUrl]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\t\\\"Test and removal are because the thumbnail is being replaced \\n\\t\\t\\tby another Morph. We don't know why. Need to fix that at \\n\\t\\t\\tthe source.\\\"! !\\n\\n\\n!Morph methodsFor: 'undo' stamp: 'ar 8/31/2000 23:15'!\\ncommandHistory\\n\\t\\\"Return the command history for the receiver\\\"\\n\\t| w |\\n\\t(w _ self world) ifNotNil:[^w commandHistory].\\n\\t(w _ self currentWorld) ifNotNil:[^w commandHistory].\\n\\t^CommandHistory new. \\\"won't really record anything but prevent breaking things\\\"! !\\n\\n!Morph methodsFor: 'undo' stamp: 'md 10/22/2003 15:56'!\\nundoMove: cmd redo: redo owner: formerOwner bounds: formerBounds predecessor: formerPredecessor \\n\\t\\\"Handle undo and redo of move commands in morphic\\\"\\n\\n\\tself owner ifNil: [^Beeper beep].\\n\\tredo \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"undo sets up the redo state first\\\"\\n\\n\\t\\t\\tcmd \\n\\t\\t\\t\\tredoTarget: self\\n\\t\\t\\t\\tselector: #undoMove:redo:owner:bounds:predecessor:\\n\\t\\t\\t\\targuments: { \\n\\t\\t\\t\\t\\t\\tcmd.\\n\\t\\t\\t\\t\\t\\ttrue.\\n\\t\\t\\t\\t\\t\\towner.\\n\\t\\t\\t\\t\\t\\tbounds.\\n\\t\\t\\t\\t\\t\\towner morphPreceding: self}].\\n\\tformerOwner ifNotNil: \\n\\t\\t\\t[formerPredecessor ifNil: [formerOwner addMorphFront: self]\\n\\t\\t\\t\\tifNotNil: [formerOwner addMorph: self after: formerPredecessor]].\\n\\tself bounds: formerBounds.\\n\\t(self isSystemWindow) ifTrue: [self activate]! !\\n\\n\\n!Morph methodsFor: 'updating' stamp: 'ar 6/25/2001 19:46'!\\nchanged\\n\\t\\\"Report that the area occupied by this morph should be redrawn.\\\"\\n\\t^fullBounds \\n\\t\\tifNil:[self invalidRect: self outerBounds]\\n\\t\\tifNotNil:[self invalidRect: fullBounds]! !\\n\\n\\n!Morph methodsFor: 'user interface' stamp: 'tak 3/15/2005 17:36'!\\nbecomeModal\\n\\tself currentWorld\\n\\t\\tifNotNil: [self currentWorld modalWindow: self]! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'sw 5/29/2000 00:41'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\t^ super printString truncateTo: 40! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'tak 3/15/2005 17:10'!\\ndoCancel\\n\\tself delete! !\\n\\n!Morph methodsFor: 'user interface' stamp: 'sw 10/2/97 23:08'!\\ninitialExtent\\n\\t| ext |\\n\\t(ext _ self valueOfProperty: #initialExtent)\\n\\t\\tifNotNil:\\n\\t\\t\\t[^ ext].\\n\\t^ super initialExtent! !\\n\\n\\n!Morph methodsFor: 'viewer' stamp: 'sw 10/30/1998 14:46'!\\nexternalName\\n\\t^ self knownName ifNil: [self innocuousName]! !\\n\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/25/1999 11:11'!\\ncanHaveFillStyles\\n\\t\\\"Return true if the receiver can have general fill styles; not just colors.\\n\\tThis method is for gradually converting old morphs.\\\"\\n\\t^self class == Morph \\\"no subclasses\\\"! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'mk 8/7/2005 10:02'!\\ncornerStyle\\n\\t\\\"Returns one of the following symbols:\\n\\t\\t#square\\n\\t\\t#rounded\\n\\taccording to the current corner style.\\\"\\n\\n\\t^ self valueOfProperty: #cornerStyle ifAbsent: [#square]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 8/28/2003 15:56'!\\ndefaultBitmapFillForm\\n\\t^ImageMorph defaultForm.\\n! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'dgd 2/16/2003 20:02'!\\nfillStyle\\n\\t\\\"Return the current fillStyle of the receiver.\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #fillStyle\\n\\t\\tifAbsent: [\\\"Workaround already converted morphs\\\"\\n\\t\\t\\tcolor\\n\\t\\t\\t\\tifNil: [self defaultColor]]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/18/1999 07:05'!\\nfillStyle: aFillStyle\\n\\t\\\"Set the current fillStyle of the receiver.\\\"\\n\\tself setProperty: #fillStyle toValue: aFillStyle.\\n\\t\\\"Workaround for Morphs not yet converted\\\"\\n\\tcolor _ aFillStyle asColor.\\n\\tself changed.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'dgd 1/7/2005 19:31'!\\nfillWithRamp: rampSpecsOrColor oriented: aRatio \\n\\trampSpecsOrColor isColor\\n\\t\\tifTrue: [self color: rampSpecsOrColor\\\".\\n\\t\\t\\tself borderColor: rampSpecsOrColor muchDarker\\\"]\\n\\t\\tifFalse: [| fill | \\n\\t\\t\\tfill := GradientFillStyle ramp: rampSpecsOrColor.\\n\\t\\t\\tfill origin: self bounds topLeft.\\n\\t\\t\\tfill direction: (self bounds extent * aRatio) truncated.\\n\\t\\t\\tfill radial: false.\\n\\t\\t\\tself fillStyle: fill.\\n\\t\\t\\tself borderColor: (rampSpecsOrColor first value mixed: 0.5 with: rampSpecsOrColor last value) muchDarker]! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 8/28/2003 15:57'!\\nuseBitmapFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\t| fill |\\n\\tself fillStyle isBitmapFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tfill _ BitmapFillStyle fromForm: self defaultBitmapFillForm.\\n\\t\\\"Note: Must fix the origin due to global coordinates\\\"\\n\\tfill origin: self bounds origin.\\n\\tself fillStyle: fill.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/25/1999 11:11'!\\nuseDefaultFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\tself fillStyle: self defaultColor.! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'nk 2/27/2003 11:48'!\\nuseGradientFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\t| fill color1 color2 |\\n\\tself fillStyle isGradientFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tcolor1 _ self color asColor.\\n\\tcolor2 _ color1 negated.\\n\\tfill _ GradientFillStyle ramp: {0.0 -> color1. 1.0 -> color2}.\\n\\tfill origin: self topLeft.\\n\\tfill direction: 0 @ self bounds extent y.\\n\\tfill normal: self bounds extent x @ 0.\\n\\tfill radial: false.\\n\\tself fillStyle: fill! !\\n\\n!Morph methodsFor: 'visual properties' stamp: 'ar 6/18/1999 06:57'!\\nuseSolidFill\\n\\t\\\"Make receiver use a solid fill style (e.g., a simple color)\\\"\\n\\tself fillStyle isSolidFill ifTrue:[^self]. \\\"Already done\\\"\\n\\tself fillStyle: self fillStyle asColor. \\\"Try minimizing changes\\\"! !\\n\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 2/16/2001 13:57'!\\naddMorphInFrontOfLayer: aMorph\\n\\n\\t| targetLayer layerHere |\\n\\n\\ttargetLayer _ aMorph morphicLayerNumberWithin: self.\\n\\tsubmorphs do: [ :each |\\n\\t\\teach == aMorph ifTrue: [^self].\\n\\t\\tlayerHere _ each morphicLayerNumberWithin: self.\\n\\t\\t\\\"the <= is the difference - it insures we go to the front of our layer\\\"\\n\\t\\ttargetLayer <= layerHere ifTrue: [\\n\\t\\t\\t^self addMorph: aMorph inFrontOf: each\\n\\t\\t].\\n\\t].\\n\\tself addMorphBack: aMorph.\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 6/29/2000 10:49'!\\naddMorphInLayer: aMorph\\n\\n\\tsubmorphs do: [ :each |\\n\\t\\teach == aMorph ifTrue: [^self].\\n\\t\\taMorph morphicLayerNumber < each morphicLayerNumber ifTrue: [\\n\\t\\t\\t^self addMorph: aMorph inFrontOf: each\\n\\t\\t].\\n\\t].\\n\\tself addMorphBack: aMorph\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'gk 5/24/2004 15:43'!\\neToyRejectDropMorph: morphToDrop event: evt\\n\\n\\t| tm am |\\n\\n\\ttm _ TextMorph new \\n\\t\\tbeAllFont: ((TextStyle named: Preferences standardEToysFont familyName) fontOfSize: 24);\\n\\t\\tcontents: 'GOT IT!!'.\\n\\t(am _ AlignmentMorph new)\\n\\t\\tcolor: Color yellow;\\n\\t\\tlayoutInset: 10;\\n\\t\\tuseRoundedCorners;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\taddMorph: tm;\\n\\t\\tfullBounds;\\n\\t\\tposition: (self bounds center - (am extent // 2));\\n\\t\\topenInWorld: self world.\\n\\tSoundService default playSoundNamed: 'yum' ifAbsentReadFrom: 'yum.aif'.\\n\\tmorphToDrop rejectDropMorphEvent: evt.\\t\\t\\\"send it back where it came from\\\"\\n\\tam delete\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 7/19/2000 20:44'!\\nmorphicLayerNumber\\n\\n\\t\\\"helpful for insuring some morphs always appear in front of or behind others.\\n\\tsmaller numbers are in front\\\"\\n\\n\\t^(owner isNil or: [owner isWorldMorph]) ifTrue: [\\n\\t\\tself valueOfProperty: #morphicLayerNumber ifAbsent: [100]\\n\\t] ifFalse: [\\n\\t\\towner morphicLayerNumber\\n\\t].\\n\\n\\t\\\"leave lots of room for special things\\\"! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 2/16/2001 13:54'!\\nmorphicLayerNumberWithin: anOwner\\n\\n\\t\\\"helpful for insuring some morphs always appear in front of or behind others.\\n\\tsmaller numbers are in front\\\"\\n\\n\\t^(owner isNil or: [owner isWorldMorph or: [anOwner == owner]]) ifTrue: [\\n\\t\\tself valueOfProperty: #morphicLayerNumber ifAbsent: [100]\\n\\t] ifFalse: [\\n\\t\\towner morphicLayerNumber\\n\\t].\\n\\n\\t\\\"leave lots of room for special things\\\"! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'RAA 7/16/2000 13:54'!\\nrandomBoundsFor: aMorph\\n\\n\\t| trialRect |\\n\\ttrialRect _ (\\n\\t\\tself topLeft + \\n\\t\\t\\t((self width * (15 + 75 atRandom/100)) rounded @\\n\\t\\t\\t(self height * (15 + 75 atRandom/100)) rounded)\\n\\t) extent: aMorph extent.\\n\\t^trialRect translateBy: (trialRect amountToTranslateWithin: self bounds)\\n! !\\n\\n!Morph methodsFor: 'WiW support' stamp: 'ar 3/18/2001 00:14'!\\nshouldGetStepsFrom: aWorld\\n\\t^self world == aWorld! !\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/24/2003 17:31'!\\ninstantiatedUserScriptsDo: aBlock\\n\\tself actorStateOrNil ifNotNilDo: [ :aState | aState instantiatedUserScriptsDictionary do: aBlock]! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:36'!\\nremoveAllEventTriggers\\n\\t\\\"Remove all the event registrations for my Player.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\t| player |\\n\\t(player _ self player) ifNil: [ ^self ].\\n\\tself removeAllEventTriggersFor: player.\\n\\tself currentWorld removeAllEventTriggersFor: player.! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/24/2003 17:46'!\\nremoveAllEventTriggersFor: aPlayer\\n\\t\\\"Remove all the event registrations for aPlayer.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\tself removeActionsSatisfying: \\n\\t\\t\\t[:action | action receiver == aPlayer and: [(#(#doScript: #triggerScript:) includes: action selector) ]].! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:37'!\\nremoveEventTrigger: aSymbol\\n\\t\\\"Remove all the event registrations for my Player that are triggered by aSymbol.\\n\\tUser custom events are triggered at the World,\\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\n\\t| player |\\n\\t(player _ self player) ifNil: [ ^self ].\\n\\tself removeEventTrigger: aSymbol for: player.\\n\\tself currentWorld removeEventTrigger: aSymbol for: player.! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:24'!\\nremoveEventTrigger: aSymbol for: aPlayer \\n\\t\\\"Remove all the event registrations for aPlayer that are triggered by \\n\\taSymbol. User custom events are triggered at the World, \\n\\twhile system custom events are triggered on individual Morphs.\\\"\\n\\tself removeActionsSatisfying: [:action | action receiver == aPlayer\\n\\t\\t\\t\\tand: [(#(#doScript: #triggerScript: ) includes: action selector)\\n\\t\\t\\t\\t\\t\\tand: [action arguments first == aSymbol]]]! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 9/25/2003 11:11'!\\nrenameScriptActionsFor: aPlayer from: oldSelector to: newSelector\\n\\n\\tself updateableActionMap keysAndValuesDo: [ :event :sequence |\\n\\t\\tsequence asActionSequence do: [ :action |\\n\\t\\t\\t((action receiver == aPlayer)\\n\\t\\t\\t\\tand: [ (#(doScript: triggerScript:) includes: action selector)\\n\\t\\t\\t\\t\\tand: [ action arguments first == oldSelector ]])\\n\\t\\t\\t\\t\\t\\tifTrue: [ action arguments at: 1 put: newSelector ]]]\\n! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 11:00'!\\ntriggerCustomEvent: aSymbol\\n\\t\\\"Trigger whatever scripts may be connected to the custom event named aSymbol\\\"\\n\\n\\tself currentWorld triggerEtoyEvent: aSymbol from: self! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 10:54'!\\ntriggerEtoyEvent: aSymbol\\n\\t\\\"Trigger whatever scripts may be connected to the event named aSymbol.\\n\\tIf anyone comes back to ask who sent it, return our player.\\\"\\n\\n\\t[ self triggerEvent: aSymbol ]\\n\\t\\ton: GetTriggeringObjectNotification do: [ :ex |\\n\\t\\t\\tex isNested\\n\\t\\t\\t\\tifTrue: [ ex pass ]\\n\\t\\t\\t\\tifFalse: [ ex resume: self assuredPlayer ]]\\n! !\\n\\n!Morph methodsFor: '*eToys-customevents-scripting' stamp: 'nk 11/1/2004 10:58'!\\ntriggerEtoyEvent: aSymbol from: aMorph\\n\\t\\\"Trigger whatever scripts may be connected to the event named aSymbol.\\n\\tIf anyone comes back to ask who sent it, return aMorph's player.\\\"\\n\\n\\t[ self triggerEvent: aSymbol ]\\n\\t\\ton: GetTriggeringObjectNotification do: [ :ex |\\n\\t\\t\\tex isNested\\n\\t\\t\\t\\tifTrue: [ ex pass ]\\n\\t\\t\\t\\tifFalse: [ ex resume: aMorph assuredPlayer ]]\\n! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*Flash-classification' stamp: 'ar 8/10/1998 18:50'!\\nisFlashMorph\\n\\t^false! !\\n\\n\\n!Morph methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 17:31'!\\nunfilteredCategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer, in order of:\\n\\t- masterOrderingOfCategorySymbols first\\n\\t- others last in order by translated wording\\\"\\n\\t\\\"\\n\\tMorph basicNew unfilteredCategoriesForViewer\\n\\t\\\"\\n\\t^self renderedMorph class unfilteredCategoriesForViewer.\\n! !\\n\\n\\n!Morph methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 1/7/2005 19:07'!\\nhighlightOnlySubmorph: aMorph\\n\\t\\\"Distinguish only aMorph with border highlighting (2-pixel wide red); make all my other submorphs have one-pixel-black highlighting. This is a rather special-purpose and hard-coded highlighting regime, of course. Later, if someone cared to do it, we could parameterize the widths and colors via properties, or some such.\\\"\\n\\n\\tself submorphs do:\\n\\t\\t[:m |\\n\\t\\t\\tm == aMorph\\n\\t\\t\\t\\tifTrue: [m borderWidth: 1; borderColor: Color red. m firstSubmorph color: Color red]\\n\\t\\t\\t\\tifFalse: [m borderWidth: 1; borderColor: Color black. m firstSubmorph color: Color black]\\n\\t\\t].\\n! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*MorphicExtras-geometry' stamp: 'dgd 8/31/2004 16:22'!\\nshiftSubmorphsBy: delta\\n\\tself shiftSubmorphsOtherThan: (submorphs select: [:m | m wantsToBeTopmost]) by: delta! !\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*MorphicExtras-menus' stamp: 'dgd 4/3/2006 14:18'!\\ndismissButton\\n\\t\\\"Answer a button whose action would be to dismiss the receiver, and whose action is to send #delete to the receiver\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton\\n\\t\\ttarget: self topRendererOrSelf;\\n\\t\\tcolor: ColorTheme current cancelColor;\\n\\t\\tborderColor: ColorTheme current cancelColor muchDarker;\\n\\t\\tborderWidth: 1;\\n\\t\\tlabel: 'X' font: Preferences standardButtonFont;\\n\\t\\tactionSelector: #delete;\\n\\t\\tsetBalloonText: 'dismiss' translated.\\n\\t^ aButton! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Morph methodsFor: '*services-base' stamp: 'rr 6/10/2005 11:30'!\\nrequestor\\n\\t^ owner ifNil: [super requestor] ifNotNil: [owner requestor]! !\\n\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 17:29'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tt > rightTime ifTrue: [^ self]. \\n\\tt < leftTime ifTrue: [^ self].\\n\\tmorphList add: (self left: (pianoRoll xForTime: t)).\\n! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 15:48'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tself triggerActionFromPianoRoll.! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'stephaneducasse 2/4/2006 20:40'!\\njustDroppedIntoPianoRoll: pianoRoll event: evt\\n\\t\\n\\t| ambientEvent startTimeInScore |\\n\\tstartTimeInScore := pianoRoll timeForX: self left.\\n\\n\\tambientEvent := AmbientEvent new \\n\\t\\tmorph: self;\\n\\t\\ttime: startTimeInScore.\\n\\n\\tpianoRoll score addAmbientEvent: ambientEvent.\\n\\n\\t\\\"self endTime > pianoRoll scorePlayer durationInTicks ifTrue:\\n\\t\\t[pianoRoll scorePlayer updateDuration]\\\"\\n! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:21'!\\npauseFrom: scorePlayer\\n\\n\\t\\\"subclasses should take five\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:22'!\\nresetFrom: scorePlayer\\n\\n\\t\\\"subclasses should revert to their initial state\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'RAA 12/11/2000 23:21'!\\nresumeFrom: scorePlayer\\n\\n\\t\\\"subclasses should continue from their current position\\\"\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"! !\\n\\n!Morph methodsFor: '*sound-piano rolls' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ntriggerActionFromPianoRoll\\n\\n\\t| evt |\\n\\t\\\"a hack to allow for abitrary morphs to be dropped into piano roll\\\"\\n\\tself world ifNil: [^self].\\n\\tevt := MouseEvent new setType: nil position: self center buttons: 0 hand: self world activeHand.\\n\\tself programmedMouseUp: evt for: self.\\n\\n! !\\n\\n\\n!Morph methodsFor: 'private' stamp: 'sw 10/25/2000 06:11'!\\nmoveWithPenDownBy: delta\\n\\t\\\"If this is a costume for a player with its pen down, draw a line.\\\"\\n\\n\\t| trailMorph tfm start tfmEnd |\\n\\t(trailMorph _ self trailMorph) ifNotNil:\\n\\t\\t[tfm _ self owner transformFrom: trailMorph.\\n\\t\\tstart _ self referencePosition.\\n\\t\\ttrailMorph batchPenTrails\\n\\t\\t\\tifTrue: [trailMorph notePenDown: true\\n\\t\\t\\t\\t\\t\\t\\t\\tforPlayer: self player\\n\\t\\t\\t\\t\\t\\t\\t\\tat: (tfm localPointToGlobal: start)]\\n\\t\\t\\tifFalse: [trailMorph drawPenTrailFor: self\\n\\t\\t\\t\\t\\t\\t\\t\\tfrom: (tfm localPointToGlobal: start)\\n\\t\\t\\t\\t\\t\\t\\t\\tto: (tfmEnd _ tfm localPointToGlobal: start + delta).\\n\\t\\t\\t\\t\\ttrailMorph noteNewLocation: tfmEnd forPlayer: self player]]\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'nk 10/11/2003 16:08'!\\nprivateAddAllMorphs: aCollection atIndex: index\\n\\t\\\"Private. Add aCollection of morphs to the receiver\\\"\\n\\t| myWorld itsWorld otherSubmorphs |\\n\\tmyWorld _ self world.\\n\\totherSubmorphs _ submorphs copyWithoutAll: aCollection.\\n\\t(index between: 0 and: otherSubmorphs size)\\n\\t\\tifFalse: [^ self error: 'index out of range'].\\n\\tindex = 0\\n\\t\\tifTrue:[\\tsubmorphs _ aCollection asArray, otherSubmorphs]\\n\\t\\tifFalse:[\\tindex = otherSubmorphs size\\n\\t\\t\\tifTrue:[\\tsubmorphs _ otherSubmorphs, aCollection]\\n\\t\\t\\tifFalse:[\\tsubmorphs _ otherSubmorphs copyReplaceFrom: index + 1 to: index with: aCollection ]].\\n\\taCollection do: [:m | | itsOwner |\\n\\t\\titsOwner _ m owner.\\n\\t\\titsOwner ifNotNil: [\\n\\t\\t\\titsWorld _ m world.\\n\\t\\t\\t(itsWorld == myWorld) ifFalse: [\\n\\t\\t\\t\\titsWorld ifNotNil: [self privateInvalidateMorph: m].\\n\\t\\t\\t\\tm outOfWorld: itsWorld].\\n\\t\\t\\t(itsOwner ~~ self) ifTrue: [\\n\\t\\t\\t\\tm owner privateRemove: m.\\n\\t\\t\\t\\tm owner removedMorph: m ]].\\n\\t\\tm privateOwner: self.\\n\\t\\tmyWorld ifNotNil: [self privateInvalidateMorph: m].\\n\\t\\t(myWorld == itsWorld) ifFalse: [m intoWorld: myWorld].\\n\\t\\titsOwner == self ifFalse: [\\n\\t\\t\\tself addedMorph: m.\\n\\t\\t\\tm noteNewOwner: self ].\\n\\t].\\n\\tself layoutChanged.\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'nk 10/11/2003 16:08'!\\nprivateAddMorph: aMorph atIndex: index\\n\\n\\t| oldIndex myWorld itsWorld oldOwner |\\n\\t((index >= 1) and: [index <= (submorphs size + 1)])\\n\\t\\tifFalse: [^ self error: 'index out of range'].\\n\\tmyWorld _ self world.\\n\\toldOwner _ aMorph owner.\\n\\t(oldOwner == self and: [(oldIndex _ submorphs indexOf: aMorph) > 0]) ifTrue:[\\n\\t\\t\\\"aMorph's position changes within in the submorph chain\\\"\\n\\t\\toldIndex < index ifTrue:[\\n\\t\\t\\t\\\"moving aMorph to back\\\"\\n\\t\\t\\tsubmorphs replaceFrom: oldIndex to: index-2 with: submorphs startingAt: oldIndex+1.\\n\\t\\t\\tsubmorphs at: index-1 put: aMorph.\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"moving aMorph to front\\\"\\n\\t\\t\\toldIndex-1 to: index by: -1 do:[:i|\\n\\t\\t\\t\\tsubmorphs at: i+1 put: (submorphs at: i)].\\n\\t\\t\\tsubmorphs at: index put: aMorph.\\n\\t\\t].\\n\\t] ifFalse:[\\n\\t\\t\\\"adding a new morph\\\"\\n\\t\\toldOwner ifNotNil:[\\n\\t\\t\\titsWorld _ aMorph world.\\n\\t\\t\\titsWorld ifNotNil: [self privateInvalidateMorph: aMorph].\\n\\t\\t\\t(itsWorld == myWorld) ifFalse: [aMorph outOfWorld: itsWorld].\\n\\t\\t\\toldOwner privateRemove: aMorph.\\n\\t\\t\\toldOwner removedMorph: aMorph.\\n\\t\\t].\\n\\t\\taMorph privateOwner: self.\\n\\t\\tsubmorphs _ submorphs copyReplaceFrom: index to: index-1 with: (Array with: aMorph).\\n\\t\\t(itsWorld == myWorld) ifFalse: [aMorph intoWorld: myWorld].\\n\\t].\\n\\tmyWorld ifNotNil:[self privateInvalidateMorph: aMorph].\\n\\tself layoutChanged.\\n\\toldOwner == self ifFalse: [\\n\\t\\tself addedMorph: aMorph.\\n\\t\\taMorph noteNewOwner: self ].\\n! !\\n\\n!Morph methodsFor: 'private'!\\nprivateBounds: boundsRect\\n\\t\\\"Private!! Use position: and/or extent: instead.\\\"\\n\\n\\tfullBounds _ nil.\\n\\tbounds _ boundsRect.! !\\n\\n!Morph methodsFor: 'private' stamp: 'jm 5/29/1998 21:28'!\\nprivateColor: aColor\\n\\n\\tcolor _ aColor.\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'RAA 5/23/2000 11:31'!\\nprivateDeleteWithAbsolutelyNoSideEffects\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\t\\\"used to delete a morph from an inactive world\\\"\\n\\n\\towner ifNil: [^self].\\n\\towner privateRemoveMorphWithAbsolutelyNoSideEffects: self.\\n\\towner _ nil.\\n\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'tk 8/30/1998 09:58'!\\nprivateFullBounds: boundsRect\\n\\t\\\"Private!! Computed automatically.\\\"\\n\\n\\tfullBounds _ boundsRect.! !\\n\\n!Morph methodsFor: 'private' stamp: 'ar 12/16/2001 21:47'!\\nprivateFullMoveBy: delta\\n\\t\\\"Private!! Relocate me and all of my subMorphs by recursion. Subclasses that implement different coordinate systems may override this method.\\\"\\n\\n\\tself privateMoveBy: delta.\\n\\t1 to: submorphs size do: [:i |\\n\\t\\t(submorphs at: i) privateFullMoveBy: delta].\\n\\towner ifNotNil:[\\n\\t\\towner isTextMorph ifTrue:[owner adjustTextAnchor: self]].! !\\n\\n!Morph methodsFor: 'private' stamp: 'md 2/27/2006 08:55'!\\nprivateMoveBy: delta \\n\\t\\\"Private!! Use 'position:' instead.\\\"\\n\\t| fill |\\n\\textension ifNotNil: [extension player\\n\\t\\t\\t\\tifNotNil: [\\\"Most cases eliminated fast by above test\\\"\\n\\t\\t\\t\\t\\tself getPenDown\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"If this is a costume for a player with its \\n\\t\\t\\t\\t\\t\\t\\tpen down, draw a line.\\\"\\n\\t\\t\\t\\t\\t\\t\\tself moveWithPenDownBy: delta]]].\\n\\tbounds _ bounds translateBy: delta.\\n\\tfullBounds ifNotNil: [fullBounds _ fullBounds translateBy: delta].\\n\\tfill _ self fillStyle.\\n\\tfill isOrientedFill ifTrue: [fill origin: fill origin + delta]! !\\n\\n!Morph methodsFor: 'private'!\\nprivateOwner: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\towner _ aMorph.! !\\n\\n!Morph methodsFor: 'private' stamp: 'RAA 5/23/2000 11:30'!\\nprivateRemoveMorphWithAbsolutelyNoSideEffects: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\t\\\"used to delete a morph from an inactive world\\\"\\n\\n\\tsubmorphs _ submorphs copyWithout: aMorph.\\n\\n! !\\n\\n!Morph methodsFor: 'private' stamp: 'di 10/18/2004 21:49'!\\nprivateRemove: aMorph\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\tsubmorphs _ submorphs copyWithout: aMorph.\\n\\tself layoutChanged.! !\\n\\n!Morph methodsFor: 'private'!\\nprivateSubmorphs\\n\\t\\\"Private!! Use 'submorphs' instead.\\\"\\n\\n\\t^ submorphs! !\\n\\n!Morph methodsFor: 'private'!\\nprivateSubmorphs: aCollection\\n\\t\\\"Private!! Should only be used by methods that maintain the ower/submorph invariant.\\\"\\n\\n\\tsubmorphs _ aCollection.! !\\n\\n\\n!Morph methodsFor: 'accessing-backstop' stamp: 'wiz 2/14/2006 19:02'!\\ntarget: aMorph\\n\\\"Morphs with targets will override. This backstop does nothing.\\\"\\n\\\"This is here because targeting meta-actions are taken at morph level. \\nDo not remove.\\\"! !\\n\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/27/2005 23:29'!\\naccumlatePlayersInto: aCollection andSelectorsInto: selectorsCollection\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue: [\\n\\t\\t\\t(tile type = #objRef and: [tile actualObject isKindOf: Player]) ifTrue: [\\n\\t\\t\\t\\taCollection add: tile actualObject\\n\\t\\t\\t]\\n\\t\\t].\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue: [\\n\\t\\t\\t(tile type = #operator) ifTrue: [\\n\\t\\t\\t\\tselectorsCollection add: tile operatorOrExpression\\n\\t\\t\\t]\\n\\t\\t].\\n\\t\\ttile accumlatePlayersInto: aCollection andSelectorsInto: selectorsCollection\\n\\t].\\n! !\\n\\n!Morph methodsFor: 'translation' stamp: 'sw 3/7/2004 13:03'!\\nisPlayer: aPlayer ofReferencingTile: tile\\n\\t\\\"Answer whether the given player is the object referred to by the given tile, or a sibling of that object. This theoretically is only sent to PhraseTileMorphs, so this version is theoretically never reached\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/27/2005 23:33'!\\nisTurtleRow\\n\\n\\t| aCollection selectorCollection |\\n\\taCollection _ Set new.\\n\\tselectorCollection _ Set new.\\n\\tself accumlatePlayersInto: aCollection andSelectorsInto: selectorCollection.\\n\\t#(turtleCount: turtleCount grouped: grouped) do: [:sel |\\n\\t\\t(selectorCollection includes: sel) ifTrue: [^ false].\\n\\t].\\n\\n\\taCollection do: [:e |\\n\\t\\t(e isKindOf: KedamaExamplerPlayer) ifTrue: [^ true].\\n\\t].\\n\\t^ false.\\n! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/18/2004 10:31'!\\ntraverseRowTranslateSlotOld: oldSlotName of: aPlayer to: newSlotName\\n\\t\\\"Traverse my submorphs, translating submorphs appropriately given the slot rename\\\"\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue:\\n\\t\\t\\t[tile assignmentRoot = oldSlotName ifTrue:\\n\\t\\t\\t\\t[(self isPlayer: aPlayer ofReferencingTile: tile) ifTrue:\\n\\t\\t\\t\\t\\t[tile setRoot: newSlotName]]].\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue:\\n\\t\\t\\t[(tile operatorOrExpression = (Utilities getterSelectorFor: oldSlotName)) ifTrue:\\n\\t\\t\\t\\t[(self isPlayer: aPlayer ofReferencingTile: tile) ifTrue:\\n\\t\\t\\t\\t\\t[tile setOperator: (Utilities getterSelectorFor: newSlotName)]]].\\n\\t\\ttile traverseRowTranslateSlotOld: oldSlotName of: aPlayer to: newSlotName]! !\\n\\n!Morph methodsFor: 'translation' stamp: 'yo 1/18/2004 10:32'!\\ntraverseRowTranslateSlotOld: oldSlotName to: newSlotName\\n\\t\\\"Traverse my submorphs, translating submorphs appropriately given the slot rename\\\"\\n\\n\\tsubmorphs do: [:tile |\\n\\t\\t(tile isKindOf: AssignmentTileMorph) ifTrue: \\n\\t\\t\\t[tile assignmentRoot = oldSlotName ifTrue: [tile setRoot: newSlotName]].\\n\\t\\t(tile isMemberOf: TileMorph) ifTrue:\\n\\t\\t\\t[(tile operatorOrExpression = (Utilities getterSelectorFor: oldSlotName)) ifTrue:\\n\\t\\t\\t\\t[tile setOperator: (Utilities getterSelectorFor: newSlotName)]].\\n\\t\\ttile traverseRowTranslateSlotOld: oldSlotName to: newSlotName]! !\\n\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/9/1999 17:43'!\\nadaptToWorld: aWorld\\n\\t\\\"The receiver finds itself operating in a possibly-different new world. If any of the receiver's parts are world-dependent (such as a target of a SimpleButtonMorph, etc.), then have them adapt accordingly\\\"\\n\\tsubmorphs do: [:m | m adaptToWorld: aWorld].\\n\\tself eventHandler ifNotNil:\\n\\t\\t[self eventHandler adaptToWorld: aWorld]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 5/17/2001 12:47'!\\nadoptVocabulary: aVocabulary\\n\\t\\\"Make aVocabulary be the one used by me and my submorphs\\\"\\n\\n\\tself submorphsDo: [:m | m adoptVocabulary: aVocabulary]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'yo 1/9/2004 16:10'!\\nallMorphsAndBookPagesInto: aSet\\n\\t\\\"Return a set of all submorphs. Don't forget the hidden ones like BookMorph pages that are not showing. Consider only objects that are in memory (see allNonSubmorphMorphs).\\\" \\n\\n\\tsubmorphs do: [:m | m allMorphsAndBookPagesInto: aSet].\\n\\tself allNonSubmorphMorphs do: [:m | \\n\\t\\t\\t(aSet includes: m) ifFalse: [\\\"Stop infinite recursion\\\"\\n\\t\\t\\t\\tm allMorphsAndBookPagesInto: aSet]].\\n\\taSet add: self.\\n\\tself player ifNotNil:\\n\\t\\t[self player allScriptEditors do: [:e | e allMorphsAndBookPagesInto: aSet]].\\n\\t^ aSet! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 1/13/2001 11:27'!\\nappearsToBeSameCostumeAs: aMorph\\n\\n\\t^false\\n! !\\n\\n!Morph methodsFor: 'e-toy support'!\\nasNumber: aPointOrNumber\\n\\t\\\"Support for e-toy demo.\\\"\\n\\n\\taPointOrNumber class = Point\\n\\t\\tifTrue: [^ aPointOrNumber r]\\n\\t\\tifFalse: [^ aPointOrNumber].\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nk 1/6/2004 12:37'!\\nasWearableCostume\\n\\t\\\"Return a wearable costume for some player\\\"\\n\\t^(World drawingClass withForm: self imageForm) copyCostumeStateFrom: self! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'mir 6/13/2001 14:34'!\\nasWearableCostumeOfExtent: extent\\n\\t\\\"Return a wearable costume for some player\\\"\\n\\t^self asWearableCostume! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 12/20/1999 17:36'!\\nautomaticViewing\\n\\t\\\"Backstop, in case this message gets sent to an owner that is not a playfield\\\"\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 5/18/2001 11:17'!\\nchangeAllBorderColorsFrom: oldColor to: newColor\\n\\t\\\"Set any occurrence of oldColor as a border color in my entire submorph tree to be newColor\\\"\\n\\n\\t(self allMorphs select: [:m | m respondsTo: #borderColor:]) do:\\n\\t\\t[:aMorph | aMorph borderColor = oldColor ifTrue: [aMorph borderColor: newColor]]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/1/97 00:18'!\\nconfigureForKids\\n\\tsubmorphs ifNotNil:\\n\\t\\t[submorphs do: [:m | m configureForKids]]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/6/2001 04:21'!\\ncontainingWindow\\n\\t\\\"Answer a window or window-with-mvc that contains the receiver\\\"\\n\\n\\t^ self ownerThatIsA: SystemWindow orA: MVCWiWPasteUpMorph! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:38'!\\ncopyCostumeStateFrom: aMorph\\n\\t\\\"Copy all state that should be persistant for costumes from aMorph\\\"\\n\\tself rotationCenter: aMorph rotationCenter.\\n\\tself rotationStyle: aMorph rotationStyle.\\n\\tself referencePosition: aMorph referencePosition.\\n\\tself forwardDirection: aMorph forwardDirection.\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/22/1998 20:28'!\\ncurrentPlayerDo: aBlock\\n\\t\\\"If the receiver is a viewer/scriptor associated with a current Player object, evaluate the given block against that object\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/8/2000 16:34'!\\ncursor\\n\\t\\\"vacuous backstop in case it gets sent to a morph that doesn't know what to do with it\\\"\\n\\n\\t^ 1! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/7/2000 09:28'!\\ncursor: aNumber\\n\\t\\\"vacuous backstop in case it gets sent to a morph that doesn't know what to do with it\\\"\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/13/2002 17:44'!\\ndecimalPlacesForGetter: aGetter\\n\\t\\\"Answer the decimal places I prefer for showing a slot with the given getter, or nil if none\\\"\\n\\n\\t| decimalPrefs |\\n\\tdecimalPrefs _ self renderedMorph valueOfProperty: #decimalPlacePreferences ifAbsent: [^ nil].\\n\\t^ decimalPrefs at: aGetter ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/24/2000 05:52'!\\ndefaultValueOrNil\\n\\t\\\"If the receiver has a property named #defaultValue, return that property's value, else return nil\\\"\\n\\n\\t^ self valueOfProperty: #defaultValue ifAbsent: [nil]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sd 3/30/2005 22:04'!\\ndefaultVariableName\\n\\t\\\"If the receiver is of the sort that wants a variable maintained on its behalf in the 'card' data, then return a variable name to be used for that datum. What is returned here is only a point of departure in the forthcoming negotiation\\\"\\n\\n\\t^ Scanner wellFormedInstanceVariableNameFrom: (self valueOfProperty: #variableName ifAbsent: [self externalName])! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nb 6/17/2003 12:25'!\\ndefinePath\\n\\t| points lastPoint aForm offset currentPoint dwell ownerPosition |\\n\\tpoints _ OrderedCollection new: 70.\\n\\tlastPoint _ nil.\\n\\taForm _ self imageForm.\\n\\toffset _ aForm extent // 2.\\n\\townerPosition _ owner position.\\n\\tCursor move show.\\n\\tSensor waitButton.\\n\\t[Sensor anyButtonPressed and: [points size < 100]] whileTrue:\\n\\t\\t[currentPoint _ Sensor cursorPoint.\\n\\t\\tdwell _ 0.\\n\\t\\tcurrentPoint = lastPoint\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[dwell _ dwell + 1.\\n\\t\\t\\t\\t((dwell \\\\\\\\ 1000) = 0) ifTrue:\\n\\t\\t\\t\\t\\t[Beeper beep]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self position: (currentPoint - offset).\\n\\t\\t\\t\\tself world displayWorld.\\n\\t\\t\\t\\t(Delay forMilliseconds: 20) wait.\\n\\t\\t\\t\\tpoints add: currentPoint.\\n\\t\\t\\t\\tlastPoint _ currentPoint]].\\n\\tpoints size > 1\\n\\t\\tifFalse:\\n\\t\\t\\t[self inform: 'no path obtained']\\n\\t\\tifTrue:\\n\\t\\t\\t[points size = 100 ifTrue: [self playSoundNamed: 'croak'].\\n\\n\\t\\t\\tTranscript cr; show: 'path defined with\\n', points size printString, ' points'.\\n\\t\\t\\tself renderedMorph setProperty: #pathPoints toValue: \\n\\t\\t\\t\\t(points collect: [:p | p - ownerPosition])].\\n\\n\\tCursor normal show\\n\\t\\t! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 1/5/1999 10:05'!\\ndeletePath\\n\\tself removeProperty: #pathPoints! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/26/1999 23:32'!\\nembeddedInMorphicWindowLabeled: labelString\\n\\t| window |\\n\\twindow _ (SystemWindow labelled: labelString) model: nil.\\n\\twindow setStripeColorsFrom: nil defaultBackgroundColor.\\n\\twindow addMorph: self frame: (0@0 extent: 1@1).\\n\\t^ window! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 5/25/2000 09:06'!\\nembedInWindow\\n\\n\\t| window worldToUse |\\n\\n\\tworldToUse _ self world.\\t\\t\\\"I'm assuming we are already in a world\\\"\\n\\twindow _ (SystemWindow labelled: self defaultLabelForInspector) model: nil.\\n\\twindow bounds: ((self position - ((0@window labelHeight) + window borderWidth))\\n\\t\\t\\t\\t\\t\\tcorner: self bottomRight + window borderWidth).\\n\\twindow addMorph: self frame: (0@0 extent: 1@1).\\n\\twindow updatePaneColors.\\n\\tworldToUse addMorph: window.\\n\\twindow activate! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 2/22/2003 14:31'!\\nenclosingEditor\\n\\t\\\"Return the next editor around the receiver\\\"\\n\\n\\t| tested |\\n\\ttested := owner.\\n\\t[tested isNil] whileFalse: \\n\\t\\t\\t[tested isTileEditor ifTrue: [^tested].\\n\\t\\t\\ttested := tested owner].\\n\\t^nil! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/15/1999 19:38'!\\nenforceTileColorPolicy\\n\\tPreferences coloredTilesEnabled\\n\\t\\tifTrue:\\n\\t\\t\\t[self makeAllTilesColored]\\n\\t\\tifFalse:\\n\\t\\t\\t[self makeAllTilesGreen]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 10/4/2000 08:29'!\\nfenceEnabled\\n\\n\\t\\\"in case a non-pasteUp is used as a container\\\"\\n\\n\\t^Preferences fenceEnabled! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'nb 6/17/2003 12:25'!\\nfollowPath\\n\\t| pathPoints offset |\\n\\t(pathPoints _ self renderedMorph valueOfProperty: #pathPoints) ifNil: [^ Beeper beep].\\n\\toffset _ owner position - (self extent // 2).\\n\\tpathPoints do:\\n\\t\\t[:aPoint |\\n\\t\\t\\tself position: aPoint + offset.\\n\\t\\t\\tself world displayWorld.\\n\\t\\t\\t(Delay forMilliseconds: 20) wait]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 2/18/2003 02:54'!\\ngetCharacters\\n\\t\\\"obtain a string value from the receiver. The default generic response is simply the name of the object.\\\"\\n\\n\\t^ self externalName! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/1/2000 10:15'!\\ngetNumericValue\\n\\t\\\"Only certain kinds of morphs know how to deal with this frontally; here we provide support for a numeric property of any morph\\\"\\n\\n\\t^ self valueOfProperty: #numericValue ifAbsent: [0]! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'kfr 9/4/2004 15:22'!\\ngridFormOrigin: origin grid: smallGrid background: backColor line: lineColor\\n\\n\\t| bigGrid gridForm gridOrigin |\\n\\tgridOrigin _ origin \\\\\\\\ smallGrid.\\n\\tbigGrid _ (smallGrid asPoint x) @ (smallGrid asPoint y).\\n\\tgridForm _ Form extent: bigGrid depth: Display depth.\\n\\tbackColor ifNotNil: [gridForm fillWithColor: backColor].\\n\\tgridOrigin x to: gridForm width by: smallGrid x do:\\n\\t\\t[:x | gridForm fill: (x@0 extent: 1@gridForm height) fillColor: lineColor].\\n\\tgridOrigin y to: gridForm height by: smallGrid y do:\\n\\t\\t[:y | gridForm fill: (0@y extent: gridForm width@1) fillColor: lineColor].\\n\\t^ InfiniteForm with: gridForm\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 4/12/2005 23:07'!\\nhandUserASibling\\n\\t\\\"Make and hand the user a sibling instance. Force the creation of a uniclass at this point if one does not already exist for the receiver.\\\"\\n\\n\\t| topRend |\\n\\ttopRend _ self topRendererOrSelf.\\n\\ttopRend couldMakeSibling ifFalse: [^ Beeper beep].\\n\\n\\ttopRend assuredPlayer assureUniClass.\\n\\t(topRend makeSiblings: 1) first openInHand! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/21/1998 15:54'!\\nisAViewer\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 6/30/1999 20:29'!\\nisCandidateForAutomaticViewing\\n\\t^ true! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 2/7/2001 17:58'!\\nisTileEditor\\n\\t\\\"No, I'm not\\\"\\n\\t^false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/9/2000 16:48'!\\nlistViewLineForFieldList: aFieldList\\n\\t\\\"Answer a ListLineView object which describes the receiver\\\"\\n\\n\\t| aLine |\\n\\taLine _ ListViewLine new objectRepresented: self.\\n\\taFieldList do:\\n\\t\\t[:fieldSym | aLine addMorphBack: (self readoutForField: fieldSym).\\n\\t\\taLine addTransparentSpacerOfSize: (7 @ 0)].\\n\\t^ aLine! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 9/6/2003 18:10'!\\nmakeGraphPaper\\n\\t| smallGrid backColor lineColor |\\n\\tsmallGrid _ Compiler evaluate: (FillInTheBlank request: 'Enter grid size' translated initialAnswer: '16').\\n\\tsmallGrid ifNil: [^ self].\\n\\tUtilities informUser: 'Choose a background color' translated during: [backColor _ Color fromUser].\\n\\tUtilities informUser: 'Choose a line color' translated during: [lineColor _ Color fromUser].\\n\\tself makeGraphPaperGrid: smallGrid background: backColor line: lineColor.! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'di 9/7/2000 20:44'!\\nmakeGraphPaperGrid: smallGrid background: backColor line: lineColor\\n\\n\\t| gridForm |\\n\\tgridForm _ self gridFormOrigin: 0@0 grid: smallGrid asPoint background: backColor line: lineColor.\\n\\tself color: gridForm.\\n\\tself world ifNotNil: [self world fullRepaintNeeded].\\n\\tself changed: #newColor. \\\"propagate to view\\\"\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 4/16/1998 13:46'!\\nmustBeBackmost\\n\\t\\\"Answer whether the receiver needs to be the backmost morph in its owner's submorph list\\\"\\n\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/13/2002 17:45'!\\nnoteDecimalPlaces: aNumber forGetter: aGetter\\n\\t\\\"Make a mental note of the user's preference for a particular number of decimal places to be associated with the slot with the given getter\\\"\\n\\n\\t(self renderedMorph valueOfProperty: #decimalPlacePreferences ifAbsentPut: [IdentityDictionary new])\\n\\t\\tat: aGetter put: aNumber! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/26/2000 11:37'!\\nnoteNegotiatedName: uniqueName for: requestedName\\n\\t\\\"This works, kind of, for morphs that have a single variable. Still holding out for generality of morphs being able to have multiple variables, but need a driving example\\\"\\n\\n\\tself setProperty: #variableName toValue: uniqueName.\\n\\tself setProperty: #setterSelector toValue: (Utilities setterSelectorFor: uniqueName).\\n\\tself setNameTo: uniqueName! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/9/2000 06:43'!\\nobjectViewed\\n\\t\\\"Answer the morph associated with the player that the structure the receiver currently finds itself within represents.\\\"\\n\\n\\t^ (self outermostMorphThat: [:o | o isKindOf: Viewer orOf: ScriptEditorMorph]) objectViewed! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/31/2004 14:11'!\\npinkXButton\\n\\t\\\"Answer a button with the old X on a pink background, targeted to self\\\"\\n\\n\\t| aButton |\\n\\taButton _ IconicButton new labelGraphic: (ScriptingSystem formAtKey: #PinkX).\\n\\taButton color: Color transparent; borderWidth: 0; shedSelvedge; actWhen: #buttonUp.\\n\\taButton target: self.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/11/2004 16:23'!\\nreferencePlayfield\\n\\t\\\"Answer the PasteUpMorph to be used for cartesian-coordinate reference\\\"\\n\\n\\t| former |\\n\\towner ifNotNil:\\n\\t\\t[(self topRendererOrSelf owner isHandMorph and: [(former _ self formerOwner) notNil])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[former _ former renderedMorph.\\n\\t\\t\\t\\t^ former isPlayfieldLike \\n\\t\\t\\t\\t\\tifTrue: [former]\\n\\t\\t\\t\\t\\tifFalse: [former referencePlayfield]]].\\n\\n\\tself allOwnersDo: [:o | o isPlayfieldLike ifTrue: [^ o]].\\n\\t^ ActiveWorld! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:40'!\\nrotationStyle\\n\\t\\\"Return the 'rotation style' of the receiver\\\"\\n\\t^#normal! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'ar 9/23/2000 22:40'!\\nrotationStyle: aSymbol\\n\\t\\\"Set the 'rotation style' of the receiver; this is ignored for non-sketches\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 3/9/2001 14:37'!\\nsetAsActionInButtonProperties: buttonProperties\\n\\n\\t^false\\t\\\"means I don't know how to be set as a button action\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 9/15/2000 06:26'!\\nsetNumericValue: aValue\\n\\t\\\"Set the receiver's contents to reflect the given numeric value. Only certain kinds of morphs know what to do with this, the rest, for now, stash the number in a property, where it may not be visible but at least it won't be lost, and can be retrieved by the companion getter. This code is never reached under normal circumstances, because the #numericValue slot is not shown in Viewers for most kinds of morphs, and those kinds of morphs that do show it also reimplement this method. However, this code *could* be reached via a user script which sends #setNumericValue: but whose receiver has been changed, via tile-scripting drag and drop for example, to one that doesn't directly handle numbers\\\"\\n\\n\\tScriptingSystem informScriptingUser: 'an unusual setNumericValue: call was made'.\\n\\tself renderedMorph setProperty: #numericValue toValue: aValue\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 7/21/1998 21:18'!\\nsetStandardTexture\\n\\t| parms |\\n\\tparms _ self textureParameters.\\n\\tself makeGraphPaperGrid: parms first\\n\\t\\tbackground: parms second\\n\\t\\tline: parms third! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 10/27/2000 17:46'!\\nslotSpecifications\\n\\t\\\"A once and possibly future feature; retained here for backward-compatibility bulletproofing.\\\"\\n\\n\\t^ #()! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/11/1998 16:55'!\\nsucceededInRevealing: aPlayer\\n\\taPlayer == self player ifTrue: [^ true].\\n\\tsubmorphs do:\\n\\t\\t[:m | (m succeededInRevealing: aPlayer) ifTrue: [^ true]].\\n\\t^ false! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 8/31/2004 14:06'!\\ntanOButton\\n\\t\\\"Answer a button with the old O on a tan background, targeted to self\\\"\\n\\n\\t| aButton |\\n\\taButton _ IconicButton new labelGraphic: (ScriptingSystem formAtKey: #TanO).\\n\\taButton color: Color transparent; borderWidth: 0; shedSelvedge; actWhen: #buttonUp.\\n\\taButton target: self.\\n\\t^ aButton! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 7/21/1998 21:17'!\\ntextureParameters\\n\\t\\\"Answer a triplet giving the preferred grid size, background color, and line color. The choices here are as suggested by Alan, 9/13/97\\\"\\n\\n\\t^ Array with: 16 with: Color lightYellow with: Color lightGreen lighter lighter! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 2/22/2003 14:35'!\\ntopEditor\\n\\t\\\"Return the top-most editor around the receiver\\\"\\n\\n\\t| found tested |\\n\\ttested := self.\\n\\t[tested isNil] whileFalse: \\n\\t\\t\\t[tested isTileEditor ifTrue: [found := tested].\\n\\t\\t\\ttested := tested owner].\\n\\t^found! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'dgd 10/8/2003 19:30'!\\nunlockOneSubpart\\n\\t| unlockables aMenu reply |\\n\\tunlockables _ self submorphs select:\\n\\t\\t[:m | m isLocked].\\n\\tunlockables size <= 1 ifTrue: [^ self unlockContents].\\n\\taMenu _ SelectionMenu labelList: (unlockables collect: [:m | m externalName]) selections: unlockables.\\n\\treply _ aMenu startUpWithCaption: 'Who should be be unlocked?' translated.\\n\\treply isNil ifTrue: [^ self].\\n\\treply unlock! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'tk 10/19/1999 07:16'!\\nupdateCachedThumbnail\\n\\t\\\"If I have a cached thumbnail, then update it. Copied up from Dan's original version in PasteUpMorph so it can be used by all morphs.\\\"\\n\\t| cachedThumbnail |\\n\\n\\t(cachedThumbnail _ self valueOfProperty: #cachedThumbnail) ifNotNil:\\n\\t\\t[(cachedThumbnail respondsTo: #computeThumbnail) \\n\\t\\t\\tifTrue: [cachedThumbnail computeThumbnail]\\n\\t\\t\\tifFalse: [self removeProperty: #computeThumbnail]].\\n\\t\\t\\\"Test and removal are because the thumbnail is being replaced by another Morph. We don't know why. Need to fix that at the source.\\\"! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'sw 11/27/2001 14:52'!\\nwantsRecolorHandle\\n\\t\\\"Answer whether the receiver would like a recoloring halo handle to be put up. Since this handle also presently affords access to the property-sheet, it is presently always allowed, even though SketchMorphs don't like regular recoloring\\\"\\n\\n\\t^ true\\n\\t\\n! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'RAA 2/5/2001 15:35'!\\nwrappedInWindowWithTitle: aTitle\\n\\t| aWindow w2 |\\n\\taWindow _ (SystemWindow labelled: aTitle) model: Model new.\\n\\taWindow addMorph: self frame: (0@0 extent: 1@1).\\n\\tw2 _ aWindow borderWidth * 2.\\n\\tw2 _ 3.\\t\\t\\\"oh, well\\\"\\n\\taWindow extent: self fullBounds extent + (0 @ aWindow labelHeight) + (w2 @ w2).\\n\\t^ aWindow! !\\n\\n!Morph methodsFor: 'e-toy support' stamp: 'tk 9/3/1999 11:46'!\\nwrappedInWindow: aSystemWindow\\n\\t| aWindow |\\n\\taWindow _ aSystemWindow model: Model new.\\n\\taWindow addMorph: self frame: (0@0 extent: 1@1).\\n\\taWindow extent: self extent.\\n\\t^ aWindow! !\\n\\n\\n!Morph methodsFor: 'messenger' stamp: 'sw 11/3/2001 12:23'!\\naffiliatedSelector\\n\\t\\\"Answer a selector affiliated with the receiver for the purposes of launching a messenger. Reimplement this to plug into the messenger service\\\"\\n\\n\\t^ nil! !\\n\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 09:58'!\\nallowsGestureStart: evt\\n\\t^false! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/11/2004 17:45'!\\nisGestureStart: anEvent\\n\\t\\\"This mouse down could be the start of a gesture, or the end of a gesture focus\\\"\\n\\n\\tanEvent hand isGenieEnabled\\n\\t\\tifFalse: [ ^false ].\\n\\n\\t(self allowsGestureStart: anEvent)\\n\\t\\tifTrue: [^ true ].\\t\\t\\\"could be the start of a gesture\\\"\\n\\n\\t\\\"otherwise, check for whether it's time to disable the Genie auto-focus\\\"\\n\\t(anEvent hand isGenieFocused\\n\\t\\tand: [anEvent whichButton ~= anEvent hand focusStartEvent whichButton])\\n\\t\\t\\tifTrue: [anEvent hand disableGenieFocus].\\n\\n\\t^false! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/11/2004 17:30'!\\nmouseStillDownStepRate\\n\\t\\\"At what rate do I want to receive #mouseStillDown: notifications?\\\"\\n\\t^1! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 06:38'!\\nredButtonGestureDictionaryOrName: aSymbolOrDictionary! !\\n\\n!Morph methodsFor: 'geniestubs' stamp: 'nk 3/10/2004 06:38'!\\nyellowButtonGestureDictionaryOrName: aSymbolOrDictionary! !\\n\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'di 9/22/1999 08:45'!\\nasEPS\\n\\n\\t^ EPSCanvas morphAsPostscript: self rotated: false.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases'!\\nasPostscript\\n\\t^self asEPS.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'di 9/22/1999 08:45'!\\nasPostscriptPrintJob\\n\\n\\t^ DSCPostscriptCanvas morphAsPostscript: self rotated: false.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'ar 1/16/2001 17:06'!\\nclipPostscript\\n\\t^Clipboard clipboardText: self asPostscript.\\n\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'mpw 8/10/1930 05:21'!\\ndrawPostscriptOn: aCanvas\\n\\n\\tself drawOn:aCanvas.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'mpw 8/10/1930 05:25'!\\nfullDrawPostscriptOn: aCanvas\\n\\n\\tself fullDrawOn:aCanvas.\\n! !\\n\\n!Morph methodsFor: '*morphic-Postscript Canvases' stamp: 'nk 12/29/2003 10:55'!\\nprintPSToFile\\n\\t\\n\\tself printPSToFileNamed: self externalName! !\\n\\n\\n!Morph methodsFor: 'player' stamp: 'tk 10/30/2001 12:13'!\\nassuredCardPlayer\\n\\t\\\"Answer the receiver's player, creating a new one if none currently exists\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self player) ifNotNil: [\\n\\t\\t(aPlayer isKindOf: CardPlayer) \\n\\t\\t\\t\\tifTrue: [^ aPlayer]\\n\\t\\t\\t\\tifFalse: [self error: 'Must convert to a CardPlayer']\\n\\t\\t\\t\\t\\t\\\"later convert using as: and remove the error\\\"].\\n\\tself assureExternalName. \\\"a default may be given if not named yet\\\"\\n\\tself player: (aPlayer _ UnscriptedCardPlayer newUserInstance).\\n\\t\\t\\\"Force it to be a CardPlayer. Morph class no longer dictates what kind of player\\\"\\n\\taPlayer costume: self.\\n\\tself presenter ifNotNil: [self presenter flushPlayerListCache].\\n\\t^ aPlayer! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 2/19/1999 09:06'!\\nassuredPlayer\\n\\t\\\"Answer the receiver's player, creating a new one if none currently exists\\\"\\n\\n\\t| aPlayer |\\n\\t(aPlayer _ self player) ifNil:\\n\\t\\t[self assureExternalName. \\\"a default may be given if not named yet\\\"\\n\\t\\tself player: (aPlayer _ self newPlayerInstance). \\n\\t\\t\\t\\\"Different morphs may demand different player types\\\"\\n\\t\\taPlayer costume: self.\\n\\t\\tself presenter ifNotNil: [self presenter flushPlayerListCache]].\\n\\t^ aPlayer! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 8/10/2000 00:06'!\\nassureExternalName\\n\\t| aName |\\n\\t^ (aName _ self knownName) ifNil:\\n\\t\\t[self setNameTo: (aName _ self externalName).\\n\\t\\t^ aName]! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 10/27/2000 17:38'!\\ncurrentDataValue\\n\\t\\\"Answer the data value associated with the receiver. Useful in conjunction with default-value setting\\\"\\n\\n\\t^ nil! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 9/15/1998 13:33'!\\nnewPlayerInstance\\n\\t^ UnscriptedPlayer newUserInstance! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 1/22/2001 14:25'!\\nokayToDuplicate\\n\\t\\\"Formerly this protocol was used to guard against awkward situations when there were anonymous scripts in the etoy system. Nowadays we just always allow duplication\\\"\\n\\n\\t^ true! !\\n\\n!Morph methodsFor: 'player' stamp: 'mir 6/13/2001 14:45'!\\nshouldRememberCostumes\\n\\t^true! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 8/11/1998 16:54'!\\nshowPlayerMenu\\n\\tself player ifNotNil:\\n\\t\\t[self player showPlayerMenu]! !\\n\\n!Morph methodsFor: 'player' stamp: 'sw 10/6/2000 07:37'!\\nvariableDocks\\n\\t\\\"Answer a list of VariableDocker objects for docking up my data with an instance held in my containing playfield. The simple presence of some objects on a Playfield will result in the maintenance of instance data on the corresponding Card. This is a generalization of the HyperCard 'field' idea. If there is already a cachedVariableDocks cached, use that. For this all to work happily, one must be certain to invalidate the #cachedVariableDocks cache when that's appropriate.\\\"\\n\\n\\t^ self valueOfProperty: #cachedVariableDocks ifAbsent: [#()]! !\\n\\n\\n!Morph methodsFor: 'player commands' stamp: 'nb 6/17/2003 12:25'!\\nbeep: soundName\\n\\n\\tself playSoundNamed: soundName\\n! !\\n\\n!Morph methodsFor: 'player commands'!\\njumpTo: aPoint\\n\\t\\\"Let my owner decide how I move.\\\"\\n\\n\\towner move: self toPosition: aPoint.\\n! !\\n\\n!Morph methodsFor: 'player commands' stamp: 'sw 2/16/1999 11:33'!\\nmakeFenceSound\\n\\tPreferences soundsEnabled ifTrue:\\n\\t\\t[self playSoundNamed: 'scratch'].\\n! !\\n\\n!Morph methodsFor: 'player commands' stamp: 'gk 2/23/2004 21:08'!\\nplaySoundNamed: soundName\\n\\t\\\"Play the sound with the given name.\\n\\tDoes nothing if this image lacks sound playing facilities.\\\"\\n\\n\\tSoundService default playSoundNamed: soundName asString! !\\n\\n!Morph methodsFor: 'player commands'!\\nset: aPointOrNumber\\n\\t\\\"Set my position.\\\"\\n\\n\\tself jumpTo: aPointOrNumber.\\n! !\\n\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 14:45'!\\nbuttonProperties\\n\\n\\t^self valueOfProperty: #universalButtonProperties! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 14:45'!\\nbuttonProperties: propertiesOrNil\\n\\n\\tpropertiesOrNil ifNil: [\\n\\t\\tself removeProperty: #universalButtonProperties\\n\\t] ifNotNil: [\\n\\t\\tself setProperty: #universalButtonProperties toValue: propertiesOrNil\\n\\t].! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 07:49'!\\nensuredButtonProperties\\n\\n\\tself hasButtonProperties ifFalse: [\\n\\t\\tself buttonProperties: (ButtonProperties new visibleMorph: self)\\n\\t].\\n\\t^self buttonProperties! !\\n\\n!Morph methodsFor: 'button properties' stamp: 'RAA 3/8/2001 07:18'!\\nhasButtonProperties\\n\\n\\t^self hasProperty: #universalButtonProperties! !\\n\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 17:12'!\\ncategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the \\n\\tviewer, in order\\\"\\n\\t| dict aList |\\n\\tdict := Dictionary new.\\n\\tself unfilteredCategoriesForViewer\\n\\t\\twithIndexDo: [:cat :index | dict at: cat put: index].\\n\\tself filterViewerCategoryDictionary: dict.\\n\\taList := SortedCollection\\n\\t\\t\\t\\tsortBlock: [:a :b | (dict at: a)\\n\\t\\t\\t\\t\\t\\t< (dict at: b)].\\n\\taList addAll: dict keys.\\n\\t^ aList asArray! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 17:09'!\\nselectorsForViewer\\n\\t\\\"Answer a list of symbols representing all the selectors available in all my viewer categories\\\"\\n\\n\\t| aClass aList itsAdditions added addBlock |\\n\\taClass := self renderedMorph class.\\n\\taList := OrderedCollection new.\\n\\tadded := Set new.\\n\\taddBlock := [ :sym | (added includes: sym) ifFalse: [ added add: sym. aList add: sym ]].\\n\\n\\t[aClass == Morph superclass] whileFalse: \\n\\t\\t\\t[(aClass hasAdditionsToViewerCategories) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[itsAdditions := aClass allAdditionsToViewerCategories.\\n\\t\\t\\t\\t\\titsAdditions do: [ :add | add do: [:aSpec |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"the spec list\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #command ifTrue: [ addBlock value: aSpec second].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #slot \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[ addBlock value: (aSpec seventh).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t addBlock value: aSpec ninth]]]].\\n\\t\\t\\taClass := aClass superclass].\\n\\n\\t^aList copyWithoutAll: #(#unused #dummy)\\n\\n\\t\\\"SimpleSliderMorph basicNew selectorsForViewer\\\"! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 17:14'!\\nselectorsForViewerIn: aCollection\\n\\t\\\"Answer a list of symbols representing all the selectors available in all my viewer categories, selecting only the ones in aCollection\\\"\\n\\n\\t| aClass aList itsAdditions added addBlock |\\n\\taClass := self renderedMorph class.\\n\\taList := OrderedCollection new.\\n\\tadded := Set new.\\n\\taddBlock := [ :sym |\\n\\t\\t(added includes: sym) ifFalse: [ (aCollection includes: sym)\\n\\t\\t\\tifTrue: [ added add: sym. aList add: sym ]]].\\n\\n\\t[aClass == Morph superclass] whileFalse: \\n\\t\\t\\t[(aClass hasAdditionsToViewerCategories) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[itsAdditions := aClass allAdditionsToViewerCategories.\\n\\t\\t\\t\\t\\titsAdditions do: [ :add | add do: [:aSpec |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"the spec list\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #command ifTrue: [ addBlock value: aSpec second].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\taSpec first == #slot \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[ addBlock value: (aSpec seventh).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t addBlock value: aSpec ninth]]]].\\n\\t\\t\\taClass := aClass superclass].\\n\\n\\t^aList copyWithoutAll: #(#unused #dummy)\\n\\n\\t\\\"SimpleSliderMorph basicNew selectorsForViewerIn: \\n\\t#(setTruncate: getColor setColor: getKnobColor setKnobColor: getWidth setWidth: getHeight setHeight: getDropEnabled setDropEnabled:)\\n\\t\\\"! !\\n\\n!Morph methodsFor: '*flexiblevocabularies-scripting' stamp: 'nk 9/4/2004 11:47'!\\nunderstandsBorderVocabulary\\n\\t\\\"Replace the 'isKindOf: BorderedMorph' so that (for instance) Connectors can have their border vocabulary visible in viewers.\\\"\\n\\t^false! !\\n\\n\\n!Morph methodsFor: 'object fileIn' stamp: 'dgd 2/22/2003 14:30'!\\nconvertAugust1998: varDict using: smartRefStrm \\n\\t\\\"These variables are automatically stored into the new instance \\n\\t('bounds' 'owner' 'submorphs' 'fullBounds' 'color' ). \\n\\tThis method is for additional changes. Use statements like (foo _ \\n\\tvarDict at: 'foo').\\\"\\n\\n\\t\\\"Be sure to to fill in ('extension' ) and deal with the information \\n\\tin ('eventHandler' 'properties' 'costumee' )\\\"\\n\\n\\t\\\"This method moves all property variables as well as \\n\\teventHandler, and costumee into a morphicExtension.\\\"\\n\\n\\t\\\"Move refs to eventhandler and costumee into extension\\\"\\n\\n\\t| propVal |\\n\\t(varDict at: 'eventHandler') isNil \\n\\t\\tifFalse: [self eventHandler: (varDict at: 'eventHandler')].\\n\\t(varDict at: 'costumee') isNil \\n\\t\\tifFalse: [self player: (varDict at: 'costumee')].\\n\\t(varDict at: 'properties') isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[(varDict at: 'properties') keys do: \\n\\t\\t\\t\\t\\t[:key | \\n\\t\\t\\t\\t\\t\\\"Move property extensions into extension\\\"\\n\\n\\t\\t\\t\\t\\tpropVal := (varDict at: 'properties') at: key.\\n\\t\\t\\t\\t\\tpropVal ifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[key == #possessive \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [propVal == true ifTrue: [self bePossessive]]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[key ifNotNil: [self assureExtension convertProperty: key toValue: propVal]]]]]! !\\n\\n!Morph methodsFor: 'object fileIn' stamp: 'md 2/27/2006 09:56'!\\nconvertNovember2000DropShadow: varDict using: smartRefStrm \\n\\t\\\"Work hard to eliminate the DropShadow. Inst vars are already \\n\\tstored into.\\\"\\n\\n\\t| rend |\\n\\tsubmorphs notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[rend := submorphs first renderedMorph.\\n\\t\\t\\t\\\"a text?\\\"\\n\\t\\t\\trend setProperty: #hasDropShadow toValue: true.\\n\\t\\t\\trend setProperty: #shadowColor toValue: (varDict at: 'color').\\n\\t\\t\\trend setProperty: #shadowOffset toValue: (varDict at: 'shadowOffset').\\n\\t\\t\\t\\\"ds owner ifNotNil: [ds owner addAllMorphs: ds \\n\\t\\t\\tsubmorphs]. ^rend does this\\\"\\n\\t\\t\\trend privateOwner: owner.\\n\\t\\t\\textension ifNotNil: [\\n\\t\\t\\t\\textension actorState ifNotNil: [rend actorState: self extension actorState].\\n\\t\\t\\t\\textension externalName ifNotNil: [rend setNameTo: self extension externalName].\\n\\t\\t\\t\\textension player ifNotNil: [\\n\\t\\t\\t\\t\\t\\t\\trend player: extension player.\\n\\t\\t\\t\\t\\t\\t\\textension player rawCostume: rend]].\\n\\t\\t\\t^rend].\\n\\t(rend := Morph new) color: Color transparent.\\n\\t^rend! !\\n\\n\\n!Morph methodsFor: 'system primitives' stamp: 'sw 10/27/2000 17:37'!\\ncreationStamp\\n\\t\\\"Answer the creation stamp stored within the receiver, if any\\\"\\n\\n\\t^ self valueOfProperty: #creationStamp ifAbsent: [super creationStamp]! !\\n\\n\\n!Morph methodsFor: 'button' stamp: 'sw 2/6/2001 23:09'!\\ndoButtonAction\\n\\t\\\"If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism. Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts\\\"! !\\n\\n!Morph methodsFor: 'button' stamp: 'sw 2/6/2001 23:22'!\\nfire\\n\\t\\\"If the receiver has any kind of button-action defined, fire that action now. Any morph can have special, personal mouseUpCodeToRun, and that will be triggered by this. Additionally, some morphs have specific buttonness, and these get sent the #doButtonAction message to carry out their firing. Finally, some morphs have mouse behaviors associated with one or more Player scripts.\\n\\tFor the present, we'll try out doing *all* the firings this object can do. \\\"\\n\\n\\tself firedMouseUpCode. \\t\\\"This will run the mouseUpCodeToRun, if any\\\"\\n\\n\\tself player ifNotNil:\\t\\t\\n\\t\\t[self player fireOnce]. \\\"Run mouseDown and mouseUp scripts\\\"\\n\\n\\tself doButtonAction\\t\\t\\t\\\"Do my native button action, if any\\\"! !\\n\\n!Morph methodsFor: 'button' stamp: 'dgd 2/22/2003 14:31'!\\nfiredMouseUpCode\\n\\t\\\"If the user has special mouseUpCodeToRun, then fire it once right now and return true, else return false\\\"\\n\\n\\t| evt |\\n\\t(self world isNil or: [self mouseUpCodeOrNil isNil]) ifTrue: [^false].\\n\\tevt := MouseEvent new \\n\\t\\t\\t\\tsetType: nil\\n\\t\\t\\t\\tposition: self center\\n\\t\\t\\t\\tbuttons: 0\\n\\t\\t\\t\\thand: self world activeHand.\\n\\tself programmedMouseUp: evt for: self.\\n\\t^true! !\\n\\n\\n!Morph methodsFor: 'event handling-override' stamp: 'nk 3/10/2004 19:47'!\\nhandlerForMouseDown: anEvent \\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily \\n\\tinstalled and can be used for morphs further down the hierarchy to negotiate whether \\n\\tthe inner or the outer morph should finally handle the event.\\\"\\n\\n\\tanEvent blueButtonPressed\\n\\t\\tifTrue: [^ self handlerForBlueButtonDown: anEvent].\\n\\tanEvent yellowButtonPressed\\n\\t\\tifTrue: [^ self handlerForYellowButtonDown: anEvent].\\n\\tanEvent controlKeyPressed\\n\\t\\tifTrue: [^ self handlerForMetaMenu: anEvent].\\n\\t(self handlesMouseDown: anEvent)\\n\\t\\tifFalse: [^ nil].\\t\\\"not interested\\\"\\n\\n\\tanEvent handler\\n\\t\\tifNil: [^ self ].\\t\\\"Same priority but I am innermost\\\"\\n\\n\\t\\\"Nobody else was interested\\\"\\n\\t^self mouseDownPriority >= anEvent handler mouseDownPriority\\n\\t\\tifTrue: [ self]\\n\\t\\tifFalse: [ nil]! !\\n\\n\\n!Morph methodsFor: 'texture support' stamp: 'dgd 2/16/2003 20:02'!\\nisValidWonderlandTexture\\n\\t\\\"Return true if the receiver is a valid wonderland texture\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: #isValidWonderlandTexture\\n\\t\\tifAbsent: [true]! !\\n\\n\\n!Morph methodsFor: 'model access' stamp: 'nk 3/10/2004 19:51'!\\nmodels\\n\\t\\\"Answer a collection of whatever models I may have.\\\"\\n\\n\\tself modelOrNil ifNil: [ ^EmptyArray ].\\n\\t^Array with: self modelOrNil! !\\n\\n\\n!Morph methodsFor: 'player viewer' stamp: 'wiz 1/1/2006 12:58'!\\nopenViewerForArgument\\n\\t\\\"Open up a viewer for a player associated with the morph in question. \\\"\\n\\tself presenter viewMorph: self! !\\n\\n!Morph methodsFor: 'player viewer' stamp: 'sw 3/13/98 17:40'!\\nupdateLiteralLabel\\n\\t\\\"Backstop -- updatingStringMorphs inform their owners with this message when they've changed; some Morphs care, others don't\\\"! !\\n\\n\\n!Morph methodsFor: 'other' stamp: 'sw 10/30/2001 13:12'!\\nremoveAllButFirstSubmorph\\n\\t\\\"Remove all of the receiver's submorphs other than the first one.\\\"\\n\\n\\tself submorphs allButFirst do: [:m | m delete]! !\\n\\n\\n!Morph methodsFor: 'selected object' stamp: 'dgd 8/28/2004 16:30'!\\nselectedObject\\n\\t\\\"answer the selected object for the hand or nil is none\\\"\\n\\t^ self primaryHand selectedObject! !\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!Morph class methodsFor: 'class initialization' stamp: 'hg 8/3/2000 16:43'!\\ninitialize\\n\\t\\\"Morph initialize\\\"\\n\\n\\t\\\"this empty array object is shared by all morphs with no submorphs:\\\"\\n\\tEmptyArray _ Array new.\\n\\tFileList registerFileReader: self! !\\n\\n\\n!Morph class methodsFor: 'connectors-scripting' stamp: 'nk 9/10/2004 11:34'!\\nadditionsToViewerCategoryConnection\\n\\t\\\"Answer viewer additions for the 'connection' category\\\"\\n\\t\\\"Vocabulary initialize\\\"\\n\\n\\t^{\\n\\t\\t#'connections to me'.\\n\\t\\t#(\\n\\t\\t(command tellAllPredecessors: 'Send a message to all graph predecessors' ScriptName)\\n\\t\\t(command tellAllSuccessors: 'Send a message to all graph predecessors' ScriptName)\\n\\t\\t(command tellAllIncomingConnections: 'Send a message to all the connectors whose destination end is connected to me' ScriptName)\\n\\t\\t(command tellAllOutgoingConnections: 'Send a message to all the connectors whose source end is connected to me' ScriptName)\\n\\t\\t(slot incomingConnectionCount 'The number of connectors whose destination end is connected to me' Number readOnly Player getIncomingConnectionCount unused unused)\\n\\t\\t(slot outgoingConnectionCount 'The number of connectors whose source end is connected to me' Number readOnly Player getOutgoingConnectionCount unused unused)\\n\\t\\t)\\n\\t}\\n! !\\n\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'nk 7/16/2003 15:54'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\n\\t^({ 'morph'. 'morphs'. 'sp'. '*' } includes: suffix)\\n\\t\\tifTrue: [\\n\\t\\t\\t{SimpleServiceEntry \\n\\t\\t\\t\\tprovider: self \\n\\t\\t\\t\\tlabel: 'load as morph'\\n\\t\\t\\t\\tselector: #fromFileName:\\n\\t\\t\\t\\tdescription: 'load as morph'}]\\n\\t\\tifFalse: [#()]! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'yo 8/7/2003 11:02'!\\nfromFileName: fullName\\n\\t\\\"Reconstitute a Morph from the file, presumed to be represent a Morph saved\\n\\tvia the SmartRefStream mechanism, and open it in an appropriate Morphic world\\\"\\n\\n \\t| aFileStream morphOrList |\\n\\taFileStream _ (MultiByteBinaryOrTextStream with: ((FileStream readOnlyFileNamed: fullName) binary contentsOfEntireFile)) binary reset.\\n\\tmorphOrList _ aFileStream fileInObjectAndCode.\\n\\t(morphOrList isKindOf: SqueakPage) ifTrue: [morphOrList _ morphOrList contentsMorph].\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue: [ActiveWorld addMorphsAndModel: morphOrList]\\n\\t\\tifFalse:\\n\\t\\t\\t[morphOrList isMorph ifFalse: [self inform: 'Can only load a single morph\\ninto an mvc project via this mechanism.'].\\n\\t\\t\\tmorphOrList openInWorld]! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 02:43'!\\nserviceLoadMorphFromFile\\n\\t\\\"Answer a service for loading a .morph file\\\"\\n\\n\\t^ SimpleServiceEntry \\n\\t\\tprovider: self \\n\\t\\tlabel: 'load as morph'\\n\\t\\tselector: #fromFileName:\\n\\t\\tdescription: 'load as morph'\\n\\t\\tbuttonLabel: 'load'! !\\n\\n!Morph class methodsFor: 'fileIn/Out' stamp: 'sd 2/1/2002 21:45'!\\nservices\\n\\n\\t^ Array with: self serviceLoadMorphFromFile! !\\n\\n\\n!Morph class methodsFor: 'initialize-release' stamp: 'SD 11/15/2001 22:22'!\\nunload\\n\\n\\tFileList unregisterFileReader: self ! !\\n\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'efo 5/3/2002 14:59'!\\ninitializedInstance\\n\\t\\\"Answer an instance of the receiver which in some sense is initialized. In the case of Morphs, this will yield an instance that can be attached to the Hand after having received the same kind of basic initialization that would be obtained from an instance chosen from the 'new morph' menu.\\n\\tReturn nil if the receiver is reluctant for some reason to return such a thing\\\"\\n\\n\\t^ (self class includesSelector: #descriptionForPartsBin)\\n\\t\\tifTrue:\\n\\t\\t\\t[self newStandAlone]\\n\\t\\tifFalse:\\n\\t\\t\\t[self new]! !\\n\\n!Morph class methodsFor: 'instance creation'!\\nnewBounds: bounds\\n\\n\\t^ self new privateBounds: bounds! !\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'jm 5/29/1998 21:28'!\\nnewBounds: bounds color: color\\n\\n\\t^ (self new privateBounds: bounds) privateColor: color\\n! !\\n\\n!Morph class methodsFor: 'instance creation' stamp: 'sw 8/4/97 12:05'!\\nnewSticky\\n\\n\\t^ self new beSticky! !\\n\\n\\n!Morph class methodsFor: 'misc' stamp: 'sw 8/4/1998 16:51'!\\nmorphsUnknownToTheirOwners\\n\\t\\\"Return a list of all morphs (other than HandMorphs) whose owners do not contain them in their submorph lists\\\"\\n\\t\\\"Morph morphsUnknownToTheirOwners\\\"\\n\\t| problemMorphs itsOwner |\\n\\tproblemMorphs _ OrderedCollection new.\\n\\tself allSubInstances do:\\n\\t\\t[:m | (m isHandMorph not and: [((itsOwner _ m owner) ~~ nil and: [(itsOwner submorphs includes: m) not])])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[problemMorphs add: m]].\\n\\t^ problemMorphs! !\\n\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'di 6/22/97 09:07'!\\nincludeInNewMorphMenu\\n\\t\\\"Return true for all classes that can be instantiated from the menu\\\"\\n\\t^ true! !\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'sw 6/28/2001 11:33'!\\nnewStandAlone\\n\\t\\\"Answer an instance capable of standing by itself as a usable morph.\\\"\\n\\n\\t^ self basicNew initializeToStandAlone! !\\n\\n!Morph class methodsFor: 'new-morph participation' stamp: 'sw 8/2/2001 12:01'!\\npartName: aName categories: aList documentation: aDoc\\n\\t\\\"Answer a DescriptionForPartsBin which will represent a launch of a new instance of my class via the #newStandAlone protocol sent to my class. Use the category-list and documentation provided\\\"\\n\\n\\n\\t^ DescriptionForPartsBin new\\n\\t\\tformalName: aName\\n\\t\\tcategoryList: aList\\n\\t\\tdocumentation: aDoc\\n\\t\\tglobalReceiverSymbol: self name\\n\\t\\tnativitySelector: #newStandAlone! !\\n\\n\\n!Morph class methodsFor: 'scripting' stamp: 'sw 7/20/2005 01:20'!\\nadditionsToViewerCategoryColorAndBorder\\n\\t\\\"Answer viewer additions for the 'color & border' category\\\"\\n\\n\\t^#(\\n\\t\\t#'color & border' \\n\\t\\t(\\n\\t\\t\\t(slot color 'The color of the object' Color readWrite Player getColor Player setColor:)\\n\\t\\t\\t(slot opacity '0 means completely transparent, 1 means completely opaque' Number readWrite Player getAlpha Player setAlpha:)\\n\\t\\t\\t(slot borderStyle 'The style of the object''s border' BorderStyle readWrite Player getBorderStyle player setBorderStyle:)\\n\\t\\t\\t(slot borderColor 'The color of the object''s border' Color readWrite Player getBorderColor Player setBorderColor:)\\n\\t\\t\\t(slot borderWidth 'The width of the object''s border' Number readWrite Player getBorderWidth Player setBorderWidth:)\\n\\t\\t\\t(slot roundedCorners 'Whether corners should be rounded' Boolean readWrite Player getRoundedCorners Player setRoundedCorners:)\\n\\n\\t\\t\\t(slot gradientFill 'Whether a gradient fill should be used' Boolean readWrite Player getUseGradientFill Player setUseGradientFill:)\\n\\t\\t\\t(slot secondColor 'The second color used when gradientFill is in effect' Color readWrite Player getSecondColor Player setSecondColor:)\\n\\n\\t\\t\\t(slot radialFill 'Whether the gradient fill, if used, should be radial' Boolean readWrite Player getRadialGradientFill Player setRadialGradientFill:)\\n\\n\\t\\t\\t(slot dropShadow 'Whether a drop shadow is shown' Boolean readWrite Player getDropShadow Player setDropShadow:)\\n\\t\\t\\t(slot shadowColor 'The color of the drop shadow' Color readWrite Player getShadowColor Player setShadowColor:)\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'sw 8/11/97 13:17'!\\nauthoringPrototype\\n\\t\\\"Answer an instance of the receiver suitable for placing in a parts bin for authors\\\"\\n\\t\\n\\t^ self new markAsPartsDonor! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'bf 9/11/2004 17:18'!\\nhasAdditionsToViewerCategories\\n\\t^ self class selectors\\n\\t\\tanySatisfy: [:each | each == #additionsToViewerCategories\\n\\t\\t\\t\\tor: [(each beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\t\\tand: [(each at: 26 ifAbsent: []) ~= $:]]]! !\\n\\n!Morph class methodsFor: 'scripting' stamp: 'yo 3/15/2005 14:10'!\\nhelpContributions\\n\\t\\\"Answer a list of pairs of the form (<symbol> <help message> ) to contribute to the system help dictionary\\\"\\n\\t\\n\\\"NB: Many of the items here are not needed any more since they're specified as part of command definitions now. Someone needs to take the time to go through the list and remove items no longer needed. But who's got that kind of time?\\\"\\n\\n\\t^ #(\\n\\t\\t(acceptScript:for:\\n\\t\\t\\t'submit the contents of the given script editor as the code defining the given selector')\\n\\t\\t(actorState\\n\\t\\t\\t'return the ActorState object for the receiver, creating it if necessary')\\n\\t\\t(addInstanceVariable\\n\\t\\t\\t'start the interaction for adding a new variable to the object')\\n\\t\\t(addPlayerMenuItemsTo:hand:\\n\\t\\t\\t'add player-specific menu items to the given menu, on behalf of the given hand. At present, these are only commands relating to the turtle')\\n\\t\\t(addYesNoToHand\\n\\t\\t\\t'Press here to tear off a TEST/YES/NO unit which you can drop into your script')\\n\\t\\t(allScriptEditors\\n\\t\\t\\t'answer a list off the extant ScriptEditors for the receiver')\\n\\t\\t(amount\\n\\t\\t\\t'The amount of displacement')\\n\\t\\t(angle\\t\\n\\t\\t\\t'The angular displacement')\\n\\t\\t(anonymousScriptEditorFor:\\n\\t\\t\\t'answer a new ScriptEditor object to serve as the place for scripting an anonymous (unnamed, unsaved) script for the receiver')\\n\\t\\t(append:\\n\\t\\t\\t'add an object to this container')\\n\\t\\t(prepend:\\n\\t\\t\\t'add an object to this container')\\n\\t\\t(assignDecrGetter:setter:amt:\\n\\t\\t\\t'evaluate the decrement variant of assignment')\\n\\t\\t(assignGetter:setter:amt:\\n\\t\\t\\t'evaluate the vanilla variant of assignment')\\n\\t\\t(assignIncrGetter:setter:amt:\\n\\t\\t\\t'evalute the increment version of assignment')\\n\\t\\t(assignMultGetter:setter:amt:\\n\\t\\t\\t'evaluate the multiplicative version of assignment')\\n\\t\\t(assureEventHandlerRepresentsStatus\\n\\t\\t\\t'make certain that the event handler associated with my current costume is set up to conform to my current script-status')\\n\\t\\t(assureExternalName\\n\\t\\t\\t'If I do not currently have an external name assigned, get one now')\\n\\t\\t(assureUniClass\\n\\t\\t\\t'make certain that I am a member a uniclass (i.e. a unique subclass); if I am not, create one now and become me into an instance of it')\\n\\t\\t(availableCostumeNames\\n\\t\\t\\t'answer a list of strings representing the names of all costumes currently available for me')\\n\\t\\t(availableCostumesForArrows\\n\\t\\t\\t'answer a list of actual, instantiated costumes for me, which can be cycled through as the user hits a next-costume or previous-costume button in a viewer')\\n\\t\\t(beep:\\n\\t\\t\\t'make the specified sound')\\n\\t\\t(borderColor\\n\\t\\t\\t'The color of the object''s border')\\n\\t\\t(borderWidth\\n\\t\\t\\t'The width of the object''s border')\\n\\t\\t(bottom\\n\\t\\t\\t'My bottom edge, measured downward from the top edge of the world')\\n\\t\\t(bounce:\\n\\t\\t\\t'If object strayed beyond the boundaries of its container, make it reflect back into it, making the specified noise while doing so.')\\n\\t\\t(bounce\\n\\t\\t\\t'If object strayed beyond the boundaries of its container, make it reflect back into it')\\n\\t\\t(chooseTrigger\\n'When this script should run.\\n\\\"normal\\\" means \\\"only when called\\\"')\\n\\t\\t(clearTurtleTrails\\n\\t\\t\\t'Clear all the pen trails in the interior.')\\n\\t\\t(clearOwnersPenTrails\\n\\t\\t\\t'Clear all the pen trails in my container.')\\n\\t\\t(color\\t\\n\\t\\t\\t'The object''s interior color')\\n\\t\\t(colorSees\\n\\t\\t\\t'Whether a given color in the object is over another given color')\\n\\t\\t(colorUnder\\n\\t\\t\\t'The color under the center of the object')\\n\\t\\t(copy\\n\\t\\t\\t'Return a new object that is very much like this one')\\n\\t\\t(cursor\\t\\n\\t\\t\\t'The index of the chosen element')\\n\\t\\t(deleteCard\\n\\t\\t\\t'Delete the current card.')\\n\\t\\t(dismiss\\n\\t\\t\\t'Click here to dismiss me')\\n\\t\\t(doMenuItem:\\n\\t\\t\\t'Do a menu item, the same way as if it were chosen manually')\\n\\t\\t(doScript:\\n\\t\\t\\t'Perform the given script once, on the next tick.')\\n\\t\\t(elementNumber\\n\\t\\t\\t'My element number as seen by my owner')\\n\\t\\t(fire\\n\\t\\t\\t'Run any and all button-firing scripts of this object')\\n\\t\\t(firstPage\\n\\t\\t\\t'Go to first page of book')\\n\\t\\t(followPath\\n\\t\\t\\t\\t'Retrace the path the object has memorized, if any.')\\n\\t\\t(forward:\\n\\t\\t\\t'Moves the object forward in the direction it is heading') \\n\\t\\t(goto:\\n\\t\\t\\t'Go to the specfied book page')\\n\\t\\t(goToNextCardInStack\\n\\t\\t\\t'Go to the next card')\\n\\t\\t(goToPreviousCardInStack\\n\\t\\t\\t'Go to the previous card.')\\n\\t\\t(goToRightOf:\\n\\t\\t\\t'Align the object just to the right of any specified object.')\\n\\t\\t(heading\\n\\t\\t\\t'Which direction the object is facing. 0 is straight up') \\n\\t\\t(height\\t\\n\\t\\t\\t'The distance between the top and bottom edges of the object')\\n\\t\\t(hide\\n\\t\\t\\t'Make the object so that it does not display and cannot handle input')\\n\\t\\t(initiatePainting\\t\\n\\t\\t\\t'Initiate painting of a new object in the standard playfield.')\\n\\t\\t(initiatePaintingIn:\\n\\t\\t\\t'Initiate painting of a new object in the given place.')\\n\\t\\t(isOverColor\\n\\t\\t\\t'Whether any part of this object is directly over the specified color')\\n\\t\\t(isUnderMouse\\n\\t\\t\\t'Whether any part of this object is beneath the current mouse-cursor position')\\n\\t\\t(lastPage\\n\\t\\t\\t'Go to the last page of the book.')\\n\\t\\t(left\\n\\t\\t\\t'My left edge, measured from the left edge of the World')\\n\\t\\t(leftRight\\n\\t\\t\\t'The horizontal displacement')\\n\\t\\t(liftAllPens\\n\\t\\t\\t'Lift the pens on all the objects in my interior.')\\n\\t\\t(lowerAllPens\\n\\t\\t\\t'Lower the pens on all the objects in my interior.')\\n\\t\\t(mouseX\\n\\t\\t\\t'The x coordinate of the mouse pointer')\\n\\t\\t(mouseY\\n\\t\\t\\t'The y coordinate of the mouse pointer')\\n\\t\\t(moveToward:\\n\\t\\t\\t'Move in the direction of another object.')\\n\\t\\t(insertCard\\n\\t\\t\\t'Create a new card.')\\n\\t\\t(nextPage\\n\\t\\t\\t'Go to next page.')\\n\\t\\t(numberAtCursor\\n\\t\\t\\t'The number held by the object at the chosen element')\\n\\t\\t(objectNameInHalo\\n\\t\\t\\t'Object''s name -- To change: click here, edit, hit ENTER')\\n\\t\\t(obtrudes\\n\\t\\t\\t'Whether any part of the object sticks out beyond its container''s borders')\\n\\t\\t(offerScriptorMenu\\n\\t\\t\\t'The Scriptee.\\nPress here to get a menu')\\n\\t\\t(pauseScript:\\n\\t\\t\\t'Make a running script become paused.')\\n\\t\\t(penDown\\n\\t\\t\\t'Whether the object''s pen is down (true) or up (false)')\\n\\t\\t(penColor\\n\\t\\t\\t'The color of the object''s pen')\\n\\t\\t(penSize\\t\\n\\t\\t\\t'The size of the object''s pen')\\n\\t\\t(clearPenTrails\\n\\t\\t\\t'Clear all pen trails in the current playfield')\\n\\t\\t(playerSeeingColorPhrase\\n\\t\\t\\t'The player who \\\"sees\\\" a given color')\\n\\t\\t(previousPage\\n\\t\\t\\t'Go to previous page')\\n\\n\\t\\t(show\\n\\t\\t\\t'If object was hidden, make it show itself again.')\\n\\t\\t(startScript:\\n\\t\\t\\t'Make a script start running.')\\n\\t\\t(stopScript:\\n\\t\\t\\t'Make a script stop running.')\\n\\t\\t(top\\n\\t\\t\\t'My top edge, measured downward from the top edge of the world')\\n\\t\\t(right\\n\\t\\t\\t'My right edge, measured from the left edge of the world')\\n\\t\\t(roundUpStrays\\n\\t\\t\\t'Bring all out-of-container subparts back into view.')\\n\\t\\t(scaleFactor\\n\\t\\t\\t'The amount by which the object is scaled')\\n\\t\\t(stopScript:\\n\\t\\t\\t'make the specified script stop running')\\n\\t\\t(tellAllSiblings:\\n\\t\\t\\t'send a message to all of my sibling instances')\\n\\t\\t(try\\n\\t\\t\\t'Run this command once.')\\n\\t\\t(tryMe\\n\\t\\t\\t'Click here to run this script once; hold button down to run repeatedly')\\n\\t\\t(turn:\\t\\t\\t\\t\\n\\t\\t\\t'Change the heading of the object by the specified amount')\\n\\t\\t(unhideHiddenObjects\\n\\t\\t\\t'Unhide all hidden objects.')\\n\\t\\t(upDown\\n\\t\\t\\t'The vertical displacement')\\n\\t\\t(userScript\\n\\t\\t\\t'This is a script defined by you.')\\n\\t\\t(userSlot\\n\\t\\t\\t'This is a variable defined by you. Click here to change its type')\\n\\t\\t(valueAtCursor\\n\\t\\t\\t'The chosen element')\\n\\t\\t(wearCostumeOf:\\n\\t\\t\\t'Wear the same kind of costume as the other object')\\n\\t\\t(width\\t\\n\\t\\t\\t'The distance between the left and right edges of the object')\\n\\t\\t(wrap\\n\\t\\t\\t'If object has strayed beond the boundaries of its container, make it reappear from the opposite edge.')\\n\\t\\t(x\\n\\t\\t\\t'The x coordinate, measured from the left of the container')\\n\\t\\t(y\\n\\t\\t\\t'The y-coordinate, measured upward from the bottom of the container')\\n\\n\\t\\t)\\n! !\\n\\n\\n!Morph class methodsFor: 'testing' stamp: 'nk 6/12/2004 09:20'!\\nallSketchMorphClasses\\n\\t\\\"Morph allSketchMorphClasses\\\"\\n\\t^ Array\\n\\t\\tstreamContents: [:s | self\\n\\t\\t\\t\\twithAllSubclassesDo: [:cls | cls isSketchMorphClass\\n\\t\\t\\t\\t\\t\\tifTrue: [s nextPut: cls ]]]\\n! !\\n\\n!Morph class methodsFor: 'testing' stamp: 'yo 3/17/2005 09:07'!\\nallSketchMorphForms\\n\\t\\\"Answer a Set of forms of SketchMorph (sub) instances, except those \\n\\tused as button images, ones being edited, and those with 0 extent.\\\"\\n\\n\\t| reasonableForms form |\\n\\treasonableForms := Set new.\\n\\tMorph allSketchMorphClasses do:\\n\\t\\t[:cls | cls allInstances do:\\n\\t\\t\\t[:m | (m owner isKindOf: SketchEditorMorph orOf: IconicButton)\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[form _ m form.\\n\\t\\t\\t\\t\\t((form width > 0) and: [form height > 0]) ifTrue: [reasonableForms add: form]]]].\\n\\t^ reasonableForms! !\\n\\n!Morph class methodsFor: 'testing' stamp: 'nk 6/12/2004 09:17'!\\nisSketchMorphClass\\n\\t^false! !\\n\\n\\n!Morph class methodsFor: '*eToys-customevents-user events' stamp: 'sw 6/16/2005 01:26'!\\nadditionsToViewerCategoryUserEvents\\n\\t\\\"Answer further viewer additions relating to user-defined events; these appear in the 'scripting' category\\\"\\n\\n\\t^ Preferences allowEtoyUserCustomEvents\\n\\t\\tifTrue: [ #(scripting (\\n\\t\\t\\t(command triggerCustomEvent: 'trigger a user-defined (global) event' CustomEvents)\\n\\t\\t\\t(slot triggeringObject 'the object that is triggering an event, either user-defined or pre-defined' Player readOnly Player getTriggeringObject unused unused)))]\\n\\t\\tifFalse: [#(scripting ())]! !\\n\\n\\n!Morph class methodsFor: '*eToys-new-morph participation' stamp: 'sw 10/24/2001 15:51'!\\npartName: aName categories: aList documentation: aDoc sampleImageForm: aForm\\n\\t\\\"Answer a DescriptionForPartsBin which will represent a launch of a new instance of my class via the #newStandAlone protocol sent to my class. Use the category-list and documentation provided. This variant allows an overriding image form to be provided, useful in cases where we don't want to launch a sample instance just to get the form\\\"\\n\\n\\n\\t| descr |\\n\\tdescr _ DescriptionForPartsBin new\\n\\t\\tformalName: aName\\n\\t\\tcategoryList: aList\\n\\t\\tdocumentation: aDoc\\n\\t\\tglobalReceiverSymbol: self name\\n\\t\\tnativitySelector: #newStandAlone.\\n\\tdescr sampleImageForm: aForm.\\n\\t^ descr\\n! !\\n\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/27/2001 17:40'!\\nadditionsToViewerCategoryBasic\\n\\t\\\"Answer viewer additions for the 'basic' category\\\"\\n\\n\\t^#(\\n\\t\\tbasic \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y \\t'The y coordinate' Number readWrite Player \\tgetY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\t\\t\\t(command forward: 'Moves the object forward in the direction it is heading' Number)\\n\\t\\t\\t(command turn: 'Change the heading of the object by the specified amount' Number)\\n\\t\\t\\t(command beep: 'Make the specified sound' Sound)\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 4/20/2002 00:47'!\\nadditionsToViewerCategoryDragAndDrop\\n\\t\\\"Answer viewer additions for the 'drag & drop' category\\\"\\n\\n\\t^#(\\n\\t\\t#'drag & drop'\\n \\n\\t\\t(\\n\\t\\t\\t(slot 'drop enabled' 'Whether drop is enabled' Boolean readWrite Player getDropEnabled Player setDropEnabled:)\\n\\t\\t\\t(slot 'resist being picked up' 'Whether a simple mouse-drag on this object should allow it to be picked up' Boolean readWrite Player getSticky Player setSticky:)\\n\\t\\t\\t(slot 'resist deletion' 'Whether this is resistant to easy removal via the pink X halo handle.' Boolean readWrite Player getResistsRemoval Player setResistsRemoval:)\\n\\t\\t\\t(slot 'be locked' 'Whether this object should be blind to all input' Boolean readWrite Player getIsLocked Player setIsLocked:)\\n\\t\\t\\n\\t\\t))! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/17/2002 13:58'!\\nadditionsToViewerCategoryGeometry\\n\\t\\\"answer additions to the geometry viewer category\\\"\\n\\n\\t^ #(geometry \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y 'The y coordinate' Number readWrite Player getY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\n\\t\\t\\t(slot scaleFactor 'The factor by which the object is magnified' Number readWrite Player getScaleFactor Player setScaleFactor:)\\n\\t\\t\\t(slot left 'The left edge' Number readWrite Player getLeft Player setLeft:)\\n\\t\\t\\t(slot right 'The right edge' Number readWrite Player getRight Player setRight:)\\n\\t\\t\\t(slot top 'The top edge' Number readWrite Player getTop Player setTop:) \\n\\t\\t\\t(slot bottom 'The bottom edge' Number readWrite Player getBottom Player setBottom:) \\n\\t\\t\\t(slot length 'The length' Number readWrite Player getLength Player setLength:) \\n\\t\\t\\t(slot width 'The width' Number readWrite Player getWidth Player setWidth:)\\n\\n\\t\\t\\t(slot headingTheta 'The angle, in degrees, that my heading vector makes with the positive x-axis' Number readWrite Player getHeadingTheta Player setHeadingTheta:)\\n\\n\\t\\t\\t(slot distance 'The length of the vector connecting the origin to the object''s position' Number readWrite Player getDistance Player setDistance:)\\n\\t\\t\\t(slot theta 'The angle between the positive x-axis and the vector connecting the origin to the object''s position' Number readWrite Player getTheta Player setTheta: )\\n\\t\\t)\\n\\t)\\n\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 11/16/2001 10:21'!\\nadditionsToViewerCategoryLayout\\n\\t\\\"Answer viewer additions for the 'layout' category\\\"\\n\\n\\t^#(\\n\\t\\tlayout \\n\\t\\t(\\n\\t\\t\\t(slot clipSubmorphs 'Whether or not to clip my submorphs' Boolean readWrite Player getClipSubmorphs Player setClipSubmorphs:)\\n\\n\\t\\t))\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 7/8/2004 00:20'!\\nadditionsToViewerCategoryMiscellaneous\\n\\t\\\"Answer viewer additions for the 'miscellaneous' category\\\"\\n\\n\\t^#(\\n\\t\\tmiscellaneous \\n\\t\\t(\\n\\t\\t\\t(command doMenuItem: 'do the menu item' Menu)\\n\\t\\t\\t(command show 'make the object visible')\\n\\t\\t\\t(command hide 'make the object invisible')\\n\\t\\t\\t(command wearCostumeOf: 'wear the costume of...' Player)\\n\\n\\t\\t\\t(command fire 'trigger any and all of this object''s button actions')\\n\\t\\t\\t(slot copy 'returns a copy of this object' Player readOnly Player getNewClone\\t unused unused)\\n\\t\\t\\t(slot elementNumber 'my index in my container' Number readWrite Player getIndexInOwner Player setIndexInOwner:)\\n\\t\\t\\t(slot holder 'the object''s container' Player readOnly Player getHolder Player setHolder:)\\n\\t\\t\\t(command stamp 'add my image to the pen trails')\\n\\t\\t\\t(command erase 'remove this object from the screen')\\n\\t\\t\\t(command stampAndErase 'add my image to the pen trails and go away')\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'dgd 8/8/2003 22:17'!\\nadditionsToViewerCategoryMotion\\n\\t\\\"Answer viewer additions for the 'motion' category\\\"\\n\\n\\t^#(\\n\\t\\tmotion \\n\\t\\t(\\n\\t\\t\\t(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n\\t\\t\\t(slot y \\t'The y coordinate' Number readWrite Player \\tgetY Player setY:)\\n\\t\\t\\t(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n\\t\\t\\t(command forward: 'Moves the object forward in the direction it is heading' Number)\\n\\t\\t\\t(slot obtrudes 'whether the object sticks out over its container''s edge' Boolean readOnly Player getObtrudes unused unused) \\n\\t\\t\\t(command turnToward: 'turn toward the given object' Player) \\n\\t\\t\\t(command moveToward: 'move toward the given object' Player) \\n\\t\\t\\t(command turn: 'Change the heading of the object by the specified amount' Number)\\n\\t\\t\\t(command bounce: 'bounce off the edge if hit' Sound) \\n\\t\\t\\t(command wrap 'wrap off the edge if appropriate') \\n\\t\\t\\t(command followPath 'follow the yellow brick road') \\n\\t\\t\\t(command goToRightOf: 'place this object to the right of another' Player)\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 12/9/2001 23:26'!\\nadditionsToViewerCategoryObservation\\n\\t\\\"Answer viewer additions for the 'observations' category\\\"\\n\\n\\t^#(\\n\\t\\tobservation\\n \\n\\t\\t(\\n\\t\\t\\t(slot colorUnder 'The color under the center of the object' Color readOnly Player getColorUnder unused unused )\\n\\t\\t\\t(slot brightnessUnder 'The brightness under the center of the object' Number readOnly Player getBrightnessUnder unused unused)\\n\\t\\t\\t(slot luminanceUnder 'The luminance under the center of the object' Number readOnly Player getLuminanceUnder unused unused)\\n\\t\\t\\t(slot saturationUnder 'The saturation under the center of the object' Number readOnly Player getSaturationUnder unused unused)\\n\\t\\t\\n\\t\\t))\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 4/17/2003 12:05'!\\nadditionsToViewerCategoryPenUse\\n\\t\\\"Answer viewer additions for the 'pen use' category\\\"\\n\\n\\t^#(\\n\\t\\t#'pen use' \\n\\t\\t(\\n\\t\\t\\t(slot penColor 'the color of ink used by the pen' Color readWrite Player getPenColor Player setPenColor:) \\n\\t\\t\\t(slot penSize 'the width of the pen' Number readWrite Player getPenSize Player setPenSize:) \\n\\t\\t\\t(slot penDown 'whether the pen is currently down' Boolean readWrite Player getPenDown Player setPenDown:)\\n\\t\\t\\t(slot trailStyle 'determines whether lines, arrows, arrowheads, or dots are used when I put down a pen trail' TrailStyle readWrite Player getTrailStyle Player setTrailStyle:)\\n\\t\\t\\t(slot dotSize 'diameter of dot to use when trailStyle is dots' Number readWrite Player getDotSize Player setDotSize:)\\n\\t\\t\\t(command clearOwnersPenTrails 'clear all pen trails in my containing playfield')\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 2/19/2003 18:04'!\\nadditionsToViewerCategoryScripting\\n\\t\\\"Answer viewer additions for the 'scripting' category\\\"\\n\\n\\t^#(\\n\\t\\tscripting \\n\\t\\t(\\n\\n\\t\\t\\t(command startScript: 'start the given script ticking' ScriptName)\\n\\t\\t\\t(command pauseScript: 'make the given script be \\\"paused\\\"' ScriptName)\\n\\t\\t\\t(command stopScript: 'make the given script be \\\"normal\\\"' ScriptName)\\n\\n\\t\\t\\t(command startAll: 'start the given script ticking in the object and all of its siblings.' ScriptName)\\n\\t\\t\\t(command pauseAll: 'make the given script be \\\"paused\\\" in the object and all of its siblings' ScriptName)\\n\\t\\t\\t(command stopAll: 'make the given script be \\\"normal\\\" in the object and all of its siblings' ScriptName)\\n\\n\\t\\t\\t(command doScript: 'run the given script once, on the next tick' ScriptName)\\n\\t\\t\\t(command tellSelfAndAllSiblings: 'run the given script in the object and in all of its siblings' ScriptName)\\n\\t\\t\\t(command tellAllSiblings: 'send a message to all siblings' ScriptName)))! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'RAA 5/18/2001 12:48'!\\nadditionsToViewerCategoryScripts\\n\\n\\t\\\"note: if you change the thing below you also need to change #tileScriptCommands.\\\"\\n\\n\\t^#(\\n\\t\\tscripts \\n\\t\\t(\\n\\t\\t\\t(command emptyScript 'an empty script')\\n\\t\\t)\\n\\t)\\n\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'nk 10/14/2004 10:59'!\\nadditionsToViewerCategoryTests\\n\\t\\\"Answer viewer additions for the 'tests' category.\\\"\\n\\n\\\"Note: Because of intractable performance problems in continuously evaluating isOverColor in a Viewer, the isOverColor entry is not given a readout\\\"\\n\\n\\t^#(\\n\\t\\t#tests \\n\\t\\t(\\n\\t\\t\\t(slot isOverColor 'whether any part of the object is over the given color' Boolean\\treadOnly Player seesColor: unused unused)\\n\\t\\t\\t(slot isUnderMouse 'whether the object is under the current mouse position' Boolean readOnly\\tPlayer getIsUnderMouse unused unused)\\n\\t\\t\\t(slot colorSees\\t'whether the given color sees the given color' Boolean readOnly\\tPlayer color:sees:\\tunused\\tunused)\\n\\t\\t\\t(slot overlaps 'whether I overlap a given object' Boolean readOnly Player overlaps: unused unused)\\n\\t\\t\\t(slot overlapsAny 'whether I overlap a given object or one of its siblings or similar objects' Boolean readOnly Player overlapsAny: unused unused)\\n\\t\\t\\t(slot touchesA\\t'whether I overlap any Sketch that is showing the same picture as a particular prototype.' Boolean readOnly Player touchesA:\\tunused\\tunused)\\n\\t\\t\\t(slot obtrudes 'whether the object sticks out over its container''s edge' Boolean readOnly Player getObtrudes unused unused)\\n\\t\\t)\\n\\t)\\n! !\\n\\n!Morph class methodsFor: '*eToys-scripting' stamp: 'sw 9/17/2002 10:00'!\\nvectorAdditions\\n\\t\\\"Answer slot/command definitions for the vector experiment\\\"\\n\\n\\t^ # (\\n(slot x 'The x coordinate' Number readWrite Player getX Player setX:)\\n(slot y 'The y coordinate' Number readWrite Player getY Player setY:)\\n(slot heading 'Which direction the object is facing. 0 is straight up' Number readWrite Player getHeading Player setHeading:)\\n(slot distance 'The length of the vector connecting the origin to the object''s position' Number readWrite Player getDistance Player setDistance:)\\n(slot theta 'The angle between the positive x-axis and the vector connecting the origin to the object''s position' Number readWrite Player getTheta Player setTheta: )\\n(slot headingTheta 'The angle that my heading vector makes with the positive x-axis' Number readWrite Player getHeadingTheta Player setHeadingTheta:)\\n\\n(command + 'Adds two players together, treating each as a vector from the origin.' Player)\\n(command - 'Subtracts one player from another, treating each as a vector from the origin.' Player)\\n(command * 'Multiply a player by a Number, treating the Player as a vector from the origin.' Number)\\n(command / 'Divide a player by a Number, treating the Player as a vector from the origin.' Number)\\n\\n(command incr: 'Each Player is a vector from the origin. Increase one by the amount of the other.' Player)\\n(command decr: 'Each Player is a vector from the origin. Decrease one by the amount of the other.' Player)\\n(command multBy: 'A Player is a vector from the origin. Multiply its length by the factor.' Number)\\n(command dividedBy: 'A Player is a vector from the origin. Divide its length by the factor.' Number)\\n\\t)! !\\n\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 10/11/2003 18:17'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the\\n\\tphrases this kind of morph wishes to add to various Viewer categories.\\n\\n\\tThis version factors each category definition into a separate method.\\n\\n\\tSubclasses that have additions can either:\\n\\t\\t- override this method, or\\n\\t\\t- (preferably) define one or more additionToViewerCategory* methods.\\n\\n\\tThe advantage of the latter technique is that class extensions may be added\\n\\tby external packages without having to re-define additionsToViewerCategories.\\n\\t\\\"\\n\\t^#()! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 8/29/2004 16:35'!\\nadditionsToViewerCategory: aCategoryName\\n\\t\\\"Answer a list of viewer specs for items to be added to the given category on behalf of the receiver. Each class in a morph's superclass chain is given the opportunity to add more things\\\"\\n\\n\\taCategoryName == #vector ifTrue:\\n\\t\\t[^ self vectorAdditions].\\n\\t^self allAdditionsToViewerCategories at: aCategoryName ifAbsent: [ #() ].! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 10/11/2003 18:06'!\\nadditionToViewerCategorySelectors\\n\\t\\\"Answer the list of my selectors matching additionsToViewerCategory*\\\"\\n\\t^self class organization allMethodSelectors select: [ :ea |\\n\\t\\t(ea beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\tand: [ (ea at: 26 ifAbsent: []) ~= $: ]]! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'nk 9/11/2004 16:56'!\\nallAdditionsToViewerCategories\\n\\t\\\"Answer a Dictionary of (<categoryName> <list of category specs>) that \\n\\tdefines the phrases this kind of morph wishes to add to various Viewer categories. \\n\\t \\n\\tThis version allows each category definition to be defined in one or more separate methods. \\n\\t \\n\\tSubclasses that have additions can either:\\n\\t- override #additionsToViewerCategories, or\\n\\t- (preferably) define one or more additionToViewerCategory* methods.\\n\\n\\tThe advantage of the latter technique is that class extensions may be added by\\n\\texternal packages without having to re-define additionsToViewerCategories.\\\"\\n\\n\\t\\\"\\n\\tMorph allAdditionsToViewerCategories\\n\\t\\\"\\n\\t| dict |\\n\\tdict := IdentityDictionary new.\\n\\t(self class includesSelector: #additionsToViewerCategories)\\n\\t\\tifTrue: [self additionsToViewerCategories\\n\\t\\t\\t\\tdo: [:group | group\\n\\t\\t\\t\\t\\t\\tpairsDo: [:key :list | (dict\\n\\t\\t\\t\\t\\t\\t\\t\\tat: key\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [OrderedCollection new])\\n\\t\\t\\t\\t\\t\\t\\t\\taddAll: list]]].\\n\\tself class selectors\\n\\t\\tdo: [:aSelector | ((aSelector beginsWith: 'additionsToViewerCategory')\\n\\t\\t\\t\\t\\tand: [(aSelector at: 26 ifAbsent: []) ~= $:])\\n\\t\\t\\t\\tifTrue: [(self perform: aSelector)\\n\\t\\t\\t\\t\\t\\tpairsDo: [:key :list | (dict\\n\\t\\t\\t\\t\\t\\t\\t\\tat: key\\n\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [OrderedCollection new])\\n\\t\\t\\t\\t\\t\\t\\t\\taddAll: list]]].\\n\\t^ dict! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-scripting' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nunfilteredCategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer for one of my instances, in order of:\\n\\t- masterOrderingOfCategorySymbols first\\n\\t- others last in order by translated wording\\\"\\n\\t\\\"\\n\\tMorph unfilteredCategoriesForViewer\\n\\t\\\"\\n\\n\\t| aClass additions masterOrder |\\n\\taClass := self.\\n\\tadditions := OrderedCollection new.\\n\\t[aClass == Morph superclass ] whileFalse: [\\n\\t\\tadditions addAll: (aClass allAdditionsToViewerCategories keys\\n\\t\\t\\tasSortedCollection: [ :a :b | a translated < b translated ]).\\n\\t\\taClass := aClass superclass ]. \\n\\n\\tmasterOrder := EToyVocabulary masterOrderingOfCategorySymbols.\\n\\n\\t^(masterOrder intersection: additions), (additions difference: masterOrder).! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-arrow head size'!\\ndefaultArrowheadSize\\n\\t\\n\\t^ 5 @ 4! !\\n\\n!Morph class methodsFor: '*MorphicExtras-arrow head size'!\\nobtainArrowheadFor: aPrompt defaultValue: defaultPoint\\n\\t\\\"Allow the user to supply a point to serve as an arrowhead size. Answer nil if we fail to get a good point\\\"\\n\\n\\t| result |\\n\\tresult := FillInTheBlank request: aPrompt initialAnswer: defaultPoint asString.\\n\\tresult isEmptyOrNil ifTrue: [^ nil].\\n\\t^ [(Point readFrom: (ReadStream on: result))]\\n\\t\\ton: Error do: [:ex | nil].! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-new-morph participation' stamp: 'sw 11/27/2001 13:20'!\\naddPartsDescriptorQuadsTo: aList if: aBlock\\n\\t\\\"For each of the standard objects to be put into parts bins based on declarations in this class, add a parts-launching quintuplet to aList, provided that the boolean-valued-block-with-one-argument supplied evaluates to true when provided the DescriptionForPartsBin\\\"\\n\\n\\t| info more |\\n\\t(self class includesSelector: #descriptionForPartsBin) ifTrue:\\n\\t\\t[info _ self descriptionForPartsBin.\\n\\t\\t(aBlock value: info) ifTrue:\\n\\t\\t\\t[aList add:\\n\\t\\t\\t\\t{info globalReceiverSymbol.\\n\\t\\t\\t\\tinfo nativitySelector.\\n\\t\\t\\t\\tinfo formalName.\\n\\t\\t\\t\\tinfo documentation.\\n\\t\\t\\t\\tinfo sampleImageFormOrNil}]].\\n\\n\\t(self class includesSelector: #supplementaryPartsDescriptions)\\n\\t\\tifTrue:\\n\\t\\t\\t[more _ self supplementaryPartsDescriptions.\\n\\t\\t\\t(more isKindOf: DescriptionForPartsBin) ifTrue: [more _ Array with: more].\\n\\t\\t\\t\\t\\\"The above being a mild bit of forgiveness, so that in the usual only-one\\n\\t\\t\\t\\tcase, the user need not return a collection\\\"\\n\\t\\t\\tmore do:\\n\\t\\t\\t\\t[:aPartsDescription | (aBlock value: aPartsDescription) ifTrue:\\n\\t\\t\\t\\t\\t[aList add:\\n\\t\\t\\t\\t\\t\\t{aPartsDescription globalReceiverSymbol.\\n\\t\\t\\t\\t\\t\\taPartsDescription nativitySelector.\\n\\t\\t\\t\\t\\t\\taPartsDescription formalName.\\n\\t\\t\\t\\t\\t\\taPartsDescription documentation.\\n\\t\\t\\t\\t\\t\\taPartsDescription sampleImageFormOrNil}]]]! !\\n\\n\\n!Morph class methodsFor: '*MorphicExtras-parts bin' stamp: 'sw 8/12/2001 14:26'!\\nsupplementaryPartsDescriptions\\n\\t\\\"Answer a list of DescriptionForPartsBin objects that characterize objects that this class wishes to contribute to Stationery bins *other* than by the standard default #newStandAlone protocol\\\"\\n\\n\\t^ {\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Status'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Buttons to run, stop, or single-step scripts'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #scriptControlButtons.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Scripting'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'A confined place for drawing and scripting, with its own private stop/step/go buttons.'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #newScriptingSpace.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'Random'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'A tile that will produce a random number in a given range'\\n\\t\\t\\tglobalReceiverSymbol: #RandomNumberTile\\n\\t\\t\\tnativitySelector: #new.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'ButtonDown?'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Tiles for querying whether the mouse button is down'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #anyButtonPressedTiles.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'ButtonUp?'\\n\\t\\t\\tcategoryList: #(Scripting)\\n\\t\\t\\tdocumentation: 'Tiles for querying whether the mouse button is up'\\n\\t\\t\\tglobalReceiverSymbol: #ScriptingSystem\\n\\t\\t\\tnativitySelector: #noButtonPressedTiles.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'NextPage'\\n\\t\\t\\tcategoryList: #(Presentation)\\n\\t\\t\\tdocumentation: 'A button which, when clicked, takes the reader to the next page of a book'\\n\\t\\t\\tglobalReceiverSymbol: #BookMorph\\n\\t\\t\\tnativitySelector: #nextPageButton.\\n\\t\\tDescriptionForPartsBin\\n\\t\\t\\tformalName: 'PreviousPage'\\n\\t\\t\\tcategoryList: #(Presentation)\\n\\t\\t\\tdocumentation: 'A button which, when clicked, takes the reader to the next page of a book'\\n\\t\\t\\tglobalReceiverSymbol: #BookMorph\\n\\t\\t\\tnativitySelector: #previousPageButton.},\\n\\n\\t(Flaps quadsDefiningToolsFlap collect:\\n\\t\\t[:aQuad | DescriptionForPartsBin fromQuad: aQuad categoryList: #(Tools)])! !\\n\\n\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'al 11/28/2005 16:46'!\\nnoteAddedSelector: aSelector meta: isMeta\\n\\t\\\"Any change to an additionsToViewer... method can invalidate existing etoy vocabularies.\\n\\tThe #respondsTo: test is to allow loading the FlexibleVocabularies change set without having to worry about method ordering.\\\"\\n\\t(isMeta\\n\\t\\t\\tand: [(aSelector beginsWith: 'additionsToViewer')\\n\\t\\t\\t\\t\\tand: [self respondsTo: #hasAdditionsToViewerCategories]])\\n\\t\\tifTrue: [Vocabulary changeMadeToViewerAdditions].\\n\\tsuper noteCompilationOf: aSelector meta: isMeta! !\\n\\n!Morph class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/15/2004 12:40'!\\nnoteCompilationOf: aSelector meta: isMeta\\n\\t\\\"This method does nothing and should be removed!!\\\"\\n\\n\\t^ super noteCompilationOf: aSelector meta: isMeta! !\\nRectangleMorph subclass: #MorphExample\\n\\tinstanceVariableNames: 'phase ball star'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n!MorphExample commentStamp: 'kfr 10/26/2003 18:38' prior: 0!\\nThis is a example of how to use a morph. It consists of only two \\nmethods, initialize and step.\\n\\nDoIt:\\nMorphExample new openInWorld.\\n\\n\\n\\n!\\n\\n\\n!MorphExample methodsFor: 'initialization' stamp: 'dgd 2/21/2003 19:59'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tphase _ 1.\\n\\tself extent: 200 @ 200.\\n\\tball _ EllipseMorph new extent: 30 @ 30.\\n\\tself\\n\\t\\taddMorph: ((star _ StarMorph new extent: 150 @ 150) center: self center)! !\\n\\n\\n!MorphExample methodsFor: 'stepping and presenter' stamp: 'kfr 10/26/2003 18:33'!\\nstep\\n\\tphase _ phase\\\\\\\\8 + 1.\\n\\tphase = 1 ifTrue: [^ ball delete].\\n\\tphase < 4 ifTrue:[^self].\\n\\tphase = 4 ifTrue: [self addMorph: ball].\\n\\tball align: ball center with: (star vertices at: (phase-3*2)).! !\\nObject subclass: #MorphExtension\\n\\tinstanceVariableNames: 'locked visible sticky balloonText balloonTextSelector externalName isPartsDonor actorState player eventHandler otherProperties'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MorphExtension commentStamp: '<historical>' prior: 0!\\nMorphExtension provides access to extra instance state that is not required in most simple morphs. This allows simple morphs to remain relatively lightweight while still admitting more complex structures as necessary. The otherProperties field takes this policy to the extreme of allowing any number of additional named attributes, albeit at a certain cost in speed and space.!\\n\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:52'!\\nballoonText\\n\\t^ balloonText! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:52'!\\nballoonTextSelector\\n\\t^ balloonTextSelector! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:51'!\\nballoonTextSelector: aSymbol \\n\\t\\\"change the receiver's balloonTextSelector\\\"\\n\\tballoonTextSelector _ aSymbol! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:55'!\\nballoonText: newValue\\n\\tballoonText _ newValue! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:51'!\\neventHandler\\n\\t\\\"answer the receiver's eventHandler\\\"\\n\\t^ eventHandler ! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:56'!\\neventHandler: newValue\\n\\teventHandler _ newValue! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:57'!\\nexternalName: aString \\n\\t\\\"change the receiver's externalName\\\"\\n\\texternalName _ aString! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:38'!\\nlocked\\n\\t\\\"answer whether the receiver is Locked\\\"\\n\\t^ locked! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:48'!\\nlocked: aBoolean \\n\\t\\\"change the receiver's locked property\\\"\\n\\tlocked _ aBoolean! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/14/1998 13:07'!\\nsticky\\n\\t^ sticky! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:47'!\\nsticky: aBoolean \\n\\t\\\"change the receiver's sticky property\\\"\\n\\tsticky _ aBoolean! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'dgd 2/16/2003 21:41'!\\nvisible\\n\\t\\\"answer whether the receiver is visible\\\"\\n\\t^ visible! !\\n\\n!MorphExtension methodsFor: 'accessing' stamp: 'di 8/10/1998 12:55'!\\nvisible: newValue\\n\\tvisible _ newValue! !\\n\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:17'!\\nlayoutFrame\\n\\t^self valueOfProperty: #layoutFrame ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutFrame: aLayoutFrame \\n\\taLayoutFrame isNil\\n\\t\\tifTrue: [self removeProperty: #layoutFrame]\\n\\t\\tifFalse: [self setProperty: #layoutFrame toValue: aLayoutFrame]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:17'!\\nlayoutPolicy\\n\\t^self valueOfProperty: #layoutPolicy ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutPolicy: aLayoutPolicy \\n\\taLayoutPolicy isNil\\n\\t\\tifTrue: [self removeProperty: #layoutPolicy]\\n\\t\\tifFalse: [self setProperty: #layoutPolicy toValue: aLayoutPolicy]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'ar 11/14/2000 17:18'!\\nlayoutProperties\\n\\t^self valueOfProperty: #layoutProperties ifAbsent:[nil]! !\\n\\n!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'dgd 2/22/2003 13:32'!\\nlayoutProperties: newProperties \\n\\t\\\"Return the current layout properties associated with the receiver\\\"\\n\\n\\tnewProperties isNil\\n\\t\\tifTrue: [self removeProperty: #layoutProperties]\\n\\t\\tifFalse: [self setProperty: #layoutProperties toValue: newProperties]! !\\n\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:41'!\\nassureOtherProperties\\n\\t\\\"creates an otherProperties for the receiver if needed\\\"\\n\\totherProperties ifNil: [self initializeOtherProperties].\\n\\t^ otherProperties! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:36'!\\nhasOtherProperties\\n\\t\\\"answer whether the receiver has otherProperties\\\"\\n\\t^ otherProperties notNil! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:42'!\\nhasProperty: aSymbol \\n\\t\\\"Answer whether the receiver has the property named aSymbol\\\"\\n\\t| property |\\n\\totherProperties ifNil: [^ false].\\n\\tproperty := otherProperties at: aSymbol ifAbsent: [].\\n\\tproperty isNil ifTrue: [^ false].\\n\\tproperty == false ifTrue: [^ false].\\n\\t^ true! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:36'!\\ninitializeOtherProperties\\n\\t\\\"private - initializes the receiver's otherProperties\\\"\\n\\totherProperties := IdentityDictionary new! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:04'!\\notherProperties\\n\\t\\\"answer the receiver's otherProperties\\\"\\n\\t^ otherProperties! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:20'!\\nprivateOtherProperties: anIndentityDictionary \\n\\t\\\"private - change the receiver's otherProperties\\\"\\n\\totherProperties _ anIndentityDictionary ! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:37'!\\nremoveOtherProperties\\n\\t\\\"Remove the 'other' properties\\\"\\n\\totherProperties := nil! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:43'!\\nremoveProperty: aSymbol \\n\\t\\\"removes the property named aSymbol if it exists\\\"\\n\\totherProperties ifNil: [^ self].\\n\\totherProperties removeKey: aSymbol ifAbsent: [].\\n\\totherProperties isEmpty ifTrue: [self removeOtherProperties]! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:49'!\\nsetProperty: aSymbol toValue: abObject \\n\\t\\\"change the receiver's property named aSymbol to anObject\\\"\\n\\tself assureOtherProperties at: aSymbol put: abObject! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:45'!\\nsortedPropertyNames\\n\\t\\\"answer the receiver's property names in a sorted way\\\"\\n\\n\\t| props |\\n\\tprops := WriteStream on: (Array new: 10).\\n\\tlocked == true ifTrue: [props nextPut: #locked].\\n\\tvisible == false ifTrue: [props nextPut: #visible].\\n\\tsticky == true ifTrue: [props nextPut: #sticky].\\n\\tballoonText isNil ifFalse: [props nextPut: #balloonText].\\n\\tballoonTextSelector isNil ifFalse: [props nextPut: #balloonTextSelector].\\n\\texternalName isNil ifFalse: [props nextPut: #externalName].\\n\\tisPartsDonor == true ifTrue: [props nextPut: #isPartsDonor].\\n\\tactorState isNil ifFalse: [props nextPut: #actorState].\\n\\tplayer isNil ifFalse: [props nextPut: #player].\\n\\teventHandler isNil ifFalse: [props nextPut: #eventHandler].\\n\\t otherProperties ifNotNil: [otherProperties associationsDo: [:a | props nextPut: a key]].\\n\\t^props contents sort: [:s1 :s2 | s1 <= s2]! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:00'!\\nvalueOfProperty: aSymbol \\n\\\"answer the value of the receiver's property named aSymbol\\\"\\n\\t^ self\\n\\t\\tvalueOfProperty: aSymbol\\n\\t\\tifAbsent: []! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'dgd 2/16/2003 21:28'!\\nvalueOfProperty: aSymbol ifAbsentPut: aBlock \\n\\t\\\"If the receiver possesses a property of the given name, answer \\n\\tits value. If not, then create a property of the given name, give \\n\\tit the value obtained by evaluating aBlock, then answer that \\n\\tvalue\\\"\\n\\t^self assureOtherProperties at: aSymbol ifAbsentPut: aBlock! !\\n\\n!MorphExtension methodsFor: 'accessing - other properties' stamp: 'md 2/27/2006 08:43'!\\nvalueOfProperty: aSymbol ifAbsent: aBlock \\n\\t\\\"if the receiver possesses a property of the given name, answer \\n\\tits value. If not then evaluate aBlock and answer the result of \\n\\tthis block evaluation\\\"\\n\\totherProperties ifNil: [^ aBlock value].\\n\\t^ otherProperties at: aSymbol ifAbsent: [^ aBlock value]! !\\n\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:20'!\\ncopyWeakly\\n\\t\\\"list of names of properties whose values should be weak-copied when veryDeepCopying a morph. See DeepCopier.\\\"\\n\\n\\t^ #(formerOwner newPermanentPlayer logger graphModel gestureDictionaryOrName)\\n\\t\\\"add yours to this list\\\" \\n\\n\\t\\\"formerOwner should really be nil at the time of the copy, but this will work just fine.\\\"! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:23'!\\npropertyNamesNotCopied\\n\\t\\\"list of names of properties whose values should be deleted when veryDeepCopying a morph.\\n\\tSee DeepCopier.\\\"\\n\\n\\t^ #(connectedConstraints connectionHighlights highlightedTargets)\\n\\t\\\"add yours to this list\\\" \\n! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:39'!\\nveryDeepFixupWith: deepCopier \\n\\t\\\"If target and arguments fields were weakly copied, fix them here.\\n\\tIf they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\n\\tsuper veryDeepFixupWith: deepCopier.\\n\\totherProperties ifNil: [ ^self ].\\n\\n\\t\\\"Properties whose values are only copied weakly replace those values if they were copied via another path\\\"\\n\\tself copyWeakly do: [ :propertyName |\\n\\t\\totherProperties at: propertyName ifPresent: [ :property |\\n\\t\\t\\totherProperties at: propertyName\\n\\t\\t\\t\\tput: (deepCopier references at: property ifAbsent: [ property ])]].\\n! !\\n\\n!MorphExtension methodsFor: 'connectors-copying' stamp: 'nk 5/1/2004 17:45'!\\nveryDeepInner: deepCopier \\n\\t\\\"Copy all of my instance variables.\\n\\tSome otherProperties need to be not copied at all, but shared. Their names are given by copyWeakly.\\n\\tSome otherProperties should not be copied or shared. Their names are given by propertyNamesNotCopied.\\n\\tThis is special code for the dictionary. See DeepCopier, and veryDeepFixupWith:.\\\"\\n\\n\\t| namesOfWeaklyCopiedProperties weaklyCopiedValues |\\n\\tsuper veryDeepInner: deepCopier.\\n\\tlocked _ locked veryDeepCopyWith: deepCopier.\\n\\tvisible _ visible veryDeepCopyWith: deepCopier.\\n\\tsticky _ sticky veryDeepCopyWith: deepCopier.\\n\\tballoonText _ balloonText veryDeepCopyWith: deepCopier.\\n\\tballoonTextSelector _ balloonTextSelector veryDeepCopyWith: deepCopier.\\n\\texternalName _ externalName veryDeepCopyWith: deepCopier.\\n\\tisPartsDonor _ isPartsDonor veryDeepCopyWith: deepCopier.\\n\\tactorState _ actorState veryDeepCopyWith: deepCopier.\\n\\tplayer _ player veryDeepCopyWith: deepCopier.\\t\\t\\\"Do copy the player of this morph\\\"\\n\\teventHandler _ eventHandler veryDeepCopyWith: deepCopier. \\t\\\"has its own restrictions\\\"\\n\\n\\totherProperties ifNil: [ ^self ].\\n\\n\\totherProperties := otherProperties copy.\\n\\tself propertyNamesNotCopied do: [ :propName | otherProperties removeKey: propName ifAbsent: [] ].\\n\\n\\tnamesOfWeaklyCopiedProperties _ self copyWeakly.\\n\\tweaklyCopiedValues _ namesOfWeaklyCopiedProperties collect: [ :propName | otherProperties removeKey: propName ifAbsent: [] ].\\n\\n\\t\\\"Now copy all the others.\\\"\\n\\totherProperties := otherProperties veryDeepCopyWith: deepCopier.\\n\\n\\t\\\"And replace the weak ones.\\\"\\n\\tnamesOfWeaklyCopiedProperties with: weaklyCopiedValues do: [ :name :value | value ifNotNil: [ otherProperties at: name put: value ]].\\n! !\\n\\n\\n!MorphExtension methodsFor: 'initialization' stamp: 'di 8/16/1998 12:02'!\\ninitialize\\n\\t\\\"Init all booleans to default values\\\"\\n\\tlocked _ false.\\n\\tvisible _ true.\\n\\tsticky _ false.\\n\\tisPartsDonor _ false.\\n! !\\n\\n\\n!MorphExtension methodsFor: 'object fileIn' stamp: 'dgd 2/16/2003 21:06'!\\nconvertProperty: aSymbol toValue: anObject \\n\\t\\\"These special cases move old properties into named fields of the \\n\\textension\\\"\\n\\taSymbol == #locked\\n\\t\\tifTrue: [^ locked _ anObject].\\n\\taSymbol == #visible\\n\\t\\tifTrue: [^ visible _ anObject].\\n\\taSymbol == #sticky\\n\\t\\tifTrue: [^ sticky _ anObject].\\n\\taSymbol == #balloonText\\n\\t\\tifTrue: [^ balloonText _ anObject].\\n\\taSymbol == #balloonTextSelector\\n\\t\\tifTrue: [^ balloonTextSelector _ anObject].\\n\\taSymbol == #actorState\\n\\t\\tifTrue: [^ actorState _ anObject].\\n\\taSymbol == #player\\n\\t\\tifTrue: [^ player _ anObject].\\n\\taSymbol == #name\\n\\t\\tifTrue: [^ externalName _ anObject].\\n\\t\\\"*renamed*\\\"\\n\\taSymbol == #partsDonor\\n\\t\\tifTrue: [^ isPartsDonor _ anObject].\\n\\t\\\"*renamed*\\\"\\n\\tself assureOtherProperties at: aSymbol put: anObject! !\\n\\n\\n!MorphExtension methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:45'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"inst vars have default booplean values.\\\"\\n\\n\\tlocked ifNil: [locked _ false].\\n\\tvisible ifNil: [visible _ true].\\n\\tsticky ifNil: [sticky _ false].\\n\\tisPartsDonor ifNil: [isPartsDonor _ false].\\n\\t^ self! !\\n\\n\\n!MorphExtension methodsFor: 'other' stamp: 'md 2/27/2006 08:39'!\\ninspectElement\\n\\t\\\"Create and schedule an Inspector on the otherProperties and the \\n\\tnamed properties.\\\"\\n\\t| key obj |\\n\\tkey _ (SelectionMenu selections: self sortedPropertyNames)\\n\\t\\t\\t\\tstartUpWithCaption: 'Inspect which property?'.\\n\\tkey\\n\\t\\tifNil: [^ self].\\n\\tobj _ otherProperties\\n\\t\\t\\t\\tat: key\\n\\t\\t\\t\\tifAbsent: ['nOT a vALuE'].\\n\\tobj = 'nOT a vALuE'\\n\\t\\tifTrue: [(self perform: key) inspect\\n\\t\\t\\t\\\"named properties\\\"]\\n\\t\\tifFalse: [obj inspect]! !\\n\\n!MorphExtension methodsFor: 'other' stamp: 'md 2/27/2006 08:42'!\\nisDefault\\n\\t\\\"Return true if the receiver is a default and can be omitted\\\"\\n\\tlocked == true\\n\\t\\tifTrue: [^ false].\\n\\tvisible == false\\n\\t\\tifTrue: [^ false].\\n\\tsticky == true\\n\\t\\tifTrue: [^ false].\\n\\tballoonText isNil\\n\\t\\tifFalse: [^ false].\\n\\tballoonTextSelector isNil\\n\\t\\tifFalse: [^ false].\\n\\texternalName isNil\\n\\t\\tifFalse: [^ false].\\n\\tisPartsDonor == true\\n\\t\\tifTrue: [^ false].\\n\\tactorState isNil\\n\\t\\tifFalse: [^ false].\\n\\tplayer isNil\\n\\t\\tifFalse: [^ false].\\n\\teventHandler isNil\\n\\t\\tifFalse: [^ false].\\n\\totherProperties ifNotNil: [otherProperties isEmpty ifFalse: [^ false]].\\n\\t^ true! !\\n\\n\\n!MorphExtension methodsFor: 'printing' stamp: 'md 2/27/2006 08:45'!\\nprintOn: aStream \\n\\t\\\"Append to the argument, aStream, a sequence of characters that \\n\\tidentifies the receiver.\\\" \\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' ' , self identityHashPrintString.\\n\\tlocked == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [locked] '].\\n\\tvisible == false\\n\\t\\tifTrue: [aStream nextPutAll: '[not visible] '].\\n\\tsticky == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [sticky] '].\\n\\tballoonText\\n\\t\\tifNotNil: [aStream nextPutAll: ' [balloonText] '].\\n\\tballoonTextSelector\\n\\t\\tifNotNil: [aStream nextPutAll: ' [balloonTextSelector: ' , balloonTextSelector printString , '] '].\\n\\texternalName\\n\\t\\tifNotNil: [aStream nextPutAll: ' [externalName = ' , externalName , ' ] '].\\n\\tisPartsDonor == true\\n\\t\\tifTrue: [aStream nextPutAll: ' [isPartsDonor] '].\\n\\tplayer\\n\\t\\tifNotNil: [aStream nextPutAll: ' [player = ' , player printString , '] '].\\n\\teventHandler\\n\\t\\tifNotNil: [aStream nextPutAll: ' [eventHandler = ' , eventHandler printString , '] '].\\n\\t(otherProperties isNil or: [otherProperties isEmpty ]) ifTrue: [^ self].\\n\\taStream nextPutAll: ' [other: '.\\n\\tself otherProperties\\n\\t\\tkeysDo: [:aKey | aStream nextPutAll: ' (' , aKey , ' -> ' , (self otherProperties at: aKey) printString , ')'].\\n\\taStream nextPut: $]! !\\n\\n\\n!MorphExtension methodsFor: 'viewer' stamp: 'di 8/10/1998 14:47'!\\nexternalName\\n\\t^ externalName! !\\n\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:56'!\\nactorState\\n\\t\\\"answer the redeiver's actorState\\\"\\n\\t^ actorState ! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:53'!\\nactorState: anActorState \\n\\\"change the receiver's actorState\\\"\\n\\tactorState _ anActorState! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:42'!\\nplayer\\n\\t\\\"answer the receiver's player\\\"\\n\\t^ player! !\\n\\n!MorphExtension methodsFor: '*eToys-accessing' stamp: 'dgd 2/16/2003 21:53'!\\nplayer: anObject \\n\\t\\\"change the receiver's player\\\"\\n\\tplayer _ anObject ! !\\n\\n\\n!MorphExtension methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 2/16/2003 21:37'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\t^ isPartsDonor! !\\n\\n!MorphExtension methodsFor: '*MorphicExtras-accessing' stamp: 'dgd 2/16/2003 21:40'!\\nisPartsDonor: aBoolean \\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\tisPartsDonor _ aBoolean! !\\n\\n\\n!MorphExtension methodsFor: '*MorphicExtras-copying' stamp: 'md 2/27/2006 08:44'!\\nupdateReferencesUsing: aDictionary \\n\\t\\\"Update intra-morph references within a composite morph that \\n\\thas been copied. For example, if a button refers to morph X in \\n\\tthe orginal \\n\\tcomposite then the copy of that button in the new composite \\n\\tshould refer to \\n\\tthe copy of X in new composite, not the original X. This default \\n\\timplementation updates the contents of any morph-bearing slot.\\\"\\n\\n\\t| old |\\n\\teventHandler isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[self eventHandler: self eventHandler copy.\\n\\t\\t\\t1 to: self eventHandler class instSize\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\told := eventHandler instVarAt: i.\\n\\t\\t\\t\\t\\told isMorph \\n\\t\\t\\t\\t\\t\\tifTrue: [eventHandler instVarAt: i put: (aDictionary at: old ifAbsent: [old])]]].\\n\\totherProperties ifNotNil: [otherProperties associationsDo: [:assn | \\n\\t\\t\\t\\t\\tassn value: (aDictionary at: assn value ifAbsent: [assn value])]]! !\\nObject subclass: #MorphHierarchy\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphHierarchy methodsFor: 'private' stamp: 'dgd 9/26/2004 18:28'!\\nasMorph\\n\\t\\\"Answer the morph version of the receiver\\\"\\n\\t| morph |\\n\\tmorph := MorphHierarchyListMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\tlist: #roots\\n\\t\\t\\t\\tselected: nil\\n\\t\\t\\t\\tchangeSelected: #selected:.\\n\\t\\\"\\\"\\n\\t^ morph inAContainer! !\\n\\n\\n!MorphHierarchy methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:29'!\\nroots\\n\\t\\\"Answer the roots for the Object Hierarchy, that means answer the World\\\"\\n\\t^ {MorphListItemWrapper with: World}! !\\n\\n!MorphHierarchy methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:30'!\\nselected: aMorphListItemWrapper \\n\\t\\\"Change the selected object\\\"\\n\\t| newSelection |\\n\\taMorphListItemWrapper isNil\\n\\t\\tifTrue: [^ self].\\n\\tnewSelection := aMorphListItemWrapper withoutListWrapper.\\n\\tnewSelection == World selectedObject\\n\\t\\tifTrue: [newSelection removeHalo]\\n\\t\\tifFalse: [newSelection addHalo].\\n\\tself changed: #selected! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphHierarchy class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphHierarchy class methodsFor: 'opening' stamp: 'dgd 9/25/2004 21:50'!\\nopenOrDelete\\n\\t| oldMorph |\\n\\toldMorph := World submorphs\\n\\t\\t\\t\\tdetect: [:each | each hasProperty: #morphHierarchy]\\n\\t\\t\\t\\tifNone: [| newMorph | \\n\\t\\t\\t\\t\\tnewMorph := self new asMorph.\\n\\t\\t\\t\\t\\tnewMorph bottomLeft: ActiveHand position.\\n\\t\\t\\t\\t\\tnewMorph openInWorld.\\n\\t\\t\\t\\t\\tnewMorph isFullOnScreen\\n\\t\\t\\t\\t\\t\\tifFalse: [newMorph goHome].\\n\\t\\t\\t\\t\\t^ self].\\n\\t\\\"\\\"\\n\\toldMorph delete! !\\nSimpleHierarchicalListMorph subclass: #MorphHierarchyListMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphHierarchyListMorph methodsFor: 'private' stamp: 'dgd 9/26/2004 18:57'!\\ncreateContainer\\n\\t\\\"Private - Create a container\\\"\\n\\t| container |\\n\\tcontainer := BorderedMorph new.\\n\\tcontainer extent: (World extent * (1 / 4 @ (2 / 3))) rounded.\\n\\tcontainer layoutPolicy: TableLayout new.\\n\\tcontainer hResizing: #rigid.\\n\\tcontainer vResizing: #rigid.\\n\\tcontainer\\n\\t\\tsetColor: Preferences menuColor\\n\\t\\tborderWidth: Preferences menuBorderWidth\\n\\t\\tborderColor: Preferences menuBorderColor.\\n\\tcontainer layoutInset: 0.\\n\\t\\\"container useRoundedCorners.\\\"\\n\\t\\\"\\\"\\n\\tcontainer setProperty: #morphHierarchy toValue: true.\\n\\tcontainer setNameTo: 'Objects Hierarchy' translated.\\n\\t\\\"\\\"\\n\\t^ container! !\\n\\n!MorphHierarchyListMorph methodsFor: 'private' stamp: 'dgd 9/26/2004 18:27'!\\ninAContainer\\n\\t\\\"Answer the receiver contained in a proper container\\\"\\n\\t| container |\\n\\tcontainer := self createContainer.\\n\\tcontainer addMorphBack: self.\\n\\t\\\" \\n\\tnasty hack to force the scroolbar recreation\\\"\\n\\tself extent: container extent - container borderWidth.\\n\\t\\\"\\\"\\n\\t^ container! !\\n\\n\\n!MorphHierarchyListMorph methodsFor: 'initialization' stamp: 'dgd 9/26/2004 18:18'!\\non: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel \\n\\tsuper\\n\\t\\ton: anObject\\n\\t\\tlist: getListSel\\n\\t\\tselected: getSelectionSel\\n\\t\\tchangeSelected: setSelectionSel\\n\\t\\tmenu: getMenuSel\\n\\t\\tkeystroke: keyActionSel.\\n\\t\\\"\\\"\\n\\tself borderWidth: 0.\\n\\tself autoDeselect: false.\\n\\tself enableDrag: false.\\n\\tself enableDrop: true.\\n\\tself hResizing: #spaceFill.\\n\\tself vResizing: #spaceFill.\\nself expandRoots! !\\n\\n\\n!MorphHierarchyListMorph methodsFor: 'selection' stamp: 'dgd 9/25/2004 21:28'!\\nsetSelectedMorph: aMorph \\n\\tsuper setSelectedMorph: aMorph.\\nself owner isNil ifFalse:[self owner delete]! !\\nListItemWrapper subclass: #MorphListItemWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!MorphListItemWrapper methodsFor: 'converting' stamp: 'dgd 9/26/2004 18:26'!\\nasString\\n\\t\\\"Answer the string representation of the receiver\\\"\\n\\t^ item externalName! !\\n\\n\\n!MorphListItemWrapper methodsFor: 'accessing' stamp: 'dgd 1/7/2005 20:01'!\\ncontents\\n\\t\\\"Answer the receiver's contents\\\"\\n\\n\\t| tentative submorphs |\\n\\ttentative := item submorphs\\n\\t\\t\\t\\tcollect: [:each | each renderedMorph].\\n\\n\\tsubmorphs := Preferences noviceMode\\n\\t\\t\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\t\\t\\ttentative\\n\\t\\t\\t\\t\\t\\treject: [:each | \\\"\\\"\\n\\t\\t\\t\\t\\t\\t\\teach isSystemWindow\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isDockingBar]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isKindOf: HaloMorph]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each hasProperty: #morphHierarchy]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isFlapOrTab]\\n\\t\\t\\t\\t\\t\\t\\t\\tor: [each isObjectsTool]]]\\n\\t\\t\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\t\\t\\ttentative\\n\\t\\t\\t\\t\\t\\treject: [:each | each isKindOf: HaloMorph]].\\n\\n\\t^ submorphs\\n\\t\\tcollect: [:each | self class with: each]! !\\n\\n!MorphListItemWrapper methodsFor: 'accessing' stamp: 'dgd 7/28/2005 13:03'!\\nicon\\n\\t\\\"Answer a form to be used as icon\\\"\\n\\t^ item iconOrThumbnailOfSize: ((Preferences tinyDisplay ifTrue: [16] ifFalse: [28]))! !\\nObjectOut subclass: #MorphObjectOut\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 4/6/1999 10:00'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Bring in the object, install, then resend aMessage\\\"\\n\\t| aMorph myUrl oldFlag response |\\n\\t\\\"Transcript show: thisContext sender selector; cr.\\\" \\\"useful for debugging\\\"\\n\\toldFlag _ recursionFlag.\\n\\trecursionFlag _ true.\\n\\tmyUrl _ url.\\t\\\"can't use inst vars after become\\\"\\n\\t\\\"fetch the object\\\"\\n\\taMorph _ self xxxFetch.\\t\\t\\\"watch out for the become!!\\\"\\n\\t\\t\\t\\\"Now we ARE a MORPH\\\"\\n\\toldFlag == true ifTrue: [\\n\\t\\tresponse _ (PopUpMenu labels: 'proceed normally\\\\debug' withCRs)\\n\\t\\t\\tstartUpWithCaption: 'Object being fetched for a second time.\\nShould not happen, and needs to be fixed later.'.\\n\\t\\tresponse = 2 ifTrue: [self halt]].\\t\\\"We are already the new object\\\"\\n\\n\\taMorph setProperty: #SqueakPage toValue: \\n\\t\\t\\t(SqueakPageCache pageCache at: myUrl).\\n\\t\\\"Can't be a super message, since this is the first message sent to this object\\\"\\n\\t^ aMorph perform: aMessage selector withArguments: aMessage arguments\\n! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 10/22/1998 15:43'!\\nfullReleaseCachedState\\n\\t\\\"do nothing, especially don't bring in my object!!\\\"! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 2/24/1999 00:08'!\\nsmallThumbnailForPageSorter\\n\\n\\t^ self sqkPage thumbnail! !\\n\\n!MorphObjectOut methodsFor: 'as yet unclassified' stamp: 'tk 2/24/1999 00:09'!\\nthumbnailForPageSorter\\n\\n\\t^ self sqkPage thumbnail! !\\nTestCase subclass: #MorphTest\\n\\tinstanceVariableNames: 'morph world'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicTests-Kernel'!\\n!MorphTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class Morph. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\ngetWorld\\n\\t^ world\\n\\t\\tifNil: [world := Project newMorphic world]! !\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\nsetUp\\n\\tmorph := Morph new! !\\n\\n!MorphTest methodsFor: 'initialize-release' stamp: 'tak 1/21/2005 11:12'!\\ntearDown\\n\\tmorph delete.\\n\\tworld\\n\\t\\tifNotNil: [Project deletingProject: world project]! !\\n\\n\\n!MorphTest methodsFor: 'testing - classification' stamp: 'md 4/16/2003 17:11'!\\ntestIsMorph\\n\\tself assert: (morph isMorph).! !\\n\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:31'!\\ntestOverlapAny\\n\\t\\\"self debug: #testOverlapAny\\\"\\n\\t| p1 p2 |\\n\\tp1 _ Morph new assuredPlayer.\\n\\tp2 _ EllipseMorph new assuredPlayer.\\n\\t\\\"Same position\\\"\\n\\tp1 costume position: 0@0.\\n\\tp2 costume position: 0@0.\\n\\tself assert: (p1 overlapsAny: p2).\\n\\t\\\"Different position\\\"\\n\\tp1 costume position: 0@0.\\n\\tp2 costume position: 500@0.\\n\\tself assert: (p1 overlapsAny: p2) not.! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:56'!\\ntestOverlapAnyDeletedPlayer\\n\\t\\\"self debug: #testOverlapAnyDeletedPlayer\\\"\\n\\t| me friend sibling |\\n\\tme := Morph new assuredPlayer assureUniClass; yourself.\\n\\tfriend := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tsibling := friend getNewClone.\\n\\tsibling costume delete.\\n\\tself getWorld addMorph: me costume.\\n\\t\\\"Same position but deleted\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 0 @ 0.\\n\\tsibling costume position: 0 @ 0.\\n\\tself assert: (me overlapsAny: friend) not.\\n\\tself assert: (me overlapsAny: sibling) not! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:40'!\\ntestOverlapAnyScriptedPlayer\\n\\t\\\"self debug: #testOverlapAnyScriptedPlayer\\\"\\n\\t| me friend other sibling |\\n\\tme := Morph new assuredPlayer assureUniClass; yourself.\\n\\tfriend := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tsibling := friend getNewClone.\\n\\tother := EllipseMorph new assuredPlayer assureUniClass; yourself.\\n\\tself getWorld addMorph: me costume;\\n\\t\\t addMorph: friend costume;\\n\\t\\t addMorph: other costume;\\n\\t\\t addMorph: sibling costume.\\n\\t\\\"myself\\\"\\n\\tself assert: (me overlapsAny: me) not.\\n\\t\\\"Same position with sibling\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 500 @ 0.\\n\\tother costume position: 500 @ 0.\\n\\tsibling costume position: 0@0.\\n\\tself assert: (me overlapsAny: friend).\\n\\t\\\"Different position with sibling but same class\\\"\\n\\tme costume position: 0 @ 0.\\n\\tfriend costume position: 500 @ 0.\\n\\tsibling costume position: 500@ 0.\\n\\tother costume position: 0 @ 0.\\n\\tself assert: (me overlapsAny: friend) not! !\\n\\n!MorphTest methodsFor: 'testing - etoys' stamp: 'tak 1/21/2005 11:32'!\\ntestOverlapAnyUnscriptedPlayer\\n\\t\\\"self debug: #testOverlapAnyUnscriptedPlayer\\\"\\n\\t| p1 p2 p3 |\\n\\tp1 := Morph new assuredPlayer.\\n\\tp2 := EllipseMorph new assuredPlayer.\\n\\tp3 := EllipseMorph new assuredPlayer.\\n\\tself getWorld addMorph: p1 costume;\\n\\t\\t addMorph: p2 costume;\\n\\t\\t addMorph: p3 costume.\\n\\t\\\"Same class, same position\\\"\\n\\tp1 costume position: 0 @ 0.\\n\\tp2 costume position: 500 @ 0.\\n\\tp3 costume position: 0 @ 0.\\n\\tself\\n\\t\\tassert: (p1 overlapsAny: p2).\\n\\t\\\"Same class, different position\\\"\\n\\tp1 costume position: 0 @ 0.\\n\\tp2 costume position: 1000 @ 0.\\n\\tp3 costume position: 500 @ 0.\\n\\tself assert: (p1 overlapsAny: p2) not.\\n! !\\n\\n\\n!MorphTest methodsFor: 'testing - initialization' stamp: 'md 4/16/2003 17:10'!\\ntestOpenInWorld\\n\\tself shouldnt: [morph openInWorld] raise: Error.! !\\n\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/4/2003 00:11'!\\ntestIntoWorldCollapseOutOfWorld\\n\\t| m1 m2 collapsed |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"add them to basic morph\\\"\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"open the guy\\\"\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\t\\\"collapse it\\\"\\n\\tcollapsed := \\tCollapsedMorph new beReplacementFor: morph.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\n\\t\\\"expand it\\\"\\n\\tcollapsed collapseOrExpand.\\n\\tself assert: (m1 intoWorldCount = 2).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 2).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\n\\t\\\"delete it\\\"\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 2).\\n\\tself assert: (m1 outOfWorldCount = 2).\\n\\tself assert: (m2 intoWorldCount = 2).\\n\\tself assert: (m2 outOfWorldCount = 2).\\n! !\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/4/2003 00:12'!\\ntestIntoWorldDeleteOutOfWorld\\n\\t| m1 m2 |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n\\t! !\\n\\n!MorphTest methodsFor: 'testing - into/outOf World' stamp: 'ar 8/10/2003 18:30'!\\ntestIntoWorldTransferToNewGuy\\n\\t| m1 m2 |\\n\\t\\\"Create the guys\\\"\\n\\tm1 := TestInWorldMorph new.\\n\\tm2 := TestInWorldMorph new.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tm1 addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 0).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 0).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph openInWorld.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m2.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph addMorphFront: m1.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tm2 addMorphFront: m1.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 0).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 0).\\n\\n\\tmorph delete.\\n\\tself assert: (m1 intoWorldCount = 1).\\n\\tself assert: (m1 outOfWorldCount = 1).\\n\\tself assert: (m2 intoWorldCount = 1).\\n\\tself assert: (m2 outOfWorldCount = 1).\\n! !\\nSketchMorph subclass: #MorphThumbnail\\n\\tinstanceVariableNames: 'morphRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Books'!\\n!MorphThumbnail commentStamp: '<historical>' prior: 0!\\nA morph whose appearance is a thumbnail of some other morph.!\\n\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 11/13/1998 09:53'!\\ncomputeThumbnail\\n\\t\\\"Assumption on entry:\\n The receiver's width represents the maximum width allowable.\\n The receiver's height represents the exact height desired.\\\"\\n\\n\\t| f scaleX scaleY |\\n\\tf _ morphRepresented imageForm.\\n\\tmorphRepresented fullReleaseCachedState.\\n\\tscaleY _ self height / f height. \\\"keep height invariant\\\"\\n\\tscaleX _ ((morphRepresented width * scaleY) <= self width)\\n\\t\\tifTrue:\\n\\t\\t\\t[scaleY] \\\"the usual case; same scale factor, to preserve aspect ratio\\\"\\n\\t\\tifFalse:\\n\\t\\t\\t[self width / f width].\\n\\tself form: (f magnify: f boundingBox by: (scaleX @ scaleY) smoothing: 2).\\n\\tself extent: originalForm extent! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 7/6/1998 22:08'!\\ngrabOriginal\\n\\tself primaryHand attachMorph: morphRepresented! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'ar 10/7/2000 15:38'!\\nmorphRepresented: aMorph\\n\\n\\tmorphRepresented _ aMorph.\\n\\tself computeThumbnail.\\n! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'md 10/22/2003 15:24'!\\nrevealOriginal\\n\\t((owner isKindOf: PasteUpMorph) and: [owner alwaysShowThumbnail]) \\n\\t\\tifTrue: [^Beeper beep].\\n\\tmorphRepresented owner isNil \\n\\t\\tifTrue: [^owner replaceSubmorph: self by: morphRepresented].\\n\\tBeeper beep! !\\n\\n!MorphThumbnail methodsFor: 'as yet unclassified' stamp: 'sw 8/10/1998 07:05'!\\nsmaller\\n\\tself form: (self form copy: (0@0 extent: self form extent // 2))! !\\n\\n\\n!MorphThumbnail methodsFor: 'copying' stamp: 'tk 1/8/1999 09:39'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If target and arguments fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\nsuper veryDeepFixupWith: deepCopier.\\nmorphRepresented _ deepCopier references at: morphRepresented \\n\\t\\tifAbsent: [morphRepresented].! !\\n\\n!MorphThumbnail methodsFor: 'copying' stamp: 'tk 1/8/1999 09:39'!\\nveryDeepInner: deepCopier\\n\\t\\\"Copy all of my instance variables. Some need to be not copied at all, but shared. \\tWarning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.\\\"\\n\\nsuper veryDeepInner: deepCopier.\\nmorphRepresented _ morphRepresented.\\t\\t\\\"Weakly copied\\\"! !\\n\\n\\n!MorphThumbnail methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGray! !\\n\\n!MorphThumbnail methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:51'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\t| f |\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\n\\tf _ Form extent: 60 @ 80 depth: Display depth.\\n\\tf fill: f boundingBox fillColor: color.\\n\\tself form: f! !\\n\\n\\n!MorphThumbnail methodsFor: 'menus' stamp: 'dgd 8/30/2003 21:53'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'reveal original morph' translated action: #revealOriginal.\\n\\taCustomMenu add: 'grab original morph' translated action: #grabOriginal.\\n! !\\n\\n\\n!MorphThumbnail methodsFor: 'naming' stamp: 'bf 3/31/1999 12:24'!\\ninnocuousName\\n\\t^ morphRepresented isNil\\n\\t\\tifTrue: [super innocuousName]\\n\\t\\tifFalse: [morphRepresented innocuousName]! !\\n\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'dgd 2/16/2003 21:37'!\\nisPartsDonor\\n\\t\\\"answer whether the receiver is PartsDonor\\\"\\n\\t^ self partRepresented isPartsDonor! !\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'dgd 2/16/2003 21:40'!\\nisPartsDonor: aBoolean\\n\\t\\\"change the receiver's isPartDonor property\\\"\\n\\tself partRepresented isPartsDonor: aBoolean! !\\n\\n!MorphThumbnail methodsFor: 'parts bin' stamp: 'ar 10/6/2000 22:46'!\\npartRepresented\\n\\t^self morphRepresented! !\\n\\n\\n!MorphThumbnail methodsFor: 'thumbnail' stamp: 'jm 11/17/97 17:30'!\\nmorphRepresented\\n\\n\\t^ morphRepresented\\n! !\\n\\n!MorphThumbnail methodsFor: 'thumbnail' stamp: 'bf 3/31/1999 07:54'!\\nrepresentativeNoTallerThan: maxHeight norWiderThan: maxWidth thumbnailHeight: thumbnailHeight\\n\\n\\t\\\"Return a morph representing the receiver but which is no taller than aHeight. If the receiver is already small enough, just return it, else return a MorphThumbnail companioned to the receiver, enforcing the maxWidth\\\"\\n\\n\\t(self height <= maxHeight and: [self width <= maxWidth]) ifTrue: [^ self].\\n\\n\\t^ MorphThumbnail new\\n\\t\\textent: maxWidth @ (thumbnailHeight min: self height);\\n\\t\\tmorphRepresented: morphRepresented! !\\nListItemWrapper subclass: #MorphWithSubmorphsWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!MorphWithSubmorphsWrapper commentStamp: 'ls 3/1/2004 17:32' prior: 0!\\nDisplay a morph in a SimpleHierarchicalListMorph, and arrange to recursively display the morph's submorphs. The \\\"item\\\" that is wrapped is the morph to display.!\\n\\n\\n!MorphWithSubmorphsWrapper methodsFor: 'hierarchy' stamp: 'ls 3/1/2004 17:34'!\\ncontents\\n\\t^item submorphs collect: [ :m |\\n\\t\\tself class with: m ]! !\\nController subclass: #MorphWorldController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-ST80'!\\n!MorphWorldController commentStamp: '<historical>' prior: 0!\\nI am a controller for SceneViews. I support gestures for scrolling, click-selection, and area selection of scene glyphs. (See the class comment in GestureController for more details about gestures.) I also support construction operations such as inserting new glyphs and merging glyphs to make them share a common point.\\n\\nThe mapping of gestures to actions is as follows (see GestureController comment for more about gestures):\\n\\n Click:\\n\\tclick on glyph\\t\\t\\t\\tselect glyph\\n\\tshift-click on glyph\\t\\t\\ttoggle selection of that glyph\\n\\tclick on background\\t\\t\\tclear selection\\n Double click:\\n\\tdouble-click on glyph\\t\\t\\tinspect glyph\\n\\tdouble-click on background\\t\\tselect all\\n Hold/Drag/Sweep:\\n\\thold (no movement)\\t\\t\\tyellow-button menu\\n\\tdrag (up/left movement)\\t\\tscrolling hand\\n\\tsweep (down/right movement)\\tselect glyphs in region\\n\\tshift-sweep\\t\\t\\t\\t\\ttoggle selection of glyphs in region\\n!\\n\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/26/1999 10:00'!\\ncontrolInitialize\\n\\t\\\"This window is becoming active.\\\"\\n\\n\\ttrue ifTrue: [model becomeTheActiveWorldWith: nil].\\n\\n\\tmodel canvas ifNil: [ \\\"i.e., only on first entry\\\"\\n\\t\\t\\\"In case of, eg, inspect during balloon help...\\\"\\n\\t\\tmodel submorphsDo: [:m | \\\"delete any existing balloons\\\"\\n\\t\\t\\t(m isKindOf: BalloonMorph) ifTrue: [m delete]].\\n\\n\\t\\tmodel handsDo: [:h | h initForEvents].\\n\\t\\tview displayView]. \\\"initializes the WorldMorph's canvas\\\"\\n! !\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/16/2001 22:43'!\\ncontrolLoop \\n\\t\\\"Overridden to keep control active when the hand goes out of the view\\\"\\n\\n\\t| db |\\n\\t[self viewHasCursor \\\"working in the window\\\"\\n\\t\\tor: [Sensor noButtonPressed \\\"wandering with no button pressed\\\"\\n\\t\\tor: [model primaryHand submorphs size > 0 \\\"dragging something outside\\\"]]]\\n\\t\\twhileTrue: \\\"... in other words anything but clicking outside\\\"\\n\\t\\t\\t[self controlActivity.\\n\\n\\t\\t\\t\\\"Check for reframing since we hold control here\\\"\\n\\t\\t\\tdb _ view superView displayBox.\\n\\t\\t\\tview superView controller checkForReframe.\\n\\t\\t\\tdb = view superView displayBox ifFalse:\\n\\t\\t\\t\\t[self controlInitialize \\\"reframe world if bounds changed\\\"]].\\n! !\\n\\n!MorphWorldController methodsFor: 'basic control sequence' stamp: 'di 11/16/2001 13:58'!\\ncontrolTerminate \\n\\t\\\"This window is becoming inactive; restore the normal cursor.\\\"\\n\\n\\tCursor normal show.\\n\\tActiveWorld _ ActiveHand _ ActiveEvent _ nil! !\\n\\n\\n!MorphWorldController methodsFor: 'control defaults' stamp: 'jm 2/20/98 13:37'!\\ncontrolActivity\\n\\t\\\"Do one step of the Morphic interaction loop. Called repeatedly while window is active.\\\"\\n\\n\\tmodel doOneCycle.\\n! !\\n\\n!MorphWorldController methodsFor: 'control defaults' stamp: 'jm 6/17/97 10:29'!\\nisControlActive\\n\\n\\t^ sensor redButtonPressed or: [self viewHasCursor]! !\\nView subclass: #MorphWorldView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'FullColorWhenInactive'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-ST80'!\\n!MorphWorldView commentStamp: '<historical>' prior: 0!\\nI am a view used to display a Scene. I may be scrolled by adjusting my offset. My default controller is SceneController.\\n\\nSceneViews encapsulate the notion of a changing foreground and a fixed background during interactive updates. During an interaction (such as dragging), some of the glyphs will not change location or appearance. These are part of the \\\"background\\\". All glyphs that may change (the \\\"foreground\\\" glyphs) are painted against this unchanging backdrop during the interaction.\\n\\nInstance Variables:\\n\\toffset\\t\\t\\t\\tthe current offset of this view (used for scrolling)\\n\\tenclosingRect \\t\\ta rectangle large enough to contain all the objects in the scene, plus a small border (this is a cache that must be recomputed when glyphs are moved, added, or removed from the scene)\\n\\tbackgroundForm\\t\\ta <Form> containing the fixed background\\n\\tvisibleForeground\\t\\tthe glyphs that are changing but not selected during an interaction\\n\\tselectedForeground\\tthe selected glyphs that are changing during an interaction!\\n\\n\\n!MorphWorldView methodsFor: 'as yet unclassified' stamp: 'md 2/24/2006 21:24'!\\nupdateSubWindowExtent\\n\\t\\\"If this MorphWorldView represents a single Morphic SystemWindow, then update that window to match the size of the WorldView.\\\"\\n\\n\\t| numMorphs subWindow |\\n\\tnumMorphs := model submorphs size.\\n\\t\\\"(Allow for the existence of an extra NewHandleMorph (for resizing).)\\\"\\n\\t(numMorphs = 0 or: [numMorphs > 2]) ifTrue: [^self].\\n\\tsubWindow := model submorphs detect: [:ea | ea respondsTo: #label]\\n\\t\\t\\t\\tifNone: [^self].\\n\\tsuperView label = subWindow label ifFalse: [^self].\\n\\tsubWindow position: model position + (0 @ -16).\\t\\\"adjust for WiW changes\\\"\\n\\tsubWindow extent: model extent - (0 @ -16).\\n\\tsubWindow isActive ifFalse: [subWindow activate]! !\\n\\n\\n!MorphWorldView methodsFor: 'controller access'!\\ndefaultControllerClass\\n\\n\\t^ MorphWorldController! !\\n\\n\\n!MorphWorldView methodsFor: 'deEmphasizing' stamp: 'RAA 5/24/2000 10:34'!\\ndeEmphasizeView \\n\\t\\\"This window is becoming inactive.\\\"\\n\\n\\tCursor normal show. \\\"restore the normal cursor\\\"\\n\\tmodel deEmphasizeViewMVC: self topView cacheBitsAsTwoTone.\\n! !\\n\\n\\n!MorphWorldView methodsFor: 'displaying' stamp: 'dew 11/8/1999 02:01'!\\ndisplayView\\n\\t\\\"This method is called by the system when the top view is framed or moved.\\\"\\n\\t| topView |\\n\\tmodel viewBox: self insetDisplayBox.\\n\\tself updateSubWindowExtent.\\n\\ttopView _ self topView.\\n\\t(topView == ScheduledControllers scheduledControllers first view\\n\\t\\tor: [topView cacheBitsAsTwoTone not])\\n\\t\\tifTrue: [model displayWorldSafely]\\n\\t\\tifFalse: [model displayWorldAsTwoTone]. \\\"just restoring the screen\\\"! !\\n\\n\\n!MorphWorldView methodsFor: 'updating' stamp: 'sw 9/26/97 20:56'!\\nupdate: symbol\\n\\n\\t^ symbol == #newColor\\n\\t\\tifTrue: [self topView backgroundColor: model color dominantColor; uncacheBits; display]\\n\\t\\tifFalse: [super update: symbol].\\n! !\\n\\n\\n!MorphWorldView methodsFor: 'private' stamp: 'dew 11/8/1999 02:00'!\\ncomputeInsetDisplayBox\\n\\t\\\"This overrides the same method in View. (It avoids using displayTransform: because it can return inaccurate results, causing a MorphWorldView's inset display box to creep inward when resized.)\\\"\\n\\n\\t^superView insetDisplayBox insetBy: borderWidth! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphWorldView class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'nk 7/30/2004 21:52'!\\nconvertToMVCWiWPasteUpMorph\\n\\t\\\"\\nMorphWorldView convertToMVCWiWPasteUpMorph\\n\\\"\\n\\n\\t| current w newModel topView |\\n\\tSmalltalk isMorphic ifTrue: [^self inform: 'do this in MVC'].\\n\\tcurrent := self allInstances \\n\\t\\t\\t\\tselect: [:each | each model class == PasteUpMorph].\\n\\tcurrent do: \\n\\t\\t\\t[:oldWorldView | \\n\\t\\t\\tw := MVCWiWPasteUpMorph newWorldForProject: nil.\\n\\t\\t\\tw\\n\\t\\t\\t\\tcolor: oldWorldView model color;\\n\\t\\t\\t\\taddAllMorphs: oldWorldView model submorphs.\\n\\t\\t\\tnewModel := CautiousModel new initialExtent: 300 @ 300.\\n\\t\\t\\ttopView := self fullColorWhenInactive \\n\\t\\t\\t\\t\\t\\tifTrue: [ColorSystemView new]\\n\\t\\t\\t\\t\\t\\tifFalse: [StandardSystemView new].\\n\\t\\t\\ttopView\\n\\t\\t\\t\\tmodel: newModel;\\n\\t\\t\\t\\tlabel: oldWorldView topView label;\\n\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\taddSubView: (self new model: w);\\n\\t\\t\\t\\tbackgroundColor: w color.\\n\\t\\t\\ttopView controller openNoTerminate.\\n\\t\\t\\ttopView reframeTo: (oldWorldView topView expandedFrame \\n\\t\\t\\t\\t\\t\\texpandBy: (0 @ 0 extent: 0 @ topView labelHeight)).\\n\\t\\t\\toldWorldView topView controller closeAndUnscheduleNoTerminate].\\n\\tScheduledControllers restore.\\n\\tProcessor terminateActive! !\\n\\n!MorphWorldView class methodsFor: 'instance creation'!\\nfullColorWhenInactive\\n\\n\\tFullColorWhenInactive ifNil: [FullColorWhenInactive _ true].\\n\\t^ FullColorWhenInactive\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'di 2/26/98 09:17'!\\nfullColorWhenInactive: fullColor\\n\\t\\\"MorphWorldView fullColorWhenInactive: true\\\"\\n\\t\\\"If FullColorWhenInactive is true then WorldMorphViews will created inside StandardSystemViews that cache their contents in full-color when the window is inactive. If it is false, only a half-tone gray approximation of the colors will be cached to save space.\\\"\\n\\n\\tFullColorWhenInactive _ fullColor.\\n\\n\\t\\\"Retroactively convert all extant windows\\\"\\n\\t((fullColor ifTrue: [StandardSystemView] ifFalse: [ColorSystemView])\\n\\t\\tallInstances select:\\n\\t\\t\\t[:v | v subViews notNil and: [v subViews isEmpty not and: [v firstSubView isKindOf: MorphWorldView]]])\\n\\t\\tdo: [:v | v uncacheBits.\\n\\t\\t\\tv controller toggleTwoTone]! !\\n\\n!MorphWorldView class methodsFor: 'instance creation'!\\nopenOn: aMorphWorld\\n\\t\\\"Open a view on the given WorldMorph.\\\"\\n\\n\\tself openOn: aMorphWorld label: 'A Morphic World'.! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sw 10/2/97 23:17'!\\nopenOn: aWorldMorph label: aString\\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\t^ self openOn: aWorldMorph label: aString model: (CautiousModel new initialExtent: aWorldMorph initialExtent)! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sw 9/21/1998 17:54'!\\nopenOn: aWorldMorph label: aString cautionOnClose: aBoolean\\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\t| aModel |\\n\\taModel _ aBoolean\\n\\t\\tifTrue:\\t\\t[CautiousModel new]\\n\\t\\tifFalse:\\t\\t[WorldViewModel new].\\n\\t^ self openOn: aWorldMorph label: aString model: (aModel initialExtent: aWorldMorph initialExtent)! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'jm 1/31/98 20:24'!\\nopenOn: aWorldMorph label: aString extent: aPoint\\n\\t\\\"Open a view with the given label and extent on the given WorldMorph.\\\"\\n\\n\\t^ self openOn: aWorldMorph\\n\\t\\tlabel: aString\\n\\t\\tmodel: (CautiousModel new initialExtent: aPoint)\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'nk 7/30/2004 22:37'!\\nopenOn: aWorldMorph label: aString model: aModel \\n\\t\\\"Open a view with the given label on the given WorldMorph.\\\"\\n\\n\\t| topView |\\n\\ttopView := self fullColorWhenInactive \\n\\t\\t\\t\\tifTrue: [topView := ColorSystemView new]\\n\\t\\t\\t\\tifFalse: [topView := StandardSystemView new].\\n\\ttopView\\n\\t\\tmodel: aModel;\\n\\t\\tlabel: aString;\\n\\t\\tborderWidth: 1;\\n\\t\\taddSubView: (self new model: aWorldMorph);\\n\\t\\tbackgroundColor: aWorldMorph color.\\n\\t\\\"minimumSize: aWorldMorph extent + (2@2); \\\"\\t\\\"add border width\\\"\\n\\ttopView controller open! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'di 11/26/1999 11:46'!\\nopenWorld\\n\\n\\t| w |\\n\\t(w _ MVCWiWPasteUpMorph newWorldForProject: nil).\\n\\tw bounds: (0@0 extent: 400@300).\\n\\tself openOn: w\\n\\t\\tlabel: 'A Morphic World'\\n\\t\\textent: w fullBounds extent + 2.\\n! !\\n\\n!MorphWorldView class methodsFor: 'instance creation' stamp: 'sma 6/12/2000 14:18'!\\nopenWorldWith: aMorph labelled: labelString\\n\\n\\t| w |\\n\\t(w _ MVCWiWPasteUpMorph newWorldForProject: nil) addMorph: aMorph.\\n\\tw extent: aMorph fullBounds extent.\\n\\tw startSteppingSubmorphsOf: aMorph.\\n\\tself openOn: w\\n\\t\\tlabel: labelString\\n\\t\\textent: w fullBounds extent + 2.\\n! !\\nMessageSend subclass: #MorphicAlarm\\n\\tinstanceVariableNames: 'scheduledTime numArgs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MorphicAlarm methodsFor: 'accessing' stamp: 'ar 9/11/2000 16:44'!\\nscheduledTime\\n\\t\\\"Return the time (in milliseconds) that the receiver is scheduled to be executed\\\"\\n\\t^scheduledTime! !\\n\\n!MorphicAlarm methodsFor: 'accessing' stamp: 'ar 9/11/2000 16:45'!\\nscheduledTime: msecs\\n\\t\\\"Set the time (in milliseconds) that the receiver is scheduled to be executed\\\"\\n\\tscheduledTime _ msecs! !\\n\\n\\n!MorphicAlarm methodsFor: 'evaluating' stamp: 'ar 10/22/2000 17:36'!\\nvalue: anArgument\\n\\t| nArgs |\\n\\tnumArgs ifNil:[numArgs _ selector numArgs].\\n\\tnArgs _ arguments ifNil:[0] ifNotNil:[arguments size].\\n\\tnArgs = numArgs ifTrue:[\\n\\t\\t\\\"Ignore extra argument\\\"\\n\\t\\t^self value].\\n\\t^arguments isNil\\n\\t\\tifTrue: [receiver perform: selector with: anArgument]\\n\\t\\tifFalse: [receiver perform: selector withArguments: (arguments copyWith: anArgument)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicAlarm class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicAlarm class methodsFor: 'instance creation' stamp: 'ar 9/11/2000 16:44'!\\nscheduledAt: scheduledTime receiver: aTarget selector: aSelector arguments: argArray\\n\\t^(self receiver: aTarget selector: aSelector arguments: argArray)\\n\\t\\tscheduledTime: scheduledTime.! !\\nObject subclass: #MorphicEvent\\n\\tinstanceVariableNames: 'timeStamp source'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n!MorphicEvent commentStamp: '<historical>' prior: 0!\\nThis class represents the base for all events.\\n\\nInstance variables:\\n\\tstamp\\t<Integer>\\tThe millisecond clock time stamp (based on Time millisecondClock)\\n\\tsource\\t<Hand | nil>\\tIf non-nil the hand that generated the event.!\\n\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 21:28'!\\ncursorPoint\\n\\t\\\"Backward compatibility. Use #position instead\\\"\\n\\t^ self position! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 16:48'!\\nhand\\n\\t\\\"Return the source that generated the event\\\"\\n\\t^source! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'wiz 12/8/2004 23:13'!\\nposition\\n\\t\\\"Since cursorPoint is defined and refers to position it should be defined\\n\\there as well\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 15:29'!\\ntimeStamp\\n\\t\\\"Return the millisecond clock value at which the event was generated\\\"\\n\\t^timeStamp ifNil:[timeStamp _ Time millisecondClockValue]! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 15:34'!\\ntype\\n\\t\\\"Return a symbol indicating the type this event.\\\"\\n\\t^self subclassResponsibility! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 01:19'!\\nwasHandled\\n\\t\\\"Return true if this event was handled. May be ignored for some types of events.\\\"\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'accessing' stamp: 'ar 10/10/2000 01:20'!\\nwasHandled: aBool\\n\\t\\\"Determine if this event was handled. May be ignored for some types of events.\\\"! !\\n\\n\\n!MorphicEvent methodsFor: 'comparing' stamp: 'ar 9/13/2000 15:36'!\\n= anEvent\\n\\tanEvent isMorphicEvent ifFalse:[^false].\\n\\t^self type = anEvent type! !\\n\\n!MorphicEvent methodsFor: 'comparing' stamp: 'ar 9/13/2000 15:36'!\\nhash\\n\\t^self type hash! !\\n\\n\\n!MorphicEvent methodsFor: 'dispatching' stamp: 'ar 9/15/2000 21:12'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\t^anObject handleUnknownEvent: self! !\\n\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/10/2000 01:18'!\\ncopyHandlerState: anEvent\\n\\t\\\"Copy the handler state from anEvent. Used for quickly transferring handler information between transformed events.\\\"\\n! !\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/10/2000 01:18'!\\nresetHandlerFields\\n\\t\\\"Reset anything that is used to cross-communicate between two eventual handlers during event dispatch\\\"! !\\n\\n!MorphicEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:21'!\\ntype: eventType readFrom: aStream\\n\\t\\\"Read a MorphicEvent from the given stream.\\\"\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 16:05'!\\nconvertOctober2000: varDict using: smartRefStrm\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\t\\\"These are going away #('type' 'cursorPoint' 'buttons' 'keyValue' 'sourceHand'). Possibly store their info in another variable?\\\"\\n\\t| type cursorPoint buttons keyValue sourceHand |\\n\\ttype _ varDict at: 'type'.\\n\\tcursorPoint _ varDict at: 'cursorPoint'.\\n\\tbuttons _ varDict at: 'buttons'.\\n\\tkeyValue _ varDict at: 'keyValue'.\\n\\tsourceHand _ varDict at: 'sourceHand'.\\n\\ttype == #mouseMove ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: cursorPoint\\n\\t\\t\\tendPoint: cursorPoint\\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: sourceHand \\n\\t\\t\\tstamp: nil].\\n\\t(type == #mouseDown) | (type == #mouseUp) ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: cursorPoint\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: sourceHand\\n\\t\\t\\t\\tstamp: nil].\\n\\t(type == #keystroke) | (type == #keyDown) | (type == #keyUp) ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: cursorPoint\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: sourceHand\\n\\t\\t\\tstamp: nil].\\n\\t\\\"All others will be handled there\\\"\\n\\t^MorphicUnknownEvent new! !\\n\\n\\n!MorphicEvent methodsFor: 'objects from disk' stamp: 'RAA 12/21/2000 11:35'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\t| answer |\\n\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\tvarDict at: 'cursorPoint' ifPresent: [ :x | \\n\\t\\tanswer _ self convertOctober2000: varDict using: smartRefStrm.\\n\\t\\tvarDict removeKey: 'cursorPoint'.\\t\\\"avoid doing this again\\\"\\n\\t\\t^answer\\n\\t].\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/22/2000 10:36'!\\nisDraggingEvent\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:17'!\\nisDropEvent\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:19'!\\nisKeyboard\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 10/10/2000 21:27'!\\nisKeystroke\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:37'!\\nisMorphicEvent\\n\\t^true! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:19'!\\nisMouse\\n\\t^false! !\\n\\n!MorphicEvent methodsFor: 'testing' stamp: 'ar 9/14/2000 18:21'!\\nisMouseOver\\n\\t^self type == #mouseOver! !\\n\\n\\n!MorphicEvent methodsFor: 'transforming' stamp: 'ar 9/13/2000 15:47'!\\ntransformedBy: aMorphicTransform\\n\\t\\\"Return the receiver transformed by the given transform into a local coordinate system.\\\"\\n! !\\n\\n\\n!MorphicEvent methodsFor: 'private' stamp: 'ar 10/25/2000 21:26'!\\nsetHand: aHand\\n\\tsource _ aHand! !\\n\\n!MorphicEvent methodsFor: 'private' stamp: 'ar 10/25/2000 20:53'!\\nsetTimeStamp: stamp\\n\\ttimeStamp _ stamp.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 00:44'!\\nconvertObsolete: anEvent\\n\\t\\\"ar 10/25/2000: This method is used to convert OLD MorphicEvents into new ones.\\\"\\n\\t| type cursorPoint buttons keyValue sourceHand |\\n\\ttype _ anEvent type.\\n\\tcursorPoint _ anEvent cursorPoint.\\n\\tbuttons _ anEvent buttons.\\n\\tkeyValue _ anEvent keyValue.\\n\\tsourceHand _ anEvent hand.\\n\\ttype == #mouseMove ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: cursorPoint\\n\\t\\t\\tendPoint: cursorPoint\\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: sourceHand \\n\\t\\t\\tstamp: nil].\\n\\t(type == #mouseDown) | (type == #mouseUp) ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: cursorPoint\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: sourceHand\\n\\t\\t\\t\\tstamp: nil].\\n\\t(type == #keystroke) | (type == #keyDown) | (type == #keyUp) ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: cursorPoint\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: sourceHand\\n\\t\\t\\tstamp: nil].\\n\\t^nil! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 00:49'!\\nreadFrom: aStream\\n\\t\\\"Read a MorphicEvent from the given stream.\\\"\\n\\t| typeString c |\\n\\ttypeString _ String streamContents:\\n\\t\\t[:s | [(c _ aStream next) isLetter] whileTrue: [s nextPut: c]].\\n\\ttypeString = 'mouseMove' ifTrue:[^MouseMoveEvent type: #mouseMove readFrom: aStream].\\n\\ttypeString = 'mouseDown' ifTrue:[^MouseButtonEvent type: #mouseDown readFrom: aStream].\\n\\ttypeString = 'mouseUp' ifTrue:[^MouseButtonEvent type: #mouseUp readFrom: aStream].\\n\\n\\ttypeString = 'keystroke' ifTrue:[^KeyboardEvent type: #keystroke readFrom: aStream].\\n\\ttypeString = 'keyDown' ifTrue:[^KeyboardEvent type: #keyDown readFrom: aStream].\\n\\ttypeString = 'keyUp' ifTrue:[^KeyboardEvent type: #keyUp readFrom: aStream].\\n\\n\\ttypeString = 'mouseOver' ifTrue:[^MouseEvent type: #mouseOver readFrom: aStream].\\n\\ttypeString = 'mouseEnter' ifTrue:[^MouseEvent type: #mouseEnter readFrom: aStream].\\n\\ttypeString = 'mouseLeave' ifTrue:[^MouseEvent type: #mouseLeave readFrom: aStream].\\n\\n\\ttypeString = 'unknown' ifTrue:[^MorphicUnknownEvent type: #unknown readFrom: aStream].\\n\\n\\t^nil\\n! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/25/2000 21:58'!\\nreadFromObsolete: aStream\\n\\t\\\"Read one of those old and now obsolete events from the stream\\\"\\n\\t| type x y buttons keyValue typeString c |\\n\\ttypeString _ String streamContents:\\n\\t\\t[:s | [(c _ aStream next) isLetter] whileTrue: [s nextPut: c]].\\n\\ttypeString = 'mouseMove'\\n\\t\\tifTrue: [type _ #mouseMove \\\"fast treatment of common case\\\"]\\n\\t\\tifFalse: [type _ typeString asSymbol].\\n\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\n\\tbuttons _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\n\\tkeyValue _ Integer readFrom: aStream.\\n\\n\\ttypeString = 'mouseMove' ifTrue:[\\n\\t\\t^MouseMoveEvent new\\n\\t\\t\\tsetType: #mouseMove \\n\\t\\t\\tstartPoint: x@y \\n\\t\\t\\tendPoint: x@y \\n\\t\\t\\ttrail: #() \\n\\t\\t\\tbuttons: buttons \\n\\t\\t\\thand: nil \\n\\t\\t\\tstamp: nil].\\n\\t(typeString = 'mouseDown') | (typeString = 'mouseUp') ifTrue:[\\n\\t\\t\\t^MouseButtonEvent new\\n\\t\\t\\t\\tsetType: type\\n\\t\\t\\t\\tposition: x@y\\n\\t\\t\\t\\twhich: 0\\n\\t\\t\\t\\tbuttons: buttons\\n\\t\\t\\t\\thand: nil\\n\\t\\t\\t\\tstamp: nil].\\n\\t(typeString = 'keystroke') | (typeString = 'keyDown') | (typeString = 'keyUp') ifTrue:[\\n\\t\\t^KeyboardEvent new\\n\\t\\t\\tsetType: type\\n\\t\\t\\tbuttons: buttons\\n\\t\\t\\tposition: x@y\\n\\t\\t\\tkeyValue: keyValue\\n\\t\\t\\thand: nil\\n\\t\\t\\tstamp: nil].\\n\\n\\t^nil! !\\n\\n!MorphicEvent class methodsFor: 'instance creation' stamp: 'ar 10/24/2000 16:32'!\\ntype: eventType readFrom: aStream\\n\\t^self new type: eventType readFrom: aStream! !\\n\\n\\n!MorphicEvent class methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:32'!\\nfromStringArray: array\\n\\t\\\"decode an event that was encoded with encodedAsStringArray\\\"\\n\\t| type |\\n\\ttype := (array at: 1).\\n\\t(type = 'mouseMove')\\n\\t\\tifTrue:[^MouseMoveEvent new decodeFromStringArray: array].\\n\\t(type = 'mouseDown' or:[type = 'mouseUp']) \\n\\t\\tifTrue:[^MouseButtonEvent new decodeFromStringArray: array].\\n\\t(type = 'keystroke' or:[type = 'keyDown' or:[type = 'keyUp']]) \\n\\t\\tifTrue:[^KeyboardEvent new decodeFromStringArray: array].\\n\\t^nil! !\\nObject subclass: #MorphicEventDecoder\\n\\tinstanceVariableNames: 'connection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!MorphicEventDecoder commentStamp: '<historical>' prior: 0!\\ndecode messages sent via a MorphicEventEncoder.!\\n\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'RAA 11/8/2000 15:15'!\\napply: aStringArray to: aHand\\n\\t\\\"decode aStringArray, and apply the encoded command to aHand\\\"\\n\\n\\taStringArray first = 'event' ifTrue: [\\n\\t\\t^self applyEventMessage: aStringArray to: aHand\\n\\t].\\n\\taStringArray first = 'viewExtent' ifTrue: [\\n\\t\\t^self applyViewExtentMessage: aStringArray to: aHand\\n\\t].\\n\\taStringArray first = 'beginBuffering' ifTrue: [\\n\\t\\t^aHand convertRemoteClientToBuffered\\n\\t].\\n\\n\\t^self error: 'unknown message type: ', aStringArray first! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ar 10/26/2000 01:55'!\\napplyEventMessage: aStringArray to: aHand\\n\\t| event |\\n\\tevent := MorphicEvent fromStringArray: (aStringArray copyFrom: 2 to: aStringArray size).\\n\\tevent ifNotNil:[aHand queueEvent: event].! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 3/25/2000 16:56'!\\napplyMessagesTo: aHand\\n\\t| msg |\\n\\t\\\"apply all queued events to the given hand\\\"\\n\\t\\\"currently, there is no way to extract the rawmessages. This is simply because I didn't feel like implementing individual classes for each message -lex\\\"\\n\\t[ msg := connection nextOrNil. msg notNil ] whileTrue: [\\n\\t\\tself apply: msg to: aHand ].\\n! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 4/11/2000 19:00'!\\napplyViewExtentMessage: aStringArray to: aHand\\n\\t| newViewExtent |\\n\\tnewViewExtent := CanvasDecoder decodePoint: aStringArray second.\\n\\n\\taHand setViewExtent: newViewExtent! !\\n\\n!MorphicEventDecoder methodsFor: 'handling messages' stamp: 'ls 3/24/2000 22:54'!\\nprocessIO\\n\\tconnection processIO! !\\n\\n\\n!MorphicEventDecoder methodsFor: 'initialization' stamp: 'ls 3/24/2000 21:42'!\\nconnection: aConnection\\n\\tconnection := aConnection! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEventDecoder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEventDecoder class methodsFor: 'instance creation' stamp: 'ls 3/24/2000 21:43'!\\non: aStringArray\\n\\t^self basicNew connection: aStringArray! !\\nObject subclass: #MorphicEventDispatcher\\n\\tinstanceVariableNames: 'lastType lastDispatch'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n!MorphicEventDispatcher commentStamp: '<historical>' prior: 0!\\nThe class represents a strategy for dispatching events to some immediate child of a morph. It is used by morphs to delegate the somewhat complex action of dispatching events accurately. !\\n\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 01:20'!\\ndispatchDefault: anEvent with: aMorph\\n\\t\\\"Dispatch the given event. The event will be passed to the front-most visible submorph that contains the position wrt. to the event.\\\"\\n\\t| localEvt index child morphs inside |\\n\\t\\\"See if we're fully outside aMorphs bounds\\\"\\n\\t(aMorph fullBounds containsPoint: anEvent position) ifFalse:[^#rejected]. \\\"outside\\\"\\n\\t\\\"Traverse children\\\"\\n\\tindex _ 1.\\n\\tmorphs _ aMorph submorphs.\\n\\tinside _ false.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\t\\\"Not rejected. The event was in some submorph of the receiver\\\"\\n\\t\\t\\tinside _ true.\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[anEvent copyHandlerState: localEvt].\\n\\t\\t\\tindex _ morphs size. \\\"break\\\"\\n\\t\\t].\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\t\\\"Check for being inside the receiver\\\"\\n\\tinside ifFalse:[inside _ aMorph containsPoint: anEvent position event: anEvent].\\n\\tinside ifTrue:[^aMorph handleEvent: anEvent].\\n\\t^#rejected\\n! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:13'!\\ndispatchDropEvent: anEvent with: aMorph\\n\\t\\\"Find the appropriate receiver for the event and let it handle it. The dispatch is similar to the default dispatch with one difference: Morphs are given the chance to reject an entire drop operation. If the operation is rejected, no drop will be executed.\\\"\\n\\t| inside index morphs child localEvt |\\n\\t\\\"Try to get out quickly\\\"\\n\\t(aMorph fullBounds containsPoint: anEvent cursorPoint)\\n\\t\\tifFalse:[^#rejected].\\n\\t\\\"Give aMorph a chance to repel the dropping morph\\\"\\n\\taMorph rejectDropEvent: anEvent.\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\n\\t\\\"Go looking if any of our submorphs wants it\\\"\\n\\tindex _ 1.\\n\\tinside _ false.\\n\\tmorphs _ aMorph submorphs.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[^anEvent wasHandled: true]. \\\"done\\\"\\n\\t\\t\\tinside _ true.\\n\\t\\t\\tindex _ morphs size]. \\\"break\\\"\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\tinside ifFalse:[inside _ aMorph containsPoint: anEvent cursorPoint event: anEvent].\\n\\tinside ifTrue:[^aMorph handleEvent: anEvent].\\n\\t^#rejected! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 1/10/2001 21:43'!\\ndispatchEvent: anEvent with: aMorph\\n\\t\\\"Dispatch the given event for a morph that has chosen the receiver to dispatch its events. The method implements a shortcut for repeated dispatches of events using the same dispatcher.\\\"\\n\\tanEvent type == lastType ifTrue:[^self perform: lastDispatch with: anEvent with: aMorph].\\n\\t\\\"Otherwise classify\\\"\\n\\tlastType _ anEvent type.\\n\\tanEvent isMouse ifTrue:[\\n\\t\\tanEvent isMouseDown ifTrue:[\\n\\t\\t\\tlastDispatch _ #dispatchMouseDown:with:.\\n\\t\\t\\t^self dispatchMouseDown: anEvent with: aMorph]].\\n\\tanEvent type == #dropEvent ifTrue:[\\n\\t\\tlastDispatch _ #dispatchDropEvent:with:.\\n\\t\\t^self dispatchDropEvent: anEvent with: aMorph].\\n\\tlastDispatch _ #dispatchDefault:with:.\\n\\t^self dispatchDefault: anEvent with: aMorph! !\\n\\n!MorphicEventDispatcher methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:14'!\\ndispatchMouseDown: anEvent with: aMorph\\n\\t\\\"Find the appropriate receiver for the event and let it handle it. Default rules:\\n\\t* The top-most chain of visible, unlocked morphs containing the event position will get a chance to handle the event.\\n\\t* When travelling down the hierarchy a prospective handler for the event is installed. This prospective handler can be used by submorphs wishing to handle the mouse down for negotiating who the receiver is.\\n\\t* When travelling up, the prospective handler is always executed. The handler needs to check if the event was handled before as well as checking if somebody else's handler has been installed.\\n\\t* If another handler has been installed but the event was not handled it means that somebody up in the hierarchy wants to handle the event.\\n\\\"\\n\\t| globalPt localEvt index child morphs handler inside lastHandler |\\n\\t\\\"Try to get out quickly\\\"\\n\\tglobalPt _ anEvent cursorPoint.\\n\\t(aMorph fullBounds containsPoint: globalPt) ifFalse:[^#rejected].\\n\\n\\t\\\"Install the prospective handler for the receiver\\\"\\n\\tlastHandler _ anEvent handler. \\\"in case the mouse wasn't even in the receiver\\\"\\n\\thandler _ aMorph handlerForMouseDown: anEvent.\\n\\thandler ifNotNil:[anEvent handler: handler].\\n\\n\\t\\\"Now give our submorphs a chance to handle the event\\\"\\n\\tindex _ 1.\\n\\tmorphs _ aMorph submorphs.\\n\\t[index <= morphs size] whileTrue:[\\n\\t\\tchild _ morphs at: index.\\n\\t\\tlocalEvt _ anEvent transformedBy: (child transformedFrom: aMorph).\\n\\t\\t(child processEvent: localEvt using: self) == #rejected ifFalse:[\\n\\t\\t\\t\\\"Some child did contain the point so we're part of the top-most chain.\\\"\\n\\t\\t\\tinside _ false.\\n\\t\\t\\tlocalEvt wasHandled ifTrue:[anEvent copyHandlerState: localEvt].\\n\\t\\t\\tindex _ morphs size].\\n\\t\\tindex _ index + 1.\\n\\t].\\n\\n\\t(inside == false or:[aMorph containsPoint: anEvent cursorPoint event: anEvent]) ifTrue:[\\n\\t\\t\\\"Receiver is in the top-most unlocked, visible chain.\\\"\\n\\t\\thandler ifNotNil:[handler handleEvent: anEvent].\\n\\t\\t\\\"Note: Re-installing the handler is not really necessary but good style.\\\"\\n\\t\\tanEvent handler: lastHandler.\\n\\t\\t^self\\n\\t].\\n\\t\\\"Mouse was not on receiver nor any of its children\\\"\\n\\tanEvent handler: lastHandler.\\n\\t^#rejected! !\\nObject subclass: #MorphicEventEncoder\\n\\tinstanceVariableNames: 'connection lastEventSent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!MorphicEventEncoder commentStamp: '<historical>' prior: 0!\\nA filter which translates MorphEvent's into StringArray's.!\\n\\n\\n!MorphicEventEncoder methodsFor: 'initialization' stamp: 'ls 3/24/2000 21:38'!\\nconnection: aConnection\\n\\tconnection := aConnection! !\\n\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/24/2000 21:42'!\\nflush\\n\\tconnection flush! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/24/2000 21:38'!\\nprocessIO\\n\\tconnection processIO! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'RAA 12/13/2000 08:19'!\\nrequestBufferedConnection\\n\\t\\\"request the opposite side to send complete screen updates rather than discrete drawing commands\\\"\\n\\t\\n\\tconnection nextPut: { 'beginBuffering' }\\n! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 3/26/2000 01:08'!\\nsendEvent: anEvent\\n\\t(anEvent isMouseMove and: [ anEvent = lastEventSent ]) ifTrue: [\\n\\t\\t\\\"save on network traffic--don't send duplicate mouse moves\\\"\\n\\t\\t^self ].\\n\\tlastEventSent := anEvent.\\n\\tconnection nextPut: #('event'), anEvent encodedAsStringArray! !\\n\\n!MorphicEventEncoder methodsFor: 'network I/O' stamp: 'ls 4/11/2000 18:59'!\\nsendViewExtent: newExtent\\n\\t\\\"inform the opposite side that our view extent has changed\\\"\\n\\t\\n\\tconnection nextPut: { 'viewExtent'. CanvasEncoder encodePoint: newExtent }\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicEventEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicEventEncoder class methodsFor: 'instance creation' stamp: 'ls 3/24/2000 21:43'!\\non: aStringArray\\n\\t^self basicNew connection: aStringArray! !\\nBorderedMorph subclass: #MorphicModel\\n\\tinstanceVariableNames: 'model slotName open'\\n\\tclassVariableNames: 'TimeOfError'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MorphicModel commentStamp: '<historical>' prior: 0!\\nMorphicModels are used to represent structures with state and behavior as well as graphical structure. A morphicModel is usually the root of a morphic tree depicting its appearance. The tree is constructed concretely by adding its consituent morphs to a world.\\n\\nWhen a part is named in a world, it is given a new slot in the model. When a part is sensitized, it is named, and a set of mouse-driven methods is also generated in the model. These may be edited to induce particular behavior. When a variable is added through the morphic world, it is given a slot in the model, along with a set of access methods.\\n\\nIn addition for public variables (and this is the default for now), methods are generated and called in any outer model in which this model gets embedded, thus propagating variable changes outward.!\\n\\n\\n!MorphicModel methodsFor: 'access'!\\nmodel \\n\\t^ model! !\\n\\n!MorphicModel methodsFor: 'access'!\\nslotName\\n\\t^ slotName! !\\n\\n!MorphicModel methodsFor: 'access' stamp: '6/7/97 10:40 di'!\\nwantsSlot\\n\\t\\\"Override this default for models that want to be installed in theri model\\\"\\n\\t^ false! !\\n\\n\\n!MorphicModel methodsFor: 'accessing' stamp: 'sw 10/23/1999 22:36'!\\nmodelOrNil\\n\\t^ model! !\\n\\n\\n!MorphicModel methodsFor: 'caching' stamp: 'sw 3/6/2001 11:22'!\\nreleaseCachedState\\n\\t\\\"Release cached state of the receiver\\\"\\n\\n\\t(model ~~ self and: [model respondsTo: #releaseCachedState]) ifTrue:\\n\\t\\t[model releaseCachedState].\\n\\tsuper releaseCachedState! !\\n\\n\\n!MorphicModel methodsFor: 'classification' stamp: 'ar 10/5/2000 16:40'!\\nisMorphicModel\\n\\t^true! !\\n\\n\\n!MorphicModel methodsFor: 'compilation'!\\naddPartNameLike: className withValue: aMorph\\n\\t| otherNames i default partName stem |\\n\\tstem _ className first asLowercase asString , className allButFirst.\\n\\totherNames _ self class allInstVarNames.\\n\\ti _ 1.\\n\\t[otherNames includes: (default _ stem, i printString)]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\tpartName _ FillInTheBlank\\n\\t\\trequest: 'Please give this part a name'\\n\\t\\tinitialAnswer: default.\\n\\t(otherNames includes: partName)\\n\\t\\tifTrue: [self inform: 'Sorry, that name is already used'. ^ nil].\\n\\tself class addInstVarName: partName.\\n\\tself instVarAt: self class instSize put: aMorph. \\\"Assumes added as last field\\\"\\n\\t^ partName! !\\n\\n!MorphicModel methodsFor: 'compilation' stamp: 'tk 4/18/97'!\\ncompileAccessForSlot: aSlotName\\n\\t\\\"Write the method to get at this inst var. \\\"\\n\\t\\\"Instead call the right thing to make this happen?\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: (String new: 2000).\\n\\ts nextPutAll: aSlotName; cr; tab; nextPutAll: '^', aSlotName.\\n\\tself class\\n\\t\\tcompile: s contents\\n\\t\\tclassified: 'public access'\\n\\t\\tnotifying: nil.\\n! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\ncompilePropagationMethods\\n\\t| varName |\\n\\t(self class organization listAtCategoryNamed: 'private - propagation' asSymbol)\\n\\t\\tdo: [:sel | varName _ sel allButLast.\\n\\t\\t\\tmodel class compilePropagationForVarName: varName slotName: slotName]! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nnameFor: aMorph\\n\\t\\\"Return the name of the slot containing the given morph or nil if that morph has not been named.\\\"\\n\\n\\t| allNames start |\\n\\tallNames _ self class allInstVarNames.\\n\\tstart _ MorphicModel allInstVarNames size + 1.\\n\\tstart to: allNames size do: [:i |\\n\\t\\t(self instVarAt: i) == aMorph ifTrue: [^ allNames at: i]].\\n\\t^ nil\\n! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\npropagate: value as: partStoreSelector\\n\\tmodel ifNil: [^ self].\\n\\\"\\n\\tLater we can cache this for more speed as follows...\\n\\t(partName == cachedPartName and: [slotName == cachedSlotName])\\n\\t\\tifFalse: [cachedPartName _ partName.\\n\\t\\t\\t\\tcachedSlotName _ slotName.\\n\\t\\t\\t\\tcachedStoreSelector _ (slotName , partStoreSelector) asSymbol].\\n\\tmodel perform: cachedStoreSelector with: value].\\n\\\"\\n\\tmodel perform: (self slotSelectorFor: partStoreSelector) with: value! !\\n\\n!MorphicModel methodsFor: 'compilation' stamp: 'tk 10/31/97 12:33'!\\nremoveAll\\n\\t\\\"Clear out all script methods and subpart instance variables in me. Start over.\\\"\\n\\t\\\"self removeAll\\\"\\n\\t\\\"MorphicModel2 removeAll\\\"\\n\\nself class == MorphicModel ifTrue: [^ self].\\t\\\"Must be a subclass!!\\\"\\nself class removeCategory: 'scripts'.\\nself class instVarNames do: [:nn | self class removeInstVarName: nn].! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nslotSelectorFor: selectorBody\\n\\t| selector |\\n\\tmodel ifNil: [^ nil].\\n\\t\\\"Make up selector from slotname if any\\\"\\n\\tselector _ (slotName ifNil: [selectorBody]\\n\\t\\t\\t\\t\\tifNotNil: [slotName , selectorBody]) asSymbol.\\n\\t(model canUnderstand: selector) ifFalse:\\n\\t\\t[self halt: 'Compiling a null response for ' , model class name , '>>' , selector].\\n\\t^ selector! !\\n\\n!MorphicModel methodsFor: 'compilation'!\\nuse: cachedSelector orMakeModelSelectorFor: selectorBody in: selectorBlock\\n\\t| selector |\\n\\tmodel ifNil: [^ nil].\\n\\tcachedSelector ifNil:\\n\\t\\t\\t[\\\"Make up selector from slotname if any\\\"\\n\\t\\t\\tselector _ (slotName ifNil: [selectorBody]\\n\\t\\t\\t\\t\\t\\t\\t\\tifNotNil: [slotName , selectorBody]) asSymbol.\\n\\t\\t\\t(model class canUnderstand: selector) ifFalse:\\n\\t\\t\\t\\t[(self confirm: 'Shall I compile a null response for'\\n\\t\\t\\t\\t\\t\\t\\t, Character cr asString\\n\\t\\t\\t\\t\\t\\t\\t, model class name , '>>' , selector)\\n\\t\\t\\t\\t\\t\\tifFalse: [self halt].\\n\\t\\t\\t\\tmodel class compile: (String streamContents:\\n\\t\\t\\t\\t\\t\\t\\t\\t[:s | selector keywords doWithIndex:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:k :i | s nextPutAll: k , ' arg' , i printString].\\n\\t\\t\\t\\t\\t\\t\\t\\ts cr; nextPutAll: '\\\"Automatically generated null response.\\\"'.\\n\\t\\t\\t\\t\\t\\t\\t\\ts cr; nextPutAll: '\\\"Add code below for appropriate behavior...\\\"'.])\\n\\t\\t\\t\\t\\t\\t\\tclassified: 'input events'\\n\\t\\t\\t\\t\\t\\t\\tnotifying: nil]]\\n\\t\\tifNotNil:\\n\\t\\t\\t[selector _ cachedSelector].\\n\\t^ selectorBlock value: selector! !\\n\\n\\n!MorphicModel methodsFor: 'debug and other' stamp: '6/7/97 10:43 di'!\\ninstallModelIn: aWorld\\n\\n\\tself wantsSlot ifFalse: [^ self]. \\\"No real need to install\\\"\\n\\tslotName _ aWorld model addPartNameLike: self class name withValue: self.\\n\\tslotName ifNil: [^ self]. \\\"user chose bad slot name\\\"\\n\\tself model: aWorld model slotName: slotName.\\n\\tself compilePropagationMethods.\\n\\taWorld model compileAccessForSlot: slotName.\\n! !\\n\\n\\n!MorphicModel methodsFor: 'drag and drop' stamp: 'di 6/22/97 23:17'!\\nallowSubmorphExtraction\\n\\t^ self isOpen\\n! !\\n\\n!MorphicModel methodsFor: 'drag and drop' stamp: 'di 6/22/97 23:16'!\\nisOpen\\n\\t\\\"Support drag/drop and other edits.\\\"\\n\\t^ open! !\\n\\n\\n!MorphicModel methodsFor: 'geometry'!\\nnewBounds: newBounds\\n\\tself bounds: newBounds! !\\n\\n!MorphicModel methodsFor: 'geometry'!\\nrecomputeBounds\\n\\n\\t| bnds |\\n\\tbnds _ submorphs first bounds.\\n\\tbounds _ bnds origin corner: bnds corner. \\\"copy it!!\\\"\\n\\tfullBounds _ nil.\\n\\tbounds _ self fullBounds.\\n! !\\n\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color yellow! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:07'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 200 @ 100! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color transparent! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'tk 4/15/97'!\\nduplicate: newGuy from: oldGuy\\n\\t\\\"oldGuy has just been duplicated and will stay in this world. Make sure all the MorphicModel requirements are carried out for the copy. Ask user to rename it. \\\"\\n\\n\\tnewGuy installModelIn: oldGuy world.\\n\\tnewGuy copySlotMethodsFrom: oldGuy slotName.! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:47'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\topen _ false! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'jm\\n 8/20/1998 09:08'!\\nmodel: anObject\\n\\t\\\"Set my model and make me me a dependent of the given object.\\\"\\n\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel _ anObject.\\n! !\\n\\n!MorphicModel methodsFor: 'initialization' stamp: 'di 6/21/97 13:25'!\\nmodel: thang slotName: nameOfThisPart\\n\\tmodel _ thang.\\n\\tslotName _ nameOfThisPart.\\n\\topen _ false.! !\\n\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:53'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\tmodel ifNotNil: [model addModelMenuItemsTo: aCustomMenu forMorph: self hand: aHandMorph].\\n\\tself isOpen ifTrue: [aCustomMenu add: 'close editing' translated action: #closeToEdits]\\n\\t\\t\\tifFalse: [aCustomMenu add: 'open editing' translated action: #openToEdits].\\n! !\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'di 6/20/97 15:36'!\\ncloseToEdits\\n\\t\\\"Disable this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\topen _ false\\n! !\\n\\n!MorphicModel methodsFor: 'menu' stamp: 'di 6/20/97 15:36'!\\nopenToEdits\\n\\t\\\"Enable this morph's ability to add and remove morphs via drag-n-drop.\\\"\\n\\n\\topen _ true\\n! !\\n\\n\\n!MorphicModel methodsFor: 'naming' stamp: 'dgd 2/21/2003 23:00'!\\nchoosePartName\\n\\t\\\"When I am renamed, get a slot, make default methods, move any existing methods. ** Does not clean up old inst var name or methods** \\\"\\n\\n\\t| old |\\n\\told := slotName.\\n\\tsuper choosePartName.\\n\\tslotName ifNil: [^self].\\t\\\"user chose bad slot name\\\"\\n\\tself model: self world model slotName: slotName.\\n\\told isNil\\n\\t\\tifTrue: [self compilePropagationMethods]\\n\\t\\tifFalse: [self copySlotMethodsFrom: old]\\n\\t\\\"old ones not erased!!\\\"! !\\n\\n\\n!MorphicModel methodsFor: 'printing'!\\ninitString\\n\\n\\t^ String streamContents:\\n\\t\\t[:s | s nextPutAll: self class name;\\n\\t\\t\\tnextPutAll: ' newBounds: (';\\n\\t\\t\\tprint: bounds;\\n\\t\\t\\tnextPutAll: ') model: self slotName: ';\\n\\t\\t\\tprint: slotName]! !\\n\\n\\n!MorphicModel methodsFor: 'submorphs-accessing' stamp: 'dgd 2/22/2003 18:51'!\\nallKnownNames\\n\\t\\\"Return a list of all known names based on the scope of the receiver. If the receiver is a member of a uniclass, incorporate the original 1997 logic that queries the known names of the values of all the instance variables.\\\"\\n\\n\\t| superNames |\\n\\tsuperNames := super allKnownNames.\\t\\\"gather them from submorph tree\\\"\\n\\t^self belongsToUniClass \\n\\t\\tifTrue: \\n\\t\\t\\t[superNames , (self instanceVariableValues \\n\\t\\t\\t\\t\\t\\tselect: [:e | e notNil and: [e knownName notNil]]\\n\\t\\t\\t\\t\\t\\tthenCollect: [:e | e knownName])]\\n\\t\\tifFalse: [superNames]! !\\n\\n\\n!MorphicModel methodsFor: 'submorphs-add/remove' stamp: 'gm 2/22/2003 12:51'!\\ndelete\\n\\t(model isMorphicModel) ifFalse: [^super delete].\\n\\tslotName ifNotNil: \\n\\t\\t\\t[(PopUpMenu confirm: 'Shall I remove the slot ' , slotName \\n\\t\\t\\t\\t\\t\\t, '\\nalong with all associated methods?') \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[(model class selectors select: [:s | s beginsWith: slotName]) \\n\\t\\t\\t\\t\\t\\tdo: [:s | model class removeSelector: s].\\n\\t\\t\\t\\t\\t(model class instVarNames includes: slotName) \\n\\t\\t\\t\\t\\t\\tifTrue: [model class removeInstVarName: slotName]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(PopUpMenu \\n\\t\\t\\t\\t\\t\\tconfirm: '...but should I at least dismiss this morph?\\n[choose no to leave everything unchanged]') \\n\\t\\t\\t\\t\\t\\t\\tifFalse: [^self]]].\\n\\tsuper delete! !\\n\\n\\n!MorphicModel methodsFor: '*MorphicExtras-compilation'!\\ncompileInitMethods\\n\\t| s nodeDict varNames |\\n\\tnodeDict _ IdentityDictionary new.\\n\\ts _ WriteStream on: (String new: 2000).\\n\\tvarNames _ self class allInstVarNames.\\n\\ts nextPutAll: 'initMorph'.\\n\\t3 to: self class instSize do:\\n\\t\\t[:i | (self instVarAt: i) isMorph ifTrue:\\n\\t\\t\\t[s cr; tab; nextPutAll: (varNames at: i) , ' _ '.\\n\\t\\t\\ts nextPutAll: (self instVarAt: i) initString; nextPutAll: '.'.\\n\\t\\t\\tnodeDict at: (self instVarAt: i) put: (varNames at: i)]].\\n\\tsubmorphs do: \\n\\t\\t[:m | s cr; tab; nextPutAll: 'self addMorph: '.\\n\\t\\tm printConstructorOn: s indent: 1 nodeDict: nodeDict.\\n\\t\\ts nextPutAll: '.'].\\n\\tself class\\n\\t\\tcompile: s contents\\n\\t\\tclassified: 'initialization'\\n\\t\\tnotifying: nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicModel class\\n\\tinstanceVariableNames: 'prototype'!\\n\\n!MorphicModel class methodsFor: 'compilation' stamp: 'tk 3/10/98 18:03'!\\ncategoryForSubclasses\\n\\t^ 'Morphic-Models'! !\\n\\n!MorphicModel class methodsFor: 'compilation' stamp: 'sw 5/23/2001 13:51'!\\nchooseNewName\\n\\t\\\"Choose a new name for the receiver, persisting until an acceptable name is provided or until the existing name is resubmitted\\\"\\n\\n\\t| oldName newName |\\n\\toldName _ self name.\\n\\t\\t[newName _ (FillInTheBlank request: 'Please give this Model a name'\\n\\t\\t\\t\\t\\tinitialAnswer: oldName) asSymbol.\\n\\t\\tnewName = oldName ifTrue: [^ self].\\n\\t\\tSmalltalk includesKey: newName]\\n\\t\\twhileTrue:\\n\\t\\t[self inform: 'Sorry, that name is already in use.'].\\n\\tself rename: newName.! !\\n\\n!MorphicModel class methodsFor: 'compilation'!\\ncompileAccessorsFor: varName\\n\\tself compile: (\\n'&var\\n\\t\\\"Return the value of &var\\\"\\n\\t^ &var'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'public access' notifying: nil.\\n\\tself compile: (\\n'&varPut: newValue\\n\\t\\\"Assign newValue to &var.\\n\\tAdd code below to update related graphics appropriately...\\\"\\n\\n\\t&var _ newValue.'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'public access' notifying: nil.\\n\\tself compile: (\\n'&var: newValue\\n\\t\\\"Assigns newValue to &var and updates owner\\\"\\n\\t&var _ newValue.\\n\\tself propagate: &var as: ''&var:'''\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\tclassified: 'private - propagation' notifying: nil.\\n! !\\n\\n!MorphicModel class methodsFor: 'compilation'!\\ncompilePropagationForVarName: varName slotName: slotName\\n\\tself compile: ((\\n'&slot&var: newValue\\n\\t\\\"The value of &var in &slot has changed to newValue.\\n\\tThis value can be read elsewhere in code with\\n\\t\\t&slot &var\\n\\tand it can be stored into with\\n\\t\\t&slot &varPut: someValue\\\"\\n\\n\\t\\\"Add code for appropriate response here...\\\"'\\n\\t\\t\\tcopyReplaceAll: '&var' with: varName)\\n\\t\\t\\tcopyReplaceAll: '&slot' with: slotName)\\n\\t\\tclassified: 'input events' notifying: nil.\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'compiling' stamp: 'sw 5/13/1998 14:33'!\\nacceptsLoggingOfCompilation\\n\\t\\\"Dont log sources for my automatically-generated subclasses. Can easily switch this back when it comes to deal with Versions, etc.\\\"\\n\\n\\t^ self == MorphicModel or: [(name last isDigit) not]! !\\n\\n!MorphicModel class methodsFor: 'compiling' stamp: 'sw 8/4/97 17:16'!\\nwantsChangeSetLogging\\n\\t\\\"Log changes for MorphicModel itself and for things like PlayWithMe2, but not for automatically-created subclasses like MorphicModel1, MorphicModel2, etc.\\\"\\n\\n\\t^ self == MorphicModel or:\\n\\t\\t[(self class name beginsWith: 'Morphic') not]! !\\n\\n\\n!MorphicModel class methodsFor: 'housekeeping' stamp: 'jm 7/30/97 16:40'!\\nremoveUninstantiatedModels\\n\\t\\\"With the user's permission, remove the classes of any models that have neither instances nor subclasses.\\\"\\n\\t\\\"MorphicModel removeUninstantiatedModels\\\"\\n\\n\\t| candidatesForRemoval ok |\\n\\tSmalltalk garbageCollect.\\n\\tcandidatesForRemoval _\\n\\t\\tMorphicModel subclasses select: [:c |\\n\\t\\t\\t(c instanceCount = 0) and: [c subclasses size = 0]].\\n\\tcandidatesForRemoval do: [:c |\\n\\t\\tok _ self confirm: 'Are you certain that you\\nwant to delete the class ', c name, '?'.\\n\\t\\tok ifTrue: [c removeFromSystem]].\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'instance creation' stamp: 'tk 8/13/1998 12:58'!\\nnew\\n\\t\\\"Return a copy of the prototype, if there is one.\\n\\tOtherwise create a new instance normally.\\\"\\n\\n\\tself hasPrototype ifTrue: [^ prototype veryDeepCopy].\\n\\t^ super new\\n! !\\n\\n!MorphicModel class methodsFor: 'instance creation' stamp: 'di 6/22/97 09:27'!\\nnewBounds: bounds model: thang slotName: nameOfThisPart\\n\\t^ (super new model: thang slotName: nameOfThisPart)\\n\\t\\tnewBounds: bounds! !\\n\\n\\n!MorphicModel class methodsFor: 'new-morph participation' stamp: 'di 2/21/98 11:01'!\\nincludeInNewMorphMenu\\n\\t\\\"Only include Models that are appropriate\\\"\\n\\t^ false! !\\n\\n\\n!MorphicModel class methodsFor: 'prototype access'!\\nprototype\\n\\t\\\"Return the prototype for this morph.\\\"\\n\\n\\t^ prototype\\n! !\\n\\n!MorphicModel class methodsFor: 'prototype access' stamp: 'gm 2/22/2003 19:13'!\\nprototype: aMorph\\n\\t\\\"Store a copy of the given morph as a prototype to be copied to make new instances.\\\"\\n\\n\\taMorph ifNil: [prototype _ nil. ^ self].\\n\\n\\tprototype _ aMorph veryDeepCopy.\\n\\t(prototype isMorphicModel) ifTrue: \\n\\t\\t[prototype model: nil slotName: nil].\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'queries'!\\nhasPrototype\\n\\t\\\"Return true if there is a prototype for this morph.\\\"\\n\\n\\t^ prototype ~~ nil\\n! !\\n\\n\\n!MorphicModel class methodsFor: 'subclass creation'!\\nnewSubclass\\n\\t| i className |\\n\\ti _ 1.\\n\\t[className _ (self name , i printString) asSymbol.\\n\\t Smalltalk includesKey: className]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\n\\t^ self subclass: className\\n\\t\\tinstanceVariableNames: ''\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: 'Morphic-Models'! !\\n\\n\\n!MorphicModel class methodsFor: 'testing' stamp: 'tk 3/15/98 20:13'!\\nofficialClass\\n\\t\\\"We want to make a new instance of the receiver, which is a subclass of MorphicModel. Answer who to make a new subclass of. Also used to tell if a given class is a UniClass, existing only for its single instance.\\\"\\n\\n\\t^ self name last isDigit ifTrue: [MorphicModel] ifFalse: [self]\\n\\t\\t\\\"MorphicModel7 can not have subclasses, but Slider and SystemWindow may\\\"! !\\n\\n\\n!MorphicModel class methodsFor: '*eToys-queries' stamp: 'sw 2/27/2002 14:58'!\\nbaseUniclass\\n\\t\\\"Answer the uniclass that new instances should be instances of. This protocol is primarily intended for the Player lineage, but can get sent to a MorphicModel subclass when the project-loading mechanism is scrambling to fix up projects that have naming conflicts with the project being loaded.\\\"\\n\\n\\t| curr |\\n\\tcurr _ self.\\n\\t[curr theNonMetaClass superclass name endsWithDigit]\\n\\t\\twhileTrue:\\n\\t\\t\\t[curr _ curr superclass].\\n\\t^ curr\\n\\n\\\"PlayWithMe1 baseUniclass\\\"! !\\nAppRegistry subclass: #MorphicTextEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\nToolBuilder subclass: #MorphicToolBuilder\\n\\tinstanceVariableNames: 'widgets panes parentMenu'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicToolBuilder commentStamp: 'ar 2/11/2005 15:02' prior: 0!\\nThe Morphic tool builder.!\\n\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:40'!\\nclose: aWidget\\n\\t\\\"Close a previously opened widget\\\"\\n\\taWidget delete! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 2/28/2006 17:39'!\\nopen: anObject\\n\\t\\\"Build and open the object. Answer the widget opened.\\\"\\n\\t| morph |\\n\\tmorph := self build: anObject.\\n\\t(morph isKindOf: MenuMorph)\\n\\t\\tifTrue:[morph popUpInWorld: World].\\n\\t(morph isKindOf: SystemWindow)\\n\\t\\tifTrue:[morph openInWorldExtent: morph extent]\\n\\t\\tifFalse:[morph openInWorld].\\n\\t^morph! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:40'!\\nopen: anObject label: aString\\n\\t\\\"Build an open the object, labeling it appropriately. Answer the widget opened.\\\"\\n\\t| window |\\n\\twindow := self open: anObject.\\n\\twindow setLabel: aString.\\n\\t^window! !\\n\\n!MorphicToolBuilder methodsFor: 'opening' stamp: 'ar 6/5/2005 12:41'!\\nrunModal: aWidget\\n\\t\\\"Run the (previously opened) widget modally, e.g., \\n\\tdo not return control to the sender before the user has responded.\\\"\\n\\t[aWidget world notNil] whileTrue: [\\n\\t\\taWidget outermostWorldMorph doOneCycle.\\n\\t].\\n! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 2/12/2005 14:22'!\\nbuildPluggableActionButton: aSpec\\n\\t| button |\\n\\tbutton := self buildPluggableButton: aSpec.\\n\\tbutton beActionButton.\\n\\t^button! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:27'!\\nbuildPluggableButton: aSpec\\n\\t| widget label state action enabled |\\n\\tlabel := aSpec label.\\n\\tstate := aSpec state.\\n\\taction := aSpec action.\\n\\twidget := PluggableButtonMorphPlus on: aSpec model\\n\\t\\t\\t\\tgetState: (state isSymbol ifTrue:[state])\\n\\t\\t\\t\\taction: nil\\n\\t\\t\\t\\tlabel: (label isSymbol ifTrue:[label]).\\n\\tself register: widget id: aSpec name.\\n\\tenabled := aSpec enabled.\\n\\tenabled isSymbol\\n\\t\\tifTrue:[widget getEnabledSelector: enabled]\\n\\t\\tifFalse:[widget enabled:enabled].\\n\\twidget action: action.\\n\\twidget getColorSelector: aSpec color.\\n\\twidget offColor: Color transparent.\\n\\taSpec help ifNotNil:[widget setBalloonText: aSpec help].\\n\\t(label isSymbol or:[label == nil]) ifFalse:[widget label: label].\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'md 8/15/2005 17:55'!\\nbuildPluggableInputField: aSpec\\n\\t| widget |\\n\\twidget := self buildPluggableText: aSpec.\\n\\twidget acceptOnCR: true.\\n\\twidget hideScrollBarsIndefinitely.\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/15/2005 12:07'!\\nbuildPluggableList: aSpec\\n\\t| widget listClass getIndex setIndex |\\n\\taSpec getSelected ifNil:[\\n\\t\\tlistClass := PluggableListMorphPlus.\\n\\t\\tgetIndex := aSpec getIndex.\\n\\t\\tsetIndex := aSpec setIndex.\\n\\t] ifNotNil:[\\n\\t\\tlistClass := PluggableListMorphByItemPlus.\\n\\t\\tgetIndex := aSpec getSelected.\\n\\t\\tsetIndex := aSpec setSelected.\\n\\t].\\n\\twidget := listClass on: aSpec model\\n\\t\\t\\t\\tlist: aSpec list\\n\\t\\t\\t\\tselected: getIndex\\n\\t\\t\\t\\tchangeSelected: setIndex\\n\\t\\t\\t\\tmenu: aSpec menu\\n\\t\\t\\t\\tkeystroke: aSpec keyPress.\\n\\tself register: widget id: aSpec name.\\n\\twidget dragItemSelector: aSpec dragItem.\\n\\twidget dropItemSelector: aSpec dropItem.\\n\\twidget wantsDropSelector: aSpec dropAccept.\\n\\twidget autoDeselect: aSpec autoDeselect.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec list ifNotNil:[panes add: aSpec list].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:27'!\\nbuildPluggableMultiSelectionList: aSpec\\n\\t| widget listClass |\\n\\taSpec getSelected ifNotNil:[^self error:'There is no PluggableListMorphOfManyByItem'].\\n\\tlistClass := PluggableListMorphOfMany.\\n\\twidget := listClass on: aSpec model\\n\\t\\tlist: aSpec list\\n\\t\\tprimarySelection: aSpec getIndex\\n\\t\\tchangePrimarySelection: aSpec setIndex\\n\\t\\tlistSelection: aSpec getSelectionList\\n\\t\\tchangeListSelection: aSpec setSelectionList\\n\\t\\tmenu: aSpec menu.\\n\\tself register: widget id: aSpec name.\\n\\twidget keystrokeActionSelector: aSpec keyPress.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec list ifNotNil:[panes add: aSpec list].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:28'!\\nbuildPluggablePanel: aSpec\\n\\t| widget children |\\n\\twidget := PluggablePanelMorph new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\twidget color: Color transparent.\\n\\twidget clipSubmorphs: true.\\n\\tchildren := aSpec children.\\n\\tchildren isSymbol ifTrue:[\\n\\t\\twidget getChildrenSelector: children.\\n\\t\\twidget update: children.\\n\\t\\tchildren := #().\\n\\t].\\n\\tself buildAll: children in: widget.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tself setLayout: aSpec layout in: widget.\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/14/2005 22:28'!\\nbuildPluggableText: aSpec\\n\\t| widget |\\n\\twidget := PluggableTextMorphPlus on: aSpec model\\n\\t\\t\\t\\ttext: aSpec getText \\n\\t\\t\\t\\taccept: aSpec setText\\n\\t\\t\\t\\treadSelection: aSpec selection \\n\\t\\t\\t\\tmenu: aSpec menu.\\n\\tself register: widget id: aSpec name.\\n\\twidget getColorSelector: aSpec color.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec getText ifNotNil:[panes add: aSpec getText].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 7/15/2005 12:10'!\\nbuildPluggableTree: aSpec\\n\\t| widget |\\n\\twidget := PluggableTreeMorph new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\twidget getSelectedPathSelector: aSpec getSelectedPath.\\n\\twidget setSelectedSelector: aSpec setSelected.\\n\\twidget getChildrenSelector: aSpec getChildren.\\n\\twidget hasChildrenSelector: aSpec hasChildren.\\n\\twidget getLabelSelector: aSpec label.\\n\\twidget getIconSelector: aSpec icon.\\n\\twidget getHelpSelector: aSpec help.\\n\\twidget getMenuSelector: aSpec menu.\\n\\twidget keystrokeActionSelector: aSpec keyPress.\\n\\twidget getRootsSelector: aSpec roots.\\n\\twidget autoDeselect: aSpec autoDeselect.\\n\\twidget dropItemSelector: aSpec dropItem.\\n\\twidget wantsDropSelector: aSpec dropAccept.\\n\\tself setFrame: aSpec frame in: widget.\\n\\tparent ifNotNil:[self add: widget to: parent].\\n\\tpanes ifNotNil:[\\n\\t\\taSpec roots ifNotNil:[panes add: aSpec roots].\\n\\t].\\n\\t^widget! !\\n\\n!MorphicToolBuilder methodsFor: 'pluggable widgets' stamp: 'ar 9/17/2005 21:07'!\\nbuildPluggableWindow: aSpec\\n\\t| widget children label |\\n\\taSpec layout == #proportional ifFalse:[\\n\\t\\t\\\"This needs to be implemented - probably by adding a single pane and then the rest\\\"\\n\\t\\t^self error: 'Not implemented'.\\n\\t].\\n\\twidget := PluggableSystemWindow new.\\n\\tself register: widget id: aSpec name.\\n\\twidget model: aSpec model.\\n\\t(label := aSpec label) ifNotNil:[\\n\\t\\tlabel isSymbol \\n\\t\\t\\tifTrue:[widget getLabelSelector: label]\\n\\t\\t\\tifFalse:[widget setLabel: label]].\\n\\tchildren := aSpec children.\\n\\tchildren isSymbol ifTrue:[\\n\\t\\twidget getChildrenSelector: children.\\n\\t\\twidget update: children.\\n\\t\\tchildren := #().\\n\\t].\\n\\twidget closeWindowSelector: aSpec closeAction.\\n\\tpanes := OrderedCollection new.\\n\\tself buildAll: children in: widget.\\n\\taSpec extent ifNotNil:[widget extent: aSpec extent].\\n\\twidget setUpdatablePanesFrom: panes.\\n\\t^widget! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/17/2005 00:00'!\\nadd: aMorph to: aParent\\n\\taParent addMorphBack: aMorph.\\n\\taParent isSystemWindow ifTrue:[\\n\\t\\taParent addPaneMorph: aMorph.\\n\\t].! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'stephaneducasse 2/3/2006 22:35'!\\nasFrame: aRectangle\\n\\t| frame |\\n\\taRectangle ifNil:[^nil].\\n\\tframe := LayoutFrame new.\\n\\tframe \\n\\t\\tleftFraction: aRectangle left; \\n\\t\\trightFraction: aRectangle right; \\n\\t\\ttopFraction: aRectangle top; \\n\\t\\tbottomFraction: aRectangle bottom.\\n\\t^frame! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/14/2005 22:28'!\\nregister: widget id: id\\n\\tid ifNil:[^self].\\n\\twidgets ifNil:[widgets := Dictionary new].\\n\\twidgets at: id put: widget.! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 2/12/2005 19:20'!\\nsetFrame: aRectangle in: widget\\n\\t| frame |\\n\\taRectangle ifNil:[^nil].\\n\\tframe := self asFrame: aRectangle.\\n\\twidget layoutFrame: frame.\\n\\twidget hResizing: #spaceFill; vResizing: #spaceFill.\\n\\t(parent isSystemWindow) ifTrue:[\\n\\t\\twidget borderWidth: 2; borderColor: #inset.\\n\\t].! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 2/10/2005 22:28'!\\nsetLayout: layout in: widget\\n\\tlayout == #proportional ifTrue:[\\n\\t\\twidget layoutPolicy: ProportionalLayout new.\\n\\t\\t^self].\\n\\tlayout == #horizontal ifTrue:[\\n\\t\\twidget layoutPolicy: TableLayout new.\\n\\t\\twidget listDirection: #leftToRight.\\n\\t\\twidget submorphsDo:[:m| m hResizing: #spaceFill; vResizing: #spaceFill].\\n\\t\\t\\\"and then some...\\\"\\n\\t\\t^self].\\n\\tlayout == #vertical ifTrue:[\\n\\t\\twidget layoutPolicy: TableLayout new.\\n\\t\\twidget listDirection: #topToBottom.\\n\\t\\twidget submorphsDo:[:m| m hResizing: #spaceFill; vResizing: #spaceFill].\\n\\t\\t\\\"and then some...\\\"\\n\\t\\t^self].\\n\\t^self error: 'Unknown layout: ', layout.! !\\n\\n!MorphicToolBuilder methodsFor: 'private' stamp: 'ar 7/14/2005 22:30'!\\nwidgetAt: id ifAbsent: aBlock\\n\\twidgets ifNil:[^aBlock value].\\n\\t^widgets at: id ifAbsent: aBlock! !\\n\\n\\n!MorphicToolBuilder methodsFor: 'building' stamp: 'ar 2/28/2006 17:30'!\\nbuildPluggableMenu: menuSpec \\n\\t| prior menu |\\n\\tprior := parentMenu.\\n\\tparentMenu := menu := MenuMorph new.\\n\\tmenuSpec label ifNotNil:[parentMenu addTitle: menuSpec label].\\n\\tmenuSpec items do:[:each| each buildWith: self].\\n\\tparentMenu := prior.\\n\\t^menu! !\\n\\n!MorphicToolBuilder methodsFor: 'building' stamp: 'ar 2/28/2006 17:37'!\\nbuildPluggableMenuItem: itemSpec\\n\\t| item action label menu |\\n\\titem _ MenuItemMorph new.\\n\\tlabel := itemSpec label.\\n\\titemSpec checked ifTrue:[label := '<on>', label] ifFalse:[label := '<off>', label].\\n\\titem contents: label.\\n\\titem isEnabled: itemSpec enabled.\\n\\t(action := itemSpec action) ifNotNil:[\\n\\t\\titem \\n\\t\\t\\ttarget: action receiver;\\n\\t\\t\\tselector: action selector;\\n\\t\\t\\targuments: action arguments.\\n\\t].\\n\\t(menu := itemSpec subMenu) ifNotNil:[\\n\\t\\titem subMenu: (menu buildWith: self).\\n\\t].\\n\\tparentMenu ifNotNil:[parentMenu addMorphBack: item].\\n\\t^item! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicToolBuilder class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicToolBuilder class methodsFor: 'accessing' stamp: 'ar 2/11/2005 15:24'!\\nisActiveBuilder\\n\\t\\\"Answer whether I am the currently active builder\\\"\\n\\t^Smalltalk isMorphic! !\\nToolBuilderTests subclass: #MorphicToolBuilderTests\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicToolBuilderTests commentStamp: 'ar 2/11/2005 15:02' prior: 0!\\nTests for the Morphic tool builder.!\\n\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:26'!\\nacceptWidgetText\\n\\twidget hasUnacceptedEdits: true.\\n\\twidget accept.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 6/21/2005 10:35'!\\nbuttonWidgetEnabled\\n\\t\\\"Answer whether the current widget (a button) is currently enabled\\\"\\n\\t^widget enabled! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:22'!\\nchangeListWidget\\n\\twidget changeModelSelection: widget getCurrentSelectionIndex + 1.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 19:15'!\\nfireButtonWidget\\n\\twidget performAction.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'cwp 6/9/2005 00:11'!\\nfireMenuItemWidget\\n\\t(widget itemWithWording: 'Menu Item')\\n\\t\\tifNotNilDo: [:item | item doButtonAction]! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 14:46'!\\nsetUp\\n\\tsuper setUp.\\n\\tbuilder := MorphicToolBuilder new.! !\\n\\n!MorphicToolBuilderTests methodsFor: 'support' stamp: 'ar 2/11/2005 21:43'!\\nwidgetColor\\n\\t\\\"Answer color from widget\\\"\\n\\t^widget color! !\\n\\n\\n!MorphicToolBuilderTests methodsFor: 'tests-window' stamp: 'ar 2/13/2005 13:52'!\\ntestWindowDynamicLabel\\n\\tself makeWindow.\\n\\tself assert: (widget label = 'TestLabel').! !\\n\\n!MorphicToolBuilderTests methodsFor: 'tests-window' stamp: 'ar 2/13/2005 13:52'!\\ntestWindowStaticLabel\\n\\t| spec |\\n\\tspec := builder pluggableWindowSpec new.\\n\\tspec model: self.\\n\\tspec children: #().\\n\\tspec label: 'TestLabel'.\\n\\twidget := builder build: spec.\\n\\tself assert: (widget label = 'TestLabel').! !\\nDisplayTransform subclass: #MorphicTransform\\n\\tinstanceVariableNames: 'offset angle scale'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Transformations'!\\n!MorphicTransform commentStamp: '<historical>' prior: 0!\\nThis class implements simple translation, scaling and rotation for points, as well as inverse transformations. These transformations are used in TransformMorphs (clipping scrollers) and TransformationMorphs (general flex-morph wrappers) to map, eg, global mouse coords into local coords, and to invert, eg, local damage rectangles into global damage rectangles.!\\n\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nangle\\n\\t^ angle! !\\n\\n!MorphicTransform methodsFor: 'accessing' stamp: 'ar 11/9/1998 14:33'!\\ninverseTransformation\\n\\t\\\"Return the inverse transformation of the receiver\\\"\\n\\t^MorphicTransform\\n\\t\\toffset: (self transform: 0@0) - (self transform: offset)\\n\\t\\tangle: angle negated\\n\\t\\tscale: scale reciprocal! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\noffset\\n\\t^ offset\\n! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nscale\\n\\t^ scale! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithAngle: a\\n\\t\\\"Return a copy of me with a different Angle\\\"\\n\\t^ self copy setAngle: a! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithOffset: a\\n\\t\\\"Return a copy of me with a different Offset\\\"\\n\\t^ self copy setOffset: a! !\\n\\n!MorphicTransform methodsFor: 'accessing'!\\nwithScale: a\\n\\t\\\"Return a copy of me with a different Scale\\\"\\n\\t^ self copy setScale: a! !\\n\\n\\n!MorphicTransform methodsFor: 'composing' stamp: 'nk 3/9/2001 13:55'!\\ncomposedWithLocal: aTransform\\n\\taTransform isIdentity ifTrue:[^self].\\n\\tself isIdentity ifTrue:[^aTransform].\\n\\taTransform isMorphicTransform ifFalse:[^super composedWithLocal: aTransform].\\n\\tself isPureTranslation ifTrue:[\\n\\t\\t^aTransform withOffset: aTransform offset + self offset].\\n\\taTransform isPureTranslation ifTrue:[\\n\\t\\t^self withOffset: (self localPointToGlobal: aTransform offset negated) negated].\\n\\t^super composedWithLocal: aTransform.! !\\n\\n\\n!MorphicTransform methodsFor: 'converting' stamp: 'ar 11/2/1998 20:14'!\\nasMatrixTransform2x3\\n\\t^((MatrixTransform2x3 withRotation: angle radiansToDegrees negated) composedWithLocal:\\n\\t\\t(MatrixTransform2x3 withScale: scale))\\n\\t\\t\\toffset: offset negated! !\\n\\n!MorphicTransform methodsFor: 'converting' stamp: 'di 10/26/1999 17:03'!\\nasMorphicTransform\\n\\n\\t^ self! !\\n\\n\\n!MorphicTransform methodsFor: 'initialize' stamp: 'ar 11/2/1998 20:58'!\\nsetIdentiy\\n\\tscale _ 1.0.\\n\\toffset _ 0@0.\\n\\tangle _ 0.0.! !\\n\\n\\n!MorphicTransform methodsFor: 'printing' stamp: 'ar 5/19/1999 18:21'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut:$(;\\n\\t\\tnextPutAll:'angle = '; print: angle;\\n\\t\\tnextPutAll:'; scale = '; print: scale;\\n\\t\\tnextPutAll:'; offset = '; print: offset;\\n\\t\\tnextPut:$).! !\\n\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 20:57'!\\nisIdentity\\n\\t\\\"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself.\\\"\\n\\n\\t^ self isPureTranslation and: [offset = (0@0)]\\n! !\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 19:51'!\\nisMorphicTransform\\n\\t^true! !\\n\\n!MorphicTransform methodsFor: 'testing' stamp: 'ar 11/2/1998 20:57'!\\nisPureTranslation\\n\\t\\\"Return true if the receiver specifies no rotation or scaling.\\\"\\n\\n\\t^ angle = 0.0 and: [scale = 1.0]\\n! !\\n\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 3/4/98 19:10'!\\ncomposedWith: aTransform\\n\\t\\\"Return a new transform that has the effect of transforming points first by the receiver and then by the argument.\\\"\\n\\n\\tself isIdentity ifTrue: [^ aTransform].\\n\\taTransform isIdentity ifTrue: [^ self].\\n\\t^ CompositeTransform new globalTransform: self\\n\\t\\t\\t\\t\\t\\t\\tlocalTransform: aTransform! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/28/1999 09:10'!\\ninvert: aPoint\\n\\t\\\"Transform the given point from local to global coordinates.\\\"\\n\\t| p3 p2 |\\n\\tself isPureTranslation ifTrue: [^ aPoint - offset].\\n\\tp3 _ aPoint * scale.\\n\\tp2 _ ((p3 x * angle cos) + (p3 y * angle sin))\\n\\t\\t@ ((p3 y * angle cos) - (p3 x * angle sin)).\\n\\t^ (p2 - offset)\\n! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/3/1998 00:18'!\\ninvertBoundsRect: aRectangle\\n\\t\\\"Return a rectangle whose coordinates have been transformed\\n\\tfrom local back to global coordinates. NOTE: if the transformation\\n\\tis not just a translation, then it will compute the bounding box\\n\\tin global coordinates.\\\"\\n\\t| outerRect |\\n\\tself isPureTranslation\\n\\tifTrue:\\n\\t\\t[^ (self invert: aRectangle topLeft)\\n\\t\\t\\tcorner: (self invert: aRectangle bottomRight)]\\n\\tifFalse:\\n\\t\\t[outerRect _ Rectangle encompassing:\\n\\t\\t\\t(aRectangle innerCorners collect: [:p | self invert: p]).\\n\\t\\t\\\"Following asymmetry due to likely subsequent truncation\\\"\\n\\t\\t^ outerRect topLeft - (1@1) corner: outerRect bottomRight + (2@2)]! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/2/1998 08:54'!\\ninvertRect: aRectangle\\n\\n\\tself error: 'method name changed to emphasize enclosing bounds'.\\n\\t^ self invertBoundsRect: aRectangle! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/28/1999 09:05'!\\ntransform: aPoint\\n\\t\\\"Transform the given point from global to local coordinates.\\\"\\n\\t| p2 p3 |\\n\\tself isPureTranslation ifTrue: [^ aPoint + offset].\\n\\tp2 _ aPoint + offset.\\n\\tp3 _ (((p2 x * angle cos) - (p2 y * angle sin))\\n\\t\\t@ ((p2 y * angle cos) + (p2 x * angle sin)))\\n\\t\\t\\t/ scale.\\n\\t^ p3! !\\n\\n!MorphicTransform methodsFor: 'transformations' stamp: 'di 10/3/1998 00:18'!\\ntransformBoundsRect: aRectangle\\n\\t\\\"Return a rectangle whose coordinates have been transformed\\n\\tfrom global to local coordinates. NOTE: if the transformation\\n\\tis not just a translation, then it will compute the bounding box\\n\\tin global coordinates.\\\"\\n\\t| outerRect |\\n\\tself isPureTranslation\\n\\tifTrue:\\n\\t\\t[^ (self transform: aRectangle topLeft)\\n\\t\\t\\tcorner: (self transform: aRectangle bottomRight)]\\n\\tifFalse:\\n\\t\\t[outerRect _ Rectangle encompassing:\\n\\t\\t\\t(aRectangle innerCorners collect: [:p | self transform: p]).\\n\\t\\t\\\"Following asymmetry due to likely subsequent truncation\\\"\\n\\t\\t^ outerRect topLeft - (1@1) corner: outerRect bottomRight + (2@2)]! !\\n\\n\\n!MorphicTransform methodsFor: 'transforming points' stamp: 'ar 11/2/1998 16:13'!\\nglobalPointToLocal: aPoint\\n\\t\\\"Transform aPoint from global coordinates into local coordinates\\\"\\n\\t^self transform: aPoint! !\\n\\n!MorphicTransform methodsFor: 'transforming points' stamp: 'ar 11/2/1998 16:32'!\\nlocalPointToGlobal: aPoint\\n\\t\\\"Transform aPoint from global coordinates into local coordinates\\\"\\n\\t^self invert: aPoint! !\\n\\n\\n!MorphicTransform methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ls 10/9/1999 19:06'!\\nencodeForRemoteCanvas\\n\\t\\\"encode this transform into a string for use by a RemoteCanvas\\\"\\n\\t^String streamContents: [ :str |\\n\\t\\tstr nextPutAll: 'Morphic,';\\n\\t\\t\\tprint: offset x truncated;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: offset y truncated;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: scale;\\n\\t\\t\\tnextPut: $,;\\n\\t\\t\\tprint: angle\\n\\t]! !\\n\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetAngle: aFloat\\n\\n\\tangle _ aFloat.\\n! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetOffset: aPoint\\n\\n\\toffset _ aPoint.\\n! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetOffset: aPoint angle: a scale: s\\n\\n\\toffset _ aPoint.\\n\\tangle _ a.\\n\\tscale _ s! !\\n\\n!MorphicTransform methodsFor: 'private'!\\nsetScale: aFloat\\n\\n\\tscale _ aFloat.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicTransform class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\nidentity\\n\\n\\t^ self offset: 0@0 angle: 0.0 scale: 1.0! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\nnew\\n\\n\\t^ self offset: 0@0\\n! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\noffset: aPoint\\n\\n\\t^ self offset: aPoint angle: 0.0 scale: 1.0! !\\n\\n!MorphicTransform class methodsFor: 'instance creation'!\\noffset: aPoint angle: a scale: s\\n\\n\\t^ self basicNew setOffset: aPoint angle: a scale: s! !\\n\\n\\n!MorphicTransform class methodsFor: '*nebraska-instance creation' stamp: 'sd 11/20/2005 21:25'!\\nfromRemoteCanvasEncoding: encoded\\n\\t\\\"DisplayTransform fromRemoteCanvasEncoding: 'Morphic,-88,-128,1.345165663873898,0.1352584843149221'\\\"\\n\\t| type offsetXEnc offsetYEnc scaleEnc angleEnc offsetX offsetY angle scale rs |\\n\\n\\t\\\"separate the numbers\\\"\\n\\trs := ReadStream on: encoded.\\n\\ttype := rs upTo: $,.\\n\\toffsetXEnc := rs upTo: $,.\\n\\toffsetYEnc := rs upTo: $,.\\n\\tscaleEnc := rs upTo: $,.\\n\\tangleEnc := rs upToEnd.\\n\\n\\t\\\"decode the numbers\\\"\\n\\toffsetX := Integer readFromString: offsetXEnc.\\n\\toffsetY := Integer readFromString: offsetYEnc.\\n\\n\\tscale := Number readFromString: scaleEnc.\\n\\tangle := Number readFromString: angleEnc.\\n\\n\\t\\\"create an instance\\\"\\n\\t^self offset: offsetX@offsetY angle: angle scale: scale! !\\nUIManager subclass: #MorphicUIManager\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-Morphic'!\\n!MorphicUIManager commentStamp: 'ar 2/11/2005 21:52' prior: 0!\\nThe Morphic ui manager.!\\n\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/16/2005 19:37'!\\nchooseDirectory: label from: dir\\n\\t\\\"Let the user choose a directory\\\"\\n\\t^FileList2 modalFolderSelector: dir! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/17/2005 00:28'!\\nchooseFileMatching: patterns label: aString\\n\\t\\\"Let the user choose a file matching the given patterns\\\"\\n\\t| result |\\n\\tresult := FileList2 modalFileSelectorForSuffixes: patterns.\\n\\t^result ifNotNil:[result fullName]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 10:47'!\\nchooseFrom: aList lines: linesArray title: aString\\n\\t\\\"Choose an item from the given list. Answer the index of the selected item.\\\"\\n\\t| menu |\\n\\tmenu := PopUpMenu labelArray: aList lines: linesArray.\\n\\t^aString isEmpty ifTrue:[menu startUp] ifFalse:[menu startUpWithCaption: aString]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/15/2005 23:44'!\\nchooseFrom: labelList values: valueList lines: linesArray title: aString\\n\\t\\\"Choose an item from the given list. Answer the selected item.\\\"\\n\\t| menu |\\n\\tmenu := SelectionMenu labels: labelList lines: linesArray selections: valueList.\\n\\t^aString isEmpty ifTrue:[menu startUp] ifFalse:[menu startUpWithCaption: aString]! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:45'!\\nconfirm: queryString\\n\\t\\\"Put up a yes/no menu with caption queryString. Answer true if the \\n\\tresponse is yes, false if no. This is a modal question--the user must \\n\\trespond yes or no.\\\"\\n\\t^PopUpMenu confirm: queryString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 09:49'!\\nconfirm: aString orCancel: cancelBlock\\n\\t\\\"Put up a yes/no/cancel menu with caption aString. Answer true if \\n\\tthe response is yes, false if no. If cancel is chosen, evaluate \\n\\tcancelBlock. This is a modal question--the user must respond yes or no.\\\"\\n\\t^PopUpMenu confirm: aString orCancel: cancelBlock! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:13'!\\ndisplayProgress: titleString at: aPoint from: minVal to: maxVal during: workBlock\\n\\t\\\"Display titleString as a caption over a progress bar while workBlock is evaluated.\\\"\\n\\t^ProgressInitiationException \\n\\t\\tdisplay: titleString\\n\\t\\tat: aPoint \\n\\t\\tfrom: minVal \\n\\t\\tto: maxVal \\n\\t\\tduring: workBlock! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 7/17/2005 00:27'!\\nedit: aText label: labelString accept: anAction\\n\\t\\\"Open an editor on the given string/text\\\"\\n\\t| window holder text |\\n\\tholder := StringHolder new.\\n\\tholder contents: aText.\\n\\ttext := PluggableTextMorphPlus \\n\\t\\ton: holder \\n\\t\\ttext: #contents \\n\\t\\taccept: #acceptContents: \\n\\t\\treadSelection: nil \\n\\t\\tmenu: nil.\\n\\ttext acceptAction: anAction.\\n\\twindow := SystemWindow new.\\n\\tlabelString ifNotNil:[window setLabel: labelString].\\n\\twindow addMorph: text frame: (0@0 extent: 1@1).\\n\\twindow paneColor: Color gray.\\n\\twindow openInWorld.\\n! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:07'!\\ninformUserDuring: aBlock\\n\\t\\\"Display a message above (or below if insufficient room) the cursor \\n\\tduring execution of the given block.\\n\\t\\tUIManager default informUserDuring:[:bar|\\n\\t\\t\\t#(one two three) do:[:info|\\n\\t\\t\\t\\tbar value: info.\\n\\t\\t\\t\\t(Delay forSeconds: 1) wait]]\\\"\\n\\t(MVCMenuMorph from: (SelectionMenu labels: '') title: '\\t\\t\\t\\t\\t\\t')\\n\\t\\tinformUserAt: Sensor cursorPoint during: aBlock.! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:46'!\\ninform: aString\\n\\t\\\"Display a message for the user to read and then dismiss\\\"\\n\\t^PopUpMenu inform: aString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 2/28/2005 17:05'!\\nmultiLineRequest: queryString centerAt: aPoint initialAnswer: defaultAnswer answerHeight: answerHeight\\n\\t\\\"Create a multi-line instance of me whose question is queryString with\\n\\tthe given initial answer. Invoke it centered at the given point, and\\n\\tanswer the string the user accepts. Answer nil if the user cancels. An\\n\\tempty string returned means that the ussr cleared the editing area and\\n\\tthen hit 'accept'. Because multiple lines are invited, we ask that the user\\n\\tuse the ENTER key, or (in morphic anyway) hit the 'accept' button, to \\n\\tsubmit; that way, the return key can be typed to move to the next line.\\\"\\n\\t^FillInTheBlank multiLineRequest: queryString centerAt: aPoint initialAnswer: defaultAnswer answerHeight: answerHeight! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:47'!\\nrequestPassword: queryString\\n\\t\\\"Create an instance of me whose question is queryString. Invoke it centered\\n\\tat the cursor, and answer the string the user accepts. Answer the empty \\n\\tstring if the user cancels.\\\"\\n\\t^FillInTheBlank requestPassword: queryString! !\\n\\n!MorphicUIManager methodsFor: 'ui requests' stamp: 'ar 12/27/2004 08:46'!\\nrequest: queryString initialAnswer: defaultAnswer \\n\\t\\\"Create an instance of me whose question is queryString with the given \\n\\tinitial answer. Invoke it centered at the given point, and answer the \\n\\tstring the user accepts. Answer the empty string if the user cancels.\\\"\\n\\t^FillInTheBlank request: queryString initialAnswer: defaultAnswer ! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMorphicUIManager class\\n\\tinstanceVariableNames: ''!\\n\\n!MorphicUIManager class methodsFor: 'accessing' stamp: 'ar 2/11/2005 15:41'!\\nisActiveManager\\n\\t\\\"Answer whether I should act as the active ui manager\\\"\\n\\t^Smalltalk isMorphic! !\\nMorphicEvent subclass: #MorphicUnknownEvent\\n\\tinstanceVariableNames: 'type argument'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'EventSensorConstants'\\n\\tcategory: 'Morphic-Events'!\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 20:04'!\\nargument\\n\\t^argument! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 20:04'!\\nargument: arg\\n\\targument _ arg! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 19:55'!\\nposition\\n\\t^0@0! !\\n\\n!MorphicUnknownEvent methodsFor: 'accessing' stamp: 'ar 10/25/2000 19:55'!\\ntype\\n\\t^type! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'initialize' stamp: 'ar 10/26/2000 01:20'!\\ntype: eventType readFrom: aStream\\n\\t| typeAndArg |\\n\\ttimeStamp _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ttypeAndArg _ Object readFrom: aStream.\\n\\ttype _ typeAndArg first.\\n\\targument _ typeAndArg last.! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'objects from disk' stamp: 'RAA 12/20/2000 17:48'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\ttype ifNil: [type _ #startSound].\\n\\tsource ifNil: [source _ varDict at: 'sourceHand'].\\n\\targument ifNil: [argument _ varDict at: 'sound' ifAbsent: [nil]].\\t\\\"???\\\"\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'printing' stamp: 'ar 10/26/2000 01:19'!\\nstoreOn: aStream\\n\\taStream nextPutAll: 'unknown'.\\n\\taStream space.\\n\\tself timeStamp storeOn: aStream.\\n\\taStream space.\\n\\t{type. argument} storeOn: aStream.! !\\n\\n\\n!MorphicUnknownEvent methodsFor: 'private' stamp: 'ar 10/25/2000 19:59'!\\nsetType: evtType argument: arg\\n\\ttype _ evtType.\\n\\targument _ arg.! !\\n\\n!MorphicUnknownEvent methodsFor: 'private' stamp: 'ar 10/25/2000 19:58'!\\nsetType: evtType argument: arg hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\targument _ arg.\\n\\tsource _ evtHand.\\n\\ttimeStamp _ stamp.! !\\nMorph subclass: #MouseActionIndicatorMorph\\n\\tinstanceVariableNames: 'siblings'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!MouseActionIndicatorMorph commentStamp: '<historical>' prior: 0!\\nI am used to highlight morphs which have a special mouseup action!\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:49'!\\ndeleteWithSiblings\\n\\n\\tsiblings do: [ :each | each delete]\\n! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:49'!\\nsiblings: aCollection\\n\\n\\tsiblings _ aCollection.\\n! !\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/12/2000 10:48'!\\nhandlesMouseOver: evt\\n\\n\\t^true! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/17/2000 09:52'!\\nhandlesMouseOverDragging: evt\\n\\n\\t^true! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/12/2000 10:50'!\\nmouseEnter: evt\\n\\n\\tself deleteWithSiblings\\n! !\\n\\n!MouseActionIndicatorMorph methodsFor: 'event handling' stamp: 'RAA 7/17/2000 09:52'!\\nmouseEnterDragging: evt\\n\\n\\tself deleteWithSiblings\\n! !\\n\\n\\n!MouseActionIndicatorMorph methodsFor: 'initialization' stamp: 'RAA 7/12/2000 10:48'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tsiblings _ #().! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMouseActionIndicatorMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MouseActionIndicatorMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 11:08'!\\nworld: aWorld inner: innerRectangle outer: outerRectangle color: aColor\\n\\n\\t| allRects allMorphs |\\n\\n\\tallRects _ outerRectangle areasOutside: innerRectangle.\\n\\tallMorphs _ allRects collect: [ :each |\\n\\t\\tself new bounds: each; color: aColor\\n\\t].\\n\\tallMorphs do: [ :each |\\n\\t\\teach siblings: allMorphs; openInWorld: aWorld\\n\\t].\\n\\t^allMorphs\\n\\n\\n! !\\nMouseEvent subclass: #MouseButtonEvent\\n\\tinstanceVariableNames: 'whichButton'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:58'!\\nblueButtonChanged\\n\\t\\\"Answer true if the blue mouse button has changed. This is the third mouse button or cmd+click on the Mac.\\\"\\n\\n\\t^ whichButton anyMask: 1! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:58'!\\nredButtonChanged\\n\\t\\\"Answer true if the red mouse button has changed. This is the first mouse button.\\\"\\n\\n\\t^ whichButton anyMask: 4! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'nk 3/11/2004 17:44'!\\nwhichButton\\n\\t^whichButton! !\\n\\n!MouseButtonEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 19:59'!\\nyellowButtonChanged\\n\\t\\\"Answer true if the yellow mouse button has changed. This is the second mouse button or option+click on the Mac.\\\"\\n\\n\\t^ whichButton anyMask: 2! !\\n\\n\\n!MouseButtonEvent methodsFor: 'dispatching' stamp: 'ar 9/16/2000 13:05'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseDown ifTrue:[^anObject handleMouseDown: self].\\n\\ttype == #mouseUp ifTrue:[^anObject handleMouseUp: self].\\n\\t^super sentTo: anObject! !\\n\\n\\n!MouseButtonEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:29'!\\ntype: eventType readFrom: aStream\\n\\tsuper type: eventType readFrom: aStream.\\n\\taStream skip: 1.\\n\\twhichButton _ Integer readFrom: aStream.! !\\n\\n\\n!MouseButtonEvent methodsFor: 'printing' stamp: 'ar 10/24/2000 16:29'!\\nstoreOn: aStream\\n\\tsuper storeOn: aStream.\\n\\taStream space.\\n\\twhichButton storeOn: aStream.! !\\n\\n\\n!MouseButtonEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'dgd 2/22/2003 19:00'!\\ndecodeFromStringArray: array \\n\\t\\\"decode the receiver from an array of strings\\\"\\n\\n\\ttype := array first asSymbol.\\n\\tposition := CanvasDecoder decodePoint: (array second).\\n\\tbuttons := CanvasDecoder decodeInteger: (array third).\\n\\twhichButton := CanvasDecoder decodeInteger: (array fourth)! !\\n\\n!MouseButtonEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:24'!\\nencodedAsStringArray\\n\\t\\\"encode the receiver into an array of strings, such that it can be retrieved via the fromStringArray: class method\\\"\\n\\t^{\\n\\t\\ttype.\\n\\t\\tCanvasEncoder encodePoint: position.\\n\\t\\tCanvasEncoder encodeInteger: buttons.\\n\\t\\tCanvasEncoder encodeInteger: whichButton.\\n\\t}! !\\n\\n\\n!MouseButtonEvent methodsFor: 'private' stamp: 'ar 10/5/2000 23:55'!\\nsetType: evtType position: evtPos which: button buttons: evtButtons hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\tposition _ evtPos.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.\\n\\twhichButton _ button.\\n\\ttimeStamp _ stamp.! !\\nObject subclass: #MouseClickState\\n\\tinstanceVariableNames: 'clickClient clickState firstClickDown firstClickUp firstClickTime clickSelector dblClickSelector dblClickTime dblClickTimeoutSelector dragSelector dragThreshold'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Kernel'!\\n!MouseClickState commentStamp: '<historical>' prior: 0!\\nMouseClickState is a simple class managing the distinction between clicks, double clicks, and drag operations. It has been factored out of HandMorph due to the many instVars.\\n\\nInstance variables:\\n\\tclickClient \\t<Morph>\\t\\tThe client wishing to receive #click:, #dblClick:, or #drag messages\\n\\tclickState \\t<Symbol>\\tThe internal state of handling the last event (#firstClickDown, #firstClickUp, #firstClickTimedOut)\\n\\tfirstClickDown \\t<MorphicEvent>\\tThe #mouseDown event after which the client wished to receive #click: or similar messages\\n\\tfirstClickUp \\t<MorphicEvent>\\tThe first mouse up event which came in before the double click time out was exceeded (it is sent if there is a timout after the first mouse up event occured)\\n\\tfirstClickTime \\t<Integer>\\tThe millisecond clock value of the first event\\n\\tclickSelector \\t<Symbol>\\tThe selector to use for sending #click: messages\\n\\tdblClickSelector \\t<Symbol>\\tThe selector to use for sending #doubleClick: messages\\n\\tdblClickTime \\t<Integer>\\tTimout in milliseconds for a double click operation\\n\\tdragSelector \\t<Symbol>\\tThe selector to use for sending #drag: messages\\n\\tdragThreshold \\t<Integer>\\tThreshold used for determining if a #drag: message is sent (pixels!!)\\n!\\n\\n\\n!MouseClickState methodsFor: 'as yet unclassified' stamp: 'nk 7/26/2004 09:13'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $[; print: clickState; nextPut: $]\\n! !\\n\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:23'!\\nclick\\n\\n\\tclickSelector ifNotNil: [clickClient perform: clickSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:24'!\\ndoubleClick\\n\\n\\tdblClickSelector ifNotNil: [clickClient perform: dblClickSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 13:09'!\\ndoubleClickTimeout\\n\\n\\tdblClickTimeoutSelector ifNotNil: [\\n\\t\\tclickClient perform: dblClickTimeoutSelector with: firstClickDown]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'jcg 9/21/2001 11:27'!\\ndrag: event\\n\\n\\tdragSelector ifNotNil: [clickClient perform: dragSelector with: event]! !\\n\\n!MouseClickState methodsFor: 'event handling' stamp: 'nk 7/26/2004 10:21'!\\nhandleEvent: evt from: aHand\\n\\t\\\"Process the given mouse event to detect a click, double-click, or drag.\\n\\tReturn true if the event should be processed by the sender, false if it shouldn't.\\n\\tNOTE: This method heavily relies on getting *all* mouse button events.\\\"\\n\\t| localEvt timedOut isDrag |\\n\\ttimedOut _ (evt timeStamp - firstClickTime) > dblClickTime.\\n\\tlocalEvt _ evt transformedBy: (clickClient transformedFrom: aHand owner).\\n\\tisDrag _ (localEvt position - firstClickDown position) r > dragThreshold.\\n\\tclickState == #firstClickDown ifTrue: [\\n\\t\\t\\\"Careful here - if we had a slow cycle we may have a timedOut mouseUp event\\\"\\n\\t\\t(timedOut and:[localEvt isMouseUp not]) ifTrue:[\\n\\t\\t\\t\\\"timeout before #mouseUp -> keep waiting for drag if requested\\\"\\n\\t\\t\\tclickState _ #firstClickTimedOut.\\n\\t\\t\\tdragSelector ifNil:[\\n\\t\\t\\t\\taHand resetClickState.\\n\\t\\t\\t\\tself doubleClickTimeout; click \\\"***\\\"].\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseUp ifTrue:[\\n\\n\\t\\t\\t(timedOut or:[dblClickSelector isNil]) ifTrue:[\\n\\t\\t\\t\\tself click.\\n\\t\\t\\t\\taHand resetClickState.\\n\\t\\t\\t\\t^true].\\n\\t\\t\\t\\\"Otherwise transfer to #firstClickUp\\\"\\n\\t\\t\\tfirstClickUp _ evt copy.\\n\\t\\t\\tclickState _ #firstClickUp.\\n\\t\\t\\t\\\"If timedOut or the client's not interested in dbl clicks get outta here\\\"\\n\\t\\t\\tself click.\\n\\t\\t\\taHand handleEvent: firstClickUp.\\n\\t\\t\\t^false].\\n\\t\\tisDrag ifTrue:[\\\"drag start\\\"\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tdragSelector \\\"If no drag selector send #click instead\\\"\\n\\t\\t\\t\\tifNil: [self click]\\n\\t\\t\\t\\tifNotNil: [self drag: firstClickDown].\\n\\t\\t\\t^true].\\n\\t\\t^false].\\n\\n\\tclickState == #firstClickTimedOut ifTrue:[\\n\\t\\tlocalEvt isMouseUp ifTrue:[\\\"neither drag nor double click\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout; click. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tisDrag ifTrue:[\\\"drag start\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout; drag: firstClickDown. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\t^false].\\n\\n\\tclickState = #firstClickUp ifTrue:[\\n\\t\\t(timedOut) ifTrue:[\\n\\t\\t\\t\\\"timed out after mouseUp - signal timeout and pass the event\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseDown ifTrue:[\\\"double click\\\"\\n\\t\\t\\tclickState _ #secondClickDown.\\n\\t\\t\\t^false]].\\n\\n\\tclickState == #secondClickDown ifTrue: [\\n\\t\\ttimedOut ifTrue:[\\n\\t\\t\\t\\\"timed out after second mouseDown - pass event after signaling timeout\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\t^true].\\n\\t\\tisDrag ifTrue: [\\\"drag start\\\"\\n\\t\\t\\tself doubleClickTimeout. \\\"***\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tdragSelector \\\"If no drag selector send #click instead\\\"\\n\\t\\t\\t\\tifNil: [self click]\\n\\t\\t\\t\\tifNotNil: [self drag: firstClickDown].\\n\\t\\t\\t^true].\\n\\t\\tlocalEvt isMouseUp ifTrue: [\\\"double click\\\"\\n\\t\\t\\taHand resetClickState.\\n\\t\\t\\tself doubleClick.\\n\\t\\t\\t^false]\\n\\t].\\n\\n\\t^true\\n! !\\n\\n\\n!MouseClickState methodsFor: 'initialize' stamp: 'jcg 9/21/2001 13:08'!\\nclient: aMorph click: aClickSelector dblClick: aDblClickSelector dblClickTime: timeOut dblClickTimeout: aDblClickTimeoutSelector drag: aDragSelector threshold: aNumber event: firstClickEvent\\n\\tclickClient _ aMorph.\\n\\tclickSelector _ aClickSelector.\\n\\tdblClickSelector _ aDblClickSelector.\\n\\tdblClickTime _ timeOut.\\n\\tdblClickTimeoutSelector _ aDblClickTimeoutSelector.\\n\\tdragSelector _ aDragSelector.\\n\\tdragThreshold _ aNumber.\\n\\tfirstClickDown _ firstClickEvent.\\n\\tfirstClickTime _ firstClickEvent timeStamp.\\n\\tclickState _ #firstClickDown.! !\\nUserInputEvent subclass: #MouseEvent\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 22:51'!\\ncursorPoint\\n\\t\\\"Answer the location of the cursor's hotspot when this event occured.\\\"\\n\\n\\t^ position! !\\n\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nanyButtonPressed\\n\\t\\\"Answer true if any mouse button is being pressed.\\\"\\n\\n\\t^ buttons anyMask: self class anyButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nblueButtonPressed\\n\\t\\\"Answer true if the blue mouse button is being pressed. This is the third mouse button or cmd+click on the Mac.\\\"\\n\\n\\t^ buttons anyMask: self class blueButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nredButtonPressed\\n\\t\\\"Answer true if the red mouse button is being pressed. This is the first mouse button.\\\"\\n\\n\\t^ buttons anyMask: self class redButton! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'ar 9/15/2000 22:51'!\\ntargetPoint\\n\\t\\\"Answer the location of the cursor's hotspot, adjusted by the offset\\n\\tof the last mouseDown relative to the recipient morph.\\\"\\n\\n\\t^ position - source targetOffset! !\\n\\n!MouseEvent methodsFor: 'button state' stamp: 'NS 5/19/2003 15:17'!\\nyellowButtonPressed\\n\\t\\\"Answer true if the yellow mouse button is being pressed. This is the second mouse button or option+click on the Mac.\\\"\\n\\n\\t^ buttons anyMask: self class yellowButton! !\\n\\n\\n!MouseEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:50'!\\n= aMorphicEvent\\n\\tsuper = aMorphicEvent ifFalse:[^false].\\n\\tposition = aMorphicEvent position ifFalse: [^ false].\\n\\tbuttons = aMorphicEvent buttons ifFalse: [^ false].\\n\\t^ true\\n! !\\n\\n!MouseEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:47'!\\nhash\\n\\t^ position hash + buttons hash! !\\n\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/10/2000 21:17'!\\nasMouseEnter\\n\\t^self clone setType: #mouseEnter! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/10/2000 21:17'!\\nasMouseLeave\\n\\t^self clone setType: #mouseLeave! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 10/6/2000 18:59'!\\nasMouseMove\\n\\t\\\"Convert the receiver into a mouse move\\\"\\n\\t^MouseMoveEvent new setType: #mouseMove startPoint: position endPoint: position trail: {position. position} buttons: buttons hand: source stamp: Time millisecondClockValue.! !\\n\\n!MouseEvent methodsFor: 'converting' stamp: 'ar 9/25/2000 14:29'!\\nasMouseOver\\n\\t\\\"Convert the receiver into a mouse over event\\\"\\n\\t^MouseEvent new setType: #mouseOver position: position buttons: buttons hand: source! !\\n\\n\\n!MouseEvent methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:15'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseOver ifTrue:[^anObject handleMouseOver: self].\\n\\ttype == #mouseEnter ifTrue:[^anObject handleMouseEnter: self].\\n\\ttype == #mouseLeave ifTrue:[^anObject handleMouseLeave: self].\\n\\t^super sentTo: anObject.! !\\n\\n\\n!MouseEvent methodsFor: 'initialize' stamp: 'ar 10/25/2000 22:08'!\\ntype: eventType readFrom: aStream\\n\\t| x y |\\n\\ttype _ eventType.\\n\\ttimeStamp _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\tbuttons _ Integer readFrom: aStream.\\n\\tposition _ x@y.\\n! !\\n\\n\\n!MouseEvent methodsFor: 'printing' stamp: 'ar 10/7/2000 22:01'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $[.\\n\\taStream nextPutAll: self cursorPoint printString; space.\\n\\taStream nextPutAll: type; space.\\n\\taStream nextPutAll: self modifierString.\\n\\taStream nextPutAll: self buttonString.\\n\\taStream nextPutAll: timeStamp printString.\\n\\taStream nextPut: $].! !\\n\\n!MouseEvent methodsFor: 'printing' stamp: 'ar 10/25/2000 22:09'!\\nstoreOn: aStream\\n\\n\\taStream nextPutAll: type.\\n\\taStream space.\\n\\tself timeStamp storeOn: aStream.\\n\\taStream space.\\n\\tposition x storeOn: aStream.\\n\\taStream space.\\n\\tposition y storeOn: aStream.\\n\\taStream space.\\n\\tbuttons storeOn: aStream.! !\\n\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 10/5/2000 19:43'!\\nisDraggingEvent\\n\\tsource ifNil:[^false].\\n\\tsource hasSubmorphs ifTrue:[^true].\\n\\tself anyButtonPressed ifTrue:[^true].\\n\\t^false! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:30'!\\nisMouse\\n\\t^true! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseDown\\n\\t^self type == #mouseDown! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseEnter\\n\\t^self type == #mouseEnter! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseLeave\\n\\t^self type == #mouseLeave! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseMove\\n\\t^self type == #mouseMove! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 15:32'!\\nisMouseUp\\n\\t^self type == #mouseUp! !\\n\\n!MouseEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:29'!\\nisMove\\n\\t^false! !\\n\\n\\n!MouseEvent methodsFor: 'private' stamp: 'ar 10/10/2000 21:15'!\\nsetType: aSymbol\\n\\t\\\"For quick conversion between event types\\\"\\n\\ttype _ aSymbol.! !\\n\\n!MouseEvent methodsFor: 'private' stamp: 'ar 9/15/2000 22:53'!\\nsetType: evtType position: evtPos buttons: evtButtons hand: evtHand\\n\\ttype _ evtType.\\n\\tposition _ evtPos.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMouseEvent class\\n\\tinstanceVariableNames: ''!\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nanyButton\\n\\t^ 7! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nblueButton\\n\\t^ 1! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nredButton\\n\\t^ 4! !\\n\\n!MouseEvent class methodsFor: 'constants' stamp: 'NS 5/19/2003 15:16'!\\nyellowButton\\n\\t^ 2! !\\nController subclass: #MouseMenuController\\n\\tinstanceVariableNames: 'redButtonMenu redButtonMessages'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Kernel-Remnants'!\\n!MouseMenuController commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:28'!\\ncontrolActivity\\n\\t\\\"Refer to the comment in Controller|controlActivity.\\\"\\n\\t| cursorPoint |\\n\\tcursorPoint _ sensor cursorPoint.\\n\\tsuper controlActivity.\\n\\t(cursorPoint = sensor cursorPoint and: [self viewHasCursor])\\n\\t\\tifTrue: \\n\\t\\t\\t[sensor redButtonPressed ifTrue: [^ self redButtonActivity].\\n\\t\\t\\tsensor yellowButtonPressed ifTrue: [^ self yellowButtonActivity].\\n\\t\\t\\tsensor blueButtonPressed ifTrue: [^ self blueButtonActivity]]! !\\n\\n!MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 11:24'!\\nisControlActive \\n\\t\\\"In contrast to class Controller, only blue button but not yellow button\\n\\tevents will end the receiver's control loop.\\\"\\n\\n\\t^ self viewHasCursor and: [sensor blueButtonPressed not]! !\\n\\n\\n!MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'!\\nrelease\\n\\tsuper release.\\n\\tredButtonMenu release! !\\n\\n!MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'!\\nreset\\n\\t\\\"Eliminate references to all mouse button menus.\\\"\\n\\n\\tredButtonMenu _ nil.\\n\\tredButtonMessages _ nil! !\\n\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 15:01'!\\nblueButtonActivity\\n\\t\\\"This normally opens the window menu. It is a no-op here\\n\\tas only the StandardSystemController deals with that kind\\n\\tof menus.\\\"! !\\n\\n!MouseMenuController methodsFor: 'menu messages'!\\nperformMenuMessage: aSelector\\n\\t\\\"Perform a menu command by sending self the message aSelector.\\n\\t Default does nothing special.\\\"\\n\\n\\t^self perform: aSelector! !\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:56'!\\nredButtonActivity\\n\\t\\\"Determine which item in the red button pop-up menu is selected. If one \\n\\tis selected, then send the corresponding message to the object designated \\n\\tas the menu message receiver.\\\"\\n\\n\\t| index |\\n\\tredButtonMenu ~~ nil\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ redButtonMenu startUp.\\n\\t\\t\\tindex ~= 0 \\n\\t\\t\\t\\tifTrue: [self perform: (redButtonMessages at: index)]]\\n\\t\\tifFalse: [super controlActivity]! !\\n\\n!MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:59'!\\nyellowButtonActivity\\n\\t\\\"This normally opens a popup menu. Determine the selected\\n\\titem and, if one is selected, then send the corresponding message\\n\\tto either the model or the receiver.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: sensor leftShiftDown! !\\n\\n\\n!MouseMenuController methodsFor: 'menu setup'!\\nredButtonMenu: aSystemMenu redButtonMessages: anArray \\n\\t\\\"Initialize the pop-up menu that should appear when the user presses the \\n\\tred mouse button to be aSystemMenu. The corresponding messages that \\n\\tshould be sent are listed in the array, anArray.\\\"\\n\\n\\tredButtonMenu release.\\n\\tredButtonMenu _ aSystemMenu.\\n\\tredButtonMessages _ anArray! !\\n\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:36'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t^ view getMenu: shiftKeyState! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 2/17/2002 04:35'!\\npluggableYellowButtonActivity: shiftKeyState\\n\\t\\\"Invoke the model's popup menu.\\\"\\n\\n\\t| menu |\\n\\t(menu _ self getPluggableYellowButtonMenu: shiftKeyState)\\n\\t\\tifNil:\\n\\t\\t\\t[sensor waitNoButton]\\n\\t\\tifNotNil:\\n\\t\\t\\t[self terminateAndInitializeAround:\\n\\t\\t\\t\\t[menu invokeOn: model orSendTo: self]]! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 3/22/2001 12:03'!\\nshiftedTextPaneMenuRequest\\n\\t\\\"The user chose the more... branch from the text-pane menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: true! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'!\\nshiftedYellowButtonActivity\\n\\t\\\"Invoke the model's special popup menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: true! !\\n\\n!MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'!\\nunshiftedYellowButtonActivity\\n\\t\\\"Invoke the model's normal popup menu.\\\"\\n\\n\\t^ self pluggableYellowButtonActivity: false! !\\nMouseEvent subclass: #MouseMoveEvent\\n\\tinstanceVariableNames: 'startPoint trail'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 9/15/2000 22:51'!\\nendPoint\\n\\t\\\"Return the point where the movement ended.\\\"\\n\\t^position! !\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 9/13/2000 16:25'!\\nstartPoint\\n\\t\\\"Return the point where the movement started.\\\"\\n\\t^startPoint! !\\n\\n!MouseMoveEvent methodsFor: 'accessing' stamp: 'ar 10/24/2000 16:33'!\\ntrail\\n\\t\\\"Return any immediate points that have been assembled along the move\\\"\\n\\t^trail ifNil:[#()]! !\\n\\n\\n!MouseMoveEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:49'!\\n= aMorphicEvent\\n\\tsuper = aMorphicEvent ifFalse:[^false].\\n\\tposition = aMorphicEvent position ifFalse: [^ false].\\n\\tstartPoint = aMorphicEvent startPoint ifFalse: [^ false].\\n\\tbuttons = aMorphicEvent buttons ifFalse: [^ false].\\n\\t^ true\\n! !\\n\\n!MouseMoveEvent methodsFor: 'comparing' stamp: 'ar 9/15/2000 22:49'!\\nhash\\n\\t^ position hash + startPoint hash + buttons hash! !\\n\\n\\n!MouseMoveEvent methodsFor: 'dispatching' stamp: 'ar 10/10/2000 21:15'!\\nsentTo: anObject\\n\\t\\\"Dispatch the receiver into anObject\\\"\\n\\ttype == #mouseMove ifTrue:[^anObject handleMouseMove: self].\\n\\t^super sentTo: anObject.\\n! !\\n\\n\\n!MouseMoveEvent methodsFor: 'initialize' stamp: 'ar 10/24/2000 16:31'!\\ntype: eventType readFrom: aStream\\n\\t| x y |\\n\\tsuper type: eventType readFrom: aStream.\\n\\taStream skip: 1.\\n\\tx _ Integer readFrom: aStream.\\n\\taStream skip: 1.\\n\\ty _ Integer readFrom: aStream.\\n\\tstartPoint _ x@y.! !\\n\\n\\n!MouseMoveEvent methodsFor: 'printing' stamp: 'ar 10/7/2000 22:00'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $[.\\n\\taStream nextPutAll: self startPoint printString; space.\\n\\taStream nextPutAll: self endPoint printString; space.\\n\\taStream nextPutAll: self type; space.\\n\\taStream nextPutAll: self modifierString.\\n\\taStream nextPutAll: self buttonString.\\n\\taStream nextPutAll: timeStamp printString.\\n\\taStream nextPut: $].! !\\n\\n!MouseMoveEvent methodsFor: 'printing' stamp: 'ar 10/24/2000 16:30'!\\nstoreOn: aStream\\n\\tsuper storeOn: aStream.\\n\\taStream space.\\n\\tself startPoint x storeOn: aStream.\\n\\taStream space.\\n\\tself startPoint y storeOn: aStream.\\n\\taStream space.\\n\\t\\\"trail storeOn: aStream.\\\"! !\\n\\n\\n!MouseMoveEvent methodsFor: 'testing' stamp: 'ar 9/13/2000 19:29'!\\nisMove\\n\\t^true! !\\n\\n\\n!MouseMoveEvent methodsFor: 'transforming' stamp: 'ar 9/15/2000 22:52'!\\ntransformBy: aMorphicTransform\\n\\t\\\"Transform the receiver into a local coordinate system.\\\"\\n\\tposition _ aMorphicTransform globalPointToLocal: position.\\n\\tstartPoint _ aMorphicTransform globalPointToLocal: startPoint.! !\\n\\n!MouseMoveEvent methodsFor: 'transforming' stamp: 'ar 9/15/2000 22:52'!\\ntranslateBy: delta\\n\\t\\\"add delta to cursorPoint, and return the new event\\\"\\n\\tposition _ position + delta.\\n\\tstartPoint _ startPoint + delta.! !\\n\\n\\n!MouseMoveEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'dgd 2/22/2003 19:01'!\\ndecodeFromStringArray: array \\n\\t\\\"decode the receiver from an array of strings\\\"\\n\\n\\ttype := array first asSymbol.\\n\\tposition := CanvasDecoder decodePoint: (array second).\\n\\tbuttons := CanvasDecoder decodeInteger: (array third).\\n\\tstartPoint := CanvasDecoder decodePoint: (array fourth)! !\\n\\n!MouseMoveEvent methodsFor: '*nebraska-*nebraska-Morphic-Remote' stamp: 'ar 10/25/2000 23:25'!\\nencodedAsStringArray\\n\\t\\\"encode the receiver into an array of strings, such that it can be retrieved via the fromStringArray: class method\\\"\\n\\t^{\\n\\t\\ttype.\\n\\t\\tCanvasEncoder encodePoint: position.\\n\\t\\tCanvasEncoder encodeInteger: buttons.\\n\\t\\tCanvasEncoder encodePoint: startPoint.\\n\\t}! !\\n\\n\\n!MouseMoveEvent methodsFor: 'private' stamp: 'ar 10/5/2000 23:55'!\\nsetType: evtType startPoint: evtStart endPoint: evtEnd trail: evtTrail buttons: evtButtons hand: evtHand stamp: stamp\\n\\ttype _ evtType.\\n\\tstartPoint _ evtStart.\\n\\tposition _ evtEnd.\\n\\ttrail _ evtTrail.\\n\\tbuttons _ evtButtons.\\n\\tsource _ evtHand.\\n\\twasHandled _ false.\\n\\ttimeStamp _ stamp.! !\\nObject subclass: #MouseOverHandler\\n\\tinstanceVariableNames: 'mouseOverMorphs enteredMorphs overMorphs leftMorphs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!MouseOverHandler methodsFor: 'event handling' stamp: 'ar 9/28/2000 18:52'!\\nnoticeMouseOver: aMorph event: anEvent\\n\\t\\\"Remember that the mouse is currently over some morph\\\"\\n\\t(leftMorphs includes: aMorph) \\n\\t\\tifTrue:[leftMorphs remove: aMorph]\\n\\t\\tifFalse:[enteredMorphs nextPut: aMorph].\\n\\toverMorphs nextPut: aMorph.\\n! !\\n\\n!MouseOverHandler methodsFor: 'event handling' stamp: 'dgd 2/21/2003 23:00'!\\nprocessMouseOver: anEvent \\n\\t\\\"Re-establish the z-order for all morphs wrt the given event\\\"\\n\\n\\t| hand localEvt focus evt |\\n\\thand := anEvent hand.\\n\\tleftMorphs := mouseOverMorphs asIdentitySet.\\n\\t\\\"Assume some coherence for the number of objects in over list\\\"\\n\\toverMorphs := WriteStream on: (Array new: leftMorphs size).\\n\\tenteredMorphs := WriteStream on: #().\\n\\t\\\"Now go looking for eventual mouse overs\\\"\\n\\thand handleEvent: anEvent asMouseOver.\\n\\t\\\"Get out early if there's no change\\\"\\n\\t(leftMorphs isEmpty and: [enteredMorphs position = 0]) \\n\\t\\tifTrue: [^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tfocus := hand mouseFocus.\\n\\t\\\"Send #mouseLeave as appropriate\\\"\\n\\tevt := anEvent asMouseLeave.\\n\\t\\\"Keep the order of the left morphs by recreating it from the mouseOverMorphs\\\"\\n\\tleftMorphs size > 1 \\n\\t\\tifTrue: [leftMorphs := mouseOverMorphs select: [:m | leftMorphs includes: m]].\\n\\tleftMorphs do: \\n\\t\\t\\t[:m | \\n\\t\\t\\t(m == focus or: [m hasOwner: focus]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[localEvt := evt transformedBy: (m transformedFrom: hand).\\n\\t\\t\\t\\t\\tm handleEvent: localEvt]\\n\\t\\t\\t\\tifFalse: [overMorphs nextPut: m]].\\n\\t\\\"Send #mouseEnter as appropriate\\\"\\n\\tevt := anEvent asMouseEnter.\\n\\tenteredMorphs ifNil: \\n\\t\\t\\t[\\\"inform: was called in handleEvent:\\\"\\n\\n\\t\\t\\t^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tenteredMorphs := enteredMorphs contents.\\n\\tenteredMorphs reverseDo: \\n\\t\\t\\t[:m | \\n\\t\\t\\t(m == focus or: [m hasOwner: focus]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[localEvt := evt transformedBy: (m transformedFrom: hand).\\n\\t\\t\\t\\t\\tm handleEvent: localEvt]].\\n\\t\\\"And remember the over list\\\"\\n\\toverMorphs ifNil: \\n\\t\\t\\t[\\\"inform: was called in handleEvent:\\\"\\n\\n\\t\\t\\t^leftMorphs := enteredMorphs := overMorphs := nil].\\n\\tmouseOverMorphs := overMorphs contents.\\n\\tleftMorphs := enteredMorphs := overMorphs := nil! !\\n\\n\\n!MouseOverHandler methodsFor: 'initialize-release' stamp: 'ar 9/28/2000 17:08'!\\ninitialize\\n\\tmouseOverMorphs _ #().! !\\nMovieClipStartMorph subclass: #MovieClipEndMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieClipEndMorph commentStamp: '<historical>' prior: 0!\\nThe idea is that soon we will show the soundtrack extending between the start cue and the end morph.!\\n\\n\\n!MovieClipEndMorph methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieFileName: movieFileName image: aForm player: aMoviePlayer frameNumber: n\\n\\n\\tmovieClipFileName := movieFileName.\\n\\tself image: aForm frameNumber: n.\\n\\tmoviePlayerMorph := movieClipPlayer := aMoviePlayer.\\n\\tscoreEvent := AmbientEvent new morph: self.\\n! !\\n\\n\\n!MovieClipEndMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:42'!\\nthumbnailHeight\\n\\n\\t^ 30! !\\n\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/26/2000 00:25'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t\\\"Ignored -- all display is done by the starting morph -- see superclass\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/11/2000 23:06'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\tmovieClipPlayer ifNotNil:\\n\\t\\t[\\\"If being shown as a clip, then tell the clipPlayer to stop showing this clip\\\"\\n\\t\\tmovieClipPlayer stopRunning]! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\npauseFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\nresetFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\n\\n!MovieClipEndMorph methodsFor: 'piano rolls' stamp: 'di 10/22/2000 12:43'!\\nresumeFrom: scorePlayer\\n\\n\\t\\\"Ignored\\\"! !\\nMovieFrameSyncMorph subclass: #MovieClipStartMorph\\n\\tinstanceVariableNames: 'movieClipPlayer movieClipFileName soundTrackFileName soundTrackPlayerReady soundTrackMorph soundTrackTimeScale scoreEvent endMorph clipColor colorMorph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieClipStartMorph commentStamp: '<historical>' prior: 0!\\nThis class and its subclasses act to syncronize movie players with the progress of a MIDI score and further background can be found in the comment for MoviePlayerMorph.\\n\\nMovieClipStartMorphs are used where you have a movie clip player plex. You can create such a plex by opening a midi score, spawning a piano roll (by the button of that name), and then choosing 'add movie clip player' from the piano roll menu. Much simpler, you can open a MoviePlayerMorph as a new morph, and then choose 'make a new movie' from its menu. This plex then serves as a central editable score for composing movie clips.\\n\\nTo add a new movie clip to the score, open a movie from the fileList (or as a new morph followed by 'open a movie'). Play or otherwise position the clip to the desired starting position, and then tear off a thumbnail and drop it into the score at the desired time. The starting thumbnail (MovieClipStartMorph) will appear in the score, tied to an endMorph by a colored stripe. The ending time will be chosen based on the total length of the clip, a default starting clip length (200 frames), and possible interference with other clips that follow it.\\n\\nTo reposition a clip, you can pick up its clipStart with halo black handle, and drop it elsewhere. The rest of the clip will follow as best it can. To delete a clip, delete its clipStart. To change the duration of a clip, play the composition up to some point in that clip, and pause it. Then use the controls on the central movie player to move forward or backward to the desired ending frame, and choose 'end clip here' from the player menu.!\\n\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/19/2000 14:27'!\\nendMorph\\n\\n\\t^ endMorph! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: newFrame\\n\\n\\tframeNumber := newFrame! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieClipPlayer: aMoviePlayerMorph\\n\\t\\\"For now, these morphs work both as a sync point in a long movie, and\\n\\tas a cue point for a short clip in a longer score.\\n\\tTo a cue point, this method provides a reference to the clip player.\\\"\\n\\n\\tmovieClipPlayer := aMoviePlayerMorph! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/25/2000 22:02'!\\nrelatedPlayer\\n \\n\\t^ movieClipPlayer! !\\n\\n!MovieClipStartMorph methodsFor: 'access' stamp: 'di 10/19/2000 12:24'!\\nscoreEvent\\n\\t^ scoreEvent! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:46'!\\ncolorMargin\\n\\t\\\"How far the clip span color highlight extends outside the starting clip\\\"\\n\\n\\t^ 5! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncolorMorph\\n\\tcolorMorph ifNotNil: [^ colorMorph].\\n\\n\\t\\\"Make up a morph to highlight the span of this clip.\\\"\\n\\tColorIndex := (ColorIndex ifNil: [0]) + 2 \\\\\\\\ 8 + 1.\\n\\t^ colorMorph := Morph newBounds: (0@0 extent: 9@9) color: ((Color wheel: 8) at: ColorIndex)\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:23'!\\nsoundTrackHeight\\n\\n\\t^ 40! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 10:58'!\\nsoundTrackOnBottom \\\"a local preference during test\\\"\\n\\n\\t^ false! !\\n\\n!MovieClipStartMorph methodsFor: 'drawing' stamp: 'di 10/23/2000 12:32'!\\nthumbnailHeight\\n\\n\\t^ 60! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'dropping/grabbing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\njustDroppedInto: newOwner event: evt\\n\\t| pianoRoll syncMorph |\\n\\t\\\"When dropping this morph into a pianoRoll, add a corresponding\\n\\tevent to the score so that it will always appear when played,\\n\\tin addition to possibly triggering other actions\\\"\\n\\n\\t(newOwner isKindOf: PianoRollScoreMorph)\\n\\tifTrue:\\n\\t\\t[pianoRoll := newOwner.\\n\\t\\tpianoRoll movieClipPlayer ifNil:\\n\\t\\t\\t[\\\"This PianoRoll is not a clip player -- replace me by a SyncMorph\\\"\\n\\t\\t\\tsyncMorph := MovieFrameSyncMorph new\\n\\t\\t\\t\\t\\t\\timage: image\\n\\t\\t\\t\\t\\t\\tplayer: moviePlayerMorph\\n\\t\\t\\t\\t\\t\\tframeNumber: frameNumber.\\n\\t\\t\\tpianoRoll replaceSubmorph: self by: syncMorph.\\n\\t\\t\\t\\\"rewrite to use justDroppedInto:...\\\"\\n\\t\\t\\tpianoRoll score removeAmbientEventWithMorph: self;\\n\\t\\t\\t\\t\\taddAmbientEvent: (scoreEvent\\n\\t\\t\\t\\t\\t\\tmorph: syncMorph;\\n\\t\\t\\t\\t\\t\\ttime: (pianoRoll timeForX: self left)).\\n\\t\\t\\t^ self].\\n\\n\\t\\tself movieClipPlayer: pianoRoll movieClipPlayer.\\n\\t\\tself setTimeInScore: pianoRoll score\\n\\t\\t\\t\\t\\tnear: (pianoRoll timeForX: self left).\\n\\t\\tself endTime > newOwner scorePlayer durationInTicks ifTrue:\\n\\t\\t\\t[newOwner scorePlayer updateDuration]]\\n\\tifFalse:\\n\\t\\t[\\\"Dropped it somewhere else -- delete related morphs\\\"\\n\\t\\tendMorph ifNotNil: [endMorph delete].\\n\\t\\tsoundTrackMorph ifNotNil: [soundTrackMorph delete]].\\n\\n\\tsuper justDroppedInto: newOwner event: evt\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:24'!\\nendTime\\n\\n\\t^ endMorph scoreEvent time! !\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:27'!\\nframeAtTick: time\\n\\t\\\"Return the frame number corresponding to the given tick time\\\"\\n\\n\\t^ frameNumber +\\n\\t\\t((time - self startTime) asFloat\\n\\t\\t\\t/ (self endTime - self startTime)\\n\\t\\t\\t* (endMorph frameNumber - frameNumber)) asInteger! !\\n\\n!MovieClipStartMorph methodsFor: 'events' stamp: 'di 10/22/2000 20:24'!\\nstartTime\\n\\n\\t^ scoreEvent time! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nimage: aForm frameNumber: n\\n\\n\\tself image: (aForm magnifyBy: self thumbnailHeight asFloat / aForm height).\\n\\tframeNumber := n.! !\\n\\n!MovieClipStartMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmovieFileName: movieFileName soundTrackFileName: soundFileName\\n\\t\\t\\timage: aForm player: aMoviePlayer frameNumber: n\\n\\tmovieClipFileName := movieFileName.\\n\\tsoundTrackFileName := soundFileName.\\n\\tself image: aForm frameNumber: n.\\n\\tmoviePlayerMorph := aMoviePlayer.\\n\\tsoundTrackPlayerReady := moviePlayerMorph scorePlayer copy.\\n\\tscoreEvent := AmbientEvent new morph: self.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'dgd 2/22/2003 14:09'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime \\n\\t\\\"This code handles both the start and end morphs.\\\"\\n\\n\\t| startX endX h delta |\\n\\tself startTime > rightTime \\n\\t\\tifTrue: [^self\\t\\\"Start time has not come into view.\\\"].\\n\\tself endTime < leftTime ifTrue: [^self\\t\\\"End time has passed out of view.\\\"].\\n\\tstartX := pianoRoll xForTime: self startTime.\\n\\tendX := pianoRoll xForTime: self endTime.\\n\\th := self colorMargin.\\t\\\"Height of highlight bar over thumbnails.\\\"\\n\\tmorphList add: (self align: self bottomLeft\\n\\t\\t\\t\\twith: startX @ (pianoRoll bottom - pianoRoll borderWidth - h)).\\n\\tmorphList \\n\\t\\tadd: (endMorph align: endMorph bounds rightCenter with: endX @ self center y).\\n\\tmorphList add: (self colorMorph \\n\\t\\t\\t\\tbounds: (self topLeft - (0 @ h) corner: endMorph right @ (self bottom + h))).\\n\\t(soundTrackMorph isNil and: [moviePlayerMorph scorePlayer isNil]) \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Wants a sound track\\\"\\n\\n\\t\\t\\t(soundTrackMorph isNil or: [pianoRoll timeScale ~= soundTrackTimeScale]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Needs a new sound track\\\"\\n\\n\\t\\t\\t\\t\\tself buildSoundTrackMorphFor: pianoRoll].\\n\\t\\t\\tmorphList add: (soundTrackMorph align: soundTrackMorph bottomLeft\\n\\t\\t\\t\\t\\t\\twith: colorMorph topLeft).\\n\\t\\t\\tself soundTrackOnBottom \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[soundTrackMorph align: soundTrackMorph bottomLeft with: self bottomLeft.\\n\\t\\t\\t\\t\\tdelta := 0 @ self soundTrackHeight.\\n\\t\\t\\t\\t\\tself position: self position - delta.\\n\\t\\t\\t\\t\\tendMorph position: endMorph position - delta.\\n\\t\\t\\t\\t\\tcolorMorph position: colorMorph position - delta]]! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'di 10/26/2000 00:09'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"If being shown as a clip, then tell the clipPlayer to start showing this clip\\\"\\n\\tmovieClipPlayer setCueMorph: self.\\n\\tmovieClipPlayer openFileNamed: movieClipFileName\\n\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\tandPlayFrom: frameNumber.\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'dgd 2/22/2003 14:09'!\\nresetFrom: scorePlayer \\n\\t(movieClipPlayer cueMorph isNil \\n\\t\\tor: [self startTime < movieClipPlayer cueMorph startTime]) \\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[movieClipPlayer\\n\\t\\t\\t\\t\\topenFileNamed: movieClipFileName\\n\\t\\t\\t\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\t\\t\\t\\tandPlayFrom: frameNumber;\\n\\t\\t\\t\\t\\tsetCueMorph: self;\\n\\t\\t\\t\\t\\tstep;\\n\\t\\t\\t\\t\\tpauseFrom: scorePlayer]! !\\n\\n!MovieClipStartMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nresumeFrom: scorePlayer\\n\\n\\t| time |\\n\\t\\\"New movie clip style of use.\\\"\\n\\ttime := scorePlayer ticksSinceStart.\\n\\ttime < self startTime ifTrue: [^ self]. \\\"It's not my time yet\\\"\\n\\ttime > self endTime ifTrue: [^ self]. \\\"It's past my time\\\"\\n\\n\\t\\\"The player is starting in the midst of this clip.\\\"\\n\\tmovieClipPlayer openFileNamed: movieClipFileName\\n\\t\\t\\t\\twithScorePlayer: soundTrackPlayerReady copy\\n\\t\\t\\t\\tandPlayFrom: (self frameAtTick: time);\\n\\t\\tsetCueMorph: self.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'submorphs-add/remove' stamp: 'di 10/23/2000 10:24'!\\ndelete\\n\\t(owner isKindOf: PianoRollScoreMorph) ifTrue:\\n\\t\\t[owner score removeAmbientEventWithMorph: self.\\n\\t\\tendMorph ifNotNil: [owner score removeAmbientEventWithMorph: endMorph]].\\n\\tendMorph ifNotNil: [endMorph delete].\\n\\tsoundTrackMorph ifNotNil: [soundTrackMorph delete].\\n\\tcolorMorph ifNotNil: [colorMorph delete].\\n\\tsuper delete.\\n! !\\n\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nbuildSoundTrackMorphFor: pianoRoll\\n\\t| stopTime soundTrackForm startTime samplesPerTick samplesPerMs |\\n\\tsoundTrackTimeScale := pianoRoll timeScale. \\\"pixels per tick\\\"\\n\\tsamplesPerTick := moviePlayerMorph scorePlayer originalSamplingRate \\\"Samples per sec\\\"\\n\\t\\t\\t\\t\\t\\t* pianoRoll scorePlayer secsPerTick. \\\"secs per tick\\\"\\n\\tsamplesPerMs := moviePlayerMorph scorePlayer originalSamplingRate / 1000.0.\\n\\tstartTime := frameNumber * moviePlayerMorph msPerFrame. \\\"ms\\\"\\n\\tstopTime := endMorph frameNumber * moviePlayerMorph msPerFrame.\\n\\tsoundTrackForm := moviePlayerMorph scorePlayer\\n\\t\\tvolumeForm: self soundTrackHeight\\n\\t\\tfrom: (startTime * samplesPerMs) rounded\\n\\t\\tto: (stopTime * samplesPerMs) rounded\\n\\t\\tnSamplesPerPixel: samplesPerTick / soundTrackTimeScale.\\n\\t^ soundTrackMorph := ImageMorph new image: soundTrackForm! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'di 10/29/2000 08:02'!\\nsetEndFrameNumber: frame\\n\\n\\tself setEndFrameNumber: frame tickTime: nil! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetEndFrameNumber: frameOrNil tickTime: timeOrNil\\n\\t\\\"May be called with either time or frame being nil,\\n\\tin which case the other will br computed.\\\"\\n\\n\\t| pianoRoll frame time |\\n\\tpianoRoll := movieClipPlayer pianoRoll.\\n\\tframe := frameOrNil ifNil:\\n\\t\\t[frameNumber + \\n\\t\\t\\t((timeOrNil - self startTime)\\n\\t\\t\\t* (pianoRoll scorePlayer secsPerTick*1000.0)\\n\\t\\t\\t/ moviePlayerMorph msPerFrame) asInteger - 1].\\n\\ttime := timeOrNil ifNil:\\n\\t\\t[self startTime + \\\"in ticks\\\"\\n\\t\\t\\t(pianoRoll scorePlayer ticksForMSecs:\\n\\t\\t\\t(frameOrNil - frameNumber) * moviePlayerMorph msPerFrame)].\\n\\tendMorph ifNil:\\n\\t\\t[endMorph := MovieClipEndMorph new\\n\\t\\t\\tmovieFileName: movieClipFileName\\n\\t\\t\\timage: (moviePlayerMorph pageFormForFrame: frame)\\n\\t\\t\\tplayer: movieClipPlayer\\n\\t\\t\\tframeNumber: frame]\\n\\t\\tifNotNil:\\n\\t\\t[endMorph image: (moviePlayerMorph pageFormForFrame: frame)\\n\\t\\t\\tframeNumber: frame].\\n\\n\\tendMorph scoreEvent time: time.\\n\\tpianoRoll score removeAmbientEventWithMorph: endMorph;\\n\\t\\taddAmbientEvent: endMorph scoreEvent.\\n\\tsoundTrackMorph := nil. \\\"Force it to be recomputed.\\\"\\n\\tpianoRoll rebuildFromScore\\n! !\\n\\n!MovieClipStartMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetTimeInScore: score near: dropTime\\n\\t\\\"Find a time to place this clip that does not overlap other clips.\\n\\tSo, if I start in the middle of another clip, move me to the end of it,\\n\\tand if I start very soon after another clip, put me right at the end.\\n\\tThen, if my end goes beyond the start of another clip, shorten me\\n\\tso I end right before that clip.\\\"\\n\\n\\t| startTime endTime delta endFrame |\\n\\tstartTime := dropTime.\\n\\tendMorph ifNil: [endFrame := moviePlayerMorph frameCount]\\n\\t\\t\\tifNotNil: [endFrame := endMorph frameNumber].\\n\\tendTime := startTime \\\"in ticks\\\"\\n\\t\\t+ (movieClipPlayer pianoRoll scorePlayer ticksForMSecs:\\n\\t\\t\\t(endFrame - frameNumber)\\n\\t\\t\\t* moviePlayerMorph msPerFrame).\\n\\tscore eventMorphsDo:\\n\\t\\t[:m | (m ~~ self and: [m isMemberOf: self class]) ifTrue:\\n\\t\\t\\t\\t[((startTime between: m startTime and: m endTime)\\n\\t\\t\\t\\t\\tor: [startTime between: m endTime and: m endTime+50])\\n\\t\\t\\t\\t\\tifTrue: [\\\"If I start in the middle of another clip, or a little\\n\\t\\t\\t\\t\\t\\t\\tpast its end, move me exactly to the end of it\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelta := (m endTime + 1) - startTime.\\n\\t\\t\\t\\t\\t\\t\\tstartTime := startTime + delta.\\n\\t\\t\\t\\t\\t\\t\\tendTime := endTime + delta].\\n\\t\\t\\t\\t(endTime between: m startTime and: m endTime)\\n\\t\\t\\t\\t\\tifTrue: [\\\"If my end goes overlaps another clip, shorten me so I fit.\\\"\\n\\t\\t\\t\\t\\t\\t\\tendTime := m startTime - 1].\\n\\t\\t\\t\\t]].\\n\\tscoreEvent time: startTime.\\n\\tscore removeAmbientEventWithMorph: self;\\n\\t\\t\\taddAmbientEvent: scoreEvent.\\n\\tself setEndFrameNumber: endFrame tickTime: endTime.\\n! !\\nImageMorph subclass: #MovieFrameSyncMorph\\n\\tinstanceVariableNames: 'moviePlayerMorph frameNumber'\\n\\tclassVariableNames: 'ColorIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MovieFrameSyncMorph commentStamp: '<historical>' prior: 0!\\nThis class and its subclasses act to syncronize movie players with the progress of a MIDI score and further background can be found in the comment for MoviePlayerMorph.\\n\\nThere are two main forms of synchroniztion.\\n\\nMovieFrameSyncMorphs are used where you have a MIDI score open with a piano roll, and a separate MoviePlayer Morph. A MovieFrameSyncMorph can be torn off from the MoviePlayer with a shift-drag gesture or menu command, and can then be dropped into a MIDI score. They are used to start a movie player at a given place in the score, and then to stretch or compress the movie frame rate so that certain frames are synchronized with the corresponding points in the score.\\n\\nMovieClipStartMorphs (q.v.) and MovieClipEndMorphs are used for the other kind of synchronization, namely where you wish to assemble a number of movie clips in a sequence.!\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 8/6/1998 14:13'!\\nframeNumber\\n\\t^ frameNumber! !\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 10/11/2000 21:39'!\\nmoviePlayerMorph\\n \\n\\t^ moviePlayerMorph! !\\n\\n!MovieFrameSyncMorph methodsFor: 'access' stamp: 'di 10/25/2000 22:02'!\\nrelatedPlayer\\n \\n\\t^ moviePlayerMorph! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'dropping/grabbing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\njustDroppedInto: newOwner event: evt \\n\\t| pianoRoll |\\n\\t\\\"When dropping this morph into a pianoRoll, add a corresponding\\n\\tevent to the score so that it will always appear when played,\\n\\tin addition to possibly triggering other actions\\\"\\n\\n\\t(self isMemberOf: MovieFrameSyncMorph) ifFalse:\\n\\t\\t[^ super justDroppedInto: newOwner event: evt].\\n\\n\\t(newOwner isKindOf: PianoRollScoreMorph)\\n\\tifTrue:\\n\\t\\t[\\\"Legacy code for existing sync morphs\\\"\\n\\t\\tpianoRoll := newOwner.\\n\\t\\tpianoRoll score\\n\\t\\t\\tremoveAmbientEventWithMorph: self;\\n\\t\\t\\taddAmbientEvent: (AmbientEvent new\\n\\t\\t\\t\\t\\t\\tmorph: self;\\n\\t\\t\\t\\t\\t\\ttime: (pianoRoll timeForX: self left))].\\n\\n\\tsuper justDroppedInto: newOwner event: evt\\n! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'events' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nnextSyncEventAfter: index inTrack: track\\n\\t| evt |\\n\\tindex to: track size do:\\n\\t\\t[:i | evt := track at: i.\\n\\t\\t((evt morph isMemberOf: self class)\\n\\t\\t\\tand: [evt morph moviePlayerMorph == moviePlayerMorph])\\n\\t\\t\\tifTrue: [^ evt]].\\n\\t^ nil! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nimage: aForm player: aMoviePlayer frameNumber: n\\n\\tself image: aForm.\\n\\tmoviePlayerMorph := aMoviePlayer.\\n\\tframeNumber := n! !\\n\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t| leftX |\\n\\tt > rightTime ifTrue: [^ self \\\"Start time has not come into view.\\\"]. \\n\\tleftX := pianoRoll xForTime: t.\\n\\t(leftX + self width) < pianoRoll left ifTrue: [^ self \\\"End time has passed out of view.\\\"].\\n\\tmorphList add: \\n\\t\\t(self align: self bottomLeft\\n\\t\\t\\twith: leftX @ (pianoRoll bottom - pianoRoll borderWidth)).\\n! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'dgd 2/21/2003 22:58'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick \\n\\t\\\"Set frame number and milliseconds since start in case of drift\\\"\\n\\n\\t| next |\\n\\tmoviePlayerMorph frameNumber: frameNumber\\n\\t\\tmsSinceStart: scorePlayer millisecondsSinceStart.\\n\\n\\t\\\"If there is a later sync point, set the appropriate frame rate until then.\\\"\\n\\t(next := self nextSyncEventAfter: index inTrack: track) isNil \\n\\t\\tifFalse: \\n\\t\\t\\t[moviePlayerMorph msPerFrame: (next time - ticks) * secsPerTick * 1000.0 \\n\\t\\t\\t\\t\\t\\t/ (next morph frameNumber - self frameNumber)]! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'RAA 12/11/2000 22:58'!\\njustDroppedIntoPianoRoll: pianoRoll event: evt\\n\\n\\t\\\"since these morphs handle their own dropping, ignore\\\"! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:03'!\\npauseFrom: scorePlayer\\n\\n\\tself relatedPlayer pauseFrom: scorePlayer! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:02'!\\nresetFrom: scorePlayer\\n\\n\\tself relatedPlayer resetFrom: scorePlayer! !\\n\\n!MovieFrameSyncMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:03'!\\nresumeFrom: scorePlayer\\n\\n\\tself relatedPlayer resumeFrom: scorePlayer! !\\nMorph subclass: #MovieMorph\\n\\tinstanceVariableNames: 'playMode msecsPerFrame rotationDegrees scalePoint frameList currentFrameIndex dwellCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic'!\\n\\n!MovieMorph methodsFor: 'accessing'!\\nform\\n\\n\\t^ self currentFrame form\\n! !\\n\\n!MovieMorph methodsFor: 'accessing' stamp: 'jm 7/24/97 15:05'!\\nscalePoint\\n\\n\\t^ scalePoint\\n! !\\n\\n!MovieMorph methodsFor: 'accessing' stamp: 'jm 7/24/97 15:05'!\\nscalePoint: newScalePoint\\n\\n\\t| frame |\\n\\tnewScalePoint ~= scalePoint ifTrue: [\\n\\t\\tself changed.\\n\\t\\tscalePoint _ newScalePoint.\\n\\t\\tframe _ self currentFrame.\\n\\t\\tframe ifNotNil: [frame scalePoint: newScalePoint].\\n\\t\\tself layoutChanged.\\n\\t\\tself changed].\\n! !\\n\\n\\n!MovieMorph methodsFor: 'drawing' stamp: 'dgd 2/22/2003 18:47'!\\ndrawOn: aCanvas \\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\tframe notNil \\n\\t\\tifTrue: [^frame drawOn: aCanvas]\\n\\t\\tifFalse: [^super drawOn: aCanvas]! !\\n\\n\\n!MovieMorph methodsFor: 'geometry testing' stamp: 'dgd 2/22/2003 18:48'!\\ncontainsPoint: p \\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\t^ (frame notNil and: [playMode = #stop]) \\n\\t\\tifTrue: [frame containsPoint: p]\\n\\t\\tifFalse: [super containsPoint: p]! !\\n\\n\\n!MovieMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:28'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 1\\n\\t\\tg: 0\\n\\t\\tb: 1! !\\n\\n!MovieMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:47'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tplayMode _ #stop.\\n\\t\\\"#stop, #playOnce, or #loop\\\"\\n\\tmsecsPerFrame _ 200.\\n\\trotationDegrees _ 0.\\n\\tscalePoint _ 1.0 @ 1.0.\\n\\tframeList _ EmptyArray.\\n\\tcurrentFrameIndex _ 1.\\n\\tdwellCount _ 0! !\\n\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'nk 6/12/2004 09:59'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\t| movies subMenu |\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tframeList size > 1 ifTrue: [\\n\\t\\tsubMenu add: 'repaint' translated action: #editDrawing.\\n\\t\\tsubMenu add: 'set rotation center' translated action: #setRotationCenter.\\n\\t\\tsubMenu add: 'play once' translated action: #playOnce.\\n\\t\\tsubMenu add: 'play loop' translated action: #playLoop.\\n\\t\\tsubMenu add: 'stop playing' translated action: #stopPlaying.\\n\\t\\tcurrentFrameIndex > 1 ifTrue: [\\n\\t\\t\\tsubMenu add: 'previous frame' translated action: #previousFrame].\\n\\t\\tcurrentFrameIndex < frameList size ifTrue: [\\n\\t\\t\\tsubMenu add: 'next frame' translated action: #nextFrame]].\\n\\tsubMenu add: 'extract this frame' translated action: #extractFrame:.\\n\\tmovies _\\n\\t\\t(self world rootMorphsAt: aHandMorph targetOffset)\\n\\t\\t\\tselect: [:m | (m isKindOf: MovieMorph) or:\\n\\t\\t\\t\\t\\t\\t[m isSketchMorph]].\\n\\t(movies size > 1) ifTrue:\\n\\t\\t[subMenu add: 'insert into movie' translated action: #insertIntoMovie:].\\n\\taCustomMenu add: 'movie...' translated subMenu: subMenu\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nadvanceFrame\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [self setFrame: currentFrameIndex + 1]\\n\\t\\tifFalse: [self setFrame: 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 18:47'!\\neditDrawing\\n\\t| frame |\\n\\tframe := self currentFrame.\\n\\tframe notNil \\n\\t\\tifTrue: [frame editDrawingIn: self pasteUpMorph forBackground: false]! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nextractFrame: evt\\n\\n\\t| f |\\n\\tf _ self currentFrame.\\n\\tf ifNil: [^ self].\\n\\tframeList _ frameList copyWithout: f.\\n\\tframeList isEmpty\\n\\t\\tifTrue: [self position: f position]\\n\\t\\tifFalse: [self setFrame: currentFrameIndex].\\n\\tevt hand attachMorph: f.\\n! !\\n\\n!MovieMorph methodsFor: 'menu' stamp: 'nk 6/12/2004 09:59'!\\ninsertIntoMovie: evt\\n\\n\\t| movies aTarget |\\n\\tmovies _\\n\\t\\t(self world rootMorphsAt: evt hand targetOffset)\\n\\t\\t\\tselect: [:m | ((m isKindOf: MovieMorph) or:\\n\\t\\t\\t\\t\\t\\t [m isSketchMorph]) and: [m ~= self]].\\n\\tmovies isEmpty ifTrue: [^ self].\\n\\taTarget _ movies first.\\n\\t(aTarget isSketchMorph) ifTrue:\\n\\t\\t[aTarget _ aTarget replaceSelfWithMovie].\\n\\tmovies first insertFrames: frameList.\\n\\tself delete.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nnextFrame\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [self setFrame: currentFrameIndex + 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nplayLoop\\n\\n\\tplayMode _ #loop.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nplayOnce\\n\\n\\tself setFrame: 1.\\n\\tplayMode _ #playOnce.\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\npreviousFrame\\n\\n\\tcurrentFrameIndex > 1\\n\\t\\tifTrue: [self setFrame: currentFrameIndex - 1].\\n! !\\n\\n!MovieMorph methodsFor: 'menu'!\\nstopPlaying\\n\\n\\tplayMode _ #stop.\\n\\tself setFrame: 1.\\n! !\\n\\n\\n!MovieMorph methodsFor: 'rotate scale and flex'!\\nrotationDegrees\\n\\n\\t^ rotationDegrees\\n! !\\n\\n\\n!MovieMorph methodsFor: 'stepping and presenter'!\\nstep\\n\\n\\tplayMode = #stop ifTrue: [^ self].\\n\\n\\tdwellCount > 0 ifTrue: [\\n\\t\\tdwellCount _ dwellCount - 1.\\n\\t\\t^ self].\\n\\n\\tcurrentFrameIndex < frameList size\\n\\t\\tifTrue: [^ self setFrame: currentFrameIndex + 1].\\n\\n\\tplayMode = #loop\\n\\t\\tifTrue: [self setFrame: 1]\\n\\t\\tifFalse: [playMode _ #stop].\\n! !\\n\\n\\n!MovieMorph methodsFor: 'testing'!\\nstepTime\\n\\n\\t^ msecsPerFrame\\n! !\\n\\n\\n!MovieMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 08:03'!\\ncurrentFrame\\n\\tframeList isEmpty ifTrue: [^nil].\\n currentFrameIndex := currentFrameIndex min: (frameList size).\\n currentFrameIndex := currentFrameIndex max: 1.\\n\\t^frameList at: currentFrameIndex! !\\n\\n!MovieMorph methodsFor: 'private'!\\ninsertFrames: newFrames\\n\\t\\\"Insert the given collection of frames into this movie just after the currentrame.\\\"\\n\\n\\tframeList isEmpty ifTrue: [\\n\\t\\tframeList _ newFrames asArray copy.\\n\\t\\tself setFrame: 1.\\n\\t\\t^ self].\\n\\n\\tframeList _\\n\\t\\tframeList\\n\\t\\t\\tcopyReplaceFrom: currentFrameIndex + 1 \\\"insert before\\\"\\n\\t\\t\\tto: currentFrameIndex\\n\\t\\t\\twith: newFrames.\\n! !\\n\\n!MovieMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 08:08'!\\nsetFrame: newFrameIndex \\n\\t| oldFrame p newFrame |\\n\\toldFrame := self currentFrame.\\n\\toldFrame ifNil: [^self].\\n\\tself changed.\\n\\tp := oldFrame referencePosition.\\n\\tcurrentFrameIndex := newFrameIndex.\\n currentFrameIndex := currentFrameIndex min: (frameList size). \\n\\tcurrentFrameIndex := currentFrameIndex max: 1.\\n\\tnewFrame := frameList at: currentFrameIndex.\\n\\tnewFrame referencePosition: p.\\n\\toldFrame delete.\\n\\tself addMorph: newFrame.\\n\\tdwellCount := newFrame framesToDwell.\\n\\tself layoutChanged.\\n\\tself changed! !\\nBookMorph subclass: #MoviePlayerMorph\\n\\tinstanceVariableNames: 'movieFileName movieFile frameSize frameDepth frameNumber frameCount playDirection msSinceStart msAtStart msAtLastSync frameAtLastSync msPerFrame frameBufferIfScaled soundTrackFileName scorePlayer soundTrackForm soundTrackMorph pianoRoll cueMorph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Player'!\\n!MoviePlayerMorph commentStamp: '<historical>' prior: 0!\\nMoviePlayerMorph plays images from a file using async io. The file format is simple but non-standard (see below).\\n\\nThe heart of the play logic is in the step method. Note that play is driven by a simulated time since start. For a movie with a sound score, this is the millisecondsSinceStart of the score player, whereas a movie by itself gets this from the millisecondClock minus msAtStart.\\n\\nMovie players are designed to be used in three ways\\n\\t1. Select a movie in the file list, 'open as movie', and play it.\\n\\t2. As in (1), but drop thumbnails for various frames into a\\n\\t\\tMIDI piano roll to synchronize video with music.\\n\\t3. Open a MoviePlayerMorph as a 'new morph', and choose\\n\\t\\t'make a new movie' from the menu.\\n\\nIn (1) and (2), a shift-drag is used to 'tear off' a thumbnail reference morph to the currently visible frame of this clips. The thumbnail can then be dropped in a MIDI score player to either syncronize that frame with what point in the music, or to cause that clip to being playing in the shared player of a SqueakMovie plex.\\n\\nWhen making a new movie, an empty score and piano roll are linked to the movie player, as a SqueakMovie plex. You can then open another movie as a clip, and drop a thumbnail morph into the score to start that clip playing at that frame in the shared player. If you pause while playing that clip, you can manually play the clip forward and backward in the current clip. if you stop at a given frame, you can choose 'end clip here' from the shared player menu to shorten or lengthen the clip.\\n\\nClips can be moved by picking up the starting thumbnail (use halo black handle), and dropping them elsewhere. If you try to place one clip in the middle of another, it will slide to the end. If you position one clip close to the end of another, it will sidle up to make them contiguous.\\n\\nIf you wish a soundtrack to be included with a clip, make sure it has been opened in the source clip player before tearing off the starting thumbnail.\\n\\nAbout the .movie file format...\\nThe following code was used to convert 27 files into a movie. They were named\\n\\t'BalloonDrop10fps003.bmp' through 'BalloonDrop10fps081.bmp'\\nincrementing by 003. Each was known to be a 320x240 image in 32-bit BMP format.\\nNote the 27 in the 5th line is the number of frames, = (3 to: 81 by: 3) size.\\n\\n\\t| ps zps f32 out ff |\\n\\tout _ FileStream newFileNamed: 'BalloonDrop10fps.movie'.\\n\\tout binary.\\n\\tff _ Form extent: 320@240 depth: 16.\\n\\t#(22 320 240 16 27 100000) , (7 to: 32)\\n\\t\\tdo: [:i | out nextInt32Put: i].\\n\\t\\t\\n\\t3 to: 81 by: 3 do:\\n\\t\\t[:i | ps _ i printString. zps _ ps padded: #left to: 3 with: $0.\\n\\t\\tf32 _ Form fromFileNamed:\\n\\t\\t\\t'BalloonDrop10fps' , zps , '.bmp'.\\n\\t\\tf32 displayOn: ff at: 0@0. \\\"Convert down to 16 bits\\\"\\n\\t\\tff display; writeOnMovie: out].\\n\\tout close.\\n!\\n\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/26/2000 00:18'!\\ncueMorph\\n\\t^ cueMorph! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/4/2000 17:19'!\\nfileName\\n\\t^ movieFileName! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/22/2000 10:54'!\\nframeCount\\n\\n\\t^ frameCount! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: n\\n\\n\\tframeNumber := n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nframeNumber: n msSinceStart: ms\\n\\t\\\"Set the current frame number, and save the scorePlayer's simulated time for synchronization.\\\"\\n\\n\\tframeAtLastSync := n.\\n\\tmsAtLastSync := ms.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/19/2000 16:31'!\\nmsPerFrame\\n\\t^ msPerFrame! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmsPerFrame: n\\n\\t\\\"Set a new frame rate, base on, eg, score synchronization info.\\\"\\n\\n\\tmsPerFrame := n.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npageFormForFrame: frameNo\\n\\n\\t| f form oldFrame |\\noldFrame := frameNumber.\\nself goToPage: frameNo.\\nform := currentPage image deepCopy.\\nself goToPage: oldFrame.\\ntrue ifTrue: [^ form].\\n\\n\\tf := FileStream readOnlyFileNamed: movieFileName.\\n\\tform := Form extent: frameSize depth: frameDepth.\\n\\n\\t\\\"For some weird reason, the next line does not work...\\\"\\n\\tf position: (self filePosForFrameNo: frameNo).\\n\\t\\\"... but this line was found empirically to work instead.\\\"\\n\\tf position: (128 + ((frameNo-1)*(form bits size*4+4)) + 4).\\n\\n\\tf nextInto: form bits.\\n\\tf close.\\n\\t^ form! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/15/2000 19:15'!\\nrelativePosition\\n\\n\\t^ frameNumber asFloat / frameCount! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/11/2000 12:13'!\\nscorePlayer\\n\\n\\t^ scorePlayer! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nscorePlayer: aScorePlayer\\n\\n\\tscorePlayer := aScorePlayer! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetCueMorph: aMorph\\n\\tcueMorph := aMorph\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'access' stamp: 'di 10/13/2000 11:51'!\\nsoundTrackFileName\\n\\t^ soundTrackFileName! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'controls and layout' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nshowHideSoundTrack\\n\\n\\tsoundTrackForm ifNotNil:\\n\\t\\t[soundTrackMorph delete.\\n\\t\\t^ soundTrackForm := soundTrackMorph := nil].\\n\\n\\tsoundTrackForm := scorePlayer volumeForm: 20 from: 1 to: scorePlayer samples size nSamplesPerPixel: 250.\\n\\tsoundTrackMorph := ImageMorph new image: (Form extent: 140 @ soundTrackForm height).\\n\\tsoundTrackMorph addMorph:\\n\\t\\t(Morph newBounds: (soundTrackMorph bounds topCenter extent: 1@soundTrackMorph height)\\n\\t\\t\\t\\t\\tcolor: Color red).\\n\\tself addMorph: soundTrackMorph after: currentPage.\\n\\tself layoutChanged.\\n\\tself stepSoundTrack.\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'copying' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nduplicate\\n\\t| dup |\\n\\tplayDirection ~= 0 ifTrue: [self stopPlay].\\n\\tdup := super duplicate.\\n\\tdup scorePlayer: scorePlayer copy. \\\"Share sound track if any.\\\"\\n\\t^ dup duplicateMore startStepping! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'event handling' stamp: 'di 10/16/2000 13:27'!\\nhandlesMouseDown: evt\\n\\t\\\"We use shift drag to 'tear off' a thumbnail\\\"\\n\\n\\tevt shiftPressed ifTrue: [^ true].\\n\\t^ super handlesMouseDown: evt! !\\n\\n!MoviePlayerMorph methodsFor: 'event handling' stamp: 'di 10/16/2000 13:32'!\\nmouseDown: evt\\n\\t\\\"We use shift drag to 'tear off' a thumbnail\\\"\\n\\n\\tevt shiftPressed ifTrue: [^ self makeThumbnailInHand: evt hand].\\n\\t^ super mouseDown: evt\\n\\t\\t! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'geometry' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nextent: newExtent\\n\\n\\t| tlMargin brMargin pageExtent scale fullSizeImage |\\n\\tfullSizeImage := frameBufferIfScaled ifNil: [currentPage image].\\n\\tframeCount ifNil: [^ self]. \\\"Not yet open\\\"\\n\\ttlMargin := currentPage topLeft - self topLeft.\\n\\tbrMargin := self bottomRight - currentPage bottomRight.\\n\\tpageExtent := newExtent - brMargin - tlMargin.\\n\\tscale := pageExtent x asFloat / frameSize x min: pageExtent y asFloat / frameSize y.\\n\\t(scale := scale max: 0.25) > 0.9 ifTrue: [scale := 1.0].\\n\\n\\tpageExtent := (frameSize * scale) rounded.\\n\\tpageExtent = frameSize\\n\\t\\tifTrue: [currentPage image: fullSizeImage.\\n\\t\\t\\t\\tframeBufferIfScaled := nil]\\n\\t\\tifFalse: [currentPage image: (Form extent: pageExtent depth: frameDepth).\\n\\t\\t\\t\\tframeBufferIfScaled := fullSizeImage.\\n\\t\\t\\t\\t(WarpBlt current toForm: currentPage image) sourceForm: fullSizeImage;\\n\\t\\t\\t\\t\\tcombinationRule: 3;\\n\\t\\t\\t\\t\\tcopyQuad: fullSizeImage boundingBox innerCorners\\n\\t\\t\\t\\t\\t\\ttoRect: currentPage image boundingBox].\\n\\t^ self layoutChanged\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'geometry' stamp: 'dgd 2/22/2003 19:01'!\\nposition: newPos \\n\\tsuper position: newPos.\\n\\t(currentPage notNil and: [currentPage left odd]) \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"crude word alignment for depth = 16\\\"\\n\\n\\t\\t\\tsuper position: newPos + (1 @ 0)]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:38'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryLightGray! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nduplicateMore\\n\\t\\\"Duplicate dies not replicate Forms, but MoviePlayers need this.\\\"\\n\\n\\tframeBufferIfScaled := frameBufferIfScaled deepCopy.\\n\\tcurrentPage image: currentPage image deepCopy.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'di 10/8/2000 21:43'!\\nopenFileNamed: fName \\n\\tself pvtOpenFileNamed: fName.\\n\\tself goToPage: 1! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nopenFileNamed: fName withScorePlayer: playerReady andPlayFrom: frameNo\\n\\t\\\"Note: The plan is that the score player (a SampledSound) is already spaced\\n\\tforward to this frame number so it does not need to be reset as would normally\\n\\thappen in startRunning.\\\"\\n\\n\\tself pvtOpenFileNamed: fName.\\n\\tscorePlayer := playerReady.\\n\\tframeNumber := frameNo.\\n\\tframeAtLastSync := frameNo.\\n\\tmsAtLastSync := frameAtLastSync * msPerFrame.\\n\\tself playForward.! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsetInitialState\\n\\tsuper setInitialState.\\n\\\"\\\"\\n\\tself layoutInset: 3.\\n\\tpageSize := frameSize := 200 @ 200.\\n\\tframeDepth := 8.\\n\\tself disableDragNDrop! !\\n\\n!MoviePlayerMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 13:22'!\\nstopSoundTrackIfAny\\n\\tscorePlayer isNil ifTrue: [^self].\\n\\t(scorePlayer isKindOf: SampledSound) \\n\\t\\tifTrue: [scorePlayer endGracefully]\\n\\t\\tifFalse: [scorePlayer := nil]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 13:21'!\\naddSoundTrack\\n\\t| fileName |\\n\\tfileName := Utilities chooseFileWithSuffixFromList: #('.aif' '.wav')\\n\\t\\t\\t\\twithCaption: 'Choose a sound track file'.\\n\\tfileName isNil ifTrue: [^self].\\n\\tsoundTrackFileName := fileName.\\n\\tself tryToShareScoreFor: soundTrackFileName.\\n\\tscorePlayer ifNil: \\n\\t\\t\\t[('*aif' match: fileName) \\n\\t\\t\\t\\tifTrue: [scorePlayer := SampledSound fromAIFFfileNamed: fileName].\\n\\t\\t\\t('*wav' match: fileName) \\n\\t\\t\\t\\tifTrue: [scorePlayer := SampledSound fromWaveFileNamed: fileName]].\\n\\tsoundTrackForm ifNotNil: \\n\\t\\t\\t[\\\"Compute new soundTrack if we're showing it.\\\"\\n\\n\\t\\t\\tself\\n\\t\\t\\t\\tshowHideSoundTrack;\\n\\t\\t\\t\\tshowHideSoundTrack]! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'di 10/19/2000 17:07'!\\nendClipHere\\n\\t\\\"Change set the termination time for this clip via the endMorph\\\"\\n\\n\\tcueMorph ifNil: [^ self].\\n\\tcueMorph setEndFrameNumber: frameNumber\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ninvokeBookMenu\\n\\t\\\"Invoke the book's control panel menu.\\\"\\n\\t| aMenu |\\n\\taMenu := MVCMenuMorph new defaultTarget: self.\\n\\taMenu add:\\t'make a new movie' translated action: #makeAMovie.\\n\\taMenu add:\\t'open movie file' translated action: #openMovieFile.\\n\\taMenu add:\\t'add sound track' translated action: #addSoundTrack.\\n\\taMenu addLine.\\n\\tscorePlayer ifNotNil:\\n\\t\\t[soundTrackForm isNil\\n\\t\\t\\tifTrue: [aMenu add:\\t'show sound track' translated action: #showHideSoundTrack]\\n\\t\\t\\tifFalse: [aMenu add:\\t'hide sound track' translated action: #showHideSoundTrack]].\\n\\taMenu add:\\t'make thumbnail' translated action: #thumbnailForThisPage.\\n\\tcueMorph ifNotNil:\\n\\t\\t[\\\"Should check if piano roll and score already have a start event\\n\\t\\tprior to this time.\\\"\\n\\t\\taMenu add:\\t'end clip here' translated action: #endClipHere].\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmakeAMovie\\n\\t| scoreController score |\\n\\tframeSize := 640@480. frameDepth := 16. self makeMyPage; changed.\\n\\n\\t(score := MIDIScore new initialize) \\\"addAmbientEvent: (AmbientEvent new time: 200*60)\\\".\\n\\tscoreController := ScorePlayerMorph new\\n\\t\\t\\tonScorePlayer: (ScorePlayer onScore: score) title: 'sMovie'.\\n\\tpianoRoll := PianoRollScoreMorph new on: scoreController scorePlayer.\\n\\tself pianoRoll: pianoRoll. \\\"back link\\\"\\n\\tpianoRoll enableDragNDrop;\\n\\t\\tuseRoundedCorners;\\n\\t\\tmovieClipPlayer: self;\\n\\t\\tborderWidth: 2;\\n\\t\\textent: self width @ 120;\\n\\t\\talign: pianoRoll topLeft with: self bottomLeft - (0@2);\\n\\t\\topenInWorld.\\n\\tscoreController extent: self width @ scoreController height;\\n\\t\\talign: scoreController topLeft with: pianoRoll bottomLeft - (0@2);\\n\\t\\topenInWorld.\\n\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nopenMovieFile\\n\\t| fileName |\\n\\tfileName := Utilities chooseFileWithSuffixFromList: #('.movie')\\n\\t\\t\\t\\t\\twithCaption: 'Choose a movie file to open'.\\n\\tfileName ifNotNil:\\n\\t\\t[self openFileNamed: fileName.\\n\\t\\tself showMoreControls]! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nscanBySlider\\n\\t| scrollSlider handle |\\n\\tscrollSlider := SimpleSliderMorph new extent: 150@10;\\n\\t\\tcolor: color; sliderColor: Color gray;\\n\\t\\ttarget: self; actionSelector: #goToRelativePosition:;\\n\\t\\tadjustToValue: self relativePosition.\\n\\t(handle := scrollSlider firstSubmorph) on: #mouseUp send: #delete to: scrollSlider.\\n\\tscrollSlider align: handle center with: self activeHand position.\\n\\tself world addMorph: scrollSlider.\\n\\tself activeHand targetOffset: (handle width // 2) @ 0.\\n\\tself activeHand newMouseFocus: handle! !\\n\\n!MoviePlayerMorph methodsFor: 'menu' stamp: 'di 10/16/2000 13:31'!\\nthumbnailForThisPage\\n\\t\\\"Overridden to make a MovieFrameSyncMorph\\\"\\n\\n\\t^ self makeThumbnailInHand: self activeHand\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'menu commands' stamp: 'di 7/6/1998 19:32'!\\nfirstPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: 1\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'menu commands' stamp: 'di 7/6/1998 14:05'!\\ninsertPage\\n\\t^ self makeMyPage! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'movie clip player' stamp: 'di 10/19/2000 22:02'!\\npianoRoll\\n\\t^ pianoRoll! !\\n\\n!MoviePlayerMorph methodsFor: 'movie clip player' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npianoRoll: aPianoRollScoreMorph\\n\\t\\\"Provides access also to the score and scorePlayer\\\"\\n\\n\\tpianoRoll := aPianoRollScoreMorph\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ngoToPage: i\\n\\tcurrentPage ifNil: [self makeMyPage].\\n\\tframeNumber := i.\\n\\tplayDirection := 0.\\n\\tself startRunning; step. \\\"will stop after first step\\\"\\n\\tsoundTrackMorph ifNotNilDo: [:m | m image fillWhite].\\n\\tself stepSoundTrack.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'di 7/6/1998 19:29'!\\nlastPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: frameCount\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nnextPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: (frameNumber := frameNumber + 1 min: frameCount).\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'navigation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npreviousPage\\n\\tplayDirection = 0 ifFalse: [^ self]. \\\"No-op during play\\\"\\n\\tself goToPage: (frameNumber := frameNumber - 1 max: 1).\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'di 10/16/2000 13:20'!\\nfullControlSpecs\\n\\t^ #(\\t\\n\\t\\t\\t( '\\U00b7'\\t\\tinvokeBookMenu 'Invoke menu')\\n\\t\\t\\t( '<--'\\t\\tfirstPage\\t\\t'Go to first page')\\n\\t\\t\\t( '<<'\\t\\tplayReverse\\t\\t'Play backward')\\n\\t\\t\\t( '<-' \\t\\tpreviousPage\\t'Back one frame')\\n\\t\\t\\t( '| |' \\t\\tstopPlay\\t\\t'Stop playback')\\n\\t\\t\\t( '->'\\t\\tnextPage\\t\\t'Forward one frame')\\n\\t\\t\\t( '>>'\\t\\tplayForward\\t'Play forward')\\n\\t\\t\\t( '-->'\\t\\tlastPage\\t\\t\\t'Go to final page')\\n\\t\\t\\t( '<->'\\t\\tscanBySlider\\t'Scan by slider' 'menu')\\n\\t\\t\\\"Note extra spec 'menu' causes mousedown activation -- see makePageControlsFrom:\\\"\\n\\t)! !\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'di 10/24/2000 16:55'!\\nshowPageControls\\n\\tself showPageControls: self fullControlSpecs.\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'page controls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nshowPageControls: controlSpecs \\n\\t| pageControls |\\n\\tself hidePageControls.\\n\\n\\tpageControls := self makePageControlsFrom: controlSpecs.\\n\\tpageControls borderWidth: 0; layoutInset: 0; extent: pageControls width@14.\\n\\tpageControls setProperty: #pageControl toValue: true.\\n\\tpageControls setNameTo: 'Page Controls'.\\n\\tpageControls eventHandler: (EventHandler new on: #mouseDown send: #move to: self).\\n\\tself addMorphBack: pageControls beSticky! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npauseFrom: player\\n\\n\\tplayDirection := 0.\\n\\tself step.! !\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'di 10/25/2000 22:06'!\\nresetFrom: player\\n\\tself pauseFrom: player.\\n\\tself firstPage! !\\n\\n!MoviePlayerMorph methodsFor: 'piano rolls' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nresumeFrom: player\\n\\tplayDirection ~= 0 ifTrue: [^ self]. \\\"Already running\\\"\\n\\tplayDirection := 1.\\n\\tpianoRoll ifNil:\\n\\t\\t[\\\"Sync movie to score player if not a clip player\\\"\\n\\t\\tscorePlayer := player].\\n\\tself startRunning! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'di 10/16/2000 11:02'!\\ngoToRelativePosition: newPos\\n\\n\\tmovieFile ifNotNil: [^ self].\\n\\tself goToPage: ((newPos*frameCount) asInteger min: frameCount max: 1).\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplayForward\\n\\t(playDirection ~= 0 or: [frameNumber >= frameCount]) ifTrue:\\n\\t\\t[^ self]. \\\"No-op during play or at end\\\"\\n\\tplayDirection := 1.\\n\\tself startRunning! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplayReverse\\n\\t(playDirection ~= 0 or: [frameNumber <= 1]) ifTrue:\\n\\t\\t[^ self]. \\\"No-op during play or at end\\\"\\n\\tplayDirection := -1.\\n\\tself startRunning! !\\n\\n!MoviePlayerMorph methodsFor: 'player control' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstopPlay\\n\\n\\tplayDirection := 0.\\n\\tself step! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'rounding' stamp: 'di 10/22/2000 23:41'!\\nwantsRoundedCorners\\n\\t^ Preferences roundedWindowCorners or: [super wantsRoundedCorners]! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'di 9/5/2000 23:09'!\\nfileByteCountPerFrame\\n\\t\\n\\t^ (frameBufferIfScaled ifNil: [currentPage image]) bits size * 4\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'di 5/27/1999 22:40'!\\nfilePosForFrameNo: frameNo\\n\\t\\n\\t^ 128 + ((frameNo-1)*(4+self fileByteCountPerFrame)) + 4\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'dgd 2/22/2003 13:22'!\\nstartRunning\\n\\t| ms |\\n\\t(frameBufferIfScaled ifNil: [currentPage image]) unhibernate.\\n\\tmovieFile := AsyncFile new \\n\\t\\t\\t\\topen: (FileDirectory default fullNameFor: movieFileName)\\n\\t\\t\\t\\tforWrite: false.\\n\\tmovieFile \\n\\t\\tprimReadStart: movieFile fileHandle\\n\\t\\tfPosition: (self filePosForFrameNo: frameNumber)\\n\\t\\tcount: self fileByteCountPerFrame.\\n\\tscorePlayer isNil \\n\\t\\tifTrue: \\n\\t\\t\\t[ms := Time millisecondClockValue.\\n\\t\\t\\tmsAtStart := ms - ((frameNumber - 1) * msPerFrame).\\n\\t\\t\\tmsAtLastSync := ms - msAtStart]\\n\\t\\tifFalse: \\n\\t\\t\\t[(playDirection > 0 and: [scorePlayer isKindOf: SampledSound]) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[scorePlayer\\n\\t\\t\\t\\t\\t\\treset;\\n\\t\\t\\t\\t\\t\\tplaySilentlyUntil: (frameNumber - 1) * msPerFrame / 1000.0;\\n\\t\\t\\t\\t\\t\\tinitialVolume: 1.0.\\n\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t[scorePlayer resumePlaying.\\n\\t\\t\\t\\t\\tmsAtLastSync := scorePlayer millisecondsSinceStart] \\n\\t\\t\\t\\t\\t\\t\\tforkAt: Processor userInterruptPriority].\\n\\t\\t\\tmsAtLastSync := scorePlayer millisecondsSinceStart].\\n\\tframeAtLastSync := frameNumber! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'dgd 2/22/2003 13:22'!\\nstep\\n\\t\\\"NOTE: The movie player has two modes of play, depending on whether scorePlayer is nil or not. If scorePlayer is nil, then play runs according to the millisecond clock. If scorePlayer is not nil, then the scorePlayer is consulted for synchronization. If the movie is running ahead, then some calls on step will skip their action until the right time. If the movie is running behind, then the frame may advance by more than one to maintain synchronization.\\\"\\n\\n\\t\\\"ALSO: This player operates with overlapped disk i/o. This means that while one frame is being displayed, the next frame in sequence is being read into a disk buffer. The value of frameNumber corresponds to the frame currently visible.\\\"\\n\\n\\t\\\"This code may not work right for playing backwards right now.\\n\\tSingle-step and backwards (dir <= 0) should just run open-loop.\\\"\\n\\n\\t| byteCount simTime ms nextFrameNumber |\\n\\tmovieFile isNil ifTrue: [^self].\\n\\tscorePlayer isNil \\n\\t\\tifTrue: \\n\\t\\t\\t[(ms := Time millisecondClockValue) < msAtStart \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"clock rollover\\\"\\n\\n\\t\\t\\t\\t\\tmsAtStart := ms - (frameNumber * msPerFrame)].\\n\\t\\t\\tsimTime := ms - msAtStart]\\n\\t\\tifFalse: [simTime := scorePlayer millisecondsSinceStart].\\n\\tplayDirection > 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[nextFrameNumber := frameAtLastSync \\n\\t\\t\\t\\t\\t\\t+ ((simTime - msAtLastSync) // msPerFrame).\\n\\t\\t\\tnextFrameNumber = frameNumber \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[((scorePlayer isKindOf: AbstractSound) and: [scorePlayer isPlaying not]) \\n\\t\\t\\t\\t\\t\\tifTrue: [^self stopRunning].\\n\\t\\t\\t\\t\\t^self]]\\n\\t\\tifFalse: \\n\\t\\t\\t[nextFrameNumber := playDirection < 0 \\n\\t\\t\\t\\t\\t\\tifTrue: [frameNumber - 1]\\n\\t\\t\\t\\t\\t\\tifFalse: [frameNumber]].\\n\\tbyteCount := self fileByteCountPerFrame.\\n\\tself stepSoundTrack.\\n\\tmovieFile waitForCompletion.\\n\\tmovieFile \\n\\t\\tprimReadResult: movieFile fileHandle\\n\\t\\tintoBuffer: (frameBufferIfScaled ifNil: [currentPage image]) bits\\n\\t\\tat: 1\\n\\t\\tcount: byteCount // 4.\\n\\tframeBufferIfScaled ifNotNil: \\n\\t\\t\\t[\\\"If this player has been shrunk, then we have to warp to the current page.\\\"\\n\\n\\t\\t\\t(WarpBlt current toForm: currentPage image)\\n\\t\\t\\t\\tsourceForm: frameBufferIfScaled;\\n\\t\\t\\t\\tcombinationRule: 3;\\n\\t\\t\\t\\tcellSize: (playDirection = 0 \\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Use smoothing if just stepping\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t2]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [1]);\\n\\t\\t\\t\\tcopyQuad: frameBufferIfScaled boundingBox innerCorners\\n\\t\\t\\t\\t\\ttoRect: currentPage image boundingBox].\\n\\tcurrentPage changed.\\n\\tframeNumber := nextFrameNumber.\\n\\t(playDirection = 0 or: \\n\\t\\t\\t[(playDirection > 0 and: [frameNumber >= frameCount]) \\n\\t\\t\\t\\tor: [playDirection < 0 and: [frameNumber <= 1]]]) \\n\\t\\tifTrue: [^self stopRunning].\\n\\n\\t\\\"Start the read operation for the next frame...\\\"\\n\\tmovieFile \\n\\t\\tprimReadStart: movieFile fileHandle\\n\\t\\tfPosition: (self filePosForFrameNo: frameNumber)\\n\\t\\tcount: byteCount! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'aoy 2/15/2003 21:45'!\\nstepSoundTrack\\n\\t| x image timeInMillisecs |\\n\\tscorePlayer ifNil: [^self].\\n\\tsoundTrackForm ifNil: [^self].\\n\\ttimeInMillisecs := playDirection = 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Stepping forward or back\\\"\\n\\n\\t\\t\\t (frameNumber - 1) * msPerFrame]\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Driven by sound track\\\"\\n\\n\\t\\t\\t scorePlayer millisecondsSinceStart].\\n\\tx := timeInMillisecs / 1000.0 * scorePlayer originalSamplingRate // 250.\\n\\timage := soundTrackMorph image.\\n\\timage \\n\\t\\tcopy: (image boundingBox translateBy: (x - (image width // 2)) @ 0)\\n\\t\\tfrom: soundTrackForm\\n\\t\\tto: 0 @ 0\\n\\t\\trule: Form over.\\n\\tsoundTrackMorph changed! !\\n\\n!MoviePlayerMorph methodsFor: 'stepping' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstopRunning\\n\\t\\\"Must only be called with no outstanding file read requests...\\\"\\n\\tmovieFile ifNotNil: [movieFile close. movieFile := nil].\\n\\tplayDirection := 0.\\n\\tself stopSoundTrackIfAny\\n! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'testing' stamp: 'di 8/8/1998 11:57'!\\nstepTime\\n\\t^ 0 \\\"step as fast as possible\\\"! !\\n\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmakeMyPage\\n\\n\\tcurrentPage ifNotNil:\\n\\t\\t[(currentPage isMemberOf: ImageMorph)\\n\\t\\t\\tifTrue: [\\\"currentPage is already an ImageMorph.\\\"\\n\\t\\t\\t\\t\\t(currentPage image extent = frameSize\\n\\t\\t\\t\\t\\t\\tand: [currentPage image depth = frameDepth])\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self \\\"page is already properly dimensioned.\\\"].\\n\\t\\t\\t\\t\\t^ currentPage image: (Form extent: frameSize depth: frameDepth)]\\n\\t\\t\\tifFalse: [currentPage releaseCachedState; delete]].\\n\\tcurrentPage := ImageMorph new image: (Form extent: frameSize depth: frameDepth).\\n\\tcurrentPage lock.\\n\\tpages := OrderedCollection with: currentPage.\\n\\tself addMorphFront: currentPage! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'di 10/25/2000 23:01'!\\nmakeThumbnailInHand: aHand\\n\\n\\tscorePlayer ifNotNil:\\n\\t\\t[\\\"Position the soundTrack for this frameNumber\\\"\\n\\t\\tscorePlayer reset; playSilentlyUntil: frameNumber - 1 * msPerFrame / 1000.0].\\n\\n\\taHand attachMorph:\\n\\t\\t(MovieClipStartMorph new\\n\\t\\t\\tmovieFileName: movieFileName\\n\\t\\t\\tsoundTrackFileName: soundTrackFileName\\n\\t\\t\\timage: currentPage image\\n\\t\\t\\tplayer: self\\n\\t\\t\\tframeNumber: frameNumber)\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\npvtOpenFileNamed: fName\\n\\t\\\"Private - open on the movie file iof the given name\\\"\\n\\n\\t| f w h d n m |\\n\\tself stopRunning.\\n\\tfName = movieFileName ifTrue: [^ self]. \\\"No reopen necessary on same file\\\"\\n\\n\\tmovieFileName := fName.\\n\\t\\\"Read movie file parameters from 128-byte header...\\n\\t\\t(records follow as {N=int32, N words}*)\\\"\\n\\tf := (FileStream oldFileNamed: movieFileName) binary.\\n\\t\\tf nextInt32.\\n\\t\\tw := f nextInt32.\\n\\t\\th := f nextInt32.\\n\\t\\td := f nextInt32.\\n\\t\\tn := f nextInt32.\\n\\t\\tm := f nextInt32.\\n\\t\\tf close.\\n\\tpageSize := frameSize := w@h.\\n\\tframeDepth := d.\\n\\tframeCount := n.\\n\\tframeNumber := 1.\\n\\tplayDirection := 0.\\n\\tmsAtLastSync := 0.\\n\\tmsPerFrame := m/1000.0.\\n\\tself makeMyPage.\\n\\t(SmalltalkImage current platformName = 'Mac OS') ifTrue:[\\n\\t\\t(SmalltalkImage current extraVMMemory < self fileByteCountPerFrame) ifTrue:\\n\\t\\t\\t[^ self inform:\\n'Playing movies in Squeak requires that extra memory be allocated\\nfor asynchronous file IO. This particular movie requires a buffer of\\n' ,\\n(self fileByteCountPerFrame printString) , ' bytes, but you only have ' , (SmalltalkImage current extraVMMemory printString) , ' allocated.\\nYou can evaluate ''SmalltalkImage current extraVMMemory'' to check your allocation,\\nand ''SmalltalkImage current extraVMMemory: 485000'' or the like to increase your allocation.\\nNote that raising your allocation in this way only marks your image as\\nneeding this much, so you must then save, quit, and start over again\\nbefore you can run this movie. Good luck.']].\\n! !\\n\\n!MoviePlayerMorph methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ntryToShareScoreFor: fileName\\n\\n\\tscorePlayer := nil.\\n\\tself class allInstancesDo:\\n\\t\\t[:mp | mp == self ifFalse:\\n\\t\\t\\t[mp soundTrackFileName = fileName ifTrue:\\n\\t\\t\\t\\t[\\\"Found this score already open in another player\\n\\t\\t\\t\\t\\t-- return a copy that shares the same sound buffer.\\\"\\n\\t\\t\\t\\tmp scorePlayer ifNotNil: [^ scorePlayer := mp scorePlayer copy reset]]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMoviePlayerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MoviePlayerMorph class methodsFor: 'class initialization' stamp: 'hg 8/3/2000 16:59'!\\ninitialize\\n\\n\\tFileList registerFileReader: self! !\\n\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sd 2/6/2002 21:36'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\n\\t^(suffix = 'movie') | (suffix = '*')\\n\\t\\tifTrue: [ self services]\\n\\t\\tifFalse: [#()]! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'hg 8/3/2000 17:01'!\\nopenAsMovie: fullFileName\\n\\t\\\"Open a MoviePlayerMorph on the given file (must be in .movie format).\\\"\\n \\n\\t(self new openFileNamed: fullFileName) openInWorld! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 01:23'!\\nserviceOpenAsMovie\\n\\t\\\"Answer a service for opening a file as a movie\\\"\\n\\n\\t^ SimpleServiceEntry \\n\\t\\tprovider: self \\n\\t\\tlabel: 'open as movie'\\n\\t\\tselector: #openAsMovie:\\n\\t\\tdescription: 'open file as movie'\\n\\t\\tbuttonLabel: 'open'! !\\n\\n!MoviePlayerMorph class methodsFor: 'fileIn/Out' stamp: 'sw 9/7/2004 18:21'!\\nservices\\n\\t\\\"Formerly: answer a service for opening as a movie. Nowadays... no services\\\"\\n\\n\\t^ #().\\n\\\"\\n\\t^ Array with: self serviceOpenAsMovie\\\"\\n\\n\\t! !\\n\\n\\n!MoviePlayerMorph class methodsFor: 'initialize-release' stamp: 'SD 11/15/2001 22:22'!\\nunload\\n\\n\\tFileList unregisterFileReader: self ! !\\nEllipseMorph subclass: #MovingEyeMorph\\n\\tinstanceVariableNames: 'inner iris'\\n\\tclassVariableNames: 'IrisSize'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n\\n!MovingEyeMorph methodsFor: 'as yet unclassified' stamp: 'yo 2/15/2001 15:24'!\\nirisPos: cp\\n\\n\\t| a b theta x y |\\n\\ttheta _ (cp - self center) theta.\\n\\ta _ inner width // 2.\\n\\tb _ inner height // 2.\\n\\tx _ a * (theta cos).\\n\\ty _ b * (theta sin).\\n\\tiris position: ((x@y) asIntegerPoint) + self center - (iris extent // 2).! !\\n\\n\\n!MovingEyeMorph methodsFor: 'geometry' stamp: 'yo 2/15/2001 15:59'!\\nextent: aPoint\\n\\n\\tsuper extent: aPoint.\\n\\tinner extent: (self extent * ((1.0@1.0)-IrisSize)) asIntegerPoint.\\n\\tiris extent: (self extent * IrisSize) asIntegerPoint.\\n\\tinner position: (self center - (inner extent // 2)) asIntegerPoint.\\n! !\\n\\n\\n!MovingEyeMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:42'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!MovingEyeMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:42'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tinner _ EllipseMorph new.\\n\\tinner color: self color.\\n\\tinner extent: (self extent * (1.0 @ 1.0 - IrisSize)) asIntegerPoint.\\n\\tinner borderColor: self color.\\n\\tinner borderWidth: 0.\\n\\\"\\\"\\n\\tiris _ EllipseMorph new.\\n\\tiris color: Color white.\\n\\tiris extent: (self extent * IrisSize) asIntegerPoint.\\n\\\"\\\"\\n\\tself addMorphCentered: inner.\\n\\tinner addMorphCentered: iris.\\n\\\"\\\"\\n\\tself extent: 26 @ 33! !\\n\\n\\n!MovingEyeMorph methodsFor: 'stepping and presenter' stamp: 'di 2/18/2001 00:10'!\\nstep\\n\\t| cp |\\n\\tcp _ self globalPointToLocal: World primaryHand position.\\n\\t(inner containsPoint: cp)\\n\\t\\tifTrue: [iris position: (cp - (iris extent // 2))]\\n\\t\\tifFalse: [self irisPos: cp].\\n\\tself changed \\\"cover up gribblies if embedded in Flash\\\"! !\\n\\n\\n!MovingEyeMorph methodsFor: 'testing' stamp: 'yo 2/15/2001 15:38'!\\nstepTime\\n\\n\\t^ 100.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMovingEyeMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!MovingEyeMorph class methodsFor: 'class initialization' stamp: 'yo 2/15/2001 16:04'!\\ninitialize\\n\\\"\\n\\tMovingEyeMorph initialize\\n\\\"\\n\\tIrisSize _ (0.42@0.50).! !\\n\\n\\n!MovingEyeMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:51'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'MovingEye'\\n\\t\\tcategories:\\t\\t#('Demo')\\n\\t\\tdocumentation:\\t'An eye which follows the cursor'! !\\nSoundCodec subclass: #MuLawCodec\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DecodingTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!MuLawCodec commentStamp: '<historical>' prior: 0!\\nI represent a mu-law (u-law) codec. I compress sound data by a factor of 2:1 by encoding the most significant 12 bits of each 16-bit sample as a signed, exponentially encoded byte. The idea is to use more resolution for smaller lower sample values. This encoding was developed for the North American phone system and a variant of it, a-law, is a European phone standard. It is a popular sound encoding on Unix platforms (.au files).\\n!\\n\\n\\n!MuLawCodec methodsFor: 'external access' stamp: 'di 2/8/1999 22:28'!\\nuLawDecodeSample: byte\\n\\t\\\"Decode a 16-bit signed sample from 8 bits using uLaw decoding\\\"\\n\\n\\t^ DecodingTable at: byte + 1! !\\n\\n!MuLawCodec methodsFor: 'external access' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuLawEncodeSample: sample\\n\\t\\\"Encode a 16-bit signed sample into 8 bits using uLaw encoding\\\"\\n\\n\\t| s |\\n\\ts := sample // 8. \\\"drop 3 least significant bits\\\"\\n\\ts < 0 ifTrue: [^ (self uLawEncode12Bits: 0-s) + 16r80]\\n\\t\\tifFalse: [^ (self uLawEncode12Bits: s)].\\n! !\\n\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'jm 2/2/1999 09:15'!\\nbytesPerEncodedFrame\\n\\t\\\"Answer the number of bytes required to hold one frame of compressed sound data. Answer zero if this codec produces encoded frames of variable size.\\\"\\n\\n\\t^ 1\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecodeFrames: frameCount from: srcByteArray at: srcIndex into: dstSoundBuffer at: dstIndex\\n\\t\\\"Decode the given number of monophonic frames starting at the given index in the given ByteArray of compressed sound data and storing the decoded samples into the given SoundBuffer starting at the given destination index. Answer a pair containing the number of bytes of compressed data consumed and the number of decompressed samples produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\t| dst |\\n\\tdst := dstIndex.\\n\\tsrcIndex to: srcIndex + frameCount - 1 do: [:src |\\n\\t\\tdstSoundBuffer at: dst put: (DecodingTable at: (srcByteArray at: src) + 1).\\n\\t\\tdst := dst + 1].\\n\\t^ Array with: frameCount with: frameCount\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'di 2/8/1999 22:25'!\\nencodeFrames: frameCount from: srcSoundBuffer at: srcIndex into: dstByteArray at: dstIndex\\n\\t\\\"Encode the given number of frames starting at the given index in the given monophonic SoundBuffer and storing the encoded sound data into the given ByteArray starting at the given destination index. Encode only as many complete frames as will fit into the destination. Answer a pair containing the number of samples consumed and the number of bytes of compressed data produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tsrcIndex to: srcIndex + frameCount - 1 do: [:i |\\n\\t\\tdstByteArray at: i put: (self uLawEncodeSample: (srcSoundBuffer at: i))].\\n\\t^ Array with: frameCount with: frameCount\\n! !\\n\\n!MuLawCodec methodsFor: 'subclass responsibility' stamp: 'jm 2/2/1999 09:11'!\\nsamplesPerFrame\\n\\t\\\"Answer the number of sound samples per compression frame.\\\"\\n\\n\\t^ 1\\n! !\\n\\n\\n!MuLawCodec methodsFor: 'private' stamp: 'di 2/9/1999 13:25'!\\nuLawEncode12Bits: s\\n\\t\\\"Encode a 12-bit unsigned sample (0-4095) into 7 bits using uLaw encoding.\\n\\tThis gets called by a method that scales 16-bit signed integers down to a\\n\\t\\t12-bit magnitude, and then ORs in 16r80 if they were negative.\\n\\tDetail: May get called with s >= 4096, and this works fine.\\\"\\n\\n\\ts < 496 ifTrue: [\\n\\t\\ts < 112 ifTrue: [\\n\\t\\t\\ts < 48 ifTrue: [\\n\\t\\t\\t\\ts < 16\\n\\t\\t\\t\\t\\tifTrue: [^ 16r70 bitOr: (15 - s)]\\n\\t\\t\\t\\t\\tifFalse: [^ 16r60 bitOr: (15 - ((s - 16) bitShift: -1))]].\\n\\t\\t\\t^ 16r50 bitOr: (15 - ((s - 48) bitShift: -2))].\\n\\t\\ts < 240\\n\\t\\t\\tifTrue: [^ 16r40 bitOr: (15 - ((s - 112) bitShift: -3))]\\n\\t\\t\\tifFalse: [^ 16r30 bitOr: (15 - ((s - 240) bitShift: -4))]].\\n\\n\\ts < 2032 ifTrue: [\\n\\t\\ts < 1008\\n\\t\\t\\tifTrue: [^ 16r20 bitOr: (15 - ((s - 496) bitShift: -5))]\\n\\t\\t\\tifFalse: [^ 16r10 bitOr: (15 - ((s - 1008) bitShift: -6))]].\\n\\n\\ts < 4080\\n\\t\\tifTrue: [^ 15 - ((s - 2032) bitShift: -7)]\\n\\t\\tifFalse: [^ 0].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMuLawCodec class\\n\\tinstanceVariableNames: ''!\\n\\n!MuLawCodec class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"Build the 256 entry table to be used to decode 8-bit uLaw-encoded samples.\\\"\\n\\t\\\"MuLawCodec initialize\\\"\\n\\n\\t| encoded codec lastEncodedPos lastEncodedNeg |\\n\\tDecodingTable := Array new: 256.\\n\\tcodec := self new.\\n\\tlastEncodedPos := nil.\\n\\tlastEncodedNeg := nil.\\n\\t4095 to: 0 by: -1 do: [:s |\\n\\t\\tencoded := codec uLawEncode12Bits: s.\\n\\t\\tlastEncodedPos = encoded\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tDecodingTable at: (encoded + 1) put: (s bitShift: 3).\\n\\t\\t\\t\\tlastEncodedPos := encoded].\\n\\t\\tencoded := encoded bitOr: 16r80.\\n\\t\\tlastEncodedNeg = encoded\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tDecodingTable at: (encoded + 1) put: (s bitShift: 3) negated.\\n\\t\\t\\t\\tlastEncodedNeg := encoded]].\\n! !\\nReadWriteStream subclass: #MultiByteBinaryOrTextStream\\n\\tinstanceVariableNames: 'isBinary converter'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n!MultiByteBinaryOrTextStream commentStamp: '<historical>' prior: 0!\\nIt is similar to MultiByteFileStream, but works on in memory stream.!\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:16'!\\nascii\\n\\tisBinary _ false\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:16'!\\nbinary\\n\\tisBinary _ true\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'nk 8/2/2004 17:02'!\\nconverter\\n\\n\\tconverter ifNil: [converter _ self class defaultConverter].\\n\\t^ converter\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 8/7/2003 09:12'!\\nconverter: aConverter\\n\\n\\tconverter _ aConverter.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 13:25'!\\nisBinary\\n\\t^ isBinary! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'accessing' stamp: 'yo 11/11/2002 16:33'!\\ntext\\n\\tisBinary _ false\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:10'!\\nfileInObjectAndCodeForProject\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileInProject. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:46'!\\nfileInProject\\n\\n\\tself setConverterForCodeForProject.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'yo 3/1/2005 06:46'!\\nsetConverterForCodeForProject\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'converting' stamp: 'yo 11/11/2002 13:16'!\\nasBinaryOrTextStream\\n\\n\\t^ self\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 8/17/2004 10:02'!\\nfileIn\\n\\n\\tself setConverterForCode.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 11/11/2002 16:31'!\\nfileInObjectAndCode\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileIn. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'tak 1/12/2005 13:47'!\\nfileOutClass: extraClass andObject: theObject \\n\\tUTF8TextConverter writeBOMOn: self.\\n\\t^ super fileOutClass: extraClass andObject: theObject! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 8/18/2004 09:36'!\\nsetConverterForCode\\n\\n\\t| current |\\n\\tcurrent _ converter saveStateOf: self.\\n\\tself position: 0.\\n\\tself binary.\\n\\t((self next: 3) = (ByteArray with: 16rEF with: 16rBB with: 16rBF)) ifTrue: [\\n\\t\\tself converter: UTF8TextConverter new\\n\\t] ifFalse: [\\n\\t\\tself converter: MacRomanTextConverter new.\\n\\t].\\n\\tconverter restoreStateOf: self with: current.\\n\\tself text.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'fileIn/Out' stamp: 'yo 7/7/2004 09:43'!\\nsetEncoderForSourceCodeNamed: streamName\\n\\n\\t| l |\\n\\tl _ streamName asLowercase.\\n\\\"\\t((l endsWith: FileStream multiCs) or: [\\n\\t\\t(l endsWith: FileStream multiSt) or: [\\n\\t\\t\\t(l endsWith: (FileStream multiSt, '.gz')) or: [\\n\\t\\t\\t\\t(l endsWith: (FileStream multiCs, '.gz'))]]]) ifTrue: [\\n\\t\\t\\t\\t\\tself converter: UTF8TextConverter new.\\n\\t\\t\\t\\t\\t^ self.\\n\\t].\\n\\\"\\n\\t((l endsWith: FileStream cs) or: [\\n\\t\\t(l endsWith: FileStream st) or: [\\n\\t\\t\\t(l endsWith: (FileStream st, '.gz')) or: [\\n\\t\\t\\t\\t(l endsWith: (FileStream cs, '.gz'))]]]) ifTrue: [\\n\\t\\t\\t\\t\\tself converter: MacRomanTextConverter new.\\n\\t\\t\\t\\t\\t^ self.\\n\\t].\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'properties-setting' stamp: 'yo 11/14/2002 13:49'!\\nsetFileTypeToObject\\n\\t\\\"do nothing. We don't have a file type\\\"! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 7/30/2004 06:59'!\\ncontents\\n\\n\\t| ret state |\\n\\tstate _ converter saveStateOf: self.\\n\\tret _ self upToEnd.\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ ret.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:39'!\\nnext\\n\\n\\t| n |\\n\\tn _ self converter nextFromStream: self.\\n\\tn ifNil: [^ nil].\\n\\tisBinary and: [n isCharacter ifTrue: [^ n asciiValue]].\\n\\t^ n.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'ar 4/12/2005 17:34'!\\nnext: anInteger \\n\\n\\t| multiString |\\n\\t\\\"self halt.\\\"\\n\\tself isBinary ifTrue: [^ (super next: anInteger) asByteArray].\\n\\tmultiString _ WideString new: anInteger.\\n\\t1 to: anInteger do: [:index |\\n\\t\\t| character |\\n\\t\\t(character _ self next) ifNotNil: [\\n\\t\\t\\tmultiString at: index put: character\\n\\t\\t] ifNil: [\\n\\t\\t\\tmultiString _ multiString copyFrom: 1 to: index - 1.\\n\\t\\t\\t^ multiString\\n\\t\\t]\\n\\t].\\n\\t^ multiString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:05'!\\nnextDelimited: terminator\\n\\n\\t| out ch pos |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\tpos _ self position.\\n\\tself next = terminator ifFalse: [\\n\\t\\t\\\"absorb initial terminator\\\"\\n\\t\\tself position: pos.\\n\\t].\\n\\t[(ch _ self next) == nil] whileFalse: [\\n\\t\\t(ch = terminator) ifTrue: [\\n\\t\\t\\tself peek = terminator ifTrue: [\\n\\t\\t\\t\\tself next. \\\"skip doubled terminator\\\"\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nnextMatchAll: aColl\\n\\n | save |\\n save _ converter saveStateOf: self.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n converter restoreStateOf: self with: save.\\n ^ false.\\n\\t\\t].\\n\\t].\\n ^ true.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/14/2002 13:54'!\\nnextPut: aCharacter\\n\\n\\taCharacter isInteger ifTrue: [^ super nextPut: aCharacter asCharacter].\\n\\t^ self converter nextPut: aCharacter toStream: self\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nnextPutAll: aCollection\\n\\n\\tself isBinary ifTrue: [\\n\\t\\t^ super nextPutAll: aCollection.\\n\\t].\\n\\taCollection do: [:e | self nextPut: e].\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/14/2002 13:54'!\\npadToEndWith: aChar\\n\\t\\\"We don't have pages, so we are at the end, and don't need to pad.\\\"! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:04'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\n\\t| next pos |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tpos _ self position.\\n\\tnext _ self next.\\n\\tself position: pos.\\n\\t^ next.\\n\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:25'!\\npeekFor: item \\n\\n\\t| next state |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\tstate _ converter saveStateOf: self.\\n\\t(next _ self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ false.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'nk 7/29/2004 12:02'!\\nreset\\n\\n\\tsuper reset.\\n\\tisBinary ifNil: [isBinary _ false].\\n\\tcollection class == ByteArray ifTrue: [\\\"Store as String and convert as needed.\\\"\\n\\t\\tcollection _ collection asString.\\n\\t\\tisBinary _ true].\\n\\n\\tself converter. \\\"ensure that we have a converter.\\\"! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:17'!\\nskipSeparators\\n\\n\\t[self atEnd] whileFalse: [\\n\\t\\tself basicNext isSeparator ifFalse: [\\n\\t\\t\\t^ self position: self position - 1]]\\n\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 12/25/2003 16:04'!\\nskipSeparatorsAndPeekNext\\n\\n\\t\\\"A special function to make nextChunk fast\\\"\\n\\t| peek pos |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tpos _ self position.\\n\\t\\t(peek _ self next) isSeparator ifFalse: [\\n\\t\\t\\tself position: pos.\\n\\t\\t\\t^ peek.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 13:24'!\\nupTo: delim \\n\\n\\t| out ch |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\t[(ch _ self next) isNil] whileFalse: [\\n\\t\\t(ch = delim) ifTrue: [\\n\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'public' stamp: 'yo 11/11/2002 16:17'!\\nupToEnd\\n\\n\\t| newStream element newCollection |\\n\\tnewCollection _ self isBinary\\n\\t\\t\\t\\tifTrue: [ByteArray new: 100]\\n\\t\\t\\t\\tifFalse: [String new: 100].\\n\\tnewStream _ WriteStream on: newCollection.\\n\\t[(element _ self next) notNil]\\n\\t\\twhileTrue: [newStream nextPut: element].\\n\\t^ newStream contents\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private' stamp: 'nk 8/2/2004 17:01'!\\nguessConverter\\n\\t^ (self originalContents includesSubString: (ByteArray withAll: {27. 36}) asString)\\n\\t\\tifTrue: [CompoundTextConverter new]\\n\\t\\tifFalse: [self class defaultConverter ]! !\\n\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 16:01'!\\nbasicNext\\n\\n\\t^ super next \\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'md 10/20/2004 15:32'!\\nbasicNext: anInteger\\n\\n\\t^ super next: anInteger.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNext: n into: aString\\n\\n\\t^ super next: n into: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextInto: aString\\n\\n\\t^ super nextInto: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextPut: char\\n\\n\\t^ super nextPut: char.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicNextPutAll: aString\\n\\n\\t^ super nextPutAll: aString.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPeek\\n\\n\\t^ super peek\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPosition\\n\\n\\t^ super position.\\n! !\\n\\n!MultiByteBinaryOrTextStream methodsFor: 'private basic' stamp: 'yo 11/11/2002 13:21'!\\nbasicPosition: pos\\n\\n\\t^ super position: pos.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiByteBinaryOrTextStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'defaults' stamp: 'yo 2/25/2005 20:04'!\\ndefaultConverter\\n\\t^ Latin1TextConverter new.\\n! !\\n\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'instance creation' stamp: 'ykoubo 9/28/2003 19:59'!\\non: aCollection encoding: encodingName \\n\\t| aTextConverter |\\n\\tencodingName isNil\\n\\t\\tifTrue: [aTextConverter _ TextConverter default]\\n\\t\\tifFalse: [aTextConverter _ TextConverter newForEncoding: encodingName].\\n\\t^ (self on: aCollection)\\n\\t\\tconverter: aTextConverter! !\\n\\n!MultiByteBinaryOrTextStream class methodsFor: 'instance creation' stamp: 'yo 11/23/2003 20:32'!\\nwith: aCollection encoding: encodingName \\n\\t| aTextConverter |\\n\\tencodingName isNil\\n\\t\\tifTrue: [aTextConverter _ TextConverter default]\\n\\t\\tifFalse: [aTextConverter _ TextConverter newForEncoding: encodingName].\\n\\t^ (self with: aCollection)\\n\\t\\tconverter: aTextConverter! !\\nStandardFileStream subclass: #MultiByteFileStream\\n\\tinstanceVariableNames: 'converter lineEndConvention wantsLineEndConversion'\\n\\tclassVariableNames: 'Cr CrLf Lf LineEndDefault LineEndStrings LookAheadCount'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n!MultiByteFileStream commentStamp: '<historical>' prior: 0!\\nThe central class to access the external file. The interface of this object is similar to good old StandardFileStream, but internally it asks the converter, which is a sub-instance of TextConverter, and do the text conversion.\\n\\n It also combined the good old CrLfFileStream. CrLfFileStream class>>new now returns an instance of MultiByteFileStream.\\n\\n There are several pitfalls:\\n\\n * You always have to be careful about the binary/text distinction. In #text mode, it usually interpret the bytes.\\n * A few file pointer operations treat the file as uninterpreted byte no matter what. This means that if you use 'fileStream skip: -1', 'fileStream position: x', etc. in #text mode, the file position can be in the middle of multi byte character. If you want to implement some function similar to #peek for example, call the saveStateOf: and restoreStateOf: methods to be able to get back to the original state.\\n * #lineEndConvention: and #wantsLineEndConversion: (and #binary) can cause some puzzling situation because the inst var lineEndConvention and wantsLineEndConversion are mutated. If you have any suggestions to clean up the protocol, please let me know.!\\n\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:57'!\\nascii\\n\\n\\tsuper ascii.\\n\\tself detectLineEndConvention.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:57'!\\nbinary\\n\\n\\tsuper binary.\\n\\tlineEndConvention _ nil.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/18/2003 15:11'!\\nconverter\\n\\n\\tconverter ifNil: [converter _ TextConverter defaultSystemConverter].\\n\\t^ converter\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/28/2002 11:09'!\\nconverter: aConverter\\n\\n\\tconverter _ aConverter.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 8/6/2003 11:56'!\\nfileInEncodingName: aString\\n\\n\\tself converter: (TextConverter newForEncoding: aString).\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'nk 9/5/2004 12:57'!\\nlineEndConvention\\n\\n\\t^lineEndConvention! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 02:59'!\\nlineEndConvention: aSymbol\\n\\n\\tlineEndConvention _ aSymbol.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'accessing' stamp: 'yo 2/21/2004 04:24'!\\nwantsLineEndConversion: aBoolean\\n\\n\\twantsLineEndConversion _ aBoolean.\\n\\tself detectLineEndConvention.! !\\n\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/24/2004 13:38'!\\nbareNext\\n\\n\\t ^ self converter nextFromStream: self.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 02:56'!\\nconvertStringFromCr: aString \\n\\t| inStream outStream |\\n\\tlineEndConvention ifNil: [^ aString].\\n\\tlineEndConvention == #cr ifTrue: [^ aString].\\n\\tlineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Cr with: Lf].\\n\\t\\\"lineEndConvention == #crlf\\\"\\n\\tinStream _ ReadStream on: aString.\\n\\toutStream _ WriteStream on: (String new: aString size).\\n\\t[inStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[outStream nextPutAll: (inStream upTo: Cr).\\n\\t\\t\\t(inStream atEnd not or: [aString last = Cr])\\n\\t\\t\\t\\tifTrue: [outStream nextPutAll: CrLf]].\\n\\t^ outStream contents! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 02:56'!\\nconvertStringToCr: aString \\n\\t| inStream outStream |\\n\\tlineEndConvention ifNil: [^ aString].\\n\\tlineEndConvention == #cr ifTrue: [^ aString].\\n\\tlineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Lf with: Cr].\\n\\t\\\"lineEndConvention == #crlf\\\"\\n\\tinStream _ ReadStream on: aString.\\n\\toutStream _ WriteStream on: (String new: aString size).\\n\\t[inStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[outStream nextPutAll: (inStream upTo: Cr).\\n\\t\\t\\t(inStream atEnd not or: [aString last = Cr])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[outStream nextPut: Cr.\\n\\t\\t\\t\\t\\tinStream peek = Lf ifTrue: [inStream next]]].\\n\\t^ outStream contents! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'nk 9/5/2004 12:50'!\\ndetectLineEndConvention\\n\\t\\\"Detect the line end convention used in this stream. The result may be either #cr, #lf or #crlf.\\\"\\n\\t| char numRead state |\\n\\tself isBinary ifTrue: [^ self error: 'Line end conventions are not used on binary streams'].\\n\\tself wantsLineEndConversion ifFalse: [^ lineEndConvention _ nil.].\\n\\tself closed ifTrue: [^ lineEndConvention _ LineEndDefault.].\\n\\n\\t\\\"Default if nothing else found\\\"\\n\\tnumRead _ 0.\\n\\tstate _ converter saveStateOf: self.\\n\\tlineEndConvention _ nil.\\n\\t[super atEnd not and: [numRead < LookAheadCount]]\\n\\t\\twhileTrue: \\n\\t\\t\\t[char _ self next.\\n\\t\\t\\tchar = Lf\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[converter restoreStateOf: self with: state.\\n\\t\\t\\t\\t\\t^ lineEndConvention _ #lf].\\n\\t\\t\\tchar = Cr\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self peek = Lf\\n\\t\\t\\t\\t\\t\\tifTrue: [lineEndConvention _ #crlf]\\n\\t\\t\\t\\t\\t\\tifFalse: [lineEndConvention _ #cr].\\n\\t\\t\\t\\t\\tconverter restoreStateOf: self with: state.\\n\\t\\t\\t\\t\\t^ lineEndConvention].\\n\\t\\t\\tnumRead _ numRead + 1].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ lineEndConvention _ LineEndDefault.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'nk 9/5/2004 12:51'!\\ndoConversion\\n\\n\\t^self wantsLineEndConversion and: [ lineEndConvention notNil ]! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/24/2004 13:44'!\\nnext: n innerFor: aString\\n\\n\\t| peekChar state |\\n\\t\\\"if we just read a CR, and the next character is an LF, then skip the LF\\\"\\n\\taString size = 0 ifTrue: [^ aString].\\n\\t(aString last = Character cr) ifTrue: [\\n\\t\\tstate _ converter saveStateOf: self.\\n\\t\\tpeekChar _ self bareNext.\\t\\t\\\"super peek doesn't work because it relies on #next\\\"\\n\\t\\t(peekChar notNil and: [peekChar ~= Character lf]) ifTrue: [\\n\\t\\t\\tconverter restoreStateOf: self with: state.\\n\\t\\t].\\n\\t].\\n \\n\\t^ aString withSqueakLineEndings.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'crlf private' stamp: 'yo 2/21/2004 03:51'!\\nwantsLineEndConversion\\n\\n\\t^ wantsLineEndConversion ifNil: [false].\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'yo 8/17/2004 10:03'!\\nfileIn\\n\\n\\tself setConverterForCode.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'ar 7/29/2005 22:33'!\\nfileInObjectAndCodeForProject\\n\\t\\\"This file may contain:\\n1) a fileIn of code \\n2) just an object in SmartReferenceStream format \\n3) both code and an object.\\n\\tFile it in and return the object. Note that self must be a FileStream or RWBinaryOrTextStream. Maybe ReadWriteStream incorporate RWBinaryOrTextStream?\\\"\\n\\t| refStream object |\\n\\tself text.\\n\\tself peek asciiValue = 4\\n\\t\\tifTrue: [ \\\"pure object file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\trefStream _ SmartRefStream on: self.\\n\\t\\t\\tobject _ refStream nextAndClose]\\n\\t\\tifFalse: [ \\\"objects mixed with a fileIn\\\"\\n\\t\\t\\tself fileInProject. \\\"reads code and objects, then closes the file\\\"\\n\\t\\t\\tself binary.\\n\\t\\t\\tobject _ SmartRefStream scannedObject].\\t\\\"set by side effect of one of the chunks\\\"\\n\\tSmartRefStream scannedObject: nil. \\\"clear scannedObject\\\"\\n\\t^ object! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'ar 7/29/2005 22:33'!\\nfileInProject\\n\\n\\tself setConverterForCodeForProject.\\n\\tsuper fileIn.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'fileIn/Out' stamp: 'tak 1/12/2005 14:48'!\\nfileOutClass: extraClass andObject: theObject \\n\\tself binary.\\n\\tUTF8TextConverter writeBOMOn: self.\\n\\tself text.\\n\\t^ super fileOutClass: extraClass andObject: theObject! !\\n\\n\\n!MultiByteFileStream methodsFor: 'open/close' stamp: 'md 7/20/2006 11:05'!\\nopen: fileName forWrite: writeMode \\n\\t| result |\\n\\tresult := super open: fileName forWrite: writeMode.\\n\\tresult ifNotNil: [\\n\\t\\t\\tconverter ifNil: [converter := UTF8TextConverter new].\\n\\t\\t\\tself detectLineEndConvention].\\n\\t^result! !\\n\\n!MultiByteFileStream methodsFor: 'open/close' stamp: 'yo 8/13/2003 13:51'!\\nreset\\n\\n\\tsuper reset.\\n\\tconverter ifNil: [\\n\\t\\tconverter _ UTF8TextConverter new.\\n\\t].\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/24/2004 13:49'!\\nnext\\n\\n\\t| char secondChar state |\\n\\tchar _ self converter nextFromStream: self.\\n\\tself doConversion ifTrue: [\\n\\t\\tchar == Cr ifTrue: [\\n\\t\\t\\tstate _ converter saveStateOf: self.\\n\\t\\t\\tsecondChar _ self bareNext.\\n\\t\\t\\tsecondChar ifNotNil: [secondChar == Lf ifFalse: [converter restoreStateOf: self with: state]].\\n\\t\\t^Cr].\\n\\t\\tchar == Lf ifTrue: [^Cr].\\n\\t].\\n\\t^ char.\\n\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 7/31/2004 18:03'!\\nnext: anInteger \\n\\n\\t| multiString |\\n\\tself isBinary ifTrue: [^ super next: anInteger].\\n\\tmultiString _ String new: anInteger.\\n\\t1 to: anInteger do: [:index |\\n\\t\\t| character |\\n\\t\\t(character _ self next) ifNotNil: [\\n\\t\\t\\tmultiString at: index put: character\\n\\t\\t] ifNil: [\\n\\t\\t\\tmultiString _ multiString copyFrom: 1 to: index - 1.\\n\\t\\t\\tself doConversion ifFalse: [\\n\\t\\t\\t\\t^ multiString\\n\\t\\t\\t].\\n\\t\\t\\t^ self next: anInteger innerFor: multiString.\\n\\t\\t]\\n\\t].\\n\\tself doConversion ifFalse: [\\n\\t\\t^ multiString\\n\\t].\\n\\n\\tmultiString _ self next: anInteger innerFor: multiString.\\n\\t(multiString size = anInteger or: [self atEnd]) ifTrue: [ ^ multiString].\\n\\t^ multiString, (self next: anInteger - multiString size).\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 03:26'!\\nnextDelimited: terminator\\n\\n\\t| out ch save |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\tsave _ converter saveStateOf: self.\\n\\n\\tself next = terminator ifFalse: [\\n\\t\\t\\\"absorb initial terminator\\\"\\n\\t\\tconverter restoreStateOf: self with: save.\\n\\t].\\n\\t[(ch _ self next) == nil] whileFalse: [\\n\\t\\t(ch = terminator) ifTrue: [\\n\\t\\t\\tself peek = terminator ifTrue: [\\n\\t\\t\\t\\tself next. \\\"skip doubled terminator\\\"\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:13'!\\nnextMatchAll: aColl\\n\\n | save |\\n save _ converter saveStateOf: self.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n converter restoreStateOf: self with: save.\\n ^ false.\\n\\t\\t].\\n\\t].\\n ^ true.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 03:42'!\\nnextPut: aCharacter\\n\\n\\taCharacter isInteger ifTrue: [^ super nextPut: aCharacter].\\n\\tself doConversion ifTrue: [\\n\\t\\taCharacter = Cr ifTrue: [\\n\\t\\t\\t(LineEndStrings at: lineEndConvention) do: [:e | converter nextPut: e toStream: self].\\n\\t\\t] ifFalse: [\\n\\t\\t\\tconverter nextPut: aCharacter toStream: self\\n\\t\\t].\\n\\t\\t^ aCharacter\\n\\t].\\n\\t^ self converter nextPut: aCharacter toStream: self\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 5/23/2003 09:40'!\\nnextPutAll: aCollection\\n\\n\\t(self isBinary or: [aCollection class == ByteArray]) ifTrue: [\\n\\t\\t^ super nextPutAll: aCollection.\\n\\t].\\n\\taCollection do: [:e | self nextPut: e].\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 04:00'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\n\\t| next save |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tsave _ converter saveStateOf: self.\\n\\tnext _ self next.\\n\\tconverter restoreStateOf: self with: save.\\n\\t^ next.\\n\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:15'!\\npeekFor: item \\n\\n\\t| next state |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\tstate _ converter saveStateOf: self.\\n\\t(next _ self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tconverter restoreStateOf: self with: state.\\n\\t^ false.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/24/2004 13:35'!\\nskipSeparators\\n\\n\\t| state |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tstate _ converter saveStateOf: self.\\n\\t\\tself next isSeparator ifFalse: [\\n\\t\\t\\t^ converter restoreStateOf: self with: state]]\\n\\n\\n\\\"\\t[self atEnd] whileFalse: [\\n\\t\\tself next isSeparator ifFalse: [\\n\\t\\t\\t^ self position: self position - converter currentCharSize.\\n\\t\\t].\\n\\t].\\n\\\"\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 2/21/2004 04:01'!\\nskipSeparatorsAndPeekNext\\n\\n\\t\\\"A special function to make nextChunk fast\\\"\\n\\t| peek save |\\n\\t[self atEnd] whileFalse: [\\n\\t\\tsave _ converter saveStateOf: self.\\n\\t\\t(peek _ self next) isSeparator ifFalse: [\\n\\t\\t\\tconverter restoreStateOf: self with: save.\\n\\t\\t\\t^ peek.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/28/2002 11:17'!\\nupTo: delim \\n\\n\\t| out ch |\\n\\tout _ WriteStream on: (String new: 1000).\\n\\tself atEnd ifTrue: [^ ''].\\n\\t[(ch _ self next) isNil] whileFalse: [\\n\\t\\t(ch = delim) ifTrue: [\\n\\t\\t\\t^ out contents \\\"terminator is not doubled; we're done!!\\\"\\n\\t\\t].\\n\\t\\tout nextPut: ch.\\n\\t].\\n\\t^ out contents.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'public' stamp: 'yo 8/30/2002 16:39'!\\nupToEnd\\n\\n\\t| newStream element |\\n\\tcollection _ self isBinary\\n\\t\\t\\t\\tifTrue: [ByteArray new: 100]\\n\\t\\t\\t\\tifFalse: [String new: 100].\\n\\tnewStream _ WriteStream on: collection.\\n\\t[(element _ self next) notNil]\\n\\t\\twhileTrue: [newStream nextPut: element].\\n\\t^ newStream contents\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'remnant' stamp: 'yo 8/28/2002 11:06'!\\naccepts: aSymbol\\n\\n \\t^ converter accepts: aSymbol.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'remnant' stamp: 'yo 8/28/2002 11:09'!\\nfilterFor: aFileStream\\n\\n\\t| rw |\\n\\tname _ aFileStream name.\\n\\trw _ aFileStream isReadOnly not.\\n\\taFileStream close.\\n\\tself open: name forWrite: rw.\\n\\t^self.\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'private' stamp: 'mir 8/25/2004 17:27'!\\nsetConverterForCode\\n\\n\\t| current |\\n\\t(SourceFiles at: 2)\\n\\t\\tifNotNil: [self fullName = (SourceFiles at: 2) fullName ifTrue: [^ self]].\\n\\tcurrent _ self converter saveStateOf: self.\\n\\tself position: 0.\\n\\tself binary.\\n\\t((self next: 3) = (ByteArray with: 16rEF with: 16rBB with: 16rBF)) ifTrue: [\\n\\t\\tself converter: UTF8TextConverter new\\n\\t] ifFalse: [\\n\\t\\tself converter: MacRomanTextConverter new.\\n\\t].\\n\\tconverter restoreStateOf: self with: current.\\n\\tself text.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private' stamp: 'ar 7/29/2005 22:33'!\\nsetConverterForCodeForProject\\n\\n\\tself converter: UTF8TextConverter new.\\n! !\\n\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'md 10/17/2004 16:09'!\\nbasicNext: anInteger\\n\\n\\t^ super next: anInteger.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNext: n into: aString\\n\\n\\t^ super next: n into: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextInto: aString\\n\\n\\t^ super nextInto: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextPut: char\\n\\n\\t^ super nextPut: char.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicNextPutAll: aString\\n\\n\\t^ super nextPutAll: aString.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'!\\nbasicPeek\\n\\n\\t^ super peek\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicPosition\\n\\n\\t^ super position.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicPosition: pos\\n\\n\\t^ super position: pos.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicReadInto: byteArray startingAt: startIndex count: count\\n\\n\\t^ super readInto: byteArray startingAt: startIndex count: count.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicSetToEnd\\n\\n\\t^ super setToEnd.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicSkip: n\\n\\n\\t^ super skip: n.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:08'!\\nbasicUpTo: delim\\n\\n\\t^ super upTo: delim.\\n! !\\n\\n!MultiByteFileStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:09'!\\nbasicVerbatim: aString\\n\\n\\t^ super verbatim: aString.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiByteFileStream class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:45'!\\ndefaultToCR\\n\\n\\t\\\"MultiByteFileStream defaultToCR\\\"\\n\\tLineEndDefault := #cr.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:45'!\\ndefaultToCRLF\\n\\n\\t\\\"MultiByteFileStream defaultToCRLF\\\"\\n\\tLineEndDefault := #crlf.! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:46'!\\ndefaultToLF\\n\\n\\t\\\"MultiByteFileStream defaultToLF\\\"\\n\\tLineEndDefault := #lf.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\nguessDefaultLineEndConvention\\n\\n\\t\\\"Lets try to guess the line end convention from what we know about the path name delimiter from FileDirectory.\\\"\\n\\tFileDirectory pathNameDelimiter = $: ifTrue:[^self defaultToCR].\\n\\tFileDirectory pathNameDelimiter = $/ ifTrue:[^self defaultToLF].\\n\\tFileDirectory pathNameDelimiter = $\\\\ ifTrue:[^self defaultToCRLF].\\n\\t\\\"in case we don't know\\\"\\n\\t^self defaultToCR.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\ninitialize\\n\\n\\t\\\"MultiByteFileStream initialize\\\"\\n\\tCr := Character cr.\\n\\tLf := Character lf.\\n\\tCrLf := String with: Cr with: Lf.\\n\\tLineEndStrings := Dictionary new.\\n\\tLineEndStrings at: #cr put: (String with: Character cr).\\n\\tLineEndStrings at: #lf put: (String with: Character lf).\\n\\tLineEndStrings at: #crlf put: (String with: Character cr with: Character lf).\\n\\tLookAheadCount := 2048.\\n\\tSmalltalk addToStartUpList: self.\\n\\tself startUp.\\n! !\\n\\n!MultiByteFileStream class methodsFor: 'class initialization' stamp: 'yo 2/21/2004 02:44'!\\nstartUp\\n\\n\\tself guessDefaultLineEndConvention.\\n! !\\n\\n\\n!MultiByteFileStream class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 11:43'!\\nnewFrom: aFileStream\\n\\n\\t| rw n |\\n\\tn _ aFileStream name.\\n\\trw _ aFileStream isReadOnly not.\\n\\taFileStream close.\\n\\t^self new open: n forWrite: rw.\\n! !\\nPluggableCanvas subclass: #MultiCanvas\\n\\tinstanceVariableNames: 'canvases extent depth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n!MultiCanvas commentStamp: '<historical>' prior: 0!\\nA canvas which forwards drawing commands to sub-canvases.!\\n\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 20:48'!\\naddCanvas: aCanvas\\n\\tcanvases add: aCanvas! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'RAA 11/7/2000 17:46'!\\nclipRect\\n\\t\\n\\t^super clipRect ifNil: [\\n\\t\\t0@0 extent: 5000@5000\\n\\t].! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'RAA 8/14/2000 10:27'!\\ncontentsOfArea: aRectangle into: aForm\\n\\n\\tself apply: [ :c |\\n\\t\\t(c isKindOf: FormCanvas) ifTrue: [\\n\\t\\t\\tc contentsOfArea: aRectangle into: aForm.\\n\\t\\t\\t^aForm\\n\\t\\t].\\n\\t].\\n\\tself apply: [ :c |\\n\\t\\tc contentsOfArea: aRectangle into: aForm.\\n\\t\\t^aForm.\\n\\t].\\n\\t^aForm! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 4/8/2000 22:35'!\\ndepth\\n\\t^depth! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 4/8/2000 22:35'!\\nextent\\n\\t^extent! !\\n\\n!MultiCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 20:48'!\\nremoveCanvas: aCanvas\\n\\tcanvases remove: aCanvas ifAbsent: []! !\\n\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'RAA 8/1/2000 13:50'!\\nallocateForm: extentPoint\\n\\t\\\"Allocate a new form which is similar to the receiver and can be used for accelerated blts\\\"\\n\\t^Form extent: extentPoint depth: self depth! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:35'!\\ndepth: newDepth\\n\\t\\\"set the extent to be used with this canvas\\\"\\n\\tdepth := newDepth.! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:34'!\\nextent: newExtent\\n\\t\\\"set the extent to be used with this canvas\\\"\\n\\textent := newExtent.! !\\n\\n!MultiCanvas methodsFor: 'initialization' stamp: 'ls 4/8/2000 22:34'!\\ninitialize\\n\\tcanvases := Set new.\\n\\textent := 600@400.\\n\\tdepth := 32. ! !\\n\\n\\n!MultiCanvas methodsFor: 'private' stamp: 'RAA 11/6/2000 14:17'!\\napply: aCommand\\n\\n\\tself flag: #roundedRudeness.\\t\\n\\t\\\"This rudeness is to help get rounded corners to work right on RemoteCanvases. Since the RemoteCanvas has no other way to read its bits, we are grabbing them from Display for now. To support this, we need to see that the Display is written before any RemoteCanvases\\\"\\n\\n\\tcanvases do: [ :canvas | \\n\\t\\t(canvas isKindOf: FormCanvas) ifTrue: [aCommand value: canvas]\\n\\t].\\n\\tcanvases do: [ :canvas | \\n\\t\\t(canvas isKindOf: FormCanvas) ifFalse: [aCommand value: canvas]\\n\\t].\\n! !\\nMultiCharacterScanner subclass: #MultiCanvasCharacterScanner\\n\\tinstanceVariableNames: 'canvas fillBlt foregroundColor runX lineY'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCanvasCharacterScanner methodsFor: 'accessing' stamp: 'yo 12/18/2002 13:55'!\\ncanvas: aCanvas\\n\\t\\\"set the canvas to draw on\\\"\\n\\tcanvas ifNotNil: [ self inform: 'initializing twice!!' ].\\n\\tcanvas _ aCanvas! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:55'!\\ndisplayLine: textLine offset: offset leftInRun: leftInRun\\n\\t| nowLeftInRun done startLoc startIndex stopCondition |\\n\\t\\\"largely copied from DisplayScanner's routine\\\"\\n\\n\\tline _ textLine.\\n\\tforegroundColor ifNil: [ foregroundColor _ Color black ].\\n\\tleftMargin _ (line leftMarginForAlignment: alignment) + offset x.\\n\\n\\trightMargin _ line rightMargin + offset x.\\n\\tlineY _ line top + offset y.\\n\\tlastIndex _ textLine first.\\n\\tleftInRun <= 0\\n\\t\\tifTrue: [self setStopConditions. \\\"also sets the font\\\"\\n\\t\\t\\t\\tnowLeftInRun _ text runLengthFor: lastIndex]\\n\\t\\tifFalse: [nowLeftInRun _ leftInRun].\\n\\trunX _ destX _ leftMargin.\\n\\n\\trunStopIndex _ lastIndex + (nowLeftInRun - 1) min: line last.\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\n\\t[done] whileFalse: [\\n\\t\\t\\\"remember where this portion of the line starts\\\"\\n\\t\\tstartLoc _ destX@destY.\\n\\t\\tstartIndex _ lastIndex.\\n\\n\\t\\t\\\"find the end of this portion of the line\\\"\\n\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\tkern: kern \\\"displaying: false\\\".\\n\\n\\t\\t\\\"display that portion of the line\\\"\\n\\t\\tcanvas drawString: text string\\n\\t\\t\\tfrom: startIndex to: lastIndex\\n\\t\\t\\tat: startLoc\\n\\t\\t\\tfont: font\\n\\t\\t\\tcolor: foregroundColor.\\n\\n\\t\\t\\\"handle the stop condition\\\"\\n\\t\\tdone _ self perform: stopCondition\\n\\t].\\n\\n\\t^runStopIndex - lastIndex! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ncr\\n\\t\\\"When a carriage return is encountered, simply increment the pointer \\n\\tinto the paragraph.\\\"\\n\\n\\tlastIndex_ lastIndex + 1.\\n\\t^false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ncrossedX\\n\\t\\\"This condition will sometimes be reached 'legally' during display, when, \\n\\tfor instance the space that caused the line to wrap actually extends over \\n\\tthe right boundary. This character is allowed to display, even though it \\n\\tis technically outside or straddling the clipping ectangle since it is in \\n\\tthe normal case not visible and is in any case appropriately clipped by \\n\\tthe scanner.\\\"\\n\\n\\t\\\"self fillLeading.\\\"\\n\\t^ true ! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\nendOfRun\\n\\t\\\"The end of a run in the display case either means that there is actually \\n\\ta change in the style (run code) to be associated with the string or the \\n\\tend of this line has been reached.\\\"\\n\\t| runLength |\\n\\n\\tlastIndex = line last ifTrue: [^true].\\n\\trunX _ destX.\\n\\trunLength _ text runLengthFor: (lastIndex _ lastIndex + 1).\\n\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\tself setStopConditions.\\n\\t^ false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\npaddedSpace\\n\\t\\\"Each space is a stop condition when the alignment is right justified. \\n\\tPadding must be added to the base width of the space according to \\n\\twhich space in the line this space is and according to the amount of \\n\\tspace that remained at the end of the line when it was composed.\\\"\\n\\n\\tdestX _ destX + spaceWidth + (line justifiedPadFor: spaceCount).\\n\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (textStyle alignment = Justified ifTrue: [#paddedSpace]).\\n! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:55'!\\ntab\\n\\n\\tdestX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"imbedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse: \\n\\t\\t\\t[textStyle nextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin].\\n\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:55'!\\ndoesDisplaying\\n\\t^false \\\"it doesn't do displaying using copyBits\\\"! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 1/6/2005 23:00'!\\nsetFont\\n\\tforegroundColor ifNil: [foregroundColor _ Color black].\\n\\tsuper setFont.\\n\\tbaselineY _ lineY + line baseline.\\n\\tdestY _ baselineY - font ascent.! !\\n\\n!MultiCanvasCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:55'!\\ntextColor: color\\n\\tforegroundColor _ color! !\\nMultiCharacterScanner subclass: #MultiCharacterBlockScanner\\n\\tinstanceVariableNames: 'characterPoint characterIndex lastCharacter lastCharacterExtent lastSpaceOrTabExtent nextLeftMargin specialWidth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\ncharacterBlockAtPoint: aPoint in: aParagraph\\n\\t\\\"Answer a CharacterBlock for character in aParagraph at point aPoint. It \\n\\tis assumed that aPoint has been transformed into coordinates appropriate \\n\\tto the text's destination form rectangle and the composition rectangle.\\\"\\n\\n\\tself initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle.\\n\\tcharacterPoint _ aPoint.\\n\\t^self buildCharacterBlockIn: aParagraph! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'nk 11/22/2004 14:36'!\\ncharacterBlockAtPoint: aPoint index: index in: textLine\\n\\t\\\"This method is the Morphic characterBlock finder. It combines\\n\\tMVC's characterBlockAtPoint:, -ForIndex:, and buildCharcterBlock:in:\\\"\\n\\t| runLength lineStop done stopCondition |\\n\\tline := textLine.\\n\\trightMargin := line rightMargin.\\n\\tlastIndex := line first.\\n\\tself setStopConditions.\\t\\t\\\"also sets font\\\"\\n\\tcharacterIndex := index. \\\" == nil means scanning for point\\\"\\n\\tcharacterPoint := aPoint.\\n\\t(characterPoint isNil or: [characterPoint y > line bottom])\\n\\t\\tifTrue: [characterPoint := line bottomRight].\\n\\t(text isEmpty or: [(characterPoint y < line top or: [characterPoint x < line left])\\n\\t\\t\\t\\tor: [characterIndex notNil and: [characterIndex < line first]]])\\n\\t\\tifTrue:\\t[^ (CharacterBlock new stringIndex: line first text: text\\n\\t\\t\\t\\t\\ttopLeft: line leftMargin@line top extent: 0 @ textStyle lineGrid)\\n\\t\\t\\t\\t\\ttextLine: line].\\n\\tdestX := leftMargin := line leftMarginForAlignment: alignment.\\n\\tdestY := line top.\\n\\trunLength := text runLengthFor: line first.\\n\\tcharacterIndex\\n\\t\\tifNotNil:\\t[lineStop := characterIndex \\\"scanning for index\\\"]\\n\\t\\tifNil:\\t[lineStop := line last \\\"scanning for point\\\"].\\n\\trunStopIndex := lastIndex + (runLength - 1) min: lineStop.\\n\\tlastCharacterExtent := 0 @ line lineHeight.\\n\\tspaceCount := 0.\\n\\n\\tdone := false.\\n\\t[done] whileFalse:\\n\\t\\t[stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\tin: text string rightX: characterPoint x\\n\\t\\t\\tstopConditions: stopConditions kern: kern.\\n\\t\\t\\\"see setStopConditions for stopping conditions for character block \\toperations.\\\"\\n\\t\\tself lastCharacterExtentSetX: (specialWidth\\n\\t\\t\\tifNil: [font widthOf: (text at: lastIndex)]\\n\\t\\t\\tifNotNil: [specialWidth]).\\n\\t\\t(self perform: stopCondition) ifTrue:\\n\\t\\t\\t[characterIndex\\n\\t\\t\\t\\tifNil: [\\n\\t\\t\\t\\t\\t\\\"Result for characterBlockAtPoint: \\\"\\n\\t\\t\\t\\t\\t(stopCondition ~~ #cr and: [ lastIndex == line last\\n\\t\\t\\t\\t\\t\\tand: [ aPoint x > ((characterPoint x) + (lastCharacterExtent x / 2)) ]])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [ \\\"Correct for right half of last character in line\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: lastIndex + 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttext: text\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + (lastCharacterExtent x @ 0) + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\textent: 0 @ lastCharacterExtent y)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line ].\\n\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: lastIndex\\n\\t\\t\\t\\t\\t\\t\\ttext: text topLeft: characterPoint + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\t\\textent: lastCharacterExtent - (font baseKern @ 0))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line]\\n\\t\\t\\t\\tifNotNil: [\\\"Result for characterBlockForIndex: \\\"\\n\\t\\t\\t\\t\\t\\t^ (CharacterBlock new stringIndex: characterIndex\\n\\t\\t\\t\\t\\t\\t\\ttext: text topLeft: characterPoint + ((font descentKern) - kern @ 0)\\n\\t\\t\\t\\t\\t\\t\\textent: lastCharacterExtent)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttextLine: line]]]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\ncharacterBlockForIndex: targetIndex in: aParagraph \\n\\t\\\"Answer a CharacterBlock for character in aParagraph at targetIndex. The \\n\\tcoordinates in the CharacterBlock will be appropriate to the intersection \\n\\tof the destination form rectangle and the composition rectangle.\\\"\\n\\n\\tself \\n\\t\\tinitializeFromParagraph: aParagraph \\n\\t\\tclippedBy: aParagraph clippingRectangle.\\n\\tcharacterIndex _ targetIndex.\\n\\tcharacterPoint _ \\n\\t\\taParagraph rightMarginForDisplay @ \\n\\t\\t\\t(aParagraph topAtLineIndex: \\n\\t\\t\\t\\t(aParagraph lineIndexOfCharacterIndex: characterIndex)).\\n\\t^self buildCharacterBlockIn: aParagraph! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\nindentationLevel: anInteger\\n\\tsuper indentationLevel: anInteger.\\n\\tnextLeftMargin _ leftMargin.\\n\\tindentationLevel timesRepeat: [\\n\\t\\tnextLeftMargin _ textStyle nextTabXFrom: nextLeftMargin\\n\\t\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\t\\trightMargin: rightMargin]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:56'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].\\n\\tspecialWidth _ anchoredMorph width.\\n\\t^ true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'scanning' stamp: 'yo 8/6/2003 05:55'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| encoding f nextDestX maxAscii startEncoding char charValue |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tchar _ (sourceString at: lastIndex).\\n\\t\\tcharValue _ char charCode.\\n\\t\\tcharValue > maxAscii ifTrue: [charValue _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: charValue + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t^ stops at: charValue + 1\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (self widthOf: char inFont: font).\\n\\t\\tnextDestX > rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 1/6/2005 22:55'!\\ncr \\n\\t\\\"Answer a CharacterBlock that specifies the current location of the mouse \\n\\trelative to a carriage return stop condition that has just been \\n\\tencountered. The ParagraphEditor convention is to denote selections by \\n\\tCharacterBlocks, sometimes including the carriage return (cursor is at \\n\\tthe end) and sometimes not (cursor is in the middle of the text).\\\"\\n\\n\\t((characterIndex ~= nil\\n\\t\\tand: [characterIndex > text size])\\n\\t\\t\\tor: [(line last = text size)\\n\\t\\t\\t\\tand: [(destY + line lineHeight) < characterPoint y]])\\n\\t\\tifTrue:\\t[\\\"When off end of string, give data for next character\\\"\\n\\t\\t\\t\\tdestY _ destY + line lineHeight.\\n\\t\\t\\t\\tbaselineY _ line lineHeight.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tcharacterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ destY.\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^ true].\\n\\t\\tlastCharacter _ CR.\\n\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\tself lastCharacterExtentSetX: rightMargin - destX.\\n\\t\\t^true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\ncrossedX\\n\\t\\\"Text display has wrapping. The scanner just found a character past the x \\n\\tlocation of the cursor. We know that the cursor is pointing at a character \\n\\tor before one.\\\"\\n\\n\\t| leadingTab currentX |\\n\\tcharacterIndex == nil ifFalse: [\\n\\t\\t\\\"If the last character of the last line is a space,\\n\\t\\tand it crosses the right margin, then locating\\n\\t\\tthe character block after it is impossible without this hack.\\\"\\n\\t\\tcharacterIndex > text size ifTrue: [\\n\\t\\t\\tlastIndex _ characterIndex.\\n\\t\\t\\tcharacterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ (destY + line lineHeight).\\n\\t\\t\\t^true]].\\n\\tcharacterPoint x <= (destX + (lastCharacterExtent x // 2))\\n\\t\\tifTrue:\\t[lastCharacter _ (text at: lastIndex).\\n\\t\\t\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\t\\t\\t^true].\\n\\tlastIndex >= line last \\n\\t\\tifTrue:\\t[lastCharacter _ (text at: line last).\\n\\t\\t\\t\\tcharacterPoint _ destX @ destY.\\n\\t\\t\\t\\t^true].\\n\\n\\t\\\"Pointing past middle of a character, return the next character.\\\"\\n\\tlastIndex _ lastIndex + 1.\\n\\tlastCharacter _ text at: lastIndex.\\n\\tcurrentX _ destX + lastCharacterExtent x + kern.\\n\\tself lastCharacterExtentSetX: (font widthOf: lastCharacter).\\n\\tcharacterPoint _ currentX @ destY.\\n\\tlastCharacter = Space ifFalse: [^ true].\\n\\n\\t\\\"Yukky if next character is space or tab.\\\"\\n\\talignment = Justified ifTrue:\\n\\t\\t[self lastCharacterExtentSetX:\\n\\t\\t\\t(lastCharacterExtent x + \\t(line justifiedPadFor: (spaceCount + 1))).\\n\\t\\t^ true].\\n\\n\\ttrue ifTrue: [^ true].\\n\\t\\\"NOTE: I find no value to the following code, and so have defeated it - DI\\\"\\n\\n\\t\\\"See tabForDisplay for illumination on the following awfulness.\\\"\\n\\tleadingTab _ true.\\n\\tline first to: lastIndex - 1 do:\\n\\t\\t[:index | (text at: index) ~= Tab ifTrue: [leadingTab _ false]].\\n\\t(alignment ~= Justified or: [leadingTab])\\n\\t\\tifTrue:\\t[self lastCharacterExtentSetX: (textStyle nextTabXFrom: currentX\\n\\t\\t\\t\\t\\tleftMargin: leftMargin rightMargin: rightMargin) -\\n\\t\\t\\t\\t\\t\\tcurrentX]\\n\\t\\tifFalse:\\t[self lastCharacterExtentSetX: (((currentX + (textStyle tabWidth -\\n\\t\\t\\t\\t\\t\\t(line justifiedTabDeltaFor: spaceCount))) -\\n\\t\\t\\t\\t\\t\\t\\tcurrentX) max: 0)].\\n\\t^ true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\nendOfRun\\n\\t\\\"Before arriving at the cursor location, the selection has encountered an \\n\\tend of run. Answer false if the selection continues, true otherwise. Set \\n\\tup indexes for building the appropriate CharacterBlock.\\\"\\n\\n\\t| runLength lineStop |\\n\\t(((characterIndex ~~ nil and:\\n\\t\\t[runStopIndex < characterIndex and: [runStopIndex < text size]])\\n\\t\\t\\tor:\\t[characterIndex == nil and: [lastIndex < line last]]) or: [\\n\\t\\t\\t\\t((lastIndex < line last)\\n\\t\\t\\t\\tand: [((text at: lastIndex) leadingChar ~= (text at: lastIndex+1) leadingChar)\\n\\t\\t\\t\\t\\tand: [lastIndex ~= characterIndex]])])\\n\\t\\tifTrue:\\t[\\\"We're really at the end of a real run.\\\"\\n\\t\\t\\t\\trunLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).\\n\\t\\t\\t\\tcharacterIndex ~~ nil\\n\\t\\t\\t\\t\\tifTrue:\\t[lineStop _ characterIndex\\t\\\"scanning for index\\\"]\\n\\t\\t\\t\\t\\tifFalse:\\t[lineStop _ line last\\t\\t\\t\\\"scanning for point\\\"].\\n\\t\\t\\t\\t(runStopIndex _ lastIndex + (runLength - 1)) > lineStop\\n\\t\\t\\t\\t\\tifTrue: \\t[runStopIndex _ lineStop].\\n\\t\\t\\t\\tself setStopConditions.\\n\\t\\t\\t\\t^false].\\n\\n\\tlastCharacter _ text at: lastIndex.\\n\\tcharacterPoint _ destX @ destY.\\n\\t((lastCharacter = Space and: [alignment = Justified])\\n\\t\\tor: [lastCharacter = Tab and: [lastSpaceOrTabExtent notNil]])\\n\\t\\tifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent].\\n\\tcharacterIndex ~~ nil\\n\\t\\tifTrue:\\t[\\\"If scanning for an index and we've stopped on that index,\\n\\t\\t\\t\\tthen we back destX off by the width of the character stopped on\\n\\t\\t\\t\\t(it will be pointing at the right side of the character) and return\\\"\\n\\t\\t\\t\\trunStopIndex = characterIndex\\n\\t\\t\\t\\t\\tifTrue:\\t[self characterPointSetX: destX - lastCharacterExtent x.\\n\\t\\t\\t\\t\\t\\t\\t^true].\\n\\t\\t\\t\\t\\\"Otherwise the requested index was greater than the length of the\\n\\t\\t\\t\\tstring. Return string size + 1 as index, indicate further that off the\\n\\t\\t\\t\\tstring by setting character to nil and the extent to 0.\\\"\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^true].\\n\\n\\t\\\"Scanning for a point and either off the end of the line or off the end of the string.\\\"\\n\\trunStopIndex = text size\\n\\t\\tifTrue:\\t[\\\"off end of string\\\"\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tlastCharacter _ nil.\\n\\t\\t\\t\\tself lastCharacterExtentSetX: 0.\\n\\t\\t\\t\\t^true].\\n\\t\\\"just off end of line without crossing x\\\"\\n\\tlastIndex _ lastIndex + 1.\\n\\t^true! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\npaddedSpace\\n\\t\\\"When the line is justified, the spaces will not be the same as the font's \\n\\tspace character. A padding of extra space must be considered in trying \\n\\tto find which character the cursor is pointing at. Answer whether the \\n\\tscanning has crossed the cursor.\\\"\\n\\n\\t| pad |\\n\\tpad _ 0.\\n\\tspaceCount _ spaceCount + 1.\\n\\tpad _ line justifiedPadFor: spaceCount.\\n\\tlastSpaceOrTabExtent _ lastCharacterExtent copy.\\n\\tself lastSpaceOrTabExtentSetX: spaceWidth + pad.\\n\\t(destX + lastSpaceOrTabExtent x) >= characterPoint x\\n\\t\\tifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy.\\n\\t\\t\\t\\t^self crossedX].\\n\\tlastIndex _ lastIndex + 1.\\n\\tdestX _ destX + lastSpaceOrTabExtent x.\\n\\t^ false\\n! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\nsetFont\\n\\tspecialWidth _ nil.\\n\\tsuper setFont! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 10/18/2004 14:31'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (alignment = Justified ifTrue: [#paddedSpace]).\\n! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:56'!\\ntab\\n\\t| currentX |\\n\\tcurrentX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"imbedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse:\\n\\t\\t\\t[textStyle\\n\\t\\t\\t\\tnextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin].\\n\\tlastSpaceOrTabExtent _ lastCharacterExtent copy.\\n\\tself lastSpaceOrTabExtentSetX: (currentX - destX max: 0).\\n\\tcurrentX >= characterPoint x\\n\\t\\tifTrue: \\n\\t\\t\\t[lastCharacterExtent _ lastSpaceOrTabExtent copy.\\n\\t\\t\\t^ self crossedX].\\n\\tdestX _ currentX.\\n\\tlastIndex _ lastIndex + 1.\\n\\t^false! !\\n\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nbuildCharacterBlockIn: para\\n\\t| lineIndex runLength lineStop done stopCondition |\\n\\t\\\"handle nullText\\\"\\n\\t(para numberOfLines = 0 or: [text size = 0])\\n\\t\\tifTrue:\\t[^ CharacterBlock new stringIndex: 1 \\\"like being off end of string\\\"\\n\\t\\t\\t\\t\\ttext: para text\\n\\t\\t\\t\\t\\ttopLeft: (para leftMarginForDisplayForLine: 1 alignment: (alignment ifNil:[textStyle alignment]))\\n\\t\\t\\t\\t\\t\\t\\t\\t@ para compositionRectangle top\\n\\t\\t\\t\\t\\textent: 0 @ textStyle lineGrid].\\n\\t\\\"find the line\\\"\\n\\tlineIndex _ para lineIndexOfTop: characterPoint y.\\n\\tdestY _ para topAtLineIndex: lineIndex.\\n\\tline _ para lines at: lineIndex.\\n\\trightMargin _ para rightMarginForDisplay.\\n\\n\\t(lineIndex = para numberOfLines and:\\n\\t\\t[(destY + line lineHeight) < characterPoint y])\\n\\t\\t\\tifTrue:\\t[\\\"if beyond lastLine, force search to last character\\\"\\n\\t\\t\\t\\t\\tself characterPointSetX: rightMargin]\\n\\t\\t\\tifFalse:\\t[characterPoint y < (para compositionRectangle) top\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"force search to first line\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tcharacterPoint _ (para compositionRectangle) topLeft].\\n\\t\\t\\t\\t\\tcharacterPoint x > rightMargin\\n\\t\\t\\t\\t\\t\\tifTrue:\\t[self characterPointSetX: rightMargin]].\\n\\tdestX _ (leftMargin _ para leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment])).\\n\\tnextLeftMargin_ para leftMarginForDisplayForLine: lineIndex+1 alignment: (alignment ifNil:[textStyle alignment]).\\n\\tlastIndex _ line first.\\n\\n\\tself setStopConditions.\\t\\t\\\"also sets font\\\"\\n\\trunLength _ (text runLengthFor: line first).\\n\\tcharacterIndex == nil\\n\\t\\tifTrue:\\t[lineStop _ line last \\\"characterBlockAtPoint\\\"]\\n\\t\\tifFalse:\\t[lineStop _ characterIndex \\\"characterBlockForIndex\\\"].\\n\\t(runStopIndex _ lastIndex + (runLength - 1)) > lineStop\\n\\t\\tifTrue:\\t[runStopIndex _ lineStop].\\n\\tlastCharacterExtent _ 0 @ line lineHeight.\\n\\tspaceCount _ 0. done _ false.\\n\\tself handleIndentation.\\n\\n\\t[done]\\n\\twhileFalse:\\n\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\tin: text string rightX: characterPoint x\\n\\t\\t\\tstopConditions: stopConditions kern: kern.\\n\\n\\t\\\"see setStopConditions for stopping conditions for character block \\toperations.\\\"\\n\\tself lastCharacterExtentSetX: (font widthOf: (text at: lastIndex)).\\n\\t(self perform: stopCondition) ifTrue:\\n\\t\\t[characterIndex == nil\\n\\t\\t\\tifTrue: [\\\"characterBlockAtPoint\\\"\\n\\t\\t\\t\\t\\t^ CharacterBlock new stringIndex: lastIndex text: text\\n\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + (font descentKern @ 0)\\n\\t\\t\\t\\t\\t\\textent: lastCharacterExtent]\\n\\t\\t\\tifFalse: [\\\"characterBlockForIndex\\\"\\n\\t\\t\\t\\t\\t^ CharacterBlock new stringIndex: lastIndex text: text\\n\\t\\t\\t\\t\\t\\ttopLeft: characterPoint + ((font descentKern) - kern @ 0)\\n\\t\\t\\t\\t\\t\\textent: lastCharacterExtent]]]! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\ncharacterPointSetX: xVal\\n\\tcharacterPoint _ xVal @ characterPoint y! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nlastCharacterExtentSetX: xVal\\n\\tlastCharacterExtent _ xVal @ lastCharacterExtent y! !\\n\\n!MultiCharacterBlockScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:56'!\\nlastSpaceOrTabExtentSetX: xVal\\n\\tlastSpaceOrTabExtent _ xVal @ lastSpaceOrTabExtent y! !\\nObject subclass: #MultiCharacterScanner\\n\\tinstanceVariableNames: 'destX lastIndex xTable destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks presentation presentationLine numOfComposition baselineY firstDestX'\\n\\tclassVariableNames: 'DefaultStopConditions NilCondition PaddedSpaceCondition SpaceCondition'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\ninitialize\\n\\tdestX _ destY _ leftMargin _ 0.! !\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\ninitializeStringMeasurer\\n\\tstopConditions _ Array new: 258.\\n\\tstopConditions at: CrossedX put: #crossedX.\\n\\tstopConditions at: EndOfRun put: #endOfRun.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'initialize' stamp: 'yo 12/18/2002 13:53'!\\nwantsColumnBreaks: aBoolean\\n\\n\\twantsColumnBreaks _ aBoolean! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/3/2003 12:09'!\\naddCharToPresentation: char\\n\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 16:15'!\\nregisterBreakableIndex\\n\\n\\t\\\"Record left x and character index of the line-wrappable point. \\n\\tThe default implementation here does nothing.\\\"\\n\\n\\t^ false.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/23/2003 14:25'!\\nremoveLastCharFromPresentation\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/1/2003 10:43'!\\nwidthOf: char inFont: aFont\\n\\n\\t(char isMemberOf: CombinedChar) ifTrue: [\\n\\t\\t^ aFont widthOf: char base.\\n\\t] ifFalse: [\\n\\t\\t^ aFont widthOf: char.\\n\\t].\\n\\n\\n! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/18/2002 13:53'!\\nbasicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\t\\\"Primitive. This is the inner loop of text display--but see \\n\\tscanCharactersFrom: to:rightX: which would get the string, \\n\\tstopConditions and displaying from the instance. March through source \\n\\tString from startIndex to stopIndex. If any character is flagged with a \\n\\tnon-nil entry in stops, then return the corresponding value. Determine \\n\\twidth of each character from xTable, indexed by map. \\n\\tIf dextX would exceed rightX, then return stops at: 258. \\n\\tAdvance destX by the width of the character. If stopIndex has been\\n\\treached, then return stops at: 257. Optional. \\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\t| ascii nextDestX char |\\n\\t<primitive: 103>\\n\\tlastIndex _ startIndex.\\n\\t[lastIndex <= stopIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[char _ (sourceString at: lastIndex).\\n\\t\\t\\tascii _ char asciiValue + 1.\\n\\t\\t\\t(stops at: ascii) == nil ifFalse: [^stops at: ascii].\\n\\t\\t\\t\\\"Note: The following is querying the font about the width\\n\\t\\t\\tsince the primitive may have failed due to a non-trivial\\n\\t\\t\\tmapping of characters to glyphs or a non-existing xTable.\\\"\\n\\t\\t\\tnextDestX _ destX + (font widthOf: char).\\n\\t\\t\\tnextDestX > rightX ifTrue: [^stops at: CrossedX].\\n\\t\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\t\\tlastIndex _ lastIndex + 1].\\n\\tlastIndex _ stopIndex.\\n\\t^stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/30/2002 22:59'!\\ncombinableChar: char for: prevEntity\\n\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 12/20/2002 11:46'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ encodingClass isBreakableAt: index in: sourceString.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:03'!\\nscanJapaneseCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\t\\\"xTable _ f xTable.\\n\\t\\tmaxAscii _ xTable size - 2.\\\"\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\t(font isMemberOf: HostFont) ifTrue: [\\n\\t\\t\\tf _ font.\\n\\t\\t\\tmaxAscii _ f maxAscii.\\n\\t\\t\\tspaceWidth _ f widthOf: Space.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tmaxAscii _ font maxAscii.\\n\\t\\t].\\n\\t].\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\t\\\"self halt.\\\"\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: ascii + 1) ~~ nil]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: (EncodedCharSet charsetAt: encoding)) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX > rightX ifTrue: [firstDestX ~= destX ifTrue: [^ stops at: CrossedX]].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:09'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| charCode encoding f maxAscii startEncoding combining combined combiningIndex c |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ font widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t\\tspaceWidth _ font widthOf: Space.\\n\\t].\\n\\n\\tcombining _ nil.\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tcharCode _ (sourceString at: lastIndex) charCode.\\n\\t\\tc _ (sourceString at: lastIndex).\\n\\t\\tcombining ifNil: [\\n\\t\\t\\tcombining _ CombinedChar new.\\n\\t\\t\\tcombining add: c.\\n\\t\\t\\tcombiningIndex _ lastIndex.\\n\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t] ifNotNil: [\\n\\t\\t\\t(combining add: c) ifFalse: [\\n\\t\\t\\t\\tself addCharToPresentation: (combined _ combining combined).\\n\\t\\t\\t\\tcombining _ CombinedChar new.\\n\\t\\t\\t\\tcombining add: c.\\n\\t\\t\\t\\tcharCode _ combined charCode.\\n\\t\\t\\t\\tencoding _ combined leadingChar.\\n\\t\\t\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1.\\n\\t\\t\\t\\t\\t(encoding = 0 and: [(stopConditions at: charCode + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t\\t\\t\\t^ stops at: charCode + 1\\n\\t\\t\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t\\t\\t ^ stops at: EndOfRun\\n\\t\\t\\t\\t\\t].\\n\\t\\t\\t\\t].\\n\\t\\t\\t\\tcharCode > maxAscii ifTrue: [charCode _ maxAscii].\\n\\t\\t\\t\\t\\\"\\\"\\n\\t\\t\\t\\t(encoding = 0 and: [(stopConditions at: charCode + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t\\t\\tcombining ifNotNil: [\\n\\t\\t\\t\\t\\t\\tself addCharToPresentation: (combining combined).\\n\\t\\t\\t\\t\\t].\\n\\t\\t\\t\\t\\t^ stops at: charCode + 1\\n\\t\\t\\t\\t].\\n\\t\\t\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\t\\t\\tself registerBreakableIndex.\\n\\t\\t\\t\\t].\\t\\t\\n\\t\\t\\t\\tdestX > rightX ifTrue: [\\n\\t\\t\\t\\t\\tdestX ~= firstDestX ifTrue: [\\n\\t\\t\\t\\t\\t\\tlastIndex _ combiningIndex.\\n\\t\\t\\t\\t\\t\\tself removeLastCharFromPresentation.\\n\\t\\t\\t\\t\\t\\t^ stops at: CrossedX]].\\n\\t\\t\\t\\tcombiningIndex _ lastIndex.\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t] ifTrue: [\\n\\t\\t\\t\\tlastIndex _ lastIndex + 1.\\n\\t\\t\\t\\tnumOfComposition _ numOfComposition + 1.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\tcombining ifNotNil: [\\n\\t\\tcombined _ combining combined.\\n\\t\\tself addCharToPresentation: combined.\\n\\t\\t\\\"assuming that there is always enough space for at least one character\\\".\\n\\t\\tdestX _ destX + (self widthOf: combined inFont: font).\\n\\t].\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:08'!\\nscanMultiCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [ascii < stopConditions size and: [(stopConditions at: ascii + 1) ~~ nil]]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX > rightX ifTrue: [destX ~= firstDestX ifTrue: [^ stops at: CrossedX]].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n!MultiCharacterScanner methodsFor: 'scanner methods' stamp: 'yo 3/16/2005 19:08'!\\nscanMultiCharactersR2LFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t\\\"Note that 'rightX' really means 'endX' in R2L context. Ie. rightX is usually smaller than destX.\\\"\\n\\t| ascii encoding f nextDestX maxAscii startEncoding |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tascii _ (sourceString at: lastIndex) charCode.\\n\\t\\tascii > maxAscii ifTrue: [ascii _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: ascii + 1) ~~ nil]) ifTrue: [^ stops at: ascii + 1].\\n\\t\\t(self isBreakableAt: lastIndex in: sourceString in: Latin1Environment) ifTrue: [\\n\\t\\t\\tself registerBreakableIndex.\\n\\t\\t].\\n\\t\\tnextDestX _ destX - (font widthOf: (sourceString at: lastIndex)).\\n\\t\\tnextDestX < rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX - kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\ncolumnBreak\\n\\n\\t^true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nembeddedObject\\n\\t| savedIndex |\\n\\tsavedIndex _ lastIndex.\\n\\ttext attributesAt: lastIndex do:[:attr| \\n\\t\\tattr anchoredMorph ifNotNil:[\\n\\t\\t\\t\\\"Following may look strange but logic gets reversed.\\n\\t\\t\\tIf the morph fits on this line we're not done (return false for true) \\n\\t\\t\\tand if the morph won't fit we're done (return true for false)\\\"\\n\\t\\t\\t(self placeEmbeddedObject: attr anchoredMorph) ifFalse:[^true]]].\\n\\tlastIndex _ savedIndex + 1. \\\"for multiple(!!) embedded morphs\\\"\\n\\t^false! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nhandleIndentation\\n\\tself indentationLevel timesRepeat: [\\n\\t\\tself plainTab]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nindentationLevel\\n\\t\\\"return the number of tabs that are currently being placed at the beginning of each line\\\"\\n\\t^indentationLevel ifNil:[0]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nindentationLevel: anInteger\\n\\t\\\"set the number of tabs to put at the beginning of each line\\\"\\n\\tindentationLevel _ anInteger! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nleadingTab\\n\\t\\\"return true if only tabs lie to the left\\\"\\n\\tline first to: lastIndex do:\\n\\t\\t[:i | (text at: i) == Tab ifFalse: [^ false]].\\n\\t^ true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 1/18/2005 08:08'!\\nmeasureString: aString inFont: aFont from: startIndex to: stopIndex\\n\\t\\\"WARNING: In order to use this method the receiver has to be set up using #initializeStringMeasurer\\\"\\n\\tdestX _ destY _ lastIndex _ 0.\\n\\tbaselineY _ aFont ascent.\\n\\txTable _ aFont xTable.\\n\\tfont := aFont. \\\" added Dec 03, 2004 \\\"\\n\\\"\\tmap _ aFont characterToGlyphMap.\\\"\\n\\tself scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999 stopConditions: stopConditions kern: 0.\\n\\t^destX! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t\\\"Place the anchoredMorph or return false if it cannot be placed.\\n\\tIn any event, advance destX by its width.\\\"\\n\\t| w |\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\tdestX _ destX + (w _ anchoredMorph width).\\n\\t(destX > rightMargin and: [(leftMargin + w) <= rightMargin])\\n\\t\\tifTrue: [\\\"Won't fit, but would on next line\\\"\\n\\t\\t\\t\\t^ false].\\n\\tlastIndex _ lastIndex + 1.\\n\\tself setFont. \\\"Force recalculation of emphasis for next run\\\"\\n\\t^ true! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'yo 12/18/2002 13:53'!\\nplainTab\\n\\t\\\"This is the basic method of adjusting destX for a tab.\\\"\\n\\tdestX _ (alignment == Justified and: [self leadingTab not])\\n\\t\\tifTrue:\\t\\t\\\"embedded tabs in justified text are weird\\\"\\n\\t\\t\\t[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]\\n\\t\\tifFalse: \\n\\t\\t\\t[textStyle nextTabXFrom: destX\\n\\t\\t\\t\\tleftMargin: leftMargin\\n\\t\\t\\t\\trightMargin: rightMargin]! !\\n\\n!MultiCharacterScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 19:53'!\\nscanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| startEncoding selector |\\n\\t(sourceString isByteString) ifTrue: [^ self basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta.].\\n\\n\\t(sourceString isWideString) ifTrue: [\\n\\t\\tstartIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\t\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\t\\tselector _ (EncodedCharSet charsetAt: startEncoding) scanSelector.\\n\\t\\t^ self perform: selector withArguments: (Array with: startIndex with: stopIndex with: sourceString with: rightX with: stopConditions with: kernDelta).\\n\\t].\\n\\t\\n\\t^ stops at: EndOfRun\\n! !\\n\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\naddEmphasis: code\\n\\t\\\"Set the bold-ital-under-strike emphasis.\\\"\\n\\temphasisCode _ emphasisCode bitOr: code! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\naddKern: kernDelta\\n\\t\\\"Set the current kern amount.\\\"\\n\\tkern _ kern + kernDelta! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ninitializeFromParagraph: aParagraph clippedBy: clippingRectangle\\n\\n\\ttext _ aParagraph text.\\n\\ttextStyle _ aParagraph textStyle. \\n! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetActualFont: aFont\\n\\t\\\"Set the basal font to an isolated font reference.\\\"\\n\\n\\tfont _ aFont! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetAlignment: style\\n\\talignment _ style.\\n\\t! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/19/2002 02:05'!\\nsetConditionArray: aSymbol\\n\\n\\taSymbol == #paddedSpace ifTrue: [^stopConditions _ PaddedSpaceCondition \\\"copy\\\"].\\n\\t\\\"aSymbol == #space ifTrue: [^stopConditions _ SpaceCondition copy].\\\"\\n\\taSymbol == nil ifTrue: [^stopConditions _ NilCondition \\\"copy\\\"].\\n\\tself error: 'undefined stopcondition for space character'.\\n! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'tak 12/19/2004 15:45'!\\nsetFont\\n\\t| priorFont |\\n\\t\\\"Set the font and other emphasis.\\\"\\n\\tpriorFont _ font.\\n\\ttext == nil ifFalse:[\\n\\t\\temphasisCode _ 0.\\n\\t\\tkern _ 0.\\n\\t\\tindentationLevel _ 0.\\n\\t\\talignment _ textStyle alignment.\\n\\t\\tfont _ nil.\\n\\t\\t(text attributesAt: lastIndex forStyle: textStyle)\\n\\t\\t\\tdo: [:att | att emphasizeScanner: self]].\\n\\tfont == nil ifTrue:\\n\\t\\t[self setFont: textStyle defaultFontIndex].\\n\\tfont _ font emphasized: emphasisCode.\\n\\tpriorFont ifNotNil: [destX _ destX + priorFont descentKern].\\n\\tdestX _ destX - font descentKern.\\n\\t\\\"NOTE: next statement should be removed when clipping works\\\"\\n\\tleftMargin ifNotNil: [destX _ destX max: leftMargin].\\n\\tkern _ kern - font baseKern.\\n\\n\\t\\\"Install various parameters from the font.\\\"\\n\\tspaceWidth _ font widthOf: Space.\\n\\txTable _ font xTable.\\n\\\"\\tmap _ font characterToGlyphMap.\\\"\\n\\tstopConditions _ DefaultStopConditions.! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\nsetFont: fontNumber\\n\\t\\\"Set the font by number from the textStyle.\\\"\\n\\n\\tself setActualFont: (textStyle fontAt: fontNumber)! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ntext: t textStyle: ts\\n\\ttext _ t.\\n\\ttextStyle _ ts! !\\n\\n!MultiCharacterScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:53'!\\ntextColor: ignored\\n\\t\\\"Overridden in DisplayScanner\\\"! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiCharacterScanner class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiCharacterScanner class methodsFor: 'class initialization' stamp: 'yo 12/18/2002 14:09'!\\ninitialize\\n\\\"\\n\\tMultiCharacterScanner initialize\\n\\\"\\n\\t| a |\\n\\ta _ Array new: 258.\\n\\ta at: 1 + 1 put: #embeddedObject.\\n\\ta at: Tab asciiValue + 1 put: #tab.\\n\\ta at: CR asciiValue + 1 put: #cr.\\n\\ta at: EndOfRun put: #endOfRun.\\n\\ta at: CrossedX put: #crossedX.\\n\\tNilCondition _ a copy.\\n\\tDefaultStopConditions _ a copy.\\n\\n\\tPaddedSpaceCondition _ a copy.\\n\\tPaddedSpaceCondition at: Space asciiValue + 1 put: #paddedSpace.\\n\\t\\n\\tSpaceCondition _ a copy.\\n\\tSpaceCondition at: Space asciiValue + 1 put: #space.\\n! !\\nMultiCharacterScanner subclass: #MultiCompositionScanner\\n\\tinstanceVariableNames: 'spaceX lineHeight baseline breakableIndex lineHeightAtBreak baselineAtBreak breakAtSpace lastWidth'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 1/3/2003 02:33'!\\npresentation\\n\\n\\t^ presentation.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 1/3/2003 02:33'!\\npresentationLine\\n\\n\\t^ presentationLine.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'accessing' stamp: 'yo 12/18/2002 14:56'!\\nrightX\\n\\t\\\"Meaningful only when a line has just been composed -- refers to the \\n\\tline most recently composed. This is a subtrefuge to allow for easy \\n\\tresizing of a composition rectangle to the width of the maximum line. \\n\\tUseful only when there is only one line in the form or when each line \\n\\tis terminated by a carriage return. Handy for sizing menus and lists.\\\"\\n\\n\\tbreakAtSpace ifTrue: [^ spaceX].\\n\\n\\t^ destX.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'intialize-release' stamp: 'yo 12/18/2002 13:57'!\\nforParagraph: aParagraph\\n\\t\\\"Initialize the receiver for scanning the given paragraph.\\\"\\n\\n\\tself\\n\\t\\tinitializeFromParagraph: aParagraph\\n\\t\\tclippedBy: aParagraph clippingRectangle.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 2/10/2004 23:00'!\\naddCharToPresentation: char\\n\\n\\tpresentation nextPut: char.\\n\\tlastWidth _ self widthOf: char inFont: font.\\n\\tdestX _ destX + lastWidth.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/16/2003 17:38'!\\ngetPresentation\\n\\n\\t^ presentation contents.\\n\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 1/16/2003 17:28'!\\ngetPresentationLine\\n\\n\\t^ presentationLine.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 11:51'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ encodingClass isBreakableAt: index in: sourceString.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 16:28'!\\nregisterBreakableIndex\\n\\n\\t\\\"Record left x and character index of the line-wrappable point. \\n\\tUsed for wrap-around. Answer whether the character has crossed the \\n\\tright edge of the composition rectangle of the paragraph.\\\"\\n\\n\\t(text at: lastIndex) = Character space ifTrue: [\\n\\t\\tbreakAtSpace _ true.\\n\\t\\tspaceX _ destX.\\n\\t\\tspaceCount _ spaceCount + 1.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t\\tbreakableIndex _ lastIndex.\\n\\t\\tdestX > rightMargin ifTrue: \\t[^self crossedX].\\n\\t] ifFalse: [\\n\\t\\tbreakAtSpace _ false.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t\\tbreakableIndex _ lastIndex - 1.\\n\\t].\\n\\t^ false.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'multilingual scanning' stamp: 'yo 2/10/2004 22:59'!\\nremoveLastCharFromPresentation\\n\\n\\tpresentation ifNotNil: [\\n\\t\\tpresentation position: presentation position - 1.\\n\\t].\\n\\tdestX _ destX - lastWidth.\\n! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 17:34'!\\ncomposeFrom: startIndex inRectangle: lineRectangle\\n\\tfirstLine: firstLine leftSide: leftSide rightSide: rightSide\\n\\t\\\"Answer an instance of TextLineInterval that represents the next line in the paragraph.\\\"\\n\\t| runLength done stopCondition |\\n\\t\\\"Set up margins\\\"\\n\\tleftMargin _ lineRectangle left.\\n\\tleftSide ifTrue: [leftMargin _ leftMargin +\\n\\t\\t\\t\\t\\t\\t(firstLine ifTrue: [textStyle firstIndent]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [textStyle restIndent])].\\n\\tdestX _ spaceX _ leftMargin.\\n\\tfirstDestX _ destX.\\n\\trightMargin _ lineRectangle right.\\n\\trightSide ifTrue: [rightMargin _ rightMargin - textStyle rightIndent].\\n\\tlastIndex _ startIndex.\\t\\\"scanning sets last index\\\"\\n\\tdestY _ lineRectangle top.\\n\\tlineHeight _ baseline _ 0. \\\"Will be increased by setFont\\\"\\n\\tself setStopConditions.\\t\\\"also sets font\\\"\\n\\trunLength _ text runLengthFor: startIndex.\\n\\trunStopIndex _ (lastIndex _ startIndex) + (runLength - 1).\\n\\tline _ (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)\\n\\t\\t\\t\\trectangle: lineRectangle.\\n\\tpresentationLine _ (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)\\n\\t\\t\\t\\trectangle: lineRectangle.\\n\\tnumOfComposition _ 0.\\n\\tspaceCount _ 0.\\n\\tself handleIndentation.\\n\\tleftMargin _ destX.\\n\\tline leftMargin: leftMargin.\\n\\tpresentationLine leftMargin: leftMargin.\\n\\n\\tpresentation _ TextStream on: (Text fromString: (WideString new: text size)).\\n\\n\\tdone _ false.\\n\\t[done]\\n\\t\\twhileFalse: \\n\\t\\t\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\\"See setStopConditions for stopping conditions for composing.\\\"\\n\\t\\t\\t(self perform: stopCondition)\\n\\t\\t\\t\\tifTrue: [presentationLine lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading.\\n\\t\\t\\t\\t\\t\\t^ line lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading]]! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'ar 4/12/2005 17:34'!\\ncomposeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph \\n\\t\\\"Answer an instance of TextLineInterval that represents the next line in the paragraph.\\\"\\n\\t| runLength done stopCondition |\\n\\tdestX _ spaceX _ leftMargin _ aParagraph leftMarginForCompositionForLine: lineIndex.\\n\\tdestY _ 0.\\n\\trightMargin _ aParagraph rightMarginForComposition.\\n\\tleftMargin >= rightMargin ifTrue: [self error: 'No room between margins to compose'].\\n\\tlastIndex _ startIndex.\\t\\\"scanning sets last index\\\"\\n\\tlineHeight _ textStyle lineGrid. \\\"may be increased by setFont:...\\\"\\n\\tbaseline _ textStyle baseline.\\n\\tbaselineY _ destY + baseline.\\n\\tself setStopConditions.\\t\\\"also sets font\\\"\\n\\tself handleIndentation.\\n\\trunLength _ text runLengthFor: startIndex.\\n\\trunStopIndex _ (lastIndex _ startIndex) + (runLength - 1).\\n\\tline _ TextLineInterval\\n\\t\\tstart: lastIndex\\n\\t\\tstop: 0\\n\\t\\tinternalSpaces: 0\\n\\t\\tpaddingWidth: 0.\\n\\tpresentationLine _ TextLineInterval\\n\\t\\tstart: lastIndex\\n\\t\\tstop: 0\\n\\t\\tinternalSpaces: 0\\n\\t\\tpaddingWidth: 0.\\n\\tnumOfComposition _ 0.\\n\\tpresentation _ TextStream on: (Text fromString: (WideString new: text size)).\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\t[done]\\n\\t\\twhileFalse: \\n\\t\\t\\t[stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\tin: text string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\\"See setStopConditions for stopping conditions for composing.\\\"\\n\\t\\t\\t(self perform: stopCondition)\\n\\t\\t\\t\\tifTrue: [presentationLine lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading.\\n\\t\\t\\t\\t\\t\\t^line lineHeight: lineHeight + textStyle leading\\n\\t\\t\\t\\t\\t\\t\\tbaseline: baseline + textStyle leading]]! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'yo 1/3/2003 11:54'!\\ncrossedX\\n\\t\\\"There is a word that has fallen across the right edge of the composition \\n\\trectangle. This signals the need for wrapping which is done to the last \\n\\tspace that was encountered, as recorded by the space stop condition.\\\"\\n\\n\\t(breakAtSpace) ifTrue: [\\n\\t\\tspaceCount >= 1 ifTrue:\\n\\t\\t\\t[\\\"The common case. First back off to the space at which we wrap.\\\"\\n\\t\\t\\tline stop: breakableIndex.\\n\\t\\t\\tpresentationLine stop: breakableIndex - numOfComposition.\\n\\t\\t\\tlineHeight _ lineHeightAtBreak.\\n\\t\\t\\tbaseline _ baselineAtBreak.\\n\\t\\t\\tspaceCount _ spaceCount - 1.\\n\\t\\t\\tbreakableIndex _ breakableIndex - 1.\\n\\n\\t\\t\\t\\\"Check to see if any spaces preceding the one at which we wrap.\\n\\t\\t\\t\\tDouble space after punctuation, most likely.\\\"\\n\\t\\t\\t[(spaceCount > 1 and: [(text at: breakableIndex) = Space])]\\n\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t[spaceCount _ spaceCount - 1.\\n\\t\\t\\t\\t\\t\\\"Account for backing over a run which might\\n\\t\\t\\t\\t\\t\\tchange width of space.\\\"\\n\\t\\t\\t\\t\\tfont _ text fontAt: breakableIndex withStyle: textStyle.\\n\\t\\t\\t\\t\\tbreakableIndex _ breakableIndex - 1.\\n\\t\\t\\t\\t\\tspaceX _ spaceX - (font widthOf: Space)].\\n\\t\\t\\tline paddingWidth: rightMargin - spaceX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t\\t\\tpresentationLine internalSpaces: spaceCount.\\n\\t\\t\\tline internalSpaces: spaceCount]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"Neither internal nor trailing spaces -- almost never happens.\\\"\\n\\t\\t\\tlastIndex _ lastIndex - 1.\\n\\t\\t\\t[destX <= rightMargin]\\n\\t\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t\\t[destX _ destX - (font widthOf: (text at: lastIndex)).\\n\\t\\t\\t\\t\\tlastIndex _ lastIndex - 1].\\n\\t\\t\\tspaceX _ destX.\\n\\t\\t\\tline paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine stop: (lastIndex max: line first).\\n\\t\\t\\tline stop: (lastIndex max: line first)].\\n\\t\\t^true\\n\\t].\\n\\n\\t(breakableIndex isNil or: [breakableIndex < line first]) ifTrue: [\\n\\t\\t\\\"Any breakable point in this line. Just wrap last character.\\\"\\n\\t\\tbreakableIndex _ lastIndex - 1.\\n\\t\\tlineHeightAtBreak _ lineHeight.\\n\\t\\tbaselineAtBreak _ baseline.\\n\\t].\\n\\n\\t\\\"It wasn't a space, but anyway this is where we break the line.\\\"\\n\\tline stop: breakableIndex.\\n\\tpresentationLine stop: breakableIndex.\\n\\tlineHeight _ lineHeightAtBreak.\\n\\tbaseline _ baselineAtBreak.\\n\\t^ true.\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'scanning' stamp: 'tak 12/22/2004 00:59'!\\nsetActualFont: aFont\\n\\t\\\"Keep track of max height and ascent for auto lineheight\\\"\\n\\t| descent |\\n\\tsuper setActualFont: aFont.\\n\\t\\\"' ', lastIndex printString, ' ' displayAt: (lastIndex * 15)@0.\\\"\\n\\tlineHeight == nil\\n\\t\\tifTrue: [descent _ font descent.\\n\\t\\t\\t\\tbaseline _ font ascent.\\n\\t\\t\\t\\tlineHeight _ baseline + descent]\\n\\t\\tifFalse: [descent _ lineHeight - baseline max: font descent.\\n\\t\\t\\t\\tbaseline _ baseline max: font ascent.\\n\\t\\t\\t\\tlineHeight _ lineHeight max: baseline + descent]! !\\n\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\ncolumnBreak\\n\\n\\t\\\"Answer true. Set up values for the text line interval currently being \\n\\tcomposed.\\\"\\n\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\tspaceX _ destX.\\n\\tline paddingWidth: rightMargin - spaceX.\\n\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t^true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\ncr\\n\\t\\\"Answer true. Set up values for the text line interval currently being \\n\\tcomposed.\\\"\\n\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\tspaceX _ destX.\\n\\tline paddingWidth: rightMargin - spaceX.\\n\\tpresentationLine paddingWidth: rightMargin - spaceX.\\n\\t^true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 2/10/2004 23:03'!\\nendOfRun\\n\\t\\\"Answer true if scanning has reached the end of the paragraph. \\n\\tOtherwise step conditions (mostly install potential new font) and answer \\n\\tfalse.\\\"\\n\\n\\t| runLength |\\n\\tlastIndex = text size\\n\\tifTrue:\\t[line stop: lastIndex.\\n\\t\\t\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\t\\t\\tspaceX _ destX.\\n\\t\\t\\tline paddingWidth: rightMargin - destX.\\n\\t\\t\\tpresentationLine paddingWidth: rightMargin - destX.\\n\\t\\t\\t^true]\\n\\tifFalse:\\t[\\n\\t\\t\\t\\\"(text at: lastIndex) charCode = 32 ifTrue: [destX _ destX + spaceWidth].\\\"\\n\\t\\t\\trunLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).\\n\\t\\t\\trunStopIndex _ lastIndex + (runLength - 1).\\n\\t\\t\\tself setStopConditions.\\n\\t\\t\\t^false]\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 1/3/2003 11:56'!\\nplaceEmbeddedObject: anchoredMorph\\n\\t| descent |\\n\\t\\\"Workaround: The following should really use #textAnchorType\\\"\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[^true].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [\\\"It doesn't fit\\\"\\n\\t\\t\\\"But if it's the first character then leave it here\\\"\\n\\t\\tlastIndex < line first ifFalse:[\\n\\t\\t\\tline stop: lastIndex-1.\\n\\t\\t\\t^ false]].\\n\\tdescent _ lineHeight - baseline.\\n\\tlineHeight _ lineHeight max: anchoredMorph height.\\n\\tbaseline _ lineHeight - descent.\\n\\tline stop: lastIndex.\\n\\tpresentationLine stop: lastIndex - numOfComposition.\\n\\t^ true! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 21:47'!\\nsetFont\\n\\tsuper setFont.\\n\\tbreakAtSpace _ false.\\n\\twantsColumnBreaks == true ifTrue: [\\n\\t\\tstopConditions _ stopConditions copy.\\n\\t\\tstopConditions at: TextComposer characterForColumnBreak asciiValue + 1 put: #columnBreak.\\n\\t].\\n! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:57'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont! !\\n\\n!MultiCompositionScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:57'!\\ntab\\n\\t\\\"Advance destination x according to tab settings in the paragraph's \\n\\ttextStyle. Answer whether the character has crossed the right edge of \\n\\tthe composition rectangle of the paragraph.\\\"\\n\\n\\tdestX _ textStyle\\n\\t\\t\\t\\tnextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.\\n\\tdestX > rightMargin ifTrue:\\t[^self crossedX].\\n\\tlastIndex _ lastIndex + 1.\\n\\t^false\\n! !\\nMultiCharacterScanner subclass: #MultiDisplayScanner\\n\\tinstanceVariableNames: 'bitBlt lineY runX foregroundColor backgroundColor fillBlt lineHeight paragraph paragraphColor morphicOffset ignoreColorChanges'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiDisplayScanner methodsFor: 'MVC-compatibility' stamp: 'yo 1/7/2005 12:15'!\\ndisplayLines: linesInterval in: aParagraph clippedBy: visibleRectangle\\n\\t\\\"The central display routine. The call on the primitive \\n\\t(scanCharactersFrom:to:in:rightX:) will be interrupted according to an \\n\\tarray of stop conditions passed to the scanner at which time the code to \\n\\thandle the stop condition is run and the call on the primitive continued \\n\\tuntil a stop condition returns true (which means the line has \\n\\tterminated).\\\"\\n\\t| runLength done stopCondition leftInRun startIndex string lastPos |\\n\\t\\\"leftInRun is the # of characters left to scan in the current run;\\n\\t\\twhen 0, it is time to call 'self setStopConditions'\\\"\\n\\tmorphicOffset _ 0@0.\\n\\tleftInRun _ 0.\\n\\tself initializeFromParagraph: aParagraph clippedBy: visibleRectangle.\\n\\tignoreColorChanges _ false.\\n\\tparagraph _ aParagraph.\\n\\tforegroundColor _ paragraphColor _ aParagraph foregroundColor.\\n\\tbackgroundColor _ aParagraph backgroundColor.\\n\\taParagraph backgroundColor isTransparent\\n\\t\\tifTrue: [fillBlt _ nil]\\n\\t\\tifFalse: [fillBlt _ bitBlt copy. \\\"Blt to fill spaces, tabs, margins\\\"\\n\\t\\t\\t\\tfillBlt sourceForm: nil; sourceOrigin: 0@0.\\n\\t\\t\\t\\tfillBlt fillColor: aParagraph backgroundColor].\\n\\trightMargin _ aParagraph rightMarginForDisplay.\\n\\tlineY _ aParagraph topAtLineIndex: linesInterval first.\\n\\tbitBlt destForm deferUpdatesIn: visibleRectangle while: [\\n\\t\\tlinesInterval do: \\n\\t\\t\\t[:lineIndex | \\n\\t\\t\\tleftMargin _ aParagraph leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment]).\\n\\t\\t\\tdestX _ (runX _ leftMargin).\\n\\t\\t\\tline _ aParagraph lines at: lineIndex.\\n\\t\\t\\tlineHeight _ line lineHeight.\\n\\t\\t\\tfillBlt == nil ifFalse:\\n\\t\\t\\t\\t[fillBlt destX: visibleRectangle left destY: lineY\\n\\t\\t\\t\\t\\twidth: visibleRectangle width height: lineHeight; copyBits].\\n\\t\\t\\tlastIndex _ line first.\\n\\t\\t\\tleftInRun <= 0\\n\\t\\t\\t\\tifTrue: [self setStopConditions. \\\"also sets the font\\\"\\n\\t\\t\\t\\t\\t\\tleftInRun _ text runLengthFor: line first].\\n\\t\\t\\tbaselineY _ lineY + line baseline.\\n\\t\\t\\tdestY _ baselineY - font ascent. \\\"Should have happened in setFont\\\"\\n\\t\\t\\trunLength _ leftInRun.\\n\\t\\t\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\t\\t\\tleftInRun _ leftInRun - (runStopIndex - lastIndex + 1).\\n\\t\\t\\tspaceCount _ 0.\\n\\t\\t\\tdone _ false.\\n\\t\\t\\tstring _ text string.\\n\\t\\t\\tself handleIndentation.\\n\\t\\t\\t[done] whileFalse:[\\n\\t\\t\\t\\tstartIndex _ lastIndex.\\n\\t\\t\\t\\tlastPos _ destX@destY.\\n\\t\\t\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\t\\tin: string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\t\\tkern: kern.\\n\\t\\t\\t\\tlastIndex >= startIndex ifTrue:[\\n\\t\\t\\t\\t\\tfont displayString: string on: bitBlt \\n\\t\\t\\t\\t\\t\\tfrom: startIndex to: lastIndex at: lastPos kern: kern baselineY: baselineY].\\n\\t\\t\\t\\t\\\"see setStopConditions for stopping conditions for displaying.\\\"\\n\\t\\t\\t\\tdone _ self perform: stopCondition].\\n\\t\\t\\tfillBlt == nil ifFalse:\\n\\t\\t\\t\\t[fillBlt destX: destX destY: lineY width: visibleRectangle right-destX height: lineHeight; copyBits].\\n\\t\\t\\tlineY _ lineY + lineHeight]]! !\\n\\n!MultiDisplayScanner methodsFor: 'MVC-compatibility' stamp: 'yo 3/14/2005 06:48'!\\ninitializeFromParagraph: aParagraph clippedBy: clippingRectangle\\n\\n\\tsuper initializeFromParagraph: aParagraph clippedBy: clippingRectangle.\\n\\tbitBlt _ BitBlt asGrafPort toForm: aParagraph destinationForm.\\n\\tbitBlt sourceX: 0; width: 0.\\t\\\"Init BitBlt so that the first call to a primitive will not fail\\\"\\n\\tbitBlt combinationRule: Form paint.\\n\\tbitBlt colorMap:\\n\\t\\t(Bitmap with: 0 \\\"Assumes 1-bit deep fonts\\\"\\n\\t\\t\\t\\twith: (bitBlt destForm pixelValueFor: aParagraph foregroundColor)).\\n\\tbitBlt clipRect: clippingRectangle.\\n! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'multilingual scanning' stamp: 'yo 12/20/2002 11:52'!\\nisBreakableAt: index in: sourceString in: encodingClass\\n\\n\\t^ false.\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'multilingual scanning' stamp: 'yo 8/6/2003 05:57'!\\nscanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta\\n\\n\\t| encoding f nextDestX maxAscii startEncoding char charValue |\\n\\tlastIndex _ startIndex.\\n\\tlastIndex > stopIndex ifTrue: [lastIndex _ stopIndex. ^ stops at: EndOfRun].\\n\\tstartEncoding _ (sourceString at: startIndex) leadingChar.\\n\\tfont ifNil: [font _ (TextConstants at: #DefaultMultiStyle) fontArray at: 1].\\n\\t((font isMemberOf: StrikeFontSet) or: [font isKindOf: TTCFontSet]) ifTrue: [\\n\\t\\t[f _ font fontArray at: startEncoding + 1]\\n\\t\\t\\ton: Exception do: [:ex | f _ font fontArray at: 1].\\n\\t\\tf ifNil: [ f _ font fontArray at: 1].\\n\\t\\tmaxAscii _ f maxAscii.\\n\\t\\tspaceWidth _ f widthOf: Space.\\n\\t] ifFalse: [\\n\\t\\tmaxAscii _ font maxAscii.\\n\\t].\\n\\n\\t[lastIndex <= stopIndex] whileTrue: [\\n\\t\\tencoding _ (sourceString at: lastIndex) leadingChar.\\n\\t\\tencoding ~= startEncoding ifTrue: [lastIndex _ lastIndex - 1. ^ stops at: EndOfRun].\\n\\t\\tchar _ (sourceString at: lastIndex).\\n\\t\\tcharValue _ char charCode.\\n\\t\\tcharValue > maxAscii ifTrue: [charValue _ maxAscii].\\n\\t\\t(encoding = 0 and: [(stopConditions at: charValue + 1) ~~ nil]) ifTrue: [\\n\\t\\t\\t^ stops at: charValue + 1\\n\\t\\t].\\n\\t\\tnextDestX _ destX + (self widthOf: char inFont: font).\\n\\t\\tnextDestX > rightX ifTrue: [^ stops at: CrossedX].\\n\\t\\tdestX _ nextDestX + kernDelta.\\n\\t\\tlastIndex _ lastIndex + 1.\\n\\t].\\n\\tlastIndex _ stopIndex.\\n\\t^ stops at: EndOfRun! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'scanning' stamp: 'yo 1/7/2005 12:15'!\\ndisplayLine: textLine offset: offset leftInRun: leftInRun\\n\\t\\\"The call on the primitive (scanCharactersFrom:to:in:rightX:) will be interrupted according to an array of stop conditions passed to the scanner at which time the code to handle the stop condition is run and the call on the primitive continued until a stop condition returns true (which means the line has terminated). leftInRun is the # of characters left to scan in the current run; when 0, it is time to call setStopConditions.\\\"\\n\\t| done stopCondition nowLeftInRun startIndex string lastPos |\\n\\tline _ textLine.\\n\\tmorphicOffset _ offset.\\n\\tlineY _ line top + offset y.\\n\\tlineHeight _ line lineHeight.\\n\\trightMargin _ line rightMargin + offset x.\\n\\tlastIndex _ line first.\\n\\tleftInRun <= 0 ifTrue: [self setStopConditions].\\n\\tleftMargin _ (line leftMarginForAlignment: alignment) + offset x.\\n\\tdestX _ runX _ leftMargin.\\n\\tfillBlt == nil ifFalse:\\n\\t\\t[\\\"Not right\\\"\\n\\t\\tfillBlt destX: line left destY: lineY\\n\\t\\t\\twidth: line width left height: lineHeight; copyBits].\\n\\tlastIndex _ line first.\\n\\tleftInRun <= 0\\n\\t\\tifTrue: [nowLeftInRun _ text runLengthFor: lastIndex]\\n\\t\\tifFalse: [nowLeftInRun _ leftInRun].\\n\\tbaselineY _ lineY + line baseline.\\n\\tdestY _ baselineY - font ascent.\\n\\trunStopIndex _ lastIndex + (nowLeftInRun - 1) min: line last.\\n\\tspaceCount _ 0.\\n\\tdone _ false.\\n\\tstring _ text string.\\n\\t[done] whileFalse:[\\n\\t\\tstartIndex _ lastIndex.\\n\\t\\tlastPos _ destX@destY.\\n\\t\\tstopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex\\n\\t\\t\\t\\t\\t\\tin: string rightX: rightMargin stopConditions: stopConditions\\n\\t\\t\\t\\t\\t\\tkern: kern.\\n\\t\\tlastIndex >= startIndex ifTrue:[\\n\\t\\t\\tfont displayString: string on: bitBlt \\n\\t\\t\\t\\tfrom: startIndex to: lastIndex at: lastPos kern: kern baselineY: baselineY].\\n\\t\\t\\\"see setStopConditions for stopping conditions for displaying.\\\"\\n\\t\\tdone _ self perform: stopCondition.\\n\\t\\t\\\"lastIndex > runStopIndex ifTrue: [done _ true].\\\"\\n\\t].\\n\\t^ runStopIndex - lastIndex \\\"Number of characters remaining in the current run\\\"! !\\n\\n!MultiDisplayScanner methodsFor: 'scanning' stamp: 'lr 1/21/2006 16:01'!\\nplaceEmbeddedObject: anchoredMorph\\n\\tanchoredMorph relativeTextAnchorPosition ifNotNil:[\\n\\t\\tanchoredMorph position: \\n\\t\\t\\tanchoredMorph relativeTextAnchorPosition +\\n\\t\\t\\t(anchoredMorph owner textBounds origin x @ 0)\\n\\t\\t\\t- (0@morphicOffset y) + (0@lineY).\\n\\t\\t^true\\n\\t].\\n\\t(super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].\\n\\tanchoredMorph isMorph ifTrue: [\\n\\t\\tanchoredMorph position: ((destX - anchoredMorph width)@lineY) - morphicOffset\\n\\t] ifFalse: [\\n\\t\\tdestY _ lineY.\\n\\t\\tbaselineY _ lineY + anchoredMorph height..\\n\\t\\trunX _ destX.\\n\\t\\tanchoredMorph \\n\\t\\t\\tdisplayOn: bitBlt destForm \\n\\t\\t\\tat: destX - anchoredMorph width @ destY\\n\\t\\t\\tclippingBox: bitBlt clipRect\\n\\t\\t\\trule: Form blend\\n\\t\\t\\tfillColor: Color white \\n\\t].\\n\\t^ true! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ncr\\n\\t\\\"When a carriage return is encountered, simply increment the pointer \\n\\tinto the paragraph.\\\"\\n\\n\\tlastIndex_ lastIndex + 1.\\n\\t^false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ncrossedX\\n\\t\\\"This condition will sometimes be reached 'legally' during display, when, \\n\\tfor instance the space that caused the line to wrap actually extends over \\n\\tthe right boundary. This character is allowed to display, even though it \\n\\tis technically outside or straddling the clipping ectangle since it is in \\n\\tthe normal case not visible and is in any case appropriately clipped by \\n\\tthe scanner.\\\"\\n\\n\\t^ true ! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nendOfRun\\n\\t\\\"The end of a run in the display case either means that there is actually \\n\\ta change in the style (run code) to be associated with the string or the \\n\\tend of this line has been reached.\\\"\\n\\t| runLength |\\n\\tlastIndex = line last ifTrue: [^true].\\n\\trunX _ destX.\\n\\trunLength _ text runLengthFor: (lastIndex _ lastIndex + 1).\\n\\trunStopIndex _ lastIndex + (runLength - 1) min: line last.\\n\\tself setStopConditions.\\n\\t^ false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\npaddedSpace\\n\\t\\\"Each space is a stop condition when the alignment is right justified. \\n\\tPadding must be added to the base width of the space according to \\n\\twhich space in the line this space is and according to the amount of \\n\\tspace that remained at the end of the line when it was composed.\\\"\\n\\n\\tspaceCount _ spaceCount + 1.\\n\\tdestX _ destX + spaceWidth + (line justifiedPadFor: spaceCount).\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nplainTab\\n\\t| oldX |\\n\\toldX _ destX.\\n\\tsuper plainTab.\\n\\tfillBlt == nil ifFalse:\\n\\t\\t[fillBlt destX: oldX destY: destY width: destX - oldX height: font height; copyBits]! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\nsetStopConditions\\n\\t\\\"Set the font and the stop conditions for the current run.\\\"\\n\\t\\n\\tself setFont.\\n\\tself setConditionArray: (alignment = Justified ifTrue: [#paddedSpace]).\\n\\n\\\"\\n\\talignment = Justified ifTrue: [\\n\\t\\tstopConditions == DefaultStopConditions \\n\\t\\t\\tifTrue:[stopConditions _ stopConditions copy].\\n\\t\\tstopConditions at: Space asciiValue + 1 put: #paddedSpace]\\n\\\"! !\\n\\n!MultiDisplayScanner methodsFor: 'stop conditions' stamp: 'yo 12/18/2002 13:58'!\\ntab\\n\\tself plainTab.\\n\\tlastIndex _ lastIndex + 1.\\n\\t^ false! !\\n\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 1/23/2003 14:40'!\\npresentationText: t\\n\\n\\ttext _ t.\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\nsetDestForm: df\\n\\tbitBlt setDestForm: df.! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 1/6/2005 23:06'!\\nsetFont \\n\\tforegroundColor _ paragraphColor.\\n\\tsuper setFont. \\\"Sets font and emphasis bits, and maybe foregroundColor\\\"\\n\\tfont installOn: bitBlt foregroundColor: foregroundColor backgroundColor: Color transparent.\\n\\ttext ifNotNil:[\\n\\t\\tbaselineY _ lineY + line baseline.\\n\\t\\tdestY _ baselineY - font ascent].\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\nsetPort: aBitBlt\\n\\t\\\"Install the BitBlt to use\\\"\\n\\tbitBlt _ aBitBlt.\\n\\tbitBlt sourceX: 0; width: 0.\\t\\\"Init BitBlt so that the first call to a primitive will not fail\\\"\\n\\tbitBlt sourceForm: nil. \\\"Make sure font installation won't be confused\\\"\\n! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\ntext: t textStyle: ts foreground: foreColor background: backColor fillBlt: blt ignoreColorChanges: shadowMode\\n\\ttext _ t.\\n\\ttextStyle _ ts. \\n\\tforegroundColor _ paragraphColor _ foreColor.\\n\\t(backgroundColor _ backColor) isTransparent ifFalse:\\n\\t\\t[fillBlt _ blt.\\n\\t\\tfillBlt fillColor: backgroundColor].\\n\\tignoreColorChanges _ shadowMode! !\\n\\n!MultiDisplayScanner methodsFor: 'private' stamp: 'yo 12/18/2002 13:58'!\\ntextColor: textColor\\n\\tignoreColorChanges ifTrue: [^ self].\\n\\tforegroundColor _ textColor! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiDisplayScanner class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiDisplayScanner class methodsFor: 'queries' stamp: 'yo 12/18/2002 13:58'!\\ndefaultFont\\n\\t^ TextStyle defaultFont! !\\nNewParagraph subclass: #MultiNewParagraph\\n\\tinstanceVariableNames: 'presentationText presentationLines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 16:09'!\\ndisplayOn: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\n\\t| visibleRectangle offset leftInRun line |\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ somePosition - positionWhenComposed.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ lines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 22:33'!\\ndisplayOnTest: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\n\\t| visibleRectangle offset leftInRun line |\\n\\t(presentationText isNil or: [presentationLines isNil]) ifTrue: [\\n\\t\\t^ self displayOn: aCanvas using: displayScanner at: somePosition.\\n\\t].\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ somePosition - positionWhenComposed.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ presentationLines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\nmultiComposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult composer presentationInfo |\\n\\n\\tcomposer _ MultiTextComposer new.\\n\\tpresentationLines _ nil.\\n\\tpresentationText _ nil.\\n\\tnewResult _ composer\\n\\t\\tmultiComposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\tpresentationInfo _ composer getPresentationInfo.\\n\\tpresentationLines _ presentationInfo first asArray.\\n\\tpresentationText _ presentationInfo second.\\n\\t\\\"maxRightX printString displayAt: 0@0.\\\"\\n\\t^maxRightX\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 17:31'!\\npresentationLines\\n\\n\\t^ presentationLines.\\n! !\\n\\n!MultiNewParagraph methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 17:31'!\\npresentationText\\n\\n\\t^ presentationText.\\n! !\\nFormCanvas subclass: #MultiResolutionCanvas\\n\\tinstanceVariableNames: 'deferredMorphs'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/4/2000 12:00'!\\ndeferredMorphs\\n\\n\\t^deferredMorphs! !\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/4/2000 11:58'!\\ndeferredMorphs: aCollection\\n\\n\\tdeferredMorphs _ aCollection! !\\n\\n!MultiResolutionCanvas methodsFor: 'as yet unclassified' stamp: 'RAA 12/17/2000 13:25'!\\ninitializeFrom: aFormCanvas\\n\\n\\torigin _ aFormCanvas origin.\\n\\tclipRect _ aFormCanvas privateClipRect.\\n\\tform _ aFormCanvas form.\\n\\tport _ aFormCanvas privatePort.\\n\\tshadowColor _ aFormCanvas shadowColor.\\n! !\\n\\n\\n!MultiResolutionCanvas methodsFor: 'drawing-general' stamp: 'RAA 12/4/2000 12:00'!\\nfullDraw: aMorph\\n\\n\\taMorph canDrawAtHigherResolution ifTrue: [\\n\\t\\tdeferredMorphs ifNil: [deferredMorphs _ OrderedCollection new].\\n\\t\\tdeferredMorphs add: aMorph.\\n\\t] ifFalse: [\\n\\t\\tsuper fullDraw: aMorph\\n\\t].! !\\nTTCFont subclass: #MultiTTCFont\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:08'!\\naccess: char at: index\\n\\n\\t| wcache entry |\\n\\twcache _ self cache.\\n\\tentry _ wcache at: index.\\n\\twcache replaceFrom: index to: wcache size - 1 with: wcache startingAt: index + 1.\\n\\twcache at: wcache size put: entry.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:09'!\\nat: char put: form\\n\\n\\t| wcache |\\n\\twcache _ self cache.\\n\\twcache replaceFrom: 1 to: wcache size - 1 with: wcache startingAt: 2.\\n\\twcache at: wcache size\\n\\t\\tput: (Array with: char asciiValue with: foregroundColor with: form).\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:27'!\\nflushCache\\n\\n\\tcache at: 1 put: ((1 to: 128) collect: [:i | Array with: -1 with: nil with: nil]).\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 21:04'!\\nformOf: char\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\t^ form.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\t^ newForm.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 1/7/2005 11:09'!\\nglyphInfoOf: char into: glyphInfoArray\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\tglyphInfoArray at: 1 put: form;\\n\\t\\t\\tat: 2 put: 0;\\n\\t\\t\\tat: 3 put: form width;\\n\\t\\t\\tat: 4 put: (self ascentOf: char);\\n\\t\\t\\tat: 5 put: self.\\n\\t\\t^ glyphInfoArray.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\n\\tglyphInfoArray at: 1 put: newForm;\\n\\t\\tat: 2 put: 0;\\n\\t\\tat: 3 put: newForm width;\\n\\t\\tat: 4 put: (self ascentOf: char);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:39'!\\nhasCached: char ifTrue: twoArgBlock\\n\\n\\t| value elem |\\n\\tvalue _ char asciiValue.\\n\\n\\tself cache size to: 1 by: -1 do: [:i |\\n\\t\\telem _ self cache at: i.\\n\\t\\t(elem first = value and: [elem second = foregroundColor]) ifTrue: [\\n\\t\\t\\t^ twoArgBlock value: elem third value: i.\\n\\t\\t].\\n\\t].\\n\\t^ false.\\n! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/29/2003 15:01'!\\nisTTCFont\\n\\t^true! !\\n\\n!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:30'!\\nwidthOf: char\\n\\n\\t\\\"This method cannot use #formOf: because formOf: discriminates the color and causes unnecessary bitmap creation.\\\"\\n\\n\\t| newForm |\\n\\tself hasCached: char ifTrue: [:form :index |\\n\\t\\tself access: char at: index.\\n\\t\\t^ form width.\\n\\t].\\n\\n\\tnewForm _ self computeForm: char.\\n\\tself at: char put: newForm.\\n\\t^ newForm width.\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiTTCFont class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiTTCFont class methodsFor: 'as yet unclassified' stamp: 'yo 12/10/2002 18:34'!\\ncacheAllNil\\n\\\"\\n\\tself cacheAllNil\\n\\\"\\n\\tself allInstances do: [:inst |\\n\\t\\tinst cache do: [:e |\\n\\t\\t\\te third ifNotNil: [^ false].\\n\\t\\t].\\n\\t].\\n\\n\\t^ true.\\n! !\\nTextComposer subclass: #MultiTextComposer\\n\\tinstanceVariableNames: 'presentation presentationLines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Multilingual-Scanning'!\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\ncomposeEachRectangleIn: rectangles\\n\\n\\t| myLine lastChar |\\n\\n\\t1 to: rectangles size do: [:i | \\n\\t\\tcurrCharIndex <= theText size ifFalse: [^false].\\n\\t\\tmyLine _ scanner \\n\\t\\t\\tcomposeFrom: currCharIndex \\n\\t\\t\\tinRectangle: (rectangles at: i)\\t\\t\\t\\t\\n\\t\\t\\tfirstLine: isFirstLine \\n\\t\\t\\tleftSide: i=1 \\n\\t\\t\\trightSide: i=rectangles size.\\n\\t\\tlines addLast: myLine.\\n\\t\\tpresentationLines addLast: scanner getPresentationLine.\\n\\t\\tpresentation ifNil: [presentation _ scanner getPresentation]\\n\\t\\t\\tifNotNil: [presentation _ presentation, scanner getPresentation].\\n\\t\\tactualHeight _ actualHeight max: myLine lineHeight. \\\"includes font changes\\\"\\n\\t\\tcurrCharIndex _ myLine last + 1.\\n\\t\\tlastChar _ theText at: myLine last.\\n\\t\\tlastChar = Character cr ifTrue: [^#cr].\\n\\t\\twantsColumnBreaks ifTrue: [\\n\\t\\t\\tlastChar = TextComposer characterForColumnBreak ifTrue: [^#columnBreak].\\n\\t\\t].\\n\\t].\\n\\t^false! !\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/23/2003 12:53'!\\ngetPresentationInfo\\n\\n\\t^ Array with: presentationLines with: presentation.\\n! !\\n\\n!MultiTextComposer methodsFor: 'as yet unclassified' stamp: 'yo 1/16/2003 17:30'!\\nmultiComposeLinesFrom: argStart to: argStop delta: argDelta into: argLinesCollection priorLines: argPriorLines atY: argStartY textStyle: argTextStyle text: argText container: argContainer wantsColumnBreaks: argWantsColumnBreaks\\n\\n\\twantsColumnBreaks _ argWantsColumnBreaks.\\n\\tlines _ argLinesCollection.\\n\\tpresentationLines _ argLinesCollection copy.\\n\\ttheTextStyle _ argTextStyle.\\n\\ttheText _ argText.\\n\\ttheContainer _ argContainer.\\n\\tdeltaCharIndex _ argDelta.\\n\\tcurrCharIndex _ startCharIndex _ argStart.\\n\\tstopCharIndex _ argStop.\\n\\tprevLines _ argPriorLines.\\n\\tcurrentY _ argStartY.\\n\\tdefaultLineHeight _ theTextStyle lineGrid.\\n\\tmaxRightX _ theContainer left.\\n\\tpossibleSlide _ stopCharIndex < theText size and: [theContainer isMemberOf: Rectangle].\\n\\tnowSliding _ false.\\n\\tprevIndex _ 1.\\n\\tscanner _ MultiCompositionScanner new text: theText textStyle: theTextStyle.\\n\\tscanner wantsColumnBreaks: wantsColumnBreaks.\\n\\tisFirstLine _ true.\\n\\tself composeAllLines.\\n\\tisFirstLine ifTrue: [\\\"No space in container or empty text\\\"\\n\\t\\tself \\n\\t\\t\\taddNullLineWithIndex: startCharIndex\\n\\t\\t\\tandRectangle: (theContainer topLeft extent: 0@defaultLineHeight)\\n\\t] ifFalse: [\\n\\t\\tself fixupLastLineIfCR\\n\\t].\\n\\t^{lines asArray. maxRightX}\\n\\n! !\\nLazyListMorph subclass: #MulticolumnLazyListMorph\\n\\tinstanceVariableNames: 'columnWidths'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n!MulticolumnLazyListMorph commentStamp: '<historical>' prior: 0!\\nA variant of LazyListMorph that can display multi-column lists.!\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'as yet unclassified' stamp: 'ls 5/17/2001 21:23'!\\ngetListItem: index\\n\\t^listSource getListRow: index! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'as yet unclassified' stamp: 'ls 5/18/2001 16:43'!\\nlistChanged\\n\\tcolumnWidths := nil.\\n\\tsuper listChanged! !\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'nk 1/10/2004 16:19'!\\ndisplay: items atRow: row on: canvas \\n\\t\\\"display the specified item, which is on the specified row; for Multicolumn \\n\\tlists, items will be a list of strings\\\"\\n\\t| drawBounds |\\n\\tdrawBounds := self drawBoundsForRow: row.\\n\\tdrawBounds := drawBounds intersect: self bounds.\\n\\titems\\n\\t\\twith: (1 to: items size)\\n\\t\\tdo: [:item :index | \\n\\t\\t\\t\\\"move the bounds to the right at each step\\\"\\n\\t\\t\\tindex > 1\\n\\t\\t\\t\\tifTrue: [drawBounds := drawBounds left: drawBounds left + 6\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t+ (columnWidths at: index - 1)].\\n\\t\\t\\titem isText\\n\\t\\t\\t\\tifTrue: [canvas\\n\\t\\t\\t\\t\\t\\tdrawString: item\\n\\t\\t\\t\\t\\t\\tin: drawBounds\\n\\t\\t\\t\\t\\t\\tfont: (font\\n\\t\\t\\t\\t\\t\\t\\t\\temphasized: (item emphasisAt: 1))\\n\\t\\t\\t\\t\\t\\tcolor: (self colorForRow: row)]\\n\\t\\t\\t\\tifFalse: [canvas\\n\\t\\t\\t\\t\\t\\tdrawString: item\\n\\t\\t\\t\\t\\t\\tin: drawBounds\\n\\t\\t\\t\\t\\t\\tfont: font\\n\\t\\t\\t\\t\\t\\tcolor: (self colorForRow: row)]]! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'ls 5/17/2001 21:58'!\\ndrawOn: aCanvas\\n self getListSize = 0 ifTrue:[ ^self ].\\n\\n self setColumnWidthsFor: aCanvas.\\n\\n super drawOn: aCanvas! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'drawing' stamp: 'sps 3/23/2004 15:51'!\\nsetColumnWidthsFor: aCanvas\\n | row topRow bottomRow |\\n \\\"set columnWidths for drawing on the specified canvas\\\"\\n\\t\\tcolumnWidths ifNil: [\\n\\t\\tcolumnWidths := (self item: 1) collect: [ :ignored | 0 ]. ].\\n\\ttopRow := (self topVisibleRowForCanvas: aCanvas) max: 1.\\n\\tbottomRow := (self bottomVisibleRowForCanvas: aCanvas) max: 1.\\n\\ttopRow > bottomRow ifTrue: [ ^ self ].\\n\\ttopRow to: bottomRow do: [ :rowIndex |\\n row := self item: rowIndex.\\n columnWidths := columnWidths with: row collect: [ :currentWidth :item |\\n\\t\\t\\t\\t| widthOfItem |\\n\\t\\t\\t\\twidthOfItem := (font widthOfStringOrText: item).\\n\\t\\t\\t\\twidthOfItem > currentWidth\\n\\t\\t\\t\\t\\tifTrue: [ self changed. widthOfItem ]\\n\\t\\t\\t\\t\\tifFalse: [ currentWidth ] ] ]! !\\n\\n\\n!MulticolumnLazyListMorph methodsFor: 'scroll range' stamp: 'sps 4/2/2004 12:16'!\\nhUnadjustedScrollRange\\n\\\"multi column list morphs don't use hScrollbars\\\"\\n\\n\\t^0\\n\\n! !\\n\\n!MulticolumnLazyListMorph methodsFor: 'scroll range' stamp: 'ls 4/17/2004 12:21'!\\nwidthToDisplayItem: item\\n\\t| widths |\\n\\twidths := item collect: [ :each | super widthToDisplayItem: each ].\\n\\t^widths sum + (10 * (widths size - 1)) \\\"add in space between the columns\\\"\\n! !\\nSketchMorph subclass: #MultiuserTinyPaint\\n\\tinstanceVariableNames: 'drawState'\\n\\tclassVariableNames: 'LastMouseIndex PenColorIndex PenIndex PenSizeIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-AdditionalWidgets'!\\n!MultiuserTinyPaint commentStamp: '<historical>' prior: 0!\\nA very simple paint program that handles multiple users (hands).\\nEach user has their own brush size and color.\\n!\\n\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nhandlesMouseDown: evt\\n\\n\\t^ true\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nmouseDown: evt\\n\\n\\t| state |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\tstate at: LastMouseIndex put: evt cursorPoint.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!\\nmouseMove: evt\\n\\n\\t| state lastP p pen |\\n\\tstate _ drawState at: evt hand ifAbsent: [^ self].\\n\\tlastP _ state at: LastMouseIndex.\\n\\tp _ evt cursorPoint.\\n\\tp = lastP ifTrue: [^ self].\\n\\n\\tpen _ state at: PenIndex.\\n\\tpen drawFrom: lastP - bounds origin to: p - bounds origin.\\n\\tself invalidRect: (\\n\\t\\t((lastP min: p) - pen sourceForm extent) corner:\\n\\t\\t((lastP max: p) + pen sourceForm extent)).\\n\\tstate at: LastMouseIndex put: p.\\n! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color veryVeryLightGray! !\\n\\n!MultiuserTinyPaint methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:52'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tdrawState _ IdentityDictionary new.\\n\\tself clear! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'clear' translated action: #clear.\\n\\taCustomMenu add: 'pen color' translated action: #setPenColor:.\\n\\taCustomMenu add: 'pen size' translated action: #setPenSize:.\\n\\\"\\taCustomMenu add: 'fill' translated action: #fill:.\\\"\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 11/4/97 07:15'!\\nbrushColor: aColor hand: hand\\n\\n\\t| state |\\n\\t(drawState includesKey: hand) ifFalse: [self createDrawStateFor: hand].\\n\\tstate _ drawState at: hand.\\n\\t(state at: PenIndex) color: aColor.\\n\\tstate at: PenColorIndex put: aColor.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 11/4/97 07:15'!\\nclear\\n\\n\\t| newPen |\\n\\tself form: ((Form extent: 400@300 depth: 8) fillColor: color).\\n\\tdrawState do: [:state |\\n\\t\\tnewPen _ Pen newOnForm: originalForm.\\n\\t\\tnewPen roundNib: (state at: PenSizeIndex).\\n\\t\\tnewPen color: (state at: PenColorIndex).\\n\\t\\tstate at: PenIndex put: newPen].\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'bf 1/5/2000 19:12'!\\nfill: evt\\n\\n\\t| state fillPt |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\n\\tCursor blank show.\\n\\tCursor crossHair showWhile:\\n\\t\\t[fillPt _ Sensor waitButton - self position].\\n\\toriginalForm shapeFill: (state at: PenColorIndex) interiorPoint: fillPt.\\n\\tself changed.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'jm 9/26/97 14:47'!\\npenSize: anInteger hand: hand\\n\\n\\t| state |\\n\\t(drawState includesKey: hand) ifFalse: [self createDrawStateFor: hand].\\n\\tstate _ drawState at: hand.\\n\\tstate at: PenSizeIndex put: anInteger.\\n\\t(state at: PenIndex) roundNib: anInteger.\\n! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'ar 10/5/2000 18:52'!\\nsetPenColor: evt\\n\\t| state |\\n\\t(drawState includesKey: evt hand) ifFalse: [self createDrawStateFor: evt hand].\\n\\tstate _ drawState at: evt hand.\\n\\tself changeColorTarget: self selector: #brushColor:hand: originalColor: (state at: PenColorIndex) hand: evt hand! !\\n\\n!MultiuserTinyPaint methodsFor: 'menu' stamp: 'RAA 6/12/2000 09:07'!\\nsetPenSize: evt\\n\\n\\t| menu sizes |\\n\\tmenu _ MenuMorph new.\\n\\tsizes _ (0 to: 5), (6 to: 12 by: 2), (15 to: 40 by: 5).\\n\\tsizes do: [:w |\\n\\t\\tmenu add: w printString\\n\\t\\t\\ttarget: self\\n\\t\\t\\tselector: #penSize:hand:\\n\\t\\t\\targumentList: (Array with: w with: evt hand)].\\n\\n\\tmenu popUpEvent: evt in: self world! !\\n\\n\\n!MultiuserTinyPaint methodsFor: 'private' stamp: 'jm 11/4/97 07:15'!\\ncreateDrawStateFor: aHand\\n\\n\\t| pen state |\\n\\tpen _ Pen newOnForm: originalForm.\\n\\tstate _ Array new: 4.\\n\\tstate at: PenIndex put: pen.\\n\\tstate at: PenSizeIndex put: 3.\\n\\tstate at: PenColorIndex put: Color red.\\n\\tstate at: LastMouseIndex put: nil.\\n\\tdrawState at: aHand put: state.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMultiuserTinyPaint class\\n\\tinstanceVariableNames: ''!\\n\\n!MultiuserTinyPaint class methodsFor: 'class initialization' stamp: 'jm 11/4/97 07:15'!\\ninitialize\\n\\t\\\"MultiuserTinyPaint initialize\\\"\\n\\n\\t\\\"indices into the state array for a given hand\\\"\\n\\tPenIndex _ 1.\\n\\tPenSizeIndex _ 2.\\n\\tPenColorIndex _ 3.\\n\\tLastMouseIndex _ 4.\\n! !\\nObject subclass: #Mutex\\n\\tinstanceVariableNames: 'semaphore owner'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!Mutex commentStamp: '<historical>' prior: 0!\\nA Mutex is a light-weight MUTual EXclusion object being used when two or more processes need to access a shared resource concurrently. A Mutex grants ownership to a single process and will suspend any other process trying to aquire the mutex while in use. Waiting processes are granted access to the mutex in the order the access was requested.\\n\\nInstance variables:\\n\\tsemaphore\\t<Semaphore>\\t\\tThe (primitive) semaphore used for synchronization.\\n\\towner\\t\\t<Process>\\t\\tThe process owning the mutex.!\\n\\n\\n!Mutex methodsFor: 'initialize' stamp: 'das 11/3/2005 22:53'!\\ninitialize\\n\\tsemaphore := Semaphore forMutualExclusion.! !\\n\\n\\n!Mutex methodsFor: 'mutual exclusion' stamp: 'das 11/3/2005 22:53'!\\ncritical: aBlock\\n\\t\\\"Evaluate aBlock protected by the receiver.\\\"\\n\\t| activeProcess |\\n\\tactiveProcess := Processor activeProcess.\\n\\tactiveProcess == owner ifTrue:[^aBlock value].\\n\\t^semaphore critical:[\\n\\t\\towner := activeProcess.\\n\\t\\taBlock ensure:[owner := nil]].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMutex class\\n\\tinstanceVariableNames: ''!\\nObject subclass: #MutexSet\\n\\tinstanceVariableNames: 'array'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Processes'!\\n!MutexSet commentStamp: '<historical>' prior: 0!\\nA MutexSet helps with aquiring a set of mutexes.!\\n\\n\\n!MutexSet methodsFor: 'initialize' stamp: 'das 11/3/2005 22:54'!\\nwithAll: mutexList\\n\\tarray := mutexList.! !\\n\\n\\n!MutexSet methodsFor: 'mutual exclusion' stamp: 'das 11/3/2005 22:54'!\\ncritical: aBlock\\n\\t\\\"Evaluate aBlock aquiring all mutexes\\\"\\n\\t^self pvtCritical: aBlock startingAt: 1! !\\n\\n\\n!MutexSet methodsFor: 'private' stamp: 'das 11/3/2005 22:54'!\\npvtCritical: aBlock startingAt: index\\n\\t| mutex |\\n\\tindex > array size ifTrue:[^aBlock value].\\n\\tmutex := array at: index.\\n\\t^mutex critical:[self pvtCritical: aBlock startingAt: index+1].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nMutexSet class\\n\\tinstanceVariableNames: ''!\\n\\n!MutexSet class methodsFor: 'instance creation' stamp: 'das 11/3/2005 22:54'!\\nwithAll: mutexList\\n\\t^self new withAll: mutexList! !\\nAppRegistry subclass: #MvcTextEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\n!MvcTextEditor commentStamp: 'tween 8/27/2004 12:24' prior: 0!\\nA subclass of AppRegistry which allows the user, or Browser add-ons, to control which class is used when creating the code editing view in mvc Browsers!\\n\\nError subclass: #MyResumableTestError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\n\\n!MyResumableTestError methodsFor: 'exceptionDescription' stamp: 'tfei 6/13/1999 00:46'!\\nisResumable\\n\\n\\t^true! !\\nError subclass: #MyTestError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\nNotification subclass: #MyTestNotification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Tests'!\\nNetworkError subclass: #NameLookupFailure\\n\\tinstanceVariableNames: 'hostName'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NameLookupFailure commentStamp: 'mir 5/12/2003 18:16' prior: 0!\\nSignals that a name lookup operation failed.\\n\\n\\thostName\\thostName for which the name loopup failed\\n!\\n\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'rbb 2/18/2005 14:27'!\\ndefaultAction\\n\\t\\\"Backward compatibility\\\"\\n\\t| response |\\n\\tresponse _ (UIManager default chooseFrom: #( 'Retry' 'Give Up')\\n\\t\\t\\ttitle: self messageText).\\n\\t^ response = 2\\n\\t\\tifFalse: [self retry]! !\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'len 12/14/2002 11:57'!\\nhostName\\n\\t^ hostName! !\\n\\n!NameLookupFailure methodsFor: 'accessing' stamp: 'len 12/14/2002 11:57'!\\nhostName: aString\\n\\thostName _ aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNameLookupFailure class\\n\\tinstanceVariableNames: ''!\\n\\n!NameLookupFailure class methodsFor: 'instance creation' stamp: 'len 12/14/2002 11:57'!\\nhostName: aString\\n\\t^ self new hostName: aString! !\\nObject subclass: #NameOfSubclass\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-Bugs'!\\nUpdatingStringMorph subclass: #NameStringInHalo\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n!NameStringInHalo commentStamp: 'kfr 10/27/2003 16:29' prior: 0!\\nShows the name of the morph in the halo. !\\n\\n\\n!NameStringInHalo methodsFor: 'accessing' stamp: 'sw 9/17/1999 13:17'!\\ninterimContents: aString\\n\\tself contents: aString.\\n\\tself placeContents! !\\n\\n\\n!NameStringInHalo methodsFor: 'as yet unclassified' stamp: 'di 11/25/1999 23:40'!\\nplaceContents\\n\\t| namePosition |\\n\\t(owner notNil and: [owner isInWorld]) ifTrue:\\n\\t\\t[namePosition _ owner basicBox bottomCenter -\\n\\t\\t\\t((self width // 2) @ (owner handleSize negated // 2 - 1)).\\n\\t\\tnamePosition _ namePosition min: self world viewBox bottomRight - self extent y + 2.\\n\\t\\tself bounds: (namePosition extent: self extent)]! !\\n\\n\\n!NameStringInHalo methodsFor: 'drawing' stamp: 'sw 9/7/1999 21:27'!\\ndrawOn: aCanvas\\n\\taCanvas fillRectangle: self bounds color: Color white.\\n\\tsuper drawOn: aCanvas.! !\\n\\n\\n!NameStringInHalo methodsFor: 'editing' stamp: 'sw 9/17/1999 13:41'!\\ncancelEdits\\n\\tself interimContents: target externalName.\\n\\tsuper cancelEdits! !\\nObject subclass: #NaturalLanguageFormTranslator\\n\\tinstanceVariableNames: 'id generics'\\n\\tclassVariableNames: 'CachedTranslations'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Localization'!\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:15'!\\ngenerics\\n\\t^generics ifNil: [generics := Dictionary new]! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:27'!\\nlocaleID\\n\\t^id! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:26'!\\nlocaleID: anID\\n\\tid := anID! !\\n\\n!NaturalLanguageFormTranslator methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:17'!\\nname: formName form: translatedForm \\n\\tself generics at: formName put: translatedForm.\\n! !\\n\\n\\n!NaturalLanguageFormTranslator methodsFor: 'i/o' stamp: 'yo 1/13/2005 14:02'!\\nsaveFormsOn: aStream\\n\\n\\t| rr |\\n\\trr _ ReferenceStream on: aStream.\\n\\trr nextPut: {id isoString. generics}.\\n\\trr close.\\n! !\\n\\n\\n!NaturalLanguageFormTranslator methodsFor: 'utilities' stamp: 'yo 1/13/2005 11:35'!\\ntranslate: aString\\n\\n\\t^ (self generics\\n\\t\\tat: aString ifAbsent: [nil]) deepCopy.\\n\\n\\t\\\"Do you like to write 'form ifNotNil: [form deepCopy]'?\\\"\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNaturalLanguageFormTranslator class\\n\\tinstanceVariableNames: ''!\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\ncachedTranslations\\n\\t\\\"CachedTranslations := nil\\\" \\n\\t^CachedTranslations ifNil: [CachedTranslations := Dictionary new]! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nisoLanguage: isoLanguage\\n\\t\\\"Return the generic language translator as there is no information about the country code\\\"\\n\\n\\t^self isoLanguage: isoLanguage isoCountry: nil! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nisoLanguage: isoLanguage isoCountry: isoCountry\\n\\t^self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry)! !\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'accessing' stamp: 'yo 1/13/2005 11:13'!\\nlocaleID: localeID \\n\\t^ self cachedTranslations\\n\\t\\tat: localeID\\n\\t\\tifAbsentPut: [self new localeID: localeID]! !\\n\\n\\n!NaturalLanguageFormTranslator class methodsFor: 'i/o' stamp: 'yo 1/13/2005 14:02'!\\nloadFormsFrom: aStream\\n\\n\\t| rr pair inst |\\n\\trr _ ReferenceStream on: aStream.\\n\\tpair _ rr next.\\n\\tinst _ self localeID: (LocaleID isoString: pair first).\\n\\tpair second associationsDo: [:assoc |\\n\\t\\tinst name: assoc key form: assoc value.\\n\\t].\\n\\t^ inst.\\n! !\\nObject subclass: #NaturalLanguageTranslator\\n\\tinstanceVariableNames: 'id generics contexts'\\n\\tclassVariableNames: 'AllKnownPhrases CachedTranslations'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Localization'!\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'dgd 8/13/2004 21:12'!\\ndisplayLanguage\\n\\t^ id displayLanguage! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'dgd 10/7/2004 20:50'!\\ndisplayName\\n\\t^ id displayName! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:41'!\\nisoCountry\\n\\t^self localeID isoCountry! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:42'!\\nisoLanguage\\n\\t^self localeID isoLanguage! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:42'!\\nlocaleID\\n\\t^id! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/21/2004 17:00'!\\ntranslations\\n\\t^self generics! !\\n\\n!NaturalLanguageTranslator methodsFor: 'accessing' stamp: 'mir 7/21/2004 17:03'!\\nuntranslated\\n\\t| translations |\\n\\ttranslations := self translations.\\n\\t^self class allKnownPhrases reject: [:each | translations includesKey: each]! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/16/2004 11:04'!\\nfileOutHeader\\n\\t^ '''Translation dictionary'''! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/28/2004 14:50'!\\nfileOutHeaderOn: aStream \\n\\taStream nextChunkPut: self fileOutHeader;\\n\\t\\t cr.\\n\\taStream timeStamp; cr.\\n\\taStream nextPut: $!!.\\n\\taStream nextChunkPut: '(' , self class name , ' localeID: ' , id storeString , ')'.\\n\\taStream cr! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 11/29/2005 11:19'!\\nfileOutOn: aStream \\n\\t\\\"self current fileOutOn: Transcript. Transcript endEntry\\\"\\n\\tself fileOutHeaderOn: aStream.\\n\\tself fileOutOn: aStream keys: nil! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 11/29/2005 11:19'!\\nfileOutOn: aStream keys: keys \\n\\t\\\"self current fileOutOn: Transcript. Transcript endEntry\\\"\\n\\t(keys\\n\\t\\tifNil: [generics keys asSortedCollection])\\n\\t\\tdo: [:key | self\\n\\t\\t\\t\\tnextChunkPut: (generics associationAt: key)\\n\\t\\t\\t\\ton: aStream].\\n\\tkeys\\n\\t\\tifNil: [self untranslated\\n\\t\\t\\t\\tdo: [:each | self nextChunkPut: each -> '' on: aStream]].\\n\\taStream nextPut: $!!;\\n\\t\\t cr! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 11/16/2004 09:26'!\\nnextChunkPut: anObject on: aStream \\n\\t| i remainder terminator |\\n\\tterminator := $!!.\\n\\tremainder := anObject storeString.\\n\\t[(i := remainder indexOf: terminator) = 0]\\n\\t\\twhileFalse: [aStream\\n\\t\\t\\t\\tnextPutAll: (remainder copyFrom: 1 to: i).\\n\\t\\t\\taStream nextPut: terminator.\\n\\t\\t\\t\\\"double imbedded terminators\\\"\\n\\t\\t\\tremainder := remainder copyFrom: i + 1 to: remainder size].\\n\\taStream nextPutAll: remainder.\\n\\taStream nextPut: terminator; cr.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'tak 12/15/2004 16:07'!\\nscanFrom: aStream \\n\\t\\\"Read a definition of dictionary. \\n\\tMake sure current locale corresponds my locale id\\\"\\n\\t| aString newTranslations assoc currentPlatform |\\n\\tnewTranslations := Dictionary new.\\n\\tcurrentPlatform := Locale currentPlatform.\\n\\t[Locale\\n\\t\\tcurrentPlatform: (Locale localeID: id).\\n\\t[aString := aStream nextChunk withSqueakLineEndings.\\n\\taString size > 0]\\n\\t\\twhileTrue: [assoc := Compiler evaluate: aString.\\n\\t\\t\\tassoc value = ''\\n\\t\\t\\t\\tifTrue: [self class registerPhrase: assoc key]\\n\\t\\t\\t\\tifFalse: [newTranslations add: assoc]]]\\n\\t\\tensure: [Locale currentPlatform: currentPlatform].\\n\\tself mergeTranslations: newTranslations! !\\n\\n!NaturalLanguageTranslator methodsFor: 'fileIn/fileOut' stamp: 'yo 2/25/2005 09:37'!\\nwriteAsMimeString\\n\\n\\t| fileName fileStream tmpStream s2 gzs |\\n\\ttmpStream _ MultiByteBinaryOrTextStream on: ''.\\n\\ttmpStream converter: UTF8TextConverter new.\\n\\tself fileOutOn: tmpStream.\\n\\ts2 _ RWBinaryOrTextStream on: ''.\\n\\tgzs := GZipWriteStream on: s2.\\n\\ttmpStream reset.\\n\\tgzs nextPutAll: (tmpStream binary contentsOfEntireFile asString) contents.\\n\\tgzs close.\\n\\ts2 reset.\\n\\n\\tfileName _ id isoString, '.translation.gz.mime'.\\n\\tfileStream _ FileStream newFileNamed: fileName.\\n\\tfileStream nextPutAll: (Base64MimeConverter mimeEncode: s2) contents.\\n\\tfileStream close.\\n! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'initialize-release' stamp: 'mir 7/15/2004 14:41'!\\nlocaleID: anID\\n\\tid := anID! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'printing' stamp: 'nk 8/29/2004 10:51'!\\nprintOn: aStream\\n\\taStream nextPutAll: self class name; nextPut: $(; print: self localeID; nextPut: $)! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 7/21/2004 18:02'!\\ncheckPhrase: phrase translation: translation! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 7/30/2004 13:03'!\\nphrase: phraseString translation: translationString \\n\\tself generics at: phraseString put: translationString asString.\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 8/2/2004 12:27'!\\nrawPhrase: phraseString translation: translationString \\n\\tself generics at: phraseString put: translationString asString.\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 1/14/2005 16:25'!\\nrawRemoveUntranslated: untranslated\\n\\n\\tself class allKnownPhrases removeKey: untranslated ifAbsent: [].\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 8/1/2004 01:07'!\\nremoveTranslationFor: phraseString\\n\\tself generics removeKey: phraseString ifAbsent: [].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'yo 1/14/2005 16:25'!\\nremoveUntranslated: untranslated\\n\\n\\tself class allKnownPhrases removeKey: untranslated ifAbsent: [].\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'em 3/23/2005 12:08'!\\ntranslate: aString\\n\\t^self generics\\n\\t\\tat: aString\\n\\t\\tifAbsent: [self class registeredPhraseFor: aString. \\n\\t\\t\\t\\t\\tself changed: #untranslated. \\n\\t\\t\\t\\t\\tself localeID hasParent\\n\\t\\t\\tifTrue: [(self class localeID: self localeID parent) translate: aString]\\n\\t\\t\\tifFalse: [aString]]! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 6/30/2004 20:22'!\\ntranslate: aString in: aContext! !\\n\\n!NaturalLanguageTranslator methodsFor: 'translation' stamp: 'mir 7/15/2004 14:58'!\\ntranslationFor: aString\\n\\t^self translate: aString! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'user interface' stamp: 'dgd 8/13/2004 21:54'!\\ndefaultBackgroundColor\\n\\t\\\"answer the receiver's defaultBackgroundColor for views\\\"\\n\\t^ Color cyan! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'private' stamp: 'mir 6/30/2004 20:23'!\\ngenerics\\n\\t^generics ifNil: [generics := Dictionary new]! !\\n\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 7/30/2004 13:00'!\\nloadFromFileNamed: fileNameString \\n\\t\\\"Load translations from an external file\\\"\\n\\n\\t| stream |\\n\\t[stream := FileStream readOnlyFileNamed: fileNameString.\\n\\tself loadFromStream: stream]\\n\\t\\tensure: [stream close].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.\\n! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'tak 11/16/2004 12:37'!\\nloadFromRefStream: stream \\n\\t\\\"Load translations from an external file\\\"\\n\\t| loadedArray refStream |\\n\\trefStream := ReferenceStream on: stream.\\n\\t[loadedArray := refStream next]\\n\\t\\tensure: [refStream close].\\n\\tself processExternalObject: loadedArray ! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'em 3/30/2005 14:32'!\\nloadFromStream: stream \\n\\t\\\"Load translations from an external file\\\"\\n\\t| header isFileIn |\\n\\theader := '''Translation dictionary'''.\\n\\tisFileIn := (stream next: header size)\\n\\t\\t\\t\\t= header.\\n\\tstream reset.\\n\\tisFileIn\\n\\t\\tifTrue: [stream fileInAnnouncing: 'Loading ' translated, stream localName]\\n\\t\\tifFalse: [self loadFromRefStream: stream]! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 8/2/2004 12:27'!\\nmergeTranslations: newTranslations\\n\\t\\\"Merge a new set of translations into the exiting table.\\n\\tOverwrites existing entries.\\\"\\n\\n\\tnewTranslations keysAndValuesDo: [:key :value |\\n\\t\\tself rawPhrase: (self class registeredPhraseFor: key) translation: value].\\n\\tself changed: #translations.\\n\\tself changed: #untranslated.! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'mir 7/15/2004 20:04'!\\nprocessExternalObject: anArray \\n\\t\\\"pivate - process the external object\\\"\\n\\n\\t\\\"new format -> {translations. untranslated}\\\"\\n\\n\\tanArray second do: [:each | self class registerPhrase: each].\\n\\n\\tself mergeTranslations: anArray first! !\\n\\n!NaturalLanguageTranslator methodsFor: 'private store-retrieve' stamp: 'yo 2/17/2005 15:45'!\\nsaveToFileNamed: fileNameString \\n\\t\\\"save the receiver's translations to a file named fileNameString\\\"\\n\\t| stream |\\n\\t\\\"Set true if you need to save as binary\\\"\\n\\tfalse\\n\\t\\tifTrue: [stream := ReferenceStream fileNamed: fileNameString.\\n\\t\\t\\tstream nextPut: {self translations. self untranslated}.\\n\\t\\t\\tstream close.\\n\\t\\t\\t^ self].\\n\\tstream := FileStream fileNamed: fileNameString.\\n\\t[self fileOutOn: stream]\\n\\t\\tensure: [stream close]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNaturalLanguageTranslator class\\n\\tinstanceVariableNames: ''!\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 20:20'!\\navailableLanguageLocaleIDs\\n\\t\\\"Return the locale ids for the currently available languages. \\n\\tMeaning those which either internally or externally have \\n\\ttranslations available.\\\"\\n\\t\\\"NaturalLanguageTranslator availableLanguageLocaleIDs\\\"\\n\\t^ CachedTranslations values collect:[:each | each localeID]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 19:39'!\\ncurrent\\n\\t^ LocaleID current translator\\n\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'nk 8/29/2004 14:23'!\\ndefault\\n\\t^self localeID: (LocaleID default)\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:36'!\\nisoLanguage: isoLanguage\\n\\t\\\"Return the generic language translator as there is no information about the country code\\\"\\n\\n\\t^self isoLanguage: isoLanguage isoCountry: nil! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'mir 7/15/2004 14:36'!\\nisoLanguage: isoLanguage isoCountry: isoCountry\\n\\t^self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry)! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'accessing' stamp: 'dgd 8/24/2004 19:18'!\\nlocaleID: localeID \\n\\t^ self cachedTranslations\\n\\t\\tat: localeID\\n\\t\\tifAbsentPut: [self new localeID: localeID]! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 8/11/2004 13:38'!\\ninitialize\\n\\t\\\"NaturalLanguageTranslator initialize\\\"\\n\\n\\tFileList registerFileReader: self.\\n\\tSmalltalk addToStartUpList: NaturalLanguageTranslator after: FileDirectory.\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 7/15/2004 19:48'!\\nresetCaches\\n\\t\\\"NaturalLanguageTranslator resetCaches\\\"\\n\\n\\tCachedTranslations := nil.\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'class initialization' stamp: 'mir 8/31/2005 23:37'!\\nstartUp: resuming \\n\\t| defaultID |\\n\\tresuming\\n\\t\\tifFalse: [^ self].\\n\\t\\\"\\\"\\n\\tdefaultID := LocaleID current.\\n\\tself cachedTranslations\\n\\t\\tat: defaultID\\n\\t\\tifAbsent: [self localeID: defaultID].\\n\\t\\\"\\\"\\n\\tself loadAvailableExternalLocales! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 8/11/2004 10:52'!\\nfileReaderServicesForFile: fullName suffix: suffix \\n\\t\\\"Answer the file services associated with given file\\\"\\n\\t^ (suffix = self translationSuffix) | (suffix = '*')\\n\\t\\tifTrue: [{self serviceMergeLanguageTranslations}]\\n\\t\\tifFalse: [#()]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'tak 3/14/2005 15:51'!\\nloadForLocaleIsoString: localeString fromGzippedMimeLiteral: mimeString \\n\\t\\\"merge the translation from the mime literal.\\\"\\n\\t| stream localeID translator gs rbStream s currentPlatform |\\n\\ts := Base64MimeConverter mimeDecodeToBytes: mimeString readStream.\\n\\ts reset.\\n\\tgs := GZipReadStream on: s.\\n\\trbStream := MultiByteBinaryOrTextStream with: gs contents asString.\\n\\trbStream converter: UTF8TextConverter new.\\n\\trbStream reset.\\n\\tlocaleID := LocaleID isoString: localeString.\\n\\tcurrentPlatform := Locale currentPlatform.\\n\\t[Locale\\n\\t\\tcurrentPlatform: (Locale localeID: localeID).\\n\\tstream := ReadStream on: rbStream contents]\\n\\t\\tensure: [Locale currentPlatform: currentPlatform].\\n\\ttranslator := self localeID: localeID.\\n\\ttranslator loadFromStream: stream.\\n\\tLanguageEnvironment resetKnownEnvironments! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'yo 2/24/2005 21:04'!\\nmergeTranslationFileNamed: fileFullNameString \\n\\t\\\"merge the translation in the file named fileFullNameString\\\"\\n\\n\\t| stream localeID translator |\\n\\tstream := FileStream readOnlyFileNamed: fileFullNameString.\\n\\t[localeID := LocaleID isoString: stream localName sansPeriodSuffix.\\n\\ttranslator := self localeID: localeID.\\n\\ttranslator loadFromStream: stream]\\n\\t\\tensure: [stream close].\\n\\tLanguageEnvironment resetKnownEnvironments.\\n\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 7/21/2004 13:45'!\\nserviceMergeLanguageTranslations\\n\\t\\\"Answer a service for merging of translation files\\\"\\n\\t^ SimpleServiceEntry\\n\\t\\tprovider: self\\n\\t\\tlabel: 'merge the translation file'\\n\\t\\tselector: #mergeTranslationFileNamed:\\n\\t\\tdescription: 'merge the translation file into the language named like the file'\\n\\t\\tbuttonLabel: 'merge'! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'file-services' stamp: 'mir 7/21/2004 13:45'!\\nservices\\n\\t\\\"Answer potential file services associated with this class\\\"\\n\\t^ {self serviceMergeLanguageTranslations}! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/15/2004 19:58'!\\nallKnownPhrases\\n\\t^AllKnownPhrases ifNil: [AllKnownPhrases := Dictionary new: 2051]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/13/2004 00:06'!\\ncachedTranslations\\n\\t\\\"CachedTranslations := nil\\\" \\n\\t^CachedTranslations ifNil: [CachedTranslations := Dictionary new]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 8/31/2005 16:55'!\\ncleanUpCache\\n\\t\\\"NaturalLanguageTranslator cleanUpCache\\\"\\n\\n\\tself cachedTranslations keys do: [:key |\\n\\t\\tkey isoLanguage size > 2 ifTrue: [self cachedTranslations removeKey: key]]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/15/2004 20:02'!\\nregisterPhrase: phrase\\n\\t\\\"Using a Dictionary so we can lookup existing string instead of creating needless copies when loading a translation.\\\"\\n\\tself allKnownPhrases at: phrase put: phrase! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 7/21/2004 14:18'!\\nregisteredPhraseFor: phrase\\n\\t\\\"Using a Dictionary so we can lookup existing string instead of creating needless copies when loading a translation.\\\"\\n\\t^self allKnownPhrases at: phrase ifAbsentPut: [phrase]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private' stamp: 'mir 8/11/2004 10:52'!\\ntranslationSuffix\\n\\t^'translation'! !\\n\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'nk 8/21/2004 13:03'!\\ndirectoryForLanguage: isoLanguage country: isoCountry create: createDir\\n\\t\\\"Try to locate the <prefs>/locale/<language>{/<country>} folder.\\n\\tIf createDir is set, create the path down to country or language, depending on wether it's specified..\\n\\tReturn the directory for country or language depending on specification.\\n\\tIf neither exists, nil\\\"\\n\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'es' country: nil create: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: 'DE' create: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: 'US' create: false\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: nil create: true\\\"\\n\\n\\t\\\"If this fails, there is nothing we can do about it here\\\"\\n\\t| localeDir countryDir languageDir |\\n\\tlocaleDir := self localeDirCreate: createDir.\\n\\tlocaleDir ifNil: [^nil].\\n\\n\\tisoCountry ifNil: [\\n\\t\\tlanguageDir := localeDir directoryNamed: isoLanguage.\\n\\t\\tcreateDir\\n\\t\\t\\tifTrue: [languageDir assureExistence].\\n\\t\\t^languageDir exists\\n\\t\\t\\tifTrue: [languageDir]\\n\\t\\t\\tifFalse: [nil]].\\n\\n\\tcountryDir := languageDir directoryNamed: isoCountry.\\n\\tcreateDir\\n\\t\\tifTrue: [countryDir assureExistence].\\n\\n\\t^countryDir exists\\n\\t\\tifTrue: [countryDir]\\n\\t\\tifFalse: [nil]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/11/2004 10:44'!\\ndirectoryForLocaleID: localeID create: createDir\\n\\t\\\"Try to locate the <prefs>/locale/<language>{/<country>} folder.\\n\\tIf createDir is set, create the path down to country or language, depending on locale.\\n\\tReturn the directory for country or language depending on locale.\\n\\tIf neither exists, nil\\\"\\n\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: nil readOnly: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'de' country: 'DE' readOnly: true\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: 'US' readOnly: false\\\"\\n\\t\\\"NaturalLanguageTranslator directoryForLanguage: 'en' country: nil readOnly: true\\\"\\n\\n\\t^self directoryForLanguage: localeID isoLanguage country: localeID isoCountry create: createDir! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 11:57'!\\nloadAvailableExternalLocales\\n\\t\\\"private - register locales IDs based on the content of the <prefs>/locale/ directory\\\"\\n\\t| localeDir |\\n\\tlocaleDir := self localeDirCreate: false.\\n\\tlocaleDir ifNil: [^ #()].\\n\\n\\tlocaleDir directoryNames\\n\\t\\tdo: [:langDirName | \\n\\t\\t\\t| langDir | \\n\\t\\t\\tlangDir := localeDir directoryNamed: langDirName.\\n\\n\\t\\t\\t(langDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\t\\t\\tifNotEmpty: [self loadTranslatorForIsoLanguage: langDirName isoCountry: nil].\\n\\n\\t\\t\\tlangDir directoryNames\\n\\t\\t\\t\\tdo: [:countryDirName | \\n\\t\\t\\t\\t\\t| countryDir | \\n\\t\\t\\t\\t\\tcountryDir := langDirName directoryNamed: countryDirName.\\n\\t\\t\\t\\t\\t(countryDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\t\\t\\t\\t\\tifNotEmpty: [self loadTranslatorForIsoLanguage: langDirName isoCountry: countryDirName]\\n\\t\\t\\t]\\n\\t\\t].\\n! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'nk 8/21/2004 13:00'!\\nloadExternalTranslationsFor: translator\\n\\t\\\"Try to load translations from external external files.\\n\\tThe files are located in the <prefs>/locale/<language>{/<country>} folder.\\n\\tThere can be more than one file for each location, so applications can install their own partial translation tables. All files in the specific folder are loaded.\\\"\\n\\n\\t| translationDir |\\n\\ttranslationDir := self directoryForLocaleID: translator localeID create: false.\\n\\ttranslationDir ifNil: [ ^nil ]. \\n\\t(translationDir fileNamesMatching: '*.' , self translationSuffix)\\n\\t\\tdo: [:fileName | translator loadFromFileNamed: (translationDir fullNameFor: fileName)]! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 11:59'!\\nloadTranslatorForIsoLanguage: isoLanguage isoCountry: isoCountry \\n\\t\\\"private - load the translations from <prefs>/locale/ directory \\n\\tthe procedure is to assure the existence of a translator for the \\n\\tgiven language/country and then load the external translations for this translator\\\"\\n\\n\\t| translator |\\n\\ttranslator := self localeID: (LocaleID isoLanguage: isoLanguage isoCountry: isoCountry).\\n\\n\\tself loadExternalTranslationsFor: translator! !\\n\\n!NaturalLanguageTranslator class methodsFor: 'private loading' stamp: 'mir 8/25/2004 12:03'!\\nlocaleDirCreate: createDir\\n\\t\\\"Try to locate the <prefs>/locale/ folder.\\n\\tIf createDir is set, try to create the path.\\n\\tIf it doesn't exist, return nil\\\"\\n\\n\\t\\\"If this fails, there is nothing we can do about it here\\\"\\n\\t| prefDir localeDir |\\n\\t(createDir not\\n\\t\\t\\tand: [ExternalSettings preferenceDirectory isNil])\\n\\t\\tifTrue: [^ nil].\\n\\n\\tprefDir := ExternalSettings assuredPreferenceDirectory.\\n\\tprefDir exists\\n\\t\\tifFalse: [^nil].\\n\\n\\n\\tlocaleDir := prefDir directoryNamed: 'locale'.\\n\\tcreateDir\\n\\t\\tifTrue: [localeDir assureExistence].\\n\\t^localeDir exists\\n\\t\\tifTrue: [localeDir]\\n\\t\\tifFalse: [nil]! !\\nObject subclass: #NebraskaClient\\n\\tinstanceVariableNames: 'connection encoder hand canvas'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaClient commentStamp: '<historical>' prior: 0!\\nA client that has connected to a Nebraska server, seen from the server's point of view.!\\n\\n\\n!NebraskaClient methodsFor: 'as yet unclassified' stamp: 'RAA 7/31/2000 23:59'!\\nbacklog\\n\\n\\t^connection backlog! !\\n\\n!NebraskaClient methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:30'!\\ncurrentStatusString\\n\\n\\t(connection isNil or: [connection isConnected not]) ifTrue: [^'nada'].\\n\\t^(NetNameResolver stringFromAddress: connection remoteAddress),\\n\\t\\t' - ',\\n\\t\\t(self backlog // 1024) printString,'k'! !\\n\\n\\n!NebraskaClient methodsFor: 'attributes' stamp: 'ls 3/25/2000 22:27'!\\ncanvas\\n\\t\\\"return the hand this canvas that should be drawn on for this client\\\"\\n\\t^canvas! !\\n\\n!NebraskaClient methodsFor: 'attributes' stamp: 'ls 3/25/2000 22:27'!\\nhand\\n\\t\\\"return the hand this client is controlling\\\"\\n\\t^hand! !\\n\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\nconvertToBuffered\\n\\n\\tcanvas purgeOutputQueue.\\n\\tcanvas := canvas asBufferedCanvas.! !\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ndestroy\\n\\thand ifNotNil:[hand world ifNotNil:[hand world removeHand: hand]].\\n\\tconnection ifNotNil:[connection destroy].\\n\\tencoder := canvas := hand := connection := nil.! !\\n\\n!NebraskaClient methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitialize: aConnection\\n\\n\\t| remoteAddress userPicture |\\n\\n\\tconnection := aConnection.\\n\\thand := RemoteControlledHandMorph on: (MorphicEventDecoder on: aConnection).\\n\\thand nebraskaClient: self.\\n\\tremoteAddress := connection remoteAddress.\\n\\tremoteAddress ifNotNil: [remoteAddress := NetNameResolver stringFromAddress: remoteAddress].\\n\\tuserPicture := EToySenderMorph pictureForIPAddress: remoteAddress.\\n\\thand\\n\\t\\tuserInitials: ((EToySenderMorph nameForIPAddress: remoteAddress) ifNil: ['???'])\\n\\t\\tandPicture: (userPicture ifNotNil: [userPicture scaledToSize: 16@20]).\\n\\tencoder := CanvasEncoder on: aConnection.\\n\\tcanvas := RemoteCanvas\\n\\t\\tconnection: encoder\\n\\t\\tclipRect: NebraskaServer extremelyBigRectangle\\n\\t\\ttransform: MorphicTransform identity! !\\n\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 4/9/2000 14:43'!\\nextent: newExtent depth: newDepth\\n\\tencoder extent: newExtent depth: newDepth! !\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 3/25/2000 22:25'!\\nisConnected\\n\\t^connection isConnected! !\\n\\n!NebraskaClient methodsFor: 'network' stamp: 'ls 3/25/2000 22:25'!\\nprocessIO\\n\\tconnection processIO.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaClient class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaClient class methodsFor: 'instance creation' stamp: 'ls 3/25/2000 22:28'!\\nonConnection: aStringSocket\\n\\t^self new initialize: aStringSocket! !\\nObject subclass: #NebraskaDebug\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DEBUG Details'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaDebug commentStamp: '<historical>' prior: 0!\\nBufferedCanvas enabled: false.\\nBufferedCanvas enabled: true.\\n\\nNebraskaDebug beginStats\\nNebraskaDebug showStats\\nNebraskaDebug stopAndShowAll\\nNebraskaDebug killStats\\nStringSocket showRatesSeen\\nStringSocket clearRatesSeen\\nNebraskaDebug showAndClearStats: #allStats\\nNebraskaDebug showAndClearStats: #queuedbufferSizes\\n\\n\\nCanvasEncoder beginStats\\nCanvasEncoder showStats\\nCanvasEncoder killStats\\nNebraskaDebug showStats: #peerBytesSent\\nNebraskaDebug showStats: #soundReductionTime\\nNebraskaDebug showStats: #FormEncodeTimes\\nNebraskaDebug showStats: #SendReceiveStats\\nNebraskaDebug showStats: #sendDeltas\\nNebraskaDebug showStats: #bigImage\\nNebraskaDebug showStats: #sketch\\nNebraskaDebug showStats: #addToOutBuf:\\n----\\nbuffered off, painting 125kb/s, dragging 400kb/s\\nbuffered on, painting 100kb/s, dragging 170kb/s!\\n]style[(62 142 14 78 17 3 73 415)f1cblue;,f1cblack;,f1,f1cblack;,f1cred;,f1cblack;,f1cblue;,f1cblack;!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaDebug class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nat: queueName add: anArray\\n\\n\\t| now |\\n\\n\\tDEBUG ifNil: [\\n\\t\\tqueueName == #sketchZZZ ifFalse: [^self].\\n\\t\\t\\\"Details := OrderedCollection new.\\\"\\n\\t\\tself beginStats.\\n\\t].\\n\\t(Details notNil and: [Details size < 20]) ifTrue: [\\n\\t\\tDetails add: thisContext longStack\\n\\t].\\n\\tnow := Time millisecondClockValue.\\n\\tDEBUG add: {now},anArray,{queueName}.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nbeginStats\\n\\n\\tDEBUG := OrderedCollection new! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nkillStats\\n\\n\\tDEBUG := nil.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowAndClearStats: queueName\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tself \\n\\t\\tshowStats: queueName \\n\\t\\tfrom: DEBUG.\\n\\tDEBUG := nil.! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'nb 6/17/2003 12:25'!\\nshowStats\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tDEBUG explore.! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'nb 6/17/2003 12:25'!\\nshowStats: queueName\\n\\n\\tDEBUG ifNil: [^Beeper beep].\\n\\tself \\n\\t\\tshowStats: queueName \\n\\t\\tfrom: DEBUG.\\n! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowStats: queueName from: aCollection\\n\\n\\t| xx answer prevTime currTime |\\n\\n\\tprevTime := nil.\\n\\tanswer := String streamContents: [ :s | \\n\\t\\ts nextPutAll: (aCollection last first - aCollection first first) asStringWithCommas,' ms';cr;cr.\\n\\t\\taCollection withIndexDo: [ :each :index | \\n\\t\\t\\t(queueName == #allStats or: [queueName == each last]) ifTrue: [\\n\\t\\t\\t\\tcurrTime := each first.\\n\\t\\t\\t\\txx := currTime printString.\\n\\t\\t\\t\\tprevTime ifNil: [prevTime := currTime].\\n\\t\\t\\t\\ts nextPutAll: index printString,'. ',\\n\\t\\t\\t\\t\\t(xx allButLast: 3),'.',(xx last: 3),' ',(currTime - prevTime) printString,' '.\\n\\t\\t\\t\\ts nextPutAll: each allButFirst printString; cr.\\n\\t\\t\\t\\tprevTime := currTime.\\n\\t\\t\\t].\\n\\t\\t]\\n\\t].\\n\\tStringHolder new \\n\\t\\tcontents: answer;\\n\\t\\topenLabel: queueName! !\\n\\n!NebraskaDebug class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nstopAndShowAll\\n\\n\\t| prev |\\n\\nself halt.\\t\\\"not updated to new format\\\"\\n\\n\\tprev := DEBUG.\\n\\tDEBUG := nil.\\n\\tprev ifNil: [^Beeper beep].\\n\\tprev keysAndValuesDo: [ :k :v |\\n\\t\\tself showStats: k from: v\\n\\t].! !\\nProjectNavigationMorph subclass: #NebraskaNavigationMorph\\n\\tinstanceVariableNames: 'nebraskaBorder nebraskaTerminal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:49'!\\naddButtons\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {self buttonScale}.\\n\\t\\tself inAColumn: {self buttonQuit}.\\n\\t\\tself inAColumn: {self buttonBuffered}.\\n\\t}.\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:26'!\\nbufferNebraska\\n\\n\\tnebraskaTerminal requestBufferedConnection\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/13/2000 08:23'!\\nbuttonBuffered\\n\\n\\t^self makeButton: 'B' balloonText: 'Request buffered Nebraska session' for: #bufferNebraska\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:34'!\\nbuttonScale\\n\\n\\t^self makeButton: '1x1' balloonText: 'Switch between 1x1 and scaled view' for: #toggleFullView\\n! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:47'!\\ncurrentNavigatorVersion\\n\\n\\t^1\\t\\t\\\"not particularly relevant here\\\"! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'yo 11/4/2002 21:06'!\\nfontForButtons\\n\\n\\t^ TextStyle defaultFont.\\n\\t\\\"^Preferences standardButtonFont\\\"! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\nnebraskaBorder: aNebraskaBorder\\n\\n\\tnebraskaBorder := aNebraskaBorder! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\nnebraskaTerminal: aNebraskaTerminal\\n\\n\\tnebraskaTerminal := aNebraskaTerminal! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\npositionVertically\\n\\n\\t| w |\\n\\tw := self world ifNil: [^self].\\n\\tself top < w top ifTrue: [self top: w top].\\n\\tself bottom > w bottom ifTrue: [self bottom: w bottom].! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:47'!\\nquitNebraska\\n\\n\\tnebraskaBorder ifNotNil: [nebraskaBorder delete].\\n\\tself delete.! !\\n\\n!NebraskaNavigationMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 11:48'!\\ntoggleFullView\\n\\n\\tnebraskaBorder ifNotNil: [nebraskaBorder toggleFullView]! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'dropping/grabbing' stamp: 'RAA 11/8/2000 11:42'!\\nwantsToBeDroppedInto: aMorph\\n\\n\\t\\\"avoid difficulties in placement\\\"\\n\\t^(aMorph isKindOf: NetworkTerminalMorph) not! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'initialization' stamp: 'dgd 2/16/2003 14:11'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color yellow ! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'stepping and presenter' stamp: 'RAA 11/8/2000 11:37'!\\nstep\\n\\n\\tsuper step.\\n\\t(nebraskaBorder isNil or: [nebraskaBorder world isNil]) ifTrue: [self delete].! !\\n\\n\\n!NebraskaNavigationMorph methodsFor: 'the buttons' stamp: 'RAA 11/8/2000 11:36'!\\nbuttonQuit\\n\\n\\t^self makeButton: 'Quit' balloonText: 'Quit this Nebraska session' for: #quitNebraska\\n! !\\nModel subclass: #NebraskaServer\\n\\tinstanceVariableNames: 'worldDepth world clients listenQueue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaServer commentStamp: '<historical>' prior: 0!\\nA Nebraska server has a private world and some collection of clients. It associates a RemoteControlledHand for each client. Redraw events in the world are broadcasted to all connected clients. A Nebraska server can listen on a TCP/IP port and accept new clients. Current version has been modified so that the server serves the world in which it was launched. Other variations are certainly possible.\\n\\nTo start a server, execute the following code:\\n\\tNebraskaServerMorph serveWorld: World\\n\\nTo start a client, run the following in another image:\\n\\tNetworkTerminalMorph openAndConnectTo: 'servername'\\n\\nFill in your server's hostname for 'servername'. At this point, everything should be working!!\\n\\nBefore starting a server, you can tweak these:\\nBufferedCanvas enabled: false.\\nBufferedCanvas enabled: true.\\n\\nAt any time you can do these:\\nNebraskaDebug beginStats\\nNebraskaDebug showStats\\nNebraskaDebug showStats: #delays\\nNebraskaDebug showStats: #bigImage\\nNebraskaDebug showStats: #FormEncodeTimes\\nNebraskaDebug killStats\\n\\nNOTE: if you want to have a local view of the server, you shouldn't use the TCP connections. The problem is that the server will occasionally do a #flush, and it won't work due to single threading. The better solution is to use a LoopBackStringSocket instead of a regular StringSocket, but there is no handy method for that right now....\\n\\n\\n!\\n]style[(266 136 49 39 56 53 96 46 1 62 29 525)f1,f1cred;,f1,f1cblue;,f1,f1cblue;,f1,f1cblue;,f1,f1cred;,f1cblue;,f1!\\n\\n\\n!NebraskaServer methodsFor: 'accessing' stamp: 'ar 10/26/2000 14:23'!\\nclients\\n\\t^clients ifNil:[#()].! !\\n\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 4/11/2000 19:48'!\\nextent: newExtent depth: newDepth\\n\\t\\\"modify the extent and/or depth of the shared world\\\"\\n\\tclients do: [ :client |\\n\\t\\tclient extent: newExtent depth: newDepth ].\\n\\tworld extent: newExtent.\\n\\n\\tworldDepth := newDepth.! !\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 4/11/2000 18:41'!\\nnumClients\\n\\t\\\"return the number of connected clients\\\"\\n\\t^clients size! !\\n\\n!NebraskaServer methodsFor: 'attributes' stamp: 'ls 3/25/2000 23:13'!\\nsharedWorld\\n\\t^world! !\\n\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'ar 10/26/2000 14:02'!\\ndestroy\\n\\tself stopListening.\\n\\tclients do:[:each| each destroy].\\n\\tself breakDependents.! !\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'ar 10/26/2000 14:20'!\\ninitialize\\n\\tclients := IdentitySet new.\\n\\tself extent: 800@600 depth: 16.! !\\n\\n!NebraskaServer methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitializeForWorld: aWorld\\n\\n\\tworld := aWorld.\\n\\tclients := IdentitySet new.\\n\\tself extent: world extent depth: Display depth.\\n\\taWorld remoteServer: self.! !\\n\\n\\n!NebraskaServer methodsFor: 'menus' stamp: 'RAA 7/31/2000 22:28'!\\nstep\\n\\n\\tself processIO.\\n\\n\\t\\\"savedWorld := Processor activeProcess world.\\n\\tProcessor activeProcess setWorld: world.\\\"\\n\\n\\tself flag: #bob.\\t\\t\\\"in this version, world is THE WORLD, so it steps itself\\\"\\n\\t\\\"world doOneCycle.\\\"\\n\\n\\t\\\"Processor activeProcess setWorld: savedWorld.\\\"\\n\\n\\tclients do: [ :each | each canvas apply: [ :ignore | ]].\\t\\\"for modes that need a little push\\\"\\n! !\\n\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:35'!\\nacceptNewConnections\\n\\t| connection |\\n\\tlistenQueue ifNil: [ ^self ].\\n\\t[ clients size > 20 ifTrue: [ \\\"too many connections!!\\\" ^self ].\\n\\t connection := listenQueue getConnectionOrNil. \\n\\t connection isNil ] \\n\\twhileFalse: [\\n\\t self addClientFromConnection: (StringSocket on: connection) ].! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'sd 11/20/2005 21:25'!\\nacceptNullConnection\\n\\n\\t| twins |\\n\\n\\ttwins := LoopbackStringSocket newPair.\\n\\tself addClientFromConnection: twins first.\\n\\t(NullTerminalMorph new connection: twins second) openInWorld.\\n! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'sd 11/20/2005 21:25'!\\nacceptPhonyConnection\\n\\n\\t| twins |\\n\\n\\ttwins := LoopbackStringSocket newPair.\\n\\tself addClientFromConnection: twins first.\\n\\t(NetworkTerminalMorph new connection: twins second) inspect \\\"openInWorld\\\".\\n! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'RAA 7/20/2000 10:03'!\\naddClientFromConnection: connection\\n\\t| client |\\n\\n\\tclient := NebraskaClient onConnection: connection.\\n\\tclients add: client.\\n\\tclient extent: world extent depth: worldDepth.\\n\\tworld addRemoteClient: client.\\n\\tself changed: #numClients.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'RAA 8/1/2000 00:01'!\\nbacklog\\n\\n\\t^clients inject: 0 into: [ :max :each | max max: each backlog]! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:36'!\\nprocessIO\\n\\tself pruneDeadConnections.\\n\\tself acceptNewConnections.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ar 10/26/2000 14:20'!\\npruneDeadConnections\\n\\t| deadConnections |\\n\\tdeadConnections := clients select: [ :client | client isConnected not ].\\n\\tdeadConnections do: [ :client |\\n\\t\\tworld removeRemoteClient: client].\\n\\n\\tdeadConnections isEmpty ifTrue:[ ^self ].\\n\\n\\tclients removeAll: deadConnections.\\n\\tself changed: #numClients.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:31'!\\nstartListeningOnPort: portNumber\\n\\tSocket initializeNetwork.\\n\\tself stopListening.\\n\\tlistenQueue := ConnectionQueue portNumber: portNumber queueLength: 5.! !\\n\\n!NebraskaServer methodsFor: 'networking' stamp: 'ls 3/25/2000 22:32'!\\nstopListening\\n\\tlistenQueue ifNil: [ ^self ].\\n\\tlistenQueue destroy.\\n\\tlistenQueue := nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaServer class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaServer class methodsFor: 'as yet unclassified' stamp: 'RAA 7/24/2000 12:06'!\\ndefaultPort\\n\\n\\t^9091! !\\n\\n!NebraskaServer class methodsFor: 'as yet unclassified' stamp: 'RAA 11/8/2000 14:59'!\\nextremelyBigRectangle\\n\\n\\t^(0@0 extent: 5000@5000)! !\\n\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'mu 11/28/2003 19:38'!\\nnewForWorld: aWorld\\n\\n\\t^self basicNew initializeForWorld: aWorld! !\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'ar 10/26/2000 14:00'!\\nserveWorld: aWorld\\n\\n\\t^self serveWorld: aWorld onPort: self defaultPort! !\\n\\n!NebraskaServer class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nserveWorld: aWorld onPort: aPortNumber\\n\\n\\t| server |\\n\\n\\tUtilities authorName.\\t\\\"since we will need it later\\\"\\n\\n\\tserver := self newForWorld: aWorld.\\n\\tserver startListeningOnPort: aPortNumber.\\n\\t^server\\n\\t\\\"server acceptNullConnection\\\"\\t\\t\\\"server acceptPhonyConnection.\\\"\\n! !\\nAlignmentMorphBob1 subclass: #NebraskaServerMorph\\n\\tinstanceVariableNames: 'server slowCounter previousBacklog lastFullUpdateTime currentStatusString fullDisplay previousClients currentBacklogString'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NebraskaServerMorph commentStamp: '<historical>' prior: 0!\\nA cheezy morph that simply steps a Nebraska server instance over and over.!\\n\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'RAA 5/31/2001 15:03'!\\ncurrentBacklogString\\n\\n\\t^currentBacklogString! !\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'RAA 11/8/2000 16:07'!\\ncurrentStatusString\\n\\n\\t^currentStatusString! !\\n\\n!NebraskaServerMorph methodsFor: 'accessing' stamp: 'ar 10/26/2000 14:05'!\\nserver\\n\\t^self world remoteServer! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:25'!\\nupdateCurrentStatusString\\n\\n\\tself server ifNil:[\\n\\t\\tcurrentStatusString := '<Nebraska not active>' translated.\\n\\t\\tcurrentBacklogString := ''.\\n\\t] ifNotNil:[\\n\\t\\tcurrentStatusString := \\n\\t\\t\\t' Nebraska: ' translated, \\n\\t\\t\\tself server numClients printString, \\n\\t\\t\\t' clients' translated.\\n\\t\\tcurrentBacklogString := 'backlog: ' translated,\\n\\t\\t\\t\\t((previousBacklog := self server backlog) // 1024) printString,'k'\\n\\t].\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:29'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color white! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tfullDisplay := false.\\n\\t\\n\\tlastFullUpdateTime := 0.\\n\\tself listDirection: #topToBottom;\\n\\t\\t hResizing: #shrinkWrap;\\n\\t\\t vResizing: #shrinkWrap! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\nrebuild\\n\\n\\t| myServer toggle closeBox font |\\n\\n\\tfont := StrikeFont familyName: #Palatino size: 14.\\n\\tself removeAllMorphs.\\n\\tself setColorsAndBorder.\\n\\tself updateCurrentStatusString.\\n\\ttoggle := SimpleHierarchicalListMorph new perform: (\\n\\t\\tfullDisplay ifTrue: [#expandedForm] ifFalse: [#notExpandedForm]\\n\\t).\\n\\tcloseBox := SimpleButtonMorph new borderWidth: 0;\\n\\t\\t\\tlabel: 'X' font: Preferences standardButtonFont; color: Color transparent;\\n\\t\\t\\tactionSelector: #delete; target: self; extent: 14@14;\\n\\t\\t\\tsetBalloonText: 'End Nebrasks session'.\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {closeBox}.\\n\\t\\tself inAColumn: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: self;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentStatusString;\\n\\t\\t\\t\\tcontents: self currentStatusString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}.\\n\\t\\tself inAColumn: {\\n\\t\\t\\ttoggle asMorph\\n\\t\\t\\t\\ton: #mouseUp send: #toggleFull to: self;\\n\\t\\t\\t\\tsetBalloonText: 'Show more or less of Nebraska Status'\\n\\t\\t}.\\n\\t}.\\n\\tmyServer := self server.\\n\\t(myServer isNil or: [fullDisplay not]) ifTrue: [\\n\\t\\t^World startSteppingSubmorphsOf: self\\n\\t].\\n\\t\\\"--- the expanded display ---\\\"\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: self;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentBacklogString;\\n\\t\\t\\t\\tcontents: self currentBacklogString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\t(StringMorph contents: '--clients--' translated) lock; font: font.\\n\\t\\t}.\\n\\t}.\\n\\n\\tmyServer clients do: [ :each |\\n\\t\\tself addARow: {\\n\\t\\t\\tUpdatingStringMorph new\\n\\t\\t\\t\\tuseStringFormat;\\n\\t\\t\\t\\ttarget: each;\\n\\t\\t\\t\\tfont: font;\\n\\t\\t\\t\\tgetSelector: #currentStatusString;\\n\\t\\t\\t\\tcontents: each currentStatusString;\\n\\t\\t\\t\\tstepTime: 2000;\\n\\t\\t\\t\\tlock.\\n\\t\\t}\\n\\t].\\n\\tWorld startSteppingSubmorphsOf: self.! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'aoy 2/15/2003 21:35'!\\nsetColorsAndBorder\\n\\t| worldColor c |\\n\\tc := ((Preferences menuColorFromWorld and: [Display depth > 4]) \\n\\t\\t\\t\\tand: [(worldColor := self currentWorld color) isColor]) \\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[worldColor luminance > 0.7 \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [worldColor mixed: 0.8 with: Color black]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [worldColor mixed: 0.4 with: Color white]]\\n\\t\\t\\t\\t\\tifFalse: [Preferences menuColor]. \\n\\tself color: c.\\n\\tself borderColor: #raised.\\n\\tself borderWidth: Preferences menuBorderWidth.\\n\\tself useRoundedCorners! !\\n\\n!NebraskaServerMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:25'!\\ntoggleFull\\n\\n\\tfullDisplay := fullDisplay not.\\n\\tself rebuild.\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'stepping and presenter' stamp: 'sd 11/20/2005 21:25'!\\nstep\\n\\n\\t| now |\\n\\n\\tself server ifNil: [ ^self ].\\n\\tself server step.\\n\\tnow := Time millisecondClockValue.\\n\\t(now - lastFullUpdateTime) abs > 5000 ifTrue: [\\n\\t\\tlastFullUpdateTime := now.\\n\\t\\t(previousBacklog = self server backlog and: [self server clients = previousClients]) ifFalse: [\\n\\t\\t\\tpreviousClients := self server clients copy.\\n\\t\\t\\tself rebuild\\n\\t\\t]\\n\\t].\\n! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'submorphs-add/remove' stamp: 'ar 10/26/2000 14:07'!\\ndelete\\n\\tself server ifNotNil:[\\n\\t\\t(self confirm:'Shutdown the server?') \\n\\t\\t\\tifTrue:[self world remoteServer: nil]].\\n\\tsuper delete.! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'testing' stamp: 'RAA 11/8/2000 15:57'!\\nstepTime\\n\\n\\t^10! !\\n\\n\\n!NebraskaServerMorph methodsFor: 'updating' stamp: 'RAA 11/8/2000 16:03'!\\nupdate: aSymbol\\n\\n\\tself rebuild.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNebraskaServerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 8/15/2000 14:49'!\\nkillOldServers\\n\\n\\tNebraskaServerMorph allInstances do: [ :each |\\n\\t\\teach delete.\\n\\t].\\n\\tNebraskaServer allInstances do: [ :each |\\n\\t\\teach stopListening.\\n\\t\\tDependentsFields removeKey: each ifAbsent: [].\\n\\t].\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:06'!\\nserveWorld\\n\\n\\t^ self serveWorld: ActiveWorld.\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:07'!\\nserveWorldButton\\n\\n\\t| button |\\n\\tbutton _ ScriptableButton new.\\n\\tbutton target: NebraskaServerMorph.\\n\\tbutton actionSelector: #serveWorld.\\n\\tbutton arguments: #().\\n\\tbutton label: 'Share'.\\n\\tbutton color: Color yellow.\\n\\t^ button.\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'wiz 1/9/2005 15:12'!\\nserveWorld: aWorld\\n\\t\\\"Check to make sure things won't crash. See Mantis #0000519\\\"\\n\\taWorld isSafeToServe ifTrue:[\\n\\t\\t^self serveWorld: aWorld onPort: NebraskaServer defaultPort]\\n\\t! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'ar 10/26/2000 14:05'!\\nserveWorld: aWorld onPort: aPortNumber\\n\\n\\t| server |\\n\\tserver := NebraskaServer serveWorld: aWorld onPort: aPortNumber.\\n\\t(self new) openInWorld: aWorld.\\n\\n\\t\\\"server acceptNullConnection\\\"\\t\\t\\\"server acceptPhonyConnection.\\\"\\n! !\\n\\n!NebraskaServerMorph class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 23:08'!\\nsupplementaryPartsDescriptions\\n\\t^ {DescriptionForPartsBin\\n\\t\\tformalName: 'NebraskaServer'\\n\\t\\tcategoryList: #('Collaborative')\\n\\t\\tdocumentation: 'A button to start the Nebraska desktop sharing server' translated\\n\\t\\tglobalReceiverSymbol: #NebraskaServerMorph\\n\\t\\tnativitySelector: #serveWorldButton\\n\\t}! !\\nObject subclass: #NetNameResolver\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DefaultHostName HaveNetwork ResolverBusy ResolverError ResolverMutex ResolverReady ResolverSemaphore ResolverUninitialized'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NetNameResolver commentStamp: '<historical>' prior: 0!\\nThis class implements TCP/IP style network name lookup and translation facilities.\\n\\nAttempt to keep track of whether there is a network available.\\nHaveNetwork\\ttrue if last attempt to contact the network was successful.\\nLastContact\\t\\tTime of that contact (totalSeconds).\\nhaveNetwork\\treturns true, false, or #expired. True means there was contact in the last 30 minutes. False means contact failed or was false last time we asked. Get out of false state by making contact with a server in some way (FileList or updates).!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNetNameResolver class\\n\\tinstanceVariableNames: ''!\\n\\n!NetNameResolver class methodsFor: 'address string utils' stamp: 'jm 9/15/97 06:19'!\\naddressFromString: addressString\\n\\t\\\"Return the internet address represented by the given string. The string should contain four positive decimal integers delimited by periods, commas, or spaces, where each integer represents one address byte. Return nil if the string is not a host address in an acceptable format.\\\"\\n\\t\\\"NetNameResolver addressFromString: '1.2.3.4'\\\"\\n\\t\\\"NetNameResolver addressFromString: '1,2,3,4'\\\"\\n\\t\\\"NetNameResolver addressFromString: '1 2 3 4'\\\"\\n\\n\\t| newAddr s byte delimiter |\\n\\tnewAddr _ ByteArray new: 4.\\n\\ts _ ReadStream on: addressString.\\n\\ts skipSeparators.\\n\\t1 to: 4 do: [:i |\\n\\t\\tbyte _ self readDecimalByteFrom: s.\\n\\t\\tbyte = nil ifTrue: [^ nil].\\n\\t\\tnewAddr at: i put: byte.\\n\\t\\ti < 4 ifTrue: [\\n\\t\\t\\tdelimiter _ s next.\\n\\t\\t\\t((delimiter = $.) or: [(delimiter = $,) or: [delimiter = $ ]])\\n\\t\\t\\t\\tifFalse: [^ nil]]].\\n\\t^ newAddr\\n! !\\n\\n!NetNameResolver class methodsFor: 'address string utils' stamp: 'jm 9/15/97 16:52'!\\nstringFromAddress: addr\\n\\t\\\"Return a string representing the given host address as four decimal bytes delimited with decimal points.\\\"\\n\\t\\\"NetNameResolver stringFromAddress: NetNameResolver localHostAddress\\\"\\n\\n\\t| s |\\n\\ts _ WriteStream on: ''.\\n\\t1 to: 3 do: [ :i | (addr at: i) printOn: s. s nextPut: $.].\\n\\t(addr at: 4) printOn: s.\\n\\t^ s contents\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'class initialization' stamp: 'jm 9/17/97 16:18'!\\ninitialize\\n\\t\\\"NetNameResolver initialize\\\"\\n\\t\\\"Note: On the Mac, the name resolver is asynchronous (i.e., Squeak can do other things while it is working), but can only handle one request at a time. On other platforms, such as Unix, the resolver is synchronous; a call to, say, the name lookup primitive will block all Squeak processes until it returns.\\\"\\n\\n\\t\\\"Resolver Status Values\\\"\\n\\tResolverUninitialized _ 0.\\t\\\"network is not initialized\\\"\\n\\tResolverReady _ 1.\\t\\t\\t\\\"resolver idle, last request succeeded\\\"\\n\\tResolverBusy _ 2.\\t\\t\\t\\\"lookup in progress\\\"\\n\\tResolverError _ 3.\\t\\t\\t\\\"resolver idle, last request failed\\\"\\n\\n\\tDefaultHostName _ ''.\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'ls 9/5/1998 01:14'!\\naddressForName: aString\\n\\t^self addressForName: aString timeout: 60! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mu 9/7/2003 22:53'!\\naddressForName: hostName timeout: secs\\n\\t\\\"Look up the given host name and return its address. Return nil if the address is not found in the given number of seconds.\\\"\\n\\t\\\"NetNameResolver addressForName: 'create.ucsb.edu' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '100000jobs.de' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '1.7.6.4' timeout: 30\\\"\\n\\t\\\"NetNameResolver addressForName: '' timeout: 30 (This seems to return nil?)\\\"\\n\\n\\t| deadline result |\\n\\tself initializeNetwork.\\n\\t\\\"check if this is a valid numeric host address (e.g. 1.2.3.4)\\\"\\n\\tresult _ self addressFromString: hostName.\\n\\tresult isNil ifFalse: [^result].\\n\\n\\t\\\"Look up a host name, including ones that start with a digit (e.g. 100000jobs.de or squeak.org)\\\"\\n\\tdeadline _ Time millisecondClockValue + (secs * 1000).\\n\\t\\\"Protect the execution of this block, as the ResolverSemaphore is used for both parts of the transaction.\\\"\\n\\tself resolverMutex\\n\\t\\tcritical: [\\n\\t\\t\\t(self waitForResolverReadyUntil: deadline)\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself primStartLookupOfName: hostName.\\n\\t\\t\\t\\t\\t(self waitForCompletionUntil: deadline)\\n\\t\\t\\t\\t\\t\\tifTrue: [result _ self primNameLookupResult]\\n\\t\\t\\t\\t\\t\\tifFalse: [(NameLookupFailure hostName: hostName) signal: 'Could not resolve the server named: ', hostName]]\\n\\t\\t\\t\\tifFalse: [(NameLookupFailure hostName: hostName) signal: 'Could not resolve the server named: ', hostName]].\\n\\t^result! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'jm 9/15/97 16:52'!\\nlocalAddressString\\n\\t\\\"Return a string representing the local host address as four decimal bytes delimited with decimal points.\\\"\\n\\t\\\"NetNameResolver localAddressString\\\"\\n\\n\\t^ NetNameResolver stringFromAddress: NetNameResolver localHostAddress\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mir 2/22/2002 15:50'!\\nlocalHostAddress\\n\\t\\\"Return the local address of this host.\\\"\\n\\t\\\"NetNameResolver localHostAddress\\\"\\n\\n\\tself initializeNetwork.\\n\\t^ self primLocalAddress\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'mir 2/22/2002 15:12'!\\nlocalHostName\\n\\t\\\"Return the local name of this host.\\\"\\n\\t\\\"NetNameResolver localHostName\\\"\\n\\n\\t| hostName |\\n\\thostName _ NetNameResolver\\n\\t\\tnameForAddress: self localHostAddress\\n\\t\\ttimeout: 5.\\n\\t^hostName\\n\\t\\tifNil: [self localAddressString]\\n\\t\\tifNotNil: [hostName]! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'nk 6/27/2003 10:51'!\\nnameForAddress: hostAddress timeout: secs\\n\\t\\\"Look up the given host address and return its name. Return nil if the lookup fails or is not completed in the given number of seconds. Depends on the given host address being known to the gateway, which may not be the case for dynamically allocated addresses.\\\"\\n\\t\\\"NetNameResolver\\n\\t\\tnameForAddress: (NetNameResolver addressFromString: '128.111.92.2')\\n\\t\\ttimeout: 30\\\"\\n\\n\\t| deadline result |\\n\\tself initializeNetwork.\\n\\tdeadline _ Time millisecondClockValue + (secs * 1000).\\n\\t\\\"Protect the execution of this block, as the ResolverSemaphore is used for both parts of the transaction.\\\"\\n\\tself resolverMutex\\n\\t\\tcritical: [\\n\\t\\t\\tresult _ (self waitForResolverReadyUntil: deadline)\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself primStartLookupOfAddress: hostAddress.\\n\\t\\t\\t\\t\\t(self waitForCompletionUntil: deadline)\\n\\t\\t\\t\\t\\t\\tifTrue: [self primAddressLookupResult]\\n\\t\\t\\t\\t\\t\\tifFalse: [nil]]\\n\\t\\t\\t\\tifFalse: [nil]].\\n\\t^result\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'jm 9/17/97 16:26'!\\npromptUserForHostAddress\\n\\t\\\"Ask the user for a host name and return its address.\\\"\\n\\t\\\"NetNameResolver promptUserForHostAddress\\\"\\n\\n\\t^ NetNameResolver promptUserForHostAddressDefault: ''\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'rbb 3/1/2005 11:01'!\\npromptUserForHostAddressDefault: defaultName\\n\\t\\\"Ask the user for a host name and return its address. If the default name is the empty string, use the last host name as the default.\\\"\\n\\t\\\"NetNameResolver promptUserForHostAddressDefault: ''\\\"\\n\\n\\t| default hostName serverAddr |\\n\\tdefaultName isEmpty\\n\\t\\tifTrue: [default := DefaultHostName]\\n\\t\\tifFalse: [default := defaultName].\\n\\thostName := UIManager default\\n\\t\\trequest: 'Host name or address?'\\n\\t\\tinitialAnswer: default.\\n\\thostName isEmpty ifTrue: [^ 0].\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 15.\\n\\thostName size > 0 ifTrue: [DefaultHostName := hostName].\\n\\t^ serverAddr! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'JMM 5/3/2000 11:25'!\\nresolverError\\n\\t^self primNameResolverError\\n! !\\n\\n!NetNameResolver class methodsFor: 'lookups' stamp: 'JMM 5/3/2000 11:25'!\\nresolverStatus\\n\\t^self primNameResolverStatus\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 15:03'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and record the semaphore to be used by the resolver. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails.\\\"\\n\\t\\\"NetNameResolver initializeNetwork\\\"\\n\\n\\t| semaIndex |\\n\\tself resolverStatus = ResolverUninitialized\\n\\t\\tifFalse: [^HaveNetwork _ true]. \\\"network is already initialized\\\"\\n\\n\\tHaveNetwork _ false.\\t\\\"in case abort\\\"\\n\\tResolverSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: ResolverSemaphore.\\n\\n\\t\\\"result is nil if network initialization failed, self if it succeeds\\\"\\n\\t(self primInitializeNetwork: semaIndex)\\n\\t\\tifNil: [NoNetworkError signal: 'failed network initialization']\\n\\t\\tifNotNil: [HaveNetwork _ true].\\n! !\\n\\n!NetNameResolver class methodsFor: 'network initialization' stamp: 'ar 2/2/2001 15:09'!\\nprimInitializeNetwork: resolverSemaIndex\\n\\t\\\"Initialize the network drivers on platforms that need it, such as the Macintosh, and return nil if network initialization failed or the reciever if it succeeds. Since mobile computers may not always be connected to a network, this method should NOT be called automatically at startup time; rather, it should be called when first starting a networking application. It is a noop if the network driver has already been initialized. If non-zero, resolverSemaIndex is the index of a VM semaphore to be associated with the network name resolver. This semaphore will be signalled when the resolver status changes, such as when a name lookup query is completed.\\\"\\n\\t\\\"Note: some platforms (e.g., Mac) only allow only one name lookup query at a time, so a manager process should be used to serialize resolver lookup requests.\\\"\\n\\n\\t<primitive: 'primitiveInitializeNetwork' module: 'SocketPlugin'>\\n\\t^ nil \\\"return nil if primitive fails\\\"\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAbortLookup\\n\\t\\\"Abort the current lookup operation, freeing the name resolver for the next query.\\\"\\n\\n\\t<primitive: 'primitiveResolverAbortLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAddressLookupResult\\n\\t\\\"Return the host name found by the last host address lookup. Returns nil if the last lookup was unsuccessful.\\\"\\n\\n\\t<primitive: 'primitiveResolverAddressLookupResult' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimLocalAddress\\n\\t\\\"Return the local address of this host.\\\"\\n\\n\\t<primitive: 'primitiveResolverLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameLookupResult\\n\\t\\\"Return the host address found by the last host name lookup. Returns nil if the last lookup was unsuccessful.\\\"\\n\\n\\t<primitive: 'primitiveResolverNameLookupResult' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameResolverError\\n\\t\\\"Return an integer reflecting the error status of the last network name resolver request. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveResolverError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimNameResolverStatus\\n\\t\\\"Return an integer reflecting the status of the network name resolver. For a list of possible values, see the comment in the 'initialize' method of this class.\\\"\\n\\n\\t<primitive: 'primitiveResolverStatus' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartLookupOfAddress: hostAddr\\n\\t\\\"Look up the given host address in the Domain Name Server to find its name. This call is asynchronous. To get the results, wait for it to complete or time out and then use primAddressLookupResult.\\\"\\n\\n\\t<primitive: 'primitiveResolverStartAddressLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!NetNameResolver class methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartLookupOfName: hostName\\n\\t\\\"Look up the given host name in the Domain Name Server to find its address. This call is asynchronous. To get the results, wait for it to complete or time out and then use primNameLookupResult.\\\"\\n\\n\\t<primitive: 'primitiveResolverStartNameLookup' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 13:57'!\\nreadDecimalByteFrom: aStream\\n\\t\\\"Read a positive, decimal integer from the given stream. Stop when a non-digit or end-of-stream is encountered. Return nil if stream is not positioned at a decimal digit or if the integer value read exceeds 255.\\nJMM - 000503 fixed didn't work correctly\\\"\\n\\n\\t| digitSeen value digit |\\n\\tdigitSeen _ false.\\n\\tvalue _ 0.\\n\\t[aStream atEnd] whileFalse: \\n\\t\\t[digit _ aStream next digitValue.\\n\\t\\t(digit < 0 or: [digit > 9]) ifTrue: [\\n\\t\\t\\taStream skip: -1.\\n\\t\\t\\t(digitSeen not or: [value > 255]) ifTrue: [^ nil].\\n\\t\\t\\t^ value].\\n\\t\\tdigitSeen _ true.\\n\\t\\tvalue _ (value * 10) + digit].\\n\\t(digitSeen not or: [value > 255]) ifTrue: [^ nil].\\n\\t^ value\\n! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'mir 6/18/2001 21:05'!\\nresolverMutex\\n\\tResolverMutex ifNil: [ResolverMutex _ Semaphore forMutualExclusion].\\n\\t^ResolverMutex! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 11:35'!\\nwaitForCompletionUntil: deadline\\n\\t\\\"Wait up to the given number of seconds for the resolver to be ready to accept a new request. Return true if the resolver is ready, false if the network is not initialized or the resolver does not become free within the given time period.\\\"\\n\\n\\t| status |\\n\\tstatus _ self resolverStatus.\\n\\t[(status = ResolverBusy) and:\\n\\t [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\t\\\"wait for resolver to be available\\\"\\n\\t\\t\\tResolverSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self resolverStatus].\\n\\n\\tstatus = ResolverReady\\n\\t\\tifTrue: [^ true]\\n\\t\\tifFalse: [\\n\\t\\t\\tstatus = ResolverBusy ifTrue: [self primAbortLookup].\\n\\t\\t\\t^ false].\\n! !\\n\\n!NetNameResolver class methodsFor: 'private' stamp: 'JMM 5/3/2000 11:36'!\\nwaitForResolverReadyUntil: deadline\\n\\t\\\"Wait up to the given number of seconds for the resolver to be ready to accept a new request. Return true if the resolver is not busy, false if the network is not initialized or the resolver does not become free within the given time period.\\\"\\n\\n\\t| status |\\n\\tstatus _ self resolverStatus.\\n\\tstatus = ResolverUninitialized ifTrue: [^ false].\\n\\n\\t[(status = ResolverBusy) and:\\n\\t [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\t\\\"wait for resolver to be available\\\"\\n\\t\\t\\tResolverSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self resolverStatus].\\n\\n\\t^ status ~= ResolverBusy\\n! !\\nError subclass: #NetworkError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NetworkError commentStamp: 'mir 5/12/2003 18:12' prior: 0!\\nAbstract super class for all network related exceptions.!\\n\\nEmbeddedWorldBorderMorph subclass: #NetworkTerminalBorderMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NetworkTerminalBorderMorph methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:25'!\\ntoggleFullView\\n\\t\\\"Toggle the full view for network terminal\\\"\\n\\t| fullExtent priorExtent |\\n\\tfullExtent := self worldIEnclose extent + (2 * self borderWidth).\\n\\tpriorExtent := self valueOfProperty: #priorExtent.\\n\\tpriorExtent ifNil:[\\n\\t\\tself setProperty: #priorExtent toValue: self extent.\\n\\t\\tself extent: fullExtent.\\n\\t\\tself position: self position + self borderWidth asPoint negated.\\n\\t] ifNotNil:[\\n\\t\\tself removeProperty: #priorExtent.\\n\\t\\tself extent: priorExtent.\\n\\t\\tself position: (self position max: 0@0).\\n\\t].! !\\n\\n\\n!NetworkTerminalBorderMorph methodsFor: 'boxes' stamp: 'RAA 8/15/2000 12:21'!\\nboxesAndColorsAndSelectors\\n\\n\\t^#()! !\\n\\n\\n!NetworkTerminalBorderMorph methodsFor: 'initialization' stamp: 'RAA 12/14/2000 14:12'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself setBalloonText: nil.\\t\\t\\\"'I am a view on another Squeak'.\\\"\\n\\tself layoutInset: 0.\\n! !\\nMorph subclass: #NetworkTerminalMorph\\n\\tinstanceVariableNames: 'connection decoder eventEncoder backgroundForm enteringHand'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n!NetworkTerminalMorph commentStamp: '<historical>' prior: 0!\\nA morph used to communicate with a remote image. It sends all mouse/keyboard events to the remote side, and it displays canvas commands that are sent back.!\\n\\n\\n!NetworkTerminalMorph methodsFor: 'as yet unclassified' stamp: 'RAA 8/29/2000 12:13'!\\naddScalingMenuItems: menu hand: aHandMorph\\n\\n\\t\\\"for comaptibility when in scaled frame\\\"! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/25/2000 13:00'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"I assume that we are opaque\\\"\\n\\n\\t^ aRectangle areasOutside: self bounds! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/24/2000 11:43'!\\ndrawOn: aCanvas\\n\\n\\tbackgroundForm ifNotNil: [\\n\\t\\taCanvas clipBy: bounds during: [ :c |\\n\\t\\t\\tc drawImage: backgroundForm at: bounds topLeft\\n\\t\\t].\\n\\t].\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:25'!\\nforceToFront: aRegion\\n\\t| highQuality |\\n\\t\\\"force the given region from the drawing form onto the background form\\\"\\n\\n\\thighQuality := false.\\t\\t\\\"highQuality is slower\\\"\\n\\n\\tself updateBackgroundForm.\\n\\tbackgroundForm\\n\\t\\tcopy: aRegion\\n\\t\\tfrom: aRegion topLeft\\n\\t\\tin: decoder drawingForm\\n\\t\\trule: Form over.\\n\\tself invalidRect: (\\n\\t\\thighQuality ifTrue: [\\n\\t\\t\\tbounds\\n\\t\\t] ifFalse: [\\n\\t\\t\\t(aRegion expandBy: 4) translateBy: bounds topLeft\\t\\\"try to remove gribblys\\\"\\n\\t\\t]\\n\\t)\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\nupdateBackgroundForm\\n\\t\\\"make sure that our background form matches what the server has most recently requested\\\"\\n\\n\\t| drawingForm |\\n\\n\\tdrawingForm := decoder drawingForm.\\n\\t(drawingForm extent = backgroundForm extent and: [\\n\\t\\tdrawingForm depth = backgroundForm depth ]) ifTrue: [\\n\\t\\t\\t\\\"they match just fine\\\"\\n\\t\\t\\t^self ].\\n\\n\\tbackgroundForm := drawingForm deepCopy.\\t\\t\\\"need copy to capture the moment\\\"\\n\\tself extent: backgroundForm extent.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'dropping/grabbing' stamp: 'RAA 11/5/2000 13:26'!\\nwantsDroppedMorph: aMorph event: evt\\n\\n\\t^true.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 11/5/2000 13:23'!\\ncommResult: anArrayOfAssociations\\n\\n\\t\\\"ignore for now\\\"! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:25'!\\nhandlesMouseOver: evt\\n\\t^true! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:24'!\\nmouseEnter: evt\\n\\tevt hand newKeyboardFocus: self.\\n\\tevt hand needsToBeDrawn ifTrue:[Cursor blank show].! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'ar 10/26/2000 15:25'!\\nmouseLeave: evt\\n\\n\\tevt hand needsToBeDrawn ifTrue:[Cursor normal show].! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 8/15/2000 11:34'!\\nsendEvent: evt\\n\\n\\tself sendEventAsIs: (evt translatedBy: bounds topLeft negated).! !\\n\\n!NetworkTerminalMorph methodsFor: 'event handling' stamp: 'RAA 8/15/2000 11:33'!\\nsendEventAsIs: evt\\n\\n\\teventEncoder ifNil: [ ^self ].\\n\\teventEncoder sendEvent: evt.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:02'!\\nhandleKeyDown: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:02'!\\nhandleKeyUp: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\t(self handlesKeyboard: anEvent) ifFalse:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:11'!\\nhandleKeystroke: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:03'!\\nhandleMouseDown: anEvent\\n\\tanEvent wasHandled ifTrue:[^self].\\n\\tanEvent hand removePendingBalloonFor: self.\\n\\tanEvent hand removePendingHaloFor: self.\\n\\tanEvent wasHandled: true.\\n\\tanEvent hand newMouseFocus: self event: anEvent.\\n\\tanEvent hand removeHaloFromClick: anEvent on: self.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:04'!\\nhandleMouseMove: anEvent\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\t(anEvent hand hasSubmorphs) ifTrue:[^self].\\n\\t(anEvent anyButtonPressed and:[anEvent hand mouseFocus ~~ self]) ifTrue:[^self].\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:03'!\\nhandleMouseUp: anEvent\\n\\tanEvent wasHandled ifTrue:[^self]. \\\"not interested\\\"\\n\\tanEvent hand mouseFocus == self ifFalse:[^self]. \\\"Not interested in other parties\\\"\\n\\tanEvent hand releaseMouseFocus: self.\\n\\tanEvent wasHandled: true.\\n\\tself sendEventAsIs: anEvent.! !\\n\\n!NetworkTerminalMorph methodsFor: 'events-processing' stamp: 'ar 10/24/2000 18:06'!\\nhandlerForMouseDown: anEvent\\n\\t^self! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'geometry' stamp: 'RAA 7/24/2000 11:35'!\\nextent: newExtent\\n\\n\\tsuper extent: newExtent.\\n\\teventEncoder sendViewExtent: self extent! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 12:06'!\\nconnection: aConnection\\n\\n\\tconnection := aConnection.\\n\\tdecoder := CanvasDecoder connection: aConnection.\\n\\teventEncoder := MorphicEventEncoder on: aConnection.! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\tsuper initialize.\\n\\tbackgroundForm := (\\n\\t\\t(StringMorph contents: '......' font: (TextStyle default fontOfSize: 24))\\n\\t\\t\\tcolor: Color white\\n\\t) imageForm.\\n\\tbounds := backgroundForm boundingBox.\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 10:45'!\\nopenInStyle: aSymbol\\n\\n\\taSymbol == #naked ifTrue: [\\n\\t\\tself openInWorld.\\n\\t].\\n\\taSymbol == #scaled ifTrue: [\\n\\t\\tself openScaled.\\n\\t].\\n\\taSymbol == #bordered ifTrue: [\\n\\t\\tAlignmentMorph newColumn\\n\\t\\t\\thResizing: \\t#shrinkWrap;\\n\\t\\t\\tvResizing: \\t#shrinkWrap;\\n\\t\\t\\tborderWidth: 8;\\n\\t\\t\\tborderColor: Color blue;\\n\\t\\t\\taddMorph: self;\\n\\t\\t\\topenInWorld.\\n\\t].\\n\\n\\t[\\n\\t\\t[self world isNil] whileFalse: [(Delay forSeconds: 2) wait].\\n\\t\\tself disconnect.\\n\\t] fork.\\n\\n! !\\n\\n!NetworkTerminalMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\nopenScaled\\n\\n\\t| window tm |\\n\\twindow := NetworkTerminalBorderMorph new\\n\\t\\tminWidth: 100;\\n\\t\\tminHeight: 100;\\n\\t\\tborderWidth: 8;\\n\\t\\tborderColor: Color orange;\\n\\t\\tbounds: (0@0 extent: Display extent * 3 // 4).\\n\\ttm := BOBTransformationMorph new.\\n\\ttm useRegularWarpBlt: true.\\t\\t\\\"try to reduce memory used\\\"\\n\\twindow addMorphBack: tm.\\n\\ttm addMorph: self.\\n\\twindow openInWorld.\\n\\tNebraskaNavigationMorph new \\n\\t\\tnebraskaBorder: window;\\n\\t\\tnebraskaTerminal: self;\\n\\t\\topenInWorld.! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'layout' stamp: 'sd 11/20/2005 21:25'!\\nacceptDroppingMorph: morphToDrop event: evt\\n\\n\\t| myCopy outData null |\\n\\n\\t(morphToDrop isKindOf: NewHandleMorph) ifTrue: [\\t\\t\\t\\\"don't send these\\\"\\n\\t\\t^morphToDrop rejectDropMorphEvent: evt.\\n\\t].\\n\\tself eToyRejectDropMorph: morphToDrop event: evt.\\t\\t\\\"we don't really want it\\\"\\n\\n\\t\\\"7 mar 2001 - remove #veryDeepCopy\\\"\\n\\tmyCopy := morphToDrop.\\t\\\"gradient fills require doing this second\\\"\\n\\tmyCopy setProperty: #positionInOriginatingWorld toValue: morphToDrop position.\\n\\n\\toutData := myCopy eToyStreamedRepresentationNotifying: nil.\\n\\tnull := String with: 0 asCharacter.\\n\\tEToyPeerToPeer new \\n\\t\\tsendSomeData: {\\n\\t\\t\\tEToyIncomingMessage typeMorph,null. \\n\\t\\t\\tPreferences defaultAuthorName,null.\\n\\t\\t\\toutData\\n\\t\\t}\\n\\t\\tto: (NetNameResolver stringFromAddress: connection remoteAddress)\\n\\t\\tfor: self.\\n! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'shutting down' stamp: 'ls 4/11/2000 18:36'!\\ndisconnect\\n\\tconnection ifNotNil: [ connection destroy ].\\n\\teventEncoder := connection := decoder := nil.! !\\n\\n!NetworkTerminalMorph methodsFor: 'shutting down' stamp: 'RAA 12/13/2000 08:21'!\\nrequestBufferedConnection\\n\\n\\teventEncoder ifNotNil: [eventEncoder requestBufferedConnection].\\n! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'stepping and presenter' stamp: 'ar 10/25/2000 23:19'!\\nstep\\n\\n\\tdecoder ifNil: [ ^self ].\\n\\tdecoder processIOOnForce: [ :rectangle | self forceToFront: rectangle ].! !\\n\\n\\n!NetworkTerminalMorph methodsFor: 'testing' stamp: 'ls 3/25/2000 16:58'!\\nstepTime\\n\\t^10! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNetworkTerminalMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'RAA 8/4/2000 15:13'!\\nconnectTo: serverHost\\n\\n\\t^self connectTo: serverHost port: NebraskaServer defaultPort\\n\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nconnectTo: serverHost port: serverPort\\n\\n\\t| stringSock |\\n\\n\\tstringSock := self socketConnectedTo: serverHost port: serverPort.\\n\\t^self new connection: stringSock\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'RAA 7/24/2000 12:08'!\\nopenAndConnectTo: serverHost\\n\\n\\t^self openAndConnectTo: serverHost port: NebraskaServer defaultPort\\n\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nopenAndConnectTo: serverHost port: serverPort\\n\\n\\t| stringSock me |\\n\\n\\tstringSock := self socketConnectedTo: serverHost port: serverPort.\\n\\tme := self new connection: stringSock.\\n\\t^me openInStyle: #naked\\n! !\\n\\n!NetworkTerminalMorph class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:26'!\\nsocketConnectedTo: serverHost port: serverPort\\n\\n\\t| sock |\\n\\n\\tSocket initializeNetwork.\\n\\tsock := Socket new.\\n\\t[sock connectTo: (NetNameResolver addressForName: serverHost) port: serverPort]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | self error: 'could not connect to server' ].\\n\\t^StringSocket on: sock\\n\\n! !\\nHandleMorph subclass: #NewHandleMorph\\n\\tinstanceVariableNames: 'hand offset waitingForClickInside'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Widgets'!\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'di 5/18/1998 15:27'!\\nfollowHand: aHand forEachPointDo: block1 lastPointDo: block2\\n\\thand _ aHand.\\n\\tpointBlock _ block1.\\n\\tlastPointBlock _ block2.\\n\\tself position: hand lastEvent cursorPoint - (self extent // 2)! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'ar 8/16/2001 15:48'!\\nfollowHand: aHand forEachPointDo: block1 lastPointDo: block2 withCursor: aCursor\\n\\thand _ aHand.\\n\\thand showTemporaryCursor: aCursor \\\"hotSpotOffset: aCursor offset negated\\\".\\n\\tborderWidth _ 0.\\n\\tcolor _ Color transparent.\\n\\tpointBlock _ block1.\\n\\tlastPointBlock _ block2.\\n\\tself position: hand lastEvent cursorPoint - (self extent // 2)! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'RAA 4/19/2001 11:36'!\\nsensorMode\\n\\n\\t\\\"If our client is still addressing the Sensor directly, we need to do so as well\\\"\\n\\t^self valueOfProperty: #sensorMode ifAbsent: [false].\\n! !\\n\\n!NewHandleMorph methodsFor: 'all' stamp: 'RAA 4/19/2001 11:36'!\\nsensorMode: aBoolean\\n\\n\\t\\\"If our client is still addressing the Sensor directly, we need to do so as well\\\"\\n\\tself setProperty: #sensorMode toValue: aBoolean.\\n! !\\n\\n\\n!NewHandleMorph methodsFor: 'dropping/grabbing' stamp: 'di 4/30/1999 14:06'!\\njustDroppedInto: aMorph event: anEvent\\n\\t\\\"No dropping behavior because stepping will delete me.\\n\\tMoreover it needs to be done that way to evaluate lastPointBlock\\\"\\n! !\\n\\n!NewHandleMorph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 18:16'!\\nundoGrabCommand\\n\\t^nil! !\\n\\n\\n!NewHandleMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:29'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\n\\tsuper initialize.\\n\\\"\\\"\\n\\twaitingForClickInside _ true.\\n\\tPreferences noviceMode\\n\\t\\tifTrue: [self setBalloonText: 'stretch']! !\\n\\n\\n!NewHandleMorph methodsFor: 'stepping and presenter' stamp: 'RAA 4/19/2001 11:37'!\\nstep\\n\\t| eventSource |\\n\\n\\teventSource _ self sensorMode ifTrue: [\\n\\t\\tSensor\\n\\t] ifFalse: [\\n\\t\\thand lastEvent\\n\\t].\\n\\teventSource anyButtonPressed\\n\\t\\tifTrue: [waitingForClickInside _ false.\\n\\t\\t\\t\\tself position: eventSource cursorPoint - (self extent // 2).\\n\\t\\t\\t\\tpointBlock value: self center]\\n\\t\\tifFalse: [waitingForClickInside\\n\\t\\t\\t\\t\\tifTrue: [(self containsPoint: eventSource cursorPoint)\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [\\\"mouse wandered out before clicked\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t^ self delete]]\\n\\t\\t\\t\\t\\tifFalse: [lastPointBlock value: self center.\\n\\t\\t\\t\\t\\t\\t\\t^ self delete]]! !\\n\\n\\n!NewHandleMorph methodsFor: 'submorphs-add/remove' stamp: 'ar 8/16/2001 15:38'!\\ndelete\\n\\thand ifNotNil:[\\n\\t\\thand showTemporaryCursor: nil.\\n\\t].\\n\\tsuper delete.! !\\n\\n\\n!NewHandleMorph methodsFor: 'WiW support' stamp: 'RAA 1/10/2001 10:15'!\\nmorphicLayerNumber\\n\\n\\t^1\\t\\t\\\"handles are very front-like - e.g. the spawn reframe logic actually asks if the first submorph of the world is one of us before deciding to create one\\\"! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNewHandleMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!NewHandleMorph class methodsFor: 'new-morph participation' stamp: 'di 5/3/1998 10:08'!\\nincludeInNewMorphMenu\\n\\t^ false! !\\nObject subclass: #NewParagraph\\n\\tinstanceVariableNames: 'text textStyle firstCharacterIndex container lines positionWhenComposed offsetToEnd maxRightX selectionStart selectionStop wantsColumnBreaks focused'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!NewParagraph commentStamp: '<historical>' prior: 0!\\nA Paragraph represents text that has been laid out, or composed, in some container.\\n\\ttext \\t\\tA Text with encoded per-character emphasis.\\n\\ttextStyle\\tA TextStyle with font set, line height and horizontal alignment.\\n\\tfirstCharacterIndex The starting index in text for this paragraph, allowing\\n\\t\\t\\t\\tcomposition of a long text into a number of containers.\\n\\tcontainer\\tA Rectangle or TextContainer that determines where text can go.\\n\\tlines\\t\\tAn Array of TextLines comprising the final layout of the text\\n\\t\\t\\t\\tafter it has been composed within its container.\\n\\tpositionWhenComposed As its name implies. Allows display at new locations\\n\\t\\t\\t\\twithout the need to recompose the text.\\nLines are ordered vertically. However, for a given y, there may be several lines in left to right order. Lines must never be empty, even if text is empty.\\n\\nNotes on yet another hack - 5 Feb 2001\\n\\nWe really need to clean up #composeLinesFrom:to:delta:into:priorLines:atY:!!!!!!\\n\\nI added one more habdful of code to correct:\\n\\nThis is an annoying bug that's been around for a couple of years, but I finally figured out how to duplicate the problem, so I figured I'd just report it now. (It doesn't necessarily have to be fixed for 3.0 if it looks messy, but if it's a simple fix, it would be worth it.)\\n\\nIn Morphic, if you have the following text in a workspace:\\n\\nThis is line 1\\nThis is line 2\\n\\n**and** you have a return character after line 2, you will normally be able to click the mouse two times below line 2 in order to select all the text. If you edit line 2 (e.g. so that it reads \\\"line number 2\\\"), you can still select all the text by clicking below the second line. However, if you edit line 1, you will not be able to select all the text from the bottom in the same way. Things get messed up such that the last return character seems to be gone. In this state, if you position the cursor immediately after the 2, and press the right arrow, the cursor jumps to the beginning of line 2... oof. (report by Doug Way)\\n\\nWhile I don't have a very deep understanding of the above mentioned method, I was able to determine that text ending in a CR worked better in the editor when the last entry in <lines> had a start of text size + 1 and a stop of text size. I have accordingly added code near the end to ensure this. It seems to have fixed the problem, but we do need to clean this baby up some day. - Bob\\n!\\n]style[(830 38 127 1000 388)f1,f2cblue;,f1,f1cred;,f1!\\n\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 11/16/97 09:02'!\\nadjustedFirstCharacterIndex\\n\\t\\\"Return the index in the text where this paragraph WOULD begin if nothing had changed, except the size of the text -- ie if there have only been an insertion of deletion in the preceding morphs\\\"\\n\\toffsetToEnd ifNil: [^ -1].\\n\\t^ text size - offsetToEnd! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/24/97 17:38'!\\nextent\\n\\t^ container width @ (lines last bottom - lines first top)! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 11/8/97 15:41'!\\nfirstCharacterIndex\\n\\t^ firstCharacterIndex! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'rr 3/22/2004 12:42'!\\nfocused\\n\\tfocused ifNil: [focused := false].\\n\\t^ focused! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'rr 3/22/2004 12:41'!\\nfocused: aBoolean\\n\\tfocused := aBoolean! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/23/97 21:01'!\\nlastCharacterIndex\\n\\t^ lines last last! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'sbw 10/13/1999 22:31'!\\nnumberOfLines\\n\\n\\t^lines size! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'sw 1/13/98 21:31'!\\nstring\\n\\t^ text string! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/21/97 14:39'!\\ntext\\n\\t^ text! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'jm 11/19/97 20:27'!\\ntextOwner: ignored \\\"See TextOnCurve\\\"! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/21/97 14:39'!\\ntextStyle\\n\\t^ textStyle! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'di 10/23/97 19:33'!\\ntextStyle: aTextStyle \\n\\t\\\"Set the style by which the receiver should display its text.\\\"\\n\\ttextStyle _ aTextStyle! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'RAA 5/6/2001 15:04'!\\nwantsColumnBreaks\\n\\n\\t^wantsColumnBreaks! !\\n\\n!NewParagraph methodsFor: 'access' stamp: 'RAA 5/6/2001 15:03'!\\nwantsColumnBreaks: aBoolean\\n\\n\\twantsColumnBreaks _ aBoolean! !\\n\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\ncentered \\n\\ttextStyle centered! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\njustified \\n\\ttextStyle justified! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\nleftFlush \\n\\ttextStyle leftFlush! !\\n\\n!NewParagraph methodsFor: 'alignment' stamp: 'di 10/25/97 19:26'!\\nrightFlush \\n\\ttextStyle rightFlush! !\\n\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'jm 2/25/2003 16:20'!\\nOLDcomposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines atY: startingY \\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| charIndex lineY lineHeight scanner line row firstLine lineHeightGuess saveCharIndex hitCR maybeSlide sliding bottom priorIndex priorLine |\\n\\tcharIndex := start.\\n\\tlines := lineColl.\\n\\tlineY := startingY.\\n\\tlineHeightGuess := textStyle lineGrid.\\n\\tmaxRightX := container left.\\n\\tmaybeSlide := stop < text size and: [container isMemberOf: Rectangle].\\n\\tsliding := false.\\n\\tpriorIndex := 1.\\n\\tbottom := container bottom.\\n\\tscanner := CompositionScanner new text: text textStyle: textStyle.\\n\\tfirstLine := true.\\n\\t[charIndex <= text size and: [lineY + lineHeightGuess <= bottom]] \\n\\t\\twhileTrue: \\n\\t\\t\\t[sliding \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"Having detected the end of rippling recoposition, we are only sliding old lines\\\"\\n\\n\\t\\t\\t\\t\\tpriorIndex < priorLines size \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"Adjust and re-use previously composed line\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tpriorIndex := priorIndex + 1.\\n\\t\\t\\t\\t\\t\\t\\tpriorLine := (priorLines at: priorIndex) slideIndexBy: delta\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tandMoveTopTo: lineY.\\n\\t\\t\\t\\t\\t\\t\\tlineColl addLast: priorLine.\\n\\t\\t\\t\\t\\t\\t\\tlineY := priorLine bottom.\\n\\t\\t\\t\\t\\t\\t\\tcharIndex := priorLine last + 1]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"There are no more priorLines to slide.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tsliding := maybeSlide := false]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[lineHeight := lineHeightGuess.\\n\\t\\t\\t\\t\\tsaveCharIndex := charIndex.\\n\\t\\t\\t\\t\\thitCR := false.\\n\\t\\t\\t\\t\\trow := container rectanglesAt: lineY height: lineHeight.\\n\\t\\t\\t\\t\\t1 to: row size\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\t\\t(charIndex <= text size and: [hitCR not]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[line := scanner \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomposeFrom: charIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinRectangle: (row at: i)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfirstLine: firstLine\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tleftSide: i = 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trightSide: i = row size.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlines addLast: line.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(text at: line last) = Character cr ifTrue: [hitCR := true].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlineHeight := lineHeight max: line lineHeight.\\t\\\"includes font changes\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex := line last + 1]].\\n\\n\\t\\t\\t\\t\\tlineY := lineY + lineHeight.\\n\\t\\t\\t\\t\\trow notEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[lineY > bottom \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Oops -- the line is really too high to fit -- back out\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex := saveCharIndex.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\trow do: [:r | lines removeLast]]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"It's OK -- the line still fits.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxRightX := maxRightX max: scanner rightX.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t1 to: row size - 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"Adjust heights across row if necess\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(lines at: lines size - row size + i) lineHeight: lines last lineHeight\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseline: lines last baseline].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcharIndex > text size \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"end of text\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thitCR \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"If text ends with CR, add a null line at the end\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlineY + lineHeightGuess <= container bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[row := container rectanglesAt: lineY height: lineHeightGuess.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trow notEmpty \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[line := (TextLine \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstart: charIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstop: charIndex - 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinternalSpaces: 0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpaddingWidth: 0)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trectangle: row first;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlines addLast: line]]].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlines := lines asArray.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t^maxRightX].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tfirstLine := false]].\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t(maybeSlide and: [charIndex > stop]) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"Check whether we are now in sync with previously composed lines\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t\\t[priorIndex < priorLines size \\n\\t\\t\\t\\t\\t\\t\\t\\tand: [(priorLines at: priorIndex) first < (charIndex - delta)]] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twhileTrue: [priorIndex := priorIndex + 1].\\n\\t\\t\\t\\t\\t\\t\\t(priorLines at: priorIndex) first = (charIndex - delta) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Yes -- next line will have same start as prior line.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tpriorIndex := priorIndex - 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmaybeSlide := false.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tsliding := true]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[priorIndex = priorLines size \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"Weve reached the end of priorLines,\\n\\t\\t\\t\\t\\t\\t\\t\\tso no use to keep looking for lines to slide.\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaybeSlide := false]]]]].\\n\\tfirstLine \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"No space in container or empty text\\\"\\n\\n\\t\\t\\tline := (TextLine \\n\\t\\t\\t\\t\\t\\tstart: start\\n\\t\\t\\t\\t\\t\\tstop: start - 1\\n\\t\\t\\t\\t\\t\\tinternalSpaces: 0\\n\\t\\t\\t\\t\\t\\tpaddingWidth: 0)\\n\\t\\t\\t\\t\\t\\trectangle: (container topLeft extent: 0 @ lineHeightGuess);\\n\\t\\t\\t\\t\\t\\tlineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\t\\t\\tlines := Array with: line]\\n\\t\\tifFalse: [self fixLastWithHeight: lineHeightGuess].\\n\\t\\\"end of container\\\"\\n\\tlines := lines asArray.\\n\\t^maxRightX! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 11/8/97 15:31'!\\ncompose: t style: ts from: startingIndex in: textContainer\\n\\ttext _ t.\\n\\ttextStyle _ ts.\\n\\tfirstCharacterIndex _ startingIndex.\\n\\toffsetToEnd _ text size - firstCharacterIndex.\\n\\tcontainer _ textContainer.\\n\\tself composeAll! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/20/2002 16:18'!\\ncomposeAll\\n\\ttext string isOctetString ifTrue: [\\n\\t\\t^ self composeLinesFrom: firstCharacterIndex to: text size delta: 0\\n\\t\\t\\tinto: OrderedCollection new priorLines: Array new atY: container top.\\n\\t].\\n\\n\\t^ self multiComposeLinesFrom: firstCharacterIndex to: text size delta: 0\\n\\t\\tinto: OrderedCollection new priorLines: Array new atY: container top.\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 11/15/97 09:21'!\\ncomposeAllStartingAt: characterIndex\\n\\tfirstCharacterIndex _ characterIndex.\\n\\toffsetToEnd _ text size - firstCharacterIndex.\\n\\tself composeAll! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 5/7/2001 10:58'!\\ncomposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult |\\n\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\t^maxRightX\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'di 10/22/97 11:13'!\\ncompositionRectangle\\n\\t^ container! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 2/25/2001 15:02'!\\nfixLastWithHeight: lineHeightGuess\\n\\\"This awful bit is to ensure that if we have scanned all the text and the last character is a CR that there is a null line at the end of lines. Sometimes this was not happening which caused anomalous selections when selecting all the text. This is implemented as a post-composition fixup because I coul;dn't figure out where to put it in the main logic.\\\"\\n\\n\\t| oldLastLine newRectangle line |\\n\\n\\t(text size > 1 and: [text last = Character cr]) ifFalse: [^self].\\n\\n\\toldLastLine _ lines last.\\n\\toldLastLine last - oldLastLine first >= 0 ifFalse: [^self].\\n\\toldLastLine last = text size ifFalse: [^self].\\n\\n\\tnewRectangle _ oldLastLine left @ oldLastLine bottom \\n\\t\\t\\t\\textent: 0@(oldLastLine bottom - oldLastLine top).\\n\\t\\\"Even though we may be below the bottom of the container,\\n\\tit is still necessary to compose the last line for consistency...\\\"\\n\\n\\tline _ TextLine start: text size+1 stop: text size internalSpaces: 0 paddingWidth: 0.\\n\\tline rectangle: newRectangle.\\n\\tline lineHeight: lineHeightGuess baseline: textStyle baseline.\\n\\tlines _ lines, (Array with: line).\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 1/3/2003 12:17'!\\nmultiComposeLinesFrom: start to: stop delta: delta into: lineColl priorLines: priorLines\\n\\tatY: startingY\\n\\t\\\"While the section from start to stop has changed, composition may ripple all the way to the end of the text. However in a rectangular container, if we ever find a line beginning with the same character as before (ie corresponding to delta in the old lines), then we can just copy the old lines from there to the end of the container, with adjusted indices and y-values\\\"\\n\\n\\t| newResult |\\n\\n\\tnewResult _ MultiTextComposer new\\n\\t\\tmultiComposeLinesFrom: start \\n\\t\\tto: stop \\n\\t\\tdelta: delta \\n\\t\\tinto: lineColl \\n\\t\\tpriorLines: priorLines\\n\\t\\tatY: startingY\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: wantsColumnBreaks == true.\\n\\tlines _ newResult first asArray.\\n\\tmaxRightX _ newResult second.\\n\\t\\\"maxRightX printString displayAt: 0@0.\\\"\\n\\t^maxRightX\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/20/2002 16:18'!\\nrecomposeFrom: start to: stop delta: delta\\n\\t\\\"Recompose this paragraph. The altered portion is between start and stop.\\n\\tRecomposition may continue to the end of the text, due to a ripple effect.\\n\\tDelta is the amount by which the current text is longer than it was\\n\\twhen its current lines were composed.\\\"\\n\\t| startLine newLines |\\n\\t\\\"Have to recompose line above in case a word-break was affected.\\\"\\n\\tstartLine _ (self lineIndexForCharacter: start) - 1 max: 1.\\n\\t[startLine > 1 and: [(lines at: startLine-1) top = (lines at: startLine) top]]\\n\\t\\twhileTrue: [startLine _ startLine - 1]. \\\"Find leftmost of line pieces\\\"\\n\\tnewLines _ OrderedCollection new: lines size + 1.\\n\\t1 to: startLine-1 do: [:i | newLines addLast: (lines at: i)].\\n\\ttext string isOctetString ifTrue: [\\n\\t\\t^ self composeLinesFrom: (lines at: startLine) first to: stop delta: delta\\n\\t\\t\\tinto: newLines priorLines: lines\\n\\t\\t\\tatY: (lines at: startLine) top.\\n\\t].\\n\\tself multiComposeLinesFrom: (lines at: startLine) first to: stop delta: delta\\n\\t\\tinto: newLines priorLines: lines\\n\\t\\tatY: (lines at: startLine) top.\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'RAA 5/6/2001 15:09'!\\ntestNewComposeAll\\n\\t| newResult |\\n\\tself \\n\\t\\tOLDcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top.\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: false.\\n\\tnewResult first with: lines do: [ :e1 :e2 |\\n\\t\\te1 longPrintString = e2 longPrintString ifFalse: [self halt].\\n\\t].\\n\\tnewResult second = maxRightX ifFalse: [self halt].\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/17/2002 14:48'!\\ntestNewComposeAll2\\n\\t| newResult |\\n\\tnewResult _ TextComposer new\\n\\t\\tcomposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: container\\n\\t\\twantsColumnBreaks: false.\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n!NewParagraph methodsFor: 'composition' stamp: 'yo 12/18/2002 15:00'!\\ntestNewComposeAll3\\n\\t| newResult |\\n\\tnewResult _ TextComposer new\\n\\t\\tmultiComposeLinesFrom: firstCharacterIndex \\n\\t\\tto: text size \\n\\t\\tdelta: 0\\n\\t\\tinto: OrderedCollection new \\n\\t\\tpriorLines: Array new \\n\\t\\tatY: container top\\n\\t\\ttextStyle: textStyle \\n\\t\\ttext: text \\n\\t\\tcontainer: (0@0 extent: 31@60)\\n\\t\\twantsColumnBreaks: false.\\n\\t^{newResult. {lines. maxRightX}}\\n! !\\n\\n\\n!NewParagraph methodsFor: 'copying' stamp: 'di 5/21/1998 21:45'!\\ndeepCopy\\n\\t\\\"Don't want to copy the container (etc) or fonts in the TextStyle.\\\"\\n\\t| new |\\n\\tnew _ self copy.\\n\\tnew textStyle: textStyle copy\\n\\t\\tlines: lines copy\\n\\t\\ttext: text deepCopy.\\n\\t^ new! !\\n\\n\\n!NewParagraph methodsFor: 'display' stamp: 'di 8/13/2000 12:27'!\\nasParagraphForPostscript\\n\\n\\t^ self! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'lr 7/12/2006 09:27'!\\ncaretWidth\\n\\t^ Preferences caretWidth! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'nk 8/31/2004 11:10'!\\ndisplaySelectionInLine: line on: aCanvas \\n\\t| leftX rightX w caretColor |\\n\\tselectionStart ifNil: [^self].\\t\\\"No selection\\\"\\n\\taCanvas isShadowDrawing ifTrue: [ ^self ].\\t\\\"don't draw selection with shadow\\\"\\n\\tselectionStart = selectionStop \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Only show caret on line where clicked\\\"\\n\\n\\t\\t\\tselectionStart textLine ~= line ifTrue: [^self]]\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Test entire selection before or after here\\\"\\n\\n\\t\\t\\t(selectionStop stringIndex < line first \\n\\t\\t\\t\\tor: [selectionStart stringIndex > (line last + 1)]) ifTrue: [^self].\\t\\\"No selection on this line\\\"\\n\\t\\t\\t(selectionStop stringIndex = line first \\n\\t\\t\\t\\tand: [selectionStop textLine ~= line]) ifTrue: [^self].\\t\\\"Selection ends on line above\\\"\\n\\t\\t\\t(selectionStart stringIndex = (line last + 1) \\n\\t\\t\\t\\tand: [selectionStop textLine ~= line]) ifTrue: [^self]].\\t\\\"Selection begins on line below\\\"\\n\\tleftX := (selectionStart stringIndex < line first \\n\\t\\t\\t\\tifTrue: [line ]\\n\\t\\t\\t\\tifFalse: [selectionStart ])left.\\n\\trightX := (selectionStop stringIndex > (line last + 1) or: \\n\\t\\t\\t\\t\\t[selectionStop stringIndex = (line last + 1) \\n\\t\\t\\t\\t\\t\\tand: [selectionStop textLine ~= line]]) \\n\\t\\t\\t\\tifTrue: [line right]\\n\\t\\t\\t\\tifFalse: [selectionStop left].\\n\\tselectionStart = selectionStop \\n\\t\\tifTrue: \\n\\t\\t\\t[rightX := rightX + 1.\\n\\t\\t\\tw := self caretWidth.\\n\\t\\t\\tcaretColor := self insertionPointColor.\\n\\t\\t\\t1 to: w\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\t\\\"Draw caret triangles at top and bottom\\\"\\n\\n\\t\\t\\t\\t\\taCanvas fillRectangle: ((leftX - w + i - 1) @ (line top + i - 1) \\n\\t\\t\\t\\t\\t\\t\\t\\textent: ((w - i) * 2 + 3) @ 1)\\n\\t\\t\\t\\t\\t\\tcolor: caretColor.\\n\\t\\t\\t\\t\\taCanvas fillRectangle: ((leftX - w + i - 1) @ (line bottom - i) \\n\\t\\t\\t\\t\\t\\t\\t\\textent: ((w - i) * 2 + 3) @ 1)\\n\\t\\t\\t\\t\\t\\tcolor: caretColor].\\n\\t\\t\\taCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom)\\n\\t\\t\\t\\tcolor: caretColor]\\n\\t\\tifFalse: \\n\\t\\t\\t[aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom)\\n\\t\\t\\t\\tcolor: self selectionColor]! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'rr 3/22/2004 19:56'!\\ninsertionPointColor\\n\\tself focused ifFalse: [^ Color transparent].\\n\\t^ Display depth <= 2\\n\\t\\tifTrue: [Color black]\\n\\t\\tifFalse: [Preferences insertionPointColor]! !\\n\\n!NewParagraph methodsFor: 'display' stamp: 'rr 3/23/2004 19:52'!\\nselectionColor\\n\\t| color |\\n\\tDisplay depth = 1 ifTrue: [^ Color veryLightGray].\\n\\tDisplay depth = 2 ifTrue: [^ Color gray].\\n\\tcolor := Preferences textHighlightColor.\\n\\tself focused ifFalse: [color := color alphaMixed: 0.2 with: Color veryVeryLightGray].\\n\\t^ color! !\\n\\n\\n!NewParagraph methodsFor: 'editing' stamp: 'mk 5/28/2005 11:15'!\\nclickAt: clickPoint for: model controller: editor\\n\\t\\\"Give sensitive text a chance to fire. Display flash: (100@100 extent: 100@100).\\\"\\n\\t| startBlock action target range boxes box |\\n\\taction _ false.\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\t(text attributesAt: startBlock stringIndex forStyle: textStyle) \\n\\t\\tdo: [:att | att mayActOnClick ifTrue:\\n\\t\\t\\t\\t[(target _ model) ifNil: [target _ editor morph].\\n\\t\\t\\t\\trange _ text rangeOf: att startingAt: startBlock stringIndex.\\n\\t\\t\\t\\tboxes _ self selectionRectsFrom: (self characterBlockForIndex: range first) \\n\\t\\t\\t\\t\\t\\t\\tto: (self characterBlockForIndex: range last+1).\\n\\t\\t\\t\\tbox _ boxes detect: [:each | each containsPoint: clickPoint] ifNone: [nil].\\n\\t\\t\\t\\tbox ifNotNil:\\n\\t\\t\\t\\t\\t[ box _ (editor transformFrom: nil) invertBoundsRect: box.\\n\\t\\t\\t\\t\\teditor morph allOwnersDo: [ :m | box _ box intersect: (m boundsInWorld) ].\\n\\t\\t\\t\\t\\tUtilities awaitMouseUpIn: box\\n\\t\\t\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\t\\t\\tifSucceed: [(att actOnClickFor: target in: self at: clickPoint editor: editor) ifTrue: [action _ true]].\\n\\t\\t\\t\\t\\tCursor currentCursor == Cursor webLink ifTrue:[Cursor normal show].\\n\\t\\t\\t\\t]]].\\n\\t^ action! !\\n\\n!NewParagraph methodsFor: 'editing' stamp: 'di 4/28/1999 10:14'!\\nreplaceFrom: start to: stop with: aText displaying: displayBoolean \\n\\t\\\"Edit the text, and then recompose the lines.\\\" \\n\\ttext replaceFrom: start to: stop with: aText.\\n\\tself recomposeFrom: start to: start + aText size - 1 delta: aText size - (stop-start+1)! !\\n\\n\\n!NewParagraph methodsFor: 'fonts-display' stamp: 'nk 3/20/2004 11:13'!\\ndisplayOn: aCanvas using: displayScanner at: somePosition\\n\\t\\\"Send all visible lines to the displayScanner for display\\\"\\n\\t| visibleRectangle offset leftInRun line |\\n\\tvisibleRectangle _ aCanvas clipRect.\\n\\toffset _ (somePosition - positionWhenComposed) truncated.\\n\\tleftInRun _ 0.\\n\\t(self lineIndexForPoint: visibleRectangle topLeft)\\n\\t\\tto: (self lineIndexForPoint: visibleRectangle bottomRight)\\n\\t\\tdo: [:i | line _ lines at: i.\\n\\t\\t\\tself displaySelectionInLine: line on: aCanvas.\\n\\t\\t\\tline first <= line last ifTrue:\\n\\t\\t\\t\\t[leftInRun _ displayScanner displayLine: line\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offset leftInRun: leftInRun]].\\n! !\\n\\n\\n!NewParagraph methodsFor: 'initialize-release' stamp: 'tak 12/21/2004 13:29'!\\ninitialize\\n\\tself positionWhenComposed: 0 @ 0! !\\n\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ar 4/12/2005 19:53'!\\ncharacterBlockAtPoint: aPoint \\n\\t\\\"Answer a CharacterBlock for the character in the text at aPoint.\\\"\\n\\t| line |\\n\\tline _ lines at: (self lineIndexForPoint: aPoint).\\n\\t^ ((text string isWideString) ifTrue: [\\n\\t\\tMultiCharacterBlockScanner new text: text textStyle: textStyle\\n\\t] ifFalse: [CharacterBlockScanner new text: text textStyle: textStyle])\\n\\t\\tcharacterBlockAtPoint: aPoint index: nil\\n\\t\\tin: line! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ar 4/12/2005 19:53'!\\ncharacterBlockForIndex: index \\n\\t\\\"Answer a CharacterBlock for the character in text at index.\\\"\\n\\t| line |\\n\\tline _ lines at: (self lineIndexForCharacter: index).\\n\\t^ ((text string isWideString) ifTrue: [\\n\\t\\tMultiCharacterBlockScanner new text: text textStyle: textStyle\\n\\t] ifFalse: [\\n\\t\\tCharacterBlockScanner new text: text textStyle: textStyle\\n\\t])\\n\\t\\tcharacterBlockAtPoint: nil index: ((index max: line first) min: text size+1)\\n\\t\\tin: line! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'jm 11/19/97 22:56'!\\ncontainsPoint: aPoint\\n\\t^ (lines at: (self lineIndexForPoint: aPoint)) rectangle\\n\\t\\tcontainsPoint: aPoint! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 10/5/1998 12:59'!\\ndefaultCharacterBlock\\n\\t^ (CharacterBlock new stringIndex: firstCharacterIndex text: text\\n\\t\\t\\ttopLeft: lines first topLeft extent: 0 @ 0)\\n\\t\\ttextLine: lines first! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 11/30/97 12:10'!\\nselectionRects\\n\\t\\\"Return an array of rectangles representing the selection region.\\\"\\n\\tselectionStart ifNil: [^ Array new].\\n\\t^ self selectionRectsFrom: selectionStart to: selectionStop! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'ls 11/2/2001 23:10'!\\nselectionRectsFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Return an array of rectangles representing the area between the two character blocks given as arguments.\\\"\\n\\t| line1 line2 rects cb1 cb2 w |\\n\\tcharacterBlock1 <= characterBlock2\\n\\t\\tifTrue: [cb1 _ characterBlock1. cb2 _ characterBlock2]\\n\\t\\tifFalse: [cb2 _ characterBlock1. cb1 _ characterBlock2].\\n\\tcb1 = cb2 ifTrue:\\n\\t\\t[w _ self caretWidth.\\n\\t\\t^ Array with: (cb1 topLeft - (w@0) corner: cb1 bottomLeft + ((w+1)@0))].\\n\\tline1 _ self lineIndexForCharacter: cb1 stringIndex.\\n\\tline2 _ self lineIndexForCharacter: cb2 stringIndex.\\n\\tline1 = line2 ifTrue:\\n\\t\\t[^ Array with: (cb1 topLeft corner: cb2 bottomRight)].\\n\\trects _ OrderedCollection new.\\n\\trects addLast: (cb1 topLeft corner: (lines at: line1) bottomRight).\\n\\tline1+1 to: line2-1 do: [ :i |\\n\\t\\t| line |\\n\\t\\tline := lines at: i.\\n\\t\\t(line left = rects last left and: [ line right = rects last right ])\\n\\t\\t\\tifTrue: [ \\\"new line has same margins as old one -- merge them, so that the caller gets as few rectangles as possible\\\"\\n\\t\\t\\t\\t\\t| lastRect |\\n\\t\\t\\t\\t\\tlastRect := rects removeLast.\\n\\t\\t\\t\\t\\trects add: (lastRect bottom: line bottom) ]\\n\\t\\t\\tifFalse: [ \\\"differing margins; cannot merge\\\"\\n\\t\\t\\t\\t\\trects add: line rectangle ] ].\\n\\n\\trects addLast: ((lines at: line2) topLeft corner: cb2 bottomLeft).\\n\\t^ rects! !\\n\\n!NewParagraph methodsFor: 'selection' stamp: 'di 12/2/97 19:57'!\\nselectionStart: startBlock selectionStop: stopBlock\\n\\tselectionStart _ startBlock.\\n\\tselectionStop _ stopBlock.! !\\n\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 11/8/97 15:47'!\\nadjustLineIndicesBy: delta\\n\\tfirstCharacterIndex _ firstCharacterIndex + delta.\\n\\tlines do: [:line | line slide: delta].\\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/26/97 15:57'!\\nadjustRightX\\n\\t| shrink |\\n\\tshrink _ container right - maxRightX.\\n\\tlines do: [:line | line paddingWidth: (line paddingWidth - shrink)].\\n\\tcontainer _ container withRight: maxRightX! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:17'!\\nfastFindFirstLineSuchThat: lineBlock\\n\\t\\\"Perform a binary search of the lines array and return the index\\n\\tof the first element for which lineBlock evaluates as true.\\n\\tThis assumes the condition is one that goes from false to true for\\n\\tincreasing line numbers (as, eg, yval > somey or start char > somex).\\n\\tIf lineBlock is not true for any element, return size+1.\\\"\\n\\t| index low high |\\n\\tlow _ 1.\\n\\thigh _ lines size.\\n\\t[index _ high + low // 2.\\n\\tlow > high]\\n\\t\\twhileFalse: \\n\\t\\t\\t[(lineBlock value: (lines at: index))\\n\\t\\t\\t\\tifTrue: [high _ index - 1]\\n\\t\\t\\t\\tifFalse: [low _ index + 1]].\\n\\t^ low! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'RAA 8/30/1998 15:30'!\\nindentationOfLineIndex: lineIndex ifBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the line at lineIndex. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\n\\t If the line is word-wrap overflow, back up a line and recur.\\\"\\n\\n\\t| arrayIndex first last cr |\\n\\tcr _ Character cr.\\n\\tarrayIndex _ lineIndex.\\n\\t[first _ (lines at: arrayIndex) first.\\n\\t first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: \\\"word wrap\\\"\\n\\t\\t[arrayIndex _ arrayIndex - 1].\\n\\tlast _ (lines at: arrayIndex) last.\\n\\t\\n\\t^(text string copyFrom: first to: last) indentationIfBlank: aBlock.\\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:11'!\\nlineIndexForCharacter: index\\n\\t\\\"Answer the index of the line in which to select the character at index.\\\"\\n\\t^ (self fastFindFirstLineSuchThat: [:line | line first > index]) - 1 max: 1! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 4/14/98 13:13'!\\nlineIndexForPoint: aPoint\\n\\t\\\"Answer the index of the line in which to select the character nearest to aPoint.\\\"\\n\\t| i py |\\n\\tpy _ aPoint y truncated.\\n\\n\\t\\\"Find the first line at this y-value\\\"\\n\\ti _ (self fastFindFirstLineSuchThat: [:line | line bottom > py]) min: lines size.\\n\\n\\t\\\"Now find the first line at this x-value\\\"\\n\\t[i < lines size and: [(lines at: i+1) top = (lines at: i) top\\n\\t\\t\\t\\tand: [aPoint x >= (lines at: i+1) left]]]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\t^ i! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'RAA 8/30/1998 15:04'!\\nlineIndexOfCharacterIndex: characterIndex \\n\\t\\\"Answer the line index for a given characterIndex.\\\"\\n\\t\\\"apparently the selector changed with NewParagraph\\\"\\n\\n\\t^self lineIndexForCharacter: characterIndex \\n! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/24/97 17:40'!\\nlines\\n\\t^ lines! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'edc 6/18/2004 09:10'!\\nmoveBy: delta\\n\\tlines do: [:line | line moveBy: delta].\\n\\tpositionWhenComposed ifNotNil:[\\n\\tpositionWhenComposed _ positionWhenComposed + delta].\\n\\tcontainer _ container translateBy: delta! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 10/21/97 21:36'!\\npositionWhenComposed: pos\\n\\tpositionWhenComposed _ pos! !\\n\\n!NewParagraph methodsFor: 'private' stamp: 'di 5/21/1998 21:47'!\\ntextStyle: ts lines: l text: t\\n\\t\\\"Private -- just a service for deepCopy\\\"\\n\\ttextStyle _ ts.\\n\\tlines _ l.\\n\\ttext _ t.! !\\nSystemWindow subclass: #NewWorldWindow\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-AdditionalWorlds'!\\n\\n!NewWorldWindow methodsFor: 'color' stamp: 'nb 6/17/2003 12:25'!\\nsetWindowColor: incomingColor\\n\\t| existingColor aColor |\\n\\n\\tincomingColor ifNil: [^ self]. \\\"it happens\\\"\\n\\taColor _ incomingColor asNontranslucentColor.\\n\\t(aColor = ColorPickerMorph perniciousBorderColor \\n\\t\\tor: [aColor = Color black]) ifTrue: [^ self].\\n\\texistingColor _ self paneColorToUse.\\n\\texistingColor ifNil: [^ Beeper beep].\\n\\tself setStripeColorsFrom: aColor\\n\\t\\t\\n! !\\n\\n\\n!NewWorldWindow methodsFor: 'initialization' stamp: 'ar 5/11/2001 23:48'!\\nopenInWorld: aWorld\\n\\t| xxx |\\n\\t\\\"This msg and its callees result in the window being activeOnlyOnTop\\\"\\n\\n\\txxx _ RealEstateAgent initialFrameFor: self world: aWorld.\\n\\n\\t\\\"Bob say: 'opening in ',xxx printString,' out of ',aWorld bounds printString.\\n\\t6 timesRepeat: [Display flash: xxx andWait: 300].\\\"\\n\\n\\tself bounds: xxx.\\n\\t^self openAsIsIn: aWorld.! !\\n\\n\\n!NewWorldWindow methodsFor: 'label' stamp: 'sw 5/19/2001 10:44'!\\nsetStripeColorsFrom: paneColor\\n\\t\\\"Since our world may be *any* color, try to avoid really dark colors so title will show\\\"\\n\\n\\t| revisedColor |\\n\\tstripes ifNil: [^ self].\\n\\trevisedColor _ paneColor atLeastAsLuminentAs: 0.1 .\\n\\tself isActive ifTrue:\\n\\t\\t[stripes second \\n\\t\\t\\tcolor: revisedColor; \\n\\t\\t\\tborderColor: stripes second color darker.\\n\\t\\tstripes first \\n\\t\\t\\tcolor: stripes second borderColor darker;\\n\\t\\t\\tborderColor: stripes first color darker.\\n\\t\\t^ self].\\n\\t\\\"This could be much faster\\\"\\n\\tstripes second \\n\\t\\tcolor: revisedColor; \\n\\t\\tborderColor: revisedColor.\\n\\tstripes first \\n\\t\\tcolor: revisedColor; \\n\\t\\tborderColor: revisedColor! !\\n\\n\\n!NewWorldWindow methodsFor: 'panes' stamp: 'ar 11/9/2000 01:31'!\\naddMorph: aMorph frame: relFrame\\n\\t| cc |\\n\\tcc _ aMorph color.\\n\\tsuper addMorph: aMorph frame: relFrame.\\n\\taMorph color: cc.! !\\n\\n!NewWorldWindow methodsFor: 'panes' stamp: 'RAA 6/1/2000 18:21'!\\nupdatePaneColors\\n\\t\\\"Useful when changing from monochrome to color display\\\"\\n\\n\\tself setStripeColorsFrom: self paneColorToUse.\\n\\n\\t\\\"paneMorphs do: [:p | p color: self paneColorToUse].\\\"\\t\\\"since pane is a world, skip this\\\"\\n! !\\n\\n\\n!NewWorldWindow methodsFor: 'stepping' stamp: 'RAA 6/1/2000 18:30'!\\namendSteppingStatus! !\\n\\n\\n!NewWorldWindow methodsFor: 'testing' stamp: 'RAA 6/1/2000 18:33'!\\nwantsSteps\\n\\t\\n\\t^true! !\\nController subclass: #NoController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Framework'!\\n!NoController commentStamp: '<historical>' prior: 0!\\nI represent a controller that never wants control. I am the controller for views that are non-interactive.!\\n\\n\\n!NoController methodsFor: 'basic control sequence'!\\nstartUp\\n\\t\\\"I do nothing.\\\"\\n\\n\\t^self! !\\n\\n\\n!NoController methodsFor: 'control defaults'!\\nisControlActive \\n\\t\\\"Refer to the comment in Controller|isControlActive.\\\"\\n\\n\\t^false! !\\n\\n!NoController methodsFor: 'control defaults'!\\nisControlWanted \\n\\t\\\"Refer to the comment in Controller|isControlWanted.\\\"\\n\\n\\t^false! !\\nClipboardInterpreter subclass: #NoConversionClipboardInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!NoConversionClipboardInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 8/11/2003 19:03'!\\nfromSystemClipboard: aString\\n\\n\\t^ aString.\\n! !\\n\\n!NoConversionClipboardInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 8/11/2003 21:06'!\\ntoSystemClipboard: aString\\n\\n\\t| result |\\n\\taString isOctetString ifTrue: [^ aString asOctetString].\\n\\n\\tresult _ WriteStream on: (String new: aString size).\\n\\taString do: [:each | each value < 256 ifTrue: [result nextPut: each]].\\n\\t^ result contents.\\n! !\\nKeyboardInputInterpreter subclass: #NoInputInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!NoInputInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 7/25/2003 14:59'!\\nnextCharFrom: sensor firstEvt: evtBuf\\n\\n\\n\\n\\t| keyValue |\\n\\n\\tkeyValue := evtBuf third.\\n\\n\\t^ keyValue asCharacter.\\n\\n! !\\nNetworkError subclass: #NoNetworkError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!NoNetworkError commentStamp: 'mir 5/12/2003 18:17' prior: 0!\\nSignals that no network was found. This could happen, e.g., on dial-up connection when no connection was established when Squeak tried to access it.\\n\\n!\\n\\nError subclass: #NonBooleanReceiver\\n\\tinstanceVariableNames: 'object'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n\\n!NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'!\\nobject\\n\\t^object! !\\n\\n!NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'!\\nobject: anObject\\n\\tobject _ anObject! !\\n\\n\\n!NonBooleanReceiver methodsFor: 'signaledException' stamp: 'hmm 7/29/2001 21:37'!\\nisResumable\\n\\n\\t^true! !\\nAbstractScoreEvent subclass: #NoteEvent\\n\\tinstanceVariableNames: 'duration midiKey velocity channel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Scores'!\\n!NoteEvent commentStamp: '<historical>' prior: 0!\\nRepresents a note on or off event in a MIDI score.\\n!\\n\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/30/97 22:02'!\\nchannel\\n\\n\\t^ channel\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nchannel: midiChannel\\n\\n\\tchannel := midiChannel.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/18/97 19:10'!\\nduration\\n\\n\\t^ duration\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nduration: aNumber\\n\\n\\tduration := aNumber.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 8/27/1998 16:38'!\\nendTime\\n\\n\\t^ time + duration\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nkey: midiKeyNum velocity: midiVelocity channel: midiChannel\\n\\n\\tmidiKey := midiKeyNum.\\n\\tvelocity := midiVelocity.\\n\\tchannel := midiChannel.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/18/97 20:58'!\\nmidiKey\\n\\n\\t^ midiKey\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmidiKey: midiKeyNum\\n\\n\\tmidiKey := midiKeyNum.\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 8/3/1998 17:06'!\\npitch\\n\\t\\\"Convert my MIDI key number to a pitch and return it.\\\"\\n\\n\\t^ AbstractSound pitchForMIDIKey: midiKey\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'jm 12/30/97 09:32'!\\nvelocity\\n\\n\\t^ velocity\\n! !\\n\\n!NoteEvent methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nvelocity: midiVelocity\\n\\n\\tvelocity := midiVelocity.\\n! !\\n\\n\\n!NoteEvent methodsFor: 'classification' stamp: 'jm 12/31/97 11:48'!\\nisNoteEvent\\n\\n\\t^ true\\n! !\\n\\n\\n!NoteEvent methodsFor: 'midi' stamp: 'jm 9/10/1998 15:58'!\\nendNoteOnMidiPort: aMidiPort\\n\\t\\\"Output a noteOff event to the given MIDI port. (Actually, output a noteOff event with zero velocity. This does the same thing, but allows running status to be used when sending a mixture of note on and off commands.)\\\"\\n\\n\\taMidiPort\\n\\t\\tmidiCmd: 16r90\\n\\t\\tchannel: channel\\n\\t\\tbyte: midiKey\\n\\t\\tbyte: 0.\\n! !\\n\\n!NoteEvent methodsFor: 'midi' stamp: 'jm 9/10/1998 15:56'!\\nstartNoteOnMidiPort: aMidiPort\\n\\t\\\"Output a noteOn event to the given MIDI port.\\\"\\n\\n\\taMidiPort\\n\\t\\tmidiCmd: 16r90\\n\\t\\tchannel: channel\\n\\t\\tbyte: midiKey\\n\\t\\tbyte: velocity.\\n! !\\n\\n\\n!NoteEvent methodsFor: 'printing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nkeyName\\n\\t\\\"Return a note name for my pitch.\\\"\\n\\n\\t| pitchName octave |\\n\\tpitchName := #(c cs d ef e f fs g af a bf b) at: (midiKey \\\\\\\\ 12) + 1.\\n\\toctave := (#(-1 0 1 2 3 4 5 6 7 8 9) at: (midiKey // 12) + 1) printString.\\n\\t^ pitchName, octave\\n! !\\n\\n!NoteEvent methodsFor: 'printing' stamp: 'jm 1/3/98 08:59'!\\nprintOn: aStream\\n\\n\\taStream nextPut: $(.\\n\\ttime printOn: aStream.\\n\\taStream nextPutAll: ': '.\\n\\taStream nextPutAll: self keyName.\\n\\taStream space.\\n\\tduration printOn: aStream.\\n\\taStream nextPut: $).\\n! !\\nException subclass: #Notification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n!Notification commentStamp: '<historical>' prior: 0!\\nA Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect.!\\n\\n\\n!Notification methodsFor: 'exceptionDescription' stamp: 'pnm 8/16/2000 15:04'!\\ndefaultAction\\n\\t\\\"No action is taken. The value nil is returned as the value of the message that signaled the exception.\\\"\\n\\n\\t^nil! !\\n\\n!Notification methodsFor: 'exceptionDescription' stamp: 'tfei 6/4/1999 18:17'!\\nisResumable\\n\\t\\\"Answer true. Notification exceptions by default are specified to be resumable.\\\"\\n\\n\\t^true! !\\nPluggableCanvas subclass: #NullCanvas\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n!NullCanvas commentStamp: '<historical>' prior: 0!\\nA canvas which ignores all drawing commands.!\\n\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:11'!\\nclipRect\\n\\t^1@1 extent: 99@99! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:11'!\\nextent\\n\\t^100@100! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:12'!\\nform\\n\\t^Form extent: self extent! !\\n\\n!NullCanvas methodsFor: 'accessing' stamp: 'ls 3/20/2000 21:13'!\\norigin\\n\\t^0@0! !\\n\\n\\n!NullCanvas methodsFor: 'copying' stamp: 'ls 3/20/2000 21:26'!\\ncopyClipRect: clipRect\\n\\t\\\"who cares what the clipping rectangle is?\\\"\\n\\t^self! !\\n\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:41'!\\nclipBy: region during: aBlock\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:39'!\\ntransformBy: aDisplayTransform clippingTo: aClipRect during: aBlock smoothing: cellSize\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\n\\n!NullCanvas methodsFor: 'drawing-support' stamp: 'ls 3/27/2000 21:40'!\\ntranslateBy: delta during: aBlock\\n\\t\\\"do this in order that timing runs work better\\\"\\n\\taBlock value: self! !\\nObject subclass: #NullEncoder\\n\\tinstanceVariableNames: 'target filterSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Support'!\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'RAA 9/17/2000 11:53'!\\nclose\\n\\n\\t^target close.\\n! !\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'MPW 1/1/1901 00:56'!\\ncontents\\n\\t^target contents.\\n! !\\n\\n!NullEncoder methodsFor: 'accessing' stamp: 'MPW 1/1/1901 00:16'!\\ntarget\\n\\t^target.! !\\n\\n\\n!NullEncoder methodsFor: 'initialization' stamp: 'MPW 1/1/1901 00:04'!\\ninitWithTarget:aTarget\\n\\ttarget _ aTarget.\\n\\tfilterSelector _ self class filterSelector.\\n\\t^self.\\n! !\\n\\n\\n!NullEncoder methodsFor: 'processing' stamp: 'MPW 1/1/1901 01:19'!\\nprocess:anObject\\n\\tself write:anObject.\\n\\t^self contents.! !\\n\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'MPW 1/1/1901 01:17'!\\nforward:anObject\\n\\tanObject ~= nil ifTrue:[target write:anObject].\\n! !\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'mpw 8/13/1999 10:54'!\\nwrite:anObject\\n\\tfilterSelector ifNil:[filterSelector_self class filterSelector].\\n\\tanObject ifNotNil: [anObject perform:filterSelector with:self].\\n! !\\n\\n!NullEncoder methodsFor: 'writing' stamp: 'MPW 1/1/1901 01:16'!\\nwriteObject:anObject\\n\\t^self forward:anObject.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNullEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!NullEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 00:02'!\\ndefaultTarget\\n\\t^OrderedCollection new.\\n! !\\n\\n!NullEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 00:02'!\\nfilterSelector\\n\\t^#writeOnFilterStream:\\n! !\\n\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 00:55'!\\nstream\\n\\t^self streamOn:self defaultTarget. \\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 00:05'!\\nstream:newTarget\\n\\t^self new initWithTarget:newTarget.\\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 01:15'!\\nstreamOn:newTargetCollection\\n\\t^self new initWithTarget:newTargetCollection.\\n! !\\n\\n!NullEncoder class methodsFor: 'creation' stamp: 'MPW 1/1/1901 02:20'!\\nstreamOnFile:fileName\\n\\t^self new initWithTarget:(FileStream newFileNamed: fileName).\\n! !\\n\\n\\n!NullEncoder class methodsFor: 'processing' stamp: 'MPW 1/1/1901 01:20'!\\nprocess:anObject\\n\\t^self stream process:anObject.\\n\\n! !\\nNetworkTerminalMorph subclass: #NullTerminalMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Morphic-Remote'!\\n\\n!NullTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/22/2000 07:20'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds fillStyle: Color orange.\\n\\taCanvas frameRectangle: self bounds color: Color black! !\\n\\n!NullTerminalMorph methodsFor: 'drawing' stamp: 'RAA 7/22/2000 07:22'!\\nforceToFront: aRegion\\n\\t\\\"force the given region from the drawing form onto the background form\\\"\\n\\tself updateBackgroundForm.\\n\\n! !\\n\\n\\n!NullTerminalMorph methodsFor: 'geometry' stamp: 'sd 11/20/2005 21:26'!\\nextent: newExtent\\n\\n\\t| aPoint |\\n\\taPoint := 50@50.\\n\\tbounds extent = aPoint ifFalse: [\\n\\t\\tself changed.\\n\\t\\tbounds := bounds topLeft extent: aPoint.\\n\\t\\tself layoutChanged.\\n\\t\\tself changed\\n\\t].\\n\\teventEncoder sendViewExtent: newExtent! !\\nMagnitude subclass: #Number\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Numbers'!\\n!Number commentStamp: '<historical>' prior: 0!\\nClass Number holds the most general methods for dealing with numbers. Subclasses Float, Fraction, and Integer, and their subclasses, provide concrete representations of a numeric quantity.\\n\\nAll of Number's subclasses participate in a simple type coercion mechanism that supports mixed-mode arithmetic and comparisons. It works as follows: If\\n\\tself<typeA> op: arg<typeB>\\nfails because of incompatible types, then it is retried in the following guise:\\n\\t(arg adaptTypeA: self) op: arg adaptToTypeA.\\nThis gives the arg of typeB an opportunity to resolve the incompatibility, knowing exactly what two types are involved. If self is more general, then arg will be converted, and viceVersa. This mechanism is extensible to any new number classes that one might wish to add to Squeak. The only requirement is that every subclass of Number must support a pair of conversion methods specific to each of the other subclasses of Number.!\\n\\n\\n!Number methodsFor: 'arithmetic'!\\n* aNumber \\n\\t\\\"Answer the result of multiplying the receiver by aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n+ aNumber \\n\\t\\\"Answer the sum of the receiver and aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n- aNumber \\n\\t\\\"Answer the difference between the receiver and aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n/ aNumber \\n\\t\\\"Answer the result of dividing the receiver by aNumber.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Number methodsFor: 'arithmetic'!\\n// aNumber \\n\\t\\\"Integer quotient defined by division with truncation toward negative \\n\\tinfinity. 9//4 = 2, -9//4 = -3. -0.9//0.4 = -3. \\\\\\\\ answers the remainder \\n\\tfrom this division.\\\"\\n\\n\\t^(self / aNumber) floor! !\\n\\n!Number methodsFor: 'arithmetic'!\\n\\\\\\\\ aNumber \\n\\t\\\"modulo. Remainder defined in terms of //. Answer a Number with the \\n\\tsame sign as aNumber. e.g. 9\\\\\\\\4 = 1, -9\\\\\\\\4 = 3, 9\\\\\\\\-4 = -3, 0.9\\\\\\\\0.4 = 0.1.\\\"\\n\\n\\t^self - (self // aNumber * aNumber)! !\\n\\n!Number methodsFor: 'arithmetic'!\\nabs\\n\\t\\\"Answer a Number that is the absolute value (positive magnitude) of the \\n\\treceiver.\\\"\\n\\n\\tself < 0\\n\\t\\tifTrue: [^self negated]\\n\\t\\tifFalse: [^self]! !\\n\\n!Number methodsFor: 'arithmetic' stamp: 'mk 10/27/2003 21:00'!\\narg\\n\\t\\\"Answer the argument of the receiver (see Complex | arg).\\\"\\n\\t\\n\\tself isZero ifTrue: [self error: 'Zero (0 + 0 i) does not have an argument.'].\\n\\t0 < self\\n\\t\\tifTrue: [^ 0]\\n\\t\\tifFalse: [^ Float pi]! !\\n\\n!Number methodsFor: 'arithmetic'!\\nnegated\\n\\t\\\"Answer a Number that is the negation of the receiver.\\\"\\n\\n\\t^0 - self! !\\n\\n!Number methodsFor: 'arithmetic'!\\nquo: aNumber \\n\\t\\\"Integer quotient defined by division with truncation toward zero. -9 quo: \\n\\t4 = -2, -0.9 quo: 0.4 = -2. rem: answers the remainder from this division.\\\"\\n\\n\\t^(self / aNumber) truncated! !\\n\\n!Number methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'!\\nreciprocal\\n\\t\\\"Answer 1 divided by the receiver. Create an error notification if the \\n\\treceiver is 0.\\\"\\n\\t#Numeric.\\n\\t\\\"Changed 200/01/19 For ANSI <number> support.\\\"\\n\\tself = 0 ifTrue: [^ (ZeroDivide dividend: self) signal\\\"<- Chg\\\"].\\n\\t^ 1 / self! !\\n\\n!Number methodsFor: 'arithmetic'!\\nrem: aNumber \\n\\t\\\"Remainder defined in terms of quo:. Answer a Number with the same \\n\\tsign as self. e.g. 9 rem: 4 = 1, -9 rem: 4 = -1. 0.9 rem: 0.4 = 0.1.\\\"\\n\\n\\t^self - ((self quo: aNumber) * aNumber)! !\\n\\n\\n!Number methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'!\\ncloseTo: num\\n\\t\\\"are these two numbers close?\\\"\\n\\n\\t| ans |\\n\\tnum isFloat ifTrue: [^ num closeTo: self asFloat].\\n\\t[ans _ self = num] ifError: [:aString :aReceiver | ^ false].\\n\\t^ ans! !\\n\\n\\n!Number methodsFor: 'converting' stamp: 'avi 9/6/2005 22:07'!\\nprintShowingDecimalPlaces: placesDesired\\n\\t\\\"Print the receiver showing precisely the given number of places desired . If the placesDesired provided is positive, a decimal point and that many digits after the decimal point will always be shown. If the placesDesired is zero, a whole number will be shown, without a decimal point. This method could probably be greatly optimized -- improvements welcomed.\\\"\\n\\n\\t| precision rounded integerString fractionString |\\n\\tplacesDesired <= 0 ifTrue: [^ self rounded printString].\\n\\tprecision _ Utilities floatPrecisionForDecimalPlaces: placesDesired.\\n\\trounded _ self roundTo: precision.\\n\\tintegerString _ rounded integerPart asInteger asString.\\n\\tfractionString _ (rounded fractionPart abs / precision) asInteger asString.\\n\\t^ String streamContents:\\n\\t\\t[:s |\\n\\t\\ts nextPutAll: integerString.\\n\\t\\ts nextPut: $..\\n\\t\\t(placesDesired - fractionString size) timesRepeat: [s nextPut: $0].\\n\\t\\ts nextPutAll: fractionString]\\n\\\"\\n23 printShowingDecimalPlaces: 2\\n23.5698 printShowingDecimalPlaces: 2\\n-234.567 printShowingDecimalPlaces: 5\\n23.4567 printShowingDecimalPlaces: 0\\n100000000 printShowingDecimalPlaces: 1\\n\\\"! !\\n\\n!Number methodsFor: 'converting'!\\n@ y \\n\\t\\\"Primitive. Answer a Point whose x value is the receiver and whose y \\n\\tvalue is the argument. Optional. No Lookup. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 18>\\n\\t^Point x: self y: y! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:43'!\\nadaptToCollection: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Collection, return a Collection of\\n\\tthe results of each element combined with me in that expression.\\\"\\n\\n\\t^ rcvr collect: [:element | element perform: selector with: self]! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:21'!\\nadaptToFloat: rcvr andSend: selector \\n\\t\\\"If I am involved in arithmetic with a Float, convert me to a Float.\\\"\\n\\t^ rcvr perform: selector with: self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToFraction: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Fraction, convert us and evaluate exprBlock.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToInteger: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Integer, convert us and evaluate exprBlock.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'!\\nadaptToPoint: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a Point, convert me to a Point.\\\"\\n\\t^ rcvr perform: selector with: self@self! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nadaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector \\n\\t\\\"Do any required conversion and then the arithmetic. \\n\\treceiverScaledDecimal arithmeticOpSelector self.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ScaledDecimal support.\\\"\\n\\t^ self subclassResponsibility! !\\n\\n!Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:45'!\\nadaptToString: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a String, convert it to a Number.\\\"\\n\\t^ rcvr asNumber perform: selector with: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'ar 5/20/2001 01:40'!\\nasB3DVector3\\n\\t^self@self@self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/13/2003 10:13'!\\nasDuration\\n\\n\\n\\n\\t^ Duration nanoSeconds: self asInteger\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatD\\n\\t\\\"Answer a d precision floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatE\\n\\t\\\"Answer a floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasFloatQ\\n\\t\\\"Answer a floating-point number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For ANSI <number> protocol.\\\"\\n\\t^ self asFloat! !\\n\\n!Number methodsFor: 'converting'!\\nasInteger\\n\\t\\\"Answer an Integer nearest the receiver toward zero.\\\"\\n\\n\\t^self truncated! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 2/16/1999 18:15'!\\nasNumber\\n\\t^ self! !\\n\\n!Number methodsFor: 'converting'!\\nasPoint\\n\\t\\\"Answer a Point with the receiver as both coordinates; often used to \\n\\tsupply the same value in two dimensions, as with symmetrical gridding \\n\\tor scaling.\\\"\\n\\n\\t^self @ self! !\\n\\n!Number methodsFor: 'converting' stamp: 'dtl 9/25/2004 11:47'!\\nasScaledDecimal\\n\\t\\\"Answer a scaled decimal number approximating the receiver.\\\"\\n\\t#Numeric.\\n\\n\\t^ self asScaledDecimal: 8\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'!\\nasScaledDecimal: scale \\n\\t\\\"Answer a scaled decimal number, with a fractional precision of scale, \\n\\tapproximating the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"add 200/01/19 For number protocol.\\\"\\n\\t^ ScaledDecimal newFromNumber: self scale: scale! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 9/8/97 16:30'!\\nasSmallAngleDegrees\\n\\t\\\"Return the receiver normalized to lie within the range (-180, 180)\\\"\\n\\n\\t| pos |\\n\\tpos _ self \\\\\\\\ 360.\\n\\tpos > 180 ifTrue: [pos _ pos - 360].\\n\\t^ pos\\n\\n\\\"#(-500 -300 -150 -5 0 5 150 300 500 1200) collect: [:n | n asSmallAngleDegrees]\\\"! !\\n\\n!Number methodsFor: 'converting' stamp: 'sw 10/7/1999 12:24'!\\nasSmallPositiveDegrees\\n\\t\\\"Return the receiver normalized to lie within the range (0, 360)\\\"\\n\\n\\t| result |\\n\\tresult _ self.\\n\\t[result < 0] whileTrue: [result _ result + 360].\\n\\t^ result \\\\\\\\ 360\\n\\n\\\"#(-500 -300 -150 -5 0 5 150 300 500 1200) collect: [:n | n asSmallPositiveDegrees]\\\"! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:12'!\\nday\\n\\n\\n\\n\\t^ self sign days! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\ndays\\n\\n\\n\\n\\t^ Duration days: self! !\\n\\n!Number methodsFor: 'converting'!\\ndegreesToRadians\\n\\t\\\"The receiver is assumed to represent degrees. Answer the conversion to \\n\\tradians.\\\"\\n\\n\\t^self asFloat degreesToRadians! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:28'!\\nhour\\n\\n\\n\\n\\t^ self sign hours\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\nhours\\n\\n\\n\\n\\t^ Duration hours: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'mk 10/27/2003 18:17'!\\ni\\n\\t^ Complex real: 0 imaginary: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:26'!\\nmilliSecond\\n\\n\\n\\n\\t^ self sign milliSeconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 9/25/2003 13:16'!\\nmilliSeconds\\n\\n\\n\\n\\t^ Duration milliSeconds: self\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:16'!\\nminute\\n\\n\\n\\n\\t^ self sign minutes\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'!\\nminutes\\n\\n\\n\\n\\t^ Duration minutes: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:27'!\\nnanoSecond\\n\\n\\n\\n\\t^ self sign nanoSeconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 08:52'!\\nnanoSeconds\\n\\n\\n\\n\\t^ Duration nanoSeconds: self.! !\\n\\n!Number methodsFor: 'converting'!\\nradiansToDegrees\\n\\t\\\"The receiver is assumed to represent radians. Answer the conversion to \\n\\tdegrees.\\\"\\n\\n\\t^self asFloat radiansToDegrees! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:17'!\\nsecond\\n\\n\\n\\n\\t^ self sign seconds\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:57'!\\nseconds\\n\\n\\n\\n\\t^ Duration seconds: self! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/21/2003 08:20'!\\nsign: aNumber\\n\\n\\t\\\"Return a Number with the same sign as aNumber\\\"\\n\\n\\n\\n\\t^ aNumber positive ifTrue: [self abs] ifFalse: [self abs negated].! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:19'!\\nweek\\n\\n\\n\\n\\t^ self sign weeks\\n\\n! !\\n\\n!Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:57'!\\nweeks\\n\\n\\n\\n\\t^ Duration weeks: self! !\\n\\n\\n!Number methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'!\\nbyteEncode:aStream\\n\\t^aStream writeNumber:self.\\n! !\\n\\n\\n!Number methodsFor: 'intervals'!\\nto: stop\\n\\t\\\"Answer an Interval from the receiver up to the argument, stop, \\n\\tincrementing by 1.\\\"\\n\\n\\t^Interval from: self to: stop by: 1! !\\n\\n!Number methodsFor: 'intervals'!\\nto: stop by: step\\n\\t\\\"Answer an Interval from the receiver up to the argument, stop, \\n\\tincrementing by step.\\\"\\n\\n\\t^Interval from: self to: stop by: step! !\\n\\n!Number methodsFor: 'intervals' stamp: 'tao 1/30/1999 08:58'!\\nto: stop by: step do: aBlock \\n\\t\\\"Normally compiled in-line, and therefore not overridable.\\n\\tEvaluate aBlock for each element of the interval (self to: stop by: \\nstep).\\\"\\n\\t| nextValue |\\n\\tnextValue _ self.\\n\\tstep = 0 ifTrue: [self error: 'step must be non-zero'].\\n\\tstep < 0\\n\\t\\tifTrue: [[stop <= nextValue]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\t\\t\\tnextValue _ nextValue + step]]\\n\\t\\tifFalse: [[stop >= nextValue]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\t\\t\\tnextValue _ nextValue + step]]! !\\n\\n!Number methodsFor: 'intervals'!\\nto: stop do: aBlock \\n\\t\\\"Normally compiled in-line, and therefore not overridable.\\n\\tEvaluate aBlock for each element of the interval (self to: stop by: 1).\\\"\\n\\t| nextValue |\\n\\tnextValue _ self.\\n\\t[nextValue <= stop]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: nextValue.\\n\\t\\t\\tnextValue _ nextValue + 1]! !\\n\\n\\n!Number methodsFor: 'mathematical functions'!\\narcCos \\n\\t\\\"The receiver is the cosine of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcCos! !\\n\\n!Number methodsFor: 'mathematical functions'!\\narcSin\\n\\t\\\"The receiver is the sine of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcSin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\narcTan\\n\\t\\\"The receiver is the tangent of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^self asFloat arcTan! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'jsp 2/24/1999 15:20'!\\narcTan: denominator\\n\\t\\\"The receiver is the tangent of an angle. Answer the angle measured in \\n\\tradians.\\\"\\n\\n\\t^(self asFloat) arcTan: denominator.! !\\n\\n!Number methodsFor: 'mathematical functions'!\\ncos\\n\\t\\\"The receiver represents an angle measured in radians. Answer its cosine.\\\"\\n\\n\\t^self asFloat cos! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'!\\ndegreeCos\\n\\t\\\"Answer the cosine of the receiver taken as an angle in degrees.\\\"\\n\\t\\n\\t^ (90 + self) degreeSin! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'!\\ndegreeSin\\n\\t\\\"Answer the sine of the receiver taken as an angle in degrees.\\\"\\n\\t\\n\\t^ self asFloat degreesToRadians sin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nexp\\n\\t\\\"Answer the exponential of the receiver as a floating point number.\\\"\\n\\n\\t^self asFloat exp! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'jm 3/27/98 06:16'!\\nfloorLog: radix\\n\\t\\\"Answer the floor of the log base radix of the receiver.\\\"\\n\\n\\t^ self asFloat floorLog: radix\\n! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'ar 8/31/2000 20:05'!\\ninterpolateTo: aNumber at: param\\n\\t^self + (aNumber - self * param)! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nln\\n\\t\\\"Answer the natural log of the receiver.\\\"\\n\\n\\t^self asFloat ln! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'di 9/8/1998 17:10'!\\nlog\\n\\t\\\"Answer the base-10 log of the receiver.\\\"\\n\\n\\t^self asFloat log! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nlog: aNumber \\n\\t\\\"Answer the log base aNumber of the receiver.\\\"\\n\\n\\t^self ln / aNumber ln! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'RJ 3/15/1999 19:35'!\\nraisedTo: aNumber \\n\\t\\\"Answer the receiver raised to aNumber.\\\"\\n\\n\\taNumber isInteger ifTrue:\\n\\t\\t[\\\"Do the special case of integer power\\\"\\n\\t\\t^ self raisedToInteger: aNumber].\\n\\tself < 0 ifTrue:\\n\\t\\t[ self error: self printString, ' raised to a non-integer power' ].\\n\\taNumber = 0 ifTrue: [^ 1].\\t\\t\\\"Special case of exponent=0\\\"\\n\\t(self = 0) | (aNumber = 1) ifTrue:\\n\\t\\t[^ self].\\t\\t\\t\\t\\t\\t\\\"Special case of exponent=1\\\"\\n\\t^ (aNumber * self ln) exp\\t\\t\\\"Otherwise use logarithms\\\"! !\\n\\n!Number methodsFor: 'mathematical functions' stamp: 'RAH 4/25/2000 19:49'!\\nraisedToInteger: operand \\n\\t\\\"Answer the receiver raised to the power operand, an Integer.\\\"\\n\\t| count result |\\n\\t#Numeric.\\n\\t\\\"Changed 200/01/19 For ANSI <number> support.\\\"\\n\\toperand isInteger ifFalse: [^ ArithmeticError signal: 'parameter is not an Integer'\\\"<- Chg\\\"].\\n\\toperand = 0 ifTrue: [^ self class one].\\n\\toperand = 1 ifTrue: [^ self].\\n\\toperand < 0 ifTrue: [^ (self raisedToInteger: operand negated) reciprocal].\\n\\tcount := 1.\\n\\t[(count := count + count) < operand] whileTrue.\\n\\tresult := self class one.\\n\\t[count > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[result := result * result.\\n\\t\\t\\t(operand bitAnd: count)\\n\\t\\t\\t\\t= 0 ifFalse: [result := result * self].\\n\\t\\t\\tcount := count bitShift: -1].\\n\\t^ result! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsin\\n\\t\\\"The receiver represents an angle measured in radians. Answer its sine.\\\"\\n\\n\\t^self asFloat sin! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsqrt\\n\\t\\\"Answer the square root of the receiver.\\\"\\n\\n\\t^self asFloat sqrt! !\\n\\n!Number methodsFor: 'mathematical functions'!\\nsquared\\n\\t\\\"Answer the receiver multipled by itself.\\\"\\n\\n\\t^self * self! !\\n\\n!Number methodsFor: 'mathematical functions'!\\ntan\\n\\t\\\"The receiver represents an angle measured in radians. Answer its \\n\\ttangent.\\\"\\n\\n\\t^self asFloat tan! !\\n\\n\\n!Number methodsFor: 'printing'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\n\\t^ super defaultLabelForInspector, ': ', self printString! !\\n\\n!Number methodsFor: 'printing' stamp: 'sw 6/29/1999 21:10'!\\nisOrAreStringWith: aNoun\\n\\t| result |\\n\\tresult _ self = 1\\n\\t\\tifTrue:\\n\\t\\t\\t[' is one ']\\n\\t\\tifFalse:\\n\\t\\t\\t[self = 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[' are no ']\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[' are ', self printString, ' ']].\\n\\tresult _ result, aNoun.\\n\\tself = 1 ifFalse: [result _ result, 's'].\\n\\t^ result\\n\\n\\\"#(0 1 2 98.6) do:\\n\\t[:num | Transcript cr; show: 'There', (num isOrAreStringWith: 'way'), ' to skin a cat']\\\"! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:53'!\\nprintOn: aStream\\n\\tself printOn: aStream base: 10! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:55'!\\nprintOn: aStream base: base\\n\\t^self subclassResponsibility! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/30/2004 10:50'!\\nprintString\\n\\t^self printStringBase: 10! !\\n\\n!Number methodsFor: 'printing'!\\nprintStringBase: base\\n\\t^ String streamContents:\\n\\t\\t[:strm | self printOn: strm base: base]! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:50'!\\nstoreOn: aStream \\n\\tself printOn: aStream! !\\n\\n!Number methodsFor: 'printing' stamp: 'laza 3/29/2004 12:59'!\\nstoreOn: aStream base: base\\n\\tself printOn: aStream base: base! !\\n\\n!Number methodsFor: 'printing'!\\nstoreStringBase: base\\n\\t^ String streamContents: [:strm | self storeOn: strm base: base]! !\\n\\n!Number methodsFor: 'printing' stamp: 'sw 7/1/1998 12:33'!\\nstringForReadout\\n\\t^ self rounded printString! !\\n\\n\\n!Number methodsFor: 'testing' stamp: 'sw 9/27/2001 17:26'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t^ #Number! !\\n\\n!Number methodsFor: 'testing'!\\neven\\n\\t\\\"Answer whether the receiver is an even number.\\\"\\n\\n\\t^self \\\\\\\\ 2 = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'sw 12/30/1998 13:21'!\\nisDivisibleBy: aNumber\\n\\taNumber = 0 ifTrue: [^ false].\\n\\taNumber isInteger ifFalse: [^ false].\\n\\t^ (self \\\\\\\\ aNumber) = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'!\\nisInf\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 4/19/98 23:33'!\\nisInfinite\\n\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'!\\nisNaN\\n\\t^ false! !\\n\\n!Number methodsFor: 'testing'!\\nisNumber\\n\\t^ true! !\\n\\n!Number methodsFor: 'testing'!\\nisZero\\n\\t^self = 0! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:18'!\\nnegative\\n\\t\\\"Answer whether the receiver is mathematically negative.\\\"\\n\\n\\t^ self < 0! !\\n\\n!Number methodsFor: 'testing'!\\nodd\\n\\t\\\"Answer whether the receiver is an odd number.\\\"\\n\\n\\t^self even == false! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:17'!\\npositive\\n\\t\\\"Answer whether the receiver is positive or equal to 0. (ST-80 protocol).\\n\\tSee also strictlyPositive\\\"\\n\\n\\t^ self >= 0! !\\n\\n!Number methodsFor: 'testing'!\\nsign\\n\\t\\\"Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0.\\\"\\n\\n\\tself > 0 ifTrue: [^1].\\n\\tself < 0 ifTrue: [^-1].\\n\\t^0! !\\n\\n!Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:02'!\\nstrictlyPositive\\n\\t\\\"Answer whether the receiver is mathematically positive.\\\"\\n\\n\\t^ self > 0! !\\n\\n\\n!Number methodsFor: 'truncation and round off'!\\nceiling\\n\\t\\\"Answer the integer nearest the receiver toward positive infinity.\\\"\\n\\n\\tself <= 0.0\\n\\t\\tifTrue: [^self truncated]\\n\\t\\tifFalse: [^self negated floor negated]! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'di 2/19/98 21:58'!\\ndetentBy: detent atMultiplesOf: grid snap: snap\\n\\t\\\"Map all values that are within detent/2 of any multiple of grid to that multiple. Otherwise, if snap is true, return self, meaning that the values in the dead zone will never be returned. If snap is false, then expand the range between dead zones so that it covers the range between multiples of the grid, and scale the value by that factor.\\\"\\n\\t| r1 r2 |\\n\\tr1 _ self roundTo: grid. \\\"Nearest multiple of grid\\\"\\n\\t(self roundTo: detent) = r1 ifTrue: [^ r1]. \\\"Snap to that multiple...\\\"\\n\\tsnap ifTrue: [^ self]. \\\"...or return self\\\"\\n\\n\\tr2 _ self < r1 \\\"Nearest end of dead zone\\\"\\n\\t\\tifTrue: [r1 - (detent asFloat/2)]\\n\\t\\tifFalse: [r1 + (detent asFloat/2)].\\n\\t\\\"Scale values between dead zones to fill range between multiples\\\"\\n\\t^ r1 + ((self - r2) * grid asFloat / (grid - detent))\\n\\\"\\n\\t(170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: true] \\t(170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: false]\\n\\t(3.9 to: 4.1 by: 0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: true] \\t(-3.9 to: -4.1 by: -0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: false]\\n\\\"! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nfloor\\n\\t\\\"Answer the integer nearest the receiver toward negative infinity.\\\"\\n\\n\\t| truncation |\\n\\ttruncation _ self truncated.\\n\\tself >= 0 ifTrue: [^truncation].\\n\\tself = truncation\\n\\t\\tifTrue: [^truncation]\\n\\t\\tifFalse: [^truncation - 1]! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'!\\nfractionPart\\n\\t\\\"Answer the fractional part of the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"2000/03/04 Harmon R. Added ANSI <number> protocol\\\"\\n\\t^ self - self truncated! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'!\\nintegerPart\\n\\t\\\"Answer the integer part of the receiver.\\\"\\n\\t#Numeric.\\n\\t\\\"2000/03/04 Harmon R. Added ANSI <number> protocol\\\"\\n\\t^ self truncated! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nreduce\\n \\\"If self is close to an integer, return that integer\\\"\\n ^ self! !\\n\\n!Number methodsFor: 'truncation and round off' stamp: 'di 10/4/1999 08:08'!\\nroundTo: quantum \\n\\t\\\"Answer the nearest number that is a multiple of quantum.\\\"\\n\\n\\t^(self / quantum) rounded * quantum! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nroundUpTo: aNumber \\n\\t\\\"Answer the next multiple of aNumber toward infinity that is nearest the \\n\\treceiver.\\\"\\n\\n\\t^(self/aNumber) ceiling * aNumber! !\\n\\n!Number methodsFor: 'truncation and round off'!\\nrounded\\n\\t\\\"Answer the integer nearest the receiver.\\\"\\n\\n\\t^(self + (self sign / 2)) truncated! !\\n\\n!Number methodsFor: 'truncation and round off'!\\ntruncateTo: aNumber \\n\\t\\\"Answer the next multiple of aNumber toward zero that is nearest the \\n\\treceiver.\\\"\\n\\n\\t^(self quo: aNumber)\\n\\t\\t* aNumber! !\\n\\n!Number methodsFor: 'truncation and round off'!\\ntruncated\\n\\t\\\"Answer an integer nearest the receiver toward zero.\\\"\\n\\n\\t^self quo: 1! !\\n\\n\\n!Number methodsFor: '*eToys-printing' stamp: 'sw 10/31/97 13:54'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new addArrows; setLiteral: self; addSuffixIfCan\\n! !\\n\\n\\n!Number methodsFor: '*eToys-vocabulary' stamp: 'sw 8/3/2001 13:43'!\\nvocabularyDemanded\\n\\t\\\"Answer the vocabulary normally preferred by this object\\\"\\n\\n\\t^ Vocabulary numberVocabulary! !\\n\\n\\n!Number methodsFor: '*Morphic-NewCurve-testing' stamp: 'jmv 2/21/2006 13:15'!\\nisNonZero\\n\\t\\\"Return true for numbers not zero and false for all other\\n\\tobjects \\\"\\n\\t^ self isZero not! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNumber class\\n\\tinstanceVariableNames: ''!\\n\\n!Number class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 21:46'!\\nreadExactlyFrom: stringOrStream \\n\\t\\\"Answer a number as described on aStream. The number may\\n\\tinclude a leading radix specification, as in 16rFADE\\\"\\n\\t\\n\\t^(SqNumberParser on: stringOrStream) nextNumber! !\\n\\n!Number class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 22:40'!\\nreadFrom: stringOrStream \\n\\t\\\"Answer a number as described on aStream. The number may\\n\\tinclude a leading radix specification, as in 16rFADE\\\"\\n\\t| value base aStream sign |\\n\\taStream _ (stringOrStream isString)\\n\\t\\tifTrue: [ReadStream on: stringOrStream]\\n\\t\\tifFalse: [stringOrStream].\\n\\t(aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan].\\n\\tsign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1].\\n\\t(aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign].\\n\\tbase _ 10.\\n\\tvalue _ Integer readFrom: aStream base: base.\\n\\t(aStream peekFor: $r)\\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"<base>r<integer>\\\"\\n\\t\\t\\t(base _ value) < 2 ifTrue: [^self error: 'Invalid radix'].\\n\\t\\t\\t(aStream peekFor: $-) ifTrue: [sign _ sign negated].\\n\\t\\t\\tvalue _ Integer readFrom: aStream base: base].\\n\\t^ self readRemainderOf: value from: aStream base: base withSign: sign.! !\\n\\n!Number class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 22:41'!\\nreadFrom: stringOrStream base: base\\n\\t\\\"Answer a number as described on aStream in the given number base.\\\"\\n\\n\\t| aStream sign |\\n\\taStream _ (stringOrStream isString)\\n\\t\\tifTrue: [ReadStream on: stringOrStream]\\n\\t\\tifFalse: [stringOrStream].\\n\\t(aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan].\\n\\tsign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1].\\n\\t(aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign].\\n\\t^ self readRemainderOf: (Integer readFrom: aStream base: base)\\n\\t\\t\\tfrom: aStream base: base withSign: sign! !\\n\\n\\n!Number class methodsFor: 'private' stamp: 'dtl 7/3/2006 17:41'!\\nreadExponent: baseValue base: base from: aStream\\n\\t\\\"Complete creation of a number, reading exponent from aStream. Answer the\\n\\tnumber, or nil if parsing fails.\\n\\t<number>(e|d|q)<exponent>>\\\"\\n\\n\\t| sign exp value |\\n\\t('edq' includes: aStream next) ifFalse: [^ nil].\\n\\tsign := ((aStream peek) == $-)\\n\\t\\tifTrue: [aStream next. -1]\\n\\t\\tifFalse: [1].\\n\\t(aStream atEnd or: [(aStream peek digitValue between: 0 and: 9) not])\\n\\t\\tifTrue: [^ nil]. \\\"Avoid throwing an error\\\"\\n\\texp := (Integer readFrom: aStream base: 10) * sign.\\n\\tvalue := baseValue * (base raisedTo: exp).\\n\\t^ value\\n! !\\n\\n!Number class methodsFor: 'private' stamp: 'dtl 7/4/2006 08:32'!\\nreadRemainderOf: integerPart from: aStream base: base withSign: sign \\n\\t\\\"Read optional fractional part and exponent or decimal scale, and return the final result\\\"\\n\\t\\\"Changed 200/01/19 For ANSI Numeric Literals support.\\\"\\n\\t\\\"Number readFrom: '3r-22.2'\\\"\\n\\n\\t| value fractionDigits fracpos fractionPart fraction pos v foundDecimal |\\n\\t#Numeric.\\n\\tvalue := integerPart.\\n\\tfractionDigits := 0.\\n\\tfoundDecimal := false.\\n\\t(aStream peekFor: $.)\\n\\t\\tifTrue: [\\\"<integer>.<fraction>\\\"\\n\\t\\t\\tfoundDecimal := true.\\n\\t\\t\\t(aStream atEnd not\\n\\t\\t\\t\\t\\tand: [aStream peek digitValue between: 0 and: base - 1])\\n\\t\\t\\t\\tifTrue: [fracpos := aStream position.\\n\\t\\t\\t\\t\\tfractionPart := Integer readFrom: aStream base: base.\\n\\t\\t\\t\\t\\tfraction := fractionPart asFloat\\n\\t\\t\\t\\t\\t\\t\\t\\t/ (base raisedTo: aStream position - fracpos).\\n\\t\\t\\t\\t\\tfractionDigits := aStream position - fracpos.\\n\\t\\t\\t\\t\\tvalue := value asFloat + fraction]].\\n\\n\\tpos := aStream position.\\n\\t(v := self readScaledDecimal: integerPart\\n\\t\\t\\tfractionPart: fractionPart\\n\\t\\t\\tdigits: fractionDigits\\n\\t\\t\\tbase: base\\n\\t\\t\\tsign: sign\\n\\t\\t\\tfrom: aStream)\\n\\t\\tifNil: [aStream position: pos]\\n\\t\\tifNotNil: [^ v \\\"<number>s<scale>>\\\"].\\n\\n\\tpos := aStream position.\\n\\t(v := self readExponent: value base: base from: aStream)\\n\\t\\tifNil: [aStream position: pos.\\n\\t\\t\\t(foundDecimal and: [fractionDigits = 0])\\n\\t\\t\\t\\tifTrue: [\\\"oops - just <integer>.\\\"\\n\\t\\t\\t\\t\\t\\t\\taStream skip: -1.\\n\\t\\t\\t\\t\\t\\t\\t\\\"un-gobble the period\\\"\\n\\t\\t\\t\\t\\t\\t\\t^ value * sign]]\\n\\t\\tifNotNil: [value := v \\\"<number>(e|d|q)<exponent>>\\\"].\\n\\n\\t(value isFloat\\n\\t\\t\\tand: [value = 0.0\\n\\t\\t\\t\\t\\tand: [sign = -1]])\\n\\t\\tifTrue: [^ Float negativeZero]\\n\\t\\tifFalse: [^ value * sign]! !\\n\\n!Number class methodsFor: 'private' stamp: 'md 7/15/2006 18:00'!\\nreadScaledDecimal: integerPart fractionPart: fractionPart digits: fractionDigits base: base sign: sign from: aStream \\n\\t\\\"Complete creation of a ScaledDecimal, reading scale from aStream. Answer\\n\\ta ScaledDecimal, or nil if parsing fails.\\n\\t<number>s[<scale>]\\\"\\n\\n\\t| scale decimalMultiplier decimalFraction |\\n\\taStream atEnd ifTrue: [^ nil].\\n\\t(aStream next == $s) ifFalse: [^ nil].\\n\\t\\\"<number>s<scale>\\\"\\n\\t(aStream atEnd not and: [aStream peek digitValue between: 0 and: 9])\\n\\t\\tifTrue: [scale := Integer readFrom: aStream]\\n\\t\\tifFalse: [^ nil].\\n\\tscale isNil\\n\\t\\tifTrue: [\\\"<number>s\\\"\\n\\t\\t\\tfractionDigits = 0\\n\\t\\t\\t\\tifTrue: [\\\"<integer>s\\\"\\n\\t\\t\\t\\t\\tscale := 0]\\n\\t\\t\\t\\tifFalse: [\\\"<integer>.<fraction>s\\\"\\n\\t\\t\\t\\t\\tscale := fractionDigits]].\\n\\tfractionPart isNil\\n\\t\\tifTrue: [^ ScaledDecimal newFromNumber: integerPart * sign scale: scale]\\n\\t\\tifFalse: [decimalMultiplier := base raisedTo: fractionDigits.\\n\\t\\t\\tdecimalFraction := integerPart * decimalMultiplier + fractionPart * sign / decimalMultiplier.\\n\\t\\t\\t^ ScaledDecimal newFromNumber: decimalFraction scale: scale]! !\\nTestCase subclass: #NumberParsingTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n!NumberParsingTest commentStamp: 'dtl 11/24/2004 15:35' prior: 0!\\nTests to verify parsing of numbers from streams and strings.\\n\\nNote: ScaledDecimalTest contains related tests for parsing ScaledDecimal.!\\n\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:29'!\\ntestFloatFromStreamAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs _ '10r-12.3456' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -12.3456 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456e2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456e2e2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs upToEnd = 'e2'.\\n\\n\\trs _ '10r-12.3456d2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '10r-12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '-12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '12.3456q2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '12.3456z2' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 12.3456 = aFloat.\\n\\tself assert: rs upToEnd = 'z2'.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'nice 4/28/2006 01:20'!\\ntestFloatFromStreamWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs _ '1.0e-14' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs _ '1.0e-14 1' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = ' 1'.\\n\\n\\trs _ '1.0e-14eee' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = 'eee'.\\n\\n\\trs _ '1.0e14e10' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0e14 = aFloat.\\n\\tself assert: rs upToEnd = 'e10'.\\n\\n\\trs _ '1.0e+14e' readStream. \\\"Plus sign is not parseable\\\"\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e+14e'.\\n\\n\\trs _ '1.0e' readStream.\\n\\taFloat _ Number readFrom: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e'.! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:07'!\\ntestFloatFromStringAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| aFloat |\\n\\taFloat _ '10r-12.3456' asNumber.\\n\\tself assert: -12.3456 = aFloat.\\n\\taFloat _ '10r-12.3456e2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '10r-12.3456d2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '10r-12.3456q2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '-12.3456q2' asNumber.\\n\\tself assert: -1234.56 = aFloat.\\n\\taFloat _ '12.3456q2' asNumber.\\n\\tself assert: 1234.56 = aFloat.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 14:12'!\\ntestFloatFromStringWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| aFloat |\\n\\taFloat _ '1.0e-14' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e-14 1' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e-14e' asNumber.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\taFloat _ '1.0e14e' asNumber.\\n\\tself assert: 1.0e14 = aFloat.\\n\\taFloat _ '1.0e+14e' asNumber. \\\"Plus sign is not parseable\\\"\\n\\tself assert: 1.0 = aFloat.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'nice 4/28/2006 01:39'!\\ntestFloatReadError\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs num |\\n\\trs := '1e' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 'e'.\\n\\t\\n\\trs := '1s' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 's'.\\n\\n\\trs := '1.' readStream.\\n\\tnum := Number readFrom: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: num isInteger.\\n\\tself assert: rs upToEnd = '.'.\\n\\t\\n\\trs := '' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := 'foo' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\n\\trs := 'radix' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '.e0' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '-.e0' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.\\n\\t\\n\\trs := '--1' readStream.\\n\\tself should: [Number readFrom: rs] raise: Error.! !\\n\\n!NumberParsingTest methodsFor: 'tests - Float' stamp: 'dtl 11/24/2004 18:16'!\\ntestFloatReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber _ '2r1.0101e9' asNumber.\\n\\tself assert: 672.0 = aNumber.\\n\\tself assert: (Number readFrom: '2r1.0101e9') = (1.3125 * (2 raisedTo: 9)).\\n\\trs _ ReadStream on: '2r1.0101e9e9'.\\n\\tself assert: (Number readFrom: rs) = 672.0.\\n\\tself assert: rs upToEnd = 'e9'\\n! !\\n\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'dtl 11/24/2004 14:05'!\\ntestIntegerFromString\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tTrailing decimal points should be ignored.\\\"\\n\\n\\tself assert: ('123' asNumber == 123).\\n\\tself assert: ('-123' asNumber == -123).\\n\\tself assert: ('123.' asNumber == 123).\\n\\tself assert: ('-123.' asNumber == -123).\\n\\tself assert: ('123This is not to be read' asNumber == 123).\\n\\tself assert: ('123s could be confused with a ScaledDecimal' asNumber == 123).\\n\\tself assert: ('123e could be confused with a Float' asNumber == 123).\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'tween 7/8/2006 12:31'!\\ntestIntegerReadFrom\\n\\t\\\"Ensure remaining characters in a stream are not lost when parsing an integer.\\\"\\n\\n\\t| rs i s |\\n\\trs _ ReadStream on: '123s could be confused with a ScaledDecimal'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 's could be confused with a ScaledDecimal' = s.\\n\\trs _ ReadStream on: '123.s could be confused with a ScaledDecimal'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: '.s could be confused with a ScaledDecimal' = s.\\n\\trs _ ReadStream on: '123sA has unary message sA'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 'sA has unary message sA' = s.\\t\\n\\trs _ ReadStream on: '123sB has unary message sB'.\\n\\ti _ Number readFrom: rs.\\n\\tself assert: i == 123.\\n\\ts _ rs upToEnd.\\n\\tself assert: 'sB has unary message sB' = s.\\n! !\\n\\n!NumberParsingTest methodsFor: 'tests - Integer' stamp: 'dtl 11/24/2004 18:18'!\\ntestIntegerReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber _ '2r1e26' asNumber.\\n\\tself assert: 67108864 = aNumber.\\n\\tself assert: (Number readFrom: '2r1e26') = (2 raisedTo: 26).\\n\\trs _ '2r1e26eee' readStream.\\n\\tself assert: (Number readFrom: rs) = 67108864.\\n\\tself assert: rs upToEnd = 'eee'\\n! !\\nClassTestCase subclass: #NumberTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n\\n!NumberTest methodsFor: 'tests' stamp: 'fbs 3/8/2006 11:24'!\\ntestPrintShowingDecimalPlaces\\n\\n\\tself assert: (111.2 printShowingDecimalPlaces: 2) = '111.20'.\\n\\tself assert: (111.2 printShowingDecimalPlaces: 0) = '111'.\\n\\tself assert: (111 printShowingDecimalPlaces: 0) = '111'.\\n\\tself assert: (111111111111111 printShowingDecimalPlaces: 2) = '111111111111111.00'.\\n\\tself assert: (10 printShowingDecimalPlaces: 20) ='10.00000000000000000000'.\\n! !\\n\\n!NumberTest methodsFor: 'tests' stamp: 'sd 6/5/2005 08:56'!\\ntestReadFrom\\n\\t\\n\\tself assert: 1.0e-14\\t= (Number readFrom: '1.0e-14').\\n\\tself assert: 2r1e26\\t= (Number readFrom: '2r1e26').! !\\nDataType subclass: #NumberType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n!NumberType commentStamp: 'sw 10/3/2002 02:18' prior: 0!\\nNumberType is a data type representing a numeric value.!\\n\\n\\n!NumberType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ (1 to: 9) atRandom! !\\n\\n\\n!NumberType methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\t| aMethodCategory aMethodInterface |\\n\\tsuper initialize.\\n\\t\\\"Vocabulary replaceNumberVocabulary\\\"\\n\\t\\\"Vocabulary addVocabulary: Vocabulary newNumberVocabulary\\\"\\n\\n\\tself vocabularyName: #Number.\\n\\tself documentation: 'Numbers are things that can do arithmetic, have their magnitudes compared, etc.'.\\n\\n#((comparing\\t\\t\\t\\t'Determining which of two numbers is larger'\\n\\t\\t(= < > <= >= ~= ~~))\\n(arithmetic \\t\\t\\t\\t'Basic numeric operation'\\n\\t\\t(* + - / // \\\\\\\\ abs negated quo: rem:))\\n(testing \\t\\t\\t\\t\\t'Testing a number'\\n\\t\\t(even isDivisibleBy: negative odd positive sign))\\n(#'mathematical functions'\\t'Trigonometric and exponential functions'\\n\\t\\t(cos exp ln log log: raisedTo: sin sqrt squared tan raisedToInteger:))\\n(converting \\t\\t\\t\\t'Converting a number to another form'\\n\\t\\t(@ asInteger asPoint degreesToRadians radiansToDegrees asSmallAngleDegrees asSmallPositiveDegrees))\\n(#'truncation and round off' 'Making a real number (with a decimal point) into an integer'\\n\\t\\t(ceiling floor roundTo: roundUpTo: rounded truncateTo: truncated))\\n) do:\\n\\n\\t\\t[:item | \\n\\t\\t\\taMethodCategory := ElementCategory new categoryName: item first.\\n\\t\\t\\taMethodCategory documentation: item second.\\n\\t\\t\\titem third do:\\n\\t\\t\\t\\t[:aSelector | \\n\\t\\t\\t\\t\\taMethodInterface := MethodInterface new conjuredUpFor: aSelector class: (Number whichClassIncludesSelector: aSelector).\\n\\t\\t\\t\\t\\taMethodInterface argumentVariables do:\\n\\t\\t\\t\\t\\t\\t\\t[:var | var variableType: #Number].\\n\\n\\t\\t\\t\\t\\t(#(* + - / // \\\\\\\\ abs negated quo: rem:\\n\\t\\t\\t\\t\\t\\tcos exp ln log log: raisedTo: sin sqrt squared tan raisedToInteger:\\n\\t\\t\\t\\t\\t\\tasInteger degreesToRadians radiansToDegrees asSmallAngleDegrees asSmallPositiveDegrees)\\n\\t\\t\\t\\t\\t\\t\\tincludes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Number].\\n\\n\\t\\t\\t\\t\\t(#( @ asPoint ) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Point].\\n\\n\\t\\t\\t\\t\\t(#(= < > <= >= ~= ~~ even isDivisibleBy: negative odd positive) includes: aSelector) ifTrue:\\n\\t\\t\\t\\t\\t\\t[aMethodInterface resultType: #Boolean].\\n\\n\\t\\t\\t\\t\\taMethodInterface setNotToRefresh. \\n\\t\\t\\t\\t\\tself atKey: aSelector putMethodInterface: aMethodInterface.\\n\\t\\t\\t\\t\\taMethodCategory elementAt: aSelector put: aMethodInterface].\\n\\t\\t\\tself addCategory: aMethodCategory].\\n\\n\\\"\\n(('truncation and round off' ceiling detentBy:atMultiplesOf:snap: floor roundTo: roundUpTo: rounded truncateTo: truncated)\\n('testing' basicType even isDivisibleBy: isInf isInfinite isNaN isNumber isZero negative odd positive sign strictlyPositive)\\n('converting' @ adaptToCollection:andSend: adaptToFloat:andSend: adaptToFraction:andSend: adaptToInteger:andSend: adaptToPoint:andSend: adaptToString:andSend: asInteger asNumber asPoint asSmallAngleDegrees asSmallPositiveDegrees degreesToRadians radiansToDegrees)\\n('intervals' to: to:by: to:by:do: to:do:)\\n('printing' defaultLabelForInspector isOrAreStringWith: newTileMorphRepresentative printOn: printStringBase: storeOn: storeOn:base: storeStringBase: stringForReadout)\\n('comparing' closeTo:)\\n('filter streaming' byteEncode:)\\n('as yet unclassified' reduce)\\\"\\n\\n\\n\\n! !\\n\\n\\n!NumberType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(0.8 0.4 0.2)! !\\n\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'dgd 9/6/2003 20:30'!\\naddExtraItemsToMenu: aMenu forSlotSymbol: slotSym\\n\\t\\\"If the receiver has extra menu items to add to the slot menu, here is its chance to do it. The defaultTarget of the menu is the player concerned.\\\"\\n\\n\\taMenu add: 'decimal places...' translated selector: #setPrecisionFor: argument: slotSym.\\n\\taMenu balloonTextForLastItem: 'Lets you choose how many decimal places should be shown in readouts for this variable' translated! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/15/2002 16:50'!\\naddUserSlotItemsTo: aMenu slotSymbol: slotSym\\n\\t\\\"Optionally add items to the menu that pertain to a user-defined slot of the given symbol\\\"\\n\\n\\t\\\"aMenu add: 'decimal places...' selector: #setPrecisionFor: argument: slotSym\\n\\tNB: This item is now generically added for system as well as user slots, so the addition is now done in NubmerType.addExtraItemsToMenu:forSlotSymbol:\\\"! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 02:53'!\\ncomparatorForSampleBoolean\\n\\t\\\"Answer the comparator to use in tile coercions involving the receiver; normally, the equality comparator is used but NumberType overrides\\\"\\n\\n\\t^ #<! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:30'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t^ 5 newTileMorphRepresentative typeColor: self typeColor! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:37'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ NumericReadoutTile new typeColor: Color lightGray lighter! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/26/2001 03:11'!\\nwantsAssignmentTileVariants\\n\\t\\\"Answer whether an assignment tile for a variable of this type should show variants to increase-by, decrease-by, multiply-by.\\\"\\n\\n\\t^ true! !\\n\\n!NumberType methodsFor: '*eToys-tiles' stamp: 'sw 9/26/2001 03:18'!\\nwantsSuffixArrow\\n\\t\\\"Answer whether a tile showing data of this type would like to have a suffix arrow\\\"\\n\\n\\t^ true! !\\nTileMorph subclass: #NumericReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'ar 9/15/2000 23:27'!\\nabandonLabelFocus\\n\\t| aLabel |\\n\\t\\\"If the receiver's label has editing focus, abandon it\\\"\\n\\tself flag: #arNote. \\\"Probably unnecessary\\\"\\n\\t(aLabel _ self labelMorph) ifNotNil:\\n\\t\\t[aLabel hasFocus ifTrue:\\n\\t\\t\\t[aLabel contents: aLabel readFromTarget.\\n\\t\\t\\taLabel handsWithMeForKeyboardFocus do:\\n\\t\\t\\t\\t[:aHand | aHand releaseKeyboardFocus]]]! !\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'tak 12/6/2004 01:53'!\\nliteralFromContents\\n\\t| label |\\n\\tlabel _ self labelMorph\\n\\t\\t\\t\\tifNil: [^ super literal].\\n\\tlabel step.\\n\\t^ literal _ label valueFromContents! !\\n\\n!NumericReadoutTile methodsFor: 'accessing' stamp: 'tak 4/6/2005 14:10'!\\nliteral: anObject \\n\\tliteral := anObject.\\n\\tself updateLiteralLabel.\\n\\tself labelMorph\\n\\t\\tifNotNilDo: [:label | label informTarget]! !\\n\\n\\n!NumericReadoutTile methodsFor: 'literal' stamp: 'sw 9/15/1999 15:14'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"like literal:width: but does not inform the target\\\"\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last setWidth: w.\\n\\tself updateLiteralLabel! !\\n\\n\\n!NumericReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:01'!\\nbasicWidth\\n\\t^ 26! !\\n\\n!NumericReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:18'!\\nminimumWidth\\n\\t^ 40! !\\n\\n\\n!NumericReadoutTile methodsFor: 'mouse' stamp: 'ar 10/25/2000 18:07'!\\nhandlesMouseMove: evt\\n\\t^true! !\\n\\n\\n!NumericReadoutTile methodsFor: 'parts bin' stamp: 'sw 11/15/2001 20:22'!\\ninitializeToStandAlone\\n\\t\\\"Enclose my prototype in a SyntaxMorph. For the ObjectTool\\\"\\n\\n\\t| aWatcher aTile aLine aColor ms slotMsg |\\n\\n\\tsuper initializeToStandAlone.\\n\\taColor _ Color r: 0.387 g: 0.581 b: 1.0.\\n\\taTile _ self typeColor: aColor.\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true;\\n\\t\\tgetSelector: nil;\\n\\t\\tputSelector: nil;\\n\\t\\tsetToAllowTextEdit.\\n\\taWatcher target: nil.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\n\\tms _ MessageSend receiver: nil selector: #aNumber arguments: #().\\n\\tslotMsg _ ms asTilesIn: Player globalNames: false.\\n\\t\\t\\\"For CardPlayers, use 'aPlayer'. For others, name it, and use its name.\\\"\\n\\tms _ MessageSend receiver: 3 selector: #= asSymbol arguments: #(5).\\n\\taLine _ ms asTilesIn: Player globalNames: false.\\n\\taLine firstSubmorph delete.\\t\\t\\\"A little over-complicated? Yes?\\\"\\n\\taLine addMorphFront: (slotMsg submorphs second) firstSubmorph.\\n\\taLine addMorphFront: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine lastSubmorph delete.\\n\\taLine lastSubmorph delete.\\n\\taLine color: aColor.\\n\\taLine addMorphBack: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine addMorphBack: aTile.\\n\\taLine cellPositioning: #leftCenter.\\n\\taWatcher step; fitContents.\\n\\t^ aLine markAsPartsDonor.! !\\n\\n\\n!NumericReadoutTile methodsFor: 'testing' stamp: 'tk 11/1/2001 12:41'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type I hold\\\"\\n\\n\\t\\\"Number String Boolean player collection sound color etc\\\"\\n\\t^ #Number! !\\n\\n\\n!NumericReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 23:36'!\\nmouseStillDown: evt \\n\\t(self labelMorph notNil\\n\\t\\t\\tand: [self labelMorph containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [^ self labelMorph mouseDown: evt].\\n\\t^ super mouseStillDown: evt! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nNumericReadoutTile class\\n\\tinstanceVariableNames: ''!\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'tk 12/14/2001 19:32'!\\nborderedPrototype\\n\\t\\\"Just number and up/down arrows\\\"\\n\\n\\t| aWatcher aTile |\\n\\n\\taTile _ self new typeColor: (Color r: 0.387 g: 0.581 b: 1.0).\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true; setNameTo: 'value'.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows; setNameTo: 'Number (mid)'.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\taWatcher step; fitContents; setToAllowTextEdit.\\n\\t^ aTile extent: 30@24; markAsPartsDonor! !\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'tk 12/14/2001 19:29'!\\nsimplePrototype\\n\\t\\\"Bare number readout. Will keep up to data with a number once it has target, getterSelector, setterSelector.\\\"\\n\\n\\t^ (UpdatingStringMorph new) contents: '5'; growable: true; setToAllowTextEdit; \\n\\t\\tstep; fitContents; setNameTo: 'Number (bare)'; markAsPartsDonor! !\\n\\n!NumericReadoutTile class methodsFor: 'instance creation' stamp: 'nk 8/23/2004 18:11'!\\nsupplementaryPartsDescriptions\\n\\t\\\"Answer additional items for the parts bin\\\"\\n\\n\\tPreferences universalTiles ifFalse: [^ #()].\\n\\n\\t^ {DescriptionForPartsBin\\n\\t\\tformalName: 'Number (fancy)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value. Shift-click on title to edit.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #authoringPrototype.\\n\\n\\t DescriptionForPartsBin\\n\\t\\tformalName: 'Number (bare)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #simplePrototype.\\n\\n\\t DescriptionForPartsBin\\n\\t\\tformalName: 'Number (mid)'\\n\\t\\tcategoryList: #('Basic')\\n\\t\\tdocumentation: 'A number readout for a Stack. Shows current value. Click and type the value.'\\n\\t\\tglobalReceiverSymbol: #NumericReadoutTile\\n\\t\\tnativitySelector: #borderedPrototype}! !\\n\\n\\n!NumericReadoutTile class methodsFor: 'scripting' stamp: 'tk 12/14/2001 19:30'!\\nauthoringPrototype\\n\\t\\\"Enclose my prototype in a SyntaxMorph.\\\"\\n\\n\\t| aWatcher aTile aLine aColor ms slotMsg |\\n\\n\\taColor _ Color r: 0.387 g: 0.581 b: 1.0.\\n\\taTile _ self new typeColor: aColor.\\n\\taWatcher _ UpdatingStringMorph new.\\n\\taWatcher growable: true;\\n\\t\\tsetToAllowTextEdit;\\n\\t\\tgetSelector: nil;\\n\\t\\tputSelector: nil.\\n\\taWatcher target: nil.\\n\\taTile addMorphBack: aWatcher.\\n\\taTile addArrows.\\n\\taTile setLiteralTo: 5 width: 30.\\n\\n\\t\\\"This is the long way around to do this...\\\"\\n\\tms _ MessageSend receiver: nil selector: #aNumber arguments: #().\\n\\tslotMsg _ ms asTilesIn: Player globalNames: false.\\n\\t\\t\\\"For CardPlayers, use 'aPlayer'. For others, name it, and use its name.\\\"\\n\\tms _ MessageSend receiver: 3 selector: #= asSymbol arguments: #(5).\\n\\taLine _ ms asTilesIn: Player globalNames: false.\\n\\taLine firstSubmorph delete.\\t\\n\\taLine addMorphFront: (slotMsg submorphs second) firstSubmorph.\\n\\taLine firstSubmorph setNameTo: 'label'.\\n\\taLine addMorphFront: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine lastSubmorph delete.\\n\\taLine lastSubmorph delete.\\n\\taLine color: aColor; setNameTo: 'Number (fancy)'.\\n\\taLine addMorphBack: (Morph new transparentSpacerOfSize: 3@3).\\n\\taLine addMorphBack: aTile.\\n\\taLine readOut setNameTo: 'value'.\\n\\taLine cellPositioning: #leftCenter.\\n\\taWatcher step; fitContents.\\n\\t^ aLine markAsPartsDonor.! !\\nOBAnnouncement subclass: #OBAboutToChange\\n\\tinstanceVariableNames: 'veto'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBAboutToChange methodsFor: 'vetos' stamp: 'cwp 4/17/2006 22:18'!\\nisVetoed\\n\\t^ veto notNil! !\\n\\n!OBAboutToChange methodsFor: 'vetos' stamp: 'cwp 4/17/2006 19:45'!\\nveto\\n\\tveto _ true! !\\nMessageSend subclass: #OBAction\\n\\tinstanceVariableNames: 'announcer dispatcher label buttonLabel keystroke icon'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n!OBAction commentStamp: 'cwp 3/4/2004 20:52' prior: 0!\\nActions represent commands for manipulating the graph domain. They can be made available through menus or buttons in the browser. They carry information on how they should be presented to the user, and are responsible for handling exceptions generated when they are triggered. Actions are created by Actors.\\n\\niVars: \\n\\nlabel \\t\\ta string which describes the action for the user.\\nmonitor \\twhen the action is triggered, any notifications raised \\n\\t\\t\\twill be passed to this object for processing!\\n\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:25'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:25'!\\nannouncer: anAnnouncer\\n\\tannouncer _ anAnnouncer! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:35'!\\nbuttonLabel\\n\\t^ buttonLabel! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:35'!\\nbuttonLabel: aString\\n\\tbuttonLabel _ aString\\n\\t! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 16:42'!\\nicon\\n\\t^icon! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 16:42'!\\nicon: anIcon\\n\\ticon _ anIcon! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 14:16'!\\nkeystroke\\n\\t^keystroke! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'hpt 5/17/2004 14:16'!\\nkeystroke: aChar\\n\\tkeystroke _ aChar! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 1/7/2004 09:11'!\\nlabel\\n\\t^ label! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 1/7/2004 09:12'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n!OBAction methodsFor: 'accessing' stamp: 'cwp 3/10/2004 23:40'!\\nwantsButton\\n\\t^ buttonLabel notNil! !\\n\\n\\n!OBAction methodsFor: 'evaluating' stamp: 'cwp 1/7/2004 18:22'!\\nperform: aSelector orSendTo: anObject\\n\\t^ self perform: aSelector! !\\n\\n!OBAction methodsFor: 'evaluating' stamp: 'cwp 6/4/2006 00:58'!\\ntrigger\\n\\t[self value]\\n\\t\\ton: OBAnnouncerRequest\\n\\t\\tdo: [:notification | notification resume: announcer].! !\\n\\n\\n!OBAction methodsFor: 'morphic' stamp: 'hpt 5/17/2004 17:00'!\\naddItemToMenu: aMenu\\n\\taMenu\\n\\t\\tadd: self labelWithKeystroke\\n\\t\\ttarget: self \\n\\t\\tselector: #trigger.\\n\\tPreferences menuWithIcons & self icon notNil\\n\\t\\tifTrue: [aMenu lastItem icon: self icon].\\n\\taMenu addBlankIconsIfNecessary: MenuIcons blankIcon.! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'cwp 7/8/2006 12:55'!\\nbuttonLabelMorph\\n\\t^ StringMorph \\n\\t\\tcontents: self buttonLabel \\n\\t\\tfont: Preferences standardButtonFont! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'cwp 7/8/2006 12:54'!\\nbuttonMorph\\n\\t^ (PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: nil\\n\\t\\taction: #trigger\\n\\t\\tlabel: #buttonLabelMorph)\\t\\n\\t\\t\\tonColor: Color lightGray lighter offColor: Color lightGray twiceLighter;\\n\\t\\t\\tborderWidth: 2;\\n\\t\\t\\tborderRaised;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\tsetBalloonText: label! !\\n\\n!OBAction methodsFor: 'morphic' stamp: 'hpt 5/17/2004 14:17'!\\nlabelWithKeystroke\\n\\t^keystroke\\n\\t\\tifNil: [label]\\n\\t\\tifNotNil: [label, ' (', keystroke asString, ')']! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAction class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 3/10/2004 23:36'!\\nlabel: aString buttonLabel: aString2 receiver: anObject selector: aSelector arguments: anArray\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tbuttonLabel: aString2! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 18:49'!\\nlabel: aString buttonLabel: aString2 receiver: anObject selector: aSelector \\narguments: anArray keystroke: aChar icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tbuttonLabel: aString2;\\n\\t\\tkeystroke: aChar;\\n\\t\\ticon: anIcon! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'cwp 1/7/2004 09:20'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) label: aString! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 16:50'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\ticon: anIcon! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 14:16'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray keystroke: aChar\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tkeystroke: aChar! !\\n\\n!OBAction class methodsFor: 'instance creation' stamp: 'hpt 5/17/2004 16:50'!\\nlabel: aString receiver: anObject selector: aSelector arguments: anArray keystroke: aChar icon: anIcon\\n\\t^ (self receiver: anObject selector: aSelector arguments: anArray) \\n\\t\\tlabel: aString;\\n\\t\\tkeystroke: aChar;\\n\\t\\ticon: anIcon! !\\nObject subclass: #OBActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n!OBActor commentStamp: 'cwp 1/7/2005 23:14' prior: 0!\\nActors provide the basic units of domain-related functionality. They are attached to metanodes, and supply the Actions used to build context menus and buttons in the browser. Actors can be proxies for functionality supplied by other classes, as in OBFileRegistryActor, or they may supply the funtionality them selves. \\n\\nOBActor is an abstract class which defines the protocol Actors must implement. Actors need not be subclasses of OBActor, however.!\\n\\n\\n!OBActor methodsFor: 'accessing' stamp: 'cwp 9/16/2004 23:25'!\\nactionWithLabel: aString selector: aSymbol \\n\\tself shouldBeImplemented! !\\n\\n\\n!OBActor methodsFor: 'public' stamp: 'cwp 2/4/2004 15:25'!\\nactionsForNode: aNode\\n\\t^#()! !\\n\\n!OBActor methodsFor: 'public' stamp: 'cwp 2/5/2004 20:12'!\\nactionsForParent: aNode\\n\\t^#()! !\\n\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:30'!\\ndeleteIcon\\n\\t^ MenuIcons tryIcons: #(deleteIcon smallDeleteIcon)! !\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:31'!\\nfindIcon\\n\\t^ MenuIcons tryIcons: #(findIcon smallFindIcon)! !\\n\\n!OBActor methodsFor: 'icons' stamp: 'cwp 7/10/2006 22:31'!\\nnewIcon\\n\\t^ MenuIcons tryIcons: #(newIcon smallNewIcon)! !\\nOBMethodCategoryNode subclass: #OBAllMethodCategoryNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBAllMethodCategoryNode commentStamp: 'cwp 1/8/2005 12:31' prior: 0!\\nOBAllMethodCategory implements the synthetic '-- all --' category, which contains all the methods in a class.!\\n\\n\\n!OBAllMethodCategoryNode methodsFor: 'accessing'!\\ncategory\\n\\t^ 'as yet unclassified'! !\\n\\n!OBAllMethodCategoryNode methodsFor: 'accessing'!\\nmethodReferences\\n\\t^ self theClass selectors asSortedArray \\n\\t\\tcollect: [:ea | MethodReference new setStandardClass: self theClass methodSymbol: ea]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAllMethodCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAllMethodCategoryNode class methodsFor: 'as yet unclassified'!\\non: className\\n\\t^ self on: '-- all --' inClass: className! !\\nObject subclass: #OBAnnouncement\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\nObject subclass: #OBAnnouncer\\n\\tinstanceVariableNames: 'subscriptions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/5/2006 00:39'!\\nannounce: anObject\\n\\n\\t| ann |\\n\\tann _ anObject asAnnouncement.\\n\\tsubscriptions keysAndValuesDo:\\n\\t\\t[:class :action |\\n\\t\\t(ann isKindOf: class) ifTrue: [action valueWithArguments: {ann}]].\\n\\t^ ann! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/3/2006 21:21'!\\nobserve: aClass do: aValuable \\n\\t| actions |\\n\\tactions _ subscriptions at: aClass ifAbsent: [ActionSequence new].\\n\\tsubscriptions at: aClass put: (actions copyWith: aValuable).! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/3/2006 23:31'!\\nobserve: aClass send: aSelector to: anObject\\n\\tself\\n\\t\\tobserve: aClass\\n\\t\\tdo: (MessageSend receiver: anObject selector: aSelector)! !\\n\\n!OBAnnouncer methodsFor: 'subscription' stamp: 'cwp 6/10/2006 00:40'!\\nunsubscribe: anObject\\n\\tsubscriptions keysAndValuesDo:\\n\\t\\t[:class :actions |\\n\\t\\tsubscriptions at: class put: (actions reject: [:ea | ea receiver == anObject])].\\n\\tsubscriptions keysAndValuesRemove: [:key :value | value isEmpty]! !\\n\\n\\n!OBAnnouncer methodsFor: 'initialize-release' stamp: 'cwp 4/17/2006 11:51'!\\ninitialize\\n\\tsubscriptions _ IdentityDictionary new.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBAnnouncer class\\n\\tinstanceVariableNames: ''!\\n\\n!OBAnnouncer class methodsFor: 'instance creation' stamp: 'cwp 6/4/2006 00:55'!\\ncurrent\\n\\t^ OBAnnouncerRequest signal! !\\n\\n!OBAnnouncer class methodsFor: 'instance creation' stamp: 'cwp 4/17/2006 11:50'!\\nnew\\n\\t^ self basicNew initialize! !\\nNotification subclass: #OBAnnouncerRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\nOBInteractionRequest subclass: #OBBrowseRequest\\n\\tinstanceVariableNames: 'browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBBrowseRequest commentStamp: 'cwp 12/7/2004 00:10' prior: 0!\\nThis notification is raised whenever a browser needs to be opened. The default action is to open a SystemWindow in Morphic, but it can be caught in situations where that's not appropriate. The OB test suite uses this extensively. !\\n\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 18:45'!\\nbrowser\\n\\t^ browser! !\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 18:45'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser! !\\n\\n!OBBrowseRequest methodsFor: 'accessing' stamp: 'cwp 10/17/2004 21:27'!\\ndefaultAction\\n\\t^ browser openInMorphic! !\\n\\n\\n!OBBrowseRequest methodsFor: 'testing' stamp: 'cwp 10/17/2004 19:32'!\\nisBrowseRequest\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBBrowseRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBBrowseRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 10/17/2004 18:45'!\\nsignal: aBrowser\\n\\t^ (self new browser: aBrowser) signal! !\\nObject subclass: #OBBrowser\\n\\tinstanceVariableNames: 'panels announcer'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBBrowser commentStamp: 'cwp 1/7/2005 23:17' prior: 0!\\nOBBrowser is the core of OmniBrower. It's the root object for each browser and the model for the SystemWindows which display them. Its main responsibily is managing panels, particularly passing update messages between them.\\n\\nOn the class side, OBBrowser provides some default settings for creating and opening browsers. Subclasses can override these settings to acheive customized behavior.\\n\\niVars:\\n\\npanels\\t- A collection of objects which manage submorphs of the browser's SystemWindow.\\n\\ncVars:\\n\\nMetaGraphs - A dictionary matching names to metagraphs!\\n\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 6/4/2006 00:36'!\\naddPanel: aPanel\\n\\tpanels add: aPanel.\\n\\taPanel browser: self.\\n! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:42'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 11/20/2004 21:00'!\\ncurrentNode\\n\\t^self navigationPanel currentNode! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 11/20/2004 21:00'!\\ncurrentOrRootNode\\n\\t^self navigationPanel currentOrRootNode! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 8/31/2004 13:04'!\\ndefaultLabel\\n\\t^ self class titleForRoot: self root! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 12/5/2004 16:25'!\\nnavigationPanel\\n\\t^ panels \\n\\t\\tdetect: [:ea | ea isNavigation] \\n\\t\\tifNone: [self error: 'No navigation panel configured']! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 9/17/2004 00:53'!\\npanels\\n\\t^ panels! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'cwp 6/28/2006 00:44'!\\nrequestor\\n\\t^ OBRequestor for: self! !\\n\\n!OBBrowser methodsFor: 'accessing' stamp: 'dvf 9/5/2005 17:30'!\\nselectionPath\\n\\t^self navigationPanel selectionPath! !\\n\\n\\n!OBBrowser methodsFor: 'callbacks' stamp: 'cwp 11/20/2004 21:05'!\\nlabelString\\n\\t| label |\\n\\tlabel := self navigationPanel labelString.\\n\\t^label \\n\\t\\tifNil: [self defaultLabel]\\n\\t\\tifNotNil: [self defaultLabel , ': ' , label]! !\\n\\n!OBBrowser methodsFor: 'callbacks' stamp: 'cwp 4/17/2006 19:52'!\\nokToChange\\n\\t^ (self announcer announce: OBAboutToChange) isVetoed not! !\\n\\n\\n!OBBrowser methodsFor: 'initializing' stamp: 'cwp 6/4/2006 14:09'!\\ninitialize\\n\\tpanels _ OrderedCollection new.\\n\\tannouncer _ OBAnnouncer new.\\n\\tself subscribe! !\\n\\n!OBBrowser methodsFor: 'initializing' stamp: 'cwp 12/5/2004 16:24'!\\nsetMetaNode: aMetaNode node: aNode \\n\\tself navigationPanel setMetaNode: aMetaNode node: aNode! !\\n\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/27/2004 22:21'!\\ndefaultBackgroundColor\\n\\t^ Color gray veryMuchLighter! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 12/5/2004 14:23'!\\nmorph\\n\\t| window |\\n\\twindow := SystemWindow labelled: self defaultLabel.\\n\\twindow model: self.\\n\\tpanels isEmpty ifFalse: [self morphicPanelLayout addMorphsTo: window].\\n\\t^window! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/21/2004 00:31'!\\nmorphicPanelLayout\\n\\t^ OBMorphicPanelLayout for: panels! !\\n\\n!OBBrowser methodsFor: 'morphic' stamp: 'cwp 11/21/2004 00:30'!\\nopenInMorphic\\n\\t^ self morph openInWorld! !\\n\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 11/20/2004 21:00'!\\njumpToRoot\\n\\t^self navigationPanel jumpToRoot! !\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 11/20/2004 21:00'!\\njumpTo: aNode \\n\\tself navigationPanel jumpTo: aNode! !\\n\\n!OBBrowser methodsFor: 'navigating' stamp: 'cwp 9/17/2005 17:48'!\\nroot\\n\\t^self navigationPanel root! !\\n\\n\\n!OBBrowser methodsFor: 'opening' stamp: 'cwp 10/17/2004 21:31'!\\nopen\\n\\t^ OBBrowseRequest signal: self! !\\n\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:29'!\\ndontTranscribe\\n\\tself announcer unsubscribe: self.\\n\\tself subscribe.! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 4/24/2006 15:10'!\\nrelabel: ann\\n\\tself changed: #relabel.\\n! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/4/2006 18:50'!\\nsignalRefresh\\n\\tself announcer announce: OBRefreshRequired! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/6/2006 00:25'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBSelectionChanged send: #relabel: to: self! !\\n\\n!OBBrowser methodsFor: 'updating' stamp: 'cwp 6/6/2006 00:26'!\\ntranscribe\\n\\tself announcer observe: OBAnnouncement do: [:ann | Transcript cr; show: ann].! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBBrowser class methodsFor: 'auto opening' stamp: 'cwp 12/6/2004 23:22'!\\nopen\\n\\t^ self new open! !\\n\\n!OBBrowser class methodsFor: 'auto opening' stamp: 'cwp 12/5/2004 17:03'!\\nopenRoot: rootNode selection: selectedNode\\n\\t^ (self root: rootNode selection: selectedNode) open! !\\n\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:10'!\\ndefaultMetaNode\\n\\tself subclassResponsibility! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/6/2004 23:20'!\\ndefaultRootNode\\n\\tself subclassResponsibility! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:10'!\\ndefinitionPanel\\n\\t^ OBDefinitionPanel new! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:01'!\\nmaxPanes\\n\\t^ self paneCount! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:00'!\\nminPanes\\n\\t^ self paneCount! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 16:55'!\\nnavigationPanel\\n\\t^ OBColumnPanel minPanes: self minPanes maxPanes: self maxPanes! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 11/26/2004 22:27'!\\noptionalButtonPanel\\n\\t| labels panel |\\n\\tlabels _ self optionalButtons.\\n\\t(Preferences optionalButtons and: [labels isEmpty not]) ifTrue: \\n\\t\\t[panel _ OBFixedButtonPanel new.\\n\\t\\tlabels do: [:ea | panel addButtonWithLabel: ea]].\\n\\t^ panel! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:07'!\\noptionalButtons\\n\\t^ #()! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:01'!\\npaneCount\\n\\t^ 4! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 15:06'!\\npanels\\n\\t^ {self navigationPanel. self optionalButtonPanel. self definitionPanel} \\n\\t\\treject: [:ea | ea isNil]! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 11:32'!\\ntitle\\n\\t^ 'OmniBrowser'! !\\n\\n!OBBrowser class methodsFor: 'configuration' stamp: 'cwp 8/31/2004 13:02'!\\ntitleForRoot: aNode\\n\\t^ self title! !\\n\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 18:12'!\\nmetaNode: metaNode node: rootNode \\n\\t^ self metaNode: metaNode root: rootNode selection: nil panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/17/2005 01:16'!\\nmetaNode: metaNode root: rootNode selection: selectedNode\\n\\t^ self metaNode: metaNode root: rootNode selection: selectedNode panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/6/2004 21:59'!\\nmetaNode: metaNode root: rootNode selection: selectedNode panels: panels\\n\\t| browser |\\n\\tbrowser _ self basicNew initialize.\\n\\tpanels do: [:ea | browser addPanel: ea].\\n\\tbrowser setMetaNode: metaNode node: rootNode.\\n\\tselectedNode ifNotNil: [browser jumpTo: selectedNode].\\n\\t^ browser! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/16/2005 23:25'!\\nnew\\n\\t^ self \\n\\t\\tmetaNode: self defaultMetaNode\\n\\t\\troot: self defaultRootNode\\n\\t\\tselection: nil\\n\\t\\tpanels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 15:26'!\\nroot: aNode \\n\\t^ self root: aNode selection: nil! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'avi 9/16/2005 23:25'!\\nroot: rootNode selection: selectedNode\\n\\t^ self metaNode: self defaultMetaNode root: rootNode selection: selectedNode panels: self panels! !\\n\\n!OBBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/6/2004 22:04'!\\nselection: selectedNode\\n\\t^ self root: self defaultRootNode selection: selectedNode! !\\n\\nObject subclass: #OBButtonModel\\n\\tinstanceVariableNames: 'bar label'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBButtonModel commentStamp: 'cwp 3/5/2004 12:15' prior: 0!\\nAn OBButtonModel serves as a model for PluggableButtonMorphs used OBRadioButtonBar. OBRadioButtonBar cannot be a direct model for its PBMs, since it can contain a variable number of buttons.\\n\\niVars:\\n\\nbar\\t\\t- the OBRadioButton bar to which this button belongs\\nlabel\\t- the label of the button!\\n\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 2/24/2004 18:29'!\\nbar: aRadioButtonBar\\n\\tbar _ aRadioButtonBar! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 3/2/2004 21:46'!\\nlabel\\n\\t^ label! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 2/24/2004 18:29'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n!OBButtonModel methodsFor: 'accessing' stamp: 'cwp 11/27/2004 00:50'!\\nselectionChanged\\n\\tself changed: #isSelected.\\n\\tself changed: #labelMorph! !\\n\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:42'!\\nisSelected\\n\\t^ bar isSelected: self! !\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/28/2006 10:45'!\\nlabelMorph\\n\\t^ (StringMorph \\n\\t\\tcontents: self label \\n\\t\\tfont: TextStyle defaultFont)\\n\\t\\t\\tcolor: (self isEnabled ifTrue: [Color black] ifFalse: [Color gray]);\\n\\t\\t\\tyourself! !\\n\\n!OBButtonModel methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 19:30'!\\npush\\n\\tbar push: self.! !\\n\\n\\n!OBButtonModel methodsFor: 'morphs' stamp: 'lr 3/23/2006 18:08'!\\nmorph\\n\\t| morph |\\n\\tmorph := PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: #isSelected\\n\\t\\taction: #push\\n\\t\\tlabel: #labelMorph.\\n\\tmorph \\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill.\\n\\t^ morph! !\\n\\n\\n!OBButtonModel methodsFor: 'testing' stamp: 'cwp 11/27/2004 19:09'!\\nisEnabled\\n\\t^ bar isEnabled: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBButtonModel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 8/29/2004 13:31'!\\noffColor\\n\\t^ Color lightGray twiceLighter! !\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 8/29/2004 13:30'!\\nonColor\\n\\t^ Color lightGray lighter! !\\n\\n!OBButtonModel class methodsFor: 'as yet unclassified' stamp: 'cwp 2/24/2004 18:35'!\\nwithLabel: aString inBar: aRadioButtonBar\\n\\t^ self new label: aString; bar: aRadioButtonBar! !\\nOBActor subclass: #OBCategoryActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n!OBCategoryActor commentStamp: 'cwp 1/7/2005 23:43' prior: 0!\\nOBCategory actor implements a number of actions useful for manipulating both class and method categories.!\\n\\n\\n!OBCategoryActor methodsFor: 'public' stamp: 'cwp 7/10/2006 21:33'!\\nactionsForNode: aNode\\n\\t^ Array\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'remove'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #remove:\\n\\t\\t\\t\\targuments: {aNode}\\n\\t\\t\\t\\tkeystroke: $x\\n\\t\\t\\t\\ticon: self deleteIcon)\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'rename...'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #rename:\\n\\t\\t\\t\\targuments: {aNode})! !\\n\\n!OBCategoryActor methodsFor: 'public' stamp: 'cwp 1/9/2005 11:30'!\\nactionsForParent: aNode\\n\\t| actions |\\n\\tactions _ self stdActionsForParent: aNode.\\n\\taNode organization \\n\\t\\t\\tisClassOrganizer ifTrue: [actions _ actions copyWith: (self categorizeActionFor: aNode)].\\n\\t^ actions! !\\n\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2005 19:20'!\\nalphabetizeCategoriesIn: aNode \\n\\taNode organization sortCategories.\\n\\taNode signalChildrenChanged! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2004 22:53'!\\ncategorizeIn: aClassOrganizer \\n\\t\\\"Categorize methods by looking in parent classes for a method category.\\\"\\n\\t| organizers |\\n\\torganizers := aClassOrganizer subject withAllSuperclasses collect: [:ea | ea organization].\\n\\t(aClassOrganizer listAtCategoryNamed: ClassOrganizer default) do: [:sel | | found |\\n\\t\\tfound := (organizers collect: [ :org | org categoryOfElement: sel])\\n\\t\\t\\tdetect: [:ea | ea ~= ClassOrganizer default and: [ ea ~= nil]]\\n\\t\\t\\tifNone: [].\\n\\t\\tfound ifNotNil: [aClassOrganizer classify: sel under: found]]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/20/2005 08:40'!\\ncreateIn: aNode\\n\\t| catName organization |\\n\\torganization := aNode organization.\\n\\tcatName := OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\t\\ttemplate: (self categoryTemplateFor: organization).\\n\\tcatName ifNotNil:\\t[organization addCategory: catName.\\n\\t\\t\\t\\t\\t\\t(aNode categoryNodeNamed: catName) signalSelection].! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2004 21:55'!\\nremoveEmptyCategoriesIn: anOrganizer \\n\\tanOrganizer removeEmptyCategories! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove: aNode\\n\\t| list choice |\\n\\tlist := aNode container organization listAtCategoryNamed: aNode name.\\n\\tlist isEmpty ifTrue: [^ aNode remove].\\n\\tchoice := OBConfirmationRequest prompt: 'Are you sure you want to\\nremove this category \\nand all its elements?' confirm: 'Remove'.\\n\\tchoice ifTrue: [^ aNode remove]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 9/18/2005 18:51'!\\nrename: aNode\\n\\t| category |\\n\\tcategory := OBTextRequest\\n\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\ttemplate: aNode name.\\n\\tcategory ifNotNil:\\t\\n\\t\\t[aNode container organization renameCategory: aNode name toBe: category.\\n\\t\\taNode signalChanged]! !\\n\\n!OBCategoryActor methodsFor: 'actions' stamp: 'cwp 6/4/2006 18:56'!\\nreorganizeCategoriesIn: anOrganizer\\n\\t| definition |\\n\\tdefinition _ OBOrganizationDefinition on: anOrganizer.\\n\\tdefinition signalChange.! !\\n\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 9/18/2004 23:52'!\\ncategorizeActionFor: aNode\\n\\t^ OBAction\\n\\t\\tlabel: 'categorize automatically'\\n\\t\\treceiver: self\\n\\t\\tselector: #categorizeIn:\\n\\t\\targuments: (Array with: aNode organization)! !\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 6/25/2006 17:36'!\\ncategoryTemplateFor: anOrganization\\n\\t^ anOrganization isClassOrganizer\\n\\t\\tifTrue: ['category name']\\n\\t\\tifFalse: ['Category-Name']! !\\n\\n!OBCategoryActor methodsFor: 'private' stamp: 'cwp 7/10/2006 21:49'!\\nstdActionsForParent: aNode\\n\\t^ Array\\n\\t\\twith: (OBAction \\n\\t\\t\\t\\tlabel: 'create category...'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #createIn:\\n\\t\\t\\t\\targuments: (Array with: aNode)\\n\\t\\t\\t\\ticon: self newIcon)\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'alphabetize categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #alphabetizeCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode))\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'remove empty categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #removeEmptyCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode organization))\\n\\t\\twith: (OBAction\\n\\t\\t\\t\\tlabel: 'reorganize categories'\\n\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\tselector: #reorganizeCategoriesIn:\\n\\t\\t\\t\\targuments: (Array with: aNode organization))\\n! !\\nObject subclass: #OBCategoryServant\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n\\n!OBCategoryServant methodsFor: 'private' stamp: 'cwp 6/25/2006 17:32'!\\ncategoryTemplateFor: anOrganization\\n\\t^ anOrganization isClassOrganizer\\n\\t\\tifTrue: ['category name']\\n\\t\\tifFalse: ['Category-Name']! !\\n\\n\\n!OBCategoryServant methodsFor: 'actions' stamp: 'cwp 6/29/2006 00:13'!\\ncreateCategory: aRequestor\\n\\t| catName organization node |\\n\\tnode _ aRequestor requestCurrentNode.\\n\\torganization _ node organization.\\n\\tcatName _ OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type new category name' \\n\\t\\t\\t\\t\\ttemplate: (self categoryTemplateFor: organization).\\n\\tcatName ifNotNil:\\t[organization addCategory: catName.\\n\\t\\t\\t\\t\\t\\taRequestor select: (node categoryNodeNamed: catName)].! !\\n\\n\\n!OBCategoryServant methodsFor: 'accessing' stamp: 'cwp 6/25/2006 17:25'!\\nservices\\n\\t| selectors |\\n\\tselectors _ self class organization listAtCategoryNamed: 'services'.\\n\\t^ selectors collect: [:ea | self perform: ea].\\n\\t! !\\n\\n\\n!OBCategoryServant methodsFor: 'services' stamp: 'cwp 6/30/2006 00:51'!\\nsvcCreateCategory\\n\\t^ (OBService action: (MessageSend receiver: self selector: #createCategory:))\\n\\t\\tcondition: [:req | req requestNode hasOrganization];\\n\\t\\tlabel: 'create category...'! !\\nOBAnnouncement subclass: #OBChildrenChanged\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBChildrenChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode\\n\\t^ node! !\\n\\n!OBChildrenChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBChildrenChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBChildrenChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:49'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBInteractionRequest subclass: #OBChoiceRequest\\n\\tinstanceVariableNames: 'prompt labels values lines'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBChoiceRequest commentStamp: 'cwp 3/5/2004 12:26' prior: 0!\\nThis notification is used to ask the user for to choose from a list of alternatives. Its defaultAction is to open a PopUpMenu. Test cases an intercept the notification and respond programmatically.\\n\\nprompt\\t- A string describing the choice the user is asked to make.\\nlabels\\t- A list of strings describing the alternatives.\\nvalues\\t- When the user chooses an alternative, the corresponding item from this list is returned!\\n\\n\\n!OBChoiceRequest methodsFor: 'initializing' stamp: 'cwp 7/9/2006 00:05'!\\nsetPrompt: aString labels: labelArray values: valueArray lines: lineArray\\n\\tprompt _ aString.\\n\\tlabels _ labelArray.\\n\\tvalues _ valueArray.\\n\\tlines _ lineArray.! !\\n\\n\\n!OBChoiceRequest methodsFor: 'signaling' stamp: 'cwp 7/9/2006 00:09'!\\ndefaultAction\\n\\t^ values \\n\\t\\tat: ((PopUpMenu labelArray: labels lines: lines) startUpWithCaption: prompt)\\n\\t\\tifAbsent: [nil]! !\\n\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nlabels\\n\\t^ labels! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/9/2006 00:11'!\\nlines\\n\\t^ lines! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nprompt\\n\\t^ prompt! !\\n\\n!OBChoiceRequest methodsFor: 'accessing' stamp: 'cwp 7/8/2006 23:45'!\\nvalues\\n\\t^ values! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBChoiceRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:07'!\\nlabels: anArray\\n\\t^ self\\n\\t\\tprompt: nil\\n\\t\\tlabels: anArray\\n\\t\\tvalues: anArray\\n\\t\\tlines: #()! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:08'!\\nlabels: labelArray lines: lineArray\\n\\t^ self\\n\\t\\tprompt: nil\\n\\t\\tlabels: labelArray\\n\\t\\tvalues: labelArray\\n\\t\\tlines: lineArray! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:06'!\\nprompt: aString labels: labelArray values: valueArray\\n\\t^ self\\n\\t\\tprompt: aString\\n\\t\\tlabels: labelArray\\n\\t\\t values: valueArray\\n\\t\\tlines: #()! !\\n\\n!OBChoiceRequest class methodsFor: 'signalling' stamp: 'cwp 7/9/2006 00:05'!\\nprompt: aString labels: labelArray values: valueArray lines: lineArray\\n\\t^ (self new \\n\\t\\tsetPrompt: aString \\n\\t\\tlabels: labelArray \\n\\t\\tvalues: valueArray \\n\\t\\tlines: lineArray) \\n\\t\\t\\tsignal! !\\nOBActor subclass: #OBClassActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n!OBClassActor commentStamp: 'cwp 1/7/2005 23:44' prior: 0!\\nOBClassActor provides basic actions for manipulating classes.!\\n\\n\\n!OBClassActor methodsFor: 'querying' stamp: 'cwp 7/10/2006 22:35'!\\nactionsForNode: aClassNode\\n\\t^ {OBAction\\n\\t\\t\\tlabel: 'remove' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #remove:\\n\\t\\t\\targuments: {aClassNode}\\n\\t\\t\\tkeystroke: $x \\n\\t\\t\\ticon: self deleteIcon.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'rename...' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #rename:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'copy...' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #copy:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'subclass template'\\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #subclassTemplate:\\n\\t\\t\\targuments: {aClassNode}.\\n\\t\\tOBAction\\n\\t\\t\\tlabel: 'browse references'\\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #browseReferences:\\n\\t\\t\\targuments: {aClassNode}\\n\\t}! !\\n\\n\\n!OBClassActor methodsFor: 'private' stamp: 'lr 3/28/2006 12:05'!\\nbrowseObsoleteRefs: aClassNode as: oldName \\n\\t| binding |\\n\\tbinding := aClassNode theNonMetaClass environment \\n\\t\\t\\t\\tassociationAt: aClassNode theNonMetaClass name.\\n\\t(SystemNavigation default allCallsOn: binding) isEmpty \\n\\t\\tifFalse: [OBReferencesBrowser\\n\\t\\t\\t\\t\\tbrowseRoot: aClassNode\\n\\t\\t\\t\\t\\ttitle: 'Obsolete references to']! !\\n\\n!OBClassActor methodsFor: 'private' stamp: 'cwp 7/8/2006 13:59'!\\ncopyClass: oldClass as: newName\\n\\t| oldDefinition newDefinition newClass |\\n\\t(oldClass environment hasClassNamed: newName)\\n\\t\\tifTrue: [^self error: newName, ' already exists'].\\n\\toldDefinition := oldClass definition.\\n\\tnewDefinition := oldDefinition \\n\\t\\t\\t\\t\\t\\tcopyReplaceAll: '#' , oldClass name asString \\n\\t\\t\\t\\t\\t\\twith: '#' , newName asString.\\n\\tCursor wait \\n\\t\\tshowWhile: [newClass := Compiler evaluate: newDefinition logged: true.\\n\\t\\t\\t\\t\\tnewClass copyAllCategoriesFrom: oldClass.\\n\\t\\t\\t\\t\\tnewClass class copyAllCategoriesFrom: oldClass class].\\n\\t^ newClass! !\\n\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:10'!\\nbrowseReferences: aClassNode \\n\\tOBReferencesBrowser browseRoot: aClassNode theNonMetaClass asNode! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'dvf 8/31/2005 13:11'!\\ncopy: aClassNode\\n\\t| newName newClass |\\n\\tnewName := OBTextRequest\\n\\t\\t\\tprompt: 'Please type new class name'\\n\\t\\t\\ttemplate: aClassNode theNonMetaClassName asString.\\n\\tnewName ifNotNil:\\t[newClass := self\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopyClass: aClassNode theNonMetaClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tas: newName asSymbol.\\n\\t\\t\\t\\t\\t\\t(newClass asNode) signalSelection].! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:04'!\\nremove: aClassNode\\n\\t(OBConfirmationRequest\\n\\t\\tprompt: 'Are you certain that you \\nwant to REMOVE the class ', aClassNode theNonMetaClassName, ' from the system?'\\n\\t\\tconfirm: 'Remove')\\n\\t\\t\\tifTrue: [aClassNode theNonMetaClass removeFromSystem.\\n\\t\\t\\t\\t\\taClassNode signalDeletion]! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'lr 3/28/2006 12:05'!\\nrename: aClassNode\\n\\t| newName |\\n\\tnewName := OBTextRequest\\n\\t\\t\\t\\t\\tprompt: 'Please type new class name' \\n\\t\\t\\t\\t\\ttemplate: aClassNode theNonMetaClassName asString.\\n\\tnewName ifNotNil:\\t[ | oldName |\\n\\t\\t\\t\\t\\t\\toldName := aClassNode theNonMetaClass name.\\n\\t\\t\\t\\t\\t\\taClassNode theNonMetaClass environment \\n\\t\\t\\t\\t\\t\\t\\trenameClassNamed: oldName\\n\\t\\t\\t\\t\\t\\t\\tas: newName asSymbol.\\n\\t\\t\\t\\t\\t\\tself browseObsoleteRefs: aClassNode as: oldName].\\n\\t! !\\n\\n!OBClassActor methodsFor: 'actions' stamp: 'cwp 6/4/2006 18:53'!\\nsubclassTemplate: aClassNode \\n\\t| class definition |\\n\\tclass _ aClassNode theNonMetaClass.\\n\\tdefinition _ (OBClassDefinition \\n\\t\\t\\t\\t\\tenvironment: class environment \\n\\t\\t\\t\\t\\ttemplate: (Class \\n\\t\\t\\t\\t\\t\\t\\t\\ttemplateForSubclassOf: class \\n\\t\\t\\t\\t\\t\\t\\t\\tcategory: class category)).\\n\\tdefinition signalChange.! !\\nOBCodeNode subclass: #OBClassAwareNode\\n\\tinstanceVariableNames: 'theClass superior'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassAwareNode commentStamp: 'cwp 1/8/2005 11:23' prior: 0!\\nOBClassAware node models program elements that are part of a class. It provides methods for manipulating the class, as well as methods relating to sorting according to class hierarchy.\\n\\niVars\\n\\ntheClass \\t- the class that this node is part of\\nsuperior \\t- during hierarchical sorting this refers to the nearest superclass\\n\\t\\t\\t that belongs to the group being sorted!\\n\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:04'!\\nadoptSuperior: other \\n\\t| descent |\\n\\tdescent := self theClass allSuperclasses reversed.\\n\\t(descent indexOf: other theClass) > (descent indexOf: self superiorClass) \\n\\t\\tifTrue: [superior := other]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:04'!\\nsortsBefore: aClassNode\\n\\t| own other |\\n\\town := self withSuperiors.\\n\\tother := aClassNode withSuperiors.\\n\\t1 \\tto: (own size min: other size)\\n\\t\\tdo: [:i | (own at: i) == (other at: i) ifFalse: \\n\\t\\t\\t\\t[^ (own at: i) theClassName <= (other at: i) theClassName]].\\n\\t^ other includes: self\\n\\t! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperior\\n\\t^ superior! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiorClass\\n\\t^superior ifNotNil: [superior theClass]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiors\\n\\t| result |\\n\\tresult := OrderedCollection new.\\n\\tself superiorsDo: [:ea | result add: ea].\\n\\t^ result asArray reversed! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nsuperiorsDo: aBlock\\n\\t| cursor |\\n\\tcursor := superior.\\n\\t[cursor isNil] whileFalse:\\n\\t\\t[aBlock value: cursor.\\n\\t\\tcursor := cursor superior]! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'dvf 8/16/2005 17:23'!\\nsuperior: other \\n\\tsuperior := other! !\\n\\n!OBClassAwareNode methodsFor: 'superiors' stamp: 'cwp 12/11/2004 22:03'!\\nwithSuperiors\\n\\t| result |\\n\\tresult := OrderedCollection new.\\n\\tresult add: self.\\n\\tself superiorsDo: [:ea | result add: ea].\\n\\t^ result asArray reversed! !\\n\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'lr 3/6/2006 19:24'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'lr 3/6/2006 19:22'!\\nbrowseHierarchically\\n\\tOBHierarchyBrowser openOnClass: self theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:10'!\\nbrowseHierarchyAction\\n\\t^ self \\n\\t\\taction: #browseHierarchically \\n\\t\\tbuttonLabel: 'hierarchy' \\n\\t\\tmenuLabel: 'browse hierarchy'.\\n! !\\n\\n!OBClassAwareNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:34'!\\nchaseVars\\n\\tOBVariablesBrowser browseRoot: self classNode! !\\n\\n\\n!OBClassAwareNode methodsFor: 'nodes' stamp: 'dvf 8/31/2005 13:11'!\\nclassNode\\n\\t^self theClass asNode! !\\n\\n\\n!OBClassAwareNode methodsFor: 'displaying' stamp: 'dvf 8/17/2005 14:59'!\\nindent\\n\\t| size indent |\\n\\tsize := 0.\\n\\tself superiorsDo: [:ea | size := size + 1].\\n\\tindent := Text new: size * 2.\\n\\tindent atAllPut: $ .\\n\\t^ indent! !\\n\\n!OBClassAwareNode methodsFor: 'displaying' stamp: 'cwp 1/7/2005 22:21'!\\nindentedName\\n\\t^ self indent, self name! !\\n\\n\\n!OBClassAwareNode methodsFor: 'ancestry' stamp: 'cwp 12/5/2004 12:56'!\\nisDescendantOfClassCat: aClassCategoryNode\\n\\n\\t\\\"optimized version: sending #category to the class is slow\\\"\\n\\t^ (self theNonMetaClass environment organization \\n\\t\\tlistAtCategoryNamed: aClassCategoryNode name)\\n\\t\\t\\tincludes: self theNonMetaClassName\\n\\n! !\\n\\n!OBClassAwareNode methodsFor: 'ancestry'!\\nisDescendantOfClass: aClassNode\\n\\t^ self theClassName = aClassNode theClassName! !\\n\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClass\\n\\t^ theClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClassName\\n\\t^ self theClass name! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheClass: aClass\\n\\ttheClass := aClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheMetaClass\\n\\t^ self theClass theMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheNonMetaClass\\n\\t^ self theClass theNonMetaClass! !\\n\\n!OBClassAwareNode methodsFor: 'accessing'!\\ntheNonMetaClassName\\n\\t^ self theNonMetaClass name! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassAwareNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassAwareNode class methodsFor: 'sorting' stamp: 'cwp 12/12/2004 22:13'!\\nsortHierarchically: nodes\\n\\tnodes do: [:a | nodes do: [:b | a adoptSuperior: b]].\\n\\tnodes sort: [:a : b | a sortsBefore: b].\\n\\t^ nodes! !\\nOBCodeNode subclass: #OBClassCategoryNode\\n\\tinstanceVariableNames: 'environment name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassCategoryNode commentStamp: 'cwp 1/8/2005 12:58' prior: 0!\\nOBClassCategory represents a system category in the image's SystemOrganization.!\\n\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:40'!\\nactions\\n\\t^ {\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t}\\n! !\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:44'!\\nbrowse\\n\\tOBSystemBrowser openOnEnvironment: environment category: name! !\\n\\n!OBClassCategoryNode methodsFor: 'actions'!\\nfileOut\\n\\tenvironment organization fileOutCategory: name.! !\\n\\n!OBClassCategoryNode methodsFor: 'actions'!\\nprintOut\\n\\tenvironment organization fileOutCategory: name asHtml: true! !\\n\\n!OBClassCategoryNode methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove\\n\\tenvironment organization removeSystemCategory: name.\\n\\tself signalDeletion! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfClassCat:! !\\n\\n!OBClassCategoryNode methodsFor: 'ancestry'!\\nisDescendantOfClassCat: other\\n\\t^ other name = name! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/15/2005 17:31'!\\nclasses\\n\\t^ self classNames collect: [:ea | (environment at: ea) asNode]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:12'!\\nclassesHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self classes! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/17/2005 17:25'!\\ncomments\\n\\t^ self classNames collect: [:ea | (environment at: ea) asCommentNode ]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:19'!\\ncommentsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self comments! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/15/2005 17:52'!\\nmetaclasses\\n\\t^self classNames collect: [:ea | (environment at: ea) asClassSideNode]! !\\n\\n!OBClassCategoryNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 22:19'!\\nmetaclassesHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self metaclasses! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'private'!\\nclassNames\\n\\t^ environment organization listAtCategoryNamed: name! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'accessing' stamp: 'cwp 9/22/2004 22:13'!\\ncontainer\\n\\t^ environment! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\ndefinition\\n\\t^ OBClassDefinition \\n\\t\\tenvironment: environment \\n\\t\\ttemplate: ((environment at: #Class) template: name)! !\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\nname\\n\\t^ name! !\\n\\n!OBClassCategoryNode methodsFor: 'displaying'!\\ntext\\n\\t^ 'Object subclass: #NameOfSubclass\\n\\tinstanceVariableNames: ''''\\n\\tclassVariableNames: ''''\\n\\tpoolDictionaries: ''''\\n\\tcategory: ''', self name, ''''! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'drag and drop'!\\ndropSelector\\n\\t^ #dropOnClassCategory:! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'class creation'!\\nisRedefinedBy: definition\\n\\t\\\"No class is selected, so the definition can't be a redefinition.\\\"\\n\\t\\n\\t^ false! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'initializing'!\\nsetName: aString\\n\\tself setName: aString environment: self class environment! !\\n\\n!OBClassCategoryNode methodsFor: 'initializing'!\\nsetName: aString environment: anEnvironment\\n\\tname := aString asSymbol.\\n\\tenvironment := anEnvironment! !\\n\\n\\n!OBClassCategoryNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:42'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassCategoryNode class methodsFor: 'actions'!\\nactionsForParent: aNode\\n\\t^ Array with: (OBAction\\n\\t\\t\\t\\t\\t\\tlabel: 'find class...'\\n\\t\\t\\t\\t\\t\\treceiver: self\\n\\t\\t\\t\\t\\t\\tselector: #findClassIn:\\n\\t\\t\\t\\t\\t\\targuments: (Array with: aNode environment)\\n\\t\\t\\t\\t\\t\\tkeystroke: $f)\\n! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'dvf 8/31/2005 11:33'!\\nfindClassIn: anEnvironment\\n\\t| pattern class |\\n\\tpattern := OBTextRequest \\n\\t\\t\\t\\t\\tprompt: 'Please type the name or fragment to look for' \\n\\t\\t\\t\\t\\ttemplate: ''.\\n\\tpattern ifNil: [^self].\\n\\tclass := self findClassIn: anEnvironment pattern: pattern.\\n\\tclass ifNotNil: [(class asNode) signalSelection].! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'cwp 7/14/2006 14:37'!\\nfindClassIn: anEnvironment pattern: pattern\\n\\t| classNames className toMatch potentialClassNames |\\n\\ttoMatch := (pattern copyWithout: $.) asLowercase.\\n\\tpotentialClassNames := (anEnvironment classNames , anEnvironment traitNames) asArray.\\n\\tclassNames := (pattern endsWith: '.')\\n\\t\\t\\t\\t\\tifTrue: [potentialClassNames\\n\\t\\t\\t\\t\\t\\t\\tselect: [:nm | nm asLowercase = toMatch]]\\n\\t\\t\\t\\t\\tifFalse: [potentialClassNames\\n\\t\\t\\t\\t\\t\\t\\tselect: [:n | n includesSubstring: toMatch caseSensitive: false]].\\n\\tclassNames size = 0 ifTrue: [^ nil].\\n\\tclassNames size = 1 ifTrue: [^ anEnvironment at: classNames first asSymbol].\\n\\tclassName := self userSelectionOf: classNames for: toMatch.\\n\\t^ className ifNotNil: [anEnvironment at: className asSymbol]\\n! !\\n\\n!OBClassCategoryNode class methodsFor: 'actions' stamp: 'cwp 7/9/2006 00:10'!\\nuserSelectionOf: classNames for: toMatch \\n\\t| exactMatch labels lines |\\n\\texactMatch := classNames detect: [:ea | ea asLowercase = toMatch] ifNone: [nil].\\n\\texactMatch \\n\\t\\tifNil: [labels _ classNames. lines _ #()]\\n\\t\\tifNotNil: [labels _ classNames copyWithFirst: exactMatch. lines _ #(1)].\\n\\t^ OBChoiceRequest labels: labels lines: lines.! !\\n\\n\\n!OBClassCategoryNode class methodsFor: 'instance creation'!\\non: aString\\n\\t^ self new setName: aString! !\\n\\n!OBClassCategoryNode class methodsFor: 'instance creation'!\\non: aString inEnvironment: anEnvironment\\n\\t^ self new setName: aString environment: anEnvironment! !\\nOBClassAwareNode subclass: #OBClassCommentNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassCommentNode commentStamp: 'cwp 1/8/2005 11:24' prior: 0!\\nOBClassCommentNode represents the comment attached to a particular class. !\\n\\n\\n!OBClassCommentNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:03'!\\nactions\\n\\t^ {\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'\\n\\t}! !\\n\\n\\n!OBClassCommentNode methodsFor: 'public' stamp: 'cwp 12/13/2004 00:51'!\\nname\\n\\t^ self theClass name! !\\n\\n\\n!OBClassCommentNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tself theClass: aClass! !\\n\\n\\n!OBClassCommentNode methodsFor: 'definition'!\\ntext\\n\\t^ self theClass comment! !\\n\\n!OBClassCommentNode methodsFor: 'definition'!\\ntext: aText\\n\\tself theClass comment: aText stamp: Utilities changeStamp.\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassCommentNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassCommentNode class methodsFor: 'as yet unclassified'!\\non: classRef\\n\\t^ self new setClass: classRef! !\\nOBDefinition subclass: #OBClassDefinition\\n\\tinstanceVariableNames: 'environment template'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBClassDefinition commentStamp: 'cwp 1/8/2005 13:13' prior: 0!\\nOBClassDefinition presents a textual interface for examining, modifying and creating classes. Given a class, it knows how to display the definition expression that reflects it's current state, and knows how to create or modify a class given a definition expression.\\n\\nOBClassDefinition implements a number of safety checks when defining or redefining classes, to ensure that existing classes are not accidentally overwritten.!\\n\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\naccept: aText notifying: aController\\n\\t^ self defineClass: aText notifying: aController! !\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBClassDefinition methodsFor: 'callbacks'!\\ntext\\n\\t^ template! !\\n\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nconfirmDefinition: definition\\n\\t\\\"Check to make sure the user isn't accidentally over-writing an existing class.\\\"\\n\\t\\n\\t(((self isRedefinition: definition) not) and: [self definedClassExists: definition])\\n\\t\\tifTrue: [^ self confirmRedefinition: definition]\\n\\t\\tifFalse: [^ true]! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nconfirmRedefinition: definition\\n\\t| newName prompt |\\n\\tnewName := self nameOfClassDefinedBy: definition.\\n\\tprompt := (newName, ' is an existing class in this system.\\nRedefining it might cause serious problems.\\nIs this really what you want to do?') asText.\\n\\t^ OBConfirmationRequest\\n\\t\\tprompt: prompt\\n\\t\\tconfirm: 'Redefine'! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\ndefinedClassExists: definition\\n\\t^ environment hasClassNamed: (self nameOfClassDefinedBy: definition)! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nisRedefinition: aDefinition\\n\\t^ (self nameOfClassDefinedBy: aDefinition) = (self nameOfClassDefinedBy: template)! !\\n\\n!OBClassDefinition methodsFor: 'confirmation'!\\nnameOfClassDefinedBy: definition\\n\\t^ (Scanner new scanTokens: definition) third! !\\n\\n!OBClassDefinition methodsFor: 'confirmation' stamp: 'cwp 10/18/2004 00:13'!\\nselectedClass\\n\\t^ environment at: (self nameOfClassDefinedBy: template) ifAbsent: [nil]! !\\n\\n\\n!OBClassDefinition methodsFor: 'class definition'!\\ndefineClass: definition notifying: aController\\n\\t| evaluator newClass |\\n\\t(self confirmDefinition: definition) ifFalse: [^ false].\\n\\tevaluator := self evaluatorForDefinition: definition.\\n\\tnewClass := evaluator\\n\\t\\t\\t\\tevaluate: definition\\n\\t\\t\\t\\tnotifying: aController\\n\\t\\t\\t\\tlogged: true.\\n\\tnewClass ifNil: [^ false].\\n\\tself signalSelectionOf: newClass.\\n\\t^ true\\n! !\\n\\n!OBClassDefinition methodsFor: 'class definition'!\\nevaluatorForDefinition: definition\\n\\t| tokens |\\n\\ttokens := Scanner new scanTokens: definition.\\n\\t^ (environment at: tokens first ifAbsent: [nil]) subclassDefinerClass! !\\n\\n!OBClassDefinition methodsFor: 'class definition' stamp: 'cwp 10/23/2005 14:42'!\\nsignalSelectionOf: aClass\\n\\taClass asNode demandSelection! !\\n\\n\\n!OBClassDefinition methodsFor: 'initializing'!\\nsetEnvironment: anEnvironment template: aText\\n\\tenvironment := anEnvironment.\\n\\ttemplate := aText.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassDefinition class methodsFor: 'instance creation'!\\nenvironment: anEnvironment template: aString \\n\\t^ self new setEnvironment: anEnvironment template: aString! !\\nOBClassAwareNode subclass: #OBClassNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassNode commentStamp: 'cwp 1/8/2005 11:27' prior: 0!\\nOBClassNode wraps a class for display in various types of code browsers. It provides many navigation methods for the different types of browsers where classes may appear.!\\n\\n\\n!OBClassNode methodsFor: 'actions' stamp: 'cwp 7/10/2006 22:33'!\\nactions\\n\\t^ {\\n\\t\\tself action: #findMethod \\n\\t\\t\\twithLabel: 'find method...' \\n\\t\\t\\twithKeystroke: $f \\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'.\\n\\t\\tself action: #inspectInstances withLabel: 'inspect instances'.\\n\\t\\tself action: #inspectSubInstances withLabel: 'inspect subinstances'\\n\\t}! !\\n\\n!OBClassNode methodsFor: 'actions' stamp: 'cwp 10/26/2004 00:49'!\\nfileOut\\n\\tself theNonMetaClass fileOut! !\\n\\n!OBClassNode methodsFor: 'actions'!\\nfindMethod\\n\\t| selectors selection |\\n\\tselectors := self theClass selectors asSortedArray.\\n\\tselectors isEmpty ifTrue: [^nil].\\n\\tselection := OBChoiceRequest labels: selectors.\\n\\tselection ifNotNil: [(OBMethodNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: selection\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinClass: self theClass) signalSelection].! !\\n\\n!OBClassNode methodsFor: 'actions'!\\ninspectInstances\\n\\tself theNonMetaClass inspectAllInstances! !\\n\\n!OBClassNode methodsFor: 'actions'!\\ninspectSubInstances\\n\\tself theNonMetaClass inspectSubInstances! !\\n\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 23:05'!\\nallCategory\\n\\t^ Array with: (OBAllMethodCategoryNode on: self theClass)! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 23:06'!\\ncategories\\n\\t^ self theClass organization categories\\n\\t\\tcollect: [:cat | OBMethodCategoryNode on: cat inClass: self theClass]\\n\\t\\t\\t! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:31'!\\nclassHierarchy\\n\\t^ self nodeHierarchyWithClass: OBClassNode! !\\n\\n!OBClassNode methodsFor: 'navigating'!\\nclassVariables\\n\\t^ self theClass allClassVarNames asArray sort\\n\\t\\tcollect: [:ea | OBClassVariableNode on: ea inClass: self theClass]! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:31'!\\ncommentHierarchy\\n\\t^ self nodeHierarchyWithClass: OBClassCommentNode! !\\n\\n!OBClassNode methodsFor: 'navigating'!\\ninstanceVariables\\n\\t^ self theClass allInstVarNames asArray sort\\n\\t\\tcollect: [:ea | OBInstanceVariableNode on: ea inClass: self theClass]! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:30'!\\nmetaclassHierarchy\\n\\t^ self nodeHierarchyWithClass: OBMetaclassNode! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/12/2004 23:30'!\\nnodeHierarchyWithClass: aClass\\n\\t^ OBClassAwareNode sortHierarchically: \\n\\t\\t(self surroundingHierarchy collect: [:ea | aClass on: ea])! !\\n\\n!OBClassNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:45'!\\nusers\\n\\t^ (SystemNavigation default allCallsOn: (theClass environment associationAt: theClass name))\\n\\t\\tcollect: [:ref | OBClassRefNode on: self name inMethod: ref]! !\\n\\n\\n!OBClassNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfClass:! !\\n\\n\\n!OBClassNode methodsFor: 'nodes' stamp: 'cwp 9/20/2005 08:42'!\\ncategoryNodeNamed: aString \\n\\t^ OBMethodCategoryNode on: aString inClass: theClass! !\\n\\n!OBClassNode methodsFor: 'nodes'!\\nclassCategoryNode\\n\\t^ OBClassCategoryNode \\n\\t\\ton: self theNonMetaClass category\\n\\t\\tinEnvironment: self theClass environment! !\\n\\n\\n!OBClassNode methodsFor: 'accessing'!\\ndefinition\\n\\t^ OBClassDefinition \\n\\t\\tenvironment: self theClass environment \\n\\t\\ttemplate: self theClass definition! !\\n\\n!OBClassNode methodsFor: 'accessing'!\\norganization\\n\\t^ self theClass organization! !\\n\\n!OBClassNode methodsFor: 'accessing' stamp: 'cwp 12/12/2004 23:27'!\\nsurroundingHierarchy\\n\\t ^ (self theClass withAllSuperclasses union: self theClass allSubclasses)\\n\\t\\tasArray! !\\n\\n!OBClassNode methodsFor: 'accessing' stamp: 'cwp 12/12/2004 22:45'!\\n= other\\n\\tself species = other species ifFalse: [^ false].\\n\\t^ self theClass = other theClass! !\\n\\n\\n!OBClassNode methodsFor: 'drag and drop' stamp: 'lr 3/28/2006 18:29'!\\ndropOnClassCategory: aNode\\n\\tself theNonMetaClass category: aNode name.\\n\\tself signalSelection.\\n\\t^ true! !\\n\\n!OBClassNode methodsFor: 'drag and drop' stamp: 'lr 4/6/2006 11:31'!\\ndropSelector\\n\\t^ #dropOnClass:! !\\n\\n\\n!OBClassNode methodsFor: 'displaying' stamp: 'cwp 12/13/2004 00:51'!\\nname\\n\\t^ self theClass name! !\\n\\n!OBClassNode methodsFor: 'displaying'!\\ntitle\\n\\t^ self name! !\\n\\n\\n!OBClassNode methodsFor: 'printing' stamp: 'cwp 12/10/2004 23:53'!\\nprintOn: aStream\\n\\taStream\\n\\t\\tprint: self class;\\n\\t\\tnextPut: $<;\\n\\t\\tprint: self theClass;\\n\\t\\tnextPut: $>! !\\n\\n\\n!OBClassNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tself theClass: aClass! !\\n\\n\\n!OBClassNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:57'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassNode class methodsFor: 'instance creation' stamp: 'cwp 11/30/2004 21:06'!\\non: aClass \\n\\t^ self new setClass: aClass ! !\\nOBMethodNode subclass: #OBClassRefNode\\n\\tinstanceVariableNames: 'className'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassRefNode commentStamp: 'cwp 1/8/2005 12:38' prior: 0!\\nEach instance of OBClassRefNode refers to a reference to a particular class from the source code of a method. It's used in the OBListBrowser created by the 'browse references' class action.!\\n\\n\\n!OBClassRefNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 22:14'!\\nname\\n\\t^ className! !\\n\\n!OBClassRefNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 01:16'!\\nselection\\n\\t| start parser |\\n\\t(parser _ Compiler parserClass new) parseSelector: self source.\\n\\tstart := parser endOfLastToken.\\n\\tstart := (self source asString findString: className startingAt: start).\\n\\t^ start to: start + className size - 1! !\\n\\n\\n!OBClassRefNode methodsFor: 'initialize-release' stamp: 'cwp 12/1/2004 01:10'!\\nsetClassName: theName reference: aMethodRef\\n\\tself setReference: aMethodRef.\\n\\tclassName := theName.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassRefNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassRefNode class methodsFor: 'as yet unclassified' stamp: 'cwp 12/1/2004 00:50'!\\non: aClassName inMethod: aMethodRef\\n\\t^ self new setClassName: aClassName reference: aMethodRef! !\\nObject subclass: #OBClassReference\\n\\tinstanceVariableNames: 'name isMeta'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBClassReference commentStamp: 'cwp 1/8/2005 13:15' prior: 0!\\nOBClassReference provides a way to refer to classes that may or may not be loaded into the image. It refers to the class indirectly, via name, rather than with a direct pointer to the class object. It also provides a number of convenience methods, which makes it more convenient than using the class name directly.!\\n\\n\\n!OBClassReference methodsFor: 'accessing'!\\nbeMeta\\n\\tisMeta := true! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\nbeNonMeta\\n\\tisMeta := false! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\nname\\n\\t^ isMeta\\n\\t\\tifTrue: [name, ' class']\\n\\t\\tifFalse: [name]! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheClass\\n\\t| theClass |\\n\\ttheClass := self theNonMetaClass ifNil: [^ nil].\\n\\t^ isMeta\\n\\t\\tifFalse: [theClass]\\n\\t\\tifTrue: [theClass class]! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaClass\\n\\t^ Smalltalk at: name ifAbsent: [].! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaName\\n\\t^ name! !\\n\\n!OBClassReference methodsFor: 'accessing'!\\ntheNonMetaName: aSymbol\\n\\tname := aSymbol! !\\n\\n\\n!OBClassReference methodsFor: 'comparing'!\\nhash\\n\\t^ isMeta\\n\\t\\tifTrue: [name hash bitInvert]\\n\\t\\tifFalse: [name hash]! !\\n\\n!OBClassReference methodsFor: 'comparing'!\\n<= other\\n\\t^ self name <= other name! !\\n\\n!OBClassReference methodsFor: 'comparing'!\\n= other\\n\\t^ (other isKindOf: self class) \\n\\t\\tand: [name = other theNonMetaName] \\n\\t\\tand: [isMeta = other isMeta]! !\\n\\n\\n!OBClassReference methodsFor: 'testing'!\\nisMeta\\n\\t^ isMeta! !\\n\\n\\n!OBClassReference methodsFor: 'printing'!\\nprintOn: aStream\\n\\taStream nextPutAll: 'OBClassReference'.\\n\\taStream nextPut: $<.\\n\\taStream nextPutAll: name.\\n\\tisMeta ifTrue: [aStream nextPutAll: ' class'].\\n\\taStream nextPut: $>.! !\\n\\n\\n!OBClassReference methodsFor: 'converting'!\\nreferenceToMethod: aSelector\\n\\t| ref |\\n\\tref := MethodReference new.\\n\\tref setClassSymbol: name classIsMeta: isMeta methodSymbol: aSelector stringVersion: ''.\\n\\t^ ref! !\\n\\n\\n!OBClassReference methodsFor: 'initializing'!\\nsetName: aSymbol\\n\\tname := (aSymbol copyUpTo: $ ) asSymbol.\\n\\tisMeta := aSymbol endsWith: ' class'.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBClassReference class\\n\\tinstanceVariableNames: ''!\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nmetaNamed: aSymbol\\n\\t^ (self named: aSymbol) beMeta! !\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nnamed: aSymbol\\n\\t^ self new setName: aSymbol! !\\n\\n!OBClassReference class methodsFor: 'instance creation'!\\nto: aClass\\n\\t^ self named: aClass name! !\\nOBVariableNode subclass: #OBClassVariableNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBClassVariableNode commentStamp: 'cwp 1/8/2005 12:51' prior: 0!\\nOBClassVariable provides a method for finding methods which refer to a shared variable, ie, by searching for an association in the literal frame rather than for bytecodes refering to an instance variable.!\\n\\n\\n!OBClassVariableNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:47'!\\naccessors\\n\\t| literal |\\n\\tliteral := (self theClass withAllSuperclasses \\n\\t\\t\\t\\tgather: [:ea | ea classPool associations])\\n\\t\\t\\t\\t\\tdetect: [:ea | ea key = name].\\n\\t^ ((self systemNavigation allCallsOn: literal) asArray sort)\\n\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\nOBBrowser subclass: #OBCodeBrowser\\n\\tinstanceVariableNames: 'hasChanges'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBCodeBrowser commentStamp: 'cwp 1/7/2005 23:45' prior: 0!\\nOBCodeBrowser is a superclass for all browsers which active code in the image. It provides methods for registering with the SystemChangeNotifier and updating it's display when it receives notification of system changes.!\\n\\n\\n!OBCodeBrowser methodsFor: 'morphic' stamp: 'cwp 1/8/2005 21:55'!\\naddModelItemsToWindowMenu: aMenu\\n\\tSmalltalk \\n\\t\\tat: #SystemBrowser \\n\\t\\tifPresent: [:class | class \\n\\t\\t\\t\\t\\t\\t\\t\\taddRegistryMenuItemsTo: aMenu \\n\\t\\t\\t\\t\\t\\t\\t\\tinAccountOf: OBSystemBrowserAdaptor new].! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\ninitialExtent\\n\\thasChanges := false.\\n\\tself register.\\n\\t^ super initialExtent! !\\n\\n!OBCodeBrowser methodsFor: 'morphic' stamp: 'cwp 6/4/2006 18:51'!\\nstepAt: milliseconds in: aSystemWindow\\n\\thasChanges ifTrue: [self signalRefresh].\\n\\tself clearChanges! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\nwantsStepsIn: aSystemWindow\\n\\t^ true! !\\n\\n!OBCodeBrowser methodsFor: 'morphic'!\\nwindowIsClosing\\n\\tself unregister! !\\n\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 1/7/2005 23:47'!\\nclearChanges\\n\\thasChanges := false! !\\n\\n!OBCodeBrowser methodsFor: 'updating'!\\nevent: anEvent\\n\\thasChanges := true! !\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 3/1/2006 19:48'!\\nregister\\n\\tSystemChangeNotifier uniqueInstance notify: self ofAllSystemChangesUsing: #event:! !\\n\\n!OBCodeBrowser methodsFor: 'updating' stamp: 'cwp 3/1/2006 19:48'!\\nunregister\\n\\tSystemChangeNotifier uniqueInstance noMoreNotificationsFor: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBCodeBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBCodeBrowser class methodsFor: 'configuration' stamp: 'lr 3/28/2006 12:00'!\\naddTo: root class: classSel comment: commentSel metaclass: metaclassSel \\n\\t| class metaclass comment methodCategory method allMethodCategory |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tcomment := OBMetaNode named: 'ClassComment'.\\n\\tmetaclass := OBMetaNode named: 'Metaclass'.\\n\\tallMethodCategory := OBMetaNode named: 'AllMethodCategory'.\\n\\tmethodCategory := OBMetaNode named: 'MethodCategory'.\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\troot\\n\\t\\tchildAt: classSel\\n\\t\\t\\tlabeled: 'instance'\\n\\t\\t\\tput: class;\\n\\t\\tchildAt: commentSel\\n\\t\\t\\tlabeled: '?'\\n\\t\\t\\tput: comment;\\n\\t\\tchildAt: metaclassSel\\n\\t\\t\\tlabeled: 'class'\\n\\t\\t\\tput: metaclass;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBClassCategoryNode);\\n\\t\\taddActor: OBCategoryActor new;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tclass\\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\tchildAt: #allCategory put: allMethodCategory;\\n\\t\\tchildAt: #categories put: methodCategory;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\taddActor: OBClassActor new.\\n\\tcomment \\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmetaclass\\n\\t\\tdisplaySelector: #indentedName;\\n\\t\\tchildAt: #allCategory put: allMethodCategory;\\n\\t\\tchildAt: #categories put: methodCategory;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\taddActor: OBClassActor new.\\n\\tallMethodCategory\\n\\t\\tchildAt: #methods put: method;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBMethodCategoryNode).\\n\\tmethodCategory\\n\\t\\tchildAt: #methods put: method;\\n\\t\\taddActor: OBCategoryActor new;\\n\\t\\taddActor: (OBNodeActor onNodeClass: OBMethodCategoryNode).\\n\\tmethod addActor: OBNodeActor new.\\n\\t^ root! !\\n\\n!OBCodeBrowser class methodsFor: 'configuration' stamp: 'cwp 12/15/2004 22:52'!\\noptionalButtons\\n\\t^ #('browse' 'variables' 'hierarchy' 'inheritance' 'senders' 'implementors' 'versions')! !\\nOBNode subclass: #OBCodeNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBCodeNode commentStamp: 'cwp 1/8/2005 11:12' prior: 0!\\nOBCodeNode is an abstract superclass for node classes that represent program elements active in the image. Though it provides little functionality, it exists for structural purposes.!\\n\\n\\n!OBCodeNode methodsFor: 'actions' stamp: 'cwp 7/14/2006 14:24'!\\nbrowseAction\\n\\t^ self \\n\\t\\taction: #browse\\n\\t\\twithMenuLabel: 'browse'\\n\\t\\twithButtonLabel: 'browse'\\n\\t\\twithKeystroke: $b\\n\\t\\twithIcon: (MenuIcons tryIcons: #(windowIcon smallWindowIcon)).\\n! !\\n\\n\\n!OBCodeNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:37'!\\nhasOrganization\\n\\t^ false! !\\nOBNode subclass: #OBCollectionNode\\n\\tinstanceVariableNames: 'collection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Nodes'!\\n!OBCollectionNode commentStamp: 'cwp 1/7/2005 23:31' prior: 0!\\nOBCollectionNode is a trivial wrapper for a collection of nodes. It is typically used as an artificial root node for metagraphs that have no natural root.!\\n\\n\\n!OBCollectionNode methodsFor: 'displaying' stamp: 'cwp 3/15/2004 23:19'!\\nname\\n\\t^ collection species name! !\\n\\n\\n!OBCollectionNode methodsFor: 'initalizing' stamp: 'cwp 3/15/2004 23:18'!\\nsetCollection: aCollection\\n\\tcollection _ aCollection! !\\n\\n\\n!OBCollectionNode methodsFor: 'navigating' stamp: 'cwp 3/15/2004 23:19'!\\nchildren\\n\\t^ collection! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBCollectionNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBCollectionNode class methodsFor: 'as yet unclassified' stamp: 'cwp 3/15/2004 23:17'!\\non: aCollection\\n\\t^ self new setCollection: aCollection! !\\nObject subclass: #OBColumn\\n\\tinstanceVariableNames: 'panel filter children selection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBColumn commentStamp: 'cwp 1/7/2005 23:19' prior: 0!\\nAn OBColumn manages a list of nodes, which it displays in a PluggableListMorph in the pane scroller at the top of the browser. All instances of OBColumn belong to an OBColumnPanel. It's main responsibility is keeping its list - and those of its neighbours - up to date. Each column has a MetaNode, which provides the list contents. It uses a filter to meditate between its self and the MetaNode.\\n\\niVars:\\n\\npanel\\t\\t- the panel which owns the column\\nfilter\\t\\t- the filter which manages the column's MetaNode.\\nparent\\t\\t- the node selected in the column to the left of this column\\nchildren \\t- the nodes which make up this column's list\\nselection \\t- the index of the node selected by the user!\\n\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:52'!\\nannouncer\\n\\t^ panel announcer! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:49'!\\nbasicNext\\n\\t^panel columnAfter: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 11/17/2004 00:18'!\\nbrowser\\n\\t^ panel browser! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:58'!\\nfilter\\n\\t^ filter! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/12/2004 18:47'!\\nfilter: aFilter\\n\\tfilter _ aFilter monitor: self.\\n\\tself changed: #filter.! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/28/2006 08:27'!\\nisEmpty\\n\\t^ children isEmpty! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:59'!\\nmetaNode\\n\\t^ self filter metaNode! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 2/12/2004 20:50'!\\nnext\\n\\t^ self basicNext\\n\\t\\tifNil: [(self hasSelection and: [self shouldBeLast not])\\n\\t\\t\\t\\tifTrue: [self createNext]]\\n\\t! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 9/24/2005 22:45'!\\nparent\\n\\t^ panel parentNodeForColumn: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 6/8/2006 01:32'!\\nparent: aNode\\n\\t\\n\\tself filter: aNode metaNode filter.\\n\\tself getChildren.\\n\\tself clearSelection.\\n\\tself changed: #list.\\n\\tpanel clearAfter: self! !\\n\\n!OBColumn methodsFor: 'accessing' stamp: 'cwp 6/28/2006 00:53'!\\nrequestor\\n\\t^ self browser requestor node: (self selectedNode ifNil: [self parent])! !\\n\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/24/2005 22:23'!\\nactionSetsForParentNode\\n\\t^ self filter children gather: [:child | child actionSetsForParent: self parent].\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/14/2004 19:08'!\\nactionSetsForSelectedNode\\n\\t| node |\\n\\tnode _ self selectedNode ifNil: [^ #()].\\n\\t^ node metaNode actionSetsForNode: node\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'hpt 5/17/2004 14:19'!\\nactionsForKeystroke: aChar\\n\\t^self actionsForParentNode, self actionsForSelectedNode\\n\\t\\tselect: [:anAction | anAction keystroke == aChar]! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 9/24/2005 22:23'!\\nactionsForParentNode\\n\\t^ self filter children gather: [:child | child actionsForParent: self parent].\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'avi 3/6/2004 16:26'!\\nactionsForSelectedNode\\n\\t| node |\\n\\tnode _ self selectedNode ifNil: [^ #()].\\n\\t^ node metaNode actionsForNode: node\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/25/2006 00:22'!\\naddActionsToMenu: aMenu\\n\\tself actionSetsForParentNode, self actionSetsForSelectedNode\\n\\t\\tdo: \\n\\t\\t\\t[:set \\n\\t\\t\\t|set do: \\n\\t\\t\\t\\t[:action | \\n\\t\\t\\t\\taction announcer: self announcer.\\n\\t\\t\\t\\taction addItemToMenu: aMenu]]\\n\\t\\tseparatedBy: [aMenu addLine]! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/28/2006 00:24'!\\naddServicesToMenu: aMenu\\n\\t| scan |\\n\\tscan _ self announcer announce: OBServiceScan.\\n\\taMenu \\n\\t\\taddServices: scan services\\n\\t\\tfor: self requestor\\n\\t\\textraLines: #().\\n\\t! !\\n\\n!OBColumn methodsFor: 'actions' stamp: 'cwp 6/25/2006 13:55'!\\nservicesForKeystroke: aChar\\n\\t| scan |\\n\\tscan _ self announcer announce: OBServiceScan.\\n\\t^ scan services select: [:ea | ea keystroke == aChar]! !\\n\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/28/2006 00:50'!\\nkeystroke: aChar from: aMorph\\n\\tself isEmpty ifTrue: [^ self].\\n\\t(self actionsForKeystroke: aChar)\\n\\t\\tdo: [:action | \\n\\t\\t\\taction announcer: self announcer.\\n\\t\\t\\taction trigger].\\n\\t(self servicesForKeystroke: aChar)\\n\\t\\tdo: [:service | service condExecuteFor: self requestor]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 12/8/2004 21:21'!\\nlist\\n\\t^ children \\n\\t\\tifNil: [#()]\\n\\t\\tifNotNil: [children collect: [:ea | ea displayString]]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 12/8/2004 21:22'!\\nlistAt: index\\n\\t^ (children at: index ifAbsent: [^ '']) displayString! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 2/29/2004 21:48'!\\nlistSize\\n\\t^ children\\n\\t\\tifNil: [0]\\n\\t\\tifNotNil: [children size]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/25/2006 00:24'!\\nmenu: aMenu\\n\\tself isEmpty ifFalse:\\n\\t\\t[self addActionsToMenu: aMenu.\\n\\t\\tself addServicesToMenu: aMenu].\\n\\t^ aMenu! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 4/18/2006 00:25'!\\nokToChange\\n\\t^ (self announcer announce: OBAboutToChange) isVetoed not! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 11/5/2003 19:01'!\\nselection\\n\\t^ selection ifNil: [0]! !\\n\\n!OBColumn methodsFor: 'callbacks' stamp: 'cwp 6/5/2006 23:37'!\\nselection: anInteger\\n\\tselection _ anInteger.\\n\\tself signalSelectionChanged.\\n\\tself changed: #selection.\\n! !\\n\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 6/4/2006 00:37'!\\nacceptDroppingMorph: transferMorph event: evt inMorph: listMorph\\n\\t^ [(self nodeForDroppedMorph: transferMorph event: evt inMorph: listMorph)\\n\\t\\tacceptDroppedNode: transferMorph passenger]\\n\\t\\t\\ton: OBAnnouncerRequest\\n\\t\\t\\tdo: [:notification | notification resume: self announcer]\\n! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 13:45'!\\ndragEnabled\\n\\t^ true! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:35'!\\ndragPassengerFor: item inMorph: listMorph\\n\\t^ self nodeForItem: item inMorph: listMorph! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:37'!\\ndragTransferType\\n\\t^ #OmniBrowser! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:36'!\\ndragTransferTypeForMorph: listMorph\\n\\t^ self dragTransferType! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:30'!\\ndropEnabled\\n\\t^ true! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 3/3/2004 02:23'!\\nnodeForDroppedMorph: transferMorph event: evt inMorph: pluggableListMorph\\n\\t| index item |\\n\\tindex _ pluggableListMorph rowAtLocation: evt position.\\n\\tindex = 0 ifTrue: [^ nil].\\n\\titem _ pluggableListMorph listMorph item: index.\\n\\t^ self nodeForItem: item inMorph: pluggableListMorph! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 6/10/2006 21:59'!\\nnodeForItem: item inMorph: pluggableListMorph\\n\\t^ children \\n\\t\\tdetect: [:child | child displayString = item contents asString]\\n\\t\\tifNone: [item contents]! !\\n\\n!OBColumn methodsFor: 'drag and drop' stamp: 'cwp 2/25/2004 21:26'!\\nwantsDroppedMorph: transferMorph event: evt inMorph: listMorph\\n\\t| node |\\n\\t(transferMorph isKindOf: TransferMorph) ifFalse: [^ false].\\n\\ttransferMorph dragTransferType == self dragTransferType ifFalse: [^ false].\\n\\tnode _ self nodeForDroppedMorph: transferMorph event: evt inMorph: listMorph.\\n\\t^ node notNil and: [node wantsDroppedNode: transferMorph passenger]! !\\n\\n\\n!OBColumn methodsFor: 'initializing' stamp: 'cwp 6/3/2006 23:38'!\\nsetPanel: aPanel \\n\\tpanel := aPanel.\\n\\tself subscribe.\\n\\tchildren := #().\\n\\tself clearSelection! !\\n\\n!OBColumn methodsFor: 'initializing' stamp: 'cwp 6/3/2006 23:39'!\\nsetPanel: aPanel metaNode: aMetaNode node: aNode \\n\\tpanel := aPanel.\\n\\tself subscribe.\\n\\tfilter := aMetaNode filter monitor: self.\\n\\tchildren _ self filter nodesForParent: aNode.\\n\\tself clearSelection! !\\n\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 12/14/2003 22:15'!\\nbuttonHeight\\n\\t^ 20! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/9/2004 21:06'!\\ncolumnWithHeader\\n\\t| col bh |\\n\\tcol _ BorderedMorph new\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tcellInset: 0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new.\\n\\t\\n\\tbh _ self buttonHeight negated.\\n\\tcol\\n\\t\\taddMorph: self listMorph\\n\\t\\tfullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (0@0 corner: 0@bh)).\\n\\tcol\\n\\t\\taddMorph: self filter buttonMorph\\n\\t\\tfullFrame: (LayoutFrame fractions: (0@1 corner: 1@1) offsets: (0@bh corner: 0@0)).\\n\\t\\t\\n\\n\\t^ col! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/28/2006 08:37'!\\nlistMorph\\n\\t^ (PluggableListMorph\\n\\t\\ton: self\\n\\t\\tlist: #list\\n\\t\\tselected: #selection\\n\\t\\tchangeSelected: #selection:\\n\\t\\tmenu: #menu:\\n\\t\\tkeystroke: #keystroke:from:)\\n\\t\\t\\tgetListElementSelector: #listAt:;\\n\\t\\t\\tgetListSizeSelector: #listSize;\\n\\t\\t\\tdragEnabled: self dragEnabled;\\n\\t\\t\\tdropEnabled: self dropEnabled;\\n\\t\\t\\tborderWidth: 0;\\n\\t\\t\\tautoDeselect: false;\\n\\t\\t\\tadoptPaneColor: panel defaultBackgroundColor;\\n\\t\\t\\tyourself! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 19:17'!\\nmorph\\n\\t^ self isEmpty \\n\\t\\tifTrue: [self simplePane]\\n\\t\\tifFalse: [self filter wantsButton\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [self paneWithHeader]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [self simplePane]]! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 18:11'!\\npaneWithHeader\\n\\t^ OBPane forColumn: self withFilter: self filter! !\\n\\n!OBColumn methodsFor: 'morphic' stamp: 'cwp 2/12/2004 18:10'!\\nsimplePane\\n\\t^ OBPane forColumn: self! !\\n\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 9/24/2005 22:29'!\\ngetChildren\\n\\tchildren _ self filter nodesForParent: self parent.\\n\\t^ children! !\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 3/3/2004 00:11'!\\nnextMetaNode\\n\\t^ self selectedNode metaNode! !\\n\\n!OBColumn methodsFor: 'nodes' stamp: 'cwp 9/26/2005 00:14'!\\nselectAncestorOf: aNode\\n\\t| ancestor |\\n\\tancestor _ self filter selectAncestorOf: aNode withParent: self parent.\\n\\tancestor ifNotNil:\\n\\t\\t[self \\n\\t\\t\\tgetChildren; \\n\\t\\t\\tchanged: #list;\\n\\t\\t\\tselect: ancestor.\\n\\t\\tpanel selected: self].\\n\\t^ ancestor! !\\n\\n\\n!OBColumn methodsFor: 'printing' stamp: 'avi 3/6/2004 16:23'!\\ndescriptor\\n\\tself isEmpty ifTrue: [^ 'empty'].\\n\\tself hasSelection ifTrue: [^ self selectedNode name].\\n\\t^ ''! !\\n\\n!OBColumn methodsFor: 'printing' stamp: 'cwp 2/11/2004 23:31'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $(.\\n\\taStream nextPutAll: self descriptor.\\n\\taStream nextPut: $)! !\\n\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'avi 3/6/2004 18:05'!\\nclearSelection\\n\\tselection _ 0! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 2/2/2004 21:54'!\\nselectedNode\\n\\t^ children at: self selection ifAbsent: [].! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 7/14/2006 12:50'!\\nselectSilently: aNode\\n\\t| match |\\n\\taNode ifNil: [selection := 0. ^ self].\\n\\tmatch := children \\n\\t\\t\\t\\tdetect: [:ea | ea correspondsWith: aNode] \\n\\t\\t\\t\\tifNone: [selection := 0. ^ self].\\n\\tselection _ children indexOf: match.! !\\n\\n!OBColumn methodsFor: 'selecting' stamp: 'cwp 12/8/2004 22:10'!\\nselect: aNode\\n\\tself selection: (children indexOf: (children detect: [:ea | ea = aNode] ifNone: []))! !\\n\\n\\n!OBColumn methodsFor: 'testing' stamp: 'avi 3/6/2004 23:07'!\\nhasSelection\\n\\t^ self selection > 0! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'cwp 12/20/2004 22:09'!\\nincludesNode: aNode\\n\\t^ children includes: aNode! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'avi 3/6/2004 16:27'!\\nshouldBeLast\\n\\t^ self hasSelection not or: [self nextMetaNode hasChildren not]! !\\n\\n!OBColumn methodsFor: 'testing' stamp: 'cwp 2/12/2004 20:18'!\\nwantsButton\\n\\t^ self filter notNil and: [self filter wantsButton]! !\\n\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 22:35'!\\nchildrenChanged: announcement\\n\\t(self parent = announcement node) ifTrue:\\n\\t\\t[self refresh]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 9/25/2005 23:56'!\\nclear\\n\\tfilter _ nil.\\n\\tchildren _ #().\\n\\tself clearSelection.\\n\\tself changed: #list.\\n\\tself changed: #selection.\\n\\tself changed: #filter.! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 9/24/2005 22:56'!\\ncreateNext\\n\\t| nextMetaNode created |\\n\\tnextMetaNode := self nextMetaNode.\\n\\tcreated := nextMetaNode columnInPanel: panel node: self selectedNode.\\n\\tpanel pushColumn: created.\\n\\t^created! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:17'!\\nlistChanged\\n\\tself refreshAndSignal: true! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:19'!\\nnodeChanged: ann\\n\\t(children includes: ann node) ifTrue: [self changed: #list]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:03'!\\nnodeDeleted: announcement \\n\\t\\\"This gets called if an action causes the currently selected node to be deleted.\\\"\\n\\n\\tself selectedNode = announcement node\\n\\t\\tifTrue: \\n\\t\\t\\t[self getChildren.\\n\\t\\t\\tself changed: #list.\\n\\t\\t\\tself selection: 0]! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefresh\\n\\tself refreshAndSignal: false! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefresh: ann\\n\\tself refreshAndSignal: false! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/9/2006 23:08'!\\nrefreshAndSignal: aBoolean\\n\\t| node oldChildren shouldSignal |\\n\\tshouldSignal _ aBoolean.\\n\\tself isEmpty ifTrue: [^self].\\n\\tnode := self selectedNode.\\n\\toldChildren := children.\\n\\tself getChildren.\\n\\tchildren = oldChildren ifFalse: \\n\\t\\t[self selectSilently: node.\\n\\t\\tself hasSelection ifFalse: \\n\\t\\t\\t[shouldSignal _ true]].\\n\\tshouldSignal ifTrue: [self signalSelectionChanged].\\n\\tself changed: #list! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/8/2006 00:27'!\\nselectionChanged: ann\\n\\t! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/5/2006 23:31'!\\nsignalSelectionChanged\\n\\tself announcer announce: (OBSelectionChanged column: self)! !\\n\\n!OBColumn methodsFor: 'updating' stamp: 'cwp 6/10/2006 00:18'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBRefreshRequired send: #refresh: to: self;\\n\\t\\tobserve: OBNodeChanged send: #nodeChanged: to: self;\\n\\t\\tobserve: OBNodeDeleted send: #nodeDeleted: to: self;\\n\\t\\tobserve: OBChildrenChanged send: #childrenChanged: to: self;\\n\\t\\tobserve: OBSelectionChanged send: #selectionChanged: to: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBColumn class\\n\\tinstanceVariableNames: ''!\\n\\n!OBColumn class methodsFor: 'instance creation' stamp: 'cwp 9/18/2005 13:26'!\\ninPanel: aBrowser\\n\\t^ self new setPanel: aBrowser! !\\n\\n!OBColumn class methodsFor: 'instance creation' stamp: 'cwp 9/18/2005 13:25'!\\ninPanel: aPanel metaNode: aMetaNode node: aNode\\n\\t^ self new\\n\\t\\t\\tsetPanel: aPanel\\n\\t\\t\\tmetaNode: aMetaNode\\n\\t\\t\\tnode: aNode! !\\nOBPanel subclass: #OBColumnPanel\\n\\tinstanceVariableNames: 'root columns minPanes maxPanes'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBColumnPanel commentStamp: 'cwp 12/6/2004 23:50' prior: 0!\\nOBColumnPanel handles navigation around the nodes of the object graph. It maintains a list of columns, which track the user's path through the node tree. As nodes are selected, additional columns are added to the list, which appear as panes on the right of the panel. \\n\\niVars:\\n\\ncolumns\\t- A collection of OBColumns, each of which manages a single pane in the scroller.\\nminPanes - The minimum number of panes that should ever be visible.\\nmaxPanes - The maximum number of panes that should ever be visible.\\n!\\n\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:46'!\\ncolumns\\n\\t^columns! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:46'!\\ncolumns: anObject\\n\\tcolumns := anObject! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:22'!\\ncurrentNode\\n\\t^ self currentColumn ifNotNilDo: [:column | column selectedNode]! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:23'!\\ncurrentOrRootNode\\n\\t^(self columns reversed detect: [:ea | ea hasSelection]\\n\\t\\tifNone: [^self columns first parent]) selectedNode! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 6/5/2006 23:10'!\\nhasSelection\\n\\t^ false! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 23:51'!\\nlabelString\\n\\t| label |\\n\\tself columns reversed do: \\n\\t\\t[:ea | \\n\\t\\tlabel := ea selectedNode ifNotNilDo: [:node | node title].\\n\\t\\tlabel ifNotNil: [^ label]].\\n\\t^ nil\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 23:29'!\\nmaxPanes\\n\\t^maxPanes! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 22:54'!\\nminPanes\\n\\t^ minPanes! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'cwp 2/28/2006 09:59'!\\nparentNodeForColumn: aColumn\\n\\t^ [(columns before: aColumn) selectedNode]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | ^ root]! !\\n\\n!OBColumnPanel methodsFor: 'accessing' stamp: 'dvf 9/5/2005 18:08'!\\nselectionPath\\n\\t^(self columns \\n\\t\\tcollect: [:e | e parent] \\n\\t\\tthenSelect: [:e | e notNil]) allButFirst! !\\n\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 9/25/2005 23:58'!\\nclearAfter: aColumn \\n\\t| start |\\n\\tstart _ (columns indexOf: aColumn) + 1.\\n\\tstart to: columns size do: [:i | (columns at: i) clear]! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 18:12'!\\ncolumnAfter: aColumn \\n\\t^ [self columns after: aColumn]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | nil]\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 19:07'!\\ncolumnBefore: aColumn \\n\\t^ self columnBefore: aColumn ifAbsent: [nil]\\n\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 2/28/2006 19:07'!\\ncolumnBefore: aColumn ifAbsent: aBlock\\n\\t^ [self columns before: aColumn]\\n\\t\\ton: Error\\n\\t\\tdo: [:err | aBlock value]\\n\\n\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 11/16/2004 22:22'!\\ncurrentColumn\\n\\t^self columns reversed detect: [:ea | ea hasSelection] ifNone: []! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 11/16/2004 23:01'!\\nemptyColumn\\n\\t^ OBColumn inPanel: self! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/4/2006 00:39'!\\npopColumn\\n\\tself announcer unsubscribe: self columns removeLast.\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/4/2006 00:40'!\\npushColumn: aColumn \\n\\tself columns addLast: aColumn.\\n\\tself changed: #panes.\\n! !\\n\\n!OBColumnPanel methodsFor: 'accessing columns' stamp: 'cwp 6/8/2006 01:35'!\\nselected: aColumn \\n\\taColumn next ifNotNilDo: \\n\\t\\t[:next | \\n\\t\\tnext parent: aColumn selectedNode].! !\\n\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/26/2004 21:55'!\\ndefaultBackgroundColor\\n\\t^ browser defaultBackgroundColor! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/23/2004 00:52'!\\nokToReclaimPane\\n\\tcolumns size > minPanes ifFalse: [^ false].\\n\\t^ columns last isEmpty or: [(columns at: columns size - 1) shouldBeLast].\\n! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/17/2004 22:48'!\\npanes\\n\\t^ columns collect: [:ea | ea morph]! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 9/18/2005 11:49'!\\nreclaimPanes\\n\\t| old |\\n\\told := columns size.\\n\\t[self okToReclaimPane] whileTrue: [self popColumn].\\n\\t^ old - columns size! !\\n\\n!OBColumnPanel methodsFor: 'callbacks' stamp: 'cwp 11/18/2004 00:00'!\\nsizing\\n\\t^ (columns size max: minPanes) min: maxPanes! !\\n\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/17/2004 23:24'!\\nbuildScroller\\n\\t^ (OBPaneScroller withModel: self)\\n\\t\\tname: 'scroller';\\n\\t\\tyourself! !\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/20/2004 22:22'!\\nmorph\\n\\t^ (OBPaneScroller withModel: self)\\n\\t\\tname: 'scroller';\\n\\t\\tyourself! !\\n\\n!OBColumnPanel methodsFor: 'constructing' stamp: 'cwp 11/20/2004 22:26'!\\nmorphHeight\\n\\t^ 0! !\\n\\n\\n!OBColumnPanel methodsFor: 'initializing' stamp: 'cwp 9/24/2005 22:45'!\\nsetMetaNode: aMetaNode node: aNode \\n\\troot _ aNode.\\n\\troot metaNode: aMetaNode.\\n\\tself pushColumn: (aMetaNode columnInPanel: self node: root).\\n\\tminPanes - self columns size \\n\\t\\ttimesRepeat: [self pushColumn: self emptyColumn]! !\\n\\n!OBColumnPanel methodsFor: 'initializing' stamp: 'cwp 12/5/2004 16:54'!\\nsetMinPanes: min maxPanes: max\\n\\tcolumns _ OrderedCollection new.\\n\\tminPanes _ min.\\n\\tmaxPanes _ max! !\\n\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 6/9/2006 23:18'!\\nhopTo: aNode \\n\\t| column |\\n\\tcolumn := self columns last.\\n\\t[column refreshAndSignal: false; includesNode: aNode]\\n\\t\\twhileFalse: [column := self \\n\\t\\t\\t\\t\\t\\tcolumnBefore: column \\n\\t\\t\\t\\t\\t\\tifAbsent: [^ self jumpTo: aNode]].\\n\\tcolumn select: aNode! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 11/16/2004 23:34'!\\njumpToRoot\\n\\t^ self columns first selection: 0! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 6/10/2006 00:11'!\\njumpTo: aNode \\n\\t| column ancestor |\\n\\tcolumn := self columns first.\\n\\t\\n\\t[ancestor := column selectAncestorOf: aNode.\\n\\tancestor = aNode or: [ancestor isNil]] whileFalse:\\n\\t\\t[column := self columns after: column].\\n\\t\\n\\tself announcer announce: (OBSelectionChanged column: column)! !\\n\\n!OBColumnPanel methodsFor: 'navigating' stamp: 'cwp 9/24/2005 22:47'!\\nroot\\n\\t^ root! !\\n\\n\\n!OBColumnPanel methodsFor: 'testing' stamp: 'cwp 11/20/2004 21:10'!\\nisNavigation\\n\\t^ true! !\\n\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 23:52'!\\nnodeDeleted: ann\\n\\tann node = self root \\n\\t\\tifTrue: \\n\\t\\t\\t[self columns first clear.\\n\\t\\t\\tself announcer announce: (OBSelectionChanged column: self)]! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 01:03'!\\nselectNode: announcement\\n\\t^ self hopTo: announcement node! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 01:33'!\\nselectionChanged: ann\\n\\tann column hasSelection\\n\\t\\tifTrue: [self selected: ann column]\\n\\t\\tifFalse: [self clearAfter: ann column]\\n! !\\n\\n!OBColumnPanel methodsFor: 'updating' stamp: 'cwp 6/5/2006 01:32'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectingNode send: #selectNode: to: self;\\n\\t\\tobserve: OBSelectionChanged send: #selectionChanged: to: self;\\n\\t\\tobserve: OBNodeCreated send: #selectNode: to: self;\\n\\t\\tobserve: OBNodeDeleted send: #nodeDeleted: to: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBColumnPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBColumnPanel class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 16:56'!\\nminPanes: min maxPanes: max\\n\\t^ self basicNew setMinPanes: min maxPanes: max! !\\n\\n!OBColumnPanel class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 16:56'!\\nnew\\n\\t^ self minPanes: 1 maxPanes: 1! !\\nOBInteractionRequest subclass: #OBConfirmationRequest\\n\\tinstanceVariableNames: 'prompt confirm cancel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBConfirmationRequest commentStamp: 'cwp 3/5/2004 12:30' prior: 0!\\nThis notification is used to ask the user to confirm some kind potentially dangerous operation. Its default action is to open a PopUpMenu.\\n\\niVars:\\n\\nprompt\\t\\t- a string describing the situation the user is asked to confirm\\nconfirm\\t\\t- a string describing the action that will be taken if the user confirms\\ncancel\\t\\t- a string describing the action that will be taken if the user does not confirm!\\n\\n\\n!OBConfirmationRequest methodsFor: 'initalizing' stamp: 'cwp 2/28/2004 12:00'!\\nsetPrompt: promptString confirm: confirmString cancel: cancelString\\n\\tprompt _ promptString.\\n\\tconfirm _ confirmString.\\n\\tcancel _ cancelString! !\\n\\n\\n!OBConfirmationRequest methodsFor: 'responding' stamp: 'cwp 2/28/2004 12:11'!\\ncancel\\n\\tself resume: false! !\\n\\n!OBConfirmationRequest methodsFor: 'responding' stamp: 'cwp 2/28/2004 12:11'!\\nok\\n\\tself resume: true! !\\n\\n\\n!OBConfirmationRequest methodsFor: 'user interaction' stamp: 'cwp 6/4/2006 14:17'!\\ndefaultAction\\n\\t(prompt beginsWith: 'BogusD') ifTrue: [self halt].\\n\\t^ PopUpMenu confirm: prompt trueChoice: confirm falseChoice: cancel! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBConfirmationRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:09'!\\nnewPrompt: prompt confirm: confirm cancel: cancel\\n\\t^ self new setPrompt: prompt confirm: confirm cancel: cancel! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:13'!\\nprompt: prompt\\n\\t^ self prompt: prompt confirm: 'Ok'! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:12'!\\nprompt: prompt confirm: confirm\\n\\t^ self prompt: prompt confirm: confirm cancel: 'Cancel'! !\\n\\n!OBConfirmationRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2004 12:02'!\\nprompt: prompt confirm: confirm cancel: cancel\\n\\t^ (self newPrompt: prompt confirm: confirm cancel: cancel) signal! !\\nObject subclass: #OBDefinition\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Utilities'!\\n!OBDefinition commentStamp: 'cwp 1/7/2005 23:38' prior: 0!\\nThe responsibility of a definition is to express a node's composition textually and respond to changes in the text by updating the node it represents. For example,a file browser might use a file definition to allow editing of a files contents.!\\n\\n\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:51'!\\naccept: aText notifying: aController\\n\\t^ self text: aText! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:08'!\\ndoItContext\\n\\t^ nil! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 2/28/2005 23:23'!\\ndoItReceiver\\n\\t| class |\\n\\tclass _ self selectedClass.\\n\\t^ class\\n\\t\\tifNotNil: [class theNonMetaClass]\\n\\t\\tifNil: [FakeClassPool new]! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 22:16'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:52'!\\ntext\\n\\t^ ''! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 22:16'!\\ntextSelection\\n\\t^ self selection! !\\n\\n!OBDefinition methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:52'!\\ntext: aText\\n\\t^ false! !\\n\\n\\n!OBDefinition methodsFor: 'updating' stamp: 'cwp 6/4/2006 18:53'!\\nsignalChange\\n\\tOBAnnouncer current announce: (OBDefinitionChanged definition: self)! !\\nOBAnnouncement subclass: #OBDefinitionChanged\\n\\tinstanceVariableNames: 'definition node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:25'!\\ndefinition\\n\\t^ definition! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:26'!\\ndefinition: aDefinition\\n\\tdefinition _ aDefinition! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:47'!\\nnode\\n\\t^ node! !\\n\\n!OBDefinitionChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/5/2006 00:47'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBDefinitionChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBDefinitionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:28'!\\ndefinition: aDefinition\\n\\t^ self new\\n\\t\\tdefinition: aDefinition;\\n\\t\\tyourself! !\\n\\n!OBDefinitionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:27'!\\nnode: aNode definition: aDefinition\\n\\t^ self new\\n\\t\\tnode: aNode;\\n\\t\\tdefinition: aDefinition;\\n\\t\\tyourself! !\\nOBPanel subclass: #OBDefinitionPanel\\n\\tinstanceVariableNames: 'definition'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBDefinitionPanel commentStamp: 'cwp 1/7/2005 23:35' prior: 0!\\nOBDefinition serves as the model for the text pane of a typical browser. It's main responsibility is to act as a relay between a PluggableTextMorph and a Definition supplied by the currently selected node.\\n\\niVars:\\n\\nbrowser - The browser of which this panel is a part.\\n!\\n\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 9/17/2004 00:56'!\\ndefinition: aDefinition\\n\\tdefinition _ aDefinition.\\n\\tself changed: #text! !\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 3/22/2004 20:06'!\\ngetDefinition\\n\\t^ browser currentNode ifNotNilDo: [:node | node definition]! !\\n\\n!OBDefinitionPanel methodsFor: 'accessing' stamp: 'cwp 3/22/2004 20:41'!\\nwithDefinitionDo: workBlock ifNil: nilBlock\\n\\tdefinition ifNil: [ ^ nilBlock value].\\n\\t^ workBlock value: definition! !\\n\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 6/4/2006 00:41'!\\naccept: aText notifying: aController\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | [def accept: aText notifying: aController]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: OBAnnouncerRequest\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdo: [:notification | notification resume: self announcer]]\\n\\t\\tifNil: [true]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:23'!\\ndoItContext\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #doItContext) ifTrue: [def doItContext]]\\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:23'!\\ndoItReceiver\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #doItReceiver) ifTrue: [def doItReceiver]]\\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 10/24/2004 09:16'!\\nmenu: aMenu shifted: aBoolean\\n\\t| items |\\n\\titems _ aBoolean \\n\\t\\tifTrue: [self shiftedYellowButtonMenu] \\n\\t\\tifFalse: [self yellowButtonMenu].\\n\\titems do: [:ea |\\n\\t\\t\\t ea = #-\\n\\t\\t\\t\\tifFalse: [aMenu add: ea first action: ea second]\\n\\t\\t\\t\\tifTrue: [aMenu addLine]].\\n\\t^ aMenu ! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 10/24/2004 09:27'!\\nperform: aSelector orSendTo: anObject\\n\\t| receiver |\\n\\treceiver _ (self respondsTo: aSelector) ifTrue: [self] ifFalse: [anObject].\\n\\treceiver perform: aSelector! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/23/2004 00:22'!\\nselectedClass\\n\\t^ self \\n\\t\\twithDefinitionDo: [:def | (def respondsTo: #selectedClass) ifTrue: [def selectedClass]] \\n\\t\\tifNil: [nil]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 21:15'!\\nselection\\n\\t^ self withDefinitionDo: [:def | def textSelection] ifNil: [1 to: 0]! !\\n\\n!OBDefinitionPanel methodsFor: 'callbacks' stamp: 'cwp 3/22/2004 20:42'!\\ntext\\n\\t^ self withDefinitionDo: [:def | def text] ifNil: ['']! !\\n\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 10/30/2004 22:03'!\\nmorph\\n\\t^ (OBPluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #text\\n\\t\\taccept: #accept:notifying:\\n\\t\\treadSelection: #selection\\n\\t\\tmenu: #menu:shifted:)\\n\\t\\t\\tfont: Preferences standardCodeFont;\\n\\t\\t\\tyourself\\n\\t\\t\\t\\n\\t\\\"see CodeHolder>>buildMorphicCodePaneWith:\\\"! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 3/9/2004 21:35'!\\nmorphHeight\\n\\t^ 0! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 7/14/2006 01:17'!\\nshiftedYellowButtonMenu\\n\\t^ {\\n\\t\\t{'explain' translated.\\t\\t\\t\\t\\t\\t#explain}.\\n\\t\\t#-.\\n\\t\\t{'selectors containing it (W)' translated.\\t\\t#methodNamesContainingIt}.\\n\\t\\t{'method strings with it (E)' translated.\\t\\t#methodStringsContainingit}.\\n\\t\\t{'method source with it' translated.\\t\\t\\t#methodSourceContainingIt}.\\n\\t\\t{'class names containing it' translated.\\t\\t#classNamesContainingIt}.\\n\\t\\t{'class comments with it' translated.\\t\\t\\t#classCommentsContainingIt}.\\n\\t\\t{'change sets with it' translated.\\t\\t\\t\\t#browseChangeSetsWithSelector}.\\n\\t\\t#-.\\n\\t\\t{'save contents to file...' translated.\\t\\t\\t#saveContentsInFile}.\\n\\t\\t#-.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t\\t\\t#yellowButtonActivity}.\\n\\t}\\n! !\\n\\n!OBDefinitionPanel methodsFor: 'constructing' stamp: 'cwp 10/24/2004 23:28'!\\nyellowButtonMenu\\n\\t^ {\\n\\t\\t{'find...(f)' translated.\\t\\t\\t\\t#find}.\\t\\t\\t \\n\\t\\t{'find again (g)' translated.\\t\\t\\t#findAgain}.\\t\\t \\n\\t\\t{'set search string (h)' translated.\\t#setSearchString}.\\n\\t\\t#-.\\t \\n\\t\\t{'do again (j)' translated.\\t\\t\\t#again}.\\t\\t \\n\\t\\t{'undo (z)' translated.\\t\\t\\t\\t#undo}.\\t\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'copy (c)' translated.\\t\\t\\t\\t#copySelection}.\\t \\n\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t#cut}.\\t\\t\\t \\n\\t\\t{'paste (v)' translated.\\t\\t\\t\\t#paste}.\\t\\t \\n\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'accept (s)' translated.\\t\\t\\t\\t#accept}.\\t\\t \\n\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t#cancel}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'do it (d)' translated.\\t\\t\\t\\t#doIt}.\\t\\t\\t \\n\\t\\t{'print it (p)' translated.\\t\\t\\t\\t#printIt}.\\t\\t \\n\\t\\t{'inspect it (i)' translated.\\t\\t\\t#inspectIt}.\\t\\t \\n\\t\\t{'explore it (I)' translated.\\t\\t\\t#exploreIt}.\\t\\t \\n\\t\\t{'debug it' translated.\\t\\t\\t\\t#debugIt}.\\t\\t \\n\\t\\t#-.\\t \\n\\t\\t{'browse it (b)' translated.\\t\\t\\t\\t\\t#browseIt}.\\n\\t\\t{'senders of it (n)' translated.\\t\\t\\t\\t#sendersOfIt}.\\n\\t\\t{'implementors of it (m)' translated.\\t\\t\\t#implementorsOfIt}.\\n\\t\\t{'references to it (N)' translated.\\t\\t\\t\\t#referencesToIt}.\\n\\t\\t#-.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t#shiftedTextPaneMenuRequest}.\\n\\t}\\n! !\\n\\n\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 4/18/2006 21:31'!\\naboutToChange: ann\\n\\t| ok |\\n\\tself canDiscardEdits ifTrue: [^ true].\\n\\tok _ OBConfirmationRequest\\n\\t\\t\\tprompt: 'Changes have not been saved.\\nIs it OK to discard those changes?'\\n\\t\\t\\tconfirm: 'Discard changes'.\\n\\tok\\n\\t\\tifTrue: [self changed: #clearUserEdits]\\n\\t\\tifFalse: [ann veto]! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 11:31'!\\ndefinitionChanged: ann\\n\\tdefinition _ ann definition.\\n\\tself changed: #text! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/3/2006 21:55'!\\nrefresh: announcement\\n\\t| oldDefinition |\\n\\tdefinition ifNil: [^ self].\\n\\toldDefinition _ definition.\\n\\tdefinition _ self getDefinition.\\n\\tdefinition text = oldDefinition text ifTrue: [^ self].\\n\\tself canDiscardEdits\\n\\t\\t\\tifTrue: [self changed: #text]\\n\\t\\t\\tifFalse: [self changed: #codeChangedElsewhere]! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 4/24/2006 16:06'!\\nselectionChanged: ann\\n\\tself definition: self getDefinition! !\\n\\n!OBDefinitionPanel methodsFor: 'updating' stamp: 'cwp 6/4/2006 11:30'!\\nsubscribe\\n\\tself announcer \\n\\t\\tobserve: OBAboutToChange\\n\\t\\tsend: #aboutToChange:\\n\\t\\tto: self;\\n\\t\\t\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self;\\n\\t\\t\\n\\t\\tobserve: OBRefreshRequired\\n\\t\\tsend: #refresh:\\n\\t\\tto: self;\\n\\t\\t\\t\\t\\n\\t\\tobserve: OBDefinitionChanged\\n\\t\\tsend: #definitionChanged: \\n\\t\\tto: self.! !\\n\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'pmm 7/6/2006 20:49'!\\nbrowseIt: aSymbol\\n\\t| entry |\\n\\tentry := self selectedClass environment at: aSymbol ifAbsent: [nil].\\n\\tentry ifNil: [^ self implementorsOfIt: aSymbol].\\n\\t(entry isBehavior or: [entry isTrait ])\\n\\t\\tifFalse: [entry := entry class].\\n\\tOBSystemBrowser openOnClass: entry.\\n\\t^ true\\n\\t! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nimplementorsOfIt: aSelector \\n\\tOBImplementorsBrowser browseRoot: (OBSelectorNode on: aSelector).\\n\\t^true! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nreferencesToIt: aClassName \\n\\t| class |\\n\\tclass := self selectedClass environment at: aClassName ifAbsent: [^false].\\n\\tclass isBehavior ifFalse: [^false].\\n\\tOBReferencesBrowser browseRoot: (OBClassNode on: class).\\n\\t^true! !\\n\\n!OBDefinitionPanel methodsFor: '*ob-standard-cmds' stamp: 'avi 9/17/2005 01:36'!\\nsendersOfIt: aSelector \\n\\tOBSendersBrowser browseRoot: (OBSelectorNode on: aSelector).\\n\\t^true! !\\nNotification subclass: #OBDispatcherRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\nOBCodeNode subclass: #OBEnvironmentNode\\n\\tinstanceVariableNames: 'environment'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBEnvironmentNode commentStamp: 'cwp 1/8/2005 13:01' prior: 0!\\nOBEnvironmentNode wraps an instance of SystemDictionary. In current Squeak images, there is only one such instance, but OB-Standard is coded so as to use rely on this assumption as little as possible. Thus OBEnvironmentNode typically serves as the root of the standard browser, and passes its environment on to other nodes in the tree.!\\n\\n\\n!OBEnvironmentNode methodsFor: 'navigating'!\\ncategories\\n\\t^ environment organization categories collect: [:cat | OBClassCategoryNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ton: cat\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinEnvironment: environment]! !\\n\\n!OBEnvironmentNode methodsFor: 'navigating' stamp: 'cwp 9/20/2005 08:43'!\\ncategoryNodeNamed: aString \\n\\t^ OBClassCategoryNode on: aString! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'accessing'!\\nenvironment\\n\\t^ environment! !\\n\\n!OBEnvironmentNode methodsFor: 'accessing'!\\norganization\\n\\t^ self environment organization! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'displaying'!\\nname \\n\\t^ 'Squeak'! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'initializing'!\\nsetEnvironment: anEnvironment\\n\\tenvironment := anEnvironment! !\\n\\n\\n!OBEnvironmentNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:54'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBEnvironmentNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBEnvironmentNode class methodsFor: 'as yet unclassified'!\\nforImage\\n\\t^ self on: Smalltalk! !\\n\\n!OBEnvironmentNode class methodsFor: 'as yet unclassified'!\\non: anEnvironment\\n\\t^ self new setEnvironment: anEnvironment! !\\nObject subclass: #OBFilter\\n\\tinstanceVariableNames: 'metaNode monitor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBFilter commentStamp: 'cwp 3/4/2004 21:53' prior: 0!\\nA browser's metagraph defines the way in which the user may traverse the graph of objects which make up the browser's domain. But it's not always desirable to have all the nodes made available by the metagraph to be visible in the browser. An filter provides a strategy for filtering out some of the nodes from the display. \\n\\nOBFilter provides a \\\"null\\\" filter - one that does no filtering at all - and serves as a superclass for other filters. !\\n\\n\\n!OBFilter methodsFor: 'accessing' stamp: 'cwp 2/11/2004 23:48'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBFilter methodsFor: 'accessing' stamp: 'cwp 2/9/2004 20:56'!\\nmonitor: aMonitor\\n\\tmonitor _ aMonitor! !\\n\\n\\n!OBFilter methodsFor: 'initalizing' stamp: 'cwp 2/9/2004 20:54'!\\nsetMetaNode: aMetaNode\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/9/2004 20:50'!\\nchildren\\n\\t^ metaNode children! !\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/9/2004 20:52'!\\nnodesForParent: aNode\\n\\t^ metaNode nodesForParent: aNode! !\\n\\n!OBFilter methodsFor: 'public' stamp: 'cwp 2/29/2004 14:34'!\\nselectAncestorOf: aNode withParent: parentNode\\n\\t^ (metaNode nodesForParent: parentNode)\\n\\t\\tdetect: [:child | child isAncestorOf: aNode] \\n\\t\\tifNone: [nil]! !\\n\\n\\n!OBFilter methodsFor: 'queries' stamp: 'cwp 2/9/2004 21:06'!\\nwantsButton\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBFilter class\\n\\tinstanceVariableNames: ''!\\n\\n!OBFilter class methodsFor: 'as yet unclassified' stamp: 'cwp 2/9/2004 20:54'!\\nforMetaNode: aMetaNode\\n\\t^ self new setMetaNode: aMetaNode! !\\nOBPanel subclass: #OBFixedButtonPanel\\n\\tinstanceVariableNames: 'models actions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBFixedButtonPanel commentStamp: 'cwp 1/7/2005 23:35' prior: 0!\\nOBFixedButtonPanel displays a horizontal row of buttons. In contrast to OBVarButtonPanel, the buttons do not change as nodes are selected in the navigation panel; instead they are enabled and disabled according to whether the actions they represent are applicable to the selected node.!\\n\\n\\n!OBFixedButtonPanel methodsFor: 'accessing' stamp: 'cwp 11/26/2004 22:53'!\\nbuttonModels\\n\\t^ models! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:20'!\\nisEnabled: aModel\\n\\t^ (actions at: aModel) notNil! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:20'!\\nisSelected: aModel\\n\\t^ true! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 8/29/2004 11:28'!\\npush: aModel\\n\\t(actions at: aModel) ifNotNilDo: [:action | action trigger]! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 6/3/2006 22:15'!\\nselectionChanged: ann\\n\\t| node nodeActions |\\n\\tnode _ browser currentNode ifNil: [^ self].\\n\\tnodeActions _ (node metaNode actionsForNode: node) select: [:ea | ea wantsButton].\\n\\tactions keys do: \\n\\t\\t[:model | \\n\\t\\tactions at: model put: nil.\\n\\t\\tnodeActions do: \\n\\t\\t\\t[:action | model label = action buttonLabel ifTrue: [actions at: model put: action]]].\\n\\tactions keys do: [:ea | ea selectionChanged].! !\\n\\n!OBFixedButtonPanel methodsFor: 'callbacks' stamp: 'cwp 6/3/2006 22:14'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'lr 3/23/2006 18:14'!\\ncreateMorph\\n\\t^(RectangleMorph new)\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tborderWidth: 0;\\n\\t\\twrapCentering: #center;\\n\\t\\tcellPositioning: #leftCenter;\\n\\t\\trubberBandCells: true;\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 2;\\n\\t\\tyourself! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:24'!\\nmorph\\n\\t| morph |\\n\\tmorph := self createMorph.\\n\\tself buttonModels do: [:ea | morph addMorphBack: (self morphForModel: ea)].\\n\\t^morph! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:25'!\\nmorphForModel: aModel\\n\\t| morph paneColor |\\n\\tmorph _ aModel morph.\\n\\tpaneColor _ browser defaultBackgroundColor.\\n\\tmorph onColor: paneColor darker offColor: paneColor lighter.\\n\\t^ morph! !\\n\\n!OBFixedButtonPanel methodsFor: 'constructing' stamp: 'lr 3/23/2006 18:15'!\\nmorphHeight\\n\\t^ 30! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'initializing' stamp: 'cwp 11/26/2004 22:53'!\\ninitialize\\n\\tmodels _ OrderedCollection new.\\n\\tactions _ Dictionary new.! !\\n\\n\\n!OBFixedButtonPanel methodsFor: 'public' stamp: 'cwp 11/26/2004 22:52'!\\naddButtonWithLabel: label\\n\\t| model |\\n\\tmodel _ OBButtonModel withLabel: label inBar: self.\\n\\tmodels add: model.\\n\\tactions at: model put: nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBFixedButtonPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBFixedButtonPanel class methodsFor: 'as yet unclassified' stamp: 'cwp 2/28/2006 10:41'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBCodeBrowser subclass: #OBHierarchyBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBHierarchyBrowser commentStamp: 'cwp 1/7/2005 23:50' prior: 0!\\nOBHierarchyBrowser provides a three-pane browers that displays a class within it's surrounding hierarchy - both superclasses and subclasses!\\n\\n\\n!OBHierarchyBrowser methodsFor: 'as yet unclassified' stamp: 'cwp 12/13/2004 00:40'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen! !\\n\\n!OBHierarchyBrowser methodsFor: 'as yet unclassified' stamp: 'cwp 12/13/2004 01:00'!\\ndefaultLabel\\n\\t^ self root name, ' Hierarchy'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBHierarchyBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:06'!\\ndefaultMetaNode\\n\\t^ self \\n\\t\\taddTo: (OBMetaNode named: 'RootClass')\\n\\t\\tclass: #classHierarchy \\n\\t\\tcomment: #commentHierarchy \\n\\t\\tmetaclass: #metaclassHierarchy.\\n! !\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'cwp 12/13/2004 00:37'!\\npaneCount\\n\\t^ 3! !\\n\\n!OBHierarchyBrowser class methodsFor: 'configuration' stamp: 'cwp 12/13/2004 01:00'!\\ntitleForRoot: aNode\\n\\t^ aNode name, ' Hierarchy'! !\\n\\n\\n!OBHierarchyBrowser class methodsFor: 'instance creation' stamp: 'lr 3/6/2006 19:28'!\\nonClass: aClass \\n\\t^self root: aClass asNode selection: aClass asNode! !\\n\\n\\n!OBHierarchyBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 22:49'!\\nopenOnClass: aClass\\n\\t^ (self onClass: aClass) open! !\\nOBListBrowser subclass: #OBImplementorsBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBImplementorsBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'cwp 3/2/2006 15:35'!\\nchaseImplementorsNav: navSelector\\n\\t| message implementor |\\n\\tmessage := OBMetaNode named: 'Message'.\\n\\timplementor := OBMetaNode named: 'Implementor'.\\n\\timplementor\\n\\t\\tdisplaySelector: #indentedFullName;\\n\\t\\tchildAt: #messages put: message;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmessage\\n\\t\\tchildAt: navSelector labeled: 'implementors' put: implementor;\\n\\t\\taddActor: OBNodeActor new.\\n\\t^ implementor! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\ndefaultMetaNode\\n\\t^ self hierarchicalImplementors! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\nhierarchicalImplementors\\n\\t^ self implementorsNav: #implementorsHierarchically! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:24'!\\nimplementorsNav: navSelector\\n\\t| selector implementors |\\n\\tselector := OBMetaNode named: 'Selector'.\\n\\timplementors := OBMetaNode named: 'Implementors'.\\n\\t\\n\\tselector \\n\\t\\tchildAt: navSelector labeled: 'list' put: implementors;\\n\\t\\tchildAt: navSelector labeled: 'chase' put: (self chaseImplementorsNav: navSelector);\\n\\t\\tfilterClass: OBModalFilter.\\n\\timplementors \\n\\t\\tdisplaySelector: #indentedFullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\t^ selector! !\\n\\n!OBImplementorsBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:36'!\\ntitle\\n\\t^ 'Implementors of'! !\\nOBActor subclass: #OBImplementorsViewActor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Services'!\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'cwp 7/14/2006 14:28'!\\nactionsForParent: aNode\\n\\t^{OBAction\\n\\t\\t\\tlabel: 'add implementor' \\n\\t\\t\\treceiver: self\\n\\t\\t\\tselector: #addImplementor:\\n\\t\\t\\targuments: {aNode}\\n\\t\\t\\tkeystroke: $a\\n\\t\\t\\ticon: self newIcon}! !\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'dvf 9/12/2005 16:34'!\\naddImplementor: aNode \\n\\t| class sel |\\n\\tsel := aNode selector.\\n\\tclass := self getClassForNewImplementationOf: sel.\\n\\tclass ifNil: [^self].\\n\\t(class selectors includes: sel) \\n\\t\\tifTrue: [^self inform: class name , ' already implements #' , sel].\\n\\tclass compile: aNode selector , '\\n\\tself shouldBeImplemented'.\\n\\t(OBMethodNode on: sel inClass: class) signalSelection! !\\n\\n!OBImplementorsViewActor methodsFor: 'as yet unclassified' stamp: 'dvf 9/12/2005 16:14'!\\ngetClassForNewImplementationOf: sel \\n\\t| className |\\n\\tclassName := (OBTextRequest \\n\\t\\t\\t\\tprompt: 'Please type class name in which to implement ' , sel\\n\\t\\t\\t\\ttemplate: '') ifNil: [''].\\n\\t^(Smalltalk classNamed: className withBlanksTrimmed) ifNil: \\n\\t\\t\\t[self inform: 'Class ' , className , ' not found'.\\n\\t\\t\\tnil]! !\\nOBCodeBrowser subclass: #OBInheritanceBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBInheritanceBrowser commentStamp: 'cwp 1/7/2005 23:51' prior: 0!\\nOBInheritanceBrowser shows the inheritance hierarchy of a method, both superclass implementations which it overrides, and subclass implementations which override it.!\\n\\n\\n!OBInheritanceBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBInheritanceBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:08'!\\ndefaultMetaNode\\n\\t| method root |\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\troot := OBMetaNode named: 'Root'.\\n\\troot\\n\\t\\tchildAt: #children put: method.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\tchildAt: #overrides put: method;\\n\\t\\taddActor: OBNodeActor new.\\n\\t^ root! !\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration'!\\ntitle\\n\\t^ 'Inheritance'! !\\n\\n!OBInheritanceBrowser class methodsFor: 'configuration' stamp: 'cwp 11/25/2004 22:05'!\\ntitleForRoot: aCollectionNode\\n\\t^ 'Inheritance of ', aCollectionNode children first selector printString! !\\nOBVariableNode subclass: #OBInstanceVariableNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBInstanceVariableNode commentStamp: 'cwp 1/8/2005 12:50' prior: 0!\\nOBClassVariable provides a method for finding methods which refer to an instance, ie, by searching for instance variable access bytecodes rather than for an association in the literal frame.!\\n\\n\\n!OBInstanceVariableNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:48'!\\naccessors\\n\\t| accessors |\\n\\taccessors := OrderedCollection new.\\n\\tself theClass withAllSubAndSuperclassesDo: [:class |\\n\\t\\t(class whichSelectorsAccess: name) asSortedCollection\\n\\t\\t\\tdo: [:ea | ea = #DoIt ifFalse: [accessors add: \\n\\t\\t\\t\\t\\t(self referenceForMethod: ea ofClass: class name)]]].\\n\\t^ accessors asArray\\tcollect: [:ref | OBMethodNode on: ref]! !\\nNotification subclass: #OBInteractionRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBInteractionRequest commentStamp: 'cwp 12/7/2004 00:13' prior: 0!\\nOBInteractionRequest is an abstract superclass for notifications that request some interaction with the user. It's useful for catching such notifications in an exception handler, while allowing other notifications to operate normally.!\\n\\n\\n!OBInteractionRequest methodsFor: 'as yet unclassified' stamp: 'cwp 10/17/2004 19:31'!\\nisBrowseRequest\\n\\t^ false! !\\nOBCodeBrowser subclass: #OBListBrowser\\n\\tinstanceVariableNames: 'labelPrefix'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBListBrowser commentStamp: 'cwp 1/7/2005 23:53' prior: 0!\\nOBListBrowsers are used to display simple lists of methods, such as senders or implementors.!\\n\\n\\n!OBListBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:58'!\\ndefaultBackgroundColor\\n\\t^ Color lightBlue! !\\n\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 11/25/2004 22:21'!\\ndefaultLabel\\n\\t^ self labelPrefix, ' ', self root name printString! !\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 11/25/2004 22:18'!\\nlabelPrefix\\n\\t^ labelPrefix ifNil: [labelPrefix _ self root metaNode edges first label capitalized, ' of']! !\\n\\n!OBListBrowser methodsFor: 'accessing' stamp: 'cwp 10/17/2004 20:54'!\\nlabelPrefix: aString\\n\\tlabelPrefix _ aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBListBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBListBrowser class methodsFor: 'opening' stamp: 'avi 9/17/2005 01:34'!\\nbrowseRoot: aNode\\n\\tself browseRoot: aNode title: self title! !\\n\\n!OBListBrowser class methodsFor: 'opening' stamp: 'avi 9/17/2005 01:21'!\\nbrowseRoot: aNode title: aString \\n\\t(self metaNode: self defaultMetaNode root: aNode selection: nil)\\n\\t\\tlabelPrefix: aString;\\n\\t\\topen\\n\\t! !\\n\\n\\n!OBListBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 17:54'!\\nmaxPanes\\n\\t^ 2! !\\n\\n!OBListBrowser class methodsFor: 'configuration' stamp: 'cwp 12/5/2004 17:54'!\\nminPanes\\n\\t^ 1! !\\nOBMethodNode subclass: #OBMessageNode\\n\\tinstanceVariableNames: 'message'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMessageNode commentStamp: 'cwp 1/8/2005 12:40' prior: 0!\\nAn OBMessageNode refers to a message send in the source code of a method. They are typically used in the 'senders' browser.!\\n\\n\\n!OBMessageNode methodsFor: 'navigating'!\\nimplementors\\n\\t^ self implementorsOf: message! !\\n\\n!OBMessageNode methodsFor: 'navigating'!\\nsendersOfMessage\\n\\t^ self sendersOf: message! !\\n\\n\\n!OBMessageNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:26'!\\nname\\n\\t^ message! !\\n\\n\\n!OBMessageNode methodsFor: 'accessing'!\\nselection\\n\\t| methodNode assoc |\\n\\tmethodNode := Parser new \\n\\t\\t\\t\\t\\tparse: self source\\n\\t\\t\\t\\t\\tclass: self theClass.\\n\\tassoc := (methodNode encoder rawSourceRanges) \\n\\t\\t\\tassociations detect: [:ea | ea key isMessage: message receiver: nil arguments: nil]\\n\\t\\t\\t\\t\\t\\tifNone: [nil -> (1 to: 0)].\\n\\t\\t\\t\\t\\t\\t\\\"Some messages are generated by the compiler.\\\"\\n\\t^ assoc value! !\\n\\n\\n!OBMessageNode methodsFor: 'initializing'!\\nsetMessage: aSelector selector: aSelector2 class: aClass\\n\\tmessage := aSelector.\\n\\tselector := aSelector2.\\n\\tself theClass: aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMessageNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\nfromMethodNode: aMethodNode\\n\\t^ self new \\n\\t\\tsetMessage: aMethodNode selector\\n\\t\\tselector: aMethodNode selector\\n\\t\\tclass: aMethodNode theClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\non: aSelector inMethodNode: aNode\\n\\t^ self \\n\\t\\ton: aSelector \\n\\t\\tinMethod: aNode selector \\n\\t\\tinClass: aNode theClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation' stamp: 'cwp 12/8/2004 23:46'!\\non: aSelector inMethodReference: ref\\n\\t^ self \\n\\t\\ton: aSelector \\n\\t\\tinMethod: ref methodSymbol\\n\\t\\tinClass: ref actualClass! !\\n\\n!OBMessageNode class methodsFor: 'instance creation'!\\non: aSelector inMethod: aSelector2 inClass: classRef\\n\\t^ self new setMessage: aSelector selector: aSelector2 class: classRef! !\\nObject subclass: #OBMetaEdge\\n\\tinstanceVariableNames: 'label selector metaNode'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBMetaEdge commentStamp: 'cwp 1/7/2005 23:20' prior: 0!\\nAn OBMetaEdge is an edge in the browser's metagraph. It represents a message sent to a node to obtain further nodes. It is refered to by the \\\"parent\\\" metanode, and refers to the \\\"child\\\" metanode.\\n\\niVars:\\n\\nlabel \\t\\t- a string describing the metaNode, for filters which allow the user \\n\\t\\t\\t to choose which edges to follow\\nselector\\t- when a node is selected by the user, this message will be \\n\\t\\t\\t sent to it to obtain its children\\nmetaNode \\t- a MetaNode corresponding to the nodes answered by the above message\\n\\t\\t!\\n\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nlabel\\n\\t^ label! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 3/3/2004 00:12'!\\nnodesForParent: aNode\\n\\t^ (aNode perform: selector) do: [:ea | ea metaNode: metaNode]\\n! !\\n\\n!OBMetaEdge methodsFor: 'accessing' stamp: 'cwp 2/7/2004 22:40'!\\nselector\\n\\t^ selector! !\\n\\n\\n!OBMetaEdge methodsFor: 'initializing' stamp: 'cwp 2/7/2004 22:36'!\\nsetLabel: aString selector: aSelector metaNode: aMetaNode\\n\\tlabel _ aString.\\n\\tselector _ aSelector.\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBMetaEdge methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:03'!\\nprintOn: aStream\\n\\taStream nextPutAll: selector printString, '->'. \\n\\tmetaNode shortPrintOn: aStream.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMetaEdge class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMetaEdge class methodsFor: 'as yet unclassified' stamp: 'cwp 2/7/2004 22:35'!\\nlabel: aString selector: aSelector metaNode: aMetaNode\\n\\t^ self new setLabel: aString selector: aSelector metaNode: aMetaNode! !\\n\\n!OBMetaEdge class methodsFor: 'as yet unclassified' stamp: 'cwp 2/9/2004 22:32'!\\nselector: aSelector metaNode: aMetaNode\\n\\t^ self new setLabel: aSelector asString selector: aSelector metaNode: aMetaNode! !\\nObject subclass: #OBMetaNode\\n\\tinstanceVariableNames: 'name filterClass columnClass edges actors displaySelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBMetaNode commentStamp: 'cwp 1/7/2005 23:23' prior: 0!\\nA MetaNode represents a hypothetical node in the browser's domain graph.\\n\\niVars:\\n\\nfilterClass\\t\\t\\t- the class used to filter this hypothetical node's children\\ncolumnClass\\t\\t- the class of column used to display this node's children\\nedges\\t\\t\\t\\t- messages that could be sent to the node to obtain children\\nactors\\t\\t\\t\\t- providers of functionality for manipulating the node\\ndisplaySelector\\t\\t- the message used to retreive a nodes display name!\\n\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 21:41'!\\ndisplaySelector\\n\\t^ displaySelector ifNil: [displaySelector _ #name]! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 12/8/2004 21:42'!\\ndisplaySelector: aSelector\\n\\tdisplaySelector _ aSelector! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 3/6/2004 21:54'!\\nname\\n\\t^ name ifNil: ['MetaNode']! !\\n\\n!OBMetaNode methodsFor: 'accessing' stamp: 'cwp 3/6/2004 21:05'!\\nname: aString\\n\\tname _ aString! !\\n\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 18:59'!\\nactionSetsForNode: aNode\\n\\t^ actors collect: [:actor | actor actionsForNode: aNode]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:01'!\\nactionSetsForParent: aNode\\n\\t^ actors collect: [:actor | actor actionsForParent: aNode]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:00'!\\nactionsForNode: aNode\\n\\t^ (self actionSetsForNode: aNode) gather: [:ea | ea]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 9/14/2004 19:02'!\\nactionsForParent: aNode\\n\\t^ (self actionSetsForParent: aNode) gather: [:ea | ea]! !\\n\\n!OBMetaNode methodsFor: 'actors' stamp: 'cwp 3/3/2004 22:48'!\\naddActor: anActor\\n\\tactors add: anActor.! !\\n\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/9/2004 20:28'!\\nchildAt: aSelector labeled: aString put: aMetaNode\\n\\tedges add: (OBMetaEdge label: aString selector: aSelector metaNode: aMetaNode)! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:35'!\\nchildAt: aSelector put: aMetaNode\\n\\tedges add: (OBMetaEdge selector: aSelector metaNode: aMetaNode)! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:44'!\\nchildren\\n\\t^ edges collect: [:edge | edge metaNode]! !\\n\\n!OBMetaNode methodsFor: 'children' stamp: 'cwp 2/7/2004 22:38'!\\nhasChildren\\n\\t^ edges isEmpty not! !\\n\\n\\n!OBMetaNode methodsFor: 'columns' stamp: 'avi 3/4/2004 03:11'!\\ncolumnClass: aClass\\n\\tcolumnClass _ aClass! !\\n\\n!OBMetaNode methodsFor: 'columns' stamp: 'cwp 11/16/2004 22:03'!\\ncolumnInPanel: aBrowser node: aNode\\n\\tcolumnClass ifNil: [columnClass _ OBColumn].\\n\\t^ columnClass\\n\\t\\tinPanel: aBrowser\\n\\t\\tmetaNode: self\\n\\t\\tnode: aNode! !\\n\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:26'!\\nfilter\\n\\tfilterClass ifNil: [filterClass _ OBFilter].\\n\\t^ filterClass forMetaNode: self! !\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:02'!\\nfilterClass: aClass\\n\\tfilterClass _ aClass! !\\n\\n!OBMetaNode methodsFor: 'filtering' stamp: 'cwp 2/9/2004 21:00'!\\nmetaNode\\n\\t^ self! !\\n\\n\\n!OBMetaNode methodsFor: 'initializing' stamp: 'cwp 12/8/2004 20:06'!\\ninitialize\\n\\tedges _ OrderedCollection new.\\n\\tactors _ OrderedCollection new.! !\\n\\n\\n!OBMetaNode methodsFor: 'metagraph' stamp: 'cwp 2/9/2004 21:12'!\\nedges\\n\\t^ edges! !\\n\\n\\n!OBMetaNode methodsFor: 'nodes' stamp: 'cwp 3/3/2004 00:22'!\\nnodesForParent: aNode\\n\\t^ edges gather: [:edge | edge nodesForParent: aNode]! !\\n\\n\\n!OBMetaNode methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:01'!\\nprintOn: aStream\\n\\taStream nextPutAll: self name;cr.\\n\\tedges do: [:e | e printOn: aStream. aStream cr].! !\\n\\n!OBMetaNode methodsFor: 'printing' stamp: 'dvf 8/16/2005 10:01'!\\nshortPrintOn: aStream\\n\\taStream nextPutAll: self name.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMetaNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMetaNode class methodsFor: 'instance creation' stamp: 'cwp 3/6/2004 21:06'!\\nnamed: aString\\n\\t^ self new name: aString! !\\n\\n!OBMetaNode class methodsFor: 'instance creation' stamp: 'cwp 3/3/2004 23:08'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBClassNode subclass: #OBMetaclassNode\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMetaclassNode commentStamp: 'cwp 1/8/2005 11:29' prior: 0!\\nOBMetaclassNode is essentially the same as an OBClassNode, but overrides a few methods to work properly with metaclasses.!\\n\\n\\n!OBMetaclassNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:57'!\\nbrowse\\n\\t^ OBSystemBrowser openOnClass: self theNonMetaClass ! !\\n\\n\\n!OBMetaclassNode methodsFor: 'displaying' stamp: 'cwp 12/13/2004 00:56'!\\nname \\n\\t^ self nonMetaName! !\\n\\n!OBMetaclassNode methodsFor: 'displaying'!\\nnonMetaName\\n\\t^ self theNonMetaClass name! !\\n\\n\\n!OBMetaclassNode methodsFor: 'initializing'!\\nsetClass: aClass\\n\\tsuper setClass: aClass theMetaClass\\n\\t\\t! !\\nOBClassAwareNode subclass: #OBMethodCategoryNode\\n\\tinstanceVariableNames: 'name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodCategoryNode commentStamp: 'cwp 1/8/2005 12:29' prior: 0!\\nOBMethodCategory represents a category within a ClassOrganization. Instead of an organization definition, OBMethodCategory presents a MethodDefinition with the class' default method template.!\\n\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 23:04'!\\nactions\\n\\t^ {\\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself action: #chaseVars buttonLabel: 'variables' menuLabel: 'chase variables'\\n\\t}\\n! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:50'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass category: name! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions'!\\nfileOut\\n\\tself theClass fileOutCategory: name! !\\n\\n!OBMethodCategoryNode methodsFor: 'actions' stamp: 'cwp 9/19/2004 00:11'!\\nremove\\n\\tself theClass removeCategory: name.\\n\\tself signalDeletion! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfMethodCat:! !\\n\\n!OBMethodCategoryNode methodsFor: 'ancestry'!\\nisDescendantOfMethodCat: other\\n\\t^ (other theClassName = self theClassName) and: [other name = name]! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'accessing'!\\ncategory\\n\\t^ name! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing'!\\ncontainer\\n\\t^ self theClass! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing' stamp: 'cwp 9/14/2005 09:06'!\\nmethodReferences\\n\\t^ (self theClass organization listAtCategoryNamed: name)\\n\\t\\tcollect: [:ea | MethodReference new\\n\\t\\t\\t\\t\\t\\tsetClassSymbol: self theNonMetaClassName\\n\\t\\t\\t\\t\\t\\tclassIsMeta: self theClass isMeta\\n\\t\\t\\t\\t\\t\\tmethodSymbol: ea\\n\\t\\t\\t\\t\\t\\tstringVersion: '']\\n! !\\n\\n!OBMethodCategoryNode methodsFor: 'accessing' stamp: 'dvf 8/16/2005 17:47'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut: $<.\\n\\tself name printOn: aStream.\\n\\taStream nextPut: $>.! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'public'!\\ndefinition\\n\\t^ OBMethodDefinition inCategory: self category inClass: self theClass! !\\n\\n!OBMethodCategoryNode methodsFor: 'public'!\\nname\\n\\t^ name! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'drag and drop' stamp: 'lr 4/6/2006 11:46'!\\ndropOnClass: aNode\\n\\tself methods do: [ :each | each dropOnClass: aNode ].\\n\\taNode signalChildrenChanged.\\n\\t^ true! !\\n\\n!OBMethodCategoryNode methodsFor: 'drag and drop'!\\ndropSelector\\n\\t^ #dropOnMethodCategory:! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'comparing' stamp: 'cwp 12/20/2004 00:53'!\\nhash\\n\\t^ self name hash! !\\n\\n!OBMethodCategoryNode methodsFor: 'comparing' stamp: 'cwp 12/20/2004 00:50'!\\n= other\\n\\tself species = other species ifFalse: [^ false].\\t\\n\\tself theClass = other theClass ifFalse: [^ false].\\n\\t^ self name = other name! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'navigating' stamp: 'dvf 8/19/2005 17:16'!\\nmethods\\n\\t^ self methodReferences collect: [:ref | ref asNode]! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'initializing'!\\nsetName: aString class: aClass\\n\\tname := aString.\\n\\tself theClass: aClass! !\\n\\n\\n!OBMethodCategoryNode methodsFor: 'testing' stamp: 'cwp 6/30/2006 00:48'!\\nhasOrganization\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodCategoryNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodCategoryNode class methodsFor: 'actions' stamp: 'cwp 9/18/2004 22:58'!\\nactionsForParent: aNode\\n\\t^ #()! !\\n\\n\\n!OBMethodCategoryNode class methodsFor: 'instance creation'!\\non: aString inClass: aClassReference\\n\\t^ self new setName: aString class: aClassReference! !\\nOBDefinition subclass: #OBMethodDefinition\\n\\tinstanceVariableNames: 'theClass category source selection callback'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBMethodDefinition commentStamp: 'cwp 1/8/2005 13:20' prior: 0!\\nOBMethodDefinition knows how to present method source in the browser's text pane and compile a new CompiledMethod when the source changes. It implements several safety checks to ensure that methods are not accidentally overwritten.!\\n\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 9/18/2005 14:53'!\\naccept: aText notifying: aController\\n\\t| newSelector |\\n\\tnewSelector := self compileMethod: aText notifying: aController.\\n\\tnewSelector ifNil: [^ false].\\n\\t(self nodeFor: newSelector) demandSelection.\\n\\t^ true! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 10/17/2004 23:16'!\\nredefineSource: aText selector: newSelector\\n\\tnewSelector = self selector \\n\\t\\tifTrue: [source := aText]\\n\\t\\tifFalse: [(self methodNodeFor: newSelector) signalSelection].\\n! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks'!\\nselectedClass\\n\\t^ self theClass! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks'!\\nselection\\n\\t^ selection ifNil: [1 to: (source ifNil: [self text size] ifNotNil: [0])]! !\\n\\n!OBMethodDefinition methodsFor: 'callbacks' stamp: 'cwp 11/29/2004 21:21'!\\ntext\\n\\t^ source \\n\\t\\tifNotNil: [source asText makeSelectorBold]\\n\\t\\tifNil: [self theClass sourceCodeTemplate]! !\\n\\n\\n!OBMethodDefinition methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:36'!\\ncallback: aBlockContext \\n\\tcallback _ aBlockContext! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\ncategory\\n\\t^ category ifNil: [category := self theClass whichCategoryIncludesSelector: self selector]! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\nselector\\n\\t^ source ifNotNil: [Parser new parseSelector: source]! !\\n\\n!OBMethodDefinition methodsFor: 'accessing'!\\ntheClass\\n\\t^ theClass! !\\n\\n\\n!OBMethodDefinition methodsFor: 'compiling'!\\ncompileMethod: aText notifying: aController\\n\\t^ (self confirmMethod: aText)\\n\\t\\tifTrue: [self theClass \\n\\t\\t\\t\\t\\tcompile: aText \\n\\t\\t\\t\\t\\tclassified: self category \\n\\t\\t\\t\\t\\tnotifying: aController]\\n\\t\\tifFalse: [nil]! !\\n\\n!OBMethodDefinition methodsFor: 'compiling' stamp: 'cwp 10/17/2004 23:33'!\\nnodeFor: aSelector\\n\\t^ callback value: aSelector! !\\n\\n\\n!OBMethodDefinition methodsFor: 'confirming' stamp: 'cwp 10/17/2004 22:42'!\\nconfirmMethod: aText\\n\\t| sel |\\n\\tsel _ Parser new parseSelector: aText.\\n\\t^ (self theClass isMeta \\n\\t\\t\\tand: [(self selectorAlreadyDefined: sel) not] \\n\\t\\t\\tand: [Metaclass isScarySelector: sel])\\n\\t\\t\\t\\tifTrue: [self confirmScarySelector: sel]\\n\\t\\t\\t\\tifFalse: [^ true]! !\\n\\n!OBMethodDefinition methodsFor: 'confirming'!\\nconfirmScarySelector: aSelector\\n\\t| prompt |\\n\\tprompt := aSelector, ' is used in the existing class system.\\nOverriding it could cause serious problems.\\nIs this really what you want to do?'.\\n\\n\\t^ OBConfirmationRequest\\n\\t\\tprompt: prompt\\n\\t\\tconfirm: 'Override'! !\\n\\n!OBMethodDefinition methodsFor: 'confirming'!\\nselectorAlreadyDefined: aSelector\\n\\t^ self theClass selectors includes: aSelector! !\\n\\n\\n!OBMethodDefinition methodsFor: 'initializing' stamp: 'cwp 10/17/2004 23:33'!\\nsetClass: aClass category: aString source: aText selection: anInterval\\n\\ttheClass := aClass.\\n\\tcategory := aString.\\n\\tsource := aText.\\n\\tselection := anInterval.\\n\\tcallback := [:sel | OBMethodNode on: sel inClass: theClass]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\ninCategory: aString inClass: aClass\\n\\t^ self \\n\\t\\tselection: nil\\n\\t\\tsource: nil\\n\\t\\tinCategory: aString\\n\\t\\tinClass: aClass! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\nselection: anInterval source: aText inCategory: aCategory inClass: aClass\\n\\t^ self new\\n\\t\\tsetClass: aClass\\n\\t\\tcategory: aCategory\\n\\t\\tsource: aText\\n\\t\\tselection: anInterval! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:07'!\\nselection: anInterval source: aText inClass: aClass\\n\\t^ self \\n\\t\\tselection: anInterval\\n\\t\\tsource: aText\\n\\t\\tinCategory: nil\\n\\t\\tinClass: aClass\\t! !\\n\\n!OBMethodDefinition class methodsFor: 'instance creation' stamp: 'cwp 10/17/2004 23:03'!\\nsource: aText inClass: aClass\\n\\t^ self \\n\\t\\tselection: nil\\n\\t\\tsource: aText\\n\\t\\tinCategory: nil\\n\\t\\tinClass: aClass! !\\nOBClassAwareNode subclass: #OBMethodNode\\n\\tinstanceVariableNames: 'selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodNode commentStamp: 'cwp 1/8/2005 12:37' prior: 0!\\nOBMethodNode wraps a method in a particular class. It supplies an OBMethodDefinition for displaying and editing the source code of the method, and various actions for manipulating the method. It has two roles: first it appears in the right most pane of a standard system browser. Second, it often serves as the root node for an OBListBrowser, and has navigation methods for senders, implementors etc.\\n\\nOBMethodNode also serves as the superclass for nodes that represent *parts* of a method, such as sends of a particular message, references to a class, accesses to a instance variable, etc.!\\n\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/12/2006 15:36'!\\nactions\\n\\t^{ \\n\\t\\tself action: #fileOut withLabel: 'file out'.\\n\\t\\tself browseAction.\\n\\t\\tself browseHierarchyAction.\\n\\t\\tself \\n\\t\\t\\taction: #browseSenders\\n\\t\\t\\twithMenuLabel: 'senders'\\n\\t\\t\\twithButtonLabel: 'senders'\\n\\t\\t\\twithKeystroke: $n\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself \\n\\t\\t\\taction: #browseImplementors\\n\\t\\t\\twithMenuLabel: 'implementors'\\n\\t\\t\\twithButtonLabel: 'implementors'\\n\\t\\t\\twithKeystroke: $m\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(findIcon smallFindIcon)).\\n\\t\\tself \\n\\t\\t\\taction: #browseVersions\\n\\t\\t\\tbuttonLabel: 'versions'\\n\\t\\t\\tmenuLabel: 'versions'.\\n\\t\\tself \\n\\t\\t\\taction: #browseInheritance\\n\\t\\t\\tbuttonLabel: 'inheritance'\\n\\t\\t\\tmenuLabel: 'inheritance'.\\n\\t\\tself \\n\\t\\t\\taction: #chaseVars\\n\\t\\t\\tbuttonLabel: 'variables'\\n\\t\\t\\tmenuLabel: 'chase variables'.\\n\\t\\tself \\n\\t\\t\\taction: #remove\\n\\t\\t\\twithLabel: 'remove'\\n\\t\\t\\twithKeystroke: $x\\n\\t\\t\\twithIcon: (MenuIcons tryIcons: #(deleteIcon smallDeleteIcon)).\\n\\t\\tself moveToPackageAction\\n\\t}\\n! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 18:35'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass selector: selector! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:29'!\\nbrowseClass: aClass\\n\\taClass browseRoot: self copy! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:28'!\\nbrowseImplementors\\n\\tself browseClass: OBImplementorsBrowser! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 18:03'!\\nbrowseInheritance\\n\\tOBInheritanceBrowser openRoot: self inheritanceRoot selection: self! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'avi 9/17/2005 01:28'!\\nbrowseSenders\\n\\tself browseClass: OBSendersBrowser! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/5/2004 15:42'!\\nbrowseVersions\\n\\tOBVersionBrowser openOn: self copy! !\\n\\n!OBMethodNode methodsFor: 'actions'!\\nfileOut\\n\\tself theClass fileOutMethod: selector! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/11/2006 02:43'!\\nmoveToPackage\\n\\t| packagesNames selection packages |\\n\\tpackages := PackageOrganizer default packages \\n\\t\\t\\t\\t\\tasSortedCollection: [:a :b | a packageName <= b packageName].\\n\\tpackagesNames := packages collect: [:ea | ea packageName].\\n\\tselection := OBChoiceRequest prompt: nil labels: packagesNames values: packages.\\n\\tselection ifNotNil: [selection addMethod: self reference].! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 7/12/2006 15:37'!\\nmoveToPackageAction\\n\\t^ self \\n\\t\\taction: #moveToPackage\\n\\t\\twithMenuLabel: 'move to package...'\\n\\t\\twithButtonLabel: 'move method'\\n\\t\\twithKeystroke: $p\\n\\t\\twithIcon: (MenuIcons tryIcons: #(windowIcon smallWindowIcon)).\\n! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 10/18/2004 00:30'!\\nremove\\n\\t| senders choice |\\n\\tsenders _ SystemNavigation default allCallsOn: self selector.\\n\\tsenders isEmpty ifTrue: [^ self doRemove].\\n\\tchoice _ OBChoiceRequest\\n\\t\\t\\t\\tprompt: 'This message has ', senders size asString, ' senders.'\\n\\t\\t\\t\\tlabels: #('Remove it' \\n\\t\\t\\t\\t\\t\\t'Remove, then browse senders' \\n\\t\\t\\t\\t\\t\\t'Don''t remove, but show me those senders' \\n\\t\\t\\t\\t\\t\\t'Forget it -- do nothing -- sorry I asked')\\n\\t\\t\\t\\tvalues: #(doRemove removeAndBrowse simpleBrowseSenders nil).\\n\\tchoice ifNotNil: [^ self perform: choice]\\n! !\\n\\n!OBMethodNode methodsFor: 'actions'!\\nselectMessage\\n\\t| messages sel |\\n\\tmessages := self messageSelectors copyWithFirst: selector.\\n\\tsel := (OBChoiceRequest labels: messages).\\n\\t^ sel ifNotNil: [OBMessageNode on: sel inMethodNode: self]! !\\n\\n!OBMethodNode methodsFor: 'actions' stamp: 'cwp 12/1/2004 00:36'!\\nsource\\n\\t^ (self theClass sourceCodeAt: self selector ifAbsent: [^ '']) \\n\\t\\tasText makeSelectorBold! !\\n\\n\\n!OBMethodNode methodsFor: 'private'!\\naddOverridersOf: aSelector inClass: aClass to: aCollection\\n\\taClass subclasses do: \\n\\t\\t[:ea | (ea includesSelector: aSelector)\\n\\t\\t\\t\\t\\tifTrue: [aCollection add: ea]\\n\\t\\t\\t\\t\\tifFalse: [self addOverridersOf: aSelector inClass: ea to: aCollection]]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 10/18/2004 00:29'!\\ndoRemove\\n\\tself theClass removeSelector: self selector.\\n\\tself signalDeletion! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 12/8/2004 23:48'!\\nimplementorsOf: aSelector\\n\\t^ (SystemNavigation default allImplementorsOf: aSelector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'cwp 12/8/2004 23:49'!\\ninheritanceRoot\\n\\t| rootClass |\\n\\trootClass := (self theClass withAllSuperclasses asArray\\n\\t\\t\\t\\t\\tselect: [:ea | ea includesSelector: self selector]) last.\\n\\t^ OBCollectionNode on: {OBMethodNode \\n\\t\\t\\t\\t\\t\\t\\t\\ton: self selector \\n\\t\\t\\t\\t\\t\\t\\t\\tinClass: rootClass}! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nmessageSelectors\\n\\t^ ((self theClass compiledMethodAt: self selector ifAbsent: [^ #()]) messages) asSortedArray! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nremoveAndBrowse\\n\\tself simpleBrowseSenders.\\n\\tself theClass removeSelector: self selector.\\n\\tself signalDeletion! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nsendersOf: aSelector\\n\\t^ (SystemNavigation default allCallsOn: aSelector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: aSelector inMethodReference: ref]! !\\n\\n!OBMethodNode methodsFor: 'private' stamp: 'avi 9/17/2005 01:29'!\\nsimpleBrowseSenders\\n\\tOBSendersBrowser browseRoot: self! !\\n\\n!OBMethodNode methodsFor: 'private'!\\nsourcePointer\\n\\t^ (self theClass compiledMethodAt: self selector) sourcePointer! !\\n\\n\\n!OBMethodNode methodsFor: 'ancestry'!\\nancestrySelector\\n\\t^ #isDescendantOfMethod: ! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 12/2/2004 23:28'!\\nisDescendantOfMethodCat: aMethodCatNode\\n\\t^ (self theClass organization categoryOfElement: self selector) = aMethodCatNode name! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:55'!\\nisDescendantOfMethodVersion: anOBMethodVersionNode \\n\\t^ false! !\\n\\n!OBMethodNode methodsFor: 'ancestry' stamp: 'cwp 11/28/2004 10:37'!\\nisDescendantOfMethod: other\\n\\t^ other selector = selector\\n\\t\\tand: [self theClass withAllSuperclasses includes: other theClass].\\n\\t! !\\n\\n\\n!OBMethodNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 00:36'!\\ndefinition\\n\\t^ OBMethodDefinition\\n\\t\\tselection: self selection\\n\\t\\tsource: self source\\n\\t\\tinClass: self theClass! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nreference\\n\\t^ self referenceForMethod: selector ofClass: self theClassName! !\\n\\n!OBMethodNode methodsFor: 'accessing' stamp: 'cwp 12/1/2004 00:37'!\\nselection\\n\\t^ 1 to: 0! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nselector\\n\\t^ selector! !\\n\\n!OBMethodNode methodsFor: 'accessing'!\\nsourceFiles\\n\\t^ OBSourceFilesRequest signal! !\\n\\n\\n!OBMethodNode methodsFor: 'drag and drop' stamp: 'lr 4/18/2006 08:55'!\\ndropOnClass: aNode\\n\\taNode theClass \\n\\t\\tcompile: self source\\n\\t\\tclassified: (self theClass organization \\n\\t\\t\\tcategoryOfElement: self selector).\\n\\tInputSensor default shiftPressed\\n\\t\\tifFalse: [ self theClass removeSelector: self selector ].\\n\\taNode signalChildrenChanged.\\n\\t^ true! !\\n\\n!OBMethodNode methodsFor: 'drag and drop' stamp: 'cwp 9/18/2005 19:01'!\\ndropOnMethodCategory: aNode\\n\\n\\t\\\"We don't support dropping on another class yet.\\\"\\n\\taNode theClass = self theClass ifFalse: [^ false].\\n\\t\\n\\tself theClass organization classify: self selector under: aNode name.\\n\\taNode signalChildrenChanged.\\n\\t\\n\\t^ true! !\\n\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'lr 3/29/2006 12:08'!\\ndisplayString\\n\\t^ (self theClass respondsTo: #includesLocalSelector:) \\n\\t\\tifFalse: [ super displayString ]\\n\\t\\tifTrue: [\\n\\t\\t\\t(self theClass includesLocalSelector: selector)\\n\\t\\t\\t\\tifTrue: [ super displayString ]\\n\\t\\t\\t\\tifFalse: [ \\n\\t\\t\\t\\t\\tsuper displayString asText \\n\\t\\t\\t\\t\\t\\taddAttribute: TextEmphasis italic ] ]! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:08'!\\nfullName\\n\\t^ self theClassName, '>>', selector! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/20/2004 23:13'!\\nindentedFullName\\n\\t^ self indent, self fullName! !\\n\\n!OBMethodNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:08'!\\nname\\n\\t^ selector! !\\n\\n\\n!OBMethodNode methodsFor: 'comparing' stamp: 'cwp 12/8/2004 22:07'!\\nhash\\n\\t^ theClass hash bitXor: selector hash! !\\n\\n!OBMethodNode methodsFor: 'comparing' stamp: 'cwp 12/8/2004 22:07'!\\n= other\\n\\t^ (self species = other species)\\n\\t\\tand: [self theClass = other theClass] \\n\\t\\tand: [self selector = other selector]! !\\n\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 1/2/2005 23:12'!\\nimplementors\\n\\t^ self implementorsOf: selector! !\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 22:35'!\\nimplementorsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self implementors! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nmessages\\n\\t^ (((self theClass\\n\\t\\t\\t\\tcompiledMethodAt: self selector \\n\\t\\t\\t\\tifAbsent: [^ #()]) messages) asSortedArray)\\n\\t\\t\\t\\t\\tcollect: [:sel | OBMessageNode \\n\\t\\t\\t\\t\\t\\t\\t\\t\\ton: sel \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinMethod: selector \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tinClass: self theClass]! !\\n\\n!OBMethodNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:49'!\\noverrides\\n\\t| classes |\\n\\tclasses := OrderedCollection new.\\n\\tself addOverridersOf: self selector inClass: self theClass to: classes.\\n\\t^ classes collect: [:ea | OBMethodNode on: selector inClass: ea] ! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nselectorAndMessages\\n\\t^ self messages copyWithFirst: self messageNode! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nsenders\\n\\t^ self sendersOf: selector! !\\n\\n!OBMethodNode methodsFor: 'navigating'!\\nversions\\n\\t^ (OBMethodVersion scan: self sourceFiles from: self sourcePointer)\\n\\t\\tcollect: [:ea | OBMethodVersionNode on: ea]! !\\n\\n\\n!OBMethodNode methodsFor: 'nodes'!\\nmessageNode\\n\\t^ OBMessageNode fromMethodNode: self! !\\n\\n\\n!OBMethodNode methodsFor: 'printing' stamp: 'cwp 12/8/2004 21:59'!\\nprintOn: aStream\\n\\taStream\\n\\t\\tnextPutAll: self class name;\\n\\t\\tnextPut: $<;\\n\\t\\tnextPutAll: self theClass name;\\n\\t\\tnextPut: $#;\\n\\t\\tnextPutAll: self selector;\\n\\t\\tnextPut: $>! !\\n\\n\\n!OBMethodNode methodsFor: 'initializing'!\\nsetReference: aMethodReference\\n\\tself \\n\\t\\tsetSelector: aMethodReference methodSymbol\\n\\t\\tclass: (aMethodReference actualClass)! !\\n\\n!OBMethodNode methodsFor: 'initializing'!\\nsetSelector: aSelector class: aClass\\n\\tselector := aSelector.\\n\\tself theClass: aClass\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodNode class methodsFor: 'instance creation'!\\non: aMethodReference\\n\\t^ self new setReference: aMethodReference! !\\n\\n!OBMethodNode class methodsFor: 'instance creation'!\\non: aSelector inClass: aClassReference\\n\\t^ self new setSelector: aSelector class: aClassReference! !\\nObject subclass: #OBMethodVersion\\n\\tinstanceVariableNames: 'sources pointer classRef className category stamp prior selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBMethodVersion commentStamp: 'cwp 1/8/2005 13:25' prior: 0!\\nOBMethodVerison represents a version of a method found in the .sources or .changes files. It provides methods for parsing the method definition referenced by a source pointer, and for filing in the source to replace the current version of the method.!\\n\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ncategory\\n\\t^ category! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nclassSymbol\\n\\t^ classRef name! !\\n\\n!OBMethodVersion methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:51'!\\nlatest\\n\\t^ self class \\n\\t\\t\\tfromSources: sources \\n\\t\\t\\tandPointer: (classRef theClass compiledMethodAt: selector) sourcePointer! !\\n\\n!OBMethodVersion methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:42'!\\npointer\\n\\t^ pointer! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nselector\\n\\t^ selector ifNil: [self setSelector]! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nsource\\n\\t| file |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tfile position: (sources filePositionFromSourcePointer: pointer).\\n\\t^ file nextChunk asText makeSelectorBold! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\nstamp\\n\\t^ stamp! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ntheClass\\n\\t^ classRef theClass! !\\n\\n!OBMethodVersion methodsFor: 'accessing'!\\ntheClassName\\n\\t^ classRef name! !\\n\\n\\n!OBMethodVersion methodsFor: 'compiling'!\\nfileIn\\n\\t(self theClass) ifNotNilDo: [:class | class\\n\\t\\t\\t\\t\\t\\t \\t\\t\\t\\tcompile: self source \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclassified: self category \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twithStamp: self stamp \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil]\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t! !\\n\\n\\n!OBMethodVersion methodsFor: 'comparing' stamp: 'cwp 10/17/2004 23:45'!\\nhash\\n\\t^ pointer hash! !\\n\\n!OBMethodVersion methodsFor: 'comparing' stamp: 'cwp 10/17/2004 23:45'!\\n= other\\n\\t^ self species = other species and: [self pointer = other pointer]! !\\n\\n\\n!OBMethodVersion methodsFor: 'initializing' stamp: 'cwp 11/6/2004 23:14'!\\nparseChunk: aString\\n\\t| tokens |\\n\\ttokens := Scanner new scanTokens: aString.\\n\\tclassRef := OBClassReference named: tokens first.\\n\\ttokens second = #class\\n\\t\\tifTrue: [classRef beMeta.\\n\\t\\t\\t\\tcategory := tokens fourth.\\n\\t\\t\\t\\tstamp := tokens sixth]\\n\\t\\tifFalse: [category := tokens third.\\n\\t\\t\\t\\ttokens size > 3 ifTrue: [stamp := tokens fifth]].\\n\\ttokens size > 6 ifTrue: [prior := tokens last].! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nparseSource\\n\\t| file position chunk |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tposition := sources filePositionFromSourcePointer: pointer.\\n\\tposition > file size ifTrue: [self error: 'Invalid source pointer'].\\n\\t\\n\\tfile position: (0 max: position-150). \\t\\\"Skip back to before the preamble\\\"\\n\\t\\t[file position < (position-1)] \\t\\\"then pick it up from the front\\\"\\n\\t\\t\\twhileTrue: [chunk := file nextChunk].\\n\\t\\n\\tself parseChunk: chunk.! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nprevious\\n\\t^ prior ifNotNil: [self class fromSources: sources andPointer: prior]! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nsetSelector\\n\\t| file |\\n\\tfile := sources at: (sources fileIndexFromSourcePointer: pointer).\\n\\tfile position: (sources filePositionFromSourcePointer: pointer).\\n\\t^ selector := Parser new parseSelector: file nextChunk.! !\\n\\n!OBMethodVersion methodsFor: 'initializing'!\\nsetSources: aSourceFileArray pointer: aSourcePointer\\n\\tsources := aSourceFileArray.\\n\\tpointer := aSourcePointer.\\n\\tself parseSource.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodVersion class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodVersion class methodsFor: 'instance creation'!\\nfromSources: sources andPointer: pointer\\n\\t^ self new setSources: sources pointer: pointer! !\\n\\n\\n!OBMethodVersion class methodsFor: 'scanning'!\\nscan: sources from: pointer \\n\\t| versions current |\\n\\t\\n\\tversions := OrderedCollection new.\\n\\tcurrent := OBMethodVersion fromSources: sources andPointer: pointer.\\n\\t[current notNil]\\n\\t\\twhileTrue: [versions add: current.\\n\\t\\t\\t\\t\\tcurrent := current previous].\\n\\t^ versions! !\\n\\n!OBMethodVersion class methodsFor: 'scanning'!\\nversionsOfMethod: methodReference \\n\\t| class selector |\\n\\tclass := methodReference actualClass.\\n\\tselector := methodReference methodSymbol.\\n\\t^ self scan: SourceFiles from: (class compiledMethodAt: selector) sourcePointer! !\\nOBClassAwareNode subclass: #OBMethodVersionNode\\n\\tinstanceVariableNames: 'version'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBMethodVersionNode commentStamp: 'cwp 1/8/2005 12:41' prior: 0!\\nOBMethodVersions refer to OBMethodVersions, and are used by the VersionBrowser.!\\n\\n\\n!OBMethodVersionNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:38'!\\nactions\\n\\t^ {\\n\\t\\tself browseAction.\\n\\t \\tself action: #revert buttonLabel: 'revert' menuLabel: 'revert to selected version'\\n\\t}! !\\n\\n!OBMethodVersionNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 21:51'!\\nbrowse\\n\\tOBSystemBrowser openOnClass: self theClass selector: version selector! !\\n\\n!OBMethodVersionNode methodsFor: 'actions'!\\nrevert\\n\\tversion fileIn! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:41'!\\nancestrySelector\\n\\t^ #isDescendantOfMethodVersion:! !\\n\\n!OBMethodVersionNode methodsFor: 'ancestry' stamp: 'cwp 10/17/2004 23:43'!\\nisDescendantOfMethodVersion: aNode\\n\\t^ (version = aNode version)! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:57'!\\ncategory\\n\\t^ self theClass organization categoryOfElement: version selector! !\\n\\n!OBMethodVersionNode methodsFor: 'accessing'!\\nreference\\n\\t^ self referenceForMethod: version selector ofClass: self theClassName.! !\\n\\n!OBMethodVersionNode methodsFor: 'accessing' stamp: 'cwp 10/17/2004 23:44'!\\nversion\\n\\t^ version! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'compiling' stamp: 'cwp 10/17/2004 23:53'!\\ndefinition\\n\\t^ (OBMethodDefinition source: version source inClass: self theClass)\\n\\t\\tcallback: [:sel | \\n\\t\\t\\t\\t\\tversion selector = sel\\n\\t\\t\\t\\t\\t\\tifTrue: [self class on: version latest]\\n\\t\\t\\t\\t\\t\\tifFalse: [OBMethodNode on: sel inClass: self theClass]]! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'displaying' stamp: 'cwp 11/27/2004 21:38'!\\nname\\n\\t| stamp |\\n\\tstamp := version stamp ifNil: ['<timestamp missing>'].\\n\\t^ version theClassName, '>>', version selector, ' ', stamp! !\\n\\n\\n!OBMethodVersionNode methodsFor: 'initializing'!\\nsetVersion: aMethodVersion\\n\\tversion := aMethodVersion.\\n\\tself theClass: version theClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMethodVersionNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMethodVersionNode class methodsFor: 'instance creation'!\\non: aMethodVersion \\n\\t^ self new setVersion: aMethodVersion! !\\nOBFilter subclass: #OBModalFilter\\n\\tinstanceVariableNames: 'selection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Utilities'!\\n!OBModalFilter commentStamp: 'cwp 1/7/2005 23:39' prior: 0!\\nOBModalFilter is used to implement the 'instance/?/class' buttons in a standard class browser. In functional terms it filters the nodes of a column according to the edge of the metagraph that they correspond to. OBModalFilter displays an OBRadioButtonBar in its column's pane, with one button per edge. Only nodes from the currently selected edge are allowed in the column.\\n\\niVars:\\n\\nselection\\t- the currently selected edge!\\n\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 2/25/2004 00:28'!\\nlist\\n\\t^ metaNode edges collect: [:edge | edge label]! !\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 2/9/2004 21:10'!\\nselection\\n\\t^ selection ifNil: [selection _ 1]! !\\n\\n!OBModalFilter methodsFor: 'callbacks' stamp: 'cwp 6/6/2006 00:20'!\\nselection: anInteger\\n\\tselection _ anInteger.\\n\\tself changed: #selection.\\n\\tmonitor listChanged.\\n! !\\n\\n\\n!OBModalFilter methodsFor: 'morphs' stamp: 'cwp 11/27/2004 18:01'!\\nbuttonMorph\\n\\t^ OBRadioButtonBar\\n\\t\\ton: self\\n\\t\\tlist: #list\\n\\t\\tselected: #selection\\n\\t\\tchangeSelected: #selection:! !\\n\\n\\n!OBModalFilter methodsFor: 'public' stamp: 'cwp 3/3/2004 00:23'!\\nnodesForParent: aNode\\n\\t^ self selectedEdge nodesForParent: aNode! !\\n\\n!OBModalFilter methodsFor: 'public' stamp: 'cwp 2/29/2004 14:35'!\\nselectAncestorOf: aNode withParent: parentNode\\n\\t| ancestor |\\n\\t1 \\tto: metaNode edges size \\n\\t \\tdo: [:i | selection _ i.\\n\\t\\t\\tancestor _ (self nodesForParent: parentNode)\\n\\t\\t\\t\\tdetect: [:child | child isAncestorOf: aNode] \\n\\t\\t\\t\\tifNone: [nil].\\n\\t\\t\\tancestor ifNotNil: [self changed: #selection. ^ ancestor]].\\n\\t^ nil! !\\n\\n\\n!OBModalFilter methodsFor: 'queries' stamp: 'cwp 2/9/2004 21:08'!\\nwantsButton\\n\\t^ true! !\\n\\n\\n!OBModalFilter methodsFor: 'selection' stamp: 'cwp 2/9/2004 21:11'!\\nincrementSelection\\n\\tselection _ selection + 1.\\n\\t(selection > metaNode edges size) ifTrue: [selection _ 1].! !\\n\\n!OBModalFilter methodsFor: 'selection' stamp: 'cwp 2/9/2004 21:11'!\\nselectedEdge\\n\\t^ metaNode edges at: self selection ! !\\nObject subclass: #OBMorphicPanelLayout\\n\\tinstanceVariableNames: 'panels'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBMorphicPanelLayout commentStamp: 'cwp 1/7/2005 23:42' prior: 0!\\nOBMorphicPanelLayout implements a somewhat hairy algorithm for layoung out panels in a morphic SystemWindow. It is the default layout strategy used by OBBrowser. Subclasses of OBBrowser may use other layout strategies to customize their appearance.!\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'initializing' stamp: 'cwp 11/21/2004 00:23'!\\nsetPanels: aCollection \\n\\tpanels := aCollection! !\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'public' stamp: 'cwp 11/21/2004 00:26'!\\naddMorphsTo: aMorph\\n\\tself addNavMorphTo: aMorph.\\n\\t(panels size > 1) ifTrue: [self addOtherMorphsTo: aMorph].\\n\\t! !\\n\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:25'!\\naddNavMorphTo: aMorph\\n\\taMorph \\n\\t\\taddMorph: self navigationPanel buildScroller\\n\\t\\tfullFrame: (LayoutFrame fractions: (0 @ 0 extent: 1 @ self columnProportion)).\\n! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:37'!\\naddOtherMorphsTo: aMorph\\n\\t| heights variableCount fraction offset vExtent h nonNavPanels |\\n\\tnonNavPanels := panels reject: [:ea | ea isNavigation].\\n\\tnonNavPanels isEmpty ifTrue: [^ self].\\n\\theights _ nonNavPanels collect: [:ea | ea morphHeight].\\n\\tvariableCount _ heights \\n\\t\\t\\t\\t\\t\\tinject: 0 \\n\\t\\t\\t\\t\\t\\tinto: [:count :ea | ea = 0 ifTrue: [count + 1] ifFalse: [count]].\\n\\tfraction _ self columnProportion.\\n\\toffset _ 0.\\n\\tvExtent _ 1- fraction / variableCount.\\n\\tnonNavPanels with: heights do: [:panel :height | \\n\\t\\th _ height = 0 ifTrue: [vExtent] ifFalse: [0].\\n\\t\\taMorph \\n\\t\\t\\taddMorph: panel morph\\n\\t\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\t\\t\\t\\tfractions: (0@fraction extent: 1@h)\\n\\t\\t\\t\\t\\t\\t\\toffsets: (0@offset corner: 0@height)).\\n\\t\\theight = 0 \\n\\t\\t\\tifTrue: \\t[offset _ 0.\\n\\t\\t\\t\\t\\tfraction _ fraction + vExtent]\\n\\t\\t\\tifFalse: \\t[offset _ offset + height]]\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\t\\t\\t! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:26'!\\ncolumnProportion\\n\\t^ panels size = 1\\n\\t\\tifTrue: [1]\\n\\t\\tifFalse: [0.4]! !\\n\\n!OBMorphicPanelLayout methodsFor: 'private' stamp: 'cwp 11/21/2004 00:28'!\\nnavigationPanel\\n\\t^ panels detect: [:ea | ea isNavigation]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBMorphicPanelLayout class\\n\\tinstanceVariableNames: ''!\\n\\n!OBMorphicPanelLayout class methodsFor: 'intance creation' stamp: 'cwp 11/20/2004 23:32'!\\nfor: aCollection\\n\\t^ self new setPanels: aCollection! !\\nObject subclass: #OBNode\\n\\tinstanceVariableNames: 'metaNode'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBNode commentStamp: 'cwp 3/4/2004 22:20' prior: 0!\\nA node is a wrapper for an object in the browser's domain graph. OBNode is an abstract superclass for concrete nodes which might appear in the browser.\\n\\niVars:\\n\\nmetaNode - the MetaNode which produced this node!\\n\\n\\n!OBNode methodsFor: 'accessing' stamp: 'cwp 3/3/2004 23:24'!\\nmetaNode\\n\\t^ metaNode! !\\n\\n!OBNode methodsFor: 'accessing' stamp: 'cwp 3/3/2004 23:24'!\\nmetaNode: aMetaNode\\n\\tmetaNode _ aMetaNode! !\\n\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 00:44'!\\nancestrySelector\\n\\t^ #isDescendantOf: ! !\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 01:47'!\\nisAncestorOf: aNode\\n\\t^ aNode perform: self ancestrySelector with: self! !\\n\\n!OBNode methodsFor: 'ancestry' stamp: 'cwp 3/3/2004 00:44'!\\nisDescendantOf: aNode\\n\\t^ false! !\\n\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 7/14/2006 12:37'!\\ncorrespondsWith: aNode\\n\\t^ self displayString = aNode displayString! !\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 1/31/2004 14:57'!\\nhash\\n\\t^ self name hash! !\\n\\n!OBNode methodsFor: 'comparing' stamp: 'cwp 1/31/2004 14:57'!\\n= other\\n\\t^ self class = other class and: [self name = other name]! !\\n\\n\\n!OBNode methodsFor: 'displaying' stamp: 'cwp 12/8/2004 21:36'!\\ndisplayString\\n\\t^ self perform: metaNode displaySelector! !\\n\\n!OBNode methodsFor: 'displaying' stamp: 'cwp 8/28/2004 00:14'!\\ntitle\\n\\t^ nil! !\\n\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:28'!\\nacceptDroppedNode: aNode\\n \\t^ aNode perform: self dropSelector with: self\\n! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'avi 2/20/2004 14:00'!\\nasDraggableMorph\\n\\t^(StringMorph contents: self name)\\n\\t\\tcolor: Color white;\\n\\t\\tyourself! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:29'!\\ndropSelector\\n\\t\\\"Override in subclasses\\\"\\n\\t\\n\\t^ #dropOnNode: ! !\\n\\n!OBNode methodsFor: 'drag and drop' stamp: 'cwp 3/2/2004 21:28'!\\nwantsDroppedNode: aNode\\n\\t^ aNode respondsTo: self dropSelector! !\\n\\n\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 2/29/2004 13:49'!\\naccept: aText notifying: aController\\n\\t^ self text: aText! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 1/7/2004 09:25'!\\nactions\\n\\t^ #()! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 3/22/2004 20:48'!\\ndefinition\\n\\t^ self! !\\n\\n!OBNode methodsFor: 'public' stamp: 'dvf 8/17/2005 13:57'!\\ndisplayName\\n\\t\\\"expected to return a decorated text (rather than string) version of name\\\"\\n\\t^self name asText! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 12/10/2003 22:27'!\\nname\\n\\tself subclassResponsibility! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 12/7/2003 19:27'!\\ntext\\n\\t^ ''! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 2/29/2004 18:30'!\\ntextSelection\\n\\t^ 1 to: 0! !\\n\\n!OBNode methodsFor: 'public' stamp: 'cwp 3/14/2004 14:09'!\\ntext: aText\\n\\t^ false! !\\n\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 3/10/2004 00:29'!\\naction: aSelector buttonLabel: buttonString menuLabel: menuString\\n\\t^ OBAction\\n\\t\\tlabel: menuString\\n\\t\\tbuttonLabel: buttonString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 2/3/2004 22:29'!\\naction: aSelector withLabel: aString\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 16:51'!\\naction: aSelector withLabel: aString withIcon: anIcon\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 14:28'!\\naction: aSelector withLabel: aString withKeystroke: aChar\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'hpt 5/17/2004 16:51'!\\naction: aSelector withLabel: aString withKeystroke: aChar withIcon: anIcon\\n\\t^ OBAction\\n\\t\\tlabel: aString\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 12/5/2004 20:11'!\\naction: aSelector withMenuLabel: aString withButtonLabel: aString2 withKeystroke: aChar withIcon: anIcon \\n\\t^OBAction \\n\\t\\tlabel: aString\\n\\t\\tbuttonLabel: aString2\\n\\t\\treceiver: self\\n\\t\\tselector: aSelector\\n\\t\\targuments: #()\\n\\t\\tkeystroke: aChar\\n\\t\\ticon: anIcon! !\\n\\n!OBNode methodsFor: 'utility' stamp: 'cwp 2/7/2004 21:29'!\\nreferenceForMethod: selector ofClass: className\\n\\t| classIsMeta symbol |\\n\\tclassIsMeta _ className endsWith: ' class'.\\n\\tsymbol _ classIsMeta ifTrue: [(className allButLast: 6) asSymbol] ifFalse: [className].\\n\\t^ MethodReference new \\n\\t\\tsetClassSymbol: symbol\\n\\t\\tclassIsMeta: classIsMeta\\n\\t\\tmethodSymbol: selector\\n\\t\\tstringVersion: symbol, '>>', selector! !\\n\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:18'!\\nannounce: anObject\\n\\t^ OBAnnouncer current ifNotNilDo: [:announcer | announcer announce: anObject]! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 01:06'!\\ndemandSelection\\n\\t^ OBAnnouncer current announce: (OBNodeCreated node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalChanged\\n\\tself announce: (OBNodeChanged node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalChildrenChanged\\n\\tself announce: (OBChildrenChanged node: self)! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 12:15'!\\nsignalDeletion\\n\\tself announce: (OBNodeDeleted node: self)\\n! !\\n\\n!OBNode methodsFor: 'updating' stamp: 'cwp 6/4/2006 13:59'!\\nsignalSelection\\n\\t(self announce: OBAboutToChange)\\n\\t\\tisVetoed ifFalse: [self announce: (OBSelectingNode node: self)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNode class methodsFor: 'as yet unclassified' stamp: 'cwp 2/5/2004 20:25'!\\nactionsForParent: aNode\\n\\t^ #()! !\\n\\n!OBNode class methodsFor: 'as yet unclassified' stamp: 'cwp 12/18/2003 22:11'!\\nfromAssociation: anAssociationNode\\n\\t^ self on: anAssociationNode value! !\\nOBActor subclass: #OBNodeActor\\n\\tinstanceVariableNames: 'nodeClass'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Actors'!\\n!OBNodeActor commentStamp: 'cwp 3/5/2004 12:23' prior: 0!\\nFor simplicity, many actions are implemented by the nodes themselves. When the contextual menu for a node is displayed, this Actor gathers those actions and makes them available in to the user.\\n\\nIf a node class is specified, the OBNodeActor will also make available any class side actions provided by the node class. This is convenient for the user, since it makes it possible to invoke an action without first selecting a node. Many 'create' actions are implemented in this way.\\n\\niVars:\\n\\nnodeClass - if not nil, this class's class-side actions will be available to the user as well.!\\n\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 1/23/2004 23:24'!\\nactionsForNode: aNode\\n\\t^ aNode actions! !\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 3/3/2004 22:46'!\\nactionsForParent: aNode\\n\\t^ nodeClass \\n\\t\\tifNotNil: [nodeClass actionsForParent: aNode]\\n\\t\\tifNil: [#()]! !\\n\\n!OBNodeActor methodsFor: 'public' stamp: 'cwp 3/3/2004 22:42'!\\nnodeClass: aClass\\n\\tnodeClass _ aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeActor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeActor class methodsFor: 'as yet unclassified' stamp: 'cwp 3/3/2004 22:51'!\\nonNodeClass: aClass\\n\\t^ self new nodeClass: aClass! !\\nOBAnnouncement subclass: #OBNodeChanged\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeChanged methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:17'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBNodeCreated\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeCreated methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 00:53'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeCreated methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 00:53'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeCreated class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeCreated class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 01:09'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBNodeDeleted\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBNodeDeleted methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode\\n\\t^ node! !\\n\\n!OBNodeDeleted methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBNodeDeleted class\\n\\tinstanceVariableNames: ''!\\n\\n!OBNodeDeleted class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 11:56'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBDefinition subclass: #OBOrganizationDefinition\\n\\tinstanceVariableNames: 'organizer'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Definitions'!\\n!OBOrganizationDefinition commentStamp: 'cwp 1/8/2005 13:31' prior: 0!\\nOBOrganizationDefinition knows how to display and edit the organization of classes or methods by a Categorizer.!\\n\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:21'!\\norganizer: anOrganizer\\n\\torganizer _ anOrganizer! !\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:18'!\\ntext\\n\\t^ organizer asString! !\\n\\n!OBOrganizationDefinition methodsFor: 'as yet unclassified' stamp: 'cwp 1/9/2005 11:45'!\\ntext: aText\\n\\torganizer changeFromString: aText asString.\\n\\t^ true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBOrganizationDefinition class\\n\\tinstanceVariableNames: ''!\\n\\n!OBOrganizationDefinition class methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2004 21:20'!\\non: anOrganizer\\n\\t^ self new organizer: anOrganizer! !\\nRectangleMorph subclass: #OBPane\\n\\tinstanceVariableNames: 'model list button'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPane commentStamp: 'cwp 1/7/2005 23:24' prior: 0!\\nAn OBPane is the visual representation of a column in a browser. It contains a morph to display nodes (typically a PluggableListMorph) and (optionally) a morph for communicating with the column's filter. It's main responsibility is to lay out its submorphs as the filter controls are added and removed.\\n\\niVars:\\n\\nmodel\\t- the OBColumn that controls the node list displayed in this pane\\nlist\\t\\t- the morph which displays the node list, usually a PluggableListMorph\\nbutton\\t- the morph which controls the column's filter, usually an OBRadioButtonBar.!\\n\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/2/2004 00:57'!\\nbuttonHeight\\n\\t^ self hasButton\\n\\t\\tifTrue: [button height]\\n\\t\\tifFalse: [self defaultButtonHeight]\\n! !\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/2/2004 01:10'!\\ndefaultButtonHeight\\n\\t^ 23! !\\n\\n!OBPane methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:19'!\\nnoteNewOwner: aMorph\\n\\tself containingWindow ifNotNilDo: [:window | self adoptPaneColor: window paneColor]! !\\n\\n\\n!OBPane methodsFor: 'geometry' stamp: 'cwp 2/12/2004 18:32'!\\nbounds: aRectangle\\n\\tsuper bounds: aRectangle.\\n\\tself adjustList.\\n\\tself adjustButton.! !\\n\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 18:26'!\\ninitGeometry\\n\\tself\\t\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tcellInset: 0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new.\\n\\t\\t\\n\\tself addMorph: list.\\n\\tlist bounds: self innerBounds.\\n\\t\\t! !\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 18:44'!\\nmodel: anObject\\n\\t\\\"Set my model and make me me a dependent of the given object.\\\"\\n\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel _ anObject.\\n! !\\n\\n!OBPane methodsFor: 'initialization' stamp: 'cwp 2/12/2004 19:17'!\\nsetColumn: aColumn filter: aFilter\\n\\tself model: aColumn.\\n\\tlist _ aColumn listMorph.\\n\\tself initGeometry.\\n\\taFilter ifNotNil: [self addButton: aFilter buttonMorph].! !\\n\\n\\n!OBPane methodsFor: 'testing' stamp: 'cwp 2/12/2004 18:35'!\\nhasButton\\n\\t^ button notNil! !\\n\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 11/2/2004 00:53'!\\naddButton: aButton\\n\\tself hasButton ifTrue: [self removeMorph: button].\\n\\tbutton _ aButton.\\n\\tbutton height: self defaultButtonHeight.\\n\\tself \\n\\t\\taddMorph: button;\\n\\t\\tadjustList;\\n\\t\\tadjustButton! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 11/2/2004 00:50'!\\nadjustButton\\n\\t| inner |\\n\\tself hasButton ifTrue: \\n\\t\\t[inner _ self innerBounds.\\n\\t\\tbutton bounds: (inner withTop: inner bottom - self buttonHeight)]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 18:35'!\\nadjustList\\n\\tself hasButton\\n\\t\\t\\tifFalse: [list bounds: self innerBounds]\\n\\t\\t\\tifTrue: [list bounds: (self innerBounds withHeight: (self height - self buttonHeight))]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 20:29'!\\nremoveButton\\n\\tself hasButton \\n\\t\\tifTrue: [self removeMorph: button.\\n\\t\\t\\t\\tbutton _ nil.\\n\\t\\t\\t\\tself adjustList]! !\\n\\n!OBPane methodsFor: 'updating' stamp: 'cwp 2/12/2004 20:23'!\\nupdate: aSelector\\n\\taSelector = #filter ifFalse: [^ self].\\n\\t(model wantsButton)\\n\\t\\t\\tifTrue: [self addButton: model filter buttonMorph]\\n\\t\\t\\tifFalse: [self removeButton]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPane class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPane class methodsFor: 'instance creation' stamp: 'cwp 2/12/2004 18:11'!\\nforColumn: aColumn\\n\\t^ self forColumn: aColumn withFilter: nil! !\\n\\n!OBPane class methodsFor: 'instance creation' stamp: 'cwp 2/12/2004 18:12'!\\nforColumn: aColumn withFilter: aFilter\\n\\t^ self new setColumn: aColumn filter: aFilter! !\\nRectangleMorph subclass: #OBPaneScroller\\n\\tinstanceVariableNames: 'model sizing panes transform scrollBar'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPaneScroller commentStamp: 'cwp 3/5/2004 12:13' prior: 0!\\nInstances of OBPaneScroller contain the panes which represent columns in a browser. Their primary responsibilities are laying out panes to fit the space available and scrolling them horizontally when there isn't sufficient space. \\n\\niVars:\\n\\nsizing\\t\\t- The number of panes which should exactly fit the available space.\\n\\t\\t \\t During layout, the width of the panes is determined accordingly.\\ntransform\\t- A TransformMorph used for scrolling\\nscrollBar\\t- An OBHorizontalScrollBar used for scrolling!\\n\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 22:03'!\\nmodel\\n\\t^model! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 22:11'!\\nmodel: anObject\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tanObject ifNotNil: [anObject addDependent: self].\\n\\tmodel := anObject! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/17/2004 23:09'!\\npanes\\n\\t^ panes ifNil: [self updatePanes. panes]! !\\n\\n!OBPaneScroller methodsFor: 'accessing' stamp: 'cwp 11/22/2004 23:19'!\\nsizing\\n\\t^ sizing ifNil: [self updateSizing]! !\\n\\n\\n!OBPaneScroller methodsFor: 'defaults' stamp: 'cwp 8/24/2003 15:13'!\\nseparatorWidth\\n\\t^ 4! !\\n\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 11/23/2004 01:28'!\\ninitialize\\n\\tsuper initialize.\\n\\tself \\n\\t\\tcolor: Color red;\\n\\t\\tborderWidth: 0;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\thResizing: #spaceFill.\\n\\tself \\n\\t\\tinitializeTransform;\\n\\t\\tinitializeScrollbar.\\n\\tself startStepping.! !\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 2/8/2004 11:01'!\\ninitializeScrollbar\\n\\tscrollBar _ OBScrollBar new model: self slotName: 'scrollBar'.\\n\\tscrollBar \\n\\t\\tborderWidth: 0;\\n\\t\\tborderColor: #inset;\\n\\t\\theight: self scrollBarHeight.\\n\\tself resizeScrollBar.\\n! !\\n\\n!OBPaneScroller methodsFor: 'initialization' stamp: 'cwp 2/8/2004 10:52'!\\ninitializeTransform\\n\\ttransform _ TransformMorph new.\\n\\ttransform\\n\\t\\tcolor: Color transparent;\\n\\t\\tborderWidth: 0;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tdisableTableLayout;\\n\\t\\tbounds: super innerBounds.\\n\\tself addMorphBack: transform.\\n! !\\n\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:10'!\\nadjustPaneHeight\\n\\t\\\"This gets called after the scrollbar has been shown or hidden, to move the bottom\\n\\tof the panes to the right place.\\\"\\n\\t\\n\\ttransform bounds: self innerBounds.\\n\\ttransform submorphsDo: [:m | m bounds: (m bounds withHeight: self paneHeight)]\\n\\t\\t! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 11/21/2004 23:45'!\\nbounds: aRectangle\\n\\tsuper bounds: aRectangle.\\n\\tself layoutWidgets.\\n\\tself layoutPanes.\\n\\tself setScrollDeltas.\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/26/2004 23:14'!\\ncomputeMorphWidths\\n\\t| paneWidths widths |\\n\\tpaneWidths _ self paneWidthsToFit: self totalPaneWidth.\\n\\twidths _ OrderedCollection new.\\n\\tpaneWidths do: [:w | widths add: w] separatedBy: [widths add: self separatorWidth].\\n\\t^ widths asArray\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:06'!\\ndoLayout\\n\\tself layoutWidgets.\\n\\tself layoutPanes.\\n\\tself hideOrShowScrollBar.\\n\\tself setScrollDeltas.\\n\\tself scrollToRight.! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 10:54'!\\ninnerBounds\\n\\t| rect |\\n\\trect _ super innerBounds.\\n\\t^ self scrollBarIsVisible\\n\\t\\tifTrue: [rect withHeight: rect height - self scrollBarHeight - 1]\\n\\t\\tifFalse: [rect]! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 01:22'!\\nlayoutPanes\\n\\t| widths rect |\\n\\twidths _ self computeMorphWidths.\\n\\trect _ 0@0 extent: (0 @ self paneHeight).\\n\\ttransform submorphs \\n\\t\\t\\t\\t\\twith: widths \\n\\t\\t\\t\\t\\tdo: [:m :w | \\n\\t\\t\\t\\t\\t\\trect _ rect withWidth: w.\\n\\t\\t\\t\\t\\t\\tm bounds: rect.\\n\\t\\t\\t\\t\\t\\trect _ rect translateBy: (w@0)]\\n\\t\\t\\t\\t\\t\\t\\n! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 8/25/2003 22:13'!\\nlayoutWidgets\\n\\t| inner outer |\\n\\touter _ super innerBounds.\\n\\tinner _ self innerBounds.\\n\\ttransform bounds: inner.\\n\\tscrollBar bounds: ((inner left @ inner bottom + 1)\\n\\t\\t\\t\\t\\t\\tcorner: outer bottomRight)! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 11/17/2004 23:09'!\\npaneCount\\n\\t^ self panes size! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 12/6/2003 17:08'!\\npaneHeight\\n\\t^ transform bounds height! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/26/2004 23:14'!\\npaneWidthsToFit: limit\\n\\t| padded |\\n\\tpadded _ Array new: self paneCount.\\n\\tpadded atAllPut: (limit / self sizing) floor.\\n\\t(1 to: limit - padded sum) do: [:i | padded at: i put: (padded at: i) + 1].\\n\\t^ padded\\n\\t\\n\\t! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/8/2004 11:03'!\\nresizeScrollBar\\n\\t| inner outer |\\n\\touter _ super innerBounds.\\n\\tinner _ outer withHeight: outer height - self scrollBarHeight - 1.\\n\\tscrollBar bounds: ((inner left @ inner bottom + 1)\\n\\t\\t\\t\\t\\t\\tcorner: outer bottomRight)! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 8/24/2003 14:29'!\\nscrollBarHeight\\n\\t^ 12! !\\n\\n!OBPaneScroller methodsFor: 'layout' stamp: 'cwp 2/25/2004 20:23'!\\ntotalPaneWidth\\n\\t^ self innerBounds width - ((self sizing - 1) * self separatorWidth)! !\\n\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 12/6/2003 17:06'!\\nclearPanes\\n\\ttransform removeAllMorphs! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/23/2004 01:22'!\\npopPanes: count\\n\\tcount * 2 timesRepeat: [transform removeMorph: transform lastSubmorph].\\n\\tpanes removeLast: count! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/17/2004 22:46'!\\npushPane: aMorph\\n\\taMorph \\n\\t\\tborderWidth: 0;\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #rigid;\\n\\t\\tlayoutInset: 0.\\n\\ttransform hasSubmorphs ifTrue: [transform addMorphBack: self separator].\\n\\ttransform addMorphBack: aMorph.\\n! !\\n\\n!OBPaneScroller methodsFor: 'panes' stamp: 'cwp 11/27/2004 01:03'!\\nseparator\\n\\t^ BorderedSubpaneDividerMorph vertical \\n\\t\\tborderWidth: self separatorWidth / 2;\\n\\t\\tcolor: model defaultBackgroundColor duller;\\n\\t\\tborderRaised.! !\\n\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:44'!\\nhideOrShowScrollBar\\n\\tself isScrollable ifTrue: [self showScrollBar] ifFalse: [self hideScrollBar]! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 11:10'!\\nhideScrollBar\\n\\tself removeMorph: scrollBar.\\n\\tself adjustPaneHeight.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:42'!\\nisScrollable\\n\\t^ self leftoverScrollRange > 0! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 21:04'!\\nleftoverScrollRange\\n\\t^ (self totalScrollRange - self innerBounds width roundTo: self scrollDeltaWidth) max: 0\\n! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 10:56'!\\nscrollBarIsVisible\\n\\t^ submorphs includes: scrollBar! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/23/2003 16:21'!\\nscrollDeltaWidth\\n\\t^ 1! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 12/8/2003 21:42'!\\nscrollToRight\\n\\t^ scrollBar setValue: 1.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 21:14'!\\nsetScrollDeltas\\n\\t| range interval value |\\n\\ttransform hasSubmorphs ifFalse: [scrollBar interval: 1.0. ^ self].\\n\\trange _ self leftoverScrollRange.\\n\\trange = 0 ifTrue: [^ scrollBar interval: 1.0; setValue: 0].\\n\\tinterval _ ((self innerBounds width) / self totalScrollRange) asFloat.\\n\\tvalue _ (transform offset x / range min: 1.0) asFloat.\\n\\tscrollBar interval: interval.\\n\\tscrollBar setValue: value.! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 2/8/2004 11:11'!\\nshowScrollBar\\n\\tself scrollBarIsVisible ifTrue: [^ self].\\n\\tself resizeScrollBar.\\n\\tself addMorphFront: scrollBar.\\n\\tself adjustPaneHeight.\\n\\t! !\\n\\n!OBPaneScroller methodsFor: 'scrolling' stamp: 'cwp 8/25/2003 19:27'!\\ntotalScrollRange\\n\\t| submorphBounds |\\n\\tsubmorphBounds := transform localSubmorphBounds ifNil: [^ 0].\\n\\t^ submorphBounds width\\n! !\\n\\n\\n!OBPaneScroller methodsFor: 'stepping' stamp: 'cwp 11/21/2004 15:38'!\\nstep\\n\\tself reclaimPanes! !\\n\\n!OBPaneScroller methodsFor: 'stepping' stamp: 'cwp 11/24/2004 22:29'!\\nstepTime\\n\\t^ 250! !\\n\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:23'!\\nreclaimPanes\\n\\t| reclaimed |\\n\\treclaimed := model reclaimPanes.\\n\\treclaimed isZero\\tifFalse: \\n\\t\\t[self \\n\\t\\t \\tpopPanes: reclaimed;\\n\\t\\t\\tbasicUpdateSizing;\\n\\t\\t\\tlayoutPanes;\\n\\t\\t\\thideOrShowScrollBar;\\n\\t\\t\\tsetScrollDeltas]! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/21/2004 13:51'!\\nscrollBarValue: value\\n\\ttransform hasSubmorphs ifFalse: [^ self].\\n\\ttransform offset: (self leftoverScrollRange * value) rounded @ 0.! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:34'!\\nupdatePanes\\n\\t| count |\\n\\tmodel ifNil: [panes := Array new. ^ self].\\n\\tcount := panes ifNotNil: [panes size] ifNil: [0].\\n\\tself basicUpdatePanes.\\n\\tself basicUpdateSizing.\\t\\n\\tself layoutPanes.\\n\\tpanes size = count\\n\\t\\tifFalse: [self hideOrShowScrollBar.\\n\\t\\t\\t\\tself setScrollDeltas].\\n\\tpanes size > count ifTrue: [self scrollToRight].\\n\\t^ panes! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/23/2004 01:14'!\\nupdateSizing\\n\\t| old |\\n\\told := sizing.\\n\\tself basicUpdateSizing.\\n\\tsizing = old ifFalse: [self layoutPanes].\\n\\t^sizing! !\\n\\n!OBPaneScroller methodsFor: 'updating' stamp: 'cwp 11/17/2004 22:40'!\\nupdate: aSymbol\\n\\taSymbol = #sizing ifTrue: [^ self updateSizing].\\n\\taSymbol = #panes ifTrue: [^ self updatePanes].! !\\n\\n\\n!OBPaneScroller methodsFor: 'private' stamp: 'cwp 11/23/2004 01:31'!\\nbasicUpdatePanes\\n\\tpanes := model ifNotNil: [model panes] ifNil: [Array new].\\t\\t\\n\\tself clearPanes.\\n\\tpanes do: [:ea | self pushPane: ea].\\n! !\\n\\n!OBPaneScroller methodsFor: 'private' stamp: 'cwp 11/23/2004 01:14'!\\nbasicUpdateSizing\\n\\tmodel ifNil: [sizing := 1] ifNotNil: [sizing := model sizing]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPaneScroller class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPaneScroller class methodsFor: 'as yet unclassified' stamp: 'cwp 11/17/2004 22:01'!\\nwithModel: aModel\\n\\t^ self new model: aModel! !\\nObject subclass: #OBPanel\\n\\tinstanceVariableNames: 'browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Kernel'!\\n!OBPanel commentStamp: 'cwp 1/7/2005 23:23' prior: 0!\\nA panel is an object that manages part of the browser's window. It provides a protocol for receiving notifications when the current domain node changes, and reacts to these changes.!\\n\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 4/17/2006 15:52'!\\nannouncer\\n\\t^ browser announcer! !\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 11/16/2004 21:58'!\\nbrowser\\n\\t^ browser! !\\n\\n!OBPanel methodsFor: 'accessing' stamp: 'cwp 4/17/2006 22:17'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser.\\n\\tself subscribe! !\\n\\n\\n!OBPanel methodsFor: 'testing' stamp: 'cwp 11/20/2004 21:09'!\\nisNavigation\\n\\t^ false! !\\n\\n\\n!OBPanel methodsFor: 'updating' stamp: 'cwp 4/17/2006 19:36'!\\nsubscribe! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBPanel class\\n\\tinstanceVariableNames: ''!\\n\\n!OBPanel class methodsFor: 'instance creation' stamp: 'cwp 8/31/2004 10:46'!\\ninBrowser: aBrowser\\n\\t^ self new browser: aBrowser! !\\nPluggableTextMorph subclass: #OBPluggableTextMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBPluggableTextMorph commentStamp: 'cwp 12/7/2004 00:04' prior: 0!\\nThis is a trivial subclass of PluggableTextMorph. It overrides initialization methods to use an OBTextMorph rather than a regular TextMorph!\\n\\n\\n!OBPluggableTextMorph methodsFor: 'event handling' stamp: 'cwp 10/30/2004 23:07'!\\nkeyStroke: evt\\n\\t^ textMorph keyStroke: evt! !\\n\\n\\n!OBPluggableTextMorph methodsFor: 'model access' stamp: 'cwp 10/30/2004 22:57'!\\nsetText: aText\\n\\tscrollBar setValue: 0.0.\\n\\ttextMorph\\n\\t\\tifNil: [textMorph _ OBTextMorph new\\n\\t\\t\\t\\t\\t\\tcontents: aText wrappedTo: self innerBounds width-6.\\n\\t\\t\\t\\ttextMorph setEditView: self.\\n\\t\\t\\t\\tscroller addMorph: textMorph]\\n\\t\\tifNotNil: [textMorph newContents: aText].\\n\\tself hasUnacceptedEdits: false.\\n\\tself setScrollDeltas.! !\\nRectangleMorph subclass: #OBRadioButtonBar\\n\\tinstanceVariableNames: 'model buttons selection getListSelector getSelectionSelector setSelectionSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBRadioButtonBar commentStamp: 'cwp 1/7/2005 23:27' prior: 0!\\nAn OBRadioButtonBar is similar to a PluggableListMorph except that it displays a row of buttons rather than a vertical list. Clicking on a button selects it.\\n\\nmodel\\t\\t\\t\\t- the model for this button bar\\nbuttons\\t\\t\\t- a collection of OBButtonModels, which are derived from the model's list\\nselection\\t\\t\\t- the index of the currently selected button\\ngetListSelector\\t \\t- the message for getting the list of labels for the buttons\\ngetSelectionSelector\\t- the message for getting the index of the currently selected item\\nsetSelectionSelector\\t- the message for informing the model that a button has been clicked!\\n\\n\\n!OBRadioButtonBar methodsFor: 'accessing' stamp: 'cwp 11/27/2004 02:09'!\\nlist\\n\\tbuttons ifNil: \\n\\t\\t\\t[| labels |\\n\\t\\t\\tlabels := model perform: getListSelector.\\n\\t\\t\\tbuttons := Array new: labels size.\\n\\t\\t\\tlabels withIndexDo: \\n\\t\\t\\t\\t\\t[:label :index | \\n\\t\\t\\t\\t\\tbuttons at: index put: (OBButtonModel withLabel: label inBar: self)].\\n\\t\\t\\tselection := self getSelectionIndex.\\n\\t\\t\\tself].\\n\\t^buttons collect: [:b | b label]! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 11/27/2004 19:18'!\\nisEnabled: aButton\\n\\t^ true! !\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:54'!\\nisSelected: aButton\\n\\t^ (buttons at: selection ifAbsent: [^ false]) == aButton! !\\n\\n!OBRadioButtonBar methodsFor: 'callbacks' stamp: 'cwp 2/24/2004 18:47'!\\npush: aButton\\n\\t| index |\\n\\tindex _ buttons indexOf: aButton.\\n\\tmodel perform: setSelectionSelector with: index.! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'constructing' stamp: 'cwp 11/27/2004 20:58'!\\nadoptPaneColor: aColor\\n\\tself submorphs do: [:ea | ea onColor: aColor darker offColor: aColor lighter]! !\\n\\n!OBRadioButtonBar methodsFor: 'constructing' stamp: 'cwp 11/27/2004 21:02'!\\nnoteNewOwner: aMorph\\n\\t| window |\\n\\twindow := aMorph containingWindow.\\n\\twindow ifNotNil: [self adoptPaneColor: window paneColor]! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'lr 3/23/2006 18:10'!\\ninitGeometry\\n\\tself\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\trubberBandCells: true;\\n\\t\\tcolor: Color transparent;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 2\\n! !\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'cwp 2/22/2004 16:51'!\\nmodel: aModel\\n\\tmodel ifNotNil: [model removeDependent: self].\\n\\tmodel _ aModel.\\n\\tmodel addDependent: self.! !\\n\\n!OBRadioButtonBar methodsFor: 'initialize-release' stamp: 'cwp 2/25/2004 00:36'!\\non: aModel list: listSelector selected: selectionGetter changeSelected: selectionSetter \\n\\tself model: aModel.\\n\\tselection _ 0.\\n\\tgetListSelector _ listSelector.\\n\\tgetSelectionSelector _ selectionGetter.\\n\\tsetSelectionSelector _ selectionSetter.\\n\\tself initGeometry.\\n\\tself updateList.! !\\n\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 18:53'!\\ngetSelectionIndex\\n\\t^ model perform: getSelectionSelector! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/27/2004 17:58'!\\nupdateButtons\\n\\t| labels |\\n\\tlabels := model perform: getListSelector.\\n\\tbuttons := Array new: labels size.\\n\\tlabels withIndexDo: \\n\\t\\t\\t[:label :index | \\n\\t\\t\\tbuttons at: index put: (OBButtonModel withLabel: label inBar: self)].\\n\\tselection := self getSelectionIndex! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/27/2004 17:58'!\\nupdateList\\n\\tself \\n\\t\\tupdateButtons; \\n\\t\\tupdateMorphs! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 11/2/2004 01:09'!\\nupdateMorphs\\n\\tself removeAllMorphs.\\n\\tbuttons do: [:button | self addMorphBack: button morph].\\n\\tself bounds: (self bounds withHeight: submorphs first height)! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:39'!\\nupdateSelection\\n\\t| oldSelection |\\n\\toldSelection _ selection.\\n\\tselection _ self getSelectionIndex.\\n\\tself withButtonAt: oldSelection do: [:button | button selectionChanged].\\n\\tself withSelectedButtonDo: [:button | button selectionChanged]! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/25/2004 00:35'!\\nupdate: aSymbol\\n\\taSymbol = getListSelector ifTrue: [self updateList. ^ self].\\n\\taSymbol = getSelectionSelector ifTrue: [self updateSelection]! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:38'!\\nwithButtonAt: index do: aBlock\\n\\t^ (buttons at: index ifAbsent: [nil]) ifNotNilDo: aBlock! !\\n\\n!OBRadioButtonBar methodsFor: 'updating' stamp: 'cwp 2/24/2004 19:38'!\\nwithSelectedButtonDo: aBlock\\n\\t^ self withButtonAt: selection do: aBlock! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBRadioButtonBar class\\n\\tinstanceVariableNames: ''!\\n\\n!OBRadioButtonBar class methodsFor: 'as yet unclassified' stamp: 'cwp 2/22/2004 16:44'!\\non: aModel list: listSelector selected: selectionSelector changeSelected: changedSelector \\n\\t^ self new\\n\\t\\t\\ton: aModel\\n\\t\\t\\tlist: listSelector\\n\\t\\t\\tselected: selectionSelector\\n\\t\\t\\tchangeSelected: changedSelector! !\\nOBListBrowser subclass: #OBReferencesBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBReferencesBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBReferencesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:22'!\\ndefaultMetaNode\\n\\t| class method |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tmethod := OBMetaNode named: 'References'.\\n\\t\\n\\tclass\\n\\t\\tchildAt: #users put: method;\\n\\t\\taddActor: OBNodeActor new.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\t\\t\\n\\t^ class! !\\n\\n!OBReferencesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:34'!\\ntitle\\n\\t^ 'References to'! !\\nOBAnnouncement subclass: #OBRefreshRequired\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\nObject subclass: #OBRequestor\\n\\tinstanceVariableNames: 'node browser'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/29/2006 00:12'!\\nannounce: anObject\\n\\t^ browser announcer announce: anObject! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:41'!\\nbrowser: aBrowser\\n\\tbrowser _ aBrowser! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:43'!\\ndoesNotUnderstand: aMessage\\n\\t^ aMessage sendTo: browser! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:43'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:38'!\\nrequestNode\\n\\t^ node! !\\n\\n!OBRequestor methodsFor: 'as yet unclassified' stamp: 'cwp 6/29/2006 00:12'!\\nselect: aNode\\n\\t(self announce: OBAboutToChange)\\n\\t\\tisVetoed ifFalse: [self announce: (OBSelectingNode node: aNode)]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBRequestor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBRequestor class methodsFor: 'as yet unclassified' stamp: 'cwp 6/28/2006 00:40'!\\nfor: aBrowser\\n\\t^ self new browser: aBrowser! !\\nSlider subclass: #OBScrollBar\\n\\tinstanceVariableNames: 'upButton downButton pagingArea scrollDelta pageDelta interval menuSelector timeOfMouseDown timeOfLastScroll nextPageDirection currentScrollDelay'\\n\\tclassVariableNames: 'CachedImages UpArrow UpArrow8Bit'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBScrollBar commentStamp: 'cwp 3/5/2004 12:01' prior: 0!\\nThis class is a relic. It was originally created to work around bugs in ScrollBar which prevented it from working correctly in horizontal orientation. At some point the bugs should be fixed, and ScrollBar should be used instead.!\\n\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\ninterval: d\\n\\t\\\"Supply an optional floating fraction so slider can expand to indicate range\\\"\\n\\tinterval _ d min: 1.0.\\n\\tself expandSlider.\\n\\tself computeSlider.! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\npagingArea\\n\\t^pagingArea! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 21:25'!\\nroundedScrollbarLook\\n\\t\\\"Rounded look currently only shows up in flop-out mode\\\"\\n\\t^false and: [self class alwaysShowFlatScrollbarForAlternativeLook not]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDelta\\n\\t^ scrollDelta! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDelta: d1 pageDelta: d2\\n\\t\\\"Supply optional increments for better scrolling of, eg, text\\\"\\n\\tscrollDelta _ d1.\\n\\tpageDelta _ d2.! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 16:26'!\\nsliderColor: aColor\\n\\t\\\"Change the color of the scrollbar to go with aColor.\\\"\\n\\t| buttonColor |\\n\\tsuper sliderColor: aColor.\\n\\tbuttonColor _ self thumbColor.\\n\\tupButton color: buttonColor.\\n\\tdownButton color: buttonColor.\\n\\tslider color: buttonColor.\\n\\tself roundedScrollbarLook\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[self color: Color transparent.\\n\\t\\t\\t\\tpagingArea color: aColor muchLighter.\\n\\t\\t\\t\\tself borderStyle style == #simple \\n\\t\\t\\t\\t\\tifTrue:[self borderColor: aColor darker darker]\\n\\t\\t\\t\\t\\tifFalse:[self borderStyle baseColor: aColor]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[pagingArea color: (aColor alphaMixed: 0.3 with: Color white).\\n\\t\\t\\t\\tself borderWidth: 0]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'cwp 11/23/2003 18:06'!\\nsliderShadowColor\\n\\t^ self roundedScrollbarLook\\n\\t\\tifTrue: [self sliderColor darker]\\n\\t\\tifFalse: [super sliderShadowColor]\\n! !\\n\\n!OBScrollBar methodsFor: 'access' stamp: 'md 2/24/2006 16:27'!\\nthumbColor\\n\\t\\\"Problem: Part of the ScrollBar/Slider code uses 'slider' to mean the entire scrollbar/slider widget, and part of it uses 'slider' to mean only the draggable 'thumb'. This should be cleaned up so that 'thumb' is used instead of 'slider' where appropriate. For now, the meaning of thumbColor is clear, at least.\\\"\\n\\n\\t^self sliderColor alphaMixed: 0.7 with: (Color gray: 0.95).! !\\n\\n\\n!OBScrollBar methodsFor: 'accessing' stamp: 'md 2/24/2006 16:12'!\\nadoptPaneColor: aColor\\n\\t\\\"Adopt the given pane color\\\"\\n\\taColor ifNil:[^self].\\n\\tself sliderColor: aColor.! !\\n\\n!OBScrollBar methodsFor: 'accessing' stamp: 'cwp 11/23/2003 18:06'!\\ncachedImageAt: aKey ifAbsentPut: aBlock\\n\\n\\tCachedImages ifNil: [CachedImages _ Dictionary new].\\n\\t^CachedImages at: aKey ifAbsentPut: aBlock! !\\n\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nbuttonExtent\\n\\t^ bounds isWide\\n\\t\\tifTrue: [11 @ self innerBounds height]\\n\\t\\tifFalse: [self innerBounds width @ 11]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nexpandSlider\\n\\t\\\"Compute the new size of the slider (use the old sliderThickness as a minimum).\\\"\\n\\t| r |\\n\\tr _ self totalSliderArea.\\n\\tslider extent: (bounds isWide\\n\\t\\tifTrue: [((r width * interval) asInteger max: self sliderThickness) @ slider height]\\n\\t\\tifFalse: [slider width @ ((r height * interval) asInteger max: self sliderThickness)])! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nextent: p\\n p x > p y\\n ifTrue: [super extent: (p max: 42@8)]\\n ifFalse: [super extent: (p max: 8@42)]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:06'!\\nsliderExtent\\n\\t\\\"The sliderExtent is now stored in the slider itself, not hardcoded as it is in the superclass.\\\"\\n\\t^slider extent! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:07'!\\nsliderThickness\\n\\t^ self roundedScrollbarLook ifTrue:[15] ifFalse:[super sliderThickness]! !\\n\\n!OBScrollBar methodsFor: 'geometry' stamp: 'cwp 11/23/2003 18:07'!\\ntotalSliderArea\\n\\t| upperBoundsButton |\\n\\tupperBoundsButton _ upButton.\\n\\tupButton bottom > upperBoundsButton bottom\\n\\t\\tifTrue: [upperBoundsButton _ upButton].\\n\\t^ bounds isWide\\n\\t\\tifTrue: [upperBoundsButton bounds topRight corner: downButton bounds bottomLeft]\\n\\t\\tifFalse: [upperBoundsButton bounds bottomLeft corner: downButton bounds topRight].\\n! !\\n\\n\\n!OBScrollBar methodsFor: 'initialization' stamp: 'cwp 11/23/2003 18:07'!\\ninitialize\\n\\tsuper initialize.\\n\\tscrollDelta _ 0.02.\\n\\tpageDelta _ 0.2.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tself borderStyle: ((BorderStyle complexFramed width: 2) \\\"baseColor: Color gray\\\")].! !\\n\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeDownButton\\n\\tdownButton := RectangleMorph\\n\\t\\tnewBounds: (self innerBounds bottomRight - self buttonExtent extent: self buttonExtent)\\n\\t\\tcolor: self thumbColor.\\n\\tdownButton on: #mouseDown send: #scrollDownInit to: self.\\n\\tdownButton on: #mouseUp send: #finishedScrolling to: self.\\n\\tdownButton addMorphCentered: (ImageMorph new image: \\n\\t\\t(self \\n\\t\\t\\tcachedImageAt: (bounds isWide ifTrue: ['right'] ifFalse: ['down']) \\n\\t\\t\\tifAbsentPut: [\\n\\t\\t\\t\\tself upArrow8Bit\\n\\t\\t\\t\\t\\trotateBy: (bounds isWide ifTrue: [#right] ifFalse: [#pi])\\n\\t\\t\\t\\t\\tcenterAt: 0@0\\n\\t\\t\\t]\\n\\t\\t)\\n\\t).\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tdownButton color: Color veryLightGray.\\n\\t\\tdownButton borderStyle: (BorderStyle complexRaised width: 3).\\n\\t] ifFalse:[\\n\\t\\tdownButton setBorderWidth: 1 borderColor: #raised.\\n\\t].\\n\\tself addMorph: downButton.\\n! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeEmbedded: aBool\\n\\t\\\"aBool == true => inboard scrollbar\\n\\taBool == false => flop-out scrollbar\\\"\\n\\tself roundedScrollbarLook ifFalse:[^self].\\n\\taBool ifTrue:[\\n\\t\\tself borderStyle: (BorderStyle inset width: 2).\\n\\t\\tself cornerStyle: #square.\\n\\t] ifFalse:[\\n\\t\\tself borderStyle: (BorderStyle width: 1 color: Color black).\\n\\t\\tself cornerStyle: #rounded.\\n\\t].\\n\\tself removeAllMorphs.\\n\\tself initializeSlider.! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializePagingArea\\n\\tpagingArea := RectangleMorph newBounds: self totalSliderArea\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: (Color r: 0.6 g: 0.6 b: 0.8).\\n\\tpagingArea borderWidth: 0.\\n\\tpagingArea on: #mouseDown send: #scrollPageInit: to: self.\\n\\tpagingArea on: #mouseUp send: #finishedScrolling to: self.\\n\\tself addMorph: pagingArea.\\n\\tself roundedScrollbarLook \\n\\t\\tifTrue:[pagingArea color: (Color gray: 0.9)].! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeSlider\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tself \\n\\t\\t\\tinitializeUpButton;\\n\\t\\t\\tinitializeDownButton;\\n\\t\\t\\tinitializePagingArea.\\n\\t] ifFalse:[\\n\\t\\tself initializeUpButton; \\n\\t\\t\\tinitializeDownButton; \\n\\t\\t\\tinitializePagingArea.\\n\\t].\\n\\tsuper initializeSlider.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tslider cornerStyle: #rounded.\\n\\t\\tslider borderStyle: (BorderStyle complexRaised width: 3).\\n\\t\\tsliderShadow cornerStyle: #rounded.\\n\\t].\\n\\tself sliderColor: self sliderColor.! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\ninitializeUpButton\\n\\tupButton := self roundedScrollbarLook \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[RectangleMorph \\n\\t\\t\\t\\t\\t\\tnewBounds: (self innerBounds topLeft extent: self buttonExtent)]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[RectangleMorph \\n\\t\\t\\t\\t\\t\\tnewBounds: ((self innerBounds topLeft) extent: self buttonExtent)].\\n\\tupButton color: self thumbColor.\\n\\tupButton \\n\\t\\ton: #mouseDown\\n\\t\\tsend: #scrollUpInit\\n\\t\\tto: self.\\n\\tupButton \\n\\t\\ton: #mouseUp\\n\\t\\tsend: #finishedScrolling\\n\\t\\tto: self.\\n\\tupButton \\n\\t\\taddMorphCentered: (ImageMorph new image: (self \\n\\t\\t\\t\\t\\t\\tcachedImageAt: (bounds isWide ifTrue: ['left'] ifFalse: ['up'])\\n\\t\\t\\t\\t\\t\\tifAbsentPut: \\n\\t\\t\\t\\t\\t\\t\\t[bounds isWide \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [self upArrow8Bit rotateBy: #left centerAt: 0 @ 0]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [self upArrow8Bit]])).\\n\\tself roundedScrollbarLook \\n\\t\\tifTrue: \\n\\t\\t\\t[upButton color: Color veryLightGray.\\n\\t\\t\\tupButton borderStyle: (BorderStyle complexRaised width: 3)]\\n\\t\\tifFalse: [upButton setBorderWidth: 1 borderColor: #raised].\\n\\tself addMorph: upButton! !\\n\\n!OBScrollBar methodsFor: 'initialize' stamp: 'cwp 11/23/2003 18:06'!\\nupArrow8Bit\\n\\n\\t\\\"convert to 8-bit and convert white to transparent to avoid gratuitous conversion every time we put one in an ImageMorph\\\"\\n\\n\\t^UpArrow8Bit ifNil: [\\n\\t\\tUpArrow8Bit _ (ColorForm mappingWhiteToTransparentFrom: UpArrow) asFormOfDepth: 8\\n\\t]! !\\n\\n\\n!OBScrollBar methodsFor: 'model access' stamp: 'cwp 11/23/2003 18:06'!\\nsetValue: newValue\\n\\t\\\"Using roundTo: instead of truncateTo: ensures that scrollUp will scroll the same distance as scrollDown.\\\"\\n\\t^ super setValue: (newValue roundTo: scrollDelta)! !\\n\\n\\n!OBScrollBar methodsFor: 'other events' stamp: 'cwp 11/23/2003 18:06'!\\nmenuButtonMouseDown: event\\n\\tevent hand showTemporaryCursor: nil.\\n\\tself use: menuSelector orMakeModelSelectorFor: 'MenuButtonPressed:'\\n\\t\\tin: [:sel | menuSelector _ sel. model perform: sel with: event]! !\\n\\n!OBScrollBar methodsFor: 'other events' stamp: 'cwp 11/23/2003 18:06'!\\nmouseDownInSlider: event\\n\\tinterval = 1.0 ifTrue:\\n\\t\\t[\\\"make the entire scrollable area visible if a full scrollbar is clicked on\\\"\\n\\t\\tself setValue: 0.\\n\\t\\tself model hideOrShowScrollBar].\\n\\tsuper mouseDownInSlider: event! !\\n\\n\\n!OBScrollBar methodsFor: 'scroll timing' stamp: 'cwp 11/23/2003 18:07'!\\nresetTimer\\n\\ttimeOfMouseDown _ Time millisecondClockValue.\\n\\ttimeOfLastScroll _ timeOfMouseDown - 1000 max: 0.\\n\\tnextPageDirection _ nil.\\n\\tcurrentScrollDelay _ nil! !\\n\\n!OBScrollBar methodsFor: 'scroll timing' stamp: 'cwp 11/23/2003 18:07'!\\nwaitForDelay1: delay1 delay2: delay2 \\n\\t\\\"Return true if an appropriate delay has passed since the last scroll operation.\\n\\tThe delay decreases exponentially from delay1 to delay2.\\\"\\n\\n\\t| now scrollDelay |\\n\\ttimeOfLastScroll isNil ifTrue: [self resetTimer].\\t\\\"Only needed for old instances\\\"\\n\\tnow := Time millisecondClockValue.\\n\\t(scrollDelay := currentScrollDelay) isNil \\n\\t\\tifTrue: [scrollDelay := delay1\\t\\\"initial delay\\\"].\\n\\tcurrentScrollDelay := scrollDelay * 9 // 10 max: delay2.\\t\\\"decrease the delay\\\"\\n\\ttimeOfLastScroll := now.\\n\\t^true! !\\n\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollByPage\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 300 delay2: 100) ifFalse: [^ self].\\n\\tnextPageDirection\\n\\t\\tifTrue: [self setValue: (value + pageDelta min: 1.0)]\\n\\t\\tifFalse: [self setValue: (value - pageDelta max: 0.0)]\\n! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollDown\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 200 delay2: 40) ifFalse: [^ self].\\n\\tself setValue: (value + scrollDelta + 0.000001 min: 1.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\ndoScrollUp\\n\\t\\\"Scroll automatically while mouse is down\\\"\\n\\t(self waitForDelay1: 200 delay2: 40) ifFalse: [^ self].\\n\\tself setValue: (value - scrollDelta - 0.000001 max: 0.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nfinishedScrolling\\n\\tself stopStepping.\\n\\tself scrollBarAction: nil.\\n\\tself roundedScrollbarLook ifTrue:[\\n\\t\\tupButton borderStyle: (BorderStyle complexRaised width: upButton borderWidth).\\n\\t\\tdownButton borderStyle: (BorderStyle complexRaised width: downButton borderWidth).\\n\\t] ifFalse:[\\n\\t\\tdownButton borderRaised.\\n\\t\\tupButton borderRaised.\\n\\t].\\n\\n! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollBarAction\\n\\t^self valueOfProperty: #scrollBarAction! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollBarAction: aSymbol\\n\\tself setProperty: #scrollBarAction toValue: aSymbol! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDown\\n\\tself flag: #obsolete.\\n\\tdownButton eventHandler: nil.\\n\\tdownButton on: #mouseDown send: #scrollDownInit to: self.\\n\\tdownButton on: #mouseUp send: #finishedScrolling to: self.\\n\\t^self scrollDownInit! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDownInit\\n\\tdownButton borderInset.\\n\\tself resetTimer.\\n\\tself scrollBarAction: #doScrollDown.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollDown: count\\n\\tself setValue: (value + (scrollDelta * count) + 0.000001 min: 1.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollPageInit: evt\\n\\tself resetTimer.\\n\\tself setNextDirectionFromEvent: evt.\\n\\tself scrollBarAction: #doScrollByPage.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUp\\n\\tself flag: #obsolete.\\n\\tupButton eventHandler: nil.\\n\\tupButton on: #mouseDown send: #scrollUpInit to: self.\\n\\tupButton on: #mouseUp send: #finishedScrolling to: self.\\n\\t^self scrollUpInit! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUpInit\\n\\tupButton borderInset.\\n\\tself resetTimer.\\n\\tself scrollBarAction: #doScrollUp.\\n\\tself startStepping.! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nscrollUp: count\\n\\tself setValue: (value - (scrollDelta * count) - 0.000001 max: 0.0)! !\\n\\n!OBScrollBar methodsFor: 'scrolling' stamp: 'cwp 11/23/2003 18:06'!\\nsetNextDirectionFromEvent: event\\n\\n\\tnextPageDirection _ bounds isWide ifTrue: [\\n\\t\\tevent cursorPoint x >= slider center x\\n\\t]\\n\\tifFalse: [\\n\\t\\tevent cursorPoint y >= slider center y\\n\\t]\\n\\n! !\\n\\n\\n!OBScrollBar methodsFor: 'stepping and presenter' stamp: 'cwp 11/23/2003 18:07'!\\nstep\\n\\t| action |\\n\\taction _ self scrollBarAction.\\n\\taction ifNotNil:[self perform: action].! !\\n\\n\\n!OBScrollBar methodsFor: 'testing' stamp: 'cwp 11/23/2003 18:06'!\\nstepTime\\n\\t^ currentScrollDelay ifNil: [300]! !\\n\\n!OBScrollBar methodsFor: 'testing' stamp: 'cwp 11/23/2003 18:06'!\\nwantsSteps\\n\\t^self scrollBarAction notNil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBScrollBar class\\n\\tinstanceVariableNames: ''!\\n\\n!OBScrollBar class methodsFor: 'as yet unclassified' stamp: 'cwp 11/23/2003 18:07'!\\nalwaysShowFlatScrollbarForAlternativeLook\\n\\t\\\"Set this value to true, if you want to see the flat scrollbar look in flop-out mode as well as inboard. Otherwise the flop-out scrollbar will be rounded and inboard will be flat.\\\"\\n\\t^ false! !\\n\\n\\n!OBScrollBar class methodsFor: 'class initialization' stamp: 'cwp 11/23/2003 18:07'!\\ninitialize \\\"ScrollBar initialize\\\"\\n\\n\\tUpArrow _ Form\\n\\t\\textent: 6@3\\n\\t\\tfromArray: #(2r11e28 2r1111e27 2r111111e26)\\n\\t\\toffset: 0@0.! !\\nOBAnnouncement subclass: #OBSelectingNode\\n\\tinstanceVariableNames: 'node'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBSelectingNode methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode\\n\\t^ node! !\\n\\n!OBSelectingNode methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectingNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectingNode class methodsFor: 'as yet unclassified' stamp: 'cwp 6/4/2006 13:58'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBAnnouncement subclass: #OBSelectionChanged\\n\\tinstanceVariableNames: 'node column'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 4/19/2006 00:53'!\\ncolumn\\n\\t^ column! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 4/19/2006 00:52'!\\ncolumn: aColumn\\n\\tcolumn _ aColumn! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 6/4/2006 12:19'!\\nnode\\n\\t^ column \\n\\t\\tifNil: [node]\\n\\t\\tifNotNil: [column selectedNode]! !\\n\\n!OBSelectionChanged methodsFor: 'accessing' stamp: 'cwp 6/4/2006 12:20'!\\nnode: aNode\\n\\tnode _ aNode! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectionChanged class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectionChanged class methodsFor: 'instance creation' stamp: 'cwp 4/19/2006 00:51'!\\ncolumn: aColumn \\n\\t^ self new column: aColumn! !\\n\\n\\n!OBSelectionChanged class methodsFor: 'as yet unclassified' stamp: 'cwp 4/19/2006 00:31'!\\nnode: aNode\\n\\t^ self new node: aNode! !\\nOBCodeNode subclass: #OBSelectorNode\\n\\tinstanceVariableNames: 'selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBSelectorNode commentStamp: 'cwp 1/8/2005 13:03' prior: 0!\\nOBSelectorNode wraps an instance of Symbol. It typically serves as the root of a senders or implementors OBListBrowser, and is used when cmd-n or cmd-m is invoke from the definition panel, and so no OBMethodNode is available.!\\n\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 12/8/2004 23:48'!\\nimplementors\\n\\t^ (SystemNavigation default allImplementorsOf: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMethodNode on: ref]! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 1/7/2005 22:35'!\\nimplementorsHierarchically\\n\\t^ OBClassAwareNode sortHierarchically: self implementors! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:12'!\\nname\\n\\t^ selector printString! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:12'!\\nselectorAndMessages\\n\\t^ Array with: self! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 11/1/2004 02:22'!\\nsenders\\n\\t^ (SystemNavigation default allCallsOn: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: self selector inMethodReference: ref]! !\\n\\n!OBSelectorNode methodsFor: 'navigating' stamp: 'cwp 10/31/2004 01:48'!\\nsendersOfMessage\\n\\t^ (SystemNavigation default allCallsOn: self selector) asSortedArray\\n\\t\\t\\tcollect: [:ref | OBMessageNode on: self selector inMethodReference: ref]! !\\n\\n\\n!OBSelectorNode methodsFor: 'accessing' stamp: 'cwp 10/31/2004 01:11'!\\nselector\\n\\t^ selector! !\\n\\n!OBSelectorNode methodsFor: 'accessing' stamp: 'cwp 10/31/2004 01:10'!\\nselector: aSelector\\n\\tselector := aSelector! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSelectorNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSelectorNode class methodsFor: 'instance creation' stamp: 'cwp 10/31/2004 01:11'!\\non: aSelector\\n\\t^ self new selector: aSelector! !\\nOBListBrowser subclass: #OBSendersBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSendersBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSendersBrowser class methodsFor: 'as yet unclassified' stamp: 'cwp 3/2/2006 15:31'!\\ndefaultMetaNode\\n\\t| selector list chase |\\n\\tlist := OBMetaNode named: 'Senders'.\\n\\tlist \\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\tchase := OBMetaNode named: 'Send'.\\n\\tchase\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\tchildAt: #senders put: chase;\\n\\t\\taddActor: OBNodeActor new.\\n\\n\\tselector := OBMetaNode named: 'Selector'.\\t\\n\\tselector \\n\\t\\tchildAt: #senders labeled: 'list' put: list;\\n\\t\\tchildAt: #senders labeled: 'chase' put: chase;\\n\\t\\tfilterClass: OBModalFilter.\\n\\n\\t^ selector! !\\n\\n!OBSendersBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:36'!\\ntitle\\n\\t^ 'Senders of'! !\\nObject subclass: #OBService\\n\\tinstanceVariableNames: 'action condition announcer label keystroke icon buttonLabel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Services'!\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/18/2006 18:53'!\\naction\\n\\t^ action! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/18/2006 18:53'!\\naction: aValuable\\n\\taction _ aValuable! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:34'!\\nannouncer\\n\\t^ announcer! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:33'!\\nannouncer: anAnnouncer\\n\\tannouncer _ anAnnouncer! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:38'!\\nbuttonLabel\\n\\t^ buttonLabel! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:39'!\\nbuttonLabel: aString\\n\\tbuttonLabel _ aString! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:40'!\\ncondition\\n\\t^ condition! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 15:40'!\\ncondition: aValuable\\n\\tcondition _ aValuable! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/25/2006 00:41'!\\ndescription\\n\\t^ 'description'! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:24'!\\nicon\\n\\t^ icon! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:24'!\\nicon: anIcon\\n\\ticon _ anIcon! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nkeystroke\\n\\t^ keystroke! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nkeystroke: aCharacter\\n\\tkeystroke _ aCharacter! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 19:04'!\\nlabel\\n\\t^ label! !\\n\\n!OBService methodsFor: 'accessing' stamp: 'cwp 6/24/2006 18:58'!\\nlabel: aString\\n\\tlabel _ aString! !\\n\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 18:46'!\\naddServiceFor: aRequestor toMenu: aMenu\\n\\taMenu\\n\\t\\tadd: self labelWithKeystroke\\n\\t\\ttarget: self \\n\\t\\tselector: #executeFor:\\n\\t\\targument: aRequestor.\\n\\taMenu lastItem isEnabled: self isEnabled.\\n\\tPreferences menuWithIcons & self icon notNil\\n\\t\\tifTrue: [aMenu lastItem icon: self icon].\\n\\taMenu addBlankIconsIfNecessary: MenuIcons blankIcon.! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:41'!\\nbuttonLabelMorph\\n\\t^ StringMorph \\n\\t\\tcontents: self buttonLabel \\n\\t\\tfont: Preferences standardButtonFont! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:41'!\\nbuttonMorph\\n\\t^ (PluggableButtonMorph\\n\\t\\ton: self\\n\\t\\tgetState: nil\\n\\t\\taction: #trigger\\n\\t\\tlabel: #buttonLabelMorph)\\t\\n\\t\\t\\tonColor: Color lightGray lighter offColor: Color lightGray twiceLighter;\\n\\t\\t\\tborderWidth: 2;\\n\\t\\t\\tborderRaised;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\tsetBalloonText: label! !\\n\\n!OBService methodsFor: 'morphic' stamp: 'cwp 6/24/2006 19:05'!\\nlabelWithKeystroke\\n\\t^keystroke\\n\\t\\tifNil: [label]\\n\\t\\tifNotNil: [label, ' (', keystroke asString, ')']! !\\n\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/29/2006 01:12'!\\ncondExecuteFor: aRequestor\\n\\t^ (self isEnabledFor: aRequestor)\\n\\t\\t ifTrue: [self executeFor: aRequestor]! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 18:15'!\\nexecute\\n\\t^ self executeFor: nil! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 18:13'!\\nexecuteFor: aRequestor\\n\\taction valueWithPossibleArgs: {aRequestor}! !\\n\\n!OBService methodsFor: 'execute' stamp: 'cwp 6/24/2006 15:42'!\\ntrigger\\n\\t^ self isEnabled ifTrue: [self execute]! !\\n\\n\\n!OBService methodsFor: 'initialize-release' stamp: 'cwp 6/24/2006 19:05'!\\ninitialize\\n\\taction _ [].\\n\\tcondition _ [true].\\n\\tlabel _ 'a service'.! !\\n\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/29/2006 01:11'!\\nisEnabled\\n\\t^ self isEnabledFor: nil! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/29/2006 01:07'!\\nisEnabledFor: aRequestor\\n\\t^ condition valueWithPossibleArgs: {aRequestor}! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/25/2006 00:43'!\\nuseLineAfter\\n\\t^ false! !\\n\\n!OBService methodsFor: 'testing' stamp: 'cwp 6/24/2006 19:46'!\\nwantsButton\\n\\t^ self buttonLabel notNil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBService class\\n\\tinstanceVariableNames: ''!\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/18/2006 18:53'!\\naction: aValuable\\n\\t^ self new action: aValuable! !\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/24/2006 15:40'!\\naction: aValuable condition: cValuable\\n\\t^ self new \\n\\t\\taction: aValuable;\\n\\t\\tcondition: cValuable;\\n\\t\\tyourself! !\\n\\n!OBService class methodsFor: 'as yet unclassified' stamp: 'cwp 6/24/2006 15:43'!\\nnew\\n\\t^ self basicNew initialize! !\\nOBAnnouncement subclass: #OBServiceScan\\n\\tinstanceVariableNames: 'services'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Announcements'!\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:31'!\\naddService: aService\\n\\tservices add: aService! !\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:31'!\\ninitialize\\n\\tservices _ OrderedCollection new! !\\n\\n!OBServiceScan methodsFor: 'as yet unclassified' stamp: 'cwp 6/25/2006 00:30'!\\nservices\\n\\t^ services! !\\nNotification subclass: #OBSourceFilesRequest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBSourceFilesRequest commentStamp: 'cwp 1/8/2005 13:09' prior: 0!\\nOBSourceFilesRequest is used to work around the fact that Squeak's source files are stored in a global array called SourceFiles. When testing OBMethodVersion and OBVersionBrowser, we don't want to use the real source files, as they are too unpredictable. Instead the test cases supply a source file array with known contents.\\n\\nTherefore, OBMethodVersion never refers directly to the SourceFiles global. Instead it raises an OBSourceFiles request. If this occurs during a test, the test catches the notification and resumes using the test source files. Otherwise, the default action resumes using the global source file array.!\\n\\n\\n!OBSourceFilesRequest methodsFor: 'exceptionDescription'!\\ndefaultAction\\n\\t^ SourceFiles! !\\n\\n!OBSourceFilesRequest methodsFor: 'exceptionDescription' stamp: 'cwp 11/27/2004 22:49'!\\nisBrowseRequest\\n\\t^ false! !\\nOBCodeBrowser subclass: #OBSystemBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBSystemBrowser commentStamp: 'cwp 1/7/2005 23:56' prior: 0!\\nThis is the basic system browser that is the work-horse of Smalltalk development tools. It presents four panes showing class categories, classes, method categories and methods.!\\n\\n\\n!OBSystemBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightGreen\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSystemBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:13'!\\nalphabeticalMetaNode\\n\\t^ self\\n\\t\\timageClass: #classes\\n\\t\\tcomment: #comments\\n\\t\\tmetaclass: #metaclasses\\n! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:54'!\\ndefaultMetaNode\\n\\t^self hierarchicalMetaNode! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'cwp 12/6/2004 22:02'!\\ndefaultRootNode\\n\\t^ OBEnvironmentNode forImage! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:54'!\\nhierarchicalMetaNode\\n\\t^self \\n\\t\\timageClass: #classesHierarchically\\n\\t\\tcomment: #commentsHierarchically\\n\\t\\tmetaclass: #metaclassesHierarchically! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:09'!\\nimageClass: classSel comment: commentSel metaclass: metaclassSel \\n\\t| env classCategory |\\n\\tenv := OBMetaNode named: 'Environment'.\\n\\tclassCategory := OBMetaNode named: 'ClassCategory'.\\n\\tenv childAt: #categories put: classCategory.\\n\\tself addTo: classCategory class: classSel comment: commentSel metaclass: metaclassSel.\\n\\t^env! !\\n\\n!OBSystemBrowser class methodsFor: 'configuration'!\\ntitle\\n\\t^ 'System Browser'! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'initializing'!\\ninitialize\\n\\tself registerInOpenMenu! !\\n\\n!OBSystemBrowser class methodsFor: 'initializing'!\\nregisterInOpenMenu\\n\\tTheWorldMenu registerOpenCommand: {'Image Browser'. {self. #open}}.\\n! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'dvf 8/31/2005 13:17'!\\nonClass: aClass \\n\\t^self selection: aClass asNode! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/15/2004 21:42'!\\nonClass: aClass category: aSymbol\\n\\t^ self selection: (OBMethodCategoryNode on: aSymbol inClass: aClass)! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/5/2004 17:38'!\\nonClass: aClass selector: aSelector\\n\\t^ self selection: (OBMethodNode on: aSelector inClass: aClass)! !\\n\\n!OBSystemBrowser class methodsFor: 'instance creation' stamp: 'cwp 12/15/2004 21:45'!\\nonEnvironment: anEnvironment category: aSymbol\\n\\t^ self selection: (OBClassCategoryNode \\n\\t\\t\\t\\t\\t\\ton: aSymbol \\n\\t\\t\\t\\t\\t\\tinEnvironment: anEnvironment)! !\\n\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 18:32'!\\nopenOnClass: aClass\\n\\t^ (self onClass: aClass) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 21:47'!\\nopenOnClass: aClass category: aSymbol\\n\\t^ (self onClass: aClass category: aSymbol) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 17:38'!\\nopenOnClass: aClass selector: aSelector\\n\\t^ (self onClass: aClass selector: aSelector) open! !\\n\\n!OBSystemBrowser class methodsFor: 'opening' stamp: 'cwp 12/15/2004 21:54'!\\nopenOnEnvironment: anEnvironment category: aSymbol\\n\\t^ (self onEnvironment: anEnvironment category: aSymbol) open! !\\nObject subclass: #OBSystemBrowserAdaptor\\n\\tinstanceVariableNames: 'class selector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Utilities'!\\n!OBSystemBrowserAdaptor commentStamp: 'cwp 1/8/2005 13:35' prior: 0!\\nOBSystemBrowserAdaptor implements the protocol expected by the SystemBrowser app registry, and thus allows OmniBrowser to be chosen as the default system browser. \\n\\nCaveat: because the required protocol is a little ...odd.... it can't be implemented well by OBSystemBrowser directly. OBSystemBrowserAdaptor does this reasonably well, but it has no way to provide a more natural name than its class name to the app registry menu.!\\n\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:50'!\\nlabelString\\n\\t^ 'System Browser'! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:49'!\\nopenEditString: anUndefinedObject \\n\\t^ self! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:49'!\\nsetClass: aClass selector: aSelector \\n\\tclass _ aClass.\\n\\tselector _ aSelector! !\\n\\n\\n!OBSystemBrowserAdaptor methodsFor: 'accessing' stamp: 'cwp 12/5/2004 21:55'!\\nselector\\n\\t^ selector! !\\n\\n!OBSystemBrowserAdaptor methodsFor: 'accessing' stamp: 'cwp 12/5/2004 21:55'!\\ntargetClass\\n\\t^ class! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBSystemBrowserAdaptor class\\n\\tinstanceVariableNames: ''!\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 12/5/2004 22:01'!\\ninitialize\\n\\tself register! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 1/8/2005 21:52'!\\nregister\\n\\tSmalltalk at: #SystemBrowser ifPresent: [:class | class register: self]! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'initializing' stamp: 'cwp 1/8/2005 21:53'!\\nunregister\\n\\tSmalltalk at: #SystemBrowser ifPresent: [:class | class unregister: self]! !\\n\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'lr 4/20/2006 08:48'!\\nfullOnClass: aClass selector: aSelector\\n\\t^ OBSystemBrowser \\n\\t\\topenOnClass: aClass\\n\\t\\tselector: aSelector! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'lr 3/28/2006 09:10'!\\nopen\\n\\tOBSystemBrowser open! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:59'!\\nopenBrowser\\n\\tOBSystemBrowser open! !\\n\\n!OBSystemBrowserAdaptor class methodsFor: 'registry protocol' stamp: 'cwp 12/5/2004 21:56'!\\nopenBrowserView: adaptor label: ignored \\n\\t^ OBSystemBrowser \\n\\t\\topenOnClass: adaptor targetClass \\n\\t\\tselector: adaptor selector! !\\nTextMorphForEditView subclass: #OBTextMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBTextMorph commentStamp: 'cwp 12/7/2004 00:07' prior: 0!\\nThis is a trivial subclass of TextMorph. It overrides editor creation to use OBTextMorphEditor rather than a regular TextMorphEditor.!\\n\\n\\n!OBTextMorph methodsFor: 'private' stamp: 'cwp 10/30/2004 23:06'!\\ninstallEditorToReplace: priorEditor\\n\\t\\\"Install an editor for my paragraph. This constitutes 'hasFocus'.\\n\\tIf priorEditor is not nil, then initialize the new editor from its state.\\n\\tWe may want to rework this so it actually uses the prior editor.\\\"\\n\\n\\t| stateArray |\\n\\tpriorEditor ifNotNil: [stateArray _ priorEditor stateArray].\\n\\teditor _ OBTextMorphEditor new morph: self.\\n\\teditor changeParagraph: self paragraph.\\n\\tpriorEditor ifNotNil: [editor stateArrayPut: stateArray].\\n\\tself selectionChanged.\\n\\t^ editor! !\\nTextMorphEditor subclass: #OBTextMorphEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Morphic'!\\n!OBTextMorphEditor commentStamp: 'cwp 1/7/2005 23:27' prior: 0!\\nOBTextMorphEditor overrides the TextMorphEditors handling of command keys, passing them along to its model for processing, rather than hard-coding their implementations.!\\n\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 01:52'!\\nbrowseIt\\n\\t| symbol |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(symbol _ self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself send: #browseIt: toModelWith: {symbol} orDo: [super browseIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 00:40'!\\nimplementorsOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #implementorsOfIt: toModelWith: {selector} orDo: [super sendersOfIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 01:10'!\\nreferencesToIt\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #referencesToIt: toModelWith: {selector} orDo: [super referencesToIt]! !\\n\\n!OBTextMorphEditor methodsFor: 'actions' stamp: 'cwp 10/31/2004 00:26'!\\nsendersOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| selector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(selector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself send: #sendersOfIt: toModelWith: {selector} orDo: [super sendersOfIt]! !\\n\\n\\n!OBTextMorphEditor methodsFor: 'model access' stamp: 'cwp 10/31/2004 00:24'!\\nsend: aSelector toModelWith: args orDo: aBlock\\n\\tself terminateAndInitializeAround:\\n\\t\\t[(model respondsTo: aSelector)\\n\\t\\t\\tifTrue: [(model perform: aSelector withArguments: args)\\n\\t\\t\\t\\t\\t\\tifFalse: [view flash]]\\n\\t\\t\\tifFalse: aBlock]! !\\nOBInteractionRequest subclass: #OBTextRequest\\n\\tinstanceVariableNames: 'prompt template'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Notifications'!\\n!OBTextRequest commentStamp: 'cwp 3/5/2004 12:35' prior: 0!\\nThis notification is used to ask the user to supply a short piece of text. Its defaultAction is to open a FillInTheBlank.\\n\\niVars:\\n\\nprompt\\t\\t- a string describing the text the user is asked to supply\\ntemplate\\t- a default reply !\\n\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:24'!\\nprompt\\n\\t^ prompt! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:23'!\\nprompt: aString\\n\\tprompt _ aString! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 21:00'!\\ntemplate\\n\\t^ template! !\\n\\n!OBTextRequest methodsFor: 'accessing' stamp: 'cwp 2/2/2004 20:59'!\\ntemplate: aString\\n\\ttemplate _ aString! !\\n\\n\\n!OBTextRequest methodsFor: 'user interaction' stamp: 'cwp 2/2/2004 21:27'!\\ndefaultAction\\n\\tself resume: self requestText! !\\n\\n!OBTextRequest methodsFor: 'user interaction' stamp: 'cwp 2/2/2004 21:27'!\\nrequestText\\n\\t^ FillInTheBlankMorph \\n\\t\\trequest: prompt\\n\\t\\tinitialAnswer: template\\n\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\tinWorld: World\\n\\t\\tonCancelReturn: nil\\n\\t\\tacceptOnCR: true! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBTextRequest class\\n\\tinstanceVariableNames: ''!\\n\\n!OBTextRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/2/2004 21:30'!\\nprompt: aString\\n\\t^ self new prompt: aString; template: ''! !\\n\\n!OBTextRequest class methodsFor: 'as yet unclassified' stamp: 'cwp 2/5/2004 20:31'!\\nprompt: promptString template: templateString\\n\\t^ (self new prompt: promptString; template: templateString) signal! !\\nOBPanel subclass: #OBVarButtonPanel\\n\\tinstanceVariableNames: 'morph'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OmniBrowser-Panels'!\\n!OBVarButtonPanel commentStamp: 'cwp 12/7/2004 00:21' prior: 0!\\nOBVarButtonPanel displays a horizontal row of buttons. In contrast to OBFixedButtonPanel, the buttons on display are updated to reflect the actions appropriate to the currently selected node.!\\n\\n\\n!OBVarButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/27/2004 18:16'!\\nmorph\\n\\t^ morph _ (RectangleMorph new)\\n\\t\\t\\t\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\t\\t\\t\\tlistDirection: #leftToRight;\\n\\t\\t\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\t\\t\\tborderWidth: 0;\\n\\t\\t\\t\\t\\twrapCentering: #center;\\n\\t\\t\\t\\t\\tcellPositioning: #leftCenter;\\n\\t\\t\\t\\t\\trubberBandCells: true;\\n\\t\\t\\t\\t\\tyourself! !\\n\\n!OBVarButtonPanel methodsFor: 'constructing' stamp: 'cwp 11/26/2004 22:41'!\\nmorphHeight\\n\\t^ 25! !\\n\\n\\n!OBVarButtonPanel methodsFor: 'updating' stamp: 'cwp 7/8/2006 12:54'!\\nselectionChanged: ann\\n\\t| node actions |\\n\\tmorph removeAllMorphs.\\n\\tnode _ browser currentNode ifNil: [^ self].\\n\\tactions _ (node metaNode actionsForNode: node) select: [:ea | ea wantsButton].\\n\\tactions do: [:ea | morph addMorphBack: ea buttonMorph]! !\\n\\n!OBVarButtonPanel methodsFor: 'updating' stamp: 'cwp 6/3/2006 22:30'!\\nsubscribe\\n\\tself announcer\\n\\t\\tobserve: OBSelectionChanged\\n\\t\\tsend: #selectionChanged:\\n\\t\\tto: self! !\\nOBClassAwareNode subclass: #OBVariableNode\\n\\tinstanceVariableNames: 'name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Nodes'!\\n!OBVariableNode commentStamp: 'cwp 1/8/2005 12:46' prior: 0!\\nOBVariableNode is an abstract superclass for the two types of variables a class can contain - class variables and instance variables. The only difference between the two subclasses is how they search for methods that refer to them.!\\n\\n\\n!OBVariableNode methodsFor: 'actions' stamp: 'cwp 12/15/2004 22:38'!\\nactions\\n\\t^ {self browseAction}! !\\n\\n\\n!OBVariableNode methodsFor: 'displaying'!\\nname\\n\\t^ name! !\\n\\n\\n!OBVariableNode methodsFor: 'initializing'!\\nsetName: aString class: aClass\\n\\tname := aString.\\n\\tself theClass: aClass! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVariableNode class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVariableNode class methodsFor: 'instance creation'!\\non: instVarName inClass: aClassReference \\n\\t^ self new setName: instVarName class: aClassReference! !\\nOBListBrowser subclass: #OBVariablesBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVariablesBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVariablesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:22'!\\ndefaultMetaNode\\n\\t| class method message var |\\n\\tclass := OBMetaNode named: 'Class'.\\n\\tvar := OBMetaNode named: 'Variable'.\\n\\tmethod := OBMetaNode named: 'Method'.\\n\\tmessage := OBMetaNode named: 'Message'.\\n\\tclass\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #instanceVariables labeled: 'instance' put: var;\\n\\t\\tchildAt: #classVariables labeled: 'class' put: var;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tvar\\n\\t\\tchildAt: #accessors put: method;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tmethod\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #senders put: message;\\n\\t\\tfilterClass: OBModalFilter.\\n\\tmessage\\n\\t\\tdisplaySelector: #fullName;\\n\\t\\taddActor: OBNodeActor new;\\n\\t\\tchildAt: #senders put: message;\\n\\t\\tfilterClass: OBModalFilter.\\n\\t\\n\\t^ class! !\\n\\n!OBVariablesBrowser class methodsFor: 'as yet unclassified' stamp: 'avi 9/17/2005 01:35'!\\ntitle\\n\\t^ 'Variables of'! !\\nOBCodeBrowser subclass: #OBVersionBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'OB-Standard-Browsers'!\\n!OBVersionBrowser commentStamp: 'cwp 1/7/2005 23:58' prior: 0!\\nOBVersionBrowser displays a list of OBMethodVersions, which represent versions of a method present in the source or changes files. !\\n\\n\\n!OBVersionBrowser methodsFor: 'morphic' stamp: 'avi 11/29/2004 21:52'!\\ndefaultBackgroundColor\\n\\t^ Color lightMagenta! !\\n\\n\\n!OBVersionBrowser methodsFor: 'accessing' stamp: 'cwp 11/27/2004 22:28'!\\ndefaultLabel\\n\\t^ 'Versions of ', self root name printString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOBVersionBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'avi 9/17/2005 01:09'!\\ndefaultMetaNode\\n\\t| version |\\n\\tversion := OBMetaNode named: 'Version'.\\n\\tversion addActor: OBNodeActor new.\\n\\t^ (OBMetaNode named: 'Method') \\n\\t\\tchildAt: #versions put: version.! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:32'!\\nmaxPanes\\n\\t^ 1! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:32'!\\nminPanes\\n\\t^ 1! !\\n\\n!OBVersionBrowser class methodsFor: 'configuration' stamp: 'cwp 11/27/2004 22:34'!\\noptionalButtons\\n\\t^ #('browse' 'revert')! !\\n\\n\\n!OBVersionBrowser class methodsFor: 'opening' stamp: 'cwp 12/5/2004 15:42'!\\nopenOn: aMethodVersionNode\\n\\t^ (self root: aMethodVersionNode) open! !\\nProtoObject subclass: #Object\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'DependentsFields'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!Object commentStamp: '<historical>' prior: 0!\\nObject is the root class for almost all of the other classes in the class hierarchy. The exceptions are ProtoObject (the superclass of Object) and its subclasses.\\n\\nClass Object provides default behavior common to all normal objects, such as access, copying, comparison, error handling, message sending, and reflection. Also utility messages that all objects should respond to are defined here.\\n\\nObject has no instance variables, nor should any be added. This is due to several classes of objects that inherit from Object that have special implementations (SmallInteger and UndefinedObject for example) or the VM knows about and depends on the structure and layout of certain standard classes.\\n\\nClass Variables:\\n\\tDependentsFields\\t\\tan IdentityDictionary\\n\\t\\tProvides a virtual 'dependents' field so that any object may have one\\n\\t\\tor more dependent views, synchronized by the changed:/update: protocol.\\n\\t\\tNote that class Model has a real slot for its dependents, and overrides\\n\\t\\tthe associated protocol with more efficient implementations.\\n\\tEventsFields\\t\\t\\tan IdentityDictionary that maps each object to its dependents.\\n\\t\\tRegisters a message send (consisting of a selector and a receiver object)\\n\\t\\twhich should be performed when anEventSymbol is triggered by the receiver.\\n\\t\\tPart of a new event notification framework which could eventually replace\\n\\t\\tthe existing changed/update mechanism. It is intended to be compatible\\n\\t\\twith Dolphin Smalltalk and VSE as much as possible.\\n\\nBecause Object is the root of the inheritance tree, methods are often defined in Object to give all objects special behaviors needed by certain subsystems or applications, or to respond to certain general test messages such as isMorph.!\\n\\n\\n!Object methodsFor: 'accessing' stamp: 'sw 4/30/1998 12:18'!\\naddInstanceVarNamed: aName withValue: aValue\\n\\t\\\"Add an instance variable named aName and give it value aValue\\\"\\n\\tself class addInstVarName: aName asString.\\n\\tself instVarAt: self class instSize put: aValue! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 11:39'!\\nat: index \\n\\t\\\"Primitive. Assumes receiver is indexable. Answer the value of an \\n\\tindexable element in the receiver. Fail if the argument index is not an \\n\\tInteger or is out of bounds. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 60>\\n\\tindex isInteger ifTrue:\\n\\t\\t[self class isVariable\\n\\t\\t\\tifTrue: [self errorSubscriptBounds: index]\\n\\t\\t\\tifFalse: [self errorNotIndexable]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self at: index asInteger]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nat: index modify: aBlock\\n\\t\\\"Replace the element of the collection with itself transformed by the block\\\"\\n\\t^ self at: index put: (aBlock value: (self at: index))! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 13:08'!\\nat: index put: value \\n\\t\\\"Primitive. Assumes receiver is indexable. Store the argument value in \\n\\tthe indexable element of the receiver indicated by index. Fail if the \\n\\tindex is not an Integer or is out of bounds. Or fail if the value is not of \\n\\tthe right type for this kind of collection. Answer the value that was \\n\\tstored. Essential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 61>\\n\\tindex isInteger ifTrue:\\n\\t\\t[self class isVariable\\n\\t\\t\\tifTrue: [(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]]\\n\\t\\t\\tifFalse: [self errorNotIndexable]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self at: index asInteger put: value]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing' stamp: 'yo 9/20/2004 10:22'!\\nbasicAddInstanceVarNamed: aName withValue: aValue\\n\\t\\\"Add an instance variable named aName and give it value aValue\\\"\\n\\tself class addInstVarName: aName asString.\\n\\tself instVarAt: self class instSize put: aValue! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicAt: index \\n\\t\\\"Primitive. Assumes receiver is indexable. Answer the value of an \\n\\tindexable element in the receiver. Fail if the argument index is not an \\n\\tInteger or is out of bounds. Essential. Do not override in a subclass. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 60>\\n\\tindex isInteger ifTrue: [self errorSubscriptBounds: index].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self basicAt: index asInteger]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicAt: index put: value \\n\\t\\\"Primitive. Assumes receiver is indexable. Store the second argument \\n\\tvalue in the indexable element of the receiver indicated by index. Fail \\n\\tif the index is not an Integer or is out of bounds. Or fail if the value is \\n\\tnot of the right type for this kind of collection. Answer the value that \\n\\twas stored. Essential. Do not override in a subclass. See Object \\n\\tdocumentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 61>\\n\\tindex isInteger\\n\\t\\tifTrue: [(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]].\\n\\tindex isNumber\\n\\t\\tifTrue: [^self basicAt: index asInteger put: value]\\n\\t\\tifFalse: [self errorNonIntegerIndex]! !\\n\\n!Object methodsFor: 'accessing'!\\nbasicSize\\n\\t\\\"Primitive. Answer the number of indexable variables in the receiver. \\n\\tThis value is the same as the largest legal subscript. Essential. Do not \\n\\toverride in any subclass. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 62>\\n\\t\\\"The number of indexable fields of fixed-length objects is 0\\\"\\n\\t^0\\t! !\\n\\n!Object methodsFor: 'accessing'!\\nbindWithTemp: aBlock\\n\\t^ aBlock value: self value: nil! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 10/7/2004 15:43'!\\nifNil: nilBlock ifNotNilDo: aBlock \\n\\t\\\"Evaluate aBlock with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'di 11/8/2000 21:04'!\\nifNotNilDo: aBlock\\n\\t\\\"Evaluate the given block with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 10/7/2004 15:43'!\\nifNotNilDo: aBlock ifNil: nilBlock\\n\\t\\\"Evaluate aBlock with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'ajh 1/21/2003 12:59'!\\nin: aBlock\\n\\t\\\"Evaluate the given block with the receiver as its argument.\\\"\\n\\n\\t^ aBlock value: self\\n! !\\n\\n!Object methodsFor: 'accessing' stamp: 'sw 10/17/2000 11:15'!\\npresenter\\n\\t\\\"Answer the presenter object associated with the receiver. For morphs, there is in effect a clear containment hierarchy of presenters (accessed via their association with PasteUpMorphs); for arbitrary objects the hook is simply via the current world, at least at present.\\\"\\n\\n\\t^ self currentWorld presenter! !\\n\\n!Object methodsFor: 'accessing'!\\nreadFromString: aString\\n\\t\\\"Create an object based on the contents of aString.\\\"\\n\\n\\t^self readFrom: (ReadStream on: aString)! !\\n\\n!Object methodsFor: 'accessing' stamp: 'di 3/29/1999 13:10'!\\nsize\\n\\t\\\"Primitive. Answer the number of indexable variables in the receiver. \\n\\tThis value is the same as the largest legal subscript. Essential. See Object \\n\\tdocumentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 62>\\n\\tself class isVariable ifFalse: [self errorNotIndexable].\\n\\t^ 0! !\\n\\n!Object methodsFor: 'accessing' stamp: 'md 5/16/2006 12:34'!\\nyourself\\n\\t\\\"Answer self.\\\"\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'associating' stamp: 'md 7/22/2005 16:03'!\\n-> anObject\\n\\t\\\"Answer an Association between self and anObject\\\"\\n\\n\\t^Association basicNew key: self value: anObject! !\\n\\n\\n\\n!Object methodsFor: 'binding'!\\nbindingOf: aString\\n\\t^nil! !\\n\\n\\n!Object methodsFor: 'casing'!\\ncaseOf: aBlockAssociationCollection\\n\\t\\\"The elements of aBlockAssociationCollection are associations between blocks.\\n\\t Answer the evaluated value of the first association in aBlockAssociationCollection\\n\\t whose evaluated key equals the receiver. If no match is found, report an error.\\\"\\n\\n\\t^ self caseOf: aBlockAssociationCollection otherwise: [self caseError]\\n\\n\\\"| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z\\\"\\n\\\"| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z\\\"\\n\\\"The following are compiled in-line:\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}\\\"! !\\n\\n!Object methodsFor: 'casing'!\\ncaseOf: aBlockAssociationCollection otherwise: aBlock\\n\\t\\\"The elements of aBlockAssociationCollection are associations between blocks.\\n\\t Answer the evaluated value of the first association in aBlockAssociationCollection\\n\\t whose evaluated key equals the receiver. If no match is found, answer the result\\n\\t of evaluating aBlock.\\\"\\n\\n\\taBlockAssociationCollection associationsDo:\\n\\t\\t[:assoc | (assoc key value = self) ifTrue: [^assoc value value]].\\n\\t^ aBlock value\\n\\n\\\"| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]\\\"\\n\\\"| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]\\\"\\n\\\"The following are compiled in-line:\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]\\\"\\n\\\"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]\\\"! !\\n\\n\\n!Object methodsFor: 'class membership'!\\nclass\\n\\t\\\"Primitive. Answer the object which is the receiver's class. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 111>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'class membership' stamp: 'sw 9/27/2001 15:51'!\\ninheritsFromAnyIn: aList\\n\\t\\\"Answer whether the receiver inherits from any class represented by any element in the list. The elements of the list can be classes, class name symbols, or strings representing possible class names. This allows speculative membership tests to be made even when some of the classes may not be known to the current image, and even when their names are not interned symbols.\\\"\\n\\n\\t| aClass |\\n\\taList do:\\n\\t\\t[:elem | Symbol hasInterned: elem asString ifTrue: \\n\\t\\t\\t[:elemSymbol | (((aClass _ Smalltalk at: elemSymbol ifAbsent: [nil]) isKindOf: Class)\\n\\t\\t\\t\\t\\t\\tand: [self isKindOf: aClass])\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[^ true]]].\\n\\t^ false\\n\\n\\n\\\"\\n{3. true. 'olive'} do:\\n\\t[:token |\\n\\t\\t {{#Number. #Boolean}. {Number. Boolean }. {'Number'. 'Boolean'}} do:\\n\\t\\t\\t[:list |\\n\\t\\t\\t\\tTranscript cr; show: token asString, ' list element provided as a ', list first class name, ' - ', (token inheritsFromAnyIn: list) asString]]\\n\\\"! !\\n\\n!Object methodsFor: 'class membership'!\\nisKindOf: aClass \\n\\t\\\"Answer whether the class, aClass, is a superclass or class of the receiver.\\\"\\n\\n\\tself class == aClass\\n\\t\\tifTrue: [^true]\\n\\t\\tifFalse: [^self class inheritsFrom: aClass]! !\\n\\n!Object methodsFor: 'class membership' stamp: 'sw 2/16/98 02:08'!\\nisKindOf: aClass orOf: anotherClass\\n\\t\\\"Answer whether either of the classes, aClass or anotherClass,, is a superclass or class of the receiver. A convenience; could be somewhat optimized\\\"\\n\\t^ (self isKindOf: aClass) or: [self isKindOf: anotherClass]! !\\n\\n!Object methodsFor: 'class membership'!\\nisMemberOf: aClass \\n\\t\\\"Answer whether the receiver is an instance of the class, aClass.\\\"\\n\\n\\t^self class == aClass! !\\n\\n!Object methodsFor: 'class membership'!\\nrespondsTo: aSymbol \\n\\t\\\"Answer whether the method dictionary of the receiver's class contains \\n\\taSymbol as a message selector.\\\"\\n\\n\\t^self class canUnderstand: aSymbol! !\\n\\n!Object methodsFor: 'class membership' stamp: 'tk 10/21/1998 12:38'!\\nxxxClass\\n\\t\\\"For subclasses of nil, such as ObjectOut\\\"\\n\\t^ self class! !\\n\\n\\n!Object methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'!\\ncloseTo: anObject\\n\\t\\\"Answer whether the receiver and the argument represent the same\\n\\tobject. If = is redefined in any subclass, consider also redefining the\\n\\tmessage hash.\\\"\\n\\n\\t| ans |\\n\\t[ans _ self = anObject] ifError: [:aString :aReceiver | ^ false].\\n\\t^ ans! !\\n\\n!Object methodsFor: 'comparing'!\\nhash\\n\\t\\\"Answer a SmallInteger whose value is related to the receiver's identity.\\n\\tMay be overridden, and should be overridden in any classes that define = \\\"\\n\\n\\t^ self identityHash! !\\n\\n!Object methodsFor: 'comparing' stamp: 'pm 9/23/97 09:36'!\\nhashMappedBy: map\\n\\t\\\"Answer what my hash would be if oops changed according to map.\\\"\\n\\n\\t^map newHashFor: self! !\\n\\n!Object methodsFor: 'comparing' stamp: 'di 9/27/97 20:23'!\\nidentityHashMappedBy: map\\n\\t\\\"Answer what my hash would be if oops changed according to map.\\\"\\n\\n\\t^map newHashFor: self! !\\n\\n!Object methodsFor: 'comparing' stamp: 'sw 8/20/1998 12:34'!\\nidentityHashPrintString\\n\\t\\\"'fred' identityHashPrintString\\\"\\n\\n\\t^ '(', self identityHash printString, ')'! !\\n\\n!Object methodsFor: 'comparing' stamp: 'ajh 2/2/2002 15:02'!\\nliteralEqual: other\\n\\n\\t^ self class == other class and: [self = other]! !\\n\\n!Object methodsFor: 'comparing'!\\n= anObject \\n\\t\\\"Answer whether the receiver and the argument represent the same \\n\\tobject. If = is redefined in any subclass, consider also redefining the \\n\\tmessage hash.\\\"\\n\\n\\t^self == anObject! !\\n\\n!Object methodsFor: 'comparing'!\\n~= anObject \\n\\t\\\"Answer whether the receiver and the argument do not represent the \\n\\tsame object.\\\"\\n\\n\\t^self = anObject == false! !\\n\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'!\\nadaptToFloat: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Float,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:14'!\\nadaptToFraction: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Fraction,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'!\\nadaptToInteger: rcvr andSend: selector\\n\\t\\\"If no method has been provided for adapting an object to a Integer,\\n\\tthen it may be adequate to simply adapt it to a number.\\\"\\n\\t^ self adaptToNumber: rcvr andSend: selector! !\\n\\n!Object methodsFor: 'converting' stamp: 'rw 4/27/2002 07:48'!\\nasActionSequence\\n\\n\\t^WeakActionSequence with: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'!\\nasActionSequenceTrappingErrors\\n\\n\\t^WeakActionSequenceTrappingErrors with: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'svp 5/16/2000 18:14'!\\nasDraggableMorph\\n\\t^(StringMorph contents: self printString)\\n\\t\\tcolor: Color white;\\n\\t\\tyourself! !\\n\\n!Object methodsFor: 'converting' stamp: 'sma 5/12/2000 17:39'!\\nasOrderedCollection\\n\\t\\\"Answer an OrderedCollection with the receiver as its only element.\\\"\\n\\n\\t^ OrderedCollection with: self! !\\n\\n!Object methodsFor: 'converting'!\\nasString\\n\\t\\\"Answer a string that represents the receiver.\\\"\\n\\n\\t^ self printString ! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 3/11/2003 10:27'!\\nasStringOrText\\n\\t\\\"Answer a string that represents the receiver.\\\"\\n\\n\\t^ self printString ! !\\n\\n!Object methodsFor: 'converting'!\\nas: aSimilarClass\\n\\t\\\"Create an object of class aSimilarClass that has similar contents to the receiver.\\\"\\n\\n\\t^ aSimilarClass newFrom: self! !\\n\\n!Object methodsFor: 'converting' stamp: 'RAA 8/2/1999 12:41'!\\ncomplexContents\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:37'!\\nmustBeBoolean\\n\\t\\\"Catches attempts to test truth of non-Booleans. This message is sent from the VM. The sending context is rewound to just before the jump causing this exception.\\\"\\n\\n\\t^ self mustBeBooleanIn: thisContext sender! !\\n\\n!Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:40'!\\nmustBeBooleanIn: context\\n\\t\\\"context is the where the non-boolean error occurred. Rewind context to before jump then raise error.\\\"\\n\\n\\t| proceedValue |\\n\\tcontext skipBackBeforeJump.\\n\\tproceedValue _ NonBooleanReceiver new\\n\\t\\tobject: self;\\n\\t\\tsignal: 'proceed for truth.'.\\n\\t^ proceedValue ~~ false! !\\n\\n!Object methodsFor: 'converting' stamp: 'sw 3/26/2001 12:12'!\\nprintDirectlyToDisplay\\n\\t\\\"For debugging: write the receiver's printString directly to the display at (0, 100); senders of this are detected by the check-for-slips mechanism.\\\"\\n\\n\\tself asString displayAt: 0@100\\n\\n\\\"StringMorph someInstance printDirectlyToDisplay\\\"! !\\n\\n!Object methodsFor: 'converting' stamp: 'RAA 3/31/1999 12:13'!\\nwithoutListWrapper\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'copying'!\\nclone\\n\\n\\t<primitive: 148>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 8/18/2001 21:25'!\\ncopy\\n\\t\\\"Answer another instance just like the receiver. Subclasses typically override postCopy; they typically do not override shallowCopy.\\\"\\n\\n\\t^self shallowCopy postCopy! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 8/20/1998 16:01'!\\ncopyAddedStateFrom: anotherObject\\n\\t\\\"Copy over the values of instance variables added by the receiver's class from anotherObject to the receiver. These will be remapped in mapUniClasses, if needed.\\\"\\n\\n\\tself class superclass instSize + 1 to: self class instSize do:\\n\\t\\t[:index | self instVarAt: index put: (anotherObject instVarAt: index)]! !\\n\\n!Object methodsFor: 'copying' stamp: 'tpr 2/14/2004 21:53'!\\ncopyFrom: anotherObject\\n\\t\\\"Copy to myself all instance variables I have in common with anotherObject. This is dangerous because it ignores an object's control over its own inst vars. \\\"\\n\\n\\t| mine his |\\n\\t<primitive: 168>\\n\\tmine _ self class allInstVarNames.\\n\\this _ anotherObject class allInstVarNames.\\n\\t1 to: (mine size min: his size) do: [:ind |\\n\\t\\t(mine at: ind) = (his at: ind) ifTrue: [\\n\\t\\t\\tself instVarAt: ind put: (anotherObject instVarAt: ind)]].\\n\\tself class isVariable & anotherObject class isVariable ifTrue: [\\n\\t\\t1 to: (self basicSize min: anotherObject basicSize) do: [:ind |\\n\\t\\t\\tself basicAt: ind put: (anotherObject basicAt: ind)]].! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 5/23/2002 00:38'!\\ncopySameFrom: otherObject\\n\\t\\\"Copy to myself all instance variables named the same in otherObject.\\n\\tThis ignores otherObject's control over its own inst vars.\\\"\\n\\n\\t| myInstVars otherInstVars match |\\n\\tmyInstVars _ self class allInstVarNames.\\n\\totherInstVars _ otherObject class allInstVarNames.\\n\\tmyInstVars doWithIndex: [:each :index |\\n\\t\\t(match _ otherInstVars indexOf: each) > 0 ifTrue:\\n\\t\\t\\t[self instVarAt: index put: (otherObject instVarAt: match)]].\\n\\t1 to: (self basicSize min: otherObject basicSize) do: [:i |\\n\\t\\tself basicAt: i put: (otherObject basicAt: i)].\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 4/20/1999 14:44'!\\ncopyTwoLevel\\n\\t\\\"one more level than a shallowCopy\\\"\\n\\n\\t| newObject class index |\\n\\tclass _ self class.\\n\\tnewObject _ self clone.\\n\\tnewObject == self ifTrue: [^ self].\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index) shallowCopy.\\n\\t\\t\\t\\t\\tindex _ index - 1]].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index) shallowCopy.\\n\\t\\t\\tindex _ index - 1].\\n\\t^newObject! !\\n\\n!Object methodsFor: 'copying'!\\ndeepCopy\\n\\t\\\"Answer a copy of the receiver with its own copy of each instance \\n\\tvariable.\\\"\\n\\n\\t| newObject class index |\\n\\tclass _ self class.\\n\\t(class == Object) ifTrue: [^self].\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\tnewObject _ class basicNew: index.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index) deepCopy.\\n\\t\\t\\t\\t\\tindex _ index - 1]]\\n\\t\\tifFalse: [newObject _ class basicNew].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index) deepCopy.\\n\\t\\t\\tindex _ index - 1].\\n\\t^newObject! !\\n\\n!Object methodsFor: 'copying' stamp: 'hg 11/23/1999 13:43'!\\ninitialDeepCopierSize\\n\\t\\\"default value is 4096; other classes may override this, esp. for smaller (=faster) sizes\\\"\\n\\n\\t^4096! !\\n\\n!Object methodsFor: 'copying' stamp: 'ajh 1/27/2003 18:45'!\\npostCopy\\n\\t\\\"self is a shallow copy, subclasses should copy fields as necessary to complete the full copy\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'copying' stamp: 'jm 11/14/97 11:08'!\\nshallowCopy\\n\\t\\\"Answer a copy of the receiver which shares the receiver's instance variables.\\\"\\n\\t| class newObject index |\\n\\t<primitive: 148>\\n\\tclass _ self class.\\n\\tclass isVariable\\n\\t\\tifTrue: \\n\\t\\t\\t[index _ self basicSize.\\n\\t\\t\\tnewObject _ class basicNew: index.\\n\\t\\t\\t[index > 0]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[newObject basicAt: index put: (self basicAt: index).\\n\\t\\t\\t\\t\\tindex _ index - 1]]\\n\\t\\tifFalse: [newObject _ class basicNew].\\n\\tindex _ class instSize.\\n\\t[index > 0]\\n\\t\\twhileTrue: \\n\\t\\t\\t[newObject instVarAt: index put: (self instVarAt: index).\\n\\t\\t\\tindex _ index - 1].\\n\\t^ newObject! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 13:58'!\\nveryDeepCopy\\n\\t\\\"Do a complete tree copy using a dictionary. An object in the tree twice is only copied once. All references to the object in the copy of the tree will point to the new copy.\\\"\\n\\n\\t| copier new |\\n\\tcopier _ DeepCopier new initialize: self initialDeepCopierSize.\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\tcopier fixDependents.\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 13:58'!\\nveryDeepCopySibling\\n\\t\\\"Do a complete tree copy using a dictionary. Substitute a clone of oldPlayer for the root. Normally, a Player or non systemDefined object would have a new class. We do not want one this time. An object in the tree twice, is only copied once. All references to the object in the copy of the tree will point to the new copy.\\\"\\n\\n\\t| copier new |\\n\\tcopier _ DeepCopier new initialize: self initialDeepCopierSize.\\n\\tcopier newUniClasses: false.\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\tcopier fixDependents.\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 5/13/2003 19:39'!\\nveryDeepCopyUsing: copier\\n\\t\\\"Do a complete tree copy using a dictionary. An object in the tree twice is only copied once. All references to the object in the copy of the tree will point to the new copy.\\n\\tSame as veryDeepCopy except copier (with dictionary) is supplied.\\n\\t** do not delete this method, even if it has no callers **\\\"\\n\\n\\t| new refs newDep newModel |\\n\\tnew _ self veryDeepCopyWith: copier.\\n\\tcopier mapUniClasses.\\n\\tcopier references associationsDo: [:assoc | \\n\\t\\tassoc value veryDeepFixupWith: copier].\\n\\t\\\"Fix dependents\\\"\\n\\trefs _ copier references.\\n\\tDependentsFields associationsDo: [:pair |\\n\\t\\tpair value do: [:dep | \\n\\t\\t\\t(newDep _ refs at: dep ifAbsent: [nil]) ifNotNil: [\\n\\t\\t\\t\\tnewModel _ refs at: pair key ifAbsent: [pair key].\\n\\t\\t\\t\\tnewModel addDependent: newDep]]].\\n\\t^ new! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 3/11/2003 14:12'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. Some classes refuse to be copied. Some classes are picky about which fields get deep copied.\\\"\\n\\t| class index sub subAss new uc sup has mine |\\n\\tdeepCopier references at: self ifPresent: [:newer | ^ newer]. \\t\\\"already did him\\\"\\n\\tclass _ self class.\\n\\tclass isMeta ifTrue: [^ self].\\t\\t\\\"a class\\\"\\n\\tnew _ self clone.\\n\\t(class isSystemDefined not and: [deepCopier newUniClasses \\\"allowed\\\"]) ifTrue: [\\n\\t\\tuc _ deepCopier uniClasses at: class ifAbsent: [nil].\\n\\t\\tuc ifNil: [\\n\\t\\t\\tdeepCopier uniClasses at: class put: (uc _ self copyUniClassWith: deepCopier).\\n\\t\\t\\tdeepCopier references at: class put: uc].\\t\\\"remember\\\"\\n\\t\\tnew _ uc new.\\n\\t\\tnew copyFrom: self].\\t\\\"copy inst vars in case any are weak\\\"\\n\\tdeepCopier references at: self put: new.\\t\\\"remember\\\"\\n\\t(class isVariable and: [class isPointers]) ifTrue: \\n\\t\\t[index _ self basicSize.\\n\\t\\t[index > 0] whileTrue: \\n\\t\\t\\t[sub _ self basicAt: index.\\n\\t\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\t\\tifNil: [new basicAt: index put: (sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\t\\tifNotNil: [new basicAt: index put: subAss value].\\n\\t\\t\\tindex _ index - 1]].\\n\\t\\\"Ask each superclass if it wants to share (weak copy) any inst vars\\\"\\n\\tnew veryDeepInner: deepCopier.\\t\\t\\\"does super a lot\\\"\\n\\n\\t\\\"other superclasses want all inst vars deep copied\\\"\\n\\tsup _ class. index _ class instSize.\\n\\t[has _ sup compiledMethodAt: #veryDeepInner: ifAbsent: [nil].\\n\\thas _ has ifNil: [class isSystemDefined not \\\"is a uniClass\\\"] ifNotNil: [true].\\n\\tmine _ sup instVarNames.\\n\\thas ifTrue: [index _ index - mine size]\\t\\\"skip inst vars\\\"\\n\\t\\tifFalse: [1 to: mine size do: [:xx |\\n\\t\\t\\t\\tsub _ self instVarAt: index.\\n\\t\\t\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\t\\t\\t\\t\\\"use association, not value, so nil is an exceptional value\\\"\\n\\t\\t\\t\\t\\tifNil: [new instVarAt: index put: \\n\\t\\t\\t\\t\\t\\t\\t\\t(sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\t\\t\\tifNotNil: [new instVarAt: index put: subAss value].\\n\\t\\t\\t\\tindex _ index - 1]].\\n\\t(sup _ sup superclass) == nil] whileFalse.\\n\\tnew rehash.\\t\\\"force Sets and Dictionaries to rehash\\\"\\n\\t^ new\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 1/6/1999 17:39'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"I have no fields and no superclass. Catch the super call.\\\"\\n! !\\n\\n!Object methodsFor: 'copying' stamp: 'tk 9/4/2001 10:30'!\\nveryDeepInner: deepCopier\\n\\t\\\"No special treatment for inst vars of my superclasses. Override when some need to be weakly copied. Object>>veryDeepCopyWith: will veryDeepCopy any inst var whose class does not actually define veryDeepInner:\\\"\\n! !\\n\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:33'!\\nasMorph\\n\\t\\\"Open a morph, as best one can, on the receiver\\\"\\n\\n\\t^ self asStringMorph\\n\\n\\t\\\"\\n234 asMorph\\n(ScriptingSystem formAtKey: #TinyMenu) asMorph\\n'fred' asMorph\\n\\\"\\n\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:35'!\\nasStringMorph\\n\\t\\\"Open a StringMorph, as best one can, on the receiver\\\"\\n\\n\\t^ self asStringOrText asStringMorph\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'nk 2/26/2004 13:35'!\\nasTextMorph\\n\\t\\\"Open a TextMorph, as best one can, on the receiver\\\"\\n\\n\\t^ TextMorph new contentsAsIs: self asStringOrText\\n! !\\n\\n!Object methodsFor: 'creation' stamp: 'sw 1/29/2002 21:45'!\\nopenAsMorph\\n\\t\\\"Open a morph, as best one can, on the receiver\\\"\\n\\n\\t^ self asMorph openInHand\\n\\n\\\"\\n234 openAsMorph\\n(ScriptingSystem formAtKey: #TinyMenu) openAsMorph\\n'fred' openAsMorph\\n\\\"! !\\n\\n\\n!Object methodsFor: 'debugging' stamp: 'md 11/24/2004 11:45'!\\nhaltIf: condition\\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. Param can be a block or expression, halt if true.\\n\\tIf the Block has one arg, the receiver is bound to that.\\n \\tIf the condition is a selector, we look up in the callchain. Halt if\\n any method's selector equals selector.\\\"\\n\\t| cntxt |\\n\\n\\tcondition isSymbol ifTrue:[\\n\\t\\t\\\"only halt if a method with selector symbol is in callchain\\\"\\n\\t\\tcntxt := thisContext.\\n\\t\\t[cntxt sender isNil] whileFalse: [\\n\\t\\t\\tcntxt := cntxt sender. \\n\\t\\t\\t(cntxt selector = condition) ifTrue: [Halt signal].\\n\\t\\t\\t].\\n\\t\\t^self.\\n\\t].\\n\\t(condition isBlock \\n\\t\\t\\tifTrue: [condition valueWithPossibleArgument: self] \\n\\t\\t\\tifFalse: [condition] \\n\\t) ifTrue: [\\n\\t\\tHalt signal\\n\\t].! !\\n\\n!Object methodsFor: 'debugging'!\\nneedsWork! !\\n\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:26'!\\ncheckHaltCountExpired\\n\\t| counter |\\n\\tcounter _ Smalltalk at: #HaltCount ifAbsent: [0].\\n\\t^counter = 0! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nclearHaltOnce\\n\\t\\\"Turn on the halt once flag.\\\"\\n\\tSmalltalk at: #HaltOnce put: false! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:30'!\\ndecrementAndCheckHaltCount\\n\\tself decrementHaltCount.\\n\\t^self checkHaltCountExpired! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:28'!\\ndecrementHaltCount\\n\\t| counter |\\n\\tcounter := Smalltalk\\n\\t\\t\\t\\tat: #HaltCount\\n\\t\\t\\t\\tifAbsent: [0].\\n\\tcounter > 0 ifTrue: [\\n\\t\\tcounter _ counter - 1.\\n\\t\\tself setHaltCountTo: counter]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:42'!\\ndoExpiredHaltCount\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself halt! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:44'!\\ndoExpiredHaltCount: aString\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself halt: aString! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:45'!\\ndoExpiredInspectCount\\n\\tself clearHaltOnce.\\n\\tself removeHaltCount.\\n\\tself inspect! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:43'!\\nhaltOnCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\nhaltOnce\\n\\t\\\"Halt unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self halt]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nhaltOnceEnabled\\n\\t^ Smalltalk\\n\\t\\tat: #HaltOnce\\n\\t\\tifAbsent: [false]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\nhaltOnce: aString \\n\\t\\\"Halt unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self halt: aString]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:45'!\\nhalt: aString onCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount: aString]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredHaltCount: aString]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:36'!\\nhasHaltCount\\n\\t^Smalltalk\\n\\t\\t\\t\\tincludesKey: #HaltCount! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:46'!\\ninspectOnCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:05'!\\ninspectOnce\\n\\t\\\"Inspect unless we have already done it once.\\\"\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce.\\n\\t\\t\\t^ self inspect]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 13:20'!\\ninspectUntilCount: int \\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self hasHaltCount\\n\\t\\t\\t\\tifTrue: [self decrementAndCheckHaltCount\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self inspect]]\\n\\t\\t\\t\\tifFalse: [int = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [self doExpiredInspectCount]\\n\\t\\t\\t\\t\\t\\tifFalse: [self setHaltCountTo: int - 1]]]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:49'!\\nremoveHaltCount\\n\\t(Smalltalk includesKey: #HaltCount) ifTrue: [\\n\\t\\tSmalltalk removeKey: #HaltCount]! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 6/2/2004 08:25'!\\nsetHaltCountTo: int\\n\\tSmalltalk at: #HaltCount put: int! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\nsetHaltOnce\\n\\t\\\"Turn on the halt once flag.\\\"\\n\\tSmalltalk at: #HaltOnce put: true! !\\n\\n!Object methodsFor: 'debugging-haltOnce' stamp: 'sbw 5/19/2004 19:04'!\\ntoggleHaltOnce\\n\\tself haltOnceEnabled\\n\\t\\tifTrue: [self clearHaltOnce]\\n\\t\\tifFalse: [self setHaltOnce]! !\\n\\n\\n!Object methodsFor: 'dependents access' stamp: 'ar 2/11/2001 01:55'!\\naddDependent: anObject\\n\\t\\\"Make the given object one of the receiver's dependents.\\\"\\n\\n\\t| dependents |\\n\\tdependents _ self dependents.\\n\\t(dependents includes: anObject) ifFalse:\\n\\t\\t[self myDependents: (dependents copyWithDependent: anObject)].\\n\\t^ anObject! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:53'!\\nbreakDependents\\n\\t\\\"Remove all of the receiver's dependents.\\\"\\n\\n\\tself myDependents: nil! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:26'!\\ncanDiscardEdits\\n\\t\\\"Answer true if none of the views on this model has unaccepted edits that matter.\\\"\\n\\n\\tself dependents\\n\\t\\tdo: [:each | each canDiscardEdits ifFalse: [^ false]]\\n\\t\\twithout: self.\\n\\t^ true! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:58'!\\ndependents\\n\\t\\\"Answer a collection of objects that are 'dependent' on the receiver;\\n\\t that is, all objects that should be notified if the receiver changes.\\\"\\n\\n\\t^ self myDependents ifNil: [#()]! !\\n\\n!Object methodsFor: 'dependents access'!\\nevaluate: actionBlock wheneverChangeIn: aspectBlock\\n\\t| viewerThenObject objectThenViewer |\\n\\tobjectThenViewer _ self.\\n\\tviewerThenObject _ ObjectViewer on: objectThenViewer.\\n\\tobjectThenViewer become: viewerThenObject.\\n\\t\\\"--- Then ---\\\"\\n\\tobjectThenViewer xxxViewedObject: viewerThenObject\\n\\t\\t\\tevaluate: actionBlock\\n\\t\\t\\twheneverChangeIn: aspectBlock! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:59'!\\nhasUnacceptedEdits\\n\\t\\\"Answer true if any of the views on this object has unaccepted edits.\\\"\\n\\n\\tself dependents\\n\\t\\tdo: [:each | each hasUnacceptedEdits ifTrue: [^ true]]\\n\\t\\twithout: self.\\n\\t^ false! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:55'!\\nmyDependents\\n\\t\\\"Private. Answer a list of all the receiver's dependents.\\\"\\n\\n\\t^ DependentsFields at: self ifAbsent: []! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:52'!\\nmyDependents: aCollectionOrNil\\n\\t\\\"Private. Set (or remove) the receiver's dependents list.\\\"\\n\\n\\taCollectionOrNil\\n\\t\\tifNil: [DependentsFields removeKey: self ifAbsent: []]\\n\\t\\tifNotNil: [DependentsFields at: self put: aCollectionOrNil]! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'reThink 2/18/2001 17:06'!\\nrelease\\n\\t\\\"Remove references to objects that may refer to the receiver. This message \\n\\tshould be overridden by subclasses with any cycles, in which case the \\n\\tsubclass should also include the expression super release.\\\"\\n\\n\\tself releaseActionMap! !\\n\\n!Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 20:23'!\\nremoveDependent: anObject\\n\\t\\\"Remove the given object as one of the receiver's dependents.\\\"\\n\\n\\t| dependents |\\n\\tdependents _ self dependents reject: [:each | each == anObject].\\n\\tself myDependents: (dependents isEmpty ifFalse: [dependents]).\\n\\t^ anObject! !\\n\\n\\n!Object methodsFor: 'drag and drop' stamp: 'bh 9/16/2001 18:10'!\\nacceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph \\n\\t\\n\\t^false.! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'mir 5/16/2000 11:35'!\\ndragAnimationFor: item transferMorph: transferMorph \\n\\t\\\"Default do nothing\\\"! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:20'!\\ndragPassengerFor: item inMorph: dragSource \\n\\t^item! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:11'!\\ndragTransferType\\n\\t^nil! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:05'!\\ndragTransferTypeForMorph: dragSource \\n\\t^nil! !\\n\\n!Object methodsFor: 'drag and drop' stamp: 'mir 5/8/2000 17:19'!\\nwantsDroppedMorph: aMorph event: anEvent inMorph: destinationLM \\n\\t^false! !\\n\\n\\n!Object methodsFor: 'error handling' stamp: 'sma 5/6/2000 19:35'!\\nassert: aBlock\\n\\t\\\"Throw an assertion error if aBlock does not evaluates to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']! !\\n\\n!Object methodsFor: 'error handling' stamp: 'nk 1/15/2004 10:54'!\\nassert: aBlock descriptionBlock: descriptionBlock\\n\\t\\\"Throw an assertion error if aBlock does not evaluate to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: descriptionBlock value asString ]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'nk 10/25/2003 16:47'!\\nassert: aBlock description: aString\\n\\t\\\"Throw an assertion error if aBlock does not evaluates to true.\\\"\\n\\n\\taBlock value ifFalse: [AssertionFailure signal: aString ]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 10/13/2004 15:59'!\\nbackwardCompatibilityOnly: anExplanationString\\n\\t\\\"Warn that the sending method has been deprecated. Methods that are tagt with #backwardCompatibility:\\n\\t are kept for compatibility.\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: thisContext sender printString, ' has been deprecated (but will be kept for compatibility). ', anExplanationString]! !\\n\\n!Object methodsFor: 'error handling'!\\ncaseError\\n\\t\\\"Report an error from an in-line or explicit case statement.\\\"\\n\\n\\tself error: 'Case not found, and no otherwise clause'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'rbb 3/1/2005 09:26'!\\nconfirm: queryString\\n\\t\\\"Put up a yes/no menu with caption queryString. Answer true if the \\n\\tresponse is yes, false if no. This is a modal question--the user must \\n\\trespond yes or no.\\\"\\n\\n\\t\\\"nil confirm: 'Are you hungry?'\\\"\\n\\n\\t^ UIManager default confirm: queryString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'rbb 3/1/2005 09:27'!\\nconfirm: aString orCancel: cancelBlock\\n\\t\\\"Put up a yes/no/cancel menu with caption aString. Answer true if \\n\\tthe response is yes, false if no. If cancel is chosen, evaluate \\n\\tcancelBlock. This is a modal question--the user must respond yes or no.\\\"\\n\\n\\t^ UIManager default confirm: aString orCancel: cancelBlock! !\\n\\n!Object methodsFor: 'error handling' stamp: 'dew 10/6/2003 18:20'!\\ndeprecated: anExplanationString\\n\\t\\\"Warn that the sending method has been deprecated.\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: thisContext sender printString, ' has been deprecated. ', anExplanationString]! !\\n\\n!Object methodsFor: 'error handling' stamp: 'dew 10/7/2003 00:26'!\\ndeprecated: anExplanationString block: aBlock \\n\\t \\\"Warn that the sender has been deprecated. Answer the value of aBlock on resumption. (Note that #deprecated: is usually the preferred method.)\\\"\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation\\n\\t\\t\\tsignal: thisContext sender printString, ' has been deprecated. ', anExplanationString].\\n\\t^ aBlock value.\\n! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 2/22/2006 21:21'!\\ndoesNotUnderstand: aMessage \\n\\t \\\"Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector).\\\"\\n\\t\\\"Testing: (3 activeProcess)\\\"\\n\\n\\tMessageNotUnderstood new \\n\\t\\tmessage: aMessage;\\n\\t\\treceiver: self;\\n\\t\\tsignal.\\n\\t^ aMessage sentTo: self.\\n! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 16:47'!\\ndpsTrace: reportObject \\n\\tTranscript myDependents isNil ifTrue: [^self].\\n\\tself dpsTrace: reportObject levels: 1 withContext: thisContext\\n\\t\\t\\n\\\" nil dpsTrace: 'sludder'. \\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 16:49'!\\ndpsTrace: reportObject levels: anInt\\n\\tself dpsTrace: reportObject levels: anInt withContext: thisContext\\n\\n\\\"(1 to: 3) do: [:int | nil dpsTrace: int levels: 5.]\\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'TRee 11/4/2003 17:02'!\\ndpsTrace: reportObject levels: anInt withContext: currentContext\\n\\t| reportString context displayCount |\\n\\treportString := (reportObject respondsTo: #asString) \\n\\t\\t\\tifTrue: [reportObject asString] ifFalse: [reportObject printString].\\n\\t(Smalltalk at: #Decompiler ifAbsent: [nil]) \\n\\tifNil: \\n\\t\\t[Transcript cr; show: reportString]\\n\\tifNotNil:\\n\\t\\t[context := currentContext.\\n\\t\\tdisplayCount := anInt > 1.\\n\\t\\t1 to: anInt do:\\n\\t\\t\\t[:count |\\n\\t\\t\\tTranscript cr.\\n\\t\\t\\tdisplayCount\\n\\t\\t\\t\\tifTrue: [Transcript show: count printString, ': '].\\n\\t\\t\\t\\n\\t\\t\\treportString notNil\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[Transcript show: context home class name \\n\\t\\t\\t, '/' , context sender selector, ' (' , reportString , ')'.\\n\\t\\t\\t\\tcontext := context sender.\\n\\t\\t\\t\\treportString := nil]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[(context notNil and: [(context := context sender) notNil])\\n\\t\\t\\t\\tifTrue: [Transcript show: context receiver class name , '/' , context selector]]].\\n\\t\\t\\\"Transcript cr\\\"].! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 8/2/2005 22:17'!\\nerror\\n\\t\\\"Throw a generic Error exception.\\\"\\n\\n\\t^self error: 'Error!!'.! !\\n\\n!Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:55'!\\nerror: aString \\n\\t\\\"Throw a generic Error exception.\\\"\\n\\n\\t^Error new signal: aString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 9/16/2005 14:12'!\\nexplicitRequirement\\n\\tself error: 'Explicitly required method'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 2/13/2006 22:20'!\\nhalt\\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. It behaves like halt:, but does not call on halt: in order to \\n\\tavoid putting this message on the stack. Halt is especially useful when \\n\\tthe breakpoint message is an arbitrary one.\\\"\\n\\n\\tHalt signal! !\\n\\n!Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:59'!\\nhalt: aString \\n\\t\\\"This is the typical message to use for inserting breakpoints during \\n\\tdebugging. It creates and schedules a Notifier with the argument, \\n\\taString, as the label.\\\"\\n\\t\\n\\tHalt new signal: aString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 1/20/2006 16:24'!\\nhandles: exception\\n\\t\\\"This method exists in case a non exception class is the first arg in an on:do: (for instance using a exception class that is not loaded). We prefer this to raising an error during error handling itself. Also, semantically it makes sense that the exception handler is not active if its exception class is not loaded\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'error handling' stamp: 'ar 9/27/2005 20:24'!\\nnotifyWithLabel: aString \\n\\t\\\"Create and schedule a Notifier with aString as the window label as well as the contents of the window, in order to request confirmation before a process can proceed.\\\"\\n\\n\\tToolSet\\n\\t\\tdebugContext: thisContext\\n\\t\\tlabel: aString\\n\\t\\tcontents: aString\\n\\n\\t\\\"nil notifyWithLabel: 'let us see if this works'\\\"! !\\n\\n!Object methodsFor: 'error handling' stamp: 'hg 10/2/2001 20:49'!\\nnotify: aString \\n\\t\\\"Create and schedule a Notifier with the argument as the message in \\n\\torder to request confirmation before a process can proceed.\\\"\\n\\n\\tWarning signal: aString\\n\\n\\t\\\"nil notify: 'confirmation message'\\\"! !\\n\\n!Object methodsFor: 'error handling'!\\nnotify: aString at: location\\n\\t\\\"Create and schedule a Notifier with the argument as the message in \\n\\torder to request confirmation before a process can proceed. Subclasses can\\n\\toverride this and insert an error message at location within aString.\\\"\\n\\n\\tself notify: aString\\n\\n\\t\\\"nil notify: 'confirmation message' at: 12\\\"! !\\n\\n!Object methodsFor: 'error handling'!\\nprimitiveFailed\\n\\t\\\"Announce that a primitive has failed and there is no appropriate \\n\\tSmalltalk code to run.\\\"\\n\\n\\tself error: 'a primitive has failed'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 9/16/2005 14:12'!\\nrequirement\\n\\tself error: 'Implicitly required method'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'AFi 2/8/2003 22:52'!\\nshouldBeImplemented\\n\\t\\\"Announce that this message should be implemented\\\"\\n\\n\\tself error: 'This message should be implemented'! !\\n\\n!Object methodsFor: 'error handling'!\\nshouldNotImplement\\n\\t\\\"Announce that, although the receiver inherits this message, it should \\n\\tnot implement it.\\\"\\n\\n\\tself error: 'This message is not appropriate for this object'! !\\n\\n!Object methodsFor: 'error handling' stamp: 'md 2/17/2006 12:02'!\\nsubclassResponsibility\\n\\t\\\"This message sets up a framework for the behavior of the class' subclasses.\\n\\tAnnounce that the subclass should have implemented this message.\\\"\\n\\n\\tself error: 'My subclass should have overridden ', thisContext sender selector printString! !\\n\\n!Object methodsFor: 'error handling' stamp: 'al 12/16/2003 16:16'!\\ntraitConflict\\n\\tself error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.'! !\\n\\n\\n!Object methodsFor: 'evaluating' stamp: 'reThink 3/12/2001 18:14'!\\nvalue\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'evaluating' stamp: 'reThink 2/18/2001 15:23'!\\nvalueWithArguments: aSequenceOfArguments\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'!\\nactionForEvent: anEventSelector\\n \\\"Answer the action to be evaluated when <anEventSelector> has been triggered.\\\"\\n\\n\\t| actions |\\n\\tactions := self actionMap\\n\\t\\tat: anEventSelector asSymbol\\n\\t\\tifAbsent: [nil].\\n\\tactions ifNil: [^nil].\\n\\t^ actions asMinimalRepresentation! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'!\\nactionForEvent: anEventSelector\\nifAbsent: anExceptionBlock\\n \\\"Answer the action to be evaluated when <anEventSelector> has been triggered.\\\"\\n\\n\\t| actions |\\n\\tactions := self actionMap\\n\\t\\tat: anEventSelector asSymbol\\n\\t\\tifAbsent: [nil].\\n\\tactions ifNil: [^anExceptionBlock value].\\n\\t^ actions asMinimalRepresentation! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 14:43'!\\nactionMap\\n\\n\\t^EventManager actionMapFor: self! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'rw 4/27/2002 08:35'!\\nactionSequenceForEvent: anEventSelector\\n\\n ^(self actionMap\\n at: anEventSelector asSymbol\\n ifAbsent: [^WeakActionSequence new])\\n asActionSequence! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'SqR 6/28/2001 13:19'!\\nactionsDo: aBlock\\n\\n\\tself actionMap do: aBlock! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'rw 2/10/2002 13:05'!\\ncreateActionMap\\n\\n\\t^IdentityDictionary new! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'SqR 2/19/2001 14:04'!\\nhasActionForEvent: anEventSelector\\n \\\"Answer true if there is an action associated with anEventSelector\\\"\\n\\n ^(self actionForEvent: anEventSelector) notNil! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 15:29'!\\nsetActionSequence: actionSequence\\nforEvent: anEventSelector\\n\\n | action |\\n action := actionSequence asMinimalRepresentation.\\n action == nil\\n ifTrue:\\n [self removeActionsForEvent: anEventSelector]\\n ifFalse:\\n [self updateableActionMap\\n at: anEventSelector asSymbol\\n put: action]! !\\n\\n!Object methodsFor: 'events-accessing' stamp: 'reThink 2/25/2001 08:50'!\\nupdateableActionMap\\n\\n\\t^EventManager updateableActionMapFor: self! !\\n\\n\\n!Object methodsFor: 'events-registering' stamp: 'reThink 2/18/2001 15:04'!\\nwhen: anEventSelector evaluate: anAction \\n\\n\\t| actions |\\n\\tactions := self actionSequenceForEvent: anEventSelector.\\n\\t(actions includes: anAction)\\n\\t\\tifTrue: [^ self].\\n\\tself \\n\\t\\tsetActionSequence: (actions copyWith: anAction)\\n\\t\\tforEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector)! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\nwithArguments: anArgArray\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector\\n\\t\\targuments: anArgArray)! !\\n\\n!Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'!\\nwhen: anEventSelector\\nsend: aMessageSelector\\nto: anObject\\nwith: anArg\\n \\n self\\n when: anEventSelector\\n evaluate: (WeakMessageSend\\n receiver: anObject\\n selector: aMessageSelector\\n\\t\\targuments: (Array with: anArg))! !\\n\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'!\\nreleaseActionMap\\n\\n\\tEventManager releaseActionMapFor: self! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'!\\nremoveActionsForEvent: anEventSelector\\n\\n | map |\\n map := self actionMap.\\n map removeKey: anEventSelector asSymbol ifAbsent: [].\\n map isEmpty\\n ifTrue: [self releaseActionMap]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'nk 8/25/2003 21:46'!\\nremoveActionsSatisfying: aBlock\\n\\n\\tself actionMap keys do:\\n\\t\\t[:eachEventSelector |\\n\\t\\t\\tself\\n \\t\\t\\t\\tremoveActionsSatisfying: aBlock\\n\\t\\t\\t\\tforEvent: eachEventSelector\\n\\t\\t]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'!\\nremoveActionsSatisfying: aOneArgBlock \\nforEvent: anEventSelector\\n\\n self\\n setActionSequence:\\n ((self actionSequenceForEvent: anEventSelector)\\n reject: [:anAction | aOneArgBlock value: anAction])\\n forEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'rw 7/29/2003 17:18'!\\nremoveActionsWithReceiver: anObject\\n\\n\\tself actionMap copy keysDo:\\n\\t\\t[:eachEventSelector |\\n\\t\\t\\tself\\n \\t\\t\\t\\tremoveActionsSatisfying: [:anAction | anAction receiver == anObject]\\n\\t\\t\\t\\tforEvent: eachEventSelector\\n\\t\\t]! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:36'!\\nremoveActionsWithReceiver: anObject\\nforEvent: anEventSelector\\n\\n self\\n removeActionsSatisfying:\\n [:anAction |\\n anAction receiver == anObject]\\n forEvent: anEventSelector! !\\n\\n!Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'!\\nremoveAction: anAction\\nforEvent: anEventSelector\\n\\n self\\n removeActionsSatisfying: [:action | action = anAction]\\n forEvent: anEventSelector! !\\n\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:22'!\\ntriggerEvent: anEventSelector\\n\\t\\\"Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action.\\\"\\n\\n ^(self actionForEvent: anEventSelector) value! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 17:09'!\\ntriggerEvent: anEventSelector\\nifNotHandled: anExceptionBlock\\n\\t\\\"Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action.\\\"\\n\\n ^(self \\n\\t\\tactionForEvent: anEventSelector\\n\\t\\tifAbsent: [^anExceptionBlock value]) value\\n! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'!\\ntriggerEvent: anEventSelector\\nwithArguments: anArgumentList\\n\\n ^(self actionForEvent: anEventSelector)\\n valueWithArguments: anArgumentList! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'!\\ntriggerEvent: anEventSelector\\nwithArguments: anArgumentList\\nifNotHandled: anExceptionBlock\\n\\n ^(self \\n\\t\\tactionForEvent: anEventSelector\\n\\t\\tifAbsent: [^anExceptionBlock value])\\n valueWithArguments: anArgumentList! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'!\\ntriggerEvent: anEventSelector\\nwith: anObject\\n\\n ^self \\n\\t\\ttriggerEvent: anEventSelector\\n\\t\\twithArguments: (Array with: anObject)! !\\n\\n!Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'!\\ntriggerEvent: anEventSelector\\nwith: anObject\\nifNotHandled: anExceptionBlock\\n\\n ^self \\n\\t\\ttriggerEvent: anEventSelector\\n\\t\\twithArguments: (Array with: anObject)\\n\\t\\tifNotHandled: anExceptionBlock! !\\n\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:42'!\\nbyteEncode:aStream\\n\\tself flattenOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming'!\\ndrawOnCanvas:aStream\\n\\tself flattenOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:31'!\\nelementSeparator\\n\\t^nil.! !\\n\\n!Object methodsFor: 'filter streaming'!\\nencodePostscriptOn:aStream\\n\\tself byteEncode:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'!\\nflattenOnStream:aStream\\n\\tself writeOnFilterStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'mpw 6/22/1930 22:56'!\\nfullDrawPostscriptOn:aStream\\n\\t^aStream fullDraw:self.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:51'!\\nprintOnStream:aStream\\n\\tself byteEncode:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:49'!\\nputOn:aStream\\n\\t^aStream nextPut:self.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:53'!\\nstoreOnStream:aStream\\n\\tself printOnStream:aStream.\\n! !\\n\\n!Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:06'!\\nwriteOnFilterStream:aStream\\n\\taStream writeObject:self.\\n! !\\n\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:26'!\\nactAsExecutor\\n\\t\\\"Prepare the receiver to act as executor for any resources associated with it\\\"\\n\\tself breakDependents! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/20/98 22:19'!\\nexecutor\\n\\t\\\"Return an object which can act as executor for finalization of the receiver\\\"\\n\\t^self shallowCopy actAsExecutor! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:10'!\\nfinalizationRegistry\\n\\t\\\"Answer the finalization registry associated with the receiver.\\\"\\n\\t^WeakRegistry default! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:27'!\\nfinalize\\n\\t\\\"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority.\\\"! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 3/21/98 18:38'!\\nretryWithGC: execBlock until: testBlock\\n\\t\\\"Retry execBlock as long as testBlock returns false. Do an incremental GC after the first try, a full GC after the second try.\\\"\\n\\t| blockValue |\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollectMost.\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollect.\\n\\t^execBlock value.! !\\n\\n!Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:14'!\\ntoFinalizeSend: aSelector to: aFinalizer with: aResourceHandle\\n\\t\\\"When I am finalized (e.g., garbage collected) close the associated resource handle by sending aSelector to the appropriate finalizer (the guy who knows how to get rid of the resource).\\n\\tWARNING: Neither the finalizer nor the resource handle are allowed to reference me. If they do, then I will NEVER be garbage collected. Since this cannot be validated here, it is up to the client to make sure this invariant is not broken.\\\"\\n\\tself == aFinalizer ifTrue:[self error: 'I cannot finalize myself'].\\n\\tself == aResourceHandle ifTrue:[self error: 'I cannot finalize myself'].\\n\\t^self finalizationRegistry add: self executor:\\n\\t\\t(ObjectFinalizer new\\n\\t\\t\\treceiver: aFinalizer\\n\\t\\t\\tselector: aSelector\\n\\t\\t\\targument: aResourceHandle)! !\\n\\n\\n!Object methodsFor: 'flagging' stamp: 'sw 8/4/97 16:49'!\\nisThisEverCalled\\n\\t^ self isThisEverCalled: thisContext sender printString! !\\n\\n!Object methodsFor: 'flagging'!\\nisThisEverCalled: msg\\n\\t\\\"Send this message, with some useful printable argument, from methods or branches of methods which you believe are never reached. 2/5/96 sw\\\"\\n\\n\\tself halt: 'This is indeed called: ', msg printString! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'!\\nlogEntry\\n\\n\\tTranscript show: 'Entered ', thisContext sender printString; cr.\\n! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'!\\nlogExecution\\n\\n\\tTranscript show: 'Executing ', thisContext sender printString; cr.\\n! !\\n\\n!Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:22'!\\nlogExit\\n\\n\\tTranscript show: 'Exited ', thisContext sender printString; cr.\\n! !\\n\\n\\n!Object methodsFor: 'graph model' stamp: 'dgd 9/18/2004 15:07'!\\naddModelYellowButtonMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph \\n\\t\\\"The receiver serves as the model for aMorph; a menu is being constructed for the morph, and here the receiver is able to add its own items\\\"\\n\\tPreferences cmdGesturesEnabled ifTrue: [ \\\"build mode\\\"\\n\\t\\taCustomMenu add: 'inspect model' translated target: self action: #inspect.\\n\\t].\\n\\n\\t^aCustomMenu\\n! !\\n\\n!Object methodsFor: 'graph model' stamp: 'nk 1/23/2004 14:35'!\\nhasModelYellowButtonMenuItems\\n\\t^Preferences cmdGesturesEnabled! !\\n\\n\\n!Object methodsFor: 'locales' stamp: 'tak 8/4/2005 14:55'!\\nlocaleChanged\\n\\tself shouldBeImplemented! !\\n\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/7/1998 23:00'!\\ncodeStrippedOut: messageString\\n\\t\\\"When a method is stripped out for external release, it is replaced by a method that calls this\\\"\\n\\n\\tself halt: 'Code stripped out -- ', messageString, '-- do not proceed.'! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 1/28/1999 17:31'!\\ncontentsChanged\\n\\tself changed: #contents! !\\n\\n!Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:03'!\\ncurrentEvent\\n\\t\\\"Answer the current Morphic event. This method never returns nil.\\\"\\n\\t^ActiveEvent ifNil:[self currentHand lastEvent]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'nk 9/1/2004 10:41'!\\ncurrentHand\\n\\t\\\"Return a usable HandMorph -- the one associated with the object's current environment. This method will always return a hand, even if it has to conjure one up as a last resort. If a particular hand is actually handling events at the moment (such as a remote hand or a ghost hand), it will be returned.\\\"\\n\\n\\t^ActiveHand ifNil: [ self currentWorld primaryHand ]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/17/2001 12:08'!\\ncurrentVocabulary\\n\\t\\\"Answer the currently-prevailing default vocabulary.\\\"\\n\\n\\t^ Smalltalk isMorphic ifTrue:\\n\\t\\t\\t[ActiveWorld currentVocabulary]\\n\\t\\tifFalse:\\n\\t\\t\\t[Vocabulary fullVocabulary]! !\\n\\n!Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:08'!\\ncurrentWorld\\n\\t\\\"Answer a morphic world that is the current UI focus.\\n\\t\\tIf in an embedded world, it's that world.\\n\\t\\tIf in a morphic project, it's that project's world. \\n\\t\\tIf in an mvc project, it is the topmost morphic-mvc-window's worldMorph. \\n\\t\\tIf in an mvc project that has no morphic-mvc-windows, then it's just some existing worldmorph instance.\\n\\t\\tIf in an mvc project in a Squeak that has NO WorldMorph instances, one is created.\\n\\n\\tThis method will never return nil, it will always return its best effort at returning a relevant world morph, but if need be -- if there are no worlds anywhere, it will create a new one.\\\"\\n\\n\\t| aView aSubview |\\n\\tActiveWorld ifNotNil:[^ActiveWorld].\\n\\tWorld ifNotNil:[^World].\\n\\taView _ ScheduledControllers controllerSatisfying:\\n\\t\\t[:ctrl | (aSubview _ ctrl view firstSubView) notNil and:\\n\\t\\t\\t[aSubview model isMorph and: [aSubview model isWorldMorph]]].\\n\\t^aView\\n\\t\\tifNotNil:\\n\\t\\t\\t[aSubview model]\\n\\t\\tifNil:\\n\\t\\t\\t[MVCWiWPasteUpMorph newWorldForProject: nil].! !\\n\\n!Object methodsFor: 'macpal' stamp: 'jm 5/6/1998 22:35'!\\nflash\\n\\t\\\"Do nothing.\\\"\\n! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 6/16/1998 15:07'!\\ninstanceVariableValues\\n\\t\\\"Answer a collection whose elements are the values of those instance variables of the receiver which were added by the receiver's class\\\"\\n\\t| c |\\n\\tc _ OrderedCollection new.\\n\\tself class superclass instSize + 1 to: self class instSize do:\\n\\t\\t[:i | c add: (self instVarAt: i)].\\n\\t^ c! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:29'!\\nisUniversalTiles\\n\\t\\\"Return true if I (my world) uses universal tiles. This message can be called in places where the current World is not known, such as when writing out a project. For more information about the project-writing subtlety addressed by this protocol, kindly contact Ted Kaehler.\\\"\\n\\n\\t^ Preferences universalTiles! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 10/24/2000 07:04'!\\nobjectRepresented\\n\\t\\\"most objects represent themselves; this provides a hook for aliases to grab on to\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 5/22/2001 18:31'!\\nrefusesToAcceptCode\\n\\t\\\"Answer whether the receiver is a code-bearing instrument which at the moment refuses to allow its contents to be submitted\\\"\\n\\n\\t^ false\\n\\t! !\\n\\n!Object methodsFor: 'macpal' stamp: 'jm 2/24/1999 12:40'!\\nscriptPerformer\\n\\n\\t^ self\\n! !\\n\\n!Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:40'!\\nslotInfo\\n\\t\\\"Answer a list of slot-information objects. Initally only provides useful info for players\\\"\\n\\n\\t^ Dictionary new! !\\n\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nexecuteMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver with no args\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: #() executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol \\n\\t\\\"Send the unary selector, aSymbol, to the receiver.\\n\\tFail if the number of arguments expected by the selector is not zero.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array new: 0)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'sw 10/30/1998 18:27'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"If I wish to intercept and handle selector myself, do it; else send it to otherTarget\\\"\\n\\t^ otherTarget perform: selector! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:55'!\\nperform: selector withArguments: argArray \\n\\t\\\"Send the selector, aSymbol, to the receiver with arguments in argArray.\\n\\tFail if the number of arguments expected by the selector \\n\\tdoes not match the size of argArray.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 84>\\n\\t^ self perform: selector withArguments: argArray inSuperclass: self class! !\\n\\n!Object methodsFor: 'message handling' stamp: 'ar 4/25/2005 13:35'!\\nperform: selector withArguments: argArray inSuperclass: lookupClass\\n\\t\\\"NOTE: This is just like perform:withArguments:, except that\\n\\tthe message lookup process begins, not with the receivers's class,\\n\\tbut with the supplied superclass instead. It will fail if lookupClass\\n\\tcannot be found among the receiver's superclasses.\\n\\tPrimitive. Essential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 100>\\n\\t(selector isSymbol)\\n\\t\\tifFalse: [^ self error: 'selector argument must be a Symbol'].\\n\\t(selector numArgs = argArray size)\\n\\t\\tifFalse: [^ self error: 'incorrect number of arguments'].\\n\\t(self class == lookupClass or: [self class inheritsFrom: lookupClass])\\n\\t\\tifFalse: [^ self error: 'lookupClass is not in my inheritance chain'].\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'message handling' stamp: 'nk 4/11/2002 14:13'!\\nperform: selector withEnoughArguments: anArray\\n\\t\\\"Send the selector, aSymbol, to the receiver with arguments in argArray.\\n\\tOnly use enough arguments for the arity of the selector; supply nils for missing ones.\\\"\\n\\t| numArgs args |\\n\\tnumArgs _ selector numArgs.\\n\\tanArray size == numArgs\\n\\t\\tifTrue: [ ^self perform: selector withArguments: anArray asArray ].\\n\\n\\targs _ Array new: numArgs.\\n\\targs replaceFrom: 1\\n\\t\\tto: (anArray size min: args size)\\n\\t\\twith: anArray\\n\\t\\tstartingAt: 1.\\n\\n\\t^ self perform: selector withArguments: args! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol with: anObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with anObject as its argument.\\n\\tFail if the number of arguments expected by the selector is not one.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array with: anObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'!\\nperform: aSymbol with: firstObject with: secondObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with the given arguments.\\n\\tFail if the number of arguments expected by the selector is not two.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol withArguments: (Array with: firstObject with: secondObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:51'!\\nperform: aSymbol with: firstObject with: secondObject with: thirdObject \\n\\t\\\"Send the selector, aSymbol, to the receiver with the given arguments.\\n\\tFail if the number of arguments expected by the selector is not three.\\n\\tPrimitive. Optional. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 83>\\n\\t^ self perform: aSymbol\\n\\t\\twithArguments: (Array with: firstObject with: secondObject with: thirdObject)! !\\n\\n!Object methodsFor: 'message handling' stamp: 'NS 1/28/2004 11:19'!\\nwithArgs: argArray executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and args in argArray\\\"\\n\\n\\t| selector |\\n\\t<primitive: 188>\\n\\tselector _ Symbol new.\\n\\tself class addSelectorSilently: selector withMethod: compiledMethod.\\n\\t^ [self perform: selector withArguments: argArray]\\n\\t\\tensure: [self class basicRemoveSelector: selector]! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1 & arg2\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 with: arg3 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1, arg2, & arg3\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2. arg3} executeMethod: compiledMethod! !\\n\\n!Object methodsFor: 'message handling' stamp: 'md 1/20/2006 16:28'!\\nwith: arg1 with: arg2 with: arg3 with: arg4 executeMethod: compiledMethod\\n\\t\\\"Execute compiledMethod against the receiver and arg1, arg2, arg3, & arg4\\\"\\n\\n\\t\\\"<primitive: 189>\\\" \\\"uncomment once prim 189 is in VM\\\"\\n\\t^ self withArgs: {arg1. arg2. arg3. arg4} executeMethod: compiledMethod! !\\n\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:46'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"Normally this read-in object is exactly what we want to store. 7/26/96 tk\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'RAA 12/20/2000 16:51'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\t\\\"subclasses should implement if they wish to convert old instances to modern ones\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 11/29/2004 15:04'!\\nfixUponLoad: aProject seg: anImageSegment\\n\\n\\t\\\"change the object due to conventions that have changed on\\n\\nthe project level. (sent to all objects in the incoming project).\\n\\nSpecific classes should reimplement this.\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'RAA 1/10/2001 14:02'!\\nindexIfCompact\\n\\n\\t^0\\t\\t\\\"helps avoid a #respondsTo: in publishing\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 2/24/1999 11:08'!\\nobjectForDataStream: refStrm\\n \\\"Return an object to store on an external data stream.\\\"\\n\\n ^ self! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:05'!\\nreadDataFrom: aDataStream size: varsOnDisk\\n\\t\\\"Fill in the fields of self based on the contents of aDataStream. Return self.\\n\\t Read in the instance-variables written by Object>>storeDataOn:.\\n\\t NOTE: This method must send beginReference: before reading any objects from aDataStream that might reference it.\\n\\t Allow aDataStream to have fewer inst vars. See SmartRefStream.\\\"\\n\\t| cntInstVars cntIndexedVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\tself class isVariable\\n\\t\\tifTrue: [cntIndexedVars _ varsOnDisk - cntInstVars.\\n\\t\\t\\t\\tcntIndexedVars < 0 ifTrue: [\\n\\t\\t\\t\\t\\tself error: 'Class has changed too much. Define a convertxxx method']]\\n\\t\\tifFalse: [cntIndexedVars _ 0.\\n\\t\\t\\t\\tcntInstVars _ varsOnDisk]. \\t\\\"OK if fewer than now\\\"\\n\\n\\taDataStream beginReference: self.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | self instVarAt: i put: aDataStream next].\\n\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | self basicAt: i put: aDataStream next].\\n\\t\\\"Total number read MUST be equal to varsOnDisk!!\\\"\\n\\t^ self\\t\\\"If we ever return something other than self, fix calls \\n\\t\\t\\ton (super readDataFrom: aDataStream size: anInteger)\\\"! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'CdG 10/17/2005 20:32'!\\nsaveOnFile\\n\\t\\\"Ask the user for a filename and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. Does not file out the class of the object. tk 6/26/97 13:48\\\"\\n\\n\\t| aFileName fileStream |\\n\\taFileName := self class name asFileName.\\t\\\"do better?\\\"\\n\\taFileName := UIManager default \\n\\t\\t\\t\\trequest: 'File name?' translated initialAnswer: aFileName.\\n\\taFileName size == 0 ifTrue: [^ Beeper beep].\\n\\n\\tfileStream := FileStream newFileNamed: aFileName asFileName.\\n\\tfileStream fileOutClass: nil andObject: self.! !\\n\\n!Object methodsFor: 'objects from disk' stamp: 'tk 8/9/2001 15:40'!\\nstoreDataOn: aDataStream\\n\\t\\\"Store myself on a DataStream. Answer self. This is a low-level DataStream/ReferenceStream method. See also objectToStoreOnDataStream. NOTE: This method must send 'aDataStream beginInstance:size:' and then (nextPut:/nextPutWeak:) its subobjects. readDataFrom:size: reads back what we write here.\\\"\\n\\t| cntInstVars cntIndexedVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\tcntIndexedVars _ self basicSize.\\n\\taDataStream\\n\\t\\tbeginInstance: self class\\n\\t\\tsize: cntInstVars + cntIndexedVars.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self instVarAt: i)].\\n\\n\\t\\\"Write fields of a variable length object. When writing to a dummy \\n\\t\\tstream, don't bother to write the bytes\\\"\\n\\t((aDataStream byteStream class == DummyStream) and: [self class isBits]) ifFalse: [\\n\\t\\t1 to: cntIndexedVars do:\\n\\t\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]].\\n! !\\n\\n\\n!Object methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:34'!\\ndescriptionForPartsBin\\n\\t\\\"If the receiver is a member of a class that would like to be represented in a parts bin, answer the name by which it should be known, and a documentation string to be provided, for example, as balloon help. When the 'nativitySelector' is sent to the 'globalReceiver', it is expected that some kind of Morph will result. The parameters used in the implementation below are for documentation purposes only!!\\\"\\n\\n\\t^ DescriptionForPartsBin\\n\\t\\tformalName: 'PutFormalNameHere'\\n\\t\\tcategoryList: #(PutACategoryHere MaybePutAnotherCategoryHere)\\n\\t\\tdocumentation: 'Put the balloon help here'\\n\\t\\tglobalReceiverSymbol: #PutAGlobalHere\\n\\t\\tnativitySelector: #PutASelectorHere! !\\n\\n\\n!Object methodsFor: 'printing' stamp: 'di 6/20/97 08:57'!\\nfullPrintString\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\n\\t^ String streamContents: [:s | self printOn: s]! !\\n\\n!Object methodsFor: 'printing'!\\nisLiteral\\n\\t\\\"Answer whether the receiver has a literal text form recognized by the \\n\\tcompiler.\\\"\\n\\n\\t^false! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:28'!\\nlongPrintOn: aStream\\n\\t\\\"Append to the argument, aStream, the names and values of all \\n\\tof the receiver's instance variables.\\\"\\n\\n\\tself class allInstVarNames doWithIndex:\\n\\t\\t[:title :index |\\n\\t\\taStream nextPutAll: title;\\n\\t\\t nextPut: $:;\\n\\t\\t space;\\n\\t\\t tab;\\n\\t\\t print: (self instVarAt: index);\\n\\t\\t cr]! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 10/19/2001 11:18'!\\nlongPrintOn: aStream limitedTo: sizeLimit indent: indent\\n\\t\\\"Append to the argument, aStream, the names and values of all of the receiver's instance variables. Limit is the length limit for each inst var.\\\"\\n\\n\\tself class allInstVarNames doWithIndex:\\n\\t\\t[:title :index |\\n\\t\\tindent timesRepeat: [aStream tab].\\n\\t\\taStream nextPutAll: title;\\n\\t\\t nextPut: $:;\\n\\t\\t space;\\n\\t\\t tab;\\n\\t\\t nextPutAll: \\n\\t\\t\\t((self instVarAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1));\\n\\t\\t cr]! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 10/16/2001 19:41'!\\nlongPrintString\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\t\\n\\t| str |\\n\\tstr _ String streamContents: [:aStream | self longPrintOn: aStream].\\n\\t\\\"Objects without inst vars should return something\\\"\\n\\t^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! !\\n\\n!Object methodsFor: 'printing' stamp: 'BG 11/7/2004 13:39'!\\nlongPrintStringLimitedTo: aLimitValue\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\\"\\n\\t\\n\\t| str |\\n\\tstr _ String streamContents: [:aStream | self longPrintOn: aStream limitedTo: aLimitValue indent: 0].\\n\\t\\\"Objects without inst vars should return something\\\"\\n\\t^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 3/7/2001 13:14'!\\nnominallyUnsent: aSelectorSymbol\\n\\t\\\"From within the body of a method which is not formally sent within the system, but which you intend to have remain in the system (for potential manual invocation, or for documentation, or perhaps because it's sent by commented-out-code that you anticipate uncommenting out someday, send this message, with the selector itself as the argument.\\n\\nThis will serve two purposes:\\n\\n\\t(1) The method will not be returned by searches for unsent selectors (because it, in a manner of speaking, sends itself).\\n\\t(2)\\tYou can locate all such methods by browsing senders of #nominallyUnsent:\\\"\\n\\n\\tfalse ifTrue: [self flag: #nominallyUnsent:] \\\"So that this method itself will appear to be sent\\\"\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:31'!\\nprintOn: aStream\\n\\t\\\"Append to the argument, aStream, a sequence of characters that \\n\\tidentifies the receiver.\\\"\\n\\n\\t| title |\\n\\ttitle _ self class name.\\n\\taStream\\n\\t\\tnextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']);\\n\\t\\tnextPutAll: title! !\\n\\n!Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:22'!\\nprintString\\n\\t\\\"Answer a String whose characters are a description of the receiver. \\n\\tIf you want to print without a character limit, use fullPrintString.\\\"\\n\\n\\t^ self printStringLimitedTo: 50000! !\\n\\n!Object methodsFor: 'printing' stamp: 'tk 5/7/1999 16:20'!\\nprintStringLimitedTo: limit\\n\\t\\\"Answer a String whose characters are a description of the receiver.\\n\\tIf you want to print without a character limit, use fullPrintString.\\\"\\n\\t| limitedString |\\n\\tlimitedString _ String streamContents: [:s | self printOn: s] limitedTo: limit.\\n\\tlimitedString size < limit ifTrue: [^ limitedString].\\n\\t^ limitedString , '...etc...'! !\\n\\n!Object methodsFor: 'printing' stamp: 'MPW 1/1/1901 00:30'!\\npropertyList\\n\\t\\\"Answer a String whose characters are a property-list description of the receiver.\\\"\\n\\n\\t^ PropertyListEncoder process:self.\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 10/17/2000 11:16'!\\nreportableSize\\n\\t\\\"Answer a string that reports the size of the receiver -- useful for showing in a list view, for example\\\"\\n\\n\\t^ (self basicSize + self class instSize) printString! !\\n\\n!Object methodsFor: 'printing'!\\nstoreOn: aStream \\n\\t\\\"Append to the argument aStream a sequence of characters that is an \\n\\texpression whose evaluation creates an object similar to the receiver.\\\"\\n\\n\\taStream nextPut: $(.\\n\\tself class isVariable\\n\\t\\tifTrue: [aStream nextPutAll: '(', self class name, ' basicNew: ';\\n\\t\\t\\t\\t\\tstore: self basicSize;\\n\\t\\t\\t\\t\\tnextPutAll: ') ']\\n\\t\\tifFalse: [aStream nextPutAll: self class name, ' basicNew'].\\n\\t1 to: self class instSize do:\\n\\t\\t[:i |\\n\\t\\taStream nextPutAll: ' instVarAt: ';\\n\\t\\t\\tstore: i;\\n\\t\\t\\tnextPutAll: ' put: ';\\n\\t\\t\\tstore: (self instVarAt: i);\\n\\t\\t\\tnextPut: $;].\\n\\t1 to: self basicSize do:\\n\\t\\t[:i |\\n\\t\\taStream nextPutAll: ' basicAt: ';\\n\\t\\t\\tstore: i;\\n\\t\\t\\tnextPutAll: ' put: ';\\n\\t\\t\\tstore: (self basicAt: i);\\n\\t\\t\\tnextPut: $;].\\n\\taStream nextPutAll: ' yourself)'\\n! !\\n\\n!Object methodsFor: 'printing' stamp: 'di 6/20/97 09:12'!\\nstoreString\\n\\t\\\"Answer a String representation of the receiver from which the receiver \\n\\tcan be reconstructed.\\\"\\n\\n\\t^ String streamContents: [:s | self storeOn: s]! !\\n\\n!Object methodsFor: 'printing' stamp: 'sw 5/2/1998 13:55'!\\nstringForReadout\\n\\t^ self stringRepresentation! !\\n\\n!Object methodsFor: 'printing'!\\nstringRepresentation\\n\\t\\\"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\\\"\\n\\n\\t^ self printString ! !\\n\\n\\n!Object methodsFor: 'scripting' stamp: 'ar 3/17/2001 20:11'!\\nadaptedToWorld: aWorld\\n\\t\\\"If I refer to a world or a hand, return the corresponding items in the new world.\\\"\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 3/10/2000 13:57'!\\ndefaultFloatPrecisionFor: aGetSelector\\n\\t\\\"Answer a number indicating the default float precision to be used in a numeric readout for which the receiver is the model.\\\"\\n\\n\\t^ 1! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 3/9/2001 17:08'!\\nevaluateUnloggedForSelf: aCodeString\\n\\n\\t^Compiler evaluate:\\n\\t\\taCodeString\\n\\t\\tfor: self\\n\\t\\tlogged: false! !\\n\\n!Object methodsFor: 'scripting' stamp: 'yo 12/25/2003 16:43'!\\nmethodInterfacesForCategory: aCategorySymbol inVocabulary: aVocabulary limitClass: aLimitClass\\n\\t\\\"Return a list of methodInterfaces for the receiver in the given category, given a vocabulary. aCategorySymbol is the inherent category symbol, not necessarily the wording as expressed in the vocabulary.\\\"\\n\\n\\t| categorySymbol |\\n\\tcategorySymbol _ aCategorySymbol asSymbol.\\n\\n\\t(categorySymbol == ScriptingSystem nameForInstanceVariablesCategory) ifTrue: [\\n\\t\\t\\\"user-defined instance variables\\\"\\n\\t\\t^ self methodInterfacesForInstanceVariablesCategoryIn: aVocabulary].\\n\\t(categorySymbol == ScriptingSystem nameForScriptsCategory) ifTrue: [\\n\\t\\t\\\"user-defined scripts\\\"\\n\\t\\t^ self methodInterfacesForScriptsCategoryIn: aVocabulary].\\n\\t\\\"all others\\\"\\n\\t^ self usableMethodInterfacesIn: (aVocabulary methodInterfacesInCategory: categorySymbol\\n\\t\\tforInstance: self\\n\\t\\tofClass: self class\\n\\t\\tlimitClass: aLimitClass)\\n! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:54'!\\nmethodInterfacesForInstanceVariablesCategoryIn: aVocabulary\\n\\t\\\"Return a collection of methodInterfaces for the instance-variables category. The vocabulary parameter, at present anyway, is not used. And for non-players, the method is at present vacuous in any case\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:53'!\\nmethodInterfacesForScriptsCategoryIn: aVocabulary\\n\\t\\\"Answer a list of method interfaces for the category #scripts, as seen in a viewer or other tool. The vocabulary argument is not presently used. Also, at present, only Players really do anyting interesting here.\\\"\\n\\n\\t^ OrderedCollection new! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsIll\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'!\\nselfWrittenAsIm\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsMe\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'!\\nselfWrittenAsMy\\n\\n\\t^self! !\\n\\n!Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'!\\nselfWrittenAsThis\\n\\n\\t^self! !\\n\\n\\n!Object methodsFor: 'self evaluating' stamp: 'sd 7/31/2005 21:47'!\\nisSelfEvaluating\\n\\t^ self isLiteral! !\\n\\n\\n!Object methodsFor: 'system primitives'!\\nasOop\\n\\t\\\"Primitive. Answer a SmallInteger whose value is half of the receiver's \\n\\tobject pointer (interpreting object pointers as 16-bit signed quantities). \\n\\tFail if the receiver is a SmallInteger. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 75>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'di 1/9/1999 15:19'!\\nbecomeForward: otherObject \\n\\t\\\"Primitive. All variables in the entire system that used to point\\n\\tto the receiver now point to the argument.\\n\\tFails if either argument is a SmallInteger.\\\"\\n\\n\\t(Array with: self)\\n\\t\\telementsForwardIdentityTo:\\n\\t\\t\\t(Array with: otherObject)! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'zz 3/3/2004 23:53'!\\nbecomeForward: otherObject copyHash: copyHash\\n\\t\\\"Primitive. All variables in the entire system that used to point to the receiver now point to the argument.\\n\\tIf copyHash is true, the argument's identity hash bits will be set to those of the receiver.\\n\\tFails if either argument is a SmallInteger.\\\"\\n\\n\\t(Array with: self)\\n\\t\\telementsForwardIdentityTo:\\n\\t\\t\\t(Array with: otherObject)\\n\\t\\t\\t\\tcopyHash: copyHash! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 10:59'!\\nclassName\\n\\t\\\"Answer a string characterizing the receiver's class, for use in list views for example\\\"\\n\\n\\t^ self class name asString! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:04'!\\ncreationStamp\\n\\t\\\"Answer a string which reports the creation particulars of the receiver. Intended perhaps for list views, but this is presently a feature not easily accessible\\\"\\n\\n\\t^ '<no creation stamp>'! !\\n\\n!Object methodsFor: 'system primitives'!\\ninstVarAt: index \\n\\t\\\"Primitive. Answer a fixed variable in an object. The numbering of the \\n\\tvariables corresponds to the named instance variables. Fail if the index \\n\\tis not an Integer or is not the index of a fixed variable. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 73>\\n\\t\\\"Access beyond fixed variables.\\\"\\n\\t^self basicAt: index - self class instSize\\t\\t! !\\n\\n!Object methodsFor: 'system primitives'!\\ninstVarAt: anInteger put: anObject \\n\\t\\\"Primitive. Store a value into a fixed variable in the receiver. The \\n\\tnumbering of the variables corresponds to the named instance variables. \\n\\tFail if the index is not an Integer or is not the index of a fixed variable. \\n\\tAnswer the value stored as the result. Using this message violates the \\n\\tprinciple that each object has sovereign control over the storing of \\n\\tvalues into its instance variables. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 74>\\n\\t\\\"Access beyond fixed fields\\\"\\n\\t^self basicAt: anInteger - self class instSize put: anObject! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:09'!\\ninstVarNamed: aString\\n\\t\\\"Return the value of the instance variable in me with that name. Slow and unclean, but very useful. \\\"\\n\\n\\t^ self instVarAt: (self class allInstVarNames indexOf: aString asString)\\n\\n\\n! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:10'!\\ninstVarNamed: aString put: aValue\\n\\t\\\"Store into the value of the instance variable in me of that name. Slow and unclean, but very useful. \\\"\\n\\n\\t^ self instVarAt: (self class allInstVarNames indexOf: aString asString) put: aValue\\n! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'sw 10/17/2000 11:12'!\\noopString\\n\\t\\\"Answer a string that represents the oop of the receiver\\\"\\n\\n\\t^ self asOop printString! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'ar 3/2/2001 01:34'!\\nprimitiveChangeClassTo: anObject\\n\\t\\\"Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have.\\n\\tNote: The primitive will fail in most cases that you think might work. This is mostly because of a) the difference between compact and non-compact classes, and b) because of differences in the format. As an example, '(Array new: 3) primitiveChangeClassTo: Morph basicNew' would fail for three of the reasons mentioned above. Array is compact, Morph is not (failure #1). Array is variable and Morph is fixed (different format - failure #2). Morph is a fixed-field-only object and the array is too short (failure #3).\\n\\tThe facility is really provided for certain, very specific applications (mostly related to classes changing shape) and not for casual use.\\\"\\n\\n\\t<primitive: 115>\\n\\tself primitiveFailed! !\\n\\n!Object methodsFor: 'system primitives' stamp: 'di 3/27/1999 12:21'!\\nrootStubInImageSegment: imageSegment\\n\\n\\t^ ImageSegmentRootStub new\\n\\t\\txxSuperclass: nil\\n\\t\\tformat: nil\\n\\t\\tsegment: imageSegment! !\\n\\n!Object methodsFor: 'system primitives'!\\nsomeObject\\n\\t\\\"Primitive. Answer the first object in the enumeration of all\\n\\t objects.\\\"\\n\\n\\t<primitive: 138>\\n\\tself primitiveFailed.! !\\n\\n\\n!Object methodsFor: 'testing' stamp: 'sw 9/26/2001 11:58'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t^ #Object! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 5/3/2001 16:19'!\\nbeViewed\\n\\t\\\"Open up a viewer on the receiver. The Presenter is invited to decide just how to present this viewer\\\"\\n\\n\\tself uniqueNameForReference. \\\"So the viewer will have something nice to refer to\\\"\\n\\tself presenter viewObject: self! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/16/2000 11:01'!\\ncostumes\\n\\t\\\"Answer a list of costumes associated with the receiver. The appearance of this method in class Object serves only as a backstop, probably only transitionally\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/12/98 18:09'!\\nhaltIfNil! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 1/20/2006 17:09'!\\nhasLiteralSuchThat: testBlock\\n\\t\\\"This is the end of the imbedded structure path so return false.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 1/20/2006 17:10'!\\nhasLiteralThorough: literal\\n\\t\\\"Answer true if literal is identical to any literal in this array, even if imbedded in further structures. This is the end of the imbedded structure path so return false.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/30/2001 22:24'!\\nhaveFullProtocolBrowsed\\n\\t\\\"Open up a Lexicon on the receiver\\\"\\n\\n\\t^ self haveFullProtocolBrowsedShowingSelector: nil\\n\\n\\t\\\"(2@3) haveFullProtocolBrowsed\\\"\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 9/27/2005 21:04'!\\nhaveFullProtocolBrowsedShowingSelector: aSelector\\n\\t\\\"Open up a Lexicon on the receiver, having it open up showing aSelector, which may be nil\\\"\\n\\n\\t| aBrowser |\\n\\taBrowser := (Smalltalk at: #InstanceBrowser ifAbsent:[^nil]) new useVocabulary: Vocabulary fullVocabulary.\\n\\taBrowser openOnObject: self inWorld: ActiveWorld showingSelector: aSelector\\n\\n\\t\\\"(2@3) haveFullProtocolBrowsed\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 7/30/2005 21:21'!\\nisArray\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 7/9/1999 18:18'!\\nisBehavior\\n\\t\\\"Return true if the receiver is a behavior.\\n\\tNote: Do not override in any class except behavior.\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ajh 1/21/2003 13:15'!\\nisBlock\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'!\\nisBlockClosure\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'yo 8/28/2002 13:41'!\\nisCharacter\\n\\n\\t^ false.\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 8/17/1999 19:43'!\\nisCollection\\n\\t\\\"Return true if the receiver is some sort of Collection and responds to basic collection messages such as #size and #do:\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing'!\\nisColor\\n\\t\\\"Answer true if receiver is a Color. False by default.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 4/17/2004 19:43'!\\nisColorForm\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'!\\nisCompiledMethod\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'mk 10/27/2003 17:33'!\\nisComplex\\n\\t\\\"Answer true if receiver is a Complex number. False by default.\\\"\\n\\n\\t^ false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 8/11/2005 16:45'!\\nisDictionary\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 11/9/1998 09:38'!\\nisFloat\\n\\t\\\"Overridden to return true in Float, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 10/30/2000 23:22'!\\nisForm\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'len 1/13/98 21:18'!\\nisFraction\\n\\t\\\"Answer true if the receiver is a Fraction.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'rhi 8/14/2003 08:51'!\\nisHeap\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing'!\\nisInteger\\n\\t\\\"Overridden to return true in Integer.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'rhi 8/12/2003 09:52'!\\nisInterval\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 4/25/2002 08:04'!\\nisMessageSend\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!\\nisMethodProperties\\n\\t^false! !\\n\\n!Object methodsFor: 'testing'!\\nisMorph\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 9/13/2000 15:37'!\\nisMorphicEvent\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'gm 2/22/2003 12:56'!\\nisMorphicModel\\n\\t\\\"Return true if the receiver is a morphic model\\\"\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing'!\\nisNumber\\n\\t\\\"Overridden to return true in Number, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 11/6/1998 08:04'!\\nisPoint\\n\\t\\\"Overridden to return true in Point.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ikp 9/26/97 14:45'!\\nisPseudoContext\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 10/2/2005 21:52'!\\nisRectangle\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'nk 6/14/2004 16:49'!\\nisSketchMorph\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'!\\nisStream\\n\\t\\\"Return true if the receiver responds to the stream protocol\\\"\\n\\t^false\\n! !\\n\\n!Object methodsFor: 'testing' stamp: 'sma 6/15/2000 15:48'!\\nisString\\n\\t\\\"Overridden to return true in String, natch\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'md 4/30/2003 15:30'!\\nisSymbol\\n\\t^ false ! !\\n\\n!Object methodsFor: 'testing' stamp: 'jam 3/9/2003 15:10'!\\nisSystemWindow\\n\\\"answer whatever the receiver is a SystemWindow\\\"\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing'!\\nisText\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'pmm 7/6/2006 20:46'!\\nisTrait\\n\\t\\\"Return true if the receiver is a trait.\\n\\tNote: Do not override in any class except TraitBehavior.\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 10/21/97 12:45'!\\nisTransparent\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'ar 8/14/2001 23:19'!\\nisVariableBinding\\n\\t\\\"Return true if I represent a literal variable binding\\\"\\n\\t^false\\n\\t! !\\n\\n!Object methodsFor: 'testing' stamp: 'ls 7/14/1998 21:45'!\\nisWebBrowser\\n\\t\\\"whether this object is a web browser. See class: Scamper\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/27/2000 06:58'!\\nknownName\\n\\t\\\"If a formal name has been handed out for this object, answer it, else nil\\\"\\n\\t\\n\\t^ Preferences capitalizedReferences\\n\\t\\tifTrue:\\n\\t\\t\\t[References keyAtValue: self ifAbsent: [nil]]\\n\\t\\tifFalse:\\n\\t\\t\\t[nil]! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 9/27/96'!\\nname\\n\\t\\\"Answer a name for the receiver. This is used generically in the title of certain inspectors, such as the referred-to inspector, and specificially by various subsystems. By default, we let the object just print itself out.. \\\"\\n\\n\\t^ self printString! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 11/19/2001 13:28'!\\nnameForViewer\\n\\t\\\"Answer a name to be shown in a Viewer that is viewing the receiver\\\"\\n\\n\\t| aName |\\n\\t(aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName].\\n\\t(aName _ self knownName) ifNotNil: [^ aName].\\n\\n\\t^ [(self asString copyWithout: Character cr) truncateTo: 27] ifError:\\n\\t\\t[:msg :rcvr | ^ self class name printString]! !\\n\\n!Object methodsFor: 'testing'!\\nnotNil\\n\\t\\\"Coerces nil to false and everything else to true.\\\"\\n\\n\\t^true! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 9/6/2001 19:15'!\\nopenInstanceBrowserWithTiles\\n\\t\\\"Open up an instance browser on me with tiles as the code type, and with the search level as desired.\\\"\\n\\n\\t| aBrowser |\\n\\taBrowser _ InstanceBrowser new.\\n\\taBrowser useVocabulary: Vocabulary fullVocabulary.\\n\\taBrowser limitClass: self class.\\n\\taBrowser contentsSymbol: #tiles.\\t\\t\\\"preset it to make extra buttons (tile menus)\\\"\\n\\taBrowser openOnObject: self inWorld: ActiveWorld showingSelector: nil.\\n\\taBrowser contentsSymbol: #source.\\n\\taBrowser toggleShowingTiles.\\n\\n\\t\\\"\\n(2@3) openInstanceBrowserWithTiles.\\nWatchMorph new openInstanceBrowserWithTiles\\n\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'tk 7/28/2005 04:50'!\\nrenameInternal: newName \\n\\t\\\"Change the internal name (because of a conflict) but leave the external name unchanged. Change Player class name, but do not change the names that appear in tiles. Any object that might be pointed to in the References dictionary might get this message sent to it upon reload\\\"\\n\\n\\t^ nil\\t\\\"caller will renameTo:. new name may be different\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 2/27/2002 14:55'!\\nrenameTo: newName\\n\\t\\\"If the receiver has an inherent idea about its own name, it should take action here. Any object that might be pointed to in the References dictionary might get this message sent to it upon reload\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 1/18/2001 13:43'!\\nshowDiffs\\n\\t\\\"Answer whether the receiver, serving as the model of a text-bearing entity, is 'showing differences' -- if it is, the editor may wish to show special feedback\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/20/1999 14:52'!\\nstepAt: millisecondClockValue in: aWindow\\n\\n\\t^ self stepIn: aWindow! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:16'!\\nstepIn: aWindow\\n\\n\\t^ self step! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:21'!\\nstepTime\\n\\t\\n\\t^ 1000 \\\"milliseconds -- default backstop for objects serving as models of system windows\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:22'!\\nstepTimeIn: aSystemWindow\\n\\t\\n\\t^ 1000 \\\"milliseconds -- default backstop for objects serving as models of system windows\\\"! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 5/3/2001 18:22'!\\nvocabularyDemanded\\n\\t\\\"Answer a vocabulary that the receiver insists be used when it is looked at in a Viewer. This allows specific classes to insist on specific custom vocabularies\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 11/13/2001 07:26'!\\nwantsDiffFeedback\\n\\t\\\"Answer whether the receiver, serving as the model of a text-bearing entity, would like for 'diffs' green pane-border feedback to be shown\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'di 1/8/1999 15:04'!\\nwantsSteps\\n\\t\\\"Overridden by morphic classes whose instances want to be stepped,\\n\\tor by model classes who want their morphic views to be stepped.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:26'!\\nwantsStepsIn: aSystemWindow\\n\\t\\n\\t^ self wantsSteps! !\\n\\n\\n!Object methodsFor: 'translation support'!\\ninline: inlineFlag\\n\\t\\\"For translation only; noop when running in Smalltalk.\\\"! !\\n\\n!Object methodsFor: 'translation support'!\\nvar: varSymbol declareC: declString\\n\\t\\\"For translation only; noop when running in Smalltalk.\\\"! !\\n\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'!\\ncapturedState\\n\\t\\\"May be overridden in subclasses.\\\"\\n\\n\\t^ self shallowCopy\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:29'!\\ncommandHistory\\n\\t\\\"Return the command history for the receiver\\\"\\n\\t| w |\\n\\t(w _ self currentWorld) ifNotNil: [^ w commandHistory].\\n\\t^ CommandHistory new. \\\"won't really record anything but prevent breaking things\\\"! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 12/12/2000 15:01'!\\npurgeAllCommands\\n\\t\\\"Purge all commands for this object\\\"\\n\\tPreferences useUndo ifFalse: [^ self]. \\\"get out quickly\\\"\\n\\tself commandHistory purgeAllCommandsSuchThat: [:cmd | cmd undoTarget == self].\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/12/2000 08:15'!\\nredoFromCapturedState: st \\n\\t\\\"May be overridden in subclasses. See also capturedState\\\"\\n\\n\\tself undoFromCapturedState: st \\\"Simple cases are symmetric\\\"\\n! !\\n\\n!Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'!\\nrefineRedoTarget: target selector: aSymbol arguments: arguments in: refineBlock \\n\\t\\\"Any object can override this method to refine its redo specification\\\"\\n\\n\\t^ refineBlock\\n\\t\\tvalue: target\\n\\t\\tvalue: aSymbol\\n\\t\\tvalue: arguments! !\\n\\n!Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'!\\nrefineUndoTarget: target selector: aSymbol arguments: arguments in: refineBlock \\n\\t\\\"Any object can override this method to refine its undo specification\\\"\\n\\n\\t^ refineBlock\\n\\t\\tvalue: target\\n\\t\\tvalue: aSymbol\\n\\t\\tvalue: arguments! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:30'!\\nrememberCommand: aCommand\\n\\t\\\"Remember the given command for undo\\\"\\n\\tPreferences useUndo ifFalse: [^ self]. \\\"get out quickly\\\"\\n\\t^ self commandHistory rememberCommand: aCommand! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:30'!\\nrememberUndoableAction: actionBlock named: caption\\n\\t| cmd result |\\n\\tcmd _ Command new cmdWording: caption.\\n\\tcmd undoTarget: self selector: #undoFromCapturedState: argument: self capturedState.\\n\\tresult _ actionBlock value.\\n\\tcmd redoTarget: self selector: #redoFromCapturedState: argument: self capturedState.\\n\\tself rememberCommand: cmd.\\n\\t^ result! !\\n\\n!Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'!\\nundoFromCapturedState: st \\n\\t\\\"May be overridden in subclasses. See also capturedState\\\"\\n\\n\\tself copyFrom: st\\n! !\\n\\n\\n!Object methodsFor: 'updating'!\\nchanged\\n\\t\\\"Receiver changed in a general way; inform all the dependents by \\n\\tsending each dependent an update: message.\\\"\\n\\n\\tself changed: self! !\\n\\n!Object methodsFor: 'updating'!\\nchanged: aParameter \\n\\t\\\"Receiver changed. The change is denoted by the argument aParameter. \\n\\tUsually the argument is a Symbol that is part of the dependent's change \\n\\tprotocol. Inform all of the dependents.\\\"\\n\\n\\tself dependents do: [:aDependent | aDependent update: aParameter]! !\\n\\n!Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:12'!\\nchanged: anAspect with: anObject\\n\\t\\\"Receiver changed. The change is denoted by the argument anAspect. \\n\\tUsually the argument is a Symbol that is part of the dependent's change \\n\\tprotocol. Inform all of the dependents. Also pass anObject for additional information.\\\"\\n\\n\\tself dependents do: [:aDependent | aDependent update: anAspect with: anObject]! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/12/1999 18:15'!\\nhandledListVerification\\n\\t\\\"When a self-updating PluggableListMorph lazily checks to see the state of affairs, it first gives its model an opportunity to handle the list verification itself (this is appropriate for some models, such as VersionsBrowser); if a list's model has indeed handled things itself, it returns true here\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/31/1999 00:15'!\\nnoteSelectionIndex: anInteger for: aSymbol\\n\\t\\\"backstop\\\"! !\\n\\n!Object methodsFor: 'updating'!\\nokToChange\\n\\t\\\"Allows a controller to ask this of any model\\\"\\n\\t^ true! !\\n\\n!Object methodsFor: 'updating' stamp: 'sw 10/19/1999 14:39'!\\nupdateListsAndCodeIn: aWindow\\n\\tself canDiscardEdits ifFalse: [^ self].\\n\\taWindow updatablePanes do: [:aPane | aPane verifyContents]! !\\n\\n!Object methodsFor: 'updating' stamp: 'sma 2/29/2000 20:05'!\\nupdate: aParameter \\n\\t\\\"Receive a change notice from an object of whom the receiver is a \\n\\tdependent. The default behavior is to do nothing; a subclass might want \\n\\tto change itself in some way.\\\"\\n\\n\\t^ self! !\\n\\n!Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:13'!\\nupdate: anAspect with: anObject\\n\\t\\\"Receive a change notice from an object of whom the receiver is a \\n\\tdependent. The default behavior is to call update:,\\n\\twhich by default does nothing; a subclass might want \\n\\tto change itself in some way.\\\"\\n\\n\\t^ self update: anAspect! !\\n\\n!Object methodsFor: 'updating' stamp: 'jm 8/20/1998 18:26'!\\nwindowIsClosing\\n\\t\\\"This message is used to inform a models that its window is closing. Most models do nothing, but some, such as the Debugger, must do some cleanup. Note that this mechanism must be used with care by models that support multiple views, since one view may be closed while others left open.\\\"\\n! !\\n\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/4/1999 08:13'!\\naddModelItemsToWindowMenu: aMenu\\n\\t\\\"aMenu is being constructed to be presented to the user in response to the user's pressing on the menu widget in the title bar of a morphic window. Here, the model is given the opportunity to add any model-specific items to the menu, whose default target is the SystemWindow itself.\\\"! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/5/1998 14:39'!\\naddModelMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph \\n\\t\\\"The receiver serves as the model for aMorph; a menu is being constructed for the morph, and here the receiver is able to add its own items\\\"\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:43'!\\nasExplorerString\\n\\t^ self printString! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 7/13/1999 15:53'!\\ndefaultBackgroundColor\\n\\t\\\"Answer the color to be used as the base window color for a window whose model is an object of the receiver's class\\\"\\n\\t\\n\\t^ Preferences windowColorFor: self class name! !\\n\\n!Object methodsFor: 'user interface'!\\ndefaultLabelForInspector\\n\\t\\\"Answer the default label to be used for an Inspector window on the receiver.\\\"\\n\\n\\t^ self class name! !\\n\\n!Object methodsFor: 'user interface' stamp: 'RAA 7/10/2000 08:11'!\\neToyStreamedRepresentationNotifying: aWidget\\n\\n\\t| outData |\\n\\t[ outData _ SmartRefStream streamedRepresentationOf: self ] \\n\\t\\ton: ProgressInitiationException\\n\\t\\tdo: [ :ex | \\n\\t\\t\\tex sendNotificationsTo: [ :min :max :curr |\\n\\t\\t\\t\\taWidget ifNotNil: [aWidget flashIndicator: #working].\\n\\t\\t\\t].\\n\\t\\t].\\n\\t^outData\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:29'!\\nexplore\\n\\t^ToolSet explore: self! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 8/15/97 17:25'!\\nfullScreenSize\\n\\t\\\"Answer the size to which a window displaying the receiver should be set\\\"\\n\\t| adj |\\n\\tadj _ (3 * Preferences scrollBarWidth) @ 0.\\n\\t^ Rectangle origin: adj extent: (DisplayScreen actualScreenSize - adj)! !\\n\\n!Object methodsFor: 'user interface' stamp: 'RAA 6/21/1999 11:27'!\\nhasContentsInExplorer\\n\\n\\t^self basicSize > 0 or: [self class allInstVarNames isEmpty not]\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'rbb 3/1/2005 09:28'!\\ninform: aString\\n\\t\\\"Display a message for the user to read and then dismiss. 6/9/96 sw\\\"\\n\\n\\taString isEmptyOrNil ifFalse: [UIManager default inform: aString]! !\\n\\n!Object methodsFor: 'user interface'!\\ninitialExtent\\n\\t\\\"Answer the desired extent for the receiver when a view on it is first opened on the screen. \\n\\t5/22/96 sw: in the absence of any override, obtain from RealEstateAgent\\\"\\n\\n\\t^ RealEstateAgent standardWindowExtent! !\\n\\n!Object methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:30'!\\ninspectWithLabel: aLabel\\n\\t\\\"Create and schedule an Inspector in which the user can examine the receiver's variables.\\\"\\n\\t^ToolSet inspect: self label: aLabel! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 6/12/2001 11:09'!\\nlaunchPartVia: aSelector\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 6/17/2004 01:47'!\\nlaunchPartVia: aSelector label: aString\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setNameTo: (ActiveWorld unusedMorphNameLike: aString).\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/16/2000 11:11'!\\nlaunchTileToRefer\\n\\t\\\"Create a tile to reference the receiver, and attach it to the hand\\\"\\n\\n\\tself currentHand attachMorph: self tileToRefer! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:26'!\\nmodelSleep\\n\\t\\\"A window with me as model is being exited or collapsed or closed.\\n\\tDefault response is no-op\\\" ! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:01'!\\nmodelWakeUp\\n\\t\\\"A window with me as model is being entered or expanded. Default response is no-op\\\" ! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 10/16/1999 22:45'!\\nmodelWakeUpIn: aWindow\\n\\t\\\"A window with me as model is being entered or expanded. Default response is no-op\\\" \\n\\tself modelWakeUp! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 3/8/1999 15:27'!\\nmouseUpBalk: evt\\n\\t\\\"A button I own got a mouseDown, but the user moved out before letting up. Certain kinds of objects (so-called 'radio buttons', for example, and other structures that must always have some selection, e.g. PaintBoxMorph) wish to take special action in this case; this default does nothing.\\\"\\n! !\\n\\n!Object methodsFor: 'user interface' stamp: 'sw 8/22/97 13:14'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new setLiteral: self! !\\n\\n!Object methodsFor: 'user interface' stamp: 'jcg 11/1/2001 13:13'!\\nnotYetImplemented\\n\\tself inform: 'Not yet implemented (', thisContext sender printString, ')'! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'!\\nwindowActiveOnFirstClick\\n\\t\\\"Return true if my window should be active on first click.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'!\\nwindowReqNewLabel: labelString\\n\\t\\\"My window's title has been edited.\\n\\tReturn true if this is OK, and override for further behavior.\\\"\\n\\n\\t^ true! !\\n\\n\\n!Object methodsFor: 'world hacking' stamp: 'ar 3/17/2001 23:45'!\\ncouldOpenInMorphic\\n\\n \\\"is there an obvious morphic world in which to open a new morph?\\\"\\n\\n ^World notNil or: [ActiveWorld notNil]! !\\n\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/24/2004 08:49'!\\nbeep\\n\\t\\\"Deprecated.\\\"\\n\\t\\n\\tself deprecated: 'Use Beeper class>>beep instead.'.\\n\\tBeeper beep! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/24/2004 08:50'!\\nbeepPrimitive\\n\\t\\\"Deprecated. Beep in the absence of sound support.\\\"\\n\\t\\n\\tself deprecated: 'Use Beeper class>>beep or Beeper class>>beepPrimitive instead.'.\\n\\tBeeper beepPrimitive! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 12/12/2003 17:02'!\\nbeep: soundName\\n\\t\\\"Make the given sound, unless the making of sound is disabled in Preferences.\\\"\\n\\n\\tself deprecated: 'Use SampledSound>>playSoundNamed: instead.'.\\n\\tPreferences soundsEnabled\\n\\t\\tifTrue: [self playSoundNamed: soundName]\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/19/2004 16:57'!\\ncontentsGetz: x\\n\\tself deprecated: 'there is no method named contents in object and in addition only one sender in a method not called'. \\n\\tself contents: x! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/13/2003 21:10'!\\ndeprecatedExplanation: aString\\n \\\"This method is OBSOLETE. Use #deprecated: instead.\\\"\\n\\tself deprecated: 'Use Object>>deprecated: instead of deprecatedExplanation:.'.\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation signal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})]! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'sd 11/13/2003 21:11'!\\ndeprecated: aBlock explanation: aString \\n\\t \\\"This method is OBSOLETE. Use #deprecated:block: instead.\\\"\\n\\tself deprecated: 'Use Object>>deprecated:block: instead of deprecated:explanation:.'.\\n\\n\\tPreferences showDeprecationWarnings ifTrue:\\n\\t\\t[Deprecation\\n\\t\\t\\tsignal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})].\\n\\t^ aBlock value.\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 12/12/2003 16:25'!\\ndoIfNotNil: aBlock\\n\\tself deprecated: 'use ifNotNilDo:'.\\n\\t^ self ifNotNilDo: aBlock\\n! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'md 11/27/2004 12:20'!\\nifKindOf: aClass thenDo: aBlock\\n\\tself deprecated: 'Deprecated. Just use #isKindOf:'.\\n\\t^ (self isKindOf: aClass) ifTrue: [aBlock value: self]! !\\n\\n!Object methodsFor: '*39Deprecated' stamp: 'gk 2/23/2004 20:51'!\\nplaySoundNamed: soundName\\n\\t\\\"Deprecated.\\n\\tPlay the sound with the given name.\\\"\\n\\n\\tself deprecated: 'Use \\\"SoundService default playSoundNamed: aName\\\" instead.'.\\n\\tSoundService default playSoundNamed: soundName! !\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n!Object methodsFor: '*monticello' stamp: 'dvf 8/10/2004 23:25'!\\nisConflict\\n\\t^false! !\\n\\n\\n!Object methodsFor: '*services-base' stamp: 'rr 3/21/2006 11:54'!\\nrequestor\\n\\t\\\"returns the focused window's requestor\\\"\\n\\n\\t\\\"SystemWindow focusedWindow ifNotNilDo: [:w | ^ w requestor].\\\"\\n\\n\\t\\\"triggers an infinite loop\\\"\\n\\n\\t^ Requestor default! !\\n\\n\\n!Object methodsFor: '*system-support' stamp: 'dvf 8/23/2003 12:27'!\\nsystemNavigation\\n\\n\\t^ SystemNavigation default! !\\n\\n\\n!Object methodsFor: '*Tools-Explorer' stamp: 'stephaneducasse 9/17/2005 21:52'!\\nexploreAndYourself\\n\\t\\\"i.e. explore; yourself. Thisway i can peek w/o typing all the parentheses\\\"\\n\\tself explore. \\n ^self! !\\n\\n!Object methodsFor: '*Tools-Explorer' stamp: 'stephaneducasse 9/17/2005 21:48'!\\nexploreWithLabel: label\\n\\n\\t^ ObjectExplorer new openExplorerFor: self withLabel:\\nlabel! !\\n\\n\\n\\n\\n\\n!Object methodsFor: '*tools-browser' stamp: 'mu 3/6/2004 15:13'!\\nbrowse\\n\\tself systemNavigation browseClass: self class! !\\n\\n!Object methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 16:00'!\\nbrowseHierarchy\\n\\tself systemNavigation browseHierarchy: self class! !\\n\\n\\n!Object methodsFor: 'private'!\\nerrorImproperStore\\n\\t\\\"Create an error notification that an improper store was attempted.\\\"\\n\\n\\tself error: 'Improper store into indexable object'! !\\n\\n!Object methodsFor: 'private'!\\nerrorNonIntegerIndex\\n\\t\\\"Create an error notification that an improper object was used as an index.\\\"\\n\\n\\tself error: 'only integers should be used as indices'! !\\n\\n!Object methodsFor: 'private' stamp: 'yo 6/29/2004 11:37'!\\nerrorNotIndexable\\n\\t\\\"Create an error notification that the receiver is not indexable.\\\"\\n\\n\\tself error: ('Instances of {1} are not indexable' translated format: {self class name})! !\\n\\n!Object methodsFor: 'private'!\\nerrorSubscriptBounds: index \\n\\t\\\"Create an error notification that an improper integer was used as an index.\\\"\\n\\n\\tself error: 'subscript is out of bounds: ' , index printString! !\\n\\n!Object methodsFor: 'private' stamp: 'ar 2/6/2004 14:47'!\\nprimitiveError: aString \\n\\t\\\"This method is called when the error handling results in a recursion in \\n\\tcalling on error: or halt or halt:.\\\"\\n\\n\\t| context |\\n\\t(String\\n\\t\\tstreamContents: \\n\\t\\t\\t[:s |\\n\\t\\t\\ts nextPutAll: '***System error handling failed***'.\\n\\t\\t\\ts cr; nextPutAll: aString.\\n\\t\\t\\tcontext _ thisContext sender sender.\\n\\t\\t\\t20 timesRepeat: [context == nil ifFalse: [s cr; print: (context _ context sender)]].\\n\\t\\t\\ts cr; nextPutAll: '-------------------------------'.\\n\\t\\t\\ts cr; nextPutAll: 'Type CR to enter an emergency evaluator.'.\\n\\t\\t\\ts cr; nextPutAll: 'Type any other character to restart.'])\\n\\t\\tdisplayAt: 0 @ 0.\\n\\t[Sensor keyboardPressed] whileFalse.\\n\\tSensor keyboard = Character cr ifTrue: [Transcripter emergencyEvaluator].\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue: [World install \\\"init hands and redisplay\\\"]\\n\\t\\tifFalse: [ScheduledControllers searchForActiveController]! !\\n\\n!Object methodsFor: 'private'!\\nspecies\\n\\t\\\"Answer the preferred class for reconstructing the receiver. For example, \\n\\tcollections create new collections whenever enumeration messages such as \\n\\tcollect: or select: are invoked. The new kind of collection is determined by \\n\\tthe species of the original collection. Species and class are not always the \\n\\tsame. For example, the species of Interval is Array.\\\"\\n\\n\\t^self class! !\\n\\n!Object methodsFor: 'private'!\\nstoreAt: offset inTempFrame: aContext\\n\\t\\\"This message had to get sent to an expression already on the stack\\n\\tas a Block argument being accessed by the debugger.\\n\\tJust re-route it to the temp frame.\\\"\\n\\t^ aContext tempAt: offset put: self! !\\n\\n\\n!Object methodsFor: '*Morphic-NewCurve-testing''' stamp: 'wiz 12/31/2005 21:31'!\\nisNonZero\\n\\\"Overriden in Number. This returns the backstop answer for non-numbers\\\"\\n^false.! !\\n\\n\\n!Object methodsFor: 'events' stamp: 'nk 8/27/2003 16:23'!\\nactionsWithReceiver: anObject forEvent: anEventSelector\\n\\n\\t^(self actionSequenceForEvent: anEventSelector)\\n select: [:anAction | anAction receiver == anObject ]! !\\n\\n!Object methodsFor: 'events' stamp: 'nk 8/27/2003 17:45'!\\nrenameActionsWithReceiver: anObject forEvent: anEventSelector toEvent: newEvent\\n\\n\\t| oldActions newActions |\\n\\toldActions _ Set new.\\n\\tnewActions _ Set new.\\n\\t(self actionSequenceForEvent: anEventSelector) do: [ :action |\\n\\t\\taction receiver == anObject\\n\\t\\t\\tifTrue: [ oldActions add: anObject ]\\n\\t\\t\\tifFalse: [ newActions add: anObject ]].\\n\\tself setActionSequence: (ActionSequence withAll: newActions) forEvent: anEventSelector.\\n\\toldActions do: [ :act | self when: newEvent evaluate: act ].! !\\n\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:35'!\\nassureUniClass\\n\\t\\\"If the receiver is not yet an instance of a uniclass, create a uniclass for it and make the receiver become an instance of that class.\\\"\\n\\n\\t| anInstance |\\n\\tself belongsToUniClass ifTrue: [^ self].\\n\\tanInstance _ self class instanceOfUniqueClass.\\n\\tself become: (self as: anInstance class).\\n\\t^ anInstance! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:41'!\\nbelongsToUniClass\\n\\t\\\"Answer whether the receiver belongs to a uniclass. For the moment (this is not entirely satisfactory) this is precisely equated with the classname ending in a digit\\\"\\n\\n\\t^ self class name endsWithDigit! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 12/11/2000 15:37'!\\nbrowseOwnClassSubProtocol\\n\\t\\\"Open up a ProtocolBrowser on the subprotocol of the receiver\\\"\\n\\n\\tProtocolBrowser openSubProtocolForClass: self class\\n! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/4/2001 00:51'!\\ncategoriesForViewer: aViewer\\n\\t\\\"Answer a list of categories to offer in the given viewer\\\"\\n\\n\\t^ aViewer currentVocabulary categoryListForInstance: self ofClass: self class limitClass: aViewer limitClass! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/3/2001 22:08'!\\ncategoriesForVocabulary: aVocabulary limitClass: aLimitClass\\n\\t\\\"Answer a list of categories of methods for the receiver when using the given vocabulary, given that one considers only methods that are implemented not further away than aLimitClass\\\"\\n\\n\\t^ aVocabulary categoryListForInstance: self ofClass: self class limitClass: aLimitClass! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/25/2000 07:20'!\\nchooseNewNameForReference\\n\\t\\\"Offer an opportunity for the receiver, presumed already to be known in the References registry, to be renamed\\\"\\n\\n\\t| nameSym current newName |\\n\\tcurrent _ References keyAtValue: self ifAbsent: [^ self error: 'not found in References'].\\n\\n\\tnewName _ FillInTheBlank request: 'Please enter new name' initialAnswer: current.\\n\\t\\\"Want to user some better way of determining the validity of the chosen identifier, and also want to give more precise diagnostic if the string the user types in is not acceptable. Work to be done here.\\\"\\n\\n\\tnewName isEmpty ifTrue: [^ nil].\\n\\t((Scanner isLiteralSymbol: newName) and: [(newName includes: $:) not])\\n\\t\\tifTrue:\\n\\t\\t\\t[nameSym _ newName capitalized asSymbol.\\n\\t\\t\\t(((References includesKey: nameSym) not and:\\n\\t\\t\\t\\t[(Smalltalk includesKey: nameSym) not]) and:\\n\\t\\t\\t\\t\\t\\t[(ScriptingSystem allKnownClassVariableNames includes: nameSym) not])\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[(References associationAt: current) key: nameSym.\\n\\t\\t\\t\\t\\t\\tReferences rehash.\\n\\t\\t\\t\\t\\t\\t^ nameSym]].\\n\\tself inform: 'Sorry, that name is not available.'.\\n\\t^ nil! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/3/2001 21:22'!\\ndefaultLimitClassForVocabulary: aVocabulary\\n\\t\\\"Answer the class to use, by default, as the limit class on a protocol browser or viewer opened up on the receiver, within the purview of the Vocabulary provided\\\"\\n\\n\\t^ (aVocabulary isKindOf: FullVocabulary)\\n\\t\\tifTrue:\\n\\t\\t\\t [self class superclass == Object\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[self class]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[self class superclass]]\\n\\t\\tifFalse:\\n\\t\\t\\t[ProtoObject]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 2/14/2000 14:24'!\\ndefaultNameStemForInstances\\n\\t\\\"Answer a basis for names of default instances of the receiver. The default is to let the class specify, but certain instances will want to override. (PasteUpMorphs serving as Worlds come to mind\\\"\\n\\n\\t^ self class defaultNameStemForInstances! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/22/2001 16:53'!\\nelementTypeFor: aStringOrSymbol vocabulary: aVocabulary\\n\\t\\\"Answer a symbol characterizing what kind of element aStringOrSymbol represents. Realistically, at present, this always just returns #systemScript; a prototyped but not-incorporated architecture supported use of a leading colon to characterize an inst var of a system class, and for the moment we still see its remnant here.\\\"\\n\\n\\tself flag: #deferred. \\\"a loose end in the non-player case\\\"\\n\\t^ #systemScript! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:04'!\\nexternalName\\n\\t\\\"Answer an external name by which the receiver is known. Generic implementation here is a transitional backstop. probably\\\"\\n\\n\\t^ self nameForViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:06'!\\ngraphicForViewerTab\\n\\t\\\"When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Answer a form or a morph to serve that purpose. A generic image is used for arbitrary objects, but note my reimplementors\\\"\\n\\t\\n\\t^ ScriptingSystem formAtKey: 'Image'! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:08'!\\nhasUserDefinedSlots\\n\\t\\\"Answer whether the receiver has any user-defined slots, in the omniuser sense of the term. This is needed to allow Viewers to look at any object, not just at Players.\\\"\\n\\n\\t^ false! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/22/2002 14:07'!\\ninfoFor: anElement inViewer: aViewer\\n\\t\\\"The user made a gesture asking for info/menu relating to me. Some of the messages dispatched here are not yet available in this image\\\"\\n\\n\\t| aMenu elementType |\\n\\telementType _ self elementTypeFor: anElement vocabulary: aViewer currentVocabulary.\\n\\t((elementType = #systemSlot) | (elementType == #userSlot))\\n\\t\\tifTrue:\\t[^ self slotInfoButtonHitFor: anElement inViewer: aViewer].\\n\\tself flag: #deferred. \\\"Use a traditional MenuMorph, and reinstate the pacify thing\\\"\\n\\taMenu _ MenuMorph new defaultTarget: aViewer.\\n\\t#(\\t('implementors'\\t\\t\\tbrowseImplementorsOf:)\\n\\t\\t('senders'\\t\\t\\t\\tbrowseSendersOf:)\\n\\t\\t('versions'\\t\\t\\t\\tbrowseVersionsOf:)\\n\\t\\t-\\n\\t\\t('browse full'\\t\\t\\tbrowseMethodFull:)\\n\\t\\t('inheritance'\\t\\t\\tbrowseMethodInheritance:)\\n\\t\\t-\\n\\t\\t('about this method'\\t\\taboutMethod:)) do:\\n\\n\\t\\t\\t[:pair |\\n\\t\\t\\t\\tpair = '-'\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[aMenu addLine]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[aMenu add: pair first target: aViewer selector: pair second argument: anElement]].\\n\\taMenu addLine.\\n\\taMenu defaultTarget: self.\\n\\t#(\\t('destroy script'\\t\\tremoveScript:)\\n\\t\\t('rename script'\\t\\trenameScript:)\\n\\t\\t('pacify script'\\t\\tpacifyScript:)) do:\\n\\t\\t\\t[:pair |\\n\\t\\t\\t\\taMenu add: pair first target: self selector: pair second argument: anElement].\\n\\n\\taMenu addLine.\\n\\taMenu add: 'show categories....' target: aViewer selector: #showCategoriesFor: argument: anElement.\\n\\taMenu items size == 0 ifTrue: \\\"won't happen at the moment a/c the above\\\"\\n\\t\\t[aMenu add: 'ok' action: nil]. \\\"in case it was a slot -- weird, transitional\\\"\\n\\n\\taMenu addTitle: anElement asString, ' (', elementType, ')'.\\n\\n\\taMenu popUpInWorld: self currentWorld.\\n ! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 9/26/2001 11:58'!\\ninitialTypeForSlotNamed: aName\\n\\t\\\"Answer the initial type to be ascribed to the given instance variable\\\"\\n\\n\\t^ #Object! !\\n\\n!Object methodsFor: 'viewer' stamp: 'ar 5/26/2001 16:13'!\\nisPlayerLike\\n\\t\\\"Return true if the receiver is a player-like object\\\"\\n\\t^false! !\\n\\n!Object methodsFor: 'viewer' stamp: 'nk 9/11/2004 16:53'!\\nmethodInterfacesInPresentationOrderFrom: interfaceList forCategory: aCategory \\n\\t\\\"Answer the interface list sorted in desired presentation order, using a \\n\\tstatic master-ordering list, q.v. The category parameter allows an \\n\\tescape in case one wants to apply different order strategies in different \\n\\tcategories, but for now a single master-priority-ordering is used -- see \\n\\tthe comment in method EToyVocabulary.masterOrderingOfPhraseSymbols\\\"\\n\\n\\t| masterOrder ordered unordered index |\\n\\tmasterOrder := Vocabulary eToyVocabulary masterOrderingOfPhraseSymbols.\\n\\tordered := SortedCollection sortBlock: [:a :b | a key < b key].\\n\\tunordered := SortedCollection sortBlock: [:a :b | a wording < b wording].\\n\\n\\tinterfaceList do: [:interface | \\n\\t\\tindex := masterOrder indexOf: interface elementSymbol.\\n\\t\\tindex isZero\\n\\t\\t\\tifTrue: [unordered add: interface]\\n\\t\\t\\tifFalse: [ordered add: index -> interface]].\\n\\n\\t^ Array\\n\\t\\tstreamContents: [:stream | \\n\\t\\t\\tordered do: [:assoc | stream nextPut: assoc value].\\n\\t\\t\\tstream nextPutAll: unordered]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/24/2000 11:36'!\\nnewScriptorAround: aPhraseTileMorph\\n\\t\\\"Sprout a scriptor around aPhraseTileMorph, thus making a new script. This is where generalized scriptors will be threaded in\\\"\\n\\n\\t^ nil! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 10/25/2000 17:42'!\\nofferViewerMenuForEvt: anEvent morph: aMorph\\n\\t\\\"Offer the viewer's primary menu to the user. aMorph is some morph within the viewer itself, the one within which a mousedown triggered the need for this menu, and it is used only to retrieve the Viewer itself\\\"\\n\\n\\tself offerViewerMenuFor: (aMorph ownerThatIsA: StandardViewer) event: anEvent! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/11/2002 02:03'!\\nofferViewerMenuFor: aViewer event: evt\\n\\t\\\"Offer the primary Viewer menu to the user. Copied up from Player code, but most of the functions suggested here don't work for non-Player objects, many aren't even defined, some relate to exploratory sw work not yet reflected in the current corpus. We are early in the life cycle of this method...\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\taMenu title: '**CAUTION -- UNDER CONSTRUCTION!!**\\nMany things may not work!!\\n', self nameForViewer.\\n\\t(aViewer affordsUniclass and: [self belongsToUniClass not]) ifTrue:\\n\\t\\t[aMenu add: 'give me a Uniclass' action: #assureUniClass.\\n\\t\\taMenu addLine].\\n\\taMenu add: 'choose vocabulary...' target: aViewer action: #chooseVocabulary.\\n\\taMenu add: 'choose limit class...' target: aViewer action: #chooseLimitClass.\\n\\taMenu add: 'add search pane' target: aViewer action: #addSearchPane.\\n\\taMenu balloonTextForLastItem: 'Specify which class should be the most generic one to have its methods shown in this Viewer'.\\n\\taMenu addLine.\\n\\n\\tself belongsToUniClass ifTrue:\\n\\t\\t[aMenu add: 'add a new instance variable' target: self selector: #addInstanceVariableIn: argument: aViewer.\\n\\t\\taMenu add: 'add a new script' target: aViewer selector: #newPermanentScriptIn: argument: aViewer.\\n\\t\\taMenu addLine.\\n\\t\\taMenu add: 'make my class be first-class' target: self selector: #makeFirstClassClassIn: argument: aViewer.\\n\\t\\taMenu add: 'move my changes up to my superclass' target: self action: #promoteChangesToSuperclass.\\n\\t\\taMenu addLine].\\n\\n\\taMenu add: 'tear off a tile' target: self selector: #launchTileToRefer.\\n\\taMenu addLine.\\n\\n\\taMenu add: 'inspect me' target: self selector: #inspect.\\n\\taMenu add: 'inspect my class' target: self class action: #inspect.\\n\\taMenu addLine.\\n\\n\\taMenu add: 'browse vocabulary' action: #haveFullProtocolBrowsed.\\n\\taMenu add: 'inspect this Viewer' target: aViewer action: #inspect.\\n\\n\\taMenu popUpEvent: evt in: aViewer currentWorld\\n\\n\\\"\\n\\taMenu add: 'references to me' target: aViewer action: #browseReferencesToObject.\\n\\taMenu add: 'toggle scratch pane' target: aViewer selector: #toggleScratchPane.\\n\\taMenu add: 'make a nascent script for me' target: aViewer selector: #makeNascentScript.\\n\\taMenu add: 'rename me' target: aViewer selector: #chooseNewNameForReference.\\n\\taMenu add: 'browse full' action: #browseOwnClassFull.\\n\\taMenu add: 'browse hierarchy' action: #browseOwnClassHierarchy.\\n\\taMenu add: 'set user level...' target: aViewer action: #setUserLevel.\\n\\taMenu add: 'browse sub-protocol' action: #browseOwnClassSubProtocol.\\n\\taMenu addLine.\\n\\n\\\"! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 1/22/2001 15:20'!\\nrenameScript: oldSelector\\n\\t\\\"prompt the user for a new selector and apply it. Presently only works for players\\\"\\n\\n\\tself notYetImplemented! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 11:53'!\\ntilePhrasesForCategory: aCategorySymbol inViewer: aViewer\\n\\t\\\"Return a collection of phrases for the category.\\\"\\n\\n\\t| interfaces |\\n\\tinterfaces _ self methodInterfacesForCategory: aCategorySymbol inVocabulary: aViewer currentVocabulary limitClass: aViewer limitClass.\\n\\tinterfaces _ self methodInterfacesInPresentationOrderFrom: interfaces forCategory: aCategorySymbol.\\n\\t^ self tilePhrasesForMethodInterfaces: interfaces inViewer: aViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 11:53'!\\ntilePhrasesForMethodInterfaces: methodInterfaceList inViewer: aViewer\\n\\t\\\"Return a collection of ViewerLine objects corresponding to the method-interface list provided. The resulting list will be in the same order as the incoming list, but may be smaller if the viewer's vocbulary suppresses some of the methods, or if, in classic tiles mode, the selector requires more arguments than can be handled.\\\"\\n\\n\\t| toSuppress interfaces resultType itsSelector |\\n\\ttoSuppress _ aViewer currentVocabulary phraseSymbolsToSuppress.\\n\\tinterfaces _ methodInterfaceList reject: [:int | toSuppress includes: int selector].\\n\\tPreferences universalTiles ifFalse: \\\"Classic tiles have their limitations...\\\"\\n\\t\\t[interfaces _ interfaces select:\\n\\t\\t\\t[:int |\\n\\t\\t\\t\\titsSelector _ int selector.\\n\\t\\t\\t\\titsSelector numArgs < 2 or:\\n\\t\\t\\t\\t\\t\\\"The lone two-arg loophole in classic tiles\\\"\\n\\t\\t\\t\\t\\t[#(color:sees:) includes: itsSelector]]].\\n\\n\\t^ interfaces collect:\\n\\t\\t[:aMethodInterface |\\n\\t\\t\\t((resultType _ aMethodInterface resultType) notNil and: [resultType ~~ #unknown]) \\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aViewer phraseForVariableFrom: aMethodInterface]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[aViewer phraseForCommandFrom: aMethodInterface]]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 8/10/2004 12:23'!\\ntilePhrasesForSelectorList: aList inViewer: aViewer\\n\\t\\\"Particular to the search facility in viewers. Answer a list, in appropriate order, of ViewerLine objects to put into the viewer.\\\"\\n\\n\\t| interfaces aVocab |\\n\\taVocab _ aViewer currentVocabulary.\\n\\tinterfaces _ self\\n\\t\\tmethodInterfacesInPresentationOrderFrom:\\n\\t\\t\\t(aList collect: [:aSel | aVocab methodInterfaceForSelector: aSel class: self class])\\n\\t\\tforCategory: #search.\\n\\t^ self tilePhrasesForMethodInterfaces: interfaces inViewer: aViewer! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 04:51'!\\ntileToRefer\\n\\t\\\"Answer a reference tile that comprises an alias to me\\\"\\n\\n\\t^ TileMorph new setToReferTo: self! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sd 3/30/2005 22:04'!\\nuniqueInstanceVariableNameLike: aString excluding: takenNames\\n\\t\\\"Answer a nice instance-variable name to be added to the receiver which resembles aString, making sure it does not coincide with any element in takenNames\\\"\\n\\n\\t| okBase uniqueName usedNames |\\n\\tusedNames _ self class allInstVarNamesEverywhere.\\n\\tusedNames removeAllFoundIn: self class instVarNames.\\n\\tusedNames addAll: takenNames.\\n\\tokBase _ Scanner wellFormedInstanceVariableNameFrom: aString.\\n\\n\\tuniqueName _ Utilities keyLike: okBase satisfying: \\n\\t\\t[:aKey | (usedNames includes: aKey) not].\\n\\n\\t^ uniqueName! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 11/21/2001 15:16'!\\nuniqueNameForReference\\n\\t\\\"Answer a nice name by which the receiver can be referred to by other objects. At present this uses a global References dictionary to hold the database of references, but in due course this will need to acquire some locality\\\"\\n\\n\\t| aName nameSym stem knownClassVars |\\n\\t(aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName].\\n\\t(stem _ self knownName) ifNil:\\n\\t\\t[stem _ self defaultNameStemForInstances asString].\\n\\tstem _ stem select: [:ch | ch isLetter or: [ch isDigit]].\\n\\tstem size == 0 ifTrue: [stem _ 'A'].\\n\\tstem first isLetter ifFalse:\\n\\t\\t[stem _ 'A', stem].\\n\\tstem _ stem capitalized.\\n\\tknownClassVars _ ScriptingSystem allKnownClassVariableNames.\\n\\taName _ Utilities keyLike: stem satisfying:\\n\\t\\t[:jinaLake |\\n\\t\\t\\tnameSym _ jinaLake asSymbol.\\n\\t\\t\\t ((References includesKey: nameSym) not and:\\n\\t\\t\\t\\t[(Smalltalk includesKey: nameSym) not]) and:\\n\\t\\t\\t\\t\\t\\t[(knownClassVars includes: nameSym) not]].\\n\\n\\tReferences at: (aName _ aName asSymbol) put: self.\\n\\t^ aName! !\\n\\n!Object methodsFor: 'viewer' stamp: 'md 1/17/2006 17:58'!\\nuniqueNameForReferenceFrom: proposedName\\n\\t\\\"Answer a satisfactory symbol, similar to the proposedName but obeying the rules, to represent the receiver\\\"\\n\\n\\t| aName nameSym stem okay |\\n\\tproposedName = self uniqueNameForReferenceOrNil \\n\\t\\tifTrue: [^ proposedName]. \\\"No change\\\"\\n\\n\\tstem _ proposedName select: [:ch | ch isLetter or: [ch isDigit]].\\n\\tstem size == 0 ifTrue: [stem _ 'A'].\\n\\tstem first isLetter ifFalse:\\n\\t\\t[stem _ 'A', stem].\\n\\tstem _ stem capitalized.\\n\\taName _ Utilities keyLike: stem satisfying:\\n\\t\\t[:jinaLake |\\n\\t\\t\\tnameSym _ jinaLake asSymbol.\\n\\t\\t\\tokay _ true.\\n\\t\\t\\t(self class bindingOf: nameSym) ifNotNil: [okay _ false \\\"don't use it\\\"].\\n\\t\\t\\tokay].\\n\\t^ aName asSymbol! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 3/15/2004 23:01'!\\nuniqueNameForReferenceOrNil\\n\\t\\\"If the receiver has a unique name for reference, return it here, else return nil\\\"\\n\\n\\t^ References keyAtValue: self ifAbsent: [nil]! !\\n\\n!Object methodsFor: 'viewer' stamp: 'ar 5/16/2001 01:40'!\\nupdateThresholdForGraphicInViewerTab\\n\\t\\\"When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Computing this graphic can take quite some time so we want to make the update frequency depending on how long it takes to compute the thumbnail. The threshold returned by this method defines that the viewer will update at most every 'threshold * timeItTakesToDraw' milliseconds. Thus, if the time for computing the receiver's thumbnail is 200 msecs and the the threshold is 10, the viewer will update at most every two seconds.\\\"\\n\\t^20 \\\"seems to be a pretty good general choice\\\"! !\\n\\n!Object methodsFor: 'viewer' stamp: 'sw 3/9/2001 13:48'!\\nusableMethodInterfacesIn: aListOfMethodInterfaces\\n\\t\\\"Filter aList, returning a subset list of apt phrases\\\"\\n\\n\\t^ aListOfMethodInterfaces\\n! !\\n\\n\\n!Object methodsFor: 'inspecting' stamp: 'ar 9/27/2005 18:31'!\\nbasicInspect\\n\\t\\\"Create and schedule an Inspector in which the user can examine the \\n\\treceiver's variables. This method should not be overriden.\\\"\\n\\t^ToolSet basicInspect: self! !\\n\\n!Object methodsFor: 'inspecting' stamp: 'md 1/18/2006 19:09'!\\ninspect\\n\\t\\\"Create and schedule an Inspector in which the user can examine the receiver's variables.\\\"\\n\\tToolSet inspect: self! !\\n\\n!Object methodsFor: 'inspecting' stamp: 'apb 7/14/2004 12:19'!\\ninspectorClass\\n\\t\\\"Answer the class of the inspector to be used on the receiver. Called by inspect; \\n\\tuse basicInspect to get a normal (less useful) type of inspector.\\\"\\n\\n\\t^ Inspector! !\\n\\n\\n!Object methodsFor: 'thumbnail' stamp: 'dgd 9/25/2004 23:17'!\\niconOrThumbnailOfSize: aNumberOrPoint \\n\\t\\\"Answer an appropiate form to represent the receiver\\\"\\n\\t^ nil! !\\n\\n\\n!Object methodsFor: 'scripts-kernel' stamp: 'nk 10/14/2004 10:55'!\\nuniversalTilesForGetterOf: aMethodInterface\\n\\t\\\"Return universal tiles for a getter on the given method interface.\\\"\\n\\n\\t| ms argTile argArray itsSelector |\\n\\titsSelector _ aMethodInterface selector.\\n\\targArray _ #().\\n\\n\\t\\\"Four gratuituous special cases...\\\"\\n\\n\\t(itsSelector == #color:sees:) ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Color.\\n\\t\\targArray _ Array with: argTile colorSwatch color with: argTile colorSwatch color copy].\\n\\n\\titsSelector == #seesColor: ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Color.\\n\\t\\targArray _ Array with: argTile colorSwatch color].\\n\\n\\t(#(touchesA: overlaps: overlapsAny:) includes: itsSelector) ifTrue:\\n\\t\\t[argTile _ ScriptingSystem tileForArgType: #Player.\\n\\t\\targArray _ Array with: argTile actualObject].\\n\\n\\tms _ MessageSend receiver: self selector: itsSelector arguments: argArray.\\n\\t^ ms asTilesIn: self class globalNames: (self class officialClass ~~ CardPlayer)\\n\\t\\t\\t\\\"For CardPlayers, use 'self'. For others, name it, and use its name.\\\"! !\\n\\n!Object methodsFor: 'scripts-kernel' stamp: 'tk 9/28/2001 13:30'!\\nuniversalTilesForInterface: aMethodInterface\\n\\t\\\"Return universal tiles for the given method interface. Record who self is.\\\"\\n\\n\\t| ms argTile itsSelector aType argList |\\n\\titsSelector _ aMethodInterface selector.\\n\\targList _ OrderedCollection new.\\n\\taMethodInterface argumentVariables doWithIndex:\\n\\t\\t[:anArgumentVariable :anIndex | \\n\\t\\t\\targTile _ ScriptingSystem tileForArgType: (aType _ aMethodInterface typeForArgumentNumber: anIndex).\\n\\t\\t\\targList add: (aType == #Player \\n\\t\\t\\t\\tifTrue: [argTile actualObject]\\n\\t\\t\\t\\tifFalse: [argTile literal]).\\t\\\"default value for each type\\\"].\\n\\n\\tms _ MessageSend receiver: self selector: itsSelector arguments: argList asArray.\\n\\t^ ms asTilesIn: self class globalNames: (self class officialClass ~~ CardPlayer)\\n\\t\\t\\t\\\"For CardPlayers, use 'self'. For others, name it, and use its name.\\\"! !\\n\\n\\n!Object methodsFor: 'breakpoint' stamp: 'bkv 7/1/2003 12:33'!\\nbreak\\n\\t\\\"This is a simple message to use for inserting breakpoints during debugging.\\n\\tThe debugger is opened by sending a signal. This gives a chance to restore\\n\\tinvariants related to multiple processes.\\\"\\n\\n\\tBreakPoint signal.\\n\\n\\t\\\"nil break.\\\"! !\\n\\n\\n\\n!Object methodsFor: '*omnibrowser-converting' stamp: 'cwp 4/17/2006 12:16'!\\nasAnnouncement\\n\\t^ self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObject class\\n\\tinstanceVariableNames: ''!\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 02:00'!\\nflushDependents\\n\\tDependentsFields keysAndValuesDo:[:key :dep|\\n\\t\\tkey ifNotNil:[key removeDependent: nil].\\n\\t].\\n\\tDependentsFields finalizeValues.! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'rw 2/10/2002 13:09'!\\nflushEvents\\n\\t\\\"Object flushEvents\\\"\\n\\n\\tEventManager flushEvents. ! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'rww 10/2/2001 07:35'!\\ninitialize\\n\\t\\\"Object initialize\\\"\\n\\tDependentsFields ifNil:[self initializeDependentsFields].! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:41'!\\ninitializeDependentsFields\\n\\t\\\"Object initialize\\\"\\n\\tDependentsFields _ WeakIdentityKeyDictionary new.\\n! !\\n\\n!Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:45'!\\nreInitializeDependentsFields\\n\\t\\\"Object reInitializeDependentsFields\\\"\\n\\t| oldFields |\\n\\toldFields _ DependentsFields.\\n\\tDependentsFields _ WeakIdentityKeyDictionary new.\\n\\toldFields keysAndValuesDo:[:obj :deps|\\n\\t\\tdeps do:[:d| obj addDependent: d]].\\n! !\\n\\n\\n!Object class methodsFor: 'documentation'!\\nhowToModifyPrimitives\\n\\t\\\"You are allowed to write methods which specify primitives, but please use \\n\\tcaution. If you make a subclass of a class which contains a primitive method, \\n\\tthe subclass inherits the primitive. The message which is implemented \\n\\tprimitively may be overridden in the subclass (E.g., see at:put: in String's \\n\\tsubclass Symbol). The primitive behavior can be invoked using super (see \\n\\tSymbol string:). \\n\\t \\n\\tA class which attempts to mimic the behavior of another class without being \\n\\tits subclass may or may not be able to use the primitives of the original class. \\n\\tIn general, if the instance variables read or written by a primitive have the \\n\\tsame meanings and are in the same fields in both classes, the primitive will \\n\\twork. \\n\\n\\tFor certain frequently used 'special selectors', the compiler emits a \\n\\tsend-special-selector bytecode instead of a send-message bytecode. \\n\\tSpecial selectors were created because they offer two advantages. Code \\n\\twhich sends special selectors compiles into fewer bytes than normal. For \\n\\tsome pairs of receiver classes and special selectors, the interpreter jumps \\n\\tdirectly to a primitive routine without looking up the method in the class. \\n\\tThis is much faster than a normal message lookup. \\n\\t \\n\\tA selector which is a special selector solely in order to save space has a \\n\\tnormal behavior. Methods whose selectors are special in order to \\n\\tgain speed contain the comment, 'No Lookup'. When the interpreter \\n\\tencounters a send-special-selector bytecode, it checks the class of the \\n\\treceiver and the selector. If the class-selector pair is a no-lookup pair, \\n\\tthen the interpreter swiftly jumps to the routine which implements the \\n\\tcorresponding primitive. (A special selector whose receiver is not of the \\n\\tright class to make a no-lookup pair, is looked up normally). The pairs are \\n\\tlisted below. No-lookup methods contain a primitive number specification, \\n\\t<primitive: xx>, which is redundant. Since the method is not normally looked \\n\\tup, deleting the primitive number specification cannot prevent this \\n\\tprimitive from running. If a no-lookup primitive fails, the method is looked \\n\\tup normally, and the expressions in it are executed. \\n\\t \\n\\tNo Lookup pairs of (class, selector) \\n\\t \\n\\tSmallInteger with any of\\t\\t+ - * / \\\\\\\\ bitOr: bitShift: bitAnd: // \\n\\tSmallInteger with any of\\t\\t= ~= > < >= <= \\n\\tAny class with\\t\\t\\t\\t\\t== \\n\\tAny class with \\t\\t\\t\\t\\t@ \\n\\tPoint with either of\\t\\t\\t\\tx y \\n\\tContextPart with\\t\\t\\t\\t\\tblockCopy: \\n\\tBlockContext with either of \\t\\tvalue value:\\n\\t\\\"\\n\\n\\tself error: 'comment only'! !\\n\\n!Object class methodsFor: 'documentation'!\\nwhatIsAPrimitive\\n\\t\\\"Some messages in the system are responded to primitively. A primitive \\n\\tresponse is performed directly by the interpreter rather than by evaluating \\n\\texpressions in a method. The methods for these messages indicate the \\n\\tpresence of a primitive response by including <primitive: xx> before the \\n\\tfirst expression in the method. \\n\\t \\n\\tPrimitives exist for several reasons. Certain basic or 'primitive' \\n\\toperations cannot be performed in any other way. Smalltalk without \\n\\tprimitives can move values from one variable to another, but cannot add two \\n\\tSmallIntegers together. Many methods for arithmetic and comparison \\n\\tbetween numbers are primitives. Some primitives allow Smalltalk to \\n\\tcommunicate with I/O devices such as the disk, the display, and the keyboard. \\n\\tSome primitives exist only to make the system run faster; each does the same \\n\\tthing as a certain Smalltalk method, and its implementation as a primitive is \\n\\toptional. \\n\\t \\n\\tWhen the Smalltalk interpreter begins to execute a method which specifies a \\n\\tprimitive response, it tries to perform the primitive action and to return a \\n\\tresult. If the routine in the interpreter for this primitive is successful, \\n\\tit will return a value and the expressions in the method will not be evaluated. \\n\\tIf the primitive routine is not successful, the primitive 'fails', and the \\n\\tSmalltalk expressions in the method are executed instead. These \\n\\texpressions are evaluated as though the primitive routine had not been \\n\\tcalled. \\n\\t \\n\\tThe Smalltalk code that is evaluated when a primitive fails usually \\n\\tanticipates why that primitive might fail. If the primitive is optional, the \\n\\texpressions in the method do exactly what the primitive would have done (See \\n\\tNumber @). If the primitive only works on certain classes of arguments, the \\n\\tSmalltalk code tries to coerce the argument or appeals to a superclass to find \\n\\ta more general way of doing the operation (see SmallInteger +). If the \\n\\tprimitive is never supposed to fail, the expressions signal an error (see \\n\\tSmallInteger asFloat). \\n\\t \\n\\tEach method that specifies a primitive has a comment in it. If the primitive is \\n\\toptional, the comment will say 'Optional'. An optional primitive that is not \\n\\timplemented always fails, and the Smalltalk expressions do the work \\n\\tinstead. \\n\\t \\n\\tIf a primitive is not optional, the comment will say, 'Essential'. Some \\n\\tmethods will have the comment, 'No Lookup'. See Object \\n\\thowToModifyPrimitives for an explanation of special selectors which are \\n\\tnot looked up. \\n\\t \\n\\tFor the primitives for +, -, *, and bitShift: in SmallInteger, and truncated \\n\\tin Float, the primitive constructs and returns a 16-bit \\n\\tLargePositiveInteger when the result warrants it. Returning 16-bit \\n\\tLargePositiveIntegers from these primitives instead of failing is \\n\\toptional in the same sense that the LargePositiveInteger arithmetic \\n\\tprimitives are optional. The comments in the SmallInteger primitives say, \\n\\t'Fails if result is not a SmallInteger', even though the implementor has the \\n\\toption to construct a LargePositiveInteger. For further information on \\n\\tprimitives, see the 'Primitive Methods' part of the chapter on the formal \\n\\tspecification of the interpreter in the Smalltalk book.\\\"\\n\\n\\tself error: 'comment only'! !\\n\\n\\n!Object class methodsFor: 'file list services' stamp: 'nk 6/12/2004 11:41'!\\nfileReaderServicesForDirectory: aFileDirectory\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n!Object class methodsFor: 'file list services' stamp: 'nk 6/12/2004 11:30'!\\nfileReaderServicesForFile: fullName suffix: suffix\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n!Object class methodsFor: 'file list services' stamp: 'md 2/15/2006 17:20'!\\nservices\\n\\t\\\"Backstop\\\"\\n\\t^#()! !\\n\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 1/23/2003 09:45'!\\ncategoryForUniclasses\\n\\n\\t\\\"Answer the default system category into which to place unique-class instances\\\"\\n\\n\\n\\n\\t^ 'UserObjects'! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'!\\nchooseUniqueClassName\\n\\t| i className |\\n\\ti _ 1.\\n\\t[className _ (self name , i printString) asSymbol.\\n\\t Smalltalk includesKey: className]\\n\\t\\twhileTrue: [i _ i + 1].\\n\\t^ className! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:22'!\\ninitialInstance\\n\\t\\\"Answer the first instance of the receiver, generate an error if there is one already\\\"\\n\\t\\\"self instanceCount > 0 ifTrue: [self error: 'instance(s) already exist.'].\\\"\\n\\t\\t\\\"Debugging test that is very slow\\\"\\n\\t^ self new! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 09:30'!\\ninitializedInstance\\n\\t^ self new! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 10/16/2000 10:58'!\\ninstanceOfUniqueClass\\n\\t\\\"Answer an instance of a unique subclass of the receiver\\\"\\n\\n\\t^ self instanceOfUniqueClassWithInstVarString: '' andClassInstVarString: ''! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:27'!\\ninstanceOfUniqueClassWithInstVarString: instVarString andClassInstVarString: classInstVarString\\n\\t\\\"Create a unique class for the receiver, and answer an instance of it\\\"\\n\\n\\t^ (self newUniqueClassInstVars: instVarString \\n\\t\\tclassInstVars: classInstVarString) initialInstance! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 10/23/1999 22:51'!\\nisUniClass\\n\\t^ false! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'ajh 5/23/2002 00:35'!\\nnewFrom: aSimilarObject\\n\\t\\\"Create an object that has similar contents to aSimilarObject.\\n\\tIf the classes have any instance varaibles with the same names, copy them across.\\n\\tIf this is bad for a class, override this method.\\\"\\n\\n\\t^ (self isVariable\\n\\t\\tifTrue: [self basicNew: aSimilarObject basicSize]\\n\\t\\tifFalse: [self basicNew]\\n\\t ) copySameFrom: aSimilarObject! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'tk 6/29/1998 12:11'!\\nnewUniqueClassInstVars: instVarString classInstVars: classInstVarString\\n\\t\\\"Create a unique class for the receiver\\\"\\n\\n\\t| aName aClass |\\n\\tself isSystemDefined ifFalse:\\n\\t\\t[^ superclass newUniqueClassInstVars: instVarString classInstVars: classInstVarString].\\n\\taName _ self chooseUniqueClassName.\\n\\taClass _ self subclass: aName instanceVariableNames: instVarString \\n\\t\\tclassVariableNames: '' poolDictionaries: '' category: self categoryForUniclasses.\\n\\tclassInstVarString size > 0 ifTrue:\\n\\t\\t[aClass class instanceVariableNames: classInstVarString].\\n\\t^ aClass! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'!\\nnewUserInstance\\n\\t\\\"Answer an instance of an appropriate class to serve as a user object in the containment hierarchy\\\"\\n\\n\\t^ self instanceOfUniqueClass! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'nk 8/30/2004 07:57'!\\nreadCarefullyFrom: textStringOrStream\\n\\t\\\"Create an object based on the contents of textStringOrStream. Return an error instead of putting up a SyntaxError window.\\\"\\n\\n\\t| object |\\n\\t(Compiler couldEvaluate: textStringOrStream)\\n\\t\\tifFalse: [^ self error: 'expected String, Stream, or Text'].\\n\\tobject _ Compiler evaluate: textStringOrStream for: nil \\n\\t\\t\\t\\tnotifying: #error: \\\"signal we want errors\\\" logged: false.\\n\\t(object isKindOf: self) ifFalse: [self error: self name, ' expected'].\\n\\t^object! !\\n\\n!Object class methodsFor: 'instance creation' stamp: 'nk 8/30/2004 07:57'!\\nreadFrom: textStringOrStream\\n\\t\\\"Create an object based on the contents of textStringOrStream.\\\"\\n\\n\\t| object |\\n\\t(Compiler couldEvaluate: textStringOrStream)\\n\\t\\tifFalse: [^ self error: 'expected String, Stream, or Text'].\\n\\tobject _ Compiler evaluate: textStringOrStream.\\n\\t(object isKindOf: self) ifFalse: [self error: self name, ' expected'].\\n\\t^object! !\\n\\n\\n!Object class methodsFor: 'objects from disk' stamp: 'tk 1/8/97'!\\ncreateFrom: aSmartRefStream size: varsOnDisk version: instVarList\\n\\t\\\"Create an instance of me so objects on the disk can be read in. Tricky part is computing the size if variable. Inst vars will be filled in later. \\\"\\n\\n\\t^ self isVariable\\n\\t\\tifFalse: [self basicNew]\\n\\t\\tifTrue: [\\\"instVarList is names of old class's inst vars plus a version number\\\" \\n\\t\\t\\t\\tself basicNew: (varsOnDisk - (instVarList size - 1))]\\n! !\\n\\n\\n!Object class methodsFor: 'window color' stamp: 'nk 6/10/2004 08:10'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference.\\n\\tThis is a backstop for classes that don't otherwise define a preference.\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name\\n\\t\\twording: 'Default' brightColor: #white\\n\\t\\tpastelColor: #white\\n\\t\\thelpMessage: 'Other windows without color preferences.'! !\\n\\n\\n!Object class methodsFor: 'private' stamp: 'mir 8/22/2001 15:20'!\\nreleaseExternalSettings\\n\\t\\\"Do nothing as a default\\\"! !\\nAbstractHierarchicalList subclass: #ObjectExplorer\\n\\tinstanceVariableNames: 'rootObject inspector monitorList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Explorer'!\\n!ObjectExplorer commentStamp: '<historical>' prior: 0!\\nObjectExplorer provides a hierarchical alternative to #inspect. Simply evaluate an expression like:\\n\\nWorld explore\\n\\nand enjoy.!\\n]style[(101 13 12)f1,f3cblue;,f1!\\n\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:11'!\\ncontentsSelection\\n\\t\\\"Return the interval of text in the code pane to select when I set the pane's contents\\\"\\n\\n\\t^ 1 to: 0 \\\"null selection\\\"! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:15'!\\ndoItContext\\n\\t\\\"Answer the context in which a text selection can be evaluated.\\\"\\n\\n\\t^nil! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:19'!\\ndoItReceiver\\n\\t\\\"Answer the object that should be informed of the result of evaluating a\\n\\ttext selection.\\\"\\n\\n\\tcurrentSelection ifNil: [^rootObject].\\n\\t^currentSelection withoutListWrapper\\n! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:27'!\\nexplorerFor: anObject\\n\\t| window listMorph |\\n\\trootObject := anObject.\\n\\twindow := (SystemWindow labelled: self label) model: self.\\n\\twindow addMorph: (listMorph := SimpleHierarchicalListMorph \\n\\t\\t\\ton: self\\n\\t\\t\\tlist: #getList\\n\\t\\t\\tselected: #getCurrentSelection\\n\\t\\t\\tchangeSelected: #noteNewSelection:\\n\\t\\t\\tmenu: #genericMenu:\\n\\t\\t\\tkeystroke: #explorerKey:from:)\\n\\t\\tframe: (0@0 corner: 1@0.8).\\n\\twindow addMorph: ((PluggableTextMorph on: self text: #trash accept: #trash:\\n\\t\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:)\\n\\t\\t\\t\\t\\taskBeforeDiscardingEdits: false)\\n\\t\\tframe: (0@0.8 corner: 1@1).\\n\\tlistMorph\\n\\t\\tautoDeselect: false.\\n ^ window! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:16'!\\ngetList\\n\\n\\t^Array with: (ObjectExplorerWrapper with: rootObject name: 'root' model: self parent: nil)\\n! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'hg 9/7/2001 12:12'!\\nlabel\\n\\n\\t^ rootObject printStringLimitedTo: 32! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:43'!\\nobject\\n\\t^currentSelection ifNotNilDo: [ :cs | cs withoutListWrapper ]! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 10:02'!\\nparentObject\\n\\tcurrentSelection ifNil: [ ^nil ].\\n\\tcurrentSelection parent ifNil: [ ^rootObject ].\\n\\t^currentSelection parent withoutListWrapper! !\\n\\n!ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:47'!\\nselector\\n\\t^currentSelection ifNotNilDo: [ :cs | cs selector ]! !\\n\\n\\n!ObjectExplorer methodsFor: 'error handling' stamp: 'nk 7/24/2003 09:29'!\\ndoesNotUnderstand: aMessage\\n\\tinspector ifNotNil: [ (inspector respondsTo: aMessage selector) ifTrue: [ ^inspector perform: aMessage selector withArguments: aMessage arguments ]].\\n\\t^super doesNotUnderstand: aMessage! !\\n\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nchasePointers\\n\\t\\\"Open a PointerFinder on the selected item\\\"\\n\\t| path sel savedRoot saved |\\n\\tpath := OrderedCollection new.\\n\\tsel := currentSelection.\\n\\t[ sel isNil ] whileFalse: [ path addFirst: sel asString. sel := sel parent ].\\n\\tpath addFirst: #openPath.\\n\\tpath := path asArray.\\n\\tsavedRoot := rootObject.\\n\\tsaved := self object.\\n\\t[ rootObject := nil.\\n\\tself changed: #getList.\\n\\t(Smalltalk includesKey: #PointerFinder)\\n\\t\\tifTrue: [PointerFinder on: saved]\\n\\t\\tifFalse: [self objectReferencesToSelection ]]\\n\\t\\tensure: [ rootObject := savedRoot.\\n\\t\\t\\tself changed: #getList.\\n\\t\\t\\tself changed: path.\\n\\t\\t]! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:22'!\\ncodePaneMenu: aMenu shifted: shifted\\n\\t\\\"Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items\\\"\\n\\t^ StringHolder basicNew codePaneMenu: aMenu shifted: shifted\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\ndefsOfSelection\\n\\t\\\"Open a browser on all defining references to the selected instance variable, if that's what's currently selected.\\\"\\n\\t| aClass sel |\\n\\n\\t(aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash].\\n\\tsel := self selector.\\n\\tself systemNavigation browseAllStoresInto: sel from: aClass! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nexplorerKey: aChar from: view\\n\\n\\t\\\"Similar to #genericMenu:...\\\"\\n\\t| insideObject parentObject |\\n\\tcurrentSelection ifNotNil: [\\n\\t\\tinsideObject := self object.\\n\\t\\tparentObject := self parentObject.\\n\\t\\tinspector ifNil: [inspector := Inspector new].\\n\\t\\tinspector\\n\\t\\t\\tinspect: parentObject;\\n\\t\\t\\tobject: insideObject.\\n\\n\\t\\taChar == $i ifTrue: [^ self inspectSelection].\\n\\t\\taChar == $I ifTrue: [^ self exploreSelection].\\n\\n\\t\\taChar == $b ifTrue:\\t[^ inspector browseMethodFull].\\n\\t\\taChar == $h ifTrue:\\t[^ inspector classHierarchy].\\n\\t\\taChar == $c ifTrue: [^ inspector copyName].\\n\\t\\taChar == $p ifTrue: [^ inspector browseFullProtocol].\\n\\t\\taChar == $N ifTrue: [^ inspector browseClassRefs].\\n\\t\\taChar == $t ifTrue: [^ inspector tearOffTile].\\n\\t\\taChar == $v ifTrue: [^ inspector viewerForValue]].\\n\\n\\t^ self arrowKey: aChar from: view! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'!\\nexploreSelection\\n\\t\\\"Open an ObjectExplorer on the current selection\\\"\\n\\tself object explore! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\ngenericMenu: aMenu \\n\\t\\\"Borrow a menu from my inspector\\\"\\n\\t| insideObject menu parentObject |\\n\\tcurrentSelection\\n\\t\\tifNil: [menu := aMenu.\\n\\t\\t\\tmenu\\n\\t\\t\\t\\tadd: '*nothing selected*'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #yourself]\\n\\t\\tifNotNil: [insideObject := self object.\\n\\t\\t\\tparentObject := self parentObject.\\n\\t\\t\\tinspector\\n\\t\\t\\t\\tifNil: [inspector := Inspector new].\\n\\t\\t\\tinspector inspect: parentObject;\\n\\t\\t\\t\\t object: insideObject.\\n\\t\\t\\taMenu defaultTarget: inspector.\\n\\t\\t\\tinspector fieldListMenu: aMenu.\\n\\t\\t\\taMenu items\\n\\t\\t\\t\\tdo: [:i | (#(#inspectSelection #exploreSelection #referencesToSelection #defsOfSelection #objectReferencesToSelection #chasePointers ) includes: i selector)\\n\\t\\t\\t\\t\\t\\tifTrue: [i target: self]].\\n\\t\\t\\taMenu addLine;\\n\\t\\t\\t\\tadd: 'monitor changes'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #monitor:\\n\\t\\t\\t\\targument: currentSelection].\\n\\tmonitorList isEmptyOrNil\\n\\t\\tifFalse: [aMenu addLine;\\n\\t\\t\\t\\tadd: 'stop monitoring all'\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tselector: #stopMonitoring].\\n\\t^ aMenu! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'!\\ninspectSelection\\n\\t\\\"Open an Inspector on the current selection\\\"\\n\\tself object inspect! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:00'!\\nobjectReferencesToSelection\\n\\t\\\"Open a browser on all references to the selected instance variable, if that's what currently selected. \\\"\\n\\tself systemNavigation\\n\\t\\tbrowseAllObjectReferencesTo: self object\\n\\t\\texcept: (Array with: self parentObject with: currentSelection with: inspector)\\n\\t\\tifNone: [:obj | self changed: #flash].\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'!\\nreferencesToSelection\\n\\t\\\"Open a browser on all references to the selected instance variable, if that's what's currently selected.\\\"\\n\\t| aClass sel |\\n\\n\\t(aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash].\\n\\tsel := self selector.\\n\\tself systemNavigation browseAllAccessesTo: sel from: aClass! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:19'!\\nselectedClass\\n\\t\\\"Answer the class of the receiver's current selection\\\"\\n\\n\\t^self doItReceiver class\\n! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'!\\ntrash\\n\\t\\\"What goes in the bottom pane\\\"\\n\\t^ ''! !\\n\\n!ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'!\\ntrash: newText\\n\\t\\\"Don't save it\\\"\\n\\t^ true! !\\n\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nmonitorList\\n\\t^monitorList ifNil: [ monitorList := WeakIdentityKeyDictionary new ].! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:02'!\\nmonitor: anObjectExplorerWrapper\\n\\t\\\"Start stepping and watching the given wrapper for changes.\\\"\\n\\tanObjectExplorerWrapper ifNil: [ ^self ].\\n\\tself world ifNil: [ ^self ].\\n\\tself monitorList at: anObjectExplorerWrapper put: anObjectExplorerWrapper asString.\\n\\tself world startStepping: self at: Time millisecondClockValue selector: #step arguments: #() stepTime: 200.! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:01'!\\nrelease\\n\\tself world ifNotNil: [ self world stopStepping: self selector: #step ].\\n\\tsuper release.! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/12/2003 17:55'!\\nshouldGetStepsFrom: aWorld\\n\\t^self monitorList notEmpty! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nstep\\n\\t\\\"If there's anything in my monitor list, see if the strings have changed.\\\"\\n\\t| string changes |\\n\\tchanges := false.\\n\\tself monitorList keysAndValuesDo: [ :k :v |\\n\\t\\tk ifNotNil: [\\n\\t\\t\\tk refresh.\\n\\t\\t\\t(string := k asString) ~= v ifTrue: [ self monitorList at: k put: string. changes := true ].\\n\\t\\t]\\n\\t].\\n\\tchanges ifTrue: [ | sel |\\n\\t\\tsel := currentSelection.\\n\\t\\tself changed: #getList.\\n\\t\\tself noteNewSelection: sel.\\n\\t].\\n\\tself monitorList isEmpty ifTrue: [ ActiveWorld stopStepping: self selector: #step ].! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'!\\nstopMonitoring\\n\\tmonitorList := nil.\\n\\tself world stopStepping: self selector: #step! !\\n\\n!ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/31/2004 15:01'!\\nworld\\n\\t^ActiveWorld! !\\n\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'stephaneducasse 9/17/2005 21:50'!\\nexplorerFor: anObject withLabel: label \\n\\t| window listMorph |\\n\\trootObject := anObject.\\n\\twindow := (SystemWindow labelled: label) \\n\\t\\t\\t\\tmodel: self.\\n\\twindow\\n\\t\\taddMorph: (listMorph := SimpleHierarchicalListMorph\\n\\t\\t\\t\\t\\t\\ton: self\\n\\t\\t\\t\\t\\t\\tlist: #getList\\n\\t\\t\\t\\t\\t\\tselected: #getCurrentSelection\\n\\t\\t\\t\\t\\t\\tchangeSelected: #noteNewSelection:\\n\\t\\t\\t\\t\\t\\tmenu: #genericMenu:\\n\\t\\t\\t\\t\\t\\tkeystroke: nil)\\n\\t\\tframe: (0 @ 0 corner: 1 @ 0.8).\\n\\twindow\\n\\t\\taddMorph: ((PluggableTextMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\ttext: #trash\\n\\t\\t\\t\\taccept: #trash:\\n\\t\\t\\t\\treadSelection: #contentsSelection\\n\\t\\t\\t\\tmenu: #codePaneMenu:shifted:)\\n\\t\\t\\t\\taskBeforeDiscardingEdits: false)\\n\\t\\tframe: (0 @ 0.8 corner: 1 @ 1).\\n\\tlistMorph autoDeselect: false.\\n\\t^ window! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:23'!\\ninitialExtent\\n\\n\\t^300@500! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:31'!\\nopenBrowser: aClass\\n\\n\\tToolSet browse: aClass selector: nil! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:24'!\\nopenExplorerFor: anObject\\n\\\"\\nObjectExplorer new openExplorerFor: Smalltalk\\n\\\"\\n\\n (self explorerFor: anObject) openInWorld.\\n ^ self\\n! !\\n\\n!ObjectExplorer methodsFor: 'user interface' stamp: 'stephaneducasse 9/17/2005 21:51'!\\nopenExplorerFor: anObject withLabel: label \\n \\\"ObjectExplorer new openExplorerFor: Smalltalk withLabel: 'Smalltalk'\\\"\\n\\n\\t(self explorerFor: anObject withLabel: label)\\nopenInWorld! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectExplorer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectExplorer class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:55'!\\nabout\\n\\n\\tStringHolder new textContents: self comment; openLabel: 'about ',self asString! !\\nListItemWrapper subclass: #ObjectExplorerWrapper\\n\\tinstanceVariableNames: 'itemName parent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!ObjectExplorerWrapper commentStamp: '<historical>' prior: 0!\\nContributed by Bob Arning as part of the ObjectExplorer package.\\n!\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:48'!\\ncanBeDragged\\n\\n\\t^false! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nparent\\n\\t^parent! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nparent: anObject\\n\\tparent _ anObject! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:49'!\\nselector\\n\\tparent ifNil: [ ^nil ].\\n\\t^(parent withoutListWrapper class allInstVarNames includes: itemName) ifTrue: [ itemName asSymbol ]! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:49'!\\nsetItem: anObject name: aString model: aModel\\n\\n\\titem _ anObject.\\n\\tmodel _ aModel.\\n\\titemName _ aString.! !\\n\\n!ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'!\\nsetItem: anObject name: aString model: aModel parent: itemParent\\n\\tparent _ itemParent.\\n\\tself setItem: anObject name: aString model: aModel! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'converting' stamp: 'edt 5/26/2003 12:36'!\\nasString\\n\\t| explorerString string |\\n\\texplorerString _ \\n\\t\\t[item asExplorerString]\\n\\t\\t\\ton: Error \\n\\t\\t\\tdo: ['<error: ', item class name, ' in asExplorerString: evaluate \\\"' , itemName , ' asExplorerString\\\" to debug>'].\\n\\tstring _ (itemName ifNotNil: [itemName , ': '] ifNil: ['']) , explorerString.\\n\\t(string includes: Character cr)\\n\\t\\tifTrue: [^ string withSeparatorsCompacted].\\n\\t^ string! !\\n\\n!ObjectExplorerWrapper methodsFor: 'converting' stamp: 'nk 7/24/2003 10:16'!\\nitemName\\n\\t^itemName! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'monitoring' stamp: 'nk 7/12/2003 18:28'!\\nrefresh\\n\\t\\\"hack to refresh item given an object and a string that is either an index or an instance variable name.\\\"\\n\\t[ | index |\\n\\t\\t(model class allInstVarNames includes: itemName)\\n\\t\\t\\tifTrue: [ item _ model instVarNamed: itemName ]\\n\\t\\t\\tifFalse: [ index _ itemName asNumber.\\n\\t\\t\\t\\t(index between: 1 and: model basicSize) ifTrue: [ item _ model basicAt: index]]\\n\\t] on: Error do: [ :ex | item _ nil ]! !\\n\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:17'!\\ncontents\\n\\n\\t(item respondsTo: #explorerContents) ifTrue: [^item explorerContents].\\n\\t\\\"For all others, show named vars first, then indexed vars\\\"\\n\\t^(item class allInstVarNames asOrderedCollection withIndexCollect: [:each :index |\\n\\t\\tself class\\n\\t\\t\\twith: (item instVarAt: index)\\n\\t\\t\\tname: each\\n\\t\\t\\tmodel: item\\n\\t\\t\\tparent: self]) ,\\n\\t((1 to: item basicSize) collect: [:index |\\n\\t\\tself class\\n\\t\\t\\twith: (item basicAt: index)\\n\\t\\t\\tname: index printString\\n\\t\\t\\tmodel: item\\n\\t\\t\\tparent: self])! !\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'RAA 6/21/1999 11:27'!\\nhasContents\\n\\n\\t^item hasContentsInExplorer\\n\\t\\n! !\\n\\n!ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:34'!\\nicon\\n\\t\\\"Answer a form to be used as icon\\\"\\n\\t^ Preferences visualExplorer\\n\\t\\tifTrue: [item iconOrThumbnailOfSize: 16]\\n\\t\\tifFalse: [nil]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectExplorerWrapper class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:50'!\\nwith: anObject name: aString model: aModel\\n\\n\\t^self new \\n\\t\\tsetItem: anObject name: aString model: aModel! !\\n\\n!ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:16'!\\nwith: anObject name: aString model: aModel parent: aParent\\n\\n\\t^self new \\n\\t\\tsetItem: anObject name: aString model: aModel parent: aParent\\n! !\\nObject subclass: #ObjectFinalizer\\n\\tinstanceVariableNames: 'receiver selector arguments'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Finalization'!\\n\\n!ObjectFinalizer methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:13'!\\nfinalize\\n\\t\\\"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority.\\\"\\n\\t[receiver perform: selector withArguments: arguments] \\n\\t\\ton: Error do:[:ex| ex return].\\n! !\\n\\n\\n!ObjectFinalizer methodsFor: 'initialize' stamp: 'ar 5/19/2003 20:12'!\\nreceiver: aReceiver selector: aSelector argument: anObject\\n\\treceiver := aReceiver.\\n\\tselector := aSelector.\\n\\targuments := Array with: anObject! !\\nTestCase subclass: #ObjectFinalizerTests\\n\\tinstanceVariableNames: 'log'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Finalization'!\\n\\n!ObjectFinalizerTests methodsFor: 'finalization handling' stamp: 'apb 9/14/2005 08:33'!\\nfinalize: anObject\\n\\tlog addLast: anObject asString, ' ', 'finalized'.! !\\n\\n\\n!ObjectFinalizerTests methodsFor: 'running' stamp: 'apb 9/14/2005 08:39'!\\nsetUp\\n\\tsuper setUp.\\n\\tlog := OrderedCollection new.! !\\n\\n\\n!ObjectFinalizerTests methodsFor: 'tests' stamp: 'stephaneducasse 10/28/2005 21:15'!\\ntestFinalization\\n\\t\\\"self run: #testFinalization\\\"\\n\\t\\n\\t| repetitions |\\n\\trepetitions := 100.\\n\\t1 to: repetitions\\n\\t\\tdo: [:i | \\n\\t\\t\\tlog addLast: 'o' , i asString , ' created'.\\n\\t\\t\\tObject new\\n\\t\\t\\t\\ttoFinalizeSend: #finalize:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twith: 'o' , i asString].\\n\\tSmalltalk garbageCollect.\\n\\tself finalizationRegistry finalizeValues.\\n\\t1 to: repetitions\\n\\t\\tdo: [:i | \\n\\t\\t\\tself assert: (log includes: 'o' , i asString , ' created').\\n\\t\\t\\tself assert: (log includes: 'o' , i asString , ' finalized')]! !\\n\\n!ObjectFinalizerTests methodsFor: 'tests' stamp: 'stephaneducasse 10/28/2005 21:15'!\\ntestFinalizationOfEquals\\n\\t\\\"self run: #testFinalizationOfEquals\\\"\\n\\t\\n\\t| bag o |\\n\\tbag := IdentityBag new.\\n\\t1 to: 5 do: [:n | o := n asString copy. bag add: n. o toFinalizeSend: #remove: to: bag with: n].\\n\\t1 to: 5 do: [:n | o := n asString copy. bag add: n. o toFinalizeSend: #remove: to: bag with: n].\\n\\tSmalltalk garbageCollect.\\n\\t1 to: 5 do: [:n | self deny: (bag includes: n)]\\n! !\\nProtoObject subclass: #ObjectOut\\n\\tinstanceVariableNames: 'url page recursionFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!ObjectOut commentStamp: '<historical>' prior: 0!\\nI am a stand-in for an object that is out on the disk. The object that is out on the disk is the head of a tree of objects that are out. See SqueakPage.\\n\\nWhen any message is sent to me, I don't understand it, and bring in my true object. I become myself with the objects and resend the message. \\n\\nI may not represent the object nil. \\nThe file is represented as a url, and that url may point at any file on the net. \\n\\npage is a SqueakPage.\\nIf the cache already has an object, widely in use, that claims to be the object for my url, what do I do? I can't become him, since others believe that he is the true object. Run through memory and replace refs to me with refs to him. Be careful not to trigger a fault. Become me to a string, then find pointers and replace?\\n\\n[[[They don't want to end up holding an ObjectOut. (would oscillate back and forth) This is a problem. A user could bring in two trees that both refer to a 3rd url. (check with cache before installing any new ObjectOut) Two trees could be written to the same url.\\nOr, I remain an ObjectOut, and keep getting notUnderstood, and keep returning the other guy.\\nOr I smash the cache, and install MY page and object. Other guy is a copy -- still in, but with no place in the cache. When we both write to the same url, there will be trouble.] No -- search and replace.]]]\\n!\\n\\n\\n!ObjectOut methodsFor: 'access' stamp: 'tk 1/15/1999 11:43'!\\nurl: aString\\n\\n\\turl _ aString! !\\n\\n!ObjectOut methodsFor: 'access' stamp: 'tk 12/18/1998 21:29'!\\nxxxReset\\n\\t\\\"mark as never brought in\\\"\\n\\trecursionFlag _ nil! !\\n\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/30/1998 15:11'!\\nisInMemory\\n\\t\\\"We are a place holder for an object that is out.\\\"\\n\\t^ false! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/21/1998 12:28'!\\nxxxClass\\n\\t\\\"Primitive. Answer the object which is the receiver's class. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 111>\\n\\tself primitiveFailed! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 15:31'!\\nxxxClone\\n\\n\\t<primitive: 148>\\n\\tself primitiveFailed! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 15:19'!\\nxxxInstVarAt: index \\n\\t\\\"Primitive. Answer a fixed variable in an object. The numbering of the \\n\\tvariables corresponds to the named instance variables. Fail if the index \\n\\tis not an Integer or is not the index of a fixed variable. Essential. See \\n\\tObject documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 73>\\n\\tself primitiveFailed ! !\\n\\n!ObjectOut methodsFor: 'basics' stamp: 'tk 10/22/1998 14:39'!\\nxxxInstVarAt: anInteger put: anObject \\n\\t\\\"Primitive. Store a value into a fixed variable in the receiver. The \\n\\tnumbering of the variables corresponds to the named instance variables. \\n\\tFail if the index is not an Integer or is not the index of a fixed variable. \\n\\tAnswer the value stored as the result. Using this message violates the \\n\\tprinciple that each object has sovereign control over the storing of \\n\\tvalues into its instance variables. Essential. See Object documentation \\n\\twhatIsAPrimitive.\\\"\\n\\n\\t<primitive: 74>\\n\\tself primitiveFailed ! !\\n\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'rbb 2/18/2005 14:55'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Bring in the object, install, then resend aMessage\\\"\\n\\t| realObject oldFlag response |\\n\\toldFlag _ recursionFlag.\\n\\trecursionFlag _ true.\\n\\t\\\"fetch the object\\\"\\n\\trealObject _ self xxxFetch.\\t\\t\\\"watch out for the become!!\\\"\\n\\t\\t\\t\\\"Now we ARE the realObject\\\"\\n\\toldFlag == true ifTrue: [\\n\\t\\tresponse _ (UIManager default chooseFrom: #('proceed normally' 'debug')\\n\\t\\t\\ttitle: 'Object being fetched for a second time.\\nShould not happen, and needs to be fixed later.').\\n\\t\\tresponse = 2 ifTrue: [self halt]].\\t\\\"We are already the new object\\\"\\n\\n\\t\\\"Can't be a super message, since this is the first message sent to this object\\\"\\n\\t^ realObject perform: aMessage selector withArguments: aMessage arguments! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'tk 11/16/1998 09:57'!\\nxxxFetch\\n\\t\\\"Bring in my object and replace all references to me with references to him. First try looking up my url in the pageCache. Then try the page (and install it, under its url). Then start from scratch with the url.\\\"\\n\\n\\t| truePage object existing |\\n\\texisting _ SqueakPageCache pageCache at: url ifAbsent: [nil].\\n\\texisting ifNotNil: [existing isContentsInMemory\\n\\t\\tifTrue: [page _ truePage _ existing]].\\t\\\"This url already has an object in this image\\\"\\n\\ttruePage ifNil: [\\n\\t\\ttruePage _ SqueakPageCache atURL: url oldPage: page].\\n\\tobject _ truePage isContentsInMemory \\n\\t\\tifTrue: [truePage contentsMorph]\\n\\t\\tifFalse: [truePage fetchInformIfError].\\t\\\"contents, not the page\\\"\\n\\t\\t\\t\\\"Later, collect pointers to object and fix them up. Not scan memory\\\"\\n\\tobject ifNil: [^ 'Object could not be fetched.'].\\n\\t\\\"recursionFlag _ false.\\\" \\t\\\"while I still have a pointer to myself\\\"\\n\\ttruePage contentsMorph: object.\\n\\tpage _ truePage.\\n\\tself xxxFixup.\\n\\t^ object\\t\\\"the final object!!\\\"\\n ! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'ar 9/27/2005 18:03'!\\nxxxFixup\\n\\t\\\"There is already an object in memory for my url. All pointers to me need to be pointers to him. Can't use become, because other pointers to him must stay valid.\\\"\\n\\n\\t| real temp list |\\n\\treal := page contentsMorph.\\n\\treal == self ifTrue: [page error: 'should be converted by now'].\\n\\ttemp := self.\\n\\tlist := (Utilities pointersTo: temp) asOrderedCollection.\\n\\tlist add: thisContext. list add: thisContext sender.\\n\\tlist do: [:holder |\\n\\t\\t1 to: holder class instSize do:\\n\\t\\t\\t[:i | (holder instVarAt: i) == temp ifTrue: [holder instVarAt: i put: real]].\\n\\t\\t1 to: holder basicSize do:\\n\\t\\t\\t[:i | (holder basicAt: i) == temp ifTrue: [holder basicAt: i put: real]].\\n\\t\\t].\\n\\t^ real! !\\n\\n!ObjectOut methodsFor: 'fetch from disk' stamp: 'tk 10/21/1998 13:01'!\\nxxxSetUrl: aString page: aSqkPage\\n\\n\\turl _ aString.\\n\\tpage _ aSqkPage.! !\\n\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 2/17/2000 22:21'!\\ncomeFullyUpOnReload: smartRefStream\\n\\t\\\"Normally this read-in object is exactly what we want to store. Try to dock first. If it is here already, use that one.\\\"\\n\\n\\t| sp |\\n\\t\\\"Transcript show: 'has ref to: ', url; cr.\\\"\\n\\t(sp _ SqueakPageCache pageCache at: page ifAbsent: [nil]) ifNotNil: [\\n\\t\\tsp isContentsInMemory ifTrue: [^ sp contentsMorph]].\\n\\t^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 2/24/1999 11:14'!\\nobjectForDataStream: refStrm\\n \\\"Return an object to store on a data stream (externalize myself).\\\"\\n\\n ^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 14:37'!\\nreadDataFrom: aDataStream size: varsOnDisk\\n\\t\\\"Make self be an object based on the contents of aDataStream, which was generated by the object's storeDataOn: method. Return self.\\\"\\n\\t| cntInstVars |\\n\\tcntInstVars _ self xxxClass instSize.\\n\\tself xxxClass isVariable\\n\\t\\tifTrue: [self xxxClass error: 'needs updating']\\t\\\"assume no variable subclasses\\\"\\n\\t\\tifFalse: [cntInstVars _ varsOnDisk].\\n\\n\\taDataStream beginReference: self.\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | self xxxInstVarAt: i put: aDataStream next].\\n\\\"\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | self basicAt: i put: aDataStream next].\\n\\\"\\n\\t^ self! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 15:18'!\\nstoreDataOn: aDataStream\\n\\t\\\"Store myself on a DataStream. See also objectToStoreOnDataStream.\\n\\tmust send 'aDataStream beginInstance:size:'\\\"\\n\\t| cntInstVars |\\n\\n\\tcntInstVars _ self class instSize.\\n\\t\\\"cntIndexedVars _ self basicSize.\\\"\\n\\taDataStream\\n\\t\\tbeginInstance: self xxxClass\\n\\t\\tsize: cntInstVars \\\"+ cntIndexedVars\\\".\\n\\t1 to: cntInstVars do:\\n\\t\\t[:i | aDataStream nextPut: (self xxxInstVarAt: i)].\\n\\\"\\t1 to: cntIndexedVars do:\\n\\t\\t[:i | aDataStream nextPut: (self basicAt: i)]\\n\\\"! !\\n\\n!ObjectOut methodsFor: 'object storage' stamp: 'tk 10/22/1998 15:29'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. Some classes refuse to be copied. Some classes are picky about which fields get deep copied.\\\"\\n\\t| class index sub subAss new absent |\\n\\tnew _ deepCopier references at: self ifAbsent: [absent _ true].\\n\\tabsent ifNil: [^ new].\\t\\\"already done\\\"\\n\\tclass _ self xxxClass.\\n\\tclass isMeta ifTrue: [^ self].\\t\\t\\\"a class\\\"\\n\\tnew _ self xxxClone.\\n\\t\\\"not a uniClass\\\"\\n\\tdeepCopier references at: self put: new.\\t\\\"remember\\\"\\n\\t\\\"class is not variable\\\"\\n\\tindex _ class instSize.\\n\\t[index > 0] whileTrue: \\n\\t\\t[sub _ self xxxInstVarAt: index.\\n\\t\\t(subAss _ deepCopier references associationAt: sub ifAbsent: [nil])\\n\\t\\t\\tifNil: [new xxxInstVarAt: index put: (sub veryDeepCopyWith: deepCopier)]\\n\\t\\t\\tifNotNil: [new xxxInstVarAt: index put: subAss value].\\n\\t\\tindex _ index - 1].\\n\\tnew rehash.\\t\\\"force Sets and Dictionaries to rehash\\\"\\n\\t^ new\\n! !\\n\\n\\n!ObjectOut methodsFor: '*MorphicExtras-access' stamp: 'tk 12/4/1998 13:01'!\\nsqkPage\\n\\t^ page! !\\n\\n!ObjectOut methodsFor: '*MorphicExtras-access' stamp: 'tk 12/4/1998 13:01'!\\nurl\\n\\t^ url! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectOut class\\n\\tinstanceVariableNames: ''!\\nGenericPropertiesMorph subclass: #ObjectPropertiesMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Experimental'!\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\nadjustTargetBorderWidth: aFractionalPoint\\n\\n\\t| n |\\n\\n\\tmyTarget borderWidth: (n _ (aFractionalPoint x * 10) rounded max: 0).\\n\\tself showSliderFeedback: n.! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\nadjustTargetGradientDirection: aFractionalPoint\\n\\n\\t| fs p |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs direction: (p _ (aFractionalPoint * myTarget extent) rounded).\\n\\tself showSliderFeedback: p.\\n\\tmyTarget changed.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:05'!\\nadjustTargetGradientOrigin: aFractionalPoint\\n\\n\\t| fs p |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs origin: (p _ myTarget topLeft + (aFractionalPoint * myTarget extent) rounded).\\n\\tself showSliderFeedback: p.\\n\\tmyTarget changed.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\nadjustTargetShadowOffset: aFractionalPoint\\n\\n\\t| n |\\n\\n\\tmyTarget changed; layoutChanged.\\n\\tmyTarget shadowOffset: (n _ (aFractionalPoint * 4) rounded).\\n\\tself showSliderFeedback: n.\\n\\tmyTarget changed; layoutChanged.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ndoEnables\\n\\n\\t| itsName fs |\\n\\n\\tfs _ myTarget fillStyle.\\n\\tself allMorphsDo: [ :each |\\n\\t\\titsName _ each knownName.\\n\\t\\titsName == #pickerForColor ifTrue: [\\n\\t\\t\\tself enable: each when: fs isSolidFill | fs isGradientFill\\n\\t\\t].\\n\\t\\titsName == #pickerForBorderColor ifTrue: [\\n\\t\\t\\tself enable: each when: (myTarget respondsTo: #borderColor:)\\n\\t\\t].\\n\\t\\titsName == #pickerForShadowColor ifTrue: [\\n\\t\\t\\tself enable: each when: myTarget hasDropShadow\\n\\t\\t].\\n\\t\\titsName == #pickerFor2ndGradientColor ifTrue: [\\n\\t\\t\\tself enable: each when: fs isGradientFill\\n\\t\\t].\\n\\t].\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\nmakeTargetGradientFill\\n\\n\\tmyTarget useGradientFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\nmakeTargetSolidFill\\n\\n\\tmyTarget useSolidFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\nnumberOneColor\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^myTarget color].\\n\\t^myTarget fillStyle colorRamp first value\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'gm 2/16/2003 20:36'!\\nnumberOneColor: aColor \\n\\tmyTarget fillStyle isGradientFill \\n\\t\\tifFalse: \\n\\t\\t\\t[^(myTarget isSystemWindow) \\n\\t\\t\\t\\tifTrue: [myTarget setWindowColor: aColor]\\n\\t\\t\\t\\tifFalse: [myTarget fillStyle: aColor]].\\n\\tmyTarget fillStyle \\n\\t\\tfirstColor: aColor\\n\\t\\tforMorph: myTarget\\n\\t\\thand: nil! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'dgd 10/8/2003 19:35'!\\nrebuild\\n\\n\\tself removeAllMorphs.\\n\\tself addARow: {\\n\\t\\tself lockedString: ('Properties for {1}' translated format: {myTarget name}).\\n\\t}.\\n\\tself addARow: {\\n\\t\\tself inAColumn: {\\n\\t\\t\\tself paneForCornerRoundingToggle.\\n\\t\\t\\tself paneForStickinessToggle.\\n\\t\\t\\tself paneForLockedToggle.\\n\\t\\t}.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself paneForMainColorPicker.\\n\\t\\tself paneFor2ndGradientColorPicker.\\n\\t}.\\n\\tself addARow: {\\n\\t\\tself paneForBorderColorPicker.\\n\\t\\tself paneForShadowColorPicker.\\n\\t}.\\n\\n\\tself addARow: {\\n\\t\\tself \\n\\t\\t\\tbuttonNamed: 'Accept' translated action: #doAccept color: color lighter \\n\\t\\t\\thelp: 'keep changes made and close panel' translated.\\n\\t\\tself \\n\\t\\t\\tbuttonNamed: 'Cancel' translated action: #doCancel color: color lighter \\n\\t\\t\\thelp: 'cancel changes made and close panel' translated.\\n\\t}, self rebuildOptionalButtons.\\n\\n\\tthingsToRevert _ Dictionary new.\\n\\t\\\"thingsToRevert at: #fillStyle: put: myTarget fillStyle.\\\"\\n\\tmyTarget isSystemWindow ifTrue: [\\n\\t\\tthingsToRevert at: #setWindowColor: put: myTarget paneColorToUse\\n\\t].\\n\\tthingsToRevert at: #hasDropShadow: put: myTarget hasDropShadow.\\n\\tthingsToRevert at: #shadowColor: put: myTarget shadowColor.\\n\\t(myTarget respondsTo: #borderColor:) ifTrue: [\\n\\t\\tthingsToRevert at: #borderColor: put: myTarget borderColor.\\n\\t].\\n\\n\\tthingsToRevert at: #borderWidth: put: myTarget borderWidth.\\n\\tthingsToRevert at: #cornerStyle: put: myTarget cornerStyle.\\n\\tthingsToRevert at: #sticky: put: myTarget isSticky.\\n\\tthingsToRevert at: #lock: put: myTarget isLocked.\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'wiz 9/21/2005 22:42'!\\nrebuildOptionalButtons\\n\\n\\t| answer |\\n\\n\\tanswer _ #() .\\n\\t\\n\\tmyTarget isTextMorph ifTrue: [\\n\\t\\tanswer _ answer, {\\n\\t\\t\\tself \\n\\t\\t\\t\\tbuttonNamed: 'Text' translated action: #doTextProperties color: color lighter \\n\\t\\t\\t\\thelp: 'open a text properties panel for the morph' translated.\\n\\t\\t}.\\n\\t].\\n\\t^answer! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'ar 8/25/2001 18:30'!\\ntargetBorderColor\\n\\t^myTarget borderStyle baseColor! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/26/2001 15:29'!\\ntargetBorderColor: aColor\\n\\t\\\"Need to replace the borderStyle or BorderedMorph will not 'feel' the change\\\"\\n\\tmyTarget borderStyle: (myTarget borderStyle copy baseColor: aColor).! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:04'!\\ntargetHasGradientFill\\n\\n\\t^myTarget fillStyle isGradientFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:01'!\\ntargetHasSolidFill\\n\\n\\t^myTarget fillStyle isSolidFill! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntargetRadial\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^false].\\n\\t^myTarget fillStyle radial! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntgt2ndGradientColor\\n\\n\\tmyTarget fillStyle isGradientFill ifFalse: [^Color black].\\n\\t^myTarget fillStyle colorRamp last value! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:03'!\\ntgt2ndGradientColor: aColor\\n\\n\\tmyTarget fillStyle lastColor: aColor forMorph: myTarget hand: nil\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 2/20/2001 17:45'!\\ntoggleTargetGradientFill\\n\\n\\tself targetHasGradientFill ifTrue: [\\n\\t\\tself makeTargetSolidFill\\n\\t] ifFalse: [\\n\\t\\tself makeTargetGradientFill\\n\\t].\\n\\tself doEnables! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 3/8/2001 18:02'!\\ntoggleTargetRadial\\n\\n\\t| fs |\\n\\n\\t(fs _ myTarget fillStyle) isGradientFill ifFalse: [^self].\\n\\tfs radial: fs radial not.\\n\\tmyTarget changed.\\n\\tself doEnables.! !\\n\\n!ObjectPropertiesMorph methodsFor: 'as yet unclassified' stamp: 'RAA 2/20/2001 17:48'!\\ntoggleTargetSolidFill\\n\\n\\tself targetHasSolidFill ifTrue: [\\n\\t\\tself makeTargetGradientFill\\n\\t] ifFalse: [\\n\\t\\tself makeTargetSolidFill\\n\\t].\\n\\tself doEnables! !\\n\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ndefaultBorderColor\\n\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ self defaultColor darker! !\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 0.548\\n\\t\\tg: 0.839\\n\\t\\tb: 0.452! !\\n\\n!ObjectPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:44'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tmyTarget\\n\\t\\tifNil: [myTarget _ RectangleMorph new openInWorld].\\n\\tself rebuild! !\\n\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'sd 11/13/2003 21:03'!\\nborderPrototype: aBorderStyle help: helpString\\n\\t| selector proto |\\n\\tselector _ BorderedMorph new.\\n\\tselector borderWidth: 0.\\n\\tselector color: Color transparent.\\n\\tproto _ Morph new extent: 16@16.\\n\\tproto color: Color transparent.\\n\\tproto borderStyle: aBorderStyle.\\n\\tselector extent: proto extent + 4.\\n\\tselector addMorphCentered: proto.\\n\\t(myTarget canDrawBorder: aBorderStyle) ifTrue:[\\n\\t\\tselector setBalloonText: helpString.\\n\\t\\tselector on: #mouseDown send: #toggleBorderStyle:with:from: to: self withValue: proto.\\n\\t\\t(myTarget borderStyle species == aBorderStyle species and:[\\n\\t\\t\\tmyTarget borderStyle style == aBorderStyle style]) ifTrue:[selector borderWidth: 1].\\n\\t] ifFalse:[\\n\\t\\tselector setBalloonText: 'This border style cannot be used here' translated.\\n\\t\\tselector on: #mouseDown send: #beep to: Beeper.\\n\\t\\tselector addMorphCentered: ((Morph new) color: (Color black alpha: 0.5); extent: selector extent).\\n\\t].\\n\\t^selector! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneFor2ndGradientColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\t(self inAColumn: {\\n\\t\\t\\t\\tself colorPickerFor: self getter: #tgt2ndGradientColor setter: #tgt2ndGradientColor:.\\n\\t\\t\\t\\tself lockedString: '2nd gradient color' translated.\\n\\t\\t\\t\\tself paneForRadialGradientToggle hResizing: #shrinkWrap.\\n\\t\\t\\t\\t(\\n\\t\\t\\t\\t\\tself inARow: {self paneForGradientOrigin. self paneForGradientDirection}\\n\\t\\t\\t\\t) hResizing: #shrinkWrap.\\n\\t\\t\\t}\\n\\t\\t\\tnamed: #pickerFor2ndGradientColor) layoutInset: 0.\\n\\t\\t\\tself paneForGradientFillToggle hResizing: #shrinkWrap \\n\\t\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:23'!\\npaneForBorderColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\tself \\n\\t\\t\\t\\tcolorPickerFor: self\\n\\t\\t\\t\\tgetter: #targetBorderColor\\n\\t\\t\\t\\tsetter: #targetBorderColor:.\\n\\t\\t\\tself lockedString: 'Border Color' translated.\\n\\t\\t\\t(self paneForBorderStyle) hResizing: #shrinkWrap; layoutInset: 5.\\n\\t\\t\\tself lockedString: 'Border style' translated.\\n\\t\\t\\tself paneForBorderWidth.\\n\\t\\t} \\n\\t\\tnamed: #pickerForBorderColor.\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:25'!\\npaneForBorderStyle\\n\\n\\t^self inARow: {\\n\\t\\tself borderPrototype: (BorderStyle width: 4 color: Color black)\\n\\t\\t\\thelp:'Click to select a simple colored border' translated.\\n\\t\\tself borderPrototype: (BorderStyle raised width: 4)\\n\\t\\t\\thelp:'Click to select a simple raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle inset width: 4)\\n\\t\\t\\thelp:'Click to select a simple inset border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexFramed width: 4)\\n\\t\\t\\thelp:'Click to select a complex framed border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexRaised width: 4)\\n\\t\\t\\thelp:'Click to select a complex raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexInset width: 4)\\n\\t\\t\\thelp:'Click to select a complex inset border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltFramed width: 4)\\n\\t\\t\\thelp:'Click to select a complex framed border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltRaised width: 4)\\n\\t\\t\\thelp:'Click to select a complex raised border' translated.\\n\\t\\tself borderPrototype: (BorderStyle complexAltInset width: 4)\\n\\t\\t\\thelp:'Click to select a complex inset border' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:29'!\\npaneForBorderWidth\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Border width' translated\\n\\t\\t\\tselector: #adjustTargetBorderWidth:\\n\\t\\t\\thelp: 'Drag in here to change the border width' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:18'!\\npaneForCornerRoundingToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #wantsRoundedCorners setter: #toggleCornerRounding\\n\\t\\t\\thelp: 'Turn rounded corners on or off' translated.\\n\\t\\tself lockedString: ' Rounded corners' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:40'!\\npaneForDropShadowToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #hasDropShadow setter: #toggleDropShadow\\n\\t\\t\\thelp: 'Turn drop shadows on or off' translated.\\n\\t\\tself lockedString: ' Drop shadow color' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:22'!\\npaneForGradientDirection\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Direction' translated\\n\\t\\t\\tselector: #adjustTargetGradientDirection:\\n\\t\\t\\thelp: 'Drag in here to change the direction of the gradient' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:22'!\\npaneForGradientFillToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetHasGradientFill\\n\\t\\t\\tsetter: #toggleTargetGradientFill\\n\\t\\t\\thelp: 'Turn gradient fill on or off' translated.\\n\\t\\tself lockedString: ' Gradient fill' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneForGradientOrigin\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Origin' translated\\n\\t\\t\\tselector: #adjustTargetGradientOrigin:\\n\\t\\t\\thelp: 'Drag in here to change the origin of the gradient' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:19'!\\npaneForLockedToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #isLocked setter: #toggleLocked\\n\\t\\t\\thelp: 'Turn lock on or off' translated.\\n\\t\\tself lockedString: ' Lock' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:20'!\\npaneForMainColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\tself \\n\\t\\t\\t\\tcolorPickerFor: self \\n\\t\\t\\t\\tgetter: #numberOneColor \\n\\t\\t\\t\\tsetter: #numberOneColor:.\\n\\t\\t\\tself lockedString: 'Color' translated.\\n\\t\\t\\t(self paneForSolidFillToggle) hResizing: #shrinkWrap.\\n\\t\\t} \\n\\t\\tnamed: #pickerForColor.\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:21'!\\npaneForRadialGradientToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetRadial setter: #toggleTargetRadial\\n\\t\\t\\thelp: 'Turn radial gradient on or off' translated.\\n\\t\\tself lockedString: ' Radial gradient' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'RAA 3/8/2001 18:03'!\\npaneForShadowColorPicker\\n\\n\\t^self \\n\\t\\tinAColumn: {\\n\\t\\t\\t(self inAColumn: {\\n\\t\\t\\t\\tself colorPickerFor: myTarget getter: #shadowColor setter: #shadowColor:.\\n\\t\\t\\t\\tself paneForShadowOffset.\\n\\t\\t\\t}\\n\\t\\t\\tnamed: #pickerForShadowColor) layoutInset: 0.\\n\\t\\t\\tself paneForDropShadowToggle hResizing: #shrinkWrap.\\n\\t\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:36'!\\npaneForShadowOffset\\n\\n\\t^(self inARow: {\\n\\t\\tself\\n\\t\\t\\tbuildFakeSlider: 'Offset' translated\\n\\t\\t\\tselector: #adjustTargetShadowOffset:\\n\\t\\t\\thelp: 'Drag in here to change the offset of the shadow' translated\\n\\t}) hResizing: #shrinkWrap\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:20'!\\npaneForSolidFillToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: self \\n\\t\\t\\tgetter: #targetHasSolidFill\\n\\t\\t\\tsetter: #toggleTargetSolidFill\\n\\t\\t\\thelp: 'Turn solid fill on or off' translated.\\n\\t\\tself lockedString: ' Solid fill' translated.\\n\\t}\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'dgd 8/31/2003 21:18'!\\npaneForStickinessToggle\\n\\n\\t^self inARow: {\\n\\t\\tself\\n\\t\\t\\tdirectToggleButtonFor: myTarget \\n\\t\\t\\tgetter: #isSticky setter: #toggleStickiness\\n\\t\\t\\thelp: 'Turn stickiness on or off' translated.\\n\\t\\tself lockedString: ' Sticky' translated.\\n\\t}\\n\\n! !\\n\\n!ObjectPropertiesMorph methodsFor: 'panes' stamp: 'ar 8/25/2001 18:35'!\\ntoggleBorderStyle: provider with: arg1 from: arg2\\n\\t| oldStyle newStyle |\\n\\toldStyle _ myTarget borderStyle.\\n\\tnewStyle _ provider borderStyle copy.\\n\\toldStyle width = 0 \\n\\t\\tifTrue:[newStyle width: 2]\\n\\t\\tifFalse:[newStyle width: oldStyle width].\\n\\tnewStyle baseColor: oldStyle baseColor.\\n\\tmyTarget borderStyle: newStyle.\\n\\tprovider owner owner submorphsDo:[:m| m borderWidth: 0].\\n\\tprovider owner borderWidth: 1.! !\\nAlignmentMorph subclass: #ObjectRepresentativeMorph\\n\\tinstanceVariableNames: 'objectRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n\\n!ObjectRepresentativeMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/1/2000 15:55'!\\nobjectRepresented: anObject\\n\\t\\\"Set the receiver's representee. This clears out any preexisting state in the receiver\\\"\\n\\n\\tobjectRepresented _ anObject.\\n\\tself removeAllMorphs.\\n\\tself hResizing: #shrinkWrap. \\n\\tself vResizing: #shrinkWrap.\\n\\tself addMorphBack: (StringMorph new contents: anObject name asString).\\n\\tself setNameTo: anObject name\\n\\t! !\\n\\n!ObjectRepresentativeMorph methodsFor: 'as yet unclassified' stamp: 'ar 11/1/2000 15:55'!\\nobjectRepresented: anObject labelString: aLabel\\n\\t\\\"Set the receiver's representee as indicated, and use the given label to tag it\\\"\\n\\n\\tobjectRepresented _ anObject.\\n\\tself removeAllMorphs.\\n\\tself hResizing: #shrinkWrap. \\n\\tself vResizing: #shrinkWrap.\\n\\tself addMorphBack: (StringMorph new contents: aLabel asString).\\n\\tself setNameTo: aLabel asString\\n\\t! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'macpal' stamp: 'sw 10/17/2000 11:42'!\\nobjectRepresented\\n\\t\\\"Answer the object represented by the receiver\\\"\\n\\n\\t^ objectRepresented! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'naming' stamp: 'sw 10/31/2000 09:22'!\\nnameOfObjectRepresented\\n\\t\\\"Answer the external name of the object represented\\\"\\n\\n\\t^ objectRepresented externalName! !\\n\\n\\n!ObjectRepresentativeMorph methodsFor: 'scripting' stamp: 'sw 10/17/2000 11:35'!\\ncategoriesForViewer\\n\\t\\\"Answer a list of symbols representing the categories to offer in the viewer, in order\\\"\\n\\n\\t^ objectRepresented class organization categories\\n! !\\nObject subclass: #ObjectScanner\\n\\tinstanceVariableNames: 'pvt3SmartRefStrm'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Object Storage'!\\n!ObjectScanner commentStamp: '<historical>' prior: 0!\\nAn instance of this class is the compiler's context for filing in a SmartRefStream containing instance-specific classes. When the old name of a new object's class conflicts with an existing class name, install a class var in me. It has the old name but points at the new class. The compiler uses it when compiling the code in the fileIn. Fill the SmartRefStream's renamed class dictionary.\\n\\nAn object fileout:\\n!!ObjectScanner new initialize!! \\\"allow me to take control with scanFrom:\\\"\\n\\nPlayer subclass: Player23 instanceVariableNames: 'foo' classVariableNames: '' \\n\\tpoolDictionaries: nil category: 'Instance Specific'!!\\n\\t\\\"I prescan this and (self rename: #Player23 toBe: #Player30)\\\"\\n\\n!!Player23 methodsFor: 'all' stamp: 'tk 3/9/98 18:58'!!\\t\\\"actually sent to Player30\\\"\\nfoo\\n\\t^ foo!! !!\\n\\n!!self smartRefStream!!<binary representation of the objects>!!\\n\\n\\n!\\n\\n\\n!ObjectScanner methodsFor: 'accessing' stamp: 'tk 3/15/98 19:33'!\\nsmartRefStream\\n\\n\\t^ pvt3SmartRefStrm! !\\n\\n\\n!ObjectScanner methodsFor: 'initialize-release' stamp: 'tk 3/15/98 20:17'!\\nclear\\n\\t\\\"remove all old class vars. They were UniClasses being remapped to aviod a name conflict.\\\"\\n\\n\\tself class classPool keys do: [:key |\\n\\t\\tself class classPool removeKey: key].\\t\\\"brute force\\\"! !\\n\\n!ObjectScanner methodsFor: 'initialize-release' stamp: 'tk 8/15/1998 15:26'!\\ninitialize\\n\\t\\\"remove all old class vars that are not instance-specific classes being renamed\\\"\\n\\n\\tself clear.\\n\\t\\\"Most importantly, return self, so a fileIn will let ObjectScanner seize control. So UniClasses can be remapped. See the transfer of control where ReadWriteStream fileIn calls scanFrom:\\\"! !\\n\\n\\n!ObjectScanner methodsFor: 'scanning' stamp: 'yo 11/11/2002 10:27'!\\nlookAhead: aChunk\\n\\t\\\"See if this chunk is a class Definition, and if the new class name already exists and is instance-specific. Modify the chunk, and record the rename in the SmartRefStream and in me.\\\"\\n\\n\\t| pieces sup oldName existing newName newDefn |\\n\\taChunk size < 90 ifTrue: [^ aChunk].\\t\\t\\\"class defn is big!!\\\"\\n\\t(aChunk at: 1) == $!! ifTrue: [^ aChunk].\\t\\\"method def, fast exit\\\"\\n\\tpieces _ (aChunk copyFrom: 1 to: (300 min: aChunk size)) findTokens: ' #\\t\\\\' withCRs.\\n\\tpieces size < 3 ifTrue: [^ aChunk].\\t\\\"really bigger, but just took front\\\"\\n\\t(pieces at: 2) = 'subclass:' ifFalse: [^ aChunk].\\n\\tsup _ Smalltalk at: (pieces at: 1) asSymbol ifAbsent: [^ aChunk].\\n\\tsup class class == Metaclass ifFalse: [^ aChunk].\\n\\t((oldName _ pieces at: 3) at: 1) canBeGlobalVarInitial ifFalse: [^ aChunk].\\n\\toldName _ oldName asSymbol.\\n\\t(Smalltalk includesKey: oldName) ifFalse: [^ aChunk].\\t\\\"no conflict\\\"\\n\\texisting _ Smalltalk at: oldName.\\n\\t(existing isKindOf: Class) ifFalse: [^ aChunk].\\t\\\"Write over non-class global\\\"\\n\\texisting isSystemDefined ifTrue: [^ aChunk].\\t\\\"Go ahead and redefine it!!\\\"\\n\\t\\\"Is a UniClass\\\"\\n\\tnewName _ sup chooseUniqueClassName.\\n\\tnewDefn _ aChunk copyReplaceAll: oldName with: newName.\\n\\tCompiler evaluate: newDefn for: self logged: true.\\t\\\"Create the new class\\\"\\n\\tself rename: oldName toBe: newName.\\n\\t^ newName asString\\t\\t\\\"to be evaluated\\\"\\n! !\\n\\n!ObjectScanner methodsFor: 'scanning' stamp: 'tk 3/15/98 20:22'!\\nscanFrom: aByteStream\\n\\t\\\"Sieze control of the fileIn. Put myself in as the context. If any UniClasses (for just one instance) are defined, they will do it through me, and I will look for conflicting class names. If so, install the old name as a class var of me, so the compile will work. Tell my SmartRefStream about renaming the class.\\\"\\n\\n\\t| valWithOddName47 scannerNamed53 chunkNamed117 |\\n\\tpvt3SmartRefStrm _ SmartRefStream on: aByteStream.\\n\\taByteStream ascii.\\n\\t[aByteStream atEnd] whileFalse:\\n\\t\\t[aByteStream skipSeparators.\\n\\t\\tvalWithOddName47 _ (aByteStream peekFor: $!!)\\n\\t\\t\\tifTrue: [chunkNamed117 _ aByteStream nextChunk.\\t\\\"debug\\\"\\n\\t\\t\\t\\t\\tscannerNamed53 _ Compiler evaluate: chunkNamed117\\n\\t\\t\\t\\t\\t\\t\\tfor: self logged: false.\\n\\t\\t\\t\\t\\tscannerNamed53 class == self class \\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"I already am the scanner for this file\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [scannerNamed53 scanFrom: aByteStream]]\\n\\t\\t\\tifFalse: [chunkNamed117 _ aByteStream nextChunk.\\n\\t\\t\\t\\t\\tchunkNamed117 _ self lookAhead: chunkNamed117.\\n\\t\\t\\t\\t\\tCompiler evaluate: chunkNamed117 for: self logged: true].\\n\\t\\taByteStream skipStyleChunk].\\n\\t^ valWithOddName47! !\\n\\n\\n!ObjectScanner methodsFor: 'utilities' stamp: 'tk 3/15/98 20:21'!\\nrename: existingName toBe: newName\\n\\t\\\"See if there is a conflict between what the fileIn wants to call the new UniClass (Player23) and what already exists for another unique instance. If conflict, make a class variable to intercept the existingName and direct it to class newName.\\\"\\n\\n\\texistingName = newName ifFalse: [\\n\\t\\tself class ensureClassPool.\\t\\\"create the dictionary\\\"\\n\\t\\t\\\"can't use addClassVarName: because it checks for conflicts with Smalltalk\\\"\\n\\t\\t(self class classPool includesKey: existingName) ifFalse: \\n\\t\\t\\t[\\\"Pick up any refs in Undeclared\\\"\\n\\t\\t\\tself class classPool declare: existingName from: Undeclared].\\n\\t\\tself class classPool at: existingName put: (Smalltalk at: newName).\\n\\t\\tpvt3SmartRefStrm renamed at: existingName put: newName]! !\\nStream subclass: #ObjectSocket\\n\\tinstanceVariableNames: 'socket outBuf outBufIndex outBufSize inBuf inBufIndex inBufLastIndex outObjects inObjects'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n!ObjectSocket commentStamp: 'ls 2/10/2005 21:27' prior: 0!\\nThis is a socket which exchanges medium-level packets instead of low-level bytes. This class is abstract; see the subclasses for particular kinds of medium-level packets which can be used.!\\n\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ndestroy\\n\\tsocket destroy.\\n\\tsocket := nil.! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'RAA 7/20/2000 15:10'!\\nisConnected\\n\\n\\t^socket notNil and: [socket isConnected]! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'ls 1/8/1999 16:14'!\\nprocessIO\\n\\t\\\"do some as much network IO as possible\\\"\\n\\n\\tself processOutput.\\n\\tself processInput.! !\\n\\n!ObjectSocket methodsFor: 'as yet unclassified' stamp: 'RAA 8/4/2000 15:38'!\\nremoteAddress\\n\\n\\tself isConnected ifFalse: [^nil].\\n\\t^socket remoteAddress! !\\n\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\naddToInBuf: aString\\n\\n\\t| newAlloc |\\n\\tnewAlloc := aString size * 2 max: 8000.\\n\\tinBuf ifNil: [\\n\\t\\tinBuf := String new: newAlloc.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBufLastIndex := 0.\\n\\t].\\n\\taString size > (inBuf size - inBufLastIndex) ifTrue: [\\n\\t\\tinBuf := inBuf , (String new: newAlloc)\\n\\t].\\n\\tinBuf \\n\\t\\treplaceFrom: inBufLastIndex + 1 \\n\\t\\tto: inBufLastIndex + aString size\\n\\t\\twith: aString \\n\\t\\tstartingAt: 1.\\n\\tinBufLastIndex := inBufLastIndex + aString size.\\n! !\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\nprocessOutput\\n\\t\\\"loop sending data as long as there is data to send, and the socket is ready to receive more data\\\"\\n\\t[ socket sendDone and: [ outBuf notNil or: [ outObjects isEmpty not ] ] ] whileTrue: [\\n\\t\\t| amountSent |\\n\\n\\t\\toutBuf isNil ifTrue: [\\n\\t\\t\\t| nextSize |\\n\\t\\t\\t\\\"no data in the current buffer; make a new buffer and encode some more\\\"\\n\\t\\t\\toutBuf := String new: ((self spaceToEncode: outObjects first) max: 8000).\\n\\t\\t\\toutBufIndex := 1.\\n\\t\\t\\toutBufSize := 0.\\n\\n\\t\\t\\t[\\toutObjects isEmpty not and: [\\n\\t\\t\\t\\t\\tnextSize := self spaceToEncode: outObjects first.\\n\\t\\t\\t\\t\\tnextSize <= (outBuf size - outBufSize + 1) ]\\n\\t\\t\\t] whileTrue: [\\n\\t\\t\\t\\tself encodeObject: outObjects first into: outBuf startingAt: outBufSize+1.\\n\\t\\t\\t\\toutBufSize := outBufSize + nextSize.\\n\\t\\t\\t\\toutObjects removeFirst ] ].\\n\\n\\t\\t\\\"at this point, the buffer definitely has data in it to send. Send some\\\"\\n\\t\\tamountSent := socket sendSomeData: outBuf startIndex: outBufIndex count: (outBufSize - outBufIndex + 1).\\n\\t\\toutBufIndex := outBufIndex + amountSent.\\n\\t\\toutBufIndex > outBufSize ifTrue: [ outBuf := nil ] ].\\n\\n! !\\n\\n!ObjectSocket methodsFor: 'encoding/decoding' stamp: 'sd 11/20/2005 21:26'!\\nshrinkInBuf\\n\\n\\tinBuf ifNil: [^self].\\n\\tinBufLastIndex < inBufIndex ifTrue: [\\n\\t\\tinBufLastIndex := 0.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBuf size > 20000 ifTrue: [inBuf := nil].\\t\\\"if really big, kill it\\\"\\n\\t\\t^self\\n\\t].\\n\\tinBuf := inBuf copyFrom: inBufIndex to: inBufLastIndex.\\n\\tinBufLastIndex := inBuf size.\\n\\tinBufIndex := 1.\\n\\n! !\\n\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnext\\n\\t^inObjects removeFirst\\t! !\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnextOrNil\\n\\tinObjects isEmpty\\n\\t\\tifTrue: [ ^nil ]\\n\\t\\tifFalse: [ ^inObjects removeFirst ]! !\\n\\n!ObjectSocket methodsFor: 'stream protocol' stamp: 'ls 4/25/2000 18:48'!\\nnextPut: anObject\\n\\toutObjects addLast: anObject! !\\n\\n\\n!ObjectSocket methodsFor: 'private-initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize: aSocket\\n\\tsocket := aSocket.\\n\\tinBuf := String new: 1000.\\n\\tinBufIndex := 1.\\n\\tinBufLastIndex := 0.\\n\\n\\toutBuf := nil.\\n\\n\\tinObjects := OrderedCollection new.\\n\\toutObjects := OrderedCollection new.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectSocket class methodsFor: 'as yet unclassified' stamp: 'RAA 7/20/2000 15:47'!\\non: aSocket\\n\\n\\t^self basicNew initialize: aSocket! !\\nClassTestCase subclass: #ObjectTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Objects'!\\n\\n!ObjectTest methodsFor: 'tests' stamp: 'md 11/26/2004 16:37'!\\ntestBecome\\n\\t\\\"self debug: #testBecome\\\"\\n\\t\\\"this test should that all the variables pointing to an object are pointing now to another one, and all\\n object pointing to the other are pointing to the object\\\"\\n\\n\\t| pt1 pt2 pt3 |\\n\\tpt1 := 0@0.\\n\\tpt2 := pt1.\\n\\tpt3 := 100@100.\\n\\n\\tpt1 become: pt3.\\n\\tself assert: pt2 = (100@100).\\n\\tself assert: pt3 = (0@0).\\n\\tself assert: pt1 = (100@100).! !\\n\\n!ObjectTest methodsFor: 'tests' stamp: 'md 11/26/2004 16:36'!\\ntestBecomeForward\\n\\t\\\"self debug: #testBecomeForward\\\"\\n\\t\\\"this test should that all the variables pointing to an object are pointing now to another one.\\n\\tNot that this inverse is not true. This kind of become is called oneWayBecome in VW\\\"\\n\\n\\t| pt1 pt2 pt3 |\\n\\tpt1 := 0@0.\\n\\tpt2 := pt1.\\n\\tpt3 := 100@100.\\n\\tpt1 becomeForward: pt3.\\n\\tself assert: pt2 = (100@100).\\n\\tself assert: pt3 == pt2.\\n\\tself assert: pt1 = (100@100)! !\\n\\n\\n!ObjectTest methodsFor: 'tests - debugging' stamp: 'sd 6/5/2005 09:05'!\\ntestAssert\\n\\n\\tself shouldnt: [Object assert: [true]] raise: Error.\\n\\tself shouldnt: [Object assert: true] raise: Error.\\n\\tself should: [Object assert: [false]] raise: AssertionFailure.\\n\\tself should: [Object assert: false] raise: AssertionFailure.! !\\n\\n!ObjectTest methodsFor: 'tests - debugging' stamp: 'sd 6/5/2005 09:05'!\\ntestHaltIf\\n\\n\\tself should: [self haltIf: true] raise: Halt.\\n\\tself shouldnt: [self haltIf: false] raise: Halt.\\n\\n\\tself should: [self haltIf: [true]] raise: Halt.\\n\\tself shouldnt: [self haltIf: [false]] raise: Halt.\\n\\n\\tself should: [self haltIf: #testHaltIf.] raise: Halt.\\n\\tself shouldnt: [self haltIf: #teadfasdfltIf.] raise: Halt.\\n\\n\\tself should: [self a] raise: Halt.\\n\\tself shouldnt: [self a1] raise: Halt.\\n\\n\\tself should: [self haltIf: [:o | o class = self class]] raise: Halt.\\n\\tself shouldnt: [self haltIf: [:o | o class ~= self class]] raise: Halt.\\n! !\\n\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:45'!\\na\\n\\tself b.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:46'!\\na1\\n\\tself b1.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:45'!\\nb\\n\\tself haltIf: #testHaltIf.! !\\n\\n!ObjectTest methodsFor: 'private' stamp: 'md 10/15/2004 13:46'!\\nb1\\n\\tself haltIf: #testasdasdfHaltIf.! !\\nProtoObject subclass: #ObjectTracer\\n\\tinstanceVariableNames: 'tracedObject recursionFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'.\\nObjectTracer superclass: nil!\\n!ObjectTracer commentStamp: '<historical>' prior: 0!\\nAn ObjectTracer can be wrapped around another object, and then give you a chance to inspect it whenever it receives messages from the outside. For instance...\\n\\t(ObjectTracer on: Display) flash: (50@50 extent: 50@50)\\nwill give control to a debugger just before the message flash is sent.\\nObviously this facility can be embellished in many useful ways.\\nSee also the even more perverse subclass, ObjectViewer, and its example.\\n!\\n\\n\\n!ObjectTracer methodsFor: 'very few messages' stamp: 'ar 9/27/2005 20:24'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"All external messages (those not caused by the re-send) get trapped here\\\"\\n\\t\\\"Present a dubugger before proceeding to re-send the message\\\"\\n\\n\\tToolSet debugContext: thisContext\\n\\t\\t\\t\\tlabel: 'About to perform: ', aMessage selector\\n\\t\\t\\t\\tcontents: nil.\\n\\t^ aMessage sentTo: tracedObject.\\n! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxUnTrace\\n\\n\\ttracedObject become: self! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxViewedObject\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\t^ tracedObject! !\\n\\n!ObjectTracer methodsFor: 'very few messages'!\\nxxxViewedObject: anObject\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\ttracedObject _ anObject! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectTracer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectTracer class methodsFor: 'instance creation'!\\non: anObject\\n\\t^ self new xxxViewedObject: anObject! !\\nObjectTracer subclass: #ObjectViewer\\n\\tinstanceVariableNames: 'valueBlock lastValue changeBlock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Objects'!\\n!ObjectViewer commentStamp: '<historical>' prior: 0!\\nObjectViewers offers the same kind of interception of messages (via doesnotUnderstand:) as ObjectTracers, but instead of just being wrappers, they actually replace the object being viewed. This makes them a lot more dangerous to use, but one can do amazing things. For instance, the example below actually intercepts the InputSensor object, and prints the mouse coordinates asynchronously, every time they change:\\n\\tSensor evaluate: [Sensor cursorPoint printString displayAt: 0@0]\\n\\t\\twheneverChangeIn: [Sensor cursorPoint].\\nTo exit from this example, execute:\\n\\tSensor xxxUnTrace\\n!\\n\\n\\n!ObjectViewer methodsFor: 'very few messages'!\\ndoesNotUnderstand: aMessage \\n\\t\\\"Check for change after sending aMessage\\\"\\n\\t| returnValue newValue |\\n\\trecursionFlag ifTrue: [^ aMessage sentTo: tracedObject].\\n\\trecursionFlag _ true.\\n\\treturnValue _ aMessage sentTo: tracedObject.\\n\\tnewValue _ valueBlock value.\\n\\tnewValue = lastValue ifFalse:\\n\\t\\t[changeBlock value.\\n\\t\\tlastValue _ newValue].\\n\\trecursionFlag _ false.\\n\\t^ returnValue! !\\n\\n!ObjectViewer methodsFor: 'very few messages'!\\nxxxViewedObject: viewedObject evaluate: block1 wheneverChangeIn: block2\\n\\t\\\"This message name must not clash with any other (natch).\\\"\\n\\ttracedObject _ viewedObject.\\n\\tvalueBlock _ block2.\\n\\tchangeBlock _ block1.\\n\\trecursionFlag _ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectViewer class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectViewer class methodsFor: 'instance creation'!\\non: viewedObject evaluate: block1 wheneverChangeIn: block2\\n\\t^ self new xxxViewedObject: viewedObject evaluate: block1 wheneverChangeIn: block2! !\\nObject subclass: #ObjectWithDocumentation\\n\\tinstanceVariableNames: 'authoringStamp properties elementSymbol naturalLanguageTranslations'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Kernel'!\\n!ObjectWithDocumentation commentStamp: '<historical>' prior: 0!\\nObjectWithDocumentation - an abstract superclass for objects that allows maintenance of an authoring stamp, a body of documentation, and a properties dictionary.\\nThe Properties implementation has not happened yet -- it would closely mirror the implemenation of properties in the MorphExtension, for example.!\\n\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:21'!\\ndocumentation\\n\\t\\\"Answer the receiver's documentation\\\"\\n\\n\\t^self helpMessage! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 19:33'!\\ndocumentation: somethingUsefulHopefully\\n\\t\\\"Set the receiver's documentation, in the current langauge\\\"\\n\\n\\tself helpMessage: somethingUsefulHopefully! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'sw 8/18/2004 20:23'!\\nhelpMessage\\n\\t\\\"Check if there is a getterSetterHelpMessage. \\n\\tOtherwise try the normal help message or return nil.\\\"\\n\\n\\t^ self getterSetterHelpMessage\\n\\t\\tifNil: [(self propertyAt: #helpMessage ifAbsent:\\n\\t\\t\\t[self legacyHelpMessage ifNil: [^ nil]]) translated]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 19:32'!\\nhelpMessage: somethingUsefulHopefully\\n\\t\\\"Set the receiver's documentation, in the current langauge\\\"\\n\\n\\tself propertyAt: #helpMessage put: somethingUsefulHopefully! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nlegacyHelpMessage\\n\\t\\\"If I have a help message stashed in my legacy naturalTranslations slot, answer its translated rendition, else answer nil. If I *do* come across a legacy help message, transfer it to my properties dictionary.\\\"\\n\\n\\t| untranslated |\\n\\tnaturalLanguageTranslations isEmptyOrNil \\\"only in legacy (pre-3.8) projects\\\"\\n\\t\\tifTrue: [^ nil].\\n\\tuntranslated := naturalLanguageTranslations first helpMessage ifNil: [^ nil].\\n\\tself propertyAt: #helpMessage put: untranslated.\\n\\tnaturalLanguageTranslations removeFirst.\\n\\tnaturalLanguageTranslations isEmpty ifTrue: [naturalLanguageTranslations := nil].\\n\\t^ untranslated translated! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 23:57'!\\nuntranslatedHelpMessage\\n\\t\\\"Check if there is a getterSetterHelpMessage. \\n\\tOtherwise try the normal help message or return nil.\\\"\\n\\n\\t^(self propertyAt: #getterSetterHelpMessage ifAbsent: [nil])\\n\\t\\tifNil: [(self propertyAt: #helpMessage ifAbsent: [nil])]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 23:56'!\\nuntranslatedWording\\n\\t\\\"Answer the receiver's wording\\\"\\n\\n\\t^self propertyAt: #wording ifAbsent: [nil]! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:34'!\\nwording\\n\\t\\\"Answer the receiver's wording\\\"\\n\\n\\t| wording |\\n\\t(wording := self propertyAt: #wording ifAbsent: [nil])\\n\\t\\tifNotNil: [^wording translated].\\n\\n\\tself initWordingAndDocumentation.\\n\\t^self propertyAt: #wording ifAbsent: ['']! !\\n\\n!ObjectWithDocumentation methodsFor: 'accessing' stamp: 'mir 7/12/2004 21:39'!\\nwording: aString\\n\\t\\\"Set the receiver's wording, in the current langauge\\\"\\n\\n\\tself propertyAt: #wording put: aString! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'documentation' stamp: 'rbb 3/1/2005 11:02'!\\neditDescription\\n\\t\\\"Allow the user to see and edit the documentation for this object\\\"\\n\\t| reply helpMessage |\\n\\thelpMessage := self documentation isNil\\n\\t\\t\\t\\tifTrue: [String new]\\n\\t\\t\\t\\tifFalse: [self documentation].\\n\\treply := UIManager default\\n\\t\\t\\t\\tmultiLineRequest: 'Kindly edit the description' translated\\n\\t\\t\\t\\tcenterAt: Sensor cursorPoint\\n\\t\\t\\t\\tinitialAnswer: helpMessage\\n\\t\\t\\t\\tanswerHeight: 200.\\n\\treply isEmptyOrNil\\n\\t\\tifFalse: [self documentation: reply]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\tauthoringStamp := Utilities changeStampPerSe\\n! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'migration' stamp: 'mir 7/12/2004 23:45'!\\nmigrateWordAndHelpMessage\\n\\t\\\"Migrate the English wording and help message to the new structure\\\"\\n\\n\\t| englishElement |\\n\\tself initWordingAndDocumentation.\\n\\t(self properties includes: #wording)\\n\\t\\tifFalse: [\\n\\t\\t\\tenglishElement := self naturalLanguageTranslations\\n\\t\\t\\t\\tdetect: [:each | each language == #English] ifNone: [^nil].\\n\\t\\t\\tself wording: englishElement wording.\\n\\t\\t\\tself helpMessage: englishElement helpMessage]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'miscellaneous' stamp: 'sw 9/12/2001 23:03'!\\nelementSymbol\\n\\t\\\"Answer the receiver's element symbol\\\"\\n\\n\\t^ elementSymbol! !\\n\\n!ObjectWithDocumentation methodsFor: 'miscellaneous' stamp: 'mir 7/12/2004 23:20'!\\nnaturalLanguageTranslations\\n\\t^naturalLanguageTranslations ifNil: [OrderedCollection new]! !\\n\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:28'!\\ngetterSetterHelpMessage\\n\\t\\\"Returns a helpMessage that has been computed previously and needs to be translated and then formatted with the elementSymbol.\\n\\t'get value of {1}' translated format: {elSym}\\\"\\n\\n\\t^(self propertyAt: #getterSetterHelpMessage ifAbsent: [^nil])\\n\\t\\ttranslated format: {self elementSymbol}! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:29'!\\ngetterSetterHelpMessage: aString\\n\\t\\\"Sets a helpMessage that needs to be translated and then formatted with the elementSymbol.\\n\\t'get value of {1}' translated format: {elSym}\\\"\\n\\n\\tself propertyAt: #getterSetterHelpMessage put: aString! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 21:31'!\\ninitWordingAndDocumentation\\n\\t\\\"Initialize wording and documentation (helpMessage) for getters and setters\\\"\\n\\n\\t| elSym |\\n\\telSym := self elementSymbol.\\n\\telSym\\n\\t\\tifNil: [^self].\\n\\n\\t((elSym beginsWith: 'get')\\n\\t\\tand: [elSym size > 3])\\n\\t\\tifTrue: [\\n\\t\\t\\tself wording: (elSym allButFirst: 3) withFirstCharacterDownshifted.\\n\\t\\t\\tself getterSetterHelpMessage: 'get value of {1}']\\n\\t\\tifFalse: [\\n\\t\\t\\t((elSym beginsWith: 'set')\\n\\t\\t\\t\\tand: [elSym size > 4])\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tself wording: (elSym allButFirst: 3) withFirstCharacterDownshifted.\\n\\t\\t\\t\\t\\tself getterSetterHelpMessage: 'set value of {1}']]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:30'!\\nproperties\\n\\t^properties ifNil: [properties := Dictionary new]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:30'!\\npropertyAt: key\\n\\t^self propertyAt: key ifAbsent: [nil]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:29'!\\npropertyAt: key ifAbsent: aBlock\\n\\t^properties\\n\\t\\tifNil: aBlock\\n\\t\\tifNotNil: [properties at: key ifAbsent: aBlock]! !\\n\\n!ObjectWithDocumentation methodsFor: 'private' stamp: 'mir 7/12/2004 19:29'!\\npropertyAt: key put: aValue\\n\\tself properties at: key put: aValue! !\\nAbstractObjectsAsMethod subclass: #ObjectsAsMethodsExample\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-ObjectsAsMethods'!\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'ar 5/17/2003 20:16'!\\nadd: a with: b\\n\\t^a + b! !\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'ar 5/17/2003 20:16'!\\nanswer42\\n\\t^42! !\\n\\n!ObjectsAsMethodsExample methodsFor: 'as yet unclassified' stamp: 'md 3/1/2006 19:37'!\\nrun: oldSelector with: arguments in: aReceiver\\n\\t^self perform: oldSelector withArguments: arguments! !\\nAlignmentMorph subclass: #ObjectsTool\\n\\tinstanceVariableNames: 'searchString modeSymbol'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-PartsBin'!\\n!ObjectsTool commentStamp: '<historical>' prior: 0!\\nI am a Master Parts Bin that allows the user to drag out a new Morph from a voluminous iconic list.\\n\\nChoose \\\"objects\\\" from the world menu, or type Alt-o (Cmd-o on the Mac).\\n\\nTo add a new kinds of Morphs:\\nIn the class of the Morph, implement the message:\\n\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Rectangle'\\n\\t\\tcategories:\\t\\t#('Graphics' ' Basic 1 ')\\n\\t\\tdocumentation:\\t'A rectangular shape, with border and fill style'\\n\\nThe partName is the title that will show in the lower pane of the Object Tool.\\nWhen is categories mode, an object can be seen in more than one category. The list above tells which ones.\\nDocumentation is what will show in the balloon help for each object thumbnail.\\nThe message #initializeToStandAlone creates the actual instance.\\n\\nTo make a second variant object prototype coming from the same class, implement #supplementaryPartsDescriptions. In it, you get to specify the nativitySelector. It is sent to the class to get the variant objects. Often it is #authoringPrototype. (A class may supply supplementaryPartsDescriptions without implementing descriptionForPartsBin. This gives you better control.)\\n\\n!\\n\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'dgd 4/4/2006 16:43'!\\nalphabeticTabs\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of a morphic category\\\"\\n\\n\\t| buttonList aButton tabLabels |\\n\\n\\tself flag: #todo. \\\"includes non-english characters\\\"\\n\\ttabLabels _ (($a to: $z) collect: [:ch | ch asString]) asOrderedCollection.\\n\\n\\tbuttonList _ tabLabels collect:\\n\\t\\t[:catName |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: catName.\\n\\t\\t\\taButton actWhen: #buttonDown.\\n\\t\\t\\taButton target: self; actionSelector: #showAlphabeticCategory:fromButton:; arguments: {catName. aButton}].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new tabsForMorphicCategories\\\"! !\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'nk 9/3/2004 13:47'!\\ninstallQuads: quads fromButton: aButton\\n\\t\\\"Install items in the bottom pane that correspond to the given set of quads, as triggered from the given button\\\"\\n\\n\\t| aPartsBin sortedQuads oldResizing |\\n\\taPartsBin _ self partsBin.\\n\\toldResizing := aPartsBin vResizing.\\n\\taPartsBin removeAllMorphs.\\n\\tsortedQuads _ (PartsBin translatedQuads: quads)\\n\\t\\t\\t\\t\\t\\t\\tasSortedCollection: [:a :b | a third < b third].\\n\\taPartsBin listDirection: #leftToRight quadList: sortedQuads.\\n\\taButton ifNotNil: [self tabsPane highlightOnlySubmorph: aButton].\\n\\taPartsBin vResizing: oldResizing.\\n\\taPartsBin layoutChanged; fullBounds.\\n\\tself isFlap ifFalse: [ self minimizePartsBinSize ].! !\\n\\n!ObjectsTool methodsFor: 'alphabetic' stamp: 'nk 9/3/2004 12:13'!\\nshowAlphabeticTabs\\n\\t\\\"Switch to the mode of showing alphabetic tabs\\\"\\n\\n\\tmodeSymbol == #alphabetic ifTrue: [ ^self ].\\n\\tself partsBin removeAllMorphs.\\n\\tself initializeWithTabs: self alphabeticTabs.\\n\\tself modeSymbol: #alphabetic.\\n\\tself tabsPane submorphs first doButtonAction! !\\n\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 9/3/2004 13:43'!\\nshowCategories\\n\\t\\\"Set the receiver up so that it shows tabs for each of the standard categories\\\"\\n\\n\\tmodeSymbol == #categories ifTrue: [ ^self ].\\n\\n\\tself partsBin removeAllMorphs.\\n\\tself initializeWithTabs: self tabsForCategories.\\n\\tself modeSymbol: #categories.\\n\\tself tabsPane submorphs first doButtonAction.\\n! !\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 9/3/2004 13:51'!\\nshowCategory: aCategoryName fromButton: aButton \\n\\t\\\"Project items from the given category into my lower pane\\\"\\n\\t| quads |\\n\\tself partsBin removeAllMorphs.\\n\\tCursor wait\\n\\t\\tshowWhile: [quads := OrderedCollection new.\\n\\t\\t\\tMorph withAllSubclasses\\n\\t\\t\\t\\tdo: [:aClass | aClass theNonMetaClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:aDescription | aDescription translatedCategories includes: aCategoryName]].\\n\\t\\t\\tquads := quads\\n\\t\\t\\t\\t\\t\\tasSortedCollection: [:q1 :q2 | q1 third <= q2 third].\\n\\t\\t\\tself installQuads: quads fromButton: aButton]! !\\n\\n!ObjectsTool methodsFor: 'categories' stamp: 'nk 8/23/2004 18:18'!\\ntabsForCategories\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of a category\\\"\\n\\n\\t| buttonList aButton classes categoryList basic |\\n\\tclasses _ Morph withAllSubclasses.\\n\\tcategoryList _ Set new.\\n\\tclasses do: [:aClass |\\n\\t\\t(aClass class includesSelector: #descriptionForPartsBin) ifTrue:\\n\\t\\t\\t[categoryList addAll: aClass descriptionForPartsBin translatedCategories].\\n\\t\\t(aClass class includesSelector: #supplementaryPartsDescriptions) ifTrue:\\n\\t\\t\\t[aClass supplementaryPartsDescriptions do:\\n\\t\\t\\t\\t[:aDescription | categoryList addAll: aDescription translatedCategories]]].\\n\\n\\tcategoryList _ OrderedCollection withAll: (categoryList asSortedArray).\\n\\t\\n\\tbasic := categoryList remove: ' Basic' translated ifAbsent: [ ].\\n\\tbasic ifNotNil: [ categoryList addFirst: basic ].\\n\\n\\tbasic := categoryList remove: 'Basic' translated ifAbsent: [ ].\\n\\tbasic ifNotNil: [ categoryList addFirst: basic ].\\n\\n\\tbuttonList _ categoryList collect:\\n\\t\\t[:catName |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: catName.\\n\\t\\t\\taButton actWhen: #buttonDown.\\n\\t\\t\\taButton target: self; actionSelector: #showCategory:fromButton:; arguments: {catName. aButton}].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new tabsForCategories\\\"! !\\n\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'nk 9/3/2004 13:46'!\\ninitializeForFlap\\n\\t\\\"Initialize the receiver to operate in a flap at the top of the screen.\\\"\\n\\n\\t\\\"\\n\\tFlaps newObjectsFlap openInWorld\\n\\t\\\"\\n\\n\\t| buttonPane aBin aColor heights tabsPane |\\n\\tself basicInitialize.\\n\\n\\tself layoutInset: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #rigid;\\n\\t\\tborderWidth: 2; borderColor: Color darkGray;\\n\\t\\textent: (self minimumWidth @ self minimumHeight).\\n\\n\\t\\\"mode buttons\\\"\\n\\tbuttonPane := self paneForTabs: self modeTabs.\\n\\tbuttonPane\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tsetNameTo: 'ButtonPane';\\n\\t\\tcolor: (aColor := buttonPane color) darker;\\n\\t\\tlayoutInset: 6;\\n\\t\\twrapDirection: nil;\\n\\t\\twidth: self width;\\n\\t\\tlayoutChanged; fullBounds.\\n\\n\\t\\\"Place holder for a tabs or text pane\\\"\\n\\ttabsPane := Morph new\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\theights := { buttonPane height. 40 }.\\n\\n\\tbuttonPane vResizing: #spaceFill.\\n\\tself\\n\\t\\taddMorph: buttonPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ 0 corner: 0 @ heights first)).\\n\\n\\tself\\n\\t\\taddMorph: tabsPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ heights first corner: 0 @ (heights first + heights second))).\\n\\n\\taBin := (PartsBin newPartsBinWithOrientation: #leftToRight from: #())\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\twrapDirection: #topToBottom;\\n\\t\\tcolor: aColor lighter lighter;\\n\\t\\tsetNameTo: 'Parts';\\n\\t\\tdropEnabled: false;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\tself\\n\\t\\taddMorph: aBin\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 1)\\n\\t\\t\\t\\toffsets: (0 @ (heights first + heights second) corner: 0 @ 0)).\\n\\n\\taBin color: (Color orange muchLighter);\\n\\t\\tsetNameTo: 'Objects' translated.\\n\\n\\tself color: (Color orange muchLighter);\\n\\t\\tsetNameTo: 'Objects' translated.\\n! !\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'dgd 4/4/2006 16:47'!\\ninitializeToStandAlone\\n\\t\\\"Initialize the receiver so that it can live as a stand-alone morph\\\"\\n\\t| buttonPane aBin aColor heights tabsPane |\\n\\tself basicInitialize.\\n\\n\\tself layoutInset: 0;\\n\\t\\tlayoutPolicy: ProportionalLayout new;\\n\\t\\tuseRoundedCorners;\\n\\t\\thResizing: #rigid;\\n\\t\\tvResizing: #rigid;\\n\\t\\textent: (self minimumWidth @ self minimumHeight).\\n\\n\\t\\\"mode buttons\\\"\\n\\tbuttonPane := self paneForTabs: self modeTabs.\\n\\tbuttonPane color: ColorTheme current dialogColor.\\n\\tbuttonPane\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tsetNameTo: 'ButtonPane';\\n\\t\\taddMorphFront: self dismissButton;\\n\\t\\taddMorphBack: self helpButton;\\n\\t\\tcolor: (aColor := buttonPane color) darker;\\n\\t\\tlayoutInset: 5;\\n\\t\\twrapDirection: nil;\\n\\t\\twidth: self width;\\n\\t\\tlayoutChanged; fullBounds.\\n\\n\\t\\\"Place holder for a tabs or text pane\\\"\\n\\ttabsPane := Morph new.\\n\\ttabsPane\\n\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\thResizing: #spaceFill.\\n\\n\\theights := { buttonPane height. 40 }.\\n\\n\\tbuttonPane vResizing: #spaceFill.\\n\\tself\\n\\t\\taddMorph: buttonPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ 0 corner: 0 @ heights first)).\\n\\n\\tself\\n\\t\\taddMorph: tabsPane\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 0)\\n\\t\\t\\t\\toffsets: (0 @ heights first corner: 0 @ (heights first + heights second))).\\n\\n\\taBin := (PartsBin newPartsBinWithOrientation: #leftToRight from: #())\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\twrapDirection: #topToBottom;\\n\\t\\tcolor: aColor lighter lighter;\\n\\t\\tsetNameTo: 'Parts';\\n\\t\\tdropEnabled: false;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tyourself.\\n\\n\\tself\\n\\t\\taddMorph: aBin\\n\\t\\tfullFrame: (LayoutFrame\\n\\t\\t\\t\\tfractions: (0 @ 0 corner: 1 @ 1)\\n\\t\\t\\t\\toffsets: (0 @ (heights first + heights second) corner: 0 @ 0)).\\n\\n\\tself\\n\\t\\tborderWidth: ColorTheme current dialogBorderWidth;\\n\\t\\tborderColor: ColorTheme current dialogBorderColor;\\n\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\tsetNameTo: 'Objects' translated;\\n\\t\\tshowCategories.\\n! !\\n\\n!ObjectsTool methodsFor: 'initialization' stamp: 'dgd 4/4/2006 16:45'!\\ntweakAppearanceAfterModeShift\\n\\t\\\"After the receiver has been put into a given mode, make an initial selection of category, if appropriate, and highlight the mode button.\\\"\\n\\n\\tself buttonPane submorphs do:\\n\\t\\t[:aButton | \\n\\t\\t\\t| aColor |\\n\\t\\t\\t\\\"aButton borderWidth: 1.\\\"\\n\\t\\t\\taColor := (aButton valueOfProperty: #modeSymbol) = modeSymbol\\n\\t\\t\\t\\tifTrue: [Color red]\\n\\t\\t\\t\\tifFalse: [Color black].\\n\\n\\t\\t\\taButton firstSubmorph color: aColor.\\n\\t\\t\\taButton borderColor: aColor.\\n\\t\\t].! !\\n\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:35'!\\nextent: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tself extent = anExtent ifTrue: [ ^self ].\\n\\tsuper extent: anExtent.\\n\\tself fixLayoutFrames.! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 13:44'!\\nfixLayoutFrames\\n\\t\\\"Adjust the boundary between the tabs or search pane and the parts bin, giving preference to the tabs.\\\"\\n\\n\\t| oldY newY tp tpHeight |\\n\\toldY := ((tp := self tabsPane\\n\\t\\t\\t\\t\\t\\tifNil: [self searchPane])\\n\\t\\t\\t\\tifNil: [^ self]) layoutFrame bottomOffset.\\n\\ttpHeight := tp hasSubmorphs\\n\\t\\t\\t\\tifTrue: [(tp submorphBounds outsetBy: tp layoutInset) height]\\n\\t\\t\\t\\tifFalse: [tp height].\\n\\tnewY := (self buttonPane\\n\\t\\t\\t\\tifNil: [^ self]) height + tpHeight.\\n\\toldY = newY\\n\\t\\tifTrue: [^ self].\\n\\ttp layoutFrame bottomOffset: newY.\\n\\t(self partsBin\\n\\t\\tifNil: [^ self]) layoutFrame topOffset: newY.\\n\\tsubmorphs\\n\\t\\tdo: [:m | m layoutChanged ]! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 13:47'!\\nminimizePartsBinSize\\n\\tself layoutChanged; fullBounds.\\n\\tself fixLayoutFrames.\\n\\tself setExtentFromHalo: (self minimumWidth @ self minimumHeight) ! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 10:35'!\\nminimumBottom\\n\\t| iconsBottom partsBin |\\n\\tpartsBin := self partsBin ifNil: [ ^self bottom ].\\n\\ticonsBottom := partsBin submorphs isEmpty\\n\\t\\tifTrue: [ partsBin top + 60 ]\\n\\t\\tifFalse: [ partsBin submorphBounds bottom + partsBin layoutInset ].\\n\\n\\t^iconsBottom + self layoutInset + self borderWidth! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 11:53'!\\nminimumHeight\\n\\t^(self minimumBottom - self top) max: 280! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:06'!\\nminimumWidth\\n\\t\\\"Answer a width that assures that the alphabet fits in two rows\\\"\\n\\n\\t^ 300! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:40'!\\nposition: aPoint\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tself position = aPoint ifTrue: [ ^self ].\\n\\tsuper position: aPoint.\\n\\tself fixLayoutFrames.! !\\n\\n!ObjectsTool methodsFor: 'layout' stamp: 'nk 9/3/2004 12:44'!\\nsetExtentFromHalo: anExtent\\n\\t\\\"The user has dragged the grow box such that the receiver's extent would be anExtent. Do what's needed\\\"\\n\\tsuper setExtentFromHalo: ((anExtent x max: self minimumWidth) @ (anExtent y max: self minimumHeight)).\\n! !\\n\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'sw 8/12/2001 16:30'!\\nmodeSymbol\\n\\t\\\"Answer the modeSymbol\\\"\\n\\n\\t^ modeSymbol! !\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'nk 9/3/2004 13:32'!\\nmodeSymbol: aSymbol\\n\\t\\\"Set the receiver's modeSymbol as indicated\\\"\\n\\n\\tmodeSymbol _ aSymbol.\\n\\tself tweakAppearanceAfterModeShift.\\n! !\\n\\n!ObjectsTool methodsFor: 'major modes' stamp: 'dgd 4/4/2006 16:47'!\\nmodeTabs\\n\\t\\\"Answer a list of buttons which, when hit, will trigger the choice of mode of the receiver\\\"\\n\\n\\t| buttonList aButton tupleList |\\n\\ttupleList _ #(\\n\\t\\t('alphabetic'\\t\\talphabetic\\tshowAlphabeticTabs\\t'A separate tab for each letter of the alphabet')\\n\\t\\t('find'\\t\\t\\t\\tsearch\\t\\t\\tshowSearchPane\\t\\t\\t'Provides a type-in pane allowing you to match')\\n\\t\\t('categories'\\t\\tcategories\\tshowCategories\\t\\t\\t'Grouped by category')\\n\\n\\t\\t\\\"('standard'\\t\\tstandard\\t\\tshowStandardPane\\t\\t'Standard Squeak tools supplies for building')\\\"\\n\\t).\\n\\t\\t\\t\\t\\n\\tbuttonList _ tupleList collect:\\n\\t\\t[:tuple |\\n\\t\\t\\taButton _ SimpleButtonMorph new label: tuple first translated.\\n\\t\\t\\taButton actWhen: #buttonUp.\\n\\t\\t\\taButton setProperty: #modeSymbol toValue: tuple second.\\n\\t\\t\\taButton target: self; actionSelector: tuple third.\\n\\t\\t\\taButton setBalloonText: tuple fourth translated.\\n\\t\\t\\taButton borderWidth: 0.\\n\\t\\t\\taButton].\\n\\t^ buttonList\\n\\n\\\"ObjectsTool new modeTabs\\\"! !\\n\\n\\n!ObjectsTool methodsFor: 'menu' stamp: 'dgd 8/30/2003 16:22'!\\naddCustomMenuItems: aMenu hand: aHand\\n\\t\\\"Add items to the given halo-menu, given a hand\\\"\\n\\n\\tsuper addCustomMenuItems: aMenu hand: aHand.\\n\\taMenu addLine.\\n\\taMenu add: 'alphabetic' translated target: self selector: #showAlphabeticTabs.\\n\\taMenu add: 'find' translated target: self selector: #showSearchPane.\\n\\taMenu add: 'categories' translated target: self selector: #showCategories.\\n\\taMenu addLine.\\n\\taMenu add: 'reset thumbnails' translated target: self selector: #resetThumbnails.! !\\n\\n!ObjectsTool methodsFor: 'menu' stamp: 'nk 9/7/2003 07:42'!\\nresetThumbnails\\n\\t\\\"Reset the thumbnail cache\\\"\\n\\n\\tPartsBin clearThumbnailCache.\\n\\tmodeSymbol == #categories ifTrue: [self showCategories] ifFalse: [self showAlphabeticTabs]! !\\n\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 11:20'!\\nnewSearchPane\\n\\t\\\"Answer a type-in pane for searches\\\"\\n\\n\\t| aTextMorph |\\n\\taTextMorph _ TextMorph new\\n\\t\\tsetProperty: #defaultContents toValue: ('' asText allBold addAttribute: (TextFontChange font3));\\n\\t\\tsetTextStyle: (TextStyle fontArray: { Preferences standardEToysFont });\\n\\t\\tsetDefaultContentsIfNil;\\n\\t\\ton: #keyStroke send: #searchPaneCharacter: to: self;\\n\\t\\tsetNameTo: 'SearchPane';\\n\\t\\tsetBalloonText: 'Type here and all entries that match will be shown.' translated;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tmargins: 4@6;\\n\\t\\tbackgroundColor: Color white.\\n\\t^ aTextMorph! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'sw 6/30/2001 14:26'!\\nsearchPaneCharacter: evt\\n\\t\\\"A character represented by the event handed in was typed in the search pane by the user\\\"\\n\\n\\t^ self showMorphsMatchingSearchString\\n\\n\\\"\\t| char | *** The variant below only does a new search if RETURN or ENTER is hit ***\\n\\tchar _ evt keyCharacter.\\n\\t(char == Character enter or: [char == Character cr]) ifTrue:\\n\\t\\t[self showMorphsMatchingSearchString]\\\"! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 10:39'!\\nsetSearchStringFromSearchPane\\n\\t\\\"Set the search string by obtaining its contents from the search pane, and doing a certain amount of munging\\\"\\n\\n\\tsearchString _ self searchPane text string asLowercase withBlanksTrimmed.\\n\\tsearchString _ searchString copyWithoutAll: {Character enter. Character cr}! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 13:51'!\\nshowMorphsMatchingSearchString\\n\\t\\\"Put items matching the search string into my lower pane\\\"\\n\\t| quads |\\n\\tself setSearchStringFromSearchPane.\\n\\tself partsBin removeAllMorphs.\\n\\tCursor wait\\n\\t\\tshowWhile: [quads := OrderedCollection new.\\n\\t\\t\\tMorph withAllSubclasses\\n\\t\\t\\t\\tdo: [:aClass | aClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:info | info formalName translated includesSubstring: searchString caseSensitive: false]].\\n\\t\\t\\tself installQuads: quads fromButton: nil]! !\\n\\n!ObjectsTool methodsFor: 'search' stamp: 'nk 9/3/2004 12:13'!\\nshowSearchPane\\n\\t\\\"Set the receiver up so that it shows the search pane\\\"\\n\\n\\t| tabsPane aPane frame |\\n\\tmodeSymbol == #search ifTrue: [ ^self ].\\n\\n\\tself partsBin removeAllMorphs.\\n\\n\\ttabsPane := self tabsPane.\\n\\taPane _ self newSearchPane.\\n\\taPane layoutChanged; fullBounds.\\n\\n\\taPane layoutFrame: (frame := tabsPane layoutFrame copy).\\n\\tframe bottomOffset: (frame topOffset + aPane height).\\n\\tself replaceSubmorph: tabsPane by: aPane.\\n\\tself partsBin layoutFrame topOffset: frame bottomOffset.\\n\\n\\tself modeSymbol: #search.\\n\\tself showMorphsMatchingSearchString.\\n\\tActiveHand newKeyboardFocus: aPane! !\\n\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:06'!\\nbuttonPane\\n\\t\\\"Answer the receiver's button pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'ButtonPane' ifNone: [].! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:09'!\\npartsBin\\n\\t^self findDeeplyA: PartsBin.! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 10:40'!\\nsearchPane\\n\\t\\\"Answer the receiver's search pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'SearchPane' ifNone: [].! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 13:51'!\\nshowAlphabeticCategory: aString fromButton: aButton \\n\\t\\\"Blast items beginning with a given letter into my lower pane\\\"\\n\\t| eligibleClasses quads uc |\\n\\tself partsBin removeAllMorphs.\\n\\tuc := aString asUppercase asCharacter.\\n\\tCursor wait\\n\\t\\tshowWhile: [eligibleClasses := Morph withAllSubclasses.\\n\\t\\t\\tquads := OrderedCollection new.\\n\\t\\t\\teligibleClasses\\n\\t\\t\\t\\tdo: [:aClass | aClass theNonMetaClass\\n\\t\\t\\t\\t\\t\\taddPartsDescriptorQuadsTo: quads\\n\\t\\t\\t\\t\\t\\tif: [:info | info formalName translated asUppercase first = uc]].\\n\\t\\t\\tself installQuads: quads fromButton: aButton]! !\\n\\n!ObjectsTool methodsFor: 'submorph access' stamp: 'nk 9/3/2004 08:06'!\\ntabsPane\\n\\t\\\"Answer the receiver's tabs pane, nil if none\\\"\\n\\n\\t^ self submorphNamed: 'TabPane' ifNone: [].! !\\n\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'nk 9/3/2004 13:47'!\\ninitializeWithTabs: tabList\\n\\t\\\"Initialize the receiver to have the given tabs\\\"\\n\\t| oldPane newPane |\\n\\toldPane := self tabsPane ifNil: [ self searchPane ].\\n\\tnewPane := (self paneForTabs: tabList)\\n\\t\\tsetNameTo: 'TabPane';\\n\\t\\tyourself.\\n\\tnewPane layoutFrame: oldPane layoutFrame.\\n\\tself replaceSubmorph: oldPane by: newPane.\\n\\tnewPane layoutChanged; fullBounds.\\n\\tself fixLayoutFrames.\\n\\n! !\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'dgd 4/4/2006 16:44'!\\npaneForTabs: tabList \\n\\t\\\"Answer a pane bearing tabs for the given list\\\"\\n\\t| aPane |\\n\\ttabList do: [:t |\\n\\t\\t\\tt color: Color transparent.\\n\\t\\t\\tt borderWidth: 1;\\n\\t\\t\\t\\tborderColor: Color black].\\n\\n\\taPane := AlignmentMorph newRow\\n\\t\\t\\t\\tcolor: ColorTheme current dialogColor;\\n\\t\\t\\t\\tlistDirection: #leftToRight;\\n\\t\\t\\t\\twrapDirection: #topToBottom;\\n\\t\\t\\t\\tvResizing: #spaceFill;\\n\\t\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\t\\tcellInset: 6;\\n\\t\\t\\t\\tlayoutInset: 4;\\n\\t\\t\\t\\tlistCentering: #center;\\n\\t\\t\\t\\tlistSpacing: #equal;\\n\\t\\t\\t\\taddAllMorphs: tabList;\\n\\t\\t\\t\\tyourself.\\n\\n\\taPane width: self layoutBounds width.\\n\\n\\t^ aPane! !\\n\\n!ObjectsTool methodsFor: 'tabs' stamp: 'dgd 8/30/2003 16:09'!\\npresentHelp\\n\\t\\\"Sent when a Help button is hit; provide the user with some form of help for the tool at hand\\\"\\n\\n'The Objects tool allows you to browse through, and obtain copies of, many kinds of objects. \\n\\nYou can obtain an Objects tool by choosing \\\"Objects\\\" from the world menu, or by the shortcut of typing alt-o (cmd-o) any time the cursor is over the desktop.\\n\\nThere are three ways to use Objects, corresponding to the three tabs seen at the top:\\n\\nalphabetic - gives you separate tabs for a, b, c, etc. Click any tab, and you will see the icons of all the objects whose names begin with that letter\\n\\nsearch - gives you a type-in pane for a search string. Type any letters there, and icons of all the objects whose names match what you have typed will appear in the bottom pane.\\n\\ncategories - provides tabs representing categories of related items. Click on any tab to see the icons of all the objects in the category.\\n\\nWhen the cursor lingers over the icon of any object, you will get balloon help for the item.\\n\\nWhen you drag an icon from Objects, it will result in a new copy of it in your hand; the new object will be deposited wherever you next click.' translated\\n\\n\\topenInWorkspaceWithTitle: 'About Objects' translated! !\\n\\n\\n!ObjectsTool methodsFor: 'thumbnail' stamp: 'dgd 9/22/2004 19:28'!\\nicon\\n\\t\\\"Answer a form with an icon to represent the receiver\\\"\\n\\t^ MenuIcons objectCatalogIcon! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nObjectsTool class\\n\\tinstanceVariableNames: ''!\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:45'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:47'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(ObjectsTool\\t\\t\\tnewStandAlone\\t\\t\\t\\t'Object Catalog'\\t\\t'A tool that lets you browse the catalog of objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ObjectsTool\\t\\tnewStandAlone\\t\\t\\t\\t'Object Catalog'\\t\\t'A tool that lets you browse the catalog of objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.]! !\\n\\n!ObjectsTool class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:37'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!ObjectsTool class methodsFor: 'parts bin' stamp: 'sw 8/11/2001 20:16'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Objects'\\n\\t\\tcategories:\\t\\t#('Useful')\\n\\t\\tdocumentation:\\t'A place to obtain many kinds of objects'! !\\nOldSocket subclass: #OldSimpleClientSocket\\n\\tinstanceVariableNames: 'buffer bufferPos'\\n\\tclassVariableNames: 'CR CrLf LF'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!OldSimpleClientSocket commentStamp: '<historical>' prior: 0!\\nThis class supports client for simple network protocols based on sending textual commands and responses. Examples of such protocols include POP3 (mail retrieval), SMTP (mail posting), HTTP (web browsing), and NTTP (network news). Some simple examples are presented as class methods, but a full-service client of some service should be implemented as a subclass.\\n\\nThe basic services provided by this class are:\\n\\tsendCommand:\\t\\t\\t-- sends a command line terminate with <CR><LF>\\n\\tgetResponse\\t\\t\\t\\t-- gets a single-line response to a command\\n\\tgetMultilineResponse\\t-- gets a multiple line response terminated by a period\\n\\t\\t\\t\\t\\t\\t\\t-- on a line by itself\\n\\nThere are variants of the getResponse commands that display lines on the screen as they are being received. Linefeeds are stripped out of all responses.\\n\\nThe 'get' commands above make use of an internal buffer. So intermixing these two commands and regular Socket recieve commands can cause problems.!\\n\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'di 4/13/1999 14:43'!\\ndisplayString: aString\\n\\t\\\"Display the given string on the Display. Used for testing.\\\"\\n\\n\\t| s |\\n\\taString isEmpty ifTrue: [^ self].\\n\\taString size > 60\\n\\t\\tifTrue: [s _ aString copyFrom: 1 to: 60] \\\"limit to 60 characters\\\"\\n\\t\\tifFalse: [s _ aString].\\n\\n\\ts displayOn: Display.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/15/97 15:43'!\\ngetMultilineResponse\\n\\t\\\"Get a multiple line response to the last command, filtering out LF characters. A multiple line response ends with a line containing only a single period (.) character.\\\"\\n\\n\\t^ self getMultilineResponseShowing: false.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 03:34'!\\ngetMultilineResponseShowing: showFlag\\n\\t\\\"Get a multiple line response to the last command. A multiple line response ends with a line containing only a single period (.) character. Linefeed characters are filtered out. If showFlag is true, each line is shown in the upper-left corner of the Display as it is received.\\\"\\n\\n\\t| response done chunk |\\n\\tresponse _ WriteStream on: ''.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tshowFlag\\n\\t\\t\\tifTrue: [chunk _ self getResponseShowing: true]\\n\\t\\t\\tifFalse: [chunk _ self getResponse].\\n\\t\\t(chunk beginsWith: '.')\\n\\t\\t\\tifTrue: [ response nextPutAll: (chunk copyFrom: 2 to: chunk size) ]\\n\\t\\t\\tifFalse: [ response nextPutAll: chunk ].\\n\\t\\tdone _ (chunk = ('.', String cr)) ].\\n\\n\\t^ response contents\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 02:10'!\\ngetResponse\\n\\t\\\"Get a one-line response from the server. The final LF is removed from the line, but the CR is left, so that the line is in Squeak's text format\\\"\\n\\n\\t^ self getResponseShowing: false\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'ls 9/11/1998 03:27'!\\ngetResponseShowing: showFlag\\n\\n\\t| line idx |\\n\\tline _ WriteStream on: String new.\\n\\n\\tbuffer ifNil: [\\n\\t\\tbuffer _ String new.\\n\\t\\tbufferPos _ 0 ].\\n\\n\\t[\\n\\t\\t\\\"look for a LF in the buffer\\\"\\n\\t\\tidx _ buffer indexOf: Character lf startingAt: bufferPos+1 ifAbsent: [ 0 ].\\n\\t\\tidx > 0 ifTrue: [\\n\\t\\t\\t\\\"found it!! we have a line\\\"\\n\\t\\t\\tline nextPutAll: (buffer copyFrom: bufferPos+1 to: idx-1).\\n\\t\\t\\tbufferPos _ idx.\\n\\t\\t\\t^line contents ].\\n\\t\\t\\n\\t\\t\\\"didn't find it. add the whole buffer to the line, and retrieve some more data\\\"\\n\\t\\tline nextPutAll: (buffer copyFrom: bufferPos+1 to: buffer size).\\n\\t\\tbufferPos _ 0.\\n\\t\\tbuffer _ String new.\\n\\t\\tself waitForDataQueryingUserEvery: 30.\\n\\t\\tbuffer _ self getData.\\n\\n\\t\\ttrue\\n\\t] whileTrue.! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/17/97 16:00'!\\nsendCommand: commandString\\n\\t\\\"Send the given command as a single line followed by a <CR><LF> terminator.\\\"\\n\\n\\tself sendData: commandString, CrLf.\\n! !\\n\\n!OldSimpleClientSocket methodsFor: 'as yet unclassified' stamp: 'jm 9/16/1998 14:37'!\\nwaitForDataQueryingUserEvery: seconds\\n\\t\\\"Wait for data to arrive, asking the user periodically if they wish to keep waiting. If they don't wish to keep waiting, destroy the socket and raise an error.\\\"\\n\\n\\t| gotData |\\n\\tgotData _ false.\\n\\t[gotData]\\n\\t\\twhileFalse: [\\n\\t\\t\\tgotData _ self waitForDataUntil: (Socket deadlineSecs: seconds).\\n\\t\\t\\tgotData ifFalse: [\\n\\t\\t\\t\\tself isConnected ifFalse: [\\n\\t\\t\\t\\t\\tself destroy.\\n\\t\\t\\t\\t\\tself error: 'server closed connection'].\\n\\t\\t\\t\\t(self confirm: 'server not responding; keep trying?')\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\tself destroy.\\n\\t\\t\\t\\t\\t\\tself error: 'no response from server']]].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOldSimpleClientSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!OldSimpleClientSocket class methodsFor: 'class initialization' stamp: 'jm 9/15/97 11:42'!\\ninitialize\\n\\t\\\"SimpleClientSocket initialize\\\"\\n\\n\\tCR _ Character cr.\\n\\tLF _ Character linefeed.\\n\\n\\t\\\"string for command line termination:\\\"\\n\\tCrLf _ String with: CR with: LF.\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'mir 5/13/2003 10:45'!\\nnntpTest\\n\\t\\\"SimpleClientSocket nntpTest\\\"\\n\\n\\t| addr s headers msgs header allNewsGroups |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 119. \\\"119 is the NNTP port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'group comp.lang.smalltalk'.\\n\\tTranscript show: s getResponse.\\n\\n\\t\\\"get all the message headers for the current newsgroup\\\"\\n\\ts sendCommand: 'xover 1-1000000'.\\n\\theaders _ s getMultilineResponseShowing: true.\\n\\n\\t\\\"print the headers of the first 10 messages of comp.lang.smalltalk\\\"\\n\\ts sendCommand: 'listgroup comp.lang.smalltalk'.\\n\\tmsgs _ self parseIntegerList: s getMultilineResponse.\\n\\tmsgs ifNotNil: [\\n\\t\\t1 to: 5 do: [:i |\\n\\t\\t\\ts sendCommand: 'head ', (msgs at: i) printString.\\n\\t\\t\\theader _ s getMultilineResponse.\\n\\t\\t\\tTranscript show: (self extractDateFromAndSubjectFromHeader: header); cr]].\\n\\n\\t\\\"get a full list of usenet newsgroups\\\"\\n\\ts sendCommand: 'newgroups 010101 000000'.\\n\\tallNewsGroups _ s getMultilineResponse.\\n\\tTranscript show: allNewsGroups size printString, ' bytes in full newsgroup list'; cr.\\n\\n\\tTranscript show: 'Sending quit...'; cr.\\n\\ts sendCommand: 'QUIT'.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n\\n\\t(headers ~~ nil and:\\n\\t [self confirm: 'show article headers from comp.lang.smalltalk?'])\\n\\t\\tifTrue: [\\n\\t\\t\\t(StringHolder new contents: (self parseHeaderList: headers))\\n\\t\\t\\t\\topenLabel: 'Newsgroup Headers'].\\n\\n\\t(allNewsGroups ~~ nil and:\\n\\t [self confirm: 'show list of all newsgroups available on your server?'])\\n\\t\\tifTrue: [\\n\\t\\t\\t(StringHolder new contents: allNewsGroups)\\n\\t\\t\\t\\topenLabel: 'All Usenet Newsgroups'].\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:25'!\\nparseHeaderList: aString\\n\\t\\\"Parse a list of newsgroup headers.\\\"\\n\\n\\t| results s lineStart |\\n\\tresults _ WriteStream on: (String new: aString size).\\n\\ts _ ReadStream on: aString.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tlineStart _ s position + 1.\\n\\t\\t\\t3 timesRepeat: [s skipTo: Character tab]. \\\"find fourth tab\\\"\\n\\t\\t\\tlineStart to: s position - 1 do: [:i | results nextPut: (aString at: i)].\\n\\t\\t\\tresults cr.\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ results contents\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:26'!\\nparseIntegerList: aString\\n\\t\\\"Parse a list of integers, each on a line by itself.\\\"\\n\\n\\t| s out |\\n\\ts _ ReadStream on: aString.\\n\\ts skipTo: Character cr. \\\"skip the first line\\\"\\n\\tout _ OrderedCollection new.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tout addLast: (Integer readFrom: s).\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ out asArray\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'net news example' stamp: 'jm 9/15/97 13:26'!\\nparseNTTPMsgList: aString\\n\\t\\\"Parse a list of integers, each on a line by itself.\\\"\\n\\n\\t| s out |\\n\\ts _ ReadStream on: aString.\\n\\ts skipTo: Character cr. \\\"skip the first line\\\"\\n\\tout _ OrderedCollection new.\\n\\t[s atEnd]\\n\\t\\twhileFalse: [\\n\\t\\t\\tout addLast: (Integer readFrom: s).\\n\\t\\t\\ts skipTo: Character cr].\\n\\t^ out asArray\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\nfinger: userName\\n\\t\\\"OldSimpleClientSocket finger: 'stp'\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 79. \\\"finger port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\ts sendCommand: userName.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\nhttpTestHost: hostName port: port url: url\\n\\t\\\"This test fetches a URL from the given host and port.\\\"\\n\\t\\\"SimpleClientSocket httpTestHost: 'www.disney.com' port: 80 url: '/'\\\"\\n\\t\\\"Tests URL fetch through a local HTTP proxie server:\\n\\t\\t(SimpleClientSocket\\n\\t\\t\\thttpTestHost: '127.0.0.1'\\n\\t\\t\\tport: 8080\\n\\t\\t\\turl: 'HTTP://www.exploratorium.edu/index.html')\\\"\\n\\n\\t| hostAddr s result buf bytes totalBytes t |\\n\\tTranscript cr; show: 'starting http test'; cr.\\n\\tSocket initializeNetwork.\\n\\thostAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\thostAddr = nil ifTrue: [^ self inform: 'Could not find an address for ', hostName].\\n\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: hostAddr port: port.\\n\\ts waitForConnectionUntil: \\\"self standardDeadline\\\" (Socket deadlineSecs: 10).\\n\\t(s isConnected) ifFalse: [\\n\\t\\ts destroy.\\n\\t\\t^ self inform: 'could not connect'].\\n\\tTranscript show: 'connection open; waiting for data'; cr.\\n\\n\\ts sendCommand: 'GET ', url, ' HTTP/1.0'.\\n\\ts sendCommand: 'User-Agent: Squeak 1.19'.\\n\\ts sendCommand: 'ACCEPT: text/html'.\\t\\\"always accept plain text\\\"\\n\\ts sendCommand: 'ACCEPT: application/octet-stream'. \\\"also accept binary data\\\"\\n\\ts sendCommand: ''. \\\"blank line\\\"\\n\\n\\tresult _ WriteStream on: (String new: 10000).\\n\\tbuf _ String new: 10000.\\n\\ttotalBytes _ 0.\\n\\tt _ Time millisecondsToRun: [\\n\\t\\t[s isConnected] whileTrue: [\\n\\t\\t\\ts waitForDataUntil: (Socket deadlineSecs: 5).\\n\\t\\t\\tbytes _ s receiveDataInto: buf.\\n\\t\\t\\t1 to: bytes do: [:i | result nextPut: (buf at: i)].\\n\\t\\t\\ttotalBytes _ totalBytes + bytes.\\n\\t\\t\\tTranscript show: totalBytes printString, ' bytes received'; cr]].\\n\\n\\ts destroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n\\tTranscript show: 'http test done; ', totalBytes printString, ' bytes read in '.\\n\\tTranscript show: ((t / 1000.0) roundTo: 0.01) printString, ' seconds'; cr.\\n\\tTranscript show: ((totalBytes asFloat / t) roundTo: 0.01) printString, ' kBytes/sec'; cr.\\n\\tTranscript endEntry.\\n\\t(StringHolder new contents: (result contents))\\n\\t\\topenLabel: 'HTTP Test Result: URL Contents'.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'other examples' stamp: 'mir 5/13/2003 10:45'!\\ntimeTest\\n\\t\\\"SimpleClientSocket timeTest\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 13. \\\"time port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'jm 9/15/97 14:47'!\\nextractDateFromAndSubjectFromHeader: headerString\\n\\n\\t| date from subject s lineBuf c line i |\\n\\tdate _ from _ subject _ ''.\\n\\ts _ ReadStream on: headerString.\\n\\tlineBuf _ WriteStream on: ''.\\n\\t[s atEnd] whileFalse: [\\n\\t\\tc _ s next.\\n\\t\\tc = CR\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tline _ lineBuf contents.\\n\\t\\t\\t\\t(line beginsWith: 'Date: ')\\tifTrue: [date _ line copyFrom: 7 to: line size].\\n\\t\\t\\t\\t(line beginsWith: 'From: ')\\tifTrue: [from _ line copyFrom: 7 to: line size].\\n\\t\\t\\t\\t(line beginsWith: 'Subject: ')\\tifTrue: [subject _ line copyFrom: 10 to: line size].\\n\\t\\t\\t\\tlineBuf _ WriteStream on: '']\\n\\t\\t\\tifFalse: [lineBuf nextPut: c]].\\n\\n\\ti _ date indexOf: $' ifAbsent: [0].\\n\\tdate _ date copyFrom: i + 1 to: date size.\\n\\t^ (self simpleDateString: date), ', ', from, ':\\n ', subject\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'rbb 3/1/2005 11:02'!\\npopTest\\n\\t\\\"SimpleClientSocket popTest\\\"\\n\\n\\t| addr userName userPassword s msgs header |\\n\\taddr := NetNameResolver promptUserForHostAddress.\\n\\tuserName := UIManager default\\n\\t\\trequest: 'What is your email name?'\\n\\t\\tinitialAnswer: 'johnm'.\\n\\tuserPassword := UIManager default\\n\\t\\trequest: 'What is your email password?'.\\n\\n\\ts := OldSimpleClientSocket new.\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts connectTo: addr port: 110. \\\"110 is the POP3 port number\\\"\\n\\ts waitForConnectionUntil: self standardDeadline.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'USER ', userName.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'PASS ', userPassword.\\n\\tTranscript show: s getResponse.\\n\\ts sendCommand: 'LIST'.\\n\\n\\t\\\"the following should be tweaked to handle an empy mailbox:\\\"\\n\\tmsgs := self parseIntegerList: s getMultilineResponse.\\n\\n\\t1 to: (msgs size min: 5) do: [ :i |\\n\\t\\ts sendCommand: 'TOP ', (msgs at: i) printString, ' 0'.\\n\\t\\theader := s getMultilineResponse.\\n\\t\\tTranscript show: (self extractDateFromAndSubjectFromHeader: header); cr].\\n\\n\\tmsgs size > 0 ifTrue: [\\n\\t\\t\\\"get the first message\\\"\\n\\t\\ts sendCommand: 'RETR 1'.\\n\\t\\tTranscript show: s getMultilineResponse].\\n\\n\\tTranscript show: 'closing connection'; cr.\\n\\ts sendCommand: 'QUIT'.\\n\\ts closeAndDestroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'POP mail example' stamp: 'tk 4/10/1998 06:47'!\\nsimpleDateString: dateString\\n\\n\\t| s |\\n\\ts _ ReadStream on: dateString.\\n\\ts skipTo: $,. \\\"scan thru first comma\\\"\\n\\ts atEnd ifTrue: [s reset]. \\\"no comma found; reset s\\\"\\n\\ts skipSeparators.\\n\\t^ (Date readFrom: s) mmddyyyy\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'queries' stamp: 'jm 2/26/98 09:50'!\\ncrLf\\n\\n\\t^ CrLf\\n! !\\n\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nforkingRemoteCursorSender\\n\\t\\\"This is the client side of a test that sends samples of the local input sensor state to the server, which may be running on a local or remote host. This method opens the connection, then forks a process to send the cursor data. Data is sent continuously until the user clicks in a 20x20 pixel square at the top-left corner of the display. The server should be started first. Note the server's address, since this method will prompt you for it.\\\"\\n\\t\\\"SimpleClientSocket forkingRemoteCursorSender\\\"\\n\\n\\t| sock addr stopRect |\\n\\tTranscript show: 'starting remote cursor sender'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock _ OldSimpleClientSocket new.\\n\\tsock connectTo: addr port: 54323.\\n\\tsock waitForConnectionUntil: self standardDeadline.\\n\\t(sock isConnected) ifFalse: [self error: 'sock not connected'].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\tstopRect _ 0@0 corner: 20@20. \\\"click in this rectangle to stop sending\\\"\\n\\tDisplay reverse: stopRect.\\n\\t[\\\"the sending process\\\"\\n\\t\\t[(stopRect containsPoint: Sensor cursorPoint) and:\\n\\t\\t [Sensor anyButtonPressed]]\\n\\t\\t\\twhileFalse: [\\n\\t\\t\\t\\tsock sendCommand: self sensorStateString.\\n\\t\\t\\t\\t(Delay forMilliseconds: 20) wait].\\n\\n\\t\\tsock waitForSendDoneUntil: self standardDeadline.\\n\\t\\tsock destroy.\\n\\t\\tTranscript show: 'remote cursor sender done'; cr.\\n\\t\\tDisplay reverse: stopRect.\\n\\t] fork.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'jm 9/15/97 14:49'!\\nparseSensorStateString: aString\\n\\t\\\"Parse the given sensor stat string and return an array whose first element is the cursor point and whose second is the cursor button state.\\\"\\n\\t\\\"SimpleClientSocket parseSensorStateString: SimpleClientSocket sensorStateString\\\"\\n\\n\\t| s buttons x y |\\n\\ts _ ReadStream on: aString.\\n\\tx _ Integer readFrom: s.\\n\\ts skipSeparators.\\n\\ty _ Integer readFrom: s.\\n\\ts skipSeparators.\\n\\tbuttons _ Integer readFrom: s.\\n\\t^ Array with: x@y with: buttons\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nremoteCursorReceiver\\n\\t\\\"Wait for a connection, then display data sent by the client until the client closes the stream. This server process is usually started first (optionally in a forked process), then the sender process is started (optionally on another machine). Note this machine's address, which is printed in the transcript, since the sender process will ask for it.\\\"\\n\\t\\\"[SimpleClientSocket remoteCursorReceiver] fork\\\"\\n\\n\\t| sock response |\\n\\tTranscript show: 'starting remote cursor receiver'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\tTranscript show: 'my address is ', NetNameResolver localAddressString; cr.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock _ OldSimpleClientSocket new.\\n\\tsock listenOn: 54323.\\n\\tsock waitForConnectionUntil: (Socket deadlineSecs: 60).\\n\\tsock isConnected\\n\\t\\tifFalse: [\\n\\t\\t\\t sock destroy.\\n\\t\\t\\tTranscript show: 'remote cursor receiver did not receive a connection in 60 seconds; aborting.'.\\n\\t\\t\\t^ self].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\t[sock isConnected]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsock dataAvailable\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tresponse _ sock getResponse.\\n\\t\\t\\t\\t\\tresponse displayOn: Display at: 10@10]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\\"if no data available, let other processes run for a while\\\"\\n\\t\\t\\t\\t\\t(Delay forMilliseconds: 20) wait]].\\n\\n\\tsock destroy.\\n\\tTranscript show: 'remote cursor receiver done'; cr.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'mir 5/13/2003 10:45'!\\nremoteCursorTest\\n\\t\\\"This version of the remote cursor test runs both the client and the server code in the same loop.\\\"\\n\\t\\\"SimpleClientSocket remoteCursorTest\\\"\\n\\n\\t| sock1 sock2 samplesToSend samplesSent done t |\\n\\tTranscript show: 'starting remote cursor test'; cr.\\n\\tTranscript show: 'initializing network'; cr.\\n\\tSocket initializeNetwork.\\n\\tTranscript show: 'opening connection'; cr.\\n\\tsock1 _ OldSimpleClientSocket new.\\n\\tsock2 _ OldSimpleClientSocket new.\\n\\tsock1 listenOn: 54321.\\n\\tsock2 connectTo: (NetNameResolver localHostAddress) port: 54321.\\n\\tsock1 waitForConnectionUntil: self standardDeadline.\\n\\tsock2 waitForConnectionUntil: self standardDeadline.\\n\\t(sock1 isConnected) ifFalse: [self error: 'sock1 not connected'].\\n\\t(sock2 isConnected) ifFalse: [self error: 'sock2 not connected'].\\n\\tTranscript show: 'connection established'; cr.\\n\\n\\tsamplesToSend _ 100.\\n\\tt _ Time millisecondsToRun: [\\n\\t\\tsamplesSent _ 0.\\n\\t\\tdone _ false.\\n\\t\\t[done]\\n\\t\\t\\twhileFalse: [\\n\\t\\t\\t\\t(sock1 sendDone and: [samplesSent < samplesToSend]) ifTrue: [\\n\\t\\t\\t\\t\\tsock1 sendCommand: self sensorStateString.\\n\\t\\t\\t\\t\\tsamplesSent _ samplesSent + 1].\\n\\t\\t\\t\\tsock2 dataAvailable ifTrue: [\\n\\t\\t\\t\\t\\tsock2 getResponse displayOn: Display at: 10@10].\\n\\t\\t\\t\\tdone _ samplesSent = samplesToSend]].\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript show: 'remote cursor test done'; cr.\\n\\tTranscript show:\\n\\t\\tsamplesSent printString, ' samples sent in ',\\n\\t\\tt printString, ' milliseconds'; cr.\\n\\tTranscript show: ((samplesSent * 1000) // t) printString, ' samples/sec'; cr.\\n! !\\n\\n!OldSimpleClientSocket class methodsFor: 'remote cursor example' stamp: 'jm 9/15/97 13:11'!\\nsensorStateString\\n\\t\\\"SimpleClientSocket sensorStateString\\\"\\n\\n\\t| pt buttons s |\\n\\tpt _ Sensor cursorPoint.\\n\\tbuttons _ Sensor primMouseButtons.\\n\\ts _ WriteStream on: (String new: 100).\\n\\ts nextPutAll: pt x printString.\\n\\ts space.\\n\\ts nextPutAll: pt y printString.\\n\\ts space.\\n\\ts nextPutAll: buttons printString.\\n\\t^ s contents\\n! !\\nObject subclass: #OldSocket\\n\\tinstanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore primitiveOnlySupportsOneSemaphore'\\n\\tclassVariableNames: 'Connected DeadServer InvalidSocket OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!OldSocket commentStamp: '<historical>' prior: 0!\\nA Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols\\n\\nSubclasses of socket provide support for network protocols such as POP, NNTP, HTTP, and FTP. Sockets also allow you to implement your own custom services and may be used to support Remote Procedure Call or Remote Method Invocation some day.\\n\\nJMM June 2nd 2000 Macintosh UDP support was added if you run open transport.\\n!\\n]style[(196 4 6 3 228)f1,f1LHTTPSocket Comment;,f1,f1LFTPSocket Comment;,f1!\\n\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\naddress\\n\\t\\\"Shortcut\\\"\\n\\t^self localAddress! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'nk 2/24/2005 14:37'!\\nlocalAddress\\n\\tself waitForConnectionUntil: self class standardDeadline.\\n\\tself isConnected ifFalse: [^ByteArray new: 4].\\n\\t^self primSocketLocalAddress: socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'nk 2/24/2005 14:37'!\\nlocalPort\\n\\tself waitForConnectionUntil: self class standardDeadline.\\n\\tself isConnected ifFalse: [^0].\\n\\t^self primSocketLocalPort: socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 3/13/98 12:11'!\\npeerName\\n\\t\\\"Return the name of the host I'm connected to, or nil if its name isn't known to the domain name server or the request times out.\\\"\\n\\t\\\"Note: Slow. Calls the domain name server, taking up to 20 seconds to time out. Even when sucessful, delays of up to 13 seconds have been observed during periods of high network load.\\\" \\n\\n\\t^ NetNameResolver\\n\\t\\tnameForAddress: self remoteAddress\\n\\t\\ttimeout: 20\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\nport\\n\\t\\\"Shortcut\\\"\\n\\t^self localPort! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 6/5/2000 10:12'!\\nprimitiveOnlySupportsOneSemaphore\\n\\t^primitiveOnlySupportsOneSemaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nreadSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^readSemaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremoteAddress\\n\\n\\t^ self primSocketRemoteAddress: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremotePort\\n\\n\\t^ self primSocketRemotePort: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/9/2000 15:32'!\\nsemaphore\\n\\t^semaphore! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'ar 7/16/1999 17:22'!\\nsocketHandle\\n\\t^socketHandle! !\\n\\n!OldSocket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nwriteSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^writeSemaphore! !\\n\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'nk 2/24/2005 14:37'!\\naccept\\n\\t\\\"Accept a connection from the receiver socket.\\n\\tReturn a new socket that is connected to the client\\\"\\n\\n\\t^self class acceptFrom: self! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 9/11/97 20:29'!\\nclose\\n\\t\\\"Close this connection gracefully. For TCP, this sends a close request, but the stream remains open until the other side also closes it.\\\"\\n\\n\\tself primSocketCloseConnection: socketHandle. \\\"close this end\\\"\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 11/4/97 07:15'!\\ncloseAndDestroy\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tself closeAndDestroy: 20.\\n\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'nk 2/24/2005 14:37'!\\ncloseAndDestroy: timeoutSeconds \\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil \\n\\t\\tifFalse: \\n\\t\\t\\t[self isConnected \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self close.\\t\\\"close this end\\\"\\n\\t\\t\\t\\t\\t(self waitForDisconnectionUntil: (self class deadlineSecs: timeoutSeconds)) \\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"if the other end doesn't close soon, just abort the connection\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tself primSocketAbortConnection: socketHandle]].\\n\\t\\t\\tself destroy]! !\\n\\n!OldSocket methodsFor: 'connection open/close'!\\nconnectTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address. This operation will return immediately; follow it with waitForConnectionUntil: to wait until the connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before opening a new connection'].\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'jm 3/10/98 11:56'!\\ndisconnect\\n\\t\\\"Break this connection, no matter what state it is in. Data that has been sent but not received will be lost.\\\"\\n\\n\\tself primSocketAbortConnection: socketHandle.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close'!\\nlistenOn: port\\n\\t\\\"Listen for a connection on the given port. This operation will return immediately; follow it with waitForConnectionUntil: to wait until a connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\n\\tself primSocket: socketHandle listenOn: port.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'ar 7/16/1999 18:26'!\\nlistenOn: portNumber backlogSize: backlog\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog.\\n! !\\n\\n!OldSocket methodsFor: 'connection open/close' stamp: 'ikp 9/1/2003 20:47'!\\nlistenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [self error: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog interface: ifAddr.\\n! !\\n\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 6/7/2000 14:58'!\\nreceiveDataInto: aStringOrByteArray fromHost: hostAddress port: portNumber\\n\\t| datagram |\\n\\t\\\"Receive a UDP packet from the given hostAddress/portNumber, storing the data in the given buffer, and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self receiveDataInto: aStringOrByteArray].\\n\\t[true] whileTrue: \\n\\t\\t[datagram _ self receiveUDPDataInto: aStringOrByteArray.\\n\\t\\t((datagram at: 2) = hostAddress and: [(datagram at: 3) = portNumber]) \\n\\t\\t\\tifTrue: [^datagram at: 1]\\n\\t\\t\\tifFalse: [^0]]! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 6/3/2000 21:54'!\\nreceiveUDPDataInto: aStringOrByteArray\\n\\t\\\"Receive UDP data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data. What is returned is an array, the first element is the bytes read, the second the sending bytearray address, the third the senders port, the fourth, true if more of the datagram awaits reading\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveUDPDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'JMM 5/25/2000 00:05'!\\nsendData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self sendData: aStringOrByteArray].\\n\\t^self sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'nk 2/24/2005 14:37'!\\nsendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber \\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\t| bytesToSend bytesSent count |\\n\\tbytesToSend := aStringOrByteArray size.\\n\\tbytesSent := 0.\\n\\t[bytesSent < bytesToSend] whileTrue: \\n\\t\\t\\t[(self waitForSendDoneUntil: (self class deadlineSecs: 20)) \\n\\t\\t\\t\\tifFalse: [self error: 'send data timeout; data not sent'].\\n\\t\\t\\tcount := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\tsendUDPData: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\ttoHost: hostAddress\\n\\t\\t\\t\\t\\t\\tport: portNumber\\n\\t\\t\\t\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\t\\t\\t\\tcount: bytesToSend - bytesSent.\\n\\t\\t\\tbytesSent := bytesSent + count].\\n\\t^bytesSent! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPeer: hostAddress port: port\\n\\t\\\"Set the default send/recv address.\\\"\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!OldSocket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPort: port\\n\\t\\\"Associate a local port number with a UDP socket. Not applicable to TCP sockets.\\\"\\n\\n\\tself primSocket: socketHandle setPort: port.\\n! !\\n\\n\\n!OldSocket methodsFor: 'finalization' stamp: 'JMM 5/22/2000 22:52'!\\nfinalize\\n\\tself primSocketDestroyGently: socketHandle.\\n\\tSmalltalk unregisterExternalObject: semaphore.\\n\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n! !\\n\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:47'!\\nacceptFrom: aSocket\\n\\t\\\"Initialize a new socket handle from an accept call\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _ self primAcceptFrom: aSocket socketHandle\\n\\t\\t\\t\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\t\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\t\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\t\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\t\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:54'!\\ndestroy\\n\\t\\\"Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil ifFalse: \\n\\t\\t[self isValid ifTrue: [self primSocketDestroy: socketHandle].\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\tsocketHandle _ nil.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil.\\n\\t\\tself unregister].\\n! !\\n\\n!OldSocket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 23:04'!\\ninitialize: socketType\\n\\t\\\"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil.\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _\\n\\t\\tself primSocketCreateNetwork: 0\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n\\n!OldSocket methodsFor: 'other' stamp: 'JMM 6/3/2000 19:39'!\\ngetOption: aName \\n\\t\\\"Get options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is an status number (0 ok, -1 read only option)\\n\\telement two is the resulting of the requested option\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [self error: 'Socket status must valid before getting an option'].\\n\\t^self primSocket: socketHandle getOption: aName\\n\\n\\\"| foo options |\\nSocket initializeNetwork.\\nfoo _ Socket newTCP.\\nfoo connectTo: (NetNameResolver addressFromString: '192.168.1.1') port: 80.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\noptions _ {\\n'SO_DEBUG'. 'SO_REUSEADDR'. 'SO_REUSEPORT'. 'SO_DONTROUTE'.\\n'SO_BROADCAST'. 'SO_SNDBUF'. 'SO_RCVBUF'. 'SO_KEEPALIVE'.\\n'SO_OOBINLINE'. 'SO_PRIORITY'. 'SO_LINGER'. 'SO_RCVLOWAT'.\\n'SO_SNDLOWAT'. 'IP_TTL'. 'IP_HDRINCL'. 'IP_RCVOPTS'.\\n'IP_RCVDSTADDR'. 'IP_MULTICAST_IF'. 'IP_MULTICAST_TTL'.\\n'IP_MULTICAST_LOOP'. 'UDP_CHECKSUM'. 'TCP_MAXSEG'.\\n'TCP_NODELAY'. 'TCP_ABORT_THRESHOLD'. 'TCP_CONN_NOTIFY_THRESHOLD'. \\n'TCP_CONN_ABORT_THRESHOLD'. 'TCP_NOTIFY_THRESHOLD'.\\n'TCP_URGENT_PTR_TYPE'}.\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\nfoo _ Socket newUDP.\\nfoo setPeer: (NetNameResolver addressFromString: '192.168.1.9') port: 7.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\\"! !\\n\\n!OldSocket methodsFor: 'other' stamp: 'nk 2/24/2005 14:37'!\\ngetResponseNoLF\\n\\t\\\"Get the response to the last command.\\\"\\n\\n\\t| buf response bytesRead c lf |\\n\\t(self waitForDataUntil: (self class deadlineSecs: 20)) \\n\\t\\tifFalse: [self error: 'getResponse timeout'].\\n\\tlf := Character lf.\\n\\tbuf := String new: 1000.\\n\\tresponse := WriteStream on: ''.\\n\\t[self dataAvailable] whileTrue: \\n\\t\\t\\t[bytesRead := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\treceiveDataInto: buf\\n\\t\\t\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\t\\t\\tcount: buf size.\\n\\t\\t\\t1 to: bytesRead\\n\\t\\t\\t\\tdo: [:i | (c := buf at: i) ~= lf ifTrue: [response nextPut: c]]].\\n\\t^response contents! !\\n\\n!OldSocket methodsFor: 'other' stamp: 'JMM 6/3/2000 19:39'!\\nsetOption: aName value: aValue \\n\\t| value |\\n\\t\\\"setup options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is the error number\\n\\telement two is the resulting of the negotiated value.\\n\\tSee getOption for list of keys\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [self error: 'Socket status must valid before setting an option'].\\n\\tvalue _ aValue asString.\\n\\taValue == true ifTrue: [value _ '1'].\\n\\taValue == false ifTrue: [value _ '0'].\\n\\t^ self primSocket: socketHandle setOption: aName value: value! !\\n\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept' module: 'SocketPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:55'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^self primAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex ! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID connectTo: hostAddress port: port\\n\\t\\\"Attempt to establish a connection to the given port of the given host. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectToPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 21:48'!\\nprimSocket: socketID getOption: aString \\n\\t\\\"Get some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the option value\\\"\\n\\n\\t<primitive: 'primitiveSocketGetOptions' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID listenOn: port\\n\\t\\\"Listen for a connection on the given port. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ikp 9/1/2003 20:55'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenOnPortBacklogInterface' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID receiveDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. Return the number of bytes read or zero if no data is available.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/24/2000 17:19'!\\nprimSocket: socketID receiveUDPDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. \\n\\tReturn an Array containing the amount read, the host address byte array, the host port, and the more flag\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID sendData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 00:08'!\\nprimSocket: socketID sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 7/18/2000 11:42'!\\nprimSocket: socketID setOption: aString value: aStringValue\\n\\t\\\"Set some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the negotiated value\\\"\\n\\n\\t<primitive: 'primitiveSocketSetOptions' module: 'SocketPlugin'>\\n\\t^nil! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID setPort: port\\n\\t\\\"Set the local port associated with a UDP socket.\\n\\tNote: this primitive is overloaded. The primitive will not fail on a TCP socket, but\\n\\tthe effects will not be what was desired. Best solution would be to split Socket into\\n\\ttwo subclasses, TCPSocket and UDPSocket.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketAbortConnection: socketID\\n\\t\\\"Terminate the connection on the given port immediately without going through the normal close sequence. This is an asynchronous call; query the socket status to discover if and when the connection is actually terminated.\\\"\\n\\n\\t<primitive: 'primitiveSocketAbortConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCloseConnection: socketID\\n\\t\\\"Close the connection on the given port. The remote end is informed that this end has closed and will do no further sends. This is an asynchronous call; query the socket status to discover if and when the connection is actually closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCloseConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketConnectionStatus: socketID\\n\\t\\\"Return an integer reflecting the connection status of this socket. For a list of possible values, see the comment in the 'initialize' method of this class. If the primitive fails, return a status indicating that the socket handle is no longer valid, perhaps because the Squeak image was saved and restored since the socket was created. (Sockets do not survive snapshots.)\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectionStatus' module: 'SocketPlugin'>\\n\\t^ InvalidSocket\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex\\n\\t\\\"Return a new socket handle for a socket of the given type and buffer sizes. Return nil if socket creation fails.\\n\\tThe netType parameter is platform dependent and can be used to encode both the protocol type (IP, Xerox XNS, etc.) and/or the physical network interface to use if this host is connected to multiple networks. A zero netType means to use IP protocols and the primary (or only) network interface.\\n\\tThe socketType parameter specifies:\\n\\t\\t0\\treliable stream socket (TCP if the protocol is IP)\\n\\t\\t1\\tunreliable datagram socket (UDP if the protocol is IP)\\n\\tThe buffer size parameters allow performance to be tuned to the application. For example, a larger receive buffer should be used when the application expects to be receiving large amounts of data, especially from a host that is far away. These values are considered requests only; the underlying implementation will ensure that the buffer sizes actually used are within allowable bounds. Note that memory may be limited, so an application that keeps many sockets open should use smaller buffer sizes. Note the macintosh implementation ignores this buffer size. Also see setOption to get/set socket buffer sizes which allows you to set/get the current buffer sizes for reading and writing.\\n \\tIf semaIndex is > 0, it is taken to be the index of a Semaphore in the external objects array to be associated with this socket. This semaphore will be signalled when the socket status changes, such as when data arrives or a send completes. All processes waiting on the semaphore will be awoken for each such event; each process must then query the socket state to figure out if the conditions they are waiting for have been met. For example, a process waiting to send some data can see if the last send has completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate' module: 'SocketPlugin'>\\n\\t^ nil \\\"socket creation failed\\\"\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:48'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"See comment in primSocketCreateNetwork: with one semaIndex. However you should know that some implementations\\n\\tignore the buffer size and this interface supports three semaphores, one for open/close/listen and the other two for\\n\\treading and writing\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^ self primSocketCreateNetwork: netType\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: rcvBufSize\\n\\t\\t\\tsendBufSize: sendBufSize\\n\\t\\t\\tsemaIndex: semaIndex! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroy: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroyGently: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\n\\tDo not fail if the receiver is already closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketError: socketID\\n\\t\\\"Return an integer encoding the most recent error on this socket. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveSocketError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalAddress: socketID\\n\\t\\\"Return the local host address for this socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalPort: socketID\\n\\t\\\"Return the local port for this socket, or zero if no port has yet been assigned.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketReceiveDataAvailable: socketID\\n\\t\\\"Return true if data may be available for reading from the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataAvailable' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemoteAddress: socketID\\n\\t\\\"Return the remote host address for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemoteAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemotePort: socketID\\n\\t\\\"Return the remote port for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemotePort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!OldSocket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketSendDone: socketID\\n\\t\\\"Return true if there is no send in progress on the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDone' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!OldSocket methodsFor: 'printing' stamp: 'jm 11/23/1998 11:57'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '[', self statusString, ']'.\\n! !\\n\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\ndataAvailable\\n\\t\\\"Return true if this socket has unread received data.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketReceiveDataAvailable: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\nisConnected\\n\\t\\\"Return true if this socket is connected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Connected\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:15'!\\nisOtherEndClosed\\n\\t\\\"Return true if this socket had the other end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == OtherEndClosed\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:17'!\\nisThisEndClosed\\n\\t\\\"Return true if this socket had the this end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == ThisEndClosed\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnected\\n\\t\\\"Return true if this socket's state is Unconnected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Unconnected\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnectedOrInvalid\\n\\t\\\"Return true if this socket is completely disconnected or is invalid.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ true].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ (status = Unconnected) | (status = InvalidSocket)\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:51'!\\nisValid\\n\\t\\\"Return true if this socket contains a valid, non-nil socket handle.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ status ~= InvalidSocket\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisWaitingForConnection\\n\\t\\\"Return true if this socket is waiting for a connection.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == WaitingForConnection\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nsendDone\\n\\t\\\"Return true if the most recent send operation on this socket has completed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketSendDone: socketHandle\\n! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'JMM 5/8/2000 23:24'!\\nsocketError\\n\\t^self primSocketError: socketHandle! !\\n\\n!OldSocket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:56'!\\nstatusString\\n\\t\\\"Return a string describing the status of this socket.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ 'destroyed'].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tstatus = InvalidSocket ifTrue: [^ 'invalidSocketHandle'].\\n\\tstatus = Unconnected ifTrue: [^ 'unconnected'].\\n\\tstatus = WaitingForConnection ifTrue: [^ 'waitingForConnection'].\\n\\tstatus = Connected ifTrue: [^ 'connected'].\\n\\tstatus = OtherEndClosed ifTrue: [^ 'otherEndClosedButNotThisEnd'].\\n\\tstatus = ThisEndClosed ifTrue: [^ 'thisEndClosedButNotOtherEnd'].\\n\\t^ 'unknown socket status'\\n! !\\n\\n\\n!OldSocket methodsFor: 'registry' stamp: 'ar 3/21/98 17:40'!\\nregister\\n\\t^self class register: self! !\\n\\n!OldSocket methodsFor: 'registry' stamp: 'ar 3/21/98 17:41'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'jm 9/15/97 12:22'!\\ndiscardReceivedData\\n\\t\\\"Discard any data received up until now, and return the number of bytes discarded.\\\"\\n\\n\\t| buf totalBytesDiscarded |\\n\\tbuf _ String new: 10000.\\n\\ttotalBytesDiscarded _ 0.\\n\\t[self isConnected and: [self dataAvailable]] whileTrue: [\\n\\t\\ttotalBytesDiscarded _\\n\\t\\t\\ttotalBytesDiscarded + (self receiveDataInto: buf)].\\n\\t^ totalBytesDiscarded\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\ngetData\\n\\t\\\"Get some data\\\"\\n\\n\\t| buf bytesRead |\\n\\t(self waitForDataUntil: self class standardDeadline) \\n\\t\\tifFalse: [self error: 'getData timeout'].\\n\\tbuf := String new: 4000.\\n\\tbytesRead := self \\n\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: buf\\n\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\tcount: buf size.\\n\\t^buf copyFrom: 1 to: bytesRead! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\nreadInto: aStringOrByteArray startingAt: aNumber \\n\\t\\\"Read data into the given buffer starting at the given index and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t(self waitForDataUntil: self class standardDeadline) \\n\\t\\tifFalse: [self error: 'receive timeout'].\\n\\t^self \\n\\t\\tprimSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size - aNumber + 1! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'jm 9/15/97 12:21'!\\nreceiveDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'tak 3/16/2005 16:51'!\\nsendData: aStringOrByteArray\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent.\\\"\\n\\n\\t\\\"An experimental version use on slow lines: Longer timeout and smaller writes to try to avoid spurious timeouts.\\\"\\n\\n\\t| bytesSent bytesToSend count |\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneUntil: (Socket deadlineSecs: 60))\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 5000).\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ar 7/20/1999 17:23'!\\nsendData: buffer count: n\\n\\t\\\"Send the amount of data from the given buffer\\\"\\n\\t| sent |\\n\\tsent _ 0.\\n\\t[sent < n] whileTrue:[\\n\\t\\tsent _ sent + (self sendSomeData: buffer startIndex: sent+1 count: (n-sent))].! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ls 1/5/1999 15:05'!\\nsendSomeData: aStringOrByteArray\\n\\t\\\"Send as much of the given data as possible and answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: 1\\n\\t\\tcount: aStringOrByteArray size! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'ls 3/3/1999 18:59'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex\\n\\t\\\"Send as much of the given data as possible starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: startIndex\\n\\t\\tcount: (aStringOrByteArray size - startIndex + 1)! !\\n\\n!OldSocket methodsFor: 'sending-receiving' stamp: 'nk 2/24/2005 14:37'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex count: count \\n\\t\\\"Send up to count bytes of the given data starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t| bytesSent |\\n\\t(self waitForSendDoneUntil: (self class deadlineSecs: 20)) \\n\\t\\tifTrue: \\n\\t\\t\\t[bytesSent := self \\n\\t\\t\\t\\t\\t\\tprimSocket: socketHandle\\n\\t\\t\\t\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\tstartIndex: startIndex\\n\\t\\t\\t\\t\\t\\tcount: count]\\n\\t\\tifFalse: [self error: 'send data timeout; data not sent'].\\n\\t^bytesSent! !\\n\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'ar 7/20/1999 17:21'!\\nwaitForAcceptUntil: deadLine\\n\\t\\\"Wait and accept an incoming connection\\\"\\n\\tself waitForConnectionUntil: deadLine.\\n\\t^self isConnected\\n\\t\\tifTrue:[self accept]\\n\\t\\tifFalse:[nil]! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'jm 3/2/98 18:15'!\\nwaitForConnectionUntil: deadline\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\t^ status = Connected\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/22/2000 22:04'!\\nwaitForDataUntil: deadline\\n\\t\\\"Wait up until the given deadline for data to arrive. Return true if data arrives by the deadline, false if not.\\\"\\n\\n\\t| dataArrived |\\n\\t[self isConnected & \\n\\t (dataArrived _ self primSocketReceiveDataAvailable: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ dataArrived\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/17/2000 14:52'!\\nwaitForDisconnectionUntil: deadline\\n\\t\\\"Wait up until the given deadline for the the connection to be broken. Return true if it is broken by the deadline, false if not.\\\"\\n\\t\\\"Note: The client should know the the connect is really going to be closed (e.g., because he has called 'close' to send a close request to the other end) before calling this method.\\nJMM 00/5/17 note that other end can close which will terminate wait\\\"\\n\\n\\t| extraBytes status |\\n\\textraBytes _ 0.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[((status = Connected) or: [(status = ThisEndClosed)]) and:\\n\\t [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\tself dataAvailable\\n\\t\\t\\tifTrue: [extraBytes _ extraBytes + self discardReceivedData].\\n\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\textraBytes > 0\\n\\t\\tifTrue: [self inform: 'Discarded ', extraBytes printString, ' bytes while closing connection.'].\\n\\n\\t^ status ~= Connected\\n! !\\n\\n!OldSocket methodsFor: 'waiting' stamp: 'JMM 5/22/2000 22:05'!\\nwaitForSendDoneUntil: deadline\\n\\t\\\"Wait up until the given deadline for the current send operation to complete. Return true if it completes by the deadline, false if not.\\\"\\n\\n\\t| sendDone |\\n\\t[self isConnected & (sendDone _ self primSocketSendDone: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself writeSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ sendDone! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOldSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!OldSocket class methodsFor: 'class initialization' stamp: 'ar 12/12/2001 19:12'!\\ninitialize\\n\\t\\\"Socket initialize\\\"\\n\\n\\t\\\"Socket Types\\\"\\n\\tTCPSocketType _ 0.\\n\\tUDPSocketType _ 1.\\n\\n\\t\\\"Socket Status Values\\\"\\n\\tInvalidSocket _ -1.\\n\\tUnconnected _ 0.\\n\\tWaitingForConnection _ 1.\\n\\tConnected _ 2.\\n\\tOtherEndClosed _ 3.\\n\\tThisEndClosed _ 4.\\n\\n\\tRegistryThreshold _ 100. \\\"# of sockets\\\"! !\\n\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nclientServerTestUDP\\n\\t\\\"Socket clientServerTestUDP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24:\\n\\t\\tclient/server UDP test done; time = 2820\\n\\t\\t2500 packets, 10000000 bytes sent (3546 kBytes/sec)\\n\\t\\t2500 packets, 10000000 bytes received (3546 kBytes/sec)\\n\\t\\t4000 bytes/packet, 886 packets/sec, 0 packets dropped\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: 'creating endpoints';\\n\\t\\tcr.\\n\\tsock1 := self newUDP.\\t\\\"the sender\\\"\\n\\tsock2 := self newUDP.\\t\\\"the recipient\\\"\\n\\tsock2 setPort: 54321.\\n\\tsock1 setPeer: NetNameResolver localHostAddress port: sock2 port.\\n\\tTranscript\\n\\t\\tshow: 'endpoints created';\\n\\t\\tcr.\\n\\tbytesToSend := 10000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (sock2 receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\tsock1 waitForSendDoneUntil: self standardDeadline.\\n\\t\\t\\t\\t\\tbytesReceived := bytesReceived + sock2 discardReceivedData].\\n\\tTranscript\\n\\t\\tshow: 'closing endpoints';\\n\\t\\tcr.\\n\\tsock1 close.\\n\\tsock2 close.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'client/server UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nclientServerTestUDP2\\n\\t\\\"Socket clientServerTestUDP2\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t datagramInfo |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: 'creating endpoints';\\n\\t\\tcr.\\n\\tsock1 := self newUDP.\\t\\\"the sender\\\"\\n\\tsock2 := self newUDP.\\t\\\"the recipient\\\"\\n\\tsock2 setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'endpoints created';\\n\\t\\tcr.\\n\\tbytesToSend := 100000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 2000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsendData: sendBuf\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttoHost: NetNameResolver localHostAddress\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tport: sock2 port)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdatagramInfo := sock2 receiveUDPDataInto: receiveBuf.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (datagramInfo at: 1)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\tsock1 waitForSendDoneUntil: self standardDeadline.\\n\\t\\t\\t\\t\\tbytesReceived := bytesReceived + sock2 discardReceivedData].\\n\\tTranscript\\n\\t\\tshow: 'closing endpoints';\\n\\t\\tcr.\\n\\tsock1 close.\\n\\tsock2 close.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'client/server UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' Bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:02'!\\nremoteTestClientTCP\\n\\t\\\"FIRST start up another image, and execute: Socket remoteTestServerTCP.\\n\\tTHEN come back to this image and execute:\\\"\\n\\n\\t\\\"Socket remoteTestClientTCP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24, both images on same CPU:\\n\\t\\tremoteClient TCP test done; time = 5680\\n\\t\\t250 packets, 1000000 bytes sent (176 kBytes/sec)\\n\\t\\t60 packets, 1000000 bytes received (176 kBytes/sec)\\\"\\n\\n\\t| socket bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newTCP.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\tport: 54321.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\tTranscript\\n\\t\\tshow: 'client endpoint created';\\n\\t\\tcr.\\n\\tbytesToSend := 1000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(socket sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (socket sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsocket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\t[bytesReceived < bytesToSend] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)]]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: 'remoteClient TCP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' bytes/sec)';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:02'!\\nremoteTestClientTCPOpenClose1000\\n\\t\\\"Socket remoteTestClientTCPOpenClose1000\\\"\\n\\n\\t| number t1 socket serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tnumber := 1000.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tt1 := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[number timesRepeat: \\n\\t\\t\\t\\t\\t\\t\\t[socket := self newTCP.\\n\\t\\t\\t\\t\\t\\t\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\t\\t\\t\\t\\t\\t\\tport: 54321.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t\\t\\t\\t\\t\\t\\tsocket closeAndDestroy]].\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'connects/close per second ' , (number / t1 * 1000.0) printString;\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\nremoteTestClientTCPOpenClosePutGet\\n\\t\\\"Socket remoteTestClientTCPOpenClosePutGet\\\"\\n\\n\\t| checkLength number bytesExpected sendBuf receiveBuf t1 socket bytesReceived serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server TCP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tnumber := 1000.\\n\\tbytesExpected := 20000.\\n\\tsendBuf := String new: 80 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tt1 := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[number timesRepeat: \\n\\t\\t\\t\\t\\t\\t\\t[socket := self newTCP.\\n\\t\\t\\t\\t\\t\\t\\tsocket connectTo: (NetNameResolver addressFromString: serverName)\\n\\t\\t\\t\\t\\t\\t\\t\\tport: 54321.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t\\t\\t\\t\\t\\t\\tsocket sendData: sendBuf.\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForSendDoneUntil: (self deadlineSecs: 5).\\n\\t\\t\\t\\t\\t\\t\\tsocket waitForDataUntil: (self deadlineSecs: 5).\\n\\t\\t\\t\\t\\t\\t\\tbytesReceived := 0.\\n\\t\\t\\t\\t\\t\\t\\t[bytesReceived < bytesExpected] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[checkLength := socket receiveDataInto: receiveBuf.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + checkLength].\\n\\t\\t\\t\\t\\t\\t\\tsocket closeAndDestroy]].\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'connects/get/put/close per second ' \\n\\t\\t\\t\\t\\t, (number / t1 * 1000.0) printString;\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\nremoteTestClientUDP\\n\\t\\\"FIRST start up another image, and execute: Socket remoteTestServerUDP.\\n\\tTHEN come back to this image and execute:\\\"\\n\\n\\t\\\"Socket remoteTestClientUDP\\\"\\n\\n\\t\\\"Performa 6400/200, Linux-PPC 2.1.24:\\n\\t\\tremoteClient UDP test done; time = 4580\\n\\t\\t2500 packets, 10000000 bytes sent (2183 kBytes/sec)\\n\\t\\t180 packets, 720000 bytes received (157 kBytes/sec)\\n\\t\\t4000 bytes/packet, 39 packets/sec, 2320 packets dropped\\\"\\n\\n\\t| socket bytesToSend sendBuf receiveBuf done bytesSent bytesReceived packetsSent packetsReceived t serverName |\\n\\tTranscript\\n\\t\\tshow: 'starting client/server UDP test';\\n\\t\\tcr.\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your remote Test Server?'\\n\\t\\t\\t\\tinitialAnswer: ''.\\n\\tsocket := self newUDP.\\n\\tsocket setPeer: (NetNameResolver addressFromString: serverName) port: 54321.\\n\\tTranscript\\n\\t\\tshow: 'client endpoint created';\\n\\t\\tcr.\\n\\tbytesToSend := 10000000.\\n\\tsendBuf := String new: 4000 withAll: $x.\\n\\treceiveBuf := String new: 4000.\\n\\tdone := false.\\n\\tbytesSent := bytesReceived := packetsSent := packetsReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(socket sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (socket sendData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsocket dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend].\\n\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t[socket waitForDataUntil: (self deadlineSecs: 1).\\n\\t\\t\\t\\t\\tsocket dataAvailable] \\n\\t\\t\\t\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[packetsReceived := packetsReceived + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (socket receiveDataInto: receiveBuf)]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: 'remoteClient UDP test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsSent printString , ' packets, ' , bytesSent printString \\n\\t\\t\\t\\t\\t, ' bytes sent (' , (bytesSent * 1000 // t) printString \\n\\t\\t\\t\\t\\t, ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: packetsReceived printString , ' packets, ' \\n\\t\\t\\t\\t\\t, bytesReceived printString , ' bytes received (' \\n\\t\\t\\t\\t\\t, (bytesReceived * 1000 // t) printString , ' bytes/sec)';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesSent // packetsSent) printString , ' bytes/packet, ' \\n\\t\\t\\t\\t\\t, (packetsReceived * 1000 // t) printString , ' packets/sec, ' \\n\\t\\t\\t\\t\\t, (packetsSent - packetsReceived) printString , ' packets dropped';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCP\\n\\t\\\"See remoteTestClientTCP for instructions on running this method.\\\"\\n\\n\\t\\\"OldSocket remoteTestServerTCP\\\"\\n\\n\\t| socket client buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetwork.\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := OldSocket newTCP.\\n\\tsocket \\n\\t\\tlistenOn: 54321\\n\\t\\tbacklogSize: 5\\n\\t\\tinterface: (NetNameResolver addressFromString: '127.0.0.1').\\t\\\"or: 0.0.0.0\\\"\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 4000.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\tclient := socket accept.\\n\\t[client isConnected] whileTrue: \\n\\t\\t\\t[client dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[n := client receiveDataInto: buffer.\\n\\t\\t\\t\\t\\tclient sendData: buffer count: n]].\\n\\tclient closeAndDestroy.\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr.\\n\\t^socket! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPOpenClose1000\\n\\t\\\"The version of #remoteTestServerTCPOpenClose1000 using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPOpenClose1000\\\"\\n\\n\\t| socket server |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 20.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\t1000 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\tsocket closeAndDestroy].\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPOpenClosePutGet\\n\\t\\\"The version of #remoteTestServerTCPOpenClosePutGet using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPOpenClosePutGet\\\"\\n\\n\\t| socket server bytesIWantToSend bytesExpected receiveBuf sendBuf checkLength |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 20.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbytesIWantToSend := 20000.\\n\\tbytesExpected := 80.\\n\\treceiveBuf := String new: 40000.\\n\\tsendBuf := String new: bytesIWantToSend withAll: $x.\\n\\t1000 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\tsocket waitForDataUntil: (self deadlineSecs: 5).\\n\\t\\t\\tcheckLength := socket receiveDataInto: receiveBuf.\\n\\t\\t\\tcheckLength ~= bytesExpected ifTrue: [self halt].\\n\\t\\t\\tsocket sendData: sendBuf.\\n\\t\\t\\tsocket waitForSendDoneUntil: (self deadlineSecs: 5).\\n\\t\\t\\tsocket closeAndDestroy].\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerTCPUsingAccept\\n\\t\\\"The version of #remoteTestServer using the BSD style accept() mechanism.\\\"\\n\\n\\t\\\"Socket remoteTestServerTCPUsingAccept\\\"\\n\\n\\t| socket buffer n server |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserver := self newTCP.\\n\\tserver listenOn: 54321 backlogSize: 4.\\n\\tserver isValid ifFalse: [self error: 'Accept() is not supported'].\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 40000.\\n\\t10 timesRepeat: \\n\\t\\t\\t[socket := server waitForAcceptUntil: (self deadlineSecs: 300).\\n\\t\\t\\t[socket isConnected] whileTrue: \\n\\t\\t\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[n := socket receiveDataInto: buffer.\\n\\t\\t\\t\\t\\t\\t\\tsocket sendData: buffer count: n]]].\\n\\tsocket closeAndDestroy.\\n\\tserver closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'server endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerUDP\\n\\t\\\"See remoteTestClientUDP for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestServerUDP\\\"\\n\\n\\t| socket buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newUDP.\\n\\tsocket setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 4000.\\n\\t[true] whileTrue: \\n\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[n := socket receiveDataInto: buffer.\\n\\t\\t\\t\\t\\tsocket sendData: buffer count: n]]! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestServerUDP2\\n\\t\\\"See remoteTestClientUDP for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestServerUDP2\\\"\\n\\n\\t| socket buffer datagramInfo |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newUDP.\\n\\tsocket setPort: 54321.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 65000.\\n\\t[true] whileTrue: \\n\\t\\t\\t[socket dataAvailable \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[datagramInfo := socket receiveUDPDataInto: buffer.\\n\\t\\t\\t\\t\\tTranscript\\n\\t\\t\\t\\t\\t\\tshow: datagramInfo printString;\\n\\t\\t\\t\\t\\t\\tcr.\\n\\t\\t\\t\\t\\tsocket sendData: buffer count: (datagramInfo at: 1)]]! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'nk 2/24/2005 14:38'!\\nremoteTestSinkTCP\\n\\t\\\"See sendTest for instructions on running this method.\\\"\\n\\n\\t\\\"Socket remoteTestSinkTCP\\\"\\n\\n\\t| socket buffer n |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tsocket := self newTCP.\\n\\tsocket listenOn: 9.\\n\\tTranscript\\n\\t\\tshow: 'server endpoint created -- run client test in other image';\\n\\t\\tcr.\\n\\tbuffer := String new: 64000.\\n\\tsocket waitForConnectionUntil: self standardDeadline.\\n\\t[socket isConnected] whileTrue: \\n\\t\\t\\t[socket dataAvailable ifTrue: [n := socket receiveDataInto: buffer]].\\n\\tsocket closeAndDestroy.\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'sink endpoint destroyed';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTest\\n\\t\\\"OldSocket timeTest\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self new.\\n\\tTranscript\\n\\t\\tshow: '---------- Connecting ----------';\\n\\t\\tcr.\\n\\ts connectTo: serverAddr port: 13.\\t\\\"13 is the 'daytime' port number\\\"\\n\\ts waitForConnectionUntil: (self deadlineSecs: 1).\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Connection Closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP\\n\\t\\\"Socket timeTestUDP\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\t\\\"a 'random' port number will be allocated by the system\\\"\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\t\\\"13 is the daytime service\\\"\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP2\\n\\t\\\"Socket timeTestUDP2\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\n\\t\\\"The following associates a port with the UDP socket, but does NOT create a connectable endpoint\\\"\\n\\ts setPort: 54321.\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n!OldSocket class methodsFor: 'examples' stamp: 'rbb 3/1/2005 11:03'!\\ntimeTestUDP3\\n\\t\\\"Socket timeTestUDP3\\\"\\n\\n\\t| serverName serverAddr s |\\n\\tTranscript show: 'initializing network ... '.\\n\\tself initializeNetworkIfFail: [^Transcript show: 'failed'].\\n\\tTranscript\\n\\t\\tshow: 'ok';\\n\\t\\tcr.\\n\\tserverName := UIManager default request: 'What is your time server?'\\n\\t\\t\\t\\tinitialAnswer: 'localhost'.\\n\\tserverName isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^Transcript\\n\\t\\t\\t\\tshow: 'never mind';\\n\\t\\t\\t\\tcr].\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [self error: 'Could not find the address for ' , serverName].\\n\\ts := self newUDP.\\n\\t\\\"The following associates a port with the UDP socket, but does NOT create a connectable endpoint\\\"\\n\\ts setPort: self wildcardPort.\\t\\\"explicitly request a default port number\\\"\\n\\t\\\"Send a packet to the daytime port and it will reply with the current date.\\\"\\n\\tTranscript\\n\\t\\tshow: '---------- Sending datagram from port ' , s port printString \\n\\t\\t\\t\\t\\t, ' ----------';\\n\\t\\tcr.\\n\\ts \\n\\t\\tsendData: '!!'\\n\\t\\ttoHost: serverAddr\\n\\t\\tport: 13.\\n\\tTranscript show: 'the time server reports: ' , s getResponseNoLF.\\n\\ts closeAndDestroy.\\n\\tTranscript\\n\\t\\tshow: '---------- Socket closed ----------';\\n\\t\\tcr! !\\n\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:45'!\\nacceptFrom: aSocket\\n\\t^[ super new acceptFrom: aSocket ]\\n\\t\\trepeatWithGCIf: [ :sock | sock isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:15'!\\ncreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\t\\\"Note: The default creates a TCP socket\\\"\\n\\t^self tcpCreateIfFail: failBlock! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:13'!\\nnew\\n\\t\\\"Return a new, unconnected Socket. Note that since socket creation may fail, it is safer to use the method createIfFail: to handle such failures gracefully; this method is primarily for backward compatibility and may be disallowed in a future release.\\\"\\n\\t\\\"Note: The default creates a TCP socket - this is also backward compatibility.\\\"\\n\\t^self newTCP! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 10:19'!\\nnewTCP\\n\\t\\\"Create a socket and initialise it for TCP\\\"\\n\\t^[ super new initialize: TCPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:44'!\\nnewUDP\\n\\t\\\"Create a socket and initialise it for UDP\\\"\\n\\t^[ super new initialize: UDPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:14'!\\ntcpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tsock _ super new initialize: TCPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n!OldSocket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:14'!\\nudpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tsock _ super new initialize: UDPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'nk 2/24/2005 14:38'!\\nensureNetworkConnected\\n\\t\\\"Try to ensure that an intermittent network connection, such as a dialup or ISDN line, is actually connected. This is necessary to make sure a server is visible in order to accept an incoming connection.\\\"\\n\\n\\t\\\"Socket ensureNetworkConnected\\\"\\n\\n\\tself initializeNetwork.\\n\\tUtilities informUser: 'Contacting domain name server...'\\n\\t\\tduring: \\n\\t\\t\\t[NetNameResolver addressForName: 'bogusNameToForceDNSToBeConsulted.org'\\n\\t\\t\\t\\ttimeout: 30]! !\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'mir 11/14/2002 19:36'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and the NetNameResolver. Do nothing if the network is already initialized.\\\"\\n\\t\\\"Note: The network must be re-initialized every time Squeak starts up, so applications that persist across snapshots should be prepared to re-initialize the network as needed. Such applications should call 'Socket initializeNetwork' before every network transaction. \\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n!OldSocket class methodsFor: 'network initialization' stamp: 'mir 11/14/2002 19:36'!\\ninitializeNetworkIfFail: failBlock\\n\\t\\\"Initialize the network drivers. Do nothing if the network is already initialized. Evaluate the given block if network initialization fails, perhaps because this computer isn't currently connected to a network.\\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\t^RegistryThreshold! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold: aNumber\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\tRegistryThreshold _ aNumber! !\\n\\n!OldSocket class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:22'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\n\\n\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:54'!\\ndeadServer\\n\\n\\t^ DeadServer! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:56'!\\ndeadServer: aStringOrNil\\n\\t\\\"Keep the machine name of the most recently encoutered non-responding machine. Next time the user can move it to the last in a list of servers to try.\\\"\\n\\n\\tDeadServer _ aStringOrNil! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 9/15/97 06:56'!\\ndeadlineSecs: secs\\n\\t\\\"Return a deadline time the given number of seconds from now.\\\"\\n\\n\\t^ Time millisecondClockValue + (secs * 1000)\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 12:13'!\\nnameForWellKnownTCPPort: portNum\\n\\t\\\"Answer the name for the given well-known TCP port number. Answer a string containing the port number if it isn't well-known.\\\"\\n\\n\\t| portList entry |\\n\\tportList _ #(\\n\\t\\t(7 'echo') (9 'discard') (13 'time') (19 'characterGenerator')\\n\\t\\t(21 'ftp') (23 'telnet') (25 'smtp')\\n\\t\\t(80 'http') (110 'pop3') (119 'nntp')).\\n\\tentry _ portList detect: [:pair | pair first = portNum] ifNone: [^ 'port-', portNum printString].\\n\\t^ entry last\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\nping: hostName \\n\\t\\\"Ping the given host. Useful for checking network connectivity. The host must be running a TCP echo server.\\\"\\n\\n\\t\\\"Socket ping: 'squeak.cs.uiuc.edu'\\\"\\n\\n\\t| tcpPort sock serverAddr startTime echoTime |\\n\\ttcpPort := 7.\\t\\\"7 = echo port, 13 = time port, 19 = character generator port\\\"\\n\\tself initializeNetwork.\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [^self inform: 'Could not find an address for ' , hostName].\\n\\tsock := self new.\\n\\tsock connectTo: serverAddr port: tcpPort.\\n\\t\\n\\t[sock waitForConnectionUntil: (self deadlineSecs: 10).\\n\\tsock isConnected] \\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(self confirm: 'Continue to wait for connection to ' , hostName , '?') \\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[sock destroy.\\n\\t\\t\\t\\t\\t\\t^self]].\\n\\tsock sendData: 'echo!!'.\\n\\tstartTime := Time millisecondClockValue.\\n\\t\\n\\t[sock waitForDataUntil: (self deadlineSecs: 15).\\n\\tsock dataAvailable] \\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(self confirm: 'Packet sent but no echo yet; keep waiting?') \\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[sock destroy.\\n\\t\\t\\t\\t\\t\\t^self]].\\n\\techoTime := Time millisecondClockValue - startTime.\\n\\tsock destroy.\\n\\tself inform: hostName , ' responded in ' , echoTime printString \\n\\t\\t\\t\\t, ' milliseconds'! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\npingPorts: portList on: hostName timeOutSecs: timeOutSecs \\n\\t\\\"Attempt to connect to each of the given sockets on the given host. Wait at most timeOutSecs for the connections to be established. Answer an array of strings indicating the available ports.\\\"\\n\\n\\t\\\"Socket pingPorts: #(7 13 19 21 23 25 80 110 119) on: 'squeak.cs.uiuc.edu' timeOutSecs: 15\\\"\\n\\n\\t| serverAddr sockets sock deadline done unconnectedCount connectedCount waitingCount result |\\n\\tself initializeNetwork.\\n\\tserverAddr := NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: \\n\\t\\t\\t[self inform: 'Could not find an address for ' , hostName.\\n\\t\\t\\t^#()].\\n\\tsockets := portList collect: \\n\\t\\t\\t\\t\\t[:portNum | \\n\\t\\t\\t\\t\\tsock := self new.\\n\\t\\t\\t\\t\\tsock connectTo: serverAddr port: portNum].\\n\\tdeadline := self deadlineSecs: timeOutSecs.\\n\\tdone := false.\\n\\t[done] whileFalse: \\n\\t\\t\\t[unconnectedCount := 0.\\n\\t\\t\\tconnectedCount := 0.\\n\\t\\t\\twaitingCount := 0.\\n\\t\\t\\tsockets do: \\n\\t\\t\\t\\t\\t[:s | \\n\\t\\t\\t\\t\\ts isUnconnectedOrInvalid \\n\\t\\t\\t\\t\\t\\tifTrue: [unconnectedCount := unconnectedCount + 1]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[s isConnected ifTrue: [connectedCount := connectedCount + 1].\\n\\t\\t\\t\\t\\t\\t\\ts isWaitingForConnection ifTrue: [waitingCount := waitingCount + 1]]].\\n\\t\\t\\twaitingCount = 0 ifTrue: [done := true].\\n\\t\\t\\tconnectedCount = sockets size ifTrue: [done := true].\\n\\t\\t\\tTime millisecondClockValue > deadline ifTrue: [done := true]].\\n\\tresult := (sockets select: [:s | s isConnected]) \\n\\t\\t\\t\\tcollect: [:s | self nameForWellKnownTCPPort: s remotePort].\\n\\tsockets do: [:s | s destroy].\\n\\t^result! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'nk 2/24/2005 14:38'!\\npingPortsOn: hostName \\n\\t\\\"Attempt to connect to a set of well-known sockets on the given host, and answer the names of the available ports.\\\"\\n\\n\\t\\\"Socket pingPortsOn: 'www.disney.com'\\\"\\n\\n\\t^self \\n\\t\\tpingPorts: #(7 13 19 21 23 25 80 110 119)\\n\\t\\ton: hostName\\n\\t\\ttimeOutSecs: 20! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'jm 9/15/97 06:56'!\\nstandardDeadline\\n\\t\\\"Return a default deadline time some seconds into the future.\\\"\\n\\n\\t^ self deadlineSecs: 45\\n! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardAddress\\n\\t\\\"Answer a don't-care address for use with UDP sockets.\\\"\\n\\n\\t^ByteArray new: 4\\t\\t\\\"0.0.0.0\\\"! !\\n\\n!OldSocket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardPort\\n\\t\\\"Answer a don't-care port for use with UDP sockets. (The system will allocate an\\n\\tunused port number to the socket.)\\\"\\n\\n\\t^0! !\\nSwitch subclass: #OneOnSwitch\\n\\tinstanceVariableNames: 'connection'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Menus'!\\n!OneOnSwitch commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nconnection\\n\\t\\\"Answer the object that connects the receiver to other Switches.\\\"\\n\\n\\t^connection! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nconnection: anObject \\n\\t\\\"Set anObject to be the connection among two or more Switches. Make the \\n\\treceiver a dependent of the argument, anObject.\\\"\\n\\n\\tconnection _ anObject.\\n\\tconnection addDependent: self! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nisConnectionSet\\n\\t\\\"Answer whether the receiver is connected to an object that coordinates \\n\\tupdates among switches.\\\"\\n\\n\\tconnection == nil\\n\\t\\tifTrue: [^false]\\n\\t\\tifFalse: [^true]! !\\n\\n!OneOnSwitch methodsFor: 'connection'!\\nnotifyConnection\\n\\t\\\"Send the receiver's connection (if it exists) the message 'changed: self' in \\n\\torder for the connection to broadcast the change to other objects \\n\\tconnected by the connection.\\\"\\n\\t\\n\\tself isConnectionSet ifTrue: [self connection changed: self]! !\\n\\n\\n!OneOnSwitch methodsFor: 'initialize-release'!\\nrelease\\n\\n\\tsuper release.\\n\\tself isConnectionSet ifTrue: [connection removeDependent: self]! !\\n\\n\\n!OneOnSwitch methodsFor: 'state'!\\nturnOn\\n\\t\\\"Does nothing if it is already on. If it is not, it is set to 'on', its\\n\\tdependents are \\tnotified of the change, its connection is notified, and\\n\\tits action is executed.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself notifyConnection.\\n\\t\\t\\tself doAction: onAction]! !\\n\\n\\n!OneOnSwitch methodsFor: 'updating'!\\nupdate: aOneOnSwitch \\n\\t\\\"Does nothing if aOneOnSwitch is identical to this object. If it is not, this \\n\\tobject is turned off. This message is sent by the connection (an Object)\\n\\twhen some related OneOnSwitch (possibly this one) has changed. This\\n\\tallows a group of related OneOnSwitches to maintain the constraint that\\n\\tat most one will be on at any time.\\\"\\n\\n\\tself ~~ aOneOnSwitch ifTrue: [self turnOff]! !\\nURI subclass: #OpaqueURI\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-URI'!\\n\\n!OpaqueURI methodsFor: 'testing' stamp: 'mir 2/20/2002 16:55'!\\nisOpaque\\n\\t^true! !\\nSmallLandColorTheme subclass: #OrangeSmallLandColorTheme\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support'!\\n\\n!OrangeSmallLandColorTheme methodsFor: 'initialization' stamp: 'dgd 3/12/2006 13:25'!\\nbaseColors\\n\\\"\\nOrangeSmallLandColorTheme apply.\\n\\\"\\n\\t^ Array\\n\\t\\twith: (Color fromArray: #(0.8 0.4 0.0 ))\\n\\t\\twith: (Color fromArray: #(1.0 0.8 0.0 ))\\n\\t\\twith: (Color fromArray: #(1.0 1.0 0.8 ))! !\\nSequenceableCollection subclass: #OrderedCollection\\n\\tinstanceVariableNames: 'array firstIndex lastIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Sequenceable'!\\n!OrderedCollection commentStamp: '<historical>' prior: 0!\\nI represent a collection of objects ordered by the collector.!\\n\\n\\n!OrderedCollection methodsFor: 'accessing'!\\nat: anInteger \\n\\t\\\"Answer my element at index anInteger. at: is used by a knowledgeable\\n\\tclient to access an existing element\\\"\\n\\n\\t(anInteger < 1 or: [anInteger + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [self errorNoSuchElement]\\n\\t\\tifFalse: [^ array at: anInteger + firstIndex - 1]! !\\n\\n!OrderedCollection methodsFor: 'accessing'!\\nat: anInteger put: anObject \\n\\t\\\"Put anObject at element index anInteger. at:put: cannot be used to\\n\\tappend, front or back, to an ordered collection; it is used by a\\n\\tknowledgeable client to replace an element.\\\"\\n\\n\\t| index |\\n\\tindex _ anInteger asInteger.\\n\\t(index < 1 or: [index + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [self errorNoSuchElement]\\n\\t\\tifFalse: [^array at: index + firstIndex - 1 put: anObject]! !\\n\\n!OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:42'!\\ncapacity\\n\\t\\\"Answer the current capacity of the receiver.\\\"\\n\\n\\t^ array size! !\\n\\n!OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:39'!\\nsize\\n\\t\\\"Answer how many elements the receiver contains.\\\"\\n\\n\\t^ lastIndex - firstIndex + 1! !\\n\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject\\n\\n\\t^self addLast: newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject after: oldObject \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just succeeding oldObject. Answer newObject.\\\"\\n\\t\\n\\t| index |\\n\\tindex _ self find: oldObject.\\n\\tself insert: newObject before: index + 1.\\n\\t^newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'di 3/15/1999 14:01'!\\nadd: newObject afterIndex: index \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just after index. Answer newObject.\\\"\\n\\n\\tself insert: newObject before: firstIndex + index.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\nadd: newObject before: oldObject \\n\\t\\\"Add the argument, newObject, as an element of the receiver. Put it in \\n\\tthe sequence just preceding oldObject. Answer newObject.\\\"\\n\\t\\n\\t| index |\\n\\tindex _ self find: oldObject.\\n\\tself insert: newObject before: index.\\n\\t^newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'BG 1/9/2004 12:30'!\\nadd: newObject beforeIndex: index \\n \\\"Add the argument, newObject, as an element of the receiver. Put it in \\n the sequence just before index. Answer newObject.\\\"\\n\\n self add: newObject afterIndex: index - 1.\\n ^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'sma 5/12/2000 11:26'!\\naddAll: aCollection \\n\\t\\\"Add each element of aCollection at my end. Answer\\taCollection.\\\"\\n\\n\\t^ self addAllLast: aCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddAllFirst: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the beginning of the \\n\\treceiver. Answer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection reverseDo: [:each | self addFirst: each].\\n\\t^anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'sw 3/1/2001 11:03'!\\naddAllFirstUnlessAlreadyPresent: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the beginning of the receiver, preserving the order, but do not add any items that are already in the receiver. Answer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection reverseDo:\\n\\t\\t[:each | (self includes: each) ifFalse: [self addFirst: each]].\\n\\t^ anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddAllLast: anOrderedCollection \\n\\t\\\"Add each element of anOrderedCollection at the end of the receiver. \\n\\tAnswer anOrderedCollection.\\\"\\n\\n\\tanOrderedCollection do: [:each | self addLast: each].\\n\\t^anOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddFirst: newObject \\n\\t\\\"Add newObject to the beginning of the receiver. Answer newObject.\\\"\\n\\n\\tfirstIndex = 1 ifTrue: [self makeRoomAtFirst].\\n\\tfirstIndex _ firstIndex - 1.\\n\\tarray at: firstIndex put: newObject.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\naddLast: newObject \\n\\t\\\"Add newObject to the end of the receiver. Answer newObject.\\\"\\n\\n\\tlastIndex = array size ifTrue: [self makeRoomAtLast].\\n\\tlastIndex _ lastIndex + 1.\\n\\tarray at: lastIndex put: newObject.\\n\\t^ newObject! !\\n\\n!OrderedCollection methodsFor: 'adding' stamp: 'ajh 5/22/2003 12:03'!\\nat: index ifAbsentPut: block\\n\\t\\\"Return value at index, however, if value does not exist (nil or out of bounds) then add block's value at index (growing self if necessary)\\\"\\n\\n\\t| v |\\n\\tindex <= self size ifTrue: [\\n\\t\\t^ (v _ self at: index)\\n\\t\\t\\tifNotNil: [v]\\n\\t\\t\\tifNil: [self at: index put: block value]\\n\\t].\\n\\t[self size < index] whileTrue: [self add: nil].\\n\\t^ self at: index put: block value! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\ngrow\\n\\t\\\"Become larger. Typically, a subclass has to override this if the subclass\\n\\tadds instance variables.\\\"\\n\\t| newArray |\\n\\tnewArray _ Array new: self size + self growSize.\\n\\tnewArray replaceFrom: 1 to: array size with: array startingAt: 1.\\n\\tarray _ newArray! !\\n\\n!OrderedCollection methodsFor: 'adding'!\\ngrowSize\\n\\t^ array size max: 2! !\\n\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver that contains no elements.\\\"\\n\\n\\t^self species new! !\\n\\n!OrderedCollection methodsFor: 'copying' stamp: 'di 12/12/2000 10:15'!\\ncopyFrom: startIndex to: endIndex \\n\\t\\\"Answer a copy of the receiver that contains elements from position\\n\\tstartIndex to endIndex.\\\"\\n\\n\\t| targetCollection |\\n\\tendIndex < startIndex ifTrue: [^self species new: 0].\\n\\ttargetCollection _ self species new: endIndex + 1 - startIndex.\\n\\tstartIndex to: endIndex do: [:index | targetCollection addLast: (self at: index)].\\n\\t^ targetCollection! !\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyReplaceFrom: start to: stop with: replacementCollection \\n\\t\\\"Answer a copy of the receiver with replacementCollection's elements in\\n\\tplace of the receiver's start'th to stop'th elements. This does not expect\\n\\ta 1-1 map from replacementCollection to the start to stop elements, so it\\n\\twill do an insert or append.\\\"\\n\\n\\t| newOrderedCollection delta startIndex stopIndex |\\n\\t\\\"if start is less than 1, ignore stop and assume this is inserting at the front. \\n\\tif start greater than self size, ignore stop and assume this is appending. \\n\\totherwise, it is replacing part of me and start and stop have to be within my \\n\\tbounds. \\\"\\n\\tdelta _ 0.\\n\\tstartIndex _ start.\\n\\tstopIndex _ stop.\\n\\tstart < 1\\n\\t\\tifTrue: [startIndex _ stopIndex _ 0]\\n\\t\\tifFalse: [startIndex > self size\\n\\t\\t\\t\\tifTrue: [startIndex _ stopIndex _ self size + 1]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(stopIndex < (startIndex - 1) or: [stopIndex > self size])\\n\\t\\t\\t\\t\\t\\tifTrue: [self errorOutOfBounds].\\n\\t\\t\\t\\t\\tdelta _ stopIndex - startIndex + 1]].\\n\\tnewOrderedCollection _ \\n\\t\\tself species new: self size + replacementCollection size - delta.\\n\\t1 to: startIndex - 1 do: [:index | newOrderedCollection add: (self at: index)].\\n\\t1 to: replacementCollection size do: \\n\\t\\t[:index | newOrderedCollection add: (replacementCollection at: index)].\\n\\tstopIndex + 1 to: self size do: [:index | newOrderedCollection add: (self at: index)].\\n\\t^newOrderedCollection! !\\n\\n!OrderedCollection methodsFor: 'copying'!\\ncopyWith: newElement \\n\\t\\\"Answer a copy of the receiver that is 1 bigger than the receiver and \\n\\tincludes the argument, newElement, at the end.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self copy.\\n\\tnewCollection add: newElement.\\n\\t^newCollection! !\\n\\n!OrderedCollection methodsFor: 'copying' stamp: 'sw 1/26/96'!\\nreversed\\n\\t\\\"Answer a copy of the receiver with element order reversed. \\\"\\n\\t| newCol |\\n\\tnewCol _ self species new.\\n\\tself reverseDo:\\n\\t\\t[:elem | newCol addLast: elem].\\n\\t^ newCol\\n\\n\\\"#(2 3 4 'fred') reversed\\\"! !\\n\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'!\\ncollect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect the \\n\\tresulting values into a collection that is like me. Answer the new \\n\\tcollection. Override superclass in order to use addLast:, not at:put:.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species new: self size.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\tnewCollection addLast: (aBlock value: (array at: index))].\\n\\t^ newCollection! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/18/2000 17:34'!\\ncollect: aBlock from: fromIndex to: toIndex\\n\\t\\\"Override superclass in order to use addLast:, not at:put:.\\\"\\n\\t| result |\\n\\t(fromIndex < 1 or:[toIndex + firstIndex - 1 > lastIndex])\\n\\t\\tifTrue: [^self errorNoSuchElement].\\n\\tresult _ self species new: toIndex - fromIndex + 1.\\n\\tfirstIndex + fromIndex - 1 to: firstIndex + toIndex - 1 do:\\n\\t\\t[:index | result addLast: (aBlock value: (array at: index))].\\n\\t^ result\\n! !\\n\\n!OrderedCollection methodsFor: 'enumerating'!\\ndo: aBlock \\n\\t\\\"Override the superclass for performance reasons.\\\"\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: (array at: index).\\n\\t\\t\\tindex _ index + 1]! !\\n\\n!OrderedCollection methodsFor: 'enumerating'!\\nreverseDo: aBlock \\n\\t\\\"Override the superclass for performance reasons.\\\"\\n\\t| index |\\n\\tindex _ lastIndex.\\n\\t[index >= firstIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[aBlock value: (array at: index).\\n\\t\\t\\tindex _ index - 1]! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:13'!\\nselect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect into\\n\\ta new collection like the receiver, only those elements for which aBlock\\n\\tevaluates to true.\\\"\\n\\n\\t| newCollection element |\\n\\tnewCollection _ self copyEmpty.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\t(aBlock value: (element _ array at: index))\\n\\t\\t\\tifTrue: [newCollection addLast: element]].\\n\\t^ newCollection! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'di 8/31/1999 13:13'!\\nwith: otherCollection collect: twoArgBlock \\n\\t\\\"Collect and return the result of evaluating twoArgBlock with \\n\\tcorresponding elements from this collection and otherCollection.\\\"\\n\\t| result |\\n\\totherCollection size = self size ifFalse: [self error: 'otherCollection must be the same size'].\\n\\tresult _ self species new: self size.\\n\\t1 to: self size do:\\n\\t\\t[:index | result addLast: (twoArgBlock value: (self at: index)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: (otherCollection at: index))].\\n\\t^ result! !\\n\\n!OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/16/2000 16:30'!\\nwithIndexCollect: elementAndIndexBlock \\n\\t\\\"Just like with:collect: except that the iteration index supplies the second argument to the block. Override superclass in order to use addLast:, not at:put:.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species new: self size.\\n\\tfirstIndex to: lastIndex do:\\n\\t\\t[:index |\\n\\t\\tnewCollection addLast: (elementAndIndexBlock\\n\\t\\t\\tvalue: (array at: index)\\n\\t\\t\\tvalue: index - firstIndex + 1)].\\n\\t^ newCollection! !\\n\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremove: oldObject ifAbsent: absentBlock\\n\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue: \\n\\t\\t\\t[oldObject = (array at: index)\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self removeIndex: index.\\n\\t\\t\\t\\t\\t^ oldObject]\\n\\t\\t\\t\\tifFalse: [index _ index + 1]].\\n\\t^ absentBlock value! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'raok 4/27/2001 15:35'!\\nremoveAllSuchThat: aBlock \\n\\t\\\"Remove each element of the receiver for which aBlock evaluates to true.\\n\\tThe method in Collection is O(N^2), this is O(N).\\\"\\n\\n\\t| n |\\n\\tn _ firstIndex.\\n\\tfirstIndex to: lastIndex do: [:index |\\n\\t (aBlock value: (array at: index)) ifFalse: [\\n\\t\\t\\tarray at: n put: (array at: index).\\n\\t\\t\\tn _ n + 1]].\\n\\tn to: lastIndex do: [:index | array at: index put: nil].\\n\\tlastIndex _ n - 1! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ar 5/22/2000 12:19'!\\nremoveAt: index\\n\\t| removed |\\n\\tremoved _ self at: index.\\n\\tself removeIndex: index + firstIndex - 1.\\n\\t^removed! !\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremoveFirst\\n\\t\\\"Remove the first element of the receiver and answer it. If the receiver is \\n\\tempty, create an error notification.\\\"\\n\\t| firstObject |\\n\\tself emptyCheck.\\n\\tfirstObject _ array at: firstIndex.\\n\\tarray at: firstIndex put: nil.\\n\\tfirstIndex _ firstIndex + 1.\\n\\t^ firstObject! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:37'!\\nremoveFirst: n\\n\\t\\\"Remove first n object into an array\\\"\\n\\n\\t| list |\\n\\tlist _ Array new: n.\\n\\t1 to: n do: [:i |\\n\\t\\tlist at: i put: self removeFirst].\\n\\t^ list! !\\n\\n!OrderedCollection methodsFor: 'removing'!\\nremoveLast\\n\\t\\\"Remove the last element of the receiver and answer it. If the receiver is \\n\\tempty, create an error notification.\\\"\\n\\t| lastObject |\\n\\tself emptyCheck.\\n\\tlastObject _ array at: lastIndex.\\n\\tarray at: lastIndex put: nil.\\n\\tlastIndex _ lastIndex - 1.\\n\\t^ lastObject! !\\n\\n!OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:36'!\\nremoveLast: n\\n\\t\\\"Remove last n object into an array with last in last position\\\"\\n\\n\\t| list |\\n\\tlist _ Array new: n.\\n\\tn to: 1 by: -1 do: [:i |\\n\\t\\tlist at: i put: self removeLast].\\n\\t^ list! !\\n\\n\\n!OrderedCollection methodsFor: 'testing' stamp: 'bf 8/20/1999 15:08'!\\nhasContentsInExplorer\\n\\n\\t^self isEmpty not! !\\n\\n\\n!OrderedCollection methodsFor: '*Tools-Inspector' stamp: 'ar 9/27/2005 18:33'!\\ninspectorClass \\n\\t\\\"Answer the class of the inspector to be used on the receiver. Called by inspect; \\n\\tuse basicInspect to get a normal (less useful) type of inspector.\\\"\\n\\n\\t^OrderedCollectionInspector! !\\n\\n\\n!OrderedCollection methodsFor: 'private'!\\ncollector \\\"Private\\\"\\n\\t^ array! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nerrorConditionNotSatisfied\\n\\n\\tself error: 'no element satisfies condition'! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nerrorNoSuchElement\\n\\n\\tself error: 'attempt to index non-existent element in an ordered collection'! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:26'!\\nfind: oldObject\\n \\\" This method answers an index in the range firstIndex .. lastIndex, which is meant for internal use only.\\n Never use this method in your code, the methods for public use are:\\n #indexOf:\\n #indexOf:ifAbsent: \\\"\\n\\n\\t| index |\\n\\tindex _ firstIndex.\\n\\t[index <= lastIndex]\\n\\t\\twhileTrue:\\n\\t\\t\\t[(array at: index) = oldObject ifTrue: [^ index].\\n\\t\\t\\tindex _ index + 1].\\n\\tself errorNotFound: oldObject! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:29'!\\ninsert: anObject before: spot\\n\\n \\\" spot is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection. \\n Never use this method in your code, it is meant for private use by OrderedCollection only.\\n The methods for use are:\\n #add:before: to insert an object before another object\\n #add:beforeIndex: to insert an object before a given position. \\\"\\n\\t| \\\"index\\\" delta spotIndex|\\n\\tspotIndex _ spot.\\n\\tdelta _ spotIndex - firstIndex.\\n\\tfirstIndex = 1\\n\\t\\tifTrue: \\n\\t\\t\\t[self makeRoomAtFirst.\\n\\t\\t\\tspotIndex _ firstIndex + delta].\\n\\tfirstIndex _ firstIndex - 1.\\n\\tarray\\n\\t\\treplaceFrom: firstIndex\\n\\t\\tto: spotIndex - 2\\n\\t\\twith: array\\n\\t\\tstartingAt: firstIndex + 1.\\n\\tarray at: spotIndex - 1 put: anObject.\\n\\\"\\tindex _ firstIndex _ firstIndex - 1.\\n\\t[index < (spotIndex - 1)]\\n\\t\\twhileTrue: \\n\\t\\t\\t[array at: index put: (array at: index + 1).\\n\\t\\t\\tindex _ index + 1].\\n\\tarray at: index put: anObject.\\\"\\n\\t^ anObject! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nmakeRoomAtFirst\\n\\t| delta index |\\n\\tdelta _ array size - self size.\\n\\tdelta = 0 ifTrue: \\n\\t\\t\\t[self grow.\\n\\t\\t\\tdelta _ array size - self size].\\n\\tlastIndex = array size ifTrue: [^ self]. \\\"just in case we got lucky\\\"\\n\\tindex _ array size.\\n\\t[index > delta]\\n\\t\\twhileTrue: \\n\\t\\t\\t[array at: index put: (array at: index - delta + firstIndex - 1).\\n\\t\\t\\tarray at: index - delta + firstIndex - 1 put: nil.\\n\\t\\t\\tindex _ index - 1].\\n\\tfirstIndex _ delta + 1.\\n\\tlastIndex _ array size! !\\n\\n!OrderedCollection methodsFor: 'private'!\\nmakeRoomAtLast\\n\\t| newLast delta |\\n\\tnewLast _ self size.\\n\\tarray size - self size = 0 ifTrue: [self grow].\\n\\t(delta _ firstIndex - 1) = 0 ifTrue: [^ self].\\n\\t\\\"we might be here under false premises or grow did the job for us\\\"\\n\\t1 to: newLast do:\\n\\t\\t[:index |\\n\\t\\tarray at: index put: (array at: index + delta).\\n\\t\\tarray at: index + delta put: nil].\\n\\tfirstIndex _ 1.\\n\\tlastIndex _ newLast! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:28'!\\nremoveIndex: removedIndex\\n \\\" removedIndex is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection.\\n Never use this method in your code, it is meant for private use by OrderedCollection only.\\n The method for public use is:\\n #removeAt: \\\"\\n\\n\\tarray \\n\\t\\treplaceFrom: removedIndex \\n\\t\\tto: lastIndex - 1 \\n\\t\\twith: array \\n\\t\\tstartingAt: removedIndex+1.\\n\\tarray at: lastIndex put: nil.\\n\\tlastIndex _ lastIndex - 1.! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'!\\nreset\\n\\tfirstIndex _ array size // 3 max: 1.\\n\\tlastIndex _ firstIndex - 1! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'ar 4/16/1999 07:59'!\\nresetTo: index\\n\\tfirstIndex _ index.\\n\\tlastIndex _ firstIndex - 1! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'!\\nsetCollection: anArray\\n\\tarray _ anArray.\\n\\tself reset! !\\n\\n!OrderedCollection methodsFor: 'private' stamp: 'apb 10/15/2000 18:10'!\\nsetContents: anArray\\n\\tarray _ anArray.\\n\\tfirstIndex _ 1.\\n\\tlastIndex _ array size.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nOrderedCollection class\\n\\tinstanceVariableNames: ''!\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:41'!\\nnew\\n\\t^ self new: 10! !\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'md 7/5/2005 15:16'!\\nnew: anInteger \\n\\t^ super basicNew setCollection: (Array new: anInteger)! !\\n\\n!OrderedCollection class methodsFor: 'instance creation'!\\nnewFrom: aCollection \\n\\t\\\"Answer an instance of me containing the same elements as aCollection.\\\"\\n\\n\\t| newCollection |\\n\\tnewCollection _ self new: aCollection size.\\n\\tnewCollection addAll: aCollection.\\n\\t^newCollection\\n\\n\\\"\\tOrderedCollection newFrom: {1. 2. 3}\\n\\t{1. 2. 3} as: OrderedCollection\\n\\t{4. 2. 7} as: SortedCollection\\n\\\"! !\\n\\n!OrderedCollection class methodsFor: 'instance creation' stamp: 'apb 10/15/2000 22:02'!\\nofSize: n\\n\\t\\\"Create a new collection of size n with nil as its elements.\\n\\tThis method exists because OrderedCollection new: n creates an\\n\\tempty collection, not one of size n.\\\"\\n\\t| collection |\\n\\tcollection _ self new: n.\\n\\tcollection setContents: (collection collector).\\n\\t^ collection\\n! !\\nInspector subclass: #OrderedCollectionInspector\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Inspector'!\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'dew 9/19/2001 03:27'!\\nfieldList\\n\\tobject ifNil: [ ^ OrderedCollection new].\\n\\t^ self baseFieldList ,\\n\\t\\t(object size <= (self i1 + self i2)\\n\\t\\t\\tifTrue: [(1 to: object size)\\n\\t\\t\\t\\t\\t\\tcollect: [:i | i printString]]\\n\\t\\t\\tifFalse: [(1 to: self i1) , (object size-(self i2-1) to: object size)\\n\\t\\t\\t\\t\\t\\tcollect: [:i | i printString]])\\n\\\"\\nOrderedCollection new inspect\\n(OrderedCollection newFrom: #(3 5 7 123)) inspect\\n(OrderedCollection newFrom: (1 to: 1000)) inspect\\n\\\"! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:38'!\\nreplaceSelectionValue: anObject \\n\\t\\\"The receiver has a list of variables of its inspected object. One of these \\n\\tis selected. The value of the selected variable is set to the value, anObject.\\\"\\n\\n\\t(selectionIndex - 2) <= object class instSize\\n\\t\\tifTrue: [^ super replaceSelectionValue: anObject].\\n\\tobject at: self selectedObjectIndex put: anObject! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:27'!\\nselectedObjectIndex\\n\\t\\\"Answer the index of the inspectee's collection that the current selection refers to.\\\"\\n\\n\\t| basicIndex |\\n\\tbasicIndex := selectionIndex - 2 - object class instSize.\\n\\t^ (object size <= (self i1 + self i2) or: [basicIndex <= self i1])\\n\\t\\tifTrue: [basicIndex]\\n\\t\\tifFalse: [object size - (self i1 + self i2) + basicIndex]! !\\n\\n!OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:39'!\\nselection\\n\\t\\\"The receiver has a list of variables of its inspected object.\\n\\tOne of these is selected. Answer the value of the selected variable.\\\"\\n\\n\\t(selectionIndex - 2) <= object class instSize\\n\\t\\tifTrue: [^ super selection].\\n\\t^ object at: self selectedObjectIndex! !\\nClassTestCase subclass: #OrderedCollectionTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Sequenceable'!\\n!OrderedCollectionTest commentStamp: 'BG 1/10/2004 22:07' prior: 0!\\nThese test cases demonstrate addition of items into an OrderedCollection as well as item removal.\\n\\nSome of the assertions are quite complicated and use a lot of collection protocol. Such methods do not test one single method, but protocol in general.!\\n\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 19:00'!\\ntestAdd\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88.\\n\\tself assert: (l = #(1 2 3 4 88) asOrderedCollection).\\n\\tl add: 99.\\n\\tself assert: (l = #(1 2 3 4 88 99) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:52'!\\ntestAddAfter\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 after: 1.\\n\\tself assert: (l = #(1 88 2 3 4) asOrderedCollection).\\n\\tl add: 99 after: 2.\\n\\tself assert: (l = #(1 88 2 99 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:56'!\\ntestAddAfterIndex\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 afterIndex: 1.\\n\\tself assert: (l = #(1 88 2 3 4) asOrderedCollection).\\n\\tl add: 99 afterIndex: 2.\\n\\tself assert: (l = #(1 88 99 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAll\\n\\t\\\"Allows one to add each element of an orderedCollection at the end of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAll\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAll: c2.\\n\\tself assert: c1 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllFirst\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAllFirst\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc2 addAllFirst: c1.\\n\\tself assert: c2 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllFirstUnlessAlreadyPresent\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of\\n\\tanother orderedCollection preserving the order but no duplicate element\\\"\\n\\t\\\"self run:#testAddAllFirstUnlessAlreadyPresent\\\" \\n\\t\\n\\t| c1 c2 c3 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc3 := #(0 1 ) asOrderedCollection.\\n\\tc2 addAllFirstUnlessAlreadyPresent: c1.\\n\\tself assert: c2 = #(1 2 3 4 5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAllFirstUnlessAlreadyPresent: c3.\\n\\tself deny: c1 = #(0 1 1 2 3 4 ) asOrderedCollection.\\n\\tself assert: c1 = #(0 1 2 3 4 ) asOrderedCollection.\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:36'!\\ntestAddAllLast\\n\\t\\\"Allows one to add each element of an orderedCollection at the beginning of another\\n\\torderedCollection \\\"\\n\\t\\\"self run:#testAddAllLast\\\" \\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9 ) asOrderedCollection.\\n\\tc1 addAllLast: c2.\\n\\tself assert: c1 = #(1 2 3 4 5 6 7 8 9) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:57'!\\ntestAddBefore\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 before: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 before: 2.\\n\\tself assert: (l = #(88 1 99 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 13:42'!\\ntestAddBeforeAndRemove\\n\\n\\t| l initialCollection |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tinitialCollection := l shallowCopy.\\n\\tl add: 88 before: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 before: 2.\\n\\tself assert: (l = #(88 1 99 2 3 4) asOrderedCollection). \\n\\tl remove: 99.\\n\\tl remove: 88.\\n\\tself assert: l = initialCollection.\\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:57'!\\ntestAddBeforeIndex\\n\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl add: 88 beforeIndex: 1.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl add: 99 beforeIndex: 2.\\n\\tself assert: (l = #(88 99 1 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 13:43'!\\ntestAddDuplicateItem1\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection add: 'John' before: 'John'.\\n\\tself\\n\\t\\tassert: ((collection asBag occurrencesOf: 'John')\\n\\t\\t\\t\\t\\t= 2\\n\\t\\t\\t\\tand: [(collection at: (collection indexOf: 'John')\\n\\t\\t\\t\\t\\t\\t\\t+ 1)\\n\\t\\t\\t\\t\\t\\t= (collection\\n\\t\\t\\t\\t\\t\\t\\t\\tat: (collection indexOf: 'John'))])! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:58'!\\ntestAddFirst\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl addFirst: 88.\\n\\tself assert: (l = #(88 1 2 3 4) asOrderedCollection).\\n\\tl addFirst: 99.\\n\\tself assert: (l = #(99 88 1 2 3 4) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 6/5/2005 09:21'!\\ntestAddItem1\\n\\n | collection size |\\n collection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n size := collection size.\\n collection add: 'James' before: 'Jim'.\\n collection add: 'Margaret' before: 'Andrew'.\\n self assert: size + 2 = collection size.\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 19:07'!\\ntestAddItem2\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection add: 'James' before: 'Jim'.\\n\\tcollection add: 'Margaret' before: 'Andrew'.\\n\\tself assert: (collection indexOf: 'James')\\n\\t\\t\\t+ 1\\n\\t\\t\\t= (collection indexOf: 'Jim').\\n\\tself assert: (collection indexOf: 'Margaret')\\n\\t\\t\\t+ 1\\n\\t\\t\\t= (collection indexOf: 'Andrew')! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'zz 12/7/2005 18:59'!\\ntestAddLast\\n\\t| l |\\n\\tl := #(1 2 3 4) asOrderedCollection.\\n\\tl addLast: 88.\\n\\tself assert: (l = #(1 2 3 4 88) asOrderedCollection).\\n\\tl addLast: 99.\\n\\tself assert: (l = #(1 2 3 4 88 99) asOrderedCollection). \\n\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAdding' stamp: 'sd 3/21/2006 22:37'!\\ntestAtIfAbsentPut\\n\\t\\\"Allows one to add an element at an index if no element exist at this index\\\"\\n\\t\\\"self run:#testAtIfAbsentPut\\\" \\n\\t\\n\\t| c |\\n\\tc := #(1 2 3 4 ) asOrderedCollection.\\n\\tself\\n\\t\\tshouldnt: [c at: 2 ifAbsentPut: [5]]\\n\\t\\traise: Error.\\n\\tself assert: c = #(1 2 3 4 ) asOrderedCollection.\\n\\tc at: 5 ifAbsentPut: [5].\\n\\tself assert: c = #(1 2 3 4 5 ) asOrderedCollection.\\n\\tc at: 7 ifAbsentPut: [7].\\n\\tself assert: c = #(1 2 3 4 5 nil 7 ) asOrderedCollection! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'zz 12/7/2005 18:50'!\\ntestAt\\n\\t| collection |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tself assert: (collection at:1) = 'Jim'.\\n\\tself assert: (collection at:2) = 'Mary'! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:38'!\\ntestAtPut\\n\\t\\\"Allows one to replace an element but not at an off range index\\\"\\n\\t\\\"self run:#testAtPut\\\"\\n\\t| c |\\n\\tc := #(1 2 3 4 ) asOrderedCollection.\\n\\tc at: 2 put: 5.\\n\\tself assert: c = #(1 5 3 4 ) asOrderedCollection.\\n\\tself\\n\\t\\tshould: [c at: 5 put: 8]\\n\\t\\traise: Error.\\n\\tself deny: c = #(1 5 3 4 8 ) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:39'!\\ntestCapacity\\n\\t\\\"Allows one to check the current capacity of an Ordered collection\\\"\\n\\t\\\"self run:#testCapacity\\\"\\n\\t\\n\\t| c1 c2 c3 |\\n\\tc1 := #(1 2 ) asOrderedCollection.\\n\\tself assert: (c1 capacity = 2).\\n\\tc2 := OrderedCollection new: 10.\\n\\tc2 add: 3.\\n\\tself assert: (c2 capacity = 10).\\t\\n\\tc3 := OrderedCollection new.\\n\\tself deny: (c3 capacity = 0).\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsAccessing' stamp: 'sd 3/21/2006 22:38'!\\ntestSize\\n\\t\\\"Allows one to check the size of an Ordered collection\\\"\\n\\t\\\"self run:#testSize\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 ) asOrderedCollection.\\n\\tself assert: (c1 size = 2).\\n\\t\\n\\tc2 := OrderedCollection new.\\n\\tself assert: (c2 size = 0)\\n\\t! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'sd 3/21/2006 22:41'!\\ntestCollect\\n\\t\\\"Allows one to collect some element of a collection into another collection\\\"\\n\\t\\\"self run: #testCollect\\\"\\n\\t \\n\\t| c1 c2 res |\\n\\tc1 := #(-1 2 -3 4) asOrderedCollection.\\n\\tc2 := #(1 2 3 4) asOrderedCollection.\\n\\tres := c1 collect: [:each | each abs].\\n\\tself assert: (c2 = res).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'cm 3/8/2006 09:09'!\\ntestCollectFromTo\\n\\t\\\"Allows one to collect some element of a collection into another collection between a first index and an end index for the collect\\\"\\n\\t\\\"self run: #testCollectFromTo\\\"\\n\\t\\n\\t| c1 res |\\n\\tc1 := #(-1 2 -3 4 -5 6 -7 8) asOrderedCollection.\\n\\tres := c1 collect: [:each | each abs] from: 1 to: 3.\\n\\tself assert: (res = #(1 2 3) asOrderedCollection).\\n\\tself should: [c1 collect: [:each | each abs] from: 10 to: 13] raise: Error.\\n\\tself should: [c1 collect: [:each | each abs] from: 5 to: 2] raise: Error.! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'zz 12/7/2005 19:06'!\\ntestIndexOf\\n\\t| collection indices |\\n\\tcollection := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tindices := collection\\n\\t\\t\\t\\tcollect: [:item | collection indexOf: item].\\n\\tself assert: (1 to: 4) asOrderedCollection = indices! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'sd 6/5/2005 09:21'!\\ntestIndexOfWithDuplicates\\n\\n | collection indices bagOfIndices |\\n collection := #('Jim' 'Mary' 'John' 'Andrew' 'Mary' 'John' 'Jim' 'Micheal') asOrderedCollection.\\n indices := collection collect: [:item | collection indexOf: item].\\n self assert: indices asSet size = collection asSet size.\\n bagOfIndices := indices asBag.\\n self assert: (indices asSet \\n allSatisfy: [:index | (bagOfIndices occurrencesOf: index)\\n\\t = (collection occurrencesOf: (collection at: index))]).\\n\\n \\\" indexOf: returns the index of the first occurrence of an item.\\n For an item with n occurrences, the index of its first occurrence\\n is found n times. \\\"! !\\n\\n!OrderedCollectionTest methodsFor: 'testsEnumerating' stamp: 'cm 3/8/2006 10:02'!\\ntestWithCollect\\n\\t\\\"Allows one to collect some element of two collections into another collection with element corresponding to the condition in the blocks\\\"\\n\\t\\\"self run: #testWithCollect\\\"\\n\\t\\n\\t| c1 c2 res |\\n\\tc1 := #(-1 2 -3 4 -5 6 -7 8) asOrderedCollection.\\n\\tc2 := #(-9 10 -11 12 -13 14 -15 16) asOrderedCollection.\\n\\tres := c1 with: c2 collect: [:each1 :each2 | each1 < each2\\n\\t\\tifTrue: [each1]\\n\\t\\tifFalse: [each2]].\\n\\tself assert: (res = #(-9 2 -11 4 -13 6 -15 8) asOrderedCollection).\\n\\t! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:40'!\\ntestCopyEmpty\\n\\t\\\"Allows one to create a copy of the receiver that contains no elements\\\"\\n\\t\\\"self run:#testCopyEmpty\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4 ) asOrderedCollection.\\n\\tc2 := c1 copyEmpty.\\n\\tself assert: (c2 size = 0).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyFromTo\\n\\t\\\"Allows one to create a copy of the receiver that contains elements from position start to end\\\"\\n\\t\\\"self run: #testCopyFromTo\\\"\\n\\t\\n\\t| c1 c2 c3 | \\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := (c1 copyFrom: 1 to: 2).\\n\\tself assert: c2 = #(1 2) asOrderedCollection.\\n\\tself should: [c1 copyFrom: 10 to: 20] raise: Error.\\n\\t\\n\\tc3 := c1 copyFrom: 4 to: 2.\\n\\tself assert: c3 isEmpty.\\n\\t\\n\\tself should: [c1 copyFrom: 4 to: 5 ] raise: Error.\\n\\t\\n\\t\\n\\t\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyReplaceFromToWith\\n\\t\\\"Allows one to create a copy from the receiver which elements between start and end of the \\treceiver being replace by \\telement of the collection after with:\\\"\\n\\t\\\"self run:#testCopyReplaceFromToWith\\\"\\n\\n\\t| c1 c2 c3 c4 |\\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := #(5 6 7 8 9) asOrderedCollection.\\n\\tc3 := (c2 copyReplaceFrom: 1 to: 2 with: c1).\\n\\tself assert: c3 = #(1 2 3 4 7 8 9) asOrderedCollection.\\n\\tself should: [c2 copyReplaceFrom: 3 to: 1 with: c1] raise: Error.\\n\\t\\n\\tc4 := (c2 copyReplaceFrom: 10 to: 25 with: c1).\\n\\tself assert: c4 = #(5 6 7 8 9 1 2 3 4) asOrderedCollection.\\n\\t\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'sd 3/21/2006 22:41'!\\ntestCopyWith\\n\\t\\\"Allows one to create a copy of the receiver that contains the new element at the end\\\"\\n\\t\\\"self run: #testCopyWith\\\"\\n\\t\\n\\t| c1 | \\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc1 := c1 copyWith: 6.\\n\\tself assert: c1 = #(1 2 3 4 6) asOrderedCollection.\\n\\t\\n\\t\\n\\n\\t\\n\\t\\n\\t\\n! !\\n\\n!OrderedCollectionTest methodsFor: 'testsCopying' stamp: 'zz 12/7/2005 13:47'!\\ntestReversed\\n\\t| collection1 collection2 |\\n\\tcollection1 := #('Jim' 'Mary' 'John' 'Andrew' ) asOrderedCollection.\\n\\tcollection2 := collection1 reversed.\\n\\tself assert: collection2 first = 'Andrew'.\\n\\tself assert: collection2 last = 'Jim'! !\\n\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'zz 12/7/2005 19:05'!\\ntestRemoveAllSuchThat\\n\\t| collection |\\n\\tcollection := (1 to: 10) asOrderedCollection.\\n\\tcollection\\n\\t\\tremoveAllSuchThat: [:e | e even].\\n\\tself assert: collection = (1 to: 10 by: 2) asOrderedCollection! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveAt\\n\\t\\\"Allows one to remove an element from a collection at an index\\\"\\n\\t\\\"self run:#testRemoveAt\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeAt: 2.\\n\\tself assert: (c1 = #(2 4 6) asOrderedCollection).\\n\\tself should: [c1 removeAt: 10] raise: Error.\\n\\tself should: [c1 removeAt: -1] raise: Error.\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveFirst\\n\\t\\\"Allows one to remove n element of a collection at the first\\\"\\n\\t\\\"self run:#testRemoveFirst\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeFirst: 1.\\n\\tself assert: (c1 = #(3 4 6) asOrderedCollection).\\n\\tc1 removeFirst: 2.\\n\\tself assert: (c1 = #(6) asOrderedCollection).\\n\\tself should: [c1 removeFirst: 10] raise: Error.\\n\\t\\n\\t! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveIfAbsent\\n\\t\\\"Allows one to remove an element from a collection and to copy it in another collection.\\\"\\n\\t\\\"If the element isn't in the first collection, the second collection copy the element after ifAbsent\\\"\\n\\t\\\"self run:#testRemoveIfAbsent\\\"\\n\\t\\n\\t| c1 c2 |\\n\\tc1 := #(1 2 3 4) asOrderedCollection.\\n\\tc2 := OrderedCollection new.\\n\\t\\n\\tc2 add: (c1 remove: 2 ifAbsent: [6]).\\n\\tself assert: (c1 = #(1 3 4) asOrderedCollection).\\n\\tself assert: (c2 = #(2) asOrderedCollection).\\n\\t\\n\\tc2 add: (c1 remove: 18 ifAbsent: [6]).\\n\\tself assert: (c1 = #(1 3 4) asOrderedCollection).\\n\\tself assert: (c2 = #(2 6) asOrderedCollection).! !\\n\\n!OrderedCollectionTest methodsFor: 'testsRemoving' stamp: 'sd 3/21/2006 22:39'!\\ntestRemoveLast\\n\\t\\\"Allows one to remove n element of a collection at the end\\\"\\n\\t\\\"self run:#testRemoveLast\\\" \\n\\t\\n\\t| c1 |\\n\\tc1 := #(2 3 4 6) asOrderedCollection.\\n\\tc1 removeLast: 1.\\n\\tself assert: (c1 = #(2 3 4) asOrderedCollection).\\n\\tc1 removeLast: 2.\\n\\tself assert: (c1 = #(2) asOrderedCollection).\\n\\tself should: [c1 removeLast: 10] raise: Error.! !\\nFillStyle subclass: #OrientedFillStyle\\n\\tinstanceVariableNames: 'origin direction normal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Balloon-Fills'!\\n!OrientedFillStyle commentStamp: '<historical>' prior: 0!\\nOrientedFill is an abstract superclass for fills which can be aligned appropriately.\\n\\nInstance variables:\\n\\torigin\\t<Point>\\tThe point at which to align the fill.\\n\\tdirection <Point>\\tThe direction in which the fill is defined\\n\\tnormal\\t<Point>\\tTypically, just the direction rotated by 90 degrees.!\\n\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 8/25/2001 17:03'!\\ndirection\\n\\t^direction ifNil:[direction := normal y @ normal x negated]! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:37'!\\ndirection: aPoint\\n\\tdirection := aPoint! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/14/1998 23:31'!\\nnormal\\n\\t^normal ifNil:[normal := direction y negated @ direction x]! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:37'!\\nnormal: aPoint\\n\\tnormal := aPoint! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:38'!\\norigin\\n\\t^origin! !\\n\\n!OrientedFillStyle methodsFor: 'accessing' stamp: 'ar 11/11/1998 22:38'!\\norigin: aPoint\\n\\torigin := aPoint.! !\\n\\n\\n!OrientedFillStyle methodsFor: 'testing' stamp: 'ar 6/18/1999 07:57'!\\nisOrientedFill\\n\\t\\\"Return true if the receiver keeps an orientation (e.g., origin, direction, and normal)\\\"\\n\\t^true! !\\n\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'dgd 10/17/2003 22:35'!\\naddFillStyleMenuItems: aMenu hand: aHand from: aMorph\\n\\t\\\"Add the items for changing the current fill style of the receiver\\\"\\n\\taMenu add: 'change origin' translated target: self selector: #changeOriginIn:event: argument: aMorph.\\n\\taMenu add: 'change orientation' translated target: self selector: #changeOrientationIn:event: argument: aMorph.! !\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'ar 6/18/1999 07:41'!\\nchangeOrientationIn: aMorph event: evt\\n\\t\\\"Interactively change the origin of the receiver\\\"\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:pt|\\n\\t\\tself direction: pt - self origin.\\n\\t\\tself normal: nil.\\n\\t\\taMorph changed].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.! !\\n\\n!OrientedFillStyle methodsFor: '*Morphic-Balloon' stamp: 'ar 6/18/1999 07:28'!\\nchangeOriginIn: aMorph event: evt\\n\\t\\\"Interactively change the origin of the receiver\\\"\\n\\t| handle |\\n\\thandle _ HandleMorph new forEachPointDo:[:pt|\\n\\t\\tself origin: pt.\\n\\t\\taMorph changed].\\n\\tevt hand attachMorph: handle.\\n\\thandle startStepping.! !\\nNotification subclass: #OutOfScopeNotification\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Kernel'!\\n\\n!OutOfScopeNotification methodsFor: 'as yet unclassified' stamp: 'RAA 2/5/2001 10:41'!\\ndefaultAction\\n\\n\\tself resume: false! !\\nPBPreferenceView subclass: #PBBooleanPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBBooleanPreferenceView commentStamp: '<historical>' prior: 0!\\nI am responsible for building the visual representation of a preference that accepts true and false values. This view is aimed to be used inside a PreferenceBrowser panel.!\\n\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:23'!\\nenabledButton\\n\\t| aButton aLabel |\\n\\taButton := UpdatingThreePhaseButtonMorph checkBox\\n\\t\\ttarget: self preference;\\n\\t\\tactionSelector: #togglePreferenceValue;\\n\\t\\tgetSelector: #preferenceValue;\\n\\t\\tyourself.\\n\\taLabel := (StringMorph contents: 'enabled' translated\\n\\t\\t\\t\\tfont: (StrikeFont familyName: TextStyle defaultFont familyName\\n\\t\\t\\t\\t\\t\\t\\tsize: TextStyle defaultFont pointSize - 1)).\\n\\t^self horizontalPanel\\n\\t\\taddMorphBack: aButton;\\n\\t\\taddMorphBack: aLabel;\\n\\t\\tyourself.! !\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:27'!\\nlocalToProjectButton\\n\\t| aButton aLabel |\\n\\taButton := UpdatingThreePhaseButtonMorph checkBox\\n\\t\\ttarget: self preference;\\n\\t\\tactionSelector: #toggleProjectLocalness;\\n\\t\\tgetSelector: #localToProject;\\n\\t\\tyourself.\\n\\taLabel := (StringMorph contents: 'local' translated\\n\\t\\t\\t\\tfont: (StrikeFont familyName: TextStyle defaultFont familyName\\n\\t\\t\\t\\t\\t\\t\\tsize: TextStyle defaultFont pointSize - 1)).\\t\\t\\n\\t^self horizontalPanel\\n\\t\\taddMorphBack: aButton;\\n\\t\\taddMorphBack: aLabel;\\n\\t\\tyourself.! !\\n\\n!PBBooleanPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:25'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferencesPanel\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcellInset: 7;\\n\\t\\tcolor: aColor;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self horizontalFiller; \\n\\t\\taddMorphBack: self enabledButton;\\n\\t\\taddMorphBack: self localToProjectButton;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBBooleanPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBBooleanPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:47'!\\ninitialize\\n\\tPreferenceViewRegistry ofBooleanPreferences register: self.\\n! !\\n\\n!PBBooleanPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:47'!\\nunload\\n\\tPreferenceViewRegistry ofBooleanPreferences unregister: self.! !\\nPBPreferenceView subclass: #PBColorPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBColorPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/6/2004 21:24'!\\ncolorSwatch\\n\\t^UpdatingRectangleMorph new\\n\\t\\ttarget: self preference;\\n\\t\\tgetSelector: #preferenceValue;\\n\\t\\tputSelector: #preferenceValue:;\\n\\t\\textent: 22@22;\\n\\t\\tsetBalloonText: 'click here to change the color' translated;\\n\\t\\tyourself.! !\\n\\n!PBColorPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/6/2004 21:12'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self horizontalFiller;\\n\\t\\taddMorphBack: self colorSwatch;\\n\\t\\tyourself! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBColorPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/6/2004 20:49'!\\ninitialize\\n\\tPreferenceViewRegistry ofColorPreferences register: self.! !\\n\\n!PBColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/6/2004 20:49'!\\nunload\\n\\tPreferenceViewRegistry ofColorPreferences unregister: self.! !\\nPBPreferenceView subclass: #PBHaloThemePreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBHaloThemePreferenceView commentStamp: '<historical>' prior: 0!\\nI am responsible for building the button for the Halo Theme preference!\\n\\n\\n!PBHaloThemePreferenceView methodsFor: 'initialization' stamp: 'hpt 12/8/2004 18:12'!\\ninitialize\\n\\tself addActionTitled: 'edit custom halos' \\n\\t\\ttarget: Preferences \\n\\t\\tselector: #editCustomHalos \\n\\t\\targuments: {} \\n\\t\\tballoonText: 'Click here to edit the method that defines the custom halos' translated.! !\\n\\n\\n!PBHaloThemePreferenceView methodsFor: 'user interface' stamp: 'hpt 12/8/2004 18:18'!\\nhaloThemeRadioButtons\\n\\t\\\"Answer a column of butons representing the choices of halo theme\\\"\\n\\n\\t| buttonColumn aRow aRadioButton aLabel |\\n\\tbuttonColumn := self verticalPanel.\\n\\t#(\\t(iconicHaloSpecifications iconic iconicHalosInForce\\t'circular halos with icons inside')\\n\\t\\t(classicHaloSpecs\\tclassic\\tclassicHalosInForce\\t\\t'plain circular halos')\\n\\t\\t(simpleFullHaloSpecifications\\t\\tsimple\\tsimpleHalosInForce\\t'fewer, larger halos')\\n\\t\\t(customHaloSpecs\\tcustom\\tcustomHalosInForce\\t\\t'customizable halos')) do:\\n\\n\\t\\t[:quad |\\n\\t\\t\\taRadioButton := UpdatingThreePhaseButtonMorph radioButton\\n\\t\\t\\t\\ttarget: Preferences;\\n\\t\\t\\t\\tsetBalloonText: quad fourth;\\n\\t\\t\\t\\tactionSelector: #installHaloTheme:;\\n\\t\\t\\t\\tgetSelector: quad third;\\n\\t\\t\\t\\targuments: (Array with: quad first);\\n\\t\\t\\t\\tyourself.\\n\\t\\t\\taLabel := (StringMorph contents: quad second asString)\\n\\t\\t\\t\\t\\t\\tsetBalloonText: quad fourth;\\n\\t\\t\\t\\t\\t\\tyourself.\\n\\t\\t\\taRow := self horizontalPanel\\n\\t\\t\\t\\tcellInset: 4;\\n\\t\\t\\t\\taddMorphBack: aRadioButton;\\n\\t\\t\\t\\taddMorphBack: aLabel.\\n\\t\\t\\tbuttonColumn addMorphBack: aRow].\\n\\t^ buttonColumn\\n\\n\\t\\\"(Preferences preferenceAt: #haloTheme) view tearOffButton\\\"! !\\n\\n!PBHaloThemePreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:45'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferencesPanel\\n\\t| innerPanel |\\n\\tinnerPanel := self horizontalPanel\\n\\t\\taddMorphBack: (self blankSpaceOf: 10@0);\\n\\t\\taddMorphBack: self haloThemeRadioButtons;\\n\\t\\tyourself.\\n\\t^self verticalPanel\\n\\t\\tcolor: aColor;\\n\\t\\tlayoutInset: 2;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: innerPanel.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBHaloThemePreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBHaloThemePreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:48'!\\ninitialize\\n\\tPreferenceViewRegistry ofHaloThemePreferences register: self.! !\\n\\n!PBHaloThemePreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 15:48'!\\nunload\\n\\tPreferenceViewRegistry ofHaloThemePreferences unregister: self.! !\\nPBPreferenceView subclass: #PBNumericPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:23'!\\npreferenceValue\\n\\t^self preference preferenceValue asString! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/10/2004 22:53'!\\npreferenceValue: aTextOrString\\n\\t(aTextOrString notEmpty and: [aTextOrString asString isAllDigits])\\n\\t\\tifFalse: [^false].\\n\\tself preference preferenceValue: aTextOrString asNumber.\\n\\t^true.! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:19'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self textField;\\n\\t\\tyourself.! !\\n\\n!PBNumericPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/9/2004 22:19'!\\ntextField\\n\\t^(PluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #preferenceValue\\n\\t\\taccept: #preferenceValue:)\\n\\t\\t\\thideVScrollBarIndefinitely: true;\\n\\t\\t\\tborderColor: #inset;\\n\\t\\t\\tacceptOnCR: true;\\n\\t\\t\\tcolor: Color gray veryMuchLighter;\\n\\t\\t\\tvResizing: #rigid;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\theight: TextStyle defaultFont height + 6;\\n\\t\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBNumericPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBNumericPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/9/2004 22:21'!\\ninitialize\\n\\tPreferenceViewRegistry ofNumericPreferences register: self.! !\\n\\n!PBNumericPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/9/2004 22:21'!\\nunload\\n\\tPreferenceViewRegistry ofNumericPreferences unregister: self.! !\\nMorph subclass: #PBPreferenceButtonMorph\\n\\tinstanceVariableNames: 'moreButton model preference preferenceMorphicView preferenceView'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBPreferenceButtonMorph methodsFor: 'accessing' stamp: 'hpt 12/8/2004 15:34'!\\nmodel\\n\\t^model! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 18:15'!\\nactionButtons\\n\\t^self preferenceView actions collect: [:aTuple |\\n\\t\\tself basicButton\\n\\t\\t\\t\\tlabel: aTuple first;\\n\\t\\t\\t\\ttarget: aTuple second;\\n\\t\\t\\t\\tactionSelector: aTuple third;\\n\\t\\t\\t\\targuments: aTuple fourth;\\n\\t\\t\\t\\tsetBalloonText: aTuple fifth ]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 8/24/2005 20:33'!\\naddExtraControls\\n\\t| m |\\n\\tm := self horizontalPanel\\n\\t\\tcellInset: 3;\\n\\t\\taddAllMorphs: self actionButtons;\\n\\t\\taddMorphBack: self horizontalFiller;\\n\\t\\taddMorphBack: self moreButton;\\n\\t\\tyourself.\\n\\tself \\n\\t\\taddMorphBack: (self blankSpaceOf: 2@2);\\n\\t\\taddMorphBack: self preferenceHelpTextMorph;\\n\\t\\tfullBounds; \\\"to force a layout compute needed by the textMorphs's autoFit\\\"\\n\\t\\taddMorphBack: m\\n! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 17:16'!\\nadvancedOptionsSelected\\n\\tself preferenceView offerPreferenceNameMenu: self model! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 18:17'!\\nmoreButton\\n\\t^moreButton ifNil: \\n\\t\\t[moreButton := self basicButton \\n\\t\\t\\t\\t\\t\\tlabel: 'more' translated; \\n\\t\\t\\t\\t\\t\\tsetBalloonText: \\n\\t\\t\\t\\t\\t\\t\\t'Click here for advanced options'translated;\\n\\t\\t\\t\\t\\t\\tactionSelector: #advancedOptionsSelected]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npreferenceHelpTextMorph\\n\\t| text tm |\\n\\ttext := self preferenceHelpText.\\n\\ttm := TextMorph new\\n\\t\\tcontents: text;\\n\\t\\twrapOnOff;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tlock: true;\\n\\t\\tvisible: text notEmpty;\\n\\t\\tyourself. \\\"we don't want an empty textmorph showing\\\"\\n\\ttm isAutoFit\\n\\t\\tifFalse: [tm autoFitOnOff].\\n\\t^tm.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'extra controls' stamp: 'hpt 12/8/2004 16:40'!\\nremoveExtraControls\\n\\tself submorphs copyWithoutFirst do: [:ea | ea delete]! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'highlighting' stamp: 'hpt 12/8/2004 15:55'!\\nhighlightOff\\n\\tself beTransparent.\\n\\tself label color: Color black.\\n\\tself removeExtraControls.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'highlighting' stamp: 'hpt 12/8/2004 17:25'!\\nhighlightOn\\n\\tself color: (Color gray alpha: 0.1).\\n\\tself label color: Color red.\\n\\tself addExtraControls.! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'initialization' stamp: 'hpt 12/8/2004 15:38'!\\ninitializeLayout\\n\\tself layoutPolicy: TableLayout new;\\n\\t\\tbeTransparent;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 0;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap.\\t\\t! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'initialization' stamp: 'hpt 12/8/2004 15:38'!\\ninitializeWithPreference: aPreference model: aModel\\n\\tpreference := aPreference.\\n\\tmodel := aModel.\\n\\tself initializeLayout.\\n\\tself addMorphBack: self preferenceMorphicView.\\n\\tself highlightOff.! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:42'!\\nlabel\\n\\t^self preferenceMorphicView firstSubmorph! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:13'!\\npreference\\n\\t^preference! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:56'!\\npreferenceHelp\\n\\t| help name |\\n\\thelp := self preference helpString withBlanksTrimmed.\\n\\tname := self preference name.\\n\\t(self caseInsensitiveBeginsWith: name in: help)\\n\\t\\tifTrue: [help := help allButFirst: name size].\\n\\t(help notEmpty and: [help first = $:])\\n\\t\\tifTrue: [help := help allButFirst].\\n\\t^help withBlanksTrimmed.\\n! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:25'!\\npreferenceHelpText\\n\\t^self preferenceHelp asText\\n\\t\\taddAttribute: TextEmphasis italic;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'hpt 12/8/2004 15:48'!\\npreferenceMorphicView\\n\\t^preferenceMorphicView\\n\\t\\tifNil: \\n\\t\\t\\t[preferenceMorphicView := self preferenceView\\n\\t\\t\\t\\trepresentativeButtonWithColor: Color transparent inPanel: self model.\\n\\t\\t\\tpreferenceMorphicView hResizing: #spaceFill.\\n\\t\\t\\t^preferenceMorphicView]! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'preference accessing' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npreferenceView\\n\\t^preferenceView\\n\\t\\tifNil: [preferenceView := self preference viewForPanel: self model.]! !\\n\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 17:06'!\\nbasicButton\\n\\t| button |\\n\\tbutton := SimpleButtonMorph new.\\n\\tbutton\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: self paneColor;\\n\\t\\ton: #mouseEnter send: #value to: [button borderWidth: 2];\\n\\t\\ton: #mouseLeave send: #value to: [button borderWidth: 1];\\n\\t\\tvResizing: #rigid;\\n\\t\\theight: (TextStyle defaultFont height + 4);\\n\\t\\tuseSquareCorners;\\n\\t\\tclipSubmorphs: true;\\n\\t\\tcolor: self paneColor muchLighter;\\n\\t\\ttarget: self.\\n\\t^button! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:59'!\\nbasicPanel\\n\\t^BorderedMorph new\\n\\t\\tbeTransparent;\\n\\t\\textent: 0@0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 0;\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #center;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tyourself! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:29'!\\nblankSpaceOf: aPoint\\n\\t^Morph new \\n\\t\\tbeTransparent;\\n\\t\\textent: aPoint; \\n\\t\\tyourself! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:43'!\\ncaseInsensitiveBeginsWith: prefix in: string\\n\\t^(string findString: prefix startingAt: 1 caseSensitive: false) = 1! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 16:42'!\\nhorizontalFiller\\n\\t^self horizontalPanel\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 16:42'!\\nhorizontalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #center;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'stephaneducasse 2/4/2006 20:39'!\\npaneColor\\n\\t| browser |\\n\\tbrowser := (self ownerChain \\n\\t\\tdetect: [:ea | ea isKindOf: PreferenceBrowserMorph] \\n\\t\\tifNone: [^Color black]) .\\n\\t^browser paneColor! !\\n\\n!PBPreferenceButtonMorph methodsFor: 'utility methods' stamp: 'hpt 12/8/2004 15:27'!\\nverticalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBPreferenceButtonMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PBPreferenceButtonMorph class methodsFor: 'instance creation' stamp: 'hpt 12/8/2004 15:20'!\\npreference: aPreference\\n\\t^self preference: aPreference model: nil! !\\n\\n!PBPreferenceButtonMorph class methodsFor: 'instance creation' stamp: 'hpt 12/8/2004 15:19'!\\npreference: aPreference model: aModel\\n\\t^self new\\n\\t\\tinitializeWithPreference: aPreference model: aModel;\\n\\t\\tyourself.! !\\nPreferenceView subclass: #PBPreferenceView\\n\\tinstanceVariableNames: 'actions'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n!PBPreferenceView commentStamp: '<historical>' prior: 0!\\nI am just a refactor of all the common method of the PreferenceBrowser preference views!\\n\\n\\n!PBPreferenceView methodsFor: 'actions' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nactions\\n\\t^actions ifNil: [actions := OrderedCollection new.]! !\\n\\n!PBPreferenceView methodsFor: 'actions' stamp: 'hpt 12/8/2004 18:13'!\\naddActionTitled: aTitle target: aTarget selector: aSelector arguments: aCollection balloonText: aText\\n\\tself actions add: { aTitle. aTarget. aSelector. aCollection. aText }! !\\n\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:42'!\\nbasicPanel\\n\\t^BorderedMorph new\\n\\t\\tbeTransparent;\\n\\t\\textent: 0@0;\\n\\t\\tborderWidth: 0;\\n\\t\\tlayoutInset: 0;\\n\\t\\tcellInset: 2;\\n\\t\\tlayoutPolicy: TableLayout new;\\n\\t\\tlistCentering: #topLeft;\\n\\t\\tcellPositioning: #center;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tyourself! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:15'!\\nblankSpaceOf: aPoint\\n\\t^Morph new \\n\\t\\tbeTransparent;\\n\\t\\textent: aPoint; \\n\\t\\tyourself! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:13'!\\nhorizontalFiller\\n\\t^self horizontalPanel\\n\\t\\thResizing: #spaceFill;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:43'!\\nhorizontalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #center;\\n\\t\\tlistDirection: #leftToRight;\\n\\t\\tyourself.! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 00:48'!\\nofferPreferenceNameMenu: aPreferenceBrowser\\n\\t\\\"the user clicked on a preference name -- put up a menu\\\"\\n\\n\\t| aMenu |\\t\\t\\t\\n\\taMenu := MenuMorph new \\n\\t\\tdefaultTarget: self preference;\\n\\t\\taddTitle: self preference name.\\n\\n\\t(Preferences okayToChangeProjectLocalnessOf: self preference name) ifTrue:\\n\\t\\t[aMenu addUpdating: #isProjectLocalString target: self preference action: #toggleProjectLocalness.\\n\\t\\taMenu balloonTextForLastItem: 'Some preferences are best applied uniformly to all projects, and others are best set by each individual project. If this item is checked, then this preference will be printed in bold and will have a separate value for each project'].\\n\\n\\taMenu add: 'browse senders' translated target: self systemNavigation selector: #browseAllCallsOn: argument: self preference name.\\n\\taMenu balloonTextForLastItem: 'This will open a method-list browser on all methods that the send the preference \\\"', self preference name, '\\\".'. \\n\\taMenu add: 'show category...' target: aPreferenceBrowser selector: #findCategoryFromPreference: argument: self preference name.\\n\\taMenu balloonTextForLastItem: 'Allows you to find out which category, or categories, this preference belongs to.'.\\n\\n\\tSmalltalk isMorphic ifTrue:\\n\\t\\t[aMenu add: 'hand me a button for this preference' target: self selector: #tearOffButton.\\n\\t\\taMenu balloonTextForLastItem: 'Will give you a button that governs this preference, which you may deposit wherever you wish'].\\n\\n\\taMenu add: 'copy this name to clipboard' target: self preference selector: #copyName.\\n\\taMenu balloonTextForLastItem: 'Copy the name of the preference to the text clipboard, so that you can paste into code somewhere'.\\n\\n\\taMenu popUpInWorld! !\\n\\n!PBPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:43'!\\nverticalPanel\\n\\t^self basicPanel\\n\\t\\tcellPositioning: #topLeft;\\n\\t\\tlistDirection: #topToBottom;\\n\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBPreferenceView class methodsFor: 'view registry' stamp: 'hpt 9/26/2004 16:09'!\\nhandlesPanel: aPreferencePanel\\n\\t^aPreferencePanel isKindOf: PreferenceBrowser! !\\nPBPreferenceView subclass: #PBTextPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 12/10/2004 22:46'!\\npreferenceValue\\n\\t^self preference preferenceValue ifNil: ['']! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:38'!\\npreferenceValue: aTextOrString\\n\\tself preference preferenceValue: aTextOrString asString.\\n\\t^true.! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:41'!\\nrepresentativeButtonWithColor: aColor inPanel: aPreferenceBrowser\\n\\t^self horizontalPanel\\n\\t\\tlayoutInset: 2;\\n\\t\\tcolor: aColor;\\n\\t\\tcellInset: 20;\\n\\t\\tcellPositioning: #center;\\n\\t\\taddMorphBack: (StringMorph contents: self preference name);\\n\\t\\taddMorphBack: self textField;\\n\\t\\tyourself.! !\\n\\n!PBTextPreferenceView methodsFor: 'user interface' stamp: 'hpt 9/26/2004 11:41'!\\ntextField\\n\\t^(PluggableTextMorph\\n\\t\\ton: self\\n\\t\\ttext: #preferenceValue\\n\\t\\taccept: #preferenceValue:)\\n\\t\\t\\thideVScrollBarIndefinitely: true;\\n\\t\\t\\tborderColor: #inset;\\n\\t\\t\\tacceptOnCR: true;\\n\\t\\t\\tcolor: Color gray veryMuchLighter;\\n\\t\\t\\tvResizing: #rigid;\\n\\t\\t\\thResizing: #spaceFill;\\n\\t\\t\\theight: TextStyle defaultFont height + 6;\\n\\t\\t\\tyourself.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBTextPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBTextPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 17:01'!\\ninitialize\\n\\tPreferenceViewRegistry ofTextPreferences register: self.! !\\n\\n!PBTextPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 9/26/2004 17:01'!\\nunload\\n\\tPreferenceViewRegistry ofTextPreferences unregister: self.! !\\nPBColorPreferenceView subclass: #PBWindowColorPreferenceView\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PreferenceBrowser'!\\n\\n!PBWindowColorPreferenceView methodsFor: 'initialization' stamp: 'hpt 12/8/2004 18:38'!\\ninitialize\\n\\tsuper initialize.\\n\\tself addActionTitled: 'Bright' target: Preferences selector: #installBrightWindowColors arguments: {} balloonText: 'Use standard bright colors for all windows' translated.\\n\\tself addActionTitled: 'Pastel' target: Preferences selector: #installPastelWindowColors arguments: {} balloonText: 'Use standard pastel colors for all windows' translated.\\t\\n\\tself addActionTitled: 'White' target: Preferences selector: #installUniformWindowColors arguments: {} balloonText: 'Use white backgrounds for all standard windows' translated.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPBWindowColorPreferenceView class\\n\\tinstanceVariableNames: ''!\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\ninitialize\\n\\tself viewRegistry register: self.! !\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\nunload\\n\\tself viewRegistry unregister: self.! !\\n\\n!PBWindowColorPreferenceView class methodsFor: 'class initialization' stamp: 'hpt 12/8/2004 18:40'!\\nviewRegistry\\n\\t^(PreferenceViewRegistry registryOf: #windowColorPreferences)\\n\\t\\tviewOrder: 6;\\n\\t\\tyourself.! !\\nPrimCallControllerAbstract subclass: #PCCByCompilation\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByCompilation commentStamp: 'sr 6/16/2004 09:00' prior: 0!\\nThis class is for switching external prim calls (primitiveExternalCall) on and off.\\n\\nIt is best suited for permanently switching plugin calls off while preserving the possibility to switch them on later. For plugin testing purposes you probably should use PCCByLiterals for temporarily switch on/off them instead.\\n\\nIt works on a source code basis by compilation:\\n\\tDisabling works by putting an enabled prim call into a special comment followed by a recompile to transform it into a disabled one.\\n\\tEnabling works by pulling the disabled prim call out of the special comment followed by a recompile to transform it into an enabled one.\\n\\nAs a consequence, enabling of prims only works with method sources containing the mentioned special comment, which normally has been generated by this tool for disabling the corresponding prim.\\n\\nPlease look into superclass PrimCallControllerAbstract for more info and the user interface.\\n\\nStructure:\\n No instVars here: look into superclass.\\n\\nImplementation note:\\nTo harden it for sunit testing purposes some special accessing of the source code has been necessary: to avoid accessing different processes a sources file at once, followed by generating garbage, the process priority of actions leading to these accesses has been increased (sunit tests run in the background). A better solution would be to introduce a source file locking mechanism.!\\n]style[(107 11 138 13 5 11 62 14 3 9 124 8 245 9 36 9 26 28 26 93 20 384)f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2LPCCByLiterals Comment;,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2,f2FAccuny#12,f3FAccuny#12,f2FAccuny#12,f2,f2LPrimCallControllerAbstract Comment;,f2,FAccuny#15uf2,f2!\\n\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:30'!\\ncomment\\n\\t^ '{prim disabled by ', self className, '} '! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\ndisabledPrimStartString\\n\\t^ '\\\"', self comment, self enabledPrimStartString! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\ndisabledPrimStopChar\\n\\t\\\"end of disabling comment\\\"\\n\\t^ $\\\"! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\nenabledPrimStartString\\n\\t^ '<primitive:'! !\\n\\n!PCCByCompilation methodsFor: 'string constants' stamp: 'sr 6/7/2004 03:31'!\\nenabledPrimStopChar\\n\\t^ $>! !\\n\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'sr 6/11/2004 06:33'!\\nextractCallModuleNames: aMethodRef \\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tifTrue: [self extractCallModuleNamesFromLiterals: aMethodRef]\\n\\t\\tifFalse: [| src | \\n\\t\\t\\t\\\"try source\\\"\\n\\t\\t\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t\\t\\t[src := aMethodRef sourceString]\\n\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\tself extractCallNamesFromPrimString: ((self extractDisabledPrimStringFrom: src)\\n\\t\\t\\t\\t\\tifNil: [\\\"no disabled prim string found\\\"\\n\\t\\t\\t\\t\\t\\t^ nil]) first]! !\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'sr 6/14/2004 21:38'!\\nmethodsWithCall\\n\\t\\\"Expensive!! For just querying the system unaffected by an instance of \\n\\tthis class use PCCByLiterals instead.\\\"\\n\\t^ self methodsWithCompiledCall , self methodsWithDisabledCall! !\\n\\n!PCCByCompilation methodsFor: 'ui querying' stamp: 'md 8/27/2005 17:17'!\\nmethodsWithDisabledCall\\n\\t\\\"Answer a SortedCollection of all the methods that contain, in source \\n\\tcode, the substring indicating a disabled prim.\\\"\\n\\t\\\"The alternative implementation \\n\\t\\t^ SystemNavigation new allMethodsWithSourceString: self disabledPrimStartString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmatchCase: true \\n\\talso searches in class comments.\\\"\\n\\t| list classCount string |\\n\\tstring := self disabledPrimStartString.\\n\\tlist := Set new.\\n\\t'Searching all method source code...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: Smalltalk classNames size * 2 \\\"classes with their metaclasses\\\"\\n\\t\\tduring: [:bar |\\n\\t\\t\\tclassCount := 0.\\n\\t\\t\\tSystemNavigation default\\n\\t\\t\\t\\tallBehaviorsDo: [:class | \\n\\t\\t\\t\\t\\tbar value: (classCount := classCount + 1).\\n\\t\\t\\t\\t\\tclass\\n\\t\\t\\t\\t\\t\\tselectorsDo: [:sel | \\n\\t\\t\\t\\t\\t\\t\\t| src | \\n\\t\\t\\t\\t\\t\\t\\t\\\"higher priority to avoid source file accessing \\n\\t\\t\\t\\t\\t\\t\\terrors\\\"\\n\\t\\t\\t\\t\\t\\t\\t[src := class sourceCodeAt: sel]\\n\\t\\t\\t\\t\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\t\\t\\t\\t\\t(src\\n\\t\\t\\t\\t\\t\\t\\t\\tfindString: string\\n\\t\\t\\t\\t\\t\\t\\t\\tstartingAt: 1\\n\\t\\t\\t\\t\\t\\t\\t\\tcaseSensitive: true) > 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [sel isDoIt ifFalse: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlist add: (MethodReference new setStandardClass: class methodSymbol: sel)]]]]].\\n\\t^ list asSortedCollection! !\\n\\n\\n!PCCByCompilation methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:26'!\\nexistsCallIn: aMethodRef \\n\\t\\\"Here existsCompiledCallIn: (see also comment there) is sufficient to \\n\\tquery for enabled and failed, but not for disabled prim calls: so check \\n\\tfor disabled ones in sources, too.\\\"\\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tor: [self existsDisabledCallIn: aMethodRef]! !\\n\\n!PCCByCompilation methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:07'!\\nexistsDisabledCallIn: aMethodRef \\n\\t| src |\\n\\t^ (self existsCompiledCallIn: aMethodRef) not\\n\\t\\tand: [\\\"higher priority to avoid source file accessing errors\\\"\\n\\t\\t\\t[src := aMethodRef sourceString]\\n\\t\\t\\t\\tvalueAt: self higherPriority.\\n\\t\\t\\tself methodSourceContainsDisabledCall: src]! !\\n\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:26'!\\ndisabled2EnabledPrimMethodString: aSourceString \\n\\t| start stop primString extract |\\n\\textract := self extractDisabledPrimStringFrom: aSourceString.\\n\\tprimString := extract at: 1.\\n\\tstart := extract at: 2.\\n\\tstop := start + primString size - 1.\\n\\t^ aSourceString\\n\\t\\tcopyReplaceFrom: start\\n\\t\\tto: stop\\n\\t\\twith: (self disabled2EnabledPrimString: primString)! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:26'!\\ndisabled2EnabledPrimString: aDisabledPrimString\\n\\t\\\"remove comment quotes and comment after first comment quote\\\"\\n\\t| enabledPrimString |\\n\\tenabledPrimString := aDisabledPrimString copyFrom: self comment size + 2 to: aDisabledPrimString size - 1.\\n\\t^ enabledPrimString! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:28'!\\nenabled2DisabledPrimMethodString: aSourceString \\n\\t| start stop primString extract |\\n\\textract := self extractEnabledPrimStringFrom: aSourceString.\\n\\tprimString := extract at: 1.\\n\\tstart := extract at: 2.\\n\\tstop := start + primString size - 1.\\n\\t^ aSourceString\\n\\t\\tcopyReplaceFrom: start\\n\\t\\tto: stop\\n\\t\\twith: (self enabled2DisabledPrimString: primString)! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:28'!\\nenabled2DisabledPrimString: anEnabledPrimString \\n\\t| disabledPrimString |\\n\\tdisabledPrimString := '\\\"' , self comment , anEnabledPrimString , '\\\"'.\\n\\t^ disabledPrimString! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'stephaneducasse 2/3/2006 22:39'!\\nextractCallNamesFromPrimString: aString\\n\\t\\\"method works for both enabled and disabled prim strings\\\"\\n\\t\\\"<primitive: 'doSomething' module:'ModuleFoo'\\\"\\n\\t| tokens |\\n\\ttokens := aString findTokens: ''''.\\n\\t^ (tokens at: 2) -> (tokens at: 4 ifAbsent: [nil])! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/11/2004 07:10'!\\nextractDisabledPrimStringFrom: aSourceString \\n\\t| startString start stop |\\n\\tstartString := self disabledPrimStartString.\\n\\tstart := aSourceString findString: startString.\\n\\tstart = 0\\n\\t\\tifTrue: [^ nil].\\n\\tstop := aSourceString indexOf: self disabledPrimStopChar startingAt: start + startString size.\\n\\tstop = 0\\n\\t\\tifTrue: [^ nil].\\n\\t^ {aSourceString copyFrom: start to: stop. start}! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:29'!\\nextractEnabledPrimStringFrom: aSourceString \\n\\t| startString start stop |\\n\\tstartString := self enabledPrimStartString.\\n\\tstart := aSourceString findString: startString.\\n\\tstart = 0\\n\\t\\tifTrue: [^ nil].\\n\\tstop := aSourceString indexOf: self enabledPrimStopChar startingAt: start + startString size.\\n\\tstop = 0\\n\\t\\tifTrue: [^ nil].\\n\\t^ {aSourceString copyFrom: start to: stop. start}! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/7/2004 03:29'!\\nhigherPriority\\n\\t\\\"this priority seems to be necessary to avoid source file accessing errors\\\"\\n\\t^ Processor userSchedulingPriority + 1! !\\n\\n!PCCByCompilation methodsFor: 'private' stamp: 'sr 6/11/2004 07:06'!\\nmethodSourceContainsDisabledCall: methodSource \\n\\t^ (methodSource findString: self disabledPrimStartString)\\n\\t\\t~= 0! !\\n\\n\\n!PCCByCompilation methodsFor: 'private user interface' stamp: 'sr 6/14/2004 01:37'!\\nprivateDisableCallIn: aMethodRef \\n\\t\\\"Disables enabled or failed external prim call by recompiling method \\n\\twith prim call commented out, will be called by superclass.\\\"\\n\\t| src newMethodSource |\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[src := aMethodRef sourceString]\\n\\t\\tvalueAt: self higherPriority.\\n\\tnewMethodSource := self enabled2DisabledPrimMethodString: src.\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[aMethodRef actualClass\\n\\t\\tcompile: newMethodSource\\n\\t\\tclassified: (aMethodRef actualClass whichCategoryIncludesSelector: aMethodRef methodSymbol)\\n\\t\\tnotifying: nil]\\n\\t\\tvalueAt: self higherPriority! !\\n\\n!PCCByCompilation methodsFor: 'private user interface' stamp: 'sr 6/14/2004 02:10'!\\nprivateEnableCallIn: aMethodRef \\n\\t\\\"Enables disabled external prim call by recompiling method with prim \\n\\tcall taken from disabling comment, will be called by superclass.\\\"\\n\\t| src newMethodSource |\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[src := aMethodRef sourceString]\\n\\t\\tvalueAt: self higherPriority.\\n\\tnewMethodSource := self disabled2EnabledPrimMethodString: src.\\n\\t\\\"higher priority to avoid source file accessing errors\\\"\\n\\t[aMethodRef actualClass\\n\\t\\tcompile: newMethodSource\\n\\t\\tclassified: (aMethodRef actualClass whichCategoryIncludesSelector: aMethodRef methodSymbol)\\n\\t\\tnotifying: nil]\\n\\t\\tvalueAt: self higherPriority! !\\nPrimCallControllerAbstractTest subclass: #PCCByCompilationTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByCompilationTest commentStamp: 'sr 6/14/2004 22:05' prior: 0!\\nPCCByCompilation tests.\\n\\nTests are in the superclass and inherited from there.!\\n\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/11/2004 05:22'!\\nclassToBeTested\\n\\t^ PCCByCompilation! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:36'!\\ndisabledCallSelectors\\n\\t^ #(#cDisabledRealExternalCall #cDisabledRealExternalCallNaked #cDisabledRealExternalCallOrPrimitiveFailed #cDisabledExternalCallWithoutModule )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:34'!\\nenabledCallSelectors\\n\\t^ #(#cRealExternalCall #cRealExternalCallNaked #cRealExternalCallOrPrimitiveFailed #cExternalCallWithoutModule )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:44'!\\nexampleModuleName\\n\\t^ 'CPCCT'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/15/2004 02:42'!\\nfailModuleName\\n\\t^ 'CFailModule'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/14/2004 00:14'!\\nfailedCallSelector\\n\\t^ #cFailedCall! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:40'!\\nmethodSelectorsToExampleModule\\n\\t^ #(#cExternalCall1 #cExternalCall2 )! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameNotWithSingularCallName\\n\\t^ 'CNotOne'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameWithSingularCallName\\n\\t^ 'COne'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 09:52'!\\nnoExternalCallSelector\\n\\t^ #cNoExternalCall! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:28'!\\nrealExternalCallOrPrimitiveFailedSelector\\n\\t^ #cRealExternalCallOrPrimitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:54'!\\nsingularCallName\\n\\t\\\"occurrs exactly once as prim call name in >>cSingularExternalCall\\\"\\n\\t^ 'cSingularExternalCall'! !\\n\\n!PCCByCompilationTest methodsFor: 'constants' stamp: 'sr 6/14/2004 23:33'!\\nsingularCallSelector\\n\\t^ #cSingularExternalCall! !\\n\\n\\n!PCCByCompilationTest methodsFor: 'example module' stamp: 'md 9/6/2005 19:39'!\\ncExternalCall1\\n\\t<primitive: 'prim1' module: 'CPCCT'>\\n! !\\n\\n!PCCByCompilationTest methodsFor: 'example module' stamp: 'md 9/6/2005 19:39'!\\ncExternalCall2\\n\\t\\t<primitive:'prim2'module:'CPCCT'>\\n\\t\\tself primitiveFailed! !\\n\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/11/2004 05:36'!\\ncDisabledExternalCallWithoutModule\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName'>\\\"\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCall\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCallNaked\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 23:54'!\\ncDisabledRealExternalCallOrPrimitiveFailed\\n\\t\\\"{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>\\\"\\n\\tself primitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:48'!\\ncExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'md 9/6/2005 19:39'!\\ncFailedCall\\n\\t<primitive: 'primGetModuleName' module:'CFailModule'>\\n\\t^ 'failed call'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:48'!\\ncNoExternalCall\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\ncRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\ncRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'md 9/6/2005 19:39'!\\ncRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\tself primitiveFailed! !\\n\\n!PCCByCompilationTest methodsFor: 'test methods' stamp: 'sr 6/15/2004 04:35'!\\ncSingularExternalCall\\n\\t<primitive: 'cSingularExternalCall' module:'COne'>\\n\\t^ 'Hello World!!'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCCByCompilationTest class\\n\\tinstanceVariableNames: ''!\\n\\n!PCCByCompilationTest class methodsFor: 'Testing' stamp: 'sr 6/7/2004 12:01'!\\nisAbstract\\n\\t^ false! !\\nPrimCallControllerAbstract subclass: #PCCByLiterals\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByLiterals commentStamp: 'sr 6/16/2004 09:14' prior: 0!\\nThis class is for switching external prim calls (primitiveExternalCall) on and off.\\n\\nIt is best suited for plugin testing purposes with temporarily switching plugin calls off and on. For permanently switching plugin calls off while preserving the possibility to switch them on later, you should use PCCByCompilation instead.\\n\\nIt works by manipulating literals in the CompiledMethods:\\n\\tDisabling works by changing the function index in the first literal of the CompiledMethod to a negative value (-2). This leads to a fast fail (value -2 is used for disabling to make a difference to the standard failed value of -1).\\n\\tEnabling works by changing the function index in the first literal of the CompiledMethod to 0, followed by flushing the method cache. This enforces a fresh lookup.\\n\\nPlease look into superclass PrimCallControllerAbstract for more info and the user interface.\\n\\nStructure:\\n No instVars here: look into superclass.!\\n]style[(136 11 40 11 101 16 10 1 9 2 14 8 26 9 224 8 157 28 26 91)f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2LPCCByCompilation Comment;,f2FAccuny#12,f2,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12b,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2FAccuny#12i,f2FAccuny#12,f2,f2LPrimCallControllerAbstract Comment;,f2!\\n\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/11/2004 07:04'!\\nextractCallModuleNames: aMethodRef \\n\\t^ (self existsCallIn: aMethodRef)\\n\\t\\tifTrue: [self extractCallModuleNamesFromLiterals: aMethodRef]! !\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/11/2004 07:05'!\\nmethodsWithCall\\n\\t^ self methodsWithCompiledCall! !\\n\\n!PCCByLiterals methodsFor: 'ui querying' stamp: 'sr 6/14/2004 21:24'!\\nmethodsWithDisabledCall\\n\\t^ self methodsWithCompiledCall\\n\\t\\tselect: [:mRef | (mRef compiledMethod literals first at: 4)\\n\\t\\t\\t\\t= -2]! !\\n\\n\\n!PCCByLiterals methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:04'!\\nexistsCallIn: aMethodRef \\n\\t\\\"Here >>existsCompiledCallIn: (see also comment there) is sufficient to \\n\\tquery for all enabled, failed and disabled prim calls; for the by \\n\\tcompiler version it is not sufficient for disabled ones.\\\"\\n\\t^ self existsCompiledCallIn: aMethodRef! !\\n\\n!PCCByLiterals methodsFor: 'ui testing' stamp: 'sr 6/11/2004 07:30'!\\nexistsDisabledCallIn: aMethodRef \\n\\t^ (self existsCompiledCallIn: aMethodRef)\\n\\t\\tand: [(aMethodRef compiledMethod literals first at: 4)\\n\\t\\t\\t\\t= -2]! !\\n\\n\\n!PCCByLiterals methodsFor: 'private user interface' stamp: 'sr 6/14/2004 01:35'!\\nprivateDisableCallIn: aMethodRef \\n\\t\\\"Disables enabled or failed external prim call by filling function ref \\n\\tliteral with special fail value, will be called by superclass.\\\"\\n\\taMethodRef compiledMethod literals first at: 4 put: -2! !\\n\\n!PCCByLiterals methodsFor: 'private user interface' stamp: 'sr 6/14/2004 02:07'!\\nprivateEnableCallIn: aMethodRef\\n\\t\\\"Enables disabled external prim call.\\\"\\n\\tself privateEnableViaLiteralIn: aMethodRef! !\\nPrimCallControllerAbstractTest subclass: #PCCByLiteralsTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-PrimCallController'!\\n!PCCByLiteralsTest commentStamp: 'sr 6/14/2004 22:05' prior: 0!\\nPCCByLiterals tests.\\n\\nTests are in the superclass and inherited from there.!\\n\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/11/2004 05:23'!\\nclassToBeTested\\n\\t^ PCCByLiterals! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:37'!\\ndisabledCallSelectors\\n\\t^ #(#lDisabledRealExternalCall #lDisabledRealExternalCallNaked #lDisabledRealExternalCallOrPrimitiveFailed #lDisabledExternalCallWithoutModule )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:34'!\\nenabledCallSelectors\\n\\t^ #(#lRealExternalCall #lRealExternalCallNaked #lRealExternalCallOrPrimitiveFailed #lExternalCallWithoutModule )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:45'!\\nexampleModuleName\\n\\t^ 'LPCCT'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/15/2004 02:42'!\\nfailModuleName\\n\\t^ 'LFailModule'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/14/2004 00:12'!\\nfailedCallSelector\\n\\t^ #lFailedCall! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:41'!\\nmethodSelectorsToExampleModule\\n\\t^ #(#lExternalCall1 #lExternalCall2 )! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameNotWithSingularCallName\\n\\t^ 'LNotOne'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 08:47'!\\nmoduleNameWithSingularCallName\\n\\t^ 'LOne'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:16'!\\nnoExternalCallSelector\\n\\t^ #lNoExternalCall! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:29'!\\nrealExternalCallOrPrimitiveFailedSelector\\n\\t^ #lRealExternalCallOrPrimitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/7/2004 10:54'!\\nsingularCallName\\n\\t\\\"occurrs exactly once as prim call name in >>lSingularExternalCall\\\"\\n\\t^ 'lSingularExternalCall'! !\\n\\n!PCCByLiteralsTest methodsFor: 'constants' stamp: 'sr 6/14/2004 23:32'!\\nsingularCallSelector\\n\\t^ #lSingularExternalCall! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'example module' stamp: 'sr 6/7/2004 08:39'!\\nlExternalCall1\\n\\t<primitive: 'prim1' module: 'LPCCT'>\\n! !\\n\\n!PCCByLiteralsTest methodsFor: 'example module' stamp: 'sr 6/7/2004 08:39'!\\nlExternalCall2\\n\\t\\t<primitive:'prim2'module:'LPCCT'>\\n\\t\\tself primitiveFailed! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 08:51'!\\nlDisabledExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlDisabledRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'> \\\"primitiveExternalCall\\\" \\n\\tself primitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:59'!\\nlExternalCallWithoutModule\\n\\t<primitive: 'primGetModuleName'> \\\"primitiveExternalCall\\\" \\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/15/2004 02:41'!\\nlFailedCall\\n\\t<primitive: 'primGetModuleName' module:'LFailModule'>\\n\\t^ 'failed call'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 09:57'!\\nlNoExternalCall\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCall\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\t^ 'Hello World!!'! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCallNaked\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/13/2004 21:14'!\\nlRealExternalCallOrPrimitiveFailed\\n\\t<primitive: 'primGetModuleName' module:'LargeIntegers'>\\n\\tself primitiveFailed! !\\n\\n!PCCByLiteralsTest methodsFor: 'test methods' stamp: 'sr 6/7/2004 10:52'!\\nlSingularExternalCall\\n\\t<primitive: 'lSingularExternalCall' module:'LOne'>\\n\\t^ 'Hello World!!'! !\\n\\n\\n!PCCByLiteralsTest methodsFor: 'tests' stamp: 'sr 6/7/2004 11:30'!\\nsetUp\\n\\tsuper setUp.\\n\\t\\\"disable external calls\\\"\\n\\t(self class selectors\\n\\t\\tselect: [:sel | sel beginsWith: 'lDisabled'])\\n\\t\\tdo: [:sel | (self class >> sel) literals first at: 4 put: -2]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCCByLiteralsTest class\\n\\tinstanceVariableNames: ''!\\n\\n!PCCByLiteralsTest class methodsFor: 'Testing' stamp: 'sr 6/7/2004 12:01'!\\nisAbstract\\n\\t^ false! !\\nImageReadWriter subclass: #PCXReadWriter\\n\\tinstanceVariableNames: 'version encoding colorPlanes isGrayScale width height bitsPerPixel colorPalette rowByteSize'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n\\n!PCXReadWriter methodsFor: 'accessing' stamp: 'tao 10/6/97 10:11'!\\nnextImage\\n\\t\\\"Read in the next PCX image from the stream.\\\"\\n\\n\\t| bytes form |\\n\\tself readHeader.\\n\\tbytes _ self readBody.\\n\\tcolorPalette _ self readPalette.\\n\\tself close.\\n\\tform _ ColorForm extent: width@height depth: bitsPerPixel.\\n\\t(Form new hackBits: bytes) displayOn: (Form new hackBits: form bits).\\n\\tform colors: colorPalette.\\n\\t^ form\\n! !\\n\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 08:38'!\\nnextWord\\n\\t^self next + (self next bitShift: 8)! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 10:07'!\\nreadBody\\n\\n\\t| array scanLine rowBytes position byte count pad |\\n\\tpad _ #(0 3 2 1) at: (width \\\\\\\\ 4 + 1).\\n\\tarray _ ByteArray new: ((width + pad) * height * bitsPerPixel) // 8.\\n\\tscanLine _ ByteArray new: rowByteSize.\\n\\tposition _ 1.\\n\\t1 to: height do:\\n\\t\\t[:line |\\n\\t\\trowBytes _ 0.\\n\\t\\t[rowBytes < rowByteSize] whileTrue:\\n\\t\\t\\t[byte _ self next.\\n\\t\\t\\tbyte < 16rC0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[rowBytes _ rowBytes + 1.\\n\\t\\t\\t\\t\\tscanLine at: rowBytes put: byte]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[count _ byte - 16rC0.\\n\\t\\t\\t\\t\\tbyte _ self next.\\n\\t\\t\\t\\t\\t1 to: count do: [:i | scanLine at: rowBytes + i put: byte].\\n\\t\\t\\t\\t\\trowBytes _ rowBytes + count]].\\n\\t\\tarray\\n\\t\\t\\treplaceFrom: position\\n\\t\\t\\tto: position + width - 1\\n\\t\\t\\twith: scanLine\\n\\t\\t\\tstartingAt: 1.\\n\\t\\tposition _ position + width + pad].\\n\\t^ array\\n! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'md 11/14/2003 16:51'!\\nreadHeader\\n\\n\\t| xMin xMax yMin yMax |\\n\\tself next.\\t\\\"skip over manufacturer field\\\"\\n\\tversion _ self next.\\n\\tencoding _ self next.\\n\\tbitsPerPixel _ self next.\\n\\txMin _ self nextWord.\\n\\tyMin _ self nextWord.\\n\\txMax _ self nextWord.\\n\\tyMax _ self nextWord.\\n\\twidth _ xMax - xMin + 1.\\n\\theight _ yMax - yMin + 1.\\n\\tself next: 4. \\\"skip over device resolution\\\"\\n\\tself next: 49. \\\"skip over EGA color palette\\\"\\n\\tcolorPlanes _ self next.\\n\\trowByteSize _ self nextWord.\\n\\tisGrayScale _ (self next: 2) = 2.\\n\\tself next: 58. \\\"skip over filler\\\"\\n\\n\\n\\n! !\\n\\n!PCXReadWriter methodsFor: 'private-decoding' stamp: 'tao 10/6/97 08:29'!\\nreadPalette\\n\\n\\t| r g b array |\\n\\tself next = 12 ifFalse: [self error: 'no Color Palette!!'].\\n\\tarray _ Array new: (1 bitShift: bitsPerPixel).\\n\\t1 to: array size do:\\n\\t\\t[:i |\\n\\t\\tr _ self next. g _ self next. b _ self next.\\n\\t\\tarray at: i put: (Color r: r g: g b: b range: 255)].\\n\\t^ array.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPCXReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PCXReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:57'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('pcx')! !\\nObject subclass: #PHOReader\\n\\tinstanceVariableNames: 'stream phonemes events pitches time'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-Support'!\\n!PHOReader commentStamp: '<historical>' prior: 0!\\nMy instances read PHO files with lines of the form 'phoneme duration time0 pitch0 time1 pitch1 ...'. Time is in milliseconds, and pitch is in hertz. Files on this format are used as inputs for the MBROLA synthesizer, and there are lots of them available on the web. Here's an example:\\n\\n_ 120 0 105\\nm 60 33 105\\nE 70 42 102\\nr 50 20 108\\nI 50 20 125 100 142\\nk 100\\nr 50 80 137\\nI 50 80 121\\ns 70\\nm 50\\n@ 90 33 111 88 108\\ns 90\\n!\\n\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\naddPitches\\n\\t| offset |\\n\\toffset := 0.0.\\n\\tevents do: [ :each |\\n\\t\\teach pitchPoints: (self pitchesBetween: offset and: offset + each duration).\\n\\t\\toffset := offset + each duration].! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 8/29/1999 02:16'!\\nevents\\n\\t^ CompositeEvent new addAll: events; yourself! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nnextEvent\\n\\t| line phonemeName phoneme duration answer ptime pitch |\\n\\tline := ReadStream on: stream nextLine.\\n\\tphonemeName := line upTo: Character space.\\n\\tphoneme := phonemes at: phonemeName.\\n\\t[line peek isSeparator] whileTrue: [line next].\\n\\tduration := (line upTo: Character space) asNumber / 1000.0.\\n\\tanswer := PhoneticEvent new phoneme: phoneme; duration: duration; loudness: 1.0.\\n\\t[line atEnd]\\n\\t\\twhileFalse: [ptime := (line upTo: Character space) asNumber * duration / 100.0.\\n\\t\\t\\t\\t\\tpitch := (line upTo: Character space) asNumber asFloat.\\n\\t\\t\\t\\t\\tpitches add: time + ptime @ pitch].\\n\\ttime := time + duration.\\n\\t^ answer! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\npitchAt: t\\n\\t\\\"Answer the pitch of the receiver at a given time. (Do linear interpolation.)\\\"\\n\\t| xVal count x1 x2 y1 y2 |\\n\\txVal := pitches first x.\\n\\tcount := 1.\\n\\t[xVal < t]\\n\\t\\twhileTrue: [count := count + 1.\\n\\t\\t\\t\\t\\tcount > pitches size ifTrue: [^ pitches last y].\\n\\t\\t\\t\\t\\txVal := (pitches at: count) x].\\n\\txVal = t ifTrue: [^ (pitches at: count) y].\\n\\tcount = 1 ifTrue: [^ pitches first y].\\n\\tx1 := (pitches at: count - 1) x.\\n\\tx2 := (pitches at: count) x.\\n\\ty1 := (pitches at: count - 1) y.\\n\\ty2 := (pitches at: count) y.\\n\\t^ (t - x1) / (x2 - x1) * (y2 - y1) + y1! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\npitchesBetween: t1 and: t2\\n\\t| step |\\n\\tstep := (t2 - t1 / 0.035) asInteger + 1. \\\"step small enough\\\"\\n\\t^ (t1 to: t2 by: t2 - t1 / step) collect: [ :each | each - t1 @ (self pitchAt: each)]! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 6/17/1999 01:45'!\\nplotPitch\\n\\tUtilities plot: ((0 to: time by: 0.050) collect: [ :each | self pitchAt: each])! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'len 6/15/1999 00:40'!\\nread\\n\\tstream reset.\\n\\t[stream atEnd] whileFalse: [events add: self nextEvent].\\n\\tself addPitches! !\\n\\n!PHOReader methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:22'!\\nstream: aStream\\n\\tstream := aStream! !\\n\\n\\n!PHOReader methodsFor: 'initialization' stamp: 'stephaneducasse 2/3/2006 22:22'!\\ninitialize\\n\\tevents := OrderedCollection new.\\n\\tpitches := OrderedCollection new.\\n\\ttime := 0.0.\\n\\tphonemes := PhonemeSet sampaToArpabet! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPHOReader class\\n\\tinstanceVariableNames: ''!\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExample\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.63489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExampleFemale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 1.3].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceExampleMale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.63489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceShortExample\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceShortExampleString.\\n\\tevents do: [ :each | each pitchBy: 1.3].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naliceShortExampleMale\\n\\t| events |\\n\\tevents := self eventsFromString: self aliceShortExampleString.\\n\\tevents do: [ :each | each pitchBy: 0.4].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:47'!\\nmbrolaExample\\n\\t^ self eventsFromString:\\n'_ 50\\nE 40 0 102\\nm 50\\nb 50\\nr 30\\n@U 80 5 119 35 126 70 140\\nl 50\\n@ 50 50 173\\nw 100 75 133\\nV 30 85 114\\nz 60 75 101\\nd 60\\n@ 40\\nv 40 85 105\\nE 60 75 121\\nl 50 70 121\\n@ 60 60 150\\np 50\\nd 70\\nb 70 0 90\\nAI 130 85 101\\nT 70\\nj 50 0 180\\nE 120 0 185 95 131\\nr 40\\ni 90 85 135\\nd 80 60 134\\n@ 50 0 119 50 114\\nt 70\\nw 70 10 117 65 127 85 115\\nA 180 0 102 55 91 95 85\\n_ 100\\n_ 100\\nI 80 18 111\\nt 80\\ns 50\\n@ 30\\ns 70\\np 80\\ni 80 25 171 85 200\\ntS 110\\ns 70\\nI 30 35 112\\nn 40\\nT 80\\n@ 40 85 108\\ns 80\\nAI 130 80 115\\nz 70 90 125\\nr= 120 75 111\\nb 80\\nEI 80 95 133\\nz 70\\nd 50\\nA 40\\nn 30\\nD 60\\n@ 30 65 121\\nk 90\\nA 30\\nn 30 100 140\\nk 80\\n{ 70 5 170\\nt 70\\n@ 40 50 186\\nn 40 75 163\\nEI 100 90 173\\nS 130\\n@ 40\\nn 30 65 153\\nV 40\\nv 70 0 148\\nd 60\\nAI 130 5 112 80 109\\nf 110\\n@U 160 87 88\\nn 70\\nz 210 88 82\\n_ 80\\n_ 100\\nI 40 0 140\\nt 50\\nt 100\\nEI 60 50 221\\nk 70\\ns 80\\n@ 30 0 190\\nl 50\\nI 30 65 180\\ns 110\\nt 70\\nV 50 20 171\\nv 50\\nf 90\\n@U 140 25 157\\nn 30\\ni 60 66 160\\nm 50 60 130\\nz 80\\n@ 40 62 78\\nz 80\\nI 70 78 134\\nn 50 70 163\\np 120\\nU 90 15 119 75 98\\nt 90\\n_ 140\\n_ 100\\nt 60 0 111\\nu 50 80 119\\ng 70\\nE 50 90 145\\nD 50\\nr= 50 40 139 90 163\\nw 90\\nI 30 15 114\\nD 50\\n_ 40\\np 50\\nr 30 0 102\\n@ 30 65 110\\ns 120\\nA 50 90 148\\nd 80\\nI 50 50 178\\nk 80\\nI 50 66 167\\nn 60\\nf 50\\nr= 50 90 125\\nm 50\\nEI 140 95 96\\nS 140\\n@ 80 35 168\\nn 100 95 142\\n_ 190\\n{ 90 0 133\\nn 30\\nd 30\\np 80\\nr 40\\n@ 40 0 97 65 103\\nd 70\\nj 20\\nu 60 65 150\\ns 90\\nI 30 50 210\\nz 50\\ns 140\\np 70\\ni 130 0 138 95 98\\ntS 160\\n{ 70 0 127\\nt 50\\nD 50\\n@ 30 15 93\\ns 140\\n{ 30 35 127\\nm 50\\np 70\\nl 50\\nI 30 35 184\\nN 70\\nf 70\\nr 60\\ni 90 30 125\\nk 40\\nw 30\\n@ 30 15 185\\nn 30\\ns 100\\ni 50 20 148 70 142\\nV 30 5 148\\nv 40\\nD 80\\n@ 40 25 106\\nd 80\\nAI 150 95 115\\nf 90\\n@U 130 95 114\\nn 70\\nd 80\\nEI 80 80 137\\n4 50\\n@ 30\\nb 100\\nEI 120 95 78\\ns 210\\n_ 80'! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:48'!\\npushExample\\n\\t^ self eventsFromString:\\n'_ 60 0 137\\np 50 100 137\\nu 110 90 137\\nS 100 10 121\\nD 90\\n@ 70 57 114 100 102\\ns 70\\nt 50\\nA 100 57 121 64 121\\nr 40\\nt 50\\nb 110\\nV 140 21 117 57 100 92 100\\n_ 3\\nn 130 25 102 50 105\\nt 60\\nu 70 28 129 71 111\\nb 70\\ni 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93\\n_ 140 92 93 100 100'! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npushExampleFemale\\n\\t| events |\\n\\tevents := self pushExample.\\n\\tevents do: [ :each | each pitchBy: 1.93489].\\n\\t^ events! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npushShortExample\\n\\t^ self eventsFromString:\\n'i 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93'.\\n\\\"\\n':= 3\\nn 130 25 102 50 105\\nt 60\\nu 70 28 129 71 111\\nb 70\\ni 70 50 102\\ng 20 10 100 80 102\\ni 130 25 117 66 114\\nn 260 3 111 23 105 42 97 61 93 73 93\\n:= 140 92 93 100 100'\\\"! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'len 7/27/1999 01:48'!\\nxmasExample\\n\\t^ self eventsFromString:\\n'_ 120 0 105\\nm 60 33 105\\nE 70 42 102\\nr 50 20 108\\nI 50 20 125 100 142\\nk 100\\nr 50 80 137\\nI 50 80 121\\ns 70\\nm 50\\n@ 90 33 111 88 108\\ns 90\\n{ 70\\nn 100 50 105 100 97\\nd 50 80 93\\nh 50 20 93\\n{ 50 20 102 60 114\\np 50\\ni 50 100 125\\nn 60 83 121\\nu 100\\nj 130 7 121 23 121 100 108\\nr= 250 41 102 83 97\\n_ 210 95 86 100 100'\\n! !\\n\\n!PHOReader class methodsFor: 'examples' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nxmasKidExample\\n\\t| events |\\n\\tevents := self xmasExample.\\n\\tevents do: [ :each | each pitchBy: 1.6].\\n\\t^ events! !\\n\\n\\n!PHOReader class methodsFor: 'examples-private' stamp: 'len 7/27/1999 01:45'!\\naliceExampleString\\n\\t^ '_ 48 0 222\\n{ 80 40 222 90 235\\nl 72 44 250 66 250\\nI 80\\ns 88\\nw 40 80 235\\n@ 40 80 210\\nz 64 12 210 50 181 75 181\\nb 72 33 173 88 181\\nI 56 71 181\\ng 56 28 153 100 166\\nI 64 62 160\\nn 40 60 160\\nI 88 27 166\\nN 40 100 166\\nt 80 20 160\\nU 40 40 181 80 166\\ng 48 100 166\\nE 104 38 153 76 137\\nt 56\\nv 48\\nE 72 11 166 66 153\\nr 88 18 160 63 166\\ni 112.8 14 166 49 173 77 173\\nt 104.8 98 137\\nAI 178.4 21 148 70 148 92 137\\nr= 108 25 137 62 133 98 129\\nd 49\\n@ 59.2 6 137 73 133\\nv 46\\ns 89\\nI 40 40 173\\nt 40 40 166\\nI 64 62 166\\nN 72 22 160 77 153\\nb 40 40 142 100 153\\nAI 136 29 142\\nh 80 30 142 100 148\\nr= 64 62 153 100 153\\ns 125\\nI 64 37 210 100 190\\ns 72 11 190\\nt 72\\nr= 104 30 160 69 142\\nO 72\\nn 40 40 142\\nD 40 40 153\\n@ 40 40 160\\nb 40 40 153 100 160\\n{ 216 18 166 51 166 70 153 88 137 100 133\\nn 40\\nk 56\\n_ 144 94 129 100 100\\n_ 100 0 137\\n{ 40\\nn 88 9 137 36 137 72 142\\nt 40 40 137 60 133\\n@ 48 16 148 100 148\\nh 40 100 142\\n{ 48 83 148\\nv 48 16 142\\nI 56 14 148 85 137\\nN 56 71 137\\nn 64 37 137 100 142\\nO 96 41 137 83 153 100 153\\nT 64\\nI 56 42 166\\nN 64 12 160 75 153\\nt 80 30 142\\n@ 56 28 166 100 148\\nd 56 71 137\\nu 160 15 160 45 160 70 153 95 142\\nw 136 23 137 58 137 88 148\\nA 112 21 153 57 160 92 173\\nn 64 50 166 62 153\\ns 56\\nO 48 50 153\\nr 40 40 142 100 133\\nt 130\\nw 56 57 166\\nAI 168 9 173 33 166 57 153 80 148 100 148\\ns 88\\n_ 300\\nS 92\\ni 48 50 235\\nh 40 40 235 100 250\\n@ 40 60 210 100 210\\nd 40\\np 40\\ni 150\\nk 56\\nd 56\\nI 72 44 222 100 210\\nn 40 80 210\\nt 56\\n@ 48 83 181\\nD 40 39 173 99 173\\n@ 39.2 100 160\\nb 104 30 153 100 153\\nU 112 35 153 85 153 100 153\\nk 72\\nh 56\\nr= 48 50 200\\ns 136 5 181\\nI 64 25 166 87 142\\ns 56 14 137\\nt 56\\nr= 56 28 173 100 173\\nw 56 71 166\\n@ 56 42 181\\nz 48 16 181 50 173\\nr 120 73 181\\ni 104 7 190 69 190 100 181\\nd 40\\nI 112 7 166 50 137 85 129\\nN 80 30 114 50 111\\n_ 56 83 111 100 100\\n_ 140 0 153\\nb 40 60 153 100 153\\nU 64 75 148\\n4 40 80 148 100 142\\nI 40\\nt 40 40 148\\nh 40 40 142\\n{ 48 33 137\\nd 136 5 133 11 129 88 148\\nn 48 66 148\\n@U 144 16 160 44 173 72 190 100 210\\np 80\\nI 96 75 190 100 181\\nk 56\\ntS 96\\nr= 104 30 190 69 181\\nz 72 11 181 33 173\\nO 40 60 173\\nr 64 37 160 100 153\\nk 72 11 153\\nO 152 63 190 89 200\\nn 40 60 181\\nv 40 60 166\\nr= 40 60 160\\ns 104 15 142\\nEI 120 20 190 53 190 86 210\\nS 104 7 210\\n@ 56 28 181 100 160\\nn 64 62 153 100 137\\nz 40\\nI 56 14 148 85 133\\nn 40 100 133\\nI 96 41 129 83 125\\nt 80\\n_ 64 85 125 100 100\\n_ 140 0 222\\n{ 56 14 222 28 220 42 235 85 235 100 220\\nn 96 33 222 75 235 100 235\\nw 48 33 222 66 250\\nO 90\\n4 48 50 222 66 252\\nI 48 33 250\\nz 64 12 235 62 210\\nD 56\\n@ 56 71 190\\nj 104 23 166 61 166 100 181\\nu 112 35 190 42 210 71 210 100 210\\ns 150\\n@ 56 42 200\\nv 40 20 160 60 148\\n@ 64 25 153 87 142\\nb 136 23 133 47 137\\nU 96 8 160 50 173 91 181 100 181\\nk 56\\n_ 56\\nT 56\\nO 119.2 20 166 53 142 80 137\\n4 40 20 133\\n{ 136 5 137 35 129 64 125\\nl 48 16 125 100 133\\nI 80 50 153 100 181\\ns 120\\n_ 40\\n_ 40\\nw 88 9 166 54 142\\nI 40 40 142\\nD 40 40 137\\naU 62.4 38 137 63 133\\nt 80\\np 55\\nI 72 16 210 38 210\\nk 40\\ntS 75.2 99 173\\nr= 136 29 160 64 160 76 166\\nz 48\\nO 44 90 185\\nr 60 6 198 46 200 72 190\\nk 40\\nO 81.6 12 148 61 133\\nn 40 20 133\\nv 48 33 133\\nr= 56 28 181 100 181\\ns 120 6 173\\nEI 136 11 222 41 210 94 210\\nS 120\\n@ 128 12 190 43 148 75 137\\nn 64 12 129 50 125\\n_ 80 88 125 100 100'! !\\n\\n!PHOReader class methodsFor: 'examples-private' stamp: 'len 7/27/1999 01:46'!\\naliceShortExampleString\\n\\t^ '_ 48 0 222\\n{ 80 40 222 90 235\\nl 72 44 250 66 250\\nI 80\\ns 88\\nw 40 80 235\\n@ 40 80 210\\nz 64 12 210 50 181 75 181\\nb 72 33 173 88 181\\nI 56 71 181\\ng 56 28 153 100 166\\nI 64 62 160\\nn 40 60 160\\nI 88 27 166\\nN 40 100 166\\nt 80 20 160\\nU 40 40 181 80 166\\ng 48 100 166\\nE 104 38 153 76 137\\nt 56\\nv 48\\nE 72 11 166 66 153\\nr 88 18 160 63 166\\ni 112.8 14 166 49 173 77 173\\nt 104.8 98 137\\nAI 178.4 21 148 70 148 92 137\\nr= 108 25 137 62 133 98 129\\nd 49\\n@ 59.2 6 137 73 133\\nv 46\\ns 89\\nI 40 40 173\\nt 40 40 166\\nI 64 62 166\\nN 72 22 160 77 153\\nb 40 40 142 100 153\\nAI 136 29 142\\nh 80 30 142 100 148\\n@ 60 50 150\\nr= 64 62 153 100 153\\ns 125\\nI 64 37 210 100 190\\ns 72 11 190\\nt 72\\nr= 104 30 160 69 142\\nO 72\\nn 40 40 142\\nD 40 40 153\\n@ 40 40 160\\nb 40 40 153 100 160\\n{ 216 18 166 51 166 70 153 88 137 100 133\\nn 40\\nk 56\\n_ 144 94 129 100 100'! !\\n\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/15/1999 00:48'!\\neventsFromStream: aStream\\n\\t^ self new stream: aStream; read; events! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/15/1999 00:49'!\\neventsFromString: aString\\n\\t^ self eventsFromStream: (ReadStream on: aString)! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/17/1999 01:47'!\\nplotPitchFromStream: aStream\\n\\t^ self new stream: aStream; read; plotPitch! !\\n\\n!PHOReader class methodsFor: 'instance creation' stamp: 'len 6/17/1999 01:47'!\\nplotPitchFromString: aString\\n\\t^ self plotPitchFromStream: (ReadStream on: aString)! !\\nImageReadWriter subclass: #PNGReadWriter\\n\\tinstanceVariableNames: 'chunk form width height depth backColor bitsPerChannel colorType interlaceMethod bitsPerPixel bytesPerScanline thisScanline prevScanline rowSize globalDataChunk unknownChunks palette transparentPixelValue filtersSeen swizzleMap cachedDecoderMap bigEndian'\\n\\tclassVariableNames: 'BPP BlockHeight BlockWidth Debugging StandardColors StandardSwizzleMaps'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n!PNGReadWriter commentStamp: '<historical>' prior: 0!\\nI am a subclass of ImageReadWriter that decodes Portable Network Graphics\\n(PNG) images.\\n\\nSubmitted by Duane Maxwell!\\n\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'RAA 11/7/2000 09:20'!\\ndebugging\\n\\n\\t^Debugging == true! !\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'nk 7/30/2004 17:51'!\\nnextImage\\n\\tbigEndian := SmalltalkImage current isBigEndian.\\n\\tfiltersSeen := Bag new.\\n\\tglobalDataChunk := nil.\\n\\ttransparentPixelValue := nil.\\n\\tunknownChunks := Set new.\\n\\tstream reset.\\n\\tstream binary.\\n\\tstream skip: 8.\\n\\t[stream atEnd] whileFalse: [self processNextChunk].\\n\\t\\\"Set up our form\\\"\\n\\tpalette ifNotNil: \\n\\t\\t\\t[\\\"Dump the palette if it's the same as our standard palette\\\"\\n\\n\\t\\t\\tpalette = (StandardColors copyFrom: 1 to: palette size) \\n\\t\\t\\t\\tifTrue: [palette := nil]].\\n\\t(depth <= 8 and: [palette notNil]) \\n\\t\\tifTrue: \\n\\t\\t\\t[form := ColorForm extent: width @ height depth: depth.\\n\\t\\t\\tform colors: palette]\\n\\t\\tifFalse: [form := Form extent: width @ height depth: depth].\\n\\tbackColor ifNotNil: [form fillColor: backColor].\\n\\tchunk := globalDataChunk ifNil: [self error: 'image data is missing'].\\n\\tchunk ifNotNil: [self processIDATChunk].\\n\\tunknownChunks isEmpty \\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Transcript show: ' ',unknownChunks asSortedCollection asArray printString.\\\"\\n\\n\\t\\t\\t].\\n\\tself debugging \\n\\t\\tifTrue: \\n\\t\\t\\t[Transcript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'form = ' , form printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'colorType = ' , colorType printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'interlaceMethod = ' , interlaceMethod printString.\\n\\t\\t\\tTranscript\\n\\t\\t\\t\\tcr;\\n\\t\\t\\t\\tshow: 'filters = ' , filtersSeen sortedCounts asArray printString].\\n\\t^form! !\\n\\n!PNGReadWriter methodsFor: 'accessing' stamp: 'DSM 3/24/2000 01:12'!\\nunderstandsImageFormat\\n\\t#(137 80 78 71 13 10 26 10) do: [ :byte |\\n\\t\\tstream next = byte ifFalse: [^ false]].\\n\\t^ true\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/10/2004 23:55'!\\nprocessBackgroundChunk\\n\\n\\t| val red green blue max |\\n\\n\\t\\\"Transcript show: ' BACKGROUND: ',chunk printString.\\\"\\n\\tcolorType = 3 ifTrue: [\\n\\t\\tbackColor := palette at: chunk first + 1.\\n\\t\\t^self\\n\\t].\\n\\tmax _ (2 raisedTo: bitsPerChannel) - 1.\\n\\t(colorType = 0 or: [colorType = 4]) ifTrue: [\\n\\t\\tval _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\tbackColor := Color gray: val / max.\\n\\t\\t^self\\n\\t].\\n\\t(colorType = 2 or: [colorType = 6]) ifTrue: [\\n\\t\\tred _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\tgreen _ chunk unsignedShortAt: 3 bigEndian: true.\\n\\t\\tblue _ chunk unsignedShortAt: 5 bigEndian: true.\\n\\t\\tbackColor := Color r: red/max g: green/max b: blue/max.\\n\\t\\t^self\\n\\t].\\n\\\"self halt.\\\"\\n\\n\\\"====\\nThe bKGD chunk specifies a default background color to present the image against. Note that viewers are not bound to honor this chunk; a viewer can choose to use a different background. \\n\\nFor color type 3 (indexed color), the bKGD chunk contains: \\n\\n\\n Palette index: 1 byte\\n\\nThe value is the palette index of the color to be used as background. \\n\\nFor color types 0 and 4 (grayscale, with or without alpha), bKGD contains: \\n\\n\\n Gray: 2 bytes, range 0 .. (2^bitdepth)-1\\n\\n(For consistency, 2 bytes are used regardless of the image bit depth.) The value is the gray level to be used as background. \\n\\nFor color types 2 and 6 (truecolor, with or without alpha), bKGD contains: \\n\\n\\n Red: 2 bytes, range 0 .. (2^bitdepth)-1\\n Green: 2 bytes, range 0 .. (2^bitdepth)-1\\n Blue: 2 bytes, range 0 .. (2^bitdepth)-1\\n\\n(For consistency, 2 bytes per sample are used regardless of the image bit depth.) This is the RGB color to be used as background. \\n\\nWhen present, the bKGD chunk must precede the first IDAT chunk, and must follow the PLTE chunk, if any. \\n===\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/4/2000 17:00'!\\nprocessIDATChunk\\n\\n\\tinterlaceMethod = 0\\n\\t\\tifTrue: [ self processNonInterlaced ]\\n\\t\\tifFalse: [ self processInterlaced ]\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/10/2004 23:55'!\\nprocessIHDRChunk\\n\\twidth _ chunk longAt: 1 bigEndian: true.\\n\\theight _ chunk longAt: 5 bigEndian: true.\\n\\tbitsPerChannel _ chunk at: 9.\\n\\tcolorType _ chunk at: 10.\\n\\t\\\"compression _ chunk at: 11.\\\" \\\"TODO - validate compression\\\"\\n\\t\\\"filterMethod _ chunk at: 12.\\\" \\\"TODO - validate filterMethod\\\"\\n\\tinterlaceMethod _ chunk at: 13. \\\"TODO - validate interlace method\\\"\\n\\t(#(2 4 6) includes: colorType)\\n\\t\\tifTrue: [depth _ 32].\\n\\t(#(0 3) includes: colorType) ifTrue: [\\n\\t\\tdepth _ bitsPerChannel min: 8.\\n\\t\\tcolorType = 0 ifTrue: [ \\\"grayscale\\\"\\n\\t\\t\\tpalette := self grayColorsFor: depth.\\n\\t\\t].\\n\\t].\\n\\tbitsPerPixel _ (BPP at: colorType+1) at: bitsPerChannel highBit.\\n\\tbytesPerScanline _ width * bitsPerPixel + 7 // 8.\\n\\trowSize _ width * depth + 31 >> 5.\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/29/2004 04:19'!\\nprocessInterlaced\\n\\t| z filter bytesPerPass startingCol colIncrement rowIncrement startingRow cx sc temp |\\n\\tstartingCol _ #(0 4 0 2 0 1 0 ).\\n\\tcolIncrement _ #(8 8 4 4 2 2 1 ).\\n\\trowIncrement _ #(8 8 8 4 4 2 2 ).\\n\\tstartingRow _ #(0 0 4 0 2 0 1 ).\\n\\tz _ ZLibReadStream on: chunk from: 1 to: chunk size.\\n\\t1 to: 7 do: [:pass |\\n\\t\\t(self doPass: pass)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[cx _ colIncrement at: pass.\\n\\t\\t\\t\\tsc _ startingCol at: pass.\\n\\t\\t\\t\\tbytesPerPass _ width - sc + cx - 1 // cx * bitsPerPixel + 7 // 8.\\n\\t\\t\\t\\tprevScanline _ ByteArray new: bytesPerPass.\\n\\t\\t\\t\\tthisScanline _ ByteArray new: bytesPerScanline.\\n\\t\\t\\t\\t(startingRow at: pass)\\n\\t\\t\\t\\t\\tto: height - 1\\n\\t\\t\\t\\t\\tby: (rowIncrement at: pass)\\n\\t\\t\\t\\t\\tdo: [:y |\\n\\t\\t\\t\\t\\t\\tfilter _ z next.\\n\\t\\t\\t\\t\\t\\tfiltersSeen add: filter.\\n\\t\\t\\t\\t\\t\\t(filter isNil or: [(filter between: 0 and: 4) not])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\t\\tthisScanline _ z next: bytesPerPass into: thisScanline startingAt: 1.\\n\\t\\t\\t\\t\\t\\tself filterScanline: filter count: bytesPerPass.\\n\\t\\t\\t\\t\\t\\tself copyPixels: y at: sc by: cx.\\n\\t\\t\\t\\t\\t\\ttemp := prevScanline.\\n\\t\\t\\t\\t\\t\\tprevScanline := thisScanline.\\n\\t\\t\\t\\t\\t\\tthisScanline := temp.\\n\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t]\\n\\t].\\n\\tz atEnd ifFalse:[self error:'Unexpected data'].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/11/2004 12:14'!\\nprocessNextChunk\\n\\n\\t| length chunkType crc chunkCrc |\\n\\n\\tlength _ self nextLong.\\n\\n\\tchunkType _ (self next: 4) asString.\\n\\tchunk _ self next: length.\\n\\tchunkCrc := self nextLong bitXor: 16rFFFFFFFF.\\n\\tcrc := self updateCrc: 16rFFFFFFFF from: 1 to: 4 in: chunkType.\\n\\tcrc := self updateCrc: crc from: 1 to: length in: chunk.\\n\\tcrc = chunkCrc ifFalse:[\\n\\t\\tself error: 'PNGReadWriter crc error in chunk ', chunkType.\\n\\t].\\n\\n\\tchunkType = 'IEND' ifTrue: [^self\\t\\\"*should* be the last chunk\\\"].\\n\\tchunkType = 'sBIT' ifTrue: [^self processSBITChunk \\\"could indicate unusual sample depth in original\\\"].\\n\\tchunkType = 'gAMA' ifTrue: [^self \\t\\\"indicates gamma correction value\\\"].\\n\\tchunkType = 'bKGD' ifTrue: [^self processBackgroundChunk].\\n\\tchunkType = 'pHYs' ifTrue: [^self processPhysicalPixelChunk].\\n\\tchunkType = 'tRNS' ifTrue: [^self processTransparencyChunk].\\n\\n\\tchunkType = 'IHDR' ifTrue: [^self processIHDRChunk].\\n\\tchunkType = 'PLTE' ifTrue: [^self processPLTEChunk].\\n\\tchunkType = 'IDAT' ifTrue: [\\n\\t\\t\\\"---since the compressed data can span multiple\\n\\t\\tchunks, stitch them all together first. later,\\n\\t\\tif memory is an issue, we need to figure out how\\n\\t\\tto do this on the fly---\\\"\\n\\t\\tglobalDataChunk _ globalDataChunk ifNil: [chunk] ifNotNil:\\n\\t\\t\\t[globalDataChunk,chunk].\\n\\t\\t^self\\n\\t].\\n\\tunknownChunks add: chunkType.\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/29/2004 04:19'!\\nprocessNonInterlaced\\n\\t| z filter temp copyMethod debug |\\n\\tdebug := self debugging.\\n\\tcopyMethod _ #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:\\n\\t\\t copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.\\n\\tdebug ifTrue: [ Transcript cr; nextPutAll: 'NI chunk size='; print: chunk size ].\\n\\tz _ ZLibReadStream on: chunk from: 1 to: chunk size.\\n\\tprevScanline _ ByteArray new: bytesPerScanline.\\n\\tthisScanline := ByteArray new: bytesPerScanline.\\n\\t0 to: height-1 do: [ :y |\\n\\t\\tfilter _ (z next: 1) first.\\n\\t\\tdebug ifTrue:[filtersSeen add: filter].\\n\\t\\tthisScanline _ z next: bytesPerScanline into: thisScanline startingAt: 1.\\n\\t\\t(debug and: [ thisScanline size < bytesPerScanline ]) ifTrue: [ Transcript nextPutAll: ('wanted {1} but only got {2}' format: { bytesPerScanline. thisScanline size }); cr ].\\n\\t\\tfilter = 0 ifFalse:[self filterScanline: filter count: bytesPerScanline].\\n\\t\\tself perform: copyMethod with: y.\\n\\t\\ttemp := prevScanline.\\n\\t\\tprevScanline := thisScanline.\\n\\t\\tthisScanline := temp.\\n\\t\\t].\\n\\tz atEnd ifFalse:[self error:'Unexpected data'].\\n\\tdebug ifTrue: [Transcript nextPutAll: ' compressed size='; print: z position ].\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 2/11/2004 01:02'!\\nprocessPLTEChunk\\n\\n\\t| colorCount i |\\n\\n\\tcolorCount _ chunk size // 3. \\\"TODO - validate colorCount against depth\\\"\\n\\tpalette _ Array new: colorCount.\\n\\t0 to: colorCount-1 do: [ :index |\\n\\t\\ti _ index * 3 + 1.\\n\\t\\tpalette at: index+1 put:\\n\\t\\t\\t(Color r: (chunk at: i)/255.0 g: (chunk at: i+1)/255.0 b: (chunk at: i+2)/255.0)\\n\\t\\t].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/5/2000 11:24'!\\nprocessPhysicalPixelChunk\\n\\n\\t\\\"Transcript show: ' PHYSICAL: ',chunk printString.\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'ar 12/12/2003 18:33'!\\nprocessSBITChunk\\n\\t| rBits gBits bBits aBits |\\n\\tcolorType = 6 ifFalse:[^self].\\n\\trBits := chunk at: 1.\\n\\tgBits := chunk at: 2.\\n\\tbBits := chunk at: 3.\\n\\taBits := chunk at: 4.\\n\\t(rBits = 5 and:[gBits = 5 and:[bBits = 5 and:[aBits = 1]]]) ifTrue:[\\n\\t\\tdepth := 16.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'chunks' stamp: 'RAA 11/4/2000 16:22'!\\nprocessTransparencyChunk\\n\\n\\t| red green blue |\\n\\n\\t\\\"Transcript show: ' TRANSPARENCY ',chunk printString.\\\"\\n\\tcolorType = 0 ifTrue: [\\n\\t\\ttransparentPixelValue _ chunk unsignedShortAt: 1 bigEndian: true.\\n\\t\\t^self\\n\\t].\\n\\tcolorType = 2 ifTrue: [\\n\\t\\tred _ chunk at: 2.\\n\\t\\tgreen _ chunk at: 2.\\n\\t\\tblue _ chunk at: 2.\\n\\t\\ttransparentPixelValue _ 16rFF00 + red << 8 + green << 8 + blue.\\n\\t\\t^self\\n\\t].\\n\\tcolorType = 3 ifTrue: [\\n\\t\\tchunk withIndexDo: [ :alpha :index |\\n\\t\\t\\tpalette at: index put: ((palette at: index) alpha: alpha/255)\\n\\t\\t].\\n\\t\\t^self\\n\\t].\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'RAA 11/7/2000 09:43'!\\nfilterAverage: count\\n\\t\\\"Use the average of the pixel to the left and the pixel above as a predictor\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\t1 to: delta do: [:i |\\n\\t\\tthisScanline at: i put: ((thisScanline at: i) + ((prevScanline at: i) // 2) bitAnd: 255)].\\n\\tdelta + 1 to: count do: [:i |\\n\\t\\tthisScanline at: i put:\\n\\t\\t\\t((thisScanline at: i)\\n\\t\\t\\t+ ((prevScanline at: i)\\n\\t\\t\\t+ (thisScanline at: i - delta) // 2) bitAnd: 255)]! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:54'!\\nfilterHorizontal: count\\n\\t\\\"Use the pixel to the left as a predictor\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\tdelta+1 to: count do: [ :i |\\n\\t\\tthisScanline at: i put: (((thisScanline at: i) +\\n(thisScanline at: i-delta)) bitAnd: 255) ]\\n\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:55'!\\nfilterNone: count\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'RAA 11/7/2000 09:45'!\\nfilterPaeth: count\\n\\t\\\"Select one of (the pixel to the left, the pixel above and the pixel to above left) to\\n\\tpredict the value of this pixel\\\"\\n\\n\\t| delta |\\n\\tdelta _ bitsPerPixel // 8 max: 1.\\n\\t1 to: delta do: [ :i |\\n\\t\\tthisScanline at: i put:\\n\\t\\t\\t(((thisScanline at: i) + (prevScanline at: i)) bitAnd: 255)].\\n\\tdelta+1 to: count do: [ :i |\\n\\t\\tthisScanline\\n\\t\\t\\tat: i\\n\\t\\t\\tput: (((thisScanline at: i) + (self\\n\\t\\t\\t\\tpaethPredictLeft: (thisScanline at: i-delta)\\n\\t\\t\\t\\tabove: (prevScanline at: i)\\n\\t\\t\\t\\taboveLeft: (prevScanline at: i-delta)))\\n\\t\\t\\t\\t\\tbitAnd: 255)]\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'eat 9/11/2000 20:08'!\\nfilterScanline: filterType count: count\\n\\n\\tself\\n\\t\\tperform: (\\n\\t\\t\\t#(filterNone: filterHorizontal: filterVertical: filterAverage: filterPaeth:)\\n\\t\\t\\t\\tat: filterType+1)\\n\\t\\twith: count.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'DSM 3/25/2000 17:54'!\\nfilterVertical: count\\n\\t\\\"Use the pixel above as a predictor\\\"\\n\\n\\t1 to: count do: [ :i |\\n\\t\\tthisScanline at: i put: (((thisScanline at: i) +\\n(prevScanline at: i)) bitAnd: 255) ]\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'filtering' stamp: 'eat 9/11/2000 20:05'!\\npaethPredictLeft: a above: b aboveLeft: c\\n\\t\\\"Predicts the value of a pixel based on nearby pixels, based on\\nPaeth (GG II, 1991)\\\"\\n\\n\\t| pa pb pc |\\n\\tpa _ b > c ifTrue: [b - c] ifFalse: [c - b].\\n\\tpb _ a > c ifTrue: [a - c] ifFalse: [c - a].\\n\\tpc _ a + b - c - c.\\n\\tpc < 0 ifTrue: [\\n\\t\\tpc := pc * -1].\\n\\t((pa <= pb) and: [pa <= pc]) ifTrue: [^ a].\\n\\t(pb <= pc) ifTrue: [^ b].\\n\\t^ c\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'miscellaneous' stamp: 'DSM 4/27/2000 13:09'!\\ndoPass: pass\\n\\t\\\"Certain interlace passes are skipped with certain small image\\ndimensions\\\"\\n\\n\\tpass = 1 ifTrue: [ ^ true ].\\n\\t((width = 1) and: [height = 1]) ifTrue: [ ^ false ].\\n\\tpass = 2 ifTrue: [ ^ width >= 5 ].\\n\\tpass = 3 ifTrue: [ ^ height >= 5 ].\\n\\tpass = 4 ifTrue: [ ^ (width >=3 ) or: [height >= 5] ].\\n\\tpass = 5 ifTrue: [ ^ height >=3 ].\\n\\tpass = 6 ifTrue: [ ^ width >=2 ].\\n\\tpass = 7 ifTrue: [ ^ height >=2 ].\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'miscellaneous' stamp: 'ar 2/11/2004 01:27'!\\ngrayColorsFor: d\\n\\t\\\"return a color table for a gray image\\\"\\n\\n\\tpalette _ Array new: 1<<d.\\n\\td = 1 ifTrue: [\\n\\t\\tpalette at: 1 put: Color black.\\n\\t\\tpalette at: 2 put: Color white.\\n\\t\\t^ palette,{Color transparent}\\n\\t\\t].\\n\\td = 2 ifTrue: [\\n\\t\\tpalette at: 1 put: Color black.\\n\\t\\tpalette at: 2 put: (Color gray: 85.0 / 255.0).\\n\\t\\tpalette at: 3 put: (Color gray: 170.0 / 255.0).\\n\\t\\tpalette at: 4 put: Color white.\\n\\t\\t^ palette,{Color transparent}.\\n\\t\\t].\\n\\td = 4 ifTrue: [\\n\\t\\t0 to: 15 do: [ :g |\\n\\t\\t\\tpalette at: g+1 put: (Color gray: (g/15) asFloat) ].\\n\\t\\t^ palette,{Color transparent}\\n\\t\\t].\\n\\td = 8 ifTrue: [\\n\\t\\t0 to: 255 do: [ :g |\\n\\t\\t\\tpalette at: g+1 put: (Color gray: (g/255) asFloat) ].\\n\\t\\t^ palette\\t\\t\\\"??transparent??\\\"\\n\\t\\t].\\n! !\\n\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'DSM 3/26/2000 21:32'!\\ncopyPixels: y\\n\\t\\\"Handle non-interlaced pixels of supported colorTypes\\\"\\n\\n\\t| s |\\n\\ts _ #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:\\n\\t\\t copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.\\n\\tself perform: s asSymbol with: y\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:08'!\\ncopyPixels: y at: startX by: incX\\n\\t\\\"Handle interlaced pixels of supported colorTypes\\\"\\n\\n\\t| s |\\n\\ts _ #(copyPixelsGray:at:by: nil copyPixelsRGB:at:by: copyPixelsIndexed:at:by:\\n\\t\\t copyPixelsGrayAlpha:at:by: nil copyPixelsRGBA:at:by:) at: colorType+1.\\n\\tself perform: s asSymbol with: y with: startX with: incX\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:12'!\\ncopyPixelsGray: y \\n\\t\\\"Handle non-interlaced grayscale color mode (colorType = 0)\\\"\\n\\t| blitter pixPerByte mask shifts pixelNumber rawByte pixel transparentIndex |\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\ttransparentIndex _ form colors size.\\n\\tbitsPerChannel = 16\\n\\t\\tifTrue: [0\\n\\t\\t\\t\\tto: width - 1\\n\\t\\t\\t\\tdo: [:x | blitter pixelAt: x @ y put: 255\\n\\t\\t\\t\\t\\t\\t\\t- (thisScanline at: x << 1 + 1)].\\n\\t\\t\\t^ self]\\n\\t\\tifFalse: [bitsPerChannel = 8\\n\\t\\t\\t\\tifTrue: [1\\n\\t\\t\\t\\t\\t\\tto: width\\n\\t\\t\\t\\t\\t\\tdo: [:x | blitter\\n\\t\\t\\t\\t\\t\\t\\t\\tpixelAt: x - 1 @ y\\n\\t\\t\\t\\t\\t\\t\\t\\tput: (thisScanline at: x)].\\n\\t\\t\\t\\t\\t^ self].\\n\\t\\t\\tbitsPerChannel = 1\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 8.\\n\\t\\t\\t\\t\\tmask _ 1.\\n\\t\\t\\t\\t\\tshifts _ #(7 6 5 4 3 2 1 0 )].\\n\\t\\t\\tbitsPerChannel = 2\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 4.\\n\\t\\t\\t\\t\\tmask _ 3.\\n\\t\\t\\t\\t\\tshifts _ #(6 4 2 0 )].\\n\\t\\t\\tbitsPerChannel = 4\\n\\t\\t\\t\\tifTrue: [pixPerByte _ 2.\\n\\t\\t\\t\\t\\tmask _ 15.\\n\\t\\t\\t\\t\\tshifts _ #(4 0 )].\\n\\t\\t\\tpixelNumber _ 0.\\n\\t\\t\\t0 to: width - 1 do: [:x | \\n\\t\\t\\t\\trawByte _ thisScanline at: pixelNumber // pixPerByte + 1.\\n\\t\\t\\t\\tpixel _ rawByte\\n\\t\\t\\t\\t\\t\\t\\t>> (shifts at: pixelNumber \\\\\\\\ pixPerByte + 1) bitAnd: mask.\\n\\t\\t\\t\\tpixel = transparentPixelValue ifTrue: [pixel _ transparentIndex].\\n\\t\\t\\t\\tblitter pixelAt: x @ y put: pixel.\\n\\t\\t\\t\\tpixelNumber _ pixelNumber + 1\\n\\t\\t\\t]\\n\\t\\t]! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGray: y at: startX by: incX\\n\\t\\\"Handle interlaced grayscale color mode (colorType = 0)\\\"\\n\\n\\t| b offset bits w pixel mask blitter pixelNumber pixPerByte rawByte\\nshifts |\\n\\tbitsPerChannel = 16\\n\\t\\tifTrue: [\\n\\t\\t\\tb _ BitBlt current bitPokerToForm: form.\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\tb pixelAt: x@y put: 255 - (thisScanline at: (x//incX<<1)+1).\\n\\t\\t\\t\\t].\\n\\t\\t\\t^ self\\n\\t\\t\\t].\\n\\toffset _ y*rowSize+1.\\n\\tbits _ form bits.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tw _ offset + (x>>2).\\n\\t\\t\\tb _ 3- (x \\\\\\\\ 4) * 8.\\n\\t\\t\\tpixel _ (thisScanline at: x // incX + 1)<<b.\\n\\t\\t\\tmask _ (255<<b) bitInvert32.\\n\\t\\t\\tbits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)\\n\\t\\t].\\n\\t\\t^ self\\n\\t].\\n\\tbitsPerChannel = 1 ifTrue: [\\n\\t\\tpixPerByte _ 8.\\n\\t\\tmask _ 1.\\n\\t\\tshifts _ #(7 6 5 4 3 2 1 0).\\n\\t].\\n\\tbitsPerChannel = 2 ifTrue: [\\n\\t\\tpixPerByte _ 4.\\n\\t\\tmask _ 3.\\n\\t\\tshifts _ #(6 4 2 0).\\n\\t].\\n\\tbitsPerChannel = 4 ifTrue: [\\n\\t\\tpixPerByte _ 2.\\n\\t\\tmask _ 15.\\n\\t\\tshifts _ #(4 0).\\n\\t].\\n\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\tpixelNumber _ 0.\\n\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\trawByte _ thisScanline at: (pixelNumber // pixPerByte) + 1.\\n\\t\\tpixel _ (rawByte >> (shifts at: (pixelNumber \\\\\\\\ pixPerByte) + 1)) bitAnd: mask.\\n\\t\\tblitter pixelAt: (x@y) put: pixel.\\n\\t\\tpixelNumber _ pixelNumber + 1.\\n\\t].\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGrayAlpha: y\\n\\t\\\"Handle non-interlaced grayscale with alpha color mode (colorType = 4)\\\"\\n\\n\\t| i pixel gray b |\\n\\tb _ BitBlt current bitPokerToForm: form.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\t0 to: width-1 do: [ :x |\\n\\t\\t\\t\\ti _ (x << 1) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\t0 to: width-1 do: [ :x |\\n\\t\\t\\t\\ti _ (x << 2) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:09'!\\ncopyPixelsGrayAlpha: y at: startX by: incX\\n\\t\\\"Handle interlaced grayscale with alpha color mode (colorType = 4)\\\"\\n\\n\\t| i pixel gray b |\\n\\tb _ BitBlt current bitPokerToForm: form.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\ti _ (x // incX << 1) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\ti _ (x // incX << 2) + 1.\\n\\t\\t\\t\\tgray _ thisScanline at: i.\\n\\t\\t\\t\\tpixel _ ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.\\n\\t\\t\\t\\tb pixelAt: x@y put: pixel.\\n\\t\\t\\t\\t]\\n\\t\\t\\t]\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 1/1/1970 21:00'!\\ncopyPixelsIndexed: y\\n\\t\\\"Handle non-interlaced indexed color mode (colorType = 3)\\\"\\n\\t| hack hackBlt swizzleHack swizzleBlt scanline hackDepth |\\n\\tscanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.\\n\\tscanline replaceFrom: 1 to: thisScanline size with: thisScanline startingAt: 1.\\n\\thackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].\\n\\thack := Form extent: width@1 depth: hackDepth bits: scanline.\\n\\thackBlt := BitBlt toForm: form.\\n\\thackBlt sourceForm: hack.\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@y.\\n\\thackBlt width: width; height: 1.\\n\\n\\t(form depth < 8 and:[bigEndian not]) ifTrue:[\\n\\t\\tswizzleHack := Form new hackBits: scanline.\\n\\t\\tswizzleBlt := BitBlt toForm: swizzleHack.\\n\\t\\tswizzleBlt sourceForm: swizzleHack.\\n\\t\\tswizzleBlt combinationRule: Form over.\\n\\t\\tswizzleBlt colorMap: (StandardSwizzleMaps at: form depth).\\n\\t\\tswizzleBlt copyBits.\\n\\t].\\n\\n\\thackBlt copyBits.! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/4/2000 16:23'!\\ncopyPixelsIndexed: y at: startX by: incX\\n\\t\\\"Handle interlaced indexed color mode (colorType = 3)\\\"\\n\\n\\t| offset b bits w pixel mask pixPerByte shifts blitter pixelNumber rawByte |\\n\\toffset _ y*rowSize+1.\\n\\tbits _ form bits.\\n\\tbitsPerChannel = 8\\n\\t\\tifTrue: [\\n\\t\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t\\tw _ offset + (x>>2).\\n\\t\\t\\t\\tb _ 3 - (x \\\\\\\\ 4) * 8.\\n\\t\\t\\t\\tpixel _ (thisScanline at: x // incX + 1)<<b.\\n\\t\\t\\t\\tmask _ (255<<b) bitInvert32.\\n\\t\\t\\t\\tbits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)].\\n\\t\\t\\t^ self ].\\n\\tbitsPerChannel = 1 ifTrue: [\\n\\t\\tpixPerByte _ 8.\\n\\t\\tmask _ 1.\\n\\t\\tshifts _ #(7 6 5 4 3 2 1 0).\\n\\t].\\n\\tbitsPerChannel = 2 ifTrue: [\\n\\t\\tpixPerByte _ 4.\\n\\t\\tmask _ 3.\\n\\t\\tshifts _ #(6 4 2 0).\\n\\t].\\n\\tbitsPerChannel = 4 ifTrue: [\\n\\t\\tpixPerByte _ 2.\\n\\t\\tmask _ 15.\\n\\t\\tshifts _ #(4 0).\\n\\t].\\n\\n\\tblitter _ BitBlt current bitPokerToForm: form.\\n\\tpixelNumber _ 0.\\n\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\trawByte _ thisScanline at: (pixelNumber // pixPerByte) + 1.\\n\\t\\tpixel _ (rawByte >> (shifts at: (pixelNumber \\\\\\\\ pixPerByte) + 1)) bitAnd: mask.\\n\\t\\tblitter pixelAt: (x@y) put: pixel.\\n\\t\\tpixelNumber _ pixelNumber + 1.\\n\\t].\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'RAA 11/7/2000 09:30'!\\ncopyPixelsRGB: y\\n\\t\\\"Handle non-interlaced RGB color mode (colorType = 2)\\\"\\n\\n\\t| i pixel tempForm tempBits |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tpixel at: 4 put: 16rFF.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti := 1.\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: x put: pixel.\\n\\t\\t\\ti _ i + 3.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti := 1.\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x put: pixel.\\n\\t\\t\\ti _ i + 6.\\n\\t\\t]\\n\\t].\\n\\ttransparentPixelValue ifNotNil: [\\n\\t\\t1 to: width do: [ :x |\\n\\t\\t\\t(tempBits at: x) = transparentPixelValue ifTrue: [\\n\\t\\t\\t\\ttempBits at: x put: 0.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paint.\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'nk 7/27/2004 17:18'!\\ncopyPixelsRGB: y at: startX by: incX\\n\\t\\\"Handle interlaced RGB color mode (colorType = 2)\\\"\\n\\n\\t| i pixel tempForm tempBits xx loopsToDo |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tpixel at: 4 put: 16rFF.\\n\\tloopsToDo _ width - startX + incX - 1 // incX.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti _ (startX // incX * 3) + 1.\\n\\t\\txx _ startX+1.\\n\\t\\t1 to: loopsToDo do: [ :j |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: xx put: pixel.\\n\\t\\t\\ti _ i + 3.\\n\\t\\t\\txx _ xx + incX.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti _ (startX // incX * 6) + 1.\\n\\t\\txx _ startX+1.\\n\\t\\t1 to: loopsToDo do: [ :j |\\n\\t\\t\\tpixel\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: xx put: pixel.\\n\\t\\t\\ti _ i + 6.\\n\\t\\t\\txx _ xx + incX.\\n\\t\\t].\\n\\t].\\n\\ttransparentPixelValue ifNotNil: [\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\t(tempBits at: x+1) = transparentPixelValue ifTrue: [\\n\\t\\t\\t\\ttempBits at: x+1 put: 0.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paint.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 2/18/2004 23:58'!\\ncopyPixelsRGBA: y\\n\\t\\\"Handle non-interlaced RGBA color modes (colorType = 6)\\\"\\n\\n\\t| i pixel tempForm tempBits ff |\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\tff := Form extent: width@1 depth: 32 bits: thisScanline.\\n\\t\\tcachedDecoderMap \\n\\t\\t\\tifNil:[cachedDecoderMap := self rgbaDecoderMapForDepth: depth].\\n\\t\\t(BitBlt toForm: form)\\n\\t\\t\\tsourceForm: ff;\\n\\t\\t\\tdestOrigin: 0@y;\\n\\t\\t\\tcombinationRule: Form over;\\n\\t\\t\\tcolorMap: cachedDecoderMap;\\n\\t\\t\\tcopyBits.\\n\\t\\t^self.\\n\\t].\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\ti := -7.\\n\\t0 to: width-1 do: [ :x |\\n\\t\\t\\ti := i + 8.\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+6);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form over.\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'nk 7/27/2004 17:57'!\\ncopyPixelsRGBA: y at: startX by: incX\\n\\t\\\"Handle interlaced RGBA color modes (colorType = 6)\\\"\\n\\n\\t| i pixel tempForm tempBits |\\n\\n\\ttempForm _ Form extent: width@1 depth: 32.\\n\\ttempBits _ tempForm bits.\\n\\tpixel := LargePositiveInteger new: 4.\\n\\tbitsPerChannel = 8 ifTrue: [\\n\\t\\ti _ (startX // incX << 2) + 1.\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+3);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+1);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+2).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t\\t\\ti _ i + 4.\\n\\t\\t]\\n\\t] ifFalse: [\\n\\t\\ti _ (startX // incX << 3) +1.\\n\\t\\tstartX to: width-1 by: incX do: [ :x |\\n\\t\\t\\tpixel at: 4 put: (thisScanline at: i+6);\\n\\t\\t\\t\\tat: 3 put: (thisScanline at: i);\\n\\t\\t\\t\\tat: 2 put: (thisScanline at: i+2);\\n\\t\\t\\t\\tat: 1 put: (thisScanline at: i+4).\\n\\t\\t\\ttempBits at: x+1 put: pixel.\\n\\t\\t\\ti _ i + 8.\\n\\t\\t].\\n\\t].\\n\\ttempForm displayOn: form at: 0@y rule: Form paintAlpha.\\n\\n! !\\n\\n!PNGReadWriter methodsFor: 'pixel copies' stamp: 'ar 2/19/2004 00:10'!\\nrgbaDecoderMapForDepth: decoderDepth\\n\\tbigEndian ifTrue:[\\n\\t\\tdepth = 16 ifTrue:[\\n\\t\\t\\t\\\"Big endian, 32 -> 16 color mapping.\\\"\\n\\t\\t\\t^ColorMap\\n\\t\\t\\t\\tshifts: #(-17 -14 -11 0)\\n\\t\\t\\t\\tmasks: #(16rF8000000 16rF80000 16rF800 16r00)\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"Big endian, 32 -> 32 color mapping\\\"\\n\\t\\t\\t^ColorMap \\n\\t\\t\\t\\tshifts: #(-8 -8 -8 24) \\n\\t\\t\\t\\tmasks: #(16rFF000000 16rFF0000 16rFF00 16rFF).\\n\\t\\t].\\n\\t].\\n\\tdepth = 16 ifTrue:[\\n\\t\\t\\\"Little endian, 32 -> 16 color mapping.\\\"\\n\\t\\t^ColorMap\\n\\t\\t\\tshifts: #(7 -6 -19 0)\\n\\t\\t\\tmasks: #(16rF8 16rF800 16rF80000 0)\\n\\t] ifFalse:[\\n\\t\\t\\\"Little endian, 32 -> 32 color mapping\\\"\\n\\t\\t^ColorMap \\n\\t\\t\\tshifts: #(-16 0 16 0) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t].! !\\n\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 16:37'!\\nnextPutImage: aForm\\n\\t\\\"Write out the given form. We're keeping it simple here, no interlacing, no filters.\\\"\\n\\t^self nextPutImage: aForm interlace: 0 filter: 0. \\\"no filtering\\\"! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 7/30/2004 17:51'!\\nnextPutImage: aForm interlace: aMethod filter: aFilterType \\n\\t\\\"Note: For now we keep it simple - interlace and filtering are simply ignored\\\"\\n\\n\\t| crcStream |\\n\\tbigEndian := SmalltalkImage current isBigEndian.\\n\\tform := aForm.\\n\\twidth := aForm width.\\n\\theight := aForm height.\\n\\taForm depth <= 8 \\n\\t\\tifTrue: \\n\\t\\t\\t[bitsPerChannel := aForm depth.\\n\\t\\t\\tcolorType := 3.\\n\\t\\t\\tbytesPerScanline := (width * aForm depth + 7) // 8]\\n\\t\\tifFalse: \\n\\t\\t\\t[bitsPerChannel := 8.\\n\\t\\t\\tcolorType := 6.\\n\\t\\t\\tbytesPerScanline := width * 4].\\n\\tself writeFileSignature.\\n\\tcrcStream := WriteStream on: (ByteArray new: 1000).\\n\\tcrcStream resetToStart.\\n\\tself writeIHDRChunkOn: crcStream.\\n\\tself writeChunk: crcStream.\\n\\tform depth <= 8 \\n\\t\\tifTrue: \\n\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\tself writePLTEChunkOn: crcStream.\\n\\t\\t\\tself writeChunk: crcStream.\\n\\t\\t\\tform isColorForm \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\t\\t\\tself writeTRNSChunkOn: crcStream.\\n\\t\\t\\t\\t\\tself writeChunk: crcStream]].\\n\\tform depth = 16 \\n\\t\\tifTrue: \\n\\t\\t\\t[crcStream resetToStart.\\n\\t\\t\\tself writeSBITChunkOn: crcStream.\\n\\t\\t\\tself writeChunk: crcStream].\\n\\tcrcStream resetToStart.\\n\\tself writeIDATChunkOn: crcStream.\\n\\tself writeChunk: crcStream.\\n\\tcrcStream resetToStart.\\n\\tself writeIENDChunkOn: crcStream.\\n\\tself writeChunk: crcStream! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 2/17/2004 16:51'!\\nupdateCrc: oldCrc from: start to: stop in: aCollection\\n\\t^ZipWriteStream updateCrc: oldCrc from: start to: stop in: aCollection! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'BG 3/16/2005 08:26'!\\nwriteChunk: crcStream\\n\\t| bytes length crc debug |\\n\\tdebug _ self debugging.\\n\\tbytes := crcStream originalContents.\\n\\tlength := crcStream position.\\n\\tcrc := self updateCrc: 16rFFFFFFFF from: 1 to: length in: bytes.\\n\\tcrc := crc bitXor: 16rFFFFFFFF.\\n\\tdebug ifTrue: [ Transcript cr;\\n\\t\\tprint: stream position; space;\\n\\t\\tnextPutAll: (bytes copyFrom: 1 to: 4) asString;\\n\\t\\tnextPutAll: ' len='; print: length;\\n\\t\\tnextPutAll: ' crc=0x'; nextPutAll: crc printStringHex ].\\n\\tstream nextNumber: 4 put: length-4. \\\"exclude chunk name\\\"\\n\\tstream next: length putAll: bytes startingAt: 1.\\n\\tstream nextNumber: 4 put: crc.\\n\\tdebug ifTrue: [ Transcript nextPutAll: ' afterPos='; print: stream position ].\\n\\tcrcStream resetToStart.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 16:40'!\\nwriteFileSignature\\n\\tstream nextPutAll: #(16r89 16r50 16r4E 16r47 16r0D 16r0A 16r1A 16r0A) asByteArray! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 2/17/2004 14:57'!\\nwriteIDATChunkOn: aStream\\n\\t\\\"Write the IDAT chunk\\\"\\n\\t| z |\\n\\taStream nextPutAll: 'IDAT' asByteArray.\\n\\tz _ ZLibWriteStream on: aStream.\\n\\tform depth <= 8 \\n\\t\\tifTrue:[self writeType3DataOn: z]\\n\\t\\tifFalse:[ self writeType6DataOn: z].\\n\\tself debugging ifTrue: [\\n\\t\\tTranscript cr;\\n\\t\\t\\tnextPutAll: 'compressed size=';\\n\\t\\t\\tprint: aStream position;\\n\\t\\t\\tnextPutAll: ' uncompressed size=';\\n\\t\\t\\tprint: z position ]\\n! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:08'!\\nwriteIENDChunkOn: aStream\\n\\t\\\"Write the IEND chunk\\\"\\n\\taStream nextPutAll: 'IEND' asByteArray.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:21'!\\nwriteIHDRChunkOn: aStream\\n\\t\\\"Write the IHDR chunk\\\"\\n\\taStream nextPutAll: 'IHDR' asByteArray.\\n\\taStream nextInt32Put: width.\\n\\taStream nextInt32Put: height.\\n\\taStream nextNumber: 1 put: bitsPerChannel.\\n\\taStream nextNumber: 1 put: colorType.\\n\\taStream nextNumber: 1 put: 0. \\\"compression\\\"\\n\\taStream nextNumber: 1 put: 0. \\\"filter method\\\"\\n\\taStream nextNumber: 1 put: 0. \\\"interlace method\\\"\\n! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'nk 4/17/2004 19:44'!\\nwritePLTEChunkOn: aStream\\n\\t\\\"Write the PLTE chunk\\\"\\n\\t| r g b colors |\\n\\taStream nextPutAll: 'PLTE' asByteArray.\\n\\t(form isColorForm) \\n\\t\\tifTrue:[colors := form colors]\\n\\t\\tifFalse:[colors := Color indexedColors copyFrom: 1 to: (1 bitShift: form depth)].\\n\\tcolors do:[:aColor|\\n\\t\\tr := (aColor red * 255) truncated.\\n\\t\\tg := (aColor green * 255) truncated.\\n\\t\\tb := (aColor blue * 255) truncated.\\n\\t\\taStream nextPut: r; nextPut: g; nextPut: b.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 18:29'!\\nwriteSBITChunkOn: aStream\\n\\t\\\"Write the IDAT chunk\\\"\\n\\taStream nextPutAll: 'sBIT' asByteArray.\\n\\tform depth = 16 ifFalse:[self error: 'Unimplemented feature'].\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 5.\\n\\taStream nextPut: 1.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 12/12/2003 17:34'!\\nwriteTRNSChunkOn: aStream\\n\\t\\\"Write out tRNS chunk\\\"\\n\\taStream nextPutAll: 'tRNS' asByteArray.\\n\\tform colors do:[:aColor|\\n\\t\\taStream nextPut: (aColor alpha * 255) truncated.\\n\\t].! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 1/1/1970 20:58'!\\nwriteType3DataOn: zStream\\n\\t\\\"Write color indexed data.\\\"\\n\\t| scanline hack hackBlt swizzleBlt swizzleHack hackDepth |\\n\\tscanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.\\n\\thackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].\\n\\thack := Form extent: width@1 depth: hackDepth bits: scanline.\\n\\thackBlt := BitBlt toForm: hack.\\n\\thackBlt sourceForm: form.\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@0.\\n\\thackBlt width: width; height: 1.\\n\\t(form depth < 8 and:[bigEndian not]) ifTrue:[\\n\\t\\tswizzleHack := Form new hackBits: scanline.\\n\\t\\tswizzleBlt := BitBlt toForm: swizzleHack.\\n\\t\\tswizzleBlt sourceForm: swizzleHack.\\n\\t\\tswizzleBlt combinationRule: Form over.\\n\\t\\tswizzleBlt colorMap: (StandardSwizzleMaps at: form depth).\\n\\t].\\n\\t0 to: height-1 do:[:i|\\n\\t\\thackBlt sourceOrigin: 0@i; copyBits.\\n\\t\\tswizzleBlt ifNotNil:[swizzleBlt copyBits].\\n\\t\\tzStream nextPut: 0. \\\"filterType\\\"\\n\\t\\tzStream next: bytesPerScanline putAll: scanline startingAt: 1.\\n\\t].\\n\\tzStream close.! !\\n\\n!PNGReadWriter methodsFor: 'writing' stamp: 'ar 2/19/2004 00:10'!\\nwriteType6DataOn: zStream\\n\\t\\\"Write RGBA data.\\\"\\n\\t| scanline hack hackBlt cm miscBlt |\\n\\tscanline := ByteArray new: bytesPerScanline.\\n\\thack := Form extent: width@1 depth: 32 bits: scanline.\\n\\tform depth = 16 ifTrue:[\\n\\t\\t\\\"Expand 16 -> 32\\\"\\n\\t\\tmiscBlt := BitBlt toForm: hack.\\n\\t\\tmiscBlt sourceForm: form.\\n\\t\\tmiscBlt combinationRule: Form over.\\n\\t\\tmiscBlt destOrigin: 0@0.\\n\\t\\tmiscBlt width: width; height: 1.\\n\\t].\\n\\thackBlt := BitBlt toForm: hack.\\n\\thackBlt sourceForm: (miscBlt ifNil:[form] ifNotNil:[hack]).\\n\\thackBlt combinationRule: Form over.\\n\\thackBlt destOrigin: 0@0.\\n\\thackBlt width: width; height: 1.\\n\\tbigEndian ifTrue:[\\n\\t\\tcm := ColorMap \\n\\t\\t\\tshifts: #(8 8 8 -24) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t] ifFalse:[\\n\\t\\tcm := ColorMap \\n\\t\\t\\tshifts: #(-16 0 16 0) \\n\\t\\t\\tmasks: #(16rFF0000 16rFF00 16rFF 16rFF000000).\\n\\t].\\n\\thackBlt colorMap: cm.\\n\\t0 to: height-1 do:[:i|\\n\\t\\tmiscBlt ifNil:[\\n\\t\\t\\thackBlt sourceOrigin: 0@i; copyBits.\\n\\t\\t] ifNotNil:[\\n\\t\\t\\tmiscBlt sourceOrigin: 0@i; copyBits.\\n\\t\\t\\thack fixAlpha.\\n\\t\\t\\thackBlt copyBits.\\n\\t\\t].\\n\\t\\tzStream nextPut: 0. \\\"filterType\\\"\\n\\t\\tzStream nextPutAll: scanline.\\n\\t].\\n\\tzStream close.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPNGReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'ar 2/11/2004 00:54'!\\ncomputeSwizzleMapForDepth: depth\\n\\t\\\"Answer a map that maps pixels in a word to their opposite location. Used for 'middle-endian' forms where the byte-order is different from the bit order (good joke, eh?).\\\"\\n\\t| map swizzled |\\n\\tmap := Bitmap new: 256.\\n\\tdepth = 4 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 15) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 15) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\n\\tdepth = 2 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 3) bitShift: 6).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 3) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 3) bitShift: 2).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 3) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\n\\tdepth = 1 ifTrue:[\\n\\t\\t0 to: 255 do:[:pix|\\n\\t\\t\\tswizzled := 0.\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 1) bitShift: 7).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -1) bitAnd: 1) bitShift: 6).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 1) bitShift: 5).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -3) bitAnd: 1) bitShift: 4).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 1) bitShift: 3).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -5) bitAnd: 1) bitShift: 2).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 1) bitShift: 1).\\n\\t\\t\\tswizzled := swizzled bitOr: (((pix bitShift: -7) bitAnd: 1) bitShift: 0).\\n\\t\\t\\tmap at: pix+1 put: swizzled.\\n\\t\\t].\\n\\t\\t^ColorMap colors: map\\n\\t].\\n\\tself error: 'Unrecognized depth'! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:22'!\\ncreateAFormFrom: data\\n\\n\\t| error f |\\n\\n\\terror _ ''.\\n\\tf _ [\\n\\t\\tself formFromStream: (RWBinaryOrTextStream with: data)\\n\\t] ifError: [ :a :b |\\n\\t\\terror _ a printString,' ',b printString.\\n\\t\\t(StringMorph contents: error) color: Color red; imageForm\\n\\t].\\n\\t^{f. error}! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:20'!\\ndebugging: aBoolean\\n\\n\\tDebugging _ aBoolean! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'ar 2/11/2004 00:55'!\\ninitialize\\n\\t\\\"\\n\\tPNGReadWriter initialize\\n\\t\\\"\\n\\n\\tBPP _ {\\t#(1 2 4 8 16).\\n\\t\\t\\t#(0 0 0 0 0).\\n\\t\\t\\t#(0 0 0 24 48).\\n\\t\\t\\t#(1 2 4 8 0).\\n\\t\\t\\t#(0 0 0 16 32).\\n\\t\\t\\t#(0 0 0 0 0).\\n\\t\\t\\t#(0 0 0 32 64).\\n\\t\\t\\t#(0 0 0 0 0) }.\\n\\n\\tBlockHeight _ #(8 8 4 4 2 2 1).\\n\\tBlockWidth _ #(8 4 4 2 2 1 1).\\n\\n\\tStandardColors := Color indexedColors collect:[:aColor|\\n\\t\\tColor \\n\\t\\t\\tr: (aColor red * 255) truncated / 255\\n\\t\\t\\tg: (aColor green * 255) truncated / 255\\n\\t\\t\\tb: (aColor blue * 255) truncated / 255.\\n\\t].\\n\\n\\tStandardSwizzleMaps := Array new: 4.\\n\\t#(1 2 4) do:[:i| StandardSwizzleMaps at: i put: (self computeSwizzleMapForDepth: i)].! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 11/7/2000 09:15'!\\ninsertMorph: aMorph named: aString into: aBook\\n\\n\\t| newPage |\\n\\n\\taBook ifNil: [^self].\\n\\tnewPage _ aBook insertPageLabel: aString morphs: {aMorph}.\\n\\tnewPage color: Color lightYellow.\\n\\tnewPage extent: (\\n\\t\\tnewPage submorphs inject: 10@10 into: [ :ex :m |\\n\\t\\t\\tm left: 10.\\n\\t\\t\\tex max: m width @ m bottom\\n\\t\\t]\\n\\t) + (20@20).\\n! !\\n\\n!PNGReadWriter class methodsFor: 'as yet unclassified' stamp: 'RAA 12/10/2000 10:11'!\\ntest1\\n\\\"PNGReadWriter test1\\\"\\n\\t| data t error d0 d1 f fileInfo book result d2 |\\n\\n\\tDebugging _ true.\\n\\t1 = 1 ifTrue: [\\n\\t\\tbook _ BookMorph new.\\n\\t\\tbook setProperty: #transitionSpec toValue: {'silence'. #none. #none}.\\n\\t].\\n\\td0 _ FileDirectory default.\\n\\td1 _ d0 directoryNamed: 'PngSuite Folder'.\\n\\td2 _ d0 directoryNamed: 'BIG PNG'.\\n\\t{d0. d1. d2}.\\t\\t\\\"keep compiler quiet\\\"\\n\\\"==\\ncitrus_none_sub.png\\ncitrus_adm7_adap.png\\ncitrus_adm7_aver.png\\ncitrus_adm7_non.png\\ncitrus_adm7_paeth.png\\npngs-img-ie5mac.png\\n==\\\"\\n\\tfileInfo _ {\\n\\t\\td2. {'citrus_adm7_adap.png'}.\\n\\t\\t\\\"d1. d1 fileNames.\\\"\\n\\t}.\\n\\tfileInfo pairsDo: [ :dir :fileNames |\\n\\t\\tfileNames do: [ :each |\\n\\t\\t\\tTranscript cr; show: each.\\n\\t\\t\\tdata _ (dir fileNamed: each) contentsOfEntireFile.\\n\\t\\t\\terror _ ''.\\n\\t\\t\\tMessageTally spyOn: [\\n\\t\\t\\t\\tt _ [\\n\\t\\t\\t\\t\\tresult _ self createAFormFrom: data.\\n\\t\\t\\t\\t\\tf_ result first.\\n\\t\\t\\t\\t\\terror _ result second.\\n\\t\\t\\t\\t] timeToRun.].\\n\\t\\t\\tself insertMorph: f asMorph named: each into: book.\\n\\t\\t\\tTranscript show: each,' ',data size printString,' = ',t printString,' ms',error; cr.\\n\\t\\t].\\n\\t].\\n\\tbook ifNotNil: [book openInWorld].\\n\\tDebugging _ false.! !\\n\\n\\n!PNGReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:57'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('png')! !\\nTestCase subclass: #PNGReadWriterTest\\n\\tinstanceVariableNames: 'fileName'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'GraphicsTests-Files'!\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/11/2004 00:42'!\\ndrawStuffOn: aForm\\n\\t\\\"Draw stuff on aForm. Avoid any symmetry.\\\"\\n\\t| canvas |\\n\\tcanvas := FormCanvas on: aForm.\\n\\tcanvas frameAndFillRectangle: (1@1 corner: aForm extent - 15) fillColor: Color red borderWidth: 3 borderColor: Color green.\\n\\tcanvas fillOval: (aForm boundingBox topRight - (15@-5) extent: 20@20) color: Color blue borderWidth: 1 borderColor: Color white.\\n\\t^aForm\\n\\t\\\"(PNGReadWriterTest new drawStuffOn: (Form extent: 32@32 depth: 16)) display\\\"! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/11/2004 00:42'!\\ndrawTransparentStuffOn: aForm\\n\\t\\\"Draw stuff on aForm. Avoid any symmetry.\\\"\\n\\t| canvas |\\n\\tcanvas := FormCanvas on: aForm.\\n\\tcanvas frameAndFillRectangle: (1@1 corner: aForm extent - 15) fillColor: (Color red alpha: 0.25) borderWidth: 3 borderColor: (Color green alpha: 0.5).\\n\\tcanvas fillOval: (aForm boundingBox topRight - (15@-5) extent: 20@20) color: (Color white alpha: 0.75) borderWidth: 1 borderColor: Color blue.\\n\\t^aForm\\n\\t\\\"(PNGReadWriterTest new drawStuffOn: (Form extent: 32@32 depth: 16)) display\\\"! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 4/17/2004 19:45'!\\nencodeAndDecode: original\\n\\t\\\"Make sure that the given form is encoded and decoded correctly\\\"\\n\\t| stream bytes decoded maxErr |\\n\\t\\\"encode\\\"\\n\\tstream := ByteArray new writeStream.\\n\\t(PNGReadWriter on: stream) nextPutImage: original; close.\\n\\tbytes := stream contents.\\n\\n\\tself writeEncoded: bytes.\\n\\n\\t\\\"decode\\\"\\n\\tstream := self readEncoded: bytes.\\n\\tdecoded := (PNGReadWriter new on: stream) nextImage.\\n\\tdecoded display.\\n\\n\\t\\\"compare\\\"\\n\\tself assert: original width = decoded width.\\n\\tself assert: original height = decoded height.\\n\\tself assert: original depth = decoded depth.\\n\\tself assert: original bits = decoded bits.\\n\\tself assert: original class == decoded class.\\n\\t(original isColorForm) ifTrue:[\\n\\t\\toriginal colors with: decoded colors do:[:c1 :c2|\\n\\t\\t\\t\\\"we must round here due to encoding errors\\\"\\n\\t\\t\\tmaxErr := 1. \\\"max. error for 8bit rgb component\\\"\\n\\t\\t\\tself assert: ((c1 red * 255) truncated - (c2 red * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 green * 255) truncated - (c2 green * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 blue * 255) truncated - (c2 blue * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 alpha * 255) truncated - (c2 alpha * 255) truncated) abs <= maxErr.\\n\\t\\t].\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:49'!\\nencodeAndDecodeAlpha: original\\n\\tfileName := 'testAlpha', original depth printString,'.png'.\\n\\tself encodeAndDecode: original.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/18/2004 23:49'!\\nencodeAndDecodeColor: aColor depth: aDepth\\n\\t| aForm |\\n\\tfileName := 'testColor', aColor name, aDepth printString,'.png'.\\n\\taForm := Form extent: 32@32 depth: aDepth.\\n\\taForm fillColor: aColor.\\n\\tself encodeAndDecode: aForm.\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:02'!\\nencodeAndDecodeDisplay: depth\\n\\t| form |\\n\\tfileName := 'testDisplay', depth printString,'.png'.\\n\\tform := Form extent: (Display extent min: 560@560) depth: depth.\\n\\tSmalltalk isMorphic \\n\\t\\tifTrue:[World fullDrawOn: form getCanvas]\\n\\t\\tifFalse:[Display displayOn: form].\\n\\tself encodeAndDecode: form.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:50'!\\nencodeAndDecodeForm: original\\n\\tfileName := 'testForm', original depth printString,'.png'.\\n\\tself encodeAndDecode: original.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 4/17/2004 19:45'!\\nencodeAndDecodeReverse: original\\n\\t\\\"Make sure that the given form is encoded and decoded correctly\\\"\\n\\t| stream bytes decoded maxErr reversed |\\n\\tfileName := 'testReverse', original depth printString,'.png'.\\n\\tself assert: original class == Form. \\\"won't work with ColorForm\\\"\\n\\t\\\"Switch pixel order\\\"\\n\\treversed := Form extent: original extent depth: original depth negated.\\n\\toriginal displayOn: reversed.\\n\\tself assert: original width = reversed width.\\n\\tself assert: original height = reversed height.\\n\\tself assert: original depth = reversed depth.\\n\\tself deny: original nativeDepth = reversed nativeDepth.\\n\\toriginal depth = 32\\n\\t\\tifTrue:[self assert: original bits = reversed bits]\\n\\t\\tifFalse:[self deny: original bits = reversed bits].\\n\\n\\t\\\"encode\\\"\\n\\tstream := ByteArray new writeStream.\\n\\t(PNGReadWriter on: stream) nextPutImage: reversed; close.\\n\\tbytes := stream contents.\\n\\tself writeEncoded: bytes.\\n\\n\\t\\\"decode\\\"\\n\\tstream := bytes readStream.\\n\\tdecoded := (PNGReadWriter new on: stream) nextImage.\\n\\tdecoded display.\\n\\n\\t\\\"compare\\\"\\n\\tself assert: original width = decoded width.\\n\\tself assert: original height = decoded height.\\n\\tself assert: original depth = decoded depth.\\n\\tself assert: original bits = decoded bits.\\n\\tself assert: original class == decoded class.\\n\\t(original isColorForm) ifTrue:[\\n\\t\\toriginal colors with: decoded colors do:[:c1 :c2|\\n\\t\\t\\t\\\"we must round here due to encoding errors\\\"\\n\\t\\t\\tmaxErr := 1. \\\"max. error for 8bit rgb component\\\"\\n\\t\\t\\tself assert: ((c1 red * 255) truncated - (c2 red * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 green * 255) truncated - (c2 green * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 blue * 255) truncated - (c2 blue * 255) truncated) abs <= maxErr.\\n\\t\\t\\tself assert: ((c1 alpha * 255) truncated - (c2 alpha * 255) truncated) abs <= maxErr.\\n\\t\\t].\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 18:18'!\\nencodeAndDecodeStream: file\\n\\t| aForm |\\n\\tfile reset.\\n\\t(PNGReadWriter new on: file) understandsImageFormat ifFalse:[^self error: 'don''t understand format!!' ].\\n\\tfile reset.\\n\\taForm := (PNGReadWriter new on: file) nextImage.\\n\\taForm ifNil:[^self error: 'nil form' ].\\n\\taForm display.\\n\\tself encodeAndDecode: aForm.\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:36'!\\nencodeAndDecodeWithColors: aColorForm\\n\\t\\\"Screw around with aColorForm colors\\\"\\n\\t| colors nColors indexedColors max myRandom |\\n\\tfileName := 'testColors', aColorForm depth printString,'.png'.\\n\\tindexedColors := Color indexedColors.\\n\\tnColors := 1 bitShift: aColorForm depth.\\n\\tcolors := WriteStream on: Array new.\\n\\n\\t\\\"Make first half translucent\\\"\\n\\tmax := nColors // 2.\\n\\t1 to: max do:[:i|\\n\\t\\tcolors nextPut: ((indexedColors at: i) alpha: i / max asFloat).\\n\\t].\\n\\n\\t\\\"Make random choices for second half\\\"\\n\\tmyRandom := Random seed: 42315.\\n\\tmax to: nColors do:[:i|\\n\\t\\tcolors nextPut: (indexedColors atRandom: myRandom).\\n\\t].\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/29/2004 03:55'!\\nencodeAndDecodeWithError: aStream\\n\\tself should:[self encodeAndDecodeStream: aStream] raise: Error! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:10'!\\nreadEncoded: bytes\\n\\t\\\"Answer a ReadStream on the file named by fileName, if possible; else a ReadStream on bytes\\\"\\n\\n\\tfileName ifNil:[^ bytes readStream ].\\n\\t^(FileStream oldFileOrNoneNamed: fileName) ifNil: [ \\n\\t\\tTranscript nextPutAll: 'can''t open ', fileName; cr.\\n\\t\\tbytes readStream ].\\n! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:45'!\\nsetUp\\n\\tfileName := nil.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'nk 2/17/2004 11:29'!\\ntearDown\\n\\tWorld changed.! !\\n\\n!PNGReadWriterTest methodsFor: 'helpers' stamp: 'ar 2/12/2004 22:51'!\\nwriteEncoded: bytes\\n\\t| file |\\n\\tfileName ifNil:[^self].\\n\\tfalse ifTrue:[^self].\\n\\tfile := FileStream forceNewFileNamed: fileName.\\n\\t[file nextPutAll: bytes] ensure:[file close].! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest16Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 16))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest16BitDisplay\\n\\tself encodeAndDecodeDisplay: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest16BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 16))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest1Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:43'!\\ntest1BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest1BitDisplay\\n\\tself encodeAndDecodeDisplay: 1! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest1BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 1))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest2Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:43'!\\ntest2BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest2BitDisplay\\n\\tself encodeAndDecodeDisplay: 2! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest2BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 2))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest32Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest32BitDisplay\\n\\tself encodeAndDecodeDisplay: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest32BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest4Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:44'!\\ntest4BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest4BitDisplay\\n\\tself encodeAndDecodeDisplay: 4! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:56'!\\ntest4BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 4))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:50'!\\ntest8Bit\\n\\tself encodeAndDecodeForm: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:44'!\\ntest8BitColors\\n\\tself encodeAndDecodeWithColors: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 00:39'!\\ntest8BitDisplay\\n\\tself encodeAndDecodeDisplay: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/11/2004 01:57'!\\ntest8BitReversed\\n\\tself encodeAndDecodeReverse: (self drawStuffOn: (Form extent: 33@33 depth: 8))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/12/2004 22:49'!\\ntestAlphaCoding\\n\\tself encodeAndDecodeAlpha: (self drawTransparentStuffOn: (Form extent: 33@33 depth: 32))! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - bits' stamp: 'ar 2/29/2004 03:55'!\\ntestPngSuite\\n\\t\\\"Requires the suite from \\n\\t\\tftp://swrinde.nde.swri.edu/pub/png/images/suite/PngSuite.zip\\n\\tto be present as PngSuite.zip\\\"\\n\\t| file zip entries |\\n\\t[file := FileStream readOnlyFileNamed: 'PngSuite.zip'] on: Error do:[:ex| ex return].\\n\\tfile ifNil:[^self].\\n\\t[zip := ZipArchive new readFrom: file.\\n\\tentries := zip members select:[:mbr| mbr fileName asLowercase endsWith: '.png'].\\n\\tentries do:[:mbr| \\n\\t\\t(mbr fileName asLowercase first = $x)\\n\\t\\t\\tifTrue: [self encodeAndDecodeWithError: mbr contentStream ]\\n\\t\\t\\tifFalse: [self encodeAndDecodeStream: mbr contentStream ] ].\\n\\t] ensure:[file close].! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack16\\n\\tself encodeAndDecodeColor: Color blue depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack32\\n\\tself encodeAndDecodeColor: Color blue depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlack8\\n\\tself encodeAndDecodeColor: Color blue depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue16\\n\\tself encodeAndDecodeColor: Color blue depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue32\\n\\tself encodeAndDecodeColor: Color blue depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestBlue8\\n\\tself encodeAndDecodeColor: Color blue depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestGreen16\\n\\tself encodeAndDecodeColor: Color green depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:50'!\\ntestGreen32\\n\\tself encodeAndDecodeColor: Color green depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestGreen8\\n\\tself encodeAndDecodeColor: Color green depth: 8! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestRed16\\n\\tself encodeAndDecodeColor: Color red depth: 16! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:48'!\\ntestRed32\\n\\tself encodeAndDecodeColor: Color red depth: 32! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - colors' stamp: 'ar 2/18/2004 23:49'!\\ntestRed8\\n\\tself encodeAndDecodeColor: Color red depth: 8! !\\n\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:25'!\\ncoloredFiles16\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 16.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{Color red-> \\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADZJ\\nREFUeF7lziEBAAAMAjD6J8b9MRAT80uT65Af8AN+wA/4AT/gB/yAH/ADfsAP+AE/4AfmgQdc\\nz9xqBS2pdAAAAABJRU5ErkJggg=='.\\n\\tColor green->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjD6J77jMRAT80sunfIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA68HyT\\n3Gqf2I6NAAAAAElFTkSuQmCC'.\\n\\t\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjD6J77jMRAT80ty3fIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA48JxX\\n3GpYhihrAAAAAElFTkSuQmCC'.\\n\\tColor black->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQFBQUBSsjp7wAAADVJ\\nREFUeF7lziEBAAAMAjDk+xfmMRAT80ty3fIDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA48LbT\\nHD3MKH3GAAAAAElFTkSuQmCC'\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:24'!\\ncoloredFiles32\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 32.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{\\n\\t\\tColor red -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANUlEQVR4XuXOIQEAAAwEoe9f\\n+hZjAoFnbfVo+QE/4Af8gB/wA37AD/gBP+AH/IAf8AN+4DlwVA34ajP6EEoAAAAASUVORK5C\\nYII='.\\n\\t\\tColor green -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAM0lEQVR4XuXOMQ0AAAACIPuX\\n1hgejAIkPfMDfsAP+AE/4Af8gB/wA37AD/gBP+AH/MA7MFfR+Grvv2BdAAAAAElFTkSuQmCC'.\\n\\n\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANElEQVR4XuXOIQEAAAACIP+f\\n1hkGAp0k7Zcf8AN+wA/4AT/gB/yAH/ADfsAP+AE/4AfOgQFblfhqnnPWHAAAAABJRU5ErkJg\\ngg=='.\\n\\t\\tColor black -> 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAANUlEQVR4XuXOMQEAAAwCINc/\\ntIvhwcFPkuuWH/ADfsAP+AE/4Af8gB/wA37AD/gBP+AHxoEH95UAPU59TTMAAAAASUVORK5C\\nYII='\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:19'!\\ncoloredFiles8\\n\\t\\\"Created by\\n\\t\\t{Color red. Color green. Color blue. Color black} collect:[:fillC|\\n\\t\\t\\t| ff bytes |\\n\\t\\t\\tff := Form extent: 32@32 depth: 8.\\n\\t\\t\\tff fillColor: fillC.\\n\\t\\t\\tbytes := WriteStream on: ByteArray new.\\n\\t\\t\\tPNGReadWriter putForm: ff onStream: bytes.\\n\\t\\t\\tfillC ->\\n\\t\\t\\t\\t(Base64MimeConverter mimeEncode: (bytes contents readStream)) contents\\n\\t\\t].\\n\\t\\\"\\n\\t^{Color red->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGklEQVR4XmO4cwc/YLgz8hWMfAUjX8EIVQAAbnlwLukXXkcAAAAASUVORK5CYII='.\\n\\n\\tColor green->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmPQ1cUPGHRHvoKRr2DkKxihCgBZ3bQBCq5u/AAAAABJRU5ErkJggg=='.\\n\\n\\tColor blue->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmNwc8MPGNxGvoKRr2DkKxihCgCl7xgQRbPxcwAAAABJRU5ErkJggg=='.\\n\\n\\tColor black->\\n'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEX///8AAAD///9/f3//\\nAAAA/wAAAP8A/////wD/AP8fHx8/Pz9fX1+fn5+/v7/f398HBwcPDw8XFxcnJycvLy83NzdH\\nR0dPT09XV1dnZ2dvb293d3eHh4ePj4+Xl5enp6evr6+3t7fHx8fPz8/X19fn5+fv7+/39/cA\\nAAAAMgAAZQAAmAAAywAA/wAAADIAMjIAZTIAmDIAyzIA/zIAAGUAMmUAZWUAmGUAy2UA/2UA\\nAJgAMpgAZZgAmJgAy5gA/5gAAMsAMssAZcsAmMsAy8sA/8sAAP8AMv8AZf8AmP8Ay/8A//8y\\nAAAyMgAyZQAymAAyywAy/wAyADIyMjIyZTIymDIyyzIy/zIyAGUyMmUyZWUymGUyy2Uy/2Uy\\nAJgyMpgyZZgymJgyy5gy/5gyAMsyMssyZcsymMsyy8sy/8syAP8yMv8yZf8ymP8yy/8y//9l\\nAABlMgBlZQBlmABlywBl/wBlADJlMjJlZTJlmDJlyzJl/zJlAGVlMmVlZWVlmGVly2Vl/2Vl\\nAJhlMphlZZhlmJhly5hl/5hlAMtlMstlZctlmMtly8tl/8tlAP9lMv9lZf9lmP9ly/9l//+Y\\nAACYMgCYZQCYmACYywCY/wCYADKYMjKYZTKYmDKYyzKY/zKYAGWYMmWYZWWYmGWYy2WY/2WY\\nAJiYMpiYZZiYmJiYy5iY/5iYAMuYMsuYZcuYmMuYy8uY/8uYAP+YMv+YZf+YmP+Yy/+Y///L\\nAADLMgDLZQDLmADLywDL/wDLADLLMjLLZTLLmDLLyzLL/zLLAGXLMmXLZWXLmGXLy2XL/2XL\\nAJjLMpjLZZjLmJjLy5jL/5jLAMvLMsvLZcvLmMvLy8vL/8vLAP/LMv/LZf/LmP/Ly//L////\\nAAD/MgD/ZQD/mAD/ywD//wD/ADL/MjL/ZTL/mDL/yzL//zL/AGX/MmX/ZWX/mGX/y2X//2X/\\nAJj/Mpj/ZZj/mJj/y5j//5j/AMv/Msv/Zcv/mMv/y8v//8v/AP//Mv//Zf//mP//y/////9E\\nCiHUAAAAGUlEQVR4XmNgZMQPGBhHvoKRr2DkKxihCgBEmAQBphO0cAAAAABJRU5ErkJggg=='\\n}! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:25'!\\ndecodeColors: colorsAndFiles depth: requiredDepth\\n\\t| color bytes form |\\n\\tcolorsAndFiles do:[:assoc|\\n\\t\\tcolor := assoc key.\\n\\t\\tbytes := Base64MimeConverter mimeDecodeToBytes: assoc value readStream.\\n\\t\\tform := PNGReadWriter formFromStream: bytes.\\n\\t\\tself assert: form depth = requiredDepth.\\n\\t\\tself assert: (form pixelValueAt: 1@1) = (color pixelValueForDepth: requiredDepth).\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:30'!\\nencodeColors: colorsAndFiles depth: requiredDepth\\n\\t| color original ff encoded |\\n\\tcolorsAndFiles do:[:assoc|\\n\\t\\tcolor := assoc key.\\n\\t\\toriginal := Base64MimeConverter mimeDecodeToBytes: assoc value readStream.\\n\\t\\tff := Form extent: 32@32 depth: requiredDepth.\\n\\t\\tff fillColor: color.\\n\\t\\tencoded := WriteStream on: ByteArray new.\\n\\t\\tPNGReadWriter putForm: ff onStream: encoded.\\n\\t\\tself assert: (encoded contents = original contents).\\n\\t].! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors16\\n\\tself decodeColors: self coloredFiles16 depth: 16.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors32\\n\\tself decodeColors: self coloredFiles32 depth: 32.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:20'!\\ntestPngDecodingColors8\\n\\tself decodeColors: self coloredFiles8 depth: 8.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors16\\n\\tself encodeColors: self coloredFiles16 depth: 16.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors32\\n\\tself encodeColors: self coloredFiles32 depth: 32.! !\\n\\n!PNGReadWriterTest methodsFor: 'tests - decoding' stamp: 'ar 2/19/2004 00:28'!\\ntestPngEncodingColors8\\n\\tself encodeColors: self coloredFiles8 depth: 8.! !\\nImageReadWriter subclass: #PNMReadWriter\\n\\tinstanceVariableNames: 'first type origin cols rows depth maxValue tupleType pragma'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Files'!\\n!PNMReadWriter commentStamp: 'jdr 10/20/2003 17:08' prior: 0!\\nI am a subclass of ImageReadWriter that decodes portable anymap file formats\\n(pbm, pgm, ppm and pam) images.\\n\\nI accept the #origin pragma for SE files as described in:\\nAlgoritms For Image Processing And Computer Vision. J. R. Parker\\n\\nDon't work with 2 bytes samples (16 bit grays, > 32 bits color, etc...), \\npam files preliminary support.\\n\\nf _ ImageReadWriter formFromFileNamed: 'Tools:Squeak3.4:Carmen.ppm'.\\nf morphEdit\\n\\nSubmitted by Javier Diaz Reinoso, Oct/2003!\\n]style[(361 18 2 26 3 11 1 43)f1,cblack;f1,f1b,f1,f1b,f1,f1b,f1!\\n\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/16/2003 14:52'!\\norigin\\n\\t^origin! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/15/2003 15:35'!\\npragma: s\\n\\tpragma _ s! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/10/2003 18:04'!\\nstream: s\\n\\tstream _ s! !\\n\\n!PNMReadWriter methodsFor: 'accessing' stamp: 'jdr 10/16/2003 14:53'!\\ntupleType\\n\\t^tupleType! !\\n\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 17:19'!\\ncleanLine\\n\\t\\\"upTo LF or CR, tab as space\\\"\\n\\n\\t| line loop b |\\n\\tline _ WriteStream with: ''.\\n\\tloop _ true.\\n\\t[loop] whileTrue: [\\n\\t\\tb _ stream next.\\n\\t\\tb ifNil:[\\n\\t\\t\\tloop _ false\\t\\t\\\"EOS\\\"\\n\\t\\t]\\n\\t\\tifNotNil: [\\n\\t\\t\\t(b = (Character cr) or:[b = Character lf]) ifTrue:[\\n\\t\\t\\t\\tloop _ false.\\n\\t\\t\\t]\\n\\t\\t\\tifFalse:[\\n\\t\\t\\t\\tb = (Character tab) ifTrue:[b _ Character space].\\n\\t\\t\\t\\tline nextPut: b.\\n\\t\\t\\t]\\n\\t\\t]\\n\\t].\\n\\t^line contents! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:20'!\\ngetTokenPbm: aCollection\\n\\t\\\"get a number, return rest of collection\\\"\\n\\t| line tokens token |\\n\\ttokens _ aCollection.\\n\\ttokens size = 0 ifTrue:[\\n\\t\\t[\\n\\t\\t\\tline _ self pbmGetLine.\\n\\t\\t\\tline ifNil:[^{nil . nil}].\\n\\t\\t\\ttokens _ line findTokens: ' '.\\n\\t\\t\\ttokens size = 0\\n\\t\\t] whileTrue:[].\\n\\t].\\n\\t\\\"Transcript cr; show: tokens asString.\\\"\\n\\ttoken _ tokens removeFirst.\\n\\t^{token asInteger . tokens}\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 16:39'!\\nnextImage\\n\\t\\\"read one image\\\"\\n\\t| data p |\\n\\tfirst ifNil:[\\n\\t\\tfirst _ false.\\n\\t\\tdata _ stream contentsOfEntireFile.\\n\\t\\tstream _ (RWBinaryOrTextStream with: data) reset.\\n\\t]\\n\\tifNotNil:[\\n\\t\\ttype < 4 ifTrue:[\\n\\t\\t\\tself error:'Plain PBM, PGM or PPM have only one image'\\n\\t\\t].\\n\\t].\\n\\tstream ascii.\\n\\tp _ stream next.\\n\\ttype _ (stream next) asInteger - 48.\\n\\t(p = $P and:[type > 0 and:[type < 8]]) ifFalse:[\\n\\t\\tself error:'Not a PNM file'\\n\\t].\\n\\ttype = 7 ifTrue:[\\n\\t\\tself readHeaderPAM\\n\\t]\\n\\tifFalse: [\\n\\t\\tself readHeader\\n\\t].\\n\\ttype caseOf: {\\n\\t\\t[1] \\t->\\t[^self readPlainBW].\\n\\t\\t[2] \\t->\\t[^self readPlainGray].\\n\\t\\t[3] \\t->\\t[^self readPlainRGB].\\n\\t\\t[4] \\t->\\t[^self readBWreverse: false].\\n\\t\\t[5] \\t->\\t[^self readGray].\\n\\t\\t[6] \\t->\\t[^self readRGB].\\n\\t\\t[7] \\t->\\t[\\t\\\"PAM\\\"\\n\\t\\t\\t\\t\\t(tupleType asUppercase) caseOf: {\\n\\t\\t\\t\\t\\t\\t['BLACKANDWHITE'] \\t\\t-> [^self readBWreverse: true].\\n\\t\\t\\t\\t\\t\\t['GRAYSCALE'] \\t\\t\\t-> [^self readGray].\\n\\t\\t\\t\\t\\t\\t['RGB'] \\t\\t\\t\\t\\t-> [^self readRGB].\\n\\t\\t\\t\\t\\t\\t['RGB_ALPHA'] \\t\\t\\t-> [^self error:'Not implemented'].\\n\\t\\t\\t\\t\\t\\t['GRAYSCALE_ALPHA'] \\t-> [^self error:'Not implemented'].\\n\\t\\t\\t\\t\\t} otherwise: [^self readData].\\n\\t\\t\\t\\t]\\n\\t}! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/10/2003 15:09'!\\npbmGetLine\\n\\t\\\"Get the next non-comment line from the PBM stream\\n\\tLook for 'pragmas' - commands hidden in the comments\\\"\\n\\t\\n \\t| line |\\n\\t[\\n\\t\\tline _ self cleanLine.\\n\\t\\tline ifNil: [^nil].\\n\\t\\t(line size > 0 and:[(line at: 1) = $#]) ifTrue:[\\n\\t\\t\\tself pbmParam: line.\\n\\t\\t].\\n\\t\\t(line size = 0) or:[(line at: 1) = $#]\\n\\t]\\n \\twhileTrue: [].\\n\\t^line! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/10/2003 15:11'!\\npbmParam: line\\n\\t\\\"Look for a parameter hidden in a comment\\\"\\n\\t| key tokens |\\n\\ttokens _ line findTokens: ' '.\\n\\tkey _ (tokens at: 1) asLowercase.\\n\\t(key = '#origin' and:[tokens size = 3]) ifTrue:[\\t\\\"ORIGIN key word\\\"\\n\\t\\t\\\"This is for SE files as described in:\\n\\t\\tAlgoritms For Image Processing And Computer Vision. J. R. Parker\\\"\\n\\t\\torigin _ ((tokens at: 2) asInteger) @ ((tokens at: 3) asInteger)\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 7/18/2005 17:02'!\\nr: r g: g b: b for: aDepth\\n\\t\\\"integer value according depth\\\"\\n\\t| val |\\n\\taDepth = 16 ifTrue: [\\n\\t\\tval := (1 << 15) + (r << 10) + (g << 5) + b.\\n\\t]\\n\\tifFalse:[\\n\\t\\tval := (16rFF << 24) + (r << 16) + (g << 8) + b.\\n\\t].\\n\\t^val\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:49'!\\nreadBWreverse: flagXor\\n\\t\\\"B&W for PAM\\\"\\n\\t| val form bytesRow nBytes |\\n\\tstream binary.\\n\\tform _ Form extent: cols@rows depth: 1.\\n\\tnBytes _ (cols/8) ceiling.\\n\\tbytesRow _ (cols/32) ceiling * 4.\\n\\t0 to: rows-1 do: [:y | | i |\\n\\t\\ti _ 1 + (bytesRow*y).\\n\\t\\t0 to: nBytes-1 do: [:x |\\n\\t\\t\\tval _ stream next.\\n\\t\\t\\tflagXor ifTrue:[val _ val bitXor: 16rFF].\\n\\t\\t\\tform bits byteAt: i put: val.\\n\\t\\t\\ti _ i+1.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'md 10/20/2004 15:45'!\\nreadData\\n\\t\\\"generic data\\\"\\n\\t| data nBits nBytes val sample |\\n\\tstream binary.\\n\\tdata _ OrderedCollection new.\\n\\tnBits _ maxValue floorLog:2.\\n\\tnBytes _ (nBits+1) >> 3.\\n\\t(nBits+1 rem: 8) > 0 ifTrue:[nBytes _ nBytes+1].\\n\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ 0.\\n\\t\\t\\t1 to: nBytes do: [:n |\\n\\t\\t\\t\\tsample _ stream next.\\n\\t\\t\\t\\tval _ val << 8 + sample.\\n\\t\\t\\t].\\n\\t\\t\\tdata add: val.\\n\\t\\t]\\n\\t].\\n\\t^data\\n\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:44'!\\nreadGray\\n\\t\\\"gray form\\\"\\n\\t| val form poker |\\n\\tmaxValue > 255 ifTrue:[self error:'Gray value > 8 bits not supported in Squeak'].\\n\\tstream binary.\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ stream next.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 15:44'!\\nreadHeader\\n\\t\\\"read header for pbm, pgm or ppm\\\"\\n\\t| tokens aux d c |\\n\\ttokens _ OrderedCollection new.\\n\\taux _ self getTokenPbm: tokens.\\n\\tcols _ aux at: 1. tokens _ aux at: 2.\\n\\taux _ self getTokenPbm: tokens.\\n\\trows _ aux at: 1. tokens _ aux at: 2.\\n\\n\\t(type = 1 or:[type = 4]) ifTrue:[\\n\\t\\tmaxValue _ 1\\n\\t]\\n\\tifFalse: [\\n\\t\\taux _ self getTokenPbm: tokens.\\n\\t\\tmaxValue _ aux at: 1. tokens _ aux at: 2.\\n\\t].\\n\\td _ {1 . 2 . 4 . \\t8 . \\t\\t16 . 32}.\\n\\tc _ {2 . 4 . 16 . 256 . 32768 . 16777216}. \\n\\t(type = 3 or:[type = 6]) ifTrue: [\\n\\t\\tmaxValue >= 65536 ifTrue:[\\n\\t\\t\\tself error:'Pixmap > 48 bits not supported in PPM'\\n\\t\\t].\\n\\t\\tmaxValue >= 256 ifTrue:[\\n\\t\\t\\tself error:'Pixmap > 32 bits are not supported in Squeak'\\n\\t\\t].\\n\\t\\tmaxValue < 32 ifTrue:[depth _ 16] ifFalse:[depth _ 32].\\n\\t]\\n\\tifFalse: [\\n\\t\\tdepth _ nil.\\n\\t\\t1 to: c size do:[:i| ((c at: i) > maxValue and:[depth = nil]) ifTrue:[depth_d at: i]].\\n\\t].\\n\\tTranscript cr; show: 'PBM file class ', type asString, ' size ', cols asString, ' x ', \\n\\t\\trows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:35'!\\nreadHeaderPAM\\n\\t\\\"read pam header, not tested\\\"\\n\\t| loop line tokens key val |\\n\\ttupleType _ ''.\\n\\tloop _ true.\\n\\tloop whileTrue:[\\n\\t\\tline _ self pbmGetLine.\\n\\t\\ttokens _ line findTokens: ' '.\\n\\t\\ttokens size = 2 ifTrue:[\\n\\t\\t\\tkey _ tokens at: 1 asUppercase.\\n\\t\\t\\tval _ tokens at: 2.\\n\\t\\t\\tkey caseOf: {\\n\\t\\t\\t\\t['WIDTH'] \\t\\t-> [cols _ val asInteger].\\n\\t\\t\\t\\t['HEIGHT'] \\t\\t-> [rows _ val asInteger].\\n\\t\\t\\t\\t['DEPTH'] \\t\\t-> [depth _ val asInteger].\\n\\t\\t\\t\\t['MAXVAL']\\t\\t-> [maxValue _ val asInteger].\\n\\t\\t\\t\\t['TUPLETYPE']\\t-> [tupleType _ tupleType, ' ', val].\\n\\t\\t\\t\\t['ENDHDR']\\t\\t-> [loop _ false].\\n\\t\\t\\t}\\n\\t\\t]\\n\\t].\\n\\tTranscript cr; show: 'PAM file class ', type asString, ' size ', cols asString, ' x ', \\n\\t\\trows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 16:03'!\\nreadPlainBW\\n\\t\\\"plain BW\\\"\\n\\t| val form poker |\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\t[val _ stream next. (val = $0 or:[val = $1])] whileFalse:[\\n\\t\\t\\t\\tval ifNil:[self error:'End of file reading PBM'].\\n\\t\\t\\t].\\n\\t\\t\\tpoker pixelAt: x@y put: (val asInteger).\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/16/2003 15:44'!\\nreadPlainGray\\n\\t\\\"plain gray\\\"\\n\\t| val form poker aux tokens |\\n\\tform _ Form extent: cols@rows depth: depth.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\ttokens _ OrderedCollection new.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\taux _ self getTokenPbm: tokens.\\n\\t\\t\\tval _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 10/15/2003 12:49'!\\nreadPlainRGB\\n\\t\\\"RGB form, use 32 bits\\\"\\n\\t| val form poker tokens aux |\\n\\tmaxValue > 255 ifTrue:[self error:'RGB value > 32 bits not supported in Squeak'].\\n\\tform _ Form extent: cols@rows depth: 32.\\n\\tpoker _ BitBlt current bitPokerToForm: form.\\n\\ttokens _ OrderedCollection new.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x | | r g b|\\n\\t\\t\\taux _ self getTokenPbm: tokens. r _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\taux _ self getTokenPbm: tokens. g _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\taux _ self getTokenPbm: tokens. b _ aux at: 1. tokens _ aux at: 2.\\n\\t\\t\\tval _ self r: r g: g b: b for: depth.\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n!PNMReadWriter methodsFor: 'reading' stamp: 'jdr 7/18/2005 16:58'!\\nreadRGB\\n\\t\\\"RGB form, use 16/32 bits\\\"\\n\\t| val form poker sample shift |\\n\\tmaxValue > 255 ifTrue:[self error:'RGB value > 32 bits not supported in Squeak'].\\n\\tstream binary.\\n\\tform := Form extent: cols@rows depth: depth.\\n\\tpoker := BitBlt current bitPokerToForm: form.\\n\\tdepth = 32 ifTrue:[shift := 8] ifFalse:[shift := 5].\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval := 16rFF.\\t\\\"no transparency\\\"\\n\\t\\t\\t1 to: 3 do: [:i |\\n\\t\\t\\t\\tsample := stream next.\\n\\t\\t\\t\\tval := val << shift + sample.\\n\\t\\t\\t].\\n\\t\\t\\tpoker pixelAt: x@y put: val.\\n\\t\\t]\\n\\t].\\n\\t^form\\n! !\\n\\n\\n!PNMReadWriter methodsFor: 'testing' stamp: 'jdr 10/11/2003 14:52'!\\nunderstandsImageFormat\\n\\t\\\"P1 to P7\\\"\\n\\t| p |\\n\\tp _ stream next asCharacter.\\n\\ttype _ stream next - 48.\\n\\t^(p = $P and:[type > 0 and:[type < 8]])\\n\\t! !\\n\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutBW: aForm reverse: flagXor\\n\\t| myType val nBytes bytesRow |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\t\\\"stream position: 0.\\\"\\n\\taForm depth = 1 ifTrue:[myType _ $4] ifFalse:[myType _ $5].\\n\\tself writeHeader: myType.\\n\\tstream binary.\\n\\tnBytes _ (cols/8) ceiling.\\n\\tbytesRow _ (cols/32) ceiling * 4.\\n\\t0 to: rows-1 do: [:y | | i |\\n\\t\\ti _ 1 + (bytesRow*y).\\n\\t\\t0 to: nBytes-1 do: [:x |\\n\\t\\t\\tval _ aForm bits byteAt: i.\\n\\t\\t\\tflagXor ifTrue:[val _ val bitXor: 16rFF].\\n\\t\\t\\tstream nextPut: val.\\n\\t\\t\\ti _ i+1.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutGray: aForm\\n\\t| myType peeker val |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\t\\\"stream position: 0.\\\"\\n\\taForm depth = 1 ifTrue:[myType _ $4] ifFalse:[myType _ $5].\\n\\tself writeHeader: myType.\\n\\tpeeker _ BitBlt current bitPeekerFromForm: aForm.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x |\\n\\t\\t\\tval _ peeker pixelAt: x@y.\\n\\t\\t\\tstream nextPut: val.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 14:22'!\\nnextPutImage: aForm\\n\\taForm unhibernate.\\n\\taForm depth\\t caseOf: {\\n\\t\\t[1] \\t\\t-> [self nextPutBW: aForm reverse: false].\\n\\t\\t[16] \\t-> [self nextPutRGB: aForm].\\n\\t\\t[32] \\t-> [self nextPutRGB: aForm].\\n\\t} otherwise: [\\n\\t\\t(aForm respondsTo: #colors) ifTrue:[\\n\\t\\t\\taForm colors ifNil: [\\n\\t\\t\\t\\tself nextPutGray: aForm\\n\\t\\t\\t]\\n\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\tself nextPutRGB: aForm\\n\\t\\t\\t]\\n\\t\\t]\\n\\t\\tifFalse:[\\n\\t\\t\\tself nextPutGray: aForm\\n\\t\\t]\\n\\t]! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/16/2003 16:08'!\\nnextPutRGB: aForm\\n\\t| myType peeker f shift mask |\\n\\tcols _ aForm width.\\n\\trows _ aForm height.\\n\\tdepth _ aForm depth.\\n\\tf _ aForm.\\n\\tdepth < 16 ifTrue:[\\n\\t\\tf _ aForm asFormOfDepth: 32.\\n\\t\\tdepth _ 32.\\n\\t].\\n\\tmyType _ $6.\\n\\t\\\"stream position: 0.\\\"\\n\\tself writeHeader: myType.\\n\\tdepth = 32 ifTrue:[shift _ 8. mask _ 16rFF] ifFalse:[shift _ 5. mask _ 16r1F].\\n\\tpeeker _ BitBlt current bitPeekerFromForm: f.\\n\\t0 to: rows-1 do: [:y |\\n\\t\\t0 to: cols-1 do: [:x | | p r g b |\\n\\t\\t\\tp _ peeker pixelAt: x@y.\\n\\t\\t\\tb _ p bitAnd: mask. p _ p >> shift.\\n\\t\\t\\tg _ p bitAnd: mask. p _ p >> shift.\\n\\t\\t\\tr _ p bitAnd: mask.\\n\\t\\t\\tstream nextPut: r.\\n\\t\\t\\tstream nextPut: g.\\n\\t\\t\\tstream nextPut: b.\\n\\t\\t]\\n\\t].\\n! !\\n\\n!PNMReadWriter methodsFor: 'writing' stamp: 'jdr 10/15/2003 15:48'!\\nwriteHeader: myType\\n\\t\\\"this is ascii\\\"\\n\\tstream nextPut: ($P asciiValue).\\n\\tstream nextPut: (myType asciiValue).\\n\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\tpragma ifNotNil:[\\n\\t\\tstream nextPutAll: (pragma asByteArray).\\n\\t].\\n\\tstream nextPutAll: (cols printString) asByteArray.\\n\\tstream nextPut: 32.\\t\\t\\\" \\\"\\n\\tstream nextPutAll: (rows printString) asByteArray.\\n\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\tdepth > 1 ifTrue: [| d c maxV |\\n\\t\\td _ {1 . 2 . 4 . 8 . 16 . 32}.\\n\\t\\tc _ {1 . 3 . 15 . 255 . 31 . 255}. \\n\\t\\tmaxV _ nil.\\n\\t\\t1 to: d size do:[:i| ((d at: i) = depth and:[maxV = nil]) ifTrue:[maxV _ c at: i]].\\n\\t\\tstream nextPutAll: (maxV printString) asByteArray.\\n\\t\\tstream nextPut: 10.\\t\\t\\\"nl\\\"\\n\\t]\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPNMReadWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!PNMReadWriter class methodsFor: 'image reading/writing' stamp: 'jdr 7/18/2005 16:25'!\\ntypicalFileExtensions\\n\\t\\\"Answer a collection of file extensions (lowercase) which files that I can read might commonly have\\\"\\n\\t^#('pbm' 'pnm' 'ppm' 'pam')! !\\n\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/11/2003 14:49'!\\ntestFromSEFile: filename\\n\\t\\\"read SE file, check origin\\n\\t\\tPNMReadWriter testFromSEFile: 'Tools:Squeak3.4:eliseSE.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw _ self new.\\n\\tprw stream: (FileStream readOnlyFileNamed: filename).\\n\\tf _ prw nextImage.\\n\\tf morphEdit.\\n\\tprw inspect! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/16/2003 17:22'!\\ntestFromString\\n\\t\\\"read SE file from string\\n\\t\\tPNMReadWriter testFromString\\n\\t\\\"\\n\\t| prw f s |\\n\\tprw _ self new.\\n\\ts _ \\n'P1\\n#origin 1 0\\n3 1\\n1\\t01'.\\n\\tprw stream: (ReadStream on: s from: 1 to: (s size)).\\n\\tf _ prw nextImage.\\n\\tf morphEdit.\\n\\tTranscript cr;show:'Origin=', prw origin asString; cr.! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 7/18/2005 17:03'!\\ntestMultiFile: filename\\n\\t\\\"write two files from user, then read\\n\\t\\tPNMReadWriter testMultiFile: 'Tools:Squeak3.6:outMulti.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw := self new.\\n\\tprw stream: ((FileStream newFileNamed: filename) binary).\\n\\tprw pragma: '#Squeak test', String lf.\\n\\tf := Form fromUser. prw nextPutImage: f. \\n\\tf := Form fromUser.prw nextPutImage: f.\\t\\n\\tprw close.\\n\\tprw stream: (StandardFileStream readOnlyFileNamed: filename).\\n\\tf := prw nextImage. (SketchMorph withForm: f) openInWorld.\\n\\tf := prw nextImage. (SketchMorph withForm: f) openInWorld.\\n! !\\n\\n!PNMReadWriter class methodsFor: 'testing' stamp: 'jdr 10/15/2003 15:43'!\\ntestToSEFile: filename\\n\\t\\\"write SE file with origin\\n\\t\\tPNMReadWriter testToSEFile: 'Tools:Squeak3.4:outSE.pbm'.\\n\\t\\\"\\n\\t| prw f |\\n\\tprw _ self new.\\n\\tprw stream: ((FileStream newFileNamed: filename) binary).\\n\\tprw pragma: '#origin 10 10', String lf.\\n\\tf _ Form fromUser.\\n\\tprw nextPutImage: f! !\\nProtocolClient subclass: #POP3Client\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Protocols'!\\n!POP3Client commentStamp: 'mir 5/12/2003 17:57' prior: 0!\\nThis class implements POP3 (Post Office Protocol 3) as specified in RFC 1939. (see http://www.ietf.org/rfc.html)\\n\\nYou can use it to download email from the mail server to your personal mail program.\\n\\nTo see an example of it's use, see POPSocket class>>example.!\\n\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:58'!\\napopLoginUser: userName password: password\\n\\n\\tself loginUser: userName password: password loginMethod: #APOP! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:35'!\\ndeleteMessage: num\\n\\t\\\"delete the numbered message\\\"\\n\\n\\tself ensureConnection.\\n\\tself sendCommand: 'DELE ', num printString.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:57'!\\nloginUser: userName password: password\\n\\n\\tself loginUser: userName password: password loginMethod: #clearText! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/8/2002 11:40'!\\nloginUser: userName password: password loginMethod: aLoginMethod\\n\\n\\tself user: userName.\\n\\tself password: password.\\n\\tself loginMethod: aLoginMethod.\\n\\tself login! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 4/7/2003 17:17'!\\nmessageCount\\n\\t\\\"Query the server and answer the number of messages that are in the user's mailbox.\\\"\\n\\n\\t| answerString numMessages |\\n\\tself ensureConnection.\\n\\tself sendCommand: 'STAT'.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\t[answerString _ (self lastResponse findTokens: Character separators) second.\\n\\tnumMessages _ answerString asNumber asInteger]\\n\\t\\ton: Error\\n\\t\\tdo: [:ex | (ProtocolClientError protocolInstance: self) signal: 'Invalid STAT response.'].\\n\\t^numMessages! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'len 12/14/2002 17:50'!\\nquit\\n\\t\\\"QUIT <CRLF>\\\"\\n\\n\\tself sendCommand: 'QUIT'.\\n\\tself checkResponse.! !\\n\\n!POP3Client methodsFor: 'public protocol' stamp: 'mir 3/7/2002 14:35'!\\nretrieveMessage: number\\n\\t\\\"retrieve the numbered message\\\"\\n\\n\\tself ensureConnection.\\n\\tself sendCommand: 'RETR ', number printString.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\t^self getMultilineResponse! !\\n\\n\\n!POP3Client methodsFor: 'private' stamp: 'mir 11/11/2002 16:20'!\\nloginMethod\\n\\t^self connectionInfo at: #loginMethod ifAbsent: [nil]! !\\n\\n!POP3Client methodsFor: 'private' stamp: 'mir 3/8/2002 11:41'!\\nloginMethod: aSymbol\\n\\t^self connectionInfo at: #loginMethod put: aSymbol! !\\n\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'BG 3/16/2005 08:27'!\\napopLogin\\n\\n\\t\\\"Attempt to authenticate ourselves to the server without sending the password as cleartext.\\\"\\n\\n\\t\\\"For secure authentication, we look for a timestamp in the initial response string we get from the server, and then try the APOP command as specified in RFC 1939. If the initial response from the server is\\n\\t+OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>\\nwe extract the timestamp\\n\\t<1896.697170952@dbc.mtview.ca.us>\\nthen form a string of the form\\n\\t<1896.697170952@dbc.mtview.ca.us>USERPASSWORD\\nand then send only the MD5 hash of that to the server. Thus the password never hits the wire\\\"\\n\\n\\t| timestamp hash |\\n\\n\\t[\\n\\t\\\"Look for a timestamp in the response we received from the server\\\"\\n\\ttimestamp _ self lastResponse findTokens: '<>' includes: '@'.\\n\\ttimestamp\\n\\t\\tifNil: [(POP3LoginError protocolInstance: self) signal: 'APOP not supported.'].\\n\\n\\t(Smalltalk includesKey: #MD5)\\n\\t\\tifTrue: [\\n\\t\\t\\thash _ ((Smalltalk at: #MD5) hashMessage: ('<', timestamp, '>', self password)) storeStringHex asLowercase.\\n\\t\\t\\t\\\"trim starting 16r and zero pad it to 32 characters if needed\\\"\\n\\t\\t\\thash _ hash padded: #left to: 32 with: $0]\\n\\t\\tifFalse: [(POP3LoginError protocolInstance: self) signal: 'APOP (MD5) not supported.'].\\n\\n\\tself sendCommand: 'APOP ', self user, ' ', hash.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse]\\n\\t\\ton: ProtocolClientError\\n\\t\\tdo: [:ex |\\n\\t\\t\\tself close.\\n\\t\\t\\t(LoginFailedException protocolInstance: self) signal: 'Login failed.']! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 4/7/2003 17:38'!\\nclearTextLogin\\n\\n\\t[self sendCommand: 'USER ', self user.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse.\\n\\n\\tself sendCommand: 'PASS ', self password.\\n\\tself checkResponse.\\n\\tself logProgress: self lastResponse]\\n\\t\\ton: TelnetProtocolError\\n\\t\\tdo: [:ex |\\n\\t\\t\\t\\\"Neither authentication worked. Indicate an error and close up\\\"\\n\\t\\t\\tself close.\\n\\t\\t\\tex resignalAs: ((LoginFailedException protocolInstance: self) signal: 'Login failed.')]! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 11/14/2002 17:40'!\\ngetMultilineResponse\\n\\t\\\"Get a multiple line response to the last command, filtering out LF characters. A multiple line response ends with a line containing only a single period (.) character.\\\"\\n\\n\\t| response done chunk |\\n\\tresponse _ WriteStream on: ''.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tchunk _ self stream nextLine.\\n\\t\\t(chunk beginsWith: '.')\\n\\t\\t\\tifTrue: [response nextPutAll: (chunk copyFrom: 2 to: chunk size); cr ]\\n\\t\\t\\tifFalse: [response nextPutAll: chunk; cr ].\\n\\t\\tdone _ (chunk = '.') ].\\n\\n\\t^ response contents\\n! !\\n\\n!POP3Client methodsFor: 'private protocol' stamp: 'mir 4/7/2003 17:39'!\\nlogin\\n\\tself loginMethod\\n\\t\\tifNil: [^self].\\n\\tself loginMethod == #clearText\\n\\t\\tifTrue: [^self clearTextLogin].\\n\\tself loginMethod == #APOP\\n\\t\\tifTrue: [^self apopLogin].\\n\\t(POP3LoginError protocolInstance: self) signal: 'Unsupported login procedure.'! !\\n\\n\\n!POP3Client methodsFor: 'private testing' stamp: 'mir 3/7/2002 13:43'!\\nresponseIsError\\n\\t^self lastResponse beginsWith: '-'! !\\n\\n!POP3Client methodsFor: 'private testing' stamp: 'mir 11/11/2002 15:44'!\\nresponseIsWarning\\n\\t^self lastResponse beginsWith: '-'! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPOP3Client class\\n\\tinstanceVariableNames: ''!\\n\\n!POP3Client class methodsFor: 'accessing' stamp: 'mir 3/7/2002 12:51'!\\ndefaultPortNumber\\n\\t^110! !\\n\\n!POP3Client class methodsFor: 'accessing' stamp: 'mir 3/7/2002 12:52'!\\nlogFlag\\n\\t^#pop! !\\n\\n\\n!POP3Client class methodsFor: 'example' stamp: 'rbb 3/1/2005 11:05'!\\nexample\\n\\t\\\"POP3Client example\\\"\\n\\t\\\"download a user's messages into an OrderedCollection and inspect the OrderedCollection\\\"\\n\\n\\t| ps messages userName password |\\n\\tuserName := (UIManager default request: 'POP username').\\n\\tpassword := (UIManager default request: 'POP password').\\n\\tps := POP3Client openOnHostNamed: (UIManager default request: 'POP server').\\n\\t[\\n\\tps loginUser: userName password: password.\\n\\tps logProgressToTranscript.\\n\\n\\tmessages := OrderedCollection new.\\n\\t1 to: ps messageCount do: [ :messageNr |\\n\\t\\tmessages add: (ps retrieveMessage: messageNr) ]]\\n\\t\\tensure: [ps close].\\n\\n\\tmessages inspect.! !\\nProtocolClientError subclass: #POP3LoginError\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Protocols'!\\n!POP3LoginError commentStamp: 'mir 5/12/2003 17:58' prior: 0!\\nException for signaling POP3 login failures.!\\n\\nObject subclass: #PRServerDirectory\\n\\tinstanceVariableNames: 'server directories'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n!PRServerDirectory commentStamp: 'md 1/26/2004 12:40' prior: 0!\\nAdd support to publish or download projects from Small-Land Project\\nRepository (SLPR).\\n\\nThe SLPR has virtual folders where the projects appears. The SLPR can\\nbe acceded from the FileList or from the web interface at\\nhttp://repository.small-land.org:8080\\n\\nBasically it's a type of superswiki (but better ;)).\\n\\nThe features in SMPR not present in SuperSwiki are:\\n\\n- Both the web interface and the squeak-side interface are full\\ntranslatable. The server has translations for English and Spanish just\\nnow, but it's almost trivial to include other translations... Stef?\\nMarcus? ;)\\n\\n- The projects are categorized in \\\"virtual\\\" folder. These folders (By\\nCategory, By Author, By Language, Alphabetical, etc) give us good\\nsearching behaviour just using the FileList and mouse clicks.\\n\\n- The web interface (also full translatable) has a search a la google.\\n\\n- All the urls to query the web interface are \\\"clean enough\\\" so google\\ncan make a good job indexing our content in .pr files.\\n\\n\\nIt's planned to add \\\"editing\\\" features to the web interface to\\nre-categorize, remove, etc projects.\\n\\n\\nEnjoy it,\\n\\n-- \\nDiego Gomez Deck\\nhttp://www.small-land.org!\\n\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 07:35'!\\ndirectories\\n\\t\\\"answer the receiver's directories\\\"\\n\\t^ directories! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:44'!\\ndirectory\\n\\t\\\"answer the receiver's directory\\\"\\n\\t| result |\\n\\tresult := String new writeStream.\\n\\tself directories\\n\\t\\tdo: [:each | result nextPutAll: each]\\n\\t\\tseparatedBy: [result nextPutAll: self slash].\\n\\t^ result contents! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 21:01'!\\ndirectoryWrapperClass\\n\\t\\\"answer the class to be used as a wrapper in FileList2\\\"\\n\\t^ FileDirectoryWrapper! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:44'!\\ndownloadUrl\\n\\t\\\"The url under which files will be accessible.\\\"\\n\\t^ (self urlFromServer: self server directories: {'programmatic'})\\n\\t\\t, self slash! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/27/2003 11:06'!\\nmoniker\\n\\t\\\"a plain language name for this directory\\\"\\n\\t^ self server! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 20:53'!\\nrealUrl\\n\\t\\\"a fully expanded version of the url we represent.\\\"\\n\\t^self urlFromServer: self server directories: self directories! !\\n\\n!PRServerDirectory methodsFor: 'accessing' stamp: 'dgd 12/22/2003 07:40'!\\nserver\\n\\t\\\"answer the receiver's server\\\"\\n\\t^ server! !\\n\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:25'!\\ncreateDirectory: localName \\n\\t\\\"Create a new sub directory within the current one\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:24'!\\ndeleteFileNamed: localFileName \\n\\t\\\"Delete the file with the given name in this directory.\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:45'!\\ndirectoryNamed: aString \\n\\t\\\"Return the subdirectory of this directory with the given name.\\\"\\n\\t^ self class server: self server directory: self directory , self slash, aString! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 21:30'!\\ndirectoryNames\\n\\t\\\"Return a collection of names for the subdirectories of this \\n\\tdirectory. \\\"\\n\\t^ self entries\\n\\t\\tselect: [:entry | entry isDirectory]\\n\\t\\tthenCollect: [:entry | entry name]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:40'!\\nentries\\n\\t\\\"Return a collection of directory entries for the files and \\n\\tdirectories in this directory.\\\"\\n\\t| lines |\\n\\tlines := self getLines.\\n\\t^ lines isNil\\n\\t\\tifTrue: [#()] ifFalse:[\\n\\t\\n\\tself parseLines: lines]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 21:30'!\\nfileNames\\n\\t\\\"Return a collection of names for the files (but not directories) in this directory.\\\"\\n\\t^ self entries\\n\\t\\tselect: [:entry | entry isDirectory not]\\n\\t\\tthenCollect: [:entry | entry name]! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:30'!\\nfullNameFor: aString \\n\\\"Return a corrected, fully-qualified name for the given file name.\\\"\\n\\t^ self urlFromServer: self server directories: self directories , {aString}! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/27/2003 12:36'!\\ngetOnly: numberOfBytes from: fileNameOnServer \\n\\t\\\"Just capture the first numberOfBytes of the file. \\n\\t \\n\\tGoes faster for long files. Return the contents, not a stream.\\\"\\n\\t| fileName |\\n\\tself flag: #todo.\\n\\t\\\"use LRUCache\\\"\\n\\tfileName := fileNameOnServer\\n\\t\\t\\t\\tallButFirst: (fileNameOnServer lastIndexOf: self pathNameDelimiter).\\n\\t\\\"\\\"\\n\\t^ self getOnly: numberOfBytes ofProjectContents: fileName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:33'!\\noldFileNamed: aName \\\"Open the existing file with the given name in this directory.\\\"\\n\\t^ self oldFileOrNoneNamed: aName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/27/2003 11:35'!\\noldFileOrNoneNamed: fullName \\n\\t\\\"If the file exists, answer a read-only FileStream on it. If it \\n\\tdoesn't, answer nil.\\\"\\n\\t| fileName contents |\\n\\tfileName := fullName\\n\\t\\t\\t\\tallButFirst: (fullName lastIndexOf: self pathNameDelimiter).\\n\\t\\\"\\\"\\n\\tcontents := self getFullProjectContents: fileName.\\n\\tcontents isNil\\n\\t\\tifTrue: [^ nil].\\n\\t\\\"\\\"\\n\\t^ (SwikiPseudoFileStream with: contents) directory: self;\\n\\t\\t localName: fileName;\\n\\t\\t reset;\\n\\t\\t yourself! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 07:58'!\\non: fullName \\n\\t\\\"Answer another ServerDirectory on the partial path name. \\n\\tfullName is directory path, and does include the name of the \\n\\tserver.\\\"\\n\\t^ self class fullPath: fullName!\\n]style[(4 8 3 133 4 4 17 8)f3b,f3cblue;b,f3,f3c146044000,f3,f3cmagenta;,f3,f3cblue;i! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:39'!\\npathName\\\"Path name as used in reading the file. \\\"\\n\\t^ self urlFromServer: self server directories: self directories! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 08:08'!\\npathParts\\n\\t\\\"Return the path from the root of the file system to this \\n\\tdirectory as an array of directory names. On a remote server.\\\"\\n\\t^ (OrderedCollection with: self server) addAll: self directories;\\n\\t\\t yourself! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:34'!\\nreadOnlyFileNamed: aName \\n\\\"Open the existing file with the given name in this directory for read-only access.\\\"\\n\\t^ self oldFileNamed: aName! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:26'!\\nrename: fullName toBe: newName \\n\\t\\\"Rename a remote file. fullName is just be a fileName, or can \\n\\tbe directory path that includes name of the server. newName \\n\\tis just a fileName\\\"\\n\\t^ self inform: 'operation not supported' translated! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:37'!\\nsleep\\\"Leave the FileList window. Do nothing. \\\"\\n\\t^ self! !\\n\\n!PRServerDirectory methodsFor: 'file directory' stamp: 'dgd 12/22/2003 20:32'!\\nwakeUp\\\"Entering a FileList window. Do nothing.\\\"\\n\\t^ self! !\\n\\n\\n!PRServerDirectory methodsFor: 'initialization' stamp: 'dgd 12/22/2003 20:46'!\\ninitializeServer: serverString directories: directoriesCollection \\n\\t\\\"initialize the receiver's server and directories\\\"\\n\\tserver := serverString withBlanksTrimmed.\\n\\tserver last = self pathNameDelimiter\\n\\t\\tifTrue: [server := server allButLast withBlanksTrimmed].\\n\\t\\\"\\\"\\n\\tdirectories := directoriesCollection! !\\n\\n\\n!PRServerDirectory methodsFor: 'path access' stamp: 'dgd 12/22/2003 20:41'!\\npathNameDelimiter\\\"Return the delimiter character for this kind of directory.\\\"\\n\\t^ $/! !\\n\\n!PRServerDirectory methodsFor: 'path access' stamp: 'dgd 12/22/2003 20:44'!\\nslash\\n\\\"answer the recevier 'slash'\\\"\\n\\t^ self pathNameDelimiter asString! !\\n\\n\\n!PRServerDirectory methodsFor: 'squeaklets' stamp: 'dgd 3/8/2006 17:38'!\\nwriteProject: aProject inFileNamed: fileNameString fromDirectory: localDirectory \\n\\t\\\"write aProject (a file version can be found in the file named \\n\\tfileNameString in localDirectory)\\\"\\n\\t| url arguments answer string |\\n\\turl := self urlFromServer: self server directories: {'programmatic'. 'uploadproject'}.\\n\\targuments := self\\n\\t\\t\\t\\tgetPostArgsFromProject: aProject\\n\\t\\t\\t\\tfileNamed: fileNameString\\n\\t\\t\\t\\tfromDirectory: localDirectory.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPClient httpPostDocument: url args: arguments.\\n\\t\\t\\t\\\"answer := HTTPSocket httpGetDocument: url args: arguments.\\\"\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"\\\"\\n\\tself\\n\\t\\tinform: ('Server responded: {1}' translated format: {string}).\\n\\t^ false! !\\n\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/22/2003 20:39'!\\nacceptsUploads\\n\\t\\\"answer whatever the receiver accepts uploads\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/22/2003 00:42'!\\nisProjectSwiki\\n\\t\\\"answer whatever the receiver is a project swiki\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/27/2003 11:04'!\\nisRemoteDirectory\\n\\t\\\"answer whatever the receiver is a remote directory\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 12/21/2003 23:31'!\\nisSearchable\\n\\t\\\"answer whatever the receiver is searchable\\\"\\n\\t^ true! !\\n\\n!PRServerDirectory methodsFor: 'testing' stamp: 'dgd 8/17/2004 22:14'!\\nqueryProjectsAndShow: thingsToSearchForCollection \\n\\t\\\"query the server for all the projects that match \\n\\tthingsToSearchForCollection\\\"\\n\\t| url arguments answer string |\\n\\turl := self urlFromServer: self server directories: {'programmatic'. 'queryprojects'}.\\n\\targuments := self getPostArgsFromThingsToSearchFor: thingsToSearchForCollection.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\t\\\"answer := HTTPClient httpPostDocument: url args: \\n\\t\\t\\targs.\\\"\\n\\t\\t\\tanswer := HTTPSocket httpGetDocument: url args: arguments.\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"\\\"\\n\\tself\\n\\t\\tinform: ('Server responded: {1}' translated format: {string}).\\n\\t^ false! !\\n\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/27/2003 11:34'!\\ngetFullProjectContents: aString \\n\\t\\\"private - get the project content from the server\\\"\\n\\t^ self getOnly: nil ofProjectContents: aString! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 8/17/2004 22:23'!\\ngetLines\\n\\t\\\"private - answer a collection of lines with the server response\\\"\\n\\t| url answer string lines |\\n\\turl := self urlFromServer: self server directories: {'programmatic'} , self directories.\\n\\turl := url , self slash.\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPClient httpGetDocument: url.\\n\\t\\t\\tstring := answer contents.\\n\\t\\t\\t(string beginsWith: '--OK--')\\n\\t\\t\\t\\tifFalse: [^ nil]].\\n\\t\\\"\\\"\\n\\tlines := OrderedCollection new.\\n\\t(string allButFirst: 6)\\n\\t\\tlinesDo: [:line | lines add: line squeakToIso].\\n\\t\\\"\\\"\\n\\t^ lines! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/27/2003 12:37'!\\ngetOnly: numberOfBytes ofProjectContents: aString \\n\\t\\\"private - get numberOfBytes of the project contents\\\"\\n\\t| url answer contents args |\\n\\tself flag: #todo.\\n\\t\\\"use an LRUCache\\\"\\n\\turl := self urlFromServer: self server directories: {'programmatic'. aString}.\\n\\t\\\"\\\"\\n\\targs := numberOfBytes isNil\\n\\t\\t\\t\\tifFalse: ['numberOfBytes=' , numberOfBytes asString].\\n\\t\\\"\\\"\\n\\tCursor read\\n\\t\\tshowWhile: [\\\"\\\"\\n\\t\\t\\tanswer := HTTPSocket httpGetDocument: url args: args.\\n\\t\\t\\tcontents := answer contents].\\\"\\\"\\n\\t(contents beginsWith: '--OK--')\\n\\t\\tifFalse: [^ nil].\\n\\t\\\"\\\"\\n\\t^ contents allButFirst: 6! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 4/3/2006 13:27'!\\ngetPostArgsFromProject: aProject fileNamed: fileNameString fromDirectory: localDirectory \\n\\t| args thumbnail uploader |\\n\\targs := Dictionary new.\\n\\n\\t\\\"args at: 'contents' put: {(localDirectory oldFileNamed: fileNameString) contentsOfEntireFile}.\\\"\\n\\targs at: 'contents' put: {(StandardFileStream\\n\\t\\t\\treadOnlyFileNamed: (localDirectory fullNameFor: fileNameString)) contentsOfEntireFile}.\\n\\n\\targs at: 'name' put: {aProject name isoToSqueak}.\\n\\targs at: 'version' put: {(Project parseProjectFileName: fileNameString) second asString}.\\n\\targs at: 'language' put: {aProject naturalLanguage asString}.\\n\\n\\tuploader := Utilities authorNamePerSe.\\n\\tuploader isEmptyOrNil\\n\\t\\tifTrue: [uploader := Utilities authorInitialsPerSe].\\n\\tuploader isEmptyOrNil\\n\\t\\tifFalse: [args at: 'uploader' put: {uploader}].\\n\\n\\tself putSmalltalkInfoInto: args.\\n\\n\\tthumbnail := self getProjectThumbnail: aProject.\\n\\tthumbnail isNil\\n\\t\\tifFalse: [args at: 'thumbnailcontents' put: {thumbnail}].\\n\\n\\tself putProjectDetailsFrom: aProject to: args.\\n\\n\\t^ args! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 8/17/2004 22:14'!\\ngetPostArgsFromThingsToSearchFor: thingsToSearchForCollection \\n\\t| args |\\n\\targs := Dictionary new.\\n\\t\\\"\\\"\\n\\tthingsToSearchForCollection\\n\\t\\tdo: [:each | \\n\\t\\t\\t| pos | \\n\\t\\t\\tpos := each indexOf: $:.\\n\\t\\t\\tpos isZero\\n\\t\\t\\t\\tifFalse: [| key value | \\n\\t\\t\\t\\t\\tkey := (each first: pos - 1) withBlanksTrimmed.\\n\\t\\t\\t\\t\\tvalue := (each allButFirst: pos) withBlanksTrimmed.\\n\\t\\t\\t\\t\\t(value beginsWith: '*')\\n\\t\\t\\t\\t\\t\\tifTrue: [value := value allButFirst].\\n\\t\\t\\t\\t\\t(value endsWith: '*')\\n\\t\\t\\t\\t\\t\\tifTrue: [value := value allButLast].\\n\\t\\t\\t\\t\\t\\\"\\\"\\n\\t\\t\\t\\t\\targs at: key put: {value}]].\\n\\t\\\"\\\"\\n\\t^ args! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/24/2003 11:33'!\\ngetProjectThumbnail: aProject \\n\\t\\\"private - answer a stream with the aProject's thumbnail or nil if none\\\"\\n\\t| form stream |\\n\\tform := aProject thumbnail.\\n\\tform isNil\\n\\t\\tifTrue: [^ nil].\\n\\t\\\"\\\"\\n\\tform unhibernate.\\n\\tform := form colorReduced.\\n\\t\\\"\\\"\\n\\tself flag: #todo.\\n\\t\\\"use a better image format than GIF\\\"\\n\\tstream := RWBinaryOrTextStream on: String new.\\n\\tGIFReadWriter putForm: form onStream: stream.\\n\\tstream reset.\\n\\t\\\"\\\"\\n\\t^ stream contents asString! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:34'!\\nparseLine: aString \\n\\\"private - parse a line from a server response\\\"\\n\\t| tokens |\\n\\ttokens := aString findTokens: '|'.\\n\\t\\\"\\\"\\n\\t^ tokens first = 'D'\\n\\t\\tifTrue: [\\\"\\\"\\n\\t\\t\\tDirectoryEntry\\n\\t\\t\\t\\tname: tokens second\\n\\t\\t\\t\\tcreationTime: 0\\n\\t\\t\\t\\tmodificationTime: 0\\n\\t\\t\\t\\tisDirectory: true\\n\\t\\t\\t\\tfileSize: 0]\\n\\t\\tifFalse: [\\\"\\\"\\n\\t\\t\\tDirectoryEntry\\n\\t\\t\\t\\tname: tokens second\\n\\t\\t\\t\\tcreationTime: tokens third asInteger\\n\\t\\t\\t\\tmodificationTime: tokens fourth asInteger\\n\\t\\t\\t\\tisDirectory: false\\n\\t\\t\\t\\tfileSize: tokens fifth asInteger]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:38'!\\nparseLines: aCollection \\n\\\"private - parse aCollection of lines from a server response\\\"\\n\\t^ aCollection\\n\\t\\tcollect: [:each | self parseLine: each]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 9/7/2004 12:16'!\\nputProjectDetailsFrom: aProject to: args \\n\\t| projectDetails |\\n\\tprojectDetails := aProject world\\n\\t\\t\\t\\tvalueOfProperty: #ProjectDetails\\n\\t\\t\\t\\tifAbsent: [^ self].\\n\\t\\\"\\\"\\n\\tself flag: #todo.\\n\\t\\\"projectname ?\\\"\\n\\tprojectDetails\\n\\t\\tat: 'projectdescription'\\n\\t\\tifPresent: [:value | args at: 'description' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectauthor'\\n\\t\\tifPresent: [:value | args at: 'author' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectcategory'\\n\\t\\tifPresent: [:value | args at: 'category' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectsubcategory'\\n\\t\\tifPresent: [:value | args at: 'subcategory' put: {value isoToSqueak}].\\n\\tprojectDetails\\n\\t\\tat: 'projectkeywords'\\n\\t\\tifPresent: [:value | args at: 'keywords' put: {value isoToSqueak}]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 9/7/2004 12:13'!\\nputSmalltalkInfoInto: args \\n\\t\\\"private - fills args with information from Smalltalk\\\"\\n\\tself flag: #todo.\\n\\t\\\" \\n\\tlastest small-land changeset / small-land version \\n\\t\\\"\\n\\t#(#datedVersion #osVersion #platformName #platformSubtype #vmPath #vmVersion #imageName #changesName #sourcesName #listBuiltinModules #listLoadedModules #getVMParameters )\\n\\t\\tdo: [:each | \\n\\t\\t\\t| value | \\n\\t\\t\\tvalue := SmalltalkImage current perform: each.\\n\\t\\t\\targs at: 'extra-' , each asString put: {value asString isoToSqueak}]! !\\n\\n!PRServerDirectory methodsFor: 'private' stamp: 'dgd 12/22/2003 20:47'!\\nurlFromServer: serverString directories: aCollection \\n\\t\\\"private - builds an url for server/directories\\\"\\n\\t| result |\\n\\tresult := String new writeStream.\\n\\t\\\"\\\"\\n\\t{serverString} , aCollection\\n\\t\\tdo: [:each | \\\"\\\"\\n\\t\\t\\tresult\\n\\t\\t\\t\\tnextPutAll: (each copyReplaceAll: ' ' with: '+')]\\n\\t\\tseparatedBy: [result nextPutAll: self slash].\\n\\t\\\"\\\"\\n\\t^ result contents! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPRServerDirectory class\\n\\tinstanceVariableNames: ''!\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 20:43'!\\nfullPath: fullNameString\\n\\t\\\"answer an instance of the receiver on fullName\\\"\\n\\t| pathParts |\\n\\tpathParts := self pathParts: fullNameString.\\n\\t^ self server: pathParts first directories: pathParts allButFirst! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 20:43'!\\npathParts: fullName \\n\\t\\\"private - parse fullName in server and directory\\\"\\n\\t| url slashPos server directory |\\n\\turl := fullName.\\n\\t(url beginsWith: 'http://')\\n\\t\\tifTrue: [url := url allButFirst: 7].\\n\\turl last = $/\\n\\t\\tifTrue: [url := url allButLast].\\n\\t\\\"\\\"\\n\\tslashPos := url indexOf: $/.\\n\\tslashPos isZero\\n\\t\\tifTrue: [^ {'http://' , url}].\\n\\t\\\"\\\"\\n\\tserver := url first: slashPos - 1.\\n\\tdirectory := url allButFirst: slashPos.\\n\\t\\\"\\\"\\n\\t^ {'http://' , server. directory}! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:57'!\\nserver: serverString \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self server: serverString directories: #()! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:56'!\\nserver: serverString directories: aCollection \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self new initializeServer: serverString directories: aCollection! !\\n\\n!PRServerDirectory class methodsFor: 'instance creation' stamp: 'dgd 12/22/2003 07:58'!\\nserver: serverString directory: directoryString \\n\\t\\\"answer a new instance of the receiver on server aString\\\"\\n\\t^ self new\\n\\t\\tinitializeServer: serverString\\n\\t\\tdirectories: (directoryString findTokens: '/')!\\n]style[(8 12 12 15 3 57 4 4 25 12 17 15 13 3 1)f3b,f3cblue;b,f3b,f3cblue;b,f3,f3c146044000,f3,f3cmagenta;,f3,f3cblue;i,f3,f3cblue;i,f3,f3c255146000b,f3! !\\nObject subclass: #PackageInfo\\n\\tinstanceVariableNames: 'packageName methodCategoryPrefix'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n!PackageInfo commentStamp: '<historical>' prior: 0!\\nSubclass this class to create new Packages.!\\n\\n\\n!PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 14:20'!\\nhash\\n\\t^ packageName hash! !\\n\\n!PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 00:09'!\\n= other\\n\\t^ other species = self species and: [other packageName = self packageName]! !\\n\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:16'!\\nexternalCallers\\n\\t^ self \\n\\t\\texternalRefsSelect: [:literal | literal isKindOf: Symbol] \\n\\t\\tthenCollect: [:l | l].! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalClasses\\n\\t| myClasses |\\n\\tmyClasses := self classesAndMetaClasses.\\n\\t^ Array streamContents:\\n\\t\\t[:s |\\n\\t\\tProtoObject withAllSubclassesDo:\\n\\t\\t\\t[:class |\\n\\t\\t\\t(myClasses includes: class) ifFalse: [s nextPut: class]]]! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalRefsSelect: selBlock thenCollect: colBlock\\n\\t| pkgMethods dependents refs extMethods otherClasses otherMethods classNames |\\n\\n\\tclassNames := self classes collect: [:c | c name].\\n\\textMethods := self extensionMethods collect: [:mr | mr methodSymbol].\\n\\totherClasses := self externalClasses difference: self externalSubclasses.\\n\\totherMethods := otherClasses gather: [:c | c selectors].\\n\\tpkgMethods := self methods asSet collect: [:mr | mr methodSymbol].\\n\\tpkgMethods removeAllFoundIn: otherMethods.\\n\\n\\tdependents := Set new.\\n\\totherClasses do: [:c |\\n\\t\\tc selectorsAndMethodsDo:\\n\\t\\t\\t[:sel :compiled |\\n\\t\\t\\t(extMethods includes: sel) ifFalse: \\n\\t\\t\\t\\t[refs := compiled literals select: selBlock thenCollect: colBlock.\\n\\t\\t\\t\\trefs do: [:ea |\\n\\t\\t\\t\\t\\t((classNames includes: ea) or: [pkgMethods includes: ea])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [dependents add: (self referenceForMethod: sel ofClass: c) -> ea]]]]].\\n\\t^ dependents! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nexternalSubclasses\\n\\t| pkgClasses subClasses |\\n\\tpkgClasses := self classes.\\n\\tsubClasses := Set new.\\n\\tpkgClasses do: [:c | subClasses addAll: (c allSubclasses)].\\n\\t^ subClasses difference: pkgClasses\\n! !\\n\\n!PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:15'!\\nexternalUsers\\n\\t^ self \\n\\t\\texternalRefsSelect: [:literal | literal isVariableBinding] \\n\\t\\tthenCollect: [:l | l key]! !\\n\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ac 5/14/2003 16:23'!\\nclasses\\n\\t^(self systemCategories gather:\\n\\t\\t[:cat |\\n\\t\\t(SystemOrganization listAtCategoryNamed: cat)\\n\\t\\t\\tcollect: [:className | Smalltalk at: className]])\\n\\t\\t\\t\\tsortBy: [:a :b | a className <= b className]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 12/14/2005 18:06'!\\nclassesAndMetaClasses\\n\\t| baseClasses |\\n\\tbaseClasses := self classes.\\n\\t^baseClasses , (baseClasses collect: [:c | c classSide])! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/13/2002 01:23'!\\ncoreMethods\\n\\t^ self classesAndMetaClasses gather: [:class | self coreMethodsForClass: class]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 3/1/2006 21:51'!\\nextensionClasses\\n\\t^ self externalBehaviors reject: [:classOrTrait | (self extensionCategoriesForClass: classOrTrait) isEmpty]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 3/1/2006 21:51'!\\nextensionMethods\\n\\t^ self externalBehaviors gather: [:classOrTrait | self extensionMethodsForClass: classOrTrait]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nforeignClasses\\n\\t| s |\\n\\ts := IdentitySet new.\\n\\tself foreignSystemCategories\\n\\t\\tdo: [:c | (SystemOrganization listAtCategoryNamed: c)\\n\\t\\t\\t\\tdo: [:cl | \\n\\t\\t\\t\\t\\t| cls | \\n\\t\\t\\t\\t\\tcls := Smalltalk at: cl. \\n\\t\\t\\t\\t\\ts add: cls;\\n\\t\\t\\t\\t\\t add: cls class]].\\n\\t^ s! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 12/3/2002 14:34'!\\nforeignSystemCategories\\n\\t^ SystemOrganization categories\\n\\t\\treject: [:cat | self includesSystemCategory: cat] ! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'al 10/9/2005 20:00'!\\nmethods\\n\\t^ (self extensionMethods, self coreMethods) select: [:method |\\n\\t\\tmethod isValid\\n\\t\\t\\tand: [method isLocalSelector]\\n\\t\\t\\tand: [method methodSymbol isDoIt not]]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'avi 11/10/2003 15:35'!\\noverrideMethods\\n\\t^ self extensionMethods select: [:ea | self isOvverideMethod: ea]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/14/2002 18:39'!\\nselectors\\n\\t^ self methods collect: [:ea | ea methodSymbol]! !\\n\\n!PackageInfo methodsFor: 'listing' stamp: 'ab 11/11/2002 21:51'!\\nsystemCategories\\n\\t^ SystemOrganization categories select: [:cat | self includesSystemCategory: cat]! !\\n\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\naddCoreMethod: aMethodReference\\n\\t| category |\\n\\tcategory := self baseCategoryOfMethod: aMethodReference.\\n\\taMethodReference actualClass organization\\n\\t\\tclassify: aMethodReference methodSymbol\\n\\t\\tunder: category\\n\\t\\tsuppressIfDefault: false! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\naddExtensionMethod: aMethodReference\\n\\t| category |\\n\\tcategory := self baseCategoryOfMethod: aMethodReference.\\n\\taMethodReference actualClass organization\\n\\t\\tclassify: aMethodReference methodSymbol\\n\\t\\tunder: self methodCategoryPrefix, '-', category! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:16'!\\naddMethod: aMethodReference\\n\\t(self includesClass: aMethodReference class)\\n\\t\\tifTrue: [self addCoreMethod: aMethodReference]\\n\\t\\tifFalse: [self addExtensionMethod: aMethodReference]! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nbaseCategoryOfMethod: aMethodReference\\n\\t| oldCat oldPrefix tokens | \\n\\toldCat := aMethodReference category.\\n\\t({ 'as yet unclassified'. 'all' } includes: oldCat) ifTrue: [ oldCat := '' ].\\n\\ttokens := oldCat findTokens: '*-' keep: '*'.\\n\\n\\t\\\"Strip off any old prefixes\\\"\\n\\t((tokens at: 1 ifAbsent: [ '' ]) = '*') ifTrue: [\\n\\t\\t[ ((tokens at: 1 ifAbsent: [ '' ]) = '*') ]\\n\\t\\t\\twhileTrue: [ tokens removeFirst ].\\n\\t\\toldPrefix := tokens removeFirst asLowercase.\\n\\t\\t[ (tokens at: 1 ifAbsent: [ '' ]) asLowercase = oldPrefix ]\\n\\t\\t\\twhileTrue: [ tokens removeFirst ].\\n\\t].\\n\\n\\ttokens isEmpty ifTrue: [^ 'as yet unclassified'].\\n\\t^ String streamContents:\\n\\t\\t[ :s |\\n\\t\\ttokens\\n\\t\\t\\tdo: [ :tok | s nextPutAll: tok ]\\n\\t\\t\\tseparatedBy: [ s nextPut: $- ]]! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'al 3/1/2006 21:42'!\\nexternalBehaviors\\n\\t^self externalClasses , self externalTraits! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'al 3/1/2006 22:08'!\\nexternalTraits\\n\\t| behaviors |\\n\\t\\n\\t^ Array streamContents: [:s |\\n\\t\\tbehaviors := self classesAndMetaClasses.\\n\\t\\tSmalltalk allTraits do: [:trait |\\n\\t\\t\\t(behaviors includes: trait) ifFalse: [s nextPut: trait].\\n\\t\\t\\t(behaviors includes: trait classSide) ifFalse: [s nextPut: trait classSide]]].\\t\\t\\t! !\\n\\n!PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:14'!\\nremoveMethod: aMethodReference! !\\n\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ncategoryName\\n\\t|category|\\n\\tcategory := self class category.\\n\\t^ (category endsWith: '-Info')\\n\\t\\tifTrue: [category copyUpToLast: $-]\\n\\t\\tifFalse: [category]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'ab 10/16/2002 21:22'!\\nexternalName\\n\\t^ self packageName! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\nmethodCategoryPrefix\\n\\t^ methodCategoryPrefix ifNil: [methodCategoryPrefix := '*', self packageName asLowercase]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\npackageName\\n\\t^ packageName ifNil: [packageName := self categoryName]! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'stephaneducasse 2/4/2006 20:40'!\\npackageName: aString\\n\\tpackageName := aString! !\\n\\n!PackageInfo methodsFor: 'naming' stamp: 'ab 10/28/2002 10:38'!\\nsystemCategoryPrefix\\n\\t^ self packageName! !\\n\\n\\n!PackageInfo methodsFor: 'registering' stamp: 'avi 11/12/2003 23:12'!\\nregister\\n\\tPackageOrganizer default registerPackage: self! !\\n\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 3/9/2004 15:53'!\\ncategory: categoryName matches: prefix\\n\\t^ categoryName notNil and: [categoryName = prefix or: [categoryName beginsWith: prefix, '-']]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:18'!\\ncoreCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | (self isForeignClassExtension: cat) not]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'!\\ncoreMethodsForClass: aClass\\n\\t^ (aClass selectors difference:\\n\\t\\t((self foreignExtensionMethodsForClass: aClass) collect: [:r | r methodSymbol]))\\n\\t\\t\\tasArray collect: [:sel | self referenceForMethod: sel ofClass: aClass]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:20'!\\nextensionCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | self isYourClassExtension: cat]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 4/6/2004 15:16'!\\nextensionMethodsForClass: aClass\\n\\t^ (self extensionCategoriesForClass: aClass)\\n\\t\\tgather: [:cat | ((aClass organization listAtCategoryNamed: cat) ifNil: [#()])\\n\\t\\t\\t\\t\\t\\t\\tcollect: [:sel | self referenceForMethod: sel ofClass: aClass]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'!\\nextensionMethodsFromClasses: classes\\n\\t^classes\\n\\t\\tgather: [:class | self extensionMethodsForClass: class]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'!\\nforeignExtensionCategoriesForClass: aClass\\n\\t^ aClass organization categories select: [:cat | self isForeignClassExtension: cat]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nforeignExtensionMethodsForClass: aClass\\n\\t^ (self foreignExtensionCategoriesForClass: aClass)\\n\\t\\tgather: [:cat | (aClass organization listAtCategoryNamed: cat)\\n\\t\\t\\t\\t\\t\\t collect: [:sel | self referenceForMethod: sel ofClass: aClass]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:08'!\\nincludesClassNamed: aClassName\\n\\t^ self includesSystemCategory: ((SystemOrganization categoryOfElement: aClassName) ifNil: [^false])! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nincludesClass: aClass\\n\\t^ self includesSystemCategory: aClass theNonMetaClass category! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:06'!\\nincludesMethodCategory: categoryName ofClassNamed: aClass\\n\\t^ (self isYourClassExtension: categoryName)\\n\\t\\tor: [(self includesClassNamed: aClass)\\n\\t\\t\\t\\tand: [(self isForeignClassExtension: categoryName) not]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 9/17/2002 00:18'!\\nincludesMethodCategory: categoryName ofClass: aClass\\n\\t^ (self isYourClassExtension: categoryName)\\n\\t\\tor: [(self includesClass: aClass)\\n\\t\\t\\t\\tand: [(self isForeignClassExtension: categoryName) not]]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/14/2002 18:06'!\\nincludesMethodReference: aMethodRef\\n\\t^ self includesMethod: aMethodRef methodSymbol ofClass: aMethodRef actualClass! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 12/5/2002 00:16'!\\nincludesMethod: aSymbol ofClass: aClass\\n\\taClass ifNil: [^ false].\\n\\t^ self\\n\\t\\tincludesMethodCategory: ((aClass organization categoryOfElement: aSymbol)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifNil: [' '])\\n\\t\\tofClass: aClass! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nincludesSystemCategory: categoryName\\n\\t^ self category: categoryName matches: self systemCategoryPrefix! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'!\\nisForeignClassExtension: categoryName\\n\\t^ categoryName first = $* and: [(self isYourClassExtension: categoryName) not]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 11/10/2003 15:42'!\\nisOverrideMethod: aMethodReference\\n\\t^ aMethodReference category endsWith: '-override'! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'avi 3/10/2004 12:37'!\\nisYourClassExtension: categoryName\\n\\t^ categoryName notNil and: [self category: categoryName asLowercase matches: self methodCategoryPrefix]! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'!\\noutsideClasses\\n\\t^ProtoObject withAllSubclasses difference: self classesAndMetaClasses! !\\n\\n!PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:25'!\\nreferenceForMethod: aSymbol ofClass: aClass\\n\\t^ MethodReference new setStandardClass: aClass methodSymbol: aSymbol! !\\n\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageInfo class\\n\\tinstanceVariableNames: ''!\\n\\n!PackageInfo class methodsFor: 'class initialization' stamp: 'avi 2/18/2004 00:46'!\\ninitialize\\n\\tself allSubclassesDo: [:ea | ea new register]! !\\n\\n\\n!PackageInfo class methodsFor: 'compatibility' stamp: 'avi 3/9/2004 16:28'!\\ndefault\\n\\t^ self allPackages detect: [:ea | ea class = self] ifNone: [self new register]! !\\n\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'nk 3/9/2004 10:49'!\\nallPackages\\n\\t^PackageOrganizer default packages! !\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'avi 11/12/2003 23:00'!\\nnamed: aString\\n\\t^ PackageOrganizer default packageNamed: aString ifAbsent: [(self new packageName: aString) register]! !\\n\\n!PackageInfo class methodsFor: 'packages access' stamp: 'avi 11/11/2003 17:19'!\\nregisterPackageName: aString\\n\\t^ PackageOrganizer default registerPackageNamed: aString! !\\nObject subclass: #PackageOrganizer\\n\\tinstanceVariableNames: 'packages'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n\\n!PackageOrganizer methodsFor: 'accessing' stamp: 'avi 11/12/2003 23:01'!\\npackageNames\\n\\t^ packages keys! !\\n\\n!PackageOrganizer methodsFor: 'accessing' stamp: 'avi 11/12/2003 23:01'!\\npackages\\n\\t^ packages values! !\\n\\n\\n!PackageOrganizer methodsFor: 'initializing' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ninitialize\\n\\tpackages := Dictionary new! !\\n\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 23:01'!\\nregisterPackage: aPackageInfo\\n\\tpackages at: aPackageInfo packageName put: aPackageInfo.\\n\\tself changed: #packages; changed: #packageNames.\\n! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 21:08'!\\nregisterPackageNamed: aString\\n\\t^ self registerPackage: (PackageInfo named: aString)! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 23:08'!\\nunregisterPackage: aPackageInfo\\n\\tpackages removeKey: aPackageInfo packageName ifAbsent: [].\\t\\n\\tself changed: #packages; changed: #packageNames.\\n! !\\n\\n!PackageOrganizer methodsFor: 'registering' stamp: 'avi 11/12/2003 21:10'!\\nunregisterPackageNamed: aString\\n\\tself unregisterPackage: (self packageNamed: aString ifAbsent: [^ self])! !\\n\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\nnoPackageFound\\n\\tself error: 'No package found'! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 11/12/2003 23:08'!\\npackageNamed: aString ifAbsent: errorBlock\\n\\t^ packages at: aString ifAbsent: errorBlock! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\npackageOfClass: aClass\\n\\t^ self packageOfClass: aClass ifNone: [self noPackageFound]! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:22'!\\npackageOfClass: aClass ifNone: errorBlock\\n\\t^ self packages detect: [:ea | ea includesClass: aClass] ifNone: errorBlock! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:21'!\\npackageOfMethod: aMethodReference\\n\\t^ self packageOfMethod: aMethodReference ifNone: [self noPackageFound]! !\\n\\n!PackageOrganizer methodsFor: 'searching' stamp: 'avi 10/11/2003 14:22'!\\npackageOfMethod: aMethodReference ifNone: errorBlock\\n\\t^ self packages detect: [:ea | ea includesMethodReference: aMethodReference] ifNone: errorBlock! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageOrganizer class\\n\\tinstanceVariableNames: 'default'!\\n\\n!PackageOrganizer class methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ndefault\\n\\t^ default ifNil: [default := self new]! !\\n\\n!PackageOrganizer class methodsFor: 'as yet unclassified' stamp: 'avi 10/13/2003 15:25'!\\nnew\\n\\t^ self basicNew initialize! !\\nBrowser subclass: #PackagePaneBrowser\\n\\tinstanceVariableNames: 'package packageListIndex packageList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Browser'!\\n!PackagePaneBrowser commentStamp: '<historical>' prior: 0!\\nA package browser represents a hierarchical query path through an organization of class and method information. It parses class categories into a two-level hierarchy on the first '-' character, giving \\\"packages\\\" (e.g., Magnitude, Collections, Graphics, etc.), and \\\"categories\\\" (e.g., Magnitude-General and Magnitude-Number).\\n\\nInstance Variables:\\n\\tpackage <Symbol> the \\\"category header,\\\" e.g., #Magnitudes or #Collections\\n\\tpackageListIndex <Integer> The index in the package list\\n\\tpackageList <OrderedCollection of String> the list of package names\\n!\\n\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:26'!\\nclassList\\n\\t\\\"Answer an array of the class names of the selected category. Answer an \\n\\tempty array if no selection exists.\\\"\\n\\n\\t^ self hasSystemCategorySelected \\n\\t\\tifFalse:\\n\\t\\t\\t[self packageClasses]\\n\\t\\tifTrue: [systemOrganizer listAtCategoryNumber:\\n\\t\\t\\t(systemOrganizer categories indexOf: self selectedSystemCategoryName asSymbol)]! !\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:36'!\\npackageClasses\\n\\t^ self categoryExistsForPackage\\n\\t\\tifFalse: [Array new]\\n\\t\\tifTrue:\\n\\t\\t\\t[systemOrganizer listAtCategoryNumber:\\n\\t\\t\\t\\t(systemOrganizer categories indexOf: self package asSymbol)]! !\\n\\n!PackagePaneBrowser methodsFor: 'class list' stamp: 'md 3/3/2006 11:04'!\\nselectedClass\\n\\t\\\"Answer the class that is currently selected. Answer nil if no selection \\n\\texists.\\\"\\n\\n\\t| name envt |\\n\\t(name := self selectedClassName) ifNil: [^ nil].\\n\\t\\\"(envt := self selectedEnvironment) ifNil: [^ nil].\\\"\\n\\tenvt:= Smalltalk.\\n\\t^ envt at: name! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'dragNDrop' stamp: 'sd 11/20/2005 21:27'!\\nchangeCategoryForClass: class srcSystemCategory: srcSystemCategorySel atListMorph: dstListMorph internal: internal copy: copyFlag \\n\\t\\\"only move semantic\\\"\\n\\t| newClassCategory success |\\n\\tself flag: #stringSymbolProblem.\\n\\tsuccess := copyFlag not ifFalse: [^ false].\\n\\tnewClassCategory := self dstCategoryDstListMorph: dstListMorph internal: internal.\\n\\t(success := newClassCategory notNil & (newClassCategory ~= class category))\\n\\t\\tifTrue: \\n\\t\\t\\t[class category: newClassCategory.\\n\\t\\t\\tself changed: #classList.\\n\\t\\t\\tinternal ifFalse: [self selectClass: class]].\\n\\t^ success! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'dragNDrop util' stamp: 'sd 11/20/2005 21:27'!\\ndstCategoryDstListMorph: dstListMorph internal: internal \\n\\t| dropItem |\\n\\t^ internal & (dstListMorph getListSelector == #systemCategoryList)\\n\\t\\tifTrue: [(dropItem := dstListMorph potentialDropItem) ifNotNil: [(self package , '-' , dropItem) asSymbol]]\\n\\t\\tifFalse: [self selectedSystemCategoryName]! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'sw 1/13/2000 16:45'!\\ndefaultBrowserTitle\\n\\t^ 'Package Browser'! !\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'sd 11/20/2005 21:27'!\\nopenAsMorphEditing: editString \\n\\t\\\"Create a pluggable version of all the views for a Browser, including \\n\\tviews and controllers.\\\"\\n\\t\\\"PackagePaneBrowser openBrowser\\\"\\n\\n\\t| listHeight window |\\n\\tlistHeight := 0.4.\\n\\t(window := SystemWindow labelled: 'later') model: self.\\n\\twindow\\n\\t\\taddMorph: (PluggableListMorph\\n\\t\\t\\t\\ton: self\\n\\t\\t\\t\\tlist: #packageList\\n\\t\\t\\t\\tselected: #packageListIndex\\n\\t\\t\\t\\tchangeSelected: #packageListIndex:\\n\\t\\t\\t\\tmenu: #packageMenu:\\n\\t\\t\\t\\tkeystroke: #packageListKey:from:)\\n\\t\\tframe: (0 @ 0 extent: 0.15 @ listHeight).\\n\\twindow\\n\\t\\taddMorph: self buildMorphicSystemCatList\\n\\t\\tframe: (0.15 @ 0 extent: 0.2 @ listHeight).\\n\\tself\\n\\t\\taddClassAndSwitchesTo: window\\n\\t\\tat: (0.35 @ 0 extent: 0.25 @ listHeight)\\n\\t\\tplus: 0.\\n\\twindow\\n\\t\\taddMorph: self buildMorphicMessageCatList\\n\\t\\tframe: (0.6 @ 0 extent: 0.15 @ listHeight).\\n\\twindow\\n\\t\\taddMorph: self buildMorphicMessageList\\n\\t\\tframe: (0.75 @ 0 extent: 0.25 @ listHeight).\\n\\tself\\n\\t\\taddLowerPanesTo: window\\n\\t\\tat: (0 @ listHeight corner: 1 @ 1)\\n\\t\\twith: editString.\\n\\twindow setUpdatablePanesFrom: #(#packageList #systemCategoryList #classList #messageCategoryList #messageList ).\\n\\t^ window! !\\n\\n!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'stp 10/06/1998 22:02'!\\nsystemOrganizer: aSystemOrganizer \\n\\t\\\"Initialize the receiver as a perspective on the system organizer, \\n\\taSystemOrganizer. Typically there is only one--the system variable \\n\\tSystemOrganization.\\\"\\n\\n\\tsuper systemOrganizer: aSystemOrganizer .\\n\\tpackageListIndex := 0! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:35'!\\ncategoryExistsForPackage\\n\\t^ self hasPackageSelected\\n\\t\\tand: [(systemOrganizer categories indexOf: self package asSymbol) ~= 0]\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:24'!\\nhasPackageSelected\\n\\n\\t^ packageListIndex ~= 0! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'sd 11/20/2005 21:27'!\\nopenEditString: aString\\n\\t\\\"Create a pluggable version of all the views for a Browser, including views and controllers.\\\"\\n\\t\\\"PackageBrowser openBrowser\\\"\\n\\n\\t| packageListView systemCategoryListView classListView messageCategoryListView\\n\\t messageListView browserCodeView topView switchView annotationPane underPane y optionalButtonsView |\\n\\n\\tself couldOpenInMorphic ifTrue: [^ self openAsMorphEditing: aString].\\n\\n\\ttopView := StandardSystemView new model: self.\\n\\ttopView borderWidth: 1. \\\"label and minSize taken care of by caller\\\"\\n\\n\\tpackageListView := PluggableListView on: self\\n\\t\\tlist: #packageList\\n\\t\\tselected: #packageListIndex\\n\\t\\tchangeSelected: #packageListIndex:\\n\\t\\tmenu: #packageMenu:.\\n\\tpackageListView window: (0 @ 0 extent: 20 @ 70).\\n\\ttopView addSubView: packageListView.\\n\\n\\tsystemCategoryListView := PluggableListView on: self\\n\\t\\tlist: #systemCategoryList\\n\\t\\tselected: #systemCategoryListIndex\\n\\t\\tchangeSelected: #systemCategoryListIndex:\\n\\t\\tmenu: #systemCategoryMenu:.\\n\\tsystemCategoryListView window: (20 @ 0 extent: 30 @ 70).\\n\\ttopView addSubView: systemCategoryListView.\\n\\n\\tclassListView := PluggableListView on: self\\n\\t\\tlist: #classList\\n\\t\\tselected: #classListIndex\\n\\t\\tchangeSelected: #classListIndex:\\n\\t\\tmenu: #classListMenu:shifted:.\\n\\tclassListView window: (0 @ 0 extent: 50 @ 62).\\n\\ttopView addSubView: classListView toRightOf: systemCategoryListView.\\n\\n\\tswitchView := self buildInstanceClassSwitchView.\\n\\tswitchView borderWidth: 1.\\n\\ttopView addSubView: switchView below: classListView.\\n\\n\\tmessageCategoryListView := PluggableListView on: self\\n\\t\\tlist: #messageCategoryList\\n\\t\\tselected: #messageCategoryListIndex\\n\\t\\tchangeSelected: #messageCategoryListIndex:\\n\\t\\tmenu: #messageCategoryMenu:.\\n\\tmessageCategoryListView window: (0 @ 0 extent: 50 @ 70).\\n\\ttopView addSubView: messageCategoryListView toRightOf: classListView.\\n\\n\\tmessageListView := PluggableListView on: self\\n\\t\\tlist: #messageList\\n\\t\\tselected: #messageListIndex\\n\\t\\tchangeSelected: #messageListIndex:\\n\\t\\tmenu: #messageListMenu:shifted:\\n\\t\\tkeystroke: #messageListKey:from:.\\n\\tmessageListView window: (0 @ 0 extent: 50 @ 70).\\n\\ttopView addSubView: messageListView toRightOf: messageCategoryListView.\\n\\n\\tself wantsAnnotationPane\\n\\t\\tifTrue:\\n\\t\\t\\t[annotationPane := PluggableTextView on: self\\n\\t\\t\\t\\ttext: #annotation accept: nil\\n\\t\\t\\t\\treadSelection: nil menu: nil.\\n\\t\\t\\tannotationPane window: (0@0 extent: 200@self optionalAnnotationHeight).\\n\\t\\t\\ttopView addSubView: annotationPane below: packageListView.\\n\\t\\t\\tunderPane := annotationPane.\\n\\t\\t\\ty := 110 - self optionalAnnotationHeight]\\n\\t\\tifFalse:\\n\\t\\t\\t[underPane := packageListView.\\n\\t\\t\\ty := 110].\\n\\n\\tself wantsOptionalButtons ifTrue:\\n\\t\\t[optionalButtonsView := self buildOptionalButtonsView.\\n\\t\\toptionalButtonsView borderWidth: 1.\\n\\t\\ttopView addSubView: optionalButtonsView below: underPane.\\n\\t\\tunderPane := optionalButtonsView.\\n\\t\\ty := y - self optionalButtonHeight].\\n\\n\\tbrowserCodeView := MvcTextEditor default on: self \\n\\t\\t\\ttext: #contents accept: #contents:notifying:\\n\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:.\\n\\tbrowserCodeView window: (0@0 extent: 200@y).\\n\\ttopView addSubView: browserCodeView below: underPane.\\n\\taString ifNotNil: [browserCodeView editString: aString.\\n\\t\\t\\tbrowserCodeView hasUnacceptedEdits: true].\\n\\t^ topView! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:25'!\\npackage\\n\\t\\\"Answer the receiver's 'package'.\\\"\\n\\n\\t^ self hasPackageSelected\\n\\t\\tifFalse: [nil]\\n\\t\\tifTrue: [self packageList at: packageListIndex]\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 20:36'!\\npackageList\\n\\t\\\"Answer a list of the packages in the current system organization.\\\"\\n\\n\\t| str cats stream |\\n\\tstr := Set new: 100.\\n\\tstream := WriteStream on: (Array new: 100).\\n\\tsystemOrganizer categories do:\\n\\t\\t[ :categ | \\n\\t\\tcats := categ asString copyUpTo: $-.\\n\\t\\t(str includes: cats) ifFalse: \\n\\t\\t\\t[str add: cats.\\n\\t\\t\\tstream nextPut: cats]].\\n\\t^stream contents! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 19:48'!\\npackageListIndex\\n\\t\\\"Answer the index of the current package selection.\\\"\\n\\n\\t^packageListIndex! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 12/01/1998 02:46'!\\npackageListIndex: anInteger \\n\\t\\\"Set anInteger to be the index of the current package selection.\\\"\\n\\n\\tpackageListIndex := anInteger.\\n\\tanInteger = 0\\n\\t\\tifFalse: [package := self packageList at: packageListIndex].\\n\\tmessageCategoryListIndex := 0.\\n\\tsystemCategoryListIndex := 0.\\n\\tmessageListIndex := 0.\\n\\tclassListIndex := 0.\\n\\tself setClassOrganizer.\\n\\tself changed: #packageSelectionChanged.\\n\\tself changed: #packageListIndex.\\t\\\"update my selection\\\"\\n\\tself changed: #systemCategoryList.\\t\\\"update the category list\\\"\\n\\tself systemCategoryListIndex: 0.\\t\\\"update category list selection\\\"\\n! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/06/1998 19:59'!\\npackageMenu: aMenu\\n\\t\\\"Answer a Menu of operations on class packages to be \\n\\tdisplayed when the operate menu button is pressed.\\\"\\n\\n\\t^aMenu\\n\\t\\t\\tlabels: 'find class...\\\\recent classes...\\\\reorganize\\\\update' withCRs\\n\\t\\t\\tlines: #(2)\\n\\t\\t\\tselections: #(#findClass #recent #editSystemCategories #updatePackages)! !\\n\\n!PackagePaneBrowser methodsFor: 'package list' stamp: 'nk 2/14/2004 15:09'!\\nupdatePackages\\n\\t\\\"Update the contents of the package list.\\\"\\n\\n\\tself editSelection: #none.\\n\\tself changed: #packageList.\\n\\tself changed: #package.\\n\\tself packageListIndex: 0 ! !\\n\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'JF 7/30/2003 12:23'!\\nhasSystemCategorySelected\\n\\t^ systemCategoryListIndex ~= 0! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'stp 01/13/2000 12:59'!\\nselectCategoryForClass: theClass\\n\\t\\\"Set the package and category lists to display the given class.\\\"\\n\\n\\t| cat |\\n\\tcat := theClass category.\\n\\tself packageListIndex: (self packageList indexOf: (cat copyUpTo: $-)).\\t\\n\\tself systemCategoryListIndex: (self systemCategoryList indexOf: \\n\\t\\t\\t(cat copyFrom: ((cat indexOf: $- ifAbsent: [0]) + 1) to: cat size)).! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/20/1999 20:16'!\\nselectedSystemCategoryName\\n\\t\\\"Answer the name of the selected system category or nil.\\\"\\n\\n\\tsystemCategoryListIndex = 0\\n\\t\\tifTrue: [^nil].\\n\\tpackageListIndex = 0\\n\\t\\tifTrue: [^ self systemCategoryList at: systemCategoryListIndex].\\n\\t^ self package , '-' , (self systemCategoryList at: systemCategoryListIndex)! !\\n\\n!PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/16/1999 16:14'!\\nsystemCategoryList\\n\\t\\\"Answer the sequenceable collection containing the class categories that \\n\\tthe receiver accesses.\\\"\\n\\n\\t| prefix |\\n\\tpackageListIndex = 0 ifTrue: [^ systemOrganizer categories].\\n\\tprefix := self package, '-'.\\n\\t^ Array streamContents:\\n\\t\\t[:strm |\\n\\t\\tsystemOrganizer categories do: \\n\\t\\t\\t[ :cat | (cat beginsWith: prefix) ifTrue:\\n\\t\\t\\t\\t[strm nextPut: (cat copyFrom: prefix size + 1 to: cat size)]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackagePaneBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!PackagePaneBrowser class methodsFor: 'class initialization' stamp: 'hpt 8/5/2004 20:12'!\\nregisterInAppRegistry\\n\\t\\\"Register the receiver in the SystemBrowser AppRegistry\\\"\\n\\tSystemBrowser register: self.! !\\n\\n\\n!PackagePaneBrowser class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nprototypicalToolWindow\\n\\t\\\"Answer an example of myself seen in a tool window, for the benefit of parts-launching tools\\\"\\n\\n\\t| aWindow |\\n\\taWindow := self new openAsMorphEditing: nil.\\n\\taWindow setLabel: 'Package Browser'.\\n\\taWindow applyModelExtent.\\n\\t^ aWindow\\n! !\\n\\n\\n!PackagePaneBrowser class methodsFor: 'window color' stamp: 'sw 2/26/2002 14:39'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name wording: 'Package Browser' brightColor: #(1.0 1.0 0.6)\\t pastelColor: #(0.976 0.976 0.835) helpMessage: 'A system browser with an extra pane at top-left for module.'! !\\n\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'hpt 8/5/2004 20:12'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry;\\n\\t\\tregisterInAppRegistry.! !\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/10/2003 13:15'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(PackagePaneBrowser\\tprototypicalToolWindow\\t\\t'Packages'\\t\\t\\t'Package Browser: like a System Browser, except that if has extra level of categorization in the top-left pane, such that class-categories are further organized into groups called \\\"packages\\\"') \\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Tools']! !\\n\\n!PackagePaneBrowser class methodsFor: '*MorphicExtras-class initialization' stamp: 'hpt 8/5/2004 20:12'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self].\\n\\tSystemBrowser unregister: self.! !\\nObject subclass: #PackageServices\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ServiceClasses'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'PackageInfo-Base'!\\n\\n!PackageServices methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 14:06'!\\nseeClassSide! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPackageServices class\\n\\tinstanceVariableNames: ''!\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 13:01'!\\nallServices\\n\\t^ ServiceClasses gather: [:ea | ea services]! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'stephaneducasse 2/4/2006 20:40'!\\ninitialize\\n\\tServiceClasses := Set new! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 12:59'!\\nregister: aClass\\n\\tServiceClasses add: aClass! !\\n\\n!PackageServices class methodsFor: 'as yet unclassified' stamp: 'avi 10/11/2003 12:59'!\\nunregister: aClass\\n\\tServiceClasses remove: aClass! !\\nImageMorph subclass: #PaintBoxColorPicker\\n\\tinstanceVariableNames: 'currentColor locOfCurrent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n!PaintBoxColorPicker commentStamp: 'JMM 9/13/2004 07:37' prior: 0!\\nA pop-up, 32-bit color palette used as part of a PaintBoxMorph.\\n!\\n\\n\\n!PaintBoxColorPicker methodsFor: 'accessing' stamp: 'jm 4/29/1998 20:07'!\\ncurrentColor\\n\\n\\t^ currentColor\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'accessing' stamp: 'jm 4/29/1998 20:18'!\\ncurrentColor: aColor\\n\\t\\\"Force me to select the given color.\\\"\\n\\n\\tcurrentColor _ aColor.\\n\\tlocOfCurrent _ nil. \\\"remove the marker\\\"\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'drawing' stamp: 'jm 4/29/1998 20:00'!\\ndrawOn: aCanvas\\n\\t\\\"Image plus circles for currently selected color.\\\"\\n\\n\\t| c |\\n\\tsuper drawOn: aCanvas.\\n\\tlocOfCurrent ifNotNil: [\\n\\t\\tc _ self ringColor.\\n\\t\\taCanvas\\n\\t\\t\\tfillOval: (Rectangle center: locOfCurrent + self topLeft extent: 9@9)\\n\\t\\t\\tcolor: Color transparent\\n\\t\\t\\tborderWidth: 1\\n\\t\\t\\tborderColor: c].\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'drawing' stamp: 'jm 4/29/1998 20:00'!\\nringColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\tcurrentColor isTransparent ifTrue: [^ Color red].\\n\\tcurrentColor red < 0.5 ifTrue: [^ Color red].\\n\\tcurrentColor red > (currentColor green + (currentColor blue * 0.5))\\n\\t\\tifTrue: [^ Color green]\\n\\t\\tifFalse: [^ Color red].\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'ar 10/5/2000 16:01'!\\nendColorSelection: evt\\n\\t\\\"Update current color and report it to paint box.\\\"\\n\\n\\tself selectColor: evt.\\n\\t\\\"restore mouseLeave handling\\\"\\n\\tself on: #mouseLeave send: #delete to: self.\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'ar 10/25/2000 17:49'!\\ninitMouseHandlers\\n\\n\\tself on: #mouseDown send: #startColorSelection: to: self.\\n\\tself on: #mouseMove send: #selectColor: to: self.\\n\\tself on: #mouseUp send: #endColorSelection: to: self.\\n\\tself on: #mouseLeave send: #delete to: self.\\n! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'JMM 9/13/2004 09:08'!\\nselectColor: evt \\n\\t\\\"Update the receiver from the given event. Constrain locOfCurrent's center to lie within the color selection area. If it is partially in the transparent area, snap it entirely into it vertically.\\\"\\n\\n\\t| r |\\n\\n\\tlocOfCurrent := evt cursorPoint - self topLeft.\\n\\tr := Rectangle center: locOfCurrent extent: 9 @ 9.\\n\\tlocOfCurrent := locOfCurrent \\n\\t\\t\\t\\t+ (r amountToTranslateWithin: (8 @ 11 corner: (self image width-6) @ (self image height-6))).\\n\\tlocOfCurrent x > (self image width-(12+7)) ifTrue: [locOfCurrent := (self image width - 12) @ locOfCurrent y].\\t\\\"snap into grayscale\\\"\\n\\tcurrentColor := locOfCurrent y < 19\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[locOfCurrent := locOfCurrent x @ 11.\\t\\\"snap into transparent\\\"\\n\\t\\t\\t\\t\\tColor transparent]\\n\\t\\t\\t\\tifFalse: [image colorAt: locOfCurrent].\\n\\t(owner isKindOf: PaintBoxMorph) \\n\\t\\tifTrue: [owner takeColorEvt: evt from: self].\\n\\tself changed! !\\n\\n!PaintBoxColorPicker methodsFor: 'event handling' stamp: 'jm 4/29/1998 21:21'!\\nstartColorSelection: evt\\n\\t\\\"Start color selection. Make me stay up as long as the mouse is down.\\\"\\n\\n\\tself on: #mouseLeave send: nil to: nil.\\n\\tself selectColor: evt.\\n! !\\n\\n\\n!PaintBoxColorPicker methodsFor: 'initialization' stamp: 'RAA 8/15/2000 14:57'!\\nbeStatic\\n\\n\\t\\\"an aid for Nebraska: make the color chart a static image to reduce traffic\\\"\\n\\timage isStatic ifFalse: [\\n\\t\\timage _ image as: StaticForm\\n\\t].! !\\n\\n!PaintBoxColorPicker methodsFor: 'initialization' stamp: 'jm 4/29/1998 21:24'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tcurrentColor _ Color black.\\n\\tlocOfCurrent _ nil.\\n\\tself initMouseHandlers.\\n! !\\nImageMorph subclass: #PaintBoxMorph\\n\\tinstanceVariableNames: 'action tool currentCursor thumbnail currentColor currentBrush colorMemory colorPatch stampHolder rotationTabForm scaleTabForm colorMemoryThin brushes focusMorph weakDependents recentColors'\\n\\tclassVariableNames: 'AllOffImage AllOnImage AllPressedImage ColorChart OriginalBounds Prototype RecentColors'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Support'!\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'laza 3/24/2000 17:58'!\\naction\\n\\t^ action\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:35'!\\nactionCursor\\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\t^self\\n\\t\\tcursorFor: action\\n\\t\\toldCursor: currentCursor\\n\\t\\tcurrentNib: self getNib\\n\\t\\tcolor: currentColor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\nbrush: brushButton action: aSelector nib: aMask evt: evt \\n\\t\\\"Set the current tool and action for the paintBox. \\\"\\n\\n\\tcurrentBrush \\n\\t\\tifNotNil: [currentBrush == brushButton ifFalse: [currentBrush state: #off]].\\n\\tcurrentBrush := brushButton.\\t\\\"A ThreePhaseButtonMorph\\\"\\n\\n\\t\\\"currentBrush state: #on.\\talready done\\\"\\n\\t\\\"aSelector is like brush3:. Don't save it. Can always say (currentBrush arguments at: 2)\\n\\taMask is the brush shape. Don't save it. Can always say (currentBrush arguments at: 3)\\\"\\n\\tself notifyWeakDependentsWith: { \\n\\t\\t\\t\\t#currentNib.\\n\\t\\t\\t\\tevt.\\n\\t\\t\\t\\tcurrentBrush arguments third}.\\n\\tself brushable ifFalse: [self setAction: #paint: evt: evt]\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 10/19/97 11:12'!\\nbrushable\\n\\t\\\"Return true if the current tool uses a brush.\\\"\\n\\t^ (#(\\\"non-brushable\\\" eyedropper: fill: pickup: stamp:) indexOf: action) = 0! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:34'!\\nclear: clearButton with: clearSelector evt: evt\\n\\n\\t| ss |\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss clearPainting: self]\\n\\t\\tifNil: [self notCurrentlyPainting].\\n\\tclearButton state: #off.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/15/97 13:35'!\\ncolorable\\n\\t\\\"Return true if the current tool uses a color.\\\"\\n\\t^ (#(\\\"These use no color\\\" erase: eyedropper: \\\"fill: does\\\" pickup: stamp:) indexOf: action) = 0! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/17/2000 17:06'!\\ncurrentColor: aColor evt: evt\\n\\t\\\"Accept a color from the outside. (my colorMemoryMorph must call takeColorEvt: evt from: colorPicker instead)\\\"\\n\\n\\tcurrentColor _ aColor.\\n\\tcolorMemory currentColor: aColor.\\n\\tself notifyWeakDependentsWith: {#currentColor. evt. currentColor}.\\n\\tself showColor.\\n\\tself colorable ifFalse: [self setAction: #paint: evt: evt].\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:37'!\\ncursorFor: anAction oldCursor: oldCursor currentNib: aNibForm color: aColor \\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the \\n\\tform must be set.\\\"\\n\\n\\t| ff width co larger c box |\\n\\n\\tanAction == #paint:\\n\\t\\tifTrue: [\\\"Make a cursor from the brush and the color\\\"\\n\\t\\t\\twidth _ aNibForm width.\\n\\t\\t\\tc _ self ringColorFor: aColor.\\n\\t\\t\\tco _ oldCursor offset - (width // 4 @ 34 - (width // 6)) min: 0 @ 0.\\n\\t\\t\\tlarger _ width negated + 10 @ 0 extent: oldCursor extent + (width @ width).\\n\\t\\t\\tff _ oldCursor copy: larger.\\n\\t\\t\\tff colors at: 1 put: Color transparent.\\n\\t\\t\\tff colors at: 2 put: Color transparent.\\n\\t\\t\\tff offset: co - (width @ width // 2).\\n\\t\\t\\tff getCanvas\\n\\t\\t\\t\\tfillOval: (Rectangle center: ff offset negated extent: width @ width)\\n\\t\\t\\t\\tcolor: Color transparent\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: c.\\n\\t\\t\\t^ ff].\\n\\tanAction == #erase:\\n\\t\\tifTrue: [\\\"Make a cursor from the cursor and the color\\\"\\n\\t\\t\\twidth _ aNibForm width.\\n\\t\\t\\tco _ oldCursor offset + (width // 2 @ 4) min: 0 @ 0.\\n\\t\\t\\tlarger _ 0 @ 0 extent: oldCursor extent + (width @ width).\\n\\t\\t\\tff _ oldCursor copy: larger.\\n\\t\\t\\tff offset: co - (width @ width // 2).\\n\\t\\t\\tff\\n\\t\\t\\t\\tfill: (box _ co negated extent: width @ width)\\n\\t\\t\\t\\tfillColor: (Color r: 0.5 g: 0.5 b: 1.0).\\n\\t\\t\\tff\\n\\t\\t\\t\\tfill: (box insetBy: 1 @ 1)\\n\\t\\t\\t\\tfillColor: Color transparent.\\n\\t\\t\\t^ ff].\\n\\t^ oldCursor! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\ndeleteCurrentStamp: evt \\n\\t\\\"The trash is telling us to delete the currently selected stamp\\\"\\n\\n\\t(tool arguments second) == #stamp: \\n\\t\\tifTrue: \\n\\t\\t\\t[stampHolder remove: tool.\\n\\t\\t\\tself setAction: #paint: evt: evt]\\t\\\"no use stamping with a blank stamp\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'JMM 9/13/2004 09:47'!\\neyedropper: aButton action: aSelector cursor: aCursor evt: evt \\n\\t\\\"Take total control and pick up a color!!!!\\\"\\n\\n\\t| pt feedbackColor delay |\\n\\tdelay _ Delay forMilliseconds: 10.\\n\\taButton state: #on.\\n\\ttool ifNotNil: [tool state: #off].\\n\\tcurrentCursor := aCursor.\\n\\tevt hand showTemporaryCursor: currentCursor\\n\\t\\thotSpotOffset: 6 negated @ 4 negated.\\n\\t\\\"<<<< the form was changed a bit??\\\"\\n\\tfeedbackColor := Display colorAt: Sensor cursorPoint.\\n\\tcolorMemory align: colorMemory bounds topRight\\n\\t\\twith: colorMemoryThin bounds topRight.\\n\\tself addMorphFront: colorMemory.\\n\\n\\t\\\"Full color picker\\\"\\n\\t[Sensor anyButtonPressed] whileFalse: \\n\\t\\t\\t[pt := Sensor cursorPoint.\\n\\t\\t\\t\\\"deal with the fact that 32 bit displays may have garbage in the \\n\\t\\t\\talpha bits\\\"\\n\\t\\t\\tfeedbackColor := Display depth = 32 \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[Color colorFromPixelValue: ((Display pixelValueAt: pt) bitOr: 4278190080)\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: 32]\\n\\t\\t\\t\\t\\t\\tifFalse: [Display colorAt: pt].\\n\\t\\t\\t\\\"the hand needs to be drawn\\\"\\n\\t\\t\\tevt hand position: pt.\\n\\t\\t\\tcurrentColor ~= feedbackColor ifTrue: [\\n\\t\\t\\t\\tcurrentColor _ feedbackColor.\\n\\t\\t\\t\\tself showColor ].\\n\\t\\t\\tself world displayWorldSafely.\\n\\t\\t\\tdelay wait].\\n\\n\\t\\\"Now wait for the button to be released.\\\"\\n\\t[Sensor anyButtonPressed] whileTrue:\\n\\t\\t[ pt := Sensor cursorPoint.\\n\\t\\t\\\"the hand needs to be drawn\\\"\\n\\t\\tevt hand position: pt.\\n\\t\\tself world displayWorldSafely.\\n\\t\\tdelay wait].\\n\\n\\tevt hand showTemporaryCursor: nil hotSpotOffset: 0 @ 0.\\n\\tself currentColor: feedbackColor evt: evt.\\n\\tcolorMemory delete.\\n\\ttool ifNotNil: \\n\\t\\t\\t[tool state: #on.\\n\\t\\t\\tcurrentCursor := tool arguments third].\\n\\taButton state: #off\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 12:52'!\\ngetColor\\n\\t^ currentColor! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:03'!\\ngetNib\\n\\t^currentBrush arguments third! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 13:02'!\\ngetSpecial\\n\\t^ action\\t\\t\\\"a selector like #paint:\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/21/2003 23:17'!\\ngrabFromScreen: evt \\n\\t\\\"Allow the user to grab a picture from the screen OUTSIDE THE PAINTING AREA and install it in a blank stamp. To get a stamp in the painting area, click on the stamp tool in a blank stamp.\\\"\\n\\n\\t\\\"scroll to blank stamp\\\"\\n\\n\\t| stampButton form |\\n\\tstampButton := stampHolder stampButtons first.\\n\\t[(stampHolder stampFormFor: stampButton) isNil] \\n\\t\\twhileFalse: [stampHolder scroll: 1].\\n\\tform := Form fromUser.\\n\\ttool state: #off.\\n\\ttool := stampHolder otherButtonFor: stampButton.\\n\\tstampHolder stampForm: form for: tool.\\t\\\"install it\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction: evt.\\n\\tevt hand showTemporaryCursor: (focusMorph getCursorFor: evt)! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'sw 8/29/2000 15:31'!\\nindicateColorUnderMouse\\n\\t\\\"Track the mouse with the special eyedropper cursor, and accept whatever color is under the mouse as the currently-chosen color; reflect that choice in the feedback box, and return that color.\\\"\\n\\n\\t| pt feedbackColor |\\n\\tpt _ Sensor cursorPoint.\\n\\t\\\"deal with the fact that 32 bit displays may have garbage in the alpha bits\\\"\\n\\tfeedbackColor _ Display depth = 32\\n\\t\\tifTrue: [ Color colorFromPixelValue: ((Display pixelValueAt: pt) bitOr: 16rFF000000) depth: 32] \\t\\tifFalse: [Display colorAt: pt].\\n\\n\\tself activeHand position: pt.\\n\\tself world displayWorldSafely.\\n\\tDisplay fill: colorPatch bounds fillColor: feedbackColor.\\n\\t^ feedbackColor\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:48'!\\nkeep: keepButton with: keepSelector evt: evt\\n\\t\\\"Showing of the corrent palette (viewer or noPalette) is done by the block submitted to the SketchMorphEditor, see (EToyHand makeNewDrawing) and (SketchMorph editDrawingInWorld:forBackground:).\\\"\\n\\t| ss |\\n\\towner ifNil: [^ self].\\n\\tkeepButton ifNotNil: [keepButton state: #off].\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss savePainting: self evt: evt]\\n\\t\\tifNil:\\n\\t\\t[keepSelector == #silent ifTrue: [^ self].\\n\\t\\tself notCurrentlyPainting].! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'sw 5/3/1998 18:22'!\\nnotCurrentlyPainting\\n\\tself inform: 'You are not currently painting'! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:04'!\\npickup: actionButton action: aSelector cursor: aCursor evt: evt \\n\\t\\\"Special version for pickup: and stamp:, because of these tests\\\"\\n\\n\\t| ss picker old map stamper |\\n\\tself \\n\\t\\ttool: actionButton\\n\\t\\taction: aSelector\\n\\t\\tcursor: aCursor\\n\\t\\tevt: evt.\\n\\taSelector == #stamp: \\n\\t\\tifTrue: \\n\\t\\t\\t[(stampHolder pickupButtons includes: actionButton) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[stamper := stampHolder otherButtonFor: actionButton.\\n\\t\\t\\t\\t\\t^self \\n\\t\\t\\t\\t\\t\\tpickup: stamper\\n\\t\\t\\t\\t\\t\\taction: #stamp:\\n\\t\\t\\t\\t\\t\\tcursor: (stamper arguments third)\\n\\t\\t\\t\\t\\t\\tevt: evt].\\n\\t\\t\\t(stampHolder stampFormFor: actionButton) ifNil: \\n\\t\\t\\t\\t\\t[\\\"If not stamp there, go to pickup mode\\\"\\n\\n\\t\\t\\t\\t\\tpicker := stampHolder otherButtonFor: actionButton.\\n\\t\\t\\t\\t\\tpicker state: #on.\\n\\t\\t\\t\\t\\t^self \\n\\t\\t\\t\\t\\t\\tpickup: picker\\n\\t\\t\\t\\t\\t\\taction: #pickup:\\n\\t\\t\\t\\t\\t\\tcursor: (picker arguments third)\\n\\t\\t\\t\\t\\t\\tevt: evt]\\n\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t[old := stampHolder stampFormFor: actionButton.\\n\\t\\t\\t\\t\\tcurrentCursor := ColorForm extent: old extent depth: 8.\\n\\t\\t\\t\\t\\told displayOn: currentCursor.\\n\\t\\t\\t\\t\\tmap := Color indexedColors copy.\\n\\t\\t\\t\\t\\tmap at: 1 put: Color transparent.\\n\\t\\t\\t\\t\\tcurrentCursor colors: map.\\n\\t\\t\\t\\t\\tcurrentCursor offset: currentCursor extent // -2.\\n\\t\\t\\t\\t\\t\\\"Emphisize the stamp button\\\"\\n\\t\\t\\t\\t\\tactionButton owner borderColor: (Color \\n\\t\\t\\t\\t\\t\\t\\t\\tr: 0.65\\n\\t\\t\\t\\t\\t\\t\\t\\tg: 0.599\\n\\t\\t\\t\\t\\t\\t\\t\\tb: 0.8)\\t\\\"layoutMorph\\\"\\t\\\"color: (Color r: 1.0 g: 0.645 b: 0.419);\\\"]].\\n\\taSelector == #pickup: \\n\\t\\tifTrue: \\n\\t\\t\\t[ss := self focusMorph.\\n\\t\\t\\tss ifNotNil: [currentCursor := aCursor]\\n\\t\\t\\t\\tifNil: \\n\\t\\t\\t\\t\\t[self notCurrentlyPainting.\\n\\t\\t\\t\\t\\tself setAction: #paint: evt: evt]]! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/2/97 22:13'!\\npickupForm: stampForm\\n\\t\\\"Install the new picture in this stamp\\\"\\n\\n\\t| stampButton |\\n\\tstampHolder stampForm: stampForm for: tool.\\n\\tstampButton _ action == #pickup: \\n\\t\\tifTrue: [stampHolder otherButtonFor: tool]\\n\\t\\tifFalse: [tool].\\t\\\"was a nil stampForm\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/17/2000 14:59'!\\npickupForm: stampForm evt: evt\\n\\t\\\"Install the new picture in this stamp\\\"\\n\\n\\t| stampButton |\\n\\tstampHolder stampForm: stampForm for: tool.\\n\\tstampButton _ action == #pickup: \\n\\t\\tifTrue: [stampHolder otherButtonFor: tool]\\n\\t\\tifFalse: [tool].\\t\\\"was a nil stampForm\\\"\\n\\tstampButton state: #on.\\n\\tstampButton doButtonAction: evt.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:40'!\\nplainCursor\\n\\t\\\"Return the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\t^currentCursor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 10/10/2000 16:38'!\\nplainCursor: aCursor event: anEvent\\n\\t\\\"Set the cursor to use with this painting action/tool. Offset of the form must be set.\\\"\\n\\n\\tcurrentCursor _ aCursor.\\n\\tanEvent hand showTemporaryCursor: aCursor.\\n\\tself notifyWeakDependentsWith: {#currentCursor. anEvent. currentCursor}.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:30'!\\nringColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\t^self ringColorFor: currentColor\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 13:29'!\\nringColorFor: aColor\\n\\t\\\"Choose a color that contrasts with my current color. If that color isn't redish, return red. Otherwise, return green\\\"\\n\\n\\taColor isTransparent ifTrue: [^ Color red].\\n\\taColor red < 0.5 ifTrue: [^ Color red].\\n\\taColor red > (aColor green + (aColor blue * 0.5))\\n\\t\\tifTrue: [^ Color green]\\n\\t\\tifFalse: [^ Color red].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:44'!\\nscrollStamps: actionButton action: aSelector evt: evt\\n\\t\\\"Move the stamps over\\\"\\n\\n\\taSelector == #prevStamp:\\n\\t\\tifTrue: [stampHolder scroll: -1]\\n\\t\\tifFalse: [stampHolder scroll: 1].\\n\\tactionButton state: #off.\\n\\taction == #stamp: ifTrue: [\\\"reselect the stamp and compute the cursor\\\"\\n\\t\\tself stampForm \\n\\t\\t\\tifNil: [self setAction: #paint: evt: evt]\\n\\t\\t\\tifNotNil: [tool doButtonAction: evt]].\\n\\t\\t! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/22/2000 11:57'!\\nsetAction: aSelector evt: evt\\n\\t\\\"Find this button and turn it on. Does not work for stamps or pickups\\\"\\n\\n\\t| button |\\n\\tbutton _ self submorphNamed: aSelector.\\n \\n\\tbutton ifNotNil: [\\n\\t\\tbutton state: #on.\\n\\t\\tbutton doButtonAction: evt].\\t\\\"select it!!\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'dgd 2/22/2003 19:04'!\\nshowColor\\n\\t\\\"Display the current color in all brushes, both on and off.\\\"\\n\\n\\t| offIndex onIndex center |\\n\\tcurrentColor ifNil: [^self].\\n\\t\\\"colorPatch color: currentColor.\\tMay delete later\\\"\\n\\t(brushes isNil or: [brushes first owner ~~ self]) \\n\\t\\tifTrue: \\n\\t\\t\\t[brushes := OrderedCollection new.\\n\\t\\t\\t#(#brush1: #brush2: #brush3: #brush4: #brush5: #brush6:) \\n\\t\\t\\t\\tdo: [:sel | brushes addLast: (self submorphNamed: sel)]].\\n\\tcenter := (brushes sixth) offImage extent // 2.\\n\\toffIndex := (brushes sixth) offImage pixelValueAt: center.\\n\\tonIndex := (brushes sixth) onImage pixelValueAt: center.\\n\\tbrushes do: \\n\\t\\t\\t[:bb | \\n\\t\\t\\tbb offImage colors at: offIndex + 1 put: currentColor.\\n\\t\\t\\tbb offImage clearColormapCache.\\n\\t\\t\\tbb onImage colors at: onIndex + 1 put: currentColor.\\n\\t\\t\\tbb onImage clearColormapCache.\\n\\t\\t\\tbb invalidRect: bb bounds].\\n\\tself invalidRect: (brushes first topLeft rect: brushes last bottomRight)! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 12/19/2000 19:16'!\\nshowColorPalette: evt\\n\\n\\t| w box |\\n\\tself comeToFront.\\n\\tcolorMemory align: colorMemory bounds topRight \\n\\t\\t\\twith: colorMemoryThin bounds topRight.\\n\\t\\\"make sure color memory fits or else align with left\\\"\\n\\tw _ self world.\\n\\tbox _ self bounds: colorMemory fullBounds in: w.\\n\\tbox left < 0 ifTrue:[\\n\\t\\tcolorMemory align: colorMemory bounds topLeft\\n\\t\\t\\twith: colorMemoryThin bounds topLeft].\\n\\tself addMorphFront: colorMemory.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/22/2000 11:58'!\\nstampCursorBeCursorFor: anAction\\n\\t\\\"User just chose a stamp. Take that stamp picture and make it be the cursor for the tool named.\\\"\\n\\t\\\"self stampCursorBeCursorFor: #star:.\\n\\tcurrentCursor offset: -9@-3.\\t\\t\\tHas side effect on the saved cursor.\\\"\\n\\n\\t(self submorphNamed: anAction) arguments at: 3 put: currentCursor.\\n\\t\\t\\\"Already converted to 8 bits and in the right form\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'di 5/6/1998 21:08'!\\nstampDeEmphasize\\n\\t\\\"Turn off an emphasized stamp. Was turned on in pickup:action:cursor:\\\"\\n\\n\\ttool owner class == AlignmentMorph ifTrue: [\\n\\t\\ttool \\\"actionButton\\\" owner \\\"layoutMorph\\\" color: Color transparent; \\n\\t\\t\\t\\t\\tborderColor: Color transparent].! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/2/97 14:02'!\\nstampForm\\n\\t\\\"Return the selected stamp\\\"\\n\\n\\t^ stampHolder stampFormFor: tool.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/17/97 11:47'!\\nstampHolder\\n\\n\\t^ stampHolder! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/17/97 11:48'!\\nstampHolder: newOne\\n\\n\\tstampHolder _ newOne! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 9/23/2000 20:00'!\\ntakeColor: aColor event: evt\\n\\t\\\"Accept the given color programmatically\\\"\\n\\tcurrentColor _ aColor.\\n\\tself notifyWeakDependentsWith: {#currentColor. evt. currentColor}.\\n\\tself showColor.\\n\\tself colorable ifFalse: [self setAction: #paint: evt: evt].\\t\\\"User now thinking of painting\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'ar 9/23/2000 20:39'!\\ntakeColorEvt: evt from: colorPicker\\n\\t\\\"Accept a new color from the colorMemory. Programs use currentColor: instead. Do not do this before the picker has a chance to set its own color!!\\\"\\n\\t^self takeColor: colorPicker currentColor event: evt! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/21/2000 16:06'!\\ntoggleShapes\\n\\t| tab sh stamps |\\n\\t\\\"The sub panel that has the shape tools on it. Rect, line...\\\"\\n\\tstamps _ self submorphNamed: 'stamps'.\\n\\ttab _ self submorphNamed: 'shapeTab'.\\n\\t(sh _ self submorphNamed: 'shapes') visible\\n\\t\\tifTrue: [sh hide. tab top: stamps bottom-1]\\n\\t\\tifFalse: [sh comeToFront. sh top: stamps bottom-9. \\n\\t\\t\\t\\tsh show. tab top: sh bottom - tab height + 10].\\n\\tself layoutChanged.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 8/21/2000 15:57'!\\ntoggleStamps\\n\\t| tab otherTab st shapes |\\n\\t\\\"The sub panel that has the stamps in it. For saving and moving parts of an image.\\\"\\n\\tshapes _ self submorphNamed: 'shapes'.\\n\\totherTab _ self submorphNamed: 'shapeTab'.\\n\\ttab _ self submorphNamed: 'stampTab'.\\n\\t(st _ self submorphNamed: 'stamps') visible\\n\\t\\tifTrue: [st hide. st bottom: self bottom. tab top: self bottom-1.\\n\\t\\t\\t\\tshapes top: self bottom-9.\\n\\t\\t\\t\\totherTab top: (shapes visible ifTrue: [shapes bottom - otherTab height + 10] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [self bottom-1])]\\n\\t\\tifFalse: [st top: self bottom-10. st show. tab top: st bottom-0.\\n\\t\\t\\t\\tshapes top: st bottom-9.\\n\\t\\t\\t\\totherTab top: (shapes visible ifTrue: [shapes bottom - otherTab height + 10] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [st bottom-0])].\\n\\tself layoutChanged.! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'tk 7/1/97 12:09'!\\ntool\\n\\t^ tool! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 12:38'!\\ntool: actionButton action: aSelector cursor: aCursor evt: evt\\n\\t\\\"Set the current tool and action for the paintBox. \\\"\\n\\n\\ttool ifNotNil: [\\n\\t\\ttool == actionButton ifFalse: [\\n\\t\\t\\ttool state: #off.\\n\\t\\t\\taction == #stamp: ifTrue: [self stampDeEmphasize]]].\\n\\ttool _ actionButton.\\t\\t\\\"A ThreePhaseButtonMorph\\\"\\n\\t\\\"tool state: #on.\\talready done\\\"\\n\\taction _ aSelector.\\t\\t\\\"paint:\\\"\\n\\tcurrentCursor _ aCursor.\\n\\tself notifyWeakDependentsWith: {#action. evt. action}.\\n\\tself notifyWeakDependentsWith: {#currentCursor. evt. currentCursor}.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 01:45'!\\ntoss: cancelButton with: cancelSelector evt: evt\\n\\t\\\"Reject the painting. Showing noPalette is done by the block submitted to the SketchEditorMorph\\\"\\n\\n\\t| focus |\\n\\towner ifNil: [\\\"it happens\\\" ^ self].\\n\\t(focus _ self focusMorph) \\n\\t\\tifNotNil: [focus cancelPainting: self evt: evt]\\n\\t\\tifNil:\\n\\t\\t\\t[self delete].\\n\\tcancelButton state: #off.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'actions' stamp: 'RAA 8/16/2000 11:15'!\\nundo: undoButton with: undoSelector evt: evt\\n\\t| ss |\\n\\t(ss _ self focusMorph) \\n\\t\\tifNotNil: [ss undoPainting: self evt: evt]\\n\\t\\tifNil: [self notCurrentlyPainting].\\n\\tundoButton state: #off.! !\\n\\n\\n!PaintBoxMorph methodsFor: 'copying' stamp: 'di 10/14/97 10:13'!\\nupdateReferencesUsing: aDictionary\\n\\t\\\"Fix up stampHolder which is a ScrollingToolHolder, which is not a Morph\\\"\\n\\n\\tsuper updateReferencesUsing: aDictionary.\\n\\tstampHolder updateReferencesUsing: aDictionary.\\n\\tcolorMemory updateReferencesUsing: aDictionary.! !\\n\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 16:47'!\\naddWeakDependent: anObject\\n\\n\\tweakDependents ifNil: [^weakDependents _ WeakArray with: anObject].\\n\\tweakDependents _ weakDependents,{anObject} reject: [ :each | each isNil].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/15/2000 14:59'!\\nbeStatic\\n\\n\\tcolorMemory ifNotNil: [colorMemory beStatic].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:53'!\\ncreateButtons\\n\\t\\\"Create buttons one at a time and let the user place them over the background. Later can move them again by turning on AuthorModeOwner in ThreePhaseButtonMorph.\\n\\tself createButtons.\\t\\\"\\n\\n\\t| rect button nib |\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: pickup: \\\"pickup: pickup: pickup:\\\" stamp: \\\"stamp: stamp: stamp:\\\" undo: keep: toss: prevStamp: nextStamp:) do: [:sel |\\n\\t\\t(self submorphNamed: sel) ifNil:\\n\\t\\t\\t[self inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ ThreePhaseButtonMorph new.\\n\\t\\t\\tbutton onImage: nil; bounds: rect.\\n\\t\\t\\tself addMorph: button.\\n\\t\\t\\tbutton actionSelector: #tool:action:cursor:evt:; arguments: (Array with: button with: sel with: nil).\\n\\t\\t\\tbutton actWhen: #buttonUp; target: self]].\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6: ) doWithIndex: [:sel :ind |\\n\\t\\t(self submorphNamed: sel) ifNil:\\n\\t\\t\\t[self inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ ThreePhaseButtonMorph new.\\n\\t\\t\\tbutton onImage: nil; bounds: rect.\\n\\t\\t\\tself addMorph: button.\\n\\t\\t\\tnib _ Form dotOfSize: (#(1 2 3 6 11 26) at: ind).\\n\\t\\t\\tbutton actionSelector: #brush:action:nib:evt:; \\n\\t\\t\\t\\t\\targuments: (Array with: button with: sel with: nib).\\n\\t\\t\\tbutton actWhen: #buttonUp; target: self]].\\n\\t\\\"stamp: Stamps are held in a ScrollingToolHolder. Pickups and stamps and brushes are id-ed by the button == with item from a list.\\\"\\n\\n\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 19:39'!\\nfixupButtons\\n\\t| changes answer newSelector |\\n\\tchanges := Dictionary new.\\n\\tchanges\\n\\t\\tat: #brush:action:nib: put: #brush:action:nib:evt:;\\n\\t\\tat: #tool:action:cursor: put: #tool:action:cursor:evt:;\\n\\t\\tat: #pickup:action:cursor: put: #pickup:action:cursor:evt:;\\n\\t\\tat: #keep:with: put: #keep:with:evt:;\\n\\t\\tat: #undo:with: put: #undo:with:evt:;\\n\\t\\tat: #scrollStamps:action: put: #scrollStamps:action:evt:;\\n\\t\\tat: #toss:with: put: #toss:with:evt:;\\n\\t\\tat: #eyedropper:action:cursor: put: #eyedropper:action:cursor:evt:;\\n\\t\\tat: #clear:with: put: #clear:with:evt:.\\n\\tanswer := WriteStream on: String new.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each isKindOf: ThreePhaseButtonMorph) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[answer nextPutAll: each actionSelector.\\n\\t\\t\\t\\t\\t(changes includesKey: each actionSelector) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[each actionSelector: (newSelector := changes at: each actionSelector).\\n\\t\\t\\t\\t\\t\\t\\tanswer nextPutAll: ' <-- ' , newSelector].\\n\\t\\t\\t\\t\\tanswer cr]].\\n\\t^answer contents\\n\\t\\\"StringHolder new\\n\\t\\tcontents: answer contents;\\n\\t\\topenLabel: 'button fixups'\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'dgd 2/22/2003 19:03'!\\ninit3\\n\\t\\\"Just a record of how we loaded in the latest paintbox button images\\\"\\n\\n\\t| bb rect lay pic16Bit aa blt on thin |\\n\\tself loadoffImage: 'etoy_default.gif'.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:button | \\n\\t\\t\\t(button isKindOf: ThreePhaseButtonMorph) \\n\\t\\t\\t\\tifTrue: [button offImage: nil]\\n\\t\\t\\t\\tifFalse: [button position: button position + (100 @ 0)]].\\n\\t(bb := self submorphNamed: #keep:) position: bb position + (100 @ 0).\\n\\t(bb := self submorphNamed: #toss:) position: bb position + (100 @ 0).\\n\\t(bb := self submorphNamed: #undo:) position: bb position + (100 @ 0).\\n\\t\\\"Transparent is (Color r: 1.0 g: 0 b: 1.0)\\\"\\n\\tself moveButtons.\\n\\tself loadOnImage: 'etoy_in.gif'.\\n\\tAllOnImage := nil.\\n\\t'save space'.\\n\\tself loadPressedImage: 'etoy_in.gif'.\\n\\tAllPressedImage := nil.\\n\\t'save space'.\\n\\tself loadCursors.\\n\\n\\t\\\"position the stamp buttons\\\"\\n\\tstampHolder stampButtons owner last delete.\\n\\tstampHolder pickupButtons last delete.\\n\\tstampHolder stampButtons: (stampHolder stampButtons copyFrom: 1 to: 3).\\n\\tstampHolder pickupButtons: (stampHolder pickupButtons copyFrom: 1 to: 3).\\n\\t\\\"| rect |\\\"\\n\\tstampHolder pickupButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\t\\\"PopUpMenu notify: 'Rectangle for ',sel.\\\"\\n\\n\\t\\t\\trect := Rectangle fromUser.\\n\\t\\t\\tbutton bounds: rect\\t\\\"image is nil\\\"].\\n\\t\\\"| rect lay |\\\"\\n\\tstampHolder clear.\\n\\tstampHolder stampButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\tbutton\\n\\t\\t\\t\\toffImage: nil;\\n\\t\\t\\t\\tpressedImage: nil.\\n\\t\\t\\tlay := button owner.\\n\\t\\t\\t\\\"PopUpMenu notify: 'Rectangle for ',sel.\\\"\\n\\t\\t\\trect := Rectangle fromUser.\\n\\t\\t\\tbutton image: (Form fromDisplay: (rect insetBy: 2)).\\n\\t\\t\\tlay borderWidth: 2.\\n\\t\\t\\tlay bounds: rect\\t\\\"image is nil\\\"].\\n\\t\\\"| pic16Bit blt aa on |\\\"\\n\\tpic16Bit := GIFReadWriter formFromFileNamed: 'etoy_in.gif'.\\t\\\"really 8\\\"\\n\\taa := Form extent: OriginalBounds extent depth: 8.\\n\\tblt := BitBlt current toForm: aa.\\n\\tblt\\n\\t\\tsourceForm: pic16Bit;\\n\\t\\tcombinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds;\\n\\t\\tdestOrigin: 0 @ 0;\\n\\t\\tcopyBits.\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tstampHolder pickupButtons do: \\n\\t\\t\\t[:button | \\n\\t\\t\\ton := ColorForm extent: button extent depth: 8.\\n\\t\\t\\ton colors: pic16Bit colors.\\n\\t\\t\\ton \\n\\t\\t\\t\\tcopy: (0 @ 0 extent: button extent)\\n\\t\\t\\t\\tfrom: button topLeft - self topLeft\\n\\t\\t\\t\\tin: aa\\n\\t\\t\\t\\trule: Form over.\\n\\t\\t\\tbutton\\n\\t\\t\\t\\timage: on;\\n\\t\\t\\t\\tpressedImage: on;\\n\\t\\t\\t\\toffImage: nil].\\n\\tself invalidRect: bounds.\\n\\t((self submorphNamed: #erase:) arguments third) offset: 12 @ 35.\\n\\t((self submorphNamed: #eyedropper:) arguments third) offset: 0 @ 0.\\n\\t((self submorphNamed: #fill:) arguments third) offset: 10 @ 44.\\n\\t((self submorphNamed: #paint:) arguments third) offset: 3 @ 3.\\t\\\"unused\\\"\\n\\t((self submorphNamed: #rect:) arguments third) offset: 6 @ 17.\\n\\t((self submorphNamed: #ellipse:) arguments third) offset: 5 @ 4.\\n\\t((self submorphNamed: #polygon:) arguments third) offset: 5 @ 4.\\n\\t((self submorphNamed: #line:) arguments third) offset: 5 @ 17.\\n\\t((self submorphNamed: #star:) arguments third) offset: 2 @ 5.\\n\\tthumbnail delete.\\n\\tthumbnail := nil.\\n\\t(submorphs select: [:e | e class == RectangleMorph]) first \\n\\t\\tbounds: Rectangle fromUser.\\n\\t((submorphs select: [:e | e class == RectangleMorph]) first)\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: Color black.\\n\\t\\\"| thin |\\\"\\n\\tsubmorphs do: [:ss | ss class == ImageMorph ifTrue: [thin := ss\\t\\\"first\\\"]].\\n\\tcolorMemoryThin := thin! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 8/22/2000 11:56'!\\ninit4\\n\\t\\\"Just a record of how Ted loaded in the paintbox button images, Feb 98\\\"\\n| bb im pp newImage pic24Bit picNewBit blt |\\n\\n\\\"self loadoffImage: 'roundedPalette3.bmp'.\\\"\\npic24Bit _ GIFReadWriter formFromServerFile: 'updates/137roundedPalette3.bmp'.\\npicNewBit _ Form extent: pic24Bit extent depth: 16.\\npic24Bit displayOn: picNewBit.\\nOriginalBounds _ picNewBit boundingBox.\\nAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\nblt _ BitBlt current toForm: AllOffImage.\\nblt sourceForm: picNewBit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\nAllOffImage mapColor: Color transparent to: Color black.\\nself image: AllOffImage.\\nself invalidRect: bounds.\\n\\nself submorphsDo: [:button | button position: button position + (10@10)].\\n(im _ submorphs at: 28) class == ImageMorph ifTrue: [\\n\\tim position: im position + (2@0)].\\t\\\"color picker\\\"\\n\\\"exercise it once\\\"\\n\\n(bb _ self submorphNamed: #keep:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #toss:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #undo:) position: bb position + (0@-25).\\n(bb _ self submorphNamed: #clear:) position: bb position + (0@-25).\\n(bb _ self submorphNamed: #undo:) position: bb position + (0@-69).\\n(bb _ self submorphNamed: #clear:) position: bb position + (0@-69).\\nself submorphsDo: [:button | \\n\\tbutton class == AlignmentMorph ifTrue: [\\n\\t\\tbutton position: button position + (0@25)].\\n\\t(button printString includesSubString: 'stamp:') ifTrue: [\\n\\t\\tbutton position: button position + (0@25)]].\\n(bb _ self submorphNamed: #prevStamp:) position: bb position + (0@25).\\n(bb _ self submorphNamed: #nextStamp:) position: bb position + (0@25).\\n\\nbb _ self submorphNamed: #keep:.\\nnewImage _ bb pressedImage copy: (0@4 corner: (bb pressedImage boundingBox extent)).\\nbb onImage: newImage. bb pressedImage: newImage. bb extent: newImage extent.\\nbb position: bb position + (4@1).\\n\\npp _ (bb _ self submorphNamed: #toss:) pressedImage.\\nnewImage _ pp copy: (0@4 corner: (bb pressedImage extent - (3@0))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@1).\\n\\npp _ (bb _ self submorphNamed: #undo:) pressedImage.\\nnewImage _ pp copy: (0@0 corner: (bb pressedImage extent - (3@5))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@-1).\\n\\npp _ (bb _ self submorphNamed: #clear:) pressedImage.\\nnewImage _ pp copy: (0@0 corner: (bb pressedImage extent - (0@5))).\\nbb onImage: newImage. bb pressedImage: newImage. \\nbb extent: newImage extent.\\nbb position: bb position + (3@-1).\\n\\npic24Bit _ GIFReadWriter formFromServerFile: 'updates/137pencil.bmp'.\\npicNewBit _ Form extent: pic24Bit extent depth: 16.\\npic24Bit displayOn: picNewBit.\\nnewImage _ picNewBit as8BitColorForm.\\nnewImage transparentColor: (Color r: 0 g: 0 b: 0).\\n(bb _ self submorphNamed: #erase:) pressedImage: newImage; onImage: newImage;\\n\\textent: newImage extent.\\n\\nbb position: bb position + (-11@-1).\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 7/28/2000 23:26'!\\ninitialize\\n\\tsuper initialize.\\n\\tcolorMemory ifNotNil: [colorMemory on: #mouseDown send: #takeColorEvt:from: to: self].! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'jm 6/18/1999 18:58'!\\nloadColorChooser\\n\\t\\\"Load Forms for ColorMemoryMorph.\\\"\\n\\n\\t| doc closedForm openForm |\\n\\tdoc _ Utilities objectStrmFromUpdates: 'colorPalClosed.obj'.\\n\\tclosedForm _ doc fileInObjectAndCode mapColor: Color transparent to: Color black.\\n\\tdoc _ Utilities objectStrmFromUpdates: 'colorPalOpen.obj'.\\n\\topenForm _ doc fileInObjectAndCode mapColor: Color transparent to: Color black.\\n\\n\\tcolorMemoryThin image: closedForm.\\n\\tcolorMemoryThin position: self position + (0@140).\\n\\n\\tcolorMemory delete.\\t\\\"delete old one\\\"\\n\\tcolorMemory _ PaintBoxColorPicker new image: openForm.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:54'!\\nloadCursors\\n\\t\\\"Display the form containing the cursors. Transparent is (Color r: 1.0 g: 0 b: 1.0). Grab the forms one at a time, and they are stored away.\\n\\tself loadCursors.\\t\\\"\\n\\n\\t| button transp cursor map |\\n\\ttransp _ Color r: 1.0 g: 0 b: 1.0.\\n\\tmap _ Color indexedColors copy.\\t\\\"just in case\\\"\\n\\t1 to: 256 do: [:ind | (map at: ind) = transp ifTrue: \\n\\t\\t\\t\\t[map at: ind put: Color transparent]].\\n\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: ) do: [:sel |\\n\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\tcursor _ ColorForm fromUser.\\n\\t\\tcursor colors: map.\\t\\\"share it\\\"\\n\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\tbutton arguments at: 3 put: cursor].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 1/13/2005 12:20'!\\nloadJapanesePaintBoxBitmaps\\n\\\"\\n\\tPaintBoxMorph new loadJapanesePaintBoxBitmaps.\\n\\\"\\n\\n\\t| formTranslator form bb |\\n\\tself position: 0@0.\\n\\tformTranslator _ NaturalLanguageFormTranslator localeID: (LocaleID isoString: 'ja').\\n\\tform _ Form fromFileNamed: 'offPaletteJapanese(children).form'.\\n\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\tbb _ (self submorphs detect: [:e | e externalName = extName]) bounds.\\n\\t\\tformTranslator name: label, '-off' form: (form copy: bb)\\n\\t].\\n\\n\\n\\tform _ Form fromFileNamed: 'pressedPaletteJapanese(children).form'.\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\tbb _ (self submorphs detect: [:e | e externalName = extName]) bounds.\\n\\t\\tformTranslator name: label, '-pressed' form: (form copy: bb)\\n\\t].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 11/4/2002 21:20'!\\nloadOffForm: pic16Bit \\n\\t\\\"Prototype loadOffForm: (Smalltalk imageImports at: #offPaletteJapanese)\\\"\\n\\n\\t| blt |\\n\\tOriginalBounds _ pic16Bit boundingBox.\\n\\tAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: AllOffImage.\\n\\tblt sourceForm: pic16Bit;\\n\\t\\t combinationRule: Form over;\\n\\t\\t sourceRect: OriginalBounds;\\n\\t\\t destOrigin: 0 @ 0;\\n\\t\\t copyBits.\\n\\tAllOffImage mapColor: Color blue to: Color transparent.\\n\\tself image: AllOffImage.\\n\\tAllOffImage _ nil.\\n\\tself invalidRect: bounds\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'ar 5/28/2000 12:10'!\\nloadOnImage: fileName\\n\\t\\\"Read in and convert the image for the paintBox with the buttons\\non. A .bmp 24-bit image. For each button, cut that chunk out and save it.\\\"\\n\\t\\\"\\tself loadOnImage: 'NoSh_on.bmp'.\\n\\t\\tAllOnImage _ nil.\\t'save space'.\\t\\\"\\n\\n\\t| pic16Bit blt aa on type |\\n\\ttype _ 'gif'. \\\" gif or bmp \\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tpic16Bit display.\\n\\taa _ AllOnImage _ Form extent: OriginalBounds extent depth: 8.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\t].\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tpic16Bit display.\\n\\taa _ AllOnImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\taa mapColor: Color transparent to: Color black.\\n\\t].\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ttype = 'gif' ifTrue: [on _ ColorForm extent: button extent depth: 8.\\n\\t\\t\\t\\t\\t on colors: pic16Bit colors]\\n\\t\\t\\t\\tifFalse: [on _ Form extent: button extent depth: 16].\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in: aa rule: Form over.\\n\\t\\t\\tbutton onImage: on]].\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'yo 11/4/2002 21:20'!\\nloadPressedForm: pic16Bit \\n\\t\\\"Prototype loadPressedForm: (Smalltalk imageImports at: #pressedPaletteJapanese)\\\"\\n\\n\\t| blt on |\\n\\tAllPressedImage _ AllPressedImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: AllPressedImage.\\n\\tblt sourceForm: pic16Bit;\\n\\t\\t combinationRule: Form over;\\n\\t\\t sourceRect: OriginalBounds;\\n\\t\\t destOrigin: 0 @ 0;\\n\\t\\t copyBits.\\n\\tAllPressedImage mapColor: Color black to: Color transparent.\\n\\tself\\n\\t\\tallMorphsDo: [:button | (button isKindOf: ThreePhaseButtonMorph)\\n\\t\\t\\t\\tifTrue: [on _ Form extent: button extent depth: 16.\\n\\t\\t\\t\\t\\ton\\n\\t\\t\\t\\t\\t\\tcopy: (0 @ 0 extent: button extent)\\n\\t\\t\\t\\t\\t\\tfrom: button topLeft - self topLeft\\n\\t\\t\\t\\t\\t\\tin: AllPressedImage\\n\\t\\t\\t\\t\\t\\trule: Form over.\\n\\t\\t\\t\\t\\tbutton pressedImage: on]].\\n\\tAllPressedImage _ nil.\\n\\tself invalidRect: bounds\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'ar 5/28/2000 12:10'!\\nloadPressedImage: fileName\\n\\t\\\"Read in and convert the image for the paintBox with the buttons\\non. A .bmp 24-bit image. For each button, cut that chunk out and save it.\\\"\\n\\t\\\"\\tself loadPressedImage: 'NoSh_on.bmp'.\\n\\t\\tAllPressedImage _ nil.\\t'save space'.\\t\\\"\\n\\n\\t| pic16Bit blt aa on type |\\n\\ttype _ 'gif'. \\\" gif or bmp \\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tpic16Bit display.\\n\\taa _ AllPressedImage _ Form extent: OriginalBounds extent depth: 8.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\t].\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tpic16Bit display.\\n\\taa _ AllPressedImage _ Form extent: OriginalBounds extent depth: 16.\\n\\tblt _ BitBlt current toForm: aa.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\taa mapColor: Color transparent to: Color black.\\n\\t].\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ttype = 'gif' ifTrue: [on _ ColorForm extent: button extent depth: 8.\\n\\t\\t\\t\\t\\t on colors: pic16Bit colors]\\n\\t\\t\\t\\tifFalse: [on _ Form extent: button extent depth: 16].\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in: aa rule: Form over.\\n\\t\\t\\tbutton pressedImage: on]].\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'md 11/14/2003 16:52'!\\nloadoffImage: fileName\\n\\t\\\"Read in and convert the background image for the paintBox. All\\nbuttons off. A .bmp 24-bit image.\\\"\\n\\t\\\"\\tPrototype loadoffImage: 'roundedPalette3.bmp'\\t\\\"\\n\\n\\t| pic16Bit blt type getBounds |\\n\\ttype _ 'bmp'. \\\" gif or bmp \\\"\\n\\tgetBounds _ 'fromPic'.\\t\\\"fromUser = draw out rect of paintbox on image\\\"\\n\\t\\t\\\"fromOB = just read in new bits, keep same size and place as last time.\\\"\\n\\t\\t\\\"fromPic = picture is just the PaintBox, use its bounds\\\"\\ntype = 'gif' ifTrue: [\\n\\tpic16Bit \\\"really 8\\\" _ GIFReadWriter formFromFileNamed: fileName.\\n\\tgetBounds = 'fromUser' ifTrue: [\\\"Just first time, collect the bounds\\\"\\n\\t\\t\\tpic16Bit display.\\n\\t\\t\\tOriginalBounds _ Rectangle fromUser].\\n\\tgetBounds = 'fromPic' ifTrue: [OriginalBounds _ pic16Bit boundingBox].\\n\\t].\\n\\t\\t\\\"Use OriginalBounds as it was last time\\\"\\ntype = 'bmp' ifTrue: [\\n\\tpic16Bit _ (Form fromBMPFileNamed: fileName) asFormOfDepth: 16.\\n\\tgetBounds = 'fromUser' ifTrue: [\\\"Just first time, collect the bounds\\\"\\n\\t\\t\\tpic16Bit display.\\n\\t\\t\\tOriginalBounds _ Rectangle fromUser].\\n\\t\\t\\\"Use OriginalBounds as it was last time\\\"\\n\\t(getBounds = 'fromPic') ifTrue: [OriginalBounds _ pic16Bit boundingBox].\\n\\tAllOffImage _ Form extent: OriginalBounds extent depth: 16.\\n\\t].\\n\\ntype = 'gif' ifTrue: [\\n\\tAllOffImage _ ColorForm extent: OriginalBounds extent depth: 8.\\n\\tAllOffImage colors: pic16Bit colors].\\n\\n\\tblt _ BitBlt current toForm: AllOffImage.\\n\\tblt sourceForm: pic16Bit; combinationRule: Form over;\\n\\t\\tsourceRect: OriginalBounds; destOrigin: 0@0; copyBits.\\n\\ntype = 'bmp' ifTrue: [AllOffImage mapColor: Color transparent to: Color black].\\n\\tself image: AllOffImage.\\n\\tself invalidRect: bounds.\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'sw 5/23/2001 13:54'!\\nmoveButtons\\n\\t\\\"Move buttons one at a time and let the user place them over the background. Later can move them again by turning on AuthorModeOwner in ThreePhaseButtonMorph.\\n\\tself createButtons.\\t\\\"\\n\\n\\t| rect button |\\n\\t#(erase: eyedropper: fill: paint: rect: ellipse: polygon: line: star: \\\"pickup: pickup: pickup: pickup:\\\" \\\"stamp: stamp: stamp: stamp:\\\" undo: keep: toss: prevStamp: nextStamp:) do: [:sel |\\n\\t\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\t\\tbutton bounds: rect.\\t\\\"image is nil\\\"].\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6: ) doWithIndex: [:sel :ind |\\n\\t\\t\\tself inform: 'Rectangle for ',sel.\\n\\t\\t\\trect _ Rectangle fromUser.\\n\\t\\t\\tbutton _ self submorphNamed: sel.\\n\\t\\t\\tbutton bounds: rect.\\t\\\"image is nil\\\"].\\n\\t\\\"stamp: Stamps are held in a ScrollingToolHolder. Pickups and stamps and brushes are id-ed by the button == with item from a list.\\\"\\n\\n\\t\\\"\\n\\t\\\"\\n! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'tk 8/22/97 15:57'!\\nnoVeneer\\n\\t\\\"For a palette with a background (off) image, clear that image.\\nBut first, for each button, cut that chunk out and save it in the offImage\\npart.\\\"\\n\\t\\\"\\tself noVeneer.\\n\\t\\tAllOffImage _ nil.\\t'save space. irreversible'.\\t\\\"\\n\\n\\t| aa on |\\n\\tAllOffImage ifNil: [AllOffImage _ image].\\n\\taa _ AllOffImage.\\n\\t\\\"Collect all the images for the buttons in the on state\\\"\\n\\tself allMorphsDo: [:button |\\n\\t\\t(button isKindOf: ThreePhaseButtonMorph) ifTrue: [\\n\\t\\t\\ton _ Form extent: button extent depth: 16.\\n\\t\\t\\ton copy: (0@0 extent: button extent)\\n\\t\\t\\t\\tfrom: (button topLeft - self topLeft) in:\\naa rule: Form over.\\n\\t\\t\\tbutton offImage: on]].\\n\\tself image: (Form extent: AllOffImage extent depth: 1).\\n\\tself invalidRect: bounds.\\n\\n\\n\\t! !\\n\\n!PaintBoxMorph methodsFor: 'initialization' stamp: 'RAA 8/16/2000 11:12'!\\nnotifyWeakDependentsWith: arguments\\n\\n\\tweakDependents ifNil: [^self].\\n\\tweakDependents do: [ :each |\\n\\t\\teach ifNotNil: [\\n\\t\\t\\teach paintBoxChanged: arguments.\\n\\t\\t\\teach paintBoxChanged: {#changed. arguments second. true}.\\n\\t\\t].\\n\\t].! !\\n\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'dgd 8/30/2003 21:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\t\\\"super addCustomMenuItems: aCustomMenu hand: aHandMorph.\\\"\\n\\t\\t\\\"don't want the ones from ImageMorph\\\"\\n\\taCustomMenu add: 'grab stamp from screen' translated action: #grabFromScreen:.\\n\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 14:08'!\\naddGraphicLabels\\n\\t\\\"translate button labels\\\"\\n\\n\\t| formTranslator ext pos newForm |\\n\\tformTranslator _ NaturalLanguageFormTranslator localeID: (Locale current localeID).\\n\\n\\t#('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:label |\\n\\t\\t(formTranslator translate: label, '-off') ifNil: [^ false].\\n\\t\\t(formTranslator translate: label, '-pressed') ifNil: [^ false].\\n\\t].\\n\\t\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\t| button |\\n\\t\\tbutton _ submorphs detect: [:m | m externalName = extName] ifNone: [nil].\\n\\t\\tbutton ifNotNil: [\\n\\t\\t\\tbutton removeAllMorphs.\\n\\t\\t\\text _ button extent.\\n\\t\\t\\tpos _ button position.\\n\\t\\t\\t(newForm _ formTranslator translate: label, '-off') ifNotNil: [\\n\\t\\t\\t\\tbutton offImage: newForm.\\n\\n\\t\\t\\t].\\n\\t\\t\\t(newForm _ formTranslator translate: label, '-pressed') ifNotNil: [\\n\\t\\t\\t\\tbutton pressedImage: newForm.\\n\\t\\t\\t].\\n\\t\\t\\tbutton extent: ext.\\n\\t\\t\\tbutton position: pos.\\n\\t\\t].\\n\\t].\\n\\n\\t^ true.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 14:08'!\\naddLabels\\n\\n\\tPreferences useFormsInPaintBox ifFalse: [\\n\\t\\tself addTextualLabels.\\n\\t] ifTrue: [\\n\\t\\tself addGraphicLabels ifFalse: [self addTextualLabels].\\n\\t].\\n! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'yo 1/13/2005 11:06'!\\naddTextualLabels\\n\\t\\\"translate button labels\\\"\\n\\n\\t#('keep:' 'undo:' 'clear:' 'toss:') with: #('KEEP' 'UNDO' 'CLEAR' 'TOSS') do: [:extName :label |\\n\\t\\t| button |\\n\\t\\tbutton _ submorphs detect: [:m | m externalName = extName] ifNone: [nil].\\n\\t\\tbutton ifNotNil: [\\n\\t\\t\\tbutton removeAllMorphs.\\n\\t\\t\\tbutton addMorph: (TextMorph new \\n\\t\\t\\t\\tcontentsWrapped: (Text string: label translated\\n\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\tTextAlignment centered. \\n\\t\\t\\t\\t\\t\\tTextEmphasis bold.\\n\\t\\t\\t\\t\\t\\tTextFontReference toFont:\\n\\t\\t\\t\\t\\t\\t\\t(Preferences standardPaintBoxButtonFont)});\\n\\t\\t\\t\\tbounds: (button bounds translateBy: 0@3);\\n\\t\\t\\t\\tlock)]]! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 10/31/97 13:38'!\\ncolorMemory\\n\\n\\t^ colorMemory! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'di 10/14/97 10:15'!\\ncolorMemory: aMorph\\n\\n\\tcolorMemory _ aMorph! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 10/31/97 13:35'!\\ncolorPatch\\n\\t^ colorPatch! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'ar 3/23/2000 14:18'!\\nfocusMorph\\n\\t\\\"Note: For backward compatibility we search the world for a SketchEditorMorph if the current focus morph is nil\\\"\\n\\t^focusMorph ifNil:[focusMorph _ self world findA: SketchEditorMorph]! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'ar 3/23/2000 14:20'!\\nfocusMorph: newFocus\\n\\t\\\"Set the new focus morph\\\"\\n\\tfocusMorph ifNotNil:[focusMorph paletteDetached: self]. \\\"In case the morph is interested\\\"\\n\\tfocusMorph _ newFocus.\\n\\tfocusMorph ifNotNil:[focusMorph paletteAttached: self]. \\\"In case the morph is interested\\\"! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 8/22/2000 11:57'!\\nmaxBounds\\n\\t| rr |\\n\\t\\\"fullBounds if all flop-out parts of the paintBox were showing.\\\"\\n\\n\\trr _ bounds merge: colorMemory bounds.\\n\\trr _ rr merge: (self submorphNamed: 'stamps') bounds.\\n\\trr _ rr origin corner: rr corner + (0@ (self submorphNamed: 'shapes') height \\n\\t\\t\\t\\t+ 10 \\\"what is showing of (self submorphNamed: #toggleShapes) height\\\").\\n\\t^ rr! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 8/22/2000 23:48'!\\noffsetFromMaxBounds\\n\\t\\\"location of normal PaintBox within maxBounds.\\\"\\n\\n\\t^ self left - colorMemory left @ 0! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 7/17/97 16:26'!\\nrotationTabForm\\n\\t^ rotationTabForm! !\\n\\n!PaintBoxMorph methodsFor: 'other' stamp: 'tk 7/17/97 16:26'!\\nscaleTabForm\\n\\t^ scaleTabForm! !\\n\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 7/8/2006 20:33'!\\nfixUpColorPicker\\n\\t| chart picker |\\n\\tchart _ ColorChart ifNil:[Cursor wait showWhile:[ColorChart _ (ColorPickerMorph colorPaletteForDepth: 16 extent: 120@89)]].\\n\\tchart getCanvas frameRectangle: chart boundingBox color: Color black.\\n\\tpicker _ Form extent: (chart extent + (14@12)) depth: 16.\\n\\tpicker fillWhite.\\n\\t\\\"top\\\"\\n\\tpicker copy: (0@0 extent: picker width@6)\\n\\t\\t\\tfrom: (colorMemory image width - picker width)@0 \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"bottom\\\"\\n\\tpicker copy: (0@ (picker height-6) extent: picker width@6) \\n\\t\\t\\tfrom: (colorMemory image width - picker width)@(colorMemory image height - 7)\\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"left\\\"\\n\\tpicker copy: (0@6 corner: 8@(picker height - 6))\\n\\t\\t\\tfrom: (colorMemory image boundingBox topLeft + (0@6)) \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\t\\\"right\\\"\\n\\tpicker copy: (picker width-6@6 corner: picker width@(picker height - 6))\\n\\t\\t\\tfrom: (colorMemory image boundingBox topRight - (6@-6)) \\n\\t\\t\\tin: colorMemory image rule: Form over.\\n\\tchart displayOn: picker at: 8@6.\\n\\tpicker getCanvas frameRectangle: picker boundingBox color: Color black.\\n\\tcolorMemory image: picker.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'dgd 2/21/2003 23:17'!\\nfixUpRecentColors\\n\\t| inner outer border box form newImage canvas morph |\\n\\tself fixUpColorPicker.\\n\\trecentColors := WriteStream on: Array new.\\n\\tform := image.\\n\\tnewImage := Form extent: form extent + (0 @ 41) depth: form depth.\\n\\tform displayOn: newImage.\\n\\tnewImage \\n\\t\\tcopy: (0 @ (form height - 10) \\n\\t\\t\\t\\textent: form width @ (newImage height - form height + 10))\\n\\t\\tfrom: 0 @ (form height - (newImage height - form height + 10))\\n\\t\\tin: form\\n\\t\\trule: Form over.\\n\\tcanvas := newImage getCanvas.\\n\\tcanvas \\n\\t\\tline: 12 @ (form height - 10)\\n\\t\\tto: 92 @ (form height - 10)\\n\\t\\twidth: 1\\n\\t\\tcolor: Color black.\\n\\tcanvas := canvas copyOffset: 12 @ (form height - 9).\\n\\tinner := Color \\n\\t\\t\\t\\tr: 0.677\\n\\t\\t\\t\\tg: 0.71\\n\\t\\t\\t\\tb: 0.968.\\n\\touter := inner darker darker.\\n\\tborder := Color \\n\\t\\t\\t\\tr: 0.194\\n\\t\\t\\t\\tg: 0.258\\n\\t\\t\\t\\tb: 0.194.\\n\\t0 to: 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\t0 to: 3\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tbox := (x * 20) @ (y * 20) extent: 20 @ 20.\\n\\t\\t\\t\\t\\tmorph := BorderedMorph new \\n\\t\\t\\t\\t\\t\\t\\t\\tbounds: ((box insetBy: 1) translateBy: canvas origin + bounds origin).\\n\\t\\t\\t\\t\\tmorph\\n\\t\\t\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\t\\t\\tborderColor: border.\\n\\t\\t\\t\\t\\tmorph color: Color white.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\t\\t\\tsend: #mouseDownRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\t\\t\\tsend: #mouseStillDownRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tmorph \\n\\t\\t\\t\\t\\t\\ton: #mouseUp\\n\\t\\t\\t\\t\\t\\tsend: #mouseUpRecent:with:\\n\\t\\t\\t\\t\\t\\tto: self.\\n\\t\\t\\t\\t\\tself addMorphFront: morph.\\n\\t\\t\\t\\t\\trecentColors nextPut: morph.\\n\\t\\t\\t\\t\\tcanvas fillRectangle: box color: Color white.\\n\\t\\t\\t\\t\\tcanvas frameRectangle: (box insetBy: 1) color: border.\\n\\t\\t\\t\\t\\tcanvas frameRectangle: box color: inner.\\n\\t\\t\\t\\t\\tbox := box insetBy: 1.\\n\\t\\t\\t\\t\\tcanvas \\n\\t\\t\\t\\t\\t\\tline: box topRight\\n\\t\\t\\t\\t\\t\\tto: box bottomRight\\n\\t\\t\\t\\t\\t\\twidth: 1\\n\\t\\t\\t\\t\\t\\tcolor: outer.\\n\\t\\t\\t\\t\\tcanvas \\n\\t\\t\\t\\t\\t\\tline: box bottomLeft\\n\\t\\t\\t\\t\\t\\tto: box bottomRight\\n\\t\\t\\t\\t\\t\\twidth: 1\\n\\t\\t\\t\\t\\t\\tcolor: outer]].\\n\\trecentColors := recentColors contents.\\n\\t(RecentColors isNil or: [RecentColors size ~= recentColors size]) \\n\\t\\tifTrue: [RecentColors := recentColors collect: [:each | each color]]\\n\\t\\tifFalse: \\n\\t\\t\\t[RecentColors \\n\\t\\t\\t\\tkeysAndValuesDo: [:idx :aColor | (recentColors at: idx) color: aColor]].\\n\\tself image: newImage.\\n\\tself toggleStamps.\\n\\tself toggleStamps! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 19:54'!\\nmouseDownRecent: evt with: aMorph\\n\\taMorph borderColor: Color white.\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 20:01'!\\nmouseStillDownRecent: evt with: aMorph\\n\\t(aMorph containsPoint: evt cursorPoint)\\n\\t\\tifTrue:[aMorph borderColor: Color white]\\n\\t\\tifFalse:[aMorph borderColor: (Color r: 0.194 g: 0.258 b: 0.194)]\\n! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'ar 9/23/2000 19:59'!\\nmouseUpRecent: evt with: aMorph\\n\\taMorph borderColor: (Color r: 0.194 g: 0.258 b: 0.194).\\n\\t(aMorph containsPoint: evt cursorPoint) ifTrue:[\\n\\t\\tself takeColor: aMorph color event: evt.\\n\\t].! !\\n\\n!PaintBoxMorph methodsFor: 'recent colors' stamp: 'dgd 2/21/2003 23:17'!\\nrecentColor: aColor \\n\\t\\\"Remember the color as one of our recent colors\\\"\\n\\n\\t(recentColors anySatisfy: [:any | any color = aColor]) ifTrue: [^self].\\t\\\"already remembered\\\"\\n\\trecentColors size to: 2\\n\\t\\tby: -1\\n\\t\\tdo: \\n\\t\\t\\t[:i | \\n\\t\\t\\t(recentColors at: i) color: (recentColors at: i - 1) color.\\n\\t\\t\\tRecentColors at: i put: (RecentColors at: i - 1)].\\n\\t(recentColors first) color: aColor.\\n\\tRecentColors at: 1 put: aColor! !\\n\\n\\n!PaintBoxMorph methodsFor: 'user interface' stamp: 'tk 7/2/97 08:10'!\\nmouseUpBalk: evt\\n\\t\\\"A button I own got a mouseDown, but the user moved out before letting up. Prevent this for the current tool. Some tool must stay selected.\\\"\\n\\n\\ttool state: #on.\\t\\\"keep current one, even if user balked on it\\\"\\n\\tcurrentBrush ifNotNil: [currentBrush state: #on].! !\\n\\n\\n!PaintBoxMorph methodsFor: '*eToys-e-toy support' stamp: 'sw 6/30/1999 20:33'!\\nisCandidateForAutomaticViewing\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPaintBoxMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 8/21/2000 12:52'!\\nfixUpPrototype\\n\\t\\\"PaintBoxMorph fixUpPrototype\\\"\\nself error: 'who uses this?'.\\n\\tPrototype eventHandler: nil! !\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'ar 7/8/2006 20:33'!\\ninitializeColorChart\\n\\t\\\"PaintBoxMorph initializeColorChart\\\"\\n\\tColorChart _ (ColorPickerMorph colorPaletteForDepth: 32 extent: (360+10)@(180+10))! !\\n\\n!PaintBoxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 10/12/97 11:01'!\\nprototype\\n\\t\\\"Later we will be a subclass of Model, and it will have a general version of this\\\"\\n\\t^ Prototype! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'class initialization' stamp: 'tk 8/21/2000 12:58'!\\ninitialize\\n\\t\\\"PaintBoxMorph initialize\\\"\\n\\n\\tPrototype eventHandler: nil.\\n\\tPrototype focusMorph: nil.\\n\\tPrototype stampHolder clear. \\\"clear stamps\\\"\\n\\tPrototype delete. \\\"break link to world, if any\\\"\\n\\n\\tAllOnImage _ AllOffImage _ AllPressedImage _ nil.\\n\\tOriginalBounds _ nil.\\n\\n! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'instance creation' stamp: 'bf 10/11/2004 13:37'!\\nnew\\n\\n\\t| pb button dualUse formCanvas rect |\\n\\tpb _ Prototype veryDeepCopy.\\n\\t\\t\\\"Assume that the PaintBox does not contain any scripted Players!!\\\"\\n\\tpb stampHolder normalize.\\t\\\"Get the stamps to show\\\"\\n\\t\\\"Get my own copies of the brushes so I can modify them\\\"\\n\\t#(brush1: brush2: brush3: brush4: brush5: brush6:) do: [:sel |\\n\\t\\tbutton _ pb submorphNamed: sel.\\n\\t\\tbutton offImage: button offImage deepCopy.\\n\\t\\tdualUse _ button onImage == button pressedImage.\\t\\\"sometimes shared\\\"\\n\\t\\tbutton onImage: button onImage deepCopy.\\n\\t\\tdualUse\\n\\t\\t\\tifTrue: [button pressedImage: button onImage]\\n\\t\\t\\tifFalse: [button pressedImage: button pressedImage deepCopy].\\n\\t\\t\\\"force color maps for later mapping\\\"\\n\\t\\tbutton offImage.\\n\\t\\tbutton onImage.\\n\\t\\tbutton pressedImage.\\n\\t\\tformCanvas _ button onImage getCanvas.\\n\\t\\tformCanvas _ formCanvas\\n\\t\\t\\tcopyOrigin: 0@0\\n\\t\\t\\tclipRect: (rect _ 0@0 extent: button onImage extent).\\n\\t\\t(#(brush1: brush3:) includes: sel) ifTrue: [\\n\\t\\t\\trect _ rect origin corner: rect corner - (2@2)].\\n\\t\\t(#brush2: == sel) ifTrue: [\\n\\t\\t\\trect _ rect origin corner: rect corner - (2@4)].\\n\\t\\tformCanvas frameAndFillRectangle: rect fillColor: Color transparent\\n\\t\\t\\tborderWidth: 2 borderColor: (Color r: 0.599 g: 0.8 b: 1.0).\\n\\t\\t].\\n\\tpb showColor.\\n\\tpb fixUpRecentColors.\\n\\tpb addLabels.\\n\\t^ pb! !\\n\\n\\n!PaintBoxMorph class methodsFor: 'notification' stamp: 'ar 7/8/2006 20:33'!\\nlocaleChanged\\n\\t| caption |\\n\\tcaption := ColorPickerMorph noColorCaption.\\n\\tcaption displayOn: ColorChart at: ColorChart boundingBox topCenter - (caption width // 2 @ 0)! !\\nImageMorph subclass: #PaintInvokingMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!PaintInvokingMorph commentStamp: '<historical>' prior: 0!\\nWhen this is dropped inside some appropriate place, then painting is invoked for that place.!\\n\\n\\n!PaintInvokingMorph methodsFor: 'dropping/grabbing' stamp: 'dgd 4/3/2006 14:19'!\\njustDroppedInto: aPasteUpMorph event: anEvent\\n\\t\\\"This message is sent to a dropped morph after it has been dropped on--and been accepted by--a drop-sensitive morph\\\"\\n\\taPasteUpMorph isPartsBin ifFalse:[\\n\\t\\tself removeHalo.\\n\\t\\tself delete.\\n\\t\\t^aPasteUpMorph makeNewDrawing: anEvent].\\n\\t^super justDroppedInto: aPasteUpMorph event: anEvent! !\\n\\n!PaintInvokingMorph methodsFor: 'dropping/grabbing' stamp: 'ar 3/3/2001 20:40'!\\nwantsToBeDroppedInto: aMorph\\n\\t\\\"Only into PasteUps that are not part bins\\\"\\n\\t^aMorph isPlayfieldLike! !\\n\\n\\n!PaintInvokingMorph methodsFor: 'initialization' stamp: 'sw 7/16/1998 00:02'!\\ninitialize\\n\\tsuper initialize.\\n\\tself image: (ScriptingSystem formAtKey: 'Painting')! !\\n\\n\\n!PaintInvokingMorph methodsFor: 'parts bin' stamp: 'sw 8/12/2001 17:19'!\\ninitializeToStandAlone\\n\\tsuper initializeToStandAlone.\\n\\tself image: (ScriptingSystem formAtKey: 'Painting')! !\\n\\n\\n!PaintInvokingMorph methodsFor: '*eToys-e-toy support' stamp: 'sw 6/30/1999 20:31'!\\nisCandidateForAutomaticViewing\\n\\t^ self isPartsDonor not! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nPaintInvokingMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 13:16'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.! !\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:09'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(PaintInvokingMorph\\tnew\\t'Paint'\\t'Drop this into an area to start making a fresh painting there')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Scripting']! !\\n\\n!PaintInvokingMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:38'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!PaintInvokingMorph class methodsFor: 'parts bin' stamp: 'nk 8/23/2004 18:11'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Paint'\\n\\t\\tcategories:\\t\\t#('Basic' 'Graphics')\\n\\t\\tdocumentation:\\t'Drop this icon to start painting a new object.'! !\\n\\n\\n!PaintInvokingMorph class methodsFor: 'scripting' stamp: 'sw 5/6/2000 02:28'!\\nauthoringPrototype\\n\\t^ self new image: (ScriptingSystem formAtKey: 'Painting'); markAsPartsDonor; setBalloonText: 'drop this into any playfield or book page to make a new painting there'; yourself! !\\nCompositeStub subclass: #PanelStub\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ToolBuilder-SUnit'!\\nDisplayText subclass: #Paragraph\\n\\tinstanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'ST80-Support'!\\n!Paragraph commentStamp: '<historical>' prior: 0!\\nI represent displayable text that has been decoraged with margin alignment, line leading, and tab settings.!\\n\\n\\n!Paragraph methodsFor: 'accessing'!\\nbackgroundColor\\n\\tbackColor == nil ifTrue: [^ Color white].\\n\\t^ backColor! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nclippingRectangle \\n\\t\\\"Answer the rectangle, defined in absolute coordinates, whose \\n\\tintersection with the destinationForm is the area in which the characters \\n\\tare constrained to display.\\\"\\n\\n\\t^clippingRectangle! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'di 10/5/97 15:33'!\\nclippingRectangle: clipRect \\n\\tclippingRectangle _ clipRect! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ncompositionRectangle\\n\\t\\\"Answer the rectangle whose width is the dimension, modified by \\n\\tindents and tabsLevels, against which line wraparound is measured. The \\n\\theight of the compositionRectangle is reset each time recomposition is \\n\\trequired.\\\"\\n\\n\\t^compositionRectangle! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ncompositionRectangle: compRectangle \\n\\t\\\"Set the rectangle whose width is the dimension, modified by indents and \\n\\ttabsLevels, against which line wraparound is measured.\\\"\\n\\n\\tcompositionRectangle _ compRectangle.\\n\\tself composeAll! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ndestinationForm \\n\\t \\\"Answer the Form into which the characters are scanned.\\\"\\n\\n\\t^destinationForm! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nfillColor \\n\\t\\\"Answer the Form with which each character is combined by the scanner \\n\\tbefore applying the rule for display.\\\"\\n\\n\\t^mask! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nfillColor: maskForm \\n\\t\\\"Set the argument, maskForm, to be the form with which each character \\n\\tis combined by the scanner before applying the rule for display.\\\"\\n\\n\\tmask _ maskForm! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nheight \\n\\t\\\"Answer the height of the composition rectangle.\\\"\\n\\n\\t^compositionRectangle height! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nindentationOfLineIndex: lineIndex ifBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the line at lineIndex. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\n\\t If the line is word-wrap overflow, back up a line and recur.\\\"\\n\\n\\t| arrayIndex first last reader leadingTabs lastSeparator cr tab ch |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\tarrayIndex _ lineIndex.\\n\\t[first _ (lines at: arrayIndex) first.\\n\\t first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: \\\"word wrap\\\"\\n\\t\\t[arrayIndex _ arrayIndex - 1].\\n\\tlast _ (lines at: lastLine) last.\\n\\treader _ ReadStream on: text string from: first to: last.\\n\\tleadingTabs _ 0.\\n\\t[reader atEnd not and: [(ch _ reader next) == tab]]\\n\\t\\twhileTrue: [leadingTabs _ leadingTabs + 1].\\n\\tlastSeparator _ first - 1 + leadingTabs.\\n\\t[reader atEnd not and: [ch isSeparator and: [ch ~~ cr]]]\\n\\t\\twhileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next].\\n\\tlastSeparator = last | (ch == cr)\\n\\t\\tifTrue: [^aBlock value: leadingTabs].\\n\\t^leadingTabs! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nmask \\n\\t\\\"Answer the Form with which each character is combined by the scanner \\n\\tbefore applying the rule for display.\\\"\\n\\n\\t^mask! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nnumberOfLines \\n\\t\\\"Answer the number of lines of text in the receiver.\\\"\\n\\n\\t^lastLine! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'ar 5/18/2000 18:34'!\\nreplaceFrom: start to: stop with: aText displaying: displayBoolean\\n\\t\\\"Replace the receiver's text starting at position start, stopping at stop, by \\n\\tthe characters in aText. It is expected that most requirements for \\n\\tmodifications to the receiver will call this code. Certainly all cut's or \\n\\tpaste's.\\\" \\n\\n\\t| compositionScanner obsoleteLines obsoleteLastLine firstLineIndex lastLineIndex\\n\\tstartLine stopLine replacementRange visibleRectangle startIndex newLine done\\n\\tnewStop obsoleteY newY moveRectangle |\\n\\n\\ttext replaceFrom: start to: stop with: aText.\\t\\t\\\"Update the text.\\\"\\n\\tlastLine = 0 ifTrue:\\n\\t\\t[\\\"if lines have never been set up, measure them and display\\n\\t\\tall the lines falling in the visibleRectangle\\\"\\n\\t\\tself composeAll.\\n\\t\\tdisplayBoolean ifTrue: [^ self displayLines: (1 to: lastLine)]].\\n\\n\\t\\\"save -- things get pretty mashed as we go along\\\"\\n\\tobsoleteLines _ lines copy.\\n\\tobsoleteLastLine _ lastLine.\\n\\n\\t\\\"find the starting and stopping lines\\\"\\n\\tfirstLineIndex _ startLine _ self lineIndexOfCharacterIndex: start.\\n\\tstopLine _ self lineIndexOfCharacterIndex: stop.\\n\\n\\t\\\"how many characters being inserted or deleted\\n\\t\\t-- negative if aText size is < characterInterval size.\\\"\\n\\treplacementRange _ aText size - (stop - start + 1).\\n\\t\\\"Give ourselves plenty of elbow room.\\\"\\n\\tcompositionRectangle _ compositionRectangle withHeight: (textStyle lineGrid * 9999).\\n\\t\\\"build a boundingBox of the actual screen space in question -- we'll need it later\\\"\\n\\tvisibleRectangle _ (clippingRectangle intersect: compositionRectangle)\\n\\t\\t\\t\\t\\t\\t\\tintersect: destinationForm boundingBox.\\n\\tcompositionScanner _ CompositionScanner new forParagraph: self.\\t\\t\\\"Initialize a scanner.\\\"\\n\\n\\t\\\"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.\\\"\\n\\tstartIndex _ (lines at: firstLineIndex) first.\\n\\tstartLine > 1\\n\\t\\tifTrue: \\t[newLine _ compositionScanner composeLine: startLine - 1\\n\\t\\t\\t\\t\\t\\tfromCharacterIndex: (lines at: startLine - 1) first\\n\\t\\t\\t\\t\\t\\tinParagraph: self.\\n\\t\\t\\t\\t(lines at: startLine - 1) = newLine\\n\\t\\t\\t\\t\\tifFalse:\\t[\\\"start in line preceding the one with the starting character\\\"\\n\\t\\t\\t\\t\\t\\t\\tstartLine _ startLine - 1.\\n\\t\\t\\t\\t\\t\\t\\tself lineAt: startLine put: newLine.\\n\\t\\t\\t\\t\\t\\t\\tstartIndex _ newLine last + 1]].\\n\\tstartIndex > text size ifTrue:\\n\\t\\t[\\\"nil lines after a deletion -- remeasure last line below\\\"\\n\\t\\tself trimLinesTo: (firstLineIndex - 1 max: 0).\\n\\t\\ttext size = 0 ifTrue:\\n\\t\\t\\t[\\\"entire text deleted -- clear visibleRectangle and return.\\\"\\n\\t\\t\\tdisplayBoolean ifTrue: [destinationForm fill: visibleRectangle rule: rule fillColor: self backgroundColor].\\n\\t\\t\\tself updateCompositionHeight.\\n\\t\\t\\t^self]].\\n\\n\\t\\\"Now we really get to it.\\\"\\n\\tdone _ false.\\n\\tlastLineIndex _ stopLine.\\n\\t[done or: [startIndex > text size]]\\n\\t\\twhileFalse: \\n\\t\\t[self lineAt: firstLineIndex put:\\n\\t\\t\\t(newLine _ compositionScanner composeLine: firstLineIndex\\n\\t\\t\\t\\t\\t\\t\\tfromCharacterIndex: startIndex inParagraph: self).\\n\\t\\t[(lastLineIndex > obsoleteLastLine\\n\\t\\t\\tor: [\\\"no more old lines to compare with?\\\"\\n\\t\\t\\t\\tnewLine last <\\n\\t\\t\\t\\t\\t(newStop _ (obsoleteLines at: lastLineIndex) last + replacementRange)])\\n\\t\\t\\t \\tor: [done]]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t[newStop = newLine last\\n\\t\\t\\t\\tifTrue:\\t[\\\"got the match\\\"\\n\\t\\t\\t\\t\\t\\t\\\"get source and dest y's for moving the unchanged lines\\\"\\n\\t\\t\\t\\t\\t\\tobsoleteY _ self topAtLineIndex: lastLineIndex + 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tusing: obsoleteLines and: obsoleteLastLine.\\n\\t\\t\\t\\t\\t\\tnewY _ self topAtLineIndex: firstLineIndex + 1.\\n\\t\\t\\t\\t\\t\\tstopLine _ firstLineIndex.\\n\\t\\t\\t\\t\\t\\tdone _ true.\\n\\t\\t\\t\\t\\t\\t\\t\\\"Fill in the new line vector with the old unchanged lines.\\n\\t\\t\\t\\t\\t\\t\\tUpdate their starting and stopping indices on the way.\\\"\\n\\t\\t\\t\\t\\t\\t((lastLineIndex _ lastLineIndex + 1) to: obsoleteLastLine) do:\\n\\t\\t\\t\\t\\t\\t\\t[:upDatedIndex | \\n\\t\\t\\t\\t\\t\\t\\tself lineAt: (firstLineIndex _ firstLineIndex + 1) \\n\\t\\t\\t\\t\\t\\t\\t\\tput: ((obsoleteLines at: upDatedIndex)\\n\\t\\t\\t\\t\\t\\t\\t \\t\\tslide: replacementRange)].\\n\\t\\t\\t\\t\\t\\t\\t\\\"trim off obsolete lines, if any\\\"\\n\\t\\t\\t\\t\\t\\tself trimLinesTo: firstLineIndex]\\n\\t\\t\\t\\tifFalse:\\t[lastLineIndex _ lastLineIndex + 1]].\\n\\t\\tstartIndex _ newLine last + 1.\\n\\t\\tfirstLineIndex _ firstLineIndex + 1].\\n\\n\\t\\\"Now the lines are up to date -- Whew!!. What remains is to move\\n\\tthe 'unchanged' lines and display those which have changed.\\\"\\n\\tdisplayBoolean \\\"Not much to do if not displaying\\\"\\n\\t\\tifFalse: [^ self updateCompositionHeight].\\n\\tstartIndex > text size ifTrue:\\n\\t\\t[\\\"If at the end of previous lines simply display lines from the line in\\n\\t\\twhich the first character of the replacement occured through the\\n\\t\\tend of the paragraph.\\\"\\n\\t\\tself updateCompositionHeight.\\n\\t\\tself displayLines:\\n\\t\\t\\t(startLine to: (stopLine _ firstLineIndex min: lastLine)).\\n\\t\\tdestinationForm \\\"Clear out area at the bottom\\\"\\n\\t\\t\\tfill: ((visibleRectangle left @ (self topAtLineIndex: lastLine + 1)\\n\\t\\t\\t\\t\\t\\textent: visibleRectangle extent)\\n\\t\\t\\t\\t\\tintersect: visibleRectangle)\\n\\t\\t\\trule: rule fillColor: self backgroundColor]\\n\\t\\tifFalse:\\n\\t\\t[newY ~= obsoleteY ifTrue:\\n\\t\\t\\t[\\\"Otherwise first move the unchanged lines within\\n\\t\\t\\tthe visibleRectangle with a good old bitblt.\\\"\\n\\t\\t\\tmoveRectangle _\\n\\t\\t\\t\\tvisibleRectangle left @ (obsoleteY max: visibleRectangle top)\\n\\t\\t\\t\\t\\tcorner: visibleRectangle corner.\\n\\t\\t\\tdestinationForm copyBits: moveRectangle from: destinationForm\\n\\t\\t\\t\\tat: moveRectangle origin + (0 @ (newY-obsoleteY))\\n\\t\\t\\t\\tclippingBox: visibleRectangle\\n\\t\\t\\t\\trule: Form over fillColor: nil].\\n\\n\\t\\t\\\"Then display the altered lines.\\\"\\n\\t\\tself displayLines: (startLine to: stopLine).\\n\\n\\t\\tnewY < obsoleteY\\n\\t\\t\\tifTrue:\\n\\t\\t\\t[(self topAtLineIndex: obsoleteLastLine+1 using: obsoleteLines and: obsoleteLastLine) > visibleRectangle bottom\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[\\\"A deletion may have 'pulled' previously undisplayed lines\\n\\t\\t\\t\\tinto the visibleRectangle. If so, display them.\\\"\\n\\t\\t\\t\\tself displayLines:\\n\\t\\t\\t\\t\\t((self lineIndexOfTop: visibleRectangle bottom - (obsoleteY - newY))\\n\\t\\t\\t\\t\\t\\tto: (self lineIndexOfTop: visibleRectangle bottom))].\\n\\t\\t\\t\\\"Clear out obsolete material at the bottom of the visibleRectangle.\\\"\\n\\t\\t\\tdestinationForm\\n\\t\\t\\t\\tfill: ((visibleRectangle left @ ((self bottomAtLineIndex: lastLine) + 1)\\n\\t\\t\\t\\t\\t\\textent: visibleRectangle extent)\\n\\t\\t\\t\\t\\tintersect: visibleRectangle) \\\"How about just corner: ??\\\"\\n\\t\\t\\t\\trule: rule fillColor: self backgroundColor].\\n\\n\\t\\t(newY > obsoleteY and: [obsoleteY < visibleRectangle top])\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[\\\"An insertion may have 'pushed' previously undisplayed lines\\n\\t\\t\\t\\tinto the visibleRectangle. If so, display them.\\\"\\n\\t\\t\\t\\tself displayLines:\\n\\t\\t\\t\\t\\t((self lineIndexOfTop: visibleRectangle top)\\n\\t\\t\\t\\t\\t\\tto: (self lineIndexOfTop: visibleRectangle top + (newY-obsoleteY)))].\\n\\n\\t\\tself updateCompositionHeight]! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nrule \\n\\t\\\"Answer the rule according to which character display behaves. For \\n\\texample, rule may equal over, under, reverse.\\\"\\n\\n\\t^rule! !\\n\\n!Paragraph methodsFor: 'accessing'!\\nrule: ruleInteger \\n\\t\\\"Set the rule according to which character display behaves.\\\"\\n\\n\\trule _ ruleInteger! !\\n\\n!Paragraph methodsFor: 'accessing' stamp: 'sw 10/29/1999 18:11'!\\nstringAtLineNumber: aNumber\\n\\t(aNumber > lastLine or: [aNumber < 1]) ifTrue: [^ nil].\\n\\t^ (text string copyFrom: (lines at: aNumber) first to: (lines at: aNumber) last) copyWithout: Character cr! !\\n\\n!Paragraph methodsFor: 'accessing'!\\ntext: aText \\n\\t\\\"Set the argument, aText, to be the text for the receiver.\\\"\\n\\n\\ttext _ aText.\\n\\tself composeAll! !\\n\\n\\n!Paragraph methodsFor: 'alignment'!\\ncentered \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that text is centered in the composition rectangle.\\\"\\n\\n\\ttextStyle alignment: Centered! !\\n\\n!Paragraph methodsFor: 'alignment'!\\njustified \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text end on an even border in the \\n\\tcomposition rectangle.\\\"\\n\\n\\ttextStyle alignment: Justified! !\\n\\n!Paragraph methodsFor: 'alignment'!\\nleftFlush \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text begin on an even border in the \\n\\tcomposition rectangle. This is also known as ragged-right.\\\"\\n\\n\\ttextStyle alignment: LeftFlush! !\\n\\n!Paragraph methodsFor: 'alignment'!\\nrightFlush \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that the characters in each of text end on an even border in the \\n\\tcomposition rectangle but the beginning of each line does not. This is \\n\\talso known as ragged-left.\\\"\\n\\n\\ttextStyle alignment: RightFlush! !\\n\\n!Paragraph methodsFor: 'alignment'!\\ntoggleAlignment \\n\\t\\\"Set the alignment for the style with which the receiver displays its text \\n\\tso that it moves from centered to justified to leftFlush to rightFlush and \\n\\tback to centered again.\\\"\\n\\n\\ttextStyle alignment: textStyle alignment + 1! !\\n\\n\\n!Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'!\\ncharacterBlockAtPoint: aPoint \\n\\t\\\"Answer a CharacterBlock for characters in the text at point aPoint. It is \\n\\tassumed that aPoint has been transformed into coordinates appropriate to \\n\\tthe receiver's destinationForm rectangle and the compositionRectangle.\\\"\\n\\n\\t^CharacterBlockScanner new characterBlockAtPoint: aPoint in: self! !\\n\\n!Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'!\\ncharacterBlockForIndex: targetIndex \\n\\t\\\"Answer a CharacterBlock for character in the text at targetIndex. The \\n\\tcoordinates in the CharacterBlock will be appropriate to the intersection \\n\\tof the destinationForm rectangle and the compositionRectangle.\\\"\\n\\n\\t^CharacterBlockScanner new characterBlockForIndex: targetIndex in: self! !\\n\\n!Paragraph methodsFor: 'character location' stamp: 'di 10/5/1998 12:59'!\\ndefaultCharacterBlock\\n\\t^ CharacterBlock new stringIndex: 1 text: text\\n\\t\\t\\ttopLeft: compositionRectangle topLeft extent: 0 @ 0! !\\n\\n\\n!Paragraph methodsFor: 'composition' stamp: 'yo 1/23/2003 22:47'!\\ncomposeAll\\n\\t\\\"Compose a collection of characters into a collection of lines.\\\"\\n\\n\\t| startIndex stopIndex lineIndex maximumRightX compositionScanner |\\n\\tlines _ Array new: 32.\\n\\tlastLine _ 0.\\n\\tmaximumRightX _ 0.\\n\\ttext size = 0\\n\\t\\tifTrue:\\n\\t\\t\\t[compositionRectangle _ compositionRectangle withHeight: 0.\\n\\t\\t\\t^maximumRightX].\\n\\tstartIndex _ lineIndex _ 1.\\n\\tstopIndex _ text size.\\n\\tcompositionScanner _ MultiCompositionScanner new forParagraph: self.\\n\\t[startIndex > stopIndex] whileFalse: \\n\\t\\t[self lineAt: lineIndex \\n\\t\\t\\t\\tput: (compositionScanner composeLine: lineIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfromCharacterIndex: startIndex \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinParagraph: self).\\n\\t\\t maximumRightX _ compositionScanner rightX max: maximumRightX.\\n\\t\\t startIndex _ (lines at: lineIndex) last + 1.\\n\\t\\t lineIndex _ lineIndex + 1].\\n\\tself updateCompositionHeight.\\n\\tself trimLinesTo: lineIndex - 1.\\n\\t^ maximumRightX! !\\n\\n!Paragraph methodsFor: 'composition'!\\nwrappingBox: compositionRect clippingBox: clippingRect \\n\\t\\\"Set the composition rectangle for the receiver so that the lines wrap \\n\\twithin the rectangle, compositionRect, and the display of the text is \\n\\tclipped by the rectangle, clippingRect.\\\"\\n\\n\\tself compositionRectangle: compositionRect copy\\n\\t\\t\\t\\ttext: text\\n\\t\\t\\t\\tstyle: textStyle\\n\\t\\t\\t\\toffset: offset.\\n\\tclippingRectangle _ clippingRect copy! !\\n\\n\\n!Paragraph methodsFor: 'converting' stamp: 'yo 6/23/2003 19:05'!\\nasForm\\n\\t\\\"Answer a Form made up of the bits that represent the receiver's displayable text.\\\"\\n\\t| theForm oldBackColor oldForeColor |\\n\\ttextStyle isTTCStyle ifTrue: [\\n\\t\\ttheForm _ (Form extent: compositionRectangle extent depth: 32)\\n\\t\\toffset: offset.\\n\\t] ifFalse: [\\n\\t\\ttheForm _ (ColorForm extent: compositionRectangle extent)\\n\\t\\t\\toffset: offset;\\n\\t\\t\\tcolors: (Array\\n\\t\\t\\t\\twith: (backColor == nil ifTrue: [Color transparent] ifFalse: [backColor])\\n\\t\\t\\t\\twith: (foreColor == nil ifTrue: [Color black] ifFalse: [foreColor])).\\n\\t].\\n\\toldBackColor _ backColor.\\n\\toldForeColor _ foreColor.\\n\\tbackColor _ Color white.\\n\\tforeColor _ Color black.\\n\\tself displayOn: theForm\\n\\t\\tat: 0@0\\n\\t\\tclippingBox: theForm boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil.\\n\\tbackColor _ oldBackColor.\\n\\tforeColor _ oldForeColor.\\n\\t^ theForm\\n\\n\\\"Example:\\n| p |\\np _ 'Abc' asParagraph.\\np foregroundColor: Color red backgroundColor: Color black.\\np asForm displayOn: Display at: 30@30 rule: Form over\\\"\\n! !\\n\\n!Paragraph methodsFor: 'converting'!\\nasString\\n\\t\\\"Answer the string of characters of the receiver's text.\\\"\\n\\n\\t^text string! !\\n\\n!Paragraph methodsFor: 'converting'!\\nasText\\n\\t\\\"Answer the receiver's text.\\\"\\n\\n\\t^text! !\\n\\n\\n!Paragraph methodsFor: 'display box access'!\\nboundingBox\\n\\n\\t^offset extent: compositionRectangle extent! !\\n\\n!Paragraph methodsFor: 'display box access'!\\ncomputeBoundingBox\\n\\n\\t^offset extent: compositionRectangle extent! !\\n\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium\\n\\t\\\"Because Paragraphs cache so much information, computation is avoided\\n\\tand displayAt: 0@0 is not appropriate here.\\\"\\n\\n\\tself displayOn: aDisplayMedium\\n\\t\\tat: compositionRectangle topLeft\\n\\t\\tclippingBox: clippingRectangle\\n\\t\\trule: rule\\n\\t\\tfillColor: mask! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aPoint\\n\\t\\\"Use internal clippingRect; destination cliping is done during actual display.\\\"\\n\\n\\tself displayOn: aDisplayMedium at: aPoint\\n\\t\\tclippingBox: (clippingRectangle translateBy: aPoint - compositionRectangle topLeft)\\n\\t\\trule: rule fillColor: mask! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm\\n\\t\\\"Default display message when aDisplayPoint is in absolute screen\\n\\tcoordinates.\\\"\\n\\n\\trule _ ruleInteger.\\n\\tmask _ aForm.\\n\\tclippingRectangle _ clipRectangle.\\n\\tcompositionRectangle _ aDisplayPoint extent: compositionRectangle extent.\\n\\t(lastLine == nil or: [lastLine < 1]) ifTrue: [self composeAll].\\n\\tself displayOn: aDisplayMedium lines: (1 to: lastLine)! !\\n\\n!Paragraph methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm \\n\\n\\tself\\t\\t\\t\\t\\\"Assumes offset has been set!!!!!!!!!!\\\"\\n\\t displayOn: aDisplayMedium\\n\\t at: (offset \\n\\t\\t\\t+ (displayTransformation applyTo: relativePoint) \\n\\t\\t\\t- alignmentPoint) rounded\\n\\t clippingBox: clipRectangle\\n\\t rule: ruleInteger\\n\\t fillColor: aForm.\\n\\t! !\\n\\n\\n!Paragraph methodsFor: 'indicating'!\\nflash \\n\\t\\\"Complement twice the visible area in which the receiver displays.\\\"\\n\\n\\tDisplay flash: clippingRectangle! !\\n\\n!Paragraph methodsFor: 'indicating'!\\noutline \\n\\t\\\"Display a border around the visible area in which the receiver presents \\n\\tits text.\\\"\\n\\n\\tclippingRectangle bottom <= compositionRectangle bottom\\n\\t ifTrue: [Display \\n\\t\\t\\t\\tborder: (clippingRectangle intersect: compositionRectangle) \\n\\t\\t\\t\\twidth: 2]\\n\\t ifFalse: [Display \\n\\t\\t\\t\\tborder: (clippingRectangle intersect: destinationForm boundingBox)\\n\\t\\t\\t\\twidth: 2].\\n\\t! !\\n\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollBy: heightToMove \\n\\t^ self scrollBy: heightToMove withSelectionFrom: nil to: nil! !\\n\\n!Paragraph methodsFor: 'scrolling' stamp: 'hmm 9/16/2000 21:30'!\\nscrollBy: heightToMove withSelectionFrom: startBlock to: stopBlock \\n\\t\\\"Translate the composition rectangle up (dy<0) by heightToMove.\\n\\tRepainting text as necessary, and selection if blocks not nil.\\n\\tReturn true unless scrolling limits have been reached.\\\"\\n\\t| max min amount |\\n\\tmax _ 0 max: \\\"cant scroll up more than dist to (top of) bottom line\\\"\\n\\t\\tcompositionRectangle bottom - textStyle lineGrid - clippingRectangle top.\\n\\tmin _ 0 min: \\\"cant scroll down more than top is above clipRect\\\"\\n\\t\\tcompositionRectangle top - clippingRectangle top.\\n\\tamount _ ((heightToMove truncateTo: textStyle lineGrid) min: max) max: min.\\n\\tamount ~= 0\\n\\t\\tifTrue: [destinationForm deferUpdatesIn: clippingRectangle while: [\\n\\t\\t\\t\\t\\tself scrollUncheckedBy: amount\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: startBlock to: stopBlock].\\n\\t\\t\\t\\t^ true]\\n\\t\\tifFalse: [^ false]! !\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollDelta\\n\\t\\\"By comparing this before and after, you know if scrolling happened\\\"\\n\\t^ clippingRectangle top - compositionRectangle top! !\\n\\n!Paragraph methodsFor: 'scrolling'!\\nscrollUncheckedBy: heightToMove withSelectionFrom: startBlock to: stopBlock \\n\\t\\\"Scroll by the given amount. Copy bits where possible, display the rest.\\n\\tIf selection blocks are not nil, then select the newly visible text as well.\\\"\\n\\t| savedClippingRectangle delta |\\n\\tdelta _ 0 @ (0 - heightToMove).\\n\\tcompositionRectangle _ compositionRectangle translateBy: delta.\\n\\tstartBlock == nil ifFalse:\\n\\t\\t[startBlock moveBy: delta.\\n\\t\\tstopBlock moveBy: delta].\\n\\tsavedClippingRectangle _ clippingRectangle.\\n\\tclippingRectangle _ clippingRectangle intersect: Display boundingBox.\\n\\theightToMove abs >= clippingRectangle height\\n\\t ifTrue: \\n\\t\\t[\\\"Entire visible region must be repainted\\\"\\n\\t\\tself displayLines: (1 to: lastLine) affectedRectangle: clippingRectangle]\\n\\t ifFalse:\\n\\t\\t[\\\"Copy bits where possible / display the rest\\\"\\n\\t\\tdestinationForm\\n\\t\\t\\tcopyBits: clippingRectangle from: destinationForm\\n\\t\\t\\tat: clippingRectangle topLeft + delta\\n\\t\\t\\tclippingBox: clippingRectangle\\n\\t\\t\\trule: Form over fillColor: nil.\\n\\t\\t\\\"Set clippingRectangle to 'vacated' area for lines 'pulled' into view.\\\"\\n\\t\\tclippingRectangle _ heightToMove < 0\\n\\t\\t\\tifTrue: \\\"On the top\\\"\\n\\t\\t\\t\\t[clippingRectangle topLeft corner: clippingRectangle topRight + delta]\\n\\t\\t\\tifFalse: \\\"At the bottom\\\"\\n\\t\\t\\t\\t[clippingRectangle bottomLeft + delta corner: clippingRectangle bottomRight].\\n\\t\\tself displayLines: (1 to: lastLine) \\\"Refresh vacated region\\\"\\n\\t\\t\\taffectedRectangle: clippingRectangle].\\n\\tstartBlock == nil ifFalse:\\n\\t\\t[self reverseFrom: startBlock to: stopBlock].\\n\\t\\\"And restore the clippingRectangle to its original value. \\\"\\n\\tclippingRectangle _ savedClippingRectangle! !\\n\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'ar 5/28/2000 12:10'!\\ncaretFormForDepth: depth\\n\\t\\\"Return a caret form for the given depth.\\\"\\n\\t\\\"(Paragraph new caretFormForDepth: Display depth) displayOn: Display at: 0@0 rule: Form reverse\\\"\\n\\n\\t| box f bb map |\\n\\tbox _ CaretForm boundingBox.\\n\\tf _ Form extent: box extent depth: depth.\\n\\tmap _ (Color cachedColormapFrom: CaretForm depth to: depth) copy.\\n\\tmap at: 1 put: (Color transparent pixelValueForDepth: depth).\\n\\tmap at: 2 put: (Color quickHighLight: depth) first. \\\"pixel value for reversing\\\"\\n\\tbb _ BitBlt current toForm: f.\\n\\tbb\\n\\t\\tsourceForm: CaretForm;\\n\\t\\tsourceRect: box;\\n\\t\\tdestOrigin: 0@0;\\n\\t\\tcolorMap: map;\\n \\t\\tcombinationRule: Form over;\\n\\t\\tcopyBits.\\n\\t^ f! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'dvf 10/1/2003 13:28'!\\nclickAt: clickPoint for: model controller: aController\\n\\t\\\"Give sensitive text a chance to fire. Display flash: (100@100 extent: 100@100).\\\"\\n\\t| startBlock action range box boxes |\\n\\taction _ false.\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\t(text attributesAt: startBlock stringIndex forStyle: textStyle) \\n\\t\\tdo: [:att | att mayActOnClick ifTrue:\\n\\t\\t\\t\\t[range _ text rangeOf: att startingAt: startBlock stringIndex.\\n\\t\\t\\t\\tboxes _ self selectionRectsFrom: (self characterBlockForIndex: range first) \\n\\t\\t\\t\\t\\t\\t\\tto: (self characterBlockForIndex: range last+1).\\n\\t\\t\\t\\tbox _ boxes detect: [:each | each containsPoint: clickPoint]\\n\\t\\t\\t\\t\\t\\t\\tifNone: [^ action].\\n\\t\\t\\t\\tUtilities awaitMouseUpIn: box repeating: []\\n\\t\\t\\t\\t\\tifSucceed: [aController terminateAndInitializeAround:\\n\\t\\t\\t\\t\\t\\t\\t\\t[(att actOnClickFor: model in: self at: clickPoint editor: aController) ifTrue: [action _ true]]]]].\\n\\t^ action! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nextendSelectionAt: beginBlock endBlock: endBlock \\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes.\\\"\\n\\t\\n\\t(self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock\\n\\t\\tifTrue: [^self mouseMovedFrom: beginBlock \\n\\t\\t\\t\\t\\tpivotBlock: endBlock\\n\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\tifFalse: [^self mouseMovedFrom: endBlock \\n\\t\\t\\t\\t\\tpivotBlock: beginBlock\\n\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'th 9/19/2002 17:27'!\\nextendSelectionMark: markBlock pointBlock: pointBlock \\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes.\\\"\\n\\ttrue \\n\\t\\tifTrue:[^self mouseMovedFrom: pointBlock\\n\\t\\t\\t\\t\\tpivotBlock: markBlock\\n\\t\\t\\t\\t\\tshowingCaret:(pointBlock = markBlock)]\\n\\t\\tifFalse:\\n\\t\\t[\\t| beginBlock endBlock |\\n\\t\\t\\tbeginBlock _ markBlock min: pointBlock.\\n\\t\\t\\tendBlock _ markBlock max: endBlock.\\n\\t\\n\\t\\t\\t(self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock\\n\\t\\t\\t\\tifTrue: [^self mouseMovedFrom: beginBlock \\n\\t\\t\\t\\t\\t\\t\\tpivotBlock: endBlock\\n\\t\\t\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\t\\t\\tifFalse: [^self mouseMovedFrom: endBlock \\n\\t\\t\\t\\t\\t\\t\\tpivotBlock: beginBlock\\n\\t\\t\\t\\t\\t\\t\\tshowingCaret: (beginBlock = endBlock)]\\n\\t\\t]\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'jm 7/1/1999 12:31'!\\nhiliteRect: rect\\n\\n\\t| highlightColor |\\n\\thighlightColor _ Color quickHighLight: destinationForm depth.\\n\\trect ifNotNil: [\\n\\t\\tdestinationForm\\n\\t\\t\\tfill: rect\\n\\t\\t\\trule: Form reverse\\n\\t\\t\\tfillColor: highlightColor.\\n\\t\\t\\\"destinationForm\\n\\t\\t\\tfill: (rect translateBy: 1@1)\\n\\t\\t\\trule: Form reverse\\n\\t\\t\\tfillColor: highlightColor\\\" ].\\n! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'jm 7/8/97 12:25'!\\nmouseMovedFrom: beginBlock pivotBlock: pivotBlock showingCaret: caretOn \\n\\t| startBlock stopBlock showingCaret |\\n\\tstopBlock _ startBlock _ beginBlock.\\n\\tshowingCaret _ caretOn.\\n\\t[Sensor redButtonPressed]\\n\\t\\twhileTrue: \\n\\t\\t\\t[stopBlock _ self characterBlockAtPoint: Sensor cursorPoint.\\n\\t\\t\\tstopBlock = startBlock\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[showingCaret\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[showingCaret _ false.\\n\\t\\t\\t\\t\\t\\t\\tself reverseFrom: pivotBlock to: pivotBlock].\\n\\t\\t\\t((startBlock >= pivotBlock and: [stopBlock >= pivotBlock])\\n\\t\\t\\t\\tor: [startBlock <= pivotBlock and: [stopBlock <= pivotBlock]])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[self reverseFrom: startBlock to: stopBlock.\\n\\t\\t\\t\\t\\tstartBlock _ stopBlock]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[self reverseFrom: startBlock to: pivotBlock.\\n\\t\\t\\t\\t\\tself reverseFrom: pivotBlock to: stopBlock.\\n\\t\\t\\t\\t\\tstartBlock _ stopBlock].\\n\\t\\t\\t(clippingRectangle containsRect: stopBlock) ifFalse:\\n\\t\\t\\t\\t[stopBlock top < clippingRectangle top\\n\\t\\t\\t\\tifTrue: [self scrollBy: stopBlock top - clippingRectangle top\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: pivotBlock to: stopBlock]\\n\\t\\t\\t\\tifFalse: [self scrollBy: stopBlock bottom + textStyle lineGrid - clippingRectangle bottom\\n\\t\\t\\t\\t\\t\\twithSelectionFrom: pivotBlock to: stopBlock]]]].\\n\\tpivotBlock = stopBlock ifTrue:\\n\\t\\t[showingCaret ifFalse: \\\"restore caret\\\"\\n\\t\\t\\t[self reverseFrom: pivotBlock to: pivotBlock]].\\n\\t^ Array with: pivotBlock with: stopBlock! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nmouseSelect\\n\\t\\\"Answer with an Array of two CharacterBlocks that represent the text \\n\\tselection that the user makes. Return quickly if the button is noticed up\\n\\tto make double-click more responsive.\\\"\\n\\n\\t| pivotBlock startBlock stopBlock origPoint stillDown |\\n\\tstillDown _ Sensor redButtonPressed.\\n\\tpivotBlock _ startBlock _ stopBlock _\\n\\t\\tself characterBlockAtPoint: (origPoint _ Sensor cursorPoint).\\n\\tstillDown _ stillDown and: [Sensor redButtonPressed].\\n\\tself reverseFrom: startBlock to: startBlock.\\n\\t[stillDown and: [Sensor cursorPoint = origPoint]] whileTrue:\\n\\t\\t[stillDown _ Sensor redButtonPressed].\\n\\t(stillDown and: [clippingRectangle containsPoint: Sensor cursorPoint])\\n\\t\\tifFalse: [^Array with: pivotBlock with: stopBlock].\\n\\t^ self mouseMovedFrom: startBlock \\n\\t\\tpivotBlock: pivotBlock\\n\\t\\tshowingCaret: true! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nmouseSelect: clickPoint \\n\\t\\\"Track text selection and answer with an Array of two CharacterBlocks.\\\"\\n\\t| startBlock |\\n\\tstartBlock _ self characterBlockAtPoint: clickPoint.\\n\\tself reverseFrom: startBlock to: startBlock.\\n\\t^ self mouseMovedFrom: startBlock \\n\\t\\tpivotBlock: startBlock\\n\\t\\tshowingCaret: true! !\\n\\n!Paragraph methodsFor: 'selecting'!\\nreverseFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Reverse area between the two character blocks given as arguments.\\\"\\n\\t| visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline caret |\\n\\tcharacterBlock1 = characterBlock2 ifTrue:\\n\\t\\t[lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex.\\n\\t\\tbaseline _ lineNo = 0 ifTrue: [textStyle baseline]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [(lines at: lineNo) baseline].\\n\\t\\tcaret _ self caretFormForDepth: Display depth.\\n\\t\\t^ caret \\\"Use a caret to indicate null selection\\\"\\n\\t\\t\\t\\tdisplayOn: destinationForm\\n\\t\\t\\t\\tat: characterBlock1 topLeft + (-3 @ baseline)\\n\\t\\t\\t\\tclippingBox: clippingRectangle\\n\\t\\t\\t\\trule: (false \\\"Display depth>8\\\" ifTrue: [9 \\\"not-reverse\\\"]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [Form reverse])\\n\\t\\t\\t\\tfillColor: nil].\\n\\tvisibleRectangle _ \\n\\t\\t(clippingRectangle intersect: compositionRectangle)\\n\\t\\t\\t\\\"intersect: destinationForm boundingBox\\\" \\\"not necessary\\\".\\n\\tcharacterBlock1 top = characterBlock2 top\\n\\t\\tifTrue: [characterBlock1 left < characterBlock2 left\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft corner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft corner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\tifFalse: [characterBlock1 top < characterBlock2 top\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\tcharacterBlock1 bottom = characterBlock2 top\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 bottom\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 top \\n\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\tcharacterBlock1 top = characterBlock2 bottom\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]].\\n\\tself hiliteRect: initialRectangle.\\n\\tself hiliteRect: interiorRectangle.\\n\\tself hiliteRect: finalRectangle.! !\\n\\n!Paragraph methodsFor: 'selecting' stamp: 'di 12/1/97 04:43'!\\nselectionRectsFrom: characterBlock1 to: characterBlock2 \\n\\t\\\"Return an array of rectangles representing the area between the two character blocks given as arguments.\\\"\\n\\t| visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline |\\n\\tcharacterBlock1 = characterBlock2 ifTrue:\\n\\t\\t[lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex.\\n\\t\\tbaseline _ lineNo = 0 ifTrue: [textStyle baseline]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [(lines at: lineNo) baseline].\\n\\t\\t^ Array with: (characterBlock1 topLeft extent: 1 @ baseline)].\\n\\tvisibleRectangle _ clippingRectangle intersect: compositionRectangle.\\n\\tcharacterBlock1 top = characterBlock2 top\\n\\t\\tifTrue: [characterBlock1 left < characterBlock2 left\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft corner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft corner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\tifFalse: [characterBlock1 top < characterBlock2 top\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t(characterBlock1 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\tcharacterBlock1 bottom = characterBlock2 top\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 bottom\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 top \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock2 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[initialRectangle _ \\n\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock1 top \\n\\t\\t\\t\\t\\t\\t\\tcorner: characterBlock1 bottomLeft)\\n\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\tcharacterBlock1 top = characterBlock2 bottom\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[finalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[interiorRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(visibleRectangle left @ characterBlock2 bottom \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right @ characterBlock1 top)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle.\\n\\t\\t\\t\\t\\t\\t\\tfinalRectangle _ \\n\\t\\t\\t\\t\\t\\t\\t\\t(characterBlock2 topLeft \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcorner: visibleRectangle right \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t@ characterBlock2 bottom)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tintersect: visibleRectangle]]].\\n\\t^ (Array with: initialRectangle with: interiorRectangle with: finalRectangle)\\n\\t\\t\\tselect: [:rect | rect notNil]! !\\n\\n\\n!Paragraph methodsFor: 'utilities'!\\nclearVisibleRectangle \\n\\t\\\"Display the area in which the receiver presents its text so that the area \\n\\tis all one tone--in this case, all white.\\\"\\n\\n\\tdestinationForm\\n\\t fill: clippingRectangle\\n\\t rule: rule\\n\\t fillColor: self backgroundColor! !\\n\\n!Paragraph methodsFor: 'utilities'!\\ndeepCopy\\n\\t\\\"Don't want to copy the destForm (Display) or fonts in the TextStyle. 9/13/96 tk\\\"\\n\\n\\t| new |\\n\\tnew _ self copy.\\n\\tnew textStyle: textStyle copy.\\n\\tnew destinationForm: destinationForm.\\n\\tnew lines: lines copy.\\n\\tnew text: text deepCopy.\\n\\t^ new! !\\n\\n!Paragraph methodsFor: 'utilities'!\\ndestinationForm: destForm\\n\\tdestinationForm _ destForm! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nfit\\n\\t\\\"Make the bounding rectangle of the receiver contain all the text without \\n\\tchanging the width of the receiver's composition rectangle.\\\"\\n\\n\\t[(self lineIndexOfTop: clippingRectangle top) = 1]\\n\\t\\twhileFalse: [self scrollBy: (0-1)*textStyle lineGrid].\\n\\tself updateCompositionHeight.\\n\\tclippingRectangle _ clippingRectangle withBottom: compositionRectangle bottom! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nlines: lineArray\\n\\tlines _ lineArray! !\\n\\n!Paragraph methodsFor: 'utilities'!\\nvisibleRectangle \\n\\t\\\"May be less than the clippingRectangle if text ends part way down.\\n\\tAlso some fearful history includes Display intersection;\\n\\tit shouldn't be necessary\\\"\\n\\n\\t^ (clippingRectangle intersect: compositionRectangle)\\n\\t\\tintersect: destinationForm boundingBox! !\\n\\n\\n!Paragraph methodsFor: 'private'!\\nbottomAtLineIndex: lineIndex \\n\\t\\\"Answer the bottom y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\tlastLine = 0 ifTrue: [^ y + textStyle lineGrid].\\n\\t1 to: (lineIndex min: lastLine) do:\\n\\t\\t[:i | y _ y + (lines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'tk 9/30/96'!\\ncompositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint\\n\\n\\tcompositionRectangle _ compositionRect copy.\\n\\ttext _ aText.\\n\\ttextStyle _ aTextStyle.\\n\\trule _ DefaultRule.\\n\\tmask _ nil.\\t\\t\\\"was DefaultMask \\\"\\n\\tmarginTabsLevel _ 0.\\n\\tdestinationForm _ Display.\\n\\toffset _ aPoint.\\n\\t^self composeAll! !\\n\\n!Paragraph methodsFor: 'private'!\\ncompositionRectangleDelta\\n\\t\\\"A handy number -- mostly for scrolling.\\\"\\n\\n\\t^compositionRectangle top - clippingRectangle top! !\\n\\n!Paragraph methodsFor: 'private'!\\ndisplayLines: linesInterval \\n\\t^ self displayLines: linesInterval\\n\\t\\taffectedRectangle: self visibleRectangle! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'yo 1/23/2003 22:48'!\\ndisplayLines: linesInterval affectedRectangle: affectedRectangle\\n\\t\\\"This is the first level workhorse in the display portion of the TextForm routines.\\n\\tIt checks to see which lines in the interval are actually visible, has the\\n\\tCharacterScanner display only those, clears out the areas in which display will\\n\\toccur, and clears any space remaining in the visibleRectangle following the space\\n\\toccupied by lastLine.\\\"\\n\\n\\t| lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |\\n\\n\\t\\\"Save some time by only displaying visible lines\\\"\\n\\tfirstLineIndex _ self lineIndexOfTop: affectedRectangle top.\\n\\tfirstLineIndex < linesInterval first ifTrue: [firstLineIndex _ linesInterval first].\\n\\tlastLineIndex _ self lineIndexOfTop: affectedRectangle bottom - 1.\\n\\tlastLineIndex > linesInterval last ifTrue:\\n\\t\\t\\t[linesInterval last > lastLine\\n\\t\\t \\t\\tifTrue: [lastLineIndex _ lastLine]\\n\\t\\t \\t\\tifFalse: [lastLineIndex _ linesInterval last]].\\n\\tlastLineIndexBottom _ (self bottomAtLineIndex: lastLineIndex).\\n\\t((Rectangle \\n\\t\\torigin: affectedRectangle left @ (topY _ self topAtLineIndex: firstLineIndex) \\n\\t\\tcorner: affectedRectangle right @ lastLineIndexBottom)\\n\\t intersects: affectedRectangle)\\n\\t\\tifTrue: [ \\\" . . . (skip to clear-below if no lines displayed)\\\"\\n\\t\\t\\t\\tMultiDisplayScanner new\\n\\t\\t\\t\\t\\tdisplayLines: (firstLineIndex to: lastLineIndex)\\n\\t\\t\\t\\t\\tin: self clippedBy: affectedRectangle].\\n\\tlastLineIndex = lastLine ifTrue: \\n\\t\\t [destinationForm \\\"Clear out white space below last line\\\"\\n\\t\\t \\tfill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)\\n\\t\\t\\t\\tcorner: affectedRectangle bottomRight)\\n\\t\\t \\trule: rule fillColor: self backgroundColor]! !\\n\\n!Paragraph methodsFor: 'private'!\\ndisplayOn: aDisplayMedium lines: lineInterval\\n\\n\\t| saveDestinationForm |\\n\\tsaveDestinationForm _ destinationForm.\\n\\tdestinationForm _ aDisplayMedium.\\n\\tself displayLines: lineInterval.\\n\\tdestinationForm _ saveDestinationForm! !\\n\\n!Paragraph methodsFor: 'private'!\\nleftMarginForCompositionForLine: lineIndex \\n\\t\\\"Build the left margin for composition of a line. Depends upon\\n\\tmarginTabsLevel and the indent.\\\"\\n\\n\\t| indent |\\n\\tlineIndex = 1\\n\\t\\tifTrue: [indent _ textStyle firstIndent]\\n\\t\\tifFalse: [indent _ textStyle restIndent].\\n\\t^indent + (textStyle leftMarginTabAt: marginTabsLevel)! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'ar 12/15/2001 23:29'!\\nleftMarginForDisplayForLine: lineIndex alignment: alignment\\n\\t\\\"Build the left margin for display of a line. Depends upon\\n\\tleftMarginForComposition, compositionRectangle left and the alignment.\\\"\\n\\n\\t| pad |\\n\\t(alignment = LeftFlush or: [alignment = Justified])\\n\\t\\tifTrue: \\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex)].\\n\\t\\\"When called from character location code and entire string has been cut,\\n\\tthere are no valid lines, hence following nil check.\\\"\\n\\t(lineIndex <= lines size and: [(lines at: lineIndex) notNil])\\n\\t\\tifTrue: \\n\\t\\t\\t[pad _ (lines at: lineIndex) paddingWidth]\\n\\t\\tifFalse: \\n\\t\\t\\t[pad _ \\n\\t\\t\\t\\tcompositionRectangle width - textStyle firstIndent - textStyle rightIndent].\\n\\talignment = Centered \\n\\t\\tifTrue: \\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex) + (pad // 2)].\\n\\talignment = RightFlush \\n\\t\\tifTrue:\\n\\t\\t\\t[^compositionRectangle left \\n\\t\\t\\t\\t+ (self leftMarginForCompositionForLine: lineIndex) + pad].\\n\\tself error: ['no such alignment']! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineAt: indexInteger put: aTextLineInterval \\n\\t\\\"Store a line, track last, and grow lines if necessary.\\\"\\n\\tindexInteger > lastLine ifTrue: [lastLine _ indexInteger].\\n\\tlastLine > lines size ifTrue: [lines _ lines , (Array new: lines size)].\\n\\t^lines at: indexInteger put: aTextLineInterval! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineIndexOfCharacterIndex: characterIndex \\n\\t\\\"Answer the line index for a given characterIndex.\\\"\\n\\n\\t1 to: lastLine do: \\n\\t\\t[:lineIndex | \\n\\t\\t(lines at: lineIndex) last >= characterIndex ifTrue: [^lineIndex]].\\n\\t^lastLine! !\\n\\n!Paragraph methodsFor: 'private'!\\nlineIndexOfTop: top \\n\\t\\\"Answer the line index at a given top y.\\\"\\n\\t| y line |\\n\\tlastLine = 0 ifTrue: [^ 1].\\n\\ty _ compositionRectangle top.\\n\\t1 to: lastLine do:\\n\\t\\t[:i | line _ lines at: i.\\n\\t\\t(y _ y + line lineHeight) > top ifTrue: [^ i]].\\n\\t^ lastLine\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\nlines\\n\\n\\t^lines! !\\n\\n!Paragraph methodsFor: 'private'!\\nmoveBy: delta\\n\\tcompositionRectangle _ compositionRectangle translateBy: delta.\\n\\tclippingRectangle _ clippingRectangle translateBy: delta.\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\nrightMarginForComposition\\n\\t\\\"Build the right margin for a line. Depends upon compositionRectangle\\n\\twidth, marginTabsLevel, and right indent.\\\"\\n\\n\\t^compositionRectangle width \\n\\t\\t- (textStyle rightMarginTabAt: marginTabsLevel) \\n\\t\\t- textStyle rightIndent! !\\n\\n!Paragraph methodsFor: 'private'!\\nrightMarginForDisplay \\n\\t\\\"Build the right margin for a line. Depends upon compositionRectangle\\n\\trightSide, marginTabsLevel, and right indent.\\\"\\n\\n\\t^compositionRectangle right - \\n\\t\\ttextStyle rightIndent - (textStyle rightMarginTabAt: marginTabsLevel)! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle \\n\\t\\\"Set text and adjust bounding rectangles to fit.\\\"\\n\\n\\t| shrink compositionWidth unbounded |\\n\\tunbounded _ Rectangle origin: 0 @ 0 extent: 9999@9999.\\n\\tcompositionWidth _ self\\n\\t\\tsetWithText: aText style: aTextStyle compositionRectangle: unbounded clippingRectangle: unbounded.\\n\\tcompositionRectangle _ compositionRectangle withWidth: compositionWidth.\\n\\tclippingRectangle _ compositionRectangle copy.\\n\\tshrink _ unbounded width - compositionWidth.\\n\\t\\\"Shrink padding widths accordingly\\\"\\n\\t1 to: lastLine do:\\n\\t\\t[:i | (lines at: i) paddingWidth: (lines at: i) paddingWidth - shrink]! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect \\n\\t\\\"Set text and using supplied parameters. Answer max composition width.\\\"\\n\\n\\tclippingRectangle _ clipRect copy.\\n\\t^self\\n\\t\\tcompositionRectangle: compRect\\n\\t\\ttext: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\toffset: 0 @ 0! !\\n\\n!Paragraph methodsFor: 'private'!\\nsetWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: cf backColor: cb\\n\\t\\\"Set text and using supplied parameters. Answer max composition width.\\\"\\n\\n\\tclippingRectangle _ clipRect copy.\\n\\tself foregroundColor: cf backgroundColor: cb.\\n\\t^ self\\n\\t\\tcompositionRectangle: compRect\\n\\t\\ttext: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\toffset: 0 @ 0! !\\n\\n!Paragraph methodsFor: 'private'!\\ntopAtLineIndex: lineIndex \\n\\t\\\"Answer the top y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\tlastLine = 0 ifTrue: [lineIndex > 0 ifTrue: [^ y + textStyle lineGrid]. ^ y].\\n\\t1 to: (lineIndex-1 min: lastLine) do:\\n\\t\\t[:i | y _ y + (lines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\ntopAtLineIndex: lineIndex using: otherLines and: otherLastLine\\n\\t\\\"Answer the top y of given line.\\\"\\n\\t| y |\\n\\ty _ compositionRectangle top.\\n\\totherLastLine = 0 ifTrue: [^ y].\\n\\t1 to: (lineIndex-1 min: otherLastLine) do:\\n\\t\\t[:i | y _ y + (otherLines at: i) lineHeight].\\n\\t^ y\\n! !\\n\\n!Paragraph methodsFor: 'private'!\\ntrimLinesTo: lastLineInteger\\n\\n\\t(lastLineInteger + 1 to: lastLine) do: [:i | lines at: i put: nil].\\n\\t(lastLine _ lastLineInteger) < (lines size // 2) \\n\\t\\tifTrue: [lines _ lines copyFrom: 1 to: lines size - (lines size // 2)]! !\\n\\n!Paragraph methodsFor: 'private'!\\nupdateCompositionHeight\\n\\t\\\"Mainly used to insure that intersections with compositionRectangle work.\\\" \\n\\n\\tcompositionRectangle _ compositionRectangle withHeight:\\n\\t\\t(self bottomAtLineIndex: lastLine) - compositionRectangle top.\\n\\t(text size ~= 0 and: [(text at: text size) = CR])\\n\\t\\tifTrue: [compositionRectangle _ compositionRectangle withHeight:\\n\\t\\t\\t\\t\\tcompositionRectangle height + (lines at: lastLine) lineHeight]! !\\n\\n!Paragraph methodsFor: 'private' stamp: 'di 8/30/97 11:14'!\\nwithClippingRectangle: clipRect do: aBlock\\n\\t| saveClip |\\n\\tsaveClip _ clippingRectangle.\\n\\tclippingRectangle _ clipRect.\\n\\t\\taBlock value.\\n\\tclippingRectangle _ saveClip! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParagraph class\\n\\tinstanceVariableNames: ''!\\n\\n!Paragraph class methodsFor: 'examples' stamp: 'tk 9/30/96'!\\nexample\\n\\t\\\"This simple example illustrates how to display a few lines of text on the screen at the current cursor point. \\n\\tFixed. \\\"\\n\\n\\t| para point |\\n\\tpoint _ Sensor waitButton.\\n\\tpara _ 'This is the first line of characters\\nand this is the second line.' asParagraph.\\n\\tpara displayOn: Display at: point.\\n\\n\\t\\\"Paragraph example\\\"! !\\n\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nnew\\n\\t\\\"Do not allow an uninitialized view. Create with text that has no\\n\\tcharacters.\\\"\\n\\n\\t^self withText: '' asText! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText \\n\\t\\\"Answer an instance of me with text set to aText and style set to the \\n\\tsystem's default text style.\\\"\\n\\n\\t^self withText: aText style: DefaultTextStyle copy! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText style: aTextStyle \\n\\t\\\"Answer an instance of me with text set to aText and style set to \\n\\taTextStyle.\\\"\\n\\n\\t^super new setWithText: aText style: aTextStyle! !\\n\\n!Paragraph class methodsFor: 'instance creation'!\\nwithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: c1 backColor: c2\\n\\t\\\"Answer an instance of me with text set to aText and style set to \\n\\taTextStyle, composition rectangle is compRect and the clipping rectangle \\n\\tis clipRect.\\\"\\n\\t| para |\\n\\tpara _ super new.\\n\\tpara setWithText: aText\\n\\t\\tstyle: aTextStyle\\n\\t\\tcompositionRectangle: compRect\\n\\t\\tclippingRectangle: clipRect\\n\\t\\tforeColor: c1 backColor: c2.\\n\\t^para! !\\nScrollController subclass: #ParagraphEditor\\n\\tinstanceVariableNames: 'paragraph startBlock stopBlock beginTypeInBlock emphasisHere initialText selectionShowing otherInterval lastParentLocation'\\n\\tclassVariableNames: 'ChangeText CmdActions FindText Keyboard ShiftCmdActions UndoInterval UndoMessage UndoParagraph UndoSelection Undone'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Kernel-ST80 Remnants'!\\n!ParagraphEditor commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!ParagraphEditor methodsFor: 'accessing' stamp: 'tk 4/21/1998 09:55'!\\ninitialText\\n\\t^ initialText! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nreplace: oldInterval with: newText and: selectingBlock \\n\\t\\\"Replace the text in oldInterval with newText and execute selectingBlock to establish the new selection. Create an undoAndReselect:redoAndReselect: undoer to allow perfect undoing.\\\"\\n\\n\\t| undoInterval |\\n\\tundoInterval _ self selectionInterval.\\n\\tundoInterval = oldInterval ifFalse: [self selectInterval: oldInterval].\\n\\tUndoSelection _ self selection.\\n\\tself zapSelectionWith: newText.\\n\\tselectingBlock value.\\n\\totherInterval _ self selectionInterval.\\n\\tself undoer: #undoAndReselect:redoAndReselect: with: undoInterval with: otherInterval! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nreplaceSelectionWith: aText\\n\\t\\\"Remember the selection text in UndoSelection.\\n\\t Deselect, and replace the selection text by aText.\\n\\t Remember the resulting selectionInterval in UndoInterval and PriorInterval.\\n\\t Set up undo to use UndoReplace.\\\"\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [^self zapSelectionWith: aText]. \\\"called from old code\\\"\\n\\tUndoSelection _ self selection.\\n\\tself zapSelectionWith: aText.\\n\\tself undoer: #undoReplace! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\nsetSearch: aString\\n\\t\\\"Set the FindText and ChangeText to seek aString; except if already seeking aString, leave ChangeText alone so again will repeat last replacement.\\\"\\n\\n\\tFindText string = aString\\n\\t\\tifFalse: [FindText _ ChangeText _ aString asText]! !\\n\\n!ParagraphEditor methodsFor: 'accessing'!\\ntext\\n\\t\\\"Answer the text of the paragraph being edited.\\\"\\n\\n\\t^paragraph text! !\\n\\n!ParagraphEditor methodsFor: 'accessing' stamp: 'jm 3/18/98 20:38'!\\nuserHasEdited\\n\\t\\\"Note that the user has edited my text. Here it is just a noop so that the Character Recognizer won't fail when used with a vanilla ParagrahEditor.\\\"\\n! !\\n\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'!\\nhasCaret\\n\\t^self markBlock = self pointBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'!\\nhasSelection\\n\\t^self hasCaret not! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:13'!\\nmark\\n\\t^ self markBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\nmarkBlock\\n\\t^ stopBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\nmarkBlock: aCharacterBlock\\n\\tstopBlock _ aCharacterBlock.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'!\\nmarkIndex\\n\\t^ self markBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\npointBlock\\n\\t^ startBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'!\\npointBlock: aCharacterBlock\\n\\tstartBlock _ aCharacterBlock.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'!\\npointIndex\\n\\t^ self pointBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'yo 7/31/2004 16:27'!\\nselection\\n\\t\\\"Answer the text in the paragraph that is currently selected.\\\"\\n\\n\\t| t |\\n\\tt _ paragraph text copyFrom: self startIndex to: self stopIndex - 1.\\n\\tt string isOctetString ifTrue: [t asOctetStringText].\\n\\t^ t.\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:10'!\\nselectionAsStream\\n\\t\\\"Answer a ReadStream on the text in the paragraph that is currently \\n\\tselected.\\\"\\n\\n\\t^ReadWriteStream\\n\\t\\ton: paragraph string\\n\\t\\tfrom: self startIndex\\n\\t\\tto: self stopIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 16:18'!\\nselectionInterval\\n\\t\\\"Answer the interval that is currently selected.\\\"\\n\\n\\t^self startIndex to: self stopIndex - 1 ! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'!\\nsetMark: anIndex\\n\\tself markBlock: (paragraph characterBlockForIndex: anIndex)\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'!\\nsetPoint: anIndex\\n\\tself pointBlock: (paragraph characterBlockForIndex: anIndex)\\n! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:10'!\\nstartBlock\\n\\t^ self pointBlock min: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'!\\nstartBlock: aCharacterBlock\\n\\tself markBlock: aCharacterBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'!\\nstartIndex\\n\\t^ self startBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:14'!\\nstopBlock\\n\\t^ self pointBlock max: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'!\\nstopBlock: aCharacterBlock\\n\\tself pointBlock: aCharacterBlock! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'!\\nstopIndex\\n\\t^ self stopBlock stringIndex! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:23'!\\nunselect\\n\\tself markBlock: self pointBlock copy.! !\\n\\n!ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:12'!\\nzapSelectionWith: aText\\n\\t\\\"Deselect, and replace the selection text by aText.\\n\\t Remember the resulting selectionInterval in UndoInterval and otherInterval.\\n\\t Do not set up for undo.\\\"\\n\\n\\t| start stop |\\n\\tself deselect.\\n\\tstart _ self startIndex.\\n\\tstop _ self stopIndex.\\n\\t(aText isEmpty and: [stop > start]) ifTrue:\\n\\t\\t[\\\"If deleting, then set emphasisHere from 1st character of the deletion\\\"\\n\\t\\temphasisHere _ (paragraph text attributesAt: start forStyle: paragraph textStyle)\\n\\t\\t\\t\\t\\tselect: [:att | att mayBeExtended]].\\n\\t(start = stop and: [aText size = 0]) ifFalse:\\n\\t\\t[paragraph\\n\\t\\t\\treplaceFrom: start\\n\\t\\t\\tto: stop - 1\\n\\t\\t\\twith: aText\\n\\t\\t\\tdisplaying: true.\\n\\t\\tself computeIntervalFrom: start to: start + aText size - 1.\\n\\t\\tUndoInterval _ otherInterval _ self selectionInterval]! !\\n\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'dvf 7/28/2003 14:54'!\\nactivateTextActions\\n\\t(paragraph text attributesAt: startBlock stringIndex) \\n\\t\\tdo: [:att | att actOnClickFor: model in: paragraph]! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'BG 6/1/2003 09:43'!\\nofferMenuFromEsc: aStream\\n sensor keyboard. \\\" consume the character \\\"\\n self yellowButtonActivity.\\n ^true \\\"tell the caller that the character was processed \\\"! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:40'!\\ntotalTextHeight\\n\\n\\t^paragraph boundingBox height! !\\n\\n!ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:33'!\\nvisibleHeight\\n\\n\\t^paragraph clippingRectangle height! !\\n\\n\\n!ParagraphEditor methodsFor: 'controlling'!\\ncontrolInitialize\\n\\n\\tsuper controlInitialize.\\n\\tself recomputeInterval.\\n\\tself initializeSelection.\\n\\tbeginTypeInBlock _ nil! !\\n\\n!ParagraphEditor methodsFor: 'controlling'!\\ncontrolTerminate\\n\\n\\tself closeTypeIn. \\\"Must call to establish UndoInterval\\\"\\n\\tsuper controlTerminate.\\n\\tself deselect! !\\n\\n!ParagraphEditor methodsFor: 'controlling' stamp: 'sma 3/11/2000 15:17'!\\nnormalActivity\\n\\tself processKeyboard.\\n\\tself processMouseButtons! !\\n\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\ndeselect\\n\\t\\\"If the text selection is visible on the screen, reverse its highlight.\\\"\\n\\n\\tselectionShowing ifTrue: [self reverseSelection]! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\ninitializeSelection\\n\\t\\\"Do the initial activity when starting up the receiver. For example, in the \\n\\tParagraphEditor highlight the current selection.\\\"\\n\\n\\tself select! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/20/2002 11:41'!\\nrecomputeInterval\\n\\t\\\"The same characters are selected but their coordinates may have changed.\\\"\\n\\n\\tself computeIntervalFrom: self mark to: self pointIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\nrecomputeSelection\\n\\t\\\"Redetermine the selection according to the start and stop block indices; \\n\\tdo not highlight.\\\"\\n\\n\\tself deselect; recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'BG 12/12/2003 12:50'!\\nreverseSelection\\n\\t\\\"Reverse the valence of the current selection highlighting.\\\"\\n\\tselectionShowing _ selectionShowing not.\\n\\tparagraph reverseFrom: self pointBlock to: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'current selection'!\\nselect\\n\\t\\\"If the text selection is visible on the screen, highlight it.\\\"\\n\\n\\tselectionShowing ifFalse: [self reverseSelection]! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:47'!\\nselectAndScroll\\n\\t\\\"Scroll until the selection is in the view and then highlight it.\\\"\\n\\t| lineHeight deltaY clippingRectangle endBlock |\\n\\tself select.\\n\\tendBlock _ self stopBlock.\\n\\tlineHeight _ paragraph textStyle lineGrid.\\n\\tclippingRectangle _ paragraph clippingRectangle.\\n\\tdeltaY _ endBlock top - clippingRectangle top.\\n\\tdeltaY >= 0 \\n\\t\\tifTrue: [deltaY _ endBlock bottom - clippingRectangle bottom max: 0].\\n\\t\\t\\t\\t\\t\\t\\\"check if stopIndex below bottom of clippingRectangle\\\"\\n\\tdeltaY ~= 0 \\n\\t\\tifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t* deltaY sign]! !\\n\\n!ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:48'!\\nselectAndScrollToTop\\n\\t\\\"Scroll until the selection is in the view and then highlight it.\\\"\\n\\t| lineHeight deltaY clippingRectangle |\\n\\tself select.\\n\\tlineHeight _ paragraph textStyle lineGrid.\\n\\tclippingRectangle _ paragraph clippingRectangle.\\n\\tdeltaY _ self stopBlock top - clippingRectangle top.\\n\\tdeltaY ~= 0 \\n\\t\\tifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t* deltaY sign]! !\\n\\n\\n!ParagraphEditor methodsFor: 'displaying'!\\ndisplay\\n\\t\\\"Redisplay the paragraph.\\\"\\n\\n\\t| selectionState |\\n\\tselectionState _ selectionShowing.\\n\\tself deselect.\\n\\tparagraph foregroundColor: view foregroundColor\\n\\t\\t\\tbackgroundColor: view backgroundColor;\\n\\t\\t\\tdisplayOn: Display.\\n\\tselectionState ifTrue: [self select]! !\\n\\n!ParagraphEditor methodsFor: 'displaying'!\\nflash\\n\\t\\\"Causes the view of the paragraph to complement twice in succession.\\\"\\n\\n\\tparagraph flash! !\\n\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'md 2/13/2006 14:36'!\\ncompileSelectionFor: anObject in: evalContext\\n\\n\\t| methodNode method |\\n\\tmethodNode _ [Compiler new\\n\\t\\tcompileNoPattern: self selectionAsStream\\n\\t\\tin: anObject class\\n\\t\\tcontext: evalContext\\n\\t\\tnotifying: self\\n\\t\\tifFail: [^nil]]\\n\\t\\t\\ton: OutOfScopeNotification\\n\\t\\t\\tdo: [:ex | ex resume: true].\\n\\tmethod _ methodNode generate.\\n\\t^method copyWithTempNames: methodNode tempNames! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:38'!\\ndoIt\\n\\t\\\"Set the context to include pool vars of the model. Then evaluate.\\\"\\n\\t^ self evaluateSelection.\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'gk 3/3/2004 17:15'!\\nevaluateSelection\\n\\t\\\"Treat the current selection as an expression; evaluate it and return the result\\\"\\n\\t| result rcvr ctxt |\\n\\tself lineSelectAndEmptyCheck: [^ ''].\\n\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: [FakeClassPool adopt: model selectedClass. \\\"Include model pool vars if any\\\"\\n\\t\\t\\t\\trcvr _ model doItReceiver.\\n\\t\\t\\t\\tctxt _ model doItContext]\\n\\t\\tifFalse: [rcvr _ ctxt _ nil].\\n\\tresult _ [\\n\\t\\trcvr class evaluatorClass new \\n\\t\\t\\tevaluate: self selectionAsStream\\n\\t\\t\\tin: ctxt\\n\\t\\t\\tto: rcvr\\n\\t\\t\\tnotifying: self\\n\\t\\t\\tifFail: [FakeClassPool adopt: nil. ^ #failedDoit]\\n\\t\\t\\tlogged: true.\\n\\t] \\n\\t\\ton: OutOfScopeNotification \\n\\t\\tdo: [ :ex | ex resume: true].\\n\\tFakeClassPool adopt: nil.\\n\\t^ result! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'acg 12/7/1999 07:53'!\\nexploreIt\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [result explore].\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 9/7/1999 11:25'!\\ninspectIt\\n\\t\\\"1/13/96 sw: minor fixup\\\"\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [result inspect].\\n! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'sd 4/16/2003 11:41'!\\nobjectsReferencingIt\\n\\t\\\"Open a list inspector on all objects that reference the object that results when the current selection is evaluated. \\\"\\n\\t| result |\\n\\tself terminateAndInitializeAround: [\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\tifTrue: [view flash]\\n\\t\\tifFalse: [self systemNavigation\\n\\t\\t\\t\\t\\tbrowseAllObjectReferencesTo: result\\n\\t\\t\\t\\t\\texcept: #()\\n\\t\\t\\t\\t\\tifNone: [:obj | view topView flash]].\\n\\t]! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:52'!\\nprintIt\\n\\t\\\"Treat the current text selection as an expression; evaluate it. Insert the \\n\\tdescription of the result of evaluation after the selection and then make \\n\\tthis description the new text selection.\\\"\\n\\t| result |\\n\\tresult _ self evaluateSelection.\\n\\t((result isKindOf: FakeClassPool) or: [result == #failedDoit])\\n\\t\\t\\tifTrue: [view flash]\\n\\t\\t\\tifFalse: [self afterSelectionInsertAndSelect: result printString]! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'ab 3/23/2005 16:49'!\\ntallyIt\\n\\n\\t^ self tallySelection! !\\n\\n!ParagraphEditor methodsFor: 'do-its' stamp: 'ab 3/23/2005 16:49'!\\ntallySelection\\n\\t\\\"Treat the current selection as an expression; evaluate it and return the time took for this evaluation\\\"\\n\\t| result rcvr ctxt cm v valueAsString |\\n\\tself lineSelectAndEmptyCheck: [^ -1].\\n\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: [FakeClassPool adopt: model selectedClass. \\\"Include model pool vars if any\\\"\\n\\t\\t\\t\\trcvr _ model doItReceiver.\\n\\t\\t\\t\\tctxt _ model doItContext]\\n\\t\\tifFalse: [rcvr _ ctxt _ nil].\\n\\tresult _ [\\n\\t\\tcm := rcvr class evaluatorClass new \\n\\t\\t\\tcompiledMethodFor: self selectionAsStream\\n\\t\\t\\tin: ctxt\\n\\t\\t\\tto: rcvr\\n\\t\\t\\tnotifying: self\\n\\t\\t\\tifFail: [FakeClassPool adopt: nil. ^ #failedDoit]\\n\\t\\t\\tlogged: false.\\n\\t\\tTime millisecondsToRun: \\n\\t\\t\\t[v := cm valueWithReceiver: rcvr arguments: (Array with: ctxt)].\\n\\t] \\n\\t\\ton: OutOfScopeNotification \\n\\t\\tdo: [ :ex | ex resume: true].\\n\\tFakeClassPool adopt: nil.\\n\\n\\t\\\"We do not want to have large result displayed\\\"\\n\\tvalueAsString := v printString.\\n\\t(valueAsString size > 30) ifTrue: [valueAsString := (valueAsString copyFrom: 1 to: 30), '...'].\\n\\tPopUpMenu \\n\\t\\tinform: 'Time to compile and execute: ', result printString, 'ms res: ', valueAsString.\\n! !\\n\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nalign: characterStream \\n\\t\\\"Triggered by Cmd-u; cycle through alignment alternatives. 8/11/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself align.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'hpt 8/5/2004 20:21'!\\nbrowseIt: characterStream \\n\\t\\\"Triggered by Cmd-B; browse the thing represented by the current selection, if plausible. 1/18/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself browseIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nbrowseItHere: characterStream \\n\\t\\\"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\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself browseItHere.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:40'!\\ncancel: characterStream \\n\\t\\\"Cancel unsubmitted changes. Flushes typeahead. 1/12/96 sw\\n\\t 1/22/96 sw: put in control terminate/init\\\"\\n\\n\\tsensor keyboard.\\n\\tself terminateAndInitializeAround: [self cancel].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'dgd 4/4/2006 15:46'!\\nchangeEmphasis: characterStream \\n\\t\\\"Change the emphasis of the current selection or prepare to\\n\\taccept characters with the change in emphasis. Emphasis\\n\\tchange amounts to a font change. Keeps typeahead.\\\"\\n\\t\\n\\t| keyCode attribute oldAttributes index thisSel colors extras |\\n\\n\\t\\\"control 0..9 -> 0..9\\\"\\n\\tkeyCode := ('0123456789-=' indexOf: sensor keyboard ifAbsent: [1]) - 1.\\n\\n\\toldAttributes := paragraph text attributesAt: self pointIndex forStyle: paragraph textStyle.\\n\\tthisSel := self selection.\\n\\n\\t\\\"Decipher keyCodes for Command 0-9...\\\"\\n\\t(keyCode between: 1 and: 5) ifTrue: [\\n\\t\\tattribute := TextFontChange fontNumber: keyCode\\n\\t].\\n\\n\\tkeyCode = 6 ifTrue: [\\n\\t\\t| labels lines | \\n\\t\\tcolors := #(#black #magenta #red #yellow #green #blue #cyan #white ).\\n\\t\\textras := (self class name = #TextMorphEditor and: [(self morph isKindOf: TextMorphForEditView) not])\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"not a system window\\\" #()]\\n\\t\\t\\t\\t\\t\\tifFalse: [#('Link to comment of class' 'Link to definition of class' 'Link to hierarchy of class' 'Link to method' )].\\n\\n\\t\\tPreferences noviceMode ifTrue: [\\n\\t\\t\\tlabels := colors , #('choose color...' ).\\n\\t\\t\\tlines := #()\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tlabels := colors , #('choose color...' 'Do it' 'Print it' ) , extras , #('be a web URL link' 'Edit hidden info' 'Copy hidden info' ).\\n\\t\\t\\tlines := Array with: colors size + 1\\n\\t\\t].\\n\\n\\t\\t\\\"index _ (PopUpMenu labelArray: labels lines: lines) startUp. \\\"\\n\\t\\tindex := UIManager default chooseFrom: labels lines: lines.\\n\\t\\tindex = 0\\n\\t\\t\\tifTrue: [ ^ true].\\n\\t\\t\\t\\n\\t\\tindex <= colors size ifTrue: [\\n\\t\\t\\tattribute := TextColor color: (Color perform: (colors at: index))\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tindex := index - colors size - 1. \\\"Re-number!!!!!!\\\"\\n\\n\\t\\t\\tindex = 0 ifTrue: [\\n\\t\\t\\t\\tattribute := self chooseColor\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 1 ifTrue: [\\n\\t\\t\\t\\tattribute := TextDoIt new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 2 ifTrue: [\\n\\t\\t\\t\\tattribute := TextPrintIt new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\n\\t\\t\\textras size = 0 & (index > 2) ifTrue: [\\n\\t\\t\\t\\tindex := index + 4 \\\"skip those\\\"\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 3 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Comment'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 4 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Definition'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 5 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString with: 'Hierarchy'\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 6 ifTrue: [\\n\\t\\t\\t\\tattribute := TextLink new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\tindex = 7 ifTrue: [\\n\\t\\t\\t\\tattribute := TextURL new.\\n\\t\\t\\t\\tthisSel := attribute analyze: self selection asString\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\tindex = 8 ifTrue: [\\n\\t\\t\\t\\t\\\"Edit hidden info\\\"\\n\\t\\t\\t\\tthisSel := self hiddenInfo. \\\"includes selection\\\"\\n\\t\\t\\t\\tattribute := TextEmphasis normal\\n\\t\\t\\t].\\n\\n\\t\\t\\tindex = 9 ifTrue: [\\n\\t\\t\\t\\t\\\"Copy hidden info\\\"\\n\\t\\t\\t\\tself copyHiddenInfo.\\n\\t\\t\\t\\t^ true\\n\\t\\t\\t].\\n\\t\\t\\n\\t\\t\\t\\\"no other action\\\"\\n\\t\\t\\tthisSel\\n\\t\\t\\t\\tifNil: [ ^ true ]\\n\\t\\t]\\n\\t].\\n\\n\\t(keyCode between: 7 and: 11) ifTrue: [\\n\\t\\tsensor leftShiftDown ifTrue: [\\n\\t\\t\\tkeyCode = 10 ifTrue: [\\n\\t\\t\\t\\tattribute := TextKern kern: -1\\n\\t\\t\\t].\\n\\t\\t\\tkeyCode = 11 ifTrue: [\\n\\t\\t\\t\\tattribute := TextKern kern: 1\\n\\t\\t\\t]\\n\\t\\t]\\n\\t\\tifFalse: [\\n\\t\\t\\tattribute := TextEmphasis perform: (#(#bold #italic #narrow #underlined #struckOut ) at: keyCode - 6).\\n\\t\\t\\toldAttributes\\n\\t\\t\\t\\t\\t\\tdo: [:att | (att dominates: attribute) ifTrue: [attribute turnOff]]\\n\\t\\t]\\n\\t].\\n\\n\\tkeyCode = 0\\n\\t\\tifTrue: [attribute := TextEmphasis normal].\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [\\n\\t\\t\\\"only change emphasisHere while typing\\\"\\n\\t\\tself insertTypeAhead: characterStream.\\n\\t\\temphasisHere := Text addAttribute: attribute toArray: oldAttributes.\\n\\t\\t^ true\\n\\t].\\n\\n\\tself\\n\\t\\treplaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t\\t\\n\\t^ true\\n! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 11:58'!\\nchangeLfToCr: characterStream \\n\\t\\\"Replace all LFs by CRs.\\n\\tTriggered by Cmd-U -- useful when getting code from FTP sites\\\"\\n\\t| cr lf |\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tcr _ Character cr. lf _ Character linefeed.\\n\\tself replaceSelectionWith: (Text fromString:\\n\\t\\t\\t(self selection string collect: [:c | c = lf ifTrue: [cr] ifFalse: [c]])).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 09:11'!\\nchooseColor\\n\\t\\\"Make a new Text Color Attribute, let the user pick a color, and return the attribute. This is the non-Morphic version.\\\"\\n\\n\\t^ TextColor color: (Color fromUser)! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:31'!\\ncompareToClipboard: characterStream \\n\\t\\\"Compare the receiver to the text on the clipboard. Flushes typeahead. 5/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself terminateAndInitializeAround: [self compareToClipboard].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 08:47'!\\ncopyHiddenInfo\\n\\t\\\"In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden\\ninfo. Copy that to the clipboard. You can paste it and see what it is.\\nUsually enclosed in <>.\\\"\\n\\n\\t^ self clipboardTextPut: self hiddenInfo asText! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\ncopySelection: characterStream \\n\\t\\\"Copy the current text selection. Flushes typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself copySelection.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\ncut: characterStream \\n\\t\\\"Cut out the current text selection. Flushes typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself cut.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:23'!\\ndoIt: characterStream \\n\\t\\\"Called when user hits cmd-d. Select the current line, if relevant, then evaluate and execute. 2/1/96 sw.\\n\\t2/29/96 sw: don't call selectLine; it's done by doIt now\\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself terminateAndInitializeAround: [self doIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/20/2002 11:41'!\\nduplicate: characterStream\\n\\t\\\"Paste the current selection over the prior selection, if it is non-overlapping and\\n\\t legal. Flushes typeahead. Undoer & Redoer: undoAndReselect.\\\"\\n\\n\\tsensor keyboard.\\n\\tself closeTypeIn.\\n\\t(self hasSelection and: [self isDisjointFrom: otherInterval])\\n\\t\\tifTrue: \\\"Something to duplicate\\\"\\n\\t\\t\\t[self replace: otherInterval with: self selection and:\\n\\t\\t\\t\\t[self selectAt: self pointIndex]]\\n\\t\\tifFalse:\\n\\t\\t\\t[view flash].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:01'!\\nenclose: characterStream\\n\\t\\\"Insert or remove bracket characters around the current selection.\\n\\t Flushes typeahead.\\\"\\n\\n\\t| char left right startIndex stopIndex oldSelection which text |\\n\\tchar _ sensor keyboard.\\n\\tself closeTypeIn.\\n\\tstartIndex _ self startIndex.\\n\\tstopIndex _ self stopIndex.\\n\\toldSelection _ self selection.\\n\\twhich _ '([<{\\\"''' indexOf: char ifAbsent: [ ^true ].\\n\\tleft _ '([<{\\\"''' at: which.\\n\\tright _ ')]>}\\\"''' at: which.\\n\\ttext _ paragraph text.\\n\\t((startIndex > 1 and: [stopIndex <= text size])\\n\\t\\tand:\\n\\t\\t[(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])\\n\\t\\tifTrue:\\n\\t\\t\\t[\\\"already enclosed; strip off brackets\\\"\\n\\t\\t\\tself selectFrom: startIndex-1 to: stopIndex.\\n\\t\\t\\tself replaceSelectionWith: oldSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"not enclosed; enclose by matching brackets\\\"\\n\\t\\t\\tself replaceSelectionWith:\\n\\t\\t\\t\\t(Text string: (String with: left), oldSelection string ,(String with: right)\\n\\t\\t\\t\\t\\temphasis: emphasisHere).\\n\\t\\t\\tself selectFrom: startIndex+1 to: stopIndex].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nexchange: characterStream\\n\\t\\\"Exchange the current and prior selections. Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t \\\"Flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself exchange.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'acg 12/7/1999 07:56'!\\nexploreIt: characterStream \\n\\t\\\"Explore the selection -- invoked via cmd-shift-I. If there is no current selection, use the current line.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self exploreIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 4/24/2001 12:28'!\\nfileItIn: characterStream \\n\\t\\\"File in the selection; invoked via a keyboard shortcut, -- for now, cmd-shift-G.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self fileItIn].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:31'!\\nhiddenInfo\\n\\t\\\"In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden info. Return the entire string that was used by Cmd-6 to create this text attribute. Usually enclosed in < >.\\\"\\n\\n\\t| attrList |\\n\\tattrList _ paragraph text attributesAt: (self pointIndex +\\nself markIndex)//2 forStyle: paragraph textStyle.\\n\\tattrList do: [:attr |\\n\\t\\t(attr isKindOf: TextAction) ifTrue:\\n\\t\\t\\t[^ self selection asString, '<', attr info, '>']].\\n\\t\\\"If none of the above\\\"\\n\\tattrList do: [:attr |\\n\\t\\tattr class == TextColor ifTrue:\\n\\t\\t\\t[^ self selection asString, '<', attr color printString, '>']].\\n\\t^ self selection asString, '[No hidden info]'! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nimplementorsOfIt: characterStream \\n\\t\\\"Triggered by Cmd-m; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself implementorsOfIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'pk 9/10/2005 22:53'!\\ninOutdent: characterStream delta: delta\\n\\t\\\"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\\\"\\n\\n\\t| cr realStart realStop lines startLine stopLine start stop adjustStart indentation size numLines inStream newString outStream |\\n\\t\\n\\tsensor keyboard. \\\"Flush typeahead\\\"\\n\\tcr := Character cr.\\n\\n\\t\\\"Operate on entire lines, but remember the real selection for re-highlighting later\\\"\\n\\trealStart := self startIndex.\\n\\trealStop := self stopIndex - 1.\\n\\n\\t\\\"Special case a caret on a line of its own, including weird case at end of paragraph\\\"\\n\\t(realStart > realStop and:\\n\\t\\t\\t\\t[realStart < 2 or: [(paragraph string at: realStart - 1) == cr]])\\n\\t\\tifTrue:\\n\\t\\t\\t[delta < 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[view flash]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[self replaceSelectionWith: Character tab asSymbol asText.\\n\\t\\t\\t\\t\\tself selectAt: realStart + 1].\\n\\t\\t\\t^ true].\\n\\n\\tlines := paragraph lines.\\n\\tstartLine := paragraph lineIndexOfCharacterIndex: realStart.\\n\\tstopLine := paragraph lineIndexOfCharacterIndex: (realStart max: realStop).\\n\\tstart := (lines at: startLine) first.\\n\\tstop := (lines at: stopLine) last.\\n\\t\\n\\t\\\"Pin the start of highlighting unless the selection starts a line\\\"\\n\\tadjustStart := realStart > start.\\n\\n\\t\\\"Find the indentation of the least-indented non-blank line; never outdent more\\\"\\n\\tindentation := (startLine to: stopLine) inject: 1000 into:\\n\\t\\t[:m :l |\\n\\t\\tm := m min: (paragraph indentationOfLineIndex: l ifBlank: [:tabs | 1000])].\\t\\t\\t\\n\\n\\tsize := stop + 1 - start.\\n\\tnumLines := stopLine + 1 - startLine.\\n\\tinStream := ReadStream on: paragraph string from: start to: stop.\\n\\n\\tnewString := WideString new: size + ((numLines * delta) max: 0).\\n\\toutStream := ReadWriteStream on: newString.\\n\\n\\t\\\"This subroutine does the actual work\\\"\\n\\tself indent: delta fromStream: inStream toStream: outStream.\\n\\n\\t\\\"Adjust the range that will be highlighted later\\\"\\n\\tadjustStart ifTrue: [realStart := (realStart + delta) max: start].\\n\\trealStop := realStop + outStream position - size.\\n\\n\\t\\\"Prepare for another iteration\\\"\\n\\tindentation := indentation + delta.\\n\\tsize := outStream position.\\n\\tinStream := outStream setFrom: 1 to: size.\\n\\n\\toutStream == nil\\n\\t\\tifTrue: \\t\\\"tried to outdent but some line(s) were already left flush\\\"\\n\\t\\t\\t[view flash]\\n\\t\\tifFalse:\\n\\t\\t\\t[self selectInvisiblyFrom: start to: stop.\\n\\t\\t\\tsize = newString size ifFalse: [newString _ outStream contents].\\n\\t\\t\\tself replaceSelectionWith: newString asText].\\n\\tself selectFrom: realStart to: realStop. \\t\\\"highlight only the original range\\\"\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nindent: characterStream\\n\\t\\\"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\\\"\\n\\n\\t^ self inOutdent: characterStream delta: 1! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'!\\ninspectIt: characterStream \\n\\t\\\"Inspect the selection -- invoked via cmd-i. If there is no current selection, use the current line. 1/17/96 sw\\n\\t 2/29/96 sw: don't call selectLine; it's done by inspectIt now\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self inspectIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'md 1/18/2006 23:42'!\\nmakeCapitalized: characterStream \\n\\t\\\"Force the current selection to be capitalized. Triggered by Cmd-Z.\\\"\\n\\t| prev |\\n\\tsensor keyboard.\\t\\t\\\"Flush the triggering cmd-key character\\\"\\n\\tprev _ $-. \\\"not a letter\\\"\\n\\tself replaceSelectionWith: (Text fromString:\\n\\t\\t\\t(self selection string collect:\\n\\t\\t\\t\\t[:c | prev _ prev isLetter ifTrue: [c asLowercase] ifFalse: [c asUppercase]])).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 12:00'!\\nmakeLowercase: characterStream \\n\\t\\\"Force the current selection to lowercase. Triggered by Cmd-X.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tself replaceSelectionWith: (Text fromString: (self selection string asLowercase)).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:21'!\\nmakeProjectLink: characterStream \\n\\t\\\"\\\"\\n\\n\\t| attribute oldAttributes thisSel |\\n\\t\\n\\tsensor keyboard.\\n\\toldAttributes _ paragraph text attributesAt: self pointIndex forStyle: paragraph textStyle.\\n\\tthisSel _ self selection.\\n\\n\\tattribute _ TextSqkProjectLink new. \\n\\tthisSel _ attribute analyze: self selection asString.\\n\\n\\tthisSel ifNil: [^ true].\\n\\tbeginTypeInBlock ~~ nil\\n\\t\\tifTrue: \\\"only change emphasisHere while typing\\\"\\n\\t\\t\\t[self insertTypeAhead: characterStream.\\n\\t\\t\\temphasisHere _ Text addAttribute: attribute toArray: oldAttributes.\\n\\t\\t\\t^ true].\\n\\tself replaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'ls 11/10/2002 12:11'!\\nmakeUppercase: characterStream \\n\\t\\\"Force the current selection to uppercase. Triggered by Cmd-Y.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\tself replaceSelectionWith: (Text fromString: (self selection string asUppercase)).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 8/1/97 15:18'!\\nmethodNamesContainingIt: characterStream \\n\\t\\\"Browse methods whose selectors containing the selection in their names\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself methodNamesContainingIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 9/9/97 16:44'!\\nmethodStringsContainingIt: characterStream \\n\\t\\\"Invoked from cmd-E -- open a browser on all methods holding string constants containing it. Flushes typeahead. \\\"\\n\\n\\tsensor keyboard.\\t\\n\\tself methodStringsContainingit.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nnoop: characterStream \\n\\t\\\"Unimplemented keyboard command; just ignore it.\\\"\\n\\n\\tsensor keyboard.\\t \\\"flush character\\\"\\n\\t^ true\\n! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 1/19/2000 11:14'!\\nofferFontMenu\\n\\t\\\"Present a menu of available fonts, and if one is chosen, apply it to the current selection. \\n\\tUse only names of Fonts of this paragraph \\\"\\n\\n\\t| aList reply |\\n\\taList _ paragraph textStyle fontNamesWithPointSizes.\\n\\treply _ (SelectionMenu labelList: aList selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[self replaceSelectionWith:\\n\\t\\t\\t(Text string: self selection asString \\n\\t\\t\\t\\tattribute: (TextFontChange fontNumber: (aList indexOf: reply)))] ! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nofferFontMenu: characterStream \\n\\t\\\"The user typed the command key that requests a font change; Offer the font menu. 5/27/96 sw\\n\\t Keeps typeahead. (?? should flush?)\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself offerFontMenu.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\noutdent: characterStream\\n\\t\\\"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\\\"\\n\\n\\t^ self inOutdent: characterStream delta: -1! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\npaste: characterStream \\n\\t\\\"Replace the current text selection by the text in the shared buffer.\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself paste.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:48'!\\npasteInitials: characterStream \\n\\t\\\"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.\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself replace: self selectionInterval with: (Text fromString: Utilities changeStamp) and: [self selectAt: self stopIndex].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'!\\nprintIt: characterStream \\n\\t\\\"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\\n\\t 2/29/96 sw: don't call selectLine now, since it's called by doIt\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself terminateAndInitializeAround: [self printIt].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nreferencesToIt: characterStream \\n\\t\\\"Triggered by Cmd-N; browse references to the current selection\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself referencesToIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'!\\nsave: characterStream\\n\\t\\\"Submit the current text. Equivalent to 'accept' 1/18/96 sw\\n\\t Keeps typeahead.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself terminateAndInitializeAround: [self accept].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nsendersOfIt: characterStream \\n\\t\\\"Triggered by Cmd-n; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself sendersOfIt.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'yo 5/27/2004 13:56'!\\nsetEmphasis: emphasisSymbol\\n\\t\\\"Change the emphasis of the current selection.\\\"\\n\\n\\t| oldAttributes attribute |\\n\\toldAttributes _ paragraph text attributesAt: self selectionInterval first forStyle: paragraph textStyle.\\n\\n\\tattribute _ TextEmphasis perform: emphasisSymbol.\\n\\t(emphasisSymbol == #normal) \\n\\t\\tifFalse:\\t[oldAttributes do:\\t\\n\\t\\t\\t[:att | (att dominates: attribute) ifTrue: [attribute turnOff]]].\\n\\tself replaceSelectionWith: (self selection addAttribute: attribute)! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:20'!\\nshiftEnclose: characterStream\\n\\t\\\"Insert or remove bracket characters around the current selection.\\n\\t Flushes typeahead.\\\"\\n\\n\\t| char left right startIndex stopIndex oldSelection which text |\\n\\tchar _ sensor keyboard.\\n\\tchar = $9 ifTrue: [ char _ $( ].\\n\\tchar = $, ifTrue: [ char _ $< ].\\n\\tchar = $[ ifTrue: [ char _ ${ ].\\n\\tchar = $' ifTrue: [ char _ $\\\" ].\\n\\tchar asciiValue = 27 ifTrue: [ char _ ${ ].\\t\\\"ctrl-[\\\"\\n\\n\\tself closeTypeIn.\\n\\tstartIndex _ self startIndex.\\n\\tstopIndex _ self stopIndex.\\n\\toldSelection _ self selection.\\n\\twhich _ '([<{\\\"''' indexOf: char ifAbsent: [1].\\n\\tleft _ '([<{\\\"''' at: which.\\n\\tright _ ')]>}\\\"''' at: which.\\n\\ttext _ paragraph text.\\n\\t((startIndex > 1 and: [stopIndex <= text size])\\n\\t\\tand:\\n\\t\\t[(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])\\n\\t\\tifTrue:\\n\\t\\t\\t[\\\"already enclosed; strip off brackets\\\"\\n\\t\\t\\tself selectFrom: startIndex-1 to: stopIndex.\\n\\t\\t\\tself replaceSelectionWith: oldSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"not enclosed; enclose by matching brackets\\\"\\n\\t\\t\\tself replaceSelectionWith:\\n\\t\\t\\t\\t(Text string: (String with: left), oldSelection string ,(String with: right)\\n\\t\\t\\t\\t\\temphasis: emphasisHere).\\n\\t\\t\\tself selectFrom: startIndex+1 to: stopIndex].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'!\\nspawnIt: characterStream\\n\\t\\\"Triggered by Cmd-o; spawn a new code window, if it makes sense.\\\"\\n\\n\\tsensor keyboard.\\n\\tself terminateAndInitializeAround: [self spawn].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:00'!\\nswapChars: characterStream \\n\\t\\\"Triggered byCmd-Y;. Swap two characters, either those straddling the insertion point, or the two that comprise the selection. Suggested by Ted Kaehler. \\\"\\n\\n\\t| currentSelection aString chars |\\n\\tsensor keyboard.\\t\\t\\\"flush the triggering cmd-key character\\\"\\n\\t(chars _ self selection) size == 0\\n\\t\\tifTrue:\\n\\t\\t\\t[currentSelection _ self pointIndex.\\n\\t\\t\\tself selectMark: currentSelection - 1 point: currentSelection]\\n\\t\\tifFalse:\\n\\t\\t\\t[chars size == 2\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[view flash. ^ true]\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[currentSelection _ self pointIndex - 1]].\\n\\taString _ self selection string.\\n\\tself replaceSelectionWith: (Text string: aString reversed emphasis: emphasisHere).\\n\\tself selectAt: currentSelection + 1.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 11/2/1998 15:50'!\\ntempCommand: characterStream \\n\\t\\\"Experimental. Triggered by Cmd-t; put trial cmd-key commands here to see how they work, before hanging them on their own cmd accelerators.\\\"\\n\\tSensor keyboard.\\n\\tself experimentalCommand.\\n\\t^ true\\n\\n\\t\\\"sensor keyboard.\\n\\tself spawnWorkspace.\\n\\t^ true\\\"! !\\n\\n!ParagraphEditor methodsFor: 'editing keys'!\\nundo: characterStream \\n\\t\\\"Undo the last edit. Keeps typeahead, so undo twice is a full redo.\\\"\\n\\n\\tsensor keyboard. \\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself undo.\\n\\t^true! !\\n\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/26/2003 22:02'!\\nexplainAnySel: symbol \\n\\t\\\"Is this any message selector?\\\"\\n\\n\\t| list reply |\\n\\tlist _ self systemNavigation allClassesImplementing: symbol.\\n\\tlist size = 0 ifTrue: [^nil].\\n\\tlist size < 12\\n\\t\\tifTrue: [reply _ ' is a message selector which is defined in these classes ' , list printString]\\n\\t\\tifFalse: [reply _ ' is a message selector which is defined in many classes'].\\n\\t^'\\\"' , symbol , reply , '.\\\"' , '\\\\' withCRs, 'SystemNavigation new browseAllImplementorsOf: #' , symbol! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'di 1/30/2002 21:09'!\\nexplainChar: string\\n\\t\\\"Does string start with a special character?\\\"\\n\\n\\t| char |\\n\\tchar _ string at: 1.\\n\\tchar = $. 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 class Float).\\\"'].\\n\\tchar = $' ifTrue: [^'\\\"The characters between two single quotes are made into an instance of class String\\\"'].\\n\\tchar = $\\\" ifTrue: [^'\\\"Double quotes enclose a comment. Smalltalk ignores everything between double quotes.\\\"'].\\n\\tchar = $# 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. It contains literal constants.\\\"'].\\n\\t(char = $( or: [char = $)]) ifTrue: [^'\\\"Expressions enclosed in parenthesis are evaluated first\\\"'].\\n\\t(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.\\\"'].\\n\\t(char = ${ or: [char = $}]) ifTrue: [^ '\\\"A sequence of expressions separated by periods, when enclosed in curly braces, are evaluated to yield the elements of a new Array\\\"'].\\n\\t(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.\\\"'].\\n\\tchar = $^ ifTrue: [^'\\\"Uparrow means return from this method. The value returned is the expression following the ^\\\"'].\\n\\tchar = $| 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.\\\"'].\\n\\tchar = $_ ifTrue: [^'\\\"Left arrow means assignment. The value of the expression after the left arrow is stored into the variable before it.\\\"'].\\n\\tchar = $; ifTrue: [^'\\\"Semicolon means cascading. The message after the semicolon is sent to the same object which received the message before the semicolon.\\\"'].\\n\\tchar = $: 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).', '\\\\\\\\' withCRs, '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).\\\"'].\\n\\tchar = $$ ifTrue: [^'\\\"The single character following a dollar sign is made into an instance of class Character\\\"'].\\n\\tchar = $- ifTrue: [^'\\\"A minus sign in front of a number means a negative number.\\\"'].\\n\\tchar = $e ifTrue: [^'\\\"An e in the middle of a number means that the exponent follows.\\\"'].\\n\\tchar = $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.\\\"'].\\n\\tchar = Character space ifTrue: [^'\\\"the space Character\\\"'].\\n\\tchar = Character tab ifTrue: [^'\\\"the tab Character\\\"'].\\n\\tchar = Character cr ifTrue: [^'\\\"the carriage return Character\\\"'].\\n\\t^nil! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/10/2004 07:02'!\\nexplainClass: symbol \\n\\t\\\"Is symbol a class variable or a pool variable?\\\"\\n\\t| class reply classes |\\n\\t(model respondsTo: #selectedClassOrMetaClass)\\n\\t\\tifFalse: [^ nil].\\n\\t(class _ model selectedClassOrMetaClass) ifNil: [^ nil].\\n\\t\\\"no class is selected\\\"\\n\\t(class isKindOf: Metaclass)\\n\\t\\tifTrue: [class _ class soleInstance].\\n\\tclasses _ (Array with: class)\\n\\t\\t\\t\\t, class allSuperclasses.\\n\\t\\\"class variables\\\"\\n\\treply _ classes detect: [:each | (each classVarNames detect: [:name | symbol = name]\\n\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t~~ nil]\\n\\t\\t\\t\\tifNone: [].\\n\\treply == nil ifFalse: [^ '\\\"is a class variable, defined in class ' , reply printString , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , reply printString , ' classPool associationAt: #' , symbol , ').'].\\n\\t\\\"pool variables\\\"\\n\\tclasses do: [:each | (each sharedPools\\n\\t\\t\\tdetect: [:pool | (pool includesKey: symbol)\\n\\t\\t\\t\\t\\tand: \\n\\t\\t\\t\\t\\t\\t[reply _ pool.\\n\\t\\t\\t\\t\\t\\ttrue]]\\n\\t\\t\\tifNone: [])\\n\\t\\t\\t~~ nil].\\n\\treply\\n\\t\\tifNil: [(Undeclared includesKey: symbol)\\n\\t\\t\\t\\tifTrue: [^ '\\\"is an undeclared variable.' , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (Undeclared associationAt: #' , symbol , ').']]\\n\\t\\tifNotNil: \\n\\t\\t\\t[classes _ WriteStream on: Array new.\\n\\t\\t\\tself systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:each | (each sharedPools\\n\\t\\t\\t\\t\\t\\tdetect: \\n\\t\\t\\t\\t\\t\\t\\t[:pool | \\n\\t\\t\\t\\t\\t\\t\\tpool == reply]\\n\\t\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t\\t~~ nil ifTrue: [classes nextPut: each]].\\n\\t\\t\\t\\\"Perhaps not print whole list of classes if too long. (unlikely)\\\"\\n\\t\\t\\t^ '\\\"is a pool variable from the pool ' , (Smalltalk keyAtIdentityValue: reply) asString , ', which is used by the following classes ' , classes contents printString , '\\\"\\\\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , (Smalltalk keyAtIdentityValue: reply) asString , ' bindingOf: #' , symbol , ').'].\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'sw 5/3/1998 14:32'!\\nexplainCtxt: symbol \\n\\t\\\"Is symbol a context variable?\\\"\\n\\n\\t| reply classes text cls |\\n\\tsymbol = #nil ifTrue: [reply _ '\\\"is a constant. It is the only instance of class UndefinedObject. nil is the initial value of all variables.\\\"'].\\n\\tsymbol = #true ifTrue: [reply _ '\\\"is a constant. It is the only instance of class True and is the receiver of many control messages.\\\"'].\\n\\tsymbol = #false ifTrue: [reply _ '\\\"is a constant. It is the only instance of class False and is the receiver of many control messages.\\\"'].\\n\\tsymbol = #thisContext ifTrue: [reply _ '\\\"is a context variable. Its value is always the MethodContext which is executing this method.\\\"'].\\n\\t(model respondsTo: #selectedClassOrMetaClass) ifTrue: [\\n\\t\\tcls _ model selectedClassOrMetaClass].\\n\\tcls ifNil: [^ reply].\\t \\\"no class known\\\"\\n\\tsymbol = #self ifTrue: \\n\\t\\t\\t[classes _ cls withAllSubclasses.\\n\\t\\t\\tclasses size > 12\\n\\t\\t\\t\\tifTrue: [text _ cls printString , ' or a subclass']\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[classes _ classes printString.\\n\\t\\t\\t\\t\\ttext _ 'one of these classes' , (classes copyFrom: 4 to: classes size)].\\n\\t\\t\\treply _ '\\\"is the receiver of this message; an instance of ' , text , '\\\"'].\\n\\tsymbol = #super ifTrue: [reply _ '\\\"is just like self. Messages to super are looked up in the superclass (' , cls superclass printString , ')\\\"'].\\n\\t^reply! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/29/2003 20:07'!\\nexplainGlobal: symbol \\n\\t\\\"Is symbol a global variable?\\\"\\n\\t| reply classes |\\n\\treply _ Smalltalk at: symbol ifAbsent: [^nil].\\n\\t(reply class == Dictionary or:[reply isKindOf: SharedPool class])\\n\\t\\tifTrue: \\n\\t\\t\\t[classes _ Set new.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply]\\n\\t\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t\\t~~ nil ifTrue: [classes add: each]].\\n\\t\\t\\tclasses _ classes printString.\\n\\t\\t\\t^'\\\"is a global variable. It is a pool which is used by the following classes ' , (classes allButFirst: 5) , '\\\"'].\\n\\t(reply isKindOf: Behavior)\\n\\t\\tifTrue: [^'\\\"is a global variable. ' , symbol , ' is a class in category ', reply category,\\n\\t\\t\\t'.\\\"', '\\\\' withCRs, 'Browser newOnClass: ' , symbol , '.'].\\n\\tsymbol == #Smalltalk ifTrue: [^'\\\"is a global. Smalltalk is the only instance of SystemDictionary and holds all global variables.\\\"'].\\n\\t^'\\\"is a global variable. ' , symbol , ' is ' , reply printString , '\\\"'! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/12/2004 16:22'!\\nexplainInst: string \\n\\t\\\"Is string an instance variable of this class?\\\"\\n\\t| classes cls |\\n\\n\\t(model respondsTo: #selectedClassOrMetaClass) ifTrue: [\\n\\t\\tcls _ model selectedClassOrMetaClass].\\n\\tcls ifNil: [^ nil].\\t \\\"no class known\\\"\\n\\tclasses _ (Array with: cls)\\n\\t\\t\\t\\t, cls allSuperclasses.\\n\\tclasses _ classes detect: [:each | (each instVarNames\\n\\t\\t\\tdetect: [:name | name = string] ifNone: [])\\n\\t\\t\\t~~ nil] ifNone: [^nil].\\n\\tclasses _ classes printString.\\n\\t^ '\\\"is an instance variable of the receiver; defined in class ' , classes , \\n\\t\\t'\\\"\\\\' withCRs , classes , ' systemNavigation browseAllAccessesTo: ''' , string , ''' from: ', classes, '.'! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'!\\nexplainMySel: symbol \\n\\t\\\"Is symbol the selector of this method? Is it sent by this method? If \\n\\tnot, then expalin will call (explainPartSel:) to see if it is a fragment of a \\n\\tselector sent here. If not, explain will call (explainAnySel:) to catch any \\n\\tselector. \\\"\\n\\n\\t| lits classes msg |\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^nil].\\t\\\"not in a message\\\"\\n\\tclasses _ self systemNavigation allClassesImplementing: symbol.\\n\\tclasses size > 12\\n\\t\\tifTrue: [classes _ 'many classes']\\n\\t\\tifFalse: [classes _ 'these classes ' , classes printString].\\n\\tmsg = symbol\\n\\t\\tifTrue: [^ '\\\"' , symbol , ' is the selector of this very method!! It is defined in ',\\n\\t\\t\\tclasses , '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"']\\n\\t\\tifFalse: \\n\\t\\t\\t[lits _ (model selectedClassOrMetaClass compiledMethodAt:\\n\\t\\t\\t\\tmsg) messages.\\n\\t\\t\\t(lits detect: [:each | each == symbol]\\n\\t\\t\\t\\tifNone: [])\\n\\t\\t\\t\\t== nil ifTrue: [^nil].\\n\\t\\t\\t^ '\\\"' , symbol , ' is a message selector which is defined in ', classes , '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"'].! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'apb 1/5/2000 16:56'!\\nexplainNumber: string \\n\\t\\\"Is string a Number?\\\"\\n\\n\\t| strm c |\\n\\t(c _ string at: 1) isDigit ifFalse: [(c = $- and: [string size > 1 and: [(string at: 2) isDigit]])\\n\\t\\t\\tifFalse: [^nil]].\\n\\tstrm _ ReadStream on: string.\\n\\tc _ Number readFrom: strm.\\n\\tstrm atEnd ifFalse: [^nil].\\n\\tc printString = string\\n\\t\\tifTrue: [^'\\\"' , string , ' is a ' , c class name , '\\\"']\\n\\t\\tifFalse: [^'\\\"' , string , ' (= ' , c printString , ') is a ' , c class name , '\\\"']! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'!\\nexplainPartSel: string \\n\\t\\\"Is this a fragment of a multiple-argument selector sent in this method?\\\"\\n\\t| lits whole reply classes s msg |\\n\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^ nil]. \\\"not in a message\\\"\\n\\tstring last == $: ifFalse: [^ nil].\\n\\t\\\"Name of this method\\\"\\n\\tlits _ Array with: msg.\\n\\t(whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]\\n\\t\\t\\t\\t\\tifNone: []) ~~ nil]\\n\\t\\t\\t\\tifNone: []) ~~ nil\\n\\t\\tifTrue: [reply _ ', which is the selector of this very method!!'.\\n\\t\\t\\ts _ '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"']\\n\\t\\tifFalse: \\n\\t\\t\\t[\\\"Selectors called from this method\\\"\\n\\t\\t\\tlits _ (model selectedClassOrMetaClass compiledMethodAt:\\n\\t\\t\\t\\tmsg) messages.\\n\\t\\t\\t(whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]\\n\\t\\t\\t\\t\\t\\t\\tifNone: []) ~~ nil]\\n\\t\\t\\t\\t\\t\\tifNone: []) ~~ nil\\n\\t\\t\\t\\tifFalse: [string = 'primitive:'\\n\\t\\t\\t\\t\\tifTrue: [^self explainChar: '<']\\n\\t\\t\\t\\t\\tifFalse: [^nil]].\\n\\t\\t\\treply _ '.'.\\n\\t\\t\\ts _ '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''.\\\"'].\\n\\tclasses _ self systemNavigation allClassesImplementing: whole.\\n\\tclasses size > 12\\n\\t\\tifTrue: [classes _ 'many classes']\\n\\t\\tifFalse: [classes _ 'these classes ' , classes printString].\\n\\t^ '\\\"' , string , ' is one part of the message selector ' , whole, reply , ' It is defined in ' , classes , s! !\\n\\n!ParagraphEditor methodsFor: 'explain'!\\nexplainScan: string \\n\\t\\\"Remove beginning and trailing space, tab, cr.\\n\\t 1/15/96 sw: copied intact from BrowserCodeController\\\"\\n\\n\\t| c beg end |\\n\\tbeg _ 1.\\n\\tend _ string size.\\n\\t\\n\\t[beg = end ifTrue: [^string copyFrom: 1 to: 1].\\n\\t\\\"if all blank, tell about the first\\\"\\n\\tc _ string at: beg.\\n\\tc = Character space or: [c = Character tab or: [c = Character cr]]]\\n\\t\\twhileTrue: [beg _ beg + 1].\\n\\t\\n\\t[c _ string at: end.\\n\\tc = Character space or: [c = Character tab or: [c = Character cr]]]\\n\\t\\twhileTrue: [end _ end - 1].\\n\\t^string copyFrom: beg to: end\\t\\\"Return purely visible characters\\\"! !\\n\\n!ParagraphEditor methodsFor: 'explain' stamp: 'tk 4/1/98 14:19'!\\nexplainTemp: string \\n\\t\\\"Is string the name of a temporary variable (or block argument variable)?\\\"\\n\\n\\t| selectedClass tempNames i reply methodNode method msg |\\n\\t(model respondsTo: #selectedMessageName) ifFalse: [^ nil].\\n\\t(msg _ model selectedMessageName) ifNil: [^nil].\\t\\\"not in a message\\\"\\n\\tselectedClass _ model selectedClassOrMetaClass.\\n\\ttempNames _ selectedClass parserClass new \\n\\t\\t\\tparseArgsAndTemps: model selectedMessage notifying: nil.\\n\\tmethod _ selectedClass compiledMethodAt: msg.\\n\\t(i _ tempNames findFirst: [:each | each = string]) = 0 ifTrue: [\\n\\t\\t(method numTemps > tempNames size)\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[\\\"It must be an undeclared block argument temporary\\\"\\n\\t\\t\\t\\tmethodNode _ selectedClass compilerClass new\\n\\t\\t\\t\\t\\t\\t\\tparse: model selectedMessage\\n\\t\\t\\t\\t\\t\\t\\tin: selectedClass\\n\\t\\t\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\ttempNames _ methodNode tempNames]\\n\\t\\t\\tifFalse: [^nil]].\\n\\t(i _ tempNames findFirst: [:each | each = string]) > 0 ifTrue: [i > method numArgs\\n\\t\\t\\tifTrue: [reply _ '\\\"is a temporary variable in this method\\\"']\\n\\t\\t\\tifFalse: [reply _ '\\\"is an argument to this method\\\"']].\\n\\t^reply! !\\n\\n\\n!ParagraphEditor methodsFor: 'initialize-release'!\\nchangeParagraph: aParagraph \\n\\t\\\"Install aParagraph as the one to be edited by the receiver.\\\"\\n\\n\\tUndoParagraph == paragraph ifTrue: [UndoParagraph _ nil].\\n\\tparagraph _ aParagraph.\\n\\tself resetState! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'th 10/21/2003 15:49'!\\nresetState \\n\\t\\\"Establish the initial conditions for editing the paragraph: place caret \\n\\tbefore first character, set the emphasis to that of the first character,\\n\\tand save the paragraph for purposes of canceling.\\\"\\n\\n\\tstopBlock _ paragraph defaultCharacterBlock.\\n\\tself pointBlock: stopBlock copy.\\n\\tbeginTypeInBlock _ nil.\\n\\tUndoInterval _ otherInterval _ 1 to: 0.\\n\\tself setEmphasisHere.\\n\\tselectionShowing _ false.\\n\\tinitialText _ paragraph text copy! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 5/15/2000 13:51'!\\nstateArray\\n\\t^ {ChangeText.\\n\\t\\tFindText.\\n\\t\\tUndoInterval.\\n\\t\\tUndoMessage.\\n\\t\\tUndoParagraph.\\n\\t\\tUndoSelection.\\n\\t\\tUndone.\\n\\t\\tself selectionInterval.\\n\\t\\tself startOfTyping.\\n\\t\\temphasisHere}! !\\n\\n!ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 10/5/1998 17:03'!\\nstateArrayPut: stateArray\\n\\t| sel |\\n\\tChangeText _ stateArray at: 1.\\n\\tFindText _ stateArray at: 2.\\n\\tUndoInterval _ stateArray at: 3.\\n\\tUndoMessage _ stateArray at: 4.\\n\\tUndoParagraph _ stateArray at: 5.\\n\\tUndoSelection _ stateArray at: 6.\\n\\tUndone _ stateArray at: 7.\\n\\tsel _ stateArray at: 8.\\n\\tself selectFrom: sel first to: sel last.\\n\\tbeginTypeInBlock _ stateArray at: 9.\\n\\temphasisHere _ stateArray at: 10.! !\\n\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'jm 5/3/1998 19:19'!\\naccept\\n\\t\\\"Save the current text of the text being edited as the current acceptable version for purposes of canceling.\\\"\\n\\n\\tinitialText _ paragraph text copy.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nagain\\n\\t\\\"Text substitution. If the left shift key is down, the substitution is made \\n\\tthroughout the entire Paragraph. Otherwise, only the next possible \\n\\tsubstitution is made.\\n\\tUndoer & Redoer: #undoAgain:andReselect:typedKey:.\\\"\\n\\n\\t\\\"If last command was also 'again', use same keys as before\\\"\\n\\tself againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:)! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nalign\\n\\t\\\"Align text according to the next greater alignment value--cycling among \\n\\tleft flush, right flush, center, justified. No effect on the undoability of the pre\\n\\tpreceding command.\\\"\\n\\n\\tparagraph toggleAlignment.\\n\\tparagraph displayOn: Display.\\n\\tself recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 8/2/2005 20:53'!\\nbrowseClassFromIt\\n\\t\\\"Launch a browser for the class indicated by the current selection. \\n\\tIf multiple classes matching the selection exist, let the user choose among them.\\\"\\n\\t| aBrow aClass |\\n\\tself\\n\\t\\tlineSelectAndEmptyCheck: [^ self].\\n\\taClass := Utilities\\n\\t\\t\\t\\tclassFromPattern: (self selection string copyWithout: Character cr)\\n\\t\\t\\t\\twithCaption: 'choose a class to browse...'.\\n\\taClass\\n\\t\\tifNil: [^ view flash].\\n\\tself\\n\\t\\tterminateAndInitializeAround: \\n\\t\\t\\t[aBrow := SystemBrowser default new.\\n\\t\\t\\taBrow setClass: aClass selector: nil.\\n\\t\\t\\taBrow class\\n\\t\\t\\t\\topenBrowserView: (aBrow openEditString: nil) label: 'System Browser'].! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'pmm 7/6/2006 20:50'!\\nbrowseIt\\n\\t\\\"Launch a browser for the current selection, if appropriate\\\"\\n\\n\\t| aSymbol anEntry |\\n\\tself flag: #yoCharCases.\\n\\n\\tPreferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt].\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround:\\n\\t\\t[aSymbol first isUppercase\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[anEntry _ (Smalltalk\\n\\t\\t\\t\\t\\tat: aSymbol\\n\\t\\t\\t\\t\\tifAbsent:\\n\\t\\t\\t\\t\\t\\t[ self systemNavigation browseAllImplementorsOf: aSymbol.\\n\\t\\t\\t\\t\\t\\t^ nil]).\\n\\t\\t\\t\\tanEntry isNil ifTrue: [^ view flash].\\n\\t\\t\\t\\t(anEntry isBehavior or: [ anEntry isTrait ])\\n\\t\\t\\t\\t\\tifFalse: [ anEntry := anEntry class ].\\n\\t\\t\\t\\tToolSet browse: anEntry selector: nil.\\n\\t\\t] ifFalse:[ self systemNavigation browseAllImplementorsOf: aSymbol]]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 1/15/98 12:57'!\\ncancel \\n\\t\\\"Restore the text of the paragraph to be the text saved since initialization \\n\\tor the last accept. Undoer & Redoer: undoAndReselect:redoAndReselect:.\\n\\tThis used to call controlTerminate and controlInitialize but this seemed illogical.\\n\\tSure enough, nobody overrode them who had cancel in the menu, and if\\n\\tanybody really cared they could override cancel.\\\"\\n\\n\\tUndoSelection _ paragraph text.\\n\\tself undoer: #undoAndReselect:redoAndReselect: with: self selectionInterval with: (1 to: 0).\\n\\tview ifNotNil: [view clearInside].\\n\\tself changeParagraph: (paragraph text: initialText).\\n\\tUndoParagraph _ paragraph.\\n\\totherInterval _ UndoInterval _ 1 to: initialText size. \\\"so undo will replace all\\\"\\n\\tparagraph displayOn: Display.\\n\\tself selectAt: 1.\\n\\tself scrollToTop\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 2/17/2005 17:53'!\\nchangeAlignment\\n\\t| aList reply |\\n\\taList _ #(leftFlush centered justified rightFlush).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ifNil:[^self].\\n\\tself setAlignment: reply.\\n\\tparagraph composeAll.\\n\\tself recomputeSelection.\\n\\tself mvcRedisplay.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 3/14/2005 13:03'!\\nchangeEmphasis\\n\\t| aList reply |\\n\\taList _ #(normal bold italic narrow underlined struckOut).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[self setEmphasis: reply.\\n\\t\\tparagraph composeAll.\\n\\t\\tself recomputeSelection.\\n\\t\\tself mvcRedisplay].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'fc 2/19/2004 22:09'!\\nchangeEmphasisOrAlignment\\n\\t| aList reply |\\n\\taList _ #(normal bold italic narrow underlined struckOut leftFlush centered rightFlush justified).\\n\\treply _ (SelectionMenu labelList: aList lines: #(6) selections: aList) startUp.\\n\\treply ~~ nil ifTrue:\\n\\t\\t[(#(leftFlush centered rightFlush justified) includes: reply)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[paragraph perform: reply.\\n\\t\\t\\t\\tself recomputeInterval]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self setEmphasis: reply.\\n\\t\\t\\t\\tparagraph composeAll.\\n\\t\\t\\t\\tself recomputeSelection.\\n\\t\\t\\t\\tself mvcRedisplay]].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 10/22/2003 15:27'!\\nchangeStyle\\n\\t\\\"Let user change styles for the current text pane \\n\\t Moved from experimentalCommand to its own method \\\"\\n\\n\\t| aList reply style |\\n\\taList _ StrikeFont actualFamilyNames.\\n\\taList addFirst: 'DefaultTextStyle'.\\n\\treply _ (SelectionMenu labelList: aList lines: #(1) selections: aList) startUp.\\n\\treply ifNotNil:\\n\\t\\t[(style _ TextStyle named: reply) ifNil: [Beeper beep. ^ true].\\n\\t\\tparagraph textStyle: style copy.\\n\\t\\tparagraph composeAll.\\n\\t\\tself recomputeSelection.\\n\\t\\tself mvcRedisplay].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'RAA 3/15/2001 12:10'!\\nchangeStyleTo: aNewStyle\\n\\n\\tparagraph textStyle: aNewStyle.\\n\\tparagraph composeAll.\\n\\tself recomputeSelection.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 9/27/1999 11:54'!\\nchooseAlignment\\n\\tself changeAlignment! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/15/2003 22:40'!\\nclassCommentsContainingIt\\n\\t\\\"Open a browser class comments which contain the current selection somewhere in them.\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself terminateAndInitializeAround: [\\n\\t\\tself systemNavigation browseClassCommentsWithString: self selection string]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dvf 8/23/2003 11:51'!\\nclassNamesContainingIt\\n\\t\\\"Open a browser on classes whose names contain the selected string\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^self].\\n\\tself systemNavigation \\n\\t\\tbrowseClassesWithNamesContaining: self selection string\\n\\t\\tcaseSensitive: Sensor leftShiftDown! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:37'!\\nclipboardText\\n\\n\\t^ Clipboard clipboardText! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'!\\nclipboardText: text\\n\\n\\t^ Clipboard clipboardText: text! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'!\\nclipboardTextPut: text\\n\\n\\t^ Clipboard clipboardText: text! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 11/23/1998 15:21'!\\ncompareToClipboard\\n\\t\\\"Check to see if whether the receiver's text is the same as the text currently on the clipboard, and inform the user.\\\"\\n\\t| s1 s2 |\\n\\ts1 _ self clipboardText string.\\n\\ts2 _ paragraph text string.\\n\\ts1 = s2 ifTrue: [^ self inform: 'Exact match'].\\n\\n\\t(StringHolder new textContents:\\n\\t\\t(TextDiffBuilder buildDisplayPatchFrom: s1 to: s2))\\n\\t\\topenLabel: 'Comparison to Clipboard Text'! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 15:09'!\\ncopySelection\\n\\t\\\"Copy the current selection and store it in the paste buffer, unless a caret. Undoer & Redoer: undoCutCopy\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\n\\t\\\"Simulate 'substitute: self selection' without locking the controller\\\"\\n\\tUndoSelection _ self selection.\\n\\tself undoer: #undoCutCopy: with: self clipboardText.\\n\\tUndoInterval _ self selectionInterval.\\n\\tself clipboardTextPut: UndoSelection! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 16:33'!\\ncut\\n\\t\\\"Cut out the current selection and redisplay the paragraph if necessary. Undoer & Redoer: undoCutCopy:\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\n\\tself replaceSelectionWith: self nullText. \\n\\tself undoer: #undoCutCopy: with: self clipboardText.\\n\\tself clipboardTextPut: UndoSelection! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nexchange\\n\\t\\\"See comment in exchangeWith:\\\"\\n\\n\\tself exchangeWith: otherInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:34'!\\nexperimentalCommand\\n\\t\\\"Use for experimental command-key implementation. Using this, \\n\\tyou can try things out without forever needing to reinitialize the \\n\\tParagraphEditor.\\\"\\n\\n\\tself prettyPrint.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ls 10/10/1999\\n11:36'!\\nexplain\\n\\t\\\"Try to shed some light on what kind of entity the current selection\\nis. \\n\\tThe selection must be a single token or construct. Insert the answer\\nafter \\n\\tthe selection. Send private messages whose names begin with 'explain' \\n\\tthat return a string if they recognize the selection, else nil.\\\"\\n\\n\\t| string tiVars cgVars selectors delimitors numbers sorry reply symbol\\n|\\nCursor execute showWhile: \\n\\t\\t\\t[sorry _ '\\\"Sorry, I can''t explain that. Please select a single\\ntoken, construct, or special character.'.\\n\\t\\t\\tsorry _ sorry , (view canDiscardEdits\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [' Also, please cancel or accept.\\\"']\\n\\t\\t\\t\\t\\t\\t\\tifTrue: ['\\\"']).\\n\\t\\t\\t(string _ self selection asString) isEmpty\\n\\t\\t\\t\\tifTrue: [reply _ '']\\n\\t\\t\\t\\tifFalse: [string _ self explainScan: string.\\n\\t\\t\\t\\t\\t\\\"Remove space, tab, cr\\\"\\n\\t\\t\\t\\t\\t\\\"Temps and Instance vars need only test strings that are all\\nletters\\\"\\n\\t\\t\\t\\t\\t(string detect: [:char | (char isLetter or: [char isDigit]) not]\\n\\t\\t\\t\\t\\t\\tifNone: []) ifNil: \\n\\t\\t\\t\\t\\t\\t\\t[tiVars _ self explainTemp: string.\\n\\t\\t\\t\\t\\t\\t\\ttiVars == nil ifTrue: [tiVars _ self explainInst: string]].\\n\\t\\t\\t\\t\\t(tiVars == nil and: [model respondsTo: #explainSpecial:])\\n\\t\\t\\t\\t\\t\\tifTrue: [tiVars _ model explainSpecial: string].\\n\\t\\t\\t\\t\\ttiVars == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [tiVars _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [tiVars _ tiVars , '\\\\' withCRs].\\n\\t\\t\\t\\t\\t\\\"Context, Class, Pool, and Global vars, and Selectors need \\n\\t\\t\\t\\t\\tonly test symbols\\\"\\n\\t\\t\\t\\t\\t(Symbol hasInterned: string ifTrue: [:s | symbol _ s])\\n\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ self explainCtxt: symbol.\\n\\t\\t\\t\\t\\t\\t\\tcgVars == nil\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ self explainClass: symbol.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcgVars == nil ifTrue: [cgVars _ self explainGlobal: symbol]].\\n\\t\\t\\t\\t\\t\\t\\t\\\"See if it is a Selector (sent here or not)\\\"\\n\\t\\t\\t\\t\\t\\t\\tselectors _ self explainMySel: symbol.\\n\\t\\t\\t\\t\\t\\t\\tselectors == nil\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[selectors _ self explainPartSel: string.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tselectors == nil ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tselectors _ self explainAnySel: symbol]]]\\n\\t\\t\\t\\t\\t\\tifFalse: [selectors _ self explainPartSel: string].\\n\\t\\t\\t\\t\\tcgVars == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [cgVars _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [cgVars _ cgVars , '\\\\' withCRs].\\n\\t\\t\\t\\t\\tselectors == nil\\n\\t\\t\\t\\t\\t\\tifTrue: [selectors _ '']\\n\\t\\t\\t\\t\\t\\tifFalse: [selectors _ selectors , '\\\\' withCRs].\\n\\t\\t\\t\\t\\tstring size = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"single special characters\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelimitors _ self explainChar: string]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"matched delimitors\\\"\\n\\t\\t\\t\\t\\t\\t\\tdelimitors _ self explainDelimitor: string].\\n\\t\\t\\t\\t\\tnumbers _ self explainNumber: string.\\n\\t\\t\\t\\t\\tnumbers == nil ifTrue: [numbers _ ''].\\n\\t\\t\\t\\t\\tdelimitors == nil ifTrue: [delimitors _ ''].\\n\\t\\t\\t\\t\\treply _ tiVars , cgVars , selectors , delimitors , numbers].\\n\\t\\t\\treply size = 0 ifTrue: [reply _ sorry].\\n\\t\\t\\tself afterSelectionInsertAndSelect: reply]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:41'!\\nfileItIn\\n\\t\\\"Make a Stream on the text selection and fileIn it.\\n\\t 1/24/96 sw: moved here from FileController; this function can be useful from any text window that shows stuff in chunk format\\\"\\n\\n\\t| selection |\\n\\tselection _ self selection.\\n\\tself terminateAndInitializeAround:\\n\\t\\t[(ReadWriteStream on: selection string from: 1 to: selection size) fileIn].\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'CdG 10/17/2005 20:49'!\\nfind\\n\\t\\\"Prompt the user for a string to search for, and search the receiver from the current selection onward for it. 1/26/96 sw\\\"\\n\\n\\t| reply |\\n\\treply := UIManager default request: 'Find what? ' translated initialAnswer: ''.\\n\\treply size == 0 ifTrue: [^ self].\\n\\tself setSearch: reply.\\n\\tChangeText := FindText. \\\"Implies no replacement to againOnce: method\\\"\\n\\tself againOrSame: true\\n\\t\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nfindAgain\\n\\t\\\"Find the text-to-find again. 1/24/96 sw\\\"\\n\\n\\tself againOrSame: true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nfit\\n\\t\\\"Make the bounding rectangle of the paragraph contain all the text while \\n\\t not changing the width of the view of the paragraph. No effect on undoability\\n\\t of the preceding command.\\\"\\n\\n\\tparagraph clearVisibleRectangle.\\n\\tparagraph fit.\\n\\tparagraph displayOn: Display; outline.\\n\\tself recomputeInterval! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 09:42'!\\nimplementorsOfIt\\n\\t\\\"Open an implementors browser on the selected selector\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [ self systemNavigation browseAllImplementorsOf: aSelector]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:12'!\\nlineSelectAndEmptyCheck: returnBlock\\n\\t\\\"If the current selection is an insertion point, expand it to be the entire current line; if after that's done the selection is still empty, then evaluate the returnBlock, which will typically consist of '[^ self]' in the caller -- check senders of this method to understand this.\\\"\\n\\n\\tself selectLine. \\\"if current selection is an insertion point, then first select the entire line in which occurs before proceeding\\\"\\n\\tself hasSelection ifFalse: [self flash. ^ returnBlock value]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dgd 11/25/2004 18:03'!\\nmakeProjectLink\\n\\t\\n\\t| attribute thisSel |\\n\\t\\n\\tthisSel := self selection.\\n\\n\\tattribute := TextSqkProjectLink new. \\n\\tthisSel := attribute analyze: self selection asString.\\n\\n\\tthisSel ifNil: [^ true].\\n\\tself replaceSelectionWith: (thisSel asText addAttribute: attribute).\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:31'!\\nmethodNamesContainingIt\\n\\t\\\"Open a browser on methods names containing the selected string\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tCursor wait showWhile:\\n\\t\\t[self terminateAndInitializeAround: [self systemNavigation browseMethodsWhoseNamesContain: self selection string withBlanksTrimmed]].\\n\\tCursor normal show! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 9/6/2005 18:45'!\\nmethodSourceContainingIt\\n\\t\\\"Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source). Slow!!\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself systemNavigation browseMethodsWithSourceString: self selection string! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:28'!\\nmethodStringsContainingit\\n\\t\\\"Open a browser on methods which contain the current selection as part of a string constant.\\\"\\n\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\tself terminateAndInitializeAround: [self systemNavigation browseMethodsWithString: self selection string]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 10/2/97 11:34'!\\nmvcRedisplay\\n\\t\\\"Overridable by subclasses that do their own display\\\"\\n\\tDisplay fill: paragraph clippingRectangle \\n\\t\\t\\tfillColor: view backgroundColor.\\t\\\"very brute force\\\"\\n\\tself display! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/20/2002 11:21'!\\npaste\\n\\t\\\"Paste the text from the shared buffer over the current selection and \\n\\tredisplay if necessary. Undoer & Redoer: undoAndReselect.\\\"\\n\\n\\tself replace: self selectionInterval with: self clipboardText and:\\n\\t\\t[self selectAt: self pointIndex]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:36'!\\npasteRecent\\n\\t\\\"Paste an item chose from RecentClippings.\\\"\\n\\n\\t| clipping |\\n\\t(clipping _ Clipboard chooseRecentClipping) ifNil: [^ self].\\n\\tClipboard clipboardText: clipping.\\n\\t^ self paste! !\\n\\n!ParagraphEditor methodsFor: 'menu messages'!\\nperformMenuMessage: aSelector\\n\\t\\\"If a menu command is invoked, typeIn must be closed first, the selection\\n\\t must be unhighlighted before and rehighlighted after, and the marker\\n\\t must be updated.\\\"\\n\\n\\tself closeTypeIn.\\n\\tself deselect.\\n\\tsuper performMenuMessage: aSelector.\\n\\tself selectAndScroll.\\n\\tself updateMarker! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'rbb 2/16/2005 16:49'!\\npresentSpecialMenu\\n\\t\\\"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\\\"\\n\\n\\t| reply items |\\n\\tself terminateAndInitializeAround:\\n\\t\\t[reply _ (UIManager default chooseFrom: (items _ self specialMenuItems) lines: #()).\\n\\t\\treply = 0 ifTrue: [^ self].\\n\\t\\tCompiler new evaluate: (items at: reply) in: [] to: self]\\n\\t! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'!\\nprettyPrint\\n\\tself prettyPrint: false! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'md 7/13/2006 16:00'!\\nprettyPrint: decorated\\n\\t\\\"Reformat the contents of the receiver's view (a Browser).\\\"\\n\\n\\t| selectedClass newText |\\n\\tmodel selectedMessageCategoryName ifNil: [^ view flash].\\n\\tselectedClass _ model selectedClassOrMetaClass.\\n\\tnewText _ selectedClass prettyPrinterClass\\n\\t\\tformat: self text\\n\\t\\tin: selectedClass\\n\\t\\tnotifying: self\\n\\t\\tdecorated: decorated.\\n\\tnewText ifNotNil:\\n\\t\\t[self deselect; selectInvisiblyFrom: 1 to: paragraph text size.\\n\\t\\tself replaceSelectionWith: (newText asText makeSelectorBoldIn: selectedClass).\\n\\t\\tself selectAt: 1]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'!\\nprettyPrintWithColor\\n\\tself prettyPrint: true! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dew 3/7/2000 21:06'!\\nprinterSetup\\n\\t\\n\\tTextPrinter defaultTextPrinter inspect\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 11:47'!\\nreferencesToIt\\n\\t\\\"Open a references browser on the selected symbol\\\"\\n\\n\\t| aSymbol |\\n\\tself selectLine.\\n\\t((aSymbol _ self selectedSymbol) == nil or:\\n\\t\\t[(Smalltalk includesKey: aSymbol) not])\\n\\t\\t\\tifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: (Smalltalk associationAt: self selectedSymbol)]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'CdG 10/17/2005 20:47'!\\nsaveContentsInFile\\n\\t\\\"Save the receiver's contents string to a file, prompting the user for a file-name. Suggest a reasonable file-name.\\\"\\n\\n\\t| fileName stringToSave parentWindow labelToUse suggestedName lastIndex |\\n\\tstringToSave := paragraph text string.\\n\\tstringToSave size == 0 ifTrue: [^ self inform: 'nothing to save.'].\\n\\tparentWindow := self model dependents\\n\\t\\t\\t\\t\\t\\tdetect: [:dep | dep isKindOf: SystemWindow orOf: StandardSystemView]\\n\\t\\t\\t\\t\\t\\tifNone: [nil].\\n\\tlabelToUse := parentWindow\\n\\t\\tifNil: \\t\\t['Untitled']\\n\\t\\tifNotNil: \\t[parentWindow label].\\n\\tsuggestedName := nil.\\n\\t#(('Decompressed contents of: '\\t\\t'.gz')) do: \\\"can add more here...\\\"\\n\\t\\t[:leaderTrailer |\\n\\t\\t\\t(labelToUse beginsWith: leaderTrailer first) ifTrue:\\n\\t\\t\\t\\t[suggestedName := labelToUse copyFrom: leaderTrailer first size + 1 to: labelToUse size.\\n\\t\\t\\t\\t(labelToUse endsWith: leaderTrailer last)\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[suggestedName := suggestedName copyFrom: 1 to: suggestedName size - leaderTrailer last size]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[lastIndex := suggestedName lastIndexOf: $. ifAbsent: [0].\\n\\t\\t\\t\\t\\t\\t(lastIndex = 0 or: [lastIndex = 1]) ifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[suggestedName := suggestedName copyFrom: 1 to: lastIndex - 1]]]].\\n\\n\\tsuggestedName ifNil:\\n\\t\\t[suggestedName := labelToUse, '.text'].\\n\\t\\t\\t\\n\\tfileName := UIManager default request: 'File name?' translated\\n\\t\\t\\tinitialAnswer: suggestedName.\\n\\tfileName isEmptyOrNil ifFalse:\\n\\t\\t[(FileStream newFileNamed: fileName) nextPutAll: stringToSave; close]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'bf 10/13/1999 09:09'!\\nselectedSelector\\n\\t\\\"Try to make a selector out of the current text selection\\\"\\n\\t^self selection string findSelector! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'yo 7/5/2004 16:38'!\\nselectedSymbol\\n\\t\\\"Return the currently selected symbol, or nil if none. Spaces, tabs and returns are ignored\\\"\\n\\n\\t| aString |\\n\\tself hasCaret ifTrue: [^ nil].\\n\\taString _ self selection string.\\n\\taString isOctetString ifTrue: [aString _ aString asOctetString].\\n\\taString _ aString copyWithoutAll:\\n\\t\\t{Character space. Character cr. Character tab}.\\n\\taString size == 0 ifTrue: [^ nil].\\n\\tSymbol hasInterned: aString ifTrue: [:sym | ^ sym].\\n\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 2/23/2001 09:26'!\\nselectionAsTiles\\n\\t\\\"Try to make new universal tiles from the selected text\\\"\\n\\t| selection tiles |\\n\\n\\tselection _ self selection.\\n\\tself terminateAndInitializeAround:\\n\\t\\t[self currentHand attachMorph: (tiles _ Player tilesFrom: selection).\\n\\t\\tPreferences tileTranslucentDrag\\n\\t\\t\\tifTrue: [tiles lookTranslucent]\\n\\t\\t\\tifFalse: [tiles align: tiles topLeft \\n\\t\\t\\t \\t\\t\\twith: self currentHand position + tiles cursorBaseOffset]].! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'gm 2/16/2003 20:38'!\\nsendContentsToPrinter\\n\\t| textToPrint printer parentWindow |\\n\\ttextToPrint := paragraph text.\\n\\ttextToPrint size == 0 ifTrue: [^self inform: 'nothing to print.'].\\n\\tprinter := TextPrinter defaultTextPrinter.\\n\\tparentWindow := self model dependents \\n\\t\\t\\t\\tdetect: [:dep | dep isSystemWindow]\\n\\t\\t\\t\\tifNone: [nil].\\n\\tparentWindow isNil \\n\\t\\tifTrue: [printer documentTitle: 'Untitled']\\n\\t\\tifFalse: [printer documentTitle: parentWindow label].\\n\\tprinter printText: textToPrint! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:30'!\\nsendersOfIt\\n\\t\\\"Open a senders browser on the selected selector\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: aSelector]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/18/2002 17:28'!\\nsetAlignment: aSymbol\\n\\t| attr interval |\\n\\tattr _ TextAlignment perform: aSymbol.\\n\\tinterval _ self encompassLine: self selectionInterval.\\n\\tparagraph replaceFrom: interval first to: interval last with:\\n\\t\\t((paragraph text copyFrom: interval first to: interval last) addAttribute: attr) displaying: true.\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:27'!\\nsetSearchString\\n\\t\\\"Make the current selection, if any, be the current search string.\\\"\\n\\tself hasCaret ifTrue: [view flash. ^ self].\\n\\tself setSearch: self selection string! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'dgd 8/28/2004 13:59'!\\nspawn\\n\\t\\\"Create and schedule a message browser for the code of the model's \\n\\tselected message. Retain any edits that have not yet been accepted.\\\"\\n\\t| code |\\n\\tcode _ paragraph text string.\\n\\tself cancel.\\n\\tmodel notNil ifTrue:[model spawn: code].\\n! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:44'!\\nspawnWorkspace\\n\\t| toUse |\\n\\tself selectLine.\\n\\ttoUse _ self selection asString.\\n\\ttoUse size > 0 ifFalse:\\n\\t\\t[toUse _ paragraph text string.\\n\\t\\ttoUse size > 0 ifFalse: [^ self flash]].\\n\\t\\\"NB: BrowserCodeController's version does a cancel here\\\"\\n\\tself terminateAndInitializeAround:\\n\\t\\t[Utilities openScratchWorkspaceLabeled: 'Untitled' contents: toUse]! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 4/29/96'!\\nspecialMenuItems\\n\\t\\\"Refer to comment under #presentSpecialMenu. .\\n\\t : added objectsReferencingIt,\\\"\\n\\n\\t^ #(\\t'Transcript cr; show: ''testing'''\\n\\t\\t\\t'view superView model inspect'\\n\\t\\t\\t'view superView model browseObjClass'\\n\\t\\t\\t'view display'\\n\\t\\t\\t'self inspect'\\n\\t\\t\\t'view backgroundColor: Color fromUser'\\n\\t\\t\\t'view topView inspect'\\n\\t\\t\\t'self compareToClipboard'\\n\\t\\t\\t'view insideColor: Form white'\\n\\t\\t\\t'self objectsReferencingIt'\\n\\t\\t) ! !\\n\\n!ParagraphEditor methodsFor: 'menu messages' stamp: 'SqR 11/14/2000 12:15'!\\nundo\\n\\t\\\"Reset the state of the paragraph prior to the previous edit.\\n\\t If another ParagraphEditor instance did that edit, UndoInterval is invalid;\\n\\t just recover the contents of the undo-buffer at the start of the paragraph.\\\"\\n\\n\\tsensor flushKeyboard. \\\"a way to flush stuck keys\\\"\\n\\tself closeTypeIn.\\n\\n\\tUndoParagraph == paragraph ifFalse: \\\"Can't undo another paragraph's edit\\\"\\n\\t\\t[UndoMessage _ Message selector: #undoReplace.\\n\\t\\tUndoInterval _ 1 to: 0.\\n\\t\\tUndone _ true].\\n\\tUndoInterval ~= self selectionInterval ifTrue: \\\"blink the actual target\\\"\\n\\t\\t[self selectInterval: UndoInterval; deselect].\\n\\n\\t\\\"Leave a signal of which phase is in progress\\\"\\n\\tUndoParagraph _ Undone ifTrue: [#redoing] ifFalse: [#undoing].\\n\\tUndoMessage sentTo: self.\\n\\tUndoParagraph _ paragraph! !\\n\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:37'!\\nadjustSelection: directionBlock\\n\\t\\\"Helper function for Cursor movement. Always moves point thus allowing selections to shrink. \\\"\\n\\t\\\"See also expandSelection:\\\"\\n\\t\\\"Accepts a one argument Block that computes the new postion given an old one.\\\"\\n\\t| newPosition |\\n\\tnewPosition _ directionBlock value: self pointIndex.\\n\\tself selectMark: self markIndex point: newPosition.\\n\\t^true.! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 10/28/2003 12:11'!\\nafterSelectionInsertAndSelect: aString\\n\\n\\tself insertAndSelect: aString at: self stopIndex ! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/17/2002 16:11'!\\ncomputeIntervalFrom: start to: stop\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\tself setMark: start.\\n\\tself setPoint: stop + 1.! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:21'!\\ncorrectFrom: start to: stop with: aString\\n\\t\\\"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.\\\"\\n\\t| wasShowing userSelection delta loc |\\n\\taString = '#insert period' ifTrue:\\n\\t\\t[loc _ start.\\n\\t\\t[(loc _ loc-1)>0 and: [(paragraph text string at: loc) isSeparator]]\\n\\t\\t\\twhileTrue: [loc _ loc-1].\\n\\t\\t^ self correctFrom: loc+1 to: loc with: '.'].\\n\\t(wasShowing _ selectionShowing) ifTrue: [ self reverseSelection ].\\n\\tuserSelection _ self selectionInterval.\\n\\n\\tself selectInvisiblyFrom: start to: stop.\\n\\tself replaceSelectionWith: aString asText.\\n\\n\\tdelta _ aString size - (stop - start + 1).\\n\\tself selectInvisiblyFrom:\\n\\t\\tuserSelection first + (userSelection first > start ifFalse: [ 0 ] ifTrue: [ delta ])\\n\\t\\tto: userSelection last + (userSelection last > start ifFalse: [ 0 ] ifTrue: [ delta ]).\\n\\twasShowing ifTrue: [ self reverseSelection ].\\n! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:21'!\\nencompassLine: anInterval\\n\\t\\\"Return an interval that encompasses the entire line\\\"\\n\\t| string left right |\\n\\tstring _ paragraph text string.\\n\\tleft _ (string lastIndexOf: Character cr startingAt: anInterval first - 1 ifAbsent:[0]) + 1.\\n\\tright _ (string indexOf: Character cr startingAt: anInterval last + 1 ifAbsent: [string size + 1]) - 1.\\n\\t^left to: right! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 12/17/1998 09:41'!\\ninsertAndSelect: aString at: anInteger\\n\\n\\tself replace: (anInteger to: anInteger - 1)\\n\\t\\twith: (Text string: (' ' , aString)\\n\\t\\t\\t\\t\\tattributes: emphasisHere)\\n\\t\\tand: [self selectAndScroll]! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:25'!\\nnextTokenFrom: start direction: dir\\n\\t\\\"simple token-finder for compiler automated corrections\\\"\\n\\t| loc str |\\n\\tloc _ start + dir.\\n\\tstr _ paragraph text string.\\n\\t[(loc between: 1 and: str size) and: [(str at: loc) isSeparator]]\\n\\t\\twhileTrue: [loc _ loc + dir].\\n\\t^ loc! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/20/1998 08:31'!\\nnotify: aString at: anInteger in: aStream \\n\\t\\\"The compilation of text failed. The syntax error is noted as the argument, \\n\\taString. Insert it in the text at starting character position anInteger.\\\"\\n\\n\\tself insertAndSelect: aString at: (anInteger max: 1)! !\\n\\n!ParagraphEditor methodsFor: 'new selection'!\\nselectAt: characterIndex \\n\\t\\\"Deselect, then place the caret before the character at characterIndex.\\n\\t Be sure it is in view.\\\"\\n\\n\\tself selectFrom: characterIndex to: characterIndex - 1! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:50'!\\nselectFrom: start to: stop\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\t(start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse:\\n\\t\\t[self deselect.\\n\\t\\tself selectInvisiblyFrom: start to: stop].\\n\\tself selectAndScroll! !\\n\\n!ParagraphEditor methodsFor: 'new selection'!\\nselectInterval: anInterval\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\tself selectFrom: anInterval first to: anInterval last! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/9/1998 20:59'!\\nselectInvisiblyFrom: start to: stop\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\t^ self computeIntervalFrom: start to: stop! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:17'!\\nselectInvisiblyMark: mark point: point\\n\\t\\\"Select the designated characters, inclusive. Make no visual changes.\\\"\\n\\n\\t^ self computeIntervalFrom: mark to: point! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:17'!\\nselectLine\\n\\t\\\"Make the receiver's selection, if it currently consists of an insertion point only, encompass the current line.\\\"\\n\\tself hasSelection ifTrue:[^self].\\n\\tself selectInterval: (self encompassLine: self selectionInterval)! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:18'!\\nselectMark: mark point: point\\n\\t\\\"Deselect, then select the specified characters inclusive.\\n\\t Be sure the selection is in view.\\\"\\n\\n\\t(mark = self markIndex and: [point + 1 = self pointIndex]) ifFalse:\\n\\t\\t[self deselect.\\n\\t\\tself selectInvisiblyMark: mark point: point].\\n\\tself selectAndScroll! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 18:49'!\\nselectPrecedingIdentifier\\n\\t\\\"Invisibly select the identifier that ends at the end of the selection, if any.\\\"\\n\\n\\t| string sep stop tok |\\n\\ttok _ false.\\n\\tstring _ paragraph text string.\\n\\tstop _ self stopIndex - 1.\\n\\t[stop > 0 and: [(string at: stop) isSeparator]] whileTrue: [stop _ stop - 1].\\n\\tsep _ stop.\\n\\t[sep > 0 and: [(string at: sep) tokenish]] whileTrue: [tok _ true. sep _ sep - 1].\\n\\ttok ifTrue: [self selectInvisiblyFrom: sep + 1 to: stop]! !\\n\\n!ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:51'!\\nselectWord\\n\\t\\\"Select delimited text or word--the result of double-clicking.\\\"\\n\\n\\t| openDelimiter closeDelimiter direction match level leftDelimiters rightDelimiters\\n\\tstring here hereChar start stop |\\n\\tstring _ paragraph text string.\\n\\there _ self pointIndex.\\n\\t(here between: 2 and: string size)\\n\\t\\tifFalse: [\\\"if at beginning or end, select entire string\\\"\\n\\t\\t\\t^self selectFrom: 1 to: string size].\\n\\tleftDelimiters _ '([{<''\\\"\\n'.\\n\\trightDelimiters _ ')]}>''\\\"\\n'.\\n\\topenDelimiter _ string at: here - 1.\\n\\tmatch _ leftDelimiters indexOf: openDelimiter.\\n\\tmatch > 0\\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"delimiter is on left -- match to the right\\\"\\n\\t\\t\\tstart _ here.\\n\\t\\t\\tdirection _ 1.\\n\\t\\t\\there _ here - 1.\\n\\t\\t\\tcloseDelimiter _ rightDelimiters at: match]\\n\\t\\tifFalse: \\n\\t\\t\\t[openDelimiter _ string at: here.\\n\\t\\t\\tmatch _ rightDelimiters indexOf: openDelimiter.\\n\\t\\t\\tmatch > 0\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"delimiter is on right -- match to the left\\\"\\n\\t\\t\\t\\t\\tstop _ here - 1.\\n\\t\\t\\t\\t\\tdirection _ -1.\\n\\t\\t\\t\\t\\tcloseDelimiter _ leftDelimiters at: match]\\n\\t\\t\\t\\tifFalse: [\\\"no delimiters -- select a token\\\"\\n\\t\\t\\t\\t\\tdirection _ -1]].\\n\\tlevel _ 1.\\n\\t[level > 0 and: [direction > 0\\n\\t\\t\\tifTrue: [here < string size]\\n\\t\\t\\tifFalse: [here > 1]]]\\n\\t\\twhileTrue: \\n\\t\\t\\t[hereChar _ string at: (here _ here + direction).\\n\\t\\t\\tmatch = 0\\n\\t\\t\\t\\tifTrue: [\\\"token scan goes left, then right\\\"\\n\\t\\t\\t\\t\\thereChar tokenish\\n\\t\\t\\t\\t\\t\\tifTrue: [here = 1\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[start _ 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"go right if hit string start\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdirection _ 1]]\\n\\t\\t\\t\\t\\t\\tifFalse: [direction < 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[start _ here + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"go right if hit non-token\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdirection _ 1]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [level _ 0]]]\\n\\t\\t\\t\\tifFalse: [\\\"bracket match just counts nesting level\\\"\\n\\t\\t\\t\\t\\thereChar = closeDelimiter\\n\\t\\t\\t\\t\\t\\tifTrue: [level _ level - 1\\\"leaving nest\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [hereChar = openDelimiter \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [level _ level + 1\\\"entering deeper nest\\\"]]]].\\n\\n\\tlevel > 0 ifTrue: [\\\"in case ran off string end\\\"\\there _ here + direction].\\n\\tdirection > 0\\n\\t\\tifTrue: [self selectFrom: start to: here - 1]\\n\\t\\tifFalse: [self selectFrom: here + 1 to: stop]! !\\n\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:51'!\\ncomment\\n\\t\\\"All key actions that are neither editing nor typing actions have to\\n\\tsend closeTypeIn at first. See comment in openTypeIn closeTypeIn\\\"! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:08'!\\ncursorDown: characterStream \\n\\n\\t\\\"Private - Move cursor from position in current line to same position in\\n\\tnext line. If next line too short, put at end. If shift key down,\\n\\tselect.\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor:[:position | self\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:line | line + 1]\\n\\t\\t\\t\\tforward: true]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 10/28/2003 10:47'!\\ncursorEnd: characterStream \\n\\n\\t\\\"Private - Move cursor end of current line.\\\"\\n\\t| string |\\n\\tself closeTypeIn: characterStream.\\n\\tstring _ paragraph text string.\\n\\tself\\n\\t\\tmoveCursor:\\n\\t\\t\\t[:position | Preferences wordStyleCursorMovement\\n\\t\\t\\t\\tifTrue:[| targetLine |\\n\\t\\t\\t\\t\\ttargetLine _ paragraph lines at:(paragraph lineIndexOfCharacterIndex: position).\\n\\t\\t\\t\\t\\ttargetLine = paragraph lines last\\n\\t\\t\\t\\t\\t\\tifTrue:[targetLine last + 1]\\n\\t\\t\\t\\t\\t\\tifFalse:[targetLine last]]\\n\\t\\t\\t\\tifFalse:[\\n\\t\\t\\t\\t\\tstring\\n\\t\\t\\t\\t\\t\\tindexOf: Character cr\\n\\t\\t\\t\\t\\t\\tstartingAt: position\\n\\t\\t\\t\\t\\t\\tifAbsent:[string size + 1]]]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | string size + 1].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/20/2002 12:14'!\\ncursorHome: characterStream \\n\\n\\t\\\"Private - Move cursor from position in current line to beginning of\\n\\tcurrent line. If control key is pressed put cursor at beginning of text\\\"\\n\\n\\t| string |\\n\\n\\tstring _ paragraph text string.\\n\\tself\\n\\t\\tmoveCursor: [ :position | Preferences wordStyleCursorMovement\\n\\t\\t\\t\\tifTrue:[\\n\\t\\t\\t\\t\\t(paragraph lines at:(paragraph lineIndexOfCharacterIndex: position)) first]\\n\\t\\t\\t\\tifFalse:[\\n\\t\\t\\t\\t\\t(string\\n\\t\\t\\t\\t\\t\\tlastIndexOf: Character cr\\n\\t\\t\\t\\t\\t\\tstartingAt: position - 1\\n\\t\\t\\t\\t\\t\\tifAbsent:[0]) + 1]]\\n\\t\\tforward: false\\n\\t\\tspecialBlock: [:dummy | 1].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:07'!\\ncursorLeft: characterStream \\n\\t\\\"Private - Move cursor left one character if nothing selected, otherwise \\n\\tmove cursor to beginning of selection. If the shift key is down, start \\n\\tselecting or extending current selection. Don't allow cursor past \\n\\tbeginning of text\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor:[:position | position - 1 max: 1]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:position | self previousWord: position].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'!\\ncursorPageDown: characterStream \\n\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor: [:position |\\n\\t\\t\\tself\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:lineNo | lineNo + self pageHeight]\\n\\t\\t\\t\\tforward: true]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'!\\ncursorPageUp: characterStream \\n\\n\\tself closeTypeIn: characterStream.\\n\\tself \\n\\t\\tmoveCursor: [:position |\\n\\t\\t\\tself\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:lineNo | lineNo - self pageHeight]\\n\\t\\t\\t\\tforward: false]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:01'!\\ncursorRight: characterStream \\n\\t\\\"Private - Move cursor right one character if nothing selected, \\n\\totherwise move cursor to end of selection. If the shift key is down, \\n\\tstart selecting characters or extending already selected characters. \\n\\tDon't allow cursor past end of text\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor: [:position | position + 1]\\n\\t\\tforward: true\\n\\t\\tspecialBlock:[:position | self nextWord: position].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:15'!\\ncursorUp: characterStream \\n\\n\\\"Private - Move cursor from position in current line to same position in\\nprior line. If prior line too short, put at end\\\"\\n\\n\\tself closeTypeIn: characterStream.\\n\\tself\\n\\t\\tmoveCursor: [:position | self\\n\\t\\t\\t\\tsameColumn: position\\n\\t\\t\\t\\tnewLine:[:line | line - 1]\\n\\t\\t\\t\\tforward: false]\\n\\t\\tforward: false\\n\\t\\tspecialBlock:[:dummy | dummy].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'di 12/3/2001 21:49'!\\nescapeToDesktop: characterStream \\n\\t\\\"Pop up a morph to field keyboard input in the context of the desktop\\\"\\n\\n\\tSmalltalk isMorphic ifTrue: [ActiveWorld putUpWorldMenuFromEscapeKey].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'dvf 12/8/2001 00:46'!\\nraiseContextMenu: characterStream \\n\\t\\\"AFAIK, this is never called in morphic, because a subclass overrides it. Which is good, because a ParagraphEditor doesn't know about Morphic and thus duplicates the text-editing actions that really belong in the specific application, not the controller. So the context menu this would raise is likely to be out of date.\\\"\\n\\tself yellowButtonActivity.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'!\\nselectCurrentTypeIn: characterStream \\n\\t\\\"Select what would be replaced by an undo (e.g., the last typeIn).\\\"\\n\\n\\t| prior |\\n\\n\\tself closeTypeIn: characterStream.\\n\\tprior _ otherInterval.\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself selectInterval: UndoInterval.\\n\\totherInterval _ prior.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'sma 12/15/1999 11:46'!\\nselectWord: characterStream\\n\\tsensor keyboard.\\n\\tself closeTypeIn: characterStream.\\n\\tself selectWord.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'!\\nsetSearchString: characterStream\\n\\t\\\"Establish the current selection as the current search string.\\\"\\n\\n\\t| aString |\\n\\tself closeTypeIn: characterStream.\\n\\tsensor keyboard.\\n\\tself lineSelectAndEmptyCheck: [^ true].\\n\\taString _ self selection string.\\n\\taString size == 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self flash]\\n\\t\\tifFalse:\\n\\t\\t\\t[self setSearch: aString].\\n\\t^ true! !\\n\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mir 8/3/2004 13:31'!\\nblinkParenAt: parenLocation \\n\\tself text\\n\\t\\taddAttribute: TextEmphasis bold\\n\\t\\tfrom: parenLocation\\n\\t\\tto: parenLocation.\\n\\tlastParentLocation _ parenLocation.! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/7/2002 04:03'!\\nblinkPrevParen\\n\\t| openDelimiter closeDelimiter level string here hereChar |\\n\\tstring _ paragraph text string.\\n\\there _ startBlock stringIndex.\\n\\topenDelimiter _ sensor keyboardPeek.\\n\\tcloseDelimiter _ '([{' at: (')]}' indexOf: openDelimiter).\\n\\tlevel _ 1.\\n\\t[level > 0 and: [here > 2]]\\n\\t\\twhileTrue:\\n\\t\\t\\t[hereChar _ string at: (here _ here - 1).\\n\\t\\t\\thereChar = closeDelimiter\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[level _ level - 1.\\n\\t\\t\\t\\t\\tlevel = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self blinkParenAt: here]]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[hereChar = openDelimiter\\n\\t\\t\\t\\t\\t\\tifTrue: [level _ level + 1]]].! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mir 8/3/2004 13:31'!\\nclearParens\\n\\tlastParentLocation ifNotNil:\\n\\t\\t[self text string size >= lastParentLocation ifTrue: [\\n\\t\\t\\tself text\\n\\t\\t\\t\\tremoveAttribute: TextEmphasis bold\\n\\t\\t\\t\\tfrom: lastParentLocation\\n\\t\\t\\t\\tto: lastParentLocation]]\\n! !\\n\\n!ParagraphEditor methodsFor: 'parenblinking' stamp: 'mikki 1/5/2005 14:10'!\\ndispatchOnCharacter: char with: typeAheadStream\\n\\t\\\"Carry out the action associated with this character, if any.\\n\\tType-ahead is passed so some routines can flush or use it.\\\"\\n\\n\\t| honorCommandKeys |\\n\\tself clearParens.\\n \\n\\t\\\"mikki 1/3/2005 21:31 Preference for auto-indent on return added.\\\"\\n\\tchar asciiValue = 13 ifTrue: [\\n\\t\\t^Preferences autoIndent \\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tsensor controlKeyPressed\\n\\t\\t\\t\\t\\tifTrue: [self normalCharacter: typeAheadStream]\\n\\t\\t\\t\\t\\tifFalse: [self crWithIndent: typeAheadStream]]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsensor controlKeyPressed\\n\\t\\t\\t\\t\\tifTrue: [self crWithIndent: typeAheadStream]\\n\\t\\t\\t\\t\\tifFalse: [self normalCharacter: typeAheadStream]]].\\n\\n\\t((honorCommandKeys _ Preferences cmdKeysInText) and: [char = Character enter])\\n\\t\\tifTrue: [^ self dispatchOnEnterWith: typeAheadStream].\\n\\t\\t\\n\\t\\\"Special keys overwrite crtl+key combinations - at least on Windows. To resolve this\\n\\tconflict, assume that keys other than cursor keys aren't used together with Crtl.\\\" \\n\\t((self class specialShiftCmdKeys includes: char asciiValue) and: [char asciiValue < 27])\\n\\t\\tifTrue: [^ sensor controlKeyPressed\\n\\t\\t\\tifTrue: [self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream]\\n\\t\\t\\tifFalse: [self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]].\\n\\n\\t\\\"backspace, and escape keys (ascii 8 and 27) are command keys\\\"\\n\\t((honorCommandKeys and: [sensor commandKeyPressed]) or: [self class specialShiftCmdKeys includes: char asciiValue]) ifTrue:\\n\\t\\t[^ sensor leftShiftDown\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]].\\n\\n\\t\\\"the control key can be used to invoke shift-cmd shortcuts\\\"\\n\\t(honorCommandKeys and: [sensor controlKeyPressed])\\n\\t\\tifTrue:\\n\\t\\t\\t[^ self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream].\\n\\n\\t(')]}' includes: char)\\n\\t\\tifTrue: [self blinkPrevParen].\\n\\n\\t^ self perform: #normalCharacter: with: typeAheadStream! !\\n\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\ncomputeMarkerRegion \\n\\t\\\"Refer to the comment in ScrollController|computeMarkerRegion.\\\"\\n\\n\\tparagraph compositionRectangle height = 0\\n\\t\\tifTrue:\\t[^0@0 extent: Preferences scrollBarWidth @ scrollBar inside height]\\n\\t\\tifFalse:\\t[^0@0 extent:\\n\\t\\t\\t\\t\\tPreferences scrollBarWidth \\n\\t\\t\\t\\t\\t\\t@ ((paragraph clippingRectangle height asFloat /\\n\\t\\t\\t\\t\\t\\t\\tself scrollRectangleHeight * scrollBar inside height) rounded\\n\\t\\t\\t\\t\\t\\t\\tmin: scrollBar inside height)]! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nmarkerDelta\\n\\n\\t^marker top - scrollBar top - ((paragraph clippingRectangle top -\\n\\t\\tparagraph compositionRectangle top) asFloat /\\n\\t\\t\\t(self scrollRectangleHeight max: 1) asFloat *\\n\\t\\t\\t\\tscrollBar height asFloat) rounded! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollAmount \\n\\t\\\"Refer to the comment in ScrollController|scrollAmount.\\\"\\n\\n\\t^sensor cursorPoint y - scrollBar top! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollBar\\n\\t^ scrollBar! !\\n\\n!ParagraphEditor methodsFor: 'scrolling' stamp: 'BG 12/12/2003 15:31'!\\nscrollBy: heightToMove\\n\\t\\\"Move the paragraph by heightToMove, and reset the text selection.\\\"\\n\\t^ paragraph scrollBy: heightToMove withSelectionFrom: self pointBlock to: self markBlock! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollRectangleHeight\\n\\n\\t^paragraph compositionRectangle height \\n\\t\\t+ paragraph lineGrid! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollToBottom\\n\\t\\\"Scroll so that the tail end of the text is visible in the view. 5/6/96 sw\\\"\\n\\n\\tself scrollView: (paragraph clippingRectangle bottom \\n\\t\\t- paragraph compositionRectangle bottom)! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollToTop\\n\\t\\\"Scroll so that the paragraph is at the top of the view.\\\"\\n\\n\\tself scrollView: (paragraph clippingRectangle top \\n\\t\\t- paragraph compositionRectangle top)! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nscrollView: anInteger \\n\\t\\\"Paragraph scrolling uses opposite polarity\\\"\\n\\t^ self scrollBy: anInteger negated! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nupdateMarker\\n\\t\\\"A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph.\\\"\\n\\tself moveMarkerTo: self computeMarkerRegion! !\\n\\n!ParagraphEditor methodsFor: 'scrolling'!\\nviewDelta \\n\\t\\\"Refer to the comment in ScrollController|viewDelta.\\\"\\n\\n\\t^paragraph clippingRectangle top \\n\\t\\t- paragraph compositionRectangle top \\n\\t\\t- ((marker top - scrollBar inside top) asFloat \\n\\t\\t\\t\\t/ scrollBar inside height asFloat * self scrollRectangleHeight asFloat)\\n\\t\\t\\troundTo: paragraph lineGrid! !\\n\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessBlueButton\\n\\t\\\"The user pressed the blue button on the mouse. Determine what action \\n\\tto take.\\\"\\n\\n\\t^self! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessKeyboard\\n\\t\\\"Determine whether the user pressed the keyboard. If so, read the keys.\\\"\\n\\n\\tsensor keyboardPressed ifTrue: [self readKeyboard]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessMouseButtons\\n\\t\\\"Determine whether the user pressed any mouse button. For each possible \\n\\tbutton, determine what actions to take.\\\"\\n\\n\\tsensor redButtonPressed ifTrue: [self processRedButton].\\n\\tsensor yellowButtonPressed ifTrue: [self processYellowButton].\\n\\tsensor blueButtonPressed ifTrue: [self processBlueButton]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access' stamp: 'th 9/19/2002 18:24'!\\nprocessRedButton\\n\\t\\\"The user pressed a red mouse button, meaning create a new text \\n\\tselection. Highlighting the selection is carried out by the paragraph \\n\\titself. Double clicking causes a selection of the area between the nearest \\n\\tenclosing delimitors.\\\"\\n\\n\\t| selectionBlocks clickPoint oldDelta oldInterval previousMarkBlock previousPointBlock |\\n\\n\\tclickPoint _ sensor cursorPoint.\\n\\t(view containsPoint: clickPoint) ifFalse: [^ self].\\n\\t(paragraph clickAt: clickPoint for: model controller: self) ifTrue: [^ self].\\n\\toldInterval _ self selectionInterval.\\n\\tpreviousMarkBlock _ self markBlock.\\n\\tpreviousPointBlock _ self pointBlock.\\n\\toldDelta _ paragraph scrollDelta.\\n\\tsensor leftShiftDown\\n\\t\\tifFalse:\\n\\t\\t\\t[self deselect.\\n\\t\\t\\tself closeTypeIn.\\n\\t\\t\\tselectionBlocks _ paragraph mouseSelect: clickPoint]\\n\\t\\tifTrue:\\n\\t\\t\\t[selectionBlocks _ paragraph extendSelectionMark: self markBlock pointBlock: self pointBlock.\\n\\t\\t\\tself closeTypeIn].\\n\\tselectionShowing _ true.\\n\\tself markBlock: (selectionBlocks at: 1).\\n\\tself pointBlock: (selectionBlocks at: 2).\\n\\t(self hasCaret\\n\\t\\tand: [previousMarkBlock = self markBlock and: [previousPointBlock = self pointBlock]])\\n\\t\\tifTrue: [self selectWord].\\n\\toldDelta ~= paragraph scrollDelta \\\"case of autoscroll\\\"\\n\\t\\t\\tifTrue: [self updateMarker].\\n\\tself setEmphasisHere.\\n\\t(self isDisjointFrom: oldInterval) ifTrue:\\n\\t\\t[otherInterval _ oldInterval]! !\\n\\n!ParagraphEditor methodsFor: 'sensor access'!\\nprocessYellowButton\\n\\t\\\"User pressed the yellow button on the mouse. Determine what actions to \\n\\ttake.\\\"\\n\\n\\tself yellowButtonActivity! !\\n\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'yo 3/16/2004 13:05'!\\nbackTo: startIndex\\n\\t\\\"During typing, backspace to startIndex. Deleted characters fall into three\\n\\t clusters, from left to right in the text: (1) preexisting characters that were\\n\\t backed over; (2) newly typed characters that were backed over (excluding\\n\\t typeahead, which never even appears); (3) preexisting characters that\\n\\t were highlighted before typing began. If typing has not yet been opened,\\n\\t open it and watch for the first and third cluster. If typing has been opened,\\n\\t watch for the first and second cluster. Save characters from the first and third\\n\\t cluster in UndoSelection. Tally characters from the first cluster in UndoMessage's parameter.\\n\\t Delete all the clusters. Do not alter Undoer or UndoInterval (except via\\n\\t openTypeIn). The code is shorter than the comment.\\\"\\n\\n\\t| saveLimit newBackovers |\\n\\tsaveLimit _ beginTypeInBlock == nil\\n\\t\\tifTrue: [self openTypeIn. UndoSelection _ self nullText. self stopIndex]\\n\\t\\tifFalse: [self startOfTyping].\\n\\tself setMark: startIndex.\\n\\tstartIndex < saveLimit ifTrue:\\n\\t\\t[newBackovers _ self startOfTyping - startIndex.\\n\\t\\tbeginTypeInBlock _ self startIndex.\\n\\t\\tUndoSelection replaceFrom: 1 to: 0 with:\\n\\t\\t\\t(paragraph text copyFrom: startIndex to: saveLimit - 1).\\n\\t\\tUndoMessage argument: (UndoMessage argument ifNil: [1]) + newBackovers].\\n\\tself zapSelectionWith: self nullText.\\n\\tself unselect! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 17:40'!\\ncloseTypeIn\\n\\t\\\"See comment in openTypeIn. It is important to call closeTypeIn before executing\\n\\t any non-typing key, making a new selection, etc. It is called automatically for\\n\\t menu commands.\\n\\t Typing commands can call 'closeTypeIn: aCharacterStream' instead of this to\\n\\t save typeahead. Undoer & Redoer: undoAndReselect:redoAndReselect:.\\\"\\n\\n\\t| begin stop |\\n\\tbeginTypeInBlock == nil ifFalse:\\n\\t\\t[(UndoMessage sends: #noUndoer) ifTrue: \\\"should always be true, but just in case...\\\"\\n\\t\\t\\t[begin _ self startOfTyping.\\n\\t\\t\\tstop _ self stopIndex.\\n\\t\\t\\tself undoer: #undoAndReselect:redoAndReselect:\\n\\t\\t\\t\\twith: (begin + UndoMessage argument to: begin + UndoSelection size - 1)\\n\\t\\t\\t\\twith: (stop to: stop - 1).\\n\\t\\t\\tUndoInterval _ begin to: stop - 1].\\n\\t\\tbeginTypeInBlock _ nil]! !\\n\\n!ParagraphEditor methodsFor: 'typing support'!\\ncloseTypeIn: characterStream\\n\\t\\\"Call instead of closeTypeIn when you want typeahead to be inserted before the\\n\\t control character is executed, e.g., from Ctrl-V.\\\"\\n\\n\\tself insertTypeAhead: characterStream.\\n\\tself closeTypeIn! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 9/7/1999 11:26'!\\ndispatchOnEnterWith: typeAheadStream\\n\\t\\\"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. \\\"\\n\\n\\tsensor keyboard. \\\"consume enter key\\\"\\n\\tself terminateAndInitializeAround: [\\n\\tsensor commandKeyPressed\\n\\t\\tifTrue:\\n\\t\\t\\t[self printIt.]\\n\\t\\tifFalse: \\n\\t\\t\\t[self closeTypeIn: typeAheadStream.\\n\\t\\t\\tself accept].\\n\\t].\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 6/14/1998 13:08'!\\ndoneTyping\\n\\tbeginTypeInBlock _ nil! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'!\\ninsertTypeAhead: typeAhead\\n\\ttypeAhead position = 0 ifFalse:\\n\\t\\t[self zapSelectionWith: (Text string: typeAhead contents emphasis: emphasisHere).\\n\\t\\ttypeAhead reset.\\n\\t\\tself unselect]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:48'!\\nopenTypeIn\\n\\t\\\"Set up UndoSelection to null text (to be added to by readKeyboard and backTo:),\\n\\t beginTypeInBlock to keep track of the leftmost backspace, and UndoParameter to tally\\n\\t how many deleted characters were backspaced over rather than 'cut'.\\n\\t You can't undo typing until after closeTypeIn.\\\"\\n\\n\\tbeginTypeInBlock == nil ifTrue:\\n\\t\\t[UndoSelection _ self nullText.\\n\\t\\tself undoer: #noUndoer with: 0.\\n\\t\\tbeginTypeInBlock _ self startIndex]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 18:26'!\\nreadKeyboard\\n\\t\\\"Key struck on the keyboard. Find out which one and, if special, carry \\n\\tout the associated special action. Otherwise, add the character to the \\n\\tstream of characters. Undoer & Redoer: see closeTypeIn.\\\"\\n\\n\\t| typeAhead char |\\n\\ttypeAhead _ WriteStream on: (String new: 128).\\n\\t[sensor keyboardPressed] whileTrue: \\n\\t\\t[self deselect.\\n\\t\\t [sensor keyboardPressed] whileTrue: \\n\\t\\t\\t[char _ sensor keyboardPeek.\\n\\t\\t\\t(self dispatchOnCharacter: char with: typeAhead) ifTrue:\\n\\t\\t\\t\\t[self doneTyping.\\n\\t\\t\\t\\tself setEmphasisHere.\\n\\t\\t\\t\\t^self selectAndScroll; updateMarker].\\n\\t\\t\\tself openTypeIn].\\n\\t\\tself hasSelection ifTrue: \\\"save highlighted characters\\\"\\n\\t\\t\\t[UndoSelection _ self selection]. \\n\\t\\tself zapSelectionWith: \\n\\t\\t\\t(Text string: typeAhead contents emphasis: emphasisHere).\\n\\t\\ttypeAhead reset.\\n\\t\\tself unselect.\\n\\t\\tsensor keyboardPressed ifFalse: \\n\\t\\t\\t[self selectAndScroll.\\n\\t\\t\\tsensor keyboardPressed\\n\\t\\t\\t\\tifFalse: [self updateMarker]]]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:49'!\\nsetEmphasisHere\\n\\n\\temphasisHere _ (paragraph text attributesAt: (self pointIndex - 1 max: 1) forStyle: paragraph textStyle)\\n\\t\\t\\t\\t\\tselect: [:att | att mayBeExtended]! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'!\\nsimulatedKeystroke: char\\n\\t\\\"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.\\\"\\n\\n\\tself deselect.\\n\\tself openTypeIn.\\n\\tself markBlock = self pointBlock ifFalse: [UndoSelection _ self selection].\\n\\tself zapSelectionWith:\\n\\t\\t(Text string: char asString emphasis: emphasisHere).\\n\\tself userHasEdited.\\n\\tself unselect.\\n\\tself selectAndScroll.\\n\\tself updateMarker.\\n\\tview ifNotNil:\\n\\t\\t[view topView uncacheBits\\n\\t\\t\\\"in mvc, this makes sure the recognized character shows up in the pane right now; in morphic, a different mechanism is used for the same effect -- see TextMorphEditor method #recognizeCharactersWhileMouseIn:\\\"]\\n! !\\n\\n!ParagraphEditor methodsFor: 'typing support' stamp: 'di 10/6/1998 08:45'!\\nstartOfTyping\\n\\t\\\"Compatibility during change from characterBlock to integer\\\"\\n\\tbeginTypeInBlock == nil ifTrue: [^ nil].\\n\\tbeginTypeInBlock isNumber ifTrue: [^ beginTypeInBlock].\\n\\t\\\"Last line for compatibility during change from CharacterBlock to Integer.\\\"\\n\\t^ beginTypeInBlock stringIndex\\n\\t! !\\n\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:22'!\\nargAdvance: characterStream\\n\\t\\\"Invoked by Ctrl-a. Useful after Ctrl-q.\\n\\t Search forward from the end of the selection for a colon followed by\\n\\t\\ta space. Place the caret after the space. If none are found, place the\\n\\t\\tcaret at the end of the text. Does not affect the undoability of the \\n\\t \\tprevious command.\\\"\\n\\n\\t| start |\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tstart _ paragraph text findString: ': ' startingAt: self stopIndex.\\n\\tstart = 0 ifTrue: [start _ paragraph text size + 1].\\n\\tself selectAt: start + 2.\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 10/21/2003 15:46'!\\nbackWord: characterStream \\n\\t\\\"If the selection is not a caret, delete it and leave it in the backspace buffer.\\n\\t Else if there is typeahead, delete it.\\n\\t Else, delete the word before the caret.\\\"\\n\\n\\t| startIndex |\\n\\tsensor keyboard.\\n\\tcharacterStream isEmpty\\n\\t\\tifTrue:\\n\\t\\t\\t[self hasCaret\\n\\t\\t\\t\\tifTrue: \\\"a caret, delete at least one character\\\"\\n\\t\\t\\t\\t\\t[startIndex _ 1 max: self markIndex - 1.\\n\\t\\t\\t\\t\\t[startIndex > 1 and:\\n\\t\\t\\t\\t\\t\\t[(paragraph text at: startIndex - 1) asCharacter tokenish]]\\n\\t\\t\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t\\t\\t[startIndex _ startIndex - 1]]\\n\\t\\t\\t\\tifFalse: \\\"a non-caret, just delete it\\\"\\n\\t\\t\\t\\t\\t[startIndex _ self markIndex].\\n\\t\\t\\tself backTo: startIndex]\\n\\t\\tifFalse:\\n\\t\\t\\t[characterStream reset].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:23'!\\nbackspace: characterStream \\n\\t\\\"Backspace over the last character.\\\"\\n\\n\\t| startIndex |\\n\\tsensor leftShiftDown ifTrue: [^ self backWord: characterStream].\\n\\tcharacterStream isEmpty\\n\\t\\tifTrue:\\n\\t\\t\\t[startIndex _ self markIndex +\\n\\t\\t\\t\\t(self hasCaret ifTrue: [0] ifFalse: [1]).\\n\\t\\t\\t[sensor keyboardPressed and:\\n\\t\\t\\t [sensor keyboardPeek asciiValue = 8]] whileTrue: [\\n\\t\\t\\t\\t\\\"process multiple backspaces\\\"\\n\\t\\t\\t\\tsensor keyboard.\\n\\t\\t\\t\\tstartIndex _ 1 max: startIndex - 1.\\n\\t\\t\\t].\\n\\t\\t\\tself backTo: startIndex]\\n\\t\\tifFalse:\\n\\t\\t\\t[sensor keyboard.\\n\\t\\t\\tcharacterStream skip: -1].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nchangeStyle: characterStream \\n\\t\\\"Put up the style-change menu\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself changeStyle.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:25'!\\ncrWithIndent: characterStream \\n\\t\\\"Replace the current text selection with CR followed by as many tabs\\n\\tas on the current line (+/- bracket count) -- initiated by Shift-Return.\\\"\\n\\t| char s i tabCount |\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\ts _ paragraph string.\\n\\ti _ self stopIndex.\\n\\ttabCount _ 0.\\n\\t[(i _ i-1) > 0 and: [(char _ s at: i) ~= Character cr]]\\n\\t\\twhileTrue: \\\"Count tabs and brackets (but not a leading bracket)\\\"\\n\\t\\t[(char = Character tab and: [i < s size and: [(s at: i+1) ~= $[ ]]) ifTrue: [tabCount _ tabCount + 1].\\n\\t\\tchar = $[ ifTrue: [tabCount _ tabCount + 1].\\n\\t\\tchar = $] ifTrue: [tabCount _ tabCount - 1]].\\n\\tcharacterStream crtab: tabCount. \\\"Now inject CR with tabCount tabs\\\"\\n\\t^ false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 4/30/2001 21:20'!\\ncursorTopHome: characterStream \\n\\t\\\"Put cursor at beginning of text -- invoked from cmd-H shortcut, useful for keyboards that have no home key.\\\"\\n\\t\\n\\tsensor keyboard.\\n\\tself selectAt: 1.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndisplayIfFalse: characterStream \\n\\t\\\"Replace the current text selection with the text 'ifFalse:'--initiated by \\n\\tctrl-f.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tcharacterStream nextPutAll: 'ifFalse:'.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndisplayIfTrue: characterStream \\n\\t\\\"Replace the current text selection with the text 'ifTrue:'--initiated by \\n\\tctrl-t.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tcharacterStream nextPutAll: 'ifTrue:'.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndoAgainMany: characterStream \\n\\t\\\"Do the previous thing again repeatedly. 1/26/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:) many: true.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\ndoAgainOnce: characterStream \\n\\t\\\"Do the previous thing again once. 1/26/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself again.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nfind: characterStream\\n\\t\\\"Prompt the user for what to find, then find it, searching from the current selection onward. 1/24/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself find.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nfindAgain: characterStream \\n\\t\\\"Find the desired text again. 1/24/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself findAgain.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/18/2002 11:39'!\\nforwardDelete: characterStream\\n\\t\\\"Delete forward over the next character.\\n\\t Make Undo work on the whole type-in, not just the one char.\\n\\twod 11/3/1998: If there was a selection use #zapSelectionWith: rather than #backspace: which was 'one off' in deleting the selection. Handling of things like undo or typeIn area were not fully considered.\\\"\\n\\t| startIndex usel upara uinterval ind stopIndex |\\n\\tstartIndex _ self mark.\\n\\tstartIndex > paragraph text size ifTrue:\\n\\t\\t[sensor keyboard.\\n\\t\\t^ false].\\n\\tself hasSelection ifTrue:\\n\\t\\t[\\\"there was a selection\\\"\\n\\t\\tsensor keyboard.\\n\\t\\tself zapSelectionWith: self nullText.\\n\\t\\t^ false].\\n\\t\\\"Null selection - do the delete forward\\\"\\n\\tbeginTypeInBlock == nil\\t\\\"no previous typing. openTypeIn\\\"\\n\\t\\tifTrue: [self openTypeIn. UndoSelection _ self nullText].\\n\\tuinterval _ UndoInterval deepCopy.\\n\\tupara _ UndoParagraph deepCopy.\\n\\tstopIndex := startIndex.\\n\\t(sensor keyboard asciiValue = 127 and: [sensor leftShiftDown])\\n\\t\\tifTrue: [stopIndex := (self nextWord: stopIndex) - 1].\\n\\tself selectFrom: startIndex to: stopIndex.\\n\\tself replaceSelectionWith: self nullText.\\n\\tself selectFrom: startIndex to: startIndex-1.\\n\\tUndoParagraph _ upara. UndoInterval _ uinterval.\\n\\tUndoMessage selector == #noUndoer ifTrue: [\\n\\t\\t(UndoSelection isText) ifTrue: [\\n\\t\\t\\tusel _ UndoSelection.\\n\\t\\t\\tind _ startIndex. \\\"UndoInterval startIndex\\\"\\n\\t\\t\\tusel replaceFrom: usel size + 1 to: usel size with:\\n\\t\\t\\t\\t(UndoParagraph text copyFrom: ind to: ind).\\n\\t\\t\\tUndoParagraph text replaceFrom: ind to: ind with:\\nself nullText]].\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nnormalCharacter: characterStream \\n\\t\\\"A nonspecial character is to be added to the stream of characters.\\\"\\n\\n\\tcharacterStream nextPut: sensor keyboard.\\n\\t^false! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:25'!\\nquerySymbol: characterStream\\n\\t\\\"Invoked by Ctrl-q to query the Symbol table and display alternate symbols.\\n\\t See comment in completeSymbol:lastOffering: for details.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\t\\\"keep typeahead\\\"\\n\\tself hasCaret\\n\\t\\tifTrue: \\\"Ctrl-q typed when a caret\\\"\\n\\t\\t\\t[self perform: #completeSymbol:lastOffering: withArguments:\\n\\t\\t\\t\\t((UndoParagraph == paragraph and: [UndoMessage sends: #undoQuery:lastOffering:])\\n\\t\\t\\t\\t\\tifTrue: [UndoMessage arguments] \\\"repeated Ctrl-q\\\"\\n\\t\\t\\t\\t\\tifFalse: [Array with: nil with: nil])] \\\"initial Ctrl-q\\\"\\n\\t\\tifFalse: \\\"Ctrl-q typed when statements were highlighted\\\"\\n\\t\\t\\t[view flash].\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nsearch: characterStream\\n\\t\\\"Invoked by Ctrl-S. Same as 'again', but always uses the existing FindText\\n\\t and ChangeText regardless of the last edit.\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself againOrSame: true. \\\"true means use same keys\\\"\\n\\t^true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 8/29/2000 14:58'!\\nselectAll\\n\\t\\\"Make the selection be all the characters of the receiver\\\"\\n\\n\\tself selectFrom: 1 to: paragraph text string size! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys'!\\nselectAll: characterStream \\n\\t\\\"select everything, invoked by cmd-a. 1/17/96 sw\\\"\\n\\n\\tsensor keyboard.\\t\\t\\\"flush character\\\"\\n\\tself closeTypeIn: characterStream.\\n\\tself selectFrom: 1 to: paragraph text string size.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 17:34'!\\nsimulatedBackspace\\n\\t\\\"Backspace over the last character, derived from hand-char recognition. 2/5/96 sw\\\"\\n\\n\\t| startIndex |\\n\\tstartIndex _ self markIndex + (self hasSelection ifTrue: [1] ifFalse: [0]).\\n\\n\\tstartIndex _ 1 max: startIndex - 1.\\n\\tself backTo: startIndex.\\n\\t^ false! !\\n\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisDoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^(self isUndoing | self isRedoing) not! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisRedoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^UndoParagraph == #redoing! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nisUndoing\\n\\t\\\"Call from a doer/undoer/redoer any time to see which it is.\\\"\\n\\n\\t^UndoParagraph == #undoing! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nnoUndoer\\n\\t\\\"The Undoer to use when the command can not be undone. Checked for\\n\\t specially by readKeyboard.\\\"\\n\\n\\tUndoMessage _ Message selector: #noUndoer! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoMessage: aMessage forRedo: aBoolean\\n\\t\\\"Call this from an undoer/redoer to set up UndoMessage as the\\n\\t corresponding redoer/undoer. Also set up UndoParagraph, as well\\n\\t as the state variable Undone. It is assumed that UndoInterval has been\\n\\t established (generally by zapSelectionWith:) and that UndoSelection has been\\n\\t saved (generally by replaceSelectionWith: or replace:With:and:).\\\"\\n\\n\\tself isDoing ifTrue: [UndoParagraph _ paragraph].\\n\\tUndoMessage _ aMessage.\\n\\tUndone _ aBoolean! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has no arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has one argument, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector argument: arg1) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1 with: arg2\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has two arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2)) forRedo: false! !\\n\\n!ParagraphEditor methodsFor: 'undo support'!\\nundoer: aSelector with: arg1 with: arg2 with: arg3\\n\\t\\\"See comment in undoMessage:. Use this version when aSelector has three arguments, and you are doing or redoing and want to prepare for undoing.\\\"\\n\\n\\tself undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2 with: arg3)) forRedo: false! !\\n\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoAgain: indices andReselect: home typedKey: wasTypedKey\\n\\t\\\"The last command was again. Undo it. Redoer: itself.\\\"\\n\\n\\t| findSize substText index subject |\\n\\t(self isRedoing & wasTypedKey) ifTrue: \\\"redelete search key\\\"\\n\\t\\t[self selectInterval: home.\\n\\t\\tself zapSelectionWith: self nullText].\\n\\n\\tfindSize _ (self isRedoing ifTrue: [FindText] ifFalse: [ChangeText]) size.\\n\\tsubstText _ self isUndoing ifTrue: [FindText] ifFalse: [ChangeText].\\n\\t(self isUndoing ifTrue: [indices size to: 1 by: -1] ifFalse: [1 to: indices size]) do:\\n\\t\\t[:i |\\n\\t\\tindex _ indices at: i.\\n\\t\\t(subject _ index to: index + findSize - 1) = self selectionInterval ifFalse:\\n\\t\\t\\t[self selectInterval: subject].\\n\\t\\tFindText == ChangeText ifFalse: [self zapSelectionWith: substText]].\\n\\n\\tself isUndoing\\n\\t\\tifTrue: \\\"restore selection to where it was when 'again' was invoked\\\"\\n\\t\\t\\t[wasTypedKey\\n\\t\\t\\t\\tifTrue: \\\"search started by typing key at a caret; restore it\\\"\\n\\t\\t\\t\\t\\t[self selectAt: home first.\\n\\t\\t\\t\\t\\tself zapSelectionWith: FindText.\\n\\t\\t\\t\\t\\tself selectAt: home last + 1]\\n\\t\\t\\t\\tifFalse: [self selectInterval: home]].\\n\\n\\tself undoMessage: UndoMessage forRedo: self isUndoing! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoAndReselect: undoHighlight redoAndReselect: redoHighlight\\n\\t\\\"Undo typing, cancel, paste, and other operations that are like replaces\\n\\t but the selection is not the whole restored text after undo, redo, or both.\\n\\t undoHighlight is selected after this phase and redoHighlight after the next phase.\\n\\tRedoer: itself.\\\"\\n\\n\\tself replace: self selectionInterval with: UndoSelection and:\\n\\t\\t[self selectInterval: undoHighlight].\\n\\tself undoMessage: (UndoMessage argument: redoHighlight) forRedo: self isUndoing\\n! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoCutCopy: oldPasteBuffer\\n\\t\\\"Undo of a cut, copy, or any edit that changed CurrentSelection. Be sure\\n\\t undo-copy does not lock the model. Redoer: itself, so never isRedoing.\\\"\\n\\n\\t| recentCut |\\n\\trecentCut _ self clipboardText.\\t\\n\\tUndoSelection size = UndoInterval size\\n\\t\\tifFalse: [self replaceSelectionWith: UndoSelection].\\n\\tself clipboardTextPut: oldPasteBuffer.\\n\\tself undoer: #undoCutCopy: with: recentCut! !\\n\\n!ParagraphEditor methodsFor: 'undoers' stamp: 'th 9/19/2002 18:46'!\\nundoQuery: hintText lastOffering: selectorOrNil\\n\\t\\\"Undo ctrl-q. selectorOrNil (if not nil) is the previously offered selector.\\n\\t hintText is the original hint. Redoer: completeSymbol.\\\"\\n\\n\\tself zapSelectionWith: UndoSelection.\\n\\tself undoMessage: (Message selector: #completeSymbol:lastOffering: arguments: UndoMessage arguments) forRedo: true.\\n\\tself selectAt: self stopIndex! !\\n\\n!ParagraphEditor methodsFor: 'undoers'!\\nundoReplace\\n\\t\\\"Undo of any command that replaced a selection by other text that it left\\n\\t highlighted, and that is undone and redone by simple reversal of the\\n\\t operation. This is the most common Undoer; call replaceSelectionWith:\\n\\t to get this setup. Redoer: itself, so never isRedoing.\\\"\\n\\n\\tself replaceSelectionWith: UndoSelection! !\\n\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseChangeSetsWithSelector\\n\\t\\\"Determine which, if any, change sets have at least one change for the selected selector, independent of class\\\"\\n\\n\\t| aSelector |\\n\\tself lineSelectAndEmptyCheck: [^ self].\\n\\t(aSelector := self selectedSelector) == nil ifTrue: [^ view flash].\\n\\tself terminateAndInitializeAround: [ChangeSorter browseChangeSetsWithSelector: aSelector]! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseItHere\\n\\t\\\"Retarget the receiver's window to look at the selected class, if appropriate. 3/1/96 sw\\\"\\n\\t| aSymbol foundClass b |\\n\\t(((b := model) isKindOf: Browser) and: [b couldBrowseAnyClass])\\n\\t\\tifFalse: [^ view flash].\\n\\tmodel okToChange ifFalse: [^ view flash].\\n\\tself selectionInterval isEmpty ifTrue: [self selectWord].\\n\\t(aSymbol := self selectedSymbol) isNil ifTrue: [^ view flash].\\n\\n\\tself terminateAndInitializeAround:\\n\\t\\t[foundClass := (Smalltalk at: aSymbol ifAbsent: [nil]).\\n\\t\\t\\tfoundClass isNil ifTrue: [^ view flash].\\n\\t\\t\\t(foundClass isKindOf: Class)\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[model systemCategoryListIndex: \\n\\t\\t\\t\\t\\t\\t(model systemCategoryList indexOf: foundClass category).\\n\\t\\tmodel classListIndex: (model classList indexOf: foundClass name)]]! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ndebugIt\\n\\n\\t| method receiver context |\\n\\t(model respondsTo: #doItReceiver) \\n\\t\\tifTrue: \\n\\t\\t\\t[FakeClassPool adopt: model selectedClass.\\n\\t\\t\\treceiver := model doItReceiver.\\n\\t\\t\\tcontext := model doItContext]\\n\\t\\tifFalse:\\n\\t\\t\\t[receiver := context := nil].\\n\\tself lineSelectAndEmptyCheck: [^self].\\n\\tmethod := self compileSelectionFor: receiver in: context.\\n\\tmethod notNil ifTrue:\\n\\t\\t[self debug: method receiver: receiver in: context].\\n\\tFakeClassPool adopt: nil! !\\n\\n!ParagraphEditor methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ndebug: aCompiledMethod receiver: anObject in: evalContext\\n\\n\\t| selector guineaPig debugger context |\\n\\tselector := evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:].\\n\\tanObject class addSelectorSilently: selector withMethod: aCompiledMethod.\\n\\tguineaPig := evalContext isNil\\n\\t\\tifTrue: [[anObject DoIt] newProcess]\\n\\t\\tifFalse: [[anObject DoItIn: evalContext] newProcess].\\n\\tcontext := guineaPig suspendedContext.\\n\\tdebugger := Debugger new\\n\\t\\tprocess: guineaPig\\n\\t\\tcontroller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess])\\n\\t\\t\\t\\tifTrue: [ScheduledControllers activeController]\\n\\t\\t\\t\\tifFalse: [nil])\\n\\t\\tcontext: context\\n\\t\\tisolationHead: nil.\\n\\tdebugger openFullNoSuspendLabel: 'Debug it'.\\n\\t[debugger interruptedContext method == aCompiledMethod]\\n\\t\\twhileFalse: [debugger send].\\n\\tanObject class basicRemoveSelector: selector! !\\n\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:48'!\\nagainOnce: indices\\n\\t\\\"Find the next occurrence of FindText. If none, answer false.\\n\\tAppend the start index of the occurrence to the stream indices, and, if\\n\\tChangeText is not the same object as FindText, replace the occurrence by it.\\n\\tNote that the search is case-sensitive for replacements, otherwise not.\\\"\\n\\n\\t| where |\\n\\twhere _ paragraph text findString: FindText startingAt: self stopIndex\\n\\t\\t\\t\\tcaseSensitive: ((ChangeText ~~ FindText) or: [Preferences caseSensitiveFinds]).\\n\\twhere = 0 ifTrue: [^ false].\\n\\tself deselect; selectInvisiblyFrom: where to: where + FindText size - 1.\\n\\tChangeText ~~ FindText ifTrue: [self zapSelectionWith: ChangeText].\\n\\tindices nextPut: where.\\n\\tself selectAndScroll.\\n\\t^ true! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nagainOrSame: useOldKeys\\n\\t\\\"Subroutine of search: and again. If useOldKeys, use same FindText and ChangeText as before.\\n\\t 1/26/96 sw: real worked moved to againOrSame:many:\\\"\\n\\n\\t^ self againOrSame: useOldKeys many: sensor leftShiftDown! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:53'!\\nagainOrSame: useOldKeys many: many\\n\\t\\\"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.\\\"\\n\\n\\t| home indices wasTypedKey |\\n\\n\\thome _ self selectionInterval. \\\"what was selected when 'again' was invoked\\\"\\n\\n\\t\\\"If new keys are to be picked...\\\"\\n\\tuseOldKeys ifFalse: \\\"Choose as FindText...\\\"\\n\\t\\t[FindText _ UndoSelection. \\\"... the last thing replaced.\\\"\\n\\t\\t\\\"If the last command was in another paragraph, ChangeText is set...\\\"\\n\\t\\tparagraph == UndoParagraph ifTrue: \\\"... else set it now as follows.\\\"\\n\\t\\t\\t[UndoInterval ~= home ifTrue: [self selectInterval: UndoInterval]. \\\"blink\\\"\\n\\t\\t\\tChangeText _ ((UndoMessage sends: #undoCutCopy:) and: [self hasSelection])\\n\\t\\t\\t\\tifTrue: [FindText] \\\"== objects signal no model-locking by 'undo copy'\\\"\\n\\t\\t\\t\\tifFalse: [self selection]]]. \\\"otherwise, change text is last-replaced text\\\"\\n\\n\\t(wasTypedKey _ FindText size = 0)\\n\\t\\tifTrue: \\\"just inserted at a caret\\\"\\n\\t\\t\\t[home _ self selectionInterval.\\n\\t\\t\\tself replaceSelectionWith: self nullText. \\\"delete search key...\\\"\\n\\t\\t\\tFindText _ ChangeText] \\\"... and search for it, without replacing\\\"\\n\\t\\tifFalse: \\\"Show where the search will start\\\"\\n\\t\\t\\t[home last = self selectionInterval last ifFalse:\\n\\t\\t\\t\\t[self selectInterval: home]].\\n\\n\\t\\\"Find and Change, recording start indices in the array\\\"\\n\\tindices _ WriteStream on: (Array new: 20). \\\"an array to store change locs\\\"\\n\\t[(self againOnce: indices) & many] whileTrue. \\\"<-- this does the work\\\"\\n\\tindices isEmpty ifTrue: \\\"none found\\\"\\n\\t\\t[self flash.\\n\\t\\twasTypedKey ifFalse: [^self]].\\n\\n\\t(many | wasTypedKey) ifFalse: \\\"after undo, select this replacement\\\"\\n\\t\\t[home _ self startIndex to:\\n\\t\\t\\tself startIndex + UndoSelection size - 1].\\n\\n\\tself undoer: #undoAgain:andReselect:typedKey: with: indices contents with: home with: wasTypedKey! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:16'!\\ncompleteSymbol: hintText lastOffering: selectorOrNil\\n\\t\\\"Invoked by Ctrl-q when there is only a caret.\\n\\t\\tDo selector-completion, i.e., try to replace the preceding identifier by a\\n\\t\\tselector that begins with those characters & has as many keywords as possible.\\n\\t \\tLeave two spaces after each colon (only one after the last) as space for\\n\\t\\targuments. Put the caret after the space after the first keyword. If the\\n\\t\\tuser types Ctrl-q again immediately, choose a different selector.\\n\\t Undoer: #undoQuery:lastOffering:; Redoer: itself.\\n\\tIf redoing, just redisplay the last offering, selector[OrNil].\\\"\\n\\n\\t| firstTime input prior caret newStart sym kwds outStream |\\n\\tfirstTime _ self isRedoing\\n\\t\\tifTrue: [prior _ sym _ selectorOrNil. true]\\n\\t\\tifFalse: [hintText isNil].\\n\\tfirstTime\\n\\t\\tifTrue: \\\"Initial Ctrl-q (or redo)\\\"\\t\\t\\t\\t\\t\\n\\t\\t\\t[caret _ self startIndex.\\n\\t\\t\\tself selectPrecedingIdentifier.\\n\\t\\t\\tinput _ self selection]\\n\\t\\tifFalse: \\\"Repeated Ctrl-q\\\"\\n\\t\\t\\t[caret _ UndoInterval first + hintText size.\\n\\t\\t\\tself selectInvisiblyFrom: UndoInterval first to: UndoInterval last.\\n\\t\\t\\tinput _ hintText.\\n\\t\\t\\tprior _ selectorOrNil].\\n\\t(input size ~= 0 and: [sym ~~ nil or:\\n\\t\\t\\t[(sym _ Symbol thatStarts: input string skipping: prior) ~~ nil]])\\n\\t\\tifTrue: \\\"found something to offer\\\"\\n\\t\\t\\t[newStart _ self startIndex.\\n\\t\\t\\toutStream _ WriteStream on: (String new: 2 * sym size).\\n\\t\\t\\t1 to: (kwds _ sym keywords) size do:\\n\\t\\t\\t\\t[:i |\\n\\t\\t\\t\\toutStream nextPutAll: (kwds at: i).\\n\\t\\t\\t\\ti = 1 ifTrue: [caret _ newStart + outStream contents size + 1].\\n\\t\\t\\t\\toutStream nextPutAll:\\n\\t\\t\\t\\t\\t(i < kwds size ifTrue: [' '] ifFalse: [' '])].\\n\\t\\t\\tUndoSelection _ input.\\n\\t\\t\\tself deselect; zapSelectionWith: outStream contents asText.\\n\\t\\t\\tself undoer: #undoQuery:lastOffering: with: input with: sym]\\n\\t\\tifFalse: \\\"no more matches\\\"\\n\\t\\t\\t[firstTime ifFalse: \\\"restore original text & set up for a redo\\\"\\n\\t\\t\\t\\t[UndoSelection _ self selection.\\n\\t\\t\\t\\tself deselect; zapSelectionWith: input.\\n\\t\\t\\t\\tself undoer: #completeSymbol:lastOffering: with: input with: prior.\\n\\t\\t\\t\\tUndone _ true].\\n\\t\\t\\tview flash].\\n\\tself selectAt: caret! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:49'!\\nexchangeWith: prior\\n\\t\\\"If the prior selection is non-overlapping and legal, exchange the text of\\n\\t it with the current selection and leave the currently selected text selected\\n\\t in the location of the prior selection (or leave a caret after a non-caret if it was\\n\\t exchanged with a caret). If both selections are carets, flash & do nothing.\\n\\t Don't affect the paste buffer. Undoer: itself; Redoer: Undoer.\\\"\\n\\n\\t| start stop before selection priorSelection delta altInterval |\\n\\tstart _ self startIndex.\\n\\tstop _ self stopIndex - 1.\\n\\t((prior first <= prior last) | (start <= stop) \\\"Something to exchange\\\" and:\\n\\t\\t\\t[self isDisjointFrom: prior])\\n\\t\\tifTrue:\\n\\t\\t\\t[before _ prior last < start.\\n\\t\\t\\tselection _ self selection.\\n\\t\\t\\tpriorSelection _ paragraph text copyFrom: prior first to: prior last.\\n\\n\\t\\t\\tdelta _ before ifTrue: [0] ifFalse: [priorSelection size - selection size].\\n\\t\\t\\tself zapSelectionWith: priorSelection.\\n\\t\\t\\tself selectFrom: prior first + delta to: prior last + delta.\\n\\n\\t\\t\\tdelta _ before ifTrue: [stop - prior last] ifFalse: [start - prior first].\\n\\t\\t\\tself zapSelectionWith: selection.\\n\\t\\t\\taltInterval _ prior first + delta to: prior last + delta.\\n\\t\\t\\tself undoer: #exchangeWith: with: altInterval.\\n\\t\\t\\t\\\"If one was a caret, make it otherInterval & leave the caret after the other\\\"\\n\\t\\t\\tprior first > prior last ifTrue: [self selectAt: UndoInterval last + 1].\\n\\t\\t\\totherInterval _ start > stop\\n\\t\\t\\t\\tifTrue: [self selectAt: altInterval last + 1. UndoInterval]\\n\\t\\t\\t\\tifFalse: [altInterval]]\\n\\t\\tifFalse:\\n\\t\\t\\t[view flash]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'raok 11/15/2001 14:01'!\\nexplainDelimitor: string\\n\\t\\\"Is string enclosed in delimitors?\\\"\\n\\n\\t| str |\\n\\t(string at: 1) isLetter ifTrue: [^nil]. \\\"only special chars\\\"\\n\\t(string first = string last) ifTrue:\\n\\t\\t\\t[^ self explainChar: (String with: string first)]\\n\\t\\tifFalse:\\n\\t\\t\\t[(string first = $( and: [string last = $)]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $[ and: [string last = $]]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = ${ and: [string last = $}]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $< and: [string last = $>]) ifTrue:\\n\\t\\t\\t\\t[^ self explainChar: (String with: string first)].\\n\\t\\t\\t(string first = $# and: [string last = $)]) ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Array. The Numbers, Characters, or Symbols between the parenthesis are the elements of the Array.\\\"'].\\n\\t\\t\\tstring first = $# ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Symbol.\\\"'].\\n\\t\\t\\t(string first = $$ and: [string size = 2]) ifTrue:\\n\\t\\t\\t\\t[^'\\\"An instance of class Character. This one is the character ', (String with: string last), '.\\\"'].\\n\\t\\t\\t(string first = $:) ifTrue:\\n\\t\\t\\t\\t[str _ string allButFirst.\\n\\t\\t\\t\\t(self explainTemp: str) ~~ nil ifTrue:\\n\\t\\t\\t\\t\\t[^'\\\"An argument to this block will be bound to the temporary variable ',\\n\\t\\t\\t\\t\\t\\tstr, '.\\\"']]].\\n\\t^ nil! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'tk 7/14/2000 12:15'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t| customMenu |\\n\\t^ ((view ~~ nil) and: [(customMenu _ view getMenu: shiftKeyState) notNil])\\n\\t\\tifTrue: [customMenu]\\n\\t\\tifFalse:\\n\\t\\t\\t[shiftKeyState\\n\\t\\t\\t\\tifTrue: [self class shiftedYellowButtonMenu]\\n\\t\\t\\t\\tifFalse: [self class yellowButtonMenu]]! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nindent: delta fromStream: inStream toStream: outStream\\n\\t\\\"Append the contents of inStream to outStream, adding or deleting delta or -delta\\n\\t tabs at the beginning, and after every CR except a final CR. Do not add tabs\\n\\t to totally empty lines, and be sure nothing but tabs are removed from lines.\\\"\\n\\n\\t| ch skip cr tab prev atEnd |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\tdelta > 0\\n\\t\\tifTrue: \\\"shift right\\\"\\n\\t\\t\\t[prev _ cr.\\n\\t\\t\\t [ch _ (atEnd _ inStream atEnd) ifTrue: [cr] ifFalse: [inStream next].\\n\\t\\t\\t (prev == cr and: [ch ~~ cr]) ifTrue:\\n\\t\\t\\t\\t[delta timesRepeat: [outStream nextPut: tab]].\\n\\t\\t\\t atEnd]\\n\\t\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t\\t[outStream nextPut: ch.\\n\\t\\t\\t\\t\\tprev _ ch]]\\n\\t\\tifFalse: \\\"shift left\\\"\\n\\t\\t\\t[skip _ delta. \\\"a negative number\\\"\\n\\t\\t\\t [inStream atEnd] whileFalse:\\n\\t\\t\\t\\t[((ch _ inStream next) == tab and: [skip < 0]) ifFalse:\\n\\t\\t\\t\\t\\t[outStream nextPut: ch].\\n\\t\\t\\t\\tskip _ ch == cr ifTrue: [delta] ifFalse: [skip + 1]]]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'cmm 4/9/2004 14:00'!\\nisDisjointFrom: anInterval\\n\\t\\\"Answer true if anInterval is a caret not touching or within the current\\n\\t interval, or if anInterval is a non-caret that does not overlap the current\\n\\t selection.\\\"\\n\\n\\t| fudge |\\n\\tfudge _ anInterval size = 0 ifTrue: [1] ifFalse: [0].\\n\\t^(anInterval last + fudge < self startIndex or:\\n\\t\\t\\t[anInterval first - fudge >= self stopIndex])\\n! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 11/24/2002 17:13'!\\nlines\\n\\t\\\"Other than my member paragraph i compute lines based on logical\\n\\tline breaks, not optical (which may change due to line wrapping of the editor)\\\"\\n\\t| lines string index lineIndex stringSize |\\n\\tstring _ paragraph text string.\\n\\t\\\"Empty strings have no lines at all. Think of something.\\\"\\n\\tstring isEmpty ifTrue:[^{#(1 0 0)}].\\n\\tstringSize _ string size.\\n\\tlines _ OrderedCollection new: (string size // 15).\\n\\tindex _ 0.\\n\\tlineIndex _ 0.\\n\\tstring linesDo:[:line |\\n\\t\\tlines addLast: (Array\\n\\t\\t\\twith: (index _ index + 1)\\n\\t\\t\\twith: (lineIndex _ lineIndex + 1)\\n\\t\\t\\twith: (index _ index + line size min: stringSize))].\\n\\t\\\"Special workaround for last line empty.\\\"\\n\\tstring last == Character cr\\n\\t\\\"lines last last < stringSize\\\" ifTrue:[lines addLast:{stringSize +1. lineIndex+1. stringSize}].\\n\\t^lines! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 19:57'!\\nmoveCursor: directionBlock forward: forward specialBlock: specialBlock\\n\\t\\\"Private - Move cursor.\\n\\tdirectionBlock is a one argument Block that computes the new Position from a given one.\\n\\tspecialBlock is a one argumentBlock that computes the new position from a given one under the alternate semantics.\\n\\tNote that directionBlock always is evaluated first.\\\"\\n\\t| shift indices newPosition |\\n\\tshift _ sensor leftShiftDown.\\n\\tindices _ self setIndices: shift forward: forward.\\n\\tnewPosition _ directionBlock value: (indices at: #moving).\\n\\t(sensor commandKeyPressed or:[sensor controlKeyPressed])\\n\\t\\tifTrue: [newPosition _ specialBlock value: newPosition].\\n\\tsensor keyboard.\\n\\tshift\\n\\t\\tifTrue: [self selectMark: (indices at: #fixed) point: newPosition - 1]\\n\\t\\tifFalse: [self selectAt: newPosition]! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:32'!\\nnextWord: position\\n\\t| string index |\\n\\tstring _ paragraph text string.\\n\\tindex _ position.\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]]\\n\\t\\twhileTrue: [index _ index + 1].\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]]\\n\\t\\twhileTrue: [index _ index + 1].\\n\\t^ index! !\\n\\n!ParagraphEditor methodsFor: 'private'!\\nnullText\\n\\n\\t^Text string: '' emphasis: emphasisHere! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'th 9/20/2002 11:09'!\\npageHeight\\n\\t| howManyLines visibleHeight totalHeight ratio |\\n\\thowManyLines _ paragraph numberOfLines.\\n\\tvisibleHeight _ self visibleHeight.\\n\\ttotalHeight _ self totalTextHeight.\\n\\tratio _ visibleHeight / totalHeight.\\n\\t^(ratio * howManyLines) rounded - 2! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:33'!\\npreviousWord: position\\n\\t| string index |\\n\\tstring _ paragraph text string.\\n\\tindex _ position.\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]]\\n\\t\\twhileTrue: [index _ index - 1].\\n\\t[(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]]\\n\\t\\twhileTrue: [index _ index - 1].\\n\\t^ index + 1! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'BG 4/29/2004 11:19'!\\nsameColumn: start newLine: lineBlock forward: isForward\\n\\t\\\"Private - Compute the index in my text\\n\\twith the line number derived from lineBlock,\\\"\\n\\t\\\" a one argument block accepting the old line number.\\n\\tThe position inside the line will be preserved as good as possible\\\"\\n\\t\\\"The boolean isForward is used in the border case to determine if\\n\\twe should move to the beginning or the end of the line.\\\"\\n\\t| wordStyle column currentLine offsetAtTargetLine targetEOL lines numberOfLines currentLineNumber targetLineNumber |\\n\\twordStyle _ Preferences wordStyleCursorMovement.\\n\\twordStyle\\n\\t\\tifTrue: [\\n\\t\\t\\tlines _ paragraph lines.\\n\\t\\t\\tnumberOfLines := paragraph numberOfLines.\\n\\t\\t\\tcurrentLineNumber _ paragraph lineIndexOfCharacterIndex: start.\\n\\t\\t\\tcurrentLine _ lines at: currentLineNumber]\\n\\t\\tifFalse: [\\n\\t\\t\\tlines _ self lines.\\n\\t\\t\\tnumberOfLines := lines size.\\n\\t\\t\\tcurrentLine _ lines\\n\\t\\t\\t\\tdetect:[:lineInterval | lineInterval last >= start]\\n\\t\\t\\t\\tifNone:[lines last].\\n\\t\\t\\tcurrentLineNumber _ currentLine second].\\n\\tcolumn _ start - currentLine first.\\n\\ttargetLineNumber _ ((lineBlock value: currentLineNumber) max: 1) min: numberOfLines.\\n\\toffsetAtTargetLine _ (lines at: targetLineNumber) first.\\n\\ttargetEOL _ (lines at: targetLineNumber) last + (targetLineNumber == numberOfLines ifTrue:[1]ifFalse:[0]).\\n\\ttargetLineNumber == currentLineNumber\\n\\t\\\"No movement or movement failed. Move to beginning or end of line.\\\"\\n\\t\\tifTrue:[^isForward\\n\\t\\t\\tifTrue:[targetEOL]\\n\\t\\t\\tifFalse:[offsetAtTargetLine]].\\n\\t^offsetAtTargetLine + column min: targetEOL.! !\\n\\n!ParagraphEditor methodsFor: 'private' stamp: 'md 2/22/2006 21:17'!\\nsetIndices: shiftPressed forward: forward\\n\\t\\\"Little helper method that sets the moving and fixed indices according to some flags.\\\"\\n\\t| indices |\\n\\tindices _ Dictionary new.\\n\\tshiftPressed ifTrue: [\\n\\t\\t\\tindices at: #moving put: self pointIndex.\\n\\t\\t\\tindices at: #fixed put: self markIndex\\n\\t\\t] ifFalse: [\\n\\t\\t\\tforward\\n\\t\\t\\t\\tifTrue:[\\n\\t\\t\\t\\t\\tindices at: #moving put: self stopIndex.\\n\\t\\t\\t\\t\\tindices at: #fixed put: self startIndex.\\n\\t\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\t\\tindices at: #moving put: self startIndex.\\n\\t\\t\\t\\t\\tindices at: #fixed put: self stopIndex.\\n\\t\\t\\t\\t]\\n\\t\\t].\\n\\t^indices! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParagraphEditor class\\n\\tinstanceVariableNames: ''!\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'sw 5/27/2000 00:03'!\\nabandonChangeText\\n\\t\\\"Call this to get out of the maddening situation in which the system keeps aggressively trying to do a replacement that you no longer wish to make, every time you make choose a new method in a list.\\\"\\n\\tChangeText _ FindText\\n\\n\\t\\\"ParagraphEditor abandonChangeText\\\"\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 10/1/2004 11:00'!\\ninitialize\\n\\t\\\"Initialize the keyboard shortcut maps and the shared buffers \\n\\tfor copying text across views and managing again and undo. \\n\\tMarked this method changed to trigger reinit\\\"\\n\\t\\\"ParagraphEditor initialize\\\"\\n\\tUndoSelection := FindText := ChangeText := Text new.\\n\\tUndoMessage := Message selector: #halt.\\n\\tself initializeCmdKeyShortcuts.\\n\\tself initializeShiftCmdKeyShortcuts.! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 4/4/2006 16:07'!\\nshiftedYellowButtonMenu\\n\\t\\\"Answer the menu to be presented when the yellow button is pressed while the shift key is down\\\"\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t{'explain' translated.\\t\\t\\t\\t\\t\\t#explain}.\\n\\t\\t{'pretty print' translated.\\t\\t\\t\\t\\t#prettyPrint}.\\n\\t\\t{'pretty print with color' translated.\\t\\t#prettyPrintWithColor}.\\n\\t\\t{'file it in (G)' translated.\\t\\t\\t\\t\\t#fileItIn}.\\n\\t\\t{'tiles from it' translated.\\t\\t\\t\\t\\t#selectionAsTiles}.\\n\\t\\t{'spawn (o)' translated.\\t\\t\\t\\t\\t\\t#spawn}.\\n\\t\\t#-.\\n\\t\\t{'browse it (b)' translated.\\t\\t\\t\\t\\t#browseIt}.\\n\\t\\t{'senders of it (n)' translated.\\t\\t\\t\\t#sendersOfIt}.\\n\\t\\t{'implementors of it (m)' translated.\\t\\t#implementorsOfIt}.\\n\\t\\t{'references to it (N)' translated.\\t\\t\\t#referencesToIt}.\\n\\t\\t#-.\\n\\t\\t{'selectors containing it (W)' translated.\\t#methodNamesContainingIt}.\\n\\t\\t{'method strings with it (E)' translated.\\t#methodStringsContainingit}.\\n\\t\\t{'method source with it' translated.\\t\\t#methodSourceContainingIt}.\\n\\t\\t{'class names containing it' translated.\\t#classNamesContainingIt}.\\n\\t\\t{'class comments with it' translated.\\t\\t#classCommentsContainingIt}.\\n\\t\\t{'change sets with it' translated.\\t\\t\\t#browseChangeSetsWithSelector}.\\n\\t\\t#-.\\n\\t\\t{'save contents to file...' translated.\\t\\t#saveContentsInFile}.\\n\\t\\t{'send contents to printer' translated.\\t#sendContentsToPrinter}.\\n\\t\\t{'printer setup' translated.\\t\\t\\t\\t\\t#printerSetup}.\\n\\t\\t#-.\\n\\t\\t{'special menu...' translated.\\t\\t\\t\\t#presentSpecialMenu}.\\n\\t\\t{'more...' translated.\\t\\t\\t\\t\\t\\t#yellowButtonActivity}.\\n\\t}\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 9/1/2005 12:35'!\\nyellowButtonExpertMenu\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t\\t{'set font... (k)' translated.\\t\\t\\t\\t#offerFontMenu}.\\n\\t\\t\\t{'set style... (K)' translated.\\t\\t\\t\\t#changeStyle}.\\n\\t\\t\\t{'set alignment... (u)' translated.\\t\\t#chooseAlignment}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'make project link (P)' translated.\\t#makeProjectLink}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'find...(f)' translated.\\t\\t\\t\\t\\t#find}.\\n\\t\\t\\t{'find again (g)' translated.\\t\\t\\t\\t#findAgain}.\\n\\t\\t\\t{'set search string (h)' translated.\\t\\t#setSearchString}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do again (j)' translated.\\t\\t\\t\\t#again}.\\n\\t\\t\\t{'undo (z)' translated.\\t\\t\\t\\t\\t#undo}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy (c)' translated.\\t\\t\\t\\t\\t#copySelection}.\\n\\t\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t\\t#cut}.\\n\\t\\t\\t{'paste (v)' translated.\\t\\t\\t\\t\\t#paste}.\\n\\t\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do it (d)' translated.\\t\\t\\t\\t\\t#doIt}.\\n\\t\\t\\t{'print it (p)' translated.\\t\\t\\t\\t#printIt}.\\n\\t\\t\\t{'inspect it (i)' translated.\\t\\t\\t\\t#inspectIt}.\\n\\t\\t\\t{'explore it (I)' translated.\\t\\t\\t\\t#exploreIt}.\\n\\t\\t\\t{'debug it' translated.\\t\\t\\t\\t\\t#debugIt}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'accept (s)' translated.\\t\\t\\t\\t\\t#accept}.\\n\\t\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t\\t#cancel}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'show bytecodes' translated.\\t\\t\\t#showBytecodes}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy html' translated.\\t\\t\\t\\t\\t#copyHtml}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'more...' translated.\\t\\t\\t\\t\\t#shiftedTextPaneMenuRequest}.\\n\\t\\t}.\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 10/1/2004 10:59'!\\nyellowButtonMenu\\n\\n\\t^ Preferences noviceMode\\n\\t\\t\\tifTrue: [self yellowButtonNoviceMenu]\\n\\t\\t\\tifFalse: [self yellowButtonExpertMenu]\\n! !\\n\\n!ParagraphEditor class methodsFor: 'class initialization' stamp: 'dgd 11/25/2004 17:33'!\\nyellowButtonNoviceMenu\\n\\n\\t^ MenuMorph fromArray: {\\n\\t\\t\\t{'set font... (k)' translated.\\t\\t\\t\\t#offerFontMenu}.\\n\\t\\t\\t{'set style... (K)' translated.\\t\\t\\t\\t#changeStyle}.\\n\\t\\t\\t{'set alignment... (u)' translated.\\t\\t#chooseAlignment}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'make project link (P)' translated.\\t#makeProjectLink}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'find...(f)' translated.\\t\\t\\t\\t\\t#find}.\\n\\t\\t\\t{'find again (g)' translated.\\t\\t\\t\\t#findAgain}.\\n\\t\\t\\t{'set search string (h)' translated.\\t\\t#setSearchString}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'do again (j)' translated.\\t\\t\\t\\t#again}.\\n\\t\\t\\t{'undo (z)' translated.\\t\\t\\t\\t\\t#undo}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'copy (c)' translated.\\t\\t\\t\\t\\t#copySelection}.\\n\\t\\t\\t{'cut (x)' translated.\\t\\t\\t\\t\\t\\t#cut}.\\n\\t\\t\\t{'paste (v)' translated.\\t\\t\\t\\t\\t#paste}.\\n\\t\\t\\t{'paste...' translated.\\t\\t\\t\\t\\t#pasteRecent}.\\n\\t\\t\\t#-.\\n\\t\\t\\t{'accept (s)' translated.\\t\\t\\t\\t\\t#accept}.\\n\\t\\t\\t{'cancel (l)' translated.\\t\\t\\t\\t\\t#cancel}.\\n\\t\\t}.\\n! !\\n\\n\\n!ParagraphEditor class methodsFor: 'instance creation' stamp: 'nk 9/3/2004 14:10'!\\nnew\\n\\t\\\"Answer a new instance of me with a null Paragraph to be edited.\\\"\\n\\n\\t| aParagraphEditor |\\n\\taParagraphEditor _ super new.\\n\\taParagraphEditor changeParagraph: '' asParagraph.\\n\\t^aParagraphEditor! !\\n\\n!ParagraphEditor class methodsFor: 'instance creation'!\\nnewParagraph: aParagraph \\n\\t\\\"Answer an instance of me with aParagraph as the text to be edited.\\\"\\n\\n\\t| aParagraphEditor |\\n\\taParagraphEditor _ super new.\\n\\taParagraphEditor initialize.\\n\\taParagraphEditor changeParagraph: aParagraph.\\n\\t^aParagraphEditor! !\\n\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'dgd 4/4/2006 16:04'!\\ninitializeCmdKeyShortcuts\\n\\t\\\"Initialize the (unshifted) command-key (or alt-key) shortcut table.\\\"\\n\\n\\t\\\"NOTE: if you don't know what your keyboard generates, use Sensor kbdTest\\\"\\n\\n\\t\\\"ParagraphEditor initialize\\\"\\n\\n\\t| cmdMap |\\n\\n\\tcmdMap := Array new: 256 withAll: #noop:.\\t\\\"use temp in case of a crash\\\"\\n\\n\\tcmdMap at: 1 + 1 put: #cursorHome:.\\t\\t\\t\\\"home key\\\"\\n\\tcmdMap at: 4 + 1 put: #cursorEnd:.\\t\\t\\t\\t\\\"end key\\\"\\n\\tcmdMap at: 8 + 1 put: #backspace:.\\t\\t\\t\\t\\\"ctrl-H or delete key\\\"\\n\\tcmdMap at: 11 + 1 put: #cursorPageUp:.\\t\\t\\\"page up key\\\"\\n\\tcmdMap at: 12 + 1 put: #cursorPageDown:.\\t\\\"page down key\\\"\\n\\tcmdMap at: 13 + 1 put: #crWithIndent:.\\t\\t\\t\\\"cmd-Return\\\"\\n\\tcmdMap at: 27 + 1 put: #offerMenuFromEsc:.\\t\\\"escape key\\\"\\n\\tcmdMap at: 28 + 1 put: #cursorLeft:.\\t\\t\\t\\\"left arrow key\\\"\\n\\tcmdMap at: 29 + 1 put: #cursorRight:.\\t\\t\\t\\\"right arrow key\\\"\\n\\tcmdMap at: 30 + 1 put: #cursorUp:.\\t\\t\\t\\t\\\"up arrow key\\\"\\n\\tcmdMap at: 31 + 1 put: #cursorDown:.\\t\\t\\t\\\"down arrow key\\\"\\n\\tcmdMap at: 32 + 1 put: #selectWord:.\\t\\t\\t\\\"space bar key\\\"\\n\\tcmdMap at: 127 + 1 put: #forwardDelete:.\\t\\t\\\"del key\\\"\\n\\n\\t'0123456789-=' \\n\\t\\tdo: [:char | cmdMap at: char asciiValue + 1 put: #changeEmphasis:].\\n\\n\\t'([{''\\\"<' do: [:char | cmdMap at: char asciiValue + 1 put: #enclose:].\\n\\n\\tcmdMap at: $, asciiValue + 1 put: #shiftEnclose:.\\n\\n\\t\\\"triplet = {character. comment selector. novice appropiated}\\\"\\n\\t#(\\n\\t\\t($a\\t\\t#selectAll:\\t\\t\\t\\ttrue)\\n\\t\\t($b\\t\\t#browseIt:\\t\\t\\t\\tfalse)\\n\\t\\t($c\\t\\t#copySelection:\\t\\t\\ttrue)\\n\\t\\t($d\\t\\t#doIt:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($e\\t\\t#exchange:\\t\\t\\t\\ttrue)\\n\\t\\t($f\\t\\t#find:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($g\\t\\t#findAgain:\\t\\t\\t\\ttrue)\\n\\t\\t($h\\t\\t#setSearchString:\\t\\ttrue)\\n\\t\\t($i\\t\\t#inspectIt:\\t\\t\\t\\tfalse)\\n\\t\\t($j\\t\\t#doAgainOnce:\\t\\t\\ttrue)\\n\\t\\t($k\\t\\t#offerFontMenu:\\t\\ttrue)\\n\\t\\t($l\\t\\t#cancel:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($m\\t#implementorsOfIt:\\t\\tfalse)\\n\\t\\t($n\\t\\t#sendersOfIt:\\t\\t\\tfalse)\\n\\t\\t($o\\t\\t#spawnIt:\\t\\t\\t\\tfalse)\\n\\t\\t($p\\t\\t#printIt:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($q\\t\\t#querySymbol:\\t\\t\\tfalse)\\n\\t\\t($s\\t\\t#save:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($t\\t\\t#tempCommand:\\t\\tfalse)\\n\\t\\t($u\\t\\t#align:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($v\\t\\t#paste:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($w\\t#backWord:\\t\\t\\t\\ttrue)\\n\\t\\t($x\\t\\t#cut:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($y\\t\\t#swapChars:\\t\\t\\t\\ttrue)\\n\\t\\t($z\\t\\t#undo:\\t\\t\\t\\t\\ttrue)\\n\\t)\\n\\t\\tselect:[:triplet | Preferences noviceMode not or:[triplet third]]\\n\\t\\tthenDo:[:triplet | cmdMap at: triplet first asciiValue + 1 put: triplet second].\\n\\n\\tCmdActions := cmdMap.\\n! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'dgd 10/4/2004 13:53'!\\ninitializeShiftCmdKeyShortcuts \\n\\t\\\"Initialize the shift-command-key (or control-key) shortcut table.\\\"\\n\\t\\\"NOTE: if you don't know what your keyboard generates, use Sensor kbdTest\\\"\\n\\t\\\"wod 11/3/1998: Fix setting of cmdMap for shifted keys to actually use the \\n\\tcapitalized versions of the letters.\\n\\tTPR 2/18/99: add the plain ascii values back in for those VMs that don't return the shifted values.\\\"\\n\\n\\t| cmdMap |\\n\\n\\t\\\"shift-command and control shortcuts\\\"\\n\\tcmdMap _ Array new: 256 withAll: #noop:. \\\"use temp in case of a crash\\\"\\n\\n\\tcmdMap at: ( 1 + 1) put: #cursorHome:.\\t\\t\\t\\t\\\"home key\\\"\\n\\tcmdMap at: ( 4 + 1) put: #cursorEnd:.\\t\\t\\t\\t\\\"end key\\\"\\n\\tcmdMap at: ( 8 + 1) put: #forwardDelete:.\\t\\t\\t\\\"ctrl-H or delete key\\\"\\n\\tcmdMap at: (11 + 1) put: #cursorPageUp:.\\t\\t\\t\\\"page up key\\\"\\n\\tcmdMap at: (12 + 1) put: #cursorPageDown:.\\t\\t\\\"page down key\\\"\\n\\tcmdMap at: (13 + 1) put: #crWithIndent:.\\t\\t\\t\\\"ctrl-Return\\\"\\n\\tcmdMap at: (27 + 1) put: #offerMenuFromEsc:.\\t\\\"escape key\\\"\\n\\tcmdMap at: (28 + 1) put: #cursorLeft:.\\t\\t\\t\\t\\\"left arrow key\\\"\\n\\tcmdMap at: (29 + 1) put: #cursorRight:.\\t\\t\\t\\t\\\"right arrow key\\\"\\n\\tcmdMap at: (30 + 1) put: #cursorUp:.\\t\\t\\t\\t\\\"up arrow key\\\"\\n\\tcmdMap at: (31 + 1) put: #cursorDown:.\\t\\t\\t\\\"down arrow key\\\"\\n\\tcmdMap at: (32 + 1) put: #selectWord:.\\t\\t\\t\\t\\\"space bar key\\\"\\n\\tcmdMap at: (45 + 1) put: #changeEmphasis:.\\t\\t\\\"cmd-sh-minus\\\"\\n\\tcmdMap at: (61 + 1) put: #changeEmphasis:.\\t\\t\\\"cmd-sh-plus\\\"\\n\\tcmdMap at: (127 + 1) put: #forwardDelete:.\\t\\t\\\"del key\\\"\\n\\n\\t\\\"Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $(\\\"\\n\\t'9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ].\\t\\\"({< and double-quote\\\"\\n\\t\\\"Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command.\\\"\\n\\n\\t\\\"NB: sw 12/9/2001 commented out the idiosyncratic line just below, which was grabbing shift-esc in the text editor and hence which argued with the wish to have shift-esc be a universal gesture for escaping the local context and calling up the desktop menu.\\\" \\n\\t\\\"cmdMap at: (27 + 1) put: #shiftEnclose:.\\\" \\t\\\"ctrl-[\\\"\\n\\n\\t\\\"'\\\"\\\"''(' do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose:].\\\"\\n\\n\\t\\\"triplet = {character. comment selector. novice appropiated}\\\"\\n\\t#(\\n\\t\\t($a\\t\\targAdvance:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($b\\t\\tbrowseItHere:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($c\\t\\tcompareToClipboard:\\t\\t\\tfalse)\\n\\t\\t($d\\t\\tduplicate:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($e\\t\\tmethodStringsContainingIt:\\tfalse)\\n\\t\\t($f\\t\\tdisplayIfFalse:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($g\\t\\tfileItIn:\\t\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($h\\t\\tcursorTopHome:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($i\\t\\texploreIt:\\t\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($j\\t\\tdoAgainMany:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($k\\t\\tchangeStyle:\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($l\\t\\toutdent:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($m\\tselectCurrentTypeIn:\\t\\t\\ttrue)\\n\\t\\t($n\\t\\treferencesToIt:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($p\\t\\tmakeProjectLink:\\t\\t\\t\\ttrue)\\n\\t\\t($r\\t\\tindent:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($s\\t\\tsearch:\\t\\t\\t\\t\\t\\t\\ttrue)\\n\\t\\t($t\\t\\tdisplayIfTrue:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($u\\t\\tchangeLfToCr:\\t\\t\\t\\t\\tfalse)\\n\\t\\t($v\\t\\tpasteInitials:\\t\\t\\t\\t\\t\\tfalse)\\n\\t\\t($w\\tmethodNamesContainingIt:\\tfalse)\\n\\t\\t($x\\t\\tmakeLowercase:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($y\\t\\tmakeUppercase:\\t\\t\\t\\t\\ttrue)\\n\\t\\t($z\\t\\tmakeCapitalized:\\t\\t\\t\\ttrue)\\n\\t)\\n\\t\\tselect:[:triplet | Preferences noviceMode not or:[triplet third]]\\n\\t\\tthenDo:[:triplet |\\n\\t\\t\\tcmdMap at: (triplet first asciiValue + 1) put: triplet second.\\t\\t\\\"plain keys\\\"\\n\\t\\t\\tcmdMap at: (triplet first asciiValue - 32 + 1) put: triplet second.\\t\\t\\\"shifted keys\\\"\\n\\t\\t\\tcmdMap at: (triplet first asciiValue - 96 + 1) put: triplet second.\\t\\t\\\"ctrl keys\\\"\\n\\t\\t].\\n\\n\\tShiftCmdActions _ cmdMap! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sps 7/24/2003 17:25'!\\nmultiRedoOverride\\n\\\"Call this to set meta-r to perform the multilevel redo (or tweak the code below to have it bound to some other key sequence).\\\"\\n\\n\\\"\\nParagraphEditor multiRedoOverride.\\n\\\"\\n\\tCmdActions at: $r asciiValue + 1 put: #multiRedo: \\n! !\\n\\n!ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sbw 10/8/1999 21:42'!\\nspecialShiftCmdKeys\\n\\n\\\"Private - return array of key codes that represent single keys acting\\nas if shift-command were also being pressed\\\"\\n\\n^#(\\n\\t1\\t\\\"home\\\"\\n\\t3\\t\\\"enter\\\"\\n\\t4\\t\\\"end\\\"\\n\\t8\\t\\\"backspace\\\"\\n\\t11\\t\\\"page up\\\"\\n\\t12\\t\\\"page down\\\"\\n\\t27\\t\\\"escape\\\"\\n\\t28\\t\\\"left arrow\\\"\\n\\t29\\t\\\"right arrow\\\"\\n\\t30\\t\\\"up arrow\\\"\\n\\t31\\t\\\"down arrow\\\"\\n\\t127\\t\\\"delete\\\"\\n\\t)! !\\nTileMorph subclass: #ParameterTile\\n\\tinstanceVariableNames: 'scriptEditor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!ParameterTile commentStamp: '<historical>' prior: 0!\\nRepresents a parameter in a user-defined script in \\\"classic\\\" tile-scripting. The type of a script's parameter is declared in the ScriptEditor for the script, and a parameter tile gets its type from the script. But because the user can change the parameter type *after* having created parameter tiles, we can later have type mismatches. Which however we at least deal with reasonably cleverly.!\\n\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 3/15/2005 21:45'!\\nisBoolean \\n\\t\\\"Answer whether the receiver's type is inherently boolean\\\"\\n\\n\\t^ self scriptEditor typeForParameter == #Boolean! !\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 3/15/2005 22:36'!\\nrowOfRightTypeFor: aLayoutMorph forActor: aPlayer\\n\\t\\\"Answer a phrase of the right type for the putative container\\\"\\n\\n\\t| aTemporaryViewer aPhrase |\\n\\taLayoutMorph demandsBoolean ifTrue:\\n\\t\\t[aTemporaryViewer _ CategoryViewer new invisiblySetPlayer: aPlayer.\\n\\t\\taPhrase _ aTemporaryViewer booleanPhraseFromPhrase: self.\\n\\t\\taPhrase justGrabbedFromViewer: false.\\n\\t\\t^ aPhrase].\\n\\t^ self! !\\n\\n!ParameterTile methodsFor: 'access' stamp: 'sw 1/18/2004 22:12'!\\nscriptEditor\\n\\t\\\"Answer the receiver's script editor. The slightly strange code here is in order to contend with the unusual situation where a parameter tile obtained from one script editor is later dropped into a different script editor. As long as the parameter tile is *in* a script editor, that containing scriptEditor is the one; if it is *not*, then we use the last known one\\\"\\n\\n\\t| aScriptEditor |\\n\\t^ (aScriptEditor _ self outermostMorphThat: [:m | m isKindOf: ScriptEditorMorph])\\n\\t\\tifNotNil:\\n\\t\\t\\t[scriptEditor _ aScriptEditor]\\n\\t\\tifNil:\\n\\t\\t\\t[scriptEditor]! !\\n\\n\\n!ParameterTile methodsFor: 'accessing' stamp: 'sw 7/18/2002 02:45'!\\nresultType\\n\\t\\\"Answer the result type of the receiver\\\"\\n\\n\\t^ self scriptEditor typeForParameter! !\\n\\n\\n!ParameterTile methodsFor: 'code generation' stamp: 'yo 12/20/2003 02:49'!\\nstoreCodeOn: aStream indent: tabCount\\n\\t\\\"Store code on the stream\\\"\\n \\n\\t| myTypeString |\\n\\tmyTypeString _ self resultType.\\n\\t(self scriptEditor hasParameter and: [self scriptEditor typeForParameter = myTypeString])\\n\\t\\tifTrue:\\n\\t\\t\\t[aStream nextPutAll: 'parameter']\\n\\t\\tifFalse:\\n\\t\\t\\t[\\\"This script no longer bears a parameter, yet there's an orphaned Parameter tile in it\\\"\\n\\t\\t\\taStream nextPutAll: '(self defaultValueOfType: #', myTypeString, ')']! !\\n\\n\\n!ParameterTile methodsFor: 'initialization' stamp: 'yo 3/14/2005 08:01'!\\nforScriptEditor: aScriptEditor\\n\\t\\\"Make the receiver be associated with the given script editor\\\"\\n\\n\\tscriptEditor _ aScriptEditor.\\n\\tself line1: aScriptEditor typeForParameter translated.! !\\n\\n!ParameterTile methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:45'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself typeColor: Color red! !\\n\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 21:55'!\\nassociatedPlayer\\n\\t\\\"Answer the player with which the receiver is associated\\\"\\n\\n\\t^ self scriptEditor playerScripted! !\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 22:37'!\\nbooleanComparatorPhrase\\n\\t\\\"Answer a boolean-valued phrase derived from a retriever (e.g. 'car's heading'); this is in order to assure that tiles laid down in a TEST area will indeed produce a boolean result\\\"\\n\\n\\t| outerPhrase rel retrieverType |\\n\\tretrieverType _ self resultType.\\n\\n\\trel _ (Vocabulary vocabularyForType: retrieverType) comparatorForSampleBoolean.\\n\\touterPhrase _ PhraseTileMorph new setOperator: rel type: #Boolean rcvrType: retrieverType argType: retrieverType.\\n\\touterPhrase firstSubmorph addMorph: self.\\n\\touterPhrase submorphs last addMorph: (ScriptingSystem tileForArgType: retrieverType).\\n\\n\\touterPhrase submorphs second submorphs last setBalloonText: (ScriptingSystem helpStringForOperator: rel). \\n\\t^ outerPhrase! !\\n\\n!ParameterTile methodsFor: 'miscellaneous' stamp: 'sw 3/15/2005 22:41'!\\ntileRows\\n\\t\\\"Answer a list of tile rows -- in this case exactly one row -- representing the receiver.\\\"\\n\\n\\t^ Array with: (Array with: self)! !\\n\\n\\n!ParameterTile methodsFor: 'type' stamp: 'sw 7/22/2002 17:48'!\\nassureTypeStillValid\\n\\t\\\"Consider the possibility that the parameter type of my surrounding method has changed and that hence I no longer represent a possible value for the parameter of the script. If this condition obtains, then banish me in favor of a default literal tile of the correct type\\\"\\n\\n\\t(self ownerThatIsA: TilePadMorph) ifNotNilDo:\\n\\t\\t[:aPad | aPad type = self scriptEditor typeForParameter ifFalse:\\n\\t\\t\\t[aPad setToBearDefaultLiteral]]! !\\nObject subclass: #ParseNode\\n\\tinstanceVariableNames: 'comment pc'\\n\\tclassVariableNames: 'Bfp BtpLong CodeBases CodeLimits DblExtDoAll Dup EndMethod EndRemote Jmp JmpLimit JmpLong LdFalse LdInstLong LdInstType LdLitIndType LdLitType LdMinus1 LdNil LdSelf LdSuper LdTempType LdThisContext LdTrue LoadLong LongLongDoAll NodeFalse NodeNil NodeSelf NodeSuper NodeThisContext NodeTrue Pop Send SendLimit SendLong SendLong2 SendPlus SendType ShortStoP StdLiterals StdSelectors StdVariables Store StorePop'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-ParseNodes'!\\n!ParseNode commentStamp: '<historical>' prior: 0!\\nThis 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.!\\n\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitBranchOn:\\ncondition dist: dist pop: stack on: strm\\n\\tstack pop: 1.\\n\\tdist = 0 ifTrue: [^ strm nextPut: Pop].\\n\\tcondition\\n\\t\\tifTrue: [self emitLong: dist code: BtpLong on: strm]\\n\\t\\tifFalse: [self emitShortOrLong: dist code: Bfp on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitForEffect: stack on: strm\\n\\n\\tself emitForValue: stack on: strm.\\n\\tstrm nextPut: Pop.\\n\\tstack pop: 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitForReturn: stack on: strm\\n\\n\\tself emitForValue: stack on: strm.\\n\\tstrm nextPut: EndMethod! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitJump: dist on: strm\\n\\n\\tdist = 0 ifFalse: [self emitShortOrLong: dist code: Jmp on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitLong: dist code: longCode on: aStream \\n\\t\\\"Force a two-byte jump.\\\"\\n\\t| code distance |\\n\\tcode _ longCode.\\n\\tdistance _ dist.\\n\\tdistance < 0\\n\\t\\tifTrue: \\n\\t\\t\\t[distance _ distance + 1024.\\n\\t\\t\\tcode _ code - 4]\\n\\t\\tifFalse: \\n\\t\\t\\t[distance > 1023 ifTrue: [distance _ -1]].\\n\\tdistance < 0\\n\\t\\tifTrue: \\n\\t\\t\\t[self error: 'A block compiles more than 1K bytes of code']\\n\\t\\tifFalse: \\n\\t\\t\\t[aStream nextPut: distance // 256 + code.\\n\\t\\t\\taStream nextPut: distance \\\\\\\\ 256]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nemitShortOrLong: dist code: shortCode on: strm\\n\\t(1 <= dist and: [dist <= JmpLimit])\\n\\t\\tifTrue: [strm nextPut: shortCode + dist - 1]\\n\\t\\tifFalse: [self emitLong: dist code: shortCode + (JmpLong-Jmp) on: strm]! !\\n\\n!ParseNode methodsFor: 'code generation' stamp: 'nk 7/10/2004 10:04'!\\npc\\n\\t\\\"Used by encoder source mapping.\\\"\\n\\n\\t^pc ifNil: [ 0 ]\\n! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeBranchOn: condition dist: dist\\n\\tdist = 0 ifTrue: [^1].\\n\\t^ condition\\n\\t\\tifTrue: [2] \\\"Branch on true is always 2 bytes\\\"\\n\\t\\tifFalse: [self sizeShortOrLong: dist]! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeForEffect: encoder\\n\\n\\t^(self sizeForValue: encoder) + 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeForReturn: encoder\\n\\n\\t^(self sizeForValue: encoder) + 1! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeJump: dist\\n\\n\\tdist = 0 ifTrue: [^0].\\n\\t^self sizeShortOrLong: dist! !\\n\\n!ParseNode methodsFor: 'code generation'!\\nsizeShortOrLong: dist\\n\\n\\t(1 <= dist and: [dist <= JmpLimit])\\n\\t\\tifTrue: [^1].\\n\\t^2! !\\n\\n\\n!ParseNode methodsFor: 'comment'!\\ncomment\\n\\n\\t^comment! !\\n\\n!ParseNode methodsFor: 'comment'!\\ncomment: newComment\\n\\n\\tcomment _ newComment! !\\n\\n\\n!ParseNode methodsFor: 'converting'!\\nasReturnNode\\n\\n\\t^ReturnNode new expr: self! !\\n\\n\\n!ParseNode methodsFor: 'encoding'!\\nencodeSelector: selector\\n\\n\\t^nil! !\\n\\n\\n!ParseNode methodsFor: 'printing' stamp: 'tk 10/16/2000 13:57'!\\nnodePrintOn: aStrm indent: nn\\n\\t| var aaStrm myLine |\\n\\t\\\"Show just the sub nodes and the code.\\\"\\n\\n\\t(aaStrm _ aStrm) ifNil: [aaStrm _ WriteStream on: (String new: 500)].\\n\\tnn timesRepeat: [aaStrm tab].\\n\\taaStrm nextPutAll: self class name; space.\\n\\tmyLine _ self printString copyWithout: Character cr.\\n\\tmyLine _ myLine copyFrom: 1 to: (myLine size min: 70).\\n\\taaStrm nextPutAll: myLine; cr.\\n\\t1 to: self class instSize do: [:ii | \\n\\t\\tvar _ self instVarAt: ii.\\n\\t\\t(var respondsTo: #asReturnNode) ifTrue: [var nodePrintOn: aaStrm indent: nn+1]].\\n\\t1 to: self class instSize do: [:ii | \\n\\t\\tvar _ self instVarAt: ii.\\n\\t\\t(var isKindOf: SequenceableCollection) ifTrue: [\\n\\t\\t\\t\\tvar do: [:aNode | \\n\\t\\t\\t\\t\\t(aNode respondsTo: #asReturnNode) ifTrue: [\\n\\t\\t\\t\\t\\t\\taNode nodePrintOn: aaStrm indent: nn+1]]]].\\n\\t^ aaStrm\\n! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'ab 7/13/2004 13:46'!\\nprintCommentOn: aStream indent: indent \\n\\t| thisComment |\\n\\tself comment == nil ifTrue: [^ self].\\n\\taStream withStyleFor: #comment\\n\\t\\tdo: [1 to: self comment size do: \\n\\t\\t\\t\\t[:index | \\n\\t\\t\\t\\tindex > 1 ifTrue: [aStream crtab: indent].\\n\\t\\t\\t\\taStream nextPut: $\\\".\\n\\t\\t\\t\\tthisComment _ self comment at: index.\\n\\t\\t\\t\\tself printSingleComment: thisComment\\n\\t\\t\\t\\t\\ton: aStream\\n\\t\\t\\t\\t\\tindent: indent.\\n\\t\\t\\t\\taStream nextPut: $\\\"]].\\n\\tself comment: nil! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'md 8/15/2005 11:02'!\\nprintOn: aStream \\n\\t\\\"Refer to the comment in Object|printOn:.\\\"\\n\\n\\taStream nextPutAll: '{'.\\n\\taStream nextPutAll: ((ColoredCodeStream contents: [:strm | self printOn: strm indent: 0])\\n\\t\\t\\t\\t\\t\\t\\tasString).\\n\\taStream nextPutAll: '}'! !\\n\\n!ParseNode methodsFor: 'printing'!\\nprintOn: aStream indent: anInteger \\n\\t\\\"If control gets here, avoid recursion loop.\\\"\\n\\n\\tsuper printOn: aStream! !\\n\\n!ParseNode methodsFor: 'printing'!\\nprintOn: aStream indent: level precedence: p\\n\\n\\tself printOn: aStream indent: level! !\\n\\n!ParseNode methodsFor: 'printing' stamp: 'ms 8/1/2006 16:47'!\\nshortPrintOn: aStream \\n\\tself printOn: aStream indent: 0! !\\n\\n\\n!ParseNode methodsFor: 'testing'!\\nassignmentCheck: encoder at: location\\n\\t\\\"For messageNodes masquerading as variables for the debugger.\\n\\tFor now we let this through - ie we allow stores ev\\n\\tinto args. Should check against numArgs, though.\\\"\\n\\t^ -1! !\\n\\n!ParseNode methodsFor: 'testing'!\\ncanBeSpecialArgument\\n\\t\\\"Can I be an argument of (e.g.) ifTrue:?\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\ncanCascade\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisArg\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisComplex\\n\\t\\\"Used for pretty printing to determine whether to start a new line\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisConstantNumber \\\"Overridden in LiteralNode\\\"\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'md 1/20/2006 16:22'!\\nisDoIt\\n\\t\\\"polymorphic with RBNodes; called by debugger\\\"\\n\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'ls 1/29/2004 21:11'!\\nisJust: node\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'di 4/5/2000 11:14'!\\nisLiteral\\n\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'md 7/27/2006 19:14'!\\nisMessage\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisMessage: selSymbol receiver: rcvrPred arguments: argsPred\\n\\t\\\"See comment in MessageNode.\\\"\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisReturnSelf\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisReturningIf\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'tk 8/2/1999 18:39'!\\nisSelfPseudoVariable\\t\\n\\t\\\"Overridden in VariableNode.\\\"\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisSpecialConstant\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing' stamp: 'di 10/12/1999 15:28'!\\nisTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisUndefTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisUnusedTemp\\n\\t^ false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nisVariableReference\\n\\n\\t^false! !\\n\\n!ParseNode methodsFor: 'testing'!\\nnowHasDef \\\"Ignored in all but VariableNode\\\"! !\\n\\n!ParseNode methodsFor: 'testing'!\\nnowHasRef \\\"Ignored in all but VariableNode\\\"! !\\n\\n!ParseNode methodsFor: 'testing'!\\ntoDoIncrement: ignored\\n\\t\\\"Only meant for Messages or Assignments - else return nil\\\"\\n\\t^ nil! !\\n\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'ab 7/13/2004 13:47'!\\naddCommentToMorph: aMorph\\n\\t| row |\\n\\t(self comment isNil or: [self comment isEmpty]) ifTrue: [^ self].\\n\\trow _ aMorph addTextRow:\\n\\t\\t(String streamContents: [:strm | self printCommentOn: strm indent: 1]).\\n\\trow firstSubmorph color: (SyntaxMorph translateColor: #comment).\\n\\trow parseNode: (self as: CommentNode).\\n! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 12:24'!\\nasMorphicSyntaxIn: parent\\n\\n\\t| morph |\\n\\t\\\"Default for missing implementations\\\"\\n\\n\\tmorph _ parent addColumn: #error on: self.\\n\\tmorph addTextRow: self class printString.\\n\\t^morph\\n\\t\\n\\n! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 13:06'!\\ncurrentValueIn: aContext\\n\\n\\t^nil! !\\n\\n!ParseNode methodsFor: '*eToys-tiles' stamp: 'RAA 8/24/1999 18:18'!\\nexplanation\\n\\n\\t^self class printString! !\\n\\n\\n!ParseNode methodsFor: 'private' stamp: 'ls 1/29/2004 21:17'!\\nifNilReceiver\\n\\t\\\"assuming this object is the receiver of an ifNil:, what object is being asked about?\\\"\\n\\t^self! !\\n\\n!ParseNode methodsFor: 'private' stamp: 'sma 5/28/2000 10:47'!\\nnextWordFrom: aStream setCharacter: aBlock\\n\\t| outStream char |\\n\\toutStream _ WriteStream on: (String new: 16).\\n\\t[(aStream peekFor: Character space) \\n\\t\\tor: [aStream peekFor: Character tab]] whileTrue.\\n\\t[aStream atEnd\\n\\t\\tor:\\n\\t\\t\\t[char _ aStream next.\\n\\t\\t\\tchar = Character cr or: [char = Character space]]]\\n\\t\\twhileFalse: [outStream nextPut: char].\\n\\taBlock value: char.\\n\\t^ outStream contents! !\\n\\n!ParseNode methodsFor: 'private' stamp: 'nk 7/11/2004 13:39'!\\nprintSingleComment: aString on: aStream indent: indent \\n\\t\\\"Print the comment string, assuming it has been indented indent tabs.\\n\\tBreak the string at word breaks, given the widths in the default\\n\\tfont, at 450 points.\\\"\\n\\n\\t| readStream word position lineBreak font wordWidth tabWidth spaceWidth lastChar |\\n\\treadStream _ ReadStream on: aString.\\n\\tfont _ TextStyle default defaultFont.\\n\\ttabWidth _ TextConstants at: #DefaultTab.\\n\\tspaceWidth _ font widthOf: Character space.\\n\\tposition _ indent * tabWidth.\\n\\tlineBreak _ 450.\\n\\t[readStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[word _ self nextWordFrom: readStream setCharacter: [:lc | lastChar _ lc].\\n\\t\\t\\twordWidth _ word inject: 0 into: [:width :char | width + (font widthOf: char)].\\n\\t\\t\\tposition _ position + wordWidth.\\n\\t\\t\\tposition > lineBreak\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[aStream skip: -1; crtab: indent.\\n\\t\\t\\t\\t\\tposition _ indent * tabWidth + wordWidth + spaceWidth.\\n\\t\\t\\t\\t\\tlastChar = Character cr\\n\\t\\t\\t\\t\\t\\tifTrue: [[readStream peekFor: Character tab] whileTrue].\\n\\t\\t\\t\\t\\tword isEmpty ifFalse: [aStream nextPutAll: word; space]]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[aStream nextPutAll: word.\\n\\t\\t\\t\\t\\treadStream atEnd\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[position _ position + spaceWidth.\\n\\t\\t\\t\\t\\t\\t\\taStream space].\\n\\t\\t\\t\\t\\tlastChar = Character cr\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[aStream skip: -1; crtab: indent.\\n\\t\\t\\t\\t\\t\\t\\tposition _ indent * tabWidth.\\n\\t\\t\\t\\t\\t\\t\\t[readStream peekFor: Character tab] whileTrue]]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nParseNode class\\n\\tinstanceVariableNames: ''!\\n\\n!ParseNode class methodsFor: 'class initialization' stamp: 'ajh 8/12/2002 11:10'!\\nblockReturnCode\\n\\n\\t^ EndRemote! !\\n\\n!ParseNode class methodsFor: 'class initialization'!\\ninitialize\\n\\t\\\"ParseNode initialize. VariableNode initialize\\\"\\n\\tLdInstType _ 1.\\n\\tLdTempType _ 2.\\n\\tLdLitType _ 3.\\n\\tLdLitIndType _ 4.\\n\\tSendType _ 5.\\n\\tCodeBases _ #(0 16 32 64 208 ).\\n\\tCodeLimits _ #(16 16 32 32 16 ).\\n\\tLdSelf _ 112.\\n\\tLdTrue _ 113.\\n\\tLdFalse _ 114.\\n\\tLdNil _ 115.\\n\\tLdMinus1 _ 116.\\n\\tLoadLong _ 128.\\n\\tStore _ 129.\\n\\tStorePop _ 130.\\n\\tShortStoP _ 96.\\n\\tSendLong _ 131.\\n\\tDblExtDoAll _ 132.\\n\\tSendLong2 _ 134.\\n\\tLdSuper _ 133.\\n\\tPop _ 135.\\n\\tDup _ 136.\\n\\tLdThisContext _ 137.\\n\\tEndMethod _ 124.\\n\\tEndRemote _ 125.\\n\\tJmp _ 144.\\n\\tBfp _ 152.\\n\\tJmpLimit _ 8.\\n\\tJmpLong _ 164. \\\"code for jmp 0\\\"\\n\\tBtpLong _ 168.\\n\\tSendPlus _ 176.\\n\\tSend _ 208.\\n\\tSendLimit _ 16! !\\n\\n!ParseNode class methodsFor: 'class initialization' stamp: 'ajh 8/6/2002 12:04'!\\npopCode\\n\\n\\t^ Pop! !\\nObject subclass: #ParseStack\\n\\tinstanceVariableNames: 'position length'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Support'!\\n!ParseStack commentStamp: '<historical>' prior: 0!\\nI keep track of the current and high position of the stack that will be needed by code being compiled.!\\n\\n\\n!ParseStack methodsFor: 'accessing'!\\npop: n\\n\\n\\t(position _ position - n) < 0 \\n\\t\\tifTrue: [self error: 'Parse stack underflow']! !\\n\\n!ParseStack methodsFor: 'accessing'!\\npush: n\\n\\n\\t(position _ position + n) > length \\n\\t\\tifTrue: [length _ position]! !\\n\\n!ParseStack methodsFor: 'accessing'!\\nsize\\n\\n\\t^length! !\\n\\n\\n!ParseStack methodsFor: 'initialize-release'!\\ninit\\n\\n\\tlength _ position _ 0! !\\n\\n\\n!ParseStack methodsFor: 'printing'!\\nprintOn: aStream\\n\\t\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' at '; print: position; nextPutAll: ' of '; print: length! !\\n\\n\\n!ParseStack methodsFor: 'results'!\\nposition\\n\\n\\t^position! !\\nScanner subclass: #Parser\\n\\tinstanceVariableNames: 'here hereType hereMark hereEnd prevMark prevEnd encoder requestor parseNode failBlock requestorOffset tempsMark doitFlag properties category'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Kernel'!\\n!Parser commentStamp: '<historical>' prior: 0!\\nI parse Smalltalk syntax and create a MethodNode that is the root of the parse tree. I look one token ahead.!\\n\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 11:01'!\\ncorrectSelector: proposedKeyword wordIntervals: spots exprInterval: expInt ifAbort: abortAction\\n\\t\\\"Correct the proposedKeyword to some selector symbol, correcting the original text if such action is indicated. abortAction is invoked if 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.\\\"\\n\\n\\t| alternatives aStream choice correctSelector userSelection lines firstLine |\\n\\t\\\"If we can't ask the user, assume that the keyword will be defined later\\\"\\n\\tself interactive ifFalse: [ ^ proposedKeyword asSymbol ].\\n\\n\\tuserSelection _ requestor selectionInterval.\\n\\trequestor selectFrom: spots first first to: spots last last.\\n\\trequestor select.\\n\\talternatives _ Symbol possibleSelectorsFor: proposedKeyword.\\n\\tself flag: #toBeFixed.\\n\\t\\\"alternatives addAll: (MultiSymbol possibleSelectorsFor: proposedKeyword).\\\"\\n\\n\\taStream _ WriteStream on: (String new: 200).\\n\\taStream nextPutAll: (proposedKeyword contractTo: 35); cr.\\n\\tfirstLine _ 1.\\n \\talternatives do:\\n\\t\\t[:sel | aStream nextPutAll: (sel contractTo: 35); nextPut: Character cr].\\n\\taStream nextPutAll: 'cancel'.\\n\\tlines _ Array with: firstLine with: (alternatives size + firstLine).\\n\\t\\n\\tchoice _ (UIManager default \\n\\t\\t\\tchooseFrom: (aStream contents substrings)\\n\\t\\t\\tlines: lines\\n\\t\\t\\ttitle: 'Unknown selector, please\\\\confirm, correct, or cancel' withCRs).\\n\\n\\t(choice = 0) | (choice > (lines at: 2))\\n\\t\\tifTrue: [ ^ abortAction value ].\\n\\n\\trequestor deselect.\\n\\trequestor selectInvisiblyFrom: userSelection first to: userSelection last.\\n\\n\\tchoice = 1 ifTrue: [ ^ proposedKeyword asSymbol ].\\n\\tcorrectSelector _ alternatives at: choice - 1.\\n\\tself substituteSelector: correctSelector keywords wordIntervals: spots.\\n\\t((proposedKeyword last ~= $:) and: [correctSelector last == $:]) ifTrue: [\\n\\t\\t^ abortAction value].\\n\\t^ correctSelector.\\n! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:01'!\\ncorrectVariable: proposedVariable interval: spot\\n\\t\\\"Correct the proposedVariable to a known variable, or declare it as a new\\n\\tvariable if such action is requested. We support declaring lowercase\\n\\tvariables as temps or inst-vars, and uppercase variables as Globals or \\n\\tClassVars, depending on whether the context is nil (class=UndefinedObject).\\n\\tSpot is the interval within the test stream of the variable.\\n\\trr 3/4/2004 10:26 : adds the option to define a new class. \\\"\\n\\n\\t| tempIvar labels actions lines alternatives binding userSelection choice action |\\n\\n\\t\\\"Check if this is an i-var, that has been corrected already (ugly)\\\"\\n\\t(encoder classEncoding allInstVarNames includes: proposedVariable) ifTrue: [\\n\\t\\t^LiteralVariableNode new \\n\\t\\t\\tname: proposedVariable index: (encoder classEncoding allInstVarNames indexOf: proposedVariable) - 1 type: 1;\\n\\t\\t\\tyourself ].\\n\\n\\t\\\"If we can't ask the user for correction, make it undeclared\\\"\\n\\tself interactive \\n\\t\\tifFalse: [ ^encoder undeclared: proposedVariable ].\\n\\n\\t\\\"First check to see if the requestor knows anything about the variable\\\"\\n\\ttempIvar _ proposedVariable first canBeNonGlobalVarInitial.\\n\\t(tempIvar and: [ (binding _ requestor bindingOf: proposedVariable) notNil ])\\n\\t\\tifTrue: [ ^encoder global: binding name: proposedVariable ].\\n\\tuserSelection _ requestor selectionInterval.\\n\\trequestor selectFrom: spot first to: spot last.\\n\\trequestor select.\\n\\n\\t\\\"Build the menu with alternatives\\\"\\n\\tlabels _ OrderedCollection new. actions _ OrderedCollection new. lines _ OrderedCollection new.\\n\\talternatives _ encoder possibleVariablesFor: proposedVariable.\\n\\ttempIvar \\n\\t\\tifTrue: [ \\n\\t\\t\\tlabels add: 'declare temp'. \\n\\t\\t\\tactions add: [ self declareTempAndPaste: proposedVariable ].\\n\\t\\t\\tlabels add: 'declare instance'.\\n\\t\\t\\tactions add: [ self declareInstVar: proposedVariable ] ]\\n\\t\\tifFalse: [ \\n\\t\\t\\tlabels add: 'define new class'.\\n\\t\\t\\tactions add: [self defineClass: proposedVariable].\\n\\t\\t\\tlabels add: 'declare global'.\\n\\t\\t\\tactions add: [ self declareGlobal: proposedVariable ].\\n\\t\\t\\tencoder classEncoding == UndefinedObject ifFalse: [ \\n\\t\\t\\t\\tlabels add: 'declare class variable'.\\n\\t\\t\\t\\tactions add: [ self declareClassVar: proposedVariable ] ] ].\\n\\tlines add: labels size.\\n\\talternatives do: [ :each | \\n\\t\\tlabels add: each.\\n\\t\\tactions add: [ \\n\\t\\t\\tself substituteWord: each wordInterval: spot offset: 0.\\n\\t\\t\\tencoder encodeVariable: each ] fixTemps ].\\n\\tlines add: labels size.\\n\\tlabels add: 'cancel'.\\n\\n\\t\\\"Display the pop-up menu\\\"\\n\\tchoice _ (UIManager default chooseFrom: labels asArray lines: lines asArray\\n\\t\\ttitle: 'Unknown variable: ', proposedVariable, ' please correct, or cancel:').\\n\\taction _ actions at: choice ifAbsent: [ ^self fail ].\\n\\n\\t\\\"Execute the selected action\\\"\\n\\trequestor deselect.\\n\\trequestor selectInvisiblyFrom: userSelection first to: userSelection last.\\n\\t^action value! !\\n\\n!Parser methodsFor: 'error correction'!\\ndeclareClassVar: name\\n\\t| sym class |\\n\\tsym _ name asSymbol.\\n\\tclass _ encoder classEncoding.\\n\\tclass _ class theNonMetaClass.\\t\\t\\\"not the metaclass\\\"\\n\\tclass addClassVarName: name.\\n\\t^ encoder global: (class classPool associationAt: sym)\\n\\t\\t\\tname: sym! !\\n\\n!Parser methodsFor: 'error correction'!\\ndeclareGlobal: name\\n\\t| sym |\\n\\tsym _ name asSymbol.\\n\\tSmalltalk at: sym put: nil.\\n\\t^ encoder global: (Smalltalk associationAt: sym) name: sym! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rr 3/6/2004 16:07'!\\ndeclareInstVar: name\\n\\t\\\" rr 3/6/2004 16:06 : adds the line to correctly compute the index. uncommented the option in \\n\\tthe caller.\\\"\\n\\t| index |\\n\\tencoder classEncoding addInstVarName: name.\\n\\tindex _ encoder classEncoding instVarNames indexOf: name.\\n\\tencoder classEncoding allSuperclassesDo: [:cls | index := index + cls instVarNames size].\\n\\t^LiteralVariableNode new\\n\\t\\tname: name index: index - 1 type: 1;\\n\\t\\tyourself\\n\\t\\t! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'RAA 6/5/2001 11:57'!\\ndeclareTempAndPaste: name\\n\\t| insertion delta theTextString characterBeforeMark |\\n\\n\\ttheTextString _ requestor text string.\\n\\tcharacterBeforeMark _ theTextString at: tempsMark-1 ifAbsent: [$ ].\\n\\t(theTextString at: tempsMark) = $| ifTrue: [\\n \\t\\t\\\"Paste it before the second vertical bar\\\"\\n\\t\\tinsertion _ name, ' '.\\n\\t\\tcharacterBeforeMark isSeparator ifFalse: [\\finsertion _ ' ', insertion].\\n\\t\\tdelta _ 0.\\n\\t] ifFalse: [\\n\\t\\t\\\"No bars - insert some with CR, tab\\\"\\n\\t\\tinsertion _ '| ' , name , ' |',String cr.\\n\\t\\tdelta _ 2.\\t\\\"the bar and CR\\\"\\n\\t\\tcharacterBeforeMark = Character tab ifTrue: [\\n\\t\\t\\tinsertion _ insertion , String tab.\\n\\t\\t\\tdelta _ delta + 1.\\t\\\"the tab\\\"\\n\\t\\t].\\n\\t].\\n\\ttempsMark _ tempsMark +\\n\\t\\t(self substituteWord: insertion\\n\\t\\t\\twordInterval: (tempsMark to: tempsMark-1)\\n\\t\\t\\toffset: 0) - delta.\\n\\t^ encoder bindAndJuggle: name! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'DF 4/28/2006 14:31'!\\ndefineClass: className \\n\\t\\\"prompts the user to define a new class, \\n\\tasks for it's category, and lets the users edit further \\n\\tthe definition\\\"\\n\\t| sym cat def d2 |\\n\\tsym := className asSymbol.\\n\\tcat := UIManager default request: 'Enter class category : ' initialAnswer: self encoder classEncoding theNonMetaClass category.\\n\\tcat\\n\\t\\tifEmpty: [cat := 'Unknown'].\\n\\tdef := 'Object subclass: #' , sym , '\\n\\t\\tinstanceVariableNames: '''' \\n\\t\\tclassVariableNames: ''''\\n\\t\\tpoolDictionaries: ''''\\n\\t\\tcategory: ''' , cat , ''''.\\n\\td2 := UIManager default request: 'Edit class definition : ' initialAnswer: def.\\n\\td2\\n\\t\\tifEmpty: [d2 := def].\\n\\tCompiler evaluate: d2.\\n\\t^ encoder\\n\\t\\tglobal: (Smalltalk associationAt: sym)\\n\\t\\tname: sym! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:10'!\\nqueryUndefined\\n\\t| varStart varName | \\n\\tvarName _ parseNode key.\\n\\tvarStart _ self endOfLastToken + requestorOffset - varName size + 1.\\n\\trequestor selectFrom: varStart to: varStart + varName size - 1; select.\\n\\t((UIManager default \\n\\t\\tchooseFrom: #('yes' 'no') \\n\\t\\ttitle: ((varName , ' appears to be\\\\undefined at this point.Proceed anyway?') \\n\\t\\t\\t\\twithCRs asText makeBoldFrom: 1 to: varName size))\\n\\t\\t= 1) ifFalse: [^ self fail]! !\\n\\n!Parser methodsFor: 'error correction' stamp: 'rbb 2/18/2005 09:08'!\\nremoveUnusedTemps\\n\\t\\\"Scan for unused temp names, and prompt the user about the prospect of removing each one found\\\"\\n\\n\\t| str end start madeChanges | \\n\\tmadeChanges _ false.\\n\\tstr _ requestor text string.\\n\\t((tempsMark between: 1 and: str size)\\n\\t\\tand: [(str at: tempsMark) = $|]) ifFalse: [^ self].\\n\\tencoder unusedTempNames do:\\n\\t\\t[:temp |\\n\\t\\t((UIManager default \\n\\t\\t\\t\\tchooseFrom: #('yes' 'no') \\n\\t\\t\\t\\ttitle: ((temp , ' appears to be\\\\unused in this method.\\\\OK to remove it?') \\n\\t\\t\\t\\t\\t\\twithCRs asText makeBoldFrom: 1 to: temp size)) = 1)\\n\\t\\tifTrue:\\n\\t\\t[(encoder encodeVariable: temp) isUndefTemp\\n\\t\\t\\tifTrue:\\n\\t\\t\\t[end _ tempsMark.\\n\\t\\t\\t[\\\"Beginning at right temp marker...\\\"\\n\\t\\t\\tstart _ end - temp size + 1.\\n\\t\\t\\tend < temp size or: [temp = (str copyFrom: start to: end)\\n\\t\\t\\t\\t\\tand: [(str at: start-1) isAlphaNumeric not & (str at: end+1) isAlphaNumeric not]]]\\n\\t\\t\\twhileFalse:\\n\\t\\t\\t\\t[\\\"Search left for the unused temp\\\"\\n\\t\\t\\t\\tend _ requestor nextTokenFrom: end direction: -1].\\n\\t\\t\\tend < temp size ifFalse:\\n\\t\\t\\t\\t[(str at: start-1) = $ ifTrue: [start _ start-1].\\n\\t\\t\\t\\trequestor correctFrom: start to: end with: ''.\\n\\t\\t\\t\\tstr _ str copyReplaceFrom: start to: end with: ''. \\n\\t\\t\\t\\tmadeChanges _ true.\\n\\t\\t\\t\\ttempsMark _ tempsMark - (end-start+1)]]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t[self inform:\\n'You''ll first have to remove the\\nstatement where it''s stored into']]].\\n\\tmadeChanges ifTrue: [ParserRemovedUnusedTemps signal]! !\\n\\n!Parser methodsFor: 'error correction'!\\nsubstituteSelector: selectorParts wordIntervals: spots\\n\\t\\\"Substitute the correctSelector into the (presuamed interactive) receiver.\\\"\\n\\t| offset |\\n\\toffset _ 0.\\n\\tselectorParts with: spots do:\\n\\t\\t[ :word :interval |\\n\\t\\toffset _ self substituteWord: word wordInterval: interval offset: offset ]\\n! !\\n\\n!Parser methodsFor: 'error correction'!\\nsubstituteWord: correctWord wordInterval: spot offset: o\\n\\t\\\"Substitute the correctSelector into the (presuamed interactive) receiver.\\\"\\n\\n\\trequestor correctFrom: (spot first + o)\\n\\t\\t\\t\\t\\tto: (spot last + o)\\n\\t\\t\\t\\t\\twith: correctWord.\\n\\n\\trequestorOffset _ requestorOffset + correctWord size - spot size.\\n\\t^ o + correctWord size - spot size! !\\n\\n\\n!Parser methodsFor: 'error handling' stamp: 'hmm 7/18/2001 21:45'!\\nexpected: aString \\n\\t\\\"Notify a problem at token 'here'.\\\"\\n\\n\\ttokenType == #doIt ifTrue: [hereMark _ hereMark + 1].\\n\\thereType == #doIt ifTrue: [hereMark _ hereMark + 1].\\n\\t^ self notify: aString , ' expected' at: hereMark + requestorOffset! !\\n\\n!Parser methodsFor: 'error handling'!\\nfail\\n\\n\\t| exitBlock |\\n\\tencoder == nil\\n\\t\\tifFalse: [encoder release. encoder _ nil]. \\\"break cycle\\\"\\n\\texitBlock _ failBlock.\\n\\tfailBlock _ nil.\\n\\t^exitBlock value! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'stephaneducassse 11/5/2005 16:39'!\\ninteractive\\n\\t\\\"this version of the method is necessary to load code from MC else the interactive mode is one. \\n\\tThis method is really bad since it links the compiler package with the Tools\\n\\tone. The solution would be to have a real SyntaxError exception belonging to the \\n\\tcompiler package and not a subclass of StringHolder - sd Nov 2005\\\"\\n\\t\\\"the code submitted by PlusTools is ideally the one that should be used\\n\\tinteractive\\n\\n\\t ^requestor ~~ nil \\\"\\n\\t\\n\\t^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not! !\\n\\n!Parser methodsFor: 'error handling'!\\nnotify: aString \\n\\t\\\"Notify problem at token before 'here'.\\\"\\n\\n\\t^self notify: aString at: prevMark + requestorOffset! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'KLC 11/28/2005 18:01'!\\nnotify: string at: location\\n\\trequestor isNil\\n\\t\\tifTrue: [(encoder == self or: [encoder isNil]) ifTrue: [^ self fail \\\"failure setting up syntax error\\\"].\\n\\t\\t\\t\\tSyntaxErrorNotification\\n\\t\\t\\t\\t\\tinClass: encoder classEncoding\\n\\t\\t\\t\\t\\tcategory: encoder classEncoding category\\n\\t\\t\\t\\t\\twithCode: \\n\\t\\t\\t\\t\\t\\t(source contents\\n\\t\\t\\t\\t\\t\\t\\tcopyReplaceFrom: location\\n\\t\\t\\t\\t\\t\\t\\tto: location - 1\\n\\t\\t\\t\\t\\t\\t\\twith: string , ' ->')\\n\\t\\t\\t\\t\\tdoitFlag: doitFlag]\\n\\t\\tifFalse: [requestor\\n\\t\\t\\t\\t\\tnotify: string , ' ->'\\n\\t\\t\\t\\t\\tat: location\\n\\t\\t\\t\\t\\tin: source].\\n\\t^self fail! !\\n\\n!Parser methodsFor: 'error handling' stamp: 'di 2/9/1999 15:43'!\\noffEnd: aString \\n\\t\\\"Notify a problem beyond 'here' (in lookAhead token). Don't be offEnded!!\\\"\\n\\n\\trequestorOffset == nil\\n\\t\\tifTrue: [^ self notify: aString at: mark]\\n\\t\\tifFalse: [^ self notify: aString at: mark + requestorOffset]\\n! !\\n\\n\\n!Parser methodsFor: 'expression types'!\\nargumentName\\n\\n\\thereType == #word\\n\\t\\tifFalse: [^self expected: 'Argument name'].\\n\\t^self advance! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'hmm 7/16/2001 18:47'!\\nassignment: varNode\\n\\t\\\" var '_' expression => AssignmentNode.\\\"\\n\\t| loc start |\\n\\t(loc _ varNode assignmentCheck: encoder at: prevMark + requestorOffset) >= 0\\n\\t\\tifTrue: [^self notify: 'Cannot store into' at: loc].\\n\\tstart _ self startOfNextToken.\\n\\tvarNode nowHasDef.\\n\\tself advance.\\n\\tself expression ifFalse: [^self expected: 'Expression'].\\n\\tparseNode _ AssignmentNode new\\n\\t\\t\\t\\tvariable: varNode\\n\\t\\t\\t\\tvalue: parseNode\\n\\t\\t\\t\\tfrom: encoder\\n\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken).\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'hmm 7/17/2001 21:03'!\\nblockExpression\\n\\t\\\"[ ({:var} |) (| {temps} |) (statements) ] => BlockNode.\\\"\\n\\n\\t| variableNodes temporaryBlockVariables start |\\n\\n\\tvariableNodes _ OrderedCollection new.\\n\\tstart _ prevMark + requestorOffset.\\n\\t\\\"Gather parameters.\\\"\\n\\t[self match: #colon] whileTrue: [variableNodes addLast: (encoder autoBind: self argumentName)].\\n\\t(variableNodes size > 0 & (hereType ~~ #rightBracket) and: [(self match: #verticalBar) not]) ifTrue: [^self expected: 'Vertical bar'].\\n\\n\\ttemporaryBlockVariables _ self temporaryBlockVariables.\\n\\tself statements: variableNodes innerBlock: true.\\n\\tparseNode temporaries: temporaryBlockVariables.\\n\\n\\t(self match: #rightBracket) ifFalse: [^self expected: 'Period or right bracket'].\\n\\n\\tencoder noteSourceRange: (self endOfLastToken to: self endOfLastToken) forNode: parseNode.\\n\\n\\t\\\"The scope of the parameters and temporary block variables is no longer active.\\\"\\n\\ttemporaryBlockVariables do: [:variable | variable scope: -1].\\n\\tvariableNodes do: [:variable | variable scope: -1]! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 3/8/2000 09:36'!\\nbraceExpression\\n\\t\\\" { elements } => BraceNode.\\\"\\n\\n\\t| elements locations loc more |\\n\\telements _ OrderedCollection new.\\n\\tlocations _ OrderedCollection new.\\n\\tself advance.\\n\\tmore _ hereType ~~ #rightBrace.\\n\\t[more]\\n\\t\\twhileTrue: \\n\\t\\t\\t[loc _ hereMark + requestorOffset.\\n\\t\\t\\tself expression\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[elements addLast: parseNode.\\n\\t\\t\\t\\t\\tlocations addLast: loc]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[^self expected: 'Variable or expression'].\\n\\t\\t\\t(self match: #period)\\n\\t\\t\\t\\tifTrue: [more _ hereType ~~ #rightBrace]\\n\\t\\t\\t\\tifFalse: [more _ false]].\\n\\tparseNode _ BraceNode new elements: elements sourceLocations: locations.\\n\\t(self match: #rightBrace)\\n\\t\\tifFalse: [^self expected: 'Period or right brace'].\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types'!\\ncascade\\n\\t\\\" {; message} => CascadeNode.\\\"\\n\\n\\t| rcvr msgs |\\n\\tparseNode canCascade\\n\\t\\tifFalse: [^self expected: 'Cascading not'].\\n\\trcvr _ parseNode cascadeReceiver.\\n\\tmsgs _ OrderedCollection with: parseNode.\\n\\t[self match: #semicolon]\\n\\t\\twhileTrue: \\n\\t\\t\\t[parseNode _ rcvr.\\n\\t\\t\\t(self messagePart: 3 repeat: false)\\n\\t\\t\\t\\tifFalse: [^self expected: 'Cascade'].\\n\\t\\t\\tparseNode canCascade\\n\\t\\t\\t\\tifFalse: [^self expected: '<- No special messages'].\\n\\t\\t\\tparseNode cascadeReceiver.\\n\\t\\t\\tmsgs addLast: parseNode].\\n\\tparseNode _ CascadeNode new receiver: rcvr messages: msgs! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 11/19/1999 07:43'!\\nexpression\\n\\n\\t(hereType == #word and: [tokenType == #leftArrow])\\n\\t\\tifTrue: [^ self assignment: self variable].\\n\\thereType == #leftBrace\\n\\t\\tifTrue: [self braceExpression]\\n\\t\\tifFalse: [self primaryExpression ifFalse: [^ false]].\\n\\t(self messagePart: 3 repeat: true)\\n\\t\\tifTrue: [hereType == #semicolon ifTrue: [self cascade]].\\n\\t^ true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 4/5/2000 08:27'!\\nkeylessMessagePartTest: level repeat: repeat\\n! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'yo 8/30/2002 14:41'!\\nmessagePart: level repeat: repeat\\n\\n\\t| start receiver selector args precedence words keywordStart |\\n\\t[receiver _ parseNode.\\n\\t(hereType == #keyword and: [level >= 3])\\n\\t\\tifTrue: \\n\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\tselector _ WriteStream on: (String new: 32).\\n\\t\\t\\targs _ OrderedCollection new.\\n\\t\\t\\twords _ OrderedCollection new.\\n\\t\\t\\t[hereType == #keyword]\\n\\t\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t\\t[keywordStart _ self startOfNextToken + requestorOffset.\\n\\t\\t\\t\\t\\tselector nextPutAll: self advance.\\n\\t\\t\\t\\t\\twords addLast: (keywordStart to: self endOfLastToken + requestorOffset).\\n\\t\\t\\t\\t\\tself primaryExpression ifFalse: [^self expected: 'Argument'].\\n\\t\\t\\t\\t\\tself messagePart: 2 repeat: true.\\n\\t\\t\\t\\t\\targs addLast: parseNode].\\n\\t\\t\\t(Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym])\\n\\t\\t\\t\\tifFalse: [ selector _ self correctSelector: selector contents\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twordIntervals: words\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texprInterval: (start to: self endOfLastToken)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbort: [ ^ self fail ] ].\\n\\t\\t\\tprecedence _ 3]\\n\\t\\tifFalse: [((hereType == #binary or: [hereType == #verticalBar])\\n\\t\\t\\t\\tand: [level >= 2])\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\t\\t\\tselector _ self advance asOctetString asSymbol.\\n\\t\\t\\t\\t\\tself primaryExpression ifFalse: [^self expected: 'Argument'].\\n\\t\\t\\t\\t\\tself messagePart: 1 repeat: true.\\n\\t\\t\\t\\t\\targs _ Array with: parseNode.\\n\\t\\t\\t\\t\\tprecedence _ 2]\\n\\t\\t\\t\\tifFalse: [hereType == #word\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[start _ self startOfNextToken.\\n\\t\\t\\t\\t\\t\\t\\tselector _ self advance.\\n\\t\\t\\t\\t\\t\\t\\targs _ #().\\n\\t\\t\\t\\t\\t\\t\\twords _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset).\\n\\t\\t\\t\\t\\t\\t\\t(Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym])\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [ selector _ self correctSelector: selector\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twordIntervals: words\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\texprInterval: (start to: self endOfLastToken)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbort: [ ^ self fail ] ].\\n\\t\\t\\t\\t\\t\\t\\tprecedence _ 1]\\n\\t\\t\\t\\t\\t\\tifFalse: [^args notNil]]].\\n\\tparseNode _ MessageNode new\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\targuments: args\\n\\t\\t\\t\\tprecedence: precedence\\n\\t\\t\\t\\tfrom: encoder\\n\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken).\\n\\trepeat]\\n\\t\\twhileTrue: [].\\n\\t^true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'lr 7/3/2006 14:37'!\\nmethod: doit context: ctxt encoder: encoderToUse\\n\\t\\\" pattern [ | temporaries ] block => MethodNode.\\\"\\n\\n\\t| sap blk prim temps messageComment methodNode |\\n\\tencoder _ encoderToUse.\\n\\tsap _ self pattern: doit inContext: ctxt.\\n\\t\\\"sap={selector, arguments, precedence}\\\"\\n\\t(sap at: 2) do: [:argNode | argNode isArg: true].\\n\\tdoit ifFalse: [ self pragmaSequence ].\\n\\ttemps _ self temporariesIn: (sap at: 1)..\\n\\tmessageComment _ currentComment.\\n\\tcurrentComment _ nil.\\n\\tdoit ifFalse: [ self pragmaSequence ].\\n\\tprim := self pragmaPrimitives.\\n\\tself statements: #() innerBlock: doit.\\n\\tblk _ parseNode.\\n\\tdoit ifTrue: [blk returnLast]\\n\\t\\tifFalse: [blk returnSelfIfNoOther].\\n\\thereType == #doIt ifFalse: [^self expected: 'Nothing more'].\\n\\tself interactive ifTrue: [self removeUnusedTemps].\\n\\tmethodNode _ self newMethodNode comment: messageComment.\\n\\t^ methodNode\\n\\t\\tselector: (sap at: 1)\\n\\t\\targuments: (sap at: 2)\\n\\t\\tprecedence: (sap at: 3)\\n\\t\\ttemporaries: temps\\n\\t\\tblock: blk\\n\\t\\tencoder: encoder\\n\\t\\tprimitive: prim\\n\\t\\tproperties: properties! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 5/30/2000 21:59'!\\nnewMethodNode\\n\\n\\t^ MethodNode new! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'ar 1/2/2002 14:31'!\\npattern: fromDoit inContext: ctxt \\n\\t\\\" unarySelector | binarySelector arg | keyword arg {keyword arg} => \\n\\t{selector, arguments, precedence}.\\\"\\n\\t| args selector |\\n\\tdoitFlag _ fromDoit.\\n\\tfromDoit ifTrue:\\n\\t\\t\\t[ctxt == nil\\n\\t\\t\\t\\tifTrue: [^ {#DoIt. {}. 1}]\\n\\t\\t\\t\\tifFalse: [^ {#DoItIn:. {encoder encodeVariable: 'homeContext'}. 3}]].\\n\\n\\thereType == #word ifTrue: [^ {self advance asSymbol. {}. 1}].\\n\\n\\t(hereType == #binary or: [hereType == #verticalBar])\\n\\t\\tifTrue: \\n\\t\\t\\t[selector _ self advance asSymbol.\\n\\t\\t\\targs _ Array with: (encoder bindArg: self argumentName).\\n\\t\\t\\t^ {selector. args. 2}].\\n\\n\\thereType == #keyword\\n\\t\\tifTrue: \\n\\t\\t\\t[selector _ WriteStream on: (String new: 32).\\n\\t\\t\\targs _ OrderedCollection new.\\n\\t\\t\\t[hereType == #keyword] whileTrue:[\\n\\t\\t\\t\\tselector nextPutAll: self advance.\\n\\t\\t\\t\\targs addLast: (encoder bindArg: self argumentName).\\n\\t\\t\\t].\\n\\t\\t\\t^ {selector contents asSymbol. args. 3}].\\n\\n\\t^ self expected: 'Message pattern'! !\\n\\n!Parser methodsFor: 'expression types'!\\nprimaryExpression \\n\\thereType == #word \\n\\t\\tifTrue: \\n\\t\\t\\t[parseNode _ self variable.\\n\\t\\t\\t(parseNode isUndefTemp and: [self interactive])\\n\\t\\t\\t\\tifTrue: [self queryUndefined].\\n\\t\\t\\tparseNode nowHasRef.\\n\\t\\t\\t^ true].\\n\\thereType == #leftBracket\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tself blockExpression.\\n\\t\\t\\t^true].\\n\\thereType == #leftBrace\\n\\t\\tifTrue: \\n\\t\\t\\t[self braceExpression.\\n\\t\\t\\t^true].\\n\\thereType == #leftParenthesis\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tself expression ifFalse: [^self expected: 'expression'].\\n\\t\\t\\t(self match: #rightParenthesis)\\n\\t\\t\\t\\tifFalse: [^self expected: 'right parenthesis'].\\n\\t\\t\\t^true].\\n\\t(hereType == #string or: [hereType == #number or: [hereType == #literal]])\\n\\t\\tifTrue: \\n\\t\\t\\t[parseNode _ encoder encodeLiteral: self advance.\\n\\t\\t\\t^true].\\n\\t(here == #- and: [tokenType == #number])\\n\\t\\tifTrue: \\n\\t\\t\\t[self advance.\\n\\t\\t\\tparseNode _ encoder encodeLiteral: self advance negated.\\n\\t\\t\\t^true].\\n\\t^false! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 6/7/2000 08:45'!\\nstatements: argNodes innerBlock: inner\\n\\n\\t| stmts returns start more blockComment |\\n\\tstmts _ OrderedCollection new.\\n\\t\\\"give initial comment to block, since others trail statements\\\"\\n\\tblockComment _ currentComment.\\n\\tcurrentComment _ nil.\\n\\treturns _ false.\\n\\tmore _ hereType ~~ #rightBracket.\\n\\t[more]\\n\\t\\twhileTrue: \\n\\t\\t[start _ self startOfNextToken.\\n\\t\\t(returns _ self matchReturn)\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[self expression\\n\\t\\t\\t\\t\\tifFalse: [^self expected: 'Expression to return'].\\n\\t\\t\\t\\tself addComment.\\n\\t\\t\\t\\tstmts addLast: (parseNode isReturningIf\\n\\t\\t\\t\\t\\tifTrue: [parseNode]\\n\\t\\t\\t\\t\\tifFalse: [ReturnNode new\\n\\t\\t\\t\\t\\t\\t\\texpr: parseNode\\n\\t\\t\\t\\t\\t\\t\\tencoder: encoder\\n\\t\\t\\t\\t\\t\\t\\tsourceRange: (start to: self endOfLastToken)])]\\n\\t\\t\\tifFalse: \\n\\t\\t\\t\\t[self expression\\n\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t[self addComment.\\n\\t\\t\\t\\t\\t\\tstmts addLast: parseNode]\\n\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t[self addComment.\\n\\t\\t\\t\\t\\t\\tstmts size = 0\\n\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t[stmts addLast: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(encoder encodeVariable:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(inner ifTrue: ['nil'] ifFalse: ['self']))]]].\\n\\t\\treturns \\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[self match: #period.\\n\\t\\t\\t\\t(hereType == #rightBracket or: [hereType == #doIt])\\n\\t\\t\\t\\t\\tifFalse: [^self expected: 'End of block']].\\n\\t\\tmore _ returns not and: [self match: #period]].\\n\\tparseNode _ BlockNode new\\n\\t\\t\\t\\targuments: argNodes\\n\\t\\t\\t\\tstatements: stmts\\n\\t\\t\\t\\treturns: returns\\n\\t\\t\\t\\tfrom: encoder.\\n\\tparseNode comment: blockComment.\\n\\t^ true! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'ar 1/4/2002 00:23'!\\ntemporaries\\n\\t\\\" [ '|' (variable)* '|' ]\\\"\\n\\t| vars theActualText |\\n\\t(self match: #verticalBar) ifFalse: \\n\\t\\t[\\\"no temps\\\"\\n\\t\\tdoitFlag ifTrue: [self interactive\\n\\t\\t\\t\\tifFalse: [tempsMark _ 1]\\n\\t\\t\\t\\tifTrue: [tempsMark _ requestor selectionInterval first].\\n\\t\\t\\t^ #()].\\n\\t\\ttempsMark _ (prevEnd ifNil: [0]) + 1.\\n\\t\\ttempsMark _ hereMark\\t\\\"formerly --> prevMark + prevToken\\\".\\n\\n\\t\\ttempsMark > 0 ifTrue:\\n\\t\\t\\t[theActualText _ source contents.\\n\\t\\t\\t[tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]]\\n\\t\\t\\t\\twhileTrue: [tempsMark _ tempsMark + 1]].\\n\\t\\t\\t^ #()].\\n\\tvars _ OrderedCollection new.\\n\\t[hereType == #word]\\n\\t\\twhileTrue: [vars addLast: (encoder bindTemp: self advance)].\\n\\t(self match: #verticalBar) ifTrue: \\n\\t\\t[tempsMark _ prevMark.\\n\\t\\t^ vars].\\n\\t^ self expected: 'Vertical bar'\\n! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'mir 1/17/2004 12:27'!\\ntemporariesIn: methodSelector\\n\\t\\\" [ '|' (variable)* '|' ]\\\"\\n\\t| vars theActualText |\\n\\t(self match: #verticalBar) ifFalse: \\n\\t\\t[\\\"no temps\\\"\\n\\t\\tdoitFlag ifTrue: [requestor\\n\\t\\t\\t\\tifNil: [tempsMark _ 1]\\n\\t\\t\\t\\tifNotNil: [tempsMark _ requestor selectionInterval first].\\n\\t\\t\\t^ #()].\\n\\t\\ttempsMark _ (prevEnd ifNil: [0]) + 1.\\n\\t\\ttempsMark _ hereMark\\t\\\"formerly --> prevMark + prevToken\\\".\\n\\n\\t\\ttempsMark > 0 ifTrue:\\n\\t\\t\\t[theActualText _ source contents.\\n\\t\\t\\t[tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]]\\n\\t\\t\\t\\twhileTrue: [tempsMark _ tempsMark + 1]].\\n\\t\\t\\t^ #()].\\n\\tvars _ OrderedCollection new.\\n\\t[hereType == #word]\\n\\t\\twhileTrue: [vars addLast: (encoder bindTemp: self advance in: methodSelector)].\\n\\t(self match: #verticalBar) ifTrue: \\n\\t\\t[tempsMark _ prevMark.\\n\\t\\t^ vars].\\n\\t^ self expected: 'Vertical bar'! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'crl 2/26/1999 12:22'!\\ntemporaryBlockVariables\\n\\t\\\"Scan and answer temporary block variables.\\\"\\n\\n\\t| variables |\\n\\n\\t(self match: #verticalBar) ifFalse: [\\n\\t\\t\\\"There are't any temporary variables.\\\"\\n\\t\\t^#()].\\n\\n\\tvariables _ OrderedCollection new.\\n\\t[hereType == #word] whileTrue: [variables addLast: (encoder bindBlockTemp: self advance)].\\n\\t(self match: #verticalBar) ifTrue: [^variables].\\n\\t^self expected: 'Vertical bar'! !\\n\\n!Parser methodsFor: 'expression types' stamp: 'di 12/4/1999 21:04'!\\nvariable\\n\\n\\t| varName varStart varEnd |\\n\\tvarStart _ self startOfNextToken + requestorOffset.\\n\\tvarName _ self advance.\\n\\tvarEnd _ self endOfLastToken + requestorOffset.\\n\\t^ encoder encodeVariable: varName\\n\\t\\tsourceRange: (varStart to: varEnd)\\n\\t\\tifUnknown: [self correctVariable: varName interval: (varStart to: varEnd)]! !\\n\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:50'!\\naddPragma: aPragma\\n\\tself properties addPragma: aPragma.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 21:02'!\\npragmaLiteral\\n\\t\\\"Read a pragma literal.\\\"\\n\\n\\t(hereType == #string or: [ hereType == #literal or: [ hereType == #number ] ])\\n\\t\\tifTrue: [ ^ self advance ].\\n\\t(here == $# and: [ tokenType == #word ])\\n\\t\\tifTrue: [ ^ self advance ].\\n\\t(here == #- and: [ tokenType == #number ])\\n\\t\\tifTrue: [ ^ (self advance; advance) negated ].\\n\\t(here = 'true' or: [ here = 'false' or: [ here = 'nil' or: [ Smalltalk hasClassNamed: here ] ] ])\\n\\t\\tifTrue: [ ^ Compiler evaluate: self advance ].\\n\\t^ self expected: 'Literal constant'.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:23'!\\npragmaPrimitives\\n\\t| primitives |\\n\\tprimitives := self properties pragmas select: [ :each | \\n\\t\\t#( primitive: primitive:module: ) \\n\\t\\t\\tincludes: each keyword ].\\n\\tprimitives isEmpty \\n\\t\\tifTrue: [ ^ 0 ].\\n\\tprimitives size = 1 \\n\\t\\tifFalse: [ ^ self notify: 'Ambigous primitives' ].\\n\\t^ primitives first message sendTo: self.! !\\n\\n!Parser methodsFor: 'pragmas' stamp: 'lr 2/6/2006 20:23'!\\npragmaSequence\\n\\t\\\"Parse a sequence of method pragmas.\\\"\\n\\t\\n\\t[ true ] whileTrue: [\\n\\t\\t(self matchToken: #<)\\n\\t\\t\\tifFalse: [ ^ self ].\\n\\t\\tself pragmaStatement.\\n\\t\\t(self matchToken: \";\n r = \"{7689049, 2109470}\";\n s = 1;\n },\n {\n l = \"instance or #class> <selector name>), and with a string to be produced as part of the error msg if any of the methods affected is reached\\\"\\n\\n\\t| aClass sel keywords codeString |\\n\\ttripletList do:\\n\\t\\t[:triplet | \\n\\t\\t\\t(aClass _ (Smalltalk at: triplet first ifAbsent: [nil])) notNil ifTrue:\\n\\t\\t\\t\\t[triplet second == #class ifTrue:\\n\\t\\t\\t\\t\\t[aClass _ aClass class].\\n\\t\\t\\t\\tsel _ triplet third.\\n\\t\\t\\t\\tkeywords _ sel keywords.\\n\\t\\t\\t\\t(keywords size == 1 and: [keywords first asSymbol isKeyword not])\\n\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t[codeString _ keywords first asString]\\n\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t[codeString _ ''.\\n\\t\\t\\t\\t\\t\\tkeywords withIndexDo:\\n\\t\\t\\t\\t\\t\\t\\t[:kwd :index |\\n\\t\\t\\t\\t\\t\\t\\t\\tcodeString _ codeString, ' ', (keywords at: index), ' ',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t'arg', index printString]].\\n\\t\\t\\t\\tcodeString _ codeString, '\\n\\tself codeStrippedOut: ', (messageString surroundedBySingleQuotes).\\n\\n\\t\\t\\t\\taClass compile: codeString classified: 'stripped']]! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nextraVMMemory\\n\\t\\\"Answer the current setting of the 'extraVMMemory' VM parameter. See the comment in extraVMMemory: for details.\\\"\\n\\n\\t^ self vmParameterAt: 23\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nextraVMMemory: extraBytesToReserve\\n\\t\\\"Request that the given amount of extra memory be reserved for use by the virtual machine to leave extra C heap space available for things like plugins, network and file buffers, and so on. This request is stored when the image is saved and honored when the image is next started up. Answer the previous value of this parameter.\\\"\\n\\n\\textraBytesToReserve < 0\\n\\t\\tifTrue: [self error: 'VM memory reservation must be non-negative'].\\n\\t^ self vmParameterAt: 23 put: extraBytesToReserve\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:47'!\\ngetVMParameters\\t\\n\\t\\\"Answer an Array containing the current values of the VM's internal\\n\\tparameter/metric registers. Each value is stored in the array at the\\n\\tindex corresponding to its VM register. (See #vmParameterAt: and\\n\\t#vmParameterAt:put:.)\\\"\\n\\t\\\"SmalltalkImage current getVMParameters\\\"\\n\\t\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'tpr 4/27/2005 11:03'!\\nvmParameterAt: parameterIndex\\n\\t\\\"parameterIndex is a positive integer corresponding to one of the VM's internal\\n\\tparameter/metric registers. Answer with the current value of that register.\\n\\tFail if parameterIndex has no corresponding register.\\n\\tVM parameters are numbered as follows:\\n\\t\\t1\\tend of old-space (0-based, read-only)\\n\\t\\t2\\tend of young-space (read-only)\\n\\t\\t3\\tend of memory (read-only)\\n\\t\\t4\\tallocationCount (read-only)\\n\\t\\t5\\tallocations between GCs (read-write)\\n\\t\\t6\\tsurvivor count tenuring threshold (read-write)\\n\\t\\t7\\tfull GCs since startup (read-only)\\n\\t\\t8\\ttotal milliseconds in full GCs since startup (read-only)\\n\\t\\t9\\tincremental GCs since startup (read-only)\\n\\t\\t10\\ttotal milliseconds in incremental GCs since startup (read-only)\\n\\t\\t11\\ttenures of surving objects since startup (read-only)\\n\\t\\t12-20 specific to the translating VM\\n\\t\\t21\\troot table size (read-only)\\n\\t\\t22\\troot table overflows since startup (read-only)\\n\\t\\t23\\tbytes of extra memory to reserve for VM buffers, plugins, etc.\\n\\n\\t\\t24\\tmemory threshold above which shrinking object memory (rw)\\n\\t\\t25\\tmemory headroom when growing object memory (rw)\\n\\t\\t26 interruptChecksEveryNms - force an ioProcessEvents every N milliseconds, in case the image is not calling getNextEvent often (rw)\\n\\t\\t27\\tnumber of times mark loop iterated for current IGC/FGC (read-only) includes ALL marking\\n\\t\\t28\\tnumber of times sweep loop iterated for current IGC/FGC (read-only)\\n\\t\\t29\\tnumber of times make forward loop iterated for current IGC/FGC (read-only)\\n\\t\\t30\\tnumber of times compact move loop iterated for current IGC/FGC (read-only)\\n\\t\\t31\\tnumber of grow memory requests (read-only)\\n\\t\\t32\\tnumber of shrink memory requests (read-only)\\n\\t\\t33\\tnumber of root table entries used for current IGC/FGC (read-only)\\n\\t\\t34\\tnumber of allocations done before current IGC/FGC (read-only)\\n\\t\\t35\\tnumber of survivor objects after current IGC/FGC (read-only)\\n\\t\\t36 millisecond clock when current IGC/FGC completed (read-only)\\n\\t\\t37 number of marked objects for Roots of the world, not including Root Table entries for current IGC/FGC (read-only)\\n\\t\\t38 milliseconds taken by current IGC (read-only)\\n\\t\\t39 Number of finalization signals for Weak Objects pending when current IGC/FGC completed (read-only)\\n\\t\\t40 VM word size - 4 or 8 (read-only)\\\"\\n\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n!SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'!\\nvmParameterAt: parameterIndex put: newValue\\n\\t\\\"parameterIndex is a positive integer corresponding to one of the VM's internal\\n\\tparameter/metric registers. Store newValue (a positive integer) into that\\n\\tregister and answer with the previous value that was stored there.\\n\\tFail if newValue is out of range, if parameterIndex has no corresponding\\n\\tregister, or if the corresponding register is read-only.\\\"\\n\\n\\t<primitive: 254>\\n\\tself primitiveFailed! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\nclearProfile\\n\\t\\\"Clear the profile database.\\\"\\n\\n\\t<primitive: 250>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\ndumpProfile\\n\\t\\\"Dump the profile database to a file.\\\"\\n\\n\\t<primitive: 251>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:54'!\\nprofile: aBlock\\n\\t\\\"Make a virtual machine profile of the given block.\\\"\\n\\t\\\"Note: Profiling support is provided so that VM implementors\\n\\t can better understand and improve the efficiency of the virtual\\n\\t machine. To use it, you must be running a version of the\\n\\t virtual machine compiled with profiling enabled (which\\n\\t makes it much slower than normal even when not profiling).\\n\\t You will also need the CodeWarrior profile reader application.\\\"\\n\\n\\tself stopProfiling.\\n\\tself clearProfile.\\n\\tself startProfiling.\\n\\taBlock value.\\n\\tself stopProfiling.\\n\\tself dumpProfile.! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:55'!\\nstartProfiling\\n\\t\\\"Start profiling the virtual machine.\\\"\\n\\n\\t<primitive: 252>\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm profiling' stamp: 'sd 9/24/2003 11:55'!\\nstopProfiling\\n\\t\\\"Stop profiling the virtual machine.\\\"\\n\\n\\t<primitive: 253>\\n! !\\n\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 7/2/2003 21:45'!\\ntextMarkerForShortReport\\n\\n\\t^ 'Since last view\\t'! !\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 9/30/2003 13:53'!\\nvmStatisticsReportString\\n\\t\\\"StringHolderView open: (StringHolder new contents:\\n\\t\\tSmalltalkImage current vmStatisticsReportString) label: 'VM Statistics'\\\"\\n\\n\\t| params oldSpaceEnd youngSpaceEnd memoryEnd fullGCs fullGCTime incrGCs incrGCTime tenureCount mcMisses mcHits icHits upTime sendCount tms tmSize upTime2 fullGCs2 fullGCTime2 incrGCs2 incrGCTime2 tenureCount2 str |\\n\\tparams _ self getVMParameters.\\n\\toldSpaceEnd\\t\\t\\t_ params at: 1.\\n\\tyoungSpaceEnd\\t\\t_ params at: 2.\\n\\tmemoryEnd\\t\\t\\t_ params at: 3.\\n\\tfullGCs\\t\\t\\t\\t_ params at: 7.\\n\\tfullGCTime\\t\\t\\t_ params at: 8.\\n\\tincrGCs\\t\\t\\t\\t_ params at: 9.\\n\\tincrGCTime\\t\\t\\t_ params at: 10.\\n\\ttenureCount\\t\\t\\t_ params at: 11.\\n\\tmcMisses\\t\\t\\t_ params at: 15.\\n\\tmcHits\\t\\t\\t\\t_ params at: 16.\\n\\ticHits\\t\\t\\t\\t_ params at: 17.\\n\\tupTime _ Time millisecondClockValue.\\n\\tsendCount _ mcMisses + mcHits + icHits.\\n\\ttms _ TranslatedMethod allSubInstances.\\n\\ttmSize _ tms inject: 0 into: [:sum :tm | sum + (tm size * 4)].\\n\\n\\tstr _ WriteStream on: (String new: 1000).\\n\\tstr\\tnextPutAll: 'uptime\\t\\t\\t';\\n\\t\\tprint: (upTime / 1000 / 60 // 60); nextPut: $h;\\n\\t\\tprint: (upTime / 1000 / 60 \\\\\\\\ 60) asInteger; nextPut: $m;\\n\\t\\tprint: (upTime / 1000 \\\\\\\\ 60) asInteger; nextPut: $s; cr.\\n\\n\\tstr\\tnextPutAll: 'memory\\t\\t\\t';\\n\\t\\tnextPutAll: memoryEnd asStringWithCommas; nextPutAll: ' bytes'; cr.\\n\\tstr\\tnextPutAll:\\t'\\told\\t\\t\\t';\\n\\t\\tnextPutAll: oldSpaceEnd asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tyoung\\t\\t';\\n\\t\\tnextPutAll: (youngSpaceEnd - oldSpaceEnd) asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((youngSpaceEnd - oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tused\\t\\t';\\n\\t\\tnextPutAll: youngSpaceEnd asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\tstr\\tnextPutAll: '\\tfree\\t\\t';\\n\\t\\tnextPutAll: (memoryEnd - youngSpaceEnd) asStringWithCommas; nextPutAll: ' bytes (';\\n\\t\\tprint: ((memoryEnd - youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\n\\tstr\\tnextPutAll: 'GCs\\t\\t\\t\\t';\\n\\t\\tnextPutAll: (fullGCs + incrGCs) asStringWithCommas.\\n\\tfullGCs + incrGCs > 0 ifTrue: [\\n\\t\\tstr\\n\\t\\t\\tnextPutAll: ' ('; \\n\\t\\t\\tprint: ((upTime / (fullGCs + incrGCs)) roundTo: 1); \\n\\t\\t\\tnextPutAll: 'ms between GCs)'\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\tprint: fullGCs; nextPutAll: ' totalling '; nextPutAll: fullGCTime asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((fullGCTime / upTime * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime)'.\\n\\tfullGCs = 0 ifFalse:\\n\\t\\t[str\\tnextPutAll: ', avg '; print: ((fullGCTime / fullGCs) roundTo: 1.0); nextPutAll: 'ms'].\\n\\tstr\\tcr.\\n\\tstr\\tnextPutAll: '\\tincr\\t\\t';\\n\\t\\tprint: incrGCs; nextPutAll: ' totalling '; nextPutAll: incrGCTime asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((incrGCTime / upTime * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime), avg '; print: ((incrGCTime / incrGCs) roundTo: 1.0); nextPutAll: 'ms'; cr.\\n\\tstr\\tnextPutAll: '\\ttenures\\t\\t';\\n\\t\\tnextPutAll: tenureCount asStringWithCommas.\\n\\ttenureCount = 0 ifFalse:\\n\\t\\t[str nextPutAll: ' (avg '; print: (incrGCs / tenureCount) asInteger; nextPutAll: ' GCs/tenure)'].\\n\\tstr\\tcr.\\n\\nLastStats ifNil: [LastStats _ Array new: 6]\\nifNotNil: [\\n\\tupTime2 _ upTime - (LastStats at: 1).\\n\\tfullGCs2 _ fullGCs - (LastStats at: 2).\\n\\tfullGCTime2 _ fullGCTime - (LastStats at: 3).\\n\\tincrGCs2 _ incrGCs - (LastStats at: 4).\\n\\tincrGCTime2 _ incrGCTime - (LastStats at: 5).\\n\\ttenureCount2 _ tenureCount - (LastStats at: 6).\\n\\n\\tstr\\tnextPutAll: self textMarkerForShortReport ;\\n\\t\\tnextPutAll: (fullGCs2 + incrGCs2) asStringWithCommas.\\n\\tfullGCs2 + incrGCs2 > 0 ifTrue: [\\n\\t\\tstr\\n\\t\\t\\tnextPutAll: ' ('; \\n\\t\\t\\tprint: ((upTime2 / (fullGCs2 + incrGCs2)) roundTo: 1); \\n\\t\\t\\tnextPutAll: 'ms between GCs)'.\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\tuptime\\t\\t'; print: ((upTime2 / 1000.0) roundTo: 0.1); nextPutAll: 's'; cr.\\n\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\tprint: fullGCs2; nextPutAll: ' totalling '; nextPutAll: fullGCTime2 asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((fullGCTime2 / upTime2 * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime)'.\\n\\tfullGCs2 = 0 ifFalse:\\n\\t\\t[str\\tnextPutAll: ', avg '; print: ((fullGCTime2 / fullGCs2) roundTo: 1.0); nextPutAll: 'ms'].\\n\\tstr\\tcr.\\n\\tstr\\tnextPutAll: '\\tincr\\t\\t';\\n\\t\\tprint: incrGCs2; nextPutAll: ' totalling '; nextPutAll: incrGCTime2 asStringWithCommas; nextPutAll: 'ms (';\\n\\t\\tprint: ((incrGCTime2 / upTime2 * 100) roundTo: 1.0);\\n\\t\\tnextPutAll: '% uptime), avg '.\\n\\tincrGCs2 > 0 ifTrue: [\\n\\t\\t str print: ((incrGCTime2 / incrGCs2) roundTo: 1.0); nextPutAll: 'ms'\\n\\t].\\n\\tstr cr.\\n\\tstr\\tnextPutAll: '\\ttenures\\t\\t';\\n\\t\\tnextPutAll: tenureCount2 asStringWithCommas.\\n\\ttenureCount2 = 0 ifFalse:\\n\\t\\t[str nextPutAll: ' (avg '; print: (incrGCs2 / tenureCount2) asInteger; nextPutAll: ' GCs/tenure)'].\\n\\tstr\\tcr.\\n].\\n\\tLastStats at: 1 put: upTime.\\n\\tLastStats at: 2 put: fullGCs.\\n\\tLastStats at: 3 put: fullGCTime.\\n\\tLastStats at: 4 put: incrGCs.\\n\\tLastStats at: 5 put: incrGCTime.\\n\\tLastStats at: 6 put: tenureCount.\\n\\n\\tsendCount > 0 ifTrue: [\\n\\t\\tstr\\tnextPutAll: 'sends\\t\\t\\t';\\n\\t\\t\\tnextPutAll: sendCount asStringWithCommas; cr.\\n\\t\\tstr\\tnextPutAll: '\\tfull\\t\\t\\t';\\n\\t\\t\\tnextPutAll: mcMisses asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((mcMisses / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tm-cache\\t';\\n\\t\\t\\tnextPutAll: mcHits asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((mcHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr.\\n\\t\\tstr\\tnextPutAll: '\\ti-cache\\t\\t';\\n\\t\\t\\tnextPutAll: icHits asStringWithCommas;\\n\\t\\t\\tnextPutAll: ' ('; print: ((icHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr].\\n\\n\\ticHits > 0 ifTrue: [\\n\\t\\tstr\\tnextPutAll: 'methods\\t\\t\\t';\\n\\t\\t\\tnextPutAll: tms size asStringWithCommas; nextPutAll: ' translated'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tsize\\t\\t\\t';\\n\\t\\t\\tnextPutAll: tmSize asStringWithCommas; nextPutAll: ' bytes, avg ';\\n\\t\\t\\tprint: ((tmSize / tms size) roundTo: 0.1); nextPutAll: ' bytes/method'; cr.\\n\\t\\tstr\\tnextPutAll: '\\tmemory\\t\\t';\\n\\t\\t\\tprint: ((tmSize / youngSpaceEnd * 100) roundTo: 0.1); nextPutAll: '% of used, ';\\n\\t\\t\\tprint: ((tmSize / memoryEnd * 100) roundTo: 0.1); nextPutAll: '% of available'; cr].\\n\\n\\t^ str contents\\n! !\\n\\n!SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 9/30/2003 13:54'!\\nvmStatisticsShortString\\n\\t\\\"Convenience item for access to recent statistics only\\\"\\n\\t\\\"StringHolderView open: (StringHolder new contents: SmalltalkImage current vmStatisticsShortString)\\n\\t\\tlabel: 'VM Recent Statistics'\\\"\\n\\n\\t^ (ReadStream on: self vmStatisticsReportString) upToAll: 'Since'; upTo: Character cr; upToEnd\\n! !\\n\\n\\n!SmalltalkImage methodsFor: 'private source file' stamp: 'sd 9/24/2003 12:42'!\\nsourceFileVersionString: aString\\n\\n\\tSourceFileVersionString := aString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSmalltalkImage class\\n\\tinstanceVariableNames: 'current'!\\n\\n!SmalltalkImage class methodsFor: 'class initialization' stamp: 'yo 2/18/2004 18:26'!\\ninitialize\\n\\\"\\n\\tself initialize\\n\\\"\\n\\tSmalltalk addToStartUpList: SmalltalkImage.\\n\\tSmalltalkImage startUp.\\n! !\\n\\n!SmalltalkImage class methodsFor: 'class initialization' stamp: 'yo 2/18/2004 18:25'!\\nstartUp\\n\\n\\tEndianCache _ nil.\\n! !\\n\\n\\n!SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 14:28'!\\ncurrent\\n\\t\\\"Note that this could be implemented differently to avoid the test\\\"\\n\\n\\tcurrent isNil\\n\\t\\tifTrue: [current := self basicNew].\\n\\t^ current! !\\n\\n!SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 13:39'!\\nnew\\n\\n\\tself error: 'Use current'.! !\\nReferenceStream subclass: #SmartRefStream\\n\\tinstanceVariableNames: 'structures steady reshaped renamed renamedConv superclasses progressBar objCount classInstVars'\\n\\tclassVariableNames: 'ScannedObject'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Object Storage'!\\n!SmartRefStream commentStamp: '<historical>' prior: 0!\\nOrdinary ReferenceStreams assume that the names and order of instance variables is exactly the same when an object file is written and read. \\n\\tSmartRefStream allows object files to be read even after instance variables have changed or the entire class has been renamed.\\n\\nWhen an object file is written, no one knows how the classes will change in the future. Therefore, all conversion must be done when the file is read. The key is to store enough information in the file about the names of the instance variables of all outgoing classes. \\n\\nSmartRefStream works best with only one tree of objects per file. You can nextPut: more than once, but each object tree gets its own class structure description, which is big. \\n\\nConversion of old objects is done by a method in each class called (convertToCurrentVersion: varDict refStream: smartRefStrm). At fileOut time, ChangeSet>>checkForConversionMethods creates a prototype of this method (if Preference #conversionMethodsAtFileOut is true). The programmer must edit this method to (1) test if the incoming object needs conversion, (2) put non-nil values into any new inst vars that need them, and (3) save the data of any inst vars that are being deleted. \\n\\nDetermining which old version is represented by the incoming object can be done in several ways: noticing that a current inst var is nil when it should have data, noticing that there is an older inst var name in the variable dictionary (varDict), checking kinds of objects in one or more inst vars, or retrieving the classVersion of the incoming object from the ref stream. \\n\\nIf a class is renamed, a method goes into SmartRefStream telling the new name. The conversion method of the new class must be prepared to accept instances of the old class also. If no inst var names have changed, the conversion method does nothing.\\n\\nAn example: \\n\\tSuppose we change the representation of class Rectangle from ('origin' 'corner') to ('origin' 'extent'). Suppose lots of Rectangle instances are already out on files (in .pr project files, especially). \\n\\tThe programmer changes the class definition, modifies all the methods, and filesOut. A series of dialogs appear, asking if instances Rectangle might be in an object file, if 'extent' needs to be non-nil (yes), and if the info in 'corner' needs to be preserved (yes). This method appears:\\n\\nRectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\\"These variables are automatically stored into the new instance: #('origin').\\n\\tTest for this particular conversion. Get values using expressions like (varDict at: 'foo').\\\"\\n\\n\\t\\\"New variables: #('extent'). If a non-nil value is needed, please assign it.\\\"\\n\\t\\\"These are going away #('corner'). Possibly store their info in some other variable?\\\"\\n\\t\\\"Move your code above the ^ super... Delete extra comments.\\\"\\n\\t^ super convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\nThe programmer modifies it to be:\\n\\nRectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n(varDict includesKey: 'extent') ifFalse: [\\\"old version!!\\\"\\n\\t\\\"Create the new extent, and preserve the info from the old corner\\\"\\n\\textent _ (varDict at: 'corner') - origin.\\n\\t].\\n^ super convertToCurrentVersion: varDict refStream: smartRefStrm\\n\\n\\tThis conversion method stays in the system and is ready to convert the old format of Rectangle whenever one is encountered in an object file. Note that the subclasses of Rectangle, (B3DViewport, CharacterBlock, and Quadrangle) do not need conversion methods. Their instances will be converted by the code in Rectangle. \\n\\n\\tFiles written by SmartRefStream are in standard fileout format. You can mix raw objects with code to be filed in. The file starts out in the normal fileOut format. Definitions of new classes on the front.\\n\\nstructures \\tDictionary of (#Rectangle -> #(<classVersionInteger> 'origin' 'corner')). Inst \\n\\t\\t\\t\\tvar names are strings.\\nsteady \\t\\tSet of Classes who have the same structure now as on the incoming file.\\n\\t\\t\\t\\tIncludes classes with same inst vars except for new ones added on the end.\\nreshaped \\tDictionary of Classes who have a different structure now from the incoming file. \\n\\t\\t\\t\\tIncludes those with same inst vars but new version number.\\n\\t\\t\\t\\t(old class name -> method selector to fill in data for version to version)\\nrenamed\\tDictionary of Classes who have a different name. Make an instance of the new\\n\\t\\t\\tclass, and send it the conversion call.\\n\\t\\t\\t\\t(old class name symbol -> new class name). \\nrenamedConv\\tDictionary of conversion selector for Classes who have a different name.\\n\\t\\t\\t\\t(old class name symbol -> conversion selector). \\ntopCall\\t\\tTells if next or nextPut: are working on the top object in the tree. \\n\\t\\t\\tnil if outside, the top object if deep inside.\\n\\nSee DataStream.typeIDFor: for where the tangle of objects is clipped, so the whole system will not be written on the file.\\n\\nNo object that is written on the file is ever a class. All class definitions are filed in. A class may be stored inside an ImageSegment that itself is stored in a SmartRefStream.\\n\\nUniClasses are classes for the instance specific behavior of just one instance. Subclasses of Player are an example. When a UniClass is read in, and a class of the same name already exists, the incoming one is renamed. ObjectScanner converts the filed-in code.\\n\\nValues in instance variables of UniClasses are stored in the array that tells the class structure. It is the fourth of the four top level objects. #(version (class-structure) the-object ((#Player25 scripts slotInfo costumeDictionary) (#Player26 scripts slotInfo costumeDictionary))).\\n\\nThere is a separate subclass for doing veryDeepCopy (in memory). Currently, any object for which objectToStoreOnDataStream return an object other than self, does this: The new object (a DiskProxy) is traced. When it comes time to go through the fields of the old object, they are not found as keys in references (DiskProxies are there instead). So the old field value is left in the new object. That is OK for StrikeFont, Class, MetaClass, DisplayScreen. But the DiskProxies are evaluated, which takes a lot of time.\\n\\nSome metaclasses are put into the structures table. This is for when a block has a receiver that is a class. See checkFatalReshape:.\\n\\nImageSegments:\\n\\tA ReferenceStream is used to enumerate objects to put inside an ImageSegment. If an instance of a UniClass is seen, the class is put in also.\\n\\tA SmartRefStream is used to store the ImageSegment. Roots are nil, and the segment is a wordArray. We are encoding the outPointers. Structures contains all classes from both places. Must filter out UniClasses for some things, and do include them for putting source code at end of file. Do not write any class inst vars in file.\\n\\n--Ted Kaehler and Bob Arning.\\n!\\n\\n\\n!SmartRefStream methodsFor: 'accessing' stamp: 'tk 5/19/1999 15:47'!\\nstructures: anObject\\n\\tstructures _ anObject! !\\n\\n!SmartRefStream methodsFor: 'accessing' stamp: 'tk 5/19/1999 15:47'!\\nsuperclasses: anObject\\n\\tsuperclasses _ anObject! !\\n\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 1/7/97'!\\ncatalogValues: instVarList size: varsOnDisk\\n\\t\\\"Create a dictionary of (name -> value) for the inst vars of this reshaped object. Indexed vars as (1 -> val) etc. \\\"\\n\\n\\t| dict sz |\\n\\tdict _ Dictionary new.\\n\\t2 to: instVarList size do: [:ind |\\n\\t\\tdict at: (instVarList at: ind) put: self next].\\n\\tsz _ varsOnDisk - (instVarList size - 1).\\n\\t1 to: sz do: [:ii | \\n\\t\\tdict at: ii put: self next].\\n\\t\\\"Total number read MUST be equal to varsOnDisk!!\\\"\\n\\tsz > 0 ifTrue: [dict at: #SizeOfVariablePart put: sz].\\n\\t^ dict! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'ar 9/27/2005 22:41'!\\nconversionMethodsFor: classList\\n\\t| oldStruct newStruct list |\\n\\t\\\"Each of these needs a conversion method. Hard part is the comment in it. Return a MessageSet.\\\"\\n\\n\\tlist _ OrderedCollection new.\\n\\tclassList do: [:cls |\\n\\t\\toldStruct _ structures at: cls name ifAbsent: [#()].\\n\\t\\tnewStruct _ (Array with: cls classVersion), (cls allInstVarNames).\\n\\t\\tself writeConversionMethodIn: cls fromInstVars: oldStruct to: newStruct \\n\\t\\t\\t\\trenamedFrom: nil.\\n\\t\\tlist add: cls name, ' convertToCurrentVersion:refStream:'.\\n\\t\\t].\\n\\n\\t^list.! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 5/26/97'!\\nstoreInstVarsIn: anObject from: dict\\n\\t\\\"For instance variables with the same names, store them in the new instance. Values in variable-length part also. This is NOT the normal inst var transfer!! See Object.readDataFrom:size:. This is for when inst var names have changed and some additional conversion is needed. Here we handle the unchanged vars. \\\"\\n\\n\\t(anObject class allInstVarNames) doWithIndex: [:varName :index |\\n\\t\\t(dict includesKey: varName) ifTrue: [\\n\\t\\t\\tanObject instVarAt: index put: (dict at: varName)]].\\n\\t\\\"variable part\\\"\\n\\t(dict includesKey: #SizeOfVariablePart) ifFalse: [^ anObject].\\n\\t1 to: (dict at: #SizeOfVariablePart) do: [:index | \\n\\t\\tanObject basicAt: index put: (dict at: index)].\\n\\t^ anObject! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 6/8/2001 09:57'!\\nwriteClassRename: newName was: oldName\\n\\t\\\"Write a method that tells which modern class to map instances to.\\\"\\n\\t| oldVer sel code |\\n\\n\\toldVer _ self versionSymbol: (structures at: oldName).\\n\\tsel _ oldName asString.\\n\\tsel at: 1 put: (sel at: 1) asLowercase.\\n\\tsel _ sel, oldVer.\\t\\\"i.e. #rectangleoc4\\\"\\n\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode nextPutAll: sel; cr.\\n\\tcode cr; tab; nextPutAll: '^ ', newName.\\t\\\"Return new class\\\"\\n\\n\\tself class compile: code contents classified: 'conversion'.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'CdG 10/17/2005 21:01'!\\nwriteClassRenameMethod: sel was: oldName fromInstVars: oldList\\n\\t\\\"The class coming is unknown. Ask the user for the existing class it maps to. If got one, write a method, and restart the obj fileIn. If none, write a dummy method and get the user to complete it later. \\\"\\n\\n| tell choice newName answ code |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\ntell := 'Reading an instance of ', oldName, '.\\nWhich modern class should it translate to?'.\\nansw := (UIManager default \\n\\t\\tchooseFrom: #('Let me type the name now' 'Let me think about it'\\n'Let me find a conversion file on the disk') \\n\\t\\ttitle: tell). \\n\\nansw = 1 ifTrue: [\\n\\ttell := 'Name of the modern class {1} should translate to:' translated format: {oldName}.\\n\\tchoice := UIManager default request: tell.\\t\\t\\\"class name\\\"\\n\\t(choice size = 0) \\n\\t\\tifTrue: [answ := 'conversion method needed']\\n\\t\\tifFalse: [newName := choice.\\n\\t\\t\\tansw := Smalltalk at: newName asSymbol \\n\\t\\t\\t\\tifAbsent: ['conversion method needed'].\\n\\t\\t\\tansw isString ifFalse: [renamed at: oldName asSymbol put: answ name]]].\\n(answ = 3) | (answ = 0) ifTrue: [self close.\\n\\t\\t^ 'conversion method needed'].\\nansw = 2 ifTrue: [answ := 'conversion method needed'].\\nansw = 'conversion method needed' ifTrue: [\\n\\t\\tself close. \\n\\t\\tnewName := 'PutNewClassHere'].\\n\\ncode := WriteStream on: (String new: 500).\\ncode nextPutAll: sel; cr.\\ncode cr; tab; nextPutAll: '^ ', newName.\\t\\\"Return new class\\\"\\n\\nself class compile: code contents classified: 'conversion'.\\n\\nnewName = 'PutNewClassHere' ifTrue: [\\n\\tself inform: 'Please complete the following method and \\nthen read-in the object file again.'.\\n\\tSystemNavigation default browseAllImplementorsOf: sel asSymbol]. \\n\\n\\t\\\"The class version number only needs to change under one specific circumstance. That is when the first letters of the instance variables have stayed the same, but their meaning has changed. A conversion method is needed, but this system does not know it. \\n\\tIf this is true for class Foo, define classVersion in Foo class. \\n\\tBeware of previous object fileouts already written after the change in meaning, but before bumping the version number. They have the old (wrong) version number, say 2. If this is true, your method must be able to test the data and successfully read files that say version 2 but are really 3.\\\"\\n\\n\\t^ answ! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'tk 6/7/2001 13:02'!\\nwriteConversionMethod: sel class: newClass was: oldName fromInstVars: oldList to: newList\\n\\t\\\"The method convertToCurrentVersion:refStream: was not found in newClass. Write a default conversion method for the author to modify.\\\"\\n\\n\\t| code newOthers oldOthers copied |\\n\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode nextPutAll: 'convertToCurrentVersion: varDict refStream: smartRefStrm'; cr; tab.\\n\\tnewOthers _ newList asOrderedCollection \\\"copy\\\".\\n\\toldOthers _ oldList asOrderedCollection \\\"copy\\\".\\n\\tcopied _ OrderedCollection new.\\n\\tnewList do: [:instVar |\\n\\t\\t(oldList includes: instVar) ifTrue: [\\n\\t\\t\\tinstVar isInteger ifFalse: [copied add: instVar].\\n\\t\\t\\tnewOthers remove: instVar.\\n\\t\\t\\toldOthers remove: instVar]].\\n\\tcode nextPutAll: '\\\"These variables are automatically stored into the new instance '.\\n\\tcode nextPutAll: copied asArray printString; nextPut: $. .\\n\\tcode cr; tab; nextPutAll: 'This method is for additional changes.'; \\n\\t\\tnextPutAll: ' Use statements like (foo _ varDict at: ''foo'').\\\"'; cr; cr; tab.\\n\\t(newOthers size = 0) & (oldOthers size = 0) ifTrue: [^ self].\\n\\t\\t\\\"Instance variables are the same. Only the order changed. No conversion needed.\\\"\\n\\t(newOthers size > 0) ifTrue: [code nextPutAll: '\\\"New variables: ', newOthers asArray printString, ' If a non-nil value is needed, please assign it.\\\"\\\\' withCRs].\\n\\t(oldOthers size > 0) ifTrue: [code nextPutAll: '\\t\\\"These are going away ', oldOthers asArray printString, '. Possibly store their info in some other variable?\\\"'].\\n\\n\\tcode cr; tab.\\n\\tcode nextPutAll: '^ super convertToCurrentVersion: varDict refStream: smartRefStrm'.\\n\\tnewClass compile: code contents classified: 'object fileIn'.\\n\\n\\n\\t\\\"If you write a conversion method beware that the class may need a version number change. This only happens when two conversion methods in the same class have the same selector name. (A) The inst var lists of the new and old versions intials as some older set of new and old inst var lists. or (B) Twice in a row, the class needs a conversion method, but the inst vars stay the same the whole time. (For an internal format change.)\\n\\tIf either is the case, fileouts already written with the old (wrong) version number, say 2. Your method must be able to read files that say version 2 but are really 3, until you expunge the erroneous version 2 files from the universe.\\\"\\n\\n ! !\\n\\n!SmartRefStream methodsFor: 'class changed shape' stamp: 'nk 7/29/2004 10:10'!\\nwriteConversionMethodIn: newClass fromInstVars: oldList to: newList renamedFrom: oldName\\n\\t\\\"The method convertToCurrentVersion:refStream: was not found in newClass. Write a default conversion method for the author to modify. If method exists, append new info into the end.\\\"\\n\\n\\t| code newOthers oldOthers copied newCode |\\n\\n\\tnewOthers _ newList asOrderedCollection \\\"copy\\\".\\n\\toldOthers _ oldList asOrderedCollection \\\"copy\\\".\\n\\tcopied _ OrderedCollection new.\\n\\tnewList do: [:instVar |\\n\\t\\t(oldList includes: instVar) ifTrue: [\\n\\t\\t\\tinstVar isInteger ifFalse: [copied add: instVar].\\n\\t\\t\\tnewOthers remove: instVar.\\n\\t\\t\\toldOthers remove: instVar]].\\n\\tcode _ WriteStream on: (String new: 500).\\n\\tcode cr; cr; tab; nextPutAll: '\\\"From ', SystemVersion current version, ' [', SmalltalkImage current lastUpdateString;\\n\\t\\t\\tnextPutAll: '] on ', Date today printString, '\\\"'; cr.\\n\\tcode tab; nextPutAll: '\\\"These variables are automatically stored into the new instance: '.\\n\\tcode nextPutAll: copied asArray printString; nextPut: $.; cr.\\n\\tcode tab; nextPutAll: 'Test for this particular conversion.'; \\n\\t\\tnextPutAll: ' Get values using expressions like (varDict at: ''foo'').\\\"'; cr; cr.\\n\\t(newOthers size = 0) & (oldOthers size = 0) & (oldName == nil) ifTrue: [^ self].\\n\\t\\t\\\"Instance variables are the same. Only the order changed. No conversion needed.\\\"\\n\\t(newOthers size > 0) ifTrue: [\\n\\t\\tcode tab; nextPutAll: '\\\"New variables: ', newOthers asArray printString, \\n\\t\\t\\t'. If a non-nil value is needed, please assign it.\\\"'; cr].\\n\\t(oldOthers size > 0) ifTrue: [\\n\\t\\tcode tab; nextPutAll: '\\\"These are going away ', oldOthers asArray printString, \\n\\t\\t\\t'. Possibly store their info in some other variable?\\\"'; cr].\\n\\toldName ifNotNil: [\\n\\t\\tcode tab; nextPutAll: '\\\"Test for instances of class ', oldName, '.'; cr.\\n\\t\\tcode tab; nextPutAll: 'Instance vars with the same name have been moved here.\\\"'; cr.\\n\\t\\t].\\n\\tcode tab; nextPutAll: '\\\"Move your code above the ^ super... Delete extra comments.\\\"'; cr. \\n\\n\\t(newClass includesSelector: #convertToCurrentVersion:refStream:) \\n\\t\\tifTrue: [\\\"append to old methods\\\"\\n\\t\\t\\tnewCode _ (newClass sourceCodeAt: #convertToCurrentVersion:refStream:),\\n\\t\\t\\t\\tcode contents]\\n\\t\\tifFalse: [\\\"new method\\\"\\n\\t\\t\\tnewCode _ 'convertToCurrentVersion: varDict refStream: smartRefStrm',\\n\\t\\t\\t\\tcode contents, \\n\\t\\t\\t\\t'\\t^ super convertToCurrentVersion: varDict refStream: smartRefStrm'].\\n\\tnewClass compile: newCode classified: 'object fileIn'.\\n\\n\\n\\t\\\"If you write a conversion method beware that the class may need a version number change. This only happens when two conversion methods in the same class have the same selector name. (A) The inst var lists of the new and old versions intials as some older set of new and old inst var lists. or (B) Twice in a row, the class needs a conversion method, but the inst vars stay the same the whole time. (For an internal format change.)\\n\\tIf either is the case, fileouts already written with the old (wrong) version number, say 2. Your method must be able to read files that say version 2 but are really 3, until you expunge the erroneous version 2 files from the universe.\\\"\\n\\n ! !\\n\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/10/2005 15:44'!\\nabstractStringx0\\n\\n\\t^ String! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 7/29/2005 18:41'!\\nalansTextPlusMorphbosfcebbmsopssrsggshtt0\\n\\n\\t^ TextPlusMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 5/21/1998 06:44'!\\nbookPageMorphbosfcepcbbfgcc0\\n\\t\\\"BookPageMorph->PasteUpMorph. For reading in old BookMorphs.\\\"\\n\\n\\t^ PasteUpMorph\\n! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 5/22/1998 15:03'!\\nclippingMorphbosfcep0\\n\\t^ PasteUpMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 5/21/1998 06:44'!\\nclippingMorphbosfcepc0\\n\\t\\\"ClippingMorph->PasteUpMorph. For reading in old BookMorphs.\\\"\\n\\n\\t^ PasteUpMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 11/3/2000 18:47'!\\ndropShadowMorphbosfces0\\n\\n\\t^ Morph ! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'jm 11/13/97 10:32'!\\ngradientFillbosfcepbbfgcc0\\n\\t^ GradientFillMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 5/21/1998 19:24'!\\nlayoutMorphbosfcepbbochvimol0\\n\\t^ AlignmentMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 5/12/1998 16:18'!\\nlayoutMorphbosfcepcbbochvimol0\\n\\t^ AlignmentMorph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 10/26/2000 01:55'!\\nmorphicEventtcbks0\\n\\t^ MorphicEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 10/26/2000 00:48'!\\nmorphicSoundEventtcbkss0\\n\\t^ MorphicUnknownEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/12/2005 17:38'!\\nmultiStringx0\\n\\n\\t^ WideString! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 4/12/2005 17:38'!\\nmultiSymbolx0\\n\\n\\t^ WideSymbol! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'ar 7/8/2001 17:11'!\\nmyMorphbosfce0\\n\\n\\treshaped at: #MyMorph put: #convertbosfce0:bosfce0:.\\n\\t\\t\\\"Be sure to define that conversion method in class Morph\\\"\\n\\t^ Morph! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'RAA 10/26/2000 09:43'!\\nnewMorphicEventts0\\n\\n\\t^ MorphicEvent! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'mir 7/12/2002 18:03'!\\nscrollControllermvslrrsmsms0\\n\\n\\t^ MouseMenuController! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'tk 1/14/1999 13:16'!\\ntransparentColorrcc0\\n\\t^ TranslucentColor! !\\n\\n!SmartRefStream methodsFor: 'conversion' stamp: 'di 8/16/2000 16:37'!\\nworldMorphbosfcebbfgccpmcpbttloiairfidcuwhavcdsll0\\n\\t^ 'PutNewClassHere' \\\" <-- Replace this by a class name (no string quotes)\\\"! !\\n\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'tk\\n\\n11/26/2004 05:53'!\\napplyConversionMethodsTo: objectIn className: className varMap: varMap\\n\\n\\t\\\"Modify the object's instance vars to have the proper values\\n\\nfor its new shape. Mostly, fill in defaut values of new inst vars.\\n\\nCan substitute an object of a different class. (Beware: if\\n\\nsubstituted, varMap will not be correct when the new object is asked\\n\\nto convert.)\\\"\\n\\n\\t| anObject prevObject |\\n\\n\\n\\n\\tself flag: #bobconv.\\n\\n\\n\\n\\tanObject _ objectIn.\\n\\n\\t[\\n\\n\\t\\tprevObject _ anObject.\\n\\n\\t\\tanObject _ anObject convertToCurrentVersion: varMap\\n\\nrefStream: self.\\n\\n\\t\\tprevObject == anObject\\n\\n\\t] whileFalse.\\n\\n\\t^anObject\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:08'!\\ncheckFatalReshape: setOfClasses\\n\\t| suspects oldInstVars newInstVars bad className |\\n\\t\\\"Inform the user if any of these classes were reshaped. A block has a method from the old system whose receiver is of this class. The method's inst var references might be wrong. OK if inst vars were only added.\\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsetOfClasses isEmpty ifTrue: [^ self].\\n\\tsuspects _ OrderedCollection new.\\n\\tsetOfClasses do: [:aClass |\\n\\t\\tclassName _ renamed keyAtValue: aClass name ifAbsent: [aClass name].\\n\\t\\toldInstVars _ (structures at: className ifAbsent: [#(0)]) allButFirst.\\t\\t\\\"should be there\\\"\\n\\t\\tnewInstVars _ aClass allInstVarNames.\\n\\t\\toldInstVars size > newInstVars size ifTrue: [bad _ true].\\n\\t\\toldInstVars size = newInstVars size ifTrue: [\\n\\t\\t\\tbad _ oldInstVars ~= newInstVars].\\n\\t\\toldInstVars size < newInstVars size ifTrue: [\\n\\t\\t\\tbad _ oldInstVars ~= (newInstVars copyFrom: 1 to: oldInstVars size)].\\n\\t\\tbad ifTrue: [suspects add: aClass]].\\n\\n\\tsuspects isEmpty ifFalse: [\\n\\t\\tself inform: ('Imported foreign methods will run on instances of:\\\\',\\n\\t\\t\\tsuspects asArray printString, \\n\\t\\t\\t'\\\\whose shape has changed. Errors may occur.') withCRs].! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:06'!\\nconvert1: misShapenInst to: goodClass allVarMaps: allVarMaps\\n\\t\\\"Go through the normal instance conversion process and return a modern object.\\\"\\n\\n\\t| className oldInstVars anObject varMap |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tgoodClass isVariable ifTrue: [\\n\\t\\tgoodClass error: 'shape change for variable class not implemented yet'\\n\\t].\\n\\t(misShapenInst class name beginsWith: 'Fake37') ifFalse: [self error: 'why mapping?'].\\n\\tclassName _ (misShapenInst class name allButFirst: 6) asSymbol.\\n\\toldInstVars _ structures at: className.\\n\\tanObject _ goodClass basicNew.\\n\\n\\tvarMap _ Dictionary new.\\t\\\"later, indexed vars as (1 -> val) etc.\\\"\\n\\t2 to: oldInstVars size do: [:ind |\\n\\t\\tvarMap at: (oldInstVars at: ind) put: (misShapenInst instVarAt: ind-1)].\\n\\tvarMap at: #ClassName put: className.\\t\\\"original\\\"\\n\\tvarMap at: #NewClassName put: goodClass name.\\t\\\"new\\\"\\n\\tself storeInstVarsIn: anObject from: varMap. \\t\\\"ones with the same names\\\"\\n\\tallVarMaps at: misShapenInst put: varMap.\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 17:15'!\\nconvert2: partiallyCorrectInst allVarMaps: allVarMaps\\n\\t\\\"Go through the normal instance conversion process and return a modern object.\\\"\\n\\n\\t| className varMap |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tvarMap _ allVarMaps at: partiallyCorrectInst.\\n\\tclassName _ varMap at: #ClassName.\\t\\\"original\\\"\\n\\t^self applyConversionMethodsTo: partiallyCorrectInst className: className varMap: varMap.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'ar 4/12/2005 18:06'!\\nmapClass: newClass origName: originalName\\n\\t\\\"See if instances changed shape. If so, make a fake class for the old shape and return it. Remember the original class name.\\\"\\n\\n\\t| newName oldInstVars fakeClass |\\n\\tnewClass isMeta ifTrue: [^ newClass].\\n\\tnewName _ newClass name.\\n\\t(steady includes: newClass) & (newName == originalName) ifTrue: [^ newClass].\\n\\t\\t\\\"instances in the segment have the right shape\\\"\\n\\toldInstVars _ structures at: originalName ifAbsent: [\\n\\t\\t\\tself error: 'class is not in structures list'].\\t\\\"Missing in object file\\\"\\n\\n\\t\\\"Allow mapping from old to new string names\\\"\\n\\t(newName == #ByteString and:[originalName == #String]) ifTrue:[^newClass].\\n\\t(newName == #WideString and:[originalName == #MultiString]) ifTrue:[^newClass].\\n\\t(newName == #WideSymbol and:[originalName == #MultiSymbol]) ifTrue:[^newClass].\\n\\n\\tfakeClass _ Object subclass: ('Fake37', originalName) asSymbol\\n\\t\\tinstanceVariableNames: oldInstVars allButFirst\\n\\t\\tclassVariableNames: ''\\n\\t\\tpoolDictionaries: ''\\n\\t\\tcategory: 'Obsolete'.\\n\\tChangeSet current removeClassChanges: fakeClass name.\\t\\\"reduce clutter\\\"\\n\\t^ fakeClass\\n! !\\n\\n!SmartRefStream methodsFor: 'import image segment' stamp: 'RAA 12/20/2000 11:09'!\\nreshapedClassesIn: outPointers\\n\\t\\\"Look for classes in the outPointer array that have changed shape. Make a fake class for the old shape. Return a dictionary mapping Fake classes to Real classes. Substitute fake classes for real ones in outPointers.\\\"\\n\\n\\t| mapFakeClassesToReal fakeCls originalName |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tmapFakeClassesToReal _ IdentityDictionary new.\\n\\toutPointers withIndexDo: [:outp :ind | \\n\\t\\toutp isBehavior ifTrue: [\\n\\t\\t\\toriginalName _ renamedConv at: ind ifAbsent: [outp name].\\n\\t\\t\\t\\t\\\"in DiskProxy>>comeFullyUpOnReload: we saved the name at the index\\\"\\n\\t\\t\\tfakeCls _ self mapClass: outp origName: originalName.\\n\\t\\t\\tfakeCls == outp ifFalse: [\\n\\t\\t\\t\\tmapFakeClassesToReal at: fakeCls put: outp.\\n\\t\\t\\t\\toutPointers at: ind put: fakeCls]]].\\n\\t^ mapFakeClassesToReal! !\\n\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/15/98 20:28'!\\nappendClassDefns\\n\\t\\\"Make this a fileOut format file. For each UniClass mentioned, prepend its source code to the file. Class name conflicts during reading will be resolved then. Assume instVarInfo: has already been done.\\\"\\n\\nbyteStream ascii.\\nbyteStream position = 0 ifTrue: [\\n\\tbyteStream setFileTypeToObject.\\n\\t\\t\\\"Type and Creator not to be text, so can attach correctly to an email msg\\\"\\n\\tbyteStream header; timeStamp].\\n\\nbyteStream cr; nextPutAll: '!!ObjectScanner new initialize!!'; cr; cr.\\nself uniClasesDo: [:class | class\\n\\t\\tclass sharedPools size > 0 ifTrue: \\\"This never happens\\\"\\n\\t\\t\\t[class shouldFileOutPools\\n\\t\\t\\t\\tifTrue: [class fileOutSharedPoolsOn: self]].\\n\\t\\tclass fileOutOn: byteStream moveSource: false toFile: 0].\\t\\n\\t\\t\\\"UniClasses are filed out normally, no special format.\\\"\\n\\n\\tbyteStream trailer.\\t\\\"Does nothing for normal files. \\n\\t\\tHTML streams will have trouble with object data\\\"\\n\\n\\t\\\"Append the object's raw data\\\"\\n\\tbyteStream cr; cr; nextPutAll: '!!self smartRefStream!!'.\\n\\tbyteStream binary.\\t\\t\\\"get ready for objects\\\"\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/19/2000 21:22'!\\ncheckCrLf\\n\\t| save isCrLf cc prev loneLf |\\n\\t\\\"Watch for a file that has had all of its Cr's converted to CrLf's. Some unpacking programs like Stuffit 5.0 do this by default!!\\\"\\n\\n\\tsave _ byteStream position.\\n\\tisCrLf _ false. loneLf _ false.\\n\\tcc _ 0.\\n\\t350 timesRepeat: [\\n\\t\\tprev _ cc.\\n\\t\\t(cc _ byteStream next) = 16r0A \\\"Lf\\\" ifTrue: [\\n\\t\\t\\tprev = 16r0D \\\"Cr\\\" ifTrue: [isCrLf _ true] ifFalse: [loneLf _ true]].\\n\\t\\t].\\n\\tisCrLf & (loneLf not) ifTrue: [\\n\\t\\tself inform: 'Carriage Returns in this file were converted to CrLfs \\nby an evil unpacking utility. Please set the preferences in \\nStuffIt Expander to \\\"do not convert file formats\\\"'].\\n\\tbyteStream position: save.\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'mir 9/12/2002 10:59'!\\ninitKnownRenames\\n\\trenamed\\n\\t\\tat: #FlasherMorph put: #Flasher;\\n\\t\\tyourself! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 19:27'!\\ninitShapeDicts\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\t\\\"These must stay constant. When structures read in, then things can change.\\\"\\n\\tsteady _ {Array. Dictionary. Association. ByteString. SmallInteger} asSet.\\n\\n\\trenamed ifNil: [\\n\\t\\trenamed _ Dictionary new. \\\"(old class name symbol -> new class name)\\\"\\n\\t\\trenamedConv _ Dictionary new \\\"(oldClassNameSymbol -> conversionSelectorInNewClass)\\\"\\n\\t].\\n\\tself initKnownRenames! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/7/2001 18:17'!\\ninstVarInfo: anObject\\n\\t\\\"Return the object to write on the outgoing file that contains the structure of each class we are about to write out. Must be an Array whose first element is 'class structure'. Its second element is a Dictionary of pairs of the form #Rectangle -> #(<classVersion> 'origin' 'corner'). \\\"\\n\\n\\t\\\"Make a pass through the objects, not writing, but recording the classes. Construct a database of their inst vars and any version info (classVersion).\\\"\\n\\n\\t| dummy refs cls newSupers |\\n\\tstructures _ Dictionary new.\\n\\tsuperclasses _ Dictionary new.\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\trefs _ dummy references.\\n\\tobjCount _ refs size.\\t\\t\\\"for progress bar\\\"\\n\\t\\t\\\"Note that Dictionary must not change its implementation!! If it does, how do we read this reading information?\\\"\\n\\t(refs includesKey: #AnImageSegment) \\n\\t\\tifFalse: [\\n\\t\\t\\tself uniClassInstVarsRefs: dummy.\\t\\\"catalog the extra objects in UniClass inst vars\\\"\\n\\t\\t\\trefs keysDo: [:each | \\n\\t\\t\\t\\tcls _ each class.\\n\\t\\t\\t\\t\\\"cls isObsolete ifTrue: [self error: 'Trying to write ', cls name].\\\"\\n\\t\\t\\t\\t(cls class ~~ Metaclass) & (cls isObsolete not) ifTrue: [\\n\\t\\t\\t\\t\\tstructures at: cls name put: false]]]\\n\\t\\tifTrue: [self recordImageSegment: refs].\\n\\t\\\"Save work by only computing inst vars once for each class\\\"\\n\\tnewSupers _ Set new.\\n\\tstructures at: #Point put: false.\\t\\\"writeRectangle: does not put out class pointer\\\"\\n\\tstructures at: #Rectangle put: false.\\n\\tstructures at: #LargePositiveInteger put: false.\\t\\\"used in slow case of WordArray\\\"\\n\\tstructures keysDo: [:nm | \\n\\t\\tcls _ (nm endsWith: ' class') \\n\\t\\t\\tifFalse: [Smalltalk at: nm]\\n\\t\\t\\tifTrue: [(Smalltalk at: nm substrings first asSymbol) class].\\n\\t\\tcls allSuperclasses do: [:aSuper |\\n\\t\\t\\tstructures at: aSuper name ifAbsent: [newSupers add: aSuper name]]].\\n\\t\\t\\t\\\"Don't modify structures during iteration\\\"\\n\\tnewSupers do: [:nm | structures at: nm put: 3].\\t\\\"Get all superclasses into list\\\"\\n\\tstructures keysDo: [:nm | \\\"Nothing added to classes during loop\\\"\\n\\t\\tcls _ (nm endsWith: ' class') \\n\\t\\t\\tifFalse: [Smalltalk at: nm]\\n\\t\\t\\tifTrue: [(Smalltalk at: nm substrings first asSymbol) class].\\n\\t\\tstructures at: nm put: \\n\\t\\t\\t((Array with: cls classVersion), (cls allInstVarNames)).\\n\\t\\tsuperclasses at: nm ifAbsent: [\\n\\t\\t\\t\\tsuperclasses at: nm put: cls superclass name]].\\n\\t(refs includesKey: #AnImageSegment) \\n\\t\\tifTrue: [classInstVars _ #()]\\n\\t\\tifFalse: [self saveClassInstVars].\\t\\\"of UniClassses\\\"\\n\\t^ (Array with: 'class structure' with: structures with: 'superclasses' with: superclasses)! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 18:52'!\\nmapClass: incoming\\n\\t\\\"See if the old class named nm exists. If so, return it. If not, map it to a new class, and save the mapping in renamed. \\\"\\n\\n\\t| cls oldVer sel nm |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tnm _ renamed at: incoming ifAbsent: [incoming].\\t\\\"allow pre-mapping around collisions\\\"\\n\\t(nm endsWith: ' class') \\n\\t\\tifFalse: [cls _ Smalltalk at: nm ifAbsent: [nil].\\n\\t\\t\\tcls ifNotNil: [^ cls]] \\t\\\"Known class. It will know how to translate the instance.\\\"\\n\\t\\tifTrue: [cls _ Smalltalk at: nm substrings first asSymbol ifAbsent: [nil].\\n\\t\\t\\tcls ifNotNil: [^ cls class]]. \\t\\\"Known class. It will know how to translate the instance.\\\"\\n\\toldVer _ self versionSymbol: (structures at: nm).\\n\\tsel _ nm asString.\\n\\tsel at: 1 put: (sel at: 1) asLowercase.\\n\\tsel _ sel, oldVer.\\t\\\"i.e. #rectangleoc4\\\"\\n\\tSymbol hasInterned: sel ifTrue: [:symb | \\n\\t\\t(self class canUnderstand: sel asSymbol) ifTrue: [\\n\\t\\t\\treshaped ifNil: [reshaped _ Dictionary new].\\n\\t\\t\\tcls _ self perform: sel asSymbol]].\\t\\\"This class will take responsibility\\\"\\n\\tcls ifNil: [cls _ self writeClassRenameMethod: sel was: nm\\n\\t\\t\\t\\t\\tfromInstVars: (structures at: nm).\\n\\t\\t\\t cls isString ifTrue: [cls _ nil]].\\n\\tcls ifNotNil: [renamed at: nm put: cls name].\\n\\t^ cls\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 5/26/1998 15:09'!\\nmoreObjects\\n\\t\\\"Return true if there appears to be another object following this one on the file.\\\"\\n\\n\\t| byte |\\n\\tbyteStream atEnd ifTrue: [^ false].\\t\\\"off end of file\\\"\\n\\t(byte _ byteStream peek) ifNil: [^ false].\\t\\\"off end of file\\\"\\n\\tbyte = 33 \\\"$!! asciiValue\\\" ifTrue: [^ false].\\n\\tbyte = 0 ifTrue: [^ false].\\n\\t^ byte <= RefTypes size\\t\\t\\\"between 1 and 16\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/19/2000 17:06'!\\nnext\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. \\\"\\n\\n\\t| version ss object |\\n\\t^ topCall == nil \\n\\t\\tifTrue: \\n\\t\\t\\t[topCall _ #marked.\\n\\t\\t\\tversion _ super next.\\n\\t\\t\\tversion class == SmallInteger ifFalse: [^ version].\\t\\n\\t\\t\\t\\t\\\"version number, else just a regular object, not in our format, \\\"\\n\\t\\t\\tself checkCrLf.\\n\\t\\t\\tss _ super next.\\n\\t\\t\\tss class == Array ifFalse: [^ ss]. \\\"just a regular object\\\"\\n\\t\\t\\t(ss at: 1) = 'class structure' ifFalse: [^ ss].\\n\\t\\t\\tstructures _ ss at: 2.\\n\\t\\t\\tsuperclasses _ (ss size > 3 and: [(ss at: 3) = 'superclasses']) \\n\\t\\t\\t\\tifTrue: [ss at: 4]\\t\\t\\\"class name -> superclass name\\\"\\n\\t\\t\\t\\tifFalse: [Dictionary new].\\n\\t\\t\\t(self verifyStructure = 'conversion method needed') ifTrue: [^ nil].\\n\\t\\t\\tobject _ super next.\\t\\\"all the action here\\\"\\n\\t\\t\\tself restoreClassInstVars.\\t\\t\\\"for UniClasses. version 4\\\"\\n\\n\\t\\t\\ttopCall _ nil.\\t\\\"reset it\\\"\\n\\t\\t\\tobject]\\n\\t\\tifFalse:\\n\\t\\t\\t[super next]\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/5/2002 09:52'!\\nnextAndClose\\n\\t\\\"Speedy way to grab one object. Only use when we are inside an object binary file. If used for the start of a SmartRefStream mixed code-and-object file, tell the user and then do the right thing.\\\"\\n\\n\\t| obj |\\n\\tbyteStream peek = ReferenceStream versionCode \\\"4\\\" ifFalse: [\\n\\t\\t\\\"OK it is a fileIn afterall...\\\"\\n\\t\\tself inform: 'Should be using fileInObjectAndCode'.\\n\\t\\tbyteStream ascii.\\n\\t\\tbyteStream fileIn.\\n\\t\\tobj _ SmartRefStream scannedObject.\\n\\t\\tSmartRefStream scannedObject: nil.\\n\\t\\t^ obj].\\n\\n\\tobj _ self next.\\n\\tself close.\\n\\t^ obj! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'md 2/24/2006 19:52'!\\nnextPut: anObject\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. If any instance-specific classes are present, prepend their source code. byteStream will be in fileOut format.\\n\\tYou can see an analysis of which objects are written out by doing: \\n\\t(SmartRefStream statsOfSubObjects: anObject)\\n\\t(SmartRefStream tallyOfSubObjects: anObject)\\n\\t(SmartRefStream subObjects: anObject ofClass: aClass)\\\"\\n\\n| info |\\ntopCall == nil \\n\\tifTrue:\\n\\t\\t[topCall _ anObject.\\n\\t\\t'Please wait while objects are counted' \\n\\t\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\t\\tfrom: 0 to: 10\\n\\t\\t\\tduring: [:bar | info _ self instVarInfo: anObject].\\n\\t\\tself appendClassDefns.\\t\\\"For instance-specific classes\\\"\\n\\t\\t'Writing an object file' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\tfrom: 0 to: objCount*4\\t\\\"estimate\\\"\\n\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\tobjCount _ 0.\\n\\t\\t\\t\\tprogressBar _ bar.\\n\\t\\t\\t\\tself setStream: byteStream reading: false.\\n\\t\\t\\t\\t\\t\\\"set basePos, but keep any class renames\\\"\\n\\t\\t\\t\\tsuper nextPut: ReferenceStream versionCode.\\n\\t\\t\\t\\tsuper nextPut: info.\\n\\t\\t\\t\\tsuper nextPut: anObject.\\t\\t\\\"<- the real writing\\\"\\n\\t\\t\\t\\tclassInstVars size > 0 ifTrue: [super nextPut: classInstVars]].\\n\\t\\t\\t\\t\\t\\\"Note: the terminator, $!!, is not doubled inside object data\\\"\\n\\t\\t\\\"references is an IDict of every object that got written\\\"\\n\\t\\tbyteStream ascii.\\n\\t\\tbyteStream nextPutAll: '!!'; cr; cr.\\n\\t\\tbyteStream padToEndWith: $ .\\t\\\"really want to truncate file, but can't\\\"\\n\\t\\ttopCall _ progressBar _ nil]\\t\\\"reset it\\\"\\n\\tifFalse:\\n\\t\\t[super nextPut: anObject.\\n\\t\\tprogressBar ifNotNil: [progressBar value: (objCount _ objCount + 1)]].\\n\\t\\t\\\"return the argument - added by kwl\\\"\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/23/1998 11:00'!\\nnextPutObjOnly: anObject\\n\\t\\\"Really write three objects: (version, class structure, object). But only when called from the outside. Not in fileOut format. No class definitions will be written for instance-specific classes. Error if find one. (Use nextPut: instead)\\\"\\n\\n\\t| info |\\n\\ttopCall == nil \\n\\t\\tifTrue:\\n\\t\\t\\t[topCall _ anObject.\\n\\t\\t\\tsuper nextPut: ReferenceStream versionCode.\\n\\t\\t\\t'Please wait while objects are counted' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\t\\tfrom: 0 to: 10\\n\\t\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\t\\tinfo _ self instVarInfo: anObject].\\n\\t\\t\\tself uniClasesDo: [:cls | cls error: 'Class defn not written out. Proceed?'].\\n\\t\\t\\t'Writing an object file' displayProgressAt: Sensor cursorPoint\\n\\t\\t\\t\\tfrom: 0 to: objCount*4\\t\\\"estimate\\\"\\n\\t\\t\\t\\tduring: [:bar |\\n\\t\\t\\t\\t\\tobjCount _ 0.\\n\\t\\t\\t\\t\\tprogressBar _ bar.\\n\\t\\t\\t\\t\\tsuper nextPut: info.\\n\\t\\t\\t\\t\\tsuper nextPut: anObject.\\t\\\"<- the real writing\\\"\\n\\t\\t\\t\\t\\t\\\"Class inst vars not written here!!\\\"].\\n\\t\\t\\t\\\"references is an IDict of every object that got written\\n\\t\\t\\t(in case you want to take statistics)\\\"\\n\\t\\t\\t\\\"Transcript cr; show: structures keys printString.\\\"\\t\\t\\\"debug\\\"\\n\\t\\t\\ttopCall _ progressBar _ nil]\\t\\\"reset it\\\"\\n\\t\\tifFalse:\\n\\t\\t\\t[super nextPut: anObject.\\n\\t\\t\\tprogressBar ifNotNil: [progressBar value: (objCount _ objCount + 1)]].! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 6/23/1998 11:13'!\\nnoHeader\\n\\t\\\"Signal that we've already dealt with the version and structure array, and are now reading objects.\\\"\\n\\n\\ttopCall _ #marked.\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 11/3/2000 17:59'!\\nreadInstance\\n\\t\\\"Read the contents of an arbitrary instance.\\n\\t ASSUMES: readDataFrom:size: sends me beginReference: after it\\n\\t instantiates the new object but before reading nested objects.\\n\\t NOTE: We must restore the current reference position after\\n\\t recursive calls to next.\\nThree cases for files from older versions of the system:\\n1) Class has not changed shape, read it straight.\\n2) Class has changed instance variables (or needs fixup). Call a particular method to do it.\\n3) There is a new class instead. Find it, call a particular method to read.\\n\\tAll classes used to construct the structures dictionary *itself* need to be in 'steady' and they must not change!! See setStream:\\\"\\n\\t| instSize className refPosn |\\n\\n\\tinstSize _ (byteStream nextNumber: 4) - 1.\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self next asSymbol.\\n\\t^ self readInstanceSize: instSize clsname: className refPosn: refPosn\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'yo 1/21/2006 19:27'!\\nreadInstanceSize: instSize clsname: className refPosn: refPosn\\n\\t\\\"The common code to read the contents of an arbitrary instance.\\n\\t ASSUMES: readDataFrom:size: sends me beginReference: after it\\n\\t instantiates the new object but before reading nested objects.\\n\\t NOTE: We must restore the current reference position after\\n\\t recursive calls to next.\\nThree cases for files from older versions of the system:\\n1) Class has not changed shape, read it straight.\\n2) Class has changed instance variables (or needs fixup). Call a particular method to do it.\\n3) There is a new class instead. Find it, call a particular method to read.\\n\\tAll classes used to construct the structures dictionary *itself* need to be in 'steady' and they must not change!! See setStream:\\\"\\n\\t| anObject newName newClass dict oldInstVars isMultiSymbol |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tself setCurrentReference: refPosn. \\\"remember pos before readDataFrom:size:\\\"\\n\\tnewName _ renamed at: className ifAbsent: [className].\\n\\tisMultiSymbol _ newName = #MultiSymbol or: [newName = #WideSymbol].\\n\\t\\\"isMultiSymbol ifTrue: [self halt].\\\"\\n\\tnewClass _ Smalltalk at: newName asSymbol.\\n\\t(steady includes: newClass) & (newName == className) ifTrue: [\\n\\t \\tanObject _ newClass isVariable \\\"Create it here\\\"\\n\\t\\t\\tifFalse: [newClass basicNew]\\n\\t\\t\\tifTrue: [newClass basicNew: instSize - (newClass instSize)].\\n\\n\\t\\tanObject _ anObject readDataFrom: self size: instSize.\\n\\t\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\t\\tisMultiSymbol ifTrue: [^ Symbol intern: anObject asString].\\n\\t\\t^ anObject].\\n\\toldInstVars _ structures at: className ifAbsent: [\\n\\t\\t\\tself error: 'class is not in structures list'].\\t\\\"Missing in object file\\\"\\n\\tanObject _ newClass createFrom: self size: instSize version: oldInstVars.\\n\\t\\t\\\"only create the instance\\\"\\n\\tself beginReference: anObject.\\n\\tdict _ self catalogValues: oldInstVars size: instSize.\\n\\t\\t\\\"indexed vars as (1 -> val) etc.\\\"\\n\\tdict at: #ClassName put: className.\\t\\\"so conversion method can know it\\\"\\n\\n\\t\\\"Give each superclass a chance to make its changes\\\"\\n\\tself storeInstVarsIn: anObject from: dict.\\t\\\"ones with the same names\\\"\\n\\n\\tanObject _ self applyConversionMethodsTo: anObject className: className varMap: dict.\\n\\n\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\tisMultiSymbol ifTrue: [^ Symbol intern: anObject asString].\\n\\t^ anObject! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 11/3/2000 18:04'!\\nreadShortInst\\n\\t\\\"Instance has just one byte of size. Class symbol is encoded in two bytes of file position. See readInstance.\\\"\\n\\t| instSize className refPosn |\\n\\n\\tinstSize _ (byteStream next) - 1.\\t\\\"one byte of size\\\"\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self readShortRef.\\t\\\"class symbol in two bytes of file pos\\\"\\n\\t^ self readInstanceSize: instSize clsname: className refPosn: refPosn\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 7/25/2005 21:30'!\\nreadWordLike\\n\\t| refPosn newClass anObject className |\\n\\t\\\"Can be used by any class that is bits and not bytes (WordArray, Bitmap, SoundBuffer, etc).\\\"\\n\\n\\trefPosn _ self getCurrentReference.\\n\\tclassName _ self next asSymbol.\\n\\tclassName _ renamed at: className ifAbsent: [className].\\n\\tnewClass _ Smalltalk at: className.\\n\\tanObject _ newClass newFromStream: byteStream.\\n\\t\\\"Size is number of long words.\\\"\\n\\tself setCurrentReference: refPosn. \\\"before returning to next\\\"\\n\\t^ anObject\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 10/10/2000 13:36'!\\nrecordImageSegment: refs\\n\\t\\\"Besides the objects being written out, record the structure of instances inside the image segment we are writing out.\\\"\\n\\n\\t| cls list |\\n\\t\\\"Do not record Player class inst vars. They are in the segement.\\\"\\n\\trefs keysDo: [:each | \\n\\t\\tcls _ each class.\\n\\t\\tcls isObsolete ifTrue: [self error: 'Trying to write ', cls name].\\n\\t\\tcls class == Metaclass \\n\\t\\t\\tifFalse: [structures at: cls name put: false.\\n\\t\\t\\t\\t(each isKindOf: ImageSegment) ifTrue: [\\n\\t\\t\\t\\t\\teach outPointers do: [:out |\\n\\t\\t\\t\\t\\t\\t(out isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tstructures at: out theNonMetaClass name put: false].\\n\\t\\t\\t\\t\\t\\tout class == DiskProxy ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tout simpleGlobalOrNil ifNotNil: [\\n\\t\\t\\t\\t\\t\\t\\t\\t(out simpleGlobalOrNil isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tstructures at: out simpleGlobalOrNil name put: false]]]].\\n\\t\\t\\t\\t\\t\\\"each arrayOfRoots do: [:rr | (rr isKindOf: Class) ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tstructures at: rr theNonMetaClass name put: false]].\\\"\\n\\t\\t\\t\\t\\t \\t\\\"all classes in roots are local to seg\\\"]]].\\n\\tlist _ refs at: #BlockReceiverClasses ifAbsent: [^ self].\\n\\tlist do: [:meta | structures at: meta name put: false].\\n\\t\\t\\\"Just the metaclasses whose instances are block receivers. Otherwise metaclasses are not allowed.\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 11:08'!\\nrenamed\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\t^ renamed! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 11:10'!\\nrenamedConv\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\t^ renamedConv! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/22/2000 15:14'!\\nrestoreClassInstVars\\n\\t\\\"Install the values of the class instance variables of UniClasses\\n(i.e. scripts slotInfo). classInstVars is ((#Player25 scripts slotInfo)\\n...). Thank you Mark Wai for the bug fix.\\\"\\n\\n\\t| normal aName newName newCls trans rList start |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\n\\tself moreObjects ifFalse: [^ self]. \\t\\\"are no UniClasses with class inst vars\\\"\\n\\tclassInstVars _ super next.\\t\\\"Array of arrays\\\"\\n\\tnormal _ Object class instSize.\\t\\\"might give trouble if Player class superclass changes size\\\"\\n\\t(structures at: #Player ifAbsent: [#()]) = #(0 'dependents' 'costume') ifTrue:\\n\\t\\t[trans _ 1].\\t\\\"now (0 costume costumes). Do the conversion of Player class\\n\\t\\t\\tinst vars in Update 509.\\\"\\n\\tclassInstVars do: [:list |\\n\\t\\taName _ (list at: 1) asSymbol.\\n\\t\\trList _ list.\\n\\t\\tnewName _ renamed at: aName ifAbsent: [aName].\\n\\t\\tnewCls _ Smalltalk at: newName\\n\\t\\t\\t\\tifAbsent: [self error: 'UniClass definition missing'].\\n\\t\\t(\\\"old conversion\\\" trans == 1 and: [newCls inheritsFrom: Player]) ifTrue: [\\n\\t\\t\\t\\\"remove costumeDictionary from Player class inst vars\\\"\\n\\t\\t\\trList _ rList asOrderedCollection.\\n\\t\\t\\trList removeAt: 4].\\t\\\"costumeDictionary's value\\\"\\n\\t\\tstart _ list second = 'Update to read classPool' ifTrue: [4] ifFalse: [2].\\n\\t\\tnewCls class instSize = (normal + (rList size) - start + 1) ifFalse:\\n\\t\\t\\t[self error: 'UniClass superclass class has changed size'].\\n\\t\\t\\t\\\"Need to install a conversion method mechanism\\\"\\n\\t\\tstart = 4 ifTrue: [newCls instVarAt: normal - 1 \\\"classPool\\\" put: (list at: 3)].\\n\\t\\tstart to: rList size do: [:ii |\\n\\t\\t\\tnewCls instVarAt: normal + ii - start + 1 put: (rList at: ii)]].\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/6/2000 18:17'!\\nsaveClassInstVars\\n\\t\\\"Install the values of the instance variables of UniClasses.\\nclassInstVars is an array of arrays (#Player3 (Player3 class's inst var\\nscripts) (Player3 class's inst var slotInfo) ...) \\\"\\n\\n\\t| normal mySize list clsPoolIndex |\\n\\tclassInstVars _ OrderedCollection new: 100.\\n\\tnormal _ Object class instSize.\\n\\tclsPoolIndex _ Object class allInstVarNames indexOf: 'classPool'.\\n\\tself uniClasesDo: [:aUniClass |\\n\\t\\tlist _ OrderedCollection new.\\n\\t\\tmySize _ aUniClass class instSize.\\n\\t\\tmySize = normal ifFalse:\\n\\t\\t\\t[list add: aUniClass name.\\t\\\"a symbol\\\"\\n\\t\\t\\tlist add: 'Update to read classPool'.\\t\\\"new\\nconvention for saving the classPool\\\"\\n\\t\\t\\tlist add: (aUniClass instVarAt: clsPoolIndex)\\n\\\"classPool\\\".\\n\\t\\t\\t\\t\\t\\t\\\"write actual value of nil\\ninstead of Dictionary()\\\"\\n\\t\\t\\tnormal + 1 to: mySize do: [:ii |\\n\\t\\t\\t\\tlist addLast: (aUniClass instVarAt: ii)].\\n\\t\\t\\tclassInstVars add: list asArray]].\\n\\tclassInstVars _ classInstVars asArray.\\n\\t! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 8/18/1998 09:02'!\\nscanFrom: aByteStream\\n\\t\\\"During a code fileIn, we need to read in an object, and stash it in ScannedObject. \\\"\\n\\n\\tself setStream: aByteStream reading: true.\\n\\tScannedObject _ self next.\\n\\tbyteStream ascii.\\n\\tbyteStream next == $!! ifFalse: [\\n\\t\\tbyteStream close.\\n\\t\\tself error: 'Object did not end correctly']. \\n\\t\\\"caller will close the byteStream\\\"\\n\\t\\\"HandMorph.readMorphFile will retrieve the ScannedObject\\\"! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 16:57'!\\nsetStream: aStream\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsuper setStream: aStream.\\n\\tself initShapeDicts.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'RAA 12/20/2000 16:57'!\\nsetStream: aStream reading: isReading\\n\\t\\\"Initialize me. \\\"\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tsuper setStream: aStream reading: isReading.\\n\\tisReading ifFalse: [^ false].\\n\\tself initShapeDicts.\\n\\n! !\\n\\n!SmartRefStream methodsFor: 'read write'!\\nstructures\\n\\t^ structures! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 9/28/97 11:17'!\\nsuperclasses\\n\\t^superclasses! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 3/6/2000 17:15'!\\nuniClasesDo: aBlock\\n\\t\\\"Examine structures and execute the block with each instance-specific class\\\"\\n\\n\\t| cls |\\n\\tstructures keysDo: [:clsName | \\n\\t\\t(clsName endsWith: ' class') ifFalse: [\\n\\t\\t\\t(cls _ Smalltalk at: clsName) isSystemDefined ifFalse: [\\n\\t\\t\\t\\t\\taBlock value: cls]]]! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 1/18/2001 15:54'!\\nuniClassInstVarsRefs: dummy\\n\\t\\\"If some of the objects seen so far are instances UniClasses, check the UniClasses for extra class inst vars, and send them to the steam also. The new objects get added to (dummy references), where they will be noticed by the caller. They will wind up in the structures array and will be written on the disk by class.\\n\\tReturn all classes seen.\\\" \\n| uniClasses normal more aUniClass mySize allClasses |\\n\\n\\\"Note: Any classes used in the structure of classInstVars must be written out also!!\\\"\\nuniClasses _ Set new.\\nallClasses _ IdentitySet new.\\nnormal _ Object class instSize.\\nmore _ true.\\n[more] whileTrue: [\\n\\tmore _ false.\\n\\tdummy references keysDo: [:each | \\\"any faster way to do this?\\\"\\n\\t\\t(aUniClass _ each class) isSystemDefined ifFalse: [\\n\\t\\t\\t(uniClasses includes: aUniClass name) ifFalse: [\\n\\t\\t\\t\\tmySize _ aUniClass class instSize.\\n\\t\\t\\t\\tnormal+1 to: mySize do: [:ii | \\n\\t\\t\\t\\t\\tmore _ true.\\n\\t\\t\\t\\t\\tdummy nextPut: (aUniClass instVarAt: ii)].\\n\\t\\t\\t\\tuniClasses add: aUniClass name]].\\n\\t\\teach class class isMeta ifFalse: [\\\"it is a class\\\" allClasses add: each]]].\\n\\\"References dictionary is modified as the loop proceeds, but we will catch any we missed on the next cycle.\\\"\\n\\n^ allClasses! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'ar 4/10/2005 18:52'!\\nverifyStructure\\n\\t\\\"Compare the incoming inst var name lists with the existing classes. Prepare tables that will help to restructure those who need it (renamed, reshaped, steady). If all superclasses are recorded in the file, only compare inst vars of this class, not of superclasses. They will get their turn. \\\"\\n\\n\\n\\t| newClass newList oldList converting |\\n\\n\\tself flag: #bobconv.\\t\\n\\n\\tconverting _ OrderedCollection new.\\n\\tstructures keysDo: [:nm \\\"an old className (symbol)\\\" |\\n\\t\\t\\\"For missing classes, there needs to be a method in SmartRefStream like \\n\\t\\t\\t#rectangleoc2 that returns the new class.\\\"\\n\\t\\tnewClass _ self mapClass: nm.\\t \\\"does (renamed at: nm put: newClass name)\\\"\\n\\t\\tnewClass isString ifTrue: [^ newClass]. \\\"error, fileIn needed\\\"\\n\\t\\tnewList _ (Array with: newClass classVersion), (newClass allInstVarNames).\\n\\t\\toldList _ structures at: nm.\\n\\t\\tnewList = oldList \\n\\t\\t\\tifTrue: [steady add: newClass] \\\"read it in as written\\\"\\n\\t\\t\\tifFalse: [converting add: newClass name]\\n\\t].\\n\\tfalse & converting isEmpty not ifTrue: [\\\"debug\\\" \\n\\t\\t\\tself inform: 'These classes are being converted from existing methods:\\\\' withCRs,\\n\\t\\t\\t\\tconverting asArray printString].\\n! !\\n\\n!SmartRefStream methodsFor: 'read write' stamp: 'tk 1/7/97'!\\nversionSymbol: instVarList\\n\\t\\\"Create the symbolic code (like a version number) for this class in some older version. First initials of all the inst vars, followed by the class version number. Returns a string, caller makes it into a compound selector. \\\"\\n\\n\\t| str |\\n\\tstr _ instVarList size = 1 ifFalse: [''] ifTrue: ['x'].\\t\\t\\\"at least one letter\\\"\\n\\t2 to: instVarList size do: [:ind |\\n\\t\\tstr _ str, (instVarList at: ind) first asString].\\n\\tstr _ str, instVarList first printString.\\t\\\"the number\\\"\\n\\t^ str\\n\\n\\\" | list | list _ (Array with: Paragraph classVersion), (Paragraph alistInstVarNames).\\n(SmartRefStream on: (DummyStream on: nil)) versionSymbol: list\\n\\\"! !\\n\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:35'!\\nstarLogoAntColonybosfcedppplppppttwssdlgrstta0\\n\\n\\t^ StarSqueakAntColony! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:31'!\\nstarLogoMorphbosfcedppplppppttwssdlgrstt0\\n\\n\\t^ StarSqueakMorph! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:32'!\\nstarLogoTreesbosfcedppplppppttwssdlgrsttdt0\\n\\n\\t^ StarSqueakTrees! !\\n\\n!SmartRefStream methodsFor: '*starSqueak-*starSqueak' stamp: 'RAA 5/16/2001 18:32'!\\nstarLogoTurtlewwxywwhcpn0\\n\\n\\t^ StarSqueakTurtle! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSmartRefStream class\\n\\tinstanceVariableNames: ''!\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 5/20/97'!\\nscannedObject\\n\\t\\\"The most recently read in object. Watch out for read-in that is interrupted and resumed. May want to make this a dictionary? \\\"\\n\\n\\t^ ScannedObject! !\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 5/20/97'!\\nscannedObject: objOrNil\\n\\t\\\"Used to free up the last object stashed here. \\\"\\n\\n\\tScannedObject _ objOrNil! !\\n\\n!SmartRefStream class methodsFor: 'accessing' stamp: 'tk 3/11/98 09:45'!\\nsubObjects: anObject ofClass: aClass\\n\\t\\\"Return a collection of all instances of aClass that would be written out with anObject. Does not actually write on the disk. Inspect the result and ask for 'references to this object'.\\\"\\n\\n\\t| dummy coll |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\tcoll _ OrderedCollection new.\\n\\tdummy references keysDo: [:each |\\n\\t\\teach class == aClass ifTrue: [coll add: each]].\\n\\t^ coll! !\\n\\n\\n!SmartRefStream class methodsFor: 'initialize-release' stamp: 'dvf 8/23/2003 12:18'!\\ncleanUpCategories\\n\\t| list valid removed newList newVers |\\n\\t\\\"Look for all conversion methods that can't be used any longer. Delete them.\\\"\\n\\t\\\" SmartRefStream cleanUpCategories \\\"\\n\\n\\t\\\"Two part selectors that begin with convert and end with a digit.\\\"\\n\\t\\\"convertasossfe0: varDict asossfeu0: smartRefStrm\\\"\\n\\tlist _ Symbol selectorsContaining: 'convert'.\\n\\tlist _ list select: [:symb | (symb beginsWith: 'convert') & (symb allButLast last isDigit)\\n\\t\\t\\t\\tifTrue: [(symb numArgs = 2)]\\n\\t\\t\\t\\tifFalse: [false]].\\n\\tvalid _ 0. removed _ 0.\\n\\tlist do: [:symb |\\n\\t\\t(self systemNavigation allClassesImplementing: symb) do: [:newClass |\\n\\t\\t\\tnewList _ (Array with: newClass classVersion), (newClass allInstVarNames).\\n\\t\\t\\tnewVers _ self new versionSymbol: newList.\\n\\t\\t\\t(symb endsWith: (':',newVers,':')) \\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\\"method is useless because can't convert to current shape\\\"\\n\\t\\t\\t\\t\\tnewClass removeSelector: symb.\\t\\\"get rid of it\\\"\\n\\t\\t\\t\\t\\tremoved _ removed + 1]\\n\\t\\t\\t\\tifTrue: [valid _ valid + 1]]].\\n\\tTranscript cr; show: 'Removed: '; print: removed; \\n\\t\\tshow: '\\t\\tKept: '; print: valid; show: ' '.! !\\n\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'RAA 7/9/2000 05:48'!\\nobjectFromStreamedRepresentation: someBytes\\n\\n\\t| file |\\n\\n\\tfile _ RWBinaryOrTextStream with: someBytes.\\n\\tfile reset.\\n\\t^file fileInObjectAndCode! !\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'tk 12/9/97 21:31'!\\nread: aByteStream withClasses: structureArray\\n\\t\\\"Read an object off the stream, but first check structureArray against the current system.\\\"\\n\\n\\t| me |\\n\\tme _ self on: aByteStream.\\n\\tme noHeader.\\n\\tme structures: (structureArray at: 2).\\n\\tme superclasses: (structureArray at: 4).\\n\\t(me verifyStructure = 'conversion method needed') ifTrue: [^ nil].\\n\\t^ super next\\n! !\\n\\n!SmartRefStream class methodsFor: 'i/o' stamp: 'tk 5/20/97'!\\nscanFrom: aByteStream\\n\\t\\\"During a code fileIn, we need to read in an object, and stash it in ScannedObject. \\\"\\n\\n\\t| me |\\n\\tme _ self on: aByteStream.\\n\\tScannedObject _ me next.\\n\\taByteStream ascii.\\n\\taByteStream next == $!! ifFalse: [\\n\\t\\taByteStream close.\\n\\t\\tself error: 'Object did not end correctly']. \\n\\t\\\"caller will close the byteStream\\\"\\n\\t\\\"HandMorph.readMorphFile will retrieve the ScannedObject\\\"! !\\n\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'tk 5/4/1998 17:34'!\\nstatsOfSubObjects: anObject\\n\\t\\\"Open a window with statistics on what objects would be written out with anObject. Does not actually write on the disk. Stats in the form:\\n\\tScriptEditorMorph 51\\n\\t\\tSortedCollection (21->LayoutMorph 15->SimpleButtonMorph 9->Array 4->CompoundTileMorph 2->StringMorph )\\\"\\n\\n\\t| dummy printOut |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\t\\\"(dummy references) is the raw data\\\"\\n\\tprintOut _ dummy statisticsOfRefs.\\n\\t(StringHolder new contents: printOut) \\n\\t\\topenLabel: 'ReferenceStream statistics'.! !\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'RAA 7/9/2000 05:35'!\\nstreamedRepresentationOf: anObject\\n\\n\\t| file |\\n\\tfile _ (RWBinaryOrTextStream on: (ByteArray new: 5000)).\\n\\tfile binary.\\n\\t(self on: file) nextPut: anObject.\\n\\tfile close.\\n\\t^file contents! !\\n\\n!SmartRefStream class methodsFor: 'utilities' stamp: 'tk 5/4/1998 17:34'!\\ntallyOfSubObjects: anObject\\n\\t\\\"Open a window with statistics on what objects would be written out with anObject. Does not actually write on the disk. Stats are simply the number of instances of each class:\\n\\t1450->Point 835->Rectangle 549->Array 300->String\\\"\\n\\n\\t| dummy bag |\\n\\tdummy _ ReferenceStream on: (DummyStream on: nil).\\n\\t\\t\\\"Write to a fake Stream, not a file\\\"\\n\\t\\\"Collect all objects\\\"\\n\\tdummy rootObject: anObject.\\t\\\"inform him about the root\\\"\\n\\tdummy nextPut: anObject.\\n\\tbag _ Bag new.\\n\\tdummy references keysDo: [:key | bag add: key class name].\\n\\t\\\"(bag sortedCounts) is the SortedCollection\\\"\\n\\t(StringHolder new contents: bag sortedCounts printString) \\n\\t\\topenLabel: 'ReferenceStream statistics'.! !\\nObject subclass: #Socket\\n\\tinstanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore primitiveOnlySupportsOneSemaphore'\\n\\tclassVariableNames: 'Connected DeadServer InvalidSocket OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!Socket commentStamp: 'gk 12/13/2005 00:43' prior: 0!\\nA Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols. Sockets are the lowest level of networking object in Squeak and are not normally used directly. SocketStream is a higher level object wrapping a Socket in a stream like protocol.\\n\\nProtocolClient and subclasses are in turn wrappers around a SocketStream to provide support for specific network protocols such as POP, NNTP, HTTP, and FTP.!\\n\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\naddress\\n\\t\\\"Shortcut\\\"\\n\\t^self localAddress! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'MU 11/26/2003 16:53'!\\nlocalAddress\\n\\tself isWaitingForConnection\\n\\t\\tifFalse: [[self waitForConnectionFor: Socket standardTimeout]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | ^ ByteArray new: 4]].\\n\\t^ self primSocketLocalAddress: socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'MU 11/26/2003 16:53'!\\nlocalPort\\n\\tself isWaitingForConnection\\n\\t\\tifFalse: [[self waitForConnectionFor: Socket standardTimeout]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | ^ 0]].\\n\\t^ self primSocketLocalPort: socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 3/13/98 12:11'!\\npeerName\\n\\t\\\"Return the name of the host I'm connected to, or nil if its name isn't known to the domain name server or the request times out.\\\"\\n\\t\\\"Note: Slow. Calls the domain name server, taking up to 20 seconds to time out. Even when sucessful, delays of up to 13 seconds have been observed during periods of high network load.\\\" \\n\\n\\t^ NetNameResolver\\n\\t\\tnameForAddress: self remoteAddress\\n\\t\\ttimeout: 20\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 4/30/1999 04:25'!\\nport\\n\\t\\\"Shortcut\\\"\\n\\t^self localPort! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 6/5/2000 10:12'!\\nprimitiveOnlySupportsOneSemaphore\\n\\t^primitiveOnlySupportsOneSemaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nreadSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^readSemaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremoteAddress\\n\\n\\t^ self primSocketRemoteAddress: socketHandle\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'jm 9/17/97 14:34'!\\nremotePort\\n\\n\\t^ self primSocketRemotePort: socketHandle\\n! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/9/2000 15:32'!\\nsemaphore\\n\\t^semaphore! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'ar 7/16/1999 17:22'!\\nsocketHandle\\n\\t^socketHandle! !\\n\\n!Socket methodsFor: 'accessing' stamp: 'JMM 5/22/2000 22:49'!\\nwriteSemaphore\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue: [^semaphore].\\n\\t^writeSemaphore! !\\n\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'bolot 7/16/1999 14:36'!\\naccept\\n\\t\\\"Accept a connection from the receiver socket.\\n\\tReturn a new socket that is connected to the client\\\"\\n\\t^Socket acceptFrom: self.! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 9/11/97 20:29'!\\nclose\\n\\t\\\"Close this connection gracefully. For TCP, this sends a close request, but the stream remains open until the other side also closes it.\\\"\\n\\n\\tself primSocketCloseConnection: socketHandle. \\\"close this end\\\"\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 11/4/97 07:15'!\\ncloseAndDestroy\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tself closeAndDestroy: 20.\\n\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'gk 12/13/2005 00:05'!\\ncloseAndDestroy: timeoutSeconds\\n\\t\\\"First, try to close this connection gracefully. If the close attempt fails or times out, abort the connection. In either case, destroy the socket. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil\\n\\t\\tifFalse: [\\n\\t\\t\\tself isConnected ifTrue: [\\n\\t\\t\\t\\tself close. \\\"close this end\\\"\\n\\t\\t\\t\\t(self waitForDisconnectionFor: timeoutSeconds)\\n\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\\"The other end didn't close so we just abort the connection\\\"\\n\\t\\t\\t\\t\\t\\tself primSocketAbortConnection: socketHandle]].\\n\\t\\t\\tself destroy].\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/9/2003 18:13'!\\nconnectNonBlockingTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address. This operation will return immediately; follow it with waitForConnectionUntil: to wait until the connection is established.\\\"\\n\\n\\t| status |\\n\\tself initializeNetwork.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before opening a new connection'].\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/15/2003 18:29'!\\nconnectTo: hostAddress port: port\\n\\t\\\"Initiate a connection to the given port at the given host address.\\n\\tWaits until the connection is established or time outs.\\\"\\n\\n\\tself connectTo: hostAddress port: port waitForConnectionFor: Socket standardTimeout! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mu 8/14/2003 15:15'!\\nconnectTo: hostAddress port: port waitForConnectionFor: timeout \\n\\t\\\"Initiate a connection to the given port at the given host \\n\\taddress. Waits until the connection is established or time outs.\\\"\\n\\tself connectNonBlockingTo: hostAddress port: port.\\n\\tself\\n\\t\\twaitForConnectionFor: timeout\\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to '\\n\\t\\t\\t\\t\\t, (NetNameResolver stringFromAddress: hostAddress) , ':' , port asString]! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 5/8/2003 16:03'!\\nconnectToHostNamed: hostName port: portNumber\\n\\t| serverIP |\\n\\tserverIP _ NetNameResolver addressForName: hostName timeout: 20.\\n\\t^self connectTo: serverIP port: portNumber\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'jm 3/10/98 11:56'!\\ndisconnect\\n\\t\\\"Break this connection, no matter what state it is in. Data that has been sent but not received will be lost.\\\"\\n\\n\\tself primSocketAbortConnection: socketHandle.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 16:25'!\\nlistenOn: port\\n\\t\\\"Listen for a connection on the given port. This operation will return immediately; follow it with waitForConnectionUntil: to wait until a connection is established.\\\"\\n\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\n\\tself primSocket: socketHandle listenOn: port.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 16:25'!\\nlistenOn: portNumber backlogSize: backlog\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog.\\n! !\\n\\n!Socket methodsFor: 'connection open/close' stamp: 'ikp 9/1/2003 20:32'!\\nlistenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Listen for a connection on the given port.\\n\\tIf this method succeeds, #accept may be used to establish a new connection\\\"\\n\\t| status |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t(status == Unconnected)\\n\\t\\tifFalse: [InvalidSocketStatusException signal: 'Socket status must Unconnected before listening for a new connection'].\\n\\tself primSocket: socketHandle listenOn: portNumber backlogSize: backlog interface: ifAddr.\\n! !\\n\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 6/7/2000 14:58'!\\nreceiveDataInto: aStringOrByteArray fromHost: hostAddress port: portNumber\\n\\t| datagram |\\n\\t\\\"Receive a UDP packet from the given hostAddress/portNumber, storing the data in the given buffer, and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self receiveDataInto: aStringOrByteArray].\\n\\t[true] whileTrue: \\n\\t\\t[datagram _ self receiveUDPDataInto: aStringOrByteArray.\\n\\t\\t((datagram at: 2) = hostAddress and: [(datagram at: 3) = portNumber]) \\n\\t\\t\\tifTrue: [^datagram at: 1]\\n\\t\\t\\tifFalse: [^0]]! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 6/3/2000 21:54'!\\nreceiveUDPDataInto: aStringOrByteArray\\n\\t\\\"Receive UDP data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data. What is returned is an array, the first element is the bytes read, the second the sending bytearray address, the third the senders port, the fourth, true if more of the datagram awaits reading\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveUDPDataInto: aStringOrByteArray\\n\\t\\tstartingAt: 1\\n\\t\\tcount: aStringOrByteArray size\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'JMM 5/25/2000 00:05'!\\nsendData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\n\\tprimitiveOnlySupportsOneSemaphore ifTrue:\\n\\t\\t[self setPeer: hostAddress port: portNumber.\\n\\t\\t^self sendData: aStringOrByteArray].\\n\\t^self sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'mir 5/15/2003 18:34'!\\nsendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber\\n\\t\\\"Send a UDP packet containing the given data to the specified host/port.\\\"\\n\\t| bytesToSend bytesSent count |\\n\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneFor: 20)\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendUDPData: aStringOrByteArray\\n\\t\\t\\ttoHost: hostAddress\\n\\t\\t\\tport: portNumber\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: bytesToSend - bytesSent.\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPeer: hostAddress port: port\\n\\t\\\"Set the default send/recv address.\\\"\\n\\n\\tself primSocket: socketHandle connectTo: hostAddress port: port.\\n! !\\n\\n!Socket methodsFor: 'datagrams' stamp: 'ar 4/30/1999 04:29'!\\nsetPort: port\\n\\t\\\"Associate a local port number with a UDP socket. Not applicable to TCP sockets.\\\"\\n\\n\\tself primSocket: socketHandle setPort: port.\\n! !\\n\\n\\n!Socket methodsFor: 'finalization' stamp: 'JMM 5/22/2000 22:52'!\\nfinalize\\n\\tself primSocketDestroyGently: socketHandle.\\n\\tSmalltalk unregisterExternalObject: semaphore.\\n\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n! !\\n\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:47'!\\nacceptFrom: aSocket\\n\\t\\\"Initialize a new socket handle from an accept call\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _ self primAcceptFrom: aSocket socketHandle\\n\\t\\t\\t\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\t\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\t\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\t\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\t\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 22:54'!\\ndestroy\\n\\t\\\"Destroy this socket. Its connection, if any, is aborted and its resources are freed. Do nothing if the socket has already been destroyed (i.e., if its socketHandle is nil).\\\"\\n\\n\\tsocketHandle = nil ifFalse: \\n\\t\\t[self isValid ifTrue: [self primSocketDestroy: socketHandle].\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\tsocketHandle _ nil.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil.\\n\\t\\tself unregister].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'JMM 5/22/2000 23:04'!\\ninitialize: socketType\\n\\t\\\"Initialize a new socket handle. If socket creation fails, socketHandle will be set to nil.\\\"\\n\\t| semaIndex readSemaIndex writeSemaIndex |\\n\\n\\tprimitiveOnlySupportsOneSemaphore _ false.\\n\\tsemaphore _ Semaphore new.\\n\\treadSemaphore _ Semaphore new.\\n\\twriteSemaphore _ Semaphore new.\\n\\tsemaIndex _ Smalltalk registerExternalObject: semaphore.\\n\\treadSemaIndex _ Smalltalk registerExternalObject: readSemaphore.\\n\\twriteSemaIndex _ Smalltalk registerExternalObject: writeSemaphore.\\n\\tsocketHandle _\\n\\t\\tself primSocketCreateNetwork: 0\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: 8000\\n\\t\\t\\tsendBufSize: 8000\\n\\t\\t\\tsemaIndex: semaIndex\\n\\t\\t\\treadSemaIndex: readSemaIndex\\n\\t\\t\\twriteSemaIndex: writeSemaIndex.\\n\\n\\tsocketHandle = nil ifTrue: [ \\\"socket creation failed\\\"\\n\\t\\tSmalltalk unregisterExternalObject: semaphore.\\n\\t\\tSmalltalk unregisterExternalObject: readSemaphore.\\n\\t\\tSmalltalk unregisterExternalObject: writeSemaphore.\\n\\t\\treadSemaphore _ writeSemaphore _ semaphore _ nil\\n\\t] ifFalse:[self register].\\n! !\\n\\n!Socket methodsFor: 'initialize-destroy' stamp: 'mir 2/22/2002 15:48'!\\ninitializeNetwork\\n\\tself class initializeNetwork! !\\n\\n\\n!Socket methodsFor: 'other' stamp: 'mir 2/22/2002 16:25'!\\ngetOption: aName \\n\\t\\\"Get options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is an status number (0 ok, -1 read only option)\\n\\telement two is the resulting of the requested option\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [InvalidSocketStatusException signal: 'Socket status must valid before getting an option'].\\n\\t^self primSocket: socketHandle getOption: aName\\n\\n\\\"| foo options |\\nSocket initializeNetwork.\\nfoo _ Socket newTCP.\\nfoo connectTo: (NetNameResolver addressFromString: '192.168.1.1') port: 80.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\noptions _ {\\n'SO_DEBUG'. 'SO_REUSEADDR'. 'SO_REUSEPORT'. 'SO_DONTROUTE'.\\n'SO_BROADCAST'. 'SO_SNDBUF'. 'SO_RCVBUF'. 'SO_KEEPALIVE'.\\n'SO_OOBINLINE'. 'SO_PRIORITY'. 'SO_LINGER'. 'SO_RCVLOWAT'.\\n'SO_SNDLOWAT'. 'IP_TTL'. 'IP_HDRINCL'. 'IP_RCVOPTS'.\\n'IP_RCVDSTADDR'. 'IP_MULTICAST_IF'. 'IP_MULTICAST_TTL'.\\n'IP_MULTICAST_LOOP'. 'UDP_CHECKSUM'. 'TCP_MAXSEG'.\\n'TCP_NODELAY'. 'TCP_ABORT_THRESHOLD'. 'TCP_CONN_NOTIFY_THRESHOLD'. \\n'TCP_CONN_ABORT_THRESHOLD'. 'TCP_NOTIFY_THRESHOLD'.\\n'TCP_URGENT_PTR_TYPE'}.\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\nfoo _ Socket newUDP.\\nfoo setPeer: (NetNameResolver addressFromString: '192.168.1.9') port: 7.\\nfoo waitForConnectionUntil: (Socket standardDeadline).\\n\\n1 to: options size do: [:i | | fum |\\n\\tfum _foo getOption: (options at: i).\\n\\tTranscript show: (options at: i),fum printString;cr].\\n\\\"! !\\n\\n!Socket methodsFor: 'other' stamp: 'mir 2/22/2002 16:30'!\\nsetOption: aName value: aValue \\n\\t| value |\\n\\t\\\"setup options on this socket, see Unix man pages for values for \\n\\tsockets, IP, TCP, UDP. IE SO_KEEPALIVE\\n\\treturns an array, element one is the error number\\n\\telement two is the resulting of the negotiated value.\\n\\tSee getOption for list of keys\\\"\\n\\n\\t(socketHandle == nil or: [self isValid not])\\n\\t\\tifTrue: [InvalidSocketStatusException signal: 'Socket status must valid before setting an option'].\\n\\tvalue _ aValue asString.\\n\\taValue == true ifTrue: [value _ '1'].\\n\\taValue == false ifTrue: [value _ '0'].\\n\\t^ self primSocket: socketHandle setOption: aName value: value! !\\n\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept' module: 'SocketPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:55'!\\nprimAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"Create and return a new socket handle based on accepting the connection from the given listening socket\\\"\\n\\t<primitive: 'primitiveSocketAccept3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^self primAcceptFrom: aHandle receiveBufferSize: rcvBufSize sendBufSize: sndBufSize semaIndex: semaIndex ! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID connectTo: hostAddress port: port\\n\\t\\\"Attempt to establish a connection to the given port of the given host. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectToPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 21:48'!\\nprimSocket: socketID getOption: aString \\n\\t\\\"Get some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the option value\\\"\\n\\n\\t<primitive: 'primitiveSocketGetOptions' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID listenOn: port\\n\\t\\\"Listen for a connection on the given port. This is an asynchronous call; query the socket status to discover if and when the connection is actually completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ikp 9/1/2003 20:33'!\\nprimSocket: aHandle listenOn: portNumber backlogSize: backlog interface: ifAddr\\n\\t\\\"Primitive. Set up the socket to listen on the given port.\\n\\tWill be used in conjunction with #accept only.\\\"\\n\\t<primitive: 'primitiveSocketListenOnPortBacklogInterface' module: 'SocketPlugin'>\\n\\tself destroy. \\\"Accept not supported so clean up\\\"! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID receiveDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. Return the number of bytes read or zero if no data is available.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/24/2000 17:19'!\\nprimSocket: socketID receiveUDPDataInto: aStringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Receive data from the given socket into the given array starting at the given index. \\n\\tReturn an Array containing the amount read, the host address byte array, the host port, and the more flag\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID sendData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/25/2000 00:08'!\\nprimSocket: socketID sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber startIndex: startIndex count: count\\n\\t\\\"Send data to the remote host through the given socket starting with the given byte index of the given byte array. The data sent is 'pushed' immediately. Return the number of bytes of data actually sent; any remaining data should be re-submitted for sending after the current send operation has completed.\\\"\\n\\t\\\"Note: In general, it many take several sendData calls to transmit a large data array since the data is sent in send-buffer-sized chunks. The size of the send buffer is determined when the socket is created.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendUDPDataBufCount' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 7/18/2000 11:42'!\\nprimSocket: socketID setOption: aString value: aStringValue\\n\\t\\\"Set some option information on this socket. Refer to the UNIX \\n\\tman pages for valid SO, TCP, IP, UDP options. In case of doubt\\n\\trefer to the source code.\\n\\tTCP_NODELAY, SO_KEEPALIVE are valid options for example\\n\\treturns an array containing the error code and the negotiated value\\\"\\n\\n\\t<primitive: 'primitiveSocketSetOptions' module: 'SocketPlugin'>\\n\\t^nil! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocket: socketID setPort: port\\n\\t\\\"Set the local port associated with a UDP socket.\\n\\tNote: this primitive is overloaded. The primitive will not fail on a TCP socket, but\\n\\tthe effects will not be what was desired. Best solution would be to split Socket into\\n\\ttwo subclasses, TCPSocket and UDPSocket.\\\"\\n\\n\\t<primitive: 'primitiveSocketListenWithOrWithoutBacklog' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketAbortConnection: socketID\\n\\t\\\"Terminate the connection on the given port immediately without going through the normal close sequence. This is an asynchronous call; query the socket status to discover if and when the connection is actually terminated.\\\"\\n\\n\\t<primitive: 'primitiveSocketAbortConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCloseConnection: socketID\\n\\t\\\"Close the connection on the given port. The remote end is informed that this end has closed and will do no further sends. This is an asynchronous call; query the socket status to discover if and when the connection is actually closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCloseConnection' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketConnectionStatus: socketID\\n\\t\\\"Return an integer reflecting the connection status of this socket. For a list of possible values, see the comment in the 'initialize' method of this class. If the primitive fails, return a status indicating that the socket handle is no longer valid, perhaps because the Squeak image was saved and restored since the socket was created. (Sockets do not survive snapshots.)\\\"\\n\\n\\t<primitive: 'primitiveSocketConnectionStatus' module: 'SocketPlugin'>\\n\\t^ InvalidSocket\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex\\n\\t\\\"Return a new socket handle for a socket of the given type and buffer sizes. Return nil if socket creation fails.\\n\\tThe netType parameter is platform dependent and can be used to encode both the protocol type (IP, Xerox XNS, etc.) and/or the physical network interface to use if this host is connected to multiple networks. A zero netType means to use IP protocols and the primary (or only) network interface.\\n\\tThe socketType parameter specifies:\\n\\t\\t0\\treliable stream socket (TCP if the protocol is IP)\\n\\t\\t1\\tunreliable datagram socket (UDP if the protocol is IP)\\n\\tThe buffer size parameters allow performance to be tuned to the application. For example, a larger receive buffer should be used when the application expects to be receiving large amounts of data, especially from a host that is far away. These values are considered requests only; the underlying implementation will ensure that the buffer sizes actually used are within allowable bounds. Note that memory may be limited, so an application that keeps many sockets open should use smaller buffer sizes. Note the macintosh implementation ignores this buffer size. Also see setOption to get/set socket buffer sizes which allows you to set/get the current buffer sizes for reading and writing.\\n \\tIf semaIndex is > 0, it is taken to be the index of a Semaphore in the external objects array to be associated with this socket. This semaphore will be signalled when the socket status changes, such as when data arrives or a send completes. All processes waiting on the semaphore will be awoken for each such event; each process must then query the socket state to figure out if the conditions they are waiting for have been met. For example, a process waiting to send some data can see if the last send has completed.\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate' module: 'SocketPlugin'>\\n\\t^ nil \\\"socket creation failed\\\"\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'JMM 5/22/2000 22:48'!\\nprimSocketCreateNetwork: netType type: socketType receiveBufferSize: rcvBufSize sendBufSize: sendBufSize semaIndex: semaIndex readSemaIndex: aReadSema writeSemaIndex: aWriteSema\\n\\t\\\"See comment in primSocketCreateNetwork: with one semaIndex. However you should know that some implementations\\n\\tignore the buffer size and this interface supports three semaphores, one for open/close/listen and the other two for\\n\\treading and writing\\\"\\n\\n\\t<primitive: 'primitiveSocketCreate3Semaphores' module: 'SocketPlugin'>\\n\\tprimitiveOnlySupportsOneSemaphore _ true.\\n\\t^ self primSocketCreateNetwork: netType\\n\\t\\t\\ttype: socketType\\n\\t\\t\\treceiveBufferSize: rcvBufSize\\n\\t\\t\\tsendBufSize: sendBufSize\\n\\t\\t\\tsemaIndex: semaIndex! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroy: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketDestroyGently: socketID\\n\\t\\\"Release the resources associated with this socket. If a connection is open, it is aborted.\\n\\tDo not fail if the receiver is already closed.\\\"\\n\\n\\t<primitive: 'primitiveSocketDestroy' module: 'SocketPlugin'>\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketError: socketID\\n\\t\\\"Return an integer encoding the most recent error on this socket. Zero means no error.\\\"\\n\\n\\t<primitive: 'primitiveSocketError' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalAddress: socketID\\n\\t\\\"Return the local host address for this socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketLocalPort: socketID\\n\\t\\\"Return the local port for this socket, or zero if no port has yet been assigned.\\\"\\n\\n\\t<primitive: 'primitiveSocketLocalPort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketReceiveDataAvailable: socketID\\n\\t\\\"Return true if data may be available for reading from the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketReceiveDataAvailable' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemoteAddress: socketID\\n\\t\\\"Return the remote host address for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemoteAddress' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketRemotePort: socketID\\n\\t\\\"Return the remote port for this socket, or zero if no connection has been made.\\\"\\n\\n\\t<primitive: 'primitiveSocketRemotePort' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!Socket methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSocketSendDone: socketID\\n\\t\\\"Return true if there is no send in progress on the current socket.\\\"\\n\\n\\t<primitive: 'primitiveSocketSendDone' module: 'SocketPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n\\n!Socket methodsFor: 'printing' stamp: 'jm 11/23/1998 11:57'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '[', self statusString, ']'.\\n! !\\n\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\ndataAvailable\\n\\t\\\"Return true if this socket has unread received data.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketReceiveDataAvailable: socketHandle\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:52'!\\nisConnected\\n\\t\\\"Return true if this socket is connected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Connected\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:15'!\\nisOtherEndClosed\\n\\t\\\"Return true if this socket had the other end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == OtherEndClosed\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/5/2000 12:17'!\\nisThisEndClosed\\n\\t\\\"Return true if this socket had the this end closed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == ThisEndClosed\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnected\\n\\t\\\"Return true if this socket's state is Unconnected.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == Unconnected\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisUnconnectedOrInvalid\\n\\t\\\"Return true if this socket is completely disconnected or is invalid.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ true].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ (status = Unconnected) | (status = InvalidSocket)\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:51'!\\nisValid\\n\\t\\\"Return true if this socket contains a valid, non-nil socket handle.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t^ status ~= InvalidSocket\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nisWaitingForConnection\\n\\t\\\"Return true if this socket is waiting for a connection.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ (self primSocketConnectionStatus: socketHandle) == WaitingForConnection\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:54'!\\nsendDone\\n\\t\\\"Return true if the most recent send operation on this socket has completed.\\\"\\n\\n\\tsocketHandle == nil ifTrue: [^ false].\\n\\t^ self primSocketSendDone: socketHandle\\n! !\\n\\n!Socket methodsFor: 'queries' stamp: 'JMM 5/8/2000 23:24'!\\nsocketError\\n\\t^self primSocketError: socketHandle! !\\n\\n!Socket methodsFor: 'queries' stamp: 'jm 2/25/1999 13:56'!\\nstatusString\\n\\t\\\"Return a string describing the status of this socket.\\\"\\n\\n\\t| status |\\n\\tsocketHandle == nil ifTrue: [^ 'destroyed'].\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tstatus = InvalidSocket ifTrue: [^ 'invalidSocketHandle'].\\n\\tstatus = Unconnected ifTrue: [^ 'unconnected'].\\n\\tstatus = WaitingForConnection ifTrue: [^ 'waitingForConnection'].\\n\\tstatus = Connected ifTrue: [^ 'connected'].\\n\\tstatus = OtherEndClosed ifTrue: [^ 'otherEndClosedButNotThisEnd'].\\n\\tstatus = ThisEndClosed ifTrue: [^ 'thisEndClosedButNotOtherEnd'].\\n\\t^ 'unknown socket status'\\n! !\\n\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 12/14/2005 10:02'!\\ndiscardReceivedData\\n\\t\\\"Discard any data received up until now, and return the number of bytes discarded.\\\"\\n\\n\\t| buf totalBytesDiscarded |\\n\\tbuf _ String new: 10000.\\n\\ttotalBytesDiscarded _ 0.\\n\\t[self isConnected] whileTrue: [\\n\\t\\ttotalBytesDiscarded _\\n\\t\\t\\ttotalBytesDiscarded + (self receiveDataInto: buf)].\\n\\t^ totalBytesDiscarded\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:52'!\\nreceiveAvailableData\\n\\t\\\"Receive all available data (if any). Do not wait.\\\"\\n \\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveAvailableDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'yo 10/10/2005 18:47'!\\nreceiveAvailableDataIntoBuffer: buffer\\n\\t\\\"Receive all available data (if any). Do not wait.\\\"\\n \\n\\t| bytesRead |\\n\\tbytesRead _ self receiveAvailableDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:52'!\\nreceiveAvailableDataInto: buffer\\n\\t\\\"Receive all available data into the given buffer and return the number of bytes received.\\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tDo not wait for data.\\\"\\n\\n\\t^self receiveAvailableDataInto: buffer startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mu 8/9/2003 18:04'!\\nreceiveAvailableDataInto: buffer startingAt: startIndex\\n\\t\\\"Receive all available data into the given buffer and return the number of bytes received.\\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tDo not wait for data.\\\"\\n\\n\\t| bufferPos bytesRead |\\n\\tbufferPos := startIndex.\\n\\t[self dataAvailable\\n\\t\\tand: [bufferPos-1 < buffer size]] \\n\\t\\twhileTrue: [\\n\\t\\t\\tbytesRead := self receiveSomeDataInto: buffer startingAt: bufferPos.\\n\\t\\t\\tbufferPos := bufferPos + bytesRead].\\n\\t^bufferPos - startIndex! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:05'!\\nreceiveData\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:05'!\\nreceiveDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t^self receiveDataInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:12'!\\nreceiveDataInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once. The answer may be zero (indicating that no data was \\n\\tavailable before the socket closed).\\\"\\n\\n\\t| bytesRead closed |\\n\\tbytesRead := 0.\\n\\tclosed := false.\\n\\t[closed not and: [bytesRead == 0]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tself waitForDataIfClosed: [closed := true].\\n\\t\\t\\tbytesRead := self primSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\t\\t\\tstartingAt: aNumber\\n\\t\\t\\t\\tcount: aStringOrByteArray size-aNumber+1].\\n\\t^bytesRead\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 2/9/2005 12:33'!\\nreceiveDataSignallingClosedInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data until something is read or the socket is closed, upon which\\n\\twe signal.\\\"\\n\\n\\t| bytesRead |\\n\\tbytesRead := 0.\\n\\t[bytesRead == 0]\\n\\t\\twhileTrue: [\\n\\t\\t\\tself waitForData.\\n\\t\\t\\tbytesRead := self primSocket: socketHandle\\n\\t\\t\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\t\\t\\tstartingAt: aNumber\\n\\t\\t\\t\\tcount: aStringOrByteArray size-aNumber+1].\\n\\t^bytesRead\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'gk 2/9/2005 12:24'!\\nreceiveDataSignallingTimeout: timeout into: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWait for data once for the specified nr of seconds. This method will\\n\\tthrow exceptions on timeout or the socket closing.\\\"\\n\\n\\tself waitForDataFor: timeout.\\n\\t^self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:03'!\\nreceiveDataTimeout: timeout\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataTimeout: timeout into: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:01'!\\nreceiveDataTimeout: timeout into: aStringOrByteArray \\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t^self receiveDataTimeout: timeout into: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/22/2003 23:58'!\\nreceiveDataTimeout: timeout into: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWait for data once for the specified nr of seconds. The answer may be \\n\\tzero (indicating that there was no data available within the given timeout).\\\"\\n\\n\\tself waitForDataFor: timeout ifClosed: [] ifTimedOut: [].\\n\\t^self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:18'!\\nreceiveDataWithTimeout\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveDataWithTimeoutInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 16:18'!\\nreceiveDataWithTimeoutInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\n\\tEither returns data or signals a time out or connection close.\\\"\\n\\n\\t^self receiveDataWithTimeoutInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'svp 9/23/2003 00:01'!\\nreceiveDataWithTimeoutInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. \\n\\tNote the given buffer may be only partially filled by the received data.\\n\\tWaits for data once.\\\"\\n\\n\\t^self receiveDataTimeout: Socket standardTimeout into: aStringOrByteArray startingAt: aNumber \\n! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeData\\n\\t\\\"Receive currently available data (if any). Do not wait.\\\"\\n \\n\\t| buffer bytesRead |\\n\\tbuffer _ String new: 2000.\\n\\tbytesRead _ self receiveSomeDataInto: buffer.\\n\\t^buffer copyFrom: 1 to: bytesRead! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeDataInto: aStringOrByteArray\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^self receiveSomeDataInto: aStringOrByteArray startingAt: 1! !\\n\\n!Socket methodsFor: 'receiving' stamp: 'mir 5/15/2003 13:46'!\\nreceiveSomeDataInto: aStringOrByteArray startingAt: aNumber\\n\\t\\\"Receive data into the given buffer and return the number of bytes received. Note the given buffer may be only partially filled by the received data.\\\"\\n\\n\\t^ self primSocket: socketHandle\\n\\t\\treceiveDataInto: aStringOrByteArray\\n\\t\\tstartingAt: aNumber\\n\\t\\tcount: aStringOrByteArray size-aNumber+1\\n! !\\n\\n\\n!Socket methodsFor: 'registry' stamp: 'ar 3/21/98 17:40'!\\nregister\\n\\t^self class register: self! !\\n\\n!Socket methodsFor: 'registry' stamp: 'ar 3/21/98 17:41'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 5/15/2003 18:33'!\\nsendData: aStringOrByteArray\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent.\\\"\\n\\n\\t\\\"An experimental version use on slow lines: Longer timeout and smaller writes to try to avoid spurious timeouts.\\\"\\n\\n\\t| bytesSent bytesToSend count |\\n\\tbytesToSend _ aStringOrByteArray size.\\n\\tbytesSent _ 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\t(self waitForSendDoneFor: 60)\\n\\t\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t\\tcount _ self primSocket: socketHandle\\n\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\tstartIndex: bytesSent + 1\\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 5000).\\n\\t\\tbytesSent _ bytesSent + count].\\n\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ar 7/20/1999 17:23'!\\nsendData: buffer count: n\\n\\t\\\"Send the amount of data from the given buffer\\\"\\n\\t| sent |\\n\\tsent _ 0.\\n\\t[sent < n] whileTrue:[\\n\\t\\tsent _ sent + (self sendSomeData: buffer startIndex: sent+1 count: (n-sent))].! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ls 1/5/1999 15:05'!\\nsendSomeData: aStringOrByteArray\\n\\t\\\"Send as much of the given data as possible and answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: 1\\n\\t\\tcount: aStringOrByteArray size! !\\n\\n!Socket methodsFor: 'sending' stamp: 'ls 3/3/1999 18:59'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex\\n\\t\\\"Send as much of the given data as possible starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t^ self\\n\\t\\tsendSomeData: aStringOrByteArray\\n\\t\\tstartIndex: startIndex\\n\\t\\tcount: (aStringOrByteArray size - startIndex + 1)! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 5/15/2003 18:34'!\\nsendSomeData: aStringOrByteArray startIndex: startIndex count: count\\n\\t\\\"Send up to count bytes of the given data starting at the given index. Answer the number of bytes actually sent.\\\"\\n\\t\\\"Note: This operation may have to be repeated multiple times to send a large amount of data.\\\"\\n\\n\\t| bytesSent |\\n\\t(self waitForSendDoneFor: 20)\\n\\t\\tifTrue: [\\n\\t\\t\\tbytesSent _ self primSocket: socketHandle\\n\\t\\t\\t\\tsendData: aStringOrByteArray\\n\\t\\t\\t\\tstartIndex: startIndex\\n\\t\\t\\t\\tcount: count]\\n\\t\\tifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].\\n\\t^ bytesSent\\n! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 2/19/2002 18:33'!\\nsendStreamContents: stream\\n\\t\\\"Send the data in the stream. Close the stream.\\n\\tUsefull for directly sending contents of a file without reading into memory first.\\\"\\n\\n\\tself sendStreamContents: stream checkBlock: [true]! !\\n\\n!Socket methodsFor: 'sending' stamp: 'mir 2/19/2002 18:31'!\\nsendStreamContents: stream checkBlock: checkBlock\\n\\t\\\"Send the data in the stream. Close the stream after you are done. After each block of data evaluate checkBlock and abort if it returns false.\\n\\tUsefull for directly sending contents of a file without reading into memory first.\\\"\\n\\n\\t| chunkSize buffer |\\n\\tchunkSize _ 5000.\\n\\tbuffer _ ByteArray new: chunkSize.\\n\\tstream binary.\\n\\t[[stream atEnd and: [checkBlock value]]\\n\\t\\twhileFalse: [\\n\\t\\t\\tbuffer _ stream next: chunkSize into: buffer.\\n\\t\\t\\tself sendData: buffer]]\\n\\t\\tensure: [stream close]! !\\n\\n\\n!Socket methodsFor: 'waiting' stamp: 'mu 8/9/2003 15:17'!\\nwaitForAcceptFor: timeout\\n\\t\\\"Wait and accept an incoming connection. Return nil if it falis\\\"\\n\\t[self waitForConnectionFor: timeout] on: ConnectionTimedOut do: [:ex | ^nil].\\n\\t^self isConnected\\n\\t\\tifTrue:[self accept]\\n\\t\\t! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:23'!\\nwaitForAcceptFor: timeout ifTimedOut: timeoutBlock\\n\\t\\\"Wait and accept an incoming connection\\\"\\n\\tself waitForConnectionFor: timeout ifTimedOut: [^timeoutBlock value].\\n\\t^self accept! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'mu 8/19/2003 02:57'!\\nwaitForConnectionFor: timeout\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t^self \\n\\t\\twaitForConnectionFor: timeout \\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Failed to connect in ', timeout asString, ' seconds']\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'gk 12/15/2005 01:09'!\\nwaitForConnectionFor: timeout ifTimedOut: timeoutBlock\\n\\t\\\"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not.\\\"\\n\\n\\t| status deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\t[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]\\n\\t\\twhileTrue: [\\n\\t\\t\\tsemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\tstatus = Connected ifFalse: [^timeoutBlock value]\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 9/23/2003 00:09'!\\nwaitForData\\n\\t\\\"Wait for data to arrive. This method will block until\\n\\tdata is available or the socket is closed. If the socket is closed\\n\\ta ConnectionClosed exception will be signaled.\\\"\\n\\n\\t^self waitForDataIfClosed:\\n\\t\\t[ConnectionClosed signal: 'Connection close while waiting for data.']! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:18'!\\nwaitForDataFor: timeout\\n\\t\\\"Wait for the given nr of seconds for data to arrive.\\n\\tSignal a time out or connection close exception if either happens before data becomes available.\\\"\\n\\n\\t^self\\n\\t\\twaitForDataFor: timeout\\n\\t\\tifClosed: [ConnectionClosed signal: 'Connection closed while waiting for data.']\\n\\t\\tifTimedOut: [ConnectionTimedOut signal: 'Data receive timed out.']\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 7/27/2003 00:16'!\\nwaitForDataFor: timeout ifClosed: closedBlock ifTimedOut: timedOutBlock\\n\\t\\\"Wait for the given nr of seconds for data to arrive.\\\"\\n\\n\\t| deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\n\\t[Time millisecondClockValue < deadline]\\n\\t\\twhileTrue: [\\n\\t\\t\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\t\\t\\tifTrue: [^self].\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifFalse: [^closedBlock value].\\n\\t\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\tifFalse: [\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifTrue: [^timedOutBlock value]\\n\\t\\t\\t\\tifFalse: [^closedBlock value]]! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'svp 9/23/2003 00:08'!\\nwaitForDataIfClosed: closedBlock\\n\\t\\\"Wait indefinitely for data to arrive. This method will block until\\n\\tdata is available or the socket is closed.\\\"\\n\\n\\t[true]\\n\\t\\twhileTrue: [\\n\\t\\t\\t(self primSocketReceiveDataAvailable: socketHandle)\\n\\t\\t\\t\\tifTrue: [^self].\\n\\t\\t\\tself isConnected\\n\\t\\t\\t\\tifFalse: [^closedBlock value].\\n\\t\\t\\tself readSemaphore wait].\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'gk 12/14/2005 09:59'!\\nwaitForDisconnectionFor: timeout\\n\\t\\\"Wait for the given nr of seconds for the connection to be broken.\\n\\tReturn true if it is broken by the deadline, false if not.\\n\\tThe client should know the connection is really going to be closed\\n\\t(e.g., because he has called 'close' to send a close request to the other end)\\n\\tbefore calling this method.\\\"\\n\\n\\t| status deadline |\\n\\tstatus _ self primSocketConnectionStatus: socketHandle.\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\t[((status == Connected) or: [(status == ThisEndClosed)]) and:\\n\\t [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\tself discardReceivedData.\\n\\t\\tself readSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).\\n\\t\\tstatus _ self primSocketConnectionStatus: socketHandle].\\n\\n\\t^ status ~= Connected\\n! !\\n\\n!Socket methodsFor: 'waiting' stamp: 'mir 5/15/2003 18:33'!\\nwaitForSendDoneFor: timeout\\n\\t\\\"Wait up until the given deadline for the current send operation to complete. Return true if it completes by the deadline, false if not.\\\"\\n\\n\\t| sendDone deadline |\\n\\tdeadline := Socket deadlineSecs: timeout.\\n\\t[self isConnected & (sendDone _ self primSocketSendDone: socketHandle) not\\n\\t\\t\\t\\\"Connection end and final data can happen fast, so test in this order\\\"\\n\\t\\tand: [Time millisecondClockValue < deadline]] whileTrue: [\\n\\t\\t\\tself writeSemaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue)].\\n\\n\\t^ sendDone! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!Socket class methodsFor: 'class initialization' stamp: 'ar 12/12/2001 19:12'!\\ninitialize\\n\\t\\\"Socket initialize\\\"\\n\\n\\t\\\"Socket Types\\\"\\n\\tTCPSocketType _ 0.\\n\\tUDPSocketType _ 1.\\n\\n\\t\\\"Socket Status Values\\\"\\n\\tInvalidSocket _ -1.\\n\\tUnconnected _ 0.\\n\\tWaitingForConnection _ 1.\\n\\tConnected _ 2.\\n\\tOtherEndClosed _ 3.\\n\\tThisEndClosed _ 4.\\n\\n\\tRegistryThreshold _ 100. \\\"# of sockets\\\"! !\\n\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ls 9/24/1999 09:45'!\\nacceptFrom: aSocket\\n\\t^[ super new acceptFrom: aSocket ]\\n\\t\\trepeatWithGCIf: [ :sock | sock isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:15'!\\ncreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\t\\\"Note: The default creates a TCP socket\\\"\\n\\t^self tcpCreateIfFail: failBlock! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'ar 4/30/1999 04:13'!\\nnew\\n\\t\\\"Return a new, unconnected Socket. Note that since socket creation may fail, it is safer to use the method createIfFail: to handle such failures gracefully; this method is primarily for backward compatibility and may be disallowed in a future release.\\\"\\n\\t\\\"Note: The default creates a TCP socket - this is also backward compatibility.\\\"\\n\\t^self newTCP! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:48'!\\nnewTCP\\n\\t\\\"Create a socket and initialise it for TCP\\\"\\n\\tself initializeNetwork.\\n\\t^[ super new initialize: TCPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\nnewUDP\\n\\t\\\"Create a socket and initialise it for UDP\\\"\\n\\tself initializeNetwork.\\n\\t^[ super new initialize: UDPSocketType ]\\n\\t\\trepeatWithGCIf: [ :socket | socket isValid not ]! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\ntcpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tself initializeNetwork.\\n\\tsock _ super new initialize: TCPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n!Socket class methodsFor: 'instance creation' stamp: 'mir 2/22/2002 15:49'!\\nudpCreateIfFail: failBlock\\n\\t\\\"Attempt to create a new socket. If successful, return the new socket. Otherwise, return the result of evaluating the given block. Socket creation can fail if the network isn't available or if there are not sufficient resources available to create another socket.\\\"\\n\\n\\t| sock |\\n\\tself initializeNetwork.\\n\\tsock _ super new initialize: UDPSocketType.\\n\\tsock isValid ifFalse: [^ failBlock value].\\n\\t^ sock\\n! !\\n\\n\\n!Socket class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 15:01'!\\ninitializeNetwork\\n\\t\\\"Initialize the network drivers and the NetNameResolver. Do nothing if the network is already initialized.\\\"\\n\\t\\\"Note: The network must be re-initialized every time Squeak starts up, so applications that persist across snapshots should be prepared to re-initialize the network as needed. Such applications should call 'Socket initializeNetwork' before every network transaction. \\\"\\n\\n\\tNetNameResolver initializeNetwork! !\\n\\n!Socket class methodsFor: 'network initialization' stamp: 'mir 2/22/2002 14:59'!\\nprimInitializeNetwork: resolverSemaIndex\\n\\t\\\"Initialize the network drivers on platforms that need it, such as the Macintosh, and return nil if network initialization failed or the reciever if it succeeds. Since mobile computers may not always be connected to a network, this method should NOT be called automatically at startup time; rather, it should be called when first starting a networking application. It is a noop if the network driver has already been initialized. If non-zero, resolverSemaIndex is the index of a VM semaphore to be associated with the network name resolver. This semaphore will be signalled when the resolver status changes, such as when a name lookup query is completed.\\\"\\n\\t\\\"Note: some platforms (e.g., Mac) only allow only one name lookup query at a time, so a manager process should be used to serialize resolver lookup requests.\\\"\\n\\n\\t<primitive: 'primitiveInitializeNetwork' module: 'SocketPlugin'>\\n\\t^ nil \\\"return nil if primitive fails\\\"\\n! !\\n\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:40'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\t^RegistryThreshold! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 12/12/2001 19:12'!\\nregistryThreshold: aNumber\\n\\t\\\"Return the registry threshold above which socket creation may fail due to too many already open sockets. If the threshold is reached, a full GC will be issued if the creation of a socket fails.\\\"\\n\\tRegistryThreshold _ aNumber! !\\n\\n!Socket class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:22'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\n\\n\\n!Socket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:54'!\\ndeadServer\\n\\n\\t^ DeadServer! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'tk 4/9/98 15:56'!\\ndeadServer: aStringOrNil\\n\\t\\\"Keep the machine name of the most recently encoutered non-responding machine. Next time the user can move it to the last in a list of servers to try.\\\"\\n\\n\\tDeadServer _ aStringOrNil! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 18:28'!\\ndeadlineSecs: secs\\n\\t\\\"Return a deadline time the given number of seconds from now.\\\"\\n\\n\\t^ Time millisecondClockValue + (secs * 1000) truncated\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 12:13'!\\nnameForWellKnownTCPPort: portNum\\n\\t\\\"Answer the name for the given well-known TCP port number. Answer a string containing the port number if it isn't well-known.\\\"\\n\\n\\t| portList entry |\\n\\tportList _ #(\\n\\t\\t(7 'echo') (9 'discard') (13 'time') (19 'characterGenerator')\\n\\t\\t(21 'ftp') (23 'telnet') (25 'smtp')\\n\\t\\t(80 'http') (110 'pop3') (119 'nntp')).\\n\\tentry _ portList detect: [:pair | pair first = portNum] ifNone: [^ 'port-', portNum printString].\\n\\t^ entry last\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 18:30'!\\nping: hostName\\n\\t\\\"Ping the given host. Useful for checking network connectivity. The host must be running a TCP echo server.\\\"\\n\\t\\\"Socket ping: 'squeak.cs.uiuc.edu'\\\"\\n\\n\\t| tcpPort sock serverAddr startTime echoTime |\\n\\ttcpPort _ 7. \\\"7 = echo port, 13 = time port, 19 = character generator port\\\"\\n\\n\\tserverAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil ifTrue: [\\n\\t\\t^ self inform: 'Could not find an address for ', hostName].\\n\\n\\tsock _ Socket new.\\n\\tsock connectNonBlockingTo: serverAddr port: tcpPort.\\n\\t[sock waitForConnectionFor: 10]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex |\\n\\t\\t\\t(self confirm: 'Continue to wait for connection to ', hostName, '?')\\n\\t\\t\\t\\tifTrue: [ex retry]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tsock destroy.\\n\\t\\t\\t\\t\\t^ self]].\\n\\n\\tsock sendData: 'echo!!'.\\n\\tstartTime _ Time millisecondClockValue.\\n\\t[sock waitForDataFor: 15]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | (self confirm: 'Packet sent but no echo yet; keep waiting?')\\n\\t\\t\\tifTrue: [ex retry]].\\n\\techoTime _ Time millisecondClockValue - startTime.\\n\\n\\tsock destroy.\\n\\tself inform: hostName, ' responded in ', echoTime printString, ' milliseconds'.\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 2/22/2002 15:49'!\\npingPorts: portList on: hostName timeOutSecs: timeOutSecs\\n\\t\\\"Attempt to connect to each of the given sockets on the given host. Wait at most timeOutSecs for the connections to be established. Answer an array of strings indicating the available ports.\\\"\\n\\t\\\"Socket pingPorts: #(7 13 19 21 23 25 80 110 119) on: 'squeak.cs.uiuc.edu' timeOutSecs: 15\\\"\\n\\n\\t| serverAddr sockets sock deadline done unconnectedCount connectedCount waitingCount result |\\n\\tserverAddr _ NetNameResolver addressForName: hostName timeout: 10.\\n\\tserverAddr = nil ifTrue: [\\n\\t\\tself inform: 'Could not find an address for ', hostName.\\n\\t\\t^ #()].\\n\\n\\tsockets _ portList collect: [:portNum |\\n\\t\\tsock _ Socket new.\\n\\t\\tsock connectTo: serverAddr port: portNum].\\n\\n\\tdeadline _ self deadlineSecs: timeOutSecs.\\n\\tdone _ false.\\n\\t[done] whileFalse: [\\n\\t\\tunconnectedCount _ 0.\\n\\t\\tconnectedCount _ 0.\\n\\t\\twaitingCount _ 0.\\n\\t\\tsockets do: [:s |\\n\\t\\t\\ts isUnconnectedOrInvalid\\n\\t\\t\\t\\tifTrue: [unconnectedCount _ unconnectedCount + 1]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\ts isConnected ifTrue: [connectedCount _ connectedCount + 1].\\n\\t\\t\\t\\t\\ts isWaitingForConnection ifTrue: [waitingCount _ waitingCount + 1]]].\\n\\t\\twaitingCount = 0 ifTrue: [done _ true].\\n\\t\\tconnectedCount = sockets size ifTrue: [done _ true].\\n\\t\\tTime millisecondClockValue > deadline ifTrue: [done _ true]].\\n\\n\\tresult _ (sockets select: [:s | s isConnected])\\n\\t\\tcollect: [:s | self nameForWellKnownTCPPort: s remotePort].\\n\\tsockets do: [:s | s destroy].\\n\\t^ result\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'jm 1/14/1999 17:25'!\\npingPortsOn: hostName\\n\\t\\\"Attempt to connect to a set of well-known sockets on the given host, and answer the names of the available ports.\\\"\\n\\t\\\"Socket pingPortsOn: 'www.disney.com'\\\"\\n\\n\\t^ Socket\\n\\t\\tpingPorts: #(7 13 19 21 23 25 80 110 119)\\n\\t\\ton: hostName\\n\\t\\ttimeOutSecs: 20\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 16:17'!\\nstandardDeadline\\n\\t\\\"Return a default deadline time some seconds into the future.\\\"\\n\\n\\t^ self deadlineSecs: self standardTimeout\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'mir 5/15/2003 16:16'!\\nstandardTimeout\\n\\n\\t^45\\n! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardAddress\\n\\t\\\"Answer a don't-care address for use with UDP sockets.\\\"\\n\\n\\t^ByteArray new: 4\\t\\t\\\"0.0.0.0\\\"! !\\n\\n!Socket class methodsFor: 'utilities' stamp: 'ar 4/30/1999 04:21'!\\nwildcardPort\\n\\t\\\"Answer a don't-care port for use with UDP sockets. (The system will allocate an\\n\\tunused port number to the socket.)\\\"\\n\\n\\t^0! !\\n\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:18'!\\nloopbackTest\\n\\t\\\"Send data from one socket to another on the local machine.\\n\\tTests most of the socket primitives.\\\"\\n\\n\\t\\\"100 timesRepeat: [Socket loopbackTest]\\\"\\n\\n\\t| sock1 sock2 bytesToSend sendBuf receiveBuf done bytesSent bytesReceived t extraBytes packetsSent packetsRead |\\n\\tTranscript\\n\\t\\tcr;\\n\\t\\tshow: 'starting loopback test';\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: '---------- Connecting ----------';\\n\\t\\tcr.\\n\\tself initializeNetwork.\\n\\tsock1 := self new.\\n\\tsock2 := self new.\\n\\tsock1 listenOn: 54321.\\n\\tsock2 connectTo: NetNameResolver localHostAddress port: 54321.\\n\\tsock1 waitForConnectionFor: self standardTimeout.\\n\\tsock2 waitForConnectionFor: self standardTimeout.\\n\\tsock1 isConnected ifFalse: [self error: 'sock1 not connected'].\\n\\tsock2 isConnected ifFalse: [self error: 'sock2 not connected'].\\n\\tTranscript\\n\\t\\tshow: 'connection established';\\n\\t\\tcr.\\n\\tbytesToSend := 5000000.\\n\\tsendBuf := String new: 5000 withAll: $x.\\n\\treceiveBuf := String new: 50000.\\n\\tdone := false.\\n\\tpacketsSent := packetsRead := bytesSent := bytesReceived := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[done] whileFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sock1 sendDone and: [bytesSent < bytesToSend]) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsSent := packetsSent + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesSent := bytesSent + (sock1 sendSomeData: sendBuf)].\\n\\t\\t\\t\\t\\t\\t\\tsock2 dataAvailable \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[packetsRead := packetsRead + 1.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbytesReceived := bytesReceived + (sock2 receiveDataInto: receiveBuf)].\\n\\t\\t\\t\\t\\t\\t\\tdone := bytesSent >= bytesToSend and: [bytesReceived = bytesSent]]].\\n\\tTranscript\\n\\t\\tshow: 'closing connection';\\n\\t\\tcr.\\n\\tsock1 waitForSendDoneFor: self standardTimeout.\\n\\tsock1 close.\\n\\tsock2 waitForDisconnectionFor: self standardTimeout.\\n\\textraBytes := sock2 discardReceivedData.\\n\\textraBytes > 0 \\n\\t\\tifTrue: \\n\\t\\t\\t[Transcript\\n\\t\\t\\t\\tshow: ' *** received ' , extraBytes size printString , ' extra bytes ***';\\n\\t\\t\\t\\tcr].\\n\\tsock2 close.\\n\\tsock1 waitForDisconnectionFor: self standardTimeout.\\n\\tsock1 isUnconnectedOrInvalid ifFalse: [self error: 'sock1 not closed'].\\n\\tsock2 isUnconnectedOrInvalid ifFalse: [self error: 'sock2 not closed'].\\n\\tTranscript\\n\\t\\tshow: '---------- Connection Closed ----------';\\n\\t\\tcr.\\n\\tsock1 destroy.\\n\\tsock2 destroy.\\n\\tTranscript\\n\\t\\tshow: 'loopback test done; time = ' , t printString;\\n\\t\\tcr.\\n\\tTranscript\\n\\t\\tshow: (bytesToSend asFloat / t roundTo: 0.01) printString \\n\\t\\t\\t\\t\\t, '* 1000 bytes/sec';\\n\\t\\tcr.\\n\\tTranscript endEntry! !\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:03'!\\nnewAcceptCheck\\n\\t\\\"Check if the platform has support for the BSD style accept().\\\"\\n\\n\\t\\\"Socket newAcceptCheck\\\"\\n\\t\\n\\t| socket |\\n\\tself initializeNetwork.\\n\\tsocket _ self newTCP.\\n\\tsocket listenOn: 44444 backlogSize: 4.\\n\\tsocket isValid ifTrue: [\\n\\t\\tself inform: 'Everything looks OK for the BSD style accept()'\\n\\t] ifFalse: [\\n\\t\\tself inform: 'It appears that you DO NOT have support for the BSD style accept()'].\\n\\tsocket destroy! !\\n\\n!Socket class methodsFor: 'tests' stamp: 'gk 12/15/2005 01:10'!\\nsendTest\\n\\t\\\"Send data to the 'discard' socket of the given host.\\n\\tTests the speed of one-way data transfers across the\\n\\tnetwork to the given host. Note that most hosts\\n\\tdo not run a discard server.\\\"\\n\\n\\t\\\"Socket sendTest\\\"\\n\\n\\t| sock bytesToSend sendBuf bytesSent t serverName serverAddr |\\n\\tTranscript cr; show: 'starting send test'; cr.\\n\\tself initializeNetwork.\\n\\tserverName := UIManager default request: 'What is the destination server?' initialAnswer: 'create.ucsb.edu'.\\n\\tserverAddr := NetNameResolver addressForName: serverName timeout: 10.\\n\\tserverAddr = nil \\n\\t\\tifTrue: [^self inform: 'Could not find an address for ' , serverName].\\n\\tsock := self new.\\n\\tTranscript show: '---------- Connecting ----------';cr.\\n\\tsock connectTo: serverAddr port: 9.\\n\\tsock isConnected ifFalse: [\\n\\t\\tsock destroy.\\n\\t\\t^self inform: 'could not connect'].\\n\\tTranscript show: 'connection established; sending data'; cr.\\n\\tbytesToSend := 1000000.\\n\\tsendBuf := String new: 64 * 1024 withAll: $x.\\n\\tbytesSent := 0.\\n\\tt := Time millisecondsToRun: \\n\\t\\t\\t\\t\\t[[bytesSent < bytesToSend] whileTrue: \\n\\t\\t\\t\\t\\t\\t\\t[sock sendDone \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [bytesSent := bytesSent + (sock sendSomeData: sendBuf)]]].\\n\\tsock waitForSendDoneFor: self standardTimeout.\\n\\tsock destroy.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr;\\n\\t\\tshow: 'send test done; time = ' , t printString; cr;\\n\\t\\tshow: (bytesToSend asFloat / t roundTo: 0.01) printString, ' * 1000 bytes/sec';cr;endEntry! !\\nObject subclass: #SocketStream\\n\\tinstanceVariableNames: 'recentlyRead socket inBuffer outBuffer inNextToWrite outNextToWrite lastRead timeout autoFlush bufferSize binary shouldSignal'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!SocketStream commentStamp: 'md 7/14/2006 16:32' prior: 0!\\nSocketStream is a wrapper for class Socket making it easy to write networking code by giving the programmer a stream-like protocol. A Socket is a two way communication link with two logically separate channels - input and output. The Socket class is the lowest level in Squeak for network communication and using it directly can be difficult and bug prone.\\n\\nA SocketStream can be in binary or ascii mode, ascii is the default which means you are transmitting and receiving Strings. Most Internet protocols are in clear text ascii, like for example HTTP. Another setting is what timeout you want to use - default is the standardTimeout from Socket. More settings can be found in the method category 'configuration'.\\n\\nSimplest example of connecting, sending/receiving and closing:\\n\\n| stream result |\\nstream := SocketStream openConnectionToHostNamed: 'www.squeak.org' port: 80.\\n[[stream nextPutAll: 'GET / HTTP/1.0'; crlf; crlf; flush.\\nresult := stream upToEnd. \\\"Give us all data until the socket is closed.\\\"\\nTranscript show: result; cr.]\\n\\tensure: [stream close]]\\n\\t\\ton: ConnectionTimedOut\\n\\t\\tdo: [:ex | Transcript show: ex asString;cr. ex resume]\\n\\nThere are two important things to note above:\\n\\t- The methods in category \\\"stream in\\\" can signal two exceptions (unless turned off with #shouldSignal:):\\n\\t\\tConnectionClosed and ConnectionTimedOut\\n\\t- We close the stream using #ensure:, that is to make sure it isn't left opened.\\n\\t- We use #on:do: to catch any signal. In this case we do not need to catch ConnectionClosed since #upToEnd does that for us intrinsically.\\n\\n----------------\\nSocketStream (below called SS) is a reimplementation of 'Old'-SocketStream (below called OSS) - the class that originates from the original Comanche implementation but now is included in standard Squeak. SS has the same protocol as OSS and is meant to replace it. SS is faster, more flexible, is better documented and adds a few features:\\n\\n1. #shouldSignal:, which decides if SS should signal low level Socket exceptions (true) or if it should swallow them like original OSS did. Default is true. The only reason I added this is for backwards compatibility - not signalling causes problems - see bug 4 below.\\n\\n2. #nextAllInBuffer, #nextInBuffer:, #skip:, #receiveData:, #nextPutAllFlush: and #recentlyRead are new additions to the public protocol.\\n\\n\\nIt also fixes various bugs:\\n\\n1. #isDataAvailable could theoretically answer false, when there actually is some in the buffer in OSS. If #receiveDataIfAvailable reads the last byte then the following \\\"socket dataAvailable\\\" would answer false. So the last byte would be sitting in the inStream missed.\\n\\n2. #upToAll: in OSS has several problems, for example - #positionOfSubCollection:ifAbsent: which was introduced answers one position too low. This was compensated in upToAll:, but only in the pushBack: call, not the actual result being returned which was cut short 1 byte. Amusingly this makes KomHttpServer not use \\\"Keep-Alive\\\" since the last $e in 'Alive' was cut short. :)\\n\\n3. SS doesn't inherit from PositionableStream since that just breaks various inherited messages, like for example #skip:. OSS should IMHO be changed to inherit from Object - or of course, replaced in full with SS. :)\\n\\n4. Since SocketStream by default signals closes and timeouts the SocketStreamTest now passes. The reason for SocketStream to fail is that while it does timeout on a low level (#SocketStream>>receiveData doesn't hang forever) - the callers of #receiveData sometimes loop - like in #next:, and thus eliminates the timeout. SS warns about some methods (in their method comments) not honouring timeouts if shouldSignal is false, I really don't know what they should do in that case:\\n\\t#next:, #upTo:, #upToAll: and #upToEnd (and #receiveData:)\\n\\n\\nThe primary reason for the SS implementation is optimal performance. The main differences in implementation with the old OSS are:\\n\\n1. SS uses two buffers directly (inBuffer and outBuffer) with pointers marking start and stop within the buffer. OSS instead uses two regular streams, a ReadStream and a WriteStream. Using internal buffers makes it possible to avoid copying and reallocation in various ways, it also makes SS be able to have specialized growing/buffer moving behaviour.\\n\\n2. #upTo:, #upToAll: and #peekForAll: uses selectged String messages that in turn uses fast primitives for searching. OSS used other messages that fell back on byte per byte reading.\\n\\n3. #receiveData in OSS creates a temporary buffer stream for each call!! During a long read operation, like say #upToAll: (which for example is used when uploading files using HTTP POST forms), this is devastating - especially since the default size is only 2000 bytes - and leads to a very high number of low level read operations on the Socket, typically 100 times more calls than with OSS. The buffer in OSS is held in an instvar (not recreated for each call), is larger from the start and above all - grows dynamically by doubling. OSS can also avoid a grow/reallocation by doing a \\\"move down\\\" if data has been read from the SS as it comes in and through that making room in the lower part of the inBuffer. The net result is that upToAll: for large files is about 10 times faster.\\n\\n4. The implementation of upTo: and upToAll: tries to avoid doing unnecessary find operations in the buffer and is greedy by default, which means it favors reading more data - if available - before searching for the stop sequence. If we had #findString:startingAt:stoppingAt: this wouldn't have to be greedy and we wouldn't be needlessly scanning dead buffer area. VM hackers? Also, while you are at it - make it work for ByteArrays too. :)\\n\\n\\nSS can not be run unbuffered, since that seems unneeded. The option to autoFlush is still available, with it set to true SocketStream (just like OSS) will flush on its own on each nextPut:/nextPutAll:, otherwise flushing it will have to be done manually but is done on close.\\n\\nThe first performance tests shows that, as noted above, receiving large amounts of data using #upToAll: is greatly improved - factor of 10. Serving HTTP with small payloads seemed at first not be faster at all - but this is due to the high overhead of Socket connect/close and other things. Increasing payloads show a difference and especially with keep alive on - where the new SS roughly doubles the throughput!!!\\n\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:37'!\\nascii\\n\\t\\\"Tell the SocketStream to send data\\n\\tas Strings instead of ByteArrays.\\n\\tThis is default.\\\"\\n\\n\\tbinary := false.\\n\\tself resetBuffers! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:26'!\\nautoFlush\\n\\t\\\"If autoFlush is enabled data will be sent through\\n\\tthe socket (flushed) when the bufferSize is reached\\n\\tor the SocketStream is closed. Otherwise the user\\n\\twill have to send #flush manually.\\n\\tClose will always flush. Default is false.\\\"\\n\\n\\t^autoFlush! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:27'!\\nautoFlush: aBoolean\\n\\t\\\"If autoFlush is enabled data will be sent through\\n\\tthe socket (flushed) when the bufferSize is reached\\n\\tor the SocketStream is closed. Otherwise the user\\n\\twill have to send #flush manually.\\n\\tClose will always flush. Default is false.\\\"\\n\\n\\tautoFlush := aBoolean! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:37'!\\nbinary\\n\\t\\\"Tell the SocketStream to send data\\n\\tas ByteArrays instead of Strings.\\n\\tDefault is ascii.\\\"\\n\\n\\tbinary := true.\\n\\tself resetBuffers! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:28'!\\nbufferSize\\n\\t\\\"Default buffer size is 4kb.\\n\\tincreased from earlier 2000 bytes.\\\"\\n\\t\\n\\t^bufferSize! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/9/2005 22:28'!\\nbufferSize: anInt\\n\\t\\\"Default buffer size is 4kb.\\n\\tincreased from earlier 2000 bytes.\\\"\\n\\n\\tbufferSize := anInt! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:58'!\\ninBufferSize\\n\\t\\\"Answers the current size of data in the inBuffer.\\\"\\n\\n\\t^inNextToWrite - lastRead - 1! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:59'!\\nnoTimeout\\n\\t\\\"Do not use timeout.\\\"\\n\\n\\ttimeout := 0! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 17:59'!\\noutBufferSize\\n\\t\\\"Answers the current size of data in the outBuffer.\\\"\\n\\n\\t^outNextToWrite - 1! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 18:00'!\\nshouldSignal\\n\\t\\\"If shouldSignal is enabled the Socket Exceptions\\n\\tConnectionClosed and ConnectionTimedOut\\n\\twill not be swallowed. Default is true.\\n\\tFor more info, see #shouldSignal:\\\"\\n\\n\\t^shouldSignal! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/10/2005 18:03'!\\nshouldSignal: aBoolean\\n\\t\\\"If shouldSignal is enabled the Socket Exceptions\\n\\tConnectionClosed and ConnectionTimedOut will not be swallowed.\\n\\tDefault is true. And please - don't set it to false - it is better to\\n\\tuse an exception handler (see below) and several methods\\n\\tin this class will not honour timeouts (says so in their method comments).\\n\\tAlso, it is quite hard to understand what for example #upToEnd\\n\\tshould return to indicate a timeout.\\n\\t\\n\\tWrap your use of SocketStream with a handler like:\\n\\t\\n\\t[stuff _ mySocketStream next: 10]\\n\\t\\ton: ConnectionClosed, ConnectionTimedOut\\n\\t\\tdo: [:ex |\\n\\t\\t\\tTranscript show: 'Oops!! Did not get my ten bytes!!;cr]\\n\\t\\\"\\n\\n\\tshouldSignal := aBoolean! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\nsocket\\n\\t^socket! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\nsocket: aSocket\\n\\tsocket _ aSocket! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/7/2005 08:41'!\\ntimeout\\n\\t\\\"Lazily initialized unless it has been set explicitly.\\\"\\n\\n\\ttimeout ifNil: [timeout := Socket standardTimeout].\\n\\t^timeout! !\\n\\n!SocketStream methodsFor: 'configuration' stamp: 'gk 2/3/2005 20:35'!\\ntimeout: seconds\\n\\ttimeout := seconds! !\\n\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 2/24/2005 11:55'!\\nclose\\n\\t\\\"Flush any data still not sent\\n\\tand take care of the socket.\\\"\\n\\n\\tself flush.\\n\\tsocket closeAndDestroy: 30! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 9/9/2005 09:33'!\\nflush\\n\\t\\\"If the other end is connected and we have something\\n\\tto send, then we send it and reset the outBuffer.\\\"\\n\\n\\t((outNextToWrite > 1) and: [socket isOtherEndClosed not])\\n\\t\\tifTrue: [\\n\\t\\t\\t[socket sendData: outBuffer count: outNextToWrite - 1]\\n\\t\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\t\\tdo: [:ex | shouldSignal ifFalse: [\\\"swallow\\\"]].\\n\\t\\t\\toutNextToWrite _ 1]! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 4/14/2005 09:49'!\\nreceiveData: nBytes\\n\\t\\\"Keep reading the socket until we have nBytes\\n\\tin the inBuffer or we reach the end. This method\\n\\tdoes not return data, but can be used to make sure\\n\\tdata has been read into the buffer from the Socket\\n\\tbefore actually reading it from the FastSocketStream.\\n\\tMainly used internally. We could also adjust the buffer\\n\\tto the expected amount of data and avoiding several\\n\\tincremental grow operations.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal\\n\\tis false!! And frankly, I am not sure how to handle that\\n\\tcase or if I care - I think we should always signal.\\\"\\n\\n\\t[self atEnd not and: [nBytes > self inBufferSize]]\\n\\t\\twhileTrue: [self receiveData]! !\\n\\n!SocketStream methodsFor: 'control' stamp: 'gk 2/9/2005 23:08'!\\nrecentlyRead\\n\\t\\\"Return the number of bytes read\\n\\tduring the last socket operation.\\\"\\n\\t\\n\\t^recentlyRead! !\\n\\n\\n!SocketStream methodsFor: 'initialize-release' stamp: 'gk 2/25/2005 14:20'!\\ninitialize\\n\\tautoFlush _ true.\\n\\tshouldSignal _ true.\\n\\trecentlyRead _ 0.\\n\\tbufferSize _ 4096.\\n\\tself ascii! !\\n\\n\\n!SocketStream methodsFor: 'printing' stamp: 'gk 2/25/2005 14:19'!\\ndebug\\n\\t\\\"Display debug info.\\\"\\n\\n\\t| data |\\n\\tdata _ self inBufferSize.\\n\\t^String streamContents: [:s |\\n\\t\\ts\\n\\t\\t\\tnextPutAll: 'Buffer size: ', inBuffer size asString;cr;\\n\\t\\t\\tnextPutAll: 'InBuffer data size: ', data asString; cr;\\n\\t\\t\\tnextPutAll: 'In data (20):', (inBuffer copyFrom: lastRead + 1 to: lastRead + (data min: 20)); cr;\\n\\t\\t\\tnextPutAll: 'OutBuffer data size: ', (outNextToWrite - 1) asString; cr;\\n\\t\\t\\tnextPutAll: 'Out data (20):', (outBuffer copyFrom: 1 to: ((outNextToWrite - 1) min: 20)); cr]! !\\n\\n!SocketStream methodsFor: 'printing' stamp: 'md 7/14/2006 12:28'!\\nprint: anObject\\n\\tanObject printOn: self! !\\n\\n!SocketStream methodsFor: 'printing' stamp: 'gk 2/10/2005 11:44'!\\nprintOn: aStream\\n\\t\\\"Display buffer sizes.\\\"\\n\\n\\taStream nextPutAll: self class name.\\n\\tinBuffer ifNotNil: [\\n\\t\\taStream nextPutAll: '[inbuf:',\\n\\t\\t(inBuffer size / 1024) rounded asString, 'kb/outbuf:',\\n\\t\\t(outBuffer size / 1024) rounded asString, 'kb]']! !\\n\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:33'!\\nnext\\n\\t\\\"Return next byte, if inBuffer is empty\\n\\twe recieve some more data and try again.\\\"\\n\\n\\tself atEnd ifTrue: [^nil].\\n\\tself isInBufferEmpty ifTrue:\\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^nil]].\\n\\tlastRead _ lastRead + 1.\\n\\t^inBuffer at: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 21:26'!\\nnextAllInBuffer\\n\\t\\\"Return all data currently in the inBuffer,\\\"\\n\\n\\t^self nextInBuffer: inNextToWrite - lastRead - 1! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 12:51'!\\nnextInBuffer: anInteger\\n\\t\\\"Answer anInteger bytes of data at most,\\n\\tbut only from the inBuffer.\\\"\\n\\n\\t| start amount |\\n\\tamount _ anInteger min: (inNextToWrite - lastRead - 1).\\n\\tstart _ lastRead + 1.\\n\\tlastRead _ lastRead + amount.\\n\\t^inBuffer copyFrom: start to: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:17'!\\nnext: anInteger\\n\\t\\\"Answer anInteger bytes of data.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| start |\\n\\tself receiveData: anInteger.\\n\\tstart _ lastRead + 1.\\n\\tlastRead _ (lastRead + anInteger) min: inNextToWrite - 1.\\n\\t^inBuffer copyFrom: start to: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:47'!\\nnextAvailable\\n\\t\\\"Answer all the data currently available,\\n\\tin buffer or in socket.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^self nextAllInBuffer].\\n\\tself isDataAvailable ifTrue: [self receiveData].\\n\\t^self nextAllInBuffer! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 13:02'!\\nnextAvailable: howMany\\n\\t\\\"Answer all the data currently available,\\n\\tin buffer or in socket - but limited to <howMany>.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^self nextInBuffer: howMany].\\n\\tself isDataAvailable ifTrue: [self receiveData].\\n\\t^self nextInBuffer: howMany! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/3/2005 20:35'!\\nnextLine\\n\\t^self nextLineCrLf! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/24/2005 12:01'!\\nnextLineCrLf\\n\\t^self upToAll: String crlf! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\nnextLineLf\\n\\t| nextLine |\\n\\tnextLine := self upToAll: String lf.\\n\\t^nextLine! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:09'!\\npeek\\n\\t\\\"Return next byte, if inBuffer is empty\\n\\twe recieve some more data and try again.\\n\\tDo not consume the byte.\\\"\\n\\n\\tself atEnd ifTrue: [^nil].\\n\\tself isInBufferEmpty ifTrue:\\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^nil]].\\n\\t^inBuffer at: lastRead! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/7/2005 14:04'!\\npeekFor: aCharacterOrByte\\n\\t\\\"Read and return next character or byte\\n\\tif it is equal to the argument.\\n\\tOtherwise return false.\\\"\\n\\n\\t| nextObject |\\n\\tself atEnd ifTrue: [^false].\\n\\tself isInBufferEmpty ifTrue: \\n\\t\\t[self receiveData.\\n\\t\\tself atEnd ifTrue: [^false]].\\n\\tnextObject _ inBuffer at: lastRead.\\n\\tnextObject = aCharacterOrByte ifTrue: [\\n\\t\\tlastRead _ lastRead + 1.\\n\\t\\t^true].\\n\\t^false\\n! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\npeekForAll: aString\\n\\t\\\"Answer whether or not the next string of characters in the receiver\\n\\tmatches aString. If a match is made, advance over that string in the receiver and\\n\\tanswer true. If no match, then leave the receiver alone and answer false.\\n\\tWe use findString:startingAt: to avoid copying.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| sz start |\\n\\tsz _ aString size.\\n\\tself receiveData: sz.\\n\\t(inNextToWrite - lastRead - 1) < sz ifTrue: [^false].\\n\\tstart _ lastRead + 1.\\n\\t(inBuffer findString: aString startingAt: start) = start\\n\\t\\tifFalse: [^false].\\n\\tlastRead _ lastRead + sz.\\n\\t^true! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:16'!\\npeek: anInteger\\n\\t\\\"Answer anInteger bytes of data.\\n\\tDo not consume data.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\t| start |\\n\\tself receiveData: anInteger.\\n\\tstart _ lastRead + 1.\\n\\t^inBuffer copyFrom: start to: ((lastRead + anInteger) min: inNextToWrite - 1).! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:15'!\\nskip: anInteger\\n\\t\\\"Skip a number of bytes.\\n\\tThis is faster than #next: since it does not\\n\\thave to copy and return a new String or ByteArray.\\n\\n\\tNOTE: This method doesn't honor timeouts if shouldSignal is false!!\\\"\\n\\n\\tself receiveData: anInteger.\\n\\tlastRead _ (lastRead + anInteger) min: inNextToWrite - 1! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 9/9/2005 02:57'!\\nupTo: aCharacterOrByte\\n\\t\\\"Return data up to, but not including given character or byte.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\n\\t\\n\\tThis method looks a bit complicated, and this is mainly because there is no fast search method\\n\\tin String that takes a stoppingAt: argument. This means we need to ignore getting hits in the\\n\\tdead buffer area above inNextToWrite.\\n\\tAnother measure is that this implementation is greedy and will load data into the buffer\\n\\tuntil there is nothing more available, or it has loaded 100kb - and not until then we search the buffer.\\n\\n\\tA totally non greedy variant would search on every loop.\\\"\\n\\n\\t| index result lastRecentlyRead searchedSoFar |\\n\\tsearchedSoFar _ 0.\\n\\tlastRecentlyRead _ 0.\\n\\tindex _ 0.\\n\\t[self atEnd not and: [\\n\\t\\t((lastRecentlyRead = 0 and: [self isInBufferEmpty not]) or: [self inBufferSize > 100000]) ifTrue: [\\n\\t\\t\\t\\\"Data begins at lastRead + 1, we add searchedSoFar as offset.\\\"\\n\\t\\t\\tindex _ inBuffer indexOf: aCharacterOrByte startingAt: lastRead + searchedSoFar + 1.\\n\\t\\t\\tsearchedSoFar _ self inBufferSize.\\n\\t\\t\\t(index > 0 and: [(index + 1) > inNextToWrite]) ifTrue: [\\n\\t\\t\\t\\t\\\"Oops, hit in dead buffer area.\\n\\t\\t\\t\\tThis is probably due to old data, so we ignore it.\\n\\t\\t\\t\\tNo point in cleaning the dead area to avoid hits - it will still search it.\\\"\\n\\t\\t\\t\\tindex _ 0]].\\n\\t\\tindex = 0]]\\n\\t\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\t\\trecentlyRead = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"blocking call for now, we don't want to poll\\\"\\n\\t\\t\\t\\t\\t\\t\\tself receiveData]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\tself receiveAvailableData].\\n\\t\\t\\t\\t\\tlastRecentlyRead _ recentlyRead].\\n\\tindex > 0\\n\\t\\tifTrue: [\\\"found it\\\"\\n\\t\\t\\tresult _ self nextInBuffer: index - lastRead - 1.\\n\\t\\t\\tself skip: 1.\\n\\t\\t\\t^ result]\\n\\t\\tifFalse: [\\\"atEnd\\\"\\n\\t\\t\\t^ self nextAllInBuffer]! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 9/9/2005 02:55'!\\nupToAll: aStringOrByteArray\\n\\t\\\"Answer a subcollection from the current access position to the occurrence (if any, but not\\n\\tinclusive) of aStringOrByteArray. If aCollection is not in the stream, answer the entire rest of\\n\\tthe stream.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\n\\t\\n\\tThis method looks a bit complicated, and this is mainly because there is no fast search method\\n\\tin String that takes a stoppingAt: argument. This means we need to ignore getting hits in the\\n\\tdead buffer area above inNextToWrite.\\n\\tAnother measure is that this implementation is greedy and will load data into the buffer\\n\\tuntil there is nothing more available, or it has loaded 100kb - and not until then we search the buffer.\\n\\n\\tA totally non greedy variant would search on every loop.\\\"\\n\\n\\t| index sz result lastRecentlyRead searchedSoFar |\\n\\tsz _ aStringOrByteArray size.\\n\\tsearchedSoFar _ 0.\\n\\tlastRecentlyRead _ 0.\\n\\tindex _ 0.\\n\\t[self atEnd not and: [\\n\\t\\t((lastRecentlyRead = 0 and: [self isInBufferEmpty not]) or: [self inBufferSize > 100000]) ifTrue: [\\n\\t\\t\\t\\\"Data begins at lastRead + 1, we add searchedSoFar as offset and backs up sz - 1\\n\\t\\t\\tso that we can catch any borderline hits.\\\"\\n\\t\\t\\tindex _ inBuffer indexOfSubCollection: aStringOrByteArray\\n\\t\\t\\t\\t\\t\\tstartingAt: lastRead + searchedSoFar - sz + 2.\\n\\t\\t\\tsearchedSoFar _ self inBufferSize.\\n\\t\\t\\t(index > 0 and: [(index + sz) > inNextToWrite]) ifTrue: [\\n\\t\\t\\t\\t\\\"Oops, hit partially or completely in dead buffer area.\\n\\t\\t\\t\\tThis is probably due to old data, so we ignore it.\\n\\t\\t\\t\\tNo point in cleaning the dead area to avoid hits - it will still search it.\\\"\\n\\t\\t\\t\\tindex _ 0]].\\n\\t\\tindex = 0]]\\n\\t\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\t\\trecentlyRead = 0\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"blocking call for now, we don't want to poll\\\"\\n\\t\\t\\t\\t\\t\\t\\tself receiveData]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\t\\t\\tself receiveAvailableData].\\n\\t\\t\\t\\t\\tlastRecentlyRead _ recentlyRead].\\n\\tindex > 0\\n\\t\\tifTrue: [\\\"found it\\\"\\n\\t\\t\\tresult _ self nextInBuffer: index - lastRead - 1.\\n\\t\\t\\tself skip: sz.\\n\\t\\t\\t^ result]\\n\\t\\tifFalse: [\\\"atEnd\\\"\\n\\t\\t\\t^ self nextAllInBuffer]! !\\n\\n!SocketStream methodsFor: 'stream in' stamp: 'gk 2/15/2005 14:14'!\\nupToEnd\\n\\t\\\"Answer all data coming in on the socket until the socket\\n\\tis closed by the other end, or we get a timeout.\\n\\tThis means this method catches ConnectionClosed by itself.\\n\\t\\n\\tNOTE: Does not honour timeouts if shouldSignal is false!!\\\"\\n\\n\\t[[self atEnd] whileFalse: [self receiveData]]\\n\\t\\ton: ConnectionClosed\\n\\t\\tdo: [:ex | \\\"swallow it\\\"]. \\n\\t^self nextAllInBuffer! !\\n\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\ncr\\n\\tself nextPutAll: String cr! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\ncrlf\\n\\tself nextPutAll: String crlf! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/10/2005 11:14'!\\nnextPutAllFlush: aCollection\\n\\t\\\"Put a String or a ByteArray onto the stream.\\n\\tYou can use this if you have very large data - it avoids\\n\\tcopying into the buffer (and avoids buffer growing)\\n\\tand also flushes any other pending data first.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [aCollection asByteArray] ifFalse: [aCollection asString].\\n\\tself flush. \\\"first flush pending stuff, then directly send\\\"\\n\\tsocket isOtherEndClosed ifFalse: [\\n\\t\\t[socket sendData: toPut count: toPut size]\\n\\t\\t\\ton: ConnectionTimedOut\\n\\t\\t\\tdo: [:ex | shouldSignal ifFalse: [\\\"swallow\\\"]]]! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'md 2/24/2006 19:51'!\\nnextPut: char\\n\\t\\\"Put a single Character or byte onto the stream.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [char asInteger] ifFalse: [char asCharacter].\\n\\tself adjustOutBuffer: 1.\\n\\toutBuffer at: outNextToWrite put: toPut.\\n\\toutNextToWrite _ outNextToWrite + 1.\\n\\tself checkFlush.\\n\\t\\\"return the argument - added by kwl\\\"\\n\\t^ char! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/7/2005 22:51'!\\nnextPutAll: aCollection\\n\\t\\\"Put a String or a ByteArray onto the stream.\\n\\tCurrently a large collection will allocate a large buffer.\\\"\\n\\n\\t| toPut |\\n\\ttoPut _ binary ifTrue: [aCollection asByteArray] ifFalse: [aCollection asString].\\n\\tself adjustOutBuffer: toPut size.\\n\\toutBuffer replaceFrom: outNextToWrite to: outNextToWrite + toPut size - 1 with: toPut startingAt: 1.\\n\\toutNextToWrite _ outNextToWrite + toPut size.\\n\\tself checkFlush! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 9/9/2005 09:32'!\\nsendCommand: aString\\n\\t\\\"Sends a String ending it with CR LF and then flush\\n\\tcausing it to block until sent.\\\"\\n\\n\\tself nextPutAll: aString, String crlf; flush! !\\n\\n!SocketStream methodsFor: 'stream out' stamp: 'gk 2/3/2005 20:35'!\\nspace\\n\\tself nextPut: Character space! !\\n\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/25/2005 14:23'!\\natEnd\\n\\t\\\"There is nothing more to read when\\n\\tthere is no more data in our inBuffer, the socket\\n\\tis disconnected and there is none available on the socket.\\n\\tNote that we need to check isConnected before isDataAvailable,\\n\\totherwise data may sneak in in the meantime. But we check the\\n\\tbuffer first, because it is faster.\\\"\\n\\n\\tself isInBufferEmpty ifFalse: [^false].\\n\\t^self isConnected not\\n\\t\\tand: [self isDataAvailable not]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/3/2005 20:35'!\\nisBinary\\n\\t^binary! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 12:24'!\\nisConnected\\n\\t\\\"The stream is connected if the socket is.\\\"\\n\\n\\t^socket isConnected! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/24/2005 12:23'!\\nisDataAvailable\\n\\t\\\"It the inbuffer is empty, we check the socket for data.\\n\\tIf it claims to have data available to read, we try to read\\n\\tsome once and recursively call this method again.\\n\\tIf something really was available it is now in the inBuffer.\\n\\tThis is because there has been spurious\\n\\tdataAvailable when there really is no data to get.\\\"\\n \\n\\tself isInBufferEmpty ifFalse: [^true].\\n\\t^socket dataAvailable\\n\\t\\tifFalse: [false]\\n\\t\\tifTrue: [self receiveDataIfAvailable; isDataAvailable]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 13:02'!\\nisEmpty\\n\\t\\\"Test if there are more data to read.\U0005\\\"\\n\\n\\t^self isInBufferEmpty and: [self isDataAvailable not]! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 13:02'!\\nisInBufferEmpty\\n\\t\\\"Any data in the buffer?\\\"\\n \\n\\t^lastRead + 1 = inNextToWrite! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/7/2005 08:59'!\\nisOtherEndConnected\\n\\t^socket isOtherEndClosed not! !\\n\\n!SocketStream methodsFor: 'testing' stamp: 'gk 2/3/2005 20:35'!\\nshouldTimeout\\n\\t^self timeout > 0! !\\n\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:44'!\\nadjustInBuffer: bytesRead\\n\\t\\\"Adjust markers and possibly grow inBuffer or move data down.\\n\\tCurrently grows through doubling when less than 1024 bytes are left.\\n\\tNever shrinks. Returns the position in the buffer where any new\\n\\tdata can be found.\\\"\\n\\n\\t| old |\\n\\tbytesRead = 0 ifTrue: [^inNextToWrite].\\n\\told _ inNextToWrite.\\n\\tinNextToWrite _ inNextToWrite + bytesRead.\\n\\t(inBuffer size - inNextToWrite) < 1024\\n\\t\\tifTrue: [\\n\\t\\t\\t\\\"Hit the roof, move data down (if enough has been read) or do we grow?\\\"\\n\\t\\t\\t(lastRead > 512)\\n\\t\\t\\t\\tifTrue: [^old - self moveInBufferDown]\\n\\t\\t\\t\\tifFalse: [self growInBuffer]].\\n\\t^old! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:42'!\\nadjustOutBuffer: bytesToWrite\\n\\t\\\"Possibly grow outBuffer to accommodate the new data.\\n\\tCurrently grows through doubling when less\\n\\tthan 1024 bytes are left. If bytesToWrite is even\\n\\tlarger we double that instead. Never shrinks.\\\"\\n\\n\\t(outBuffer size - outNextToWrite - bytesToWrite) < 1024 ifTrue: [\\n\\t\\toutBuffer _ (self streamBuffer: ((outBuffer size max: bytesToWrite) * 2))\\n\\t\\t\\t\\t\\t\\treplaceFrom: 1 to: outBuffer size with: outBuffer startingAt: 1]! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/7/2005 13:09'!\\ncheckFlush\\n\\t\\\"If autoFlush is true we flush if\\n\\twe have reached the bufferSize\\n\\tof data in the outBuffer.\\\"\\n\\n\\t(autoFlush and: [outNextToWrite > bufferSize])\\n\\t\\tifTrue: [self flush]! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/7/2005 23:05'!\\ngrowInBuffer\\n\\t\\\"Grows through doubling.\\\"\\n\\n\\tself resizeInBuffer: inBuffer size * 2! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/8/2005 22:15'!\\nmoveInBufferDown\\n\\t\\\"Move down contents of inBuffer to the start.\\n\\tReturn distance moved.\\\"\\n\\n\\t| sz distanceMoved |\\n\\tsz _ inNextToWrite - lastRead - 1.\\n\\tinBuffer replaceFrom: 1 to: sz with: inBuffer startingAt: lastRead + 1.\\n\\tdistanceMoved _ lastRead.\\n\\tlastRead _ 0.\\n\\tinNextToWrite _ sz + 1.\\n\\t^distanceMoved\\n! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:36'!\\nresetBuffers\\n\\t\\\"Recreate the buffers with default start sizes.\\\"\\n\\n\\tinBuffer _ self streamBuffer: bufferSize.\\n\\tlastRead _ 0.\\n\\tinNextToWrite _ 1.\\n\\toutBuffer _ self streamBuffer: bufferSize.\\n\\toutNextToWrite _ 1! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 9/9/2005 02:29'!\\nresizeInBuffer: newSize\\n\\t\\\"Resize the inBuffer by recreating it.\\n\\tThis also has the effect of getting rid of\\n\\tdead data above inNextToWrite.\\n\\t<newSize> must >= inBuffer size!!\\\"\\n\\n\\tinBuffer _ (self streamBuffer: newSize)\\n\\t\\t\\t\\t\\treplaceFrom: 1 to: inNextToWrite - 1 with: inBuffer startingAt: 1! !\\n\\n!SocketStream methodsFor: 'private' stamp: 'gk 2/9/2005 22:35'!\\nstreamBuffer: size\\n\\t\\\"Create a buffer of the correct class and given size.\\\"\\n\\n\\t^(self isBinary\\n\\t\\tifTrue: [ByteArray]\\n\\t\\tifFalse: [String]) new: size! !\\n\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/25/2005 14:20'!\\nreceiveAvailableData\\n\\t\\\"Receive available data (as much as fits in the inBuffer)\\n\\tbut not waiting for more to arrive.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\t\\n\\trecentlyRead _ socket receiveAvailableDataInto: inBuffer startingAt: inNextToWrite.\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/25/2005 14:20'!\\nreceiveData\\n\\t\\\"Receive data with timeout if it has been set.\\n\\tIf shouldSignal is false we use the Socket methods\\n\\tthat swallow those Exceptions, if it is true the\\n\\tcaller will have to handle those Exceptions.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\t\\n\\trecentlyRead := shouldSignal ifTrue: [\\n\\t\\tself shouldTimeout ifTrue: [\\n\\t\\t\\t\\tsocket receiveDataSignallingTimeout: timeout\\n\\t\\t\\t\\t\\tinto: inBuffer startingAt: inNextToWrite]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsocket receiveDataSignallingClosedInto: inBuffer\\n\\t\\t\\t\\t\\tstartingAt: inNextToWrite]]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\tself shouldTimeout ifTrue: [\\n\\t\\t\\t\\\"This case is tricky, if it times out and is swallowed\\n\\t\\t\\thow does other methods calling this method repeatedly\\n\\t\\t\\tget to know that? And what should they do?\\\"\\n\\t\\t\\t\\tsocket receiveDataTimeout: timeout\\n\\t\\t\\t\\t\\tinto: inBuffer startingAt: inNextToWrite]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsocket receiveDataInto: inBuffer\\n\\t\\t\\t\\t\\tstartingAt: inNextToWrite]].\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n!SocketStream methodsFor: 'private-socket' stamp: 'gk 2/9/2005 22:53'!\\nreceiveDataIfAvailable\\n\\t\\\"Only used to check that there really is data to read\\n\\tfrom the socket after it signals dataAvailable.\\n\\tIt has been known to signal true and then still\\n\\tnot have anything to read. See also isDataAvailable.\\n\\tReturn the position in the buffer where the\\n\\tnew data starts, regardless if anything\\n\\twas read, see #adjustInBuffer.\\\"\\n\\n\\trecentlyRead _ socket receiveSomeDataInto: inBuffer startingAt: inNextToWrite.\\n\\t^self adjustInBuffer: recentlyRead! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocketStream class\\n\\tinstanceVariableNames: ''!\\n\\n!SocketStream class methodsFor: 'example' stamp: 'md 8/14/2005 18:25'!\\nfinger: userName\\n\\t\\\"SocketStream finger: 'stp'\\\"\\n\\n\\t| addr s |\\n\\taddr _ NetNameResolver promptUserForHostAddress.\\n\\ts _ SocketStream openConnectionToHost: addr port: 79. \\\"finger port number\\\"\\n\\tTranscript show: '---------- Connecting ----------'; cr.\\n\\ts sendCommand: userName.\\n\\tTranscript show: s getLine.\\n\\ts close.\\n\\tTranscript show: '---------- Connection Closed ----------'; cr; endEntry.\\n! !\\n\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 22:19'!\\non: socket\\n\\t\\\"Create a socket stream on a connected server socket.\\\"\\n\\n\\t^self basicNew initialize socket: socket! !\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 20:35'!\\nopenConnectionToHost: hostIP port: portNumber\\n\\t| socket |\\n\\tsocket _ Socket new.\\n\\tsocket connectTo: hostIP port: portNumber.\\n\\t^self on: socket! !\\n\\n!SocketStream class methodsFor: 'instance creation' stamp: 'gk 2/3/2005 20:35'!\\nopenConnectionToHostNamed: hostName port: portNumber\\n\\t| hostIP |\\n\\thostIP _ NetNameResolver addressForName: hostName timeout: 20.\\n\\t^self openConnectionToHost: hostIP port: portNumber! !\\nSocket subclass: #SocksSocket\\n\\tinstanceVariableNames: 'vers method socksIP socksPort dstPort dstIP dstName'\\n\\tclassVariableNames: 'DefaultSocksVersion'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-Kernel'!\\n!SocksSocket commentStamp: '<historical>' prior: 0!\\nThis class implements the socks 4 and partially socks 5 connection protocol.\\nFor backward compatibility the socks protocol is disabled by default, so subclasses still work.\\nFor further documentation check out:\\n\\nSocks4: http://spiderman.socks.nec.com/protocol/socks4.protocol\\n\\nSocks5: http://spiderman.socks.nec.com/rfc/rfc1928.txt!\\n\\n\\n!SocksSocket methodsFor: 'connection open/close' stamp: 'mir 2/22/2002 15:49'!\\nconnectTo: hostAddress port: port\\n\\tself initializeNetwork.\\n\\tself shouldUseSocks\\n\\t\\tifFalse: [^super connectTo: hostAddress port: port].\\n\\tsuper connectTo: socksIP port: socksPort.\\n\\tself waitForConnectionUntil: Socket standardDeadline.\\n\\tdstIP _ hostAddress.\\n\\tdstPort _ port.\\n\\tvers == 4\\n\\t\\tifTrue: [self connectSocks4]\\n\\t\\tifFalse: [self connectSocks5]\\n\\t! !\\n\\n!SocksSocket methodsFor: 'connection open/close' stamp: 'mir 3/6/2000 15:17'!\\nconnectToHostNamed: hostName port: port\\n\\tsuper connectTo: socksIP port: socksPort.\\n\\tself waitForConnectionUntil: Socket standardDeadline.\\n\\tdstName _ hostName.\\n\\tdstPort _ port.\\n\\tvers == 4\\n\\t\\tifTrue: [self connectSocks4]\\n\\t\\tifFalse: [self connectSocks5]\\n\\t! !\\n\\n\\n!SocksSocket methodsFor: 'initialize' stamp: 'mir 9/26/2000 00:05'!\\nsocks4\\n\\tvers _ 4.\\n\\tmethod _ nil.\\n\\tsocksIP _ self class defaultSocksHostAddress.\\n\\tsocksPort _ self class defaultSocksPort! !\\n\\n!SocksSocket methodsFor: 'initialize' stamp: 'mir 9/26/2000 00:05'!\\nsocks5\\n\\tvers _ 5.\\n\\tmethod _ self class noAutorizationMethod.\\n\\tsocksIP _ self class defaultSocksHostAddress.\\n\\tsocksPort _ self class defaultSocksPort! !\\n\\n\\n!SocksSocket methodsFor: 'methods' stamp: 'mir 3/6/2000 13:24'!\\nnoAutorizationMethod\\n\\t^0! !\\n\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 3/6/2000 15:07'!\\nconnectSocks4\\n\\tself\\n\\t\\tsendSocks4ConnectionRequestUserId: '';\\n\\t\\twaitForSocks4ConnectionReply.\\n! !\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 2/22/2002 15:49'!\\nsendSocks4ConnectionRequestUserId: userId\\n\\t\\\"The client connects to the SOCKS server and sends a CONNECT request when\\nit wants to establish a connection to an application server. The client\\nincludes in the request packet the IP address and the port number of the\\ndestination host, and userid, in the following format.\\n\\n\\t+----+----+----+----+----+----+----+----+----+----+....+----+\\n\\t| VN | CD | DSTPORT | DSTIP | USERID |NULL|\\n\\t+----+----+----+----+----+----+----+----+----+----+....+----+\\n\\t 1 1 2 4 variable 1\\n\\t\\\"\\n\\n\\t| requestString |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\tdstIP\\n\\t\\tifNil: [dstIP _ NetNameResolver addressForName: dstName].\\n\\trequestString\\n\\t\\tnextPut: 4;\\n\\t\\tnextPut: self connectCommandCode;\\n\\t\\tnextWordPut: dstPort;\\n\\t\\tnextPutAll: self dstIP;\\n\\t\\tnextPutAll: userId asByteArray;\\n\\t\\tnextPut: 0.\\n\\tself sendData: requestString contents! !\\n\\n!SocksSocket methodsFor: 'socks4' stamp: 'mir 3/6/2000 15:11'!\\nwaitForSocks4ConnectionReply\\n\\n\\t| response |\\n\\tresponse _ self waitForReply: 8 for: self defaultTimeOutDuration.\\n\\n\\t(response at: 2) = self requestGrantedCode\\n\\t\\tifFalse: [^self socksError: 'Connection failed: ' , (response at: 2) printString].! !\\n\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:42'!\\nconnectSocks5\\n\\tself\\n\\t\\tsocks5MethodSelection;\\n\\t\\tsendSocks5ConnectionRequest;\\n\\t\\tsocks5RequestReply\\n! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:29'!\\nhostIP6Code\\n\\t^4! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:20'!\\nhostIPCode\\n\\t^1! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:15'!\\nqualifiedHostNameCode\\n\\t^3! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:25'!\\nsendSocks5ConnectionRequest\\n\\t\\\"Once the method-dependent subnegotiation has completed, the client\\n sends the request details.\\\"\\n\\n\\t| requestString |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\trequestString\\n\\t\\tnextPut: 5;\\n\\t\\tnextPut: self connectCommandCode;\\n\\t\\tnextPut: 0. \\\"Reserved slot\\\"\\n\\tdstName isNil\\n\\t\\tifTrue: [\\n\\t\\t\\trequestString\\n\\t\\t\\t\\tnextPutAll: self hostIPCode;\\n\\t\\t\\t\\tnextPutAll: dstIP]\\n\\t\\tifFalse: [\\n\\t\\t\\trequestString\\n\\t\\t\\t\\tnextPut: self qualifiedHostNameCode;\\n\\t\\t\\t\\tnextPut: dstName size;\\n\\t\\t\\t\\tnextPutAll: dstName asByteArray].\\n\\trequestString nextWordPut: dstPort.\\n\\tself sendData: requestString contents! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:35'!\\nskipQualifiedHostName\\n\\n\\t| startTime response bytesRead |\\n\\tstartTime _ Time millisecondClockValue.\\n\\tresponse _ ByteArray new: 1.\\n\\n\\t[(bytesRead _ self receiveDataInto: response) < 1\\n\\t\\tand: [(Time millisecondClockValue - startTime) < self defaultTimeOutDuration]] whileTrue.\\n\\n\\tbytesRead < 1\\n\\t\\tifTrue: [self socksError: 'Time out reading data'].\\n\\n\\tself waitForReply: (response at: 1) + 2 for: self defaultTimeOutDuration! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 15:16'!\\nsocks5MethodSelection\\n\\t\\\"The client connects to the server, and sends a version\\n identifier/method selection message.\\n\\tThe server selects from one of the methods given in METHODS, and\\n sends a METHOD selection message.\\\"\\n\\n\\t| requestString response |\\n\\trequestString _ WriteStream on: ByteArray new.\\n\\trequestString\\n\\t\\tnextPut: 5;\\n\\t\\tnextPut: 1;\\n\\t\\tnextPut: 0.\\n\\tself sendData: requestString contents.\\n\\n\\tresponse _ self waitForReply: 2 for: self defaultTimeOutDuration.\\n\\t(response at: 2) == 16rFF\\n\\t\\tifTrue: [self socksError: 'No acceptable methods.']\\n\\t\\tifFalse: [method _ response at: 2]! !\\n\\n!SocksSocket methodsFor: 'socks5' stamp: 'mir 3/6/2000 17:28'!\\nsocks5RequestReply\\n\\n\\t| response |\\n\\tresponse _ self waitForReply: 4 for: self defaultTimeOutDuration.\\n\\t\\\"Skip rest for now.\\\"\\n\\t(response at: 4) = self hostIPCode\\n\\t\\tifTrue: [self waitForReply: 6 for: self defaultTimeOutDuration].\\n\\t(response at: 4) = self qualifiedHostNameCode\\n\\t\\tifTrue: [self skipQualifiedHostName].\\n\\t(response at: 4) = self hostIP6Code\\n\\t\\tifTrue: [self waitForReply: 18 for: self defaultTimeOutDuration].\\n\\t(response at: 2) ~= 0\\n\\t\\tifTrue: [^self socksError: 'Connection failed: ', (response at: 2) printString].\\n! !\\n\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 13:34'!\\nconnectCommandCode\\n\\t^1! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:07'!\\ndefaultTimeOutDuration\\n\\t^20000! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:29'!\\ndstIP\\n\\t^dstIP! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 2/22/2002 16:23'!\\ndstPort\\n\\t^dstPort! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 14:03'!\\nrequestGrantedCode\\n\\t^90! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 9/26/2000 11:23'!\\nshouldUseSocks\\n\\t^vers notNil! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'mir 3/6/2000 15:11'!\\nsocksError: errorString\\n\\tself close; destroy.\\n\\tself error: errorString! !\\n\\n!SocksSocket methodsFor: 'private' stamp: 'len 12/14/2002 11:39'!\\nwaitForReply: replySize for: timeOutDuration\\n\\t| startTime response delay bytesRead |\\n\\tstartTime _ Time millisecondClockValue.\\n\\tresponse _ ByteArray new: replySize.\\n\\tbytesRead _ 0.\\n\\tdelay _ Delay forMilliseconds: 500.\\n\\t[bytesRead < replySize\\n\\t\\tand: [(Time millisecondClockValue - startTime) < timeOutDuration]] whileTrue: [\\n\\t\\tbytesRead _ bytesRead + (self receiveDataInto: response).\\n\\t\\tdelay wait.\\n\\t\\tTranscript show: '.'].\\n\\tbytesRead < replySize\\n\\t\\tifTrue: [self close; destroy.\\n\\t\\t\\t\\t^ (ConnectionRefused host: self dstIP port: self dstPort) signal].\\n\\t^response! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSocksSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'nk 7/6/2003 07:30'!\\ndefaultSocksHostAddress\\n\\n\\t^NetNameResolver addressForName: HTTPSocket httpProxyServer! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'nk 7/6/2003 07:30'!\\ndefaultSocksPort\\n\\t^HTTPSocket httpProxyPort! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'mir 9/26/2000 00:06'!\\ndefaultSocksVersion\\n\\t\\\"nil means no socks\\\"\\n\\t^DefaultSocksVersion! !\\n\\n!SocksSocket class methodsFor: 'accessing' stamp: 'mir 9/26/2000 00:07'!\\ndefaultSocksVersion: anInteger\\n\\t\\\"nil means no socks\\\"\\n\\tDefaultSocksVersion _ anInteger! !\\nFillStyle subclass: #SolidFillStyle\\n\\tinstanceVariableNames: 'color pixelValue32'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Balloon-Fills'!\\n!SolidFillStyle commentStamp: '<historical>' prior: 0!\\nSolidFillStyle is a fill which represents a color for the BalloonEngine.\\n\\nInstance variables:\\n\\tcolor\\t<Color>\\tThe color to use.\\n\\tpixelValue32 <Integer>\\tThe cached pixel value to use.!\\n\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 1/14/1999 15:24'!\\ncolor: aColor\\n\\tcolor := aColor.\\n\\tpixelValue32 := aColor scaledPixelValue32! !\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 11/9/1998 03:29'!\\ndisplay\\n\\t^color display! !\\n\\n!SolidFillStyle methodsFor: 'accessing' stamp: 'ar 1/14/1999 15:25'!\\nscaledPixelValue32\\n\\t\\\"Return the alpha scaled pixel value for depth 32\\\"\\n\\t^pixelValue32! !\\n\\n\\n!SolidFillStyle methodsFor: 'converting' stamp: 'ar 11/9/1998 13:55'!\\nasColor\\n\\t^color! !\\n\\n\\n!SolidFillStyle methodsFor: 'printing' stamp: 'ar 11/17/1998 00:29'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPut:$(; print: color; nextPut:$).! !\\n\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 11/8/1998 18:34'!\\nisSolidFill\\n\\t^true! !\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 9/2/1999 14:30'!\\nisTranslucent\\n\\t^color isTranslucent! !\\n\\n!SolidFillStyle methodsFor: 'testing' stamp: 'ar 10/26/2000 19:25'!\\nisTransparent\\n\\t^color isTransparent! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSolidFillStyle class\\n\\tinstanceVariableNames: ''!\\n\\n!SolidFillStyle class methodsFor: 'instance creation' stamp: 'ar 11/8/1998 18:31'!\\ncolor: aColor\\n\\t^self new color: aColor! !\\nImageMorph subclass: #Sonogram\\n\\tinstanceVariableNames: 'lastX scrollDelta columnForm minVal maxVal pixValMap'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!Sonogram commentStamp: '<historical>' prior: 0!\\nSonograms are imageMorphs that will repeatedly plot arrays of values as black on white columns moving to the right in time and scrolling left as necessary.!\\n\\n\\n!Sonogram methodsFor: 'all' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextent: extent minVal: min maxVal: max scrollDelta: d\\n\\tminVal := min.\\n\\tmaxVal := max.\\n\\tscrollDelta := d.\\n\\tself extent: extent.\\n\\n\\\" try following with scrolldelta = 1, 20, 200\\n\\t| s data |\\n\\ts := Sonogram new extent: 200@50\\n\\t\\t\\t\\tminVal: 0.0 maxVal: 1.0 scrollDelta: 20.\\n\\tWorld addMorph: s.\\n\\tdata := (1 to: 133) collect: [:i | 0.0].\\n\\t1 to: 300 do:\\n\\t\\t[:i | data at: (i\\\\\\\\133)+1 put: 1.0.\\n\\t\\ts plotColumn: data.\\n\\t\\tdata at: (i\\\\\\\\133)+1 put: 0.0.\\n\\t\\tWorld doOneCycleNow].\\n\\ts delete\\t\\n\\\"! !\\n\\n!Sonogram methodsFor: 'all' stamp: 'jdl 3/28/2003 09:30'!\\nplotColumn: dataArray \\n\\t| chm1 i normVal r |\\n\\tcolumnForm unhibernate.\\n\\tchm1 := columnForm height - 1.\\n\\t0 to: chm1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\ti := y * (dataArray size - 1) // chm1 + 1.\\n\\t\\t\\tnormVal := ((dataArray at: i) - minVal) / (maxVal - minVal).\\n\\t\\t\\tnormVal := normVal max: 0.0.\\n\\t\\t\\tnormVal := normVal min: 1.0.\\n\\t\\t\\tcolumnForm bits at: chm1 - y + 1\\n\\t\\t\\t\\tput: (pixValMap at: (normVal * 255.0) truncated + 1)].\\n\\t(lastX := lastX + 1) > (image width - 1) ifTrue: [self scroll].\\n\\timage \\n\\t\\tcopy: (r := lastX @ 0 extent: 1 @ image height)\\n\\t\\tfrom: (32 // image depth - 1) @ 0\\n\\t\\tin: columnForm\\n\\t\\trule: Form over.\\n\\t\\\"self changed.\\\"\\n\\tself invalidRect: (r translateBy: self position)! !\\n\\n!Sonogram methodsFor: 'all' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscroll\\n\\timage copy: (scrollDelta@0 extent: (image width-scrollDelta)@image height)\\n\\t\\t\\tfrom: image to: 0@0 rule: Form over.\\n\\tlastX := lastX - scrollDelta.\\n\\tself changed! !\\n\\n\\n!Sonogram methodsFor: 'geometry' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextent: newExtent\\n\\tsuper image: (Form extent: newExtent depth: Display depth).\\n\\tlastX := -1.\\n\\tcolumnForm := Form extent: (32//image depth)@(image height) depth: image depth.\\n\\tpixValMap := ((1 to: 256) collect:\\n\\t\\t\\t[:i | columnForm pixelValueFor: (Color gray: (256-i)/255.0)])\\n\\t\\tas: Bitmap.\\n! !\\nOrderedCollection subclass: #SortedCollection\\n\\tinstanceVariableNames: 'sortBlock'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Sequenceable'!\\n!SortedCollection commentStamp: '<historical>' prior: 0!\\nI represent a collection of objects ordered by some property of the objects themselves. The ordering is specified in a BlockContext.!\\n\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'sma 4/28/2000 17:47'!\\nat: anInteger put: anObject\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'tk 3/28/1999 22:55'!\\nmedian\\n\\t\\\"Return the middle element, or as close as we can get.\\\"\\n\\n\\t^ self at: self size + 1 // 2! !\\n\\n!SortedCollection methodsFor: 'accessing'!\\nsortBlock\\n\\t\\\"Answer the blockContext which is the criterion for sorting elements of \\n\\tthe receiver.\\\"\\n\\n\\t^sortBlock! !\\n\\n!SortedCollection methodsFor: 'accessing' stamp: 'stp 12/05/1999 07:09'!\\nsortBlock: aBlock \\n\\t\\\"Make the argument, aBlock, be the criterion for ordering elements of the \\n\\treceiver.\\\"\\n\\n\\taBlock\\n\\t\\tifNotNil: [sortBlock := aBlock fixTemps]\\n\\t\\tifNil: [sortBlock := aBlock].\\n\\t\\\"The sortBlock must copy its home context, so as to avoid circularities!!\\\"\\n\\t\\\"Therefore sortBlocks with side effects may not work right\\\"\\n\\tself size > 0 ifTrue: [self reSort]! !\\n\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'go 4/27/2000 13:19'!\\nadd: newObject\\n\\t^ super insert: newObject before: (self indexForInserting: newObject)! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'sma 4/28/2000 18:35'!\\naddAll: aCollection\\n\\taCollection size > (self size // 3)\\n\\t\\tifTrue:\\n\\t\\t\\t[aCollection do: [:each | self addLast: each].\\n\\t\\t\\tself reSort]\\n\\t\\tifFalse: [aCollection do: [:each | self add: each]].\\n\\t^ aCollection! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'go 4/26/2000 17:26'!\\naddFirst: newObject\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'adding' stamp: 'MPH 10/23/2000 13:31'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver without any of the receiver's elements.\\\"\\n\\n\\t^self species sortBlock: sortBlock! !\\n\\n\\n!SortedCollection methodsFor: 'comparing'!\\n= aSortedCollection\\n\\t\\\"Answer true if my and aSortedCollection's species are the same,\\n\\tand if our blocks are the same, and if our elements are the same.\\\"\\n\\n\\tself species = aSortedCollection species ifFalse: [^ false].\\n\\tsortBlock = aSortedCollection sortBlock\\n\\t\\tifTrue: [^ super = aSortedCollection]\\n\\t\\tifFalse: [^ false]! !\\n\\n\\n!SortedCollection methodsFor: 'copying'!\\ncopy\\n\\n\\t| newCollection |\\n\\tnewCollection _ self species sortBlock: sortBlock.\\n\\tnewCollection addAll: self.\\n\\t^newCollection! !\\n\\n\\n!SortedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'!\\ncollect: aBlock \\n\\t\\\"Evaluate aBlock with each of my elements as the argument. Collect the \\n\\tresulting values into an OrderedCollection. Answer the new collection. \\n\\tOverride the superclass in order to produce an OrderedCollection instead\\n\\tof a SortedCollection.\\\"\\n\\n\\t| newCollection | \\n\\tnewCollection _ OrderedCollection new: self size.\\n\\tself do: [:each | newCollection addLast: (aBlock value: each)].\\n\\t^ newCollection! !\\n\\n\\n!SortedCollection methodsFor: 'topological sort' stamp: 'hg 1/2/2002 13:34'!\\nsortTopologically\\n\\t\\\"Plenty of room for increased efficiency in this one.\\\"\\n\\n\\t| remaining result pick |\\n\\tremaining _ self asOrderedCollection.\\n\\tresult _ OrderedCollection new.\\n\\t[remaining isEmpty] whileFalse: [\\n\\t\\tpick _ remaining select: [:item |\\n\\t\\t\\tremaining allSatisfy: [:anotherItem |\\n\\t\\t\\t\\titem == anotherItem or: [self should: item precede: anotherItem]]].\\n\\t\\tpick isEmpty ifTrue: [self error: 'bad topological ordering'].\\n\\t\\tresult addAll: pick.\\n\\t\\tremaining removeAll: pick].\\n\\t^self copySameFrom: result! !\\n\\n\\n!SortedCollection methodsFor: 'private' stamp: 'stp 04/23/1999 05:36'!\\nindexForInserting: newObject\\n\\n\\t| index low high |\\n\\tlow _ firstIndex.\\n\\thigh _ lastIndex.\\n\\tsortBlock isNil\\n\\t\\tifTrue: [[index _ high + low // 2. low > high]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[((array at: index) <= newObject)\\n\\t\\t\\t\\t\\tifTrue: [low _ index + 1]\\n\\t\\t\\t\\t\\tifFalse: [high _ index - 1]]]\\n\\t\\tifFalse: [[index _ high + low // 2. low > high]\\n\\t\\t\\twhileFalse: \\n\\t\\t\\t\\t[(sortBlock value: (array at: index) value: newObject)\\n\\t\\t\\t\\t\\tifTrue: [low _ index + 1]\\n\\t\\t\\t\\t\\tifFalse: [high _ index - 1]]].\\n\\t^low! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'go 4/26/2000 17:17'!\\ninsert: anObject before: spot\\n\\tself shouldNotImplement! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'sma 4/28/2000 17:46'!\\nreSort\\n\\tself sort: firstIndex to: lastIndex! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 19:30'!\\nshould: a precede: b\\n\\n\\t^sortBlock ifNil: [a <= b] ifNotNil: [sortBlock value: a value: b]\\n! !\\n\\n!SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 20:22'!\\nsort: i to: j \\n\\t\\\"Sort elements i through j of self to be nondescending according to\\n\\tsortBlock.\\\"\\n\\n\\t| di dij dj tt ij k l n |\\n\\t\\\"The prefix d means the data at that index.\\\"\\n\\t(n _ j + 1 - i) <= 1 ifTrue: [^self].\\t\\\"Nothing to sort.\\\" \\n\\t \\\"Sort di,dj.\\\"\\n\\tdi _ array at: i.\\n\\tdj _ array at: j.\\n\\t(self should: di precede: dj)\\n\\t\\tifFalse: \\n\\t\\t\\t[array swap: i with: j.\\n\\t\\t\\t tt _ di.\\n\\t\\t\\t di _ dj.\\n\\t\\t\\t dj _ tt].\\n\\tn > 2\\n\\t\\tifTrue: \\\"More than two elements.\\\"\\n\\t\\t\\t[ij _ (i + j) // 2. \\\"ij is the midpoint of i and j.\\\"\\n\\t\\t\\t dij _ array at: ij. \\\"Sort di,dij,dj. Make dij be their median.\\\"\\n\\t\\t\\t (self should: di precede: dij)\\n\\t\\t\\t ifTrue: \\n\\t\\t\\t\\t[(self should: dij precede: dj)\\n\\t\\t\\t\\t ifFalse: \\n\\t\\t\\t\\t\\t[array swap: j with: ij.\\n\\t\\t\\t\\t\\t dij _ dj]]\\n\\t\\t\\t ifFalse:\\n\\t\\t\\t\\t[array swap: i with: ij.\\n\\t\\t\\t\\t dij _ di].\\n\\t\\t\\tn > 3\\n\\t\\t\\t ifTrue: \\\"More than three elements.\\\"\\n\\t\\t\\t\\t[\\\"Find k>i and l<j such that dk,dij,dl are in reverse order.\\n\\t\\t\\t\\tSwap k and l. Repeat this procedure until k and l pass each other.\\\"\\n\\t\\t\\t\\t k _ i.\\n\\t\\t\\t\\t l _ j.\\n\\t\\t\\t\\t [[l _ l - 1. k <= l and: [self should: dij precede: (array at: l)]]\\n\\t\\t\\t\\t whileTrue. \\\"i.e. while dl succeeds dij\\\"\\n\\t\\t\\t\\t [k _ k + 1. k <= l and: [self should: (array at: k) precede: dij]]\\n\\t\\t\\t\\t whileTrue. \\\"i.e. while dij succeeds dk\\\"\\n\\t\\t\\t\\t k <= l]\\n\\t\\t\\t\\t whileTrue:\\n\\t\\t\\t\\t\\t[array swap: k with: l]. \\n\\t\\\"Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk\\n\\tthrough dj. Sort those two segments.\\\"\\n\\t\\t\\t\\tself sort: i to: l.\\n\\t\\t\\t\\tself sort: k to: j]]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSortedCollection class\\n\\tinstanceVariableNames: ''!\\n\\n!SortedCollection class methodsFor: 'instance creation' stamp: 'stp 04/23/1999 05:34'!\\nnew: anInteger \\n\\t\\\"The default sorting function is a <= comparison on elements.\\\"\\n\\n\\t^(super new: anInteger) \\\"sortBlock: [:x :y | x <= y]\\\" \\t\\t\\\"nil sortBlock OK\\\"! !\\n\\n!SortedCollection class methodsFor: 'instance creation'!\\nsortBlock: aBlock \\n\\t\\\"Answer an instance of me such that its elements are sorted according to \\n\\tthe criterion specified in aBlock.\\\"\\n\\n\\t^(super new: 10) sortBlock: aBlock! !\\nTestCase subclass: #SortedCollectionTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Unordered'!\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:27'!\\ntestAdd\\n\\t\\\"self run: #testAdd\\\"\\n\\t\\\"self debug: #testAdd\\\"\\n\\t\\n\\t| collection |\\n\\tcollection := #(10 9 8 7 5 4 4 2) asSortedCollection.\\n\\tself assert: collection first = 2.\\n\\tself assert: collection last = 10.\\n\\tself assert: (collection size = 8).\\n\\tcollection add:1.\\n\\tself assert: (collection size = 9).\\n\\tcollection add: 6.\\n\\tself assert: ((collection at: 5) = 5).\\n\\tself assert: (collection size = 10).\\n\\tcollection add: 3.\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:30'!\\ntestAddAll\\n\\t\\\"self run: #testAddAll\\\"\\n\\t\\\"self debug: #testAddAll\\\"\\n\\t\\n\\t| sorted2 sorted|\\n\\tsorted2 := SortedCollection new.\\n\\tsorted2 add: 'brochet'; add:'truitelle'.\\n\\tsorted := SortedCollection new.\\n\\tsorted addAll: sorted2.\\n\\tself assert: (sorted hasEqualElements: sorted2).\\n\\t ! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:32'!\\ntestAddAll2\\n\\t\\\"self run: #testAddAll2\\\"\\n\\t\\\"self debug: #testAddAll2\\\"\\n\\t\\n\\t| sorted2 sorted|\\n\\tsorted2 := SortedCollection new.\\n\\tsorted2 add: 'brochet'; add:'truitelle'.\\n\\tsorted := SortedCollection new.\\n\\tsorted add: 'perche'.\\n\\tsorted addAll: sorted2.\\n\\tself assert: (sorted size = (sorted2 size + 1)).\\n\\tsorted2 do: \\n\\t\\t\\t[ :each | self assert: (sorted includes: each)]\\n\\t ! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:33'!\\ntestCollect\\n\\t\\\"self run: #testCollect\\\"\\n\\t\\n\\t|result aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\tresult := OrderedCollection new.\\n\\tresult add:true ; add: true ; add: true ;add: false ; add: false.\\n\\taSortedCollection := (1 to: 5) asSortedCollection.\\n\\tself assert: (result = (aSortedCollection collect: [:each | each < 4])).\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:39'!\\ntestCopy\\n\\t\\\"self run: #testCopy\\\"\\n\\t\\\"self debug: #testCopy\\\"\\n\\t\\n\\t|aSortedCollection copySorted|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a < b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet'.\\n\\tself assert: aSortedCollection first = 'brochet'.\\n\\t\\n\\tcopySorted := aSortedCollection copy.\\n\\t\\n\\tself assert: (copySorted hasEqualElements: aSortedCollection).\\n\\tself assert: (copySorted species = aSortedCollection species).\\n\\tself assert: (copySorted sortBlock = aSortedCollection sortBlock).\\n\\tself assert: copySorted first = 'brochet'.! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:30'!\\ntestCreation\\n\\t\\\"self run: #testCreation\\\"\\n\\t\\\"self debug: #testCreation\\\"\\n\\t\\n\\t| collection |\\n\\tcollection := #(10 9 3 6 1 8 7 5 4 2) asSortedCollection.\\n\\tself assert: collection = (1 to: 10) asSortedCollection.\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:42'!\\ntestEquals\\n\\t\\\"self run: #testEquals\\\"\\n\\t\\\"self debug: #testEquals\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection add:'truite' ; add: 'brochet'.\\n\\tself assert: aSortedCollection copy = aSortedCollection.! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:43'!\\ntestMedian\\n\\t\\\"self run: #testMedian\\\"\\n\\t\\\"self debug: #testMedian\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := (1 to: 10) asSortedCollection.\\n\\tself assert: aSortedCollection median=5.\\n\\t\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection add:'truite' ; add:'porcinet' ; add:'carpe'.\\n\\tself assert: (aSortedCollection median = 'porcinet').\\n\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:46'!\\ntestShouldPrecede\\n\\t\\\"self run: #testShouldPrecede\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\tself assert: (aSortedCollection should: 'za' precede: 'zb').\\n\\tself assert: (aSortedCollection isEmpty).\\n\\tself assert: (aSortedCollection should: 1 precede: 2).\\n\\t\\n\\taSortedCollection sortBlock: [:a :b | a > b].\\n\\taSortedCollection reSort.\\n\\tself assert: (aSortedCollection should: 'zb' precede: 'za').\\n\\tself assert: (aSortedCollection isEmpty).\\n\\tself assert: (aSortedCollection should: 2 precede: 1).\\n\\t\\t! !\\n\\n!SortedCollectionTest methodsFor: 'basic' stamp: 'DM 3/16/2006 11:38'!\\ntestSortBlock\\n\\t\\\"self run: #testSortBlock\\\"\\n\\t\\\"self debug: #testSortBlock\\\"\\n\\t\\n\\t|aSortedCollection|\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a < b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet' ; add: 'tortue'.\\n\\tself assert: aSortedCollection first = 'brochet'.\\n\\t\\n\\taSortedCollection := SortedCollection new.\\n\\taSortedCollection sortBlock: [:a :b | a >b].\\n\\taSortedCollection add: 'truite' ; add: 'brochet' ; add: 'tortue'.\\n\\tself assert: aSortedCollection first = 'truite'.\\n\\t\\n\\t\\n\\t! !\\nBorderedMorph subclass: #SorterTokenMorph\\n\\tinstanceVariableNames: 'morphRepresented'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Palettes'!\\n\\n!SorterTokenMorph methodsFor: 'as yet unclassified' stamp: 'sw 12/1/1998 12:38'!\\nfitContents\\n\\tsubmorphs size == 1 ifTrue: [self bounds: (submorphs first bounds insetBy: (-1 @ -1))]! !\\n\\n!SorterTokenMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/21/2003 23:16'!\\nforMorph: aMorph \\n\\t| it |\\n\\tmorphRepresented := aMorph.\\n\\taMorph submorphs notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[self addMorphBack: (it := aMorph submorphs first veryDeepCopy).\\n\\t\\t\\tit position: self position + (1 @ 1).\\n\\t\\t\\tit lock].\\n\\tself fitContents! !\\n\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color blue! !\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!SorterTokenMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color transparent! !\\n\\n\\n!SorterTokenMorph methodsFor: 'thumbnail' stamp: 'sw 12/1/1998 12:27'!\\nmorphRepresented\\n\\t^ morphRepresented! !\\nArrayedCollection variableWordSubclass: #SoundBuffer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'SineTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundBuffer commentStamp: '<historical>' prior: 0!\\nSoundBuffers store 16 bit unsigned quantities. !\\n\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'tk 3/13/2000 14:46'!\\nbytesPerElement\\n\\t\\\"Number of bytes in each item. This multiplied by (self size)*8 gives the number of bits stored.\\\"\\n\\t^ 2! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:00'!\\nmonoSampleCount\\n\\t\\\"Return the number of monaural 16-bit samples that fit into this SoundBuffer.\\\"\\n\\n\\t^ super size * 2\\n! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:28'!\\nsize\\n\\t\\\"Return the number of 16-bit sound samples that fit in this sound buffer. To avoid confusion, it is better to get the size of SoundBuffer using monoSampleCount or stereoSampleCount.\\\"\\n\\n\\t^ self monoSampleCount\\n! !\\n\\n!SoundBuffer methodsFor: 'accessing' stamp: 'jm 9/17/97 13:01'!\\nstereoSampleCount\\n\\t\\\"Return the number of stereo slices that fit into this SoundBuffer. A stereo 'slice' consists of two 16-bit samples, one for each channel.\\\"\\n\\n\\t^ super size\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'as yet unclassified' stamp: 'RAA 7/11/2000 11:31'!\\nwriteOnGZIPByteStream: aStream \\n\\t\\n\\taStream nextPutAllWordArray: self! !\\n\\n\\n!SoundBuffer methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrestoreEndianness\\n\\t\\\"This word object was just read in from a stream. It was stored in Big Endian (Mac) format. Swap each pair of bytes (16-bit word), if the current machine is Little Endian.\\n\\tWhy is this the right thing to do? We are using memory as a byteStream. High and low bytes are reversed in each 16-bit word, but the stream of words ascends through memory. Different from a Bitmap.\\\"\\n\\n\\t| hack blt |\\n\\tSmalltalkImage current isLittleEndian ifTrue: [\\n\\t\\t\\\"The implementation is a hack, but fast for large ranges\\\"\\n\\t\\thack := Form new hackBits: self.\\n\\t\\tblt := (BitBlt toForm: hack) sourceForm: hack.\\n\\t\\tblt combinationRule: Form reverse. \\\"XOR\\\"\\n\\t\\tblt sourceY: 0; destY: 0; height: self size; width: 1.\\n\\t\\tblt sourceX: 0; destX: 1; copyBits. \\\"Exchange bytes 0 and 1\\\"\\n\\t\\tblt sourceX: 1; destX: 0; copyBits.\\n\\t\\tblt sourceX: 0; destX: 1; copyBits.\\n\\t\\tblt sourceX: 2; destX: 3; copyBits. \\\"Exchange bytes 2 and 3\\\"\\n\\t\\tblt sourceX: 3; destX: 2; copyBits.\\n\\t\\tblt sourceX: 2; destX: 3; copyBits].\\n\\n! !\\n\\n!SoundBuffer methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreverseEndianness\\n\\t\\\"Swap the bytes of each 16-bit word, using a fast BitBlt hack.\\\"\\n\\n\\t| hack blt |\\n\\thack := Form new hackBits: self.\\n\\tblt := (BitBlt toForm: hack) sourceForm: hack.\\n\\tblt combinationRule: Form reverse. \\\"XOR\\\"\\n\\tblt sourceY: 0; destY: 0; height: self size; width: 1.\\n\\tblt sourceX: 0; destX: 1; copyBits. \\\"Exchange bytes 0 and 1\\\"\\n\\tblt sourceX: 1; destX: 0; copyBits.\\n\\tblt sourceX: 0; destX: 1; copyBits.\\n\\tblt sourceX: 2; destX: 3; copyBits. \\\"Exchange bytes 2 and 3\\\"\\n\\tblt sourceX: 3; destX: 2; copyBits.\\n\\tblt sourceX: 2; destX: 3; copyBits.\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/17/97 13:03'!\\nat: index\\n\\t\\\"Return the 16-bit integer value at the given index of the receiver.\\\"\\n\\n\\t<primitive: 143>\\n\\tindex isInteger ifTrue: [self errorSubscriptBounds: index].\\n\\tindex isNumber ifTrue: [^ self at: index truncated].\\n\\tself errorNonIntegerIndex.\\n! !\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/17/97 13:03'!\\nat: index put: value\\n\\t\\\"Store the given 16-bit integer at the given index in the receiver.\\\"\\n\\n\\t<primitive: 144>\\n\\tindex isInteger\\n\\t\\tifTrue: [\\n\\t\\t\\t(index >= 1 and: [index <= self size])\\n\\t\\t\\t\\tifTrue: [self errorImproperStore]\\n\\t\\t\\t\\tifFalse: [self errorSubscriptBounds: index]].\\n\\tindex isNumber ifTrue: [^ self at: index truncated put: value].\\n\\tself errorNonIntegerIndex.\\n! !\\n\\n!SoundBuffer methodsFor: 'primitives' stamp: 'jm 9/2/97 16:07'!\\nprimFill: aPositiveInteger\\n\\t\\\"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.\\\"\\n\\t\\\"Note: Since 16-bit word arrays are not built into the virtual machine, this primitive fills by 32-bit words.\\\"\\n\\n\\t<primitive: 145>\\n\\tself errorImproperStore.\\n! !\\n\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nasByteArray\\n\\t\\\"Answer a ByteArray containing my sample data serialized in most-significant byte first order.\\\"\\n\\n\\t| sampleCount bytes dst s |\\n\\tsampleCount := self monoSampleCount.\\n\\tbytes := ByteArray new: 2 * sampleCount.\\n\\tdst := 0.\\n\\t1 to: sampleCount do: [:src |\\n\\t\\ts := self at: src.\\n\\t\\tbytes at: (dst := dst + 1) put: ((s bitShift: -8) bitAnd: 255).\\n\\t\\tbytes at: (dst := dst + 1) put: (s bitAnd: 255)].\\n\\t^ bytes\\n\\n\\t! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\naverageEvery: nSamples from: anotherBuffer upTo: inCount\\n\\n\\t| fromIndex sum |\\n\\n\\tfromIndex := 1.\\n\\t1 to: inCount // nSamples do: [ :i |\\n\\t\\tsum := 0.\\n\\t\\tnSamples timesRepeat: [\\n\\t\\t\\tsum := sum + (anotherBuffer at: fromIndex).\\n\\t\\t\\tfromIndex := fromIndex + 1.\\n\\t\\t].\\n\\t\\tself at: i put: sum // nSamples.\\n\\t].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndownSampledLowPassFiltering: doFiltering\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of every other sample. If doFiltering is true, a simple low-pass filter is applied to avoid aliasing of high frequencies. Assume that receiver is monophonic.\\\"\\n\\t\\\"Details: The simple low-pass filter in the current implementation could be improved, at some additional cost.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\tdoFiltering\\n\\t\\tifTrue: [\\n\\t\\t\\t1 to: n by: 2 do: [:i |\\n\\t\\t\\t\\tresultBuf at: (j := j + 1) put:\\n\\t\\t\\t\\t\\t(((self at: i) + (self at: i + 1)) bitShift: -1)]]\\n\\t\\tifFalse: [\\n\\t\\t\\t1 to: n by: 2 do: [:i |\\n\\t\\t\\t\\tresultBuf at: (j := j + 1) put: (self at: i)]].\\n\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractLeftChannel\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of only the left channel of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t1 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (self at: i)].\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractRightChannel\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver consisting of only the right channel of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t2 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (self at: i)].\\n\\t^ resultBuf! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'jhm 10/15/97 15:13'!\\nindexOfFirstSampleOver: threshold\\n\\t\\\"Return the index of the first sample whose absolute value is over the given threshold value. Return an index one greater than my size if no sample is over the threshold.\\\"\\n\\n\\t1 to: self size do: [:i |\\n\\t\\t(self at: i) abs > threshold ifTrue: [^ i]].\\n\\t^ self size + 1! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'jhm 10/15/97 15:13'!\\nindexOfLastSampleOver: threshold\\n\\t\\\"Return the index of the last sample whose absolute value is over the given threshold value. Return zero if no sample is over the threshold.\\\"\\n\\n\\tself size to: 1 by: -1 do: [:i |\\n\\t\\t(self at: i) abs > threshold ifTrue: [^ i]].\\n\\t^ 0\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nlowPassFiltered\\n\\t\\\"Answer a simple low-pass filtered copy of this buffer. Assume it is monophonic.\\\"\\n\\n\\t| sz out last this |\\n\\tsz := self monoSampleCount.\\n\\tout := self clone.\\n\\tlast := self at: 1.\\n\\t2 to: sz do: [:i |\\n\\t\\tthis := self at: i.\\n\\t\\tout at: i put: (this + last) // 2.\\n\\t\\tlast := this].\\n\\t^ out\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmergeStereo\\n\\t\\\"Answer a new SoundBuffer half the size of the receiver that mixes the left and right stereo channels of the receiver, which is assumed to contain stereo sound data.\\\"\\n\\n\\t| n resultBuf j |\\n\\tn := self monoSampleCount.\\n\\tresultBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tj := 0.\\n\\t1 to: n by: 2 do: [:i | resultBuf at: (j := j + 1) put: (((self at: i) + (self at: i + 1)) // 2)].\\n\\t^ resultBuf\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnormalized: percentOfFullVolume\\n\\t\\\"Increase my amplitudes so that the highest peak is the given percent of full volume. For example 's normalized: 50' would normalize to half of full volume.\\\"\\n\\n\\t| peak s mult |\\n\\tpeak := 0.\\n\\t1 to: self size do: [:i |\\n\\t\\ts := (self at: i) abs.\\n\\t\\ts > peak ifTrue: [peak := s]].\\n\\tmult := (32767.0 * percentOfFullVolume) / (100.0 * peak).\\n\\t1 to: self size do: [:i | self at: i put: (mult * (self at: i)) asInteger].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsaveAsAIFFFileSamplingRate: rate on: aBinaryStream\\n\\t\\\"Store this mono sound buffer in AIFF file format with the given sampling rate on the given stream.\\\"\\n\\n\\t| sampleCount s swapBytes |\\n\\tsampleCount := self monoSampleCount.\\n\\taBinaryStream nextPutAll: 'FORM' asByteArray.\\n\\taBinaryStream nextInt32Put: (2 * sampleCount) + ((7 * 4) + 18).\\n\\taBinaryStream nextPutAll: 'AIFF' asByteArray.\\n\\taBinaryStream nextPutAll: 'COMM' asByteArray.\\n\\taBinaryStream nextInt32Put: 18.\\n\\taBinaryStream nextNumber: 2 put: 1. \\\"channels\\\"\\n\\taBinaryStream nextInt32Put: sampleCount.\\n\\taBinaryStream nextNumber: 2 put: 16. \\\"bits/sample\\\"\\n\\tself storeExtendedFloat: rate on: aBinaryStream.\\n\\taBinaryStream nextPutAll: 'SSND' asByteArray.\\n\\taBinaryStream nextInt32Put: (2 * sampleCount) + 8.\\n\\taBinaryStream nextInt32Put: 0.\\n\\taBinaryStream nextInt32Put: 0.\\n\\n\\t(aBinaryStream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\t\\\"optimization: write sound buffer directly to file\\\"\\n\\t\\tswapBytes := SmalltalkImage current isLittleEndian.\\n\\t\\tswapBytes ifTrue: [self reverseEndianness]. \\\"make big endian\\\"\\n\\t\\taBinaryStream next: (self size // 2) putAll: self startingAt: 1. \\\"size in words\\\"\\n\\t\\tswapBytes ifTrue: [self reverseEndianness]. \\\"revert to little endian\\\"\\n\\t\\t^ self].\\n\\n\\t1 to: sampleCount do: [:i |\\n\\t\\ts := self at: i.\\n\\t\\taBinaryStream nextPut: ((s bitShift: -8) bitAnd: 16rFF).\\n\\t\\taBinaryStream nextPut: (s bitAnd: 16rFF)].\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsplitStereo\\n\\t\\\"Answer an array of two SoundBuffers half the size of the receiver consisting of the left and right channels of the receiver (which is assumed to contain stereo sound data).\\\"\\n\\n\\t| n leftBuf rightBuf leftIndex rightIndex |\\n\\tn := self monoSampleCount.\\n\\tleftBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\trightBuf := SoundBuffer newMonoSampleCount: n // 2.\\n\\tleftIndex := rightIndex := 0.\\n\\t1 to: n by: 2 do: [:i |\\n\\t\\tleftBuf at: (leftIndex := leftIndex + 1) put: (self at: i).\\n\\t\\trightBuf at: (rightIndex := rightIndex + 1) put: (self at: i + 1)].\\n\\t^ Array with: leftBuf with: rightBuf\\n! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreExtendedFloat: aNumber on: aBinaryStream\\n\\t\\\"Store an Apple extended-precision 80-bit floating point number on the given stream.\\\"\\n\\t\\\"Details: I could not find the specification for this format, so constants were determined empirically based on assumption of 1-bit sign, 15-bit exponent, 64-bit mantissa. This format does not seem to have an implicit one before the mantissa as some float formats do.\\\"\\n\\n\\t| n isNeg exp mantissa |\\n\\tn := aNumber asFloat.\\n\\tisNeg := false.\\n\\tn < 0.0 ifTrue: [\\n\\t\\tn := 0.0 - n.\\n\\t\\tisNeg := true].\\n\\texp := (n log: 2.0) ceiling.\\n\\tmantissa := (n * (2 raisedTo: 64 - exp)) truncated.\\n\\texp := exp + 16r4000 - 2. \\\"not sure why the -2 is needed...\\\"\\n\\tisNeg ifTrue: [exp := exp bitOr: 16r8000]. \\\"set sign bit\\\"\\n\\taBinaryStream nextPut: ((exp bitShift: -8) bitAnd: 16rFF).\\n\\taBinaryStream nextPut: (exp bitAnd: 16rFF).\\n\\t8 to: 1 by: -1 do: [:i | aBinaryStream nextPut: (mantissa digitAt: i)].! !\\n\\n!SoundBuffer methodsFor: 'utilities' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntrimmedThreshold: threshold\\n\\n\\t| start end |\\n\\tstart := self indexOfFirstSampleOver: threshold.\\n\\tend := self indexOfLastSampleOver: threshold.\\n\\tstart > end ifTrue: [^ SoundBuffer new].\\n\\tstart := (start - 200) max: 1.\\n\\tend := (end + 200) min: self size.\\n\\t^ self copyFrom: start to: end\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundBuffer class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundBuffer class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"Build a sine wave table.\\\"\\n\\t\\\"SoundBuffer initialize\\\"\\n\\n\\t| tableSize radiansPerStep peak |\\n\\ttableSize := 4000.\\n\\tSineTable := self newMonoSampleCount: tableSize.\\n\\tradiansPerStep := (2.0 * Float pi) / tableSize asFloat.\\n\\tpeak := ((1 bitShift: 15) - 1) asFloat. \\\"range is +/- (2^15 - 1)\\\"\\n\\t1 to: tableSize do: [:i |\\n\\t\\tSineTable at: i put: (peak * (radiansPerStep * (i - 1)) sin) rounded].\\n! !\\n\\n!SoundBuffer class methodsFor: 'class initialization' stamp: 'ads 7/31/2003 11:13'!\\nsineTable\\n\\t\\\"Answer a SoundBuffer containing one complete cycle of a sine wave.\\\"\\n\\n\\t^ SineTable\\n! !\\n\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'RAA 12/30/2000 18:20'!\\naverageEvery: nSamples from: anotherBuffer upTo: inCount\\n\\n\\t^(self newMonoSampleCount: inCount // nSamples)\\n\\t\\taverageEvery: nSamples \\n\\t\\tfrom: anotherBuffer \\n\\t\\tupTo: inCount! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfromArray: anArray\\n\\t\\\"Return a new SoundBuffer whose contents are copied from the given Array or ByteArray.\\\"\\n\\n\\t| new |\\n\\tnew := SoundBuffer newMonoSampleCount: anArray size.\\n\\t1 to: anArray size do: [:i | new at: i put: (anArray at: i)].\\n\\t^ new\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfromByteArray: aByteArray\\n\\t\\\"Convert the given ByteArray (stored with the most significant byte first) into 16-bit sample buffer.\\\"\\n\\n\\t| n buf src w |\\n\\tn := aByteArray size // 2.\\n\\tbuf := SoundBuffer newMonoSampleCount: n.\\n\\tsrc := 1.\\n\\t1 to: n do: [:i |\\n\\t\\tw := ((aByteArray at: src) bitShift: 8) + (aByteArray at: src + 1).\\n\\t\\tw > 32767 ifTrue: [w := w - 65536].\\n\\t\\tbuf at: i put: w.\\n\\t\\tsrc := src + 2].\\n\\t^ buf\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 13:25'!\\nnew: anInteger\\n\\t\\\"See the comment in newMonoSampleCount:. To avoid confusion, it is best to create new instances using newMonoSampleCount: or newStereoSampleCount:.\\\"\\n\\n\\t^ self newMonoSampleCount: anInteger\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 12:44'!\\nnewMonoSampleCount: anInteger\\n\\t\\\"Return a SoundBuffer large enough to hold the given number of monaural samples (i.e., 16-bit words).\\\"\\n\\t\\\"Details: The size is rounded up to an even number, since the underlying representation is in terms of 32-bit words.\\\"\\n\\n\\t^ self basicNew: (anInteger + 1) // 2\\n! !\\n\\n!SoundBuffer class methodsFor: 'instance creation' stamp: 'jm 9/17/97 12:52'!\\nnewStereoSampleCount: anInteger\\n\\t\\\"Return a SoundBuffer large enough to hold the given number of stereo slices. A stereo 'slice' consists of two 16-bit samples, one for each channel.\\\"\\n\\n\\t^ self basicNew: anInteger\\n! !\\n\\n\\n!SoundBuffer class methodsFor: 'objects from disk' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartUp\\n\\t\\\"Check if the word order has changed from the last save.\\\"\\n\\n\\t| la |\\n\\tla := ShortIntegerArray classPool at: #LastSaveOrder.\\n\\t((la at: 2) = 42 and: [(la at: 1) = 13]) \\n\\t\\tifTrue: [^self swapHalves]. \\\"Reverse the two 16-bit halves.\\\"\\n\\t\\t\\t\\t\\\"Another reversal happened automatically which reversed the bytes.\\\"\\n! !\\n\\n!SoundBuffer class methodsFor: 'objects from disk' stamp: 'nk 2/22/2005 15:29'!\\nstartUpFrom: anImageSegment \\n\\t\\\"In this case, do we need to swap word halves when reading this segment?\\\"\\n\\n\\t^SmalltalkImage current endianness ~~ anImageSegment endianness \\n\\t\\tifTrue: [Message selector: #swapHalves\\t\\\"will be run on each instance\\\"]\\n\\t\\tifFalse: [nil]! !\\nObject subclass: #SoundCodec\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundCodec commentStamp: '<historical>' prior: 0!\\nI am an abstract class that describes the protocol for sound codecs. Each codec (the name stems from \\\"COder/DECoder\\\") describes a particular algorithm for compressing and decompressing sound data. Most sound codecs are called 'lossy' because they lose information; the decompressed sound data is not exactly the same as the original data.\\n!\\n\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'jm 2/2/1999 16:01'!\\ncompressAndDecompress: aSound\\n\\t\\\"Compress and decompress the given sound. Useful for testing.\\\"\\n\\t\\\"(MuLawCodec new compressAndDecompress: (SampledSound soundNamed: 'camera')) play\\\"\\n\\n\\t^ (self compressSound: aSound) asSound\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncompressSound: aSound\\n\\t\\\"Compress the entirety of the given sound with this codec. Answer a CompressedSoundData.\\\"\\n\\n\\t| compressed channels |\\n\\tcompressed := CompressedSoundData new\\n\\t\\tcodecName: self class name;\\n\\t\\tsoundClassName: aSound class name.\\n\\t(aSound isKindOf: SampledSound) ifTrue: [\\n\\t\\tchannels := Array new: 1.\\n\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound samples).\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: 1;\\n\\t\\t\\tloopEnd: aSound samples size;\\n\\t\\t\\tloopLength: 0.0;\\n\\t\\t\\tperceivedPitch: 100.0;\\n\\t\\t\\tgain: aSound loudness.\\n\\t\\t^ compressed].\\n\\t(aSound isKindOf: LoopedSampledSound) ifTrue: [\\n\\t\\taSound isStereo\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tchannels := Array new: 2.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples).\\n\\t\\t\\t\\tchannels at: 2 put: (self encodeSoundBuffer: aSound rightSamples)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tchannels := Array new: 1.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples)].\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: aSound firstSample;\\n\\t\\t\\tloopEnd: aSound loopEnd;\\n\\t\\t\\tloopLength: aSound loopLength;\\n\\t\\t\\tperceivedPitch: aSound perceivedPitch;\\n\\t\\t\\tgain: aSound gain.\\n\\t\\t^ compressed].\\n\\tself error: 'you can only compress sampled sounds'.\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncompressSound: aSound atRate: desiredSampleRate\\n\\t\\\"Compress the entirety of the given sound with this codec. Answer a CompressedSoundData.\\\"\\n\\n\\t| compressed channels samples newRate ratio buffer |\\n\\n\\tcompressed := CompressedSoundData new\\n\\t\\tcodecName: self class name;\\n\\t\\tsoundClassName: aSound class name.\\n\\t(aSound isKindOf: SampledSound) ifTrue: [\\n\\t\\t(desiredSampleRate isNil or: \\n\\t\\t\\t\\t[(ratio := aSound originalSamplingRate // desiredSampleRate) <= 1]) ifTrue: [\\n\\t\\t\\tsamples := aSound samples.\\n\\t\\t\\tnewRate := aSound originalSamplingRate.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tbuffer := aSound samples.\\n\\t\\t\\tsamples := SoundBuffer \\n\\t\\t\\t\\taverageEvery: ratio \\n\\t\\t\\t\\tfrom: buffer \\n\\t\\t\\t\\tupTo: buffer monoSampleCount.\\n\\t\\t\\tnewRate := aSound originalSamplingRate / ratio.\\n\\t\\t].\\n\\n\\t\\tchannels := Array new: 1.\\n\\t\\tchannels at: 1 put: (self encodeSoundBuffer: samples).\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: newRate;\\n\\t\\t\\tfirstSample: 1;\\n\\t\\t\\tloopEnd: samples size;\\n\\t\\t\\tloopLength: 0.0;\\n\\t\\t\\tperceivedPitch: 100.0;\\n\\t\\t\\tgain: aSound loudness.\\n\\t\\t^ compressed].\\n\\t(aSound isKindOf: LoopedSampledSound) ifTrue: [\\n\\t\\taSound isStereo\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tchannels := Array new: 2.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples).\\n\\t\\t\\t\\tchannels at: 2 put: (self encodeSoundBuffer: aSound rightSamples)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tchannels := Array new: 1.\\n\\t\\t\\t\\tchannels at: 1 put: (self encodeSoundBuffer: aSound leftSamples)].\\n\\t\\tcompressed\\n\\t\\t\\tchannels: channels;\\n\\t\\t\\tsamplingRate: aSound originalSamplingRate;\\n\\t\\t\\tfirstSample: aSound firstSample;\\n\\t\\t\\tloopEnd: aSound loopEnd;\\n\\t\\t\\tloopLength: aSound loopLength;\\n\\t\\t\\tperceivedPitch: aSound perceivedPitch;\\n\\t\\t\\tgain: aSound gain.\\n\\t\\t^ compressed].\\n\\tself error: 'you can only compress sampled sounds'.\\n! !\\n\\n!SoundCodec methodsFor: 'compress/decompress' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecompressSound: aCompressedSound\\n\\t\\\"Decompress the entirety of the given compressed sound with this codec and answer the resulting sound.\\\"\\n\\n\\t| channels sound |\\n\\tchannels := aCompressedSound channels\\n\\t\\tcollect: [:compressed | self decodeCompressedData: compressed].\\n\\t'SampledSound' = aCompressedSound soundClassName ifTrue: [\\n\\t\\tsound := SampledSound\\n\\t\\t\\tsamples: channels first\\n\\t\\t\\tsamplingRate: (aCompressedSound samplingRate).\\n\\t\\tsound loudness: aCompressedSound gain.\\n\\t\\t^ sound].\\n\\t'LoopedSampledSound' = aCompressedSound soundClassName ifTrue: [\\n\\t\\taCompressedSound loopLength = 0\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tsound := LoopedSampledSound\\n\\t\\t\\t\\t\\tunloopedSamples: channels first\\n\\t\\t\\t\\t\\tpitch: aCompressedSound perceivedPitch\\n\\t\\t\\t\\t\\tsamplingRate: aCompressedSound samplingRate]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tsound := LoopedSampledSound\\n\\t\\t\\t\\t\\tsamples: channels first\\n\\t\\t\\t\\t\\tloopEnd: aCompressedSound loopEnd\\n\\t\\t\\t\\t\\tloopLength: aCompressedSound loopLength\\n\\t\\t\\t\\t\\tpitch: aCompressedSound perceivedPitch\\n\\t\\t\\t\\t\\tsamplingRate: aCompressedSound samplingRate].\\n\\t\\tchannels size > 1 ifTrue: [sound rightSamples: channels last].\\n\\t\\tsound\\n\\t\\t\\tfirstSample: aCompressedSound firstSample;\\n\\t\\t\\tgain: aCompressedSound gain.\\n\\t\\tsound\\n\\t\\t\\tsetPitch: 100.0\\n\\t\\t\\tdur: (channels first size / aCompressedSound samplingRate)\\n\\t\\t\\tloudness: 1.0.\\n\\t\\t^ sound].\\n\\tself error: 'unknown sound class'.\\n! !\\n\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'di 2/8/1999 14:23'!\\nbytesPerEncodedFrame\\n\\t\\\"Answer the number of bytes required to hold one frame of compressed sound data. Answer zero if this codec produces encoded frames of variable size.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:38'!\\ndecodeFrames: frameCount from: srcByteArray at: srcIndex into: dstSoundBuffer at: dstIndex\\n\\t\\\"Decode the given number of monophonic frames starting at the given index in the given ByteArray of compressed sound data and storing the decoded samples into the given SoundBuffer starting at the given destination index. Answer a pair containing the number of bytes of compressed data consumed and the number of decompressed samples produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:39'!\\nencodeFrames: frameCount from: srcSoundBuffer at: srcIndex into: dstByteArray at: dstIndex\\n\\t\\\"Encode the given number of frames starting at the given index in the given monophonic SoundBuffer and storing the encoded sound data into the given ByteArray starting at the given destination index. Encode only as many complete frames as will fit into the destination. Answer a pair containing the number of samples consumed and the number of bytes of compressed data produced.\\\"\\n\\t\\\"Note: Assume that the sender has ensured that the given number of frames will not exhaust either the source or destination buffers.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/4/1999 11:30'!\\nreset\\n\\t\\\"Reset my encoding and decoding state. Optional. This default implementation does nothing.\\\"\\n! !\\n\\n!SoundCodec methodsFor: 'subclass responsibilities' stamp: 'jm 2/2/1999 15:45'!\\nsamplesPerFrame\\n\\t\\\"Answer the number of sound samples per compression frame.\\\"\\n\\n\\tself subclassResponsibility.\\n! !\\n\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndecodeCompressedData: aByteArray\\n\\t\\\"Decode the entirety of the given encoded data buffer with this codec. Answer a monophonic SoundBuffer containing the uncompressed samples.\\\"\\n\\n\\t| frameCount result increments |\\n\\tframeCount := self frameCount: aByteArray.\\n\\tresult := SoundBuffer newMonoSampleCount: frameCount * self samplesPerFrame.\\n\\tself reset.\\n\\tincrements := self decodeFrames: frameCount from: aByteArray at: 1 into: result at: 1.\\n\\t((increments first = aByteArray size) and: [increments last = result size]) ifFalse: [\\n\\t\\tself error: 'implementation problem; increment sizes should match buffer sizes'].\\n\\t^ result\\n! !\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nencodeSoundBuffer: aSoundBuffer\\n\\t\\\"Encode the entirety of the given monophonic SoundBuffer with this codec. Answer a ByteArray containing the compressed sound data.\\\"\\n\\n\\t| codeFrameSize frameSize fullFrameCount lastFrameSamples result increments finalFrame i lastIncs |\\n\\tframeSize := self samplesPerFrame.\\n\\tfullFrameCount := aSoundBuffer monoSampleCount // frameSize.\\n\\tlastFrameSamples := aSoundBuffer monoSampleCount - (fullFrameCount * frameSize).\\n\\tcodeFrameSize := self bytesPerEncodedFrame.\\n\\tcodeFrameSize = 0 ifTrue:\\n\\t\\t[\\\"Allow room for 1 byte per sample for variable-length compression\\\"\\n\\t\\tcodeFrameSize := frameSize].\\n\\tlastFrameSamples > 0\\n\\t\\tifTrue: [result := ByteArray new: (fullFrameCount + 1) * codeFrameSize]\\n\\t\\tifFalse: [result := ByteArray new: fullFrameCount * codeFrameSize].\\n\\tself reset.\\n\\tincrements := self encodeFrames: fullFrameCount from: aSoundBuffer at: 1 into: result at: 1.\\n\\tlastFrameSamples > 0 ifTrue: [\\n\\t\\tfinalFrame := SoundBuffer newMonoSampleCount: frameSize.\\n\\t\\ti := fullFrameCount * frameSize.\\n\\t\\t1 to: lastFrameSamples do: [:j |\\n\\t\\t\\tfinalFrame at: j put: (aSoundBuffer at: (i := i + 1))].\\n\\t\\tlastIncs := self encodeFrames: 1 from: finalFrame at: 1 into: result at: 1 + increments second.\\n\\t\\tincrements := Array with: increments first + lastIncs first\\n\\t\\t\\t\\t\\t\\t\\twith: increments second + lastIncs second].\\n\\tincrements second < result size\\n\\t\\tifTrue: [^ result copyFrom: 1 to: increments second]\\n\\t\\tifFalse: [^ result]\\n! !\\n\\n!SoundCodec methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nframeCount: aByteArray\\n\\t\\\"Compute the frame count for this byteArray. This default computation will have to be overridden by codecs with variable frame sizes.\\\"\\n\\n\\t| codeFrameSize |\\n\\tcodeFrameSize := self bytesPerEncodedFrame.\\n\\t(aByteArray size \\\\\\\\ codeFrameSize) = 0 ifFalse:\\n\\t\\t[self error: 'encoded buffer is not an even multiple of the encoded frame size'].\\n\\t^ aByteArray size // codeFrameSize! !\\nAlignmentMorph subclass: #SoundDemoMorph\\n\\tinstanceVariableNames: 'soundColumn'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'tk 2/19/2001 17:49'!\\nmakeControls\\n\\n\\t| bb r cc |\\n\\tcc _ Color black.\\n\\tr _ AlignmentMorph newRow.\\n\\tr color: cc; borderWidth: 0; layoutInset: 0.\\n\\tr hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V1';\\t\\t\\tactionSelector: #playV1).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V2';\\t\\t\\tactionSelector: #playV2).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'V3';\\t\\t\\tactionSelector: #playV3).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'All';\\t\\t\\tactionSelector: #playAll).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tr addMorphBack: (bb label: 'Stop';\\t\\tactionSelector: #stopSound).\\n\\t^ r\\n! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:34'!\\nplayAll\\n\\t| snd |\\n\\tsoundColumn submorphs isEmpty\\n\\t\\tifTrue: [^ self].\\n\\tself setTimbreFromTile: soundColumn submorphs first.\\n\\tsnd _ SampledSound bachFugueVoice1On: SampledSound new.\\n\\tsoundColumn submorphs size >= 2\\n\\t\\tifTrue: [\\\"\\\"self setTimbreFromTile: soundColumn submorphs second.\\n\\t\\t\\tsnd _ snd\\n\\t\\t\\t\\t\\t\\t+ (AbstractSound bachFugueVoice2On: SampledSound new)].\\n\\tsoundColumn submorphs size >= 3\\n\\t\\tifTrue: [\\\"\\\"self setTimbreFromTile: soundColumn submorphs third.\\n\\t\\t\\tsnd _ snd\\n\\t\\t\\t\\t\\t\\t+ (AbstractSound bachFugueVoice3On: SampledSound new)].\\n\\tsnd play! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV1\\n\\tsoundColumn submorphs isEmpty\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs first).\\n\\t(SampledSound bachFugueVoice1On: SampledSound new) play! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV2\\n\\tsoundColumn submorphs size < 2\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs second).\\n\\t(SampledSound bachFugueVoice2On: SampledSound new) playSilentlyUntil: 4.8;\\n\\t\\t resumePlaying! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'dgd 2/22/2003 13:35'!\\nplayV3\\n\\tsoundColumn submorphs size < 3\\n\\t\\tifTrue: [^ self].\\n\\tself\\n\\t\\tsetTimbreFromTile: (soundColumn submorphs third).\\n\\t(AbstractSound bachFugueVoice3On: SampledSound new) playSilentlyUntil: 14.4;\\n\\t\\t resumePlaying! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:09'!\\nsetTimbreFromTile: aSoundTile\\n\\n\\tSampledSound defaultSampleTable: aSoundTile sound samples.\\n\\tSampledSound nominalSamplePitch: 400.\\n! !\\n\\n!SoundDemoMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:09'!\\nstopSound\\n\\n\\tSoundPlayer shutDown.\\n! !\\n\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGray! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:04'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\t wrapCentering: #center;\\n\\t\\t cellPositioning: #topCenter;\\n\\t\\t hResizing: #spaceFill;\\n\\t\\t vResizing: #spaceFill;\\n\\t\\t layoutInset: 3;\\n\\t\\t addMorph: self makeControls;\\n\\tinitializeSoundColumn.\\n\\tself extent: 118 @ 150! !\\n\\n!SoundDemoMorph methodsFor: 'initialization' stamp: 'jam 3/9/2003 17:52'!\\ninitializeSoundColumn\\n\\\"initialize the receiver's soundColumn\\\"\\n\\tsoundColumn _ AlignmentMorph newColumn.\\n\\tsoundColumn enableDragNDrop.\\n\\tself addMorphBack: soundColumn! !\\nAbstractMediaEventMorph subclass: #SoundEventMorph\\n\\tinstanceVariableNames: 'sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundEventMorph methodsFor: 'as yet unclassified' stamp: 'RAA 12/7/2000 13:01'!\\nsound: aSound\\n\\n\\tsound _ aSound.\\n\\tself setBalloonText: 'a sound of duration ',(sound duration roundTo: 0.1) printString,' seconds'.! !\\n\\n\\n!SoundEventMorph methodsFor: 'caching' stamp: 'RAA 12/8/2000 09:52'!\\nreleaseCachedState\\n\\n\\tsuper releaseCachedState.\\n\\tsound _ sound compressWith: GSMCodec.\\n! !\\n\\n\\n!SoundEventMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightGreen! !\\n\\n!SoundEventMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:39'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself height: 10! !\\n\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/7/2000 12:36'!\\naddMorphsTo: morphList pianoRoll: pianoRoll eventTime: t betweenTime: leftTime and: rightTime\\n\\n\\t| startX lengthInTicks endX |\\n\\n\\tstartTimeInScore > rightTime ifTrue: [^ self]. \\n\\tlengthInTicks _ pianoRoll scorePlayer ticksForMSecs: sound duration * 1000.0.\\n\\tstartTimeInScore + lengthInTicks < leftTime ifTrue: [^ self].\\n\\tstartX _ pianoRoll xForTime: startTimeInScore.\\n\\tendX _ pianoRoll xForTime: startTimeInScore + lengthInTicks.\\n\\tmorphList add: \\n\\t\\t(self left: startX; width: endX - startX).\\n\\n! !\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/7/2000 12:29'!\\nencounteredAtTime: ticks inScorePlayer: scorePlayer atIndex: index inEventTrack: track secsPerTick: secsPerTick\\n\\n\\t\\\"hack... since we are called from within the SoundPlayer loop, the Semaphore will\\n\\tblock attempts to play directly from here\\\"\\n\\tWorldState addDeferredUIMessage: [sound play].! !\\n\\n!SoundEventMorph methodsFor: 'piano rolls' stamp: 'RAA 12/9/2000 18:48'!\\njustDroppedIntoPianoRoll: newOwner event: evt\\n\\t\\n\\t| startX lengthInTicks endX |\\n\\n\\tsuper justDroppedIntoPianoRoll: newOwner event: evt.\\n\\n\\tstartTimeInScore _ newOwner timeForX: self left.\\n\\tlengthInTicks _ newOwner scorePlayer ticksForMSecs: sound duration * 1000.0.\\n\\tendTimeInScore _ startTimeInScore + lengthInTicks.\\n\\n\\tendTimeInScore > newOwner scorePlayer durationInTicks ifTrue:\\n\\t\\t[newOwner scorePlayer updateDuration].\\n\\n\\tstartX _ newOwner xForTime: startTimeInScore.\\n\\tendX _ newOwner xForTime: endTimeInScore.\\n\\tself width: endX - startX.\\n\\n! !\\nSoundRecorder subclass: #SoundInputStream\\n\\tinstanceVariableNames: 'bufferSize mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SoundInputStream commentStamp: '<historical>' prior: 0!\\nThis subclass of SoundRecorder supports real-time processing of incoming sound data. The sound input process queues raw sound buffers, allowing them to be read and processed by the client as they become available. A semaphore is used to synchronize between the record process and the client process. Since sound data is buffered, the client process may lag behind the input process without losing data.\\n!\\n\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nbufferCount\\n\\t\\\"Answer the number of sound buffers that have been queued.\\\"\\n\\n\\t| n |\\n\\tmutex ifNil: [^ 0]. \\\"not recording\\\"\\n\\tmutex critical: [n := recordedBuffers size].\\n\\t^ n\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'jm 9/6/1999 10:36'!\\nbufferSize\\n\\n\\t^ bufferSize\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nbufferSize: aNumber\\n\\t\\\"Set the sound buffer size. Buffers of this size will be queued for the client to process.\\\"\\n\\n\\tbufferSize := aNumber truncated.\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'jm 9/8/1999 15:23'!\\nisRecording\\n\\t\\\"Answer true if the sound input process is running.\\\"\\n\\n\\t^ recordProcess ~~ nil\\n! !\\n\\n!SoundInputStream methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnextBufferOrNil\\n\\t\\\"Answer the next input buffer or nil if no buffer is available.\\\"\\n\\n\\t| result |\\n\\tmutex ifNil: [^ nil]. \\\"not recording\\\"\\n\\tmutex critical: [\\n\\t\\trecordedBuffers size > 0\\n\\t\\t\\tifTrue: [result := recordedBuffers removeFirst]\\n\\t\\t\\tifFalse: [result := nil]].\\n\\t^ result\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tbufferSize := 1024.\\n\\tmutex := nil.\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartRecording\\n\\t\\\"Start the sound input process.\\\"\\n\\n\\trecordProcess ifNotNil: [self stopRecording].\\n\\trecordedBuffers := OrderedCollection new: 100.\\n\\tmutex := Semaphore forMutualExclusion.\\n\\tsuper startRecording.\\n\\tpaused := false.\\n! !\\n\\n!SoundInputStream methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopRecording\\n\\t\\\"Turn off the sound input process and close the driver.\\\"\\n\\n\\tsuper stopRecording.\\n\\trecordedBuffers := nil.\\n\\tmutex := nil.\\n! !\\n\\n\\n!SoundInputStream methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nallocateBuffer\\n\\t\\\"Allocate a new buffer and reset nextIndex. This message is sent by the sound input process.\\\"\\n\\n\\tcurrentBuffer := SoundBuffer newMonoSampleCount: bufferSize.\\n\\tnextIndex := 1.\\n! !\\n\\n!SoundInputStream methodsFor: 'private' stamp: 'jm 9/8/1999 15:24'!\\nemitBuffer: buffer\\n\\t\\\"Queue a buffer for later processing. This message is sent by the sound input process.\\\"\\n\\n\\tmutex critical: [recordedBuffers addLast: buffer].\\n! !\\nRectangleMorph subclass: #SoundLoopMorph\\n\\tinstanceVariableNames: 'samplesUntilNextControl seqSound cursor controlIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:21'!\\naddCursorMorph\\n\\tself addMorph:\\n\\t\\t(cursor _ (RectangleMorph\\n\\t\\t\\t\\tnewBounds: (self innerBounds topLeft extent: 1@self innerBounds height)\\n\\t\\t\\t\\tcolor: Color red)\\n\\t\\t\\t\\t\\t\\tborderWidth: 0)! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:11'!\\nallowSubmorphExtraction\\n\\n\\t^ true! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 1/5/98 17:31'!\\nbuildSound\\n\\t\\\"Build a compound sound for the next iteration of the loop.\\\"\\n\\n\\t| mixer soundMorphs startTime pan |\\n\\tmixer _ MixedSound new.\\n\\tmixer add: (RestSound dur: (self width - (2 * borderWidth)) / 128.0).\\n\\tsoundMorphs _ self submorphs select: [:m | m respondsTo: #sound].\\n\\tsoundMorphs do: [:m |\\n\\t\\tstartTime _ (m position x - (self left + borderWidth)) / 128.0.\\n\\t\\tpan _ (m position y - (self top + borderWidth)) asFloat / (self height - (2 * borderWidth) - m height).\\n\\t\\tmixer add: ((RestSound dur: startTime), m sound copy) pan: pan].\\n\\t^ mixer\\n! !\\n\\n!SoundLoopMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:11'!\\nplay\\n\\t\\\"Play this sound to the sound ouput port in real time.\\\"\\n\\n\\tself reset.\\n\\tSoundPlayer playSound: self.\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'dropping/grabbing' stamp: 'jm 11/14/97 11:11'!\\nwantsDroppedMorph: aMorph event: evt\\n\\n\\t^ aMorph respondsTo: #sound\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'geometry' stamp: 'jm 11/14/97 11:21'!\\nextent: newExtent\\n\\tsuper extent: (newExtent truncateTo: 128@128) + (self borderWidth*2)! !\\n\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 15:07'!\\ndefaultBounds\\n\\\"answer the default bounds for the receiver\\\"\\n\\t^ 0 @ 0 corner: 128 @ 128 + (self defaultBorderWidth * 2)! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightBlue! !\\n\\n!SoundLoopMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:50'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\t\\n\\tcontrolIndex _ 0.\\n\\tself addCursorMorph! !\\n\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\ncontrolRate\\n\\t\\\"Answer the number of control changes per second.\\\"\\n\\n\\t^ 32\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\ndoControl\\n\\n\\tseqSound doControl.\\n\\tcontrolIndex _ controlIndex + 1.\\n\\tcontrolIndex >= (self controlRate * (self innerBounds width // 128))\\n\\t\\tifTrue: [controlIndex _ 0].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 1/5/98 13:40'!\\nmixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol\\n\\t\\\"Repeatedly play my sounds.\\\"\\n\\n\\t| i count samplesNeeded |\\n\\ti _ startIndex.\\n\\tsamplesNeeded _ n.\\n\\t[samplesNeeded > 0] whileTrue: [\\n\\t\\tcount _ seqSound samplesRemaining min: samplesNeeded.\\n\\t\\tcount = 0 ifTrue: [\\n\\t\\t\\tself reset.\\n\\t\\t\\tcount _ seqSound samplesRemaining min: samplesNeeded.\\n\\t\\t\\tcount = 0 ifTrue: [^ self]]. \\\"zero length sound\\\"\\n\\t\\tseqSound mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: leftVol rightVol: rightVol.\\n\\t\\ti _ i + count.\\n\\t\\tsamplesNeeded _ samplesNeeded - count].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 1/26/98 22:05'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"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.\\\"\\n\\n\\t| fullVol samplesBetweenControlUpdates pastEnd i remainingSamples count |\\n\\tfullVol _ AbstractSound scaleFactor.\\n\\tsamplesBetweenControlUpdates _ self samplingRate // self controlRate.\\n\\tpastEnd _ startIndex + n. \\\"index just index of after last sample\\\"\\n\\ti _ startIndex.\\n\\t[i < pastEnd] whileTrue: [\\n\\t\\tremainingSamples _ self samplesRemaining.\\n\\t\\tremainingSamples <= 0 ifTrue: [^ self].\\n\\t\\tcount _ pastEnd - i.\\n\\t\\tsamplesUntilNextControl < count ifTrue: [count _ samplesUntilNextControl].\\n\\t\\tremainingSamples < count ifTrue: [count _ remainingSamples].\\n\\t\\tself mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: fullVol rightVol: fullVol.\\n\\t\\tsamplesUntilNextControl _ samplesUntilNextControl - count.\\n\\t\\tsamplesUntilNextControl <= 0 ifTrue: [\\n\\t\\t\\tself doControl.\\n\\t\\t\\tsamplesUntilNextControl _ samplesBetweenControlUpdates].\\n\\t\\ti _ i + count].\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\npositionCursor\\n\\t| x |\\n\\tx _ controlIndex * 128 // self controlRate.\\n\\tcursor position: self innerBounds topLeft + (x@0)\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:21'!\\nreset\\n\\t\\\"Reset my internal state for a replay.\\\"\\n\\n\\tseqSound _ self buildSound reset.\\n\\tsamplesUntilNextControl _ (self samplingRate // self controlRate).\\n\\tcontrolIndex _ 0.\\n\\tself positionCursor! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:11'!\\nsamplesRemaining\\n\\n\\t^ 1000000\\n! !\\n\\n!SoundLoopMorph methodsFor: 'playing' stamp: 'jm 11/14/97 11:11'!\\nsamplingRate\\n\\t\\\"Answer the sampling rate in samples per second.\\\"\\n\\n\\t^ SoundPlayer samplingRate! !\\n\\n\\n!SoundLoopMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:21'!\\nstep\\n\\tself positionCursor! !\\n\\n!SoundLoopMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:11'!\\nstop\\n\\t\\\"Stop playing this sound.\\\"\\n\\n\\tSoundPlayer pauseSound: self.\\n! !\\n\\n\\n!SoundLoopMorph methodsFor: 'testing' stamp: 'jm 11/14/97 11:21'!\\nstepTime\\n\\n\\t^ 50\\n! !\\nImageMorph subclass: #SoundMorph\\n\\tinstanceVariableNames: 'sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n!SoundMorph commentStamp: '<historical>' prior: 0!\\nNote: as of December 2000, this does not work. SoundMorph>>buildImage requires the sound to implement #volumeEnvelopeScaledTo: and as yet, no one does.!\\n\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:21'!\\nbuildImage\\n\\t| scale env h imageColor |\\n\\towner ifNil: [scale _ 128@128] \\\"Default is 128 pix/second, 128 pix fullscale\\\"\\n\\t\\tifNotNil: [scale _ owner soundScale].\\n\\tenv _ sound volumeEnvelopeScaledTo: scale.\\n\\tself image: (ColorForm extent: env size @ env max).\\n\\t1 to: image width do:\\n\\t\\t[:x | h _ env at: x.\\n\\t\\timage fillBlack: ((x-1)@(image height-h//2) extent: 1@h)].\\n\\timageColor _ #(black red orange green blue) atPin:\\n\\t\\t\\t\\t\\t\\t(sound pitch / 110.0) rounded highBit.\\n\\timage colors: (Array with: Color transparent with: (Color perform: imageColor)).\\n! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nreset\\n\\tsound reset! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nsound\\n\\t^ sound! !\\n\\n!SoundMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nsound: aSound\\n\\tsound _ aSound copy.\\n\\tsound reset.\\n\\tself buildImage! !\\n\\n\\n!SoundMorph methodsFor: 'dropping/grabbing' stamp: 'ar 10/5/2000 20:05'!\\njustDroppedInto: aMorph event: anEvent\\n\\t| relPosition |\\n\\trelPosition _ self position - aMorph innerBounds topLeft.\\n\\trelPosition _ (relPosition x roundTo: 8) @ relPosition y.\\n\\tself position: aMorph innerBounds topLeft + relPosition.\\n\\tsound copy play.\\n\\t^super justDroppedInto: aMorph event: anEvent! !\\n\\n\\n!SoundMorph methodsFor: 'initialization' stamp: 'jm 12/17/97 22:43'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself sound: (FMSound pitch: 880.0 dur: 0.2 loudness: 0.8).\\n! !\\nObject subclass: #SoundPlayer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ActiveSounds Buffer BufferIndex BufferMSecs LastBuffer PlayerProcess PlayerSemaphore ReadyForBuffer ReverbState SamplingRate SoundJustStarted SoundSupported Stereo UseReadySemaphore UseReverb'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundPlayer class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'jm 8/13/1998 15:00'!\\nbufferMSecs\\n\\n\\t^ BufferMSecs\\n! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'jm 1/27/98 09:28'!\\nreverbState\\n\\n\\t^ ReverbState! !\\n\\n!SoundPlayer class methodsFor: 'accessing'!\\nsamplingRate\\n\\n\\t^ SamplingRate! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'JMM 11/6/2000 10:16'!\\nsetVolumeLeft: aLeftVolume volumeRight: aRightVolume\\n\\t\\\"Set sound pass in float 0.0-1.0 for left and right channel, with possible 2.0 or higher to overdrive sound channel \\\"\\n\\tself primSoundSetVolumeLeft: aLeftVolume volumeRight: aRightVolume! !\\n\\n!SoundPlayer class methodsFor: 'accessing' stamp: 'JMM 11/6/2000 10:17'!\\nsoundVolume\\n\\t\\\"Return sound as array of doubles left then right channel, range is 0.0 to 1.0 but may be overdriven\\\"\\n\\t^self primSoundGetVolume! !\\n\\n!SoundPlayer class methodsFor: 'accessing'!\\nstereo\\n\\n\\t^ Stereo\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundPlayer initialize; shutDown; startUp\\\"\\n\\t\\\"Details: BufferMSecs represents a tradeoff between latency and quality. If BufferMSecs is too low, the sound will not play smoothly, especially during long-running primitives such as large BitBlts. If BufferMSecs is too high, there will be a long time lag between when a sound buffer is submitted to be played and when that sound is actually heard. BufferMSecs is typically in the range 50-200.\\\"\\n\\n\\tSamplingRate := 22050.\\n\\tBufferMSecs := 120.\\n\\tStereo := true.\\n\\tUseReverb ifNil: [UseReverb := true].\\n! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'ar 1/24/2002 18:40'!\\nuseLastBuffer\\n\\t^LastBuffer notNil! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuseLastBuffer: aBool\\n\\tBuffer ifNil:[^self].\\n\\taBool \\n\\t\\tifTrue:[LastBuffer := SoundBuffer basicNew: Buffer basicSize]\\n\\t\\tifFalse:[LastBuffer := nil]\\t! !\\n\\n!SoundPlayer class methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nuseShortBuffer\\n\\t\\\"Experimental support for real-time MIDI input. This only works on platforms whose hardware allows very short buffer sizes. It has been tested on a Macintosh Powerbook G3.\\\"\\n\\t\\\"SoundPlayer useShortBuffer\\\"\\n\\n\\tself shutDown.\\n\\tBufferMSecs := 15.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'jm 1/29/98 18:56'!\\nisReverbOn\\n\\n\\t^ ReverbState ~~ nil\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'ar 1/24/2002 18:41'!\\nlastPlayBuffer\\n\\t^LastBuffer! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\noldStylePlayLoop\\n\\t\\\"This version of the play loop is used if the VM does not yet support sound primitives that signal a semaphore when a sound buffer becomes available.\\\"\\n\\n\\t| bytesPerSlice count |\\n\\tbytesPerSlice := Stereo ifTrue: [4] ifFalse: [2].\\n\\t[true] whileTrue: [\\n\\t\\t[(count := self primSoundAvailableBytes // bytesPerSlice) > 100]\\n\\t\\t\\twhileFalse: [(Delay forMilliseconds: 1) wait].\\n\\n\\t\\tcount := count min: Buffer stereoSampleCount.\\n\\t\\tPlayerSemaphore critical: [\\n\\t\\t\\tActiveSounds := ActiveSounds select: [:snd | snd samplesRemaining > 0].\\n\\t\\t\\tActiveSounds do: [:snd |\\n\\t\\t\\t\\tsnd ~~ SoundJustStarted ifTrue: [\\n\\t\\t\\t\\t\\tsnd playSampleCount: count into: Buffer startingAt: 1]].\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: 1 count: count].\\n\\t\\t\\tself primSoundPlaySamples: count from: Buffer startingAt: 1.\\n\\t\\t\\tBuffer primFill: 0.\\n\\t\\t\\tSoundJustStarted := nil]].\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayLoop\\n\\t\\\"The sound player process loop.\\\"\\n\\n\\t| bytesPerSlice count willStop mayStop |\\n\\tmayStop := Preferences soundStopWhenDone.\\n\\tbytesPerSlice := Stereo ifTrue: [4] ifFalse: [2].\\n\\t[true] whileTrue: [\\n\\t\\t[(count := self primSoundAvailableBytes // bytesPerSlice) > 100]\\n\\t\\t\\twhileFalse: [ReadyForBuffer wait].\\n\\n\\t\\tcount := count min: Buffer stereoSampleCount.\\n\\t\\tPlayerSemaphore critical: [\\n\\t\\t\\tActiveSounds := ActiveSounds select: [:snd | snd samplesRemaining > 0].\\n\\t\\t\\tActiveSounds do: [:snd |\\n\\t\\t\\t\\tsnd ~~ SoundJustStarted ifTrue: [\\n\\t\\t\\t\\t\\tsnd playSampleCount: count into: Buffer startingAt: 1]].\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: 1 count: count].\\n\\t\\t\\tself primSoundPlaySamples: count from: Buffer startingAt: 1.\\n\\t\\t\\twillStop := mayStop and:[\\n\\t\\t\\t\\t\\t\\t(ActiveSounds size = 0) and:[\\n\\t\\t\\t\\t\\t\\t\\tself isAllSilence: Buffer size: count]].\\n\\t\\t\\tLastBuffer ifNotNil:[\\n\\t\\t\\t\\tLastBuffer replaceFrom: 1 to: LastBuffer size with: Buffer startingAt: 1.\\n\\t\\t\\t].\\n\\t\\t\\twillStop\\n\\t\\t\\t\\tifTrue:[self shutDown. PlayerProcess := nil]\\n\\t\\t\\t\\tifFalse:[Buffer primFill: 0].\\n\\t\\t\\tSoundJustStarted := nil].\\n\\t\\twillStop ifTrue:[^self].\\n\\t].\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'nk 2/16/2001 13:26'!\\nplayerProcess\\n\\t^PlayerProcess! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'ar 2/4/2001 18:01'!\\nstartPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag\\n\\t\\\"Start the sound player process. Terminate the old process, if any.\\\"\\n\\t\\\"SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false\\\"\\n\\t^self startPlayerProcessBufferSize: bufferSize \\n\\t\\t\\trate: samplesPerSecond \\n\\t\\t\\tstereo: stereoFlag \\n\\t\\t\\tsound: nil! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag sound: aSound\\n\\t\\\"Start the sound player process. Terminate the old process, if any.\\\"\\n\\t\\\"SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false\\\"\\n\\n\\tself stopPlayerProcess.\\n\\taSound\\n\\t\\tifNil:[ActiveSounds := OrderedCollection new]\\n\\t\\tifNotNil:[ActiveSounds := OrderedCollection with: aSound].\\n\\tBuffer := SoundBuffer newStereoSampleCount: (bufferSize // 4) * 4.\\n\\tLastBuffer ifNotNil:[LastBuffer := SoundBuffer basicNew: Buffer basicSize].\\n\\tPlayerSemaphore := Semaphore forMutualExclusion.\\n\\tSamplingRate := samplesPerSecond.\\n\\tStereo := stereoFlag.\\n\\tReadyForBuffer := Semaphore new.\\n\\tSoundSupported := true. \\\"Assume so\\\"\\n\\tUseReadySemaphore := true. \\\"set to false if ready semaphore not supported by VM\\\"\\n\\tself primSoundStartBufferSize: Buffer stereoSampleCount\\n\\t\\trate: samplesPerSecond\\n\\t\\tstereo: Stereo\\n\\t\\tsemaIndex: (Smalltalk registerExternalObject: ReadyForBuffer).\\n\\t\\\"Check if sound start prim was successful\\\"\\n\\tSoundSupported ifFalse:[^self].\\n\\tUseReadySemaphore\\n\\t\\tifTrue: [PlayerProcess := [SoundPlayer playLoop] newProcess]\\n\\t\\tifFalse: [PlayerProcess := [SoundPlayer oldStylePlayLoop] newProcess].\\n\\tUseReverb ifTrue: [self startReverb].\\n\\n\\tPlayerProcess priority: Processor userInterruptPriority.\\n\\tPlayerProcess resume.! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartReverb\\n\\t\\\"Start a delay-line style reverb with the given tap delays and gains. Tap delays are given in samples and should be prime integers; the following comment gives an expression that generates primes.\\\"\\n\\t\\\"Integer primesUpTo: 22050\\\"\\n\\n\\tUseReverb := true.\\n\\tReverbState := ReverbSound new\\n\\t\\ttapDelays: #(1601 7919) gains: #(0.12 0.07).\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopPlayerProcess\\n\\t\\\"Stop the sound player process.\\\"\\n\\t\\\"SoundPlayer stopPlayerProcess\\\"\\n\\n\\t(PlayerProcess == nil or:[PlayerProcess == Processor activeProcess]) \\n\\t\\tifFalse:[PlayerProcess terminate].\\n\\tPlayerProcess := nil.\\n\\tself primSoundStop.\\n\\tActiveSounds := OrderedCollection new.\\n\\tBuffer := nil.\\n\\tPlayerSemaphore := Semaphore forMutualExclusion.\\n\\tReadyForBuffer ifNotNil:\\n\\t\\t[Smalltalk unregisterExternalObject: ReadyForBuffer].\\n\\tReadyForBuffer := nil.\\n! !\\n\\n!SoundPlayer class methodsFor: 'player process' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopReverb\\n\\n\\tUseReverb := false.\\n\\tReverbState := nil.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'ar 2/1/2001 15:20'!\\ncanStartPlayer\\n\\t\\\"Some platforms do no support simultaneous record and play. If this is one of those platforms, return false if there is a running SoundRecorder.\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifTrue: [^ true].\\n\\tSoundRecorder anyActive ifTrue:[^false].\\n\\t^ true\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'di 8/5/1998 23:08'!\\nisPlaying: aSound\\n\\t^ ActiveSounds includes: aSound! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 8/23/97 20:38'!\\npauseSound: aSound\\n\\t\\\"Stop playing the given sound. Playing can be resumed from this point later.\\\"\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\tActiveSounds remove: aSound ifAbsent: []].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'ar 2/19/2001 01:28'!\\nplaySound: aSound\\n\\t\\\"Reset and start playing the given sound from its beginning.\\\"\\n\\n\\taSound reset.\\n\\taSound samplesRemaining = 0 ifTrue:[^self].\\n\\tself resumePlaying: aSound.\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 9/8/1998 17:54'!\\nresumePlaying: aSound\\n\\t\\\"Start playing the given sound without resetting it; it will resume playing from where it last stopped.\\\"\\n\\t\\\"Implementation detail: On virtual machines that don't support the quickstart primitive, you may need to edit this method to pass false to resumePlaying:quickStart:.\\\"\\n\\n\\tself resumePlaying: aSound quickStart: true.\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nresumePlaying: aSound quickStart: quickStart\\n\\t\\\"Start playing the given sound without resetting it; it will resume playing from where it last stopped. If quickStart is true, then try to start playing the given sound immediately.\\\"\\n\\n\\t| doQuickStart |\\n\\tPreferences soundsEnabled ifFalse: [^ self].\\n\\tdoQuickStart := quickStart.\\n\\tPreferences soundQuickStart ifFalse: [doQuickStart := false].\\n\\tPlayerProcess == nil ifTrue: [\\n\\t\\tself canStartPlayer ifFalse: [^ self].\\n\\t\\t^self startUpWithSound: aSound].\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\t(ActiveSounds includes: aSound)\\n\\t\\t\\tifTrue: [doQuickStart := false]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tdoQuickStart ifFalse: [ActiveSounds add: aSound]]].\\n\\n\\t\\\"quick-start the given sound, unless the sound player has just started\\\"\\n\\tdoQuickStart ifTrue: [self startPlayingImmediately: aSound].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopPlayingAll\\n\\t\\\"Stop playing all sounds.\\\"\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\tActiveSounds := ActiveSounds species new].\\n! !\\n\\n!SoundPlayer class methodsFor: 'playing' stamp: 'jm 9/13/97 19:49'!\\nwaitUntilDonePlaying: aSound\\n\\t\\\"Wait until the given sound is no longer playing.\\\"\\n\\n\\t[PlayerSemaphore critical: [ActiveSounds includes: aSound]]\\n\\t\\twhileTrue: [(Delay forMilliseconds: 100) wait].\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nboinkPitch: p dur: d loudness: l waveTable: waveTable pan: pan\\n\\t\\\"Play a decaying note on the given stream using the given wave table. Used for testing only.\\\"\\n\\n\\t| decay tableSize amplitude increment cycles i |\\n\\tdecay := 0.96.\\n\\ttableSize := waveTable size.\\n\\tamplitude := l asInteger min: 1000.\\n\\tincrement := ((p asFloat * tableSize asFloat) / SamplingRate asFloat) asInteger.\\n\\tincrement := (increment max: 1) min: (tableSize // 2).\\n\\tcycles := (d * SamplingRate asFloat) asInteger.\\n\\n\\ti := 1.\\n\\t1 to: cycles do: [:cycle |\\n\\t\\t(cycle \\\\\\\\ 100) = 0\\n\\t\\t\\tifTrue: [amplitude := (decay * amplitude asFloat) asInteger].\\n\\t\\ti := (((i - 1) + increment) \\\\\\\\ tableSize) + 1.\\n\\t\\tself playTestSample: (amplitude * (waveTable at: i)) // 1000 pan: pan].\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nboinkScale\\n\\t\\\"Tests the sound output primitives by playing a scale.\\\"\\n\\t\\\"SoundPlayer boinkScale\\\"\\n\\n\\t| sineTable pan |\\n\\tself shutDown.\\n\\tSamplingRate := 11025.\\n\\tStereo := true.\\n\\tsineTable := self sineTable: 1000.\\n\\tBuffer := SoundBuffer newStereoSampleCount: 1000.\\n\\tBufferIndex := 1.\\n\\tself primSoundStartBufferSize: Buffer stereoSampleCount\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n\\tpan := 0.\\n\\t#(261.626 293.665 329.628 349.229 391.996 440.001 493.884 523.252) do: [:p |\\n\\t\\tself boinkPitch: p dur: 0.3 loudness: 300 waveTable: sineTable pan: pan.\\n\\t\\tpan := pan + 125].\\n\\n\\tself boinkPitch: 261.626 dur: 1.0 loudness: 300 waveTable: sineTable pan: 500.\\n\\tself primSoundStop.\\n\\tself shutDown.\\n\\tSoundPlayer initialize. \\\"reset sampling rate, buffer size, and stereo flag\\\"\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayTestSample: s pan: pan\\n\\t\\\"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.\\\"\\n\\n\\t| sample leftSample |\\n\\tBufferIndex >= Buffer size\\n\\t\\tifTrue: [\\n\\t\\t\\t\\\"current buffer is full; play it\\\"\\n\\t\\t\\t[self primSoundAvailableBytes > 0]\\n\\t\\t\\t\\twhileFalse. \\\"wait for space to be available\\\"\\n\\t\\t\\tself primSoundPlaySamples: Buffer stereoSampleCount from: Buffer startingAt: 1.\\n\\t\\t\\tBuffer primFill: 0.\\n\\t\\t\\tBufferIndex := 1].\\n\\n\\tsample := s.\\n\\tsample > 32767 ifTrue: [ sample := 32767 ]. \\n\\tsample < -32767 ifTrue: [ sample := -32767 ].\\n\\n\\tStereo\\n\\t\\tifTrue: [\\n\\t\\t\\tleftSample := (sample * pan) // 1000.\\n\\t\\t\\tBuffer at: BufferIndex\\t\\tput: sample - leftSample.\\n\\t\\t\\tBuffer at: BufferIndex + 1\\tput: leftSample]\\n\\t\\tifFalse: [\\n\\t\\t\\tBuffer at: BufferIndex + 1 put: sample].\\n\\tBufferIndex := BufferIndex + 2.\\n! !\\n\\n!SoundPlayer class methodsFor: 'primitive test' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsineTable: size\\n\\t\\\"Compute a sine table of the given size. Used for testing only.\\\"\\n\\n\\t| radiansPerStep table |\\n\\ttable := Array new: size.\\n\\tradiansPerStep := (2.0 * Float pi) / table size asFloat.\\n\\t1 to: table size do: [:i |\\n\\t\\ttable at: i put:\\n\\t\\t\\t(32767.0 * (radiansPerStep * i) sin) asInteger].\\n\\n\\t^ table\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nshutDown\\n\\t\\\"Stop player process, for example before snapshotting.\\\"\\n\\n\\tself stopPlayerProcess.\\n\\tReverbState := nil.\\n! !\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'jm 7/11/97 12:17'!\\nstartUp\\n\\t\\\"Start up the player process.\\\"\\n\\n\\tSoundPlayer initialize.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo.\\n! !\\n\\n!SoundPlayer class methodsFor: 'snapshotting' stamp: 'ar 2/4/2001 17:59'!\\nstartUpWithSound: aSound\\n\\t\\\"Start up the player process.\\\"\\n\\n\\tSoundPlayer initialize.\\n\\tSoundPlayer\\n\\t\\tstartPlayerProcessBufferSize: (BufferMSecs * SamplingRate) // 1000\\n\\t\\trate: SamplingRate\\n\\t\\tstereo: Stereo\\n\\t\\tsound: aSound.\\n! !\\n\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nisAllSilence: buffer size: count\\n\\t\\\"return true if the buffer is all silence after reverb has ended\\\"\\n\\t| value |\\n\\tvalue := buffer at: 1.\\n\\t2 to: count do:[:i| (buffer at: i) = value ifFalse:[^false]].\\n\\t^true! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundAvailableBytes\\n\\t\\\"Return the number of bytes of available space in the sound output buffer.\\\"\\n\\t\\\"Note: Squeak always uses buffers containing 4-bytes per sample (2 channels at 2 bytes per channel) regardless of the state of the Stereo flag.\\\"\\n\\n\\t<primitive: 'primitiveSoundAvailableSpace' module: 'SoundPlugin'>\\n\\t^ self primitiveFailed\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'JMM 11/6/2000 10:17'!\\nprimSoundGetVolume\\n\\t\\\"Return sound as array of doubles left then right channel, range is 0.0 to 1.0 but may be overdriven\\\"\\n\\t<primitive: 'primitiveSoundGetVolume' module: 'SoundPlugin'>\\n\\t^Array with: 1.0 with: 1.0! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundInsertSamples: count from: aSoundBuffer samplesOfLeadTime: anInteger\\n\\t\\\"Mix the given number of sample frames from the given sound buffer into the queue of samples that has already been submitted to the sound driver. This primitive is used to start a sound playing with minimum latency, even if large sound output buffers are being used to ensure smooth sound output. Returns the number of samples consumed, or zero if the primitive is not implemented or fails.\\\"\\n\\n\\t<primitive: 'primitiveSoundInsertSamples' module: 'SoundPlugin'>\\n\\t^ 0\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'!\\nprimSoundPlaySamples: count from: aSampleBuffer startingAt: index\\n\\t\\\"Copy count bytes into the current sound output buffer from the given sample buffer starting at the given index.\\\"\\n\\n\\t<primitive: 'primitiveSoundPlaySamples' module: 'SoundPlugin'>\\n\\t^ self primitiveFailed\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'JMM 11/6/2000 10:14'!\\nprimSoundSetVolumeLeft: aLeftVolume volumeRight: aRightVolume\\n\\t\\\"Set sound pass in float 0.0-1.0 for left and right channel, with possible 2.0 or higher to overdrive sound channel \\\"\\n\\t<primitive: 'primitiveSoundSetLeftVolume' module: 'SoundPlugin'>\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nprimSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag\\n\\t\\\"Start double-buffered sound output with the given buffer size and sampling rate. This version has been superceded by primitive 171 (primSoundStartBufferSize:rate:stereo:semaIndex:).\\\"\\n\\t\\\"ar 12/5/1998 Turn off the sound if not supported\\\"\\n\\t<primitive: 'primitiveSoundStart' module: 'SoundPlugin'>\\n\\tSoundSupported := false.! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nprimSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag semaIndex: anInteger\\n\\t\\\"Start double-buffered sound output with the given buffer size and sampling rate. If the given semaphore index is > 0, it is taken to be the index of a Semaphore in the external objects array to be signalled when the sound driver is ready to accept another buffer of samples.\\\"\\n\\t\\\"Details: If this primitive fails, this method tries to use the older version instead.\\\"\\n\\n\\t<primitive: 'primitiveSoundStartWithSemaphore' module: 'SoundPlugin'>\\n\\tUseReadySemaphore := false.\\n\\tself primSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag.\\n! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'tpr 2/2/2001 19:46'!\\nprimSoundStop\\n\\t\\\"Stop double-buffered sound output. Must not raise an error because it is used inside error handling and at system shutdown\\\"\\n\\n\\t<primitive: 'primitiveSoundStop' module: 'SoundPlugin'>! !\\n\\n!SoundPlayer class methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartPlayingImmediately: aSound\\n\\t\\\"Private!! Start playing the given sound as soon as possible by mixing it into the sound output buffers of the underlying sound driver.\\\"\\n\\n\\t| totalSamples buf n leftover src rest |\\n\\t\\\"first, fill a double-size buffer with samples\\\"\\n\\t\\\"Note: The code below assumes that totalSamples contains two\\n\\t buffers worth of samples, and the insertSamples primitive is\\n\\t expected to consume at least one buffer's worth of these\\n\\t samples. The remaining samples are guaranteed to fit into\\n\\t a single buffer.\\\"\\n\\ttotalSamples := Buffer stereoSampleCount * 2. \\\"two buffer's worth\\\"\\n\\tbuf := SoundBuffer newStereoSampleCount: totalSamples.\\n\\taSound playSampleCount: totalSamples into: buf startingAt: 1.\\n\\tReverbState == nil ifFalse: [\\n\\t\\tReverbState applyReverbTo: buf startingAt: 1 count: totalSamples].\\n\\n\\tPlayerSemaphore critical: [\\n\\t\\t\\\"insert as many samples as possible into the sound driver's buffers\\\"\\n\\t\\tn := self primSoundInsertSamples: totalSamples\\n\\t\\t\\tfrom: buf\\n\\t\\t\\tsamplesOfLeadTime: 1024.\\n\\t\\tn > 0 ifTrue:[\\n\\t\\t\\tleftover := totalSamples - n.\\n\\n\\t\\t\\t\\\"copy the remainder of buf into Buffer\\\"\\n\\t\\t\\t\\\"Note: the following loop iterates over 16-bit words, not two-word stereo slices\\\"\\n\\t\\t\\t\\\"assert: 0 < leftover <= Buffer stereoSampleCount\\\"\\n\\t\\t\\tsrc := 2 * n.\\n\\t\\t\\t1 to: 2 * leftover do:\\n\\t\\t\\t\\t[:dst | Buffer at: dst put: (buf at: (src := src + 1))].\\n\\n\\t\\t\\t\\\"generate enough additional samples to finish filling Buffer\\\"\\n\\t\\t\\trest := Buffer stereoSampleCount - leftover.\\n\\t\\t\\taSound playSampleCount: rest into: Buffer startingAt: leftover + 1.\\n\\t\\t\\tReverbState == nil ifFalse: [\\n\\t\\t\\t\\tReverbState applyReverbTo: Buffer startingAt: leftover + 1 count: rest].\\n\\n\\t\\t\\t\\\"record the fact that this sound has already been played into Buffer so that we don't process it again this time around\\\"\\n\\t\\t\\tSoundJustStarted := aSound.\\n\\t\\t] ifFalse:[\\n\\t\\t\\t\\\"quick start failed; reset the sound so we start over\\\"\\n\\t\\t\\taSound reset.\\n\\t\\t].\\n\\t\\tActiveSounds add: aSound].\\n! !\\nStringReadoutTile subclass: #SoundReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SoundReadoutTile commentStamp: 'sw 11/24/2003 15:25' prior: 0!\\nA tile comprising a readout for a sound-valued instance variable in a Viewer. It sports up/down arrows, and a click on the sound name results in a pop-up menu, offering the user the opportunity to choose a new one.!\\n\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 1/28/2005 00:57'!\\narrowAction: delta\\n\\t\\\"Do what is appropriate when an arrow on the tile is pressed; delta will be +1 or -1\\\"\\n\\n\\t| soundChoices index |\\n\\tsoundChoices _ self soundChoices.\\n\\tindex _ soundChoices indexOf: literal.\\n\\tself literal: (soundChoices atWrap: (index + delta)).\\n\\tself playSoundNamed: literal! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 11/24/2003 14:54'!\\nhandlerForMouseDown: anEvent\\n\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event\\\"\\n\\n\\n\\n\\t^ ((self findA: UpdatingStringMorph) bounds containsPoint: anEvent cursorPoint)\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self]\\n\\n\\t\\tifFalse:\\n\\n\\t\\t\\t[super handlerForMouseDown: anEvent]! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'sw 1/28/2005 00:56'!\\nmouseDown: evt\\n\\t\\\"Handle a mouse down event\\\"\\n\\n\\t| aPoint index isUp soundChoices adjustment |\\n\\tupArrow ifNotNil: [((isUp _ upArrow containsPoint: (aPoint _ evt cursorPoint)) or: [downArrow containsPoint: aPoint])\\n\\t\\tifTrue:\\n\\t\\t\\t[soundChoices _ self soundChoices.\\n\\t\\t\\tindex _ soundChoices indexOf: literal ifAbsent: [1].\\n\\t\\t\\tindex > 0 ifTrue:\\n\\t\\t\\t\\t[adjustment _ isUp ifTrue: [1] ifFalse: [-1].\\n\\t\\t\\t\\tself literal: (soundChoices atWrap: (index + adjustment))].\\n\\t\\t\\tself playSoundNamed: literal.\\n\\t\\t\\t^ self]].\\n\\tself soundNameFromUser ifNotNilDo:\\n\\t\\t[:aSoundName |\\n\\t\\t\\tself literal: aSoundName.\\n\\t\\t\\tself playSoundNamed: literal]! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'yo 2/11/2005 16:12'!\\nsetLiteral: aLiteral\\n\\n\\tsuper setLiteral: aLiteral.\\n\\n\\t(self findA: UpdatingStringMorph) useSymbolFormat; lock! !\\n\\n!SoundReadoutTile methodsFor: 'arrows' stamp: 'yo 2/11/2005 16:08'!\\nsoundNameFromUser\\n\\t\\\"Obtain a sound from the user. Exclude the items designated as being discouraged, except that if the current selection is one of those, show it anyway\\\"\\n\\n\\t| choices |\\n\\tchoices _ self soundChoices.\\n\\t^ (SelectionMenu labels: (choices collect: [:t | t translated]) selections: self soundChoices) startUpWithCaption: 'Sounds' translated! !\\n\\n\\n!SoundReadoutTile methodsFor: 'literal' stamp: 'sw 1/28/2005 00:57'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"Set the literal and width of the tile as indicated\\\"\\n\\n\\t| soundChoices index |\\n\\tsoundChoices _ self soundChoices.\\n\\tindex _ soundChoices indexOf: anObject.\\n\\tself setLiteral: (soundChoices atWrap: index)! !\\n\\n\\n!SoundReadoutTile methodsFor: 'private' stamp: 'yo 2/11/2005 16:13'!\\nupdateLiteralLabel\\n\\n\\t\\\"Update the wording emblazoned on the tile, if needed\\\"\\n\\n\\n\\n\\tsuper updateLiteralLabel.\\n\\n\\t(self findA: UpdatingStringMorph) useSymbolFormat; lock! !\\nObject subclass: #SoundRecorder\\n\\tinstanceVariableNames: 'stereo samplingRate recordLevel recordedBuffers recordedSound recordProcess bufferAvailableSema paused meteringBuffer meterLevel soundPlaying currentBuffer nextIndex codec desiredSampleRate'\\n\\tclassVariableNames: 'CanRecordWhilePlaying RecorderActive'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncodec: aSoundCodec\\n\\n\\tcodec := aSoundCodec! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ndesiredSampleRate: newRate\\n\\n\\t\\\"use of this method indicates a strong desire for the specified rate, even if\\n\\tthe OS/hardware are not cooperative\\\"\\n\\n\\tdesiredSampleRate := samplingRate := newRate \\\"Best are 44100 22050 11025\\\"\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jj 10/20/97 15:30'!\\nisActive\\n\\t\\\"Return true if I have a recordProcess running.\\\"\\n\\n\\t^ recordProcess ~~ nil\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 9/2/97 16:16'!\\nisPaused\\n\\t\\\"Return true if recording is paused.\\\"\\n\\n\\t^ paused\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 9/18/97 19:19'!\\nmeterLevel\\n\\t\\\"Return the meter level, an integer in the range [0..100] where zero is silence and 100 represents the maximum signal level possible without clipping.\\\"\\n\\n\\t^ (100 * meterLevel) // 32768\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 7/4/1998 15:03'!\\nrecordLevel\\n\\n\\t^ recordLevel\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrecordLevel: level\\n\\t\\\"Set the desired recording level to the given value in the range 0.0 to 1.0, where 0.0 is the lowest recording level and 1.0 is the maximum. Do nothing if the sound input hardware does not support changing the recording level.\\\"\\n\\t\\\"Details: On the Macintosh, the lowest possible record level attenuates the input signal, but does not silence it entirely.\\\" \\n\\n\\trecordLevel := (level asFloat min: 1.0) max: 0.0.\\n\\trecordProcess ifNotNil: [\\n\\t\\tself primSetRecordLevel: (1000.0 * recordLevel) asInteger].\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'jm 12/15/97 14:28'!\\nsamplingRate\\n\\n\\t^ samplingRate\\n! !\\n\\n!SoundRecorder methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplingRate: newRate\\n\\n\\tsamplingRate := newRate \\\"Best are 44100 22050 11025\\\"\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundRecorder new\\\"\\n\\n\\tstereo := false.\\n\\tsamplingRate := 11025.\\n\\trecordLevel := 0.5.\\n\\tself initializeRecordingState.\\n! !\\n\\n!SoundRecorder methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitializeRecordingState\\n\\n\\trecordProcess := nil.\\n\\tbufferAvailableSema := nil.\\n\\tpaused := true.\\n\\tmeteringBuffer := nil.\\n\\tmeterLevel := 0.\\n\\tsoundPlaying := nil.\\n\\tcurrentBuffer := nil.\\n\\tnextIndex := 1.\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimGetActualRecordingSampleRate\\n\\t\\\"Return the actual sample rate being used for recording. This primitive fails unless sound recording is currently in progress.\\\"\\n\\n\\t<primitive: 'primitiveSoundGetRecordingSampleRate' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimRecordSamplesInto: aWordArray startingAt: index\\n\\t\\\"Record a sequence of 16-bit sound samples into the given array starting at the given sample index. Return the number of samples recorded, which may be zero if no samples are currently available.\\\"\\n\\n\\t<primitive: 'primitiveSoundRecordSamples' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSetRecordLevel: anInteger\\n\\t\\\"Set the desired recording level to the given value in the range 0-1000, where 0 is the lowest recording level and 1000 is the maximum. Do nothing if the sound input hardware does not support changing the recording level.\\\"\\n\\n\\t<primitive: 'primitiveSoundSetRecordLevel' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimStartRecordingDesiredSampleRate: samplesPerSec stereo: stereoFlag semaIndex: anInteger\\n\\t\\\"Start sound recording with the given stereo setting. Use a sampling rate as close to the desired rate as the underlying platform will support. If the given semaphore index is > 0, it is taken to be the index of a Semaphore in the external objects array to be signalled every time a recording buffer is filled.\\\"\\n\\n\\t<primitive: 'primitiveSoundStartRecording' module: 'SoundPlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!SoundRecorder methodsFor: 'primitives' stamp: 'tpr 2/15/2001 17:13'!\\nprimStopRecording\\n\\t\\\"Stop sound recording. Does nothing if recording is not currently in progress. Do not fail if plugin is not available\\\"\\n\\n\\t<primitive: 'primitiveSoundStopRecording' module: 'SoundPlugin'>! !\\n\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nclearRecordedSound\\n\\t\\\"Clear the sound recorded thus far. Go into pause mode if currently recording.\\\"\\n\\n\\tpaused := true.\\n\\trecordedSound := SequentialSound new.\\n\\tself allocateBuffer.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'sw 6/10/2003 12:34'!\\nhasRecordedSound\\n\\n\\t\\\"Answer whether the receiver currently has any recorded sound\\\"\\n\\n\\n\\n\\t^ self recordedSound notNil! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npause\\n\\t\\\"Go into pause mode. The record level continues to be updated, but no sound is recorded.\\\"\\n\\n\\tpaused := true.\\n\\t((currentBuffer ~~ nil) and: [nextIndex > 1])\\n\\t\\tifTrue: [self emitPartialBuffer.\\n\\t\\t\\t\\tself allocateBuffer].\\n\\n\\tsoundPlaying ifNotNil: [\\n\\t\\tsoundPlaying pause.\\n\\t\\tsoundPlaying := nil].\\n\\t\\\"Note: there can be problems if canRecordWhilePlaying is true. Recorders which only pause will inhibit other recorders from recording. I chose to make #stopPlaying unconditional in a subclass. The same might be appropriate here at the expense of making recorders resumable\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifFalse: [self stopRecording].\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplayback\\n\\t\\\"Playback the sound that has been recorded.\\\"\\n\\n\\tself pause.\\n\\tsoundPlaying := self recordedSound.\\n\\tsoundPlaying play.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nresumeRecording\\n\\t\\\"Continue recording from the point at which it was last paused.\\\"\\n\\n\\tself flag: #bob.\\n\\t\\\"Note: If canRecordWhilePlaying is true, then recordings may never get started (at least by this method). One possibility, used in a subclass, is to make the #startPlaying unconditional. Another would be to use #startPlaying instead of #resumePlaying in appropriate cases\\\"\\n\\n\\tPreferences canRecordWhilePlaying ifFalse: [self startRecording].\\n\\tpaused := false.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartRecording\\n\\t\\\"Turn of the sound input driver and start the recording process. Initially, recording is paused.\\\"\\n\\n\\t| semaIndex |\\n\\trecordLevel ifNil: [recordLevel := 0.5]. \\\"lazy initialization\\\"\\n\\tPreferences canRecordWhilePlaying ifFalse: [SoundPlayer shutDown].\\n\\trecordProcess ifNotNil: [self stopRecording].\\n\\tpaused := true.\\n\\tmeteringBuffer := SoundBuffer newMonoSampleCount: 1024.\\n\\tmeterLevel := 0.\\n\\tself allocateBuffer.\\n\\tbufferAvailableSema := Semaphore new.\\n\\tsemaIndex := Smalltalk registerExternalObject: bufferAvailableSema.\\n\\tself primStartRecordingDesiredSampleRate: samplingRate asInteger\\n\\t\\tstereo: stereo\\n\\t\\tsemaIndex: semaIndex.\\n\\tRecorderActive := true.\\n\\tsamplingRate := self primGetActualRecordingSampleRate.\\n\\tself primSetRecordLevel: (1000.0 * recordLevel) asInteger.\\n\\trecordProcess := [self recordLoop] newProcess.\\n\\trecordProcess priority: Processor userInterruptPriority.\\n\\trecordProcess resume.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstopRecording\\n\\t\\\"Stop the recording process and turn of the sound input driver.\\\"\\n\\n\\trecordProcess ifNotNil: [recordProcess terminate].\\n\\trecordProcess := nil.\\n\\tself primStopRecording.\\n\\tRecorderActive := false.\\n\\tSmalltalk unregisterExternalObject: bufferAvailableSema.\\n\\t((currentBuffer ~~ nil) and: [nextIndex > 1])\\n\\t\\tifTrue: [self emitPartialBuffer].\\n\\tself initializeRecordingState.\\n! !\\n\\n!SoundRecorder methodsFor: 'recording controls' stamp: 'sw 3/3/2004 19:49'!\\nverifyExistenceOfRecordedSound\\n\\n\\t\\\"If the receiver has a recorded sound, answer true; if not, put up an informer and answer false\\\"\\n\\n\\n\\n\\t^ self recordedSound\\n\\n\\t\\tifNotNil:\\n\\n\\t\\t\\t[true]\\n\\n\\t\\tifNil:\\n\\n\\t\\t\\t[self inform: 'please record a sound first' translated.\\n\\n\\t\\t\\tfalse]! !\\n\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncondensedSamples\\n\\t\\\"Return a single SoundBuffer that is the contatenation of all my recorded buffers.\\\"\\n\\n\\t| sz newBuf i |\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\trecordedBuffers isEmpty ifTrue: [^ SoundBuffer new: 0].\\n\\trecordedBuffers size = 1 ifTrue: [^ recordedBuffers first copy].\\n\\tsz := recordedBuffers inject: 0 into: [:tot :buff | tot + buff size].\\n\\tnewBuf := SoundBuffer newMonoSampleCount: sz.\\n\\ti := 1.\\n\\trecordedBuffers do: [:b |\\n\\t\\t1 to: b size do: [:j |\\n\\t\\t\\tnewBuf at: i put: (b at: j).\\n\\t\\t\\ti := i + 1]].\\n\\trecordedBuffers := nil.\\n\\t^ newBuf\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncondensedStereoSound\\n\\t\\\"Decompose my buffers into left and right channels and return a mixed sound consisting of the those two channels. This may be take a while, since the data must be copied into new buffers.\\\"\\n\\n\\t| sz leftBuf rightBuf leftI rightI left |\\n\\tsz := recordedBuffers inject: 0 into: [:tot :buff | tot + buff size].\\n\\tleftBuf := SoundBuffer newMonoSampleCount: (sz + 1) // 2.\\n\\trightBuf := SoundBuffer newMonoSampleCount: (sz + 1) // 2.\\n\\tleftI := rightI := 1.\\n\\tleft := true.\\n\\trecordedBuffers do: [:b |\\n\\t\\t1 to: b size do: [:j |\\n\\t\\t\\tleft\\n\\t\\t\\t\\tifTrue: [leftBuf at: leftI put: (b at: j). leftI := leftI + 1. left := false]\\n\\f\\t\\t\\t\\tifFalse: [rightBuf at: rightI put: (b at: j). rightI := rightI + 1. left := true]]].\\n\\t^ MixedSound new\\n\\t\\tadd: (SampledSound new setSamples: leftBuf samplingRate: samplingRate) pan: 0.0;\\n\\t\\tadd: (SampledSound new setSamples: rightBuf samplingRate: samplingRate) pan: 1.0\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'di 2/17/1999 11:07'!\\nrecordedSound\\n\\t\\\"Return the sound that was recorded.\\\"\\n\\n\\t^ recordedSound\\n! !\\n\\n!SoundRecorder methodsFor: 'results' stamp: 'di 2/17/1999 21:24'!\\nsoundSegments\\n\\n\\t^ self segmentsAbove: 1000 normalizedVolume: 80.0\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopyFrom: startPlace to: endPlace normalize: nFactor dcOffset: dcOffset\\n\\t\\\"Return a new SoundBuffer containing the samples in the given range.\\\"\\n\\n\\t| startBufIndex startSampleIndex endBufIndex endSampleIndex\\n\\t count resultBuf j buf firstInBuf n |\\n\\tstartBufIndex := startPlace at: 1.\\n\\tstartSampleIndex := startPlace at: 2.\\n\\tendBufIndex := endPlace at: 1.\\n\\tendSampleIndex := endPlace at: 2.\\n\\n\\tstartBufIndex = endBufIndex\\n\\t\\tifTrue: [count := endSampleIndex + 1 - startSampleIndex]\\n\\t\\tifFalse: [\\n\\t\\t\\tcount := ((recordedBuffers at: startBufIndex) size + 1 - startSampleIndex). \\\"first buffer\\\"\\n\\t\\t\\tcount := count + endSampleIndex. \\\"last buffer\\\"\\n\\t\\t\\tstartBufIndex + 1 to: endBufIndex - 1 do:\\n\\t\\t\\t\\t[:i | count := count + (recordedBuffers at: i) size]]. \\\"middle buffers\\\"\\n\\tresultBuf := SoundBuffer newMonoSampleCount: count.\\n\\n\\tj := 1. \\\"next destination index in resultBuf\\\"\\n\\tstartBufIndex to: endBufIndex do: [:i |\\n\\t\\tbuf := recordedBuffers at: i.\\n\\t\\tfirstInBuf := 1.\\n\\t \\tn := buf size.\\n\\t\\ti = startBufIndex ifTrue: [\\n\\t\\t\\tn := (recordedBuffers at: startBufIndex) size + 1 - startSampleIndex.\\n\\t\\t\\tfirstInBuf := startSampleIndex].\\n\\t\\ti = endBufIndex ifTrue: [\\n\\t\\t\\ti = startBufIndex\\n\\t\\t\\t\\tifTrue: [n := endSampleIndex + 1 - startSampleIndex]\\n\\t\\t\\t\\tifFalse: [n := endSampleIndex]].\\n\\t\\tself copyTo: resultBuf from: j to: (j + n - 1)\\n\\t\\t\\tfrom: buf startingAt: firstInBuf\\n\\t\\t\\tnormalize: nFactor dcOffset: dcOffset.\\n\\t\\tj := j + n].\\n\\t^ resultBuf\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncopyTo: resultBuf from: startIndex to: endIndex from: buf startingAt: firstInBuf normalize: nFactor dcOffset: dcOffset\\n\\t\\\"Copy samples from buf to resultBuf removing the DC offset and normalizing their volume in the process.\\\"\\n\\n\\t| indexOffset |\\n\\tindexOffset := firstInBuf - startIndex.\\n\\tstartIndex to: endIndex do: [:i |\\n\\t\\tresultBuf at: i put: (((buf at: (i + indexOffset)) - dcOffset) * nFactor) // 1000].\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'di 2/16/1999 22:11'!\\nendPlace\\n\\n\\t^ Array with: recordedBuffers size with: recordedBuffers last size! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nfirstSampleOverThreshold: threshold dcOffset: dcOffset startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will return the first place at which a sample exceeds the given threshold.\\\"\\n\\n\\t| buf s iStart jStart nThreshold |\\n\\tnThreshold := threshold negated.\\n\\tiStart := startPlace first.\\n\\tjStart := startPlace second.\\n\\tiStart to: recordedBuffers size do:\\n\\t\\t[:i | buf := recordedBuffers at: i.\\n\\t\\tjStart to: buf size do:\\n\\t\\t\\t[:j | s := (buf at: j) - dcOffset.\\n\\t\\t\\t(s < nThreshold or: [s > threshold]) ifTrue:\\n\\t\\t\\t\\t[\\\"found a sample over threshold\\\"\\n\\t\\t\\t\\t^ Array with: i with: j]].\\n\\t\\tjStart := 1].\\n\\t^ self endPlace! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nnormalizeFactorFor: percentOfMaxVolume min: min max: max dcOffset: dcOffset\\n\\t\\\"Return a normalization factor for the range of sample values and DC offset. A normalization factor is a fixed-point number that will be divided by 1000 after multiplication with each sample value.\\\"\\n\\n\\t| peak factor |\\n\\tpeak := (max - dcOffset) max: (min - dcOffset) negated.\\n\\tpeak = 0 ifTrue: [^ 1000].\\n\\tfactor := (32767.0 * percentOfMaxVolume) / (100.0 * peak).\\n\\t^ (factor * 1000.0) asInteger\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplace: startPlace plus: nSamples\\n\\t\\\"Return the place that is nSamples (may be negative) beyond thisPlace.\\\"\\n\\n\\t| i j remaining buf |\\n\\ti := startPlace first.\\n\\tj := startPlace second.\\n\\tnSamples >= 0\\n\\tifTrue: [remaining := nSamples.\\n\\t\\t\\t[buf := recordedBuffers at: i.\\n\\t\\t\\t(j + remaining) <= buf size ifTrue: [^ Array with: i with: j + remaining].\\n\\t\\t\\ti < recordedBuffers size]\\n\\t\\t\\t\\twhileTrue: [remaining := remaining - (buf size - j + 1).\\n\\t\\t\\t\\t\\t\\t\\ti := i+1. j := 1].\\n\\t\\t\\t^ self endPlace]\\n\\tifFalse: [remaining := nSamples negated.\\n\\t\\t\\t[buf := recordedBuffers at: i.\\n\\t\\t\\t(j - remaining) >= 1 ifTrue: [^ Array with: i with: j - remaining].\\n\\t\\t\\ti > 1]\\n\\t\\t\\t\\twhileTrue: [remaining := remaining - j.\\n\\t\\t\\t\\t\\t\\t\\ti := i-1. j := (recordedBuffers at: i) size].\\n\\t\\t\\t^ #(1 1)]! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscanForEndThreshold: threshold dcOffset: dcOffset minLull: lull startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will find the last sound that exceeds threshold, such that if you look lull samples later you will not find another sound over threshold within the following block of lull samples.\\n\\tReturn the place that is lull samples beyond to that last sound.\\n\\tIf no end of sound is found, return endPlace.\\\"\\n\\n\\t| buf s iStart jStart nThreshold n |\\n\\tnThreshold := threshold negated.\\n\\tiStart := startPlace first.\\n\\tjStart := startPlace second.\\n\\tn := 0.\\n\\tiStart to: recordedBuffers size do:\\n\\t\\t[:i | buf := recordedBuffers at: i.\\n\\t\\tjStart to: buf size do:\\n\\t\\t\\t[:j | s := (buf at: j) - dcOffset.\\n\\t\\t\\t(s < nThreshold or: [s > threshold])\\n\\t\\t\\t\\tifTrue: [\\\"found a sample over threshold\\\"\\n\\t\\t\\t\\t\\t\\tn := 0]\\n\\t\\t\\t\\tifFalse: [\\\"still not over threshold\\\"\\n\\t\\t\\t\\t\\t\\tn := n + 1.\\n\\t\\t\\t\\t\\t\\tn >= lull ifTrue: [^ Array with: i with: j]]].\\n\\t\\tjStart := 1].\\n\\t^ self endPlace! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nscanForStartThreshold: threshold dcOffset: dcOffset minDur: duration startingAt: startPlace\\n\\t\\\"Beginning at startPlace, this routine will find the first sound that exceeds threshold, such that if you look duration samples later you will find another sound over threshold within the following block of duration samples.\\n\\tReturn the place that is duration samples prior to that first sound.\\n\\tIf no sound is found, return endPlace.\\\"\\n\\n\\t| soundPlace lookPlace nextSoundPlace thirdPlace |\\n\\tsoundPlace := self firstSampleOverThreshold: threshold dcOffset: dcOffset\\n\\t\\t\\t\\t\\tstartingAt: startPlace.\\n\\t[soundPlace = self endPlace ifTrue: [^ soundPlace].\\n\\t\\\"Found a sound -- look duration later\\\"\\n\\tlookPlace := self place: soundPlace plus: duration.\\n\\tnextSoundPlace := self firstSampleOverThreshold: threshold dcOffset: dcOffset\\n\\t\\t\\t\\t\\tstartingAt: lookPlace.\\n\\tthirdPlace := self place: lookPlace plus: duration.\\n\\tnextSoundPlace first < thirdPlace first\\n\\t\\tor: [nextSoundPlace first = thirdPlace first\\n\\t\\t\\tand: [nextSoundPlace second < thirdPlace second]]]\\n\\t\\twhileFalse: [soundPlace := nextSoundPlace].\\n\\n\\t\\\"Yes, there is sound in the next interval as well\\\"\\n\\t^ self place: soundPlace plus: 0-duration\\n! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsegmentsAbove: threshold normalizedVolume: percentOfMaxVolume\\n\\t\\\"Break the current recording up into a sequence of sound segments separated by silences.\\\"\\n\\n\\t| max min sum totalSamples bufSize s dcOffset firstPlace endPlace resultBuf nFactor lastPlace segments gapSize minDur minLull soundSize restSize |\\n\\tstereo ifTrue: [self error: 'stereo trimming is not yet supported'].\\n\\tpaused ifFalse: [self error: 'must stop recording before trimming'].\\n\\t(recordedSound == nil or: [recordedSound sounds isEmpty]) ifTrue:[^ self].\\n\\t\\\"Reconstruct buffers so old trimming code will work\\\"\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\tsoundSize := restSize := 0.\\n\\n\\tmax := min := sum := totalSamples := 0.\\n\\trecordedBuffers do: [:buf |\\n\\t\\tbufSize := buf size.\\n\\t\\ttotalSamples := totalSamples + buf size.\\n\\t\\t1 to: bufSize do: [:i |\\n\\t\\t\\ts := buf at: i.\\n\\t\\t\\ts > max ifTrue: [max := s].\\n\\t\\t\\ts < min ifTrue: [min := s].\\n\\t\\t\\tsum := sum + s]].\\n\\tdcOffset := sum // totalSamples.\\n\\n\\tminDur := (samplingRate/20.0) asInteger. \\\" 1/20 second \\\"\\n\\tminLull := (samplingRate/4.0) asInteger. \\\" 1/2 second \\\"\\n\\tsegments := SequentialSound new.\\n\\tendPlace := self endPlace.\\n\\tlastPlace := #(1 1).\\n\\t[firstPlace := self scanForStartThreshold: threshold\\n\\t\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\t\\tminDur: minDur\\n\\t\\t\\t\\t\\t\\tstartingAt: lastPlace.\\n\\tfirstPlace = endPlace]\\n\\t\\twhileFalse:\\n\\t\\t[firstPlace = lastPlace ifFalse:\\n\\t\\t\\t[\\\"Add a silence equal to the gap size\\\"\\n\\t\\t\\t\\\"Wasteful but simple way to get gap size...\\\"\\n\\t\\t\\tgapSize := (self copyFrom: lastPlace to: firstPlace\\n\\t\\t\\t\\t\\t\\tnormalize: 1000 dcOffset: dcOffset) size - 2.\\n\\t\\t\\t\\\"... -2 makes up for overlap of one sample on either end\\\"\\n\\t\\t\\tsegments add: (RestSound dur: gapSize asFloat / samplingRate).\\n\\t\\t\\trestSize := restSize + gapSize.\\n\\\"Transcript cr; print: firstPlace; space; print: lastPlace; space; print: gapSize; space; show: 'gap'.\\\"\\n\\t\\t\\t].\\n\\t\\tlastPlace := self scanForEndThreshold: threshold\\n\\t\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\t\\tminLull: minLull + minDur\\n\\t\\t\\t\\t\\t\\tstartingAt: firstPlace.\\n\\t\\t\\\"Allow room for lead time of next sound\\\"\\n\\t\\tlastPlace := self place: lastPlace plus: minDur negated.\\n\\t\\tnFactor := self normalizeFactorFor: percentOfMaxVolume\\n\\t\\t\\t\\t\\t\\tmin: min max: max dcOffset: dcOffset.\\n\\t\\tresultBuf := self copyFrom: firstPlace to: lastPlace\\n\\t\\t\\t\\t\\t\\tnormalize: nFactor dcOffset: dcOffset.\\n\\t\\tsoundSize := soundSize + resultBuf size.\\n\\\"Transcript cr; print: firstPlace; space; print: lastPlace; space; print: resultBuf size; space; show: 'sound'.\\\"\\n\\t\\tsegments add: (codec == nil\\n\\t\\t\\tifTrue: [SampledSound new setSamples: resultBuf samplingRate: samplingRate]\\n\\t\\t\\tifFalse: [codec compressSound: (SampledSound new setSamples: resultBuf samplingRate: samplingRate)])].\\n\\n\\t\\\"Final gap for consistency\\\"\\n\\tgapSize := (self copyFrom: lastPlace to: self endPlace\\n\\t\\t\\t\\tnormalize: 1000 dcOffset: dcOffset) size - 1.\\n\\tsegments add: (RestSound dur: gapSize asFloat / samplingRate).\\n\\trestSize := restSize + gapSize.\\n\\tself inform: ((soundSize+restSize/samplingRate) roundTo: 0.1) printString , ' secs reduced to ' , ((soundSize/samplingRate) roundTo: 0.1) printString.\\n\\trecordedBuffers := nil.\\n\\t^ segments! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsuppressSilence\\n\\n\\trecordedSound := self soundSegments! !\\n\\n!SoundRecorder methodsFor: 'trimming' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ntrim: threshold normalizedVolume: percentOfMaxVolume\\n\\t\\\"Remove the leading and trailing parts of this recording that are below the given threshold. Remove any DC offset and scale the recording so that its peaks are the given percent of the maximum volume.\\\"\\n\\n\\t| max min sum totalSamples bufSize s dcOffset startPlace endPlace resultBuf nFactor |\\n\\tstereo ifTrue: [self error: 'stereo trimming is not yet supported'].\\n\\tpaused ifFalse: [self error: 'must stop recording before trimming'].\\n\\trecordedBuffers := recordedSound sounds collect: [:snd | snd samples].\\n\\trecordedBuffers isEmpty ifTrue: [^ self].\\n\\n\\tmax := min := sum := totalSamples := 0.\\n\\trecordedBuffers do: [:buf |\\n\\t\\tbufSize := buf size.\\n\\t\\ttotalSamples := totalSamples + buf size.\\n\\t\\t1 to: bufSize do: [:i |\\n\\t\\t\\ts := buf at: i.\\n\\t\\t\\ts > max ifTrue: [max := s].\\n\\t\\t\\ts < min ifTrue: [min := s].\\n\\t\\t\\tsum := sum + s]].\\n\\tdcOffset := sum // totalSamples.\\n\\n\\t\\\"a place is an array of <buffer index><index of sample in buffer>\\\"\\n\\tstartPlace := self scanForStartThreshold: threshold\\n\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\tminDur: (samplingRate/60.0) asInteger \\\"at least 1/60th of a second\\\"\\n\\t\\t\\t\\t\\tstartingAt: #(1 1).\\n\\tstartPlace = self endPlace ifTrue:\\n\\t\\t[\\\"no samples above threshold\\\"\\n\\t\\trecordedBuffers := nil. ^ self].\\n\\n\\tendPlace := self scanForEndThreshold: threshold\\n\\t\\t\\t\\t\\tdcOffset: dcOffset\\n\\t\\t\\t\\t\\tminLull: (samplingRate/5) asInteger\\n\\t\\t\\t\\t\\tstartingAt: startPlace.\\n\\tnFactor := self normalizeFactorFor: percentOfMaxVolume min: min max: max dcOffset: dcOffset.\\n\\tresultBuf := self copyFrom: startPlace to: endPlace normalize: nFactor dcOffset: dcOffset.\\n\\trecordedSound := SampledSound new setSamples: resultBuf samplingRate: samplingRate.\\n\\trecordedBuffers := nil\\n! !\\n\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nallocateBuffer\\n\\t\\\"Allocate a new buffer and reset nextIndex.\\\"\\n\\n\\t| bufferTime |\\n\\tbufferTime := stereo \\\"Buffer time = 1/2 second\\\"\\n\\t\\tifTrue: [self samplingRate asInteger]\\n\\t\\tifFalse: [self samplingRate asInteger // 2].\\n\\tcurrentBuffer := SoundBuffer newMonoSampleCount:\\n\\t\\t\\\"Multiple of samplesPerFrame that is approx. bufferTime long\\\"\\n\\t\\t(bufferTime truncateTo: self samplesPerFrame).\\n\\tnextIndex := 1.\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nemitBuffer: buffer\\n\\n\\t| sound ratio resultBuf |\\n\\n\\t\\\"since some sound recording devices cannot (or will not) record below a certain sample rate,\\n\\ttrim the samples down if the user really wanted fewer samples\\\"\\n\\n\\t(desiredSampleRate isNil or: [(ratio := samplingRate // desiredSampleRate) <= 1]) ifTrue: [\\n\\t\\tsound := SampledSound new setSamples: buffer samplingRate: samplingRate.\\n\\t] ifFalse: [\\n\\t\\tresultBuf := SoundBuffer \\n\\t\\t\\taverageEvery: ratio \\n\\t\\t\\tfrom: buffer \\n\\t\\t\\tupTo: buffer monoSampleCount.\\n\\t\\tsound := SampledSound new setSamples: resultBuf samplingRate: samplingRate / ratio.\\n\\t].\\n\\n\\trecordedSound add: (codec ifNil: [sound] ifNotNil: [codec compressSound: sound])! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nemitPartialBuffer\\n\\t| s |\\n\\ts := self samplesPerFrame.\\n\\tself emitBuffer: (currentBuffer copyFrom: 1 to: ((nextIndex-1) +( s-1) truncateTo: s))! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmeterFrom: start count: count in: buffer\\n\\t\\\"Update the meter level with the maximum signal level in the given range of the given buffer.\\\"\\n\\n\\t| last max sample |\\n\\tcount = 0 ifTrue: [^ self]. \\\"no new samples\\\"\\n\\tlast := start + count - 1.\\n\\tmax := 0.\\n\\tstart to: last do: [:i |\\n\\t\\tsample := buffer at: i.\\n\\t\\tsample < 0 ifTrue: [sample := sample negated].\\n\\t\\tsample > max ifTrue: [max := sample]].\\n\\tmeterLevel := max.\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'dgd 4/4/2006 16:15'!\\nrecordLoop\\n\\t\\\"Record process loop that records samples.\\\"\\n\\n\\t| n sampleCount |\\n\\n\\tn := 0.\\n\\t[true] whileTrue: [\\n\\t\\tn = 0 ifTrue: [bufferAvailableSema wait].\\n\\t\\tpaused\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tn := self primRecordSamplesInto: meteringBuffer startingAt: 1.\\n\\t\\t\\t\\tself meterFrom: 1 count: n in: meteringBuffer]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tn := self primRecordSamplesInto: currentBuffer startingAt: nextIndex.\\n\\t\\t\\t\\tself meterFrom: nextIndex count: n in: currentBuffer.\\n\\t\\t\\t\\tnextIndex := nextIndex + n.\\n\\t\\t\\t\\tstereo\\n\\t\\t\\t\\t\\tifTrue: [sampleCount := currentBuffer stereoSampleCount]\\n\\t\\t\\t\\t\\tifFalse: [sampleCount := currentBuffer monoSampleCount].\\n\\t\\t\\t\\tnextIndex > sampleCount\\n\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\tself emitBuffer: currentBuffer.\\n\\t\\t\\t\\t\\t\\tself allocateBuffer]].\\n\\n\\t\\t\\\"workaround for OSS emulation on top on ALSA (on Linux environments)\\\"\\n\\t\\t(Delay forMilliseconds: 20) wait.\\n\\t].\\n! !\\n\\n!SoundRecorder methodsFor: 'private' stamp: 'di 2/17/1999 10:39'!\\nsamplesPerFrame\\n\\t\\\"Can be overridden to quantize buffer size for, eg, fixed-frame codecs\\\"\\n\\n\\tcodec == nil\\n\\t\\tifTrue: [^ 1]\\n\\t\\tifFalse: [^ codec samplesPerFrame]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSoundRecorder class\\n\\tinstanceVariableNames: ''!\\n\\n!SoundRecorder class methodsFor: 'accessing' stamp: 'ar 2/1/2001 15:20'!\\nanyActive\\n\\t\\\"Return true if any sound recorder is actively recording\\\"\\n\\t^RecorderActive == true! !\\n\\n!SoundRecorder class methodsFor: 'accessing' stamp: 'RAA 8/7/2000 19:23'!\\ncanRecordWhilePlaying\\n\\t\\\"Return true if this platform supports simultaneous sound recording and playback.\\\"\\n\\n\\t^Preferences canRecordWhilePlaying.\\t\\t\\\"now in preferences\\\"\\n! !\\n\\n\\n!SoundRecorder class methodsFor: 'class initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitialize\\n\\t\\\"SoundRecorder initialize\\\"\\n\\t\\\"Details: Some computers cannot record and playback sound at the same time. If CanRecordWhilePlaying is false, then the SoundRecorder alternates between recording and playing. If it is true, sounds can be playing during recording.\\\"\\n\\n\\tCanRecordWhilePlaying := #ignoredNowInPreferences.\\n! !\\nRectangleMorph subclass: #SoundSequencerMorph\\n\\tinstanceVariableNames: 'controlPanel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'tk 2/19/2001 18:14'!\\nmakeControlPanel\\n\\t| bb cc |\\n\\tcc _ Color black.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel _ AlignmentMorph newRow.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel color: bb color; borderWidth: 0; layoutInset: 0.\\n\\tcontrolPanel hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'reset';\\tactionSelector: #reset).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'stop';\\t\\tactionSelector: #stop).\\n\\tbb _ SimpleButtonMorph new target: self; borderColor: cc.\\n\\tcontrolPanel addMorphBack: (bb label: 'play';\\tactionSelector: #play).\\n! !\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nplay\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m play]]! !\\n\\n!SoundSequencerMorph methodsFor: 'as yet unclassified' stamp: 'jm 11/14/97 11:08'!\\nreset\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m reset]]! !\\n\\n\\n!SoundSequencerMorph methodsFor: 'initialization' stamp: 'jm 11/14/97 11:21'!\\ninitialize\\n\\tsuper initialize.\\n\\tself extent: 550@350.\\n\\tself makeControlPanel.\\n\\tself addMorph: controlPanel.\\n\\tself addMorph: ((SoundLoopMorph newBounds: (10@40 extent: 128@128)) extent: 128@128).\\n\\tself addMorph: ((SoundLoopMorph newBounds: (10@200 extent: 512@128)) extent: 512@128).! !\\n\\n\\n!SoundSequencerMorph methodsFor: 'stepping and presenter' stamp: 'jm 11/14/97 11:21'!\\nstop\\n\\tself submorphsDo: [:m | m == controlPanel ifFalse: [m stop]].\\n\\tSoundPlayer shutDown! !\\nAppRegistry subclass: #SoundService\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Applications'!\\n!SoundService commentStamp: 'gk 2/24/2004 23:14' prior: 0!\\nThis is the AppRegistry class for the sound system.\\n\\nA sound system offers a small protocol for playing sounds and making beeps and works like a facade towards the rest of Squeak. A sound system is registered in this registry and can be accessed by \\\"SoundService default\\\". This way we decouple the sound system from the rest of Squeak and make it pluggable. It also is a perfect spot to check for the Preference class>>soundsEnabled.!\\n\\nTileMorph subclass: #SoundTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SoundTile commentStamp: 'sw 1/28/2005 01:42' prior: 0!\\nA scripting tile representing a 'sound' constant. Sounds are represented by their names, which are strings; the actual sounds live in SampleSound's SoundLibrary.!\\n\\n\\n!SoundTile methodsFor: 'access' stamp: 'gk 2/23/2004 21:08'!\\nsound\\n\\n\\t^ SoundService default soundNamed: literal\\n! !\\n\\n\\n!SoundTile methodsFor: 'accessing' stamp: 'sw 9/27/2001 17:28'!\\nresultType\\n\\t\\\"Answer the result type of the receiver\\\"\\n\\n\\t^ #Sound! !\\n\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'sw 1/28/2005 01:49'!\\noptions\\n\\t\\\"Answer the options of the tile for an arrow\\\"\\n\\n\\t| soundChoices |\\n\\tsoundChoices _ self soundChoices.\\n\\t^ {soundChoices. soundChoices}! !\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'tak 12/5/2004 02:09'!\\nvalue: anObject \\n\\tsuper value: anObject.\\n\\tself playSoundNamed: anObject! !\\n\\n!SoundTile methodsFor: 'event handling' stamp: 'sw 11/3/97 02:11'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t^ false! !\\n\\n\\n!SoundTile methodsFor: 'initialization' stamp: 'yo 7/22/2005 15:51'!\\ninitialize\\n\\t\\\"Initialize the state of the receiver. Pick the croak sound\\n\\tif available, otherwise any sound.\\\"\\n\\t\\n\\t| soundChoices startingSoundName |\\n\\tsuper initialize.\\n\\tsoundChoices _ self soundChoices.\\n\\tstartingSoundName _ (soundChoices includes: 'croak')\\n\\t\\t\\t\\t\\t\\t\\tifTrue: ['croak']\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [[soundChoices anyOne] ifError: ['silence']].\\n\\tself addArrows; setLiteral: startingSoundName.\\n\\tself labelMorph useSymbolFormat! !\\n\\n!SoundTile methodsFor: 'initialization' stamp: 'yo 4/6/2005 16:34'!\\nsetLiteral: anObject\\n\\n\\tsuper setLiteral: anObject.\\n\\tself labelMorph useSymbolFormat\\n! !\\n\\n\\n!SoundTile methodsFor: 'mouse handling' stamp: 'sw 11/24/2003 14:44'!\\nhandlerForMouseDown: anEvent\\n\\n\\t\\\"Return the (prospective) handler for a mouse down event. The handler is temporarily installed and can be used for morphs further down the hierarchy to negotiate whether the inner or the outer morph should finally handle the event\\\"\\n\\n\\n\\n\\t^ ((self findA: UpdatingStringMorph) bounds containsPoint: anEvent cursorPoint)\\n\\n\\t\\tifTrue:\\n\\n\\t\\t\\t[self]\\n\\n\\t\\tifFalse:\\n\\n\\t\\t\\t[super handlerForMouseDown: anEvent]! !\\nDataType subclass: #SoundType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n\\n!SoundType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ 'croak'! !\\n\\n\\n!SoundType methodsFor: 'initialization' stamp: 'sw 9/27/2001 17:24'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\tsuper initialize.\\n\\tself vocabularyName: #Sound! !\\n\\n\\n!SoundType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(1.0 0.06 0.84)\\t! !\\n\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:30'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t^ SoundTile new typeColor: self typeColor! !\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:37'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ SoundReadoutTile new typeColor: Color lightGray lighter! !\\n\\n!SoundType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nsetFormatForDisplayer: aDisplayer\\n\\t\\\"Set up the displayer to have the right format characteristics\\\"\\n\\n\\taDisplayer useStringFormat\\n\\t! !\\nSequenceableCollection subclass: #SourceFileArray\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-System'!\\n!SourceFileArray commentStamp: '<historical>' prior: 0!\\nThis class is an abstract superclass for source code access mechanisms. It defines the messages that need to be understood by those subclasses that store and retrieve source chunks on files, over the network or in databases.\\nThe first concrete subclass, StandardSourceFileArray, supports access to the traditional sources and changes files. Other subclasses might implement multiple source files for different applications, or access to a network source server.!\\n]style[(254 23 184)f1,f1LStandardSourceFileArray Comment;,f1!\\n\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:42'!\\nat: index\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'!\\nat: index put: aFileStream\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ncollect: aBlock\\n\\t| copy |\\n\\tcopy := self species new: self size.\\n\\t1 to: self size do:[:i| copy at: i put: (aBlock value: (self at: i))].\\n\\t^copy! !\\n\\n!SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'!\\nsize\\n\\tself subclassResponsibility! !\\n\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'!\\nfileIndexFromSourcePointer: anInteger\\n\\t\\\"Return the index of a source file corresponding to the given source pointer.\\\"\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'!\\nfilePositionFromSourcePointer: anInteger\\n\\t\\\"Return the position within a source file for the given source pointer.\\\"\\n\\tself subclassResponsibility! !\\n\\n!SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:01'!\\nsourcePointerFromFileIndex: index andPosition: position\\n\\t\\\"Return a sourcePointer encoding the given file index and position\\\"\\n\\tself subclassResponsibility! !\\nObject subclass: #SpaceTally\\n\\tinstanceVariableNames: 'results'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!SpaceTally commentStamp: 'sd 6/20/2003 22:31' prior: 0!\\nI'm responsible to help getting information about system space usage. The information I compute is represented by a spaceTallyItem\\n\\ntry something like: \\n\\n((SpaceTally new spaceTally: (Array with: TextMorph with: Point)) \\n\\tasSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) \\n\\nSpaceTally new systemWideSpaceTally\\n\\n\\nThis class has been created from a part of SystemDictionary. It still deserves a nice\\nclean, such as using object instead of array having 4 slots.\\n\\nsd-20 June 2003!\\n\\n\\n!SpaceTally methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:31'!\\nresults\\n\\n\\t^ results! !\\n\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'efc 7/6/2004 00:30'!\\ncomputeSpaceUsage\\n\\n\\t| entry c instanceCount |\\n\\t1 to: results size do: [:i |\\n\\t\\tentry := results at: i.\\n\\t\\tc := self class environment at: entry analyzedClassName.\\n\\t\\tinstanceCount _ c instanceCount.\\n\\t\\tentry codeSize: c spaceUsed.\\n\\t\\tentry instanceCount: instanceCount.\\n\\t\\tentry spaceForInstances: (self spaceForInstancesOf: c withInstanceCount: instanceCount).\\n\\t\\tSmalltalk garbageCollectMost].\\n\\t\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'sd 6/20/2003 22:54'!\\npreAllocateResultsFor: classes\\n\\n\\tresults := OrderedCollection new: classes size.\\n\\tclasses do: [:cl | results add: (SpaceTallyItem analyzedClassName: cl name)].\\n\\tresults _ results asArray.\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'sd 6/20/2003 22:24'!\\nspaceTally: classes\\n\\t\\\"Answer a collection of SpaceTallyItems representing the memory space (in bytes) consumed \\tby the code and instances of each class in the system. Note that code sizes do not currently \\treport memory consumed by class variables. \\\"\\n\\n\\t\\\"((SpaceTally new spaceTally: (Array with: TextMorph with: Point)) asSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) asArray\\\"\\n\\n\\tself preAllocateResultsFor: classes.\\n\\tSmalltalk garbageCollect.\\n\\tself computeSpaceUsage.\\n\\t^ results\\n! !\\n\\n!SpaceTally methodsFor: 'class analysis' stamp: 'efc 7/6/2004 00:25'!\\nsystemWideSpaceTally\\n\\t\\\"Answer a collection of SpaceTallyItems representing the memory space (in bytes) consumed \\tby the code and instances of each class in the system. Note that code sizes do not currently \\treport memory consumed by class variables. \\\"\\n\\n\\t\\\"(SpaceTally new systemWideSpaceTally asSortedCollection: [:a :b | a spaceForInstances > b spaceForInstances]) asArray\\\"\\n\\n\\t^self spaceTally: Smalltalk allClasses.\\n\\n! !\\n\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 22:39'!\\ncompareTallyIn: beforeFileName to: afterFileName\\n\\t\\\"SpaceTally new compareTallyIn: 'tally' to: 'tally2'\\\"\\n\\n\\t| answer s beforeDict a afterDict allKeys before after diff |\\n\\tbeforeDict _ Dictionary new.\\n\\ts _ FileDirectory default fileNamed: beforeFileName.\\n\\t[s atEnd] whileFalse: [\\n\\t\\ta _ Array readFrom: s nextLine.\\n\\t\\tbeforeDict at: a first put: a allButFirst.\\n\\t].\\n\\ts close.\\n\\tafterDict _ Dictionary new.\\n\\ts _ FileDirectory default fileNamed: afterFileName.\\n\\t[s atEnd] whileFalse: [\\n\\t\\ta _ Array readFrom: s nextLine.\\n\\t\\tafterDict at: a first put: a allButFirst.\\n\\t].\\n\\ts close.\\n\\tanswer _ WriteStream on: String new.\\n\\tallKeys _ (Set new addAll: beforeDict keys; addAll: afterDict keys; yourself) asSortedCollection.\\n\\tallKeys do: [ :each |\\n\\t\\tbefore _ beforeDict at: each ifAbsent: [#(0 0 0)].\\n\\t\\tafter _ afterDict at: each ifAbsent: [#(0 0 0)].\\n\\t\\tdiff _ before with: after collect: [ :vBefore :vAfter | vAfter - vBefore].\\n\\t\\tdiff = #(0 0 0) ifFalse: [\\n\\t\\t\\tanswer nextPutAll: each,' ',diff printString; cr.\\n\\t\\t].\\n\\t].\\n\\tStringHolder new contents: answer contents; openLabel: 'space diffs'.\\n\\t\\n\\n\\n! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:04'!\\nprintSpaceAnalysis\\t\\n\\t\\\"SpaceTally new printSpaceAnalysis\\\"\\n\\n\\t^ self printSpaceAnalysis: 0 on: 'STspace.text'! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:03'!\\nprintSpaceAnalysis: threshold on: fileName\\n\\t\\\"SpaceTally new printSpaceAnalysis: 1000 on: 'STspace.text1'\\\"\\n\\n\\t\\\"sd-This method should be rewrote to be more coherent within the rest of the class \\n\\tie using preAllocate and spaceForInstanceOf:\\\"\\n\\n\\t\\\"If threshold > 0, then only those classes with more than that number\\n\\tof instances will be shown, and they will be sorted by total instance space.\\n\\tIf threshold = 0, then all classes will appear, sorted by name.\\\"\\n\\n\\t| f codeSpace instCount instSpace totalCodeSpace totalInstCount totalInstSpace eltSize n totalPercent percent |\\n\\tSmalltalk garbageCollect.\\n\\ttotalCodeSpace _ totalInstCount _ totalInstSpace _ n _ 0.\\n\\tresults _ OrderedCollection new: Smalltalk classNames size.\\n'Taking statistics...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: Smalltalk classNames size\\n\\tduring: [:bar |\\n\\tSmalltalk allClassesDo:\\n\\t\\t[:cl | codeSpace _ cl spaceUsed.\\n\\t\\tbar value: (n _ n+1).\\n\\t\\tSmalltalk garbageCollectMost.\\n\\t\\tinstCount _ cl instanceCount.\\n\\t\\tinstSpace _ (cl indexIfCompact > 0 ifTrue: [4] ifFalse: [8])*instCount. \\\"Object headers\\\"\\n\\t\\tcl isVariable\\n\\t\\t\\tifTrue: [eltSize _ cl isBytes ifTrue: [1] ifFalse: [4].\\n\\t\\t\\t\\t\\tcl allInstancesDo: [:x | instSpace _ instSpace + (x basicSize*eltSize)]]\\n\\t\\t\\tifFalse: [instSpace _ instSpace + (cl instSize*instCount*4)].\\n\\t\\tresults add: (SpaceTallyItem analyzedClassName: cl name codeSize: codeSpace instanceCount: instCount spaceForInstances: instSpace).\\n\\t\\ttotalCodeSpace _ totalCodeSpace + codeSpace.\\n\\t\\ttotalInstCount _ totalInstCount + instCount.\\n\\t\\ttotalInstSpace _ totalInstSpace + instSpace]].\\n\\ttotalPercent _ 0.0.\\n\\n\\tf _ FileStream newFileNamed: fileName.\\n\\tf timeStamp.\\n\\tf nextPutAll: ('Class' padded: #right to: 30 with: $ );\\n\\t\\t\\tnextPutAll: ('code space' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('# instances' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('inst space' padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: ('percent' padded: #left to: 8 with: $ ); cr.\\n\\n\\tthreshold > 0 ifTrue:\\n\\t\\t[\\\"If inst count threshold > 0, then sort by space\\\"\\n\\t\\tresults _ (results select: [:s | s instanceCount >= threshold or: [s spaceForInstances > (totalInstSpace // 500)]])\\n\\t\\t\\t\\tasSortedCollection: [:s :s2 | s spaceForInstances > s2 spaceForInstances]].\\n\\n\\tresults do:\\n\\t\\t[:s | f nextPutAll: (s analyzedClassName padded: #right to: 30 with: $ );\\n\\t\\t\\tnextPutAll: (s codeSize printString padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: (s instanceCount printString padded: #left to: 12 with: $ );\\n\\t\\t\\tnextPutAll: (s spaceForInstances printString padded: #left to: 14 with: $ ).\\n\\t\\tpercent _ s spaceForInstances*100.0/totalInstSpace roundTo: 0.1.\\n\\t\\ttotalPercent _ totalPercent + percent.\\n\\t\\tpercent >= 0.1 ifTrue:\\n\\t\\t\\t[f nextPutAll: (percent printString padded: #left to: 8 with: $ )].\\n\\t\\tf cr].\\n\\n\\tf cr; nextPutAll: ('Total' padded: #right to: 30 with: $ );\\n\\t\\tnextPutAll: (totalCodeSpace printString padded: #left to: 12 with: $ );\\n\\t\\tnextPutAll: (totalInstCount printString padded: #left to: 12 with: $ );\\n\\t\\tnextPutAll: (totalInstSpace printString padded: #left to: 14 with: $ );\\n\\t\\tnextPutAll: ((totalPercent roundTo: 0.1) printString padded: #left to: 8 with: $ ).\\n\\tf close! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 23:07'!\\nprintSpaceDifferenceFrom: fileName1 to: fileName2\\n\\t\\\"For differential results, run printSpaceAnalysis twice with different fileNames,\\n\\tthen run this method...\\n\\t\\tSpaceTally new printSpaceAnalysis: 0 on: 'STspace.text1'.\\n\\t\\t\\t--- do something that uses space here ---\\n\\t\\tSpaceTally new printSpaceAnalysis: 0 on: 'STspace.text2'.\\n\\t\\tSpaceTally new printSpaceDifferenceFrom: 'STspace.text1' to: 'STspace.text2'\\n\\\"\\n\\t| f coll1 coll2 item |\\n\\tf _ FileStream readOnlyFileNamed: fileName1.\\n\\tcoll1 _ OrderedCollection new.\\n\\t[f atEnd] whileFalse: [coll1 add: (f upTo: Character cr)].\\n\\tf close.\\n\\tf _ FileStream readOnlyFileNamed: fileName2.\\n\\tcoll2 _ OrderedCollection new.\\n\\t[f atEnd] whileFalse:\\n\\t\\t[item _ (f upTo: Character cr).\\n\\t\\t((coll1 includes: item) and: [(item endsWith: 'percent') not])\\n\\t\\t\\tifTrue: [coll1 remove: item]\\n\\t\\t\\tifFalse: [coll2 add: item]].\\n\\tf close.\\n\\t(StringHolder new contents: (String streamContents: \\n\\t\\t\\t[:s | \\n\\t\\t\\ts nextPutAll: fileName1; cr.\\n\\t\\t\\tcoll1 do: [:x | s nextPutAll: x; cr].\\n\\t\\t\\ts cr; cr.\\n\\t\\t\\ts nextPutAll: fileName2; cr.\\n\\t\\t\\tcoll2 do: [:x | s nextPutAll: x; cr]]))\\n\\t\\topenLabel: 'Differential Space Analysis'.\\n! !\\n\\n!SpaceTally methodsFor: 'fileOut' stamp: 'sd 6/20/2003 22:59'!\\nsaveTo: aFileName\\n\\t\\\"| st |\\n\\tst := SpaceTally new.\\n\\tst spaceTally: (Array with: TextMorph with: Point).\\n\\tst saveTo: 'spaceTally2'\\\"\\n\\t| s |\\n\\t(FileDirectory default fileExists: aFileName) ifTrue: [\\n\\t\\tFileDirectory default deleteFileNamed: aFileName].\\n\\ts _ FileDirectory default fileNamed: aFileName.\\n\\tresults do: [:each | s nextPutAll: each analyzedClassName asString ; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each codeSize printString; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each instanceCount printString; \\n\\t\\t\\t\\t\\t\\tnextPutAll: ' '; nextPutAll: each spaceForInstances printString; cr].\\n\\ts close! !\\n\\n\\n!SpaceTally methodsFor: 'instance size' stamp: 'efc 7/6/2004 00:30'!\\nspaceForInstancesOf: aClass withInstanceCount: instCount\\n\\t\\\"Answer the number of bytes consumed by all instances of the given class, including their object headers.\\\"\\n\\n\\t| isCompact instVarBytes bytesPerElement contentBytes headerBytes total |\\n\\tinstCount = 0 ifTrue: [^ 0].\\n\\tisCompact _ aClass indexIfCompact > 0.\\n\\tinstVarBytes _ aClass instSize * 4.\\n\\taClass isVariable\\n\\t\\tifTrue: [\\n\\t\\t\\tbytesPerElement _ aClass isBytes ifTrue: [1] ifFalse: [4].\\n\\t\\t\\ttotal _ 0.\\n\\t\\t\\taClass allInstancesDo: [:inst |\\n\\t\\t\\t\\tcontentBytes _ instVarBytes + (inst size * bytesPerElement).\\n\\t\\t\\t\\theaderBytes _\\n\\t\\t\\t\\t\\tcontentBytes > 255\\n\\t\\t\\t\\t\\t\\tifTrue: [12]\\n\\t\\t\\t\\t\\t\\tifFalse: [isCompact ifTrue: [4] ifFalse: [8]].\\n\\t\\t\\t\\ttotal _ total + headerBytes + contentBytes].\\n\\t\\t\\t^ total]\\n\\t\\tifFalse: [\\n\\t\\t\\theaderBytes _\\n\\t\\t\\t\\tinstVarBytes > 255\\n\\t\\t\\t\\t\\tifTrue: [12]\\n\\t\\t\\t\\t\\tifFalse: [isCompact ifTrue: [4] ifFalse: [8]].\\n\\t\\t\\t^ instCount * (headerBytes + instVarBytes)].\\n! !\\nObject subclass: #SpaceTallyItem\\n\\tinstanceVariableNames: 'analyzedClassName codeSize instanceCount spaceForInstances'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Tools'!\\n!SpaceTallyItem commentStamp: 'sd 6/20/2003 22:02' prior: 0!\\nI'm represent an entry in the spaceTally.!\\n\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:59'!\\nanalyzedClassName\\n\\n\\t^ analyzedClassName! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:59'!\\nanalyzedClassName: aClassName\\n\\n\\tanalyzedClassName := aClassName! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:08'!\\ncodeSize\\n\\n\\t^ codeSize! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ncodeSize: aNumber\\n\\n\\tcodeSize := aNumber! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ninstanceCount\\n\\n\\t^ instanceCount! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:09'!\\ninstanceCount: aNumber\\n\\n\\tinstanceCount := aNumber! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:10'!\\nspaceForInstances\\n\\n\\t^ spaceForInstances! !\\n\\n!SpaceTallyItem methodsFor: 'accessing' stamp: 'sd 6/20/2003 22:10'!\\nspaceForInstances: aNumber\\n\\n\\tspaceForInstances := aNumber! !\\n\\n\\n!SpaceTallyItem methodsFor: 'printing' stamp: 'sd 6/20/2003 22:52'!\\nprintOn: aStream\\n\\n\\tanalyzedClassName isNil\\n\\t\\tifFalse: [aStream nextPutAll: analyzedClassName asString]. \\n\\taStream nextPutAll: ' ('.\\n\\tcodeSize isNil\\n\\t\\tifFalse: [aStream nextPutAll: 'code size: ' ; nextPutAll: codeSize asString]. \\n\\tinstanceCount isNil\\n\\t\\tifFalse: [aStream nextPutAll: ' instance count: ' ; nextPutAll: instanceCount asString]. \\n\\tspaceForInstances isNil\\n\\t\\tifFalse: [aStream nextPutAll: ' space for instances: ' ; nextPutAll: spaceForInstances asString]. \\n\\taStream nextPut: $).\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpaceTallyItem class\\n\\tinstanceVariableNames: ''!\\n\\n!SpaceTallyItem class methodsFor: 'instance creation' stamp: 'sd 6/20/2003 22:54'!\\nanalyzedClassName: aClassName\\n\\n\\t^ self new\\n\\t\\tanalyzedClassName: aClassName ; yourself\\n\\t\\t! !\\n\\n!SpaceTallyItem class methodsFor: 'instance creation' stamp: 'sd 6/20/2003 22:54'!\\nanalyzedClassName: aClassName codeSize: codeSize instanceCount: instanceCount spaceForInstances: spaceForInstances\\n\\n\\t^ self new\\n\\t\\tanalyzedClassName: aClassName ;\\n\\t\\tcodeSize: codeSize ;\\n\\t\\tinstanceCount: instanceCount ;\\n\\t\\tspaceForInstances: spaceForInstances ; yourself! !\\nArrayedCollection variableSubclass: #SparseLargeTable\\n\\tinstanceVariableNames: 'base size chunkSize defaultValue'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Arrayed'!\\n!SparseLargeTable commentStamp: '<historical>' prior: 0!\\nDerivated from Stephan Pair's LargeArray, but to hold a sparse table, in which most of the entries are the same default value, it uses some tricks.!\\n\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\narrayClass\\n\\n\\t^(self basicAt: 1) class\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nat: index\\n\\n\\tself pvtCheckIndex: index.\\n\\t^self noCheckAt: index.\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nat: index put: value\\n\\t\\n\\tself pvtCheckIndex: index.\\n\\t^self noCheckAt: index put: value\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 17:56'!\\nbase\\n\\n\\t^ base.\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nchunkSize\\n\\n\\t^chunkSize\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'tak 12/21/2004 16:59'!\\nnoCheckAt: index\\n\\t| chunkIndex t |\\n\\n\\tchunkIndex := index - base // chunkSize + 1.\\n\\t(chunkIndex > self basicSize or: [chunkIndex < 1]) ifTrue: [^ defaultValue].\\n\\tt _ self basicAt: chunkIndex.\\n\\tt ifNil: [^ defaultValue].\\n\\t^ t at: (index - base + 1 - (chunkIndex - 1 * chunkSize))\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 19:18'!\\nnoCheckAt: index put: value\\n\\t| chunkIndex t |\\n\\n\\tchunkIndex := index - base // chunkSize + 1.\\n\\tchunkIndex > self basicSize ifTrue: [^ value].\\n\\tt _ self basicAt: chunkIndex.\\n\\tt ifNil: [^ value].\\n\\t^ t at: (index - base + 1 - (chunkIndex - 1 * chunkSize)) put: value\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:58'!\\nsize\\n\\n\\t^size\\n! !\\n\\n!SparseLargeTable methodsFor: 'accessing' stamp: 'yo 12/1/2003 22:34'!\\nzapDefaultOnlyEntries\\n\\n\\t| lastIndex newInst |\\n\\t1 to: self basicSize do: [:i |\\n\\t\\t(self allDefaultValueSubtableAt: i) ifTrue: [self basicAt: i put: nil].\\n\\t].\\n\\n\\tlastIndex _ self findLastNonNilSubTable.\\n\\tlastIndex = 0 ifTrue: [^ self].\\n\\t\\n\\tnewInst _ self class new: lastIndex*chunkSize chunkSize: chunkSize arrayClass: (self basicAt: lastIndex) class base: base defaultValue: defaultValue.\\n\\tnewInst privateSize: self size.\\n\\tbase to: newInst size do: [:i | newInst at: i put: (self at: i)].\\n\\t1 to: newInst basicSize do: [:i |\\n\\t\\t(newInst allDefaultValueSubtableAt: i) ifTrue: [newInst basicAt: i put: nil].\\n\\t].\\n\\n\\tself becomeForward: newInst.\\n\\t^ newInst.\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'initialization' stamp: 'yo 12/1/2003 16:58'!\\ninitChunkSize: aChunkSize size: aSize arrayClass: aClass base: b defaultValue: d\\n\\n\\t| lastChunkSize |\\n\\tchunkSize := aChunkSize.\\n\\tsize := aSize.\\n\\tbase _ b.\\n\\tdefaultValue _ d.\\n\\t1 to: (self basicSize - 1) do: [ :in | self basicAt: in put: (aClass new: chunkSize withAll: defaultValue) ].\\n\\tlastChunkSize := size \\\\\\\\ chunkSize.\\n\\tlastChunkSize = 0 ifTrue: [lastChunkSize := chunkSize].\\n\\tsize = 0 \\n\\t\\tifTrue: [self basicAt: 1 put: (aClass new: 0)]\\n\\t\\tifFalse: [self basicAt: self basicSize put: (aClass new: lastChunkSize withAll: defaultValue)].\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 17:06'!\\nprintElementsOn: aStream\\n\\t| element |\\n\\taStream nextPut: $(.\\n\\tbase to: size do: [:index | element _ self at: index. aStream print: element; space].\\n\\tself isEmpty ifFalse: [aStream skip: -1].\\n\\taStream nextPut: $)\\n! !\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 15:58'!\\nprintOn: aStream\\n\\n\\t(#(String) includes: self arrayClass name) \\n\\t\\tifTrue: [^self storeOn: aStream].\\n\\t^super printOn: aStream\\n! !\\n\\n!SparseLargeTable methodsFor: 'printing' stamp: 'yo 12/1/2003 15:59'!\\nstoreOn: aStream\\n\\n\\t| x |\\n\\t(#(String) includes: self arrayClass name) ifTrue: \\n\\t\\t[aStream nextPut: $'.\\n\\t\\t1 to: self size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\taStream nextPut: (x _ self at: i).\\n\\t\\t\\tx == $' ifTrue: [aStream nextPut: x]].\\n\\t\\taStream nextPutAll: ''' asLargeArrayChunkSize: '.\\n\\t\\taStream nextPutAll: self chunkSize asString.\\n\\t\\t^self].\\n\\t^super storeOn: aStream\\n! !\\n\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 18:58'!\\nallDefaultValueSubtableAt: index\\n\\n\\t| t |\\n\\tt _ self basicAt: index.\\n\\tt ifNil: [^ true].\\n\\tt do: [:e |\\n\\t\\te ~= defaultValue ifTrue: [^ false].\\n\\t].\\n\\t^ true.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 17:10'!\\nanalyzeSpaceSaving\\n\\n\\t| total elems tablesTotal nonNilTables |\\n\\ttotal _ size - base + 1.\\n\\telems _ 0.\\n\\tbase to: size do: [:i | (self at: i) ~= defaultValue ifTrue: [elems _ elems + 1]].\\n\\ttablesTotal _ self basicSize.\\n\\tnonNilTables _ 0.\\n\\t1 to: self basicSize do: [:i | (self basicAt: i) ifNotNil: [nonNilTables _ nonNilTables + 1]].\\n\\n\\t^ String streamContents: [:strm |\\n\\t\\tstrm nextPutAll: 'total: '.\\n\\t\\tstrm nextPutAll: total printString.\\n\\t\\tstrm nextPutAll: ' elements: '.\\n\\t\\tstrm nextPutAll: elems printString.\\n\\t\\tstrm nextPutAll: ' tables: '.\\n\\t\\tstrm nextPutAll: tablesTotal printString.\\n\\t\\tstrm nextPutAll: ' non-nil: '.\\n\\t\\tstrm nextPutAll: nonNilTables printString.\\n\\t].\\n\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'nk 8/31/2004 08:34'!\\ncopyEmpty\\n\\t\\\"Answer a copy of the receiver that contains no elements.\\\"\\n\\t^self speciesNew: 0\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 22:34'!\\nfindLastNonNilSubTable\\n\\n\\t(self basicAt: self basicSize) ifNotNil: [^ self basicSize].\\n\\n\\tself basicSize - 1 to: 1 by: -1 do: [:lastIndex |\\n\\t\\t(self basicAt: lastIndex) ifNotNil: [^ lastIndex].\\n\\t].\\n\\t^ 0.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 19:19'!\\nprivateSize: s\\n\\n\\tsize _ s.\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 17:34'!\\npvtCheckIndex: index \\n\\n\\tindex isInteger ifFalse: [self errorNonIntegerIndex].\\n\\tindex < 1 ifTrue: [self errorSubscriptBounds: index].\\n\\tindex > size ifTrue: [self errorSubscriptBounds: index].\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarInstance\\n\\n\\t^self class\\n\\t\\tnew: self size \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarInstance: newSize\\n\\n\\t^self class\\n\\t\\tnew: newSize \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 15:59'!\\nsimilarSpeciesInstance\\n\\n\\t^self similarInstance\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nsimilarSpeciesInstance: newSize\\n\\n\\t^self similarInstance: newSize\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nspeciesNew\\n\\n\\t^self species\\n\\t\\tnew: self size \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n!SparseLargeTable methodsFor: 'private' stamp: 'yo 12/1/2003 16:00'!\\nspeciesNew: newSize\\n\\n\\t^self species\\n\\t\\tnew: newSize \\n\\t\\tchunkSize: self chunkSize \\n\\t\\tarrayClass: self arrayClass\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSparseLargeTable class\\n\\tinstanceVariableNames: ''!\\n\\n!SparseLargeTable class methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:54'!\\ndefaultChunkSize\\n\\n\\t^100! !\\n\\n!SparseLargeTable class methodsFor: 'accessing' stamp: 'yo 12/1/2003 15:54'!\\ndefaultChunkSizeForFiles\\n\\n\\t^8000! !\\n\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:06'!\\nnew: size\\n\\n\\t^self new: size chunkSize: self defaultChunkSize\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:07'!\\nnew: size chunkSize: chunkSize\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:08'!\\nnew: size chunkSize: chunkSize arrayClass: aClass\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array base: 1.\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:37'!\\nnew: size chunkSize: chunkSize arrayClass: aClass base: b\\n\\n\\t^self new: size chunkSize: chunkSize arrayClass: Array base: 1 defaultValue: nil.\\n! !\\n\\n!SparseLargeTable class methodsFor: 'instance creation' stamp: 'yo 12/1/2003 16:37'!\\nnew: size chunkSize: chunkSize arrayClass: aClass base: b defaultValue: d\\n\\n\\t| basicSize |\\n\\t(basicSize := ((size - 1) // chunkSize) + 1) = 0\\n\\t\\tifTrue: [basicSize := 1].\\n\\t^(self basicNew: basicSize)\\n\\t\\tinitChunkSize: chunkSize size: size arrayClass: aClass base: b defaultValue: d;\\n\\t\\tyourself\\n! !\\nObject subclass: #SparseXTable\\n\\tinstanceVariableNames: 'tables xTables'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!SparseXTable methodsFor: 'as yet unclassified' stamp: 'yo 7/30/2003 17:38'!\\ntableFor: code\\n\\n\\t| div t table |\\n\\tdiv _ code // 65536.\\n\\tt _ xTables at: div ifAbsent: [table _ Array new: 65536 withAll: 0. xTables at: div put: table. table].\\n\\t^ t.\\n! !\\nObject subclass: #Speaker\\n\\tinstanceVariableNames: 'pitch range loudness speed transcriber voice visitors'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-TTS'!\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:33'!\\nloudness\\n\\t^ loudness! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nloudness: aNumber\\n\\tloudness := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/13/1999 03:02'!\\nphonemes\\n\\t\\\"Answer the phoneme set of the receiver.\\\"\\n\\t^ self transcriber phonemes! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:18'!\\npitch\\n\\t\\\"Answer the average pitch.\\\"\\n\\t^ pitch! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\npitch: aNumber\\n\\t\\\"Set the average pitch.\\\"\\n\\tpitch := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:18'!\\nrange\\n\\t\\\"Answer the pitch range (variation).\\\"\\n\\t^ range! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nrange: aNumber\\n\\t\\\"Set the pitch range (variation).\\\"\\n\\trange := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:33'!\\nspeed\\n\\t^ speed! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nspeed: aNumber\\n\\tspeed := aNumber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:31'!\\ntranscriber\\n\\t^ transcriber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\ntranscriber: aPhoneticTranscriber\\n\\ttranscriber := aPhoneticTranscriber! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/12/1999 23:02'!\\nvisitors\\n\\t^ visitors! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nvisitors: aCollection\\n\\tvisitors := aCollection! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'len 12/8/1999 16:32'!\\nvoice\\n\\t^ voice! !\\n\\n!Speaker methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nvoice: aVoice\\n\\tvoice := aVoice! !\\n\\n\\n!Speaker methodsFor: 'editing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nedit\\n\\t| answer buttons |\\n\\tanswer := (self findAVoice: KlattVoice) editor.\\n\\tbuttons := AlignmentMorph new listDirection: #leftToRight; color: answer color.\\n\\tbuttons\\n\\t\\taddMorphFront: (SimpleButtonMorph new target: self; actWhen: #buttonDown; actionSelector: #newHead; labelString: 'new head');\\n\\t\\taddMorphFront: (SimpleButtonMorph new target: self; actWhen: #buttonDown; actionSelector: #saySomething; labelString: 'test').\\n\\tanswer\\n\\t\\taddSliderForParameter: #speed target: self min: 0.1 max: 2.0 description: 'Speed';\\n\\t\\taddSliderForParameter: #loudness target: self min: 0.0 max: 1.0 description: 'Loudness';\\n\\t\\taddSliderForParameter: #range target: self min: 0.0 max: 1.0 description: 'Pitch Range';\\n\\t\\taddSliderForParameter: #pitch target: self min: 20.0 max: 800.0 description: 'Pitch';\\n\\t\\taddMorphFront: buttons;\\n\\t\\topenInWorld! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:19'!\\nfindAVoice: aClass\\n\\t(self voice isKindOf: aClass) ifTrue: [^ self voice].\\n\\t(self voice isKindOf: CompositeVoice)\\n\\t\\tifTrue: [self voice do: [ :each | (each isKindOf: aClass) ifTrue: [^ each]]].\\n\\t^ nil! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:27'!\\nmakeGestural\\n\\t(self findAVoice: GesturalVoice) isNil ifFalse: [^ self].\\n\\tself voice: self voice + GesturalVoice new! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/2/1999 03:27'!\\nnewHead\\n\\tself makeGestural.\\n\\t(self findAVoice: GesturalVoice) newHead! !\\n\\n!Speaker methodsFor: 'editing' stamp: 'len 12/14/1999 05:24'!\\nsaySomething\\n\\tself say: #('This is my voice.' 'I am speaking.' 'Do you like my voice?' 'Listen to my voice.' 'Hello.' 'Hay. What are you doing?' 'How are you?' 'Is this my voice?' 'Are you there?' 'Help, please.' 'Howdy.' 'Ha ha he he hi.') atRandom! !\\n\\n\\n!Speaker methodsFor: 'initialization' stamp: 'len 11/27/2000 09:59'!\\ninitialize\\n\\tself pitch: 100.0; range: 0.3; loudness: 1.0; speed: 0.6; \\\"normalizer: TextNormalizer new;\\\" transcriber: PhoneticTranscriber default; visitors: {IntonationVisitor default. DurationsVisitor default. F0RenderingVisitor default}! !\\n\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/14/1999 02:13'!\\nclauseFromString: aString\\n\\t^ Clause new\\n\\t\\tstring: aString;\\n\\t\\tphrases: ((aString findTokens: '!!?.,;()') collect: [ :each | self phraseFromString: each])! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\neventsFromString: aString\\n\\t| clause |\\n\\tclause := self clauseFromString: aString.\\n\\tclause phrases do: [ :each | each lastSyllable events add: (PhoneticEvent new phoneme: self phonemes silence; duration: 0.1)].\\n\\tclause lastSyllable events last duration: 0.5.\\n\\tvisitors do: [ :each | each speaker: self. clause accept: each].\\n\\tclause eventsDo: [ :each | each loudness: self loudness].\\n\\t^ clause events! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/13/1999 03:19'!\\nphraseFromString: aString\\n\\t^ Phrase new\\n\\t\\tstring: aString;\\n\\t\\twords: ((aString findTokens: ' !!?.,;()') collect: [ :each | self wordFromString: each])! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nsyllabizationOf: phonemes\\n\\t| syllable stream last answer |\\n\\tanswer := OrderedCollection new.\\n\\tsyllable := Syllable new phonemes: (OrderedCollection new: 4).\\n\\tstream := ReadStream on: phonemes.\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [syllable phonemes add: (last := stream next).\\n\\t\\t\\t\\t\\t(stream atEnd not and: [last isConsonant not and: [stream peek isConsonant]])\\n\\t\\t\\t\\t\\t\\tifTrue: [answer add: syllable. syllable := Syllable new phonemes: (OrderedCollection new: 4)]].\\n\\tsyllable phonemes isEmpty ifFalse: [answer add: syllable].\\n\\t^ answer! !\\n\\n!Speaker methodsFor: 'parsing' stamp: 'len 12/8/1999 18:24'!\\nwordFromString: aString\\n\\t^ Word new\\n\\t\\tstring: aString;\\n\\t\\tsyllables: (self syllabizationOf: (self transcriber transcriptionOf: aString))! !\\n\\n\\n!Speaker methodsFor: 'playing' stamp: 'nk 2/19/2004 16:50'!\\nnumberSignDelay\\n\\t\\\"Answer the number of milliseconds that a # symbol in the string given to say: will generate.\\\"\\n\\t^200! !\\n\\n!Speaker methodsFor: 'playing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nsay: aString \\n\\t\\\"aString may contain characters and punctuation.\\n\\tYou may also include the # symbol in aString;\\n\\tfor each one of these, a 200msec delay will be generated.\\\"\\n\\n\\t| events stream string token delay |\\n\\n\\tstream := ReadStream\\n\\t\\t\\t\\ton: ((aString\\n\\t\\t\\t\\t\\t\\tcopyReplaceAll: '-'\\n\\t\\t\\t\\t\\t\\twith: ' '\\n\\t\\t\\t\\t\\t\\tasTokens: false)\\n\\t\\t\\t\\t\\t\\tfindTokens: '?# '\\n\\t\\t\\t\\t\\t\\tkeep: '?#').\\n\\tstring := ''.\\n\\tdelay := 0.\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [token := stream next.\\n\\t\\t\\ttoken = '#'\\n\\t\\t\\t\\tifTrue: [ self voice playSilenceMSecs: self numberSignDelay.\\n\\t\\t\\t\\t\\tdelay := delay + self numberSignDelay ]\\n\\t\\t\\t\\tifFalse: [string := string , ' ' , token.\\n\\t\\t\\t\\t\\t(token = '?' or: [stream atEnd])\\n\\t\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tevents := CompositeEvent new.\\n\\t\\t\\t\\t\\t\\t\\tevents addAll: (self eventsFromString: string).\\n\\t\\t\\t\\t\\t\\t\\tevents playOn: self voice delayed: delay.\\n\\t\\t\\t\\t\\t\\t\\tdelay := delay + (events duration * 1000).\\n\\t\\t\\t\\t\\t\\t\\tstring := '' ]]].\\n\\tself voice flush! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpeaker class\\n\\tinstanceVariableNames: ''!\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:17'!\\nbicyclic\\n\\t\\\"\\n\\tSpeaker bicyclic say: 'This is my voice. I am a woman with bicyclic voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 200.0;\\n\\t\\tvoice: (KlattVoice new diplophonia: 0.4; tract: 14.4)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:56'!\\nbigMan\\n\\t\\\"\\n\\tSpeaker bigMan say: 'I am the child? No. I am the big man speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 90.0;\\n\\t\\trange: 0.5;\\n\\t\\tvoice: (KlattVoice new tract: 20)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:19'!\\nbreathy\\n\\t\\\"\\n\\tSpeaker breathy say: 'This is my breathy voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.6; turbulence: 70)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:07'!\\nchild\\n\\t\\\"\\n\\tSpeaker child say: 'Hello. I am a child speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 320.0;\\n\\t\\tvoice: (KlattVoice new tract: 12)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:21'!\\ncreaky\\n\\t\\\"\\n\\tSpeaker creaky say: 'This is my creaky voice with hight jitter and shimmer.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 90.0;\\n\\t\\tspeed: 0.5;\\n\\t\\tvoice: (KlattVoice new jitter: 0.5; shimmer: 0.5)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 11/27/2000 10:01'!\\ndefault\\n\\t\\\"\\n\\tSpeaker default say: 'This is the default voice.'\\n\\t\\\"\\n\\n\\t^ self new voice: KlattVoice new! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:13'!\\nexorsist\\n\\t\\\"\\n\\tSpeaker exorsist say: 'This is an scary voice. Boo.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 40.0;\\n\\t\\tspeed: 0.5;\\n\\t\\tvoice: (KlattVoice new tract: 10; diplophonia: 0.4; jitter: 0.3; shimmer: 0.5; turbulence: 50)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:13'!\\nfly\\n\\t\\\"\\n\\tSpeaker fly say: 'Haaaaaalp.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 650.0;\\n\\t\\tloudness: 0.5;\\n\\t\\tspeed: 0.8;\\n\\t\\tvoice: (KlattVoice new flutter: 1.0; tract: 1)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:01'!\\nkid\\n\\t\\\"\\n\\tSpeaker kid say: 'Do you like my voice? I am the kid speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 170.0;\\n\\t\\trange: 0.4;\\n\\t\\tvoice: (KlattVoice new tract: 16)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 11/27/2000 10:01'!\\nman\\n\\t\\\"\\n\\tSpeaker man say: 'Listen to my voice. I am a man speaking.'\\n\\t\\\"\\n\\n\\t^ self default pitch: 90.0! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:26'!\\nnotPressed\\n\\t\\\"\\n\\tSpeaker notPressed say: 'This is a non pressed voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.9)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:26'!\\npressed\\n\\t\\\"\\n\\tSpeaker pressed say: 'This is a pressed voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 100.0;\\n\\t\\tvoice: (KlattVoice new ro: 0.1)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 03:27'!\\nwhispery\\n\\t\\\"\\n\\tSpeaker whispery say: 'This is my whispery voice.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tvoice: (KlattVoice new breathiness: 1.0)! !\\n\\n!Speaker class methodsFor: 'examples' stamp: 'len 12/14/1999 04:10'!\\nwoman\\n\\t\\\"\\n\\tSpeaker woman say: 'Do you listen? I am a woman speaking.'\\n\\t\\\"\\n\\n\\t^ self new\\n\\t\\tpitch: 230.0;\\n\\t\\trange: 0.5;\\n\\t\\tspeed: 0.7;\\n\\t\\tvoice: (KlattVoice new flutter: 0.5; ro: 0.3; ra: 0.003; tract: 14.4)! !\\n\\n\\n!Speaker class methodsFor: 'examples-others' stamp: 'len 12/2/1999 03:46'!\\nmanWithEditor\\n\\t\\\"\\n\\tSpeaker manWithEditor say: 'With this editor you can change my voice.'\\n\\t\\\"\\n\\n\\t^ self man edit! !\\n\\n!Speaker class methodsFor: 'examples-others' stamp: 'len 12/14/1999 05:10'!\\nmanWithHead\\n\\t\\\"\\n\\tSpeaker manWithHead say: 'This is my voice. Can you see my lips?'\\n\\t\\\"\\n\\n\\t^ self man newHead! !\\nMorph subclass: #SpeakerMorph\\n\\tinstanceVariableNames: 'bufferSize buffer lastConePosition sound'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'nk 6/12/2004 10:05'!\\naddGraphic\\n\\n\\t| graphic |\\n\\tgraphic _ World drawingClass withForm: self speakerGraphic.\\n\\tgraphic position: bounds center - (graphic extent // 2).\\n\\tself addMorph: graphic.\\n! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:51'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color\\n\\t\\tr: 1.0\\n\\t\\tg: 0.484\\n\\t\\tb: 0.258! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:51'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself addGraphic.\\n\\tbufferSize _ 5000.\\n\\tbuffer _ WriteStream\\n\\t\\t\\t\\ton: (SoundBuffer newMonoSampleCount: bufferSize).\\n\\tlastConePosition _ 0.\\n\\tsound _ SequentialSound new! !\\n\\n!SpeakerMorph methodsFor: 'initialization' stamp: 'jm 4/22/1999 22:58'!\\nspeakerGraphic\\n\\n\\t^ Form\\n\\t\\textent: 19@18\\n\\t\\tdepth: 8\\n\\t\\tfromArray: #(0 0 1493172224 2816 0 0 0 1493172224 11 0 0 138 1493172224 184549376 184549376 0 35509 2315255808 720896 720896 0 9090522 2315255808 2816 720896 0 2327173887 2315255819 2816 720896 138 3051028442 2315255819 2816 2816 1505080590 4294957786 2315255808 184549387 2816 3053453311 4292532917 1493172224 184549387 2816 1505080714 3048584629 1493172224 184549387 2816 9079434 3048584629 1493172224 184549387 2816 138 2327164341 1493172235 2816 2816 0 2324346293 1493172235 2816 720896 0 9079477 1493172224 2816 720896 0 35466 1493172224 720896 720896 0 138 0 184549376 184549376 0 0 0 11 0 0 0 0 2816 0)\\n\\t\\toffset: 0@0\\n! !\\n\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jdl 3/28/2003 09:38'!\\nappendSample: aFloat \\n\\t\\\"Append the given sample, a number between -100.0 and 100.0, to my buffer. Flush the buffer if it is full.\\\"\\n\\n\\tlastConePosition := aFloat.\\n\\tlastConePosition := lastConePosition min: 100.0.\\n\\tlastConePosition := lastConePosition max: -100.0.\\n\\tbuffer nextPut: (327.67 * lastConePosition) truncated.\\n\\tbuffer position >= bufferSize ifTrue: [self flushBuffer]\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/21/1999 10:18'!\\nconePosition\\n\\n\\t^ lastConePosition\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 16:46'!\\nconePosition: aNumber\\n\\n\\tself appendSample: aNumber asFloat. \\\"sets lastConePosition\\\"\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 13:29'!\\nflushBuffer\\n\\n\\t| buf |\\n\\tbuf _ buffer contents.\\n\\tbuffer resetContents.\\n\\tsound isPlaying ifFalse: [sound _ SequentialSound new].\\n\\tsound add: (SampledSound samples: buf samplingRate: 11025).\\n\\tsound isPlaying\\n\\t\\tifTrue: [sound pruneFinishedSounds]\\n\\t\\tifFalse: [sound play].\\n! !\\n\\n!SpeakerMorph methodsFor: 'speaker' stamp: 'jm 4/22/1999 15:33'!\\nstopSound\\n\\n\\tsound pause.\\n\\tbuffer resetContents.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpeakerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SpeakerMorph class methodsFor: '*eToys-scripting' stamp: 'sw 9/26/2001 04:27'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories.\\\"\\n\\n\\t^ #((speaker\\n\\n((slot conePosition 'the position of the speaker cone' Number readWrite Player getConePosition Player setConePosition:))))\\n\\n\\n\\n! !\\nAlignmentMorph subclass: #SpectrumAnalyzerMorph\\n\\tinstanceVariableNames: 'soundInput statusLight levelMeter graphMorph sonogramMorph fft displayType'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SoundInterface'!\\n!SpectrumAnalyzerMorph commentStamp: '<historical>' prior: 0!\\nI am a tool for analyzing sound data from a microphone, CD, or other input source in real time. I have several display modes:\\n\\n\\tsignal\\t\\tsnapshots of the raw signal data as it arrives\\n\\tspectrum\\tfrequency spectrum of the signal data as it arrives\\n\\tsonogram\\tscrolling plot of the frequency spectrum over time,\\n\\t\\t\\t where the vertical axis is frequency, the horizontal\\n\\t\\t\\t\\t axis is time, and amount of energy at a given\\n\\t\\t\\t\\t frequency is shown as a grayscale value with\\n\\t\\t\\t\\t larger values being darker\\n\\nTo use this tool, be sure that you have selected the proper sound source using you host OS facilities. Set the desired sampling rate and FFT size (try 22050 samples/sec and an FFT size of 512) then click on the 'start' button. Use the slider to adjust the level so that the yellow level indicator peaks somewhere between the middle and the right edge at the maximum signal level.\\n\\nNote that if the level meter peaks hit the right edge, you will get 'clipping', which creates a bunch of spurious high frequency noise in the frequency spectrum. If the display is set to 'signal' mode, you can actually see the tops and bottoms of the waveform being cut off when clipping occurs.\\n\\nMany machines may not be able to perform spectrum analysis in real time, especially at higher sampling rates and larger FFT sizes. In both 'signal' and 'spectrum' modes, this tool will skip data to try to keep up with real time. However, in 'sonogram' mode it always processes all the data, even if it falls behind. This allows you to get a complete sonogram without dropouts even on a slower machine. However, as the sonogram display falls behind there will be a larger and larger time lag between when a sound is input and when it appears on the display.\\n\\nThe smaller the FFT size, the less frequency resolution you get. The lower the sampling rate, the less total frequency range you get. For an FFT size of N and a sampling rate of R, each of the N/2 'bins' of the frequency spectrum has a frequency resolution of R / N. For example, at a sampleing rate of 22050 samples/second, the total frequency range is 0 to 11025 Hz and an FFT of size 256 would divide this range into 128 bins (the output of an FFT of size N has N/2 bins), each of which covers a frequency band about 86 Hz wide.\\n\\nTo increase time resolution, increase the sampling rate and decrease the FFT size.\\n!\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:52'!\\ndefaultBorderWidth\\n\\\"answer the default border width for the receiver\\\"\\n\\t^ 2! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:52'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tself listDirection: #topToBottom.\\n\\tsoundInput _ SoundInputStream new samplingRate: 22050.\\n\\tfft _ FFT new: 512.\\n\\tdisplayType _ 'sonogram'.\\n\\tself hResizing: #shrinkWrap.\\n\\tself vResizing: #shrinkWrap.\\n\\tself addButtonRow.\\n\\tself addLevelSlider.\\n\\tself addMorphBack: self makeLevelMeter.\\n\\tself addMorphBack: (Morph new extent: 10 @ 10;\\n\\t\\t\\t color: Color transparent).\\n\\t\\\"spacer\\\"\\n\\tself resetDisplay! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:25'!\\ninvokeMenu\\n\\t\\\"Invoke the settings menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ CustomMenu new.\\n\\taMenu addList:\\t{\\n\\t\\t{'set sampling rate' translated.\\t\\t#setSamplingRate}.\\n\\t\\t{'set FFT size' translated.\\t\\t\\t#setFFTSize}.\\n\\t\\t{'set display type' translated.\\t\\t#setDisplayType}}.\\n\\taMenu invokeOn: self defaultSelection: nil.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'jm 9/8/1999 12:52'!\\nresetDisplay\\n\\t\\\"Recreate my display after changing some parameter such as FFT size.\\\"\\n\\n\\tdisplayType = 'signal' ifTrue: [self showSignal].\\n\\tdisplayType = 'spectrum' ifTrue: [self showSpectrum].\\n\\tdisplayType = 'sonogram' ifTrue: [self showSonogram].\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:29'!\\nsetDisplayType\\n\\t\\\"Set the display type.\\\"\\n\\n\\t| aMenu choice on |\\n\\taMenu _ CustomMenu new title: ('display type (currently {1})' translated format:{displayType}).\\n\\taMenu addList:\\t{\\n\\t\\t{'signal' translated.\\t'signal'}.\\n\\t\\t{'spectrum' translated.\\t'spectrum'}.\\n\\t\\t{'sonogram' translated.\\t'sonogram'}}.\\n\\tchoice _ aMenu startUp.\\n\\tchoice ifNil: [^ self].\\n\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tdisplayType _ choice.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:27'!\\nsetFFTSize\\n\\t\\\"Set the size of the FFT used for frequency analysis.\\\"\\n\\n\\t| aMenu sz on |\\n\\taMenu _ CustomMenu new title: ('FFT size (currently {1})' translated format:{fft n}).\\n\\t((7 to: 10) collect: [:n | 2 raisedTo: n]) do:[:r | aMenu add: r printString action: r].\\n\\tsz _ aMenu startUp.\\n\\tsz ifNil: [^ self].\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tfft _ FFT new: sz.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'menu and buttons' stamp: 'dgd 9/19/2003 13:26'!\\nsetSamplingRate\\n\\t\\\"Set the sampling rate to be used for incoming sound data.\\\"\\n\\n\\t| aMenu rate on |\\n\\taMenu _ CustomMenu new title:\\n\\t\\t('Sampling rate (currently {1})' translated format:{soundInput samplingRate}).\\n\\t#(11025 22050 44100) do:[:r | aMenu add: r printString action: r].\\n\\trate _ aMenu startUp.\\n\\trate ifNil: [^ self].\\n\\ton _ soundInput isRecording.\\n\\tself stop.\\n\\tsoundInput samplingRate: rate.\\n\\tself resetDisplay.\\n\\ton ifTrue: [self start].\\n\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 15:12'!\\nstart\\n\\t\\\"Start displaying sound data.\\\"\\n\\n\\tdisplayType = 'signal'\\n\\t\\tifTrue: [soundInput bufferSize: graphMorph width - (2 * graphMorph borderWidth)]\\n\\t\\tifFalse: [soundInput bufferSize: fft n].\\n\\tsoundInput startRecording.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 19:05'!\\nstep\\n\\t\\\"Update the record light, level meter, and display.\\\"\\n\\n\\t| w |\\n\\t\\\"update the record light and level meter\\\"\\n\\tsoundInput isRecording\\n\\t\\tifTrue: [statusLight color: Color yellow]\\n\\t\\tifFalse: [statusLight color: Color gray].\\n\\tw _ ((121 * soundInput meterLevel) // 100) max: 1.\\n\\tlevelMeter width ~= w ifTrue: [levelMeter width: w].\\n\\n\\t\\\"update the display if any data is available\\\"\\n\\tself updateDisplay.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/8/1999 15:12'!\\nstop\\n\\t\\\"Stop displaying sound data.\\\"\\n\\n\\tsoundInput stopRecording.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'stepping and presenter' stamp: 'jm 9/6/1999 12:12'!\\nstopStepping\\n\\t\\\"Turn off recording.\\\"\\n\\n\\tsuper stopStepping.\\n\\tsoundInput stopRecording.\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'submorphs-add/remove' stamp: 'jm 9/6/1999 14:40'!\\ndelete\\n\\t\\\"Turn off recording when this morph is deleted.\\\"\\n\\n\\tsuper delete.\\n\\tsoundInput stopRecording.\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'testing' stamp: 'jm 9/7/1999 22:26'!\\nstepTime\\n\\n\\t^ 0\\n! !\\n\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'dgd 9/19/2003 13:30'!\\naddButtonRow\\n\\n\\t| r |\\n\\tr _ AlignmentMorph newRow vResizing: #shrinkWrap.\\n\\tr addMorphBack: (self buttonName: 'Menu' translated action: #invokeMenu).\\n\\tr addMorphBack: (Morph new extent: 4@1; color: Color transparent).\\n\\tr addMorphBack: (self buttonName: 'Start' translated action: #start).\\n\\tr addMorphBack: (Morph new extent: 4@1; color: Color transparent).\\n\\tr addMorphBack: (self buttonName: 'Stop' translated action: #stop).\\n\\tr addMorphBack: (Morph new extent: 12@1; color: Color transparent).\\n\\tr addMorphBack: self makeStatusLight.\\n\\tself addMorphBack: r.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'ar 11/9/2000 21:23'!\\naddLevelSlider\\n\\n\\t| levelSlider r |\\n\\tlevelSlider _ SimpleSliderMorph new\\n\\t\\tcolor: color;\\n\\t\\textent: 100@2;\\n\\t\\ttarget: soundInput;\\n\\t\\tactionSelector: #recordLevel:;\\n\\t\\tadjustToValue: soundInput recordLevel.\\n\\tr _ AlignmentMorph newRow\\n\\t\\tcolor: color;\\n\\t\\tlayoutInset: 0;\\n\\t\\twrapCentering: #center; cellPositioning: #leftCenter;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #rigid;\\n\\t\\theight: 24.\\n\\tr addMorphBack: (StringMorph contents: '0 ').\\n\\tr addMorphBack: levelSlider.\\n\\tr addMorphBack: (StringMorph contents: ' 10').\\n\\tself addMorphBack: r.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jhm 10/15/97 14:30'!\\nbuttonName: aString action: aSymbol\\n\\n\\t^ SimpleButtonMorph new\\n\\t\\ttarget: self;\\n\\t\\tlabel: aString;\\n\\t\\tactionSelector: aSymbol\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 13:27'!\\nmakeLevelMeter\\n\\n\\t| outerBox |\\n\\touterBox _ RectangleMorph new extent: 125@14; color: Color lightGray.\\n\\tlevelMeter _ Morph new extent: 2@10; color: Color yellow.\\n\\tlevelMeter position: outerBox topLeft + (2@2).\\n\\touterBox addMorph: levelMeter.\\n\\t^ outerBox\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'dgd 9/19/2003 13:31'!\\nmakeStatusLight\\n\\n\\t| s |\\n\\tstatusLight _ RectangleMorph new extent: 24@19.\\n\\tstatusLight color: Color gray.\\n\\ts _ StringMorph contents: 'On' translated.\\n\\ts position: statusLight center - (s extent // 2).\\n\\tstatusLight addMorph: s.\\n\\t^ statusLight\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'gm 2/28/2003 00:11'!\\nprocessBuffer: buf \\n\\t\\\"Analyze one buffer of data.\\\"\\n\\n\\t| data |\\n\\tdata := displayType = 'signal' \\n\\t\\tifTrue: [buf]\\n\\t\\tifFalse: [fft transformDataFrom: buf startingAt: 1].\\n\\tgraphMorph ifNotNil: \\n\\t\\t\\t[graphMorph\\n\\t\\t\\t\\tdata: data;\\n\\t\\t\\t\\tchanged].\\n\\tsonogramMorph ifNotNil: \\n\\t\\t\\t[data := data collect: [:v | v sqrt].\\t\\\"square root compresses dynamic range\\\"\\n\\t\\t\\tdata /= 400.0.\\n\\t\\t\\tsonogramMorph plotColumn: (data copyFrom: 1 to: data size // 1)]! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 12:49'!\\nremoveAllDisplays\\n\\t\\\"Remove all currently showing displays.\\\"\\n\\n\\tsonogramMorph ifNotNil: [sonogramMorph delete].\\n\\tgraphMorph ifNotNil: [graphMorph delete].\\n\\tsonogramMorph _ graphMorph _ nil.\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:56'!\\nshowSignal\\n\\t\\\"Display the actual signal waveform.\\\"\\n\\n\\tdisplayType _ 'signal'.\\n\\tself removeAllDisplays.\\n\\tgraphMorph _ GraphMorph new.\\n\\tgraphMorph extent: (400 + (2 * graphMorph borderWidth))@128.\\n\\tgraphMorph data: (Array new: 100 withAll: 0).\\n\\tgraphMorph color: (Color r: 0.8 g: 1.0 b: 1.0).\\n\\tself addMorphBack: graphMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:43'!\\nshowSonogram\\n\\t\\\"Display a sonogram showing the frequency spectrum versus time.\\\"\\n\\n\\t| zeros h w |\\n\\tdisplayType _ 'sonogram'.\\n\\tself removeAllDisplays.\\n\\th _ fft n // 2.\\n\\th _ h min: 512 max: 64.\\n\\tw _ 400.\\n\\tsonogramMorph _\\n\\t\\tSonogram new\\n\\t\\t\\textent: w@h\\n\\t\\t\\tminVal: 0.0\\n\\t\\t\\tmaxVal: 1.0\\n\\t\\t\\tscrollDelta: w.\\n\\tzeros _ Array new: sonogramMorph height withAll: 0.\\n\\tsonogramMorph width timesRepeat: [sonogramMorph plotColumn: zeros].\\n\\tself addMorphBack: sonogramMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 15:10'!\\nshowSpectrum\\n\\t\\\"Display the frequency spectrum.\\\"\\n\\n\\tdisplayType _ 'spectrum'.\\n\\tself removeAllDisplays.\\n\\tgraphMorph _ GraphMorph new.\\n\\tgraphMorph extent: ((fft n // 2) + (2 * graphMorph borderWidth))@128.\\n\\tgraphMorph data: (Array new: fft n // 2 withAll: 0).\\n\\tself addMorphBack: graphMorph.\\n\\tself extent: 10@10. \\\"shrink to minimum size\\\"\\n! !\\n\\n!SpectrumAnalyzerMorph methodsFor: 'private' stamp: 'jm 9/8/1999 19:39'!\\nupdateDisplay\\n\\t\\\"Update the display if any data is available.\\\"\\n\\n\\t| buf bufCount |\\n\\tsoundInput bufferCount = 0 ifTrue: [^ self].\\n\\n\\tgraphMorph ifNotNil: [\\n\\t\\t[soundInput bufferCount > 0] whileTrue: [\\n\\t\\t\\t\\\"skip to the most recent buffer\\\"\\n\\t\\t\\tbuf _ soundInput nextBufferOrNil].\\n\\t\\t^ self processBuffer: buf].\\n\\n\\tsonogramMorph ifNotNil: [\\n\\t\\t\\\"at small buffer sizes we have to update the sonogram in\\n\\t\\t batches or we may get behind; shoot for 8 updates/second\\\"\\n\\t\\tbufCount _ (soundInput samplingRate / (8 * soundInput bufferSize)) truncated max: 1.\\n\\t\\t[bufCount > 0 and: [soundInput bufferCount > 0]] whileTrue: [\\n\\t\\t\\tself processBuffer: (soundInput nextBufferOrNil)]].\\n! !\\nPath subclass: #Spline\\n\\tinstanceVariableNames: 'coefficients'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Paths'!\\n!Spline commentStamp: '<historical>' prior: 0!\\nI represent a collection of Points through which a cubic spline curve is fitted.!\\n\\n\\n!Spline methodsFor: 'accessing'!\\ncoefficients\\n\\t\\\"Answer an eight-element Array of Arrays each of which is the length \\n\\tof the receiver. The first four arrays are the values, first, second and \\n\\tthird derivatives, respectively, for the parametric spline in x. The last \\n\\tfour elements are for y.\\\"\\n\\n\\t^coefficients! !\\n\\n\\n!Spline methodsFor: 'displaying'!\\ncomputeCurve\\n\\t\\\"Compute an array for the coefficients.\\\"\\n\\n\\t| length extras |\\n\\tlength _ self size.\\n\\textras _ 0.\\n\\tcoefficients _ Array new: 8.\\n\\t1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].\\n\\t1 to: 5 by: 4 do: \\n\\t\\t[:k | \\n\\t\\t1 to: length do:\\n\\t\\t\\t[:i | (coefficients at: k)\\n\\t\\t\\t\\t\\tat: i put: (k = 1\\n\\t\\t\\t\\t\\t\\tifTrue: [(self at: i) x asFloat]\\n\\t\\t\\t\\t\\t\\tifFalse: [(self at: i) y asFloat])].\\n\\t\\t\\t1 to: extras do: [:i | (coefficients at: k)\\n\\t\\t\\t\\t\\tat: length + i put: ((coefficients at: k)\\n\\t\\t\\t\\t\\t\\tat: i + 1)].\\n\\t\\t\\tself derivs: (coefficients at: k)\\n\\t\\t\\t\\tfirst: (coefficients at: k + 1)\\n\\t\\t\\t\\tsecond: (coefficients at: k + 2)\\n\\t\\t\\t\\tthird: (coefficients at: k + 3)].\\n\\textras > 0 \\n\\t\\tifTrue: [1 to: 8 do: \\n\\t\\t\\t\\t\\t[:i | \\n\\t\\t\\t\\t\\tcoefficients at: i put: ((coefficients at: i)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopyFrom: 2 to: length + 1)]]! !\\n\\n!Spline methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm \\n\\t\\\"Display the receiver, a spline curve, approximated by straight line\\n\\tsegments.\\\"\\n\\n\\t| n line t x y x1 x2 x3 y1 y2 y3 |\\n\\tcollectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].\\n\\tline _ Line new.\\n\\tline form: self form.\\n\\tline beginPoint: \\n\\t\\t(x _ (coefficients at: 1) at: 1) rounded @ (y _ (coefficients at: 5) at: 1) rounded.\\n\\t1 to: (coefficients at: 1) size - 1 do: \\n\\t\\t[:i | \\n\\t\\t\\\"taylor series coefficients\\\"\\n\\t\\tx1 _ (coefficients at: 2) at: i.\\n\\t\\ty1 _ (coefficients at: 6) at: i.\\n\\t\\tx2 _ ((coefficients at: 3) at: i) / 2.0.\\n\\t\\ty2 _ ((coefficients at: 7) at: i) / 2.0.\\n\\t\\tx3 _ ((coefficients at: 4) at: i) / 6.0.\\n\\t\\ty3 _ ((coefficients at: 8) at: i) / 6.0.\\n\\t\\t\\\"guess n\\\"\\n\\t\\tn _ 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)\\n\\t\\t\\t\\t\\t\\t\\tat: i + 1) abs + ((coefficients at: 7)\\n\\t\\t\\t\\t\\t\\t\\tat: i + 1) abs / 100.0) rounded.\\n\\t\\t1 to: n - 1 do: \\n\\t\\t\\t[:j | \\n\\t\\t\\tt _ j asFloat / n.\\n\\t\\t\\tline endPoint: \\n\\t\\t\\t\\t(x3 * t + x2 * t + x1 * t + x) rounded \\n\\t\\t\\t\\t\\t\\t\\t@ (y3 * t + y2 * t + y1 * t + y) rounded.\\n\\t\\t\\tline\\n\\t\\t\\t\\tdisplayOn: aDisplayMedium\\n\\t\\t\\t\\tat: aPoint\\n\\t\\t\\t\\tclippingBox: clipRect\\n\\t\\t\\t\\trule: anInteger\\n\\t\\t\\t\\tfillColor: aForm.\\n\\t\\t\\tline beginPoint: line endPoint].\\n\\t\\tline beginPoint: \\n\\t\\t\\t\\t(x _ (coefficients at: 1) at: i + 1) rounded \\n\\t\\t\\t\\t\\t@ (y _ (coefficients at: 5) at: i + 1) rounded.\\n\\t\\tline\\n\\t\\t\\tdisplayOn: aDisplayMedium\\n\\t\\t\\tat: aPoint\\n\\t\\t\\tclippingBox: clipRect\\n\\t\\t\\trule: anInteger\\n\\t\\t\\tfillColor: aForm]! !\\n\\n!Spline methodsFor: 'displaying'!\\ndisplayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm \\n\\t\\\"Get the scaled and translated path of newKnots.\\\"\\n\\n\\t| newKnots newSpline |\\n\\tnewKnots _ aTransformation applyTo: self.\\n\\tnewSpline _ Spline new.\\n\\tnewKnots do: [:knot | newSpline add: knot].\\n\\tnewSpline form: self form.\\n\\tnewSpline\\n\\t\\tdisplayOn: aDisplayMedium\\n\\t\\tat: 0 @ 0\\n\\t\\tclippingBox: clipRect\\n\\t\\trule: anInteger\\n\\t\\tfillColor: aForm! !\\n\\n\\n!Spline methodsFor: 'private'!\\nderivs: a first: point1 second: point2 third: point3\\n\\t\\\"Compute the first, second and third derivitives (in coefficients) from\\n\\tthe Points in this Path (coefficients at: 1 and coefficients at: 5).\\\"\\n\\n\\t| l v anArray |\\n\\tl _ a size.\\n\\tl < 2 ifTrue: [^self].\\n\\tl > 2\\n\\t ifTrue:\\n\\t\\t[v _ Array new: l.\\n\\t\\t v at: 1 put: 4.0.\\n\\t\\t anArray _ Array new: l.\\n\\t\\t anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))).\\n\\t\\t 2 to: l - 2 do:\\n\\t\\t\\t[:i | \\n\\t\\t\\tv at: i put: (4.0 - (1.0 / (v at: (i - 1)))).\\n\\t\\t\\tanArray\\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: (6.0 * ((a at: i) - ((a at: (i + 1)) * 2.0) + (a at: (i + 2)))\\n\\t\\t\\t\\t\\t\\t- ((anArray at: (i - 1)) / (v at: (i - 1))))].\\n\\t\\t point2 at: (l - 1) put: ((anArray at: (l - 2)) / (v at: (l - 2))).\\n\\t\\t l - 2 to: 2 by: 0-1 do: \\n\\t\\t\\t[:i | \\n\\t\\t\\tpoint2 \\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: ((anArray at: (i - 1)) - (point2 at: (i + 1)) / (v at: (i - 1)))]].\\n\\tpoint2 at: 1 put: (point2 at: l put: 0.0).\\n\\t1 to: l - 1 do:\\n\\t\\t[:i | point1 \\n\\t\\t\\t\\tat: i \\n\\t\\t\\t\\tput: ((a at: (i + 1)) - (a at: i) - \\n\\t\\t\\t\\t\\t\\t((point2 at: i) * 2.0 + (point2 at: (i + 1)) / 6.0)).\\n\\t\\t point3 at: i put: ((point2 at: (i + 1)) - (point2 at: i))]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSpline class\\n\\tinstanceVariableNames: ''!\\n\\n!Spline class methodsFor: 'examples' stamp: '6/8/97 13:55 di'!\\nexample\\n\\t\\\"Designate points on the Path by clicking the red button. Terminate by\\n\\tpressing any other button. A curve will be displayed, through the\\n\\tselected points, using a long black form.\\\"\\n\\n\\t| splineCurve aForm flag|\\n\\taForm _ Form extent: 2@2.\\n\\taForm fillBlack.\\n\\tsplineCurve _ Spline new.\\n\\tsplineCurve form: aForm.\\n\\tflag _ true.\\n\\t[flag] whileTrue:\\n\\t\\t[Sensor waitButton.\\n\\t\\t Sensor redButtonPressed\\n\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[splineCurve add: Sensor waitButton. \\n\\t\\t\\t\\t Sensor waitNoButton.\\n\\t\\t\\t\\t aForm displayOn: Display at: splineCurve last]\\n\\t\\t\\tifFalse: [flag_false]].\\n\\tsplineCurve computeCurve.\\n\\tsplineCurve isEmpty \\n\\t\\tifFalse: [splineCurve displayOn: Display.\\n\\t\\t\\t\\tSensor waitNoButton].\\n \\n\\t\\\"Spline example\\\"! !\\nObject subclass: #SqNumberParser\\n\\tinstanceVariableNames: 'sourceStream base neg integerPart fractionPart exponent scale nDigits lastNonZero requestor failBlock'\\n\\tclassVariableNames: 'BelllerophonBase10'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Numbers'!\\n!SqNumberParser commentStamp: 'nice 4/27/2006 22:38' prior: 0!\\nThis is a class specialized in parsing and building numbers.\\nNumber syntax should follow Smalltalk syntax.\\n\\nIf you have to read foreign number syntax, create a subclass.!\\n\\n\\n!SqNumberParser methodsFor: 'error' stamp: 'nice 4/28/2006 00:20'!\\nexpected: errorString \\n\\trequestor isNil\\n\\t\\tifFalse: [requestor\\n\\t\\t\\t\\tnotify: errorString , ' ->'\\n\\t\\t\\t\\tat: sourceStream position\\n\\t\\t\\t\\tin: sourceStream].\\n\\tself fail! !\\n\\n!SqNumberParser methodsFor: 'error' stamp: 'nice 4/28/2006 00:19'!\\nfail\\n\\tfailBlock isNil ifFalse: [^failBlock value].\\n\\tself error: 'Reading a number failed'! !\\n\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 4/27/2006 22:57'!\\nexponentLetters\\n\\t\\\"answer the list of possible exponents for Numbers.\\n\\tNote: this parser will not honour precision attached to the exponent.\\n\\tdifferent exponent do not lead to different precisions.\\n\\tonly IEEE 754 floating point numbers will be created\\\"\\n\\t\\n\\t^'edq'! !\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 5/1/2006 01:58'!\\nfailBlock: aBlockOrNil\\n\\tfailBlock := aBlockOrNil! !\\n\\n!SqNumberParser methodsFor: 'accessing' stamp: 'nice 5/1/2006 01:59'!\\nrequestor: anObjectOrNil\\n\\trequestor := anObjectOrNil! !\\n\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 5/7/2006 17:33'!\\nmakeFloatFromMantissa: m exponent: k base: aRadix \\n\\t\\\"Convert infinite precision arithmetic into Floating point.\\n\\tThis alogrithm rely on correct IEEE rounding mode\\n\\tbeing implemented in Integer>>asFloat and Fraction>>asFloat\\\"\\n\\n\\t^(k positive\\n\\t\\tifTrue: [m * (aRadix raisedTo: k)]\\n\\t\\tifFalse: [Fraction numerator: m denominator: (aRadix raisedTo: k negated)]) asFloat! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 00:52'!\\nmakeIntegerOrScaledInteger\\n\\t\\\"at this point, there is no digit, nor fractionPart.\\n\\tmaybe it can be a scaled decimal with fraction omitted...\\\"\\n\\t\\n\\tneg\\n\\t\\tifTrue: [integerPart := integerPart negated].\\n\\tself readExponent\\n\\t\\tifTrue: [integerPart := integerPart\\n\\t\\t\\t\\t\\t\\t* (base raisedTo: exponent)]\\n\\t\\tifFalse: [self readScale\\n\\t\\t\\t\\tifTrue: [nil.\\n\\t\\t\\t\\t\\t^ ScaledDecimal newFromNumber: integerPart scale: scale]].\\n\\t^ integerPart! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 01:14'!\\nreadExponent\\n\\t\\\"read the exponent if any (stored in instVar).\\n\\tAnswer true if found, answer false if none.\\n\\tIf exponent letter is not followed by a digit,\\n\\tthis is not considered as an error.\\n\\tExponent are always read in base 10, though i do not see why...\\\"\\n\\t\\n\\t| eneg |\\n\\texponent := 0.\\n\\tsourceStream atEnd\\n\\t\\tifTrue: [^ false].\\n\\t(self exponentLetters includes: sourceStream next)\\n\\t\\tifFalse: [sourceStream skip: -1.\\n\\t\\t\\t^ false].\\n\\teneg := sourceStream peekFor: $-.\\n\\texponent := self\\n\\t\\t\\t\\tnextUnsignedIntegerBase: 10\\n\\t\\t\\t\\tifFail: [sourceStream\\n\\t\\t\\t\\t\\t\\tskip: (eneg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [-2]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [-1]).\\n\\t\\t\\t\\t\\t^ false].\\n\\teneg\\n\\t\\tifTrue: [exponent := exponent negated].\\n\\t^ true! !\\n\\n!SqNumberParser methodsFor: 'parsing-private' stamp: 'nice 4/28/2006 03:08'!\\nreadScale\\n\\t\\\"read the scale if any (stored in instVar).\\n\\tAnswer true if found, answer false if none.\\n\\tIf scale letter is not followed by a digit,\\n\\tthis is not considered as an error.\\n\\tScales are always read in base 10, though i do not see why...\\\"\\n\\t\\n\\tscale := 0.\\n\\tsourceStream atEnd ifTrue: [^ false].\\n\\t('s' includes: sourceStream next)\\n\\t\\tifFalse: [sourceStream skip: -1.\\n\\t\\t\\t^ false].\\n\\tscale := self\\n\\t\\t\\t\\tnextUnsignedIntegerBase: 10\\n\\t\\t\\t\\tifFail: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\t^ false].\\n\\t^ true! !\\n\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/27/2006 23:08'!\\nnextIntegerBase: aRadix\\n\\t\\\"Form an integer with following digits\\\"\\n\\t\\n\\t| isNeg value |\\n\\tisNeg := sourceStream peekFor: $-.\\n\\tvalue := self nextUnsignedIntegerBase: aRadix.\\n\\t^isNeg\\n\\t\\tifTrue: [value negated]\\n\\t\\tifFalse: [value]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 01:12'!\\nnextIntegerBase: aRadix ifFail: aBlock\\n\\t\\\"Form an integer with following digits\\\"\\n\\t\\n\\t| isNeg value |\\n\\tisNeg := sourceStream peekFor: $-.\\n\\tvalue := self nextUnsignedIntegerBase: aRadix ifFail: [^aBlock value].\\n\\t^isNeg\\n\\t\\tifTrue: [value negated]\\n\\t\\tifFalse: [value]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 03:38'!\\nnextNumber\\n\\t\\\"main method for reading a number.\\n\\tThis one can read Float Integer and ScaledDecimal\\\"\\n\\t\\n\\t| numberOfTrailingZeroInIntegerPart numberOfNonZeroFractionDigits mantissa decimalMultiplier decimalFraction value numberOfTrailingZeroInFractionPart |\\n\\t(sourceStream nextMatchAll: 'NaN')\\n\\t\\tifTrue: [^ Float nan].\\n\\tneg := sourceStream peekFor: $-.\\n\\t(sourceStream nextMatchAll: 'Infinity')\\n\\t\\tifTrue: [^ neg\\n\\t\\t\\t\\tifTrue: [Float infinity negated]\\n\\t\\t\\t\\tifFalse: [Float infinity]].\\n\\tintegerPart := self nextUnsignedIntegerBase: base.\\n\\tnumberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.\\n\\t(sourceStream peekFor: $r)\\n\\t\\tifTrue: [\\\"<base>r<integer>\\\"\\n\\t\\t\\t(base := integerPart) < 2\\n\\t\\t\\t\\tifTrue: [^ self expected: 'an integer greater than 1 as valid radix'].\\n\\t\\t\\t(sourceStream peekFor: $-)\\n\\t\\t\\t\\tifTrue: [neg := neg not].\\n\\t\\t\\tintegerPart := self nextUnsignedIntegerBase: base.\\n\\t\\t\\tnumberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].\\n\\t^ (sourceStream peekFor: $.)\\n\\t\\tifTrue: [fractionPart := self\\n\\t\\t\\t\\t\\t\\tnextUnsignedIntegerBase: base\\n\\t\\t\\t\\t\\t\\tifFail: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\t\\t\\t^ neg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [integerPart negated]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [integerPart]].\\n\\t\\t\\tnumberOfNonZeroFractionDigits := lastNonZero.\\n\\t\\t\\tnumberOfTrailingZeroInFractionPart := nDigits - lastNonZero.\\n\\t\\t\\tself readExponent\\n\\t\\t\\t\\tifFalse: [self readScale\\n\\t\\t\\t\\t\\t\\tifTrue: [decimalMultiplier := base raisedTo: numberOfNonZeroFractionDigits.\\n\\t\\t\\t\\t\\t\\t\\tdecimalFraction := integerPart * decimalMultiplier + fractionPart / decimalMultiplier.\\n\\t\\t\\t\\t\\t\\t\\tneg\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [decimalFraction := decimalFraction negated].\\n\\t\\t\\t\\t\\t\\t\\t^ ScaledDecimal newFromNumber: decimalFraction scale: scale]].\\n\\t\\t\\tfractionPart isZero\\n\\t\\t\\t\\tifTrue: [mantissa := integerPart\\n\\t\\t\\t\\t\\t\\t\\t\\t// (base raisedTo: numberOfTrailingZeroInIntegerPart).\\n\\t\\t\\t\\t\\texponent := exponent + numberOfTrailingZeroInIntegerPart]\\n\\t\\t\\t\\tifFalse: [mantissa := integerPart\\n\\t\\t\\t\\t\\t\\t\\t\\t* (base raisedTo: numberOfNonZeroFractionDigits) + (fractionPart // (base raisedTo: numberOfTrailingZeroInFractionPart)).\\n\\t\\t\\t\\t\\texponent := exponent - numberOfNonZeroFractionDigits].\\n\\t\\t\\t\\\"very naive algorithm\\\"\\n\\t\\t\\tvalue := self makeFloatFromMantissa: mantissa exponent: exponent base: base.\\n\\t\\t\\t^ neg\\n\\t\\t\\t\\tifTrue: [value isZero\\n\\t\\t\\t\\t\\t\\tifTrue: [Float negativeZero]\\n\\t\\t\\t\\t\\t\\tifFalse: [value negated]]\\n\\t\\t\\t\\tifFalse: [value]]\\n\\t\\tifFalse: [self makeIntegerOrScaledInteger]! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 01:10'!\\nnextUnsignedIntegerBase: aRadix \\n\\t\\\"Form an unsigned integer with incoming digits from sourceStream.\\n\\tCount the number of digits and the lastNonZero digit and store int in\\n\\tinstVar \\\"\\n\\t\\n\\t^ self\\n\\t\\tnextUnsignedIntegerBase: aRadix\\n\\t\\tifFail: [self expected: 'a digit between 0 and 9']! !\\n\\n!SqNumberParser methodsFor: 'parsing-public' stamp: 'nice 4/28/2006 03:14'!\\nnextUnsignedIntegerBase: aRadix ifFail: errorBlock\\n\\t\\\"Form an unsigned integer with incoming digits from sourceStream.\\n\\tCount the number of digits and the lastNonZero digit and store int in instVar\\\"\\n\\t\\n\\t| value digit |\\n\\tvalue := 0.\\n\\tnDigits := 0.\\n\\tlastNonZero := 0.\\n\\t[sourceStream atEnd\\n\\t\\tor: [digit := sourceStream next digitValue.\\n\\t\\t\\t(digit < 0\\n\\t\\t\\t\\t\\tor: [digit >= aRadix])\\n\\t\\t\\t\\tand: [sourceStream skip: -1.\\n\\t\\t\\t\\t\\ttrue]]]\\n\\t\\twhileFalse: [nDigits := nDigits + 1.\\n\\t\\t\\tdigit isZero\\n\\t\\t\\t\\tifFalse: [lastNonZero := nDigits].\\n\\t\\t\\tvalue := value * aRadix + digit].\\n\\tnDigits = 0\\n\\t\\tifTrue: [errorBlock value].\\n\\t^value! !\\n\\n\\n!SqNumberParser methodsFor: 'initialize-release' stamp: 'nice 5/1/2006 00:41'!\\non: aStringOrStream\\n\\tsourceStream := aStringOrStream isString\\n\\t\\tifTrue: [ReadStream on: aStringOrStream]\\n\\t\\tifFalse: [aStringOrStream].\\n\\tbase := 10.\\n\\tneg := false.\\n\\tintegerPart := fractionPart := exponent := scale := 0.\\n\\trequestor := failBlock := nil.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqNumberParser class\\n\\tinstanceVariableNames: ''!\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 00:45'!\\non: aStringOrStream\\n\\t^self new on: aStringOrStream! !\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 02:02'!\\nparse: aStringOrStream \\n\\t^(self new)\\n\\t\\ton: aStringOrStream;\\n\\t\\tnextNumber! !\\n\\n!SqNumberParser class methodsFor: 'instance creation' stamp: 'nice 5/1/2006 02:02'!\\nparse: aStringOrStream onError: failBlock \\n\\t^(self new)\\n\\t\\ton: aStringOrStream;\\n\\t\\tfailBlock: failBlock;\\n\\t\\tnextNumber! !\\nClassTestCase subclass: #SqNumberParserTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Numbers'!\\n!SqNumberParserTest commentStamp: 'nice 5/7/2006 17:54' prior: 0!\\nProvide tests for new clas aimed at parsing numbers.\\n\\nIt duplicates NumberParsingTest, with few more tests.!\\n\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatFromStreamAsNumber\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs := '10r-12.3456' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -12.3456 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456e2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456e2e2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs upToEnd = 'e2'.\\n\\n\\trs := '10r-12.3456d2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '10r-12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '-12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: -1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '12.3456q2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1234.56 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '12.3456z2' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 12.3456 = aFloat.\\n\\tself assert: rs upToEnd = 'z2'.\\n! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatFromStreamWithExponent\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs aFloat |\\n\\trs := '1.0e-14' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs atEnd.\\n\\n\\trs := '1.0e-14 1' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = ' 1'.\\n\\n\\trs := '1.0e-14eee' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e-14 = aFloat.\\n\\tself assert: rs upToEnd = 'eee'.\\n\\n\\trs := '1.0e14e10' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0e14 = aFloat.\\n\\tself assert: rs upToEnd = 'e10'.\\n\\n\\trs := '1.0e+14e' readStream. \\\"Plus sign is not parseable\\\"\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e+14e'.\\n\\n\\trs := '1.0e' readStream.\\n\\taFloat := SqNumberParser parse: rs.\\n\\tself assert: 1.0 = aFloat.\\n\\tself assert: rs upToEnd = 'e'.! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/1/2006 00:40'!\\ntestFloatPrintString\\n\\t\\\"self debug: #testFloatPrintString\\\"\\n\\t\\n\\t| f r |\\n\\tf := Float basicNew: 2.\\n\\tr := Random new seed: 1234567.\\n\\t100\\n\\t\\ttimesRepeat: [f basicAt: 1 put: (r nextInt: 16r100000000)- 1.\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].\\n\\t\\\"test big num near infinity\\\"\\n\\t10\\n\\t\\ttimesRepeat: [f basicAt: 1 put: 16r7FE00000 + ((r nextInt: 16r100000) - 1).\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].\\n\\t\\\"test infinitesimal (gradual underflow)\\\"\\n\\t10\\n\\t\\ttimesRepeat: [f basicAt: 1 put: 0 + ((r nextInt: 16r100000) - 1).\\n\\t\\t\\tf basicAt: 2 put: (r nextInt: 16r100000000) - 1.\\n\\t\\t\\t#(2 8 10 16)\\n\\t\\t\\t\\tdo: [:base | | str |\\n\\t\\t\\t\\t\\t\\tstr := (String new: 64) writeStream.\\n\\t\\t\\t\\t\\t\\tf negative ifTrue: [str nextPut: $-].\\n\\t\\t\\t\\t\\t\\tstr print: base; nextPut: $r.\\n\\t\\t\\t\\t\\t\\tf absPrintExactlyOn: str base: base.\\n\\t\\t\\t\\t\\t\\tself assert: (SqNumberParser parse: str contents) = f]].! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/1/2006 00:40'!\\ntestFloatReadError\\n\\t\\\"This covers parsing in Number>>readFrom:\\\"\\n\\n\\t| rs num |\\n\\trs := '1e' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 'e'.\\n\\t\\n\\trs := '1s' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: rs upToEnd = 's'.\\n\\n\\trs := '1.' readStream.\\n\\tnum := SqNumberParser parse: rs.\\n\\tself assert: 1 = num.\\n\\tself assert: num isInteger.\\n\\tself assert: rs upToEnd = '.'.\\n\\t\\n\\trs := '' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := 'foo' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\n\\trs := 'radix' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '.e0' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '-.e0' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.\\n\\t\\n\\trs := '--1' readStream.\\n\\tself should: [SqNumberParser parse: rs] raise: Error.! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Float' stamp: 'nice 5/7/2006 17:46'!\\ntestFloatReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber := '2r1.0101e9' asNumber.\\n\\tself assert: 672.0 = aNumber.\\n\\tself assert: (SqNumberParser parse: '2r1.0101e9') = (1.3125 * (2 raisedTo: 9)).\\n\\trs := ReadStream on: '2r1.0101e9e9'.\\n\\tself assert: (SqNumberParser parse: rs) = 672.0.\\n\\tself assert: rs upToEnd = 'e9'\\n! !\\n\\n\\n!SqNumberParserTest methodsFor: 'tests - Integer' stamp: 'nice 5/7/2006 17:46'!\\ntestIntegerReadFrom\\n\\t\\\"Ensure remaining characters in a stream are not lost when parsing an integer.\\\"\\n\\n\\t| rs i s |\\n\\trs := ReadStream on: '123s could be confused with a ScaledDecimal'.\\n\\ti := SqNumberParser parse: rs.\\n\\tself assert: i == 123.\\n\\ts := rs upToEnd.\\n\\tself assert: 's could be confused with a ScaledDecimal' = s.\\n\\trs := ReadStream on: '123.s could be confused with a ScaledDecimal'.\\n\\ti := SqNumberParser parse: rs.\\n\\tself assert: i == 123.\\n\\ts := rs upToEnd.\\n\\tself assert: '.s could be confused with a ScaledDecimal' = s\\n! !\\n\\n!SqNumberParserTest methodsFor: 'tests - Integer' stamp: 'nice 5/7/2006 17:46'!\\ntestIntegerReadWithRadix\\n\\t\\\"This covers parsing in Number>>readFrom:\\n\\tNote: In most Smalltalk dialects, the radix notation is not used for numbers\\n\\twith exponents. In Squeak, a string with radix and exponent can be parsed,\\n\\tand the exponent is always treated as base 10 (not the base indicated in the\\n\\tradix prefix). I am not sure if this is a feature, a bug, or both, but the\\n\\tSqueak behavior is documented in this test. -dtl\\\"\\n\\n\\t| aNumber rs |\\n\\taNumber := '2r1e26' asNumber.\\n\\tself assert: 67108864 = aNumber.\\n\\tself assert: (SqNumberParser parse: '2r1e26') = (2 raisedTo: 26).\\n\\trs := '2r1e26eee' readStream.\\n\\tself assert: (SqNumberParser parse: rs) = 67108864.\\n\\tself assert: rs upToEnd = 'eee'\\n! !\\nObject subclass: #SqueakPage\\n\\tinstanceVariableNames: 'url title comment thumbnail contentsMorph creationTime creationAuthor lastChangeTime lastChangeAuthor policy dirty'\\n\\tclassVariableNames: 'MaxThumbnailWidthOrHeight RecentMaxNum RecentStem'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n!SqueakPage commentStamp: '<historical>' prior: 0!\\nA SqueakPage is holder for a page of morphs that live on the disk or on a server.\\nA URLMorph is a thumbnail sized stand-in for the page. Clicking on it gets the page.\\nAn ObjectOut is a fake object that stands for an object that is out on the disk. (Like ObjectTracer or ObjectViewer.)\\nA MorphObjectOut is a subclass that stands for a Morph that is out on the disk.\\n\\nTo find out how to make the pages of any BookMorph go out to the disk (or a server), see \\thttp://minnow.cc.gatech.edu/SqueakDoc.1 then go to 'SqueakPages'.\\n\\nA SqueakPage is always in-memory. Its contentsMorph will be 'become-ed' to a MorphObjectOut tombstone when it goes out. (A page may or may not be in the cache. First put it in, then ask it for the data.) Sending any message to the contentsMorph triggers the fetch. Many URLMorphs may hold onto one page. A page has a thumbnail. A URLMorph points at its page object.\\n\\nStates of a SqueakPage, and the transitions to another state:\\n1) have a url as a string. Then: (URLMorph grabURL: 'file://Ted''s/books/tryThis/p1'). \\n\\tDrop it into any morph.\\n2) have a URLMorph, with page==nil. Click it. (makes an empty page, installs \\n\\tit in the global page cache)\\n3) have a URLMorph with a SqueakPage, with contentsMorph==nil, \\n\\tbut page is not in the cache (this is a rare case). ask page contentsMorph.\\n4) OUT: have a URLMorph with a SqueakPage, with contentsMorph being a MorphObjectOut, \\n\\tand its page is in the cache. Sending the contentsMorph any message brings it in and\\n\\tbecomes it to the morph. (fix up morph's pointer to the page.)\\n5) Totally IN: a morph, owned by a SqueakPage, has a page in the cache. \\n\\tThe morph is clean. \\n\\tWhenever someone triggers a purge (when?), contentsMorph is becomed\\n\\tto a MorphObjectOut. (go to 4)\\n\\tCausing the morph to execute layoutChanged marks the morph as dirty.\\n\\t(morph's property #pageDirty is set to true) (go to 6)\\n6) Totally IN and dirty. \\n\\tWhenever any other page is fetched from the disk or the net, all other \\n\\tdirty pages are written and marked clean. (go to 5)\\n\\nNote that the entire tree of submorphs goes out -- hundreds of objects. Bringing the object back in brings in the SqueakPage, installs it in the cache. Classes other than PasteUpMorph can easily be made to send their contents out if there is any need.\\n\\nNote that every book is now automatically a WebBook. We simply give a page a url and tell it to purge.\\n\\nurl\\t\\ta string\\ntitle\\t\\t\\ncomment\\t\\t\\nthumbnail\\t\\t\\ncontentsMorph\\t\\t(1) a pasteUpMorph with other morphs in it.\\n\\t\\t\\t\\t\\t(2) a MorphObjectOut. Sending any message brings it in. \\n\\t\\t\\t\\t\\t(3) nil if the page has never been in this image.\\ncreationTime\\t\\t\\ncreationAuthor\\t\\t\\nlastChangeTime\\t\\t\\nlastChangeAuthor \\npolicy\\t\\t#alwaysWrite, #neverWrite, #ask. (cache can override with a global policy)\\n\\t\\t\\t(Explicit writing by user has policy #neverWrite)\\ndirty \\t\\t(Morph>>layoutChanged sends changed: #SqueakPage. If policy==#check, \\n\\t\\t\\t\\tthen the page sets dirty_true.)\\n\\t\\t\\t(If policy==#alwaysWrite, then set dirty when the page is retrieved from the cache.)\\n\\nClass MorphObjectOut has an instance variable called page.\\nAll messages to an MorphObjectOut cause it to be brought in. Except the messages needed to write the MorphObjectOut on the disk as part of a parent's being sent out. (size, class, instSize, instVar:at:. Can rename these and call from its own version of the writing routine.)\\n\\tTo purge, go through the clean pages, and any that have world not equal to this world, entomb them. \\n\\t(If an object in the subtree is held by an object outside the tree, it will remain, And will be duplicated when the tree comes back in. This is a problem already in normal uses of SmartRefStream.)\\n\\n\\n!\\n\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/5/1999 16:47'!\\nasMorph\\n\\t^ self fetchContents! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 13:47'!\\ncomment\\n\\n\\tcomment ifNil: [^ ''] ifNotNil: [^ comment].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 18:12'!\\ncomment: aString\\n\\n\\taString isEmpty\\n\\t\\tifTrue: [comment _ nil]\\n\\t\\tifFalse: [comment _ aString].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/2/1998 11:27'!\\ncontentsMorph\\n\\t\\\"Return what it is now. If the morph is out on the disk, return nil. Use fetchContents to get the data for sure.\\\"\\n\\n\\t^ contentsMorph\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 11/11/1998 12:54'!\\ncontentsMorph: aPasteUpMorph\\n\\n\\tcontentsMorph _ aPasteUpMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/23/1999 14:39'!\\ncopyForSaving\\n\\t\\\"Make a copy and configure me to be put out on the disk. When it is brought in and touched, it will turn into the object at the url.\\\"\\n\\n\\t| forDisk holder |\\n\\tforDisk _ self clone.\\n\\tholder _ MorphObjectOut new xxxSetUrl: url page: forDisk.\\n\\tforDisk contentsMorph: holder.\\n\\t^ holder\\t\\t\\\"directly representing the object\\\"! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/30/1998 15:08'!\\nfetchContents\\n\\t\\\"Make every effort to get contentsMorph.\\\"\\n\\n\\tself isContentsInMemory ifTrue: [^ contentsMorph].\\n\\t^ self fetchInformIfError! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'ar 4/10/2005 18:52'!\\nfetchContentsIfAbsent: failBlock\\n\\t\\\"Make every effort to get contentsMorph. Assume I am in the cache already.\\\"\\n\\t| strm page temp temp2 |\\n\\tSqueakPageCache write.\\t\\t\\\"sorry about the pause\\\"\\n\\tCursor wait showWhile: [\\n\\t\\tstrm _ (ServerFile new fullPath: url) asStream].\\n\\tstrm isString ifTrue: [^ failBlock value].\\t\\t\\n\\tpage _ strm fileInObjectAndCode.\\n\\tpage isMorph ifTrue: [contentsMorph _ page].\\t\\\"may be a bare morph\\\"\\n\\t\\\"copy over the state\\\"\\n\\ttemp _ url.\\n\\ttemp2 _ policy.\\n\\tself copyAddedStateFrom: page.\\n\\turl _ temp.\\t\\\"don't care what it says\\\"\\n\\ttemp2 ifNotNil: [policy _ temp2].\\t\\t\\\"use mine\\\"\\n\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\tself dirty: false.\\n\\t^ contentsMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'ar 4/10/2005 18:52'!\\nfetchInformIfError\\n\\t\\\"Make every effort to get contentsMorph. Put up a good notice if can't get it. Assume page is in the cache already. Overwrite the contentsMorph no matter what.\\\"\\n\\t| strm page temp temp2 |\\n\\n\\tSqueakPageCache write.\\t\\t\\\"sorry about the pause\\\"\\n\\tCursor wait showWhile: [\\n\\t\\tstrm _ (ServerFile new fullPath: url) asStream].\\n\\tstrm isString ifTrue: [self inform: 'Sorry, ',strm. ^ nil].\\t\\\"<<<<< Note Diff\\\"\\n\\t(url beginsWith: 'file:') ifTrue: [Transcript show: 'Fetching ', url; cr].\\t\\n\\tpage _ strm fileInObjectAndCode.\\n\\tpage isMorph \\n\\t\\tifTrue: [contentsMorph _ page]\\t\\\"may be a bare morph\\\"\\n\\t\\tifFalse: [\\\"copy over the state\\\"\\n\\t\\t\\ttemp _ url.\\n\\t\\t\\ttemp2 _ policy.\\n\\t\\t\\tself copyFrom: page.\\t\\\"including contentsMorph\\\"\\n\\t\\t\\turl _ temp.\\t\\\"I know best!!\\\"\\n\\t\\t\\ttemp2 ifNotNil: [policy _ temp2]].\\t\\t\\\"use mine\\\"\\n\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\tcontentsMorph setProperty: #SqueakPage toValue: self.\\n\\tself dirty: false.\\n\\t^ contentsMorph! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 10/30/1998 15:08'!\\nisContentsInMemory\\n\\t\\\"Is my contentsMorph in memory, or is it an ObjectOut tombstone? Be careful not to send it any message.\\\"\\n\\n\\t^ (contentsMorph xxxClass inheritsFrom: Object) and: [(contentsMorph == nil) not]! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 12/4/1998 01:00'!\\nlastChangeTime\\n\\t^ lastChangeTime! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 2/24/1999 12:06'!\\nsaveMorph: aMorph author: authorString\\n\\t\\\"Save the given morph as this page's contents. Update its thumbnail and inform references to this URL that the page has changed.\\\"\\n\\t\\\"Details: updateThumbnail releases the cached state of the saved page contents after computing the thumbnail.\\\"\\n\\n\\t| n |\\n\\tcontentsMorph _ aMorph.\\n\\tn _ aMorph knownName.\\n\\tn ifNotNil: [self title: n].\\n\\tcreationAuthor ifNil: [\\n\\t\\tcreationAuthor _ authorString.\\n\\t\\tcreationTime _ Time totalSeconds].\\n\\\"\\tlastChangeAuthor _ authorString.\\n\\tlastChangeTime _ Time totalSeconds.\\tdo it when actually write\\\"\\n\\tself computeThumbnail.\\n\\tself postChangeNotification.\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 17:45'!\\nthumbnail\\n\\n\\t^ thumbnail\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 13:47'!\\ntitle\\n\\n\\ttitle ifNil: [^ ''] ifNotNil: [^ title].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'jm 6/16/1998 18:12'!\\ntitle: aString\\n\\n\\taString isEmpty\\n\\t\\tifTrue: [title _ nil]\\n\\t\\tifFalse: [title _ aString].\\n! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 11/4/1998 20:34'!\\nurl\\n\\n\\t^ url! !\\n\\n!SqueakPage methodsFor: 'accessing' stamp: 'tk 1/14/1999 23:50'!\\nurl: aString\\n\\n\\t| sd |\\n\\taString isEmpty ifTrue: [url _ nil. ^ self].\\n\\n\\t\\\"Expand ./ and store as an absolute url\\\"\\n\\tsd _ ServerFile new.\\n\\tsd fullPath: aString.\\n\\turl _ sd realUrl.! !\\n\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 9/30/1998 22:40'!\\ndirty: aBool\\n\\tdirty _ aBool! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 10/8/1998 13:18'!\\npolicy\\n\\t^ policy! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 9/30/1998 22:39'!\\npolicy: aSymbol\\n\\tpolicy _ aSymbol! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'ar 3/17/2001 23:36'!\\nprePurge\\n\\t\\\"Return self if ready to be purged, or nil if not\\\"\\n\\n\\tself isContentsInMemory ifFalse: [^ nil].\\n\\tcontentsMorph ifNil: [^ nil]. \\\"out already\\\"\\n\\turl ifNil: [^ nil].\\t\\\"just to be safe\\\"\\n\\t^ (World ~~ nil and: [contentsMorph world == World]) \\n\\t\\tifTrue: [nil \\\"showing now\\\"] ifFalse: [self]! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 12/16/1998 08:24'!\\npurge\\n\\t\\\"Replace my morph with a tombstone, if I am not in a world that is being shown.\\\"\\n\\n\\t(self prePurge) ifNotNil: [\\n\\t\\tcontentsMorph become: (MorphObjectOut new xxxSetUrl: url page: self)].\\n\\t\\t\\\"Simple, isn't it!!\\\"! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'tk 1/23/1999 13:19'!\\nurlNoOverwrite: suggested\\n\\t\\\"Look in the directory. If there is a file of this name, create a new name. Keep track of highest numbers used as a hint.\\\"\\n\\n\\t| dir ll stem num local trial suffix |\\n\\t(suggested endsWith: '.sp') ifTrue: [suffix _ '.sp'].\\n\\t(suggested endsWith: '.bo') ifTrue: [suffix _ '.bo'].\\n\\tsuffix ifNil: [self error: 'unknown suffix'].\\n\\tdir _ ServerFile new fullPath: suggested.\\n\\t(dir includesKey: dir fileName) ifFalse: [^ url _ suggested].\\n\\t\\\"File already exists!! Create a new name\\\"\\n\\t\\\"Find the stem file name\\\"\\n\\tstem _ SqueakPage stemUrl: suggested.\\n\\tnum _ stem = RecentStem ifTrue: [RecentMaxNum+1] ifFalse: [1].\\n\\n\\tlocal _ dir fileName.\\t\\\"ugh, take stem again...\\\"\\n\\tll _ local findLast: [:char | char == $.].\\n\\tll = 0 ifFalse: [local _ local copyFrom: 1 to: ll-1].\\t\\\"remove .sp\\\"\\n\\tlocal _ (local splitInteger) at: 1.\\t\\t\\\"remove trailing number\\\"\\n\\tlocal last == $x ifFalse: [local _ local , 'x'].\\n\\t[trial _ local, num printString, suffix.\\n\\t\\tdir includesKey: trial] whileTrue: [num _ num + 1].\\n\\tRecentStem _ stem. RecentMaxNum _ num.\\n\\t^ url _ stem, 'x', num printString, suffix! !\\n\\n!SqueakPage methodsFor: 'saving' stamp: 'RAA 8/30/2000 11:43'!\\nwrite\\n\\t\\\"Decide whether to write this page on the disk.\\\"\\n\\t| sf remoteFile |\\n\\tpolicy == #neverWrite ifTrue: [^ self].\\n\\t\\t\\\"demo mode, or write only when user explicitly orders it\\\"\\n\\n\\t\\\"All other policies do write: #now\\\"\\n\\tcontentsMorph ifNil: [^ self].\\n\\tdirty _ dirty | ((contentsMorph valueOfProperty: #pageDirty) == true).\\n\\t\\t\\\"set by layoutChanged\\\"\\n\\tdirty == true ifTrue: [ \\n\\t\\tsf _ ServerDirectory new fullPath: url.\\n\\t\\t\\\"check for shared password\\\"\\n\\t\\t\\\"contentsMorph allMorphsDo: [:m | m prepareToBeSaved].\\n\\t\\t\\t\\tdone in objectToStoreOnDataStream\\\"\\n\\t\\tlastChangeAuthor _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\t\\tlastChangeTime _ Time totalSeconds.\\n\\t\\tCursor wait showWhile: [\\n\\t\\t\\tremoteFile _ sf fileNamed: url.\\t\\\"no notification when overwriting\\\"\\n\\t\\t\\tremoteFile dataIsValid.\\n\\t\\t\\tremoteFile fileOutClass: nil andObject: self.\\n\\t\\t\\t\\\"remoteFile close\\\"].\\n\\t\\tcontentsMorph setProperty: #pageDirty toValue: nil.\\n\\t\\tdirty _ false].! !\\n\\n\\n!SqueakPage methodsFor: 'private' stamp: 'tk 2/25/1999 09:13'!\\ncomputeThumbnail\\n\\t\\\"Make a thumbnail from my morph.\\\"\\n\\n\\t(contentsMorph isKindOf: PasteUpMorph) \\n\\t\\tifTrue: [thumbnail _ contentsMorph smallThumbnailForPageSorter]\\n\\t\\tifFalse: [self updateThumbnail]! !\\n\\n!SqueakPage methodsFor: 'private' stamp: 'tk 6/24/1999 11:42'!\\npostChangeNotification\\n\\t\\\"Inform all thumbnails and books that this page has been updated.\\\"\\n\\n\\tURLMorph allSubInstancesDo: [:m | m pageHasChanged: self].\\n! !\\n\\n!SqueakPage methodsFor: 'private' stamp: 'jm 6/18/1998 11:31'!\\nupdateThumbnail\\n\\t\\\"Update my thumbnail from my morph.\\\"\\n\\n\\t| f scale scaleX scaleY shrunkF |\\n\\tcontentsMorph ifNil: [thumbnail _ nil. ^ self].\\n\\tf _ contentsMorph imageForm.\\n\\tscaleX _ MaxThumbnailWidthOrHeight asFloat / f height.\\n\\tscaleY _ MaxThumbnailWidthOrHeight asFloat/ f width.\\n\\tscale _ scaleX min: scaleY. \\\"choose scale that maintains aspect ratio\\\"\\n\\tshrunkF _ (f magnify: f boundingBox by: scale@scale smoothing: 2).\\n\\tthumbnail _ Form extent: shrunkF extent depth: 8. \\\"force depth to be 8\\\"\\n\\tshrunkF displayOn: thumbnail.\\n\\tcontentsMorph allMorphsDo: [:m | m releaseCachedState].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqueakPage class\\n\\tinstanceVariableNames: ''!\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'jm 6/18/1998 11:15'!\\ninitialize\\n\\t\\\"SqueakPage initialize\\\"\\n\\n\\tMaxThumbnailWidthOrHeight _ 60.\\n! !\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'sw 7/6/1998 11:49'!\\nnewURLAndPageFor: aMorph\\n\\t\\\"Create a new SqueakPage whose contents is the given morph. Assign a URL for that page, record it in the page cache, and answer its URL.\\\"\\n\\n\\t| pg newURL stamp |\\n\\tpg _ self new.\\n\\tstamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\n\\tpg saveMorph: aMorph author: stamp.\\n\\tnewURL _ SqueakPageCache generateURL.\\n\\tSqueakPageCache atURL: newURL put: pg.\\n\\t^ newURL \\n! !\\n\\n!SqueakPage class methodsFor: 'as yet unclassified' stamp: 'tk 1/15/1999 08:13'!\\nstemUrl: aUrlString\\n\\t\\\"Peel off the 'x5.sp' or '.bo' from the end of a url of a SqueakPage or a BookMorph index file\\\"\\n\\n\\t| ll aUrl |\\n\\tll _ aUrlString findLast: [:char | char == $.].\\n\\tll = 0 \\n\\t\\tifTrue: [aUrl _ aUrlString]\\n\\t\\tifFalse: [aUrl _ aUrlString copyFrom: 1 to: ll-1].\\t\\\"remove .sp\\\"\\n\\taUrl _ (aUrl stemAndNumericSuffix) at: 1.\\n\\t\\t\\t\\\"remove trailing number\\\"\\n\\taUrl size = 0 ifTrue: [^ aUrl].\\t\\\"empty\\\"\\n\\t[aUrl last == $x] whileTrue: [aUrl _ aUrl allButLast].\\n\\t^ aUrl! !\\nObject subclass: #SqueakPageCache\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'GlobalPolicy PageCache'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-SqueakPage'!\\n!SqueakPageCache commentStamp: '<historical>' prior: 0!\\nA global cache of web pages known to this Squeak image. Since there is a single, global page cache, it is implemented entirely as class methods.\\n\\nOnce a page has an entry, keep it. (url string -> A SqueakPage) The SqueakPage has a thumbnail and other info, but may not have the contentsMorph. The morph is purged when space is needed, and fetched from the server as needed.\\n\\nSee SqueakPage's comment for the stages of in/out.!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSqueakPageCache class\\n\\tinstanceVariableNames: ''!\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'jm 6/25/1998 11:06'!\\nallURLs\\n\\t\\\"Answer a collection of URLs for all pages in the cache.\\\"\\n\\n\\t^ PageCache keys\\n\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/2/1998 12:07'!\\natURL: aURLString\\n\\t\\\"Answer the page corresponding to this URL. Evaluate the given block if there is no entry for the given URL.\\\"\\n\\n\\t| pg |\\n\\t^ PageCache at: aURLString ifAbsent: [\\n\\t\\tpg _ SqueakPage new.\\n\\t\\t\\\"stamp _ Utilities authorInitialsPerSe ifNil: ['*'].\\\"\\n\\t\\t\\\"pg author: stamp.\\\"\\n\\t\\t\\\"Need to deal with inst vars if we turn out to be new!!\\\"\\n\\t\\t\\\"pg url: aURLString. \\tdone by atURL:put:\\\"\\n\\t\\tself atURL: aURLString put: pg.\\n\\t\\tpg]\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/2/1998 12:06'!\\natURL: aURLString ifAbsent: failBlock\\n\\t\\\"Answer the page corresponding to this URL. Evaluate the given block if there is no entry for the given URL.\\\"\\n\\n\\tself halt. \\\"use atURL:\\\"\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/20/1998 15:51'!\\natURL: aURLString oldPage: aPage\\n\\t\\\"Bring in page and return the object. First try looking up my url in the pageCache. Then try the page (and install it, under its url). Then start from scratch with the url.\\\"\\n\\n\\t| myPage |\\n\\t(myPage _ PageCache at: aURLString ifAbsent: [nil]) ifNotNil: [\\n\\t\\t^ myPage].\\n\\taPage url: aURLString.\\t\\\"for consistancy\\\"\\n\\tPageCache at: aPage url put: aPage.\\n\\t^ aPage! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 12/8/1998 21:51'!\\natURL: aURLString put: aSqueakPage\\n\\t\\\"Store the given page in the cache entry for the given URL.\\\"\\n\\n\\taSqueakPage url: aURLString.\\n\\taSqueakPage contentsMorph isInMemory ifTrue: [\\n\\t\\taSqueakPage contentsMorph ifNotNil: [\\n\\t\\t\\taSqueakPage contentsMorph setProperty: #SqueakPage \\n\\t\\t\\t\\ttoValue: aSqueakPage]].\\n\\tPageCache at: aURLString put: aSqueakPage.\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/30/1998 15:08'!\\ndoPagesInMemory: aBlock\\n\\t\\\"Evaluate aBlock for each page whose contentsMorph is in-memory. Don't add or remove pages while in this loop.\\\"\\n\\n\\tPageCache do: [:sqkPage |\\n\\t\\tsqkPage isContentsInMemory ifTrue: [aBlock value: sqkPage]].! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 11/24/1998 14:52'!\\ngenerateURL\\n\\t\\\"Generate an unused URL for an in-memory page.\\\"\\n\\t\\\"SqueakPageCache generateURL\\\"\\n\\n\\t| sd |\\n\\tsd _ ServerFile new on: 'file:./'.\\n\\tsd fileName: 'page1.sp'.\\n\\t^ SqueakPage new urlNoOverwrite: sd pathForFile\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/1/1998 13:02'!\\nincludesMorph: aPasteUp\\n\\n\\tPageCache do: [:squeakPage |\\n\\t\\tsqueakPage contentsMorph == aPasteUp ifTrue: [^ true]].\\n\\t^ false! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/20/1998 15:11'!\\npageCache\\n\\n\\t^ PageCache! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/1/1998 13:04'!\\npageForMorph: aPasteUp\\n\\n\\tPageCache do: [:squeakPage |\\n\\t\\tsqueakPage contentsMorph == aPasteUp ifTrue: [^ squeakPage]].\\n\\t^ nil! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 12/16/1998 08:30'!\\npurge\\n\\t\\\"Replace morphs with tombstones in all pages that are clean and not being shown. Write any dirty ones first, if allowed to.\\\"\\n\\n\\t| list |\\n\\tlist _ OrderedCollection new.\\n\\tGlobalPolicy == #neverWrite \\n\\t\\tifTrue: [PageCache doPagesInMemory: [:aPage | list add: aPage prePurge]]\\n\\t\\t\\t\\\"Writing only done by user's command\\\"\\n\\t\\tifFalse: [\\n\\t\\t\\tPageCache doPagesInMemory: [:aPage | aPage write\\n\\t\\t\\t\\t\\t list add: aPage prePurge]].\\n\\tlist _ list select: [:each | each notNil].\\n\\t\\\"do bulk become:\\\"\\n\\t(list collect: [:each | each contentsMorph])\\n\\t\\telementsExchangeIdentityWith:\\n\\t\\t\\t(list collect: [:pg | MorphObjectOut new xxxSetUrl: pg url page: pg])\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/21/1998 13:28'!\\npurge: megs\\n\\t\\\"Replace morphs with tombstones in all pages that are clean and not being shown. Do this until megs of new memory have been recovered. Write any dirty ones first, if allowed to.\\\"\\n\\n\\t| goal |\\n\\tgoal _ Smalltalk garbageCollect + (megs * 1000000) asInteger.\\n\\tPageCache doPagesInMemory: [:aPage | \\n\\t\\tGlobalPolicy == #neverWrite ifFalse: [aPage write].\\n\\t\\taPage purge.\\n\\t\\tSmalltalk garbageCollect > goal ifTrue: [^ true]].\\t\\\"got enough\\\"\\n\\t^ false\\t\\\"caller may want to tell the user to write out more pages\\\"! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'jm 6/16/1998 18:12'!\\nremoveURL: aURLString\\n\\t\\\"Remove the cache entry for the given URL. Do nothing if it has no cache entry.\\\"\\n\\n\\tPageCache removeKey: aURLString ifAbsent: [].\\n! !\\n\\n!SqueakPageCache class methodsFor: 'cache access' stamp: 'tk 10/22/1998 11:07'!\\nwrite\\n\\t\\\"Write out all dirty pages\\\"\\n\\tGlobalPolicy == #neverWrite ifTrue: [^ self].\\n\\tself doPagesInMemory: [:aPage | aPage write].! !\\n\\n\\n!SqueakPageCache class methodsFor: 'class initialization' stamp: 'tk 11/24/1998 14:53'!\\ninitialize\\n\\t\\\"SqueakPageCache initialize\\\"\\n\\n\\tGlobalPolicy _ #neverWrite.\\n\\tPageCache _ Dictionary new: 100.\\n\\t\\t\\\"forgets urls of pages, but ObjectOuts still remember them\\\"\\n! !\\n\\n\\n!SqueakPageCache class methodsFor: 'housekeeping' stamp: 'tk 6/24/1999 11:42'!\\ndeleteUnreferencedPages\\n\\t\\\"Remove any pages that are not current referred to by any book or URL morph.\\\"\\n\\t\\\"Details: Since unreferenced pages could refer to other pages, this process is iterated until no unreferenced pages can be found. It currently does not collect cycles.\\\"\\n\\t\\\"SqueakPageCache deleteUnreferencedPages\\\"\\n\\n\\t| unreferenced |\\n\\t[true] whileTrue: [\\n\\t\\tSmalltalk garbageCollect.\\n\\t\\tunreferenced _ PageCache keys.\\n\\t\\tURLMorph allSubInstancesDo: [:m | unreferenced remove: m url ifAbsent: []].\\n\\t\\tMorphObjectOut allInstancesDo: [:ticklish |\\n\\t\\t\\tunreferenced remove: ticklish url ifAbsent: []].\\n\\t\\tunreferenced size = 0 ifTrue: [^ self].\\n\\t\\tunreferenced do: [:url | PageCache removeKey: url ifAbsent: []]].\\n! !\\n\\n!SqueakPageCache class methodsFor: 'housekeeping' stamp: 'jm 6/25/1998 13:00'!\\nreleaseCachedStateOfPages\\n\\t\\\"Note: This shouldn't be necessary if we are doing a good job of releasing cached state as we go. If running this doesn't do very much, we're doing well!!\\\"\\n\\t\\\"SqueakPageCache releaseCachedStateOfPages\\\"\\n\\n\\t| memBytes |\\n\\tmemBytes _ Smalltalk garbageCollect.\\n\\tPageCache do: [:pg |\\n\\t\\tpg contentsMorph allMorphsDo: [:m | m releaseCachedState]].\\n\\t^ (Smalltalk garbageCollect - memBytes) printString, ' bytes recovered'\\n! !\\nMorph subclass: #SquishedNameMorph\\n\\tinstanceVariableNames: 'target getSelector setSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Navigators'!\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:19'!\\ncolorAroundName\\n\\n\\t^Color gray: 0.8! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:18'!\\nfontForName\\n\\n\\t| pickem |\\n\\tpickem _ 3.\\n\\n\\tpickem = 1 ifTrue: [\\n\\t\\t^(((TextStyle named: #Helvetica) ifNil: [TextStyle default]) fontOfSize: 13) emphasized: 1.\\n\\t].\\n\\tpickem = 2 ifTrue: [\\n\\t\\t^(((TextStyle named: #Palatino) ifNil: [TextStyle default]) fontOfSize: 12) emphasized: 1.\\n\\t].\\n\\t^((TextStyle default) fontAt: 1) emphasized: 1\\n! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:17'!\\nisEditingName\\n\\n\\t^((self findA: UpdatingStringMorph) ifNil: [^false]) hasFocus\\n! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:32'!\\nstringToShow\\n\\n\\t(target isNil or: [getSelector isNil]) ifTrue: [^'????'].\\n\\t^target perform: getSelector! !\\n\\n!SquishedNameMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/11/2000 23:31'!\\ntarget: aTarget getSelector: symbol1 setSelector: symbol2\\n\\n\\ttarget _ aTarget.\\n\\tgetSelector _ symbol1.\\n\\tsetSelector _ symbol2.! !\\n\\n\\n!SquishedNameMorph methodsFor: 'drawing' stamp: 'RAA 11/11/2000 23:17'!\\ndrawOn: aCanvas\\n\\n\\t| font stringToShow nameForm rectForName |\\n\\n\\tsuper drawOn: aCanvas.\\n\\tself isEditingName ifTrue: [^self].\\n\\n\\tfont _ self fontForName.\\n\\tstringToShow _ self stringToShow.\\n\\tnameForm _ (StringMorph contents: stringToShow font: font) imageForm.\\n\\tnameForm _ nameForm scaledToSize: (self extent - (4@2) min: nameForm extent).\\n\\trectForName _ self bottomLeft + \\n\\t\\t\\t(self width - nameForm width // 2 @ (nameForm height + 2) negated)\\n\\t\\t\\t\\textent: nameForm extent.\\n\\trectForName topLeft eightNeighbors do: [ :pt |\\n\\t\\taCanvas\\n\\t\\t\\tstencil: nameForm \\n\\t\\t\\tat: pt\\n\\t\\t\\tcolor: self colorAroundName.\\n\\t].\\n\\taCanvas\\n\\t\\tstencil: nameForm \\n\\t\\tat: rectForName topLeft \\n\\t\\tcolor: Color black.\\n\\n\\n\\t\\n! !\\nObject subclass: #Stack\\n\\tinstanceVariableNames: 'linkedList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Stack'!\\n!Stack commentStamp: 'dc 7/24/2005 15:41' prior: 0!\\nI implement a simple Stack. #push: adds a new object of any kind on top of the stack. #pop returns the first element and remove it from the stack. #top answer the first element of the stack without removing it.!\\n\\n\\n!Stack methodsFor: 'accessing' stamp: 'dc 7/25/2005 10:04'!\\nsize\\n\\t\\\"How many objects in me ?\\\"\\n\\t^ self linkedList size! !\\n\\n!Stack methodsFor: 'accessing' stamp: 'sd 3/25/2006 15:05'!\\ntop\\n\\t\\\"Answer the first element of the stack without removing it.\\\"\\n\\tself notEmptyCheck.\\n\\t^ self linkedList first element! !\\n\\n\\n!Stack methodsFor: 'adding' stamp: 'dc 7/25/2005 10:22'!\\npush: anObject \\n\\t\\\"Adds a new object of any kind on top of the stack.\\\"\\n\\tself linkedList\\n\\t\\taddFirst: (StackLink with: anObject).\\n\\t^ anObject.! !\\n\\n\\n!Stack methodsFor: 'initialize-release' stamp: 'dc 7/25/2005 11:39'!\\ninitialize\\n\\tsuper initialize.\\n\\tlinkedList := LinkedList new! !\\n\\n\\n!Stack methodsFor: 'removing' stamp: 'dc 7/24/2005 16:16'!\\npop\\n\\t\\\"Returns the first element and remove it from the stack.\\\"\\n\\n\\tself notEmptyCheck.\\n\\t^self linkedList removeFirst element! !\\n\\n\\n!Stack methodsFor: 'testing' stamp: 'dc 7/25/2005 10:05'!\\nisEmpty\\n\\t^ self linkedList isEmpty! !\\n\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:05'!\\nerrorEmptyStack\\n\\tself error: 'this stack is empty'! !\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:20'!\\nlinkedList\\n\\t\\\"The stack is implemented with a LinkedList. Do NOT call this function, it \\n\\tis for private use !!\\\"\\n\\t^ linkedList! !\\n\\n!Stack methodsFor: 'private' stamp: 'dc 7/25/2005 10:05'!\\nnotEmptyCheck\\n\\t\\\"Ensure the stack is not empty.\\\"\\n\\tself isEmpty\\n\\t\\tifTrue: [self errorEmptyStack]! !\\nLink subclass: #StackLink\\n\\tinstanceVariableNames: 'element'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Stack'!\\n!StackLink commentStamp: '<historical>' prior: 0!\\nI implement an element of a stack. I'm a container for any type of object, saved into the 'element' variable. My superclass Link allows me to be part of a LinkedList.!\\n\\n\\n!StackLink methodsFor: 'accessing' stamp: 'dc 7/24/2005 15:34'!\\nelement\\n\\t^element! !\\n\\n!StackLink methodsFor: 'accessing' stamp: 'dc 7/25/2005 10:16'!\\nelement: anObject \\n\\t\\\"Any kind of Object.\\\"\\n\\telement := anObject! !\\n\\n\\n!StackLink methodsFor: 'printing' stamp: 'dc 7/25/2005 10:15'!\\nprintOn: aStream \\n\\taStream nextPutAll: self class printString;\\n\\t\\t nextPutAll: ' with: ';\\n\\t\\t nextPutAll: self element printString! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackLink class\\n\\tinstanceVariableNames: ''!\\n\\n!StackLink class methodsFor: 'instance creation' stamp: 'dc 7/25/2005 10:15'!\\nwith: anObject \\n\\t^ self new element: anObject! !\\nBookMorph subclass: #StackMorph\\n\\tinstanceVariableNames: 'cards'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Stacks'!\\n!StackMorph commentStamp: '<historical>' prior: 0!\\nA book that is very much like a HyperCard stack. \\n\\nEach book page represents a different background. The page stays while different cards are projected onto it. \\n\\tThe data for a single card is stored in a CardPlayer. There is a list of objects that only appear on this card (privateMorphs) and the card-specific text to be inserted into the background fields.\\n\\nItem\\t\\t\\t\\t\\tHow it is stored\\na background\\t\\t\\ta page of the StackMorph\\na card\\t\\t\\t\\t\\tdata is in an instance of a subclass of CardPlayer.\\n\\t\\t\\t\\t\\t\\tA list of CardPlayers is in the 'cards' inst var of the StackMorph.\\na background field\\t\\ta TextMorph on a page of the StackMorph\\na background picture\\ta morph of any kind on a page of the StackMorph\\nscript for bkgnd button\\t\\tmethod in Player. Button is its costume.\\ntext in a background field\\t\\tvalue of inst var 'field1' in a CardPlayer.\\n\\t\\t\\t\\t\\t\\t\\t\\t(The CardPlayer is also pointed at by the #cardInstance \\n\\t\\t\\t\\t\\t\\t\\t\\tproperty of the bkgnd field (TextMorph))\\ntext in a card field\\t\\tin the TextMorph in privateMorphs in the CardPlayer.\\npicture on a card\\t\\ta morph of any kind in privateMorphs in the CardPlayer.\\nscript for card button\\tmethod in the CardPlayer. Button is its costume.\\n\\nSee VariableDock.!\\n\\n\\n!StackMorph methodsFor: 'accessing' stamp: 'sw 11/2/2002 15:51'!\\ncardNumberOf: aPlayer\\n\\t\\\"Answer the card-number of the given player, in the which-card-of-the-stack sense.\\\"\\n\\n\\t^ self cards identityIndexOf: aPlayer ifAbsent: [0]! !\\n\\n!StackMorph methodsFor: 'accessing' stamp: 'sw 3/18/2002 02:09'!\\ncardsOrPages\\n\\t\\\"The turnable and printable entities\\\"\\n\\n\\t^ self cards! !\\n\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 10/23/2000 16:27'!\\ncommitCardData\\n\\t\\\"Make certain that the player data are written back to the player instance\\\"\\n\\n\\t^ self currentCard commitCardPlayerData \\n! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'em 3/31/2005 10:56'!\\ninsertCardOfBackground\\n\\t\\\"Prompt the user for choice of a background, and insert a new card of that background\\\"\\n\\n\\t| bgs aMenu aBackground |\\n\\t(bgs _ self backgrounds) size == 1 ifTrue:\\n\\t\\t[self inform: \\n'At this time, there IS only one kind of\\nbackground in this stack, so that''s\\nwhat you''ll get' translated.\\n\\t\\t^ self insertCard].\\n\\taMenu _ SelectionMenu\\n\\t\\tlabels: \\t\\t(bgs collect: [:bg | bg externalName])\\n\\t\\tselections: \\tbgs.\\n\\t(aBackground _ aMenu startUp) ifNotNil:\\n\\t\\t[self insertCardOfBackground: aBackground]! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 3/18/2002 02:02'!\\ninsertCardOfBackground: aBackground\\n\\t\\\"Insert a new card of the given background and have it become the current card\\\"\\n\\n\\t| newCard |\\n\\tnewCard _ aBackground newCard.\\n\\tself privateCards add: newCard after: self currentCard.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'as yet unclassified' stamp: 'sw 10/30/2000 10:08'!\\nopenInsideLook\\n\\t\\\"Open an inside-look at the current page. This is a previously-demoed feature not presently incorporated in released code,\\\"\\n\\n\\ttrue ifTrue: [self notYetImplemented] ifFalse: [self currentPage openInsideLook]\\n! !\\n\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromAFile\\n\\t\\\"Using the current background, create new cards by reading in data from a fileThe data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\t| aFileStream |\\n\\t(aFileStream _ FileList2 modalFileSelector) ifNil: [^ Beeper beep].\\n\\tself addCardsFromString: aFileStream contentsOfEntireFile.\\n\\taFileStream close! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromClipboardData\\n\\t\\\"Using the current background, paste data from the (textual) clipboard to create new records. The data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\t| clip |\\n\\t(clip _ Clipboard clipboardText) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: clip! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromClipboardDataForInstanceVariables: slotNames\\n\\t\\\"Using the current background, paste data from the (textual) clipboard to create new records. No senders, but can be usefully called manually for selectively bringing in data in oddball format.\\\"\\n\\n\\t| clip |\\n\\t(clip _ Clipboard clipboardText) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: clip slotNames: slotNames! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'nb 6/17/2003 12:25'!\\naddCardsFromFile: fileStream\\n\\t\\\"Using the current background, take tab delimited data from the file to create new records.\\\"\\n\\n\\t| aString |\\n\\t(aString _ fileStream contentsOfEntireFile) isEmptyOrNil ifTrue: [^ Beeper beep].\\n\\tself addCardsFromString: aString! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/18/2001 11:35'!\\naddCardsFromString: aString\\n\\t\\\"Using the current background, add cards from a string, which is expected be tab- and return-delimited. The data are in each record are expected to be tab-delimited, and to occur in the same order as the instance variables of the current-background's cards \\\"\\n\\n\\tself addCardsFromString: aString slotNames: self currentCard slotNames\\n \\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'em 3/31/2005 10:23'!\\naddCardsFromString: aString slotNames: slotNames \\n\\t\\\"Using the current background, add cards from a string, which is expected be tab- and return-delimited\\\"\\n\\n\\t| count |\\n\\tcount := 0.\\n\\taString asString linesDo: \\n\\t\\t\\t[:aLine | \\n\\t\\t\\taLine notEmpty \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[count := count + 1.\\n\\t\\t\\t\\t\\tself \\n\\t\\t\\t\\t\\t\\tinsertCardOfBackground: self currentPage\\n\\t\\t\\t\\t\\t\\twithDataFrom: aLine\\n\\t\\t\\t\\t\\t\\tforInstanceVariables: slotNames]].\\n\\tself inform: count asString , ' card(s) added' translated! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 10/26/2000 14:41'!\\nbackgroundWithCard: aCard\\n\\t\\\"Answer the background which contains aCard.\\\"\\n\\n\\t^ self backgrounds detect:\\n\\t\\t[:aBackground | aBackground containsCard: aCard] ifNone: [nil]! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 10/30/2000 10:04'!\\nbackgrounds\\n\\t\\\"Answer the list of backgrounds available in the receiver\\\"\\n\\n\\t^ self pages! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/6/2001 21:26'!\\nbeDefaultsForNewCards\\n\\t\\\"Make the values that I see here all be accepted as defaults for new cards\\\"\\n\\n\\tself currentPage submorphs do:\\n\\t\\t[:aMorph | aMorph holdsSeparateDataForEachInstance ifTrue:\\n\\t\\t\\t[aMorph setAsDefaultValueForNewCard]]! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 11/2/2002 17:56'!\\nchangeInstVarOrder\\n\\t\\\"Change the order of the receiver's instance variables\\\"\\n\\n\\t| reply |\\n\\treply _ FillInTheBlank request: 'rearrange, then accept; or cancel' initialAnswer:\\n\\t\\t((self currentPage player class instVarNames asArray collect: [:v | v asSymbol]) storeString copyWithoutAll: #($# $( $))) asString.\\n\\treply isEmptyOrNil ifTrue: [^ self].\\n\\tself flag: #deferred. \\\"Error checking and graceful escape wanted\\\"\\n\\tself currentPage player class resortInstanceVariables: (Compiler evaluate:\\n\\t\\t('#(', reply, ')'))! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'em 3/30/2005 14:47'!\\ninsertAsBackground: newPage resize: doResize\\n\\t\\\"Make a new background for the stack. Obtain a name for it from the user. It starts out life empty\\\"\\n\\n\\t| aName |\\n\\taName _ FillInTheBlank request: 'What should we call this new background?' translated initialAnswer: 'alternateBackground' translated.\\n\\taName isEmptyOrNil ifTrue: [^ self].\\n\\tnewPage beSticky.\\n\\tdoResize ifTrue: [newPage extent: currentPage extent].\\n\\tnewPage beAStackBackground.\\n\\tnewPage setNameTo: aName.\\n\\tnewPage vResizeToFit: false.\\n\\tpages isEmpty\\n\\t\\tifTrue: [pages add: newPage]\\n\\t\\tifFalse: [pages add: newPage after: currentPage].\\n\\tself privateCards add: newPage currentDataInstance after: currentPage currentDataInstance.\\n\\tself nextPage.\\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'tk 10/30/2001 19:01'!\\nmakeNewBackground\\n\\t\\\"Make a new background for the stack. Obtain a name for it from the user. It starts out life empty\\\"\\n\\n\\t| newPage |\\n\\t(newPage _ PasteUpMorph newSticky) color: self color muchLighter.\\n\\tnewPage borderWidth: currentPage borderWidth; borderColor: currentPage borderColor.\\n\\tself insertAsBackground: newPage resize: true. \\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 3/18/2002 02:14'!\\nsortByField: varName\\n\\t\\\"Perform a simple reordering of my cards, sorting by the given field name. If there are multiple backgrounds, then sort the current one, placing all its cards first, followed by all others in unchanged order\\\"\\n\\n\\t| holdCards thisClassesInstances sortedList |\\n\\tholdCards _ self privateCards copy.\\n\\n\\tthisClassesInstances _ self privateCards select: [:c | c isKindOf: self currentCard class].\\n\\tsortedList _ thisClassesInstances asSortedCollection:\\n\\t\\t[:a :b | (a instVarNamed: varName) asString <= (b instVarNamed: varName) asString].\\n\\tsortedList _ sortedList asOrderedCollection.\\n\\tholdCards removeAllFoundIn: sortedList.\\n\\tself privateCards: (sortedList asOrderedCollection, holdCards).\\n\\tself goToFirstCardOfStack\\n! !\\n\\n!StackMorph methodsFor: 'background' stamp: 'sw 12/6/2001 22:08'!\\nsortCards\\n\\t\\\"Let the user provide an inst var on which to sort the cards of a background.\\\"\\n\\n\\t| names aMenu |\\n\\tnames _ self currentPage player class instVarNames.\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Choose field by which to sort:'.\\n\\tnames do: [:n | aMenu add: n selector: #sortByField: argument: n].\\n\\taMenu popUpInWorld! !\\n\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 10/23/2000 16:24'!\\nbrowseCardClass\\n\\t\\\"Browse the class of the current card\\\"\\n\\n\\t| suffix |\\n\\tsuffix _ self currentCard class name numericSuffix.\\n\\tHierarchyBrowser newFor: self currentCard class labeled: 'Background ', suffix asString\\n! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:20'!\\ncardIndexOf: aCard\\n\\t\\\"Answer the ordinal position of aCard in the receiver's list\\\"\\n\\n\\t^ self privateCards indexOf: aCard ifAbsent: [nil]! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:12'!\\ncards\\n\\t\\\"Answer a list of the cards of the receiver, in order\\\"\\n\\n\\t^ self privateCards copy! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 10/23/2000 16:27'!\\ncurrentCard\\n\\t\\\"Answer the current card of the current background of the receiver\\\"\\n\\n\\t^ currentPage currentDataInstance! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'em 3/31/2005 10:24'!\\ndeleteAllCardsExceptThisOne\\n\\t\\\"Delete all cards except the current one\\\"\\n\\n\\tself privateCards size <= 1 ifTrue: [^ Beeper beep].\\n\\t(self confirm: 'Really delete ' translated, self privateCards size asString, ' card(s) and all of their data?' translated) ifTrue:\\n\\t\\t[self privateCards: (OrderedCollection with: self currentCard)].! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sd 11/13/2003 21:03'!\\ndeleteCard\\n\\t\\\"Delete the current card from the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards size = 1 ifTrue: [^ Beeper beep].\\n\\t(self confirm: 'Really delete this card and all of its data?' translated) ifTrue:\\n\\t\\t[self goToNextCardInStack.\\n\\t\\tself privateCards remove: aCard].! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ndeleteCard: aCard\\n\\t\\\"Delete the current card from the stack.\\\"\\n\\n\\tself privateCards size = 1 ifTrue: [^ Beeper beep].\\n\\t(aCard == self currentCard) ifTrue: [^ self deleteCard].\\n\\n\\tself privateCards remove: aCard ifAbsent: []! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'em 3/31/2005 10:23'!\\ngoToCard\\n\\t\\\"prompt the user for an ordinal number, and use that as a basis for choosing a new card to install in the receiver\\\"\\n\\n\\t| reply index |\\n\\treply _ FillInTheBlank request: 'Which card number? ' translated initialAnswer: '1'.\\n\\treply isEmptyOrNil ifTrue: [^ self].\\n\\t((index _ reply asNumber) > 0 and: [index <= self privateCards size])\\n\\t\\tifFalse: [^ self inform: 'no such card'].\\n\\tself goToCard: (self privateCards at: index)! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 11/8/2002 15:15'!\\ngoToCard: destinationCard\\n\\t\\\"Install the indicated destinationCard as the current card in the receiver. Any viewer currently open on the current card will get retargeted to look at the new one.\\\"\\n\\n\\t| aBackground existingCard oldViewers |\\n\\tdestinationCard == self currentCard ifTrue: [^ self].\\n\\tself currentPlayerDo:\\n\\t\\t[:aPlayer | aPlayer runAllClosingScripts]. \\\"Like HyperCard 'on closeCard'\\\"\\n\\n\\taBackground _ self backgroundWithCard: destinationCard.\\n\\texistingCard _ aBackground currentDataInstance.\\n\\toldViewers _ existingCard ifNil: [#()] ifNotNil: [existingCard allOpenViewers].\\n\\n\\taBackground installAsCurrent: destinationCard.\\n\\taBackground setProperty: #myStack toValue: self.\\t\\\"pointer cardMorph -> stack\\\"\\n\\n\\taBackground ~~ currentPage ifTrue:\\n\\t\\t[self goToPageMorph: aBackground runTransitionScripts: false].\\n\\tself currentPlayerDo:\\n\\t\\t[:aPlayer | aPlayer runAllOpeningScripts] . \\\"Like HyperCard 'on opencard'\\\"\\n\\n\\toldViewers do: [:aViewer | aViewer retargetFrom: existingCard to: destinationCard]! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 11/11/2002 03:07'!\\ngoToCardNumber: aCardNumber\\n\\t\\\"Install the card whose ordinal number is provided as the current card in the stack\\\"\\n\\n\\tself goToCard: (self privateCards atWrap: aCardNumber)! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ngoToFirstCardInBackground\\n\\t\\\"Install the initial card in the current background as the current card in the stack\\\"\\n\\n\\t| kind |\\n\\tkind _ currentPage player class baseUniclass.\\n\\tself goToCard: (self privateCards detect: [:aCard | aCard isKindOf: kind] ifNone: [^ Beeper beep])! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:01'!\\ngoToFirstCardOfStack\\n\\t\\\"Install the initial card in the stack as the current card\\\"\\n\\n\\tself goToCard: self privateCards first! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'nb 6/17/2003 12:25'!\\ngoToLastCardInBackground\\n\\t\\\"Install the final card in the current background as the current card\\\"\\n\\n\\t| kind |\\n\\tkind _ currentPage player class baseUniclass.\\n\\tself goToCard: (self privateCards reversed detect: [:aCard | aCard isKindOf: kind] ifNone: [^ Beeper beep])! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:09'!\\ngoToLastCardOfStack\\n\\t\\\"Install the final card in the stack as the current card\\\"\\n\\n\\tself goToCard: self privateCards last! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:03'!\\ninsertCardOfBackground: aBackground withDataFrom: aLine forInstanceVariables: slotNames\\n\\t\\\"Insert a new card of the given background and have it become the current card. \\\"\\n\\n\\t| newCard |\\n\\tnewCard _ aBackground newCard.\\n\\tself privateCards add: newCard after: self currentCard.\\n\\tnewCard absorbBackgroundDataFrom: aLine forInstanceVariables: slotNames.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 01:57'!\\nmakeCurrentCardFirstInStack\\n\\t\\\"Move the current card such that it becomes the first card in the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards remove: aCard ifAbsent: [];\\n\\t\\taddFirst: aCard.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:03'!\\nmakeCurrentCardLastInStack\\n\\t\\\"Move the current card such that it becomes the last card in the stack\\\"\\n\\n\\t| aCard |\\n\\taCard _ self currentCard.\\n\\tself privateCards remove: aCard ifAbsent: [];\\n\\t\\taddLast: aCard.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:08'!\\nmoveCardOnePositionEarlier\\n\\t\\\"Move the current card such that its ordinal position is one fewer than it formerly was. If the current card is already the first one one in the stack, then do nothing\\\"\\n\\n\\t| aCard aPosition |\\n\\taCard _ self currentCard.\\n\\taCard == self privateCards first ifTrue: [^ self].\\n\\taPosition _ self privateCards indexOf: aCard.\\n\\tself privateCards remove: aCard;\\n\\t\\tadd: aCard afterIndex: (aPosition - 2).\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:05'!\\nmoveCardOnePositionLater\\n\\t\\\"Move the current card such that its ordinal position is one greater than it formerly was. If the current card is already the last one one in the stack, then do nothing\\\"\\n\\n\\t| aCard aPosition privateCards |\\n\\taCard _ self currentCard.\\n\\tprivateCards _ self privateCards.\\n\\taCard == privateCards last ifTrue: [^ self].\\n\\taPosition _ privateCards indexOf: aCard.\\n\\tprivateCards remove: aCard.\\n\\tprivateCards add: aCard afterIndex: aPosition.\\n\\tself currentPage flash! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 01:56'!\\nprivateCards\\n\\t\\\"Private - answer the collection object that sits in my cards instance variable\\\"\\n\\n\\t^ cards! !\\n\\n!StackMorph methodsFor: 'card access' stamp: 'sw 3/18/2002 02:51'!\\nprivateCards: aCollection\\n\\t\\\"Private - Make my cards be te given colllection\\\"\\n\\n\\tcards _ aCollection! !\\n\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:03'!\\nexplainDesignations\\n\\t\\\"Give the user an explanation of what the designations mean\\\"\\n\\n\\tself currentPage explainDesignations\\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 3/18/2002 02:03'!\\ngoToNextCardInStack\\n\\t\\\"Make the card *after* the current card become the current card\\\"\\n\\n\\t| anIndex newCard |\\n\\tanIndex _ self privateCards indexOf: currentPage currentDataInstance.\\n\\tnewCard _ self privateCards atWrap: anIndex + 1.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 3/18/2002 02:01'!\\ngoToPreviousCardInStack\\n\\t\\\"Install the previous card as my current one\\\"\\n\\n\\t| anIndex newCard |\\n\\tanIndex _ self privateCards indexOf: currentPage currentDataInstance.\\n\\tnewCard _ self privateCards atWrap: anIndex - 1.\\n\\tself goToCard: newCard! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 16:02'!\\ninsertCard\\n\\t\\\"Create a new card of the current background and make it become the current card\\\"\\n\\n\\tself insertCardOfBackground: currentPage! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'tk 10/5/2001 06:27'!\\nreassessBackgroundShape\\n\\t\\\"Have the current page reconsider its cards' instance structure\\\"\\n\\n\\tcurrentPage setProperty: #myStack toValue: self. \\t\\\"pointer cardMorph -> stack\\\"\\n\\t^ self currentPage reassessBackgroundShape \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:04'!\\nrelaxGripOnVariableNames\\n\\t\\\"Have the current background relax its grip on existing variable name\\\"\\n\\n\\t^ self currentPage relaxGripOnVariableNames \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:15'!\\nreshapeBackground\\n\\t\\\"Abandon any memory of variable-name preferences for the current background, and reassess its instance structure\\\"\\n\\n\\t^ self currentPage reshapeBackground \\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/30/2000 10:10'!\\nshowDesignationsOfObjects\\n\\t\\\"Momentarily show which objects on the current card belong to which designation category\\\"\\n\\n\\tself currentPage showDesignationsOfObjects\\n! !\\n\\n!StackMorph methodsFor: 'card in a stack' stamp: 'sw 10/23/2000 17:37'!\\nstackDo: aBlock\\n\\t\\\"Evaluate aBlock on behalf of the receiver stack\\\"\\n\\n\\t^ aBlock value: self! !\\n\\n\\n!StackMorph methodsFor: 'controls' stamp: 'sw 10/30/2000 16:31'!\\npageControlsMorphFrom: controlSpecs\\n\\t\\\"Answer a controls morph derived from the spec supplied\\\"\\n\\n\\t| controls |\\n\\tcontrols _ super pageControlsMorphFrom: controlSpecs.\\n\\tcontrols eventHandler: nil. \\\"not grabbable\\\"\\n\\t^ controls! !\\n\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/30/2000 10:13'!\\ninspectCurrentBackground\\n\\t\\\"Open an inspector on the corrent background. Ideally should put include the background name in the inspector's title.\\\"\\n\\n\\t^ self currentPage inspectWithLabel: 'A Background'\\n! !\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/23/2000 16:37'!\\ninspectCurrentCard\\n\\t\\\"For debugging: open an Inspector on the receiver's current card\\\"\\n\\n\\t^ self currentCard inspectWithLabel: 'A Card'\\n! !\\n\\n!StackMorph methodsFor: 'debugging' stamp: 'sw 10/30/2000 10:09'!\\ninspectCurrentStack\\n\\t\\\"Triggered from the stack-debug menu, open an Inspector on the receiver\\\"\\n\\n\\t^ self inspectWithLabel: 'A Stack'\\n! !\\n\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 6/5/2003 04:04'!\\naddPane: aPane paneType: aType\\n\\n\\t| anIndex |\\n\\n\\tanIndex _ self insertionIndexForPaneOfType: aType.\\n\\n\\tself privateAddMorph: aPane atIndex: anIndex! !\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 3/18/2002 02:12'!\\ninitialize\\n\\t\\\"Initialize the stack\\\"\\n\\n\\t| initialBackground |\\n\\tsuper initialize.\\n\\tinitialBackground _ pages first.\\n\\tinitialBackground extent: (640@480); beSticky.\\n\\tinitialBackground beAStackBackground.\\n\\tself beUnsticky.\\n\\tself setProperty: #controlsAtBottom toValue: true.\\n\\tself privateCards: (OrderedCollection with: initialBackground currentDataInstance).\\n\\n\\\"self currentHand attachMorph: StackMorph authoringPrototype\\\"! !\\n\\n!StackMorph methodsFor: 'initialization' stamp: 'sw 3/18/2002 02:13'!\\ninitializeWith: aCardMorph\\n\\t\\\"Install the card inside a new stack. Make no border or controls, so I the card's look is unchanged. Card already has a CardPlayer.\\\"\\n\\t\\n\\t| wld |\\n\\twld _ aCardMorph world.\\n\\tself initialize.\\n\\tself pageSize: aCardMorph extent.\\n\\tself borderWidth: 0; layoutInset: 0; color: Color transparent.\\n\\tpages _ Array with: aCardMorph.\\n\\tcurrentPage _ aCardMorph.\\n\\tself privateCards: (OrderedCollection with: currentPage currentDataInstance).\\n\\tcurrentPage beAStackBackground.\\n\\tself position: aCardMorph position.\\n\\tsubmorphs last delete.\\n\\tself addMorph: currentPage.\\t\\n\\tself showPageControls: self fullControlSpecs.\\n\\twld addMorph: self.\\n! !\\n\\n\\n!StackMorph methodsFor: 'insert and delete' stamp: 'sw 10/30/2000 10:10'!\\ndefaultNameStemForNewPages\\n\\t\\\"Answer the stem to use as the default for names of cards in the stack\\\"\\n\\n\\t^ 'card'\\n! !\\n\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:14'!\\naddBookMenuItemsTo: aMenu hand: aHandMorph\\n\\t\\\"Add book-related items to the given menu\\\"\\n\\n\\t| controlsShowing subMenu |\\n\\tsubMenu _ MenuMorph new defaultTarget: self.\\n\\tsubMenu add: 'previous card' translated action: #goToPreviousCardInStack.\\n\\tsubMenu add: 'next card' translated action: #goToNextCardInStack.\\n\\tsubMenu add: 'go to card...' translated action: #goToCard.\\n\\tsubMenu add: 'insert a card' translated action: #insertCard.\\n\\tsubMenu add: 'delete this card' translated action: #deleteCard.\\n\\n\\tcontrolsShowing _ self hasSubmorphWithProperty: #pageControl.\\n\\tcontrolsShowing\\n\\t\\tifTrue:\\n\\t\\t\\t[subMenu add: 'hide card controls' translated action: #hidePageControls.\\n\\t\\t\\tsubMenu add: 'fewer card controls' translated action: #fewerPageControls]\\n\\t\\tifFalse:\\n\\t\\t\\t[subMenu add: 'show card controls' translated action: #showPageControls].\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'sound effect for all backgrounds' translated action: #menuPageSoundForAll:.\\n\\tsubMenu add: 'sound effect this background only' translated action: #menuPageSoundForThisPage:.\\n\\tsubMenu add: 'visual effect for all backgrounds' translated action: #menuPageVisualForAll:.\\n\\tsubMenu add: 'visual effect this background only' translated action: #menuPageVisualForThisPage:.\\n\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'sort pages' translated action: #sortPages:.\\n\\tsubMenu add: 'uncache page sorter' translated action: #uncachePageSorter.\\n\\t(self hasProperty: #dontWrapAtEnd)\\n\\t\\tifTrue: [subMenu add: 'wrap after last page' translated selector: #setWrapPages: argument: true]\\n\\t\\tifFalse: [subMenu add: 'stop at last page' translated selector: #setWrapPages: argument: false].\\n\\n\\tsubMenu addUpdating: #showingFullScreenString action: #toggleFullScreen.\\n\\tsubMenu addLine.\\n\\tsubMenu add: 'search for text' translated action: #textSearch.\\n\\t(self primaryHand pasteBuffer class isKindOf: PasteUpMorph class) ifTrue:\\n\\t\\t[subMenu add: 'paste book page' translated action: #pasteBookPage].\\n\\n\\tsubMenu add: 'send all pages to server' translated action: #savePagesOnURL.\\n\\tsubMenu add: 'send this page to server' translated action: #saveOneOnURL.\\n\\tsubMenu add: 'reload all from server' translated action: #reload.\\n\\tsubMenu add: 'copy page url to clipboard' translated action: #copyUrl.\\n\\tsubMenu add: 'keep in one file' translated action: #keepTogether.\\n\\tsubMenu add: 'save as new-page prototype' translated action: #setNewPagePrototype.\\n\\tnewPagePrototype ifNotNil:\\n\\t\\t[subMenu add: 'clear new-page prototype' translated action: #clearNewPagePrototype].\\n\\n\\taMenu add: 'book...' translated subMenu: subMenu\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:06'!\\nfindText: wants\\n\\t\\\"Turn to the next card that has all of the strings mentioned on it. Highlight where it is found. allText and allTextUrls have been set. Case insensitive search.\\n\\tResuming a search. If container's text is still in the list and secondary keys are still in the page, (1) search rest of that container. (2) search rest of containers on that page (3) pages till end of book, (4) from page 1 to this page again.\\\"\\n\\n\\t\\\"Later sort wants so longest key is first\\\"\\n\\t| allText good thisWord here fromHereOn startToHere oldContainer oldIndex otherKeys strings |\\n\\tallText _ self valueOfProperty: #allText ifAbsent: [#()].\\n\\there _ self privateCards identityIndexOf: self currentCard ifAbsent: [1].\\n\\tfromHereOn _ here+1 to: self privateCards size.\\n\\tstartToHere _ 1 to: here.\\t\\t\\\"repeat this page\\\"\\n\\t(self valueOfProperty: #searchKey ifAbsent: [#()]) = wants ifTrue: [\\n\\t\\t\\\"does page have all the other keys? No highlight if found!!\\\"\\n\\t\\totherKeys _ wants allButFirst.\\n\\t\\tstrings _ allText at: here.\\n\\t\\tgood _ true.\\n\\t\\totherKeys do: [:searchString | \\\"each key\\\"\\n\\t\\t\\tgood ifTrue: [thisWord _ false.\\n\\t\\t\\t\\tstrings do: [:longString |\\n\\t\\t\\t\\t\\t(longString findWordStart: searchString startingAt: 1) > 0 ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tthisWord _ true]].\\n\\t\\t\\t\\tgood _ thisWord]].\\n\\t\\tgood ifTrue: [\\\"all are on this page. Look in rest for string again.\\\"\\n\\t\\t\\toldContainer _ self valueOfProperty: #searchContainer.\\n\\t\\t\\toldIndex _ self valueOfProperty: #searchOffset.\\n\\t\\t\\t(self findText: (OrderedCollection with: wants first) inStrings: strings\\t\\n\\t\\t\\t\\tstartAt: oldIndex+1 container: oldContainer \\n\\t\\t\\t\\tcardNum: here) ifTrue: [\\n\\t\\t\\t\\t\\tself setProperty: #searchKey toValue: wants.\\n\\t\\t\\t\\t\\t^ true]]]\\n\\t\\tifFalse: [fromHereOn _ here to: self privateCards size].\\t\\\"do search this page\\\"\\n\\t\\\"other pages\\\"\\n\\tfromHereOn do: [:cardNum |\\n\\t\\t(self findText: wants inStrings: (allText at: cardNum) startAt: 1 container: nil \\n\\t\\t\\t\\tcardNum: cardNum) \\n\\t\\t\\t\\t\\tifTrue: [^ true]].\\n\\tstartToHere do: [:cardNum |\\n\\t\\t(self findText: wants inStrings: (allText at: cardNum) startAt: 1 container: nil \\n\\t\\t\\t\\tcardNum: cardNum) \\n\\t\\t\\t\\t\\tifTrue: [^ true]].\\n\\t\\\"if fail\\\"\\n\\tself setProperty: #searchContainer toValue: nil.\\n\\tself setProperty: #searchOffset toValue: nil.\\n\\tself setProperty: #searchKey toValue: nil.\\n\\t^ false! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'gm 2/22/2003 13:13'!\\nfindText: keys inStrings: rawStrings startAt: startIndex container: oldContainer cardNum: cardNum \\n\\t\\\"Call once to search a card of the stack. Return true if found and highlight the text. oldContainer should be NIL. \\n\\t(oldContainer is only non-nil when (1) doing a 'search again' and (2) the page is in memory and (3) keys has just one element. oldContainer is a TextMorph.)\\\"\\n\\n\\t| good thisWord index insideOf place container start strings old |\\n\\tgood := true.\\n\\tstart := startIndex.\\n\\tstrings := oldContainer ifNil: \\n\\t\\t\\t\\t\\t[\\\"normal case\\\"\\n\\n\\t\\t\\t\\t\\trawStrings]\\n\\t\\t\\t\\tifNotNil: [self currentPage allStringsAfter: oldContainer text].\\n\\tkeys do: \\n\\t\\t\\t[:searchString | \\n\\t\\t\\t\\\"each key\\\"\\n\\n\\t\\t\\tgood \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[thisWord := false.\\n\\t\\t\\t\\t\\tstrings do: \\n\\t\\t\\t\\t\\t\\t\\t[:longString | \\n\\t\\t\\t\\t\\t\\t\\t(index := longString findWordStart: searchString startingAt: start) > 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[thisWord not & (searchString == keys first) \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t[insideOf := longString.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tplace := index].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthisWord := true].\\n\\t\\t\\t\\t\\t\\t\\tstart := 1].\\t\\\"only first key on first container\\\"\\n\\t\\t\\t\\t\\tgood := thisWord]].\\n\\tgood \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"all are on this page\\\"\\n\\n\\t\\t\\t\\\"wasIn _ (pages at: pageNum) isInMemory.\\\"\\n\\n\\t\\t\\tself goToCardNumber: cardNum\\n\\t\\t\\t\\\"wasIn ifFalse: ['search again, on the real current text. Know page is in.'.\\n\\t\\t\\t^ self findText: keys \\n\\t\\t\\t\\tinStrings: ((pages at: pageNum) allStringsAfter: nil) recompute it\\t\\n\\t\\t\\t\\tstartAt: startIndex container: oldContainer \\n\\t\\t\\t\\tpageNum: pageNum]\\\"].\\n\\t(old := self valueOfProperty: #searchContainer) ifNotNil: \\n\\t\\t\\t[(old respondsTo: #editor) \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[old editor selectFrom: 1 to: 0.\\t\\\"trying to remove the previous selection!!\\\"\\n\\t\\t\\t\\t\\told changed]].\\n\\tgood \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"have the exact string object\\\"\\n\\n\\t\\t\\t(container := oldContainer) ifNil: \\n\\t\\t\\t\\t\\t[container := self \\n\\t\\t\\t\\t\\t\\t\\t\\thighlightText: keys first\\n\\t\\t\\t\\t\\t\\t\\t\\tat: place\\n\\t\\t\\t\\t\\t\\t\\t\\tin: insideOf]\\n\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t[container userString == insideOf \\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[container := self \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thighlightText: keys first\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tat: place\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: insideOf]\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[(container isTextMorph) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[container editor selectFrom: place to: keys first size - 1 + place.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcontainer changed]]].\\n\\t\\t\\tself setProperty: #searchContainer toValue: container.\\n\\t\\t\\tself setProperty: #searchOffset toValue: place.\\n\\t\\t\\tself setProperty: #searchKey toValue: keys.\\t\\\"override later\\\"\\n\\t\\t\\tActiveHand newKeyboardFocus: container.\\n\\t\\t\\t^true].\\n\\t^false! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'em 3/31/2005 10:20'!\\nfindViaTemplate\\n\\t| list pl cardInst |\\n\\t\\\"Current card is the template. Only search cards in this background. Look at cards directly (not allText). Key must be found in the same field as in the template. HyperCard style (multiple starts of words). \\n\\tPut results in a list, outside the stack.\\\"\\n\\n\\tlist _ self templateMatches.\\n\\tlist isEmpty ifTrue: [^ self inform: 'No matches were found.\\nBe sure the current card is mostly blank\\nand only has text you want to match.' translated]. \\n\\t\\\"put up a PluggableListMorph\\\"\\n\\tcardInst _ self currentCard.\\n\\tcardInst matchIndex: 0.\\t\\\"establish entries\\\"\\n\\tcardInst results at: 1 put: list.\\n\\tself currentPage setProperty: #myStack toValue: self.\\t\\\"way to get back\\\"\\n\\n\\tpl _ PluggableListMorph new\\n\\t\\t\\ton: cardInst list: #matchNames\\n\\t\\t\\tselected: #matchIndex changeSelected: #matchIndex:\\n\\t\\t\\tmenu: nil \\\"#matchMenu:shifted:\\\" keystroke: nil.\\n\\tActiveHand attachMorph: (self formatList: pl).\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'tk 6/2/2001 11:40'!\\nformatList: pl\\n\\t| rr ff |\\n\\t\\\"Turn this plugglable list into a good looking morph.\\\"\\n\\n\\tpl color: Color transparent; borderWidth: 0.\\n\\tpl font: ((TextStyle named: #Palatino) fontOfSize: 14).\\n\\tpl toggleCornerRounding; width: 252; retractableOrNot; hResizing: #spaceFill.\\n\\trr _ (RectangleMorph new) toggleCornerRounding; extent: pl extent + (30@30).\\n\\trr color: self currentPage color; fillStyle: (ff _ self currentPage fillStyle copy).\\n\\tff isGradientFill ifTrue: [\\n\\t\\trr fillStyle direction: (ff direction * self currentPage extent / rr extent) rounded.\\n\\t\\trr fillStyle origin: rr bounds origin].\\n\\trr addMorph: pl.\\n\\trr layoutPolicy: TableLayout new.\\n\\trr layoutInset: 10@15; cellInset: 10@15; wrapDirection: #leftToRight.\\n\\trr listCentering: #center; borderWidth: 5; borderColor: #raised.\\n\\t\\\"Up and down buttons on left with arrows in a holder.\\\"\\n\\t\\\"lb _ (RectangleMorph new) color: transparent; borderWidth: 0.\\\"\\n\\t^ rr! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:07'!\\ngetAllText\\n\\t\\\"Collect the text for each card. Just point at strings so don't have to recopy them. (Parallel array of urls for ID of cards. Remote cards not working yet.)\\n\\tallText = Array (cards size) of arrays (fields in it) of strings of text.\\n\\tallTextUrls = Array (cards size) of urls or card numbers.\\\"\\n\\n\\t| oldUrls oldStringLists allText allTextUrls aUrl which |\\n\\tself writeSingletonData.\\n\\toldUrls _ self valueOfProperty: #allTextUrls ifAbsent: [#()].\\n\\toldStringLists _ self valueOfProperty: #allText ifAbsent: [#()].\\n\\tallText _ self privateCards collect: [:pg | OrderedCollection new].\\n\\tallTextUrls _ Array new: self privateCards size.\\n\\tself privateCards doWithIndex: [:aCard :ind | aUrl _ aCard url. aCard isInMemory \\n\\t\\tifTrue: [(allText at: ind) addAll: (aCard allStringsAfter: nil).\\n\\t\\t\\taUrl ifNil: [aUrl _ ind].\\n\\t\\t\\tallTextUrls at: ind put: aUrl]\\n\\t\\tifFalse: [\\\"Order of cards on server may be different. (later keep up to date?)\\\"\\n\\t\\t\\t\\\"*** bug in this algorithm if delete a page?\\\"\\n\\t\\t\\twhich _ oldUrls indexOf: aUrl.\\n\\t\\t\\tallTextUrls at: ind put: aUrl.\\n\\t\\t\\twhich = 0 ifFalse: [allText at: ind put: (oldStringLists at: which)]]].\\n\\tself setProperty: #allText toValue: allText.\\n\\tself setProperty: #allTextUrls toValue: allTextUrls.\\n\\t^ allText! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 9/29/2004 20:47'!\\ninvokeBookMenu\\n\\t\\\"Invoke the book's control panel menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack' translated.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList: {\\n\\t\\t{'find...' translated.\\t\\t\\t\\t\\t#textSearch}.\\n\\t\\t{'find via this template' translated.\\t\\t\\t#findViaTemplate}.\\n\\t\\t{'show designations' translated. \\t\\t\\t#showDesignationsOfObjects}.\\n\\t\\t{'explain designations' translated.\\t\\t\\t#explainDesignations}.\\n\\t\\t#-.\\n\\t\\t{'previous card' translated. \\t\\t\\t\\t#goToPreviousCardInStack}.\\n\\t\\t{'next card' translated. \\t\\t\\t\\t#goToNextCardInStack}.\\n\\t\\t{'first card' translated. \\t\\t\\t\\t#goToFirstCardOfStack}.\\n\\t\\t{'last card' translated. \\t\\t\\t\\t#goToLastCardOfStack}.\\n\\t\\t{'go to card...' translated. \\t\\t\\t\\t#goToCard}.\\n\\t\\t#-.\\n\\t\\t{'add a card of this background' translated. \\t\\t#insertCard}.\\n\\t\\t{'add a card of background...' translated.\\t\\t#insertCardOfBackground}.\\n\\t\\t{'make a new background...' translated. \\t\\t#makeNewBackground}.\\n\\t\\t#-.\\n\\t\\t{'insert cards from clipboard data' translated.\\t\\t#addCardsFromClipboardData.\\t'Create new cards from a formatted string on the clipboard' translated}.\\n\\t\\t{'insert cards from a file...' translated.\\t\\t#addCardsFromAFile.\\t\\t'Create new cards from data in a file' translated}.\\n\\t\\t#-.\\n\\t\\t{'instance variable order...' translated.\\t\\t#changeInstVarOrder.\\t\\t'Caution -- DANGER. Change the order of the variables on the cards' translated}.\\n\\t\\t{'be defaults for new cards' translated. \\t\\t#beDefaultsForNewCards.\\t\\t'Make these current field values be the defaults for their respective fields on new cards' translated}.\\n\\t\\t {'sort cards by...' translated.\\t\\t\\t#sortCards.\\t\\t\\t'Sort all the cards of the current background using some field as the sort key' translated}.\\n\\t\\t#-.\\n\\t\\t{'delete this card' translated. \\t\\t\\t#deleteCard}.\\n\\t\\t{'delete all cards *except* this one' translated.\\t#deleteAllCardsExceptThisOne}.\\n\\t\\t#-.\\n\\t\\t{'move card to front of stack' translated.\\t\\t#makeCurrentCardFirstInStack}.\\n\\t\\t{'move card to back of stack' translated.\\t\\t#makeCurrentCardLastInStack}.\\n\\t\\t{'move card one position earlier' translated.\\t\\t#moveCardOnePositionEarlier}.\\n\\t\\t{'move card one position later' translated.\\t\\t#moveCardOnePositionLater}.\\n\\t\\t#-.\\n\\t\\t{'scripts for this background' translated.\\t\\t#browseCardClass}.\\n\\t\\t#-.\\n\\t\\t{'debug...' translated.\\t\\t\\t\\t\\t#offerStackDebugMenu}.\\n\\t\\t{'bookish items...' translated. \\t\\t\\t#offerBookishMenu}}.\\n\\n\\taMenu addUpdating: #showingPageControlsString action: #toggleShowingOfPageControls.\\n\\taMenu addUpdating: #showingFullScreenString action: #toggleFullScreen.\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 4/4/2006 16:49'!\\nofferBookishMenu\\n\\t\\\"Offer a menu with book-related items in it\\\"\\n\\n\\t| aMenu |\\n\\taMenu := MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack / Book' translated.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList:\\n\\t\\t#(('sort pages' sortPages)\\n\\t\\t('uncache page sorter' uncachePageSorter)).\\n\\t(self hasProperty: #dontWrapAtEnd)\\n\\t\\tifTrue: [aMenu add: 'wrap after last page' translated selector: #setWrapPages: argument: true]\\n\\t\\tifFalse: [aMenu add: 'stop at last page' translated selector: #setWrapPages: argument: false].\\n\\taMenu addList:\\n\\t\\t#(('make bookmark'\\t bookmarkForThisPage)\\n\\t\\t('make thumbnail' thumbnailForThisPage)).\\n\\n\\taMenu addLine.\\n\\taMenu add: 'sound effect for all pages' translated action: #menuPageSoundForAll:.\\n\\taMenu add: 'sound effect this page only' translated action: #menuPageSoundForThisPage:.\\n\\taMenu add: 'visual effect for all pages' translated action: #menuPageVisualForAll:.\\n\\taMenu add: 'visual effect this page only' translated action: #menuPageVisualForThisPage:.\\n\\n\\taMenu addLine.\\n\\t(self primaryHand pasteBuffer class isKindOf: PasteUpMorph class) ifTrue:\\n\\t\\t[aMenu add: 'paste book page' translated action: #pasteBookPage].\\n\\n\\taMenu add: 'save as new-page prototype' translated action: #setNewPagePrototype.\\n\\tnewPagePrototype ifNotNil: [\\n\\t\\taMenu add: 'clear new-page prototype' translated action: #clearNewPagePrototype].\\n\\n\\taMenu add: (self dragNDropEnabled ifTrue: ['close' translated ] ifFalse: ['open' translated]) , ' dragNdrop' translated\\n\\t\\t\\taction: #toggleDragNDrop.\\n\\taMenu addLine.\\n\\taMenu add: 'make all pages this size' translated action: #makeUniformPageSize.\\n\\taMenu addUpdating: #keepingUniformPageSizeString target: self action: #toggleMaintainUniformPageSize.\\n\\taMenu addLine.\\n\\taMenu add: 'send all pages to server' translated action: #savePagesOnURL.\\n\\taMenu add: 'send this page to server' translated action: #saveOneOnURL.\\n\\taMenu add: 'reload all from server' translated action: #reload.\\n\\taMenu add: 'copy page url to clipboard' translated action: #copyUrl.\\n\\taMenu add: 'keep in one file' translated action: #keepTogether.\\n\\n\\taMenu addLine.\\n\\taMenu add: 'load PPT images from slide #1' translated action: #loadImagesIntoBook.\\n\\taMenu add: 'background color for all pages...' translated action: #setPageColor.\\n\\n\\taMenu popUpEvent: self world activeHand lastEvent in: self world\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'dgd 9/29/2004 20:47'!\\nofferStackDebugMenu\\n\\t\\\"Put up a menu offering debugging items for the stack\\\"\\n\\n\\t| aMenu |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\taMenu addTitle: 'Stack debugging'.\\n\\tPreferences noviceMode\\n\\t\\tifFalse: [aMenu addStayUpItem].\\n\\taMenu addList: #(\\n\\t\\t('reassess'\\t\\t\\t\\t\\t\\t\\t\\treassessBackgroundShape)\\n\\t\\t('relax grip on variable names'\\t\\t\\trelaxGripOnVariableNames)\\n\\t\\t('commit card data'\\t\\t\\t\\t\\t\\tcommitCardData)\\n\\t\\t-\\n\\t\\t('browse card uniclass'\\t\\t\\t\\t\\tbrowseCardClass)\\n\\t\\t('inspect card'\\t\\t\\t\\t\\t\\t\\tinspectCurrentCard)\\n\\t\\t('inspect background'\\t\\t\\t\\t\\tinspectCurrentBackground)\\n\\t\\t('inspect stack'\\t\\t\\t\\t\\t\\t\\tinspectCurrentStack)).\\n\\taMenu popUpInWorld: (self world ifNil: [self currentWorld])\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 01:58'!\\ntemplateMatches\\n\\t| template docks keys bkg |\\n\\t\\\"Current card is the template. Only search cards in this background. Look at cards directly (not allText). Key must be found in the same field as in the template. HyperCard style (multiple starts of words). \\n\\tPut results in a list, outside the stack.\\\"\\n\\n\\ttemplate _ self currentCard.\\n\\ttemplate commitCardPlayerData.\\n\\tdocks _ template class variableDocks.\\n\\t(keys _ template asKeys) ifNil: [^ #()]. \\\"nothing to match against\\\"\\n\\tbkg _ self currentPage.\\n\\t^ self privateCards select: [:cardPlayer | \\n\\t\\t(((cardPlayer == template) not) and: [cardPlayer costume == bkg]) \\n\\t\\t\\tand: [cardPlayer match: keys fields: docks]].\\n! !\\n\\n!StackMorph methodsFor: 'menu' stamp: 'sw 3/18/2002 02:00'!\\nwriteSingletonData\\n\\t\\\"Backgrounds that have just one card, may never get their data written into a CardPlayer. Make sure we do it.\\\"\\n\\n\\t| sieve |\\n\\tsieve _ IdentityDictionary new.\\n\\tpages do: [:pp | sieve at: pp put: 0].\\n\\tself privateCards do: [:cc | sieve at: cc costume put: (sieve at: cc costume) + 1].\\n\\tsieve associationsDo: [:ass | \\n\\t\\tass value = 1 ifTrue:\\n\\t\\t\\t[ass key player commitCardPlayerDataFrom: ass key]].\\n\\t\\t\\t\\\"If currently showing card, may be some trouble... <- tk note 5/01\\\"! !\\n\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'sw 6/6/2003 13:59'!\\naddPageControlMorph: aMorph\\n\\n\\t\\\"Add the given morph as a page-control, at the appropriate place\\\"\\n\\n\\n\\n\\taMorph setProperty: #pageControl toValue: true.\\n\\n\\tself addPane: aMorph paneType: #pageControl! !\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'tk 11/5/2001 08:21'!\\nfullControlSpecs\\n\\t\\\"Answer specifications for the long form of iconic stack/book controls\\\"\\n\\n\\t^ #(\\n\\t\\tspacer\\n\\t\\tvariableSpacer\\n\\t\\t('-'\\t\\t\\tdeleteCard\\t\\t\\t\\t\\t'Delete this card')\\n\\t\\tspacer\\n\\t\\t( '\\U00ab'\\t\\tgoToFirstCardOfStack\\t\\t\\t'First card')\\n\\t\\tspacer\\n\\t\\t( '<' \\t\\tgoToPreviousCardInStack\\t\\t'Previous card')\\n\\t\\tspacer\\n\\t\\t('\\U00b7'\\t\\t\\tinvokeBookMenu \\t\\t\\t'Click here to get a menu of options for this stack.')\\n\\t\\t\\\"spacer\\t('\\U00b6'\\t\\t\\treshapeBackground \\t\\t'Reshape')\\t\\\"\\n\\n\\t\\tspacer\\n\\t\\t('\\U00a7'\\t\\t\\tshowDesignationsOfObjects \\t'Show designations')\\n\\t\\tspacer\\n\\t\\t('>'\\t\\t\\tgoToNextCardInStack\\t\\t\\t'Next card')\\n\\t\\tspacer\\n\\t\\t( '\\U00bb'\\t\\tgoToLastCardOfStack\\t\\t\\t'Final card')\\n\\t\\tspacer\\n\\t\\t('+'\\t\\t\\tinsertCard\\t\\t\\t\\t\\t'Add a new card after this one')\\n\\t\\tvariableSpacer\\n\\t\\t('\\U00b3'\\t\\t\\tfewerPageControls\\t\\t\\t'Fewer controls\\n(if shift key pressed,\\ndeletes controls)')\\n)! !\\n\\n!StackMorph methodsFor: 'page controls' stamp: 'sw 10/30/2000 10:09'!\\nshortControlSpecs\\n\\t\\\"Answer specficiations for the shorter form of stack controls\\\"\\n\\n\\t^ #(\\n\\t\\tspacer\\n\\t\\tvariableSpacer\\n\\t\\t( '<'\\t\\tgoToPreviousCardInStack\\t\\t'Previous card')\\n\\t\\tspacer\\n\\t\\t('\\U00b7'\\t\\tinvokeBookMenu \\t\\t\\t'Click here to get a menu for this stack.')\\n\\t\\tspacer\\n\\t\\t('>'\\t\\tgoToNextCardInStack\\t\\t\\t'Next card')\\n\\t\\tvariableSpacer\\n\\t\\t('\\U00b3'\\tshowMoreControls\\t\\t\\t\\t'More controls\\n(if shift key pressed,\\ndeletes controls)'))! !\\n\\n\\n!StackMorph methodsFor: 'parts bin' stamp: 'sw 8/2/2001 18:14'!\\ninitializeToStandAlone\\n\\t\\n\\tself initialize.\\n\\tself pageSize: (480 @ 320); color: (Color gray: 0.7).\\n\\tself borderWidth: 1; borderColor: Color black.\\n\\tself currentPage extent: self pageSize.\\n\\tself showPageControls: self fullControlSpecs.\\n\\t^ self\\n\\n\\\"StackMorph initializedInstance openInHand\\\"! !\\n\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 3/18/2002 02:20'!\\nallNonSubmorphMorphs\\n\\t\\\"Return a collection containing all morphs in this morph which are not currently in the submorph containment hierarchy. Especially the non-showing pages in BookMorphs.\\\"\\n\\n\\t| coll |\\n\\tcoll _ OrderedCollection new.\\n\\tself privateCards do: [:cd | \\n\\t\\tcd privateMorphs ifNotNil: [coll addAll: cd privateMorphs]].\\n\\t^ coll! !\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 6/5/2003 04:01'!\\ninsertionIndexForPaneOfType: aType\\n\\n\\t| naturalIndex insertionIndex |\\n\\n\\tnaturalIndex _ self naturalPaneOrder indexOf: aType.\\n\\n\\tinsertionIndex _ 1.\\n\\n\\t(self naturalPaneOrder copyFrom: 1 to: (naturalIndex - 1)) do: \\\"guys that would precede\\\"\\n\\n\\t\\t[:sym | (self hasSubmorphWithProperty: sym)\\n\\n\\t\\t\\tifTrue:\\n\\n\\t\\t\\t\\t[insertionIndex _ insertionIndex + 1]].\\n\\n\\t^ insertionIndex! !\\n\\n!StackMorph methodsFor: 'submorphs-accessing' stamp: 'sw 6/5/2003 04:02'!\\nnaturalPaneOrder\\n\\n\\t^ #(header pageControl retrieve search index content)! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StackMorph class methodsFor: 'authoring prototype' stamp: 'nk 7/12/2003 08:59'!\\ndesignationsExplainer\\n\\t\\\"Answer a morph that contains designation explanation\\\"\\n\\n\\t| aMorph aSwatch aTextMorph |\\n\\taMorph _ AlignmentMorph newColumn color: Color black; layoutInset: 1.\\n\\t#((green\\t\\t\\n'Shared items on\\nBackground.\\nExact same item\\nshared by every card')\\n\\t(orange\\n'Data items on\\nBackground\\nEach card has its\\nown data')\\n\\t(red\\n'Instance-specific\\nitems\\nunique\\nto this card')) do:\\n\\n\\t[:aPair |\\n\\t\\taSwatch _ AlignmentMorph new extent: 132 @80; color: (Color perform: aPair first); lock.\\n\\t\\taSwatch hResizing: #rigid; vResizing: #rigid; layoutInset: 0.\\n\\t\\taSwatch borderColor: Color black.\\n\\t\\taTextMorph _ TextMorph new string: aPair second fontName: Preferences standardEToysFont familyName size: 18.\\n\\t\\taTextMorph width: 130.\\n\\t\\taTextMorph centered.\\n\\t\\taSwatch addMorphBack: aTextMorph.\\n\\t\\taMorph addMorphBack: aSwatch].\\n\\taMorph hResizing: #shrinkWrap; vResizing: #shrinkWrap.\\n\\n\\t^ aMorph\\n\\n\\t\\\"StackMorph designationsExplainer openInHand\\\"\\n! !\\n\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:30'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:36'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StackMorph\\tauthoringPrototype\\t'Stack'\\t\\t'A multi-card data base'\\t)\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Scripting'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tauthoringPrototype\\t'Stack'\\t\\t'A multi-card data base'\\t)\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tstackHelpWindow\\t'Stack Help'\\t'Some hints about how to use Stacks')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tpreviousCardButton\\t'Previous Card'\\t'A button that takes the user to the previous card in the stack')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StackMorph\\tnextCardButton\\t'Next Card'\\t\\t'A button that takes the user to the next card in the stack')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Stack Tools']! !\\n\\n!StackMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:40'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!StackMorph class methodsFor: 'misc' stamp: 'tk 12/14/2001 19:23'!\\ndiscoverSlots: aMorph\\n\\t\\\"Examine the parts of the morph for ones that couldHoldSeparateData. Return a pair of lists: Named morphs, and unnamed morphs (which may be labels, and non-data). Examine all submorphs.\\\"\\n\\n\\t| named unnamed got sn generic |\\n\\tnamed _ OrderedCollection new.\\n\\tunnamed _ OrderedCollection new.\\n\\taMorph submorphsDo: [:direct | \\n\\t\\tgot _ false.\\n\\t\\tdirect allMorphsDo: [:sub |\\n\\t\\t\\tsub couldHoldSeparateDataForEachInstance ifTrue: [\\n\\t\\t\\t\\t(sn _ sub knownName) ifNotNil: [\\n\\t\\t\\t\\t\\tgeneric _ (#('Number (fancy)' 'Number (mid)' 'Number (bare)')\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tincludes: sn).\\n\\t\\t\\t\\t\\t(sn beginsWith: 'shared' \\\"label\\\") | generic ifFalse: [\\n\\t\\t\\t\\t\\t\\tnamed add: sub.\\n\\t\\t\\t\\t\\t\\tgot _ true]]]].\\n\\t\\tgot ifFalse: [unnamed add: direct]].\\n\\t^ Array with: named with: unnamed\\n\\t\\t! !\\n\\n\\n!StackMorph class methodsFor: 'navigation buttons' stamp: 'sw 10/27/2000 10:53'!\\nnextCardButton\\n\\t\\\"Answer a button that advances the user to the next card in the stack\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton target: aButton; actionSelector: #goToNextCardInStack; label: '>'; color: Color yellow; borderWidth: 0.\\n\\taButton setNameTo: 'next'.\\n\\t^ aButton! !\\n\\n!StackMorph class methodsFor: 'navigation buttons' stamp: 'sw 10/27/2000 10:53'!\\npreviousCardButton\\n\\t\\\"Answer a button that will take the user to the preceding card in the stack\\\"\\n\\n\\t| aButton |\\n\\taButton _ SimpleButtonMorph new.\\n\\taButton target: aButton; actionSelector: #goToPreviousCardInStack; label: '<'; color: Color yellow ; borderWidth: 0.\\n\\taButton setNameTo: 'previous'.\\n\\t^ aButton! !\\n\\n\\n!StackMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:52'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Stack'\\n\\t\\tcategories:\\t\\t#('Presentation')\\n\\t\\tdocumentation:\\t'A database of any sort -- slide show, rolodex, and any point in between'! !\\n\\n!StackMorph class methodsFor: 'parts bin' stamp: 'sw 4/8/2002 09:30'!\\nstackHelpWindow\\n\\t^ (Workspace new contents: 'A \\\"stack\\\" is a place where you can create, store, view and retrieve data \\\"fields\\\" from a set of \\\"cards\\\". Data that you want to occur on every card (such as a name and an address in an Address Stack) are represented by objects such as \\\"Simple Text\\\", \\\"Fancy Text\\\", and \\\"Scrolling Text\\\" that you obtain from the Stack Tools flap.\\n\\nWhen you look at a card in a Stack, you may be seeing three different kinds of material. Press the \\U00a7 button in the stack''s controls to see the current designations, and use the \\\"explain designations\\\" to get a reminder of what the three different colors mean.\\n\\U00b7 Things that are designated to be seen on every card, and have the same contents whichever card is being shown. (green)\\n\\U00b7 Things that are designated to be seen on every card, with each card having its own value for them. (orange)\\n\\U00b7 Things that are designated to occur only on the particular card at hand. (red)\\n\\nUse the \\\"stack/cards\\\" menu (in an object''s halo menu) to change the designation of any object. For example, if you have an object that is private to just one card, and you want to make it visible on all cards, use \\\"place onto background\\\". If you further want it to hold a separate value for each separate card, use \\\"start holding separate data for each instance\\\".\\n\\nThe normal sequence to define a Stack''s structure is to obtain a blank Stack, then create your fields by grabbing what you want from the Stack Tools flap and dropping it where you want it in the stack. For easiest use, give a name to each field (by editing the name in its halo) *before* you put it onto the background.. Those fields that you want to represent the basic data of the stack need to be given names, placed on the background, and then told to hold separate data.\\n\\nWhen you hit the + button in a stack''s controls, a new card is created with default values in all the fields. You can arrange for a particular default value to be used in a field -- do this either for one field at a time with \\\"be default value on new card\\\", or you can request that the all the values seen on a particular card serve as default by choosing \\\"be defaults for new cards\\\" from the stack''s \\U00b7 menu.\\n\\nIt is also possible to have multiple \\\"backgrounds\\\" in the same stack -- each different background defines a different data structure, and cards from multiple backgrounds can be freely mixed in the same stack.\\n\\nBesides text fields, it is also possible to have picture-valued fields -- and potentially fields with data values of any other type as well.')\\n\\n\\tembeddedInMorphicWindowLabeled: 'Stack Help'\\n\\n\\t\\\"StackMorph stackHelpWindow\\\"! !\\n\\n\\n!StackMorph class methodsFor: 'scripting' stamp: 'sw 11/2/2002 15:47'!\\nadditionsToViewerCategories\\n\\t\\\"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories.\\\"\\n\\n\\t^ # ((#'stack navigation'\\n\\t\\t\\t((command goToNextCardInStack 'Go to the next card')\\n\\t\\t\\t(command goToPreviousCardInStack 'Go to the previous card')\\n\\t\\t\\t(command goToFirstCardInBackground 'Go to the first card of the current background')\\n\\t\\t\\t(command goToFirstCardOfStack 'Go to the first card of the entire stack')\\n\\t\\t\\t(command goToLastCardInBackground 'Go to the last card of the current background')\\n\\t\\t\\t(command goToLastCardOfStack 'Go to the last card of the entire stack')\\n\\t\\t\\t(command deleteCard 'Delete the current card')\\n\\t\\t\\t(command insertCard 'Create a new card')\\n\\t\\t\\t(slot cardNumber 'The ordinal number of the current card' Number readWrite Player getCardNumber Player setCardNumber:))))! !\\n\\n!StackMorph class methodsFor: 'scripting' stamp: 'sw 10/9/2000 07:43'!\\nauthoringPrototype\\n\\t\\\"Answer an instance of the receiver suitable for placing in a parts bin for authors\\\"\\n\\t\\n\\t| book |\\n\\tbook _ self new markAsPartsDonor.\\n\\tbook pageSize: (480 @ 320); color: (Color gray: 0.7).\\n\\tbook borderWidth: 1; borderColor: Color black.\\n\\tbook currentPage extent: book pageSize.\\n\\tbook showPageControls: book fullControlSpecs.\\n\\t^ book\\n\\n\\\"self currentHand attachMorph: StackMorph authoringPrototype\\\"! !\\nTestCase subclass: #StackTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Stack'!\\n\\n!StackTest methodsFor: 'test' stamp: 'dc 6/21/2006 10:55'!\\ntestEmptyError\\n\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself should: [ aStack top ] raise: Error.\\n\\tself should: [ aStack pop] raise: Error.\\n\\t\\n\\taStack push: 'element'.\\n\\t\\n\\tself shouldnt: [ aStack top ] raise: Error.\\n\\tself shouldnt: [ aStack pop] raise: Error.\\n\\t\\n\\t\\n\\t\\\"The stack is empty again due to previous pop\\\"\\n\\tself should: [ aStack top ] raise: Error.\\n\\tself should: [ aStack pop] raise: Error.! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestPop\\n\\n\\t| aStack res elem |\\n\\telem := 'anElement'.\\t\\n\\taStack := Stack new.\\n\\tself assert: aStack isEmpty.\\n\\t\\n\\taStack push: 'a'.\\n\\taStack push: elem.\\n\\tres := aStack pop.\\t\\n\\tself assert: res = elem.\\n\\tself assert: res == elem.\\n\\t\\n\\tself assert: aStack size = 1.\\n\\taStack pop.\\n\\tself assert: aStack isEmpty.\\n\\n! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestPush\\n\\t\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\taStack push: 'a'.\\n\\tself assert: aStack size = 1.\\t\\n\\taStack push: 'b'.\\n\\tself assert: aStack size = 2.\\n\\t! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestSize\\n\\t\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself assert: aStack size = 0.\\n\\taStack push: 'a'.\\n\\tself assert: aStack size = 1.\\n\\taStack push: 'b'.\\n\\tself assert: aStack size = 2.\\n\\taStack pop.\\n\\tself assert: aStack size = 1.\\n\\taStack pop.\\n\\tself assert: aStack size = 0.\\n\\n \\n\\t\\n\\n\\n! !\\n\\n!StackTest methodsFor: 'test' stamp: 'sd 3/21/2006 22:13'!\\ntestTop\\n\\n\\t| aStack |\\n\\taStack := Stack new.\\n\\tself assert: aStack isEmpty.\\n\\taStack push: 'a'.\\n\\taStack push: 'b'.\\n\\tself assert: aStack top = 'b'.\\n\\tself assert: aStack top = 'b'.\\n\\tself assert: aStack size = 2.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStackTest class\\n\\tinstanceVariableNames: 'testSize'!\\nSelectionMenu subclass: #StandardFileMenu\\n\\tinstanceVariableNames: 'canTypeFileName pattern'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n!StandardFileMenu commentStamp: 'mp 8/15/2005 18:44' prior: 0!\\nI represent a SelectionMenu which operates like a modal dialog for selecting files, somewhat similar to the StandardFile dialogs in MacOS and Java Swing.\\n\\nTry for example, the following:\\n\\n\\tStandardFileMenu oldFile inspect\\n\\n\\tStandardFileMenu oldFileStream inspect\\n\\n\\tStandardFileMenu newFile inspect\\n\\n\\tStandardFileMenu newFileStream inspect\\n\\t\\n\\t(StandardFileMenu oldFileMenu: FileDirectory default withPattern: '*') startUpWithCaption: 'Select a file:'\\n\\t\\n\\t(StandardFileMenu oldFileMenu: (FileDirectory default) withPatternList: {'*.txt'. '*.changes'}) startUpWithCaption: 'Select a file:'\\n!\\n\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'rbb 2/16/2005 16:59'!\\nconfirmExistingFiles: aResult\\n\\n\\t|choice|\\n\\t(aResult directory fileExists: aResult name) ifFalse: [^aResult].\\n\\t\\n\\tchoice _ (UIManager default chooseFrom: #('overwrite that file' 'choose another name'\\n 'cancel')\\n\\t\\ttitle: aResult name, '\\nalready exists.').\\n\\n\\tchoice = 1 ifTrue: [\\n\\t\\taResult directory \\n\\t\\t\\tdeleteFileNamed: aResult name\\n\\t\\t\\tifAbsent: \\n\\t\\t\\t\\t[^self startUpWithCaption: \\n'Can''t delete ', aResult name, '\\nSelect another file'].\\n\\t\\t^aResult].\\n\\tchoice = 2 ifTrue: [^self startUpWithCaption: 'Select Another File'].\\n\\t^nil\\n ! !\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'rbb 3/1/2005 11:14'!\\ngetTypedFileName: aResult\\n\\n\\t| name |\\n\\tname := UIManager default \\n\\t\\trequest: 'Enter a new file name' \\n\\t\\tinitialAnswer: ''.\\n\\tname = '' ifTrue: [^self startUpWithCaption: 'Select a File:' translated].\\n\\tname := aResult directory fullNameFor: name.\\n\\t^ StandardFileMenuResult\\n\\t\\t\\tdirectory: (FileDirectory forFileName: name)\\n\\t\\t\\tname: (FileDirectory localNameFor: name)\\n! !\\n\\n!StandardFileMenu methodsFor: 'basic control sequences' stamp: 'acg 9/28/1999 23:34'!\\nstartUpWithCaption: aString at: location\\n\\n\\t|result|\\n\\tresult _ super startUpWithCaption: aString at: location.\\n\\tresult ifNil: [^nil].\\n\\tresult isDirectory ifTrue:\\n\\t\\t[self makeFileMenuFor: result directory.\\n\\t\\t self computeForm.\\n\\t\\t ^self startUpWithCaption: aString at: location].\\n\\tresult isCommand ifTrue: \\n\\t\\t[result _ self getTypedFileName: result.\\n\\t\\tresult ifNil: [^nil]].\\n\\tcanTypeFileName ifTrue: [^self confirmExistingFiles: result].\\n\\t^result\\n\\t! !\\n\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'di 5/12/2000 10:31'!\\ndirectoryNamesString: aDirectory\\n\\\"Answer a string concatenating the directory name strings in aDirectory, each string followed by a '[...]' indicator, and followed by a cr.\\\"\\n\\n\\t^ String streamContents:\\n\\t\\t[:s | aDirectory directoryNames do: \\n\\t\\t\\t\\t[:dn | s nextPutAll: dn withBlanksTrimmed , ' [...]'; cr]]\\n\\n! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 17:33'!\\nfileNamesString: aDirectory\\n\\\"Answer a string concatenating the file name strings in aDirectory, each string followed by a cr.\\\"\\n\\n\\t^String streamContents:\\n\\t\\t[:s | \\n\\t\\t\\taDirectory fileNames do: \\n\\t\\t\\t\\t[:fn |\\n\\t\\t\\t\\t\\tpattern do:[:each | (each match: fn) ifTrue: [\\n\\t\\t\\t\\t\\t\\ts nextPutAll: fn withBlanksTrimmed; cr]]]]\\n\\t\\t! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 16:28'!\\nmakeFileMenuFor: aDirectory\\n\\\"Initialize an instance of me to operate on aDirectory\\\"\\n\\n\\t| theMenu |\\n\\tpattern ifNil: [pattern := {'*'}].\\n\\tCursor wait showWhile: \\n\\t\\t[self \\n\\t\\t\\tlabels: \\t(self menuLabelsString: aDirectory)\\n\\t\\t\\tfont: \\t(MenuStyle fontAt: 1) \\n\\t\\t\\tlines: \\t(self menuLinesArray: aDirectory).\\n\\t\\ttheMenu := self selections: (self menuSelectionsArray: aDirectory)].\\n\\t^theMenu! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:57'!\\nmenuLabelsString: aDirectory\\n\\\"Answer a menu labels object corresponding to aDirectory\\\"\\n\\n\\t^ String streamContents: \\n\\t\\t[:s | \\n\\t\\t\\tcanTypeFileName ifTrue: \\n\\t\\t\\t\\t[s nextPutAll: 'Enter File Name...'; cr].\\n\\t\\t\\ts nextPutAll: (self pathPartsString: aDirectory).\\n\\t\\t\\ts nextPutAll: (self directoryNamesString: aDirectory).\\n\\t\\t\\ts nextPutAll: (self fileNamesString: aDirectory).\\n\\t\\t\\ts skip: -1]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'tpr 11/28/2003 15:12'!\\nmenuLinesArray: aDirectory\\n\\\"Answer a menu lines object corresponding to aDirectory\\\"\\n\\n\\t| typeCount nameCnt dirDepth|\\n\\ttypeCount _ canTypeFileName \\n\\t\\tifTrue: [1] \\n\\t\\tifFalse: [0].\\n\\tnameCnt _ aDirectory directoryNames size.\\n\\tdirDepth _ aDirectory pathParts size.\\n\\t^Array streamContents: [:s |\\n\\t\\tcanTypeFileName ifTrue: [s nextPut: 1].\\n\\t\\ts nextPut: dirDepth + typeCount + 1.\\n\\t\\ts nextPut: dirDepth + nameCnt + typeCount + 1]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'zz 8/15/2005 18:18'!\\nmenuSelectionsArray: aDirectory\\n\\\"Answer a menu selections object corresponding to aDirectory. The object is an array corresponding to each item, each element itself constituting a two-element array, the first element of which contains a selector to operate on and the second element of which contains the parameters for that selector.\\\"\\n\\n\\t|dirSize|\\n\\tdirSize := aDirectory pathParts size.\\n\\t^Array streamContents: [:s |\\n\\t\\tcanTypeFileName ifTrue:\\n\\t\\t\\t[s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\tdirectory: aDirectory\\n\\t\\t\\t\\tname: nil)].\\n\\t\\ts nextPut: (StandardFileMenuResult\\n\\t\\t\\tdirectory: (FileDirectory root)\\n\\t\\t\\tname: '').\\n\\t\\taDirectory pathParts doWithIndex: \\n\\t\\t\\t[:d :i | s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\tdirectory: (self \\n\\t\\t\\t\\t\\t\\tadvance: dirSize - i\\n\\t\\t\\t\\t\\t\\tcontainingDirectoriesFrom: aDirectory)\\n\\t\\t\\t\\t\\tname: '')].\\n\\t\\taDirectory directoryNames do: \\n\\t\\t\\t[:dn | s nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\t\\tdirectory: (FileDirectory on: (aDirectory fullNameFor: dn))\\n\\t\\t\\t\\t\\t\\tname: '')].\\n\\t\\taDirectory fileNames do: \\n\\t\\t\\t[:fn | pattern do: [:pat | (pat match: fn) ifTrue: [\\n\\t\\t\\t\\t\\ts nextPut: (StandardFileMenuResult\\n\\t\\t\\t\\t\\t\\tdirectory: aDirectory\\n\\t\\t\\t\\t\\t\\tname: fn)]]]]! !\\n\\n!StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:03'!\\npathPartsString: aDirectory\\n\\\"Answer a string concatenating the path parts strings in aDirectory, each string followed by a cr.\\\"\\n\\n\\t^String streamContents:\\n\\t\\t[:s | \\n\\t\\t\\ts nextPutAll: '[]'; cr.\\n\\t\\t\\taDirectory pathParts asArray doWithIndex: \\n\\t\\t\\t\\t[:part :i |\\n\\t\\t\\t\\t\\ts next: i put: $ .\\n\\t\\t\\t\\t\\ts nextPutAll: part withBlanksTrimmed; cr]]! !\\n\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 00:32'!\\nadvance: anInteger containingDirectoriesFrom: aDirectory\\n\\n\\t| theDirectory |\\n\\ttheDirectory _ aDirectory.\\n\\t1 to: anInteger do: [:i | theDirectory _ theDirectory containingDirectory].\\n\\t^theDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 20:50'!\\ncomputeLabelParagraph\\n\\t\\\"Answer a Paragraph containing this menu's labels, one per line and centered.\\\"\\n\\n\\t^ Paragraph withText: labelString asText style: (MenuStyle leftFlush)! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'!\\nnewFileFrom: aDirectory\\n\\n\\tcanTypeFileName _ true.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 18:25'!\\nnewFileFrom: aDirectory withPatternList: aPatternList\\n\\n\\tcanTypeFileName := true.\\n\\tpattern := aPatternList.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:29'!\\nnewFileFrom: aDirectory withPattern: aPattern\\n\\n\\tcanTypeFileName := true.\\n\\tpattern := {aPattern}.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'!\\noldFileFrom: aDirectory\\n\\n\\tcanTypeFileName _ false.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 17:28'!\\noldFileFrom: aDirectory withPatternList: aPatternList\\n\\n\\tcanTypeFileName := false.\\n\\tpattern := aPatternList.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:28'!\\noldFileFrom: aDirectory withPattern: aPattern\\n\\n\\tcanTypeFileName := false.\\n\\tpattern := {aPattern}.\\n\\t^self makeFileMenuFor: aDirectory! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 17:29'!\\npatternList: aPatternList\\n\\n\\tpattern := aPatternList! !\\n\\n!StandardFileMenu methodsFor: 'private' stamp: 'zz 8/15/2005 16:31'!\\npattern: aPattern\\n\\t\\\" * for all files, or '*.cs' for changeSets, etc. Just like fileLists\\\"\\n\\n\\tpattern := {aPattern}! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileMenu class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:14'!\\nnewFileMenu: aDirectory\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'zz 8/15/2005 18:21'!\\nnewFileMenu: aDirectory withPatternList: aPatternList\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory withPatternList: aPatternList! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'rww 9/23/2001 09:56'!\\nnewFileMenu: aDirectory withPattern: aPattern\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory].\\n\\t^ super new newFileFrom: aDirectory withPattern: aPattern! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:15'!\\noldFileMenu: aDirectory\\n\\tSmalltalk isMorphic ifFalse: [^ PluggableFileList oldFileMenu: aDirectory].\\n\\t^ super new oldFileFrom: aDirectory! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'zz 8/15/2005 17:41'!\\noldFileMenu: aDirectory withPatternList: aPatternList\\n\\n\\tSmalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory].\\n\\t^super new oldFileFrom: aDirectory withPatternList: aPatternList! !\\n\\n!StandardFileMenu class methodsFor: 'instance creation' stamp: 'RAA 5/25/2000 09:30'!\\noldFileMenu: aDirectory withPattern: aPattern\\n\\n\\tSmalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory].\\n\\t^super new oldFileFrom: aDirectory withPattern: aPattern! !\\n\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\nnewFile\\n\\n\\t^self newFileFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'!\\nnewFileFrom: aDirectory\\n\\n\\t^(self newFileMenu: aDirectory)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:18'!\\nnewFileStream\\n\\n\\t^self newFileStreamFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\nnewFileStreamFrom: aDirectory\\n\\n\\t| sfmResult fileStream |\\n\\tsfmResult _ self newFileFrom: aDirectory.\\n\\tsfmResult ifNil: [^nil].\\n\\tfileStream _ sfmResult directory newFileNamed: sfmResult name.\\n\\t[fileStream isNil] whileTrue:\\n\\t\\t[sfmResult _ self newFileFrom: aDirectory.\\n\\t\\tsfmResult ifNil: [^nil].\\n\\t\\tfileStream _ sfmResult directory newFileNamed: sfmResult name].\\n\\t^fileStream\\n! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'!\\noldFile\\n\\n\\t^self oldFileFrom: (FileDirectory default)! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'!\\noldFileFrom: aDirectory\\n\\n\\t^(self oldFileMenu: aDirectory)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'MM 4/6/2004 22:56'!\\noldFileFrom: aDirectory withPattern: aPattern\\n\\\"\\nSelect an existing file from a selection conforming to aPattern.\\n\\\"\\n\\t^(self oldFileMenu: aDirectory withPattern: aPattern)\\n\\t\\tstartUpWithCaption: 'Select a File:' translated! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:17'!\\noldFileStream\\n\\n\\t^self oldFileStreamFrom: (FileDirectory default)\\n! !\\n\\n!StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:27'!\\noldFileStreamFrom: aDirectory\\n\\n\\t| sfmResult fileStream |\\n\\tsfmResult _ self oldFileFrom: aDirectory.\\n\\tsfmResult ifNil: [^nil].\\n\\tfileStream _ sfmResult directory oldFileNamed: sfmResult name.\\n\\t[fileStream isNil] whileTrue:\\n\\t\\t[sfmResult _ self oldFileFrom: aDirectory.\\n\\t\\tsfmResult ifNil: [^nil].\\n\\t\\tfileStream _ sfmResult directory oldFileNamed: sfmResult name].\\n\\t^fileStream\\n! !\\nObject subclass: #StandardFileMenuResult\\n\\tinstanceVariableNames: 'directory name'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-FileList'!\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\ndirectory\\n\\n\\t^directory! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\ndirectory: aDirectory\\n\\n\\t^directory _ aDirectory! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\nname\\n\\n\\t^name! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'!\\nname: aString\\n\\n\\t^name _ aString! !\\n\\n!StandardFileMenuResult methodsFor: 'accessing' stamp: 'sw 6/9/1999 11:50'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: ' with directory: '.\\n\\tdirectory printOn: aStream.\\n\\taStream nextPutAll: ' name: '.\\n\\tname printOn: aStream\\n\\n\\\"StandardFileMenu oldFile\\\"! !\\n\\n\\n!StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 09:05'!\\nisCommand\\n\\n\\t^name isNil! !\\n\\n!StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 20:57'!\\nisDirectory\\n\\n\\t^name = ''! !\\n\\n\\n!StandardFileMenuResult methodsFor: 'private' stamp: 'acg 4/15/1999 08:42'!\\ndirectory: aDirectory name: aString\\n\\n\\tdirectory _ aDirectory.\\n\\tname _ aString.\\n\\t^self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileMenuResult class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileMenuResult class methodsFor: 'instance creation' stamp: 'acg 4/15/1999 08:42'!\\ndirectory: aDirectory name: aString\\n\\n\\t^super new directory: aDirectory name: aString! !\\nFileStream subclass: #StandardFileStream\\n\\tinstanceVariableNames: 'name fileID buffer1'\\n\\tclassVariableNames: 'Registry'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-Kernel'!\\n!StandardFileStream commentStamp: '<historical>' prior: 0!\\nProvides 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!\\n\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:16'!\\ndirectory\\n\\t\\\"Return the directory containing this file.\\\"\\n\\n\\t^ FileDirectory forFileName: self fullName\\n! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'tk 3/14/2000 23:31'!\\ndirectoryUrl\\n\\n\\t^ self directory url! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nfile\\n\\t\\\"Answer the object representing the receiver's file. Need for compatibility with some calls -- check senders. 2/14/96 sw\\\"\\n\\n\\t^ self! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'!\\nfullName\\n\\t\\\"Answer this file's full path name.\\\"\\n\\n\\t^ name\\n! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nisDirectory\\n\\t\\\"Answer whether the receiver represents a directory. For the post-transition case, uncertain what to do. 2/14/96 sw\\\"\\n\\t^ false! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'ar 11/24/1998 14:00'!\\nlocalName\\n\\t^ name ifNotNil: [(name findTokens: FileDirectory pathNameDelimiter asString) last]! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'!\\nname\\n\\t\\\"Answer this file's full path name.\\\"\\n\\n\\t^ name\\n! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npeekFor: item \\n\\t\\\"Answer false and do not advance if the next element is not equal to item, or if this stream is at the end. If the next element is equal to item, then advance over it and return true\\\"\\n\\t| next |\\n\\t\\\"self atEnd ifTrue: [^ false]. -- SFStream will give nil\\\"\\n\\t(next := self next) == nil ifTrue: [^ false].\\n\\titem = next ifTrue: [^ true].\\n\\tself skip: -1.\\n\\t^ false! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nprintOn: aStream\\n\\t\\\"Put a printed version of the receiver onto aStream. 1/31/96 sw\\\"\\n\\n\\taStream nextPutAll: self class name; nextPutAll: ': '; print: name! !\\n\\n!StandardFileStream methodsFor: 'access' stamp: 'ar 6/16/2002 18:58'!\\nreset\\n\\tself ensureOpen.\\n\\tself position: 0.! !\\n\\n!StandardFileStream methodsFor: 'access'!\\nsize\\n\\t\\\"Answer the size of the file in characters. 2/12/96 sw\\\"\\n\\n\\t^ self primSize: fileID! !\\n\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 1/11/2000 10:44'!\\ndefaultBrowserReadyWait\\n\\t^5000! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npost: data target: target url: url ifError: errorBlock\\n\\t\\\"Post data to the given URL. The returned file stream contains the reply of the server.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLPost: url target: target data: data semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tresult ifTrue:[fileID := self primURLRequestFileHandle: request].\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 2/2/2001 14:22'!\\npost: data url: url ifError: errorBlock\\n\\n\\tself post: data target: nil url: url ifError: errorBlock! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'ar 2/26/2001 15:58'!\\nprimBrowserReady\\n\\t<primitive:'primitivePluginBrowserReady'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 9/21/2000 16:58'!\\nprimURLPost: url data: contents semaIndex: index\\n\\t^self primURLPost: url target: nil data: contents semaIndex: index! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 9/21/2000 16:58'!\\nprimURLPost: url target: target data: contents semaIndex: index\\n\\t\\\"Post the data (url might be 'mailto:' etc)\\\"\\n\\t<primitive:'primitivePluginPostURL'>\\n\\t^nil\\n ! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequest: url semaIndex: index\\n\\t<primitive:'primitivePluginRequestURLStream'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nprimURLRequest: url target: target semaIndex: index\\n\\t\\\"target - String (frame, also ':=top', ':=parent' etc)\\\"\\n\\t<primitive:'primitivePluginRequestURL'>\\n\\t^nil\\n ! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestDestroy: request\\n\\t<primitive:'primitivePluginDestroyRequest'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestFileHandle: request\\n\\t<primitive: 'primitivePluginRequestFileHandle'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nprimURLRequestState: request\\n\\t<primitive:'primitivePluginRequestState'>\\n\\t^false! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'mir 2/29/2000 11:22'!\\nrequestURL: url target: target\\n\\t^self requestURL: url target: target ifError: [nil]! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestURL: url target: target ifError: errorBlock\\n\\t\\\"Request to go to the target for the given URL.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLRequest: url target: target semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests'!\\nrequestURLStream: url\\n\\t\\\"FileStream requestURLStream:'http://www.squeak.org'\\\"\\n\\t^self requestURLStream: url ifError:[nil]! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestURLStream: url ifError: errorBlock\\n\\t\\\"Request a FileStream for the given URL.\\n\\tIf Squeak is not running in a browser evaluate errorBlock\\\"\\n\\t\\\"FileStream requestURLStream:'http://www.squeak.org'\\\"\\n\\t| sema index request result |\\n\\tself waitBrowserReadyFor: self defaultBrowserReadyWait ifFail: [^errorBlock value].\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\trequest := self primURLRequest: url semaIndex: index.\\n\\trequest == nil ifTrue:[\\n\\t\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t^errorBlock value.\\n\\t] ifFalse:[\\n\\t\\t[sema wait. \\\"until something happens\\\"\\n\\t\\tresult := self primURLRequestState: request.\\n\\t\\tresult == nil] whileTrue.\\n\\t\\tresult ifTrue:[fileID := self primURLRequestFileHandle: request].\\n\\t\\tself primURLRequestDestroy: request.\\n\\t].\\n\\tSmalltalk unregisterExternalObject: sema.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\tname := url.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.! !\\n\\n!StandardFileStream methodsFor: 'browser requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nwaitBrowserReadyFor: timeout ifFail: errorBlock\\n\\t| startTime delay okay |\\n\\tokay := self primBrowserReady.\\n\\tokay ifNil:[^errorBlock value].\\n\\tokay ifTrue: [^true].\\n\\tstartTime := Time millisecondClockValue.\\n\\tdelay := Delay forMilliseconds: 100.\\n\\t[(Time millisecondsSince: startTime) < timeout]\\n\\t\\twhileTrue: [\\n\\t\\t\\tdelay wait.\\n\\t\\t\\tokay := self primBrowserReady.\\n\\t\\t\\tokay ifNil:[^errorBlock value].\\n\\t\\t\\tokay ifTrue: [^true]].\\n\\t^errorBlock value! !\\n\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'ar 1/10/2001 20:01'!\\nprimDropRequestFileHandle: dropIndex\\n\\t\\\"Primitive. Return the (read-only) file handle for some file that was just dropped onto Squeak.\\n\\tFail if dropIndex is out of range or the primitive is not supported.\\\"\\n\\t<primitive: 'primitiveDropRequestFileHandle' module:'DropPlugin'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'ar 1/10/2001 20:01'!\\nprimDropRequestFileName: dropIndex\\n\\t\\\"Primitive. Return the file name for some file that was just dropped onto Squeak.\\n\\tFail if dropIndex is out of range or the primitive is not supported.\\\"\\n\\t<primitive: 'primitiveDropRequestFileName' module:'DropPlugin'>\\n\\t^nil! !\\n\\n!StandardFileStream methodsFor: 'dnd requests' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nrequestDropStream: dropIndex\\n\\t\\\"Return a read-only stream for some file the user has just dropped onto Squeak.\\\"\\n\\tname := self primDropRequestFileName: dropIndex.\\n\\tfileID := self primDropRequestFileHandle: dropIndex.\\n\\tfileID == nil ifTrue:[^nil].\\n\\tself register.\\n\\trwmode := false.\\n\\tbuffer1 := String new: 1.\\n\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'finalization' stamp: 'ar 3/21/98 18:16'!\\nactAsExecutor\\n\\tsuper actAsExecutor.\\n\\tname := nil.! !\\n\\n!StandardFileStream methodsFor: 'finalization' stamp: 'ar 10/7/1998 15:44'!\\nfinalize\\n\\tself primCloseNoError: fileID.! !\\n\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nclose\\n\\t\\\"Close this file.\\\"\\n\\n\\tfileID ifNotNil: [\\n\\t\\tself primClose: fileID.\\n\\t\\tself unregister.\\n\\t\\tfileID := nil].\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 2/6/2002 08:33'!\\nclosed\\n\\t\\\"Answer true if this file is closed.\\\"\\n\\n\\t^ fileID isNil or: [(self primSizeNoError: fileID) isNil]\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 16:20'!\\nensureOpen\\n\\t\\\"Make sure that this file really is open.\\\"\\n\\n\\tself closed ifTrue: [^ self reopen].\\n\\t(self primSizeNoError: fileID) ifNotNil: [^ self].\\n\\tself reopen.\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close'!\\nopen\\n\\t\\\"For compatibility with a few existing things. 2/14/96 sw\\\"\\n\\n\\t^ self reopen! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nopen: fileName forWrite: writeMode \\n\\t\\\"Open the file with the given name. If writeMode is true, allow writing, otherwise open the file in read-only mode.\\\"\\n\\t\\\"Changed to do a GC and retry before failing ar 3/21/98 17:25\\\"\\n\\t| f |\\n\\tf := fileName asVmPathName.\\n\\n\\tfileID := StandardFileStream retryWithGC:[self primOpen: f writable: writeMode] \\n\\t\\t\\t\\t\\tuntil:[:id| id notNil] \\n\\t\\t\\t\\t\\tforFileNamed: fileName.\\n\\tfileID ifNil: [^ nil]. \\\"allows sender to detect failure\\\"\\n\\tself register.\\n\\tname := fileName.\\n\\trwmode := writeMode.\\n\\tbuffer1 := String new: 1.\\n! !\\n\\n!StandardFileStream methodsFor: 'open/close'!\\nopenReadOnly\\n\\t\\\"Open the receiver as a read-only file. 1/31/96 sw\\\"\\n\\n\\t^ self open: name forWrite: false! !\\n\\n!StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 13:58'!\\nreopen\\n\\t\\\"Close and reopen this file. The file position is reset to zero.\\\"\\n\\t\\\"Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened.\\\"\\n\\n\\tfileID ifNotNil: [self primCloseNoError: fileID].\\n\\tself open: name forWrite: rwmode.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimAtEnd: id\\n\\t\\\"Answer true if the file position is at the end of the file.\\\"\\n\\n\\t<primitive: 'primitiveFileAtEnd' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimClose: id\\n\\t\\\"Close this file.\\\"\\n\\n\\t<primitive: 'primitiveFileClose' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimCloseNoError: id\\n\\t\\\"Close this file. Don't raise an error if the primitive fails.\\\"\\n\\n\\t<primitive: 'primitiveFileClose' module: 'FilePlugin'>\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nprimFlush: id\\n\\t\\\"Flush pending changes to the disk\\\"\\n\\t| p |\\n\\t<primitive: 'primitiveFileFlush' module: 'FilePlugin'>\\n\\t\\\"In some OS's seeking to 0 and back will do a flush\\\"\\n\\tp := self position.\\n\\tself position: 0; position: p! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimGetPosition: id\\n\\t\\\"Get this files current position.\\\"\\n\\n\\t<primitive: 'primitiveFileGetPosition' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimOpen: fileName writable: writableFlag\\n\\t\\\"Open a file of the given name, and return the file ID obtained.\\n\\tIf writableFlag is true, then\\n\\t\\tif there is none with this name, then create one\\n\\t\\telse prepare to overwrite the existing from the beginning\\n\\totherwise\\n\\t\\tif the file exists, open it read-only\\n\\t\\telse return nil\\\"\\n\\n\\t<primitive: 'primitiveFileOpen' module: 'FilePlugin'>\\n\\t^ nil\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimRead: id into: byteArray startingAt: startIndex count: count\\n\\t\\\"Read up to count bytes of data from this file into the given string or byte array starting at the given index. Answer the number of bytes actually read.\\\"\\n\\n\\t<primitive: 'primitiveFileRead' module: 'FilePlugin'>\\n\\tself closed ifTrue: [^ self error: 'File is closed'].\\n\\tself error: 'File read failed'.\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSetPosition: id to: anInteger\\n\\t\\\"Set this file to the given position.\\\"\\n\\n\\t<primitive: 'primitiveFileSetPosition' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSize: id\\n\\t\\\"Answer the size of this file.\\\"\\n\\n\\t<primitive: 'primitiveFileSize' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimSizeNoError: id\\n\\t\\\"Answer the size of this file. Answer nil if the primitive fails; this indicates that the file handle has become stale.\\\"\\n\\n\\t<primitive: 'primitiveFileSize' module: 'FilePlugin'>\\n\\t^ nil\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'JMM 5/24/2001 21:55'!\\nprimTruncate: id to: anInteger\\n\\t\\\"Truncate this file to the given position.\\\"\\n\\n\\t<primitive: 'primitiveFileTruncate' module: 'FilePlugin'>\\n\\tself primitiveFailed\\n! !\\n\\n!StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'!\\nprimWrite: id from: stringOrByteArray startingAt: startIndex count: count\\n\\t\\\"Write count bytes onto this file from the given string or byte array starting at the given index. Answer the number of bytes written.\\\"\\n\\n\\t<primitive: 'primitiveFileWrite' module: 'FilePlugin'>\\n\\tself closed ifTrue: [^ self error: 'File is closed'].\\n\\tself error: 'File write failed'.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'properties-setting'!\\nasHtml\\n\\t\\\"Convert me in to an HtmlFileStream. 4/11/96 tk\\\"\\n\\n\\t^ self as: HtmlFileStream \\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nascii\\n\\t\\\"opposite of binary\\\"\\n\\tbuffer1 := String new: 1! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nbinary\\n\\tbuffer1 := ByteArray new: 1! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'JMM 1/28/2001 18:44'!\\ngetFileType\\n\\t\\\"On the Macintosh, get the file type and creator of this file. On other platforms, do nothing.\\\"\\n\\n\\t^FileDirectory default\\n\\t\\tgetMacFileTypeAndCreator: self fullName\\n\\t\\t\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninsertLineFeeds\\n\\t\\\"(FileStream oldFileNamed: 'BBfix2.st') insertLineFeeds\\\"\\n\\t| s crLf f |\\n\\tcrLf := String with: Character cr with: (Character value: 10).\\n\\ts := ReadStream on: (self next: self size).\\n\\tself close.\\n\\tf := FileStream newFileNamed: self name.\\n\\t[s atEnd] whileFalse: \\n\\t\\t[f nextPutAll: (s upTo: Character cr); nextPutAll: crLf].\\n\\tf close! !\\n\\n!StandardFileStream methodsFor: 'properties-setting'!\\nisBinary\\n\\t^ buffer1 class == ByteArray! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'tk 11/4/1998 19:17'!\\nisReadOnly\\n\\n\\t^ rwmode not\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnly\\n\\t\\\"Make this file read-only.\\\"\\n\\n\\trwmode := false.\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadWrite\\n\\t\\\"Make this file writable.\\\"\\n\\n\\trwmode := true.\\n! !\\n\\n!StandardFileStream methodsFor: 'properties-setting' stamp: 'jm 12/5/97 15:14'!\\nsetFileTypeToObject\\n\\t\\\"On the Macintosh, set the file type and creator of this file to be a Squeak object file. On other platforms, do nothing. Setting the file type allows Squeak object files to be sent as email attachments and launched by double-clicking. On other platforms, similar behavior is achieved by creating the file with the '.sqo' file name extension.\\\"\\n\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: self fullName\\n\\t\\ttype: 'SOBJ'\\n\\t\\tcreator: 'FAST'.\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'sw 2/12/96'!\\natEnd\\n\\t\\\"Answer whether the receiver is at its end. \\\"\\n\\t^ self primAtEnd: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nbasicNext\\n\\t\\\"Answer the next byte from this file, or nil if at the end of the file.\\\"\\n\\n\\t| count |\\n\\tcount := self primRead: fileID into: buffer1 startingAt: 1 count: 1.\\n\\tcount = 1\\n\\t\\tifTrue: [^ buffer1 at: 1]\\n\\t\\tifFalse: [^ nil].\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ncompressFile\\n\\t\\\"Write a new file that has the data in me compressed in GZip format.\\\"\\n\\t| zipped buffer |\\n\\n\\tself readOnly; binary.\\n\\tzipped := self directory newFileNamed: (self name, FileDirectory dot, 'gz').\\n\\tzipped binary; setFileTypeToObject.\\n\\t\\t\\\"Type and Creator not to be text, so can be enclosed in an email\\\"\\n\\tzipped := GZipWriteStream on: zipped.\\n\\tbuffer := ByteArray new: 50000.\\n\\t'Compressing ', self fullName displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: self size\\n\\t\\tduring: [:bar |\\n\\t\\t\\t[self atEnd] whileFalse: [\\n\\t\\t\\t\\tbar value: self position.\\n\\t\\t\\t\\tzipped nextPutAll: (self nextInto: buffer)].\\n\\t\\t\\tzipped close.\\n\\t\\t\\tself close].\\n\\t^zipped! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfindString: string\\n\\t\\\"Fast version of #upToAll: to find a String in a file starting from the beginning.\\n\\tReturns the position and also sets the position there.\\n\\tIf string is not found 0 is returned and position is unchanged.\\\"\\n\\n\\t| pos buffer count oldPos sz |\\n\\toldPos := self position.\\n\\tself reset.\\n\\tsz := self size.\\n\\tpos := 0.\\n\\tbuffer := String new: 2000.\\n\\t[ buffer := self nextInto: buffer.\\n\\t(count := buffer findString: string) > 0\\n\\t\\tifTrue: [\\\"Found the string part way into buffer\\\"\\n\\t\\t\\tself position: pos.\\n\\t\\t\\tself next: count - 1.\\n\\t\\t\\t^self position ].\\n\\tpos := ((pos + 2000 - string size) min: sz).\\n\\tself position: pos.\\n\\tpos = sz] whileFalse.\\n\\t\\\"Never found it, and hit end of file\\\"\\n\\tself position: oldPos.\\n\\t^0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfindStringFromEnd: string\\n\\t\\\"Fast version to find a String in a file starting from the end.\\n\\tReturns the position and also sets the position there.\\n\\tIf string is not found 0 is returned and position is unchanged.\\\"\\n\\n\\t| pos buffer count oldPos |\\n\\toldPos := self position.\\n\\tself setToEnd.\\n\\tpos := self position.\\n\\t[ pos := ((pos - 2000 + string size) max: 0). \\\"the [+ string size] allows for the case where the end of the search string is at the beginning of the current buffer\\\"\\n\\tself position: pos.\\n\\tbuffer := self next: 2000.\\n\\t(count := buffer findString: string) > 0\\n\\t\\tifTrue: [\\\"Found the string part way into buffer\\\"\\n\\t\\t\\tself position: pos.\\n\\t\\t\\tself next: count-1. \\\"use next instead of position:, so that CrLfFileStream can do its magic if it is being used\\\"\\n\\t\\t\\t^self position].\\n\\tpos = 0] whileFalse.\\n\\t\\\"Never found it, and hit beginning of file\\\"\\n\\tself position: oldPos.\\n\\t^0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 2/6/2001 17:59'!\\nflush\\n\\t\\\"Flush pending changes\\\"\\n\\t^self primFlush: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'mir 2/25/2000 12:37'!\\nnext\\n\\t\\\"Answer the next byte from this file, or nil if at the end of the file.\\\"\\n\\n\\t^ self basicNext! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nnext: n\\n\\t\\\"Return a string with the next n characters of the filestream in it. 1/31/96 sw\\\"\\n\\t^ self nextInto: (buffer1 class new: n)! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nnext: n into: aString startingAt: startIndex\\n\\t\\\"Read n bytes into the given string.\\n\\tReturn aString or a partial copy if less than\\n\\tn elements have been read.\\\"\\n\\t| count |\\n\\tcount := self primRead: fileID into: aString\\n\\t\\t\\t\\tstartingAt: startIndex count: n.\\n\\tcount = n\\n\\t\\tifTrue:[^aString]\\n\\t\\tifFalse:[^aString copyFrom: 1 to: startIndex+count-1]! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 1/2/2000 15:33'!\\nnext: anInteger putAll: aString startingAt: startIndex\\n\\t\\\"Store the next anInteger elements from the given collection.\\\"\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tself primWrite: fileID from: aString startingAt: startIndex count: anInteger.\\n\\t^aString! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'jm 9/21/1998 13:55'!\\nnextPut: char\\n\\t\\\"Write the given character to this file.\\\"\\n\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tbuffer1 at: 1 put: char.\\n\\tself primWrite: fileID from: buffer1 startingAt: 1 count: 1.\\n\\t^ char\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:43'!\\nnextPutAll: aString\\n\\t\\\"Write all the characters of the given string to this file.\\\"\\n\\n\\trwmode ifFalse: [^ self error: 'Cannot write a read-only file'].\\n\\tself primWrite: fileID from: aString startingAt: 1 count: aString basicSize.\\n\\t^ aString\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:58'!\\nnextWordsInto: aBitmap\\n\\t\\\"Note: The file primitives automatically adjust for word based objects.\\\"\\n\\n\\tself next: aBitmap basicSize into: aBitmap startingAt: 1.\\n\\taBitmap restoreEndianness.\\n\\t^ aBitmap! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npadToEndWith: aChar\\n\\t\\\"On the Mac, files do not truncate. One can delete the old file and write a new one, but sometime deletion fails (file still open? file stale?). This is a sad compromise. Just let the file be the same length but pad it with a harmless character.\\\"\\n\\n\\t| pad |\\n\\tself atEnd ifTrue: [^ self].\\n\\tpad := self isBinary \\n\\t\\tifTrue: [aChar asCharacter asciiValue]\\t\\\"ok for char or number\\\"\\n\\t\\tifFalse: [aChar asCharacter].\\n\\tself nextPutAll: (buffer1 class new: ((self size - self position) min: 20000) \\n\\t\\t\\t\\t\\t\\t\\twithAll: pad).! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\npeek\\n\\t\\\"Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. \\\"\\n\\t| next |\\n\\tself atEnd ifTrue: [^ nil].\\n\\tnext := self basicNext.\\n\\tself position: self position - 1.\\n\\t^ next! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 10/19/2001 11:29'!\\npeekLast\\n\\t\\\"Return that item just put at the end of the stream\\\"\\n\\n\\t^ buffer1 size > 0 \\n\\t\\tifTrue: [buffer1 last]\\n\\t\\tifFalse: [nil]\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nposition\\n\\t\\\"Return the receiver's current file position. 2/12/96 sw\\\"\\n\\n\\t^ self primGetPosition: fileID! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nposition: pos\\n\\t\\\"Set the receiver's position as indicated. 2/12/96 sw\\\"\\n\\n\\t^ self primSetPosition: fileID to: pos! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nreadInto: byteArray startingAt: startIndex count: count\\n\\t\\\"Read into the given array as specified, and return the count\\n\\tactually transferred. index and count are in units of bytes or\\n\\tlongs depending on whether the array is Bitmap, String or ByteArray\\\"\\n\\t^ self primRead: fileID into: byteArray\\n\\t\\t\\tstartingAt: startIndex count: count\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'yo 10/31/2002 22:33'!\\nreadOnlyCopy\\n\\n\\t^ self class readOnlyFileNamed: self name.\\n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nsetToEnd\\n\\t\\\"Set the position of the receiver to the end of file. 1/31/96 sw\\\"\\n\\n\\tself position: self size! !\\n\\n!StandardFileStream methodsFor: 'read, write, position'!\\nskip: n\\n\\t\\\"Set the character position to n characters from the current position.\\n\\tError if not enough characters left in the file. 1/31/96 sw\\\"\\n\\n\\tself position: self position + n! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'JMM 5/24/2001 22:00'!\\ntruncate\\n\\t\\\"Truncate to zero\\\"\\n\\n\\t^ self truncate: 0! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'JMM 5/24/2001 22:47'!\\ntruncate: pos\\n\\t\\\"Truncate to this position\\\"\\n\\n\\tself position: pos.\\n\\t^self primTruncate: fileID to: pos! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nupTo: delim \\n\\t\\\"Fast version to speed up nextChunk\\\"\\n\\t| pos buffer count |\\n\\tpos := self position.\\n\\tbuffer := self next: 2000.\\n\\t(count := buffer indexOf: delim) > 0 ifTrue: \\n\\t\\t[\\\"Found the delimiter part way into buffer\\\"\\n\\t\\tself position: pos + count.\\n\\t\\t^ buffer copyFrom: 1 to: count - 1].\\n\\tself atEnd ifTrue:\\n\\t\\t[\\\"Never found it, and hit end of file\\\"\\n\\t\\t^ buffer].\\n\\t\\\"Never found it, but there's more...\\\"\\n\\t^ buffer , (self upTo: delim)! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nupToEnd\\n\\t\\\"Answer a subcollection from the current access position through the last element of the receiver.\\\"\\n\\n\\t| newStream buffer |\\n\\tbuffer := buffer1 species new: 1000.\\n\\tnewStream := WriteStream on: (buffer1 species new: 100).\\n\\t[self atEnd] whileFalse: [newStream nextPutAll: (self nextInto: buffer)].\\n\\t^ newStream contents! !\\n\\n!StandardFileStream methodsFor: 'read, write, position' stamp: 'jm 9/21/1998 13:56'!\\nverbatim: aString\\n\\t\\\"A version of nextPutAll that can be called knowing it won't call nextPut: \\\"\\n\\n\\t^ self nextPutAll: aString\\n! !\\n\\n\\n!StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'!\\nregister\\n\\t^self class register: self! !\\n\\n!StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'!\\nunregister\\n\\t^self class unregister: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardFileStream class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardFileStream class methodsFor: 'browser requests' stamp: 'mir 3/8/2001 16:28'!\\nisRunningAsBrowserPlugin\\n\\tself new waitBrowserReadyFor: 1000 ifFail: [^false].\\n\\t^true! !\\n\\n!StandardFileStream class methodsFor: 'browser requests' stamp: 'mir 9/7/2000 16:08'!\\nprivateCheckForBrowserPrimitives\\n\\t<primitive:'primitivePluginBrowserReady'>\\n\\t^false! !\\n\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileDoesNotExistUserHandling: fullFileName\\n\\n\\t| selection newName |\\n\\tselection := (PopUpMenu labels:\\n'create a new file\\nchoose another name\\ncancel')\\n\\t\\t\\tstartUpWithCaption: (FileDirectory localNameFor: fullFileName) , '\\ndoes not exist.'.\\n\\tselection = 1 ifTrue:\\n\\t\\t[^ self new open: fullFileName forWrite: true].\\n\\tselection = 2 ifTrue:\\n\\t\\t[ newName := FillInTheBlank request: 'Enter a new file name'\\n\\t\\t\\t\\t\\t\\tinitialAnswer: fullFileName.\\n\\t\\t^ self oldFileNamed:\\n\\t\\t\\t(self fullName: newName)].\\n\\tself halt! !\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileExistsUserHandling: fullFileName\\n\\t| dir localName choice newName newFullFileName |\\n\\tdir := FileDirectory forFileName: fullFileName.\\n\\tlocalName := FileDirectory localNameFor: fullFileName.\\n\\tchoice := (PopUpMenu\\n\\t\\tlabels:\\n'overwrite that file\\\\choose another name\\\\cancel' withCRs)\\n\\t\\tstartUpWithCaption: localName, '\\nalready exists.'.\\n\\n\\tchoice = 1 ifTrue: [\\n\\t\\tdir deleteFileNamed: localName\\n\\t\\t\\tifAbsent: [self error: 'Could not delete the old version of that file'].\\n\\t\\t^ self new open: fullFileName forWrite: true].\\n\\n\\tchoice = 2 ifTrue: [\\n\\t\\tnewName := FillInTheBlank request: 'Enter a new file name' initialAnswer: fullFileName.\\n\\t\\tnewFullFileName := self fullName: newName.\\n\\t\\t^ self newFileNamed: newFullFileName].\\n\\n\\tself error: 'Please close this to abort file opening'! !\\n\\n!StandardFileStream class methodsFor: 'error handling' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnlyFileDoesNotExistUserHandling: fullFileName\\n\\n\\t| dir files choices selection newName fileName |\\n\\tdir := FileDirectory forFileName: fullFileName.\\n\\tfiles := dir fileNames.\\n\\tfileName := FileDirectory localNameFor: fullFileName.\\n\\tchoices := fileName correctAgainst: files.\\n\\tchoices add: 'Choose another name'.\\n\\tchoices add: 'Cancel'.\\n\\tselection := (PopUpMenu labelArray: choices lines: (Array with: 5) )\\n\\t\\tstartUpWithCaption: (FileDirectory localNameFor: fullFileName), '\\ndoes not exist.'.\\n\\tselection = choices size ifTrue:[\\\"cancel\\\" ^ nil \\\"should we raise another exception here?\\\"].\\n\\tselection < (choices size - 1) ifTrue: [\\n\\t\\tnewName := (dir pathName , FileDirectory slash , (choices at: selection))].\\n\\tselection = (choices size - 1) ifTrue: [\\n\\t\\tnewName := FillInTheBlank \\n\\t\\t\\t\\t\\t\\t\\trequest: 'Enter a new file name' \\n\\t\\t\\t\\t\\t\\t\\tinitialAnswer: fileName].\\n\\tnewName = '' ifFalse: [^ self readOnlyFileNamed: (self fullName: newName)].\\n\\t^ self error: 'Could not open a file'! !\\n\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'TPR 8/13/1999 21:22'!\\nfileNamed: fileName\\n\\t\\\"Open a file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close.\\\"\\n\\n\\t^ self new open: (self fullName: fileName) forWrite: true\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nforceNewFileNamed: fileName \\n\\t\\\"Create a new file with the given name, and answer a stream opened \\n\\tfor writing on that file. If the file already exists, delete it without \\n\\tasking before creating the new file.\\\"\\n\\t| dir localName fullName f |\\n\\tfullName := self fullName: fileName.\\n\\t(self isAFileNamed: fullName)\\n\\t\\tifFalse: [f := self new open: fullName forWrite: true.\\n\\t\\t\\t^ f isNil\\n\\t\\t\\t\\tifTrue: [\\\"Failed to open the file\\\"\\n\\t\\t\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]\\n\\t\\t\\t\\tifFalse: [f]].\\n\\tdir := FileDirectory forFileName: fullName.\\n\\tlocalName := FileDirectory localNameFor: fullName.\\n\\tdir\\n\\t\\tdeleteFileNamed: localName\\n\\t\\tifAbsent: [(CannotDeleteFileException new\\n\\t\\t\\tmessageText: 'Could not delete the old version of file ' , fullName) signal].\\n\\tf := self new open: fullName forWrite: true.\\n\\t^ f isNil\\n\\t\\tifTrue: [\\\"Failed to open the file\\\"\\n\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]\\n\\t\\tifFalse: [f]! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nisAFileNamed: fileName\\n\\t\\\"Answer true if a file of the given name exists.\\\"\\n\\n\\t| f |\\n\\tf := self new open: fileName forWrite: false.\\n\\tf ifNil: [^ false].\\n\\tf close.\\n\\t^ true\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nnewFileNamed: fileName\\n \\t\\\"Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, ask the user what to do.\\\"\\n\\n\\t| fullName |\\n\\tfullName := self fullName: fileName.\\n\\n\\t^(self isAFileNamed: fullName)\\n\\t\\tifTrue: [\\\"file already exists:\\\"\\n\\t\\t\\t(FileExistsException fileName: fullName fileClass: self) signal]\\n\\t\\tifFalse: [self new open: fullName forWrite: true]\\n\\n! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\noldFileNamed: fileName\\n\\t\\\"Open an existing file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close.\\\"\\n\\n\\t| fullName |\\n\\tfullName := self fullName: fileName.\\n\\n\\t^(self isAFileNamed: fullName)\\n\\t\\tifTrue: [self new open: fullName forWrite: true]\\n\\t\\tifFalse: [\\\"File does not exist...\\\"\\n\\t\\t\\t(FileDoesNotExistException fileName: fullName) signal]! !\\n\\n!StandardFileStream class methodsFor: 'file creation' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nreadOnlyFileNamed: fileName \\n\\t\\\"Open an existing file with the given name for reading.\\\"\\n\\n\\t| fullName f |\\n\\tfullName := self fullName: fileName.\\n\\tf := self new open: fullName forWrite: false.\\n\\t^ f isNil\\n\\t\\tifFalse: [f]\\n\\t\\tifTrue: [\\\"File does not exist...\\\"\\n\\t\\t\\t((FileDoesNotExistException fileName: fullName) readOnly: true) signal].\\n\\n\\t\\\"StandardFileStream readOnlyFileNamed: 'kjsd.txt' \\\"! !\\n\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'!\\nregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry add: anObject! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'!\\nregistry\\n\\tWeakArray isFinalizationSupported ifFalse:[^nil].\\n\\t^Registry isNil\\n\\t\\tifTrue:[Registry := WeakRegistry new]\\n\\t\\tifFalse:[Registry].! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nretryWithGC: execBlock until: testBlock forFileNamed: fullName\\n\\t\\\"Re-implemented to only force GC if a file with the given name exists\\\"\\n\\t| blockValue foundIt |\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\t\\\"See if we have a file with the given name\\\"\\n\\tfoundIt := Registry keys \\\"hold on strongly for now\\\" \\n\\t\\tanySatisfy:[:file| file name sameAs: fullName].\\n\\tfoundIt ifFalse:[^blockValue].\\n\\tSmalltalk garbageCollectMost.\\n\\tblockValue := execBlock value.\\n\\t(testBlock value: blockValue) ifTrue:[^blockValue].\\n\\tSmalltalk garbageCollect.\\n\\t^execBlock value.! !\\n\\n!StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:23'!\\nunregister: anObject\\n\\tWeakArray isFinalizationSupported ifFalse:[^anObject].\\n\\tself registry remove: anObject ifAbsent:[]! !\\nObject subclass: #StandardScriptingSystem\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'ClassVarNamesInUse FormDictionary HelpStrings StandardPartsBin'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Refactoring Candidates'!\\n!StandardScriptingSystem commentStamp: '<historical>' prior: 0!\\nAn instance of this is installed as the value of the global variable \\\"ScriptingSystem\\\". Client subclasses are invited, such as one used internally by squeak team for ongoing internal work.!\\n\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:45'!\\ndeletePrivateGraphics\\n\\t\\\"ScriptingSystem deletePrivateGraphics\\\"\\n\\tself deletePrivateGraphics: self privateGraphics\\n\\t\\tafterStoringToFileNamed: 'disGraphics'! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'di 2/3/2001 20:10'!\\ndeletePrivateGraphics: nameList afterStoringToFileNamed: aFileName\\n\\t\\\"This method is used to strip private graphics from the FormDictionary and store them on a file of the given name\\\"\\n\\n\\t| replacement toRemove aReferenceStream keySymbol |\\n\\ttoRemove _ Dictionary new.\\n\\treplacement _ FormDictionary at: #Gets.\\n\\n\\tnameList do:\\n\\t\\t[:aKey |\\n\\t\\t\\tkeySymbol _ aKey asSymbol.\\n\\t\\t\\t(toRemove at: keySymbol put: (self formAtKey: keySymbol)).\\n\\t\\t\\tFormDictionary at: keySymbol put: replacement].\\n\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\taReferenceStream nextPut: toRemove.\\n\\taReferenceStream close! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 2/24/2003 16:28'!\\nformAtKey: aString\\n\\t\\\"Answer the form saved under the given key\\\"\\n\\n\\tSymbol hasInterned: aString ifTrue:\\n\\t\\t[:aKey | ^ FormDictionary at: aKey ifAbsent: [nil]].\\n\\t^ nil! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:46'!\\nformAtKey: aKey extent: extent depth: depth\\n\\t\\\"ScriptingSystem saveForm: (TileMorph downPicture) atKey: 'downArrow'\\\"\\n\\t^ FormDictionary at: aKey asSymbol ifAbsent: [Form extent: extent depth: depth]! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:49'!\\nformDictionary\\n\\t^FormDictionary! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sd 5/11/2003 21:32'!\\ninspectFormDictionary\\n\\t\\\"ScriptingSystem inspectFormDictionary\\\"\\n\\t\\n\\tGraphicalDictionaryMenu openOn: FormDictionary withLabel: 'Testing One Two Three'! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'ar 3/3/2001 19:44'!\\nprivateGraphics\\n\\t\\\"ScriptingSystem deletePrivateGraphics\\\"\\n\\t^#(#BadgeMiniPic #BadgePic #Broom #CedarPic #CollagePic #CoverMain #CoverSpiral #CoverTexture #Fred #ImagiPic #KayaPic #StudioPic)! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 10/6/1999 20:57'!\\nsaveForm: aForm atKey: aKey\\n\\tFormDictionary at: aKey asSymbol put: aForm! !\\n\\n!StandardScriptingSystem methodsFor: 'form dictionary' stamp: 'sw 10/24/1998 14:12'!\\nsqueakyMouseForm\\n\\t^ self formAtKey: 'squeakyMouse'\\n\\n\\\"\\n\\tScriptingSystem saveForm: (Form\\n\\textent: 30@29\\n\\tdepth: 16\\n\\tfromArray: #( 1811114995 1878286257 2012637171 1811180532 1811180533 1811179508 1811180532 1811179508 1744006133 1878289396 1811180533 1878289396 1744007156 1674736630 1744006132 1811114995 1811181556 1744006131 1811246068 1811180532 1811179508 1811180532 1744071668 1811113972 1811180532 1811180532 1811179507 1878288338 1945529332 1744071668 1743941620 1811112945 1811179506 1811114995 1744006131 1744006130 1744005106 1811048434 1811113969 1743939570 1811179506 1743939571 1676833782 1676765171 1811047410 1744006131 1811048435 1811116020 1811180531 1743939571 1811048435 1743939570 1743939570 1743939570 1743940594 1744005106 1811181556 1811180532 1676766196 1743939570 1878420468 1676963830 1189896082 1811245044 1744137204 1744070644 1811179508 1811113971 1743939571 1811179508 1811246070 1811309524 1811302093 1811310580 1811246068 1674867703 1744049472 1120606594 1118465013 1744137205 1811179508 1811180532 1744071667 1744006132 1811112947 1811247095 1605584589 358761132 289435638 1676830707 1741975543 1462778473 1811312631 702891724 1811310548 1945528308 1811178450 1945528307 1878288372 1878353875 1878421494 1051471335 1809213397 1118524175 1811246068 1945659348 1185698607 1878486005 1672694510 1118531574 1607626741 1878420467 1811180533 1743942645 1744072693 1811301035 1185770487 1878486006 1324239597 1811180533 1811116019 1120623438 1878352818 1945462739 704868339 1878289395 1811049459 1878221808 1878223859 1743876083 1811162563 1945463796 1811181556 1464746666 1811116018 1809019893 1120551562 1945464821 1741844468 1466842760 1878289395 1811048434 1811050483 1811050483 1878223859 1049188174 1741910004 1811181556 1256998634 1811114994 1878289396 1466840647 1744007156 1744006131 1676877216 1743940596 1878222835 1743938545 1878351792 1676833781 358641652 1743940596 1811050484 845566798 1811113970 1811114995 1811163652 1811112913 1878420468 1878282028 1811179506 1607560178 1878289395 1676900342 1878351825 1466853330 1811113971 1811116019 635659217 1811179506 1811245045 1676942754 1744137206 1744201717 1676962806 1676962805 1811310581 1676896245 1744199635 1811376117 1744072695 1744005109 1811244019 499279861 1811310581 1811244020 1811293668 1399943159 1605528567 1744136181 982063522 986342388 1744070645 1744189066 430063308 1744071669 1744070644 1744067504 566519797 1744136181 1744137205 1743999854 912813044 1811311606 1742162607 4195488 283139922 1945531382 1253113857 144710948 1601400791 1811246069 1811167879 1464821747 1744136180 1674799094 1811178482 843473875 1811311606 1878533542 2106790 2080066222 1876193270 696845376 627472380 1185772536 1878355957 1743990309 1744007157 1676898294 1744006132 1811114996 1743941620 1811180533 1809204941 4194368 4217681 1878290421 1252982848 4194336 1670540278 1739811795 1878353906 1744006131 1811179506 1744007157 1744005106 1945462771 1811182582 1811311574 1393641133 1462856629 2012638196 1876382449 1112301394 1742041045 1945596917 1676833781 1811113970 1811179507 1811180532 1672705014 1674735606 1672697648 1945725943 1878551479 1809215479 1811312629 1809216504 1809215479 1809215478 1462853490 1878487029 1744007158 1744005075 1811239726 704979363 495004132 700789287 562372997 631646663 1739998892 4194400 1116497846 698688932 562375109 770124262 633609569 495070758 1257010166 562315916 1809279958 2012894002 1047280171 980237901 910966381 1668677696 4194400 6314867 1047281260 908804749 910968495 1393719290 1809279959 1185750370 1809214455 1878469062 423836236 1532188466 1601592148 1462986647 1672937568 4194368 6319062 1603622706 1601525554 1601522417 1047336194 770206679 1878487031 1878409899 977955830 1809145716 1118586509 980105834 980045584 1811372914 980104778 1605526483 1395605131 910769804 1118651052 1534358520 1809136234 1118596053 1532059506 1878485973 1326456163 1945660374 1742106615 1811311607 1945725942 1742107641 1744072693 1811311605 1744203767 1878551543 564478604 1878553591 1603428242 1811048433 1811049459 1051290611 1744006131 1811049459 1878156273 1743874034 1744007156 1743874033 1811048434 1811113970 1743939571 1743933228 1603301363 1743875059 1811049458 1945461745 1811181556 1811113971 1811049458 1811048434 1811116020 1878287346 1878223857 1743940594 1744006130 1744007157 1945395153 1945400309 1811048434 1743810547 1676765170 1878353906 1811113970 1743874032 1810983921 1743874033 1811113971 1676765169 1743874034 1743940593 1743939569 1811047409 1676765168 1743940595 1810981872 1945397235 1607560179 1743941620 1810982897 1810983921 1811048433 1744007155 1743875059 1811048434 1743875058 1743939568 1676832754 1811116019 1811114994 1811244019 1676962805 1677029367 1811244020 1744005106 1743940594 1811246068 1744070645 1676961781 1744004084 1676897269 1811180533 1878353908 1744004083 1744070645)\\n\\toffset: 0@0) atKey: 'squeakyMouse'\\\"! !\\n\\n\\n!StandardScriptingSystem methodsFor: 'help dictionary' stamp: 'dgd 9/1/2003 14:25'!\\nhelpStringOrNilFor: aSymbol \\n\\t\\\"If my HelpStrings dictionary has an entry at the given symbol, \\n\\tanswer that entry's value, else answer nil\\\"\\n\\tHelpStrings\\n\\t\\tat: aSymbol\\n\\t\\tifPresent:[:string | ^ string translated].\\n^ nil! !\\n\\n!StandardScriptingSystem methodsFor: 'help dictionary' stamp: 'sw 6/15/1999 17:03'!\\ninitializeHelpStrings\\n\\t\\\"Initialize the data structure that determines, for the etoy system, help messages for various scripting elements. The structure is built up by letting every Morph subclass contribute elements simply by implementing method #helpContributions. Consult implementors of #helpContributions for examples of how this goes.\\\"\\n\\n\\t\\\"ScriptingSystem initializeHelpStrings\\\"\\n\\n\\t| aDictionary |\\n\\taDictionary _ IdentityDictionary new. \\n\\t\\\"For safety, the new copy is built up in this temp first, so that if an error occurs during the creation of the structure, the old version will remain remain in place\\\"\\n\\n\\tMorph withAllSubclasses do:\\n\\t\\t[:aClass | (aClass class selectors includes: #helpContributions)\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[aClass helpContributions do:\\n\\t\\t\\t\\t\\t[:pair | aDictionary at: pair first put: pair second]]].\\n\\n\\t\\tHelpStrings _ aDictionary! !\\n\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 10/30/2000 16:33'!\\nallClassVarNamesInSystem\\n\\t\\\"Compute and answer a set of all the class variable names known to the sytem from any class\\\"\\n\\n\\t| aList |\\n\\taList _ OrderedCollection new.\\n\\tObject withAllSubclasses do:\\n\\t\\t[:c | aList addAll: c allClassVarNames].\\n\\t^ aList asSet\\n\\n\\t\\\"ScriptingSystem allClassVarNamesInSystem\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 6/16/2005 01:35'!\\ncustomizeForEToyUsers: aBoolean\\n\\t\\\"If aBoolean is true, set things up for etoy users. If it's false, unset some of those things. Some things are set when switching into etoy mode but not reversed when switching out of etoy mode.\\\"\\n \\n\\t#(\\t\\n\\t\\t(allowEtoyUserCustomEvents\\tno\\t\\treverse)\\n\\t\\t(balloonHelpEnabled\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(debugHaloHandle\\t\\t\\tno\\t\\treverse)\\n\\t\\t(modalColorPickers\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(oliveHandleForScriptedObjects\\tno\\tdontReverse)\\n\\t\\t(uniqueNamesInHalos\\t\\tyes\\t\\treverse)\\n\\t\\t(useUndo\\t\\t\\t\\t\\tyes\\t\\tdontReverse)\\n\\t\\t(infiniteUndo\\t\\t\\t\\tno\\t\\tdontReverse)\\n\\t\\t(warnIfNoChangesFile\\t\\tno\\t\\treverse)\\n\\t\\t(warnIfNoSourcesFile\\t\\tno\\t\\treverse)) do:\\n\\t\\t\\t[:trip |\\n\\t\\t\\t\\t(aBoolean or: [trip third == #reverse]) ifTrue:\\n\\t\\t\\t\\t\\t[Preferences enableOrDisable: trip first asPer:\\n\\t\\t\\t\\t\\t\\t((trip second == #yes) & aBoolean) | ((trip second == #no) & aBoolean not)]]! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 4/6/2005 09:30'!\\nsoundNamesToSuppress\\n\\t\\\"Answer a list of sound-names that are not to be offered in sound-choice pop-ups unless they are the current choice\\\"\\n\\n\\t^ #('scrape' 'scritch' 'peaks')! !\\n\\n!StandardScriptingSystem methodsFor: 'utilities' stamp: 'sw 11/26/1999 15:44'!\\nstripGraphicsForExternalRelease\\n\\t\\\"ScriptingSystem stripGraphicsForExternalRelease\\\"\\n\\n\\t| replacement |\\n\\treplacement _ FormDictionary at: #Gets.\\n\\n\\t#('BadgeMiniPic' 'BadgePic' 'Broom' 'CedarPic' 'CollagePic' 'CoverMain' 'CoverSpiral' 'CoverTexture' 'Fred' 'ImagiPic' 'KayaPic' 'StudioPic')\\n\\t\\tdo:\\n\\t\\t\\t[:aKey | FormDictionary at: aKey asSymbol put: replacement]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 07:47'!\\naddCustomEventFor: registrantClass named: aSymbol help: helpString targetMorphClass: targetClass\\n\\t| registration |\\n\\tregistration _ self customEventsRegistry at: aSymbol ifAbsentPut: [ IdentityDictionary new ].\\n\\tregistration at: registrantClass put: { helpString. targetClass }.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:23'!\\naddUserCustomEventNamed: aSymbol help: helpString\\n\\tself currentWorld addUserCustomEventNamed: aSymbol help: helpString.\\n\\t\\\"Vocabulary addStandardVocabulary: UserCustomEventNameType new.\\\"\\n\\tVocabulary customEventsVocabulary.\\n\\tSymbolListTile updateAllTilesForVocabularyNamed: #CustomEvents! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 08:19'!\\ncustomEventNamesAndHelpStringsFor: aPlayer\\n\\t| retval help helpStrings morph |\\n\\tmorph := aPlayer costume renderedMorph.\\n\\tretval := SortedCollection sortBlock: [ :a :b | a first < b first ].\\n\\tself customEventsRegistry\\n\\t\\tkeysAndValuesDo: [ :k :v |\\n\\t\\t\\thelpStrings := Array streamContents: [ :hsStream |\\n\\t\\t\\t\\tv keysAndValuesDo: [ :registrant :array |\\n\\t\\t\\t\\t\\t(morph isKindOf: array second) ifTrue: [\\n\\t\\t\\t\\t\\t\\thelp := String streamContents: [ :stream |\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv size > 1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [ stream nextPut: $(;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnextPutAll: array second name;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnextPut: $);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspace ].\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstream nextPutAll: array first ].\\n\\t\\t\\t\\t\\t\\thsStream nextPut: help ]]].\\n\\t\\t\\thelpStrings isEmpty ifFalse: [retval add: { k. helpStrings } ]].\\n\\t^ retval! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:31'!\\ncustomEventStati\\n\\t^self globalCustomEventNames,\\n\\tself userCustomEventNames! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 10/12/2003 13:14'!\\ncustomEventsRegistry\\n\\t^Smalltalk at: #CustomEventsRegistry ifAbsentPut: [ IdentityDictionary new ].! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:30'!\\nglobalCustomEventNames\\n\\t^self customEventsRegistry keys asArray sort! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 11/1/2004 07:56'!\\nglobalCustomEventNamesFor: aPlayer\\n\\t| morph names |\\n\\tmorph := aPlayer costume renderedMorph.\\n\\tnames := SortedCollection new.\\n\\tself customEventsRegistry keysAndValuesDo: [ :k :v |\\n\\t\\t(v anySatisfy: [ :array | morph isKindOf: array second ])\\n\\t\\t\\tifTrue: [ names add: k ]].\\n\\t^names asArray! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 7/20/2003 12:37'!\\nremoveCustomEventNamed: aSymbol for: registrant\\n\\t| registration helpString |\\n\\tregistration _ self customEventsRegistry at: aSymbol ifAbsent: [ ^nil ].\\n\\thelpString _ registration removeKey: registrant ifAbsent: [].\\n\\tregistration isEmpty ifTrue: [ self customEventsRegistry removeKey: aSymbol ].\\n\\t^helpString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:26'!\\nremoveUserCustomEventNamed: eventName\\n\\t| retval |\\n\\tretval _ self currentWorld removeUserCustomEventNamed: eventName.\\n\\t\\\"Vocabulary addStandardVocabulary: UserCustomEventNameType new.\\\"\\n\\tVocabulary customEventsVocabulary.\\n\\tSymbolListTile updateAllTilesForVocabularyNamed: #CustomEvents.\\n\\t^retval! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 6/30/2004 18:16'!\\nstandardEventStati\\n\\t\\\"Answer the events that can be directed to a particular morph by its event handler.\\\"\\n\\t^ #(mouseDown\\t\\\"run when mouse goes down on me\\\"\\n\\t\\tmouseStillDown\\t\\\"while mouse still down\\\"\\n\\t\\tmouseUp\\t\\t\\\"when mouse comes back up\\\"\\n\\t\\tmouseEnter\\t\\\"when mouse enters my bounds, button up\\\"\\n\\t\\tmouseLeave\\t\\\"when mouse exits my bounds, button up\\\"\\n\\t\\tmouseEnterDragging\\t\\\"when mouse enters my bounds, button down\\\"\\n\\t\\tmouseLeaveDragging\\t\\\"when mouse exits my bounds, button down\\\"\\n\\t\\t\\\"keyStroke\\\"\\n\\t\\t\\\"gesture\\\"\\n\\t)\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-custom events' stamp: 'nk 9/26/2003 23:22'!\\nuserCustomEventNames\\n\\t^ self currentWorld userCustomEventNames! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-customevents-help dictionary' stamp: 'nk 11/1/2004 08:21'!\\nstatusHelpStringFor: aPlayer\\n\\t^String streamContents: [ :stream |\\n\\t\\tstream nextPutAll: 'normal -- run when called\\npaused -- ready to run all the time\\nticking -- run all the time\\nmouseDown -- run when mouse goes down on me\\nmouseStillDown -- while mouse still down\\nmouseUp -- when mouse comes back up\\nmouseEnter -- when mouse enters my bounds, button up\\nmouseLeave -- when mouse exits my bounds, button up\\nmouseEnterDragging -- when mouse enters my bounds, button down\\nmouseLeaveDragging -- when mouse exits my bounds, button down\\nopening -- when I am being opened\\nclosing -- when I am being closed' translated.\\n\\n\\\"'keyStroke -- run when user hits a key' \\\"\\n\\n\\tstream cr; cr; nextPutAll: 'More events:' translated; cr.\\n\\n\\t(self customEventNamesAndHelpStringsFor: aPlayer) do: [ :array |\\n\\t\\tstream cr;\\n\\t\\tnextPutAll: array first;\\n\\t\\tnextPutAll: ' -- '.\\n\\t\\tarray second do: [ :help | stream nextPutAll: help translated ]\\n\\t\\t\\tseparatedBy: [ stream nextPutAll: ' or ' translated ]].\\n\\n\\t(Preferences allowEtoyUserCustomEvents) ifTrue: [\\n\\tself userCustomEventNames isEmpty ifFalse: [\\n\\t\\tstream cr; cr; nextPutAll: 'User custom events:' translated; cr.\\n\\t\\tself currentWorld userCustomEventsRegistry keysAndValuesDo: [ :key :value |\\n\\t\\t\\tstream cr; nextPutAll: key; nextPutAll: ' -- '; nextPutAll: value ]]]]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 5/2/1998 14:26'!\\ncolorBehindTiles\\n\\t^ Color r: 0.903 g: 1.0 b: 0.903! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'dgd 7/12/2003 12:06'!\\nfontForNameEditingInScriptor\\n\\t^ Preferences standardEToysFont! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'dgd 7/12/2003 12:05'!\\nfontForTiles\\n\\t^ Preferences standardEToysFont! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'nk 7/12/2003 08:59'!\\nsmallBoldFont\\n\\t\\\"Answer a small bold font for use in some standard scripting-support structures\\\"\\n\\n\\t^ StrikeFont familyName: Preferences standardEToysFont familyName size: 12! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 9/14/1998 14:41'!\\nstatusColorSymbolFor: statusSymbol\\n\\t#(\\t(normal\\t\\t\\t\\t\\tgreen)\\n\\t\\t(ticking\\t\\t\\t\\t\\tblue)\\n\\t\\t(paused\\t\\t\\t\\t\\tred)\\n\\t\\t(mouseDown\\t\\t\\t\\tyellow)\\n\\t\\t(mouseStillDown\\t\\t\\tlightYellow)\\n\\t\\t(mouseUp\\t\\t\\t\\tlightBlue)\\n\\t\\t(mouseEnter\\t\\t\\t\\tlightBrown)\\n\\t\\t(mouseLeave\\t\\t\\tlightRed)\\n\\t\\t(mouseEnterDragging\\tlightGray)\\n\\t\\t(mouseLeaveDragging\\tdarkGray)\\n\\t\\t(keyStroke\\t\\t\\t\\tlightGreen)) do:\\n\\n\\t\\t\\t[:pair | statusSymbol == pair first ifTrue: [^ pair second]].\\n\\n\\t\\t^ #blue! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-font & color choices' stamp: 'sw 5/2/1998 14:23'!\\nuniformTileInteriorColor\\n\\t^ Color r: 0.806 g: 1.0 b: 0.806! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/12/1999 10:09'!\\ninstallSolidMenuForm\\n\\t\\\"ScriptingSystem installSolidMenuForm\\\"\\n\\tself saveForm:\\n\\t\\t(Form extent: 14@16 depth: 16\\n\\tfromArray: #( 1 0 0 0 0 0 0 65537 65536 0 0 0 65537 0 65537 65537 65537 65537 65537 65537 65536 65537 65537 65537 65537 65537 1600061441 65536 65537 1600085855 1600085855 1600085855 1600085855 1600061441 65536 65537 1600085855 65537 65537 65537 65537 65536 65537 1600085855 65537 65537 65537 1600061441 65536 65537 1600085855 1600085855 1600085855 1600085855 1600085855 65537 65537 1600085855 65537 65537 65537 1600085855 65537 65537 1600085855 1600061441 65537 65537 89951 65537 65537 1600085855 1600085855 1600085855 1600085855 1600085855 65537 65537 1600085855 1600061441 65537 65537 65537 65537 65537 1600085855 65537 65537 65537 65536 65537 65537 65537 65537 65537 65537 65537 65537 1 65537 65537 65537 65537 65537 65536 0 65536 0 0 0 0 0) offset: 0@0)\\n\\t\\tatKey: 'SolidMenu'! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 11/26/1999 15:37'!\\nmergeGraphicsFrom: aDictionary\\n\\t\\\"aDictionary is assumed to hold associations of the form <formName> -> <form>. Merge the graphics held by that dictionary into the internal FormDictionary, overlaying any existing entries with the ones found in aDictionary\\\"\\n\\n\\taDictionary associationsDo:\\n\\t\\t[:assoc | self saveForm: assoc value atKey: assoc key]\\n\\n\\t\\t\\\"works ok even if keys in aDictionary are strings rather than symbols\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 2/20/2002 01:09'!\\npatchInNewStandardPlayerForm\\n\\t\\\"Patch in a darker and larger representation of a Dot. No senders -- called from the postscript of an update\\\"\\n\\n\\t\\\"ScriptingSystem patchInNewStandardPlayerForm\\\"\\n\\n\\tFormDictionary at: #standardPlayer put:\\n\\t\\t(Form\\n\\textent: 13@13\\n\\tdepth: 16\\n\\tfromArray: #( 0 0 0 65536 0 0 0 0 0 65537 65537 65536 0 0 0 65537 65537 65537 65537 65536 0 0 65537 65537 65537 65537 65536 0 1 65537 65537 65537 65537 65537 0 1 65537 65537 65537 65537 65537 0 65537 65537 65537 65537 65537 65537 65536 1 65537 65537 65537 65537 65537 0 1 65537 65537 65537 65537 65537 0 0 65537 65537 65537 65537 65536 0 0 65537 65537 65537 65537 65536 0 0 0 65537 65537 65536 0 0 0 0 0 65536 0 0 0)\\n\\toffset: 0@0)! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/2/1998 14:01'!\\nreadFormsFromFileNamed: aFileName\\n\\t\\\"Read the entire FormDictionary in from a designated file on disk\\\"\\n\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\tFormDictionary _ aReferenceStream next.\\n\\taReferenceStream close\\n\\n\\t\\\"ScriptingSystem readFormsFromFileNamed: 'EToyForms22Apr'\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 9/14/2000 21:29'!\\nreadFormsFromFileNamed: aFileName andStoreIntoGlobal: globalName\\n\\t\\\"Read the a FormDictionary in from a designated file on disk and save it in the designated global\\\"\\n\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: aFileName.\\n\\tSmalltalk at: globalName put: aReferenceStream next.\\n\\taReferenceStream close\\n\\n\\t\\\"ScriptingSystem readFormsFromFileNamed: 'SystemFormsFromFwdF.forms' andStoreIntoGlobal: #FormsTemp\\\"\\n\\n\\t\\\"ScriptingSystem saveForm: (FormsTemp at: #StackElementDesignationHelp) atKey: #StackElementDesignationHelp\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 4/23/1999 11:24'!\\nrestorePrivateGraphics\\n\\t\\\"ScriptingSystem restorePrivateGraphics\\\"\\n\\t| aReferenceStream |\\n\\taReferenceStream _ ReferenceStream fileNamed: 'disGraphics'.\\n\\tself mergeGraphicsFrom: aReferenceStream next.\\n\\taReferenceStream close.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 5/6/1998 17:46'!\\nsaveFormsToFileNamed: aFileName\\n\\t\\\"Save the current state of form dictionary to disk for possible later retrieval\\\"\\n \\t (ReferenceStream fileNamed: aFileName) nextPut: FormDictionary; close\\n\\n\\t\\\"ScriptingSystem saveFormsToFileNamed: 'SystemForms06May98.forms'\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-form dictionary' stamp: 'sw 12/7/1998 16:47'!\\nstandardForms\\n\\t\\\"ScriptingSystem standardForms\\\"\\n\\t^ FormDictionary collect: [:f | f]! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'tk 10/20/2004 15:52'!\\nanyButtonPressedTiles\\n\\t\\\"Answer tiles representing the query 'is any button pressed?'\\\"\\n\\n\\t^ self tilesForQuery: '(ActiveHand anyButtonPressed)' label: 'button down?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 11/16/2004 13:56'!\\nnoButtonPressedTiles\\n\\t\\\"Answer tiles representing the query 'is no button pressed?'\\\"\\n\\n\\t^ self tilesForQuery: '(ActiveHand noButtonPressed)' label: 'button up?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 5/3/1999 22:40'!\\nprototypicalHolder\\n\\t| aHolder |\\n\\taHolder _ PasteUpMorph authoringPrototype color: Color orange muchLighter; borderColor: Color orange lighter.\\n\\taHolder setNameTo: 'holder'; extent: 160 @ 110.\\n\\t^ aHolder behaveLikeHolder.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 10/27/1998 13:35'!\\nresetStandardPartsBin\\n\\t\\\"ScriptingSystem resetStandardPartsBin\\\"\\n\\n\\tStandardPartsBin _ nil! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-parts bin' stamp: 'sw 7/3/2001 08:01'!\\ntilesForQuery: expressionString label: aLabel\\n\\t\\\"Answer scripting tiles that represent the query,\\\"\\n\\n\\t| aPhrase aTile |\\n\\taPhrase _ SystemQueryPhrase new.\\n\\taTile _ BooleanTile new.\\n\\taTile setExpression: expressionString label: aLabel.\\n\\taPhrase addMorph: aTile.\\n\\t^ aPhrase\\n! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:40'!\\ngoButton\\n\\t| aButton |\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\taButton image: (ScriptingSystem formAtKey: 'GoPicOn');\\n\\t\\t\\toffImage: (ScriptingSystem formAtKey: 'GoPic');\\n\\t\\t\\tpressedImage: (ScriptingSystem formAtKey: 'GoPicOn');\\n\\t\\t\\tactionSelector: #goUp:with:; \\n\\t\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\t\\tactWhen: #buttonUp;\\n\\t\\t\\ttarget: self;\\n\\t\\t\\tsetNameTo: 'Go Button';\\n\\t\\t\\tsetBalloonText:\\n'Resume running all paused scripts' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 11/11/1998 15:24'!\\ngoUp: evt with: aGoButton\\n\\taGoButton presenter startRunningScriptsFrom: aGoButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 1/23/2001 11:39'!\\nscriptControlButtons\\n\\t\\\"Answer a composite object that serves to control the stop/stop/go status of a Presenter\\\"\\n\\n\\t| wrapper |\\n\\twrapper _ AlignmentMorph newRow setNameTo: 'script controls'.\\n\\twrapper vResizing: #shrinkWrap.\\n\\twrapper hResizing: #shrinkWrap.\\n\\twrapper addMorph: self stopButton.\\n\\twrapper addMorphBack: self stepButton.\\n\\twrapper addMorphBack: self goButton.\\n\\twrapper beTransparent.\\n\\t^ wrapper! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:41'!\\nstepButton\\n\\t| aButton |\\n\\tself flag: #deferred. \\\"ambiguity about recipients\\\"\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\t\\taButton\\n\\t\\t\\timage: (ScriptingSystem formAtKey: 'StepPicOn');\\n\\t\\t\\toffImage: (ScriptingSystem formAtKey: 'StepPic');\\n\\t\\t\\tpressedImage: (ScriptingSystem formAtKey: 'StepPicOn');\\n\\t\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\t \\tactionSelector: #stepStillDown:with:; \\n\\t\\t\\ttarget: self;\\n\\t\\t\\tsetNameTo: 'Step Button'; \\n\\t\\t\\tactWhen: #whilePressed;\\n\\t\\t\\ton: #mouseDown send: #stepDown:with: to: self;\\n\\t\\t\\ton: #mouseStillDown send: #stepStillDown:with: to: self;\\n\\t\\t\\ton: #mouseUp send: #stepUp:with: to: self;\\n\\t\\t\\tsetBalloonText:\\n'Run every paused script exactly once. Keep the mouse button down over \\\"Step\\\" and everything will keep running until you release it' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:33'!\\nstepDown: evt with: aMorph\\n\\taMorph presenter stopRunningScripts! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:35'!\\nstepStillDown: dummy with: theButton\\n\\ttheButton presenter stepStillDown: dummy with: theButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 10/30/1998 15:35'!\\nstepUp: evt with: aMorph\\n\\taMorph presenter stepUp: evt with: aMorph! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'dgd 9/19/2003 14:41'!\\nstopButton\\n\\t\\\"Answer a new button that can serve as a stop button\\\"\\n\\t| aButton |\\n\\taButton _ ThreePhaseButtonMorph new.\\n\\taButton\\n\\t\\timage: (ScriptingSystem formAtKey: 'StopPic');\\n\\t\\toffImage: (ScriptingSystem formAtKey: 'StopPic');\\n\\t\\tpressedImage: (ScriptingSystem formAtKey: 'StopPicOn').\\n\\t\\taButton actionSelector: #stopUp:with:; \\n\\t\\targuments: (Array with: nil with: aButton);\\n\\t\\tactWhen: #buttonUp;\\n\\t\\ttarget: self;\\n\\t\\tsetNameTo: 'Stop Button'; \\n\\t\\tsetBalloonText: 'Pause all ticking scripts.' translated.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-script-control' stamp: 'sw 11/11/1998 15:16'!\\nstopUp: dummy with: theButton\\n\\t| aPresenter |\\n\\t(aPresenter _ theButton presenter) flushPlayerListCache. \\\"catch guys not in cache but who're running\\\"\\n\\taPresenter stopRunningScriptsFrom: theButton! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 8/28/2004 15:19'!\\ncolorForType: typeSymbol\\n\\t\\\"Answer the color to use to represent the given type symbol\\\"\\n\\n\\ttrue ifTrue:\\n\\t\\t[^ self standardTileBorderColor].\\n\\n\\ttypeSymbol capitalized = #Command ifTrue:\\n\\t\\t[^ Color fromRgbTriplet: #(0.065 0.258 1.0)].\\n\\t\\\"Command is historical and idiosyncratic and should be regularized\\\"\\n\\n\\t^ (Vocabulary vocabularyForType: typeSymbol) typeColor! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 10/29/1998 16:18'!\\ncolorFudge\\n\\t^ 0.4! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-tile colors' stamp: 'sw 8/28/2004 20:31'!\\nstandardTileBorderColor\\n\\t\\\"Answer the color to use for tile borders\\\"\\n\\n\\t^ Color r: 0.804 g: 0.76 b: 0.564! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'sw 1/4/2005 02:20'!\\nacceptableSlotNameFrom: originalString forSlotCurrentlyNamed: currentName asSlotNameIn: aPlayer world: aWorld\\n\\t\\\"Produce an acceptable slot name, derived from the current name, for aPlayer. This method will always return a valid slot name that will be suitable for use in the given situation, though you might not like its beauty sometimes.\\\"\\n\\n\\t| aString stemAndSuffix proscribed stem suffix putative |\\n\\taString _ originalString asIdentifier: false. \\\"get an identifier not lowercase\\\"\\n\\tstemAndSuffix _ aString stemAndNumericSuffix.\\n\\tproscribed _ #(self super thisContext costume costumes dependents #true #false size), aPlayer class allInstVarNames.\\n\\n\\tstem _ stemAndSuffix first.\\n\\tsuffix _ stemAndSuffix last.\\n\\tputative _ aString asSymbol.\\n\\t\\n\\t[(putative ~~ currentName) and: [(proscribed includes: putative)\\n\\t\\tor:\\t[(aPlayer respondsTo: putative)\\n\\t\\tor:\\t[Smalltalk includesKey: putative]]]]\\n\\twhileTrue:\\n\\t\\t[suffix _ suffix + 1.\\n\\t\\tputative _ (stem, suffix printString) asSymbol].\\n\\t^ putative! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'kfr 9/23/2003 09:29'!\\ndoesOperatorWantArrows: aSymbol\\n\\taSymbol = #, ifTrue:[^ false].\\n\\t^ aSymbol isInfix or: [#(isDivisibleBy:) includes: aSymbol]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-universal slots & scripts' stamp: 'sw 9/27/2001 04:08'!\\nsystemSlotNamesOfType: aType\\n\\t\\\"Answer the type of the slot name, or nil if not found.\\\"\\n\\t\\n\\t| aList |\\n\\tself flag: #deferred. \\\"Hard-coded etoyVocabulary needed here to make this work.\\\"\\n\\taList _ OrderedCollection new.\\n\\tVocabulary eToyVocabulary methodInterfacesDo:\\n\\t\\t [:anInterface |\\n\\t\\t\\tanInterface resultType = aType ifTrue:\\n\\t\\t\\t\\t[aList add: anInterface selector]].\\n\\t^ aList! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:37'!\\nallKnownClassVariableNames\\n\\t\\\"Answer a set of all the knwon class variable names in the system. This normally retrieves them from a cache, and at present there is no organized mechanism for invalidating the cache. The idea is to avoid, in the References scheme, names that may create a conflict\\\"\\n\\n\\t^ ClassVarNamesInUse ifNil: [ClassVarNamesInUse _ self allClassVarNamesInSystem]\\n\\n\\t\\\"ClassVarNamesInUse _ nil.\\n\\tTime millisecondsToRun: [ScriptingSystem allKnownClassVariableNames]\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'kfr 9/23/2003 09:44'!\\narithmeticalOperatorsAndHelpStrings\\n\\t\\\"Answer an array consisting of lists of the standard arithmetical operator tiles and of the corresponding balloon help for them\\\"\\n\\n\\t^ #((+ - * / // \\\\\\\\ max: min:)\\n\\t \\t('add' 'subtract' 'multiply' 'divide' 'divide & truncate' 'remainder when divided by' 'larger value' 'smaller value' ))! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 10/20/2004 15:52'!\\nbuttonDownTile\\n\\t\\\"Answer a boolean-valued tile which reports whether the button is down\\\"\\n\\n\\t^ self systemQueryPhraseWithActionString: '(ActiveHand anyButtonPressed)' labelled: 'button down?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 10/20/2004 15:52'!\\nbuttonUpTile\\n\\t\\\"Answer a boolean-valued tile which reports whether the button is up\\\"\\n\\n\\t^ self systemQueryPhraseWithActionString: '(ActiveHand noButtonPressed)' labelled: 'button up?' translated! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'tk 8/21/2000 12:59'!\\ncleanupsForRelease\\n\\t\\\"Miscellaneous space cleanups to do before a release.\\\"\\n\\t\\\"EToySystem cleanupsForRelease\\\"\\n\\n\\tSocket deadServer: ''. \\\"Don't reveal any specific server name\\\"\\n\\tHandMorph initialize. \\\"free cached ColorChart\\\"\\n\\tPaintBoxMorph initialize.\\t\\\"forces Prototype to let go of extra things it might hold\\\"\\n\\tSmalltalk removeKey: #AA ifAbsent: [].\\n\\tSmalltalk removeKey: #BB ifAbsent: [].\\n\\tSmalltalk removeKey: #CC ifAbsent: [].\\n\\tSmalltalk removeKey: #DD ifAbsent: [].\\n\\tSmalltalk removeKey: #Temp ifAbsent: [].\\n\\n\\tScriptingSystem reclaimSpace.\\n\\tSmalltalk cleanOutUndeclared.\\n\\tSmalltalk reclaimDependents.\\n\\tSmalltalk forgetDoIts.\\n\\tSmalltalk removeEmptyMessageCategories.\\n\\tSymbol rehash! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 3/10/2004 23:24'!\\nhelpStringForOperator: anOperator\\n\\t\\\"Answer the help string associated with the given operator. If none found, return a standard no-help-available reply\\\"\\n\\n\\t^ (self helpStringOrNilForOperator: anOperator) ifNil:\\n\\t\\t['Sorry, no help available here' translated] \\\"This should never be seen, but is provided as a backstop\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 6/27/2004 11:11'!\\nhelpStringOrNilForOperator: anOperator\\n\\t\\\"Answer the help string associated with the given operator, nil if none found.\\\"\\n\\n\\t| anIndex opsAndHelp |\\n\\t(anIndex _ (opsAndHelp _ self arithmeticalOperatorsAndHelpStrings) first indexOf: anOperator) > 0\\n\\t\\tifTrue:\\t[^ (opsAndHelp second at: anIndex) translated].\\n\\n\\t(anIndex _ (opsAndHelp _ self numericComparitorsAndHelpStrings) first indexOf: anOperator) > 0\\n\\t\\tifTrue:\\t[^ (opsAndHelp second at: anIndex) translated].\\n\\n\\tanOperator = #, ifTrue:\\n\\t\\t[^ 'Concatenate two Strings' translated].\\n\\n\\t^ nil! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'nk 7/12/2003 08:59'!\\nholderWithAlphabet\\n\\t\\\"Answer a fully instantiated Holder that has submorphs that represent the letters of the uppercase alphabet, with each one having an 'index' slot which bears the letter's index in the alphabet -- 1 for A, 2 for B, etc. A few special characters are provided as per ack request 10/00; for these the index provided is rather arbitrarily assigned\\\"\\n\\n\\t| aMorph aPlayer newMorph oneCharString aContainer aWrapper |\\n\\n\\t\\\"ScriptingSystem holderWithAlphabet openInHand\\\"\\n\\n\\taContainer _ self prototypicalHolder useRoundedCorners.\\n\\taContainer borderColor: Color blue lighter.\\n\\n\\taWrapper _ AlignmentMorph new hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutInset: 0.\\n\\taWrapper addMorphBack: (aMorph _ TextMorph new contents: 'A').\\n\\taMorph beAllFont: ((TextStyle named: Preferences standardEToysFont familyName) fontOfSize: 24).\\n\\taMorph width: 14; lock.\\n\\taWrapper beTransparent; setNameTo: 'A'.\\n\\taPlayer _ aWrapper assuredPlayer.\\n\\taPlayer addInstanceVariableNamed: #index type: #Number value: 1.\\n\\taContainer addMorphBack: aWrapper.\\n\\t2 to: 26 do:\\n\\t\\t[:anIndex |\\n\\t\\t\\tnewMorph _ aWrapper usableSiblingInstance.\\n\\t\\t\\tnewMorph player perform: #setIndex: with: anIndex.\\n\\t\\t\\tnewMorph firstSubmorph contents: (oneCharString _ ($A asciiValue + anIndex - 1) asCharacter asString).\\n\\t\\t\\tnewMorph setNameTo: oneCharString.\\n\\n\\t\\t\\taContainer addMorphBack: newMorph].\\n\\n\\t#(' ' '.' '#') with: #(27 28 29) do:\\n\\t\\t[:aString :anIndex |\\n\\t\\t\\tnewMorph _ aWrapper usableSiblingInstance.\\n\\t\\t\\tnewMorph player perform: #setIndex: with: anIndex.\\n\\t\\t\\tnewMorph firstSubmorph contents: aString.\\n\\t\\t\\taString = ' '\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[newMorph setNameTo: 'space'.\\n\\t\\t\\t\\t\\tnewMorph color: (Color gray alpha: 0.2)]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[newMorph setNameTo: aString].\\n\\t\\t\\taContainer addMorphBack: newMorph].\\n\\n\\taContainer setNameTo: 'alphabet'.\\n\\taContainer isPartsBin: true.\\n\\taContainer enableDrop: false.\\n\\taContainer indicateCursor: false; width: 162.\\n\\taContainer color: (Color r: 0.839 g: 1.0 b: 1.0). \\\"Color fromUser\\\"\\n\\t^ aContainer! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/15/2000 06:24'!\\ninformScriptingUser: aString\\n\\t\\\"This provides a hook for logging messages that the user or the developer may wish to see; at present it simply logs the message to the Transcript, with a standard prefix to signal their provenance. Such messages will fall on the floor if there is no Transcript window open\\\"\\n\\n\\tTranscript cr; show: 'SCRIPT NOTE: ', aString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/26/2003 22:44'!\\nnameForInstanceVariablesCategory\\n\\t\\\"Answer the name to use for the viewer category that contains instance variables\\\"\\n\\n\\t^ #variables \\n\\t\\\"^ #'instance variables'\\\"\\n\\n\\\"ScriptingSystem nameForInstanceVariablesCategory\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/6/2003 18:00'!\\nnameForScriptsCategory\\n\\t\\\"Answer the name to use for the viewer category that contains scripts\\\"\\n\\n\\t^ #scripts! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 2/18/2001 17:50'!\\nnewScriptingSpace\\n\\t\\\"Answer a complete scripting space - raa 19 sept 2000 - experiment for Alan, a variant *not* in a window, now adopted as the only true scripting space\\\"\\n\\n\\t^ self newScriptingSpace2! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 11/13/2001 14:41'!\\nnewScriptingSpace2\\n\\t\\\"Answer a complete scripting space\\\"\\n\\n\\t| aTemplate aPlayfield aControl |\\n\\t\\n\\t(aTemplate _ PasteUpMorph new)\\n\\t\\tsetNameTo: 'etoy';\\n\\t\\textent: 638 @ 470;\\n\\t\\tcolor: Color white;\\n\\t\\timpartPrivatePresenter;\\n\\t\\tsetProperty: #automaticPhraseExpansion toValue: true;\\n\\t\\tbeSticky.\\n\\taTemplate useRoundedCorners; borderWidth: 2. \\n\\taControl _ ScriptingSystem scriptControlButtons setToAdhereToEdge: #bottomLeft.\\n\\taControl beSticky; borderWidth: 0; beTransparent.\\n\\taTemplate addMorphBack: aControl.\\n\\taTemplate presenter addTrashCan.\\n\\n\\taTemplate addMorph: (aPlayfield _ PasteUpMorph new).\\n\\taPlayfield\\n\\t\\tsetNameTo: 'playfield';\\n\\t\\tuseRoundedCorners;\\n\\t\\tsetToAdhereToEdge: #topLeft;\\n\\t\\textent: 340@300;\\n\\t\\tposition: aTemplate topRight - (400@0);\\n\\t\\tbeSticky;\\n\\t\\tautomaticViewing: true;\\n\\t\\twantsMouseOverHalos: true.\\n\\taTemplate presenter standardPlayfield: aPlayfield.\\n\\t\\n\\t^ aTemplate\\n\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/21/2000 22:39'!\\nnumericComparitorsAndHelpStrings\\n\\t\\\"Answer an array whose first element is the list of comparitors, and whose second element is a list of the corresponding help strings\\\"\\n\\n\\t^ #((< <= = ~= > >= isDivisibleBy:)\\n\\t \\t('less than' 'less than or equal' 'equal' 'not equal' 'greater than' 'greater than or equal' 'divisible by' ))! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities'!\\nprepareForExternalReleaseNamed: aReleaseName\\n\\t\\\"ScriptingSystem prepareForExternalReleaseNamed: '2.2Beta'\\\"\\n\\n\\tEToySystem stripMethodsForExternalRelease.\\n\\n\\tScriptingSystem saveFormsToFileNamed: aReleaseName, '.Dis.Forms'.\\n\\tScriptingSystem stripGraphicsForExternalRelease.\\n\\tScriptingSystem cleanupsForRelease.\\n\\tScreenController initialize.\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 5/2/1998 14:17'!\\nreclaimSpace\\n\\t\\\"Reclaim space from the scripting system, and report the result in an informer\\\"\\n\\t\\\"ScriptingSystem reclaimSpace\\\"\\n\\n\\t| reclaimed |\\n\\t(reclaimed _ self spaceReclaimed) > 0\\n\\t\\tifTrue:\\t[self inform: reclaimed printString, ' bytes reclaimed']\\n\\t\\tifFalse:\\t[self inform: 'Hmm... Nothing gained this time.']! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 09:08'!\\nreferenceAt: aSymbol\\n\\t\\\"Answer the object referred to by aSymbol in the 'References' scheme of things, or nil if none\\\"\\n\\n\\t^ References at: aSymbol ifAbsent: [nil]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 09:33'!\\nreferenceAt: aSymbol put: anObject\\n\\t\\\"Store a reference to anObject at the given symbol in the References directory\\\"\\n\\n\\t^ References at: aSymbol put: anObject! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 6/9/2000 18:44'!\\nreinvigorateThumbnailsInViewerFlapTabs\\n\\t\\\"It has happened that the thumbnail in a viewer flap tab will go solid gray because it got associated with some passing and disused player temporarily created during the initial painting process. This method takes a sledge hammer to repair such thumbnails. At its genesis, this method is called only from the postscript of its defining fileout.\\\"\\n\\t| vwr thumbnail |\\n\\tViewerFlapTab allInstancesDo:\\n\\t\\t[:aTab | \\n\\t\\t\\tvwr _ aTab referent findA: StandardViewer.\\n\\t\\t\\tthumbnail _ aTab findA: ThumbnailMorph.\\n\\t\\t\\t(vwr notNil and: [thumbnail notNil]) ifTrue:\\n\\t\\t\\t\\t[thumbnail objectToView: vwr scriptedPlayer]]\\n\\n\\t\\\"ScriptingSystem reinvigorateThumbnailsInViewerFlapTabs\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 12/20/2003 18:02'!\\nreportToUser: aString\\n\\t\\\"Make a message accessible to the user. For the moment, we simply defer to the Transcript mechanism\\\"\\n\\n\\tTranscript cr; show: aString! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:47'!\\nresetAllScriptingReferences\\n\\t\\\"Clear out all the elements in the References directory\\\"\\n\\t\\n\\tSmalltalk at: #References put: IdentityDictionary new\\n\\n\\t\\\"ScriptingSystem resetAllScriptingReferences\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 10/30/2000 16:45'!\\nresetStaleScriptingReferences\\n\\t\\\"Remove all scripting references that are no longer needed\\\"\\n\\n\\tReferences removeUnreferencedKeys\\n\\n\\t\\\"ScriptingSystem resetStaleScriptingReferences\\\"\\n! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 7/25/2004 17:27'!\\nrestoreClassicEToyLook\\n\\t\\\"Restore classic EToy look, as closely as possible. If ComicBold is present, restore it as the standard etoy and button font. Substitute ComicSansMS and Accuny as respective alternatives if the classic fonts are absent. If those also aren't available, do nothing.\\\"\\n\\n\\t| aTextStyle aFont | \\n\\t(aTextStyle _ TextStyle named: #ComicBold)\\n\\t\\tifNotNil:\\n\\t\\t\\t[aFont _ aTextStyle fontOfSize: 16.\\n\\t\\t\\tPreferences setEToysFontTo: aFont.\\n\\t\\t\\tPreferences setButtonFontTo: aFont]\\n\\t\\tifNil:\\n\\t\\t\\t[(aTextStyle _ TextStyle named: #ComicSansMS) ifNotNil:\\n\\t\\t\\t\\t[Preferences setEToysFontTo: (aTextStyle fontOfSize: 18)].\\n\\t\\t\\t(aTextStyle _ TextStyle named: #Accuny) ifNotNil:\\n\\t\\t\\t\\t[Preferences setButtonFontTo: (aTextStyle fontOfSize: 12)]].\\n\\n\\t(aTextStyle _ TextStyle named: #NewYork)\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences setSystemFontTo: (aTextStyle fontOfSize: 12)]! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 5/16/2001 12:58'!\\nsetterSelectorForGetter: aGetterSymbol\\n\\t\\\"Answer the setter selector corresponding to a given getter\\\"\\n\\n\\t^ (('s', (aGetterSymbol copyFrom: 2 to: aGetterSymbol size)), ':') asSymbol\\n\\n\\t\\\"ScriptingSystem setterSelectorForGetter: #getCursor\\\"! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'di 3/3/2001 08:47'!\\nspaceReclaimed\\n\\t\\\"Reclaim space from the EToy system, and return the number of bytes reclaimed\\\"\\n\\t\\\"ScriptingSystem spaceReclaimed\\\"\\n\\n\\t| oldFree |\\n\\toldFree _ Smalltalk garbageCollect.\\n\\tThumbnailMorph recursionReset.\\n\\tPlayer removeUninstantiatedSubclassesSilently.\\n\\tSmalltalk cleanOutUndeclared.\\n\\tSmalltalk reclaimDependents.\\n\\t^ Smalltalk garbageCollect - oldFree.! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'sw 9/27/2001 13:28'!\\ntileForArgType: aType\\n\\t\\\"Anwer a default tile to represent a datum of the given argument type, which may be either a symbol (e.g. #Color) or a class\\\"\\n\\n\\t(aType isKindOf: Class) \\\"Allowed in Ted's work\\\"\\n\\t\\tifTrue:\\n\\t\\t\\t[^ aType name asString newTileMorphRepresentative typeColor: Color gray].\\n\\n\\t^ (Vocabulary vocabularyForType: aType) defaultArgumentTile! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'dgd 7/12/2003 12:05'!\\ntryButtonFor: aPhraseTileMorph \\n\\t| aButton |\\n\\taButton := SimpleButtonMorph new.\\n\\taButton target: aPhraseTileMorph;\\n\\t\\t actionSelector: #try;\\n\\t\\t\\n\\t\\tlabel: '!!'\\n\\t\\tfont: Preferences standardEToysFont;\\n\\t\\t color: Color yellow;\\n\\t\\t borderWidth: 0.\\n\\taButton actWhen: #whilePressed.\\n\\taButton balloonTextSelector: #try.\\n\\t^ aButton! !\\n\\n!StandardScriptingSystem methodsFor: '*eToys-utilities' stamp: 'nk 10/14/2004 11:19'!\\nwordingForOperator: aString\\n\\t\\\"Answer the wording to be seen by the user for the given operator symbol/string\\\"\\n\\n\\t| toTest |\\n\\ttoTest _ aString asString.\\n\\t#(\\t(append:\\t\\t\\t\\t'include at end')\\n\\t\\t(arrowheadsOnAllPens\\t'arrowheads on all pens')\\n\\t\\t(beep:\\t\\t\\t\\t\\t'make sound')\\n\\t\\t(bounce:\\t\\t\\t\\t'bounce')\\n\\t\\t(clearTurtleTrails\\t\\t'clear pen trails')\\n\\t\\t(clearOwnersPenTrails\\t'clear all pen trails')\\n\\t\\t(colorSees\\t\\t\\t\\t'color sees')\\n\\t\\t(color:sees:\\t\\t\\t\\t'color sees')\\n\\t\\t(doMenuItem:\\t\\t\\t'do menu item')\\n\\t\\t(doScript:\\t\\t\\t\\t'do')\\n\\t\\t(forward:\\t\\t\\t\\t'forward by')\\n\\t\\t(goToRightOf:\\t\\t\\t'align after')\\n\\t\\t(includeAtCursor:\\t\\t'include at cursor')\\n\\t\\t(isDivisibleBy:\\t\\t\\t'is divisible by')\\n\\t\\t(liftAllPens\\t\\t\\t\\t'lift all pens')\\n\\t\\t(lowerAllPens\\t\\t\\t'lower all pens')\\n\\t\\t(makeNewDrawingIn:\\t'start painting in')\\n\\t\\t(max:\\t\\t\\t\\t\\t'max')\\n\\t\\t(min:\\t\\t\\t\\t\\t'min')\\n\\t\\t(moveToward:\\t\\t\\t'move toward')\\n\\t\\t(noArrowheadsOnAllPens\\t'no arrowheads on pens')\\n\\t\\t(overlapsAny\\t\\t\\t'overlaps any')\\n\\t\\t(pauseAll:\\t\\t\\t\\t'pause all')\\n\\t\\t(pauseScript:\\t\\t\\t'pause script')\\n\\t\\t(prepend:\\t\\t\\t\\t'include at beginning')\\n\\t\\t(seesColor:\\t\\t\\t\\t'is over color')\\n\\t\\t(startAll:\\t\\t\\t\\t'start all')\\n\\t\\t(startScript:\\t\\t\\t\\t'start script')\\n\\t\\t(stopProgramatically\\t'stop')\\n\\t\\t(stopAll:\\t\\t\\t\\t\\t'stop all')\\n\\t\\t(stopScript:\\t\\t\\t\\t'stop script')\\n\\t\\t(tellAllSiblings:\\t\\t\\t'tell all siblings')\\n\\t\\t(tellSelfAndAllSiblings:\\t'send to all')\\n\\t\\t(turn:\\t\\t\\t\\t\\t'turn by')\\n\\t\\t(turnToward:\\t\\t\\t\\t'turn toward')\\n\\t\\t(wearCostumeOf:\\t\\t'look like'))\\n\\n\\tdo:\\n\\t\\t[:pair | toTest = pair first ifTrue: [^ pair second]].\\n\\n\\t^ toTest\\n\\n\\t\\\"StandardScriptingSystem initialize\\\"\\n\\n! !\\n\\n\\n!StandardScriptingSystem methodsFor: '*eToys-viewer' stamp: 'sw 10/30/2000 09:07'!\\nuniqueNameForReference\\n\\t\\\"Answer a more-or-less global name by which the receiver can be referred to in scripts\\\"\\n\\n\\t^ #ScriptingSystem! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardScriptingSystem class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardScriptingSystem class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 19:04'!\\ninitialize\\n\\t\\\"Initialize the scripting system. Sometimes this method is vacuously changed just to get it in a changeset so that its invocation will occur as part of an update\\\"\\n\\n\\t(self environment at: #ScriptingSystem ifAbsent: [nil]) ifNil:\\n\\t\\t[self environment at: #ScriptingSystem put: self new].\\n\\n\\tScriptingSystem\\n\\t\\tinitializeHelpStrings.\\n\\n\\tself registerInFlapsRegistry.\\n\\n\\\"StandardScriptingSystem initialize\\\"! !\\n\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'nk 9/1/2004 10:53'!\\napplyNewEToyLook\\n\\t\\\"Apply the new EToy look based on free fonts, approximating the classic look as closely as possible.\\\"\\n\\n\\t\\\"StandardScriptingSystem applyNewEToyLook\\\"\\n\\n\\\"\\t| aTextStyle aFont | \\n\\taTextStyle _ TextStyle named: #BitstreamVeraSansMono.\\n\\taFont _ aTextStyle fontOfSize: 12.\\n\\taFont _ aFont emphasis: 1.\\n\\tPreferences setEToysFontTo: aFont.\\n\\tPreferences setButtonFontTo: aFont.\\n\\n\\taTextStyle _ TextStyle named: #Accushi.\\n\\taFont _ aTextStyle fontOfSize: 12.\\n\\tPreferences setFlapsFontTo: aFont.\\n\\n\\t(aTextStyle _ TextStyle named: #Accuny)\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences setSystemFontTo: (aTextStyle fontOfSize: 12)]\\\"\\n\\n\\tPreferences setDefaultFonts: #(\\n\\t\\t(setEToysFontTo:\\t\\t\\tBitstreamVeraSansBold\\t10)\\n\\t\\t(setButtonFontTo:\\t\\tBitstreamVeraSansMono\\t9)\\n\\t\\t(setFlapsFontTo:\\t\\t\\tAccushi\\t\\t\\t\\t12)\\n\\t\\t(setSystemFontTo:\\t\\tAccuny\\t\\t\\t\\t10)\\n\\t\\t(setWindowTitleFontTo:\\tBitstreamVeraSansBold\\t12)\\n\\t)\\n! !\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'mir 11/26/2004 16:14'!\\nremovePlayersIn: project\\n\\t\\\"Remove existing player references for project\\\"\\n\\n\\tReferences keys do: \\n\\t\\t[:key | (References at: key) costume pasteUpMorph == project world\\n\\t\\t\\tifTrue: [References removeKey: key]].\\n! !\\n\\n!StandardScriptingSystem class methodsFor: 'utilities' stamp: 'mir 11/25/2004 19:01'!\\nremoveUnreferencedPlayers\\n\\t\\\"Remove existing but unreferenced player references\\\"\\n\\t\\\"StandardScriptingSystem removeUnreferencedPlayers\\\"\\n\\tReferences keys do: \\n\\t\\t[:key | (References at: key) costume pasteUpMorph\\n\\t\\t\\tifNil: [References removeKey: key]].\\n! !\\n\\n\\n!StandardScriptingSystem class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/11/2003 19:08'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(ScriptingSystem\\tprototypicalHolder\\t'Holder'\\t\\t'A place for storing alternative pictures in an animation, etc.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tprototypicalHolder\\t'Holder'\\t\\t'A place for storing alternative pictures in an animation, etc.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tnewScriptingSpace\\t'Scripting'\\t'A confined place for drawing and scripting, with its own private stop/step/go buttons.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(ScriptingSystem\\tholderWithAlphabet\\t'Alphabet'\\t'A source for single-letter objects')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Widgets'.]! !\\n\\n!StandardScriptingSystem class methodsFor: '*MorphicExtras-class initialization' stamp: 'asm 4/12/2003 14:38'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: ScriptingSystem] ! !\\n\\n\\n\\n!StandardScriptingSystem class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/8/2004 19:06'!\\nnoteAddedSelector: aSelector meta: isMeta\\n\\taSelector == #wordingForOperator: ifTrue:\\n\\t\\t[Vocabulary changeMadeToViewerAdditions].\\n\\tsuper noteAddedSelector: aSelector meta: isMeta! !\\n\\n!StandardScriptingSystem class methodsFor: '*flexibleVocabularies-flexibleVocabularies' stamp: 'NS 4/15/2004 12:41'!\\nnoteCompilationOf: aSelector meta: isMeta\\n\\t\\\"This method does nothing and should be removed.\\\"\\n\\n\\t^ super noteCompilationOf: aSelector meta: isMeta! !\\nSourceFileArray subclass: #StandardSourceFileArray\\n\\tinstanceVariableNames: 'files'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Files-System'!\\n!StandardSourceFileArray commentStamp: '<historical>' prior: 0!\\nThis class implements the source file management behavior of traditional Squeak, with a sources file and a changes file. File positions are mapped such that those files can be up to 32MBytes in size.\\n\\nStructure:\\n files\\t\\tArray -- storing the actual source files\\n!\\n\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nat: index\\n\\t^files at: index! !\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nat: index put: aFile\\n\\tfiles at: index put: aFile! !\\n\\n!StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'!\\nsize\\n\\t^files size! !\\n\\n\\n!StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninitialize\\n\\tfiles := Array new: 2.\\n\\tfiles at: 1 put: (SourceFiles at: 1).\\n\\tfiles at: 2 put: (SourceFiles at: 2)! !\\n\\n!StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'stephaneducasse 2/4/2006 20:32'!\\ninitialize: nFiles\\n\\tfiles := Array new: nFiles! !\\n\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfileIndexFromSourcePointer: anInteger\\n\\t\\\"Return the index of the source file which contains the source chunk addressed by anInteger\\\"\\n\\t\\\"This implements the recent 32M source file algorithm\\\"\\n\\n\\t| hi |\\n\\thi := anInteger // 16r1000000.\\n\\t^hi < 3\\n\\t\\tifTrue: [hi]\\n\\t\\tifFalse: [hi - 2]! !\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nfilePositionFromSourcePointer: anInteger\\n\\t\\\"Return the position of the source chunk addressed by anInteger\\\"\\n\\t\\\"This implements the recent 32M source file algorithm\\\"\\n\\n\\t| hi lo |\\n\\thi := anInteger // 16r1000000.\\n\\tlo := anInteger \\\\\\\\ 16r1000000.\\n\\t^hi < 3\\n\\t\\tifTrue: [lo]\\n\\t\\tifFalse: [lo + 16r1000000]! !\\n\\n!StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'stephaneducasse 2/4/2006 20:32'!\\nsourcePointerFromFileIndex: index andPosition: position\\n\\t| hi lo |\\n\\t\\\"Return a source pointer according to the new 32M algorithm\\\"\\n\\t((index between: 1 and: 2) and: [position between: 0 and: 16r1FFFFFF])\\n\\t\\tifFalse: [self error: 'invalid source code pointer'].\\n\\thi := index.\\n\\tlo := position.\\n\\tlo >= 16r1000000 ifTrue: [\\n\\t\\thi := hi+2.\\n\\t\\tlo := lo - 16r1000000].\\n\\t^hi * 16r1000000 + lo! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSourceFileArray class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'nk 7/30/2004 21:50'!\\ninstall\\n\\t\\\"Replace SourceFiles by an instance of me with the standard sources and changes files.\\n\\tThis only works if SourceFiles is either an Array or an instance of this class\\\"\\n\\n\\t\\\"StandardSourceFileArray install\\\"\\n\\n\\tSourceFiles := self new! !\\n\\n!StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'ar 5/17/2000 18:27'!\\nnew: nFiles\\n\\t^self new initialize: nFiles.! !\\nMouseMenuController subclass: #StandardSystemController\\n\\tinstanceVariableNames: 'status'\\n\\tclassVariableNames: 'HBorderCursor ScheduledBlueButtonMenu ScheduledBlueButtonMessages VBorderCursor'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StandardSystemController commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StandardSystemController methodsFor: 'basic control sequence' stamp: 'sw 10/20/1999 09:52'!\\ncontrolInitialize\\n\\tview displayEmphasized.\\n\\tview uncacheBits. \\\"Release cached bitmap while active\\\"\\n\\tmodel windowActiveOnFirstClick ifFalse: [sensor waitNoButton].\\n\\tstatus _ #active.\\n\\tview isCollapsed ifFalse: [model modelWakeUpIn: view]! !\\n\\n!StandardSystemController methodsFor: 'basic control sequence' stamp: 'di 5/11/1999 22:05'!\\ncontrolTerminate\\n\\tstatus == #closed\\n\\t\\tifTrue: \\n\\t\\t\\t[view ~~ nil ifTrue: [view release].\\n\\t\\t\\tScheduledControllers unschedule: self.\\n\\t\\t\\t^self].\\n\\tview deEmphasize; cacheBits.\\n\\tview isCollapsed ifFalse: [model modelSleep].! !\\n\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:45'!\\nadjustPaneBorders \\n\\t| side sub newRect outerFrame |\\n\\touterFrame _ view displayBox.\\n\\tside _ #none.\\n\\tVBorderCursor showWhile:\\n\\t\\t[ [sub _ view subviewWithLongestSide: [:s | side _ s]\\n\\t\\t\\t\\t\\t\\tnear: sensor cursorPoint.\\n\\t\\t self cursorOnBorder and: [(side = #left) | (side = #right)]]\\n\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\tself interActivityPause.\\n\\t\\t\\t\\tsensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[side = #left ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withLeft: sensor cursorPoint x)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tside = #right ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withRight: sensor cursorPoint x)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tview reframePanesAdjoining: sub along: side to: newRect]]].\\n\\tHBorderCursor showWhile:\\n\\t\\t[ [sub _ view subviewWithLongestSide: [:s | side _ s]\\n\\t\\t\\t\\t\\t\\tnear: sensor cursorPoint.\\n\\t\\t self cursorOnBorder and: [(side = #top) | (side = #bottom)]]\\n\\t\\t\\twhileTrue: [\\n\\t\\t\\t\\tself interActivityPause.\\n\\t\\t\\t\\tsensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[side = #top ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withTop: sensor cursorPoint y)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tside = #bottom ifTrue:\\n\\t\\t\\t\\t\\t[newRect _ sub stretchFrame:\\n\\t\\t\\t\\t\\t\\t[:f | (f withBottom: sensor cursorPoint y)\\n\\t\\t\\t\\t\\t\\t\\t\\tintersect: outerFrame]\\n\\t\\t\\t\\t\\t\\tstartingWith: sub displayBox].\\n\\t\\t\\t\\tview reframePanesAdjoining: sub along: side to: newRect]]]! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:22'!\\nadjustWindowBorders \\n\\t| side noClickYet |\\n\\tnoClickYet _ true.\\n\\tVBorderCursor showWhile:\\n\\t\\t[ [side _ view displayBox sideNearestTo: sensor cursorPoint.\\n\\t\\t self cursorOnBorder\\n\\t\\t\\tand: [(side = #left) | (side = #right)\\n\\t\\t\\tand: [noClickYet or: [sensor redButtonPressed]]]]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[sensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[noClickYet _ false.\\n\\t\\t\\t\\tside = #left ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withLeft: sensor cursorPoint x]].\\n\\t\\t\\t\\tside = #right ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withRight: sensor cursorPoint x]]].\\n\\t\\t\\tself interActivityPause]].\\n\\tHBorderCursor showWhile:\\n\\t\\t[ [side _ view displayBox sideNearestTo: sensor cursorPoint.\\n\\t\\t self cursorOnBorder\\n\\t\\t\\tand: [(side = #top) | (side = #bottom)\\n\\t\\t\\tand: [noClickYet or: [sensor redButtonPressed]]]]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[sensor redButtonPressed ifTrue:\\n\\t\\t\\t\\t[noClickYet _ false.\\n\\t\\t\\t\\tside = #top ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withTop: sensor cursorPoint y]].\\n\\t\\t\\t\\tside = #bottom ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame: [:f | f withBottom: sensor cursorPoint y]]].\\n\\t\\t self interActivityPause]]! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:38'!\\nadjustWindowCorners \\n\\t| box cornerBox p clicked f2 |\\n\\tbox _ view windowBox.\\n\\tclicked _ false.\\n\\t#(topLeft topRight bottomRight bottomLeft)\\n\\t\\tdo: [:readCorner |\\n\\t\\t\\tcornerBox _ ((box insetBy: 2) perform: readCorner) - (10@10) extent: 20@20.\\n\\t\\t\\t(cornerBox containsPoint: sensor cursorPoint)\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t[\\\"Display reverse: cornerBox.\\\"\\n\\t\\t\\t\\t(Cursor perform: readCorner) showWhile:\\n\\t\\t\\t\\t\\t[[(cornerBox containsPoint: (p _ sensor cursorPoint))\\n\\t\\t\\t\\t\\t\\tand: [(clicked _ sensor anyButtonPressed) not]]\\n\\t\\t\\t\\t\\t\\twhileTrue: [ self interActivityPause ].\\n\\t\\t\\t\\t\\\"Display reverse: cornerBox.\\\"\\n\\t\\t\\t\\tclicked ifTrue:\\n\\t\\t\\t\\t\\t[view newFrame:\\n\\t\\t\\t\\t\\t\\t[:f | p _ sensor cursorPoint.\\n\\t\\t\\t\\t\\t\\treadCorner = #topLeft ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ p corner: f bottomRight].\\n\\t\\t\\t\\t\\t\\treadCorner = #bottomLeft ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ (f withBottom: p y) withLeft: p x].\\n\\t\\t\\t\\t\\t\\treadCorner = #bottomRight ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ f topLeft corner: p].\\n\\t\\t\\t\\t\\t\\treadCorner = #topRight ifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[f2 _ (f withTop: p y) withRight: p x].\\n\\t\\t\\t\\t\\t\\tf2]]]]].\\n\\t^ clicked! !\\n\\n!StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:30'!\\ncheckForReframe\\n\\t| cp |\\n\\tview isCollapsed ifTrue: [^ self].\\n\\tcp _ sensor cursorPoint.\\n\\t((view closeBoxFrame expandBy: 2) containsPoint: cp)\\n\\t\\t| ((view growBoxFrame expandBy: 2) containsPoint: cp)\\n\\t\\tifTrue: [^ self]. \\\"Dont let reframe interfere with close/grow\\\"\\n\\tself adjustWindowCorners.\\n\\tself cursorOnBorder ifFalse: [^ self].\\n\\t((view insetDisplayBox insetBy: 2@2) containsPoint: cp)\\n\\t\\tifFalse: [^ self adjustWindowBorders].\\n\\tview subViews size <= 1 ifTrue: [^ self].\\n\\t(view subviewWithLongestSide: [:s | ] near: cp) == nil\\n\\t\\tifFalse: [^ self adjustPaneBorders].! !\\n\\n!StandardSystemController methodsFor: 'borders'!\\ncursorOnBorder \\n\\t| cp i box |\\n\\tview isCollapsed ifTrue: [^ false].\\n\\tcp _ sensor cursorPoint.\\n\\t((view labelDisplayBox insetBy: (0@2 corner: 0@-2)) containsPoint: cp)\\n\\t\\tifTrue: [^ false].\\n\\t(i _ view subViews findFirst: [:v | v displayBox containsPoint: cp]) = 0\\n\\t\\tifTrue: [box _ view windowBox]\\n\\t\\tifFalse: [box _ (view subViews at: i) insetDisplayBox].\\n\\t^ ((box insetBy: 3) containsPoint: cp) not\\n\\t\\tand: [(box expandBy: 4) containsPoint: cp]! !\\n\\n!StandardSystemController methodsFor: 'borders'!\\nfullScreen\\n\\t\\\"Make the receiver's window occupy jes' about the full screen. 6/10/96 sw\\\"\\n\\n\\tview fullScreen! !\\n\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:01'!\\nblueButtonActivity\\n\\tScheduledBlueButtonMenu ifNil: [^ super controlActivity].\\n\\tScheduledBlueButtonMenu invokeOn: self! !\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:20'!\\ncontrolActivity\\n\\tself checkForReframe.\\n\\t^ super controlActivity! !\\n\\n!StandardSystemController methodsFor: 'control defaults'!\\nisControlActive\\n\\tstatus == #active ifFalse: [^ false].\\n\\tsensor anyButtonPressed ifFalse: [^ true].\\n\\tself viewHasCursor\\n\\t\\tifTrue: [^ true]\\n\\t\\tifFalse: [ScheduledControllers noteNewTop.\\n\\t\\t\\t\\t^ false]! !\\n\\n!StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/15/2000 22:19'!\\nredButtonActivity\\n\\t\\\"If cursor is in label of a window when red button is pushed,\\n\\tcheck for closeBox or growBox, else drag the window frame\\n\\tor edit the label.\\\"\\n\\n\\t| box p |\\n\\tp _ sensor cursorPoint.\\n\\tself labelHasCursor ifFalse: [super redButtonActivity. ^ self].\\n\\t((box _ view closeBoxFrame) containsPoint: p)\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed: [self close. ^ self].\\n\\t\\t\\t^ self].\\n\\t((box _ view growBoxFrame) containsPoint: p)\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed:\\n\\t\\t\\t\\t\\t[Sensor controlKeyPressed ifTrue: [^ self expand; fullScreen].\\n\\t\\t\\t\\t\\t^ view isCollapsed\\n\\t\\t\\t\\t\\t\\tifTrue: [self expand]\\n\\t\\t\\t\\t\\t\\tifFalse: [self collapse]].\\n\\t\\t\\t^ self].\\n\\t(((box _ view labelTextRegion expandBy: 1) containsPoint: p)\\n\\t\\t\\tand: [Preferences clickOnLabelToEdit or: [sensor leftShiftDown]])\\n\\t\\tifTrue:\\n\\t\\t\\t[Utilities\\n\\t\\t\\t\\tawaitMouseUpIn: box\\n\\t\\t\\t\\trepeating: []\\n\\t\\t\\t\\tifSucceed: [^ self label].\\n\\t\\t\\t^ self].\\n\\tself move! !\\n\\n\\n!StandardSystemController methodsFor: 'cursor'!\\nlabelHasCursor\\n\\t\\\"Answer true if the cursor is within the window's label\\\"\\n\\t^view labelContainsPoint: sensor cursorPoint! !\\n\\n\\n!StandardSystemController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 11:48'!\\ninitialize\\n\\tsuper initialize.\\n\\tstatus _ #inactive! !\\n\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nchooseColor\\n\\t\\\"Allow the user to specify a new background color for the receiver's window. 5/6/96 sw.\\n\\t 7/31/96 sw: use Color fromUser\\\"\\n\\n\\tview backgroundColor: Color fromUser; uncacheBits; display! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nclose\\n\\t\\\"The receiver's view should be removed from the screen and from the \\n\\tcollection of scheduled views.\\\"\\n\\n\\tmodel okToChange ifFalse: [^self].\\n\\tstatus _ #closed.\\n\\tview erase! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\ncollapse\\n\\t\\\"Get the receiver's view to change to a collapsed view on the screen.\\\"\\n\\tview collapseToPoint: view chooseCollapsePoint! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nexpand\\n\\t\\\"The receiver's view was collapsed; open it again and ask the user to \\n\\tdesignate its rectangular area.\\\"\\n\\tview expand; emphasize! !\\n\\n!StandardSystemController methodsFor: 'menu messages' stamp: 'rbb 3/1/2005 11:14'!\\nlabel\\n\\n\\t| newLabel |\\n\\tnewLabel := UIManager default\\n\\t\\trequest: 'Edit the label, then type RETURN'\\n\\t\\tinitialAnswer: view label.\\n\\tnewLabel isEmpty ifFalse: [view relabel: newLabel].\\n! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nmove\\n\\t\\\"Ask the user to designate a new origin position for the receiver's view.\\n\\t6/10/96 sw: tell the view that it has moved\\\"\\n\\n\\t| oldBox | \\n\\toldBox _ view windowBox.\\n\\tview uncacheBits.\\n\\tview align: view windowBox topLeft\\n\\t\\twith: view chooseMoveRectangle topLeft.\\n\\tview displayEmphasized.\\n\\tview moved. \\\"In case its model wishes to take note.\\\"\\n\\t(oldBox areasOutside: view windowBox) do:\\n\\t\\t[:rect | ScheduledControllers restore: rect]! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nreframe\\n\\t^ view reframeTo: view getFrame! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\ntoggleTwoTone\\n\\t(view isMemberOf: StandardSystemView) ifTrue:\\n\\t\\t[^ view become: (view as: ColorSystemView)].\\n\\t(view isMemberOf: ColorSystemView) ifTrue:\\n\\t\\t[^ view become: (view as: StandardSystemView)].\\n! !\\n\\n!StandardSystemController methodsFor: 'menu messages'!\\nunder\\n\\t\\\"Deactive the receiver's scheduled view and pass control to any view that \\n\\tmight be positioned directly underneath it and the cursor.\\\"\\n\\n\\tstatus _ #inactive! !\\n\\n\\n!StandardSystemController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 15:12'!\\ngetPluggableYellowButtonMenu: shiftKeyState\\n\\t^ nil! !\\n\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'sw 9/30/97 22:04'!\\ncloseAndUnschedule\\n\\t\\\"Erase the receiver's view and remove it from the collection of scheduled \\n\\tviews.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview erase.\\n\\tview release.\\n\\tScheduledControllers unschedule: self; searchForActiveController\\n! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\ncloseAndUnscheduleNoErase\\n\\t\\\"Remove the scheduled view from the collection of scheduled views. Set \\n\\tits status to closed but do not erase.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview release.\\n\\tScheduledControllers unschedule: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'jm 3/18/98 19:21'!\\ncloseAndUnscheduleNoTerminate\\n\\t\\\"Erase the receiver's view and remove it from the collection of scheduled views, but do not terminate the current process.\\\"\\n\\n\\tstatus _ #closed.\\n\\tview erase.\\n\\tview release.\\n\\tScheduledControllers unschedule: self.\\n! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopen\\n\\t\\\"Create an area on the screen in which the receiver's scheduled view can \\n\\tbe displayed. Make it the active view.\\\"\\n\\n\\tview resizeInitially.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActive: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopenDisplayAt: aPoint \\n\\t\\\"Create an area with origin aPoint in which the receiver's scheduled \\n\\tview can be displayed. Make it the active view.\\\"\\n\\n\\tview align: view viewport center with: aPoint.\\n\\tview translateBy:\\n\\t\\t(view displayBox amountToTranslateWithin: Display boundingBox).\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActive: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling' stamp: 'jm 10/22/97 08:16'!\\nopenNoTerminate\\n\\t\\\"Create an area in which the receiver's scheduled view can be displayed. \\n\\tMake it the active view. Do not terminate the currently active process.\\\"\\n\\n\\tview resizeInitially.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActiveNoTerminate: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nopenNoTerminateDisplayAt: aPoint \\n\\t\\\"Create an area with origin aPoint in which the receiver's scheduled \\n\\tview can be displayed. Make it the active view. Do not terminate the \\n\\tcurrently active process.\\\"\\n\\n\\tview resizeMinimumCenteredAt: aPoint.\\n\\tstatus _ #open.\\n\\tScheduledControllers scheduleActiveNoTerminate: self! !\\n\\n!StandardSystemController methodsFor: 'scheduling'!\\nstatus: aSymbol\\n\\tstatus _ aSymbol! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSystemController class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSystemController class methodsFor: 'class initialization' stamp: 'sma 3/11/2000 11:57'!\\ninitialize\\n\\t\\\"StandardSystemController initialize\\\"\\n\\n\\tScheduledBlueButtonMenu _ SelectionMenu\\n\\t\\tlabels:\\n'edit label\\nchoose color...\\ntwo-tone/full color\\nmove\\nframe\\nfull screen\\ncollapse\\nclose'\\n\\tlines: #(3 7)\\n\\tselections: #(label chooseColor toggleTwoTone move reframe fullScreen collapse close).\\n\\n\\tVBorderCursor _ Cursor extent: 16@16 fromArray: #(\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010010000100000\\n\\t\\t2r1010110000110000\\n\\t\\t2r1011111111111000\\n\\t\\t2r1010110000110000\\n\\t\\t2r1010010000100000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000\\n\\t\\t2r1010000000000000)\\n\\t\\t\\toffset: 0@0.\\n\\tHBorderCursor _ Cursor extent: 16@16 fromArray: #(\\n\\t\\t2r1111111111111111\\n\\t\\t2r0000000000000000\\n\\t\\t2r1111111111111111\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000001110000000\\n\\t\\t2r0000011111000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000011111000000\\n\\t\\t2r0000001110000000\\n\\t\\t2r0000000100000000\\n\\t\\t2r0000000000000000\\n\\t\\t2r0000000000000000\\n\\t\\t2r0000000000000000)\\n\\t\\t\\toffset: 0@0.! !\\nTestCase subclass: #StandardSystemFontsTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support-Tests'!\\n\\n!StandardSystemFontsTest methodsFor: 'testing' stamp: 'bp 11/6/2004 23:15'!\\ntestRestoreDefaultFonts\\n\\n\\tself saveStandardSystemFontsDuring: [\\n\\t\\tPreferences restoreDefaultFonts.\\n\\t\\tself assert: #standardDefaultTextFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardListFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardFlapFont familyName: 'Accushi' pointSize: 12.\\n\\t\\tself assert: #standardEToysFont familyName: 'BitstreamVeraSans' pointSize: 9.\\n\\t\\tself assert: #standardMenuFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #windowTitleFont familyName: 'BitstreamVeraSans' pointSize: 12.\\n\\t\\tself assert: #standardBalloonHelpFont familyName: 'Accujen' pointSize: 9.\\n\\t\\tself assert: #standardCodeFont familyName: 'Accuny' pointSize: 10.\\n\\t\\tself assert: #standardButtonFont familyName: 'BitstreamVeraSansMono' pointSize: 9]! !\\n\\n\\n!StandardSystemFontsTest methodsFor: 'utilities' stamp: 'bp 6/13/2004 18:22'!\\nassert: selector familyName: aString pointSize: anInteger\\n\\n\\t| font |\\n\\tfont _ Preferences perform: selector.\\n\\tself assert: font familyName = aString.\\n\\tself assert: font pointSize = anInteger\\n\\t! !\\n\\n!StandardSystemFontsTest methodsFor: 'utilities' stamp: 'bp 6/13/2004 21:51'!\\nsaveStandardSystemFontsDuring: aBlock\\n\\n\\t| standardDefaultTextFont standardListFont standardEToysFont standardMenuFont \\n\\twindowTitleFont standardBalloonHelpFont standardCodeFont standardButtonFont |\\n\\n\\tstandardDefaultTextFont _ Preferences standardDefaultTextFont.\\n\\tstandardListFont _ Preferences standardListFont.\\n\\tstandardEToysFont _ Preferences standardEToysFont.\\n\\tstandardMenuFont _ Preferences standardMenuFont.\\n\\twindowTitleFont _ Preferences windowTitleFont.\\n\\tstandardBalloonHelpFont _ Preferences standardBalloonHelpFont.\\n\\tstandardCodeFont _ Preferences standardCodeFont.\\n\\tstandardButtonFont _ Preferences standardButtonFont.\\n\\t[aBlock value] ensure: [\\n\\t\\tPreferences setSystemFontTo: standardDefaultTextFont.\\n\\t\\tPreferences setListFontTo: standardListFont.\\n\\t\\tPreferences setEToysFontTo: standardEToysFont.\\n\\t\\tPreferences setMenuFontTo: standardMenuFont.\\n\\t\\tPreferences setWindowTitleFontTo: windowTitleFont.\\n\\t\\tPreferences setBalloonHelpFontTo: standardBalloonHelpFont.\\n\\t\\tPreferences setCodeFontTo: standardCodeFont.\\n\\t\\tPreferences setButtonFontTo: standardButtonFont].\\n! !\\nView subclass: #StandardSystemView\\n\\tinstanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes'\\n\\tclassVariableNames: 'CacheBits LabelStyle'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StandardSystemView commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StandardSystemView methodsFor: 'clipping box access'!\\nclippingBox\\n\\t\\\"Answer the rectangular area in which the receiver can show its label.\\\"\\n\\n\\t^self isTopView\\n\\t\\tifTrue: [self labelDisplayBox]\\n\\t\\tifFalse: [super insetDisplayBox]! !\\n\\n!StandardSystemView methodsFor: 'clipping box access' stamp: 'BG 12/5/2003 11:13'!\\nconstrainFrame: aRectangle\\n\\t\\\"Constrain aRectangle, to the minimum and maximum size\\n\\tfor this window\\\"\\n\\n | adjustmentForLabel |\\n adjustmentForLabel := 0 @ (labelFrame height - labelFrame borderWidth).\\n\\t^ aRectangle origin extent:\\n\\t\\t((aRectangle extent max: minimumSize + adjustmentForLabel)\\n\\t\\t min: maximumSize + adjustmentForLabel).! !\\n\\n\\n!StandardSystemView methodsFor: 'controller access'!\\ndefaultControllerClass \\n\\t\\\"Refer to the comment in View|defaultControllerClass.\\\"\\n\\n\\t^StandardSystemController! !\\n\\n\\n!StandardSystemView methodsFor: 'deEmphasizing'!\\ndeEmphasizeView \\n\\t\\\"Refer to the comment in View|deEmphasizeView.\\\"\\n\\n\\tisLabelComplemented ifTrue:\\n\\t\\t[self deEmphasizeLabel.\\n\\t\\tisLabelComplemented _ false]! !\\n\\n!StandardSystemView methodsFor: 'deEmphasizing'!\\nemphasizeView \\n\\t\\\"Refer to the comment in View|emphasizeView.\\\"\\n\\n\\tself emphasizeLabel! !\\n\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBits\\n\\t| oldLabelState |\\n\\tCacheBits ifFalse: [^ self uncacheBits].\\n\\t(oldLabelState _ isLabelComplemented) ifTrue: [ self deEmphasize ].\\n\\tself cacheBitsAsIs.\\n\\t(isLabelComplemented _ oldLabelState) ifTrue: [ self emphasize ].\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBitsAsIs\\n\\tCacheBits ifFalse: [^ self uncacheBits].\\n\\twindowBits _ (self cacheBitsAsTwoTone and: [Display depth > 1])\\n\\t\\tifTrue: [ColorForm\\n\\t\\t\\t\\t\\ttwoToneFromDisplay: self windowBox\\n\\t\\t\\t\\t\\tusing: windowBits\\n\\t\\t\\t\\t\\tbackgroundColor: self backgroundColor]\\n\\t\\tifFalse: [Form fromDisplay: self windowBox using: windowBits].\\n\\tbitsValid _ true.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ncacheBitsAsTwoTone\\n\\t^ true! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndeEmphasizeForDebugger\\n\\t\\\"Carefully de-emphasis this window because a debugger is being opened. Care must be taken to avoid invoking potentially buggy window display code that could cause a recursive chain of errors eventually resulting in a virtual machine crash. In particular, do not de-emphasize the subviews.\\\"\\n\\n\\tself deEmphasizeView. \\\"de-emphasize this top-level view\\\"\\n\\tself uncacheBits.\\n\\tSmalltalk garbageCollectMost > 1000000 ifTrue: [\\n\\t\\t\\\"if there is enough space, cache current window screen bits\\\"\\n\\t\\tself cacheBitsAsIs].\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'!\\ndeEmphasizeLabel\\n\\t\\\"Un-Highlight the label.\\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayLabelBackground: false.\\n\\tself displayLabelText.! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplay\\n\\tisLabelComplemented\\n\\t\\tifTrue: [self displayEmphasized]\\n\\t\\tifFalse: [self displayDeEmphasized]! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'hmm 7/21/1999 07:37'!\\ndisplayDeEmphasized \\n\\t\\\"Display this view with emphasis off.\\n\\tIf windowBits is not nil, then simply BLT if possible,\\n\\t\\tbut force full display for top window so color is preserved.\\\"\\n\\t(bitsValid and: [controller ~~ ScheduledControllers activeController])\\n\\t\\tifTrue: [self lock.\\n\\t\\t\\t\\twindowBits displayAt: self windowOrigin]\\n\\t\\tifFalse: [Display deferUpdates: true.\\n\\t\\t\\t\\tsuper display.\\n\\t\\t\\t\\tDisplay deferUpdates: false; forceToScreen: self windowBox.\\n\\t\\t\\t\\tCacheBits ifTrue: [self cacheBitsAsIs]]\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplayEmphasized\\n\\t\\\"Display with label highlighted to indicate that it is active.\\\"\\n\\n\\tself displayDeEmphasized; emphasize.\\n\\tisLabelComplemented _ true! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 5/15/1998 21:55'!\\ndisplayLabelBackground: emphasized\\n\\t\\\"Clear or emphasize the inner region of the label\\\"\\n\\t| r1 r2 r3 c3 c2 c1 |\\n\\temphasized ifFalse:\\n\\t\\t[\\\"Just clear the label if not emphasized\\\"\\n\\t\\t^ Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor].\\n\\tr1 _ self labelDisplayBox insetBy: 2.\\n\\tr2 _ r1 insetBy: 0@2.\\n\\tr3 _ r2 insetBy: 0@3.\\n\\tc3 _ self labelColor.\\n\\tc2 _ c3 dansDarker.\\n\\tc1 _ c2 dansDarker.\\n\\tDisplay fill: r1 fillColor: c1.\\n\\tDisplay fill: r2 fillColor: c2.\\n\\tDisplay fill: r3 fillColor: c3.\\n \\n\\\"\\tHere is the Mac racing stripe code\\n\\tstripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth)\\n\\t\\t\\t\\t\\twith: (Form black pixelWordForDepth: Display depth).\\n\\tself windowOrigin y even ifTrue: [stripes swap: 1 with: 2].\\n\\tDisplay fill: (self labelDisplayBox insetBy: 3) fillColor: stripes.\\n\\\"! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\ndisplayLabelBoxes\\n\\t\\\"closeBox, growBox.\\\"\\n\\t| aRect smallRect backColor |\\n\\taRect _ self closeBoxFrame.\\n\\tbackColor _ self labelColor.\\n\\tDisplay fill: (aRect insetBy: -2) fillColor: backColor.\\n\\tDisplay fillBlack: aRect.\\n\\tDisplay fill: (aRect insetBy: 1) fillColor: backColor.\\n\\n\\taRect _ self growBoxFrame.\\n\\tsmallRect _ aRect origin extent: 7@7.\\n\\tDisplay fill: (aRect insetBy: -2) fillColor: backColor.\\n\\taRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0.\\n\\tDisplay fillBlack: aRect.\\n\\tDisplay fill: (aRect insetBy: 1) fillColor: backColor.\\n\\tDisplay fillBlack: smallRect.\\n\\tDisplay fill: (smallRect insetBy: 1) fillColor: backColor! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 9/10/1998 09:43'!\\ndisplayLabelText\\n\\t\\\"The label goes in the center of the window\\\"\\n\\t| labelRect |\\n\\tlabelText foregroundColor: self foregroundColor\\n\\t\\t\\tbackgroundColor: self labelColor.\\n\\tlabelRect _ self labelTextRegion.\\n\\tDisplay fill: (labelRect expandBy: 3@0) fillColor: self labelColor.\\n\\tlabelText displayOn: Display at: labelRect topLeft clippingBox: labelRect\\n\\t\\t\\trule: labelText rule fillColor: labelText fillColor.\\n\\tlabelText destinationForm: nil! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 8/29/97 18:57'!\\ndisplayOn: aPort\\n\\tbitsValid ifFalse:\\n\\t\\t[^ Display clippingTo: aPort clipRect do: [super display]].\\n\\twindowBits displayOnPort: aPort at: self windowOrigin! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'ar 5/14/2001 23:40'!\\ndisplayRacingStripes\\n\\t\\\"Display Racing Stripes in the label\\\"\\n\\t| labelDisplayBox stripes top bottom left box right |\\n\\tlabelDisplayBox _ self labelDisplayBox.\\n\\ttop _ labelDisplayBox top + 3.\\n\\tbottom _ labelDisplayBox bottom - 3.\\n\\tstripes _ Bitmap with: (Display pixelWordFor: self labelColor)\\n\\t\\t\\twith: (Display pixelWordFor: Color black).\\n\\ttop even ifFalse: [stripes swap: 1 with: 2].\\n\\n\\tleft _ labelDisplayBox left + 3.\\n\\n\\tbox _ self closeBoxFrame.\\n\\tright _ box left - 2.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tbox _ self labelTextRegion.\\n\\tright _ box left - 3.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tbox _ self growBoxFrame.\\n\\tright _ box left - 2.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n\\tleft _ box right + 2.\\n\\n\\tright _ labelDisplayBox right - 3.\\n\\tDisplay fill: (Rectangle left: left right: right top: top bottom: bottom)\\n\\t\\t\\tfillColor: stripes.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:14'!\\ndisplayView\\n\\t\\\"Refer to the comment in View|displayView. \\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayBox width = labelFrame width ifFalse:\\n\\t\\t[\\\"recompute label width when window changes size\\\"\\n\\t\\tself setLabelRegion].\\n\\t(labelFrame align: labelFrame topLeft with: self windowOrigin)\\n\\t\\tinsideColor: self labelColor;\\n\\t\\tdisplayOn: Display.\\n\\tself displayLabelText! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'!\\nemphasizeLabel\\n\\t\\\"Highlight the label.\\\"\\n\\tlabelFrame height = 0 ifTrue: [^ self]. \\\"no label\\\"\\n\\tself displayLabelBackground: true.\\n\\tself displayLabelBoxes.\\n\\tself displayLabelText.! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'di 8/30/97 11:07'!\\nerase\\n\\t\\\"Clear the display box of the receiver to be gray, as the screen background.\\\"\\n\\t| oldValid |\\n\\tCacheBits\\n\\t\\tifTrue:\\n\\t\\t\\t[oldValid _ bitsValid.\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tScheduledControllers restore: self windowBox without: self.\\n\\t\\t\\tbitsValid _ oldValid]\\n\\t\\tifFalse:\\n\\t\\t\\t[ScheduledControllers restore: self windowBox without: self]! !\\n\\n!StandardSystemView methodsFor: 'displaying' stamp: 'RAA 6/14/2000 17:27'!\\nmakeMeVisible\\n\\n | newLoc portRect |\\n ((Display boundingBox insetBy: (0@0 corner: self labelHeight asPoint))\\n containsPoint: self displayBox topLeft) ifTrue: [^ self \\\"OK -- my top left is visible\\\"].\\n\\n \\\"window not on screen (probably due to reframe) -- move it now\\\"\\n newLoc _ self isCollapsed\\n ifTrue: [RealEstateAgent assignCollapsePointFor: self]\\n ifFalse: [(RealEstateAgent initialFrameFor: self world: nil) topLeft].\\n portRect _ newLoc + self labelOffset\\n extent: self windowBox extent - self labelOffset.\\n self resizeTo: portRect.\\n self setLabelRegion.\\n! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\nuncacheBits\\n\\twindowBits _ nil.\\n\\tbitsValid _ false.! !\\n\\n!StandardSystemView methodsFor: 'displaying'!\\nwindowBits\\n\\t^ windowBits! !\\n\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sr 3/26/2000 03:47'!\\nchooseCollapsePoint\\n\\t\\\"Answer the point at which to place the collapsed window.\\\"\\n\\t| pt labelForm beenDown offset |\\n\\tlabelForm _ Form fromDisplay: self labelDisplayBox.\\n\\tself uncacheBits.\\n\\tself erase.\\n\\tbeenDown _ Sensor anyButtonPressed.\\n\\tself isCollapsed ifTrue:\\n\\t\\t[offset _ self labelDisplayBox topLeft - self growBoxFrame topLeft.\\n\\t\\tlabelForm follow: [pt _ (Sensor cursorPoint + offset max: 0@0) truncateTo: 8]\\n\\t\\t\\t\\twhile: [Sensor anyButtonPressed\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [beenDown _ true]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [beenDown not]].\\n\\t\\t^ pt].\\n\\t^ (RealEstateAgent assignCollapseFrameFor: self) origin.\\n! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nchooseFrame\\n\\t\\\"Answer a new frame, depending on whether the view is currently \\n\\tcollapsed or not.\\\"\\n\\t| labelForm f |\\n\\tself isCollapsed & expandedViewport notNil\\n\\t\\tifTrue:\\n\\t\\t\\t[labelForm _ bitsValid\\n\\t\\t\\t\\tifTrue: [windowBits]\\n\\t\\t\\t\\tifFalse: [Form fromDisplay: self labelDisplayBox].\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tself erase.\\n\\t\\t\\tlabelForm slideFrom: self labelDisplayBox origin\\n\\t\\t\\t\\t\\tto: expandedViewport origin-self labelOffset\\n\\t\\t\\t\\t\\tnSteps: 10.\\n\\t\\t\\t^ expandedViewport]\\n\\t\\tifFalse:\\n\\t\\t\\t[f _ self getFrame.\\n\\t\\t\\tbitsValid _ false.\\n\\t\\t\\tself erase.\\n\\t\\t\\t^ f topLeft + self labelOffset extent: f extent]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nchooseMoveRectangle\\n\\t\\\"Ask the user to designate a new window rectangle.\\\"\\n\\t| offset p |\\n\\toffset _ Sensor anyButtonPressed \\\"Offset if draggin, eg, label\\\"\\n\\t\\tifTrue: [self windowBox topLeft - Sensor cursorPoint]\\n\\t\\tifFalse: [0@0].\\n\\tself isCollapsed\\n\\t\\tifTrue: [^ self labelDisplayBox newRectFrom:\\n\\t\\t\\t\\t\\t[:f | p _ Sensor cursorPoint + offset.\\n\\t\\t\\t\\t\\tp _ (p max: 0@0) truncateTo: 8.\\n\\t\\t\\t\\t\\tp extent: f extent]]\\n\\t\\tifFalse: [^ self windowBox newRectFrom:\\n\\t\\t\\t\\t\\t[:f | p _ Sensor cursorPoint + offset.\\n\\t\\t\\t\\t\\tself constrainFrame: (p extent: f extent)]]! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 5/11/1999 22:09'!\\ncollapse\\n\\t\\\"If the receiver is not already collapsed, change its view to be that of its \\n\\tlabel only.\\\"\\n\\n\\tself isCollapsed ifFalse:\\n\\t\\t\\t[model modelSleep.\\n\\t\\t\\t(subViews ~~ nil and: [subViews size = 1 and: [subViews first isKindOf: MorphWorldView]])\\n\\t\\t\\t\\tifTrue: [subViews first deEmphasizeView].\\n\\t\\t\\texpandedViewport _ self viewport.\\n\\t\\t\\tsavedSubViews _ subViews.\\n\\t\\t\\tself resetSubViews.\\n\\t\\t\\tlabelText isNil ifTrue: [self label: nil. bitsValid _ false.].\\n\\t\\t\\tself window: (self inverseDisplayTransform:\\n\\t\\t\\t\\t\\t((self labelDisplayBox topLeft extent: (labelText extent x + 70) @ self labelHeight)\\n\\t\\t\\t\\t\\t\\t intersect: self labelDisplayBox))]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ncollapseToPoint: collapsePoint\\n\\tself collapse.\\n\\tself align: self displayBox topLeft with: collapsePoint.\\n\\tcollapsedViewport _ self viewport.\\n\\tself displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ncollapsedFrame\\n\\t\\\"Answer the rectangle occupied by this window when collapsed.\\\"\\n\\t^ collapsedViewport \\\"NOTE may be nil\\\"! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 10/20/1999 09:46'!\\nexpand\\n\\t\\\"If the receiver is collapsed, change its view to be that of all of its subviews, not its label alone.\\\"\\n\\t| newFrame |\\n\\tself isCollapsed\\n\\t\\tifTrue:\\n\\t\\t\\t[newFrame _ self chooseFrame expandBy: borderWidth.\\n\\t\\t\\tcollapsedViewport _ self viewport.\\n\\t\\t\\tsubViews _ savedSubViews.\\n\\t\\t\\tlabelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\t\\t\\tsavedSubViews _ nil.\\n\\t\\t\\tself setWindow: nil.\\n\\t\\t\\tself resizeTo: newFrame.\\n\\t\\t\\tself displayDeEmphasized.\\n\\t\\t\\tmodel modelWakeUpIn: self]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nexpandedFrame\\n\\t\\\"Answer the rectangle occupied by this window when expanded.\\\"\\n\\t^ expandedViewport \\\"NOTE may be nil\\\"! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 8/15/97 17:18'!\\nfullScreen\\n\\t\\\"Expand the receiver to fill the screen. Let the model decide how big is full -- allows for flop-out scrollbar on left if desired\\\"\\n\\n\\tself isCollapsed ifFalse:\\n\\t\\t[self reframeTo: model fullScreenSize]! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\ngetFrame\\n\\t\\\"Ask the user to designate a rectangular area in which\\n\\tthe receiver should be displayed.\\\"\\n\\t| minFrame |\\n\\tminFrame _ Cursor origin showWhile: \\n\\t\\t[(Sensor cursorPoint extent: self minimumSize) newRectFrom:\\n\\t\\t\\t[:f | Sensor cursorPoint extent: self minimumSize]].\\n\\tself maximumSize <= self minimumSize ifTrue: [^ minFrame].\\n\\t^ Cursor corner showWhile:\\n\\t\\t[minFrame newRectFrom:\\n\\t\\t\\t[:f | self constrainFrame: (f origin corner: Sensor cursorPoint)]]! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'sw 1/22/96'!\\ninitialExtent\\n\\t\\\"Answer the desired extent for the receiver when it is first opened on the screen. \\\"\\n\\n\\t^ model initialExtent min: maximumSize max: minimumSize! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'RAA 6/14/2000 17:27'!\\ninitialFrame\\n \\\"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\\\"\\n\\n ^ RealEstateAgent initialFrameFor: self world: nil! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nmoved\\n\\t\\\"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\\\" ! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nnewFrame: frameChangeBlock\\n\\tself reframeTo: (self windowBox newRectFrom:\\n\\t\\t[:f | self constrainFrame: (frameChangeBlock value: f)])! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 10/22/1998 16:15'!\\nreframePanesAdjoining: subView along: side to: aDisplayBox \\n\\t| newBox delta newRect minDim theMin |\\n\\tnewRect _ aDisplayBox.\\n\\ttheMin _ 16.\\n\\t\\\"First check that this won't make any pane smaller than theMin screen dots\\\"\\n\\tminDim _ ((subViews select: [:sub | sub displayBox bordersOn: subView displayBox along: side])\\n\\t\\tcollect: [:sub | sub displayBox adjustTo: newRect along: side])\\n\\t\\t\\tinject: 999 into: [:was :rect | (was min: rect width) min: rect height].\\n\\t\\\"If so, amend newRect as required\\\"\\n\\tminDim < theMin ifTrue:\\n\\t\\t[delta _ minDim - theMin.\\n\\t\\tnewRect _ newRect withSide: side setTo: \\n\\t\\t\\t\\t((newRect perform: side) > (subView displayBox perform: side)\\n\\t\\t\\t\\t\\tifTrue: [(newRect perform: side) + delta]\\n\\t\\t\\t\\t\\tifFalse: [(newRect perform: side) - delta])].\\n\\t\\\"Now adjust all adjoining panes for real\\\"\\n\\tsubViews do:\\n\\t\\t[:sub | (sub displayBox bordersOn: subView displayBox along: side) ifTrue:\\n\\t\\t\\t[newBox _ sub displayBox adjustTo: newRect along: side.\\n\\t\\t\\tsub window: sub window viewport:\\n\\t\\t\\t\\t(sub transform: (sub inverseDisplayTransform: newBox)) rounded]].\\n\\t\\\"And adjust the growing pane itself\\\"\\n\\tsubView window: subView window viewport:\\n\\t\\t\\t(subView transform: (subView inverseDisplayTransform: newRect)) rounded.\\n\\n\\t\\\"Finally force a recomposition of the whole window\\\"\\n\\tviewport _ nil.\\n\\tself resizeTo: self viewport.\\n\\tself uncacheBits; displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'BG 12/4/2003 13:14'!\\nreframeTo: newFrame\\n\\t\\\"Reframe the receiver to the given screen rectangle. \\n\\tRepaint difference after the change. \\\"\\n\\t| oldBox newBox portRect |\\n\\tself uncacheBits.\\n\\toldBox _ self windowBox.\\n\\tportRect _ newFrame topLeft + self labelOffset\\n\\t\\t\\t\\tcorner: newFrame corner.\\n\\tself setWindow: nil.\\n\\tself resizeTo: portRect.\\n\\tself setLabelRegion.\\n\\tnewBox _ self windowBox.\\n\\t(oldBox areasOutside: newBox) do:\\n\\t\\t[:rect | ScheduledControllers restore: rect].\\n\\tself displayEmphasized! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nresize\\n\\t\\\"Determine the rectangular area for the receiver, adjusted to the \\n\\tminimum and maximum sizes.\\\"\\n\\t| f |\\n\\tf _ self getFrame.\\n\\tself resizeTo: (f topLeft + self labelOffset extent: f extent)\\n! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nresizeInitially\\n\\t\\\"Determine the rectangular area for the receiver, adjusted to the \\n\\tminimum and maximum sizes.\\\"\\n\\tself resizeTo: self initialFrame\\n! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:12'!\\nresizeMinimumCenteredAt: aPoint \\n\\t\\\"Determine the rectangular area for the receiver, adjusted so that it is \\n\\tcentered a position, aPoint.\\\"\\n\\t| aRectangle |\\n\\taRectangle _ 0 @ 0 extent: self minimumSize.\\n\\taRectangle _ aRectangle align: aRectangle center with: aPoint.\\n\\tself resizeTo: aRectangle! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:29'!\\nresizeTo: aRectangle\\n\\t\\\"Resize this view to aRectangle\\\"\\n\\n\\t\\\"First get scaling right inside borders\\\"\\n\\tself window: (self window insetBy: borderWidth)\\n\\t\\tviewport: (aRectangle insetBy: borderWidth).\\n\\n\\t\\\"Then ensure window maps to aRectangle\\\"\\n\\twindow _ transformation applyInverseTo: aRectangle! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nstandardWindowOffset\\n\\t^ Preferences standardWindowOffset! !\\n\\n!StandardSystemView methodsFor: 'framing'!\\nwindowBox\\n\\t^ self displayBox merge: self labelDisplayBox! !\\n\\n!StandardSystemView methodsFor: 'framing' stamp: 'di 10/3/97 14:19'!\\nwindowOrigin\\n\\t^ (self isCollapsed or: [labelFrame height = 0 \\\"no label\\\"])\\n\\t\\tifTrue: [self displayBox topLeft]\\n\\t\\tifFalse: [self displayBox topLeft - self labelOffset]! !\\n\\n\\n!StandardSystemView methodsFor: 'initialize-release' stamp: 'sw 10/29/1999 12:58'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\tsuper initialize.\\n\\tlabelFrame _ Quadrangle new.\\n\\tlabelFrame region: (Rectangle origin: 0 @ 0 extent: 50 @ self labelHeight).\\n\\tlabelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\tself label: nil.\\n\\tisLabelComplemented _ false.\\n\\tminimumSize _ 50 @ 50.\\n\\tmaximumSize _ Display extent.\\n\\tcollapsedViewport _ nil.\\n\\texpandedViewport _ nil.\\n\\tbitsValid _ false.\\n\\tupdatablePanes _ #()! !\\n\\n!StandardSystemView methodsFor: 'initialize-release'!\\nmodel: aModel\\n\\t\\\"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\\\"\\n\\tsuper model: aModel.\\n\\tself setDefaultBackgroundColor! !\\n\\n!StandardSystemView methodsFor: 'initialize-release' stamp: 'jm 8/20/1998 18:29'!\\nrelease\\n\\n\\tmodel windowIsClosing.\\n\\tself isCollapsed ifTrue: [savedSubViews do: [:v | v release]].\\n\\tsuper release.\\n! !\\n\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:30'!\\ncloseBoxFrame\\n\\t^ Rectangle origin: (self labelDisplayBox leftCenter + (10@-5)) extent: (11@11)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:29'!\\ngrowBoxFrame\\n\\t^ Rectangle origin: (self labelDisplayBox rightCenter + (-22@-5)) extent: (11@11)! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabel\\n\\t\\\"Answer the string that appears in the receiver's label.\\\"\\n\\tlabelText isNil\\n\\t\\tifTrue: [^ 'Untitled' copy]\\n\\t\\tifFalse: [^ labelText asString]! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:44'!\\nlabel: aString \\n\\t\\\"Set aString to be the receiver's label.\\\"\\n\\tlabelText _ Paragraph\\n\\t\\t\\twithText: (Text string: ((aString == nil or: [aString isEmpty])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: ['Untitled' copy]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [aString])\\n\\t\\t\\t\\t\\t\\t\\tattributes: (Array with: TextEmphasis bold))\\n\\t\\t\\tstyle: LabelStyle.\\n\\tinsetDisplayBox == nil ifTrue: [^ self]. \\\"wait for further initialization\\\"\\n\\tself setLabelRegion! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelColor\\n\\t\\\"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\\\"\\n\\n\\t^ self backgroundColor! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelDisplayBox\\n\\t\\\"Answer the rectangle that borders the visible parts of the receiver's label \\n\\ton the display screen.\\\"\\n\\n\\t^ labelFrame region\\n\\t\\talign: labelFrame topLeft\\n\\t\\twith: self windowOrigin! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelFrame\\n\\t^labelFrame! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:47'!\\nlabelHeight\\n\\t^ ((LabelStyle fontAt: 1) height + 4) max: 20! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelOffset\\n\\t^ 0 @ (self labelHeight-2)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sr 3/26/2000 04:26'!\\nlabelText\\n\\t^labelText! !\\n\\n!StandardSystemView methodsFor: 'label access'!\\nlabelTextRegion\\n\\tlabelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0].\\n\\t^ (labelText boundingBox\\n\\t\\t\\talign: labelText boundingBox center\\n\\t\\t\\twith: self labelDisplayBox center)\\n\\t\\tintersect: (self labelDisplayBox insetBy: 35@0)! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 14:20'!\\nnoLabel\\n\\t\\\"A label of zero height indicates no label\\\"\\n\\tlabelFrame height > 0\\n\\t\\tifTrue: [labelFrame region: (labelFrame bottomLeft + (0@1) extent: labelFrame width@0).\\n\\t\\t\\t\\tlabelFrame borderWidth: 0.\\n\\t\\t\\t\\tself uncacheBits]! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 6/10/1998 13:18'!\\nrelabel: aString \\n\\t\\\"A new string for the label. Window is assumed to be active.\\n\\tWindow will redisplay only if label bar has to grow.\\\"\\n\\t| oldRegion oldWidth |\\n\\t(model windowReqNewLabel: aString) ifFalse: [^ self].\\n\\toldRegion _ self labelTextRegion.\\n\\toldWidth _ self insetDisplayBox width.\\n\\tself label: aString.\\n\\tDisplay fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0)\\n\\t\\t\\tfillColor: self labelColor.\\n\\tself insetDisplayBox width = oldWidth\\n\\t\\tifTrue: [self displayLabelText; emphasizeLabel]\\n\\t\\tifFalse: [self uncacheBits; displayEmphasized].\\n! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sw 1/19/2001 20:13'!\\nsetLabel: aLabel\\n\\t\\\"For compatibility with morphic\\\"\\n\\n\\tself relabel: aLabel! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 13:35'!\\nsetLabelRegion\\n\\t\\\"Always follows view width\\\"\\n\\n\\tlabelFrame region: (0 @ 0 extent: self displayBox width @ self labelHeight).\\n\\tlabelFrame borderWidth: 2! !\\n\\n!StandardSystemView methodsFor: 'label access' stamp: 'sumim 2/8/2002 14:36'!\\nsetLabelTo: aString \\n\\t\\\"Force aString to be the new label of the receiver, bypassing any logic about whether it is acceptable and about propagating information about the change.\\\"\\n\\n\\t| oldRegion oldWidth |\\n\\tself label: aString.\\n\\tself controller isControlActive ifFalse: [^ self].\\n\\toldRegion _ self labelTextRegion.\\n\\toldWidth _ self insetDisplayBox width.\\n\\tDisplay fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0)\\n\\t\\t\\tfillColor: self labelColor.\\n\\tself insetDisplayBox width = oldWidth\\n\\t\\tifTrue: [self displayLabelText; emphasizeLabel]\\n\\t\\tifFalse: [self uncacheBits; displayEmphasized]! !\\n\\n\\n!StandardSystemView methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:49'!\\nconvertToCurrentVersion: varDict refStream: smartRefStrm\\n\\t\\n\\tupdatablePanes ifNil: [updatablePanes _ #()].\\n\\t^super convertToCurrentVersion: varDict refStream: smartRefStrm.\\n\\n! !\\n\\n\\n!StandardSystemView methodsFor: 'size'!\\nmaximumSize\\n\\t\\\"Answer a point representing the maximum width and height of the \\n\\treceiver.\\\"\\n\\n\\t^maximumSize! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nmaximumSize: aPoint \\n\\t\\\"Set the argument, aPoint, to be the maximum width and height of the \\n\\treceiver.\\\"\\n\\n\\tmaximumSize _ aPoint! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nminimumSize\\n\\t\\\"Answer a point representing the minimum width and height of the \\n\\treceiver.\\\"\\n\\n\\t^minimumSize! !\\n\\n!StandardSystemView methodsFor: 'size'!\\nminimumSize: aPoint \\n\\t\\\"Set the argument, aPoint, to be the minimum width and height of the \\n\\treceiver.\\\"\\n\\n\\tminimumSize _ aPoint! !\\n\\n\\n!StandardSystemView methodsFor: 'testing'!\\ncontainsPoint: aPoint \\n\\t\\\"Refer to the comment in View|containsPoint:.\\\"\\n\\n\\t^(super containsPoint: aPoint) | (self labelContainsPoint: aPoint)! !\\n\\n!StandardSystemView methodsFor: 'testing'!\\nisCollapsed\\n\\t\\\"Answer whether the receiver is collapsed (true) or expanded (false).\\\"\\n\\n\\t^savedSubViews ~~ nil! !\\n\\n!StandardSystemView methodsFor: 'testing'!\\nlabelContainsPoint: aPoint \\n\\t\\\"Answer TRUE if aPoint is in the label box.\\\"\\n\\n\\t^self labelDisplayBox containsPoint: aPoint! !\\n\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 12:57'!\\nsetUpdatablePanesFrom: getSelectors\\n\\t| aList aPane |\\n\\t\\\"Set my updatablePanes inst var to the list of panes which are list panes with the given get-list selectors. Order is important here!! Note that the method is robust in the face of panes not found, but a warning is printed in the transcript in each such case\\\"\\n\\n\\taList _ OrderedCollection new.\\n\\tgetSelectors do:\\n\\t\\t[:sel | aPane _ self subViewSatisfying:\\n\\t\\t\\t\\t[:pane | (pane isKindOf: PluggableListView) and: [pane getListSelector == sel]].\\n\\t\\t\\taPane\\n\\t\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t\\t[aList add: aPane]\\n\\t\\t\\t\\tifNil:\\n\\t\\t\\t\\t\\t[Transcript cr; show: 'Warning: view ', sel, ' not found.']].\\n\\tupdatablePanes _ aList asArray! !\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:20'!\\nupdatablePanes\\n\\t\\\"Answer the list of panes, in order, which might be sent the #verifyContents message upon window activation or expansion.\\\"\\n\\t^ updatablePanes ifNil: [updatablePanes _ #()]! !\\n\\n!StandardSystemView methodsFor: 'updating' stamp: 'sw 1/11/2000 15:30'!\\nupdate: aSymbol\\n\\taSymbol = #relabel\\n\\t\\tifTrue: [^ self setLabelTo: model labelString].\\n\\t^ super update: aSymbol! !\\n\\n\\n!StandardSystemView methodsFor: 'private'!\\nsetTransformation: aTransformation \\n\\t\\\"Override to support label size changes \\\"\\n\\tsuper setTransformation: aTransformation.\\n\\tself label: self label! !\\n\\n!StandardSystemView methodsFor: 'private' stamp: 'di 10/21/1998 16:12'!\\nsubviewWithLongestSide: sideBlock near: aPoint \\n\\t| theSub theSide theLen box |\\n\\ttheLen _ 0.\\n\\tsubViews do:\\n\\t\\t[:sub | box _ sub insetDisplayBox.\\n\\t\\tbox forPoint: aPoint closestSideDistLen:\\n\\t\\t\\t[:side :dist :len |\\n\\t\\t\\t(dist <= 5 and: [len > theLen]) ifTrue:\\n\\t\\t\\t\\t[theSub _ sub.\\n\\t\\t\\t\\ttheSide _ side.\\n\\t\\t\\t\\ttheLen _ len]]].\\n\\tsideBlock value: theSide.\\n\\t^ theSub! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardSystemView class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ncachingBits\\n\\t^ CacheBits! !\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ndoCacheBits\\n\\t\\\"StandardSystemView doCacheBits - Enable fast window repaint feature\\\"\\n\\tCacheBits _ true.\\n\\tScheduledControllers unCacheWindows.\\n\\tScheduledControllers restore! !\\n\\n!StandardSystemView class methodsFor: 'class initialization'!\\ndontCacheBits\\n\\t\\\"StandardSystemView dontCacheBits - Disable fast window repaint feature.\\n\\tReturn true iff bits were cached, ie if space was been recovered\\\"\\n\\tCacheBits ifFalse: [^ false].\\n\\tCacheBits _ false.\\n\\tScheduledControllers unCacheWindows.\\n\\t^ true! !\\n\\n!StandardSystemView class methodsFor: 'class initialization' stamp: 'sw 12/6/1999 23:42'!\\ninitialize\\t\\t\\\"StandardSystemView initialize\\\"\\n\\tself doCacheBits.\\n\\tself setLabelStyle! !\\n\\n!StandardSystemView class methodsFor: 'class initialization' stamp: 'nk 9/1/2004 10:26'!\\nsetLabelStyle\\n\\t| aFont |\\n\\t\\\"StandardSystemView setLabelStyle\\\"\\n\\taFont _ Preferences windowTitleFont.\\n\\tLabelStyle _ TextStyle fontArray: { aFont }.\\n\\tLabelStyle gridForFont: 1 withLead: 0! !\\nObject subclass: #StandardToolSet\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Base'!\\n!StandardToolSet commentStamp: '<historical>' prior: 0!\\nMain comment stating the purpose of this class and relevant relationship to other classes.\\n\\nPossible useful expressions for doIt or printIt.\\n\\nStructure:\\n instVar1\\t\\ttype -- comment about the purpose of instVar1\\n instVar2\\t\\ttype -- comment about the purpose of instVar2\\n\\nAny further useful comments about the general approach of this implementation.!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStandardToolSet class\\n\\tinstanceVariableNames: ''!\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/16/2005 15:20'!\\nbrowseChangeSetsWithClass: aClass selector: aSelector\\n\\t\\\"Browse all the change sets with the given class/selector\\\"\\n\\t^ChangeSorter browseChangeSetsWithClass: aClass selector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'md 3/10/2006 21:42'!\\nbrowseHierarchy: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\t| newBrowser |\\n\\t(aClass == nil) ifTrue: [^ self].\\n\\t(newBrowser := SystemBrowser default new) setClass: aClass selector: aSelector.\\n\\tnewBrowser spawnHierarchy.! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:12'!\\nbrowseMessageNames: aString\\n\\t^(MessageNames methodBrowserSearchingFor: aString) openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:13'!\\nbrowseMessageSet: messageList name: title autoSelect: autoSelectString\\n\\t\\\"Open a message set browser\\\"\\n\\t^MessageSet\\n\\t\\topenMessageList: messageList \\n\\t\\tname: title \\n\\t\\tautoSelect: autoSelectString! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/17/2005 11:35'!\\nbrowseVersionsOf: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\tVersionsBrowser\\n\\t\\tbrowseVersionsOf: (aClass compiledMethodAt: aSelector)\\n\\t\\tclass: aClass theNonMetaClass\\n\\t\\tmeta: aClass isMeta\\n\\t\\tcategory: (aClass organization categoryOfElement: aSelector)\\n\\t\\tselector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'md 3/10/2006 21:43'!\\nbrowse: aClass selector: aSelector\\n\\t\\\"Open a browser\\\"\\n\\t^SystemBrowser default fullOnClass: aClass selector: aSelector! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/15/2005 18:58'!\\nopenChangedMessageSet: aChangeSet\\n\\t\\\"Open a ChangedMessageSet for aChangeSet\\\"\\n\\tChangedMessageSet openFor: aChangeSet! !\\n\\n!StandardToolSet class methodsFor: 'browsing' stamp: 'ar 7/15/2005 18:58'!\\nopenClassListBrowser: anArray title: aString\\n\\t\\\"Open a class list browser\\\"\\n\\t^ClassListBrowser new initForClassesNamed: anArray title: aString\\n! !\\n\\n\\n!StandardToolSet class methodsFor: 'class initialization' stamp: 'ar 7/17/2005 01:04'!\\ninitialize\\n\\tToolSet register: self.\\n\\tPreferences installMissingWindowColors.! !\\n\\n!StandardToolSet class methodsFor: 'class initialization' stamp: 'ar 7/16/2005 16:18'!\\nunload\\n\\tToolSet unregister: self.! !\\n\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/15/2005 19:15'!\\ndebugContext: aContext label: aString contents: contents\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\t^Debugger openContext: aContext label: aString contents: contents! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/17/2005 11:16'!\\ndebugError: anError\\n\\t\\\"Handle an otherwise unhandled error\\\"\\n\\t^Processor activeProcess\\n\\t\\tdebug: anError signalerContext\\n\\t\\ttitle: anError description! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 9/27/2005 19:18'!\\ndebugSyntaxError: anError\\n\\t\\\"Handle a syntax error\\\"\\n\\t| notifier |\\n\\tnotifier := SyntaxError new\\n\\t\\tsetClass: anError errorClass\\n\\t\\tcode: anError errorCode\\n\\t\\tdebugger: (Debugger context: anError signalerContext)\\n\\t\\tdoitFlag: anError doitFlag.\\n\\tnotifier category: anError category.\\n\\tSyntaxError open: notifier.! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/15/2005 18:57'!\\ndebug: aProcess context: aContext label: aString contents: contents fullView: aBool\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\t^Debugger openOn: aProcess context: aContext label: aString contents: contents fullView: aBool! !\\n\\n!StandardToolSet class methodsFor: 'debugging' stamp: 'ar 7/17/2005 11:16'!\\ninterrupt: aProcess label: aString\\n\\t\\\"Open a debugger on the given process and context.\\\"\\n\\tDebugger\\n\\t\\topenInterrupt: aString\\n\\t\\tonProcess: aProcess! !\\n\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 18:57'!\\nbasicInspect: anObject\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^BasicInspector openOn: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:34'!\\nexplore: anObject\\n\\t\\\"Open an explorer on the given object.\\\"\\n\\t^ObjectExplorer new openExplorerFor: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:54'!\\ninspectorClassOf: anObject\\n\\t\\\"Answer the inspector class for the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t| map |\\n\\tmap := Dictionary new.\\n\\t#(\\n\\t\\t(CompiledMethod\\t\\tCompiledMethodInspector)\\n\\t\\t(CompositeEvent\\t\\tOrderedCollectionInspector)\\n\\t\\t(Dictionary\\t\\t\\tDictionaryInspector)\\n\\t\\t(ExternalStructure\\tExternalStructureInspector)\\n\\t\\t(FloatArray\\t\\t\\tOrderedCollectionInspector)\\n\\t\\t(OrderedCollection\\tOrderedCollectionInspector)\\n\\t\\t(Set\\t\\t\\t\\t\\tSetInspector)\\n\\t\\t(WeakSet\\t\\t\\tWeakSetInspector)\\n\\t) do:[:spec|\\n\\t\\tmap at: spec first put: spec last.\\n\\t].\\n\\tanObject class withAllSuperclassesDo:[:cls|\\n\\t\\tmap at: cls name ifPresent:[:inspectorName| ^Smalltalk classNamed: inspectorName].\\n\\t].\\n\\t^Inspector! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 18:58'!\\ninspect: anObject\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^(self inspectorClassOf: anObject) openOn: anObject! !\\n\\n!StandardToolSet class methodsFor: 'inspecting' stamp: 'ar 7/15/2005 19:57'!\\ninspect: anObject label: aString\\n\\t\\\"Open an inspector on the given object. The tool set must know which inspector type to use for which object - the object cannot possibly know what kind of inspectors the toolset provides.\\\"\\n\\t^(self inspectorClassOf: anObject) openOn: anObject withEvalPane: true withLabel: aString! !\\n\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:19'!\\nmenuItems\\n\\t\\\"Answer the menu items available for this tool set\\\"\\n\\t^#(\\n\\t\\t('class browser' \\t\\t\\t#openClassBrowser)\\n\\t\\t('workspace'\\t\\t\\t\\t#openWorkspace)\\n\\t\\t('file list'\\t\\t\\t\\t\\t#openFileList)\\n\\t\\t('package pane browser' \\t#openPackagePaneBrowser)\\n\\t\\t('process browser' \\t\\t\\t#openProcessBrowser)\\n\\t\\t-\\n\\t\\t('method finder'\\t\\t\\t\\t#openSelectorBrowser)\\n\\t\\t('message names'\\t\\t\\t#openMessageNames)\\n\\t\\t-\\n\\t\\t('simple change sorter'\\t\\t#openChangeSorter)\\n\\t\\t('dual change sorter'\\t\\t#openDualChangeSorter)\\n\\t)\\n! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:05'!\\nopenChangeSorter\\n\\tChangeSorter new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 3/10/2006 21:47'!\\nopenClassBrowser\\n\\tSystemBrowser default open! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:05'!\\nopenDualChangeSorter\\n\\tDualChangeSorter new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 2/24/2006 15:21'!\\nopenFileList\\n\\tFileList2 prototypicalToolWindow openInWorld.! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 12:59'!\\nopenMessageNames\\n\\t\\\"Bring a MessageNames tool to the front\\\"\\n\\tMessageNames openMessageNames! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:04'!\\nopenPackagePaneBrowser\\n\\tPackagePaneBrowser openBrowser.! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 12:59'!\\nopenProcessBrowser\\n\\tProcessBrowser open! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'ar 7/17/2005 13:00'!\\nopenSelectorBrowser\\n\\tSelectorBrowser new morphicWindow openInWorld! !\\n\\n!StandardToolSet class methodsFor: 'menu' stamp: 'md 1/18/2006 19:08'!\\nopenWorkspace\\n\\tWorkspace open! !\\nViewer subclass: #StandardViewer\\n\\tinstanceVariableNames: 'firstPanel'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting'!\\n!StandardViewer commentStamp: 'sw 8/17/2002 02:04' prior: 0!\\nA structure that allows you to view state and behavior of an object; it consists of a header and then any number of CategoryViewers.!\\n\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 12/28/1998 15:22'!\\naddCategoryViewer\\t\\n\\tself addCategoryViewerFor: self likelyCategoryToShow! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:50'!\\naddCategoryViewerFor: categoryInfo\\n\\t\\\"Add a category viewer for the given category info\\\"\\n\\n\\tself addCategoryViewerFor: categoryInfo atEnd: true! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:56'!\\naddCategoryViewerFor: categoryInfo atEnd: atEnd\\n\\t\\\"Add a category viewer for the given category info. If atEnd is true, add it at the end, else add it just after the header morph\\\"\\n\\n\\t| aViewer |\\n\\taViewer _ self categoryViewerFor: categoryInfo.\\n\\tatEnd\\n\\t\\tifTrue:\\n\\t\\t\\t[self addMorphBack: aViewer]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorph: aViewer after: submorphs first].\\n\\taViewer establishContents.\\n\\tself world ifNotNil: [self world startSteppingSubmorphsOf: aViewer].\\n\\tself fitFlap! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/23/2002 14:18'!\\naddSearchPane\\n\\t\\\"Add a search pane\\\"\\n\\n\\tself addCategoryViewerFor: #(search '') atEnd: false! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 11/18/1999 16:00'!\\ncategoriesCurrentlyShowing\\n\\t^ self categoryMorphs collect: [:m | m currentCategory]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 10/30/1998 18:38'!\\ncategoryMorphs\\n\\t^ self submorphsSatisfying: [:m | m isKindOf: CategoryViewer]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'gm 2/22/2003 13:01'!\\ncategoryViewerFor: categoryInfo \\n\\t\\\"Answer a category viewer for the given category info\\\"\\n\\n\\t| aViewer |\\n\\taViewer := ((categoryInfo isCollection) \\n\\t\\t\\t\\tand: [categoryInfo first == #search]) \\n\\t\\t\\t\\t\\tifFalse: [CategoryViewer new]\\n\\t\\t\\t\\t\\tifTrue: [SearchingViewer new].\\n\\taViewer initializeFor: scriptedPlayer categoryChoice: categoryInfo.\\n\\t^aViewer! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:22'!\\nchooseLimitClass\\n\\t\\\"Put up a menu allowing the user to choose the most generic class to show\\\"\\n\\n\\t| aMenu limitClass |\\n\\taMenu _ MenuMorph new defaultTarget: self.\\n\\tlimitClass _ self limitClass.\\n\\tscriptedPlayer class withAllSuperclasses do:\\n\\t\\t[:aClass | \\n\\t\\t\\taClass == ProtoObject\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aMenu addLine].\\n\\t\\t\\taMenu add: aClass name selector: #setLimitClass: argument: aClass.\\n\\t\\t\\taClass == limitClass ifTrue:\\n\\t\\t\\t\\t[aMenu lastItem color: Color red].\\n\\t\\t\\taClass == limitClass ifTrue: [aMenu addLine]].\\n\\taMenu addTitle: 'Show only methods\\nimplemented at or above...'. \\\"heh heh -- somebody please find nice wording here!!\\\"\\n\\taMenu popUpInWorld: self currentWorld! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'ka 11/29/2005 20:53'!\\nlikelyCategoryToShow\\n\\t\\\"Choose a category to show based on what's already showing and on some predefined heuristics\\\"\\n\\n\\t| possible all aCat currVocab |\\n\\tall := (scriptedPlayer categoriesForViewer: self) asOrderedCollection.\\n\\tpossible _ all copy.\\n\\n\\tcurrVocab := self currentVocabulary.\\n\\tself categoryMorphs do: \\n\\t\\t\\t[:m | \\n\\t\\t\\taCat := currVocab categoryWhoseTranslatedWordingIs: m currentCategory.\\n\\t\\t\\taCat ifNotNil: [possible remove: aCat wording ifAbsent: []]].\\n\\n\\t(possible includes: ScriptingSystem nameForInstanceVariablesCategory translated) ifTrue:\\n\\t\\t[^ ScriptingSystem nameForInstanceVariablesCategory].\\n\\n\\t(currVocab isEToyVocabulary) \\n\\t\\tifTrue: \\n\\t\\t\\t[(possible includes: ScriptingSystem nameForScriptsCategory translated) \\n\\t\\t\\t\\tifTrue: [^ ScriptingSystem nameForScriptsCategory]].\\n\\t{'kedama' translated. #basic translated} \\n\\t\\tdo: [:preferred | (possible includes: preferred) ifTrue: [^ preferred]].\\n\\t((scriptedPlayer isPlayerLike) \\n\\t\\tand: [scriptedPlayer hasOnlySketchCostumes]) \\n\\t\\t\\tifTrue: [(possible includes: #tests translated) ifTrue: [^#tests translated]].\\n\\t{#'color & border' translated. #tests translated. #color translated. #flagging translated. #comparing translated.} \\n\\t\\tdo: [:preferred | (possible includes: preferred) ifTrue: [^ preferred]].\\n\\t^ possible isEmpty ifFalse: [possible first] ifTrue: [all first]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:17'!\\nlimitClass\\n\\t\\\"Answer the limit class to use in this viewer\\\"\\n\\n\\t| aClass |\\n\\t(aClass _ self valueOfProperty: #limitClass) ifNotNil:\\n\\t\\t[^ aClass].\\n\\n\\taClass _ scriptedPlayer defaultLimitClassForVocabulary: self currentVocabulary.\\n\\tself setProperty: #limitClass toValue: aClass.\\n\\t^ aClass! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:31'!\\nlimitClass: aClass\\n\\t\\\"Set aClass as the limit class for this viewer, without side effects\\\"\\n\\n\\tself setProperty: #limitClass toValue: aClass\\n! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 12/11/2000 10:51'!\\nouterViewer\\n\\t\\\"Answer the StandardViewer or equivalent that contains this object\\\"\\n\\n\\t^ self! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'di 2/19/2001 10:39'!\\nrecreateCategories\\n\\t\\\"To change from old to new tiles\\\"\\n\\t| cats |\\n\\tcats _ self categoriesCurrentlyShowing.\\n\\tself removeAllMorphsIn: self categoryMorphs.\\n\\tcats do: [:cat | self addCategoryViewerFor: cat]! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'yo 4/4/2005 14:42'!\\nsearchingViewerMorphs\\n\\t^ self submorphsSatisfying: [:m | m isKindOf: SearchingViewer].! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 8/3/2001 18:31'!\\nsetLimitClass: aClass\\n\\t\\\"Set aClass as the limit class for this viewer\\\"\\n\\n\\tself limitClass: aClass.\\n\\tself relaunchViewer\\n! !\\n\\n!StandardViewer methodsFor: 'categories' stamp: 'sw 5/29/2001 22:43'!\\nsymbolsOfCategoriesCurrentlyShowing\\n\\t\\\"Answer the category symbols of my categoryMorphs\\\"\\n\\n\\t^ self categoryMorphs collect: [:m | m chosenCategorySymbol]! !\\n\\n\\n!StandardViewer methodsFor: 'classification' stamp: 'ar 6/30/2001 13:13'!\\nisStandardViewer\\n\\t^true! !\\n\\n\\n!StandardViewer methodsFor: 'debug and other' stamp: 'sw 6/20/2001 12:47'!\\nviewMorphDirectly\\n\\t\\\"Launch a new viewer to replace the receiver.\\\"\\n\\n\\tself delete.\\n\\tself presenter viewObjectDirectly: scriptedPlayer costume renderedMorph! !\\n\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 9/2/2004 11:30'!\\naddHeaderMorphWithBarHeight: anInteger includeDismissButton: aBoolean\\n\\t\\\"Add the header morph to the receiver, using anInteger as a guide for its height, and if aBoolean is true, include a dismiss buton for it\\\"\\n\\n\\t| header aFont aButton aTextMorph nail wrpr costs headWrapper |\\n\\theader _ AlignmentMorph newRow color: self color muchLighter; wrapCentering: #center; cellPositioning: #leftCenter.\\n\\taFont _ Preferences standardButtonFont.\\n\\taBoolean ifTrue:\\n\\t\\t[aButton _ self tanOButton.\\n\\t\\theader addMorph: aButton.\\n\\t\\taButton target: self;\\n\\t\\t\\t\\tactionSelector: #dismiss;\\n\\t\\t\\t\\tsetBalloonText: 'remove this entire Viewer from the screen\\ndon''t worry -- nothing will be lost!!.' translated.\\n\\t\\theader addTransparentSpacerOfSize: 4@1].\\n\\n\\taButton _ IconicButton new borderWidth: 0;\\n\\t\\t\\tlabelGraphic: (ScriptingSystem formAtKey: #AddCategoryViewer); color: Color transparent; \\n\\t\\t\\tactWhen: #buttonDown;\\n\\t\\t\\ttarget: self;\\n\\t\\t\\tactionSelector: #addCategoryViewer;\\n\\t\\t\\tsetBalloonText: 'click here to add\\nanother category pane' translated;\\n\\t\\t\\tshedSelvedge.\\n\\theader addMorphBack: aButton.\\n\\theader addTransparentSpacerOfSize: 4@1.\\n\\n\\tcosts _ scriptedPlayer costumes.\\n\\tcosts ifNotNil:\\n\\t[(costs size > 1 or: [costs size = 1 and: [costs first ~~ scriptedPlayer costume]]) ifTrue:\\n\\t\\t[header addUpDownArrowsFor: self.\\n\\t\\t(wrpr _ header submorphs last) submorphs second setBalloonText: 'switch to previous costume' translated.\\t\\n\\t\\twrpr submorphs first setBalloonText: 'switch to next costume' translated]].\\t\\n\\n\\tnail _ (self hasProperty: #noInteriorThumbnail)\\n\\t\\tifFalse:\\n\\t\\t\\t[ThumbnailMorph new objectToView: scriptedPlayer viewSelector: #costume]\\n\\t\\tifTrue:\\n\\t\\t\\t[ImageMorph new image: Cursor menu].\\n\\tnail on: #mouseDown send: #offerViewerMenuForEvt:morph: to: scriptedPlayer.\\n\\theader addMorphBack: nail.\\n\\tnail setBalloonText: 'click here to get a menu\\nthat will allow you to\\nadd a variable,\\ntear off a tile, etc..' translated.\\n\\t(self hasProperty: #noInteriorThumbnail)\\n\\t\\tifFalse:\\n\\t\\t\\t[nail borderWidth: 3; borderColor: #raised].\\n\\n\\theader addTransparentSpacerOfSize: 5@5.\\n\\n\\\"\\taButton _ SimpleButtonMorph new target: self; actionSelector: #newEmptyScript; label: 'S' translated font: (aFont _ StrikeFont familyName: #ComicBold size: 16); color: Color transparent; borderWidth: 0; actWhen: #buttonDown.\\n\\taButton setBalloonText: 'drag from here to\\ncreate a new script\\nfor this object' translated.\\t\\n\\theader addMorphBack: aButton.\\n\\n\\theader addTransparentSpacerOfSize: 8@5.\\\"\\n\\t\\n\\taButton _ SimpleButtonMorph new target: scriptedPlayer; actionSelector: #addInstanceVariable; label: 'v' translated font: (aFont emphasized: 1); color: Color transparent; borderWidth: 1; actWhen: #buttonUp.\\n\\t\\\"aButton firstSubmorph color: Color gray.\\\"\\n\\taButton setBalloonText: 'click here to add a variable\\nto this object.' translated.\\n\\theader addMorphBack: aButton.\\n\\n\\theader addTransparentSpacerOfSize: 5@5.\\n\\tself viewsMorph ifTrue: [scriptedPlayer costume assureExternalName].\\n\\taTextMorph _ UpdatingStringMorph new\\n\\t\\tuseStringFormat;\\n\\t\\ttarget: scriptedPlayer;\\n\\t\\tgetSelector: #nameForViewer;\\n\\t\\tsetNameTo: 'name';\\n\\t\\tfont: ScriptingSystem fontForNameEditingInScriptor.\\n\\tself viewsMorph ifTrue:\\n\\t\\t[aTextMorph putSelector: #setName:.\\n\\t\\taTextMorph setProperty: #okToTextEdit toValue: true].\\n\\taTextMorph step.\\n\\theader addMorphBack: aTextMorph.\\n\\taTextMorph setBalloonText: 'Click here to edit the player''s name.' translated.\\t\\n\\n\\theader beSticky.\\n\\tanInteger > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[headWrapper _ AlignmentMorph newColumn color: self color.\\n\\t\\t\\theadWrapper addTransparentSpacerOfSize: (0 @ anInteger).\\n\\t\\t\\theadWrapper addMorphBack: header.\\n\\t\\t\\tself addMorph: headWrapper]\\n\\t\\tifFalse:\\n\\t\\t\\t[self addMorph: header]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'gm 2/22/2003 13:44'!\\naffordsUniclass\\n\\t\\\"Answer true iff the receiver operates on behalf of an object that is, or could become, a member of a Uniclass\\\"\\n\\n\\t| viewee |\\n\\t^(viewee := self objectViewed) belongsToUniClass or: \\n\\t\\t\\t[((viewee isInteger) not and: [viewee isBehavior not]) \\n\\t\\t\\t\\tand: [self userLevel > 0]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'ar 6/30/2001 13:23'!\\nfitFlap\\n\\t(owner notNil and:[owner isFlap]) ifTrue:[\\n\\t\\towner width < self fullBounds width ifTrue:[\\n\\t\\t\\towner assureFlapWidth: self fullBounds width + 25.\\n\\t\\t].\\n\\t].! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 12/23/1998 23:26'!\\ninitialHeightToAllow\\n\\t^ 300! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/25/1999 23:04'!\\ninitializeFor: aPlayer barHeight: anInteger\\n\\t^ self initializeFor: aPlayer barHeight: anInteger includeDismissButton: true! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 8/4/2000 13:02'!\\ninitializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean\\n\\tself initializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean showCategories: nil! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'yo 8/18/2005 13:43'!\\ninitializeFor: aPlayer barHeight: anInteger includeDismissButton: aBoolean showCategories: categoryInfo\\n\\t\\\"Initialize the receiver to be a look inside the given Player. The categoryInfo, if present, describes which categories should be present in it, in which order\\\"\\n\\n\\tscriptedPlayer _ aPlayer.\\n\\tself listDirection: #topToBottom;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tborderWidth: 1.\\n\\tself color: self standardViewerColor.\\n\\tself addHeaderMorphWithBarHeight: anInteger includeDismissButton: aBoolean.\\n\\n\\tcategoryInfo isEmptyOrNil\\n\\t\\tifFalse: \\\"Reincarnating an pre-existing list\\\"\\n\\t\\t\\t[categoryInfo do:\\n\\t\\t\\t\\t[:aCat | self addCategoryViewerFor: aCat]]\\n\\t\\tifTrue: \\\"starting fresh\\\"\\n\\t\\t\\t[self addSearchPane. \\n\\t\\t\\tself addCategoryViewer.\\n\\t\\t\\tself addCategoryViewer.\\n\\t\\t\\t(scriptedPlayer costume isMemberOf: KedamaMorph) ifTrue: [self addCategoryViewer].\\n\\t\\t].! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/4/2001 18:06'!\\nrawVocabulary: aVocabulary\\n\\t\\\"Mark the receiver as having aVocabulary as its vocabulary\\\"\\n\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocabulary vocabularyName! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 8/29/2004 17:18'!\\nswitchToVocabulary: aVocabulary\\n\\t\\\"Make the receiver show categories and methods as dictated by aVocabulary. If this constitutes a switch, then wipe out existing category viewers, which may be showing the wrong thing.\\\"\\n\\n\\tself adoptVocabulary: aVocabulary. \\\"for benefit of submorphs\\\"\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocabulary vocabularyName.\\n\\t((scriptedPlayer isPlayerLike) and: [self isUniversalTiles not]) ifTrue:\\n\\t\\t[scriptedPlayer allScriptEditors do:\\n\\t\\t\\t[:aScriptEditor |\\n\\t\\t\\t\\taScriptEditor adoptVocabulary: aVocabulary]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 6/4/2001 19:40'!\\nuseVocabulary: aVocabulary\\n\\t\\\"Make the receiver show categories and methods as dictated by aVocabulary\\\"\\n\\n\\t| itsName |\\n\\t((self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil]) == (itsName _ aVocabulary vocabularyName)) ifFalse:\\n\\t\\t[self setProperty: #currentVocabularySymbol toValue: itsName.\\n\\t\\tself removeProperty: #currentVocabulary. \\\"grandfathered\\\"\\n\\t\\t(self submorphs select: [:m | m isKindOf: CategoryViewer]) do: [:m | m delete]]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'sw 10/26/2000 09:42'!\\nuserLevel\\n\\t\\\"Answer the user level for this viewer, which can be used in figuring out what to display in the viewer. Initially, we make little use of this, but in past prototypes, and in future deployments, it may be handy.\\\"\\n\\n\\t^ self valueOfProperty: #userLevel ifAbsent: [1]! !\\n\\n!StandardViewer methodsFor: 'initialization' stamp: 'nk 8/29/2004 17:18'!\\nviewsMorph\\n\\t\\\"Answer whether the receiver views a morph. Traditional viewers up until late 2000 *all* viewed morphs (as per the morph/player architecture), but viewers on non-morph/players have now become possible\\\"\\n\\n\\t^ scriptedPlayer isPlayerLike! !\\n\\n\\n!StandardViewer methodsFor: 'macpal' stamp: 'sw 6/4/2001 18:05'!\\ncurrentVocabulary\\n\\t\\\"Answer the vocabulary currently associated with the receiver\\\"\\n\\n\\t| aSym aVocab |\\n\\taSym _ self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil].\\n\\taSym ifNil:\\n\\t\\t[aVocab _ self valueOfProperty: #currentVocabulary ifAbsent: [nil].\\n\\t\\taVocab ifNotNil:\\n\\t\\t\\t[aSym _ aVocab vocabularyName.\\n\\t\\t\\tself removeProperty: #currentVocabulary.\\n\\t\\t\\tself setProperty: #currentVocabularySymbol toValue: aSym]].\\n\\t^ aSym\\n\\t\\tifNotNil:\\n\\t\\t\\t[Vocabulary vocabularyNamed: aSym]\\n\\t\\tifNil:\\n\\t\\t\\t[(self world ifNil: [ActiveWorld]) currentVocabularyFor: scriptedPlayer]! !\\n\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/25/1999 22:08'!\\ndismiss\\n\\t| aFlapTab |\\n\\t\\\"User hit the dismiss button.\\\"\\n\\t(owner isKindOf: TabbedPalette)\\n\\t\\tifTrue:\\n\\t\\t\\t[^ owner showNoPalette].\\n\\t(aFlapTab _ self pasteUpMorph correspondingFlapTab) ifNotNil:\\n\\t\\t[^ aFlapTab dismissViaHalo].\\n\\tself topRendererOrSelf delete! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/24/1998 14:34'!\\ndownArrowHit\\n\\tself nextCostume! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/26/1999 01:07'!\\nhasDismissButton\\n\\tsubmorphs isEmptyOrNil ifTrue: [^ false].\\n\\t^ (submorphs first allMorphs detect:\\n\\t\\t[:possible | (possible isKindOf: SimpleButtonMorph) and: [possible actionSelector == #dismiss]]\\n\\t\\t\\tifNone: [nil]) notNil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 5/18/2001 10:46'!\\nopenLexicon\\n\\t\\\"Open a lexicon browser on the receiver, showing its current vocabulary\\\"\\n\\n\\t| littleHim | \\n\\tlittleHim _ scriptedPlayer assureUniClass.\\n\\n\\t(InstanceBrowser new useVocabulary: self currentVocabulary) openOnObject: littleHim inWorld: ActiveWorld showingSelector: nil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 4/20/2001 21:22'!\\nrelaunchViewer\\n\\t\\\"Launch a new viewer to replace the receiver.\\\"\\n\\n\\tself presenter updateViewer: self forceToShow: nil! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 12/23/1998 22:45'!\\nstandardViewerColor\\n\\t ^ Color r: 0.572 g: 0.883 b: 0.572! !\\n\\n!StandardViewer methodsFor: 'user interface' stamp: 'sw 10/24/1998 14:33'!\\nupArrowHit\\n\\tself previousCostume! !\\nPolygonMorph subclass: #StarMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n!StarMorph commentStamp: 'wiz 9/6/2005 12:30' prior: 0!\\nI am a very flexible star..\\n\\nGrab me from the supplies flap or from the graphic objects.\\nAdd my handles and you can move and resize me.\\nThe up and down arrows increase or reduce the number of my sides.\\nThe right and left arrows cycle thru different amounts of pointiness.\\n\\n\\nUse the arrows right and left of my center or get stars with a specific amount of pointyness. The left side goes from fat to thin and then cycles around again. The right goes from thin to fat. Hold down the shift key if you wish to stop the cycling at the extremes.\\n\\nUse the arrows up and down to change the number of sides if you would like a different number of points.\\n\\nTo add or remove just one side hold the shift key down as you use the arrows or use the menu items for that purpose.\\n\\n\\nIf you add or remove just one point I will have an odd number of sides. When that happens I can only look like a regular polygon. The right and left arrows will have no effect. Add or remove just one more side and you can shift drag the outer handle or use the arrows to restore my pointiness. \\n\\nThat was too complicated. It is gone. You can get regular polygon shapes by adjusting my pointiness. For example the extreme of a five pointed star is a dodecahedron (10 sided regular polygon) and one step less extreme is a pentagon (5 sided regular polygon).\\n\\n\\nAt some time you will probably shift drag the outer handle thru the center handle.\\nWhile I looked round as you shrunk me, I will look very much like an asterisk as you pull me away. What happens is that inside bend shrunk on the way down because it can never be larger than the outer point (or it wouldn't be the innerbend would it).\\nBut on the way out it is perfectly happy to remain small. So I look like an asterisk.\\n\\nTo fatten me up (if you haven't already figured this out by fooling around) hold the shift down an move the outer handle towards the center (but not quite all the way) then let the shift up and move the outer handle away. A couple of cycles like this and I'll be looking fat and jolly again. Or you can now just use the right arrow to make me fatter.\\n\\nThis is also the reason I don't let the inside bend get larger than the outer point.\\nIf I did the same process that fattened me when I was an asterisk would also grow an asterisk so large squeak would complain about not having enough memory.\\n\\nHistorical note:\\n\\nThe former star had two bugs that are fixed here.\\nThe outer handle now no longer jumps from one point to another.\\nThe other bug prevented some higher order stars from looking right. \\nWhich is why the former star didn't allow you to change the number of points. !\\n\\n\\n!StarMorph methodsFor: 'access' stamp: 'wiz 1/11/2005 03:58'!\\nskipRatios\\n\\\"Return an array of ratios of the inner radius to the outer radius.\\nRatios are in ascending order from 0.0 to 1.0.\\\"\\n\\\"Assume we have at least one vertex.\\nAll ways return a number <= 1.0\\\"\\n\\n| n alpha |\\n\\\"Odd vertices sizes can not be stars only regular polygons\\\"\\nn:= vertices size . n odd ifTrue: [ ^ #( 1.0) ] .\\n\\nalpha := Float pi / (n//2) asFloat .\\n\\n^ (((( Float halfPi -alpha to: alpha /2.0 by: alpha negated ) \\n\\tcollect: [:angle |( (angle) sin )/\\n\\t\\t\\t\\t\\t(angle + alpha ) sin ]\\n\\t) copyWith: 0.0) copyWithFirst: 1.0) reversed .! !\\n\\n!StarMorph methodsFor: 'access' stamp: 'wiz 1/4/2005 20:14'!\\nstarRatio\\n\\\"Return the ratio of the inner radius to the outer radius.\\\"\\n\\\"Assume we have at least one vertex.\\nAll ways return a number <= 1.0\\\"\\n| r c |\\nc := vertices average rounded .\\nr := (c dist: vertices last) / (c dist: vertices first) .\\n^ r > 1.0 ifTrue: [ r reciprocal ] ifFalse: [r ] .! !\\n\\n\\n!StarMorph methodsFor: 'accessing' stamp: 'wiz 1/4/2005 19:47'!\\nstarRatio: r\\n\\\"Set the star s.t. the ratio of the inner radius to the outer radius is r.\\nIf r is > 1 use the reciprocal to keep the outer radius first.\\\"\\n\\\"Assume we have at least one vertex.\\nset\\nAll ways return a number <= 1.0\\\"\\nself makeVertices: vertices size starRatio:( r > 1.0 ifTrue: [ r reciprocal ] ifFalse: [r ] ).! !\\n\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 12/15/2004 00:59'!\\naddHandles\\n\\tself addStarHandles! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/15/2005 00:20'!\\naddStarHandles\\n\\t\\\"Outer handle must not be blocked so it comes first. \\n\\tThe editing routine expects to find the center handle second.\\n\\tThe side and shape changing handles follow these.\\\"\\n\\t| center |\\n\\tself removeHandles.\\n\\t\\\"Check for old stars and correct order of vertices.\\\"\\n\\tself insureCompatability .\\n\\thandles := OrderedCollection new.\\n\\tcenter := vertices average rounded.\\n\\tself withCenterOuterHandles; withUpDownLeftRightHandlesAround: 6 center: center.\\n\\tself placeHandles.\\n\\tself changed.\\n\\t! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 9/5/2005 23:12'!\\nchangeVertices: label event: evt fromHandle: handle \\n\\t| |\\n\\tlabel == #more\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self moreVertices \\\"not oneMoreVertex\\\"]\\n\\t\\t\\t\\tifFalse: [self moreVertices]].\\n\\tlabel == #less\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self lessVertices \\\"not oneLessVertex\\\"]\\n\\t\\t\\t\\tifFalse: [self lessVertices]].\\n\\tlabel == #next\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self makeVertices: vertices size starRatio: self nextSkip]\\n\\t\\t\\t\\tifFalse: [self makeVertices: vertices size starRatio: self nextTwinkleSkip]].\\n\\tlabel == #prev\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self makeVertices: vertices size starRatio: self prevSkip]\\n\\t\\t\\t\\tifFalse: [self makeVertices: vertices size starRatio: self prevTwinkleSkip]].\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/20/2005 19:07'!\\ndragVertex: label event: evt fromHandle: handle \\n\\t| center r1 rN rNext a1 rTotal |\\n\\tlabel == #outside\\n\\t\\tifTrue: [center := handles second center.\\n\\t\\t\\tr1 := center dist: vertices first.\\n\\t\\t\\t\\\"Rounding and what happens as the outer handle\\n\\t\\t\\tapproached the center, \\n\\t\\t\\trequires we guard the inner radius \\n\\t\\t\\tfrom becoming larger than the outer radius.\\\"\\n\\t\\t\\trN := r1\\n\\t\\t\\t\\t\\t\\tmin: (center dist: vertices last).\\n\\t\\t\\trNext := 1\\n\\t\\t\\t\\t\\t\\tmax: (center dist: evt cursorPoint).\\n\\t\\t\\ta1 := 270.0\\n\\t\\t\\t\\t\\t\\t+ (center bearingToPoint: evt cursorPoint).\\n\\t\\t\\trTotal := vertices size even\\n\\t\\t\\t\\t\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [r1 + rN * rNext / r1]]\\n\\t\\t\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\t\\t\\trNext := rTotal - rNext.\\n\\t\\t\\tvertices := ((a1 to: a1 + 359.999 by: 360.0 / vertices size)\\n\\t\\t\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)]) .\\n\\t\\t\\thandle align: handle center with: evt cursorPoint].\\n\\tlabel == #center\\n\\t\\tifTrue: [evt shiftPressed\\n\\t\\t\\t\\tifTrue: [self updateFormFromUser]\\n\\t\\t\\t\\tifFalse: [self position: self position + (evt cursorPoint - handle center)]].\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/15/2005 00:19'!\\nplaceHandles\\n\\t\\\"Add the handles to my submorphs.\\\"\\n\\thandles reverseDo: [:each | self addMorphFront: each ] .\\n\\t\\n\\t! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'di 9/26/97 11:11'!\\nupdateHandles! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/11/2005 19:39'!\\nwithCenterOuterHandles\\n\\t\\\"Add to our handles the center positioning and outer resizing\\n\\thandles. Outer handle must not be blocked so it comes first. \\n\\tThe editing routine expects to find the center handle second.\\n\\tThe side and shape changing handles follow these.\\\"\\n\\t| center v1 hExtent holder |\\n\\tcenter := vertices average rounded.\\n\\thExtent := 8 @ 8.\\n\\tv1 := vertices first.\\n\\tholder := {(EllipseMorph\\n\\t\\t\\t\\tnewBounds: (Rectangle center: v1 extent: hExtent)\\n\\t\\t\\t\\tcolor: Color yellow)\\n\\t\\t\\t\\tsetBalloonText: 'Move me to adjust size. Shift move to adjust pointiness'. (EllipseMorph\\n\\t\\t\\t\\tnewBounds: (Rectangle center: center extent: hExtent)\\n\\t\\t\\t\\tcolor: Color yellow)\\n\\t\\t\\t\\tsetBalloonText: 'Move me to adjust position'}.\\n\\tholder\\n\\t\\twith: {#outside. #center}\\n\\t\\tdo: [:handle :which | handle\\n\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\tsend: #dragVertex:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which;\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\tsend: #dragVertex:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which].\\n\\thandles addAll: holder! !\\n\\n!StarMorph methodsFor: 'editing' stamp: 'wiz 1/11/2005 19:47'!\\nwithUpDownLeftRightHandlesAround: radius center: center\\n\\t\\\"Add to our handles the side and shape changing handles.\\\"\\n\\t| tri above holder triAbove triBelow triRight triLeft |\\n\\tabove := 0 @ radius negated.\\n\\t\\n\\ttri := Array\\n\\t\\t\\t\\twith: 0 @ -5\\n\\t\\t\\t\\twith: 4 @ 3\\n\\t\\t\\t\\twith: -4 @ 3.\\n\\ttriAbove := tri + (center + above).\\n\\ttriBelow := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #pi centerAt: center].\\n\\ttriRight := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #right centerAt: center].\\n\\ttriLeft := triAbove\\n\\t\\t\\t\\tcollect: [:pt | pt rotateBy: #left centerAt: center].\\n\\t\\t\\t\\t\\n\\tholder := { (PolygonMorph\\n\\t\\t\\t\\tvertices: triAbove\\n\\t\\t\\t\\tcolor: Color green\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'More points.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triBelow\\n\\t\\t\\t\\tcolor: Color magenta\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Fewer points.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triRight\\n\\t\\t\\t\\tcolor: Color green\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Twinkle fatter.'. \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t(PolygonMorph\\n\\t\\t\\t\\tvertices: triLeft\\n\\t\\t\\t\\tcolor: Color magenta\\n\\t\\t\\t\\tborderWidth: 1\\n\\t\\t\\t\\tborderColor: Color black)\\n\\t\\t\\t\\t setBalloonText: 'Twinkle thinner.'}.\\n\\t\\n\\tholder\\n\\t\\twith: {#more. #less. #next. #prev}\\n\\t\\tdo: [:handle :which | handle\\n\\t\\t\\t\\ton: #mouseDown\\n\\t\\t\\t\\tsend: #changeVertices:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which;\\n\\t\\t\\t\\t\\n\\t\\t\\t\\ton: #mouseMove\\n\\t\\t\\t\\tsend: #changeVertices:event:fromHandle:\\n\\t\\t\\t\\tto: self\\n\\t\\t\\t\\twithValue: which].\\n\\t^ handles addAll: holder! !\\n\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:34'!\\nnextSkip\\n\\t\\\"Set starRatio to next skip wrapping if needed.\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := (c dist: vertices first) truncated asFloat.\\n\\trN := c dist: vertices last.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindFirst: [:r | r > (rN + 1.0)].\\n\\t\\\"n = 0\\n\\t\\tifTrue: [n := skips size].\\\"\\n\\t^ skips atWrap: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:42'!\\nnextTwinkleSkip\\n\\t\\\"Set starRatio to next skip wrapping if needed.\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := (c dist: vertices first) truncated asFloat.\\n\\trN := c dist: vertices last.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindFirst: [:r | r > (rN + 1.0)].\\n\\tn = 0\\n\\t\\tifTrue: [ n := 1].\\n\\t^ skips atWrap: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:41'!\\nprevSkip\\n\\t\\\"Set starRatio to next skip wrapping if necessary\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := c dist: vertices first.\\n\\trN := (c dist: vertices last) truncated asFloat.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindLast: [:r | r + 1.0 < rN].\\n\\tn = 0\\n\\t\\tifTrue: [n := 1].\\n\\t^ skips at: n! !\\n\\n!StarMorph methodsFor: 'geometry' stamp: 'wiz 1/19/2005 22:19'!\\nprevTwinkleSkip\\n\\t\\\"Set starRatio to next skip wrapping if necessary\\\"\\n\\t| skips n c r1 rN |\\n\\tc := vertices average rounded.\\n\\tr1 := c dist: vertices first.\\n\\trN := (c dist: vertices last) truncated asFloat.\\n\\tskips := self skipRatios.\\n\\tn := skips * r1\\n\\t\\t\\t\\tfindLast: [:r | r + 1.0 < rN].\\n\\t\\\"n = 0\\n\\tifTrue: [^ oldR].\\\"\\n\\t^ skips atWrap: n! !\\n\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:35'!\\ndefaultBorderColor\\n\\t\\\"answer the default border color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:40'!\\ndefaultBorderWidth\\n\\t\\\"answer the default border width for the receiver\\\"\\n\\t^ 1! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:33'!\\ndefaultCenter\\n\\t\\\"answer the default center for the receiver\\\"\\n\\t^ 0 asPoint! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color lightBlue! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:33'!\\ndefaultFirstVertex\\n\\t\\\"answer the default first outer point for the receiver.\\n\\tThis with the center determines the angle and size of the outer radius.\\\"\\n\\t^ 10 asPoint! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:28'!\\ndefaultSides\\n\\t\\\"answer the default number of sides for the receiver\\\"\\n\\t^ 10! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:29'!\\ndefaultStarRatio\\n\\t\\\"answer the default ratio of outer radius to inner radius for the receiver\\\"\\n\\t^ 5.0 / 12.0! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 14:36'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\tself\\n\\t\\tmakeVertices: self defaultSides\\n\\t\\tstarRatio: self defaultStarRatio\\n\\t\\twithCenter: self defaultCenter\\n\\t\\twithPoint: self defaultFirstVertex.\\n\\tself computeBounds! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/9/2005 20:15'!\\ninsureCompatability\\n\\\"The old stars had the point on the second not the first vertex. So we need to check for this special case.\\\"\\n | c v1 v2 |\\nc := vertices average rounded.\\n v1 := vertices first .\\n v2 := vertices second .\\n(c dist: v1) + 0.001 < (c dist: v2) ifTrue: [vertices := vertices allButFirst copyWith: v1]\\n\\n! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 12/30/2004 02:57'!\\nmakeVertices: nSides \\n\\t\\\"Assuming vertices has at least one point, make a new star \\n\\tor regular polygon (for odd sided polygons).\\n\\tThe center of the polygon and the first vertex remain in\\n\\tplace. The inner distances for stars remain the same also if\\n\\tpossible.\\\"\\n\\t| center r1 rN rNext a1 rTotal |\\n\\tcenter := vertices average rounded.\\n\\tr1 := center dist: vertices first.\\n\\trN := center dist: vertices last.\\n\\trNext := 1 max: r1.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: vertices first).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed .\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/4/2005 19:31'!\\nmakeVertices: nSides starRatio: fraction\\n\\t\\\"Assuming vertices has at least one point, make a new star \\n\\tor regular polygon (for odd sided polygons).\\n\\tThe center of the polygon and the first vertex remain in\\n\\tplace. The inner distances for stars remain the same also if\\n\\tpossible.\\\"\\n\\t| center r1 rN rNext a1 rTotal |\\n\\tcenter := vertices average rounded.\\n\\tr1 := center dist: vertices first.\\n\\trNext := 1 max: r1.\\n\\trN := (1.0 min: fraction) * rNext.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: vertices first).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed .\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n!StarMorph methodsFor: 'initialization' stamp: 'wiz 1/11/2005 21:36'!\\nmakeVertices: nSides starRatio: fraction withCenter: center withPoint: aPoint \\n\\t\\\"Make a new star or regular polygon (for odd sided polygons).\\n\\tThis makes star vertices from scratch without any feedback from existing vertices.\\\"\\n\\t| r1 rN rNext a1 rTotal |\\n\\tr1 := center dist: aPoint.\\n\\trNext := 1 max: r1.\\n\\trN := (1.0 min: fraction)\\n\\t\\t\\t\\t* rNext.\\n\\ta1 := 270.0\\n\\t\\t\\t\\t+ (center bearingToPoint: aPoint).\\n\\trTotal := nSides even\\n\\t\\t\\t\\tifTrue: [rNext + rNext min: rNext + rN]\\n\\t\\t\\t\\tifFalse: [rNext + rNext].\\n\\trNext := rTotal - rNext.\\n\\tself changed.\\n\\tvertices := (a1 to: a1 + 359.999 by: 360.0 / nSides)\\n\\t\\t\\t\\tcollect: [:angle | center\\n\\t\\t\\t\\t\\t\\t+ (Point r: (rNext := rTotal - rNext) degrees: angle)].\\n\\tself computeBounds.\\n\\tself changed! !\\n\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 9/5/2005 23:08'!\\naddChangeSidesMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Menu items to change number of sides.\\\"\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'more sides' translated action: #moreVertices.\\n\\taCustomMenu add: 'fewer sides' translated action: #lessVertices.\\n\\\"\\tRegular polygons can be simulated with the one of the skip stars \\n\\tand it would confuse users to have stars be limited to Regular polygons.\\n\\tSo we've removed those menu items - wiz\\\"\\n\\\"\\taCustomMenu add: 'one more side' translated action: #oneMoreVertex.\\n\\taCustomMenu add: 'one fewer side' translated action: #oneLessVertex\\\"! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 1/11/2005 14:55'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph \\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\nself addChangeSidesMenuItems: aCustomMenu hand: aHandMorph.\\nself addTwinkleMenuItems: aCustomMenu hand: aHandMorph.\\n\\t! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 1/11/2005 20:38'!\\naddTwinkleMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Menu items to change the sharpness of the star.\\\"\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'twinkle fatter' translated action: #nextTwinkle.\\n\\taCustomMenu add: 'twinkle thinner' translated action: #prevTwinkle.\\n\\\"\\taCustomMenu add: 'fatter star' translated action: #nextFatter.\\n\\taCustomMenu add: 'thinner star' translated action: #prevThinner\\\"\\n\\t\\n\\t\\n\\n\\n! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 12/11/2004 16:45'!\\noneLessVertex\\n\\tself\\n\\t\\tmakeVertices: (3 max: 1 negated + vertices size)! !\\n\\n!StarMorph methodsFor: 'menu' stamp: 'wiz 12/11/2004 16:46'!\\noneMoreVertex\\n\\tself makeVertices: 1 + vertices size! !\\n\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 12/12/2004 16:43'!\\nlessVertices\\n\\\"Reduce the number of points by one until we are a diamond. If odd reduce the number of sides by two until we become a triangle. See class comment.\\\"\\n\\t| nVerts |\\n\\t( nVerts := 2 negated + vertices size) < 3 ifFalse: [\\n\\tself\\n\\t\\tmakeVertices: nVerts]! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 12/11/2004 16:45'!\\nmoreVertices\\n\\tself makeVertices: 2+ vertices size! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/11/2005 20:37'!\\nnextTwinkle\\n\\tself makeVertices: vertices size starRatio: self nextTwinkleSkip .\\n\\tself computeBounds.! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/11/2005 20:37'!\\nprevTwinkle\\n\\tself makeVertices: vertices size starRatio: self prevTwinkleSkip .\\n\\tself computeBounds.! !\\n\\n!StarMorph methodsFor: 'menus' stamp: 'wiz 1/15/2005 02:26'!\\nupdateFormFromUser\\n\\\"Does nothing here. Overridden in subclasses e.g. Kaleidoscope.\\\"\\n^ self.! !\\n\\n\\n!StarMorph methodsFor: 'parts bin' stamp: 'sw 7/2/2001 11:07'!\\ninitializeToStandAlone\\n\\t^ self initialize removeHandles! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:37'!\\ninitialize\\n\\n\\tself registerInFlapsRegistry.\\t! !\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:39'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StarMorph\\t\\tauthoringPrototype\\t'Star'\\t'A star')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.\\n\\t\\t\\t\\t\\t\\tcl registerQuad: #(StarMorph\\tauthoringPrototype\\t'Star'\\t'A star')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.]! !\\n\\n!StarMorph class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:41'!\\nunload\\n\\t\\\"Unload the receiver from global registries\\\"\\n\\n\\tself environment at: #Flaps ifPresent: [:cl |\\n\\tcl unregisterQuadsWithReceiver: self] ! !\\n\\n\\n!StarMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 16:22'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Star'\\n\\t\\tcategories:\\t\\t#('Graphics')\\n\\t\\tdocumentation:\\t'A symmetrical polygon in the shape of a star'! !\\nStarSqueakMorph subclass: #StarSqueakAntColony\\n\\tinstanceVariableNames: 'antCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakAntColony methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tantCount := 50.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'menu' stamp: 'jm 2/7/2001 18:41'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(antCount 10 500 'The number of ants searching for food.'))\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 1/19/2001 10:30'!\\ndiffusePheromone\\n\\n\\tself diffusePatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 1/19/2001 18:02'!\\nevaporatePheromone\\n\\n\\tself decayPatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 2/7/2001 08:03'!\\nsetupFood: aPatch\\n\\t\\\"Create several food caches.\\\"\\n\\n\\taPatch set: 'food' to: 0. \\\"patch default is no food\\\"\\n\\n\\t((aPatch distanceTo: 15@15) <= 1 or:\\n\\t [(aPatch distanceTo: 80@20) <= 1 or:\\n\\t [(aPatch distanceTo: 25@80) <= 1 or:\\n\\t [(aPatch distanceTo: 70@70) <= 1]]]) ifTrue: [\\n\\t\\taPatch set: 'food' to: 10.\\n\\t\\taPatch color: Color red].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'sd 11/20/2005 21:26'!\\nsetupNest: aPatch\\n\\t\\\"Create a nest of radius 5 centered at 50@50.\\\"\\n\\n\\t| distanceToNest |\\n\\tdistanceToNest := aPatch distanceTo: 50@50.\\n\\tdistanceToNest <= 4\\n\\t\\tifTrue: [\\n\\t\\t\\taPatch set: 'isNest' to: 1.\\n\\t\\t\\taPatch color: Color brown lighter]\\n\\t\\tifFalse: [aPatch set: 'isNest' to: 0].\\n\\n\\t\\\"create a 'hill' of nest scent centered on the nest\\\"\\n\\tdistanceToNest > 0 ifTrue: [\\n\\t\\taPatch set: 'nestScent' to: 10000.0 // distanceToNest].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 3/8/2001 14:23'!\\nsetupPatches\\n\\t\\\"Create patch variables for sensing the nest and food caches. The nestScent variable is diffused so that it forms a 'hill' of scent over the entire world with its peak at the center of the nest. That way, the ants always know which way the nest is.\\\"\\n\\n\\tself createPatchVariable: 'food'.\\t\\t\\t\\\"greater than zero if patch has food\\\"\\n\\tself createPatchVariable: 'isNest'.\\t\\t\\\"greater than zero if patch is nest\\\"\\n\\tself createPatchVariable: 'nestScent'.\\t\\\"circular gradient with peak centered on nest\\\"\\n\\tself createPatchVariable: 'pheromone'.\\t\\\"dropped by ants when carrying food\\\"\\n\\tself displayPatchVariable: 'pheromone'.\\n\\tself patchesDo: [:p |\\n\\t\\tp color: self backgroundColor.\\n\\t\\tself setupNest: p.\\n\\t\\tself setupFood: p].\\n\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'other' stamp: 'jm 3/8/2001 14:24'!\\nsetupTurtles\\n\\n\\tself makeTurtles: antCount class: AntColonyTurtle.\\n\\tturtles do: [:t |\\n\\t\\tt goto: 50@50.\\n\\t\\tt color: Color black.\\n\\t\\tt isCarryingFood: false.\\n\\t\\tt pheromoneDropSize: 100].\\n! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'jm 2/7/2001 14:45'!\\nantCount\\n\\n\\t^ antCount\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\nantCount: aNumber\\n\\n\\tantCount := aNumber.\\n! !\\n\\n!StarSqueakAntColony methodsFor: 'parameters' stamp: 'jm 3/11/2001 17:10'!\\nbackgroundColor\\n\\n\\t^ Color brown lighter lighter lighter! !\\n\\n\\n!StarSqueakAntColony methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself setupPatches.\\n\\tself setupTurtles.\\n\\tturtleDemons := #(searchForFood pickUpFood returnToNest dropFoodInNest).\\n\\tworldDemons := #(evaporatePheromone diffusePheromone).\\n! !\\nStarSqueakMorph subclass: #StarSqueakDiffusion\\n\\tinstanceVariableNames: 'waterCount dyeCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakDiffusion methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tdyeCount := 200.\\n\\twaterCount := 2000.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'menu' stamp: 'jm 3/8/2001 14:08'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(dyeCount 50 1000 'The number of dye particles.')\\n\\t\\t(waterCount 100 4000 'The number of water particles.'))\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'other' stamp: 'sd 11/20/2005 21:26'!\\nsetupTurtles\\n\\n\\t| radius t |\\n\\tdyeCount ifNil: [dyeCount := 200].\\n\\twaterCount ifNil: [waterCount := 2000].\\n\\tradius := 10.\\n\\tself makeTurtles: waterCount class: DiffusionTurtle.\\n\\tturtles do: [:each |\\n\\t\\teach color: (Color gray: 0.7).\\n\\t\\t(each distanceTo: 50@50) < radius ifTrue: [each die]].\\n\\n\\tself makeTurtles: dyeCount class: DiffusionTurtle.\\n\\tturtles size - (dyeCount - 1) to: turtles size do: [:i |\\n\\t\\tt := turtles at: i.\\n\\t\\tt goto: 50@50.\\n\\t\\tt forward: (self random: radius).\\n\\t\\tt color: Color green darker darker].\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'jm 3/8/2001 14:07'!\\ndyeCount\\n\\n\\t^ dyeCount\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ndyeCount: aNumber\\n\\n\\tdyeCount := aNumber asInteger max: 1.\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'jm 3/8/2001 14:07'!\\nwaterCount\\n\\n\\t^ waterCount\\n! !\\n\\n!StarSqueakDiffusion methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\nwaterCount: aNumber\\n\\n\\twaterCount := aNumber asInteger max: 1.\\n! !\\n\\n\\n!StarSqueakDiffusion methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself patchesDo: [:p | p color: (Color gray: 0.9)].\\n\\tself setupTurtles.\\n\\tturtleDemons := #(move bounce).\\n! !\\nStarSqueakMorph subclass: #StarSqueakForestFire\\n\\tinstanceVariableNames: 'treePercentage'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakForestFire methodsFor: 'demons' stamp: 'sd 11/20/2005 21:26'!\\nconsumeFuel\\n\\n\\t| level |\\n\\tself patchesDo: [:p |\\n\\t\\tlevel := p get: #flameLevel.\\n\\t\\tlevel > 0 ifTrue: [\\n\\t\\t\\tlevel := (level - 15) max: 0.\\n\\t\\t\\tp set: #flameLevel to: level.\\n\\t\\t\\tp brightness: level]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'demons' stamp: 'jm 1/28/2001 16:33'!\\nspreadFire\\n\\n\\tself patchesDo: [:p |\\n\\t\\t(p get: #isUnburnt) > 0 ifTrue: [\\n\\t\\t\\t((p neighborN get: #flameLevel) +\\n\\t\\t\\t (p neighborS get: #flameLevel) +\\n\\t\\t\\t (p neighborE get: #flameLevel) +\\n\\t\\t\\t (p neighborW get: #flameLevel)) > 0 ifTrue: [\\n\\t\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\t\\tp set: #flameLevel to: 100.\\n\\t\\t\\t\\tp color: Color red]]].\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\ttreePercentage := 70.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'menu' stamp: 'jm 3/10/2001 11:06'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(treePercentage 0 100 'The probability of that a given patch has a tree.'))\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'parameters' stamp: 'jm 3/10/2001 11:06'!\\ntreePercentage\\n\\n\\t^ treePercentage\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ntreePercentage: aNumber\\n\\n\\ttreePercentage := aNumber.\\n! !\\n\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself createPatchVariable: #isUnburnt.\\n\\tself createPatchVariable: #flameLevel.\\n\\tself setupTrees.\\n\\tself setupFire.\\n\\tself setupBorder.\\n\\tworldDemons := #(spreadFire consumeFuel).\\n\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 1/28/2001 16:32'!\\nsetupBorder\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp isLeftEdge | p isRightEdge |\\n\\t\\tp isTopEdge | p isBottomEdge ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\tp color: Color blue]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 1/28/2001 16:32'!\\nsetupFire\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp neighborW isLeftEdge ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 0.\\n\\t\\t\\tp set: #flameLevel to: 100.\\n\\t\\t\\tp color: Color red]].\\n! !\\n\\n!StarSqueakForestFire methodsFor: 'setup' stamp: 'jm 3/10/2001 11:09'!\\nsetupTrees\\n\\t\\\"Setup a forest with treePercentage of trees.\\\"\\n\\n\\tself patchesDo: [:p |\\n\\t\\tp set: #isUnburnt to: 0.\\n\\t\\tp set: #flameLevel to: 0.\\n\\t\\t(10 * treePercentage) > (self random: 1000) ifTrue: [\\n\\t\\t\\tp set: #isUnburnt to: 1.\\n\\t\\t\\tp color: Color green]].\\n! !\\nMorph subclass: #StarSqueakMorph\\n\\tinstanceVariableNames: 'dimensions pixelsPerPatch patchVariables patchVariableToDisplay logPatchVariableScale patchVarDisplayForm patchForm patchColorSetter patchColorGetter turtles turtleDemons worldDemons sniffRange scaledEvaporationRate diffusionRate lastTurtleID generation running stepTime turtlesAtPatchCache turtlesAtPatchCacheValid'\\n\\tclassVariableNames: 'RandomSeed'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakMorph commentStamp: '<historical>' prior: 0!\\nI implement a StarSqueak simulation. StarSqueak is a Squeak version of Mitchel Resnick's Star Logo, a simulation environment designed to explore massively parallel simulations with hundreds or thousands of turtles. See the excellent book \\\"Turtles, Termites, and Traffic Jams: Explorations in Massively Parallel Microworlds\\\" by Mitchel Resnick, MIT Press, 1994.\\n!\\n\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 2/7/2001 13:48'!\\ndiffusionRate\\n\\n\\t^ diffusionRate\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ndiffusionRate: newRate\\n\\t\\\"Set the diffusion rate to an integer between 0 and 10. The diffusion rate gives the number of patches on one size of the area averaged to compute the next value of the variable for a given patch. Larger numbers cause faster diffusion. Zero means no diffusion.\\\"\\n\\n\\tdiffusionRate := (newRate rounded max: 0) min: 10.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 2/7/2001 18:59'!\\nevaporationRate\\n\\n\\t^ 1024 - scaledEvaporationRate! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nevaporationRate: newRate\\n\\t\\\"Set the evaporation rate. The useful range is 0 to 25 or so. Larger numbers cause faster evaporation. Zero means no evaporization.\\\"\\n\\n\\tscaledEvaporationRate := ((1024 - newRate truncated) max: 1) min: 1024.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'jm 3/3/2001 12:50'!\\npixelsPerPatch\\n\\n\\t^ pixelsPerPatch\\n! !\\n\\n!StarSqueakMorph methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\npixelsPerPatch: anInteger\\n\\t\\\"Set the width of one patch in pixels. Larger numbers scale up this StarSqueak world, but numbers larger than 2 or 3 result in a blocky look. The useful range is 1 to 10.\\\"\\n\\n\\tpixelsPerPatch := (anInteger rounded max: 1) min: 10.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'jm 3/3/2001 12:55'!\\nareasRemainingToFill: aRectangle\\n\\t\\\"Drawing optimization. Since I completely fill my bounds with opaque pixels, this method tells Morphic that it isn't necessary to draw any morphs covered by me.\\\"\\n\\t\\n\\t^ aRectangle areasOutside: self bounds\\n! !\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\ndisplay\\n\\t\\\"Display this world on the Display. Used for debugging.\\\"\\n\\n\\t| c |\\n\\tc := FormCanvas extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tc := c copyOffset: bounds origin negated.\\n\\tself drawOn: c.\\n\\tc form display.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'drawing' stamp: 'sd 11/20/2005 21:26'!\\ndrawOn: aCanvas\\n\\t\\\"Display this StarSqueak world.\\\"\\n\\n\\t| tmpForm bitBlt t |\\n\\t\\\"copy the patches form\\\"\\n\\ttmpForm := patchForm deepCopy.\\n\\n\\t\\\"draw patchVariableToDisplay on top of tmpForm as translucent color\\\"\\n\\tself displayPatchVariableOn: tmpForm color: Color yellow shift: logPatchVariableScale.\\n\\n\\t\\\"draw turtles on top of tmpForm\\\"\\n\\tbitBlt := (BitBlt toForm: tmpForm)\\n\\t\\tclipRect: tmpForm boundingBox;\\n\\t\\tcombinationRule: Form over.\\n\\t1 to: turtles size do: [:i |\\n\\t\\tt := turtles at: i.\\n\\t\\tbitBlt\\n\\t\\t\\tdestX: (pixelsPerPatch * t x truncated)\\n\\t\\t\\tdestY: (pixelsPerPatch * t y truncated)\\n\\t\\t\\twidth: pixelsPerPatch\\n\\t\\t\\theight: pixelsPerPatch.\\n\\t\\tbitBlt\\n\\t\\t\\tfillColor: t color;\\n\\t\\t\\tcopyBits].\\n\\n\\t\\\"display tmpForm\\\"\\n\\taCanvas paintImage: tmpForm at: bounds origin.\\n\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'geometry' stamp: 'jm 2/7/2001 13:31'!\\nextent: aPoint\\n\\t\\\"Do nothing; my extent is determined by my StarSqueak world dimensions and pixelsPerPatch.\\\"\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tdimensions := self starSqueakDimensions. \\\"dimensions of this StarSqueak world in patches\\\"\\n\\tpixelsPerPatch := 2.\\n\\tsuper extent: dimensions * pixelsPerPatch.\\n\\tself evaporationRate: 6.\\n\\tself diffusionRate: 1.\\n\\tself clearAll. \\\"be sure this is done once in case setup fails to do it\\\"\\n\\tself setup.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'start' translated action: #startRunning.\\n\\taCustomMenu add: 'stop' translated action: #stopRunning.\\n\\taCustomMenu add: 'step' translated action: #singleStep.\\n\\taCustomMenu add: 'start over' translated action: #startOver.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'full speed' translated action: #fullSpeed.\\n\\taCustomMenu add: 'slow speed' translated action: #slowSpeed.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'set scale' translated action: #setScale.\\n\\taCustomMenu add: 'make parameter slider' translated action: #makeParameterSlider.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nfullSpeed\\n\\t\\\"Run at maximum speed.\\\"\\n\\n\\tstepTime := 0.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'dgd 2/21/2003 22:53'!\\nmakeParameterSlider\\n\\t| menu choice s |\\n\\tmenu := CustomMenu new title: 'Parameter?'.\\n\\tself sliderParameters do: [:rec | menu add: rec first action: rec].\\n\\tchoice := menu startUp.\\n\\tchoice ifNil: [^self].\\n\\ts := self \\n\\t\\t\\t\\tnewSliderForParameter: choice first\\n\\t\\t\\t\\ttarget: self\\n\\t\\t\\t\\tmin: (choice second)\\n\\t\\t\\t\\tmax: (choice third)\\n\\t\\t\\t\\tdescription: (choice fourth).\\n\\tself world activeHand attachMorph: s! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nsetScale\\n\\n\\t| reply |\\n\\treply := FillInTheBlank\\n\\t\\trequest: 'Set the number of pixels per patch (a number between 1 and 10)?'\\n\\t\\t initialAnswer: pixelsPerPatch printString.\\n\\treply isEmpty ifTrue: [^ self].\\n\\tpixelsPerPatch := ((reply asNumber rounded) max: 1) min: 10.\\n\\tself changed.\\n\\tsuper extent: dimensions * pixelsPerPatch.\\n\\tself clearAll. \\\"be sure this is done once in case setup fails to do it\\\"\\n\\tself setup.\\n\\tself startOver.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/5/2001 17:52'!\\nsingleStep\\n\\t\\\"Take one step and redisplay.\\\"\\n\\n\\tself oneStep.\\n\\tself changed.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/7/2001 19:07'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ #((evaporationRate 0 40\\n\\t\\t\\t'The rate at which chemicals evaporate in this world. Larger numbers give faster evaporation.')\\n\\t\\t(diffusionRate 0 5\\n\\t\\t\\t'The rate of chemical diffusion. Larger numbers give quicker diffusion.'))\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nslowSpeed\\n\\t\\\"Run at slow speed.\\\"\\n\\n\\tstepTime := 250.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'jm 2/6/2001 22:04'!\\nstartOver\\n\\t\\\"Restart this StarSqueak simulation from its initial conditions.\\\"\\n\\n\\tself clearAll.\\n\\tself setup.\\n\\tself changed.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nstartRunning\\n\\t\\\"Start running this StarSqueak simulation.\\\"\\n\\n\\trunning := true.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nstopRunning\\n\\t\\\"STop running this StarSqueak simulation.\\\"\\n\\n\\trunning := false.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'parts bin' stamp: 'sw 7/13/2001 22:22'!\\ninitializeToStandAlone\\n\\tself initialize.\\n\\tself startRunning! !\\n\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'jm 3/8/2001 13:47'!\\nclearPatches\\n\\t\\\"Clear patch colors, including turtle trails.\\\"\\n\\n\\tpatchForm fill: patchForm boundingBox fillColor: Color black.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'jm 1/22/2001 16:52'!\\ncreatePatchVariable: patchVarName\\n\\t\\\"Create a patch variable of the given name. It is initialized to a value of zero for every patch.\\\"\\n\\n\\tpatchVariables\\n\\t\\tat: patchVarName\\n\\t\\tput: (Bitmap new: (dimensions x * dimensions y) withAll: 0).\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\ndecayPatchVariable: patchVarName\\n\\t\\\"Decay the values of the patch variable of the given name. That is, the value of each patch is replaced by a fraction of its former value, resulting in an expontial decay each patch's value over time. This can be used to model evaporation of a pheromone.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tself primEvaporate: patchVar rate: scaledEvaporationRate.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\ndiffusePatchVariable: patchVarName\\n\\t\\\"Diffuse the patch variable of the given name.\\\"\\n\\n\\t| v newV |\\n\\tdiffusionRate = 0 ifTrue: [^ self]. \\\"no diffusion\\\"\\n\\tv := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tnewV := Bitmap new: v size.\\n\\tself primDiffuseFrom: v\\n\\t\\tto: newV\\n\\t\\twidth: dimensions x\\n\\t\\theight: dimensions y\\n\\t\\tdelta: diffusionRate truncated.\\n\\tpatchVariables at: patchVarName put: newV.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'patches' stamp: 'sd 11/20/2005 21:26'!\\npatchesDo: aBlock\\n\\t\\\"Evaluate the given block for every patch in this world.\\\"\\n\\n\\t| patch |\\n\\tpatch := StarSqueakPatch new world: self.\\n\\t0 to: dimensions y - 1 do: [:y |\\n\\t\\tpatch y: y.\\n\\t\\t0 to: dimensions x - 1 do: [:x |\\n\\t\\t\\tpatch x: x.\\n\\t\\t\\taBlock value: patch]].\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\naddTurtleDemon: aSelector\\n\\t\\\"Add the given selector to the list of selectors sent to every turtle on every step.\\\"\\n\\n\\tturtleDemons := turtleDemons copyWith: aSelector.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\naddWorldDemon: aSelector\\n\\t\\\"Add the given selector to the list of selectors sent to the world on every step.\\\"\\n\\n\\tworldDemons := worldDemons copyWith: aSelector.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nclearAll\\n\\t\\\"Reset this StarSqueak world. All patch variables are cleared, all turtles are removed, and all demons are turned off.\\\"\\n\\n\\tpatchVariables := Dictionary new: 10.\\n\\tpatchVariableToDisplay := nil.\\n\\tlogPatchVariableScale := 0.\\n\\tpatchForm := Form extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tself createPatchFormGetterAndSetter.\\n\\tpatchVarDisplayForm := nil.\\n\\tself clearPatches.\\n\\tturtles := #().\\n\\tturtleDemons := #().\\n\\tworldDemons := #().\\n\\tsniffRange := 1.\\n\\tlastTurtleID := -1.\\n\\tgeneration := 0.\\n\\trunning := false.\\n\\tstepTime := 0. \\\"full speed\\\"\\n\\tturtlesAtPatchCache := nil.\\n\\tturtlesAtPatchCacheValid := false.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 1/24/2001 12:42'!\\ndisplayPatchVariable: patchVarName\\n\\t\\\"Make this StarSqueak world display the patch variable of the given name. Only one patch variable can be displayed at any given time.\\\"\\n\\n\\tself displayPatchVariable: patchVarName logScale: -2.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\ndisplayPatchVariable: patchVarName logScale: logBase2OfScaleFactor\\n\\t\\\"Make this StarSqueak world display the patch variable of the given name. Only one patch variable can be displayed at any given time. Values are scaled by 2^logBase2OfScaleFactor. For example, a value of 5 scales by 32 and a value of -2 scales by 1/4.\\\"\\n\\n\\t(patchVariables includesKey: patchVarName) ifFalse: [\\n\\t\\tpatchVariableToDisplay := nil.\\n\\t\\tpatchVarDisplayForm := nil.\\n\\t\\t^ self].\\n\\tpatchVariableToDisplay := patchVarName.\\n\\tpatchVarDisplayForm := Form extent: (dimensions * pixelsPerPatch) depth: 32.\\n\\tlogPatchVariableScale := logBase2OfScaleFactor.\\n\\tself clearPatches.\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nrandom: range\\n\\t\\\"Answer a random integer between 0 and range.\\\"\\n\\n\\tRandomSeed := ((RandomSeed * 1309) + 13849) bitAnd: 65535.\\n\\t^ (RandomSeed * (range + 1)) // 65536\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 1/23/2001 07:24'!\\nsetup\\n\\t\\\"Subclasses should override this to setup the initial conditions of this StarSqueak world. The method should start with 'self clearAll'.\\\"\\n\\n\\tself clearAll.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'setup' stamp: 'jm 3/3/2001 12:54'!\\nstarSqueakDimensions\\n\\t\\\"Answer the dimensions of this StarSqueak simulation. Subclasses can override this method to define their own world size.\\\"\\n\\n\\t^ 100@100\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'stepping and presenter' stamp: 'dgd 2/21/2003 22:53'!\\noneStep\\n\\t\\\"Perform one step of the StarSqueak world. Execute all turtle and world demons.\\\"\\n\\n\\t\\\"run demons in random order and increment the generation counter\\\"\\n\\n\\t| currentTurtles |\\n\\tturtleDemons notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"Note: Make a copy of turtles list that won't change if turtles are created/deleted.\\\"\\n\\n\\t\\t\\tcurrentTurtles := turtles copy.\\n\\t\\t\\tturtleDemons shuffled \\n\\t\\t\\t\\tdo: [:sel | 1 to: currentTurtles size do: [:i | (currentTurtles at: i) perform: sel]]].\\n\\tworldDemons shuffled do: [:sel | self perform: sel].\\n\\tgeneration := generation + 1.\\n\\tturtlesAtPatchCacheValid := false! !\\n\\n!StarSqueakMorph methodsFor: 'stepping and presenter' stamp: 'jm 1/26/2001 17:21'!\\nstep\\n\\n\\trunning ifTrue: [\\n\\t\\tself oneStep.\\n\\t\\tself changed].\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'testing' stamp: 'jm 1/22/2001 17:52'!\\nstepTime\\n\\n\\t^ stepTime\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 3/12/2001 09:44'!\\nmakeTurtles: count\\n\\t\\\"Create the given number of generic turtles.\\\"\\n\\n\\tself makeTurtles: count class: StarSqueakTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'sd 11/20/2005 21:26'!\\nmakeTurtles: count class: turtleClass\\n\\t\\\"Create the given number of turtles of the given turtle class.\\\"\\n\\n\\tturtles := turtles,\\n\\t\\t((1 to: count) collect: [:i |\\n\\t\\t\\tturtleClass new\\n\\t\\t\\t\\tinitializeWorld: self\\n\\t\\t\\t\\twho: (lastTurtleID := lastTurtleID + 1)]).\\n\\tself changed.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 1/28/2001 10:55'!\\nturtles\\n\\n\\t^ turtles\\n! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'dgd 2/21/2003 22:53'!\\nturtlesAtX: x y: y do: aBlock \\n\\t\\\"Evaluate the given block for each turtle at the given location.\\\"\\n\\n\\t| t |\\n\\tt := self firstTurtleAtX: x y: y.\\n\\t[t isNil] whileFalse: \\n\\t\\t\\t[aBlock value: t.\\n\\t\\t\\tt := t nextTurtle]! !\\n\\n!StarSqueakMorph methodsFor: 'turtles' stamp: 'jm 3/3/2001 18:08'!\\nturtlesDo: aBlock\\n\\t\\\"Evaluate the given block for every turtle. For example:\\n\\t\\tw turtlesDo: [:t | t forward: 1]\\n\\twill tell every turtle to go forward by one turtle step.\\\"\\n\\n\\tturtles do: aBlock.\\n\\tself changed.\\n! !\\n\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ncreatePatchFormGetterAndSetter\\n\\t\\\"Create BitBlt's for getting and setting patch colors.\\\"\\n\\n\\tpatchColorGetter := BitBlt bitPeekerFromForm: patchForm.\\n\\tpatchColorSetter :=\\n\\t\\t(BitBlt toForm: patchForm)\\n\\t\\t\\tcombinationRule: Form over;\\n\\t\\t\\tclipRect: patchForm boundingBox;\\n\\t\\t\\twidth: pixelsPerPatch;\\n\\t\\t\\theight: pixelsPerPatch.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ndeleteTurtle: aTurtle\\n\\t\\\"Delete the given turtle from this world.\\\"\\n\\n\\tturtles := turtles copyWithout: aTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 1/22/2001 16:58'!\\ndimensions\\n\\n\\t^ dimensions\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:32'!\\ndisplayPatchVariableOn: aForm color: aColor shift: shiftAmount \\n\\t\\\"Display patchVariableToDisplay in the given color. The opacity (alpha) of of each patch is determined by the patch variable value for that patch and shiftAmount. If shiftAmount is zero, the source value is unscaled. Positive shiftAmount values result in right shifting the source value by the given number of bits (That is, multiplying by 2^N. Negative values perform right shifts, dividing by 2^N).\\\"\\n\\n\\t| patchVar bitBlt w rowOffset alpha |\\n\\tpatchVariableToDisplay ifNil: [^self].\\n\\tpatchVar := patchVariables at: patchVariableToDisplay ifAbsent: [^self].\\n\\n\\t\\\"set up the BitBlt\\\"\\n\\tbitBlt := (BitBlt toForm: aForm)\\n\\t\\t\\t\\tsourceRect: (0 @ 0 extent: pixelsPerPatch);\\n\\t\\t\\t\\tfillColor: aColor;\\n\\t\\t\\t\\tcombinationRule: 30.\\n\\tw := dimensions x.\\n\\t0 to: dimensions y - 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\trowOffset := y * w + 1.\\n\\t\\t\\t0 to: w - 1\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\talpha := (patchVar at: rowOffset + x) bitShift: shiftAmount.\\n\\t\\t\\t\\t\\talpha := alpha min: 255.\\n\\t\\t\\t\\t\\talpha > 1 \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[\\\"if not transparent, fill using the given alpha\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\tbitBlt destOrigin: (x * pixelsPerPatch) @ (y * pixelsPerPatch).\\n\\t\\t\\t\\t\\t\\t\\tbitBlt copyBitsTranslucent: alpha]]]! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nfirstTurtleAtX: xPos y: yPos \\n\\n\\t| w t x y index |\\n\\t\\\"create turtlesAtPatchCache if necessary\\\"\\n\\tturtlesAtPatchCache ifNil: [\\n\\t\\tturtlesAtPatchCache := Array new: (dimensions x * dimensions y) withAll: nil.\\n\\t\\tturtlesAtPatchCacheValid := false].\\n\\n\\tw := dimensions y.\\n\\tturtlesAtPatchCacheValid ifFalse: [\\n\\t\\tturtlesAtPatchCache atAllPut: nil.\\n\\t\\t\\\"cache not yet computed for this step; make linked list of turtles for each patch\\\"\\n\\t\\t1 to: turtles size do: [:i |\\n\\t\\t\\tt := turtles at: i.\\n\\t\\t\\tx := t x truncated.\\n\\t\\t\\ty := t y truncated.\\n\\t\\t\\tindex := (w * y) + x + 1.\\n\\t\\t\\tt nextTurtle: (turtlesAtPatchCache at: index).\\n\\t\\t\\tturtlesAtPatchCache at: index put: t].\\n\\t\\tturtlesAtPatchCacheValid := true].\\n\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\tindex := (w * y) + x + 1.\\n\\t^ turtlesAtPatchCache at: index\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchBrightnessAtX: x y: y\\n\\t\\\"Answer the brightness of the patch at the given location, a number from 0 to 100.\\\"\\n\\n\\t| c |\\n\\tc := self getPatchColorAtX: x y: y.\\n\\t^ (c brightness * 100.0) rounded\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchColorAtX: x y: y\\n\\t\\\"Answer the color of the patch at the given location.\\\"\\n\\n\\t| pixel |\\n\\tpixel := patchColorGetter pixelAt:\\n\\t\\t(pixelsPerPatch * x truncated)@(pixelsPerPatch * y truncated).\\n\\t^ Color colorFromPixelValue: pixel depth: patchForm depth\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\ngetPatchVariable: patchVarName atX: xPos y: yPos\\n\\t\\\"Answer the value of the given patch variable at the given turtle. Answer zero if the turtle is out of bounds.\\\"\\n\\n\\t| x y i |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ 0].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ 0].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\t^ (patchVariables at: patchVarName ifAbsent: [^ 0]) at: i\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nincrementPatchVariable: patchVarName atX: xPos y: yPos by: amount\\n\\t\\\"Increment the value of the given patch variable at the given location by the given amount. Do nothing if the location is out of bounds.\\\"\\n\\n\\t| x y i var |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ self].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ self].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\tvar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tvar at: i put: ((var at: i) + amount).\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nnewSliderForParameter: parameter target: target min: min max: max description: description\\n\\n\\t| c slider r s |\\n\\tc := (AlignmentMorph newColumn)\\n\\t\\tcolor: Color lightBlue;\\n\\t\\tborderWidth: 2;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tuseRoundedCorners.\\n\\tslider := SimpleSliderMorph new\\n\\t\\tcolor: (Color r: 0.065 g: 0.548 b: 0.645);\\n\\t\\textent: 150@2;\\n\\t\\ttarget: target;\\n\\t\\tactionSelector: (parameter, ':') asSymbol;\\n\\t\\tminVal: min;\\n\\t\\tmaxVal: max;\\n\\t\\tadjustToValue: (target perform: parameter asSymbol).\\n\\tc addMorphBack: slider.\\n\\tr := (AlignmentMorph newRow)\\n\\t\\tcolor: Color lightBlue;\\n\\t\\thResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill.\\n\\ts := StringMorph new contents: parameter, ': '.\\n\\tr addMorphBack: s.\\n\\ts := UpdatingStringMorph new\\n\\t\\ttarget: target;\\n\\t\\tgetSelector: parameter asSymbol;\\n\\t\\tputSelector: (parameter, ':') asSymbol;\\n\\t\\tfloatPrecision: (10.0 raisedTo: (((max - min) / 150.0) log: 10) floor);\\n\\t\\tstep.\\n\\tr addMorphBack: s.\\n\\tc addMorphBack: r.\\n\\tc setBalloonText: description.\\n\\t^ c\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 1/18/2001 21:58'!\\npatchVariable: patchVarName ifAbsent: aBlock\\n\\t\\\"Answer the patch variable array of the given name. If no such patch variables exists, answer the result of evaluating the given block.\\\"\\n\\n\\t^ patchVariables at: patchVarName ifAbsent: aBlock\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nreplicateTurtle: aTurtle\\n\\t\\\"Create an exact copy of the given turtle and add it to this world.\\\"\\n\\n\\t| newTurtle |\\n\\tnewTurtle := aTurtle clone who: (lastTurtleID := lastTurtleID + 1).\\n\\tturtles := turtles copyWith: newTurtle.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:34'!\\nsetPatchBrightnessAtX: x y: y to: percent \\n\\t\\\"Set the brightness of the patch at the given location to the given level, where 0 is black and 100 is full brightness.\\\"\\n\\n\\t| c brightness |\\n\\tc := self getPatchColorAtX: x y: y.\\n\\tbrightness := percent / 100.0.\\n\\tbrightness := brightness max: 0.03125.\\n\\tself \\n\\t\\tsetPatchColorAtX: x\\n\\t\\ty: y\\n\\t\\tto: (Color \\n\\t\\t\\t\\th: c hue\\n\\t\\t\\t\\ts: c saturation\\n\\t\\t\\t\\tv: brightness)! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jm 2/7/2001 07:20'!\\nsetPatchColorAtX: x y: y to: aColor\\n\\t\\\"Paint the patch at the given location with the given color.\\\"\\n\\n\\tpatchColorSetter\\n\\t\\tfillColor: aColor;\\n\\t\\tdestX: (pixelsPerPatch * x truncated);\\n\\t\\tdestY: (pixelsPerPatch * y truncated);\\n\\t\\tcopyBits.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nsetPatchVariable: patchVarName atX: xPos y: yPos to: newValue\\n\\t\\\"Set the value of the given patch variable below the given turtle to the given value. Do nothing if the turtle is out of bounds.\\\"\\n\\n\\t| x y i var |\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ self].\\n\\t((x >= dimensions x) or: [y >= dimensions y]) ifTrue: [^ self].\\n\\ti := ((y * dimensions x) + x) truncated + 1.\\n\\tvar := patchVariables at: patchVarName ifAbsent: [^ self].\\n\\tvar at: i put: newValue.\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'sd 11/20/2005 21:26'!\\nsumPatchVariable: patchVarName neighborsAtX: xPos y: yPos\\n\\t\\\"Answer the sum of the given patch variable for the eight neighbors of the patch at the given location. Answer zero if the location is out of bounds.\\\"\\n\\n\\t| patchVar x y w h xLeft xRight rowOffset sum |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^ 0].\\n\\tx := xPos truncated.\\n\\ty := yPos truncated.\\n\\tw := dimensions x.\\n\\th := dimensions y.\\n\\t((x < 0) or: [y < 0]) ifTrue: [^ 0].\\n\\t((x >= w) or: [y >= h]) ifTrue: [^ 0].\\n\\txLeft := (x - 1) \\\\\\\\ w. \\\"column before x, wrapped\\\"\\n\\txRight := (x + 1) \\\\\\\\ w. \\\"column after x, wrapped\\\"\\n\\trowOffset := y * w.\\n\\tsum :=\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\trowOffset := ((y - 1) \\\\\\\\ h) * w. \\\"row above y, wrapped\\\"\\n\\tsum := sum +\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + x) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\trowOffset := ((y + 1) \\\\\\\\ h) * w. \\\"row below y, wrapped\\\"\\n\\tsum := sum +\\n\\t\\t(patchVar at: rowOffset + xLeft) +\\n\\t\\t(patchVar at: rowOffset + x) +\\n\\t\\t(patchVar at: rowOffset + xRight).\\n\\t^ sum\\n\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private' stamp: 'jdl 3/28/2003 09:36'!\\nuphillOf: patchVarName forTurtle: aTurtle \\n\\t\\\"Answer the heading the points in the direction of increasing value for the given patch variable. If there is no gradient, or if the turtle is outside the world bounds, answer the turtles current heading.\\\"\\n\\n\\t| patchVar turtleX turtleY startX endX startY endY maxVal rowOffset thisVal maxValX maxValY |\\n\\tpatchVar := patchVariables at: patchVarName ifAbsent: [^aTurtle heading].\\n\\tturtleX := aTurtle x truncated + 1.\\n\\tturtleY := aTurtle y truncated + 1.\\n\\tturtleX := turtleX max: 1.\\n\\tturtleY := turtleY max: 1.\\n\\tturtleX := turtleX min: dimensions x.\\n\\tturtleY := turtleY min: dimensions y.\\n\\tstartX := turtleX - sniffRange max: 1.\\n\\tendX := turtleX + sniffRange min: dimensions x.\\n\\tstartY := turtleY - sniffRange max: 1.\\n\\tendY := turtleY + sniffRange min: dimensions y.\\n\\tmaxVal := patchVar at: (turtleY - 1) * dimensions x + turtleX.\\n\\tmaxValX := nil.\\n\\tstartY to: endY\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\trowOffset := (y - 1) * dimensions x.\\n\\t\\t\\tstartX to: endX\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tthisVal := patchVar at: rowOffset + x.\\n\\t\\t\\t\\t\\tthisVal > maxVal \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[maxValX := x.\\n\\t\\t\\t\\t\\t\\t\\tmaxValY := y.\\n\\t\\t\\t\\t\\t\\t\\tmaxVal := thisVal]]].\\n\\tnil = maxValX ifTrue: [^aTurtle heading].\\n\\t^(((maxValX - turtleX) @ (maxValY - turtleY)) degrees + 90.0) \\\\\\\\ 360.0! !\\n\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'jdl 3/28/2003 09:46'!\\nprimDiffuseFrom: srcBitmap to: dstBitmap width: width height: height delta: delta \\n\\t\\\"Diffuse the integer values of the source patch variable Bitmap into the output Bitmap. Each cell of the output is the average of the NxN area around it in the source, where N = (2 * delta) + 1.\\\"\\n\\n\\t| area startY endY startX endX sum rowStart |\\n\\t<primitive: 'primitiveDiffuseFromToWidthHeightDelta' module: 'StarSqueakPlugin'>\\n\\tarea := (2 * delta + 1) * (2 * delta + 1).\\n\\t1 to: height\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\tstartY := y - delta.\\n\\t\\t\\tstartY := startY max: 1.\\n\\t\\t\\tendY := y + delta.\\n\\t\\t\\tendY := endY min: height.\\n\\t\\t\\t1 to: width\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tstartX := x - delta.\\n\\t\\t\\t\\t\\tstartX := startX max: 1.\\n\\t\\t\\t\\t\\tendX := x + delta.\\n\\t\\t\\t\\t\\tendX := endX min: width.\\n\\t\\t\\t\\t\\tsum := 0.\\n\\t\\t\\t\\t\\tstartY to: endY\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:y2 | \\n\\t\\t\\t\\t\\t\\t\\trowStart := (y2 - 1) * width.\\n\\t\\t\\t\\t\\t\\t\\tstartX to: endX do: [:x2 | sum := sum + (srcBitmap at: rowStart + x2)]].\\n\\t\\t\\t\\t\\tdstBitmap at: (y - 1) * width + x put: sum // area]]! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'jm 3/12/2001 09:45'!\\nprimEvaporate: aBitmap rate: rate\\n\\t\\\"Evaporate the integer values of the source Bitmap at the given rate, an integer between 0 and 1024, where 1024 is a scale factor of 1.0 (i.e., no evaporation). That is, replace each integer element v with (rate * v) / 1024.\\\"\\n\\n\\t<primitive: 'primitiveEvaporateRate' module: 'StarSqueakPlugin'>\\n\\t1 to: aBitmap size do: [:i |\\n\\t\\taBitmap at: i put: (((aBitmap at: i) * rate) bitShift: -10)].\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\nprimMapFrom: srcBitmap to: dstBitmap width: w height: h patchSize: patchSize rgbFlags: rgbFlags shift: shiftAmount \\n\\t\\\"Map values in the source bitmap (interpreted as unsigned 32-bit integers) to 2x2 patches of color in the destination bitmap. The color brightness level is determined by the source value and the color hue is determined by the bottom three bits of the rgbFlags value. For example, if rgbFlags is 1, you get shades of blue, if it is 6 you get shades of yellow, and if it is 7, you get shades of gray. The shiftAmount is used to scale the source data values by a power of two. If shiftAmount is zero, the data is unscaled. Positive shiftAmount values result in right shifting the source data by the given number of bits (multiplying by 2^N, negative values perform right shifts (dividing by 2^N). The width parameter gives the width of the Form that owns the destination bitmap.\\\"\\n\\n\\t| rgbMult srcIndex level pixel offset |\\n\\t<primitive: 'primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift' module: 'StarSqueakPlugin'>\\n\\trgbMult := 0.\\n\\t(rgbFlags bitAnd: 4) > 0 ifTrue: [rgbMult := rgbMult + 65536].\\n\\t(rgbFlags bitAnd: 2) > 0 ifTrue: [rgbMult := rgbMult + 256].\\n\\t(rgbFlags bitAnd: 1) > 0 ifTrue: [rgbMult := rgbMult + 1].\\n\\tsrcIndex := 0.\\n\\t0 to: h // patchSize - 1\\n\\t\\tdo: \\n\\t\\t\\t[:y | \\n\\t\\t\\t0 to: w // patchSize - 1\\n\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t[:x | \\n\\t\\t\\t\\t\\tlevel := (srcBitmap at: (srcIndex := srcIndex + 1)) bitShift: shiftAmount.\\n\\t\\t\\t\\t\\tlevel := level min: 255.\\n\\t\\t\\t\\t\\tpixel := level <= 0 \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"non-transparent black\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t1]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [level * rgbMult].\\n\\n\\t\\t\\t\\t\\t\\\"fill a patchSize x patchSize square with the pixel value\\\"\\n\\t\\t\\t\\t\\toffset := (y * w + x) * patchSize.\\n\\t\\t\\t\\t\\toffset to: offset + ((patchSize - 1) * w)\\n\\t\\t\\t\\t\\t\\tby: w\\n\\t\\t\\t\\t\\t\\tdo: \\n\\t\\t\\t\\t\\t\\t\\t[:rowStart | \\n\\t\\t\\t\\t\\t\\t\\trowStart + 1 to: rowStart + patchSize\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:dstIndex | dstBitmap at: dstIndex put: pixel]]]]! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\ntestDiffusePrim\\n\\t\\\"This test should diffuse the initial value in the center cell so that each cell has 1000.\\\"\\n\\t\\\"StarSqueakMorph new testDiffusePrim\\\"\\n\\n\\t| src dst |\\n\\tsrc := Bitmap new: 49.\\n\\tsrc at: 25 put: 49000.\\n\\tdst := Bitmap new: 49.\\n\\tself primDiffuseFrom: src to: dst width: 7 height: 7 delta: 3.\\n\\t^ dst asArray\\n! !\\n\\n!StarSqueakMorph methodsFor: 'private-primitives' stamp: 'sd 11/20/2005 21:26'!\\ntestEvaporatePrim\\n\\t\\\"This test should result in reducing each element of the array to 75% of its initial value.\\\"\\n\\t\\\"StarSqueakMorph new testEvaporatePrim\\\"\\n\\n\\t| data |\\n\\tdata := Bitmap new: 10.\\n\\t1 to: data size do: [:i | data at: i put: (10000 * i)].\\n\\tself primEvaporate: data rate: (75 * 1024) // 100.\\n\\t^ data asArray\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakMorph class methodsFor: 'class initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\t\\\"StarSqueakMorph initialize\\\"\\n\\n\\tRandomSeed := 17.\\n! !\\nObject subclass: #StarSqueakPatch\\n\\tinstanceVariableNames: 'world worldWidth worldHeight x y'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakPatch commentStamp: '<historical>' prior: 0!\\nI represent a patch in a StarSqueak world. Patch objects are not retained, but are created as needed, such as in patchesDo:.\\n!\\n\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/27/2001 08:59'!\\nasPoint\\n\\n\\t^ x @ y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/19/2001 08:28'!\\nworld\\n\\n\\t^ world\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nworld: aStarSqueakMorph\\n\\t\\\"Set the world for this patch. Also record the world's width and height.\\\"\\n\\n\\t| dims |\\n\\tworld := aStarSqueakMorph.\\n\\tdims := world dimensions.\\n\\tworldWidth := dims x.\\n\\tworldHeight := dims y.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/18/2001 21:27'!\\nx\\n\\n\\t^ x\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nx: anInteger\\n\\n\\tx := anInteger.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'jm 1/18/2001 21:27'!\\ny\\n\\n\\t^ y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ny: anInteger\\n\\n\\ty := anInteger.\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisBottomEdge\\n\\n\\t^ y = (worldHeight - 1)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisLeftEdge\\n\\n\\t^ x = 0\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisRightEdge\\n\\n\\t^ x = (worldWidth - 1)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'geometry' stamp: 'jm 1/28/2001 15:27'!\\nisTopEdge\\n\\n\\t^ y = 0\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone x: ((x + 1) \\\\\\\\ worldWidth)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborN\\n\\t\\\"Answer the neightboring patch directly north of (above) this patch.\\\"\\n\\n\\t^ self clone y: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborNE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x + 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborNW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x - 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y - 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborS\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone y: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:03'!\\nneighborSE\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x + 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'hh 8/26/2001 17:04'!\\nneighborSW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone\\n\\t\\tx: ((x - 1) \\\\\\\\ worldWidth);\\n\\t\\ty: ((y + 1) \\\\\\\\ worldHeight)\\n! !\\n\\n!StarSqueakPatch methodsFor: 'neighborhood' stamp: 'jm 1/28/2001 15:06'!\\nneighborW\\n\\t\\\"Answer the neightboring patch directly south of (below) this patch.\\\"\\n\\n\\t^ self clone x: ((x - 1) \\\\\\\\ worldWidth)\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:57'!\\nbrightness\\n\\t\\\"Answer the brightness of this patch, a number from 0 to 100.\\\"\\n\\n\\t^ world getPatchBrightnessAtX: x y: y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:56'!\\nbrightness: percent\\n\\t\\\"Set the brightness of this patch to the given level, where 0 is nearly black and 100 is full brightness.\\\"\\n\\n\\tworld setPatchBrightnessAtX: x y: y to: percent.\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:58'!\\ncolor\\n\\t\\\"Answer the color of this patch.\\\"\\n\\n\\t^ world getPatchColorAtX: x y: y\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch color' stamp: 'jm 1/24/2001 15:58'!\\ncolor: aColor\\n\\t\\\"Paint this patch the given color.\\\"\\n\\n\\tworld setPatchColorAtX: x y: y to: aColor.\\n! !\\n\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'jm 1/18/2001 21:31'!\\ndistanceTo: aPoint\\n\\t\\\"Answer the distance from this patch to the given point.\\\"\\n\\n\\t^ ((x - aPoint x) squared + (y - aPoint y) squared) sqrt\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'sd 11/20/2005 21:26'!\\nget: patchVarName\\n\\t\\\"Answer the value of the given patch variable for this patch.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := world patchVariable: patchVarName ifAbsent: [^ 0].\\n\\t^ patchVar at: (y * world dimensions x) + x + 1\\n! !\\n\\n!StarSqueakPatch methodsFor: 'patch variables' stamp: 'sd 11/20/2005 21:26'!\\nset: patchVarName to: newValue\\n\\t\\\"Set the value of the given patch variable for this patch to the given value.\\\"\\n\\n\\t| patchVar |\\n\\tpatchVar := world patchVariable: patchVarName ifAbsent: [^ self].\\n\\tpatchVar at: (y * world dimensions x) + x + 1 put: newValue.\\n! !\\nStarSqueakMorph subclass: #StarSqueakSlimeMold\\n\\tinstanceVariableNames: 'cellCount'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakSlimeMold methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tcellCount := 200.\\n\\tsuper initialize.\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'menu' stamp: 'jm 2/7/2001 19:51'!\\nsliderParameters\\n\\t\\\"Answer a list of parameters that the user can change via a slider. Each parameter is described by an array of: <name> <min value> <max value> <balloon help string>.\\\"\\n\\n\\t^ super sliderParameters, #(\\n\\t\\t(cellCount 50 2000 'The number of slime mold cells.'))\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'other' stamp: 'jm 1/19/2001 18:36'!\\ndiffusePheromone\\n\\n\\tself diffusePatchVariable: 'pheromone'.\\n! !\\n\\n!StarSqueakSlimeMold methodsFor: 'other' stamp: 'jm 1/19/2001 18:36'!\\nevaporatePheromone\\n\\n\\tself decayPatchVariable: 'pheromone'.\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'parameters' stamp: 'jm 2/7/2001 19:28'!\\ncellCount\\n\\n\\t^ cellCount\\n! !\\n\\n!StarSqueakSlimeMold methodsFor: 'parameters' stamp: 'sd 11/20/2005 21:26'!\\ncellCount: aNumber\\n\\n\\tcellCount := aNumber asInteger.\\n\\n! !\\n\\n\\n!StarSqueakSlimeMold methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself makeTurtles: cellCount class: SlimeMoldTurtle.\\n\\tself createPatchVariable: 'pheromone'. \\\"emitted by slime mold cells\\\"\\n\\tturtleDemons := #(dropPheromone followPheromone breakLoose).\\n\\tworldDemons := #(evaporatePheromone diffusePheromone).\\n\\tself displayPatchVariable: 'pheromone'.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakSlimeMold class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakSlimeMold class methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:36'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName:\\t'SlimeMold'\\n\\t\\tcategories:\\t\\t#('StarSqueak')\\n\\t\\tdocumentation:\\t'A slime-mold simulation using StarSqueak'\\n\\t\\tsampleImageForm: (Form\\n\\textent: 92@96\\n\\tdepth: 8\\n\\tfromArray: #( 673720360 676154664 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1398364499 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1396729208 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1294477352 674900008 673720360 673720360 673720360 673720360 673720360 673729869 1918072946 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 674900008 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 673720360 1296921202 1920103026 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1296902184 673720360 673720360 673720397 1296921239 2021169010 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296921202 1917668685 1296911656 673720360 673720360 673720397 1299346040 1701148786 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729832 673720360 673720360 673720360 673720360 673720360 673729869 1299355580 2543284850 1296911656 673720360 673720360 673720397 1296921276 2122234994 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920121883 3784808306 1296911656 673720360 673720360 673720397 1296921202 2543294322 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922530886 3787233138 1296911656 673720360 673720360 673720397 1296911730 1920103026 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1918442267 3784808306 1296911656 673720360 673720360 673720397 1296911693 1920093517 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299365052 3164041842 1296911656 673720360 673720360 673720397 1296911693 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296902184 673720360 673720360 673720360 673720360 673720397 1299346034 2540859981 1296911656 673720360 673720360 673720397 1296911693 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1294477352 673720360 673720360 673720360 673720397 1296911730 1920093517 1296911656 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 673720360 673720360 673720360 673720360 1296911693 1296911693 1296911656 673720360 673720360 676154701 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1299336525 1296911693 673720360 673720360 673720360 673720360 1296911693 1296911693 1296911656 673720360 673720360 1296911693 1296911693 1294477352 673720360 1179002920 673720360 673720360 673720360 673720360 673720360 673720360 1296911730 1920103026 1917668685 1296902184 673720360 673720360 673720360 676154701 1296911693 1296911656 673720360 673720397 1296911693 1179471181 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296921202 2543294359 1920093517 1296911693 1294477352 673720360 673720360 673729869 1296911693 1296911656 673720360 673720397 1296462450 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921177 1189199036 2540850509 1296911693 1296911656 673720360 673720360 673729869 1296911693 1296911693 673720360 673720397 1299346071 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921276 3779479228 2540859981 1296911693 1296911693 673720360 673720360 673729869 1296921202 1917668685 1294477352 673720397 1299334726 1179471181 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346108 1179050465 2543284850 1920103026 1917668685 1294477352 673720360 673729869 1299346034 1920093517 1294477352 673720397 1299346071 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921276 3779518908 2540860018 1920103001 1500663117 1294477352 673720360 673729869 1920112454 2540859981 1296902184 673720397 1296921202 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921239 3166485692 1920103026 1920104537 1501065805 1296902184 673720360 673729869 1922530886 2123854413 1296902184 673720360 1296911693 1296911656 673720360 673720360 975710248 673720360 673720360 673720360 673720360 673720360 673720397 1296921202 1920103026 1920093554 1920104549 1702392397 1296902184 673720360 673729869 1922530886 1503097421 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673721896 673720360 673720360 673720360 673720360 1296911693 1920103026 1296911693 1920103032 2020756813 1296902184 673720360 673729869 1920121945 2540859981 1294477352 673720360 673720360 673720360 673720360 774383656 673720360 673720360 673721896 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 1299346040 2020756813 1294477352 673720360 673729869 1299346034 1500663117 1294477352 673720360 673720360 673720360 673720360 774383656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1296911699 1397574989 1294477352 673720360 673729869 1296911693 877481293 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 774776872 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 1296911693 673720360 673720360 673720397 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 774776872 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296902184 673720360 673720360 673720397 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299346034 1920102989 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299355580 3164041842 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1922546845 2646382450 1296911656 673720360 673720360 673720360 674900008 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1924981019 454777202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920917787 454777202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920122044 3166466674 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1920103001 1180267085 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1299346034 1920093517 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911730 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673724968 673720360 673720397 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 676154701 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1296902184 673720360 673720360 673720360 673720360 673720397 1296921202 1499024717 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720397 1296921239 2540850509 1294477352 673720360 673720360 673720360 673720360 675686440 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673729869 1296914758 1180257613 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296462450 1917668685 1294477352 673720360 673720360 673720360 673720360 673729869 1299346009 1500663117 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112535 2540850509 1294477352 673720360 673720360 673720360 673720360 676154701 1296921202 1920093517 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112454 2539205709 1294477352 673720360 673720360 673720360 673720360 676154701 1296921202 1917668685 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922516550 3161607501 1294477352 673720360 673720360 673720360 673720360 1296911693 1299345997 1296911693 1294477352 673720360 673720360 673720360 673720390 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299339609 2540850509 1294477352 673720360 673720360 673720360 673720360 1296911730 1920093517 1296911693 1294477352 673729832 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1299346009 1917668685 1294477352 673720360 673720360 673720360 673720360 1296921202 1500672589 1296911693 673720397 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911705 1296911693 673720360 673720360 673720360 673720360 673720397 1296914839 1181905491 1397574989 673729869 1296911668 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 1296914802 1181896019 1397574952 676154701 1296921177 1917668685 1294477352 673720360 673720360 673720366 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 1296911730 1181896013 1296902184 673729869 1299346009 1397969741 1296902184 673720360 673720360 673720366 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674900008 673720360 673720360 676154701 877481293 1294477352 673729869 1296914777 1397969741 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674900008 673720360 673720360 673729869 1296911693 673720360 673720397 1296914802 1917668685 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911705 1296911693 1294477352 673729844 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154676 1296911656 673720360 673729844 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673729869 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674113576 673720360 673720360 673720360 673720360 673720360 676154701 1296911693 1294477352 673720360 673720360 673720360 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674113576 673720360 673720360 673720360 673720360 673720360 1296911693 1296911693 1296902184 673724986 673720360 673720397 1296921202 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296921202 1920103026 1296911656 673720360 673720360 673720397 1299355543 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346071 2543294322 1917668648 673720360 673720360 673720397 1299334726 1498238285 673720360 673720360 673720360 673720360 673720360 673720360 673720378 975710248 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1920112572 3789676988 1917668648 673720360 673720360 673720397 1299339609 1917668685 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922546913 3779518908 1920093480 673720360 673720360 673720397 1296921202 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922516705 3779468121 1499024717 673720360 673720360 673720360 1296911693 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1922546913 3779518908 1920093480 673720360 673720360 673720360 676154701 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1920112572 3789676988 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 674904616 673720397 1299334726 2543294322 1917668648 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1299346034 1920103026 1296911656 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673724986 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911730 1920093517 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1294477352 673720360 673720360 673720360 1296911693 1296911693 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676148294 877471784 673720360 673720360 673720360 676154701 1296911693 673720360 673720360 673720360 675686440 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911668 877013032 673720360 673720360 673720360 673720360 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911693 1296902184 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720397 1296911656 673720360 673720360 676154701 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1397968205 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1497387853 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1497387853 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676154701 1397968205 1294477352 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673729869 1296911693 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1296911668 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720378 673720360 673720360 673720360 673720360 673720360 673720360 673721896 673720360 673720360 673720360)\\n\\toffset: 152@256)! !\\nStarSqueakMorph subclass: #StarSqueakTermites\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakTermites methodsFor: 'all' stamp: 'jm 1/24/2001 08:50'!\\nsetupPatches\\n\\t\\\"Create patch variables for sensing the nest and food caches. The nestScent variable is diffused so that it forms a 'hill' of scent over the entire world with its peak at the center of the nest. That way, the ants always know which way the nest is.\\\"\\n\\n\\tself createPatchVariable: 'woodChips'. \\\"number of wood chips on patch\\\"\\n\\tself displayPatchVariable: 'woodChips' logScale: 5.\\n\\tself patchesDo: [:p |\\n\\t\\t(self random: 8) = 0\\n\\t\\t\\tifTrue: [p set: 'woodChips' to: 1]\\n\\t\\t\\tifFalse: [p set: 'woodChips' to: 0]].\\n! !\\n\\n!StarSqueakTermites methodsFor: 'all' stamp: 'jm 1/28/2001 15:35'!\\nsetupTurtles\\n\\t\\\"Create an initialize my termites.\\\"\\n\\n\\tself makeTurtles: 400 class: TermiteTurtle.\\n\\tself turtlesDo: [:t | t isCarryingChip: false].\\n! !\\n\\n\\n!StarSqueakTermites methodsFor: 'setup' stamp: 'sd 11/20/2005 21:26'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself setupPatches.\\n\\tself setupTurtles.\\n\\tturtleDemons := #(walk wiggle lookForChip lookForPile).\\n! !\\nStarSqueakMorph subclass: #StarSqueakTrees\\n\\tinstanceVariableNames: 'depth treeTypeSelector'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Worlds'!\\n\\n!StarSqueakTrees methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tdepth := 8.\\n\\ttreeTypeSelector := #tree1.\\n\\tself setup.\\n! !\\n\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu addLine.\\n\\taCustomMenu add: 'set tree depth' translated action: #setTreeDepth.\\n\\taCustomMenu add: 'set tree type' translated action: #setTreeType.\\n! !\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'rbb 3/1/2005 11:15'!\\nsetTreeDepth\\n\\n\\t| reply |\\n\\treply := UIManager default\\n\\t\\trequest: 'Tree depth (a number between 1 and 12)?'\\n\\t\\tinitialAnswer: depth printString.\\n\\treply isEmpty ifTrue: [^ self].\\n\\tdepth := ((reply asNumber rounded) max: 1) min: 12.\\n\\tself startOver.\\n! !\\n\\n!StarSqueakTrees methodsFor: 'menu' stamp: 'sd 11/20/2005 21:26'!\\nsetTreeType\\n\\n\\t| menu choice |\\n\\tmenu := CustomMenu new title: 'Choose tree type:'.\\n\\tmenu add: 'tree1' action: #tree1.\\n\\tmenu add: 'tree2' action: #tree2.\\n\\tchoice := menu startUp.\\n\\tchoice ifNotNil: [\\n\\t\\ttreeTypeSelector := choice.\\n\\t\\tself startOver].\\n! !\\n\\n\\n!StarSqueakTrees methodsFor: 'parts bin' stamp: 'sd 11/20/2005 21:26'!\\ninitializeToStandAlone\\n\\tself initialize.\\n\\ttreeTypeSelector := #tree2.\\n\\tself setup. \\\"Run earlier, but need to run again to get the #tree2 used\\\"\\n\\tself startRunning! !\\n\\n\\n!StarSqueakTrees methodsFor: 'setup' stamp: 'jm 3/12/2001 09:59'!\\nsetup\\n\\n\\tself clearAll.\\n\\tself makeTurtles: 1 class: TreeTurtle.\\n\\tself turtlesDo: [:t |\\n\\t\\tt goto: 50@90.\\n\\t\\tt penDown.\\n\\t\\tt color: Color red.\\n\\t\\tt heading: 0.\\n\\t\\tt length: 15.\\n\\t\\tt depth: depth].\\n\\tself addTurtleDemon: treeTypeSelector.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStarSqueakTrees class\\n\\tinstanceVariableNames: ''!\\n\\n!StarSqueakTrees class methodsFor: 'parts bin' stamp: 'sw 10/24/2001 16:37'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName:\\t'Trees'\\n\\t\\tcategories:\\t\\t#('StarSqueak')\\n\\t\\tdocumentation:\\t'A tree-growing simulation using StarSqueak'\\n\\t\\tsampleImageForm: (Form\\n\\textent: 70@72\\n\\tdepth: 8\\n\\tfromArray: #( 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 681453608 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 681453608 673720360 673720360 673720360 673710080 673720360 673720360 673720360 1313744936 2661165134 2655922216 673720360 676241054 673720360 673720360 673720360 673720360 2653431848 1311284776 673720398 673720360 673720360 673710080 673720360 673720360 673720398 1313744936 2661195342 1311254568 673720360 676241054 2653431848 673750686 2661174862 2653431848 2655931944 1318987816 673720398 681453608 673720360 673710080 673720360 673720360 673750686 1313754664 2661195342 1311254568 673750606 673750686 673720360 673750686 2655931982 1318987816 2655922254 2653462174 673720398 2653431848 673720360 673710080 673720360 673720360 681453646 1319018024 2653431966 1311254568 673750686 1311284894 673720360 673720478 2661174862 2661165096 2653441694 2661195422 673720398 673750568 673720360 673710080 673720360 673720360 2661195342 676220574 2653431886 1313775262 681483934 1311284776 2653441576 673720478 681463374 2653431848 3257421470 2653462174 1311264334 681453726 673720360 673710080 673720360 673720398 2661195342 673730206 2653431848 1318997662 2661174862 3262300712 2653462174 1311254722 683852402 673720514 683843230 2661195422 1311264334 2661195304 673720360 673710080 673720360 673720360 2661195342 1313754782 2661165096 1920093854 2653441614 3262300712 681483854 1313744936 3262300786 673720514 3257411662 2661195304 673730206 673720360 673720360 673710080 673720360 673720398 681483934 2661195422 2661165096 1319018142 2653462094 678609448 681463454 2655922216 3262280232 673759938 3257421470 3267504286 676220456 673750568 673720360 673710080 673720360 673730206 673750606 2655922370 673759902 2661174942 3257421352 678570024 683852366 673720360 3245437224 683786792 683831848 1915264670 1316123176 673750686 673720360 673710080 673720360 673720360 2661165134 678589122 673750686 3267514049 2663524392 678504488 683812904 673720360 683766056 683747368 3267543746 2661195304 3262261288 2661165214 1311254568 673710080 673720360 673720360 673750606 673739304 3265175118 2661174977 3267504168 678504488 3240634408 673720360 678504488 1898496449 673720433 3265175198 3267543746 2661195422 1311254568 673710080 673720360 673730206 673720398 673720514 3257411742 2663563969 683812904 673759681 3240634408 673720360 678504488 1908484136 673720433 1898487490 1915234344 673720360 673720360 673710080 673720360 676241054 673720434 3262261288 3257441832 673739458 683747368 673759528 673720360 673720360 678504561 1898457128 673720433 1908484136 673720360 2661165096 673720360 673710080 673720360 676220456 2661195304 1920084008 3250661416 673720513 3250661416 673759528 673720360 673720360 678504561 1898457128 673739121 1898457128 673720360 2661195422 673720360 673710080 673720360 673730206 2653432002 3267523112 673759528 673720360 3250661416 673759528 673720360 673720360 678523249 673720360 673739201 1898457128 673720360 2661195304 673720360 673710080 673720360 676154958 1311254642 1920103025 1898496296 673720360 3245428008 676163880 673720360 673720360 681341261 673720360 676163953 1294477352 673720397 1313754702 673720360 673710080 673720360 676154664 673720360 673729905 1903280461 673720360 3240653133 678504488 673720360 673720360 681332008 673720360 681341224 673720360 676164253 676220574 673720360 673710080 673720360 673720360 673720360 673720360 678523292 1294477352 3240653212 1299261480 673720360 673720360 1903241256 673720360 681332008 673720360 1302109554 1319018142 673720360 673710080 673720360 673720360 673720360 673720360 673720433 1903250728 3240643996 1903241256 673720360 673720360 3243059240 673720360 1900881960 673720433 1903250728 1313775262 673720360 673710080 673720360 673720360 673720360 673720360 673720360 1299280168 3240634445 1906059304 673720360 673720360 3223857192 673720433 1898457165 1903260097 1898457128 1917754958 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673739121 1903241256 1302079528 673720360 673720360 3223857192 673739121 1903260017 1903260017 1903260274 1917734440 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673729905 1908484136 678504488 673720360 673720360 3223857192 678543729 1903259981 673720360 1299280498 1917724712 1296902184 673710080 673720360 673720360 673720360 673720360 673720360 673720360 1908418600 678504488 673720360 673720360 3223857192 1287680369 673720360 673720360 673720360 1922977358 1313679400 673710080 673720360 673720360 673720360 673720360 673720360 673720360 678513704 678504488 673720360 673720360 3223857228 1903241256 673720360 673720360 673720360 676240974 1313679400 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673739084 678504488 673720360 673720433 1898466417 1277700136 673720360 673720360 673720360 673750606 1296902184 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673739163 1282484264 673720360 673720512 676098380 673720360 673720360 673720360 673720360 673730206 1294477352 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673729691 1903241256 673720360 673720512 1903250472 673720360 673720360 673720360 673720360 673720478 1294477352 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720396 1905993768 673720360 673720512 1900816424 673720360 673720360 673720360 673720360 673720398 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1285236776 673720360 673739200 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 678504488 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 678504488 673720360 673759272 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 676098344 673720360 676098344 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673739121 673720360 678504488 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720512 673720360 1282484264 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720433 1898457128 1903241256 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 3223857192 1903241256 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 3223857228 1900816424 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 1903241329 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 683681905 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 683681905 1898457128 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673759345 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673739121 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673738864 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673720360 673710080)\\n\\toffset: 478@345)! !\\nObject subclass: #StarSqueakTurtle\\n\\tinstanceVariableNames: 'world who x y wrapX wrapY headingRadians color penDown nextTurtle'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'StarSqueak-Kernel'!\\n!StarSqueakTurtle commentStamp: '<historical>' prior: 0!\\nI represent a \\\"creature\\\" that can move about on the surface of a StarSqueak world. I have a position and a heading (direction), and respond commands such as \\\"turnRight:\\\" and \\\"forward:\\\" by turning or moving. I also have an imaginary pen that can draw a trail as I move. In StarSqueak, turtles are born with random positions and headings.\\n\\nHere are some expressions to try in a workspace:\\n\\tw _ StarSqueakMorph new openInWorld.\\t\\\"make an empty world\\\"\\n\\tw makeTurtles: 100.\\t\\t\\t\\t\\t\\t\\\"create 100 turtles\\\"\\n\\tw turtlesDo: [:t | t forward: 1].\\t\\t\\t\\\"tell all turtles to take a step\\\"\\n\\tw turtlesDo: [:t | t goto: 50@50].\\t\\t\\t\\\"tell all turtles to go to 50@50\\\"\\n\\tw turtlesDo: [:t | t forward: 10].\\t\\t\\t\\\"tell all turtles to take 10 steps\\\"\\n\\nStructure:\\n world\\t\\t\\t\\tStarSqueakMorph\\t\\tthe world that owns this turtle\\n who\\t\\t\\t\\tinteger\\t\\t\\t\\t\\tunique id\\n x\\t\\t\\t\\t\\tnumber\\t\\t\\t\\t\\tx position in world\\n y\\t\\t\\t\\t\\tnumber\\t\\t\\t\\t\\ty position in world\\n wrapX\\t\\t\\t\\tfloat\\t\\t\\t\\t\\tprivate; used for wrapping in x\\n wrapY\\t\\t\\tfloat\\t\\t\\t\\t\\tprivate; used for wrapping in y\\n headingRadians\\tfloat\\t\\t\\t\\t\\theading in radians\\n color\\t\\t\\t\\tcolor\\t\\t\\t\\t\\tturtle color and its pen color\\n penDown\\t\\t\\tboolean\\t\\t\\t\\t\\ttrue if drawing a pen trail\\n nextTurtle\\t\\t\\tStarSqueaktTurtle\\t\\tprivate; used to make linked list of turtles\\n!\\n\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 1/27/2001 08:59'!\\nasPoint\\n\\n\\t^ x truncated @ y truncated\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:03'!\\ncolor\\n\\n\\t^ color\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ncolor: aColor\\n\\n\\tcolor := aColor.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nheading\\n\\t\\\"Answer my heading in degrees.\\\"\\n\\n\\t| degrees |\\n\\tdegrees := 90.0 - headingRadians radiansToDegrees.\\n\\t^ degrees >= 0.0 ifTrue: [degrees] ifFalse: [degrees + 360.0].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nheading: angleInDegrees\\n\\t\\\"Set my heading in degrees. Like a compass, up or north is 0 degrees and right or east is 90 degrees.\\\"\\n\\n\\theadingRadians := ((90.0 - angleInDegrees) \\\\\\\\ 360.0) degreesToRadians.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 3/3/2001 17:49'!\\nnextTurtle\\n\\t\\\"The nextTurtle slot is used to make a linked list of turtles at a given patch.\\\"\\n\\n\\t^ nextTurtle\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nnextTurtle: aStarSqueakTurtle\\n\\t\\\"The nextTurtle slot is used to make a linked list of turtles at a given patch.\\\"\\n\\n\\tnextTurtle := aStarSqueakTurtle.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 1/26/2001 17:36'!\\nwho\\n\\n\\t^ who\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nwho: anInteger\\n\\n\\twho := anInteger.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:02'!\\nx\\n\\n\\t^ x\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\nx: aNumber\\n\\n\\tx := aNumber.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'jm 2/25/2000 16:02'!\\ny\\n\\n\\t^ y\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'accessing' stamp: 'sd 11/20/2005 21:26'!\\ny: aNumber\\n\\n\\ty := aNumber.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/26/2001 17:39'!\\ndie\\n\\t\\\"Delete this turtle at the end of the current cycle. The turtle will finish running all demons for the current cycle before it dies.\\\"\\n\\n\\tworld deleteTurtle: self.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/23/2001 17:26'!\\nforward: dist\\n\\t\\\"Move the given distance in the direction of my heading.\\\"\\n\\n\\t1 to: dist do: [:i | self forwardOne].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\nforwardOne\\n\\t\\\"Move one turtle step in the direction of my heading.\\\"\\n\\n\\tpenDown ifTrue: [world setPatchColorAtX: x y: y to: color].\\n\\tx := x + headingRadians cos.\\n\\ty := y - headingRadians sin.\\n\\tx < 0.0 ifTrue: [x := x + wrapX].\\n\\ty < 0.0 ifTrue: [y := y + wrapY].\\n\\tx >= wrapX ifTrue: [x := x - wrapX].\\n\\ty >= wrapY ifTrue: [y := y - wrapY].\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\ngoto: aPoint\\n\\t\\\"Jump to the given location.\\\"\\n\\n\\tx := aPoint x.\\n\\ty := aPoint y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\npenDown\\n\\t\\\"Put down this turtle's pen. That is, the turtle will leave a trail the same color as itself when it moves.\\\"\\n\\n\\tpenDown := true.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\npenUp\\n\\t\\\"Lift this turtle's pen. The turtle will stop leaving a trail.\\\"\\n\\n\\tpenDown := false.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/19/2001 19:20'!\\nrandom: range\\n\\t\\\"Answer a random integer between 0 and range.\\\"\\n\\n\\t^ world random: range\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/27/2001 08:47'!\\nreplicate\\n\\t\\\"Add an exact replica of this turtle to the world. The new turtle does not become active until the next cycle.\\\"\\n\\t\\\"Note: We call this operation 'replicate' instead of Mitch Resnick's term 'clone' because Squeak already used the message 'clone' for cloning a generic object.\\\"\\n\\n\\tworld replicateTurtle: self.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/29/2001 10:11'!\\nstop\\n\\t\\\"Stop running.\\\"\\n\\n\\tworld stopRunning.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/19/2001 19:14'!\\nturnLeft: degrees\\n\\t\\\"Turn left by the given number of degrees.\\\"\\n\\n\\tself heading: (self heading - degrees).\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 2/27/2000 18:19'!\\nturnRight: degrees\\n\\t\\\"Turn right by the given number of degrees.\\\"\\n\\n\\tself heading: (self heading + degrees).\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'sd 11/20/2005 21:26'!\\nturnTowards: aPointTurtleOrPatch\\n\\t\\\"Turn to face the given point, turtle, or patch.\\\"\\n\\n\\t| degrees |\\n\\tdegrees := (aPointTurtleOrPatch asPoint - self asPoint) degrees.\\n\\theadingRadians := (0.0 - degrees) degreesToRadians.\\n\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'commands' stamp: 'jm 1/27/2001 08:58'!\\nturnTowardsStrongest: patchVarName\\n\\t\\\"Turn to point toward the nearby patch having the highest value of the given patch variable. This command uses only local information. In particular, it only considers patches within 'sniffRange' of this turtles location. For example, with the default 'sniffRange' of 1, it only considers the immediate neighbors of the patch this turtle is on.\\\"\\n\\n\\tself heading: (world uphillOf: patchVarName forTurtle: self).\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:26'!\\ninitializeWorld: aStarSqueakWorld who: anInteger\\n\\n\\t| dims |\\n\\tdims := aStarSqueakWorld dimensions.\\n\\tworld := aStarSqueakWorld.\\n\\twho := anInteger.\\n\\tx := world random: dims x - 1.\\n\\ty := world random: dims y - 1.\\n\\twrapX := dims x asFloat.\\n\\twrapY := dims y asFloat.\\n\\theadingRadians := ((self random: 36000) / 100.0) degreesToRadians.\\n\\tcolor := Color blue.\\n\\tpenDown := false.\\n\\tnextTurtle := nil.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/19/2001 19:08'!\\nget: patchVar\\n\\t\\\"Answer the value of the given patch variable below this turtle.\\\"\\n\\n\\t^ world getPatchVariable: patchVar atX: x y: y\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/27/2001 08:49'!\\nincrement: patchVar by: delta\\n\\t\\\"Increment the value of the given patch variable below this turtle by the given amount (positive or negative).\\\"\\n\\n\\t world incrementPatchVariable: patchVar atX: x y: y by: delta.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'hh 8/26/2001 19:49'!\\npatchBrightness\\n\\t\\\"Answer the brightness of the patch below this turtle, where 0 is black and 100 is full brightness.\\\"\\n\\n\\t^world getPatchBrightnessAtX: x y: y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/24/2001 13:28'!\\npatchBrightness: percent\\n\\t\\\"Set the brightness of the patch below this turtle to the given value, where 0 is black and 100 is full brightness.\\\"\\n\\n\\tworld setPatchBrightnessAtX: x y: y to: percent.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/23/2001 17:17'!\\npatchColor\\n\\t\\\"Answer the color of the patch below this turtle.\\\"\\n\\n\\t^ world getPatchColorAtX: x y: y.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/24/2001 13:37'!\\npatchColor: aColor\\n\\t\\\"Paint the patch below this turtle with the given color.\\\"\\n\\n\\tworld setPatchColorAtX: x y: y to: aColor.\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'patches' stamp: 'jm 1/19/2001 19:09'!\\nset: patchVar to: newValue\\n\\t\\\"Set the value of the given patch variable below this turtle to the given value.\\\"\\n\\n\\t world setPatchVariable: patchVar atX: x y: y to: newValue.\\n! !\\n\\n\\n!StarSqueakTurtle methodsFor: 'sensing' stamp: 'jm 2/5/2001 19:42'!\\ndistanceTo: aPoint\\n\\t\\\"Answer the distance from this turtle to the given point.\\\"\\n\\n\\t^ ((x - aPoint x) squared + (y - aPoint y) squared) sqrt\\n! !\\n\\n!StarSqueakTurtle methodsFor: 'sensing' stamp: 'sd 11/20/2005 21:26'!\\nturtleCountHere\\n\\t\\\"Answer a collection of turtles at this turtle's current location, including this turtle itself.\\\"\\n\\n\\t| n |\\n\\tn := 0.\\n\\tworld turtlesAtX: x y: y do: [:t | n := n + 1].\\n\\t^ n\\n! !\\nChangeSetCategory subclass: #StaticChangeSetCategory\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Changes'!\\n!StaticChangeSetCategory commentStamp: '<historical>' prior: 0!\\nStaticChangeSetCategory is a user-defined change-set category that has in it only those change sets specifically placed there.!\\n\\n\\n!StaticChangeSetCategory methodsFor: 'add' stamp: 'sw 4/11/2001 15:58'!\\naddChangeSet: aChangeSet\\n\\t\\\"Add the change set manually\\\"\\n\\n\\tself elementAt: aChangeSet name put: aChangeSet! !\\n\\n\\n!StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:10'!\\nacceptsManualAdditions\\n\\t\\\"Answer whether the user is allowed manually to manipulate the contents of the change-set-category.\\\"\\n\\n\\t^ true! !\\n\\n!StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:00'!\\nincludesChangeSet: aChangeSet\\n\\t\\\"Answer whether the receiver includes aChangeSet in its retrieval list\\\"\\n\\n\\t^ elementDictionary includesKey: aChangeSet name! !\\n\\n\\n!StaticChangeSetCategory methodsFor: 'updating' stamp: 'sd 11/20/2005 21:27'!\\nreconstituteList\\n\\t\\\"Reformulate the list. Here, since we have a manually-maintained list, at this juncture we only make sure change-set-names are still up to date, and we purge moribund elements\\\"\\n\\n\\t| survivors |\\n\\tsurvivors := elementDictionary select: [:aChangeSet | aChangeSet isMoribund not].\\n\\tself clear.\\n\\t(survivors asSortedCollection: [:a :b | a name <= b name]) reverseDo:\\n\\t\\t[:aChangeSet | self addChangeSet: aChangeSet]! !\\nForm subclass: #StaticForm\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Graphics-Display Objects'!\\n!StaticForm commentStamp: '<historical>' prior: 0!\\nAn optimization for Nebraska - a StaticForm does not change once created so it may be cached on the remote end.!\\n\\n\\n!StaticForm methodsFor: 'as yet unclassified' stamp: 'RAA 8/14/2000 09:59'!\\nisStatic\\n\\n\\t^true! !\\nMorphicAlarm subclass: #StepMessage\\n\\tinstanceVariableNames: 'stepTime'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Events'!\\n\\n!StepMessage methodsFor: 'accessing' stamp: 'ar 10/22/2000 16:56'!\\nstepTime: aNumber\\n\\t\\\"Set the step time for this message. If nil, the receiver of the message will be asked for its #stepTime.\\\"\\n\\tstepTime _ aNumber! !\\n\\n\\n!StepMessage methodsFor: 'printing' stamp: 'ar 10/22/2000 15:59'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream \\n\\t\\tnextPut: $(;\\n\\t\\tprint: receiver;\\n\\t\\tspace;\\n\\t\\tprint: selector;\\n\\t\\tspace;\\n\\t\\tprint: scheduledTime;\\n\\t\\tnextPut: $).! !\\n\\n\\n!StepMessage methodsFor: 'testing' stamp: 'ar 10/22/2000 16:56'!\\nstepTime\\n\\t\\\"Return the step time for this message. If nil, the receiver of the message will be asked for its #stepTime.\\\"\\n\\t^stepTime! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStepMessage class\\n\\tinstanceVariableNames: ''!\\n\\n!StepMessage class methodsFor: 'instance creation' stamp: 'ar 10/22/2000 15:48'!\\nscheduledAt: scheduledTime stepTime: stepTime receiver: aTarget selector: aSelector arguments: argArray\\n\\t^(self receiver: aTarget selector: aSelector arguments: argArray)\\n\\t\\tscheduledTime: scheduledTime;\\n\\t\\tstepTime: stepTime! !\\nRectangleMorph subclass: #StickyPadMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'Colors LastColorIndex'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Demo'!\\n!StickyPadMorph commentStamp: 'sw 3/3/2004 13:31' prior: 0!\\nA custom item for the Squeakland Supplies bin, as defined by Kim Rose and BJ Con.A parts bin will deliver up translucent, borderless Rectangles in a sequence of 6 colors. It offers some complication to the parts-bin protocols in two ways::\\n* The multi-colored icon seen in the parts bin is not a thumbnail of any actual instance, all of which are monochrome\\n* New instances need to be given default names that are not the same as the name seen in the parts bin.!\\n\\n\\n!StickyPadMorph methodsFor: 'visual properties' stamp: 'dgd 9/18/2004 18:52'!\\ncanHaveFillStyles\\n\\t\\\"Return true if the receiver can have general fill styles; not just \\n\\tcolors. This method is for gradually converting old morphs.\\\"\\n\\t^ true! !\\n\\n\\n!StickyPadMorph methodsFor: 'parts bin' stamp: 'sw 4/3/2003 15:25'!\\ninitializeToStandAlone\\n\\t\\\"Initialize the receiver to stand alone. Use the next color in the standard sequence.\\\"\\n\\n\\tColors ifNil: [self initialize].\\n\\tLastColorIndex _ \\n\\t\\tLastColorIndex\\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[1]\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[(LastColorIndex \\\\\\\\ Colors size) + 1].\\n\\tsuper initializeToStandAlone.\\n\\tself assureExternalName.\\n\\tself color: (Colors at: LastColorIndex).\\n\\tself extent: 100@80.\\n\\tself borderWidth: 0\\n\\t! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStickyPadMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StickyPadMorph class methodsFor: 'as yet unclassified' stamp: 'sw 3/3/2004 13:42'!\\nregisterInFlapsRegistry\\n\\t\\\"Register the receiver in the system's flaps registry\\\"\\n\\t\\n\\tself environment\\n\\t\\tat: #Flaps\\n\\t\\tifPresent: [:cl | cl registerQuad: #(StickyPadMorph\\t\\tnewStandAlone\\t\\t\\t'Sticky Pad'\\t\\t\\t'Each time you obtain one of these pastel, translucent, borderless rectangles, it will be a different color from the previous time.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'Supplies'.\\n\\t\\t\\t\\tcl registerQuad: #(StickyPadMorph\\t\\tnewStandAlone\\t\\t\\t'Sticky Pad'\\t\\t\\t'Each time you obtain one of these pastel, translucent, borderless rectangles, it will be a different color from the previous time.')\\n\\t\\t\\t\\t\\t\\tforFlapNamed: 'PlugIn Supplies'.]! !\\n\\n\\n!StickyPadMorph class methodsFor: 'class initialization' stamp: 'sw 3/3/2004 13:44'!\\ninitialize\\n\\t\\\"Class initialization\\\"\\n\\n\\tLastColorIndex _ 0.\\n\\tColors _ {\\n\\t\\tTranslucentColor r: 0.0 g: 0.0 b: 0.839 alpha: 0.267.\\n\\t\\tTranslucentColor r: 0.484 g: 1.0 b: 0.452 alpha: 0.706.\\n\\t\\tTranslucentColor r: 1.0 g: 0.355 b: 0.71 alpha: 0.569.\\n\\t\\tTranslucentColor r: 1.0 g: 1.0 b: 0.03 alpha: 0.561.\\n\\t\\tTranslucentColor r: 0.484 g: 0.161 b: 1.0 alpha: 0.529.\\n\\t\\tTranslucentColor r: 0.097 g: 0.097 b: 0.097 alpha: 0.192.\\n\\t}.\\n\\t\\n\\tself registerInFlapsRegistry.\\t\\n\\n\\\"StickyPadMorph initialize\\\"! !\\n\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 4/3/2003 14:26'!\\ndefaultNameStemForInstances\\n\\t\\\"Answer the default name stem to use\\\"\\n\\n\\t^ 'tear off'! !\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 4/4/2003 11:12'!\\ndescriptionForPartsBin\\n\\t\\\"Answer a description of the receiver for use in a parts bin\\\"\\n\\n\\t^ self partName: \\t'Sticky Pad'\\n\\t\\tcategories:\\t\\t#('Graphics')\\n\\t\\tdocumentation:\\t'A translucent, borderless rectangle of a standard size, delivered in a predictable sequence of pastel colors'\\n\\t\\tsampleImageForm: (Form extent: 50@40 depth: 16\\n\\tfromArray: #( 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1796762392 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461409563 1461414680 1796762392 1796762392 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1723098804 1723098804 1723098804 1599692633 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1521900214 1521900214 1521900214 1521903284 1723098804 1723098804 1723096921 1599692633 1599692633 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322274512 1389318863 1389318863 1389318863 1328697138 1328697138 1328697138 1662149394 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1322275535 1389318863 1389318863 1389317938 1328697138 1328697138 1328702226 1662149394 1662149394 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521900214 1389318863 1389318863 1389318863 1460426508 1460426508 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1521903284 1389318863 1389318863 1389317938 1460426508 1460426508 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521900214 1723098804 1389318863 1389318863 1328697138 1460426508 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1521903284 1723098804 1389318863 1389317938 1328697138 1460426508 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521900214 1723098804 1723098804 1389318863 1328697138 1328697138 1460426508 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1521903284 1723098804 1723098804 1389317938 1328697138 1328697138 1460429548 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461409563 1723098804 1723098804 1723098804 1328697138 1328697138 1328697138 1659658988 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1461414680 1723098804 1723098804 1723096921 1328697138 1328697138 1328702226 1659658988 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461409563 1796762392 1723098804 1723098804 1599692633 1328697138 1328697138 1662149394 1659658988 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1461414680 1796762392 1723098804 1723096921 1599692633 1328697138 1328702226 1662149394 1659658988 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461409563 1796762392 1796762392 1723098804 1599692633 1599692633 1328697138 1662149394 1662149394 1659658988 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1736271741 1461414680 1796762392 1796762392 1723096921 1599692633 1599692633 1328702226 1662149394 1662149394 1659660157 1736271741 1736271741 1736271741 1736271741 1736271741)\\n\\toffset: 0@0)! !\\n\\n!StickyPadMorph class methodsFor: 'parts bin' stamp: 'sw 7/5/2004 18:09'!\\nlaunchPartVia: aSelector label: aString\\n\\t\\\"Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins. Overridden here so that all instances will be given the name, unlike the prevailing convention for other object types\\\"\\n\\n\\t| aMorph |\\n\\taMorph _ self perform: aSelector.\\n\\taMorph setNameTo: self defaultNameStemForInstances. \\\"i.e., circumvent uniqueness in this case\\\"\\n\\taMorph setProperty: #beFullyVisibleAfterDrop toValue: true.\\n\\taMorph openInHand! !\\nSketchMorph subclass: #StickySketchMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Support'!\\n\\n!StickySketchMorph methodsFor: 'e-toy support' stamp: 'sw 4/16/1998 13:44'!\\nmustBeBackmost\\n\\t^ true! !\\n\\n\\n!StickySketchMorph methodsFor: 'halos and balloon help' stamp: 'sw 9/18/97 15:37'!\\nwantsHalo\\n\\t^ false! !\\n\\n\\n!StickySketchMorph methodsFor: 'thumbnail' stamp: 'sw 6/16/1999 11:32'!\\npermitsThumbnailing\\n\\t^ false! !\\nObject subclass: #Stopwatch\\n\\tinstanceVariableNames: 'timespans state'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Kernel-Chronology'!\\n!Stopwatch commentStamp: '<historical>' prior: 0!\\nA Stopwatch maintains a collection of timespans.!\\n\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:12'!\\nactivate\\n\\n\\tself isSuspended ifTrue:\\n\\t\\t[self timespans add: \\n\\t\\t\\t(Timespan starting: DateAndTime now duration: Duration zero).\\n\\t\\tself state: #active]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:45'!\\nduration\\n\\n\\t| ts last |\\n\\tself isSuspended \\n\\t\\tifTrue:\\n\\t\\t\\t[ (ts _ self timespans) isEmpty ifTrue: \\n\\t\\t\\t\\t[ ts _ { Timespan starting: DateAndTime now duration: Duration zero } ] ]\\n\\t\\tifFalse:\\n\\t\\t\\t[ last _ self timespans last.\\n\\t\\t\\tts _ self timespans allButLast\\n\\t\\t\\t\\tadd: (last duration: (DateAndTime now - last start); yourself);\\n\\t\\t\\t\\tyourself ].\\n\\t\\t\\n\\t^ (ts collect: [ :t | t duration ]) sum\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:21'!\\nend\\n\\n\\t^ self timespans last next\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'!\\nisActive\\n\\n\\t^ self state = #active\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'!\\nisSuspended\\n\\n\\t^ self state = #suspended\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 13:25'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPut: $(;\\n\\t\\tnextPutAll: self state;\\n\\t\\tnextPut: $:;\\n\\t\\tprint: self duration;\\n\\t\\tnextPut: $).\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 12:03'!\\nreActivate\\n\\n\\tself \\n\\t\\tsuspend;\\n\\t\\tactivate.\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:54'!\\nreset\\n\\n\\tself suspend.\\n\\ttimespans _ nil.\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:18'!\\nstart\\n\\n\\t^ self timespans first start\\n\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:47'!\\nstate\\n\\n\\t^ state ifNil: [ state _ #suspended ]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:46'!\\nstate: aSymbol\\n\\n\\tstate _ aSymbol\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:13'!\\nsuspend\\n\\n\\t| ts |\\n\\tself isActive ifTrue:\\n\\t\\t[ ts _ self timespans last.\\n\\t\\tts duration: (DateAndTime now - ts start).\\n\\t\\tself state: #suspended]\\n! !\\n\\n!Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:44'!\\ntimespans\\n\\n\\t^ timespans ifNil: [ timespans _ OrderedCollection new ]\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStopwatch class\\n\\tinstanceVariableNames: ''!\\nClassTestCase subclass: #StopwatchTest\\n\\tinstanceVariableNames: 'aStopwatch aDelay'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'KernelTests-Chronology'!\\n\\n!StopwatchTest methodsFor: 'Coverage' stamp: 'brp 9/24/2003 22:49'!\\nclassToBeTested\\n\\n\\t^ Stopwatch\\n\\n! !\\n\\n!StopwatchTest methodsFor: 'Coverage' stamp: 'brp 9/24/2003 23:01'!\\nselectorsToBeIgnored\\n\\n\\t| private | \\n\\tprivate := #( #printOn: #state: ).\\n\\n\\t^ super selectorsToBeIgnored, private\\n! !\\n\\n\\n!StopwatchTest methodsFor: 'running' stamp: 'brp 1/21/2004 18:49'!\\nsetUp\\n\\taStopwatch := Stopwatch new.\\n\\taDelay := Delay forMilliseconds: 1.! !\\n\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 11:45'!\\ntestActive\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw activate.\\n\\t\\n\\t1 seconds asDelay wait.\\n\\tself \\n\\t\\tassert: (sw duration >= 1 seconds).\\n\\n\\t2 seconds asDelay wait.\\n\\tself \\n\\t\\tassert: (sw duration >= 3 seconds).\\n\\n\\tsw suspend.! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/24/2003 22:56'!\\ntestNew\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\t\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tassert: (sw state = #suspended);\\n\\t\\tdeny: (sw isActive);\\n\\t\\tassert: (sw timespans isEmpty)\\n\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 12:02'!\\ntestReActivate\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw \\n\\t\\tactivate;\\n\\t\\tsuspend;\\n\\t\\treActivate.\\n\\t\\n\\tself \\n\\t\\tassert: (sw isActive).\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/25/2003 11:56'!\\ntestReset\\n\\n\\t| sw |\\n\\tsw _ Stopwatch new.\\n\\tsw activate.\\n\\t\\n\\tsw reset.\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tassert: (sw timespans isEmpty)\\n! !\\n\\n!StopwatchTest methodsFor: 'Tests' stamp: 'brp 9/26/2004 19:36'!\\ntestStartStop\\n\\n\\t| sw t1 t2 t3 t4 |\\n\\tsw := Stopwatch new.\\n\\tt1 := DateAndTime now.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tsw activate; activate.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt2 := DateAndTime now.\\n\\t\\n\\tself \\n\\t\\tdeny: (sw isSuspended);\\n\\t\\tassert: (sw isActive);\\n\\t\\tassert: (sw timespans size = 1);\\n\\t\\tassert: (t1 <= sw start);\\n\\t\\tassert: (sw start <= t2).\\n\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt3 := DateAndTime now.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tsw suspend; suspend.\\n\\t(Delay forMilliseconds: 10) wait.\\n\\tt4 := DateAndTime now.\\n\\n\\tself \\n\\t\\tassert: (sw isSuspended);\\n\\t\\tdeny: (sw isActive);\\n\\t\\tassert: (sw timespans size = 1);\\n\\t\\tassert: (sw end between: t3 and: t4);\\n\\t\\tassert: (t3 <= sw end);\\n\\t\\tassert: (sw end <= t4).\\n! !\\n\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestChangingStatus\\n\\taStopwatch activate.\\n\\tself assert: aStopwatch isActive.\\n\\tself assert: aStopwatch timespans size = 1.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch isSuspended.\\n\\tself assert: aStopwatch timespans size = 1.\\n\\taStopwatch activate.\\n\\taStopwatch reActivate.\\n\\tself assert: aStopwatch isActive.\\n\\tself assert: aStopwatch timespans size = 3.\\n\\taStopwatch reset.\\n\\tself assert: aStopwatch isSuspended.\\n\\tself assert: aStopwatch timespans size = 0.! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestInitialStatus\\n\\tself assert: aStopwatch isSuspended.\\n\\tself deny: aStopwatch isActive.\\n\\tself assert: aStopwatch duration = 0 seconds! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 9/26/2004 19:32'!\\ntestMultipleTimings\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch timespans size = 2. \\n\\tself assert: aStopwatch timespans first asDateAndTime <= \\n\\t\\t\\t\\t\\taStopwatch timespans last asDateAndTime.\\n! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 1/21/2004 18:49'!\\ntestPrintOn\\n\\t| cs rw |\\n\\tcs := ReadStream on: 'a Stopwatch(suspended:0:00:00:00)'.\\n\\trw := ReadWriteStream on: ''.\\n\\taStopwatch printOn: rw.\\n\\tself assert: rw contents = cs contents! !\\n\\n!StopwatchTest methodsFor: 'testing' stamp: 'brp 9/26/2004 19:32'!\\ntestSingleTiming\\n\\t| timeBefore |\\n\\ttimeBefore := DateAndTime now.\\n\\taStopwatch activate.\\n\\taDelay wait.\\n\\taStopwatch suspend.\\n\\tself assert: aStopwatch timespans size = 1. \\n\\tself assert: aStopwatch timespans first asDateAndTime >= timeBefore. \\n\\tself assert: aStopwatch timespans first asDateAndTime <= aStopwatch end.\\n! !\\nPrintableEncoder subclass: #StoreEncoder\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Postscript Filters'!\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStoreEncoder class\\n\\tinstanceVariableNames: ''!\\n\\n!StoreEncoder class methodsFor: 'configuring' stamp: 'MPW 1/1/1901 01:52'!\\nfilterSelector\\n ^#storeOnStream:.\\n! !\\nBookMorph subclass: #StoryboardBookMorph\\n\\tinstanceVariableNames: 'alansSliders panAndTiltFactor zoomFactor zoomController'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Books'!\\n!StoryboardBookMorph commentStamp: '<historical>' prior: 0!\\nA BookMorph variant whose pages are instances of ZoomAndScrollMorph. I have a control area where the user may pan, tilt and zoom over the image shown in the page.\\n\\n- drag up and down to zoom in and out\\n- drag left and right to pan\\n- shift-drag up and down to tilt.!\\n\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:37'!\\nchangeTiltFactor: x\\n\\n\\tcurrentPage changeTiltFactor: x.\\n\\tpanAndTiltFactor _ x.\\n\\n! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:37'!\\nchangeZoomFactor: x\\n\\n\\tcurrentPage changeZoomFactor: x.\\n\\tzoomFactor _ x.! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:38'!\\ngetTiltFactor\\n\\n\\t^panAndTiltFactor ifNil: [panAndTiltFactor _ 0.5].! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/30/2000 16:38'!\\ngetZoomFactor\\n\\n\\t^zoomFactor ifNil: [zoomFactor _ 0.5]! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetX\\n\\n\\t^currentPage offsetX! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetX: aNumber\\n\\n\\tcurrentPage offsetX: aNumber! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetY\\n\\n\\t^currentPage offsetY! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:41'!\\noffsetY: aNumber\\n\\n\\tcurrentPage offsetY: aNumber! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:35'!\\nscale\\n\\n\\t^currentPage scale! !\\n\\n!StoryboardBookMorph methodsFor: 'as yet unclassified' stamp: 'RAA 11/22/2000 08:26'!\\nscale: aValue\\n\\n\\tcurrentPage scale: aValue! !\\n\\n\\n!StoryboardBookMorph methodsFor: 'initialization' stamp: 'RAA 12/1/2000 15:22'!\\ninitialize\\n\\n\\tnewPagePrototype _ ZoomAndScrollMorph new extent: Display extent // 3.\\n\\tzoomController _ ZoomAndScrollControllerMorph new\\n\\t\\t\\tsetBalloonText: 'Drag in here to zoom, tilt and pan the page above'.\\n\\n\\tsuper initialize.\\n\\n\\tself addMorphBack: zoomController.\\n\\n\\talansSliders _ {\\n\\t\\t{#changeTiltFactor: . #getTiltFactor . 'Pan and tilt sensitivity'}.\\n\\t\\t{#changeZoomFactor: . #getZoomFactor . 'Zoom sensitivity'}.\\n\\t} collect: [ :sData |\\n\\t\\t{\\n\\t\\t\\tSimpleSliderMorph new\\n\\t\\t\\t\\textent: 150@10;\\n\\t\\t\\t\\tcolor: Color orange;\\n\\t\\t\\t\\tsliderColor: Color gray;\\n\\t\\t\\t\\ttarget: self; \\n\\t\\t\\t\\tactionSelector: sData first;\\n\\t\\t\\t\\tsetBalloonText: sData third;\\n\\t\\t\\t\\tadjustToValue: (self perform: sData second).\\n\\t\\t\\tsData second\\n\\t\\t}\\n\\t].\\n\\talansSliders do: [ :each | self addMorphBack: each first]\\n! !\\n\\n\\n!StoryboardBookMorph methodsFor: 'navigation' stamp: 'sw 7/25/2003 16:47'!\\ninsertPageMorphInCorrectSpot: aPageMorph\\n\\t\\\"Insert the page morph at the correct spot\\\"\\n\\t\\n\\t| place |\\n\\tplace _ submorphs size > 1 ifTrue: [submorphs second] ifFalse: [submorphs first].\\n\\t\\\"Old architecture had a tiny spacer morph as the second morph; now architecture does not\\\"\\n\\tself addMorph: (currentPage _ aPageMorph) behind: place.\\n\\tself changeTiltFactor: self getTiltFactor.\\n\\tself changeZoomFactor: self getZoomFactor.\\n\\tzoomController target: currentPage.\\n\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStoryboardBookMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StoryboardBookMorph class methodsFor: 'parts bin' stamp: 'sw 8/2/2001 12:53'!\\ndescriptionForPartsBin\\n\\t^ self partName:\\t'Storyboard'\\n\\t\\tcategories:\\t\\t#('Presentation')\\n\\t\\tdocumentation:\\t'A storyboard authoring tool'! !\\nObject subclass: #Stream\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Streams'!\\n!Stream commentStamp: '<historical>' prior: 0!\\nI am an abstract class that represents an accessor for a sequence of objects. This sequence is referred to as my \\\"contents\\\".!\\n\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNext\\n\\n\\t^ self next.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNextPut: anObject \\n\\n\\t^ self nextPut: anObject! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'yo 8/30/2002 17:13'!\\nbasicNextPutAll: aCollection \\n\\n\\t^ self nextPutAll: aCollection.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 2/24/2001 17:31'!\\nbinary! !\\n\\n!Stream methodsFor: 'accessing'!\\ncontents\\n\\t\\\"Answer all of the contents of the receiver.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:07'!\\nflush\\n\\t\\\"Do nothing by default\\\"! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:38'!\\nlocalName\\n\\t^'a stream'! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext\\n\\t\\\"Answer the next object accessible by the receiver.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext: anInteger \\n\\t\\\"Answer the next anInteger number of objects accessible by the receiver.\\\"\\n\\n\\t| aCollection |\\n\\taCollection _ OrderedCollection new.\\n\\tanInteger timesRepeat: [aCollection addLast: self next].\\n\\t^aCollection! !\\n\\n!Stream methodsFor: 'accessing'!\\nnext: anInteger put: anObject \\n\\t\\\"Make anObject be the next anInteger number of objects accessible by the \\n\\treceiver. Answer anObject.\\\"\\n\\n\\tanInteger timesRepeat: [self nextPut: anObject].\\n\\t^anObject! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextMatchAll: aColl\\n \\\"Answer true if next N objects are the ones in aColl,\\n else false. Advance stream of true, leave as was if false.\\\"\\n | save |\\n save _ self position.\\n aColl do: [:each |\\n (self next) = each ifFalse: [\\n self position: save.\\n ^ false]\\n ].\\n ^ true! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextMatchFor: anObject \\n\\t\\\"Gobble the next object and answer whether it is equal to the argument, \\n\\tanObject.\\\"\\n\\n\\t^anObject = self next! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextPut: anObject \\n\\t\\\"Insert the argument, anObject, as the next object accessible by the \\n\\treceiver. Answer anObject.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'accessing'!\\nnextPutAll: aCollection \\n\\t\\\"Append the elements of aCollection to the sequence of objects accessible \\n\\tby the receiver. Answer aCollection.\\\"\\n\\n\\taCollection do: [:v | self nextPut: v].\\n\\t^aCollection! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:40'!\\nopenReadOnly\\n\\t^self! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'ajh 7/31/2001 20:34'!\\nprintOn: stream\\n\\n\\tsuper printOn: stream.\\n\\tstream space.\\n\\tself contents printOn: stream.\\n! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:41'!\\nreadOnly\\n\\t^self! !\\n\\n!Stream methodsFor: 'accessing' stamp: 'ls 9/12/1998 20:55'!\\nupToEnd\\n\\t\\\"answer the remaining elements in the string\\\"\\n\\t| elements |\\n\\telements _ OrderedCollection new.\\n\\t[ self atEnd ] whileFalse: [ \\n\\t\\telements add: self next ].\\n\\t^elements! !\\n\\n\\n!Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:52'!\\ndialect\\n\\n\\t^#ST80\\t\\t\\\"in case a regular stream is used to print parse nodes\\\"! !\\n\\n!Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:54'!\\nwithStyleFor: elementType do: aBlock\\n\\n\\t^aBlock value\\t\\t\\\"in case a regular stream is used to print parse nodes\\\"\\n\\\">>\\n(Compiler new compile: 'blah ^self' in: String notifying: nil ifFail: []) printString\\n<<\\\"! !\\n\\n\\n!Stream methodsFor: 'as yet unclassified' stamp: 'RAA 9/11/2000 19:12'!\\nsleep\\n\\n\\t\\\"an FTP-based stream might close the connection here\\\"! !\\n\\n\\n!Stream methodsFor: 'enumerating'!\\ndo: aBlock \\n\\t\\\"Evaluate aBlock for each of the objects accessible by receiver.\\\"\\n\\n\\t[self atEnd]\\n\\t\\twhileFalse: [aBlock value: self next]! !\\n\\n\\n!Stream methodsFor: 'file open/close' stamp: 'mir 8/10/1999 12:04'!\\nclose! !\\n\\n\\n!Stream methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:48'!\\nwrite:encodedObject\\n\\t^encodedObject putOn:self.\\n! !\\n\\n\\n!Stream methodsFor: 'printing' stamp: 'sma 6/1/2000 09:56'!\\nprint: anObject\\n\\t\\\"Have anObject print itself on the receiver.\\\"\\n\\n\\tanObject printOn: self! !\\n\\n!Stream methodsFor: 'printing' stamp: 'djp 7/21/1998 17:13'!\\nprintHtml: anObject\\n\\tanObject printHtmlOn: self! !\\n\\n\\n!Stream methodsFor: 'testing'!\\natEnd\\n\\t\\\"Answer whether the receiver can access any more objects.\\\"\\n\\n\\tself subclassResponsibility! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ab 8/28/2003 18:30'!\\nclosed\\n\\t^ false! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'!\\nisStream\\n\\t\\\"Return true if the receiver responds to the stream protocol\\\"\\n\\t^true! !\\n\\n!Stream methodsFor: 'testing' stamp: 'mir 11/10/2003 18:22'!\\nisTypeHTTP\\n\\n\\t^false! !\\n\\n!Stream methodsFor: 'testing' stamp: 'ar 5/17/2001 19:07'!\\nnextWordsPutAll: aCollection\\n\\t\\\"Write the argument a word-like object in big endian format on the receiver.\\n\\tMay be used to write other than plain word-like objects (such as ColorArray).\\\"\\n\\taCollection class isPointers | aCollection class isWords not \\n\\t\\tifTrue: [^self error: aCollection class name,' is not word-like'].\\n\\t1 to: aCollection basicSize do:[:i|\\n\\t\\tself nextNumber: 4 put: (aCollection basicAt: i).\\n\\t].\\n\\t^aCollection! !\\n\\n\\n!Stream methodsFor: '*monticello' stamp: 'cwp 8/9/2003 12:02'!\\nisMessageStream\\n\\t^ false! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStream class\\n\\tinstanceVariableNames: ''!\\n\\n!Stream class methodsFor: 'instance creation'!\\nnew\\n\\n\\tself error: 'Streams are created with on: and with:'! !\\nTestCase subclass: #StreamBugz\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tests-Bugs'!\\n\\n!StreamBugz methodsFor: 'as yet unclassified' stamp: 'ar 8/5/2003 02:25'!\\ntestReadWriteStreamNextNBug\\n\\t| aStream |\\n\\taStream := ReadWriteStream on: String new.\\n\\taStream nextPutAll: 'Hello World'.\\n\\tself shouldnt:[aStream next: 5] raise: Error.\\n! !\\nAbstractSound subclass: #StreamingMP3Sound\\n\\tinstanceVariableNames: 'volume repeat mpegFile mpegStreamIndex totalSamples streamSamplingRate mixer lastBufferMSecs mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Movies-Kernel'!\\n!StreamingMP3Sound commentStamp: '<historical>' prior: 0!\\nI implement a streaming player for MPEG or MP3 files.\\nExample of use:\\n\\t(StreamingMP3Sound onFileNamed: 'song.mp3') play.\\n!\\n\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:16'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t^ totalSamples asFloat / streamSamplingRate\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nrepeat\\n\\t\\\"Answer the repeat flag.\\\"\\n\\n\\trepeat ifNil: [repeat := false].\\n\\t^ repeat\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nrepeat: aBoolean\\n\\t\\\"Set the repeat flag. If true, this sound will loop back to the beginning when it gets to the end.\\\"\\n\\n\\trepeat := aBoolean.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 16:18'!\\nsoundPosition\\n\\t\\\"Answer the relative position of sound playback as a number between 0.0 and 1.0.\\\"\\n\\n\\tself mpegFileIsOpen ifFalse: [^ 0.0].\\n\\tmpegFile hasAudio ifFalse: [^ 0.0].\\n\\t^ (mpegFile audioGetSample: 0) asFloat / totalSamples\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsoundPosition: fraction\\n\\t\\\"Jump to the position the given fraction through the sound file. The argument is a number between 0.0 and 1.0.\\\"\\n\\n\\t| sampleIndex |\\n\\tself mpegFileIsOpen ifFalse: [^ self].\\n\\tmpegFile hasAudio ifTrue: [\\n\\t\\tsampleIndex := ((totalSamples * fraction) truncated max: 0) min: totalSamples.\\n\\t\\tmpegFile audioSetSample: 0 stream: 0. \\\"work around for library bug: first seek to zero\\\"\\n\\t\\tmpegFile audioSetSample: sampleIndex stream: 0].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 11/16/2001 15:34'!\\nstreamSamplingRate\\n\\t\\\"Answer the sampling rate of the MP3 stream.\\\"\\n\\n\\t^ streamSamplingRate\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'jm 9/26/2000 07:49'!\\nvolume\\n\\t\\\"Answer my volume.\\\"\\n\\n\\t^ volume\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nvolume: aNumber\\n\\t\\\"Set my volume to the given number between 0.0 and 1.0.\\\"\\n\\n\\tvolume := aNumber.\\n\\tself createMixer.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsaveAsFileNamed: newFileName compressionType: compressionTypeString\\n\\t\\\"Store this MP3 sound in a SunAudio file with the given name using the given compression type.\\\"\\n\\n\\t| outFile |\\n\\toutFile := (FileStream newFileNamed: newFileName) binary.\\n\\tself storeSunAudioOn: outFile compressionType: compressionTypeString.\\n\\toutFile close.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nstoreSunAudioOn: aBinaryStream compressionType: compressionName\\n\\t\\\"Store myself on the given stream as a monophonic sound compressed with the given type of compression. The sampling rate is reduced to 22050 samples/second if it is higher.\\\"\\n\\n\\t| fmt inBufSize samplesPerFrame codec inBuf compressed outSamplingRate audioWriter samplesRemaining outBuf counts byteCount |\\n\\tself pause; reset. \\\"stop playing and return to beginning\\\"\\n\\n\\tfmt := SunAudioFileWriter formatCodeForCompressionType: compressionName.\\n\\tinBufSize := 64000.\\n\\tsamplesPerFrame := 1.\\n\\tcodec := SunAudioFileWriter codecForFormatCode: fmt.\\n\\tcodec ifNotNil: [\\n\\t\\tsamplesPerFrame := codec samplesPerFrame.\\n\\t\\tinBufSize := inBufSize roundUpTo: (2 * samplesPerFrame).\\n\\t\\tcompressed := ByteArray new:\\n\\t\\t\\t(inBufSize // samplesPerFrame) * codec bytesPerEncodedFrame].\\n\\tinBuf := SoundBuffer newMonoSampleCount: inBufSize.\\n\\toutSamplingRate := streamSamplingRate.\\n\\tstreamSamplingRate > 22050 ifTrue: [\\n\\t\\tstreamSamplingRate = 44100 ifFalse: [self error: 'unexpected MP3 sampling rate'].\\n\\t\\toutSamplingRate := 22050].\\n\\n\\t\\\"write audio header\\\"\\n\\taudioWriter := SunAudioFileWriter onStream: aBinaryStream.\\n\\taudioWriter writeHeaderSamplingRate: outSamplingRate format: fmt.\\n\\n\\t\\\"convert and write sound data\\\"\\n\\t'Storing audio...' displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: totalSamples during: [:bar |\\n\\t\\t\\tsamplesRemaining := totalSamples.\\n\\t\\t\\t[samplesRemaining > 0] whileTrue: [\\n\\t\\t\\t\\tbar value: totalSamples - samplesRemaining.\\n\\t\\t\\t\\tsamplesRemaining < inBuf monoSampleCount ifTrue: [\\n\\t\\t\\t\\t\\tinBuf := SoundBuffer newMonoSampleCount:\\n\\t\\t\\t\\t\\t\\t(samplesRemaining roundUpTo: 2 * samplesPerFrame)].\\n\\t\\t\\t\\tmpegFile audioReadBuffer: inBuf stream: 0 channel: 0.\\n\\t\\t\\t\\toutSamplingRate < streamSamplingRate\\n\\t\\t\\t\\t\\tifTrue: [outBuf := inBuf downSampledLowPassFiltering: true]\\n\\t\\t\\t\\t\\tifFalse: [outBuf := inBuf].\\n\\t\\t\\t\\tcodec\\n\\t\\t\\t\\t\\tifNil: [audioWriter appendSamples: outBuf]\\n\\t\\t\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\t\\t\\tcounts := codec\\n\\t\\t\\t\\t\\t\\t\\tencodeFrames: (outBuf size // samplesPerFrame)\\n\\t\\t\\t\\t\\t\\t\\tfrom: outBuf at: 1\\n\\t\\t\\t\\t\\t\\t\\tinto: compressed at: 1.\\n\\t\\t\\t\\t\\t\\tbyteCount := counts last.\\n\\t\\t\\t\\t\\t\\tbyteCount = compressed size\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [audioWriter appendBytes: compressed]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [audioWriter appendBytes: (compressed copyFrom: 1 to: byteCount)]].\\n\\t\\t\\t\\tsamplesRemaining := samplesRemaining - inBuf monoSampleCount]].\\n\\n\\t\\\"update audio header\\\"\\n\\taudioWriter updateHeaderDataSize.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'file ops' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncloseFile\\n\\t\\\"Close the MP3 or MPEG file.\\\"\\n\\n\\tself pause.\\n\\tmpegFile ifNil: [^ self].\\n\\tmpegFile closeFile.\\n\\tmpegFile := nil.\\n\\tmixer := nil.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'file ops' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmpegFileIsOpen\\n\\t\\\"Answer true if I have an open, valid MPEG file handle. If the handle is not valid, try to re-open the file.\\\"\\n\\n\\tmpegFile ifNil: [^ false].\\n\\tmpegFile fileHandle ifNil: [\\n\\t\\t\\\"try to reopen the file, which may have been saved in a snapshot\\\"\\n\\t\\tmpegFile openFile: mpegFile fileName.\\n\\t\\tmpegFile fileHandle ifNil: [mpegFile := nil]].\\n\\t^ mpegFile notNil\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ninitMPEGFile: anMPEGFile streamIndex: anInteger\\n\\t\\\"Initialize for playing the given stream of the given MPEG or MP3 file.\\\"\\n\\n\\tvolume := 0.3.\\n\\trepeat := false.\\n\\tmpegFile := anMPEGFile.\\n\\tmpegStreamIndex := anInteger.\\n\\ttotalSamples := mpegFile audioSamples: mpegStreamIndex.\\n\\tself reset.\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nmillisecondsSinceStart\\n\\t\\\"Answer the number of milliseconds since this sound started playing.\\\"\\n\\n\\t| i mSecs |\\n\\tmpegFile ifNil: [^ 0].\\n\\tmpegFile fileHandle ifNil: [^ 0]. \\\"mpeg file not open\\\"\\n\\ti := mpegFile audioGetSample: mpegStreamIndex.\\n\\ti < 0 ifTrue: [^ 0]. \\\"movie file has no audio\\\"\\n\\tmSecs := i * 1000 // streamSamplingRate.\\n\\t(self isPlaying and: [lastBufferMSecs > 0]) ifTrue: [\\n\\t\\t\\\"adjust mSecs by the milliseconds since the last buffer\\\"\\n\\t\\tmutex critical: [\\n\\t\\t\\tmSecs := i * 1000 // streamSamplingRate.\\n\\t\\t\\tmSecs := mSecs + ((Time millisecondClockValue - lastBufferMSecs) max: 0)]].\\n\\t^ mSecs + 350 - (2 * SoundPlayer bufferMSecs)\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"Mix the next n samples of this sound into the given buffer starting at the given index\\\"\\n\\n\\t| current |\\n\\tself repeat ifTrue: [ \\\"loop if necessary\\\"\\n\\t\\tcurrent := mpegFile audioGetSample: mpegStreamIndex.\\n\\t\\t(totalSamples - current) < n ifTrue: [\\n\\t\\t\\tmpegFile audioSetSample: 0 stream: mpegStreamIndex]].\\n\\n\\tmutex critical: [\\n\\t\\tlastBufferMSecs := Time millisecondClockValue.\\n\\t\\tself loadBuffersForSampleCount: (n * streamSamplingRate) // SoundPlayer samplingRate.\\n\\t\\tmixer playSampleCount: n into: aSoundBuffer startingAt: startIndex].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nreset\\n\\n\\tsuper reset.\\n\\tself createMixer.\\n\\tmpegFile audioSetSample: 0 stream: mpegStreamIndex.\\n\\tlastBufferMSecs := 0.\\n\\tmutex := Semaphore forMutualExclusion.\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nsamplesRemaining\\n\\n\\t| samplesPlayed |\\n\\tmpegFile ifNil: [^ 0].\\n\\tself repeat ifTrue: [^ 1000000].\\n\\tsamplesPlayed := mpegFile audioGetSample: mpegStreamIndex.\\n\\tsamplesPlayed > totalSamples ifTrue: [^ 0].\\n\\t^ totalSamples - samplesPlayed\\n! !\\n\\n\\n!StreamingMP3Sound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\ncreateMixer\\n\\t\\\"Create a mixed sound consisting of sampled sounds with one sound buffer's worth of samples. The sound has the same sampling rate and number of channels as the MPEG or MP3 file.\\\"\\n\\n\\t| channels pan snd |\\n\\tmpegFile ifNil: [^ self error: 'No MPEG or MP3 file'].\\n\\tchannels := mpegFile audioChannels: mpegStreamIndex.\\n\\tstreamSamplingRate := mpegFile audioSampleRate: mpegStreamIndex.\\n\\tmixer := MixedSound new.\\n\\t1 to: channels do: [:c |\\n\\t\\tchannels = 1\\n\\t\\t\\tifTrue: [pan := 0.5]\\n\\t\\t\\tifFalse: [pan := (c - 1) asFloat / (channels - 1)].\\n\\t\\tsnd := SampledSound\\n\\t\\t\\tsamples: (SoundBuffer newMonoSampleCount: 2) \\\"buffer size will be adjusted dynamically\\\"\\n\\t\\t\\tsamplingRate: streamSamplingRate.\\n\\t\\tmixer add: snd pan: pan volume: volume].\\n! !\\n\\n!StreamingMP3Sound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nloadBuffersForSampleCount: count\\n \\\"Load the sound buffers for all tracks with the next count\\nsamples from the MPEG\\nfile sound track.\\\"\\n\\n | snd buf |\\n 1 to: mixer sounds size do: [:i |\\n snd := mixer sounds at: i.\\n buf := snd samples.\\n buf monoSampleCount = count ifFalse: [\\n buf := SoundBuffer newMonoSampleCount: count.\\n snd setSamples: buf samplingRate:\\nstreamSamplingRate].\\n i = 1 ifTrue: [ \\\"first channel\\\"\\n mpegFile\\n audioReadBuffer: buf\\n stream: mpegStreamIndex\\n channel: 0]\\n ifFalse: [ \\\"all other channels\\\"\\n mpegFile\\n audioReReadBuffer: buf\\n stream: mpegStreamIndex\\n channel: 1]].\\n mixer reset.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStreamingMP3Sound class\\n\\tinstanceVariableNames: ''!\\n\\n!StreamingMP3Sound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:48'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me for playing the sound track of the MPEG or MP3 file with the given name. Answer nil the file is not a valid MPEG or MP3 file.\\\"\\n\\n\\t| mpegFile |\\n\\t(MPEGFile isFileValidMPEG: fileName) ifFalse: [^ nil].\\n\\tmpegFile := MPEGFile openFile: fileName.\\n\\t^ self new initMPEGFile: mpegFile streamIndex: 0 \\\"assume sound track is in stream 0\\\"\\n! !\\nAbstractSound subclass: #StreamingMonoSound\\n\\tinstanceVariableNames: 'stream volume repeat headerStart audioDataStart streamSamplingRate totalSamples codec mixer leftoverSamples lastBufferMSecs mutex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!StreamingMonoSound commentStamp: '<historical>' prior: 0!\\nI implement a streaming player for monophonic Sun (.au) and AIFF (.aif) audio files.\\nExample of use:\\n\\t(StreamingMonoSound onFileNamed: 'song.aif') play.\\n!\\n\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:12'!\\nduration\\n\\t\\\"Answer the duration of this sound in seconds.\\\"\\n\\n\\t^ totalSamples asFloat / streamSamplingRate\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 10/18/2001 15:46'!\\nrepeat\\n\\t\\\"Answer the repeat flag.\\\"\\n\\n\\t^ repeat\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nrepeat: aBoolean\\n\\t\\\"Set the repeat flag. If true, this sound will loop back to the beginning when it gets to the end.\\\"\\n\\n\\trepeat := aBoolean.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/16/2001 17:05'!\\nsoundPosition\\n\\t\\\"Answer the relative position of sound playback as a number between 0.0 and 1.0.\\\"\\n\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0.0].\\n\\t^ self currentSampleIndex asFloat / totalSamples\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsoundPosition: fraction\\n\\t\\\"Jump to the position the given fraction through the sound file. The argument is a number between 0.0 and 1.0.\\\"\\n\\n\\t| desiredSampleIndex |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ self].\\n\\tdesiredSampleIndex := ((totalSamples * fraction) truncated max: 0) min: totalSamples.\\n\\tcodec\\n\\t\\tifNil: [stream position: audioDataStart + (desiredSampleIndex * 2)]\\n\\t\\tifNotNil: [self positionCodecTo: desiredSampleIndex].\\n\\tleftoverSamples := SoundBuffer new.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 11/20/2001 16:59'!\\nstreamSamplingRate\\n\\t\\\"Answer the sampling rate of the MP3 stream.\\\"\\n\\n\\t^ streamSamplingRate\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'jm 9/26/2000 07:49'!\\nvolume\\n\\t\\\"Answer my volume.\\\"\\n\\n\\t^ volume\\n! !\\n\\n!StreamingMonoSound methodsFor: 'accessing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nvolume: aNumber\\n\\t\\\"Set my volume to the given number between 0.0 and 1.0.\\\"\\n\\n\\tvolume := aNumber.\\n\\tself createMixer.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsaveAsFileNamed: newFileName compressionType: compressionTypeString\\n\\t\\\"Store this sound in a new file with the given name using the given compression type. Useful for converting between compression formats.\\\"\\n\\n\\t| outFile |\\n\\toutFile := (FileStream newFileNamed: newFileName) binary.\\n\\tself storeSunAudioOn: outFile compressionType: compressionTypeString.\\n\\toutFile close.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'converting' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreSunAudioOn: aBinaryStream compressionType: compressionName\\n\\t\\\"Store myself on the given stream as a monophonic sound compressed with the given type of compression. The sampling rate is reduced to 22050 samples/second if it is higher.\\\"\\n\\n\\t| fmt inBufSize samplesPerFrame outCodec compressed outSamplingRate audioWriter samplesRemaining inBuf outBuf counts byteCount |\\n\\tself pause; reset. \\\"stop playing and return to beginning\\\"\\n\\n\\tfmt := SunAudioFileWriter formatCodeForCompressionType: compressionName.\\n\\tinBufSize := 64000.\\n\\tsamplesPerFrame := 1.\\n\\toutCodec := SunAudioFileWriter codecForFormatCode: fmt.\\n\\toutCodec ifNotNil: [\\n\\t\\tsamplesPerFrame := outCodec samplesPerFrame.\\n\\t\\tinBufSize := inBufSize roundUpTo: (2 * samplesPerFrame).\\n\\t\\tcompressed := ByteArray new:\\n\\t\\t\\t(inBufSize // samplesPerFrame) * outCodec bytesPerEncodedFrame].\\n\\toutSamplingRate := streamSamplingRate.\\n\\tstreamSamplingRate > 22050 ifTrue: [\\n\\t\\tstreamSamplingRate = 44100 ifFalse: [self error: 'unexpected MP3 sampling rate'].\\n\\t\\toutSamplingRate := 22050].\\n\\n\\t\\\"write audio header\\\"\\n\\taudioWriter := SunAudioFileWriter onStream: aBinaryStream.\\n\\taudioWriter writeHeaderSamplingRate: outSamplingRate format: fmt.\\n\\n\\t\\\"convert and write sound data\\\"\\n\\t'Storing audio...' displayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: totalSamples during: [:bar |\\n\\t\\t\\tsamplesRemaining := totalSamples.\\n\\t\\t\\t[samplesRemaining > 0] whileTrue: [\\n\\t\\t\\t\\tbar value: totalSamples - samplesRemaining.\\n\\t\\t\\t\\tself loadBuffersForSampleCount: (inBufSize min: samplesRemaining).\\n\\t\\t\\t\\tinBuf := mixer sounds first samples.\\n\\t\\t\\t\\toutSamplingRate < streamSamplingRate\\n\\t\\t\\t\\t\\tifTrue: [outBuf := inBuf downSampledLowPassFiltering: true]\\n\\t\\t\\t\\t\\tifFalse: [outBuf := inBuf].\\n\\t\\t\\t\\toutCodec\\n\\t\\t\\t\\t\\tifNil: [audioWriter appendSamples: outBuf]\\n\\t\\t\\t\\t\\tifNotNil: [\\n\\t\\t\\t\\t\\t\\tcounts := outCodec\\n\\t\\t\\t\\t\\t\\t\\tencodeFrames: (outBuf size // samplesPerFrame)\\n\\t\\t\\t\\t\\t\\t\\tfrom: outBuf at: 1\\n\\t\\t\\t\\t\\t\\t\\tinto: compressed at: 1.\\n\\t\\t\\t\\t\\t\\tbyteCount := counts last.\\n\\t\\t\\t\\t\\t\\tbyteCount = compressed size\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [audioWriter appendBytes: compressed]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [audioWriter appendBytes: (compressed copyFrom: 1 to: byteCount)]].\\n\\t\\t\\t\\tsamplesRemaining := samplesRemaining - inBuf monoSampleCount]].\\n\\n\\t\\\"update audio header\\\"\\n\\taudioWriter updateHeaderDataSize.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ninitStream: aStream headerStart: anInteger\\n\\t\\\"Initialize for streaming from the given stream. The audio file header starts at the given stream position.\\\"\\n\\n\\tstream := aStream.\\n\\tvolume := 1.0.\\n\\trepeat := false.\\n\\theaderStart := anInteger.\\n\\tself reset.\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncloseFile\\n\\t\\\"Close my stream, if it responds to close.\\\"\\n\\n\\tstream ifNotNil: [\\n\\t\\t(stream respondsTo: #close) ifTrue: [stream close]].\\n\\tmixer := nil.\\n\\tcodec := nil.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nextractFrom: startSecs to: endSecs\\n\\t\\\"Extract a portion of this sound between the given start and end times. The current implementation only works if the sound is uncompressed.\\\"\\n\\n\\t| emptySound first last sampleCount byteStream sndBuf |\\n\\tcodec ifNotNil: [^ self error: 'only works on uncompressed sounds'].\\n\\temptySound := SampledSound samples: SoundBuffer new samplingRate: streamSamplingRate.\\n\\tfirst := (startSecs * streamSamplingRate) truncated max: 0.\\n\\tlast := ((endSecs * streamSamplingRate) truncated min: totalSamples) - 1.\\n\\tfirst >= last ifTrue: [^ emptySound].\\n\\tcodec ifNotNil: [self error: 'extracting from compressed sounds is not supported'].\\n\\tsampleCount := last + 1 - first.\\n\\tstream position: audioDataStart + (2 * first).\\n\\tbyteStream := ReadStream on: (stream next: 2 * sampleCount).\\n\\tsndBuf := SoundBuffer newMonoSampleCount: sampleCount.\\n\\t1 to: sampleCount do: [:i | sndBuf at: i put: byteStream int16].\\n\\t^ SampledSound samples: sndBuf samplingRate: streamSamplingRate\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nmillisecondsSinceStart\\n\\t\\\"Answer the number of milliseconds of this sound started playing.\\\"\\n\\n\\t| mSecs |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0].\\n\\tmSecs := self currentSampleIndex * 1000 // streamSamplingRate.\\n\\t(self isPlaying and: [lastBufferMSecs > 0]) ifTrue: [\\n\\t\\t\\\"adjust mSecs by the milliseconds since the last buffer\\\"\\n\\t\\tmutex critical: [\\n\\t\\t\\tmSecs := self currentSampleIndex * 1000 // streamSamplingRate.\\n\\t\\t\\tmSecs := mSecs + ((Time millisecondClockValue - lastBufferMSecs) max: 0)]].\\n\\t^ mSecs + 350 - (2 * SoundPlayer bufferMSecs)\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nplaySampleCount: n into: aSoundBuffer startingAt: startIndex\\n\\t\\\"Mix the next n samples of this sound into the given buffer starting at the given index\\\"\\n\\n\\tself repeat ifTrue: [ \\\"loop if necessary\\\"\\n\\t\\t(totalSamples - self currentSampleIndex) < n ifTrue: [self startOver]].\\n\\n\\tmutex critical: [\\n\\t\\tlastBufferMSecs := Time millisecondClockValue.\\n\\t\\tself loadBuffersForSampleCount: (n * streamSamplingRate) // SoundPlayer samplingRate.\\n\\t\\tmixer playSampleCount: n into: aSoundBuffer startingAt: startIndex].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'jm 10/21/2001 09:45'!\\nreset\\n\\n\\tsuper reset.\\n\\tself startOver.\\n\\tself createMixer.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'playing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsamplesRemaining\\n\\t\\\"Answer the number of samples remaining to be played.\\\"\\n\\n\\t| result |\\n\\t(stream isNil or: [stream closed]) ifTrue: [^ 0].\\n\\tself repeat ifTrue: [^ 1000000].\\n\\tresult := (totalSamples - self currentSampleIndex) max: 0.\\n\\tresult <= 0 ifTrue: [self closeFile].\\n\\t^ result\\n! !\\n\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncreateMixer\\n\\t\\\"Create a mixed sound consisting of sampled sounds with one sound buffer's worth of samples.\\\"\\n\\n\\t| snd |\\n\\tmixer := MixedSound new.\\n\\tsnd := SampledSound\\n\\t\\tsamples: (SoundBuffer newMonoSampleCount: 2) \\\"buffer size will be adjusted dynamically\\\"\\n\\t\\tsamplingRate: streamSamplingRate.\\n\\tmixer add: snd pan: 0.5 volume: volume.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\ncurrentSampleIndex\\n\\t\\\"Answer the index of the current sample.\\\"\\n\\n\\t| bytePosition frameIndex |\\n\\tbytePosition := stream position - audioDataStart.\\n\\tcodec\\n\\t\\tifNil: [^ bytePosition // 2]\\n\\t\\tifNotNil: [\\n\\t\\t\\tframeIndex := bytePosition // codec bytesPerEncodedFrame.\\n\\t\\t\\t^ (frameIndex * codec samplesPerFrame) - leftoverSamples monoSampleCount].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadBuffer: aSoundBuffer compressedSampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the compressed sample stream.\\\"\\n\\t\\\"Details: Most codecs decode in multi-sample units called 'frames'. Since the requested sampleCount is typically not an even multiple of the frame size, we need to deal with partial frames. The unused samples from a partial frame are retained until the next call to this method.\\\"\\n\\n\\t| n samplesNeeded frameCount encodedBytes r decodedCount buf j |\\n\\t\\\"first, use any leftover samples\\\"\\n\\tn := self loadFromLeftovers: aSoundBuffer sampleCount: sampleCount.\\n\\tsamplesNeeded := sampleCount - n.\\n\\tsamplesNeeded <= 0 ifTrue: [^ self].\\n\\n\\t\\\"decode an integral number of full compression frames\\\"\\n\\tframeCount := samplesNeeded // codec samplesPerFrame.\\n\\tencodedBytes := stream next: (frameCount * codec bytesPerEncodedFrame).\\n\\tr := codec decodeFrames: frameCount from: encodedBytes at: 1 into: aSoundBuffer at: n + 1.\\n\\tdecodedCount := r last.\\n\\tdecodedCount >= samplesNeeded ifTrue: [^ self].\\n\\n\\t\\\"decode one last compression frame to finish filling the buffer\\\"\\n\\tbuf := SoundBuffer newMonoSampleCount: codec samplesPerFrame.\\n\\tencodedBytes := stream next: codec bytesPerEncodedFrame.\\n\\tcodec decodeFrames: 1 from: encodedBytes at: 1 into: buf at: 1.\\n\\tj := 0.\\n\\t(n + decodedCount + 1) to: sampleCount do: [:i |\\n\\t\\taSoundBuffer at: i put: (buf at: (j := j + 1))].\\n\\n\\t\\\"save the leftover samples\\\"\\n\\tleftoverSamples := buf copyFrom: (j + 1) to: buf monoSampleCount.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'jm 11/21/2001 08:03'!\\nloadBuffer: aSoundBuffer uncompressedSampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the uncompressed sample stream.\\\"\\n\\n\\t\\\"read directly into the sample buffer; count is in 32-bit words\\\"\\n\\tstream next: sampleCount // 2 into: aSoundBuffer startingAt: 1.\\n\\taSoundBuffer restoreEndianness.\\n\\n\\t\\\"read the final sample if sampleCount is odd:\\\"\\n\\tsampleCount odd ifTrue: [aSoundBuffer at: sampleCount put: stream int16].\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadBuffersForSampleCount: count\\n\\t\\\"Load the sound buffers from the stream.\\\"\\n\\n\\t| snd buf sampleCount |\\n\\tsnd := mixer sounds first.\\n\\tbuf := snd samples.\\n\\tbuf monoSampleCount = count ifFalse: [\\n\\t\\tbuf := SoundBuffer newMonoSampleCount: count.\\n\\t\\tsnd setSamples: buf samplingRate: streamSamplingRate].\\n\\tsampleCount := count min: (totalSamples - self currentSampleIndex).\\n\\tsampleCount < count ifTrue: [buf primFill: 0].\\n\\n\\tcodec\\n\\t\\tifNil: [self loadBuffer: buf uncompressedSampleCount: sampleCount]\\n\\t\\tifNotNil: [self loadBuffer: buf compressedSampleCount: sampleCount].\\n\\n\\tmixer reset.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nloadFromLeftovers: aSoundBuffer sampleCount: sampleCount\\n\\t\\\"Load the given sound buffer from the samples leftover from the last frame. Answer the number of samples loaded, which typically is less than sampleCount.\\\"\\n\\n\\t| leftoverCount n |\\n\\tleftoverCount := leftoverSamples monoSampleCount.\\n\\tleftoverCount = 0 ifTrue: [^ 0].\\n\\n\\tn := leftoverCount min: sampleCount.\\n\\t1 to: n do: [:i | aSoundBuffer at: i put: (leftoverSamples at: i)].\\n\\tn < sampleCount\\n\\t\\tifTrue: [leftoverSamples := SoundBuffer new]\\n\\t\\tifFalse: [leftoverSamples := leftoverSamples copyFrom: n + 1 to: leftoverSamples size].\\n\\t^ n\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\npositionCodecTo: desiredSampleIndex\\n\\t\\\"Position to the closest frame before the given sample index when using a codec. If using the ADPCM codec, try to ensure that it is in sync with the compressed sample stream.\\\"\\n\\n\\t| desiredFrameIndex desiredPosition tmpStream tmpCodec byteBuf bufFrames sampleBuf frameCount n startOffset |\\n\\t(codec isKindOf: ADPCMCodec) ifFalse: [\\n\\t\\t\\\"stateless codecs (or relatively stateless ones, like GSM: just jump to frame boundary\\\"\\n\\t\\tdesiredFrameIndex := desiredSampleIndex // codec samplesPerFrame.\\n\\t\\tstream position: audioDataStart + (desiredFrameIndex * codec bytesPerEncodedFrame).\\n\\t\\tcodec reset.\\n\\t\\t^ self].\\n\\n\\t\\\"compute the desired stream position\\\"\\n\\tdesiredFrameIndex := desiredSampleIndex // codec samplesPerFrame.\\n\\tdesiredPosition := audioDataStart + (desiredFrameIndex * codec bytesPerEncodedFrame).\\n\\n\\t\\\"copy stream and codec\\\"\\n\\t(stream isKindOf: FileStream)\\n\\t\\tifTrue: [tmpStream := (FileStream readOnlyFileNamed: stream name) binary]\\n\\t\\tifFalse: [tmpStream := stream deepCopy].\\n\\ttmpCodec := codec copy reset.\\n\\n\\t\\\"reset the codec and start back about 30 seconds to try to get codec in sync\\\"\\n\\tstartOffset := ((desiredFrameIndex - 80000) max: 0) * codec bytesPerEncodedFrame.\\n\\ttmpStream position: audioDataStart + startOffset.\\n\\n\\t\\\"decode forward to the desired position\\\"\\n\\tbyteBuf := ByteArray new: (32000 roundTo: codec bytesPerEncodedFrame).\\n\\tbufFrames := byteBuf size // codec bytesPerEncodedFrame.\\n\\tsampleBuf := SoundBuffer newMonoSampleCount: bufFrames * codec samplesPerFrame.\\n\\tframeCount := (desiredPosition - tmpStream position) // codec bytesPerEncodedFrame.\\n\\t[frameCount > 0] whileTrue: [\\n\\t\\tn := bufFrames min: frameCount.\\n\\t\\ttmpStream next: n * codec bytesPerEncodedFrame into: byteBuf startingAt: 1.\\n\\t\\ttmpCodec decodeFrames: n from: byteBuf at: 1 into: sampleBuf at: 1.\\n\\t\\tframeCount := frameCount - n].\\n\\n\\tcodec := tmpCodec.\\n\\tstream position: tmpStream position.\\n\\t(tmpStream isKindOf: FileStream) ifTrue: [tmpStream close].! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadAIFFHeader\\n\\t\\\"Read an AIFF file header from stream.\\\"\\n\\n\\t| aiffReader |\\n\\taiffReader := AIFFFileReader new.\\n\\taiffReader readFromStream: stream mergeIfStereo: false skipDataChunk: true.\\n\\taiffReader channelCount = 1 ifFalse: [self error: 'not monophonic'].\\n\\taiffReader bitsPerSample = 16 ifFalse: [self error: 'not 16-bit'].\\n\\n\\taudioDataStart := headerStart + aiffReader channelDataOffset.\\n\\tstreamSamplingRate := aiffReader samplingRate.\\n\\ttotalSamples := aiffReader frameCount min: (stream size - audioDataStart) // 2.\\n\\tcodec := nil.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadHeader\\n\\t\\\"Read the sound file header from my stream.\\\"\\n\\n\\t| id |\\n\\tstream position: headerStart.\\n\\tid := (stream next: 4) asString.\\n\\tstream position: headerStart.\\n\\tid = '.snd' ifTrue: [^ self readSunAudioHeader].\\n\\tid = 'FORM' ifTrue: [^ self readAIFFHeader].\\n\\tself error: 'unrecognized sound file format'.\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nreadSunAudioHeader\\n\\t\\\"Read a Sun audio file header from my stream.\\\"\\n\\n\\t| id headerBytes dataBytes format channelCount |\\n\\tid := (stream next: 4) asString.\\n\\theaderBytes := stream uint32. \\\"header bytes\\\"\\n\\tdataBytes := stream uint32.\\n\\tformat := stream uint32.\\n\\tstreamSamplingRate := stream uint32.\\n\\tchannelCount := stream uint32.\\n\\n\\tid = '.snd' ifFalse: [self error: 'not Sun audio format'].\\n\\tdataBytes := dataBytes min: (stream size - headerBytes).\\n\\tchannelCount = 1 ifFalse: [self error: 'not monophonic'].\\n\\taudioDataStart := headerStart + headerBytes.\\n\\tcodec := nil.\\n\\tformat = 1 ifTrue: [ \\\"8-bit u-LAW\\\"\\n\\t\\tcodec := MuLawCodec new.\\n\\t\\ttotalSamples := dataBytes.\\n\\t\\t^ self].\\n\\tformat = 3 ifTrue: [ \\\"16-bit linear\\\"\\n\\t\\ttotalSamples := dataBytes // 2.\\n\\t\\t^ self].\\n\\tformat = 23 ifTrue: [ \\\"ADPCM-4 bit (CCITT G.721)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 4 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 4) * 8.\\n\\t\\t^ self].\\n\\tformat = 25 ifTrue: [ \\\"ADPCM-3 bit (CCITT G.723)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 3 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 3) * 8.\\n\\t\\t^ self].\\n\\tformat = 26 ifTrue: [ \\\"ADPCM-5 bit (CCITT G.723)\\\"\\n\\t\\tcodec := ADPCMCodec new\\n\\t\\t\\tinitializeForBitsPerSample: 5 samplesPerFrame: 0.\\n\\t\\ttotalSamples := (dataBytes // 5) * 8.\\n\\t\\t^ self].\\n\\tformat = 610 ifTrue: [ \\\"GSM 06.10 (this format was added by Squeak)\\\"\\n\\t\\tcodec := GSMCodec new.\\n\\t\\ttotalSamples := (dataBytes // 33) * 160.\\n\\t\\t^ self].\\n\\tself error: 'unsupported Sun audio format ', format printString\\n! !\\n\\n!StreamingMonoSound methodsFor: 'private' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstartOver\\n\\t\\\"Jump back to the first sample.\\\"\\n\\n\\tstream reopen; binary.\\n\\tself readHeader.\\n\\tstream position: audioDataStart.\\n\\tleftoverSamples := SoundBuffer new.\\n\\tlastBufferMSecs := 0.\\n\\tmutex := Semaphore forMutualExclusion.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStreamingMonoSound class\\n\\tinstanceVariableNames: ''!\\n\\n!StreamingMonoSound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me for playing the file with the given name.\\\"\\n\\n\\t| f |\\n\\tf := FileDirectory default readOnlyFileNamed: fileName.\\n\\tf ifNil: [^ self error: 'could not open ', fileName].\\n\\t^ self new initStream: f headerStart: 0\\n! !\\n\\n!StreamingMonoSound class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName headerStart: anInteger\\n\\t\\\"Answer an instance of me for playing audio data starting at the given position in the file with the given name.\\\"\\n\\n\\t| f |\\n\\tf := FileDirectory default readOnlyFileNamed: fileName.\\n\\tf ifNil: [^ self error: 'could not open ', fileName].\\n\\t^ self new initStream: f headerStart: anInteger\\n! !\\nAlignmentMorphBob1 subclass: #StretchyImageMorph\\n\\tinstanceVariableNames: 'form cache'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Experimental'!\\n!StretchyImageMorph commentStamp: '<historical>' prior: 0!\\nI draw a form to fill whatever bounds I have.!\\n\\n\\n!StretchyImageMorph methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 16:20'!\\nform: aForm\\n\\n\\tform _ aForm! !\\n\\n\\n!StretchyImageMorph methodsFor: 'drawing' stamp: 'nk 1/3/2004 17:40'!\\ndrawOn: aCanvas\\n| t |\\n\\\"\\nSmalltalk at: #Q4 put: OrderedCollection new.\\n\\\"\\n\\tform ifNil: [form _ (Form extent: 32@32 depth: 8) fillColor: Color green].\\n\\t(cache isNil or: [cache extent ~= bounds extent]) ifTrue: [\\n\\t\\tt _ [cache _ Form extent: bounds extent depth: form depth.\\n\\t\\tform displayInterpolatedIn: cache boundingBox on: cache.\\n\\t\\tcache _ cache asFormOfDepth: aCanvas depth] timeToRun.\\n\\t\\t\\\"Q4 add: {t. form. cache}.\\\"\\n\\t].\\n\\taCanvas paintImage: cache at: bounds origin.\\n! !\\n\\n\\n!StretchyImageMorph methodsFor: 'initialization' stamp: 'ar 10/30/2000 15:31'!\\ninitialize\\n\\n\\tsuper initialize.\\n\\tself hResizing: #spaceFill.\\n\\tself vResizing: #spaceFill.\\n! !\\nAbstractFont subclass: #StrikeFont\\n\\tinstanceVariableNames: 'characterToGlyphMap xTable glyphs name type minAscii maxAscii maxWidth strikeLength ascent descent xOffset raster subscript superscript emphasis derivativeFonts pointSize fallbackFont charIndex'\\n\\tclassVariableNames: 'DefaultStringScanner'\\n\\tpoolDictionaries: 'TextConstants'\\n\\tcategory: 'Graphics-Fonts'!\\n!StrikeFont commentStamp: '<historical>' prior: 0!\\nI 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 glyphs. Characters are mapped to glyphs by using the characterToGyphMap.\\n\\nSubclasses can have non-trivial mapping rules as well as different representations for glyphs sizes (e.g., not using an xTable). If so, these classes should return nil when queried for xTable and/or the characterToGlyphMap. This will cause the CharacterScanner primitive to fail and query the font for the width of a character (so that a more programatical approach can be implemented).\\n\\nFor display, fonts need to implement two messages:\\n\\t#installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor\\nThis method installs the receiver (a font) on the given DisplayContext (which may be an instance of BitBlt or Canvas (or any of it's subclasses). The font should take the appropriate action to initialize the display context so that further display operations can be optimized.\\n\\t#displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta\\nThis method is called for each subsequent run of characters in aString which is to be displayed with the (previously installed) settings.\\n!\\n\\n\\n!StrikeFont methodsFor: 'accessing'!\\nascent\\n\\t\\\"Answer the receiver's maximum extent of characters above the baseline.\\\"\\n\\n\\t^ascent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/2/2000 13:06'!\\nascentKern\\n\\t\\\"Return the kern delta for ascenders.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ (self ascent-5+4)//4 max: 0 \\\"See makeItalicGlyphs\\\"\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nascentOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont ascentOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self ascent.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/1/2000 17:17'!\\nbaseKern\\n\\t\\\"Return the base kern value to be used for all characters.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ ((self height-1-self ascent+4)//4 max: 0) \\\"See makeItalicGlyphs\\\"\\n\\t\\t+ (((self ascent-5+4)//4 max: 0))\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 5/23/2000 12:52'!\\ncharacterToGlyphMap\\n\\t^characterToGlyphMap ifNil:[characterToGlyphMap _ self createCharacterToGlyphMap].! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 5/23/2000 12:52'!\\ncharacterToGlyphMap: anArray\\n\\tcharacterToGlyphMap _ anArray.! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'nk 3/15/2004 18:57'!\\nderivativeFonts\\n\\t^derivativeFonts copyWithout: nil! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\ndescent\\n\\t\\\"Answer the receiver's maximum extent of characters below the baseline.\\\"\\n\\n\\t^descent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'di 9/2/2000 13:06'!\\ndescentKern\\n\\t\\\"Return the kern delta for descenders.\\\"\\n\\t(emphasis noMask: 2) ifTrue: [^ 0].\\n\\t^ (self height-1-self ascent+4)//4 max: 0 \\\"See makeItalicGlyphs\\\"\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\ndescentOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont descentOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self descent.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'tak 12/22/2004 01:25'!\\nfallbackFont\\n\\t^ fallbackFont\\n\\t\\tifNil: [fallbackFont _ FixedFaceFont new errorFont fontSize: self height]! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 5/20/2004 11:01'!\\nfallbackFont: aFontSetOrNil\\n\\n\\tfallbackFont _ aFontSetOrNil.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nfamilyName\\n\\t^self name withoutTrailingDigits.\\n\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'tk 6/26/1998 16:45'!\\nfamilySizeFace\\n\\t\\\"Answer an array with familyName, a String, pointSize, an Integer, and\\n\\tfaceCode, an Integer.\\\"\\n\\n\\t^Array with: name\\n\\t\\twith: self height\\n\\t\\twith: emphasis\\n\\n\\t\\\"(1 to: 12) collect: [:x | (TextStyle default fontAt: x) familySizeFace]\\\"! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 9/21/2000 11:53'!\\nfontNameWithPointSize\\n\\t^self name withoutTrailingDigits, ' ', self pointSize printString! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/7/2005 11:15'!\\nglyphInfoOf: aCharacter into: glyphInfoArray\\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\n\\t| code |\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont glyphInfoOf: aCharacter into: glyphInfoArray.\\n\\t\\t].\\n\\t\\tcode _ 0.\\n\\t] ifTrue: [\\n\\t\\tcode _ aCharacter charCode.\\n\\t].\\n\\tglyphInfoArray at: 1 put: glyphs;\\n\\t\\tat: 2 put: (xTable at: code + 1);\\n\\t\\tat: 3 put: (xTable at: code + 2);\\n\\t\\tat: 4 put: (self ascentOf: aCharacter);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nglyphOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\n\\t| code |\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont glyphOf: aCharacter.\\n\\t\\t].\\n\\t\\t^ (Form extent: 1@self height) fillColor: Color white\\n\\t].\\n\\tcode _ aCharacter charCode.\\n\\t^ glyphs copy: (((xTable at: code + 1)@0) corner: (xTable at: code +2)@self height).\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nglyphs\\n\\t\\\"Answer a Form containing the bits representing the characters of the \\n\\treceiver.\\\"\\n\\n\\t^glyphs! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nheight\\n\\t\\\"Answer the height of the receiver, total of maximum extents of \\n\\tcharacters above and below the baseline.\\\"\\n\\n\\t^self ascent + self descent! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 1/6/2005 04:19'!\\nheightOf: aCharacter\\n\\n\\t(self hasGlyphOf: aCharacter) ifFalse: [\\n\\t\\tfallbackFont ifNotNil: [\\n\\t\\t\\t^ fallbackFont heightOf: aCharacter.\\n\\t\\t].\\n\\t].\\n\\t^ self height.\\n! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nlineGrid\\n\\t^ ascent + descent! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nmaxAscii\\n\\t\\\"Answer the integer that is the last Ascii character value of the receiver.\\\"\\n\\n\\t^maxAscii! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nmaxWidth\\n\\t\\\"Answer the integer that is the width of the receiver's widest character.\\\"\\n\\n\\t^maxWidth! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nminAscii\\n\\t\\\"Answer the integer that is the first Ascii character value of the receiver.\\\"\\n\\n\\t^minAscii! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ls 3/27/2000 19:54'!\\nname\\n\\t\\\"Answer the receiver's name.\\\"\\n\\n\\t^name ifNil: ['(unnamed)']! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nname: aString\\n\\t\\\"Set the receiver's name.\\\"\\n\\n\\tname _ aString! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'sw 1/18/2000 20:54'!\\npointSize\\n\\t^ pointSize! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'sma 5/5/2000 14:21'!\\npointSize: anInteger\\n\\tpointSize _ anInteger! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nraster\\n\\t\\\"Answer an integer that specifies the layout of the glyphs' form.\\\"\\n\\n\\t^raster! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsetGlyphs: newGlyphs\\n\\t\\\"Replace the glyphs form. Used to make a synthetic bold or italic font quickly.\\\"\\n\\n\\tglyphs _ newGlyphs! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsubscript\\n\\t\\\"Answer an integer that is the further vertical offset relative to the \\n\\tbaseline for positioning characters as subscripts.\\\"\\n\\n\\t^subscript! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nsuperscript\\n\\t\\\"Answer an integer that is the further vertical offset relative to the \\n\\tbaseline for positioning characters as superscripts.\\\"\\n\\n\\t^superscript! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'nk 6/17/2003 14:26'!\\ntextStyle\\n\\t^ TextStyle actualTextStyles detect:\\n\\t\\t[:aStyle | aStyle fontArray includes: self] ifNone: [nil]! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:12'!\\nwidthOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\t| code |\\n\\tcode := aCharacter charCode.\\n\\t((code < minAscii or: [maxAscii < code]) \\n\\t\\tor: [(xTable at: code + 1) < 0])\\n\\t\\t\\tifTrue: [^ self fallbackFont widthOf: aCharacter].\\n\\t^ (xTable at: code + 2) - (xTable at: code + 1)! !\\n\\n!StrikeFont methodsFor: 'accessing'!\\nxTable\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^xTable! !\\n\\n!StrikeFont methodsFor: 'accessing' stamp: 'yo 8/28/2002 16:33'!\\nxTable: anObject\\n\\n\\txTable _ anObject.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'character shapes'!\\nalter: char formBlock: formBlock\\n\\tself characterFormAt: char \\n\\t\\tput: (formBlock value: (self characterFormAt: char))! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'yo 12/28/2002 22:37'!\\ncharacterFormAtMulti: character \\n\\t\\\"Answer a Form copied out of the glyphs for the argument, character.\\\"\\n\\t| ascii leftX rightX |\\n\\tascii _ character charCode.\\n\\t(ascii between: minAscii and: maxAscii) ifFalse: [ascii _ maxAscii + 1].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\t^ glyphs copy: (leftX @ 0 corner: rightX @ self height)! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'yo 12/1/2003 17:01'!\\ncharacterFormAt: character \\n\\t\\\"Answer a Form copied out of the glyphs for the argument, character.\\\"\\n\\t| ascii leftX rightX |\\n\\tascii _ character charCode.\\n\\t(ascii between: minAscii and: maxAscii) ifFalse: [ascii _ maxAscii + 1].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\tleftX < 0 ifTrue: [^ glyphs copy: (0@0 corner: 0@self height)].\\n\\t^ glyphs copy: (leftX @ 0 corner: rightX @ self height)! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 8/30/2000 10:00'!\\ncharacterFormAt: character put: characterForm\\n\\t\\\"Copy characterForm over the glyph for the argument, character.\\\"\\n\\t| ascii leftX rightX widthDif newGlyphs |\\n\\tascii _ character asciiValue.\\n\\tascii < minAscii ifTrue: [^ self error: 'Cant store characters below min ascii'].\\n\\tascii > maxAscii ifTrue:\\n\\t\\t[(self confirm:\\n'This font does not accomodate ascii values higher than ' , maxAscii printString , '.\\nDo you wish to extend it permanently to handle values up to ' , ascii printString)\\n\\t\\t\\tifTrue: [self extendMaxAsciiTo: ascii]\\n\\t\\t\\tifFalse: [^ self error: 'No change made']].\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\twidthDif _ characterForm width - (rightX - leftX).\\n\\twidthDif ~= 0 ifTrue:\\n\\t\\t[\\\"Make new glyphs with more or less space for this char\\\"\\n\\t\\tnewGlyphs _ Form extent: (glyphs width + widthDif) @ glyphs height.\\n\\t\\tnewGlyphs copy: (0@0 corner: leftX@glyphs height)\\n\\t\\t\\tfrom: 0@0 in: glyphs rule: Form over.\\n\\t\\tnewGlyphs copy: ((rightX+widthDif)@0 corner: newGlyphs width@glyphs height)\\n\\t\\t\\tfrom: rightX@0 in: glyphs rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\t\\\"adjust further entries on xTable\\\"\\n\\t\\txTable _ xTable copy.\\n\\t\\tascii+2 to: xTable size\\n\\t\\t\\tdo: [:i | xTable at: i put: (xTable at: i) + widthDif]].\\n\\tglyphs copy: (leftX @ 0 extent: characterForm extent)\\n\\t\\tfrom: 0@0 in: characterForm rule: Form over\\n\\\"\\n| f | f _ TextStyle defaultFont.\\nf characterFormAt: $ put: (Form extent: (f widthOf: $ )+10@f height)\\n\\\"! !\\n\\n!StrikeFont methodsFor: 'character shapes'!\\ncharacterForm: char pixelValueAt: pt put: val\\n\\t| f |\\n\\tf _ self characterFormAt: char.\\n\\tf pixelAt: pt put: val.\\n\\tself characterFormAt: char put: val! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'btr 11/18/2002 15:00'!\\nedit: character \\n\\t\\\"Open a Bit Editor on the given character. Note that you must do an accept \\n\\t(in the option menu of the bit editor) if you want this work. \\n\\tAccepted edits will not take effect in the font until you leave or close the bit editor. \\n\\tAlso note that unaccepted edits will be lost when you leave or close.\\\"\\n\\t\\\"Note that BitEditor only works in MVC currently.\\\"\\n\\n\\t\\\"(TextStyle default fontAt: 1) edit: $_\\\"\\n\\n\\t| charForm editRect scaleFactor bitEditor savedForm r |\\n\\tcharForm _ self characterFormAt: character.\\n\\teditRect _ BitEditor locateMagnifiedView: charForm scale: (scaleFactor _ 8 @ 8).\\n\\tbitEditor _ BitEditor\\n\\t\\t\\t\\tbitEdit: charForm\\n\\t\\t\\t\\tat: editRect topLeft\\n\\t\\t\\t\\tscale: scaleFactor\\n\\t\\t\\t\\tremoteView: nil.\\n\\tsavedForm _ Form fromDisplay: (r _ bitEditor displayBox\\n\\t\\t\\t\\t\\t\\t\\texpandBy: (0 @ 23 corner: 0 @ 0)).\\n\\tbitEditor controller startUp.\\n\\tbitEditor release.\\n\\tsavedForm displayOn: Display at: r topLeft.\\n\\tself characterFormAt: character put: charForm! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'BG 12/6/2004 19:22'!\\nensureCleanBold\\n\\t\\\"This ensures that all character glyphs have at least one pixel of white space on the right\\n\\tso as not to cause artifacts in neighboring characters in bold or italic.\\\"\\n\\n\\t| newGlyphs newXTable newGlyphPos startPos newWidth widthOfGlyph increment lastCol |\\n\\temphasis = 0 ifFalse: [^ self].\\n newWidth := glyphs width + maxAscii - minAscii + 1.\\n lastCol := Form extent: 1@ glyphs height.\\n newGlyphs := Form extent: newWidth @ glyphs height.\\n newXTable := Array new: xTable size.\\n 1 to: minAscii do: [:idx | newXTable at: idx put: (xTable at: idx)].\\n \\n newGlyphPos := startPos := 0.\\n minAscii to: maxAscii do:\\n [:idx | \\n newXTable at: idx + 1 put: newGlyphPos.\\n widthOfGlyph := (xTable at: idx + 2 ) - (xTable at: idx + 1).\\n widthOfGlyph > 0\\n ifTrue:\\n [newGlyphs copy: (newGlyphPos @ 0 extent: widthOfGlyph @ glyphs height)\\n from: startPos@0 in: glyphs rule: Form over.\\n lastCol copy: (0 @ 0 extent: 1 @ glyphs height)\\n from: startPos + widthOfGlyph - 1 @0 in: glyphs rule: Form over.\\n increment := lastCol isAllWhite ifTrue: [0] ifFalse: [1].\\n startPos := startPos + widthOfGlyph.\\n newGlyphPos := newGlyphPos + widthOfGlyph + increment.\\n ].\\n ].\\n maxAscii + 2 to: newXTable size do: [:idx | newXTable at: idx put: newGlyphPos.].\\n glyphs := Form extent: newGlyphPos @ glyphs height.\\n glyphs copy: (0 @ 0 extent: glyphs extent)\\n from: 0@0 in: newGlyphs rule: Form over.\\n xTable := newXTable.\\n\\\"\\nStrikeFont allInstancesDo: [:f | f ensureCleanBold].\\n(StrikeFont familyName: 'NewYork' size: 21) ensureCleanBold.\\nStrikeFont shutDown. 'Flush synthetic fonts'.\\n\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'ar 5/23/2000 12:48'!\\nextendMaxAsciiTo: newMax\\n\\t\\\"Extend the range of this font so that it can display glyphs up to newMax.\\\"\\n\\n\\t(newMax+3) <= xTable size ifTrue: [^ self]. \\\"No need to extend.\\\"\\n\\txTable size = (maxAscii+3) ifFalse:\\n\\t\\t[^ self error: 'This font is not well-formed.'].\\n\\n\\t\\\"Insert a bunch of zero-width characters...\\\"\\n\\txTable _ (xTable copyFrom: 1 to: maxAscii+2) ,\\n\\t\\t\\t((maxAscii+1 to: newMax) collect: [:i | xTable at: maxAscii+2]) ,\\n\\t\\t\\t{ xTable at: maxAscii+3 }.\\n\\tmaxAscii _ newMax.\\n\\tself fillZeroWidthSlots.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 3/27/2000 16:10'!\\nfillZeroWidthSlots\\n\\t| nullGlyph |\\n\\t\\\"Note: this is slow because it copies the font once for every replacement.\\\"\\n\\n\\tnullGlyph _ (Form extent: 1@glyphs height) fillGray.\\n\\t\\\"Now fill the empty slots with narrow box characters.\\\"\\n\\tminAscii to: maxAscii do:\\n\\t\\t[:i | (self widthOf: (Character value: i)) = 0 ifTrue:\\n\\t\\t\\t[self characterFormAt: (Character value: i) put: nullGlyph]].\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'di 4/28/2000 16:10'!\\nfixOneWideChars \\n\\t\\\"This fixes all 1-wide characters to be 2 wide with blank on the right\\n\\tso as not to cause artifacts in neighboring characters in bold or italic.\\\"\\n\\t| twoWide |\\n\\tminAscii to: maxAscii do:\\n\\t\\t[:i | (self widthOf: (Character value: i)) = 1 ifTrue:\\n\\t\\t\\t[twoWide _ Form extent: 2@glyphs height.\\n\\t\\t\\t(self characterFormAt: (Character value: i)) displayOn: twoWide at: 0@0.\\n\\t\\t\\tself characterFormAt: (Character value: i) put: twoWide]].\\n\\\"\\nStrikeFont allInstancesDo: [:f | f fixOneWideChars].\\nStrikeFont shutDown. 'Flush synthetic fonts'.\\n\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes' stamp: 'RAA 7/6/2000 16:50'!\\nmakeCarriageReturnsWhite\\n\\t| crForm |\\n\\t\\\"Some larger fonts have a gray carriage return (from the zero wide fixup) make it white so it doesn't show\\\"\\n\\n\\tcrForm _ self characterFormAt: 13 asCharacter.\\n\\tcrForm fillWhite.\\n\\tself characterFormAt: 13 asCharacter put: crForm.\\n! !\\n\\n!StrikeFont methodsFor: 'character shapes'!\\nwiden: char by: delta\\n\\t| newForm |\\n\\t^ self alter: char formBlock: \\\"Make a new form, wider or narrower...\\\"\\n\\t\\t[:charForm | newForm _ Form extent: charForm extent + (delta@0).\\n\\t\\tcharForm displayOn: newForm. \\\"Copy this image into it\\\"\\n\\t\\tnewForm] \\\"and substitute it in the font\\\"! !\\n\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'BG 12/9/2004 17:27'!\\ndeepCopy\\n \\\" there is a circular reference from the derivative fonts back to the receiver. It is therefore not possible to make a deep copy. We make a sahllow copy. The method postCopy can be used to modify the shallow copy. \\\" \\n ^self copy! !\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'BG 12/9/2004 17:35'!\\npostCopy\\n \\\" the receiver is a just created shallow copy. This method gives it the final touch. \\\" \\n \\n glyphs := glyphs copy.\\n xTable := xTable copy.\\n characterToGlyphMap := characterToGlyphMap copy.\\n \\n self reset. \\\" takes care of the derivative fonts \\\"! !\\n\\n!StrikeFont methodsFor: 'copying' stamp: 'tk 8/19/1998 16:15'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I am shared. Do not record me.\\\"! !\\n\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:34'!\\ncharacters: anInterval in: sourceString displayAt: aPoint clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm kernDelta: kernDelta on: aBitBlt\\n\\t\\\"Simple, slow, primitive method for displaying a line of characters.\\n\\tNo wrap-around is provided.\\\"\\n\\t| ascii destPoint leftX rightX sourceRect |\\n\\tdestPoint _ aPoint.\\n\\tanInterval do: \\n\\t\\t[:i |\\n\\t\\tself flag: #yoDisplay.\\n\\t\\t\\\"if the char is not supported, fall back to the specified fontset.\\\"\\n\\t\\tascii _ (sourceString at: i) charCode.\\n\\t\\t(ascii < minAscii or: [ascii > maxAscii])\\n\\t\\t\\tifTrue: [ascii _ maxAscii].\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\tsourceRect _ leftX@0 extent: (rightX-leftX) @ self height.\\n\\t\\taBitBlt copyFrom: sourceRect in: glyphs to: destPoint.\\n\\t\\tdestPoint _ destPoint + ((rightX-leftX+kernDelta)@0).\\n\\t\\t\\\"destPoint printString displayAt: 0@(i*20)\\\"].\\n\\t^ destPoint! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:36'!\\ndisplayLine: aString at: aPoint \\n\\t\\\"Display the characters in aString, starting at position aPoint.\\\"\\n\\n\\tself characters: (1 to: aString size)\\n\\t\\tin: aString\\n\\t\\tdisplayAt: aPoint\\n\\t\\tclippedBy: Display boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil\\n\\t\\tkernDelta: 0\\n\\t\\ton: (BitBlt current toForm: Display).\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 1/7/2005 15:16'!\\ndisplayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo char displayInfo destY |\\n\\tdestPoint _ aPoint.\\n\\tcharIndex _ startIndex.\\n\\tglyphInfo _ Array new: 5.\\n\\t[charIndex <= stopIndex] whileTrue: [\\n\\t\\tchar _ aString at: charIndex.\\n\\t\\t(self hasGlyphOf: char) not ifTrue: [\\n\\t\\t\\t\\tdisplayInfo _ self fallbackFont displayString: aString on: aBitBlt from: charIndex to: stopIndex at: destPoint kern: kernDelta from: self baselineY: baselineY.\\n\\t\\t\\t\\tcharIndex _ displayInfo first.\\n\\t\\t\\t\\tdestPoint _ displayInfo second.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tself glyphInfoOf: char into: glyphInfo.\\n\\t\\t\\tleftX _ glyphInfo second.\\n\\t\\t\\trightX _ glyphInfo third.\\n\\t\\t\\t(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\t\\tglyphInfo fifth installOn: aBitBlt.\\n\\t\\t\\t].\\n\\t\\t\\taBitBlt sourceForm: glyphInfo first.\\n\\t\\t\\tdestY _ baselineY - glyphInfo fourth. \\n\\t\\t\\taBitBlt destX: destPoint x.\\n\\t\\t\\taBitBlt destY: destY.\\n\\t\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\t\\taBitBlt width: rightX - leftX.\\n\\t\\t\\taBitBlt height: self height.\\n\\t\\t\\taBitBlt copyBits.\\n\\t\\t\\tdestPoint _ destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t\\t\\tcharIndex _ charIndex + 1.\\n\\t\\t].\\n\\t].\\n\\t^ Array with: charIndex with: destPoint.\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 12/20/2002 18:54'!\\ndisplayStringR2L: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta\\n\\t\\\"You are screwed if you reach this method.\\\"\\n\\tself halt.\\n\\taBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 4/10/2005 18:06'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t(aString isByteString) ifFalse: [^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: aPoint y + self ascent.].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 4/10/2005 18:06'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t(aString isByteString) ifFalse:[^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY.].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta.! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'BG 3/16/2005 08:27'!\\nfontDisplay\\n\\t\\\"TextStyle default defaultFont fontDisplay.\\\"\\n\\n\\tDisplay restoreAfter:\\n\\t\\t[(Form extent: 440@400) displayAt: 90@90.\\n\\t\\t 0 to: 15 do:\\n\\t\\t\\t[:i |\\n\\t\\t\\ti storeStringHex displayAt: 100 @ (20 * i + 100).\\n\\t\\t\\t0 to: 15 do:\\n\\t\\t\\t\\t[:j |\\n\\t\\t\\t\\t((16*i+j) between: 1 and: (self xTable size - 2)) ifTrue:\\n\\t\\t\\t\\t\\t[(self characterFormAt: (16 * i + j) asCharacter)\\n\\t\\t\\t\\t\\t\\tdisplayAt: (20 * j + 150) @ (20 * i + 100)]]].\\n\\t\\t\\t'Click to continue...' asDisplayText displayAt: 100@450]! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'yo 1/5/2005 13:59'!\\ninstallOn: aDisplayContext\\n\\n\\t^aDisplayContext installStrikeFont: self.\\n! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 15:08'!\\ninstallOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor\\n\\t^aDisplayContext \\n\\t\\tinstallStrikeFont: self\\n\\t\\tforegroundColor: foregroundColor \\n\\t\\tbackgroundColor: backgroundColor! !\\n\\n!StrikeFont methodsFor: 'displaying' stamp: 'tak 1/11/2005 18:03'!\\nwidthOfString: aString from: firstIndex to: lastIndex\\n\\t| resultX |\\n\\tresultX _ 0.\\n\\tfirstIndex to: lastIndex do:[:i | \\n\\t\\tresultX _ resultX + (self widthOf: (aString at: i))].\\n\\t^ resultX.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 12/18/2003 23:30'!\\nbonk: glyphForm with: bonkForm\\n\\t\\\"Bonking means to run through the glyphs clearing out black pixels\\n\\tbetween characters to prevent them from straying into an adjacent\\n\\tcharacter as a result of, eg, bolding or italicizing\\\"\\n\\t\\\"Uses the bonkForm to erase at every character boundary in glyphs.\\\"\\n\\t| bb offset x |\\n\\toffset _ bonkForm offset x.\\n\\tbb _ BitBlt current toForm: glyphForm.\\n\\tbb sourceForm: bonkForm; sourceRect: bonkForm boundingBox;\\n\\t\\tcombinationRule: Form erase; destY: 0.\\n\\tx _ self xTable.\\n\\t(x isMemberOf: SparseLargeTable) ifTrue: [\\n\\t\\tx base to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t] ifFalse: [\\n\\t\\t1 to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis'!\\nemphasis\\n\\t\\\"Answer the integer code for synthetic bold, italic, underline, and \\n\\tstrike-out.\\\"\\n\\n\\t^emphasis! !\\n\\n!StrikeFont methodsFor: 'emphasis'!\\nemphasis: code \\n\\t\\\"Set the integer code for synthetic bold, itallic, underline, and strike-out, \\n\\twhere bold=1, italic=2, underlined=4, and struck out=8.\\\"\\n\\n\\temphasis _ code! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'di 9/3/2000 13:22'!\\nemphasized: code \\n\\t\\\"Answer a copy of the receiver with emphasis set to include code.\\\"\\n\\t| derivative addedEmphasis base safeCode |\\n\\tcode = 0 ifTrue: [^ self].\\n\\t(derivativeFonts == nil or: [derivativeFonts size = 0]) ifTrue: [^ self].\\n\\tderivative _ derivativeFonts at: (safeCode _ code min: derivativeFonts size).\\n\\tderivative == nil ifFalse: [^ derivative]. \\\"Already have this style\\\"\\n\\n\\t\\\"Dont have it -- derive from another with one with less emphasis\\\"\\n\\taddedEmphasis _ 1 bitShift: safeCode highBit - 1.\\n\\tbase _ self emphasized: safeCode - addedEmphasis. \\\"Order is Bold, Ital, Under, Narrow\\\"\\n\\taddedEmphasis = 1 ifTrue: \\\"Compute synthetic bold version of the font\\\"\\n\\t\\t[derivative _ (base copy ensureCleanBold name: base name , 'B') makeBoldGlyphs].\\n\\taddedEmphasis = 2 ifTrue: \\\"Compute synthetic italic version of the font\\\"\\n\\t\\t[ derivative _ (base copy name: base name , 'I') makeItalicGlyphs].\\n\\taddedEmphasis = 4 ifTrue: \\\"Compute underlined version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'U') makeUnderlinedGlyphs].\\n\\taddedEmphasis = 8 ifTrue: \\\"Compute narrow version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'N') makeCondensedGlyphs].\\n\\taddedEmphasis = 16 ifTrue: \\\"Compute struck-out version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'X') makeStruckOutGlyphs].\\n\\tderivative emphasis: safeCode.\\n\\tderivativeFonts at: safeCode put: derivative.\\n\\t^ derivative! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeBoldGlyphs\\n\\t\\\"Make a bold set of glyphs with same widths by ORing 1 bit to the right\\n\\t\\t(requires at least 1 pixel of intercharacter space)\\\"\\n\\t| g bonkForm |\\n\\tg _ glyphs deepCopy.\\n\\tbonkForm _ (Form extent: 1@16) fillBlack offset: -1@0.\\n\\tself bonk: g with: bonkForm.\\n\\tg copyBits: g boundingBox from: g at: (1@0)\\n\\t\\tclippingBox: g boundingBox rule: Form under fillColor: nil.\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 1\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:51'!\\nmakeCondensedGlyphs\\n\\t\\\"Make a condensed set of glyphs with same widths.\\n\\tNOTE: this has been superceded by kerning -- should not get called\\\"\\n\\t| g newXTable x x1 w |\\n\\tg _ glyphs deepCopy.\\n\\tnewXTable _ Array new: xTable size.\\n\\tnewXTable at: 1 put: (x _ xTable at: 1).\\n\\t1 to: xTable size-1 do:\\n\\t\\t[:i | x1 _ xTable at: i. w _ (xTable at: i+1) - x1.\\n\\t\\tw > 1 ifTrue: [w _ w-1]. \\\"Shrink every character wider than 1\\\"\\n\\t\\tg copy: (x@0 extent: w@g height) from: x1@0 in: glyphs rule: Form over.\\n\\t\\tnewXTable at: i+1 put: (x _ x + w)].\\n\\txTable _ newXTable.\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont emphasized: 8\\n\\t].\\n\\n\\\"\\n(TextStyle default fontAt: 1) copy makeCondensedGlyphs\\n\\tdisplayLine: 'The quick brown fox jumps over the lazy dog'\\n\\tat: Sensor cursorPoint\\n\\\"! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeItalicGlyphs\\n\\t\\\"Make an italic set of glyphs with same widths by skewing left and right.\\n\\tIn the process, characters would overlap, so we widen them all first.\\n\\t\\\"\\n\\t| extraWidth newGlyphs newXTable x newX w extraOnLeft | \\n\\textraOnLeft _ (self height-1-self ascent+4)//4 max: 0.\\n\\textraWidth _ ((self ascent-5+4)//4 max: 0) + extraOnLeft.\\n\\tnewGlyphs _ Form extent: (glyphs width + (maxAscii + 1 - minAscii*extraWidth)) @ glyphs height.\\n\\tnewXTable _ xTable copy.\\n\\n\\t\\\"Copy glyphs into newGlyphs with room on left and right for overlap.\\\"\\n\\tminAscii to: maxAscii+1 do:\\n\\t\\t[:ascii | x _ xTable at: ascii+1. w _ (xTable at: ascii+2) - x.\\n\\t\\tnewX _ newXTable at: ascii+1.\\n\\t\\tnewGlyphs copy: ((newX + extraOnLeft) @ 0 extent: w @ glyphs height)\\n\\t\\t\\tfrom: x @ 0 in: glyphs rule: Form over.\\n\\t\\tnewXTable at: ascii+2 put: newX + w + extraWidth].\\t\\t\\n\\tglyphs _ newGlyphs. \\n\\txTable _ newXTable.\\n\\t\\\"Slide the bitmaps left and right for synthetic italic effect.\\\"\\n\\t4 to: self ascent-1 by: 4 do:\\n\\t\\t[:y | \\t\\t\\\"Slide ascenders right...\\\"\\n\\t\\tglyphs copy: (1@0 extent: glyphs width @ (self ascent - y))\\n\\t\\t\\tfrom: 0@0 in: glyphs rule: Form over].\\n\\tself ascent to: self height-1 by: 4 do:\\n\\t\\t[:y | \\t\\t\\\"Slide descenders left...\\\"\\n\\t\\tglyphs copy: (0@y extent: glyphs width @ glyphs height)\\n\\t\\t\\tfrom: 1@y in: glyphs rule: Form over].\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 2\\n\\t].\\n\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeStruckOutGlyphs\\n\\t\\\"Make a struck-out set of glyphs with same widths\\\"\\n\\t| g |\\n\\tg _ glyphs deepCopy.\\n\\tg fillBlack: (0 @ (self ascent - (self ascent//3)) extent: g width @ 1).\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 16\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'yo 5/24/2004 17:54'!\\nmakeUnderlinedGlyphs\\n\\t\\\"Make an underlined set of glyphs with same widths\\\"\\n\\t| g |\\n\\tg _ glyphs deepCopy.\\n\\tg fillBlack: (0 @ (self ascent+1) extent: g width @ 1).\\n\\tglyphs _ g.\\n\\tfallbackFont ifNotNil: [\\n\\t\\tfallbackFont _ fallbackFont emphasized: 4\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'nk 3/15/2004 18:46'!\\nreleaseCachedState\\n\\n\\tself reset.! !\\n\\n!StrikeFont methodsFor: 'emphasis' stamp: 'tak 3/11/2005 17:09'!\\nreset\\n\\t\\\"Reset the cache of derivative emphasized fonts\\\"\\n\\n\\t| style font |\\n\\tfallbackFont class = FixedFaceFont\\n\\t\\tifTrue: [fallbackFont _ nil].\\n\\tderivativeFonts _ Array new: 32.\\n\\t#('B' 'I' 'BI') doWithIndex:\\n\\t\\t[:tag :index | \\n\\t\\t(style _ TextStyle named: self familyName) ifNotNil:\\n\\t\\t\\t[(font _ style fontArray\\n\\t\\t\\t\\tdetect: [:each | each name = (self name , tag)]\\n\\t\\t\\t\\tifNone: [nil]) ifNotNil: [derivativeFonts at: index put: font]]]! !\\n\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:50'!\\nbuildfontNamed: nm fromForms: forms startingAtAscii: startAscii\\n\\tascent: a descent: d maxWid: m\\n\\t\\\"This builds a StrikeFont instance from existing forms.\\\"\\n\\n\\t| lastAscii width ascii charForm missingForm tempGlyphs |\\n\\tname _ nm.\\n\\tascent _ 11.\\n\\tdescent _ 3.\\n\\tmaxWidth _ 16.\\n\\tpointSize _ 8.\\n\\tname _ (name copyWithout: Character space) ,\\n\\t\\t\\t\\t(pointSize < 10\\n\\t\\t\\t\\t\\tifTrue: ['0' , pointSize printString]\\n\\t\\t\\t\\t\\tifFalse: [pointSize printString]).\\n\\tminAscii _ 258.\\n\\tmaxAscii _ 0.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\ttype _ 0. \\\"ignored for now\\\"\\n\\n\\ttempGlyphs _ Form extent: (maxWidth*257) @ self height.\\n\\txTable _ (Array new: 258) atAllPut: 0.\\n\\txTable at: 1 put: 0.\\n\\n\\t\\\"Read character forms and blt into tempGlyphs\\\"\\n\\tlastAscii _ -1.\\n\\t1 to: forms size do:\\n\\t\\t[:i | charForm _ forms at: i. width _ charForm width.\\n\\t\\tascii _ startAscii-1+i.\\n\\t\\tself displayChar: ascii form: charForm.\\n\\t\\tascii = 256\\n\\t\\t\\tifTrue: [missingForm _ charForm deepCopy]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t[minAscii _ minAscii min: ascii.\\n\\t\\t\\tmaxAscii _ maxAscii max: ascii.\\n\\t\\t\\tlastAscii+1 to: ascii-1 do: [:as | xTable at: as+2 put: (xTable at: as+1)].\\n\\t\\t\\ttempGlyphs copy: ((xTable at: ascii+1)@0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\textent: charForm extent)\\n\\t\\t\\t\\t\\t\\tfrom: 0@0 in: charForm rule: Form over.\\n\\t\\t\\txTable at: ascii+2 put: (xTable at: ascii+1) + width.\\n\\t\\t\\tlastAscii _ ascii]].\\n\\tlastAscii+1 to: maxAscii+1 do: [:as | xTable at: as+2 put: (xTable at: as+1)].\\n\\tmissingForm == nil ifFalse:\\n\\t\\t[tempGlyphs copy: missingForm boundingBox from: missingForm\\n\\t\\t\\t\\tto: (xTable at: maxAscii+2)@0 rule: Form over.\\n\\t\\txTable at: maxAscii+3 put: (xTable at: maxAscii+2) + missingForm width].\\n\\tglyphs _ Form extent: (xTable at: maxAscii+3) @ self height.\\n\\tglyphs copy: glyphs boundingBox from: 0@0 in: tempGlyphs rule: Form over.\\n\\txTable _ xTable copyFrom: 1 to: maxAscii+3.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\ndisplayChar: ascii form: charForm\\n\\t\\\"Convenience utility used during conversion of BitFont files\\\"\\n\\t| m bigForm |\\n\\tDisplay fillBlack: (0@0 extent: 20@14).\\n\\tascii printString displayAt: 0@2.\\n\\tcharForm width > 0 ifTrue:\\n\\t\\t[m _ 5.\\n\\t\\tbigForm _ charForm magnify: charForm boundingBox by: m@m.\\n\\t\\tDisplay border: ((bigForm boundingBox expandBy: m) translateBy: 50@2) width: m.\\n\\t\\tbigForm displayAt: 50@2.\\n\\t\\tDisplay fillBlack: ((50@2)+((m*charForm width)@0) extent: 1@(m*self height))].! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'md 11/14/2003 17:25'!\\nnewFromStrike: fileName\\n\\t\\\"Build an instance from the strike font file name. The '.strike' extension\\n\\tis optional.\\\"\\n\\n\\t| strike startName raster16 |\\n\\tname _ fileName copyUpTo: $..\\t\\\"assumes extension (if any) is '.strike'\\\"\\n\\tstrike _ FileStream readOnlyFileNamed: name, '.strike.'.\\n\\tstrike binary.\\n\\n\\t\\\"strip off direcory name if any\\\"\\n\\tstartName _ name size.\\n\\t[startName > 0 and: [((name at: startName) ~= $>) & ((name at: startName) ~= $])]]\\n\\t\\twhileTrue: [startName _ startName - 1].\\n\\tname _ name copyFrom: startName+1 to: name size.\\n\\n\\ttype\\t\\t\\t_\\t\\tstrike nextWord.\\t\\t\\\"type is ignored now -- simplest\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tassumed. Kept here to make\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twriting and consistency more\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstraightforward.\\\"\\n\\tminAscii\\t\\t_\\t\\tstrike nextWord.\\n\\tmaxAscii\\t\\t_\\t\\tstrike nextWord.\\n\\tmaxWidth\\t\\t_\\t\\tstrike nextWord.\\n\\tstrikeLength\\t_\\t\\tstrike nextWord.\\n\\tascent\\t\\t\\t_\\t\\tstrike nextWord.\\n\\tdescent\\t\\t\\t_\\t\\tstrike nextWord.\\n\\t\\\"xOffset\\t\\t\\t_\\\"\\t\\tstrike nextWord. \\t\\n\\traster16\\t\\t\\t_\\t\\tstrike nextWord.\\t\\n\\tsuperscript\\t\\t_\\t\\tascent - descent // 3.\\t\\n\\tsubscript\\t\\t_\\t\\tdescent - ascent // 3.\\t\\n\\temphasis\\t\\t_\\t\\t0.\\n\\tglyphs\\t\\t\\t_\\tForm extent: (raster16 * 16) @ (self height) \\n\\t\\t\\t\\t\\t\\t\\toffset: 0@0.\\n\\t\\tglyphs bits fromByteStream: strike.\\n\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | xTable at: index put: strike nextWord].\\n\\n\\t\\\"Set up space character\\\"\\n\\t((xTable at: (Space asciiValue + 2)) = 0 or:\\n\\t\\t\\t[(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))])\\n\\t\\tifTrue:\\t[(Space asciiValue + 2) to: xTable size do:\\n\\t\\t\\t\\t\\t[:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]].\\n\\tstrike close.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'tk 9/28/2000 15:50'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to a known Font in the other system instead. \\\"\\n\\n\\t\\\"A path to me\\\"\\n\\t(TextConstants at: #forceFontWriting ifAbsent: [false]) ifTrue: [^ self].\\n\\t\\t\\\"special case for saving the default fonts on the disk. See collectionFromFileNamed:\\\"\\n\\n\\tdp _ DiskProxy global: #StrikeFont selector: #familyName:size:emphasized:\\n\\t\\t\\targs: (Array with: self familyName with: self height\\n\\t\\t\\t\\t\\twith: self emphasis).\\n\\trefStrm replace: self with: dp.\\n\\t^ dp! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'sma 6/1/2000 09:32'!\\nprintOn: aStream\\n\\tsuper printOn: aStream.\\n\\taStream\\n\\t\\tnextPut: $(;\\n\\t\\tnextPutAll: self name;\\n\\t\\tspace;\\n\\t\\tprint: self height;\\n\\t\\tnextPut: $)! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 10/25/2005 00:21'!\\nreadBDFFromFile: fileName name: aString \\n\\t\\\"This builds a StrikeFont instance by reading the X11 Binary \\n\\tDistribution Format font source file. See the BDFFontReader class\\n\\tcomment.\\\"\\n\\n\\t\\\"StrikeFont new readBDFFromFile: 'helvR12' name: 'Helvetica12'.\\\"\\n\\n\\t| fontReader stream |\\n\\tfontReader := BDFFontReader openFileNamed: fileName.\\n\\tstream := ReadStream on: fontReader read.\\n\\txTable := stream next.\\n\\tglyphs := stream next.\\n\\tminAscii := stream next.\\n\\tmaxAscii := stream next.\\n\\tmaxWidth := stream next.\\n\\tascent := stream next.\\n\\tdescent := stream next.\\n\\tpointSize := stream next.\\n\\tname := aString.\\n\\\"\\txTable size <= 256 ifTrue: [self setStopConditions].\\\"\\n\\ttype := 0.\\t\\\"no one see this\\\"\\n\\tsuperscript := (ascent - descent) // 3.\\n\\tsubscript := (descent - ascent) // 3.\\n\\temphasis := 0.\\n\\tself reset! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\nreadBFHeaderFrom: f\\n\\tname _ self restOfLine: 'Font name = ' from: f.\\n\\tascent _ (self restOfLine: 'Ascent = ' from: f) asNumber.\\n\\tdescent _ (self restOfLine: 'Descent = ' from: f) asNumber.\\n\\tmaxWidth _ (self restOfLine: 'Maximum width = ' from: f) asNumber.\\n\\tpointSize _ (self restOfLine: 'Font size = ' from: f) asNumber.\\n\\tname _ (name copyWithout: Character space) ,\\n\\t\\t\\t\\t(pointSize < 10\\n\\t\\t\\t\\t\\tifTrue: ['0' , pointSize printString]\\n\\t\\t\\t\\t\\tifFalse: [pointSize printString]).\\n\\tminAscii _ 258.\\n\\tmaxAscii _ 0.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\ttype _ 0. \\\"ignored for now\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 11/30/2003 17:08'!\\nreadEFontBDFForJapaneseFromFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: fontReader rangesForJapanese overrideWith: otherFileName otherRanges: {Array with: 8481 with: 12320} additionalOverrideRange: fontReader additionalRangesForJapanese).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 1/15/2004 16:48'!\\nreadEFontBDFForKoreanFromFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: fontReader rangesForKorean overrideWith: otherFileName otherRanges: {Array with: 8481 with: 12320} additionalOverrideRange: fontReader additionalRangesForKorean).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 12/28/2002 21:02'!\\nreadEFontBDFFromFile: fileName name: aString rangeFrom: startRange to: endRange\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReader readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readFrom: startRange to: endRange).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 1/19/2005 11:22'!\\nreadEFontBDFFromFile: fileName name: aString ranges: ranges\\n\\n\\t| fontReader stream |\\n\\tfontReader _ EFontBDFFontReaderForRanges readOnlyFileNamed: fileName.\\n\\tstream _ ReadStream on: (fontReader readRanges: ranges).\\n\\txTable _ stream next.\\n\\tglyphs _ stream next.\\n\\tminAscii _ stream next.\\n\\tmaxAscii _ stream next.\\n\\tmaxWidth _ stream next.\\n\\tascent _ stream next.\\n\\tdescent _ stream next.\\n\\tpointSize _ stream next.\\n\\tname _ aString.\\n\\ttype _ 0. \\\"no one see this\\\"\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ 0.\\n\\tself reset.\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'yo 9/23/2002 16:30'!\\nreadF12FromStream: aStream\\n\\n\\t| box blt |\\n\\tminAscii _ 0.\\n\\tmaxAscii _ 94*94.\\n\\tascent _ 12.\\n\\tdescent _ 0.\\n\\tpointSize _ 12.\\n\\tsuperscript _ 0.\\n\\tsubscript _ 0.\\n\\temphasis _ 0.\\n\\tmaxWidth _ 12.\\n\\t\\n\\tbox _ Form extent: 12@12.\\n\\tglyphs _ Form extent: (94*94*12)@12.\\n\\tblt _ BitBlt toForm: glyphs. \\n\\txTable _ XTableForFixedFont new.\\n\\txTable maxAscii: maxAscii + 3.\\n\\txTable width: 12.\\n\\t1 to: 256 do: [:index | \\n\\t\\t1 to: 12 do: [:i |\\n\\t\\t\\taStream next.\\n\\t\\t].\\n\\t].\\n\\t(minAscii + 1 to: 94*94) do: [:index | \\n\\t\\tself readCharacter: (box bits) from: aStream.\\n\\t\\tblt copy: ((12*(index-1))@0 extent: 12@12) from: 0@0 in: box.\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:50'!\\nreadFromBitFont: fileName\\n\\t\\\"This builds a StrikeFont instance by reading the data file format\\n\\tproduced by BitFont, a widely available font conversion utility\\n\\twritten by Peter DiCamillo at Brown University\\\"\\n\\t\\\"StrikeFont new readFromBitFont: 'Palatino10.BF' \\\"\\n\\t| f lastAscii charLine width ascii charForm line missingForm tempGlyphs iRect p rectLine left tokens right |\\n\\tf _ FileStream readOnlyFileNamed: fileName.\\n\\tself readBFHeaderFrom: f.\\n\\n\\t\\\"NOTE: if font has been scaled (and in any case),\\n\\tthe REAL bitmap dimensions come after the header.\\\"\\n\\tself restOfLine: 'Extent information for entire font' from: f.\\n\\t\\\"Parse the following line (including mispelling!!)\\\"\\n\\t\\\"Image rectange: left = -2, right = 8, bottom = -2, top = 7\\\"\\n\\ttokens _ (f upTo: Character cr) findTokens: ' '.\\n\\tiRect _ Rectangle left: (tokens at: 5) asNumber right: (tokens at: 8) asNumber\\n\\t\\t\\t\\ttop: (tokens at: 14) asNumber bottom: (tokens at: 11) asNumber.\\n\\tascent _ iRect top.\\n\\tdescent _ iRect bottom negated.\\n\\t\\n\\ttempGlyphs _ Form extent: (maxWidth*257) @ self height.\\n\\txTable _ (Array new: 258) atAllPut: 0.\\n\\txTable at: 1 put: 0.\\n\\n\\t\\\"Read character forms and blt into tempGlyphs\\\"\\n\\tlastAscii _ -1.\\n\\t[charLine _ self restOfLine: 'Character: ' from: f.\\n\\tcharLine == nil ifFalse:\\n\\t\\t[p _ f position.\\n\\t\\trectLine _ f upTo: Character cr.\\n\\t\\t(rectLine beginsWith: 'Image rectange: left = ')\\n\\t\\t\\tifTrue: [tokens _ rectLine findTokens: ' '.\\n\\t\\t\\t\\t\\tleft _ (tokens at: 5) asNumber. right _ (tokens at: 8) asNumber]\\n\\t\\t\\tifFalse: [left _ right _ 0. f position: p].\\n\\t\\twidth_ (self restOfLine: 'Width (final pen position) = ' from: f) asNumber - left\\n\\t\\t\\t\\t\\tmax: (right-left+1).\\n\\t\\t(charLine beginsWith: 'Missing character') ifTrue: [ascii _ 256].\\n\\t\\t('x''*' match: charLine) ifTrue:\\n\\t\\t\\t[ascii _ Number readFrom: (charLine copyFrom: 3 to: 4) asUppercase base: 16].\\n\\t\\tcharForm _ Form extent: width@self height.\\n\\t\\t('*[all blank]' match: charLine) ifFalse:\\n\\t\\t\\t[self restOfLine: ' +' from: f.\\n\\t\\t\\t1 to: self height do:\\n\\t\\t\\t\\t[:y | line _ f upTo: Character cr.\\n\\t\\t\\t\\t4 to: (width + 3 min: line size + iRect left - left) do:\\n\\t\\t\\t\\t\\t[:x | (line at: x - iRect left + left) = $*\\n\\t\\t\\t\\t\\t\\tifTrue: [charForm pixelValueAt: (x-4)@(y-1) put: 1]]]]].\\n\\tcharLine == nil]\\n\\t\\twhileFalse:\\n\\t\\t\\t[self displayChar: ascii form: charForm.\\n\\t\\t\\tascii = 256\\n\\t\\t\\t\\tifTrue: [missingForm _ charForm deepCopy]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[minAscii _ minAscii min: ascii.\\n\\t\\t\\t\\tmaxAscii _ maxAscii max: ascii.\\n\\t\\t\\t\\tlastAscii+1 to: ascii-1 do: [:a | xTable at: a+2 put: (xTable at: a+1)].\\n\\t\\t\\t\\ttempGlyphs copy: ((xTable at: ascii+1)@0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\textent: charForm extent)\\n\\t\\t\\t\\t\\t\\t\\tfrom: 0@0 in: charForm rule: Form over.\\n\\t\\t\\t\\txTable at: ascii+2 put: (xTable at: ascii+1) + width.\\n\\t\\t\\t\\tlastAscii _ ascii]].\\n\\tf close.\\n\\tlastAscii+1 to: maxAscii+1 do: [:a | xTable at: a+2 put: (xTable at: a+1)].\\n\\tmissingForm == nil ifFalse:\\n\\t\\t[tempGlyphs copy: missingForm boundingBox from: missingForm\\n\\t\\t\\t\\tto: (xTable at: maxAscii+2)@0 rule: Form over.\\n\\t\\txTable at: maxAscii+3 put: (xTable at: maxAscii+2) + missingForm width].\\n\\tglyphs _ Form extent: (xTable at: maxAscii+3) @ self height.\\n\\tglyphs copy: glyphs boundingBox from: 0@0 in: tempGlyphs rule: Form over.\\n\\txTable _ xTable copyFrom: 1 to: maxAscii+3.\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:53'!\\nreadFromStrike2Stream: file \\n\\t\\\"Build an instance from the supplied binary stream on data in strike2 format\\\"\\n\\ttype _ file nextInt32. type = 2 ifFalse: [file close. self error: 'not strike2 format'].\\n\\tminAscii _ file nextInt32.\\n\\tmaxAscii _ file nextInt32.\\n\\tmaxWidth _ file nextInt32.\\n\\tascent _ file nextInt32.\\n\\tdescent _ file nextInt32.\\n\\tpointSize _ file nextInt32.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\temphasis _ file nextInt32.\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | xTable at: index put: file nextInt32].\\n\\tglyphs _ Form new readFrom: file.\\n\\n\\t\\\"Set up space character\\\"\\n\\t((xTable at: (Space asciiValue + 2)) = 0 or:\\n\\t\\t\\t[(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))])\\n\\t\\tifTrue:\\t[(Space asciiValue + 2) to: xTable size do:\\n\\t\\t\\t\\t\\t[:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]].\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'sma 12/30/1999 14:20'!\\nreadFromStrike2: fileName \\\"StrikeFont new readFromStrike2: 'Palatino14.sf2'\\\"\\n\\t\\\"Build an instance from the strike font stored in strike2 format.\\n\\tfileName is of the form: <family name><pointSize>.sf2\\\"\\n\\t| file |\\n\\t('*.sf2' match: fileName) ifFalse: [self halt. \\\"likely incompatible\\\"].\\n\\tname _ fileName copyUpTo: $. . \\\"Drop filename extension\\\"\\n\\tfile _ FileStream readOnlyFileNamed: fileName.\\n\\tfile binary.\\n\\t[self readFromStrike2Stream: file] ensure: [file close]! !\\n\\n!StrikeFont methodsFor: 'file in/out'!\\nrestOfLine: leadString from: file\\n\\t\\\"Utility method to assist reading of BitFont data files\\\"\\n\\t| line |\\n\\t[line _ file upTo: Character cr.\\n\\tline size < leadString size or: [leadString ~= (line copyFrom: 1 to: leadString size)]]\\n\\twhileTrue: [file atEnd ifTrue: [^ nil]].\\n\\t^ line copyFrom: leadString size+1 to: line size! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ls 4/11/2000 18:57'!\\nwriteAsStrike2named: fileName\\n\\t\\\"Write me onto a file in strike2 format.\\n\\tfileName should be of the form: <family name><pointSize>.sf2\\\"\\n\\t| file |\\n\\tfile _ FileStream fileNamed: fileName.\\n\\tself writeAsStrike2On: file.\\n\\tfile close.! !\\n\\n!StrikeFont methodsFor: 'file in/out' stamp: 'ls 3/27/2000 17:43'!\\nwriteAsStrike2On: file\\n\\t\\\"Write me onto a file in strike2 format.\\n\\tfileName should be of the form: <family name><pointSize>.sf2\\\"\\n\\tfile binary.\\n\\tfile nextInt32Put: 2.\\n\\tfile nextInt32Put: minAscii.\\n\\tfile nextInt32Put: maxAscii.\\n\\tfile nextInt32Put: maxWidth.\\n\\tfile nextInt32Put: ascent.\\n\\tfile nextInt32Put: descent.\\n\\tfile nextInt32Put: pointSize.\\n\\tsuperscript _ ascent - descent // 3.\\t\\n\\tsubscript _ descent - ascent // 3.\\t\\n\\tfile nextInt32Put: emphasis.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | file nextInt32Put: (xTable at: index)].\\n\\tglyphs writeOn: file.\\n\\tfile close.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\naComment\\n\\t\\\"To read Mac font resources. \\n1) 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).\\n2) Open the FOND resource and scroll down to the list of sizes and resource numbers. Note the resource number of the size you want.\\n3) Open the NFNT resource. Click on the number you have noted.\\n4) Choose 'Open Using Hex Editor' from the resource editor.\\n5) 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).\\n6) Enter the fileName below and execute: \\n\\nTextStyle default fontAt: 8 put: (StrikeFont new readMacFontHex: 'fileName').\\n\\nSelect text and type Command-7 to change it to your new font.\\n\\n(There is some problem in the ParagraphEditor with the large size of Cairo 18. Its line heights are not the right.)\\n\\t\\\"! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nfixKerning: extraWidth\\n\\t\\\"Insert one pixel (extraWidth) between each character. And add the bits for the space character\\\"\\n\\t\\\"Create a space character Form. Estimate width by ascent / 2 - 1\\\"\\n\\t| characterForm char leftX |\\n\\tcharacterForm _ Form extent: (ascent//2 - 1) @ self height.\\n\\tself characterFormAt: $ put: characterForm.\\n\\n\\t\\\"Put one pixel of space after every character. Mac fonts have no space in the bitmap.\\\"\\n\\textraWidth <= 0 ifTrue: [^ self].\\n\\tminAscii to: maxAscii do: [:ascii |\\n\\t\\tchar _ Character value: ascii.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\tcharacterForm _ Form extent: \\n\\t\\t\\t((self widthOf: char) + extraWidth) @ self height.\\n\\t\\tcharacterForm \\n\\t\\t\\tcopy: (characterForm boundingBox extendBy: \\n\\t\\t\\t\\t(0-extraWidth@0))\\n\\t\\t\\tfrom: leftX@0 in: glyphs rule: Form over.\\n\\t\\tself characterFormAt: char put: characterForm.\\n\\t\\t].\\t! !\\n\\n!StrikeFont methodsFor: 'Mac reader' stamp: 'ar 5/23/2000 12:49'!\\nreadMacFontHex: fileName\\n\\t\\\"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\\\"\\n\\t| file hh fRectWidth |\\n\\tname _ fileName.\\t\\\"Palatino 12\\\"\\n\\tfile _ FileStream readOnlyFileNamed: fileName, ' hex'.\\n\\n\\t\\\"See Inside Macintosh page IV-42 for this record\\\"\\n\\t\\\"FontType _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\temphasis\\t\\t_\\t\\t0.\\n\\tminAscii _ Number readFrom: (file next: 4) base: 16.\\n\\tmaxAscii _ Number readFrom: (file next: 4) base: 16.\\n\\tmaxWidth\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"kernMax _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\t\\\"NDescent _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\tfRectWidth _ Number readFrom: (file next: 4) base: 16.\\n\\thh _ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"OWTLoc _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\tascent\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\tdescent\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\t\\\"leading _ \\\" Number readFrom: (file next: 4) base: 16.\\n\\txOffset\\t\\t\\t_\\t\\t0. \\t\\n\\traster\\t\\t\\t_ Number readFrom: (file next: 4) base: 16.\\n\\n\\tstrikeLength\\t_\\t\\traster*16.\\n\\tsuperscript\\t\\t_\\t\\tascent - descent // 3.\\t\\n\\tsubscript\\t\\t_\\t\\tdescent - ascent // 3.\\t\\n\\tself strikeFromHex: file width: raster height: hh.\\n\\tself xTableFromHex: file.\\n\\tfile close.\\n\\n\\t\\\"Insert one pixel between each character. And add space character.\\\"\\n\\tself fixKerning: (fRectWidth - maxWidth).\\t\\n\\n\\t\\\"Recompute character to glyph mapping\\\"\\n\\tcharacterToGlyphMap _ nil.! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nstrikeFromHex: file width: w height: h\\n\\t\\\"read in just the raw strike bits from a hex file. No spaces or returns. W is in words (2 bytes), h in pixels.\\\" \\n\\t| newForm theBits offsetX offsetY str num cnt |\\n\\toffsetX _ 0.\\n\\toffsetY _ 0.\\n\\toffsetX > 32767 ifTrue: [offsetX _ offsetX - 65536]. \\\"stored two's-complement\\\"\\n\\toffsetY > 32767 ifTrue: [offsetY _ offsetY - 65536]. \\\"stored two's-complement\\\"\\n\\tnewForm _ Form extent: strikeLength @ h offset: offsetX @ offsetY.\\n\\ttheBits _ newForm bits.\\n\\tcnt _ 0.\\t\\t\\\"raster may be 16 bits, but theBits width is 32\\\" \\n\\t1 to: theBits size do: [:i | \\n\\t\\t(cnt _ cnt + 32) > strikeLength \\n\\t\\t ifTrue: [cnt _ 0.\\n\\t\\t\\tnum _ Number readFrom: (str _ file next: 4) base: 16]\\n\\t\\t ifFalse: [\\n\\t\\t\\tcnt = strikeLength ifTrue: [cnt _ 0].\\n\\t\\t\\tnum _ Number readFrom: (str _ file next: 8) base: 16].\\n\\t\\ttheBits at: i put: num].\\n\\tglyphs _ newForm.! !\\n\\n!StrikeFont methodsFor: 'Mac reader'!\\nxTableFromHex: file\\n\\n\\t| strike num str wid |\\n\\tstrike _ file.\\n\\txTable _ (Array new: maxAscii + 3) atAllPut: 0.\\n\\t(minAscii + 1 to: maxAscii + 3) do:\\n\\t\\t[:index | \\n\\t\\t\\tnum _ Number readFrom: (str _ strike next: 4) base: 16. \\n\\t\\t\\txTable at: index put: num].\\n\\n\\t1 to: xTable size - 1 do: [:ind |\\n\\t\\twid _ (xTable at: ind+1) - (xTable at: ind).\\n\\t\\t(wid < 0) | (wid > 40) ifTrue: [\\n\\t\\t\\tfile close.\\n\\t\\t\\tself error: 'illegal character width']].\\n! !\\n\\n\\n!StrikeFont methodsFor: 'make arrows' stamp: 'sps 10/15/2003 17:06'!\\nmakeAssignArrow\\n\\\"Replace the underline character with an arrow for this font\\\"\\n\\n\\t| arrowForm arrowCanvas arrowY arrowLeft arrowRight arrowHeadLength |\\n\\n\\tarrowForm _ (self characterFormAt: $_) copy.\\n\\tarrowCanvas _ arrowForm getCanvas.\\n\\tarrowCanvas fillColor: Color white.\\n\\tarrowY _ arrowForm height // 2.\\n\\tarrowLeft _ 0. \\n\\tarrowRight _ arrowForm width - 2.\\n\\tarrowHeadLength _ (arrowRight - arrowLeft) * 2 // 5.\\n\\t\\\"Draw the lines\\\"\\n\\tarrowCanvas line: (arrowLeft@arrowY) to: (arrowRight@arrowY) color: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowLeft@arrowY) \\n\\t\\tto: ((arrowLeft + arrowHeadLength)@(arrowY - arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowLeft@arrowY) \\n\\t\\tto: ((arrowLeft + arrowHeadLength)@(arrowY + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\n\\t\\\"Replace the glyph\\\"\\n\\tself characterFormAt: $_ put: arrowForm.\\n\\n! !\\n\\n!StrikeFont methodsFor: 'make arrows' stamp: 'sps 10/15/2003 17:06'!\\nmakeReturnArrow\\n\\\"Replace the caret character with an arrow\\\"\\n\\n\\t| arrowForm arrowCanvas arrowHeadLength arrowX arrowTop arrowBottom |\\n\\n\\tarrowForm _ (self characterFormAt: $^) copy.\\n\\tarrowCanvas _ arrowForm getCanvas.\\n\\tarrowCanvas fillColor: Color white.\\n\\n\\tarrowHeadLength _ ((arrowForm width - 2)// 2).\\n\\tarrowX _ (arrowHeadLength max: (arrowForm width // 2)).\\n\\tarrowTop _ arrowForm height // 4. \\n\\tarrowBottom _ (arrowTop + (arrowForm width * 4 // 5 )).\\n\\tarrowBottom _ (arrowBottom min: arrowForm height) max: (arrowForm height * 2 // 3).\\n\\n\\t\\\"Draw the lines\\\"\\n\\tarrowCanvas line: (arrowX@arrowTop) to: (arrowX@arrowBottom) color: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowX@arrowTop) \\n\\t\\tto: ((arrowX - arrowHeadLength)@(arrowTop + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\tarrowCanvas \\n\\t\\tline: (arrowX@arrowTop) \\n\\t\\tto: ((arrowX + arrowHeadLength)@(arrowTop + arrowHeadLength)) \\n\\t\\tcolor: Color black.\\n\\n\\t\\\"Replace the glyph\\\"\\n\\tself characterFormAt: $^ put: arrowForm.\\n\\n! !\\n\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 3/18/2004 00:10'!\\nfixAccuISO8859From: aStrikeFont\\n\\n\\t| f |\\n\\tself reset.\\n\\txTable _ aStrikeFont xTable copy.\\n\\tglyphs _ Form extent: aStrikeFont glyphs extent.\\n\\tmaxAscii _ 255.\\n\\tminAscii _ 0.\\n\\t\\\"stopConditions _ nil.\\\"\\n\\n\\t0 to: 127 do: [:i |\\n\\t\\tf _ aStrikeFont characterFormAt: (Character value: i) isoToSqueak.\\n\\t\\tf width = 0 ifTrue: [f _ Form extent: 1@f height].\\n\\t\\t\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t128 to: 159 do: [:i |\\n\\t\\tf _ Form extent: 1@f height.\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t160 to: 255 do: [:i |\\n\\t\\tf _ aStrikeFont characterFormAt: (Character value: i) isoToSqueak.\\n\\t\\tf width = 0 ifTrue: [f _ Form extent: 1@f height].\\n\\t\\t\\n\\t\\tself characterFormAt: (Character value: i) put: f.\\n\\t].\\n\\t\\t\\n\\t^ self.\\t\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 11/12/2002 12:56'!\\nfixAscent: a andDescent: d head: h\\n\\n\\t| bb newGlyphs |\\n\\t\\\"(a + d) = (ascent + descent) ifTrue: [\\\"\\n\\t\\tascent _ a.\\n\\t\\tdescent _ d.\\n\\t\\tnewGlyphs _ Form extent: (glyphs width@(h + glyphs height)).\\n\\t\\tbb _ BitBlt toForm: newGlyphs.\\n\\t\\tbb copy: (0@h extent: (glyphs extent)) from: 0@0 in: glyphs\\n\\t\\t\\tfillColor: nil rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\\"].\\\"\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 9/16/2002 15:07'!\\nfixForISO8859From: aStrikeFont\\n\\n\\t| fixer m mappingTable |\\n\\tfixer _ StrikeFontFixer newOn: aStrikeFont.\\n\\tself reset.\\n\\txTable _ aStrikeFont xTable copy.\\n\\tglyphs _ Form extent: aStrikeFont glyphs extent.\\n\\tmaxAscii _ 255.\\n\\tminAscii _ 0.\\n\\tmappingTable _ fixer mappingTable.\\n\\t\\\"stopConditions _ nil.\\\"\\n\\n\\t0 to: 255 do: [:i |\\n\\t\\t(m _ mappingTable at: i+1) ~= nil ifTrue: [\\n\\t\\t\\tself characterFormAt: (Character value: i)\\n\\t\\t\\t\\tput: (aStrikeFont characterFormAt: (Character value: m)).\\n\\t\\t] ifFalse: [\\n\\t\\t\\tself characterFormAt: (Character value: i)\\n\\t\\t\\t\\tput: (aStrikeFont characterFormAt: (Character space)).\\n\\t\\t]\\n\\t].\\n\\t^self.\\t\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 8/28/2002 16:35'!\\nfixXTable\\n\\n\\t| newXTable val |\\n\\txTable size >= 258 ifTrue: [\\n\\t\\t^ self.\\n\\t].\\n\\n\\tnewXTable _ Array new: 258.\\n\\t1 to: xTable size do: [:i |\\n\\t\\tnewXTable at: i put: (xTable at: i).\\n\\t].\\n\\n\\tval _ xTable at: (xTable size).\\n\\t\\n\\txTable size + 1 to: 258 do: [:i |\\n\\t\\tnewXTable at: i put: val.\\n\\t].\\n\\tminAscii _ 0.\\n\\tmaxAscii _ 255.\\n\\txTable _ newXTable.\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 1/6/2005 04:18'!\\nhasGlyphOf: aCharacter\\n\\n\\t| code |\\n\\tcode _ aCharacter charCode.\\n\\t((code between: self minAscii and: self maxAscii) not) ifTrue: [\\n\\t\\t^ false.\\n\\t].\\n\\t(xTable at: code + 1) < 0 ifTrue: [\\n\\t\\t^ false.\\n\\t].\\n\\t^ true.\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 8/28/2002 16:37'!\\nreadCharacter: aBits from: aStream\\n\\n\\t| pos |\\n\\tpos _ 0.\\n\\t12 timesRepeat: [\\n\\t\\t1 to: 2 do: [ :w |\\n\\t\\t\\taBits byteAt: (pos+w) put: (aStream next ). \\n\\t\\t].\\n\\t\\tpos _ pos + 4.\\n\\t].\\n! !\\n\\n!StrikeFont methodsFor: 'multibyte character methods' stamp: 'yo 5/24/2004 23:11'!\\nsetupDefaultFallbackFont\\n\\n\\t| fonts f |\\n\\tfonts _ TextStyle default fontArray.\\n\\tf _ fonts first.\\n\\t1 to: fonts size do: [:i |\\n\\t\\tself height > (fonts at: i) height ifTrue: [f _ fonts at: i].\\n\\t].\\n\\tself fallbackFont: f.\\n\\tself reset.\\n\\n! !\\n\\n\\n!StrikeFont methodsFor: 'testing'!\\ncheckCharacter: character \\n\\t\\\"Answer a Character that is within the ascii range of the receiver--either \\n\\tcharacter or the last character in the receiver.\\\"\\n\\n\\t| ascii | \\n\\tascii _ character asciiValue.\\n\\t((ascii < minAscii) or: [ascii > maxAscii])\\n\\t\\t\\tifTrue: [^maxAscii asCharacter]\\n\\t\\t\\tifFalse:\\t[^character]\\n! !\\n\\n\\n!StrikeFont methodsFor: '*nebraska-file in/out' stamp: 'yo 12/17/2005 20:36'!\\nencodedForRemoteCanvas\\n\\n\\t| stream |\\n\\tstream := RWBinaryOrTextStream on: ''.\\n\\tstream nextPutAll: self familyName.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self name.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self height.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self emphasis asString.\\n\\t^ stream contents asString.\\n! !\\n\\n\\n!StrikeFont methodsFor: 'private' stamp: 'yo 3/11/2005 07:38'!\\ncreateCharacterToGlyphMap\\n \\\"Private. Create the character to glyph mapping for a font that didn't have any before. This is basically equivalent to what the former setStopCondition did, only based on indexes.\\\"\\n\\n maxAscii < 256 ifTrue: [^ (1 to: 256) collect: [:i | i - 1]].\\n ^ nil.\\n! !\\n\\n!StrikeFont methodsFor: 'private' stamp: 'yo 5/20/2004 10:51'!\\nleftAndRighOrNilFor: char\\n\\n\\t| code leftX |\\n\\tcode _ char charCode.\\n\\t((code between: self minAscii and: self maxAscii) not) ifTrue: [\\n\\t\\tcode _ $? charCode.\\n\\t].\\n\\tleftX _ xTable at: code + 1.\\n\\tleftX < 0 ifTrue: [\\n\\t\\tcode _ $? charCode.\\n\\t\\tleftX _ xTable at: code + 1.\\n\\t].\\n\\t^ Array with: leftX with: (xTable at: code + 2).\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFont class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'nk 9/1/2004 11:00'!\\nactualFamilyNames\\n\\t\\\"Answer a sorted list of actual family names, without the Default aliases\\\"\\n\\n\\t^(self familyNames copyWithoutAll: TextStyle defaultFamilyNames) asOrderedCollection! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'ar 2/3/2002 23:04'!\\nfamilyName: aName pointSize: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\n\\t^ ((TextStyle named: aName asSymbol) ifNil: [TextStyle default]) fontOfPointSize: aSize! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'ar 11/25/2004 15:19'!\\nfamilyName: aName size: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\t| style |\\n\\tstyle := TextStyle named: aName asSymbol.\\n\\tstyle ifNil: [^(FontSubstitutionDuringLoading forFamilyName: aName pixelSize: aSize)\\n\\t\\t\\tsignal: 'missing font' ].\\n\\t^style fontOfSize: aSize! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'sma 12/30/1999 13:48'!\\nfamilyNames\\n\\t^ (TextConstants select: [:each | each isKindOf: TextStyle]) keys asSortedCollection! !\\n\\n!StrikeFont class methodsFor: 'accessing' stamp: 'tak 11/11/2004 21:14'!\\nsetupDefaultFallbackFont\\n\\\"\\n\\tStrikeFont setupDefaultFallbackFont\\n\\\"\\n\\n\\t(#(#Accuat #Accujen #Accula #Accumon #Accusf #Accushi #Accuve #Atlanta) collect: [:e | TextStyle named: e]) do: [:style |\\n\\t\\tstyle fontArray do: [:e |\\n\\t\\t\\te reset.\\n\\t\\t\\te setupDefaultFallbackFont.\\n\\t\\t].\\n\\t].\\n\\tTTCFont allSubInstances\\n\\t\\tdo: [:font | font reset.\\n\\t\\t\\tfont setupDefaultFallbackFont]\\n\\n! !\\n\\n\\n!StrikeFont class methodsFor: 'derivative font caching' stamp: 'tak 3/11/2005 16:27'!\\nshutDown \\\"StrikeFont shutDown\\\"\\n\\t\\\"Deallocate synthetically derived copies of base fonts to save space\\\"\\n\\tself allSubInstancesDo: [:sf | sf reset].\\n\\tStrikeFontSet allSubInstancesDo: [:sf | sf reset].\\n\\tDefaultStringScanner _ nil.\\n! !\\n\\n\\n!StrikeFont class methodsFor: 'examples'!\\nconvertFontsNamed: familyName \\\" StrikeFont convertFontsNamed: 'NewYork' \\\"\\n\\t\\\"This utility is for use after you have used BitFont to produce data files \\n\\tfor the fonts you wish to use. It will read the BitFont files and then \\n\\twrite them out in strike2 (*.sf2) format which is much more compact,\\n\\tand which can be read in again very quickly.\\\"\\n\\t\\\"For this utility to work as is, the BitFont data files must be named\\n\\t'familyNN.BF', and must reside in the same directory as the image.\\\"\\n\\t| f |\\n\\t(FileDirectory default fileNamesMatching: familyName , '*.BF') do:\\n\\t\\t[:fname | Transcript cr; show: fname.\\n\\t\\tf _ StrikeFont new readFromBitFont: fname.\\n\\t\\tf writeAsStrike2named: f name , '.sf2']! !\\n\\n!StrikeFont class methodsFor: 'examples'!\\nexample\\n\\t\\\"Displays a line of text on the display screen at the location of the cursor.\\n\\tExample depends on the strike font file, 'TimesRoman10.strike'. existing.\\\"\\n\\n\\t(StrikeFont new readFromStrike2: 'NewYork12.sf2')\\n\\t\\tdisplayLine: 'A line of 12-pt text in New York style' at: Sensor cursorPoint\\n\\t \\n\\t\\\"StrikeFont example.\\\"! !\\n\\n!StrikeFont class methodsFor: 'examples' stamp: 'tpr 6/10/2005 16:07'!\\nreadStrikeFont2Family: familyName \\n\\t\\\"StrikeFont readStrikeFont2Family: 'Lucida'\\\"\\n\\t^self readStrikeFont2Family: familyName fromDirectory: FileDirectory default! !\\n\\n!StrikeFont class methodsFor: 'examples' stamp: 'tpr 6/10/2005 16:07'!\\nreadStrikeFont2Family: familyName fromDirectory: aDirectory\\n\\t\\\"StrikeFont readStrikeFont2Family: 'Lucida' fromDirectory: FileDirectory default\\\"\\n\\t\\\"This utility reads all available .sf2 StrikeFont files for a given family from \\n\\tthe current directory. It returns an Array, sorted by size, suitable for handing \\n\\tto TextStyle newFontArray: .\\\"\\n\\t\\\"For this utility to work as is, the .sf2 files must be named 'familyNN.sf2'.\\\"\\n\\t| fileNames strikeFonts fontArray |\\n\\tfileNames _ aDirectory fileNamesMatching: familyName , '##.sf2'.\\n\\tstrikeFonts _ fileNames collect: [:fname | StrikeFont new readFromStrike2: fname].\\n\\tstrikeFonts do: [ :font | font reset ].\\n\\tstrikeFonts _ strikeFonts asSortedCollection: [:a :b | a height < b height].\\n\\tfontArray _ strikeFonts asArray.\\n\\t^ fontArray\\n\\n\\\"TextConstants at: #Lucida put: (TextStyle fontArray: (StrikeFont \\n\\treadStrikeFont2Family: 'Lucida')).\\\"! !\\n\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:27'!\\nfromHostFont: fontName size: fontSize flags: fontFlags weight: fontWeight\\n\\t\\\"\\n\\t\\t^StrikeFont fromHostFont: (StrikeFont hostFontFromUser)\\n\\t\\t\\t\\t\\tsize: 12 flags: 0 weight: 4.\\n\\t\\\"\\n\\t| fontHandle glyphs xTable xStart maxWidth w glyphForm ascent descent fontHeight |\\n\\tfontHandle _ self primitiveCreateFont: fontName size: fontSize flags: fontFlags weight: fontWeight.\\n\\tascent _ self primitiveFontAscent: fontHandle.\\n\\tdescent _ self primitiveFontDescent: fontHandle.\\n\\tfontHeight _ ascent + descent.\\n\\txTable _ Array new: 258.\\n\\txStart _ maxWidth _ 0.\\n\\t0 to: 255 do:[:i|\\n\\t\\txTable at: i+1 put: xStart.\\n\\t\\tw _ self primitiveFont: fontHandle widthOfChar: i.\\n\\t\\tw > maxWidth ifTrue:[maxWidth _ w].\\n\\t\\txStart _ xStart + w].\\n\\txTable at: 256 put: xStart.\\n\\txTable at: 257 put: xStart.\\n\\txTable at: 258 put: xStart.\\n\\tglyphs _ Form extent: xTable last @ fontHeight depth: 1.\\n\\tglyphForm _ Form extent: maxWidth @ fontHeight depth: 1.\\n\\t0 to: 255 do:[:i|\\n\\t\\tglyphForm fillWhite.\\n\\t\\tself primitiveFont: fontHandle glyphOfChar: i into: glyphForm.\\n\\t\\txStart _ xTable at: i+1.\\n\\t\\tglyphForm displayOn: glyphs at: xStart@0.\\n\\t\\tglyphForm displayOn: Display at: xStart@0.\\n\\t].\\n\\tself primitiveDestroyFont: fontHandle.\\n\\t^Array with: glyphs with: xTable! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'rbb 2/18/2005 13:21'!\\nhostFontFromUser\\n\\t\\\"StrikeFont hostFontFromUser\\\"\\n\\t| fontNames index labels |\\n\\tfontNames _ self listFontNames asSortedCollection.\\n\\tlabels _ WriteStream on: (String new: 100).\\n\\tfontNames do:[:fn| labels nextPutAll: fn] separatedBy:[labels cr].\\n\\tindex _ (UIManager default chooseFrom: (labels contents substrings) \\n\\t\\t\\t\\ttitle: 'Choose your font').\\n\\tindex = 0 ifTrue:[^nil].\\n\\t^fontNames at: index! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:12'!\\nlistFont: index\\n\\t<primitive:'primitiveListFont' module:'FontPlugin'>\\n\\t^nil! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:12'!\\nlistFontNames\\n\\t\\\"StrikeFont listFontNames\\\"\\n\\t\\\"List all the OS font names\\\"\\n\\t| font fontNames index |\\n\\tfontNames _ WriteStream on: Array new.\\n\\tindex _ 0.\\n\\t[font _ self listFont: index.\\n\\tfont == nil] whileFalse:[\\n\\t\\tfontNames nextPut: font.\\n\\t\\tindex _ index + 1].\\n\\t^fontNames contents! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'tak 8/3/2005 21:11'!\\nlocaleChanged\\n\\tself setupDefaultFallbackFont! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:13'!\\nprimitiveCreateFont: fontName size: fontSize flags: fontFlags weight: fontWeight\\n\\t<primitive:'primitiveCreateFont' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:13'!\\nprimitiveDestroyFont: fontHandle\\n\\t<primitive:'primitiveDestroyFont' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:14'!\\nprimitiveFont: fontHandle glyphOfChar: charIndex into: glyphForm\\n\\t<primitive:'primitiveFontGlyphOfChar' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:15'!\\nprimitiveFont: fontHandle widthOfChar: charIndex\\n\\t<primitive:'primitiveFontWidthOfChar' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:25'!\\nprimitiveFontAscent: fontHandle\\n\\t<primitive:'primitiveFontAscent' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 22:25'!\\nprimitiveFontDescent: fontHandle\\n\\t<primitive:'primitiveFontDescent' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n!StrikeFont class methodsFor: 'font creation' stamp: 'ar 6/4/2000 21:14'!\\nprimitiveFontEncoding: fontHandle\\n\\t<primitive:'primitiveFontEncoding' module:'FontPlugin'>\\n\\t^self primitiveFailed! !\\n\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'ar 2/3/2002 23:06'!\\nfamilyName: aName pointSize: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName pointSize: aSize) emphasized: emphasisCode! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'tk 1/28/1999 11:31'!\\nfamilyName: aName size: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName size: aSize) emphasized: emphasisCode! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 3/18/2004 00:10'!\\nfixAccuISO8859From: aStrikeFont\\n\\n\\t^aStrikeFont copy fixAccuISO8859From: aStrikeFont.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 9/16/2002 15:55'!\\nfixForISO8859From: aStrikeFont\\n\\n\\t^aStrikeFont copy fixForISO8859From: aStrikeFont.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation'!\\nfromStrike: fileName \\n\\t\\\"Read a font from disk in the old ST-80 'strike' format.\\n\\tNote: this is an old format; use strike2 format instead\\\"\\n\\n\\t^self new newFromStrike: fileName! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'ar 1/5/2002 21:41'!\\nfromUser\\n\\t\\\"StrikeFont fromUser\\\"\\n\\t^self fromUser: TextStyle defaultFont! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nk 9/1/2004 14:29'!\\nfromUser: priorFont\\n\\t^self fromUser: priorFont allowKeyboard: true! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nk 9/1/2004 14:28'!\\nfromUser: priorFont allowKeyboard: aBoolean\\n\\t\\\"rr 3/23/2004 10:02 : made the menu invoked modally, thus allowing\\n\\tkeyboard control\\\" \\n\\t\\\"StrikeFont fromUser\\\"\\n\\t\\\"Present a menu of available fonts, and if one is chosen, return it.\\n\\tOtherwise return nil.\\\"\\n\\n\\t| fontList fontMenu style active ptMenu label spec font |\\n\\tfontList _ StrikeFont actualFamilyNames.\\n\\tfontMenu _ MenuMorph new defaultTarget: self.\\n\\tfontList do: [:fontName |\\n\\t\\tstyle _ TextStyle named: fontName.\\n\\t\\tactive _ priorFont familyName sameAs: fontName.\\n\\t\\tptMenu _ MenuMorph new defaultTarget: self.\\n\\t\\tstyle pointSizes do: [:pt |\\n\\t\\t\\t(active and:[pt = priorFont pointSize]) \\n\\t\\t\\t\\tifTrue:[label _ '<on>'] \\n\\t\\t\\t\\tifFalse:[label _ '<off>'].\\n\\t\\t\\tlabel _ label, pt printString, ' pt'.\\n\\t\\t\\tptMenu add: label \\n\\t\\t\\t\\ttarget: fontMenu\\n\\t\\t\\t\\tselector: #modalSelection:\\n\\t\\t\\t\\targument: {fontName. pt}].\\n\\t\\tstyle isTTCStyle ifTrue: [\\n\\t\\t\\tptMenu add: 'new size'\\n\\t\\t\\t\\ttarget: style selector: #addNewFontSizeDialog: argument: {fontName. fontMenu}.\\n\\t\\t].\\n\\t\\tactive ifTrue:[label _ '<on>'] ifFalse:[label _ '<off>'].\\n\\t\\tlabel _ label, fontName.\\n\\t\\tfontMenu add: label subMenu: ptMenu].\\n\\tspec _ fontMenu invokeModalAt: ActiveHand position in: ActiveWorld allowKeyboard: aBoolean.\\n\\tspec ifNil: [^ nil].\\n\\tstyle _ TextStyle named: spec first.\\n\\tstyle ifNil: [^ self].\\n\\tfont _ style fonts detect: [:any | any pointSize = spec last] ifNone: [nil].\\n\\t^ font! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 8/5/2003 13:11'!\\nnewForJapaneseFromEFontBDFFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFForJapaneseFromFile: fileName name: aString overrideWith: otherFileName.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 1/15/2004 16:48'!\\nnewForKoreanFromEFontBDFFile: fileName name: aString overrideWith: otherFileName\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFForKoreanFromFile: fileName name: aString overrideWith: otherFileName.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'nop 1/23/2000 19:21'!\\nnewFromBDFFile: aFileName name: aString \\\"StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'\\\"\\n\\t\\\"Read a font from disk in the X11 Bitmap Distribution Format.\\\"\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readBDFFromFile: aFileName name: aString.\\n\\t^n.\\n\\n\\t\\\"TextConstants at: #Helvetica put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'})\\\"\\n\\t\\\"TextConstants at: #Lucida put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'luRS12.bdf' name: 'Lucida'})\\\"\\n\\t\\\"TextStyle default fontAt: 5 put: (StrikeFont new readFromStrike2: 'helv12.sf2').\\\"\\n\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 1/19/2005 11:22'!\\nnewFromEFontBDFFile: fileName name: aString ranges: ranges\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFFromFile: fileName name: aString ranges: ranges.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 12/27/2002 16:57'!\\nnewFromEFontBDFFile: aFileName name: aString startRange: start endRange: end\\n\\n\\t| n |\\n\\tn _ self new.\\n\\tn readEFontBDFFromFile: aFileName name: aString rangeFrom: start to: end.\\n\\t^n.\\n\\n\\t\\\"TextConstants at: #Helvetica put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'helvR12.bdf' name: 'Helvetica12'})\\\"\\n\\t\\\"TextConstants at: #Lucida put: (TextStyle fontArray: {StrikeFont newFromBDFFile: 'luRS12.bdf' name: 'Lucida'})\\\"\\n\\t\\\"TextStyle default fontAt: 5 put: (StrikeFont new readFromStrike2: 'helv12.sf2').\\\"\\n\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'yo 9/23/2002 16:28'!\\nnewFromF12File: aFileName\\n\\t\\\"StrikeFont newFromF12File: 'kaname.f12'\\\"\\n\\n\\t| file n |\\n\\t('*.F12' match: aFileName) ifFalse: [\\\"self halt. \\\" \\\"likely incompatible\\\"].\\n\\tfile _ FileStream readOnlyFileNamed: aFileName.\\n\\tfile binary.\\n\\tn _ self new.\\n\\tn name: (FileDirectory baseNameFor: (FileDirectory localNameFor: aFileName)).\\n\\tn readF12FromStream: file.\\n\\t^ n.\\n! !\\n\\n!StrikeFont class methodsFor: 'instance creation' stamp: 'tak 12/20/2004 10:23'!\\npasswordFontSize: aSize \\n\\t^ FixedFaceFont new passwordFont fontSize: aSize! !\\n\\n\\n!StrikeFont class methodsFor: '*nebraska-instance creation' stamp: 'yo 12/17/2005 22:41'!\\ndecodedFromRemoteCanvas: aString\\n\\n\\t| array style base |\\n\\tarray _ aString findTokens: #($ ).\\n\\tstyle _ TextStyle named: (array at: 1) asSymbol.\\n\\tstyle ifNil: [^ TextStyle defaultFont].\\n\\t(style fontArray first name = style fontArray first name withoutTrailingDigits) ifTrue: [\\n\\t\\t\\t^ self familyName: (array at: 1) size: (array at: 3) asNumber emphasized: (array at: 4) asNumber].\\n\\tbase _ style fontArray detect: [:f | (array at: 2) beginsWith: f name].\\n\\t^ base emphasized: (array at: 4) asNumber.\\n\\n\\t\\\"^ self familyName: (array at: 1) size: (array at: 2) asNumber emphasized: (array at: 3) asNumber.\\\"\\n! !\\nObject subclass: #StrikeFontFixer\\n\\tinstanceVariableNames: 'strikeFont charForms newFont'\\n\\tclassVariableNames: 'MappingTable NoFontTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\ncharacterFormAt: aCharacter at: aPoint\\n\\n\\t| f |\\n\\tf _ charForms at: aCharacter asciiValue + 1.\\n\\t(f magnifyBy: 3) displayAt: aPoint.\\n\\t^ f.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\ndisplayOn: aDisplayObject at: aPoint magnifyBy: aNumber\\n\\n\\t| form hStep vStep bb source nextPoint |\\n\\thStep _ (strikeFont maxWidth * aNumber * 1.2) asInteger.\\n\\tvStep _ (strikeFont height * aNumber * 1.2) asInteger.\\n\\t\\n\\tform _ Form extent: (hStep * 16)@(vStep * 16).\\n\\tbb _ BitBlt toForm: form.\\n\\t0 to: 15 do: [:i |\\n\\t\\t1 to: 16 do: [:j |\\n\\t\\t\\tsource _ ((charForms at: (i * 16 + j)) magnifyBy: aNumber).\\n\\t\\t\\tnextPoint _ (hStep * (j - 1)@(vStep * i)).\\n\\t\\t\\tbb copy: ((nextPoint+((hStep@vStep - source extent) // 2)) extent: source extent)\\n\\t\\t\\t\\tfrom: 0@0 in: source fillColor: Color black rule: Form over.\\n\\t\\t].\\n\\t].\\n\\tform displayOn: aDisplayObject at: aPoint.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:03'!\\nfont: aStrikeFont\\n\\n\\tstrikeFont _ aStrikeFont.\\n\\tself forms.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nforms\\n\\n\\t1 to: 256 do: [:i |\\n\\t\\tcharForms at: i put: (strikeFont characterFormAt: (Character value: (i - 1)))\\n\\t].\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\ninitialize\\n\\n\\tcharForms _ Array new: 256.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nmappingTable\\n\\n\\t^ MappingTable.\\n! !\\n\\n!StrikeFontFixer methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:04'!\\nstoreEditedGlyphsOn: aStream\\n\\n\\t| n |\\n\\tNoFontTable do: [:i |\\n\\t\\tn _ strikeFont name.\\n\\t\\t(n beginsWith: 'NewYork') ifTrue: [n _ 'NewYork'].\\n\\t\\taStream nextPutAll: '((StrikeFont familyName: ''', n, ''' size: ',\\n\\t\\t\\tstrikeFont height asString, ')'.\\n\\t\\taStream nextPutAll: ' characterFormAt: '.\\n\\t\\taStream nextPutAll: '(Character value: ', i asString, ')'.\\n\\t\\taStream nextPutAll: ' put: '.\\n\\t\\t(strikeFont characterFormAt: (Character value: i)) storeOn: aStream base: 2.\\n\\t\\taStream nextPutAll: ')!!'.\\n\\t\\taStream nextPut: Character cr.\\n\\t\\taStream nextPut: Character cr.\\n\\t].\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFontFixer class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:06'!\\ninitialize\\n\\\"\\n\\tStrikeFontFixer initialize\\n\\\"\\n\\n\\t| d |\\n\\tself initializeNoFontTable.\\n\\td _ Array new: 256.\\n\\t0 to: 127 do: [:i | d at: i+1 put: i].\\n\\t16r80 to: 16r9F do: [:i | d at: i+1 put: nil].\\n\\td at: 16rA0+1 put: 16r20.\\n\\td at: 16rA1+1 put: 16rC1.\\n\\td at: 16rA2+1 put: 16rA2.\\n\\td at: 16rA3+1 put: 16rA3.\\n\\td at: 16rA4+1 put: 16rA9. \\\"CURRENCY SIGN\\\"\\n\\td at: 16rA5+1 put: 16rB4.\\n\\td at: 16rA6+1 put: 16r7C. \\\"BROKEN BAR\\\"\\n\\td at: 16rA7+1 put: 16rA4.\\n\\td at: 16rA8+1 put: 16r80. \\\"DIAERESIS\\\"\\n\\td at: 16rA9+1 put: 16rA9.\\n\\td at: 16rAA+1 put: 16rBB.\\n\\td at: 16rAB+1 put: 16rC7.\\n\\td at: 16rAC+1 put: 16rD1. \\\"NOT SIGN\\\"\\n\\td at: 16rAD+1 put: 16rD0.\\n\\td at: 16rAE+1 put: 16rA8.\\n\\td at: 16rAF+1 put: 16rD1. \\\"MACRON\\\"\\n\\td at: 16rB0+1 put: 16rA1.\\n\\td at: 16rB1+1 put: 16r2B. \\\"PLUS-MINUS SIGN\\\"\\n\\td at: 16rB2+1 put: 16rAB. \\\"SUPERSCRIPT TWO\\\"\\n\\td at: 16rB3+1 put: 16rAB. \\\"SUPERSCRIPT THREE\\\"\\n\\td at: 16rB4+1 put: 16rAB.\\n\\td at: 16rB5+1 put: 16r75. \\\"MICRO SIGN\\\"\\n\\td at: 16rB6+1 put: 16rA6.\\n\\td at: 16rB7+1 put: 16rA5.\\n\\td at: 16rB8+1 put: 16r82. \\\"CEDILLA\\\"\\n\\td at: 16rB9+1 put: 16rAB. \\\"SUPERSCRIPT ONE\\\"\\n\\td at: 16rBA+1 put: 16rBC.\\n\\td at: 16rBB+1 put: 16rC8.\\n\\td at: 16rBC+1 put: 16r4D. \\\"VULGAR FRACTION ONE QUARTER\\\"\\n\\td at: 16rBD+1 put: 16r4D. \\\"VULGAR FRACTIOIN ONE HALF\\\"\\n\\td at: 16rBE+1 put: 16r4D. \\\"VALGAR FRACTION THREE QUARTERS\\\"\\n\\td at: 16rBF+1 put: 16rC0.\\n\\td at: 16rC0+1 put: 16rCB.\\n\\td at: 16rC1+1 put: 16rCB. \\\"CAPITAL A WITH ACUTE\\\"\\n\\td at: 16rC2+1 put: 16rCB. \\\"CAPITAL A WITH CIRCUMFLEX\\\"\\n\\td at: 16rC3+1 put: 16rCC.\\n\\td at: 16rC4+1 put: 16r80.\\n\\td at: 16rC5+1 put: 16r81.\\n\\td at: 16rC6+1 put: 16rAE.\\n\\td at: 16rC7+1 put: 16r82.\\n\\td at: 16rC8+1 put: 16r83. \\\"CAPITAL E WITH GRAVE\\\"\\n\\td at: 16rC9+1 put: 16r83.\\n\\td at: 16rCA+1 put: 16r83. \\\"CAPITAL E WITH CIRCUMFLEX\\\"\\n\\td at: 16rCB+1 put: 16r83. \\\"CAPITAL E WITH DIAERESIS\\\"\\n\\td at: 16rCC+1 put: 16r49. \\\"CAPITAL I WITH GRAVE\\\"\\n\\td at: 16rCD+1 put: 16r49. \\\"CAPITAL I WITH ACUTE\\\"\\n\\td at: 16rCE+1 put: 16r49. \\\"CAPITAL I WITH CIRCUMFLEX\\\"\\n\\td at: 16rCF+1 put: 16r49. \\\"CAPITAL I WITH DIAERESIS\\\"\\n\\td at: 16rD0+1 put: 16r44. \\\"CAPITAL ETH\\\"\\n\\td at: 16rD1+1 put: 16r84.\\n\\td at: 16rD2+1 put: 16rCD. \\\"CAPITAL O WITH GRAVE\\\"\\n\\td at: 16rD3+1 put: 16rCD. \\\"CAPITAL O WITH ACUTE\\\"\\n\\td at: 16rD4+1 put: 16rCD. \\\"CAPITAL O WITH CIRCUMFLEX\\\"\\n\\td at: 16rD5+1 put: 16rCD.\\n\\td at: 16rD6+1 put: 16r85.\\n\\td at: 16rD7+1 put: 16r2B. \\\"MULTIPLICATION SIGN\\\"\\n\\td at: 16rD8+1 put: 16rBF.\\n\\td at: 16rD9+1 put: 16r86. \\\"CAPITAL U WITH GRAVE\\\"\\n\\td at: 16rDA+1 put: 16r86. \\\"CAPITAL U WITH ACUTE\\\"\\n\\td at: 16rDB+1 put: 16r86. \\\"CAPITAL U WITH CIRCUMFLEX\\\"\\n\\td at: 16rDC+1 put: 16r86. \\\"CAPTIAL U WITH DIAERESIS\\\"\\n\\td at: 16rDD+1 put: 16r59. \\\"CAPITAL Y WITH ACUTE\\\"\\n\\td at: 16rDE+1 put: 16r50. \\\"CAPITAL THORN\\\"\\n\\td at: 16rDF+1 put: 16rA7.\\n\\td at: 16rE0+1 put: 16r88.\\n\\td at: 16rE1+1 put: 16r87.\\n\\td at: 16rE2+1 put: 16r89.\\n\\td at: 16rE3+1 put: 16r8B.\\n\\td at: 16rE4+1 put: 16r8A.\\n\\td at: 16rE5+1 put: 16r8C.\\n\\td at: 16rE6+1 put: 16rBE.\\n\\td at: 16rE7+1 put: 16r8D.\\n\\td at: 16rE8+1 put: 16r8F.\\n\\td at: 16rE9+1 put: 16r8E.\\n\\td at: 16rEA+1 put: 16r90.\\n\\td at: 16rEB+1 put: 16r91.\\n\\td at: 16rEC+1 put: 16r93.\\n\\td at: 16rED+1 put: 16r92.\\n\\td at: 16rEE+1 put: 16r94.\\n\\td at: 16rEF+1 put: 16r95.\\n\\td at: 16rF0+1 put: 16r64. \\\"SMALL ETH\\\"\\n\\td at: 16rF1+1 put: 16r96.\\n\\td at: 16rF2+1 put: 16r98.\\n\\td at: 16rF3+1 put: 16r97.\\n\\td at: 16rF4+1 put: 16r99.\\n\\td at: 16rF5+1 put: 16r9B.\\n\\td at: 16rF6+1 put: 16r9A.\\n\\td at: 16rF7+1 put: 16r2D. \\\"DIVISION SIGN\\\"\\n\\td at: 16rF8+1 put: 16rBF.\\n\\td at: 16rF9+1 put: 16r9D.\\n\\td at: 16rFA+1 put: 16r9C.\\n\\td at: 16rFB+1 put: 16r9E.\\n\\td at: 16rFC+1 put: 16r9F.\\n\\td at: 16rFD+1 put: 16rD8. \\\"SMALL Y WITH ACUTE\\\"\\n\\td at: 16rFE+1 put: 16r70. \\\"SMALL THORN\\\"\\n\\td at: 16rFF+1 put: 16rD8.\\n\\n\\tMappingTable _ d.\\n! !\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'yo 9/16/2002 15:05'!\\ninitializeNoFontTable\\n\\n\\t| n |\\n\\tn _ #(\\n\\t16rA4 \\\"CURRENCY SIGN\\\"\\n\\t16rA6 \\\"BROKEN BAR\\\"\\n\\t16rA8 \\\"DIAERESIS\\\"\\n\\t16rAC \\\"NOT SIGN\\\"\\n\\t16rAF \\\"MACRON\\\"\\n\\t16rB1 \\\"PLUS-MINUS SIGN\\\"\\n\\t16rB2 \\\"SUPERSCRIPT TWO\\\"\\n\\t16rB3 \\\"SUPERSCRIPT THREE\\\"\\n\\t16rB5 \\\"MICRO SIGN\\\"\\n\\t16rB8 \\\"CEDILLA\\\"\\n\\t16rB9 \\\"SUPERSCRIPT ONE\\\"\\n\\t16rBC \\\"VULGAR FRACTION ONE QUARTER\\\"\\n\\t16rBD \\\"VULGAR FRACTIOIN ONE HALF\\\"\\n\\t16rBE \\\"VALGAR FRACTION THREE QUARTERS\\\"\\n\\t16rC1 \\\"CAPITAL A WITH ACUTE\\\"\\n\\t16rC2 \\\"CAPITAL A WITH CIRCUMFLEX\\\"\\n\\t16rC8 \\\"CAPITAL E WITH GRAVE\\\"\\n\\t16rCA \\\"CAPITAL E WITH CIRCUMFLEX\\\"\\n\\t16rCB \\\"CAPITAL E WITH DIAERESIS\\\"\\n\\t16rCC \\\"CAPITAL I WITH GRAVE\\\"\\n\\t16rCD \\\"CAPITAL I WITH ACUTE\\\"\\n\\t16rCE \\\"CAPITAL I WITH CIRCUMFLEX\\\"\\n\\t16rCF \\\"CAPITAL I WITH DIAERESIS\\\"\\n\\t16rD0 \\\"CAPITAL ETH\\\"\\n\\t16rD2 \\\"CAPITAL O WITH GRAVE\\\"\\n\\t16rD3 \\\"CAPITAL O WITH ACUTE\\\"\\n\\t16rD4 \\\"CAPITAL O WITH CIRCUMFLEX\\\"\\n\\t16rD7 \\\"MULTIPLICATION SIGN\\\"\\n\\t16rD9 \\\"CAPITAL U WITH GRAVE\\\"\\n\\t16rDA \\\"CAPITAL U WITH ACUTE\\\"\\n\\t16rDB \\\"CAPITAL U WITH CIRCUMFLEX\\\"\\n\\t16rDD \\\"CAPITAL Y WITH ACUTE\\\"\\n\\t16rDE \\\"CAPITAL THORN\\\"\\n\\t16rF0 \\\"SMALL ETH\\\"\\n\\t16rF7 \\\"DIVISION SIGN\\\"\\n\\t16rFD \\\"SMALL Y WITH ACUTE\\\"\\n\\t16rFE \\\"SMALL THORN\\\"\\n\\t).\\n\\tNoFontTable _ n.\\n\\n! !\\n\\n!StrikeFontFixer class methodsFor: 'as yet unclassified' stamp: 'nk 7/30/2004 18:09'!\\nnewOn: aStrikeFont \\n\\t^self new font: aStrikeFont! !\\nAbstractFont subclass: #StrikeFontSet\\n\\tinstanceVariableNames: 'fontArray emphasis derivativeFonts name rIndex'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-Display'!\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nascentOf: aCharacter\\n\\t^(self fontOf: aCharacter) ascent! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\ndescentOf: aCharacter\\n\\t^(self fontOf: aCharacter) descent! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 9/23/2002 20:08'!\\nfontArray\\n\\n\\t^ fontArray\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nfontOf: aCharacter\\n\\t\\\"Answer the actual font to use for aCharacter\\\"\\n\\t^self fontOf: aCharacter ifAbsent:[fontArray at: 1]! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:14'!\\nfontOf: aCharacter ifAbsent: aBlock\\n\\t\\\"Answer the actual font to use for aCharacter\\\"\\n\\t| encoding font |\\n\\tencoding := aCharacter leadingChar + 1.\\n\\tencoding <= fontArray size \\n\\t\\tifTrue:[font := fontArray at: encoding].\\n\\tfont ifNil:[^aBlock value].\\n\\t^font\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\nheightOf: aCharacter\\n\\t^(self fontOf: aCharacter) height! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'tak 12/21/2004 16:43'!\\nlatin1\\n\\t\\\"Answer primary font\\\"\\n\\t^ fontArray at: 1! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 11/15/2002 14:22'!\\nmaxAsciiFor: encoding\\n\\n\\t| f |\\n\\tf _ (fontArray at: encoding+1).\\n\\tf ifNotNil: [^ f maxAscii].\\n\\t^ 0.\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'yo 8/5/2003 15:31'!\\ntextStyle\\n\\n\\t^ TextStyle actualTextStyles detect: [:aStyle | (aStyle fontArray collect: [:s | s name]) includes: self name]\\n\\t\\tifNone: [].\\n! !\\n\\n!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/12/2005 17:15'!\\nwidthOf: aCharacter \\n\\t\\\"Answer the width of the argument as a character in the receiver.\\\"\\n\\t^(self fontOf: aCharacter) widthOf: aCharacter! !\\n\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:43'!\\nascent\\n\\n\\t^ fontArray first ascent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:49'!\\nascentKern\\n\\n\\t^ fontArray first ascentKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 16:49'!\\nbaseKern\\n\\n\\t^ fontArray first baseKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 12/1/2003 18:00'!\\nbonk: glyphForm with: bonkForm at: j\\n\\t\\\"Bonking means to run through the glyphs clearing out black pixels\\n\\tbetween characters to prevent them from straying into an adjacent\\n\\tcharacter as a result of, eg, bolding or italicizing\\\"\\n\\t\\\"Uses the bonkForm to erase at every character boundary in glyphs.\\\"\\n\\n\\t| bb offset font x |\\n\\tfont _ (fontArray at: j).\\n\\toffset _ bonkForm offset x.\\n\\tbb _ BitBlt toForm: glyphForm.\\n\\tbb sourceForm: bonkForm; sourceRect: bonkForm boundingBox;\\n\\t\\tcombinationRule: Form erase; destY: 0.\\n\\tx _ font xTable.\\n\\t(x isMemberOf: SparseLargeTable) ifTrue: [\\n\\t\\tx base to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t] ifFalse: [\\n\\t\\t1 to: x size-1 do: [:i | bb destX: (x at: i) + offset; copyBits].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:15'!\\ncopy\\n\\n\\t| s a |\\n\\ts _ self class new.\\n\\ts name: self name.\\n\\ts emphasis: self emphasis.\\n\\ts reset.\\n\\ta _ Array new: fontArray size.\\n\\t1 to: a size do: [:i |\\n\\t\\ta at: i put: (fontArray at: i) copy.\\n\\t].\\n\\ts fontArray: a.\\n\\t^ s.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'nk 9/1/2004 12:06'!\\nderivativeFonts\\n\\t^derivativeFonts copyWithout: nil! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:02'!\\ndescent\\n\\n\\t^ fontArray first descent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:02'!\\ndescentKern\\n\\n\\t^ fontArray first descentKern.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 5/19/2004 11:36'!\\ndisplayLine: aString at: aPoint \\n\\t\\\"Display the characters in aString, starting at position aPoint.\\\"\\n\\n\\tself characters: (1 to: aString size)\\n\\t\\tin: aString\\n\\t\\tdisplayAt: aPoint\\n\\t\\tclippedBy: Display boundingBox\\n\\t\\trule: Form over\\n\\t\\tfillColor: nil\\n\\t\\tkernDelta: 0\\n\\t\\ton: (BitBlt current toForm: Display).\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:06'!\\nemphasis\\n\\t\\\"Answer the integer code for synthetic bold, italic, underline, and \\n\\tstrike-out.\\\"\\n\\n\\t^ emphasis.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:07'!\\nemphasis: code \\n\\t\\\"Set the integer code for synthetic bold, itallic, underline, and strike-out, \\n\\twhere bold=1, italic=2, underlined=4, and struck out=8.\\\"\\n\\n\\temphasis _ code.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:15'!\\nemphasized: code \\n\\n\\t\\\"Answer a copy of the receiver with emphasis set to include code.\\\"\\n\\t| derivative addedEmphasis base safeCode |\\n\\tcode = 0 ifTrue: [^ self].\\n\\t(derivativeFonts == nil or: [derivativeFonts size = 0]) ifTrue: [^ self].\\n\\tderivative _ derivativeFonts at: (safeCode _ code min: derivativeFonts size).\\n\\tderivative == nil ifFalse: [^ derivative]. \\\"Already have this style\\\"\\n\\n\\t\\\"Dont have it -- derive from another with one with less emphasis\\\"\\n\\taddedEmphasis _ 1 bitShift: safeCode highBit - 1.\\n\\tbase _ self emphasized: safeCode - addedEmphasis. \\\"Order is Bold, Ital, Under, Narrow\\\"\\n\\taddedEmphasis = 1 ifTrue: \\\"Compute synthetic bold version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'B') makeBoldGlyphs].\\n\\taddedEmphasis = 2 ifTrue: \\\"Compute synthetic italic version of the font\\\"\\n\\t\\t[ derivative _ (base copy name: base name , 'I') makeItalicGlyphs].\\n\\taddedEmphasis = 4 ifTrue: \\\"Compute underlined version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'U') makeUnderlinedGlyphs].\\n\\taddedEmphasis = 8 ifTrue: \\\"Compute narrow version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'N') makeCondensedGlyphs].\\n\\taddedEmphasis = 16 ifTrue: \\\"Compute struck-out version of the font\\\"\\n\\t\\t[derivative _ (base copy name: base name , 'X') makeStruckOutGlyphs].\\n\\tderivative emphasis: safeCode.\\n\\tderivativeFonts at: safeCode put: derivative.\\n\\t^ derivative\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 20:59'!\\nfamilyName\\n\\n\\t^ fontArray first familyName.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:38'!\\nfamilySizeFace\\n\\n\\t^ Array\\n\\t\\twith: fontArray first name\\n\\t\\twith: self height\\n\\t\\twith: fontArray first emphasis\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:49'!\\nfontArray: anArray\\n\\n\\tfontArray _ anArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:49'!\\nfontNameWithPointSize\\n\\n\\t^ fontArray first fontNameWithPointSize.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nglyphs\\n\\n\\t^ fontArray first glyphs\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nglyphsEncoding: anInteger\\n\\n\\t^ (fontArray at: (anInteger+1)) glyphs.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nheight\\n\\n\\t^ fontArray first height.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'tak 12/16/2004 19:15'!\\ninitializeWithFontArray: anArray \\n\\t\\\"Initialize with given font array, the ascent of primary font is modified \\n\\tif another font has higher size\\\"\\n\\t| primaryFont maxHeight newFont |\\n\\tfontArray := anArray.\\n\\tprimaryFont := anArray first.\\n\\temphasis := 0.\\n\\tname := primaryFont name.\\n\\tmaxHeight := anArray\\n\\t\\t\\t\\tinject: 0\\n\\t\\t\\t\\tinto: [:theHeight :font | (font notNil\\n\\t\\t\\t\\t\\t\\t\\tand: [theHeight < font height])\\n\\t\\t\\t\\t\\t\\tifTrue: [font height]\\n\\t\\t\\t\\t\\t\\tifFalse: [theHeight]].\\n\\tprimaryFont height < maxHeight\\n\\t\\tifTrue: [newFont := primaryFont copy\\n\\t\\t\\t\\t\\t\\tfixAscent: primaryFont ascent + (maxHeight - primaryFont height)\\n\\t\\t\\t\\t\\t\\tandDescent: primaryFont descent\\n\\t\\t\\t\\t\\t\\thead: 0.\\n\\t\\t\\tfontArray at: 1 put: newFont].\\n\\tself reset! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 1/5/2005 13:59'!\\ninstallOn: aDisplayContext\\n\\n\\t^ aDisplayContext installStrikeFont: self.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\ninstallOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor \\n\\n\\t^ aDisplayContext\\n\\t\\tinstallStrikeFont: self\\n\\t\\tforegroundColor: foregroundColor\\n\\t\\tbackgroundColor: backgroundColor.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:50'!\\nlineGrid\\n\\n\\t| f |\\n\\tf _ fontArray first.\\n\\t^ f ascent + f descent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nmaxEncoding\\n\\n\\t^ fontArray size.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 2/24/2005 15:45'!\\nmaxWidth\\n\\n\\t^ (fontArray at: 1) maxWidth.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nname\\n\\n\\t^ name\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:52'!\\nname: aString\\n\\n\\tname _ aString\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 21:17'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to a known Font in the other system instead. \\\"\\n\\n\\t\\\"A path to me\\\"\\n\\t(TextConstants at: #forceFontWriting ifAbsent: [false]) ifTrue: [^ self].\\n\\t\\t\\\"special case for saving the default fonts on the disk. See collectionFromFileNamed:\\\"\\n\\n\\tdp _ DiskProxy global: #StrikeFontSet selector: #familyName:size:emphasized:\\n\\t\\t\\targs: (Array with: self familyName with: self pointSize\\n\\t\\t\\t\\t\\twith: self emphasis).\\n\\trefStrm replace: self with: dp.\\n\\t^ dp.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\npointSize\\n\\n\\t^ fontArray first pointSize.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream nextPutAll: '(' , self name.\\n\\taStream space.\\n\\tself height printOn: aStream.\\n\\taStream nextPut: $).\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nreset\\n\\t\\\"Reset the cache of derivative emphasized fonts\\\"\\n\\n\\tderivativeFonts _ Array new: 32.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nsubscript\\n\\n\\t^ fontArray first subscript\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:53'!\\nsuperscript\\n\\n\\t^ fontArray first superscript\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 18:53'!\\nwidthOfString: aString\\n\\n\\taString ifNil:[^0].\\n\\t\\\"Optimizing\\\"\\n\\t(aString isByteString) ifTrue: [\\n\\t\\t^ self fontArray first widthOfString: aString from: 1 to: aString size].\\n\\t^ self widthOfString: aString from: 1 to: aString size.\\n\\\"\\n\\tTextStyle default defaultFont widthOfString: 'zort' 21\\n\\\"\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'tak 1/11/2005 17:59'!\\nwidthOfString: aString from: startIndex to: stopIndex\\n\\t\\\"Measure the length of the given string between start and stop index\\\"\\n\\n\\t| resultX |\\n\\tresultX _ 0.\\n\\tstartIndex to: stopIndex do:[:i | \\n\\t\\tresultX _ resultX + (self widthOf: (aString at: i))].\\n\\t^ resultX.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:56'!\\nxTable\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^ fontArray first xTable.\\n! !\\n\\n!StrikeFontSet methodsFor: 'as yet unclassified' stamp: 'yo 9/17/2002 17:56'!\\nxTableEncoding: anInteger\\n\\t\\\"Answer an Array of the left x-coordinate of characters in glyphs.\\\"\\n\\n\\t^(fontArray at: anInteger + 1) xTable.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'character shapes' stamp: 'yo 12/27/2002 04:35'!\\ncharacterFormAt: character \\n\\n\\t| encoding ascii xTable leftX rightX |\\n\\tencoding _ character leadingChar + 1.\\n\\tascii _ character charCode.\\n\\t(ascii < (fontArray at: encoding) minAscii or: [ascii > (fontArray at: encoding) maxAscii])\\n\\t\\tifTrue: [ascii _ (fontArray at: encoding) maxAscii].\\n\\txTable _ (fontArray at: encoding) xTable.\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\t^ (fontArray at: encoding) glyphs copy: (leftX @ 0 corner: rightX @ self height).\\n! !\\n\\n!StrikeFontSet methodsFor: 'character shapes' stamp: 'yo 12/27/2002 04:35'!\\ncharacterFormAt: character put: characterForm \\n\\n\\t| ascii leftX rightX widthDif newGlyphs encoding xTable glyphs |\\n\\tencoding _ character leadingChar + 1.\\n\\tascii _ character charCode.\\n\\tascii < (fontArray at: encoding) minAscii ifTrue: [\\n\\t\\t^ self error: 'Cant store characters below min ascii'\\n\\t].\\n\\tascii > (fontArray at: encoding) maxAscii ifTrue: [\\n\\t\\t^ self error: 'No change made'\\n\\t].\\n\\txTable _ (fontArray at: encoding) xTable.\\n\\tleftX _ xTable at: ascii + 1.\\n\\trightX _ xTable at: ascii + 2.\\n\\tglyphs _ (fontArray at: encoding) glyphs.\\n\\twidthDif _ characterForm width - (rightX - leftX).\\n\\twidthDif ~= 0 ifTrue: [\\n\\t\\tnewGlyphs _ Form extent: glyphs width + widthDif @ glyphs height.\\n\\t\\tnewGlyphs copy: (0 @ 0 corner: leftX @ glyphs height) from: 0 @ 0\\n\\t\\t\\tin: glyphs rule: Form over.\\n\\t\\tnewGlyphs\\n\\t\\t\\t\\tcopy: (rightX + widthDif @ 0 corner: newGlyphs width @ glyphs height)\\n\\t\\t\\t\\tfrom: rightX @ 0 in: glyphs rule: Form over.\\n\\t\\tglyphs _ newGlyphs.\\n\\t\\t\\\"adjust further entries on xTable\\\"\\n\\t\\txTable _ xTable copy.\\n\\t\\tascii + 2 to: xTable size do: [:i |\\n\\t\\t\\txTable at: i put: (xTable at: i) + widthDif]].\\n\\tglyphs copy: (leftX @ 0 extent: characterForm extent) from: 0 @ 0 in: characterForm rule: Form over.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 5/19/2004 11:35'!\\ncharacters: anInterval in: sourceString displayAt: aPoint clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm kernDelta: kernDelta on: aBitBlt\\n\\t\\\"Simple, slow, primitive method for displaying a line of characters.\\n\\tNo wrap-around is provided.\\\"\\n\\n\\t| ascii encoding destPoint leftX rightX sourceRect xTable noFont f |\\n\\tdestPoint _ aPoint.\\n\\tanInterval do: \\n\\t\\t[:i |\\n\\t\\tencoding _ (sourceString at: i) leadingChar + 1.\\n\\t\\tnoFont _ false.\\n\\t\\t[f _ fontArray at: encoding]\\n\\t\\t\\ton: Exception do: [:ex | noFont _ true. f _ fontArray at: 1].\\n\\t\\tf ifNil: [noFont _ true. f _ fontArray at: 1].\\n\\t\\tascii _ noFont ifTrue: [$?] ifFalse: [(sourceString at: i) charCode].\\n\\t\\t(ascii < f minAscii\\n\\t\\t\\tor: [ascii > f maxAscii])\\n\\t\\t\\tifTrue: [ascii _ f maxAscii].\\n\\t\\txTable _ f xTable.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\tsourceRect _ leftX@0 extent: (rightX-leftX) @ self height.\\n\\t\\taBitBlt copyFrom: sourceRect in: f glyphs to: destPoint.\\n\\t\\tdestPoint _ destPoint + ((rightX-leftX+kernDelta)@0).\\n\\t\\t\\\"destPoint printString displayAt: 0@(i*20).\\\"\\n\\t].\\n\\t^ destPoint.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'efc 8/6/2005 11:45'!\\ndisplayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo g destY |\\n\\tdestPoint := aPoint.\\n\\tglyphInfo := Array new: 5.\\n\\tstartIndex to: stopIndex do: [:charIndex |\\n\\t\\tself glyphInfoOf: (aString at: charIndex) into: glyphInfo.\\n\\t\\tg := glyphInfo at:1.\\n\\t\\tleftX := glyphInfo at:2.\\n\\t\\trightX := glyphInfo at:3.\\n\\t\\t((glyphInfo at:5) ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\t(glyphInfo at:5) installOn: aBitBlt.\\n\\t\\t].\\n\\t\\taBitBlt sourceForm: g.\\n\\t\\tdestY := baselineY - (glyphInfo at:4).\\n\\t\\taBitBlt destX: (destPoint x) destY: destY width: (rightX - leftX) height: (self height).\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint := destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t].\\n\\t^ destPoint.! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 12/27/2002 04:35'!\\ndisplayStringR2L: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta \\n\\n\\t| destPoint font |\\n\\tdestPoint _ aPoint.\\n\\tstartIndex to: stopIndex do: [:charIndex | \\n\\t\\t| encoding ascii xTable leftX rightX | \\n\\t\\tencoding _ (aString at: charIndex) leadingChar + 1.\\n\\t\\tascii _ (aString at: charIndex) charCode.\\n\\t\\tfont _ fontArray at: encoding.\\n\\t\\t((ascii between: font minAscii and: font maxAscii) not) ifTrue: [\\n\\t\\t\\tascii _ font maxAscii].\\n\\t\\txTable _ font xTable.\\n\\t\\tleftX _ xTable at: ascii + 1.\\n\\t\\trightX _ xTable at: ascii + 2.\\n\\t\\taBitBlt sourceForm: font glyphs.\\n\\t\\taBitBlt destX: destPoint x - (rightX - leftX).\\n\\t\\taBitBlt destY: destPoint y.\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt width: rightX - leftX.\\n\\t\\taBitBlt height: self height.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint _ destPoint - (rightX - leftX + kernDelta @ 0).\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 1/7/2005 12:04'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta \\n\\n\\t^ self displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: aPoint y + self ascent.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'efc 8/6/2005 13:35'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY\\n\\t\\\"Draw the given string from startIndex to stopIndex \\n\\tat aPoint on the (already prepared) BitBlt.\\\"\\n\\t\\n\\t\\\"Assume this is a wide string\\\"\\n\\t| isMulti |\\n\\tisMulti _ true.\\n\\n\\t\\\"Look for an excuse to use the fast primitive\\\"\\n \\t(aString isKindOf: ByteString) \\n\\t\\tifTrue:[ isMulti _ false]\\n\\t\\tifFalse:[ (aString isKindOf: Text) \\n\\t\\t\\tifTrue:[ (aString string isKindOf: ByteString) \\n\\t\\t\\t\\tifTrue:[ isMulti _ false ] \\n\\t]].\\n\\n\\tisMulti ifTrue:[^ self displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY].\\n\\n\\t^ aBitBlt displayString: aString \\n\\t\\t\\tfrom: startIndex \\n\\t\\t\\tto: stopIndex \\n\\t\\t\\tat: aPoint \\n\\t\\t\\tstrikeFont: self\\n\\t\\t\\tkern: kernDelta! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'yo 1/7/2005 15:17'!\\ndisplayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta from: fromFont baselineY: baselineY\\n\\n\\t| destPoint leftX rightX glyphInfo g tag char destY |\\n\\tdestPoint _ aPoint.\\n\\trIndex _ startIndex.\\n\\ttag _ (aString at: rIndex) leadingChar.\\n\\tglyphInfo _ Array new: 5.\\n\\t[rIndex <= stopIndex] whileTrue: [\\n\\t\\tchar _ aString at: rIndex.\\n\\t\\t((fromFont hasGlyphOf: char) or: [char leadingChar ~= tag]) ifTrue: [^ Array with: rIndex with: destPoint].\\n\\t\\tself glyphInfoOf: char into: glyphInfo.\\n\\t\\tg _ glyphInfo first.\\n\\t\\tleftX _ glyphInfo second.\\n\\t\\trightX _ glyphInfo third.\\n\\t\\t(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [\\n\\t\\t\\tglyphInfo fifth installOn: aBitBlt.\\n\\t\\t].\\n\\t\\taBitBlt sourceForm: g.\\n\\t\\tdestY _ baselineY - glyphInfo fourth. \\n\\t\\taBitBlt destX: destPoint x.\\n\\t\\taBitBlt destY: destY.\\n\\t\\taBitBlt sourceOrigin: leftX @ 0.\\n\\t\\taBitBlt width: rightX - leftX.\\n\\t\\taBitBlt height: self height.\\n\\t\\taBitBlt copyBits.\\n\\t\\tdestPoint _ destPoint + (rightX - leftX + kernDelta @ 0).\\n\\t\\trIndex _ rIndex + 1.\\n\\t].\\n\\t^ Array with: rIndex with: destPoint.\\n! !\\n\\n!StrikeFontSet methodsFor: 'displaying' stamp: 'BG 3/16/2005 08:27'!\\nfontDisplay\\n\\t\\\"TextStyle default defaultFont fontDisplay.\\\"\\n\\n\\tDisplay restoreAfter:\\n\\t\\t[(Form extent: 440@400) displayAt: 90@90.\\n\\t\\t 0 to: 15 do:\\n\\t\\t\\t[:i |\\n\\t\\t\\ti storeStringHex displayAt: 100 @ (20 * i + 100).\\n\\t\\t\\t0 to: 15 do:\\n\\t\\t\\t\\t[:j |\\n\\t\\t\\t\\t((16*i+j) between: 1 and: (self xTable size - 2)) ifTrue:\\n\\t\\t\\t\\t\\t[(self characterFormAt: (16 * i + j) asCharacter)\\n\\t\\t\\t\\t\\t\\tdisplayAt: (20 * j + 150) @ (20 * i + 100)]]].\\n\\t\\t\\t'Click to continue...' asDisplayText displayAt: 100@450]! !\\n\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:52'!\\nmakeBoldGlyphs\\n\\t\\\"Make a bold set of glyphs with same widths by ORing 1 bit to the right\\n\\t\\t(requires at least 1 pixel of intercharacter space)\\\"\\n\\n\\t| g bonkForm font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ fontArray at: i.\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tbonkForm _ (Form extent: 1@16) fillBlack offset: -1@0.\\n\\t\\t\\tself bonk: g with: bonkForm at: i.\\n\\t\\t\\tg copyBits: g boundingBox from: g at: (1@0)\\n\\t\\t\\t\\tclippingBox: g boundingBox rule: Form under fillColor: nil.\\n\\t\\t\\t(fontArray at: i) setGlyphs: g.\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:51'!\\nmakeItalicGlyphs\\n\\t\\\"Make an italic set of glyphs with same widths by skewing left and right\\n\\t\\t(may require more intercharacter space)\\\"\\n\\n\\t| g bonkForm bc font |\\n\\t1 to: fontArray size do: [:j |\\n\\t\\tfont _ (fontArray at: j).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\t\\\"BonkForm will have bits where slanted characters overlap their neighbors.\\\"\\n\\t\\t\\tbonkForm _ Form extent: (self height//4+2) @ self height.\\n\\t\\t\\tbc _ font descent//4 + 1. \\\"Bonker x-coord corresponding to char boundary.\\\"\\n\\t\\t\\tbonkForm fill: (0 @ 0 corner: (bc+1) @ font ascent) fillColor: Color black.\\n\\t\\t\\t4 to: font ascent-1 by: 4 do:\\n\\t\\t\\t\\t[:y | \\t\\t\\\"Slide ascenders right...\\\"\\n\\t\\t\\t\\tg copy: (1@0 extent: g width @ (font ascent - y))\\n\\t\\t\\t\\t\\tfrom: 0@0 in: g rule: Form over.\\n\\t\\t\\t\\tbonkForm copy: (1@0 extent: bonkForm width @ (font ascent - y))\\n\\t\\t\\t\\t\\tfrom: 0@0 in: bonkForm rule: Form over].\\n\\t\\t\\tbonkForm fill: (0 @ 0 corner: (bc+1) @ font ascent) fillColor: Color white.\\n\\t\\t\\tbonkForm fill: (bc @ font ascent corner: bonkForm extent) fillColor: Color black.\\n\\t\\t\\tfont ascent to: font height-1 by: 4 do:\\n\\t\\t\\t\\t[:y | \\t\\t\\\"Slide descenders left...\\\"\\n\\t\\t\\t\\tg copy: (0@y extent: g width @ g height)\\n\\t\\t\\t\\t\\tfrom: 1@y in: g rule: Form over.\\n\\t\\t\\t\\tbonkForm copy: (0@0 extent: bonkForm width @ bonkForm height)\\n\\t\\t\\t\\t\\tfrom: 1@0 in: bonkForm rule: Form over].\\n\\t\\t\\tbonkForm fill: (bc @ font ascent corner: bonkForm extent) fillColor: Color white.\\n\\t\\t\\t\\\"Now use bonkForm to erase at every character boundary in glyphs.\\\"\\n\\t\\t\\tbonkForm offset: (0-bc) @ 0.\\n\\t\\t\\tfont bonk: g with: bonkForm.\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:53'!\\nmakeStruckOutGlyphs\\n\\t\\\"Make a struck-out set of glyphs with same widths\\\"\\n\\n\\t| g font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ (fontArray at: i).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tg fillBlack: (0 @ (font ascent - (font ascent//3)) extent: g width @ 1).\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet methodsFor: 'emphasis' stamp: 'yo 12/27/2002 13:51'!\\nmakeUnderlinedGlyphs\\n\\t\\\"Make an underlined set of glyphs with same widths\\\"\\n\\n\\t| g font |\\n\\t1 to: fontArray size do: [:i |\\n\\t\\tfont _ (fontArray at: i).\\n\\t\\tfont ifNotNil: [\\n\\t\\t\\tg _ font glyphs deepCopy.\\n\\t\\t\\tg fillBlack: (0 @ (font ascent+1) extent: g width @ 1).\\n\\t\\t\\tfont setGlyphs: g\\n\\t\\t].\\n\\t].\\n! !\\n\\n\\n!StrikeFontSet methodsFor: '*nebraska-as yet unclassified' stamp: 'yo 12/17/2005 20:19'!\\nencodedForRemoteCanvas\\n\\n\\t| stream |\\n\\tstream := RWBinaryOrTextStream on: ''.\\n\\tstream nextPutAll: self familyName.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self pointSize asString.\\n\\tstream nextPut: Character space.\\n\\tstream nextPutAll: self emphasis asString.\\n\\t^ stream contents asString.\\n! !\\n\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 12/27/2002 13:39'!\\naddNewFont: aFont at: encodingIndex\\n\\n\\t| newArray |\\n\\tencodingIndex > fontArray size ifTrue: [\\n\\t\\tnewArray _ Array new: encodingIndex.\\n\\t\\tnewArray replaceFrom: 1 to: fontArray size with: fontArray startingAt: 1.\\n\\t] ifFalse: [\\n\\t\\tnewArray _ fontArray.\\n\\t].\\n\\n\\tnewArray at: encodingIndex put: aFont.\\n\\n\\tself initializeWithFontArray: newArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 1/7/2005 11:16'!\\nglyphInfoOf: aCharacter into: glyphInfoArray\\n\\n\\t| index f code leftX |\\n\\tindex _ aCharacter leadingChar + 1.\\n\\tfontArray size < index ifTrue: [^ self questionGlyphInfoInto: glyphInfoArray].\\n\\t(f _ fontArray at: index) ifNil: [^ self questionGlyphInfoInto: glyphInfoArray].\\n\\n\\tcode _ aCharacter charCode.\\n\\t((code between: f minAscii and: f maxAscii) not) ifTrue: [\\n\\t\\t^ self questionGlyphInfoInto: glyphInfoArray.\\n\\t].\\n\\tleftX _ f xTable at: code + 1.\\n\\tleftX < 0 ifTrue: [\\n\\t\\t^ self questionGlyphInfoInto: glyphInfoArray.\\n\\t].\\n\\tglyphInfoArray at: 1 put: f glyphs;\\n\\t\\tat: 2 put: leftX;\\n\\t\\tat: 3 put: (f xTable at: code + 2);\\n\\t\\tat: 4 put: (f ascentOf: aCharacter);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n!StrikeFontSet methodsFor: 'private' stamp: 'yo 1/13/2005 16:43'!\\nquestionGlyphInfoInto: glyphInfoArray\\n\\n\\t| f ascii |\\n\\tf _ fontArray at: 1.\\n\\tascii _ $? asciiValue.\\n\\tglyphInfoArray at: 1 put: f glyphs;\\n\\t\\tat: 2 put: (f xTable at: ascii + 1);\\n\\t\\tat: 3 put: (f xTable at: ascii + 2);\\n\\t\\tat: 4 put: (self ascentOf: $?);\\n\\t\\tat: 5 put: self.\\n\\t^ glyphInfoArray.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStrikeFontSet class\\n\\tinstanceVariableNames: ''!\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 1/19/2005 11:25'!\\ncreateExternalFontFileForLatin2: fileName\\n\\\"\\n\\tStrikeFontSet createExternalFontFileForLatin2: 'latin2.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b10.bdf' name: 'LatinTwo9' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'LatinTwo10' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'LatinTwo12' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b16.bdf' name: 'LatingTwo14' ranges: EFontBDFFontReaderForRanges rangesForLatin2)\\n\\t\\t\\t\\twith: (StrikeFont newFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'LatinTwo20' ranges: EFontBDFFontReaderForRanges rangesForLatin2).\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 5/25/2004 11:05'!\\ncreateExternalFontFileForUnicodeJapanese: fileName\\n\\\"\\n\\tStrikeFontSet createExternalFontFileForUnicodeJapanese: 'uJapaneseFont.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'Japanese10' overrideWith: 'shnmk12.bdf')\\n\\t\\t\\t\\twith: ((StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'Japanese12' overrideWith: 'shnmk14.bdf') \\\"fixAscent: 14 andDescent: 1 head: 1\\\")\\n\\t\\t\\t\\twith: ((StrikeFont newForJapaneseFromEFontBDFFile: 'b16.bdf' name: 'Japanese14' overrideWith: 'shnmk16.bdf') \\\"fixAscent: 16 andDescent: 4 head: 4\\\")\\n\\t\\t\\t\\twith: (StrikeFont newForJapaneseFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'Japanese18' overrideWith: 'kanji24.bdf').\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 1/15/2004 16:58'!\\ncreateExternalFontFileForUnicodeKorean: fileName\\n\\\"\\n\\tSmalltalk garbageCollect.\\n\\tStrikeFontSet createExternalFontFileForUnicodeKorean: 'uKoreanFont.out'.\\n\\\"\\n\\n\\t| file array f installDirectory |\\n\\tfile _ FileStream newFileNamed: fileName.\\n\\tinstallDirectory _ Smalltalk at: #M17nInstallDirectory ifAbsent: [].\\n\\tinstallDirectory _ installDirectory\\n\\t\\tifNil: [String new]\\n\\t\\tifNotNil: [installDirectory , FileDirectory pathNameDelimiter asString].\\n\\tarray _ Array\\n\\t\\t\\t\\twith: (StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b12.bdf' name: 'Japanese10' overrideWith: 'shnmk12.bdf')\\n\\t\\t\\t\\twith: ((StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b14.bdf' name: 'Japanese12' overrideWith: 'shnmk14.bdf') \\\"fixAscent: 14 andDescent: 1 head: 1\\\")\\n\\t\\t\\t\\twith: ((StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b16.bdf' name: 'Japanese14' overrideWith: 'hanglg16.bdf') fixAscent: 16 andDescent: 4 head: 4)\\n\\t\\t\\t\\twith: (StrikeFont newForKoreanFromEFontBDFFile: installDirectory , 'b24.bdf' name: 'Japanese18' overrideWith: 'hanglm24.bdf').\\n\\tTextConstants at: #forceFontWriting put: true.\\n\\tf _ ReferenceStream on: file.\\n\\tf nextPut: array.\\n\\tfile close.\\n\\tTextConstants removeKey: #forceFontWriting.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 12/17/2005 22:42'!\\ndecodedFromRemoteCanvas: aString\\n\\n\\t| array |\\n\\tarray _ aString findTokens: #($ ).\\n\\t^ self familyName: (array at: 1) size: (array at: 2) asNumber emphasized: (array at: 3) asNumber.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 12/27/2002 14:08'!\\nduplicateArrayElementsForLeadingCharShift\\n\\\"\\n\\tself duplicateArrayElementsForLeadingCharShift\\n\\\"\\n\\t| array font |\\n\\tself allInstances do: [:s |\\n\\t\\ts emphasis = 0 ifTrue: [\\n\\t\\t\\tarray _ s fontArray.\\n\\t\\t\\t2 to: (4 min: array size) do: [:i |\\n\\t\\t\\t\\tfont _ array at: i.\\n\\t\\t\\t\\ts addNewFont: font at: ((i - 1) << 2) + 1.\\n\\t\\t\\t].\\n\\t\\t] ifFalse: [\\n\\t\\t\\ts reset\\n\\t\\t].\\n\\t].\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 8/19/2003 13:04'!\\nfamilyName: aName size: aSize\\n\\t\\\"Answer a font (or the default font if the name is unknown) in the specified size.\\\"\\n\\n\\t| collection |\\n\\tcollection _ self allInstances select: [:inst | (inst name beginsWith: aName) and: [inst emphasis = 0]].\\n\\tcollection isEmpty ifTrue: [\\n\\t\\t(aName = 'DefaultMultiStyle') ifTrue: [\\n\\t\\t\\tcollection _ (TextConstants at: #DefaultMultiStyle) fontArray.\\n\\t\\t] ifFalse: [\\n\\t\\t\\t^ TextStyle defaultFont\\n\\t\\t]\\n\\t].\\n\\tcollection _ collection asSortedCollection: [:a :b | a pointSize <= b pointSize].\\n\\tcollection do: [:s | (s pointSize >= aSize) ifTrue: [^ s]].\\n\\t^ TextStyle defaultFont.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 8/18/2003 21:03'!\\nfamilyName: aName size: aSize emphasized: emphasisCode\\n\\t\\\"Create the font with this emphasis\\\"\\n\\n\\t^ (self familyName: aName size: aSize) emphasized: emphasisCode\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 5/25/2004 14:32'!\\nfindMaximumLessThan: f in: array\\n\\n\\tarray size to: 1 by: -1 do: [:i |\\n\\t\\tf height >= (array at: i) height ifTrue: [^ array at: i].\\n\\t].\\n\\t^ array first.\\n! !\\n\\n!StrikeFontSet class methodsFor: 'as yet unclassified' stamp: 'yo 9/23/2002 16:32'!\\nnewFontArray: anArray\\n \\n\\t^super new initializeWithFontArray: anArray\\n! !\\n\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 1/18/2005 16:00'!\\ninstallExternalFontFileName6: fileName encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t^ self installExternalFontFileName6: fileName inDir: FileDirectory default encoding: encoding encodingName: aString textStyleName: styleName.\\n\\n\\\"\\nStrikeFontSet createExternalFontFileForCyrillic: 'cyrillicFont.out'.\\n\\nStrikeFontSet installExternalFontFileName6: 'latin2.out' encoding: Latin2Environment leadingChar encodingName: #Latin2 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName6: 'uJapaneseFont.out' encoding: JapaneseEnvironment leadingChar encodingName: #Japanese textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName6: 'uKoreanFont.out' encoding: UnicodeKorean leadingChar encodingName: #Korean textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet removeFontsForEncoding: 2 encodingName: #Gb2312.\\nself halt.\\nStrikeFontSet removeFontsForEncoding: 3 encodingName: #KsX1001.\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/3/2005 17:40'!\\ninstallExternalFontFileName6: fileName inDir: dir encoding: encoding encodingName: aString textStyleName: styleName \\n\\t| aStream |\\n\\taStream := dir readOnlyFileNamed: fileName.\\n\\t[self\\n\\t\\tinstallExternalFontOn: aStream\\n\\t\\tencoding: encoding\\n\\t\\tencodingName: aString\\n\\t\\ttextStyleName: styleName]\\n\\t\\tensure: [aStream close]! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 3/17/2004 10:32'!\\ninstallExternalFontFileName: fileName encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t^ self installExternalFontFileName: fileName inDir: FileDirectory default encoding: encoding encodingName: aString textStyleName: styleName.\\n\\n\\\"\\nStrikeFontSet createExternalFontFileForCyrillic: 'cyrillicFont.out'.\\n\\nStrikeFontSet installExternalFontFileName: 'chineseFont.out' encoding: 2 encodingName: #Gb2312 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'japaneseFont.out' encoding: 1 encodingName: #JisX0208 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'defaultFont.out' encoding: 0 encodingName: #Latin1 textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'cyrillicFont.out' encoding: UnicodeCyrillic leadingChar encodingName: #Cyrillic textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'extendedLatinFont.out' encoding: UnicodeLatinExtendedAB leadingChar encodingName: #ExtendedLatin textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'ipaExtensionsFont.out' encoding: UnicodeIPA leadingChar encodingName: #IPAExtensions textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'armenianFont.out' encoding: UnicodeArmenian leadingChar encodingName: #Armenian textStyleName: #DefaultMultiStyle.\\nStrikeFontSet installExternalFontFileName: 'greekFont.out' encoding: UnicodeGreek leadingChar encodingName: #Greek textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'arrowFont.out' encoding: UnicodeArrows leadingChar encodingName: #Arrow textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'uJapaneseFont.out' indir: FileDirectory default encoding: JapaneseEnvironment leadingChar encodingName: #Japanese textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet installExternalFontFileName: 'uKoreanFont.out' encoding: UnicodeKorean leadingChar encodingName: #Korean textStyleName: #DefaultMultiStyle.\\n\\nStrikeFontSet removeFontsForEncoding: 2 encodingName: #Gb2312.\\nself halt.\\nStrikeFontSet removeFontsForEncoding: 3 encodingName: #KsX1001.\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 8/19/2003 00:32'!\\ninstallExternalFontFileName: fileName inDir: dir encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t| array arrayFour oldStyle arrayOfFS fs fonts newFonts |\\n\\tarray _ (ReferenceStream on: (dir readOnlyFileNamed: fileName)) next.\\n\\n\\tarrayFour _ Array new: 4 withAll: array last.\\n\\tarrayFour replaceFrom: 1 to: array size with: array startingAt: 1.\\n\\tTextConstants at: aString asSymbol put: arrayFour.\\n\\n\\toldStyle _ TextConstants at: styleName asSymbol.\\n\\tarrayOfFS _ oldStyle fontArray.\\n\\tarrayOfFS _ (1 to: 4) collect: [:i |\\n\\t\\tfs _ arrayOfFS at: i.\\n\\t\\tfonts _ fs fontArray.\\n\\t\\tencoding + 1 > fonts size ifTrue: [\\n\\t\\t\\tnewFonts _ Array new: encoding + 1.\\n\\t\\t\\tnewFonts replaceFrom: 1 to: fonts size with: fonts startingAt: 1.\\n\\t\\t\\tnewFonts at: encoding + 1 put: (arrayFour at: i).\\n\\t\\t\\tfs initializeWithFontArray: newFonts.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tfonts at: encoding + 1 put: (arrayFour at: i).\\n\\t\\t].\\n\\t\\tfs.\\n\\t].\\n\\n\\tTextConstants at: styleName asSymbol put: (TextStyle fontArray: arrayOfFS).\\n\\toldStyle becomeForward: (TextConstants at: styleName asSymbol).\\n\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/5/2005 10:34'!\\ninstallExternalFontOn: aStream encoding: encoding encodingName: aString textStyleName: styleName\\n\\n\\t| array fonts encodingIndex textStyle |\\n\\n\\tarray _ aStream\\n\\t\\tuntilEndWithFork: [(ReferenceStream on: aStream) next]\\n\\t\\tdisplayingProgress: 'Font reading...'. \\n\\t\\n\\tTextConstants at: aString asSymbol put: array.\\n\\n\\ttextStyle _ TextConstants at: styleName asSymbol.\\n\\tencodingIndex _ encoding + 1.\\n\\ttextStyle fontArray do: [:fs |\\n\\t\\tfonts _ fs fontArray.\\n\\t\\tencodingIndex > fonts size\\n\\t\\t\\tifTrue: [fonts _ (Array new: encodingIndex)\\n\\t\\t\\t\\treplaceFrom: 1 to: fonts size with: fonts startingAt: 1].\\n\\t\\tfonts at: encodingIndex put: (self findMaximumLessThan: fs fontArray first in: array).\\n\\t\\tfs initializeWithFontArray: fonts.\\n\\t].\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/4/2005 11:03'!\\ninstallExternalFontOn: aStream forLocale: locale \\n\\tself\\n\\t\\tinstallExternalFontOn: aStream\\n\\t\\tencoding: locale languageEnvironment leadingChar\\n\\t\\tencodingName: locale languageEnvironment fontEncodingName\\n\\t\\ttextStyleName: #DefaultMultiStyle! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'yo 1/15/2004 16:06'!\\ninstallNewFontAtIndex: newIndex fromOld: oldIndex\\n\\n\\t| fontArray newArray |\\n\\tself allInstances do: [:set |\\n\\t\\tfontArray _ set fontArray.\\n\\t\\tnewIndex + 1 > fontArray size ifTrue: [\\n\\t\\t\\tnewArray _ Array new: newIndex + 1.\\n\\t\\t\\tnewArray replaceFrom: 1 to: fontArray size with: fontArray startingAt: 1.\\n\\t\\t\\tnewArray at: newIndex + 1 put: (fontArray at: oldIndex + 1).\\n\\t\\t\\tset initializeWithFontArray: newArray.\\n\\t\\t] ifFalse: [\\n\\t\\t\\tfontArray at: newIndex + 1 put: (fontArray at: oldIndex + 1).\\n\\t\\t].\\n\\t].\\n\\n\\\"\\nStrikeFontSet installNewFontAtIndex: UnicodeSimplifiedChinese leadingChar fromOld: UnicodeJapanese leadingChar\\nStrikeFontSet installNewFontAtIndex: UnicodeKorean leadingChar fromOld: UnicodeJapanese leadingChar\\n\\\"\\n! !\\n\\n!StrikeFontSet class methodsFor: 'fileIn/Out' stamp: 'tak 8/4/2005 14:41'!\\nremoveFontsForEncoding: leadingChar encodingName: encodingSymbol\\n\\n\\t| insts fonts newFonts index |\\n\\tleadingChar = 0 ifTrue: [^ self error: 'you cannot delete the intrinsic fonts'].\\n\\tinsts _ self allInstances.\\n\\tinsts do: [:inst |\\n\\t\\tfonts _ inst fontArray.\\n\\t\\tfonts size >= (leadingChar + 1) ifTrue: [\\n\\t\\t\\tleadingChar + 1 = fonts size ifTrue: [\\n\\t\\t\\t\\tnewFonts _ fonts copyFrom: 1 to: fonts size - 1.\\n\\t\\t\\t\\tindex _ newFonts indexOf: nil.\\n\\t\\t\\t\\tindex > 0 ifTrue: [newFonts _ newFonts copyFrom: 1 to: index - 1].\\n\\t\\t\\t\\tinst initializeWithFontArray: newFonts.\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\tfonts at: leadingChar + 1 put: nil.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t].\\n\\n\\tTextConstants removeKey: encodingSymbol asSymbol ifAbsent: [].\\n! !\\nArrayedCollection subclass: #String\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'AsciiOrder CSLineEnders CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder HtmlEntities LowercasingTable Tokenish UppercasingTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Strings'!\\n!String commentStamp: '<historical>' prior: 0!\\nA String is an indexed collection of Characters. Class String provides the abstract super class for ByteString (that represents an array of 8-bit Characters) and WideString (that represents an array of 32-bit characters). In the similar manner of LargeInteger and SmallInteger, those subclasses are chosen accordingly for a string; namely as long as the system can figure out so, the String is used to represent the given string.\\n\\nStrings support a vast array of useful methods, which can best be learned by browsing and trying out examples as you find them in the code.\\n\\nHere are a few useful methods to look at...\\n\\tString match:\\n\\tString contractTo:\\n\\nString also inherits many useful methods from its hierarchy, such as\\n\\tSequenceableCollection ,\\n\\tSequenceableCollection copyReplaceAll:with:\\n!\\n]style[(55 376 188 13 2 18 72 24 2 44)f1,f2,f1,f1LString match:;,f1,f1LString contractTo:;,f1,f1LSequenceableCollection ,;,f1,f1LSequenceableCollection copyReplaceAll:with:;!\\n\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteAt: index\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteAt: index put: value\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:30'!\\nbyteSize\\n\\t^self subclassResponsibility! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\ndo: aBlock toFieldNumber: aNumber\\n\\t\\\"Considering the receiver as a holder of tab-delimited fields, evaluate aBlock on behalf of a field in this string\\\"\\n\\n\\t| start end index |\\n\\tstart _ 1.\\n\\tindex _ 1.\\n\\t[start <= self size] whileTrue: \\n\\t\\t[end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1].\\n\\t\\tend _ end - 1.\\n\\t\\taNumber = index ifTrue:\\n\\t\\t\\t[aBlock value: (self copyFrom: start to: end).\\n\\t\\t\\t^ self].\\n\\t\\tindex _ index + 1.\\n\\t\\tstart _ end + 2]\\n\\n\\\"\\n1 to: 6 do:\\n\\t[:aNumber |\\n\\t\\t'fred\\tcharlie\\telmo\\t\\twimpy\\tfriml' do:\\n\\t\\t\\t[:aField | Transcript cr; show: aField] toFieldNumber: aNumber]\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nendsWithDigit\\n\\t\\\"Answer whether the receiver's final character represents a digit. 3/11/96 sw\\\"\\n\\n\\t^ self size > 0 and: [self last isDigit]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 17:12'!\\nfindAnySubStr: delimiters startingAt: start \\n\\t\\\"Answer the index of the character within the receiver, starting at start, that begins a substring matching one of the delimiters. delimiters is an Array of Strings (Characters are permitted also). If the receiver does not contain any of the delimiters, answer size + 1.\\\"\\n\\n\\t| min ind |\\n\\tmin _ self size + 1.\\n\\tdelimiters do: [:delim |\\t\\\"May be a char, a string of length 1, or a substring\\\"\\n\\t\\tdelim isCharacter \\n\\t\\t\\tifTrue: [ind _ self indexOfSubCollection: (String with: delim) \\n\\t\\t\\t\\t\\t\\tstartingAt: start ifAbsent: [min]]\\n\\t\\t\\tifFalse: [ind _ self indexOfSubCollection: delim \\n\\t\\t\\t\\t\\t\\tstartingAt: start ifAbsent: [min]].\\n\\t\\t\\tmin _ min min: ind].\\n\\t^ min! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindBetweenSubStrs: delimiters\\n\\t\\\"Answer the collection of String tokens that result from parsing self. Tokens are separated by 'delimiters', which can be a collection of Strings, or a collection of Characters. Several delimiters in a row are considered as just one separation.\\\"\\n\\n\\t| tokens keyStart keyStop |\\n\\ttokens _ OrderedCollection new.\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipAnySubStr: delimiters startingAt: keyStop.\\n\\t\\tkeyStop _ self findAnySubStr: delimiters startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindCloseParenthesisFor: startIndex\\n\\t\\\"assume (self at: startIndex) is $(. Find the matching $), allowing parentheses to nest.\\\"\\n\\t\\\" '(1+(2-3))-3.14159' findCloseParenthesisFor: 1 \\\"\\n\\t\\\" '(1+(2-3))-3.14159' findCloseParenthesisFor: 4 \\\"\\n\\t| pos nestLevel |\\n\\tpos := startIndex+1.\\n\\tnestLevel := 1.\\n\\t[ pos <= self size ] whileTrue: [\\n\\t\\t(self at: pos) = $( ifTrue: [ nestLevel := nestLevel + 1 ].\\n\\t\\t(self at: pos) = $) ifTrue: [ nestLevel := nestLevel - 1 ].\\n\\t\\tnestLevel = 0 ifTrue: [ ^pos ].\\n\\t\\tpos := pos + 1.\\n\\t].\\n\\t^self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindDelimiters: delimiters startingAt: start \\n\\t\\\"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.\\\"\\n\\n\\tstart to: self size do: [:i |\\n\\t\\tdelimiters do: [:delim | delim = (self at: i) ifTrue: [^ i]]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 10/15/2003 15:32'!\\nfindLastOccuranceOfString: subString startingAt: start \\n\\t\\\"Answer the index of the last occurance of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\n\\t| last now |\\n\\tlast _ self findSubstring: subString in: self startingAt: start matchTable: CaseSensitiveOrder.\\n\\tlast = 0 ifTrue: [^ 0].\\n\\t[last > 0] whileTrue: [\\n\\t\\tnow _ last.\\n\\t\\tlast _ self findSubstring: subString in: self startingAt: last + subString size matchTable: CaseSensitiveOrder.\\n\\t].\\n\\n\\t^ now.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: subString\\n\\t\\\"Answer the index of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\t^self findString: subString startingAt: 1.! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: subString startingAt: start \\n\\t\\\"Answer the index of subString within the receiver, starting at start. If \\n\\tthe receiver does not contain subString, answer 0.\\\"\\n\\n\\t^ self findSubstring: subString in: self startingAt: start matchTable: CaseSensitiveOrder! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindString: key startingAt: start caseSensitive: caseSensitive\\n\\t\\\"Answer the index in this String at which the substring key first occurs, at or beyond start. The match can be case-sensitive or not. If no match is found, zero will be returned.\\\"\\n\\n\\tcaseSensitive\\n\\tifTrue: [^ self findSubstring: key in: self startingAt: start matchTable: CaseSensitiveOrder]\\n\\tifFalse: [^ self findSubstring: key in: self startingAt: start matchTable: CaseInsensitiveOrder]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 17:13'!\\nfindTokens: delimiters\\n\\t\\\"Answer the collection of tokens that result from parsing self. Return strings between the delimiters. Any character in the Collection delimiters marks a border. Several delimiters in a row are considered as just one separation. Also, allow delimiters to be a single character.\\\"\\n\\n\\t| tokens keyStart keyStop separators |\\n\\n\\ttokens _ OrderedCollection new.\\n\\tseparators _ delimiters isCharacter \\n\\t\\tifTrue: [Array with: delimiters]\\n\\t\\tifFalse: [delimiters].\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipDelimiters: separators startingAt: keyStop.\\n\\t\\tkeyStop _ self findDelimiters: separators startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'dtl 8/14/2004 11:27'!\\nfindTokens: delimiters escapedBy: quoteDelimiters \\n\\t\\\"Answer a collection of Strings separated by the delimiters, where \\n\\tdelimiters is a Character or collection of characters. Two delimiters in a \\n\\trow produce an empty string (compare this to #findTokens, which \\n\\ttreats sequential delimiters as one). \\n\\t \\n\\tThe characters in quoteDelimiters are treated as quote characters, such \\n\\tthat any delimiter within a pair of matching quoteDelimiter characters \\n\\tis treated literally, rather than as a delimiter. \\n\\t \\n\\tThe quoteDelimiter characters may be escaped within a quoted string. \\n\\tTwo sequential quote characters within a quoted string are treated as \\n\\ta single character. \\n\\t \\n\\tThis method is useful for parsing comma separated variable strings for \\n\\tspreadsheet import and export.\\\"\\n\\n\\t| tokens rs activeEscapeCharacter ts char token delimiterChars quoteChars |\\n\\tdelimiterChars _ (delimiters isNil\\n\\t\\t\\t\\tifTrue: ['']\\n\\t\\t\\t\\tifFalse: [delimiters]) asString.\\n\\tquoteChars _ (quoteDelimiters isNil\\n\\t\\t\\t\\tifTrue: ['']\\n\\t\\t\\t\\tifFalse: [quoteDelimiters]) asString.\\n\\ttokens _ OrderedCollection new.\\n\\trs _ ReadStream on: self.\\n\\tactiveEscapeCharacter _ nil.\\n\\tts _ WriteStream on: ''.\\n\\t[rs atEnd]\\n\\t\\twhileFalse: [char _ rs next.\\n\\t\\t\\tactiveEscapeCharacter isNil\\n\\t\\t\\t\\tifTrue: [(quoteChars includes: char)\\n\\t\\t\\t\\t\\t\\tifTrue: [activeEscapeCharacter _ char]\\n\\t\\t\\t\\t\\t\\tifFalse: [(delimiterChars includes: char)\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [token _ ts contents.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttokens add: token.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tts _ WriteStream on: '']\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [ts nextPut: char]]]\\n\\t\\t\\t\\tifFalse: [char == activeEscapeCharacter\\n\\t\\t\\t\\t\\t\\tifTrue: [rs peek == activeEscapeCharacter\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [ts nextPut: rs next]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [activeEscapeCharacter _ nil]]\\n\\t\\t\\t\\t\\t\\tifFalse: [ts nextPut: char]]].\\n\\ttoken _ ts contents.\\n\\t(tokens isEmpty and: [token isEmpty])\\n\\t\\tifFalse: [tokens add: token].\\n\\t^ tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindTokens: delimiters includes: subString\\n\\t\\\"Divide self into pieces using delimiters. Return the piece that includes subString anywhere in it. Is case sensitive (say asLowercase to everything beforehand to make insensitive).\\\"\\n\\n^ (self findTokens: delimiters) \\n\\tdetect: [:str | (str includesSubString: subString)] \\n\\tifNone: [nil]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindTokens: delimiters keep: keepers\\n\\t\\\"Answer the collection of tokens that result from parsing self. The tokens are seperated by delimiters, any of a string of characters. If a delimiter is also in keepers, make a token for it. (Very useful for carriage return. A sole return ends a line, but is also saved as a token so you can see where the line breaks were.)\\\"\\n\\n\\t| tokens keyStart keyStop |\\n\\ttokens _ OrderedCollection new.\\n\\tkeyStop _ 1.\\n\\t[keyStop <= self size] whileTrue:\\n\\t\\t[keyStart _ self skipDelimiters: delimiters startingAt: keyStop.\\n\\t\\tkeyStop to: keyStart-1 do: [:ii | \\n\\t\\t\\t(keepers includes: (self at: ii)) ifTrue: [\\n\\t\\t\\t\\ttokens add: (self copyFrom: ii to: ii)]].\\t\\\"Make this keeper be a token\\\"\\n\\t\\tkeyStop _ self findDelimiters: delimiters startingAt: keyStart.\\n\\t\\tkeyStart < keyStop\\n\\t\\t\\tifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].\\n\\t^tokens! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nfindWordStart: key startingAt: start\\n\\t| ind |\\n\\t\\\"HyperCard style searching. Answer the index in self of the substring key, when that key is preceeded by a separator character. Must occur at or beyond start. The match is case-insensitive. If no match is found, zero will be returned.\\\"\\n\\n\\tind _ start.\\n\\t[ind _ self findSubstring: key in: self startingAt: ind matchTable: CaseInsensitiveOrder.\\n\\tind = 0 ifTrue: [^ 0].\\t\\\"not found\\\"\\n\\tind = 1 ifTrue: [^ 1].\\t\\\"First char is the start of a word\\\"\\n\\t(self at: ind-1) isSeparator] whileFalse: [ind _ ind + 1].\\n\\t^ ind\\t\\\"is a word start\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nincludesSubString: subString\\n\\t^ (self findString: subString startingAt: 1) > 0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nincludesSubstring: aString caseSensitive: caseSensitive\\n\\t\\n\\t^ (self findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/28/2002 16:45'!\\nindexOf: aCharacter\\n\\n\\taCharacter isCharacter ifFalse: [^ 0].\\n\\t^ self class\\n\\t\\tindexOfAscii: aCharacter asciiValue\\n\\t\\tinString: self\\n\\t\\tstartingAt: 1.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:31'!\\nindexOf: aCharacter startingAt: start\\n\\n\\t(aCharacter isCharacter) ifFalse: [^ 0].\\n\\t^ self class indexOfAscii: aCharacter asciiValue inString: self startingAt: start! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/12/2005 16:31'!\\nindexOf: aCharacter startingAt: start ifAbsent: aBlock\\n\\t| ans |\\n\\t(aCharacter isCharacter) ifFalse: [ ^ aBlock value ].\\n\\tans _ self class indexOfAscii: aCharacter asciiValue inString: self startingAt: start.\\n\\tans = 0\\n\\t\\tifTrue: [ ^ aBlock value ]\\n\\t\\tifFalse: [ ^ ans ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet\\n\\t\\\"returns the index of the first character in the given set. Returns 0 if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet ifAbsent: aBlock\\n\\t\\\"returns the index of the first character in the given set. Returns the evaluation of aBlock if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: 1 ifAbsent: aBlock! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfAnyOf: aCharacterSet startingAt: start\\n\\t\\\"returns the index of the first character in the given set, starting from start. Returns 0 if none are found\\\"\\n\\t^self indexOfAnyOf: aCharacterSet startingAt: start ifAbsent: [ 0 ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'ar 4/10/2005 16:22'!\\nindexOfAnyOf: aCharacterSet startingAt: start ifAbsent: aBlock\\n\\t\\\"returns the index of the first character in the given set, starting from start\\\"\\n\\n\\t| ans |\\n\\tans _ self class findFirstInString: self inSet: aCharacterSet byteArrayMap startingAt: start.\\n\\n\\tans = 0 \\n\\t\\tifTrue: [ ^aBlock value ]\\n\\t\\tifFalse: [ ^ans ]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfSubCollection: sub \\n\\t#Collectn.\\n\\t\\\"Added 2000/04/08 For ANSI <sequenceReadableCollection> protocol.\\\"\\n\\t^ self\\n\\t\\tindexOfSubCollection: sub\\n\\t\\tstartingAt: 1\\n\\t\\tifAbsent: [0]! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nindexOfSubCollection: sub startingAt: start ifAbsent: exceptionBlock\\n\\t| index |\\n\\tindex _ self findSubstring: sub in: self startingAt: start matchTable: CaseSensitiveOrder.\\n\\tindex = 0 ifTrue: [^ exceptionBlock value].\\n\\t^ index! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nlastIndexOfPKSignature: aSignature\\n\\t\\\"Answer the last index in me where aSignature (4 bytes long) occurs, or 0 if not found\\\"\\n\\t| a b c d |\\n\\ta _ aSignature first.\\n\\tb _ aSignature second.\\n\\tc _ aSignature third.\\n\\td _ aSignature fourth.\\n\\t(self size - 3) to: 1 by: -1 do: [ :i |\\n\\t\\t(((self at: i) = a)\\n\\t\\t\\tand: [ ((self at: i + 1) = b)\\n\\t\\t\\t\\tand: [ ((self at: i + 2) = c)\\n\\t\\t\\t\\t\\tand: [ ((self at: i + 3) = d) ]]])\\n\\t\\t\\t\\t\\t\\tifTrue: [ ^i ]\\n\\t].\\n\\t^0! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 12/17/2002 16:56'!\\nleadingCharRunLengthAt: index\\n\\n\\t| leadingChar |\\n\\tleadingChar _ (self at: index) leadingChar.\\n\\tindex to: self size do: [:i |\\n\\t\\t(self at: i) leadingChar ~= leadingChar ifTrue: [^ i - index].\\n\\t].\\n\\t^ self size - index + 1.\\n! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:33'!\\nlineCorrespondingToIndex: anIndex\\n\\t\\\"Answer a string containing the line at the given character position. 1/15/96 sw: Inefficient first stab at this\\\"\\n\\n\\t| cr aChar answer |\\n\\tcr _ Character cr.\\n\\tanswer _ ''.\\n\\t1 to: self size do:\\n\\t\\t[:i | \\n\\t\\t\\taChar _ self at: i.\\n\\t\\t\\taChar = cr\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[i > anIndex\\n\\t\\t\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t\\t\\t[^ answer]\\n\\t\\t\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t\\t\\t[answer _ '']]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[answer _ answer copyWith: aChar]].\\n\\t^ answer! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:34'!\\nlineCount\\n\\t\\\"Answer the number of lines represented by the receiver, where every cr adds one line. 5/10/96 sw\\\"\\n\\n\\t| cr count |\\n\\tcr _ Character cr.\\n\\tcount _ 1 min: self size..\\n\\t1 to: self size do:\\n\\t\\t[:i | (self at: i) = cr ifTrue: [count _ count + 1]].\\n\\t^ count\\n\\n\\\"\\n'Fred\\nthe\\nBear' lineCount\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/27/2002 14:34'!\\nlineNumber: anIndex\\n\\t\\\"Answer a string containing the characters in the given line number. 5/10/96 sw\\\"\\n\\n\\t| crString pos finalPos |\\n\\tcrString _ String with: Character cr.\\n\\tpos _ 0.\\n\\t1 to: anIndex - 1 do:\\n\\t\\t[:i | pos _ self findString: crString startingAt: pos + 1.\\n\\t\\t\\tpos = 0 ifTrue: [^ nil]].\\n\\tfinalPos _ self findString: crString startingAt: pos + 1.\\n\\tfinalPos = 0 ifTrue: [finalPos _ self size + 1].\\n\\t^ self copyFrom: pos + 1 to: finalPos - 1\\n\\n\\\"\\n'Fred\\nthe\\nBear' lineNumber: 3\\n\\\"! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nlinesDo: aBlock\\n\\t\\\"execute aBlock with each line in this string. The terminating CR's are not included in what is passed to aBlock\\\"\\n\\t| start end |\\n\\tstart _ 1.\\n\\t[ start <= self size ] whileTrue: [\\n\\t\\tend _ self indexOf: Character cr startingAt: start ifAbsent: [ self size + 1 ].\\n\\t\\tend _ end - 1.\\n\\n\\t\\taBlock value: (self copyFrom: start to: end).\\n\\t\\tstart _ end + 2. ].! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 8/28/2002 14:28'!\\nskipAnySubStr: delimiters startingAt: start \\n\\t\\\"Answer the index of the last character within the receiver, starting at start, that does NOT match one of the delimiters. delimiters is a Array of substrings (Characters also allowed). If the receiver is all delimiters, answer size + 1.\\\"\\n\\n\\t| any this ind ii |\\n\\tii _ start-1.\\n\\t[(ii _ ii + 1) <= self size] whileTrue: [ \\\"look for char that does not match\\\"\\n\\t\\tany _ false.\\n\\t\\tdelimiters do: [:delim |\\n\\t\\t\\tdelim isCharacter \\n\\t\\t\\t\\tifTrue: [(self at: ii) == delim ifTrue: [any _ true]]\\n\\t\\t\\t\\tifFalse: [\\\"a substring\\\"\\n\\t\\t\\t\\t\\tdelim size > (self size - ii + 1) ifFalse: \\\"Here's where the one-off error was.\\\"\\n\\t\\t\\t\\t\\t\\t[ind _ 0.\\n\\t\\t\\t\\t\\t\\tthis _ true.\\n\\t\\t\\t\\t\\t\\tdelim do: [:dd | \\n\\t\\t\\t\\t\\t\\t\\tdd == (self at: ii+ind) ifFalse: [this _ false].\\n\\t\\t\\t\\t\\t\\t\\tind _ ind + 1].\\n\\t\\t\\t\\t\\t\\tthis ifTrue: [ii _ ii + delim size - 1. any _ true]]\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [any _ false] \\\"if the delim is too big, it can't match\\\"]].\\n\\t\\tany ifFalse: [^ ii]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nskipDelimiters: delimiters startingAt: start \\n\\t\\\"Answer the index of the character within the receiver, starting at start, that does NOT match 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.\\\"\\n\\n\\tstart to: self size do: [:i |\\n\\t\\tdelimiters detect: [:delim | delim = (self at: i)]\\n\\t\\t\\t\\tifNone: [^ i]].\\n\\t^ self size + 1! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\nstartsWithDigit\\n\\t\\\"Answer whether the receiver's first character represents a digit\\\"\\n\\n\\t^ self size > 0 and: [self first isDigit]! !\\n\\n!String methodsFor: 'accessing' stamp: 'md 5/26/2005 13:35'!\\nstring\\n\\t^self! !\\n\\n!String methodsFor: 'accessing' stamp: 'yo 11/3/2004 19:24'!\\ntabDelimitedFieldsDo: aBlock\\n\\t\\\"Considering the receiver as a holder of tab-delimited fields, evaluate execute aBlock with each field in this string. The separatilng tabs are not included in what is passed to aBlock\\\"\\n\\n\\t| start end |\\n\\t\\\"No senders but was useful enough in earlier work that it's retained for the moment.\\\"\\n\\tstart _ 1.\\n\\t[start <= self size] whileTrue: \\n\\t\\t[end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1].\\n\\t\\tend _ end - 1.\\n\\t\\taBlock value: (self copyFrom: start to: end).\\n\\t\\tstart _ end + 2]\\n\\n\\\"\\n'fred\\tcharlie\\telmo\\t\\t2' tabDelimitedFieldsDo: [:aField | Transcript cr; show: aField]\\n\\\"! !\\n\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n* arg\\n\\n\\t^ arg adaptToString: self andSend: #*! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n+ arg\\n\\n\\t^ arg adaptToString: self andSend: #+! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n- arg\\n\\n\\t^ arg adaptToString: self andSend: #-! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n/ arg\\n\\n\\t^ arg adaptToString: self andSend: #/! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n// arg\\n\\n\\t^ arg adaptToString: self andSend: #//! !\\n\\n!String methodsFor: 'arithmetic' stamp: 'yo 11/3/2004 19:24'!\\n\\\\\\\\ arg\\n\\n\\t^ arg adaptToString: self andSend: #\\\\\\\\! !\\n\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:19'!\\n< aString \\n\\t\\\"Answer whether the receiver sorts before aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 1! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:20'!\\n<= aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\t\\n\\t^ (self compare: self with: aString collated: AsciiOrder) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n= aString \\n\\t\\\"Answer whether the receiver sorts equally as aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\t\\n\\taString isString ifFalse: [ ^ false ].\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n> aString \\n\\t\\\"Answer whether the receiver sorts after aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) = 3! !\\n\\n!String methodsFor: 'comparing' stamp: 'lr 7/7/2006 11:21'!\\n>= aString \\n\\t\\\"Answer whether the receiver sorts after or equal to aString.\\n\\tThe collation order is simple ascii (with case differences).\\\"\\n\\n\\t^ (self compare: self with: aString collated: AsciiOrder) >= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nalike: aString \\n\\t\\\"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.\\\"\\n\\n\\t| i j k minSize bonus |\\n\\tminSize _ (j _ self size) min: (k _ aString size).\\n\\tbonus _ (j - k) abs < 2 ifTrue: [ 1 ] ifFalse: [ 0 ].\\n\\ti _ 1.\\n\\t[(i <= minSize) and: [((super at: i) bitAnd: 16rDF) = ((aString at: i) asciiValue bitAnd: 16rDF)]]\\n\\t\\twhileTrue: [ i _ i + 1 ].\\n\\t[(j > 0) and: [(k > 0) and:\\n\\t\\t[((super at: j) bitAnd: 16rDF) = ((aString at: k) asciiValue bitAnd: 16rDF)]]]\\n\\t\\t\\twhileTrue: [ j _ j - 1. k _ k - 1. ].\\n\\t^ i - 1 + self size - j + bonus. ! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nbeginsWith: prefix\\n\\t\\\"Answer whether the receiver begins with the given prefix string.\\n\\tThe comparison is case-sensitive.\\\"\\n\\n\\tself size < prefix size ifTrue: [^ false].\\n\\t^ (self findSubstring: prefix in: self startingAt: 1\\n\\t\\t\\tmatchTable: CaseSensitiveOrder) = 1\\n! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:39'!\\ncaseInsensitiveLessOrEqual: aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is case insensitive.\\\"\\n\\t^(self compare: aString caseSensitive: false) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:39'!\\ncaseSensitiveLessOrEqual: aString \\n\\t\\\"Answer whether the receiver sorts before or equal to aString.\\n\\tThe collation order is case sensitive.\\\"\\n\\t^(self compare: aString caseSensitive: true) <= 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 8/27/2002 14:15'!\\ncharactersExactlyMatching: aString\\n\\t\\\"Do a character-by-character comparison between the receiver and aString. Return the index of the final character that matched exactly.\\\"\\n\\n\\t| count |\\n\\tcount _ self size min: aString size.\\n\\t1 to: count do: [:i | \\n\\t\\t(self at: i) = (aString at: i) ifFalse: [\\n\\t\\t\\t^ i - 1]].\\n\\t^ count! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:38'!\\ncompare: aString \\n\\t\\\"Answer a comparison code telling how the receiver sorts relative to aString:\\n\\t\\t1 - before\\n\\t\\t2 - equal\\n\\t\\t3 - after.\\n\\tThe collation sequence is ascii with case differences ignored.\\n\\tTo get the effect of a <= b, but ignoring case, use (a compare: b) <= 2.\\\"\\n\\t^self compare: aString caseSensitive: false! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 16:42'!\\ncompare: aString caseSensitive: aBool\\n\\t\\\"Answer a comparison code telling how the receiver sorts relative to aString:\\n\\t\\t1 - before\\n\\t\\t2 - equal\\n\\t\\t3 - after.\\n\\t\\\"\\n\\t| map |\\n\\tmap := aBool ifTrue:[CaseSensitiveOrder] ifFalse:[CaseInsensitiveOrder].\\n\\t^self compare: self with: aString collated: map! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 12/15/2005 14:28'!\\ncompare: string1 with: string2 collated: order\\n\\n\\t(string1 isByteString and: [string2 isByteString]) ifTrue: [\\n\\t\\t^ ByteString compare: string1 with: string2 collated: order\\n\\t].\\n \\\"Primitive does not fail properly right now\\\"\\n ^ String compare: string1 with: string2 collated: order\\n\\n\\\"\\nself assert: 'abc' = 'abc' asWideString.\\nself assert: 'abc' asWideString = 'abc'.\\nself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString ~= 'a000' asWideString).\\nself assert: ('a000' asWideString ~= (ByteArray with: 97 with: 0 with: 0 with: 0) asString).\\n\\nself assert: ('abc' sameAs: 'aBc' asWideString).\\nself assert: ('aBc' asWideString sameAs: 'abc').\\nself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString sameAs: 'Abcd' asWideString) not.\\nself assert: ('a000' asWideString sameAs: (ByteArray with: 97 with: 0 with: 0 with: 0) asString) not.\\n\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 17:27'!\\ncrc16\\n\\t\\\"Compute a 16 bit cyclic redundancy check.\\\"\\n\\n\\t| crc |\\n\\tcrc := 0.\\n\\t1 to: self byteSize do: [:i |\\n\\t\\tcrc := (crc bitShift: -8) bitXor: (\\n\\t\\t #(\\t16r0000\\t16rC0C1\\t16rC181\\t16r0140\\t16rC301\\t16r03C0\\t16r0280\\t16rC241\\n\\t\\t\\t16rC601\\t16r06C0\\t16r0780\\t16rC741\\t16r0500\\t16rC5C1\\t16rC481\\t16r0440\\n\\t\\t\\t16rCC01\\t16r0CC0\\t16r0D80\\t16rCD41\\t16r0F00\\t16rCFC1\\t16rCE81\\t16r0E40\\n\\t\\t\\t16r0A00\\t16rCAC1\\t16rCB81\\t16r0B40\\t16rC901\\t16r09C0\\t16r0880\\t16rC841\\n\\t\\t\\t16rD801\\t16r18C0\\t16r1980\\t16rD941\\t16r1B00\\t16rDBC1\\t16rDA81\\t16r1A40\\n\\t\\t\\t16r1E00\\t16rDEC1\\t16rDF81\\t16r1F40\\t16rDD01\\t16r1DC0\\t16r1C80\\t16rDC41\\n\\t\\t\\t16r1400\\t16rD4C1\\t16rD581\\t16r1540\\t16rD701\\t16r17C0\\t16r1680\\t16rD641\\n\\t\\t\\t16rD201\\t16r12C0\\t16r1380\\t16rD341\\t16r1100\\t16rD1C1\\t16rD081\\t16r1040\\n\\t\\t\\t16rF001\\t16r30C0\\t16r3180\\t16rF141\\t16r3300\\t16rF3C1\\t16rF281\\t16r3240\\n\\t\\t\\t16r3600\\t16rF6C1\\t16rF781\\t16r3740\\t16rF501\\t16r35C0\\t16r3480\\t16rF441\\n\\t\\t\\t16r3C00\\t16rFCC1\\t16rFD81\\t16r3D40\\t16rFF01\\t16r3FC0\\t16r3E80\\t16rFE41\\n\\t\\t\\t16rFA01\\t16r3AC0\\t16r3B80\\t16rFB41\\t16r3900\\t16rF9C1\\t16rF881\\t16r3840\\n\\t\\t\\t16r2800\\t16rE8C1\\t16rE981\\t16r2940\\t16rEB01\\t16r2BC0\\t16r2A80\\t16rEA41\\n\\t\\t\\t16rEE01\\t16r2EC0\\t16r2F80\\t16rEF41\\t16r2D00\\t16rEDC1\\t16rEC81\\t16r2C40\\n\\t\\t\\t16rE401\\t16r24C0\\t16r2580\\t16rE541\\t16r2700\\t16rE7C1\\t16rE681\\t16r2640\\n\\t\\t\\t16r2200\\t16rE2C1\\t16rE381\\t16r2340\\t16rE101\\t16r21C0\\t16r2080\\t16rE041\\n\\t\\t\\t16rA001\\t16r60C0\\t16r6180\\t16rA141\\t16r6300\\t16rA3C1\\t16rA281\\t16r6240\\n\\t\\t\\t16r6600\\t16rA6C1\\t16rA781\\t16r6740\\t16rA501\\t16r65C0\\t16r6480\\t16rA441\\n\\t\\t\\t16r6C00\\t16rACC1\\t16rAD81\\t16r6D40\\t16rAF01\\t16r6FC0\\t16r6E80\\t16rAE41\\n\\t\\t\\t16rAA01\\t16r6AC0\\t16r6B80\\t16rAB41\\t16r6900\\t16rA9C1\\t16rA881\\t16r6840\\n\\t\\t\\t16r7800\\t16rB8C1\\t16rB981\\t16r7940\\t16rBB01\\t16r7BC0\\t16r7A80\\t16rBA41\\n\\t\\t\\t16rBE01\\t16r7EC0\\t16r7F80\\t16rBF41\\t16r7D00\\t16rBDC1\\t16rBC81\\t16r7C40\\n\\t\\t\\t16rB401\\t16r74C0\\t16r7580\\t16rB541\\t16r7700\\t16rB7C1\\t16rB681\\t16r7640\\n\\t\\t\\t16r7200\\t16rB2C1\\t16rB381\\t16r7340\\t16rB101\\t16r71C0\\t16r7080\\t16rB041\\n\\t\\t\\t16r5000\\t16r90C1\\t16r9181\\t16r5140\\t16r9301\\t16r53C0\\t16r5280\\t16r9241\\n\\t\\t\\t16r9601\\t16r56C0\\t16r5780\\t16r9741\\t16r5500\\t16r95C1\\t16r9481\\t16r5440\\n\\t\\t\\t16r9C01\\t16r5CC0\\t16r5D80\\t16r9D41\\t16r5F00\\t16r9FC1\\t16r9E81\\t16r5E40\\n\\t\\t\\t16r5A00\\t16r9AC1\\t16r9B81\\t16r5B40\\t16r9901\\t16r59C0\\t16r5880\\t16r9841\\n\\t\\t\\t16r8801\\t16r48C0\\t16r4980\\t16r8941\\t16r4B00\\t16r8BC1\\t16r8A81\\t16r4A40\\n\\t\\t\\t16r4E00\\t16r8EC1\\t16r8F81\\t16r4F40\\t16r8D01\\t16r4DC0\\t16r4C80\\t16r8C41\\n\\t\\t\\t16r4400\\t16r84C1\\t16r8581\\t16r4540\\t16r8701\\t16r47C0\\t16r4680\\t16r8641\\n\\t\\t\\t16r8201\\t16r42C0\\t16r4380\\t16r8341\\t16r4100\\t16r81C1\\t16r8081\\t16r4040)\\n\\t\\t\\t at: ((crc bitXor: (self byteAt: i)) bitAnd: 16rFF) + 1) ].\\n\\t^crc! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nendsWith: suffix\\n\\t\\\"Answer whether the tail end of the receiver is the same as suffix.\\n\\tThe comparison is case-sensitive.\\\"\\n\\t| extra |\\n\\t(extra _ self size - suffix size) < 0 ifTrue: [^ false].\\n\\t^ (self findSubstring: suffix in: self startingAt: extra + 1\\n\\t\\t\\tmatchTable: CaseSensitiveOrder) > 0\\n\\\"\\n 'Elvis' endsWith: 'vis'\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nendsWithAnyOf: aCollection\\n\\taCollection do:[:suffix|\\n\\t\\t(self endsWith: suffix) ifTrue:[^true].\\n\\t].\\n\\t^false! !\\n\\n!String methodsFor: 'comparing' stamp: 'md 2/16/2006 17:49'!\\nhash\\n\\t\\\"#hash is implemented, because #= is implemented\\\"\\n\\t\\\"ar 4/10/2005: I had to change this to use ByteString hash as initial \\n\\thash in order to avoid having to rehash everything and yet compute\\n\\tthe same hash for ByteString and WideString.\\n\\tmd 16/10/2006: use identityHash as initialHash, as behavior hash will \\n use String hash (name) to have a better hash soon\\\"\\n\\t^ self class stringHash: self initialHash: ByteString identityHash! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nhashMappedBy: map\\n\\t\\\"My hash is independent of my oop.\\\"\\n\\n\\t^self hash! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nhowManyMatch: string \\n\\t\\\"Count the number of characters that match up in self and aString.\\\"\\n\\t| count shorterLength |\\n\\t\\n\\tcount _ 0 .\\n\\tshorterLength _ ((self size ) min: (string size ) ) .\\n\\t(1 to: shorterLength do: [:index |\\n\\t\\t (((self at: index ) = (string at: index ) ) ifTrue: [count _ (count + 1 ) .\\n\\t\\t\\t] ).\\n\\t\\t] ).\\n\\t^ count \\n\\t\\n\\t! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nmatch: text\\n\\t\\\"Answer whether text matches the pattern in this string.\\n\\tMatching ignores upper/lower case differences.\\n\\tWhere this string contains #, text may contain any character.\\n\\tWhere this string contains *, text may contain any sequence of characters.\\\"\\n\\n\\t^ self startingAt: 1 match: text startingAt: 1\\n\\\"\\n\\t'*'\\t\\t\\tmatch: 'zort' true\\n\\t'*baz'\\t\\tmatch: 'mobaz' true\\n\\t'*baz'\\t\\tmatch: 'mobazo' false\\n\\t'*baz*'\\t\\tmatch: 'mobazo' true\\n\\t'*baz*'\\t\\tmatch: 'mozo' false\\n\\t'foo*'\\t\\tmatch: 'foozo' true\\n\\t'foo*'\\t\\tmatch: 'bozo' false\\n\\t'foo*baz'\\tmatch: 'foo23baz' true\\n\\t'foo*baz'\\tmatch: 'foobaz' true\\n\\t'foo*baz'\\tmatch: 'foo23bazo' false\\n\\t'foo'\\t\\tmatch: 'Foo' true\\n\\t'foo*baz*zort' match: 'foobazort' false\\n\\t'foo*baz*zort' match: 'foobazzort' false\\n\\t'*foo#zort'\\tmatch: 'afoo3zortthenfoo3zort' true\\n\\t'*foo*zort'\\tmatch: 'afoodezortorfoo3zort' true\\n\\\"! !\\n\\n!String methodsFor: 'comparing' stamp: 'ar 4/10/2005 17:35'!\\nsameAs: aString \\n\\t\\\"Answer whether the receiver sorts equal to aString. The \\n\\tcollation sequence is ascii with case differences ignored.\\\"\\n\\t^(self compare: aString caseSensitive: false) = 2! !\\n\\n!String methodsFor: 'comparing' stamp: 'yo 11/3/2004 19:24'!\\nstartingAt: keyStart match: text startingAt: textStart\\n\\t\\\"Answer whether text matches the pattern in this string.\\n\\tMatching ignores upper/lower case differences.\\n\\tWhere this string contains #, text may contain any character.\\n\\tWhere this string contains *, text may contain any sequence of characters.\\\"\\n\\t| anyMatch matchStart matchEnd i matchStr j ii jj |\\n\\ti _ keyStart.\\n\\tj _ textStart.\\n\\n\\t\\\"Check for any #'s\\\"\\n\\t[i > self size ifTrue: [^ j > text size \\\"Empty key matches only empty string\\\"].\\n\\t(self at: i) = $#] whileTrue:\\n\\t\\t[\\\"# consumes one char of key and one char of text\\\"\\n\\t\\tj > text size ifTrue: [^ false \\\"no more text\\\"].\\n\\t\\ti _ i+1. j _ j+1].\\n\\n\\t\\\"Then check for *\\\"\\n\\t(self at: i) = $*\\n\\t\\tifTrue: [i = self size ifTrue:\\n\\t\\t\\t\\t\\t[^ true \\\"Terminal * matches all\\\"].\\n\\t\\t\\t\\t\\\"* means next match string can occur anywhere\\\"\\n\\t\\t\\t\\tanyMatch _ true.\\n\\t\\t\\t\\tmatchStart _ i + 1]\\n\\t\\tifFalse: [\\\"Otherwise match string must occur immediately\\\"\\n\\t\\t\\t\\tanyMatch _ false.\\n\\t\\t\\t\\tmatchStart _ i].\\n\\n\\t\\\"Now determine the match string\\\"\\n\\tmatchEnd _ self size.\\n\\t(ii _ self indexOf: $* startingAt: matchStart) > 0 ifTrue:\\n\\t\\t[ii = 1 ifTrue: [self error: '** not valid -- use * instead'].\\n\\t\\tmatchEnd _ ii-1].\\n\\t(ii _ self indexOf: $# startingAt: matchStart) > 0 ifTrue:\\n\\t\\t[ii = 1 ifTrue: [self error: '*# not valid -- use #* instead'].\\n\\t\\tmatchEnd _ matchEnd min: ii-1].\\n\\tmatchStr _ self copyFrom: matchStart to: matchEnd.\\n\\n\\t\\\"Now look for the match string\\\"\\n\\t[jj _ text findString: matchStr startingAt: j caseSensitive: false.\\n\\tanyMatch ifTrue: [jj > 0] ifFalse: [jj = j]]\\n\\t\\twhileTrue:\\n\\t\\t[\\\"Found matchStr at jj. See if the rest matches...\\\"\\n\\t\\t(self startingAt: matchEnd+1 match: text startingAt: jj + matchStr size) ifTrue:\\n\\t\\t\\t[^ true \\\"the rest matches -- success\\\"].\\n\\t\\t\\\"The rest did not match.\\\"\\n\\t\\tanyMatch ifFalse: [^ false].\\n\\t\\t\\\"Preceded by * -- try for a later match\\\"\\n\\t\\tj _ j+1].\\n\\t^ false \\\"Failed to find the match string\\\"! !\\n\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToCollection: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a collection, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToNumber: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a number, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToPoint: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a point, convert me to a number.\\\"\\n\\n\\t^ rcvr perform: selector with: self asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nadaptToString: rcvr andSend: selector\\n\\t\\\"If I am involved in arithmetic with a string, convert us both to\\n\\tnumbers, and return the printString of the result.\\\"\\n\\n\\t^ (rcvr asNumber perform: selector with: self asNumber) printString! !\\n\\n!String methodsFor: 'converting' stamp: 'mw 1/30/2004 11:53'!\\nasAlphaNumeric: totalSize extraChars: additionallyAllowed mergeUID: minimalSizeOfRandomPart\\n\\t\\\"Generates a String with unique identifier ( UID ) qualities, the difference to a\\n\\t UUID is that its beginning is derived from the receiver, so that it has a meaning\\n\\t for a human reader.\\n\\n\\t Answers a String of totalSize, which consists of 3 parts\\n\\t 1.part: the beginning of the receiver only consisting of\\n\\t\\ta-z, A-Z, 0-9 and extraChars in Collection additionallyAllowed ( which can be nil )\\n\\t 2.part: a single _\\n\\t 3.part: a ( random ) UID of size >= minimalSizeOfRandomPart consisting of\\n\\t\\ta-z, A-Z, 0-9\\n\\n\\t Starting letters are capitalized. \\n\\t TotalSize must be at least 1.\\n\\t Exactly 1 occurrence of $_ is guaranteed ( unless additionallyAllowed includes $_ ).\\n\\t The random part has even for small sizes good UID qualitites for many practical purposes.\\n\\t If only lower- or uppercase letters are demanded, simply convert the answer with\\n\\t say #asLowercase. The probability of a duplicate will rise only moderately ( see below ).\\n\\n\\t Example: \\n\\t\\tsize of random part = 10\\n\\t\\tin n generated UIDs the chance p of having non-unique UIDs is\\n\\t\\t\\tn = 10000 -> p < 1e-10\\t\\tif answer is reduced to lowerCase: p < 1.4 e-8\\n\\t\\t\\tn = 100000 -> p < 1e-8\\n\\t\\tat the bottom is a snippet for your own calculations \\n\\t\\tNote: the calculated propabilites are theoretical,\\n\\t\\t\\tfor the actually used random generator they may be much worse\\\"\\n\\n\\t| stream out sizeOfFirstPart index ascii ch skip array random |\\n\\ttotalSize > minimalSizeOfRandomPart \\n\\t\\tifFalse: [ self errorOutOfBounds ].\\n\\tstream := ReadStream on: self.\\n\\tout := WriteStream on: ( String new: totalSize ).\\n\\tindex := 0.\\n\\tskip := true.\\n\\tsizeOfFirstPart := totalSize - minimalSizeOfRandomPart - 1.\\n\\t[ stream atEnd or: [ index >= sizeOfFirstPart ]]\\n\\twhileFalse: [\\n\\t\\t((( ascii := ( ch := stream next ) asciiValue ) >= 65 and: [ ascii <= 90 ]) or: [\\n\\t\\t\\t( ascii >= 97 and: [ ascii <= 122 ]) or: [\\t\\t\\t \\n\\t\\t\\tch isDigit or: [\\n\\t\\t\\tadditionallyAllowed notNil and: [ additionallyAllowed includes: ch ]]]])\\n\\t\\tifTrue: [\\n\\t\\t\\tskip\\n\\t\\t\\t\\tifTrue: [ out nextPut: ch asUppercase ]\\n\\t\\t\\t\\tifFalse: [ out nextPut: ch ].\\n\\t\\t\\tindex := index + 1.\\n\\t\\t\\tskip := false ]\\n\\t\\tifFalse: [ skip := true ]].\\n\\tout nextPut: $_.\\n\\tarray := Array new: 62.\\n\\t1 to: 26 do: [ :i |\\n\\t\\tarray at: i put: ( i + 64 ) asCharacter.\\n\\t\\tarray at: i + 26 put: ( i + 96 ) asCharacter ].\\n\\t53 to: 62 do: [ :i |\\n\\t\\tarray at: i put: ( i - 5 ) asCharacter ].\\n\\trandom := UUIDGenerator default randomGenerator. \\n\\ttotalSize - index - 1 timesRepeat: [\\n\\t\\tout nextPut: ( array atRandom: random )].\\n\\t^out contents\\n\\n\\t\\\"\\tcalculation of probability p for failure of uniqueness in n UIDs\\n\\t\\tNote: if answer will be converted to upper or lower case replace 62 with 36\\n\\t| n i p all |\\n\\tall := 62 raisedTo: sizeOfRandomPart.\\n\\ti := 1.\\n\\tp := 0.0 .\\n\\tn := 10000.\\n\\t[ i <= n ]\\n\\twhileTrue: [\\n\\t\\tp := p + (( i - 1 ) / all ).\\n\\t\\ti := i + 1 ].\\n\\tp \\n\\n\\tapproximation formula: n squared / ( 62.0 raisedTo: sizeOfRandomPart ) / 2 \\n\\t\\\" \\n\\n\\t\\\"'Crop SketchMorphs and Grab Screen Rect to JPG' \\n\\t\\t\\tasAlphaNumeric: 31 extraChars: nil mergeUID: 10 \\n\\t \\t\\t\\t'CropSketchMorphsAndG_iOw94jquN6'\\n\\t 'Monticello' \\n\\t\\t\\tasAlphaNumeric: 31 extraChars: nil mergeUID: 10 \\n\\t\\t\\t\\t'Monticello_kp6aV2l0IZK9uBULGOeG' \\n\\t 'version-', ( '1.1.2' replaceAll: $. with: $- )\\n\\t\\t\\tasAlphaNumeric: 31 extraChars: #( $- ) mergeUID: 10 \\n\\t\\t\\t\\t'Version-1-1-2_kuz2tMg2xX9iRLDVR'\\\"\\n\\t\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:18'!\\nasByteArray\\n\\t\\\"Convert to a ByteArray with the ascii values of the string.\\\"\\n\\t| b |\\n\\tb _ ByteArray new: self byteSize.\\n\\t1 to: self size * 4 do: [:i |\\n\\t\\tb at: i put: (self byteAt: i).\\n\\t].\\n\\t^ b.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 16:22'!\\nasByteString\\n\\t\\\"Convert the receiver into a ByteString\\\"\\n\\t^self asOctetString! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:03'!\\nasCharacter\\n\\t\\\"Answer the receiver's first character, or '*' if none. Idiosyncratic, provisional.\\\"\\n\\n\\t^ self size > 0 ifTrue: [self first] ifFalse:[$\\U00b7]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDate\\n\\t\\\"Many allowed forms, see Date>>#readFrom:\\\"\\n\\n\\t^ Date fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDateAndTime\\n\\n\\n\\n\\t\\\"Convert from UTC format\\\" \\t^ DateAndTime fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 10/22/2002 17:38'!\\nasDefaultDecodedString\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDisplayText\\n\\t\\\"Answer a DisplayText whose text string is the receiver.\\\"\\n\\n\\t^DisplayText text: self asText! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasDuration\\n\\n\\t\\\"convert from [nnnd]hh:mm:ss[.nanos] format. [] implies optional elements\\\"\\n\\n\\n\\n\\t^ Duration fromString: self\\n\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 13:55'!\\nasFileName\\n\\t\\\"Answer a String made up from the receiver that is an acceptable file \\n\\tname.\\\"\\n\\n\\t| string checkedString |\\n\\tstring _ FileDirectory checkName: self fixErrors: true.\\n\\tcheckedString _ (FilePath pathName: string) asVmPathName.\\n\\t^ (FilePath pathName: checkedString isEncoded: true) asSqueakPathName.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:38'!\\nasFourCode\\n\\n\\t| result |\\n\\tself size = 4 ifFalse: [^self error: 'must be exactly four characters'].\\n\\tresult _ self inject: 0 into: [:val :each | 256 * val + each asciiValue].\\n\\t(result bitAnd: 16r80000000) = 0 \\n\\t\\tifFalse: [self error: 'cannot resolve fourcode'].\\n\\t(result bitAnd: 16r40000000) = 0 ifFalse: [^result - 16r80000000].\\n\\t^ result\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/26/2002 23:06'!\\nasHex\\n\\t| stream |\\n\\tstream _ WriteStream on: (String new: self size * 4).\\n\\tself do: [ :ch | stream nextPutAll: ch hex ].\\n\\t^stream contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasHtml\\n\\t\\\"Do the basic character conversion for HTML. Leave all original return \\n\\tand tabs in place, so can conver back by simply removing bracked \\n\\tthings. 4/4/96 tk\\\"\\n\\t| temp |\\n\\ttemp _ self copyReplaceAll: '&' with: '&'.\\n\\tHtmlEntities keysAndValuesDo:\\n\\t\\t[:entity :char |\\n\\t\\tchar = $& ifFalse:\\n\\t\\t\\t[temp _ temp copyReplaceAll: char asString with: '&' , entity , ';']].\\n\\ttemp _ temp copyReplaceAll: '\\t' with: '\\t<IMG SRC=\\\"tab.gif\\\" ALT=\\\" \\\">'.\\n\\ttemp _ temp copyReplaceAll: '\\n' with: '\\n<BR>'.\\n\\t^ temp\\n\\n\\\"\\n\\t'A<&>B' asHtml\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasIRCLowercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tlowercase, where 'lowercase' is by IRC's definition\\\"\\n\\n\\t^self collect: [ :c | c asIRCLowercase ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasIdentifier: shouldBeCapitalized\\n\\t\\\"Return a legal identifier, with first character in upper case if shouldBeCapitalized is true, else lower case. This will always return a legal identifier, even for an empty string\\\"\\n\\n\\t| aString firstChar firstLetterPosition |\\n\\taString _ self select: [:el | el isAlphaNumeric].\\n\\tfirstLetterPosition _ aString findFirst: [:ch | ch isLetter].\\n\\taString _ firstLetterPosition == 0\\n\\t\\tifFalse:\\n\\t\\t\\t[aString copyFrom: firstLetterPosition to: aString size]\\n\\t\\tifTrue:\\n\\t\\t\\t['a', aString].\\n\\tfirstChar _ shouldBeCapitalized ifTrue: [aString first asUppercase] ifFalse: [aString first asLowercase].\\n\\n\\t^ firstChar asString, (aString copyFrom: 2 to: aString size)\\n\\\"\\n'234Fred987' asIdentifier: false\\n'235Fred987' asIdentifier: true\\n'' asIdentifier: true\\n'()87234' asIdentifier: false\\n'())z>=PPve889 U >' asIdentifier: false\\n\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 09:55'!\\nasInteger \\n\\t^self asSignedInteger\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasLegalSelector\\n\\t| toUse |\\n\\ttoUse _ ''.\\n\\tself do:\\n\\t\\t[:char | char isAlphaNumeric ifTrue: [toUse _ toUse copyWith: char]].\\n\\t(self size == 0 or: [self first isLetter not])\\n\\t\\tifTrue:\\t\\t[toUse _ 'v', toUse].\\n\\n\\t^ toUse withFirstCharacterDownshifted\\n\\n\\\"'234znak 43 ) 2' asLegalSelector\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasLowercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tlowercase.\\\"\\n\\n\\t^ self copy asString translateToLowercase! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasNumber \\n\\t\\\"Answer the Number created by interpreting the receiver as the string \\n\\trepresentation of a number.\\\"\\n\\n\\t^Number readFromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 20:55'!\\nasOctetString\\n\\t\\\"Convert the receiver into an octet string\\\"\\n\\t| string |\\n\\tstring _ String new: self size.\\n\\t1 to: self size do: [:i | string at: i put: (self at: i)].\\n\\t^string! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:39'!\\nasPacked\\n\\t\\\"Convert to a longinteger that describes the string\\\"\\n\\n\\t^ self inject: 0 into: [ :pack :next | pack _ pack * 256 + next asInteger ].! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasParagraph\\n\\t\\\"Answer a Paragraph whose text string is the receiver.\\\"\\n\\n\\t^Paragraph withText: self asText! !\\n\\n!String methodsFor: 'converting' stamp: 'dew 9/13/2001 01:17'!\\nasPluralBasedOn: aNumberOrCollection\\n\\t\\\"Append an 's' to this string based on whether aNumberOrCollection is 1 or of size 1.\\\"\\n\\n\\t^ (aNumberOrCollection = 1 or:\\n\\t\\t[aNumberOrCollection isCollection and: [aNumberOrCollection size = 1]])\\n\\t\\t\\tifTrue: [self]\\n\\t\\t\\tifFalse: [self, 's']\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 09:54'!\\nasSignedInteger \\n\\t\\\"Returns the first signed integer it can find or nil.\\\"\\n\\n\\t| start stream |\\n\\tstart := self findFirst: [:char | char isDigit].\\n\\tstart isZero ifTrue: [^nil].\\n\\tstream := (ReadStream on: self) position: start.\\n\\tstream back = $- ifTrue: [stream back].\\n\\t^Integer readFrom: stream! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasSmalltalkComment\\n\\t\\\"return this string, munged so that it can be treated as a comment in Smalltalk code. Quote marks are added to the beginning and end of the string, and whenever a solitary quote mark appears within the string, it is doubled\\\"\\n\\n\\t^String streamContents: [ :str |\\n\\t\\t| quoteCount first |\\n\\n\\t\\tstr nextPut: $\\\".\\n\\t\\n\\t\\tquoteCount := 0.\\n\\t\\tfirst := true.\\n\\t\\tself do: [ :char |\\n\\t\\t\\tchar = $\\\"\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tfirst ifFalse: [\\n\\t\\t\\t\\t\\t\\tstr nextPut: char.\\n\\t\\t\\t\\t\\t\\tquoteCount := quoteCount + 1 ] ]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tquoteCount odd ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\\"add a quote to even the number of quotes in a row\\\"\\n\\t\\t\\t\\t\\t\\tstr nextPut: $\\\" ].\\n\\t\\t\\t\\t\\tquoteCount := 0.\\n\\t\\t\\t\\t\\tstr nextPut: char ].\\n\\t\\t\\tfirst := false ]. \\n\\n\\t\\tquoteCount odd ifTrue: [\\n\\t\\t\\t\\\"check at the end\\\"\\n\\t\\t\\tstr nextPut: $\\\". ].\\n\\n\\t\\tstr nextPut: $\\\".\\n\\t].\\n\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 12/19/2003 21:16'!\\nasSqueakPathName\\n\\n\\t^ self.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasString\\n\\t\\\"Answer this string.\\\"\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasStringOrText\\n\\t\\\"Answer this string.\\\"\\n\\n\\t^ self\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 19:24'!\\nasSymbol\\n\\t\\\"Answer the unique Symbol whose characters are the characters of the \\n\\tstring.\\\"\\n\\t^Symbol intern: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasText\\n\\t\\\"Answer a Text whose string is the receiver.\\\"\\n\\n\\t^Text fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasTime\\n\\t\\\"Many allowed forms, see Time>>readFrom:\\\"\\n\\n\\t^ Time fromString: self.! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasTimeStamp\\n\\t\\\"Convert from obsolete TimeStamp format\\\"\\n\\n\\n\\t^ TimeStamp fromString: self! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/10/2005 17:05'!\\nasUnHtml\\n\\t\\\"Strip out all Html stuff (commands in angle brackets <>) and convert\\nthe characters &<> back to their real value. Leave actual cr and tab as\\nthey were in text.\\\"\\n\\t| in out char rest did |\\n\\tin _ ReadStream on: self.\\n\\tout _ WriteStream on: (String new: self size).\\n\\t[in atEnd] whileFalse:\\n\\t\\t[in peek = $<\\n\\t\\t\\tifTrue: [in unCommand] \\t\\\"Absorb <...><...>\\\"\\n\\t\\t\\tifFalse: [(char _ in next) = $&\\n\\t\\t\\t\\t\\t\\tifTrue: [rest _ in upTo: $;.\\n\\t\\t\\t\\t\\t\\t\\t\\tdid _ out position.\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'lt' ifTrue: [out nextPut: $<].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'gt' ifTrue: [out nextPut: $>].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'amp' ifTrue: [out nextPut: $&].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'deg' ifTrue: [out nextPut: $\\U00b0].\\n\\t\\t\\t\\t\\t\\t\\t\\trest = 'quot' ifTrue: [out nextPut: $\\\"].\\n\\t\\t\\t\\t\\t\\t\\t\\tdid = out position ifTrue: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tself error: 'unknown encoded HTML char'.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"Please add it to this method\\\"]]\\n\\t\\t\\t\\t\\t\\tifFalse: [out nextPut: char]].\\n\\t\\t].\\n\\t^ out contents! !\\n\\n!String methodsFor: 'converting' stamp: 'laza 10/1/2004 10:02'!\\nasUnsignedInteger \\n\\t\\\"Returns the first integer it can find or nil.\\\"\\n\\n\\t| start stream |\\n\\tstart := self findFirst: [:char | char isDigit].\\n\\tstart isZero ifTrue: [^nil].\\n\\tstream := (ReadStream on: self) position: start - 1.\\n\\t^Integer readFrom: stream! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUppercase\\n\\t\\\"Answer a String made up from the receiver whose characters are all \\n\\tuppercase.\\\"\\n\\n\\t^self copy asString translateToUppercase! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUrl\\n\\t\\\"convert to a Url\\\"\\n\\t\\\"'http://www.cc.gatech.edu/' asUrl\\\"\\n\\t\\\"msw://chaos.resnet.gatech.edu:9000/' asUrl\\\"\\n\\t^Url absoluteFromText: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nasUrlRelativeTo: aUrl\\n\\t^aUrl newFromRelativeText: self! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 2/24/2005 18:33'!\\nasVmPathName\\n\\n\\t^ (FilePath pathName: self) asVmPathName.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\naskIfAddStyle: priorMethod req: requestor\\n\\t^ self \\\"we are a string with no text style\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 17:36'!\\nasWideString \\n\\tself isWideString\\n\\t\\tifTrue:[^self]\\n\\t\\tifFalse:[^WideString from: self]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncapitalized\\n\\t\\\"Return a copy with the first letter capitalized\\\"\\n\\t| cap |\\n\\tself isEmpty ifTrue: [ ^self copy ].\\n\\tcap _ self copy.\\n\\tcap at: 1 put: (cap at: 1) asUppercase.\\n\\t^ cap! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncompressWithTable: tokens\\n\\t\\\"Return a string with all substrings that occur in tokens replaced\\n\\tby a character with ascii code = 127 + token index.\\n\\tThis will work best if tokens are sorted by size.\\n\\tAssumes this string contains no characters > 127, or that they\\n\\tare intentionally there and will not interfere with this process.\\\"\\n\\t| str null finalSize start result ri c ts |\\n\\tnull _ Character value: 0.\\n\\tstr _ self copyFrom: 1 to: self size. \\\"Working string will get altered\\\"\\n\\tfinalSize _ str size.\\n\\ttokens doWithIndex:\\n\\t\\t[:token :tIndex |\\n\\t\\tstart _ 1.\\n\\t\\t[(start _ str findString: token startingAt: start) > 0]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t[ts _ token size.\\n\\t\\t\\t((start + ts) <= str size\\n\\t\\t\\t\\tand: [(str at: start + ts) = $ and: [tIndex*2 <= 128]])\\n\\t\\t\\t\\tifTrue: [ts _ token size + 1. \\\"include training blank\\\"\\n\\t\\t\\t\\t\\t\\tstr at: start put: (Character value: tIndex*2 + 127)]\\n\\t\\t\\t\\tifFalse: [str at: start put: (Character value: tIndex + 127)].\\n\\t\\t\\tstr at: start put: (Character value: tIndex + 127).\\n\\t\\t\\t1 to: ts-1 do: [:i | str at: start+i put: null].\\n\\t\\t\\tfinalSize _ finalSize - (ts - 1).\\n\\t\\t\\tstart _ start + ts]].\\n\\tresult _ String new: finalSize.\\n\\tri _ 0.\\n\\t1 to: str size do:\\n\\t\\t[:i | (c _ str at: i) = null ifFalse: [result at: (ri _ ri+1) put: c]].\\n\\t^ result! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncontractTo: smallSize\\n\\t\\\"return myself or a copy shortened by ellipsis to smallSize\\\"\\n\\t| leftSize |\\n\\tself size <= smallSize\\n\\t\\tifTrue: [^ self]. \\\"short enough\\\"\\n\\tsmallSize < 5\\n\\t\\tifTrue: [^ self copyFrom: 1 to: smallSize]. \\\"First N characters\\\"\\n\\tleftSize _ smallSize-2//2.\\n\\t^ self copyReplaceFrom: leftSize+1\\t\\t\\\"First N/2 ... last N/2\\\"\\n\\t\\tto: self size - (smallSize - leftSize - 3)\\n\\t\\twith: '...'\\n\\\"\\n\\t'A clear but rather long-winded summary' contractTo: 18\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:47'!\\nconvertFromEncoding: encodingName\\n\\t^self convertFromWithConverter: (TextConverter newForEncoding: encodingName)! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:47'!\\nconvertFromSuperSwikiServerString\\n\\t^self convertFromEncoding: 'shift_jis'! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/8/2004 12:02'!\\nconvertFromWithConverter: converter\\n\\n\\t| readStream writeStream c |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tc _ converter nextFromStream: readStream.\\n\\t\\tc ifNotNil: [writeStream nextPut: c] ifNil: [^ writeStream contents]\\n\\t].\\n\\t^ writeStream contents\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:49'!\\nconvertToEncoding: encodingName\\n\\t^self convertToWithConverter: (TextConverter newForEncoding: encodingName).! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 1/30/2006 21:50'!\\nconvertToSuperSwikiServerString\\n\\t^self convertToEncoding: 'shift_jis'! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 14:01'!\\nconvertToSystemString\\n\\n\\t| readStream writeStream converter |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter _ LanguageEnvironment defaultSystemConverter.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tconverter nextPut: readStream next toStream: writeStream\\n\\t].\\n\\tconverter emitSequenceToResetStateIfNeededOn: writeStream.\\n\\t^ writeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/8/2004 12:01'!\\nconvertToWithConverter: converter\\n\\n\\t| readStream writeStream |\\n\\treadStream _ self readStream.\\n\\twriteStream _ String new writeStream.\\n\\tconverter ifNil: [^ self].\\n\\t[readStream atEnd] whileFalse: [\\n\\t\\tconverter nextPut: readStream next toStream: writeStream\\n\\t].\\n\\tconverter emitSequenceToResetStateIfNeededOn: writeStream.\\n\\t^ writeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainst: wordList\\n\\t\\\"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:\\\"\\n\\t| results |\\n\\tresults _ self correctAgainst: wordList continuedFrom: nil.\\n\\tresults _ self correctAgainst: nil continuedFrom: results.\\n\\t^ results! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainst: wordList continuedFrom: oldCollection\\n\\t\\\"Like correctAgainst:. Use when you want to correct against several lists, give nil as the first oldCollection, and nil as the last wordList.\\\"\\n\\n\\t^ wordList isNil\\n\\t\\tifTrue: [ self correctAgainstEnumerator: nil\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]\\n\\t\\tifFalse: [ self correctAgainstEnumerator: [ :action | wordList do: action without: nil]\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainstDictionary: wordDict continuedFrom: oldCollection\\n\\t\\\"Like correctAgainst:continuedFrom:. Use when you want to correct against a dictionary.\\\"\\n\\n\\t^ wordDict isNil\\n\\t\\tifTrue: [ self correctAgainstEnumerator: nil\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]\\n\\t\\tifFalse: [ self correctAgainstEnumerator: [ :action | wordDict keysDo: action ]\\n\\t\\t\\t\\t\\tcontinuedFrom: oldCollection ]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:04'!\\nencodeForHTTP\\n\\t\\\"change dangerous characters to their %XX form, for use in HTTP transactions\\\"\\n\\n\\t^ self encodeForHTTPWithTextEncoding: 'utf-8' conditionBlock: [:c | c isSafeForHTTP].\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:04'!\\nencodeForHTTPWithTextEncoding: encodingName\\n\\n\\t^ self encodeForHTTPWithTextEncoding: encodingName conditionBlock: [:c | c isSafeForHTTP].\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/29/2005 16:03'!\\nencodeForHTTPWithTextEncoding: encodingName conditionBlock: conditionBlock\\n\\t\\\"change dangerous characters to their %XX form, for use in HTTP transactions\\\"\\n\\n\\t| httpSafeStream encodedStream cont |\\n\\thttpSafeStream _ WriteStream on: (String new).\\n\\tencodedStream _ MultiByteBinaryOrTextStream on: (String new: 6).\\n\\tencodedStream converter: (TextConverter newForEncoding: encodingName).\\n\\tself do: [:c |\\n\\t\\t(conditionBlock value: c)\\n\\t\\t\\tifTrue: [httpSafeStream nextPut: (Character value: c charCode)]\\n\\t\\t\\tifFalse: [\\n\\t\\t\\t\\tencodedStream text; reset.\\n\\t\\t\\t\\tencodedStream nextPut: c.\\n\\t\\t\\t\\tencodedStream position: 0.\\n\\t\\t\\t\\tencodedStream binary.\\n\\t\\t\\t\\tcont _ encodedStream contents.\\n\\t\\t\\t\\tcont do: [:byte |\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: $%.\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: (byte // 16) asHexDigit.\\n\\t\\t\\t\\t\\thttpSafeStream nextPut: (byte \\\\\\\\ 16) asHexDigit.\\n\\t\\t\\t\\t].\\n\\t\\t\\t].\\n\\t].\\n\\t^ httpSafeStream contents.\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/5/2004 16:48'!\\nfindSelector\\n\\t\\\"Dan's code for hunting down selectors with keyword parts; while this doesn't give a true parse, in most cases it does what we want, in where it doesn't, we're none the worse for it.\\\"\\n\\t| sel possibleParens level n |\\n\\tsel _ self withBlanksTrimmed.\\n\\t(sel includes: $:) ifTrue:\\n\\t\\t[sel _ sel copyReplaceAll: ':' with: ': '.\\t\\\"for the style (aa max:bb) with no space\\\"\\n\\t\\tpossibleParens _ sel findTokens: Character separators.\\n\\t\\tsel _ self class streamContents:\\n\\t\\t\\t[:s | level _ 0.\\n\\t\\t\\tpossibleParens do:\\n\\t\\t\\t\\t[:token |\\n\\t\\t\\t\\t(level = 0 and: [token endsWith: ':'])\\n\\t\\t\\t\\t\\tifTrue: [s nextPutAll: token]\\n\\t\\t\\t\\t\\tifFalse: [(n _ token occurrencesOf: $( ) > 0 ifTrue: [level _ level + n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $[ ) > 0 ifTrue: [level _ level + n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $] ) > 0 ifTrue: [level _ level - n].\\n\\t\\t\\t\\t\\t\\t\\t(n _ token occurrencesOf: $) ) > 0 ifTrue: [level _ level - n]]]]].\\n\\n\\tsel isEmpty ifTrue: [^ nil].\\n\\tsel isOctetString ifTrue: [sel _ sel asOctetString].\\n\\tSymbol hasInterned: sel ifTrue:\\n\\t\\t[:aSymbol | ^ aSymbol].\\n\\t^ nil! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ninitialIntegerOrNil\\n\\t\\\"Answer the integer represented by the leading digits of the receiver, or nil if the receiver does not begin with a digit\\\"\\n\\t| firstNonDigit |\\n\\t(self size == 0 or: [self first isDigit not]) ifTrue: [^ nil].\\n\\tfirstNonDigit _ (self findFirst: [:m | m isDigit not]).\\n\\tfirstNonDigit = 0 ifTrue: [firstNonDigit _ self size + 1].\\n\\t^ (self copyFrom: 1 to: (firstNonDigit - 1)) asNumber\\n\\\"\\n'234Whoopie' initialIntegerOrNil\\n'wimpy' initialIntegerOrNil\\n'234' initialIntegerOrNil\\n'2N' initialIntegerOrNil\\n'2' initialIntegerOrNil\\n' 89Ten ' initialIntegerOrNil\\n'78 92' initialIntegerOrNil\\n\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nkeywords\\n\\t\\\"Answer an array of the keywords that compose the receiver.\\\"\\n\\t| kwd char keywords |\\n\\tkeywords _ Array streamContents:\\n\\t\\t[:kwds | kwd _ WriteStream on: (String new: 16).\\n\\t\\t1 to: self size do:\\n\\t\\t\\t[:i |\\n\\t\\t\\tkwd nextPut: (char _ self at: i).\\n\\t\\t\\tchar = $: ifTrue: \\n\\t\\t\\t\\t\\t[kwds nextPut: kwd contents.\\n\\t\\t\\t\\t\\tkwd reset]].\\n\\t\\tkwd isEmpty ifFalse: [kwds nextPut: kwd contents]].\\n\\t(keywords size >= 1 and: [(keywords at: 1) = ':']) ifTrue:\\n\\t\\t[\\\"Has an initial keyword, as in #:if:then:else:\\\"\\n\\t\\tkeywords _ keywords allButFirst].\\n\\t(keywords size >= 2 and: [(keywords at: keywords size - 1) = ':']) ifTrue:\\n\\t\\t[\\\"Has a final keyword, as in #nextPut::andCR\\\"\\n\\t\\tkeywords _ keywords copyReplaceFrom: keywords size - 1\\n\\t\\t\\t\\t\\t\\t\\t\\tto: keywords size with: {':' , keywords last}].\\n\\t^ keywords! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nnumericSuffix\\n\\t^ self stemAndNumericSuffix last\\n\\n\\\"\\n'abc98' numericSuffix\\n'98abc' numericSuffix\\n\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nonlyLetters\\n\\t\\\"answer the receiver with only letters\\\"\\n\\t^ self select:[:each | each isLetter]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nromanNumber\\n\\t| value v1 v2 |\\n\\tvalue _ v1 _ v2 _ 0.\\n\\tself reverseDo:\\n\\t\\t[:each |\\n\\t\\tv1 _ #(1 5 10 50 100 500 1000) at: ('IVXLCDM' indexOf: each).\\n\\t\\tv1 >= v2\\n\\t\\t\\tifTrue: [value _ value + v1]\\n\\t\\t\\tifFalse: [value _ value - v1].\\n\\t\\tv2 _ v1].\\n\\t^ value! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsansPeriodSuffix\\n\\t\\\"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. \\\"\\n\\n\\t| likely |\\n\\tlikely _ self copyUpTo: $..\\n\\t^ likely size == 0\\n\\t\\tifTrue:\\t[self]\\n\\t\\tifFalse:\\t[likely]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 11:13'!\\nsplitInteger\\n\\t\\\"Answer an array that is a splitting of self into a string and an integer.\\n\\t'43Sam' ==> #(43 'Sam'). 'Try90' ==> #('Try' 90)\\n\\tBUT NOTE: 'Sam' ==> #('Sam' 0), and '90' ==> #('' 90) ie, (<string> <integer>).\\\"\\n\\n\\t| pos |\\n\\t(pos _ self findFirst: [:d | d isDigit not]) = 0 ifTrue: [^ Array with: '' with: self asNumber].\\n\\tself first isDigit ifTrue: [\\n\\t\\t^ Array with: (self copyFrom: 1 to: pos - 1) asNumber \\n\\t\\t\\t\\twith: (self copyFrom: pos to: self size)].\\n\\t(pos _ self findFirst: [:d | d isDigit]) = 0 ifTrue: [^ Array with: self with: 0].\\n\\t^ Array with: (self copyFrom: 1 to: pos - 1)\\n\\t\\t\\twith: (self copyFrom: pos to: self size) asNumber! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nstemAndNumericSuffix\\n\\t\\\"Parse the receiver into a string-valued stem and a numeric-valued suffix. 6/7/96 sw\\\"\\n\\n\\t| stem suffix position |\\n\\n\\tstem _ self.\\n\\tsuffix _ 0.\\n\\tposition _ 1.\\n\\t[stem endsWithDigit and: [stem size > 1]] whileTrue:\\n\\t\\t[suffix _ stem last digitValue * position + suffix.\\n\\t\\tposition _ position * 10.\\n\\t\\tstem _ stem copyFrom: 1 to: stem size - 1].\\n\\t^ Array with: stem with: suffix\\n\\n\\\"'Fred2305' stemAndNumericSuffix\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsubStrings\\n\\t\\\"Answer an array of the substrings that compose the receiver.\\\"\\n\\t#Collectn.\\n\\t\\\"Added 2000/04/08 For ANSI <readableString> protocol.\\\"\\n\\t^ self substrings! !\\n\\n!String methodsFor: 'converting' stamp: 'ar 4/12/2005 16:32'!\\nsubStrings: separators \\n\\t\\\"Answer an array containing the substrings in the receiver separated \\n\\tby the elements of separators.\\\"\\n\\t| char result sourceStream subString |\\n\\t#Collectn.\\n\\t\\\"Changed 2000/04/08 For ANSI <readableString> protocol.\\\"\\n\\t(separators isString or:[separators allSatisfy: [:element | element isKindOf: Character]])\\n\\t\\tifFalse: [^ self error: 'separators must be Characters.'].\\n\\tsourceStream := ReadStream on: self.\\n\\tresult := OrderedCollection new.\\n\\tsubString := String new.\\n\\t[sourceStream atEnd]\\n\\t\\twhileFalse: \\n\\t\\t\\t[char := sourceStream next.\\n\\t\\t\\t(separators includes: char)\\n\\t\\t\\t\\tifTrue: [subString notEmpty\\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[result add: subString copy.\\n\\t\\t\\t\\t\\t\\t\\tsubString := String new]]\\n\\t\\t\\t\\tifFalse: [subString := subString , (String with: char)]].\\n\\tsubString notEmpty ifTrue: [result add: subString copy].\\n\\t^ result asArray! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsubstrings\\n\\t\\\"Answer an array of the substrings that compose the receiver.\\\"\\n\\t| result end beginning |\\n\\n\\tresult _ WriteStream on: (Array new: 10).\\n\\n\\n\\n\\tend _ 0.\\n\\t\\\"find one substring each time through this loop\\\"\\n\\t[ \\n\\t\\t\\\"find the beginning of the next substring\\\"\\n\\t\\tbeginning _ self indexOfAnyOf: CSNonSeparators startingAt: end+1 ifAbsent: [ nil ].\\n\\t\\tbeginning ~~ nil ] \\n\\twhileTrue: [\\n\\t\\t\\\"find the end\\\"\\n\\t\\tend _ self indexOfAnyOf: CSSeparators startingAt: beginning ifAbsent: [ self size + 1 ].\\n\\t\\tend _ end - 1.\\n\\n\\t\\tresult nextPut: (self copyFrom: beginning to: end).\\n\\n\\t].\\n\\n\\n\\t^result contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nsurroundedBySingleQuotes\\n\\t\\\"Answer the receiver with leading and trailing quotes. \\\"\\n\\n\\t^ $' asString, self, $' asString! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/28/2002 15:14'!\\ntranslateFrom: start to: stop table: table\\n\\t\\\"translate the characters in the string by the given table, in place\\\"\\n\\tself class translate: self from: start to: stop table: table! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntranslateToLowercase\\n\\t\\\"Translate all characters to lowercase, in place\\\"\\n\\n\\tself translateWith: LowercasingTable! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntranslateToUppercase\\n\\t\\\"Translate all characters to lowercase, in place\\\"\\n\\n\\tself translateWith: UppercasingTable! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/28/2002 15:13'!\\ntranslateWith: table\\n\\t\\\"translate the characters in the string by the given table, in place\\\"\\n\\t^ self translateFrom: 1 to: self size table: table! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntruncateTo: smallSize\\n\\t\\\"return myself or a copy shortened to smallSize. 1/18/96 sw\\\"\\n\\n\\t^ self size <= smallSize\\n\\t\\tifTrue:\\n\\t\\t\\t[self]\\n\\t\\tifFalse:\\n\\t\\t\\t[self copyFrom: 1 to: smallSize]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\ntruncateWithElipsisTo: maxLength\\n\\t\\\"Return myself or a copy suitably shortened but with elipsis added\\\"\\n\\n\\t^ self size <= maxLength\\n\\t\\tifTrue:\\n\\t\\t\\t[self]\\n\\t\\tifFalse:\\n\\t\\t\\t[(self copyFrom: 1 to: (maxLength - 3)), '...']\\n\\n\\n\\t\\\"'truncateWithElipsisTo:' truncateWithElipsisTo: 20\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'KR 9/22/2005 23:06'!\\nunescapePercents\\n\\t\\\"decode %xx form. This is the opposite of #encodeForHTTP\\\"\\n\\t^ self unescapePercentsWithTextEncoding: 'utf-8'.! !\\n\\n!String methodsFor: 'converting' stamp: 'ky 7/8/2006 17:56'!\\nunescapePercentsWithTextEncoding: encodingName \\n\\t\\\"decode string including %XX form\\\"\\n\\t| unescaped char asciiVal specialChars oldPos pos converter |\\n\\tunescaped := ReadWriteStream on: String new.\\n\\tspecialChars := '+%' asCharacterSet.\\n\\toldPos := 1.\\n\\t[pos := self indexOfAnyOf: specialChars startingAt: oldPos.\\n\\tpos > 0]\\n\\t\\twhileTrue: [unescaped\\n\\t\\t\\t\\tnextPutAll: (self copyFrom: oldPos to: pos - 1).\\n\\t\\t\\tchar := self at: pos.\\n\\t\\t\\t(char = $%\\n\\t\\t\\t\\t\\tand: [pos + 2 <= self size])\\n\\t\\t\\t\\tifTrue: [asciiVal := (self at: pos + 1) asUppercase digitValue * 16 + (self at: pos + 2) asUppercase digitValue.\\n\\t\\t\\t\\t\\tasciiVal > 255\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\tunescaped\\n\\t\\t\\t\\t\\t\\tnextPut: (Character value: asciiVal).\\n\\t\\t\\t\\t\\tpos := pos + 3.\\n\\t\\t\\t\\t\\tpos <= self size\\n\\t\\t\\t\\t\\t\\tifFalse: [char := nil].\\n\\t\\t\\t\\t\\toldPos := pos]\\n\\t\\t\\t\\tifFalse: [char = $+\\n\\t\\t\\t\\t\\t\\tifTrue: [unescaped nextPut: Character space]\\n\\t\\t\\t\\t\\t\\tifFalse: [unescaped nextPut: char].\\n\\t\\t\\t\\t\\toldPos := pos + 1]].\\n\\toldPos <= self size\\n\\t\\tifTrue: [unescaped\\n\\t\\t\\t\\tnextPutAll: (self copyFrom: oldPos to: self size)].\\n\\tconverter := (TextConverter newForEncoding: encodingName)\\n\\t\\t\\t\\tifNil: [TextConverter newForEncoding: nil].\\n\\t^ [unescaped contents convertFromWithConverter: converter]\\n\\t\\ton: Error\\n\\t\\tdo: [\\\"the contents may be squeak-encoded\\\"\\n\\t\\t\\tunescaped contents]! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 11:20'!\\nunparenthetically\\n\\t\\\"If the receiver starts with (..( and ends with matching )..), strip them\\\"\\n\\n\\t| curr |\\n\\tcurr _ self.\\n\\t[((curr first = $() and: [curr last = $)])] whileTrue:\\n\\t\\t[curr _ curr copyFrom: 2 to: (curr size - 1)].\\n\\n\\t^ curr\\n\\n\\\"\\n\\n'((fred the bear))' unparenthetically\\n\\n\\\"\\n\\t\\t! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nunzipped\\n\\t| magic1 magic2 |\\n\\tmagic1 _ (self at: 1) asInteger.\\n\\tmagic2 _ (self at: 2) asInteger.\\n\\t(magic1 = 16r1F and:[magic2 = 16r8B]) ifFalse:[^self].\\n\\t^(GZipReadStream on: self) upToEnd! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithBlanksCondensed\\n\\t\\\"Return a copy of the receiver with leading/trailing blanks removed\\n\\t and consecutive white spaces condensed.\\\"\\n\\n\\t| trimmed lastBlank |\\n\\ttrimmed _ self withBlanksTrimmed.\\n\\t^String streamContents: [:stream |\\n\\t\\tlastBlank _ false.\\n\\t\\ttrimmed do: [:c | (c isSeparator and: [lastBlank]) ifFalse: [stream nextPut: c].\\n\\t\\t\\tlastBlank _ c isSeparator]].\\n\\n\\t\\\" ' abc d ' withBlanksCondensed\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 7/5/2004 16:43'!\\nwithBlanksTrimmed\\n\\t\\\"Return a copy of the receiver from which leading and trailing blanks have been trimmed.\\\"\\n\\n\\t| first result |\\n\\tfirst _ self findFirst: [:c | c isSeparator not].\\n\\tfirst = 0 ifTrue: [^ '']. \\\"no non-separator character\\\"\\n\\tresult _ self\\n\\t\\tcopyFrom: first\\n\\t\\tto: (self findLast: [:c | c isSeparator not]).\\n\\tresult isOctetString ifTrue: [^ result asOctetString] ifFalse: [^ result].\\n\\n\\t\\\" ' abc d ' withBlanksTrimmed\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'md 9/19/2004 15:19'!\\nwithFirstCharacterDownshifted\\n\\t\\\"Return a copy with the first letter downShifted\\\"\\n\\t\\n\\t| answer |\\n\\t\\n\\tself ifEmpty: [^ self copy].\\n\\tanswer _ self copy.\\n\\tanswer at: 1 put: (answer at: 1) asLowercase.\\n\\t^ answer. ! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithNoLineLongerThan: aNumber\\n\\t\\\"Answer a string with the same content as receiver, but rewrapped so that no line has more characters than the given number\\\"\\n\\t| listOfLines currentLast currentStart resultString putativeLast putativeLine crPosition |\\n\\taNumber isNumber not | (aNumber < 1) ifTrue: [self error: 'too narrow'].\\n\\tlistOfLines _ OrderedCollection new.\\n\\tcurrentLast _ 0.\\n\\t[currentLast < self size] whileTrue:\\n\\t\\t[currentStart _ currentLast + 1.\\n\\t\\tputativeLast _ (currentStart + aNumber - 1) min: self size.\\n\\t\\tputativeLine _ self copyFrom: currentStart to: putativeLast.\\n\\t\\t(crPosition _ putativeLine indexOf: Character cr) > 0 ifTrue:\\n\\t\\t\\t[putativeLast _ currentStart + crPosition - 1.\\n\\t\\t\\tputativeLine _ self copyFrom: currentStart to: putativeLast].\\n\\t\\tcurrentLast _ putativeLast == self size\\n\\t\\t\\tifTrue:\\n\\t\\t\\t\\t[putativeLast]\\n\\t\\t\\tifFalse:\\n\\t\\t\\t\\t[currentStart + putativeLine lastSpacePosition - 1].\\n\\t\\tcurrentLast <= currentStart ifTrue:\\n\\t\\t\\t[\\\"line has NO spaces; baleout!!\\\"\\n\\t\\t\\tcurrentLast _ putativeLast].\\n\\t\\tlistOfLines add: (self copyFrom: currentStart to: currentLast) withBlanksTrimmed].\\n\\n\\tlistOfLines size > 0 ifFalse: [^ ''].\\n\\tresultString _ listOfLines first.\\n\\t2 to: listOfLines size do:\\n\\t\\t[:i | resultString _ resultString, String cr, (listOfLines at: i)].\\n\\t^ resultString\\n\\n\\\"#(5 7 20) collect:\\n\\t[:i | 'Fred the bear went down to the brook to read his book in silence' withNoLineLongerThan: i]\\\"! !\\n\\n!String methodsFor: 'converting' stamp: 'md 10/5/2005 11:01'!\\nwithoutLeadingBlanks\\n\\t\\n\\t\\\"Return a copy of the receiver from which leading blanks have been\\ntrimmed.\\\"\\n\\n\\t\\n\\t| first |\\n\\t\\n\\tfirst := self findFirst: [:c | c isSeparator not ].\\n\\n\\tfirst = 0 ifTrue: [^ '']. \\n\\t\\n\\t\\\"no non-separator character\\\"\\n\\t\\n\\t^ self copyFrom: first to: self size\\n\\n\\t\\n\\t\\t\\n\\t\\\" ' abc d' withoutLeadingBlanks\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'tak 4/25/2004 12:57'!\\nwithSeparatorsCompacted\\n\\t\\\"replace each sequences of whitespace by a single space character\\\"\\n\\t\\\"' test ' withSeparatorsCompacted = ' test '\\\"\\n\\t\\\"' test test' withSeparatorsCompacted = ' test test'\\\"\\n\\t\\\"'test test\\t\\t' withSeparatorsCompacted = 'test test '\\\"\\n\\n\\t| out in next isSeparator |\\n\\tself isEmpty ifTrue: [^ self].\\n\\n\\tout _ WriteStream on: (String new: self size).\\n\\tin _ self readStream.\\n\\tisSeparator _ [:char | char asciiValue < 256\\n\\t\\t\\t\\tand: [CSSeparators includes: char]].\\n\\t[in atEnd] whileFalse: [\\n\\t\\tnext _ in next.\\n\\t\\t(isSeparator value: next)\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\tout nextPut: $ .\\n\\t\\t\\t\\t[in atEnd or:\\n\\t\\t\\t\\t\\t[next _ in next.\\n\\t\\t\\t\\t\\t(isSeparator value: next)\\n\\t\\t\\t\\t\\t\\tifTrue: [false]\\n\\t\\t\\t\\t\\t\\tifFalse: [out nextPut: next. true]]] whileFalse]\\n\\t\\t\\tifFalse: [out nextPut: next]].\\n\\t^ out contents! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:06'!\\nwithoutLeadingDigits\\n\\t\\\"Answer the portion of the receiver that follows any leading series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string\\\"\\n\\t| firstNonDigit |\\n\\tfirstNonDigit _ (self findFirst: [:m | m isDigit not and: [m ~= $ ]]).\\n\\t^ firstNonDigit > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self copyFrom: firstNonDigit to: self size]\\n\\t\\tifFalse:\\n\\t\\t\\t['']\\n\\n\\\"\\n'234Whoopie' withoutLeadingDigits\\n' 4321 BlastOff!!' withoutLeadingDigits\\n'wimpy' withoutLeadingDigits\\n' 89Ten ' withoutLeadingDigits\\n'78 92' withoutLeadingDigits\\n\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 11/3/2004 19:24'!\\nwithoutTrailingBlanks\\n\\t\\\"Return a copy of the receiver from which trailing blanks have been trimmed.\\\"\\n\\n\\t| last |\\n\\tlast _ self findLast: [:c | c isSeparator not].\\n\\tlast = 0 ifTrue: [^ '']. \\\"no non-separator character\\\"\\n\\t^ self copyFrom: 1 to: last\\n\\n\\t\\\" ' abc d ' withoutTrailingBlanks\\\"\\n! !\\n\\n!String methodsFor: 'converting' stamp: 'yo 8/27/2002 14:06'!\\nwithoutTrailingDigits\\n\\t\\\"Answer the portion of the receiver that precedes any trailing series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string\\\"\\n\\t| firstDigit |\\n\\tfirstDigit _ (self findFirst: [:m | m isDigit or: [m = $ ]]).\\n\\t^ firstDigit > 0\\n\\t\\tifTrue:\\n\\t\\t\\t[self copyFrom: 1 to: firstDigit-1]\\n\\t\\tifFalse:\\n\\t\\t\\t[self]\\n\\n\\\"\\n'Whoopie234' withoutTrailingDigits\\n' 4321 BlastOff!!' withoutLeadingDigits\\n'wimpy' withoutLeadingDigits\\n' 89Ten ' withoutLeadingDigits\\n'78 92' withoutLeadingDigits\\n\\\"\\n! !\\n\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\ncopyReplaceTokens: oldSubstring with: newSubstring \\n\\t\\\"Replace all occurrences of oldSubstring that are surrounded\\n\\tby non-alphanumeric characters\\\"\\n\\t^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: true\\n\\t\\\"'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Snick'\\\"! !\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\ndeepCopy\\n\\t\\\"DeepCopy would otherwise mean make a copy of the character; since \\n\\tcharacters are unique, just return a shallowCopy.\\\"\\n\\n\\t^self shallowCopy! !\\n\\n!String methodsFor: 'copying' stamp: 'yo 11/3/2004 19:24'!\\npadded: leftOrRight to: length with: char\\n\\tleftOrRight = #left ifTrue:\\n\\t\\t[^ (String new: (length - self size max: 0) withAll: char) , self].\\n\\tleftOrRight = #right ifTrue:\\n\\t\\t[^ self , (String new: (length - self size max: 0) withAll: char)].! !\\n\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayAt: aPoint \\n\\t\\\"Display the receiver as a DisplayText at aPoint on the display screen.\\\"\\n\\n\\tself displayOn: Display at: aPoint! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium\\n\\t\\\"Display the receiver on the given DisplayMedium. 5/16/96 sw\\\"\\n\\n\\tself displayOn: aDisplayMedium at: 0 @ 0! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium at: aPoint \\n\\t\\\"Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, using black-colored text.\\\"\\n\\n\\tself displayOn: aDisplayMedium at: aPoint textColor: Color black! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayOn: aDisplayMedium at: aPoint textColor: aColor\\n\\t\\\"Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, rendering the text in the designated color\\\"\\n\\n\\t(self asDisplayText foregroundColor: (aColor ifNil: [Color black]) backgroundColor: Color white)\\n\\t\\tdisplayOn: aDisplayMedium at: aPoint! !\\n\\n!String methodsFor: 'displaying' stamp: 'yo 11/3/2004 19:24'!\\ndisplayProgressAt: aPoint from: minVal to: maxVal during: workBlock \\n\\t\\\"Display this string as a caption over a progress bar while workBlock is evaluated.\\n\\nEXAMPLE (Select next 6 lines and Do It)\\n'Now here''s some Real Progress'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: 10\\n\\tduring: [:bar |\\n\\t1 to: 10 do: [:x | bar value: x.\\n\\t\\t\\t(Delay forMilliseconds: 500) wait]].\\n\\nHOW IT WORKS (Try this in any other language :-)\\nSince your code (the last 2 lines in the above example) is in a block,\\nthis method gets control to display its heading before, and clean up \\nthe screen after, its execution.\\nThe key, though, is that the block is supplied with an argument,\\nnamed 'bar' in the example, which will update the bar image every \\nit is sent the message value: x, where x is in the from:to: range.\\n\\\"\\n\\t^ProgressInitiationException \\n\\t\\tdisplay: self\\n\\t\\tat: aPoint \\n\\t\\tfrom: minVal \\n\\t\\tto: maxVal \\n\\t\\tduring: workBlock! !\\n\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:16'!\\ngetInteger32: location\\n\\t| integer |\\n\\t<primitive: 'getInteger' module: 'IntegerPokerPlugin'>\\n\\t\\\"^IntegerPokerPlugin doPrimitive: #getInteger\\\"\\n\\n\\t\\\"the following is about 7x faster than interpreting the plugin if not compiled\\\"\\n\\n\\tinteger := \\n\\t\\t((self at: location) asInteger bitShift: 24) +\\n\\t\\t((self at: location+1) asInteger bitShift: 16) +\\n\\t\\t((self at: location+2) asInteger bitShift: 8) +\\n\\t\\t(self at: location+3) asInteger.\\n\\n\\tinteger > 1073741824 ifTrue: [^1073741824 - integer ].\\n\\t^integer\\n! !\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:17'!\\nputInteger32: anInteger at: location\\n\\t| integer |\\n\\t<primitive: 'putInteger' module: 'IntegerPokerPlugin'>\\n\\t\\\"IntegerPokerPlugin doPrimitive: #putInteger\\\"\\n\\n\\t\\\"the following is close to 20x faster than the above if the primitive is not compiled\\\"\\n\\t\\\"PUTCOUNTER _ PUTCOUNTER + 1.\\\"\\n\\tinteger _ anInteger.\\n\\tinteger < 0 ifTrue: [integer := 1073741824 - integer. ].\\n\\tself at: location+3 put: (Character value: (integer \\\\\\\\ 256)).\\n\\tself at: location+2 put: (Character value: (integer bitShift: -8) \\\\\\\\ 256).\\n\\tself at: location+1 put: (Character value: (integer bitShift: -16) \\\\\\\\ 256).\\n\\tself at: location put: (Character value: (integer bitShift: -24) \\\\\\\\ 256).\\n\\n\\\"Smalltalk at: #PUTCOUNTER put: 0\\\"! !\\n\\n!String methodsFor: 'encoding' stamp: 'ar 4/10/2005 17:18'!\\nwriteLeadingCharRunsOn: stream\\n\\n\\t| runLength runValues runStart leadingChar |\\n\\tself isEmpty ifTrue: [^ self].\\n\\n\\trunLength _ OrderedCollection new.\\n\\trunValues _ OrderedCollection new.\\n\\trunStart _ 1.\\n\\tleadingChar _ (self at: runStart) leadingChar.\\n\\t2 to: self size do: [:index |\\n\\t\\t(self at: index) leadingChar = leadingChar ifFalse: [\\n\\t\\t\\trunValues add: leadingChar.\\n\\t\\t\\trunLength add: (index - runStart).\\n\\t\\t\\tleadingChar _ (self at: index) leadingChar.\\n\\t\\t\\trunStart _ index.\\n\\t\\t].\\n\\t].\\n\\trunValues add: (self last) leadingChar.\\n\\trunLength add: self size + 1 - runStart.\\n\\n\\tstream nextPut: $(.\\n\\trunLength do: [:rr | rr printOn: stream. stream space].\\n\\tstream skip: -1; nextPut: $).\\n\\trunValues do: [:vv | vv printOn: stream. stream nextPut: $,].\\n\\tstream skip: -1.\\n! !\\n\\n\\n!String methodsFor: 'filter streaming' stamp: 'yo 8/26/2002 22:31'!\\nbyteEncode:aStream\\n\\n\\t^aStream writeString: self.\\n! !\\n\\n!String methodsFor: 'filter streaming' stamp: 'yo 8/26/2002 22:31'!\\nputOn:aStream\\n\\n\\t^aStream nextPutAll: self.\\n! !\\n\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacros\\n\\t^self expandMacrosWithArguments: #()! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWithArguments: anArray \\n\\t| newStream readStream char index |\\n\\tnewStream := WriteStream on: (String new: self size).\\n\\treadStream := ReadStream on: self.\\n\\t[readStream atEnd] whileFalse: \\n\\t\\t\\t[char := readStream next.\\n\\t\\t\\tchar == $< \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[| nextChar |\\n\\t\\t\\t\\t\\tnextChar := readStream next asUppercase.\\n\\t\\t\\t\\t\\tnextChar == $N ifTrue: [newStream cr].\\n\\t\\t\\t\\t\\tnextChar == $T ifTrue: [newStream tab].\\n\\t\\t\\t\\t\\tnextChar isDigit \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[index := nextChar digitValue.\\n\\t\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t\\t[readStream atEnd \\n\\t\\t\\t\\t\\t\\t\\t\\tor: [(nextChar := readStream next asUppercase) isDigit not]] \\n\\t\\t\\t\\t\\t\\t\\t\\t\\twhileFalse: [index := index * 10 + nextChar digitValue]].\\n\\t\\t\\t\\t\\tnextChar == $? \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[| trueString falseString |\\n\\t\\t\\t\\t\\t\\t\\ttrueString := readStream upTo: $:.\\n\\t\\t\\t\\t\\t\\t\\tfalseString := readStream upTo: $>.\\n\\t\\t\\t\\t\\t\\t\\treadStream position: readStream position - 1.\\n\\t\\t\\t\\t\\t\\t\\tnewStream \\n\\t\\t\\t\\t\\t\\t\\t\\tnextPutAll: ((anArray at: index) ifTrue: [trueString] ifFalse: [falseString])].\\n\\t\\t\\t\\t\\tnextChar == $P \\n\\t\\t\\t\\t\\t\\tifTrue: [newStream nextPutAll: (anArray at: index) printString].\\n\\t\\t\\t\\t\\tnextChar == $S ifTrue: [newStream nextPutAll: (anArray at: index)].\\n\\t\\t\\t\\t\\treadStream skipTo: $>]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[newStream nextPut: (char == $% ifTrue: [readStream next] ifFalse: [char])]].\\n\\t^newStream contents! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject \\n\\t^self expandMacrosWithArguments: (Array with: anObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject \\n\\t^self \\n\\t\\texpandMacrosWithArguments: (Array with: anObject with: anotherObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject with: thirdObject \\n\\t^self expandMacrosWithArguments: (Array \\n\\t\\t\\t\\twith: anObject\\n\\t\\t\\t\\twith: anotherObject\\n\\t\\t\\t\\twith: thirdObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'md 5/26/2005 13:34'!\\nexpandMacrosWith: anObject with: anotherObject with: thirdObject with: fourthObject \\n\\t^self expandMacrosWithArguments: (Array \\n\\t\\t\\t\\twith: anObject\\n\\t\\t\\t\\twith: anotherObject\\n\\t\\t\\t\\twith: thirdObject\\n\\t\\t\\t\\twith: fourthObject)! !\\n\\n!String methodsFor: 'formatting' stamp: 'yo 11/3/2004 19:24'!\\nformat: aCollection \\n\\t\\\"format the receiver with aCollection \\n\\t \\n\\tsimplest example: \\n\\t'foo {1} bar' format: {Date today}.\\n\\t \\n\\tcomplete example: \\n\\t'\\\\{ \\\\} \\\\\\\\ foo {1} bar {2}' format: {12. 'string'}. \\n\\t\\\"\\n\\t| result stream |\\n\\tresult := String new writeStream.\\n\\tstream := self readStream.\\n\\n\\t[stream atEnd]\\n\\t\\twhileFalse: [| currentChar | \\n\\t\\t\\tcurrentChar := stream next.\\n\\t\\t\\tcurrentChar == ${\\n\\t\\t\\t\\tifTrue: [| expression | \\n\\t\\t\\t\\t\\texpression := self getEnclosedExpressionFrom: stream.\\n\\t\\t\\t\\t\\tresult\\n\\t\\t\\t\\t\\t\\tnextPutAll: (self evaluateExpression: expression parameters: aCollection)]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tcurrentChar == $\\\\\\n\\t\\t\\t\\t\\t\\tifTrue: [stream atEnd\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [result nextPut: stream next]]\\n\\t\\t\\t\\t\\t\\tifFalse: [result nextPut: currentChar]]].\\n\\n\\t^ result contents! !\\n\\n!String methodsFor: 'formatting' stamp: 'yo 11/3/2004 19:24'!\\nwithCRs\\n\\t\\\"Return a copy of the receiver in which backslash (\\\\) characters have been replaced with carriage returns.\\\"\\n\\n\\t^ self collect: [ :c | c = $\\\\ ifTrue: [ Character cr ] ifFalse: [ c ]].! !\\n\\n\\n!String methodsFor: 'internet' stamp: 'yo 12/28/2003 01:17'!\\ndecodeMimeHeader\\n\\t\\\"See RFC 2047, MIME Part Three: Message Header Extension for Non-ASCII \\n\\tText. Text containing non-ASCII characters is encoded by the sequence \\n\\t=?character-set?encoding?encoded-text?= \\n\\tEncoding is Q (quoted printable) or B (Base64), handled by \\n\\tBase64MimeConverter / RFC2047MimeConverter.\\n\\n\\tThanks to Yokokawa-san, it works in m17n package. Try the following:\\n\\n\\t'=?ISO-2022-JP?B?U1dJS0lQT1AvGyRCPUJDKyVpJXMlQRsoQi8=?= =?ISO-2022-JP?B?GyRCJVElRiUjJSobKEIoUGF0aW8p?=' decodeMimeHeader.\\n\\\"\\n\\t| input output temp charset decoder encodedStream encoding pos |\\n\\tinput _ ReadStream on: self.\\n\\toutput _ WriteStream on: String new.\\n\\t[output\\n\\t\\tnextPutAll: (input upTo: $=).\\n\\t\\\"ASCII Text\\\"\\n\\tinput atEnd]\\n\\t\\twhileFalse: [(temp _ input next) = $?\\n\\t\\t\\t\\tifTrue: [charset _ input upTo: $?.\\n\\t\\t\\t\\t\\tencoding _ (input upTo: $?) asUppercase.\\n\\t\\t\\t\\t\\ttemp _ input upTo: $?.\\n\\t\\t\\t\\t\\tinput next.\\n\\t\\t\\t\\t\\t\\\"Skip final =\\\"\\n\\t\\t\\t\\t\\t(charset isNil or: [charset size = 0]) ifTrue: [charset _ 'LATIN-1'].\\n\\t\\t\\t\\t\\tencodedStream _ MultiByteBinaryOrTextStream on: String new encoding: charset.\\n\\t\\t\\t\\t\\tdecoder _ encoding = 'B'\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [Base64MimeConverter new]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [RFC2047MimeConverter new].\\n\\t\\t\\t\\t\\tdecoder\\n\\t\\t\\t\\t\\t\\tmimeStream: (ReadStream on: temp);\\n\\t\\t\\t\\t\\t\\t dataStream: encodedStream;\\n\\t\\t\\t\\t\\t\\t mimeDecode.\\n\\t\\t\\t\\t\\toutput nextPutAll: encodedStream reset contents.\\n\\t\\t\\t\\t\\tpos _ input position.\\n\\t\\t\\t\\t\\tinput skipSeparators.\\n\\t\\t\\t\\t\\t\\\"Delete spaces if followed by =\\\"\\n\\t\\t\\t\\t\\tinput peek = $=\\n\\t\\t\\t\\t\\t\\tifFalse: [input position: pos]]\\n\\t\\t\\t\\tifFalse: [output nextPut: $=;\\n\\t\\t\\t\\t\\t\\t nextPut: temp]].\\n\\t^ output contents! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\ndecodeQuotedPrintable\\n\\t\\\"Assume receiver is in MIME 'quoted-printable' encoding, and decode it.\\\"\\n \\n\\t^QuotedPrintableMimeConverter mimeDecode: self as: self class! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/9/2005 22:16'!\\nisoToSqueak\\n\\t^self \\\"no longer needed\\\"! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nisoToUtf8\\n\\t\\\"Convert ISO 8559-1 to UTF-8\\\"\\n\\t| s v |\\n\\ts _ WriteStream on: (String new: self size).\\n\\n\\tself do: [:c |\\n\\t\\tv _ c asciiValue.\\n\\t\\t(v > 128)\\n\\t\\t\\tifFalse: [s nextPut: c]\\n\\t\\t\\tifTrue: [\\n\\t\\t\\t\\ts nextPut: (192+(v >> 6)) asCharacter.\\n\\t\\t\\t\\ts nextPut: (128+(v bitAnd: 63)) asCharacter]].\\n\\t^s contents. \\n! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/10/2005 15:58'!\\nmacToSqueak\\n\\t\\\"Convert the receiver from MacRoman to Squeak encoding\\\"\\n\\t^ self collect: [:each | each macToSqueak]! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/9/2005 22:16'!\\nsqueakToIso\\n\\t^self \\\"no longer needed\\\"! !\\n\\n!String methodsFor: 'internet' stamp: 'ar 4/10/2005 15:55'!\\nsqueakToMac\\n\\t\\\"Convert the receiver from Squeak to MacRoman encoding\\\"\\n\\t^ self collect: [:each | each squeakToMac]! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nutf8ToIso\\n\\t\\\"Only UTF-8 characters that maps to 8-bit ISO-8559-1 values are converted. Others raises an error\\\"\\n\\t| s i c v c2 v2 |\\n\\ts _ WriteStream on: (String new: self size).\\n\\t\\n\\ti _ 1.\\n\\t[i <= self size] whileTrue: [\\n\\t\\tc _ self at: i. i_i+1.\\n\\t\\tv _ c asciiValue.\\n\\t\\t(v > 128)\\n\\t\\t\\tifFalse: [ s nextPut: c ]\\n\\t\\t\\tifTrue: [((v bitAnd: 252) == 192)\\n\\t\\t\\t\\tifFalse: [self error: 'illegal UTF-8 ISO character']\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t(i > self size) ifTrue: [ self error: 'illegal end-of-string, expected 2nd byte of UTF-8'].\\n\\t\\t\\t\\t\\tc2 _ self at: i. i_i+1.\\n\\t\\t\\t\\t\\tv2 _ c2 asciiValue.\\n\\t\\t\\t\\t\\t((v2 bitAnd: 192) = 128) ifFalse: [self error: 'illegal 2nd UTF-8 char']. \\n\\t\\t\\t\\t\\ts nextPut: ((v2 bitAnd: 63) bitOr: ((v << 6) bitAnd: 192)) asCharacter]]].\\n\\t^s contents. \\n! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithInternetLineEndings\\n\\t\\\"change line endings from CR's to CRLF's. This is probably in\\nprepration for sending a string over the Internet\\\"\\n\\t| cr lf |\\n\\tcr _ Character cr.\\n\\tlf _ Character linefeed.\\n\\t^self class streamContents: [ :stream |\\n\\t\\tself do: [ :c |\\n\\t\\t\\tstream nextPut: c.\\n\\t\\t\\tc = cr ifTrue:[ stream nextPut: lf ]. ] ].! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithSqueakLineEndings\\n\\t\\\"assume the string is textual, and that CR, LF, and CRLF are all \\n\\tvalid line endings. Replace each occurence with a single CR\\\"\\n\\t| cr lf input c crlf inPos outPos outString lineEndPos newOutPos |\\n\\tcr _ Character cr.\\n\\tlf _ Character linefeed.\\n\\tcrlf _ CharacterSet new.\\n\\tcrlf add: cr; add: lf.\\n\\n\\tinPos _ 1.\\n\\toutPos _ 1.\\n\\toutString _\\n String new: self size.\\n\\n\\t[ lineEndPos _ self indexOfAnyOf: crlf startingAt: inPos ifAbsent: [0].\\n\\t\\tlineEndPos ~= 0 ] whileTrue: [\\n\\t\\t\\tnewOutPos _ outPos + (lineEndPos - inPos + 1).\\n\\t\\t\\toutString replaceFrom: outPos to: newOutPos - 2 with: self startingAt: inPos.\\n\\t\\t\\toutString at: newOutPos-1 put: cr.\\n\\t\\t\\toutPos _ newOutPos.\\n\\n\\t\\t\\t((self at: lineEndPos) = cr and: [ lineEndPos < self size and: [ (self at: lineEndPos+1) = lf ] ]) ifTrue: [\\n\\t\\t\\t\\t\\\"CRLF ending\\\"\\n\\t\\t\\t\\tinPos _ lineEndPos + 2 ]\\n\\t\\t\\tifFalse: [ \\n\\t\\t\\t\\t\\\"CR or LF ending\\\"\\n\\t\\t\\t\\tinPos _ lineEndPos + 1 ]. ].\\n\\n\\t\\\"no more line endings. copy the rest\\\"\\n\\tnewOutPos _ outPos + (self size - inPos + 1).\\n\\toutString replaceFrom: outPos to: newOutPos-1 with: self startingAt: inPos.\\n\\n\\t^outString copyFrom: 1 to: newOutPos-1\\n\\t! !\\n\\n!String methodsFor: 'internet' stamp: 'yo 11/3/2004 19:24'!\\nwithoutQuoting\\n\\t\\\"remove the initial and final quote marks, if present\\\"\\n\\t\\\"'''h''' withoutQuoting\\\"\\n\\t| quote |\\n\\tself size < 2 ifTrue: [ ^self ].\\n\\tquote _ self first.\\n\\t(quote = $' or: [ quote = $\\\" ])\\n\\t\\tifTrue: [ ^self copyFrom: 2 to: self size - 1 ]\\n\\t\\tifFalse: [ ^self ].! !\\n\\n\\n!String methodsFor: 'paragraph support' stamp: 'yo 8/26/2002 22:19'!\\nindentationIfBlank: aBlock\\n\\t\\\"Answer the number of leading tabs in the receiver. If there are\\n\\t no visible characters, pass the number of tabs to aBlock and return its value.\\\"\\n\\n\\t| reader leadingTabs lastSeparator cr tab ch |\\n\\tcr _ Character cr.\\n\\ttab _ Character tab.\\n\\treader _ ReadStream on: self.\\n\\tleadingTabs _ 0.\\n\\t[reader atEnd not and: [(ch _ reader next) = tab]]\\n\\t\\twhileTrue: [leadingTabs _ leadingTabs + 1].\\n\\tlastSeparator _ leadingTabs + 1.\\n\\t[reader atEnd not and: [ch isSeparator and: [ch ~= cr]]]\\n\\t\\twhileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next].\\n\\tlastSeparator = self size | (ch = cr)\\n\\t\\tifTrue: [^aBlock value: leadingTabs].\\n\\t^ leadingTabs.\\n! !\\n\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nbasicType\\n\\t\\\"Answer a symbol representing the inherent type of the receiver\\\"\\n\\n\\t\\\"Number String Boolean player collection sound color etc\\\"\\n\\t^ #String! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 8/26/2002 22:57'!\\nencodeDoublingQuoteOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n\\t| x |\\n\\taStream print: $'.\\n\\t1 to: self size do:\\n\\t\\t[:i |\\n\\t\\taStream print: (x _ self at: i).\\n\\t\\tx = $' ifTrue: [aStream print: x]].\\n\\taStream print: $'! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nisLiteral\\n\\n\\t^true! !\\n\\n!String methodsFor: 'printing' stamp: 'sd 7/8/2006 18:06'!\\nprintOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n \\n\\tself storeOn: aStream! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 8/26/2002 22:58'!\\nstoreOn: aStream \\n\\t\\\"Print inside string quotes, doubling inbedded quotes.\\\"\\n\\t| x |\\n\\taStream nextPut: $'.\\n\\t1 to: self size do:\\n\\t\\t[:i |\\n\\t\\taStream nextPut: (x _ self at: i).\\n\\t\\tx = $' ifTrue: [aStream nextPut: x]].\\n\\taStream nextPut: $'! !\\n\\n!String methodsFor: 'printing' stamp: 'yo 11/3/2004 19:24'!\\nstringRepresentation\\n\\t\\\"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\\\"\\n\\n\\t^ self ! !\\n\\n\\n!String methodsFor: 'system primitives' stamp: 'sw 10/20/2004 17:51'!\\nendsWithAColon \\n\\t\\\"Answer whether the final character of the receiver is a colon\\\"\\n\\n\\t^ self size > 0 and: [self last == $:]\\n\\n\\\"\\n#fred: endsWithAColon\\n'fred' endsWithAColon\\n\\\"! !\\n\\n!String methodsFor: 'system primitives' stamp: 'ar 4/10/2005 16:55'!\\nfindSubstring: key in: body startingAt: start matchTable: matchTable\\n\\t\\\"Answer the index in the string body at which the substring key first occurs, at or beyond start. The match is determined using matchTable, which can be used to effect, eg, case-insensitive matches. If no match is found, zero will be returned.\\\"\\n\\t| index c1 c2 |\\n\\tmatchTable == nil ifTrue: [\\n\\t\\tkey size = 0 ifTrue: [^ 0].\\n\\t\\tstart to: body size - key size + 1 do:\\n\\t\\t\\t[:startIndex |\\n\\t\\t\\tindex _ 1.\\n\\t\\t\\t\\t[(body at: startIndex+index-1)\\n\\t\\t\\t\\t\\t= (key at: index)]\\n\\t\\t\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t\\t[index = key size ifTrue: [^ startIndex].\\n\\t\\t\\t\\t\\tindex _ index+1]].\\n\\t\\t^ 0\\n\\t].\\n\\n\\tkey size = 0 ifTrue: [^ 0].\\n\\tstart to: body size - key size + 1 do:\\n\\t\\t[:startIndex |\\n\\t\\tindex _ 1.\\n\\t\\t[c1 _ body at: startIndex+index-1.\\n\\t\\tc2 _ key at: index.\\n\\t\\t((c1 leadingChar = 0) ifTrue: [(matchTable at: c1 asciiValue + 1)]\\n\\t\\t\\t\\t\\t\\tifFalse: [c1 asciiValue + 1])\\n\\t\\t\\t= ((c2 leadingChar = 0) ifTrue: [(matchTable at: c2 asciiValue + 1)]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [c2 asciiValue + 1])]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t[index = key size ifTrue: [^ startIndex].\\n\\t\\t\\t\\tindex _ index+1]].\\n\\t^ 0\\n! !\\n\\n!String methodsFor: 'system primitives' stamp: 'yo 11/3/2004 19:24'!\\nnumArgs \\n\\t\\\"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.\\\"\\n\\n\\t| firstChar numColons excess start ix |\\n\\tself size = 0 ifTrue: [^ -1].\\n\\tfirstChar _ self at: 1.\\n\\t(firstChar isLetter or: [firstChar = $:]) ifTrue:\\n\\t\\t[\\\"Fast reject if any chars are non-alphanumeric\\\"\\n\\t\\t(self findSubstring: '~' in: self startingAt: 1 matchTable: Tokenish) > 0 ifTrue: [^ -1].\\n\\t\\t\\\"Fast colon count\\\"\\n\\t\\tnumColons _ 0. start _ 1.\\n\\t\\t[(ix _ self findSubstring: ':' in: self startingAt: start matchTable: CaseSensitiveOrder) > 0]\\n\\t\\t\\twhileTrue:\\n\\t\\t\\t\\t[numColons _ numColons + 1.\\n\\t\\t\\t\\tstart _ ix + 1].\\n\\t\\tnumColons = 0 ifTrue: [^ 0].\\n\\t\\tfirstChar = $:\\n\\t\\t\\tifTrue: [excess _ 2 \\\"Has an initial keyword, as #:if:then:else:\\\"]\\n\\t\\t\\tifFalse: [excess _ 0].\\n\\t\\tself last = $:\\n\\t\\t\\tifTrue: [^ numColons - excess]\\n\\t\\t\\tifFalse: [^ numColons - excess - 1 \\\"Has a final keywords as #nextPut::andCR\\\"]].\\n\\tfirstChar isSpecial ifTrue:\\n\\t\\t[self size = 1 ifTrue: [^ 1].\\n\\t\\t2 to: self size do: [:i | (self at: i) isSpecial ifFalse: [^ -1]].\\n\\t\\t^ 1].\\n\\t^ -1.! !\\n\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nhasContentsInExplorer\\n\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 16:49'!\\nincludesUnifiedCharacter\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisAllDigits\\n\\t\\\"whether the receiver is composed entirely of digits\\\"\\n\\tself do: [:c | c isDigit ifFalse: [^ false]].\\n\\t^ true! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisAllSeparators\\n\\t\\\"whether the receiver is composed entirely of separators\\\"\\n\\tself do: [ :c | c isSeparator ifFalse: [ ^false ] ].\\n\\t^true! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 8/4/2003 12:26'!\\nisAsciiString\\n\\n\\t| c |\\n\\tc _ self detect: [:each | each asciiValue > 127] ifNone: [nil].\\n\\t^ c isNil.\\n! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 16:23'!\\nisByteString\\n\\t\\\"Answer whether the receiver is a ByteString\\\"\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/10/2005 23:25'!\\nisOctetString\\n\\t\\\"Answer whether the receiver can be represented as a byte string. \\n\\tThis is different from asking whether the receiver *is* a ByteString \\n\\t(i.e., #isByteString)\\\"\\n\\t1 to: self size do: [:pos |\\n\\t\\t(self at: pos) asInteger >= 256 ifTrue: [^ false].\\n\\t].\\n\\t^ true.\\n! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nisString\\n\\t^ true! !\\n\\n!String methodsFor: 'testing' stamp: 'ar 4/12/2005 19:52'!\\nisWideString\\n\\t\\\"Answer whether the receiver is a WideString\\\"\\n\\t^false! !\\n\\n!String methodsFor: 'testing' stamp: 'yo 11/3/2004 19:24'!\\nlastSpacePosition\\n\\t\\\"Answer the character position of the final space or other separator character in the receiver, and 0 if none\\\"\\n\\tself size to: 1 by: -1 do:\\n\\t\\t[:i | ((self at: i) isSeparator) ifTrue: [^ i]].\\n\\t^ 0\\n\\n\\\"\\n'fred the bear' lastSpacePosition\\n'ziggie' lastSpacePosition\\n'elvis ' lastSpacePosition\\n'wimpy ' lastSpacePosition\\n'' lastSpacePosition\\n\\\"! !\\n\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/24/2004 19:42'!\\ntranslated\\n\\t\\\"answer the receiver translated to the default language\\\"\\n\\t^ NaturalLanguageTranslator current translate: self! !\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/27/2004 18:43'!\\ntranslatedIfCorresponds\\n\\t\\\"answer the receiver translated to the default language only if \\n\\tthe receiver begins and ends with an underscore (_)\\\"\\n\\t^ ('_*_' match: self)\\n\\t\\tifTrue: [(self copyFrom: 2 to: self size - 1) translated]\\n\\t\\tifFalse: [self]! !\\n\\n!String methodsFor: 'translating' stamp: 'dgd 8/24/2004 19:38'!\\ntranslatedTo: localeID \\n\\t\\\"answer the receiver translated to the given locale id\\\"\\n\\t^ localeID translator translate: self! !\\n\\n\\n!String methodsFor: 'user interface' stamp: 'md 7/28/2005 20:42'!\\nasExplorerString\\n\\n\\t^ self printString! !\\n\\n!String methodsFor: 'user interface' stamp: 'ar 9/27/2005 20:02'!\\nopenInWorkspaceWithTitle: aTitle\\n\\t\\\"Open up a workspace with the receiver as its contents, with the given title\\\"\\n\\tUIManager default edit: self label: aTitle! !\\n\\n\\n!String methodsFor: '*eToys-*Morphic' stamp: 'ar 4/10/2005 17:06'!\\nnewTileMorphRepresentative\\n\\t^ TileMorph new setLiteral: self;addSuffixIfCan! !\\n\\n\\n!String methodsFor: '*Morphic' stamp: 'ar 4/10/2005 17:07'!\\nasMorph \\n\\t\\\"Answer the receiver as a StringMorph\\\"\\n\\n\\t^ StringMorph contents: self\\n\\n\\\"'bugs black blood' asMorph openInHand\\\"! !\\n\\n!String methodsFor: '*Morphic' stamp: 'ar 4/10/2005 17:07'!\\nasStringMorph \\n\\t\\\"Answer the receiver as a StringMorph\\\"\\n\\n\\t^ StringMorph contents: self\\n\\n\\\"'bugs black blood' asStringMorph openInHand\\\"! !\\n\\n\\n!String methodsFor: '*MorphicExtras-*morphic-Postscript Canvases' stamp: 'yo 11/3/2004 19:24'!\\nasPostscript\\n\\n\\t| temp |\\n\\ttemp _ self asString copyReplaceAll: '(' with: '\\\\('.\\n\\ttemp _ temp copyReplaceAll: ')' with: '\\\\)'.\\n\\ttemp _ temp copyReplaceAll: '\\n' \\n\\t\\t\\twith: ''.\\n\\t^ PostscriptEncoder mapMacStringToPS: temp! !\\n\\n\\n!String methodsFor: '*Morphic-converting' stamp: 'yo 11/3/2004 19:24'!\\nopenAsMorph\\n\\t\\\"Open the receiver as a morph\\\"\\n\\n\\t^ self asMorph openInHand ! !\\n\\n\\n!String methodsFor: '*monticello' stamp: 'avi 2/4/2004 14:14'!\\nextractNumber\\n\\t^ ('0', self select: [:ea | ea isDigit]) asNumber! !\\n\\n\\n!String methodsFor: '*network-uri' stamp: 'mir 2/26/2002 14:59'!\\nasURI\\n\\t\\\"convert to a Url\\\"\\n\\t\\\"'http://www.cc.gatech.edu/' asURI\\\"\\n\\t\\\"'msw://chaos.resnet.gatech.edu:9000/' asURI\\\"\\n\\t^URI fromString: self! !\\n\\n\\n!String methodsFor: '*packageinfo-base' stamp: 'nk 8/30/2004 09:02'!\\nescapeEntities\\n\\t^ self species streamContents: [:s | self do: [:c | s nextPutAll: c escapeEntities]]\\n! !\\n\\n\\n!String methodsFor: '*services-base' stamp: 'rr 3/21/2006 12:00'!\\nservice\\n\\t^ self serviceOrNil ifNil: [ServiceCategory new id: self asSymbol]! !\\n\\n!String methodsFor: '*services-base' stamp: 'rr 3/21/2006 12:00'!\\nserviceOrNil\\n\\t^ ServiceRegistry current serviceWithId: self asSymbol! !\\n\\n\\n!String methodsFor: '*versionnumber' stamp: 'yo 11/3/2004 19:24'!\\nasVersion\\n\\n\\t\\\"Answer a VersionNumber\\\"\\n\\n\\n\\n\\t^VersionNumber fromString: self! !\\n\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\ncorrectAgainstEnumerator: wordBlock continuedFrom: oldCollection\\n\\t\\\"The guts of correction, instead of a wordList, there is a block that should take another block and enumerate over some list with it.\\\"\\n\\n\\t| choices scoreMin results score maxChoices |\\n\\tscoreMin _ self size // 2 min: 3.\\n\\tmaxChoices _ 10.\\n\\toldCollection isNil\\n\\t\\tifTrue: [ choices _ SortedCollection sortBlock: [ :x :y | x value > y value ] ]\\n\\t\\tifFalse: [ choices _ oldCollection ].\\n\\twordBlock isNil\\n\\t\\tifTrue:\\n\\t\\t\\t[ results _ OrderedCollection new.\\n\\t\\t\\t1 to: (maxChoices min: choices size) do: [ :i | results add: (choices at: i) key ] ]\\n\\t\\tifFalse:\\n\\t\\t\\t[ wordBlock value: [ :word |\\n\\t\\t\\t\\t(score _ self alike: word) >= scoreMin ifTrue:\\n\\t\\t\\t\\t\\t[ choices add: (Association key: word value: score).\\n\\t\\t\\t\\t\\t\\t(choices size >= maxChoices) ifTrue: [ scoreMin _ (choices at: maxChoices) value] ] ].\\n\\t\\t\\tresults _ choices ].\\n\\t^ results! !\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\nevaluateExpression: aString parameters: aCollection \\n\\t\\\"private - evaluate the expression aString with \\n\\taCollection as the parameters and answer the \\n\\tevaluation result as an string\\\"\\n\\t| index |\\n\\tindex := ('0' , aString) asNumber.\\n\\n\\tindex isZero\\n\\t\\tifTrue: [^ '[invalid subscript: {1}]' format: {aString}].\\n\\n\\tindex > aCollection size\\n\\t\\tifTrue: [^ '[subscript is out of bounds: {1}]' format: {aString}].\\n\\n\\t^ (aCollection at: index) asString! !\\n\\n!String methodsFor: 'private' stamp: 'yo 11/3/2004 19:24'!\\ngetEnclosedExpressionFrom: aStream \\n\\t\\\"private - get the expression enclosed between '{' and \\n\\t'}' and remove all the characters from the stream\\\"\\n\\t| result currentChar |\\n\\tresult := String new writeStream.\\n\\n\\t[aStream atEnd \\n\\t\\tor: [(currentChar := aStream next) == $}]]\\n\\t\\twhileFalse: [result nextPut: currentChar].\\n\\n\\t^ result contents withBlanksTrimmed! !\\n\\n!String methodsFor: 'private' stamp: 'yo 8/26/2002 22:53'!\\nreplaceFrom: start to: stop with: replacement startingAt: repStart \\n\\t\\\"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.\\\"\\n\\t<primitive: 105>\\n\\tsuper replaceFrom: start to: stop with: replacement startingAt: repStart! !\\n\\n!String methodsFor: 'private' stamp: 'yo 8/28/2002 15:22'!\\nstringhash\\n\\n\\t^ self hash.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nString class\\n\\tinstanceVariableNames: ''!\\n\\n!String class methodsFor: 'examples' stamp: 'yo 11/3/2004 19:24'!\\nexample\\n\\t\\\"To see the string displayed at the cursor point, execute this expression\\n\\tand select a point by pressing a mouse button.\\\"\\n\\n\\t'this is some text' displayOn: Display at: Sensor waitButton! !\\n\\n\\n!String class methodsFor: 'formatting' stamp: 'md 6/5/2005 07:49'!\\nexpandMacro: macroType argument: argument withExpansions: expansions \\n\\tmacroType = $s ifTrue: [^expansions at: argument].\\n\\tmacroType = $p ifTrue: [^(expansions at: argument) printString].\\n\\tmacroType = $n ifTrue: [^String cr].\\n\\tmacroType = $t ifTrue: [^String tab].\\n\\tself error: 'unknown expansion type'! !\\n\\n\\n!String class methodsFor: 'initialization' stamp: 'ar 4/9/2005 22:37'!\\ninitialize \\\"self initialize\\\"\\n\\n\\t| order |\\n\\tAsciiOrder _ (0 to: 255) as: ByteArray.\\n\\n\\tCaseInsensitiveOrder _ AsciiOrder copy.\\n\\t($a to: $z) do:\\n\\t\\t[:c | CaseInsensitiveOrder at: c asciiValue + 1\\n\\t\\t\\t\\tput: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)].\\n\\n\\t\\\"Case-sensitive compare sorts space, digits, letters, all the rest...\\\"\\n\\tCaseSensitiveOrder _ ByteArray new: 256 withAll: 255.\\n\\torder _ -1.\\n\\t' 0123456789' do: \\\"0..10\\\"\\n\\t\\t[:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].\\n\\t($a to: $z) do: \\\"11-64\\\"\\n\\t\\t[:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order _ order+1).\\n\\t\\tCaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)].\\n\\t1 to: CaseSensitiveOrder size do:\\n\\t\\t[:i | (CaseSensitiveOrder at: i) = 255 ifTrue:\\n\\t\\t\\t[CaseSensitiveOrder at: i put: (order _ order+1)]].\\n\\torder = 255 ifFalse: [self error: 'order problem'].\\n\\n\\t\\\"a table for translating to lower case\\\"\\n\\tLowercasingTable _ String withAll: (Character allByteCharacters collect: [:c | c asLowercase]).\\n\\n\\t\\\"a table for translating to upper case\\\"\\n\\tUppercasingTable _ String withAll: (Character allByteCharacters collect: [:c | c asUppercase]).\\n\\n\\t\\\"a table for testing tokenish (for fast numArgs)\\\"\\n\\tTokenish _ String withAll: (Character allByteCharacters collect:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[:c | c tokenish ifTrue: [c] ifFalse: [$~]]).\\n\\n\\t\\\"CR and LF--characters that terminate a line\\\"\\n\\tCSLineEnders _ CharacterSet empty.\\n\\tCSLineEnders add: Character cr.\\n\\tCSLineEnders add: Character lf.\\n\\n \\t\\\"separators and non-separators\\\"\\n\\tCSSeparators _ CharacterSet separators.\\n\\tCSNonSeparators _ CSSeparators complement.! !\\n\\n!String class methodsFor: 'initialization' stamp: 'yo 8/11/2003 21:11'!\\ninitializeHtmlEntities\\n\\t\\\"self initializeHtmlEntities\\\"\\n\\n\\tHtmlEntities _ (Dictionary new: 128)\\n\\t\\tat: 'amp'\\tput: $&;\\n\\t\\tat: 'lt'\\t\\tput: $<;\\n\\t\\tat: 'gt'\\t\\tput: $>;\\n\\t\\tat: 'quot'\\tput: $\\\";\\n\\t\\tat: 'euro'\\tput: Character euro;\\n\\t\\tyourself.\\n\\t#('nbsp' 'iexcl' 'cent' 'pound' 'curren' 'yen' 'brvbar' 'sect' 'uml' 'copy' 'ordf' 'laquo' 'not' 'shy' 'reg' 'hibar' 'deg' 'plusmn' 'sup2' 'sup3' 'acute' 'micro' 'para' 'middot' 'cedil' 'sup1' 'ordm' 'raquo' 'frac14' 'frac12' 'frac34' 'iquest' 'Agrave' 'Aacute' 'Acirc' 'Atilde' 'Auml' 'Aring' 'AElig' 'Ccedil' 'Egrave' 'Eacute' 'Ecirc' 'Euml' 'Igrave' 'Iacute' 'Icirc' 'Iuml' 'ETH' 'Ntilde' 'Ograve' 'Oacute' 'Ocirc' 'Otilde' 'Ouml' 'times' 'Oslash' 'Ugrave' 'Uacute' 'Ucirc' 'Uuml' 'Yacute' 'THORN' 'szlig' 'agrave' 'aacute' 'acirc' 'atilde' 'auml' 'aring' 'aelig' 'ccedil' 'egrave' 'eacute' 'ecirc' 'euml' 'igrave' 'iacute' 'icirc' 'iuml' 'eth' 'ntilde' 'ograve' 'oacute' 'ocirc' 'otilde' 'ouml' 'divide' 'oslash' 'ugrave' 'uacute' 'ucirc' 'uuml' 'yacute' 'thorn' 'yuml' ) withIndexDo: [:each :index | HtmlEntities at: each put: (index + 159) asCharacter]! !\\n\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncr\\n\\t\\\"Answer a string containing a single carriage return character.\\\"\\n\\n\\t^ self with: Character cr\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncrlf\\n\\t\\\"Answer a string containing a carriage return and a linefeed.\\\"\\n\\n\\t^ self with: Character cr with: Character lf\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ncrlfcrlf\\n\\t^self crlf , self crlf.\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 16:24'!\\nfromByteArray: aByteArray\\n\\n\\t^ aByteArray asString\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nfromPacked: aLong\\n\\t\\\"Convert from a longinteger to a String of length 4.\\\"\\n\\n\\t| s |\\n\\ts _ self new: 4.\\n\\ts at: 1 put: (aLong digitAt: 4) asCharacter.\\n\\ts at: 2 put: (aLong digitAt: 3) asCharacter.\\n\\ts at: 3 put: (aLong digitAt: 2) asCharacter.\\n\\ts at: 4 put: (aLong digitAt: 1) asCharacter.\\n\\t^s\\n\\n\\\"String fromPacked: 'TEXT' asPacked\\\"\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nfromString: aString \\n\\t\\\"Answer an instance of me that is a copy of the argument, aString.\\\"\\n\\t\\n\\t^ aString copyFrom: 1 to: aString size! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\nlf\\n\\t\\\"Answer a string containing a single carriage return character.\\\"\\n\\n\\t^ self with: Character lf! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 23:26'!\\nnew: sizeRequested \\n\\t\\\"Answer an instance of this class with the number of indexable\\n\\tvariables specified by the argument, sizeRequested.\\\"\\n\\tself == String \\n\\t\\tifTrue:[^ByteString new: sizeRequested]\\n\\t\\tifFalse:[^self basicNew: sizeRequested].! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 13:27'!\\nreadFrom: inStream\\n\\t\\\"Answer an instance of me that is determined by reading the stream, \\n\\tinStream. Embedded double quotes become the quote Character.\\\"\\n\\n\\t| outStream char done |\\n\\toutStream _ WriteStream on: (self new: 16).\\n\\t\\\"go to first quote\\\"\\n\\tinStream skipTo: $'.\\n\\tdone _ false.\\n\\t[done or: [inStream atEnd]]\\n\\t\\twhileFalse: \\n\\t\\t\\t[char _ inStream next.\\n\\t\\t\\tchar = $'\\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[char _ inStream next.\\n\\t\\t\\t\\t\\tchar = $'\\n\\t\\t\\t\\t\\t\\tifTrue: [outStream nextPut: char]\\n\\t\\t\\t\\t\\t\\tifFalse: [done _ true]]\\n\\t\\t\\t\\tifFalse: [outStream nextPut: char]].\\n\\t^outStream contents! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 11/3/2004 19:24'!\\ntab\\n\\t\\\"Answer a string containing a single tab character.\\\"\\n\\n\\t^ self with: Character tab\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'yo 8/28/2002 13:29'!\\nvalue: anInteger\\n\\n\\t^ self with: (Character value: anInteger).\\n! !\\n\\n!String class methodsFor: 'instance creation' stamp: 'ar 4/12/2005 17:34'!\\nwith: aCharacter\\n\\t| newCollection |\\n\\taCharacter asInteger < 256\\n\\t\\tifTrue:[newCollection _ ByteString new: 1]\\n\\t\\tifFalse:[newCollection _ WideString new: 1].\\n\\tnewCollection at: 1 put: aCharacter.\\n\\t^newCollection! !\\n\\n\\n!String class methodsFor: 'primitives' stamp: 'yo 12/15/2005 13:41'!\\ncompare: string1 with: string2 collated: order\\n\\t\\\"Return 1, 2 or 3, if string1 is <, =, or > string2, with the collating order of characters given by the order array.\\\"\\n\\n\\t| len1 len2 c1 c2 |\\n\\torder == nil ifTrue: [\\n\\t\\tlen1 _ string1 size.\\n\\t\\tlen2 _ string2 size.\\n\\t\\t1 to: (len1 min: len2) do:[:i |\\n\\t\\t\\tc1 _ (string1 at: i) asInteger.\\n\\t\\t\\tc2 _ (string2 at: i) asInteger.\\n\\t\\t\\tc1 = c2 ifFalse: [c1 < c2 ifTrue: [^ 1] ifFalse: [^ 3]].\\n\\t\\t].\\n\\t\\tlen1 = len2 ifTrue: [^ 2].\\n\\t\\tlen1 < len2 ifTrue: [^ 1] ifFalse: [^ 3].\\n\\t].\\n\\tlen1 _ string1 size.\\n\\tlen2 _ string2 size.\\n\\t1 to: (len1 min: len2) do:[:i |\\n\\t\\tc1 _ (string1 at: i) asInteger.\\n\\t\\tc2 _ (string2 at: i) asInteger.\\n\\t\\tc1 < 256 ifTrue: [c1 _ order at: c1 + 1].\\n\\t\\tc2 < 256 ifTrue: [c2 _ order at: c2 + 1].\\n\\t\\tc1 = c2 ifFalse:[c1 < c2 ifTrue: [^ 1] ifFalse: [^ 3]].\\n\\t].\\n\\tlen1 = len2 ifTrue: [^ 2].\\n\\tlen1 < len2 ifTrue: [^ 1] ifFalse: [^ 3].\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\nfindFirstInString: aString inSet: inclusionMap startingAt: start\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| i stringSize ascii more |\\n\\tinclusionMap size ~= 256 ifTrue: [^ 0].\\n\\tstringSize _ aString size.\\n\\tmore _ true.\\n\\ti _ start - 1.\\n\\t[more and: [i + 1 <= stringSize]] whileTrue: [\\n\\t\\ti _ i + 1.\\n\\t\\tascii _ (aString at: i) asciiValue.\\n\\t\\tmore _ ascii < 256 ifTrue: [(inclusionMap at: ascii + 1) = 0] ifFalse: [true].\\n\\t].\\n\\n\\ti + 1 > stringSize ifTrue: [^ 0].\\n\\t^ i! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\nindexOfAscii: anInteger inString: aString startingAt: start\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| stringSize |\\n\\tstringSize _ aString size.\\n\\tstart to: stringSize do: [:pos |\\n\\t\\t(aString at: pos) asInteger = anInteger ifTrue: [^ pos]].\\n\\t^ 0\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:29'!\\nstringHash: aString initialHash: speciesHash\\n\\t| stringSize hash low |\\n\\tstringSize _ aString size.\\n\\thash _ speciesHash bitAnd: 16rFFFFFFF.\\n\\t1 to: stringSize do: [:pos |\\n\\t\\thash _ hash + (aString at: pos) asInteger.\\n\\t\\t\\\"Begin hashMultiply\\\"\\n\\t\\tlow _ hash bitAnd: 16383.\\n\\t\\thash _ (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF.\\n\\t].\\n\\t^ hash.\\n! !\\n\\n!String class methodsFor: 'primitives' stamp: 'ar 4/10/2005 16:36'!\\ntranslate: aString from: start to: stop table: table\\n\\t\\\"Trivial, non-primitive version\\\"\\n\\t| char |\\n\\tstart to: stop do: [:i |\\n\\t\\tchar _ (aString at: i) asInteger.\\n\\t\\tchar < 256 ifTrue: [aString at: i put: (table at: char+1)].\\n\\t].\\n! !\\nStringMorph subclass: #StringButtonMorph\\n\\tinstanceVariableNames: 'target actionSelector arguments actWhen oldColor'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'MorphicExtras-Widgets'!\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\nactionSelector\\n\\n\\t^ actionSelector\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\nactionSelector: aSymbolOrString\\n\\n\\t(nil = aSymbolOrString or:\\n\\t ['nil' = aSymbolOrString or:\\n\\t [aSymbolOrString isEmpty]])\\n\\t\\tifTrue: [^ actionSelector _ nil].\\n\\n\\tactionSelector _ aSymbolOrString asSymbol.\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\narguments\\n\\n\\t^ arguments\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\narguments: aCollection\\n\\n\\targuments _ aCollection asArray copy.\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\ntarget\\n\\n\\t^ target\\n! !\\n\\n!StringButtonMorph methodsFor: 'accessing'!\\ntarget: anObject\\n\\n\\ttarget _ anObject\\n! !\\n\\n\\n!StringButtonMorph methodsFor: 'button' stamp: 'dgd 2/22/2003 18:45'!\\ndoButtonAction\\n\\t\\\"Perform the action of this button. Subclasses may override this method. The default behavior is to send the button's actionSelector to its target object with its arguments.\\\"\\n\\n\\t(target notNil and: [actionSelector notNil]) \\n\\t\\tifTrue: \\n\\t\\t\\t[Cursor normal \\n\\t\\t\\t\\tshowWhile: [target perform: actionSelector withArguments: arguments]]! !\\n\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'jm 7/28/97 11:55'!\\nupdateReferencesUsing: aDictionary\\n\\t\\\"If the arguments array points at a morph we are copying, then point at the new copy. And also copies the array, which is important!!\\\"\\n\\n\\tsuper updateReferencesUsing: aDictionary.\\n\\targuments _ arguments collect:\\n\\t\\t[:old | aDictionary at: old ifAbsent: [old]].\\n! !\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'tk 1/8/1999 09:47'!\\nveryDeepFixupWith: deepCopier\\n\\t\\\"If target and arguments fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!!!\\\"\\n\\nsuper veryDeepFixupWith: deepCopier.\\ntarget _ deepCopier references at: target ifAbsent: [target].\\narguments _ arguments collect: [:each |\\n\\tdeepCopier references at: each ifAbsent: [each]].\\n! !\\n\\n!StringButtonMorph methodsFor: 'copying' stamp: 'tk 1/8/1999 09:46'!\\nveryDeepInner: deepCopier\\n\\t\\\"Copy all of my instance variables. Some need to be not copied at all, but shared. \\tWarning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.\\\"\\n\\nsuper veryDeepInner: deepCopier.\\n\\\"target _ target.\\t\\tWeakly copied\\\"\\n\\\"actionSelector _ actionSelector.\\t\\ta Symbol\\\"\\n\\\"arguments _ arguments.\\t\\tAll weakly copied\\\"\\nactWhen _ actWhen veryDeepCopyWith: deepCopier.\\noldColor _ oldColor veryDeepCopyWith: deepCopier.! !\\n\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nhandlesMouseDown: evt\\n\\n\\t^ true\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:14'!\\nhandlesMouseStillDown: evt\\n\\t^actWhen == #whilePressed! !\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nmouseDown: evt\\n\\n\\toldColor _ color.\\n\\tactWhen == #buttonDown\\n\\t\\tifTrue: [self doButtonAction].\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:15'!\\nmouseMove: evt\\n\\tactWhen == #buttonDown ifTrue: [^ self].\\n\\t(self containsPoint: evt cursorPoint)\\n\\t\\tifTrue:[self color: (oldColor alphaMixed: 1/2 with: Color white)]\\n\\t\\tifFalse: [self color: oldColor].\\n! !\\n\\n!StringButtonMorph methodsFor: 'event handling' stamp: 'ar 10/25/2000 18:15'!\\nmouseStillDown: evt\\n\\tactWhen == #whilePressed ifFalse: [^ self].\\n\\t(self containsPoint: evt cursorPoint) ifTrue:[self doButtonAction].! !\\n\\n!StringButtonMorph methodsFor: 'event handling'!\\nmouseUp: evt\\n\\n\\tself color: oldColor.\\n\\t(actWhen == #buttonUp and: [self containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [self doButtonAction].\\n! !\\n\\n\\n!StringButtonMorph methodsFor: 'e-toy support' stamp: 'ar 3/17/2001 20:17'!\\nadaptToWorld: aWorld\\n\\tsuper adaptToWorld: aWorld.\\n\\ttarget _ target adaptedToWorld: aWorld.! !\\n\\n\\n!StringButtonMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:44'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\ttarget _ nil.\\n\\tactionSelector _ #flash.\\n\\targuments _ EmptyArray.\\n\\tactWhen _ #buttonUp.\\n\\tself contents: 'Flash' ! !\\n\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:57'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'change label' translated action: #setLabel.\\n\\taCustomMenu add: 'change action selector' translated action: #setActionSelector.\\n\\taCustomMenu add: 'change arguments' translated action: #setArguments.\\n\\taCustomMenu add: 'change when to act' translated action: #setActWhen.\\n\\tself addTargetingMenuItems: aCustomMenu hand: aHandMorph .! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:56'!\\naddTargetingMenuItems: aCustomMenu hand: aHandMorph \\n\\t\\\"Add targeting menu items\\\"\\n\\taCustomMenu addLine.\\n\\n\\taCustomMenu add: 'set target' translated action: #targetWith:.\\n\\taCustomMenu add: 'sight target' translated action: #sightTargets:.\\n\\ttarget\\n\\t\\tifNotNil: [aCustomMenu add: 'clear target' translated action: #clearTarget]! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'wiz 1/16/2006 19:55'!\\nclearTarget\\n\\n\\ttarget _ nil.\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/16/2005 21:02'!\\nsetActWhen\\n\\n\\t| selections |\\n\\tselections _ #(buttonDown buttonUp whilePressed).\\n\\tactWhen _ (SelectionMenu labelList: (selections collect: [:t | t translated]) selections: selections)\\n\\t\\tstartUpWithCaption: 'Choose one of the following conditions' translated.\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/16/2005 20:54'!\\nsetActionSelector\\n\\n\\t| newSel |\\n\\tnewSel _ FillInTheBlank\\n\\t\\trequest:\\n'Please type the selector to be sent to\\nthe target when this button is pressed' translated\\n\\t\\tinitialAnswer: actionSelector.\\n\\tnewSel isEmpty ifFalse: [self actionSelector: newSel].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'yo 3/14/2005 13:09'!\\nsetArguments\\n\\n\\t| s newArgs newArgsArray |\\n\\ts _ WriteStream on: ''.\\n\\targuments do: [:arg | arg printOn: s. s nextPutAll: '. '].\\n\\tnewArgs _ FillInTheBlank\\n\\t\\trequest:\\n'Please type the arguments to be sent to the target\\nwhen this button is pressed separated by periods' translated\\n\\t\\tinitialAnswer: s contents.\\n\\tnewArgs isEmpty ifFalse: [\\n\\t\\tnewArgsArray _ Compiler evaluate: '{', newArgs, '}' for: self logged: false.\\n\\t\\tself arguments: newArgsArray].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu'!\\nsetLabel\\n\\n\\t| newLabel |\\n\\tnewLabel _ FillInTheBlank\\n\\t\\trequest:\\n'Please type a new label for this button'\\n\\t\\tinitialAnswer: self contents.\\n\\tnewLabel isEmpty ifFalse: [self contents: newLabel].\\n! !\\n\\n!StringButtonMorph methodsFor: 'menu' stamp: 'dgd 2/22/2003 18:55'!\\nsetTarget: evt \\n\\t| rootMorphs |\\n\\trootMorphs _ self world rootMorphsAt: evt hand targetOffset.\\n\\ttarget _ rootMorphs size > 1\\n\\t\\tifTrue: [rootMorphs second]\\n\\t\\tifFalse: [nil]! !\\n\\n\\n!StringButtonMorph methodsFor: 'submorphs-add/remove'!\\nactWhen: aSymbol\\n\\t\\\"Set the condition under which to invoke my action to one of: #buttonDown, #buttonUp, and #whilePressed.\\\"\\n\\n\\tactWhen _ aSymbol.\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringButtonMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StringButtonMorph class methodsFor: 'printing' stamp: 'sw 2/16/98 03:02'!\\ndefaultNameStemForInstances\\n\\t^ 'SButton'! !\\nModel subclass: #StringHolder\\n\\tinstanceVariableNames: 'contents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Kernel-Remnants'!\\n!StringHolder commentStamp: '<historical>' prior: 0!\\nI am a kind of Model that includes a piece of text. In some cases, the text can be edited, and in some the text is a method.\\n\\nCategories 'code pane menu' and 'message list menu' are messages that may be called by my menus when the text is a method, and when some pane is a list of methods. Other of my subclasses may ignore these two catagories altogether.!\\n\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'di 5/19/1998 15:34'!\\nacceptContents: aString \\n\\t\\\"Set aString to be the contents of the receiver. Return true cuz happy\\\"\\n\\n\\tself contents: aString.\\n\\t^ true! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'nk 4/29/2004 12:32'!\\nclassCommentIndicated\\n\\t\\\"Answer true iff we're viewing the class comment.\\\"\\n\\t^false! !\\n\\n!StringHolder methodsFor: 'accessing'!\\ncontents\\n\\t\\\"Answer the contents that the receiver is holding--presumably a string.\\\"\\n\\n\\t^contents! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 1/12/1999 11:47'!\\ncontents: textOrString \\n\\t\\\"Set textOrString to be the contents of the receiver.\\\"\\n\\n\\tcontents _ textOrString \\\"asString\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/3/98 22:50'!\\ncontentsSelection\\n\\t\\\"Return the interval of text in the code pane to select when I set the pane's contents\\\"\\n\\n\\t^ 1 to: 0 \\\"null selection\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/9/2000 23:59'!\\nnoteAcceptanceOfCodeFor: aSelector\\n\\t\\\"A method has possibly been submitted for the receiver with aSelector as its selector; If the receiver wishes to take soem action here is a chance for it to do so\\\"\\n! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/1/2000 11:04'!\\nreformulateList\\n\\t\\\"If the receiver has a way of reformulating its message list, here is a chance for it to do so\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'sw 12/6/2000 17:48'!\\nreformulateListNoting: newSelector\\n\\t\\\"A method has possibly been submitted for the receiver with newSelector as its selector; If the receiver has a way of reformulating its message list, here is a chance for it to do so\\\"\\n\\n\\t^ self reformulateList! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 14:59'!\\nselectedClassName\\n\\t\\\"I may know what class is currently selected\\\"\\n\\n\\tself selectedClass ifNotNil: [^ self selectedClass name].\\n\\t^ nil! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:01'!\\nselectedClassOrMetaClass\\n\\n\\t^ self selectedClass\\t\\\"I don't know any better\\\"! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:22'!\\nselectedMessageName\\n\\n\\t^ nil! !\\n\\n!StringHolder methodsFor: 'accessing' stamp: 'di 11/23/1998 15:21'!\\ntextContents: aStringOrText \\n\\t\\\"Set aStringOrText to be the contents of the receiver.\\\"\\n\\n\\tcontents _ aStringOrText! !\\n\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'dgd 10/1/2004 13:43'!\\ncodePaneMenu: aMenu shifted: shifted \\n\\t\\\"Note that unless we override perform:orSendTo:, \\n\\tPluggableTextController will respond to all menu items in a \\n\\ttext pane\\\"\\n\\t| donorMenu |\\n\\tdonorMenu := shifted\\n\\t\\t\\t\\tifTrue: [ParagraphEditor shiftedYellowButtonMenu]\\n\\t\\t\\t\\tifFalse: [ParagraphEditor yellowButtonMenu].\\n\\t^ aMenu addAllFrom: donorMenu! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'wod 5/29/1998 16:35'!\\nperform: selector orSendTo: otherTarget\\n\\t\\\"Selector was just chosen from a menu by a user. If can respond, then\\nperform it on myself. If not, send it to otherTarget, presumably the\\neditPane from which the menu was invoked.\\\"\\n\\n\\t(self respondsTo: selector)\\n\\t\\tifTrue: [^ self perform: selector]\\n\\t\\tifFalse: [^ otherTarget perform: selector]! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'tk 4/6/98 11:43'!\\nshowBytecodes\\n\\t\\\"We don't know how to do this\\\"\\n\\n\\t^ self changed: #flash! !\\n\\n!StringHolder methodsFor: 'code pane menu' stamp: 'ar 9/27/2005 20:47'!\\nspawn: contentsString\\n\\n\\tUIManager default edit: contentsString label: 'Workspace'\\n! !\\n\\n\\n!StringHolder methodsFor: 'evaluation'!\\ndoItContext\\n\\t\\\"Answer the context in which a text selection can be evaluated.\\\"\\n\\n\\t^nil! !\\n\\n!StringHolder methodsFor: 'evaluation'!\\ndoItReceiver\\n\\t\\\"Answer the object that should be informed of the result of evaluating a \\n\\ttext selection.\\\"\\n\\n\\t^nil! !\\n\\n\\n!StringHolder methodsFor: 'initialize-release'!\\ndefaultContents\\n\\n\\t^''! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 10/16/1998 11:36'!\\nembeddedInMorphicWindowLabeled: labelString\\n\\t| window |\\n\\twindow _ (SystemWindow labelled: labelString) model: self.\\n\\twindow addMorph: (PluggableTextMorph on: self text: #contents accept: #acceptContents:\\n\\t\\t\\treadSelection: nil menu: #codePaneMenu:shifted:)\\n\\t\\tframe: (0@0 corner: 1@1).\\n\\t^ window! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'jm 3/24/98 17:56'!\\ninitialize\\n\\t\\\"Initialize the state of the receiver with its default contents.\\\"\\n\\n\\tcontents _ self defaultContents.\\n! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 10/16/1998 11:37'!\\nopenAsMorphLabel: labelString \\n\\t\\\"Workspace new openAsMorphLabel: 'Workspace'\\\"\\n\\t(self embeddedInMorphicWindowLabeled: labelString) openInWorld! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sw 12/22/1998 00:16'!\\nopenLabel: aString \\n\\t\\\"Create a standard system view of the model, me, a StringHolder and open it. If in mvc, terminate the active controller so that the new window will immediately be activated.\\\"\\n\\tself openLabel: aString andTerminate: true! !\\n\\n!StringHolder methodsFor: 'initialize-release' stamp: 'sma 4/30/2000 10:15'!\\nopenLabel: aString andTerminate: terminateBoolean\\n\\t\\\"Create a standard system view of the model, me, a StringHolder and open it.; do not terminate the active process if in mvc\\\"\\n\\t| topView codeView |\\n\\n\\tSmalltalk isMorphic ifTrue: [^ self openAsMorphLabel: aString].\\n\\n\\ttopView _ (StandardSystemView new) model: self.\\n\\ttopView borderWidth: 1.\\n\\ttopView label: aString.\\n\\ttopView minimumSize: 100 @ 50.\\n\\n\\tcodeView _ PluggableTextView on: self \\n\\t\\t\\ttext: #contents accept: #acceptContents:\\n\\t\\t\\treadSelection: #contentsSelection menu: #codePaneMenu:shifted:.\\n\\tcodeView window: (0@0 extent: 200@200).\\n\\ttopView addSubView: codeView.\\n\\t\\\"self contents size > 0 ifTrue: [\\n\\t\\t\\tcodeView hasUnacceptedEdits: true]. Is it already saved or not??\\\"\\n\\tterminateBoolean\\n\\t\\tifTrue:\\n\\t\\t\\t[topView controller open]\\n\\t\\tifFalse:\\n\\t\\t\\t[topView controller openNoTerminate]! !\\n\\n\\n!StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 21:25'!\\nwantsAnnotationPane\\n\\t\\\"Answer whether the receiver, seen in some browser window, would like to have the so-called annotationpane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary.\\\"\\n\\n\\t^ Preferences annotationPanes! !\\n\\n!StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 18:57'!\\nwantsOptionalButtons\\n\\t\\\"Answer whether the receiver, seen in some browser window, would like to have the so-called optional button pane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary.\\\"\\n\\n\\t^ Preferences optionalButtons! !\\n\\n\\n!StringHolder methodsFor: 'tiles' stamp: 'di 11/4/2000 11:07'!\\nopenSyntaxView\\n\\t\\\"Open a syntax view on the current method\\\"\\n\\n\\t| class selector |\\n\\n\\t(selector _ self selectedMessageName) ifNotNil: [\\n\\t\\tclass _ self selectedClassOrMetaClass.\\n\\t\\tSyntaxMorph testClass: class andMethod: selector.\\n\\t]! !\\n\\n\\n!StringHolder methodsFor: 'toolbuilder' stamp: 'ar 2/11/2005 20:36'!\\nbuildWith: builder\\n\\t| windowSpec textSpec |\\n\\twindowSpec := builder pluggableWindowSpec new.\\n\\twindowSpec model: self.\\n\\twindowSpec label: 'Workspace'.\\n\\twindowSpec children: OrderedCollection new.\\n\\ttextSpec := builder pluggableTextSpec new.\\n\\ttextSpec \\n\\t\\tmodel: self;\\n\\t\\tgetText: #contents; \\n\\t\\tsetText: #acceptContents:; \\n\\t\\tselection: nil; \\n\\t\\tmenu: #codePaneMenu:shifted:;\\n\\t\\tframe: (0@0corner: 1@1).\\n\\twindowSpec children add: textSpec.\\n\\n\\t^builder build: windowSpec! !\\n\\n\\n!StringHolder methodsFor: 'user edits' stamp: 'di 4/21/1998 11:30'!\\nclearUserEditFlag\\n\\t\\\"Clear the hasUnacceptedEdits flag in all my dependent views.\\\"\\n\\n\\tself changed: #clearUserEdits! !\\n\\n!StringHolder methodsFor: 'user edits' stamp: 'tk 4/13/1998 23:07'!\\nokToChange\\n\\n\\tself canDiscardEdits ifTrue: [^ true].\\n\\tself changed: #wantToChange. \\\"Solicit cancel from view\\\"\\n\\t^ self canDiscardEdits\\n! !\\n\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 3/15/2004 09:17'!\\ncodeTextMorph\\n\\t^ self dependents\\n\\t\\tdetect: [:dep | (dep isKindOf: PluggableTextMorph)\\n\\t\\t\\t\\tand: [dep getTextSelector == #contents]]\\n\\t\\tifNone: []! !\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 6/9/2005 10:47'!\\nrequestor\\n\\t^ (TextRequestor new) model: self; yourself! !\\n\\n!StringHolder methodsFor: '*services-base' stamp: 'rr 3/15/2004 09:17'!\\nselectedInterval\\n\\t^self codeTextMorph selectionInterval! !\\n\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseAllMessages\\n\\t\\\"Create and schedule a message set browser on all implementors of all the messages sent by the current method.\\\"\\n\\n\\t| aClass aName method filteredList |\\n\\t(aName := self selectedMessageName) ifNotNil: [\\n\\t\\tmethod := (aClass := self selectedClassOrMetaClass) compiledMethodAt: aName.\\n\\t\\tfilteredList := method messages reject: \\n\\t\\t\\t[:each | #(new initialize = ) includes: each].\\n\\t\\tself systemNavigation browseAllImplementorsOfList: filteredList asSortedCollection\\n\\t\\t\\t title: 'All messages sent in ', aClass name, '.', aName]\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/18/1998 16:11'!\\nbrowseClass\\n\\t\\\"Open an class browser on this class and method\\\"\\n\\n\\tself selectedClassOrMetaClass ifNotNil: [\\n\\t\\tBrowser newOnClass: self selectedClassOrMetaClass \\n\\t\\t\\tselector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 08:42'!\\nbrowseLocalImplementors\\n\\t\\\"Present a menu of all messages sent by the currently selected message. \\n\\tOpen a message set browser of all implementors of the message chosen in or below\\n\\tthe selected class.\\n\\tDo nothing if no message is chosen.\\\"\\n\\tself getSelectorAndSendQuery: #browseAllImplementorsOf:localTo:\\n\\t\\tto: self systemNavigation\\n\\t\\twith: { self selectedClass }! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 20:41'!\\nbrowseLocalSendersOfMessages\\n\\t\\\"Present a menu of the currently selected message, as well as all\\n\\tmessages sent by it. Open a message set browser of all implementors\\n\\tof the message chosen in or below the selected class\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllCallsOn:localTo:\\n\\t\\tto: self systemNavigation\\n\\t\\twith: { self selectedClass }! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 08:45'!\\nbrowseMessages\\n\\t\\\"Present a menu of all messages sent by the currently selected message. \\n\\tOpen a message set browser of all implementors of the message chosen.\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseMethodFull\\n\\t\\\"Create and schedule a full Browser and then select the current class and message.\\\"\\n\\n\\t| myClass |\\n\\t(myClass := self selectedClassOrMetaClass) ifNotNil:\\n\\t\\t[Browser fullOnClass: myClass selector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 4/16/2003 20:40'!\\nbrowseSendersOfMessages\\n\\t\\\"Present a menu of the currently selected message, as well as all messages sent by it. Open a message set browser of all senders of the selector chosen.\\\"\\n\\n\\tself getSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseUnusedMethods\\n\\t| classes unsent messageList cls |\\n\\t(cls := self selectedClass)\\n\\t\\tifNil: [^ self].\\n\\tclasses := Array with: cls with: cls class.\\n\\tunsent := Set new.\\n\\tclasses\\n\\t\\tdo: [:c | unsent addAll: c selectors].\\n\\tunsent := self systemNavigation allUnSentMessagesIn: unsent.\\n\\tmessageList := OrderedCollection new.\\n\\tclasses\\n\\t\\tdo: [:c | (c selectors\\n\\t\\t\\t\\tselect: [:s | unsent includes: s]) asSortedCollection\\n\\t\\t\\t\\tdo: [:sel | messageList add: c name , ' ' , sel]].\\n\\tself systemNavigation browseMessageList: messageList name: 'Unsent Methods in ' , cls name! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nbrowseVersions\\n\\t\\\"Create and schedule a Versions Browser, showing all versions of the \\n\\tcurrently selected message. Answer the browser or nil.\\\"\\n\\t| selector class | \\n\\tself classCommentIndicated\\n\\t\\tifTrue: [ ClassCommentVersionsBrowser browseCommentOf: self selectedClass.\\n\\t\\t\\t^nil ].\\n\\n\\t(selector := self selectedMessageName)\\n\\t\\tifNil:[ self inform: 'Sorry, only actual methods have retrievable versions.'. ^nil ]\\n\\t\\tifNotNil: [\\n\\t\\t\\tclass := self selectedClassOrMetaClass.\\n\\t\\t\\t^VersionsBrowser\\n\\t\\t\\t\\tbrowseVersionsOf: (class compiledMethodAt: selector)\\n\\t\\t\\t\\tclass: self selectedClass\\n\\t\\t\\t\\tmeta: class isMeta\\n\\t\\t\\t\\tcategory: (class organization categoryOfElement: selector)\\n\\t\\t\\t\\tselector: selector]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/28/1998 19:14'!\\nbuildMessageBrowser\\n\\t\\\"Create and schedule a message browser.\\\"\\n\\n\\tself selectedMessageName ifNil: [^ self].\\n\\tBrowser openMessageBrowserForClass: self selectedClassOrMetaClass \\n\\t\\tselector: self selectedMessageName editString: nil! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 1/16/2004 21:14'!\\nclassHierarchy\\n\\t\\\"Create and schedule a class list browser on the receiver's hierarchy.\\\"\\n\\n\\tself systemNavigation\\n\\t\\tspawnHierarchyForClass: self selectedClassOrMetaClass \\\"OK if nil\\\"\\n\\t\\tselector: self selectedMessageName\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 5/8/2000 02:16'!\\nclassListKey: aChar from: view \\n\\t\\\"Respond to a Command key. I am a model with a list of classes and a \\n\\tcode pane, and I also have a listView that has a list of methods. The \\n\\tview knows how to get the list and selection.\\\"\\n\\n\\taChar == $f ifTrue: [^ self findMethod].\\n\\taChar == $r ifTrue: [^ self recent].\\n\\taChar == $h ifTrue: [^ self spawnHierarchy].\\n\\taChar == $x ifTrue: [^ self removeClass].\\n\\t^ self messageListKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ncopyName\\n\\t\\\"Copy the current selector to the clipboard\\\"\\n\\t| selector |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[Clipboard clipboardText: selector asString asText]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ncopySelector\\n\\t\\\"Copy the selected selector to the clipboard\\\"\\n\\n\\t| selector |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[Clipboard clipboardText: selector asString]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 7/1/2001 08:24'!\\nfileOutMessage\\n\\t\\\"Put a description of the selected message on a file\\\"\\n\\n\\tself selectedMessageName ifNotNil:\\n\\t\\t[Cursor write showWhile:\\n\\t\\t\\t[self selectedClassOrMetaClass fileOutMethod: self selectedMessageName]]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nfindMethodInChangeSets\\n\\t\\\"Find and open a changeSet containing the current method.\\\"\\n\\n\\t| aName |\\n\\t(aName := self selectedMessageName) ifNotNil: [\\n\\t\\tChangeSorter browseChangeSetsWithClass: self selectedClassOrMetaClass\\n\\t\\t\\t\\t\\tselector: aName]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ninspectInstances\\n\\t\\\"Inspect all instances of the selected class.\\\"\\n\\n\\t| myClass |\\n\\t(myClass := self selectedClassOrMetaClass) ifNotNil:\\n\\t\\t[myClass theNonMetaClass inspectAllInstances]. \\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ninspectSubInstances\\n\\t\\\"Inspect all instances of the selected class and all its subclasses\\\"\\n\\n\\t| aClass |\\n\\t(aClass := self selectedClassOrMetaClass) ifNotNil: [\\n\\t\\taClass theNonMetaClass inspectSubInstances].\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmakeIsolatedCodePane\\n\\t| msgName |\\n\\n\\t(msgName := self selectedMessageName) ifNil: [^ Beeper beep].\\n\\tMethodHolder makeIsolatedCodePaneForClass: self selectedClassOrMetaClass selector: msgName! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmessageListKey: aChar from: view\\n\\t\\\"Respond to a Command key. I am a model with a code pane, and I also\\n\\thave a listView that has a list of methods. The view knows how to get\\n\\tthe list and selection.\\\"\\n\\n\\t| sel class |\\n\\taChar == $D ifTrue: [^ self toggleDiffing].\\n\\n\\tsel := self selectedMessageName.\\n\\taChar == $m ifTrue: \\\"These next two put up a type in if no message selected\\\"\\n\\t\\t[^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation].\\n\\taChar == $n ifTrue: \\n\\t\\t[^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation].\\n\\n\\t\\\"The following require a class selection\\\"\\n\\t(class := self selectedClassOrMetaClass) ifNil: [^ self arrowKey: aChar from: view].\\n\\taChar == $b ifTrue: [^ Browser fullOnClass: class selector: sel].\\n\\taChar == $N ifTrue: [^ self browseClassRefs].\\n\\taChar == $i ifTrue: [^ self methodHierarchy].\\n\\taChar == $h ifTrue: [^ self classHierarchy].\\n\\taChar == $p ifTrue: [^ self browseFullProtocol].\\n\\n\\t\\\"The following require a method selection\\\"\\n\\tsel ifNotNil: \\n\\t\\t[aChar == $o ifTrue: [^ self fileOutMessage].\\n\\t\\taChar == $c ifTrue: [^ self copySelector].\\n\\t\\taChar == $v ifTrue: [^ self browseVersions].\\n\\t\\taChar == $O ifTrue: [^ self openSingleMessageBrowser].\\n\\t\\taChar == $x ifTrue: [^ self removeMessage]].\\n\\n\\t^ self arrowKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nmessageListSelectorTitle\\n\\t| selector aString aStamp aSize |\\n\\n\\t(selector := self selectedMessageName)\\n\\t\\tifNil:\\n\\t\\t\\t[aSize := self messageList size.\\n\\t\\t\\t^ (aSize == 0 ifTrue: ['no'] ifFalse: [aSize printString]), ' message', (aSize == 1 ifTrue: [''] ifFalse: ['s'])]\\n\\t\\tifNotNil:\\n\\t\\t\\t[Preferences timeStampsInMenuTitles\\n\\t\\t\\t\\tifFalse:\\t[^ nil].\\n\\t\\t\\taString := selector truncateWithElipsisTo: 28.\\n\\t\\t\\t^ (aStamp := self timeStamp) size > 0\\n\\t\\t\\t\\tifTrue:\\n\\t\\t\\t\\t\\t[aString, String cr, aStamp]\\n\\t\\t\\t\\tifFalse:\\n\\t\\t\\t\\t\\t[aString]]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 1/16/2004 21:10'!\\nmethodHierarchy\\n\\t\\\"Create and schedule a method browser on the hierarchy of implementors.\\\"\\n\\n\\tself systemNavigation \\n\\t\\t\\tmethodHierarchyBrowserForClass: self selectedClassOrMetaClass \\n\\t\\t\\tselector: self selectedMessageName\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nofferDurableMenuFrom: menuRetriever shifted: aBoolean\\n\\t\\\"Pop up (morphic only) a menu whose target is the receiver and whose contents are provided by sending the menuRetriever to the receiver. The menuRetriever takes two arguments: a menu, and a boolean representing the shift state; put a stay-up item at the top of the menu.\\\"\\n\\n\\t| aMenu |\\n\\taMenu := MenuMorph new defaultTarget: self.\\n\\taMenu addStayUpItem.\\n\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\taMenu popUpInWorld! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nofferMenuFrom: menuRetriever shifted: aBoolean\\n\\t\\\"Pop up, in morphic or mvc as the case may be, a menu whose target is the receiver and whose contents are provided by sending the menuRetriever to the receiver. The menuRetriever takes two arguments: a menu, and a boolean representing the shift state.\\\"\\n\\n\\t| aMenu |\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue:\\n\\t\\t\\t[aMenu := MenuMorph new defaultTarget: self.\\n\\t\\t\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\t\\taMenu popUpInWorld]\\n\\t\\tifFalse:\\n\\t\\t\\t[aMenu := CustomMenu new.\\n\\t\\t\\tself perform: menuRetriever with: aMenu with: aBoolean.\\n\\t\\t\\taMenu invokeOn: self]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nopenSingleMessageBrowser\\n\\t| msgName mr |\\n\\t\\\"Create and schedule a message list browser populated only by the currently selected message\\\"\\n\\n\\t(msgName := self selectedMessageName) ifNil: [^ self].\\n\\n\\tmr := MethodReference new\\n\\t\\tsetStandardClass: self selectedClassOrMetaClass\\n\\t\\tmethodSymbol: msgName.\\n\\n\\tself systemNavigation \\n\\t\\tbrowseMessageList: (Array with: mr)\\n\\t\\tname: mr asStringOrText\\n\\t\\tautoSelect: nil! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'RAA 12/10/1999 09:36'!\\npackageListKey: aChar from: view\\n\\t\\\"Respond to a Command key in the package pane in the PackageBrowser\\\"\\n\\taChar == $f ifTrue: [^ self findClass].\\n\\t^ self classListKey: aChar from: view\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'tk 4/28/1998 18:16'!\\nprintOutMessage\\n\\t\\\"Write a file with the text of the selected message, for printing by a web browser\\\"\\n\\n\\tself selectedMessageName ifNotNil: [\\n\\t\\tself selectedClassOrMetaClass fileOutMethod: self selectedMessageName\\n\\t\\t\\t\\t\\t\\t\\tasHtml: true]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 5/23/2003 14:42'!\\nremoveFromCurrentChanges\\n\\t\\\"Tell the changes mgr to forget that the current msg was changed.\\\"\\n\\n\\tChangeSet current removeSelectorChanges: self selectedMessageName \\n\\t\\t\\tclass: self selectedClassOrMetaClass.\\n\\tself changed: #annotation! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sw 1/28/1999 12:34'!\\nrevertAndForget\\n\\t\\\"Revert to the previous version of the current method, and tell the changes mgr to forget that it was ever changed. Danger!! Use only if you really know what you're doing!!\\\"\\n\\n\\tself okToChange ifFalse: [^ self].\\n\\tself revertToPreviousVersion.\\n\\tself removeFromCurrentChanges.\\n\\tself contentsChanged\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nrevertToPreviousVersion\\n\\t\\\"Revert to the previous version of the current method\\\"\\n\\t| aClass aSelector changeRecords |\\n\\tself okToChange ifFalse: [^ self].\\n\\taClass := self selectedClassOrMetaClass.\\n\\taClass ifNil: [^ self changed: #flash].\\n\\taSelector := self selectedMessageName.\\n\\tchangeRecords := aClass changeRecordsAt: aSelector.\\n\\t(changeRecords == nil or: [changeRecords size <= 1]) ifTrue: [self changed: #flash. ^ Beeper beep].\\n\\tchangeRecords second fileIn.\\n\\tself contentsChanged\\n! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nselectMessageAndEvaluate: aBlock\\n\\t\\\"Allow the user to choose one selector, chosen from the currently selected message's selector, as well as those of all messages sent by it, and evaluate aBlock on behalf of chosen selector. If there is only one possible choice, simply make it; if there are multiple choices, put up a menu, and evaluate aBlock on behalf of the the chosen selector, doing nothing if the user declines to choose any\\\"\\n\\n\\t| selector method messages |\\n\\t(selector := self selectedMessageName) ifNil: [^ self].\\n\\tmethod := (self selectedClassOrMetaClass ifNil: [^ self])\\n\\t\\tcompiledMethodAt: selector\\n\\t\\tifAbsent: [].\\n\\t(method isNil or: [(messages := method messages) size == 0])\\n\\t\\t ifTrue: [^ aBlock value: selector].\\n\\t(messages size == 1 and: [messages includes: selector])\\n\\t\\tifTrue:\\n\\t\\t\\t[^ aBlock value: selector]. \\\"If only one item, there is no choice\\\"\\n\\n\\tself systemNavigation \\n\\t\\tshowMenuOf: messages\\n\\t\\twithFirstItem: selector\\n\\t\\tifChosenDo: [:sel | aBlock value: sel]! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'nk 11/15/2002 12:23'!\\nsystemCatListKey: aChar from: view\\n\\t\\\"Respond to a Command key. I am a model with a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection.\\\"\\n\\n\\taChar == $f ifTrue: [^ self findClass].\\n\\taChar == $x ifTrue: [^ self removeSystemCategory].\\n\\t^ self classListKey: aChar from: view! !\\n\\n!StringHolder methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\ntimeStamp\\n\\t\\\"Answer the time stamp for the chosen class and method, if any, else an empty string\\\"\\n\\n\\t| selector aMethod |\\n\\t(selector := self selectedMessageName) ifNotNil:\\n\\t\\t[self selectedClassOrMetaClass \\n\\t\\t\\tifNil:\\n\\t\\t\\t\\t[^ String new]\\n\\t\\t\\tifNotNil:\\n\\t\\t\\t\\t[aMethod := self selectedClassOrMetaClass compiledMethodAt: selector ifAbsent: [nil].\\n\\t\\t\\t\\taMethod ifNotNil: [^ Utilities timeStampForMethod: aMethod]]].\\n\\t^ String new! !\\n\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:22'!\\nbrowseClassRefs\\n\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseAllCallsOnClass: cls theNonMetaClass]\\n! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:22'!\\nbrowseClassVariables\\n\\t\\\"Browse the class variables of the selected class. 2/5/96 sw\\\"\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseClassVariables: cls]\\n! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:23'!\\nbrowseClassVarRefs\\n\\t\\\"1/17/96 sw: devolve responsibility to the class, so that the code that does the real work can be shared\\\"\\n\\n\\t| cls |\\n\\tcls := self selectedClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseClassVarRefs: cls]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:23'!\\nbrowseFullProtocol\\n\\t\\\"Open up a protocol-category browser on the value of the receiver's current selection. If in mvc, an old-style protocol browser is opened instead. Someone who still uses mvc might wish to make the protocol-category-browser work there too, thanks.\\\"\\n\\n\\t| aClass |\\n\\n\\t(Smalltalk isMorphic and: [Smalltalk includesKey: #Lexicon]) ifFalse: [^ self spawnFullProtocol].\\n\\t((aClass := self selectedClassOrMetaClass) notNil and: [aClass isTrait not]) ifTrue:\\n\\t\\t[(Smalltalk at: #Lexicon) new openOnClass: aClass inWorld: ActiveWorld showingSelector: self selectedMessageName]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:24'!\\nbrowseInstVarDefs \\n\\n\\t| cls |\\n\\tcls := self selectedClassOrMetaClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseInstVarDefs: cls]! !\\n\\n!StringHolder methodsFor: '*Tools-traits' stamp: 'al 12/6/2005 22:24'!\\nbrowseInstVarRefs\\n\\t\\\"1/26/96 sw: real work moved to class, so it can be shared\\\"\\n\\t| cls |\\n\\tcls := self selectedClassOrMetaClass.\\n\\t(cls notNil and: [cls isTrait not])\\n\\t\\tifTrue: [self systemNavigation browseInstVarRefs: cls]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringHolder class\\n\\tinstanceVariableNames: ''!\\n\\n!StringHolder class methodsFor: 'class initialization'!\\ninitialize\\n\\t\\\"The class variables were initialized once, and subsequently filled with\\n\\tinformation. Re-executing this method is therefore dangerous.\\\" \\n\\t \\n\\t\\\"workSpace _ StringHolder new\\\"\\n\\n\\t\\\"StringHolder initialize\\\"! !\\n\\n\\n!StringHolder class methodsFor: 'instance creation' stamp: 'ar 9/27/2005 20:48'!\\nopen\\n\\t(Smalltalk at: #Workspace ifAbsent:[self]) new openLabel: 'Workspace'\\n\\t\\t\\\"Not to be confused with our own class var 'Workspace'\\\"! !\\n\\n!StringHolder class methodsFor: 'instance creation' stamp: 'tk 5/4/1998 16:41'!\\nopenLabel: aString\\n\\n\\tself new openLabel: aString! !\\n\\n\\n!StringHolder class methodsFor: 'window color' stamp: 'sw 2/26/2002 14:44'!\\nwindowColorSpecification\\n\\t\\\"Answer a WindowColorSpec object that declares my preference\\\"\\n\\n\\t^ WindowColorSpec classSymbol: self name wording: 'Workspace' brightColor: #lightYellow pastelColor: #paleYellow helpMessage: 'A place for text in a window.'! !\\nParagraphEditor subclass: #StringHolderController\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'CodeYellowButtonMenu CodeYellowButtonMessages'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StringHolderController commentStamp: '<historical>' prior: 0!\\nI 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.\\n\\tdoIt\\tevaluate the text selection as an expression\\n\\tprintIt\\tsame as doIt but insert a description of the result after the selection\\n\\taccept\\tstore the contents of the StringHolder into the model\\n\\tcancel\\tstore the contents of the model into the StringHolder!\\n\\n\\n!StringHolderController methodsFor: 'accessing' stamp: 'di 6/21/2001 10:32'!\\nchangeText: aText\\n\\t\\\"The paragraph to be edited is changed to aText.\\\"\\n\\tparagraph text: aText.\\n\\tself resetState.\\n\\tself selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size.\\n\\tself selectAndScroll.\\n\\tself deselect! !\\n\\n!StringHolderController methodsFor: 'accessing'!\\nmodel: aModel\\n\\n\\tsuper model: aModel.\\n\\tview displayContents == nil\\n\\t\\tifFalse: [self changeParagraph: view displayContents]! !\\n\\n\\n!StringHolderController methodsFor: 'compiler access'!\\nbindingOf: aString\\n\\t^model bindingOf: aString! !\\n\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'di 10/9/1998 15:41'!\\nhasUnacceptedEdits: aBoolean\\n\\t^ view hasUnacceptedEdits: aBoolean! !\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:09'!\\nuserHasEdited\\n\\t\\\"Note that the user has edited my text.\\\"\\n\\n\\tview hasUnacceptedEdits: true\\n! !\\n\\n!StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:08'!\\nuserHasNotEdited\\n\\t\\\"Note that my text is free of user edits.\\\"\\n\\n\\tmodel clearUserEditFlag\\n! !\\n\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:53'!\\naccept \\n\\t\\\"Refer to the comment in ParagraphEditor|accept.\\\"\\n\\n\\tsuper accept.\\n\\tmodel contents: paragraph string.\\n\\tself userHasNotEdited.\\n! !\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:54'!\\ncancel \\n\\t\\\"Refer to the comment in ParagraphEditor|cancel.\\\"\\n\\n\\tsuper cancel.\\n\\tself userHasNotEdited.\\n! !\\n\\n!StringHolderController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:14'!\\nperformMenuMessage: aSelector\\n\\t\\\"Intercept #again so the model does not get locked by keying the search text.\\\"\\n\\n\\t| hadEdits |\\n\\thadEdits _ view canDiscardEdits not.\\n\\tsuper performMenuMessage: aSelector.\\n\\t(hadEdits not and:\\n\\t [aSelector == #again and:\\n\\t [(UndoMessage sends: #undoAgain:andReselect:typedKey:) and:\\n\\t [UndoMessage arguments at: 3]]])\\n\\t\\tifTrue: [self userHasNotEdited].\\n! !\\n\\n\\n!StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:43'!\\ncloseTypeIn\\n\\t\\\"Note edit if something actually was typed.\\\"\\n\\n\\tbeginTypeInBlock ~~ nil ifTrue: [self userHasEdited].\\n\\tsuper closeTypeIn.\\n! !\\n\\n!StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:45'!\\nzapSelectionWith: aText\\n\\t\\\"Note edit except during typeIn, which notes edits at close.\\\"\\n\\n\\tsuper zapSelectionWith: aText.\\n\\tbeginTypeInBlock == nil ifTrue: [self userHasEdited].\\n! !\\nView subclass: #StringHolderView\\n\\tinstanceVariableNames: 'displayContents hasUnacceptedEdits askBeforeDiscardingEdits'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Support'!\\n!StringHolderView commentStamp: '<historical>' prior: 0!\\nI 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.!\\n\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndefaultController \\n\\t\\\"Refer to the comment in View|defaultController.\\\"\\n\\n\\t^self defaultControllerClass newParagraph: displayContents! !\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndefaultControllerClass \\n\\t\\\"Refer to the comment in View|defaultControllerClass.\\\"\\n\\n\\t^StringHolderController! !\\n\\n!StringHolderView methodsFor: 'controller access'!\\ndisplayContents\\n\\n\\t^displayContents! !\\n\\n\\n!StringHolderView methodsFor: 'deEmphasizing'!\\ndeEmphasizeView \\n\\t\\\"Refer to the comment in View|deEmphasizeView.\\\"\\n\\n\\t(self controller isKindOf: ParagraphEditor)\\n\\t \\tifTrue: [controller deselect]! !\\n\\n\\n!StringHolderView methodsFor: 'displaying'!\\ndisplay \\n\\t\\\"Refer to the comment in View.display.\\\"\\n\\t(self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])\\n\\t\\tifTrue: \\\"Recompose the text if the window changed\\\"\\n\\t\\t\\t\\t[self positionDisplayContents. \\n\\t\\t\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\t\\t\\tifTrue: [controller recomputeSelection]].\\n\\tsuper display! !\\n\\n!StringHolderView methodsFor: 'displaying' stamp: 'hmm 6/18/2000 19:24'!\\ndisplayView \\n\\t\\\"Refer to the comment in View|displayView.\\\"\\n\\n\\tDisplay deferUpdatesIn: self displayBox while: [\\n\\t\\tself clearInside.\\n\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\tifTrue: [controller display]\\n\\t\\t\\tifFalse: [displayContents display]]! !\\n\\n!StringHolderView methodsFor: 'displaying'!\\nlock\\n\\t\\\"Refer to the comment in view|lock. Must do at least what display would do to lock the view.\\\"\\n\\t(self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])\\n\\t\\tifTrue: \\\"Recompose the text if the window changed\\\"\\n\\t\\t\\t\\t[self positionDisplayContents. \\n\\t\\t\\t\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\t\\t\\t\\tifTrue: [controller recomputeSelection]].\\n\\tsuper lock! !\\n\\n!StringHolderView methodsFor: 'displaying'!\\npositionDisplayContents\\n\\t\\\"Presumably the text being displayed changed so that the wrapping box \\n\\tand clipping box should be reset.\\\"\\n\\n\\tdisplayContents \\n\\t\\twrappingBox: (self insetDisplayBox insetBy: 6 @ 0)\\n\\t\\tclippingBox: self insetDisplayBox! !\\n\\n\\n!StringHolderView methodsFor: 'initialize-release' stamp: 'jm 3/24/98 14:39'!\\ninitialize \\n\\t\\\"Refer to the comment in View|initialize.\\\"\\n\\n\\tsuper initialize.\\n\\tdisplayContents _ '' asParagraph.\\n\\thasUnacceptedEdits _ false.\\n\\taskBeforeDiscardingEdits _ true.\\n! !\\n\\n\\n!StringHolderView methodsFor: 'model access'!\\neditString: aString \\n\\t\\\"The paragraph to be displayed is created from the characters in aString.\\\"\\n\\n\\tdisplayContents _ Paragraph withText: aString asText\\n\\t\\tstyle: TextStyle default copy\\n\\t\\tcompositionRectangle: (self insetDisplayBox insetBy: 6 @ 0)\\n\\t\\tclippingRectangle: self insetDisplayBox\\n\\t\\tforeColor: self foregroundColor backColor: self backgroundColor.\\n\\t(self controller isKindOf: ParagraphEditor)\\n\\t\\tifTrue: [controller changeParagraph: displayContents]! !\\n\\n!StringHolderView methodsFor: 'model access' stamp: 'sma 5/28/2000 23:25'!\\ngetMenu: shiftKeyState\\n\\t^ nil! !\\n\\n!StringHolderView methodsFor: 'model access'!\\nmodel: aLockedModel \\n\\t\\\"Refer to the comment in View|model:.\\\"\\n \\n\\tsuper model: aLockedModel.\\n\\tself editString: model contents! !\\n\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 14:38'!\\naskBeforeDiscardingEdits: aBoolean\\n\\t\\\"Set the flag that determines whether the user should be asked before discarding unaccepted edits.\\\"\\n\\n\\taskBeforeDiscardingEdits _ aBoolean.\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 22:58'!\\ncanDiscardEdits\\n\\t\\\"Return true if this view either has no text changes or does not care.\\\"\\n\\n\\t^ (hasUnacceptedEdits & askBeforeDiscardingEdits) not\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 17:49'!\\nhasUnacceptedEdits\\n\\t\\\"Return true if this view has unaccepted edits.\\\"\\n\\n\\t^ hasUnacceptedEdits\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 17:17'!\\nhasUnacceptedEdits: aBoolean\\n\\t\\\"Set the hasUnacceptedEdits flag to the given value.\\\"\\n\\n\\thasUnacceptedEdits _ aBoolean.\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'dgd 9/21/2003 17:42'!\\npromptForCancel\\n\\t\\\"Ask if it is OK to cancel changes to text\\\"\\n\\t| okToCancel stripes |\\n\\tself topView isCollapsed ifTrue:\\n\\t\\t[(self confirm: 'Changes have not been saved.\\nIs it OK to cancel those changes?' translated) ifTrue: [model clearUserEditFlag].\\n\\t\\t^ self].\\n\\tstripes _ (Form extent: 16@16 fromStipple: 16r36C9) bits.\\n\\tDisplay border: self insetDisplayBox width: 4\\n\\t\\t\\trule: Form reverse fillColor: stripes.\\n\\tokToCancel _ self confirm: 'Changes have not been saved.\\nIs it OK to cancel those changes?' translated.\\n\\tDisplay border: self insetDisplayBox width: 4\\n\\t\\t\\trule: Form reverse fillColor: stripes.\\n\\tokToCancel ifTrue:\\n\\t\\t[self updateDisplayContents.\\n\\t\\tmodel clearUserEditFlag].\\n! !\\n\\n!StringHolderView methodsFor: 'updating' stamp: 'di 4/21/1998 11:30'!\\nupdate: aSymbol\\n\\t\\\"Refer to the comment in View|update:.\\\"\\n\\taSymbol == #wantToChange ifTrue: [^ self promptForCancel].\\n\\taSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false].\\n\\taSymbol == #flash ifTrue: [^ controller flash].\\n\\tself updateDisplayContents! !\\n\\n!StringHolderView methodsFor: 'updating'!\\nupdateDisplayContents\\n\\t\\\"Make the text that is displayed be the contents of the receiver's model.\\\"\\n\\n\\tself editString: model contents.\\n\\tself displayView! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringHolderView class\\n\\tinstanceVariableNames: ''!\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\ncontainer\\n\\t\\\"Answer an instance of me with a new instance of StringHolder as the \\n\\tmodel.\\\"\\n\\n\\t^self container: StringHolder new! !\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\ncontainer: aContainer \\n\\t\\\"Answer an instance of me whose model is aContainer. Give it a 2-dot \\n\\tborder.\\\"\\n\\n\\t| aCodeView |\\n\\taCodeView _ self new model: aContainer.\\n\\taCodeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.\\n\\t^aCodeView! !\\n\\n!StringHolderView class methodsFor: 'instance creation' stamp: 'ar 9/27/2005 20:48'!\\nopen\\n\\t\\\"Create a standard system view of a workspace on the screen.\\\"\\n\\n\\tself open: StringHolder new label: 'Workspace'! !\\n\\n!StringHolderView class methodsFor: 'instance creation'!\\nopen: aStringHolder \\n\\t\\\"Create a standard system view of the argument, aStringHolder, as viewed \\n\\tby an instance of me. The view has label 'StringHolder'.\\\"\\n\\n\\tself open: aStringHolder label: 'StringHolder'! !\\n\\n!StringHolderView class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:15'!\\nopen: aStringHolder label: labelString \\n\\t\\\"NOTE this should be in the model class, and all senders so redirected,\\n\\tin order that the view class can be discarded in a morphic world.\\\"\\n\\n\\t\\\"Create a standard system view of the model, aStringHolder, as viewed by \\n\\tan instance of me. The label of the view is aString.\\\"\\n\\t| aStringHolderView topView |\\n\\n\\tSmalltalk isMorphic ifTrue: [^ aStringHolder openAsMorphLabel: labelString].\\n\\n\\taStringHolderView _ self container: aStringHolder.\\n\\ttopView _ StandardSystemView new.\\n\\ttopView model: aStringHolderView model.\\n\\ttopView addSubView: aStringHolderView.\\n\\ttopView label: labelString.\\n\\ttopView minimumSize: 100 @ 50.\\n\\ttopView controller open! !\\nMorph subclass: #StringMorph\\n\\tinstanceVariableNames: 'font emphasis contents hasFocus'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Basic'!\\n!StringMorph commentStamp: 'efc 3/7/2003 17:34' prior: 0!\\nStringMorph is a \\\"lightweight\\\" Morph to display a String. It supports only a single font, color, and emphasis combination. For multiple text styles, use TextMorph.\\n\\nStructure:\\ninstance var \\tType Description \\nfont \\t\\t\\tStrikeFont \\t\\t(normally nil; then the accessor #font gives back TextStyle \\n\\t\\t\\t\\tor nil\\t\\t\\tdefaultFont) \\nemphasis \\t\\tSmallInteger\\tbitmask determining character attributes (underline, bold, \\t\\t\\t\\t\\t\\t\\t\\titalics, narrow, struckout) \\ncontents \\t\\tString \\t\\t\\tThe text that will be displayed. \\nhasFocus \\t\\tBoolean \\t\\tDo I have the keyboard focus or not? \\n\\nIf you shift-click on a StringMorph you can edit its string. This is accomplished the following way: StringMorph can launch a StringMorphEditor if it receives a #mouseDown event.\\n\\nA StringMorph may also be used like a SimpleButtonMorph to do an action when clicked. Use the menu 'extras' / 'add mouseUpAction'.\\n\\nThe following propery will be defined:\\naStringMorph valueOfProperty: #mouseUpCodeToRun!\\n]style[(11 20 5 14 6 97 9 14 47 9 10 53 9 40 12 108 6 49 7 168 17 75 17 163)f1LStringMorph Hierarchy;,f1,f1LMorph Comment;,f1,f1LString Comment;,f1,f1LTextMorph Comment;,f1,f1i,f1,f1LStrikeFont Comment;,f1,f1LTextStyle Comment;,f1,f1LSmallInteger Comment;,f1,f1LString Comment;,f1,f1LBoolean Comment;,f1,f1LStringMorphEditor Comment;,f1,f1LSimpleButtonMorph Comment;,f1!\\n\\n\\n!StringMorph methodsFor: 'accessing'!\\ncontents\\n\\n\\t^ contents! !\\n\\n!StringMorph methodsFor: 'accessing'!\\ncontentsClipped: aString\\n\\t\\\"Change my text, but do not change my size as a result\\\"\\n\\tcontents = aString ifTrue: [^ self]. \\\"No substantive change\\\"\\n\\tcontents _ aString.\\n\\tself changed! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:15'!\\ncontents: newContents \\n\\t| scanner |\\n\\tcontents := newContents isText\\n\\t\\t\\t\\tifTrue: [scanner := StringMorphAttributeScanner new initializeFromStringMorph: self.\\n\\t\\t\\t\\t\\t(newContents attributesAt: 1 forStyle: self font textStyle)\\n\\t\\t\\t\\t\\t\\tdo: [:attr | attr emphasizeScanner: scanner].\\n\\t\\t\\t\\t\\temphasis := scanner emphasis.\\n\\t\\t\\t\\t\\tfont := scanner font emphasis: emphasis.\\n\\t\\t\\t\\t\\tcolor := scanner textColor.\\n\\t\\t\\t\\t\\tnewContents string]\\n\\t\\t\\t\\tifFalse: [contents = newContents\\n\\t\\t\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t\\t\\t\\\"no substantive change\\\"\\n\\t\\t\\t\\t\\tnewContents].\\n\\tself fitContents! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 12/12/2001 02:44'!\\nfitContents\\n\\n\\t| newBounds boundsChanged |\\n\\tnewBounds _ self measureContents.\\n\\tboundsChanged _ bounds extent ~= newBounds.\\n\\tself extent: newBounds.\\t\\t\\\"default short-circuits if bounds not changed\\\"\\n\\tboundsChanged ifFalse: [self changed]! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 1/31/2001 19:33'!\\nfont\\n\\t\\\"who came up with #fontToUse rather than font?!!\\\"\\n\\t^self fontToUse! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'tk 8/28/2000 13:59'!\\nfontName: fontName size: fontSize\\n\\n\\t^ self font: (StrikeFont familyName: fontName size: fontSize) \\n\\t\\t\\temphasis: 0! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'dgd 2/21/2003 23:07'!\\nfontToUse\\n\\t| fontToUse |\\n\\tfontToUse := font isNil ifTrue: [TextStyle defaultFont] ifFalse: [font].\\n\\t(emphasis isNil or: [emphasis = 0]) \\n\\t\\tifTrue: [^fontToUse]\\n\\t\\tifFalse: [^fontToUse emphasized: emphasis]! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'di 4/2/1999 16:11'!\\nfont: aFont emphasis: emphasisCode\\n\\tfont _ aFont.\\n\\temphasis _ emphasisCode.\\n\\tself fitContents.\\n\\\"\\nin inspector say,\\n\\t self font: (TextStyle default fontAt: 2) emphasis: 1\\n\\\"! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/8/1999 11:10'!\\ninterimContents: aString\\n\\t\\\"The receiver is under edit and aString represents the string the user sees as she edits, which typically will not have been accepted and indeed may be abandoned\\\"\\n\\n\\tself contents: aString! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'ar 12/30/2001 20:45'!\\nmeasureContents\\n\\t| f |\\n\\tf _ self fontToUse.\\n\\t^(((f widthOfString: contents) max: self minimumWidth) @ f height).! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/8/1999 13:44'!\\nminimumWidth\\n\\t\\\"Answer the minimum width that the receiver can have. A nonzero value here keeps the receiver from degenerating into something that cannot ever be seen or touched again!! Obeyed by fitContents.\\\"\\n\\n\\t^ 3! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 12/6/1999 13:16'!\\nsetWidth: width\\n\\n\\tself extent: width @ (font ifNil: [TextStyle defaultFont]) height! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'tk 12/16/1998 11:55'!\\nuserString\\n\\t\\\"Do I have a text string to be searched on?\\\"\\n\\n\\t^ contents! !\\n\\n!StringMorph methodsFor: 'accessing' stamp: 'sw 9/16/1999 22:57'!\\nvalueFromContents\\n\\t\\\"Return a new value from the current contents string.\\\"\\n\\t^ contents! !\\n\\n\\n!StringMorph methodsFor: 'connectors-layout' stamp: 'dgd 2/16/2003 21:52'!\\nminHeight\\n\\\"answer the receiver's minHeight\\\"\\n\\t^ self fontToUse height! !\\n\\n\\n!StringMorph methodsFor: 'drawing' stamp: 'ar 12/31/2001 02:38'!\\ndrawOn: aCanvas\\n\\n\\taCanvas drawString: contents in: bounds font: self fontToUse color: color.! !\\n\\n!StringMorph methodsFor: 'drawing' stamp: 'tk 8/1/2001 14:15'!\\nlookTranslucent\\n\\n\\t\\\"keep the text the same color (black)\\\"! !\\n\\n\\n!StringMorph methodsFor: 'editing'!\\nacceptContents\\n\\t\\\"The message is sent when the user hits enter or Cmd-S. Accept the current contents and end editing. This default implementation does nothing.\\\"\\n! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/8/1999 17:04'!\\nacceptValue: aValue\\n\\t| val |\\n\\tself contents: (val _ aValue asString).\\n\\t^ val! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/17/1999 13:27'!\\ncancelEdits\\n\\n\\tself doneWithEdits! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'di 9/6/1999 22:44'!\\ndoneWithEdits\\n\\n\\thasFocus _ false! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'nk 2/24/2005 20:11'!\\nlaunchMiniEditor: evt\\n\\n\\t| textMorph |\\n\\thasFocus _ true. \\\"Really only means edit in progress for this morph\\\"\\n\\ttextMorph _ StringMorphEditor new contentsAsIs: contents.\\n\\ttextMorph beAllFont: self fontToUse.\\n\\ttextMorph bounds: (self bounds expandBy: 0@2).\\n\\tself addMorphFront: textMorph.\\n\\tevt hand newKeyboardFocus: textMorph.\\n\\ttextMorph editor selectFrom: 1 to: textMorph paragraph text string size! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 9/8/1999 10:42'!\\nlostFocusWithoutAccepting\\n\\t\\\"The message is sent when the user, having been in an editing episode on the receiver, changes the keyboard focus -- typically by clicking on some editable text somewhere else -- without having accepted the current edits.\\\"\\n\\n\\tself acceptContents! !\\n\\n!StringMorph methodsFor: 'editing' stamp: 'sw 7/21/1999 14:59'!\\nwantsKeyboardFocusOnShiftClick\\n\\t^ owner topRendererOrSelf wantsKeyboardFocusFor: self\\n! !\\n\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'ar 10/6/2000 00:16'!\\nhandlesMouseDown: evt\\n\\t^ (evt shiftPressed and: [self wantsKeyboardFocusOnShiftClick])\\n\\t\\tifTrue: [true]\\n\\t\\tifFalse: [super handlesMouseDown: evt].\\n! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'sw 9/8/1999 11:26'!\\nhasFocus\\n\\t^ hasFocus! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'di 9/5/1999 17:25'!\\nmouseDown: evt\\n\\t\\\"If the shift key is pressed, make this string the keyboard input focus.\\\"\\n\\n\\t(evt shiftPressed and: [self wantsKeyboardFocusOnShiftClick])\\n\\t\\tifTrue: [self launchMiniEditor: evt]\\n\\t\\tifFalse: [super mouseDown: evt].\\n! !\\n\\n!StringMorph methodsFor: 'event handling' stamp: 'sw 5/6/1998 15:45'!\\nwouldAcceptKeyboardFocus\\n\\t^ self isLocked not! !\\n\\n\\n!StringMorph methodsFor: 'font' stamp: 'efc 2/22/2003 21:35'!\\nemphasis: aNumber\\n\\t\\\"Set the receiver's emphasis as indicated. aNumber is a bitmask with the following format:\\n\\n\\tbit\\tattribute\\n\\t1\\tbold\\n\\t2\\titalic\\n\\t4\\tunderlined\\n\\t8\\tnarrow\\n\\t16\\tstruckOut\\\"\\n\\n\\t\\\"examples: 0 -> plain. \\n\\t1 -> bold. 2 -> italic. 3 -> bold italic. 4 -> underlined \\n\\t5 -> bold underlined. 6 -> italic underlined. 7 -> bold italic underlined \\n\\tetc...\\\"\\n\\n\\temphasis _ aNumber.\\n\\t^ self font: font emphasis: emphasis! !\\n\\n\\n!StringMorph methodsFor: 'halos and balloon help' stamp: 'sw 6/15/1998 15:34'!\\naddOptionalHandlesTo: aHalo box: box\\n\\tself flag: #deferred.\\n\\n\\t\\\"Eventually...\\n\\tself addFontHandlesTo: aHalo box: box\\\"! !\\n\\n!StringMorph methodsFor: 'halos and balloon help' stamp: 'sw 6/6/2001 13:34'!\\nboundsForBalloon\\n\\t\\\"Some morphs have bounds that are way too big. This is a contorted way of making things work okay in PluggableListMorphs, whose list elements historically have huge widths\\\"\\n\\n\\t| ownerOwner |\\n\\t^ ((owner notNil and: [(ownerOwner _ owner owner) notNil]) and:\\n\\t\\t\\t[ownerOwner isKindOf: PluggableListMorph])\\n\\t\\tifTrue:\\n\\t\\t\\t[self boundsInWorld intersect: ownerOwner boundsInWorld]\\n\\t\\tifFalse:\\n\\t\\t\\t[super boundsForBalloon]! !\\n\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 22:31'!\\ndefaultColor\\n\\t\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 20:42'!\\ninitialize\\n\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\\"\\\"\\n\\tfont _ nil.\\n\\temphasis _ 0.\\n\\thasFocus _ false! !\\n\\n!StringMorph methodsFor: 'initialization' stamp: 'dgd 2/14/2003 21:57'!\\ninitWithContents: aString font: aFont emphasis: emphasisCode \\n\\tsuper initialize.\\n\\t\\n\\tfont _ aFont.\\n\\temphasis _ emphasisCode.\\n\\thasFocus _ false.\\n\\tself contents: aString! !\\n\\n\\n!StringMorph methodsFor: 'layout' stamp: 'nk 5/11/2001 09:33'!\\nfullBounds\\n\\tself contents ifNil: [ self contents: 'String Morph' ].\\n\\t^super fullBounds! !\\n\\n\\n!StringMorph methodsFor: 'menu' stamp: 'dgd 8/30/2003 22:17'!\\naddCustomMenuItems: aCustomMenu hand: aHandMorph\\n\\n\\tsuper addCustomMenuItems: aCustomMenu hand: aHandMorph.\\n\\taCustomMenu add: 'change font' translated action: #changeFont.\\n\\taCustomMenu add: 'change emphasis' translated action: #changeEmphasis.\\n! !\\n\\n!StringMorph methodsFor: 'menu' stamp: 'yo 3/14/2005 13:03'!\\nchangeEmphasis\\n\\n\\t| reply aList |\\n\\taList _ #(normal bold italic narrow underlined struckOut).\\n\\treply _ (SelectionMenu labelList: (aList collect: [:t | t translated]) selections: aList) startUp.\\n\\treply ifNotNil:[\\n\\t\\tself emphasis: (TextEmphasis perform: reply) emphasisCode.\\n\\t].\\n! !\\n\\n!StringMorph methodsFor: 'menu' stamp: 'ar 1/5/2002 21:45'!\\nchangeFont\\n\\t| newFont |\\n\\tnewFont _ StrikeFont fromUser: self fontToUse.\\n\\tnewFont ifNotNil:[self font: newFont].! !\\n\\n\\n!StringMorph methodsFor: 'objects from disk' stamp: 'tk 11/29/2004 16:52'!\\nfixUponLoad: aProject seg: anImageSegment\\n\\n\\t\\\"We are in an old project that is being loaded from disk.\\n\\nFix up conventions that have changed.\\\"\\n\\n\\n\\n\\t| substituteFont |\\n\\n\\tsubstituteFont _ aProject projectParameters at:\\n\\n#substitutedFont ifAbsent: [#none].\\n\\n\\t(substituteFont ~~ #none and: [self font == substituteFont])\\n\\n\\t\\t\\tifTrue: [ self fitContents ].\\n\\n\\n\\n\\t^ super fixUponLoad: aProject seg: anImageSegment! !\\n\\n\\n!StringMorph methodsFor: 'parts bin' stamp: 'dgd 2/14/2003 21:58'!\\ninitializeToStandAlone\\n\\tsuper initializeToStandAlone.\\n\\t\\n\\tfont _ nil.\\n\\temphasis _ 0.\\n\\thasFocus _ false.\\n\\tself contents: 'String: Shift-click on me to edit'! !\\n\\n\\n!StringMorph methodsFor: 'printing' stamp: 'efc 2/22/2003 21:35'!\\nfont: aFont \\n\\t\\\"Set the font my text will use. The emphasis remains unchanged.\\\"\\n\\n\\tfont _ aFont.\\n\\t^ self font: font emphasis: emphasis! !\\n\\n!StringMorph methodsFor: 'printing' stamp: 'jm 11/3/97 16:52'!\\nprintOn: aStream\\n\\n\\tsuper printOn: aStream.\\n\\taStream print: contents.\\n! !\\n\\n\\n!StringMorph methodsFor: '*MorphicExtras-accessing' stamp: 'sw 2/18/2003 02:55'!\\ngetCharacters\\n\\t\\\"obtain a string value from the receiver.\\\"\\n\\n\\t^ self contents! !\\n\\n!StringMorph methodsFor: '*MorphicExtras-accessing' stamp: 'sw 9/9/1999 18:09'!\\nhandsWithMeForKeyboardFocus\\n\\t| foc |\\n\\t\\\"Answer the hands that have me as their keyboard focus\\\"\\n\\n\\thasFocus ifFalse: [^ #()].\\n\\t^ self currentWorld hands select:\\n\\t\\t[:aHand | (foc _ aHand keyboardFocus) notNil and: [foc owner == self]]! !\\n\\n\\n!StringMorph methodsFor: '*MorphicExtras-printing'!\\nfullPrintOn: aStream\\n\\n\\taStream nextPutAll: '('.\\n\\tsuper fullPrintOn: aStream.\\n\\taStream nextPutAll: ') contents: '; print: contents! !\\n\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForClassAndMethodString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as an encoding of the form\\n\\t\\t<className> [ class ] <selector>\\\"\\n\\n\\t| aComment |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\tMessageSet parse: self contents asString toClassAndSelector:\\n\\t\\t[:aClass :aSelector |\\n\\t\\t\\t(aClass notNil and: [aSelector notNil]) ifTrue:\\n\\t\\t\\t\\t[aComment := aClass precodeCommentOrInheritedCommentFor: aSelector]].\\n\\t^ aComment\\n! !\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForLexiconString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as an encoding (used in Lexicons) of the form\\n\\t\\t<selector> <spaces> (<className>>)\\\"\\n\\n\\t| aComment contentsString aSelector aClassName |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\tcontentsString := self contents asString.\\n\\taSelector := contentsString upTo: $ .\\n\\taClassName := contentsString copyFrom: ((contentsString indexOf: $() + 1) to: ((contentsString indexOf: $)) - 1).\\n\\tMessageSet parse: (aClassName, ' dummy') toClassAndSelector:\\n\\t\\t[:cl :sel | cl ifNotNil:\\n\\t\\t\\t[aComment := cl precodeCommentOrInheritedCommentFor: aSelector]].\\n\\t^ aComment\\n! !\\n\\n!StringMorph methodsFor: '*Tools' stamp: 'sd 11/20/2005 21:26'!\\nballoonTextForMethodString\\n\\t\\\"Answer suitable balloon text for the receiver thought of as a method belonging to the currently-selected class of a browser tool.\\\"\\n\\n\\t| aWindow aCodeHolder aClass |\\n\\tPreferences balloonHelpInMessageLists\\n\\t\\tifFalse: [^ nil].\\n\\taWindow := self ownerThatIsA: SystemWindow.\\n\\t(aWindow isNil or: [((aCodeHolder := aWindow model) isKindOf: CodeHolder) not])\\n\\t\\tifTrue:\\t[^ nil].\\n\\t((aClass := aCodeHolder selectedClassOrMetaClass) isNil or:\\n\\t\\t[(aClass includesSelector: contents asSymbol) not])\\n\\t\\t\\tifTrue: [^ nil].\\n\\t^ aClass precodeCommentOrInheritedCommentFor: contents asSymbol\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'sw 8/22/97 22:19'!\\ncontents: aString\\n\\t\\\" 'StringMorph contents: str' is faster than 'StringMorph new contents: str' \\\"\\n\\t^ self contents: aString font: nil! !\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'di 4/1/1999 17:15'!\\ncontents: aString font: aFont\\n\\t^ self basicNew initWithContents: aString font: aFont emphasis: 0! !\\n\\n!StringMorph class methodsFor: 'instance creation' stamp: 'di 4/1/1999 17:15'!\\ncontents: aString font: aFont emphasis: emphasisCode\\n\\t^ self basicNew initWithContents: aString font: aFont emphasis: emphasisCode! !\\n\\n\\n!StringMorph class methodsFor: 'scripting' stamp: 'sw 5/6/1998 14:00'!\\nauthoringPrototype\\n\\t^ super authoringPrototype contents: 'String'! !\\n\\n\\n!StringMorph class methodsFor: 'testing' stamp: 'di 5/6/1998 21:07'!\\ntest\\n\\t\\\"Return a morph with lots of strings for testing display speed.\\\"\\n\\t| c |\\n\\tc _ AlignmentMorph newColumn.\\n\\tSystemOrganization categories do:\\n\\t\\t[:cat | c addMorph: (StringMorph new contents: cat)].\\n\\t^ c! !\\n\\n!StringMorph class methodsFor: 'testing' stamp: 'di 5/6/1998 21:08'!\\ntest2\\n\\t\\\"Return a morph with lots of strings for testing display speed.\\\"\\n\\t| c r |\\n\\tc _ AlignmentMorph newColumn.\\n\\tSystemOrganization categories reverseDo:\\n\\t\\t[:cat | c addMorph: (StringMorph new contents: cat)].\\n\\tr _ RectangleMorph new extent: c fullBounds extent.\\n\\tc submorphsDo: [:m | r addMorph: m].\\n\\t^ r\\n! !\\nObject subclass: #StringMorphAttributeScanner\\n\\tinstanceVariableNames: 'fontNumber textColor emphasis alignment actualFont indent kern'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!StringMorphAttributeScanner commentStamp: '<historical>' prior: 0!\\nA StringMorphAttributeScanner provides the interface of a CharacterScanner so that text attributes may be collected from a Text and used elsewhere, like in setting the attributes of a StringMorph.\\n!\\n]style[(2 195)cblack;,f3cblack;!\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:12'!\\nactualFont\\n\\t\\\"Answer the value of actualFont\\\"\\n\\n\\t^ actualFont ifNil: [ TextStyle defaultFont ]! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nalignment\\n\\t\\\"Answer the value of alignment\\\"\\n\\n\\t^ alignment! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nemphasis\\n\\t\\\"Answer the value of emphasis\\\"\\n\\n\\t^ emphasis! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:14'!\\nfont\\n\\t\\\"Answer the value of font\\\"\\n\\n\\t^self textStyle fontAt: self fontNumber! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:11'!\\nfontNumber\\n\\t\\\"Answer the value of font\\\"\\n\\n\\t^ fontNumber! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nindent\\n\\t\\\"Answer the value of indent\\\"\\n\\n\\t^ indent! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\nkern\\n\\t\\\"Answer the value of kern\\\"\\n\\n\\t^ kern! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 12:34'!\\ntextColor\\n\\t\\\"Answer the value of textColor\\\"\\n\\n\\t^ textColor! !\\n\\n!StringMorphAttributeScanner methodsFor: 'accessing' stamp: 'nk 2/26/2004 13:12'!\\ntextStyle\\n\\t^self actualFont textStyle ifNil: [ TextStyle default ]! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'initialize-release' stamp: 'nk 2/26/2004 13:10'!\\ninitialize\\n\\temphasis _ 0.\\n\\tindent _ 0.\\n\\tkern _ 0.\\n\\tfontNumber _ 1.\\n\\tactualFont _ TextStyle defaultFont! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:40'!\\naddEmphasis: anInteger\\n\\t\\\"Set the value of emphasis\\\"\\n\\n\\temphasis _ emphasis bitOr: anInteger! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:41'!\\naddKern: kernDelta\\n\\t\\\"Set the current kern amount.\\\"\\n\\tkern _ kern + kernDelta! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:37'!\\nindentationLevel: anInteger\\n\\t\\\"Set the value of indent\\\"\\n\\n\\tindent _ anInteger! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 13:09'!\\nsetActualFont: aFont\\n\\t\\\"Set the value of actualFont, from a TextFontReference\\\"\\n\\n\\tactualFont _ aFont.\\n\\taFont textStyle ifNotNilDo: [ :ts | fontNumber _ ts fontIndexOf: aFont ]! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:39'!\\nsetAlignment: aSymbol\\n\\t\\\"Set the value of alignment\\\"\\n\\n\\talignment _ aSymbol! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 13:10'!\\nsetFont: fontNum\\n\\t\\\"Set the value of font\\\"\\n\\n\\tfontNumber _ fontNum! !\\n\\n!StringMorphAttributeScanner methodsFor: 'scanning' stamp: 'nk 2/26/2004 12:34'!\\ntextColor: anObject\\n\\t\\\"Set the value of textColor\\\"\\n\\n\\ttextColor _ anObject! !\\n\\n\\n!StringMorphAttributeScanner methodsFor: 'string morph' stamp: 'nk 2/26/2004 13:09'!\\ninitializeFromStringMorph: aStringMorph\\n\\t| style |\\n\\tactualFont _ aStringMorph font ifNil: [ TextStyle defaultFont ].\\n\\tstyle _ actualFont textStyle.\\n\\temphasis _ actualFont emphasis.\\n\\tfontNumber _ (style fontIndexOf: actualFont) ifNil: [ 1 ].\\n\\ttextColor _ aStringMorph color.\\n! !\\nTextMorph subclass: #StringMorphEditor\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Text Support'!\\n!StringMorphEditor commentStamp: '<historical>' prior: 0!\\nI am a textMorph used as a pop-up editor for StringMorphs. I present a yellow background and I go away when a CR is typed or when the user clicks elsewhere.!\\n\\n\\n!StringMorphEditor methodsFor: 'display' stamp: 'sw 4/20/2003 15:46'!\\ninitialize\\n\\n\\t\\\"Initialize the receiver. Give it a white background\\\"\\n\\n\\n\\n\\tsuper initialize.\\n\\n\\tself backgroundColor: Color white.\\n\\n\\tself color: Color red! !\\n\\n\\n!StringMorphEditor methodsFor: 'drawing' stamp: 'sw 9/7/1999 16:22'!\\ndrawOn: aCanvas\\n\\n\\taCanvas fillRectangle: self bounds color: Color yellow muchLighter.\\n\\t^ super drawOn: aCanvas! !\\n\\n\\n!StringMorphEditor methodsFor: 'event handling' stamp: 'nk 6/12/2004 22:07'!\\nkeyStroke: evt\\n\\t\\\"This is hugely inefficient, but it seems to work, and it's unlikely it will ever need\\n\\tto be any more efficient -- it's only intended to edit single-line strings.\\\"\\n\\n\\t| char priorEditor newSel |\\n\\t(((char _ evt keyCharacter) = Character enter) or: [(char = Character cr)\\n\\t\\t\\tor: [char = $s and: [evt commandKeyPressed]]])\\n\\t\\t\\t\\tifTrue: [owner doneWithEdits; acceptContents.\\n\\tself flag: #arNote. \\\"Probably unnecessary\\\"\\n\\t\\t\\t\\t\\t\\tevt hand releaseKeyboardFocus.\\n\\t\\t\\t\\t\\t\\t^ self delete].\\n\\t\\n\\t(char = $l and: [evt commandKeyPressed]) ifTrue: \\\"cancel\\\"\\n\\t\\t[owner cancelEdits.\\n\\t\\tevt hand releaseKeyboardFocus.\\n\\t\\t^ self delete].\\n\\n\\tsuper keyStroke: evt.\\n\\towner interimContents: self contents asString.\\n\\tnewSel _ self editor selectionInterval.\\n\\n\\tpriorEditor _ self editor. \\\"Save editor state\\\"\\n\\tself releaseParagraph. \\\"Release paragraph so it will grow with selection.\\\"\\n\\tself paragraph. \\\"Re-instantiate to set new bounds\\\"\\n\\tself installEditorToReplace: priorEditor. \\\"restore editor state\\\"\\n\\tself editor selectFrom: newSel first to: newSel last.\\n! !\\n\\n!StringMorphEditor methodsFor: 'event handling' stamp: 'nk 1/23/2004 13:18'!\\nkeyboardFocusChange: aBoolean\\n\\t| hadFocus |\\n\\towner ifNil: [ ^self ].\\n\\thadFocus _ owner hasFocus.\\n\\tsuper keyboardFocusChange: aBoolean.\\n\\taBoolean ifFalse:\\n\\t\\t[hadFocus ifTrue:\\n\\t\\t\\t[owner lostFocusWithoutAccepting; doneWithEdits].\\n\\t\\t^ self delete]! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringMorphEditor class\\n\\tinstanceVariableNames: ''!\\n\\n!StringMorphEditor class methodsFor: 'new-morph participation' stamp: 'kfr 5/1/2000 13:41'!\\nincludeInNewMorphMenu\\n\\t\\\"Not to be instantiated from the menu\\\"\\n\\t^ false! !\\nTileMorph subclass: #StringReadoutTile\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n\\n!StringReadoutTile methodsFor: 'accessing' stamp: 'sw 11/1/97 13:15'!\\nliteral: anObject\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last informTarget! !\\n\\n\\n!StringReadoutTile methodsFor: 'literal' stamp: 'sw 9/15/1999 15:14'!\\nsetLiteralTo: anObject width: w\\n\\t\\\"like literal:width: but does not inform the target\\\"\\n\\tliteral _ anObject.\\n\\tself updateLiteralLabel.\\n\\tsubmorphs last setWidth: w.\\n\\tself updateLiteralLabel! !\\n\\n\\n!StringReadoutTile methodsFor: 'misc' stamp: 'sw 9/17/1999 08:01'!\\nbasicWidth\\n\\t^ 26! !\\n\\n\\n!StringReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 18:20'!\\nhandlesMouseDown: evt \\n\\t^ true! !\\n\\n!StringReadoutTile methodsFor: 'event handling' stamp: 'tak 8/2/2005 23:38'!\\nmouseStillDown: evt \\n\\t(self labelMorph notNil\\n\\t\\t\\tand: [self labelMorph containsPoint: evt cursorPoint])\\n\\t\\tifTrue: [^ self labelMorph mouseDown: evt].\\n\\t^ super mouseStillDown: evt! !\\nObjectSocket subclass: #StringSocket\\n\\tinstanceVariableNames: 'numStringsInNextArray stringsForNextArray nextStringSize files startTime stringCounter socketWriterProcess outputQueue bytesInOutputQueue extraUnsentBytes transmissionError readBuffer'\\n\\tclassVariableNames: 'MaxRatesSeen RecentSendHistory RunningSendCount'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n!StringSocket commentStamp: 'ls 8/4/2004 15:15' prior: 0!\\nThis is a socket which sends arrays of strings back and forth. This is less convenient than ObjectSockets, but it is more secure and it makes it easier to reason about updates to the protocol.\\n\\nAn array of strings is represented on the network as:\\n\\n\\t4-bytes\\t\\tnumber of strings in the array\\n\\t4-byte\\t\\tnumber of bytes in the first string\\n\\tn1-bytes\\t\\tcharacters in the first string\\n\\t4-bytes\\t\\tnumber of bytes in the second string\\n\\tn2-bytes\\tcharacters in the second string\\n\\t...\\n\\n!\\n\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ndestroy\\n\\n\\tsocketWriterProcess ifNotNil: [socketWriterProcess terminate. socketWriterProcess := nil].\\n\\toutputQueue := nil.\\n\\tbytesInOutputQueue := 0.\\n\\tsocket ifNotNil: [socket destroy. socket := nil.].\\n! !\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ninitialize: aSocket\\n\\n\\ttransmissionError := false.\\n\\tsuper initialize: aSocket.\\n\\toutputQueue := SharedQueue new.\\n\\textraUnsentBytes := bytesInOutputQueue := 0.\\n\\tsocketWriterProcess := [\\n\\t\\t[self transmitQueueNext] whileTrue.\\n\\t\\tsocketWriterProcess := nil.\\n\\t\\toutputQueue := nil.\\n\\t\\tbytesInOutputQueue := 0.\\n\\t] forkAt: Processor lowIOPriority.! !\\n\\n!StringSocket methodsFor: 'as yet unclassified' stamp: 'yo 10/10/2005 18:47'!\\nreadBuffer\\n\\n\\t^ readBuffer ifNil: [readBuffer _ String new: 20000].\\n! !\\n\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'yo 10/10/2005 18:49'!\\naddToInBuf: aString\\n\\n\\t| newAlloc |\\n\\tnewAlloc _ aString size * 2 max: 80000.\\n\\tinBuf ifNil: [\\n\\t\\tinBuf _ String new: newAlloc.\\n\\t\\tinBufIndex _ 1.\\n\\t\\tinBufLastIndex _ 0.\\n\\t].\\n\\taString size > (inBuf size - inBufLastIndex) ifTrue: [\\n\\t\\tinBuf _ inBuf , (String new: newAlloc)\\n\\t].\\n\\tinBuf \\n\\t\\treplaceFrom: inBufLastIndex + 1 \\n\\t\\tto: inBufLastIndex + aString size\\n\\t\\twith: aString \\n\\t\\tstartingAt: 1.\\n\\tinBufLastIndex _ inBufLastIndex + aString size.\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\naddToOutBuf: arrayToWrite\\n\\n\\t| size newAlloc |\\n\\tsize := self spaceToEncode: arrayToWrite.\\n\\tnewAlloc := size * 2 max: 8000.\\t\\\"gives us room to grow\\\"\\n\\toutBuf ifNil: [\\n\\t\\toutBuf := String new: newAlloc.\\n\\t\\toutBufIndex := 1.\\n\\t].\\n\\toutBuf size - outBufIndex + 1 < size ifTrue: [\\n\\t\\toutBuf := outBuf , (String new: newAlloc).\\n\\t].\\n\\tCanvasEncoder at: 1 count: arrayToWrite size + 1.\\n\\toutBuf putInteger32: arrayToWrite size at: outBufIndex.\\n\\toutBufIndex := outBufIndex + 4.\\n\\tarrayToWrite do: [ :each |\\n\\t\\toutBuf putInteger32: each size at: outBufIndex.\\n\\t\\toutBufIndex := outBufIndex + 4.\\n\\t\\toutBuf \\n\\t\\t\\treplaceFrom: outBufIndex \\n\\t\\t\\tto: outBufIndex + each size - 1 \\n\\t\\t\\twith: each \\n\\t\\t\\tstartingAt: 1.\\n\\t\\toutBufIndex := outBufIndex + each size.\\n\\t].\\n\\t^size! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/13/2000 08:29'!\\nbacklog\\n\\n\\t^bytesInOutputQueue + extraUnsentBytes! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ngotSomething\\n\\n\\tnumStringsInNextArray ifNil: [^self tryForNumStringsInNextArray ].\\n\\tnumStringsInNextArray = 0 ifTrue: [\\n\\t\\tinObjects add: #().\\n\\t\\tnumStringsInNextArray := nil.\\n\\t\\t^true ].\\n\\tnextStringSize ifNil: [^ self tryForNextStringSize ].\\n\\t^self tryForString\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ninBufNext: anInteger\\n\\t\\n\\t| answer |\\n\\tanswer := inBuf copyFrom: inBufIndex to: inBufIndex + anInteger - 1.\\n\\tinBufIndex := inBufIndex + anInteger.\\n\\t^answer! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 7/20/2000 15:55'!\\ninBufSize\\n\\n\\tinBuf ifNil: [^0].\\n\\t^inBufLastIndex - inBufIndex + 1! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/14/2000 09:54'!\\nisConnected\\n\\n\\t^super isConnected and: [socketWriterProcess notNil]! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'md 2/24/2006 19:51'!\\nnextPut: anObject\\n\\n\\tsocketWriterProcess ifNil: [^self].\\n\\toutObjects addLast: anObject.\\n\\t\\\"return the argument - added by kwl\\\"\\n\\t^ anObject! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'RAA 12/14/2000 09:46'!\\nprocessIO\\n\\t\\\"do some as much network IO as possible\\\"\\n\\n\\tsocketWriterProcess ifNil: [^self].\\n\\tself processOutput.\\n\\tself processInput.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'yo 10/10/2005 18:47'!\\nprocessInput\\n\\t| totalReceived chunkOfData |\\n\\t\\\"do as much input as possible\\\"\\n\\n\\tself flag: #XXX. \\\"should have resource limits here--no more than X objects and Y bytes\\\"\\n\\n\\tchunkOfData _ socket receiveAvailableDataIntoBuffer: self readBuffer.\\n\\tself addToInBuf: chunkOfData.\\n\\ttotalReceived _ chunkOfData size.\\n\\n\\ttotalReceived > 0 ifTrue: [\\n\\t\\tNebraskaDebug at: #SendReceiveStats add: {'GET'. totalReceived}.\\n\\t].\\n\\n\\t[ self gotSomething ] whileTrue: [].\\t\\t\\\"decode as many string arrays as possible\\\"\\n\\n\\tself shrinkInBuf.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nprocessOutput\\n\\n\\t| arrayToWrite size bytesSent timeStartSending t itemsSent now timeSlot bucketAgeInMS bytesThisSlot |\\n\\n\\toutBufIndex := 1.\\n\\titemsSent := bytesSent := 0.\\n\\ttimeStartSending := Time millisecondClockValue.\\n\\t[outObjects isEmpty not and: [self isConnected]] whileTrue: [\\n\\t\\tarrayToWrite := outObjects removeFirst.\\n\\t\\tsize := self addToOutBuf: arrayToWrite.\\n\\t\\tbytesSent := bytesSent + size.\\n\\t\\titemsSent := itemsSent + 1.\\n\\t\\toutBufIndex > 10000 ifTrue: [self queueOutBufContents].\\n\\t].\\n\\toutBufIndex > 1 ifTrue: [self queueOutBufContents].\\n\\tbytesSent > 0 ifTrue: [\\n\\t\\tMaxRatesSeen ifNil: [MaxRatesSeen := Dictionary new].\\n\\t\\tnow := Time millisecondClockValue.\\n\\t\\tt := now - timeStartSending.\\n\\t\\ttimeSlot := now // 10000.\\t\\\"ten second buckets\\\"\\n\\t\\tbucketAgeInMS := now \\\\\\\\ 10.\\n\\t\\tbytesThisSlot := (MaxRatesSeen at: timeSlot ifAbsent: [0]) + bytesSent.\\n\\t\\tMaxRatesSeen \\n\\t\\t\\tat: timeSlot \\n\\t\\t\\tput: bytesThisSlot.\\n\\t\\tNebraskaDebug \\n\\t\\t\\tat: #SendReceiveStats \\n\\t\\t\\tadd: {'put'. bytesSent. t. itemsSent. bytesThisSlot // (bucketAgeInMS max: 100)}.\\n\\t].\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\npurgeOutputQueue\\n\\n\\tbytesInOutputQueue := 0.\\n\\t[outputQueue nextOrNil notNil] whileTrue.! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nqueueOutBufContents\\n\\n\\tbytesInOutputQueue := bytesInOutputQueue + outBufIndex - 1.\\n\\toutputQueue nextPut: {outBuf. outBufIndex - 1}.\\n\\tNebraskaDebug at: #queuedbufferSizes add: {outBufIndex - 1}.\\n\\toutBufIndex := 1.\\n\\toutBuf := String new: 11000.\\n\\t\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nsendDataCautiously: aStringOrByteArray bytesToSend: bytesToSend\\n\\t\\\"Send all of the data in the given array, even if it requires multiple calls to send it all. Return the number of bytes sent. Try not to send too much at once since this seemed to cause problems talking to a port on the same machine\\\"\\n\\n\\t| bytesSent count |\\n\\n\\tbytesSent := 0.\\n\\t[bytesSent < bytesToSend] whileTrue: [\\n\\t\\textraUnsentBytes := bytesToSend - bytesSent.\\n\\t\\tcount := socket \\n\\t\\t\\tsendSomeData: aStringOrByteArray \\n\\t\\t\\tstartIndex: bytesSent + 1 \\n\\t\\t\\tcount: (bytesToSend - bytesSent min: 6000).\\n\\t\\tbytesSent := bytesSent + count.\\n\\t\\t(Delay forMilliseconds: 1) wait.\\n\\t].\\n\\textraUnsentBytes := 0.\\n\\t^ bytesSent\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\nshrinkInBuf\\n\\n\\tinBuf ifNil: [^self].\\n\\tinBufLastIndex < inBufIndex ifTrue: [\\n\\t\\tinBufLastIndex := 0.\\n\\t\\tinBufIndex := 1.\\n\\t\\tinBuf size > 20000 ifTrue: [inBuf := nil].\\t\\\"if really big, kill it\\\"\\n\\t\\t^self\\n\\t].\\n\\tinBuf := inBuf copyFrom: inBufIndex to: inBufLastIndex.\\n\\tinBufLastIndex := inBuf size.\\n\\tinBufIndex := 1.\\n\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'ls 4/25/2000 18:36'!\\nspaceToEncode: anArray\\n\\t\\\"return the number of characters needed to encode the given string array\\\"\\n\\t^anArray inject: 4 into: [ :sum :array |\\n\\t\\tsum + (array size + 4) ].! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntransmitQueueNext\\n\\n\\t| bufTuple |\\n\\n\\tbufTuple := outputQueue next.\\n\\tbytesInOutputQueue := bytesInOutputQueue - bufTuple second max: 0.\\n\\t[\\n\\t\\tself \\n\\t\\t\\tsendDataCautiously: bufTuple first \\n\\t\\t\\tbytesToSend: bufTuple second.\\n\\t]\\n\\t\\ton: Error\\n\\t\\tdo: [ :ex |\\n\\t\\t\\ttransmissionError := true.\\n\\t\\t].\\n\\t^transmissionError not\\n\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForNextStringSize\\n\\t\\\"grab the size of the next string, if it's available\\\"\\n\\n\\tself inBufSize >= 4 ifFalse: [^false].\\n\\n\\tnextStringSize := inBuf getInteger32: inBufIndex.\\n\\t\\\"nextStringSize > 100000 ifTrue: [self barf].\\\"\\n\\tinBufIndex := inBufIndex + 4.\\n\\t\\n\\tnextStringSize < 0 ifTrue: [\\n\\t\\tsocket disconnect.\\n\\t\\t^false ].\\n\\t\\n\\t^true\\n! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForNumStringsInNextArray\\n\\t\\\"input numStringsInNextARray, if 4 bytes are available\\\"\\n\\n\\tself inBufSize >= 4 ifFalse: [^false].\\n\\n\\tnumStringsInNextArray := inBuf getInteger32: inBufIndex.\\n\\t\\\"(numStringsInNextArray > 100 or: [numStringsInNextArray < 1]) ifTrue: [self barf].\\\"\\n\\tinBufIndex := inBufIndex + 4.\\n\\n\\tnumStringsInNextArray < 0 ifTrue: [\\n\\t\\tsocket disconnect.\\n\\t\\t^false ].\\n\\t\\n\\tstringsForNextArray := Array new: numStringsInNextArray.\\n\\tstringCounter := 0.\\n\\tnextStringSize := nil. \\n\\t^true! !\\n\\n!StringSocket methodsFor: 'private-IO' stamp: 'sd 11/20/2005 21:26'!\\ntryForString\\n\\t\\\"try to grab an actual string\\\"\\n\\n\\tself inBufSize >= nextStringSize ifFalse: [^false].\\n\\n\\tstringsForNextArray \\n\\t\\tat: (stringCounter := stringCounter + 1)\\n\\t\\tput: (self inBufNext: nextStringSize) asString.\\n\\n\\tstringCounter = numStringsInNextArray ifTrue: [\\t\\\"we have finished another array!!\\\"\\n\\t\\tinObjects addLast: stringsForNextArray.\\n\\t\\tstringCounter := stringsForNextArray := numStringsInNextArray := nextStringSize := nil.\\n\\t] ifFalse: [\\t\\\"still need more strings for this array\\\"\\n\\t\\tnextStringSize := nil.\\n\\t].\\n\\n\\t^true\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nStringSocket class\\n\\tinstanceVariableNames: ''!\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nclearRatesSeen\\n\\\"\\nStringSocket clearRatesSeen\\n\\\"\\n\\tMaxRatesSeen := nil ! !\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\ncompareFiles\\n\\\"\\nStringSocket compareFiles\\n\\\"\\n\\t| data1 data2 |\\n\\n\\tdata1 := (FileStream fileNamed: 'Macintosh HD:bob:nebraska test:58984048.1')\\n\\t\\t\\tcontentsOfEntireFile.\\n\\tdata2 := (FileStream fileNamed: 'BobsG3:squeak:dsqueak:DSqueak2.7 folder:58795431.3')\\n\\t\\t\\tcontentsOfEntireFile.\\n\\t1 to: (data1 size min: data2 size) do: [ :i |\\n\\t\\t(data1 at: i) = (data2 at: i) ifFalse: [self halt].\\n\\t].\\n! !\\n\\n!StringSocket class methodsFor: 'as yet unclassified' stamp: 'sd 11/20/2005 21:26'!\\nshowRatesSeen\\n\\\"\\nStringSocket showRatesSeen\\n\\\"\\n\\t| answer |\\n\\n\\tMaxRatesSeen ifNil: [^Beeper beep].\\n\\tanswer := WriteStream on: String new.\\n\\tMaxRatesSeen keys asSortedCollection do: [ :key |\\n\\t\\tanswer nextPutAll: key printString,' ',((MaxRatesSeen at: key) // 10000) printString; cr\\n\\t].\\n\\tStringHolder new contents: answer contents; openLabel: 'send rates at 10 second intervals'.! !\\nTestCase subclass: #StringSocketTestCase\\n\\tinstanceVariableNames: 'socket1 socket2 end1 end2'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Nebraska-Network-ObjectSocket'!\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\nsetUp\\n\\t\\\"it would be nice to have an in-image loopback socket, so that the tests do not need the underlying platform's sockets to behave nicely\\\"\\n\\tsocket1 := Socket newTCP.\\n\\tsocket2 := Socket newTCP.\\n\\t\\n\\tsocket1 listenOn: 9999.\\n\\tsocket2 connectTo: (NetNameResolver localHostAddress) port: 9999.\\n\\n\\tsocket1 waitForConnectionFor: 60.\\t\\n\\tsocket2 waitForConnectionFor: 60.\\n\\t\\n\\tend1 := StringSocket on: socket1.\\n\\tend2 := StringSocket on: socket2.\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'ls 8/4/2004 15:22'!\\ntearDown\\n\\tend1 destroy.\\n\\tend2 destroy.\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'ls 8/4/2004 15:21'!\\ntestBasics\\n\\tend1 nextPut: #().\\n\\tend1 nextPut: #('').\\n\\tend1 nextPut: #('hello' 'world').\\n\\tend1 processIO.\\n\\t\\n\\tend2 processIO.\\n\\n\\tself should: [ end2 next = #() ].\\n\\tself should: [ end2 next = #('') ].\\n\\tself should: [ end2 next = #('hello' 'world') ].\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\ntestBogusInput1\\n\\t| negString |\\n\\tnegString := String new: 4.\\n\\tnegString putInteger32: -10 at: 1.\\n\\tsocket1 sendData: negString.\\n\\tend2 processIO.\\n\\t\\n\\tself should: [ end2 isConnected not ].\\n\\t! !\\n\\n!StringSocketTestCase methodsFor: 'running' stamp: 'sd 11/20/2005 21:26'!\\ntestBogusInput2\\n\\t| bogoString |\\n\\tbogoString := String new: 8.\\n\\tbogoString putInteger32: 2 at: 1.\\n\\tbogoString putInteger32: -10 at: 5.\\n\\tsocket1 sendData: bogoString.\\n\\tend2 processIO.\\n\\t\\n\\tself should: [ end2 isConnected not ].\\n\\t! !\\nClassTestCase subclass: #StringTest\\n\\tinstanceVariableNames: 'string'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Text'!\\n!StringTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class String. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!StringTest methodsFor: 'initialize-release' stamp: 'md 4/18/2003 10:00'!\\nsetUp\\n\\tstring := 'Hi, I am a String'! !\\n\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy01\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test\\\"'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:20'!\\ntestFindTokensEscapedBy02\\n\\n\\t| tokens |\\n\\tstring := ''.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens isEmpty! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy03\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 4! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy04\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a\\\",\\\" test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy05\\n\\n\\t| tokens |\\n\\tstring := 'this, /is, a\\\",\\\" test/'.\\n\\ttokens := string findTokens: ',#' escapedBy: '\\\"/'.\\n\\tself assert: tokens size = 2.\\n\\tself assert: tokens first = 'this'.\\n\\tself assert: tokens second = ' is, a\\\",\\\" test'.! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy06\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy07\\n\\n\\t| tokens |\\n\\tstring := 'a:b::c'.\\n\\ttokens := string findTokens: ':' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 4.\\n\\tself assert: tokens first = 'a'.\\n\\tself assert: tokens second = 'b'.\\n\\tself assert: tokens third = ''.\\n\\tself assert: tokens fourth = 'c'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy08\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ##a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 4.\\n\\tself assert: tokens third = ' a'.\\n\\tself assert: tokens fourth = ' test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy09\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ###a, test#'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' #a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy10\\n\\n\\t| tokens |\\n\\tstring := 'this, is, ###a, test'.\\n\\ttokens := string findTokens: ',' escapedBy: '#'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' #a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy11\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"\\\"\\\"a, test\\\"'.\\n\\ttokens := string findTokens: ',' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' \\\"a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy12\\n\\n\\t| tokens |\\n\\tstring := 'one, two# three; four. five'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: '\\\"'.\\n\\tself assert: tokens size == 5.\\n\\tself assert: tokens third = ' three'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy13\\n\\n\\t| tokens |\\n\\tstring := 'one, two# three; four. five'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: nil.\\n\\tself assert: tokens size == 5.\\n\\tself assert: tokens third = ' three'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy14\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: ',#;.' escapedBy: '\\\"&'.\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens second = ' two# three'.\\n\\tself assert: tokens third = ' four. five'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy15\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: nil escapedBy: '\\\"&'.\\n\\tself assert: tokens size = 1.\\n\\tself assert: tokens first = 'one, two# three; four. five'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy16\\n\\n\\t| tokens |\\n\\tstring := 'one, \\\"two# three\\\"; &four. five&'.\\n\\ttokens := string findTokens: nil escapedBy: nil.\\n\\tself assert: tokens size = 1.\\n\\tself assert: tokens first = string! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy21\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test\\\"'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy22\\n\\n\\t| tokens |\\n\\tstring := ''.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size = 0! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy23\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a, test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 4! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy24\\n\\n\\t| tokens |\\n\\tstring := 'this, is, a\\\",\\\" test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'fbs 2/13/2006 22:19'!\\ntestFindTokensEscapedBy25\\n\\n\\t| tokens |\\n\\tstring := 'this, /is, a\\\",\\\" test/'.\\n\\ttokens := string findTokens: $, escapedBy: $/.\\n\\tself assert: tokens size = 2.\\n\\tself assert: tokens first = 'this'.\\n\\tself assert: tokens second = ' is, a\\\",\\\" test'.! !\\n\\n!StringTest methodsFor: 'testing - tokenizing' stamp: 'stephaneducasse 2/4/2006 20:10'!\\ntestFindTokensEscapedBy26\\n\\n\\t| tokens |\\n\\tstring := 'this, is, \\\"a, test'.\\n\\ttokens := string findTokens: $, escapedBy: $\\\".\\n\\tself assert: tokens size == 3.\\n\\tself assert: tokens third = ' a, test'! !\\n\\n\\n!StringTest methodsFor: 'tests - accessing' stamp: 'sd 6/5/2005 09:27'!\\ntestAt\\n\\n\\tself assert: (string at: 1) = $H.! !\\n\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:26'!\\ntestAsInteger\\n\\n\\tself assert: '1796exportFixes-tkMX' asInteger = 1796.\\n\\tself assert: 'donald' asInteger isNil.\\n\\tself assert: 'abc234def567' asInteger = 234.\\n\\tself assert: '-94' asInteger = -94.\\n\\tself assert: 'foo-bar-92' asInteger = -92! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestAsSmalltalkComment\\n\\n\\t| exampleStrings |\\n\\texampleStrings := #(\\n\\t\\t''\\n\\t\\t' '\\n\\t\\t'\\\"'\\n\\t\\t'\\\"\\\"'\\n\\t\\t'\\\"\\\"\\\"'\\n\\t\\t'abc\\\"abc'\\n\\t\\t'abc\\\"\\\"abc'\\n\\t\\t'abc\\\"hello\\\"abc'\\n\\t\\t'abc\\\"'\\n\\t\\t'\\\"abc' ).\\n\\n\\t\\\"check that the result of scanning the comment is empty\\\"\\n\\texampleStrings do: [ :s |\\n\\t\\t| tokens |\\n\\t\\ttokens := Scanner new scanTokens: s asSmalltalkComment.\\n\\t\\tself assert: (tokens isEmpty) ].\\n\\n\\t\\\"check that the result has the same non-quote characters as the original\\\"\\n\\texampleStrings do: [ :s |\\n\\t\\tself assert: ( (s copyWithout: $\\\") = (s asSmalltalkComment copyWithout: $\\\"))].\\n\\n\\t\\\"finnaly, test for some common kinds of inputs\\\"\\n\\tself assert: ( 'abc' asSmalltalkComment = '\\\"abc\\\"').\\n\\tself assert: ( 'abc\\\"abc' asSmalltalkComment = '\\\"abc\\\"\\\"abc\\\"').\\n\\tself assert: ('abc\\\"\\\"abc' asSmalltalkComment = '\\\"abc\\\"\\\"abc\\\"' ).\\n\\t\\t! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestCapitalized\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := 'MElViN'.\\n\\tlc := 'mElViN'.\\n\\tempty := ' '.\\n\\tself assert: lc capitalized = uc.\\n\\tself assert: uc capitalized = uc.\\n\\t\\\"the string gets copied\\\"\\n\\tself deny: uc capitalized == uc.\\n\\tself deny: empty capitalized == empty.! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'ky 7/8/2006 15:28'!\\ntestUnescapePercents\\n\\tself assert: '' unescapePercents = ''.\\n\\tself assert: 'x' unescapePercents = 'x'.\\n\\n\\tself assert: '+' unescapePercents = ' '.\\n\\tself assert: 'x+' unescapePercents = 'x '.\\n\\tself assert: '+x' unescapePercents = ' x'.\\n\\tself assert: 'x+x' unescapePercents = 'x x'.\\n\\n\\tself assert: '%' unescapePercents = '%'.\\n\\tself assert: '%3' unescapePercents = '%3'.\\n\\tself assert: '%3C' unescapePercents = '<'.\\n\\t\\n\\tself assert: '%3Cx%3E4%3C%2Fx%3E' unescapePercents = '<x>4</x>'.\\n\\t\\n\\tself assert: '!!@#$%25%5E&*()%7B%7D%5B%5D=:/;?+''%22' unescapePercents = '!!@#$%^&*(){}[]=:/;? ''\\\"'.\\n\\tself assert: '!!%40%23%24%25%5E%26*()%7B%7D%5B%5D%3D%3A%2F%3B%3F%2B''%22' unescapePercents = '!!@#$%^&*(){}[]=:/;?+''\\\"'.\\n\\tself assert: '%21@%23%24%25%5E%26*%28%29%7B%7D%5B%5D%3D%3A/%3B%3F+%27%22' unescapePercents = '!!@#$%^&*(){}[]=:/;? ''\\\"'! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'ky 7/8/2006 18:01'!\\ntestUnescapePercentsWithTextEncoding\\n\\t| leading kataTe kataSu kataTo |\\n\\tleading := JapaneseEnvironment leadingChar.\\n\\t\\\"Katakana letter Te\\\"\\n\\tkataTe := (Character leadingChar: leading code: 12486) asString.\\n\\t\\\"Katakana letter Su\\\"\\n\\tkataSu := (Character leadingChar: leading code: 12473) asString.\\n\\t\\\"Katakana letter To\\\"\\n\\tkataTo := (Character leadingChar: leading code: 12488) asString.\\n\\tself assert: ('%83e%83X%83g' unescapePercentsWithTextEncoding: 'shift_jis')\\n\\t\\t\\t= (kataTe , kataSu , kataTo).\\n\\tself assert: ('%83e%83X%83g%20and%20%83e%83X%83g' unescapePercentsWithTextEncoding: 'shift_jis')\\n\\t\\t\\t= (kataTe , kataSu , kataTo , ' and ' , kataTe , kataSu , kataTo)! !\\n\\n!StringTest methodsFor: 'tests - converting' stamp: 'sd 6/5/2005 09:27'!\\ntestWithFirstCharacterDownshifted\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := 'MElViN'.\\n\\tlc := 'mElViN'.\\n\\tempty := ' '.\\n\\tself assert: uc withFirstCharacterDownshifted = lc.\\n\\tself assert: lc withFirstCharacterDownshifted = lc.\\n\\t\\\"the string gets copied\\\"\\n\\tself deny: lc withFirstCharacterDownshifted == lc.\\n\\tself deny: empty withFirstCharacterDownshifted == empty.! !\\n\\n\\n!StringTest methodsFor: 'as yet unclassified' stamp: 'md 3/16/2006 22:12'!\\ntestEquality\\n\\n\\tself assert: 'abc' = 'abc' asWideString.\\n\\tself assert: 'abc' asWideString = 'abc'.\\n\\tself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString ~= 'a000' asWideString).\\n\\tself assert: ('a000' asWideString ~= (ByteArray with: 97 with: 0 with: 0 with: 0) asString).\\n\\n\\tself assert: ('abc' sameAs: 'aBc' asWideString).\\n\\tself assert: ('aBc' asWideString sameAs: 'abc').\\n\\tself assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString \\n\\t\\t\\t\\t\\t\\tsameAs: 'Abcd' asWideString) not.\\n\\tself assert: ('a000' asWideString sameAs: \\n\\t\\t\\t\\t\\t(ByteArray with: 97 with: 0 with: 0 with: 0) asString) not.! !\\n\\n\\n!StringTest methodsFor: 'test-comparing' stamp: 'lr 7/7/2006 11:32'!\\ntestComparing\\n\\tself assert: 'foo' < 'foo:'.\\n\\tself assert: 'foo' < 'fooBar'.\\n\\tself assert: 'foo' <= 'foo:'.\\n\\tself assert: 'foo' <= 'fooBar'.\\n\\tself assert: 'foo:' > 'foo'.\\n\\tself assert: 'fooBar' > 'foo'.\\n\\tself assert: 'foo:' >= 'foo'.\\n\\tself assert: 'fooBar' >= 'foo'! !\\n\\n\\n!StringTest methodsFor: 'testing - converting' stamp: 'KR 06/24/2005 11:21'!\\ntestPercentEncodingJa\\n\\t| leading hiraA hiraO hiraAO encodedHiraA encodedHiraO encodedHiraAO |\\n\\n \\\"Make Japanese String from unicode. see http://www.unicode.org/charts/PDF/U3040.pdf\\\"\\n leading _ JapaneseEnvironment leadingChar.\\n\\thiraA _ (Character leadingChar: leading code: 16r3042) asString. \\\"HIRAGANA LETTER A\\\"\\n\\thiraO _ (Character leadingChar: leading code: 16r304A) asString. \\\"HIRAGANA LETTER O\\\"\\n\\thiraAO _ hiraA, hiraO.\\n\\n\\t\\\"Percent Encoded Japanese String\\\"\\n\\tencodedHiraA _ hiraA encodeForHTTP.\\n\\tself assert: encodedHiraA = '%E3%81%82'.\\n\\tencodedHiraO _ hiraO encodeForHTTP.\\n\\tself assert: encodedHiraO = '%E3%81%8A'.\\n\\tencodedHiraAO _ hiraAO encodeForHTTP.\\n\\tself assert: encodedHiraAO = '%E3%81%82%E3%81%8A'.\\n\\n \\\"without percent encoded string\\\"\\n\\tself assert: '' unescapePercents = ''.\\n\\tself assert: 'abc' unescapePercents = 'abc'.\\t\\\"latin1 character\\\"\\n\\tself assert: hiraAO unescapePercents = hiraAO. \\\"multibyte character\\\"\\n\\n\\t\\\"encoded latin1 string\\\"\\n\\tself assert: '%61' unescapePercents = 'a'.\\n\\tself assert: '%61%62%63' unescapePercents = 'abc'.\\n\\n\\t\\\"encoded multibyte string\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: encodedHiraA unescapePercents = hiraA.\\n\\t\\tself assert: encodedHiraAO unescapePercents = hiraAO].\\n\\n\\t\\\"mixed string\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: (encodedHiraAO,'a') unescapePercents = (hiraAO, 'a').\\n\\t\\tself assert: ('a', encodedHiraA) unescapePercents = ('a', hiraA).\\n\\t\\tself assert: ('a', encodedHiraA, 'b') unescapePercents = ('a', hiraA, 'b').\\n\\t\\tself assert: ('a', encodedHiraA, 'b', encodedHiraO) unescapePercents = ('a', hiraA, 'b', hiraO).\\n\\t\\tself assert: (encodedHiraA, encodedHiraO, 'b', encodedHiraA) unescapePercents = (hiraA, hiraO, 'b', hiraA)].\\n\\n\\n\\t\\\"for Seaside\\\"\\n\\tLocale currentPlatform: (Locale isoLanguage: 'ja') during: [ \\n\\t\\tself assert: (encodedHiraA, '+', encodedHiraO) unescapePercents = (hiraA, ' ', hiraO)].\\n\\n! !\\n\\n\\n!StringTest methodsFor: 'tests - indexOf' stamp: 'nice 5/9/2006 23:55'!\\ntestIndexOf\\n\\t\\n\\t\\\"test for http://bugs.impara.de/view.php?id=3574\\\"\\n\\tself assert: ('abc-' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 4.\\n\\tself assert: ('ab7' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 3.\\n\\tself assert: ('a2c' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 2.\\n\\tself assert: ('3bc' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 1.\\n\\tself assert: ('abc' asWideString indexOfAnyOf: (CharacterSet newFrom: ' -0123456789')) = 0.\\n\\t\\n\\t\\\"extension to wide characters\\\"\\n\\tself assert: ((String with: 803 asCharacter with: 811 asCharacter) indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: 812 asCharacter))) = 2.\\n\\t\\n\\tself assert: ('abc' indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: 812 asCharacter))) = 0.\\n\\t\\n\\tself assert: ('abc' indexOfAnyOf: (CharacterSet newFrom: (String with: 811 asCharacter with: $c))) = 3.! !\\nDataType subclass: #StringType\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n\\n!StringType methodsFor: 'initial value' stamp: 'sw 9/27/2001 17:29'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ 'abc'! !\\n\\n\\n!StringType methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:39'!\\ninitialize\\n\\t\\\"Initialize the receiver (automatically called when instances are created via 'new')\\\"\\n\\n\\t| aMethodCategory aMethodInterface |\\n\\tsuper initialize.\\n\\tself vocabularyName: #String.\\n\\n#((accessing \\t\\t\\t'The basic info'\\n\\t\\t(at: at:put: size endsWithDigit findString: findTokens: includesSubString: indexOf: indexOf:startingAt: indexOf:startingAt:ifAbsent: lineCorrespondingToIndex: lineCount lineNumber: startsWithDigit numArgs))\\n(#'more accessing' \\t\\t'More basic info'\\n\\t\\t(allButFirst allButFirst: allButLast allButLast: at:ifAbsent: atAllPut: atPin: atRandom: atWrap: atWrap:put: fifth first first: fourth from:to:put: last last: lastIndexOf: lastIndexOf:ifAbsent: middle replaceAll:with: replaceFrom:to:with: replaceFrom:to:with:startingAt: second sixth third))\\n(comparing\\t\\t\\t\\t'Determining which comes first alphabeticly'\\n\\t\\t(< <= = > >= beginsWith: endsWith: endsWithAnyOf: howManyMatch: match:))\\n(testing \\t\\t\\t\\t'Testing'\\n\\t\\t(includes: isEmpty ifNil: ifNotNil: isAllDigits isAllSeparators isString lastSpacePosition))\\n(converting \\t\\t\\t'Converting it to another form'\\n\\t\\t(asCharacter asDate asInteger asLowercase asNumber asString asStringOrText asSymbol asText asTime asUppercase asUrl capitalized keywords numericSuffix romanNumber reversed splitInteger surroundedBySingleQuotes withBlanksTrimmed withSeparatorsCompacted withoutTrailingBlanks withoutTrailingDigits asSortedCollection))\\n(copying \\t\\t\\t\\t'Make another one like me'\\n\\t\\t(copy copyFrom:to: copyUpTo: copyUpToLast: shuffled))\\n(enumerating\\t\\t'Passing over the letters'\\n\\t\\t(collect: collectWithIndex: do: from:to:do: reverseDo: select: withIndexDo: detect: detect:ifNone:))\\n) do: [:item | \\n\\t\\t\\taMethodCategory := ElementCategory new categoryName: item first.\\n\\t\\t\\taMethodCategory documentation: item second.\\n\\t\\t\\titem third do:\\n\\t\\t\\t\\t[:aSelector | \\n\\t\\t\\t\\t\\taMethodInterface := MethodInterface new initializeFor: aSelector.\\n\\t\\t\\t\\t\\tself atKey: aSelector putMethodInterface: aMethodInterface.\\n\\t\\t\\t\\t\\taMethodCategory elementAt: aSelector put: aMethodInterface].\\n\\t\\t\\tself addCategory: aMethodCategory].\\n! !\\n\\n\\n!StringType methodsFor: '*eToys-color' stamp: 'sw 9/27/2001 17:21'!\\ntypeColor\\n\\t\\\"Answer the color for tiles to be associated with objects of this type\\\"\\n\\n\\t^ self subduedColorFromTriplet: #(0.0 0.0 1.0)\\t! !\\n\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'yo 3/14/2005 21:27'!\\ndefaultArgumentTile\\n \\\"Answer a tile to represent the type\\\"\\n\\n ^ 'abc' translated newTileMorphRepresentative typeColor: self typeColor! !\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nsetFormatForDisplayer: aDisplayer\\n\\t\\\"Set up the displayer to have the right format characteristics\\\"\\n\\n\\taDisplayer useStringFormat\\n\\t! !\\n\\n!StringType methodsFor: '*eToys-tiles' stamp: 'sw 9/27/2001 17:33'!\\nwantsArrowsOnTiles\\n\\t\\\"Answer whether this data type wants up/down arrows on tiles representing its values\\\"\\n\\n\\t^ false! !\\nMorph subclass: #SubpaneDividerMorph\\n\\tinstanceVariableNames: 'resizingEdge'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Windows'!\\n!SubpaneDividerMorph commentStamp: '<historical>' prior: 0!\\nA morph which presents a visible separator between subpanes of a SystemWindow which have zero edgeWidth. Subpanes are submorphs of a SystemWindow's paneMorphs.\\n\\nA SubpaneDividerMorph may also initiate reframe handles for the subpanes. For resizing, it is expected that the main paneMorph has a ProportionalLayout LayoutPolicy, and that the subpanes to be resized have LayoutFrames with equal topFractions and bottomFractions, but different topOffsets and bottomOffsets. It is the offsets that are changed, and the change is propagated through sibling morphs up to the first resizable morph (with different nominal frame fractions).\\n\\nThe direction of propagation is determined by the value of resizingEdge, which is one of: nil (for non-adjustible subpane divisions), #bottom or #top (which acts a though the divider is the corresponding edge of the subpane directly above or below it). Does not currently support #left or #right binding, or subpanes in a TableLayout.\\n!\\n\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'sw 5/18/2001 11:27'!\\nborderColor\\n\\t\\\"I behave like a border for the purpose of browser beautifying, so I obey this protocol, to advantage\\\"\\n\\n\\t^ self color! !\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'sw 5/18/2001 11:26'!\\nborderColor: aColor\\n\\t\\\"I behave like a border for the purpose of browser beautifying, so I obey this protocol, to advantage\\\"\\n\\n\\tself color: aColor! !\\n\\n!SubpaneDividerMorph methodsFor: 'accessing' stamp: 'JW 2/3/2001 09:39'!\\nresizingEdge\\n\\n\\t^resizingEdge\\n! !\\n\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:53'!\\ndefaultColor\\n\\\"answer the default color/fill style for the receiver\\\"\\n\\t^ Color black! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:26'!\\nfirstEnter: evt\\n\\t\\\"The first time this divider is activated, find its window and redirect further interaction there.\\\"\\n\\t| window |\\n\\n\\twindow := self firstOwnerSuchThat: [:m | m respondsTo: #secondaryPaneTransition:divider:].\\n\\twindow ifNil: [ self suspendEventHandler. ^ self ]. \\\"not working out\\\"\\n\\twindow secondaryPaneTransition: evt divider: self.\\n\\tself on: #mouseEnter send: #secondaryPaneTransition:divider: to: window.\\n! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:07'!\\nhorizontal\\n\\n\\tself hResizing: #spaceFill.! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'dgd 3/7/2003 14:53'!\\ninitialize\\n\\t\\\"initialize the state of the receiver\\\"\\n\\tsuper initialize.\\n\\t\\\"\\\"\\n\\tself extent: 1 @ 1! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:12'!\\nresizingEdge: edgeSymbol\\n\\n\\t(#(top bottom) includes: edgeSymbol) ifFalse:\\n\\t\\t[ self error: 'resizingEdge must be #top or #bottom' ].\\n\\tresizingEdge := edgeSymbol.\\n\\tself on: #mouseEnter send: #firstEnter: to: self.\\n! !\\n\\n!SubpaneDividerMorph methodsFor: 'initialization' stamp: 'JW 2/3/2001 09:07'!\\nvertical\\n\\n\\tself vResizing: #spaceFill.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSubpaneDividerMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:35'!\\nforBottomEdge\\n\\t^self new horizontal resizingEdge: #bottom! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:35'!\\nforTopEdge\\n\\t^self new horizontal resizingEdge: #top! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:31'!\\nhorizontal\\n\\t^self new horizontal! !\\n\\n!SubpaneDividerMorph class methodsFor: 'instance creation' stamp: 'JW 2/3/2001 09:31'!\\nvertical\\n\\t^self new vertical! !\\nObject subclass: #SunAudioFileWriter\\n\\tinstanceVariableNames: 'stream headerStart'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Sound-Synthesis'!\\n!SunAudioFileWriter commentStamp: '<historical>' prior: 0!\\nI encode monophonic sampled sounds in Sun audio (.au) file format. Sun audio files have a very simple format but can store both compressed and uncompressed sample data. I can write this format either directly into a file or onto any writable binary stream.\\n!\\n\\n\\n!SunAudioFileWriter methodsFor: 'initialization' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nsetStream: aBinaryStream\\n\\t\\\"Initialize myself for writing on the given stream.\\\"\\n\\n\\tstream := aBinaryStream.\\n\\theaderStart := aBinaryStream position.\\n! !\\n\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 18:02'!\\nappendBytes: aByteArray\\n\\t\\\"Append the given sample data to my stream.\\\"\\n\\n\\tstream nextPutAll: aByteArray.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nappendSamples: aSoundBuffer\\n\\t\\\"Append the given SoundBuffer to my stream.\\\"\\n\\n\\t| swapBytes s |\\n\\t(stream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\t\\\"optimization: write sound buffer directly to file\\\"\\n\\t\\tswapBytes := SmalltalkImage current isLittleEndian.\\n\\t\\tswapBytes ifTrue: [aSoundBuffer reverseEndianness]. \\\"make big endian\\\"\\n\\t\\tstream next: (aSoundBuffer size // 2) putAll: aSoundBuffer startingAt: 1. \\\"size in words\\\"\\n\\t\\tswapBytes ifTrue: [aSoundBuffer reverseEndianness]. \\\"revert to little endian\\\"\\n\\t\\t^ self].\\n\\n\\t\\\"for non-file streams:\\\"\\n\\ts := WriteStream on: (ByteArray new: 2 * aSoundBuffer monoSampleCount).\\n\\t1 to: aSoundBuffer monoSampleCount do: [:i | s int16: (aSoundBuffer at: i)].\\n\\tself appendBytes: s contents.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 22:09'!\\ncloseFile\\n\\t\\\"Update the Sun audio file header to reflect the final size of the sound data. If my stream is a file stream, close it and, on a Macintosh, set the file type and creator to that used by SoundApp for Sun Audio files. (This does nothing on other platforms.)\\\"\\n\\n\\tself ensureOpen.\\n\\tself updateHeaderDataSize.\\n\\t(stream isKindOf: StandardFileStream) ifTrue: [\\n\\t\\tstream close.\\n\\t\\tFileDirectory default setMacFileNamed: stream name type: 'ULAW' creator: 'SCPL'].\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'sd 1/30/2004 15:23'!\\nensureOpen\\n\\t\\\"Ensure that my stream is open.\\\"\\n\\n\\tstream closed ifTrue: [stream reopen; binary].\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nupdateHeaderDataSize\\n\\t\\\"Update the Sun audio file header to reflect the final size of the sound data.\\\"\\n\\n\\t| byteCount |\\n\\tbyteCount := stream position - (headerStart + 24).\\n\\tstream position: headerStart + 8.\\n\\tstream uint32: byteCount.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 17:55'!\\nwriteHeaderSamplingRate: samplingRate\\n\\t\\\"Write a Sun audio file header for 16-bit linear format.\\\"\\n\\n\\tself writeHeaderSamplingRate: samplingRate format: 3.\\n! !\\n\\n!SunAudioFileWriter methodsFor: 'other' stamp: 'jm 11/16/2001 22:10'!\\nwriteHeaderSamplingRate: samplingRate format: audioFormat\\n\\t\\\"Write a Sun audio file header for the given sampling rate and format. Currently, only monophonic files are supported.\\\"\\n\\n\\tself ensureOpen.\\n\\tstream position: headerStart.\\n\\tstream nextPutAll: '.snd' asByteArray.\\n\\tstream uint32: 24.\\t\\\"header size in bytes\\\"\\n\\tstream uint32: 0.\\t\\\"sample data size in bytes; fill in later\\\"\\n\\tstream uint32: audioFormat.\\n\\tstream uint32: samplingRate truncated.\\n\\tstream uint32: 1.\\t\\\"channel count\\\"\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSunAudioFileWriter class\\n\\tinstanceVariableNames: ''!\\n\\n!SunAudioFileWriter class methodsFor: 'instance creation' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nonFileNamed: fileName\\n\\t\\\"Answer an instance of me on a newly created file with the given name.\\\"\\n\\n\\t| file |\\n\\tfile := (FileStream newFileNamed: fileName) binary.\\n\\t^ self new setStream: file\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'instance creation' stamp: 'jm 11/16/2001 17:50'!\\nonStream: aBinaryStream\\n\\t\\\"Answer an instance of me on the given binary stream.\\\"\\n\\n\\t^ self new setStream: aBinaryStream\\n! !\\n\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'jm 11/21/2001 15:42'!\\ncodecForFormatCode: formatCode\\n\\t\\\"Answer the codec for the given Sun audio file format number.\\\"\\n\\n\\tformatCode = 1 ifTrue: [^ MuLawCodec new].\\n\\tformatCode = 3 ifTrue: [^ nil]. \\\"uncompressed\\\"\\n\\tformatCode = 23 ifTrue: [^ ADPCMCodec newBitsPerSample: 4].\\n\\tformatCode = 25 ifTrue: [^ ADPCMCodec newBitsPerSample: 3].\\n\\tformatCode = 26 ifTrue: [^ ADPCMCodec newBitsPerSample: 5].\\n\\tformatCode = 610 ifTrue: [^ GSMCodec new].\\n\\tself error: 'unsupported Sun audio format'\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nformatCodeForCompressionType: aString\\n\\t\\\"Answer the Sun audio file format number for the given compression type name.\\\"\\n\\n\\t| lowercase |\\n\\tlowercase := aString asLowercase.\\n\\t'mulaw' = lowercase ifTrue: [^ 1].\\n\\t'none' = lowercase ifTrue: [^ 3].\\n\\t'adpcm3' = lowercase ifTrue: [^ 25].\\n\\t'adpcm4' = lowercase ifTrue: [^ 23].\\n\\t'adpcm5' = lowercase ifTrue: [^ 26].\\n\\t'gsm' = lowercase ifTrue: [^ 610].\\n\\tself error: 'unknown compression style'\\n! !\\n\\n!SunAudioFileWriter class methodsFor: 'sound storing' stamp: 'stephaneducasse 2/4/2006 20:41'!\\nstoreSampledSound: aSampledSound onFileNamed: fileName compressionType: aString\\n\\t\\\"Store the samples of the given sampled sound on a file with the given name using the given type of compression. See formatCodeForCompressionType: for the list of compression types.\\\"\\n\\n\\t| fmt codec f compressed |\\n\\tfmt := self formatCodeForCompressionType: aString.\\n\\tcodec := self codecForFormatCode: fmt.\\n\\tf := self onFileNamed: fileName.\\n\\tf writeHeaderSamplingRate: aSampledSound originalSamplingRate format: fmt.\\n\\tcodec\\n\\t\\tifNil: [f appendSamples: aSampledSound samples]\\n\\t\\tifNotNil: [\\n\\t\\t\\tcompressed := codec encodeSoundBuffer: aSampledSound samples.\\n\\t\\t\\tf appendBytes: compressed].\\n\\tf closeFile.\\n! !\\nFileDirectoryWrapper subclass: #SuperSwikiDirectoryWrapper\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Morphic-Explorer'!\\n!SuperSwikiDirectoryWrapper commentStamp: '<historical>' prior: 0!\\nThe super swiki does not at present have subdirectories!\\n\\n\\n!SuperSwikiDirectoryWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 2/2/2001 08:28'!\\ncontents\\n\\n\\t^#()\\t\\t\\\"we have no sundirectories\\\"! !\\n\\n!SuperSwikiDirectoryWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 2/2/2001 08:28'!\\nhasContents\\n\\n\\t^false\\t\\t\\\"we have no sundirectories\\\"! !\\nProjectSwikiServer subclass: #SuperSwikiServer\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n\\n!SuperSwikiServer methodsFor: 'accessing' stamp: 'KR 2/1/2006 13:07'!\\nencodingName\\n\\t(super encodingName) ifNil: [ ^SuperSwikiServer defaultEncodingName ] ifNotNil: [^super encodingName].! !\\n\\n!SuperSwikiServer methodsFor: 'accessing' stamp: 'mir 6/25/2001 17:17'!\\ntypeForPrefs\\n\\n\\t^'bss'! !\\n\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'mir 8/23/2001 22:15'!\\nallEntries\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: listallprojects'.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [^#()].\\n\\t^self parseListEntries: answer! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'ar 3/2/2001 14:36'!\\ndirectoryNames\\n\\n\\t^self entries select:[:each| each isDirectory] thenCollect: [ :each | each name]! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 2/2/2001 08:29'!\\ndirectoryWrapperClass\\n\\n\\t^SuperSwikiDirectoryWrapper! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'mir 8/23/2001 22:16'!\\nentries\\n\\n\\t^self allEntries! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 21:59'!\\nfastParseEntriesFrom: aString\\n\\n\\t| c first strm xEntryName xCreationTime xModificationTime xIsDirectory xFileSize ch |\\n\\n\\tc _ OrderedCollection new.\\n\\tfirst _ true.\\n\\taString linesDo: [ :x |\\n\\t\\tfirst ifFalse: [\\n\\t\\t\\tstrm _ ReadStream on: x.\\n\\t\\t\\t(strm upTo: $ ) = '(DirectoryEntry' ifFalse: [^nil].\\n\\t\\t\\t(strm upTo: $ ) = 'name:' ifFalse: [^nil].\\n\\t\\t\\txEntryName _ WriteStream on: String new.\\n\\t\\t\\tstrm next = $' ifFalse: [^nil].\\n\\t\\t\\t[\\n\\t\\t\\t\\tch _ strm next.\\n\\t\\t\\t\\tch = $' and: [(strm peekFor: $') not]\\n\\t\\t\\t] whileFalse: [\\n\\t\\t\\t\\txEntryName nextPut: ch.\\n\\t\\t\\t].\\n\\t\\t\\txEntryName _ xEntryName contents.\\n\\t\\t\\tstrm skipSeparators.\\n\\t\\t\\t(strm upTo: $ ) = 'creationTime:' ifFalse: [^nil].\\n\\t\\t\\txCreationTime _ (strm upTo: $ ) asNumber.\\n\\t\\t\\t(strm upTo: $ ) = 'modificationTime:' ifFalse: [^nil].\\n\\t\\t\\txModificationTime _ (strm upTo: $ ) asNumber.\\n\\t\\t\\t(strm upTo: $ ) = 'isDirectory:' ifFalse: [^nil].\\n\\t\\t\\txIsDirectory _ (strm upTo: $ ) = 'true'.\\n\\t\\t\\t(strm upTo: $ ) = 'fileSize:' ifFalse: [^nil].\\n\\t\\t\\txFileSize _ (strm upTo: $ ) asNumber.\\n\\n\\t\\t\\tc add: (DirectoryEntry \\n\\t\\t\\t\\tname: (xEntryName convertFromEncoding: self encodingName)\\n\\t\\t\\t\\tcreationTime: xCreationTime \\n\\t\\t\\t\\tmodificationTime: xModificationTime \\n\\t\\t\\t\\tisDirectory: xIsDirectory \\n\\t\\t\\t\\tfileSize: xFileSize\\n\\t\\t\\t)\\n\\t\\t].\\n\\t\\tfirst _ false.\\n\\t].\\n\\t^c\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'ar 3/2/2001 14:36'!\\nfileNames\\n\\n\\t^self entries select:[:each| each isDirectory not] thenCollect: [ :each | each name]! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/17/2000 12:49'!\\ngetOnly: numberOfBytes from: aName\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',aName.\\n\\t\\t'bytestoread: ',numberOfBytes printString.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [ ^nil].\\n\\t^answer allButFirst: 3\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'md 11/14/2003 17:28'!\\nmatchingEntries: criteria\\n\\t| result |\\n\\teToyUserListUrl ifNil:[^self entries].\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: listmatchingprojects'.\\n\\t} , criteria.\\n\\t(result beginsWith: 'OK')\\n\\t\\tifFalse: [^self entries]. \\\"If command not supported\\\"\\n\\t^self parseListEntries: result! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 22:02'!\\noldFileNamed: aName\\n\\n\\t| answer |\\n\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',aName convertToEncoding: self encodingName.\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [ ^nil].\\n\\t^(SwikiPseudoFileStream with: (answer allButFirst: 3))\\n\\t\\treset;\\n\\t\\tdirectory: self;\\n\\t\\tlocalName: (aName convertToEncoding: self encodingName);\\n\\t\\tyourself\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/17/2000 14:54'!\\noldFileOrNoneNamed: fullName\\n\\n\\t| answer aName |\\n\\n\\tself flag: #bob.\\t\\t\\\"fix this up for full names\\\"\\n\\n\\taName _ fullName.\\n\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t'action: readnamedfile'.\\n\\t\\t'projectname: ',(self localNameFor: aName).\\n\\t}.\\n\\t(answer beginsWith: 'OK') ifFalse: [^nil].\\n\\t^(SwikiPseudoFileStream with: (answer allButFirst: 3))\\n\\t\\treset;\\n\\t\\tdirectory: self;\\n\\t\\tlocalName: aName;\\n\\t\\tyourself\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 1/30/2006 21:57'!\\nputFile: fileStream named: fileNameOnServer\\n\\n\\t\\n\\t^(\\n\\t\\tself sendToSwikiProjectServer: {\\n\\t\\t\\t'uploadproject: ',fileNameOnServer convertToEncoding: self encodingName.\\n\\t\\t\\t'password: ',ProjectPasswordNotification signal.\\n\\t\\t\\tfileStream contentsOfEntireFile.\\n\\t\\t}\\n\\t) beginsWith: 'OK'\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 10/13/2000 16:53'!\\nreadOnlyFileNamed: aName\\n\\n\\t^self oldFileNamed: aName\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'RAA 2/16/2001 18:22'!\\nsendToSwikiProjectServer: anArray\\n\\n\\t| argsDict answer buildStream |\\n\\n\\tbuildStream _ WriteStream on: String new.\\n\\tanArray do: [ :each | \\n\\t\\tbuildStream \\n\\t\\t\\tnextPutAll: each size printString;\\n\\t\\t\\tspace;\\n\\t\\t\\tnextPutAll: each\\n\\t].\\n\\t(argsDict _ Dictionary new)\\n\\t\\tat: 'swikicommands'\\n\\t\\tput: {buildStream contents}.\\n\\tanswer _ HTTPSocket \\n\\t\\thttpPostToSuperSwiki: self url\\n\\t\\targs: argsDict\\n\\t\\taccept: 'application/octet-stream' \\n\\t\\trequest: ''.\\n\\t^(answer isKindOf: MIMEDocument) ifTrue: [answer content] ifFalse: [answer]\\n! !\\n\\n!SuperSwikiServer methodsFor: 'for real' stamp: 'KR 2/20/2006 12:50'!\\nupdateProjectInfoFor: aProject\\n\\n\\t| data details projectLinks linkString uploader |\\n\\n\\tdata _ OrderedCollection new.\\n\\tdata add: 'action: updatepage'.\\n\\tdata add: 'password: ',ProjectPasswordNotification signal.\\n\\tdata add: 'projectimage: ', (aProject name convertToEncoding: self encodingName) , '.gif'.\\n\\tuploader _ Utilities authorNamePerSe.\\n\\tuploader isEmptyOrNil ifTrue: [uploader _ Utilities authorInitialsPerSe].\\n\\tuploader isEmptyOrNil ifFalse: [\\n\\t\\tdata add: ('submittedBy: ',uploader convertToEncoding: self encodingName).\\n\\t].\\n\\tprojectLinks _ Set new.\\n\\taProject world allMorphsDo: [ :each |\\n\\t\\t(each isKindOf: ProjectViewMorph) ifTrue: [\\n\\t\\t\\tprojectLinks add: each safeProjectName.\\n\\t\\t].\\n\\t].\\n\\tdetails _ aProject world valueOfProperty: #ProjectDetails ifAbsent: [Dictionary new].\\n\\tdetails at: 'projectname' ifAbsentPut: [aProject name].\\n\\tprojectLinks isEmpty ifTrue: [\\n\\t\\tdetails removeKey: 'projectlinks' ifAbsent: []\\n\\t] ifFalse: [\\n\\t\\tlinkString _ String streamContents: [ :strm |\\n\\t\\t\\tprojectLinks asSortedCollection do: [ :each |\\n\\t\\t\\t\\tstrm nextPutAll: each\\n\\t\\t\\t] separatedBy: [\\n\\t\\t\\t\\tstrm nextPut: $.\\n\\t\\t\\t].\\n\\t\\t].\\n\\t\\tdetails at: 'projectlinks' put: linkString\\n\\t].\\n\\tdetails keysAndValuesDo: [ :k :v |\\n\\t\\tdata add: k , ': ' , (v convertToEncoding: self encodingName). self flag: #yoFlag.\\n\\t].\\n\\t^self sendToSwikiProjectServer: data! !\\n\\n\\n\\n!SuperSwikiServer methodsFor: 'squeaklets' stamp: 'KR 1/30/2006 22:15'!\\nupLoadProject: projectName members: archiveMembers retry: aBool\\n\\t| answer |\\n\\tarchiveMembers do:[:entry|\\n\\t\\tProgressNotification signal: '4:uploadingFile' extra:'(uploading ' translated, entry fileName convertFromSystemString , '...)' translated.\\n\\t\\tanswer _ self sendToSwikiProjectServer: {\\n\\t\\t\\t'uploadproject2: ', entry fileName convertFromSystemString convertToEncoding: self encodingName.\\n\\t\\t\\t'password: ',ProjectPasswordNotification signal.\\n\\t\\t\\tentry contents.\\n\\t\\t}.\\n\\t\\tanswer = 'OK' ifFalse:[\\n\\t\\t\\tself inform:'Server responded ' translated, answer.\\n\\t\\t\\t^false].\\n\\t].\\n\\tProgressNotification signal: '4:uploadingFile' extra:''.\\n\\t^true! !\\n\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'mir 11/14/2001 16:25'!\\nisSearchable\\n\\t^true! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'ar 8/24/2001 15:12'!\\nparseQueryResult: resultStream\\n\\n\\t| projectInfos projectName downloadUrl |\\n\\tprojectInfos _ OrderedCollection new.\\n\\tdownloadUrl _ self downloadUrl.\\n\\tresultStream reset; nextLine.\\n\\t[resultStream atEnd] whileFalse: [\\n\\t\\tprojectName _ resultStream nextLine.\\n\\t\\tprojectInfos add: projectName.\\n\\t\\t\\\"Transcript show: projectName; cr.\\\"\\n\\t\\t].\\n\\t\\\"Transcript show: 'done'; cr.\\\"\\n\\t^projectInfos\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/17/2000 16:10'!\\nqueryAllProjects\\n\\n\\\"answer a collection of DirectoryEntry objects for each file on server\\\"\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki queryAllProjects\\\"\\n\\n\\t^self sendToSwikiProjectServer: {\\n\\t\\t'action: listallprojects'.\\n\\t}! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'md 11/14/2003 17:28'!\\nqueryProjects: criteria\\n\\t| result |\\n\\t\\\"SuperSwikiServer defaultSuperSwiki queryProjects: #('submittedBy: mir' )\\\"\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t} , criteria.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\t^self parseQueryResult: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/17/2000 19:23'!\\nqueryProjectsAndShow\\n\\t| result |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t\\t\\\"'projectname: *proj*'.\\\"\\n\\t}.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\tself showQueryAsPVM: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/18/2000 12:23'!\\nqueryProjectsAndShow: thingsToSearchFor\\n\\t| result |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresult _ self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t}, thingsToSearchFor.\\n\\t(result beginsWith: 'OK') ifFalse: [^self inform: result printString].\\n\\tself showQueryAsPVM: (ReadStream on: result).\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/12/2000 17:01'!\\nqueryPythagoras\\n\\\"SuperSwikiServer testOnlySuperSwiki queryPythagoras\\\"\\n\\n\\t^self sendToSwikiProjectServer: {\\n\\t\\t'action: findproject'.\\n\\t\\t'projectsubcategory: *geometry*'.\\n\\t\\t\\\"'projectname: *pythagoras*'.\\\"\\n\\t}! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'KR 1/30/2006 21:59'!\\nshowQueryAsPVM: resultStream\\n\\t| answer gif whatToShow projectName fileName firstURL wrapper currX currY maxX maxY rawProjectName |\\n\\\"SuperSwikiServer testOnlySuperSwiki queryProjectsAndShow\\\"\\n\\n\\tresultStream reset; nextLine.\\n\\tanswer _ RectangleMorph new\\n\\t\\tuseRoundedCorners;\\n\\t\\tborderWidth: 0;\\n\\t\\tborderColor: Color blue;\\n\\t\\tcolor: Color paleBlue.\\n\\tcurrX _ currY _ maxX _ maxY _ 10.\\n\\t[resultStream atEnd] whileFalse: [\\n\\t\\trawProjectName _ resultStream nextLine.\\n\\t\\tprojectName _ rawProjectName convertFromEncoding: self encodingName.\\n\\t\\tfileName _ resultStream nextLine convertFromEncoding: self encodingName.\\n\\t\\tgif _ self oldFileOrNoneNamed: rawProjectName,'.gif'.\\n\\t\\tgif ifNotNil: [gif _ GIFReadWriter formFromStream: gif].\\n\\t\\tcurrX > 600 ifTrue: [\\n\\t\\t\\tcurrX _ 10.\\n\\t\\t\\tcurrY _ maxY + 10.\\n\\t\\t].\\n\\t\\tgif ifNil: [\\n\\t\\t\\tgif _ AlignmentMorph newColumn\\n\\t\\t\\t\\thResizing: #shrinkWrap;\\n\\t\\t\\t\\tvResizing: #shrinkWrap;\\n\\t\\t\\t\\tborderWidth: 8;\\n\\t\\t\\t\\tborderColor: Color red;\\n\\t\\t\\t\\tcolor: Color lightRed;\\n\\t\\t\\t\\taddMorph: (StringMorph contents: 'No GIF for ',projectName);\\n\\t\\t\\t\\tfullBounds;\\n\\t\\t\\t\\timageForm\\n\\t\\t].\\n\\t\\tfirstURL _ self url.\\n\\t\\tfirstURL last == $/ ifFalse: [firstURL _ firstURL, '/'].\\n\\n\\t\\twhatToShow _ ProjectViewMorph new\\n\\t\\t\\timage: (gif asFormOfDepth: Display depth);\\n\\t\\t\\tlastProjectThumbnail: gif;\\n\\t\\t\\tsetProperty: #SafeProjectName toValue: projectName;\\n\\t\\t\\tproject: (DiskProxy \\n\\t\\t\\t\\tglobal: #Project \\n\\t\\t\\t\\tselector: #namedUrl: \\n\\t\\t\\t\\targs: {firstURL,fileName}\\n\\t\\t\\t).\\n\\n\\t\\tanswer addMorphBack: (whatToShow position: currX @ currY).\\n\\t\\tcurrX _ currX + whatToShow width + 10.\\n\\t\\tmaxX _ maxX max: currX.\\n\\t\\tmaxY _ maxY max: currY + whatToShow height.\\n\\t].\\n\\tmaxX = 10 ifTrue: [\\n\\t\\t^self inform: 'No projects found for your criteria'\\n\\t].\\n\\tanswer extent: (maxX @ maxY) + (0@10).\\n\\twrapper _ ScrollPane new extent: (answer width + 10) @ (answer height min: 400).\\n\\twrapper color: Color white.\\n\\twrapper scroller addMorph: answer.\\n\\twrapper \\n\\t\\tbecomeModal;\\n\\t\\topenCenteredInWorld;\\n\\t\\tuseRoundedCorners;\\n\\t\\tsetScrollDeltas.! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/25/2000 12:14'!\\nspeedTest1\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki speedTest1\\\"\\n\\n\\t| answer t totalTime |\\n\\n\\ttotalTime _ [\\n\\t\\tanswer _ (1 to: 10) collect: [ :x |\\n\\t\\t\\tt _ [answer _ self sendToSwikiProjectServer: {\\n\\t\\t\\t\\t'action: readnamedfile'.\\n\\t\\t\\t\\t'projectname: xyz.002.pr'.\\n\\t\\t\\t}] timeToRun.\\n\\t\\t\\t{t. answer size}\\n\\t\\t].\\n\\t] timeToRun.\\n\\t^{totalTime. answer}\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'ar 7/8/2001 17:06'!\\nspeedTest2\\n\\n\\\"SuperSwikiServer testOnlySuperSwiki speedTest2\\\"\\n\\n\\\"==observed results\\n10 forks of 10 reads of 88K in 12.7 seconds\\n100 * 88110 / 12.7 ===> 693779 bytes per second\\n---\\n10 forks of 10 reads of 88K in 10.7 seconds\\n100 * 88110 / 10.7 ===> 823457 bytes per second\\n---at priority 5\\n10 forks of 10 reads of 88K in 9.8 seconds\\n100 * 88110 / 9.8 ===> 899081 bytes per second\\n===\\\"\\n\\n\\t| answer bigAnswer tRealBegin tRealEnd |\\n\\n\\tbigAnswer _ SharedQueue new.\\n\\ttRealBegin _ tRealEnd _ Time millisecondClockValue.\\n\\t10 timesRepeat: [\\n\\t\\t[\\n\\t\\t\\tanswer _ SuperSwikiServer testOnlySuperSwiki speedTest1.\\n\\t\\t\\ttRealEnd _ Time millisecondClockValue.\\n\\t\\t\\tbigAnswer nextPut: {\\n\\t\\t\\t\\t{tRealBegin. tRealEnd. tRealEnd - tRealBegin}.\\n\\t\\t\\t\\tanswer\\n\\t\\t\\t}.\\n\\t\\t] forkAt: Processor userInterruptPriority.\\n\\t].\\n\\tbigAnswer inspect.\\n! !\\n\\n!SuperSwikiServer methodsFor: 'testing' stamp: 'RAA 10/7/2000 16:12'!\\ntest1\\n\\n\\t| localDirectory localFileName local resp |\\n\\n\\tlocalDirectory _ FileDirectory default.\\n\\tlocalFileName _ 'superTest1.07Oct1611.cs'.\\n\\tlocal _ localDirectory oldFileNamed: localFileName.\\n\\tresp _ self putFile: local named: localFileName retry: false.\\n\\tlocal close.\\n\\t^resp\\n! !\\n\\n\\n!SuperSwikiServer methodsFor: 'private' stamp: 'mir 8/23/2001 22:04'!\\nparseListEntries: listResult\\n\\n\\t| c first |\\n\\tc _ self fastParseEntriesFrom: listResult.\\n\\tc ifNotNil: [^c].\\n\\tc _ OrderedCollection new.\\n\\tfirst _ true.\\n\\tlistResult linesDo: [ :x |\\n\\t\\tfirst ifFalse: [c add: (Compiler evaluate: x)].\\n\\t\\tfirst _ false.\\n\\t].\\n\\t^c\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSuperSwikiServer class\\n\\tinstanceVariableNames: ''!\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/7/2000 17:47'!\\ncurrentSuperSwiki\\n\\n\\t\\\"make this return nil to disable SuperSwiki hack\\\"\\n\\n\\t^self defaultSuperSwiki\\n\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'KR 2/1/2006 13:18'!\\ndefaultEncodingName\\n\\tLocale current isoLanguage = 'ja' ifTrue: [^'shift_jis' copy] ifFalse: [^'latin1' copy].\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 19:11'!\\ndefaultSuperSwiki\\n\\n\\t^SuperSwikiServer new \\n\\t\\ttype: #http;\\n\\t\\tserver: self defaultSuperSwikiIPAddress;\\n\\t\\tdirectory: '/super/SuperSwikiProj'\\n\\t\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/19/2000 11:05'!\\ndefaultSuperSwikiIPAddress\\n\\n\\t^'209.143.91.36'\\n! !\\n\\n!SuperSwikiServer class methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 19:11'!\\ntestOnlySuperSwiki\\n\\n\\t^SuperSwikiServer new \\n\\t\\ttype: #http;\\n\\t\\tserver: self defaultSuperSwikiIPAddress;\\n\\t\\tdirectory: '/super/SuperSwikiProj'\\n\\t\\n! !\\nRWBinaryOrTextStream subclass: #SwikiPseudoFileStream\\n\\tinstanceVariableNames: 'directoryUrl localName directory'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Network-RemoteDirectory'!\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:53'!\\ndirectory\\n\\n\\t^directory url! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:53'!\\ndirectory: x\\n\\n\\tdirectory _ x! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 15:00'!\\ndirectoryObject\\n\\n\\t^directory! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 15:00'!\\ndirectoryUrl\\n\\n\\t^directory url! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\ndirectoryUrl: x\\n\\n\\tdirectoryUrl _ x! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 13:59'!\\nfileName\\n\\n\\t^localName! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/17/2000 14:01'!\\nisTypeHTTP\\n\\n\\t^true! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\nlocalName\\n\\n\\t^localName! !\\n\\n!SwikiPseudoFileStream methodsFor: 'as yet unclassified' stamp: 'RAA 10/13/2000 11:50'!\\nlocalName: x\\n\\n\\tlocalName _ x! !\\nModel subclass: #Switch\\n\\tinstanceVariableNames: 'on onAction offAction'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'ST80-Menus'!\\n!Switch commentStamp: '<historical>' prior: 0!\\nI 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.\\n1/24/96 sw: made this a subclass of Model, for faster dependents handling!\\n\\n\\n!Switch methodsFor: 'action'!\\ndoAction: anAction \\n\\t\\\"Execute anAction if it is non-nil.\\\"\\n\\n\\tanAction == nil ifFalse: [anAction value]! !\\n\\n!Switch methodsFor: 'action'!\\noffAction: anAction \\n\\t\\\"Set the off action of the receiver to anAction.\\\"\\n\\n\\toffAction _ anAction fixTemps! !\\n\\n!Switch methodsFor: 'action'!\\nonAction: anAction \\n\\t\\\"Set the on action of the receiver to anAction.\\\"\\n\\n\\tonAction _ anAction fixTemps! !\\n\\n\\n!Switch methodsFor: 'converting' stamp: 'md 9/18/2004 19:51'!\\nprintOn: aStream\\n\\tself isOn\\n\\t\\tifTrue: [aStream nextPutAll: 'ON-Switch']\\n\\t\\tifFalse: [aStream nextPutAll: 'OFF-Switch']! !\\n\\n\\n!Switch methodsFor: 'state'!\\nclear\\n\\t\\\"Set the state of the receiver to 'off'. If the state of the receiver was \\n\\tpreviously 'on', then 'self change' is sent. The receiver's off action is \\n\\tNOT executed.\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ false.\\n\\t\\t\\tself changed]! !\\n\\n!Switch methodsFor: 'state'!\\nisOff\\n\\t\\\"Answer whether the receiver is set off or not.\\\"\\n\\n\\t^on not! !\\n\\n!Switch methodsFor: 'state'!\\nisOn\\n\\t\\\"Answer whether the receiver is set on or not.\\\"\\n\\n\\t^on! !\\n\\n!Switch methodsFor: 'state'!\\nset\\n\\t\\\"Set the state of the receiver to 'on'. If the state of the receiver was \\n\\tpreviously 'off', then 'self change' is sent. The receiver's on action is \\n\\tNOT executed.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed]! !\\n\\n!Switch methodsFor: 'state'!\\nswitch\\n\\t\\\"Change the state of the receiver from 'on' to 'off' or from 'off' to 'on' (see \\n\\tSwitch|turnOn, Switch|turnOff).\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: [self turnOff]\\n\\t\\tifFalse: [self turnOn]! !\\n\\n!Switch methodsFor: 'state'!\\nturnOff\\n\\t\\\"Set the state of the receiver to 'off'. If the state of the receiver was \\n\\tpreviously 'on', then 'self change' is sent and the receiver's off action is \\n\\texecuted.\\\"\\n\\n\\tself isOn\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ false.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself doAction: offAction]! !\\n\\n!Switch methodsFor: 'state'!\\nturnOn\\n\\t\\\"Set the state of the receiver to 'on'. If the state of the receiver was \\n\\tpreviously 'off', then 'self change' is sent and the receiver's on action is \\n\\texecuted.\\\"\\n\\n\\tself isOff\\n\\t\\tifTrue: \\n\\t\\t\\t[on _ true.\\n\\t\\t\\tself changed.\\n\\t\\t\\tself doAction: onAction]! !\\n\\n\\n!Switch methodsFor: 'private'!\\ninitializeOff\\n\\n\\ton _ false. \\n\\tonAction _ nil.\\n\\toffAction _ nil! !\\n\\n!Switch methodsFor: 'private'!\\ninitializeOn\\n\\n\\ton _ true. \\n\\tonAction _ nil.\\n\\toffAction _ nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSwitch class\\n\\tinstanceVariableNames: ''!\\n\\n!Switch class methodsFor: 'instance creation'!\\nnew\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil\\n\\t('no action'), and the state is set to 'off'.\\\"\\n\\n\\t^self newOff! !\\n\\n!Switch class methodsFor: 'instance creation'!\\nnewOff\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil \\n\\t('no action'), and the state is set to 'off'.\\\"\\n\\n\\t^super new initializeOff! !\\n\\n!Switch class methodsFor: 'instance creation'!\\nnewOn\\n\\t\\\"Answer an instance of me such that the on and off actions are set to nil \\n\\t('no action'), and the state is set to 'on'.\\\"\\n\\n\\t^super new initializeOn! !\\nObject subclass: #Syllable\\n\\tinstanceVariableNames: 'phonemes accent events'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Speech-TTS'!\\n!Syllable commentStamp: '<historical>' prior: 0!\\nMy instances are syllables. They can carry a pitch accent: 'H*', 'L*', etc.!\\n\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/11/1999 13:03'!\\naccent\\n\\t^ accent! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\naccent: aString\\n\\taccent := aString! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 17:47'!\\naccept: anObject\\n\\tanObject syllable: self! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nevents\\n\\t^ events ifNil: [events := CompositeEvent new addAll: (self phonemes collect: [ :each | PhoneticEvent new phoneme: each; duration: 0.080]); yourself]! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 02:55'!\\nphonemes\\n\\t^ phonemes! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nphonemes: aCollection\\n\\tphonemes := aCollection! !\\n\\n!Syllable methodsFor: 'accessing' stamp: 'len 12/8/1999 02:54'!\\nstress\\n\\tself phonemes do: [ :each | each stress > 0 ifTrue: [^ each stress]].\\n\\t^ 0! !\\n\\n\\n!Syllable methodsFor: 'enumarating' stamp: 'len 12/13/1999 01:20'!\\neventsDo: aBlock\\n\\tself events do: aBlock! !\\n\\n\\n!Syllable methodsFor: 'printing' stamp: 'stephaneducasse 2/3/2006 22:23'!\\nprintOn: aStream\\n\\t| first |\\n\\taStream nextPut: $[.\\n\\tfirst := true.\\n\\tself phonemes do: [ :each |\\n\\t\\tfirst ifFalse: [aStream space].\\n\\t\\taStream print: each.\\n\\t\\tfirst := false].\\n\\taStream nextPut: $]! !\\n\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/8/1999 19:03'!\\nhasPrimaryStress\\n\\t^ self stress = 1! !\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/8/1999 19:03'!\\nhasSecondaryStress\\n\\t^ self stress = 2! !\\n\\n!Syllable methodsFor: 'testing' stamp: 'len 12/11/1999 13:11'!\\nisAccented\\n\\t^ self accent notNil! !\\nString subclass: #Symbol\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: 'NewSymbols OneCharacterSymbols SymbolTable'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Collections-Strings'!\\n!Symbol commentStamp: '<historical>' prior: 0!\\nI represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol.!\\n\\n\\n!Symbol methodsFor: 'accessing'!\\nat: anInteger put: anObject \\n\\t\\\"You cannot modify the receiver.\\\"\\n\\n\\tself errorNoModification! !\\n\\n!Symbol methodsFor: 'accessing' stamp: 'sma 2/5/2000 12:32'!\\nprecedence\\n\\t\\\"Answer the receiver's precedence, assuming it is a valid Smalltalk\\n\\tmessage selector or 0 otherwise. The numbers are 1 for unary,\\n\\t2 for binary and 3 for keyword selectors.\\\"\\n\\n\\tself size = 0 ifTrue: [^ 0].\\n\\tself first isLetter ifFalse: [^ 2].\\n\\tself last = $: ifTrue: [^ 3].\\n\\t^ 1! !\\n\\n!Symbol methodsFor: 'accessing'!\\nreplaceFrom: start to: stop with: replacement startingAt: repStart\\n\\n\\tself errorNoModification! !\\n\\n\\n!Symbol methodsFor: 'comparing' stamp: 'ar 4/10/2005 23:45'!\\n= aSymbol\\n\\t\\\"Compare the receiver and aSymbol.\\\" \\n\\tself == aSymbol ifTrue: [^ true].\\n\\tself class == aSymbol class ifTrue: [^ false].\\n\\t\\\"Use String comparison otherwise\\\"\\n\\t^ super = aSymbol! !\\n\\n\\n!Symbol methodsFor: 'converting' stamp: 'st 11/22/2004 17:26'!\\nasMutator\\n\\t\\\"Return a setter message from a getter message. For example,\\n\\t#name asMutator returns #name:\\\"\\n\\t^ (self copyWith: $:) asSymbol! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'ar 4/10/2005 22:42'!\\nasString \\n\\t\\\"Refer to the comment in String|asString.\\\"\\n\\t| newString |\\n\\tnewString _ self species new: self size.\\n\\tnewString replaceFrom: 1 to: newString size with: self startingAt: 1.\\n\\t^newString! !\\n\\n!Symbol methodsFor: 'converting'!\\nasSymbol \\n\\t\\\"Refer to the comment in String|asSymbol.\\\"! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'sw 1/28/98 18:18'!\\ncapitalized\\n\\t^ self asString capitalized asSymbol! !\\n\\n!Symbol methodsFor: 'converting' stamp: 'md 8/10/2004 10:54'!\\nwithFirstCharacterDownshifted\\n\\t\\\"Answer an object like the receiver but with first character downshifted if necesary\\\"\\n\\n\\t^self asString withFirstCharacterDownshifted asSymbol.! !\\n\\n\\n!Symbol methodsFor: 'copying' stamp: 'tk 6/26/1998 11:35'!\\nclone\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying'!\\ncopy\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying'!\\nshallowCopy\\n\\t\\\"Answer with the receiver, because Symbols are unique.\\\"! !\\n\\n!Symbol methodsFor: 'copying' stamp: 'tk 8/19/1998 16:05'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I am immutable in the Morphic world. Do not record me.\\\"! !\\n\\n\\n!Symbol methodsFor: 'filter streaming' stamp: 'mpw 1/1/1901 00:20'!\\nbyteEncode:aStream\\n\\t^aStream writeSymbol:self.\\n! !\\n\\n\\n!Symbol methodsFor: 'printing' stamp: 'sw 8/19/1999 11:30'!\\nisOrientedFill\\n\\t\\\"Needs to be implemented here because symbols can occupy 'color' slots of morphs.\\\"\\n\\n\\t^ false! !\\n\\n!Symbol methodsFor: 'printing' stamp: 'di 4/25/2000 12:32'!\\nstoreOn: aStream \\n\\n\\taStream nextPut: $#.\\n\\t(Scanner isLiteralSymbol: self)\\n\\t\\tifTrue: [aStream nextPutAll: self]\\n\\t\\tifFalse: [super storeOn: aStream]! !\\n\\n\\n!Symbol methodsFor: 'system primitives' stamp: 'di 1/2/1999 17:00'!\\nflushCache\\n\\t\\\"Tell the interpreter to remove all entries with this symbol as a selector from its method lookup cache, if it has one. This primitive must be called whenever a method is defined or removed.\\n\\tNOTE: Only one of the two selective flush methods needs to be used.\\n\\tSqueak 2.3 and later uses 116 (See CompiledMethod flushCache).\\\"\\n\\n\\t<primitive: 119>\\n! !\\n\\n!Symbol methodsFor: 'system primitives' stamp: 'md 2/16/2006 17:17'!\\nnumArgs: n\\n\\t\\\"Answer a string that can be used as a selector with n arguments.\\n\\t TODO: need to be extended to support shrinking and for selectors like #+ \\\" \\n\\n\\t| selector numArgs aStream offs |\\n\\t\\n\\tselector := self.\\n\\t(numArgs := selector numArgs) >= n ifTrue: [^self].\\t\\n\\taStream := WriteStream on: (String new: 16).\\n\\taStream nextPutAll: self.\\n\\t\\n\\t(numArgs = 0) ifTrue: [aStream nextPutAll: ':'. offs := 0] ifFalse: [offs := 1].\\n\\t2 to: n - numArgs + offs do: [:i | aStream nextPutAll: 'with:'].\\t\\n\\t^aStream contents asSymbol\\n\\t\\n! !\\n\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 1/20/2006 16:16'!\\nincludesKey: sym\\n\\t^self == sym.! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 8/27/2005 16:33'!\\nisDoIt\\n\\n\\t^ (self == #DoIt) or: [self == #DoItIn:].! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:32'!\\nisInfix\\n\\t\\\"Answer whether the receiver is an infix message selector.\\\"\\n\\n\\t^ self precedence == 2! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'!\\nisKeyword\\n\\t\\\"Answer whether the receiver is a message keyword.\\\"\\n\\n\\t^ self precedence == 3! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'di 4/25/2000 12:32'!\\nisLiteral\\n\\t\\\"Answer whether the receiver is a valid Smalltalk literal.\\\"\\n\\n\\t^ true! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:13'!\\nisPvtSelector\\n\\t\\\"Answer whether the receiver is a private message selector, that is,\\n\\tbegins with 'pvt' followed by an uppercase letter, e.g. pvtStringhash.\\\"\\n\\n\\t^ (self beginsWith: 'pvt') and: [self size >= 4 and: [(self at: 4) isUppercase]]! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'md 4/30/2003 15:31'!\\nisSymbol\\n\\t^ true ! !\\n\\n!Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'!\\nisUnary\\n\\t\\\"Answer whether the receiver is an unary message selector.\\\"\\n\\n\\t^ self precedence == 1! !\\n\\n\\n!Symbol methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:46'!\\nasExplorerString\\n\\t^ self printString! !\\n\\n\\n!Symbol methodsFor: 'private'!\\nerrorNoModification\\n\\n\\tself error: 'symbols can not be modified.'! !\\n\\n!Symbol methodsFor: 'private'!\\nstring: aString\\n\\n\\t1 to: aString size do: [:j | super at: j put: (aString at: j)].\\n\\t^self ! !\\n\\n\\n!Symbol methodsFor: 'evaluating' stamp: 'md 3/24/2006 12:09'!\\nvalue: anObject \\n\\t^anObject perform: self.! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSymbol class\\n\\tinstanceVariableNames: ''!\\n\\n!Symbol class methodsFor: 'access' stamp: 'ar 4/10/2005 22:49'!\\nallSymbols\\n\\t\\\"Answer all interned symbols\\\"\\n\\t^Array streamContents:[:s|\\n\\t\\ts nextPutAll: NewSymbols.\\n\\t\\ts nextPutAll: OneCharacterSymbols.\\n\\t\\ts nextPutAll: SymbolTable.\\n\\t].\\n! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'yo 11/3/2004 19:24'!\\nselectorsContaining: aString\\n\\t\\\"Answer a list of selectors that contain aString within them. Case-insensitive. Does return symbols that begin with a capital letter.\\\"\\n\\n\\t| size selectorList ascii |\\n\\n\\tselectorList _ OrderedCollection new.\\n\\t(size _ aString size) = 0 ifTrue: [^selectorList].\\n\\n\\taString size = 1 ifTrue:\\n\\t\\t[\\n\\t\\t\\tascii _ aString first asciiValue.\\n\\t\\t\\tascii < 128 ifTrue: [selectorList add: (OneCharacterSymbols at: ascii+1)]\\n\\t\\t].\\n\\n\\taString first isLetter ifFalse:\\n\\t\\t[\\n\\t\\t\\taString size == 2 ifTrue: \\n\\t\\t\\t\\t[Symbol hasInterned: aString ifTrue:\\n\\t\\t\\t\\t\\t[:s | selectorList add: s]].\\n\\t\\t\\t^selectorList\\n\\t\\t].\\n\\n\\tselectorList _ selectorList copyFrom: 2 to: selectorList size.\\n\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\teach size >= size ifTrue:\\n\\t\\t\\t[(each findSubstring: aString in: each startingAt: 1 \\n\\t\\t\\t\\tmatchTable: CaseInsensitiveOrder) > 0\\n\\t\\t\\t\\t\\t\\tifTrue: [selectorList add: each]]].\\n\\n\\t^selectorList reject: [:each | \\\"reject non-selectors, but keep ones that begin with an uppercase\\\"\\n\\t\\teach numArgs < 0 and: [each asString withFirstCharacterDownshifted numArgs < 0]].\\n\\n\\\"Symbol selectorsContaining: 'scon'\\\"! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'tween 9/13/2004 10:09'!\\nthatStartsCaseSensitive: leadingCharacters skipping: skipSym\\n\\t\\\"Same as thatStarts:skipping: but caseSensitive\\\"\\n\\t| size firstMatch key |\\n\\n\\tsize := leadingCharacters size.\\n\\tsize = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]].\\n\\tfirstMatch := leadingCharacters at: 1.\\n\\tsize > 1 ifTrue: [key := leadingCharacters copyFrom: 2 to: size].\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\t\\teach size >= size ifTrue:\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t((each at: 1) == firstMatch and:\\n\\t\\t\\t\\t\\t\\t[key == nil or:\\n\\t\\t\\t\\t\\t\\t\\t[(each findString: key startingAt: 2 caseSensitive: true) = 2]])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^each]\\n\\t\\t\\t\\t]\\n\\t\\t] after: skipSym.\\n\\n\\t^nil\\n! !\\n\\n!Symbol class methodsFor: 'access' stamp: 'RAA 5/29/2001 14:35'!\\nthatStarts: leadingCharacters skipping: skipSym\\n\\t\\\"Answer a selector symbol that starts with leadingCharacters.\\n\\tSymbols beginning with a lower-case letter handled directly here.\\n\\tIgnore case after first char.\\n\\tIf skipSym is not nil, it is a previous answer; start searching after it.\\n\\tIf no symbols are found, answer nil.\\n\\tUsed by Alt-q (Command-q) routines\\\"\\n\\n\\t| size firstMatch key |\\n\\n\\tsize _ leadingCharacters size.\\n\\tsize = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]].\\n\\n\\tfirstMatch _ leadingCharacters at: 1.\\n\\tsize > 1 ifTrue: [key _ leadingCharacters copyFrom: 2 to: size].\\n\\n\\tself allSymbolTablesDo: [:each |\\n\\t\\t\\teach size >= size ifTrue:\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t((each at: 1) == firstMatch and:\\n\\t\\t\\t\\t\\t\\t[key == nil or:\\n\\t\\t\\t\\t\\t\\t\\t[(each findString: key startingAt: 2 caseSensitive: false) = 2]])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [^each]\\n\\t\\t\\t\\t]\\n\\t\\t] after: skipSym.\\n\\n\\t^nil\\n\\n\\\"Symbol thatStarts: 'sf' skipping: nil\\\"\\n\\\"Symbol thatStarts: 'sf' skipping: #sfpGetFile:with:with:with:with:with:with:with:with:\\\"\\n\\\"Symbol thatStarts: 'candidate' skipping: nil\\\"\\n! !\\n\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 08:21'!\\nallSymbolTablesDo: aBlock\\n\\n\\tNewSymbols do: aBlock.\\n\\tSymbolTable do: aBlock.! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 14:35'!\\nallSymbolTablesDo: aBlock after: aSymbol\\n\\n\\tNewSymbols do: aBlock after: aSymbol.\\n\\tSymbolTable do: aBlock after: aSymbol.! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 12/17/2000 18:05'!\\ncompactSymbolTable\\n\\t\\\"Reduce the size of the symbol table so that it holds all existing symbols + 25% (changed from 1000 since sets like to have 25% free and the extra space would grow back in a hurry)\\\"\\n\\n\\t| oldSize |\\n\\n\\tSmalltalk garbageCollect.\\n\\toldSize _ SymbolTable array size.\\n\\tSymbolTable growTo: SymbolTable size * 4 // 3 + 100.\\n\\t^oldSize printString,' ',(oldSize - SymbolTable array size) printString, ' slot(s) reclaimed'! !\\n\\n!Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 09:04'!\\ninitialize\\n\\n\\t\\\"Symbol initialize\\\"\\n\\n\\tSymbol rehash.\\n\\tOneCharacterSymbols _ nil.\\n\\tOneCharacterSymbols _ (1 to: 256) collect: [ :i | (i - 1) asCharacter asSymbol].\\n\\tSmalltalk addToShutDownList: self.\\n! !\\n\\n\\n!Symbol class methodsFor: 'instance creation'!\\nfindInterned:aString\\n\\n\\tself hasInterned:aString ifTrue:[:symbol| ^symbol].\\n\\t^nil.! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'ar 4/10/2005 23:04'!\\ninternCharacter: aCharacter\\n\\taCharacter asciiValue > 256 ifTrue:[^self intern: aCharacter asString].\\n\\tOneCharacterSymbols ifNil: [^self intern: aCharacter asString].\\n\\t^OneCharacterSymbols at: aCharacter asciiValue + 1\\n! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'ar 4/12/2005 17:37'!\\nintern: aStringOrSymbol \\n\\n\\t^(self lookup: aStringOrSymbol) ifNil:[\\n\\t\\t| aClass aSymbol |\\n\\t\\taStringOrSymbol isSymbol ifTrue:[\\n\\t\\t\\taSymbol _ aStringOrSymbol.\\n\\t\\t] ifFalse:[\\n\\t\\t\\taClass := aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol].\\n\\t\\t\\taSymbol := aClass new: aStringOrSymbol size.\\n\\t\\t\\taSymbol string: aStringOrSymbol.\\n\\t\\t].\\n\\t\\tNewSymbols add: aSymbol.\\n\\t\\taSymbol].! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'RAA 5/29/2001 08:09'!\\nlookup: aStringOrSymbol\\n\\n\\t^(SymbolTable like: aStringOrSymbol) ifNil: [\\n\\t\\tNewSymbols like: aStringOrSymbol\\n\\t]! !\\n\\n!Symbol class methodsFor: 'instance creation'!\\nnewFrom: aCollection \\n\\t\\\"Answer an instance of me containing the same elements as aCollection.\\\"\\n\\n\\t^ (aCollection as: String) asSymbol\\n\\n\\\"\\tSymbol newFrom: {$P. $e. $n}\\n\\t{$P. $e. $n} as: Symbol\\n\\\"! !\\n\\n!Symbol class methodsFor: 'instance creation' stamp: 'di 10/11/1999 00:02'!\\nreadFrom: strm \\\"Symbol readFromString: '#abc'\\\"\\n\\n\\tstrm peek = $# ifFalse: [self error: 'Symbols must be introduced by #'].\\n\\t^ (Scanner new scan: strm) advance \\\"Just do what the code scanner does\\\"! !\\n\\n\\n!Symbol class methodsFor: 'private' stamp: 'ar 4/10/2005 22:43'!\\nhasInterned: aString ifTrue: symBlock \\n\\t\\\"Answer with false if aString hasnt been interned (into a Symbol), \\n\\totherwise supply the symbol to symBlock and return true.\\\"\\n\\n\\t| symbol |\\n\\t^ (symbol _ self lookup: aString)\\n\\t\\tifNil: [false]\\n\\t\\tifNotNil: [symBlock value: symbol.\\n\\t\\t\\ttrue]! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 14:33'!\\npossibleSelectorsFor: misspelled \\n\\t\\\"Answer an ordered collection of possible corrections\\n\\tfor the misspelled selector in order of likelyhood\\\"\\n\\n\\t| numArgs candidates lookupString best binary short long first ss |\\n\\tlookupString _ misspelled asLowercase. \\\"correct uppercase selectors to lowercase\\\"\\n\\tnumArgs _ lookupString numArgs.\\n\\t(numArgs < 0 or: [lookupString size < 2]) ifTrue: [^ OrderedCollection new: 0].\\n\\tfirst _ lookupString first.\\n\\tshort _ lookupString size - (lookupString size // 4 max: 3) max: 2.\\n\\tlong _ lookupString size + (lookupString size // 4 max: 3).\\n\\n\\t\\\"First assemble candidates for detailed scoring\\\"\\n\\tcandidates _ OrderedCollection new.\\n\\tself allSymbolTablesDo: [:s | (((ss _ s size) >= short\\t\\\"not too short\\\"\\n\\t\\t\\tand: [ss <= long\\t\\t\\t\\\"not too long\\\"\\n\\t\\t\\t\\t\\tor: [(s at: 1) = first]])\\t\\\"well, any length OK if starts w/same letter\\\"\\n\\t\\t\\tand: [s numArgs = numArgs])\\t\\\"and numArgs is the same\\\"\\n\\t\\t\\tifTrue: [candidates add: s]].\\n\\n\\t\\\"Then further prune these by correctAgainst:\\\"\\n\\tbest _ lookupString correctAgainst: candidates.\\n\\t((misspelled last ~~ $:) and: [misspelled size > 1]) ifTrue: [\\n\\t\\tbinary _ misspelled, ':'.\\t\\t\\\"try for missing colon\\\"\\n\\t\\tSymbol hasInterned: binary ifTrue: [:him | best addFirst: him]].\\n\\t^ best! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'ar 9/27/2005 20:01'!\\nrehash\\t\\t\\\"Symbol rehash\\\"\\n\\t\\\"Rebuild the hash table, reclaiming unreferenced Symbols.\\\"\\n\\n\\tSymbolTable := WeakSet withAll: self allSubInstances.\\n\\tNewSymbols := WeakSet new.! !\\n\\n!Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 09:04'!\\nshutDown: aboutToQuit\\n\\n\\tSymbolTable addAll: NewSymbols.\\n\\tNewSymbols _ WeakSet new.! !\\nKeyboardInputInterpreter subclass: #SymbolInputInterpreter\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Multilingual-TextConversion'!\\n\\n!SymbolInputInterpreter methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 16:10'!\\nnextCharFrom: sensor firstEvt: evtBuf\\n\\n\\t| keyValue |\\n\\tkeyValue := evtBuf third.\\n\\tevtBuf fifth > 1 ifTrue: [^ keyValue asCharacter macToSqueak].\\n\\t^ (self symbolKeyValueToUnicode: keyValue) asCharacter.\\n! !\\n\\n!SymbolInputInterpreter methodsFor: 'as yet unclassified' stamp: 'yo 11/8/2004 18:53'!\\nsymbolKeyValueToUnicode: keyValue\\n\\n\\tkeyValue = 127 ifTrue: [^ 127].\\n\\tkeyValue < 32 ifTrue: [^ keyValue].\\n\\tkeyValue > 255 ifTrue: [^ 0].\\n\\t^ #(0 0 0 0 0 0 0 0 0 61472 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 61472 61473 61474 61475 61476 61477 61478 61479 61480 61481 61482 61483 61484 61485 61486 61487 61488 61489 61490 61491 61492 61493 61494 61495 61496 61497 61498 61499 61500 61501 61502 61503 61504 61505 61506 61507 61508 61509 61510 61511 61512 61513 61514 61515 61516 61517 61518 61519 61520 61521 61522 61523 61524 61525 61526 61527 61528 61529 61530 61531 61532 61533 61534 61535 61536 61537 61538 61539 61540 61541 61542 61543 61544 61545 61546 61547 61548 61549 61550 61551 61552 61553 61554 61555 61556 61557 61558 61559 61560 61561 61562 61563 61564 61565 61566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 61601 61602 61603 61604 61605 61606 61607 61608 61609 61610 61611 61612 61613 61614 61615 61616 61617 61618 61619 61620 61621 61622 61623 61624 61625 61626 61627 61628 61629 61630 61631 61632 61633 61634 61635 61636 61637 61638 61639 61640 61641 61642 61643 61644 61645 61646 61647 61648 61649 61650 61651 61652 61653 61654 61655 61656 61657 61658 61659 61660 61661 61662 61663 61664 61665 61666 61667 61668 61669 61670 61671 61672 61673 61674 61675 61676 61677 61678 61679 0 61681 61682 61683 61684 61685 61686 61687 61688 61689 61690 61691 61692 61693 61694 0) at: keyValue + 1.\\n! !\\nTileMorph subclass: #SymbolListTile\\n\\tinstanceVariableNames: 'choices dataType'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Scripting Tiles'!\\n!SymbolListTile commentStamp: '<historical>' prior: 0!\\nInstances of SymbolListTile are literal tiles whose literals are choosable from a finite list.!\\n\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'yo 7/2/2004 21:27'!\\nliteral: anObject\\n\\t\\\"Set the receiver's literal as indicated\\\"\\n\\tself flag: #yo.\\n\\n\\tliteral _ anObject asSymbol.\\n\\tself updateLiteralLabel.\\n\\\"\\n\\tkey _ Vocabulary eToyVocabulary translationKeyFor: literal.\\n\\tkey isNil ifFalse: [literal _ key].\\n\\\"\\n\\tself flag: #deferred. \\\"The below formerly was necessary but now is problematical, leading to low-space condition etc. May need to revisit, since as I comment this out now I am uncertain what if anything this may break\\\"\\n\\t\\\"self labelMorph informTarget\\\"\\n\\n! !\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'tak 12/6/2004 01:58'!\\noptions\\n\\t^ {self choices. self choices\\n\\t\\tcollect: [:each | ScriptingSystem helpStringForOperator: literal]}! !\\n\\n!SymbolListTile methodsFor: 'accessing' stamp: 'tak 12/7/2004 14:42'!\\nvalue: anObject \\n\\tself acceptNewLiteral: anObject! !\\n\\n\\n!SymbolListTile methodsFor: 'customevents-accessing' stamp: 'nk 7/21/2003 22:02'!\\ndataType\\n\\t^dataType! !\\n\\n\\n!SymbolListTile methodsFor: 'customevents-initialization' stamp: 'nk 7/21/2003 22:14'!\\nupdateChoices\\n\\tchoices _ (Vocabulary vocabularyNamed: dataType) choices.\\n\\t(choices includes: literal) ifFalse: [ literal _ choices first. self changed ]! !\\n\\n\\n!SymbolListTile methodsFor: 'event handling' stamp: 'sw 12/3/2001 21:30'!\\nhandlesMouseDown: evt\\n\\t\\\"Answer whether the receiver handles mouse-down\\\"\\n\\n\\t^ true! !\\n\\n!SymbolListTile methodsFor: 'event handling' stamp: 'sw 11/16/2001 07:31'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t\\\"Answer whether a plain mouse click on aSubmorph, a text-edit-capable thing, should result in a text selection there\\\"\\n\\n\\t^ false! !\\n\\n\\n!SymbolListTile methodsFor: 'events-processing' stamp: 'sw 12/3/2001 20:45'!\\nmouseDownPriority\\n\\t\\\"Higher-priority than parts donor, so that the tile can offer a popup even when it is in a larger structure, such as a PhraseTileMorph, that itself behaves as a parts donor\\\"\\n\\n\\t^ 75! !\\n\\n\\n!SymbolListTile methodsFor: 'initialization' stamp: 'sw 10/30/2000 09:04'!\\nchoices: choiceList dataType: aDataType\\n\\t\\\"Initialize the receiver with the given choice-list and data type\\\"\\n\\n\\tchoices _ choiceList.\\n\\tdataType _ aDataType.\\n\\tliteral _ choiceList first! !\\n\\n!SymbolListTile methodsFor: 'initialization' stamp: 'tak 12/6/2004 01:38'!\\ninitialize\\n\\tsuper initialize.\\n\\tliteral _ #nothing! !\\n\\n\\n!SymbolListTile methodsFor: 'misc' stamp: 'sw 11/6/2001 13:30'!\\nsetLiteralInitially: anObject\\n\\t\\\"Establish the initial literal. Get the label correct, but do *not* send the value back to the target via the setter (unlike #literal:)\\\"\\n\\n\\tliteral _ anObject ifNotNil: [anObject asSymbol].\\n\\tself updateLiteralLabel! !\\n\\n\\n!SymbolListTile methodsFor: 'player viewer' stamp: 'yo 1/12/2005 14:28'!\\nupdateLiteralLabel\\n\\t\\\"Update the wording emblazoned on the tile, if needed. Copied down, for jimmying, unfortunately\\\"\\n\\n\\t| myLabel |\\n\\t(myLabel _ self labelMorph) ifNil: [^ self].\\n\\tmyLabel useSymbolFormat.\\n\\tmyLabel acceptValue: literal asString.\\n\\tself changed.! !\\n\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'yo 1/12/2005 14:38'!\\nacceptNewLiteral: aLiteral\\n\\t\\\"Accept the new literal\\\"\\n\\n\\tself labelMorph useSymbolFormat.\\n\\tself literal: aLiteral.\\n\\tself adjustHelpMessage.\\n\\tself acceptNewLiteral. \\\"so tile scriptor can recompile if necessary\\\"\\n\\tself labelMorph informTarget\\n! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 3/10/2004 23:24'!\\nadjustHelpMessage\\n\\t\\\"Adjust the help message to reflect the new literal\\\"\\n\\n\\t(ScriptingSystem helpStringOrNilForOperator: literal) ifNotNilDo:\\n\\t\\t[:aString |\\n\\t\\t\\tself labelMorph setBalloonText: aString]! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 12/21/2003 00:07'!\\nchoices\\n\\t\\\"Answer the list of current choices for the receiver's symbol\\\"\\n\\n\\tdataType == #ScriptName ifTrue: \\\"Backward compatibility with old tiles\\\"\\n\\t\\t[^ ActiveWorld presenter allKnownUnaryScriptSelectors].\\n\\t^ choices! !\\n\\n!SymbolListTile methodsFor: 'user interface' stamp: 'sw 1/4/2005 00:16'!\\nofferAllChoicesInAPopUp\\n\\t\\\"Retained in deference to pre-existing content that may have event handlers that send this message.\\\"\\n\\n\\t! !\\n\\n\\n!SymbolListTile methodsFor: 'private' stamp: 'yo 1/12/2005 14:28'!\\nline1: line1\\n\\t\\\"Emblazon the receiver with the requested label. If the receiver already has a label, make the new label be of the same class\\\"\\n\\n\\tsuper line1: line1.\\n\\tself labelMorph useSymbolFormat! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSymbolListTile class\\n\\tinstanceVariableNames: ''!\\n\\n!SymbolListTile class methodsFor: 'customevents-updating' stamp: 'nk 7/21/2003 22:16'!\\nupdateAllTilesForVocabularyNamed: aVocabularyName\\n\\t\\\"The choices in the Vocabulary named aVocabularyName may have changed.\\n\\tUpdate my subinstances if necessary to reflect the changes.\\\"\\n\\n\\t (self allSubInstances select: [ :ea | ea dataType = aVocabularyName ])\\n\\t\\tdo: [ :ea | ea updateChoices ] ! !\\nDataType subclass: #SymbolListType\\n\\tinstanceVariableNames: 'symbols'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Protocols-Type Vocabularies'!\\n!SymbolListType commentStamp: 'sw 1/6/2005 17:52' prior: 0!\\nA type whose values range across a finite set of symbols, which are held in the \\\"symbols\\\" instance variable.!\\n\\n\\n!SymbolListType methodsFor: 'initial value' stamp: 'sw 12/3/2001 19:27'!\\ninitialValueForASlotFor: aPlayer\\n\\t\\\"Answer the value to give initially to a newly created slot of the given type in the given player\\\"\\n\\n\\t^ self choices first! !\\n\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'sw 12/3/2001 19:14'!\\nchoices\\n\\t\\\"answer the list of choices to offer as variant values\\\"\\n\\n\\t^ symbols copy! !\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'sw 1/6/2005 17:24'!\\nrepresentsAType\\n\\t\\\"Answer whether this vocabulary represents an end-user-sensible data type\\\"\\n\\n\\t^ #(BorderStyle ButtonPhase TrailStyle) includes: vocabularyName! !\\n\\n!SymbolListType methodsFor: 'tiles' stamp: 'stephaneducasse 2/4/2006 20:39'!\\nsymbols: symbolList\\n\\t\\\"Set the receiver's list of symbols as indicated\\\"\\n\\n\\tsymbols := symbolList! !\\n\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 1/12/2005 10:13'!\\naffordsCoercionToBoolean\\n\\t\\\"Answer true if a tile of this data type, when dropped into a pane that demands a boolean, could plausibly be expanded into a comparison (of the form frog < toad or frog = toad) to provide a boolean expression\\\"\\n\\n\\t\\\"Formerly this had been disabled (9/27/01) but from today's perspective I don't see any reason to disable it...\\\"\\n\\n\\t^ true! !\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 12/3/2001 19:15'!\\ndefaultArgumentTile\\n\\t\\\"Answer a tile to represent the type\\\"\\n\\n\\t| aTile choices |\\n\\taTile _ SymbolListTile new choices: (choices _ self choices) dataType: self vocabularyName.\\n\\taTile addArrows.\\n\\taTile setLiteral: choices first.\\n\\t^ aTile! !\\n\\n!SymbolListType methodsFor: '*eToys-tiles' stamp: 'sw 12/3/2001 21:00'!\\nnewReadoutTile\\n\\t\\\"Answer a tile that can serve as a readout for data of this type\\\"\\n\\n\\t^ SymbolListTile new choices: self choices dataType: self vocabularyName\\n! !\\nClassTestCase subclass: #SymbolTest\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'CollectionsTests-Text'!\\n!SymbolTest commentStamp: '<historical>' prior: 0!\\nThis is the unit test for the class Symbol. Unit tests are a good way to exercise the functionality of your system in a repeatable and automatic manner. They are therefore recommended if you plan to release anything. For more information, see: \\n\\t- http://www.c2.com/cgi/wiki?UnitTest\\n\\t- http://minnow.cc.gatech.edu/squeak/1547\\n\\t- the sunit class category!\\n\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'md 9/6/2005 20:02'!\\ntestAsMutator\\n\\n\\tself assert: #x asMutator = #x:.\\n\\tself assert: #x asMutator isSymbol! !\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'sd 6/5/2005 09:29'!\\ntestCapitalized\\n\\n\\t| uc lc |\\t\\t\\n\\tuc := #MElViN.\\n\\tlc := #mElViN.\\n\\tself assert: lc capitalized = uc.\\n\\tself assert: uc capitalized = uc.\\n! !\\n\\n!SymbolTest methodsFor: 'tests' stamp: 'sd 6/5/2005 09:29'!\\ntestWithFirstCharacterDownshifted\\n\\n\\t| uc lc empty |\\t\\t\\n\\tuc := #MElViN.\\n\\tlc := #mElViN.\\n\\tempty := #' '.\\n\\tself assert: uc withFirstCharacterDownshifted = lc.\\n\\tself assert: lc withFirstCharacterDownshifted = lc.\\n\\t\\n! !\\n\\n\\n!SymbolTest methodsFor: 'as yet unclassified' stamp: 'md 2/16/2006 17:17'!\\ntestNumArgs2\\n \\\"TODO: need to be extended to support shrinking and for selectors like #+ \\\" \\n\\t\\n\\tself assert: (#test numArgs: 0) = #test.\\n\\tself assert: (#test numArgs: 1) = #test:.\\n\\tself assert: (#test numArgs: 2) = #test:with:.\\n\\tself assert: (#test numArgs: 3) = #test:with:with:.\\n\\t\\n\\n\\tself assert: (#test: numArgs: 0) = #test:.\\n\\tself assert: (#test: numArgs: 1) = #test:.\\n\\tself assert: (#test: numArgs: 2) = #test:with:.\\n\\tself assert: (#test: numArgs: 3) = #test:with:with:.\\n\\t\\n\\tself assert: (#test:with: numArgs: 0) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 1) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 2) = #test:with:.\\n\\tself assert: (#test:with: numArgs: 3) = #test:with:with:.\\n\\tself assert: (#test:with: numArgs: 4) = #test:with:with:with:.\\n\\t\\n\\tself assert: (#test:with:with: numArgs: 0) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 1) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 2) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 3) = #test:with:with:.\\n\\tself assert: (#test:with:with: numArgs: 4) = #test:with:with:with:.! !\\nObject subclass: #SyntaxAttribute\\n\\tinstanceVariableNames: 'color emphasis attributeList'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Compiler-Support'!\\n!SyntaxAttribute commentStamp: '<historical>' prior: 0!\\nRepresents a color and possibly a style attribute to be applied to a syntactic element for pretty-printing. The attributeList inst var is a cache.!\\n\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/17/1999 15:04'!\\nattributeList\\n\\t\\\"Answer a list of text attributes that characterize the receiver\\\"\\n\\tattributeList ifNil:\\n\\t\\t[attributeList _ OrderedCollection new: 2.\\n\\t\\tcolor ifNotNil: [attributeList add: (TextColor color: color)].\\n\\t\\temphasis ifNotNil: [attributeList add: (TextEmphasis perform: emphasis)]].\\n\\t^ attributeList! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'djp 11/7/1999 14:52'!\\ncolor\\n\\n\\t^ color! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/16/1999 16:21'!\\ncolor: aTextColor\\n\\tcolor _ aTextColor.\\n\\tattributeList _ nil! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'djp 11/7/1999 14:52'!\\nemphasis\\n\\n\\t^ emphasis! !\\n\\n!SyntaxAttribute methodsFor: 'accessing' stamp: 'sw 11/16/1999 16:22'!\\nemphasis: aTextEmphasis\\n\\temphasis _ aTextEmphasis.\\n\\tattributeList _ nil! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxAttribute class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxAttribute class methodsFor: 'as yet unclassified' stamp: 'sw 11/16/1999 12:01'!\\ncolor: aColor emphasis: anEmphasis\\n\\t^ self new color: aColor; emphasis: anEmphasis; yourself! !\\nStringHolder subclass: #SyntaxError\\n\\tinstanceVariableNames: 'class selector category debugger doitFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Debugger'!\\n!SyntaxError commentStamp: '<historical>' prior: 0!\\nI represent syntax error report for syntax errors encountered when filing in class descriptions from a non-interactive source such as an external file. As a StringHolder, the string to be viewed is the method code or expression containing the error.\\n\\nThe user may fix the error and accept the method to continue the fileIn.\\n!\\n\\n\\n!SyntaxError methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:27'!\\ncategory: aSymbol\\n\\t\\\"Record the message category of method being compiled. This is used when the user corrects the error and accepts.\\\"\\n\\n\\tcategory := aSymbol.\\n! !\\n\\n!SyntaxError methodsFor: 'initialization' stamp: 'sd 11/20/2005 21:30'!\\nsetClass: aClass code: aString debugger: aDebugger doitFlag: flag\\n\\n\\t| types printables badChar |\\n\\tclass := aClass.\\n\\tdebugger := aDebugger.\\n\\tselector := aClass parserClass new parseSelector: aString.\\n\\ttypes := Scanner classPool at: #TypeTable.\\t\\\"dictionary\\\"\\n\\tprintables := '!!@#$%&*-_=+<>{}?/\\\\,\\U00b7\\U00a3\\U00a2\\U00a7\\U00b6\\U00aa\\U00ba\\U0096\\U0097\\U0093\\U0091\\U0094\\U0092\\U0085\\U00da\\U00e6\\U00da\\U00af\\U00d7\\U00bf\\U00ab\\U00bb`~`' asSet.\\n\\tbadChar := aString detect: [:aChar | (types at: aChar asciiValue ifAbsent: [#xLetter]) == #xBinary and: [\\n\\t\\t\\t(printables includes: aChar) not]] ifNone: [nil].\\n\\tcontents := badChar \\n\\t\\tifNil: [aString]\\n\\t\\tifNotNil: ['<<<This string contains a character (ascii value ', \\n\\t\\t\\tbadChar asciiValue printString,\\n\\t\\t\\t') that is not normally used in code>>> ', aString].\\n\\tcategory ifNil: [category := aClass organization categoryOfElement: selector].\\n\\tcategory ifNil: [category := ClassOrganizer default].\\n\\tdoitFlag := flag! !\\n\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'RAA 12/1/2000 14:24'!\\ndebug\\n\\t\\\"Show the stack of the process leading to this syntax editor, typically showing the stack of the compiler as called from fileIn.\\\"\\n\\n\\tdebugger openFullNoSuspendLabel: 'Stack of the Syntax Error'.\\n\\tSmalltalk isMorphic ifFalse: [Processor terminateActive].\\n! !\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'jm 5/3/1998 14:22'!\\nlistMenu: aMenu\\n\\n\\t^ aMenu labels:\\n'proceed\\ndebug calling process\\nbrowse full'\\n\\tlines: #()\\n\\tselections: #(proceed debug browseMethodFull)\\n! !\\n\\n!SyntaxError methodsFor: 'menu' stamp: 'di 5/5/1998 00:06'!\\nproceed\\n\\t\\\"The user has has edited and presumably fixed the syntax error and the filein can now proceed.\\\"\\n\\n\\tdebugger proceed: self topView.\\n! !\\n\\n\\n!SyntaxError methodsFor: 'message list' stamp: 'tk 4/19/1999 08:08'!\\nlist\\n\\t\\\"Answer an array of one element made up of the class name, message category, and message selector in which the syntax error was found. This is the single item in the message list of a view/browser on the receiver.\\\"\\n\\n\\tselector ifNil: [^ Array with: (class name, ' ', category, ' ', '<none>')].\\n\\t^ Array with: (class name, ' ', category, ' ', selector)\\n! !\\n\\n!SyntaxError methodsFor: 'message list' stamp: 'jm 5/3/1998 13:48'!\\nlistIndex\\n\\t\\\"There is always exactly one element in my list and it is always selected.\\\"\\n\\n\\t^ 1\\n! !\\n\\n\\n!SyntaxError methodsFor: 'other' stamp: 'di 10/9/1998 16:36'!\\ncontents: aString notifying: aController\\n\\t\\\"Compile the code in aString and notify aController of any errors. If there are no errors, then automatically proceed.\\\"\\n\\n\\tdoitFlag\\n\\tifTrue: [Compiler new evaluate: aString in: nil to: nil\\n\\t\\t\\t\\t\\t\\tnotifying: aController ifFail: [^ false]]\\n\\tifFalse: [(class compile: aString classified: category\\n\\t\\t\\t\\t\\t\\tnotifying: aController) ifNil: [^ false]].\\n\\n\\taController hasUnacceptedEdits: false.\\n\\tself proceed! !\\n\\n!SyntaxError methodsFor: 'other' stamp: 'sd 11/20/2005 21:27'!\\nnotify: error at: location in: source\\n\\t\\\"Open a syntax error view, inserting the given error message into the given source at the given location. This message is sent to the 'requestor' when the parser or compiler finds a syntax error.\\\"\\n\\n\\t| aClass aString |\\n\\taClass := thisContext sender receiver encoder classEncoding.\\n\\taString :=\\n\\t\\tsource contents\\n\\t\\t\\tcopyReplaceFrom: location\\n\\t\\t\\tto: location - 1\\n\\t\\t\\twith: error.\\n\\tself setClass: aClass\\n\\t\\tcode: aString\\n\\t\\tdebugger: (Debugger context: thisContext)\\n\\t\\tdoitFlag: false.\\n\\tself class open: self.\\n! !\\n\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:15'!\\nselectedClass\\n\\t\\\"Answer the class in which the syntax error occurred.\\\"\\n\\n\\t^ class\\n! !\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:33'!\\nselectedClassOrMetaClass\\n\\t\\\"Answer the class of the method being compiled.\\\"\\n\\n\\t^ class\\n! !\\n\\n!SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:17'!\\nselectedMessageName\\n\\t\\\"Answer the selector of the method being compiled.\\\"\\n\\n\\t^ selector\\n! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxError class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nbuildMVCViewOn: aSyntaxError\\n\\t\\\"Answer an MVC view on the given SyntaxError.\\\"\\n\\n\\t| topView aListView aCodeView |\\n\\ttopView := StandardSystemView new\\n\\t\\tmodel: aSyntaxError;\\n\\t\\tlabel: 'Syntax Error';\\n\\t\\tminimumSize: 380@220.\\n\\n\\taListView := PluggableListView on: aSyntaxError\\n\\t\\tlist: #list\\n\\t\\tselected: #listIndex\\n\\t\\tchangeSelected: nil\\n\\t\\tmenu: #listMenu:.\\n\\taListView window: (0@0 extent: 380@20).\\n\\ttopView addSubView: aListView.\\n\\n\\taCodeView := PluggableTextView on: aSyntaxError\\n\\t\\ttext: #contents\\n\\t\\taccept: #contents:notifying:\\n\\t\\treadSelection: #contentsSelection\\n\\t\\tmenu: #codePaneMenu:shifted:.\\n\\taCodeView window: (0@0 extent: 380@200).\\n\\ttopView addSubView: aCodeView below: aListView.\\n\\n\\t^ topView\\n! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nbuildMorphicViewOn: aSyntaxError\\n\\t\\\"Answer an Morphic view on the given SyntaxError.\\\"\\n\\t| window |\\n\\twindow := (SystemWindow labelled: 'Syntax Error') model: aSyntaxError.\\n\\n\\twindow addMorph: (PluggableListMorph on: aSyntaxError list: #list\\n\\t\\t\\tselected: #listIndex changeSelected: nil menu: #listMenu:)\\n\\t\\tframe: (0@0 corner: 1@0.15).\\n\\n\\twindow addMorph: (PluggableTextMorph on: aSyntaxError text: #contents\\n\\t\\t\\taccept: #contents:notifying: readSelection: #contentsSelection\\n\\t\\t\\tmenu: #codePaneMenu:shifted:)\\n\\t\\tframe: (0@0.15 corner: 1@1).\\n\\n\\t^ window openInWorldExtent: 380@220! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'di 9/14/2001 07:46'!\\nerrorInClass: aClass withCode: codeString doitFlag: doit\\n\\t\\\"Open a view whose model is a syntax error. The error occurred when trying to add the given method code to the given class.\\\"\\n\\n\\tself open:\\n\\t\\t(self new setClass: aClass\\n\\t\\t\\tcode: codeString\\n\\t\\t\\tdebugger: (Debugger context: thisContext)\\n\\t\\t\\tdoitFlag: doit).\\n! !\\n\\n!SyntaxError class methodsFor: 'instance creation' stamp: 'sd 11/20/2005 21:28'!\\nopen: aSyntaxError\\n\\t\\\"Answer a standard system view whose model is an instance of me.\\\"\\n\\t| topView |\\n\\t<primitive: 19> \\\"Simulation guard\\\"\\n\\tSmalltalk isMorphic\\n\\t\\tifTrue:\\n\\t\\t\\t[self buildMorphicViewOn: aSyntaxError.\\n\\t\\t\\tProject spawnNewProcessIfThisIsUI: Processor activeProcess.\\n\\t\\t\\t^ Processor activeProcess suspend].\\n\\ttopView := self buildMVCViewOn: aSyntaxError.\\n\\ttopView controller openNoTerminateDisplayAt: Display extent // 2.\\n\\tCursor normal show.\\n\\tProcessor activeProcess suspend.\\n! !\\nNotification subclass: #SyntaxErrorNotification\\n\\tinstanceVariableNames: 'inClass code category doitFlag'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Exceptions-Extensions'!\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:17'!\\ncategory\\n\\t^category! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:11'!\\ndoitFlag\\n\\t^doitFlag! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:10'!\\nerrorClass\\n\\t^inClass! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:10'!\\nerrorCode\\n\\t^code! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:14'!\\nmessageText\\n\\t^ super messageText\\n\\t\\tifNil: [messageText := code]! !\\n\\n!SyntaxErrorNotification methodsFor: 'accessing' stamp: 'ar 9/27/2005 19:15'!\\nsetClass: aClass category: aCategory code: codeString doitFlag: aBoolean\\n\\tinClass := aClass.\\n\\tcategory := aCategory.\\n\\tcode := codeString.\\n\\tdoitFlag := aBoolean ! !\\n\\n\\n!SyntaxErrorNotification methodsFor: 'exceptionDescription' stamp: 'ar 9/27/2005 19:13'!\\ndefaultAction\\n\\t^ToolSet debugSyntaxError: self! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxErrorNotification class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxErrorNotification class methodsFor: 'exceptionInstantiator' stamp: 'ar 9/27/2005 19:15'!\\ninClass: aClass category: aCategory withCode: codeString doitFlag: doitFlag \\n\\t^ (self new\\n\\t\\tsetClass: aClass\\n\\t\\tcategory: aCategory \\n\\t\\tcode: codeString\\n\\t\\tdoitFlag: doitFlag) signal! !\\nAlignmentMorph subclass: #SyntaxMorph\\n\\tinstanceVariableNames: 'parseNode markerMorph'\\n\\tclassVariableNames: 'AllSpecs ContrastFactor DownRightArrow SelfTile SizeScaleFactor'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Tile Scriptors'!\\n!SyntaxMorph commentStamp: '<historical>' prior: 0!\\nA single class of morph that holds any piece of Smalltalk syntax, and allows it to be a tile. Tiles can be dragged in or out of a method. \\n\\nIn the message list pane of a Browser, choose 'tile scriptor'. Bring up a second one to steal parts from. If you use a Protocol Browser, and choose tiles, there will be two buttons that bring up menus with many tiles on them.\\n\\nClicking multiple times selects enclosing phrases of code. Dragging lets you take away a copy. Any tile may be replaced by dropping on it. Shift-click to edit the text of any tile. Change variable and message names, but do not change the part-of-speech (objects to selector).\\n\\nEach SyntaxMorph holds a ParseNode. After editing, the parseNode is only good as a part-of-speech indicator. Only the Class of a parseNode is important. It's state is not kept up to date with the tile edits (but maybe it should be). (For MessageNodes, whether the receiver slot is nil is significant.)\\n\\nThe correspondence between SyntaxMorphs and parseNodes in the real parse tree is not one-to-one. Several extra levels of SyntaxMorph were added as aligners to make the horizontal and vertical layout right. These sometimes have nil for the parseNode.\\n\\nWhen accept the method, we pass over the tree of SyntaxMorphs, gathering their printStrings and inserting punctuation. See (SyntaxMorph>>printOn:indent:). We send the result to the compiler. (We do not use the parse tree we already have.)\\n\\nTo turn on type checking: \\nPreferences enable: #eToyFriendly\\nor for testing: World project projectParameters at: #fullCheck put: true.\\n\\nColors of tiles: Each tile has a current color (inst car color) and a deselectedColor (a property). The deselectedColor may be governed by the part of speech, or not. (translateColor: is only used when a tile is created, to set deselectedColor.) From deselectedColor (set by #setDeselectedColor), the color changes to:\\n\\tlightBrown when selected (not the submorphs) in #select\\n\\ttranslucent when held in the hand (allMorphs) in #lookTranslucent\\n\\tgreen when a drop target (allMorphs) (change the owners back) #dropColor, \\n\\t\\t#trackDropZones \\ndeselectedColor is moderated by the darkness setting, #scaleColorByUserPref:. (as it is put into color in #color:)\\n\\nCode to produce an individual tile is: \\n\\t(SyntaxMorph new) attachTileForCode: '''abc''' nodeType: LiteralNode.\\nsee offerTilesMenuFor:in: for many other phrases that produce useful tiles.\\n\\nAssignmentNode: If three submorphs, is a statement, and is a noun. If one submorph, is just the left arrow. When dropped on a variable, it creates a new assignment statement. !\\n\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 8/21/2001 09:36'!\\nactualObject\\n\\t| sub |\\n\\t\\\"Who is self in these tiles? Usually a Player.\\\"\\n\\n\\n\\t(self nodeClassIs: LiteralVariableNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t\\\"Need to decompile here for odd synonyms of 'self' ?\\\"\\n\\t\\t^ Compiler evaluate: sub contents for: Player logged: false].\\n\\n\\t(self nodeClassIs: VariableNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t^ References at: (self cleanUpString: sub) asSymbol ifAbsent: [nil]].\\n\\n\\t(self nodeClassIs: LiteralNode) ifTrue: [\\n\\t\\t(sub _ self findA: StringMorph) ifNil: [^ nil].\\n\\t\\t^ Compiler evaluate: sub contents for: nil logged: false].\\n\\n\\t(sub _ self findA: SyntaxMorph) ifNil: [^ nil].\\n\\t^ sub actualObject\\t\\\"receiver\\\"! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/20/2001 13:21'!\\nargumentNodes\\n\\t\\\"Return a collection of this message's argument nodes. \\\"\\n\\n\\t| cls coll rec |\\n\\tparseNode ifNil: [^ #()].\\n\\tcls _ parseNode class.\\n\\tcls == SelectorNode ifTrue: [^ #()].\\n\\tcls == KeyWordNode ifTrue: [^ #()].\\n\\n\\tcoll _ OrderedCollection new.\\n\\trec _ self receiverNode.\\n\\tsubmorphs do: [:sub | \\n\\t\\t(sub isSyntaxMorph and: [sub ~~ rec]) ifTrue: [\\n\\t\\t\\tsub isNoun ifTrue: [coll addLast: sub]\\t\\\"complete arg\\\"\\n\\t\\t\\t\\tifFalse: [coll _ coll, sub argumentNodes]]].\\t\\\"MessagePartNode, MessageNode with no receiver\\\"\\n\\t^ coll! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/24/1999 17:57'!\\nballoonText\\n\\n\\t^(('Value: ',(self getCurrentValue ifNil: [^nil])) \\n\\t\\twithNoLineLongerThan: 35) truncateWithElipsisTo: 300! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'di 12/13/2000 15:25'!\\nborderColor: colorOrSymbolOrNil\\n\\n\\tborderColor = colorOrSymbolOrNil ifFalse: [\\n\\t\\tborderColor _ colorOrSymbolOrNil.\\n\\t\\tself bounds area < 40000\\n\\t\\t\\tifTrue: [self invalidRect: self bounds]\\n\\t\\t\\tifFalse: [(self bounds areasOutside: (self bounds insetBy: self borderWidth))\\n\\t\\t\\t\\t\\t\\tdo: [:r | self invalidRect: r]]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 4/4/2001 12:36'!\\ncleanUpString: stringSubMorph\\n\\n\\t| style rawData |\\n\\t^ stringSubMorph \\n\\t\\tvalueOfProperty: #syntacticallyCorrectContents \\n\\t\\tifAbsent: [\\n\\t\\t\\tstyle _ stringSubMorph valueOfProperty: #syntacticReformatting.\\n\\t\\t\\trawData _ stringSubMorph contents.\\n\\t\\t\\t (#(unary tempVariableDeclaration blockarg2 methodHeader1 tempVariable variable) includes: style) ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: nil.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #keywordGetz ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: 'Getz:'.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #keywordSetter ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: 'set ',rawData appending: ':'.\\n\\t\\t\\t].\\n\\t\\t\\tstyle == #unaryGetter ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: 'get ',rawData appending: nil.\\n\\t\\t\\t].\\n\\t\\t\\t(#(keyword2 methodHeader2) includes: style) ifTrue: [\\n\\t\\t\\t\\trawData _ self unSpaceAndUpShift: rawData appending: ':'.\\n\\t\\t\\t].\\n\\t\\t\\trawData\\n\\t\\t]\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 7/19/2001 20:04'!\\ncolor: aColorOrSymbol\\n\\n\\t| deselectedColor cc |\\n\\taColorOrSymbol isColor ifTrue: [\\n\\t\\tself valueOfProperty: #deselectedColor ifAbsent: [\\\"record my color the first time\\\"\\n\\t\\t\\tself setProperty: #deselectedColor toValue: aColorOrSymbol.\\n\\t\\t\\t^ super color: (self scaleColorByUserPref: aColorOrSymbol)].\\n\\t\\t^ super color: aColorOrSymbol].\\n\\n\\tdeselectedColor _ self valueOfProperty: #deselectedColor ifAbsent: [nil].\\n\\tdeselectedColor ifNotNil: [^ super color: (self scaleColorByUserPref: deselectedColor)].\\n\\n\\taColorOrSymbol == #comment ifTrue: [^ self color: Color blue lighter].\\n\\tSyntaxMorph noTileColor ifTrue: [\\t\\\"override\\\"\\n\\t\\t^ self color: Color transparent].\\t\\\"Fix this to be real color!!\\\"\\n\\n\\t(cc _ self class translateColor: aColorOrSymbol) isColor\\n\\t\\tifTrue: [^ self color: cc]\\n\\t\\tifFalse: [Transcript show: aColorOrSymbol, ' needs to be handled in translateColor:'; cr.\\n\\t\\t\\t^ self color: Color transparent].\\t\\\"help!!\\\"! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/20/2001 12:43'!\\ndissectMessage\\n\\t\\\"I am a MessageNode. Return {receiverNode or nil, selector, (keyword nodes), (argument nodes)}. Ignore all spacing morphs.\\\"\\n\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'sw 2/3/2001 01:40'!\\neditor\\n\\t\\\"In parallel with the interface for text morphs, we respond to this, but in our case we are our own editor\\\"\\n\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/19/2001 15:39'!\\nenclosingPane\\n\\t\\\"The object that owns this script layout\\\"\\n\\n\\t| oo higher |\\n\\too _ self owner.\\n\\t[higher _ oo isSyntaxMorph.\\n\\thigher _ higher or: [oo class == TransformMorph].\\n\\thigher _ higher or: [oo class == TwoWayScrollPane].\\n\\thigher ifFalse: [^ oo].\\n\\thigher] whileTrue: [oo _ oo owner].\\n! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/7/2001 16:13'!\\ngetCurrentValue\\n\\n\\tparseNode ifNil: [^nil].\\n\\tparseNode class == Symbol ifTrue: [^nil].\\t\\\"special\\\"\\n\\t^parseNode currentValueIn: self hostContext! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'dgd 2/22/2003 18:48'!\\nmessageNode\\n\\t\\\"Return the enclosing messageNode that is the full message. It has a receiver.\\\"\\n\\n\\t^self orOwnerSuchThat: [:oo | oo receiverNode notNil]! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/15/1999 16:23'!\\nparseNode\\n\\t\\n\\t^parseNode\\n\\t\\t\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'RAA 8/15/1999 16:11'!\\nparseNode: x\\n\\t\\n\\tparseNode _ x\\n\\t\\t\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'di 11/17/2000 08:07'!\\nparsedInClass\\n\\n\\t^ self rootTile parseNode encoder classEncoding! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/15/2000 14:39'!\\nparsedInClass: x\\n\\n\\tself parsedInClass == x ifFalse: [self error: 'inconsistent value']! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/25/2001 11:28'!\\nreadOut\\n\\t\\\"Find and return an UpdatingStringMorph, possibly in a NumericReadoutTile\\\"\\n\\n\\t^ ((self findA: NumericReadoutTile) ifNil: [^ nil]) findA: UpdatingStringMorph! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 7/23/2001 18:04'!\\nreceiverNode\\n\\t\\\"If I am (have) a MessageNode, return the node of the receiver. Watch out for foolish noise words.\\\"\\n\\n\\tparseNode class == MessageNode ifFalse: [^ nil].\\n\\tparseNode receiver ifNil: [^ nil].\\n\\tsubmorphs do: [:ss | \\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode ifNotNil: [\\\"not noise word\\\"\\n\\t\\t\\t\\tss isNoun ifTrue: [^ ss] \\n\\t\\t\\t\\t\\tifFalse: [^ nil \\\"found selector\\\"]]]].\\n\\t^ nil! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 9/23/2001 00:27'!\\nreceiverObject\\n\\t\\\"Return some object that could be the receiver to me (a selector). Either the actual object who is the receiver in this message, or a guy of the right class.\\\"\\n\\n\\t| rec value mm |\\n\\t(rec _ owner) isSyntaxMorph ifFalse: [^ nil].\\n\\trec _ rec receiverNode.\\n\\trec ifNil: [(rec _ owner owner) isSyntaxMorph ifFalse: [^ nil].\\n\\t\\t\\t\\trec _ rec receiverNode].\\t\\n\\trec ifNil: [(rec _ owner owner owner) isSyntaxMorph ifFalse: [^ nil].\\n\\t\\t\\t\\trec _ rec receiverNode].\\n\\trec isSelfTile ifTrue: [\\n\\t\\t^ ((mm _ self containingWindow model) respondsTo: #targetObject) \\n\\t\\t\\tifTrue: [mm targetObject]\\n\\t\\t\\tifFalse: [mm selectedClassOrMetaClass new]].\\n\\tvalue _ rec ifNotNil: [rec try].\\n\\tvalue class == Error ifTrue: [\\n\\t\\tvalue _ Vocabulary instanceWhoRespondsTo: self selector].\\n\\t^ value! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 1/13/2001 20:08'!\\nrename: newSelector\\n\\t| keywords mainSel list last |\\n\\t\\\"Attempt to change the name as listed in my tiles. Can change the number of argumtents. MethodNode (SelectorNode (SelectorNode (string))) or MethodNode (SelectorNode (SelectorNode (string) TempVarNode() SelectorNode (string) TempVarNode()))\\\"\\n\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile rename: newSelector \\\"always do at the root\\\"].\\n\\n\\tkeywords _ newSelector keywords.\\n\\tmainSel _ self findA: SelectorNode.\\n\\tlist _ mainSel submorphs select: [:mm | \\n\\t\\tmm isSyntaxMorph and: [mm parseNode class == SelectorNode]].\\n\\t1 to: (list size min: keywords size) do: [:ind |\\n\\t\\t((list at: ind) findA: UpdatingStringMorph) contents: (keywords at: ind)].\\n\\tkeywords size + 1 to: list size do: [:ind | \\\"removing keywords\\\"\\n\\t\\t[last _ mainSel submorphs last.\\n\\t\\t (last isSyntaxMorph and: [last parseNode class == TempVariableNode])] whileFalse: [\\n\\t\\t\\t\\tlast delete].\\n\\t\\t[last _ mainSel submorphs last.\\n\\t\\t (last isSyntaxMorph and: [last parseNode class == SelectorNode])] whileFalse: [\\n\\t\\t\\t\\tlast delete].\\t\\\"the TempVariableNode and others\\\"\\n\\t\\tmainSel submorphs last delete.\\t\\\"the SelectorNode\\\"\\n\\t\\t].\\n\\tlist size + 1 to: keywords size do: [:ind | \\\"adding keywords\\\"\\n\\t\\t\\\"add a SelectorNode, add a spacer, add a TempVarNode\\\"\\n\\t\\tmainSel addToken: (keywords at: ind) type: #keyword1 \\n\\t\\t\\ton: (SelectorNode new key: (keywords at: ind) code: nil).\\n\\t\\tmainSel addMorphBack: (mainSel transparentSpacerOfSize: 4@4).\\n\\t\\t(TempVariableNode new name: 'arg', ind printString index: ind type: nil scope: nil)\\n\\t\\t\\t asMorphicSyntaxIn: mainSel].! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'dgd 2/22/2003 13:41'!\\nselector\\n\\t\\\"Find the selector I represent, or have inside of me. My parseNode is a SelectorNode or a MessageNode.\\\"\\n\\n\\t| sel cnt |\\n\\tparseNode class == SelectorNode \\n\\t\\tifTrue: [^self decompile asString asSymbol].\\n\\tparseNode class == KeyWordNode ifTrue: [^self decompile asString asSymbol].\\n\\tparseNode class == MessageNode | (parseNode class == MessagePartNode) \\n\\t\\tifFalse: [^nil].\\n\\t\\\"Must be one of those to have a selector\\\"\\n\\t\\\"Beware of messageParts. If MessagePartNode, only returns this one keyword.\\\"\\n\\tsel := ''.\\n\\tcnt := 0.\\n\\tsubmorphs do: \\n\\t\\t\\t[:mm | \\n\\t\\t\\tmm isSyntaxMorph \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[cnt := cnt + 1.\\n\\t\\t\\t\\t\\t(mm nodeClassIs: SelectorNode) ifTrue: [^mm selector].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: MessagePartNode) ifTrue: [sel := sel , mm selector].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: KeyWordNode) ifTrue: [sel := sel , mm decompile asString].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: ReturnNode) ifTrue: [cnt := cnt - 1].\\n\\t\\t\\t\\t\\t(mm nodeClassIs: MessageNode) \\n\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t[parseNode receiver ifNil: [sel := mm selector].\\n\\t\\t\\t\\t\\t\\t\\tcnt = 2 & (sel isEmpty) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[\\\"not the receiver. Selector and arg\\\"\\n\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tsel := mm selector]]]].\\n\\tsel ifNil: [^nil].\\n\\tsel notEmpty ifTrue: [^sel asSymbol].\\n\\t^nil! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'aoy 2/15/2003 21:31'!\\nunSpaceAndUpShift: aString appending: extraChars \\n\\t| answer upShiftNext |\\n\\tanswer := WriteStream on: String new.\\n\\tupShiftNext := false.\\n\\taString do: \\n\\t\\t\\t[:ch | \\n\\t\\t\\tupShiftNext :=( ch == Character space) \\n\\t\\t\\t\\tifTrue: [ true]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[answer nextPut: (upShiftNext ifTrue: [ch asUppercase] ifFalse: [ch]).\\n\\t\\t\\t\\t\\t false]].\\n\\tanswer := answer contents.\\n\\textraChars isEmptyOrNil ifTrue: [^answer].\\n\\t(answer endsWith: extraChars) ifFalse: [answer := answer , extraChars].\\n\\t^answer! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/12/2000 14:42'!\\nuserScriptSelector\\n\\t\\\"user wrote this script\\\"\\n\\n\\t^ self valueOfProperty: #userScriptSelector! !\\n\\n!SyntaxMorph methodsFor: 'accessing' stamp: 'tk 11/12/2000 14:41'!\\nuserScriptSelector: sel\\n\\t\\\"user wrote this script\\\"\\n\\n\\tself setProperty: #userScriptSelector toValue: sel.! !\\n\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 16:03'!\\naSimpleStringMorphWith: aString\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t^StringMorph contents: aString font: self alansCurrentFontPreference\\n\\t].\\n\\n\\t^StringMorph contents: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:24'!\\nalansCurrentFontPreference\\n\\n\\t^nil\\t\\t\\\"StrikeFont familyName: 'ComicBold' size: 16\\\"! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:38'!\\nalansTemplateStyleFor: key\\n\\n\\t(#(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:) includes: key) ifTrue: [^1].\\n\\t(#(do: collect:) includes: key) ifTrue: [^2].\\n\\t(#(if:do:) includes: key) ifTrue: [^3].\\n\\t^0\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 13:46'!\\nanUpdatingStringMorphWith: aString special: aBoolean\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t^(aBoolean ifTrue: [SyntaxUpdatingStringMorph] ifFalse: [UpdatingStringMorph])\\n\\t\\t\\t contents: aString\\n\\t\\t\\tfont: self alansCurrentFontPreference\\n\\t].\\n\\t^UpdatingStringMorph contents: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:39'!\\nconstructSelfVariant: receiver and: key\\n\\n\\t| wordy |\\n\\t(receiver isKindOf: VariableNode) ifFalse: [^nil].\\n\\treceiver name = 'self' ifFalse: [^nil].\\n\\t(wordy _ self translateFromWordySelfVariant: key) ifNil: [^nil].\\n\\t^wordy\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:20'!\\ndarkerColor\\n\\n\\t^(Color r: 1.0 g: 0.839 b: 0.613)\\t\\\"Color lightBrown lighter lighter.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:23'!\\nfontToUseForSpecialWord: aString\\n\\n\\t^(#('Yes' 'No' 'Test') includes: aString) ifTrue: [\\n\\t\\t(StrikeFont familyName: 'Helvetica' size: 14)\\n\\t] ifFalse: [\\n\\t\\tnil\\t\\\"(StrikeFont familyName: 'ComicBold' size: 16)\\\"\\n\\t]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 09:35'!\\nlighterColor\\n\\n\\t^Color gray: 0.9\\t\\t\\n\\\"(Color r: 0.935 g: 0.935 b: 0.935)\\\"\\n\\\"paleGreen lighter\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 8/7/2001 23:15'!\\nnoiseBeforeBlockArg\\n\\n\\t^ self alansTest1 ifTrue: [' Use'] ifFalse: [' from']! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 3/25/2001 17:16'!\\nnoiseStringMorph: aNoiseString\\n\\n\\t| sMorph |\\n\\n\\tsMorph _ self aSimpleStringMorphWith: aNoiseString.\\n\\tsMorph \\n\\t\\tfont: (self fontToUseForSpecialWord: aNoiseString); \\n\\t\\tsetProperty: #noiseWord toValue: true.\\n\\n\\t^sMorph\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 8/7/2001 23:12'!\\nnoiseWordBeforeVariableNode: aNode string: aString\\n\\n\\t(#('self' 'nil') includes: aString) ifFalse: [\\n\\t\\taNode code ifNil: [^'my'].\\n\\t\\taNode type < 4 ifTrue: [^'my']\\n\\t].\\n\\t^nil! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetConditionalPartStyle\\n\\n\\tself specialColor: self lighterColor andBorder: self darkerColor.\\n\\tself useRoundedCorners.\\n\\tself borderWidth: 1.\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/27/2001 07:34'!\\nsetSpecialOuterTestFormat\\n\\n\\tself \\n\\t\\tspecialColor: self darkerColor \\n\\t\\tandBorder: self lighterColor.\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetSpecialTempDeclarationFormat1\\n\\n\\t\\\"the outer template for temp defs\\\"\\n\\n\\tself \\n\\t\\tspecialColor: self darkerColor \\n\\t\\tandBorder: self lighterColor.\\n\\t\\\"self \\n\\t\\tspecialColor: (Color lightYellow) \\n\\t\\tandBorder: (Color r: 0.581 g: 0.774 b: 0.903).\\\"\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\tself cellPositioning: #center.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 22:50'!\\nsetSpecialTempDeclarationFormat2\\n\\n\\t\\\"the inner template for temp defs\\\"\\n\\n\\tself \\n\\t\\tspecialColor: self lighterColor \\n\\t\\tandBorder: self darkerColor.\\n\\t\\\"self \\n\\t\\tspecialColor: (Color r: 1.0 g: 1.0 b: 0.548) \\n\\t\\tandBorder: (Color r: 0.581 g: 0.774 b: 0.903).\\\"\\n\\tself useRoundedCorners.\\n\\tself layoutInset: 1.\\n\\t\\\"self setProperty: #variableInsetSize toValue: 6.\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/27/2001 16:53'!\\nshouldBeBrokenIntoWords: aSymbol\\n\\n\\t^#(methodHeader1 methodHeader2 keyword2 upArrow \\n\\t\\ttempVariable tempVariableDeclaration blockarg2 variable\\n\\t\\tkeywordGetz keywordSetter unaryGetter\\n\\t\\tassignmentArrow) includes: aSymbol! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:44'!\\nspecialColor: c1 andBorder: c2\\n\\n\\tself color: (self scaleColorByUserPref: c1).\\n\\tself setProperty: #deselectedColor toValue: c1.\\n\\tself borderColor: (self scaleColorByUserPref: c2).\\n\\tself setProperty: #deselectedBorderColor toValue: c2.\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'yo 11/11/2002 10:32'!\\nsplitAtCapsAndDownshifted: aString\\n\\n\\tself flag: #yoCharCases.\\n\\n\\t^String streamContents: [ :strm |\\n\\t\\taString do: [ :each | \\n\\t\\t\\teach = $: ifFalse: [\\n\\t\\t\\t\\teach isUppercase ifTrue: [strm nextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t \\tnextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t \\tnextPut: (Character value: 0); \\n\\t\\t\\t\\t\\t\\t\\tnextPut: each asLowercase]\\n\\t\\t\\t\\t\\tifFalse: [strm nextPut: each]\\n\\t\\t\\t].\\n\\t\\t]\\n\\t].! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 23:01'!\\nstandardCellPositioning\\n\\n\\t^ self alansTest1 ifTrue: [#leftCenter] ifFalse: [#topLeft]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/25/2001 17:33'!\\nstandardInset\\n\\n\\tparseNode class == BlockNode ifTrue: [^ 5@1].\\n\\t\\t\\\"allow pointing beside a line so can replace it\\\"\\n\\t^ self alansTest1 ifTrue: [1] ifFalse: [-1]! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 4/4/2001 13:12'!\\nsubstituteKeywordFor: aString\\n\\n\\taString isEmpty ifTrue: [^aString asString].\\n\\taString asString = '^ ' ifTrue: [^'answer'].\\n\\taString asString = 'ifTrue:' ifTrue: [^'Yes'].\\n\\taString asString = 'ifFalse:' ifTrue: [^'No'].\\n\\taString asString = 'self' ifTrue: [^'self'].\\n\\taString first isUppercase ifTrue: [^aString asString].\\n\\n\\t^self splitAtCapsAndDownshifted: aString! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/28/2001 15:03'!\\ntokenVerticalSeparator\\n\\n\\t^Morph new \\n\\t\\tcolor: Color transparent;\\n\\t\\textent: 3@3;\\n\\t\\tlock\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:45'!\\ntranslateFromWordySelfVariant: key\\n\\n\\t#selfWrittenAsMe == key ifTrue: [^'me'].\\n\\t#selfWrittenAsMy == key ifTrue: [^'my'].\\n\\t#selfWrittenAsIll == key ifTrue: [^'I''ll'].\\n\\t#selfWrittenAsIm == key ifTrue: [^'I''m'].\\n\\t#selfWrittenAsThis == key ifTrue: [^'this'].\\n\\t^nil\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/28/2001 09:05'!\\ntranslateToWordyGetter: key\\n\\t\\\" setBlob: becomes 's blob _ \\\"\\n\\n\\t^ '''s ', \\n\\t (self splitAtCapsAndDownshifted: (key asString allButFirst: 3) \\n\\t\\t\\twithFirstCharacterDownshifted)! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'RAA 2/26/2001 13:45'!\\ntranslateToWordySelfVariant: aString\\n\\n\\t| lc |\\n\\tlc _ aString asLowercase.\\n\\tlc = 'me' ifTrue: [^#selfWrittenAsMe].\\n\\tlc = 'my' ifTrue: [^#selfWrittenAsMy].\\n\\tlc = 'i''ll' ifTrue: [^#selfWrittenAsIll].\\n\\tlc = 'i''m' ifTrue: [^#selfWrittenAsIm].\\n\\tlc = 'this' ifTrue: [^#selfWrittenAsThis].\\n\\t^nil\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'alans styles' stamp: 'tk 7/27/2001 17:26'!\\ntranslateToWordySetter: key\\n\\t\\\" setBlob: becomes 's blob _ \\\"\\n\\n\\t^ '''s ', \\n\\t (self splitAtCapsAndDownshifted: (key asString allButFirst: 3) allButLast \\n\\t\\t\\twithFirstCharacterDownshifted), \\n\\t ' _'! !\\n\\n\\n!SyntaxMorph methodsFor: 'card in a stack' stamp: 'tk 9/25/2001 11:46'!\\ncouldHoldSeparateDataForEachInstance\\n\\t\\\"Answer whether this type of morph is inherently capable of holding separate data for each instance ('card data')\\\"\\n\\n\\t^ true! !\\n\\n\\n!SyntaxMorph methodsFor: 'card & stack' stamp: 'tk 9/25/2001 11:41'!\\nsetNewContentsFrom: stringOrNumberOrNil\\n\\t\\\"Using stringOrNumberOrNil as a guide, set the receiver's contents afresh. If the input parameter is nil, the a default value stored in a property of the receiver, if any, will supply the new initial content. This method is only called when a VariableDock is attempting to put a new value.\\\"\\n\\n\\t(self readOut ifNil: [^ self]) setNewContentsFrom: stringOrNumberOrNil.! !\\n\\n!SyntaxMorph methodsFor: 'card & stack' stamp: 'tk 11/4/2001 21:47'!\\nsetTarget: aPlayer\\n\\t\\\"Find my UpdatingStringMorph and set its getSelector, putSelector, and target\\\"\\n\\n\\t| updatingString |\\n\\t(updatingString _ self readOut) ifNil: [^ self].\\n\\tupdatingString putSelector: (Utilities setterSelectorFor: self knownName).\\n\\tupdatingString getSelector: (Utilities getterSelectorFor: self knownName).\\n\\tupdatingString target: aPlayer. ! !\\n\\n\\n!SyntaxMorph methodsFor: 'change reporting' stamp: 'tk 9/28/2001 13:36'!\\ncolorChangedForSubmorph: colorPatch\\n\\t| sel newSel cc ms phrase completeMsg |\\n\\t\\\"reporting a color change\\\"\\n\\n\\t(self nodeClassIs: MessageNode) ifFalse: [^ nil].\\n\\t(sel _ self selector) ifNil: [^ nil].\\n\\t(Color colorNames includes: sel) | (sel == #r:g:b:) ifFalse: [^ nil].\\n\\t\\t\\\"a standard color name\\\"\\n\\t\\\"replace self with new tiles from the color\\\"\\n\\t(newSel _ (cc _ colorPatch color) name) \\n\\t\\tifNil: [ms _ MessageSend receiver: Color selector: #r:g:b: arguments: \\n\\t\\t\\t\\t(Array with: cc red with: cc green with: cc blue).\\n\\t\\t\\tphrase _ ms asTilesIn: Color globalNames: true]\\n\\t\\tifNotNil: [ms _ MessageSend receiver: Color selector: newSel arguments: #().\\n\\t\\t\\tphrase _ ms asTilesIn: Color globalNames: true].\\n\\tself deletePopup.\\n\\tcompleteMsg _ self isNoun ifTrue: [self] ifFalse: [owner].\\n\\tcompleteMsg owner replaceSubmorph: completeMsg by: phrase.\\n\\t\\\"rec setSelection: {rec. nil. rec}.\\\"\\n\\tphrase acceptIfInScriptor.! !\\n\\n\\n!SyntaxMorph methodsFor: 'classification' stamp: 'di 11/2/2000 13:25'!\\nisSyntaxMorph\\n\\t^ true! !\\n\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'di 11/17/2000 07:59'!\\ndebugger\\n\\n\\t^ self rootTile valueOfProperty: #debugger! !\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'di 11/17/2000 07:59'!\\ndebugger: x\\n\\n\\tself rootTile setProperty: #debugger toValue: x! !\\n\\n!SyntaxMorph methodsFor: 'debugging' stamp: 'RAA 8/24/1999 12:35'!\\nhostContext\\n\\n\\t^nil\\t\\t\\\"we don't have one\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'drawing' stamp: 'RAA 3/25/2001 16:16'!\\ndrawOn: aCanvas\\n\\n\\tsuper drawOn: aCanvas.\\n\\tself isBlockNode ifFalse: [^self].\\n\\tself alansTest1 ifTrue: [^self].\\n\\n\\tself immediatelyBelowTheMethodNode ifTrue: [\\n\\t\\taCanvas fillRectangle: (self topLeft + (0@-1) extent: self width@1) color: Color gray\\n\\t] ifFalse: [\\n\\t\\taCanvas fillRectangle: (self topLeft + (1@1) extent: 2@(self height-2)) color: Color gray.\\n\\t\\taCanvas fillRectangle: (self topLeft + (1@1) extent: 4@1) color: Color gray.\\n\\t\\taCanvas fillRectangle: (self bottomLeft + (1@-1) extent: 4@1) color: Color gray\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'drawing' stamp: 'tk 9/13/2001 15:13'!\\nlookTranslucent\\n\\n\\tself setDeselectedColor.\\n\\tsuper color: (self color alpha: 0.25).\\n\\tsubmorphs do: [:mm | (mm respondsTo: #lookTranslucent) \\n\\t\\tifTrue: [mm lookTranslucent]\\n\\t\\tifFalse: [\\\"mm color: color\\\"]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'di 1/29/2001 16:23'!\\ncleanupAfterItDroppedOnMe\\n\\t\\\"A tile just dropped into me. Clean up\\\"\\n\\n\\tself layoutChanged. \\\"** Isn't this already implied by the addMorph: ?\\\"\\n\\t\\\"Auto-accept on drop if in a scriptor\\\"\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'di 5/4/2001 13:16'!\\nhighlightForDrop: evt\\n\\n\\t(self wantsDroppedMorph: evt hand firstSubmorph event: evt)\\n\\t\\tifTrue: [self color: self dropColor].! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 7/19/2001 19:04'!\\njustDroppedInto: aMorph event: evt\\n\\taMorph isSyntaxMorph ifFalse:\\n\\t\\t[Preferences tileTranslucentDrag\\n\\t\\t\\tifTrue: [self setDeselectedColor]\\n\\t\\t\\tifFalse: [self align: self topLeft with: self topLeft - self cursorBaseOffset]].\\n\\tself removeProperty: #beScript.\\n\\t^ super justDroppedInto: aMorph event: evt! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 9/30/2001 11:09'!\\nmorphToDropInPasteUp: aPasteUp\\n\\t\\\"If property #beScript is true, create a scriptor around me.\\\"\\n\\n\\t| actualObject itsSelector aScriptor adjustment handy tw blk |\\n\\t(self valueOfProperty: #beScript ifAbsent: [false]) ifFalse: [^ self].\\n\\tself removeProperty: #beScript.\\n\\tactualObject _ self actualObject ifNil: [\\n\\t\\t\\t\\t\\tself valueOfProperty: #scriptedPlayer ifAbsent: [nil]].\\n\\tactualObject ifNil: [^ self].\\n\\tself removeProperty: #scriptedPlayer.\\n\\tactualObject assureUniClass.\\n\\n\\titsSelector _ self userScriptSelector.\\n\\taScriptor _ itsSelector isEmptyOrNil\\n\\t\\tifFalse:\\n\\t\\t\\t[adjustment _ 0@0.\\n\\t\\t\\tactualObject scriptEditorFor: itsSelector]\\n\\t\\tifTrue:\\n\\t\\t\\t[adjustment _ 60 @ 20.\\n\\t\\t\\tactualObject newScriptorAround: self].\\n\\taScriptor ifNil: [^self].\\n\\thandy _ aPasteUp primaryHand.\\n\\n\\taScriptor position: handy position - adjustment.\\n\\taPasteUp addMorphFront: aScriptor.\\t\\\"do this early so can find World\\\"\\n\\taScriptor showingMethodPane ifFalse: [\\n\\t\\t\\\"(tw _ aScriptor findA: TwoWayScrollPane) ifNil:\\n\\t\\t\\t[itsSelector ifNil: ['blank script'.\\n\\t\\t\\t\\ttw _ aScriptor findA: TwoWayScrollPane.\\n\\t\\t\\t\\tblk _ (tw scroller findA: SyntaxMorph \\\"\\\"MethodNode\\\"\\\") findA: BlockNode.\\n\\t\\t\\t\\tblk addMorphFront: self]].\\n\\t\\t\\\"\\n\\t\\tSyntaxMorph setSize: nil andMakeResizable: aScriptor.\\n\\t\\t].\\n\\t^ aScriptor\\n! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'tk 9/24/2001 10:04'!\\nstructureMatchWith: aMorph\\n\\t| meNoun itNoun |\\n\\t\\\"Return true if the node types would allow aMorph to replace me. This tests the gross structure of the method only.\\\"\\n\\n\\tmeNoun _ self isNoun.\\n\\titNoun _ aMorph isNoun.\\n\\n\\t\\\"Consider these nouns to be equal: TempVariableNode, LiteralNode, VariableNode, (MessageNode with receiver), CascadeNode, AssignmentNode\\\"\\n\\tmeNoun & itNoun ifTrue: [^ true].\\n\\tmeNoun & aMorph isBlockNode ifTrue: [^ true].\\n\\n\\t\\\"If I am a BlockNode, and it is a TempVariableNode, add it into list\\\"\\n\\t\\\"If I am a BlockNode, and it is a noun, add it as a new line\\\"\\n\\tself isBlockNode ifTrue:\\n\\t\\t[itNoun ifTrue: [^ true].\\n\\t\\t(aMorph nodeClassIs: ReturnNode) ifTrue:\\n\\t\\t\\t[^ (self submorphs\\n\\t\\t\\t\\tdetect: [:mm | ((mm isSyntaxMorph) and: [mm nodeClassIs: ReturnNode])]\\n\\t\\t\\t\\tifNone: [nil]) isNil].\\t\\\"none already in this block\\\"\\n\\t\\t\\t\\t\\\"If I am a BlockNode, and it is a ReturnNode, add to end\\\"\\n\\t\\t(aMorph nodeClassIs: CommentNode) ifTrue: [^ true]].\\n\\n\\t(self isMethodNode) ifTrue: [^ false].\\t\\\"Later add args and keywords\\\"\\n\\t\\t\\\"Later allow comments to be dropped in\\\"\\n\\t\\t\\\"Add MethodTemps by dropping into the main block\\\"\\n\\n\\t(self nodeClassIs: ReturnNode) & (aMorph parseNode class == MessageNode) \\n\\t\\tifTrue: [^ true].\\t\\t\\\"Command replace Return\\\"\\n\\t(self nodeClassIs: MessageNode) & (aMorph parseNode class == ReturnNode) ifTrue: [\\n\\t\\t(owner submorphs select: [:ss | ss isSyntaxMorph]) last == self\\n\\t\\t\\tifTrue: [^ true]].\\t\\\"Return replace last command\\\"\\n\\n\\t(aMorph nodeClassIs: AssignmentNode) ifTrue: [\\n\\t\\titNoun ifFalse: [\\\"create a new assignment\\\"\\n\\t\\t\\t^ self isAVariable & self isDeclaration not]].\\t\\\"only assign to a variable\\\"\\n\\n\\t\\\"If nodes are of equal class, replace me with new one.\\\"\\n\\t(self nodeClassIs: aMorph parseNode class) ifTrue: [\\n\\t\\t(self nodeClassIs: MessageNode) \\n\\t\\t\\t\\tifFalse: [^ true]\\t\\\"normal match\\\"\\n\\t\\t\\t\\tifTrue: [^ self receiverNode == aMorph receiverNode]].\\t\\\"both nil\\\"\\n\\n\\t^ false \\\"otherwise reject\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'dropping/grabbing' stamp: 'gm 2/22/2003 12:49'!\\nwantsDroppedMorph: aMorph event: evt \\n\\t\\\"For the moment, you have to drop it the right place. We do not look at enclosing morphs\\\"\\n\\n\\t\\\"Two ways to do this: Must always destroy old node, then drag in new one.\\n\\t\\tOr, drop replaces what you drop on. Nasty with blocks.\\\"\\n\\n\\t(aMorph isSyntaxMorph) ifFalse: [^false].\\n\\t(self structureMatchWith: aMorph) ifFalse: [^false].\\t\\\"gross structure\\\"\\n\\n\\t\\\"Only look at types if NoviceMode -- building EToys\\\"\\n\\t^self okToBeReplacedBy: aMorph\\t\\\"test the types\\\"\\n\\n\\t\\\"^ true\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/8/2000 22:05'!\\ncursorBaseOffset\\n\\n\\t^ 7@14\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/6/2000 16:20'!\\nhandlesKeyboard: evt\\n\\t^ evt keyCharacter = Character backspace! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 13:39'!\\nhandlesMouseDown: evt \\n\\tevt yellowButtonPressed ifTrue: [^true].\\n\\tparseNode isNil ifTrue: [^false].\\n\\towner isSyntaxMorph \\n\\t\\tifTrue: [(owner isMethodNode and: [self isBlockNode not]) ifTrue: [^false]].\\t\\\"Can only take block out of a MethodNode\\\"\\n\\t^true! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 10/26/2000 16:58'!\\nhandlesMouseOver: evt\\n\\t\\\"Am I a tile that could be picked up?\\\"\\n\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/6/2000 08:21'!\\nhandlesMouseOverDragging: evt\\n\\n\\t^ evt hand hasSubmorphs\\n\\t\\tand: [evt hand firstSubmorph isSyntaxMorph]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/17/2000 08:21'!\\nkeyStroke: evt\\n\\t\\\"Handle a keystroke event.\\\"\\n\\t| spacer |\\n\\tevt keyCharacter = Character backspace ifTrue:\\n\\t\\t[(owner notNil and: [owner isSyntaxMorph]) ifTrue:\\n\\t\\t\\t[owner isBlockNode ifTrue:\\n\\t\\t\\t\\t[\\\"Delete a statement.\\\"\\n\\t\\t\\t\\t(spacer _ self submorphAfter) class == AlignmentMorph\\n\\t\\t\\t\\t\\t\\tifTrue: [spacer delete].\\n\\t\\t\\t\\tself delete].\\n\\t\\t\\t]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 9/26/2001 05:56'!\\nmouseDown: evt \\n\\t| dup rootTile |\\n\\tevt yellowButtonPressed ifTrue: [^ self showMenu: evt].\\n\\t(rootTile _ self rootTile) isMethodNode ifTrue:\\n\\t\\t[self currentSelectionDo:\\n\\t\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\t\\t(outerMorph notNil and: [self == innerMorph])\\n\\t\\t\\t\\tifTrue: [\\\"Click on prior selection -- record click point.\\\"\\n\\t\\t\\t\\t\\t\\tself setSelection: {self. evt cursorPoint. outerMorph}]\\n\\t\\t\\t\\tifFalse: [\\\"A new selection sequence.\\\"\\n\\t\\t\\t\\t\\t\\tself setSelection: {self. evt cursorPoint. nil}]].\\n\\t\\t^ self].\\n\\n\\t\\\"Out in the world -- treat as a unit\\\"\\n\\trootTile isSticky ifTrue: [^ self].\\t\\\"later may allow to be selected\\\"\\n\\trootTile isPartsDonor \\n\\t\\tifTrue: [dup _ rootTile duplicate.\\n\\t\\t\\t\\tdup setProperty: #beScript toValue: true]\\n\\t\\tifFalse: [dup _ rootTile].\\n\\tevt hand attachMorph: dup.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [^ dup lookTranslucent]\\n\\t\\tifFalse: [^ dup align: dup topLeft with: evt hand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 7/19/2001 20:21'!\\nmouseEnter: evt\\n\\t\\\"Highlight this level as a potential grab target\\\"\\n\\n\\\"Transcript cr; print: self; show: ' enter'.\\\"\\n\\tself rootTile isMethodNode ifFalse: [^ self]. \\t\\\"not in a script\\\"\\n\\tself unhighlightOwnerBorder.\\n\\tself highlightForGrab: evt.\\n\\tevt hand newKeyboardFocus: self.\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 7/25/2001 10:09'!\\nmouseEnterDragging: evt\\n\\t\\\"Highlight this level as a potential drop target\\\"\\n\\n\\\"self isBlockNode ifTrue: [Transcript cr; print: self; show: ' enterDragging'].\\\"\\n\\tself rootTile isMethodNode ifFalse: [^ self]. \\t\\\"not in a script\\\"\\n\\n\\tevt hand hasSubmorphs ifFalse: [^ self]. \\\"Don't react to empty hand\\\"\\n\\tself unhighlightOwnerBorder.\\n\\tself isBlockNode ifFalse: [self highlightForDrop: evt.\\n\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m color = self dropColor]])\\n\\t\\t\\tifNotNilDo: [:m | m unhighlight]].\\n\\n\\tself isBlockNode ifTrue:\\n\\t\\t[(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]])\\n\\t\\t\\tifNotNilDo: [:m | \\\"Suspend outer block.\\\"\\n\\t\\t\\t\\t\\t\\tm stopStepping; removeDropZones].\\n\\t\\tself startStepping]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 18:48'!\\nmouseLeave: evt \\n\\t\\\"Move grab highlight back out a level\\\"\\n\\n\\t\\\"Transcript cr; print: self; show: ' leave'.\\\"\\n\\n\\tself rootTile isMethodNode ifFalse: [^self].\\t\\\"not in a script\\\"\\n\\tself unhighlightBorder.\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner highlightForGrab: evt]! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'dgd 2/22/2003 18:48'!\\nmouseLeaveDragging: evt \\n\\t\\\"Transcript cr; print: self; show: ' leaveDragging'.\\\"\\n\\n\\tself rootTile isMethodNode ifFalse: [^self].\\t\\\"not in a script\\\"\\n\\tself isBlockNode \\n\\t\\tifTrue: \\n\\t\\t\\t[self\\n\\t\\t\\t\\tstopStepping;\\n\\t\\t\\t\\tremoveDropZones.\\n\\t\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]]) \\n\\t\\t\\t\\tifNotNilDo: [:m | m startStepping].\\t\\\"Activate outer block.\\\"\\n\\t\\t\\tself submorphs do: \\n\\t\\t\\t\\t\\t[:ss | \\n\\t\\t\\t\\t\\t\\\"cancel drop color in line beside mouse\\\"\\n\\n\\t\\t\\t\\t\\tss color = self dropColor ifTrue: [ss setDeselectedColor]]].\\n\\n\\t\\\"Move drop highlight back out a level\\\"\\n\\tself unhighlight.\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner isBlockNode ifFalse: [owner highlightForDrop: evt]]! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 10/17/2001 13:41'!\\nmouseMove: evt\\n\\t| dup selection |\\n\\towner isSyntaxMorph ifFalse: [^ self].\\n\\nfalse ifTrue: [\\\"for now, do not drag off a tile\\\"\\n\\tself currentSelectionDo:\\n\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tmouseDownLoc ifNotNil: [\\n\\t\\t\\t(evt cursorPoint dist: mouseDownLoc) > 4 ifTrue:\\n\\t\\t\\t\\t[\\\"If drag 5 pixels, then tear off a copy of outer selection.\\\"\\n\\t\\t\\t\\tselection _ outerMorph ifNil: [self].\\n\\t\\t\\t\\tselection deletePopup.\\n\\t\\t\\t\\tevt hand attachMorph: (dup _ selection duplicate).\\n\\t\\t\\t\\tPreferences tileTranslucentDrag\\n\\t\\t\\t\\t\\tifTrue: [dup lookTranslucent]\\n\\t\\t\\t\\t\\tifFalse: [dup align: dup topLeft\\n\\t\\t\\t\\t\\t\\t\\t\\twith: evt hand position + self cursorBaseOffset].\\n\\t\\t\\t\\tself setSelection: nil.\\t\\\"Why doesn't this deselect?\\\"\\n\\t\\t\\t\\t(self firstOwnerSuchThat: [:m | m isSyntaxMorph and: [m isBlockNode]])\\n\\t\\t\\t\\t\\tifNotNilDo: [:m | \\\"Activate enclosing block.\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tm startStepping]]]].\\n\\t].! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'di 11/17/2000 08:13'!\\nmouseUp: evt\\n\\t| newSel |\\n\\tself rootTile isMethodNode ifFalse: [^ self].\\n\\tself currentSelectionDo:\\n\\t\\t[:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tnewSel _ outerMorph\\n\\t\\t\\tifNil: [self \\\"first click\\\"]\\n\\t\\t\\tifNotNil: [(outerMorph firstOwnerSuchThat:\\n\\t\\t\\t\\t\\t\\t\\t[:m | m isSyntaxMorph and: [m isSelectable]]) ifNil: [self]].\\n\\t\\tnewSel isMethodNode ifTrue: [^ self setSelection: nil].\\n\\t\\tself setSelection: {self. nil. newSel}]\\n! !\\n\\n!SyntaxMorph methodsFor: 'event handling' stamp: 'tk 12/1/2000 15:42'!\\nwantsKeyboardFocusFor: aSubmorph\\n\\t| doEdit |\\n\\t\\\"only let strings edit on shift-click. Editing on ordinary click defeats the brown selection and tile dragging.\\\"\\n\\n\\tdoEdit _ self world primaryHand lastEvent shiftPressed.\\n\\tdoEdit ifTrue: [\\\"remove the arrows during editing\\\"\\n\\t\\tself valueOfProperty: #myPopup ifPresentDo: [:panel |\\n\\t\\t\\tpanel delete. self removeProperty: #myPopup]].\\n\\t^ doEdit! !\\n\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'di 2/21/2001 11:42'!\\nalansTest1\\n\\t\\n\\t| root |\\n\\n\\troot _ self rootTile ifNil: [self].\\n\\t^root valueOfProperty: #alansNewStyle ifAbsent: [self usingClassicTiles not]! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:02'!\\ncontrolContrast2: evt\\n\\n\\t| origin scale startingContrastX |\\n\\n\\tevt isMouseUp ifTrue: [\\n\\t\\t^self removeProperty: #startingPointForSomeAdjustment\\n\\t].\\n\\tevt isMouseDown ifTrue: [\\n\\t\\t^self setProperty: #startingPointForSomeAdjustment toValue: evt cursorPoint\\n\\t].\\n\\tContrastFactor ifNil: [ContrastFactor _ 0.5].\\n\\tscale _ 200.0.\\n\\tstartingContrastX _ ContrastFactor * scale.\\n\\torigin _ self valueOfProperty: #startingPointForSomeAdjustment.\\n\\tContrastFactor _ (evt cursorPoint x - origin x + startingContrastX) / scale min: 1.0 max: 0.0.\\n\\tself finalAppearanceTweaks.\\n! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:07'!\\ncontrolContrast: evt\\n\\n\\t\\\"old version. may be some scripts saved with me, so don't crash\\\"\\n\\t^self! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 5/11/2001 07:41'!\\ncontrolSpacing2: evt\\n\\n\\t| origin scale startingContrastX |\\n\\n\\tevt isMouseUp ifTrue: [\\n\\t\\t^self removeProperty: #startingPointForSomeAdjustment\\n\\t].\\n\\tevt isMouseDown ifTrue: [\\n\\t\\t^self setProperty: #startingPointForSomeAdjustment toValue: evt cursorPoint\\n\\t].\\n\\tSizeScaleFactor ifNil: [SizeScaleFactor _ 0.15].\\n\\tscale _ 200.0.\\n\\tstartingContrastX _ SizeScaleFactor * scale.\\n\\torigin _ self valueOfProperty: #startingPointForSomeAdjustment.\\n\\tSizeScaleFactor _ (evt cursorPoint x - origin x + startingContrastX) / scale min: 1.0 max: 0.0.\\n\\tself finalAppearanceTweaks.\\n! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'RAA 2/26/2001 09:07'!\\ncontrolSpacing: evt\\n\\n\\t\\\"old version. may be some scripts saved with me, so don't crash\\\"\\n\\t^self! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'di 2/21/2001 12:30'!\\nlookClassic\\n\\tself isLeafTile ifTrue: [self layoutInset: 2@4]! !\\n\\n!SyntaxMorph methodsFor: 'formatting options' stamp: 'tk 7/18/2001 16:00'!\\nusingClassicTiles \\n\\n\\t^ Preferences uniTilesClassic! !\\n\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/30/2001 14:48'!\\ncompoundBorderColor \\n\\n\\t^ self valueOfProperty: #deselectedBorderColor ifAbsent: [Color veryLightGray]\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 11/5/2000 07:26'!\\ndropColor\\n\\t^ Color green darker! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/23/2001 18:28'!\\ngrabColor\\n\\n\\t\\\"Not the select color, but the mouseOver border color. Means it could be grabbed\\\"\\n\\t^ Color paleOrange mixed: 0.5 with: Color brown! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 11/6/2000 09:22'!\\nhighlightForGrab: evt\\n\\n\\tself borderColor: self grabColor.! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/19/2001 19:09'!\\nstdBorderColor \\n\\n\\t\\\"put choices of how to do the border here\\\"\\n\\t^ self valueOfProperty: #deselectedBorderColor ifAbsent: [Color transparent]! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'tk 7/19/2001 19:50'!\\nunhighlight\\n\\n\\tself setDeselectedColor.\\n\\n\\nfalse ifTrue: [\\n\\tself currentSelectionDo: [:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tself color: ( false\\n\\t\\t\\t\\\"(self == outerMorph or: [owner notNil and: [owner isSyntaxMorph not]])\\\"\\n\\t\\t\\t\\tifTrue: [self valueOfProperty: #deselectedBorderColor ifAbsent: [#raised]]\\n\\t\\t\\t\\tifFalse: [self color: Color transparent]\\n\\t\\t)\\n\\t]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'di 5/4/2001 13:21'!\\nunhighlightBorder\\n\\n\\tself currentSelectionDo: [:innerMorph :mouseDownLoc :outerMorph |\\n\\t\\tself borderColor: (\\n\\t\\t\\t(self == outerMorph or: [owner notNil and: [owner isSyntaxMorph not]])\\n\\t\\t\\t\\tifTrue: [self valueOfProperty: #deselectedBorderColor ifAbsent: [#raised]]\\n\\t\\t\\t\\tifFalse: [self stdBorderColor]\\n\\t\\t)\\n\\t]\\n! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'dgd 2/22/2003 18:48'!\\nunhighlightOwner\\n\\t\\\"Unhighlight my owner\\\"\\n\\n\\t(owner notNil and: [owner isSyntaxMorph]) ifTrue: [owner unhighlight]! !\\n\\n!SyntaxMorph methodsFor: 'highlighting' stamp: 'dgd 2/22/2003 18:49'!\\nunhighlightOwnerBorder\\n\\t\\\"Unhighlight my owner's border\\\"\\n\\n\\t(owner notNil and: [owner isSyntaxMorph]) \\n\\t\\tifTrue: [owner unhighlightBorder]! !\\n\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'sw 3/6/2001 11:26'!\\ninAPluggableScrollPane\\n\\t\\\"Answer a PluggableTileScriptorMorph that holds the receiver\\\"\\n\\n\\t| widget |\\n\\twidget _ PluggableTileScriptorMorph new.\\n\\twidget extent: 10@10; borderWidth: 0.\\n\\twidget scroller addMorph: self.\\n\\twidget setScrollDeltas.\\n\\twidget hResizing: #spaceFill; vResizing: #spaceFill.\\n\\t^ widget\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'sw 6/26/2001 10:58'!\\ninAScrollPane\\n\\t\\\"Answer a scroll pane in which the receiver is scrollable\\\"\\n\\n\\t^ self inATwoWayScrollPane! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'di 1/31/2001 10:14'!\\nopenInWindow\\n\\n\\t| window widget sel |\\n\\tsel _ ''.\\n\\tself firstSubmorph allMorphs do: [:rr | \\n\\t\\t\\t(rr isKindOf: StringMorph) ifTrue: [sel _ sel, rr contents]].\\n\\twindow _ (SystemWindow labelled: 'Tiles for ', self parsedInClass printString, '>>',sel).\\n\\twidget _ self inAScrollPane.\\n\\twidget color: Color paleOrange.\\n\\twindow\\n\\t\\taddMorph: widget\\n\\t\\tframe: (0@0 extent: 1.0@1.0).\\n\\twindow openInWorldExtent: (\\n\\t\\tself extent + (20@40) min: (Display boundingBox extent * 0.8) rounded\\n\\t)\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'FBS 2/24/2004 14:21'!\\nreturnNode: aNode expression: expr\\n\\n\\t| row expMorph sMorph aNoiseString |\\n\\trow _ self addRow: #return on: aNode.\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t\\taNoiseString _ ' Reply '.\\n\\t\\tsMorph _ self aSimpleStringMorphWith: aNoiseString.\\n\\t\\tsMorph \\n\\t\\t\\temphasis: TextEmphasis bold emphasisCode;\\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: '^'.\\n\\n\\t\\trow addMorphBack: sMorph.\\n\\t] ifFalse: [\\n\\t\\trow addToken: '^ ' type: #upArrow on: aNode.\\n\\t].\\n\\texpMorph _ expr asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [\\n\\t\\t(expMorph hasProperty: #deselectedColor) ifFalse: [expMorph setConditionalPartStyle].\\n\\t].\\n\\texpr addCommentToMorph: row.\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'initialization' stamp: 'tk 1/19/2001 13:29'!\\nsample: arg1\\n\\\"a comment\\\"\\n| temp1 |\\ntemp1 _ 5.\\ntemp1 yourself.\\ntemp1 min: arg1.! !\\n\\n\\n!SyntaxMorph methodsFor: 'insertion drop zones' stamp: 'di 1/30/2001 21:00'!\\nremoveDropZones\\n\\t\\\"Remove the insertion drop-zone morphs.\\\"\\n\\n\\tself submorphsDo:\\n\\t\\t[:mm | (mm isMemberOf: BorderedMorph) ifTrue: [mm delete]].\\n! !\\n\\n!SyntaxMorph methodsFor: 'insertion drop zones' stamp: 'tk 9/13/2001 15:24'!\\ntrackDropZones\\n\\t| hand i localPt insertion insHt ii prevBot nxtHt d c1 c2 ht2 spacer1 spacer2 wid ht1 dc each |\\n\\thand _ self primaryHand.\\n\\t(\\\"hand lastEvent redButtonPressed &\\\" hand hasSubmorphs\\n\\t\\tand: [(self hasOwner: hand) not]) ifFalse: [^ self].\\n\\n\\tinsertion _ hand firstSubmorph renderedMorph.\\n\\tinsertion isSyntaxMorph ifFalse: [^ self].\\n\\tinsertion isNoun ifFalse: [(insertion nodeClassIs: CommentNode) ifFalse: [^ self]].\\n\\tlocalPt _ self globalPointToLocal: hand position.\\n\\tinsHt _ insertion height. \\\"**just use standard line height here\\\"\\n\\tself removeDropZones. \\\"Maybe first check if in right place, then just tweak heights.\\\"\\n\\ti _ (ii _ self indexOfMorphAbove: localPt) min: submorphs size-1.\\n\\tprevBot _ i <= 0 ifTrue: [(self innerBounds) top]\\n\\t\\t\\t\\t\\tifFalse: [(self submorphs at: i) bottom].\\n\\tnxtHt _ (submorphs isEmpty\\n\\t\\tifTrue: [insertion]\\n\\t\\tifFalse: [self submorphs at: i+1]) height.\\n\\td _ ii > i ifTrue: [nxtHt \\\"for consistent behavior at bottom\\\"]\\n\\t\\t\\tifFalse: [0 max: (localPt y - prevBot min: nxtHt)].\\n\\n\\t\\\"Top and bottom spacer heights cause continuous motion...\\\"\\n\\tc1 _ Color transparent. c2 _ Color transparent.\\n\\tht2 _ d*insHt//nxtHt. ht1 _ insHt - ht2.\\n\\twid _ self width - (2*borderWidth) - (2*self layoutInset).\\n\\twid isPoint ifTrue: [wid _ wid x].\\n\\t(spacer1 _ BorderedMorph newBounds: (0@0 extent: wid@ht1)\\n\\t\\t\\t\\tcolor: (ht1 > (insHt//2) ifTrue: [c1] ifFalse: [c2]))\\n\\t\\t\\t\\t\\tborderWidth: 1; borderColor: spacer1 color.\\n\\tself privateAddMorph: spacer1 atIndex: (i+1 max: 1).\\n\\t(spacer2 _ BorderedMorph newBounds: (0@0 extent: wid@ht2)\\n\\t\\t\\t\\tcolor: (ht2 > (insHt//2+1) ifTrue: [c1] ifFalse: [c2]))\\n\\t\\t\\t\\t\\tborderWidth: 1; borderColor: spacer2 color.\\n\\tspacer1 setProperty: #dropZone toValue: true.\\n\\tspacer2 setProperty: #dropZone toValue: true.\\n\\tself privateAddMorph: spacer2 atIndex: (i+3 min: submorphs size+1).\\n\\tself fullBounds. \\\"Force layout prior to testing for cursor containment\\\"\\n\\n\\t\\\"Maintain the drop target highlight -- highlight spacer if hand is in it.\\\"\\n\\t{spacer1. spacer2} do:\\n\\t\\t[:spacer | (spacer containsPoint: localPt) ifTrue:\\n\\t\\t\\t[spacer color: self dropColor.\\n\\t\\t\\t\\\"Ignore border color. Maybe do it later.\\n\\t\\t\\tself borderColor = self dropColor\\n\\t\\t\\t\\tifTrue: [self borderColor: self stdBorderColor]\\\"]].\\n\\t\\\"If no submorph (incl spacers) highlighted, then re-highlight the block.\\\"\\n\\t\\\"Ignore border color. Maybe do it later.\\n\\t((self wantsDroppedMorph: insertion event: hand lastEvent) and:\\n\\t\\t[(self submorphs anySatisfy: [:m | m containsPoint: localPt]) not])\\n\\t\\t\\tifTrue: [self borderColor: self dropColor].\\n\\t\\\"\\n\\n\\t\\\"Dragging a tile within a Block, if beside a tile, color it a dropzone\\\"\\n\\t\\\"Transcript show: localPt y printString; space; show: submorphs first top \\n\\t\\tprintString; space; show: submorphs last top printString; cr.\\\"\\n\\tdc _ self dropColor.\\n\\t1 to: ((ii+4 min: submorphs size) max: 1) do: [:ind | \\n\\t\\teach _ submorphs at: ind.\\n\\t\\teach isSyntaxMorph ifTrue: [\\n\\t\\t\\tlocalPt y >= each top \\n\\t\\t\\t\\tifTrue: [\\\"in this one or beyond\\\"\\n\\t\\t\\t\\t\\t(localPt y < each bottom) \\n\\t\\t\\t\\t\\t\\tifTrue: [(each submorphs anySatisfy: [:m | \\n\\t\\t\\t\\t\\t\\t\\t\\tm containsPoint: localPt])\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [each setDeselectedColor]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [each color: dc]]\\n\\t\\t\\t\\t\\t\\tifFalse: [each color = dc ifTrue: [each setDeselectedColor]]]\\n\\t\\t\\t\\tifFalse: [each color = dc ifTrue: [each setDeselectedColor]]]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 9/13/2001 15:28'!\\nacceptDroppingMorph: aMorph event: evt\\n\\t| itNoun old |\\n\\t\\\"Two cases: 1) a phrase being dropped into a block. Add a new line.\\n\\t\\t2) aMorph is replacing self by dropping on it.\\n\\tFor the moment, you have to drop it the right place (the end of a tile if it is complex). We do not look at enclosing morphs\\\"\\n\\n\\titNoun _ aMorph isNoun.\\n\\tself withAllOwnersDo:\\n\\t\\t[:m | (m isSyntaxMorph and: [m isBlockNode])\\n\\t\\t\\t\\tifTrue: [m stopStepping; removeDropZones]].\\n\\tself isBlockNode & itNoun ifTrue:\\n\\t\\t[(aMorph nodeClassIs: TempVariableNode) ifTrue:\\n\\t\\t\\t\\t[\\\"If I am a BlockNode, and it is a TempVariableNode, add it into list\\\"\\n\\t\\t\\t\\t(self addBlockArg: aMorph)].\\n\\t\\t\\\"If I am a BlockNode and it is a noun add it as a new line\\\"\\n\\t\\t^ self addToBlock: aMorph event: evt].\\n\\t\\t\\t\\t\\n\\tself isBlockNode ifTrue: [\\n\\t\\t (aMorph nodeClassIs: CommentNode) ifTrue: [^ self addToBlock: aMorph event: evt].\\n\\t\\t (aMorph nodeClassIs: ReturnNode) ifTrue: [^ self addToBlock: aMorph event: evt]].\\n\\n\\t\\\"Later add args and keywords. later allow comments to be dropped\\\"\\n\\n\\t\\\"Can't put statement, literal, assignment, or cascade into left side of assignment\\\"\\n\\t(owner isSyntaxMorph) ifTrue:\\n\\t\\t[(owner nodeClassIs: AssignmentNode) ifTrue:\\n\\t\\t\\t[(owner submorphIndexOf: self) = 1 ifTrue:\\n\\t\\t\\t\\t[aMorph isAVariable ifFalse: [ ^ self]]]].\\n\\n\\t(aMorph nodeClassIs: AssignmentNode) ifTrue: [\\n\\t\\titNoun ifFalse: [\\\"create a new assignment\\\"\\n\\t\\t\\tself isAVariable ifTrue: [^ self newAssignment]\\n\\t\\t\\t\\t\\tifFalse: [^ self]]].\\t\\\"only assign to a variable\\\"\\n\\n\\taMorph deselect.\\n\\t(old _ owner) replaceSubmorph: self by: aMorph.\\t\\\"do the normal replacement\\\"\\n\\t(old isSyntaxMorph) ifTrue: [old cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:24'!\\naddBlockArg: aMorph\\n\\t\\\"Add a temporary to a block or the method. Return true if succeed\\\"\\n\\t\\\"(aMorph nodeClassIs: TempVariableNode) is known to be true.\\\"\\n\\t\\\"***NOTE: This method should be combined with addTempVar:\\\"\\n\\n\\t| tempHolder tt var nn |\\n\\towner isMethodNode ifTrue: [\\n\\t\\t^ (self addTempVar: aMorph)].\\t\\\"Node for them is not inside the block\\\"\\n\\t\\t\\\"If exists, drop the temp in this block and let user extend it.\\\"\\n\\tnn _ aMorph decompile string.\\t\\\"name\\\"\\n\\t(self isKnownVarName: nn) ifTrue: [^ false].\\t\\\"already defined\\\"\\n\\n\\ttt _ self firstSubmorph.\\n\\ttempHolder _ tt firstSubmorph isSyntaxMorph \\n\\t\\t\\t\\tifTrue: [(tt nodeClassIs: BlockArgsNode) \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [tt] ifFalse: [nil]]\\n\\t\\t\\t\\tifFalse: [nil].\\n\\n\\ttempHolder ifNil: [\\\"make new row\\\"\\n\\t\\ttempHolder _ self addRow: #blockarg1 on: (BlockArgsNode new).\\n\\t\\ttempHolder addNoiseString: self noiseBeforeBlockArg.\\n\\t\\ttempHolder submorphs last firstSubmorph emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttempHolder useRoundedCorners.\\n\\n\\t\\tself addMorphFront: tempHolder.\\n\\t\\taMorph parseNode name: nn key: nn code: nil.\\n\\t\\taMorph parseNode asMorphicSyntaxIn: tempHolder.\\n\\t\\ttempHolder cleanupAfterItDroppedOnMe.\\n\\t\\t^ true].\\n\\n\\t\\\"Know this variable is not present, so add it\\\"\\n\\n\\taMorph parseNode name: nn key: nn code: nil.\\n\\ttempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4).\\n\\tvar _ tempHolder addRow: #tempVariable on: aMorph parseNode.\\n\\tvar layoutInset: 1.\\n\\tvar addMorphBack: (self aSimpleStringMorphWith: nn).\\n\\tvar cleanupAfterItDroppedOnMe.\\n\\t^ true\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 16:15'!\\naddColumn: aColorOrSymbol on: aNode\\n\\t| col |\\n\\tself addMorphBack: (col _ self class column: aColorOrSymbol on: aNode).\\n\\n\\\"col setProperty: #howCreated toValue: thisContext longStack.\\\"\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\t(aColorOrSymbol == #block and: [self isMethodNode not]) ifTrue: [\\n\\t\\t\\tcol setConditionalPartStyle.\\n\\t\\t].\\n\\t].\\n\\t^ col\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:44'!\\naddNoiseString: aNoiseString\\n\\n\\t^self addNoiseString: aNoiseString emphasis: TextEmphasis normal emphasisCode.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 16:17'!\\naddNoiseString: aNoiseString emphasis: anInteger\\n\\n\\tself alansTest1 ifFalse: [^self].\\n\\t^(self addColumn: #keyword1 on: nil)\\n\\t\\tlayoutInset: 1;\\n\\t\\taddMorphBack: ((self noiseStringMorph: aNoiseString) emphasis: anInteger)\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/15/2001 19:22'!\\naddRow: aColorOrSymbol on: aNode\\n\\n\\t| row |\\n\\tself addMorphBack: (row _ self class row: aColorOrSymbol on: aNode).\\n\\n\\\"row setProperty: #howCreated toValue: thisContext longStack.\\\"\\n\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/24/2001 15:15'!\\naddSingleKeywordRow: aStringLikeItem\\n\\n\\t| row sMorph modifiedString |\\n\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\n\\tmodifiedString _ self substituteKeywordFor: aStringLikeItem.\\n\\tsMorph _ self addString: modifiedString special: true.\\n\\tsMorph font: (self fontToUseForSpecialWord: modifiedString).\\n\\tmodifiedString = aStringLikeItem ifFalse: [\\n\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem].\\n\\n\\trow addMorph: sMorph.\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 4/4/2001 13:15'!\\naddString: literalOrVarName special: aBoolean\\n\\n\\t| answer |\\n\\t\\\"Create and return an UpdatingStringMorph containing the value. Use an UpdatingStringMorph, so it can inform its owner when it has been edited. Keep the getSelector being nil\\\"\\n\\n\\tanswer _ (self anUpdatingStringMorphWith: literalOrVarName special: aBoolean)\\n\\t\\ttarget: self;\\n\\t\\tputSelector: #acceptIgnoring:;\\n\\t\\tuseStringFormat.\\n\\n\\t^answer\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:23'!\\naddTempVar: aMorph \\n\\t\\\"know we are a block inside a MethodNode\\\" \\n\\t\\\"(aMorph nodeClassIs: TempVariableNode) is known to be true.\\\"\\n\\t| tempHolder ii tt var nn |\\n\\tnn _ aMorph decompile string.\\t\\\"name\\\"\\n\\t(self isKnownVarName: nn) ifTrue: [^ false].\\t\\\"already defined\\\"\\n\\n\\ttempHolder _ nil.\\n\\t(ii _ owner submorphIndexOf: self) = 1 ifFalse: [\\n\\t\\ttt _ owner submorphs at: ii - 1.\\n\\t\\ttt isSyntaxMorph ifTrue: [\\n\\t\\t\\t(tt nodeClassIs: MethodTempsNode) ifTrue: [tempHolder _ tt].\\n\\t\\t\\t(tt nodeClassIs: UndefinedObject) ifTrue: [tempHolder _ tt findA: MethodTempsNode]]].\\n\\n\\ttempHolder ifNil: [\\n\\t\\ttempHolder _ owner addRow: #tempVariable on: MethodTempsNode new.\\n\\t\\ttempHolder addNoiseString: self noiseBeforeBlockArg.\\n\\t\\ttempHolder submorphs last firstSubmorph emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttempHolder useRoundedCorners.\\n\\n\\t\\towner addMorph: tempHolder inFrontOf: self.\\n\\t\\taMorph parseNode name: nn key: nn code: nil.\\n\\t\\taMorph parseNode asMorphicSyntaxIn: tempHolder.\\n\\t\\ttempHolder cleanupAfterItDroppedOnMe.\\n\\t\\t^ true].\\n\\n\\taMorph parseNode name: nn key: nn code: nil.\\n\\ttempHolder addMorphBack: (tempHolder transparentSpacerOfSize: 4@4).\\n\\tvar _ tempHolder addRow: #tempVariable on: aMorph parseNode.\\n\\tvar layoutInset: 1.\\n\\tvar addMorphBack: (self addString: nn special: false).\\n\\tvar cleanupAfterItDroppedOnMe.\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/10/2001 09:57'!\\naddTextRow: aStringLikeItem\\n\\n\\t| row tt |\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\t(tt _ TextMorph new) contents: aStringLikeItem.\\n\\trow addMorph: tt.\\n\\t\\\"row addMorph: (self addString: (aStringLikeItem copyWithout: Character cr) special: false).\\\"\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 7/25/2001 10:01'!\\naddToBlock: aMorph event: evt\\n\\t\\\"Insert a new line of code. Figure out who it goes before. If evt Y is within an existing line (to the right of a tile), then replace that tile.\\\"\\n\\n\\t| whereDropped dropBefore replace |\\n\\twhereDropped _ \\\"self pointFromWorld:\\\" evt cursorPoint.\\n\\tdropBefore _ self submorphs \\n\\t\\tdetect: [:each | each isSyntaxMorph ifTrue: [\\n\\t\\t\\twhereDropped y < each top ifTrue: [true]\\t\\\"before this one\\\"\\n\\t\\t\\t\\tifFalse: [whereDropped y < each bottom \\n\\t\\t\\t\\t\\t\\t\\tifTrue: [replace _ true]\\t\\\"replace this one\\\"\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [false]]]] \\\"try next line\\\"\\n\\t\\tifNone: [nil].\\n\\t(aMorph nodeClassIs: ReturnNode) ifTrue: [dropBefore _ nil].\\n\\t\\t\\\"Returns are always at the end. (Watch out for comments)\\\"\\n\\n\\tdropBefore \\n\\t\\tifNil: [self addMorphBack: aMorph]\\n\\t\\tifNotNil: [\\n\\t\\t\\treplace ifNotNil: [aMorph deselect.\\n\\t\\t\\t\\tself replaceSubmorph: dropBefore by: aMorph.\\t\\\"replace it!!\\\"\\n\\t\\t\\t\\t^ dropBefore cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n\\t\\t\\tself addMorph: aMorph inFrontOf: dropBefore].\\n\\tself cleanupAfterItDroppedOnMe.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'FBS 2/24/2004 14:22'!\\naddToken: aString type: aColorOrSymbol on: aNode\\n\\n\\t| sMorph modifiedString noiseWord row |\\n\\n\\trow _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1.\\n\\tself alansTest1 ifFalse: [\\n\\t\\tsMorph _ self addString: aString special: false.\\n\\t\\trow addMorphBack: sMorph.\\n\\t\\t^row\\n\\t].\\n\\n\\tnoiseWord _ [ :w |\\n\\t\\tw ifNotNil: [\\n\\t\\t\\trow \\n\\t\\t\\t\\taddMorphBack: (self noiseStringMorph: w);\\n\\t\\t\\t\\taddMorphBack: (self tokenVerticalSeparator)\\n\\t\\t].\\n\\t].\\n\\t(self shouldBeBrokenIntoWords: aColorOrSymbol) ifTrue: [\\n\\t\\tmodifiedString _ self substituteKeywordFor: aString.\\n\\t\\tsMorph _ self addString: modifiedString special: (aColorOrSymbol ~= #assignmentArrow).\\n\\t\\t\\t\\\"(#(unary keywordGetz keywordSetter unaryGetter) includes: aColorOrSymbol)\\\"\\n\\t\\tmodifiedString = aString ifFalse: [\\n\\t\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aString].\\n\\t\\tsMorph setProperty: #syntacticReformatting toValue: aColorOrSymbol;\\n\\t\\t\\tcontents: modifiedString.\\n\\t] ifFalse: [\\n\\t\\tsMorph _ self addString: (modifiedString _ aString) special: false.\\n\\t].\\n\\t(#(keyword2 upArrow) includes: aColorOrSymbol) ifTrue: [\\n\\t\\tsMorph \\n\\t\\t\\tfont: (self fontToUseForSpecialWord: modifiedString).\\n\\t].\\n\\t(#(keyword2 unary assignmentArrow methodHeader1 methodHeader2) includes: aColorOrSymbol) ifTrue: [\\n\\t\\tsMorph emphasis: TextEmphasis bold emphasisCode.\\n\\t].\\n\\taColorOrSymbol == #blockarg1 ifTrue: [\\n\\t].\\n\\t(aColorOrSymbol == #variable or: [aColorOrSymbol == #tempVariable]) ifTrue: [\\n\\t\\taString = 'self' ifTrue: [\\n\\t\\t\\tsMorph setProperty: #wordyVariantOfSelf toValue: true.\\n\\t\\t].\\n\\t\\tnoiseWord value: (self noiseWordBeforeVariableNode: aNode string: aString).\\n\\t].\\n\\n\\trow addMorphBack: sMorph.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 3/25/2001 17:22'!\\naddTokenSpecialCase: aString type: aColorOrSymbol on: aNode\\n\\n\\t| sMorph modifiedString noiseWord col |\\n\\n\\tnoiseWord _ nil.\\n\\tsMorph _ self addString: aString special: false.\\n\\t(aColorOrSymbol == #keyword2) ifTrue: [\\n\\t\\tmodifiedString _ aString = 'if:' ifTrue: ['Test'] ifFalse: ['Yes'].\\n\\t\\tsMorph \\n\\t\\t\\tfont: (self fontToUseForSpecialWord: modifiedString); \\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: aString;\\n\\t\\t\\tcontents: modifiedString.\\n\\t].\\n\\n\\tcol _ (self addRow: aColorOrSymbol on: aNode) layoutInset: 1.\\n\\tnoiseWord ifNotNil: [\\n\\t\\tcol \\n\\t\\t\\taddMorphBack: (self noiseStringMorph: noiseWord);\\n\\t\\t\\taddMorphBack: (self transparentSpacerOfSize: 3@1)\\n\\t].\\n\\tcol addMorphBack: sMorph.\\n\\t^col! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/24/2001 15:21'!\\naddUnaryRow: aStringLikeItem style: aSymbol\\n\\n\\t| row sMorph modifiedString fontToUse |\\n\\n\\t(row _ self class row: #text on: nil) borderWidth: 1.\\n\\tmodifiedString _ self substituteKeywordFor: aStringLikeItem.\\n\\tsMorph _ self addString: modifiedString special: true.\\n\\tfontToUse _ self fontToUseForSpecialWord: modifiedString.\\n\\n\\tsMorph \\n\\t\\tfont: fontToUse emphasis: 1;\\n\\t\\tsetProperty: #syntacticReformatting toValue: #unary.\\n\\tmodifiedString = aStringLikeItem ifFalse: [\\n\\t\\tsMorph setProperty: #syntacticallyCorrectContents toValue: aStringLikeItem].\\n\\trow addMorph: sMorph.\\n\\tself addMorphBack: row.\\n\\t^row! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'RAA 2/15/2001 19:43'!\\nfoldMessage\\n\\t\\\"I am a message whose receiver is wide, and whose message part is a column.\\n\\tRearrange me so that the message part appears indented under the receiver part.\\\"\\n\\t| messageRow node2 |\\n\\tnode2 _ parseNode copy receiver: nil.\\n\\tmessageRow _ SyntaxMorph row: #keyword1 on: node2.\\n\\n\\tmessageRow \\n\\t\\taddMorph: (self transparentSpacerOfSize: 20@10);\\n\\t\\taddMorphBack: submorphs last.\\t\\t\\\"<<handle noise words better\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\taddMorphBack: (self transparentSpacerOfSize: 4@4);\\n\\t\\taddMorphBack: messageRow.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 1/15/2001 11:15'!\\nfoldMessageOneArg\\n\\t\\\"I am a message that is wide, a row with receiver and a row with selector and arg.\\n\\tRearrange me so that the message part appears indented under the receiver part.\\\"\\n\\t| messageRow node2 |\\n\\tnode2 _ parseNode copy receiver: nil.\\n\\tmessageRow _ SyntaxMorph row: #keyword1 on: node2.\\n\\tmessageRow addMorph: (self transparentSpacerOfSize: 20@10);\\n\\t\\t\\taddMorphBack: submorphs second;\\n\\t\\t\\taddMorphBack: submorphs second. \\\"was the third\\\"\\n\\tself listDirection: #topToBottom;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\taddMorphBack: messageRow.\\n! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/22/2001 16:30'!\\nisKnownVarName: newVarName\\n\\t\\\"Return true if this variable is already known, as an argument, temp var, block temp, or instance variable.\\\"\\n\\n\\t| syntLevel |\\n\\t(self parsedInClass allInstVarNames includes: newVarName) ifTrue: [^ true].\\n\\tsyntLevel _ self.\\n\\t[syntLevel tempVarNodesDo: [:node | \\n\\t\\tnode decompile string = newVarName ifTrue: [^ true]].\\n\\t (syntLevel _ syntLevel owner) isSyntaxMorph] whileTrue.\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/1/2001 13:06'!\\nremoveReturnNode\\n\\t| blk |\\n\\t\\\"If last line is ^ self, remove it. I am a methodNode. Keep if no other tiles in the block.\\\"\\n\\n\\tblk _ self findA: BlockNode.\\n\\tblk submorphs last decompile string = '^self ' ifTrue: [\\n\\t\\t(blk submorphs count: [:ss | ss isSyntaxMorph]) > 1 ifTrue: [\\n\\t\\t\\tblk submorphs last delete]].! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 8/22/2001 16:35'!\\ntempVarNodesDo: aBlock\\n\\t\\\"Execute the block for any block temporary variables, method temps, or method args we have\\\"\\n\\n\\t| tempHolder argsHolder |\\n\\t((self parseNode class == MethodNode) or: [self parseNode class == BlockNode]) ifTrue: [\\n\\t\\tself submorphsDoIfSyntax: [:sub | \\n\\t\\t\\t\\t(sub nodeClassIs: MethodTempsNode) ifTrue: [tempHolder _ sub].\\n\\t\\t\\t\\t((sub nodeClassIs: UndefinedObject) and: [tempHolder isNil]) ifTrue: [\\n\\t\\t\\t\\t\\ttempHolder _ sub findA: MethodTempsNode].\\n\\t\\t\\t\\t(sub nodeClassIs: BlockArgsNode) ifTrue: [tempHolder _ sub].\\n\\t\\t\\t\\t(sub nodeClassIs: SelectorNode) ifTrue: [argsHolder _ sub].\\n\\t\\t\\t\\t]\\n\\t\\t\\tifString: [:sub | ].\\n\\t\\ttempHolder ifNotNil: [\\\"Temp variables\\\"\\n\\t\\t\\ttempHolder submorphsDoIfSyntax: [:sm | \\n\\t\\t\\t\\t\\t(sm nodeClassIs: TempVariableNode) ifTrue: [aBlock value: sm]]\\n\\t\\t\\t\\tifString: [:sm | ]].\\n\\t\\targsHolder ifNotNil: [\\\"arguments\\\"\\n\\t\\t\\targsHolder submorphsDoIfSyntax: [:sm | \\n\\t\\t\\t\\t\\t(sm nodeClassIs: TempVariableNode) ifTrue: [aBlock value: sm]]\\n\\t\\t\\t\\tifString: [:sm | ]].\\n\\t\\t].\\n\\t\\\"otherwise do nothing\\\"! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'tk 2/12/2001 14:39'!\\ntry\\n\\t\\\"Evaluate me once\\\"\\n\\n\\t(#(MessageNode LiteralNode VariableNode) includes: parseNode class name) \\n\\t\\tifFalse: [^ Error new].\\n\\t^ [Compiler evaluate: self decompile\\n\\t\\t\\t\\tfor: self actualObject\\n\\t\\t\\t\\tlogged: false.\\t\\\"should do something to the player\\\"\\n\\t\\t] ifError: [ :a :b | Error new].! !\\n\\n!SyntaxMorph methodsFor: 'layout' stamp: 'ar 8/10/2003 18:19'!\\nunfoldMessage\\n\\t\\\"I am a message whose message part is a column.\\n\\tRearrange me so that the entire message is one row.\\\"\\n\\t| messageRow |\\n\\tmessageRow _ self submorphs last.\\n\\tself removeMorph: messageRow.\\n\\tmessageRow submorphs do: [:m | self addMorphBack: m].\\n\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'macpal' stamp: 'sw 6/4/2001 19:26'!\\ncurrentVocabulary\\n\\t\\\"Answer the current vocabulary associated with the receiver. If none is yet set, determine an appropriate vocabulary and cache it within my properties dictionary.\\\"\\n\\n\\t| aVocab aSym |\\n\\taSym _ self valueOfProperty: #currentVocabularySymbol ifAbsent: [nil].\\n\\taSym ifNil:\\n\\t\\t[aVocab _ self valueOfProperty: #currentVocabulary ifAbsent: [nil].\\n\\t\\taVocab ifNotNil:\\n\\t\\t\\t[aSym _ aVocab vocabularyName.\\n\\t\\t\\tself removeProperty: #currentVocabulary.\\n\\t\\t\\tself setProperty: #currentVocabularySymbol toValue: aSym]].\\n\\n\\taSym ifNotNil:\\n\\t\\t[^ Vocabulary vocabularyNamed: aSym].\\n\\taVocab _ super currentVocabulary.\\n\\tself setProperty: #currentVocabularySymbol toValue: aVocab vocabularyName.\\n\\t^ aVocab! !\\n\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 19:09'!\\naccept\\n\\t\\\"Turn my current state into the text of a method. Compile it in my class.\\\"\\n\\n\\t^ self acceptInCategory: ClassOrganizer default! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 11/21/2000 16:35'!\\nacceptIfInScriptor\\n\\t| root |\\n\\t\\\"If I am in a ScriptEditorMorph, tell my root to accept the new changes.\\\"\\n\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNotNil: [\\n\\t\\troot _ self rootTile.\\n\\t\\troot ifNotNil: [root accept]]. ! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'RAA 2/14/2001 15:40'!\\nacceptIgnoring: aString\\n\\t\\\"If I am inside a ScriptEditorMorph, tell my root to accept the new changes. Ignore the argument, which is the string whose conents just changed.\\\"\\n\\n\\tthisContext sender receiver removeProperty: #syntacticallyCorrectContents.\\n\\tself acceptIfInScriptor! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 17:15'!\\nacceptInCategory: categoryString\\n\\t\\\"Turn my current state into the text of a method. Compile it in my class.\\\"\\n\\t| cls sc sel |\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile accept \\\"always accept at the root\\\"].\\n\\t(cls _ self parsedInClass) ifNil: [^ self].\\n\\tsel _ cls compile: self decompile classified: categoryString.\\n\\t(sc _ self firstOwnerSuchThat: [:mm | mm class == ScriptEditorMorph]) \\n\\t\\tifNotNil: [sc hibernate; unhibernate].\\t\\\"rebuild the tiles\\\"\\n\\t^ sel! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/27/2001 19:12'!\\nacceptSilently\\n\\t\\\"Turn my current state into the text of a method.\\n\\tCompile it in my class. Don't rebuild the tiles.\\\"\\n\\t| cls |\\n\\tself isMethodNode ifFalse: [\\n\\t\\tself rootTile == self ifTrue: [^ false]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile acceptSilently \\\"always accept at the root\\\"].\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNil: [^ false].\\n\\t(cls _ self parsedInClass) ifNil: [^ false].\\n\\tcls compile: self decompile classified: 'scripts'.\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 5/4/2001 12:14'!\\nacceptUnlogged\\n\\t\\\"This is an exact copy of acceptSilently, except it does not log to the source file.\\n\\tUsed for all but the last of scrolling number changes.\\\"\\n\\t| cls |\\n\\tself isMethodNode ifFalse:\\n\\t\\t[self rootTile == self ifTrue: [^ self]. \\\"not in a script\\\"\\n\\t\\t^ self rootTile acceptUnlogged \\\"always accept at the root\\\"].\\n\\t(self ownerThatIsA: ScriptEditorMorph) ifNil: [^ self].\\n\\t(cls _ self parsedInClass) ifNil: [^ self].\\n\\tcls compile: self decompile\\n\\t\\tclassified: ClassOrganizer default\\n\\t\\twithStamp: nil\\n\\t\\tnotifying: nil\\n\\t\\tlogSource: false.\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'md 8/15/2005 11:02'!\\ndecompile\\n\\t| stream |\\n\\t\\\"Produce Smalltalk code. We have a tree of SyntaxMorphs, but not a tree of ParseNodes. The user has dragged in many SyntaxMorphs, each with its own parseNode, but those nodes are not sewn together in a tree. The only data we get from a ParseNode is its class.\\n\\tWe produce really ugly code. But we compile it and decompile (prettyPrint) again for user to see.\\\"\\n\\n\\tstream _ ColoredCodeStream on: (Text new: 400).\\n\\tself printOn: stream indent: 1.\\t\\\"Tree walk and produce text of the code\\\"\\n\\t^ stream contents! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 11/13/2000 20:23'!\\ngetMenuBlock\\n\\n\\t^ nil! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/23/2001 02:05'!\\nofferTilesMenuFor: aReceiver in: aLexiconModel\\n\\t\\\"Offer a menu of tiles for assignment and constants\\\"\\n\\n\\t| menu |\\n\\tmenu _ MenuMorph new addTitle: 'Hand me a tile for...'.\\n\\tmenu addLine.\\n\\tmenu add: '(accept method now)' target: aLexiconModel selector: #acceptTiles.\\n\\tmenu submorphs last color: Color red darker.\\n\\tmenu addLine.\\n\\n\\tmenu add: 'me, by name' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'<me by name>'. aReceiver}.\\n\\tmenu add: 'self' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'self'. VariableNode}.\\n\\tmenu add: '_ (assignment)' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'<assignment>'. nil}.\\n\\tmenu add: '\\\"a Comment\\\"' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'\\\"a comment\\\"\\\\' withCRs. CommentNode}.\\n\\tmenu submorphs last color: Color blue.\\n\\tmenu add: 'a Number' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'5'. LiteralNode}.\\n\\tmenu add: 'a Character' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'$z'. LiteralNode}.\\n\\tmenu add: '''abc''' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'''abc'''. LiteralNode}.\\n\\tmenu add: 'a Symbol constant' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'#next'. LiteralNode}.\\n\\tmenu add: 'true' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'true'. VariableNode}.\\n\\tmenu add: 'a Test' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'true ifTrue: [self] ifFalse: [self]'. MessageNode}.\\n\\tmenu add: 'a Loop' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'1 to: 10 do: [:index | self]'. MessageNode}.\\n\\tmenu add: 'a Block' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'[self]'. BlockNode}.\\n\\tmenu add: 'a Class or Global' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'Character'. LiteralVariableNode}.\\n\\tmenu add: 'a Reply' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'| temp | temp'. ReturnNode}.\\n\\tmenu popUpAt: ActiveHand position forHand: ActiveHand in: World.\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 9/17/2001 13:38'!\\nofferVarsMenuFor: aReceiver in: aLexiconModel\\n\\t\\\"Offer a menu of tiles for assignment and constants\\\"\\n\\n\\t| menu instVarList cls |\\n\\tmenu _ MenuMorph new addTitle: 'Hand me a tile for...'.\\n\\tmenu addLine.\\n\\tmenu add: '(accept method now)' target: aLexiconModel selector: #acceptTiles.\\n\\tmenu submorphs last color: Color red darker.\\n\\tmenu addLine.\\n\\tmenu add: 'new temp variable' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\targumentList: {'| temp | temp'. TempVariableNode}.\\n\\n\\tinstVarList _ OrderedCollection new.\\n\\tcls _ aReceiver class.\\n\\t[instVarList addAllFirst: cls instVarNames.\\n\\t cls == aLexiconModel limitClass] whileFalse: [cls _ cls superclass].\\n\\tinstVarList do: [:nn |\\n\\t\\tmenu add: nn target: self selector: #instVarTile: argument: nn].\\n\\tmenu popUpAt: ActiveHand position forHand: ActiveHand in: World.\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 12/14/2001 11:58'!\\nputOnBackground\\n\\t\\\"Place the receiver, formerly private to its card, onto the shared background. If the receiver needs data carried on its behalf by the card, such data will be represented on every card.\\\"\\n\\n\\t| updStr |\\n\\t(updStr _ self readOut) ifNotNil: [\\\"If has a place to put per-card data, set that up.\\\"\\n\\t\\tupdStr getSelector ifNotNil: [\\n\\t\\t\\tself setProperty: #holdsSeparateDataForEachInstance toValue: true]].\\n\\tsuper putOnBackground.! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'di 11/17/2000 09:00'!\\nshowCode\\n\\t\\\"Turn my current state into the text of a method. Put it in a window.\\\"\\n\\n\\t(Workspace new contents: self rootTile decompile) openLabel: self printString,' code'\\n\\n\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'menus' stamp: 'tk 12/10/2001 17:48'!\\nshowMenu: evt\\n\\t| menu |\\n\\tmenu _ MenuMorph new.\\n\\tself rootTile isMethodNode ifTrue:\\n\\t\\t[menu add: 'accept method' target: self selector: #accept.\\n\\t\\tmenu addLine.\\n\\n\\t\\tmenu add: 'new temp variable' target: self selector: #attachTileForCode:nodeType: \\n\\t\\t\\t\\t\\targumentList: {'| temp | temp'. TempVariableNode}.\\n\\t\\tmenu addLine.\\n\\n\\t\\tself parsedInClass allInstVarNames do: [:nn |\\n\\t\\t\\tmenu add: nn,' tile' target: self selector: #instVarTile: argument: nn].\\n\\t\\tmenu addLine.\\n\\n\\t\\tmenu add: 'show code' target: self selector: #showCode.\\n\\t\\tmenu add: 'try out' target: self selector: #try.\\n\\t\\tmenu popUpAt: evt hand position forHand: evt hand in: World].\\n\\n\\n\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'FBS 2/24/2004 14:32'!\\nattachTileForCode: expression nodeType: nodeClass\\n\\t| nn master tile |\\n\\t\\\"create a new tile for a part of speech, and put it into the hand\\\"\\n\\n\\t\\\"a few special cases\\\"\\n\\texpression = 'self' ifTrue: [\\n\\t\\t^ (((self string: expression toTilesIn: Object) \\n\\t\\t\\t\\tfindA: ReturnNode) findA: nodeClass) attachToHand].\\n\\n\\texpression = '<me by name>' ifTrue: [\\\"Tile for the variable in References\\\"\\n\\t\\tnn _ nodeClass knownName ifNil: [#+].\\n\\t\\t(References at: nn asSymbol ifAbsent: [nil]) == nodeClass ifTrue: [\\n\\t\\t\\t^ self attachTileForCode: nn nodeType: LiteralVariableNode].\\n\\t\\t\\\"otherwise just give a tile for self\\\"\\n\\t\\t^ self attachTileForCode: 'self' nodeType: VariableNode].\\n\\n\\texpression = '<assignment>' ifTrue: [\\\"do something really special\\\"\\n\\t\\tmaster _ self class new.\\n\\t\\tmaster addNoiseString: ' _ ' emphasis: TextEmphasis bold emphasisCode.\\n\\t\\ttile _ master firstSubmorph.\\n\\t\\t^ (tile parseNode: AssignmentNode new) attachToHand].\\t\\\"special marker\\\"\\n\\t\\t\\\"When this is dropped on a variable, enclose it in \\n\\t\\t\\ta new assignment statement\\\"\\n\\n\\t\\\"general case -- a tile for a whole line of code is returned\\\"\\n\\t^ ((self string: expression toTilesIn: Object) \\n\\t\\t\\t\\tfindA: nodeClass) attachToHand.! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 9/7/2001 11:21'!\\nattachToHand\\n\\t\\\"Adjust my look and attach me to the hand\\\"\\n\\n\\tself roundedCorners.\\n\\tActiveHand attachMorph: self.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [self lookTranslucent.\\n\\t\\t\\tself align: self center with: ActiveHand position \\\"+ self cursorBaseOffset\\\"]\\n\\t\\tifFalse: [self align: self topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 8/30/2001 06:22'!\\ninstVarTile: aName\\n\\t\\\"Make and put into hand a tile for an instance variable\\\"\\n\\n\\t| sm |\\n\\tsm _ ((VariableNode new\\n\\t\\t\\t\\t\\tname: aName\\n\\t\\t\\t\\t\\tindex: 1\\n\\t\\t\\t\\t\\ttype: 1 \\\"LdInstType\\\") asMorphicSyntaxIn: SyntaxMorph new).\\n\\tsm roundedCorners.\\n\\tActiveHand attachMorph: sm.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [sm lookTranslucent.\\n\\t\\t\\tsm align: sm center with: ActiveHand position \\\"+ self cursorBaseOffset\\\"]\\n\\t\\tifFalse: [sm align: sm topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n!SyntaxMorph methodsFor: 'new tiles' stamp: 'tk 9/13/2001 13:44'!\\nstring: anExpression toTilesIn: playerClass\\n\\t| code tree methodNode |\\n\\t\\\"Construct SyntaxMorph tiles for some code. Returns the main BlockNode of a doIt.\\\"\\n\\n\\t\\\"This is really cheating!! Make a true parse tree later. -tk\\\"\\n\\tcode _ String streamContents: [:strm | \\n\\t\\tstrm nextPutAll: 'doIt'; cr; tab; nextPutAll: anExpression].\\n\\t\\\"decompile to tiles\\\"\\n\\ttree _ Compiler new \\n\\t\\tparse: code \\n\\t\\tin: playerClass\\n\\t\\tnotifying: nil.\\n\\tmethodNode _ tree asMorphicSyntaxUsing: SyntaxMorph.\\n\\tanExpression first == $\\\" ifTrue: [\\\"a comment\\\" \\n\\t\\t\\\"(methodNode findA: CommentNode) firstSubmorph color: Color blue.\\\"\\n\\t\\t^ methodNode].\\n\\t^ methodNode submorphs detect: [:mm | \\n\\t\\t(mm respondsTo: #parseNode) \\n\\t\\t\\tifTrue: [mm parseNode class == BlockNode] \\n\\t\\t\\tifFalse: [false]].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:23'!\\naddTemporaries: temporaries \\n\\t| tempMorph outerMorph w2 |\\n\\ttemporaries notEmpty ifFalse: [^self].\\n\\tself alansTest1 \\n\\t\\tifFalse: \\n\\t\\t\\t[tempMorph := self addRow: #tempVariable on: MethodTempsNode new.\\n\\t\\t\\ttemporaries do: [:temp | temp asMorphicSyntaxIn: tempMorph]\\n\\t\\t\\t\\tseparatedBy: \\n\\t\\t\\t\\t\\t[tempMorph addMorphBack: (tempMorph transparentSpacerOfSize: 4 @ 4)].\\n\\t\\t\\t^self].\\n\\touterMorph := self addRow: #tempVariable on: nil.\\n\\touterMorph setSpecialTempDeclarationFormat1.\\n\\touterMorph \\n\\t\\taddMorphBack: (w2 := self noiseStringMorph: self noiseBeforeBlockArg).\\n\\tw2 emphasis: TextEmphasis bold emphasisCode.\\n\\ttempMorph := outerMorph addRow: #tempVariable on: MethodTempsNode new.\\n\\ttempMorph setSpecialTempDeclarationFormat2.\\n\\ttemporaries do: \\n\\t\\t\\t[:temp | \\n\\t\\t\\ttempMorph \\n\\t\\t\\t\\taddToken: temp name\\n\\t\\t\\t\\ttype: #tempVariableDeclaration\\n\\t\\t\\t\\ton: temp]\\n\\t\\tseparatedBy: [tempMorph addMorphBack: self tokenVerticalSeparator]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/31/2001 17:27'!\\naddTemporaryControls\\n\\n\\t| row stdSize |\\n\\t\\n\\tstdSize _ 8@8.\\n\\trow _ AlignmentMorph newRow\\n\\t\\tcolor: Color transparent;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap.\\n\\tself addMorphBack: row.\\n\\n\\t{\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color paleBlue darker;\\n\\t\\t\\tsetBalloonText: 'Change the contrast';\\n\\t\\t\\ton: #mouseUp send: #controlContrast2: to: self;\\n\\t\\t\\ton: #mouseMove send: #controlContrast2: to: self;\\n\\t\\t\\ton: #mouseDown send: #controlContrast2: to: self.\\n\\n\\t\\\"Removed because it's default is giant tiles, which no one wants. --tk\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color green;\\n\\t\\t\\tsetBalloonText: 'Change basic spacing';\\n\\t\\t\\ton: #mouseUp send: #controlSpacing2: to: self;\\n\\t\\t\\ton: #mouseMove send: #controlSpacing2: to: self;\\n\\t\\t\\ton: #mouseDown send: #controlSpacing2: to: self.\\n\\t\\\"\\n\\n\\t\\tMorph new\\n\\t\\t\\textent: stdSize; \\n\\t\\t\\tcolor: Color lightRed;\\n\\t\\t\\tsetBalloonText: 'Change basic style';\\n\\t\\t\\ton: #mouseUp send: #changeBasicStyle to: self.\\n\\n\\t} do: [ :each |\\n\\t\\trow addMorphBack: each.\\n\\t\\trow addMorphBack: (self transparentSpacerOfSize: stdSize).\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 12/3/2004 17:01'!\\nalanBinaryPostRcvr: aNode key: key args: args\\n\\n\\t| nodeWithNilReceiver row |\\n\\n\\\"==\\nRepeat for collection [ collect ( from foo. blah blah foo blah) ]\\nRepeat for 1 to 50 [ do ( from i. blah blab i blah ) ]\\n==\\\"\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\trow addToken: key asString\\n\\t\\ttype: #binary\\n\\t\\ton: (SelectorNode new key: key asString code: nil \\\"fill this in?\\\").\\n\\targs first asMorphicSyntaxIn: row.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/30/2001 14:52'!\\nalanKeywordMessage: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver column keywords row onlyOne |\\n\\n\\t(key == #collect: and: [args first isKindOf: BlockNode]) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdCollect: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tkey == #repeatFor:doing: ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdRepeatForDoing: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tkey == #if:do: ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdIfDo: aNode \\n\\t\\t\\tisAConditional: template \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\t(args size = 1 and: [key endsWith: 'Getz:']) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdSetter: aNode \\n\\t\\t\\tisAConditional: 0 \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\t(args size = 1 and: [self isStandardSetterKeyword: key]) ifTrue: [\\n\\t\\t^self\\n\\t\\t\\talanKwdSetter2: aNode \\n\\t\\t\\tisAConditional: 0 \\n\\t\\t\\tkey: key \\n\\t\\t\\targs: args\\n\\t].\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\ttemplate = 1 ifTrue: [\\n\\t\\tself listDirection: #topToBottom.\\n\\t].\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\tkeywords _ key keywords.\\n\\tonlyOne _ args size = 1.\\n\\tonlyOne ifFalse: [\\\"necessary for three keyword messages!!\\\"\\n\\t\\tcolumn setProperty: #deselectedBorderColor toValue: column compoundBorderColor].\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\ttemplate = 1 ifTrue: [\\n\\t\\t\\t\\tcolumn addMorphBack: (column transparentSpacerOfSize: 3@3).\\n\\t\\t\\t].\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: \\n\\t\\t\\t\\t\\t\\t(onlyOne ifTrue: [MessageNode] ifFalse: [MessagePartNode]));\\n\\t\\t\\t\\tborderColor: row stdBorderColor.\\n\\t\\t\\ttemplate = 1 ifTrue: [row addMorphBack: (row transparentSpacerOfSize: 20@6)].\\n\\t\\t\\trow addToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: (onlyOne ifTrue: [SelectorNode new key: kwd code: nil \\\"fill this in?\\\"]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [KeyWordNode new]).\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n\\tonlyOne ifTrue: [\\n\\t\\tself replaceSubmorph: column by: row.\\n\\t\\tcolumn _ row.\\n\\t].\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 3/25/2001 16:31'!\\nalanKwdCollect: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row kwdHolder |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\tkwdHolder _ row\\n\\t\\taddToken: key\\n\\t\\ttype: #keyword2\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString;\\n\\t\\tcontents: ''.\\n\\n\\targs first asMorphicCollectSyntaxIn: row.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/30/2001 14:52'!\\nalanKwdIfDo: aNode isAConditional: template key: key args: args\\n\\t\\\"(know it has more than one arg)\\\"\\n\\t| nodeWithNilReceiver column keywords row |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\t\\\"column borderColor: column compoundBorderColor.\\\"\\n\\tkeywords _ key keywords.\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: MessagePartNode).\\n\\t\\t\\tkwd = 'do:' ifTrue: [\\n\\t\\t\\t\\trow addMorphBack: (row transparentSpacerOfSize: 26@6).\\n\\t\\t\\t] ifFalse: [\\n\\t\\t\\t\\trow addMorphBack: (row transparentSpacerOfSize: 10@6).\\n\\t\\t\\t].\\n\\t\\t\\trow addTokenSpecialCase: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: KeyWordNode new.\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/28/2001 10:16'!\\nalanKwdRepeatForDoing: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row column keywords |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\tcolumn _ self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\tkeywords _ key keywords.\\n\\tkeywords\\n\\t\\twith: (args first: keywords size)\\n\\t\\tdo: [:kwd :arg |\\n\\t\\t\\t(row _ column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver as: MessagePartNode).\\n\\t\\t\\trow addToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: KeyWordNode new.\\n\\t\\t\\t(arg asMorphicSyntaxIn: row) setConditionalPartStyle.\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:22'!\\nalanKwdSetter2: aNode isAConditional: template key: key args: args\\n\\t\\\"translates\\n\\t\\tfoo setHeading: 0\\n\\tto\\n\\t\\tfoo's heading _ 0\\n\\t\\\"\\n\\t| kwdHolder wordy |\\n\\tkwdHolder _ self\\n\\t\\taddToken: key\\n\\t\\ttype: #keywordSetter\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\twordy _ self translateToWordySetter: key.\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticReformatting toValue: #keywordSetter;\\n\\t\\tcontents: wordy;\\n\\t\\temphasis: TextEmphasis bold emphasisCode.\\n\\twordy = key asString ifFalse: [\\n\\t\\tkwdHolder firstSubmorph \\n\\t\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString].\\n\\n\\t(args first asMorphicSyntaxIn: self) setConditionalPartStyle\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:22'!\\nalanKwdSetter: aNode isAConditional: template key: key args: args\\n\\n\\t| nodeWithNilReceiver row kwdHolder |\\n\\n\\tnodeWithNilReceiver _ aNode copy receiver: nil.\\n\\t(row _ self addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\tborderWidth: 1;\\n\\t\\tparseNode: (nodeWithNilReceiver as: MessageNode);\\n\\t\\tborderColor: row stdBorderColor.\\n\\trow addNoiseString: '''s' emphasis: TextEmphasis bold emphasisCode.\\n\\tkwdHolder _ row\\n\\t\\taddToken: key\\n\\t\\ttype: #keywordGetz\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tkwdHolder firstSubmorph \\n\\t\\tsetProperty: #syntacticReformatting toValue: #keywordGetz;\\n\\t\\tsetProperty: #syntacticallyCorrectContents toValue: key asString;\\n\\t\\tcontents: (self splitAtCapsAndDownshifted: (key asString allButLast: 5));\\n\\t\\temphasis: TextEmphasis bold emphasisCode.\\n\\trow addNoiseString: '_' emphasis: TextEmphasis bold emphasisCode.\\n\\n\\t(args first asMorphicSyntaxIn: row) setConditionalPartStyle\\n\\t\\t\\t\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:21'!\\nalanUnaryGetter: aNode key: key\\n\\t\\\"I am a MessageNode. Fill me with a SelectorNode {getX} whose string is {'s x}. All on one level.\\\"\\n\\n\\t| selSyn usm wordy |\\n\\tselSyn _ self\\n\\t\\taddToken: key\\n\\t\\ttype: #unaryGetter\\n\\t\\ton: (SelectorNode new key: key code: nil \\\"fill this in?\\\").\\n\\tusm _ selSyn firstSubmorph.\\n\\tusm setProperty: #syntacticReformatting toValue: #unaryGetter.\\n\\twordy _ self translateToWordyGetter: key.\\n\\twordy = key asString ifFalse: [\\n\\t\\tusm setProperty: #syntacticallyCorrectContents toValue: key asString].\\n\\tusm contents: wordy; emphasis: TextEmphasis bold emphasisCode.\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 4/4/2001 12:49'!\\nalanUnaryPostRcvr: aNode key: key selector: selector\\n\\n\\t| row |\\n\\n\\t(self isStandardGetterSelector: key) ifTrue: [\\n\\t\\t^self alanUnaryGetter: aNode key: key\\n\\t].\\n\\trow _ (self addUnaryRow: key style: #unary) layoutInset: 1.\\n\\t^ row parseNode: selector\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:38'!\\nalansMessageNode: aNode receiver: receiver selector: selector keywords: key arguments: args \\n\\t| receiverMorph testAndReceiver anotherSelf wordyMorph template |\\n\\ttemplate := self alansTemplateStyleFor: key.\\n\\treceiver ifNotNil: \\n\\t\\t\\t[\\\"i.e. not a cascade\\\"\\n\\n\\t\\t\\tanotherSelf := self constructSelfVariant: receiver and: key.\\n\\t\\t\\tanotherSelf ifNotNil: \\n\\t\\t\\t\\t\\t[wordyMorph := self addString: anotherSelf special: false.\\n\\t\\t\\t\\t\\twordyMorph setProperty: #wordyVariantOfSelf toValue: true.\\n\\t\\t\\t\\t\\tself addMorph: wordyMorph.\\n\\t\\t\\t\\t\\tself layoutInset: 1.\\n\\t\\t\\t\\t\\t^self].\\n\\t\\t\\ttestAndReceiver := self.\\n\\t\\t\\ttemplate = 1 \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[testAndReceiver := self addRow: #keyword1 on: nil.\\n\\t\\t\\t\\t\\tself setSpecialOuterTestFormat.\\n\\t\\t\\t\\t\\ttestAndReceiver addNoiseString: 'Test'].\\n\\t\\t\\tfalse \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[\\\"template = 2\\\"\\n\\n\\t\\t\\t\\t\\ttestAndReceiver := self addRow: #keyword1 on: nil.\\n\\t\\t\\t\\t\\t\\\"self setSpecialOuterTestFormat.\\\"\\n\\t\\t\\t\\t\\ttestAndReceiver addNoiseString: 'Repeat for'].\\n\\t\\t\\treceiverMorph := receiver asMorphicSyntaxIn: testAndReceiver.\\n\\t\\t\\ttemplate = 1 ifTrue: [receiverMorph setConditionalPartStyle]].\\n\\n\\t\\\"unary messages\\\"\\n\\targs isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talanUnaryPostRcvr: aNode\\n\\t\\t\\t\\tkey: key\\n\\t\\t\\t\\tselector: selector].\\n\\n\\t\\\"binary messages\\\"\\n\\tkey last = $: \\n\\t\\tifFalse: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talanBinaryPostRcvr: aNode\\n\\t\\t\\t\\tkey: key\\n\\t\\t\\t\\targs: args].\\n\\n\\t\\\"keyword messages\\\"\\n\\treceiverMorph ifNotNil: [receiverMorph setConditionalPartStyle].\\n\\tself setSpecialOuterTestFormat.\\n\\tself \\n\\t\\talanKeywordMessage: aNode\\n\\t\\tisAConditional: template\\n\\t\\tkey: key\\n\\t\\targs: args! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/27/2001 14:19'!\\nassignmentNode: aNode variable: variable value: value\\n\\n\\t| row v expMorph |\\n\\n\\trow _ self addRow: #assignment on: aNode.\\n\\tv _ variable asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [v setConditionalPartStyle; layoutInset: 2].\\n\\trow addToken: ' _ ' type: #assignmentArrow on: aNode.\\n\\texpMorph _ value asMorphicSyntaxIn: row.\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t\\t(expMorph hasProperty: #deselectedColor) ifFalse: [expMorph setConditionalPartStyle].\\n\\t].\\n\\t^row\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:39'!\\nblockNode: aNode arguments: arguments statements: statements \\n\\t| row column |\\n\\tcolumn := self addColumn: #block on: aNode.\\n\\tself alansTest1 ifFalse: [column layoutInset: 5 @ -1].\\n\\tself alansTest1 \\n\\t\\tifTrue: \\n\\t\\t\\t[column setProperty: #deselectedBorderColor toValue: self lighterColor].\\n\\taNode addCommentToMorph: column.\\n\\targuments notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := column addRow: #blockarg1 on: BlockArgsNode new.\\n\\t\\t\\trow addNoiseString: self noiseBeforeBlockArg.\\n\\t\\t\\targuments do: \\n\\t\\t\\t\\t\\t[:arg | \\n\\t\\t\\t\\t\\trow \\n\\t\\t\\t\\t\\t\\taddToken: arg name\\n\\t\\t\\t\\t\\t\\ttype: #blockarg2\\n\\t\\t\\t\\t\\t\\ton: arg]].\\n\\tstatements do: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(row := each asMorphicSyntaxIn: column) borderWidth: 1.\\n\\t\\t\\tself alansTest1 ifTrue: [row setSpecialOuterTestFormat].\\n\\t\\t\\teach addCommentToMorph: column].\\n\\t^column! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'FBS 2/24/2004 14:32'!\\nblockNodeCollect: aNode arguments: arguments statements: statements \\n\\t| row column c2 r2 r3 |\\n\\tcolumn := self addColumn: #blockCollectOnly on: aNode.\\n\\tself alansTest1 ifFalse: [column layoutInset: 5 @ -1].\\n\\taNode addCommentToMorph: column.\\n\\targuments notEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := column addRow: #blockarg1 on: BlockArgsNode new.\\n\\t\\t\\trow addNoiseString: 'collect using' emphasis: TextEmphasis bold emphasisCode.\\n\\t\\t\\tr3 := row addRow: #blockarg1b on: nil.\\t\\\"aNode\\\"\\n\\t\\t\\tr3 setConditionalPartStyle.\\n\\t\\t\\targuments do: \\n\\t\\t\\t\\t\\t[:arg | \\n\\t\\t\\t\\t\\tr3 \\n\\t\\t\\t\\t\\t\\taddToken: arg name\\n\\t\\t\\t\\t\\t\\ttype: #blockarg2\\n\\t\\t\\t\\t\\t\\ton: arg]].\\n\\tr2 := column addRow: #block on: aNode.\\n\\tr2 setProperty: #ignoreNodeWhenPrinting toValue: true.\\n\\tr2 addNoiseString: self noiseBeforeBlockArg emphasis: TextEmphasis bold emphasisCode.\\n\\tc2 := r2 addColumn: #block on: aNode.\\n\\tc2 setProperty: #ignoreNodeWhenPrinting toValue: true.\\n\\tstatements do: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each asMorphicSyntaxIn: c2) borderWidth: 1.\\n\\t\\t\\teach addCommentToMorph: c2].\\n\\t^column! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/22/2001 17:00'!\\ncascadeNode: aNode receiver: receiver messages: messages\\n\\t| row |\\n\\n\\tself alansTest1 ifTrue: [\\n\\t\\trow _ self addColumn: #cascade on: aNode.\\n\\t\\trow setSpecialOuterTestFormat.\\n\\t] ifFalse: [\\n\\t\\trow _ self addRow: #cascade on: aNode\\n\\t].\\n\\treceiver asMorphicSyntaxIn: row.\\n\\tmessages do: [:m | m asMorphicSyntaxIn: row].\\n\\t^ row\\n\\n\\\"\\t(node2 _ aNode copy) receiver: nil messages: messages.\\n\\tcascadeMorph _ row addColumn: #cascade2 on: node2.\\n\\tmessages do: [ :m | m asMorphicSyntaxIn: cascadeMorph].\\n\\t^row\\n\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/16/2001 16:34'!\\nchangeBasicStyle\\n\\n\\tself removeAllMorphs.\\n\\tself setProperty: #alansNewStyle toValue: self alansTest1 not.\\n\\tself methodNodeOuter: parseNode\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'gm 2/22/2003 13:42'!\\nfinalAppearanceTweaks\\n\\t| deletes lw |\\n\\tSizeScaleFactor ifNil: [SizeScaleFactor := 0.15].\\n\\tSizeScaleFactor := 0.0.\\t\\\"disable this feature. Default was for giant tiles\\\"\\n\\tself usingClassicTiles \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tallMorphsDo: [:each | (each isSyntaxMorph) ifTrue: [each lookClassic]].\\n\\t\\t\\t^self].\\n\\tdeletes := OrderedCollection new.\\n\\tself allMorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each respondsTo: #setDeselectedColor) ifTrue: [each setDeselectedColor].\\n\\t\\t\\t\\\"(each hasProperty: #variableInsetSize) ifTrue: [\\n\\t\\t\\teach layoutInset: \\n\\t\\t\\t\\t((each valueOfProperty: #variableInsetSize) * SizeScaleFactor) rounded].\\\"\\n\\t\\t\\teach isSyntaxMorph \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[lw := each layoutInset.\\n\\t\\t\\t\\t\\tlw isPoint ifTrue: [lw := lw x].\\n\\t\\t\\t\\t\\teach layoutInset: lw @ 0\\t\\\"(6 * SizeScaleFactor) rounded\\\"]].\\n\\tdeletes do: [:each | each delete]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 11/11/2002 10:30'!\\nisStandardGetterSelector: key\\n\\n\\tself flag: #yoCharCases.\\n\\n\\tkey size > 3 ifFalse: [^false].\\n\\t(key beginsWith: 'get') ifFalse: [^false].\\n\\tkey fourth isUppercase ifFalse: [^false].\\n\\t^true\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'yo 11/11/2002 10:31'!\\nisStandardSetterKeyword: key\\n\\n\\tself flag: #yoCharCases.\\n\\n\\tkey size > 4 ifFalse: [^false].\\n\\t(key endsWith: ':') ifFalse: [^false].\\n\\t(key beginsWith: 'set') ifFalse: [^false].\\n\\tkey fourth isUppercase ifFalse: [^false].\\n\\t^true\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'dgd 2/22/2003 13:39'!\\nmessageNode: aNode receiver: receiver selector: selector keywords: key arguments: args \\n\\t| keywords column row receiverMorph receiverWidth messageWidth onlyOne nodeWithNilReceiver isAConditional |\\n\\tself alansTest1 \\n\\t\\tifTrue: \\n\\t\\t\\t[^self \\n\\t\\t\\t\\talansMessageNode: aNode\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\tkeywords: key\\n\\t\\t\\t\\targuments: args].\\n\\tisAConditional := #(#ifTrue: #ifFalse: #ifTrue:ifFalse: #ifFalse:ifTrue:) \\n\\t\\t\\t\\tincludes: key.\\n\\treceiver ifNotNil: \\n\\t\\t\\t[\\\"i.e. not a cascade\\\"\\n\\n\\t\\t\\treceiverMorph := receiver asMorphicSyntaxIn: self].\\n\\tkeywords := key keywords.\\n\\targs isEmpty \\n\\t\\tifTrue: \\n\\t\\t\\t[row := (self addSingleKeywordRow: key) layoutInset: 1.\\n\\t\\t\\t^row parseNode: selector].\\n\\treceiverWidth := receiver ifNil: [0]\\n\\t\\t\\t\\tifNotNil: [receiverMorph fullBounds width].\\n\\tonlyOne := args size = 1.\\n\\t(receiverWidth <= 80 and: [onlyOne]) \\n\\t\\tifTrue: \\n\\t\\t\\t[self \\n\\t\\t\\t\\tmessageOneArg: key\\n\\t\\t\\t\\treceiver: receiver\\n\\t\\t\\t\\tselector: selector\\n\\t\\t\\t\\targs: args.\\n\\t\\t\\t^self].\\n\\tnodeWithNilReceiver := aNode copy receiver: nil.\\n\\tcolumn := self addColumn: #keyword1 on: nodeWithNilReceiver.\\n\\t\\\"onlyOne ifTrue: [column parseNode: nil].\\tis a spacer\\\"\\n\\tmessageWidth := 0.\\n\\tkeywords with: (args copyFrom: 1 to: keywords size)\\n\\t\\tdo: \\n\\t\\t\\t[:kwd :arg | \\n\\t\\t\\tisAConditional \\n\\t\\t\\t\\tifTrue: [column addMorphBack: (column transparentSpacerOfSize: 3 @ 3)].\\n\\t\\t\\t(row := column addRow: #keyword2 on: nodeWithNilReceiver)\\n\\t\\t\\t\\tborderWidth: 1;\\n\\t\\t\\t\\tparseNode: (nodeWithNilReceiver \\n\\t\\t\\t\\t\\t\\t\\tas: (onlyOne ifTrue: [MessageNode] ifFalse: [MessagePartNode]));\\n\\t\\t\\t\\tborderColor: row stdBorderColor.\\n\\t\\t\\tisAConditional \\n\\t\\t\\t\\tifTrue: [row addMorphBack: (row transparentSpacerOfSize: 20 @ 6)].\\n\\t\\t\\trow \\n\\t\\t\\t\\taddToken: kwd\\n\\t\\t\\t\\ttype: #keyword2\\n\\t\\t\\t\\ton: (onlyOne \\n\\t\\t\\t\\t\\t\\tifTrue: [SelectorNode new key: kwd code: nil\\t\\\"fill this in?\\\"]\\n\\t\\t\\t\\t\\t\\tifFalse: [KeyWordNode new]).\\n\\t\\t\\targ asMorphicSyntaxIn: row.\\n\\t\\t\\tmessageWidth := messageWidth + row fullBounds width].\\n\\tonlyOne \\n\\t\\tifTrue: \\n\\t\\t\\t[self replaceSubmorph: column by: row.\\n\\t\\t\\tcolumn := row].\\n\\treceiverMorph ifNil: [^self].\\n\\treceiverWidth + messageWidth < 350 \\n\\t\\tifTrue: \\n\\t\\t\\t[isAConditional ifFalse: [self unfoldMessage].\\n\\t\\t\\t^self].\\n\\t((receiverWidth > 200 \\n\\t\\tor: [receiverWidth > 80 and: [column fullBounds height > 20]]) or: \\n\\t\\t\\t\\t[receiverMorph fullBounds width > 30 \\n\\t\\t\\t\\t\\tand: [column fullBounds height > 100 or: [column fullBounds width > 250]]]) \\n\\t\\tifTrue: [^self foldMessage]! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/26/2001 14:04'!\\nmessageOneArg: key receiver: receiver selector: selector args: args\\n\\n\\t| row firstArgMorph |\\n\\n\\trow _ (self addSingleKeywordRow: key) layoutInset: 1.\\n\\trow parseNode: selector.\\n\\tfirstArgMorph _ args first asMorphicSyntaxIn: self.\\n\\treceiver ifNil: [^ self].\\n\\t(firstArgMorph fullBounds height > 100\\n\\t\\t\\tor: [firstArgMorph fullBounds width > 250])\\n\\t\\tifTrue: [self foldMessageOneArg].\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/26/2001 17:12'!\\nmethodNodeInner: aNode selectorOrFalse: selectorOrFalse precedence: precedence arguments: arguments temporaries: temporaries primitive: primitive block: block\\n\\t| header selNode |\\n\\n\\tselNode _ selectorOrFalse class == SelectorNode \\n\\t\\tifTrue: [selectorOrFalse] \\n\\t\\tifFalse: [SelectorNode new key: selectorOrFalse code: nil].\\n\\theader _ self addRow: Color white on: selNode.\\n\\tprecedence = 1\\n\\t\\tifTrue: [header addToken: aNode selector type: #methodHeader1 on: selNode]\\n\\t\\tifFalse: [aNode selector keywords with: arguments do:\\n\\t\\t\\t\\t\\t[:kwd :arg | \\n\\t\\t\\t\\t\\theader addToken: kwd type: #methodHeader2 on: selNode.\\n\\t\\t\\t\\t\\t(arg asMorphicSyntaxIn: header) color: #blockarg2]].\\n\\taNode addCommentToMorph: self.\\n\\tself addTemporaries: temporaries.\\n\\t(primitive > 0 and: [(primitive between: 255 and: 519) not]) ifTrue:\\n\\t\\t[\\\"Dont decompile <prim> for, eg, ^ self \\\"\\n\\t\\tself addTextRow: (String streamContents: [ :strm | aNode printPrimitiveOn: strm])].\\n\\tblock asMorphicSyntaxIn: self.\\n\\t^ self\\n! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'tk 7/31/2001 17:37'!\\nmethodNodeOuter: aNode\\n\\n\\t| block |\\n\\t\\n\\tself borderWidth: 0.\\n\\taNode asMorphicSyntaxIn: self.\\n\\tself alansTest1 ifTrue: [self addTemporaryControls].\\n\\tself finalAppearanceTweaks.\\n\\t\\t\\\"self setProperty: #deselectedColor toValue: Color transparent.\\\"\\n\\tblock _ self findA: BlockNode.\\n\\t\\t\\\"block setProperty: #deselectedColor toValue: Color transparent.\\\"\\n\\tblock submorphs size = 1 ifTrue: [^ self].\\t\\\"keep '^ self' if that is the only thing in method\\\"\\n\\tblock submorphs last decompile string = '^ self ' ifTrue: [\\n\\t\\tblock submorphs last delete].\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'node to morph' stamp: 'RAA 2/15/2001 19:49'!\\nvanillaMessageNode: aNode receiver: receiver selector: selector arguments: arguments\\n\\n\\t| substitute row sel |\\n\\tsel _ #message.\\n\\t((self nodeClassIs: CascadeNode) and: [self parseNode receiver ~~ aNode]) ifTrue: [\\n\\t\\tsel _ #keyword2.\\n\\t\\treceiver ifNotNil: [self inform: 'receiver should be nil']].\\n\\trow _ self addRow: sel on: aNode.\\n\\tsubstitute _ aNode as: TileMessageNode.\\n\\t(aNode macroPrinter == #printCaseOn:indent:) ifTrue: [\\n\\t\\taNode asMorphicCaseOn: row indent: nil.\\n\\t\\t^ self].\\n\\taNode macroPrinter\\n\\t\\tifNotNil: \\n\\t\\t\\t[substitute perform: aNode macroPrinter with: row with: nil]\\n\\t\\tifNil: \\n\\t\\t\\t[substitute \\n\\t\\t\\t\\tprintKeywords: selector key\\n\\t\\t\\t\\targuments: arguments\\n\\t\\t\\t\\ton: row\\n\\t\\t\\t\\tindent: nil].\\n\\t^ row addTransparentSpacerOfSize: 3@0.\\t\\\"horizontal spacing only\\\"\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'RAA 2/14/2001 20:34'!\\nimmediatelyBelowTheMethodNode\\n\\n\\t^(owner respondsTo: #isMethodNode) and: [owner isMethodNode]! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 8/24/2001 15:41'!\\nisAVariable\\n\\t\\\"There are three kinds of variable nodes\\\"\\n\\n\\t((parseNode class == TempVariableNode) or: [\\n\\t\\t(parseNode class == LiteralVariableNode) or: [\\n\\t\\t\\tparseNode class == VariableNode]]) ifFalse: [^ false].\\n\\t^ (ClassBuilder new reservedNames includes: \\n\\t\\t\\tself decompile string withoutTrailingBlanks) not! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/17/2000 08:31'!\\nisBlockNode\\n\\t^ parseNode class == BlockNode! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/26/2001 05:50'!\\nisDeclaration\\n\\t\\\"Return true if I am a TempVarNode inside a declaration of some kind, including a method arg\\\"\\n\\n\\t| opc |\\n\\towner isSyntaxMorph ifFalse: [^ false].\\n\\topc _ owner parseNode class.\\n\\topc == BlockArgsNode ifTrue: [^ true].\\n\\topc == MethodTempsNode ifTrue: [^ true].\\n\\topc == SelectorNode ifTrue: [^ true].\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'gm 2/22/2003 12:30'!\\nisLeafTile\\n\\tself hasSubmorphs ifFalse: [^false].\\n\\t(self firstSubmorph isSyntaxMorph) ifTrue: [^false].\\n\\t(self firstSubmorph isMemberOf: Morph) ifTrue: [^false].\\n\\t^true! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/17/2000 08:31'!\\nisMethodNode\\n\\t^ parseNode class == MethodNode! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/13/2001 15:28'!\\nisNoun\\n\\t\\\"Consider these to be nouns: MessageNode with receiver, CascadeNode with receiver, AssignmentNode, TempVariableNode, LiteralNode, VariableNode, LiteralVariableNode.\\\"\\n\\n\\t(#(TempVariableNode LiteralNode VariableNode LiteralVariableNode) includes:\\n\\t\\t(parseNode class name)) ifTrue: [^ true].\\n\\n\\t(self nodeClassIs: MessageNode) ifTrue: [^ parseNode receiver notNil].\\n\\t(self nodeClassIs: CascadeNode) ifTrue: [^ parseNode receiver notNil].\\n\\t(self nodeClassIs: AssignmentNode) ifTrue: [^ submorphs size >= 3].\\n\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'tk 9/23/2001 00:17'!\\nisSelfTile\\n\\n\\t^ parseNode class == VariableNode and: [self decompile asString = 'self ']\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'di 11/6/2000 15:26'!\\nnodeClassIs: aParseNodeClass\\n\\t\\\"Test the class of my parseNode\\\"\\n\\n\\t^ parseNode class == aParseNodeClass! !\\n\\n!SyntaxMorph methodsFor: 'node types' stamp: 'dgd 2/22/2003 13:40'!\\nrootTile\\n\\t^self \\n\\t\\torOwnerSuchThat: [:m | m owner isNil or: [m owner isSyntaxMorph not]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'player' stamp: 'tk 9/26/2001 06:05'!\\ncurrentDataValue\\n\\t\\\"Answer the current data value held by the receiver\\\"\\n\\n\\t^ self readOut valueFromContents! !\\n\\n!SyntaxMorph methodsFor: 'player' stamp: 'tk 2/15/2002 13:03'!\\nvariableDocks\\n\\t\\\"Answer a list of VariableDock objects for docking up my data with an instance held in my containing playfield. For a numeric-readout tile.\\\"\\n\\n\\t\\\"Is CardPlayer class holding my variableDock, or should I be using the caching mechanism in Morph>>variableDocks?\\\"\\n\\t| updatingString lab nn aGetter |\\n\\t(updatingString _ self readOut) ifNil: [^ #()].\\n\\tupdatingString getSelector ifNil: [\\n\\t\\tlab _ self submorphNamed: 'label' ifNone: [self defaultName].\\n\\t\\tnn _ lab contents asString.\\n\\t\\t\\\"nn at: 1 put: nn first asUppercase.\\\"\\n\\t\\tupdatingString getSelector: (aGetter _ 'get',nn) asSymbol;\\n\\t\\t\\tputSelector: (ScriptingSystem setterSelectorForGetter: aGetter).\\n\\t\\t].\\n\\t^ Array with: (VariableDock new \\n\\t\\t\\tvariableName: (updatingString getSelector allButFirst: 3) withFirstCharacterDownshifted \\n\\t\\t\\ttype: #number \\n\\t\\t\\tdefiningMorph: updatingString \\n\\t\\t\\tmorphGetSelector: #valueFromContents \\n\\t\\t\\tmorphPutSelector: #acceptValue:)! !\\n\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'aoy 2/15/2003 21:30'!\\naddArg: index \\n\\t\\\"I rep a SelectorNode. My string has been replaced. Append an argument to my owner.\\\"\\n\\n\\t\\\"See if any sample args are recorded\\\"\\n\\n\\t| sel rec aVocabulary mi sample descrip mthNode tiles |\\n\\tsel := self decompile asString asSymbol.\\n\\trec := self receiverObject.\\n\\tsample := rec class == Error \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[aVocabulary := self vocabularyToUseWith: rec.\\n\\t\\t\\t\\t\\tmi := aVocabulary methodInterfaceAt: sel ifAbsent: [nil].\\n\\t\\t\\t\\t\\tmi ifNil: [5]\\n\\t\\t\\t\\t\\t\\tifNotNil: \\n\\t\\t\\t\\t\\t\\t\\t[descrip := mi argumentVariables at: index.\\n\\t\\t\\t\\t\\t\\t\\tdescrip sample]]\\n\\t\\t\\t\\tifTrue: [5]. \\n\\tmthNode := self string: sample storeString toTilesIn: sample class.\\n\\ttiles := mthNode submorphs at: mthNode submorphs size - 1.\\t\\\"before the ^ self\\\"\\n\\tself owner addMorphBack: tiles! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:24'!\\nassignmentArrow\\n\\t\\\"Offer to embed this variable in a new assignment statement. (Don't confuse this with upDownAssignment:, which runs the up and down arrows that rotate among assignment types.)\\\"\\n\\t| rr |\\n\\n\\tself isAVariable ifFalse: [^ nil].\\n\\tself isDeclaration ifTrue: [^ nil].\\n\\t^ (rr _ RectangleMorph new)\\n\\t\\textent: 11@13; borderWidth: 1; color: Color lightGreen;\\n\\t\\tborderColor: Color gray;\\n\\t\\taddMorph: ((self noiseStringMorph: '_') topLeft: rr topLeft + (3@0));\\n\\t\\ton: #mouseUp send: #newAssignment to: self\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'gk 2/23/2004 21:08'!\\nchangeSound: upDown\\n\\t| ind arg st soundChoices index it current |\\n\\t\\\"move in the list of sounds. Adjust arg tile after me\\\"\\n\\n\\tind _ owner submorphs indexOf: self.\\n\\targ _ owner submorphs atWrap: ind+1.\\n\\targ isSyntaxMorph ifFalse: [^ self].\\n\\tst _ arg submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\tsoundChoices _ SoundService default sampledSoundChoices.\\n\\tcurrent _ st contents copyFrom: 2 to: st contents size-1.\\t\\\"remove string quotes\\\"\\n\\tindex _ soundChoices indexOf: current.\\n\\tindex > 0 ifTrue:\\n\\t\\t[st contents: (it _ soundChoices atWrap: index + upDown) printString.\\n\\t\\tself playSoundNamed: it].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/26/2001 14:31'!\\ncolorPatch\\n\\t\\\"Return a color patch button that lets the user choose a color and modifies the code\\\"\\n\\t| cc patch sel completeMsg |\\n\\t\\n\\t\\n\\t((self nodeClassIs: MessageNode) \\\"or: [self nodeClassIs: SelectorNode]\\\") ifFalse: [^ nil].\\n\\t(sel _ self selector) ifNil: [^ nil].\\n\\t(Color colorNames includes: sel) | (sel == #r:g:b:) ifFalse: [^ nil].\\n\\t\\t\\\"a standard color name\\\"\\n\\tcompleteMsg _ self isNoun ifTrue: [self] \\n\\t\\t\\t\\tifFalse: [owner isNoun ifTrue: [owner] ifFalse: [owner owner]].\\n\\n\\t(cc _ completeMsg try) class == Color ifFalse: [^ nil].\\n\\tpatch _ ColorTileMorph new colorSwatchColor: cc.\\n\\t\\t\\\"sends colorChangedForSubmorph: to the messageNode\\\"\\n\\tpatch color: Color transparent; borderWidth: 0. patch submorphs last delete.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 2/21/2001 16:37'!\\ndeleteLine\\n\\t| temp |\\n\\ttemp _ owner.\\n\\tself deletePopup.\\n\\tself delete.\\n\\ttemp setSelection: nil.\\n\\ttemp acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 12/13/2000 13:05'!\\ndeletePopup\\n\\n\\tself valueOfProperty: #myPopup ifPresentDo:\\n\\t\\t[:panel | panel delete. self removeProperty: #myPopup]! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 2/21/2001 13:09'!\\ndismisser\\n\\t\\\"Return the icon to delete this line of tiles. I am an entire line in a block.\\\"\\n\\t| handle handleSpec colorToUse iconName form |\\n\\n\\t(owner isSyntaxMorph and: [owner nodeClassIs: BlockNode]) ifFalse: [^ nil].\\n\\thandleSpec _ Preferences haloSpecifications fourth.\\t\\\"dismiss\\\"\\n\\thandle _ EllipseMorph\\n\\t\\t\\tnewBounds: (Rectangle center: 10@10 extent: 16 asPoint)\\n\\t\\t\\tcolor: (colorToUse _ Color colorFrom: handleSpec color).\\n\\ticonName _ handleSpec iconSymbol.\\n\\tform _ ScriptingSystem formAtKey: iconName.\\t\\\"#'Halo-Dismiss'\\\"\\n\\thandle addMorphCentered: (ImageMorph new\\n\\t\\t\\t\\timage: form; \\n\\t\\t\\t\\tcolor: colorToUse makeForegroundColor;\\n\\t\\t\\t\\tlock).\\n\\thandle on: #mouseDown send: #deleteLine to: self.\\n\\t^ handle! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 10/17/2001 13:38'!\\ndupTile: evt\\n\\n\\t| dup |\\n\\tself deletePopup.\\n\\t\\\"self deselect.\\\"\\n\\tdup _ self duplicateMorph: evt.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [dup align: dup center with: evt hand position.\\n\\t\\t\\t\\tdup lookTranslucent]\\n\\t\\tifFalse: [dup align: dup topLeft\\n\\t\\t\\t\\t\\twith: evt hand position + self cursorBaseOffset].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 10/17/2001 13:29'!\\nduplicator\\n\\t\\\"Return the icon to duplicate this tile.\\\"\\n\\t| handle handleSpec colorToUse iconName form |\\n\\n\\thandleSpec _ Preferences haloSpecifications at: 11.\\t\\\"duplicate\\\"\\n\\thandle _ EllipseMorph\\n\\t\\t\\tnewBounds: (Rectangle center: 10@10 extent: 16 asPoint)\\n\\t\\t\\tcolor: (colorToUse _ Color colorFrom: handleSpec color).\\n\\ticonName _ handleSpec iconSymbol.\\n\\tform _ ScriptingSystem formAtKey: iconName.\\t\\\"#'Halo-Dup'\\\"\\n\\thandle addMorphCentered: (ImageMorph new\\n\\t\\t\\t\\timage: form; \\n\\t\\t\\t\\tcolor: colorToUse makeForegroundColor;\\n\\t\\t\\t\\tlock).\\n\\thandle on: #mouseDown send: #dupTile: to: self.\\n\\t^ handle! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'ar 3/18/2001 17:28'!\\nevent: arg1 arrow: arg2 upDown: arg3\\n\\t\\\"Reorder the arguments for existing event handlers\\\"\\n\\t(arg3 isMorph and:[arg3 eventHandler notNil]) ifTrue:[arg3 eventHandler fixReversedValueMessages].\\n\\t^self upDown: arg1 event: arg2 arrow: arg3! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 13:38'!\\nextend\\n\\t| messageNodeMorph first |\\n\\t\\\"replace this noun with a new message like (arg + 1). If type is not known, ask the user to type in a selector. Use nil as arg. Let user drag something to it afterwards.\\\"\\n\\n\\t\\\"Later do evaluation of self to see what type and offer right selector\\\"\\n\\tself deselect.\\n\\tmessageNodeMorph _ (MessageSend receiver: 1 selector: #+ arguments: #(1))\\n\\t\\t\\t\\t\\t\\t\\t\\tasTilesIn: Player globalNames: false.\\n\\towner replaceSubmorph: self by: messageNodeMorph.\\n\\tfirst _ messageNodeMorph submorphs detect: [:mm | mm isSyntaxMorph].\\n\\tmessageNodeMorph replaceSubmorph: first by: self.\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:14'!\\nextendArrow\\n\\t\\\"Return the extend arrow button. It replaces the argument with a new message.\\n\\tI am a number or getter messageNode.\\\"\\n\\t| patch |\\n\\t\\n\\tself isNoun ifFalse: [^ nil].\\n\\tself isDeclaration ifTrue: [^ nil].\\n\\tpatch _ (ImageMorph new image: (TileMorph classPool at: #SuffixPicture)).\\n\\tpatch on: #mouseDown send: #extend to: self.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 11:35'!\\nnewAssignment\\n\\t\\\"I am a variableNode. Place me inside an assignment statement.\\\"\\n\\n\\t| new old |\\n\\tparseNode name: self decompile.\\t\\\"in case user changed name\\\"\\n\\tnew _ owner assignmentNode: AssignmentNode new variable: parseNode \\n\\t\\t\\t\\t\\tvalue: parseNode copy.\\n\\tself deselect.\\n\\t(old _ owner) replaceSubmorph: self by: new.\\t\\\"do the normal replacement\\\"\\n\\t(old isSyntaxMorph) ifTrue: [old cleanupAfterItDroppedOnMe].\\t\\\"now owned by no one\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'dgd 2/22/2003 13:40'!\\nofferPopUp\\n\\t\\\"Put up a halo to allow user to change\\n\\t\\tLiterals (Integer, true),\\n\\t\\tSelector (beep: sound, +,-,*,//,\\\\\\\\, r:g:b:, setX: incX: decX: for any X,),\\n\\t\\tVariable (Color),\\n\\t\\tnot AssignmentNode (_ inc dec),\\n\\tExtend arrows on each literal, variable, and message, (block that is by itself).\\n\\tRetract arrows on each literal or variable, or message or block that is an argument.\\n\\tAny literal can be changed by Shift-clicking and typing.\\\"\\n\\n\\t| panel any upDown retract extend colorPatch edge dismiss rr duplicate |\\n\\t(self hasProperty: #myPopup) ifTrue: [^self].\\t\\\"already has one\\\"\\n\\tany := false.\\n\\t(upDown := self upDownArrows) ifNotNil: [any := true].\\t\\\"includes menu of selectors\\\"\\n\\t(retract := self retractArrow) ifNotNil: [any := true].\\n\\t(extend := self extendArrow) ifNotNil: [any := true].\\n\\t(dismiss := self dismisser) ifNotNil: [any := true].\\n\\t(duplicate := self duplicator) ifNotNil: [any := true].\\n\\t\\\"(assign _ self assignmentArrow) ifNotNil: [any _ true].\\n\\t\\t\\tget from menu or any other assignment\\\"\\n\\tsubmorphs last class == ColorTileMorph \\n\\t\\tifFalse: [(colorPatch := self colorPatch) ifNotNil: [any := true]].\\n\\tany ifFalse: [^self].\\n\\t\\\"Transcript cr; print: parseNode class; space; \\n\\t\\tprint: (self hasProperty: #myPopup); endEntry.\\\"\\n\\tpanel := (RectangleMorph new)\\n\\t\\t\\t\\tcolor: Color transparent;\\n\\t\\t\\t\\tborderWidth: 0.\\n\\tupDown ifNotNil: \\n\\t\\t\\t[panel addMorphBack: upDown first.\\n\\t\\t\\tupDown first align: upDown first topLeft with: panel topLeft + (0 @ 0).\\n\\t\\t\\tpanel addMorphBack: upDown second.\\n\\t\\t\\tupDown second align: upDown second topLeft\\n\\t\\t\\t\\twith: upDown first bottomLeft + (0 @ 1).\\n\\t\\t\\tupDown size > 2 \\n\\t\\t\\t\\tifTrue: \\n\\t\\t\\t\\t\\t[panel addMorphBack: upDown third.\\n\\t\\t\\t\\t\\tupDown third align: upDown third topLeft\\n\\t\\t\\t\\t\\t\\twith: upDown first topRight + (2 @ 3)]].\\n\\trr := self right.\\n\\tcolorPatch ifNotNil: \\n\\t\\t\\t[rr := rr + colorPatch submorphs first width + 1.\\n\\t\\t\\tself addMorphBack: colorPatch\\t\\\"always in tile\\\"\\n\\t\\t\\t\\\"colorPatch align: colorPatch topLeft \\n\\t\\t\\t\\t\\twith: panel topLeft + (1@1)\\\"].\\n\\tretract ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: retract.\\n\\t\\t\\tretract align: retract topLeft with: (edge + 2) @ (panel top + 3)].\\n\\textend ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: extend.\\n\\t\\t\\textend align: extend topLeft with: (edge + 2) @ (panel top + 3)].\\n\\tduplicate ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: duplicate.\\n\\t\\t\\tduplicate align: duplicate topLeft with: (edge + 2) @ (panel top + 1)].\\n\\tdismiss ifNotNil: \\n\\t\\t\\t[edge := panel submorphs isEmpty \\n\\t\\t\\t\\t\\t\\tifTrue: [panel left]\\n\\t\\t\\t\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\t\\tpanel addMorphBack: dismiss.\\n\\t\\t\\tdismiss align: dismiss topLeft with: (edge + 2) @ (panel top + 1)].\\n\\t\\\"\\tassign ifNotNil: [\\n\\t\\tedge _ panel submorphs isEmpty \\n\\t\\t\\tifTrue: [panel left] \\n\\t\\t\\tifFalse: [panel submorphs last right].\\n\\t\\tpanel addMorphBack: assign.\\n\\t\\tassign align: assign topLeft with: (edge+2) @ (panel top + 2)].\\n\\\"\\n\\tpanel align: panel topLeft with: rr @ (self top - 2).\\n\\tpanel extent: panel submorphs last bottomRight - panel topLeft.\\n\\tself setProperty: #myPopup toValue: panel.\\n\\tself addMorphBack: panel\\t\\\"Any reason ever to have panel below?\\\"\\n\\t\\\"(owner listDirection = #topToBottom and: [self listDirection = #leftToRight])\\n\\t\\tifTrue: [self addMorphBack: panel]\\n\\t\\tifFalse: [owner addMorph: panel after: self].\\\"! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 13:39'!\\nreplaceKeyWord: evt menuItem: stringMorph\\n\\t\\\"Replace my entire message (which may be multi-part) with the one specified. Preserve all argument tiles, either in the new message or in the world outside the scriptor. I am a SelectorNode or KeyWordNode.\\\"\\n\\n\\t| menu new news newSel mm newTree newRec newArgs top oldArgNodes share ctrY |\\n\\t(menu _ stringMorph owner owner) class == RectangleMorph ifTrue: [\\n\\t\\tmenu delete].\\n\\tnew _ stringMorph contents.\\n\\tnew first = $( ifTrue: [^ self].\\t\\\"Cancel\\\"\\n\\tnew first = $ ifTrue: [^ self].\\t\\\"nothing\\\"\\n\\tnews _ String streamContents: [:strm | \\\"remove fake args\\\"\\n\\t\\t(new findBetweenSubStrs: #(' 5' $ )) do: [:part | strm nextPutAll: part]].\\n\\tnewSel _ stringMorph valueOfProperty: #syntacticallyCorrectContents.\\n\\tnewSel ifNil: [newSel _ news].\\n\\tmm _ MessageSend receiver: 5 selector: newSel \\n\\t\\t\\targuments: ((Array new: newSel numArgs) atAllPut: 5).\\n\\tnewTree _ mm asTilesIn: Object globalNames: false.\\n\\tnewRec _ newTree receiverNode.\\n\\tnewArgs _ newTree argumentNodes.\\n\\tctrY _ self fullBoundsInWorld center y.\\n\\ttop _ self messageNode.\\n\\tnewRec owner replaceSubmorph: newRec by: top receiverNode.\\n\\toldArgNodes _ top argumentNodes.\\n\\tshare _ newArgs size min: oldArgNodes size.\\n\\t(newArgs first: share) with: (oldArgNodes first: share) do: [:newNode :oldNode | \\n\\t\\tnewNode owner replaceSubmorph: newNode by: oldNode].\\n\\t\\\"later get nodes for objects of the right type for new extra args\\\"\\n\\n\\ttop owner replaceSubmorph: top by: newTree.\\n\\n\\t\\\"Deposit extra args in the World\\\"\\n\\t(oldArgNodes copyFrom: share+1 to: oldArgNodes size) do: [:leftOver |\\n\\t\\t(leftOver parseNode class == LiteralNode and: [leftOver decompile asString = '5']) \\n\\t\\t\\tifFalse: [newTree pasteUpMorph addMorphFront: leftOver.\\n\\t\\t\\t\\tleftOver position: newTree enclosingPane fullBoundsInWorld right - 20 @ ctrY.\\n\\t\\t\\t\\tctrY _ ctrY + 26]\\n\\t\\t\\tifTrue: [leftOver delete]].\\n\\tnewTree acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/19/2001 21:32'!\\nreplaceSel: evt menuItem: stringMorph\\n\\t\\\"I rep a SelectorNode. Replace my selector with new one that was just chosen from a menu\\\"\\n\\n\\t| menu new old newSel ms oa na case news |\\n\\t(menu _ stringMorph owner owner) class == RectangleMorph ifTrue: [\\n\\t\\tmenu delete].\\n\\tnew _ stringMorph contents.\\n\\tnew first = $( ifTrue: [^ self].\\t\\\"Cancel\\\"\\n\\tnew first = $ ifTrue: [^ self].\\t\\\"nothing\\\"\\n\\tnews _ String streamContents: [:strm | \\\"remove fake args\\\"\\n\\t\\t(new findBetweenSubStrs: #(' 5' $ )) do: [:part | strm nextPutAll: part]].\\n\\tnewSel _ stringMorph valueOfProperty: #syntacticallyCorrectContents.\\n\\tnewSel ifNil: [newSel _ news].\\n\\told _ (ms _ self findA: StringMorph) valueOfProperty: #syntacticallyCorrectContents.\\n\\told ifNil: [old _ (self findA: StringMorph) contents].\\n\\toa _ old numArgs. na _ newSel numArgs. case _ 5.\\n\\t(oa = 1) & (na = 1) ifTrue: [case _ 1]. \\n\\t(oa = 0) & (na = 0) ifTrue: [case _ 2].\\n\\t(oa = 1) & (na = 0) ifTrue: [case _ 3].\\n\\t(oa = 0) & (na = 1) ifTrue: [case _ 4].\\n\\tcase <= 4 ifTrue: [\\\"replace the selector\\\"\\n\\t\\tms contents: news.\\t\\\"not multi-part\\\"\\n\\t\\tms setProperty: #syntacticallyCorrectContents toValue: newSel].\\n\\tcase = 3 ifTrue: [owner tossOutArg: 1].\\n\\tcase = 4 ifTrue: [self addArg: 1].\\n\\t\\\"more cases here. Rebuild the entire MessageNode\\\"\\n\\t\\n\\tself acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/28/2001 10:06'!\\nretract\\n\\t\\\"replace this message with its receiver. I am the message node.\\\"\\n\\t| rec cascade msg |\\n\\t(self nodeClassIs: CascadeNode) ifTrue:\\n\\t\\t[\\\"This is a piece of a cascaded message -- just delete it\\\"\\n\\t\\tself deletePopup.\\n\\t\\tcascade _ owner.\\n\\t\\tself delete.\\n\\t\\tcascade setSelection: {cascade. nil. cascade}.\\n\\t\\t^ cascade acceptIfInScriptor].\\n\\tself deletePopup.\\n\\t(rec _ self receiverNode)\\n\\t\\tifNil: [msg _ owner.\\n\\t\\t\\trec _ owner receiverNode.\\n\\t\\t\\tmsg owner replaceSubmorph: msg by: rec]\\n\\t\\tifNotNil: [owner replaceSubmorph: self by: rec].\\n\\trec setSelection: {rec. nil. rec}.\\n\\trec acceptIfInScriptor.! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 12/13/2000 12:57'!\\nretractArrow\\n\\t\\\"Return the retract arrow button. It replaces the current message with its receiver.\\n\\tI am in a MessageNode whose first subnode is not a MessagePartNode. I did not encounter a block on the way up to it. I am the last subnode in every owner up to it.\\\"\\n\\t| patch |\\n\\n\\t(self nodeClassIs: MessageNode) ifFalse: [^ nil].\\n\\t(owner isSyntaxMorph and: [owner parseNode == parseNode]) ifTrue: [^ nil].\\n\\n\\tpatch _ (ImageMorph new image: (TileMorph classPool at: #RetractPicture)).\\n\\tpatch on: #mouseDown send: #retract to: self.\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/18/2001 16:27'!\\nselectorMenu\\n\\t\\\"Put up a menu of all selectors that my receiver could be sent. Replace me with the one chosen. (If fewer args, put the tiles for the extra arg to the side, in script's owner (world?).)\\n\\tGo ahead and eval receiver to find out its type. Later, mark selectors for side effects, and don't eval those.\\n\\tPut up a table. Each column is a viewer category.\\\"\\n\\n\\t| cats value catNames interfaces list setter wording all words ind aVocabulary limitClass |\\n\\tcats _ #().\\n\\tall _ Set new.\\n\\tvalue _ self receiverObject.\\n\\tvalue class == Error ifTrue: [^ nil].\\n\\t\\n\\taVocabulary _ self vocabularyToUseWith: value.\\n\\tlimitClass _ self limitClassToUseWith: value vocabulary: aVocabulary.\\n\\tcatNames _ value categoriesForVocabulary: aVocabulary limitClass: limitClass.\\n\\tcats _ catNames collect: [:nn | \\n\\t\\tlist _ OrderedCollection new.\\n\\t\\tinterfaces _ value methodInterfacesForCategory: nn \\n\\t\\t\\t\\t\\t\\tinVocabulary: aVocabulary limitClass: limitClass.\\n\\t\\tinterfaces do: [:mi | \\n\\t\\t\\t(all includes: mi selector) ifFalse: [\\n\\t\\t\\t\\t\\\"list add: (self aSimpleStringMorphWith: mi elementWording). Expensive\\\"\\n\\t\\t\\t\\twords _ mi selector.\\n\\t\\t\\t\\t(words beginsWith: 'get ') ifTrue: [words _ words allButFirst: 4].\\n\\t\\t\\t\\tmi selector last == $: ifTrue: [\\n\\t\\t\\t\\t\\twords _ String streamContents: [:strm | \\\"add fake args\\\"\\n\\t\\t\\t\\t\\t\\t(words findTokens: $:) do: [:part | strm nextPutAll: part; nextPutAll: ' 5 ']].\\n\\t\\t\\t\\t\\twords _ words allButLast].\\n\\t\\t\\t\\tmi selector isInfix ifTrue: [words _ words, ' 5'].\\n\\t\\t\\t\\twords _ self splitAtCapsAndDownshifted: words.\\t\\n\\t\\t\\t\\tlist add: (self anUpdatingStringMorphWith: words special: true).\\n\\t\\t\\t\\twords = mi selector ifFalse: [\\n\\t\\t\\t\\t\\tlist last setProperty: #syntacticallyCorrectContents toValue: mi selector].\\n\\t\\t\\t\\tall add: mi selector].\\n\\t\\t\\tsetter _ mi companionSetterSelector asString.\\n\\t\\t\\t(setter = 'nil') | (all includes: setter) ifFalse: [\\\"need setters also\\\"\\n\\t\\t\\t\\twording _ (self translateToWordySetter: setter).\\n\\t\\t\\t\\tlist add: (self aSimpleStringMorphWith: wording, ' 5').\\n\\t\\t\\t\\twording = setter ifFalse: [\\n\\t\\t\\t\\t\\tlist last setProperty: #syntacticallyCorrectContents \\n\\t\\t\\t\\t\\t\\ttoValue: setter].\\n\\t\\t\\t\\tall add: setter]].\\n\\t\\tlist].\\n\\t(ind _ catNames indexOf: 'scripts') > 0 ifTrue: [\\n\\t\\t(cats at: ind) first contents = 'empty script' ifTrue: [(cats at: ind) removeFirst]].\\n\\tcats first addFirst: (self aSimpleStringMorphWith: ' ').\\t\\\"spacer\\\"\\n\\tcats first addFirst: (self aSimpleStringMorphWith: '( from ', value class name, ' )').\\n\\tcats first first color: (Color green mixed: 0.25 with: Color black).\\n\\tself selectorMenuAsk: cats.\\t\\\"The method replaceSel:menuItem: does the work. \\n\\t\\tand replaces the selector.\\\"\\n\\t! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/20/2001 16:04'!\\nselectorMenuAsk: listOfLists\\n\\t\\\"I represent a SelectorNode to be replaced by one of the selectors in one of the category lists. Each list has pre-built StringMorphs in it.\\\"\\n\\n\\t| menu col |\\n\\tlistOfLists isEmpty ifTrue: [^ nil].\\n\\tlistOfLists first addFirst: (self aSimpleStringMorphWith: '( Cancel )').\\n\\tlistOfLists first first color: Color red.\\n\\tmenu _ RectangleMorph new.\\n\\tmenu listDirection: #leftToRight; layoutInset: 3; cellInset: 1@0.\\n\\tmenu layoutPolicy: TableLayout new; hResizing: #shrinkWrap; \\n\\t\\tvResizing: #shrinkWrap; color: (Color r: 0.767 g: 1.0 b: 0.767);\\n\\t\\tuseRoundedCorners; cellPositioning: #topLeft.\\n\\tlistOfLists do: [:ll |\\n\\t\\tcol _ Morph new.\\n\\t \\tcol listDirection: #topToBottom; layoutInset: 0; cellInset: 0@0.\\n\\t\\tcol layoutPolicy: TableLayout new; hResizing: #shrinkWrap.\\n\\t\\tcol color: Color transparent; vResizing: #shrinkWrap.\\n\\t\\tmenu addMorphBack: col.\\n\\t\\tll do: [:ss | \\n\\t\\t\\tcol addMorphBack: ss.\\n\\t\\t\\tss on: #mouseUp send: #replaceKeyWord:menuItem: to: self]\\n\\t\\t].\\n\\tself world addMorph: menu.\\n\\tmenu setConstrainedPosition: (owner localPointToGlobal: self topRight) + (10@-30) \\n\\t\\t\\thangOut: false.\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'sw 3/18/2004 00:35'!\\nsetSelector: stringLike in: stringMorph\\n\\t\\\"Store the new selector and accept method.\\\"\\n\\n\\t| aSymbol myType str |\\n\\taSymbol _ stringLike asSymbol.\\n\\t(ScriptingSystem helpStringOrNilFor: aSymbol) ifNotNilDo:\\n\\t\\t[:aString |\\n\\t\\t\\tself setBalloonText: aString translated].\\n\\tmyType _ stringMorph valueOfProperty: #syntacticReformatting ifAbsent: [#none].\\n\\tstr _ aSymbol.\\n\\t(self isStandardSetterKeyword: str) ifTrue: [str _ self translateToWordySetter: str].\\n\\t(self isStandardGetterSelector: str) ifTrue: [str _ self translateToWordyGetter: str].\\n\\t(self shouldBeBrokenIntoWords: myType) \\n\\t\\tifTrue: [str _ self substituteKeywordFor: str].\\n\\tstringMorph contents: str.\\n\\t\\\"parseNode key: aSymbol code: nil.\\\"\\n\\tstr = stringLike ifFalse:\\n\\t\\t[stringMorph setProperty: #syntacticallyCorrectContents toValue: aSymbol].\\n\\tself acceptSilently! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/19/2001 15:47'!\\ntossOutArg: extras\\n\\n\\t\\\"Remove the tiles for the last N keywords and arguments. Place the tiles beside the current window. I am a SyntaxMorph for a MessageNode.\\\"\\n\\n\\t| cnt ctr |\\n\\tcnt _ 0.\\n\\t submorphs copy reverseDo: [:sub |\\n\\t\\tctr _ sub fullBoundsInWorld center.\\n\\t\\tsub delete.\\n\\t\\t(sub isSyntaxMorph and: [sub parseNode notNil]) ifTrue: [\\n\\t\\t\\tsub isNoun ifTrue: [\\n\\t\\t\\t\\tself pasteUpMorph addMorphFront: sub.\\n\\t\\t\\t\\tsub position: self enclosingPane fullBoundsInWorld right - 20 @ ctr y].\\n\\t\\t\\t(cnt _ cnt + 1) >= extras ifTrue: [^ self]]].! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 13:35'!\\nupDown: delta event: evt arrow: arrowMorph\\n\\n\\t| st |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: LiteralNode) ifTrue:\\n\\t\\t[ \\\"+/- 1\\\"\\n\\t\\tst contents: (self decompile asNumber + delta) printString.\\n\\t\\t^ self acceptUnlogged].\\n\\t(self nodeClassIs: VariableNode) ifTrue:\\n\\t\\t[ \\\"true/false\\\"\\n\\t\\tst contents: (self decompile string = 'true') not printString.\\n\\t\\t^ self acceptSilently ifFalse: [self changed].\\n\\t\\t\\t\\\"maybe set parseNode's key\\\"].\\n\\n\\t(self upDownArithOp: delta) ifTrue: [^ self].\\t\\\"+ - // * < > <= = beep:\\\"\\n\\n\\t(self upDownAssignment: delta) ifTrue: [^ self].\\n\\t\\t\\\"Handle assignment -- increaseBy: <- multiplyBy:\\\"\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 7/24/2001 17:54'!\\nupDownArithOp: delta\\n\\t\\\"Change a + into a -. Also do sounds (change the arg to the beep:).\\\"\\n\\n\\t| aList index st |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: SelectorNode) ifTrue:\\n\\t\\t[aList _ #(+ - * / // \\\\\\\\ min: max:).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\taList _ #(= ~= > >= isDivisibleBy: < <=).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\taList _ #(== ~~).\\n\\t\\t(index _ aList indexOf: self decompile asString) > 0 ifTrue:\\n\\t\\t\\t[self setSelector: (aList atWrap: index + delta) in: st. ^ true].\\n\\n\\t\\t'beep:' = self decompile asString ifTrue:\\n\\t\\t\\t[\\\"replace sound arg\\\"\\n\\t\\t\\tself changeSound: delta.\\n\\t\\t\\tself acceptSilently. ^ true].\\n\\t\\t].\\n\\t^ false! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 9/20/2001 16:33'!\\nupDownArrows\\n\\t\\\"Return an array of two up/down arrow buttons.\\n\\tIt replaces the selector or arg with a new one.\\n\\tI am a number or boolean or a selector (beep:, +,-,*,//,\\\\\\\\, or setX: incX: decX: for any X.\\\"\\n\\t| patch any noMenu |\\n\\tany _ (self nodeClassIs: LiteralNode) and: [parseNode key isNumber].\\n\\tany _ any or: [(self nodeClassIs: VariableNode) and:\\n\\t\\t\\t\\t\\t\\t[(#('true' 'false') includes: self decompile asString)]].\\n\\tnoMenu _ any.\\n\\n\\tany _ any or: [self nodeClassIs: SelectorNode].\\t\\\"arrows and menu of selectors\\\"\\n\\tany _ any or: [self nodeClassIs: KeyWordNode].\\n\\tany ifFalse: [^ nil].\\n\\n\\tpatch _ {(ImageMorph new image: TileMorph upPicture)\\n\\t\\t\\t\\ton: #mouseDown send: #upDown:event:arrow: to: self withValue: 1;\\n\\t\\t\\t\\ton: #mouseStillDown send: #upDownMore:event:arrow: \\n\\t\\t\\t\\t\\tto: self withValue: 1;\\n\\t\\t\\t\\ton: #mouseUp send: #upDownDone to: self.\\n\\t\\t\\t(ImageMorph new image: TileMorph downPicture)\\n\\t\\t\\t\\ton: #mouseDown send: #upDown:event:arrow: to: self withValue: -1;\\n\\t\\t\\t\\ton: #mouseStillDown send: #upDownMore:event:arrow: \\n\\t\\t\\t\\t\\tto: self withValue: -1;\\n\\t\\t\\t\\ton: #mouseUp send: #upDownDone to: self}.\\n\\tnoMenu ifFalse: [patch _ patch, {(RectangleMorph new)\\n\\t\\t\\t\\t\\t\\textent: 6@10; borderWidth: 1;\\n\\t\\t\\t\\t\\t\\tborderColor: Color gray;\\n\\t\\t\\t\\t\\t\\ton: #mouseUp send: #selectorMenu to: self}.\\n\\t\\t\\t\\t\\tpatch last color: ((self nodeClassIs: SelectorNode) \\n\\t\\t\\t\\t\\t\\tifTrue: [Color lightGreen] ifFalse: [Color red darker])].\\n\\t^ patch! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'tk 8/24/2001 12:33'!\\nupDownAssignment: delta\\n\\t\\\"Rotate between increaseBy: decreaseBy: _ multiplyBy:\\\"\\n\\n\\t| st now want instVar |\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\t(self nodeClassIs: SelectorNode) ifTrue:\\n\\t\\t[\\\"kinds of assignment\\\"\\n\\t\\t((now _ self decompile asString) beginsWith: 'set') ifTrue:\\n\\t\\t\\t[\\\"a setX: 3\\\"\\n\\t\\t\\twant _ 1+delta. instVar _ (now allButFirst: 3) allButLast].\\n\\t\\t(now endsWith: 'IncreaseBy:') ifTrue:\\n\\t\\t\\t[\\\"a xIncreaseBy: 3 a setX: (a getX +3).\\\"\\n\\t\\t\\twant _ 2+delta. instVar _ now allButLast: 11].\\n\\t\\t(now endsWith: 'DecreaseBy:') ifTrue:\\n\\t\\t\\t[\\\"a xDecreaseBy: 3 a setX: (a getX -3).\\\"\\n\\t\\t\\twant _ 3+delta. instVar _ now allButLast: 11].\\n\\t\\t(now endsWith: 'MultiplyBy:') ifTrue:\\n\\t\\t\\t[\\\"a xMultiplyBy: 3 a setX: (a getX *3).\\\"\\n\\t\\t\\twant _ 4+delta. instVar _ now allButLast: 11].\\n\\t\\twant ifNil: [^ false].\\n\\t\\tinstVar _ instVar asLowercase.\\n\\t\\twant _ #(1 2 3 4) atWrap: want.\\n\\t\\twant = 1 ifTrue:\\n\\t\\t\\t[\\\"setter method is present\\\"\\n\\t\\t\\tself setSelector: ('set', instVar capitalized, ':') in: st. ^ true].\\n\\t\\twant = 2 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'IncreaseBy:' in: st. ^ true].\\n\\t\\twant = 3 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'DecreaseBy:' in: st. ^ true].\\n\\t\\twant = 4 ifTrue:\\n\\t\\t\\t[\\\"notUnderstood will create the method if needed\\\"\\n\\t\\t\\tself setSelector: instVar, 'MultiplyBy:' in: st. ^ true].\\n\\t\\t].\\n\\t^ false\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 5/4/2001 11:49'!\\nupDownDone\\n\\n\\t(self nodeClassIs: LiteralNode) ifTrue:\\n\\t\\t[self acceptSilently. \\\"Final compilation logs source\\\"\\n\\t\\tself removeProperty: #timeOfLastTick;\\n\\t\\t\\tremoveProperty: #currentDelay].\\n! !\\n\\n!SyntaxMorph methodsFor: 'pop ups' stamp: 'di 5/4/2001 12:26'!\\nupDownMore: delta event: evt arrow: arrowMorph\\n\\n\\t| st delay1 delay2 now timeOfLastTick currentDelay |\\n\\t(self nodeClassIs: LiteralNode) ifFalse: [^ self].\\n\\tst _ submorphs detect: [:mm | mm isKindOf: StringMorph] ifNone: [^ self].\\n\\tdelay1 _ 300. \\\"ms\\\"\\n\\tdelay2 _ 50. \\\"ms\\\"\\n\\tnow _ Time millisecondClockValue.\\n\\ttimeOfLastTick _ (self valueOfProperty: #timeOfLastTick) ifNil: [now - delay1].\\n\\tcurrentDelay _ (self valueOfProperty: #currentDelay) ifNil: [delay1].\\n\\tnow >= (timeOfLastTick + currentDelay) ifTrue:\\n\\t\\t[self setProperty: #timeOfLastTick toValue: now.\\n\\t\\t\\\"decrease the delay\\\"\\n\\t\\tself setProperty: #currentDelay toValue: (currentDelay*8//10 max: delay2).\\n\\t\\tst contents: (self decompile asNumber + delta) printString.\\n\\t\\t^ self acceptUnlogged].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:33'!\\ngetHeader: strm\\n\\t| se |\\n\\t\\\"We are in an EToy scriptor and the method header line has been removed. Try to recover the method name. Fail if method has args (deal with this later).\\\"\\n\\n\\t(se _ self ownerThatIsA: ScriptEditorMorph) ifNotNil: [\\n\\t\\tse scriptName numArgs > 0 ifTrue: [^ false].\\t\\\"abort\\\"\\n\\t\\tstrm nextPutAll: se scriptName].\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'dgd 2/22/2003 13:40'!\\nownerPrecedence\\n\\t\\\"Return the selector precedence of my owner. 1 for unary (asInteger), 2 for binary arithmetic (+), and 3 for keyword selectors (from:to:). Subtract 0.5 if self is an arg, not the receiver (the case of a + (b + c))\\\"\\n\\n\\t| oo below sel pp |\\n\\too := owner.\\n\\tbelow := self.\\n\\t\\n\\t[oo isSyntaxMorph ifFalse: [^10].\\t\\\"I do not need parens\\\"\\n\\too parseNode isNil] \\n\\t\\t\\twhileTrue: \\n\\t\\t\\t\\t[below := oo.\\n\\t\\t\\t\\too := oo owner].\\n\\t(sel := oo selector) ifNil: [^10].\\n\\t(pp := sel precedence) = 3 ifTrue: [^2.5].\\t\\\"keyword messages need parens\\\"\\n\\t^oo receiverNode == below ifTrue: [pp] ifFalse: [pp - 0.5]! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 02:11'!\\nprintAssignmentNodeOn: strm indent: level\\n\\t\\\"sometimes an assignment is in parens\\\"\\n\\t| parens above |\\n\\n\\tparens _ submorphs size >= 3.\\n\\tparens ifTrue: [\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ above <= 3].\\t\\\"assignment is a noun inside a message\\\"\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tstrm ensureNoSpace. \\t\\\"_ will have a leading space\\\"\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 12:19'!\\nprintBlockArgsNodeOn: strm indent: level\\n\\n\\t| argString |\\n\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\t(argString _ sub decompile) isEmpty ifFalse: [\\n\\t\\t\\t\\tstrm \\n\\t\\t\\t\\t\\tnextPut: $:;\\n\\t\\t\\t\\t\\tnextPutAll: argString;\\n\\t\\t\\t\\t\\tspace\\n\\t\\t\\t].\\n\\t\\t] \\n\\t\\tifString: [ :sub |\\n\\t\\t\\t\\\"self printSimpleStringMorph: sub on: strm\\t<<<< do we need this??\\\"\\n\\t\\t].\\n\\tstrm nextPut: $|; crtab: level.\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:17'!\\nprintBlockNodeOn: strm indent: level\\n\\n\\t| lev inASyntaxButNotOutermost subNodeClass |\\n\\n\\tlev _ level.\\n\\tinASyntaxButNotOutermost _ owner isSyntaxMorph and: [ owner isMethodNode not].\\n\\tinASyntaxButNotOutermost ifTrue: [strm nextPut: $[. lev _ lev+1].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: lev.\\n\\t\\t\\tsubNodeClass _ sub parseNode class.\\n\\t\\t\\t(#(BlockArgsNode ReturnNode CommentNode) includes: subNodeClass name) ifFalse: [\\n\\t\\t\\t\\tstrm ensureNoSpace; nextPut: $.].\\n\\t\\t\\tsubNodeClass == BlockArgsNode\\n\\t\\t\\t\\tifTrue: [strm space]\\n\\t\\t\\t\\tifFalse: [strm crtab: lev].\\n\\t\\t] \\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tinASyntaxButNotOutermost ifTrue: [strm nextPut: $] ].\\n\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:19'!\\nprintCascadeNodeOn: strm indent: level\\n\\n\\t| parens cnt me above |\\n\\n\\tparens _ parseNode receiver notNil.\\n\\tparens ifTrue: [me _ self selector precedence.\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ me > above].\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tcnt _ 0.\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tcnt _ cnt + 1.\\n\\t\\t\\t\\\"maybe we want to test sub isCascadePart for the following???\\\"\\n\\t\\t\\tcnt > 2 ifTrue: [strm nextPutAll: '; '].\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 01:17'!\\nprintMessageNodeOn: strm indent: level\\n\\n\\t| parens me above |\\n\\n\\tparens _ parseNode receiver notNil.\\n\\tparens ifTrue: [me _ self selector precedence.\\n\\t\\tabove _ self ownerPrecedence.\\t\\\"high if not in an expression\\\"\\n\\t\\tparens _ me > above].\\n\\tparens ifTrue: [strm nextPut: $( ].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tparens ifTrue: [strm ensureNoSpace; nextPut: $) ].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/23/2001 02:12'!\\nprintMethodNodeOn: strm indent: level\\n\\n\\t(self findA: SelectorNode) ifNil: [\\n\\t\\t(self getHeader: strm) ifFalse: [^ self].\\t\\t\\\"might fail\\\"\\n\\t\\tstrm crtab: level].\\n\\tself \\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm crtab: level.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t]. \\n\\tstrm last == $. ifTrue: [strm skip: -1]. \\\"ugh!! erase duplicate final period\\\"! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 12:08'!\\nprintMethodTempsNodeOn: strm indent: level\\n\\n\\tstrm nextPut: $|; space.\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm space.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n\\tstrm nextPut: $|; crtab: level.\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 10/22/2000 20:43'!\\nprintOn: strm\\n\\n\\tsuper printOn: strm.\\n\\tstrm space; nextPutAll: parseNode class name.! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'tk 9/14/2001 13:52'!\\nprintOn: strm indent: level\\n\\n\\t| nodeClass |\\n\\n\\t(self hasProperty: #ignoreNodeWhenPrinting) ifFalse: [\\n\\t\\tnodeClass _ parseNode class.\\n\\t\\tnodeClass == VariableNode ifTrue: [^self printVariableNodeOn: strm indent: level].\\n\\t\\tnodeClass == LiteralVariableNode ifTrue: [^self printVariableNodeOn: strm indent: level].\\n\\t\\tnodeClass == MessageNode ifTrue: [^self printMessageNodeOn: strm indent: level].\\n\\t\\tnodeClass == BlockNode ifTrue: [^self printBlockNodeOn: strm indent: level].\\n\\t\\tnodeClass == BlockArgsNode ifTrue: [^self printBlockArgsNodeOn: strm indent: level].\\n\\t\\tnodeClass == MethodNode ifTrue: [^self printMethodNodeOn: strm indent: level].\\n\\t\\tnodeClass == MethodTempsNode ifTrue: [^self printMethodTempsNodeOn: strm indent: level].\\n\\t\\tnodeClass == CascadeNode ifTrue: [^self printCascadeNodeOn: strm indent: level].\\n\\t\\tnodeClass == AssignmentNode ifTrue: [^self printAssignmentNodeOn: strm indent: level].\\n\\t].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 2/16/2001 18:16'!\\nprintSimpleStringMorph: aMorph on: strm\\n\\n\\t| trialContents |\\n\\n\\t(aMorph hasProperty: #wordyVariantOfSelf) ifTrue: [\\n\\t\\tstrm nextPutAll: 'self '.\\n\\t\\tstrm nextPutAll: ((self translateToWordySelfVariant: aMorph contents) ifNil: [^self]).\\n\\t\\t^self\\n\\t].\\n\\t(aMorph hasProperty: #noiseWord) ifFalse: [\\n\\t\\ttrialContents _ self cleanUpString: aMorph.\\n\\t\\tstrm nextPutAll: trialContents\\n\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 2/13/2001 23:10'!\\nprintStatementsOn: aStream indent: indent\\n\\n\\t\\\"seemed to be necessary to see top node in explorer\\\"\\n\\n\\t^parseNode printStatementsOn: aStream indent: indent! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'ar 8/16/2001 13:29'!\\nprintVariableNodeOn: strm indent: level\\n\\n\\t\\\"nil out any old association\\\"\\n\\tparseNode key isVariableBinding ifTrue: [\\n\\t\\tparseNode \\n\\t\\t\\tname: parseNode name \\n\\t\\t\\tkey: nil \\n\\t\\t\\tcode: parseNode code\\n\\t].\\n\\tself\\n\\t\\tsubmorphsDoIfSyntax: [ :sub |\\n\\t\\t\\tsub printOn: strm indent: level.\\n\\t\\t\\tstrm ensureASpace.\\n\\t\\t]\\n\\t\\tifString: [ :sub |\\n\\t\\t\\tself printSimpleStringMorph: sub on: strm\\n\\t\\t].\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'di 11/13/2000 07:43'!\\nstructure\\n\\t\\\"Print my structure from inner to outer.\\\"\\n\\t^ String streamContents: [:s |\\n\\t\\tself withAllOwnersDo:\\n\\t\\t\\t[:m | m isSyntaxMorph ifTrue:\\n\\t\\t\\t\\t[s cr; print: m parseNode class.\\n\\t\\t\\t\\t((m nodeClassIs: MessageNode) or: [m nodeClassIs: TileMessageNode]) ifTrue:\\n\\t\\t\\t\\t\\t[s space; nextPutAll: m parseNode selector key]]]]! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'RAA 3/4/2001 11:55'!\\nsubmorphsDoIfSyntax: block1 ifString: block2 \\n\\n\\t^self submorphsDoIfSyntax: block1 ifString: block2 otherwise: [ :sub | ]\\n! !\\n\\n!SyntaxMorph methodsFor: 'printing' stamp: 'gm 2/22/2003 12:34'!\\nsubmorphsDoIfSyntax: block1 ifString: block2 otherwise: block3 \\n\\tsubmorphs do: \\n\\t\\t\\t[:sub | \\n\\t\\t\\tsub isSyntaxMorph \\n\\t\\t\\t\\tifTrue: [block1 value: sub]\\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[(sub isKindOf: StringMorph) \\n\\t\\t\\t\\t\\t\\tifTrue: [block2 value: sub]\\n\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t[(sub isTextMorph) \\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [block2 value: sub]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [block3 value: sub]]]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'scripting' stamp: 'tk 9/26/2001 06:01'!\\ntearOffTile\\n\\t\\\"For a SyntaxMorph, this means give a copy of me\\\"\\n\\n\\t| dup |\\n\\tdup _ self duplicate.\\n\\tActiveHand attachMorph: dup.\\n\\tPreferences tileTranslucentDrag\\n\\t\\tifTrue: [^ dup lookTranslucent]\\n\\t\\tifFalse: [^ dup align: dup topLeft with: ActiveHand position + self cursorBaseOffset]\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'di 11/17/2000 08:10'!\\ncurrentSelectionDo: blockForSelection\\n\\t| rootTile |\\n\\t(rootTile _ self rootTile) isMethodNode ifFalse:\\n\\t\\t [^ blockForSelection value: nil value: nil value: nil].\\n\\trootTile valueOfProperty: #selectionSpec ifPresentDo:\\n\\t\\t[:selectionSpec | ^ blockForSelection\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec first\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec second\\n\\t\\t\\t\\t\\t\\t\\tvalue: selectionSpec third].\\n\\t^ blockForSelection value: nil value: nil value: nil! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'RAA 2/14/2001 11:33'!\\ndeselect\\n\\tself allMorphsDo:\\n\\t\\t[:m | m isSyntaxMorph ifTrue: [m setDeselectedColor]].\\n\\n\\t\\\"Note following is wasteful because we do a deselect before each select, and it is often the same morph.\\\"\\n\\tself deletePopup! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 1/17/2001 15:07'!\\nisSelectable\\n\\t| ss |\\n\\t\\\"Spacer morphs enclose other morphs with the same parseNode\\\"\\n\\tself submorphs size > 1 ifTrue: [\\n\\t\\tss _ self submorphs second.\\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode == parseNode ifTrue: [\\n\\t\\t\\t\\t^ self submorphs first class ~~ Morph]]].\\n\\t\\t\\n\\\"\\t(self nodeClassIs: SelectorNode) ifTrue: [^ false].\\n\\t(self nodeClassIs: KeyWordNode) ifTrue: [^ false].\\n\\\"\\n\\tself isMethodNode ifTrue: [^ false].\\n\\tparseNode ifNil: [^ false].\\n\\t^ true! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/31/2001 17:18'!\\nscaleColorByUserPref: aColor\\n\\t\\n\\t| myRoot underLyingColor |\\n\\n\\tmyRoot _ self rootTile.\\n\\tunderLyingColor _ myRoot ifNil: [Color transparent] ifNotNil: [myRoot color].\\n\\t[underLyingColor isTransparent and: [(myRoot _ myRoot owner) notNil]] whileTrue: [\\n\\t\\tunderLyingColor _ myRoot color.\\n\\t].\\n\\t\\n\\t\\\"rude hack to get the desired effect before we have an owner\\\"\\n\\n\\tunderLyingColor isTransparent ifTrue: [underLyingColor _ Color r: 0.903 g: 1.0 b: 0.903].\\n\\t^aColor mixed: (ContrastFactor ifNil: [0.3]) with: underLyingColor\\n\\n\\\"Would like to be able to make MethodNode and outer Block be transparent. This method does not allow that. Consider (^ myRoot color) inside the whileTrue. Consider setting underLyingColor to (myRoot valueOfProperty: #deselectedBorderColor ifAbsent: [myRoot color]) in second line.\\\"! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/23/2001 18:31'!\\nselect\\n\\tself deselect.\\n\\t\\\"Outer block is not colored and has no popup\\\"\\n\\t(owner isSyntaxMorph and: [owner nodeClassIs: MethodNode]) \\n\\t\\tifTrue: [self setDeselectedColor \\\"normal\\\"]\\n\\t\\tifFalse: [self color: Color lightBrown].\\n\\tself borderColor: #raised.\\n\\tself offerPopUp.! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'tk 7/19/2001 17:52'!\\nsetDeselectedColor\\n\\t\\\"The normal color of the tile, stored with the tile\\\"\\n\\t| deselectedColor deselectedBorderColor |\\n\\n\\tdeselectedColor _ self valueOfProperty: #deselectedColor ifAbsent: [nil].\\n\\tdeselectedBorderColor _ self valueOfProperty: #deselectedBorderColor ifAbsent: [nil].\\n\\tdeselectedColor ifNotNil: [\\n\\t\\tdeselectedColor _ self scaleColorByUserPref: deselectedColor].\\n\\tdeselectedBorderColor ifNotNil: [\\n\\t\\tdeselectedBorderColor _ self scaleColorByUserPref: deselectedBorderColor].\\n\\tself \\n\\t\\tcolor: (deselectedColor ifNil: [Color transparent]);\\n\\t\\tborderColor: (deselectedBorderColor ifNil: [Color transparent])! !\\n\\n!SyntaxMorph methodsFor: 'selection' stamp: 'dgd 2/22/2003 13:41'!\\nsetSelection: newSpec \\n\\t\\\"A selectionSpec is {Inner morph. Where clicked. Outer morph}.\\n\\tFirst mouseDown starts a selection (with outerMorph isNil).\\n\\tDragging more than 4 pixels means to grab a copy of the current outer selection.\\n\\t\\tThe current selection is the outerMorph, or the inner if it is nil.\\n\\tEach mouseUp extends the selection to the next outer morph that is selectable.\\n\\t\\tExcept if this is the first click.\\\"\\n\\n\\t| rootTile |\\n\\t(rootTile := self rootTile) valueOfProperty: #selectionSpec\\n\\t\\tifPresentDo: [:oldSpec | oldSpec third ifNotNilDo: [:m | m deselect]].\\n\\t(newSpec isNil or: [newSpec third isNil and: [self isMethodNode]]) \\n\\t\\tifTrue: \\n\\t\\t\\t[self deselect.\\n\\t\\t\\t^rootTile removeProperty: #selectionSpec].\\n\\n\\t\\\"Select outer morph of the new selection\\\"\\n\\tnewSpec third isNil \\n\\t\\tifTrue: [self select\\t\\\"first click down\\\"]\\n\\t\\tifFalse: [newSpec third select\\t\\\"subsequent clicks\\\"].\\n\\trootTile setProperty: #selectionSpec toValue: newSpec! !\\n\\n\\n!SyntaxMorph methodsFor: 'stepping and presenter' stamp: 'tk 7/25/2001 11:26'!\\nstep\\n\\tsuper step.\\n\\tself isBlockNode ifTrue: [self trackDropZones].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'submorphs-accessing' stamp: 'tk 1/13/2001 20:41'!\\nfindA: aClass\\n\\t| ans |\\n\\t\\\"Allow finding on the class of the parseNode\\\"\\n\\n\\t(ans _ super findA: aClass) ifNotNil: [^ ans].\\n\\tsubmorphs do: [:ss | \\n\\t\\tss isSyntaxMorph ifTrue: [\\n\\t\\t\\tss parseNode class == aClass ifTrue: [^ ss]]].\\n\\t^ nil! !\\n\\n\\n!SyntaxMorph methodsFor: 'testing' stamp: 'di 11/3/2000 08:03'!\\nstepTime\\n\\n\\t^ 50! !\\n\\n!SyntaxMorph methodsFor: 'testing' stamp: 'di 1/30/2001 11:22'!\\nwantsSteps\\n\\t\\\"Only step this morph if we explicitly send startStepping\\\"\\n\\n\\t^ false! !\\n\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'di 11/6/2000 10:47'!\\ntest\\n\\t3 > 4 ifTrue: [].\\n\\t^ self! !\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'gm 2/22/2003 12:35'!\\ntestForNode: targetNode andDo: aBlock \\n\\ttargetNode == parseNode ifTrue: [aBlock value: self].\\n\\tself submorphsDo: \\n\\t\\t\\t[:each | \\n\\t\\t\\t(each isSyntaxMorph) \\n\\t\\t\\t\\tifTrue: [each testForNode: targetNode andDo: aBlock]]! !\\n\\n!SyntaxMorph methodsFor: 'tests' stamp: 'di 11/14/2000 14:54'!\\ntoDo\\n\\\"\\nBiggies...\\n[ ]\\tIntegrate with EToy scriptors\\n\\treleaseCachedState can discard all morphic structure.\\n\\n[ ]\\tOptions:\\n\\tShow / hide syntax markers (like [], (), ., :, ;, etc)\\n\\tNo color / color-in-focus / full color\\n\\tTiles / textiles / text\\n\\n[ ]\\tParsedTextMorph -- looks like text but has all same substructure\\n\\n[ ]\\tIntroduce notion of an UnParsedNode -- maybe a flag in ParseNode\\n\\tText -> UnParsed -> Parsed -> CodeGen\\n\\n[ ]\\tNeed DnD evaluator, or some sort of '!!' button on any entity (halo?)\\n\\tAlso inspector / browser\\n\\n[ ]\\tAll the type help we can get\\n\\nDetails ...\\n[ ]\\tOpen up the parse of BraceNodes\\n\\n[ ]\\tVerify that all pastes are OK\\n\\n[ ]\\tColors not yet right for colored version.\\n\\n[ ]\\tStart work on show / hide of syntax markers -- (), [], etc.\\n\\n[ ]\\tStart work on textiles (grabable entites in 'normal' text)\\n\\n[ ]\\tNeed autoscroll during drag for drop\\n\\n[ ]\\tUse, eg, shift-drag to move, del to delete\\n\\n[ ]\\tWhat about invalid drops -- stick on cursor?\\n\\nSystem...\\n[ ]\\tOnly keep history 7 deep; option to clear on quit\\n\\tclear command above spaceLeft\\n\\n[ ]\\tCompute each page of prefs viewer on demand instead of as now.\\n\\n[ ]\\tOffer a search command that will gather up all preferences that match a given string (name or help string)\\n\\nPreferences enable: #noTileColor.\\nPreferences disable: #noTileColor.\\nSmalltalk browseAllSelect: [:cm | cm size > 600]\\nSyntaxMorph testAll\\n\\\"! !\\n\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/23/2001 23:40'!\\nargTypeFor: aSelector\\n\\t\\\"Answer the type of the argument of this selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\taSelector numArgs = 0 \\n\\t\\tifTrue: [self inform: aSelector, ' does not take an argument'. ^ #error \\\"7\\\"].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface typeForArgumentNumber: 1! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/15/2001 14:25'!\\nokToBeReplacedBy: aSyntaxMorph\\n\\t\\\"Return true if it is OK to replace me with aSyntaxMorph. Enforce the type rules in the old EToy green tiles.\\\"\\n\\n\\t| itsType myType |\\n\\t(Preferences eToyFriendly or: [Preferences typeCheckingInTileScripting])\\n\\t\\tifFalse: [^ true].\\t\\\"not checking unless one of those prefs is true\\\"\\n\\t(parseNode class == BlockNode and: [aSyntaxMorph parseNode class == BlockNode]) \\n\\t\\tifTrue: [^ true].\\n\\t(parseNode class == ReturnNode and: [aSyntaxMorph parseNode class == ReturnNode]) \\n\\t\\tifTrue: [^ true].\\n\\tparseNode class == KeyWordNode ifTrue: [^ false].\\n\\taSyntaxMorph parseNode class == KeyWordNode ifTrue: [^ false].\\n\\tparseNode class == SelectorNode ifTrue: [^ false].\\n\\taSyntaxMorph parseNode class == SelectorNode ifTrue: [^ false].\\n\\towner isSyntaxMorph ifFalse: [^ true].\\t\\\"only within a script\\\"\\n\\t\\t\\\"Transcript show: aSyntaxMorph resultType printString, ' dropped on ', \\n\\t\\t\\tself receiverOrArgType printString; cr.\\n\\t\\t\\\"\\n\\t(itsType _ aSyntaxMorph resultType) == #unknown ifTrue: [^ true].\\n\\t(myType _ self receiverOrArgType) == #unknown ifTrue: [^ true].\\n\\t\\t\\\"my type in enclosing message\\\"\\n\\t^ myType = itsType! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'tk 2/9/2001 15:56'!\\nreceiverOrArgType\\n\\t| ty |\\n\\t\\\"Return my type in my role as a receiver or as an argument. Ask my enclosing message first, then ask myself. (If owner accepts any #object, and I am a #point, do return #object.)\\\"\\n\\n\\t^ (ty _ self receiverOrArgTypeAbove) == #unknown\\n\\t\\tifTrue: [self resultType]\\n\\t\\tifFalse: [ty]! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'dgd 2/22/2003 18:48'!\\nreceiverOrArgTypeAbove\\n\\t\\\"Return the type for me according to the message that encloses me.\\\"\\n\\n\\t| enclosing sub list |\\n\\t(self nodeClassIs: BlockNode) ifTrue: [^#command].\\n\\tenclosing := owner.\\n\\tsub := self.\\n\\t\\n\\t[enclosing isSyntaxMorph ifFalse: [^#unknown].\\n\\t(enclosing nodeClassIs: MessageNode) \\n\\t\\tifTrue: \\n\\t\\t\\t[list := enclosing submorphs \\n\\t\\t\\t\\t\\t\\tselect: [:ss | ss isSyntaxMorph and: [ss parseNode notNil]].\\n\\t\\t\\tlist size = 1 \\n\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t[^(list indexOf: sub) = 1 \\n\\t\\t\\t\\t\\t\\tifTrue: [enclosing receiverTypeFor: enclosing selector]\\n\\t\\t\\t\\t\\t\\tifFalse: [enclosing argTypeFor: enclosing selector]]].\\n\\t(enclosing nodeClassIs: BlockNode) ifTrue: [^#command].\\n\\tsub := enclosing.\\n\\tenclosing := enclosing owner.\\n\\ttrue] \\n\\t\\t\\twhileTrue! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/27/2001 09:11'!\\nreceiverTypeFor: aSelector\\n\\t\\\"Answer the type of the receiver of this selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\n\\taSelector ifNil: [^ #unknown].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface receiverType! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'yo 7/22/2005 16:43'!\\nresultType\\n\\t\\\"Look up my result type. If I am a constant, use that class. If I am a message, look up the selector.\\\"\\n\\n\\t| list value soundChoices |\\n\\tparseNode class == BlockNode ifTrue: [^#blockContext].\\n\\tparseNode class == AssignmentNode ifTrue: [^#command].\\n\\tparseNode class == ReturnNode ifTrue: [^#command].\\t\\\"Need more restriction than this\\\"\\n\\tlist := submorphs \\n\\t\\t\\t\\tselect: [:ss | ss isSyntaxMorph and: [ss parseNode notNil]].\\n\\tlist size > 1 ifTrue: [^self resultTypeFor: self selector].\\n\\tlist size = 1 \\n\\t\\tifTrue: \\n\\t\\t\\t[\\\"test for levels that are just for spacing in layout\\\"\\n\\n\\t\\t\\t(list first isSyntaxMorph and: [list first nodeClassIs: MessageNode]) \\n\\t\\t\\t\\tifTrue: [^list first resultType]].\\t\\\"go down one level\\\"\\n\\tvalue := self try.\\n\\tvalue class == Error ifTrue: [^#unknown].\\n\\t(value isNumber) ifTrue: [^#Number].\\n\\t(value isKindOf: Boolean) ifTrue: [^#Boolean].\\n\\t(value isForm) ifTrue: [^#Graphic].\\n\\t(value isPlayerLike and: [value costume renderedMorph isMemberOf: KedamaPatchMorph]) ifTrue: [^#Patch].\\n\\tvalue isString\\n\\t\\tifTrue: \\n\\t\\t\\t[soundChoices := #('silence').\\t\\\"default, if no SampledSound class\\\"\\n\\t\\t\\tSmalltalk at: #SampledSound\\n\\t\\t\\t\\tifPresent: [:sampledSound | soundChoices := sampledSound soundNames].\\n\\t\\t\\t(soundChoices includes: value) ifTrue: [^#Sound]].\\n\\t(value isPlayerLike) ifTrue: [^#Player].\\n\\t^value class name asLowercase\\t\\\"asSymbol (not needed)\\\"! !\\n\\n!SyntaxMorph methodsFor: 'type checking' stamp: 'sw 2/24/2001 12:13'!\\nresultTypeFor: aSelector\\n\\t\\\"Answer the result type of selector. Return #unknown if not found.\\\"\\n\\n\\t| itsInterface |\\n\\taSelector ifNil: [self inform: 'Please tell Ted how you caused this'.\\n\\t\\t^ #abs \\\"a bogus type\\\"].\\n\\titsInterface _ self currentVocabulary methodInterfaceAt: aSelector ifAbsent:\\n\\t\\t[^ #unknown].\\n\\t^ itsInterface resultType! !\\n\\n\\n!SyntaxMorph methodsFor: 'updating' stamp: 'di 11/13/2000 20:30'!\\nupdate: aSymbol\\n\\n\\t| bingo saveOwner newMorph db |\\n\\n\\t(db _ self debugger) ifNil: [^super update: aSymbol].\\n\\taSymbol == #contents ifTrue: [\\n\\t\\tsaveOwner _ owner.\\n\\t\\tdb removeDependent: self.\\n\\t\\tmarkerMorph ifNotNil: [markerMorph delete. markerMorph _ nil].\\n\\t\\tnewMorph _ db createSyntaxMorph.\\n\\t\\tself delete.\\n\\t\\tsaveOwner addMorph: newMorph.\\n\\t\\tsaveOwner owner setScrollDeltas.\\n\\t\\tnewMorph update: #contentsSelection.\\n\\t].\\n\\taSymbol == #contentsSelection ifTrue: [\\n\\t\\tmarkerMorph ifNil: [\\n\\t\\t\\tmarkerMorph _ RectangleMorph new.\\n\\t\\t\\tmarkerMorph\\n\\t\\t\\t\\tcolor: Color transparent;\\n\\t\\t\\t\\tborderWidth: 2;\\n\\t\\t\\t\\tborderColor: Color red;\\n\\t\\t\\t\\tlock.\\n\\t\\t\\towner addMorphFront: markerMorph.\\n\\t\\t].\\n\\t\\tbingo _ parseNode rawSourceRanges keyAtValue: db pcRange ifAbsent: [nil].\\n\\t\\tself testForNode: bingo andDo: [ :foundMorph | \\n\\t\\t\\tmarkerMorph\\n\\t\\t\\t\\tposition: foundMorph position;\\n\\t\\t\\t\\textent: foundMorph extent.\\n\\t\\t\\towner owner scrollIntoView: foundMorph bounds extra: 0.5.\\n\\t\\t\\t^self\\n\\t\\t].\\n\\t].\\n\\tsuper update: aSymbol! !\\n\\n\\n!SyntaxMorph methodsFor: 'viewer' stamp: 'tk 11/5/2001 08:32'!\\nexternalName\\n\\n\\t^ self knownName ifNil: [\\n\\t\\tparseNode ifNil: ['Syntax -- (extra layer)']\\n\\t\\t\\t\\tifNotNil: [self parseNode class printString]]! !\\n\\n\\n!SyntaxMorph methodsFor: 'visual properties' stamp: 'tk 7/31/2001 16:53'!\\nfillStyle: aFillStyle\\n\\n\\taFillStyle isColor \\n\\t\\tifTrue: [self color: aFillStyle]\\t\\\"so we will process it\\\"\\n\\t\\tifFalse: [super fillStyle: aFillStyle].\\n! !\\n\\n\\n!SyntaxMorph methodsFor: 'vocabulary' stamp: 'gm 2/22/2003 12:31'!\\nlimitClassToUseWith: aValue vocabulary: aVocabulary \\n\\t\\\"Answer the most generic whose method should be shown in a selector pop-up in the receiver that is put up on behalf of aValue\\\"\\n\\n\\t(aValue isNumber) ifTrue: [^Number].\\n\\t\\\"Ted: This hook allows you to intervene as suits your purposes here if you don't like the defaults.\\\"\\n\\t^aValue defaultLimitClassForVocabulary: aVocabulary! !\\n\\n!SyntaxMorph methodsFor: 'vocabulary' stamp: 'gm 2/22/2003 12:48'!\\nvocabularyToUseWith: aValue \\n\\t\\\"Answer a vocabulary to use with the given value\\\"\\n\\n\\t(aValue isNumber) ifTrue: [^Vocabulary numberVocabulary].\\n\\t(aValue isKindOf: Time) ifTrue: [^Vocabulary vocabularyForClass: Time].\\n\\t(aValue isString) ifTrue: [^Vocabulary vocabularyForClass: String].\\n\\taValue class isUniClass ifTrue: [^Vocabulary eToyVocabulary].\\n\\t^self currentVocabulary! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSyntaxMorph class\\n\\tinstanceVariableNames: ''!\\n\\n!SyntaxMorph class methodsFor: 'accessing' stamp: 'tk 9/18/2001 16:10'!\\nsourceCodeTemplate\\n\\t\\\"Return the default tile method template\\\"\\n\\n\\t^ 'anEmpty: input1 method: input2\\n\\t\\\"Edit the name above and the code below to make your own method\\\"\\n\\t3 + 4.\\n\\t\\\"Drag tiles in here. Use the ''tiles'' and ''vars'' menus to get new tiles\\\"\\n\\t^ ''this is a statement'' sort' \\n! !\\n\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 22:59'!\\ncolumn: aColor on: aParseNode\\n\\n\\t| c color |\\n\\tcolor _ self translateColor: aColor.\\n\\t(c _ self newColumn)\\n\\t\\tparseNode: aParseNode;\\n\\t\\tlayoutInset: c standardInset;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcolor: color;\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: c stdBorderColor;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\tcellPositioning: c standardCellPositioning.\\n\\t^c\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/16/2001 15:37'!\\nmethodNodeOuter: aNode\\n\\n\\t^(self column: #method on: aNode) methodNodeOuter: aNode\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 11/13/2000 21:12'!\\nnoTileColor\\n\\n\\t^ true! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 23:00'!\\nrow: aColor on: aParseNode\\n\\n\\t| r color |\\n\\tcolor _ self translateColor: aColor.\\n\\t(r _ self newRow)\\n\\t\\tparseNode: aParseNode;\\n\\t\\tlayoutInset: r standardInset;\\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcolor: color;\\n\\t\\tborderWidth: 1;\\n\\t\\tborderColor: r stdBorderColor;\\n\\t\\twrapCentering: #topLeft;\\n\\t\\tcellPositioning: r standardCellPositioning.\\n\\t^r! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 5/2/2001 09:59'!\\nsetSize: oldExtent andMakeResizable: outerMorph\\n\\t| tw |\\n\\t(tw _ outerMorph findA: TwoWayScrollPane) ifNil: [^self].\\n\\ttw hResizing: #spaceFill;\\n\\t\\tvResizing: #spaceFill;\\n\\t\\tcolor: Color transparent;\\n\\t\\tsetProperty: #hideUnneededScrollbars toValue: true.\\n\\touterMorph \\n\\t\\thResizing: #shrinkWrap;\\n\\t\\tvResizing: #shrinkWrap;\\n\\t\\tcellPositioning: #topLeft.\\n\\touterMorph fullBounds.\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 2/26/2001 22:56'!\\nstandardInset\\n\\n\\t^ self alansTest1 ifTrue: [1] ifFalse: [-1@-1]! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'RAA 8/24/1999 11:59'!\\ntest\\n\\n\\\"\\nSyntaxMorph test\\n\\\"\\n\\tself testClass: MessageNode andMethod: #asMorphicSyntaxIn:.\\n\\t\\\"self testClass: MethodNode andMethod: #asMorphicSyntaxIn:.\\\"\\n\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'dvf 8/23/2003 12:20'!\\ntestAll\\n\\n\\t| source tree total count systNav|\\n\\\"\\nSyntaxMorph testAll\\n\\\"\\n\\tsystNav _ self systemNavigation.\\n\\tcount _ total _ 0.\\n\\tsystNav allBehaviorsDo: [ :aClass | total _ total + 1].\\n'Testing all behaviors'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: total\\n\\tduring: [ :bar |\\n\\t\\tsystNav allBehaviorsDo: [ :aClass |\\n\\t\\t\\tbar value: (count _ count + 1).\\n\\t\\t\\taClass selectors do: [ :aSelector |\\n\\t\\t\\t\\tsource _ (aClass compiledMethodAt: aSelector) getSourceFromFile.\\n\\t\\t\\t\\ttree _ Compiler new \\n\\t\\t\\t\\t\\tparse: source \\n\\t\\t\\t\\t\\tin: aClass \\n\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\ttree asMorphicSyntaxUsing: SyntaxMorph.\\n\\t\\t\\t].\\n\\t\\t].\\t].\\n\\n\\n! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'dvf 8/23/2003 12:20'!\\ntestAllMethodsOver: methodSize \\n\\t\\\"MessageTally spyOn: [SyntaxMorph testAllMethodsOver: 600]\\\"\\n\\t\\\"Add up the total layout area for syntax morphs representing all \\n\\tmethods over the given size. This is a stress-test for SyntaxMorph \\n\\tlayout. A small value for the total area is also a figure of merit in the \\n\\tpresentation of Squeak source code in general.\\\"\\n\\t\\\"Results: \\n\\t#(69 600 180820874 103700) 11/4 \\n\\t70% build morphs, 12% get source, 9% layout, 8% parse, 1% roundoff \\n\\tFolded wide receivers, don't center keywords any more. \\n\\t#(68 600 160033784 127727) 11/9 \\n\\t76% build morphs, 8% get source, 8% layout, 8% parse, 0% roundoff \\n\\tFolded more messages, dropped extra vertical spacing in blocks. \\n\\t#(68 600 109141704 137308) 11/10 \\n\\t79% build morphs, 6% get source, 8% layout, 7% parse \\n\\tFolded more messages, dropped extra horizontal spacing. \\n\\t#(68 600 106912968 132171) 11/10 \\n\\t80% build morphs, ??% get source, 11% layout, 7% parse \\n\\tUnfolded keyword messages that will fit on one line. \\n\\t#(68 600 96497372 132153) 11/10 \\n\\t81% build morphs, ??% get source, 8% layout, 8% parse \\n\\tAfter alignment rewrite... \\n\\t#(74 600 101082316 244799) 11/12 \\n\\t76% build morphs, 4% get source, 15% layout, 5% parse \\n\\tAfter alignment rewrite... \\n\\t#(74 600 101250620 204972) 11/15 \\n\\t74% build morphs, 6% get source, 13% layout, 7% parse \\n\\t\\\"\\n\\t| tree source biggies morph stats time area |\\n\\tbiggies _ self systemNavigation \\n\\t\\t\\t\\tallMethodsSelect: [:cm | cm size > methodSize].\\n\\tstats _ OrderedCollection new.\\n\\t'Laying out all ' , biggies size printString , ' methods over ' , methodSize printString , ' bytes...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 1\\n\\t\\tto: biggies size\\n\\t\\tduring: [:bar | biggies\\n\\t\\t\\t\\twithIndexDo: [:methodRef :i | \\n\\t\\t\\t\\t\\tbar value: i.\\n\\t\\t\\t\\t\\tUtilities\\n\\t\\t\\t\\t\\t\\tsetClassAndSelectorFrom: methodRef\\n\\t\\t\\t\\t\\t\\tin: [:aClass :aSelector | \\n\\t\\t\\t\\t\\t\\t\\tsource _ (aClass compiledMethodAt: aSelector) getSourceFromFile.\\n\\t\\t\\t\\t\\t\\t\\ttime _ Time\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmillisecondsToRun: [tree _ Compiler new\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparse: source\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: aClass\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmorph _ tree asMorphicSyntaxUsing: SyntaxMorph.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tarea _ morph fullBounds area]].\\n\\t\\t\\t\\t\\tstats add: {methodRef. area. time}]].\\n\\t^ {{biggies size. methodSize. stats\\n\\t\\tdetectSum: [:a | a second]. stats\\n\\t\\tdetectSum: [:a | a third]}. (stats\\n\\t\\tasSortedCollection: [:x :y | x third >= y third]) asArray}! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'di 7/30/2001 16:29'!\\ntestClass: aClass andMethod: aSelector\\n\\t| tree |\\n\\ttree _ Compiler new \\n\\t\\tparse: (aClass sourceCodeAt: aSelector) \\n\\t\\tin: aClass \\n\\t\\tnotifying: nil.\\n\\t(tree asMorphicSyntaxUsing: SyntaxMorph)\\n\\t\\tparsedInClass: aClass;\\n\\t\\topenInWindow! !\\n\\n!SyntaxMorph class methodsFor: 'as yet unclassified' stamp: 'tk 7/19/2001 20:06'!\\ntranslateColor: aColorOrSymbol\\n\\n\\taColorOrSymbol isColor ifTrue: [^ aColorOrSymbol].\\n\\taColorOrSymbol == #comment ifTrue: [^ Color blue lighter].\\n\\taColorOrSymbol == #block ifTrue: [^ Color r: 0.903 g: 1.0 b: 0.903].\\n\\taColorOrSymbol == #method ifTrue: [^ Color r: 0.903 g: 1.0 b: 0.903].\\n\\taColorOrSymbol == #text ifTrue: [^ Color r: 0.9 g: 0.9 b: 0.9].\\n\\n\\tself noTileColor ifTrue: [^ Color r: 1.0 g: 0.839 b: 0.613].\\t\\\"override\\\"\\n\\n\\taColorOrSymbol == #assignment ifTrue: [^ Color paleGreen].\\n\\taColorOrSymbol == #keyword1 ifTrue: [^ Color paleBuff].\\t\\\"binary\\\"\\n\\taColorOrSymbol == #keyword2 ifTrue: [^ Color paleBuff lighter].\\t\\\"multipart\\\" \\n\\taColorOrSymbol == #cascade ifTrue: [^ Color paleYellow darker].\\t\\\"has receiver\\\"\\n\\taColorOrSymbol == #cascade2 ifTrue: [^ Color paleOrange].\\t\\\"one send in the cascade\\\"\\n\\taColorOrSymbol == #literal ifTrue: [^ Color paleMagenta].\\n\\taColorOrSymbol == #message ifTrue: [^ Color paleYellow].\\n\\taColorOrSymbol == #method ifTrue: [^ Color white].\\n\\taColorOrSymbol == #error ifTrue: [^ Color red].\\n\\taColorOrSymbol == #return ifTrue: [^ Color lightGray].\\n\\taColorOrSymbol == #variable ifTrue: [^ Color paleTan].\\n\\taColorOrSymbol == #brace ifTrue: [^ Color paleOrange].\\n\\taColorOrSymbol == #tempVariable ifTrue: [^ Color paleYellow mixed: 0.75 with: Color paleGreen\\n\\t\\t\\\"Color yellow lighter lighter\\\"].\\n\\taColorOrSymbol == #blockarg2 ifTrue: [\\n\\t\\t\\t^ Color paleYellow mixed: 0.75 with: Color paleGreen].\\t\\\"arg itself\\\"\\n\\taColorOrSymbol == #blockarg1 ifTrue: [^ Color paleRed].\\t\\\"container\\\"\\n\\t\\t\\\"yellow mixed: 0.5 with: Color white\\\"\\n\\n\\t^ Color tan\\t\\\"has to be something!!\\\"! !\\n\\n\\n!SyntaxMorph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-accessing' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nallSpecs\\n\\t\\\"Return all specs that the Viewer knows about. Cache them.\\\"\\n\\t\\\"SyntaxMorph allSpecs\\\"\\n\\n\\t^AllSpecs ifNil: [\\n\\t\\tAllSpecs := Dictionary new.\\n\\t\\t(EToyVocabulary morphClassesDeclaringViewerAdditions)\\n\\t\\t\\tdo: [:cls | cls allAdditionsToViewerCategories keysAndValuesDo: [ :k :v | \\n\\t\\t\\t\\t(AllSpecs at: k ifAbsentPut: [ OrderedCollection new ]) addAll: v ] ].\\n\\t\\tAllSpecs\\n\\t]! !\\n\\n!SyntaxMorph class methodsFor: '*flexibleVocabularies-flexiblevocabularies-accessing' stamp: 'stephaneducasse 2/4/2006 20:33'!\\nclearAllSpecs\\n\\t\\\"Clear the specs that the Viewer knows about.\\\"\\n\\t\\\"SyntaxMorph clearAllSpecs\\\"\\n\\n\\tAllSpecs := nil.! !\\nUpdatingStringMorph subclass: #SyntaxUpdatingStringMorph\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'EToys-Tile Scriptors'!\\n\\n!SyntaxUpdatingStringMorph methodsFor: 'drawing' stamp: 'tk 1/31/2002 09:53'!\\ndrawOn: aCanvas\\n\\n\\t| tempForm strm where chars wid spaceWidth putLigature topOfLigature sizeOfLigature colorOfLigature dots charZero canvas f |\\n\\n\\ttempForm _ Form extent: self extent depth: aCanvas depth.\\n\\tcanvas _ tempForm getCanvas.\\n\\tf _ self fontToUse.\\n\\tspaceWidth _ f widthOf: Character space.\\n\\tstrm _ ReadStream on: contents.\\n\\tcharZero _ Character value: 0.\\t\\\"a marker for center dot \\U00b7\\\"\\n\\twhere _ 0@0.\\n\\ttopOfLigature _ self height // 2 - 1.\\n\\tsizeOfLigature _ (spaceWidth-2)@(spaceWidth-2).\\n\\tcolorOfLigature _ Color black alpha: 0.45\\t\\\"veryLightGray\\\".\\n\\tdots _ OrderedCollection new.\\n\\tputLigature _ [\\n\\t\\tdots add: ((where x + 1) @ topOfLigature extent: sizeOfLigature).\\n\\t\\twhere _ where + (spaceWidth@0)].\\n\\tstrm peek = charZero ifTrue: [\\n\\t\\tstrm next.\\n\\t\\tputLigature value].\\n\\t[strm peek = charZero] whileTrue: [strm next].\\n\\t[strm atEnd] whileFalse: [\\n\\t\\tchars _ strm upTo: charZero.\\n\\t\\twid _ f widthOfString: chars.\\n\\t\\tcanvas drawString: chars at: where.\\n\\t\\twhere _ where + (wid@0).\\n\\t\\tstrm atEnd ifFalse: [putLigature value.\\n\\t\\t\\t[strm peek = charZero] whileTrue: [strm next]].\\n\\t].\\n\\taCanvas paintImage: tempForm at: self topLeft.\\n\\tdots do: [ :each |\\n\\t\\taCanvas \\n\\t\\t\\tfillRectangle: (each translateBy: self topLeft) \\n\\t\\t\\tfillStyle: colorOfLigature.\\n\\t].\\n! !\\nAppRegistry subclass: #SystemBrowser\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'Tools-Base'!\\n!SystemBrowser commentStamp: '<historical>' prior: 0!\\nThis is the AppRegistry class for class browsing!\\n\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSystemBrowser class\\n\\tinstanceVariableNames: ''!\\n\\n!SystemBrowser class methodsFor: 'class initialization' stamp: 'sd 11/20/2005 21:28'!\\ninitialize\\n\\t| pref |\\n\\tpref := Preferences preferenceAt: #browserShowsPackagePane.\\n\\tPreferences\\n\\t\\taddPreference: #browserShowsPackagePane\\n\\t\\tcategories: pref categoryList\\n\\t\\tdefault: pref defaultValue\\n\\t\\tballoonHelp: pref helpString\\n\\t\\tprojectLocal: pref localToProject\\n\\t\\tchangeInformee: self\\n\\t\\tchangeSelector: #packagePanePreferenceChanged\\n\\t\\t! !\\n\\n\\n!SystemBrowser class methodsFor: 'events' stamp: 'sd 11/20/2005 21:28'!\\npackagePanePreferenceChanged\\n\\t| theOtherOne |\\n\\tself registeredClasses size = 2\\n\\t\\tifTrue: [theOtherOne := (self registeredClasses copyWithout: PackagePaneBrowser) first]\\n\\t\\tifFalse: [theOtherOne := nil].\\n\\t(Preferences valueOfFlag: #browserShowsPackagePane ifAbsent: [false])\\n\\t\\tifTrue: [self default: PackagePaneBrowser]\\n\\t\\tifFalse: [self default: theOtherOne].\\n\\tSystemNavigation default browserClass: self default.! !\\n\\n\\n!SystemBrowser class methodsFor: 'initialize-release' stamp: 'sd 11/20/2005 21:28'!\\nunload\\n\\t| pref |\\n\\tpref := Preferences preferenceAt: #browserShowsPackagePane.\\n\\tPreferences\\n\\t\\taddPreference: #browserShowsPackagePane\\n\\t\\tcategories: pref categoryList\\n\\t\\tdefault: pref defaultValue\\n\\t\\tballoonHelp: pref helpString\\n\\t\\tprojectLocal: pref localToProject\\n\\t\\tchangeInformee: nil\\n\\t\\tchangeSelector: nil\\n\\t\\t! !\\n\\n\\n!SystemBrowser class methodsFor: 'instance creation' stamp: 'hpt 8/5/2004 20:27'!\\ndefaultOpenBrowser\\n\\t^self default openBrowser! !\\n\\n\\n!SystemBrowser class methodsFor: 'registration' stamp: 'hpt 9/30/2004 20:53'!\\naddRegistryMenuItemsTo: aMenu inAccountOf: aBrowser \\n\\t\\\"Add some useful options related Browser registry to the\\n\\tbrowsers windows menu\\\"\\n\\taMenu addLine;\\n\\t\\tadd: 'Register this Browser as default'\\n\\t\\ttarget: [self default: aBrowser class]\\n\\t\\taction: #value;\\n\\t\\tadd: 'Choose new default Browser'\\n\\t\\ttarget: self\\n\\t\\taction: #askForDefault! !\\nSystemChangeTestRoot subclass: #SystemChangeErrorHandling\\n\\tinstanceVariableNames: 'capturedEvents'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeErrorHandling commentStamp: 'rw 4/3/2006 17:21' prior: 0!\\nThis class tests the error handing of the notification mechanism to ensure that one client that receives a system change cannot lock up the complete system.\\\"!\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nhandleEventWithError: event\\n\\n\\tself error: 'Example of event handling code that throws an error.'! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 18:07'!\\nhandleEventWithHalt: event\\n\\n\\tself halt: 'Example of event handling code that contains a halt.'! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent1: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent2: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:57'!\\nstoreEvent3: anEvent\\n\\n\\tcapturedEvents add: anEvent! !\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Running' stamp: 'rw 4/3/2006 17:51'!\\nsetUp\\n\\n\\tsuper setUp.\\n\\tcapturedEvents := OrderedCollection new! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Running' stamp: 'rw 4/3/2006 17:56'!\\ntearDown\\n\\n\\tcapturedEvents := nil.\\n\\tsuper tearDown! !\\n\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestErrorOperation\\n\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent1:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent2:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #handleEventWithError:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: Error do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestHaltOperation\\n\\t\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent1:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent2:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #handleEventWithHalt:.\\n\\tnotifier notify: self ofAllSystemChangesUsing: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: Halt do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\n\\n!SystemChangeErrorHandling methodsFor: 'Testing' stamp: 'rw 4/5/2006 17:24'!\\ntestUnhandledEventOperation\\n\\n\\t| notifier wasCaptured |\\n\\tnotifier := self systemChangeNotifier.\\n\\twasCaptured := false.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent1:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent2:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #zork:.\\n\\tnotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #storeEvent3:.\\n\\t[notifier classAdded: self class inCategory: #FooCat] on: MessageNotUnderstood do: [:exc |\\n\\t\\twasCaptured := true.\\n\\t\\tself assert: (capturedEvents size = 3)].\\n\\tself assert: wasCaptured.! !\\nObject subclass: #SystemChangeNotifier\\n\\tinstanceVariableNames: 'eventSource silenceLevel'\\n\\tclassVariableNames: 'UniqueInstance'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Change Notification'!\\n\\n!SystemChangeNotifier methodsFor: 'initialize' stamp: 'NS 1/26/2004 20:41'!\\ninitialize\\n\\n\\teventSource := SystemEventManager new.\\n\\tsilenceLevel _ 0.! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/28/2004 11:29'!\\ndoSilently: aBlock\\n\\t\\\"Perform the block, and ensure that no system notification are broadcasted while doing so.\\\"\\n\\n\\t| result |\\n\\tsilenceLevel := silenceLevel + 1.\\n\\t[result := aBlock value] ensure: [silenceLevel > 0 ifTrue: [silenceLevel := silenceLevel - 1]].\\n\\t^ result.! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/26/2004 20:41'!\\nisBroadcasting\\n\\n\\t^ silenceLevel = 0! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/29/2003 17:01'!\\nnoMoreNotificationsFor: anObject\\n\\t\\\"Stop sending system notifications to an object.\\\"\\n\\n\\teventSource removeActionsWithReceiver: anObject! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/10/2003 12:00'!\\nnotify: anObject ofAllSystemChangesUsing: oneArgumentSelector \\n\\t\\\"Notifies an object of any system changes.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: self allSystemEvents\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfChange: changeKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified changeKind (#added, #removed, ...). Evaluate 'AbstractEvent allChangeKinds' to get the complete list.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (self systemEventsForChange: changeKind)\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfItem: itemKind change: changeKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified itemKind (#class, #category, ...) and changeKind (#added, #removed, ...). This is the finest granularity possible.\\n\\tEvaluate 'AbstractEvent allChangeKinds' to get the complete list of change kinds, and 'AbstractEvent allItemKinds to get all the possible item kinds supported.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (Bag with: (self systemEventsForItem: itemKind change: changeKind))\\n\\t\\tusing: oneArgumentSelector! !\\n\\n!SystemChangeNotifier methodsFor: 'public' stamp: 'bvs 7/20/2004 12:13'!\\nnotify: anObject ofSystemChangesOfItem: itemKind using: oneArgumentSelector \\n\\t\\\"Notifies an object of system changes of the specified itemKind (#class, #method, #protocol, ...). Evaluate 'AbstractEvent allItemKinds' to get the complete list.\\\"\\n\\n\\tself \\n\\t\\tnotify: anObject\\n\\t\\tofEvents: (self systemEventsForItem: itemKind)\\n\\t\\tusing: oneArgumentSelector! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:32'!\\nclassCategoryAdded: aClassCategoryName\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\t\\tclassCategory: aClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:35'!\\nclassCategoryRemoved: aClassCategoryName\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\t\\tclassCategory: aClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'ab 2/10/2005 16:44'!\\nclassCategoryRenamedFrom: anOldClassCategoryName to: aNewClassCategoryName\\n\\n\\tself trigger: (RenamedEvent\\n\\t\\t\\t\\t\\tclassCategoryRenamedFrom: anOldClassCategoryName \\n\\t\\t\\t\\t\\tto: aNewClassCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:12'!\\nclass: aClass recategorizedFrom: oldCategory to: newCategory \\n\\tself trigger: (RecategorizedEvent \\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\tcategory: newCategory\\n\\t\\t\\t\\toldCategory: oldCategory)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:11'!\\nclassAdded: aClass inCategory: aCategoryName \\n\\tself trigger: (AddedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/26/2004 09:37'!\\nclassCommented: aClass\\n\\t\\\"A class with the given name was commented in the system.\\\"\\n\\n\\tself trigger: (CommentedEvent class: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:11'!\\nclassCommented: aClass inCategory: aCategoryName \\n\\t\\\"A class with the given name was commented in the system.\\\"\\n\\n\\tself trigger: (CommentedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/20/2004 19:37'!\\nclassDefinitionChangedFrom: oldClass to: newClass\\n\\tself trigger: (ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/16/2004 15:10'!\\nclassRemoved: aClass fromCategory: aCategoryName \\n\\tself trigger: (RemovedEvent class: aClass category: aCategoryName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:19'!\\nclassRenamed: aClass from: oldClassName to: newClassName inCategory: aCategoryName \\n\\tself trigger: (RenamedEvent \\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\tcategory: aCategoryName\\n\\t\\t\\t\\toldName: oldClassName\\n\\t\\t\\t\\tnewName: newClassName)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:48'!\\nclassReorganized: aClass\\n\\tself trigger: (ReorganizedEvent class: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/19/2004 09:48'!\\nevaluated: textOrStream\\n\\t^ self evaluated: textOrStream context: nil.! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/19/2004 09:47'!\\nevaluated: expression context: aContext\\n\\tself trigger: (DoItEvent \\n\\t\\t\\t\\texpression: expression\\n\\t\\t\\t\\tcontext: aContext)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inClass: aClass \\n\\t\\\"A method with the given selector was added to aClass, but not put in a protocol.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\t\\\"A method with the given selector was added to aClass, but not put in a protocol.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inProtocol: aCategoryName class: aClass \\n\\t\\\"A method with the given selector was added to aClass in protocol aCategoryName.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod\\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: aCategoryName\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'!\\nmethodAdded: aMethod selector: aSymbol inProtocol: aCategoryName class: aClass requestor: requestor\\n\\t\\\"A method with the given selector was added to aClass in protocol aCategoryName.\\\"\\n\\n\\tself trigger: (AddedEvent\\n\\t\\t\\t\\tmethod: aMethod\\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: aCategoryName\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:41'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass\\n\\tself trigger: (ModifiedEvent\\n\\t\\t\\t\\t\\tmethodChangedFrom: oldMethod\\n\\t\\t\\t\\t\\tto: newMethod\\n\\t\\t\\t\\t\\tselector: aSymbol \\n\\t\\t\\t\\t\\tinClass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:41'!\\nmethodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor\\n\\tself trigger: (ModifiedEvent\\n\\t\\t\\t\\t\\tmethodChangedFrom: oldMethod\\n\\t\\t\\t\\t\\tto: newMethod\\n\\t\\t\\t\\t\\tselector: aSymbol \\n\\t\\t\\t\\t\\tinClass: aClass\\n\\t\\t\\t\\t\\trequestor: requestor)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/28/2004 11:12'!\\nmethodRemoved: aMethod selector: aSymbol class: aClass \\n\\t\\\"A method with the given selector was removed from the class.\\\"\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/28/2004 11:11'!\\nmethodRemoved: aMethod selector: aSymbol inProtocol: protocol class: aClass \\n\\t\\\"A method with the given selector was removed from the class.\\\"\\n\\n\\tself trigger: (RemovedEvent\\n\\t\\t\\t\\tmethod: aMethod \\n\\t\\t\\t\\tselector: aSymbol\\n\\t\\t\\t\\tprotocol: protocol\\n\\t\\t\\t\\tclass: aClass)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 4/7/2004 13:35'!\\nselector: selector recategorizedFrom: oldCategory to: newCategory inClass: aClass\\n\\n\\tself trigger: (RecategorizedEvent \\n\\t\\t\\t\\tmethod: (aClass compiledMethodAt: selector ifAbsent: [nil])\\n\\t\\t\\t\\tprotocol: newCategory\\n\\t\\t\\t\\tclass: aClass\\n\\t\\t\\t\\toldProtocol: oldCategory)! !\\n\\n!SystemChangeNotifier methodsFor: 'system triggers' stamp: 'al 7/18/2004 10:48'!\\ntraitDefinitionChangedFrom: oldTrait to: newTrait\\n\\tself trigger: (ModifiedTraitDefinitionEvent traitDefinitionChangedFrom: oldTrait to: newTrait)! !\\n\\n\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'rw 7/10/2003 15:15'!\\nnotify: anObject ofEvents: eventsCollection using: oneArgumentSelector\\n\\t\\\"Notifies an object of any events in the eventsCollection. Send it back a message #oneArgumentSelector, with as argument the particular system event instance.\\\"\\n\\n\\teventsCollection do: [:eachEvent |\\n\\t\\teventSource when: eachEvent send: oneArgumentSelector to: anObject]! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'rw 7/29/2003 17:05'!\\nreleaseAll\\n\\t\\\"Release all the dependents so that nobody receives notifications anymore.\\\"\\n\\n\\t\\\"Done for cleaning up the system.\\\"\\n\\t\\\"self uniqueInstance releaseAll\\\"\\n\\n\\teventSource releaseActionMap! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'NS 1/26/2004 20:43'!\\nsetBroadcasting\\n\\tsilenceLevel := 0.! !\\n\\n!SystemChangeNotifier methodsFor: 'private' stamp: 'NS 1/26/2004 20:41'!\\ntrigger: event\\n\\n\\tself isBroadcasting ifTrue: [event trigger: eventSource]\\n\\n\\\"\\t| caughtExceptions |\\n\\tcaughtExceptions := OrderedCollection new.\\n\\tself isBroadcasting ifTrue: [\\n\\t\\t[(eventSource actionForEvent: event eventSelector) valueWithArguments: (Array with: event)] on: Exception do: [:exc | caughtExceptions add: exc]].\\n\\tcaughtExceptions do: [:exc | exc resignalAs: exc class new]\\\"! !\\n\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nallSystemEvents\\n\\t^AbstractEvent systemEvents! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForChange: changeKind \\n\\t| selectorBlock |\\n\\tselectorBlock := AbstractEvent eventSelectorBlock.\\n\\t^AbstractEvent allItemKinds \\n\\t\\tcollect: [:itemKind | selectorBlock value: itemKind value: changeKind]! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForItem: itemKind \\n\\t| selectorBlock |\\n\\tselectorBlock := AbstractEvent eventSelectorBlock.\\n\\t^AbstractEvent allChangeKinds \\n\\t\\tcollect: [:changeKind | selectorBlock value: itemKind value: changeKind]! !\\n\\n!SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'!\\nsystemEventsForItem: itemKind change: changeKind \\n\\t^AbstractEvent eventSelectorBlock value: itemKind value: changeKind! !\\n\\n\\\"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- \\\"!\\n\\nSystemChangeNotifier class\\n\\tinstanceVariableNames: ''!\\n\\n!SystemChangeNotifier class methodsFor: 'instance creation' stamp: 'rw 6/28/2003 09:41'!\\nnew\\n\\n\\t^self error: self instanceCreationErrorString! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\ncategoryKind\\n\\n\\t^ AbstractEvent categoryKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\nclassKind\\n\\n\\t^ AbstractEvent classKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'!\\nexpressionKind\\n\\t^ AbstractEvent expressionKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'!\\nmethodKind\\n\\n\\t^ AbstractEvent methodKind! !\\n\\n!SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'!\\nprotocolKind\\n\\t^ AbstractEvent protocolKind! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'public' stamp: 'NS 1/27/2004 16:23'!\\nuniqueInstance\\n\\n\\tUniqueInstance ifNil: [UniqueInstance := self createInstance].\\n\\t^UniqueInstance! !\\n\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'NS 1/27/2004 16:23'!\\ncreateInstance\\n\\n\\t^self basicNew initialize! !\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'rw 6/28/2003 09:41'!\\ninstanceCreationErrorString\\n\\n\\t^'This is a singleton implementation, so you are not allowed to create instances yourself. Use #uniqueInstance to access the instance.'! !\\n\\n!SystemChangeNotifier class methodsFor: 'private' stamp: 'rw 7/11/2003 14:36'!\\nresetUniqueInstance\\n\\t\\\"self resetUniqueInstance\\\"\\n\\n\\tUniqueInstance\\n\\t\\tifNotNilDo: [:u | UniqueInstance releaseAll.\\n\\t\\t\\tUniqueInstance _ nil]! !\\nSystemChangeTestRoot subclass: #SystemChangeNotifierTest\\n\\tinstanceVariableNames: 'capturedEvent'\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeNotifierTest commentStamp: 'rw 4/3/2006 17:19' prior: 0!\\nA SystemChangeNotifierTest is a test class that tests whether the triggering of changes indeed results in the intended changes to be sent to registered object. The basic mechanism for each test is fairly simple:\\n\\t- register the receiver as the one to get the change notifier.\\n\\t- manually trigger a change (so the system is not polluted just to see whether we get the needed event).\\n\\t- the method #event: is invoked and remembers the change event.\\n\\t- the change event is checked to see whether it was the intended one.\\n\\nInstance Variables\\n\\tcapturedEvent:\\t\\tRemembers the captured event!\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:34'!\\ncapturedEvent: eventOrNil\\n\\t\\\"Remember the event being sent.\\\"\\n\\n\\tcapturedEvent := eventOrNil! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:36'!\\ncheckEventForClass: aClass category: cat change: changeKind \\n\\n\\tself assert: (capturedEvent perform: ('is' , changeKind) asSymbol).\\n\\tself assert: capturedEvent item = aClass.\\n\\tself assert: capturedEvent itemKind = AbstractEvent classKind.\\n\\tself assert: capturedEvent itemClass = aClass.\\n\\tself assert: capturedEvent itemCategory = cat! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:43'!\\ncheckEventForMethod: aMethod protocol: prot change: changeKind \\n\\n\\tself assert: (capturedEvent perform: ('is' , changeKind) asSymbol).\\n\\tself assert: capturedEvent item = aMethod.\\n\\tself assert: capturedEvent itemKind = AbstractEvent methodKind.\\n\\tself assert: capturedEvent itemClass = self class.\\n\\tself assert: capturedEvent itemMethod = aMethod.\\n\\tself assert: capturedEvent itemProtocol = prot! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Private' stamp: 'rw 4/3/2006 16:43'!\\ncheckEventForMethod: aMethod protocol: prot change: changeKind oldMethod: oldMethod\\n\\n\\tself checkEventForMethod: aMethod protocol: prot change: changeKind.\\n\\tself assert: capturedEvent oldItem == oldMethod\\n\\t! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Event Notifications' stamp: 'rw 4/3/2006 17:50'!\\nevent: event\\n\\t\\\"The notification message being sent to me when an event is captured. Remember it.\\\"\\n\\n\\\"\\tcapturedEvent isNil ifTrue: [\\tself capturedEvent: event] ifFalse: [self assert: false]\\\"\\n\\n\\tself capturedEvent: event! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Running' stamp: 'rw 4/3/2006 17:55'!\\ntearDown\\n\\n\\tself capturedEvent: nil.\\n\\tsuper tearDown! !\\n\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassAddedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classAdded: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassAddedEvent2\\n\\n\\tself systemChangeNotifier notify: self ofSystemChangesOfItem: #class change: #Added using: #event:.\\n\\tself systemChangeNotifier classAdded: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassCommentedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classCommented: self class inCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Commented! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRecategorizedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tclass: self class\\n\\t\\trecategorizedFrom: #FooCat\\n\\t\\tto: #FooBar.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooBar\\n\\t\\tchange: #Recategorized.\\n\\tself assert: capturedEvent oldCategory = #FooCat! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRemovedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier classRemoved: self class fromCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Removed! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:24'!\\ntestClassRenamedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tclassRenamed: self class\\n\\t\\tfrom: #OldFooClass\\n\\t\\tto: #NewFooClass\\n\\t\\tinCategory: #FooCat.\\n\\tself\\n\\t\\tcheckEventForClass: self class\\n\\t\\tcategory: #FooCat\\n\\t\\tchange: #Renamed.\\n\\\"\\tself assert: capturedEvent oldName = #OldFooClass.\\n\\tself assert: capturedEvent newName = #NewFooClass\\\"! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestDoItEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tevaluated: '1 + 2'\\n\\t\\tcontext: self.\\n\\tself assert: capturedEvent isDoIt.\\n\\tself assert: capturedEvent item = '1 + 2'.\\n\\tself assert: capturedEvent itemKind = AbstractEvent expressionKind.\\n\\tself assert: capturedEvent itemClass = nil.\\n\\tself assert: capturedEvent itemMethod = nil.\\n\\tself assert: capturedEvent itemProtocol = nil.\\n\\tself assert: capturedEvent itemExpression = '1 + 2'.\\n\\tself assert: capturedEvent context = self.! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent1\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodAdded: self class >> #testMethodAddedEvent1\\n\\t\\tselector: #testMethodAddedEvent1\\n\\t\\tinProtocol: #FooCat\\n\\t\\tclass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent1\\n\\t\\tprotocol: #FooCat\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent2\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodAdded: self class >> #testMethodAddedEvent1\\n\\t\\tselector: #testMethodAddedEvent1\\n\\t\\tinClass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent1\\n\\t\\tprotocol: nil\\n\\t\\tchange: #Added! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodAddedEvent3\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodChangedFrom: self class >> #testMethodAddedEvent1\\n\\t\\tto: self class >> #testMethodAddedEvent2\\n\\t\\tselector: #testMethodAddedEvent2\\n\\t\\tinClass: self class.\\n\\tself \\n\\t\\tcheckEventForMethod: self class >> #testMethodAddedEvent2\\n\\t\\tprotocol: nil\\n\\t\\tchange: #Modified\\n\\t\\toldMethod: self class >> #testMethodAddedEvent1.! !\\n\\n!SystemChangeNotifierTest methodsFor: 'Testing-system triggers' stamp: 'rw 4/5/2006 17:25'!\\ntestMethodRemovedEvent\\n\\n\\tself systemChangeNotifier notify: self ofAllSystemChangesUsing: #event:.\\n\\tself systemChangeNotifier \\n\\t\\tmethodRemoved: self class>> #testMethodRemovedEvent\\n\\t\\tselector: #testMethodRemovedEvent\\n\\t\\tinProtocol: #FooCat\\n\\t\\tclass: self class.\\n\\tself\\n\\t\\tcheckEventForMethod: self class>> #testMethodRemovedEvent\\n\\t\\tprotocol: #FooCat\\n\\t\\tchange: #Removed.! !\\nTestCase subclass: #SystemChangeTestRoot\\n\\tinstanceVariableNames: ''\\n\\tclassVariableNames: ''\\n\\tpoolDictionaries: ''\\n\\tcategory: 'SystemChangeNotification-Tests'!\\n!SystemChangeTestRoot commentStamp: 'rw 4/5/2006 17:28' prior: 0!\\nThe Root test class for the System Change Notification tests.!\\n\\n\\n!SystemChangeTestRoot methodsFor: 'Private' stamp: 'rw 4/3/2006 17:48'!\\nsystemChangeNotifier\\n\\t\\\"The notifier to use. Use the one for the system.\\\"\\n\\n\\t^SystemChangeNotifier uniqueInstance! !\\n\\n\\n!SystemChangeTestRoot methodsFor: 'Running' stamp: 'rw 4/3/2006 17:59'!\\ntearDown\\n\\n\\tself unhook.\\n\\tsuper tearDown! !\\n\\n!SystemChangeTestRoot methodsFor: 'Running' stamp: 'rw 4/3/2006 17:23'!\\nunhook\\n\\n\\tself systemChangeNotifier noMoreNotificationsFor: self! !\\nIdentityDictionary subclass: #SystemDictionary\\n\\tinstanceVariableNames: 'cachedClassNames'\\n\\tclassVariableNames: 'LastImageName LastQuitLogPosition LowSpaceProcess LowSpaceSemaphore MemoryHogs ShutDownList SpecialSelectors StartUpList StartupStamp SystemChanges'\\n\\tpoolDictionaries: ''\\n\\tcategory: 'System-Support'!\\n!SystemDictionary commentStamp: '<historical>' prior: 0!\\nI represent a special dictionary that supports protocol for asking questions about the structure of the system. Other than class names, I contain (print this)...\\n\\tSmalltalk keys select: [:k | ((Smalltalk at: k) isKindOf: Class) not]\\n\\t\\t\\tthenCollect: [:k | k -> (Smalltalk at: k) class]\\n!\\n\\n\\n!SystemDictionary methodsFor: 'accessing' stamp: 'ar 7/11/1999 21:56'!\\norganization\\n\\t\\\"Return the organizer for the receiver\\\"\\n\\t^SystemOrganization! !\\n\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:59'!\\nallClassesAndTraits\\n\\t\\\"Return all the classes and traits defined in the Smalltalk SystemDictionary\\\"\\n\\n\\t^ self classNames , self traitNames collect: [:each | self at: each]! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/13/2006 00:15'!\\nallClassesAndTraitsDo: aBlock\\n\\t^self allClassesAndTraits do: aBlock! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:57'!\\nclassNamed: className \\n\\t^self classOrTraitNamed: className.! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/13/2006 00:51'!\\nclassNames\\n\\t\\\"Answer a SortedCollection of all class names.\\\"\\n\\t| names |\\n\\tcachedClassNames == nil ifTrue:\\n\\t\\t[names _ OrderedCollection new: self size.\\n\\t\\tself do: \\n\\t\\t\\t[:cl | (cl isInMemory\\n\\t\\t\\t\\tand: [(cl isKindOf: Class)\\n\\t\\t\\t\\t\\tand: [(cl name beginsWith: 'AnObsolete') not]])\\n\\t\\t\\t\\tifTrue: [names add: cl name]].\\n\\t\\tcachedClassNames _ names asSortedCollection].\\n\\t^ cachedClassNames! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:56'!\\nclassOrTraitNamed: aString \\n\\t\\\"aString is either a class or trait name or a class or trait name followed by ' class' or 'classTrait' respectively.\\n\\tAnswer the class or metaclass it names.\\\"\\n\\n\\t| meta baseName baseClass |\\n\\t(aString endsWith: ' class')\\n\\t\\tifTrue: [meta _ true.\\n\\t\\t\\t\\tbaseName _ aString copyFrom: 1 to: aString size - 6]\\n\\t\\tifFalse: [\\n\\t\\t\\t(aString endsWith: ' classTrait')\\n\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\tmeta _ true.\\n\\t\\t\\t\\t\\tbaseName _ aString copyFrom: 1 to: aString size - 11]\\n\\t\\t\\t\\tifFalse: [\\n\\t\\t\\t\\t\\tmeta _ false.\\n\\t\\t\\t\\t\\tbaseName _ aString]].\\n\\tbaseClass _ Smalltalk at: baseName asSymbol ifAbsent: [^ nil].\\n\\tmeta\\n\\t\\tifTrue: [^ baseClass classSide]\\n\\t\\tifFalse: [^ baseClass]! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'di 2/16/2000 10:28'!\\nflushClassNameCache\\n\\t\\\"Smalltalk flushClassNameCache\\\"\\n\\t\\\"Forse recomputation of the cached list of class names.\\\"\\n\\n\\tcachedClassNames _ nil! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'NS 1/27/2004 12:08'!\\nforgetClass: aClass logged: aBool \\n\\t\\\"Delete the class, aClass, from the system.\\n\\tNote that this doesn't do everything required to dispose of a class - to do that use Class>>removeFromSystem.\\\"\\n\\n\\taBool ifTrue: [SystemChangeNotifier uniqueInstance classRemoved: aClass fromCategory: aClass category].\\t\\t\\n\\tSystemOrganization removeElement: aClass name.\\n\\tself removeFromStartUpList: aClass.\\n\\tself removeFromShutDownList: aClass.\\n\\tself removeKey: aClass name ifAbsent: [].\\n\\tself flushClassNameCache! !\\n\\n!SystemDictionary methodsFor: 'class and trait names'!\\nhasClassNamed: aString\\n\\t\\\"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\\\"\\n\\n\\tSymbol hasInterned: aString ifTrue: \\n\\t\\t[:aSymbol | ^ (self at: aSymbol ifAbsent: [nil]) isKindOf: Class].\\n\\t^ false! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'sw 9/5/97 18:30'!\\nremoveClassNamed: aName\\n\\t\\\"Invoked from fileouts: if there is currently a class in the system named aName, then remove it. If anything untoward happens, report it in the Transcript. \\\"\\n\\n\\t| oldClass |\\n\\t(oldClass _ self at: aName asSymbol ifAbsent: [nil]) == nil\\n\\t\\tifTrue:\\n\\t\\t\\t[Transcript cr; show: 'Removal of class named ', aName, ' ignored because ', aName, ' does not exist.'.\\n\\t\\t\\t^ self].\\n\\n\\toldClass removeFromSystem! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'sw 10/28/96'!\\nrenameClassNamed: oldName as: newName\\n\\t\\\"Invoked from fileouts: if there is currently a class in the system named oldName, then rename it to newName. If anything untoward happens, report it in the Transcript. \\\"\\n\\n\\t| oldClass |\\n\\t(oldClass _ self at: oldName asSymbol ifAbsent: [nil]) == nil\\n\\t\\tifTrue:\\n\\t\\t\\t[Transcript cr; show: 'Class-rename for ', oldName, ' ignored because ', oldName, ' does not exist.'.\\n\\t\\t\\t^ self].\\n\\n\\toldClass rename: newName! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'rr 3/11/2004 15:18'!\\nrenameClass: aClass as: newName \\n\\t\\\"Rename the class, aClass, to have the title newName.\\\"\\n\\t| oldref i oldName category |\\n\\toldName := aClass name.\\n\\tcategory := aClass category.\\n\\tSystemOrganization classify: newName under: aClass category.\\n\\tSystemOrganization removeElement: aClass name.\\n\\toldref _ self associationAt: aClass name.\\n\\tself removeKey: aClass name.\\n\\toldref key: newName.\\n\\tself add: oldref. \\\"Old association preserves old refs\\\"\\n\\t(Array with: StartUpList with: ShutDownList) do:\\n\\t\\t[:list | i _ list indexOf: aClass name ifAbsent: [0].\\n\\t\\ti > 0 ifTrue: [list at: i put: newName]].\\n\\tself flushClassNameCache.\\n\\tSystemChangeNotifier uniqueInstance classRenamed: aClass from: oldName to: newName inCategory: category! !\\n\\n!SystemDictionary methodsFor: 'class and trait names' stamp: 'al 1/12/2006 23:54'!\\ntraitNames\\n\\t\\\"Answer a SortedCollection of all traits (not including class-traits) names.\\\"\\n\\t| names |\\n\\tnames := OrderedCollection new.\\n\\tself do: \\n\\t\\t[:cl | (cl isInMemory\\n\\t\\t\\tand: [(cl isKindOf: Trait)\\n\\t\\t\\tand: [(cl name beginsWith: 'AnObsolete') not]])\\n\\t\\t\\t\\tifTrue: [names add: cl name]].\\n\\t^ names! !\\n\\n\\n!SystemDictionary methodsFor: 'copying' stamp: 'tk 10/20/2000 11:35'!\\nveryDeepCopyWith: deepCopier\\n\\t\\\"Return self. I can't be copied. Do not record me.\\\"! !\\n\\n\\n!SystemDictionary methodsFor: 'dictionary access' stamp: 'md 3/2/2006 22:01'!\\nassociationOrUndeclaredAt: key \\n\\t\\\"return an association or install in undeclared. Used for mating up ImageSegments.\\\"\\n\\n\\t^ self associationAt: key ifAbsent: [\\n\\t\\tUndeclared at: key put: nil.\\n\\t\\tUndeclared associationAt: key]! !\\n\\n!SystemDictionary methodsFor: 'dictionary access'!\\nat: aKey put: anObject \\n\\t\\\"Override from Dictionary to check Undeclared and fix up\\n\\treferences to undeclared variables.\\\"\\n\\t| index element |\\n\\t(self includesKey: aKey) ifFalse: \\n\\t\\t[self declare: aKey from: Undeclared.\\n\\t\\tself flushClassNameCache].\\n\\tsuper at: aKey put: anObject.\\n\\t^ anObject! !\\n\\n\\n!SystemDictionary methodsFor: 'housekeeping'!\\ncleanOutUndeclared \\n\\tUndeclared removeUnreferencedKeys! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'md 1/5/2004 18:05'!\\ncompressSources\\t\\n\\t\\\"Copy all the source file to a compressed file. Usually preceded by Smalltalk condenseSources.\\\"\\n\\t\\\"The new file will be created in the default directory, and the code in openSources\\n\\twill try to open it if it is there, otherwise it will look for normal sources.\\\"\\n\\t\\\"Smalltalk compressSources\\\"\\n\\n\\t| f cfName cf |\\n\\tf _ SourceFiles first.\\n\\t(SmalltalkImage current sourcesName endsWith: 'sources')\\n\\t\\tifTrue: [cfName _ (SmalltalkImage current sourcesName allButLast: 7) , 'stc']\\n\\t\\tifFalse: [self error: 'Hey, I thought the sources name ended with ''.sources''.'].\\n\\tcf _ (CompressedSourceStream on: (FileStream newFileNamed: cfName))\\n\\t\\t\\t\\tsegmentSize: 20000 maxSize: f size.\\n\\n\\t\\\"Copy the sources\\\"\\n'Compressing Sources File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: f size\\n\\tduring:\\n\\t\\t[:bar | f position: 0.\\n\\t\\t[f atEnd] whileFalse:\\n\\t\\t\\t[cf nextPutAll: (f next: 20000).\\n\\t\\t\\tbar value: f position]].\\n\\tcf close.\\n\\tself setMacFileInfoOn: cfName.\\n\\tself inform: 'You now have a compressed sources file!!\\nSqueak will use it the next time you start.'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'al 1/13/2006 00:17'!\\ncondenseChanges\\n\\t\\\"Move all the changes onto a compacted sources file.\\\"\\n\\t\\\"Smalltalk condenseChanges\\\"\\n\\t| f oldChanges count |\\n\\tf := FileStream fileNamed: 'ST80.temp'.\\n\\tf header; timeStamp.\\n\\t'Condensing Changes File...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: self classNames size + self traitNames size\\n\\t\\tduring: [:bar | \\n\\t\\t\\tcount := 0.\\n\\t\\t\\tself\\n\\t\\t\\t\\tallClassesAndTraitsDo: [:classOrTrait | \\n\\t\\t\\t\\t\\tbar value: (count := count + 1).\\n\\t\\t\\t\\t\\tclassOrTrait moveChangesTo: f.\\n\\t\\t\\t\\t\\tclassOrTrait putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\t\\t\\tclassOrTrait classSide moveChangesTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges := SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default deleteFileNamed: oldChanges name , '.old';\\n\\t\\t rename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\t rename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles\\n\\t\\tat: 2\\n\\t\\tput: (StandardFileStream oldFileNamed: oldChanges name)! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'md 3/1/2006 00:02'!\\ncondenseSources\\t\\n\\t\\\"Move all the changes onto a compacted sources file.\\\"\\n\\t\\\"Smalltalk condenseSources\\\"\\n\\n\\t| f dir newVersionString count |\\n\\tUtilities fixUpProblemsWithAllCategory.\\n\\t\\\"The above removes any concrete, spurious '-- all --' categories, which mess up the process.\\\"\\n\\tdir := FileDirectory default.\\n\\tnewVersionString := UIManager default request: 'Please designate the version\\nfor the new source code file...' initialAnswer: SmalltalkImage current sourceFileVersionString.\\n\\tnewVersionString ifNil: [^ self].\\n\\tnewVersionString = SmalltalkImage current sourceFileVersionString ifTrue:\\n\\t\\t[^ self error: 'The new source file must not be the same as the old.'].\\n\\tSmalltalkImage current sourceFileVersionString: newVersionString.\\n\\n\\t\\\"Write all sources with fileIndex 1\\\"\\n\\tf := FileStream newFileNamed: SmalltalkImage current sourcesName.\\n\\tf header; timeStamp.\\n'Condensing Sources File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: self classNames size + self traitNames size\\n\\tduring:\\n\\t\\t[:bar | count := 0.\\n\\t\\tSmalltalk allClassesAndTraitsDo:\\n\\t\\t\\t[:classOrTrait | bar value: (count := count + 1).\\n\\t\\t\\tclassOrTrait fileOutOn: f moveSource: true toFile: 1]].\\n\\tf trailer; close.\\n\\n\\t\\\"Make a new empty changes file\\\"\\n\\tSmalltalkImage current closeSourceFiles.\\n\\tdir rename: SmalltalkImage current changesName\\n\\t\\ttoBe: SmalltalkImage current changesName , '.old'.\\n\\t(FileStream newFileNamed: SmalltalkImage current changesName)\\n\\t\\theader; timeStamp; close.\\n\\tSmalltalkImage current lastQuitLogPosition: 0.\\n\\n\\tself setMacFileInfoOn: SmalltalkImage current changesName.\\n\\tself setMacFileInfoOn: SmalltalkImage current sourcesName.\\n\\tSmalltalkImage current openSourceFiles.\\n\\tself inform: 'Source files have been rewritten!!\\nCheck that all is well,\\nand then save/quit.'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 4/17/2003 20:59'!\\nforgetDoIts\\t\\n\\t\\\"Smalltalk forgetDoIts\\\"\\n\\t \\\"get rid of old DoIt methods\\\"\\n\\n\\tself systemNavigation allBehaviorsDo:\\n\\t\\t[:cl | cl forgetDoIts]\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'ar 9/27/2005 21:45'!\\nmakeExternalRelease\\n\\t\\\"Smalltalk makeExternalRelease\\\"\\n\\t(self confirm: SystemVersion current version , '\\nIs this the correct version designation?\\nIf not, choose no, and fix it.')\\n\\t\\tifFalse: [^ self].\\n\\t\\\"Object classPool at: #DependentsFields\\\"\\n\\tself reclaimDependents.\\n\\tPreferences enable: #mvcProjectsAllowed.\\n\\tPreferences enable: #fastDragWindowForMorphic.\\n\\tSmalltalk at: #Browser ifPresent:[:br| br initialize].\\n\\tUndeclared isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tScriptingSystem deletePrivateGraphics.\\n\\t#(#Helvetica #Palatino #Courier )\\n\\t\\tdo: [:n | TextConstants\\n\\t\\t\\t\\tremoveKey: n\\n\\t\\t\\t\\tifAbsent: []].\\n\\t(Utilities classPool at: #UpdateUrlLists) copy\\n\\t\\tdo: [:pair | (pair first includesSubstring: 'Disney' caseSensitive: false)\\n\\t\\t\\t\\tifTrue: [(Utilities classPool at: #UpdateUrlLists)\\n\\t\\t\\t\\t\\t\\tremove: pair]].\\n\\t(ServerDirectory serverNames copyWithoutAll: #('UCSBCreateArchive' 'UIUCArchive' 'UpdatesExtUIUC' 'UpdatesExtWebPage' ))\\n\\t\\tdo: [:sn | ServerDirectory removeServerNamed: sn].\\n\\tself garbageCollect.\\n\\tself obsoleteClasses isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tSymbol rehash.\\n\\tself halt: 'Ready to condense changes or sources'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'ar 9/27/2005 21:45'!\\nmakeInternalRelease\\n\\t\\\"Smalltalk makeInternalRelease\\\"\\n\\t(self confirm: SystemVersion current version , '\\nIs this the correct version designation?\\nIf not, choose no, and fix it.')\\n\\t\\tifFalse: [^ self].\\n\\t(Object classPool at: #DependentsFields) size > 1\\n\\t\\tifTrue: [self halt].\\n\\tSmalltalk at: #Browser ifPresent:[:br| br initialize].\\n\\tUndeclared isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tself garbageCollect.\\n\\tself obsoleteClasses isEmpty\\n\\t\\tifFalse: [self halt].\\n\\tSymbol rehash.\\n\\tself halt: 'Ready to condense changes'.\\n\\tself condenseChanges! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 9/29/2004 18:15'!\\nreclaimDependents\\n\\t\\\"No-opped due to weak dictionary in use\\\"\\n\\tself garbageCollect! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'al 1/13/2006 00:19'!\\nreconstructChanges\\t\\n\\t\\\"Move all the changes and its histories onto another sources file.\\\"\\n\\t\\\"Smalltalk reconstructChanges\\\"\\n\\n\\t| f oldChanges classCount |\\n\\tf _ FileStream fileNamed: 'ST80.temp'.\\n\\tf header; timeStamp.\\n'Condensing Changes File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: self classNames size + self traitNames size\\n\\tduring:\\n\\t\\t[:bar | classCount _ 0.\\n\\t\\tSmalltalk allClassesAndTraitsDo:\\n\\t\\t\\t[:classOrTrait | bar value: (classCount _ classCount + 1).\\n\\t\\t\\tclassOrTrait moveChangesWithVersionsTo: f.\\n\\t\\t\\tclassOrTrait putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\tclassOrTrait classSide moveChangesWithVersionsTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges _ SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default \\n\\t\\tdeleteFileNamed: oldChanges name , '.old';\\n\\t\\trename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\trename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles at: 2\\n\\t\\t\\tput: (FileStream oldFileNamed: oldChanges name)! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'yo 2/24/2005 18:01'!\\nreformatChangesToUTF8\\n\\t\\\"Smalltalk reformatChangesToUTF8\\\"\\n\\n\\t| f oldChanges classCount |\\n\\tf _ FileStream fileNamed: 'ST80.temp'.\\n\\tf converter: (UTF8TextConverter new).\\n\\tf header; timeStamp.\\n'Condensing Changes File...'\\n\\tdisplayProgressAt: Sensor cursorPoint\\n\\tfrom: 0 to: Smalltalk classNames size\\n\\tduring:\\n\\t\\t[:bar | classCount _ 0.\\n\\t\\tSmalltalk allClassesDo:\\n\\t\\t\\t[:class | bar value: (classCount _ classCount + 1).\\n\\t\\t\\tclass moveChangesTo: f.\\n\\t\\t\\tclass putClassCommentToCondensedChangesFile: f.\\n\\t\\t\\tclass class moveChangesTo: f]].\\n\\tSmalltalkImage current lastQuitLogPosition: f position.\\n\\tf trailer; close.\\n\\toldChanges _ SourceFiles at: 2.\\n\\toldChanges close.\\n\\tFileDirectory default \\n\\t\\tdeleteFileNamed: oldChanges name , '.old';\\n\\t\\trename: oldChanges name toBe: oldChanges name , '.old';\\n\\t\\trename: f name toBe: oldChanges name.\\n\\tself setMacFileInfoOn: oldChanges name.\\n\\tSourceFiles at: 2\\n\\t\\t\\tput: (FileStream oldFileNamed: oldChanges name).\\n\\tMultiByteFileStream codeConverterClass: UTF8TextConverter.\\n\\t(SourceFiles at: 2) converter: (UTF8TextConverter new).\\n! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 10:22'!\\nremoveAllLineFeeds\\n\\t\\\"Smalltalk removeAllLineFeeds\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tWhen done, offers to display an Inspector containing the message\\n\\tnames grouped by author initials.\\n\\tIn this dictionary, the key 'OK' contains the methods that had literals that contained <LF> characters.\\\"\\n\\t| n authors totalStripped totalOK |\\n\\t'Scanning sources for LineFeeds.\\nThis will take a few minutes...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: [:bar | \\n\\t\\t\\tn _ 0.\\n\\t\\t\\tauthors _ self\\n\\t\\t\\t\\t\\t\\tremoveAllLineFeedsQuietlyCalling: [:cls :sel | (n _ n + 1) \\\\\\\\ 100 = 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [bar value: n]]].\\n\\ttotalStripped _ authors\\n\\t\\t\\t\\tinject: 1\\n\\t\\t\\t\\tinto: [:sum :set | sum + set size].\\n\\ttotalOK _ (authors at: 'OK') size.\\n\\ttotalStripped _ totalStripped - totalOK.\\n\\tTranscript cr; show: totalStripped printString , ' methods stripped of LFs.'.\\n\\tTranscript cr; show: totalOK printString , ' methods still correctly contain LFs.'.\\n\\t(self confirm: 'Do you want to see the affected methods?')\\n\\t\\tifTrue: [authors inspect]! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 08:35'!\\nremoveAllLineFeedsQuietly\\n\\t\\\"Smalltalk removeAllLineFeedsQuietly\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tAnswer a Dictionary keyed by author name containing sets of affected method names,\\n\\tas well as (at the key 'OK') a list of methods that still contain LF characters inside literal strings or characters.\\\"\\n\\t^self removeAllLineFeedsQuietlyCalling: [ :cls :sel | ].! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 6/2/2006 09:22'!\\nremoveAllLineFeedsQuietlyCalling: aBlock\\n\\t\\\"Smalltalk removeAllLineFeedsQuietly\\\"\\n\\t\\\"Scan all methods for source code with lineFeeds.\\n\\tReplaces all occurrences of <CR><LF> or <LF> by <CR>.\\n\\tAnswer a Dictionary keyed by author name containing sets of affected method names,\\n\\tas well as (at the key 'OK') a list of methods that still contain LF characters inside literal strings or characters.\\n\\tEvaluate aBlock for each method so that status can be updated.\\\"\\n\\t| oldCodeString newCodeString oldStamp oldCategory authors nameString |\\n\\tself forgetDoIts.\\n\\tauthors _ Dictionary new.\\n\\tauthors at: 'OK' put: Set new.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:cls | cls selectors\\n\\t\\t\\t\\tdo: [:selector | \\n\\t\\t\\t\\t\\taBlock value: cls value: selector.\\n\\t\\t\\t\\t\\toldCodeString _ cls sourceCodeAt: selector.\\n\\t\\t\\t\\t\\t(oldCodeString includes: Character lf)\\n\\t\\t\\t\\t\\t\\tifTrue: [\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString _ oldCodeString withSqueakLineEndings.\\n\\t\\t\\t\\t\\t\\t\\tnameString _ cls name , '>>' , selector.\\n\\t\\t\\t\\t\\t\\t\\t((cls compiledMethodAt: selector) hasLiteralSuchThat: [ :lit | lit asString includes: Character lf ])\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [(authors at: 'OK')\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tadd: nameString]\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: [oldStamp _ (Utilities\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttimeStampForMethod: (cls compiledMethodAt: selector))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopy replaceAll: Character cr\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twith: Character space.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t(authors\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tat: (oldStamp copyFrom: 1 to: (oldStamp findFirst: [ :c | c isAlphaNumeric not ]))\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifAbsentPut: [Set new])\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tadd: nameString.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\toldCategory _ cls whichCategoryIncludesSelector: selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompile: newCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclassified: oldCategory\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twithStamp: oldStamp\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil ]]]].\\n\\t^ authors! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 9/29/2004 18:15'!\\nremoveEmptyMessageCategories\\n\\t\\\"Smalltalk removeEmptyMessageCategories\\\"\\n\\tself garbageCollect.\\n\\t(ClassOrganizer allInstances copyWith: SystemOrganization)\\n\\t\\tdo: [:org | org removeEmptyCategories]! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 2/23/2005 18:00'!\\ntestFormatter\\n\\t\\\"Smalltalk testFormatter\\\"\\n\\n\\t\\\"Reformats the source for every method in the system, and\\n\\tthen compiles that source and verifies that it generates\\n\\tidentical code. The formatting used will be either classic\\n\\tmonochrome or fancy polychrome, depending on the setting\\n\\tof the preference #colorWhenPrettyPrinting.\\\"\\n\\n\\t| newCodeString methodNode oldMethod newMethod badOnes n |\\n\\tbadOnes := OrderedCollection new.\\n\\tself forgetDoIts.\\n\\t'Formatting all classes...' \\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: \\n\\t\\t\\t[:bar | \\n\\t\\t\\tn := 0.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: \\n\\t\\t\\t\\t\\t[:cls | \\n\\t\\t\\t\\t\\t\\\"Transcript cr; show: cls name.\\\"\\n\\n\\t\\t\\t\\t\\tcls selectors do: \\n\\t\\t\\t\\t\\t\\t\\t[:selector | \\n\\t\\t\\t\\t\\t\\t\\t(n := n + 1) \\\\\\\\ 100 = 0 ifTrue: [bar value: n].\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString := cls prettyPrinterClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: (cls sourceCodeAt: selector)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecorated: Preferences colorWhenPrettyPrinting.\\n\\t\\t\\t\\t\\t\\t\\tmethodNode := cls compilerClass new \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompile: newCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tifFail: [].\\n\\t\\t\\t\\t\\t\\t\\tnewMethod := methodNode generate: #(0 0 0 0).\\n\\t\\t\\t\\t\\t\\t\\toldMethod := cls compiledMethodAt: selector.\\n\\t\\t\\t\\t\\t\\t\\toldMethod = newMethod \\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[Transcript\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcr;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshow: '***' , cls name , ' ' , selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbadOnes add: cls name , ' ' , selector]]]].\\n\\tself systemNavigation browseMessageList: badOnes asSortedCollection\\n\\t\\tname: 'Formatter Discrepancies'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'nk 2/23/2005 18:00'!\\ntestFormatter2\\n\\t\\\"Smalltalk testFormatter2\\\"\\n\\n\\t\\\"Reformats the source for every method in the system, and\\n\\tthen verifies that the order of source tokens is unchanged.\\n\\tThe formatting used will be either classic monochrome or\\n\\tfancy polychrome, depending on the setting of the preference\\n\\t#colorWhenPrettyPrinting. \\\"\\n\\n\\t| newCodeString badOnes n oldCodeString oldTokens newTokens |\\n\\tbadOnes := OrderedCollection new.\\n\\tself forgetDoIts.\\n\\t'Formatting all classes...' \\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: \\n\\t\\t\\t[:bar | \\n\\t\\t\\tn := 0.\\n\\t\\t\\tself systemNavigation allBehaviorsDo: \\n\\t\\t\\t\\t\\t[:cls | \\n\\t\\t\\t\\t\\t\\\"Transcript cr; show: cls name.\\\"\\n\\n\\t\\t\\t\\t\\tcls selectors do: \\n\\t\\t\\t\\t\\t\\t\\t[:selector | \\n\\t\\t\\t\\t\\t\\t\\t(n := n + 1) \\\\\\\\ 100 = 0 ifTrue: [bar value: n].\\n\\t\\t\\t\\t\\t\\t\\toldCodeString := (cls sourceCodeAt: selector) asString.\\n\\t\\t\\t\\t\\t\\t\\tnewCodeString := cls prettyPrinterClass \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: oldCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cls\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecorated: Preferences colorWhenPrettyPrinting.\\n\\t\\t\\t\\t\\t\\t\\toldTokens := oldCodeString findTokens: Character separators.\\n\\t\\t\\t\\t\\t\\t\\tnewTokens := newCodeString findTokens: Character separators.\\n\\t\\t\\t\\t\\t\\t\\toldTokens = newTokens \\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t[Transcript\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcr;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshow: '***' , cls name , ' ' , selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbadOnes add: cls name , ' ' , selector]]]].\\n\\tself systemNavigation browseMessageList: badOnes asSortedCollection\\n\\t\\tname: 'Formatter Discrepancies'! !\\n\\n!SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 4/17/2003 21:01'!\\nverifyChanges\\t\\t\\\"Smalltalk verifyChanges\\\"\\n\\t\\\"Recompile all methods in the changes file.\\\"\\n\\tself systemNavigation allBehaviorsDo: [:class | class recompileChanges].\\n! !\\n\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimImageName\\n\\t\\\"Answer the full path name for the current image.\\\"\\n\\t\\\"Smalltalk imageName\\\"\\n\\n\\t<primitive: 121>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimImageName: newName\\n\\t\\\"Set the the full path name for the current image. All further snapshots will use this.\\\"\\n\\n\\t<primitive: 121>\\n\\t^ self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'image, changes name' stamp: 'yo 3/29/2004 09:36'!\\nprimVmPath\\n\\t\\\"Answer the path for the directory containing the Smalltalk virtual machine. Return the empty string if this primitive is not implemented.\\\"\\n\\t\\\"Smalltalk vmPath\\\"\\n\\n\\t<primitive: 142>\\n\\t^ ''! !\\n\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nbytesLeft\\n\\t\\\"Answer the number of bytes of space available. Does a full garbage collection.\\\"\\n\\n\\t^ self garbageCollect\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 18:00'!\\nbytesLeftString\\n\\t\\\"Return a string describing the amount of memory available\\\"\\n\\t| availInternal availPhysical availTotal |\\n\\tself garbageCollect.\\n\\tavailInternal _ self primBytesLeft.\\n\\tavailPhysical _ self bytesLeft: false.\\n\\tavailTotal _ self bytesLeft: true.\\n\\t(availTotal > (availInternal + 10000)) \\\"compensate for mini allocations inbetween\\\"\\n\\t\\tifFalse:[^availInternal asStringWithCommas, ' bytes available'].\\n\\t^String streamContents:[:s|\\n\\t\\ts nextPutAll: availInternal asStringWithCommas, \\t' bytes (internal) '; cr.\\n\\t\\ts nextPutAll: availPhysical asStringWithCommas,\\t' bytes (physical) '; cr.\\n\\t\\ts nextPutAll: availTotal asStringWithCommas, \\t' bytes (total) '].! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 17:55'!\\nbytesLeft: aBool\\n\\t\\\"Return the amount of available space. If aBool is true, include possibly available swap space. If aBool is false, include possibly available physical memory. For a report on the largest free block currently availabe within Squeak memory but not counting extra memory use #primBytesLeft.\\\"\\n\\t<primitive: 112>\\n\\t^self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ncreateStackOverflow\\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; createStackOverflow\\\"\\n\\n\\tself createStackOverflow. \\\"infinite recursion\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 13:23'!\\nforceTenure\\n\\t\\\"Primitive. Tell the GC logic to force a tenure on the next increment GC.\\\"\\n\\t<primitive: 'primitiveForceTenure'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:36'!\\ngarbageCollect\\n\\t\\\"Primitive. Reclaims all garbage and answers the number of bytes of available space.\\\"\\n\\tObject flushDependents.\\n\\tObject flushEvents.\\n\\t^self primitiveGarbageCollect! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ngarbageCollectMost\\n\\t\\\"Primitive. Reclaims recently created garbage (which is usually most of it) fairly quickly and answers the number of bytes of available space.\\\"\\n\\n\\t<primitive: 131>\\n\\t^ self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\ninstallLowSpaceWatcher\\n\\t\\\"Start a process to watch for low-space conditions.\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher\\\"\\n\\n\\tself primSignalAtBytesLeft: 0. \\\"disable low-space interrupts\\\"\\n\\tLowSpaceProcess == nil ifFalse: [LowSpaceProcess terminate].\\n\\tLowSpaceProcess _ [self lowSpaceWatcher] newProcess.\\n\\tLowSpaceProcess priority: Processor lowIOPriority.\\n\\tLowSpaceProcess resume.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:46'!\\nisRoot: oop\\n\\t\\\"Primitive. Answer whether the object is currently a root for youngSpace.\\\"\\n\\t<primitive: 'primitiveIsRoot'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:47'!\\nisYoung: oop\\n\\t\\\"Primitive. Answer whether the object currently resides in youngSpace.\\\"\\n\\t<primitive: 'primitiveIsYoung'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:49'!\\nlowSpaceThreshold \\n\\t\\\"Return the low space threshold. When the amount of free memory (after garbage collection) falls below this limit, the system is in serious danger of completely exhausting memory and crashing. This limit should be made high enough to allow the user open a debugger to diagnose a problem or to save the image.\\\"\\n\\n\\tthisContext isPseudoContext\\n\\t\\tifTrue: [^ 400000 \\\"Enough for JIT compiler\\\"]\\n\\t\\tifFalse: [^ 200000 \\\"Enough for interpreter\\\"]! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'dtl 10/3/2005 06:12'!\\nlowSpaceWatcher\\n\\t\\\"Wait until the low space semaphore is signalled, then take appropriate actions.\\\"\\n\\n\\t| free preemptedProcess |\\n\\tself garbageCollectMost <= self lowSpaceThreshold\\n\\t\\tifTrue: [self garbageCollect <= self lowSpaceThreshold\\n\\t\\t\\t\\tifTrue: [\\\"free space must be above threshold before\\n\\t\\t\\t\\t\\tstarting low space watcher\\\"\\n\\t\\t\\t\\t\\t^ Beeper beep]].\\n\\n\\tSmalltalk specialObjectsArray at: 23 put: nil. \\\"process causing low space will be saved here\\\"\\n\\tLowSpaceSemaphore _ Semaphore new.\\n\\tself primLowSpaceSemaphore: LowSpaceSemaphore.\\n\\tself primSignalAtBytesLeft: self lowSpaceThreshold. \\\"enable low space interrupts\\\"\\n\\n\\tLowSpaceSemaphore wait. \\\"wait for a low space condition...\\\"\\n\\n\\tself primSignalAtBytesLeft: 0. \\\"disable low space interrupts\\\"\\n\\tself primLowSpaceSemaphore: nil.\\n\\tLowSpaceProcess _ nil.\\n\\n\\t\\\"The process that was active at the time of the low space interrupt.\\\"\\n\\tpreemptedProcess _ Smalltalk specialObjectsArray at: 23.\\n\\tSmalltalk specialObjectsArray at: 23 put: nil.\\n\\n\\t\\\"Note: user now unprotected until the low space watcher is re-installed\\\"\\n\\n\\tself memoryHogs isEmpty\\n\\t\\tifFalse: [free := self bytesLeft.\\n\\t\\t\\tself memoryHogs\\n\\t\\t\\t\\tdo: [ :hog | hog freeSomeSpace ].\\n\\t\\t\\tself bytesLeft > free\\n\\t\\t\\t\\tifTrue: [ ^ self installLowSpaceWatcher ]].\\n\\tself isMorphic\\n\\t\\tifTrue: [CurrentProjectRefactoring\\n\\t\\t\\t\\tcurrentInterruptName: 'Space is low'\\n\\t\\t\\t\\tpreemptedProcess: preemptedProcess]\\n\\t\\tifFalse: [ScheduledControllers\\n\\t\\t\\t\\tinterruptName: 'Space is low'\\n\\t\\t\\t\\tpreemptedProcess: preemptedProcess]\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'nk 10/28/2000 20:37'!\\nlowSpaceWatcherProcess\\n\\t^LowSpaceProcess! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'sma 4/22/2000 19:03'!\\nmemoryHogs\\n\\t\\\"Answer the list of objects to notify with #freeSomeSpace if memory gets full.\\\"\\n\\n\\t^ MemoryHogs ifNil: [MemoryHogs _ OrderedCollection new]! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nokayToProceedEvenIfSpaceIsLow\\n\\t\\\"Return true if either there is enough memory to do so safely or if the user gives permission after being given fair warning.\\\"\\n\\n\\tself garbageCollectMost > self lowSpaceThreshold ifTrue: [^ true]. \\\"quick\\\"\\n\\tself garbageCollect > self lowSpaceThreshold ifTrue: [^ true]. \\\"work harder\\\"\\n\\n\\t^ self confirm:\\n'WARNING: There is not enough space to start the low space watcher.\\nIf you proceed, you will not be warned again, and the system may\\nrun out of memory and crash. If you do proceed, you can start the\\nlow space notifier when more space becomes available simply by\\nopening and then closing a debugger (e.g., by hitting Cmd-period.)\\nDo you want to proceed?'\\n! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimBytesLeft\\n\\t\\\"Primitive. Answer the number of bytes available for new object data.\\n\\tNot accurate unless preceded by\\n\\t\\tSmalltalk garbageCollectMost (for reasonable accuracy), or\\n\\t\\tSmalltalk garbageCollect (for real accuracy).\\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 112>\\n\\t^ 0! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:16'!\\nprimitiveGarbageCollect\\n\\t\\\"Primitive. Reclaims all garbage and answers the number of bytes of available space.\\\"\\n\\n\\t<primitive: 130>\\n\\t^ self primBytesLeft! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimLowSpaceSemaphore: aSemaphore\\n\\t\\\"Primitive. Register the given Semaphore to be signalled when the\\n\\tnumber of free bytes drops below some threshold. Disable low-space\\n\\tinterrupts if the argument is nil.\\\"\\n\\n\\t<primitive: 124>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nprimSignalAtBytesLeft: numBytes\\n\\t\\\"Tell the interpreter the low-space threshold in bytes. When the free\\n\\tspace falls below this threshold, the interpreter will signal the low-space\\n\\tsemaphore, if one has been registered. Disable low-space interrupts if the\\n\\targument is zero. Fail if numBytes is not an Integer.\\\"\\n\\n\\t<primitive: 125>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:48'!\\nrootTable\\n\\t\\\"Primitive. Answer a snapshot of the VMs root table. \\n\\tKeep in mind that the primitive may itself cause GC.\\\"\\n\\t<primitive: 'primitiveRootTable'>\\n\\t^self primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:49'!\\nrootTableAt: index\\n\\t\\\"Primitive. Answer the nth element of the VMs root table\\\"\\n\\t<primitive: 'primitiveRootTableAt'>\\n\\t^nil! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 12:27'!\\nsetGCBiasToGrowGCLimit: aNumber\\n\\t\\\"Primitive. Indicate that the bias to grow logic should do a GC after aNumber Bytes\\\"\\n\\t<primitive: 'primitiveSetGCBiasToGrowGCLimit'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\tSmalltalk setGCBiasToGrowGCLimit: 16*1024*1024.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'JMM 1/27/2005 13:12'!\\nsetGCBiasToGrow: aNumber\\n\\t\\\"Primitive. Indicate that the GC logic should be bias to grow\\\"\\n\\t<primitive: 'primitiveSetGCBiasToGrow'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\tSmalltalk setGCBiasToGrowGCLimit: 16*1024*1024.\\n\\tSmalltalk setGCBiasToGrow: 1.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'ar 1/18/2005 16:54'!\\nsetGCSemaphore: semaIndex\\n\\t\\\"Primitive. Indicate the GC semaphore index to be signaled on GC occurance.\\\"\\n\\t<primitive: 'primitiveSetGCSemaphore'>\\n\\t^self primitiveFailed\\n\\\"Example:\\n\\n\\t| index sema process |\\n\\tsema := Semaphore new.\\n\\tindex := Smalltalk registerExternalObject: sema.\\n\\tSmalltalk setGCSemaphore: index.\\n\\tprocess := [\\n\\t\\t[[true] whileTrue:[\\n\\t\\t\\tsema wait.\\n\\t\\t\\tSmalltalk beep.\\n\\t\\t]] ensure:[\\n\\t\\t\\tSmalltalk setGCSemaphore: 0.\\n\\t\\t\\tSmalltalk unregisterExternalObject: sema.\\n\\t\\t].\\n\\t] fork.\\n\\tprocess inspect.\\n\\\"! !\\n\\n!SystemDictionary methodsFor: 'memory space'!\\nsignalLowSpace\\n\\t\\\"Signal the low-space semaphore to alert the user that space is running low.\\\"\\n\\n\\tLowSpaceSemaphore signal.! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'apb 10/3/2000 16:40'!\\nuseUpMemory\\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemory\\\"\\n\\n\\t| lst |\\n\\tlst _ nil.\\n\\t[true] whileTrue: [\\n\\t\\tlst _ Link nextLink: lst.\\n\\t].! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 21:15'!\\nuseUpMemoryWithArrays \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithArrays\\\"\\n\\n\\t| b | \\\"First use up most of memory.\\\"\\n\\tb _ String new: self bytesLeft - self lowSpaceThreshold - 100000.\\n\\tb _ b. \\\"Avoid unused value warning\\\"\\n\\t(1 to: 10000) collect: [:i | Array new: 10000]! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:49'!\\nuseUpMemoryWithContexts \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithContexts\\\"\\n\\n\\tself useUpMemoryWithContexts! !\\n\\n!SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:50'!\\nuseUpMemoryWithTinyObjects \\n\\t\\\"For testing the low space handler...\\\"\\n\\t\\\"Smalltalk installLowSpaceWatcher; useUpMemoryWithTinyObjects\\\"\\n\\n\\t| b | \\\"First use up most of memory.\\\"\\n\\tb _ String new: self bytesLeft - self lowSpaceThreshold - 100000.\\n\\tb _ b. \\\"Avoid unused value warning\\\"\\n\\t(1 to: 10000) collect: [:i | BitBlt new]! !\\n\\n\\n!SystemDictionary methodsFor: 'miscellaneous'!\\nexitToDebugger\\n\\t\\\"Primitive. Enter the machine language debugger, if one exists. Essential.\\n\\tSee Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 114>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'dao 10/1/2004 13:33'!\\nhandleUserInterrupt\\n\\tPreferences cmdDotEnabled ifTrue:\\n\\t\\t[Smalltalk isMorphic\\n\\t\\t\\tifTrue: [[Project interruptName: 'User Interrupt'] fork]\\n\\t\\t\\tifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] fork]]! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'sd 9/29/2004 18:17'!\\nhasMorphic\\n\\t\\\"Answer whether the Morphic classes are available in the\\n\\tsystem (they may have been stripped, such as by a call to\\n\\tSmalltalk removeMorphic\\\"\\n\\t^ (self\\n\\t\\tat: #Morph\\n\\t\\tifAbsent: [])\\n\\t\\tisKindOf: Class! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'tk 10/16/2001 19:24'!\\nlogError: errMsg inContext: aContext to: aFilename\\n\\t\\\"Log the error message and a stack trace to the given file.\\\"\\n\\n\\t| ff |\\n\\tFileDirectory default deleteFileNamed: aFilename ifAbsent: [].\\n\\t(ff _ FileStream fileNamed: aFilename) ifNil: [^ self \\\"avoid recursive errors\\\"].\\n\\n \\tff nextPutAll: errMsg; cr.\\n\\taContext errorReportOn: ff.\\n\\tff close.! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'yo 7/2/2004 13:32'!\\nm17nVersion\\n\\n\\t^ 'M17n 5.0' copy\\n! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'yo 7/2/2004 13:32'!\\nnihongoVersion\\n\\n\\t^ 'Nihongo7.0' copy\\n! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'MPH 10/24/2000 14:27'!\\nsetMacFileInfoOn: aString\\n\\t\\\"On Mac, set the file type and creator (noop on other platforms)\\\"\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: aString\\n\\t\\ttype: 'STch'\\n\\t\\tcreator: 'FAST'.! !\\n\\n!SystemDictionary methodsFor: 'miscellaneous' stamp: 'nb 6/17/2003 12:25'!\\nverifyMorphicAvailability\\n\\t\\\"If Morphic is available, return true; if not, put up an informer and return false\\\"\\n\\tself hasMorphic ifFalse:\\n\\t\\t[Beeper beep.\\n\\t\\tself inform: 'Sorry, Morphic must\\nbe present to use this feature'.\\n\\t\\t^ false].\\n\\t^ true! !\\n\\n\\n!SystemDictionary methodsFor: 'objects from disk' stamp: 'tk 9/28/2000 15:50'!\\nobjectForDataStream: refStrm\\n\\t| dp |\\n\\t\\\"I am about to be written on an object file. Write a reference to Smalltalk instead.\\\"\\n\\n\\tdp _ DiskProxy global: #Smalltalk selector: #yourself\\n\\t\\t\\targs: #().\\n\\trefStrm replace: self with: dp.\\n\\t^ dp! !\\n\\n!SystemDictionary methodsFor: 'objects from disk' stamp: 'tk 3/7/2000 18:40'!\\nstoreDataOn: aDataStream\\n\\t\\\"I don't get stored. Use a DiskProxy\\\"\\n\\n\\tself error: 'use a DiskProxy to store me'! !\\n\\n\\n!SystemDictionary methodsFor: 'printing' stamp: 'sma 6/1/2000 09:53'!\\nprintElementsOn: aStream\\n\\taStream nextPutAll:'(lots of globals)'! !\\n\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:15'!\\nallClasses \\n\\t\\\"Return all the class defines in the Smalltalk SystemDictionary\\\"\\n\\t\\\"Smalltalk allClasses\\\"\\n\\n\\t^ self classNames collect: [:name | self at: name]! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:18'!\\nallClassesDo: aBlock\\n\\t\\\"Evaluate the argument, aBlock, for each class in the system.\\\"\\n\\n\\t(self classNames collect: [:name | self at: name]) do: aBlock! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'al 2/23/2006 21:39'!\\nallTraits\\n\\t\\\"Return all traits defined in the Smalltalk SystemDictionary\\\"\\n\\n\\t^ self traitNames collect: [:each | self at: each]! !\\n\\n!SystemDictionary methodsFor: 'retrieving' stamp: 'sd 9/29/2004 18:17'!\\npoolUsers\\n\\t\\\"Answer a dictionary of pool name -> classes that refer to it.\\n\\tAlso includes any globally know dictionaries (such as\\n\\tSmalltalk, Undeclared etc) which although not strictly\\n\\taccurate is potentially useful information\\\"\\n\\t\\\"Smalltalk poolUsers\\\"\\n\\t| poolUsers pool refs |\\n\\tpoolUsers := Dictionary new.\\n\\tself keys\\n\\t\\tdo: [:k | \\\"yes, using isKindOf: is tacky but for reflective code like\\n\\t\\t\\tthis it is very useful. If you really object you can:-\\n\\t\\t\\ta) go boil your head.\\n\\t\\t\\tb) provide a better answer.\\n\\t\\t\\tyour choice.\\\"\\n\\t\\t\\t(((pool := self at: k) isKindOf: Dictionary)\\n\\t\\t\\t\\t\\tor: [pool isKindOf: SharedPool class])\\n\\t\\t\\t\\tifTrue: [refs := self systemNavigation allClasses\\n\\t\\t\\t\\t\\t\\t\\t\\tselect: [:c | c sharedPools identityIncludes: pool]\\n\\t\\t\\t\\t\\t\\t\\t\\tthenCollect: [:c | c name].\\n\\t\\t\\t\\t\\trefs\\n\\t\\t\\t\\t\\t\\tadd: (self systemNavigation\\n\\t\\t\\t\\t\\t\\t\\t\\tallCallsOn: (self associationAt: k)).\\n\\t\\t\\t\\t\\tpoolUsers at: k put: refs]].\\n\\t^ poolUsers! !\\n\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:18'!\\nabandonSources\\n\\t\\\"Smalltalk abandonSources\\\"\\n\\t\\\"Replaces every method by a copy with the 4-byte source\\n\\tpointer \\n\\treplaced by a string of all arg and temp names, followed by its\\n\\tlength. These names can then be used to inform the\\n\\tdecompiler. See stats below\\\"\\n\\t\\\"wod 11/3/1998: zap the organization before rather than after\\n\\tcondensing changes.\\\"\\n\\t| oldCodeString argsAndTemps oldMethods newMethods m bTotal bCount |\\n\\t(self confirm: 'This method will preserve most temp names\\n(up to about 400 characters) while allowing\\nthe sources file to be discarded.\\n-- CAUTION --\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nabandoning source code files, choose Yes.\\nIf you have any doubts, you may choose No\\nto back out with no harm done.')\\n\\t\\t\\t== true\\n\\t\\tifFalse: [^ self inform: 'Okay - no harm done'].\\n\\tself forgetDoIts.\\n\\toldMethods := OrderedCollection new: CompiledMethod instanceCount.\\n\\tnewMethods := OrderedCollection new: CompiledMethod instanceCount.\\n\\tbTotal := 0.\\n\\tbCount := 0.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:b | bTotal := bTotal + 1].\\n\\t'Saving temp names for better decompilation...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: bTotal\\n\\t\\tduring: [:bar | self systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:cl | \\n\\t\\t\\t\\t\\t\\\"for test: (Array with: Arc with: Arc class) do:\\\"\\n\\t\\t\\t\\t\\tbar value: (bCount := bCount + 1).\\n\\t\\t\\t\\t\\tcl selectors\\n\\t\\t\\t\\t\\t\\tdo: [:selector | \\n\\t\\t\\t\\t\\t\\t\\tm := cl compiledMethodAt: selector.\\n\\t\\t\\t\\t\\t\\t\\tm fileIndex > 0\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [oldCodeString := cl sourceCodeAt: selector.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\targsAndTemps := (cl compilerClass new\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparse: oldCodeString\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tin: cl\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnotifying: nil) tempNames.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\toldMethods addLast: m.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tnewMethods\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddLast: (m copyWithTempNames: argsAndTemps)]]]].\\n\\toldMethods asArray elementsExchangeIdentityWith: newMethods asArray.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:b | b zapOrganization].\\n\\tself condenseChanges.\\n\\tPreferences disable: #warnIfNoSourcesFile! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:18'!\\nabandonTempNames\\n\\t\\\"Replaces every method by a copy with no source pointer or\\n\\tencoded temp names.\\\"\\n\\t\\\"Smalltalk abandonTempNames\\\"\\n\\t| continue oldMethods newMethods n m |\\n\\tcontinue := self confirm: '-- CAUTION --\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nabandoning all source code, hit Yes.\\nIf you have any doubts, hit No,\\nto back out with no harm done.'.\\n\\tcontinue\\n\\t\\tifFalse: [^ self inform: 'Okay - no harm done'].\\n\\tself forgetDoIts; garbageCollect.\\n\\toldMethods := OrderedCollection new.\\n\\tnewMethods := OrderedCollection new.\\n\\tn := 0.\\n\\t'Removing temp names to save space...'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: CompiledMethod instanceCount\\n\\t\\tduring: [:bar | self systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:cl | cl selectors\\n\\t\\t\\t\\t\\t\\tdo: [:sel | \\n\\t\\t\\t\\t\\t\\t\\tbar value: (n := n + 1).\\n\\t\\t\\t\\t\\t\\t\\tm := cl compiledMethodAt: sel.\\n\\t\\t\\t\\t\\t\\t\\toldMethods addLast: m.\\n\\t\\t\\t\\t\\t\\t\\tnewMethods\\n\\t\\t\\t\\t\\t\\t\\t\\taddLast: (m copyWithTrailerBytes: #(0 ))]]].\\n\\toldMethods asArray elementsExchangeIdentityWith: newMethods asArray.\\n\\tSmalltalkImage current closeSourceFiles.\\n\\tself flag: #shouldUseAEnsureBlockToBeSureThatTheFileIsClosed.\\n\\t\\\"sd: 17 April 2003\\\"\\n\\tPreferences disable: #warnIfNoChangesFile.\\n\\tPreferences disable: #warnIfNoSourcesFile! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'di 3/3/2001 08:31'!\\ncleanUpUndoCommands\\n\\t\\\"Smalltalk cleanUpUndoCommands\\\" \\\"<== print this to get classes involved\\\"\\n\\n\\t| classes i p |\\n\\tclasses _ Bag new.\\n\\t'Ferreting out obsolete undo commands'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0 to: Morph withAllSubclasses size\\n\\t\\tduring:\\n\\t[:bar | i _ 0.\\n\\tMorph withAllSubclassesDo:\\n\\t\\t[:c | bar value: (i _ i+1).\\n\\t\\tc allInstancesDo:\\n\\t\\t\\t[:m | (p _ m otherProperties) ifNotNil:\\n\\t\\t\\t\\t[p keys do:\\n\\t\\t\\t\\t\\t[:k | (p at: k) class == Command ifTrue:\\n\\t\\t\\t\\t\\t\\t[classes add: c name.\\n\\t\\t\\t\\t\\t\\tm removeProperty: k]]]]]].\\n\\t^ classes! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:40'!\\ncomputeImageSegmentation\\n\\t\\\"Smalltalk computeImageSegmentation\\\"\\n\\t\\\"Here's how the segmentation works:\\n\\tFor each partition, we collect the classes involved, and also all\\n\\tmessages no longer used in the absence of this partition. We\\n\\tstart by computing a 'Miscellaneous' segment of all the\\n\\tunused classes in the system as is.\\\"\\n\\t| partitions unusedCandM newClasses expandedCandM |\\n\\tpartitions := Dictionary new.\\n\\tunusedCandM := self unusedClassesAndMethodsWithout: {{}. {}}.\\n\\tpartitions at: 'Miscellaneous' put: unusedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'VMConstruction-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'VMConstruction' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'ST80-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'ST80' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Morphic-Games')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Games' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Morphic-Remote')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Nebraska' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | ((SystemOrganization categoriesMatching: 'Network-*')\\n\\t\\t\\t\\t\\t\\tcopyWithoutAll: #('Network-Kernel' 'Network-Url' 'Network-Protocols' 'Network-ObjectSocket' ))\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := Smalltalk unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Network' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon3D-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Balloon3D' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'FFI-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'FFI' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Genie-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Genie' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Speech-*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Speech' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | #('Morphic-Components' )\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses copyWithoutAll: #(#ComponentLikeModel ).\\n\\texpandedCandM := Smalltalk unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Components' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | #('Sound-Scores' 'Sound-Interface' )\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses , #(#WaveletCodec #Sonogram #FWT #AIFFFileReader ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Sound' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | ((SystemOrganization categoriesMatching: 'Tools-*')\\n\\t\\t\\t\\t\\t\\tcopyWithout: 'Tools-Menus')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses copyWithoutAll: #(#Debugger #Inspector #ContextVariablesInspector #SyntaxError #ChangeSet #ChangeRecord #ClassChangeRecord #ChangeList #VersionsBrowser ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Tools' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon-MMFlash*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\tnewClasses := newClasses , #(#ADPCMCodec ).\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'Flash' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Balloon-TrueType*')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'TrueType' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\tnewClasses := Array\\n\\t\\t\\t\\tstreamContents: [:s | (SystemOrganization categoriesMatching: 'Graphics-Files')\\n\\t\\t\\t\\t\\t\\tdo: [:cat | (SystemOrganization superclassOrder: cat)\\n\\t\\t\\t\\t\\t\\t\\t\\tdo: [:c | s nextPut: c name]]].\\n\\texpandedCandM := self unusedClassesAndMethodsWithout: {unusedCandM first asArray , newClasses. unusedCandM second}.\\n\\tpartitions at: 'GraphicFiles' put: {(expandedCandM first copyWithoutAll: unusedCandM first) addAll: newClasses;\\n\\t\\t\\t yourself. expandedCandM second copyWithoutAll: unusedCandM second}.\\n\\tunusedCandM := expandedCandM.\\n\\t#(#AliceConstants 'Balloon3D' #B3DEngineConstants 'Balloon3D' #WonderlandConstants 'Balloon3D' #FFIConstants 'FFI' #KlattResonatorIndices 'Speech' )\\n\\t\\tpairsDo: [:poolName :part | (partitions at: part) first add: poolName].\\n\\tpartitions\\n\\t\\tkeysDo: [:k | k = 'Miscellaneous'\\n\\t\\t\\t\\tifFalse: [(partitions at: 'Miscellaneous') first removeAllFoundIn: (partitions at: k) first]].\\n\\t^ partitions! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sma 6/18/2000 12:32'!\\ndiscardDiscards\\n\\t\\\"Discard all discard* methods - including this one.\\\"\\n\\n\\t(self class selectors select: [:each | each beginsWith: 'discard']) \\n\\t\\tdo: [:each | self class removeSelector: each].\\n\\t#(lastRemoval majorShrink zapMVCprojects)\\n\\t\\tdo: [:each | self class removeSelector: each]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:20'!\\ndiscardFFI\\n\\t\\\"Discard the complete foreign function interface.\\n\\tNOTE: Recreates specialObjectsArray to prevent obsolete\\n\\treferences. Has to specially remove external structure\\n\\thierarchy before ExternalType\\\"\\n\\tself\\n\\t\\tat: #ExternalStructure\\n\\t\\tifPresent: [:cls | (ChangeSet superclassOrder: cls withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\tSystemOrganization removeCategoriesMatching: 'FFI-*'.\\n\\tself recreateSpecialObjectsArray.\\n\\t\\\"Remove obsolete refs\\\"\\n\\tByteArray removeSelector: #asExternalPointer.\\n\\tByteArray removeSelector: #pointerAt:! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/5/2000 01:32'!\\ndiscardFlash\\n\\t\\\"Discard Flash support.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-MMFlash*'\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'RAA 12/17/2000 16:50'!\\ndiscardMIDI\\n\\n\\t\\\"this seems to have gone away\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:21'!\\ndiscardMorphic\\n\\t\\\"Discard Morphic.\\n\\tUpdated for 2.8 TPR\\\"\\n\\t\\\"Smalltalk discardMorphic\\\"\\n\\t\\\"Check that we are in an MVC Project and that there are no\\n\\tMorphic Projects\\n\\tor WorldMorphViews.\\\"\\n\\t| subs |\\n\\tFlaps clobberFlapTabList.\\n\\tself discardFlash.\\n\\tself discardTrueType.\\n\\tsubs := OrderedCollection new.\\n\\tMorph\\n\\t\\tallSubclassesWithLevelDo: [:c :i | subs addFirst: c]\\n\\t\\tstartingLevel: 0.\\n\\tsubs\\n\\t\\tdo: [:c | c removeFromSystem].\\n\\tself removeClassNamed: #CornerRounder.\\n\\tself\\n\\t\\tremoveKey: #BalloonEngineConstants\\n\\t\\tifAbsent: [].\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-*'.\\n\\tSystemOrganization removeCategoriesMatching: 'Morphic-*'.\\n\\tSystemOrganization removeSystemCategory: 'Graphics-Transformations'.\\n\\tSystemOrganization removeSystemCategory: 'ST80-Morphic'.\\n\\tScriptingSystem := nil! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:21'!\\ndiscardMVC\\n\\t\\\"After suitable checks, strip out much of MVC from the system\\\"\\n\\t\\\"Smalltalk discardMVC\\\"\\n\\t| keepers |\\n\\tself flag: #bob.\\n\\t\\\"zapping projects\\\"\\n\\tself isMorphic\\n\\t\\tifFalse: [self inform: 'You must be in a Morphic project to discard MVC.'.\\n\\t\\t\\t^ self].\\n\\t\\\"Check that there are no MVC Projects\\\"\\n\\t(Project allProjects\\n\\t\\t\\tallSatisfy: [:proj | proj isMorphic])\\n\\t\\tifFalse: [(self confirm: 'Would you like a chance to remove your\\nMVC projects in an orderly manner?')\\n\\t\\t\\t\\tifTrue: [^ self].\\n\\t\\t\\t(self confirm: 'If you wish, I can remove all MVC projects,\\nmake this project be the top project, and place\\nall orphaned sub-projects of MVC parents here.\\nWould you like be to do this\\nand proceed to discard all MVC classes?')\\n\\t\\t\\t\\tifTrue: [self zapMVCprojects]\\n\\t\\t\\t\\tifFalse: [^ self]].\\n\\tself reclaimDependents.\\n\\t\\\"Remove old Paragraph classes and View classes.\\\"\\n\\tself\\n\\t\\tat: #Paragraph\\n\\t\\tifPresent: [:paraClass | (ChangeSet superclassOrder: paraClass withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\tself\\n\\t\\tat: #View\\n\\t\\tifPresent: [:viewClass | (ChangeSet superclassOrder: viewClass withAllSubclasses asArray)\\n\\t\\t\\t\\treverseDo: [:c | c removeFromSystem]].\\n\\t\\\"Get rid of ParagraphEditor's ScrollController dependence\\\"\\n\\t#(#markerDelta #viewDelta #scrollAmount #scrollBar #computeMarkerRegion )\\n\\t\\tdo: [:sel | ParagraphEditor removeSelector: sel].\\n\\tParagraphEditor compile: 'updateMarker'.\\n\\t\\\"Reshape to MouseMenuController\\\"\\n\\tCompiler\\n\\t\\tevaluate: (ParagraphEditor definition copyReplaceAll: 'ScrollController' with: 'MouseMenuController').\\n\\t\\\"Get rid of all Controller classes not needed by\\n\\tParagraphEditor and ScreenController\\\"\\n\\tkeepers := TextMorphEditor withAllSuperclasses copyWith: ScreenController.\\n\\t(ChangeSet superclassOrder: Controller withAllSubclasses asArray)\\n\\t\\treverseDo: [:c | (keepers includes: c)\\n\\t\\t\\t\\tifFalse: [c removeFromSystem]].\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Paths'.\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Symbols'.\\n\\tSystemOrganization removeCategoriesMatching: 'ST80-Pluggable Views'.\\n\\tself removeClassNamed: 'FormButtonCache'.\\n\\tself removeClassNamed: 'WindowingTransformation'.\\n\\tself removeClassNamed: 'ControlManager'.\\n\\tself removeClassNamed: 'DisplayTextView'.\\n\\tScheduledControllers := nil.\\n\\tUndeclared removeUnreferencedKeys.\\n\\tSystemOrganization removeEmptyCategories.\\n\\tSymbol rehash! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'cwp 11/8/2002 13:38'!\\ndiscardNetworking\\n\\t\\\"Discard the support for TCP/IP networking.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Network-*'.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'md 7/29/2005 16:00'!\\ndiscardOddsAndEnds\\n\\t\\\"This method throws out lots of classes that are not frequently\\n\\tused.\\\"\\n\\t\\\"Smalltalk discardOddsAndEnds\\\"\\n\\tself organization removeSystemCategory: 'System-Serial Port'.\\n\\tself organization removeSystemCategory: 'ST80-Symbols'.\\n\\tself organization removeSystemCategory: 'Tools-File Contents Browser'.\\n\\tself organization removeSystemCategory: 'System-Compression'.\\n\\tself organization removeSystemCategory: 'Tools-Explorer'.\\n\\tself organization removeSystemCategory: 'System-Digital Signatures'.\\n\\tForm removeSelector: #edit.\\n\\tself\\n\\t\\tat: #FormView\\n\\t\\tifPresent: [:c | c compile: 'defaultControllerClass ^ NoController' classified: 'controller access'].\\n\\tself removeClassNamed: #FormEditorView.\\n\\tself removeClassNamed: #FormEditor.\\n\\tself organization removeSystemCategory: 'ST80-Paths'.\\n\\t\\\"bit editor (remove Form editor first):\\\"\\n\\tForm removeSelector: #bitEdit.\\n\\tForm removeSelector: #bitEditAt:scale:.\\n\\tStrikeFont removeSelector: #edit:.\\n\\tself removeClassNamed: #FormButtonCache.\\n\\tself removeClassNamed: #FormMenuController.\\n\\tself removeClassNamed: #FormMenuView.\\n\\tself removeClassNamed: #BitEditor.\\n\\t\\\"inspector for Dictionaries of Forms\\\"\\n\\tDictionary removeSelector: #inspectFormsWithLabel:.\\n\\tSystemDictionary removeSelector: #viewImageImports.\\n\\tScreenController removeSelector: #viewImageImports.\\n\\tself removeClassNamed: #FormHolderView.\\n\\tself removeClassNamed: #FormInspectView.\\n\\t\\\"experimental updating object viewer:\\\"\\n\\tObject removeSelector: #evaluate:wheneverChangeIn:.\\n\\tself removeClassNamed: #ObjectViewer.\\n\\tself removeClassNamed: #ObjectTracer.\\n\\t\\\"miscellaneous classes:\\\"\\n\\tself removeClassNamed: #Array2D.\\n\\tself removeClassNamed: #DriveACar.\\n\\tself removeClassNamed: #EventRecorder.\\n\\tself removeClassNamed: #FindTheLight.\\n\\tself removeClassNamed: #PluggableTest.\\n\\tself removeClassNamed: #SystemMonitor.\\n\\tself removeClassNamed: #ProtocolBrowser.\\n\\tself removeClassNamed: #ObjectExplorerWrapper.\\n\\tself removeClassNamed: #HierarchyBrowser.\\n\\tself removeClassNamed: #LinkedMessageSet.\\n\\tself removeClassNamed: #ObjectExplorer.\\n\\tself removeClassNamed: #PackageBrowser.\\n\\tself removeClassNamed: #AbstractHierarchicalList.\\n\\tself removeClassNamed: #ChangeList.\\n\\tself removeClassNamed: #VersionsBrowser.\\n\\tself removeClassNamed: #ChangeRecord.\\n\\tself removeClassNamed: #SelectorBrowser.\\n\\tself removeClassNamed: #HtmlFileStream.\\n\\tself removeClassNamed: #CrLfFileStream.\\n\\tself removeClassNamed: #FXGrafPort.\\n\\tself removeClassNamed: #FXBlt.\\n\\tself\\n\\t\\tat: #SampledSound\\n\\t\\tifPresent: [:c | c initialize].\\n\\t#(#Helvetica #Palatino #Courier #ComicBold #ComicPlain )\\n\\t\\tdo: [:k | TextConstants\\n\\t\\t\\t\\tremoveKey: k\\n\\t\\t\\t\\tifAbsent: []].\\n\\tPreferences\\n\\t\\tsetButtonFontTo: (StrikeFont familyName: #NewYork size: 12).\\n\\tPreferences\\n\\t\\tsetFlapsFontTo: (StrikeFont familyName: #NewYork size: 12).\\n\\t#(#GZipConstants #ZipConstants #KlattResonatorIndices )\\n\\t\\tdo: [:k | self\\n\\t\\t\\t\\tremoveKey: k\\n\\t\\t\\t\\tifAbsent: []]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:23'!\\ndiscardSoundSynthesis\\n\\t\\\"Discard the sound synthesis facilities, and the methods and\\n\\tclasses that use it. This also discards MIDI.\\\"\\n\\tself discardMIDI.\\n\\tself discardSpeech.\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Interface'.\\n\\tself\\n\\t\\tat: #GraphMorph\\n\\t\\tifPresent: [:graphMorph | #(#playOnce #readDataFromFile )\\n\\t\\t\\t\\tdo: [:sel | graphMorph removeSelector: sel]].\\n\\tself\\n\\t\\tat: #TrashCanMorph\\n\\t\\tifPresent: [:trashMorph | \\n\\t\\t\\ttrashMorph class removeSelector: #samplesForDelete.\\n\\t\\t\\ttrashMorph class removeSelector: #samplesForMouseEnter.\\n\\t\\t\\ttrashMorph class removeSelector: #samplesForMouseLeave].\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Synthesis'.\\n\\tSystemOrganization removeCategoriesMatching: 'Sound-Scores'! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/3/2000 19:21'!\\ndiscardSpeech\\n\\t\\\"Discard support for speech synthesis\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Speech*'.\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:23'!\\ndiscardSUnit\\n\\t\\\"Smalltalk discardSUnit\\\"\\n\\t| oc |\\n\\toc := OrderedCollection new.\\n\\t(self\\n\\t\\tat: #TestCase\\n\\t\\tifAbsent: [^ self])\\n\\t\\tallSubclassesWithLevelDo: [:c :i | oc addFirst: c]\\n\\t\\tstartingLevel: 0.\\n\\toc\\n\\t\\tdo: [:c | c removeFromSystem].\\n\\tSystemOrganization removeCategoriesMatching: 'SUnit-*'! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'TPR 8/5/2000 01:32'!\\ndiscardTrueType\\n\\t\\\"Discard TrueType support.\\\"\\n\\n\\tSystemOrganization removeCategoriesMatching: 'Balloon-TrueType*'.\\n\\n! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:24'!\\nlastRemoval\\n\\t\\\"Smalltalk lastRemoval\\\"\\n\\t\\\"Some explicit removals - add unwanted methods keeping\\n\\tother methods.\\\"\\n\\t| oldDicts newDicts |\\n\\t#(#abandonSources )\\n\\t\\tdo: [:each | self class removeSelector: each].\\n\\t\\\"Get rid of all unsent methods.\\\"\\n\\t[self removeAllUnSentMessages > 0] whileTrue.\\n\\t\\\"Shrink method dictionaries.\\\"\\n\\tself garbageCollect.\\n\\toldDicts := MethodDictionary allInstances.\\n\\tnewDicts := Array new: oldDicts size.\\n\\toldDicts\\n\\t\\twithIndexDo: [:d :index | newDicts at: index put: d rehashWithoutBecome].\\n\\toldDicts elementsExchangeIdentityWith: newDicts.\\n\\toldDicts := newDicts := nil.\\n\\tself\\n\\t\\tallClassesDo: [:c | c zapOrganization].\\n\\tSystemOrganization := nil.\\n\\tChangeSet current initialize! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'md 2/24/2006 15:42'!\\nmajorShrink\\n\\t\\\"Undertake a major shrinkage of the image.\\n\\tThis method throws out lots of the system that is not needed\\n\\tfor, eg, operation in a hand-held PC. majorShrink produces a\\n\\t999k image in Squeak 2.8\\n\\tSmalltalk majorShrink; abandonSources; lastRemoval\\\"\\n\\t| oldDicts newDicts |\\n\\tself isMorphic\\n\\t\\tifTrue: [^ self error: 'You can only run majorShrink in MVC'].\\n\\tProject current isTopProject\\n\\t\\tifFalse: [^ self error: 'You can only run majorShrink in the top project'].\\n\\t(self confirm: 'All sub-projects will be deleted from this image.\\nYou should already have made a backup copy,\\nor you must save with a different name after shrinking.\\nShall we proceed to discard most of the content in this image?')\\n\\t\\tifFalse: [^ self inform: 'No changes have been made.'].\\n\\t\\\"Remove all projects but the current one. - saves 522k\\\"\\n\\tProjectView\\n\\t\\tallInstancesDo: [:pv | pv controller closeAndUnscheduleNoTerminate].\\n\\tProject current setParent: Project current.\\n\\tMorphWorldView\\n\\t\\tallInstancesDo: [:pv | pv topView controller closeAndUnscheduleNoTerminate].\\n\\tself\\n\\t\\tat: #Wonderland\\n\\t\\tifPresent: [:cls | cls removeActorPrototypesFromSystem].\\n\\tPlayer freeUnreferencedSubclasses.\\n\\tMorphicModel removeUninstantiatedModels.\\n\\tUtilities classPool at: #ScrapsBook put: nil.\\n\\tUtilities zapUpdateDownloader.\\n\\tProjectHistory currentHistory initialize.\\n\\tProject rebuildAllProjects.\\n\\t\\\"Smalltalk discardVMConstruction.\\\"\\n\\t\\\"755k\\\"\\n\\tself discardSoundSynthesis.\\n\\t\\\"544k\\\"\\n\\tself discardOddsAndEnds.\\n\\t\\\"227k\\\"\\n\\tself discardNetworking.\\n\\t\\\"234k\\\"\\n\\t\\\"Smalltalk discard3D.\\\"\\n\\t\\\"407k\\\"\\n\\tself discardFFI.\\n\\t\\\"33k\\\"\\n\\tself discardMorphic.\\n\\t\\\"1372k\\\"\\n\\tSymbol rehash.\\n\\t\\\"40k\\\"\\n\\t\\\"Above by itself saves about 4,238k\\\"\\n\\t\\\"Remove references to a few classes to be deleted, so that they\\n\\twon't leave obsolete versions around.\\\"\\n\\tChangeSet class compile: 'defaultName\\n\\t\\t^ ''Changes'' ' classified: 'initialization'.\\n\\tScreenController removeSelector: #openChangeManager.\\n\\tScreenController removeSelector: #exitProject.\\n\\tScreenController removeSelector: #openProject.\\n\\tScreenController removeSelector: #viewImageImports.\\n\\t\\\"Now delete various other classes..\\\"\\n\\tSystemOrganization removeSystemCategory: 'Graphics-Files'.\\n\\tSystemOrganization removeSystemCategory: 'System-Object Storage'.\\n\\tself removeClassNamed: #ProjectController.\\n\\tself removeClassNamed: #ProjectView.\\n\\t\\\"Smalltalk removeClassNamed: #Project.\\\"\\n\\tself removeClassNamed: #Component1.\\n\\tself removeClassNamed: #FormSetFont.\\n\\tself removeClassNamed: #FontSet.\\n\\tself removeClassNamed: #InstructionPrinter.\\n\\tself removeClassNamed: #ChangeSorter.\\n\\tself removeClassNamed: #DualChangeSorter.\\n\\tself removeClassNamed: #EmphasizedMenu.\\n\\tself removeClassNamed: #MessageTally.\\n\\tStringHolder class removeSelector: #originalWorkspaceContents.\\n\\tCompiledMethod removeSelector: #symbolic.\\n\\tRemoteString removeSelector: #makeNewTextAttVersion.\\n\\tUtilities class removeSelector: #absorbUpdatesFromServer.\\n\\tself removeClassNamed: #PenPointRecorder.\\n\\tself removeClassNamed: #Path.\\n\\tself removeClassNamed: #Base64MimeConverter.\\n\\t\\\"Smalltalk removeClassNamed: #EToySystem. Dont bother - its\\n\\tvery small and used for timestamps etc\\\"\\n\\tself removeClassNamed: #RWBinaryOrTextStream.\\n\\tself removeClassNamed: #AttributedTextStream.\\n\\tself removeClassNamed: #WordNet.\\n\\tself removeClassNamed: #SelectorBrowser.\\n\\tTextStyle\\n\\t\\tallSubInstancesDo: [:ts | ts\\n\\t\\t\\t\\tnewFontArray: (ts fontArray\\n\\t\\t\\t\\t\\t\\tcopyFrom: 1\\n\\t\\t\\t\\t\\t\\tto: (2 min: ts fontArray size))].\\n\\tListParagraph initialize.\\n\\tPopUpMenu initialize.\\n\\tStandardSystemView initialize.\\n\\tChangeSet noChanges.\\n\\tChangeSet classPool\\n\\t\\tat: #AllChangeSets\\n\\t\\tput: (OrderedCollection with: ChangeSet current).\\n\\tSystemDictionary removeSelector: #majorShrink.\\n\\t[self removeAllUnSentMessages > 0]\\n\\t\\twhileTrue: [Smalltalk unusedClasses\\n\\t\\t\\t\\tdo: [:c | (Smalltalk at: c) removeFromSystem]].\\n\\tSystemOrganization removeEmptyCategories.\\n\\tself\\n\\t\\tallClassesDo: [:c | c zapOrganization].\\n\\tself garbageCollect.\\n\\t'Rehashing method dictionaries . . .'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: MethodDictionary instanceCount\\n\\t\\tduring: [:bar | \\n\\t\\t\\toldDicts := MethodDictionary allInstances.\\n\\t\\t\\tnewDicts := Array new: oldDicts size.\\n\\t\\t\\toldDicts\\n\\t\\t\\t\\twithIndexDo: [:d :index | \\n\\t\\t\\t\\t\\tbar value: index.\\n\\t\\t\\t\\t\\tnewDicts at: index put: d rehashWithoutBecome].\\n\\t\\t\\toldDicts elementsExchangeIdentityWith: newDicts].\\n\\toldDicts := newDicts := nil.\\n\\tProject rebuildAllProjects.\\n\\tChangeSet current initialize.\\n\\t\\\"seems to take more than one try to gc all the weak refs in\\n\\tSymbolTable \\\"\\n\\t3\\n\\t\\ttimesRepeat: [self garbageCollect.\\n\\t\\t\\tSymbol compactSymbolTable]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'nk 4/28/2004 10:24'!\\npresumedSentMessages | sent |\\n\\\"Smalltalk presumedSentMessages\\\"\\n\\n\\t\\\"The following should be preserved for doIts, etc\\\"\\n\\tsent _ IdentitySet new.\\n\\t#( rehashWithoutBecome compactSymbolTable rebuildAllProjects\\n\\t\\tbrowseAllSelect: lastRemoval\\n\\t\\tscrollBarValue: vScrollBarValue: scrollBarMenuButtonPressed: \\n\\t\\twithSelectionFrom: to: removeClassNamed:\\n\\t\\tdragon: hilberts: mandala: web test3 factorial tinyBenchmarks benchFib\\n\\t\\tnewDepth: restoreAfter: forgetDoIts zapAllMethods obsoleteClasses\\n\\t\\tremoveAllUnSentMessages abandonSources removeUnreferencedKeys\\n\\t\\treclaimDependents zapOrganization condenseChanges browseObsoleteReferences\\n\\t\\tsubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:\\n\\t\\tmethodsFor:stamp: methodsFor:stamp:prior: instanceVariableNames:\\n\\t\\tstartTimerInterruptWatcher unusedClasses) do:\\n\\t\\t[:sel | sent add: sel].\\n\\t\\\"The following may be sent by perform: in dispatchOnChar...\\\"\\n\\t(ParagraphEditor classPool at: #CmdActions) asSet do:\\n\\t\\t[:sel | sent add: sel].\\n\\t(ParagraphEditor classPool at: #ShiftCmdActions) asSet do:\\n\\t\\t[:sel | sent add: sel].\\n\\t^ sent! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'nk 4/28/2004 10:24'!\\nremoveAllUnSentMessages\\n\\t\\\"Smalltalk removeAllUnSentMessages\\\"\\n\\t\\\"[Smalltalk unusedClasses do: [:c | (Smalltalk at: c) removeFromSystem]. \\n\\tSmalltalk removeAllUnSentMessages > 0] whileTrue.\\\"\\n\\t\\\"Remove all implementations of unsent messages.\\\"\\n\\t| sels n |\\n\\tsels _ self systemNavigation allUnSentMessages.\\n\\t\\\"The following should be preserved for doIts, etc\\\"\\n\\t\\\"needed even after #majorShrink is pulled\\\"\\n\\t#(#rehashWithoutBecome #compactSymbolTable #rebuildAllProjects #browseAllSelect: #lastRemoval #scrollBarValue: vScrollBarValue: #scrollBarMenuButtonPressed: #withSelectionFrom: #to: #removeClassNamed: #dragon: #hilberts: #mandala: #web #test3 #factorial #tinyBenchmarks #benchFib #newDepth: #restoreAfter: #forgetDoIts #zapAllMethods #obsoleteClasses #removeAllUnSentMessages #abandonSources #removeUnreferencedKeys #reclaimDependents #zapOrganization #condenseChanges #browseObsoleteReferences #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: #methodsFor:stamp: #methodsFor:stamp:prior: #instanceVariableNames: #startTimerInterruptWatcher #unusedClasses )\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\t\\\"The following may be sent by perform: in dispatchOnChar...\\\"\\n\\t(ParagraphEditor classPool at: #CmdActions) asSet\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\t(ParagraphEditor classPool at: #ShiftCmdActions) asSet\\n\\t\\tdo: [:sel | sels\\n\\t\\t\\t\\tremove: sel\\n\\t\\t\\t\\tifAbsent: []].\\n\\tsels size = 0\\n\\t\\tifTrue: [^ 0].\\n\\tn _ 0.\\n\\tself systemNavigation\\n\\t\\tallBehaviorsDo: [:x | n _ n + 1].\\n\\t'Removing ' , sels size printString , ' messages . . .'\\n\\t\\tdisplayProgressAt: Sensor cursorPoint\\n\\t\\tfrom: 0\\n\\t\\tto: n\\n\\t\\tduring: [:bar | \\n\\t\\t\\tn _ 0.\\n\\t\\t\\tself systemNavigation\\n\\t\\t\\t\\tallBehaviorsDo: [:class | \\n\\t\\t\\t\\t\\tbar value: (n _ n + 1).\\n\\t\\t\\t\\t\\tsels\\n\\t\\t\\t\\t\\t\\tdo: [:sel | class basicRemoveSelector: sel]]].\\n\\t^ sels size! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:26'!\\nremoveNormalCruft\\n\\t\\\"Remove various graphics, uniclasses, references. Caution: see\\n\\tcomment at bottom of method\\\"\\n\\t\\\"Smalltalk removeNormalCruft\\\"\\n\\tScriptingSystem stripGraphicsForExternalRelease.\\n\\tScriptingSystem spaceReclaimed.\\n\\tReferences keys\\n\\t\\tdo: [:k | References removeKey: k].\\n\\tself classNames\\n\\t\\tdo: [:cName | #('Player' 'CardPlayer' 'Component' 'WonderlandActor' 'MorphicModel' 'PlayWithMe' )\\n\\t\\t\\t\\tdo: [:superName | ((cName ~= superName\\n\\t\\t\\t\\t\\t\\t\\t\\tand: [cName beginsWith: superName])\\n\\t\\t\\t\\t\\t\\t\\tand: [(cName allButFirst: superName size)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tallSatisfy: [:ch | ch isDigit]])\\n\\t\\t\\t\\t\\t\\tifTrue: [self removeClassNamed: cName]]].\\n\\tself\\n\\t\\tat: #Wonderland\\n\\t\\tifPresent: [:cls | cls removeActorPrototypesFromSystem].\\n\\tChangeSet current clear\\n\\t\\\"Caution: if any worlds in the image happen to have uniclass\\n\\tplayers associated with them, running this method would\\n\\tlikely compromise their functioning and could cause errors,\\n\\tespecially if the uniclass player of the current world had any\\n\\tscripts set to ticking. If that happens to you somehow, you will\\n\\tprobably want to find a way to reset the offending world's\\n\\tplayer to be an UnscriptedCardPlayer, or perhaps nil\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 9/29/2004 18:26'!\\nremoveSelector: descriptor \\n\\t\\\"Safely remove a selector from a class (or metaclass). If the\\n\\tclass or the method doesn't exist anymore, never mind and\\n\\tanswer nil.\\n\\tThis method should be used instead of 'Class removeSelector:\\n\\t#method' to omit global class references.\\\"\\n\\t| class sel |\\n\\tclass := self\\n\\t\\t\\t\\tat: descriptor first\\n\\t\\t\\t\\tifAbsent: [^ nil].\\n\\t(descriptor size > 2\\n\\t\\t\\tand: [descriptor second == #class])\\n\\t\\tifTrue: [class := class class.\\n\\t\\t\\tsel := descriptor third]\\n\\t\\tifFalse: [sel := descriptor second].\\n\\t^ class removeSelector: sel! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'di 2/25/2001 22:34'!\\nreportClassAndMethodRemovalsFor: collectionOfClassNames\\n\\t| initialClassesAndMethods finalClassesAndMethods |\\n\\t\\\"Smalltalk reportClassAndMethodRemovalsFor: #(Celeste Scamper MailMessage)\\\"\\n\\n\\tinitialClassesAndMethods _ self unusedClassesAndMethodsWithout: {{}. {}}.\\n\\tfinalClassesAndMethods _ self unusedClassesAndMethodsWithout: {collectionOfClassNames. {}}.\\n\\t^ {finalClassesAndMethods first copyWithoutAll: initialClassesAndMethods first.\\n\\t\\tfinalClassesAndMethods second copyWithoutAll: initialClassesAndMethods second}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'sd 4/29/2003 19:06'!\\nunusedClasses\\n\\t\\\"Enumerates all classes in the system and returns a list of those that are \\n\\tapparently unused. A class is considered in use if it (a) has subclasses \\n\\tor (b) is referred to by some method or (c) has its name in use as a \\n\\tliteral. \\\"\\n\\t\\\"Smalltalk unusedClasses asSortedCollection\\\"\\n\\t^ self systemNavigation allUnusedClassesWithout: {{}. {}}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'edc 11/8/2005 10:11'!\\nunusedClassesAndMethodsWithout: classesAndMessagesPair \\n\\t\\\"Accepts and returns a pair: {set of class names. set of selectors}. \\n\\tIt is expected these results will be diff'd with the normally unused \\n\\tresults. \\\"\\n\\t| classRemovals messageRemovals nClasses nMessages |\\n\\t(classRemovals _ IdentitySet new) addAll: classesAndMessagesPair first.\\n\\t(messageRemovals _ IdentitySet new) addAll: classesAndMessagesPair second.\\n\\tnClasses _ nMessages _ -1.\\n\\t[\\\"As long as we keep making progress...\\\"\\n\\tclassRemovals size > nClasses\\n\\t\\tor: [messageRemovals size > nMessages]]\\n\\t\\twhileTrue: [\\\"...keep trying for bigger sets of unused classes and selectors.\\\"\\n\\t\\t\\tnClasses _ classRemovals size.\\n\\t\\t\\tnMessages _ messageRemovals size.\\n\\t\\t\\tUtilities\\n\\t\\t\\t\\tinformUser: 'Iterating removals '\\n\\t\\t\\t\\t\\t\\t, (classesAndMessagesPair first isEmpty\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: ['for baseline...']\\n\\t\\t\\t\\t\\t\\t\\t\\tifFalse: ['for ' , classesAndMessagesPair first first , ' etc...']) , Character cr asString , nClasses printString , ' classes, ' , nMessages printString , ' messages.\\n|\\n|'\\n\\t\\t\\t\\tduring: [\\\"spacers move menu off cursor\\\"\\n\\t\\t\\t\\t\\tclassRemovals\\n\\t\\t\\t\\t\\t\\taddAll: (self systemNavigation allUnusedClassesWithout: {classRemovals. messageRemovals}).\\n\\t\\t\\t\\t\\tmessageRemovals\\n\\t\\t\\t\\t\\t\\taddAll: (self systemNavigation allUnSentMessagesWithout: {classRemovals. messageRemovals})]].\\n\\t^ {classRemovals. self systemNavigation allUnSentMessagesWithout: {classRemovals. messageRemovals}}! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'dao 10/1/2004 13:51'!\\nwriteImageSegmentsFrom: segmentDictionary withKernel: kernel\\n\\t\\\"segmentDictionary is associates segmentName -> {classNames. methodNames},\\n\\tand kernel is another set of classNames determined to be essential.\\n\\tAdd a partition, 'Secondary' with everything not in partitions and not in the kernel.\\n\\tThen write segments based on this partitioning of classes.\\\"\\n\\n\\t| metas secondary dups segDict overlaps classes n symbolHolder |\\n\\t\\\"First, put all classes that are in no other partition, and not in kernel into a new partition called 'Secondary'. Also remove any classes in kernel from putative partitions.\\\"\\n\\tsecondary _ Smalltalk classNames asIdentitySet.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName |\\n\\t\\tsecondary removeAllFoundIn: (segmentDictionary at: segName) first.\\n\\t\\t(segmentDictionary at: segName) first removeAllFoundIn: kernel].\\n\\tsecondary removeAllFoundIn: kernel.\\n\\tsecondary removeAllFoundIn: #(PseudoContext TranslatedMethod Utilities Preferences OutOfScopeNotification FakeClassPool BlockCannotReturn FormSetFont ExternalSemaphoreTable NetNameResolver ScreenController InterpreterPlugin Command WeakSet).\\n\\tFileDirectory allSubclassesDo: [:c | secondary remove: c name ifAbsent: []].\\n\\tsegmentDictionary at: 'Secondary' put: {secondary. {}}.\\n\\n\\t\\\"Now build segDict giving className -> segName, and report any duplicates.\\\"\\n\\tdups _ Dictionary new.\\n\\tsegDict _ IdentityDictionary new: 3000.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | (segmentDictionary at: segName) first do:\\n\\t\\t\\t[:className |\\n\\t\\t\\t(segDict includesKey: className) ifTrue:\\n\\t\\t\\t\\t[(dups includesKey: className) ifFalse: [dups at: className put: Array new].\\n\\t\\t\\t\\tdups at: className put: (dups at: className) , {segName}].\\n\\t\\t\\tsegDict at: className put: segName]].\\n\\tdups size > 0 ifTrue: [dups inspect. ^ self error: 'Duplicate entries'].\\n\\n\\t\\\"Then for every class in every partition, make sure that neither it\\n\\tnor any of its superclasses are in any other partition. If they are,\\n\\tenter them in a dictionary of overlaps.\\n\\tIf the dictionary is not empty, then stop and report it.\\\"\\n\\toverlaps _ Dictionary new.\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | \\n\\t\\tclasses _ (segmentDictionary at: segName) first asArray collect: [:k | Smalltalk at: k].\\n\\t\\tclasses do:\\n\\t\\t\\t[:c | (c isKindOf: Class) ifTrue:\\n\\t\\t\\t\\t[c withAllSuperclasses do:\\n\\t\\t\\t\\t\\t[:sc | n _ segDict at: sc name ifAbsent: [segName].\\n\\t\\t\\t\\t\\tn ~= segName ifTrue:\\n\\t\\t\\t\\t\\t\\t[n = 'Secondary'\\n\\t\\t\\t\\t\\t\\t\\tifTrue: [(segmentDictionary at: 'Secondary') first\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tremove: sc name ifAbsent: []]\\n\\t\\t\\t\\t\\t\\t\\tifFalse: [overlaps at: c name put: \\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t(c withAllSuperclasses collect: [:cc | segDict associationAt: cc name ifAbsent: [cc name -> 'Kernel']])]]]]]].\\n\\toverlaps size > 0 ifTrue: [overlaps inspect. ^ self error: 'Superclasses in separate segments'].\\n\\n\\t\\\"If there are no overlaps, then proceed to write the partitioned classes.\\\"\\n\\tsymbolHolder _ Symbol allInstances.\\t\\\"Hold onto Symbols with strong pointers, \\n\\t\\tso they will be in outPointers\\\"\\n\\tsegmentDictionary keysDo:\\n\\t\\t[:segName | Utilities informUser: segName during:\\n\\t\\t\\t[classes _ (segmentDictionary at: segName) first asArray collect: [:k | Smalltalk at: k].\\n\\t\\t\\tmetas _ classes select: [:c | c isKindOf: Class] thenCollect: [:c | c class].\\n\\t\\t\\t(ImageSegment new copyFromRoots: classes , metas sizeHint: 0) extract; \\n\\t\\t\\t\\t\\twriteToFile: segName]].\\n\\tsymbolHolder. \\\"Keep compiler for getting uppity.\\\"! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'ar 9/27/2005 20:12'!\\nzapAllOtherProjects \\n\\t\\\"Smalltalk zapAllOtherProjects\\\"\\n\\\"Note: as of this writing, the only reliable way to get rid of all but the current project is te execute the following, one line at a time...\\n\\t\\tSmalltalk zapAllOtherProjects.\\n\\t\\tProjectHistory currentHistory initialize.\\n\\t\\tSmalltalk garbageCollect.\\n\\t\\tProject rebuildAllProjects.\\n\\\"\\n\\n\\t\\n\\tProject allInstancesDo: [:p | p setParent: nil].\\n\\tProject current setParent: Project current.\\n\\tProject current isMorphic ifTrue: [ScheduledControllers := nil].\\n\\tTheWorldMenu allInstancesDo: [:m | 1 to: m class instSize do: [:i | m instVarAt: i put: nil]].\\n\\tChangeSet classPool at: #AllChangeSets put: nil.\\n\\tProject classPool at: #AllProjects put: nil.\\n\\tProjectHistory currentHistory initialize.\\n\\tChangeSet initialize.\\n\\tProject rebuildAllProjects. \\\"Does a GC\\\"\\n\\tProject allProjects size > 1 ifTrue: [Project allProjects inspect]! !\\n\\n!SystemDictionary methodsFor: 'shrinking' stamp: 'dao 10/1/2004 13:30'!\\nzapMVCprojects\\n\\t\\\"Smalltalk zapMVCprojects\\\"\\n\\t| window |\\n\\n\\tself flag: #bob. \\\"zapping projects\\\"\\n\\n\\tSmalltalk garbageCollect.\\n\\t\\\"So allInstances is precise\\\"\\n\\tProject\\n\\t\\tallSubInstancesDo: [:proj | proj isTopProject\\n\\t\\t\\t\\tifTrue: [proj isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Root project is MVC -- we must become the root\\\"\\n\\t\\t\\t\\t\\t\\t\\tProject current setParent: Project current.]]\\n\\t\\t\\t\\tifFalse: [proj parent isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [proj isMorphic\\n\\t\\t\\t\\t\\t\\t\\t\\tifTrue: [\\\"Remove Morphic projects from MVC \\n\\t\\t\\t\\t\\t\\t\\t\\t\\tviews \\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\\"... and add them back here.\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow _ (SystemWindow labelled: proj name)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodel: proj.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddMorph: (ProjectViewMorph on: proj)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframe: (0 @ 0 corner: 1.0 @ 1.0).\\n\\t\\t\\t\\t\\t\\t\\t\\t\\twindow openInWorld.\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tproj setParent: Project current]].\\n\\t\\t\\t\\t\\tproj isMorphic\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Remove MVC projects from Morphic views\\\"\\n\\t\\t\\t\\t\\t\\t\\tProject deletingProject: proj]]]! !\\n\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:38'!\\naddToShutDownList: aClass\\n\\t\\\"This will add a ref to this class at the BEGINNING of the shutDown list.\\\"\\n\\n\\tself addToShutDownList: aClass after: nil! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'!\\naddToShutDownList: aClass after: predecessor\\n\\n\\tself add: aClass toList: ShutDownList after: predecessor! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:37'!\\naddToStartUpList: aClass\\n\\t\\\"This will add a ref to this class at the END of the startUp list.\\\"\\n\\n\\tself addToStartUpList: aClass after: nil! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'!\\naddToStartUpList: aClass after: predecessor\\n\\n\\tself add: aClass toList: StartUpList after: predecessor! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/19/1999 22:36'!\\nadd: aClass toList: startUpOrShutDownList after: predecessor\\n\\t\\\"Add the name of aClass to the startUp or shutDown list.\\n\\tAdd it after the name of predecessor, or at the end if predecessor is nil.\\\"\\n\\n\\t| name earlierName |\\n\\tname _ aClass name.\\n\\t(self at: name ifAbsent: [nil]) == aClass ifFalse:\\n\\t\\t[self error: name , ' cannot be found in Smalltalk dictionary.'].\\n\\tpredecessor == nil\\n\\t\\tifTrue: [\\\"No-op if alredy in the list.\\\"\\n\\t\\t\\t\\t(startUpOrShutDownList includes: name) ifFalse:\\n\\t\\t\\t\\t\\t[startUpOrShutDownList == StartUpList\\n\\t\\t\\t\\t\\t\\tifTrue: [\\\"Add to end of startUp list\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tstartUpOrShutDownList addLast: name]\\n\\t\\t\\t\\t\\t\\tifFalse: [\\\"Add to front of shutDown list\\\"\\n\\t\\t\\t\\t\\t\\t\\t\\tstartUpOrShutDownList addFirst: name]]]\\n\\t\\tifFalse: [\\\"Add after predecessor, moving it if already there.\\\"\\n\\t\\t\\t\\tearlierName _ predecessor name.\\n\\t\\t\\t\\t(self at: earlierName) == predecessor ifFalse:\\n\\t\\t\\t\\t\\t[self error: earlierName , ' cannot be found in Smalltalk dictionary.'].\\n\\t\\t\\t\\t(startUpOrShutDownList includes: earlierName) ifFalse:\\n\\t\\t\\t\\t\\t[self error: earlierName , ' cannot be found in the list.'].\\n\\t\\t\\t\\tstartUpOrShutDownList remove: name ifAbsent:[].\\n\\t\\t\\t\\tstartUpOrShutDownList add: name after: earlierName]! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'RAA 6/14/2000 17:21'!\\nisMorphic\\n \\\"Answer true if the user interface is running in Morphic rathern than \\n MVC. By convention the gloabl variable World is set to nil when MVC is \\n running. ScheduledControllers could be set to nil when Morphic is \\n running, but this symmetry is not yet in effect.\\\"\\n\\n ^ World ~~ nil \\\"or: [RequestCurrentWorldNotification signal notNil]\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'!\\nprocessShutDownList: quitting\\n\\t\\\"Send #shutDown to each class that needs to wrap up before a snapshot.\\\"\\n\\n\\tself send: #shutDown: toClassesNamedIn: ShutDownList with: quitting.\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'!\\nprocessStartUpList: resuming\\n\\t\\\"Send #startUp to each class that needs to run initialization after a snapshot.\\\"\\n\\n\\tself send: #startUp: toClassesNamedIn: StartUpList with: resuming.\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit'!\\nquitPrimitive\\n\\t\\\"Primitive. Exit to another operating system on the host machine, if one\\n\\texists. All state changes in the object space since the last snapshot are lost.\\n\\tEssential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 113>\\n\\tself primitiveFailed! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'!\\nremoveFromShutDownList: aClass\\n\\n\\tShutDownList remove: aClass name ifAbsent: []! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'!\\nremoveFromStartUpList: aClass\\n\\n\\tStartUpList remove: aClass name ifAbsent: []! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 3/7/2001 01:26'!\\nsend: startUpOrShutDown toClassesNamedIn: startUpOrShutDownList with: argument\\n\\t\\\"Send the message #startUp: or #shutDown: to each class named in the list.\\n\\tThe argument indicates if the system is about to quit (for #shutDown:) or if\\n\\tthe image is resuming (for #startUp:).\\n\\tIf any name cannot be found, then remove it from the list.\\\"\\n\\n\\t| removals class |\\n\\tremovals _ OrderedCollection new.\\n\\tstartUpOrShutDownList do:\\n\\t\\t[:name |\\n\\t\\tclass _ self at: name ifAbsent: [nil].\\n\\t\\tclass == nil\\n\\t\\t\\tifTrue: [removals add: name]\\n\\t\\t\\tifFalse: [class isInMemory ifTrue:\\n\\t\\t\\t\\t\\t\\t[class perform: startUpOrShutDown with: argument]]].\\n\\n\\t\\\"Remove any obsolete entries, but after the iteration\\\"\\n\\tstartUpOrShutDownList removeAll: removals! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 9/30/2003 13:47'!\\nsetGCParameters\\n\\t\\\"Adjust the VM's default GC parameters to avoid premature tenuring.\\\"\\n\\n\\tSmalltalkImage current vmParameterAt: 5 put: 4000. \\\"do an incremental GC after this many allocations\\\"\\n\\tSmalltalkImage current vmParameterAt: 6 put: 2000. \\\"tenure when more than this many objects survive the GC\\\"\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 13:14'!\\nshutDown\\n\\t^ SmalltalkImage current closeSourceFiles! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'gk 2/23/2004 20:51'!\\nshutDownSound\\n\\t\\\"No longer used in the release, but retained for backward compatibility.\\\"\\n\\n\\tSoundService default shutDown\\n! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'JMM 11/21/2000 21:02'!\\nsnapshotEmbeddedPrimitive\\n\\t<primitive: 247>\\n\\t^nil \\\"indicates error writing embedded image file\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 7/22/2000 14:34'!\\nsnapshotPrimitive\\n\\t\\\"Primitive. Write the current state of the object memory on a file in the\\n\\tsame format as the Smalltalk-80 release. The file can later be resumed,\\n\\treturning you to this exact state. Return normally after writing the file.\\n\\tEssential. See Object documentation whatIsAPrimitive.\\\"\\n\\n\\t<primitive: 97>\\n\\t^nil \\\"indicates error writing image file\\\"! !\\n\\n!SystemDictionary methodsFor: 'snapshot and quit' stamp: 'nk 11/12/2003 10:32'!\\nunbindExternalPrimitives\\n\\t\\\"Primitive. Force all external primitives to be looked up again afterwards. Since external primitives that have not found are bound for fast failure this method will force the lookup of all primitives again so that after adding some plugin the primitives may be found.\\\"\\n\\t^ self deprecated: 'Use SmalltalkImage unbindExternalPrimitives'\\n\\t\\tblock: [SmalltalkImage unbindExternalPrimitives].\\n\\t\\\"Do nothing if the primitive fails for compatibility with older VMs\\\"! !\\n\\n\\n!SystemDictionary methodsFor: 'sources, change log'!\\ncopyright\\n\\t\\\"The Smalltalk copyright.\\\"\\n\\n\\t^'Copyright (c) Xerox Corp. 1981, 1982 All rights reserved.\\nCopyright (c) Apple Computer, Inc. 1985-1996 All rights reserved.'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'em 3/31/2005 11:48'!\\ncurrentChangeSetString\\n\\t\\\"Smalltalk currentChangeSetString\\\"\\n\\t^ 'Current Change Set: ' translated, ChangeSet current name! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 9/29/2004 18:27'!\\ncurrentProjectDo: aBlock \\n\\t\\\"So that code can work after removal of Projects\\\"\\n\\tself\\n\\t\\tat: #Project\\n\\t\\tifPresent: [:projClass | aBlock value: projClass current]! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\nexternalizeSources \\n\\t\\\"Write the sources and changes streams onto external files.\\\"\\n \\t\\\"Smalltalk externalizeSources\\\"\\n\\t\\\"the logic of this method is complex because it uses changesName and self changesName\\n\\tmay be this is normal - sd\\\"\\n\\t\\n\\t| sourcesName changesName aFile |\\n\\tsourcesName _ SmalltalkImage current sourcesName.\\n\\t(FileDirectory default fileExists: sourcesName)\\n\\t\\tifTrue: [^ self inform:\\n'Sorry, you must first move or remove the\\nfile named ', sourcesName].\\n\\tchangesName _ SmalltalkImage current changesName.\\n\\t(FileDirectory default fileExists: changesName)\\n\\t\\tifTrue: [^ self inform:\\n'Sorry, you must first move or remove the\\nfile named ', changesName].\\n\\n\\taFile _ FileStream newFileNamed: sourcesName.\\n\\taFile nextPutAll: SourceFiles first originalContents.\\n\\taFile close.\\n\\tself setMacFileInfoOn: sourcesName.\\n\\tSourceFiles at: 1 put: (FileStream readOnlyFileNamed: sourcesName).\\n\\n\\taFile _ FileStream newFileNamed: SmalltalkImage current changesName.\\n\\taFile nextPutAll: SourceFiles last contents.\\n\\taFile close.\\n\\t\\\"On Mac, set the file type and creator (noop on other platforms)\\\"\\n\\tFileDirectory default\\n\\t\\tsetMacFileNamed: SmalltalkImage current changesName\\n\\t\\ttype: 'STch'\\n\\t\\tcreator: 'FAST'.\\n\\tSourceFiles at: 2 put: (FileStream oldFileNamed: changesName).\\n\\n\\tself inform: 'Sources successfully externalized'.\\n! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'ar 2/6/2001 18:42'!\\nforceChangesToDisk\\n\\t\\\"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.\\\"\\n\\n\\t| changesFile |\\n\\tchangesFile _ SourceFiles at: 2.\\n\\t(changesFile isKindOf: FileStream) ifTrue: [\\n\\t\\tchangesFile flush.\\n\\t\\tSecurityManager default hasFileAccess ifTrue:[\\n\\t\\t\\tchangesFile close.\\n\\t\\t\\tchangesFile open: changesFile name forWrite: true].\\n\\t\\tchangesFile setToEnd.\\n\\t].\\n! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\ninternalizeChangeLog \\n\\t\\t\\\"Smalltalk internalizeChangeLog\\\"\\n\\t\\\"Bring the changes file into a memory-resident filestream, for faster access and freedom from external file system. 1/31/96 sw\\\"\\n\\n\\t| reply aName aFile |\\n\\treply _ self confirm: 'CAUTION -- do not undertake this lightly!!\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nthe requested internalization of sources,\\nhit Yes. If you have any doubts, hit No\\nto back out with no harm done.'.\\n\\n\\t(reply == true) ifFalse:\\n\\t\\t[^ self inform: 'Okay - abandoned'].\\n\\n\\taName _ SmalltalkImage current changesName.\\n\\t(aFile _ SourceFiles last) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\tself inform: 'Okay, changes file internalized'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 11/16/2003 12:55'!\\ninternalizeSources \\n\\t\\t\\\"Smalltalk internalizeSources\\\"\\n\\t\\\"Bring the sources and changes files into memory-resident filestreams, for faster access and freedom from file-system interface. 1/29/96 sw\\\"\\n\\n\\t| reply aName aFile |\\n\\treply _ self confirm: 'CAUTION -- do not undertake this lightly!!\\nIf you have backed up your system and\\nare prepared to face the consequences of\\nthe requested internalization of sources,\\nhit Yes. If you have any doubts, hit No\\nto back out with no harm done.'.\\n\\n\\t(reply == true) ifFalse:\\n\\t\\t[^ self inform: 'Okay - abandoned'].\\n\\n\\taName _ SmalltalkImage current sourcesName.\\n\\t(aFile _ SourceFiles first) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 1 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\taName _ SmalltalkImage current changesName.\\n\\t(aFile _ SourceFiles last) == nil ifTrue:\\n\\t\\t[(FileDirectory default fileExists: aName)\\n\\t\\t\\tifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].\\n\\t\\taFile _ FileStream readOnlyFileNamed: aName].\\n\\tSourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).\\n\\n\\tself inform: 'Okay, sources internalized'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'sw 2/3/2000 15:59'!\\nrecover: nCharacters\\n\\t\\\"Schedule an editable text view on the last n characters of changes.\\\"\\n\\tself writeRecentCharacters: nCharacters toFileNamed: 'st80.recent'! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'md 5/16/2006 12:34'!\\nversion\\n\\t\\\"Answer the version of this release.\\\"\\n\\n\\t^SystemVersion current version! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'JMM 4/13/2005 20:35'!\\nwordSize\\n\\t\\\"Answer the size (in bytes) of an object pointer.\\\"\\n\\t\\\"Smalltalk wordSize\\\"\\n\\n\\t^[SmalltalkImage current vmParameterAt: 40] on: Error do: [4]! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'nk 8/21/2004 15:55'!\\nwriteRecentCharacters: nCharacters toFileNamed: aFilename\\n\\t\\\"Schedule an editable text view on the last n characters of changes.\\\"\\n\\t| changes |\\n\\tchanges _ SourceFiles at: 2.\\n\\tchanges setToEnd; skip: nCharacters negated.\\n\\t(StandardFileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit! !\\n\\n!SystemDictionary methodsFor: 'sources, change log' stamp: 'ar 9/27/2005 22:38'!\\nwriteRecentToFile\\n\\t\\\"Smalltalk writeRecentToFile\\\"\\n\\t| numChars aDirectory aFileName |\\n\\taDirectory := FileDirectory default.\\n\\taFileName := Utilities\\n\\t\\t\\t\\tkeyLike: 'squeak-recent.01'\\n\\t\\t\\t\\twithTrailing: '.log'\\n\\t\\t\\t\\tsatisfying: [:aKey | (aDirectory includesKey: aKey) not].\\n\\tnumChars := ChangeSet getRecentLocatorWithPrompt: 'copy logged source as far back as...'.\\n\\tnumChars\\n\\t\\tifNotNil: [self writeRecentCharacters: numChars toFileNamed: aFileName]! !\\n\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 20:36'!\\nclearExternalObjects\\n\\t\\\"Clear the array of objects that have been registered for use in non-Smalltalk code.\\\"\\n\\t\\\"Smalltalk clearExternalObjects\\\"\\n\\n\\tExternalSemaphoreTable clearExternalObjects\\n! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'sd 9/29/2004 18:30'!\\ncompactClassesArray\\n\\t\\\"Smalltalk compactClassesArray\\\"\\n\\t\\\"Return the array of 31 classes whose instances may be\\n\\trepresented compactly\\\"\\n\\t^ self specialObjectsArray at: 29! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 21:01'!\\nexternalObjects\\n\\t\\\"Return an array of objects that have been registered for use in non-Smalltalk code. Smalltalk objects should be referrenced by external code only via indirection through this array, thus allowing the objects to move during compaction. This array can be cleared when the VM re-starts, since variables in external code do not survive snapshots. Note that external code should not attempt to access a Smalltalk object, even via this mechanism, while garbage collection is in progress.\\\"\\n\\t\\\"Smalltalk externalObjects\\\"\\n\\n\\t^ ExternalSemaphoreTable externalObjects\\n! !\\n\\n!SystemDictionary methodsFor: 'special objects'!\\nhasSpecialSelector: aLiteral ifTrueSetByte: aBlock\\n\\n\\t1 to: self specialSelectorSize do:\\n\\t\\t[:index | \\n\\t\\t(self specialSelectorAt: index) == aLiteral\\n\\t\\t\\tifTrue: [aBlock value: index + 16rAF. ^true]].\\n\\t^false! !\\n\\n!SystemDictionary methodsFor: 'special objects' stamp: 'dtl 10/3/2005 05:56'!\\nrecreateSpecialObjectsArray\\n\\t\\\"Smalltalk recreateSpecialObjectsArray\\\"\\n\\t\\\"The Special Objects Array is an array of object pointers used\\n\\tby the\\n\\tSqueak virtual machine. Its contents are critical and\\n\\tunchecked, so don't even think of playing here unless you\\n\\tknow what you are doing.\\\"\\n\\t| newArray |\\n\\tnewArray := Array new: 50.\\n\\t\\\"Nil false and true get used throughout the interpreter\\\"\\n\\tnewArray at: 1 put: nil.\\n\\tnewArray at: 2 put: false.\\n\\tnewArray at: 3 put: true.\\n\\t\\\"This association holds the active process (a ProcessScheduler)\\\"\\n\\tnewArray\\n\\t\\tat: 4\\n\\t\\tput: (self associationAt: #Processor).\\n\\t\\\"Numerous classes below used for type checking and\\n\\tinstantiation\\\"\\n\\tnewArray at: 5 put: Bitmap.\\n\\tnewArray at: 6 put: SmallInteger.\\n\\tnewArray at: 7 put: ByteString.\\n\\tnewArray at: 8 put: Array.\\n\\tnewArray at: 9 put: Smalltalk.\\n\\tnewArray at: 10 put: Float.\\n\\tnewArray at: 11 put: MethodContext.\\n\\tnewArray at: 12 put: BlockContext.\\n\\tnewArray at: 13 put: Point.\\n\\tnewArray at: 14 put: LargePositiveInteger.\\n\\tnewArray at: 15 put: Display.\\n\\tnewArray at: 16 put: Message.\\n\\tnewArray at: 17 put: CompiledMethod.\\n\\tnewArray\\n\\t\\tat: 18\\n\\t\\tput: (self specialObjectsArray at: 18).\\n\\t\\\"(low space Semaphore)\\\"\\n\\tnewArray at: 19 put: Semaphore.\\n\\tnewArray at: 20 put: Character.\\n\\tnewArray at: 21 put: #doesNotUnderstand:.\\n\\tnewArray at: 22 put: #cannotReturn:.\\n\\t\\\"The process that signaled the low space semaphore.\\\"\\n\\tnewArray at: 23 put: nil.\\n\\t\\\"An array of the 32 selectors that are compiled as special\\n\\tbytecodes, paired alternately with the number of arguments\\n\\teach takes.\\\"\\n\\tnewArray at: 24 put: #(#+ 1 #- 1 #< 1 \";\n r = \"{13490630, 1448950}\";\n s = 1;\n }\n );\n r = \"{0, 17583493}\";\n s = 0;\n}"; sepNavIntBoundsRect = "{{0, 0}, {3988, 3.06823e+06}}"; sepNavSelRange = "{1340, 0}"; sepNavVisRange = "{0, 2724}"; }; }; } ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjcCogVM.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ 040F20C212CE0FFB008BA0CB /* UnixOSProcessPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F20C112CE0FFB008BA0CB /* UnixOSProcessPlugin.c */; }; 040F20C812CE1057008BA0CB /* Squeak3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F20C712CE1057008BA0CB /* Squeak3D.c */; }; 040F20CB12CE10AC008BA0CB /* ClipboardExtendedPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F20CA12CE10AC008BA0CB /* ClipboardExtendedPlugin.c */; }; 040F20E312CE1283008BA0CB /* ObjectiveCPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F20E212CE1283008BA0CB /* ObjectiveCPlugin.c */; }; 040F22DB12CE1517008BA0CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 040F22DA12CE1517008BA0CB /* Foundation.framework */; }; 040F22E412CE155C008BA0CB /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 040F22E312CE155C008BA0CB /* OpenGL.framework */; }; 040F22FC12CE1752008BA0CB /* SoundPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F22FB12CE1752008BA0CB /* SoundPlugin.c */; }; 040F230712CE1AE2008BA0CB /* SqueakFFIPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F230612CE1AE2008BA0CB /* SqueakFFIPrims.c */; }; 040F230E12CE1B28008BA0CB /* HostWindowPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 040F230D12CE1B28008BA0CB /* HostWindowPlugin.c */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 9402DD7110CE0E91005C2102 /* SqViewClut.m in Sources */ = {isa = PBXBuildFile; fileRef = 9402DD6F10CE0E91005C2102 /* SqViewClut.m */; }; 9402F2B00F3F9BB900F3D637 /* PDColoredProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9402F2AF0F3F9BB900F3D637 /* PDColoredProgressView.m */; }; 9402F2C60F3F9C5600F3D637 /* drawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 9402F2C50F3F9C5600F3D637 /* drawing.m */; }; 9412CAB30E6C037B00DB8625 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 9412CAB20E6C037B00DB8625 /* Settings.bundle */; }; 9412CAE60E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */; }; 9414422610BC89440088F8AC /* Squeak.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414421E10BC89440088F8AC /* Squeak.icns */; }; 9414422710BC89440088F8AC /* SqueakChanges.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414421F10BC89440088F8AC /* SqueakChanges.icns */; }; 9414422810BC89440088F8AC /* SqueakGeneric.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422010BC89440088F8AC /* SqueakGeneric.icns */; }; 9414422910BC89440088F8AC /* SqueakImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422110BC89440088F8AC /* SqueakImage.icns */; }; 9414422A10BC89440088F8AC /* SqueakPlugin.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422210BC89440088F8AC /* SqueakPlugin.icns */; }; 9414422B10BC89440088F8AC /* SqueakProject.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422310BC89440088F8AC /* SqueakProject.icns */; }; 9414422C10BC89440088F8AC /* SqueakScript.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422410BC89440088F8AC /* SqueakScript.icns */; }; 9414422D10BC89440088F8AC /* SqueakSources.icns in Resources */ = {isa = PBXBuildFile; fileRef = 9414422510BC89440088F8AC /* SqueakSources.icns */; }; 941724440F36624C0031AF33 /* squeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 941724420F36624C0031AF33 /* squeakProxy.m */; }; 941D1C9B0E696FC7005B77B3 /* Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */; }; 9424FF620DDCB1C7009912BF /* sqNamedPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */; }; 9424FF6B0DDCB202009912BF /* sqMacV2Memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; }; 9424FF730DDCB234009912BF /* macintoshextra.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF710DDCB234009912BF /* macintoshextra.c */; }; 9424FF760DDCB271009912BF /* osExports.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF750DDCB271009912BF /* osExports.c */; }; 9427E45612628749002DCA6D /* Squeak72x72.png in Resources */ = {isa = PBXBuildFile; fileRef = 9427E45512628749002DCA6D /* Squeak72x72.png */; }; 9428BA9710BB440800DAD287 /* sqSqueakOSXClipboardAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */; }; 9428BB0610BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */; }; 942ABE6F10AA23E20086D908 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 942ABE6E10AA23E20086D908 /* ApplicationServices.framework */; }; 942F48FE123C1C0C002B05DF /* SqueakUIViewCALayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */; }; 942F48FF123C1C0C002B05DF /* SqueakUIViewOpenGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */; }; 942F75D30E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */; }; 942F76320E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */; }; 943B9B2A1235BDD20056205E /* sqMacHostWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 943B9B281235BDD20056205E /* sqMacHostWindow.m */; }; 944069CF10E6B63200353B27 /* MacMenubarPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */; }; 9452D5E50E044A9D000AD792 /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D80E044A9D000AD792 /* Queue.m */; }; 9452D5E60E044A9D000AD792 /* sqMacV2Time.c in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */; }; 9452D5E70E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */; }; 9452D5E80E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; }; 9452D5E90E044A9D000AD792 /* sqSqueakMainApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */; }; 9452D5EA0E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */; }; 9452D5EB0E044A9D000AD792 /* sqSqueakMainApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */; }; 9452D6030E044CB3000AD792 /* sqSqueakAttributesAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */; }; 9452D6080E044D2F000AD792 /* sqSqueakEventsAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */; }; 945550010DF1BC6A00FB176B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 945550000DF1BC6A00FB176B /* AudioToolbox.framework */; }; 94577FBD10684D5E0020840A /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FBC10684D5E0020840A /* CoreAudio.framework */; }; 94577FBF10684D5E0020840A /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FBE10684D5E0020840A /* CoreLocation.framework */; }; 94577FC510684D7E0020840A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FC410684D7E0020840A /* SystemConfiguration.framework */; }; 94584FDC10F02378001401E7 /* sqMacExtendedClipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */; }; 945851F010F03E60001401E7 /* sqMacExtendedClipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */; }; 9458525610F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */; }; 9458525C10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */; }; 9463943F0E95845000015851 /* squeakSUnitTester.m in Sources */ = {isa = PBXBuildFile; fileRef = 9463943E0E95845000015851 /* squeakSUnitTester.m */; }; 946DA8D310C0C30D00F26F56 /* DropPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 946DA8D210C0C30D00F26F56 /* DropPlugin.c */; }; 946DA91510C0C71100F26F56 /* sqSqueakOSXDropAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */; }; 946DAA0010C0D35500F26F56 /* sqMacUnixExternalPrims.m in Sources */ = {isa = PBXBuildFile; fileRef = 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */; }; 9471D2730E04703B00703D45 /* sqSqueakScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */; }; 9471D2E10E04743F00703D45 /* sqSqueakAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; }; 9478E0340EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */; }; 9478E0600EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */; }; 947E627510AA098300D3B69E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 947E627610AA098300D3B69E /* sqNamedPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */; }; 947E627710AA098300D3B69E /* sqMacV2Memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF670DDCB202009912BF /* sqMacV2Memory.c */; }; 947E627910AA098300D3B69E /* osExports.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF750DDCB271009912BF /* osExports.c */; }; 947E627A10AA098300D3B69E /* sqSqueakScreenAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */; }; 947E627B10AA098300D3B69E /* ADPCMCodecPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */; }; 947E627C10AA098300D3B69E /* B2DPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658E60DDD03FE00358328 /* B2DPlugin.c */; }; 947E627D10AA098300D3B69E /* BitBltPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */; }; 947E627E10AA098300D3B69E /* BMPReadWriterPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */; }; 947E627F10AA098300D3B69E /* DSAPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F00DDD03FE00358328 /* DSAPrims.c */; }; 947E628010AA098300D3B69E /* FFTPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F20DDD03FE00358328 /* FFTPlugin.c */; }; 947E628110AA098300D3B69E /* FilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F40DDD03FE00358328 /* FilePlugin.c */; }; 947E628210AA098300D3B69E /* FloatArrayPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */; }; 947E628310AA098300D3B69E /* GeniePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F80DDD03FE00358328 /* GeniePlugin.c */; }; 947E628510AA098300D3B69E /* JPEGReaderPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */; }; 947E628610AA098300D3B69E /* JPEGReadWriter2Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */; }; 947E628710AA098300D3B69E /* Klatt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659020DDD03FE00358328 /* Klatt.c */; }; 947E628810AA098300D3B69E /* LargeIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659040DDD03FE00358328 /* LargeIntegers.c */; }; 947E628910AA098300D3B69E /* Matrix2x3Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */; }; 947E628A10AA098300D3B69E /* MiscPrimitivePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */; }; 947E628B10AA098300D3B69E /* RePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590C0DDD03FE00358328 /* RePlugin.c */; }; 947E628C10AA098300D3B69E /* SecurityPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */; }; 947E628D10AA098300D3B69E /* SoundCodecPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659120DDD03FE00358328 /* SoundCodecPrims.c */; }; 947E628E10AA098300D3B69E /* SoundGenerationPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */; }; 947E629110AA098300D3B69E /* StarSqueakPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */; }; 947E629210AA098300D3B69E /* UUIDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */; }; 947E629310AA098300D3B69E /* ZipPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591F0DDD03FE00358328 /* ZipPlugin.c */; }; 947E629410AA098300D3B69E /* sqFilePluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */; }; 947E629510AA098300D3B69E /* SurfacePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659490DDD053900358328 /* SurfacePlugin.c */; }; 947E629610AA098300D3B69E /* Error.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659520DDD053900358328 /* Error.c */; }; 947E629710AA098300D3B69E /* jcapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659530DDD053900358328 /* jcapimin.c */; }; 947E629810AA098300D3B69E /* jcapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659540DDD053900358328 /* jcapistd.c */; }; 947E629910AA098300D3B69E /* jccoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659550DDD053900358328 /* jccoefct.c */; }; 947E629A10AA098300D3B69E /* jccolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659560DDD053900358328 /* jccolor.c */; }; 947E629B10AA098300D3B69E /* jcdctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659570DDD053900358328 /* jcdctmgr.c */; }; 947E629C10AA098300D3B69E /* jchuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659580DDD053900358328 /* jchuff.c */; }; 947E629D10AA098300D3B69E /* jcinit.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595A0DDD053900358328 /* jcinit.c */; }; 947E629E10AA098300D3B69E /* jcmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595B0DDD053900358328 /* jcmainct.c */; }; 947E629F10AA098300D3B69E /* jcmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595C0DDD053900358328 /* jcmarker.c */; }; 947E62A010AA098300D3B69E /* jcmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595D0DDD053900358328 /* jcmaster.c */; }; 947E62A110AA098300D3B69E /* jcomapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595E0DDD053900358328 /* jcomapi.c */; }; 947E62A210AA098300D3B69E /* jcparam.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659600DDD053900358328 /* jcparam.c */; }; 947E62A310AA098300D3B69E /* jcphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659610DDD053900358328 /* jcphuff.c */; }; 947E62A410AA098300D3B69E /* jcprepct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659620DDD053900358328 /* jcprepct.c */; }; 947E62A510AA098300D3B69E /* jcsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659630DDD053900358328 /* jcsample.c */; }; 947E62A610AA098300D3B69E /* jctrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659640DDD053900358328 /* jctrans.c */; }; 947E62A710AA098300D3B69E /* jdapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659650DDD053900358328 /* jdapimin.c */; }; 947E62A810AA098300D3B69E /* jdapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659660DDD053900358328 /* jdapistd.c */; }; 947E62A910AA098300D3B69E /* jdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659670DDD053900358328 /* jdatadst.c */; }; 947E62AA10AA098300D3B69E /* jdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659680DDD053900358328 /* jdatasrc.c */; }; 947E62AB10AA098300D3B69E /* jdcoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659690DDD053900358328 /* jdcoefct.c */; }; 947E62AC10AA098300D3B69E /* jdcolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596A0DDD053900358328 /* jdcolor.c */; }; 947E62AD10AA098300D3B69E /* jddctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596C0DDD053900358328 /* jddctmgr.c */; }; 947E62AE10AA098300D3B69E /* jdhuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596D0DDD053900358328 /* jdhuff.c */; }; 947E62AF10AA098300D3B69E /* jdinput.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596F0DDD053900358328 /* jdinput.c */; }; 947E62B010AA098300D3B69E /* jdmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659700DDD053900358328 /* jdmainct.c */; }; 947E62B110AA098300D3B69E /* jdmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659710DDD053900358328 /* jdmarker.c */; }; 947E62B210AA098300D3B69E /* jdmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659720DDD053900358328 /* jdmaster.c */; }; 947E62B310AA098300D3B69E /* jdmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659730DDD053900358328 /* jdmerge.c */; }; 947E62B410AA098300D3B69E /* jdphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659740DDD053900358328 /* jdphuff.c */; }; 947E62B510AA098300D3B69E /* jdpostct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659750DDD053900358328 /* jdpostct.c */; }; 947E62B610AA098300D3B69E /* jdsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659760DDD053900358328 /* jdsample.c */; }; 947E62B710AA098300D3B69E /* jdtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659770DDD053900358328 /* jdtrans.c */; }; 947E62B810AA098300D3B69E /* jerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659780DDD053900358328 /* jerror.c */; }; 947E62B910AA098300D3B69E /* jfdctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597A0DDD053900358328 /* jfdctflt.c */; }; 947E62BA10AA098300D3B69E /* jfdctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597B0DDD053900358328 /* jfdctfst.c */; }; 947E62BB10AA098300D3B69E /* jfdctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597C0DDD053900358328 /* jfdctint.c */; }; 947E62BC10AA098300D3B69E /* jidctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597D0DDD053900358328 /* jidctflt.c */; }; 947E62BD10AA098300D3B69E /* jidctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597E0DDD053900358328 /* jidctfst.c */; }; 947E62BE10AA098300D3B69E /* jidctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597F0DDD053900358328 /* jidctint.c */; }; 947E62BF10AA098300D3B69E /* jidctred.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659800DDD053900358328 /* jidctred.c */; }; 947E62C010AA098300D3B69E /* jmemdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659820DDD053900358328 /* jmemdatadst.c */; }; 947E62C110AA098300D3B69E /* jmemdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659830DDD053900358328 /* jmemdatasrc.c */; }; 947E62C210AA098300D3B69E /* jmemmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659840DDD053900358328 /* jmemmgr.c */; }; 947E62C310AA098300D3B69E /* jmemnobs.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659850DDD053900358328 /* jmemnobs.c */; }; 947E62C410AA098300D3B69E /* jquant1.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598B0DDD053900358328 /* jquant1.c */; }; 947E62C510AA098300D3B69E /* jquant2.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598C0DDD053900358328 /* jquant2.c */; }; 947E62C610AA098300D3B69E /* jutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598D0DDD053900358328 /* jutils.c */; }; 947E62C710AA098300D3B69E /* b3dAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659980DDD053900358328 /* b3dAlloc.c */; }; 947E62C810AA098300D3B69E /* b3dDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599A0DDD053900358328 /* b3dDraw.c */; }; 947E62C910AA098300D3B69E /* b3dInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599B0DDD053900358328 /* b3dInit.c */; }; 947E62CA10AA098300D3B69E /* b3dMain.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599C0DDD053900358328 /* b3dMain.c */; }; 947E62CB10AA098300D3B69E /* b3dRemap.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599D0DDD053900358328 /* b3dRemap.c */; }; 947E62CC10AA098300D3B69E /* sqSoundCodecPluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */; }; 947E62CD10AA098300D3B69E /* chartables.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A290DDD053900358328 /* chartables.c */; }; 947E62CE10AA098300D3B69E /* get.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A2B0DDD053900358328 /* get.c */; }; 947E62CF10AA098300D3B69E /* pcre.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A2E0DDD053900358328 /* pcre.c */; }; 947E62D010AA098300D3B69E /* study.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A340DDD053900358328 /* study.c */; }; 947E62D110AA098300D3B69E /* sqUnixUUID.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */; }; 947E62D210AA098300D3B69E /* sqSqueakMainApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */; }; 947E62D310AA098300D3B69E /* sqSqueakMainApplication+screen.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */; }; 947E62D510AA098300D3B69E /* sqVirtualMachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */; }; 947E62D610AA098300D3B69E /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D80E044A9D000AD792 /* Queue.m */; }; 947E62D710AA098300D3B69E /* sqMacV2Time.c in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */; }; 947E62D810AA098300D3B69E /* sqSqueakFileDirectoryAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */; }; 947E62D910AA098300D3B69E /* sqSqueakFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */; }; 947E62DA10AA098300D3B69E /* sqSqueakMainApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */; }; 947E62DB10AA098300D3B69E /* sqSqueakMainApplication+vmAndImagePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */; }; 947E62DC10AA098300D3B69E /* sqSqueakMainApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */; }; 947E62DD10AA098300D3B69E /* sqSqueakAttributesAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */; }; 947E62DE10AA098300D3B69E /* sqSqueakEventsAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */; }; 947E62DF10AA098300D3B69E /* sqSqueakScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */; }; 947E62E010AA098300D3B69E /* sqSqueakAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */; }; 947E62E110AA098300D3B69E /* sqSqueakVmAndImagePathAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */; }; 947E62E210AA098300D3B69E /* sqSqueakMainApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */; }; 947E62E310AA098300D3B69E /* SocketPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659100DDD03FE00358328 /* SocketPlugin.c */; }; 947E62E410AA098300D3B69E /* sqUnixSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */; }; 947E62E510AA098300D3B69E /* sqSqueakMainApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */; }; 947E62E610AA098300D3B69E /* sqSqueakSoundAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */; }; 947E62E710AA098300D3B69E /* sqSqueakMainApplication+sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */; }; 947E62E810AA098300D3B69E /* sqSqueakInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */; }; 947E62EA10AA098300D3B69E /* squeakSUnitTester.m in Sources */ = {isa = PBXBuildFile; fileRef = 9463943E0E95845000015851 /* squeakSUnitTester.m */; }; 947E62ED10AA098300D3B69E /* sqSqueakSoundCoreAudioAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */; }; 947E62EE10AA098300D3B69E /* sqSqueakSoundCoreAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */; }; 947E62EF10AA098300D3B69E /* squeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 941724420F36624C0031AF33 /* squeakProxy.m */; }; 947E62F410AA098300D3B69E /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 945550000DF1BC6A00FB176B /* AudioToolbox.framework */; }; 947E62F510AA098300D3B69E /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FBC10684D5E0020840A /* CoreAudio.framework */; }; 947E62F710AA098300D3B69E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94577FC410684D7E0020840A /* SystemConfiguration.framework */; }; 947E62FF10AA09C300D3B69E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 947E61C210AA03C300D3B69E /* Cocoa.framework */; }; 947E632410AA0B4E00D3B69E /* dummyFFI.c in Sources */ = {isa = PBXBuildFile; fileRef = 947E21320EB2868A007957D0 /* dummyFFI.c */; }; 947E642D10AA0E9E00D3B69E /* sqMacV2Browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */; }; 947E647B10AA100900D3B69E /* SqueakOSXAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */; }; 947E64AB10AA149F00D3B69E /* sqMacSecurity.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */; }; 947E64CC10AA16FE00D3B69E /* sqSqueakOSXApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */; }; 947E64DE10AA18FE00D3B69E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 947E64DC10AA18FE00D3B69E /* MainMenu.xib */; }; 9484F80210B0D81F0038BDC0 /* iPhone.image in Resources */ = {isa = PBXBuildFile; fileRef = 94A349B50DDCDBE200D1D4A9 /* iPhone.image */; }; 9484F80310B0D81F0038BDC0 /* iPhone.changes in Resources */ = {isa = PBXBuildFile; fileRef = 94638B260EAFB77B00A3F155 /* iPhone.changes */; }; 9484F8D410B0E04E0038BDC0 /* sqMacSecurity.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */; }; 9484F8DB10B0E09B0038BDC0 /* sqiPhoneScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */; }; 9484F8DC10B0E0C60038BDC0 /* sqSqueakIPhoneApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */; }; 9484F8DD10B0E0C70038BDC0 /* sqSqueakIPhoneApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */; }; 9484F8DE10B0E0C90038BDC0 /* sqSqueakIPhoneApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */; }; 9484F8DF10B0E0CB0038BDC0 /* sqSqueakIPhoneApplication+Network.m in Sources */ = {isa = PBXBuildFile; fileRef = 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */; }; 9484F8E010B0E0CE0038BDC0 /* sqSqueakiPhoneApplication+sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */; }; 9484F8E110B0E0CE0038BDC0 /* sqSqueakIPhoneApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */; }; 9484F8E210B0E0D10038BDC0 /* sqSqueakIPhoneFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */; }; 9484F8E310B0E0D30038BDC0 /* sqSqueakIPhoneInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */; }; 9484F8E510B0E0F00038BDC0 /* SqueakNoOGLIPhoneAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */; }; 9484F8E610B0E0FD0038BDC0 /* SqueakUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */; }; 9484F8E710B0E0FE0038BDC0 /* SqueakUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */; }; 9484F8EF10B0E1580038BDC0 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 945550910DF2041100FB176B /* Default.png */; }; 9484F91210B0E25B0038BDC0 /* dummyFFI.c in Sources */ = {isa = PBXBuildFile; fileRef = 947E21320EB2868A007957D0 /* dummyFFI.c */; }; 9484F9AF10B13DA50038BDC0 /* sqMacHostWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */; }; 94883B1C0E0C2937005A4738 /* SocketPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659100DDD03FE00358328 /* SocketPlugin.c */; }; 94883B410E0C2B9C005A4738 /* sqUnixSocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */; }; 948EC3901155312600B08A4F /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */; }; 9492453110BA43AA00E726F5 /* SqueakOSXApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */; }; 9494928411E5178D0019BC29 /* cogit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494927D11E5178D0019BC29 /* cogit.c */; }; 9494928511E5178D0019BC29 /* gcc3x-cointerp.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */; }; 949492C711E51C6B0019BC29 /* sqExternalSemaphores.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */; }; 949492C811E51C6B0019BC29 /* sqHeapMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C511E51C6B0019BC29 /* sqHeapMap.c */; }; 949492C911E51C6B0019BC29 /* sqTicker.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C611E51C6B0019BC29 /* sqTicker.c */; }; 949492CA11E51C6B0019BC29 /* sqExternalSemaphores.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */; }; 949492CB11E51C6B0019BC29 /* sqHeapMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C511E51C6B0019BC29 /* sqHeapMap.c */; }; 949492CC11E51C6B0019BC29 /* sqTicker.c in Sources */ = {isa = PBXBuildFile; fileRef = 949492C611E51C6B0019BC29 /* sqTicker.c */; }; 9494932F11E527180019BC29 /* sqUnixHeartbeat.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */; }; 9494933011E527180019BC29 /* sqUnixThreads.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494932D11E527180019BC29 /* sqUnixThreads.c */; }; 9494933211E527180019BC29 /* sqUnixHeartbeat.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */; }; 9494933311E527180019BC29 /* sqUnixThreads.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494932D11E527180019BC29 /* sqUnixThreads.c */; }; 9494933411E527180019BC29 /* sqUnixVMProfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 9494932E11E527180019BC29 /* sqUnixVMProfile.c */; }; 949493C011E52ADE0019BC29 /* aio.c in Sources */ = {isa = PBXBuildFile; fileRef = 949493BF11E52ADE0019BC29 /* aio.c */; }; 949493C111E52ADE0019BC29 /* aio.c in Sources */ = {isa = PBXBuildFile; fileRef = 949493BF11E52ADE0019BC29 /* aio.c */; }; 94A0E8850DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */; }; 94A0E9840DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */; }; 94A1B0070E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */; }; 94A1B02D0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */; }; 94A1B0320E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */; }; 94A1B21C10B9DE0300C64473 /* keyBoardStrokeDetails.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */; }; 94A3488E0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */; }; 94AB2E570E003692006A79E4 /* sqVirtualMachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */; }; 94B6E9DD10BC777A00333E9E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94B6E9DC10BC777A00333E9E /* Localizable.strings */; }; 94B6E9DE10BC777A00333E9E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94B6E9DC10BC777A00333E9E /* Localizable.strings */; }; 94B9533610E6BD7100DC476A /* MacMenuOS9ToOSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 94B9533410E6BD7100DC476A /* MacMenuOS9ToOSX.m */; }; 94BCABC110AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */; }; 94BCAD1D10AB942300F87527 /* sqSqueakOSXApplication+attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */; }; 94BCAE6910ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */; }; 94BCE78C0DDDF61200F38F31 /* sqUnixUUID.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */; }; 94BD817011C8A58D00556751 /* sqManualSurface.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BD816F11C8A58D00556751 /* sqManualSurface.c */; }; 94BD817311C8A59A00556751 /* sqManualSurface.c in Sources */ = {isa = PBXBuildFile; fileRef = 94BD816F11C8A58D00556751 /* sqManualSurface.c */; }; 94C2068A10AF4F53002F4160 /* sqSqueakOSXNSView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */; }; 94C208F910AF7262002F4160 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94C208F810AF7262002F4160 /* QuartzCore.framework */; }; 94C3682610AFA39A0041953A /* macintoshosxextra.c in Sources */ = {isa = PBXBuildFile; fileRef = 94C3682510AFA39A0041953A /* macintoshosxextra.c */; }; 94C3687810AFA77F0041953A /* sqSqueakOSXApplication+cursor.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */; }; 94C3687D10AFA8300041953A /* sqSqueakCursorAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */; }; 94C3688C10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */; }; 94C36A9410B09EE70041953A /* sqSqueakOSXApplication+events.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */; }; 94C4B83010C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */; }; 94C887FB10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */; }; 94C88BDF10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */; }; 94D16CB010BCF96B00A69A89 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 94D16CAF10BCF96B00A69A89 /* Credits.rtf */; }; 94D2A24C112B8ED000B6E459 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94C208F810AF7262002F4160 /* QuartzCore.framework */; }; 94E659230DDD03FE00358328 /* ADPCMCodecPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */; }; 94E659240DDD03FE00358328 /* B2DPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658E60DDD03FE00358328 /* B2DPlugin.c */; }; 94E659260DDD03FE00358328 /* BitBltPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */; }; 94E659270DDD03FE00358328 /* BMPReadWriterPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */; }; 94E659290DDD03FE00358328 /* DSAPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F00DDD03FE00358328 /* DSAPrims.c */; }; 94E6592A0DDD03FE00358328 /* FFTPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F20DDD03FE00358328 /* FFTPlugin.c */; }; 94E6592B0DDD03FE00358328 /* FilePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F40DDD03FE00358328 /* FilePlugin.c */; }; 94E6592C0DDD03FE00358328 /* FloatArrayPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */; }; 94E6592D0DDD03FE00358328 /* GeniePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658F80DDD03FE00358328 /* GeniePlugin.c */; }; 94E659300DDD03FE00358328 /* JPEGReaderPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */; }; 94E659310DDD03FE00358328 /* JPEGReadWriter2Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */; }; 94E659320DDD03FE00358328 /* Klatt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659020DDD03FE00358328 /* Klatt.c */; }; 94E659330DDD03FE00358328 /* LargeIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659040DDD03FE00358328 /* LargeIntegers.c */; }; 94E659340DDD03FE00358328 /* Matrix2x3Plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */; }; 94E659360DDD03FE00358328 /* MiscPrimitivePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */; }; 94E659370DDD03FE00358328 /* RePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590C0DDD03FE00358328 /* RePlugin.c */; }; 94E659380DDD03FE00358328 /* SecurityPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */; }; 94E6593A0DDD03FE00358328 /* SoundCodecPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659120DDD03FE00358328 /* SoundCodecPrims.c */; }; 94E6593B0DDD03FE00358328 /* SoundGenerationPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */; }; 94E6593E0DDD03FE00358328 /* StarSqueakPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */; }; 94E6593F0DDD03FE00358328 /* UUIDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */; }; 94E659400DDD03FE00358328 /* ZipPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6591F0DDD03FE00358328 /* ZipPlugin.c */; }; 94E659470DDD04FA00358328 /* sqFilePluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */; }; 94E65A350DDD053900358328 /* SurfacePlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659490DDD053900358328 /* SurfacePlugin.c */; }; 94E65A370DDD053900358328 /* Error.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659520DDD053900358328 /* Error.c */; }; 94E65A380DDD053900358328 /* jcapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659530DDD053900358328 /* jcapimin.c */; }; 94E65A390DDD053900358328 /* jcapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659540DDD053900358328 /* jcapistd.c */; }; 94E65A3A0DDD053900358328 /* jccoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659550DDD053900358328 /* jccoefct.c */; }; 94E65A3B0DDD053900358328 /* jccolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659560DDD053900358328 /* jccolor.c */; }; 94E65A3C0DDD053900358328 /* jcdctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659570DDD053900358328 /* jcdctmgr.c */; }; 94E65A3D0DDD053900358328 /* jchuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659580DDD053900358328 /* jchuff.c */; }; 94E65A3E0DDD053900358328 /* jcinit.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595A0DDD053900358328 /* jcinit.c */; }; 94E65A3F0DDD053900358328 /* jcmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595B0DDD053900358328 /* jcmainct.c */; }; 94E65A400DDD053900358328 /* jcmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595C0DDD053900358328 /* jcmarker.c */; }; 94E65A410DDD053900358328 /* jcmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595D0DDD053900358328 /* jcmaster.c */; }; 94E65A420DDD053900358328 /* jcomapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6595E0DDD053900358328 /* jcomapi.c */; }; 94E65A430DDD053900358328 /* jcparam.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659600DDD053900358328 /* jcparam.c */; }; 94E65A440DDD053900358328 /* jcphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659610DDD053900358328 /* jcphuff.c */; }; 94E65A450DDD053900358328 /* jcprepct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659620DDD053900358328 /* jcprepct.c */; }; 94E65A460DDD053900358328 /* jcsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659630DDD053900358328 /* jcsample.c */; }; 94E65A470DDD053900358328 /* jctrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659640DDD053900358328 /* jctrans.c */; }; 94E65A480DDD053900358328 /* jdapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659650DDD053900358328 /* jdapimin.c */; }; 94E65A490DDD053900358328 /* jdapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659660DDD053900358328 /* jdapistd.c */; }; 94E65A4A0DDD053900358328 /* jdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659670DDD053900358328 /* jdatadst.c */; }; 94E65A4B0DDD053900358328 /* jdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659680DDD053900358328 /* jdatasrc.c */; }; 94E65A4C0DDD053900358328 /* jdcoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659690DDD053900358328 /* jdcoefct.c */; }; 94E65A4D0DDD053900358328 /* jdcolor.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596A0DDD053900358328 /* jdcolor.c */; }; 94E65A4E0DDD053900358328 /* jddctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596C0DDD053900358328 /* jddctmgr.c */; }; 94E65A4F0DDD053900358328 /* jdhuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596D0DDD053900358328 /* jdhuff.c */; }; 94E65A500DDD053900358328 /* jdinput.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6596F0DDD053900358328 /* jdinput.c */; }; 94E65A510DDD053900358328 /* jdmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659700DDD053900358328 /* jdmainct.c */; }; 94E65A520DDD053900358328 /* jdmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659710DDD053900358328 /* jdmarker.c */; }; 94E65A530DDD053900358328 /* jdmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659720DDD053900358328 /* jdmaster.c */; }; 94E65A540DDD053900358328 /* jdmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659730DDD053900358328 /* jdmerge.c */; }; 94E65A550DDD053900358328 /* jdphuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659740DDD053900358328 /* jdphuff.c */; }; 94E65A560DDD053900358328 /* jdpostct.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659750DDD053900358328 /* jdpostct.c */; }; 94E65A570DDD053900358328 /* jdsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659760DDD053900358328 /* jdsample.c */; }; 94E65A580DDD053900358328 /* jdtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659770DDD053900358328 /* jdtrans.c */; }; 94E65A590DDD053900358328 /* jerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659780DDD053900358328 /* jerror.c */; }; 94E65A5A0DDD053900358328 /* jfdctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597A0DDD053900358328 /* jfdctflt.c */; }; 94E65A5B0DDD053900358328 /* jfdctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597B0DDD053900358328 /* jfdctfst.c */; }; 94E65A5C0DDD053900358328 /* jfdctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597C0DDD053900358328 /* jfdctint.c */; }; 94E65A5D0DDD053900358328 /* jidctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597D0DDD053900358328 /* jidctflt.c */; }; 94E65A5E0DDD053900358328 /* jidctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597E0DDD053900358328 /* jidctfst.c */; }; 94E65A5F0DDD053900358328 /* jidctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6597F0DDD053900358328 /* jidctint.c */; }; 94E65A600DDD053900358328 /* jidctred.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659800DDD053900358328 /* jidctred.c */; }; 94E65A610DDD053900358328 /* jmemdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659820DDD053900358328 /* jmemdatadst.c */; }; 94E65A620DDD053900358328 /* jmemdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659830DDD053900358328 /* jmemdatasrc.c */; }; 94E65A630DDD053900358328 /* jmemmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659840DDD053900358328 /* jmemmgr.c */; }; 94E65A640DDD053900358328 /* jmemnobs.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659850DDD053900358328 /* jmemnobs.c */; }; 94E65A650DDD053900358328 /* jquant1.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598B0DDD053900358328 /* jquant1.c */; }; 94E65A660DDD053900358328 /* jquant2.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598C0DDD053900358328 /* jquant2.c */; }; 94E65A670DDD053900358328 /* jutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6598D0DDD053900358328 /* jutils.c */; }; 94E65A690DDD053900358328 /* b3dAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659980DDD053900358328 /* b3dAlloc.c */; }; 94E65A6A0DDD053900358328 /* b3dDraw.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599A0DDD053900358328 /* b3dDraw.c */; }; 94E65A6B0DDD053900358328 /* b3dInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599B0DDD053900358328 /* b3dInit.c */; }; 94E65A6C0DDD053900358328 /* b3dMain.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599C0DDD053900358328 /* b3dMain.c */; }; 94E65A6D0DDD053900358328 /* b3dRemap.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E6599D0DDD053900358328 /* b3dRemap.c */; }; 94E65A6F0DDD053900358328 /* sqSoundCodecPluginBasicPrims.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */; }; 94E65AEE0DDD053900358328 /* chartables.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A290DDD053900358328 /* chartables.c */; }; 94E65AEF0DDD053900358328 /* get.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A2B0DDD053900358328 /* get.c */; }; 94E65AF00DDD053900358328 /* pcre.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A2E0DDD053900358328 /* pcre.c */; }; 94E65AF40DDD053900358328 /* study.c in Sources */ = {isa = PBXBuildFile; fileRef = 94E65A340DDD053900358328 /* study.c */; }; 94EF6CC311E55947003BA64D /* gcc3x-interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 9469CEED10BFD8CE002245C2 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.gcc.4_2; fileType = sourcecode.c; isEditable = 1; outputFiles = ( ); }; /* End PBXBuildRule section */ /* Begin PBXFileReference section */ 040F20C112CE0FFB008BA0CB /* UnixOSProcessPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UnixOSProcessPlugin.c; sourceTree = "<group>"; }; 040F20C712CE1057008BA0CB /* Squeak3D.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Squeak3D.c; sourceTree = "<group>"; }; 040F20CA12CE10AC008BA0CB /* ClipboardExtendedPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ClipboardExtendedPlugin.c; sourceTree = "<group>"; }; 040F20E212CE1283008BA0CB /* ObjectiveCPlugin.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = ObjectiveCPlugin.c; sourceTree = "<group>"; }; 040F22DA12CE1517008BA0CB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 040F22E312CE155C008BA0CB /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; }; 040F22FB12CE1752008BA0CB /* SoundPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundPlugin.c; sourceTree = "<group>"; }; 040F230612CE1AE2008BA0CB /* SqueakFFIPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SqueakFFIPrims.c; sourceTree = "<group>"; }; 040F230D12CE1B28008BA0CB /* HostWindowPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = HostWindowPlugin.c; sourceTree = "<group>"; }; 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakNoOGLIPhoneAppDelegate.h; sourceTree = "<group>"; }; 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakNoOGLIPhoneAppDelegate.m; sourceTree = "<group>"; }; 1D6058910D05DD3D006BFB54 /* Squeak.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Squeak.app; sourceTree = BUILT_PRODUCTS_DIR; }; 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = vm/Common/main.m; sourceTree = "<group>"; }; 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqDummyaio.h; sourceTree = "<group>"; }; 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqDummyaio.c; sourceTree = "<group>"; }; 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqViewBitmapConversion.h; path = vm/OSX/SqViewBitmapConversion.h; sourceTree = "<group>"; }; 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqViewBitmapConversion.m; path = vm/OSX/SqViewBitmapConversion.m; sourceTree = "<group>"; }; 9402DD6F10CE0E91005C2102 /* SqViewClut.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqViewClut.m; path = vm/OSX/SqViewClut.m; sourceTree = "<group>"; }; 9402F2AE0F3F9BB900F3D637 /* PDColoredProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDColoredProgressView.h; sourceTree = "<group>"; }; 9402F2AF0F3F9BB900F3D637 /* PDColoredProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDColoredProgressView.m; sourceTree = "<group>"; }; 9402F2C50F3F9C5600F3D637 /* drawing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = drawing.m; sourceTree = "<group>"; }; 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIController.h; sourceTree = "<group>"; }; 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIController.m; sourceTree = "<group>"; }; 9412CAB20E6C037B00DB8625 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; }; 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakInfoPlistInterface.h; path = vm/Common/Classes/sqSqueakInfoPlistInterface.h; sourceTree = "<group>"; }; 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakInfoPlistInterface.m; path = vm/Common/Classes/sqSqueakInfoPlistInterface.m; sourceTree = "<group>"; }; 9414421E10BC89440088F8AC /* Squeak.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Squeak.icns; path = OSX/Squeak.icns; sourceTree = "<group>"; }; 9414421F10BC89440088F8AC /* SqueakChanges.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakChanges.icns; path = OSX/SqueakChanges.icns; sourceTree = "<group>"; }; 9414422010BC89440088F8AC /* SqueakGeneric.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakGeneric.icns; path = OSX/SqueakGeneric.icns; sourceTree = "<group>"; }; 9414422110BC89440088F8AC /* SqueakImage.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakImage.icns; path = OSX/SqueakImage.icns; sourceTree = "<group>"; }; 9414422210BC89440088F8AC /* SqueakPlugin.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakPlugin.icns; path = OSX/SqueakPlugin.icns; sourceTree = "<group>"; }; 9414422310BC89440088F8AC /* SqueakProject.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakProject.icns; path = OSX/SqueakProject.icns; sourceTree = "<group>"; }; 9414422410BC89440088F8AC /* SqueakScript.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakScript.icns; path = OSX/SqueakScript.icns; sourceTree = "<group>"; }; 9414422510BC89440088F8AC /* SqueakSources.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SqueakSources.icns; path = OSX/SqueakSources.icns; sourceTree = "<group>"; }; 941724420F36624C0031AF33 /* squeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = squeakProxy.m; sourceTree = "<group>"; }; 941724430F36624C0031AF33 /* squeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeakProxy.h; sourceTree = "<group>"; }; 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = "<group>"; }; 9424FF5B0DDCB1C7009912BF /* sqGnu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqGnu.h; path = vm/sqGnu.h; sourceTree = "<group>"; }; 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMemoryAccess.h; sourceTree = "<group>"; }; 9424FF5D0DDCB1C7009912BF /* sq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sq.h; sourceTree = "<group>"; }; 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqNamedPrims.c; sourceTree = "<group>"; }; 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqVirtualMachine.c; sourceTree = "<group>"; }; 9424FF610DDCB1C7009912BF /* sqVirtualMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqVirtualMachine.h; sourceTree = "<group>"; }; 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqPlatformSpecific.h; sourceTree = "<group>"; }; 9424FF650DDCB1EF009912BF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; }; 9424FF660DDCB1EF009912BF /* sqConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqConfig.h; sourceTree = "<group>"; }; 9424FF670DDCB202009912BF /* sqMacV2Memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacV2Memory.c; sourceTree = "<group>"; }; 9424FF680DDCB202009912BF /* sqMacV2Memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacV2Memory.h; sourceTree = "<group>"; }; 9424FF710DDCB234009912BF /* macintoshextra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = macintoshextra.c; sourceTree = "<group>"; }; 9424FF720DDCB234009912BF /* macintoshextra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macintoshextra.h; sourceTree = "<group>"; }; 9424FF750DDCB271009912BF /* osExports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = osExports.c; sourceTree = "<group>"; }; 9427E45512628749002DCA6D /* Squeak72x72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Squeak72x72.png; sourceTree = "<group>"; }; 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXClipboardAPI.h; path = vm/OSX/sqSqueakOSXClipboardAPI.h; sourceTree = "<group>"; }; 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXClipboardAPI.m; path = vm/OSX/sqSqueakOSXClipboardAPI.m; sourceTree = "<group>"; }; 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+clipboard.h"; path = "vm/OSX/sqSqueakOSXApplication+clipboard.h"; sourceTree = "<group>"; }; 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+clipboard.m"; path = "vm/OSX/sqSqueakOSXApplication+clipboard.m"; sourceTree = "<group>"; }; 942ABE6E10AA23E20086D908 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; }; 942F48FA123C1C0C002B05DF /* SqueakUIViewCALayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIViewCALayer.h; sourceTree = "<group>"; }; 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIViewCALayer.m; sourceTree = "<group>"; }; 942F48FC123C1C0C002B05DF /* SqueakUIViewOpenGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIViewOpenGL.h; sourceTree = "<group>"; }; 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIViewOpenGL.m; sourceTree = "<group>"; }; 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakVmAndImagePathAPI.h; path = vm/Common/Classes/sqSqueakVmAndImagePathAPI.h; sourceTree = "<group>"; }; 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakVmAndImagePathAPI.m; path = vm/Common/Classes/sqSqueakVmAndImagePathAPI.m; sourceTree = "<group>"; }; 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneApplication.h; sourceTree = "<group>"; }; 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneApplication.m; sourceTree = "<group>"; }; 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+attributes.m"; path = "vm/Common/Classes/sqSqueakMainApplication+attributes.m"; sourceTree = "<group>"; }; 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+attributes.h"; sourceTree = "<group>"; }; 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneFileDirectoryInterface.h; sourceTree = "<group>"; }; 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneFileDirectoryInterface.m; sourceTree = "<group>"; }; 943B9B281235BDD20056205E /* sqMacHostWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqMacHostWindow.m; sourceTree = "<group>"; }; 943B9B291235BDD20056205E /* sqMacHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacHostWindow.h; sourceTree = "<group>"; }; 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MacMenubarPlugin.c; sourceTree = "<group>"; }; 944895AD10F4081300FB3EC8 /* PharoV10.sources */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = PharoV10.sources; path = iPhone/PharoV10.sources; sourceTree = "<group>"; }; 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+Network.h"; sourceTree = "<group>"; }; 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+Network.m"; sourceTree = "<group>"; }; 9452D5D70E044A9D000AD792 /* Queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = vm/Common/Classes/Queue.h; sourceTree = "<group>"; }; 9452D5D80E044A9D000AD792 /* Queue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Queue.m; path = vm/Common/Classes/Queue.m; sourceTree = "<group>"; }; 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqMacV2Time.c; path = vm/Common/Classes/sqMacV2Time.c; sourceTree = "<group>"; }; 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqMacV2Time.h; path = vm/Common/Classes/sqMacV2Time.h; sourceTree = "<group>"; }; 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakFileDirectoryAPI.h; path = vm/Common/Classes/sqSqueakFileDirectoryAPI.h; sourceTree = "<group>"; }; 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakFileDirectoryAPI.m; path = vm/Common/Classes/sqSqueakFileDirectoryAPI.m; sourceTree = "<group>"; }; 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakFileDirectoryInterface.h; path = vm/Common/Classes/sqSqueakFileDirectoryInterface.h; sourceTree = "<group>"; }; 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakFileDirectoryInterface.m; path = vm/Common/Classes/sqSqueakFileDirectoryInterface.m; sourceTree = "<group>"; }; 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakMainApp.m; path = vm/Common/Classes/sqSqueakMainApp.m; sourceTree = "<group>"; }; 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakMainApp.h; path = vm/Common/Classes/sqSqueakMainApp.h; sourceTree = "<group>"; }; 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+vmAndImagePath.h"; path = "vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.h"; sourceTree = "<group>"; }; 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+vmAndImagePath.m"; path = "vm/Common/Classes/sqSqueakMainApplication+vmAndImagePath.m"; sourceTree = "<group>"; }; 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakMainApplication.h; path = vm/Common/Classes/sqSqueakMainApplication.h; sourceTree = "<group>"; }; 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakMainApplication.m; path = vm/Common/Classes/sqSqueakMainApplication.m; sourceTree = "<group>"; }; 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakAttributesAPI.h; path = vm/Common/Classes/sqSqueakAttributesAPI.h; sourceTree = "<group>"; }; 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakAttributesAPI.m; path = vm/Common/Classes/sqSqueakAttributesAPI.m; sourceTree = "<group>"; }; 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakEventsAPI.h; path = vm/Common/Classes/sqSqueakEventsAPI.h; sourceTree = "<group>"; }; 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakEventsAPI.m; path = vm/Common/Classes/sqSqueakEventsAPI.m; sourceTree = "<group>"; }; 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqiPhoneScreenAndWindow.h; sourceTree = "<group>"; }; 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqiPhoneScreenAndWindow.m; sourceTree = "<group>"; }; 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+sound.h"; sourceTree = "<group>"; }; 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakiPhoneApplication+sound.m"; sourceTree = "<group>"; }; 945550000DF1BC6A00FB176B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; }; 945550910DF2041100FB176B /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; }; 94577FBC10684D5E0020840A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; }; 94577FBE10684D5E0020840A /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = /System/Library/Frameworks/CoreLocation.framework; sourceTree = "<absolute>"; }; 94577FC410684D7E0020840A /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; }; 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqMacExtendedClipboard.m; sourceTree = "<group>"; }; 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacExtendedClipboard.h; sourceTree = "<group>"; }; 945851EE10F03E60001401E7 /* sqMacExtendedClipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacExtendedClipboard.h; sourceTree = "<group>"; }; 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqMacExtendedClipboard.m; sourceTree = "<group>"; }; 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneClipboardAPI.h; sourceTree = "<group>"; }; 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneClipboardAPI.m; sourceTree = "<group>"; }; 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+clipboard.h"; sourceTree = "<group>"; }; 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+clipboard.m"; sourceTree = "<group>"; }; 94638B260EAFB77B00A3F155 /* iPhone.changes */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = iPhone.changes; path = iPhone/iPhone.changes; sourceTree = "<group>"; }; 9463943D0E95845000015851 /* squeakSUnitTester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeakSUnitTester.h; sourceTree = "<group>"; }; 9463943E0E95845000015851 /* squeakSUnitTester.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = squeakSUnitTester.m; sourceTree = "<group>"; }; 946DA8D210C0C30D00F26F56 /* DropPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DropPlugin.c; sourceTree = "<group>"; }; 946DA8EF10C0C38600F26F56 /* DropPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DropPlugin.h; sourceTree = "<group>"; }; 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXDropAPI.h; path = vm/OSX/sqSqueakOSXDropAPI.h; sourceTree = "<group>"; }; 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXDropAPI.m; path = vm/OSX/sqSqueakOSXDropAPI.m; sourceTree = "<group>"; }; 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqMacUnixExternalPrims.m; path = vm/OSX/sqMacUnixExternalPrims.m; sourceTree = "<group>"; }; 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakScreenAndWindow.h; path = vm/Common/Classes/sqSqueakScreenAndWindow.h; sourceTree = "<group>"; }; 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakScreenAndWindow.m; path = vm/Common/Classes/sqSqueakScreenAndWindow.m; sourceTree = "<group>"; }; 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakAppDelegate.h; path = vm/Common/Classes/sqSqueakAppDelegate.h; sourceTree = "<group>"; }; 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakAppDelegate.m; path = vm/Common/Classes/sqSqueakAppDelegate.m; sourceTree = "<group>"; }; 9478E0250EC8D957007096A7 /* dummyFFI.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dummyFFI.c; sourceTree = "<group>"; }; 9478E0260EC8D957007096A7 /* dummyFFI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummyFFI.h; sourceTree = "<group>"; }; 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = squeakSUnitTester.h; sourceTree = "<group>"; }; 9478E02B0EC8D957007096A7 /* squeakSUnitTester.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = squeakSUnitTester.m; sourceTree = "<group>"; }; 9478E0320EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakSoundCoreAudioAPI.h; sourceTree = "<group>"; }; 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakSoundCoreAudioAPI.m; sourceTree = "<group>"; }; 9478E05E0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakSoundCoreAudio.h; sourceTree = "<group>"; }; 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakSoundCoreAudio.m; sourceTree = "<group>"; }; 947E20F90EB2826C007957D0 /* sqFFI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqFFI.h; sourceTree = "<group>"; }; 947E21310EB2868A007957D0 /* dummyFFI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummyFFI.h; sourceTree = "<group>"; }; 947E21320EB2868A007957D0 /* dummyFFI.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dummyFFI.c; sourceTree = "<group>"; }; 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakPureObjc_Prefix.pch; sourceTree = "<group>"; }; 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SqueakPureObjc-Info.plist"; sourceTree = "<group>"; }; 947E61C210AA03C300D3B69E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 947E61C410AA03DC00D3B69E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 947E62FC10AA098300D3B69E /* Squeak.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Squeak.app; sourceTree = BUILT_PRODUCTS_DIR; }; 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqMacV2Browser.h; path = vm/OSX/sqMacV2Browser.h; sourceTree = "<group>"; }; 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqMacV2Browser.m; path = vm/OSX/sqMacV2Browser.m; sourceTree = "<group>"; }; 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqueakOSXAppDelegate.h; path = vm/OSX/SqueakOSXAppDelegate.h; sourceTree = "<group>"; }; 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqueakOSXAppDelegate.m; path = vm/OSX/SqueakOSXAppDelegate.m; sourceTree = "<group>"; }; 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXApplication.h; path = vm/OSX/sqSqueakOSXApplication.h; sourceTree = "<group>"; }; 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXApplication.m; path = vm/OSX/sqSqueakOSXApplication.m; sourceTree = "<group>"; }; 947E64DD10AA18FE00D3B69E /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; }; 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixSocket.c; sourceTree = "<group>"; }; 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = "<group>"; }; 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqueakOSXApplication.h; path = vm/OSX/SqueakOSXApplication.h; sourceTree = "<group>"; }; 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SqueakOSXApplication.m; path = vm/OSX/SqueakOSXApplication.m; sourceTree = "<group>"; }; 9494927D11E5178D0019BC29 /* cogit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cogit.c; sourceTree = "<group>"; }; 9494927E11E5178D0019BC29 /* cogit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cogit.h; sourceTree = "<group>"; }; 9494927F11E5178D0019BC29 /* cogmethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cogmethod.h; sourceTree = "<group>"; }; 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "gcc3x-cointerp.c"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = "<none>"; }; 9494928111E5178D0019BC29 /* cointerp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cointerp.h; sourceTree = "<group>"; }; 949492C011E51C6B0019BC29 /* dispdbg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dispdbg.h; sourceTree = "<group>"; }; 949492C111E51C6B0019BC29 /* sqAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqAssert.h; sourceTree = "<group>"; }; 949492C211E51C6B0019BC29 /* sqCogStackAlignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqCogStackAlignment.h; sourceTree = "<group>"; }; 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqExternalSemaphores.c; sourceTree = "<group>"; }; 949492C411E51C6B0019BC29 /* sqAtomicOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqAtomicOps.h; sourceTree = "<group>"; }; 949492C511E51C6B0019BC29 /* sqHeapMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqHeapMap.c; sourceTree = "<group>"; }; 949492C611E51C6B0019BC29 /* sqTicker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqTicker.c; sourceTree = "<group>"; }; 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixHeartbeat.c; sourceTree = "<group>"; }; 9494932D11E527180019BC29 /* sqUnixThreads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixThreads.c; sourceTree = "<group>"; }; 9494932E11E527180019BC29 /* sqUnixVMProfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixVMProfile.c; sourceTree = "<group>"; }; 9494935011E527AB0019BC29 /* sqMemoryFence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMemoryFence.h; sourceTree = "<group>"; }; 949493BF11E52ADE0019BC29 /* aio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aio.c; path = ../../../../unix/vm/aio.c; sourceTree = BUILT_PRODUCTS_DIR; }; 949AD14911E542E8006D6BF4 /* SqueakPureObjc-InfoCOG.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SqueakPureObjc-InfoCOG.plist"; sourceTree = "<group>"; }; 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SqueakUIView.h; sourceTree = "<group>"; }; 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SqueakUIView.m; sourceTree = "<group>"; }; 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+attributes.h"; path = "vm/Common/Classes/sqSqueakMainApplication+attributes.h"; sourceTree = "<group>"; }; 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+attributes.m"; sourceTree = "<group>"; }; 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+imageReadWrite.h"; path = "vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+imageReadWrite.m"; path = "vm/Common/Classes/sqSqueakMainApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+screen.h"; path = "vm/Common/Classes/sqSqueakMainApplication+screen.h"; sourceTree = "<group>"; }; 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+screen.m"; path = "vm/Common/Classes/sqSqueakMainApplication+screen.m"; sourceTree = "<group>"; }; 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+events.h"; path = "vm/Common/Classes/sqSqueakMainApplication+events.h"; sourceTree = "<group>"; }; 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+events.m"; path = "vm/Common/Classes/sqSqueakMainApplication+events.m"; sourceTree = "<group>"; }; 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakSoundAPI.h; path = vm/Common/Classes/sqSqueakSoundAPI.h; sourceTree = "<group>"; }; 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakSoundAPI.m; path = vm/Common/Classes/sqSqueakSoundAPI.m; sourceTree = "<group>"; }; 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+sound.h"; path = "vm/Common/Classes/sqSqueakMainApplication+sound.h"; sourceTree = "<group>"; }; 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+sound.m"; path = "vm/Common/Classes/sqSqueakMainApplication+sound.m"; sourceTree = "<group>"; }; 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyBoardStrokeDetails.h; path = vm/OSX/keyBoardStrokeDetails.h; sourceTree = "<group>"; }; 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = keyBoardStrokeDetails.m; path = vm/OSX/keyBoardStrokeDetails.m; sourceTree = "<group>"; }; 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakScreenAPI.h; path = vm/Common/Classes/sqSqueakScreenAPI.h; sourceTree = "<group>"; }; 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakScreenAPI.m; path = vm/Common/Classes/sqSqueakScreenAPI.m; sourceTree = "<group>"; }; 94A349B50DDCDBE200D1D4A9 /* iPhone.image */ = {isa = PBXFileReference; lastKnownFileType = file; name = iPhone.image; path = iPhone/iPhone.image; sourceTree = "<group>"; }; 94B6E9D910BC775E00333E9E /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = vm/Common/English.lproj/Localizable.strings; sourceTree = "<group>"; }; 94B8F54E10CF677800F0DD6B /* SqViewClut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SqViewClut.h; path = vm/OSX/SqViewClut.h; sourceTree = "<group>"; }; 94B9528510E6B79E00DC476A /* MacMenubarPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacMenubarPlugin.h; sourceTree = "<group>"; }; 94B9533310E6BD7100DC476A /* MacMenuOS9ToOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacMenuOS9ToOSX.h; sourceTree = "<group>"; }; 94B9533410E6BD7100DC476A /* MacMenuOS9ToOSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MacMenuOS9ToOSX.m; sourceTree = "<group>"; }; 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXFileDirectoryInterface.h; path = vm/OSX/sqSqueakOSXFileDirectoryInterface.h; sourceTree = "<group>"; }; 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXFileDirectoryInterface.m; path = vm/OSX/sqSqueakOSXFileDirectoryInterface.m; sourceTree = "<group>"; }; 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+attributes.h"; path = "vm/OSX/sqSqueakOSXApplication+attributes.h"; sourceTree = "<group>"; }; 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+attributes.m"; path = "vm/OSX/sqSqueakOSXApplication+attributes.m"; sourceTree = "<group>"; }; 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXInfoPlistInterface.h; path = vm/OSX/sqSqueakOSXInfoPlistInterface.h; sourceTree = "<group>"; }; 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXInfoPlistInterface.m; path = vm/OSX/sqSqueakOSXInfoPlistInterface.m; sourceTree = "<group>"; }; 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqMacHostWindow.h; sourceTree = "<group>"; }; 94BCE6870DDDECB800F38F31 /* HostWindowPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostWindowPlugin.h; sourceTree = "<group>"; }; 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqUnixUUID.c; sourceTree = "<group>"; }; 94BCE7A60DDDF8F800F38F31 /* sqaio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqaio.h; path = vm/sqaio.h; sourceTree = "<group>"; }; 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sqSqueakIPhoneApplication+events.h"; sourceTree = "<group>"; }; 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sqSqueakIPhoneApplication+events.m"; sourceTree = "<group>"; }; 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacHostWindow.c; sourceTree = "<group>"; }; 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqMacSecurity.c; sourceTree = "<group>"; }; 94BD816F11C8A58D00556751 /* sqManualSurface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqManualSurface.c; sourceTree = "<group>"; }; 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXNSView.h; path = vm/OSX/sqSqueakOSXNSView.h; sourceTree = "<group>"; }; 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXNSView.m; path = vm/OSX/sqSqueakOSXNSView.m; sourceTree = "<group>"; }; 94C208F810AF7262002F4160 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = "<absolute>"; }; 94C3682410AFA39A0041953A /* macintoshosxextra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macintoshosxextra.h; path = vm/OSX/macintoshosxextra.h; sourceTree = "<group>"; }; 94C3682510AFA39A0041953A /* macintoshosxextra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = macintoshosxextra.c; path = vm/OSX/macintoshosxextra.c; sourceTree = "<group>"; }; 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+cursor.h"; path = "vm/OSX/sqSqueakOSXApplication+cursor.h"; sourceTree = "<group>"; }; 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+cursor.m"; path = "vm/OSX/sqSqueakOSXApplication+cursor.m"; sourceTree = "<group>"; }; 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakCursorAPI.h; path = vm/Common/Classes/sqSqueakCursorAPI.h; sourceTree = "<group>"; }; 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakCursorAPI.m; path = vm/Common/Classes/sqSqueakCursorAPI.m; sourceTree = "<group>"; }; 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakMainApplication+cursor.h"; path = "vm/Common/Classes/sqSqueakMainApplication+cursor.h"; sourceTree = "<group>"; }; 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakMainApplication+cursor.m"; path = "vm/Common/Classes/sqSqueakMainApplication+cursor.m"; sourceTree = "<group>"; }; 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+events.h"; path = "vm/OSX/sqSqueakOSXApplication+events.h"; sourceTree = "<group>"; }; 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+events.m"; path = "vm/OSX/sqSqueakOSXApplication+events.m"; sourceTree = "<group>"; }; 94C36C9710B0CF290041953A /* Info-iPhone.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iPhone.plist"; sourceTree = "<group>"; }; 94C4B80F10C06C4700CD4F90 /* configx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configx.h; sourceTree = "<group>"; }; 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXSoundCoreAudio.h; path = vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.h; sourceTree = "<group>"; }; 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXSoundCoreAudio.m; path = vm/OSX/plugins/SoundPlugin/sqSqueakOSXSoundCoreAudio.m; sourceTree = "<group>"; }; 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sqSqueakOSXApplication+imageReadWrite.h"; path = "vm/OSX/sqSqueakOSXApplication+imageReadWrite.h"; sourceTree = "<group>"; }; 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "sqSqueakOSXApplication+imageReadWrite.m"; path = "vm/OSX/sqSqueakOSXApplication+imageReadWrite.m"; sourceTree = "<group>"; }; 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqSqueakOSXScreenAndWindow.h; path = vm/OSX/sqSqueakOSXScreenAndWindow.h; sourceTree = "<group>"; }; 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = sqSqueakOSXScreenAndWindow.m; path = vm/OSX/sqSqueakOSXScreenAndWindow.m; sourceTree = "<group>"; }; 94D16CAF10BCF96B00A69A89 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = Credits.rtf; path = OSX/Credits.rtf; sourceTree = "<group>"; }; 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitMapConversionLogicFromX11.h; path = vm/OSX/BitMapConversionLogicFromX11.h; sourceTree = "<group>"; }; 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BitMapConversionLogicFromX11.c; path = vm/OSX/BitMapConversionLogicFromX11.c; sourceTree = "<group>"; }; 94E658E10DDD03FE00358328 /* interp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interp.h; sourceTree = "<group>"; }; 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ADPCMCodecPlugin.c; sourceTree = "<group>"; }; 94E658E60DDD03FE00358328 /* B2DPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = B2DPlugin.c; sourceTree = "<group>"; }; 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BitBltPlugin.c; sourceTree = "<group>"; }; 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BMPReadWriterPlugin.c; sourceTree = "<group>"; }; 94E658F00DDD03FE00358328 /* DSAPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DSAPrims.c; sourceTree = "<group>"; }; 94E658F20DDD03FE00358328 /* FFTPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FFTPlugin.c; sourceTree = "<group>"; }; 94E658F40DDD03FE00358328 /* FilePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FilePlugin.c; sourceTree = "<group>"; }; 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FloatArrayPlugin.c; sourceTree = "<group>"; }; 94E658F80DDD03FE00358328 /* GeniePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GeniePlugin.c; sourceTree = "<group>"; }; 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = JPEGReaderPlugin.c; sourceTree = "<group>"; }; 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = JPEGReadWriter2Plugin.c; sourceTree = "<group>"; }; 94E659020DDD03FE00358328 /* Klatt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Klatt.c; sourceTree = "<group>"; }; 94E659040DDD03FE00358328 /* LargeIntegers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LargeIntegers.c; sourceTree = "<group>"; }; 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Matrix2x3Plugin.c; sourceTree = "<group>"; }; 94E659080DDD03FE00358328 /* MIDIPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MIDIPlugin.c; sourceTree = "<group>"; }; 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MiscPrimitivePlugin.c; sourceTree = "<group>"; }; 94E6590C0DDD03FE00358328 /* RePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RePlugin.c; sourceTree = "<group>"; }; 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecurityPlugin.c; sourceTree = "<group>"; }; 94E659100DDD03FE00358328 /* SocketPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SocketPlugin.c; sourceTree = "<group>"; }; 94E659120DDD03FE00358328 /* SoundCodecPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundCodecPrims.c; sourceTree = "<group>"; }; 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SoundGenerationPlugin.c; sourceTree = "<group>"; }; 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = StarSqueakPlugin.c; sourceTree = "<group>"; }; 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UUIDPlugin.c; sourceTree = "<group>"; }; 94E6591F0DDD03FE00358328 /* ZipPlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ZipPlugin.c; sourceTree = "<group>"; }; 94E659200DDD03FE00358328 /* sqNamedPrims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqNamedPrims.h; path = src/vm/sqNamedPrims.h; sourceTree = SOURCE_ROOT; }; 94E659430DDD04FA00358328 /* AsynchFilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsynchFilePlugin.h; sourceTree = "<group>"; }; 94E659450DDD04FA00358328 /* FilePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePlugin.h; sourceTree = "<group>"; }; 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqFilePluginBasicPrims.c; sourceTree = "<group>"; }; 94E659490DDD053900358328 /* SurfacePlugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SurfacePlugin.c; sourceTree = "<group>"; }; 94E6594A0DDD053900358328 /* SurfacePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SurfacePlugin.h; sourceTree = "<group>"; }; 94E6594D0DDD053900358328 /* SecurityPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityPlugin.h; sourceTree = "<group>"; }; 94E6594F0DDD053900358328 /* SoundGenerationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundGenerationPlugin.h; sourceTree = "<group>"; }; 94E659520DDD053900358328 /* Error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Error.c; sourceTree = "<group>"; }; 94E659530DDD053900358328 /* jcapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapimin.c; sourceTree = "<group>"; }; 94E659540DDD053900358328 /* jcapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapistd.c; sourceTree = "<group>"; }; 94E659550DDD053900358328 /* jccoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccoefct.c; sourceTree = "<group>"; }; 94E659560DDD053900358328 /* jccolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccolor.c; sourceTree = "<group>"; }; 94E659570DDD053900358328 /* jcdctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcdctmgr.c; sourceTree = "<group>"; }; 94E659580DDD053900358328 /* jchuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jchuff.c; sourceTree = "<group>"; }; 94E659590DDD053900358328 /* jchuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jchuff.h; sourceTree = "<group>"; }; 94E6595A0DDD053900358328 /* jcinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcinit.c; sourceTree = "<group>"; }; 94E6595B0DDD053900358328 /* jcmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmainct.c; sourceTree = "<group>"; }; 94E6595C0DDD053900358328 /* jcmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmarker.c; sourceTree = "<group>"; }; 94E6595D0DDD053900358328 /* jcmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmaster.c; sourceTree = "<group>"; }; 94E6595E0DDD053900358328 /* jcomapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcomapi.c; sourceTree = "<group>"; }; 94E6595F0DDD053900358328 /* jconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jconfig.h; sourceTree = "<group>"; }; 94E659600DDD053900358328 /* jcparam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcparam.c; sourceTree = "<group>"; }; 94E659610DDD053900358328 /* jcphuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcphuff.c; sourceTree = "<group>"; }; 94E659620DDD053900358328 /* jcprepct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcprepct.c; sourceTree = "<group>"; }; 94E659630DDD053900358328 /* jcsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcsample.c; sourceTree = "<group>"; }; 94E659640DDD053900358328 /* jctrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jctrans.c; sourceTree = "<group>"; }; 94E659650DDD053900358328 /* jdapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapimin.c; sourceTree = "<group>"; }; 94E659660DDD053900358328 /* jdapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapistd.c; sourceTree = "<group>"; }; 94E659670DDD053900358328 /* jdatadst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatadst.c; sourceTree = "<group>"; }; 94E659680DDD053900358328 /* jdatasrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatasrc.c; sourceTree = "<group>"; }; 94E659690DDD053900358328 /* jdcoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcoefct.c; sourceTree = "<group>"; }; 94E6596A0DDD053900358328 /* jdcolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcolor.c; sourceTree = "<group>"; }; 94E6596B0DDD053900358328 /* jdct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdct.h; sourceTree = "<group>"; }; 94E6596C0DDD053900358328 /* jddctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jddctmgr.c; sourceTree = "<group>"; }; 94E6596D0DDD053900358328 /* jdhuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdhuff.c; sourceTree = "<group>"; }; 94E6596E0DDD053900358328 /* jdhuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdhuff.h; sourceTree = "<group>"; }; 94E6596F0DDD053900358328 /* jdinput.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdinput.c; sourceTree = "<group>"; }; 94E659700DDD053900358328 /* jdmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmainct.c; sourceTree = "<group>"; }; 94E659710DDD053900358328 /* jdmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmarker.c; sourceTree = "<group>"; }; 94E659720DDD053900358328 /* jdmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmaster.c; sourceTree = "<group>"; }; 94E659730DDD053900358328 /* jdmerge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmerge.c; sourceTree = "<group>"; }; 94E659740DDD053900358328 /* jdphuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdphuff.c; sourceTree = "<group>"; }; 94E659750DDD053900358328 /* jdpostct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdpostct.c; sourceTree = "<group>"; }; 94E659760DDD053900358328 /* jdsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdsample.c; sourceTree = "<group>"; }; 94E659770DDD053900358328 /* jdtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdtrans.c; sourceTree = "<group>"; }; 94E659780DDD053900358328 /* jerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jerror.c; sourceTree = "<group>"; }; 94E659790DDD053900358328 /* jerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jerror.h; sourceTree = "<group>"; }; 94E6597A0DDD053900358328 /* jfdctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctflt.c; sourceTree = "<group>"; }; 94E6597B0DDD053900358328 /* jfdctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctfst.c; sourceTree = "<group>"; }; 94E6597C0DDD053900358328 /* jfdctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctint.c; sourceTree = "<group>"; }; 94E6597D0DDD053900358328 /* jidctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctflt.c; sourceTree = "<group>"; }; 94E6597E0DDD053900358328 /* jidctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctfst.c; sourceTree = "<group>"; }; 94E6597F0DDD053900358328 /* jidctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctint.c; sourceTree = "<group>"; }; 94E659800DDD053900358328 /* jidctred.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctred.c; sourceTree = "<group>"; }; 94E659810DDD053900358328 /* jinclude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jinclude.h; sourceTree = "<group>"; }; 94E659820DDD053900358328 /* jmemdatadst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemdatadst.c; sourceTree = "<group>"; }; 94E659830DDD053900358328 /* jmemdatasrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemdatasrc.c; sourceTree = "<group>"; }; 94E659840DDD053900358328 /* jmemmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemmgr.c; sourceTree = "<group>"; }; 94E659850DDD053900358328 /* jmemnobs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemnobs.c; sourceTree = "<group>"; }; 94E659860DDD053900358328 /* jmemsys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmemsys.h; sourceTree = "<group>"; }; 94E659870DDD053900358328 /* jmorecfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmorecfg.h; sourceTree = "<group>"; }; 94E659880DDD053900358328 /* jpegint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpegint.h; sourceTree = "<group>"; }; 94E659890DDD053900358328 /* jpeglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpeglib.h; sourceTree = "<group>"; }; 94E6598A0DDD053900358328 /* JPEGReadWriter2Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEGReadWriter2Plugin.h; sourceTree = "<group>"; }; 94E6598B0DDD053900358328 /* jquant1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant1.c; sourceTree = "<group>"; }; 94E6598C0DDD053900358328 /* jquant2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant2.c; sourceTree = "<group>"; }; 94E6598D0DDD053900358328 /* jutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jutils.c; sourceTree = "<group>"; }; 94E6598E0DDD053900358328 /* jversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jversion.h; sourceTree = "<group>"; }; 94E659910DDD053900358328 /* UUIDPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UUIDPlugin.h; sourceTree = "<group>"; }; 94E659930DDD053900358328 /* SoundPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundPlugin.h; sourceTree = "<group>"; }; 94E659970DDD053900358328 /* b3d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3d.h; sourceTree = "<group>"; }; 94E659980DDD053900358328 /* b3dAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dAlloc.c; sourceTree = "<group>"; }; 94E659990DDD053900358328 /* b3dAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3dAlloc.h; sourceTree = "<group>"; }; 94E6599A0DDD053900358328 /* b3dDraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dDraw.c; sourceTree = "<group>"; }; 94E6599B0DDD053900358328 /* b3dInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dInit.c; sourceTree = "<group>"; }; 94E6599C0DDD053900358328 /* b3dMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dMain.c; sourceTree = "<group>"; }; 94E6599D0DDD053900358328 /* b3dRemap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b3dRemap.c; sourceTree = "<group>"; }; 94E6599E0DDD053900358328 /* b3dTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b3dTypes.h; sourceTree = "<group>"; }; 94E659A00DDD053900358328 /* SocketPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketPlugin.h; sourceTree = "<group>"; }; 94E659A30DDD053900358328 /* SoundCodecPrims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundCodecPrims.h; sourceTree = "<group>"; }; 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqSoundCodecPluginBasicPrims.c; sourceTree = "<group>"; }; 94E65A290DDD053900358328 /* chartables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = chartables.c; sourceTree = "<group>"; }; 94E65A2B0DDD053900358328 /* get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = get.c; sourceTree = "<group>"; }; 94E65A2C0DDD053900358328 /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; 94E65A2E0DDD053900358328 /* pcre.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcre.c; sourceTree = "<group>"; }; 94E65A2F0DDD053900358328 /* pcre.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pcre.h; sourceTree = "<group>"; }; 94E65A300DDD053900358328 /* rePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rePlugin.h; sourceTree = "<group>"; }; 94E65A340DDD053900358328 /* study.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = study.c; sourceTree = "<group>"; }; 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "gcc3x-interp.c"; sourceTree = "<group>"; }; 94EF6CC011E55947003BA64D /* interp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interp.h; sourceTree = "<group>"; }; 94F3A9690E6BFA7C00E0B12A /* Squeak.png */ = {isa = PBXFileReference; explicitFileType = image.png; path = Squeak.png; sourceTree = "<group>"; }; 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqSqueakIPhoneInfoPlistInterface.h; sourceTree = "<group>"; }; 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sqSqueakIPhoneInfoPlistInterface.m; sourceTree = "<group>"; }; 94FFF7A40EBE2B9C00C69C79 /* SqueakV39.sources */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SqueakV39.sources; path = iPhone/SqueakV39.sources; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 94D2A24C112B8ED000B6E459 /* QuartzCore.framework in Frameworks */, 945550010DF1BC6A00FB176B /* AudioToolbox.framework in Frameworks */, 94577FBD10684D5E0020840A /* CoreAudio.framework in Frameworks */, 94577FBF10684D5E0020840A /* CoreLocation.framework in Frameworks */, 94577FC510684D7E0020840A /* SystemConfiguration.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 947E62F210AA098300D3B69E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 947E62FF10AA09C300D3B69E /* Cocoa.framework in Frameworks */, 947E62F410AA098300D3B69E /* AudioToolbox.framework in Frameworks */, 947E62F510AA098300D3B69E /* CoreAudio.framework in Frameworks */, 947E62F710AA098300D3B69E /* SystemConfiguration.framework in Frameworks */, 942ABE6F10AA23E20086D908 /* ApplicationServices.framework in Frameworks */, 94C208F910AF7262002F4160 /* QuartzCore.framework in Frameworks */, 040F22DB12CE1517008BA0CB /* Foundation.framework in Frameworks */, 040F22E412CE155C008BA0CB /* OpenGL.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 040F20B812CE0C84008BA0CB /* UnixOSProcessPlugin */ = { isa = PBXGroup; children = ( 040F20C112CE0FFB008BA0CB /* UnixOSProcessPlugin.c */, ); path = UnixOSProcessPlugin; sourceTree = "<group>"; }; 040F20C312CE1006008BA0CB /* Squeak3D */ = { isa = PBXGroup; children = ( 040F20C712CE1057008BA0CB /* Squeak3D.c */, ); name = Squeak3D; path = ../../platforms/iOS/vm/src/vm/intplugins/Squeak3D; sourceTree = "<group>"; }; 040F20C912CE1067008BA0CB /* ClipboardExtendedPlugin */ = { isa = PBXGroup; children = ( 040F20CA12CE10AC008BA0CB /* ClipboardExtendedPlugin.c */, ); name = ClipboardExtendedPlugin; path = ../../platforms/iOS/vm/src/vm/intplugins/ClipboardExtendedPlugin; sourceTree = "<group>"; }; 040F20E112CE1283008BA0CB /* ObjectiveCPlugin */ = { isa = PBXGroup; children = ( 040F20E212CE1283008BA0CB /* ObjectiveCPlugin.c */, ); name = ObjectiveCPlugin; path = src/vm/intplugins/ObjectiveCPlugin; sourceTree = SOURCE_ROOT; }; 040F22FA12CE1752008BA0CB /* SoundPlugin */ = { isa = PBXGroup; children = ( 040F22FB12CE1752008BA0CB /* SoundPlugin.c */, ); name = SoundPlugin; path = src/vm/intplugins/SoundPlugin; sourceTree = SOURCE_ROOT; }; 040F230512CE1AE2008BA0CB /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 040F230612CE1AE2008BA0CB /* SqueakFFIPrims.c */, ); name = SqueakFFIPrims; path = src/vm/intplugins/SqueakFFIPrims; sourceTree = SOURCE_ROOT; }; 040F230C12CE1B28008BA0CB /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 040F230D12CE1B28008BA0CB /* HostWindowPlugin.c */, ); name = HostWindowPlugin; path = src/vm/intplugins/HostWindowPlugin; sourceTree = SOURCE_ROOT; }; 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( 1D3623240D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.h */, 1D3623250D0F684500981E51 /* SqueakNoOGLIPhoneAppDelegate.m */, 942F761B0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.h */, 942F761C0E0B6B6100848BF2 /* sqSqueakIPhoneApplication.m */, 942F76350E0B6CEF00848BF2 /* sqSqueakIPhoneApplication+attributes.h */, 94A0E8450DE5EB6E0071C8B9 /* sqSqueakIPhoneApplication+attributes.m */, 9458525A10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.h */, 9458525B10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m */, 943001260E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.h */, 943001270E0D5D670040BB27 /* sqSqueakIPhoneApplication+imageReadWrite.m */, 94BCE93E0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.h */, 94BCE93F0DDE044700F38F31 /* sqSqueakIPhoneApplication+events.m */, 9452BDC10F4095DE006410DE /* sqSqueakIPhoneApplication+Network.h */, 9452BDC20F4095DE006410DE /* sqSqueakIPhoneApplication+Network.m */, 94554F1D0DF1B65700FB176B /* sqSqueakIPhoneApplication+sound.h */, 94554F1E0DF1B65700FB176B /* sqSqueakiPhoneApplication+sound.m */, 943001A30E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.h */, 943001A40E0D600C0040BB27 /* sqSqueakIPhoneFileDirectoryInterface.m */, 94F8798F0E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.h */, 94F879900E6C0C7E00662DEA /* sqSqueakIPhoneInfoPlistInterface.m */, 9452D7630E0452D3000AD792 /* sqiPhoneScreenAndWindow.h */, 9452D7640E0452D3000AD792 /* sqiPhoneScreenAndWindow.m */, 949E5DB50DE3AB6A007388E0 /* SqueakUIView.h */, 949E5DB60DE3AB6A007388E0 /* SqueakUIView.m */, 942F48FA123C1C0C002B05DF /* SqueakUIViewCALayer.h */, 942F48FB123C1C0C002B05DF /* SqueakUIViewCALayer.m */, 942F48FC123C1C0C002B05DF /* SqueakUIViewOpenGL.h */, 942F48FD123C1C0C002B05DF /* SqueakUIViewOpenGL.m */, 940CE8540DFCE2D200EBA91B /* SqueakUIController.h */, 940CE8550DFCE2D200EBA91B /* SqueakUIController.m */, 9458525410F04339001401E7 /* sqSqueakIPhoneClipboardAPI.h */, 9458525510F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m */, ); path = Classes; sourceTree = "<group>"; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 1D6058910D05DD3D006BFB54 /* Squeak.app */, 947E62FC10AA098300D3B69E /* Squeak.app */, ); name = Products; sourceTree = "<group>"; }; 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( 9412CAB20E6C037B00DB8625 /* Settings.bundle */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 948EC38E1155311D00B08A4F /* Resources-iPad */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, 941D1C9A0E696FC7005B77B3 /* Entitlements.plist */, 94C36C9710B0CF290041953A /* Info-iPhone.plist */, 947E5F9F10A9FFA000D3B69E /* SqueakPureObjc-Info.plist */, 949AD14911E542E8006D6BF4 /* SqueakPureObjc-InfoCOG.plist */, ); name = CustomTemplate; sourceTree = "<group>"; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( 9424FF570DDCB17F009912BF /* platforms */, 94E658DC0DDD03FE00358328 /* src */, 94EF6CB911E55947003BA64D /* stacksrc */, 947E5F9310A9FF4A00D3B69E /* SqueakPureObjc_Prefix.pch */, ); name = "Other Sources"; sourceTree = "<group>"; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( 94B6E9DC10BC777A00333E9E /* Localizable.strings */, 947E64DC10AA18FE00D3B69E /* MainMenu.xib */, 94A349B50DDCDBE200D1D4A9 /* iPhone.image */, 94638B260EAFB77B00A3F155 /* iPhone.changes */, 94FFF7A40EBE2B9C00C69C79 /* SqueakV39.sources */, 944895AD10F4081300FB3EC8 /* PharoV10.sources */, 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 945550910DF2041100FB176B /* Default.png */, 94F3A9690E6BFA7C00E0B12A /* Squeak.png */, 9427E45512628749002DCA6D /* Squeak72x72.png */, 9414421E10BC89440088F8AC /* Squeak.icns */, 9414421F10BC89440088F8AC /* SqueakChanges.icns */, 9414422010BC89440088F8AC /* SqueakGeneric.icns */, 9414422110BC89440088F8AC /* SqueakImage.icns */, 9414422210BC89440088F8AC /* SqueakPlugin.icns */, 9414422310BC89440088F8AC /* SqueakProject.icns */, 9414422410BC89440088F8AC /* SqueakScript.icns */, 9414422510BC89440088F8AC /* SqueakSources.icns */, 94D16CAF10BCF96B00A69A89 /* Credits.rtf */, ); name = Resources; sourceTree = "<group>"; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( 947E61C410AA03DC00D3B69E /* AppKit.framework */, 947E61C210AA03C300D3B69E /* Cocoa.framework */, 945550000DF1BC6A00FB176B /* AudioToolbox.framework */, 94577FBC10684D5E0020840A /* CoreAudio.framework */, 94577FBE10684D5E0020840A /* CoreLocation.framework */, 94577FC410684D7E0020840A /* SystemConfiguration.framework */, 942ABE6E10AA23E20086D908 /* ApplicationServices.framework */, 94C208F810AF7262002F4160 /* QuartzCore.framework */, 040F22DA12CE1517008BA0CB /* Foundation.framework */, 040F22E312CE155C008BA0CB /* OpenGL.framework */, ); name = Frameworks; sourceTree = "<group>"; }; 9424FF570DDCB17F009912BF /* platforms */ = { isa = PBXGroup; children = ( 94BCE77E0DDDF61200F38F31 /* unix */, 94BCE6880DDDECC200F38F31 /* Cross */, 9424FF590DDCB198009912BF /* iOS */, ); name = platforms; path = ../..; sourceTree = "<group>"; }; 9424FF580DDCB18C009912BF /* vm */ = { isa = PBXGroup; children = ( 9494935011E527AB0019BC29 /* sqMemoryFence.h */, 949492C011E51C6B0019BC29 /* dispdbg.h */, 949492C111E51C6B0019BC29 /* sqAssert.h */, 949492C211E51C6B0019BC29 /* sqCogStackAlignment.h */, 949492C311E51C6B0019BC29 /* sqExternalSemaphores.c */, 949492C411E51C6B0019BC29 /* sqAtomicOps.h */, 949492C511E51C6B0019BC29 /* sqHeapMap.c */, 949492C611E51C6B0019BC29 /* sqTicker.c */, 9424FF5C0DDCB1C7009912BF /* sqMemoryAccess.h */, 9424FF5D0DDCB1C7009912BF /* sq.h */, 9424FF5E0DDCB1C7009912BF /* sqNamedPrims.c */, 9424FF600DDCB1C7009912BF /* sqVirtualMachine.c */, 9424FF610DDCB1C7009912BF /* sqVirtualMachine.h */, ); path = vm; sourceTree = "<group>"; }; 9424FF590DDCB198009912BF /* iOS */ = { isa = PBXGroup; children = ( 947E642610AA0E1100D3B69E /* OSX */, 9452D5EF0E044AC2000AD792 /* Common */, 9424FF5B0DDCB1C7009912BF /* sqGnu.h */, 9424FF5A0DDCB19F009912BF /* iPhone */, ); path = iOS; sourceTree = "<group>"; }; 9424FF5A0DDCB19F009912BF /* iPhone */ = { isa = PBXGroup; children = ( 94BCE6640DDDEB5000F38F31 /* plugins */, 080E96DDFE201D6D7F000001 /* Classes */, 9424FF650DDCB1EF009912BF /* config.h */, 9424FF710DDCB234009912BF /* macintoshextra.c */, 9424FF720DDCB234009912BF /* macintoshextra.h */, 9424FF750DDCB271009912BF /* osExports.c */, 9424FF660DDCB1EF009912BF /* sqConfig.h */, 9400325C0DEF3936002FA1C4 /* sqDummyaio.c */, 9400325B0DEF3936002FA1C4 /* sqDummyaio.h */, 9424FF670DDCB202009912BF /* sqMacV2Memory.c */, 9424FF680DDCB202009912BF /* sqMacV2Memory.h */, 9424FF640DDCB1EF009912BF /* sqPlatformSpecific.h */, ); name = iPhone; path = vm/iPhone; sourceTree = "<group>"; }; 943B9B271235BD960056205E /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 943B9B281235BDD20056205E /* sqMacHostWindow.m */, 943B9B291235BDD20056205E /* sqMacHostWindow.h */, ); name = HostWindowPlugin; path = vm/OSX/plugins/HostWindowPlugin; sourceTree = "<group>"; }; 944069CC10E6B63200353B27 /* MacMenubarPlugin */ = { isa = PBXGroup; children = ( 944069CD10E6B63200353B27 /* MacMenubarPlugin.c */, ); path = MacMenubarPlugin; sourceTree = "<group>"; }; 9452D5EF0E044AC2000AD792 /* Common */ = { isa = PBXGroup; children = ( 29B97316FDCFA39411CA2CEA /* main.m */, 9478E0220EC8D957007096A7 /* plugins */, 9452D5F00E044AD1000AD792 /* Classes */, ); name = Common; sourceTree = "<group>"; }; 9452D5F00E044AD1000AD792 /* Classes */ = { isa = PBXGroup; children = ( 9452D5D70E044A9D000AD792 /* Queue.h */, 9452D5D80E044A9D000AD792 /* Queue.m */, 9452D5D90E044A9D000AD792 /* sqMacV2Time.c */, 9452D5DA0E044A9D000AD792 /* sqMacV2Time.h */, 9471D2DF0E04743F00703D45 /* sqSqueakAppDelegate.h */, 9471D2E00E04743F00703D45 /* sqSqueakAppDelegate.m */, 9452D5DB0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.h */, 9452D5DC0E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m */, 9452D5DD0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.h */, 9452D5DE0E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m */, 9412CAE40E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.h */, 9412CAE50E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m */, 9452D5DF0E044A9D000AD792 /* sqSqueakMainApp.m */, 9452D5E00E044A9D000AD792 /* sqSqueakMainApp.h */, 9452D5E30E044A9D000AD792 /* sqSqueakMainApplication.h */, 9452D5E40E044A9D000AD792 /* sqSqueakMainApplication.m */, 94A0E8440DE5EB6E0071C8B9 /* sqSqueakMainApplication+attributes.h */, 942F76310E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m */, 9452D6010E044CB3000AD792 /* sqSqueakAttributesAPI.h */, 9452D6020E044CB3000AD792 /* sqSqueakAttributesAPI.m */, 94A1B0050E0DBE2400EB5EFC /* sqSqueakMainApplication+events.h */, 94A1B0060E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m */, 9452D6060E044D2F000AD792 /* sqSqueakEventsAPI.h */, 9452D6070E044D2F000AD792 /* sqSqueakEventsAPI.m */, 94A0E8830DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.h */, 94A0E8840DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m */, 94A1B0300E0DC19300EB5EFC /* sqSqueakMainApplication+sound.h */, 94A1B0310E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m */, 94A1B02B0E0DC10D00EB5EFC /* sqSqueakSoundAPI.h */, 94A1B02C0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m */, 9452D5E10E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.h */, 9452D5E20E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m */, 942F75D10E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.h */, 942F75D20E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m */, 94A0E9820DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.h */, 94A0E9830DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m */, 94A3488C0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.h */, 94A3488D0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m */, 9471D2710E04703B00703D45 /* sqSqueakScreenAndWindow.h */, 9471D2720E04703B00703D45 /* sqSqueakScreenAndWindow.m */, 94C3687B10AFA8300041953A /* sqSqueakCursorAPI.h */, 94C3687C10AFA8300041953A /* sqSqueakCursorAPI.m */, 94C3688A10AFA9EF0041953A /* sqSqueakMainApplication+cursor.h */, 94C3688B10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m */, ); name = Classes; sourceTree = "<group>"; }; 94584FD810F02378001401E7 /* ClipboardExtended */ = { isa = PBXGroup; children = ( 94584FD910F02378001401E7 /* sqMacExtendedClipboard.m */, 94584FDA10F02378001401E7 /* sqMacExtendedClipboard.h */, ); name = ClipboardExtended; path = plugins/ClipboardExtended; sourceTree = "<group>"; }; 945851ED10F03E60001401E7 /* ClipboardExtended */ = { isa = PBXGroup; children = ( 945851EE10F03E60001401E7 /* sqMacExtendedClipboard.h */, 945851EF10F03E60001401E7 /* sqMacExtendedClipboard.m */, ); path = ClipboardExtended; sourceTree = "<group>"; }; 9463943C0E95845000015851 /* SqueakObjectiveC */ = { isa = PBXGroup; children = ( 9463943E0E95845000015851 /* squeakSUnitTester.m */, 9463943D0E95845000015851 /* squeakSUnitTester.h */, ); name = SqueakObjectiveC; path = ../plugins/SqueakObjectiveC; sourceTree = SOURCE_ROOT; }; 946DA8D110C0C30D00F26F56 /* DropPlugin */ = { isa = PBXGroup; children = ( 946DA8D210C0C30D00F26F56 /* DropPlugin.c */, ); path = DropPlugin; sourceTree = "<group>"; }; 946DA8EE10C0C38600F26F56 /* DropPlugin */ = { isa = PBXGroup; children = ( 946DA8EF10C0C38600F26F56 /* DropPlugin.h */, ); path = DropPlugin; sourceTree = "<group>"; }; 9478E0220EC8D957007096A7 /* plugins */ = { isa = PBXGroup; children = ( 9478E0230EC8D957007096A7 /* SoundPlugin */, 9478E0240EC8D957007096A7 /* SqueakFFIPrims */, 9478E0270EC8D957007096A7 /* SqueakObjectiveC */, 94BCEAF10DDE16B400F38F31 /* SecurityPlugin */, ); path = plugins; sourceTree = "<group>"; }; 9478E0230EC8D957007096A7 /* SoundPlugin */ = { isa = PBXGroup; children = ( 9478E0320EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.h */, 9478E0330EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m */, 9478E05E0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.h */, 9478E05F0EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m */, ); path = SoundPlugin; sourceTree = "<group>"; }; 9478E0240EC8D957007096A7 /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 9478E0250EC8D957007096A7 /* dummyFFI.c */, 9478E0260EC8D957007096A7 /* dummyFFI.h */, ); path = SqueakFFIPrims; sourceTree = "<group>"; }; 9478E0270EC8D957007096A7 /* SqueakObjectiveC */ = { isa = PBXGroup; children = ( 9402F2C50F3F9C5600F3D637 /* drawing.m */, 9402F2AE0F3F9BB900F3D637 /* PDColoredProgressView.h */, 9402F2AF0F3F9BB900F3D637 /* PDColoredProgressView.m */, 9478E02A0EC8D957007096A7 /* squeakSUnitTester.h */, 9478E02B0EC8D957007096A7 /* squeakSUnitTester.m */, 941724430F36624C0031AF33 /* squeakProxy.h */, 941724420F36624C0031AF33 /* squeakProxy.m */, ); path = SqueakObjectiveC; sourceTree = "<group>"; }; 947E20F80EB2826C007957D0 /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 94BD816F11C8A58D00556751 /* sqManualSurface.c */, 947E20F90EB2826C007957D0 /* sqFFI.h */, ); path = SqueakFFIPrims; sourceTree = "<group>"; }; 947E21300EB28650007957D0 /* SqueakFFIPrims */ = { isa = PBXGroup; children = ( 947E21310EB2868A007957D0 /* dummyFFI.h */, 947E21320EB2868A007957D0 /* dummyFFI.c */, ); path = SqueakFFIPrims; sourceTree = "<group>"; }; 947E642610AA0E1100D3B69E /* OSX */ = { isa = PBXGroup; children = ( 94C4B82C10C06F0D00CD4F90 /* plugins */, 947E647610AA0FF200D3B69E /* Classes */, ); name = OSX; sourceTree = "<group>"; }; 947E647610AA0FF200D3B69E /* Classes */ = { isa = PBXGroup; children = ( 947E647910AA100900D3B69E /* SqueakOSXAppDelegate.h */, 947E647A10AA100900D3B69E /* SqueakOSXAppDelegate.m */, 947E642710AA0E9E00D3B69E /* sqMacV2Browser.h */, 947E642810AA0E9E00D3B69E /* sqMacV2Browser.m */, 946DA9FF10C0D35500F26F56 /* sqMacUnixExternalPrims.m */, 947E64CA10AA16FE00D3B69E /* sqSqueakOSXApplication.h */, 947E64CB10AA16FE00D3B69E /* sqSqueakOSXApplication.m */, 94BCABBF10AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.h */, 94BCABC010AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m */, 94BCAD1B10AB942300F87527 /* sqSqueakOSXApplication+attributes.h */, 94BCAD1C10AB942300F87527 /* sqSqueakOSXApplication+attributes.m */, 94BCAE6710ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.h */, 94BCAE6810ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m */, 94C887F910ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.h */, 94C887FA10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m */, 94C88BDD10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.h */, 94C88BDE10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m */, 94C2068810AF4F53002F4160 /* sqSqueakOSXNSView.h */, 94C2068910AF4F53002F4160 /* sqSqueakOSXNSView.m */, 9402DD6F10CE0E91005C2102 /* SqViewClut.m */, 94B8F54E10CF677800F0DD6B /* SqViewClut.h */, 94D3654D10CEC86C00805023 /* BitMapConversionLogicFromX11.h */, 94D3654E10CEC86C00805023 /* BitMapConversionLogicFromX11.c */, 9402DD5E10CE0C16005C2102 /* SqViewBitmapConversion.h */, 9402DD5F10CE0C16005C2102 /* SqViewBitmapConversion.m */, 94C3682410AFA39A0041953A /* macintoshosxextra.h */, 94C3682510AFA39A0041953A /* macintoshosxextra.c */, 94C3687610AFA77F0041953A /* sqSqueakOSXApplication+cursor.h */, 94C3687710AFA77F0041953A /* sqSqueakOSXApplication+cursor.m */, 94C36A9210B09EE70041953A /* sqSqueakOSXApplication+events.h */, 94C36A9310B09EE70041953A /* sqSqueakOSXApplication+events.m */, 94A1B21A10B9DE0300C64473 /* keyBoardStrokeDetails.h */, 94A1B21B10B9DE0300C64473 /* keyBoardStrokeDetails.m */, 9492452F10BA43AA00E726F5 /* SqueakOSXApplication.h */, 9492453010BA43AA00E726F5 /* SqueakOSXApplication.m */, 9428BA9510BB440800DAD287 /* sqSqueakOSXClipboardAPI.h */, 9428BA9610BB440800DAD287 /* sqSqueakOSXClipboardAPI.m */, 9428BB0410BB478600DAD287 /* sqSqueakOSXApplication+clipboard.h */, 9428BB0510BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m */, 946DA91310C0C71100F26F56 /* sqSqueakOSXDropAPI.h */, 946DA91410C0C71100F26F56 /* sqSqueakOSXDropAPI.m */, ); name = Classes; sourceTree = "<group>"; }; 94883B3F0E0C2B9C005A4738 /* SocketPlugin */ = { isa = PBXGroup; children = ( 94883B400E0C2B9C005A4738 /* sqUnixSocket.c */, 949493BF11E52ADE0019BC29 /* aio.c */, ); path = SocketPlugin; sourceTree = "<group>"; }; 948EC38E1155311D00B08A4F /* Resources-iPad */ = { isa = PBXGroup; children = ( 948EC38F1155312600B08A4F /* MainWindow-iPad.xib */, ); name = "Resources-iPad"; sourceTree = "<group>"; }; 9494932B11E527180019BC29 /* vm */ = { isa = PBXGroup; children = ( 9494932C11E527180019BC29 /* sqUnixHeartbeat.c */, 9494932D11E527180019BC29 /* sqUnixThreads.c */, 9494932E11E527180019BC29 /* sqUnixVMProfile.c */, ); path = vm; sourceTree = "<group>"; }; 94B9528410E6B79E00DC476A /* MacMenubarPlugin */ = { isa = PBXGroup; children = ( 94B9528510E6B79E00DC476A /* MacMenubarPlugin.h */, 94B9533310E6BD7100DC476A /* MacMenuOS9ToOSX.h */, 94B9533410E6BD7100DC476A /* MacMenuOS9ToOSX.m */, ); name = MacMenubarPlugin; path = plugins/MacMenubarPlugin; sourceTree = "<group>"; }; 94BCE6640DDDEB5000F38F31 /* plugins */ = { isa = PBXGroup; children = ( 945851ED10F03E60001401E7 /* ClipboardExtended */, 947E21300EB28650007957D0 /* SqueakFFIPrims */, 94BCE6650DDDEB5000F38F31 /* HostWindowPlugin */, ); path = plugins; sourceTree = "<group>"; }; 94BCE6650DDDEB5000F38F31 /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 94BCEA2B0DDE0C1600F38F31 /* sqMacHostWindow.c */, 94BCE6660DDDEB5000F38F31 /* sqMacHostWindow.h */, ); path = HostWindowPlugin; sourceTree = "<group>"; }; 94BCE6860DDDECB800F38F31 /* HostWindowPlugin */ = { isa = PBXGroup; children = ( 94BCE6870DDDECB800F38F31 /* HostWindowPlugin.h */, ); path = HostWindowPlugin; sourceTree = "<group>"; }; 94BCE6880DDDECC200F38F31 /* Cross */ = { isa = PBXGroup; children = ( 9424FF580DDCB18C009912BF /* vm */, 94BCE6890DDDECD600F38F31 /* plugins */, ); path = Cross; sourceTree = "<group>"; }; 94BCE6890DDDECD600F38F31 /* plugins */ = { isa = PBXGroup; children = ( 94E659420DDD04FA00358328 /* AsynchFilePlugin */, 946DA8EE10C0C38600F26F56 /* DropPlugin */, 94E659440DDD04FA00358328 /* FilePlugin */, 94BCE6860DDDECB800F38F31 /* HostWindowPlugin */, 94E659510DDD053900358328 /* JPEGReadWriter2Plugin */, 94E65A280DDD053900358328 /* RePlugin */, 94E6594C0DDD053900358328 /* SecurityPlugin */, 94E6599F0DDD053900358328 /* SocketPlugin */, 94E659A20DDD053900358328 /* SoundCodecPrims */, 94E6594E0DDD053900358328 /* SoundGenerationPlugin */, 94E659920DDD053900358328 /* SoundPlugin */, 9463943C0E95845000015851 /* SqueakObjectiveC */, 94E659960DDD053900358328 /* Squeak3D */, 947E20F80EB2826C007957D0 /* SqueakFFIPrims */, 94E659480DDD053900358328 /* SurfacePlugin */, 94E659900DDD053900358328 /* UUIDPlugin */, ); path = plugins; sourceTree = "<group>"; }; 94BCE77E0DDDF61200F38F31 /* unix */ = { isa = PBXGroup; children = ( 94BCE7A60DDDF8F800F38F31 /* sqaio.h */, 9494932B11E527180019BC29 /* vm */, 94BCE77F0DDDF61200F38F31 /* plugins */, ); path = unix; sourceTree = "<group>"; }; 94BCE77F0DDDF61200F38F31 /* plugins */ = { isa = PBXGroup; children = ( 94883B3F0E0C2B9C005A4738 /* SocketPlugin */, 94BCE7840DDDF61200F38F31 /* UUIDPlugin */, ); path = plugins; sourceTree = "<group>"; }; 94BCE7840DDDF61200F38F31 /* UUIDPlugin */ = { isa = PBXGroup; children = ( 94BCE7870DDDF61200F38F31 /* sqUnixUUID.c */, ); path = UUIDPlugin; sourceTree = "<group>"; }; 94BCEAF10DDE16B400F38F31 /* SecurityPlugin */ = { isa = PBXGroup; children = ( 94BCEAF20DDE16B400F38F31 /* sqMacSecurity.c */, ); path = SecurityPlugin; sourceTree = "<group>"; }; 94C4B82C10C06F0D00CD4F90 /* plugins */ = { isa = PBXGroup; children = ( 943B9B271235BD960056205E /* HostWindowPlugin */, 94584FD810F02378001401E7 /* ClipboardExtended */, 94B9528410E6B79E00DC476A /* MacMenubarPlugin */, 94C4B82D10C06F1800CD4F90 /* SoundPlugin */, ); name = plugins; sourceTree = "<group>"; }; 94C4B82D10C06F1800CD4F90 /* SoundPlugin */ = { isa = PBXGroup; children = ( 94C4B82E10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.h */, 94C4B82F10C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m */, ); name = SoundPlugin; sourceTree = "<group>"; }; 94E658DC0DDD03FE00358328 /* src */ = { isa = PBXGroup; children = ( 94E658DD0DDD03FE00358328 /* plugins */, 94E658DF0DDD03FE00358328 /* vm */, ); name = src; path = ../../../src; sourceTree = "<group>"; }; 94E658DD0DDD03FE00358328 /* plugins */ = { isa = PBXGroup; children = ( ); path = plugins; sourceTree = "<group>"; }; 94E658DF0DDD03FE00358328 /* vm */ = { isa = PBXGroup; children = ( 9494927D11E5178D0019BC29 /* cogit.c */, 9494927E11E5178D0019BC29 /* cogit.h */, 9494927F11E5178D0019BC29 /* cogmethod.h */, 9494928011E5178D0019BC29 /* gcc3x-cointerp.c */, 9494928111E5178D0019BC29 /* cointerp.h */, 94E658E10DDD03FE00358328 /* interp.h */, 94E658E20DDD03FE00358328 /* plugins */, 94E659200DDD03FE00358328 /* sqNamedPrims.h */, ); path = vm; sourceTree = "<group>"; }; 94E658E20DDD03FE00358328 /* plugins */ = { isa = PBXGroup; children = ( 040F230C12CE1B28008BA0CB /* HostWindowPlugin */, 040F230512CE1AE2008BA0CB /* SqueakFFIPrims */, 040F22FA12CE1752008BA0CB /* SoundPlugin */, 040F20E112CE1283008BA0CB /* ObjectiveCPlugin */, 040F20C912CE1067008BA0CB /* ClipboardExtendedPlugin */, 040F20C312CE1006008BA0CB /* Squeak3D */, 040F20B812CE0C84008BA0CB /* UnixOSProcessPlugin */, 94E658E30DDD03FE00358328 /* ADPCMCodecPlugin */, 94E658E50DDD03FE00358328 /* B2DPlugin */, 94E658E90DDD03FE00358328 /* BitBltPlugin */, 94E658EB0DDD03FE00358328 /* BMPReadWriterPlugin */, 946DA8D110C0C30D00F26F56 /* DropPlugin */, 94E658EF0DDD03FE00358328 /* DSAPrims */, 94E658F10DDD03FE00358328 /* FFTPlugin */, 94E658F30DDD03FE00358328 /* FilePlugin */, 94E658F50DDD03FE00358328 /* FloatArrayPlugin */, 94E658F70DDD03FE00358328 /* GeniePlugin */, 94E658FD0DDD03FE00358328 /* JPEGReaderPlugin */, 94E658FF0DDD03FE00358328 /* JPEGReadWriter2Plugin */, 94E659010DDD03FE00358328 /* Klatt */, 94E659030DDD03FE00358328 /* LargeIntegers */, 944069CC10E6B63200353B27 /* MacMenubarPlugin */, 94E659050DDD03FE00358328 /* Matrix2x3Plugin */, 94E659070DDD03FE00358328 /* MIDIPlugin */, 94E659090DDD03FE00358328 /* MiscPrimitivePlugin */, 94E6590B0DDD03FE00358328 /* RePlugin */, 94E6590D0DDD03FE00358328 /* SecurityPlugin */, 94E6590F0DDD03FE00358328 /* SocketPlugin */, 94E659110DDD03FE00358328 /* SoundCodecPrims */, 94E659130DDD03FE00358328 /* SoundGenerationPlugin */, 94E659190DDD03FE00358328 /* StarSqueakPlugin */, 94E6591B0DDD03FE00358328 /* SurfacePlugin */, 94E6591C0DDD03FE00358328 /* UUIDPlugin */, 94E6591E0DDD03FE00358328 /* ZipPlugin */, ); name = plugins; path = ../plugins; sourceTree = "<group>"; }; 94E658E30DDD03FE00358328 /* ADPCMCodecPlugin */ = { isa = PBXGroup; children = ( 94E658E40DDD03FE00358328 /* ADPCMCodecPlugin.c */, ); path = ADPCMCodecPlugin; sourceTree = "<group>"; }; 94E658E50DDD03FE00358328 /* B2DPlugin */ = { isa = PBXGroup; children = ( 94E658E60DDD03FE00358328 /* B2DPlugin.c */, ); path = B2DPlugin; sourceTree = "<group>"; }; 94E658E90DDD03FE00358328 /* BitBltPlugin */ = { isa = PBXGroup; children = ( 94E658EA0DDD03FE00358328 /* BitBltPlugin.c */, ); path = BitBltPlugin; sourceTree = "<group>"; }; 94E658EB0DDD03FE00358328 /* BMPReadWriterPlugin */ = { isa = PBXGroup; children = ( 94E658EC0DDD03FE00358328 /* BMPReadWriterPlugin.c */, ); path = BMPReadWriterPlugin; sourceTree = "<group>"; }; 94E658EF0DDD03FE00358328 /* DSAPrims */ = { isa = PBXGroup; children = ( 94E658F00DDD03FE00358328 /* DSAPrims.c */, ); path = DSAPrims; sourceTree = "<group>"; }; 94E658F10DDD03FE00358328 /* FFTPlugin */ = { isa = PBXGroup; children = ( 94E658F20DDD03FE00358328 /* FFTPlugin.c */, ); path = FFTPlugin; sourceTree = "<group>"; }; 94E658F30DDD03FE00358328 /* FilePlugin */ = { isa = PBXGroup; children = ( 94E658F40DDD03FE00358328 /* FilePlugin.c */, ); path = FilePlugin; sourceTree = "<group>"; }; 94E658F50DDD03FE00358328 /* FloatArrayPlugin */ = { isa = PBXGroup; children = ( 94E658F60DDD03FE00358328 /* FloatArrayPlugin.c */, ); path = FloatArrayPlugin; sourceTree = "<group>"; }; 94E658F70DDD03FE00358328 /* GeniePlugin */ = { isa = PBXGroup; children = ( 94E658F80DDD03FE00358328 /* GeniePlugin.c */, ); path = GeniePlugin; sourceTree = "<group>"; }; 94E658FD0DDD03FE00358328 /* JPEGReaderPlugin */ = { isa = PBXGroup; children = ( 94E658FE0DDD03FE00358328 /* JPEGReaderPlugin.c */, ); path = JPEGReaderPlugin; sourceTree = "<group>"; }; 94E658FF0DDD03FE00358328 /* JPEGReadWriter2Plugin */ = { isa = PBXGroup; children = ( 94E659000DDD03FE00358328 /* JPEGReadWriter2Plugin.c */, ); path = JPEGReadWriter2Plugin; sourceTree = "<group>"; }; 94E659010DDD03FE00358328 /* Klatt */ = { isa = PBXGroup; children = ( 94E659020DDD03FE00358328 /* Klatt.c */, ); path = Klatt; sourceTree = "<group>"; }; 94E659030DDD03FE00358328 /* LargeIntegers */ = { isa = PBXGroup; children = ( 94E659040DDD03FE00358328 /* LargeIntegers.c */, ); path = LargeIntegers; sourceTree = "<group>"; }; 94E659050DDD03FE00358328 /* Matrix2x3Plugin */ = { isa = PBXGroup; children = ( 94E659060DDD03FE00358328 /* Matrix2x3Plugin.c */, ); path = Matrix2x3Plugin; sourceTree = "<group>"; }; 94E659070DDD03FE00358328 /* MIDIPlugin */ = { isa = PBXGroup; children = ( 94E659080DDD03FE00358328 /* MIDIPlugin.c */, ); path = MIDIPlugin; sourceTree = "<group>"; }; 94E659090DDD03FE00358328 /* MiscPrimitivePlugin */ = { isa = PBXGroup; children = ( 94E6590A0DDD03FE00358328 /* MiscPrimitivePlugin.c */, ); path = MiscPrimitivePlugin; sourceTree = "<group>"; }; 94E6590B0DDD03FE00358328 /* RePlugin */ = { isa = PBXGroup; children = ( 94E6590C0DDD03FE00358328 /* RePlugin.c */, ); path = RePlugin; sourceTree = "<group>"; }; 94E6590D0DDD03FE00358328 /* SecurityPlugin */ = { isa = PBXGroup; children = ( 94E6590E0DDD03FE00358328 /* SecurityPlugin.c */, ); path = SecurityPlugin; sourceTree = "<group>"; }; 94E6590F0DDD03FE00358328 /* SocketPlugin */ = { isa = PBXGroup; children = ( 94E659100DDD03FE00358328 /* SocketPlugin.c */, ); path = SocketPlugin; sourceTree = "<group>"; }; 94E659110DDD03FE00358328 /* SoundCodecPrims */ = { isa = PBXGroup; children = ( 94E659120DDD03FE00358328 /* SoundCodecPrims.c */, ); path = SoundCodecPrims; sourceTree = "<group>"; }; 94E659130DDD03FE00358328 /* SoundGenerationPlugin */ = { isa = PBXGroup; children = ( 94E659140DDD03FE00358328 /* SoundGenerationPlugin.c */, ); path = SoundGenerationPlugin; sourceTree = "<group>"; }; 94E659190DDD03FE00358328 /* StarSqueakPlugin */ = { isa = PBXGroup; children = ( 94E6591A0DDD03FE00358328 /* StarSqueakPlugin.c */, ); path = StarSqueakPlugin; sourceTree = "<group>"; }; 94E6591B0DDD03FE00358328 /* SurfacePlugin */ = { isa = PBXGroup; children = ( ); path = SurfacePlugin; sourceTree = "<group>"; }; 94E6591C0DDD03FE00358328 /* UUIDPlugin */ = { isa = PBXGroup; children = ( 94E6591D0DDD03FE00358328 /* UUIDPlugin.c */, ); path = UUIDPlugin; sourceTree = "<group>"; }; 94E6591E0DDD03FE00358328 /* ZipPlugin */ = { isa = PBXGroup; children = ( 94E6591F0DDD03FE00358328 /* ZipPlugin.c */, ); path = ZipPlugin; sourceTree = "<group>"; }; 94E659420DDD04FA00358328 /* AsynchFilePlugin */ = { isa = PBXGroup; children = ( 94E659430DDD04FA00358328 /* AsynchFilePlugin.h */, ); path = AsynchFilePlugin; sourceTree = "<group>"; }; 94E659440DDD04FA00358328 /* FilePlugin */ = { isa = PBXGroup; children = ( 94E659450DDD04FA00358328 /* FilePlugin.h */, 94E659460DDD04FA00358328 /* sqFilePluginBasicPrims.c */, ); path = FilePlugin; sourceTree = "<group>"; }; 94E659480DDD053900358328 /* SurfacePlugin */ = { isa = PBXGroup; children = ( 94E659490DDD053900358328 /* SurfacePlugin.c */, 94E6594A0DDD053900358328 /* SurfacePlugin.h */, ); path = SurfacePlugin; sourceTree = "<group>"; }; 94E6594C0DDD053900358328 /* SecurityPlugin */ = { isa = PBXGroup; children = ( 94E6594D0DDD053900358328 /* SecurityPlugin.h */, ); path = SecurityPlugin; sourceTree = "<group>"; }; 94E6594E0DDD053900358328 /* SoundGenerationPlugin */ = { isa = PBXGroup; children = ( 94E6594F0DDD053900358328 /* SoundGenerationPlugin.h */, ); path = SoundGenerationPlugin; sourceTree = "<group>"; }; 94E659510DDD053900358328 /* JPEGReadWriter2Plugin */ = { isa = PBXGroup; children = ( 94E659520DDD053900358328 /* Error.c */, 94E659530DDD053900358328 /* jcapimin.c */, 94E659540DDD053900358328 /* jcapistd.c */, 94E659550DDD053900358328 /* jccoefct.c */, 94E659560DDD053900358328 /* jccolor.c */, 94E659570DDD053900358328 /* jcdctmgr.c */, 94E659580DDD053900358328 /* jchuff.c */, 94E659590DDD053900358328 /* jchuff.h */, 94E6595A0DDD053900358328 /* jcinit.c */, 94E6595B0DDD053900358328 /* jcmainct.c */, 94E6595C0DDD053900358328 /* jcmarker.c */, 94E6595D0DDD053900358328 /* jcmaster.c */, 94E6595E0DDD053900358328 /* jcomapi.c */, 94E6595F0DDD053900358328 /* jconfig.h */, 94E659600DDD053900358328 /* jcparam.c */, 94E659610DDD053900358328 /* jcphuff.c */, 94E659620DDD053900358328 /* jcprepct.c */, 94E659630DDD053900358328 /* jcsample.c */, 94E659640DDD053900358328 /* jctrans.c */, 94E659650DDD053900358328 /* jdapimin.c */, 94E659660DDD053900358328 /* jdapistd.c */, 94E659670DDD053900358328 /* jdatadst.c */, 94E659680DDD053900358328 /* jdatasrc.c */, 94E659690DDD053900358328 /* jdcoefct.c */, 94E6596A0DDD053900358328 /* jdcolor.c */, 94E6596B0DDD053900358328 /* jdct.h */, 94E6596C0DDD053900358328 /* jddctmgr.c */, 94E6596D0DDD053900358328 /* jdhuff.c */, 94E6596E0DDD053900358328 /* jdhuff.h */, 94E6596F0DDD053900358328 /* jdinput.c */, 94E659700DDD053900358328 /* jdmainct.c */, 94E659710DDD053900358328 /* jdmarker.c */, 94E659720DDD053900358328 /* jdmaster.c */, 94E659730DDD053900358328 /* jdmerge.c */, 94E659740DDD053900358328 /* jdphuff.c */, 94E659750DDD053900358328 /* jdpostct.c */, 94E659760DDD053900358328 /* jdsample.c */, 94E659770DDD053900358328 /* jdtrans.c */, 94E659780DDD053900358328 /* jerror.c */, 94E659790DDD053900358328 /* jerror.h */, 94E6597A0DDD053900358328 /* jfdctflt.c */, 94E6597B0DDD053900358328 /* jfdctfst.c */, 94E6597C0DDD053900358328 /* jfdctint.c */, 94E6597D0DDD053900358328 /* jidctflt.c */, 94E6597E0DDD053900358328 /* jidctfst.c */, 94E6597F0DDD053900358328 /* jidctint.c */, 94E659800DDD053900358328 /* jidctred.c */, 94E659810DDD053900358328 /* jinclude.h */, 94E659820DDD053900358328 /* jmemdatadst.c */, 94E659830DDD053900358328 /* jmemdatasrc.c */, 94E659840DDD053900358328 /* jmemmgr.c */, 94E659850DDD053900358328 /* jmemnobs.c */, 94E659860DDD053900358328 /* jmemsys.h */, 94E659870DDD053900358328 /* jmorecfg.h */, 94E659880DDD053900358328 /* jpegint.h */, 94E659890DDD053900358328 /* jpeglib.h */, 94E6598A0DDD053900358328 /* JPEGReadWriter2Plugin.h */, 94E6598B0DDD053900358328 /* jquant1.c */, 94E6598C0DDD053900358328 /* jquant2.c */, 94E6598D0DDD053900358328 /* jutils.c */, 94E6598E0DDD053900358328 /* jversion.h */, ); path = JPEGReadWriter2Plugin; sourceTree = "<group>"; }; 94E659900DDD053900358328 /* UUIDPlugin */ = { isa = PBXGroup; children = ( 94E659910DDD053900358328 /* UUIDPlugin.h */, ); path = UUIDPlugin; sourceTree = "<group>"; }; 94E659920DDD053900358328 /* SoundPlugin */ = { isa = PBXGroup; children = ( 94E659930DDD053900358328 /* SoundPlugin.h */, ); path = SoundPlugin; sourceTree = "<group>"; }; 94E659960DDD053900358328 /* Squeak3D */ = { isa = PBXGroup; children = ( 94E659970DDD053900358328 /* b3d.h */, 94E659980DDD053900358328 /* b3dAlloc.c */, 94E659990DDD053900358328 /* b3dAlloc.h */, 94E6599A0DDD053900358328 /* b3dDraw.c */, 94E6599B0DDD053900358328 /* b3dInit.c */, 94E6599C0DDD053900358328 /* b3dMain.c */, 94E6599D0DDD053900358328 /* b3dRemap.c */, 94E6599E0DDD053900358328 /* b3dTypes.h */, ); path = Squeak3D; sourceTree = "<group>"; }; 94E6599F0DDD053900358328 /* SocketPlugin */ = { isa = PBXGroup; children = ( 94E659A00DDD053900358328 /* SocketPlugin.h */, ); path = SocketPlugin; sourceTree = "<group>"; }; 94E659A20DDD053900358328 /* SoundCodecPrims */ = { isa = PBXGroup; children = ( 94E659A30DDD053900358328 /* SoundCodecPrims.h */, 94E659A40DDD053900358328 /* sqSoundCodecPluginBasicPrims.c */, ); path = SoundCodecPrims; sourceTree = "<group>"; }; 94E65A280DDD053900358328 /* RePlugin */ = { isa = PBXGroup; children = ( 94C4B80F10C06C4700CD4F90 /* configx.h */, 94E65A290DDD053900358328 /* chartables.c */, 94E65A2B0DDD053900358328 /* get.c */, 94E65A2C0DDD053900358328 /* internal.h */, 94E65A2E0DDD053900358328 /* pcre.c */, 94E65A2F0DDD053900358328 /* pcre.h */, 94E65A300DDD053900358328 /* rePlugin.h */, 94E65A340DDD053900358328 /* study.c */, ); path = RePlugin; sourceTree = "<group>"; }; 94EF6CB911E55947003BA64D /* stacksrc */ = { isa = PBXGroup; children = ( 94EF6CBC11E55947003BA64D /* vm */, ); name = stacksrc; path = ../../../stacksrc; sourceTree = "<group>"; }; 94EF6CBC11E55947003BA64D /* vm */ = { isa = PBXGroup; children = ( 94EF6CBE11E55947003BA64D /* gcc3x-interp.c */, 94EF6CC011E55947003BA64D /* interp.h */, ); path = vm; sourceTree = "<group>"; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */ = { isa = PBXNativeTarget; buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "SqueakNoOGLIPhone" */; buildPhases = ( 1D60588D0D05DD3D006BFB54 /* Resources */, 1D60588E0D05DD3D006BFB54 /* Sources */, 1D60588F0D05DD3D006BFB54 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = SqueakNoOGLIPhone; productName = SqueakNoOGLIPhone; productReference = 1D6058910D05DD3D006BFB54 /* Squeak.app */; productType = "com.apple.product-type.application"; }; 947E626F10AA098300D3B69E /* SqueakPureObjc */ = { isa = PBXNativeTarget; buildConfigurationList = 947E62F810AA098300D3B69E /* Build configuration list for PBXNativeTarget "SqueakPureObjc" */; buildPhases = ( 947E627010AA098300D3B69E /* Resources */, 947E627410AA098300D3B69E /* Sources */, 947E62F210AA098300D3B69E /* Frameworks */, ); buildRules = ( 9469CEED10BFD8CE002245C2 /* PBXBuildRule */, ); dependencies = ( ); name = SqueakPureObjc; productName = SqueakNoOGLIPhone; productReference = 947E62FC10AA098300D3B69E /* Squeak.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SqueakPureObjcCogVM" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; targets = ( 1D6058900D05DD3D006BFB54 /* SqueakNoOGLIPhone */, 947E626F10AA098300D3B69E /* SqueakPureObjc */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 1D60588D0D05DD3D006BFB54 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 9484F80210B0D81F0038BDC0 /* iPhone.image in Resources */, 9484F80310B0D81F0038BDC0 /* iPhone.changes in Resources */, 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 941D1C9B0E696FC7005B77B3 /* Entitlements.plist in Resources */, 9412CAB30E6C037B00DB8625 /* Settings.bundle in Resources */, 9484F8EF10B0E1580038BDC0 /* Default.png in Resources */, 94B6E9DD10BC777A00333E9E /* Localizable.strings in Resources */, 948EC3901155312600B08A4F /* MainWindow-iPad.xib in Resources */, 9427E45612628749002DCA6D /* Squeak72x72.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 947E627010AA098300D3B69E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 947E64DE10AA18FE00D3B69E /* MainMenu.xib in Resources */, 94B6E9DE10BC777A00333E9E /* Localizable.strings in Resources */, 9414422610BC89440088F8AC /* Squeak.icns in Resources */, 9414422710BC89440088F8AC /* SqueakChanges.icns in Resources */, 9414422810BC89440088F8AC /* SqueakGeneric.icns in Resources */, 9414422910BC89440088F8AC /* SqueakImage.icns in Resources */, 9414422A10BC89440088F8AC /* SqueakPlugin.icns in Resources */, 9414422B10BC89440088F8AC /* SqueakProject.icns in Resources */, 9414422C10BC89440088F8AC /* SqueakScript.icns in Resources */, 9414422D10BC89440088F8AC /* SqueakSources.icns in Resources */, 94D16CB010BCF96B00A69A89 /* Credits.rtf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 1D60588E0D05DD3D006BFB54 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 9424FF620DDCB1C7009912BF /* sqNamedPrims.c in Sources */, 9424FF6B0DDCB202009912BF /* sqMacV2Memory.c in Sources */, 9424FF730DDCB234009912BF /* macintoshextra.c in Sources */, 9424FF760DDCB271009912BF /* osExports.c in Sources */, 94A3488E0DDCCCC700D1D4A9 /* sqSqueakScreenAPI.m in Sources */, 94E659230DDD03FE00358328 /* ADPCMCodecPlugin.c in Sources */, 94E659240DDD03FE00358328 /* B2DPlugin.c in Sources */, 94E659260DDD03FE00358328 /* BitBltPlugin.c in Sources */, 94E659270DDD03FE00358328 /* BMPReadWriterPlugin.c in Sources */, 94E659290DDD03FE00358328 /* DSAPrims.c in Sources */, 94E6592A0DDD03FE00358328 /* FFTPlugin.c in Sources */, 94E6592B0DDD03FE00358328 /* FilePlugin.c in Sources */, 94E6592C0DDD03FE00358328 /* FloatArrayPlugin.c in Sources */, 94E6592D0DDD03FE00358328 /* GeniePlugin.c in Sources */, 94E659300DDD03FE00358328 /* JPEGReaderPlugin.c in Sources */, 94E659310DDD03FE00358328 /* JPEGReadWriter2Plugin.c in Sources */, 94E659320DDD03FE00358328 /* Klatt.c in Sources */, 94E659330DDD03FE00358328 /* LargeIntegers.c in Sources */, 94E659340DDD03FE00358328 /* Matrix2x3Plugin.c in Sources */, 94E659360DDD03FE00358328 /* MiscPrimitivePlugin.c in Sources */, 94E659370DDD03FE00358328 /* RePlugin.c in Sources */, 94E659380DDD03FE00358328 /* SecurityPlugin.c in Sources */, 94E6593A0DDD03FE00358328 /* SoundCodecPrims.c in Sources */, 94E6593B0DDD03FE00358328 /* SoundGenerationPlugin.c in Sources */, 94E6593E0DDD03FE00358328 /* StarSqueakPlugin.c in Sources */, 94E6593F0DDD03FE00358328 /* UUIDPlugin.c in Sources */, 94E659400DDD03FE00358328 /* ZipPlugin.c in Sources */, 94E659470DDD04FA00358328 /* sqFilePluginBasicPrims.c in Sources */, 94E65A350DDD053900358328 /* SurfacePlugin.c in Sources */, 94E65A370DDD053900358328 /* Error.c in Sources */, 94E65A380DDD053900358328 /* jcapimin.c in Sources */, 94E65A390DDD053900358328 /* jcapistd.c in Sources */, 94E65A3A0DDD053900358328 /* jccoefct.c in Sources */, 94E65A3B0DDD053900358328 /* jccolor.c in Sources */, 94E65A3C0DDD053900358328 /* jcdctmgr.c in Sources */, 94E65A3D0DDD053900358328 /* jchuff.c in Sources */, 94E65A3E0DDD053900358328 /* jcinit.c in Sources */, 94E65A3F0DDD053900358328 /* jcmainct.c in Sources */, 94E65A400DDD053900358328 /* jcmarker.c in Sources */, 94E65A410DDD053900358328 /* jcmaster.c in Sources */, 94E65A420DDD053900358328 /* jcomapi.c in Sources */, 94E65A430DDD053900358328 /* jcparam.c in Sources */, 94E65A440DDD053900358328 /* jcphuff.c in Sources */, 94E65A450DDD053900358328 /* jcprepct.c in Sources */, 94E65A460DDD053900358328 /* jcsample.c in Sources */, 94E65A470DDD053900358328 /* jctrans.c in Sources */, 94E65A480DDD053900358328 /* jdapimin.c in Sources */, 94E65A490DDD053900358328 /* jdapistd.c in Sources */, 94E65A4A0DDD053900358328 /* jdatadst.c in Sources */, 94E65A4B0DDD053900358328 /* jdatasrc.c in Sources */, 94E65A4C0DDD053900358328 /* jdcoefct.c in Sources */, 94E65A4D0DDD053900358328 /* jdcolor.c in Sources */, 94E65A4E0DDD053900358328 /* jddctmgr.c in Sources */, 94E65A4F0DDD053900358328 /* jdhuff.c in Sources */, 94E65A500DDD053900358328 /* jdinput.c in Sources */, 94E65A510DDD053900358328 /* jdmainct.c in Sources */, 94E65A520DDD053900358328 /* jdmarker.c in Sources */, 94E65A530DDD053900358328 /* jdmaster.c in Sources */, 94E65A540DDD053900358328 /* jdmerge.c in Sources */, 94E65A550DDD053900358328 /* jdphuff.c in Sources */, 94E65A560DDD053900358328 /* jdpostct.c in Sources */, 94E65A570DDD053900358328 /* jdsample.c in Sources */, 94E65A580DDD053900358328 /* jdtrans.c in Sources */, 94E65A590DDD053900358328 /* jerror.c in Sources */, 94E65A5A0DDD053900358328 /* jfdctflt.c in Sources */, 94E65A5B0DDD053900358328 /* jfdctfst.c in Sources */, 94E65A5C0DDD053900358328 /* jfdctint.c in Sources */, 94E65A5D0DDD053900358328 /* jidctflt.c in Sources */, 94E65A5E0DDD053900358328 /* jidctfst.c in Sources */, 94E65A5F0DDD053900358328 /* jidctint.c in Sources */, 94E65A600DDD053900358328 /* jidctred.c in Sources */, 94E65A610DDD053900358328 /* jmemdatadst.c in Sources */, 94E65A620DDD053900358328 /* jmemdatasrc.c in Sources */, 94E65A630DDD053900358328 /* jmemmgr.c in Sources */, 94E65A640DDD053900358328 /* jmemnobs.c in Sources */, 94E65A650DDD053900358328 /* jquant1.c in Sources */, 94E65A660DDD053900358328 /* jquant2.c in Sources */, 94E65A670DDD053900358328 /* jutils.c in Sources */, 94E65A690DDD053900358328 /* b3dAlloc.c in Sources */, 94E65A6A0DDD053900358328 /* b3dDraw.c in Sources */, 94E65A6B0DDD053900358328 /* b3dInit.c in Sources */, 94E65A6C0DDD053900358328 /* b3dMain.c in Sources */, 94E65A6D0DDD053900358328 /* b3dRemap.c in Sources */, 94E65A6F0DDD053900358328 /* sqSoundCodecPluginBasicPrims.c in Sources */, 94E65AEE0DDD053900358328 /* chartables.c in Sources */, 94E65AEF0DDD053900358328 /* get.c in Sources */, 94E65AF00DDD053900358328 /* pcre.c in Sources */, 94E65AF40DDD053900358328 /* study.c in Sources */, 94BCE78C0DDDF61200F38F31 /* sqUnixUUID.c in Sources */, 94A0E8850DE5EF430071C8B9 /* sqSqueakMainApplication+imageReadWrite.m in Sources */, 94A0E9840DE5F1FE0071C8B9 /* sqSqueakMainApplication+screen.m in Sources */, 94AB2E570E003692006A79E4 /* sqVirtualMachine.c in Sources */, 9452D5E50E044A9D000AD792 /* Queue.m in Sources */, 9452D5E60E044A9D000AD792 /* sqMacV2Time.c in Sources */, 9452D5E70E044A9D000AD792 /* sqSqueakFileDirectoryAPI.m in Sources */, 9452D5E80E044A9D000AD792 /* sqSqueakFileDirectoryInterface.m in Sources */, 9452D5E90E044A9D000AD792 /* sqSqueakMainApp.m in Sources */, 9452D5EA0E044A9D000AD792 /* sqSqueakMainApplication+vmAndImagePath.m in Sources */, 9452D5EB0E044A9D000AD792 /* sqSqueakMainApplication.m in Sources */, 9452D6030E044CB3000AD792 /* sqSqueakAttributesAPI.m in Sources */, 9452D6080E044D2F000AD792 /* sqSqueakEventsAPI.m in Sources */, 9471D2730E04703B00703D45 /* sqSqueakScreenAndWindow.m in Sources */, 9471D2E10E04743F00703D45 /* sqSqueakAppDelegate.m in Sources */, 942F75D30E0B67AD00848BF2 /* sqSqueakVmAndImagePathAPI.m in Sources */, 942F76320E0B6C7600848BF2 /* sqSqueakMainApplication+attributes.m in Sources */, 94883B1C0E0C2937005A4738 /* SocketPlugin.c in Sources */, 94883B410E0C2B9C005A4738 /* sqUnixSocket.c in Sources */, 94A1B0070E0DBE2400EB5EFC /* sqSqueakMainApplication+events.m in Sources */, 94A1B02D0E0DC10D00EB5EFC /* sqSqueakSoundAPI.m in Sources */, 94A1B0320E0DC19300EB5EFC /* sqSqueakMainApplication+sound.m in Sources */, 9412CAE60E6C05EC00DB8625 /* sqSqueakInfoPlistInterface.m in Sources */, 9463943F0E95845000015851 /* squeakSUnitTester.m in Sources */, 9478E0340EC8D98F007096A7 /* sqSqueakSoundCoreAudioAPI.m in Sources */, 9478E0600EC8DCFB007096A7 /* sqSqueakSoundCoreAudio.m in Sources */, 941724440F36624C0031AF33 /* squeakProxy.m in Sources */, 9402F2B00F3F9BB900F3D637 /* PDColoredProgressView.m in Sources */, 9402F2C60F3F9C5600F3D637 /* drawing.m in Sources */, 9484F8D410B0E04E0038BDC0 /* sqMacSecurity.c in Sources */, 9484F8DB10B0E09B0038BDC0 /* sqiPhoneScreenAndWindow.m in Sources */, 9484F8DC10B0E0C60038BDC0 /* sqSqueakIPhoneApplication+attributes.m in Sources */, 9484F8DD10B0E0C70038BDC0 /* sqSqueakIPhoneApplication+events.m in Sources */, 9484F8DE10B0E0C90038BDC0 /* sqSqueakIPhoneApplication+imageReadWrite.m in Sources */, 9484F8DF10B0E0CB0038BDC0 /* sqSqueakIPhoneApplication+Network.m in Sources */, 9484F8E010B0E0CE0038BDC0 /* sqSqueakiPhoneApplication+sound.m in Sources */, 9484F8E110B0E0CE0038BDC0 /* sqSqueakIPhoneApplication.m in Sources */, 9484F8E210B0E0D10038BDC0 /* sqSqueakIPhoneFileDirectoryInterface.m in Sources */, 9484F8E310B0E0D30038BDC0 /* sqSqueakIPhoneInfoPlistInterface.m in Sources */, 9484F8E510B0E0F00038BDC0 /* SqueakNoOGLIPhoneAppDelegate.m in Sources */, 9484F8E610B0E0FD0038BDC0 /* SqueakUIController.m in Sources */, 9484F8E710B0E0FE0038BDC0 /* SqueakUIView.m in Sources */, 9484F91210B0E25B0038BDC0 /* dummyFFI.c in Sources */, 9484F9AF10B13DA50038BDC0 /* sqMacHostWindow.c in Sources */, 945851F010F03E60001401E7 /* sqMacExtendedClipboard.m in Sources */, 9458525610F04339001401E7 /* sqSqueakIPhoneClipboardAPI.m in Sources */, 9458525C10F043EB001401E7 /* sqSqueakIPhoneApplication+clipboard.m in Sources */, 94BD817011C8A58D00556751 /* sqManualSurface.c in Sources */, 949492C711E51C6B0019BC29 /* sqExternalSemaphores.c in Sources */, 949492C811E51C6B0019BC29 /* sqHeapMap.c in Sources */, 949492C911E51C6B0019BC29 /* sqTicker.c in Sources */, 9494932F11E527180019BC29 /* sqUnixHeartbeat.c in Sources */, 9494933011E527180019BC29 /* sqUnixThreads.c in Sources */, 949493C011E52ADE0019BC29 /* aio.c in Sources */, 94EF6CC311E55947003BA64D /* gcc3x-interp.c in Sources */, 942F48FE123C1C0C002B05DF /* SqueakUIViewCALayer.m in Sources */, 942F48FF123C1C0C002B05DF /* SqueakUIViewOpenGL.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 947E627410AA098300D3B69E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 947E627510AA098300D3B69E /* main.m in Sources */, 947E627610AA098300D3B69E /* sqNamedPrims.c in Sources */, 947E627710AA098300D3B69E /* sqMacV2Memory.c in Sources */, 947E627910AA098300D3B69E /* osExports.c in Sources */, 947E627A10AA098300D3B69E /* sqSqueakScreenAPI.m in Sources */, 947E627B10AA098300D3B69E /* ADPCMCodecPlugin.c in Sources */, 947E627C10AA098300D3B69E /* B2DPlugin.c in Sources */, 947E627D10AA098300D3B69E /* BitBltPlugin.c in Sources */, 947E627E10AA098300D3B69E /* BMPReadWriterPlugin.c in Sources */, 947E627F10AA098300D3B69E /* DSAPrims.c in Sources */, 947E628010AA098300D3B69E /* FFTPlugin.c in Sources */, 947E628110AA098300D3B69E /* FilePlugin.c in Sources */, 947E628210AA098300D3B69E /* FloatArrayPlugin.c in Sources */, 947E628310AA098300D3B69E /* GeniePlugin.c in Sources */, 947E628510AA098300D3B69E /* JPEGReaderPlugin.c in Sources */, 947E628610AA098300D3B69E /* JPEGReadWriter2Plugin.c in Sources */, 947E628710AA098300D3B69E /* Klatt.c in Sources */, 947E628810AA098300D3B69E /* LargeIntegers.c in Sources */, 947E628910AA098300D3B69E /* Matrix2x3Plugin.c in Sources */, 947E628A10AA098300D3B69E /* MiscPrimitivePlugin.c in Sources */, 947E628B10AA098300D3B69E /* RePlugin.c in Sources */, 947E628C10AA098300D3B69E /* SecurityPlugin.c in Sources */, 947E628D10AA098300D3B69E /* SoundCodecPrims.c in Sources */, 947E628E10AA098300D3B69E /* SoundGenerationPlugin.c in Sources */, 947E629110AA098300D3B69E /* StarSqueakPlugin.c in Sources */, 947E629210AA098300D3B69E /* UUIDPlugin.c in Sources */, 947E629310AA098300D3B69E /* ZipPlugin.c in Sources */, 947E629410AA098300D3B69E /* sqFilePluginBasicPrims.c in Sources */, 947E629510AA098300D3B69E /* SurfacePlugin.c in Sources */, 947E629610AA098300D3B69E /* Error.c in Sources */, 947E629710AA098300D3B69E /* jcapimin.c in Sources */, 947E629810AA098300D3B69E /* jcapistd.c in Sources */, 947E629910AA098300D3B69E /* jccoefct.c in Sources */, 947E629A10AA098300D3B69E /* jccolor.c in Sources */, 947E629B10AA098300D3B69E /* jcdctmgr.c in Sources */, 947E629C10AA098300D3B69E /* jchuff.c in Sources */, 947E629D10AA098300D3B69E /* jcinit.c in Sources */, 947E629E10AA098300D3B69E /* jcmainct.c in Sources */, 947E629F10AA098300D3B69E /* jcmarker.c in Sources */, 947E62A010AA098300D3B69E /* jcmaster.c in Sources */, 947E62A110AA098300D3B69E /* jcomapi.c in Sources */, 947E62A210AA098300D3B69E /* jcparam.c in Sources */, 947E62A310AA098300D3B69E /* jcphuff.c in Sources */, 947E62A410AA098300D3B69E /* jcprepct.c in Sources */, 947E62A510AA098300D3B69E /* jcsample.c in Sources */, 947E62A610AA098300D3B69E /* jctrans.c in Sources */, 947E62A710AA098300D3B69E /* jdapimin.c in Sources */, 947E62A810AA098300D3B69E /* jdapistd.c in Sources */, 947E62A910AA098300D3B69E /* jdatadst.c in Sources */, 947E62AA10AA098300D3B69E /* jdatasrc.c in Sources */, 947E62AB10AA098300D3B69E /* jdcoefct.c in Sources */, 947E62AC10AA098300D3B69E /* jdcolor.c in Sources */, 947E62AD10AA098300D3B69E /* jddctmgr.c in Sources */, 947E62AE10AA098300D3B69E /* jdhuff.c in Sources */, 947E62AF10AA098300D3B69E /* jdinput.c in Sources */, 947E62B010AA098300D3B69E /* jdmainct.c in Sources */, 947E62B110AA098300D3B69E /* jdmarker.c in Sources */, 947E62B210AA098300D3B69E /* jdmaster.c in Sources */, 947E62B310AA098300D3B69E /* jdmerge.c in Sources */, 947E62B410AA098300D3B69E /* jdphuff.c in Sources */, 947E62B510AA098300D3B69E /* jdpostct.c in Sources */, 947E62B610AA098300D3B69E /* jdsample.c in Sources */, 947E62B710AA098300D3B69E /* jdtrans.c in Sources */, 947E62B810AA098300D3B69E /* jerror.c in Sources */, 947E62B910AA098300D3B69E /* jfdctflt.c in Sources */, 947E62BA10AA098300D3B69E /* jfdctfst.c in Sources */, 947E62BB10AA098300D3B69E /* jfdctint.c in Sources */, 947E62BC10AA098300D3B69E /* jidctflt.c in Sources */, 947E62BD10AA098300D3B69E /* jidctfst.c in Sources */, 947E62BE10AA098300D3B69E /* jidctint.c in Sources */, 947E62BF10AA098300D3B69E /* jidctred.c in Sources */, 947E62C010AA098300D3B69E /* jmemdatadst.c in Sources */, 947E62C110AA098300D3B69E /* jmemdatasrc.c in Sources */, 947E62C210AA098300D3B69E /* jmemmgr.c in Sources */, 947E62C310AA098300D3B69E /* jmemnobs.c in Sources */, 947E62C410AA098300D3B69E /* jquant1.c in Sources */, 947E62C510AA098300D3B69E /* jquant2.c in Sources */, 947E62C610AA098300D3B69E /* jutils.c in Sources */, 947E62C710AA098300D3B69E /* b3dAlloc.c in Sources */, 947E62C810AA098300D3B69E /* b3dDraw.c in Sources */, 947E62C910AA098300D3B69E /* b3dInit.c in Sources */, 947E62CA10AA098300D3B69E /* b3dMain.c in Sources */, 947E62CB10AA098300D3B69E /* b3dRemap.c in Sources */, 947E62CC10AA098300D3B69E /* sqSoundCodecPluginBasicPrims.c in Sources */, 947E62CD10AA098300D3B69E /* chartables.c in Sources */, 947E62CE10AA098300D3B69E /* get.c in Sources */, 947E62CF10AA098300D3B69E /* pcre.c in Sources */, 947E62D010AA098300D3B69E /* study.c in Sources */, 947E62D110AA098300D3B69E /* sqUnixUUID.c in Sources */, 947E62D210AA098300D3B69E /* sqSqueakMainApplication+imageReadWrite.m in Sources */, 947E62D310AA098300D3B69E /* sqSqueakMainApplication+screen.m in Sources */, 947E62D510AA098300D3B69E /* sqVirtualMachine.c in Sources */, 947E62D610AA098300D3B69E /* Queue.m in Sources */, 947E62D710AA098300D3B69E /* sqMacV2Time.c in Sources */, 947E62D810AA098300D3B69E /* sqSqueakFileDirectoryAPI.m in Sources */, 947E62D910AA098300D3B69E /* sqSqueakFileDirectoryInterface.m in Sources */, 947E62DA10AA098300D3B69E /* sqSqueakMainApp.m in Sources */, 947E62DB10AA098300D3B69E /* sqSqueakMainApplication+vmAndImagePath.m in Sources */, 947E62DC10AA098300D3B69E /* sqSqueakMainApplication.m in Sources */, 947E62DD10AA098300D3B69E /* sqSqueakAttributesAPI.m in Sources */, 947E62DE10AA098300D3B69E /* sqSqueakEventsAPI.m in Sources */, 947E62DF10AA098300D3B69E /* sqSqueakScreenAndWindow.m in Sources */, 947E62E010AA098300D3B69E /* sqSqueakAppDelegate.m in Sources */, 947E62E110AA098300D3B69E /* sqSqueakVmAndImagePathAPI.m in Sources */, 947E62E210AA098300D3B69E /* sqSqueakMainApplication+attributes.m in Sources */, 947E62E310AA098300D3B69E /* SocketPlugin.c in Sources */, 947E62E410AA098300D3B69E /* sqUnixSocket.c in Sources */, 947E62E510AA098300D3B69E /* sqSqueakMainApplication+events.m in Sources */, 947E62E610AA098300D3B69E /* sqSqueakSoundAPI.m in Sources */, 947E62E710AA098300D3B69E /* sqSqueakMainApplication+sound.m in Sources */, 947E62E810AA098300D3B69E /* sqSqueakInfoPlistInterface.m in Sources */, 947E62EA10AA098300D3B69E /* squeakSUnitTester.m in Sources */, 947E62ED10AA098300D3B69E /* sqSqueakSoundCoreAudioAPI.m in Sources */, 947E62EE10AA098300D3B69E /* sqSqueakSoundCoreAudio.m in Sources */, 947E62EF10AA098300D3B69E /* squeakProxy.m in Sources */, 947E632410AA0B4E00D3B69E /* dummyFFI.c in Sources */, 947E642D10AA0E9E00D3B69E /* sqMacV2Browser.m in Sources */, 947E647B10AA100900D3B69E /* SqueakOSXAppDelegate.m in Sources */, 947E64AB10AA149F00D3B69E /* sqMacSecurity.c in Sources */, 947E64CC10AA16FE00D3B69E /* sqSqueakOSXApplication.m in Sources */, 94BCABC110AB72A600F87527 /* sqSqueakOSXFileDirectoryInterface.m in Sources */, 94BCAD1D10AB942300F87527 /* sqSqueakOSXApplication+attributes.m in Sources */, 94BCAE6910ACA10100F87527 /* sqSqueakOSXInfoPlistInterface.m in Sources */, 94C887FB10ADCEFC007CB39E /* sqSqueakOSXApplication+imageReadWrite.m in Sources */, 94C88BDF10AF3C52007CB39E /* sqSqueakOSXScreenAndWindow.m in Sources */, 94C2068A10AF4F53002F4160 /* sqSqueakOSXNSView.m in Sources */, 94C3682610AFA39A0041953A /* macintoshosxextra.c in Sources */, 94C3687810AFA77F0041953A /* sqSqueakOSXApplication+cursor.m in Sources */, 94C3687D10AFA8300041953A /* sqSqueakCursorAPI.m in Sources */, 94C3688C10AFA9EF0041953A /* sqSqueakMainApplication+cursor.m in Sources */, 94C36A9410B09EE70041953A /* sqSqueakOSXApplication+events.m in Sources */, 94A1B21C10B9DE0300C64473 /* keyBoardStrokeDetails.m in Sources */, 9492453110BA43AA00E726F5 /* SqueakOSXApplication.m in Sources */, 9428BA9710BB440800DAD287 /* sqSqueakOSXClipboardAPI.m in Sources */, 9428BB0610BB478600DAD287 /* sqSqueakOSXApplication+clipboard.m in Sources */, 94C4B83010C06F8800CD4F90 /* sqSqueakOSXSoundCoreAudio.m in Sources */, 946DA8D310C0C30D00F26F56 /* DropPlugin.c in Sources */, 946DA91510C0C71100F26F56 /* sqSqueakOSXDropAPI.m in Sources */, 946DAA0010C0D35500F26F56 /* sqMacUnixExternalPrims.m in Sources */, 9402DD7110CE0E91005C2102 /* SqViewClut.m in Sources */, 944069CF10E6B63200353B27 /* MacMenubarPlugin.c in Sources */, 94B9533610E6BD7100DC476A /* MacMenuOS9ToOSX.m in Sources */, 94584FDC10F02378001401E7 /* sqMacExtendedClipboard.m in Sources */, 94BD817311C8A59A00556751 /* sqManualSurface.c in Sources */, 9494928411E5178D0019BC29 /* cogit.c in Sources */, 9494928511E5178D0019BC29 /* gcc3x-cointerp.c in Sources */, 949492CA11E51C6B0019BC29 /* sqExternalSemaphores.c in Sources */, 949492CB11E51C6B0019BC29 /* sqHeapMap.c in Sources */, 949492CC11E51C6B0019BC29 /* sqTicker.c in Sources */, 9494933211E527180019BC29 /* sqUnixHeartbeat.c in Sources */, 9494933311E527180019BC29 /* sqUnixThreads.c in Sources */, 9494933411E527180019BC29 /* sqUnixVMProfile.c in Sources */, 949493C111E52ADE0019BC29 /* aio.c in Sources */, 943B9B2A1235BDD20056205E /* sqMacHostWindow.m in Sources */, 040F20C212CE0FFB008BA0CB /* UnixOSProcessPlugin.c in Sources */, 040F20C812CE1057008BA0CB /* Squeak3D.c in Sources */, 040F20CB12CE10AC008BA0CB /* ClipboardExtendedPlugin.c in Sources */, 040F20E312CE1283008BA0CB /* ObjectiveCPlugin.c in Sources */, 040F22FC12CE1752008BA0CB /* SoundPlugin.c in Sources */, 040F230712CE1AE2008BA0CB /* SqueakFFIPrims.c in Sources */, 040F230E12CE1B28008BA0CB /* HostWindowPlugin.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 947E64DC10AA18FE00D3B69E /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( 947E64DD10AA18FE00D3B69E /* English */, ); name = MainMenu.xib; sourceTree = "<group>"; }; 94B6E9DC10BC777A00333E9E /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( 94B6E9D910BC775E00333E9E /* English */, ); name = Localizable.strings; path = ..; sourceTree = "<group>"; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 9427E3A612627B12002DCA6D /* Distribution Store */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = SQUEAK_BUILTIN_PLUGIN; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/uuid; PREBINDING = NO; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "4D1323CE-3998-4FF8-AB83-49838083E965"; SDKROOT = iphoneos4.1; }; name = "Distribution Store"; }; 9427E3A712627B12002DCA6D /* Distribution Store */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; CODE_SIGN_ENTITLEMENTS = Entitlements.plist; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = SqueakNoOGLIPhone_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUGVM=0", "STACKVM=1", "NDEBUG=1", "COGMTVM=0", "USE_GLOBAL_STRUCT=0", "BASE_HEADER_SIZE=4", TARGET_OS_IS_IPHONE, XXXUSE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, "ISQUEAK_IMAGE=\"iPhone\"", "ISQUEAK_SOURCES=\"PharoV10\"", ); GCC_THUMB_SUPPORT = NO; GCC_VERSION = 4.2; INFOPLIST_FILE = "Info-iPhone.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "-fno-cse-follow-jumps", "-finline-functions", "-O3", "-fno-gcse", "-fomit-frame-pointer", ); PRODUCT_NAME = Squeak; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "D0FAB1BA-D41B-4D7E-A984-469B9016ACB9"; SDKROOT = iphoneos4.1; TARGETED_DEVICE_FAMILY = 2; }; name = "Distribution Store"; }; 9427E3A812627B12002DCA6D /* Distribution Store */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = i386; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_ENABLE_SSE41_EXTENSIONS = YES; GCC_ENABLE_SSE42_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREFIX_HEADER = SqueakPureObjc_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUGVM=0", "NDEBUG=1", "COGMTVM=0", "USE_GLOBAL_STRUCT=0", "BASE_HEADER_SIZE=4", BUILD_FOR_OSX, USE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, ); GCC_VERSION = ""; INFOPLIST_FILE = "SqueakPureObjc-InfoCOG.plist"; MACOSX_DEPLOYMENT_TARGET = 10.5; PER_ARCH_CFLAGS_i386 = "-DLSB_FIRST -mfpmath=sse -finline-functions -fomit-frame-pointer -fno-cse-follow-jumps -fno-gcse -mtune=prescott -march=pentium-m -falign-functions=16"; PRODUCT_NAME = Squeak; "PROVISIONING_PROFILE[sdk=macosx*]" = "4D1323CE-3998-4FF8-AB83-49838083E965"; SDKROOT = macosx10.6; }; name = "Distribution Store"; }; 947E5F3610A9FD0400D3B69E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = "-DSQUEAK_BUILTIN_PLUGIN"; GCC_THUMB_SUPPORT = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/uuid; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = iphoneos4.1; }; name = Debug; }; 947E5F3710A9FD0400D3B69E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; CODE_SIGN_ENTITLEMENTS = ""; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = SqueakNOOGLIPhone_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "NDEBUG=1", xxxUSE_INLINE_MEMORY_ACCESSORS, "STACKVM=1", "COGMTVM=0", "USE_GLOBAL_STRUCT=1", NO_ISNAN, "BASE_HEADER_SIZE=4", TARGET_OS_IS_IPHONE, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, "ISQUEAK_IMAGE=\"iPhone\"", "ISQUEAK_SOURCES=\"PharoV10\"", "DEBUGVM=0", ); GCC_THUMB_SUPPORT = NO; GCC_VERSION = 4.2; INFOPLIST_FILE = "Info-iPhone.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.1.3; PRODUCT_NAME = Squeak; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphoneos4.1; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 947E62F910AA098300D3B69E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = i386; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = SqueakPureObjc_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUGVM=0", "COGMTVM=0", "USE_GLOBAL_STRUCT=0", NO_ISNAN, "BASE_HEADER_SIZE=4", BUILD_FOR_OSX, USE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, ); GCC_VERSION = 4.2; GCC_WARN_64_TO_32_BIT_CONVERSION = NO; INFOPLIST_FILE = "SqueakPureObjc-InfoCOG.plist"; MACOSX_DEPLOYMENT_TARGET = 10.5; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; PER_ARCH_CFLAGS_i386 = "-DLSB_FIRST"; PRODUCT_NAME = Squeak; SDKROOT = macosx10.6; }; name = Debug; }; 947E62FB10AA098300D3B69E /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = i386; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Don't Code Sign"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_ENABLE_SSE41_EXTENSIONS = YES; GCC_ENABLE_SSE42_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREFIX_HEADER = SqueakPureObjc_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUGVM=0", "NDEBUG=1", "COGMTVM=0", "USE_GLOBAL_STRUCT=0", "BASE_HEADER_SIZE=4", BUILD_FOR_OSX, USE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, ); GCC_VERSION = ""; INFOPLIST_FILE = "SqueakPureObjc-InfoCOG.plist"; MACOSX_DEPLOYMENT_TARGET = 10.5; PER_ARCH_CFLAGS_i386 = "-DLSB_FIRST -mfpmath=sse -finline-functions -fomit-frame-pointer -fno-cse-follow-jumps -fno-gcse -mtune=prescott -march=pentium-m -falign-functions=16"; PRODUCT_NAME = Squeak; SDKROOT = macosx10.5; }; name = Distribution; }; 9480CD150E5C7D9300C32178 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; GCC_C_LANGUAGE_STANDARD = c99; GCC_PREPROCESSOR_DEFINITIONS = SQUEAK_BUILTIN_PLUGIN; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/uuid; PREBINDING = NO; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "4D1323CE-3998-4FF8-AB83-49838083E965"; SDKROOT = iphoneos4.1; }; name = Distribution; }; 9480CD160E5C7D9300C32178 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; CODE_SIGN_ENTITLEMENTS = Entitlements.plist; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Corporate Smalltalk Consulting Ltd"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = SqueakNoOGLIPhone_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUGVM=0", "STACKVM=1", "NDEBUG=1", "COGMTVM=0", "USE_GLOBAL_STRUCT=0", "BASE_HEADER_SIZE=4", TARGET_OS_IS_IPHONE, XXXUSE_INLINE_MEMORY_ACCESSORS, HAVE_SYS_TIME_H, HAVE_NANOSLEEP, SQUEAK_BUILTIN_PLUGIN, "ISQUEAK_IMAGE=\"iPhone\"", "ISQUEAK_SOURCES=\"PharoV10\"", ); GCC_THUMB_SUPPORT = NO; GCC_VERSION = 4.2; INFOPLIST_FILE = "Info-iPhone.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "-fno-cse-follow-jumps", "-finline-functions", "-O3", "-fno-gcse", "-fomit-frame-pointer", ); PRODUCT_NAME = Squeak; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "813AC9F6-39F6-492C-8710-8D1C5D88E049"; SDKROOT = iphoneos4.2; TARGETED_DEVICE_FAMILY = 2; }; name = Distribution; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "SqueakNoOGLIPhone" */ = { isa = XCConfigurationList; buildConfigurations = ( 947E5F3710A9FD0400D3B69E /* Debug */, 9480CD160E5C7D9300C32178 /* Distribution */, 9427E3A712627B12002DCA6D /* Distribution Store */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; 947E62F810AA098300D3B69E /* Build configuration list for PBXNativeTarget "SqueakPureObjc" */ = { isa = XCConfigurationList; buildConfigurations = ( 947E62F910AA098300D3B69E /* Debug */, 947E62FB10AA098300D3B69E /* Distribution */, 9427E3A812627B12002DCA6D /* Distribution Store */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SqueakPureObjcCogVM" */ = { isa = XCConfigurationList; buildConfigurations = ( 947E5F3610A9FD0400D3B69E /* Debug */, 9480CD150E5C7D9300C32178 /* Distribution */, 9427E3A612627B12002DCA6D /* Distribution Store */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } ================================================ FILE: vm/src/from_squeak/iOS/vm/SqueakPureObjc_Prefix.pch ================================================ // // Prefix header for all source files of the 'Untitled2' target in the 'Untitled2' project // #ifdef __OBJC__ #import <Cocoa/Cocoa.h> #endif ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMAbstractEvent.h ================================================ // // RoarVMAbstractEvent.h // RoarVMOnIPad // #import <Foundation/Foundation.h> #import "sq.h" #import "SqueakUIController.h" typedef enum {RoarVMEventLocationOffset, RoarVMEventLocationPrevious, RoarVMEventLocationAbsolute, RoarVMEventLocationRelative} RoarVMEventLocationType; @interface RoarVMAbstractEvent : NSObject { int touches; int taps; CGPoint location; } + (void) enqueueFrom: (UIGestureRecognizer*) recognizer controller: (SqueakUIController*) controller where: (RoarVMEventLocationType) where; + (RoarVMAbstractEvent*) newFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where; - (void) initFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where; - (void) processInto: (sqInputEvent*)evt; + (CGPoint) adjustLocation: (CGPoint) p size: (CGSize) s; + (CGPoint) leftmostLocationInView: (UIView*) view recognizer: (UIGestureRecognizer*) recognizer ; - (CGPoint) computeLocationFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where; - (BOOL) resetsRelativeOffset; @property (nonatomic, readonly) CGPoint location; @property (nonatomic,assign) int touches; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMAbstractEvent.m ================================================ // // RoarVMAbstractEvent.m // RoarVMOnIPad // #import "sq.h" #import "RoarVMAbstractEvent.h" #import "sqSqueakIPhoneApplication.h" #import "sqSqueakIPhoneApplication+events.h" #import "SqueakNoOGLIPhoneAppDelegate.h" #import "UIGestureRecognizer+RoarVMEvents.h" extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; static const char* typeString(RoarVMEventLocationType t) { switch (t) { case RoarVMEventLocationRelative: return "relative"; case RoarVMEventLocationAbsolute: return "absolute"; case RoarVMEventLocationPrevious: return "previous"; case RoarVMEventLocationOffset: return "offset"; } } @implementation RoarVMAbstractEvent @synthesize location, touches; - (void ) initFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where { touches = recognizer.numberOfTouches; taps = recognizer.numberOfTapsRequired; location = [self computeLocationFrom: recognizer view: view where: where]; } - (BOOL) resetsRelativeOffset { return NO; } - (CGPoint) computeLocationFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where { static BOOL inited = NO; static BOOL nextWillEstablishRelativeOffset = YES; static CGPoint lastLocation; static CGPoint prevTouchLocation; if (!inited) { inited = YES; lastLocation = CGPointMake(CGRectGetMidX(view.frame), CGRectGetMidY(view.frame)); } CGPoint touchLocation = [[self class] leftmostLocationInView: view recognizer: recognizer]; switch (where) { case RoarVMEventLocationPrevious: break; case RoarVMEventLocationAbsolute: lastLocation = touchLocation; break; case RoarVMEventLocationOffset: lastLocation = [[self class] adjustLocation: touchLocation size: view.frame.size]; break; case RoarVMEventLocationRelative: if (!nextWillEstablishRelativeOffset) { lastLocation.x += touchLocation.x - prevTouchLocation.x; lastLocation.y += touchLocation.y - prevTouchLocation.y; } break; } prevTouchLocation = touchLocation; nextWillEstablishRelativeOffset = where != RoarVMEventLocationRelative || [self resetsRelativeOffset]; return lastLocation; } - (void) processInto: (sqInputEvent*)evt { } + (RoarVMAbstractEvent*) newFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where { RoarVMAbstractEvent* evt = [self new]; [evt initFrom: recognizer view: view where: where]; return evt; } + (void) enqueueFrom: (UIGestureRecognizer*) recognizer controller: (SqueakUIController*) controller where: (RoarVMEventLocationType) where { RoarVMAbstractEvent* e = [self newFrom: recognizer view: controller.view where: where]; controller.cursor.center = e.location; [(sqSqueakIPhoneApplication *) gDelegateApp.squeakApplication enqueueRoarVMEvent: e]; } + (CGPoint) adjustLocation: (CGPoint) p size: (CGSize) s { static const float offsetUp = 100; return CGPointMake(p.x, s.height - p.y > offsetUp ? p.y - offsetUp : 2 * p.y - s.height); } + (CGPoint) leftmostLocationInView: (UIView*) view recognizer: (UIGestureRecognizer*) recognizer { CGPoint result = CGPointMake(INFINITY, INFINITY); NSUInteger nt = [recognizer numberOfTouches]; for (NSUInteger i = 0; i < nt; ++i) { CGPoint p = [recognizer locationOfTouch:i inView: view]; if (p.x < result.x) result = p; } return result; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMMouseEvent.h ================================================ // // RoarVMMouseEvent.h // RoarVMOnIPad // #import <Foundation/Foundation.h> #import "RoarVMAbstractEvent.h" @interface RoarVMMouseEvent : RoarVMAbstractEvent { int buttonBits; // RedButtonBit YellowButtonBit BlueButtonBit } - (int) buttonBitsFor: (UIGestureRecognizer*) recognizer; @property (nonatomic,assign) int buttonBits; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMMouseEvent.m ================================================ // // RoarVMMouseEvent.m // RoarVMOnIPad // #import "RoarVMMouseEvent.h" @implementation RoarVMMouseEvent @synthesize buttonBits; - (void) processInto: (sqInputEvent*)evt { sqMouseEvent* me = (sqMouseEvent*)evt; me->type = EventTypeMouse; me->timeStamp = 0; // fix later me->x = lround(location.x); me->y = lround(location.y); me->buttons = buttonBits; me->modifiers = 0; // fix later me->nrClicks = 0; me->windowIndex = 0; // is this right? } - (void) initFrom: (UIGestureRecognizer*) recognizer view: (UIView*) view where: (RoarVMEventLocationType) where { [super initFrom: recognizer view: view where: where]; buttonBits = [self buttonBitsFor: recognizer]; } - (int) buttonBitsFor: (UIGestureRecognizer*) recognizer { if ( [recognizer isKindOfClass: [UITapGestureRecognizer class]]) { switch (touches) { case 1: return RedButtonBit; case 2: return YellowButtonBit; case 3: return BlueButtonBit; default: return 0; } } if ( [recognizer isKindOfClass: [UILongPressGestureRecognizer class]]) { switch (touches) { case 1: return 0; case 2: return RedButtonBit; case 3: return YellowButtonBit; case 4: return BlueButtonBit; default: return 0; } } return 0; } @end; ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMMouseUpEvent.h ================================================ // // RoarVMMouseUpEvent.h // RoarVMOnIPad // // Created by David Ungar on 4/13/11. // Copyright 2011 IBM. All rights reserved. // #import <Foundation/Foundation.h> # import "RoarVMMouseEvent.h" @interface RoarVMMouseUpEvent : RoarVMMouseEvent { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/RoarVMMouseUpEvent.m ================================================ // // RoarVMMouseUpEvent.m // RoarVMOnIPad // // Created by David Ungar on 4/13/11. // Copyright 2011 IBM. All rights reserved. // #import "RoarVMMouseUpEvent.h" @implementation RoarVMMouseUpEvent - (int) buttonBitsFor: (UIGestureRecognizer*) recognizer { return 0; } - (BOOL) resetsRelativeOffset { return YES; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakNoOGLIPhoneAppDelegate.h ================================================ // // SqueakNoOGLIPhoneAppDelegate.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/15/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> #import "SqueakUIView.h" #import "SqueakUIController.h" #import "sqSqueakAppDelegate.h" #import "sqiPhoneScreenAndWindow.h" @interface SqueakNoOGLIPhoneAppDelegate : sqSqueakAppDelegate <UIApplicationDelegate,UIScrollViewDelegate,UIAccelerometerDelegate,CLLocationManagerDelegate> { IBOutlet UIWindow *window; IBOutlet SqueakUIView *mainView; //This is the squeak screen surface IBOutlet SqueakUIController *viewController; //This controler manages the ability to do orientation UIScrollView *scrollView; //This scroll view wrapps the mainView sqiPhoneScreenAndWindow *screenAndWindow; } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration; - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error; - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation; - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application; // try to clean up as much memory as possible. next step is to terminate app - (void) zoomToOrientation:(UIInterfaceOrientation)o animated:(BOOL)animated; @property (nonatomic,retain) UIWindow *window; @property (nonatomic,retain) SqueakUIView *mainView; @property (nonatomic,retain) UIScrollView *scrollView; @property (nonatomic,retain) SqueakUIController *viewController; @property (nonatomic,retain) sqiPhoneScreenAndWindow *screenAndWindow; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakNoOGLIPhoneAppDelegate.m ================================================ // // SqueakNoOGLIPhoneAppDelegate.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/15/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <UIKit/UIKit.h> #import "SqueakNoOGLIPhoneAppDelegate.h" #import "sqSqueakIPhoneApplication.h" #import "sqiPhoneScreenAndWindow.h" #import "sqSqueakIPhoneInfoPlistInterface.h" #import "SqueakUIViewCALayer.h" #import "SqueakUIViewOpenGL.h" extern struct VirtualMachine* interpreterProxy; SqueakNoOGLIPhoneAppDelegate *gDelegateApp; @implementation SqueakNoOGLIPhoneAppDelegate @synthesize window; @synthesize mainView; @synthesize scrollView; @synthesize viewController; @synthesize screenAndWindow; - (sqSqueakMainApplication *) makeApplicationInstance { return [sqSqueakIPhoneApplication new]; } - (void)applicationDidFinishLaunching:(UIApplication *)application { #warning this is wrong, need to get shared application gDelegateApp = self; mainView = null; scrollView = null; squeakApplication = [self makeApplicationInstance]; screenAndWindow = [sqiPhoneScreenAndWindow new]; [self.squeakApplication setupEventQueue]; [self singleThreadStart]; //[self workerThreadStart]; } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.mainView; } - (id) createPossibleWindow { if (gDelegateApp.mainView == nil) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSMethodSignature * methodSignature = [gDelegateApp methodSignatureForSelector:@selector(makeMainWindowOnMainThread)]; NSInvocation *redrawInv = [NSInvocation invocationWithMethodSignature: methodSignature]; [redrawInv setTarget: gDelegateApp]; [redrawInv setSelector:@selector(makeMainWindowOnMainThread)]; [redrawInv performSelectorOnMainThread: @selector(invoke) withObject: nil waitUntilDone: YES]; [pool drain]; } return self.window; } - (void) zoomToOrientation:(UIInterfaceOrientation)o animated:(BOOL)animated { /* Magic eToys code, leave this here to be nice.. Don't use unless you know what you are doing? CGRect zoomRect; zoomRect.origin.x = 0; zoomRect.origin.y = 0; if (UIInterfaceOrientationIsPortrait(o)) { zoomRect.size.width = 1200 * 4 / 3; } else { zoomRect.size.width = 1200 * 3 / 4; } zoomRect.size.height = zoomRect.size.width * 3 / 4; [self.scrollView zoomToRect: zoomRect animated: animated]; */ } - (Class) whatRenderCanWeUse { // Ok the proper way is to get the glGetString() extensions, but at this point open/gl is not setup. // So bail and decide on operating system version.. // BOOL hasGL_APPLE_texture_2D_limited_npot = (0 != strstr((char *)glGetString(GL_EXTENSIONS), "GL_APPLE_texture_2D_limited_npot")); // return (hasGL_APPLE_texture_2D_limited_npot) ? [SqueakUIViewOpenGL class] : [SqueakUIViewCALayer class]; // The device must be running running iOS 3.2 or later. NSString *reqSysVer = @"3.2"; NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending); return (osVersionSupported) ? [SqueakUIViewOpenGL class] : [SqueakUIViewCALayer class]; } - (void) makeMainWindowOnMainThread //This is fired via a cross thread message send from logic that checks to see if the window exists in the squeak thread. { // Set up content view // The application frame includes the status area if needbe. CGRect mainScreenSize = [[UIScreen mainScreen] applicationFrame]; BOOL useScrollingView = [(sqSqueakIPhoneInfoPlistInterface*)self.squeakApplication.infoPlistInterfaceLogic useScrollingView]; if (useScrollingView) { scrollView = [[UIScrollView alloc ] initWithFrame: mainScreenSize]; //Now setup the true view size as the width/height * 2.0 so we can have a larger squeak window and zoom in/out. CGRect fakeScreenSize = mainScreenSize; fakeScreenSize.origin.x = 0; fakeScreenSize.origin.y = 0; fakeScreenSize.size.width *= 2.0; fakeScreenSize.size.height *= 2.0; /* eToys setup fakeScreenSize.size.width = 1200; fakeScreenSize.size.height = 900; */ mainView = [[[self whatRenderCanWeUse] alloc] initWithFrame: fakeScreenSize]; mainView.backgroundColor = [UIColor blackColor]; mainView.multipleTouchEnabled = YES; mainView.autoresizingMask = UIViewAutoresizingNone; self.mainView.clearsContextBeforeDrawing = NO; //Setup the scroll view which wraps the mainView self.scrollView.scrollEnabled = useScrollingView; self.scrollView.clearsContextBeforeDrawing = NO; self.scrollView.canCancelContentTouches = NO; self.scrollView.minimumZoomScale = 0.5; self.scrollView.maximumZoomScale = 4.0; self.scrollView.delegate = self; self.scrollView.backgroundColor = [UIColor blackColor]; self.scrollView.autoresizesSubviews=YES; self.scrollView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth); self.viewController = [SqueakUIController new]; self.viewController.view = self.scrollView; [self zoomToOrientation: UIInterfaceOrientationPortrait animated: NO]; [self.scrollView addSubview: self.mainView]; [window addSubview: self.scrollView]; } else { CGRect fakeScreenSize = mainScreenSize; mainView = [[[self whatRenderCanWeUse] alloc] initWithFrame: fakeScreenSize]; self.mainView.clearsContextBeforeDrawing = NO; [self.mainView setMultipleTouchEnabled: YES]; self.viewController = [SqueakUIController new]; self.viewController.view = self.mainView; [window addSubview: self.mainView]; } [window makeKeyAndVisible]; [self.viewController setupRecognizers]; [self.viewController addCursor]; } - (void)dealloc { [mainView release]; [scrollView release]; [viewController release]; [window release]; [screenAndWindow release]; [super dealloc]; } - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { NSMutableArray* data = [NSMutableArray new]; [acceleration retain]; [data addObject: [NSNumber numberWithInteger: 2]]; [data addObject: acceleration]; [[[self squeakApplication] eventQueue] addItem: data]; [data release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSMutableArray* data = [NSMutableArray new]; [manager retain]; [error retain]; [data addObject: [NSNumber numberWithInteger: 3]]; [data addObject: manager]; [data addObject: error]; [[[self squeakApplication] eventQueue] addItem: data]; [data release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSMutableArray* data = [NSMutableArray new]; [manager retain]; [newLocation retain]; [oldLocation retain]; [data addObject: [NSNumber numberWithInteger: 4]]; [data addObject: manager]; [data addObject: newLocation]; [data addObject: oldLocation]; [[[self squeakApplication] eventQueue] addItem: data]; [data release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { // try to clean up as much memory as possible. next step is to terminate app /* Actually sending the message to the image is nice, but it's impossible to clean up things here on the VM level. It could be some Object-C thing is going on, like URL fetching, or JPEG rendering, if so the squeak application can decide what to do, or ignore it which leads to death in a few seconds */ NSMutableArray* data = [NSMutableArray new]; [data addObject: [NSNumber numberWithInteger: 5]]; [[[self squeakApplication] eventQueue] addItem: data]; [data release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } - (void)applicationWillTerminate:(UIApplication *)application { [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplicationWillTerminate" object: self]; } @end /* unableToReadImageError and others, where do they go? */ /* > kCLLocationAccuracyBest = -1.0 > kCLLocationAccuracyNearestTenMeters = 10.0 > kCLLocationAccuracyHundredMeters = 100.0 > kCLLocationAccuracyKilometer = 1000.0 > kCLLocationAccuracyThreeKilometers = 3000.0 */ ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIController.h ================================================ // // SqueakUIController.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/8/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ # ifdef ROAR_VM @interface SqueakUIController : UIViewController <UIGestureRecognizerDelegate, UIKeyInput> { UIButton* cursor; UILongPressGestureRecognizer* longRecognizers[4]; } - (void) setupRecognizers; - (void) addCursor; - (void)handleTapFrom:(UITapGestureRecognizer *)recognizer; - (void)finishTapFrom:(UITapGestureRecognizer *)recognizer; - (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognize; - (void)handleLongPressFrom:(UILongPressGestureRecognizer *)recognizer; - (void)startEnteringText; @property (nonatomic,assign) UIButton* cursor; # else @interface SqueakUIController : UIViewController # endif // ROAR_VM @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIController.m ================================================ // // SqueakUIController.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/8/08.SqueakNoOGLIPhoneAppDelegate.m: [[[self squeakApplication] eventQueue] addItem: data]; /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "SqueakNoOGLIPhoneAppDelegate.h" #import "SqueakUIController.h" #import "sqiPhoneScreenAndWindow.h" #import "sq.h" #import "sqSqueakIPhoneApplication.h" #import "sqSqueakIPhoneApplication+events.h" #import "RoarVMMouseUpEvent.h" #import "RoarVMSwipeEvent.h" extern struct VirtualMachine* interpreterProxy; extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; static sqWindowEvent evt; @implementation SqueakUIController @synthesize cursor; - (void) setupRecognizers { for ( int touches = 1; touches <= 3; ++touches ) { UIGestureRecognizer *fewerTapRecognizer = nil; for ( int taps = 1; taps <= 2; ++taps) { UITapGestureRecognizer *r; r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapFrom:)]; r.numberOfTapsRequired = taps; r.numberOfTouchesRequired = touches; r.delaysTouchesBegan = NO; r.delaysTouchesEnded = NO; r.cancelsTouchesInView = NO; [self.view addGestureRecognizer:r]; r.delegate = self; // if (fewerTapRecognizer != nil) [fewerTapRecognizer requireGestureRecognizerToFail: r]; fewerTapRecognizer = r; } } for ( int taps = 0; taps <= 0; ++taps) { for (int touches = 1; touches <= sizeof(longRecognizers)/sizeof(longRecognizers[0]); ++touches) { UILongPressGestureRecognizer *r; r = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressFrom:)]; r.delaysTouchesBegan = NO; r.delaysTouchesEnded = NO; r.cancelsTouchesInView = YES; r.numberOfTouchesRequired = touches; r.numberOfTapsRequired = taps; CFTimeInterval minSecs = 0.1; // if zero don't get taps, or long press changed r.minimumPressDuration = minSecs; r.allowableMovement = 10000; [self.view addGestureRecognizer: r]; longRecognizers[touches-1] = r; r.delegate = self; } } static int dirs[] = { UISwipeGestureRecognizerDirectionDown, UISwipeGestureRecognizerDirectionLeft, UISwipeGestureRecognizerDirectionRight, UISwipeGestureRecognizerDirectionUp}; for (int touches = 3; touches <= 4; ++touches) for (int i = 0; i < sizeof(dirs)/sizeof(dirs[0]); ++i) { UISwipeGestureRecognizer *spr; spr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)]; spr.direction = dirs[i]; spr.delaysTouchesBegan = NO; spr.delaysTouchesEnded = NO; spr.cancelsTouchesInView = YES; spr.numberOfTouchesRequired = touches; [self.view addGestureRecognizer: spr]; spr.delegate = self; } } static const char* stateString(UIGestureRecognizerState s) { switch (s) { case UIGestureRecognizerStatePossible: return "Possible"; case UIGestureRecognizerStateBegan: return "Began"; case UIGestureRecognizerStateChanged: return "Changed"; case UIGestureRecognizerStateRecognized: return "Recognized"; case UIGestureRecognizerStateCancelled: return "Cancelled"; case UIGestureRecognizerStateFailed: return "Failed"; default: return "Unknown state"; } } - (void)handleTapFrom:(UITapGestureRecognizer *)recognizer { if (recognizer.numberOfTapsRequired > 1) { [self startEnteringText]; return; } [RoarVMMouseEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationAbsolute]; [self performSelector: @selector(finishTapFrom:) withObject: recognizer afterDelay: 0.3]; } - (void) finishTapFrom:(UITapGestureRecognizer *) recognizer { [RoarVMMouseUpEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationPrevious]; } - (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer { [RoarVMSwipeEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationAbsolute]; } - (BOOL)canBecomeFirstResponder { return YES; } - (BOOL) hasText {return NO;} - (void)startEnteringText { [self becomeFirstResponder]; } - (void) insertText:(NSString *)text { [(SqueakUIView*)self.view recordCharEvent: text]; } - (void) deleteBackward { static NSString* backspace = nil; if (!backspace) { backspace = [NSString stringWithCString: "\b" encoding: NSASCIIStringEncoding]; [backspace retain]; } [self insertText: backspace]; } - (void)handleLongPressFrom:(UILongPressGestureRecognizer *)recognizer { switch ( recognizer.state ) { case UIGestureRecognizerStateBegan: [RoarVMMouseEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationRelative]; break; case UIGestureRecognizerStateChanged: [RoarVMMouseEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationRelative]; break; case UIGestureRecognizerStateEnded: [RoarVMMouseUpEvent enqueueFrom: recognizer controller: self where: RoarVMEventLocationRelative]; //for (int i = 1; i < recognizer.numberOfTouchesRequired; ++i) // longRecognizers[i-1].enabled = YES; break; default: break; } } # if 0 - (BOOL) gestureRecognizer: (UIGestureRecognizer*) r1 shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)r2 { if (![r1 isKindOfClass: [UILongPressGestureRecognizer class]]) return NO; if (![r2 isKindOfClass: [UILongPressGestureRecognizer class]]) return NO; return YES; } - (BOOL) gestureRecognizerShouldBegin: (UIGestureRecognizer*) r { if (![r isKindOfClass: [UILongPressGestureRecognizer class]]) return YES; UILongPressGestureRecognizer* lpr = (UILongPressGestureRecognizer*)r; for (int i = 1; i < lpr.numberOfTouchesRequired; ++i) longRecognizers[i-1].enabled = NO; return YES; } # endif // Subclasses override this method to define how the view they control will respond to device rotation - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { //Called by Main Thread, beware of calling Squeak routines in Squeak Thread return YES; } - (void) pushEventToQueue { NSMutableArray* data = [NSMutableArray new]; [data addObject: [NSNumber numberWithInteger: 8]]; [data addObject: [NSData dataWithBytes:(const void *) &evt length: sizeof(sqInputEvent)]]; [[gDelegateApp.squeakApplication eventQueue] addItem: data]; [data release]; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [gDelegateApp zoomToOrientation: toInterfaceOrientation animated: YES]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { UIInterfaceOrientation o = [[UIApplication sharedApplication] statusBarOrientation]; /* etoys rotate for keyboard! if (UIInterfaceOrientationIsPortrait(o)) [gDelegateApp.mainView becomeFirstResponder]; else [gDelegateApp.mainView resignFirstResponder]; */ CGRect mainScreenSize = [[UIScreen mainScreen] applicationFrame]; CGRect f; f.origin.x = 0.0f; f.origin.y = 0.0f; f.size.width = UIInterfaceOrientationIsPortrait(o) ? mainScreenSize.size.width : mainScreenSize.size.height; f.size.height = UIInterfaceOrientationIsPortrait(o) ? mainScreenSize.size.height : mainScreenSize.size.width; evt.type = EventTypeWindow; evt.timeStamp = (int) ioMSecs(); evt.action = WindowEventPaint; evt.value1 = (int) f.origin.x; evt.value2 = (int) f.origin.y; evt.value3 = (int) f.size.width;; evt.value4 = (int) f.size.height; evt.windowIndex = 1; // f.size.width *= 2.0; // f.size.height *= 2.0; // gDelegateApp.mainView.frame = f; // [gDelegateApp.scrollView sizeToFit]; [self performSelector: @selector(pushEventToQueue) withObject: nil afterDelay: 1.0]; } - (void) addCursor { cursor = [UIButton buttonWithType: UIButtonTypeRoundedRect]; cursor.alpha = 0.66; cursor.frame = CGRectMake(100, 100, 20, 20); [self.view addSubview: cursor]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIView.h ================================================ // // SqueakUIView.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/20/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #include <AvailabilityInternal.h> #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2 @interface SqueakUIView : UIView <UIKeyInput> { #else @interface SqueakUIView : UIView { #endif CGColorSpaceRef colorspace; void *squeakTheDisplayBits; } - (void) recordCharEvent:(NSString *) unicodeString; - (void) drawThelayers; - (void) drawImageUsingClip: (CGRect) clip; @property (nonatomic,assign) void *squeakTheDisplayBits; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIView.m ================================================ // // SqueakUIView.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/20/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "SqueakUIView.h" #import "sqSqueakMainApplication.h" #import "SqueakNoOGLIPhoneAppDelegate.h" #import "sqSqueakIPhoneApplication+events.h" #import "sqiPhoneScreenAndWindow.h" #import "sq.h" extern struct VirtualMachine* interpreterProxy; extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; @implementation SqueakUIView : UIView ; @synthesize squeakTheDisplayBits; - (id)initWithFrame:(CGRect) aFrame { self = [super initWithFrame: aFrame]; self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; colorspace = CGColorSpaceCreateDeviceRGB(); return self; } - (void) dealloc { [super dealloc]; // if (colorspace) // CGColorSpaceRelease(colorspace); } - (void) drawThelayers { } - (void) drawImageUsingClip: (CGRect) clip { } # ifndef ROAR_VM // Handles the start of a touch - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //Called by Main Thread, beware of calling Squeak routines in Squeak Thread [(sqSqueakIPhoneApplication *) gDelegateApp.squeakApplication recordTouchEvent: touches type: UITouchPhaseBegan]; } // Handles the continuation of a touch. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { //Called by Main Thread, beware of calling Squeak routines in Squeak Thread [(sqSqueakIPhoneApplication *) gDelegateApp.squeakApplication recordTouchEvent: touches type: UITouchPhaseMoved]; } // Handles the end of a touch event. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { //Called by Main Thread, beware of calling Squeak routines in Squeak Thread [(sqSqueakIPhoneApplication *) gDelegateApp.squeakApplication recordTouchEvent: touches type: UITouchPhaseEnded]; } - (void) touchesCancelled: (NSSet *) touches withEvent: (UIEvent *) event { //Called by Main Thread, beware of calling Squeak routines in Squeak Thread [(sqSqueakIPhoneApplication *) gDelegateApp.squeakApplication recordTouchEvent: touches type: UITouchPhaseCancelled]; } # endif // !ROAR_VM - (BOOL)canBecomeFirstResponder { return YES; } - (BOOL)hasText { return YES; } - (void)insertText:(NSString *)text { [self recordCharEvent: text]; } - (void)deleteBackward { unichar delete[1]; delete[0] = 0x08; [self recordCharEvent:[NSString stringWithCharacters: delete length: 1]]; } - (void) pushEventToQueue: (sqInputEvent *) evt { NSMutableArray* data = [NSMutableArray new]; [data addObject: [NSNumber numberWithInteger: 7]]; [data addObject: [NSData dataWithBytes:(const void *) evt length: sizeof(sqInputEvent)]]; [[gDelegateApp.squeakApplication eventQueue] addItem: data]; [data release]; } - (int) figureOutKeyCode: (unichar) unicode { static int unicodeToKeyCode[] = {54, 115, 11, 52, 119, 114, 3, 5, 51, 48, 38, 116, 121, 36, 45, 31, 96, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 53, 123, 124, 126, 125, 49, 18, 39, 20, 21, 23, 26, 39, 25, 29, 67, 69, 43, 27, 47, 44, 29, 18, 19, 20, 21, 23, 22, 26, 28, 25, 41, 41, 43, 24, 47, 44, 19, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37, 46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 33, 42, 30, 22, 27, 50, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37, 46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 33, 42, 30, 50, 117}; if (unicode > 127) return 0; return unicodeToKeyCode[unicode]; } - (void) recordCharEvent:(NSString *) unicodeString { sqKeyboardEvent evt; unichar unicode; unsigned char macRomanCharacter; NSInteger i; NSRange picker; NSUInteger totaLength; evt.type = EventTypeKeyboard; evt.timeStamp = (int) ioMSecs(); picker.location = 0; picker.length = 1; totaLength = [unicodeString length]; for (i=0;i < totaLength;i++) { unicode = [unicodeString characterAtIndex: i]; NSString *lookupString = [[NSString alloc] initWithCharacters: &unicode length: 1]; [lookupString getBytes: &macRomanCharacter maxLength: 1 usedLength: NULL encoding: NSMacOSRomanStringEncoding options: 0 range: picker remainingRange: NULL]; [lookupString release]; // LF -> CR if (macRomanCharacter == 10) macRomanCharacter = 13; evt.pressCode = EventKeyDown; BOOL isUppercase = [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember: unicode]; evt.modifiers = isUppercase ? ShiftKeyBit : 0; evt.charCode = [self figureOutKeyCode: unicode]; unsigned int keyCodeRemembered = evt.charCode; evt.utf32Code = 0; evt.reserved1 = 0; evt.windowIndex = 1; [self pushEventToQueue: (sqInputEvent *)&evt]; evt.charCode = macRomanCharacter; evt.pressCode = EventKeyChar; evt.modifiers = evt.modifiers; if ((evt.modifiers & CommandKeyBit) && (evt.modifiers & ShiftKeyBit)) { /* command and shift */ if ((unicode >= 97) && (unicode <= 122)) { /* convert ascii code of command-shift-letter to upper case */ unicode = unicode - 32; } } evt.utf32Code = unicode; evt.timeStamp++; [self pushEventToQueue: (sqInputEvent *) &evt]; if (YES) { evt.pressCode = EventKeyUp; evt.charCode = keyCodeRemembered; evt.utf32Code = 0; evt.timeStamp++; [self pushEventToQueue: (sqInputEvent *) &evt]; } } interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIViewCALayer.h ================================================ // // SqueakUIViewCALayer.h // SqueakPureObjc // // Created by John M McIntosh on 10-09-09. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <UIKit/UIKit.h> #import "SqueakUIView.h" @interface SqueakUIViewCALayer : SqueakUIView { CALayer *myLayer[4][4]; BOOL dirty[4][4]; CGRect frameForQuartz[4][4]; CGFloat dividedWidth; CGFloat dividedHeight; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIViewCALayer.m ================================================ // // SqueakUIViewCALayer.m // SqueakPureObjc // // Created by John M McIntosh on 10-09-09. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "SqueakUIViewCALayer.h" #import <QuartzCore/QuartzCore.h> #import "sq.h" extern struct VirtualMachine* interpreterProxy; static void MyProviderReleaseData ( void *info, const void *data, size_t size ) { } @implementation SqueakUIViewCALayer - (void)layoutSubviews { CGRect aFrame = self.bounds; dividedWidth = aFrame.size.width/4.0; dividedHeight = aFrame.size.height/4.0; for (int v=0;v<4;v++) { for (int h=0;h<4;h++) { CALayer *setupLayer = [CALayer layer]; [setupLayer setOpaque: YES]; setupLayer.frame = CGRectMake(dividedWidth*h, dividedHeight*v, dividedWidth, dividedHeight); if (myLayer[v][h]) { [self.layer replaceSublayer: myLayer[v][h] with: setupLayer]; myLayer[v][h] = setupLayer; } else { myLayer[v][h] = setupLayer; [self.layer addSublayer: setupLayer]; } frameForQuartz[v][h] = CGRectMake(dividedWidth*h,dividedHeight*(3-v), dividedWidth, dividedHeight); dirty[v][h] = NO; } } } - (CGImageRef) createImageFrom: (void *) dispBitsIndex affectedT: (int) affectedT affectedB: (int) affectedB affectedL: (int) affectedL affectedR: (int) affectedR height: (int) height width: (int) width { const size_t depth = 32; size_t pitch = ((((width)*(depth) + 31) >> 5) << 2); size_t totalSize = pitch * (affectedB-affectedT)-affectedL*4; CGDataProviderRef provider = CGDataProviderCreateWithData (NULL,(void*)dispBitsIndex+ pitch*affectedT + affectedL*4,(size_t) totalSize,MyProviderReleaseData); CGImageRef image = CGImageCreate((size_t) affectedR-affectedL,(size_t) affectedB-affectedT, (size_t) 8 /* bitsPerComponent */, (size_t) depth /* bitsPerPixel */, (size_t) pitch, colorspace, (CGBitmapInfo) kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host , provider, NULL, (bool) 0, kCGRenderingIntentDefault); CGDataProviderRelease(provider); return image; } - (void) drawImageUsingClip: (CGRect) clip { for (int v=0;v<4;v++) { for (int h=0;h<4;h++) { dirty[v][h] = dirty[v][h] || CGRectIntersectsRect(frameForQuartz[v][h],clip); } } } - (void) drawThelayers { sqInt formObj = interpreterProxy->displayObject(); sqInt formPtrOop = interpreterProxy->fetchPointerofObject(0, formObj); void* dispBitsIndex = interpreterProxy->firstIndexableField(formPtrOop); squeakTheDisplayBits = (void*) dispBitsIndex; [CATransaction begin]; [CATransaction setValue: [NSNumber numberWithBool:YES] forKey: kCATransactionDisableActions]; for (int v=0;v<4;v++) { for (int h=0;h<4;h++) { if (dirty[v][h]) { CGRect rect = myLayer[v][h].frame; CGImageRef x= [self createImageFrom: squeakTheDisplayBits affectedT: rect.origin.y affectedB: rect.origin.y+rect.size.height affectedL: rect.origin.x affectedR: rect.origin.x+rect.size.width height: (int) dividedHeight*4 width: (int) dividedWidth*4]; myLayer[v][h].contents = (id)x; CGImageRelease(x); dirty[v][h] = NO; } } } [CATransaction commit]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIViewOpenGL.h ================================================ // // SqueakUIViewOpenGL.h // SqueakPureObjc // // Created by John M McIntosh on 10-09-09. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <UIKit/UIKit.h> #import "SqueakUIView.h" #import <OpenGLES/EAGL.h> #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> #import <OpenGLES/EAGLDrawable.h> #import <QuartzCore/QuartzCore.h> extern struct VirtualMachine* interpreterProxy; // Run-time assertion #if 0 #define rt_assert(expression) assert(expression) #else #define rt_assert(expression) #endif // Catch run-time GL errors #if 0 #define glCheckError() { \ GLenum err = glGetError(); \ if (err != GL_NO_ERROR) { \ fprintf(stderr, "glCheckError: %04x caught at %s:%u\n", err, __FILE__, __LINE__); \ rt_assert(0); \ } \ } #else #define glCheckError() #endif @interface SqueakUIViewOpenGL : SqueakUIView { // The pixel dimensions of the backbuffer GLint backingWidth; GLint backingHeight; GLuint textureId; BOOL clippyIsEmpty; BOOL syncNeeded; CGRect clippy; // OpenGL names for the renderbuffer and framebuffer used to render to this view EAGLContext *context; GLuint viewRenderbuffer, viewFramebuffer; } -(void)setupOpenGL; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIViewOpenGL.m ================================================ // // SqueakUIViewOpenGL.m // SqueakPureObjc // // Created by John M McIntosh on 10-09-09. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "SqueakUIViewOpenGL.h" #import "sq.h" // A class extension to declare private methods @interface SqueakUIViewOpenGL () @property (nonatomic, retain) EAGLContext *context; @end const GLfloat spriteTexcoords[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; @implementation SqueakUIViewOpenGL @synthesize context; + (Class)layerClass { return [CAEAGLLayer class]; } - (id)initWithFrame:(CGRect) aFrame { self = [super initWithFrame: aFrame]; clippyIsEmpty = YES; syncNeeded = NO; // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; //other choice is kEAGLColorFormatRGB565 context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if (!context || ![EAGLContext setCurrentContext:context]) { [self release]; return nil; } [self setupOpenGL]; return self; } -(void)setupOpenGL { // Create system framebuffer object. The backing will be allocated in -reshapeFramebuffer glGenFramebuffersOES(1, &viewFramebuffer);glCheckError(); glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);glCheckError(); glGenRenderbuffersOES(1, &viewRenderbuffer);glCheckError(); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);glCheckError(); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);glCheckError(); } -(GLuint)createTextuerUsingWidth:(GLuint)w Height:(GLuint)h { GLuint handle; glGenTextures(1, &handle);glCheckError(); glBindTexture(GL_TEXTURE_2D, handle);glCheckError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glCheckError(); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glCheckError(); // http://www.khronos.org/registry/gles/extensions/APPLE/APPLE_texture_2D_limited_npot.txt glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);glCheckError(); glDisable(GL_DEPTH_TEST);glCheckError(); glDisableClientState(GL_COLOR_ARRAY);glCheckError(); glEnable(GL_TEXTURE_2D);glCheckError(); glEnableClientState(GL_VERTEX_ARRAY);glCheckError(); glEnableClientState(GL_TEXTURE_COORD_ARRAY);glCheckError(); return handle; } - (void)dealloc { if ([EAGLContext currentContext] == context) [EAGLContext setCurrentContext:nil]; self.context = nil; [super dealloc]; } - (void)layoutSubviews { // Allocate GL color buffer backing, matching the current layer size [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; glCheckError(); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);glCheckError(); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);glCheckError(); rt_assert(GL_FRAMEBUFFER_COMPLETE_OES == glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); if (textureId) { glDeleteTextures(1,&textureId); textureId = 0; } } - (void) drawImageUsingClip: (CGRect) clip { if (clippyIsEmpty){ clippy = clip; clippyIsEmpty = NO; } else { clippy = CGRectUnion(clippy, clip); } syncNeeded = YES; } - (void) drawThelayers { if (syncNeeded) { [self drawRect: clippy]; syncNeeded = NO; clippyIsEmpty = YES; // glFlush(); [EAGLContext setCurrentContext:context]; [context presentRenderbuffer:GL_RENDERBUFFER_OES]; } } - (void)loadTexturesFrom: (void*) lastBitsIndex subRectangle: (CGRect) subRectSqueak { CGRect subRect = subRectSqueak; NSUInteger imageWidth = (NSUInteger)self.bounds.size.width*4; GLfloat spriteVertices[] = { 0.0f,0.0f, self.bounds.size.width,0.0f, 0.0f,self.bounds.size.height, self.bounds.size.width,self.bounds.size.height}; subRect.origin.y = self.bounds.size.height-subRectSqueak.origin.y-subRectSqueak.size.height; void *span = lastBitsIndex+(NSUInteger)subRect.origin.y*imageWidth + (NSUInteger)subRect.origin.x* 4; if (!textureId) { textureId = [self createTextuerUsingWidth: backingWidth Height: backingHeight]; } else { glBindTexture(GL_TEXTURE_2D, textureId);glCheckError(); } for( GLint y = 0; y < (GLint) subRect.size.height; y++ ) { void *row = imageWidth*y + span; glTexSubImage2D( GL_TEXTURE_2D, 0, (GLint)subRect.origin.x, (GLint)subRect.origin.y+y, (GLsizei)subRect.size.width, 1, GL_BGRA, GL_UNSIGNED_BYTE, row );glCheckError(); } glViewport( 0, 0, self.bounds.size.width, self.bounds.size.height);glCheckError(); glMatrixMode(GL_PROJECTION);glCheckError(); glLoadIdentity();glCheckError(); glMatrixMode(GL_MODELVIEW);glCheckError(); glLoadIdentity();glCheckError(); glVertexPointer(2, GL_FLOAT, 0, spriteVertices);glCheckError(); glTexCoordPointer(2, GL_FLOAT, 0, spriteTexcoords); glCheckError(); glOrthof(0, (GLfloat) self.bounds.size.width, 0, (GLfloat) self.bounds.size.height, 0, 1);glCheckError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);glCheckError(); } -(void)drawRect:(CGRect)rect { // NSLog(@" drawRect %f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); sqInt formObj = interpreterProxy->displayObject(); sqInt formPtrOop = interpreterProxy->fetchPointerofObject(0, formObj); void* dispBitsIndex = interpreterProxy->firstIndexableField(formPtrOop); if ( dispBitsIndex ) { [self loadTexturesFrom:dispBitsIndex subRectangle: rect]; } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/SqueakUIViewOpenGLAlternate.m ================================================ // // SqueakUIViewOpenGL.m // SqueakPureObjc // // Created by John M McIntosh on 10-09-09. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "SqueakUIViewOpenGL.h" #import "sq.h" // A class extension to declare private methods @interface SqueakUIViewOpenGL () @property (nonatomic, retain) EAGLContext *context; @end const GLfloat spriteTexcoords[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; @implementation SqueakUIViewOpenGL @synthesize context; + (Class)layerClass { return [CAEAGLLayer class]; } - (id)initWithFrame:(CGRect) aFrame { self = [super initWithFrame: aFrame]; clippyIsEmpty = YES; syncNeeded = NO; // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; //other choice is kEAGLColorFormatRGB565 context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if (!context || ![EAGLContext setCurrentContext:context]) { [self release]; return nil; } [self setupOpenGL]; return self; } -(void)setupOpenGL { // Create system framebuffer object. The backing will be allocated in -reshapeFramebuffer glGenFramebuffersOES(1, &viewFramebuffer);glCheckError(); glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);glCheckError(); glGenRenderbuffersOES(1, &viewRenderbuffer);glCheckError(); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);glCheckError(); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);glCheckError(); } -(GLuint)createTextuerUsingWidth:(GLuint)w Height:(GLuint)h { GLuint handle; glGenTextures(1, &handle);glCheckError(); glBindTexture(GL_TEXTURE_2D, handle);glCheckError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glCheckError(); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glCheckError(); // http://www.khronos.org/registry/gles/extensions/APPLE/APPLE_texture_2D_limited_npot.txt glDisable(GL_DEPTH_TEST);glCheckError(); glDisableClientState(GL_COLOR_ARRAY);glCheckError(); glEnable(GL_TEXTURE_2D);glCheckError(); glEnableClientState(GL_VERTEX_ARRAY);glCheckError(); glEnableClientState(GL_TEXTURE_COORD_ARRAY);glCheckError(); return handle; } - (void)dealloc { if ([EAGLContext currentContext] == context) [EAGLContext setCurrentContext:nil]; self.context = nil; [super dealloc]; } - (void)layoutSubviews { // Allocate GL color buffer backing, matching the current layer size [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; glCheckError(); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);glCheckError(); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);glCheckError(); rt_assert(GL_FRAMEBUFFER_COMPLETE_OES == glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); if (textureId) { glDeleteTextures(1,&textureId); textureId = 0; } } - (void) drawImageUsingClip: (CGRect) clip { if (clippyIsEmpty){ clippy = clip; clippyIsEmpty = NO; } else { clippy = CGRectUnion(clippy, clip); } syncNeeded = YES; } - (void) drawThelayers { if (syncNeeded) { [self drawRect: clippy]; syncNeeded = NO; clippyIsEmpty = YES; // glFlush(); [EAGLContext setCurrentContext:context]; [context presentRenderbuffer:GL_RENDERBUFFER_OES]; } } - (void)loadTexturesFrom: (void*) lastBitsIndex subRectangle: (CGRect) subRectSqueak { CGRect subRect = subRectSqueak; NSUInteger imageWidth = (NSUInteger)self.bounds.size.width*4; GLfloat spriteVertices[] = { 0.0f,0.0f, subRect.size.width,0.0f, 0.0f,subRect.size.height, subRect.size.width,subRect.size.height}; subRect.origin.y = self.bounds.size.height-subRectSqueak.origin.y-subRectSqueak.size.height; void *span = lastBitsIndex+(NSUInteger)subRect.origin.y*imageWidth + (NSUInteger)subRect.origin.x* 4; if (!textureId) { textureId = [self createTextuerUsingWidth: backingWidth Height: backingHeight]; } else { glBindTexture(GL_TEXTURE_2D, textureId);glCheckError(); } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)subRect.size.width, (GLsizei)subRect.size.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);glCheckError(); for( GLint y = 0; y < (GLint) subRect.size.height; y++ ) { void *row = imageWidth*y + span; glTexSubImage2D( GL_TEXTURE_2D, 0, 0, y, (GLsizei)subRect.size.width, 1, GL_BGRA, GL_UNSIGNED_BYTE, row );glCheckError(); } glViewport( subRect.origin.x, subRectSqueak.origin.y, subRect.size.width, subRect.size.height);glCheckError(); glMatrixMode(GL_PROJECTION);glCheckError(); glLoadIdentity();glCheckError(); glMatrixMode(GL_MODELVIEW);glCheckError(); glLoadIdentity();glCheckError(); glVertexPointer(2, GL_FLOAT, 0, spriteVertices);glCheckError(); glTexCoordPointer(2, GL_FLOAT, 0, spriteTexcoords); glCheckError(); glOrthof(0, (GLfloat) subRect.size.width, 0, (GLfloat) subRect.size.height, 0, 1);glCheckError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);glCheckError(); } -(void)drawRect:(CGRect)rect { // NSLog(@" drawRect %f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); sqInt formObj = interpreterProxy->displayObject(); sqInt formPtrOop = interpreterProxy->fetchPointerofObject(0, formObj); void* dispBitsIndex = interpreterProxy->firstIndexableField(formPtrOop); if ( dispBitsIndex ) { [self loadTexturesFrom:dispBitsIndex subRectangle: rect]; } } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/UIGestureRecognizer+RoarVMEvents.h ================================================ // // UIGestureRecognizer+RoarVMEvents.h // RoarVMOnIPad // // Created by David Ungar on 4/13/11. // Copyright 2011 IBM. All rights reserved. // #import <Foundation/Foundation.h> @interface UIGestureRecognizer (UIGestureRecognizer_RoarVMEvents) - (int) numberOfTapsRequired; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/UIGestureRecognizer+RoarVMEvents.m ================================================ // // UIGestureRecognizer+RoarVMEvents.m // RoarVMOnIPad // // Created by David Ungar on 4/13/11. // Copyright 2011 IBM. All rights reserved. // #import "UIGestureRecognizer+RoarVMEvents.h" @implementation UIGestureRecognizer (UIGestureRecognizer_RoarVMEvents) - (int) numberOfTapsRequired { return 0; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+Network.h ================================================ // // sqSqueakIPhoneApplication+Network.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 09/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. // // This example code comes from https://devforums.apple.com/message/26334#26334 #import <Foundation/Foundation.h> #import <SystemConfiguration/SCNetworkReachability.h> @interface UIApplication (NetworkExtensions) +(BOOL)hasActiveWiFiConnection; // fast wi-fi connection +(BOOL)hasNetworkConnection; // any type of internet connection (edge, 3g, wi-fi) @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+Network.m ================================================ // // sqSqueakIPhoneApplication+Network.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 09/02/09. // Copyright 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. // // This example code comes from https://devforums.apple.com/message/26334#26334 // Also see http://developer.apple.com/iphone/library/samplecode/Reachability/listing2.html #import "sqSqueakIPhoneApplication+Network.h" @implementation UIApplication (NetworkExtensions) // fast wi-fi connection +(BOOL)hasActiveWiFiConnection { SCNetworkReachabilityFlags flags; SCNetworkReachabilityRef reachabilityRef; BOOL gotFlags; reachabilityRef = SCNetworkReachabilityCreateWithName(CFAllocatorGetDefault(), [@"0.0.0.0" UTF8String]); gotFlags = SCNetworkReachabilityGetFlags(reachabilityRef, &flags); CFRelease(reachabilityRef); if (!gotFlags) { return NO; } if( flags & kSCNetworkReachabilityFlagsIsWWAN ) { return NO; } if( flags & kSCNetworkReachabilityFlagsReachable ) { return YES; } return NO; } // any type of internet connection (edge, 3g, wi-fi) +(BOOL)hasNetworkConnection { SCNetworkReachabilityFlags flags; SCNetworkReachabilityRef reachabilityRef; BOOL gotFlags; reachabilityRef = SCNetworkReachabilityCreateWithName(CFAllocatorGetDefault(), [@"www.apple.com" UTF8String]); gotFlags = SCNetworkReachabilityGetFlags(reachabilityRef, &flags); CFRelease(reachabilityRef); if (!gotFlags || (flags == 0) ) { return NO; } return YES; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+attributes.h ================================================ // // sqSqueakIPhoneApplication+attributes.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication.h" @interface sqSqueakIPhoneApplication (attributes) - (const char *) getAttribute:(sqInt) indexNumber; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+attributes.m ================================================ // // sqSqueakIPhoneApplication+attributes.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication+attributes.h" #import "sqSqueakMainApplication+attributes.h" #import "sqSqueakMainApplication+vmAndImagePath.h" extern struct VirtualMachine* interpreterProxy; @implementation sqSqueakIPhoneApplication (attributes) - (const char *) getAttribute:(sqInt)indexNumber { //indexNumber is a postive/negative number switch (indexNumber) { case 1001: /* OS type: "unix", "win32", "mac", ... */ return "iPhone"; case 1002: /* OS name: "solaris2.5" on unix, "win95" on win32, ... */ return "iPhone"; case 1003: /* processor architecture: "68k", "x86", "PowerPC", ... */ return "iPhone"; case 1006: /* vm build string */ return "iPhone 2.2.4b1 20-Mar-10 >432619D7-FA70-4449-BEDF-68A74B3E4EF5<"; /* return "iPhone 2.2.3b2 05-Mar-10 >9E99B1C2-0B6B-4944-8B6F-74030D14F3C6<"; return "iPhone 2.2.2b1 17-Feb-10 >18862A37-A8AD-411D-945B-95AE2596AD89<"; return "iPhone 2.1.1b1 06-Jan-10 >3487508B-770D-4F8D-B9FF-75B2A5657D42<"; return "iPhone 2.1.0b1 05-Jan-10 >E33C3EE9-3038-4F83-8BE9-C6BE0C00E5B1<"; return "iPhone 2.0.2b1 04-Jan-10 >1159F4AC-5B8A-4F56-B5E0-C792ACC9E094<"; return "iPhone 2.0.1b1 02-Jan-10 >DE4B61C0-E36D-4F72-AE95-148A0664CC1A<"; return "iPhone 2.0.0b1 04-Sep-09 >41158CDC-6D20-4C58-82AB-72B754757C01<"; return "iPhone 1.0.9b2 04-Feb-09 >32DDCF17-D959-44ED-8DF8-10EE08D4DBFC<"; return "iPhone 1.0.9b1 01-Feb-09 >9FD8E823-6E8B-4416-A9D6-8770E74F7BB1<"; return "iPhone 1.0.7b2 03-Nov-08 >D60C0BDB-CA0F-45E1-822F-05A93C104712<"; return "iPhone 1.0.7b1 27-Oct-08 >C2B2864E-B83D-4A6E-B8EF-CCD4AC64CFDC<"; return "iPhone 1.0.6b5 22-Oct-08 >BD6F8836-420A-479B-B400-70F73845A140<"; return "iPhone 1.0.6b4 20-Oct-08 >E1936807-92EA-43AC-85A5-5BDA5755A606<"; return "iPhone 1.0.6b3 10-Oct-08 >1EA1C0AA-BD8C-4BDD-94D7-19E021A32A66<"; return "iPhone 1.0.6b2 10-Oct-08 >5BD0B1C3-5D5F-4E39-8EB4-2A6B75D969B0<"; return "iPhone 1.0.6b1 09-Oct-08 >BBBBD9F3-64F7-4C86-8416-021732AAA9CB<"; return "iPhone 1.0.5b4 03-Oct-08 >B35DA17D-2A1E-4DB6-9A3B-FEA51C5E8BEB<"; return "iPhone 1.0.5b3 02-Oct-08 >2C04C0A4-5A5E-494E-BD49-2958E5AFA17D<"; return "iPhone 1.0.5b1 21-Sep-08 >FF17E074-9A2F-4538-9433-BDDB87F97AD5<"; return "iPhone 1.0.4b1 16-Sep-08 >B0574F6D-48DD-48CD-BE9F-0D197DED1A8F<"; return "iPhone 1.0.3b2 13-Sep-08 >EB1B4D70-E96B-4F43-B2BA-B2A470E4A265<"; return "iPhone 1.0.3b1 03-Sep-08 >721B48ED-CD8C-43A1-BE69-09FC9131E573<"; return "iPhone 1.0.1b1 18-May-08 >1B1BAAE0-F4CA-4192-B3E5-4FE51E5BB820<"; return "iPhone 1.0.2b1 02-Sep-08 >08F8D709-6867-4272-B18C-DBA704CB3C62<"; */ case 1007: { /* vm build string also info.plist */ #if STACKVM extern char *__interpBuildInfo; return __interpBuildInfo; #endif break; } case 1008: { /* vm build string also info.plist */ # if COGVM extern char *__cogitBuildInfo; return __cogitBuildInfo; #endif break; } default: break; } return (char *) [super getAttribute: indexNumber]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+clipboard.h ================================================ // // sqSqueakIPhoneApplication+clipboard.h // SqueakPureObjc // // Created by John M McIntosh on 10-01-02. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. // /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication.h" @interface sqSqueakIPhoneApplication (clipboard) - (sqInt) clipboardSize; - (void) clipboardRead: (sqInt) count into: (char *)byteArrayIndex startingAt: (sqInt) startIndex; - (void) clipboardWrite: (sqInt) count from: (char *)byteArrayIndex startingAt: (sqInt) startIndex; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+clipboard.m ================================================ // // sqSqueakIPhoneApplication+clipboard.m // SqueakPureObjc // // Created by John M McIntosh on 10-01-02. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. // #import "sqSqueakIPhoneApplication+clipboard.h" static char * clipboard=NULL; @implementation sqSqueakIPhoneApplication (clipboard) /* Cheat, we always call clipboardSize before clipboardRead, so obviously we can do the read when asking for the size */ - (sqInt) clipboardSize { UIPasteboard *pboard= [UIPasteboard generalPasteboard]; if (clipboard) free(clipboard); clipboard = NULL; NSString *possibleData = pboard.string; if (!possibleData) return 0; const char *contents= [[possibleData precomposedStringWithCanonicalMapping] UTF8String]; if (contents != nil) clipboard= strdup(contents); return clipboard ? (sqInt) strlen(clipboard) : 0; } //Evil assumption is that clipboardSize size <= byteArrayIndex size - (void) clipboardRead: (sqInt) count into: (char *)byteArrayIndex startingAt: (sqInt) startIndex { if (clipboard){ memcpy((char *)byteArrayIndex + startIndex, clipboard, count); //use memcpy versus strlcpy, targets is not null terminated. } } - (void) clipboardWrite: (sqInt) count from: (char *)byteArrayIndex startingAt: (sqInt) startIndex { UIPasteboard *pboard= [UIPasteboard generalPasteboard]; NSString * string = [[NSString alloc] initWithBytes: byteArrayIndex length:(NSUInteger)count encoding: NSUTF8StringEncoding]; pboard.string = string; [string release]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+events.h ================================================ /* * sqSqueakIPhoneApplication+events.h * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/16/08. * Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication.h" #import "RoarVMAbstractEvent.h" #import "RoarVMMouseEvent.h" @interface sqSqueakIPhoneApplication (events) # ifdef ROAR_VM - (void) enqueueRoarVMEvent: (RoarVMAbstractEvent*) evt; - (void) processRoarVMEvent: (RoarVMAbstractEvent*) event placeIn: (sqInputEvent *) evt; # else - (void) recordTouchEvent:(NSSet *) touches type: (UITouchPhase) phase; # endif - (void) buildTouchEventComplexObject:(NSSet *) touches forType: (NSNumber *) aType placeIn: (sqComplexEvent *) evt ; - (void) buildAccelerationEventComplexObject: (UIAcceleration *) acceleration placeIn: (sqComplexEvent *) evt; - (void) buildLocationEventComplexObject: (NSMutableArray *) acceleration placeIn: (sqComplexEvent *) evt; - (void) buildApplicationEventComplexObject: (NSMutableArray *) acceleration placeIn: (sqComplexEvent *) evt; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+events.m ================================================ /* * sqSqueakIPhoneApplication+events.m * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/16/08. * Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sq.h" #import "sqSqueakMainApplication+events.h" #import "sqSqueakIPhoneApplication+events.h" #import "sqDummyaio.h" #import "sqMacHostWindow.h" #import "SqueakNoOGLIPhoneAppDelegate.h" #import "Queue.h" #import "RoarVMAbstractEvent.h" #import "RoarVMSwipeEvent.h" extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; extern struct VirtualMachine* interpreterProxy; sqInt windowActive=1; @implementation sqSqueakIPhoneApplication (events) - (void ) processAsOldEventOrComplexEvent: (id) event placeIn: (sqInputEvent *) evt { if ([event isKindOfClass: [NSData class]]) { [super processAsOldEventOrComplexEvent: event placeIn: evt]; return; } if ([event isKindOfClass: [RoarVMAbstractEvent class]]) { [self processRoarVMEvent: (RoarVMAbstractEvent*)event placeIn: evt]; return; } if ([event isKindOfClass: [NSArray class]]) { if ([[event objectAtIndex: 0] intValue] == 1) { [self buildTouchEventComplexObject: [event objectAtIndex: 2] forType: [event objectAtIndex: 1] placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 2) { // acceleration dataa [self buildAccelerationEventComplexObject: [event objectAtIndex: 1] placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 3) { // location data error [self buildLocationEventComplexObject: event placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 4) { // location data [self buildLocationEventComplexObject: event placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 5) { // memory warning [self buildApplicationEventComplexObject: event placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 6) { // termination warning [self buildApplicationEventComplexObject: event placeIn: (sqComplexEvent *) evt]; return; } if ([[event objectAtIndex: 0] intValue] == 7) { // keyboard [(NSData *)[event objectAtIndex: 1] getBytes: evt length: sizeof(sqInputEvent)]; return; } if ([[event objectAtIndex: 0] intValue] == 8) { // window [(NSData *)[event objectAtIndex: 1] getBytes: evt length: sizeof(sqWindowEvent)]; return; } } } # ifdef ROAR_VM - (void) processRoarVMEvent: (RoarVMAbstractEvent*) event placeIn: (sqInputEvent *) evt { [event processInto: evt]; } - (void) enqueueRoarVMEvent:(RoarVMAbstractEvent *) evt { [eventQueue addItem: evt]; [evt release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } # else - (void) recordTouchEvent:(NSSet *) touches type: (UITouchPhase) phase { NSMutableArray* data = [NSMutableArray new]; [data addObject: [NSNumber numberWithInteger: 1]]; [data addObject: [NSNumber numberWithInteger: (signed) phase]]; [data addObject: touches]; [eventQueue addItem: data]; [data release]; interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex); } # endif // ROAR_VM // unused now - (void) buildTouchEventComplexObject:(NSSet *) touches forType: (NSNumber *) aType placeIn: (sqComplexEvent *) evt { sqInt count = [touches count],arrayIndex=0,squeakMSTimeNow = ioMSecs(),action; UITouch *touch; sqInt previousLocationInViewY,previousLocationInViewX,locationInViewX,locationInViewY,squeakMSTime, view, window, tapCount, phase,timeStamp,storageArea,containerArray,touchId; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), count)); for (touch in touches) { interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 11)); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(squeakMSTimeNow)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf([touch timestamp])); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf((signed)[touch phase])); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf((signed)[touch tapCount])); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor((sqLong)[touch window])); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor((sqLong)[touch view])); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf([touch locationInView:[gDelegateApp mainView]].x)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf([touch locationInView:[gDelegateApp mainView]].y)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf([touch previousLocationInView:[gDelegateApp mainView]].x)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf([touch previousLocationInView:[gDelegateApp mainView]].y)); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor((sqLong)touch)); touchId = interpreterProxy->popRemappableOop(); previousLocationInViewY = interpreterProxy->popRemappableOop(); previousLocationInViewX = interpreterProxy->popRemappableOop(); locationInViewY = interpreterProxy->popRemappableOop(); locationInViewX = interpreterProxy->popRemappableOop(); view = interpreterProxy->popRemappableOop(); window = interpreterProxy->popRemappableOop(); tapCount = interpreterProxy->popRemappableOop(); phase = interpreterProxy->popRemappableOop(); timeStamp = interpreterProxy->popRemappableOop(); squeakMSTime = interpreterProxy->popRemappableOop(); storageArea = interpreterProxy->popRemappableOop(); containerArray = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, storageArea, squeakMSTime); interpreterProxy->storePointerofObjectwithValue(1, storageArea, timeStamp); interpreterProxy->storePointerofObjectwithValue(2, storageArea, phase); interpreterProxy->storePointerofObjectwithValue(3, storageArea, tapCount); interpreterProxy->storePointerofObjectwithValue(4, storageArea, window); interpreterProxy->storePointerofObjectwithValue(5, storageArea, view); interpreterProxy->storePointerofObjectwithValue(6, storageArea, locationInViewX); interpreterProxy->storePointerofObjectwithValue(7, storageArea, locationInViewY); interpreterProxy->storePointerofObjectwithValue(8, storageArea, previousLocationInViewX); interpreterProxy->storePointerofObjectwithValue(9, storageArea, previousLocationInViewY); interpreterProxy->storePointerofObjectwithValue(10, storageArea, touchId); interpreterProxy->storePointerofObjectwithValue(arrayIndex++, containerArray, storageArea); interpreterProxy->pushRemappableOop(containerArray); } evt->type = EventTypeComplex; //This is read as an integer and converted to an oop by interp.c evt->timeStamp = interpreterProxy->integerObjectOf(squeakMSTimeNow); switch ([aType integerValue]) { case UITouchPhaseBegan: action = ComplexEventTypeTouchsDown; break; case UITouchPhaseEnded: action = ComplexEventTypeTouchsUp; break; case UITouchPhaseMoved: action = ComplexEventTypeTouchsMoved; break; case UITouchPhaseStationary: action = ComplexEventTypeTouchsStationary; break; case UITouchPhaseCancelled: action = ComplexEventTypeTouchsCancelled; break; default: action = 0; break; } evt->action = interpreterProxy->integerObjectOf(action); containerArray = interpreterProxy->popRemappableOop(); evt->objectPointer = containerArray; evt->unused1 =interpreterProxy->integerObjectOf(0); evt->unused2 = interpreterProxy->integerObjectOf(0); evt->unused3 =interpreterProxy->integerObjectOf(0); evt->windowIndex = interpreterProxy->integerObjectOf(windowActive); } - (void) buildAccelerationEventComplexObject: (UIAcceleration *) acceleration placeIn: (sqComplexEvent *) evt { sqInt squeakMSTimeNow = ioMSecs(); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor(((usqInt) acceleration))); evt->type = EventTypeComplex; //This is read as an integer and converted to an oop by interp.c evt->timeStamp = interpreterProxy->integerObjectOf(squeakMSTimeNow); evt->action = interpreterProxy->integerObjectOf(ComplexEventTypeAccelerationData); evt->objectPointer = interpreterProxy->popRemappableOop(); evt->unused1 =interpreterProxy->integerObjectOf(0); evt->unused2 = interpreterProxy->integerObjectOf(0); evt->unused3 =interpreterProxy->integerObjectOf(0); evt->windowIndex = interpreterProxy->integerObjectOf(windowActive); } - (void) buildLocationEventComplexObject: (NSMutableArray *) event placeIn: (sqComplexEvent *) evt { sqInt squeakMSTimeNow = ioMSecs(); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor(((usqInt) event))); evt->type = EventTypeComplex; //This is read as an integer and converted to an oop by interp.c evt->timeStamp = interpreterProxy->integerObjectOf(squeakMSTimeNow); evt->action = interpreterProxy->integerObjectOf(ComplexEventTypeLocationData); evt->objectPointer = interpreterProxy->popRemappableOop(); evt->unused1 =interpreterProxy->integerObjectOf(0); evt->unused2 = interpreterProxy->integerObjectOf(0); evt->unused3 =interpreterProxy->integerObjectOf(0); evt->windowIndex = interpreterProxy->integerObjectOf(windowActive); } - (void) buildApplicationEventComplexObject: (NSMutableArray *) event placeIn: (sqComplexEvent *) evt { sqInt squeakMSTimeNow = ioMSecs(); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor(((usqInt) event))); evt->type = EventTypeComplex; //This is read as an integer and converted to an oop by interp.c evt->timeStamp = interpreterProxy->integerObjectOf(squeakMSTimeNow); evt->action = interpreterProxy->integerObjectOf(ComplexEventTypeApplicationData); evt->objectPointer = interpreterProxy->popRemappableOop(); evt->unused1 =interpreterProxy->integerObjectOf(0); evt->unused2 = interpreterProxy->integerObjectOf(0); evt->unused3 =interpreterProxy->integerObjectOf(0); evt->windowIndex = interpreterProxy->integerObjectOf(windowActive); } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+imageReadWrite.h ================================================ // // sqSqueakIPhoneApplication+imageReadWrite.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication.h" @interface sqSqueakIPhoneApplication (imageReadWrite) @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+imageReadWrite.m ================================================ // // sqSqueakIPhoneApplication+imageReadWrite.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/22/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication+imageReadWrite.h" #import "sqMacV2Memory.h" #import "sqSqueakIPhoneInfoPlistInterface.h" #define QUOTEME_(x) #x #define QUOTEME(x) QUOTEME_(x) #ifndef ISQUEAK_IMAGE #error ISQUEAK_IMAGE is undefined (add ISQUEAK_IMAGE="iPhone" to your preprocessor macros) #else #define QUOTEDIMAGE QUOTEME(ISQUEAK_IMAGE) #endif #ifndef ISQUEAK_SOURCES #error ISQUEAK_SOURCES is undefined (add ISQUEAK_SOURCES="PharoV10" to your preprocessor macros) #else #define QUOTEDSOURCES QUOTEME(ISQUEAK_SOURCES) #endif @implementation sqSqueakIPhoneApplication (imageReadWrite) - (void) findImageViaBundleOrPreferences { NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSFileManager *dfm = [NSFileManager defaultManager]; NSString* documentsPath = [dfm currentDirectoryPath]; //This should point to the Documents folder via a previous setup NSString* documentsImagePath = [documentsPath stringByAppendingPathComponent: [@QUOTEDIMAGE stringByAppendingString: @".image"]]; NSString* documentsSourcesPath = [documentsPath stringByAppendingPathComponent: [@QUOTEDSOURCES stringByAppendingString: @".sources"]]; BOOL fileExists = [dfm fileExistsAtPath: documentsImagePath], sourcesFileIsReadable,sourcesFileExists,copyOk,removeOK; NSError* error; /* At this point we copy over the image/changes/sources if they do not exist in Documents however it appears the simulator logic caches things in the "iPhone Simulator" folder between builds and is not cleaned by clean all, also you must delete the app on the iPhone when doing development. Not sure how this will work for production. Do not know where Apple syncs the iphone data to via iTunes yet */ const char *imageNameCharactersInDocumentPath = [dfm fileSystemRepresentationWithPath: documentsImagePath]; imageNamePutLength((sqInt) imageNameCharactersInDocumentPath, strlen(imageNameCharactersInDocumentPath)); NSString * likelySourceFilePath = [dfm destinationOfSymbolicLinkAtPath: documentsSourcesPath error: &error]; if (likelySourceFilePath) { sourcesFileExists = true; sourcesFileIsReadable = [dfm isReadableFileAtPath: documentsSourcesPath]; } else { sourcesFileExists = false; sourcesFileIsReadable = false; } if (sourcesFileExists && !sourcesFileIsReadable) { sourcesFileExists = 0; removeOK = [dfm removeItemAtPath: documentsSourcesPath error: &error]; } if (!sourcesFileExists) { NSString* bundleSourcesPath = [[NSBundle mainBundle] pathForResource:@QUOTEDSOURCES ofType:@"sources"]; if (bundleSourcesPath) copyOk = [dfm createSymbolicLinkAtPath: documentsSourcesPath withDestinationPath: bundleSourcesPath error: &error]; } if (fileExists) { [pool drain]; return; } else { NSString* bundleImagePath = [[NSBundle mainBundle] pathForResource:@QUOTEDIMAGE ofType:@"image"]; BOOL writeable = [(sqSqueakIPhoneInfoPlistInterface*)[self infoPlistInterfaceLogic] imageIsWriteable]; if (writeable) { NSString* documentsChangesPath = [documentsPath stringByAppendingPathComponent: [@QUOTEDIMAGE stringByAppendingString: @".changes"]]; NSString* bundleChangesPath = [[NSBundle mainBundle] pathForResource:@QUOTEDIMAGE ofType:@"changes"]; copyOk = [dfm copyItemAtPath: bundleImagePath toPath: documentsImagePath error: &error]; if (!copyOk) { [pool drain]; return; } copyOk = [dfm copyItemAtPath: bundleChangesPath toPath: documentsChangesPath error: &error]; } else { const char *imageNameCharacters = [dfm fileSystemRepresentationWithPath: bundleImagePath]; imageNamePutLength((sqInt) imageNameCharacters, strlen(imageNameCharacters)); } } [pool drain]; } @end #undef QUOTEDIMAGE #undef QUOTEDSOURCES #undef QUOTEME #undef QUOTEME_ ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication+sound.h ================================================ // // sqSqueakIPhoneApplication+sound.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/31/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #import "sqSqueakIPhoneApplication.h" @interface sqSqueakIPhoneApplication (sound) - (void) ioBeep; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication.h ================================================ // // sqSqueakIPhoneApplication.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakMainApplication.h" #import "sqSqueakIPhoneFileDirectoryInterface.h" @interface sqSqueakIPhoneApplication : sqSqueakMainApplication { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneApplication.m ================================================ // // sqSqueakIPhoneApplication.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/19/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneApplication.h" #import "sqSqueakAppDelegate.h" #import "sqSqueakIPhoneInfoPlistInterface.h" usqInt gMaxHeapSize=32*1024*1024; extern sqSqueakAppDelegate *gDelegateApp; @implementation sqSqueakIPhoneApplication - (sqSqueakFileDirectoryInterface *) newFileDirectoryInterfaceInstance { return [sqSqueakIPhoneFileDirectoryInterface new]; } - (sqSqueakInfoPlistInterface *) newSqSqueakInfoPlistInterfaceCreation { return [sqSqueakIPhoneInfoPlistInterface new]; } - (void) doMemorySetup { gMaxHeapSize = [(sqSqueakIPhoneInfoPlistInterface*) self.infoPlistInterfaceLogic memorySize]; if (gMaxHeapSize == 0) // NO IDEA is this a 4.1 bug? gMaxHeapSize = 32*1024*1024; } - (void) fetchPreferences { [super fetchPreferences]; extern char gSqueakUntrustedDirectoryName[]; extern char gSqueakTrustedDirectoryName[]; strlcpy(gSqueakUntrustedDirectoryName, "/foobar/tooBar/forSqueak/bogus/",PATH_MAX); strlcpy(gSqueakTrustedDirectoryName, "/foobar/tooBar/forSqueak/bogus/",PATH_MAX); } @end /* Profiling. */ void ioProfileStatus(sqInt *running, void **exestartpc, void **exelimitpc, void **vmhst, long *nvmhbin, void **eahst, long *neahbin) {}; void ioControlProfile(int on, void **vhp, long *nvb, void **ehp, long *neb) {}; long ioControlNewProfile(int on, unsigned long buffer_size) {return 0;}; void ioNewProfileStatus(sqInt *running, long *buffersize) {}; long ioNewProfileSamplesInto(void *sampleBuffer) {return 0;}; void ioClearProfile(void) {}; ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneClipboardAPI.h ================================================ // // sqSqueakIPhoneClipboardAPI.h // SqueakPureObjc // // Created by John M McIntosh on 01-02-10. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2009 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneClipboardAPI.m ================================================ // // sqSqueakIPhoneClipboardAPI.m // SqueakPureObjc // // Created by John M McIntosh on 01-02-10. // Copyright 2010 Corporate Smalltalk Consulting Ltd. All rights reserved. // #import "sqSqueakIPhoneClipboardAPI.h" #import "SqueakNoOGLIPhoneAppDelegate.h" #import "sqSqueakIPhoneApplication+clipboard.h" extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; /* Clipboard (cut/copy/paste). */ sqInt clipboardSize(void) { NSAutoreleasePool * pool = [NSAutoreleasePool new]; sqInt value = [(sqSqueakIPhoneApplication*)(SqueakNoOGLIPhoneAppDelegate *)gDelegateApp.squeakApplication clipboardSize]; [pool drain]; return value; } sqInt clipboardReadIntoAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex){ NSAutoreleasePool * pool = [NSAutoreleasePool new]; [(sqSqueakIPhoneApplication*)(SqueakNoOGLIPhoneAppDelegate *)gDelegateApp.squeakApplication clipboardRead: count into: (char *) pointerForIndex_xxx_dmu((usqInt)byteArrayIndex) startingAt: startIndex]; [pool drain]; return 0; } sqInt clipboardWriteFromAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex){ NSAutoreleasePool * pool = [NSAutoreleasePool new]; [(sqSqueakIPhoneApplication*)(SqueakNoOGLIPhoneAppDelegate *)gDelegateApp.squeakApplication clipboardWrite: count from: (char *)pointerForIndex_xxx_dmu((usqInt)byteArrayIndex) startingAt: startIndex]; [pool drain]; return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneFileDirectoryInterface.h ================================================ // // sqSqueakIPhoneFileDirectoryInterface.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/21/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakFileDirectoryInterface.h" @interface sqSqueakIPhoneFileDirectoryInterface : sqSqueakFileDirectoryInterface { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneFileDirectoryInterface.m ================================================ // // sqSqueakIPhoneFileDirectoryInterface.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/21/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import "sqSqueakIPhoneFileDirectoryInterface.h" /* IPhone can only write to certain locations so we want to write to the documents directory */ @implementation sqSqueakIPhoneFileDirectoryInterface - (BOOL) setWorkingDirectory { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; BOOL results = [[NSFileManager defaultManager] changeCurrentDirectoryPath: documentsDirectory]; return results; } - (NSString *) resolvedAliasFiles: (NSString *) filePath { NSFileManager * fileMgr = [NSFileManager defaultManager]; NSDictionary * fileAttributes = [fileMgr fileAttributesAtPath: filePath traverseLink: NO]; if (fileAttributes) { if ([[fileAttributes objectForKey: NSFileTypeSymbolicLink] boolValue]) { NSString* targetFilePath = [fileMgr destinationOfSymbolicLinkAtPath: filePath error: NULL]; if (targetFilePath) { filePath = targetFilePath; } } } return filePath; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneInfoPlistInterface.h ================================================ // // sqSqueakIPhoneInfoPlistInterface.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 9/1/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. Sept-02-08 1.03b1 setup useScrollingView */ // #import "sqSqueakInfoPlistInterface.h" @interface sqSqueakIPhoneInfoPlistInterface : sqSqueakInfoPlistInterface - (BOOL) imageIsWriteable; - (BOOL) useScrollingView; - (NSInteger) memorySize; @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakIPhoneInfoPlistInterface.m ================================================ // // sqSqueakIPhoneInfoPlistInterface // SqueakNoOGLIPhone // // Created by John M McIntosh on 9/1/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. Sept-02-08 1.03b1 setup useScrollingView */ // #import "sqSqueakIPhoneInfoPlistInterface.h" NSString * kwriteable_preferenceKey = @"writeable_preference"; NSString * kscrollableView_preferenceKey = @"scrollableView_preference"; NSString * kmemorySize_preferenceKey = @"memorySize_preference"; extern int gSqueakUseFileMappedMMAP; @implementation sqSqueakIPhoneInfoPlistInterface - (void) parseInfoPlist { NSAutoreleasePool * pool = [NSAutoreleasePool new]; [super parseInfoPlist]; self.SqueakUseFileMappedMMAP = YES; gSqueakUseFileMappedMMAP = 1; NSString *testValue = [defaults stringForKey: kwriteable_preferenceKey]; if (testValue == nil) { // no default values have been set, create them here based on what's in our Settings bundle info // NSString *pathStr = [[NSBundle mainBundle] bundlePath]; NSString *settingsBundlePath = [pathStr stringByAppendingPathComponent:@"Settings.bundle"]; NSString *finalPath = [settingsBundlePath stringByAppendingPathComponent:@"Root.plist"]; NSDictionary *settingsDict = [NSDictionary dictionaryWithContentsOfFile:finalPath]; NSArray *prefSpecifierArray = [settingsDict objectForKey:@"PreferenceSpecifiers"]; NSDictionary *prefItem; NSString *writeable_preferenceDefault = @"YES"; NSString *scrollableView_preferenceDefault= @"NO"; NSString *memorySize_preferenceDefault=@"33554432"; for (prefItem in prefSpecifierArray) { NSString *keyValueStr = [prefItem objectForKey:@"Key"]; id defaultValue = [prefItem objectForKey:@"DefaultValue"]; if ([keyValueStr isEqualToString: kwriteable_preferenceKey]) { writeable_preferenceDefault = defaultValue; } if ([keyValueStr isEqualToString: kscrollableView_preferenceKey]) { scrollableView_preferenceDefault = defaultValue; } if ([keyValueStr isEqualToString: kmemorySize_preferenceKey]) { memorySize_preferenceDefault = defaultValue; } } // since no default values have been set (i.e. no preferences file created), create it here NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys: writeable_preferenceDefault, kwriteable_preferenceKey, scrollableView_preferenceDefault, kscrollableView_preferenceKey, memorySize_preferenceDefault, kmemorySize_preferenceKey, nil]; [[NSUserDefaults standardUserDefaults] registerDefaults: appDefaults]; [[NSUserDefaults standardUserDefaults] synchronize]; } [pool drain]; } - (BOOL) imageIsWriteable { return [defaults boolForKey: kwriteable_preferenceKey]; } - (BOOL) useScrollingView { return [defaults boolForKey: kscrollableView_preferenceKey]; } - (NSInteger) memorySize { return [defaults integerForKey: kmemorySize_preferenceKey]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqSqueakiPhoneApplication+sound.m ================================================ // // sqSqueakIPhoneApplication+sound.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/31/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ /* Note iphone mic is 8 Khz mono, question is where the audio comes froms and goes to technically has two speakers, telephone receiver, speaker, plus headphones, plus bluetooth plus to a doc and audio out, or USB out! note the ringer controlls and volme controls Lots of this is user interaction, don't want the user to manage things if they fiddle with hardware plug in/out adjust switchs ipod can play in background, where is audio routed Oh and ipod touch and iphone are different, iphone has many audio paths/routings interrupt listener, begin/end when alarm, begin on phone start, but app then gets terminated so you don't get end look for audio session current hardware settings to see what the hardware has, ie 44khz input or 8kHz input? look for audio route changing, you get audio route change notification */ #import "sqSqueakIPhoneApplication+sound.h" #import <AudioToolbox/AudioToolbox.h> #import <UIKit/UIKit.h> @implementation sqSqueakIPhoneApplication (sound) - (void) ioBeep { #if TARGET_OS_IPHONE AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); #else AudioServicesPlaySystemSound(kSystemSoundID_UserPreferredAlert); #endif /*Note:System-suppliedalertsoundsandsystem-supplieduser-interfacesoundeffectsarenotavailable iniPhoneOS.Forexample,usingthekSystemSoundID_UserPreferredAlertconstantasaparameter totheAudioServicesPlayAlertSoundfunctionwillnotplayanything. */ #warning this does nothing on the iPod Touch } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqiPhoneScreenAndWindow.h ================================================ // // sqiPhoneScreenAndWindow.h // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/14/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <Foundation/Foundation.h> #import "sqSqueakScreenAndWindow.h" @interface sqiPhoneScreenAndWindow : sqSqueakScreenAndWindow { } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Classes/sqiPhoneScreenAndWindow.m ================================================ // // sqiPhoneScreenAndWindow.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 6/14/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2002-2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #import <QuartzCore/QuartzCore.h> #import "sqiPhoneScreenAndWindow.h" #import "sqSqueakMainApplication+screen.h" #import "SqueakNoOGLIPhoneAppDelegate.h" #import "sq.h" extern struct VirtualMachine* interpreterProxy; extern SqueakNoOGLIPhoneAppDelegate *gDelegateApp; @implementation sqiPhoneScreenAndWindow - (id)init { self = [super init]; if (self) { self.windowIndex = 1; } return self; } - (SqueakUIView *) getMainView { return gDelegateApp.mainView; } - (void)dealloc { [super dealloc]; } @end ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/Info-iPhone.plist ================================================ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleDisplayName</key> <string>${PRODUCT_NAME}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIconFile</key> <string>Squeak.png</string> <key>CFBundleIdentifier</key> <string>com.smalltalkconsulting.squeakbase</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>${PRODUCT_NAME}</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>2.0.0</string> <key>CFBundleSignature</key> <string>FAST</string> <key>CFBundleVersion</key> <string>2.0.0</string> <key>LSRequiresIPhoneOS</key> <true/> <key>NSMainNibFile</key> <string>MainWindow</string> <key>UIInterfaceOrientation</key> <string>UIInterfaceOrientationPortrait</string> <key>UIPrerenderedIcon</key> <true/> </dict> </plist> ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/SqueakV3-minimum-MVC.sources ================================================ 'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 8 October 2008 at 1:15:45 pm'! Object subclass: #AbstractEvent instanceVariableNames: 'item itemKind environment' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:10'! changeKind ^self class changeKind! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:43'! environmentAt: anItemKind (self itemKind = anItemKind) ifTrue: [^self item]. ^environment at: anItemKind ifAbsent: [nil]! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:20'! eventSelector ^self class eventSelectorBlock value: itemKind value: self changeKind! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:36'! item: anItem kind: anItemKind item := anItem. itemKind := anItemKind. environment := Dictionary new! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:37'! itemCategory: aCategory environment at: self class categoryKind put: aCategory! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:36'! itemClass: aClass environment at: self class classKind put: aClass! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'rw 7/10/2003 12:38'! itemProtocol: aProtocol environment at: self class protocolKind put: aProtocol! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'NS 1/27/2004 10:38'! itemRequestor: requestor environment at: #requestor put: requestor! ! !AbstractEvent methodsFor: 'private-accessing' stamp: 'NS 1/27/2004 10:39'! itemSelector: aSymbol environment at: #selector put: aSymbol! ! !AbstractEvent methodsFor: 'accessing' stamp: 'rw 6/30/2003 08:22'! item "Return the item that triggered the event (typically the name of a class, a category, a protocol, a method)." ^item! ! !AbstractEvent methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:43'! itemClass ^self environmentAt: self class classKind! ! !AbstractEvent methodsFor: 'accessing' stamp: 'rw 6/30/2003 08:22'! itemKind "Return the kind of the item of the event (#category, #class, #protocol, #method, ...)" ^itemKind! ! !AbstractEvent methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:44'! itemProtocol ^self environmentAt: self class protocolKind! ! !AbstractEvent methodsFor: 'accessing' stamp: 'NS 1/27/2004 10:38'! itemRequestor ^self environmentAt: #requestor! ! !AbstractEvent methodsFor: 'accessing' stamp: 'NS 1/27/2004 10:38'! itemSelector ^self environmentAt: #selector! ! !AbstractEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 17:52'! printOn: aStream self printEventKindOn: aStream. aStream nextPutAll: ' Event for item: '; print: self item; nextPutAll: ' of kind: '; print: self itemKind! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 6/30/2003 08:34'! isAdded ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 7/10/2003 15:01'! isCommented ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 7/14/2003 10:15'! isDoIt ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'NS 1/19/2004 15:09'! isModified ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 7/1/2003 19:53'! isRecategorized ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 6/30/2003 08:34'! isRemoved ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'rw 7/1/2003 11:35'! isRenamed ^false! ! !AbstractEvent methodsFor: 'testing' stamp: 'NS 1/27/2004 12:44'! isReorganized ^ false! ! !AbstractEvent methodsFor: 'triggering' stamp: 'rw 7/14/2003 17:06'! trigger: anEventManager "Trigger the event manager." anEventManager triggerEvent: self eventSelector with: self.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! AbstractEvent class instanceVariableNames: ''! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/19/2004 18:42'! class: aClass ^ self item: aClass kind: AbstractEvent classKind.! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/19/2004 18:42'! class: aClass category: cat | instance | instance := self class: aClass. instance itemCategory: cat. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'rw 7/9/2003 11:19'! item: anItem kind: anItemKind ^self basicNew item: anItem kind: anItemKind! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/16/2004 14:19'! method: aMethod class: aClass | instance | instance := self item: aMethod kind: self methodKind. instance itemClass: aClass. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/16/2004 14:20'! method: aMethod protocol: prot class: aClass | instance | instance := self method: aMethod class: aClass. instance itemProtocol: prot. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 10:48'! method: aMethod selector: aSymbol class: aClass | instance | instance := self item: aMethod kind: self methodKind. instance itemSelector: aSymbol. instance itemClass: aClass. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 10:49'! method: aMethod selector: aSymbol class: aClass requestor: requestor | instance | instance := self method: aMethod selector: aSymbol class: aClass. instance itemRequestor: requestor. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 10:49'! method: aMethod selector: aSymbol protocol: prot class: aClass | instance | instance := self method: aMethod selector: aSymbol class: aClass. instance itemProtocol: prot. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 10:50'! method: aMethod selector: aSymbol protocol: prot class: aClass requestor: requestor | instance | instance := self method: aMethod selector: aSymbol protocol: prot class: aClass. instance itemRequestor: requestor. ^instance! ! !AbstractEvent class methodsFor: 'instance creation' stamp: 'rw 6/30/2003 09:20'! new "Override new to trigger an error, since we want to use specialized methods to create basic and higher-level events." ^self error: 'Instances can only be created using specialized instance creation methods.'! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/29/2003 15:14'! allItemKinds "SystemEvent allItemKinds" ^(AbstractEvent class organization listAtCategoryNamed: #'item kinds') collect: [:sel | self perform: sel]! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:08'! changeKind "Return a symbol, with a : as last character, identifying the change kind." self subclassResponsibility! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:18'! eventSelectorBlock ^[:itemKind :changeKind | itemKind, changeKind, 'Event:']! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:19'! itemChangeCombinations ^self supportedKinds collect: [:itemKind | self eventSelectorBlock value: itemKind value: self changeKind]! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:04'! supportedKinds "All the kinds of items that this event can take. By default this is all the kinds in the system. But subclasses can override this to limit the choices. For example, the SuperChangedEvent only works with classes, and not with methods, instance variables, ..." ^self allItemKinds! ! !AbstractEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 11:39'! systemEvents "Return all the possible events in the system. Make a cross product of the items and the change types." "self systemEvents" ^self allSubclasses inject: OrderedCollection new into: [:allEvents :eventClass | allEvents addAll: eventClass itemChangeCombinations; yourself]! ! !AbstractEvent class methodsFor: 'item kinds' stamp: 'rw 7/9/2003 11:12'! categoryKind ^#category! ! !AbstractEvent class methodsFor: 'item kinds' stamp: 'rw 7/9/2003 11:12'! classKind ^#class! ! !AbstractEvent class methodsFor: 'item kinds' stamp: 'rw 7/14/2003 11:41'! expressionKind ^#expression! ! !AbstractEvent class methodsFor: 'item kinds' stamp: 'rw 7/9/2003 11:12'! methodKind ^#method! ! !AbstractEvent class methodsFor: 'item kinds' stamp: 'rw 7/10/2003 12:36'! protocolKind ^#protocol! ! Object subclass: #AbstractFont instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !AbstractFont commentStamp: '<historical>' prior: 0! AbstractFont defines the generic interface that all fonts need to implement.! !AbstractFont methodsFor: 'accessing' stamp: 'nk 4/2/2004 11:06'! baseKern ^0! ! !AbstractFont methodsFor: 'accessing' stamp: 'ar 5/19/2000 14:56'! characterToGlyphMap "Return the character to glyph mapping table. If the table is not provided the character scanner will query the font directly for the width of each individual character." ^nil! ! !AbstractFont methodsFor: 'accessing' stamp: 'nk 4/1/2004 10:51'! height "Answer the height of the receiver, total of maximum extents of characters above and below the baseline." ^self ascent + self descent! ! !AbstractFont methodsFor: 'accessing' stamp: 'nk 4/2/2004 11:07'! lineGrid "Answer the relative space between lines" ^ self ascent + self descent! ! !AbstractFont methodsFor: 'accessing' stamp: 'nk 4/2/2004 11:33'! pixelSize "Make sure that we don't return a Fraction" ^ TextStyle pointsToPixels: self pointSize! ! !AbstractFont methodsFor: 'accessing' stamp: 'nk 4/1/2004 10:48'! pointSize self subclassResponsibility.! ! !AbstractFont methodsFor: 'accessing' stamp: 'nk 7/11/2004 21:15'! textStyle ^ TextStyle actualTextStyles detect: [:aStyle | aStyle fontArray includes: self] ifNone: [ TextStyle fontArray: { self } ]! ! !AbstractFont methodsFor: 'accessing' stamp: 'ar 5/19/2000 14:57'! xTable "Return the xTable for the font. The xTable defines the left x-value for each individual glyph in the receiver. If such a table is not provided, the character scanner will ask the font directly for the appropriate width of each individual character." ^nil! ! !AbstractFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 14:59'! displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta "Draw the given string from startIndex to stopIndex at aPoint on the (already prepared) display context." ^self subclassResponsibility! ! !AbstractFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 14:59'! installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor "Install the receiver on the given DisplayContext (either BitBlt or Canvas) for further drawing operations." ^self subclassResponsibility! ! !AbstractFont methodsFor: 'measuring' stamp: 'ar 5/19/2000 14:58'! widthOf: aCharacter "Return the width of the given character" ^self subclassResponsibility! ! !AbstractFont methodsFor: 'measuring' stamp: 'ar 12/31/2001 14:25'! widthOfString: aString aString ifNil:[^0]. ^self widthOfString: aString from: 1 to: aString size. " TextStyle default defaultFont widthOfString: 'zort' 21 "! ! !AbstractFont methodsFor: 'measuring' stamp: 'ar 12/31/2001 00:54'! widthOfString: aString from: startIndex to: stopIndex "Measure the length of the given string between start and stop index" | character resultX | resultX _ 0. startIndex to: stopIndex do:[:i | character _ aString at: i. resultX _ resultX + (self widthOf: character)]. ^resultX! ! !AbstractFont methodsFor: 'testing' stamp: 'nk 6/25/2003 12:54'! isTTCFont ^false! ! !AbstractFont methodsFor: 'caching' stamp: 'nk 3/15/2004 18:47'! releaseCachedState ! ! Array variableSubclass: #ActionSequence instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Object Events'! !ActionSequence methodsFor: 'converting' stamp: 'reThink 2/18/2001 15:12'! asActionSequence ^self! ! !ActionSequence methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'! asActionSequenceTrappingErrors ^WeakActionSequenceTrappingErrors withAll: self! ! !ActionSequence methodsFor: 'converting' stamp: 'reThink 2/18/2001 15:28'! asMinimalRepresentation self size = 0 ifTrue: [^nil]. self size = 1 ifTrue: [^self first]. ^self! ! !ActionSequence methodsFor: 'evaluating' stamp: 'reThink 2/18/2001 17:51'! value "Answer the result of evaluating the elements of the receiver." | answer | self do: [:each | answer := each value]. ^answer! ! !ActionSequence methodsFor: 'evaluating' stamp: 'reThink 2/18/2001 17:52'! valueWithArguments: anArray | answer | self do: [:each | answer := each valueWithArguments: anArray]. ^answer! ! !ActionSequence methodsFor: 'printing' stamp: 'SqR 07/28/2001 18:25'! printOn: aStream self size < 2 ifTrue: [^super printOn: aStream]. aStream nextPutAll: '#('. self do: [:each | each printOn: aStream] separatedBy: [aStream cr]. aStream nextPut: $)! ! AbstractEvent subclass: #AddedEvent instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !AddedEvent methodsFor: 'testing' stamp: 'rw 6/30/2003 08:35'! isAdded ^true! ! !AddedEvent methodsFor: 'printing' stamp: 'rw 6/30/2003 09:31'! printEventKindOn: aStream aStream nextPutAll: 'Added'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! AddedEvent class instanceVariableNames: ''! !AddedEvent class methodsFor: 'accessing' stamp: 'rw 7/19/2003 09:52'! changeKind ^#Added! ! !AddedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:22'! supportedKinds "All the kinds of items that this event can take." ^ Array with: self classKind with: self methodKind with: self categoryKind with: self protocolKind! ! Object subclass: #AppRegistry instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Applications'! !AppRegistry commentStamp: 'ads 4/2/2003 15:30' prior: 0! AppRegistry is a simple little class, not much more than a wrapper around a collection. It's intended to help break dependencies between packages. For example, if you'd like to be able to send e-mail, you could use the bare-bones MailComposition class, or you could use the full-blown Celeste e-mail client. Instead of choosing one or the other, you can call "MailSender default" (where MailSender is a subclass of AppRegistry), and thus avoid creating a hard-coded dependency on either of the two mail senders. This will only really be useful, of course, for applications that have a very simple, general, well-defined interface. Most of the time, you're probably better off just marking your package as being dependent on a specific other package, and avoiding the hassle of this whole AppRegistry thing. But for simple things like e-mail senders or web browsers, it might be useful. ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! AppRegistry class instanceVariableNames: 'registeredClasses default'! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 3/29/2003 13:36'! appName "Defaults to the class name, which is probably good enough, but you could override this in subclasses if you want to." ^ self name! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 4/2/2003 15:31'! askForDefault | menu | self registeredClasses isEmpty ifTrue: [self inform: 'There are no ', self appName, ' applications registered.'. ^ default _ nil]. self registeredClasses size = 1 ifTrue: [^ default _ self registeredClasses anyOne]. menu _ CustomMenu new. self registeredClasses do: [:c | menu add: c name printString action: c]. ^ default _ menu startUpWithCaption: 'Which ', self appName, ' would you prefer?'! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 3/29/2003 13:11'! default ^ default ifNil: [self askForDefault]! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'nk 3/9/2004 12:33'! default: aClassOrNil "Sets my default to aClassOrNil. Answers the old default." | oldDefault | oldDefault := default. aClassOrNil ifNotNil: [ self register: aClassOrNil ]. default := aClassOrNil. ^ oldDefault! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 4/2/2003 15:25'! register: aProviderClass (self registeredClasses includes: aProviderClass) ifFalse: [default _ nil. "so it'll ask for a new default, since if you're registering a new app you probably want to use it" self registeredClasses add: aProviderClass].! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 3/29/2003 13:01'! registeredClasses ^ registeredClasses ifNil: [registeredClasses _ OrderedCollection new]! ! !AppRegistry class methodsFor: 'as yet unclassified' stamp: 'ads 3/29/2003 13:03'! unregister: aProviderClass (default = aProviderClass) ifTrue: [default _ nil]. self registeredClasses remove: aProviderClass ifAbsent: [].! ! Path subclass: #Arc instanceVariableNames: 'quadrant radius center' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Arc commentStamp: '<historical>' prior: 0! Arcs are an unusual implementation of splines due to Ted Kaehler. Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner. Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern). By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines. Voila.! !Arc methodsFor: 'accessing'! center "Answer the point at the center of the receiver." ^center! ! !Arc methodsFor: 'accessing'! center: aPoint "Set aPoint to be the receiver's center." center _ aPoint! ! !Arc methodsFor: 'accessing'! quadrant "Answer the part of the circle represented by the receiver." ^quadrant! ! !Arc methodsFor: 'accessing'! quadrant: section "Set the part of the circle represented by the receiver to be the argument, section." quadrant _ section! ! !Arc methodsFor: 'accessing'! radius "Answer the receiver's radius." ^radius! ! !Arc methodsFor: 'accessing'! radius: anInteger "Set the receiver's radius to be the argument, anInteger." radius _ anInteger! ! !Arc methodsFor: 'display box access'! computeBoundingBox | aRectangle aPoint | aRectangle _ center - radius + form offset extent: form extent + (radius * 2) asPoint. aPoint _ center + form extent. quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y]. quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y]. quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y]. quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]! ! !Arc methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm | nSegments line angle sin cos xn yn xn1 yn1 | nSegments _ 12.0. line _ Line new. line form: self form. angle _ 90.0 / nSegments. sin _ (angle * (2 * Float pi / 360.0)) sin. cos _ (angle * (2 * Float pi / 360.0)) cos. quadrant = 1 ifTrue: [xn _ radius asFloat. yn _ 0.0]. quadrant = 2 ifTrue: [xn _ 0.0. yn _ 0.0 - radius asFloat]. quadrant = 3 ifTrue: [xn _ 0.0 - radius asFloat. yn _ 0.0]. quadrant = 4 ifTrue: [xn _ 0.0. yn _ radius asFloat]. nSegments asInteger timesRepeat: [xn1 _ xn * cos + (yn * sin). yn1 _ yn * cos - (xn * sin). line beginPoint: center + (xn asInteger @ yn asInteger). line endPoint: center + (xn1 asInteger @ yn1 asInteger). line displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm. xn _ xn1. yn _ yn1]! ! !Arc methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm | newArc tempCenter | newArc _ Arc new. tempCenter _ aTransformation applyTo: self center. newArc center: tempCenter x asInteger @ tempCenter y asInteger. newArc quadrant: self quadrant. newArc radius: (self radius * aTransformation scale x) asInteger. newArc form: self form. newArc displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRect rule: anInteger fillColor: aForm! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Arc class instanceVariableNames: ''! !Arc class methodsFor: 'examples'! example "Click the button somewhere on the screen. The designated point will be the center of an Arc with radius 50 in the 4th quadrant." | anArc aForm | aForm _ Form extent: 1 @ 30. "make a long thin Form for display" aForm fillBlack. "turn it black" anArc _ Arc new. anArc form: aForm. "set the form for display" anArc radius: 50.0. anArc center: Sensor waitButton. anArc quadrant: 4. anArc displayOn: Display. Sensor waitButton "Arc example"! ! Error subclass: #ArithmeticError instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! ArrayedCollection variableSubclass: #Array instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !Array commentStamp: '<historical>' prior: 0! I present an ArrayedCollection whose elements are objects.! !Array methodsFor: 'comparing'! hashMappedBy: map "Answer what my hash would be if oops changed according to map." self size = 0 ifTrue: [^self hash]. ^(self first hashMappedBy: map) + (self last hashMappedBy: map)! ! !Array methodsFor: 'comparing' stamp: 'ajh 2/2/2002 15:03'! literalEqual: other self class == other class ifFalse: [^ false]. self size = other size ifFalse: [^ false]. self with: other do: [:e1 :e2 | (e1 literalEqual: e2) ifFalse: [^ false]]. ^ true! ! !Array methodsFor: 'converting' stamp: 'sma 5/12/2000 17:32'! asArray "Answer with the receiver itself." ^ self! ! !Array methodsFor: 'converting' stamp: 'ajh 9/8/2002 17:45'! elementsExchangeIdentityWith: otherArray "This primitive performs a bulk mutation, causing all pointers to the elements of this array to be replaced by pointers to the corresponding elements of otherArray. At the same time, all pointers to the elements of otherArray are replaced by pointers to the corresponding elements of this array. The identityHashes remain with the pointers rather than with the objects so that objects in hashed structures should still be properly indexed after the mutation." <primitive: 128> otherArray class == Array ifFalse: [^ self error: 'arg must be array']. self size = otherArray size ifFalse: [^ self error: 'arrays must be same size']. (self anySatisfy: [:obj | obj class == SmallInteger]) ifTrue: [^ self error: 'can''t become SmallIntegers']. (otherArray anySatisfy: [:obj | obj class == SmallInteger]) ifTrue: [^ self error: 'can''t become SmallIntegers']. "Must have failed because not enough space in forwarding table (see ObjectMemory-prepareForwardingTableForBecoming:with:twoWay:). Do GC and try again only once" (Smalltalk bytesLeft: true) = Smalltalk primitiveGarbageCollect ifTrue: [^ self primitiveFailed]. ^ self elementsExchangeIdentityWith: otherArray! ! !Array methodsFor: 'converting' stamp: 'di 3/28/1999 10:23'! elementsForwardIdentityTo: otherArray "This primitive performs a bulk mutation, causing all pointers to the elements of this array to be replaced by pointers to the corresponding elements of otherArray. The identityHashes remain with the pointers rather than with the objects so that the objects in this array should still be properly indexed in any existing hashed structures after the mutation." <primitive: 72> self primitiveFailed! ! !Array methodsFor: 'converting' stamp: 'brp 9/26/2003 08:09'! elementsForwardIdentityTo: otherArray copyHash: copyHash "This primitive performs a bulk mutation, causing all pointers to the elements of this array to be replaced by pointers to the corresponding elements of otherArray. The identityHashes remain with the pointers rather than with the objects so that the objects in this array should still be properly indexed in any existing hashed structures after the mutation." <primitive: 249> self primitiveFailed! ! !Array methodsFor: 'converting'! evalStrings "Allows you to construct literal arrays. #(true false nil '5@6' 'Set new' '''text string''') evalStrings gives an array with true, false, nil, a Point, a Set, and a String instead of just a bunch of Symbols" | it | ^ self collect: [:each | it _ each. each == #true ifTrue: [it _ true]. each == #false ifTrue: [it _ false]. each == #nil ifTrue: [it _ nil]. each class == String ifTrue: [ it _ Compiler evaluate: each]. each class == Array ifTrue: [it _ it evalStrings]. it]! ! !Array methodsFor: 'printing' stamp: 'sma 5/12/2000 14:11'! isLiteral ^ self allSatisfy: [:each | each isLiteral]! ! !Array methodsFor: 'printing' stamp: 'sma 6/1/2000 09:39'! printOn: aStream aStream nextPut: $#. self printElementsOn: aStream! ! !Array methodsFor: 'printing'! storeOn: aStream "Use the literal form if possible." self isLiteral ifTrue: [aStream nextPut: $#; nextPut: $(. self do: [:element | element printOn: aStream. aStream space]. aStream nextPut: $)] ifFalse: [super storeOn: aStream]! ! !Array methodsFor: 'private' stamp: 'sma 6/3/2000 21:39'! hasLiteral: literal "Answer true if literal is identical to any literal in this array, even if imbedded in further array structure. This method is only intended for private use by CompiledMethod hasLiteralSymbol:" | lit | 1 to: self size do: [:index | (lit _ self at: index) == literal ifTrue: [^ true]. (lit class == Array and: [lit hasLiteral: literal]) ifTrue: [^ true]]. ^ false! ! !Array methodsFor: 'private' stamp: 'di 8/15/97 09:55'! hasLiteralSuchThat: litBlock "Answer true if litBlock returns true for any literal in this array, even if imbedded in further array structure. This method is only intended for private use by CompiledMethod hasLiteralSuchThat:" | lit | 1 to: self size do: [:index | lit _ self at: index. (litBlock value: lit) ifTrue: [^ true]. (lit class == Array and: [lit hasLiteralSuchThat: litBlock]) ifTrue: [^ true]]. ^false! ! !Array methodsFor: 'private'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> super replaceFrom: start to: stop with: replacement startingAt: repStart! ! !Array methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:42'! byteEncode:aStream aStream writeArray:self. ! ! !Array methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:55'! storeOnStream:aStream self isLiteral ifTrue: [super storeOnStream:aStream] ifFalse:[aStream writeCollection:self]. ! ! !Array methodsFor: 'copying' stamp: 'ar 2/11/2001 01:55'! copyWithDependent: newElement self size = 0 ifTrue:[^DependentsArray with: newElement]. ^self copyWith: newElement! ! !Array methodsFor: 'accessing' stamp: 'ar 8/26/2001 22:02'! atWrap: index "Optimized to go through the primitive if possible" <primitive: 60> ^ self at: index - 1 \\ self size + 1! ! !Array methodsFor: 'accessing' stamp: 'ar 8/26/2001 22:03'! atWrap: index put: anObject "Optimized to go through the primitive if possible" <primitive: 61> ^ self at: index - 1 \\ self size + 1 put: anObject! ! !Array methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:09'! +* aCollection "Premultiply aCollection by self. aCollection should be an Array or Matrix. The name of this method is APL's +.x squished into Smalltalk syntax." ^aCollection preMultiplyByArray: self ! ! !Array methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:10'! preMultiplyByArray: a "Answer a+*self where a is an Array. Arrays are always understood as column vectors, so an n element Array is an n*1 Array. This multiplication is legal iff self size = 1." self size = 1 ifFalse: [self error: 'dimensions do not conform']. ^a * self first! ! !Array methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:08'! preMultiplyByMatrix: m "Answer m+*self where m is a Matrix." |s| m columnCount = self size ifFalse: [self error: 'dimensions do not conform']. ^(1 to: m rowCount) collect: [:row | s _ 0. 1 to: self size do: [:k | s _ (m at: row at: k) * (self at: k) + s]. s]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Array class instanceVariableNames: ''! !Array class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:12'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asIntPtrFrom: anInteger on: aStream! ! !Array class methodsFor: 'plugin generation' stamp: 'acg 9/19/1999 13:10'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asIntPtrFrom: anInteger andThen: (cg ccgValBlock: 'isIndexable')! ! !Array class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:12'! ccgDeclareCForVar: aSymbolOrString ^'int *', aSymbolOrString! ! !Array class methodsFor: 'brace support' stamp: 'di 11/18/1999 22:53'! braceStream: nElements "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." ^ WriteStream basicNew braceArray: (self new: nElements) ! ! !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:16'! braceWith: a "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." | array | array _ self new: 1. array at: 1 put: a. ^ array! ! !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:15'! braceWith: a with: b "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." | array | array _ self new: 2. array at: 1 put: a. array at: 2 put: b. ^ array! ! !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:17'! braceWith: a with: b with: c "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." | array | array _ self new: 3. array at: 1 put: a. array at: 2 put: b. array at: 3 put: c. ^ array! ! !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:17'! braceWith: a with: b with: c with: d "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." | array | array _ self new: 4. array at: 1 put: a. array at: 2 put: b. array at: 3 put: c. array at: 4 put: d. ^ array! ! !Array class methodsFor: 'brace support' stamp: 'di 11/19/1999 08:16'! braceWithNone "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." ^ self new: 0! ! SequenceableCollection subclass: #ArrayedCollection instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Abstract'! !ArrayedCollection commentStamp: '<historical>' prior: 0! I am an abstract collection of elements with a fixed range of integers (from 1 to n>=0) as external keys.! !ArrayedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:36'! size "Answer how many elements the receiver contains." <primitive: 62> ^ self basicSize! ! !ArrayedCollection methodsFor: 'adding' stamp: 'sma 5/12/2000 14:09'! add: newObject self shouldNotImplement! ! !ArrayedCollection methodsFor: 'filter streaming' stamp: 'sma 5/12/2000 14:20'! flattenOnStream: aStream aStream writeArrayedCollection: self! ! !ArrayedCollection methodsFor: 'printing'! storeOn: aStream aStream nextPutAll: '(('. aStream nextPutAll: self class name. aStream nextPutAll: ' new: '. aStream store: self size. aStream nextPut: $). (self storeElementsFrom: 1 to: self size on: aStream) ifFalse: [aStream nextPutAll: '; yourself']. aStream nextPut: $)! ! !ArrayedCollection methodsFor: 'private'! defaultElement ^nil! ! !ArrayedCollection methodsFor: 'private'! storeElementsFrom: firstIndex to: lastIndex on: aStream | noneYet defaultElement arrayElement | noneYet _ true. defaultElement _ self defaultElement. firstIndex to: lastIndex do: [:index | arrayElement _ self at: index. arrayElement = defaultElement ifFalse: [noneYet ifTrue: [noneYet _ false] ifFalse: [aStream nextPut: $;]. aStream nextPutAll: ' at: '. aStream store: index. aStream nextPutAll: ' put: '. aStream store: arrayElement]]. ^noneYet! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 18:18'! asSortedArray self isSorted ifTrue: [^ self asArray]. ^ super asSortedArray! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 6/1/2000 11:57'! isSorted "Return true if the receiver is sorted by the given criterion. Optimization for isSortedBy: [:a :b | a <= b]." | lastElm elm | self isEmpty ifTrue: [^ true]. lastElm _ self first. 2 to: self size do: [:index | elm _ self at: index. lastElm <= elm ifFalse: [^ false]. lastElm _ elm]. ^ true! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 6/1/2000 11:58'! isSortedBy: aBlock "Return true if the receiver is sorted by the given criterion." | lastElm elm | self isEmpty ifTrue: [^ true]. lastElm _ self first. 2 to: self size do: [:index | elm _ self at: index. (aBlock value: lastElm value: elm) ifFalse: [^ false]. lastElm _ elm]. ^ true! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:28'! mergeFirst: first middle: middle last: last into: dst by: aBlock "Private. Merge the sorted ranges [first..middle] and [middle+1..last] of the receiver into the range [first..last] of dst." | i1 i2 val1 val2 out | i1 _ first. i2 _ middle + 1. val1 _ self at: i1. val2 _ self at: i2. out _ first - 1. "will be pre-incremented" "select 'lower' half of the elements based on comparator" [(i1 <= middle) and: [i2 <= last]] whileTrue: [(aBlock value: val1 value: val2) ifTrue: [dst at: (out _ out + 1) put: val1. val1 _ self at: (i1 _ i1 + 1)] ifFalse: [dst at: (out _ out + 1) put: val2. i2 _ i2 + 1. i2 <= last ifTrue: [val2 _ self at: i2]]]. "copy the remaining elements" i1 <= middle ifTrue: [dst replaceFrom: out + 1 to: last with: self startingAt: i1] ifFalse: [dst replaceFrom: out + 1 to: last with: self startingAt: i2]! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:25'! mergeSortFrom: startIndex to: stopIndex by: aBlock "Sort the given range of indices using the mergesort algorithm. Mergesort is a worst-case O(N log N) sorting algorithm that usually does only half as many comparisons as heapsort or quicksort." "Details: recursively split the range to be sorted into two halves, mergesort each half, then merge the two halves together. An extra copy of the data is used as temporary storage and successive merge phases copy data back and forth between the receiver and this copy. The recursion is set up so that the final merge is performed into the receiver, resulting in the receiver being completely sorted." self size <= 1 ifTrue: [^ self]. "nothing to do" startIndex = stopIndex ifTrue: [^ self]. self assert: [startIndex >= 1 and: [startIndex < stopIndex]]. "bad start index" self assert: [stopIndex <= self size]. "bad stop index" self mergeSortFrom: startIndex to: stopIndex src: self clone dst: self by: aBlock! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:26'! mergeSortFrom: first to: last src: src dst: dst by: aBlock "Private. Split the range to be sorted in half, sort each half, and merge the two half-ranges into dst." | middle | first = last ifTrue: [^ self]. middle _ (first + last) // 2. self mergeSortFrom: first to: middle src: dst dst: src by: aBlock. self mergeSortFrom: middle + 1 to: last src: dst dst: src by: aBlock. src mergeFirst: first middle: middle last: last into: dst by: aBlock! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:22'! sort "Sort this array into ascending order using the '<=' operator." self sort: [:a :b | a <= b]! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:21'! sort: aSortBlock "Sort this array using aSortBlock. The block should take two arguments and return true if the first element should preceed the second one." self mergeSortFrom: 1 to: self size by: aSortBlock! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'nk 3/17/2004 15:22'! byteSize ^self basicSize * self bytesPerBasicElement ! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'nk 3/17/2004 16:28'! bytesPerBasicElement "Answer the number of bytes that each of my basic elements requires. In other words: self basicSize * self bytesPerBasicElement should equal the space required on disk by my variable sized representation." ^self class isBytes ifTrue: [ 1 ] ifFalse: [ 4 ]! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'nk 3/17/2004 18:51'! bytesPerElement ^self class isBytes ifTrue: [ 1 ] ifFalse: [ 4 ]. ! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'sd 6/28/2003 09:49'! restoreEndianness "This word object was just read in from a stream. It was stored in Big Endian (Mac) format. Reverse the byte order if the current machine is Little Endian. We only intend this for non-pointer arrays. Do nothing if I contain pointers." self class isPointers | self class isWords not ifTrue: [^ self]. Smalltalk isLittleEndian ifTrue: [Bitmap swapBytesIn: self from: 1 to: self basicSize] ! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'md 12/12/2003 17:01'! swapBytesFrom: start to: stop "Perform a bigEndian/littleEndian byte reversal of my words. We only intend this for non-pointer arrays. Do nothing if I contain pointers." | hack blt | self deprecated: 'Use BitMap class>>swapBytesIn:from:to:'. self class isPointers | self class isWords not ifTrue: [^ self]. "The implementation is a hack, but fast for large ranges" hack _ Form new hackBits: self. blt _ (BitBlt toForm: hack) sourceForm: hack. blt combinationRule: Form reverse. "XOR" blt sourceY: start-1; destY: start-1; height: stop-start+1; width: 1. blt sourceX: 0; destX: 3; copyBits. "Exchange bytes 0 and 3" blt sourceX: 3; destX: 0; copyBits. blt sourceX: 0; destX: 3; copyBits. blt sourceX: 1; destX: 2; copyBits. "Exchange bytes 1 and 2" blt sourceX: 2; destX: 1; copyBits. blt sourceX: 1; destX: 2; copyBits. ! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'tk 3/7/2001 17:36'! swapHalves "A normal switch in endianness (byte order in words) reverses the order of 4 bytes. That is not correct for SoundBuffers, which use 2-bytes units. If a normal switch has be done, this method corrects it further by swapping the two halves of the long word. This method is only used for 16-bit quanities in SoundBuffer, ShortIntegerArray, etc." | hack blt | "The implementation is a hack, but fast for large ranges" hack _ Form new hackBits: self. blt _ (BitBlt toForm: hack) sourceForm: hack. blt combinationRule: Form reverse. "XOR" blt sourceY: 0; destY: 0; height: self size; width: 2. blt sourceX: 0; destX: 2; copyBits. "Exchange bytes 0&1 with 2&3" blt sourceX: 2; destX: 0; copyBits. blt sourceX: 0; destX: 2; copyBits.! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'ar 5/17/2001 19:50'! writeOn: aStream "Store the array of bits onto the argument, aStream. (leading byte ~= 16r80) identifies this as raw bits (uncompressed). Always store in Big Endian (Mac) byte order. Do the writing at BitBlt speeds. We only intend this for non-pointer arrays. Do nothing if I contain pointers." self class isPointers | self class isWords not ifTrue: [^ super writeOn: aStream]. "super may cause an error, but will not be called." aStream nextInt32Put: self basicSize. aStream nextWordsPutAll: self.! ! !ArrayedCollection methodsFor: 'objects from disk' stamp: 'tk 3/7/2001 18:07'! writeOnGZIPByteStream: aStream "We only intend this for non-pointer arrays. Do nothing if I contain pointers." self class isPointers | self class isWords not ifTrue: [^ super writeOnGZIPByteStream: aStream]. "super may cause an error, but will not be called." aStream nextPutAllWordArray: self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ArrayedCollection class instanceVariableNames: ''! !ArrayedCollection class methodsFor: 'instance creation'! new "Answer a new instance of me, with size = 0." ^self new: 0! ! !ArrayedCollection class methodsFor: 'instance creation'! new: size withAll: value "Answer an instance of me, with number of elements equal to size, each of which refers to the argument, value." ^(self new: size) atAllPut: value! ! !ArrayedCollection class methodsFor: 'instance creation'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." | newArray | newArray _ self new: aCollection size. 1 to: aCollection size do: [:i | newArray at: i put: (aCollection at: i)]. ^ newArray " Array newFrom: {1. 2. 3} {1. 2. 3} as: Array {1. 2. 3} as: ByteArray {$c. $h. $r} as: String {$c. $h. $r} as: Text "! ! !ArrayedCollection class methodsFor: 'instance creation' stamp: 'ar 5/17/2001 19:50'! newFromStream: s "Only meant for my subclasses that are raw bits and word-like. For quick unpack form the disk." | len | self isPointers | self isWords not ifTrue: [^ super newFromStream: s]. "super may cause an error, but will not be called." s next = 16r80 ifTrue: ["A compressed format. Could copy what BitMap does, or use a special sound compression format. Callers normally compress their own way." ^ self error: 'not implemented']. s skip: -1. len _ s nextInt32. ^ s nextWordsInto: (self basicNew: len)! ! !ArrayedCollection class methodsFor: 'instance creation'! with: anObject "Answer a new instance of me, containing only anObject." | newCollection | newCollection _ self new: 1. newCollection at: 1 put: anObject. ^newCollection! ! !ArrayedCollection class methodsFor: 'instance creation'! with: firstObject with: secondObject "Answer a new instance of me, containing firstObject and secondObject." | newCollection | newCollection _ self new: 2. newCollection at: 1 put: firstObject. newCollection at: 2 put: secondObject. ^newCollection! ! !ArrayedCollection class methodsFor: 'instance creation'! with: firstObject with: secondObject with: thirdObject "Answer a new instance of me, containing only the three arguments as elements." | newCollection | newCollection _ self new: 3. newCollection at: 1 put: firstObject. newCollection at: 2 put: secondObject. newCollection at: 3 put: thirdObject. ^newCollection! ! !ArrayedCollection class methodsFor: 'instance creation'! with: firstObject with: secondObject with: thirdObject with: fourthObject "Answer a new instance of me, containing only the three arguments as elements." | newCollection | newCollection _ self new: 4. newCollection at: 1 put: firstObject. newCollection at: 2 put: secondObject. newCollection at: 3 put: thirdObject. newCollection at: 4 put: fourthObject. ^newCollection! ! !ArrayedCollection class methodsFor: 'instance creation'! with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject "Answer a new instance of me, containing only the five arguments as elements." | newCollection | newCollection _ self new: 5. newCollection at: 1 put: firstObject. newCollection at: 2 put: secondObject. newCollection at: 3 put: thirdObject. newCollection at: 4 put: fourthObject. newCollection at: 5 put: fifthObject. ^newCollection! ! !ArrayedCollection class methodsFor: 'instance creation' stamp: 'sw 10/24/1998 22:22'! with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject with: sixthObject "Answer a new instance of me, containing only the 6 arguments as elements." | newCollection | newCollection _ self new: 6. newCollection at: 1 put: firstObject. newCollection at: 2 put: secondObject. newCollection at: 3 put: thirdObject. newCollection at: 4 put: fourthObject. newCollection at: 5 put: fifthObject. newCollection at: 6 put: sixthObject. ^ newCollection! ! !ArrayedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:37'! withAll: aCollection "Create a new collection containing all the elements from aCollection." ^ (self new: aCollection size) replaceFrom: 1 to: aCollection size with: aCollection! ! !ArrayedCollection class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 10:03'! ccg: cg generateCoerceToOopFrom: aNode on: aStream self instSize > 0 ifTrue: [self error: 'cannot auto-coerce arrays with named instance variables']. cg generateCoerceToObjectFromPtr: aNode on: aStream! ! !ArrayedCollection class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:18'! ccg: cg generateCoerceToValueFrom: aNode on: aStream cg generateCoerceToPtr: (self ccgDeclareCForVar: '') fromObject: aNode on: aStream! ! Halt subclass: #AssertionFailure instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Extensions'! !AssertionFailure commentStamp: 'gh 5/2/2002 20:29' prior: 0! AsssertionFailure is the exception signaled from Object>>assert: when the assertion block evaluates to false.! ParseNode subclass: #AssignmentNode instanceVariableNames: 'variable value' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !AssignmentNode commentStamp: '<historical>' prior: 0! AssignmentNode comment: 'I represent a (var_expr) construct.'! !AssignmentNode methodsFor: 'initialize-release'! toDoIncrement: var var = variable ifFalse: [^ nil]. (value isMemberOf: MessageNode) ifTrue: [^ value toDoIncrement: var] ifFalse: [^ nil]! ! !AssignmentNode methodsFor: 'initialize-release'! value ^ value! ! !AssignmentNode methodsFor: 'initialize-release'! variable: aVariable value: expression variable _ aVariable. value _ expression! ! !AssignmentNode methodsFor: 'initialize-release' stamp: 'di 3/22/1999 12:00'! variable: aVariable value: expression from: encoder (aVariable isMemberOf: MessageAsTempNode) ifTrue: ["Case of remote temp vars" ^ aVariable store: expression from: encoder]. variable _ aVariable. value _ expression! ! !AssignmentNode methodsFor: 'initialize-release' stamp: 'hmm 7/15/2001 21:17'! variable: aVariable value: expression from: encoder sourceRange: range encoder noteSourceRange: range forNode: self. ^self variable: aVariable value: expression from: encoder! ! !AssignmentNode methodsFor: 'code generation' stamp: 'di 9/5/2001 18:46'! emitForEffect: stack on: aStream variable emitLoad: stack on: aStream. value emitForValue: stack on: aStream. variable emitStorePop: stack on: aStream. pc _ aStream position! ! !AssignmentNode methodsFor: 'code generation' stamp: 'di 9/5/2001 21:26'! emitForValue: stack on: aStream variable emitLoad: stack on: aStream. value emitForValue: stack on: aStream. variable emitStore: stack on: aStream. pc _ aStream position! ! !AssignmentNode methodsFor: 'code generation'! sizeForEffect: encoder ^(value sizeForValue: encoder) + (variable sizeForStorePop: encoder)! ! !AssignmentNode methodsFor: 'code generation'! sizeForValue: encoder ^(value sizeForValue: encoder) + (variable sizeForStore: encoder)! ! !AssignmentNode methodsFor: 'printing' stamp: 'brp 10/8/2003 14:55'! printOn: aStream indent: level aStream dialect = #SQ00 ifTrue: [aStream withStyleFor: #setOrReturn do: [aStream nextPutAll: 'Set ']. variable printOn: aStream indent: level. aStream withStyleFor: #setOrReturn do: [aStream nextPutAll: ' to ']. value printOn: aStream indent: level + 2] ifFalse: [variable printOn: aStream indent: level. aStream nextPutAll: (Preferences ansiAssignmentOperatorWhenPrettyPrinting ifTrue: [' := '] ifFalse: [' _ ']). value printOn: aStream indent: level + 2]! ! !AssignmentNode methodsFor: 'printing' stamp: 'di 4/25/2000 13:52'! printOn: aStream indent: level precedence: p (aStream dialect = #SQ00 ifTrue: [p < 3] ifFalse: [p < 4]) ifTrue: [aStream nextPutAll: '('. self printOn: aStream indent: level. aStream nextPutAll: ')'] ifFalse: [self printOn: aStream indent: level]! ! !AssignmentNode methodsFor: 'equation translation'! variable ^variable! ! LookupKey subclass: #Association instanceVariableNames: 'value' classVariableNames: '' poolDictionaries: '' category: 'Collections-Support'! !Association commentStamp: '<historical>' prior: 0! I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.! !Association methodsFor: 'accessing'! key: aKey value: anObject "Store the arguments as the variables of the receiver." key _ aKey. value _ anObject! ! !Association methodsFor: 'accessing'! value "Answer the value of the receiver." ^value! ! !Association methodsFor: 'accessing'! value: anObject "Store the argument, anObject, as the value of the receiver." value _ anObject! ! !Association methodsFor: 'printing'! printOn: aStream super printOn: aStream. aStream nextPutAll: '->'. value printOn: aStream! ! !Association methodsFor: 'printing' stamp: 'MPW 1/4/1901 08:31'! propertyListOn: aStream aStream write:key; print:'='; write:value. ! ! !Association methodsFor: 'printing'! storeOn: aStream "Store in the format (key->value)" aStream nextPut: $(. key storeOn: aStream. aStream nextPutAll: '->'. value storeOn: aStream. aStream nextPut: $)! ! !Association methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 20:53'! byteEncode: aStream aStream writeAssocation:self.! ! !Association methodsFor: 'testing' stamp: 'ar 8/14/2001 23:06'! isSpecialWriteBinding "Return true if this variable binding is write protected, e.g., should not be accessed primitively but rather by sending #value: messages" ^false! ! !Association methodsFor: 'testing' stamp: 'ar 8/14/2001 22:39'! isVariableBinding "Return true if I represent a literal variable binding" ^true! ! !Association methodsFor: 'comparing' stamp: 'md 1/27/2004 17:27'! = anAssociation ^ super = anAssociation and: [value = anAssociation value]! ! !Association methodsFor: 'comparing' stamp: 'md 1/27/2004 17:28'! hash "Hash is reimplemented because = is implemented." ^key hash bitXor: value hash.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Association class instanceVariableNames: ''! !Association class methodsFor: 'instance creation'! key: newKey value: newValue "Answer an instance of me with the arguments as the key and value of the association." ^(super key: newKey) value: newValue! ! Error subclass: #AttemptToWriteReadOnlyGlobal instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !AttemptToWriteReadOnlyGlobal commentStamp: 'gh 5/2/2002 20:26' prior: 0! This is a resumable error you get if you try to assign a readonly variable a value. Name definitions in the module system can be read only and are then created using instances of ReadOnlyVariableBinding instead of Association. See also LookupKey>>beReadWriteBinding and LookupKey>>beReadOnlyBinding. ! !AttemptToWriteReadOnlyGlobal methodsFor: 'as yet unclassified' stamp: 'ar 8/17/2001 18:02'! description "Return a textual description of the exception." | desc mt | desc := 'Error'. ^(mt := self messageText) == nil ifTrue: [desc] ifFalse: [desc, ': ', mt]! ! !AttemptToWriteReadOnlyGlobal methodsFor: 'as yet unclassified' stamp: 'ar 8/17/2001 18:02'! isResumable ^true! ! Collection subclass: #Bag instanceVariableNames: 'contents' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !Bag commentStamp: '<historical>' prior: 0! I represent an unordered collection of possibly duplicate elements. 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.! !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 17:23'! at: index self errorNotKeyed! ! !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 17:23'! at: index put: anObject self errorNotKeyed! ! !Bag methodsFor: 'accessing' stamp: 'tao 1/5/2000 18:25'! cumulativeCounts "Answer with a collection of cumulative percents covered by elements so far." | s n | s _ self size / 100.0. n _ 0. ^ self sortedCounts asArray collect: [:a | n _ n + a key. (n / s roundTo: 0.1) -> a value]! ! !Bag methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:35'! size "Answer how many elements the receiver contains." | tally | tally _ 0. contents do: [:each | tally _ tally + each]. ^ tally! ! !Bag methodsFor: 'accessing' stamp: 'sma 6/15/2000 17:00'! sortedCounts "Answer with a collection of counts with elements, sorted by decreasing count." | counts | counts _ SortedCollection sortBlock: [:x :y | x >= y]. contents associationsDo: [:assn | counts add: (Association key: assn value value: assn key)]. ^ counts! ! !Bag methodsFor: 'accessing'! sortedElements "Answer with a collection of elements with counts, sorted by element." | elements | elements _ SortedCollection new. contents associationsDo: [:assn | elements add: assn]. ^elements! ! !Bag methodsFor: 'adding' stamp: 'sma 5/12/2000 17:18'! add: newObject "Include newObject as one of the receiver's elements. Answer newObject." ^ self add: newObject withOccurrences: 1! ! !Bag methodsFor: 'adding' stamp: 'sma 5/12/2000 17:20'! add: newObject withOccurrences: anInteger "Add newObject anInteger times to the receiver. Answer newObject." contents at: newObject put: (contents at: newObject ifAbsent: [0]) + anInteger. ^ newObject! ! !Bag methodsFor: 'converting' stamp: 'sma 5/12/2000 14:34'! asBag ^ self! ! !Bag methodsFor: 'converting' stamp: 'sma 5/12/2000 14:30'! asSet "Answer a set with the elements of the receiver." ^ contents keys! ! !Bag methodsFor: 'copying' stamp: 'sma 5/12/2000 14:53'! copy ^ self shallowCopy setContents: contents copy! ! !Bag methodsFor: 'enumerating'! do: aBlock "Refer to the comment in Collection|do:." contents associationsDo: [:assoc | assoc value timesRepeat: [aBlock value: assoc key]]! ! !Bag methodsFor: 'private' stamp: 'sma 5/12/2000 14:49'! setContents: aDictionary contents _ aDictionary! ! !Bag methodsFor: 'removing' stamp: 'sma 5/12/2000 14:32'! remove: oldObject ifAbsent: exceptionBlock "Refer to the comment in Collection|remove:ifAbsent:." | count | count _ contents at: oldObject ifAbsent: [^ exceptionBlock value]. count = 1 ifTrue: [contents removeKey: oldObject] ifFalse: [contents at: oldObject put: count - 1]. ^ oldObject! ! !Bag methodsFor: 'testing'! includes: anObject "Refer to the comment in Collection|includes:." ^contents includesKey: anObject! ! !Bag methodsFor: 'testing'! occurrencesOf: anObject "Refer to the comment in Collection|occurrencesOf:." (self includes: anObject) ifTrue: [^contents at: anObject] ifFalse: [^0]! ! !Bag methodsFor: 'comparing' stamp: 'raok 6/10/2002 15:28'! = aBag "Two bags are equal if (a) they are the same 'kind' of thing. (b) they have the same size. (c) each element occurs the same number of times in both of them". (aBag isKindOf: Bag) ifFalse: [^false]. self size = aBag size ifFalse: [^false]. contents associationsDo: [:assoc| (aBag occurrencesOf: assoc key) = assoc value ifFalse: [^false]]. ^true ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Bag class instanceVariableNames: ''! !Bag class methodsFor: 'instance creation' stamp: 'nk 3/17/2001 09:52'! contentsClass ^Dictionary! ! !Bag class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 13:31'! new ^ self new: 4! ! !Bag class methodsFor: 'instance creation' stamp: 'nk 3/17/2001 09:52'! new: nElements ^ super new setContents: (self contentsClass new: nElements)! ! !Bag class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:17'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." ^ self withAll: aCollection "Examples: Bag newFrom: {1. 2. 3. 3} {1. 2. 3. 3} as: Bag "! ! Categorizer subclass: #BasicClassOrganizer instanceVariableNames: 'subject classComment commentStamp' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:02'! classComment classComment ifNil: [^ '']. ^ classComment text ifNil: ['']! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! classComment: aString "Store the comment, aString, associated with the object that refers to the receiver." (aString isKindOf: RemoteString) ifTrue: [classComment _ aString] ifFalse: [(aString == nil or: [aString size = 0]) ifTrue: [classComment _ nil] ifFalse: [ self error: 'use aClass classComment:'. classComment _ RemoteString newString: aString onFileNumber: 2]] "Later add priorSource and date and initials?"! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! classComment: aString stamp: aStamp "Store the comment, aString, associated with the object that refers to the receiver." self commentStamp: aStamp. (aString isKindOf: RemoteString) ifTrue: [classComment _ aString] ifFalse: [(aString == nil or: [aString size = 0]) ifTrue: [classComment _ nil] ifFalse: [self error: 'use aClass classComment:'. classComment _ RemoteString newString: aString onFileNumber: 2]] "Later add priorSource and date and initials?"! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! commentRemoteStr ^ classComment! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! commentStamp "Answer the comment stamp for the class" ^ commentStamp! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! commentStamp: aStamp commentStamp _ aStamp! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! dateCommentLastSubmitted "Answer a Date object indicating when my class comment was last submitted. If there is no date stamp, or one of the old-time <historical> guys, return nil" "RecentMessageSet organization dateCommentLastSubmitted" | aStamp tokens | (aStamp _ self commentStamp) isEmptyOrNil ifTrue: [^ nil]. tokens _ aStamp findBetweenSubStrs: ' '. "space is expected delimiter, but cr is sometimes seen, though of mysterious provenance" ^ tokens size > 1 ifTrue: [[tokens second asDate] ifError: [nil]] ifFalse: [nil]! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:03'! hasNoComment "Answer whether the class classified by the receiver has a comment." ^classComment == nil! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:04'! hasSubject ^ self subject notNil! ! !BasicClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 16:04'! subject ^ subject.! ! !BasicClassOrganizer methodsFor: 'fileIn/Out' stamp: 'NS 4/7/2004 16:03'! fileOutCommentOn: aFileStream moveSource: moveSource toFile: fileIndex "Copy the class comment to aFileStream. If moveSource is true (as in compressChanges or compressSources, then update classComment to point to the new file." | fileComment | classComment ifNotNil: [aFileStream cr. fileComment _ RemoteString newString: classComment text onFileNumber: fileIndex toFile: aFileStream. moveSource ifTrue: [classComment _ fileComment]]! ! !BasicClassOrganizer methodsFor: 'fileIn/Out' stamp: 'NS 4/7/2004 16:04'! putCommentOnFile: aFileStream numbered: sourceIndex moveSource: moveSource forClass: aClass "Store the comment about the class onto file, aFileStream." | header | classComment ifNotNil: [aFileStream cr; nextPut: $!!. header _ String streamContents: [:strm | strm nextPutAll: aClass name; nextPutAll: ' commentStamp: '. commentStamp ifNil: [commentStamp _ '<historical>']. commentStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: '0']. aFileStream nextChunkPut: header. aClass organization fileOutCommentOn: aFileStream moveSource: moveSource toFile: sourceIndex. aFileStream cr]! ! !BasicClassOrganizer methodsFor: 'private' stamp: 'NS 4/7/2004 16:04'! setSubject: aClassDescription subject _ aClassDescription! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BasicClassOrganizer class instanceVariableNames: ''! !BasicClassOrganizer class methodsFor: 'instance creation' stamp: 'NS 4/7/2004 16:04'! class: aClassDescription ^ self new setSubject: aClassDescription! ! Inspector subclass: #BasicInspector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !BasicInspector methodsFor: 'as yet unclassified' stamp: 'ajh 1/31/2003 15:49'! inspect: anObject "Initialize the receiver so that it is inspecting anObject. There is no current selection." self initialize. object _ anObject. selectionIndex _ 0. contents _ ''! ! Object subclass: #Beeper instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Support'! !Beeper commentStamp: 'gk 2/26/2004 22:44' prior: 0! Beeper provides simple audio (or in some other way) feedback to the user. The recommended use is "Beeper beep" to give the user the equivalence of a beep. If you want to force the beep to use the primitive in the VM for beeping, then use "Beeper beepPrimitive". In either case, if sounds are disabled there will be no beep. The actual beeping, when you use "Beeper beep", is done by sending a #play message to a registered playable object. You can register your own playable object by invoking the class side method #setDefault: passing in an object that responds to the #play message. The default playable object is an instance of Beeper itself which implements #play on the instance side. That implementation delegates the playing of the beep to the default SoundService. Note that #play is introduced as a common interface between AbstractSound and Beeper. This way we can register instances of AbstractSound as playable entities, for example: Beeper setDefault: (SampledSound new setSamples: self coffeeCupClink samplingRate: 12000). Then "Beeper beep" will play the coffeeCup sound.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Beeper class instanceVariableNames: 'default'! !Beeper class methodsFor: 'customize' stamp: 'gk 2/22/2004 17:55'! default "When the default is not defined it is initialized using #newDefault." default isNil ifTrue: [default := self newDefault ]. ^ default! ! !Beeper class methodsFor: 'customize' stamp: 'gk 2/24/2004 22:12'! newDefault "Subclasses may override me to provide a default beep. This base implementation returns an instance of Beeper which uses the pluggable sound service." ^ self new! ! !Beeper class methodsFor: 'beeping' stamp: 'BG 11/26/2003 22:58'! beep "The preferred way of producing an audible feedback" self beepPrimitive ! ! !Beeper class methodsFor: 'beeping' stamp: 'gk 2/24/2004 08:38'! beepPrimitive "Make a primitive beep. Only use this if you want to force this to be a primitive beep. Otherwise use Beeper class>>beep since this method bypasses the current registered playable entity." Preferences soundsEnabled ifTrue: [ self primitiveBeep]! ! !Beeper class methodsFor: 'private' stamp: 'gk 2/24/2004 23:51'! primitiveBeep "Make a primitive beep. Not to be called directly. It is much better to use Beeper class>>beep or Beeper class>>beepPrimitive since this method bypasses the current registered playable entity and does not check Preferences class>>soundsEnabled." <primitive: 140> self primitiveFailed! ! Object subclass: #Behavior instanceVariableNames: 'superclass methodDict format' classVariableNames: 'ObsoleteSubclasses' poolDictionaries: '' category: 'Kernel-Classes'! !Behavior commentStamp: '<historical>' prior: 0! 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).! !Behavior methodsFor: 'initialize-release' stamp: 'NS 1/28/2004 11:17'! forgetDoIts "get rid of old DoIt methods" self basicRemoveSelector: #DoIt; basicRemoveSelector: #DoItIn:! ! !Behavior methodsFor: 'initialize-release' stamp: 'ar 9/10/1999 17:33'! obsolete "Invalidate and recycle local messages, e.g., zap the method dictionary if can be done safely." self canZapMethodDictionary ifTrue:[ methodDict _ MethodDictionary new ].! ! !Behavior methodsFor: 'initialize-release' stamp: 'ar 7/15/1999 16:39'! superclass: aClass methodDictionary: mDict format: fmt "Basic initialization of the receiver. Must only be sent to a new instance; else we would need Object flushCache." superclass _ aClass. format _ fmt. methodDict _ mDict.! ! !Behavior methodsFor: 'accessing'! compilerClass "Answer a compiler class appropriate for source methods of this class." ^Compiler! ! !Behavior methodsFor: 'accessing'! decompilerClass "Answer a decompiler class appropriate for compiled methods of this class." ^Decompiler! ! !Behavior methodsFor: 'accessing' stamp: 'ar 7/11/1999 05:17'! environment "Return the environment in which the receiver is visible" ^Smalltalk! ! !Behavior methodsFor: 'accessing'! evaluatorClass "Answer an evaluator class appropriate for evaluating expressions in the context of this class." ^Compiler! ! !Behavior methodsFor: 'accessing'! format "Answer an Integer that encodes the kinds and numbers of variables of instances of the receiver." ^format! ! !Behavior methodsFor: 'accessing' stamp: 'di 3/7/2001 17:05'! methodDict methodDict == nil ifTrue: [self recoverFromMDFaultWithTrace]. ^ methodDict! ! !Behavior methodsFor: 'accessing' stamp: 'rca 7/26/2000 16:53'! name "Answer a String that is the name of the receiver." ^'a subclass of ', superclass name! ! !Behavior methodsFor: 'accessing'! parserClass "Answer a parser class to use for parsing method headers." ^self compilerClass parserClass! ! !Behavior methodsFor: 'accessing'! sourceCodeTemplate "Answer an expression to be edited and evaluated in order to define methods in this class." ^'message selector and argument names "comment stating purpose of message" | temporary variable names | statements'! ! !Behavior methodsFor: 'accessing'! subclassDefinerClass "Answer an evaluator class appropriate for evaluating definitions of new subclasses of this class." ^Compiler! ! !Behavior methodsFor: 'accessing' stamp: 'ar 7/13/1999 22:00'! typeOfClass "Answer a symbol uniquely describing the type of the receiver" self instSpec = CompiledMethod instSpec ifTrue:[^#compiledMethod]. "Very special!!" self isBytes ifTrue:[^#bytes]. (self isWords and:[self isPointers not]) ifTrue:[^#words]. self isWeak ifTrue:[^#weak]. self isVariable ifTrue:[^#variable]. ^#normal.! ! !Behavior methodsFor: 'testing' stamp: 'ar 9/10/1999 17:29'! canZapMethodDictionary "Return true if it is safe to zap the method dictionary on #obsolete" ^true! ! !Behavior methodsFor: 'testing'! instSize "Answer the number of named instance variables (as opposed to indexed variables) of the receiver." self flag: #instSizeChange. "Smalltalk browseAllCallsOn: #instSizeChange" " NOTE: This code supports the backward-compatible extension to 8 bits of instSize. When we revise the image format, it should become... ^ ((format bitShift: -1) bitAnd: 16rFF) - 1 Note also that every other method in this category will require 2 bits more of right shift after the change. " ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! ! !Behavior methodsFor: 'testing'! instSpec ^ (format bitShift: -7) bitAnd: 16rF! ! !Behavior methodsFor: 'testing' stamp: 'ar 7/9/1999 18:18'! isBehavior "Return true if the receiver is a behavior" ^true! ! !Behavior methodsFor: 'testing'! isBits "Answer whether the receiver contains just bits (not pointers)." ^ self instSpec >= 6! ! !Behavior methodsFor: 'testing'! isBytes "Answer whether the receiver has 8-bit instance variables." ^ self instSpec >= 8! ! !Behavior methodsFor: 'testing'! isFixed "Answer whether the receiver does not have a variable (indexable) part." ^self isVariable not! ! !Behavior methodsFor: 'testing' stamp: 'ab 3/12/2003 17:44'! isMeta ^ false! ! !Behavior methodsFor: 'testing' stamp: 'ar 7/14/1999 02:38'! isObsolete "Return true if the receiver is obsolete." ^self instanceCount = 0! ! !Behavior methodsFor: 'testing'! isPointers "Answer whether the receiver contains just pointers (not bits)." ^self isBits not! ! !Behavior methodsFor: 'testing'! isVariable "Answer whether the receiver has indexable variables." ^ self instSpec >= 2! ! !Behavior methodsFor: 'testing' stamp: 'ar 3/21/98 02:36'! isWeak "Answer whether the receiver has contains weak references." ^ self instSpec = 4! ! !Behavior methodsFor: 'testing'! isWords "Answer whether the receiver has 16-bit instance variables." ^self isBytes not! ! !Behavior methodsFor: 'testing' stamp: 'sd 3/28/2003 15:07'! shouldNotBeRedefined "Return true if the receiver should not be redefined. The assumption is that compact classes, classes in Smalltalk specialObjects and Behaviors should not be redefined" ^(self environment compactClassesArray includes: self) or:[(self environment specialObjectsArray includes: self) or:[self isKindOf: self]]! ! !Behavior methodsFor: 'copying' stamp: 'di 2/17/2000 22:37'! copy "Answer a copy of the receiver without a list of subclasses." | myCopy | myCopy _ self shallowCopy. ^myCopy methodDictionary: self methodDict copy! ! !Behavior methodsFor: 'copying' stamp: 'tk 4/16/1999 17:30'! deepCopy "Classes should only be shallowCopied or made anew." ^ self shallowCopy! ! !Behavior methodsFor: 'printing' stamp: 'sw 10/13/2000 12:59'! defaultNameStemForInstances "Answer a basis for external names for default instances of the receiver. For classees, the class-name itself is a good one." ^ self name! ! !Behavior methodsFor: 'printing' stamp: 'ar 5/17/2003 14:11'! literalScannedAs: scannedLiteral notifying: requestor "Postprocesses a literal scanned by Scanner scanToken (esp. xLitQuote). If scannedLiteral is not an association, answer it. Else, if it is of the form: nil->#NameOfMetaclass answer nil->theMetaclass, if any has that name, else report an error. Else, if it is of the form: #NameOfGlobalVariable->anythiEng answer the global, class, or pool association with that nameE, if any, else add it to Undeclared a answer the new Association." | key value | (scannedLiteral isVariableBinding) ifFalse: [^ scannedLiteral]. key _ scannedLiteral key. value _ scannedLiteral value. key isNil ifTrue: "###<metaclass soleInstance name>" [(self bindingOf: value) ifNotNilDo:[:assoc| (assoc value isKindOf: Behavior) ifTrue: [^ nil->assoc value class]]. requestor notify: 'No such metaclass'. ^false]. (key isMemberOf: Symbol) ifTrue: "##<global var name>" [(self bindingOf: key) ifNotNilDo:[:assoc | ^assoc]. Undeclared at: key put: nil. ^Undeclared bindingOf: key]. requestor notify: '## must be followed by a non-local variable name'. ^false " Form literalScannedAs: 14 notifying: nil 14 Form literalScannedAs: #OneBitForm notiEfying: nil OneBitForm Form literalScannedAs: ##OneBitForm notifying: nil OneBitForm->a Form Form literalScannedAs: ##Form notifying: nil Form->Form Form literalScannedAs: ###Form notifying: nil nilE->Form class "! ! !Behavior methodsFor: 'printing' stamp: 'tk 10/16/2001 19:35'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables. But, not useful for a class with a method dictionary." aStream nextPutAll: '<<too complex to show>>'; cr.! ! !Behavior methodsFor: 'printing'! printHierarchy "Answer a description containing the names and instance variable names of all of the subclasses and superclasses of the receiver." | aStream index | index _ 0. aStream _ WriteStream on: (String new: 16). self allSuperclasses reverseDo: [:aClass | aStream crtab: index. index _ index + 1. aStream nextPutAll: aClass name. aStream space. aStream print: aClass instVarNames]. aStream cr. self printSubclassesOn: aStream level: index. ^aStream contents! ! !Behavior methodsFor: 'printing'! printOn: aStream "Refer to the comment in Object|printOn:." aStream nextPutAll: 'a descendent of '. superclass printOn: aStream! ! !Behavior methodsFor: 'printing' stamp: 'MPW 1/1/1901 21:56'! printOnStream: aStream "Refer to the comment in Object|printOn:." aStream print: 'a descendent of '; write:superclass.! ! !Behavior methodsFor: 'compiling'! compile: code "Compile the argument, code, as source code in the context of the receiver. Create an error notification if the code can not be compiled. The argument is either a string or an object that converts to a string or a PositionableStream on an object that converts to a string." ^self compile: code notifying: nil! ! !Behavior methodsFor: 'compiling' stamp: 'NS 1/28/2004 13:59'! compile: code notifying: requestor "Compile the argument, code, as source code in the context of the receiver and insEtall the result in the receiver's method dictionary. The second argument, requestor, is to be notified if an error occurs. The argument code is either a string or an object that converts to a string or a PositionableStream. This method also saves the source code." | methodAndNode | methodAndNode _ self basicCompile: code "a Text" notifying: requestor trailer: self defaultMethodTrailer ifFail: [^nil]. methodAndNode method putSource: code fromParseNode: methodAndNode node inFile: 2 withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr]. self addSelector: methodAndNode selector withMethod: methodAndNode method notifying: requestor. ^ methodAndNode selector! ! !Behavior methodsFor: 'compiling'! compileAll ^ self compileAllFrom: self! ! !Behavior methodsFor: 'compiling' stamp: 'sd 3/28/2003 15:07'! compileAllFrom: oldClass "Compile all the methods in the receiver's method dictionary. This validates sourceCode and variable references and forces all methods to use the current bytecode set" "ar 7/10/1999: Use oldClass selectors not self selectors" oldClass selectorsDo: [:sel | self recompile: sel from: oldClass]. self environment currentProjectDo: [:proj | proj compileAllIsolated: self from: oldClass].! ! !Behavior methodsFor: 'compiling' stamp: 'NS 1/28/2004 11:32'! defaultMethodTrailer ^ #(0 0 0 0)! ! !Behavior methodsFor: 'compiling' stamp: 'NS 1/28/2004 09:22'! recompile: selector from: oldClass "Compile the method associated with selector in the receiver's method dictionary." "ar 7/10/1999: Use oldClass compiledMethodAt: not self compiledMethodAt:" | method trailer methodNode | method _ oldClass compiledMethodAt: selector. trailer _ method trailer. methodNode _ self compilerClass new compile: (oldClass sourceCodeAt: selector) in: self notifying: nil ifFail: [^ self]. "Assume OK after proceed from SyntaxError" selector == methodNode selector ifFalse: [self error: 'selector changed!!']. self addSelectorSilently: selector withMethod: (methodNode generate: trailer). ! ! !Behavior methodsFor: 'compiling' stamp: 'ajh 6/11/2001 17:05'! recompileNonResidentMethod: method atSelector: selector from: oldClass "Recompile the method supplied in the context of this class." | trailer methodNode | trailer _ method trailer. methodNode _ self compilerClass new compile: (method getSourceFor: selector in: oldClass) in: self notifying: nil ifFail: ["We're in deep doo-doo if this fails (syntax error). Presumably the user will correct something and proceed, thus installing the result in this methodDict. We must retrieve that new method, and restore the original (or remove) and then return the method we retrieved." ^ self error: 'see comment']. selector == methodNode selector ifFalse: [self error: 'selector changed!!']. ^ methodNode generate: trailer ! ! !Behavior methodsFor: 'instance creation' stamp: 'sd 3/28/2003 15:06'! basicNew "Primitive. Answer an instance of the receiver (which is a class) with no indexable variables. Fail if the class is indexable. Essential. See Object documentation whatIsAPrimitive." <primitive: 70> self isVariable ifTrue: [ ^ self basicNew: 0 ]. "space must be low" self environment signalLowSpace. ^ self basicNew "retry if user proceeds" ! ! !Behavior methodsFor: 'instance creation' stamp: 'sd 3/28/2003 15:06'! basicNew: sizeRequested "Primitive. Answer an instance of this class with the number of indexable variables specified by the argument, sizeRequested. Fail if this class is not indexable or if the argument is not a positive Integer, or if there is not enough memory available. Essential. See Object documentation whatIsAPrimitive." <primitive: 71> self isVariable ifFalse: [self error: self printString, ' cannot have variable sized instances']. (sizeRequested isInteger and: [sizeRequested >= 0]) ifTrue: ["arg okay; space must be low." self environment signalLowSpace. ^ self basicNew: sizeRequested "retry if user proceeds"]. self primitiveFailed! ! !Behavior methodsFor: 'instance creation' stamp: 'sw 5/4/2000 20:47'! initializedInstance "Answer an instance of the receiver which in some sense is initialized. In the case of Morphs, this will yield an instance that can be attached to the Hand after having received the same kind of basic initialization that would be obtained from an instance chosen from the 'new morph' menu. Return nil if the receiver is reluctant for some reason to return such a thing" ^ self new! ! !Behavior methodsFor: 'instance creation'! new "Answer a new initialized instance of the receiver (which is a class) with no indexable variables. Fail if the class is indexable." ^ self basicNew initialize ! ! !Behavior methodsFor: 'instance creation' stamp: 'sd 5/20/2004 11:20'! new: sizeRequested "Answer an initialized instance of this class with the number of indexable variables specified by the argument, sizeRequested." ^ (self basicNew: sizeRequested) initialize ! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'nb 5/6/2003 17:11'! allSubclasses "Answer a Set of the receiver's and the receiver's descendent's subclasses. " | scan scanTop | scan _ OrderedCollection withAll: self subclasses. scanTop _ 1. [scanTop > scan size] whileFalse: [scan addAll: (scan at: scanTop) subclasses. scanTop _ scanTop + 1]. ^ scan asSet! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'sd 3/28/2003 15:06'! allSubclassesWithLevelDo: classAndLevelBlock startingLevel: level "Walk the tree of subclasses, giving the class and its level" | subclassNames | classAndLevelBlock value: self value: level. self == Class ifTrue: [^ self]. "Don't visit all the metaclasses" "Visit subclasses in alphabetical order" subclassNames _ SortedCollection new. self subclassesDo: [:subC | subclassNames add: subC name]. subclassNames do: [:name | (self environment at: name) allSubclassesWithLevelDo: classAndLevelBlock startingLevel: level+1]! ! !Behavior methodsFor: 'accessing class hierarchy'! allSuperclasses "Answer an OrderedCollection of the receiver's and the receiver's ancestor's superclasses. The first element is the receiver's immediate superclass, followed by its superclass; the last element is Object." | temp | ^ superclass == nil ifTrue: [ OrderedCollection new] ifFalse: [temp _ superclass allSuperclasses. temp addFirst: superclass. temp]! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'sd 3/14/2004 18:09'! subclasses "slow implementation since Behavior does not keep trace of subclasses" ^ self class allInstances select: [:each | each superclass = self ]! ! !Behavior methodsFor: 'accessing class hierarchy'! superclass "Answer the receiver's superclass, a Class." ^superclass! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'ar 7/10/1999 12:10'! superclass: aClass "Change the receiver's superclass to be aClass." "Note: Do not use 'aClass isKindOf: Behavior' here in case we recompile from Behavior itself." (aClass == nil or: [aClass isBehavior]) ifTrue: [superclass _ aClass. Object flushCache] ifFalse: [self error: 'superclass must be a class-describing object']! ! !Behavior methodsFor: 'accessing class hierarchy'! withAllSubclasses "Answer a Set of the receiver, the receiver's descendent's, and the receiver's descendent's subclasses." ^ self allSubclasses add: self; yourself! ! !Behavior methodsFor: 'accessing class hierarchy'! withAllSuperclasses "Answer an OrderedCollection of the receiver and the receiver's superclasses. The first element is the receiver, followed by its superclass; the last element is Object." | temp | temp _ self allSuperclasses. temp addFirst: self. ^ temp! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'bf 9/27/1999 17:23'! >> selector "Answer the compiled method associated with the argument, selector (a Symbol), a message selector in the receiver's method dictionary. If the selector is not in the dictionary, create an error notification." ^self compiledMethodAt: selector ! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'NS 1/28/2004 09:34'! addSelector: selector withMethod: compiledMethod notifying: requestor ^ self addSelectorSilently: selector withMethod: compiledMethod! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'NS 1/28/2004 11:27'! addSelectorSilently: selector withMethod: compiledMethod "Add the message selector with the corresponding compiled method to the receiver's method dictionary. Do this without sending system change notifications" | oldMethodOrNil | oldMethodOrNil _ self lookupSelector: selector. self methodDict at: selector put: compiledMethod. "Now flush Squeak's method cache, either by selector or by method" oldMethodOrNil == nil ifFalse: [oldMethodOrNil flushCache]. selector flushCache.! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'NS 12/12/2003 15:57'! allSelectors "Answer all selectors understood by instances of the receiver" | coll | coll _ OrderedCollection new. self withAllSuperclasses do: [:aClass | coll addAll: aClass selectors]. ^ coll asIdentitySet! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 10/19/1999 15:12'! changeRecordsAt: selector "Return a list of ChangeRecords for all versions of the method at selector. Source code can be retrieved by sending string to any one. Return nil if the method is absent." "(Pen changeRecordsAt: #go:) collect: [:cRec | cRec string]" | aList | aList _ VersionsBrowser new scanVersionsOf: (self compiledMethodAt: selector ifAbsent: [^ nil]) class: self meta: self isMeta category: (self whichCategoryIncludesSelector: selector) selector: selector. ^ aList ifNotNil: [aList changeList]! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:37'! compiledMethodAt: selector "Answer the compiled method associated with the argument, selector (a Symbol), a message selector in the receiver's method dictionary. If the selector is not in the dictionary, create an error notification." ^ self methodDict at: selector! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:41'! compiledMethodAt: selector ifAbsent: aBlock "Answer the compiled method associated with the argument, selector (a Symbol), a message selector in the receiver's method dictionary. If the selector is not in the dictionary, return the value of aBlock" ^ self methodDict at: selector ifAbsent: [aBlock value]! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 12/1/2000 20:12'! firstCommentAt: selector "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 does map doubled quote into a single quote." | sourceString commentStart pos nextQuotePos | sourceString _ (self sourceCodeAt: selector) asString. sourceString size == 0 ifTrue: [^ '']. commentStart _ sourceString findString: '"' startingAt: 1. commentStart == 0 ifTrue: [^ '']. pos _ commentStart + 1. [(nextQuotePos _ sourceString findString: '"' startingAt: pos) == (sourceString findString: '""' startingAt: pos)] whileTrue: [pos _ nextQuotePos + 2]. commentStart == nextQuotePos ifTrue: [^ '']. "Must have been a quote in string literal" ^ (sourceString copyFrom: commentStart + 1 to: nextQuotePos - 1) copyReplaceAll: '""' with: '"' "Behavior firstCommentAt: #firstCommentAt:"! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 6/20/2001 15:46'! firstPrecodeCommentFor: selector "If there is a comment in the source code at the given selector that preceeds the body of the method, return it here, else return nil" | parser source tree | "Behavior firstPrecodeCommentFor: #firstPrecodeCommentFor:" (MessageSet isPseudoSelector: selector) ifTrue: ["Not really a selector" ^ nil]. source _ self sourceCodeAt: selector asSymbol ifAbsent: [^ nil]. parser _ self parserClass new. tree _ parser parse: (ReadStream on: source) class: self noPattern: false context: nil notifying: nil ifFail: [^ nil]. ^ (tree comment ifNil: [^ nil]) first! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 1/2/1999 15:45'! lookupSelector: selector "Look up the given selector in my methodDictionary. Return the corresponding method if found. Otherwise chase the superclass chain and try again. Return nil if no method is found." | lookupClass | lookupClass _ self. [lookupClass == nil] whileFalse: [(lookupClass includesSelector: selector) ifTrue: [^ lookupClass compiledMethodAt: selector]. lookupClass _ lookupClass superclass]. ^ nil! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'ar 7/11/1999 05:11'! methodDictionary "Convenience" ^self methodDict! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'ar 7/12/1999 07:45'! methodDictionary: aDictionary "Store the argument, aDictionary, as the method dictionary of the receiver." methodDict _ aDictionary.! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'ar 12/27/2001 22:29'! methodHeaderFor: selector "Answer the string corresponding to the method header for the given selector" | sourceString parser | sourceString _ self ultimateSourceCodeAt: selector ifAbsent: [self standardMethodHeaderFor: selector]. (parser _ self parserClass new) parseSelector: sourceString. ^ sourceString asString copyFrom: 1 to: (parser endOfLastToken min: sourceString size) "Behavior methodHeaderFor: #methodHeaderFor: " ! ! !Behavior methodsFor: 'accessing method dictionary'! precodeCommentOrInheritedCommentFor: selector "Answer a string representing the first comment in the method associated with selector, considering however only comments that occur before the beginning of the actual code. If the version recorded in the receiver is uncommented, look up the inheritance chain. Return nil if none found." | aSuper aComment | ^ (aComment _ self firstPrecodeCommentFor: selector) isEmptyOrNil ifTrue: [(self == Behavior or: [superclass == nil or: [(aSuper _ superclass whichClassIncludesSelector: selector) == nil]]) ifFalse: [aSuper precodeCommentOrInheritedCommentFor: selector] "ActorState precodeCommentOrInheritedCommentFor: #printOn:"] ifFalse: [aComment]! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'NS 1/28/2004 11:17'! removeSelector: selector "Assuming that the argument, selector (a Symbol), is a message selector in my method dictionary, remove it and its method." ^ self basicRemoveSelector: selector! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'rw 5/12/2003 11:19'! selectorAtMethod: method setClass: classResultBlock "Answer both the message selector associated with the compiled method and the class in which that selector is defined." | sel | sel _ self methodDict keyAtIdentityValue: method ifAbsent: [superclass == nil ifTrue: [classResultBlock value: self. ^method defaultSelector]. sel _ superclass selectorAtMethod: method setClass: classResultBlock. "Set class to be self, rather than that returned from superclass. " sel == method defaultSelector ifTrue: [classResultBlock value: self]. ^sel]. classResultBlock value: self. ^sel! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:38'! selectors "Answer a Set of all the message selectors specified in the receiver's method dictionary." ^ self methodDict keys "Point selectors."! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:41'! selectorsAndMethodsDo: aBlock "Evaluate selectorBlock for all the message selectors in my method dictionary." ^ self methodDict keysAndValuesDo: aBlock! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:38'! selectorsDo: selectorBlock "Evaluate selectorBlock for all the message selectors in my method dictionary." ^ self methodDict keysDo: selectorBlock! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'tk 3/24/1999 07:44'! selectorsWithArgs: numberOfArgs "Return all selectors defined in this class that take this number of arguments. Could use String.keywords. Could see how compiler does this." | list num | list _ OrderedCollection new. self selectorsDo: [:aSel | num _ aSel count: [:char | char == $:]. num = 0 ifTrue: [aSel last isLetter ifFalse: [num _ 1]]. num = numberOfArgs ifTrue: [list add: aSel]]. ^ list! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:40'! sourceCodeAt: selector ^ (self methodDict at: selector) getSourceFor: selector in: self! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 2/17/2000 22:40'! sourceCodeAt: selector ifAbsent: aBlock ^ (self methodDict at: selector ifAbsent: [^ aBlock value]) getSourceFor: selector in: self! ! !Behavior methodsFor: 'accessing method dictionary'! sourceMethodAt: selector "Answer the paragraph corresponding to the source code for the argument." ^(self sourceCodeAt: selector) asText makeSelectorBoldIn: self! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 11/3/97 00:10'! sourceMethodAt: selector ifAbsent: aBlock "Answer the paragraph corresponding to the source code for the argument." ^ (self sourceCodeAt: selector ifAbsent: [^ aBlock value]) asText makeSelectorBoldIn: self! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'ar 12/27/2001 22:29'! standardMethodHeaderFor: aSelector | args | args _ (1 to: aSelector numArgs) collect:[:i| 'arg', i printString]. args size = 0 ifTrue:[^aSelector asString]. args size = 1 ifTrue:[^aSelector,' arg1']. ^String streamContents:[:s| (aSelector findTokens:':') with: args do:[:tok :arg| s nextPutAll: tok; nextPutAll:': '; nextPutAll: arg; nextPutAll:' '. ]. ]. ! ! !Behavior methodsFor: 'accessing method dictionary'! supermostPrecodeCommentFor: selector "Answer a string representing the precode comment in the most distant superclass's implementation of the selector. Return nil if none found." | aSuper superComment | (self == Behavior or: [superclass == nil or: [(aSuper _ superclass whichClassIncludesSelector: selector) == nil]]) ifFalse: ["There is a super implementor" superComment _ aSuper supermostPrecodeCommentFor: selector]. ^ superComment ifNil: [self firstPrecodeCommentFor: selector "ActorState supermostPrecodeCommentFor: #printOn:"]! ! !Behavior methodsFor: 'accessing method dictionary' stamp: 'sd 2/1/2004 19:41'! zapAllMethods "Remove all methods in this class which is assumed to be obsolete" methodDict _ MethodDictionary new. self class isMeta ifTrue: [self class zapAllMethods]! ! !Behavior methodsFor: 'accessing instances and variables'! allClassVarNames "Answer a Set of the names of the receiver's and the receiver's ancestor's class variables." ^superclass allClassVarNames! ! !Behavior methodsFor: 'accessing instances and variables'! allInstVarNames "Answer an Array of the names of the receiver's instance variables. The Array ordering is the order in which the variables are stored and accessed by the interpreter." | vars | superclass == nil ifTrue: [vars _ self instVarNames copy] "Guarantee a copy is answered." ifFalse: [vars _ superclass allInstVarNames , self instVarNames]. ^vars! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'jm 5/20/1998 15:53'! allInstances "Answer a collection of all current instances of the receiver." | all | all _ OrderedCollection new. self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. ^ all asArray ! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'tpr 5/30/2003 13:04'! allSharedPools "Answer a Set of the names of the pools (Dictionaries or SharedPool subclasses) that the receiver and the receiver's ancestors share." ^superclass allSharedPools! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'di 6/20/97 10:51'! allSubInstances "Answer a list of all current instances of the receiver and all of its subclasses." | aCollection | aCollection _ OrderedCollection new. self allSubInstancesDo: [:x | x == aCollection ifFalse: [aCollection add: x]]. ^ aCollection! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'ajh 10/17/2002 11:03'! allowsSubInstVars "Classes that allow instances to change classes among its subclasses will want to override this and return false, so inst vars are not accidentally added to its subclasses." ^ true! ! !Behavior methodsFor: 'accessing instances and variables'! classVarNames "Answer a Set of the receiver's class variable names." ^Set new! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'sw 5/21/2001 22:51'! inspectAllInstances "Inpsect all instances of the receiver. 1/26/96 sw" | all allSize prefix | all _ self allInstances. (allSize _ all size) == 0 ifTrue: [^ self inform: 'There are no instances of ', self name]. prefix _ allSize == 1 ifTrue: ['The lone instance'] ifFalse: ['The ', allSize printString, ' instances']. all asArray inspectWithLabel: (prefix, ' of ', self name)! ! !Behavior methodsFor: 'accessing instances and variables' stamp: 'sw 5/21/2001 22:51'! inspectSubInstances "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" | all allSize prefix | all _ self allSubInstances. (allSize _ all size) == 0 ifTrue: [^ self inform: 'There are no instances of ', self name, ' or any of its subclasses']. prefix _ allSize == 1 ifTrue: ['The lone instance'] ifFalse: ['The ', allSize printString, ' instances']. all asArray inspectWithLabel: (prefix, ' of ', self name, ' & its subclasses')! ! !Behavior methodsFor: 'accessing instances and variables'! instVarNames "Answer an Array of the instance variable names. Behaviors must make up fake local instance variable names because Behaviors have instance variables for the purpose of compiling methods, but these are not named instance variables." | mySize superSize | mySize _ self instSize. superSize _ superclass == nil ifTrue: [0] ifFalse: [superclass instSize]. mySize = superSize ifTrue: [^#()]. ^(superSize + 1 to: mySize) collect: [:i | 'inst' , i printString]! ! !Behavior methodsFor: 'accessing instances and variables'! instanceCount "Answer the number of instances of the receiver that are currently in use." | count | count _ 0. self allInstancesDo: [:x | count _ count + 1]. ^count! ! !Behavior methodsFor: 'accessing instances and variables'! sharedPools "Answer a Set of the names of the pools (Dictionaries) that the receiver shares. 9/12/96 tk sharedPools have an order now" ^ OrderedCollection new! ! !Behavior methodsFor: 'accessing instances and variables'! someInstance "Primitive. Answer the first instance in the enumeration of all instances of the receiver. Fails if there are none. Essential. See Object documentation whatIsAPrimitive." <primitive: 77> ^nil! ! !Behavior methodsFor: 'accessing instances and variables'! subclassInstVarNames "Answer a Set of the names of the receiver's subclasses' instance variables." | vars | vars _ Set new. self allSubclasses do: [:aSubclass | vars addAll: aSubclass instVarNames]. ^vars! ! !Behavior methodsFor: 'testing class hierarchy' stamp: 'ar 3/12/98 12:36'! includesBehavior: aClass ^self == aClass or:[self inheritsFrom: aClass]! ! !Behavior methodsFor: 'testing class hierarchy'! inheritsFrom: aClass "Answer whether the argument, aClass, is on the receiver's superclass chain." | aSuperclass | aSuperclass _ superclass. [aSuperclass == nil] whileFalse: [aSuperclass == aClass ifTrue: [^true]. aSuperclass _ aSuperclass superclass]. ^false! ! !Behavior methodsFor: 'testing class hierarchy'! kindOfSubclass "Answer a String that is the keyword that describes the receiver's kind of subclass, either a regular subclass, a variableSubclass, a variableByteSubclass, a variableWordSubclass, or a weakSubclass." self isWeak ifTrue: [^ ' weakSubclass: ']. ^ self isVariable ifTrue: [self isBits ifTrue: [self isBytes ifTrue: [ ' variableByteSubclass: '] ifFalse: [ ' variableWordSubclass: ']] ifFalse: [ ' variableSubclass: ']] ifFalse: [ ' subclass: ']! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'ar 5/17/2003 14:06'! bindingOf: varName "Answer the binding of some variable resolved in the scope of the receiver" ^superclass bindingOf: varName! ! !Behavior methodsFor: 'testing method dictionary'! canUnderstand: selector "Answer whether the receiver can respond to the message whose selector is the argument. The selector can be in the method dictionary of the receiver's class or any of its superclasses." (self includesSelector: selector) ifTrue: [^true]. superclass == nil ifTrue: [^false]. ^superclass canUnderstand: selector! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'ar 5/18/2003 18:13'! classBindingOf: varName "Answer the binding of some variable resolved in the scope of the receiver's class" ^self bindingOf: varName! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'di 2/17/2000 22:40'! hasMethods "Answer whether the receiver has any methods in its method dictionary." ^ self methodDict size > 0! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'di 3/27/1999 23:20'! includesSelector: aSymbol "Answer whether the message whose selector is the argument is in the method dictionary of the receiver's class." ^ self methodDict includesKey: aSymbol! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'ar 5/17/2003 14:20'! scopeHas: varName ifTrue: aBlock "Obsolete. Kept around for possible spurios senders which we don't know about" (self bindingOf: varName) ifNotNilDo:[:binding| aBlock value: binding. ^true]. ^false! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'ar 8/16/2001 13:31'! thoroughWhichSelectorsReferTo: literal special: specialFlag byte: specialByte "Answer a set of selectors whose methods access the argument as a literal. Dives into the compact literal notation, making it slow but thorough " | who | who _ Set new. self selectorsAndMethodsDo: [:sel :method | ((method hasLiteralThorough: literal) or: [specialFlag and: [method scanFor: specialByte]]) ifTrue: [((literal isVariableBinding) not or: [method sendsToSuper not or: [method literals allButLast includes: literal]]) ifTrue: [who add: sel]]]. ^ who! ! !Behavior methodsFor: 'testing method dictionary'! whichClassIncludesSelector: aSymbol "Answer the class on the receiver's superclass chain where the argument, aSymbol (a message selector), will be found. Answer nil if none found." "Rectangle whichClassIncludesSelector: #inspect." (self includesSelector: aSymbol) ifTrue: [^ self]. superclass == nil ifTrue: [^ nil]. ^ superclass whichClassIncludesSelector: aSymbol! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'di 2/17/2000 22:40'! whichSelectorsAccess: instVarName "Answer a Set of selectors whose methods access the argument, instVarName, as a named instance variable." | instVarIndex | instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new]. ^ self methodDict keys select: [:sel | ((self methodDict at: sel) readsField: instVarIndex) or: [(self methodDict at: sel) writesField: instVarIndex]] "Point whichSelectorsAccess: 'x'."! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'sd 3/28/2003 15:07'! whichSelectorsReferTo: literal "Answer a Set of selectors whose methods access the argument as a literal." | special byte | special _ self environment hasSpecialSelector: literal ifTrueSetByte: [:b | byte _ b]. ^self whichSelectorsReferTo: literal special: special byte: byte "Rectangle whichSelectorsReferTo: #+."! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'ar 8/16/2001 13:31'! whichSelectorsReferTo: literal special: specialFlag byte: specialByte "Answer a set of selectors whose methods access the argument as a literal." | who | who _ Set new. self selectorsAndMethodsDo: [:sel :method | ((method hasLiteral: literal) or: [specialFlag and: [method scanFor: specialByte]]) ifTrue: [((literal isVariableBinding) not or: [method sendsToSuper not or: [method literals allButLast includes: literal]]) ifTrue: [who add: sel]]]. ^ who! ! !Behavior methodsFor: 'testing method dictionary' stamp: 'di 2/17/2000 22:39'! whichSelectorsStoreInto: instVarName "Answer a Set of selectors whose methods access the argument, instVarName, as a named instance variable." | instVarIndex | instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new]. ^ self methodDict keys select: [:sel | (self methodDict at: sel) writesField: instVarIndex] "Point whichSelectorsStoreInto: 'x'."! ! !Behavior methodsFor: 'enumerating'! allInstancesDo: aBlock "Evaluate the argument, aBlock, for each of the current instances of the receiver." | inst next | self == UndefinedObject ifTrue: [^ aBlock value: nil]. inst _ self someInstance. [inst == nil] whileFalse: [aBlock value: inst. inst _ inst nextInstance]! ! !Behavior methodsFor: 'enumerating' stamp: 'di 6/20/97 10:50'! allSubInstancesDo: aBlock "Evaluate the argument, aBlock, for each of the current instances of the receiver and all its subclasses." self allInstancesDo: aBlock. self allSubclassesDo: [:sub | sub allInstancesDo: aBlock]! ! !Behavior methodsFor: 'enumerating'! allSubclassesDo: aBlock "Evaluate the argument, aBlock, for each of the receiver's subclasses." self subclassesDo: [:cl | aBlock value: cl. cl allSubclassesDo: aBlock]! ! !Behavior methodsFor: 'enumerating' stamp: 'tk 8/18/1999 17:38'! allSubclassesDoGently: aBlock "Evaluate the argument, aBlock, for each of the receiver's subclasses." self subclassesDoGently: [:cl | cl isInMemory ifTrue: [ aBlock value: cl. cl allSubclassesDoGently: aBlock]]! ! !Behavior methodsFor: 'enumerating'! allSuperclassesDo: aBlock "Evaluate the argument, aBlock, for each of the receiver's superclasses." superclass == nil ifFalse: [aBlock value: superclass. superclass allSuperclassesDo: aBlock]! ! !Behavior methodsFor: 'enumerating'! withAllSubclassesDo: aBlock "Evaluate the argument, aBlock, for the receiver and each of its subclasses." aBlock value: self. self allSubclassesDo: aBlock! ! !Behavior methodsFor: 'enumerating' stamp: 'nk 2/14/2001 12:09'! withAllSuperAndSubclassesDoGently: aBlock self allSuperclassesDo: aBlock. aBlock value: self. self allSubclassesDoGently: aBlock! ! !Behavior methodsFor: 'enumerating' stamp: 'ar 7/11/1999 04:21'! withAllSuperclassesDo: aBlock "Evaluate the argument, aBlock, for each of the receiver's superclasses." aBlock value: self. superclass == nil ifFalse: [superclass withAllSuperclassesDo: aBlock]! ! !Behavior methodsFor: 'user interface' stamp: 'sd 3/28/2003 15:05'! allLocalCallsOn: aSymbol "Answer a SortedCollection of all the methods that call on aSymbol, anywhere in my class hierarchy." | aSet special byte cls | aSet _ Set new. cls _ self theNonMetaClass. special _ self environment hasSpecialSelector: aSymbol ifTrueSetByte: [:b | byte _ b ]. cls withAllSuperAndSubclassesDoGently: [ :class | (class whichSelectorsReferTo: aSymbol special: special byte: byte) do: [:sel | sel ~~ #DoIt ifTrue: [aSet add: class name , ' ', sel]]]. cls class withAllSuperAndSubclassesDoGently: [ :class | (class whichSelectorsReferTo: aSymbol special: special byte: byte) do: [:sel | sel ~~ #DoIt ifTrue: [aSet add: class name , ' ', sel]]]. ^aSet! ! !Behavior methodsFor: 'user interface' stamp: 'sw 4/4/2000 11:22'! allUnreferencedInstanceVariables "Return a list of the instance variables known to the receiver which are not referenced in the receiver or any of its subclasses OR superclasses" | any definingClass | ^ self allInstVarNames copy reject: [:ivn | any _ false. definingClass _ self classThatDefinesInstanceVariable: ivn. definingClass withAllSubclasses do: [:class | any ifFalse: [(class whichSelectorsAccess: ivn asSymbol) do: [:sel | sel ~~ #DoIt ifTrue: [any _ true]]]]. any]! ! !Behavior methodsFor: 'user interface' stamp: 'RAA 5/28/2001 12:00'! withAllSubAndSuperclassesDo: aBlock self withAllSubclassesDo: aBlock. self allSuperclassesDo: aBlock. ! ! !Behavior methodsFor: 'private' stamp: 'NS 1/28/2004 13:59'! basicCompile: code notifying: requestor trailer: bytes ifFail: failBlock "Compile code without logging the source in the changes file" | methodNode | methodNode _ self compilerClass new compile: code in: self notifying: requestor ifFail: failBlock. methodNode encoder requestor: requestor. ^ CompiledMethodWithNode generateMethodFromNode: methodNode trailer: bytes.! ! !Behavior methodsFor: 'private' stamp: 'NS 1/28/2004 10:29'! basicRemoveSelector: selector "Assuming that the argument, selector (a Symbol), is a message selector in my method dictionary, remove it and its method." | oldMethod | oldMethod _ self methodDict at: selector ifAbsent: [^ self]. self methodDict removeKey: selector. "Now flush Squeak's method cache, either by selector or by method" oldMethod flushCache. selector flushCache.! ! !Behavior methodsFor: 'private' stamp: 'sd 3/28/2003 15:06'! becomeCompact "Here are the restrictions on compact classes in order for export segments to work: A compact class index may not be reused. If a class was compact in a release of Squeak, no other class may use that index. The class might not be compact later, and there should be nil in its place in the array." | cct index | self isWeak ifTrue:[^ self halt: 'You must not make a weak class compact']. cct _ self environment compactClassesArray. (self indexIfCompact > 0 or: [cct includes: self]) ifTrue: [^ self halt: self name , 'is already compact']. index _ cct indexOf: nil ifAbsent: [^ self halt: 'compact class table is full']. "Install this class in the compact class table" cct at: index put: self. "Update instspec so future instances will be compact" format _ format + (index bitShift: 11). "Make up new instances and become old ones into them" self updateInstancesFrom: self. "Purge any old instances" Smalltalk garbageCollect.! ! !Behavior methodsFor: 'private' stamp: 'sd 3/28/2003 15:06'! becomeUncompact | cct index | cct _ self environment compactClassesArray. (index _ self indexIfCompact) = 0 ifTrue: [^ self]. (cct includes: self) ifFalse: [^ self halt "inconsistent state"]. "Update instspec so future instances will not be compact" format _ format - (index bitShift: 11). "Make up new instances and become old ones into them" self updateInstancesFrom: self. "Make sure there are no compact ones left around" Smalltalk garbageCollect. "Remove this class from the compact class table" cct at: index put: nil. ! ! !Behavior methodsFor: 'private'! flushCache "Tell the interpreter to remove the contents of its method lookup cache, if it has one. Essential. See Object documentation whatIsAPrimitive." <primitive: 89> self primitiveFailed! ! !Behavior methodsFor: 'private'! indexIfCompact "If these 5 bits are non-zero, then instances of this class will be compact. It is crucial that there be an entry in Smalltalk compactClassesArray for any class so optimized. See the msgs becomeCompact and becomeUncompact." ^ (format bitShift: -11) bitAnd: 16r1F " Smalltalk compactClassesArray doWithIndex: [:c :i | c == nil ifFalse: [c indexIfCompact = i ifFalse: [self halt]]] "! ! !Behavior methodsFor: 'system startup' stamp: 'ar 11/16/1999 20:15'! shutDown "This message is sent on system shutdown to registered classes" ! ! !Behavior methodsFor: 'system startup' stamp: 'ar 11/16/1999 20:15'! shutDown: quitting "This message is sent on system shutdown to registered classes" ^self shutDown.! ! !Behavior methodsFor: 'system startup' stamp: 'ar 11/16/1999 20:15'! startUp "This message is sent to registered classes when the system is coming up." ! ! !Behavior methodsFor: 'system startup' stamp: 'ar 11/16/1999 20:15'! startUp: resuming "This message is sent to registered classes when the system is coming up." ^self startUp! ! !Behavior methodsFor: 'obsolete subclasses' stamp: 'ar 3/2/2001 00:58'! addObsoleteSubclass: aClass "Weakly remember that aClass was a subclass of the receiver and is now obsolete" | obs | ObsoleteSubclasses finalizeValues. "clean up if need be" obs _ ObsoleteSubclasses at: self ifAbsent:[WeakArray new]. (obs includes: aClass) ifTrue:[^self]. obs _ obs copyWithout: nil. obs _ obs copyWith: aClass. ObsoleteSubclasses at: self put: obs. ! ! !Behavior methodsFor: 'obsolete subclasses' stamp: 'ar 3/2/2001 00:58'! obsoleteSubclasses "Return all the weakly remembered obsolete subclasses of the receiver" | obs | ObsoleteSubclasses finalizeValues. "clean up if need be" obs _ ObsoleteSubclasses at: self ifAbsent:[^#()]. obs _ obs copyWithout: nil. obs isEmpty ifTrue:[ObsoleteSubclasses removeKey: self ifAbsent:[]] ifFalse:[ObsoleteSubclasses at: self put: obs]. ^obs! ! !Behavior methodsFor: 'obsolete subclasses' stamp: 'NS 2/19/2002 11:16'! removeObsoleteSubclass: aClass "Remove aClass from the weakly remembered obsolete subclasses" | obs | ObsoleteSubclasses finalizeValues. "clean up if need be" obs _ ObsoleteSubclasses at: self ifAbsent:[^ self]. (obs includes: aClass) ifFalse:[^self]. obs _ obs copyWithout: aClass. obs _ obs copyWithout: nil. obs isEmpty ifTrue: [ObsoleteSubclasses removeKey: self ifAbsent: []] ifFalse: [ObsoleteSubclasses at: self put: obs].! ! !Behavior methodsFor: 'deprecated' stamp: 'NS 1/28/2004 11:29'! removeSelectorSimply: selector "Assuming that the argument, selector (a Symbol), is a message selector in my method dictionary, remove it and its method." | oldMethod | self deprecated: 'Use basicRemoveSelector: instead.'. oldMethod _ self methodDict at: selector ifAbsent: [^ self]. self methodDict removeKey: selector. "Now flush Squeak's method cache, either by selector or by method" oldMethod flushCache. selector flushCache.! ! !Behavior methodsFor: '*system-support' stamp: 'tpr 12/17/2003 16:04'! allCallsOn "Answer a SortedCollection of all the methods that refer to me by name or as part of an association in a global dict." ^ (self systemNavigation allCallsOn: (self environment associationAt: self theNonMetaClass name)), (self systemNavigation allCallsOn: self theNonMetaClass name) ! ! !Behavior methodsFor: '*system-support' stamp: 'dvf 8/23/2003 12:43'! allCallsOn: aSymbol "Answer a SortedCollection of all the methods that call on aSymbol." ^ self systemNavigation allCallsOn: aSymbol from: self . ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Behavior class instanceVariableNames: ''! !Behavior class methodsFor: 'testing' stamp: 'ar 9/10/1999 17:28'! canZapMethodDictionary "Return false since zapping the method dictionary of Behavior class or its subclasses will cause the system to fail." ^false! ! !Behavior class methodsFor: 'class initialization' stamp: 'ar 3/3/2001 00:30'! flushObsoleteSubclasses "Behavior flushObsoleteSubclasses" ObsoleteSubclasses keys "need a copy" do:[:obs| obs ifNotNil:[obs obsoleteSubclasses]]. "remove themselves" ObsoleteSubclasses finalizeValues.! ! !Behavior class methodsFor: 'class initialization' stamp: 'ar 3/2/2001 00:47'! initialize "Behavior initialize" "Never called for real" ObsoleteSubclasses ifNil:[self initializeObsoleteSubclasses].! ! !Behavior class methodsFor: 'class initialization' stamp: 'ar 3/2/2001 00:48'! initializeObsoleteSubclasses ObsoleteSubclasses _ WeakIdentityKeyDictionary new.! ! Object subclass: #BitBlt instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap' classVariableNames: 'CachedFontColorMaps' poolDictionaries: '' category: 'Graphics-Primitives'! !BitBlt commentStamp: '<historical>' prior: 0! 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. 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: 8: if source is 0 and destination is 0 4: if source is 0 and destination is 1 2: if source is 1 and destination is 0 1: if source is 1 and destination is 1. 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. Forms may be of different depths, see the comment in class Form. In addition to the original 16 combination rules, this BitBlt supports 16 fails (to simulate paint bits) 17 fails (to simulate erase bits) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord. Sum of color components 21 rgbSub: sourceWord with: destinationWord. Difference of color components 22 OLDrgbDiff: sourceWord with: destinationWord. Sum of abs of differences in components 23 OLDtallyIntoMap: destinationWord. Tallies pixValues into a colorMap these old versions don't do bitwise dest clipping. Use 32 and 33 now. 24 alphaBlend: sourceWord with: destinationWord. 32-bit source and dest only 25 pixPaint: sourceWord with: destinationWord. Wherever the sourceForm is non-zero, it replaces the destination. Can be used with a 1-bit source color mapped to (0, FFFFFFFF), and a fillColor to fill the dest with that color wherever the source is 1. 26 pixMask: sourceWord with: destinationWord. Like pixPaint, but fills with 0. 27 rgbMax: sourceWord with: destinationWord. Max of each color component. 28 rgbMin: sourceWord with: destinationWord. Min of each color component. 29 rgbMin: sourceWord bitInvert32 with: destinationWord. Min with (max-source) 30 alphaBlendConst: sourceWord with: destinationWord. alpha is an arg. works in 16 bits. 31 alphaPaintConst: sourceWord with: destinationWord. alpha is an arg. works in 16 bits. 32 rgbDiff: sourceWord with: destinationWord. Sum of abs of differences in components 33 tallyIntoMap: destinationWord. Tallies pixValues into a colorMap 34 alphaBlendScaled: srcWord with: dstWord. Alpha blend of scaled srcWord and destWord. 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. 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. To make a small Form repeat and fill a big form, use an InfiniteForm as the source. To write on a form and leave with both transparent and opapue areas, use a MaskedForm as the source. 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 either word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source, or a fully specified ColorMap which may contain a lookup table (ie Bitmap) and/or four separate masks and shifts which are applied to the pixels. For every source pixel, BitBlt will first perform masking and shifting and then index the lookup table, and select the corresponding pixelValue and mask it to the destination pixel size before storing. 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. Two other sized of colorMaps are allowed, 4096 (4 bits per color) and 32786 (five bits per color). Normal blits between 16 and 32 bit forms truncates or pads the colors automatically to provide the best preservation of colors. 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.)! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/17/2000 18:58'! clipHeight ^clipHeight! ! !BitBlt methodsFor: 'accessing'! clipHeight: anInteger "Set the receiver's clipping area height to be the argument, anInteger." clipHeight _ anInteger! ! !BitBlt methodsFor: 'accessing'! clipRect "Answer the receiver's clipping area rectangle." ^clipX @ clipY extent: clipWidth @ clipHeight! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 10/4/2000 16:37'! clipRect: aRectangle "Set the receiver's clipping area rectangle to be the argument, aRectangle." clipX _ aRectangle left truncated. clipY _ aRectangle top truncated. clipWidth _ aRectangle right truncated - clipX. clipHeight _ aRectangle bottom truncated - clipY.! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/17/2000 18:58'! clipWidth ^clipWidth! ! !BitBlt methodsFor: 'accessing'! clipWidth: anInteger "Set the receiver's clipping area width to be the argument, anInteger." clipWidth _ anInteger! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/17/2000 18:58'! clipX ^clipX! ! !BitBlt methodsFor: 'accessing'! clipX: anInteger "Set the receiver's clipping area top left x coordinate to be the argument, anInteger." clipX _ anInteger! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/17/2000 18:58'! clipY ^clipY! ! !BitBlt methodsFor: 'accessing'! clipY: anInteger "Set the receiver's clipping area top left y coordinate to be the argument, anInteger." clipY _ anInteger! ! !BitBlt methodsFor: 'accessing' stamp: 'tk 8/15/2001 10:56'! color "Return the current fill color as a Color. Gives the wrong answer if the halftoneForm is a complex pattern of more than one word." halftoneForm ifNil: [^ Color black]. ^ Color colorFromPixelValue: halftoneForm first depth: destForm depth! ! !BitBlt methodsFor: 'accessing'! colorMap ^ colorMap! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/4/2001 15:45'! colorMap: map "See last part of BitBlt comment. 6/18/96 tk" colorMap _ map.! ! !BitBlt methodsFor: 'accessing'! combinationRule: anInteger "Set the receiver's combination rule to be the argument, anInteger, a number in the range 0-15." combinationRule _ anInteger! ! !BitBlt methodsFor: 'accessing'! destForm ^ destForm! ! !BitBlt methodsFor: 'accessing'! destOrigin: aPoint "Set the receiver's destination top left coordinates to be those of the argument, aPoint." destX _ aPoint x. destY _ aPoint y! ! !BitBlt methodsFor: 'accessing'! destRect: aRectangle "Set the receiver's destination form top left coordinates to be the origin of the argument, aRectangle, and set the width and height of the receiver's destination form to be the width and height of aRectangle." destX _ aRectangle left. destY _ aRectangle top. width _ aRectangle width. height _ aRectangle height! ! !BitBlt methodsFor: 'accessing'! destX: anInteger "Set the top left x coordinate of the receiver's destination form to be the argument, anInteger." destX _ anInteger! ! !BitBlt methodsFor: 'accessing'! destX: x destY: y width: w height: h "Combined init message saves 3 sends from DisplayScanner" destX _ x. destY _ y. width _ w. height _ h.! ! !BitBlt methodsFor: 'accessing'! destY: anInteger "Set the top left y coordinate of the receiver's destination form to be the argument, anInteger." destY _ anInteger! ! !BitBlt methodsFor: 'accessing'! fillColor ^ halftoneForm! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/14/2001 23:25'! fillColor: aColorOrPattern "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" aColorOrPattern == nil ifTrue: [halftoneForm _ nil. ^ self]. destForm == nil ifTrue: [self error: 'Must set destForm first']. halftoneForm _ destForm bitPatternFor: aColorOrPattern ! ! !BitBlt methodsFor: 'accessing'! height: anInteger "Set the receiver's destination form height to be the argument, anInteger." height _ anInteger! ! !BitBlt methodsFor: 'accessing'! sourceForm: aForm "Set the receiver's source form to be the argument, aForm." sourceForm _ aForm! ! !BitBlt methodsFor: 'accessing'! sourceOrigin: aPoint "Set the receiver's source form coordinates to be those of the argument, aPoint." sourceX _ aPoint x. sourceY _ aPoint y! ! !BitBlt methodsFor: 'accessing'! sourceRect: aRectangle "Set the receiver's source form top left x and y, width and height to be the top left coordinate and extent of the argument, aRectangle." sourceX _ aRectangle left. sourceY _ aRectangle top. width _ aRectangle width. height _ aRectangle height! ! !BitBlt methodsFor: 'accessing'! sourceX: anInteger "Set the receiver's source form top left x to be the argument, anInteger." sourceX _ anInteger! ! !BitBlt methodsFor: 'accessing'! sourceY: anInteger "Set the receiver's source form top left y to be the argument, anInteger." sourceY _ anInteger! ! !BitBlt methodsFor: 'accessing' stamp: 'ar 5/25/2000 19:39'! tallyMap: aBitmap "Install the map used for tallying pixels" colorMap _ aBitmap! ! !BitBlt methodsFor: 'accessing'! width: anInteger "Set the receiver's destination form width to be the argument, anInteger." width _ anInteger! ! !BitBlt methodsFor: 'copying'! copy: destRectangle from: sourcePt in: srcForm | destOrigin | sourceForm _ srcForm. halftoneForm _ nil. combinationRule _ 3. "store" destOrigin _ destRectangle origin. destX _ destOrigin x. destY _ destOrigin y. sourceX _ sourcePt x. sourceY _ sourcePt y. width _ destRectangle width. height _ destRectangle height. self copyBits! ! !BitBlt methodsFor: 'copying' stamp: 'ar 5/14/2001 23:32'! copy: destRectangle from: sourcePt in: srcForm fillColor: hf rule: rule "Specify a Color to fill, not a Form. 6/18/96 tk" | destOrigin | sourceForm _ srcForm. self fillColor: hf. "sets halftoneForm" combinationRule _ rule. destOrigin _ destRectangle origin. destX _ destOrigin x. destY _ destOrigin y. sourceX _ sourcePt x. sourceY _ sourcePt y. width _ destRectangle width. height _ destRectangle height. srcForm == nil ifFalse: [colorMap _ srcForm colormapIfNeededFor: destForm]. ^ self copyBits! ! !BitBlt methodsFor: 'copying' stamp: 'nk 4/17/2004 19:41'! copyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " <primitive: 'primitiveCopyBits' module: 'BitBltPlugin'> "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'nk 4/17/2004 19:42'! copyBitsTranslucent: factor "This entry point to BitBlt supplies an extra argument to specify translucency for operations 30 and 31. The argument must be an integer between 0 and 255." <primitive: 'primitiveCopyBits' module: 'BitBltPlugin'> "Check for compressed source, destination or halftone forms" ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBitsTranslucent: factor]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBitsTranslucent: factor]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBitsTranslucent: factor]. self primitiveFailed "Later do nicer error recovery -- share copyBits recovery"! ! !BitBlt methodsFor: 'copying' stamp: 'ar 5/14/2001 23:32'! copyForm: srcForm to: destPt rule: rule ^ self copyForm: srcForm to: destPt rule: rule colorMap: (srcForm colormapIfNeededFor: destForm)! ! !BitBlt methodsFor: 'copying' stamp: 'di 7/17/97 10:04'! copyForm: srcForm to: destPt rule: rule colorMap: map sourceForm _ srcForm. halftoneForm _ nil. combinationRule _ rule. destX _ destPt x + sourceForm offset x. destY _ destPt y + sourceForm offset y. sourceX _ 0. sourceY _ 0. width _ sourceForm width. height _ sourceForm height. colorMap _ map. self copyBits! ! !BitBlt methodsFor: 'copying'! copyForm: srcForm to: destPt rule: rule fillColor: color sourceForm _ srcForm. self fillColor: color. "sets halftoneForm" combinationRule _ rule. destX _ destPt x + sourceForm offset x. destY _ destPt y + sourceForm offset y. sourceX _ 0. sourceY _ 0. width _ sourceForm width. height _ sourceForm height. self copyBits! ! !BitBlt methodsFor: 'copying' stamp: 'ar 5/14/2001 23:32'! copyFrom: sourceRectangle in: srcForm to: destPt | sourceOrigin | sourceForm _ srcForm. halftoneForm _ nil. combinationRule _ 3. "store" destX _ destPt x. destY _ destPt y. sourceOrigin _ sourceRectangle origin. sourceX _ sourceOrigin x. sourceY _ sourceOrigin y. width _ sourceRectangle width. height _ sourceRectangle height. colorMap _ srcForm colormapIfNeededFor: destForm. self copyBits! ! !BitBlt methodsFor: 'copying' stamp: 'RAA 9/27/2000 16:48'! displayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta destY _ aPoint y. destX _ aPoint x. "the following are not really needed, but theBitBlt primitive will fail if not set" sourceX ifNil: [sourceX _ 100]. width ifNil: [width _ 100]. ^self primDisplayString: aString from: startIndex to: stopIndex map: font characterToGlyphMap xTable: font xTable kern: kernDelta.! ! !BitBlt methodsFor: 'copying'! fill: destRect fillColor: grayForm rule: rule "Fill with a Color, not a Form. 6/18/96 tk" sourceForm _ nil. self fillColor: grayForm. "sets halftoneForm" combinationRule _ rule. destX _ destRect left. destY _ destRect top. sourceX _ 0. sourceY _ 0. width _ destRect width. height _ destRect height. self copyBits! ! !BitBlt methodsFor: 'copying' stamp: 'ar 3/1/2004 13:49'! pixelAt: aPoint "Assumes this BitBlt has been set up specially (see the init message, BitBlt bitPeekerFromForm:. Returns the pixel at aPoint." sourceX _ aPoint x. sourceY _ aPoint y. destForm unhibernate. "before poking" destForm bits at: 1 put: 0. "Just to be sure" self copyBits. ^ destForm bits at: 1! ! !BitBlt methodsFor: 'copying' stamp: 'ar 3/1/2004 13:49'! pixelAt: aPoint put: pixelValue "Assumes this BitBlt has been set up specially (see the init message, BitBlt bitPokerToForm:. Overwrites the pixel at aPoint." destX _ aPoint x. destY _ aPoint y. sourceForm unhibernate. "before poking" sourceForm bits at: 1 put: pixelValue. self copyBits " | bb | bb _ (BitBlt bitPokerToForm: Display). [Sensor anyButtonPressed] whileFalse: [bb pixelAt: Sensor cursorPoint put: 55] "! ! !BitBlt methodsFor: 'line drawing'! drawFrom: startPoint to: stopPoint ^ self drawFrom: startPoint to: stopPoint withFirstPoint: true! ! !BitBlt methodsFor: 'line drawing' stamp: '6/8/97 15:41 di'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards _ (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 _ startPoint. point2 _ stopPoint] ifFalse: [point1 _ stopPoint. point2 _ startPoint]. sourceForm == nil ifTrue: [destX _ point1 x. destY _ point1 y] ifFalse: [width _ sourceForm width. height _ sourceForm height. offset _ sourceForm offset. destX _ (point1 x + offset x) rounded. destY _ (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'ar 2/2/2001 15:09'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | <primitive: 'primitiveDrawLoop' module: 'BitBltPlugin'> dx _ xDelta sign. dy _ yDelta sign. px _ yDelta abs. py _ xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P _ py // 2. 1 to: py do: [:i | destX _ destX + dx. (P _ P - px) < 0 ifTrue: [destY _ destY + dy. P _ P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P _ px // 2. 1 to: px do: [:i | destY _ destY + dy. (P _ P - py) < 0 ifTrue: [destX _ destX + dx. P _ P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'private' stamp: 'hg 6/27/2000 12:27'! cachedFontColormapFrom: sourceDepth to: destDepth | srcIndex map | CachedFontColorMaps class == Array ifFalse: [CachedFontColorMaps _ (1 to: 9) collect: [:i | Array new: 32]]. srcIndex _ sourceDepth. sourceDepth > 8 ifTrue: [srcIndex _ 9]. (map _ (CachedFontColorMaps at: srcIndex) at: destDepth) ~~ nil ifTrue: [^ map]. map _ (Color cachedColormapFrom: sourceDepth to: destDepth) copy. (CachedFontColorMaps at: srcIndex) at: destDepth put: map. ^ map ! ! !BitBlt methodsFor: 'private' stamp: 'ar 3/8/2003 00:34'! clipRange "clip and adjust source origin and extent appropriately" "first in x" | sx sy dx dy bbW bbH | "fill in the lazy state if needed" destX ifNil:[destX := 0]. destY ifNil:[destY := 0]. width ifNil:[width := destForm width]. height ifNil:[height := destForm height]. sourceX ifNil:[sourceX := 0]. sourceY ifNil:[sourceY := 0]. clipX ifNil:[clipX := 0]. clipY ifNil:[clipY := 0]. clipWidth ifNil:[clipWidth := destForm width]. clipHeight ifNil:[clipHeight := destForm height]. destX >= clipX ifTrue: [sx _ sourceX. dx _ destX. bbW _ width] ifFalse: [sx _ sourceX + (clipX - destX). bbW _ width - (clipX - destX). dx _ clipX]. (dx + bbW) > (clipX + clipWidth) ifTrue: [bbW _ bbW - ((dx + bbW) - (clipX + clipWidth))]. "then in y" destY >= clipY ifTrue: [sy _ sourceY. dy _ destY. bbH _ height] ifFalse: [sy _ sourceY + clipY - destY. bbH _ height - (clipY - destY). dy _ clipY]. (dy + bbH) > (clipY + clipHeight) ifTrue: [bbH _ bbH - ((dy + bbH) - (clipY + clipHeight))]. sourceForm ifNotNil:[ sx < 0 ifTrue: [dx _ dx - sx. bbW _ bbW + sx. sx _ 0]. sx + bbW > sourceForm width ifTrue: [bbW _ bbW - (sx + bbW - sourceForm width)]. sy < 0 ifTrue: [dy _ dy - sy. bbH _ bbH + sy. sy _ 0]. sy + bbH > sourceForm height ifTrue: [bbH _ bbH - (sy + bbH - sourceForm height)]. ]. (bbW <= 0 or:[bbH <= 0]) ifTrue:[ sourceX := sourceY := destX := destY := clipX := clipY := width := height := 0. ^true]. (sx = sourceX and:[sy = sourceY and:[dx = destX and:[dy = destY and:[bbW = width and:[bbH = height]]]]]) ifTrue:[^false]. sourceX := sx. sourceY := sy. destX := dx. destY := dy. width := bbW. height := bbH. ^true! ! !BitBlt methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! copyBitsAgain "Primitive. See BitBlt|copyBits, also a Primitive. Essential. See Object documentation whatIsAPrimitive." <primitive: 'primitiveCopyBits' module: 'BitBltPlugin'> self primitiveFailed! ! !BitBlt methodsFor: 'private'! eraseBits "Perform the erase operation, which puts 0's in the destination wherever the source (which is assumed to be just 1 bit deep) has a 1. This requires the colorMap to be set in order to AND all 1's into the destFrom pixels regardless of their size." | oldMask oldMap | oldMask _ halftoneForm. halftoneForm _ nil. oldMap _ colorMap. self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF). combinationRule _ Form erase. self copyBits. "Erase the dest wherever the source is 1" halftoneForm _ oldMask. "already converted to a Bitmap" colorMap _ oldMap! ! !BitBlt methodsFor: 'private' stamp: 'ar 5/14/2001 23:43'! installStrikeFont: aStrikeFont foregroundColor: foregroundColor backgroundColor: backgroundColor | lastSourceDepth | sourceForm ifNotNil:[lastSourceDepth _ sourceForm depth]. sourceForm _ aStrikeFont glyphs. (colorMap notNil and:[lastSourceDepth = sourceForm depth]) ifFalse: ["Set up color map for a different source depth (color font)" "Uses caching for reasonable efficiency" colorMap _ self cachedFontColormapFrom: sourceForm depth to: destForm depth. colorMap at: 1 put: (destForm pixelValueFor: backgroundColor)]. sourceForm depth = 1 ifTrue: [colorMap at: 2 put: (destForm pixelValueFor: foregroundColor). "Ignore any halftone pattern since we use a color map approach here" halftoneForm _ nil]. sourceY _ 0. height _ aStrikeFont height. ! ! !BitBlt methodsFor: 'private'! paintBits "Perform the paint operation, which requires two calls to BitBlt." | color oldMap saveRule | sourceForm depth = 1 ifFalse: [^ self halt: 'paint operation is only defined for 1-bit deep sourceForms']. saveRule _ combinationRule. color _ halftoneForm. halftoneForm _ nil. oldMap _ colorMap. "Map 1's to ALL ones, not just one" self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF). combinationRule _ Form erase. self copyBits. "Erase the dest wherever the source is 1" halftoneForm _ color. combinationRule _ Form under. self copyBits. "then OR, with whatever color, into the hole" colorMap _ oldMap. combinationRule _ saveRule " | dot | dot _ Form dotOfSize: 32. ((BitBlt destForm: Display sourceForm: dot fillColor: Color lightGray combinationRule: Form paint destOrigin: Sensor cursorPoint sourceOrigin: 0@0 extent: dot extent clipRect: Display boundingBox) colorMap: (Bitmap with: 0 with: 16rFFFFFFFF)) copyBits"! ! !BitBlt methodsFor: 'private' stamp: 'ar 5/18/2000 21:49'! primDisplayString: aString from: startIndex to: stopIndex map: glyphMap xTable: xTable kern: kernDelta | ascii glyph | <primitive:'primitiveDisplayString' module:'BitBltPlugin'> startIndex to: stopIndex do:[:charIndex| ascii _ (aString at: charIndex) asciiValue. glyph _ glyphMap at: ascii + 1. sourceX _ xTable at: glyph + 1. width _ (xTable at: glyph + 2) - sourceX. self copyBits. destX _ destX + width + kernDelta. ].! ! !BitBlt methodsFor: 'private'! setDestForm: df | bb | bb _ df boundingBox. destForm _ df. clipX _ bb left. clipY _ bb top. clipWidth _ bb width. clipHeight _ bb height! ! !BitBlt methodsFor: 'private' stamp: 'ar 5/14/2001 23:32'! setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect | aPoint | destForm _ df. sourceForm _ sf. self fillColor: hf. "sets halftoneForm" combinationRule _ cr. destX _ destOrigin x. destY _ destOrigin y. sourceX _ sourceOrigin x. sourceY _ sourceOrigin y. width _ extent x. height _ extent y. aPoint _ clipRect origin. clipX _ aPoint x. clipY _ aPoint y. aPoint _ clipRect corner. clipWidth _ aPoint x - clipX. clipHeight _ aPoint y - clipY. sourceForm == nil ifFalse: [colorMap _ sourceForm colormapIfNeededFor: destForm]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BitBlt class instanceVariableNames: ''! !BitBlt class methodsFor: 'instance creation' stamp: 'di 3/2/98 12:53'! bitPeekerFromForm: sourceForm "Answer an instance to be used extract individual pixels from the given Form. The destination for a 1x1 copyBits will be the low order bits of (bits at: 1)." | pixPerWord | pixPerWord _ 32 // sourceForm depth. sourceForm unhibernate. ^ self destForm: (Form extent: pixPerWord@1 depth: sourceForm depth) sourceForm: sourceForm halftoneForm: nil combinationRule: Form over destOrigin: (pixPerWord - 1)@0 sourceOrigin: 0@0 extent: 1@1 clipRect: (0@0 extent: pixPerWord@1) ! ! !BitBlt class methodsFor: 'instance creation' stamp: 'di 3/2/98 12:53'! bitPokerToForm: destForm "Answer an instance to be used for valueAt: aPoint put: pixValue. The source for a 1x1 copyBits will be the low order of (bits at: 1)" | pixPerWord | pixPerWord _ 32//destForm depth. destForm unhibernate. ^ self destForm: destForm sourceForm: (Form extent: pixPerWord@1 depth: destForm depth) halftoneForm: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: (pixPerWord-1)@0 extent: 1@1 clipRect: (0@0 extent: destForm extent) ! ! !BitBlt class methodsFor: 'instance creation' stamp: 'ar 5/28/2000 12:00'! current "Return the class currently to be used for BitBlt" ^Display defaultBitBltClass! ! !BitBlt class methodsFor: 'instance creation'! destForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect "Answer an instance of me with values set according to the arguments." ^ self new setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect! ! !BitBlt class methodsFor: 'instance creation'! destForm: df sourceForm: sf halftoneForm: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect "Answer an instance of me with values set according to the arguments." ^ self new setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect! ! !BitBlt class methodsFor: 'instance creation'! toForm: aForm ^ self new setDestForm: aForm! ! !BitBlt class methodsFor: 'examples' stamp: 'dew 9/18/2001 02:30'! exampleOne "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). This only works at Display depth of 1. (Rule 15 does not work?)" | path displayDepth | displayDepth _ Display depth. Display newDepth: 1. path _ Path new. 0 to: 3 do: [:i | 0 to: 3 do: [:j | path add: j * 100 @ (i * 75)]]. Display fillWhite. path _ path translateBy: 60 @ 40. 1 to: 16 do: [:index | BitBlt exampleAt: (path at: index) rule: index - 1 fillColor: nil]. [Sensor anyButtonPressed] whileFalse: []. Display newDepth: displayDepth. "BitBlt exampleOne"! ! !BitBlt class methodsFor: 'examples' stamp: 'jrm 2/21/2001 23:43'! exampleTwo "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. This only works at Depth of 1." | f aBitBlt displayDepth | "create a small black Form source as a brush. " displayDepth _ Display depth. Display newDepth: 1. f _ Form extent: 20 @ 20. f fillBlack. "create a BitBlt which will OR gray into the display. " aBitBlt _ BitBlt destForm: Display sourceForm: f fillColor: Color gray combinationRule: Form over destOrigin: Sensor cursorPoint sourceOrigin: 0 @ 0 extent: f extent clipRect: Display computeBoundingBox. "paint the gray Form on the screen for a while. " [Sensor anyButtonPressed] whileFalse: [aBitBlt destOrigin: Sensor cursorPoint. aBitBlt copyBits]. Display newDepth: displayDepth. "BitBlt exampleTwo"! ! !BitBlt class methodsFor: 'private' stamp: 'jrm 2/21/2001 23:45'! exampleAt: originPoint rule: rule fillColor: mask "This builds a source and destination form and copies the source to the destination using the specifed rule and mask. It is called from the method named exampleOne. Only works with Display depth of 1" | s d border aBitBlt | border_Form extent: 32@32. border fillBlack. border fill: (1@1 extent: 30@30) fillColor: Color white. s _ Form extent: 32@32. s fillWhite. s fillBlack: (7@7 corner: 25@25). d _ Form extent: 32@32. d fillWhite. d fillBlack: (0@0 corner: 32@16). s displayOn: Display at: originPoint. border displayOn: Display at: originPoint rule: Form under. d displayOn: Display at: originPoint + (s width @0). border displayOn: Display at: originPoint + (s width @0) rule: Form under. d displayOn: Display at: originPoint + (s extent // (2 @ 1)). aBitBlt _ BitBlt destForm: Display sourceForm: s fillColor: mask combinationRule: rule destOrigin: originPoint + (s extent // (2 @ 1)) sourceOrigin: 0 @ 0 extent: s extent clipRect: Display computeBoundingBox. aBitBlt copyBits. border displayOn: Display at: originPoint + (s extent // (2 @ 1)) rule: Form under. "BitBlt exampleAt: 100@100 rule: 0 fillColor: nil" ! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 5/14/2001 23:31'! benchmark "BitBlt benchmark" "Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else. Attention: *this*may*take*a*while*" | bb source dest destRect log t | log _ WriteStream on: String new. destRect _ 0@0 extent: 600@600. "Form paint/Form over - the most common rules" #( 25 3 ) do:[:rule| Transcript cr; show:'---- Combination rule: ', rule printString,' ----'. log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'. #(1 2 4 8 16 32) do:[:destDepth| dest _ nil. dest _ Form extent: destRect extent depth: destDepth. Transcript cr. log cr. #(1 2 4 8 16 32) do:[:sourceDepth| Transcript cr; show: sourceDepth printString, ' => ', destDepth printString. log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString. source _ nil. bb _ nil. source _ Form extent: destRect extent depth: sourceDepth. (source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black. bb _ WarpBlt toForm: dest. bb sourceForm: source. bb sourceRect: source boundingBox. bb destRect: dest boundingBox. bb colorMap: (source colormapIfNeededFor: dest). bb combinationRule: rule. "Measure speed of copyBits" t _ Time millisecondsToRun:[bb copyBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. bb sourceForm: source destRect: source boundingBox. "Measure speed of 1x1 warpBits" bb cellSize: 1. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 2x2 warpBits" bb cellSize: 2. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 3x3 warpBits" bb cellSize: 3. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. ]. ]. ]. ^log contents! ! ArrayedCollection variableWordSubclass: #Bitmap instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Bitmap commentStamp: '<historical>' prior: 0! 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.! !Bitmap methodsFor: 'filing' stamp: 'ar 2/3/2001 16:11'! compress: bm toByteArray: ba "Store a run-coded compression of the receiver into the byteArray ba, and return the last index stored into. ba is assumed to be large enough. The encoding is as follows... S {N D}*. S is the size of the original bitmap, followed by run-coded pairs. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes" | size k word j lowByte eqBytes i | <primitive: 'primitiveCompressToByteArray' module: 'MiscPrimitivePlugin'> self var: #bm declareC: 'int *bm'. self var: #ba declareC: 'unsigned char *ba'. size _ bm size. i _ self encodeInt: size in: ba at: 1. k _ 1. [k <= size] whileTrue: [word _ bm at: k. lowByte _ word bitAnd: 16rFF. eqBytes _ ((word >> 8) bitAnd: 16rFF) = lowByte and: [((word >> 16) bitAnd: 16rFF) = lowByte and: [((word >> 24) bitAnd: 16rFF) = lowByte]]. j _ k. [j < size and: [word = (bm at: j+1)]] "scan for = words..." whileTrue: [j _ j+1]. j > k ifTrue: ["We have two or more = words, ending at j" eqBytes ifTrue: ["Actually words of = bytes" i _ self encodeInt: j-k+1*4+1 in: ba at: i. ba at: i put: lowByte. i _ i+1] ifFalse: [i _ self encodeInt: j-k+1*4+2 in: ba at: i. i _ self encodeBytesOf: word in: ba at: i]. k _ j+1] ifFalse: ["Check for word of 4 = bytes" eqBytes ifTrue: ["Note 1 word of 4 = bytes" i _ self encodeInt: 1*4+1 in: ba at: i. ba at: i put: lowByte. i _ i+1. k _ k + 1] ifFalse: ["Finally, check for junk" [j < size and: [(bm at: j) ~= (bm at: j+1)]] "scan for ~= words..." whileTrue: [j _ j+1]. j = size ifTrue: [j _ j + 1]. "We have one or more unmatching words, ending at j-1" i _ self encodeInt: j-k*4+3 in: ba at: i. k to: j-1 do: [:m | i _ self encodeBytesOf: (bm at: m) in: ba at: i]. k _ j]]]. ^ i - 1 "number of bytes actually stored" " Space check: | n rawBytes myBytes b | n _ rawBytes _ myBytes _ 0. Form allInstancesDo: [:f | f unhibernate. b _ f bits. n _ n + 1. rawBytes _ rawBytes + (b size*4). myBytes _ myBytes + (b compressToByteArray size). f hibernate]. Array with: n with: rawBytes with: myBytes ColorForms: (116 230324 160318 ) Forms: (113 1887808 1325055 ) Integerity check: Form allInstances do: [:f | f unhibernate. f bits = (Bitmap decompressFromByteArray: f bits compressToByteArray) ifFalse: [self halt]. f hibernate] Speed test: MessageTally spyOn: [Form allInstances do: [:f | Bitmap decompressFromByteArray: f bits compressToByteArray]] "! ! !Bitmap methodsFor: 'filing' stamp: 'di 8/5/1998 11:31'! compressToByteArray "Return a run-coded compression of this bitmap into a byteArray" | byteArray lastByte | "Without skip codes, it is unlikely that the compressed bitmap will be any larger than was the original. The run-code cases are... N >= 1 words of equal bytes: 4N bytes -> 2 bytes (at worst 4 -> 2) N > 1 equal words: 4N bytes -> 5 bytes (at worst 8 -> 5) N > 1 unequal words: 4N bytes -> 4N + M, where M is the number of bytes required to encode the run length. The worst that can happen is that the method begins with unequal words, and than has interspersed occurrences of a word with equal bytes. Thus we require a run-length at the beginning, and after every interspersed word of equal bytes. However, each of these saves 2 bytes, so it must be followed by a run of 1984 (7936//4) or more (for which M jumps from 2 to 5) to add any extra overhead. Therefore the worst case is a series of runs of 1984 or more, with single interspersed words of equal bytes. At each break we save 2 bytes, but add 5. Thus the overhead would be no more than 5 (encoded size) + 2 (first run len) + (S//1984*3)." "NOTE: This code is copied in Form hibernate for reasons given there." byteArray _ ByteArray new: (self size*4) + 7 + (self size//1984*3). lastByte _ self compress: self toByteArray: byteArray. ^ byteArray copyFrom: 1 to: lastByte! ! !Bitmap methodsFor: 'filing' stamp: 'ar 2/3/2001 16:11'! decompress: bm fromByteArray: ba at: index "Decompress the body of a byteArray encoded by compressToByteArray (qv)... The format is simply a sequence of run-coded pairs, {N D}*. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent (could be used to skip from one raster line to the next) 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows (see decodeIntFrom:)... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes" "NOTE: If fed with garbage, this routine could read past the end of ba, but it should fail before writing past the ned of bm." | i code n anInt data end k pastEnd | <primitive: 'primitiveDecompressFromByteArray' module: 'MiscPrimitivePlugin'> self var: #bm declareC: 'int *bm'. self var: #ba declareC: 'unsigned char *ba'. i _ index. "byteArray read index" end _ ba size. k _ 1. "bitmap write index" pastEnd _ bm size + 1. [i <= end] whileTrue: ["Decode next run start N" anInt _ ba at: i. i _ i+1. anInt <= 223 ifFalse: [anInt <= 254 ifTrue: [anInt _ (anInt-224)*256 + (ba at: i). i _ i+1] ifFalse: [anInt _ 0. 1 to: 4 do: [:j | anInt _ (anInt bitShift: 8) + (ba at: i). i _ i+1]]]. n _ anInt >> 2. (k + n) > pastEnd ifTrue: [^ self primitiveFail]. code _ anInt bitAnd: 3. code = 0 ifTrue: ["skip"]. code = 1 ifTrue: ["n consecutive words of 4 bytes = the following byte" data _ ba at: i. i _ i+1. data _ data bitOr: (data bitShift: 8). data _ data bitOr: (data bitShift: 16). 1 to: n do: [:j | bm at: k put: data. k _ k+1]]. code = 2 ifTrue: ["n consecutive words = 4 following bytes" data _ 0. 1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i). i _ i+1]. 1 to: n do: [:j | bm at: k put: data. k _ k+1]]. code = 3 ifTrue: ["n consecutive words from the data..." 1 to: n do: [:m | data _ 0. 1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i). i _ i+1]. bm at: k put: data. k _ k+1]]]! ! !Bitmap methodsFor: 'filing' stamp: 'jm 2/15/98 17:27'! encodeBytesOf: anInt in: ba at: i "Copy the integer anInt into byteArray ba at index i, and return the next index" self inline: true. self var: #ba declareC: 'unsigned char *ba'. 0 to: 3 do: [:j | ba at: i+j put: (anInt >> (3-j*8) bitAnd: 16rFF)]. ^ i+4! ! !Bitmap methodsFor: 'filing' stamp: 'jm 2/12/98 17:32'! encodeInt: int "Encode the integer int as per encodeInt:in:at:, and return it as a ByteArray" | byteArray next | byteArray _ ByteArray new: 5. next _ self encodeInt: int in: byteArray at: 1. ^ byteArray copyFrom: 1 to: next - 1 ! ! !Bitmap methodsFor: 'filing' stamp: 'jm 2/15/98 17:26'! encodeInt: anInt in: ba at: i "Encode the integer anInt in byteArray ba at index i, and return the next index. The encoding is as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes" self inline: true. self var: #ba declareC: 'unsigned char *ba'. anInt <= 223 ifTrue: [ba at: i put: anInt. ^ i+1]. anInt <= 7935 ifTrue: [ba at: i put: anInt//256+224. ba at: i+1 put: anInt\\256. ^ i+2]. ba at: i put: 255. ^ self encodeBytesOf: anInt in: ba at: i+1! ! !Bitmap methodsFor: 'filing' stamp: 'di 2/11/98 21:34'! readCompressedFrom: strm "Decompress an old-style run-coded stream into this bitmap: [0 means end of runs] [n = 1..127] [(n+3) copies of next byte] [n = 128..191] [(n-127) next bytes as is] [n = 192..255] [(n-190) copies of next 4 bytes]" | n byte out outBuff bytes | out _ WriteStream on: (outBuff _ ByteArray new: self size*4). [(n _ strm next) > 0] whileTrue: [(n between: 1 and: 127) ifTrue: [byte _ strm next. 1 to: n+3 do: [:i | out nextPut: byte]]. (n between: 128 and: 191) ifTrue: [1 to: n-127 do: [:i | out nextPut: strm next]]. (n between: 192 and: 255) ifTrue: [bytes _ (1 to: 4) collect: [:i | strm next]. 1 to: n-190 do: [:i | bytes do: [:b | out nextPut: b]]]]. out position = outBuff size ifFalse: [self error: 'Decompression size error']. "Copy the final byteArray into self" self copyFromByteArray: outBuff.! ! !Bitmap methodsFor: 'filing' stamp: 'tk 1/24/2000 22:37'! restoreEndianness "This word object was just read in from a stream. Bitmaps are always compressed and serialized in a machine-independent way. Do not correct the Endianness." "^ self" ! ! !Bitmap methodsFor: 'filing' stamp: 'nk 12/31/2003 16:02'! storeBits: startBit to: stopBit on: aStream "Store my bits as a hex string, breaking the lines every 100 bytes or so to comply with the maximum line length limits of Postscript (255 bytes). " | lineWidth | lineWidth := 0. self do: [:word | startBit to: stopBit by: -4 do: [:shift | aStream nextPut: (word >> shift bitAnd: 15) asHexDigit. lineWidth := lineWidth + 1]. (lineWidth > 100) ifTrue: [aStream cr. lineWidth := 0]]. lineWidth > 0 ifTrue: [ aStream cr ].! ! !Bitmap methodsFor: 'filing' stamp: 'jm 2/18/98 14:19'! writeOn: aStream "Store the array of bits onto the argument, aStream. A leading byte of 16r80 identifies this as compressed by compressToByteArray (qv)." | b | aStream nextPut: 16r80. b _ self compressToByteArray. aStream nextPutAll: (self encodeInt: b size); nextPutAll: b. ! ! !Bitmap methodsFor: 'filing' stamp: 'tk 2/19/1999 07:36'! writeUncompressedOn: aStream "Store the array of bits onto the argument, aStream. (leading byte ~= 16r80) identifies this as raw bits (uncompressed)." aStream nextInt32Put: self size. aStream nextPutAll: self ! ! !Bitmap methodsFor: 'printing' stamp: 'sma 6/1/2000 09:42'! printOn: aStream self printNameOn: aStream. aStream nextPutAll: ' of length '; print: self size! ! !Bitmap methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:00'! printOnStream: aStream aStream print: 'a Bitmap of length '; write:self size. ! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 3/3/2001 16:11'! atAllPut: value "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." <primitive: 145> super atAllPut: value.! ! !Bitmap methodsFor: 'accessing'! bitPatternForDepth: depth "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" ^ self! ! !Bitmap methodsFor: 'accessing'! byteAt: byteAddress "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" | lowBits | lowBits _ byteAddress - 1 bitAnd: 3. ^((self at: byteAddress - 1 - lowBits // 4 + 1) bitShift: (lowBits - 3) * 8) bitAnd: 16rFF! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 9/21/2001 23:06'! byteAt: byteAddress put: byte "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" | longWord shift lowBits longAddr | (byte < 0 or:[byte > 255]) ifTrue:[^self errorImproperStore]. lowBits _ byteAddress - 1 bitAnd: 3. longWord _ self at: (longAddr _ (byteAddress - 1 - lowBits) // 4 + 1). shift _ (3 - lowBits) * 8. longWord _ longWord - (longWord bitAnd: (16rFF bitShift: shift)) + (byte bitShift: shift). self at: longAddr put: longWord. ^ byte! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 3/3/2001 16:18'! byteSize ^self size * 4! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 6/16/2002 18:49'! copyFromByteArray: byteArray "This method should work with either byte orderings" | myHack byteHack | myHack := Form new hackBits: self. byteHack := Form new hackBits: byteArray. Smalltalk isLittleEndian ifTrue:[byteHack swapEndianness]. byteHack displayOn: myHack. ! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 11/2/1998 12:19'! defaultElement "Return the default element of the receiver" ^0! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:41'! integerAt: index "Return the integer at the given index" | word | <primitive: 165> word _ self basicAt: index. word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations" ^word >= 16r80000000 "Negative?!!" ifTrue:["word - 16r100000000" (word bitInvert32 + 1) negated] ifFalse:[word]! ! !Bitmap methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:42'! integerAt: index put: anInteger "Store the integer at the given index" | word | <primitive: 166> anInteger < 0 ifTrue:["word _ 16r100000000 + anInteger" word _ (anInteger + 1) negated bitInvert32] ifFalse:[word _ anInteger]. self basicAt: index put: word. ^anInteger! ! !Bitmap methodsFor: 'accessing' stamp: 'tk 3/15/97'! pixelValueForDepth: depth "Self is being used to represent a single color. 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. First pixel only. " ^ (self at: 1) bitAnd: (1 bitShift: depth) - 1! ! !Bitmap methodsFor: 'accessing'! primFill: aPositiveInteger "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." <primitive: 145> self errorImproperStore.! ! !Bitmap methodsFor: 'accessing'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> super replaceFrom: start to: stop with: replacement startingAt: repStart! ! !Bitmap methodsFor: 'testing' stamp: 'ar 5/25/2000 19:42'! isColormap "Bitmaps were used as color maps for BitBlt. This method allows to recognize real color maps." ^false! ! !Bitmap methodsFor: 'as yet unclassified' stamp: 'RAA 7/28/2000 21:51'! copy ^self clone! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Bitmap class instanceVariableNames: ''! !Bitmap class methodsFor: 'instance creation' stamp: 'di 2/9/98 16:02'! decodeIntFrom: s "Decode an integer in stream s as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes " | int | int _ s next. int <= 223 ifTrue: [^ int]. int <= 254 ifTrue: [^ (int-224)*256 + s next]. int _ s next. 1 to: 3 do: [:j | int _ (int bitShift: 8) + s next]. ^ int! ! !Bitmap class methodsFor: 'instance creation' stamp: 'di 2/12/98 14:34'! decompressFromByteArray: byteArray | s bitmap size | s _ ReadStream on: byteArray. size _ self decodeIntFrom: s. bitmap _ self new: size. bitmap decompress: bitmap fromByteArray: byteArray at: s position+1. ^ bitmap! ! !Bitmap class methodsFor: 'instance creation' stamp: 'ar 12/23/1999 14:35'! newFromStream: s | len | s next = 16r80 ifTrue: ["New compressed format" len _ self decodeIntFrom: s. ^ Bitmap decompressFromByteArray: (s nextInto: (ByteArray new: len))]. s skip: -1. len _ s nextInt32. len <= 0 ifTrue: ["Old compressed format" ^ (self new: len negated) readCompressedFrom: s] ifFalse: ["Old raw data format" ^ s nextWordsInto: (self new: len)]! ! !Bitmap class methodsFor: 'utilities' stamp: 'sd 6/28/2003 09:33'! swapBytesIn: aNonPointerThing from: start to: stop "Perform a bigEndian/littleEndian byte reversal of my words. We only intend this for non-pointer arrays. Do nothing if I contain pointers." | hack blt | "The implementation is a hack, but fast for large ranges" hack _ Form new hackBits: aNonPointerThing. blt _ (BitBlt toForm: hack) sourceForm: hack. blt combinationRule: Form reverse. "XOR" blt sourceY: start-1; destY: start-1; height: stop-start+1; width: 1. blt sourceX: 0; destX: 3; copyBits. "Exchange bytes 0 and 3" blt sourceX: 3; destX: 0; copyBits. blt sourceX: 0; destX: 3; copyBits. blt sourceX: 1; destX: 2; copyBits. "Exchange bytes 1 and 2" blt sourceX: 2; destX: 1; copyBits. blt sourceX: 1; destX: 2; copyBits. ! ! Error subclass: #BlockCannotReturn instanceVariableNames: 'result deadHome' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !BlockCannotReturn commentStamp: '<historical>' prior: 0! This class is private to the EHS implementation. Its use allows for ensured execution to survive code such as: [self doThis. ^nil] ensure: [self doThat] Signaling or handling this exception is not recommended.! !BlockCannotReturn methodsFor: 'accessing' stamp: 'ajh 2/6/2002 11:12'! deadHome: context deadHome _ context! ! !BlockCannotReturn methodsFor: 'accessing' stamp: 'tfei 3/30/1999 12:54'! result ^result! ! !BlockCannotReturn methodsFor: 'accessing' stamp: 'tfei 3/30/1999 12:54'! result: r result := r! ! !BlockCannotReturn methodsFor: 'exceptionDescription' stamp: 'tfei 3/30/1999 12:55'! defaultAction self messageText: 'Block cannot return'. ^super defaultAction! ! !BlockCannotReturn methodsFor: 'exceptionDescription' stamp: 'tfei 4/2/1999 15:49'! isResumable ^true! ! ContextPart variableSubclass: #BlockContext instanceVariableNames: 'nargs startpc home' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !BlockContext commentStamp: '<historical>' prior: 0! 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. 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. BlockContexts must only be created using the method newForMethod:. Note that it is impossible to determine the real object size of a BlockContext except by asking for the frameSize of its method. Any fields above the stack pointer (stackp) are truly invisible -- even (and especially!!) to the garbage collector. Any store into stackp other than by the primitive method stackp: is potentially fatal.! !BlockContext methodsFor: 'initialize-release' stamp: 'ls 6/21/2000 17:42'! home: aContextPart startpc: position nargs: anInteger "This is the initialization message. The receiver has been initialized with the correct size only." home _ aContextPart. pc _ startpc _ position. nargs _ anInteger. stackp _ 0.! ! !BlockContext methodsFor: 'initialize-release' stamp: 'ajh 7/18/2003 21:49'! privRefresh "Reinitialize the receiver so that it is in the state it was at its creation." pc _ startpc. self stackp: 0. nargs timesRepeat: [ "skip arg popping" self nextInstruction selector = #popIntoTemporaryVariable: ifFalse: [self halt: 'unexpected bytecode instruction'] ]. ! ! !BlockContext methodsFor: 'accessing' stamp: 'ajh 1/24/2003 12:35'! blockHome ^ self home! ! !BlockContext methodsFor: 'accessing' stamp: 'ajh 1/31/2003 23:29'! finalBlockHome ^ self home! ! !BlockContext methodsFor: 'accessing'! fixTemps "Fix the values of the temporary variables used in the block that are ordinarily shared with the method in which the block is defined." home _ home copy. home swapSender: nil! ! !BlockContext methodsFor: 'accessing'! hasMethodReturn "Answer whether the receiver has a return ('^') in its code." | method scanner end | method _ self method. "Determine end of block from long jump preceding it" end _ (method at: startpc-2)\\16-4*256 + (method at: startpc-1) + startpc - 1. scanner _ InstructionStream new method: method pc: startpc. scanner scanFor: [:byte | (byte between: 120 and: 124) or: [scanner pc > end]]. ^scanner pc <= end! ! !BlockContext methodsFor: 'accessing'! home "Answer the context in which the receiver was defined." ^home! ! !BlockContext methodsFor: 'accessing' stamp: 'ajh 1/21/2003 13:16'! isBlock ^ true! ! !BlockContext methodsFor: 'accessing' stamp: 'ajh 1/31/2003 12:12'! isExecutingBlock ^ true! ! !BlockContext methodsFor: 'accessing'! method "Answer the compiled method in which the receiver was defined." ^home method! ! !BlockContext methodsFor: 'accessing' stamp: 'mdr 4/10/2001 10:34'! numArgs "Answer the number of arguments that must be used to evaluate this block" ^nargs! ! !BlockContext methodsFor: 'accessing'! receiver "Refer to the comment in ContextPart|receiver." ^home receiver! ! !BlockContext methodsFor: 'accessing'! tempAt: index "Refer to the comment in ContextPart|tempAt:." ^home at: index! ! !BlockContext methodsFor: 'accessing'! tempAt: index put: value "Refer to the comment in ContextPart|tempAt:put:." ^home at: index put: value! ! !BlockContext methodsFor: 'evaluating' stamp: 'ajh 1/13/2002 13:36'! ifError: errorHandlerBlock "Evaluate the block represented by the receiver, and normally return it's value. If an error occurs, the errorHandlerBlock is evaluated, and it's value is instead returned. The errorHandlerBlock must accept zero, one, or two parameters (the error message and the receiver)." "Examples: [1 whatsUpDoc] ifError: [:err :rcvr | 'huh?']. [1 / 0] ifError: [:err :rcvr | 'ZeroDivide' = err ifTrue: [Float infinity] ifFalse: [self error: err]] " ^ self on: Error do: [:ex | errorHandlerBlock valueWithPossibleArgs: {ex description. ex receiver}]! ! !BlockContext methodsFor: 'evaluating' stamp: 'jm 6/3/1998 14:25'! timeToRun "Answer the number of milliseconds taken to execute this block." ^ Time millisecondsToRun: self ! ! !BlockContext methodsFor: 'evaluating'! value "Primitive. Evaluate the block represented by the receiver. Fail if the block expects any arguments or if the block is already being executed. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: #()! ! !BlockContext methodsFor: 'evaluating'! value: arg "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than one argument or if the block is already being executed. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: (Array with: arg)! ! !BlockContext methodsFor: 'evaluating'! value: arg1 value: arg2 "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than two arguments or if the block is already being executed. Optional. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: (Array with: arg1 with: arg2)! ! !BlockContext methodsFor: 'evaluating'! value: arg1 value: arg2 value: arg3 "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than three arguments or if the block is already being executed. Optional. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: (Array with: arg1 with: arg2 with: arg3)! ! !BlockContext methodsFor: 'evaluating' stamp: 'di 11/30/97 09:19'! value: arg1 value: arg2 value: arg3 value: arg4 "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than three arguments or if the block is already being executed. Optional. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: (Array with: arg1 with: arg2 with: arg3 with: arg4)! ! !BlockContext methodsFor: 'evaluating' stamp: 'mjr 9/10/2003 22:42'! valueWithArguments: anArray "Primitive. Evaluate the block represented by the receiver. The argument is an Array whose elements are the arguments for the block. Fail if the length of the Array is not the same as the the number of arguments that the block was expecting. Fail if the block is already being executed. Essential. See Object documentation whatIsAPrimitive." <primitive: 82> self numArgs = anArray size ifTrue: [self error: 'Attempt to evaluate a block that is already being evaluated.'] ifFalse: [self error: 'This block accepts ' ,self numArgs printString, ' argument', (self numArgs = 1 ifTrue:[''] ifFalse:['s']) , ', but was called with ', anArray size printString, '.'] ! ! !BlockContext methodsFor: 'controlling' stamp: 'sma 5/12/2000 13:22'! repeat "Evaluate the receiver repeatedly, ending only if the block explicitly returns." [self value. true] whileTrue! ! !BlockContext methodsFor: 'controlling'! whileFalse "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the receiver, as long as its value is false." ^ [self value] whileFalse: []! ! !BlockContext methodsFor: 'controlling'! whileFalse: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is false." ^ [self value] whileFalse: [aBlock value]! ! !BlockContext methodsFor: 'controlling'! whileTrue "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the receiver, as long as its value is true." ^ [self value] whileTrue: []! ! !BlockContext methodsFor: 'controlling'! whileTrue: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true." ^ [self value] whileTrue: [aBlock value]! ! !BlockContext methodsFor: 'scheduling' stamp: 'di 9/12/1998 11:53'! fork "Create and schedule a Process running the code in the receiver." ^ self newProcess resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'jm 11/9/1998 10:16'! forkAt: priority "Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process." | forkedProcess | forkedProcess _ self newProcess. forkedProcess priority: priority. ^ forkedProcess resume ! ! !BlockContext methodsFor: 'scheduling' stamp: 'ar 6/5/1998 21:44'! newProcess "Answer a Process running the code in the receiver. The process is not scheduled." <primitive: 19> "Simulation guard" ^Process forContext: [self value. Processor terminateActive] priority: Processor activePriority! ! !BlockContext methodsFor: 'instruction decoding' stamp: 'ajh 1/24/2003 16:35'! blockReturnTop "Simulate the interpreter's action when a ReturnTopOfStack bytecode is encountered in the receiver." | save dest | save _ home. "Needed because return code will nil it" dest _ self return: self pop from: self. home _ save. sender _ nil. ^ dest! ! !BlockContext methodsFor: 'printing' stamp: 'LC 1/6/2002 11:59'! decompile ^ Decompiler new decompileBlock: self! ! !BlockContext methodsFor: 'printing' stamp: 'dew 11/11/2003 01:15'! printOn: aStream | blockString truncatedBlockString | home == nil ifTrue: [^aStream nextPutAll: 'a BlockContext with home=nil']. aStream nextPutAll: '[] in '. super printOn: aStream. aStream nextPutAll: ' '. blockString _ ((self decompile ifNil: ['--source missing--']) printString replaceAll: Character cr with: Character space) replaceAll: Character tab with: Character space. truncatedBlockString _ blockString truncateWithElipsisTo: 80. truncatedBlockString size < blockString size ifTrue: [truncatedBlockString _ truncatedBlockString, ']}']. aStream nextPutAll: truncatedBlockString. ! ! !BlockContext methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:01'! printOnStream: aStream home == nil ifTrue: [^aStream print: 'a BlockContext with home=nil']. aStream print: '[] in '. super printOnStream: aStream! ! !BlockContext methodsFor: 'private' stamp: 'ajh 1/24/2003 20:36'! aboutToReturn: result through: firstUnwindContext "Called from VM when an unwindBlock is found between self and its home. Return to home's sender, executing unwind blocks on the way." self home return: result! ! !BlockContext methodsFor: 'private' stamp: 'tfei 3/31/1999 17:40'! cannotReturn: result "The receiver tried to return result to a method context that no longer exists." | ex newResult | ex := BlockCannotReturn new. ex result: result. newResult := ex signal. ^newResult! ! !BlockContext methodsFor: 'private' stamp: 'di 1/14/1999 22:28'! instVarAt: index put: value index = 3 ifTrue: [self stackp: value. ^ value]. ^ super instVarAt: index put: value! ! !BlockContext methodsFor: 'private'! startpc "for use by the System Tracer only" ^startpc! ! !BlockContext methodsFor: 'private' stamp: 'ar 3/2/2001 01:16'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess _ Processor activeProcess. oldPriority _ activeProcess priority. activeProcess priority: Processor highestPriority. result _ self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !BlockContext methodsFor: 'system simulation' stamp: 'di 1/11/1999 10:24'! pushArgs: args from: sendr "Simulates action of the value primitive." args size ~= nargs ifTrue: [^self error: 'incorrect number of args']. self stackp: 0. args do: [:arg | self push: arg]. sender _ sendr. pc _ startpc! ! !BlockContext methodsFor: 'system simulation' stamp: 'hmm 7/30/2001 18:03'! stepToSendOrReturn pc = startpc ifTrue: [ "pop args first" self numArgs timesRepeat: [self step]]. ^super stepToSendOrReturn! ! !BlockContext methodsFor: 'exceptions' stamp: 'ajh 3/4/2004 22:36'! ensure: aBlock "Evaluate a termination block after evaluating the receiver, regardless of whether the receiver's evaluation completes." | returnValue b | <primitive: 198> returnValue := self value. "aBlock wasn't nil when execution of this method began; it is nil'd out by the unwind machinery, and that's how we know it's already been evaluated ... otherwise, obviously, it needs to be evaluated" aBlock == nil ifFalse: [ "nil out aBlock temp before evaluating aBlock so it is not executed again if aBlock remote returns" b _ aBlock. thisContext tempAt: 1 put: nil. "aBlock _ nil" b value. ]. ^ returnValue! ! !BlockContext methodsFor: 'exceptions' stamp: 'ajh 1/24/2003 21:43'! ifCurtailed: aBlock "Evaluate the receiver with an abnormal termination action." <primitive: 198> ^ self value! ! !BlockContext methodsFor: 'exceptions' stamp: 'ar 3/6/2001 14:25'! on: exception do: handlerAction "Evaluate the receiver in the scope of an exception handler." | handlerActive | <primitive: 199> handlerActive _ true. ^self value! ! !BlockContext methodsFor: 'private-debugger' stamp: 'tfei 3/20/2000 00:24'! hideFromDebugger ^home ~~ nil and: [home hideFromDebugger]! ! !BlockContext methodsFor: 'tiles' stamp: 'RAA 8/16/1999 13:52'! valueWithPossibleArgs: anArray self numArgs = 0 ifTrue: [^self value]. self numArgs = anArray size ifTrue: [^self valueWithArguments: anArray]. self numArgs > anArray size ifTrue: [ ^self valueWithArguments: anArray, (Array new: (self numArgs - anArray size)) ]. ^self valueWithArguments: (anArray copyFrom: 1 to: self numArgs) ! ! ParseNode subclass: #BlockNode instanceVariableNames: 'arguments statements returns nArgsNode size remoteCopyNode temporaries' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !BlockNode commentStamp: '<historical>' prior: 0! 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.! !BlockNode methodsFor: 'initialize-release'! arguments: argNodes statements: statementsCollection returns: returnBool from: encoder "Compile." arguments _ argNodes. statements _ statementsCollection size > 0 ifTrue: [statementsCollection] ifFalse: [argNodes size > 0 ifTrue: [statementsCollection copyWith: arguments last] ifFalse: [Array with: NodeNil]]. returns _ returnBool! ! !BlockNode methodsFor: 'initialize-release' stamp: 'sma 3/3/2000 13:38'! statements: statementsCollection returns: returnBool "Decompile." | returnLast | returnLast _ returnBool. returns _ false. statements _ (statementsCollection size > 1 and: [(statementsCollection at: statementsCollection size - 1) isReturningIf]) ifTrue: [returnLast _ false. statementsCollection allButLast] ifFalse: [statementsCollection size = 0 ifTrue: [Array with: NodeNil] ifFalse: [statementsCollection]]. arguments _ #(). temporaries _ #(). returnLast ifTrue: [self returnLast]! ! !BlockNode methodsFor: 'accessing'! arguments: argNodes "Decompile." arguments _ argNodes! ! !BlockNode methodsFor: 'accessing' stamp: 'tk 8/4/1999 22:53'! block ^ self! ! !BlockNode methodsFor: 'accessing'! firstArgument ^ arguments first! ! !BlockNode methodsFor: 'accessing'! numberOfArguments ^arguments size! ! !BlockNode methodsFor: 'accessing'! returnLast self returns ifFalse: [returns _ true. statements at: statements size put: statements last asReturnNode]! ! !BlockNode methodsFor: 'accessing'! returnSelfIfNoOther self returns ifFalse: [statements last == NodeSelf ifFalse: [statements add: NodeSelf]. self returnLast]! ! !BlockNode methodsFor: 'accessing' stamp: 'sma 2/27/2000 22:37'! temporaries: aCollection temporaries _ aCollection! ! !BlockNode methodsFor: 'testing'! canBeSpecialArgument "Can I be an argument of (e.g.) ifTrue:?" ^arguments size = 0! ! !BlockNode methodsFor: 'testing'! isComplex ^statements size > 1 or: [statements size = 1 and: [statements first isComplex]]! ! !BlockNode methodsFor: 'testing'! isJust: node returns ifTrue: [^false]. ^statements size = 1 and: [statements first == node]! ! !BlockNode methodsFor: 'testing'! isJustCaseError ^ statements size = 1 and: [statements first isMessage: #caseError receiver: [:r | r==NodeSelf] arguments: nil]! ! !BlockNode methodsFor: 'testing'! isQuick ^ statements size = 1 and: [statements first isVariableReference or: [statements first isSpecialConstant]]! ! !BlockNode methodsFor: 'testing'! returns ^returns or: [statements last isReturningIf]! ! !BlockNode methodsFor: 'code generation'! code ^statements first code! ! !BlockNode methodsFor: 'code generation' stamp: 'di 11/19/1999 19:32'! emitExceptLast: stack on: aStream | nextToLast | nextToLast _ statements size - 1. nextToLast < 1 ifTrue: [^ self]. "Only one statement" 1 to: nextToLast do: [:i | (statements at: i) emitForEffect: stack on: aStream]. ! ! !BlockNode methodsFor: 'code generation'! emitForEvaluatedEffect: stack on: aStream self returns ifTrue: [self emitForEvaluatedValue: stack on: aStream. stack pop: 1] ifFalse: [self emitExceptLast: stack on: aStream. statements last emitForEffect: stack on: aStream]! ! !BlockNode methodsFor: 'code generation' stamp: 'di 11/19/1999 19:44'! emitForEvaluatedValue: stack on: aStream self emitExceptLast: stack on: aStream. statements last emitForValue: stack on: aStream. ! ! !BlockNode methodsFor: 'code generation' stamp: 'hmm 7/17/2001 21:02'! emitForValue: stack on: aStream aStream nextPut: LdThisContext. stack push: 1. nArgsNode emitForValue: stack on: aStream. remoteCopyNode emit: stack args: 1 on: aStream. "Force a two byte jump." self emitLong: size code: JmpLong on: aStream. stack push: arguments size. arguments reverseDo: [:arg | arg emitStorePop: stack on: aStream]. self emitForEvaluatedValue: stack on: aStream. self returns ifFalse: [ aStream nextPut: EndRemote. pc _ aStream position. ]. stack pop: 1! ! !BlockNode methodsFor: 'code generation' stamp: 'di 11/19/1999 19:33'! sizeExceptLast: encoder | codeSize nextToLast | nextToLast _ statements size - 1. nextToLast < 1 ifTrue: [^ 0]. "Only one statement" codeSize _ 0. 1 to: nextToLast do: [:i | codeSize _ codeSize + ((statements at: i) sizeForEffect: encoder)]. ^ codeSize! ! !BlockNode methodsFor: 'code generation'! sizeForEvaluatedEffect: encoder self returns ifTrue: [^self sizeForEvaluatedValue: encoder]. ^(self sizeExceptLast: encoder) + (statements last sizeForEffect: encoder)! ! !BlockNode methodsFor: 'code generation'! sizeForEvaluatedValue: encoder ^(self sizeExceptLast: encoder) + (statements last sizeForValue: encoder)! ! !BlockNode methodsFor: 'code generation'! sizeForValue: encoder nArgsNode _ encoder encodeLiteral: arguments size. remoteCopyNode _ encoder encodeSelector: #blockCopy:. size _ (self sizeForEvaluatedValue: encoder) + (self returns ifTrue: [0] ifFalse: [1]). "endBlock" arguments _ arguments collect: "Chance to prepare debugger remote temps" [:arg | arg asStorableNode: encoder]. arguments do: [:arg | size _ size + (arg sizeForStorePop: encoder)]. ^1 + (nArgsNode sizeForValue: encoder) + (remoteCopyNode size: encoder args: 1 super: false) + 2 + size! ! !BlockNode methodsFor: 'printing' stamp: 'RAA 7/5/2000 11:43'! printArgumentsOn: aStream indent: level arguments size = 0 ifTrue: [^ self]. aStream dialect = #SQ00 ifTrue: [aStream withStyleFor: #setOrReturn do: [aStream nextPutAll: 'With']. arguments do: [:arg | aStream space. aStream withStyleFor: #blockArgument do: [aStream nextPutAll: arg key]]. aStream nextPutAll: '. '] ifFalse: [arguments do: [:arg | aStream withStyleFor: #blockArgument do: [aStream nextPutAll: ':'; nextPutAll: arg key; space]]. aStream nextPutAll: '| ']. "If >0 args and >1 statement, put all statements on separate lines" statements size > 1 ifTrue: [aStream crtab: level]! ! !BlockNode methodsFor: 'printing' stamp: 'di 5/1/2000 23:49'! printOn: aStream indent: level "statements size <= 1 ifFalse: [aStream crtab: level]." aStream nextPut: $[. self printArgumentsOn: aStream indent: level. self printTemporariesOn: aStream indent: level. self printStatementsOn: aStream indent: level. aStream nextPut: $]! ! !BlockNode methodsFor: 'printing' stamp: 'di 4/3/1999 23:25'! printStatementsOn: aStream indent: levelOrZero | len shown thisStatement level | level _ 1 max: levelOrZero. comment == nil ifFalse: [self printCommentOn: aStream indent: level. aStream crtab: level]. len _ shown _ statements size. (levelOrZero = 0 "top level" and: [statements last isReturnSelf]) ifTrue: [shown _ 1 max: shown - 1] ifFalse: [(len = 1 and: [((statements at: 1) == NodeNil) & (arguments size = 0)]) ifTrue: [shown _ shown - 1]]. 1 to: shown do: [:i | thisStatement _ statements at: i. thisStatement printOn: aStream indent: level. i < shown ifTrue: [aStream nextPut: $.; crtab: level]. (thisStatement comment ~~ nil and: [thisStatement comment size > 0]) ifTrue: [i = shown ifTrue: [aStream crtab: level]. thisStatement printCommentOn: aStream indent: level. i < shown ifTrue: [aStream crtab: level]]]! ! !BlockNode methodsFor: 'printing' stamp: 'di 4/5/2000 15:09'! printTemporariesOn: aStream indent: level (temporaries == nil or: [temporaries size = 0]) ifFalse: [aStream nextPut: $|. temporaries do: [:arg | aStream space; withStyleFor: #temporaryVariable do: [aStream nextPutAll: arg key]]. aStream nextPutAll: ' | '. "If >0 args and >1 statement, put all statements on separate lines" statements size > 1 ifTrue: [aStream crtab: level]]! ! !BlockNode methodsFor: 'equation translation'! statements ^statements! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BlockNode class instanceVariableNames: ''! !BlockNode class methodsFor: 'instance creation' stamp: 'sma 3/3/2000 13:34'! statements: statements returns: returns ^ self new statements: statements returns: returns! ! !BlockNode class methodsFor: 'instance creation' stamp: 'sma 3/3/2000 13:34'! withJust: aNode ^ self statements: (Array with: aNode) returns: false! ! Object subclass: #Boolean instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !Boolean commentStamp: '<historical>' prior: 0! Boolean is an abstract class defining the protocol for logic testing operations and conditional control structures for the logical values represented by the instances of its subclasses True and False. Boolean redefines #new so no instances of Boolean can be created. It also redefines several messages in the 'copying' protocol to ensure that only one instance of each of its subclasses True (the global true, logical assertion) and False (the global false, logical negation) ever exist in the system.! !Boolean methodsFor: 'logical operations'! & aBoolean "Evaluating conjunction. Evaluate the argument. Then answer true if both the receiver and the argument are true." self subclassResponsibility! ! !Boolean methodsFor: 'logical operations'! eqv: aBoolean "Answer true if the receiver is equivalent to aBoolean." ^self == aBoolean! ! !Boolean methodsFor: 'logical operations'! not "Negation. Answer true if the receiver is false, answer false if the receiver is true." self subclassResponsibility! ! !Boolean methodsFor: 'logical operations'! xor: aBoolean "Exclusive OR. Answer true if the receiver is not equivalent to aBoolean." ^(self == aBoolean) not! ! !Boolean methodsFor: 'logical operations'! | aBoolean "Evaluating disjunction (OR). Evaluate the argument. Then answer true if either the receiver or the argument is true." self subclassResponsibility! ! !Boolean methodsFor: 'controlling'! and: alternativeBlock "Nonevaluating conjunction. If the receiver is true, answer the value of the argument, alternativeBlock; otherwise answer false without evaluating the argument." self subclassResponsibility! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:44'! and: block1 and: block2 "Nonevaluating conjunction without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as false, then return false immediately, without evaluating any further blocks. If all return true, then return true." self ifFalse: [^ false]. block1 value ifFalse: [^ false]. block2 value ifFalse: [^ false]. ^ true! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:44'! and: block1 and: block2 and: block3 "Nonevaluating conjunction without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as false, then return false immediately, without evaluating any further blocks. If all return true, then return true." self ifFalse: [^ false]. block1 value ifFalse: [^ false]. block2 value ifFalse: [^ false]. block3 value ifFalse: [^ false]. ^ true! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:44'! and: block1 and: block2 and: block3 and: block4 "Nonevaluating conjunction without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as false, then return false immediately, without evaluating any further blocks. If all return true, then return true." self ifFalse: [^ false]. block1 value ifFalse: [^ false]. block2 value ifFalse: [^ false]. block3 value ifFalse: [^ false]. block4 value ifFalse: [^ false]. ^ true! ! !Boolean methodsFor: 'controlling'! ifFalse: alternativeBlock "If the receiver is true (i.e., the condition is true), then the value is the true alternative, which is nil. Otherwise answer the result of evaluating the argument, alternativeBlock. Create an error notification if the receiver is nonBoolean. Execution does not actually reach here because the expression is compiled in-line." self subclassResponsibility! ! !Boolean methodsFor: 'controlling'! ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock "Same as ifTrue:ifFalse:." self subclassResponsibility! ! !Boolean methodsFor: 'controlling'! ifTrue: alternativeBlock "If the receiver is false (i.e., the condition is false), then the value is the false alternative, which is nil. Otherwise answer the result of evaluating the argument, alternativeBlock. Create an error notification if the receiver is nonBoolean. Execution does not actually reach here because the expression is compiled in-line." self subclassResponsibility! ! !Boolean methodsFor: 'controlling'! ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock "If the receiver is true (i.e., the condition is true), then answer the value of the argument trueAlternativeBlock. If the receiver is false, answer the result of evaluating the argument falseAlternativeBlock. If the receiver is a nonBoolean then create an error notification. Execution does not actually reach here because the expression is compiled in-line." self subclassResponsibility! ! !Boolean methodsFor: 'controlling'! or: alternativeBlock "Nonevaluating disjunction. If the receiver is false, answer the value of the argument, alternativeBlock; otherwise answer true without evaluating the argument." self subclassResponsibility! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:45'! or: block1 or: block2 "Nonevaluating alternation without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as true, then return true immediately, without evaluating any further blocks. If all return false, then return false." self ifTrue: [^ true]. block1 value ifTrue: [^ true]. block2 value ifTrue: [^ true]. ^ false! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:45'! or: block1 or: block2 or: block3 "Nonevaluating alternation without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as true, then return true immediately, without evaluating any further blocks. If all return false, then return false." self ifTrue: [^ true]. block1 value ifTrue: [^ true]. block2 value ifTrue: [^ true]. block3 value ifTrue: [^ true]. ^ false! ! !Boolean methodsFor: 'controlling' stamp: 'zz 3/2/2004 23:45'! or: block1 or: block2 or: block3 or: block4 "Nonevaluating alternation without deep nesting. The receiver is evaluated, followed by the blocks in order. If any of these evaluates as true, then return true immediately, without evaluating any further blocks. If all return false, then return false." self ifTrue: [^ true]. block1 value ifTrue: [^ true]. block2 value ifTrue: [^ true]. block3 value ifTrue: [^ true]. block4 value ifTrue: [^ true]. ^ false! ! !Boolean methodsFor: 'copying' stamp: 'tk 6/26/1998 11:32'! clone "Receiver has two concrete subclasses, True and False. Only one instance of each should be made, so return self."! ! !Boolean methodsFor: 'copying'! deepCopy "Receiver has two concrete subclasses, True and False. Only one instance of each should be made, so return self."! ! !Boolean methodsFor: 'copying'! shallowCopy "Receiver has two concrete subclasses, True and False. Only one instance of each should be made, so return self."! ! !Boolean methodsFor: 'copying' stamp: 'tk 8/20/1998 16:07'! veryDeepCopyWith: deepCopier "Return self. I can't be copied. Do not record me."! ! !Boolean methodsFor: 'printing' stamp: 'sw 9/27/2001 17:19'! basicType "Answer a symbol representing the inherent type of the receiver" ^ #Boolean! ! !Boolean methodsFor: 'printing'! storeOn: aStream "Refer to the comment in Object|storeOn:." self printOn: aStream! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Boolean class instanceVariableNames: ''! !Boolean class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 00:31'! initializedInstance ^ nil! ! !Boolean class methodsFor: 'instance creation'! new self error: 'You may not create any more Booleans - this is two-valued logic'! ! !Boolean class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:06'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asBooleanValueFrom: anInteger on: aStream ! ! !Boolean class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:05'! ccg: cg generateCoerceToOopFrom: aNode on: aStream cg generateCoerceToBooleanObjectFrom: aNode on: aStream! ! !Boolean class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:10'! ccg: cg generateCoerceToValueFrom: aNode on: aStream cg generateCoerceToBooleanValueFrom: aNode on: aStream! ! !Boolean class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 17:08'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asBooleanValueFrom: anInteger! ! ParseNode subclass: #BraceNode instanceVariableNames: 'elements sourceLocations emitNode' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !BraceNode commentStamp: '<historical>' prior: 0! Used for compiling and decompiling brace constructs. These now compile into either a fast short form for 4 elements or less: Array braceWith: a with: b ... or a long form of indefinfite length: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray. The erstwhile brace assignment form is no longer supported.! !BraceNode methodsFor: 'initialize-release'! elements: collection "Decompile." elements _ collection! ! !BraceNode methodsFor: 'initialize-release'! elements: collection sourceLocations: locations "Compile." elements _ collection. sourceLocations _ locations! ! !BraceNode methodsFor: 'initialize-release' stamp: 'di 11/19/1999 11:06'! matchBraceStreamReceiver: receiver messages: messages ((receiver isMessage: #braceStream: receiver: nil arguments: [:arg | arg isConstantNumber]) and: [messages last isMessage: #braceArray receiver: nil arguments: nil]) ifFalse: [^ nil "no match"]. "Appears to be a long form brace construct" self elements: (messages allButLast collect: [:msg | (msg isMessage: #nextPut: receiver: nil arguments: nil) ifFalse: [^ nil "not a brace element"]. msg arguments first])! ! !BraceNode methodsFor: 'initialize-release' stamp: 'di 11/19/1999 11:19'! matchBraceWithReceiver: receiver selector: selector arguments: arguments selector = (self selectorForShortForm: arguments size) ifFalse: [^ nil "no match"]. "Appears to be a short form brace construct" self elements: arguments! ! !BraceNode methodsFor: 'testing'! blockAssociationCheck: encoder "If all elements are MessageNodes of the form [block]->[block], and there is at least one element, answer true. Otherwise, notify encoder of an error." elements size = 0 ifTrue: [^encoder notify: 'At least one case required']. elements with: sourceLocations do: [:x :loc | (x isMessage: #-> receiver: [:rcvr | (rcvr isKindOf: BlockNode) and: [rcvr numberOfArguments = 0]] arguments: [:arg | (arg isKindOf: BlockNode) and: [arg numberOfArguments = 0]]) ifFalse: [^encoder notify: 'Association between 0-argument blocks required' at: loc]]. ^true! ! !BraceNode methodsFor: 'testing'! numElements ^ elements size! ! !BraceNode methodsFor: 'code generation' stamp: 'di 11/19/1999 08:58'! emitForValue: stack on: aStream ^ emitNode emitForValue: stack on: aStream! ! !BraceNode methodsFor: 'code generation' stamp: 'di 1/4/2000 11:24'! selectorForShortForm: nElements nElements > 4 ifTrue: [^ nil]. ^ #(braceWithNone braceWith: braceWith:with: braceWith:with:with: braceWith:with:with:with:) at: nElements + 1! ! !BraceNode methodsFor: 'code generation' stamp: 'di 11/19/1999 11:13'! sizeForValue: encoder emitNode _ elements size <= 4 ifTrue: ["Short form: Array braceWith: a with: b ... " MessageNode new receiver: (encoder encodeVariable: #Array) selector: (self selectorForShortForm: elements size) arguments: elements precedence: 3 from: encoder] ifFalse: ["Long form: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray" CascadeNode new receiver: (MessageNode new receiver: (encoder encodeVariable: #Array) selector: #braceStream: arguments: (Array with: (encoder encodeLiteral: elements size)) precedence: 3 from: encoder) messages: ((elements collect: [:elt | MessageNode new receiver: nil selector: #nextPut: arguments: (Array with: elt) precedence: 3 from: encoder]) copyWith: (MessageNode new receiver: nil selector: #braceArray arguments: (Array new) precedence: 1 from: encoder))]. ^ emitNode sizeForValue: encoder! ! !BraceNode methodsFor: 'enumerating'! casesForwardDo: aBlock "For each case in forward order, evaluate aBlock with three arguments: the key block, the value block, and whether it is the last case." | numCases case | 1 to: (numCases _ elements size) do: [:i | case _ elements at: i. aBlock value: case receiver value: case arguments first value: i=numCases]! ! !BraceNode methodsFor: 'enumerating'! casesReverseDo: aBlock "For each case in reverse order, evaluate aBlock with three arguments: the key block, the value block, and whether it is the last case." | numCases case | (numCases _ elements size) to: 1 by: -1 do: [:i | case _ elements at: i. aBlock value: case receiver value: case arguments first value: i=numCases]! ! !BraceNode methodsFor: 'printing' stamp: 'di 11/19/1999 09:17'! printOn: aStream indent: level aStream nextPut: ${. 1 to: elements size do: [:i | (elements at: i) printOn: aStream indent: level. i < elements size ifTrue: [aStream nextPutAll: '. ']]. aStream nextPut: $}! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BraceNode class instanceVariableNames: ''! !BraceNode class methodsFor: 'examples' stamp: 'di 11/19/1999 09:05'! example "Test the {a. b. c} syntax." | x | x _ {1. {2. 3}. 4}. ^ {x first. x second first. x second last. x last. 5} as: Set "BraceNode example Set (0 1 2 3 4 5 )" ! ! Halt subclass: #BreakPoint instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Debugger'! !BreakPoint commentStamp: 'md 11/18/2003 09:32' prior: 0! This exception is raised on executing a breakpoint. "BreakPoint signal" is called from "Object>>break".! Object subclass: #BreakpointManager instanceVariableNames: '' classVariableNames: 'Installed' poolDictionaries: '' category: 'Tools-Debugger'! !BreakpointManager commentStamp: 'emm 5/30/2002 14:20' prior: 0! This class manages methods that include breakpoints. It has several class methods to install and uninstall breakpoints. Evaluating "BreakpointManager clear" will remove all installed breakpoints in the system. Known issues: - currently, only break-on-entry type of breakpoints are supported - emphasis change not implemented for MVC browsers - uninstalling the breakpoint doesn't auto-update other browsers - uninstalling a breakpoint while debugging should restart-simulate the current method Ernest Micklei, 2002 Send comments to emicklei@philemonworks.com! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BreakpointManager class instanceVariableNames: ''! !BreakpointManager class methodsFor: 'install-uninstall' stamp: 'emm 5/30/2002 09:37'! installInClass: aClass selector: aSymbol "Install a new method containing a breakpoint. The receiver will remember this for unstalling it later" | breakMethod | breakMethod _ self compilePrototype: aSymbol in: aClass. breakMethod isNil ifTrue: [^ nil]. self installed at: breakMethod put: aClass >> aSymbol. "old method" aClass methodDictionary at: aSymbol put: breakMethod.! ! !BreakpointManager class methodsFor: 'install-uninstall' stamp: 'emm 4/24/2002 23:24'! unInstall: breakMethod | who oldMethod | oldMethod _ self installed at: breakMethod ifAbsent:[^self]. who _ breakMethod who. (who first methodDictionary at: who last) == breakMethod ifTrue:[ who first methodDictionary at: who last put: oldMethod]. self installed removeKey: breakMethod! ! !BreakpointManager class methodsFor: 'private' stamp: 'emm 5/30/2002 09:36'! breakpointMethodSourceFor: aSymbol in: aClass "Compose new source containing a break statement (currently it will be the first, later we want to insert it in any place)" | oldSource methodNode breakOnlyMethodNode sendBreakMessageNode | oldSource := aClass sourceCodeAt: aSymbol. methodNode := aClass compilerClass new compile: oldSource in: aClass notifying: nil ifFail: [self error: '[breakpoint] unable to install breakpoint']. breakOnlyMethodNode := aClass compilerClass new compile: 'temporaryMethodSelectorForBreakpoint self break. ^self' in: aClass notifying: nil ifFail: [self error: '[breakpoint] unable to install breakpoint']. sendBreakMessageNode := breakOnlyMethodNode block statements first. methodNode block statements addFirst: sendBreakMessageNode. ^methodNode printString ! ! !BreakpointManager class methodsFor: 'private' stamp: 'emm 5/30/2002 09:33'! compilePrototype: aSymbol in: aClass "Compile and return a new method containing a break statement" | source node method | source := self breakpointMethodSourceFor: aSymbol in: aClass. node := aClass compilerClass new compile: source in: aClass notifying: nil ifFail: [self error: '[breakpoint] unable to install breakpoint']. node isNil ifTrue: [^nil]. "dunno what the arguments mean..." method := node generate: #(0 0 0 0). ^method! ! !BreakpointManager class methodsFor: 'private' stamp: 'emm 4/24/2002 23:24'! installed Installed isNil ifTrue:[Installed := IdentityDictionary new]. ^Installed! ! !BreakpointManager class methodsFor: 'intialization-release' stamp: 'emm 5/30/2002 09:08'! clear "BreakpointManager clear" self installed copy keysDo:[ :breakMethod | self unInstall: breakMethod]. ! ! !BreakpointManager class methodsFor: 'testing' stamp: 'emm 5/30/2002 09:22'! methodHasBreakpoint: aMethod ^self installed includesKey: aMethod! ! CodeHolder subclass: #Browser instanceVariableNames: 'systemOrganizer classOrganizer metaClassOrganizer systemCategoryListIndex classListIndex messageCategoryListIndex messageListIndex editSelection metaClassIndicated' classVariableNames: 'RecentClasses' poolDictionaries: '' category: 'Tools-Browser'! !Browser commentStamp: '<historical>' prior: 0! I represent a query path into the class descriptions, the software of the system.! !Browser methodsFor: 'accessing' stamp: 'ls 10/28/2003 12:28'! contents "Depending on the current selection, different information is retrieved. Answer a string description of that information. This information is the method of the currently selected class and message." | comment theClass latestCompiledMethod | latestCompiledMethod _ currentCompiledMethod. currentCompiledMethod _ nil. editSelection == #none ifTrue: [^ '']. editSelection == #editSystemCategories ifTrue: [^ systemOrganizer printString]. editSelection == #newClass ifTrue: [^ (theClass _ self selectedClass) ifNil: [Class template: self selectedSystemCategoryName] ifNotNil: [Class templateForSubclassOf: theClass category: self selectedSystemCategoryName]]. editSelection == #editClass ifTrue: [^ self classDefinitionText ]. editSelection == #editComment ifTrue: [(theClass _ self selectedClass) ifNil: [^ '']. comment _ theClass comment. currentCompiledMethod _ theClass organization commentRemoteStr. ^ comment size = 0 ifTrue: ['This class has not yet been commented.'] ifFalse: [comment]]. editSelection == #hierarchy ifTrue: [^ self selectedClassOrMetaClass printHierarchy]. editSelection == #editMessageCategories ifTrue: [^ self classOrMetaClassOrganizer printString]. editSelection == #newMessage ifTrue: [^ (theClass _ self selectedClassOrMetaClass) ifNil: [''] ifNotNil: [theClass sourceCodeTemplate]]. editSelection == #editMessage ifTrue: [self showingByteCodes ifTrue: [^ self selectedBytecodes]. currentCompiledMethod _ latestCompiledMethod. ^ self selectedMessage]. self error: 'Browser internal error: unknown edit selection.'! ! !Browser methodsFor: 'accessing' stamp: 'nk 3/29/2004 10:11'! contents: input notifying: aController "The retrieved information has changed and its source must now be updated. The information can be a variety of things, depending on the list selections (such as templates for class or message definition, methods) or the user menu commands (such as definition, comment, hierarchy). Answer the result of updating the source." | aString aText theClass | self changed: #annotation. aString _ input asString. aText _ input asText. editSelection == #editSystemCategories ifTrue: [^ self changeSystemCategories: aString]. editSelection == #editClass | (editSelection == #newClass) ifTrue: [^ self defineClass: aString notifying: aController]. editSelection == #editComment ifTrue: [theClass _ self selectedClass. theClass ifNil: [self inform: 'You must select a class before giving it a comment.'. ^ false]. theClass comment: aText stamp: Utilities changeStamp. self changed: #classCommentText. ^ true]. editSelection == #hierarchy ifTrue: [^ true]. editSelection == #editMessageCategories ifTrue: [^ self changeMessageCategories: aString]. editSelection == #editMessage | (editSelection == #newMessage) ifTrue: [^ self okayToAccept ifFalse: [false] ifTrue: [self compileMessage: aText notifying: aController]]. editSelection == #none ifTrue: [self inform: 'This text cannot be accepted in this part of the browser.'. ^ false]. self error: 'unacceptable accept'! ! !Browser methodsFor: 'accessing' stamp: 'drs 1/6/2003 16:11'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" messageCategoryListIndex > 0 & (messageListIndex = 0) ifTrue: [^ 1 to: 500] "entire empty method template" ifFalse: [^ 1 to: 0] "null selection"! ! !Browser methodsFor: 'accessing' stamp: 'BG 10/29/2003 09:01'! couldBrowseAnyClass "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" self dependents detect: [:d | ((d isKindOf: PluggableListView)) and: [d getListSelector == #systemCategoryList]] ifNone: [^ false]. ^ true ! ! !Browser methodsFor: 'accessing' stamp: 'sma 5/28/2000 11:28'! doItReceiver "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." ^ self selectedClass ifNil: [FakeClassPool new]! ! !Browser methodsFor: 'accessing'! editSelection ^editSelection! ! !Browser methodsFor: 'accessing' stamp: 'nk 2/15/2004 13:27'! editSelection: aSelection "Set the editSelection as requested." editSelection _ aSelection. self changed: #editSelection.! ! !Browser methodsFor: 'accessing' stamp: 'sw 10/30/1999 22:59'! noteSelectionIndex: anInteger for: aSymbol aSymbol == #systemCategoryList ifTrue: [systemCategoryListIndex _ anInteger]. aSymbol == #classList ifTrue: [classListIndex _ anInteger]. aSymbol == #messageCategoryList ifTrue: [messageCategoryListIndex _ anInteger]. aSymbol == #messageList ifTrue: [messageListIndex _ anInteger].! ! !Browser methodsFor: 'accessing' stamp: 'jm 4/28/1998 05:55'! request: prompt initialAnswer: initialAnswer ^ FillInTheBlank request: prompt initialAnswer: initialAnswer ! ! !Browser methodsFor: 'accessing' stamp: 'sw 1/4/2001 12:24'! spawn: aString "Create and schedule a fresh browser and place aString in its code pane. This method is called when the user issues the #spawn command (cmd-o) in any code pane. Whatever text was in the original code pane comes in to this method as the aString argument; the changes in the original code pane have already been cancelled by the time this method is called, so aString is the only copy of what the user had in his code pane." self selectedClassOrMetaClass ifNotNil: [^ super spawn: aString]. systemCategoryListIndex ~= 0 ifTrue: ["This choice is slightly useless but is the historical implementation" ^ self buildSystemCategoryBrowserEditString: aString]. ^ super spawn: aString "This bail-out at least saves the text being spawned, which would otherwise be lost"! ! !Browser methodsFor: 'accessing' stamp: 'sw 9/26/2002 17:56'! suggestCategoryToSpawnedBrowser: aBrowser "aBrowser is a message-category browser being spawned from the receiver. Tell it what it needs to know to get its category info properly set up." (self isMemberOf: Browser) "yecch, but I didn't invent the browser hierarchy" ifTrue: [aBrowser messageCategoryListIndex: (self messageCategoryList indexOf: self categoryOfCurrentMethod ifAbsent: [2])] ifFalse: [aBrowser setOriginalCategoryIndexForCurrentMethod]! ! !Browser methodsFor: 'annotation' stamp: 'sw 8/26/2002 10:00'! annotation "Provide a line of content for an annotation pane, representing information about the method associated with the selected class and selector in the receiver." | aSelector aClass | (aClass _ self selectedClassOrMetaClass) == nil ifTrue: [^ '------']. self editSelection == #editComment ifTrue: [^ self annotationForSelector: #Comment ofClass: aClass]. self editSelection == #editClass ifTrue: [^ self annotationForSelector: #Definition ofClass: aClass]. (aSelector _ self selectedMessageName) ifNil: [^ '------']. ^ self annotationForSelector: aSelector ofClass: aClass! ! !Browser methodsFor: 'breakpoints' stamp: 'emm 5/30/2002 09:23'! toggleBreakOnEntry "Install or uninstall a halt-on-entry breakpoint" | selectedMethod | self selectedClassOrMetaClass isNil ifTrue:[^self]. selectedMethod := self selectedClassOrMetaClass >> self selectedMessageName. selectedMethod hasBreakpoint ifTrue: [BreakpointManager unInstall: selectedMethod] ifFalse: [BreakpointManager installInClass: self selectedClassOrMetaClass selector: self selectedMessageName]. self changed: #messageList ! ! !Browser methodsFor: 'class comment pane' stamp: 'nk 2/15/2004 13:19'! classComment: aText notifying: aPluggableTextMorph "The user has just entered aText. It may be all red (a side-effect of replacing the default comment), so remove the color if it is." | theClass cleanedText redRange | theClass := self selectedClassOrMetaClass. theClass ifNotNil: [cleanedText := aText asText. redRange := cleanedText rangeOf: TextColor red startingAt: 1. redRange size = cleanedText size ifTrue: [cleanedText removeAttribute: TextColor red from: 1 to: redRange last ]. theClass classComment: aText]. self changed: #classCommentText. ^ true! ! !Browser methodsFor: 'class functions' stamp: 'sd 5/23/2003 14:23'! addAllMethodsToCurrentChangeSet "Add all the methods in the selected class or metaclass to the current change set. You ought to know what you're doing before you invoke this!!" | aClass | (aClass _ self selectedClassOrMetaClass) ifNotNil: [aClass selectors do: [:sel | ChangeSet current adoptSelector: sel forClass: aClass]. self changed: #annotation] ! ! !Browser methodsFor: 'class functions'! buildClassBrowser "Create and schedule a new class category browser for the current class selection, if one exists." self buildClassBrowserEditString: nil! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 14:32'! classCommentText "return the text to display for the comment of the currently selected class" | theClass | theClass _ self selectedClassOrMetaClass. theClass ifNil: [ ^'']. ^ theClass hasComment ifTrue: [ theClass comment ] ifFalse: [ Text string: 'THIS CLASS HAS NO COMMENT!!' translated attribute: TextColor red ]! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 15:11'! classDefinitionText "return the text to display for the definition of the currently selected class" | theClass | theClass _ self selectedClassOrMetaClass. theClass ifNil: [ ^'']. ^theClass definitionST80: Preferences printAlternateSyntax not! ! !Browser methodsFor: 'class functions' stamp: 'sw 12/6/2000 16:32'! classListMenu: aMenu "For backward compatibility with old browers stored in image segments" ^ self classListMenu: aMenu shifted: false! ! !Browser methodsFor: 'class functions' stamp: 'sw 2/27/2001 12:06'! classListMenu: aMenu shifted: shifted "Set up the menu to apply to the receiver's class list, honoring the #shifted boolean" shifted ifTrue: [^ self shiftedClassListMenu: aMenu]. aMenu addList: #( - ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' spawnHierarchy) ('browse protocol (p)' browseFullProtocol) - ('printOut' printOutClass) ('fileOut' fileOutClass) - ('show hierarchy' hierarchy) ('show definition' editClass) ('show comment' editComment) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) - ('class var refs...' browseClassVarRefs) ('class vars' browseClassVariables) ('class refs (N)' browseClassRefs) - ('rename class ...' renameClass) ('copy class' copyClass) ('remove class (x)' removeClass) - ('find method...' findMethod) - ('more...' offerShiftedClassListMenu)). ^ aMenu! ! !Browser methodsFor: 'class functions' stamp: 'dwh 11/23/1999 00:09'! copyClass | originalName copysName class oldDefinition newDefinition | classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. originalName _ self selectedClass name. copysName _ self request: 'Please type new class name' initialAnswer: originalName. copysName = '' ifTrue: [^ self]. " Cancel returns '' " copysName _ copysName asSymbol. copysName = originalName ifTrue: [^ self]. (Smalltalk includesKey: copysName) ifTrue: [^ self error: copysName , ' already exists']. oldDefinition _ self selectedClass definition. newDefinition _ oldDefinition copyReplaceAll: '#' , originalName asString with: '#' , copysName asString. Cursor wait showWhile: [class _ Compiler evaluate: newDefinition logged: true. class copyAllCategoriesFrom: (Smalltalk at: originalName). class class copyAllCategoriesFrom: (Smalltalk at: originalName) class]. self classListIndex: 0. self changed: #classList! ! !Browser methodsFor: 'class functions' stamp: 'sw 10/22/2002 16:10'! createInstVarAccessors "Create getters and setters for all inst vars defined at the level of the current class selection, except do NOT clobber or override any selectors already understood by the instances of the selected class" | aClass newMessage setter | (aClass _ self selectedClassOrMetaClass) ifNotNil: [aClass instVarNames do: [:aName | (aClass canUnderstand: aName asSymbol) ifFalse: [newMessage _ aName, ' "Answer the value of ', aName, '" ^ ', aName. aClass compile: newMessage classified: 'accessing' notifying: nil]. (aClass canUnderstand: (setter _ aName, ':') asSymbol) ifFalse: [newMessage _ setter, ' anObject "Set the value of ', aName, '" ', aName, ' _ anObject'. aClass compile: newMessage classified: 'accessing' notifying: nil]]]! ! !Browser methodsFor: 'class functions' stamp: 'sw 11/21/2003 21:45'! defineClass: defString notifying: aController "The receiver's textual content is a request to define a new class. The source code is defString. If any errors occur in compilation, notify aController." | oldClass class newClassName defTokens keywdIx envt | oldClass _ self selectedClassOrMetaClass. defTokens _ defString findTokens: Character separators. keywdIx _ defTokens findFirst: [:x | x beginsWith: 'category']. envt _ Smalltalk environmentForCategory: ((defTokens at: keywdIx+1) copyWithout: $'). keywdIx _ defTokens findFirst: [:x | '*subclass*' match: x]. newClassName _ (defTokens at: keywdIx+1) copyWithoutAll: '#()'. ((oldClass isNil or: [oldClass theNonMetaClass name asString ~= newClassName]) and: [envt includesKeyOrAbove: newClassName asSymbol]) ifTrue: ["Attempting to define new class over existing one when not looking at the original one in this browser..." (self confirm: ((newClassName , ' is an existing class in this system. Redefining it might cause serious problems. Is this really what you want to do?') asText makeBoldFrom: 1 to: newClassName size)) ifFalse: [^ false]]. "ar 8/29/1999: Use oldClass superclass for defining oldClass since oldClass superclass knows the definerClass of oldClass." oldClass ifNotNil:[oldClass _ oldClass superclass]. class _ oldClass subclassDefinerClass evaluate: defString notifying: aController logged: true. (class isKindOf: Behavior) ifTrue: [self changed: #systemCategoryList. self changed: #classList. self clearUserEditFlag. self setClass: class selector: nil. "self clearUserEditFlag; editClass." ^ true] ifFalse: [^ false]! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/15/2004 13:23'! editClass "Retrieve the description of the class definition." classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. self messageCategoryListIndex: 0. self editSelection: #editClass. self changed: #contents. self changed: #classCommentText. ! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 15:08'! editComment "Retrieve the description of the class comment." classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. self messageCategoryListIndex: 0. metaClassIndicated _ false. self editSelection: #editComment. self changed: #classSelectionChanged. self changed: #messageCategoryList. self changed: #messageList. self decorateButtons. self contentsChanged ! ! !Browser methodsFor: 'class functions' stamp: 'nb 5/6/2003 16:49'! explainSpecial: string "Answer a string explaining the code pane selection if it is displaying one of the special edit functions." | classes whole lits reply | (editSelection == #editClass or: [editSelection == #newClass]) ifTrue: ["Selector parts in class definition" string last == $: ifFalse: [^nil]. lits _ Array with: #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:. (whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string] ifNone: []) ~~ nil] ifNone: []) ~~ nil ifTrue: [reply _ '"' , string , ' is one part of the message selector ' , whole , '.'] ifFalse: [^nil]. classes _ self systemNavigation allClassesImplementing: whole. classes _ 'these classes ' , classes printString. ^reply , ' It is defined in ' , classes , '." Smalltalk browseAllImplementorsOf: #' , whole]. editSelection == #hierarchy ifTrue: ["Instance variables in subclasses" classes _ self selectedClassOrMetaClass allSubclasses. classes _ classes detect: [:each | (each instVarNames detect: [:name | name = string] ifNone: []) ~~ nil] ifNone: [^nil]. classes _ classes printString. ^'"is an instance variable in class ' , classes , '." ' , classes , ' browseAllAccessesTo: ''' , string , '''.']. editSelection == #editSystemCategories ifTrue: [^nil]. editSelection == #editMessageCategories ifTrue: [^nil]. ^nil! ! !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'! fileOutClass "Print a description of the selected class onto a file whose name is the category name followed by .st." Cursor write showWhile: [classListIndex ~= 0 ifTrue: [self selectedClass fileOut]]! ! !Browser methodsFor: 'class functions' stamp: 'je 12/4/2002 18:10'! findMethod "Pop up a list of the current class's methods, and select the one chosen by the user" | aClass selectors reply cat messageCatIndex messageIndex | self classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. aClass _ self selectedClassOrMetaClass. selectors _ aClass selectors asSortedArray. selectors isEmpty ifTrue: [self inform: aClass name, ' has no methods.'. ^ self]. reply _ (SelectionMenu labelList: selectors selections: selectors) startUp. reply == nil ifTrue: [^ self]. cat _ aClass whichCategoryIncludesSelector: reply. messageCatIndex _ self messageCategoryList indexOf: cat. self messageCategoryListIndex: messageCatIndex. messageIndex _ (self messageList indexOf: reply). self messageListIndex: messageIndex! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 15:09'! hierarchy "Display the inheritance hierarchy of the receiver's selected class." classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. self messageCategoryListIndex: 0. self editSelection: #hierarchy. self changed: #editComment. self contentsChanged. ^ self! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 15:07'! makeNewSubclass self selectedClassOrMetaClass ifNil: [^ self]. self okToChange ifFalse: [^ self]. self editSelection: #newClass. self contentsChanged! ! !Browser methodsFor: 'class functions' stamp: 'nk 2/14/2004 15:09'! plusButtonHit "Cycle among definition, comment, and hierachy" editSelection == #editComment ifTrue: [self hierarchy. ^ self]. editSelection == #hierarchy ifTrue: [self editSelection: #editClass. classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. self changed: #editComment. self contentsChanged. ^ self]. self editComment! ! !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'! printOutClass "Print a description of the selected class onto a file whose name is the category name followed by .html." Cursor write showWhile: [classListIndex ~= 0 ifTrue: [self selectedClass fileOutAsHtml: true]]! ! !Browser methodsFor: 'class functions' stamp: 'sw 3/5/2001 18:04'! removeClass "If the user confirms the wish to delete the class, do so" super removeClass ifTrue: [self classListIndex: 0]! ! !Browser methodsFor: 'class functions' stamp: 'sd 4/29/2003 11:49'! renameClass | oldName newName obs | classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. oldName _ self selectedClass name. newName _ self request: 'Please type new class name' initialAnswer: oldName. newName = '' ifTrue: [^ self]. "Cancel returns ''" newName _ newName asSymbol. newName = oldName ifTrue: [^ self]. (Smalltalk includesKey: newName) ifTrue: [^ self error: newName , ' already exists']. self selectedClass rename: newName. self changed: #classList. self classListIndex: ((systemOrganizer listAtCategoryNamed: self selectedSystemCategoryName) indexOf: newName). obs _ self systemNavigation allCallsOn: (Smalltalk associationAt: newName). obs isEmpty ifFalse: [self systemNavigation browseMessageList: obs name: 'Obsolete References to ' , oldName autoSelect: oldName]! ! !Browser methodsFor: 'class functions' stamp: 'BG 11/1/2003 13:59'! shiftedClassListMenu: aMenu "Set up the menu to apply to the receiver's class list when the shift key is down" ^ aMenu addList: #( - ('unsent methods' browseUnusedMethods 'browse all methods defined by this class that have no senders') ('unreferenced inst vars' showUnreferencedInstVars 'show a list of all instance variables that are not referenced in methods') ('unreferenced class vars' showUnreferencedClassVars 'show a list of all class variables that are not referenced in methods') ('subclass template' makeNewSubclass 'put a template into the code pane for defining of a subclass of this class') - ('sample instance' makeSampleInstance 'give me a sample instance of this class, if possible') ('inspect instances' inspectInstances 'open an inspector on all the extant instances of this class') ('inspect subinstances' inspectSubInstances 'open an inspector on all the extant instances of this class and of all of its subclasses') - ('add all meths to current chgs' addAllMethodsToCurrentChangeSet 'place all the methods defined by this class into the current change set') ('create inst var accessors' createInstVarAccessors 'compile instance-variable access methods for any instance variables that do not yet have them') - ('more...' offerUnshiftedClassListMenu 'return to the standard class-list menu'))! ! !Browser methodsFor: 'class list'! classList "Answer an array of the class names of the selected category. Answer an empty array if no selection exists." systemCategoryListIndex = 0 ifTrue: [^Array new] ifFalse: [^systemOrganizer listAtCategoryNumber: systemCategoryListIndex]! ! !Browser methodsFor: 'class list'! classListIndex "Answer the index of the current class selection." ^classListIndex! ! !Browser methodsFor: 'class list' stamp: 'nk 2/14/2004 15:07'! classListIndex: anInteger "Set anInteger to be the index of the current class selection." | className | classListIndex _ anInteger. self setClassOrganizer. messageCategoryListIndex _ 0. messageListIndex _ 0. self classCommentIndicated ifTrue: [] ifFalse: [self editSelection: (anInteger = 0 ifTrue: [metaClassIndicated | (systemCategoryListIndex == 0) ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. contents _ nil. self selectedClass isNil ifFalse: [className _ self selectedClass name. (RecentClasses includes: className) ifTrue: [RecentClasses remove: className]. RecentClasses addFirst: className. RecentClasses size > 16 ifTrue: [RecentClasses removeLast]]. self changed: #classSelectionChanged. self changed: #classCommentText. self changed: #classListIndex. "update my selection" self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged! ! !Browser methodsFor: 'class list' stamp: 'tk 4/5/98 12:25'! classListSingleton | name | name _ self selectedClassName. ^ name ifNil: [Array new] ifNotNil: [Array with: name]! ! !Browser methodsFor: 'class list' stamp: 'nb 6/17/2003 12:25'! recent "Let the user select from a list of recently visited classes. 11/96 stp. 12/96 di: use class name, not classes themselves. : dont fall into debugger in empty case" | className class recentList | recentList _ RecentClasses select: [:n | Smalltalk includesKey: n]. recentList size == 0 ifTrue: [^ Beeper beep]. className := (SelectionMenu selections: recentList) startUp. className == nil ifTrue: [^ self]. class := Smalltalk at: className. self selectCategoryForClass: class. self classListIndex: (self classList indexOf: class name)! ! !Browser methodsFor: 'class list' stamp: 'sr 10/29/1999 20:28'! selectClass: classNotMeta self classListIndex: (self classList indexOf: classNotMeta name)! ! !Browser methodsFor: 'class list' stamp: 'di 12/6/1999 20:41'! selectedClass "Answer the class that is currently selected. Answer nil if no selection exists." | name envt | (name _ self selectedClassName) ifNil: [^ nil]. (envt _ self selectedEnvironment) ifNil: [^ nil]. ^ envt at: name! ! !Browser methodsFor: 'class list' stamp: 'sw 11/24/1999 14:48'! selectedClassName | aClassList | "Answer the name of the current class. Answer nil if no selection exists." (classListIndex = 0 or: [classListIndex > (aClassList _ self classList) size]) ifTrue: [^ nil]. ^ aClassList at: classListIndex! ! !Browser methodsFor: 'class list'! toggleClassListIndex: anInteger "If anInteger is the current class index, deselect it. Else make it the current class selection." self classListIndex: (classListIndex = anInteger ifTrue: [0] ifFalse: [anInteger])! ! !Browser methodsFor: 'code pane' stamp: 'asm 6/25/2003 22:48'! compileMessage: aText notifying: aController "Compile the code that was accepted by the user, placing the compiled method into an appropriate message category. Return true if the compilation succeeded, else false." | fallBackCategoryIndex fallBackMethodIndex originalSelectorName result | self selectedMessageCategoryName ifNil: [ self selectOriginalCategoryForCurrentMethod ifFalse:["Select the '--all--' category" self messageCategoryListIndex: 1]]. self selectedMessageCategoryName asSymbol = ClassOrganizer allCategory ifTrue: [ "User tried to save a method while the ALL category was selected" fallBackCategoryIndex _ messageCategoryListIndex. fallBackMethodIndex _ messageListIndex. editSelection == #newMessage ifTrue: [ "Select the 'as yet unclassified' category" messageCategoryListIndex _ 0. (result _ self defineMessageFrom: aText notifying: aController) ifNil: ["Compilation failure: reselect the original category & method" messageCategoryListIndex _ fallBackCategoryIndex. messageListIndex _ fallBackMethodIndex] ifNotNil: [self setSelector: result]] ifFalse: [originalSelectorName _ self selectedMessageName. self setOriginalCategoryIndexForCurrentMethod. messageListIndex _ fallBackMethodIndex _ self messageList indexOf: originalSelectorName. (result _ self defineMessageFrom: aText notifying: aController) ifNotNil: [self setSelector: result] ifNil: [ "Compilation failure: reselect the original category & method" messageCategoryListIndex _ fallBackCategoryIndex. messageListIndex _ fallBackMethodIndex. ^ result notNil]]. self changed: #messageCategoryList. ^ result notNil] ifFalse: [ "User tried to save a method while the ALL category was NOT selected" ^ (self defineMessageFrom: aText notifying: aController) notNil]! ! !Browser methodsFor: 'code pane' stamp: 'sw 5/18/2001 20:55'! showBytecodes "Show or hide the bytecodes of the selected method -- an older protocol now mostly not relevant." self toggleShowingByteCodes! ! !Browser methodsFor: 'copying' stamp: 'tk 12/5/1999 17:59'! veryDeepInner: deepCopier "Copy all of my instance variables. Some need to be not copied at all, but shared. See DeepCopier class comment." super veryDeepInner: deepCopier. "systemOrganizer _ systemOrganizer. clone has the old value. we share it" "classOrganizer _ classOrganizer clone has the old value. we share it" "metaClassOrganizer _ metaClassOrganizer clone has the old value. we share it" systemCategoryListIndex _ systemCategoryListIndex veryDeepCopyWith: deepCopier. classListIndex _ classListIndex veryDeepCopyWith: deepCopier. messageCategoryListIndex _ messageCategoryListIndex veryDeepCopyWith: deepCopier. messageListIndex _ messageListIndex veryDeepCopyWith: deepCopier. editSelection _ editSelection veryDeepCopyWith: deepCopier. metaClassIndicated _ metaClassIndicated veryDeepCopyWith: deepCopier. ! ! !Browser methodsFor: 'drag and drop' stamp: 'mir 5/25/2000 13:08'! acceptMethod: methodSel dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel dstClass: dstClass dstClassOrMeta: dstClassOrMeta srcClassOrMeta: srcClassOrMeta internal: internal copySemantic: copyFlag | success hierarchyChange higher checkForOverwrite | (success _ dstClassOrMeta ~~ nil) ifFalse: [^false]. checkForOverwrite _ dstClassOrMeta selectors includes: methodSel. hierarchyChange _ (higher _ srcClassOrMeta inheritsFrom: dstClassOrMeta) | (dstClassOrMeta inheritsFrom: srcClassOrMeta). success _ (checkForOverwrite not or: [self overwriteDialogHierarchyChange: hierarchyChange higher: higher sourceClassName: srcClassOrMeta name destinationClassName: dstClassOrMeta name methodSelector: methodSel]) and: [self message: methodSel compileInClass: dstClassOrMeta fromClass: srcClassOrMeta dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel internal: internal copySemantic: copyFlag]. ^ success! ! !Browser methodsFor: 'drag and drop' stamp: 'mir 5/25/2000 13:27'! acceptMethod: methodSel messageCategory: srcMessageCategorySel class: srcClassOrMeta atListMorph: dstListMorph internal: internal copy: copyFlag | success dstClassOrMeta dstClass dstMessageCategorySel | dstClass _ self dstClassDstListMorph: dstListMorph. dstClassOrMeta _ dstClass ifNotNil: [self metaClassIndicated ifTrue: [dstClass class] ifFalse: [dstClass]]. dstMessageCategorySel _ self dstMessageCategoryDstListMorph: dstListMorph. success _ (dstClassOrMeta notNil and: [dstClassOrMeta == srcClassOrMeta]) ifTrue: ["one class" self changeMessageCategoryForMethod: methodSel dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel insideClassOrMeta: dstClassOrMeta internal: internal copySemantic: copyFlag] ifFalse: ["different classes" self acceptMethod: methodSel dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel dstClass: dstClass dstClassOrMeta: dstClassOrMeta srcClassOrMeta: srcClassOrMeta internal: internal copySemantic: copyFlag]. ^ success! ! !Browser methodsFor: 'drag and drop' stamp: 'mir 5/25/2000 13:27'! changeCategoryForClass: class srcSystemCategory: srcSystemCategorySel atListMorph: dstListMorph internal: internal copy: copyFlag "only move semantic" | newClassCategory success | self flag: #stringSymbolProblem. success _ copyFlag not ifFalse: [^ false]. newClassCategory _ self dstCategoryDstListMorph: dstListMorph. (success _ newClassCategory notNil & (newClassCategory ~= class category)) ifTrue: [class category: newClassCategory. self changed: #classList. internal ifFalse: [self selectClass: class]]. ^ success! ! !Browser methodsFor: 'drag and drop' stamp: 'mir 5/23/2000 17:27'! changeMessageCategoryForMethod: methodSel dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel insideClassOrMeta: classOrMeta internal: internal copySemantic: copyFlag "only move semantic" | success messageCategorySel | (success _ copyFlag not) ifFalse: [^ false]. messageCategorySel _ dstMessageCategorySel ifNil: [srcMessageCategorySel]. (success _ messageCategorySel notNil & (messageCategorySel ~= '-- all --' asSymbol) and: [messageCategorySel ~= srcMessageCategorySel and: [classOrMeta organization categories includes: messageCategorySel]]) ifTrue: [classOrMeta organization classify: methodSel under: messageCategorySel suppressIfDefault: false. self changed: #messageList]. success & internal not ifTrue: [self setSelector: methodSel]. ^ success! ! !Browser methodsFor: 'drag and drop' stamp: 'ls 6/22/2001 23:21'! dstCategoryDstListMorph: dstListMorph ^(dstListMorph getListSelector == #systemCategoryList) ifTrue: [dstListMorph potentialDropItem ] ifFalse: [self selectedSystemCategoryName]! ! !Browser methodsFor: 'drag and drop' stamp: 'ls 6/22/2001 23:20'! dstClassDstListMorph: dstListMorph | dropItem | ^(dstListMorph getListSelector == #classList) ifTrue: [(dropItem _ dstListMorph potentialDropItem) ifNotNil: [Smalltalk at: dropItem withBlanksCondensed asSymbol]] ifFalse: [dstListMorph model selectedClass]! ! !Browser methodsFor: 'drag and drop' stamp: 'nk 6/13/2004 06:16'! dstMessageCategoryDstListMorph: dstListMorph | dropItem | ^dstListMorph getListSelector == #messageCategoryList ifTrue: [dropItem _ dstListMorph potentialDropItem. dropItem ifNotNil: [dropItem asSymbol]] ifFalse: [self selectedMessageCategoryName ifNil: [ Categorizer default ]]! ! !Browser methodsFor: 'drag and drop' stamp: 'mir 5/25/2000 13:47'! message: messageSel compileInClass: dstClassOrMeta fromClass: srcClassOrMeta dstMessageCategory: dstMessageCategorySel srcMessageCategory: srcMessageCategorySel internal: internal copySemantic: copyFlag | source messageCategorySel tm success oldOrNoMethod newMethod | source _ srcClassOrMeta sourceCodeAt: messageSel. messageCategorySel _ dstMessageCategorySel ifNil: [srcMessageCategorySel]. self selectClass: dstClassOrMeta theNonMetaClass. (self messageCategoryList includes: messageCategorySel) ifFalse: ["create message category" self classOrMetaClassOrganizer addCategory: messageCategorySel]. self selectMessageCategoryNamed: messageCategorySel. tm _ self codeTextMorph. tm setText: source. tm setSelection: (0 to: 0). tm hasUnacceptedEdits: true. oldOrNoMethod _ srcClassOrMeta compiledMethodAt: messageSel ifAbsent: []. tm accept. "compilation successful?" newMethod _ dstClassOrMeta compiledMethodAt: messageSel ifAbsent: []. success _ newMethod ~~ nil & (newMethod ~~ oldOrNoMethod). " success ifFalse: [TransferMorph allInstances do: [:e | e delete]]. " success ifTrue: [copyFlag not ifTrue: ["remove old method in move semantic if new exists" srcClassOrMeta removeSelector: messageSel].internal ifTrue: [self selectClass: srcClassOrMeta] ifFalse: [self selectClass: dstClassOrMeta]. self setSelector: messageSel]. ^ success! ! !Browser methodsFor: 'drag and drop'! overwriteDialogHierarchyChange: hierarchyChange higher: higherFlag sourceClassName: srcClassName destinationClassName: dstClassName methodSelector: methodSelector | lf success | lf _ Character cr asString. success _ SelectionMenu confirm: 'There is a conflict.' , ' Overwrite' , (hierarchyChange ifTrue: [higherFlag ifTrue: [' superclass'] ifFalse: [' subclass']] ifFalse: ['']) , ' method' , lf , dstClassName , '>>' , methodSelector , lf , 'by ' , (hierarchyChange ifTrue: ['moving'] ifFalse: ['copying']) , ' method' , lf , srcClassName name , '>>' , methodSelector , ' ?' trueChoice: 'Yes, don''t care.' falseChoice: 'No, I have changed my opinion.'. ^ success! ! !Browser methodsFor: 'initialize-release' stamp: 'rww 8/18/2002 09:31'! browseSelectionInPlace "In place code - incomplete" " self systemCategoryListIndex: (self systemCategoryList indexOf: self selectedClass category). self classListIndex: (self classList indexOf: self selectedClass name)" self spawnHierarchy.! ! !Browser methodsFor: 'initialize-release'! browserWindowActivated "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"! ! !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 15:22'! buildClassSwitchView | aSwitchView | aSwitchView _ PluggableButtonView on: self getState: #classMessagesIndicated action: #indicateClassMessages. aSwitchView label: 'class'; window: (0@0 extent: 15@8); askBeforeChanging: true. ^ aSwitchView ! ! !Browser methodsFor: 'initialize-release' stamp: 'di 4/13/1999 13:54'! buildCommentSwitchView | aSwitchView | aSwitchView _ PluggableButtonView on: self getState: #classCommentIndicated action: #plusButtonHit. aSwitchView label: '?' asText allBold; borderWidthLeft: 0 right: 1 top: 0 bottom: 0; window: (0@0 extent: 10@8); askBeforeChanging: true. ^ aSwitchView ! ! !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 16:11'! buildInstanceClassSwitchView | aView aSwitchView instSwitchView comSwitchView | aView _ View new model: self. aView window: (0 @ 0 extent: 50 @ 8). instSwitchView _ self buildInstanceSwitchView. aView addSubView: instSwitchView. comSwitchView _ self buildCommentSwitchView. aView addSubView: comSwitchView toRightOf: instSwitchView. aSwitchView _ self buildClassSwitchView. aView addSubView: aSwitchView toRightOf: comSwitchView. ^aView! ! !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 16:10'! buildInstanceSwitchView | aSwitchView | aSwitchView _ PluggableButtonView on: self getState: #instanceMessagesIndicated action: #indicateInstanceMessages. aSwitchView label: 'instance'; borderWidthLeft: 0 right: 1 top: 0 bottom: 0; window: (0@0 extent: 25@8); askBeforeChanging: true. ^ aSwitchView ! ! !Browser methodsFor: 'initialize-release' stamp: 'sw 1/4/2001 15:55'! buildOptionalButtonsView "Build the view for the optional buttons (mvc)" | aView buttonView offset bWidth bHeight first previousView | aView _ View new model: self. bHeight _ self optionalButtonHeight. aView window: (0 @ 0 extent: 200 @ bHeight). offset _ 0. first _ true. previousView _ nil. self optionalButtonPairs do: [:pair | buttonView _ PluggableButtonView on: self getState: nil action: pair second. buttonView label: pair first asParagraph. bWidth _ buttonView label boundingBox width // 2. "Need something more deterministic." buttonView window: (offset@0 extent: bWidth@bHeight). offset _ offset + bWidth + 0. first ifTrue: [aView addSubView: buttonView. first _ false] ifFalse: [buttonView borderWidthLeft: 1 right: 0 top: 0 bottom: 0. aView addSubView: buttonView toRightOf: previousView]. previousView _ buttonView]. ^ aView! ! !Browser methodsFor: 'initialize-release' stamp: 'sw 1/13/2000 16:45'! defaultBrowserTitle ^ 'System Browser'! ! !Browser methodsFor: 'initialize-release' stamp: 'ar 1/31/2001 20:56'! highlightClassList: list with: morphList! ! !Browser methodsFor: 'initialize-release' stamp: 'ar 1/31/2001 20:56'! highlightMessageCategoryList: list with: morphList! ! !Browser methodsFor: 'initialize-release' stamp: 'ar 1/31/2001 20:56'! highlightSystemCategoryList: list with: morphList! ! !Browser methodsFor: 'initialize-release' stamp: 'nk 2/13/2001 13:25'! labelString ^self selectedClass ifNil: [ self defaultBrowserTitle ] ifNotNil: [ self defaultBrowserTitle, ': ', self selectedClass printString ]. ! ! !Browser methodsFor: 'initialize-release' stamp: 'sw 9/22/1999 17:13'! methodCategoryChanged self changed: #messageCategoryList. self changed: #messageList. self changed: #annotation. self messageListIndex: 0! ! !Browser methodsFor: 'initialize-release' stamp: 'BG 10/30/2003 21:09'! openEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers." | systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView underPane y optionalButtonsView annotationPane | topView _ StandardSystemView new model: self. topView borderWidth: 1. "label and minSize taken care of by caller" systemCategoryListView _ PluggableListView on: self list: #systemCategoryList selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex: menu: #systemCategoryMenu: keystroke: #systemCatListKey:from:. systemCategoryListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: systemCategoryListView. classListView _ PluggableListView on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 50 @ 62). topView addSubView: classListView toRightOf: systemCategoryListView. switchView _ self buildInstanceClassSwitchView. switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView controller terminateDuringSelect: true. messageCategoryListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView window: (0 @ 0 extent: 50 @ 70). messageListView menuTitleSelector: #messageListSelectorTitle. topView addSubView: messageListView toRightOf: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: systemCategoryListView. underPane _ annotationPane. y _ 110 - self optionalAnnotationHeight] ifFalse: [ underPane _ systemCategoryListView. y _ 110]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(systemCategoryList classList messageCategoryList messageList). ^ topView! ! !Browser methodsFor: 'initialize-release' stamp: 'BG 10/30/2003 21:09'! openMessageCatEditString: aString "Create a pluggable version of the views for a Browser that just shows one message category." | messageCategoryListView messageListView browserCodeView topView annotationPane underPane y optionalButtonsView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" messageCategoryListView _ PluggableListView on: self list: #messageCatListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageCategoryMenu:. messageCategoryListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: messageCategoryListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView menuTitleSelector: #messageListSelectorTitle. messageListView window: (0 @ 0 extent: 200 @ 70). topView addSubView: messageListView below: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: messageListView. underPane _ annotationPane. y _ (200 - 12 - 70) - self optionalAnnotationHeight] ifFalse: [underPane _ messageListView. y _ (200 - 12 - 70)]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(messageCatListSingleton messageList). ^ topView! ! !Browser methodsFor: 'initialize-release' stamp: 'BG 10/28/2003 20:45'! openMessageEditString: aString "Create a pluggable version of the views for a Browser that just shows one message." | messageListView browserCodeView topView annotationPane underPane y | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" messageListView _ PluggableListView on: self list: #messageListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageListMenu:shifted:. messageListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: messageListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: messageListView. underPane _ annotationPane. y _ (200 - 12) - self optionalAnnotationHeight] ifFalse: [underPane _ messageListView. y _ 200 - 12]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. ^ topView! ! !Browser methodsFor: 'initialize-release' stamp: 'BG 10/28/2003 20:45'! openOnClassWithEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers." | classListView messageCategoryListView messageListView browserCodeView topView switchView annotationPane underPane y optionalButtonsView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" classListView _ PluggableListView on: self list: #classListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 100 @ 12). topView addSubView: classListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView window: (0 @ 0 extent: 100 @ 70). topView addSubView: messageCategoryListView below: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView menuTitleSelector: #messageListSelectorTitle. messageListView window: (0 @ 0 extent: 100 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. switchView _ self buildInstanceClassSwitchView. switchView borderWidth: 1. switchView window: switchView window viewport: (classListView viewport topRight corner: messageListView viewport topRight). topView addSubView: switchView toRightOf: classListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: messageCategoryListView. underPane _ annotationPane. y _ (200-12-70) - self optionalAnnotationHeight] ifFalse: [underPane _ messageCategoryListView. y _ (200-12-70)]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(messageCategoryList messageList). ^ topView! ! !Browser methodsFor: 'initialize-release' stamp: 'BG 10/28/2003 20:45'! openSystemCatEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers. The top list view is of the currently selected system class category--a single item list." | systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView y annotationPane underPane optionalButtonsView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" systemCategoryListView _ PluggableListView on: self list: #systemCategorySingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #systemCatSingletonMenu: keystroke: #systemCatSingletonKey:from:. systemCategoryListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: systemCategoryListView. classListView _ PluggableListView on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 67 @ 62). topView addSubView: classListView below: systemCategoryListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView controller terminateDuringSelect: true. messageCategoryListView window: (0 @ 0 extent: 66 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. switchView _ self buildInstanceClassSwitchView. switchView window: switchView window viewport: (classListView viewport bottomLeft corner: messageCategoryListView viewport bottomLeft). switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView menuTitleSelector: #messageListSelectorTitle. messageListView window: (0 @ 0 extent: 67 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: switchView. y _ 110 - 12 - self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [y _ 110 - 12. underPane _ switchView]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(classList messageCategoryList messageList). ^ topView! ! !Browser methodsFor: 'initialize-release' stamp: 'sbw 12/8/1999 12:37'! optionalAnnotationHeight ^ 10! ! !Browser methodsFor: 'initialize-release' stamp: 'sbw 12/8/1999 12:23'! optionalButtonHeight ^ 10! ! !Browser methodsFor: 'initialize-release' stamp: 'rhi 5/12/2004 23:23'! setClass: aBehavior selector: aSymbol "Set the state of a new, uninitialized Browser." | isMeta aClass messageCatIndex | aBehavior ifNil: [^ self]. (aBehavior isKindOf: Metaclass) ifTrue: [ isMeta _ true. aClass _ aBehavior soleInstance] ifFalse: [ isMeta _ false. aClass _ aBehavior]. self selectCategoryForClass: aClass. self classListIndex: ( (SystemOrganization listAtCategoryNamed: self selectedSystemCategoryName) indexOf: aClass name). self metaClassIndicated: isMeta. aSymbol ifNil: [^ self]. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: (messageCatIndex > 0 ifTrue: [messageCatIndex + 1] ifFalse: [0]). messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ( (aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol).! ! !Browser methodsFor: 'initialize-release' stamp: 'sw 5/26/1999 23:46'! setSelector: aSymbol "Make the receiver point at the given selector, in the currently chosen class" | aClass messageCatIndex | aSymbol ifNil: [^ self]. (aClass _ self selectedClassOrMetaClass) ifNil: [^ self]. messageCatIndex _ aClass organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: messageCatIndex + 1. messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ((aClass organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol)! ! !Browser methodsFor: 'initialize-release' stamp: 'sw 11/8/1999 13:36'! systemCatSingletonKey: aChar from: aView ^ self messageListKey: aChar from: aView! ! !Browser methodsFor: 'initialize-release' stamp: 'rhi 5/12/2004 15:00'! systemOrganizer: aSystemOrganizer "Initialize the receiver as a perspective on the system organizer, aSystemOrganizer. Typically there is only one--the system variable SystemOrganization." contents _ nil. systemOrganizer _ aSystemOrganizer. systemCategoryListIndex _ 0. classListIndex _ 0. messageCategoryListIndex _ 0. messageListIndex _ 0. metaClassIndicated _ false. self setClassOrganizer. self editSelection: #none.! ! !Browser methodsFor: 'message category functions' stamp: 'mir 5/5/2000 16:02'! addCategory "Present a choice of categories or prompt for a new category name and add it before the current selection, or at the end if no current selection" | labels reject lines cats menuIndex oldIndex newName | self okToChange ifFalse: [^ self]. classListIndex = 0 ifTrue: [^ self]. labels _ OrderedCollection with: 'new...'. reject _ Set new. reject addAll: self selectedClassOrMetaClass organization categories; add: ClassOrganizer nullCategory; add: ClassOrganizer default. lines _ OrderedCollection new. self selectedClassOrMetaClass allSuperclasses do: [:cls | cls = Object ifFalse: [ cats _ cls organization categories reject: [:cat | reject includes: cat]. cats isEmpty ifFalse: [ lines add: labels size. labels addAll: cats asSortedCollection. reject addAll: cats]]]. newName _ (labels size = 1 or: [ menuIndex _ (PopUpMenu labelArray: labels lines: lines) startUpWithCaption: 'Add Category'. menuIndex = 0 ifTrue: [^ self]. menuIndex = 1]) ifTrue: [ self request: 'Please type new category name' initialAnswer: 'category name'] ifFalse: [ labels at: menuIndex]. oldIndex _ messageCategoryListIndex. newName isEmpty ifTrue: [^ self] ifFalse: [newName _ newName asSymbol]. self classOrMetaClassOrganizer addCategory: newName before: (messageCategoryListIndex = 0 ifTrue: [nil] ifFalse: [self selectedMessageCategoryName]). self changed: #messageCategoryList. self messageCategoryListIndex: (oldIndex = 0 ifTrue: [self classOrMetaClassOrganizer categories size + 1] ifFalse: [oldIndex]). self changed: #messageCategoryList. ! ! !Browser methodsFor: 'message category functions' stamp: 'NS 4/7/2004 22:47'! alphabetizeMessageCategories classListIndex = 0 ifTrue: [^ false]. self okToChange ifFalse: [^ false]. self classOrMetaClassOrganizer sortCategories. self clearUserEditFlag. self editClass. self classListIndex: classListIndex. ^ true! ! !Browser methodsFor: 'message category functions'! buildMessageCategoryBrowser "Create and schedule a message category browser for the currently selected message category." self buildMessageCategoryBrowserEditString: nil! ! !Browser methodsFor: 'message category functions' stamp: 'nk 6/13/2004 07:21'! buildMessageCategoryBrowserEditString: aString "Create and schedule a message category browser for the currently selected message category. The initial text view contains the characters in aString." "wod 6/24/1998: set newBrowser classListIndex so that it works whether the receiver is a standard or a Hierarchy Browser." | newBrowser | messageCategoryListIndex ~= 0 ifTrue: [newBrowser _ Browser new. newBrowser systemCategoryListIndex: systemCategoryListIndex. newBrowser classListIndex: (newBrowser classList indexOf: self selectedClassName). newBrowser metaClassIndicated: metaClassIndicated. newBrowser messageCategoryListIndex: messageCategoryListIndex. newBrowser messageListIndex: messageListIndex. self class openBrowserView: (newBrowser openMessageCatEditString: aString) label: 'Message Category Browser (' , newBrowser selectedClassOrMetaClassName , ')']! ! !Browser methodsFor: 'message category functions' stamp: 'sw 10/8/2001 14:10'! canShowMultipleMessageCategories "Answer whether the receiver is capable of showing multiple message categories" ^ true! ! !Browser methodsFor: 'message category functions' stamp: 'sw 2/22/2001 06:54'! categoryOfCurrentMethod "Determine the method category associated with the receiver at the current moment, or nil if none" | aCategory | ^ super categoryOfCurrentMethod ifNil: [(aCategory _ self messageCategoryListSelection) == ClassOrganizer allCategory ifTrue: [nil] ifFalse: [aCategory]]! ! !Browser methodsFor: 'message category functions' stamp: 'NS 4/7/2004 22:56'! changeMessageCategories: aString "The characters in aString represent an edited version of the the message categories for the selected class. Update this information in the system and inform any dependents that the categories have been changed. This message is invoked because the user had issued the categories command and edited the message categories. Then the user issued the accept command." self classOrMetaClassOrganizer changeFromString: aString. self clearUserEditFlag. self editClass. self classListIndex: classListIndex. ^ true! ! !Browser methodsFor: 'message category functions' stamp: 'nk 2/14/2004 15:06'! editMessageCategories "Indicate to the receiver and its dependents that the message categories of the selected class have been changed." self okToChange ifFalse: [^ self]. classListIndex ~= 0 ifTrue: [self messageCategoryListIndex: 0. self editSelection: #editMessageCategories. self changed: #editMessageCategories. self contentsChanged]! ! !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'! fileOutMessageCategories "Print a description of the selected message category of the selected class onto an external file." Cursor write showWhile: [messageCategoryListIndex ~= 0 ifTrue: [self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName]]! ! !Browser methodsFor: 'message category functions' stamp: 'emm 5/30/2002 09:20'! highlightMessageList: list with: morphList "Changed by emm to add emphasis in case of breakpoint" morphList do:[:each | | classOrNil methodOrNil | classOrNil := self selectedClassOrMetaClass. methodOrNil := classOrNil isNil ifTrue:[nil] ifFalse:[classOrNil methodDictionary at: each contents ifAbsent:[]]. (methodOrNil notNil and:[methodOrNil hasBreakpoint]) ifTrue:[each contents: ((each contents ,' [break]') asText allBold)]]! ! !Browser methodsFor: 'message category functions' stamp: 'dew 9/20/2001 00:21'! messageCategoryMenu: aMenu ^ aMenu labels: 'browse printOut fileOut reorganize alphabetize remove empty categories categorize all uncategorized new category... rename... remove' lines: #(3 8) selections: #(buildMessageCategoryBrowser printOutMessageCategories fileOutMessageCategories editMessageCategories alphabetizeMessageCategories removeEmptyCategories categorizeAllUncategorizedMethods addCategory renameCategory removeMessageCategory) ! ! !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'! printOutMessageCategories "Print a description of the selected message category of the selected class onto an external file in Html format." Cursor write showWhile: [messageCategoryListIndex ~= 0 ifTrue: [self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName asHtml: true]]! ! !Browser methodsFor: 'message category functions' stamp: 'nk 4/23/2004 09:18'! removeEmptyCategories self okToChange ifFalse: [^ self]. self selectedClassOrMetaClass organization removeEmptyCategories. self changed: #messageCategoryList ! ! !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:54'! removeMessageCategory "If a message category is selected, create a Confirmer so the user can verify that the currently selected message category should be removed from the system. If so, remove it." | messageCategoryName | messageCategoryListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. messageCategoryName _ self selectedMessageCategoryName. (self messageList size = 0 or: [self confirm: 'Are you sure you want to remove this method category and all its methods?']) ifTrue: [self selectedClassOrMetaClass removeCategory: messageCategoryName. self messageCategoryListIndex: 0. self changed: #classSelectionChanged]. self changed: #messageCategoryList. ! ! !Browser methodsFor: 'message category functions' stamp: 'NS 4/7/2004 23:01'! renameCategory "Prompt for a new category name and add it before the current selection, or at the end if no current selection" | oldIndex oldName newName | classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. (oldIndex _ messageCategoryListIndex) = 0 ifTrue: [^ self]. oldName _ self selectedMessageCategoryName. newName _ self request: 'Please type new category name' initialAnswer: oldName. newName isEmpty ifTrue: [^ self] ifFalse: [newName _ newName asSymbol]. newName = oldName ifTrue: [^ self]. self classOrMetaClassOrganizer renameCategory: oldName toBe: newName. self classListIndex: classListIndex. self messageCategoryListIndex: oldIndex. self changed: #messageCategoryList. ! ! !Browser methodsFor: 'message category functions' stamp: 'sw 10/8/2001 15:08'! showHomeCategory "Show the home category of the selected method. This is only really useful if one is in a tool that supports the showing of categories. Thus, it's good in browsers and hierarchy browsers but not in message-list browsers" | aSelector | self okToChange ifTrue: [(aSelector _ self selectedMessageName) ifNotNil: [self selectOriginalCategoryForCurrentMethod. self selectedMessageName: aSelector]]! ! !Browser methodsFor: 'message category list' stamp: 'nk 11/30/2002 08:20'! categorizeAllUncategorizedMethods "Categorize methods by looking in parent classes for a method category." | organizer organizers | organizer _ self classOrMetaClassOrganizer. organizers _ self selectedClassOrMetaClass withAllSuperclasses collect: [:ea | ea organization]. (organizer listAtCategoryNamed: ClassOrganizer default) do: [:sel | | found | found _ (organizers collect: [ :org | org categoryOfElement: sel]) detect: [:ea | ea ~= ClassOrganizer default and: [ ea ~= nil]] ifNone: []. found ifNotNil: [organizer classify: sel under: found]]. self changed: #messageCategoryList! ! !Browser methodsFor: 'message category list' stamp: 'tk 4/5/98 12:25'! messageCatListSingleton | name | name _ self selectedMessageCategoryName. ^ name ifNil: [Array new] ifNotNil: [Array with: name]! ! !Browser methodsFor: 'message category list' stamp: 'ccn 3/22/1999 17:56'! messageCategoryList "Answer the selected category of messages." classListIndex = 0 ifTrue: [^ Array new] ifFalse: [^ (Array with: ClassOrganizer allCategory), self classOrMetaClassOrganizer categories]! ! !Browser methodsFor: 'message category list'! messageCategoryListIndex "Answer the index of the selected message category." ^messageCategoryListIndex! ! !Browser methodsFor: 'message category list' stamp: 'rhi 5/12/2004 19:36'! messageCategoryListIndex: anInteger "Set the selected message category to be the one indexed by anInteger." messageCategoryListIndex _ anInteger. messageListIndex _ 0. self changed: #messageCategorySelectionChanged. self changed: #messageCategoryListIndex. "update my selection" self changed: #messageList. self editSelection: (anInteger > 0 ifTrue: [#newMessage] ifFalse: [self classListIndex > 0 ifTrue: [#editClass] ifFalse: [#newClass]]). contents _ nil. self contentsChanged.! ! !Browser methodsFor: 'message category list' stamp: 'ccn 3/24/1999 11:02'! messageCategoryListSelection "Return the selected category name or nil." ^ ((self messageCategoryList size = 0 or: [self messageCategoryListIndex = 0]) or: [self messageCategoryList size < self messageCategoryListIndex]) ifTrue: [nil] ifFalse: [self messageCategoryList at: (self messageCategoryListIndex max: 1)]! ! !Browser methodsFor: 'message category list' stamp: 'sw 10/16/1999 22:56'! rawMessageCategoryList ^ classListIndex = 0 ifTrue: [Array new] ifFalse: [self classOrMetaClassOrganizer categories]! ! !Browser methodsFor: 'message category list' stamp: 'nk 6/13/2004 06:20'! selectMessageCategoryNamed: aSymbol "Given aSymbol, select the category with that name. Do nothing if aSymbol doesn't exist." self messageCategoryListIndex: (self messageCategoryList indexOf: aSymbol ifAbsent: [ 1])! ! !Browser methodsFor: 'message category list' stamp: 'KLC 2/20/2004 08:08'! selectOriginalCategoryForCurrentMethod "private - Select the message category for the current method. Note: This should only be called when somebody tries to save a method that they are modifying while ALL is selected. Returns: true on success, false on failure." | aSymbol selectorName | aSymbol _ self categoryOfCurrentMethod. selectorName _ self selectedMessageName. (aSymbol notNil and: [aSymbol ~= ClassOrganizer allCategory]) ifTrue: [messageCategoryListIndex _ (self messageCategoryList indexOf: aSymbol). messageListIndex _ (self messageList indexOf: selectorName). self changed: #messageCategorySelectionChanged. self changed: #messageCategoryListIndex. "update my selection" self changed: #messageList. self changed: #messageListIndex. ^ true]. ^ false! ! !Browser methodsFor: 'message category list'! selectedMessageCategoryName "Answer the name of the selected message category, if any. Answer nil otherwise." messageCategoryListIndex = 0 ifTrue: [^nil]. ^self messageCategoryList at: messageCategoryListIndex! ! !Browser methodsFor: 'message category list' stamp: 'ccn+ceg 5/13/1999 19:54'! setOriginalCategoryIndexForCurrentMethod "private - Set the message category index for the currently selected method. Note: This should only be called when somebody tries to save a method that they are modifying while ALL is selected." messageCategoryListIndex _ self messageCategoryList indexOf: self categoryOfCurrentMethod ! ! !Browser methodsFor: 'message category list'! toggleMessageCategoryListIndex: anInteger "If the currently selected message category index is anInteger, deselect the category. Otherwise select the category whose index is anInteger." self messageCategoryListIndex: (messageCategoryListIndex = anInteger ifTrue: [0] ifFalse: [anInteger])! ! !Browser methodsFor: 'message functions' stamp: 'sw 1/11/2001 07:22'! addExtraShiftedItemsTo: aMenu "The shifted selector-list menu is being built; some menu items are appropriate only for certain kinds of browsers, and this gives a hook for them to be added as approrpiate. If any is added here, a line should be added first -- browse reimplementors of this message for examples." ! ! !Browser methodsFor: 'message functions'! buildMessageBrowser "Create and schedule a message browser on the currently selected message. Do nothing if no message is selected. The initial text view contains nothing." self buildMessageBrowserEditString: nil! ! !Browser methodsFor: 'message functions' stamp: 'sd 1/5/2002 21:11'! buildMessageBrowserEditString: aString "Create and schedule a message browser for the receiver in which the argument, aString, contains characters to be edited in the text view." messageListIndex = 0 ifTrue: [^ self]. ^ self class openMessageBrowserForClass: self selectedClassOrMetaClass selector: self selectedMessageName editString: aString! ! !Browser methodsFor: 'message functions' stamp: 'tk 4/25/1998 00:08'! defineMessage: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer true if compilation succeeds, false otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ self selectedClassOrMetaClass compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ false]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ true! ! !Browser methodsFor: 'message functions' stamp: 'di 11/24/1999 13:40'! defineMessageFrom: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer the selector obtained if compilation succeeds, nil otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ (Parser new parseSelector: aString). (self metaClassIndicated and: [(self selectedClassOrMetaClass includesSelector: selector) not and: [Metaclass isScarySelector: selector]]) ifTrue: ["A frist-time definition overlaps the protocol of Metaclasses" (self confirm: ((selector , ' is used in the existing class system. Overriding it could cause serious problems. Is this really what you want to do?') asText makeBoldFrom: 1 to: selector size)) ifFalse: [^nil]]. selector _ self selectedClassOrMetaClass compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ nil]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ selector! ! !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:02'! inspectInstances "Inspect all instances of the selected class. 1/26/96 sw" | myClass | myClass _ self selectedClassOrMetaClass. myClass ~~ nil ifTrue: [myClass theNonMetaClass inspectAllInstances]. ! ! !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:02'! inspectSubInstances "Inspect all instances of the selected class and all its subclasses 1/26/96 sw" | aClass | aClass _ self selectedClassOrMetaClass. aClass ~~ nil ifTrue: [aClass _ aClass theNonMetaClass. aClass inspectSubInstances]. ! ! !Browser methodsFor: 'message functions' stamp: 'BG 11/1/2003 13:27'! messageListMenu: aMenu shifted: shifted "Answer the message-list menu" shifted ifTrue: [^ self shiftedMessageListMenu: aMenu]. aMenu addList:#( ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' classHierarchy) ('browse method (O)' openSingleMessageBrowser) ('browse protocol (p)' browseFullProtocol) - ('fileOut (o)' fileOutMessage) ('printOut' printOutMessage) ('copy selector (c)' copySelector) - ('senders of... (n)' browseSendersOfMessages) ('implementors of... (m)' browseMessages) ('inheritance (i)' methodHierarchy) ('versions (v)' browseVersions) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' browseClassVarRefs) ('class variables' browseClassVariables) ('class refs (N)' browseClassRefs) - ('remove method (x)' removeMessage) - ('more...' shiftedYellowButtonActivity)). ^ aMenu! ! !Browser methodsFor: 'message functions' stamp: 'sd 5/11/2003 21:01'! removeMessage "If a message is selected, create a Confirmer so the user can verify that the currently selected message should be removed from the system. If so, remove it. If the Preference 'confirmMethodRemoves' is set to false, the confirmer is bypassed." | messageName confirmation | messageListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. messageName _ self selectedMessageName. confirmation _ self systemNavigation confirmRemovalOf: messageName on: self selectedClassOrMetaClass. confirmation == 3 ifTrue: [^ self]. self selectedClassOrMetaClass removeSelector: self selectedMessageName. self messageListIndex: 0. self changed: #messageList. self setClassOrganizer. "In case organization not cached" confirmation == 2 ifTrue: [self systemNavigation browseAllCallsOn: messageName]! ! !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:03'! removeMessageFromBrowser "Our list speaks the truth and can't have arbitrary things removed" ^ self changed: #flash! ! !Browser methodsFor: 'message functions' stamp: 'BG 11/1/2003 13:58'! shiftedMessageListMenu: aMenu "Fill aMenu with the items appropriate when the shift key is held down" aMenu addList: #( ('toggle diffing (D)' toggleDiffing) ('implementors of sent messages' browseAllMessages) - ('local senders of...' browseLocalSendersOfMessages) ('local implementors of...' browseLocalImplementors) - ('spawn sub-protocol' spawnProtocol) ('spawn full protocol' spawnFullProtocol) - ('sample instance' makeSampleInstance) ('inspect instances' inspectInstances) ('inspect subinstances' inspectSubInstances)). self addExtraShiftedItemsTo: aMenu. aMenu addList: #( - ('change category...' changeCategory)). self canShowMultipleMessageCategories ifTrue: [aMenu addList: #(('show category (C)' showHomeCategory))]. aMenu addList: #( - ('change sets with this method' findMethodInChangeSets) ('revert to previous version' revertToPreviousVersion) ('remove from current change set' removeFromCurrentChanges) ('revert & remove from changes' revertAndForget) ('add to current change set' adoptMessageInCurrentChangeset) ('copy up or copy down...' copyUpOrCopyDown) - ('more...' unshiftedYellowButtonActivity)). ^ aMenu ! ! !Browser methodsFor: 'message list' stamp: 'drs 1/1/2003 23:33'! messageList "Answer an Array of the message selectors of the currently selected message category, provided that the messageCategoryListIndex is in proper range. Otherwise, answer an empty Array If messageCategoryListIndex is found to be larger than the number of categories (it happens!!), it is reset to zero." | sel | (sel _ self messageCategoryListSelection) ifNil: [ ^ self classOrMetaClassOrganizer ifNil: [Array new] ifNotNil: [self classOrMetaClassOrganizer allMethodSelectors] "^ Array new" ]. ^ sel = ClassOrganizer allCategory ifTrue: [self classOrMetaClassOrganizer ifNil: [Array new] ifNotNil: [self classOrMetaClassOrganizer allMethodSelectors]] ifFalse: [(self classOrMetaClassOrganizer listAtCategoryNumber: messageCategoryListIndex - 1) ifNil: [messageCategoryListIndex _ 0. Array new]]! ! !Browser methodsFor: 'message list'! messageListIndex "Answer the index of the selected message selector into the currently selected message category." ^messageListIndex! ! !Browser methodsFor: 'message list' stamp: 'rhi 5/12/2004 19:35'! messageListIndex: anInteger "Set the selected message selector to be the one indexed by anInteger." messageListIndex _ anInteger. self editSelection: (anInteger > 0 ifTrue: [#editMessage] ifFalse: [self messageCategoryListIndex > 0 ifTrue: [#newMessage] ifFalse: [self classListIndex > 0 ifTrue: [#editClass] ifFalse: [#newClass]]]). contents _ nil. self changed: #messageListIndex. "update my selection" self contentsChanged. self decorateButtons.! ! !Browser methodsFor: 'message list' stamp: 'tk 4/6/98 10:48'! messageListSingleton | name | name _ self selectedMessageName. ^ name ifNil: [Array new] ifNotNil: [Array with: name]! ! !Browser methodsFor: 'message list' stamp: 'sw 12/1/2000 11:17'! reformulateList "If the receiver has a way of reformulating its message list, here is a chance for it to do so" super reformulateList. self messageListIndex: 0! ! !Browser methodsFor: 'message list' stamp: 'nk 6/19/2004 16:44'! selectedMessage "Answer a copy of the source code for the selected message." | class selector method | contents == nil ifFalse: [^ contents copy]. self showingDecompile ifTrue: [^ self decompiledSourceIntoContentsWithTempNames: Sensor leftShiftDown not ]. class _ self selectedClassOrMetaClass. selector _ self selectedMessageName. method _ class compiledMethodAt: selector ifAbsent: [^ '']. "method deleted while in another project" currentCompiledMethod _ method. ^ contents _ (self showingDocumentation ifFalse: [ self sourceStringPrettifiedAndDiffed ] ifTrue: [ self commentContents ]) copy asText makeSelectorBoldIn: class! ! !Browser methodsFor: 'message list' stamp: 'sw 8/26/2002 09:55'! selectedMessageName "Answer the message selector of the currently selected message, if any. Answer nil otherwise." | aList | editSelection == #editComment ifTrue: [^ #Comment]. editSelection == #editClass ifTrue: [^ #Definition]. messageListIndex = 0 ifTrue: [^ nil]. ^ (aList _ self messageList) size >= messageListIndex ifTrue: [aList at: messageListIndex] ifFalse: [nil]! ! !Browser methodsFor: 'message list' stamp: 'sw 10/8/2001 13:37'! selectedMessageName: aSelector "Make the given selector be the selected message name" | anIndex | anIndex _ self messageList indexOf: aSelector. anIndex > 0 ifTrue: [self messageListIndex: anIndex]! ! !Browser methodsFor: 'message list'! toggleMessageListIndex: anInteger "If the currently selected message index is anInteger, deselect the message selector. Otherwise select the message selector whose index is anInteger." self messageListIndex: (messageListIndex = anInteger ifTrue: [0] ifFalse: [anInteger])! ! !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 12:25'! classCommentIndicated "Answer true iff we're viewing the class comment." ^ editSelection == #editComment ! ! !Browser methodsFor: 'metaclass' stamp: 'ak 11/24/2000 21:46'! classMessagesIndicated "Answer whether the messages to be presented should come from the metaclass." ^ self metaClassIndicated and: [self classCommentIndicated not]! ! !Browser methodsFor: 'metaclass'! classOrMetaClassOrganizer "Answer the class organizer for the metaclass or class, depending on which (instance or class) is indicated." self metaClassIndicated ifTrue: [^metaClassOrganizer] ifFalse: [^classOrganizer]! ! !Browser methodsFor: 'metaclass'! indicateClassMessages "Indicate that the message selection should come from the metaclass messages." self metaClassIndicated: true! ! !Browser methodsFor: 'metaclass'! indicateInstanceMessages "Indicate that the message selection should come from the class (instance) messages." self metaClassIndicated: false! ! !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 13:20'! instanceMessagesIndicated "Answer whether the messages to be presented should come from the class." ^metaClassIndicated not and: [self classCommentIndicated not]! ! !Browser methodsFor: 'metaclass' stamp: 'sr 6/21/2000 17:23'! metaClassIndicated "Answer the boolean flag that indicates which of the method dictionaries, class or metaclass." ^ metaClassIndicated! ! !Browser methodsFor: 'metaclass' stamp: 'nk 2/14/2004 15:08'! metaClassIndicated: trueOrFalse "Indicate whether browsing instance or class messages." metaClassIndicated _ trueOrFalse. self setClassOrganizer. systemCategoryListIndex > 0 ifTrue: [self editSelection: (classListIndex = 0 ifTrue: [metaClassIndicated ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. messageCategoryListIndex _ 0. messageListIndex _ 0. contents _ nil. self changed: #classSelectionChanged. self changed: #messageCategoryList. self changed: #messageList. self changed: #contents. self changed: #annotation. self decorateButtons ! ! !Browser methodsFor: 'metaclass' stamp: 'tk 4/9/98 10:48'! selectedClassOrMetaClass "Answer the selected class or metaclass." | cls | self metaClassIndicated ifTrue: [^ (cls _ self selectedClass) ifNil: [nil] ifNotNil: [cls class]] ifFalse: [^ self selectedClass]! ! !Browser methodsFor: 'metaclass'! selectedClassOrMetaClassName "Answer the selected class name or metaclass name." ^self selectedClassOrMetaClass name! ! !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 13:27'! setClassOrganizer "Install whatever organization is appropriate" | theClass | classOrganizer _ nil. metaClassOrganizer _ nil. classListIndex = 0 ifTrue: [^ self]. classOrganizer _ (theClass _ self selectedClass) organization. metaClassOrganizer _ theClass class organization.! ! !Browser methodsFor: 'system category functions' stamp: 'je 4/30/2001 17:59'! addSystemCategory "Prompt for a new category name and add it before the current selection, or at the end if no current selection" | oldIndex newName | self okToChange ifFalse: [^ self]. oldIndex _ systemCategoryListIndex. newName _ self request: 'Please type new category name' initialAnswer: 'Category-Name'. newName isEmpty ifTrue: [^ self] ifFalse: [newName _ newName asSymbol]. systemOrganizer addCategory: newName before: (systemCategoryListIndex = 0 ifTrue: [nil] ifFalse: [self selectedSystemCategoryName]). self systemCategoryListIndex: (oldIndex = 0 ifTrue: [self systemCategoryList size] ifFalse: [oldIndex]). self changed: #systemCategoryList.! ! !Browser methodsFor: 'system category functions' stamp: 'brp 8/4/2003 21:38'! alphabetizeSystemCategories self okToChange ifFalse: [^ false]. systemOrganizer sortCategories. self systemCategoryListIndex: 0. self changed: #systemCategoryList. ! ! !Browser methodsFor: 'system category functions' stamp: 'sd 1/5/2002 21:11'! browseAllClasses "Create and schedule a new browser on all classes alphabetically." | newBrowser | newBrowser _ HierarchyBrowser new initAlphabeticListing. self class openBrowserView: (newBrowser openSystemCatEditString: nil) label: 'All Classes Alphabetically'! ! !Browser methodsFor: 'system category functions'! buildSystemCategoryBrowser "Create and schedule a new system category browser." self buildSystemCategoryBrowserEditString: nil! ! !Browser methodsFor: 'system category functions' stamp: 'sd 1/5/2002 21:12'! buildSystemCategoryBrowserEditString: aString "Create and schedule a new system category browser with initial textual contents set to aString." | newBrowser | systemCategoryListIndex > 0 ifTrue: [newBrowser _ self class new. newBrowser systemCategoryListIndex: systemCategoryListIndex. newBrowser setClass: self selectedClassOrMetaClass selector: self selectedMessageName. self class openBrowserView: (newBrowser openSystemCatEditString: aString) label: 'Classes in category ', newBrowser selectedSystemCategoryName]! ! !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:21'! changeSystemCategories: aString "Update the class categories by parsing the argument aString." systemOrganizer changeFromString: aString. self changed: #systemCategoryList. ^ true! ! !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:43'! classNotFound self changed: #flash.! ! !Browser methodsFor: 'system category functions' stamp: 'nk 2/14/2004 15:09'! editSystemCategories "Retrieve the description of the class categories of the system organizer." self okToChange ifFalse: [^ self]. self systemCategoryListIndex: 0. self editSelection: #editSystemCategories. self changed: #editSystemCategories. self contentsChanged! ! !Browser methodsFor: 'system category functions' stamp: 'tk 3/31/98 07:52'! fileOutSystemCategory "Print a description of each class in the selected category onto a file whose name is the category name followed by .st." systemCategoryListIndex ~= 0 ifTrue: [systemOrganizer fileOutCategory: self selectedSystemCategoryName]! ! !Browser methodsFor: 'system category functions' stamp: 'stp 01/13/2000 12:26'! findClass "Search for a class by name." | pattern foundClass classNames index toMatch exactMatch potentialClassNames | self okToChange ifFalse: [^ self classNotFound]. pattern _ FillInTheBlank request: 'Class name or fragment?'. pattern isEmpty ifTrue: [^ self classNotFound]. toMatch _ (pattern copyWithout: $.) asLowercase. potentialClassNames _ self potentialClassNames asOrderedCollection. classNames _ pattern last = $. ifTrue: [potentialClassNames select: [:nm | nm asLowercase = toMatch]] ifFalse: [potentialClassNames select: [:n | n includesSubstring: toMatch caseSensitive: false]]. classNames isEmpty ifTrue: [^ self classNotFound]. exactMatch _ classNames detect: [:each | each asLowercase = toMatch] ifNone: [nil]. index _ classNames size = 1 ifTrue: [1] ifFalse: [exactMatch ifNil: [(PopUpMenu labelArray: classNames lines: #()) startUp] ifNotNil: [classNames addFirst: exactMatch. (PopUpMenu labelArray: classNames lines: #(1)) startUp]]. index = 0 ifTrue: [^ self classNotFound]. foundClass _ Smalltalk at: (classNames at: index) asSymbol. self selectCategoryForClass: foundClass. self selectClass: foundClass ! ! !Browser methodsFor: 'system category functions' stamp: 'sw 11/8/1999 10:04'! potentialClassNames "Answer the names of all the classes that could be viewed in this browser. This hook is provided so that HierarchyBrowsers can indicate their restricted subset. For generic Browsers, the entire list of classes known to Smalltalk is provided, though of course that really only is accurate in the case of full system browsers." ^ Smalltalk classNames! ! !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:46'! printOutSystemCategory "Print a description of each class in the selected category as Html." Cursor write showWhile: [systemCategoryListIndex ~= 0 ifTrue: [systemOrganizer fileOutCategory: self selectedSystemCategoryName asHtml: true ]] ! ! !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:55'! removeSystemCategory "If a class category is selected, create a Confirmer so the user can verify that the currently selected class category and all of its classes should be removed from the system. If so, remove it." systemCategoryListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. (self classList size = 0 or: [self confirm: 'Are you sure you want to remove this system category and all its classes?']) ifTrue: [systemOrganizer removeSystemCategory: self selectedSystemCategoryName. self systemCategoryListIndex: 0. self changed: #systemCategoryList]! ! !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:55'! renameSystemCategory "Prompt for a new category name and add it before the current selection, or at the end if no current selection" | oldIndex oldName newName | (oldIndex _ systemCategoryListIndex) = 0 ifTrue: [^ self]. "no selection" self okToChange ifFalse: [^ self]. oldName _ self selectedSystemCategoryName. newName _ self request: 'Please type new category name' initialAnswer: oldName. newName isEmpty ifTrue: [^ self] ifFalse: [newName _ newName asSymbol]. oldName = newName ifTrue: [^ self]. systemOrganizer renameCategory: oldName toBe: newName. self systemCategoryListIndex: oldIndex. self changed: #systemCategoryList.! ! !Browser methodsFor: 'system category functions' stamp: 'sw 11/8/1999 14:07'! systemCatSingletonMenu: aMenu ^ aMenu labels: 'browse all browse printOut fileOut update rename... remove' lines: #(2 4) selections: #(browseAllClasses buildSystemCategoryBrowser printOutSystemCategory fileOutSystemCategory updateSystemCategories renameSystemCategory removeSystemCategory) ! ! !Browser methodsFor: 'system category functions' stamp: 'brp 8/4/2003 21:32'! systemCategoryMenu: aMenu ^ aMenu labels: 'find class... (f) recent classes... (r) browse all browse printOut fileOut reorganize alphabetize update add item... rename... remove' lines: #(2 4 6 8) selections: #(findClass recent browseAllClasses buildSystemCategoryBrowser printOutSystemCategory fileOutSystemCategory editSystemCategories alphabetizeSystemCategories updateSystemCategories addSystemCategory renameSystemCategory removeSystemCategory )! ! !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:17'! updateSystemCategories "The class categories were changed in another browser. The receiver must reorganize its lists based on these changes." self okToChange ifFalse: [^ self]. self changed: #systemCategoryList! ! !Browser methodsFor: 'system category list' stamp: 'tk 5/4/1998 15:46'! indexIsOne "When used as a singleton list, index is always one" ^ 1! ! !Browser methodsFor: 'system category list' stamp: 'tk 5/4/1998 15:46'! indexIsOne: value "When used as a singleton list, can't change it" ^ self! ! !Browser methodsFor: 'system category list' stamp: 'stp 01/13/2000 12:25'! selectCategoryForClass: theClass self systemCategoryListIndex: (self systemCategoryList indexOf: theClass category) ! ! !Browser methodsFor: 'system category list' stamp: 'di 12/6/1999 20:11'! selectedEnvironment "Answer the name of the selected system category or nil." systemCategoryListIndex = 0 ifTrue: [^nil]. ^ Smalltalk environmentForCategory: self selectedSystemCategoryName! ! !Browser methodsFor: 'system category list'! selectedSystemCategoryName "Answer the name of the selected system category or nil." systemCategoryListIndex = 0 ifTrue: [^nil]. ^self systemCategoryList at: systemCategoryListIndex! ! !Browser methodsFor: 'system category list'! systemCategoryList "Answer the class categories modelled by the receiver." ^systemOrganizer categories! ! !Browser methodsFor: 'system category list'! systemCategoryListIndex "Answer the index of the selected class category." ^systemCategoryListIndex! ! !Browser methodsFor: 'system category list' stamp: 'nk 2/14/2004 15:06'! systemCategoryListIndex: anInteger "Set the selected system category index to be anInteger. Update all other selections to be deselected." systemCategoryListIndex _ anInteger. classListIndex _ 0. messageCategoryListIndex _ 0. messageListIndex _ 0. self editSelection: ( anInteger = 0 ifTrue: [#none] ifFalse: [#newClass]). metaClassIndicated _ false. self setClassOrganizer. contents _ nil. self changed: #systemCategorySelectionChanged. self changed: #systemCategoryListIndex. "update my selection" self changed: #classList. self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged! ! !Browser methodsFor: 'system category list' stamp: 'tk 4/3/98 10:30'! systemCategorySingleton | cat | cat _ self selectedSystemCategoryName. ^ cat ifNil: [Array new] ifNotNil: [Array with: cat]! ! !Browser methodsFor: 'system category list'! toggleSystemCategoryListIndex: anInteger "If anInteger is the current system category index, deselect it. Else make it the current system category selection." self systemCategoryListIndex: (systemCategoryListIndex = anInteger ifTrue: [0] ifFalse: [anInteger])! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Browser class instanceVariableNames: ''! !Browser class methodsFor: 'instance creation' stamp: 'sd 2/2/2004 13:50'! fullOnClass: aClass "Open a new full browser set to class." | brow | brow _ self new. brow setClass: aClass selector: nil. ^ self openBrowserView: (brow openEditString: nil) label: 'System Browser'! ! !Browser class methodsFor: 'instance creation' stamp: 'jcg 10/29/2003 23:11'! fullOnClass: aClass selector: aSelector "Open a new full browser set to class." | brow classToUse | classToUse _ Preferences browseToolClass. brow _ classToUse new. brow setClass: aClass selector: aSelector. ^ classToUse openBrowserView: (brow openEditString: nil) label: brow labelString! ! !Browser class methodsFor: 'instance creation' stamp: 'di 10/18/1999 22:03'! new ^super new systemOrganizer: SystemOrganization! ! !Browser class methodsFor: 'instance creation' stamp: 'jcg 10/29/2003 23:12'! newOnCategory: aCategory "Browse the system category of the given name. 7/13/96 sw" "Browser newOnCategory: 'Interface-Browser'" | newBrowser catList | newBrowser _ self new. catList _ newBrowser systemCategoryList. newBrowser systemCategoryListIndex: (catList indexOf: aCategory asSymbol ifAbsent: [^ self inform: 'No such category']). ^ self openBrowserView: (newBrowser openSystemCatEditString: nil) label: 'Classes in category ', aCategory ! ! !Browser class methodsFor: 'instance creation' stamp: 'tk 4/18/1998 16:28'! newOnClass: aClass "Open a new class browser on this class." ^ self newOnClass: aClass label: 'Class Browser: ', aClass name! ! !Browser class methodsFor: 'instance creation' stamp: 'jcg 10/29/2003 23:12'! newOnClass: aClass label: aLabel "Open a new class browser on this class." | newBrowser | newBrowser _ self new. newBrowser setClass: aClass selector: nil. ^ self openBrowserView: (newBrowser openOnClassWithEditString: nil) label: aLabel ! ! !Browser class methodsFor: 'instance creation' stamp: 'jcg 10/29/2003 23:12'! newOnClass: aClass selector: aSymbol "Open a new class browser on this class." | newBrowser | newBrowser _ self new. newBrowser setClass: aClass selector: aSymbol. ^ self openBrowserView: (newBrowser openOnClassWithEditString: nil) label: 'Class Browser: ', aClass name ! ! !Browser class methodsFor: 'instance creation' stamp: 'jcg 10/29/2003 23:11'! openBrowser "Create and schedule a BrowserView with default browser label. The view consists of five subviews, starting with the list view of system categories of SystemOrganization. The initial text view part is empty." | br | br := self new. ^ self openBrowserView: (br openEditString: nil) label: br defaultBrowserTitle. ! ! !Browser class methodsFor: 'instance creation' stamp: 'BG 10/30/2003 21:10'! openBrowserView: aBrowserView label: aString "Schedule aBrowserView, labelling the view aString." aBrowserView label: aString. aBrowserView minimumSize: 300 @ 200. aBrowserView subViews do: [:each | each controller]. aBrowserView controller open! ! !Browser class methodsFor: 'instance creation' stamp: 'sd 1/5/2002 21:10'! openMessageBrowserForClass: aBehavior selector: aSymbol editString: aString "Create and schedule a message browser for the class, aBehavior, in which the argument, aString, contains characters to be edited in the text view. These characters are the source code for the message selector aSymbol." | newBrowser | (newBrowser _ self new) setClass: aBehavior selector: aSymbol. ^ self openBrowserView: (newBrowser openMessageEditString: aString) label: newBrowser selectedClassOrMetaClassName , ' ' , newBrowser selectedMessageName ! ! !Browser class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:27'! initialize "Browser initialize" RecentClasses := OrderedCollection new. self registerInFlapsRegistry. ! ! !Browser class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:32'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(#Browser #prototypicalToolWindow 'Browser' 'A Browser is a tool that allows you to view all the code of all the classes in the system' ) forFlapNamed: 'Tools']! ! !Browser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:32'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! Switch subclass: #Button instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !Button commentStamp: '<historical>' prior: 0! I am a Switch that turns off automatically after being turned on, that is, I act like a push-button switch.! !Button methodsFor: 'state'! turnOff "Sets the state of the receiver to 'off'. The off action of the receiver is not executed." on _ false! ! !Button methodsFor: 'state'! turnOn "The receiver remains in the 'off' state'." self doAction: onAction. self doAction: offAction! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Button class instanceVariableNames: ''! !Button class methodsFor: 'instance creation'! newOn "Refer to the comment in Switch|newOn." self error: 'Buttons cannot be created in the on state'. ^nil! ! ArrayedCollection variableByteSubclass: #ByteArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !ByteArray commentStamp: '<historical>' prior: 0! I represent an ArrayedCollection whose elements are integers between 0 and 255. ! !ByteArray methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:47'! atAllPut: value "Fill the receiver with the given value" <primitive: 145> super atAllPut: value! ! !ByteArray methodsFor: 'accessing' stamp: 'ar 12/5/1998 14:52'! byteAt: index <primitive: 60> ^self at: index! ! !ByteArray methodsFor: 'accessing' stamp: 'ar 12/5/1998 14:52'! byteAt: index put: value <primitive: 61> ^self at: index put: value! ! !ByteArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 16:17'! byteSize ^self size! ! !ByteArray methodsFor: 'accessing' stamp: 'tk 3/13/2000 14:46'! bytesPerElement "Number of bytes in each item. This multiplied by (self size)*8 gives the number of bits stored." ^ 1! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:44'! longAt: index bigEndian: aBool "Return a 32bit integer quantity starting from the given byte index" | b0 b1 b2 w h | aBool ifTrue:[ b0 _ self at: index. b1 _ self at: index+1. b2 _ self at: index+2. w _ self at: index+3. ] ifFalse:[ w _ self at: index. b2 _ self at: index+1. b1 _ self at: index+2. b0 _ self at: index+3. ]. "Minimize LargeInteger arithmetic" h _ ((b0 bitAnd: 16r7F) - (b0 bitAnd: 16r80) bitShift: 8) + b1. b2 = 0 ifFalse:[w _ (b2 bitShift: 8) + w]. h = 0 ifFalse:[w _ (h bitShift: 16) + w]. ^w! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 8/2/2003 19:29'! longAt: index put: value bigEndian: aBool "Return a 32bit integer quantity starting from the given byte index" | b0 b1 b2 b3 | b0 _ value bitShift: -24. b0 _ (b0 bitAnd: 16r7F) - (b0 bitAnd: 16r80). b0 < 0 ifTrue:[b0 := 256 + b0]. b1 _ (value bitShift: -16) bitAnd: 255. b2 _ (value bitShift: -8) bitAnd: 255. b3 _ value bitAnd: 255. aBool ifTrue:[ self at: index put: b0. self at: index+1 put: b1. self at: index+2 put: b2. self at: index+3 put: b3. ] ifFalse:[ self at: index put: b3. self at: index+1 put: b2. self at: index+2 put: b1. self at: index+3 put: b0. ]. ^value! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:57'! shortAt: index bigEndian: aBool "Return a 16 bit integer quantity starting from the given byte index" | uShort | uShort _ self unsignedShortAt: index bigEndian: aBool. ^(uShort bitAnd: 16r7FFF) - (uShort bitAnd: 16r8000)! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/3/1998 14:20'! shortAt: index put: value bigEndian: aBool "Store a 16 bit integer quantity starting from the given byte index" self unsignedShortAt: index put: (value bitAnd: 16r7FFF) - (value bitAnd: -16r8000) bigEndian: aBool. ^value! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:49'! unsignedLongAt: index bigEndian: aBool "Return a 32bit unsigned integer quantity starting from the given byte index" | b0 b1 b2 w | aBool ifTrue:[ b0 _ self at: index. b1 _ self at: index+1. b2 _ self at: index+2. w _ self at: index+3. ] ifFalse:[ w _ self at: index. b2 _ self at: index+1. b1 _ self at: index+2. b0 _ self at: index+3. ]. "Minimize LargeInteger arithmetic" b2 = 0 ifFalse:[w _ (b2 bitShift: 8) + w]. b1 = 0 ifFalse:[w _ (b1 bitShift: 16) + w]. b0 = 0 ifFalse:[w _ (b0 bitShift: 24) + w]. ^w! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:49'! unsignedLongAt: index put: value bigEndian: aBool "Store a 32bit unsigned integer quantity starting from the given byte index" | b0 b1 b2 b3 | b0 _ value bitShift: -24. b1 _ (value bitShift: -16) bitAnd: 255. b2 _ (value bitShift: -8) bitAnd: 255. b3 _ value bitAnd: 255. aBool ifTrue:[ self at: index put: b0. self at: index+1 put: b1. self at: index+2 put: b2. self at: index+3 put: b3. ] ifFalse:[ self at: index put: b3. self at: index+1 put: b2. self at: index+2 put: b1. self at: index+3 put: b0. ]. ^value! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:51'! unsignedShortAt: index bigEndian: aBool "Return a 16 bit unsigned integer quantity starting from the given byte index" ^aBool ifTrue:[((self at: index) bitShift: 8) + (self at: index+1)] ifFalse:[((self at: index+1) bitShift: 8) + (self at: index)].! ! !ByteArray methodsFor: 'platform independent access' stamp: 'ar 11/1/1998 20:53'! unsignedShortAt: index put: value bigEndian: aBool "Store a 16 bit unsigned integer quantity starting from the given byte index" aBool ifTrue:[ self at: index put: (value bitShift: -8). self at: index+1 put: (value bitAnd: 255). ] ifFalse:[ self at: index+1 put: (value bitShift: -8). self at: index put: (value bitAnd: 255). ]. ^value! ! !ByteArray methodsFor: 'converting' stamp: 'sma 5/12/2000 17:35'! asByteArray ^ self! ! !ByteArray methodsFor: 'converting'! asString "Convert to a String with Characters for each byte. Fast code uses primitive that avoids character conversion" ^ (String new: self size) replaceFrom: 1 to: self size with: self! ! !ByteArray methodsFor: 'private'! defaultElement ^0! ! !ByteArray methodsFor: 'private'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> super replaceFrom: start to: stop with: replacement startingAt: repStart! ! !ByteArray methodsFor: 'comparing' stamp: 'SqR 8/13/2002 10:52'! hash "#hash is implemented, because #= is implemented" ^self class hashBytes: self startingWith: self species hash! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ByteArray class instanceVariableNames: ''! !ByteArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:13'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asCharPtrFrom: anInteger on: aStream! ! !ByteArray class methodsFor: 'plugin generation' stamp: 'acg 9/19/1999 00:25'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asCharPtrFrom: anInteger andThen: (cg ccgValBlock: 'isBytes')! ! !ByteArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:13'! ccgDeclareCForVar: aSymbolOrString ^'char *', aSymbolOrString! ! !ByteArray class methodsFor: 'byte based hash' stamp: 'SqR 8/21/2002 16:21'! hashBytes: aByteArray startingWith: speciesHash "Answer the hash of a byte-indexed collection, using speciesHash as the initial value. See SmallInteger>>hashMultiply. The primitive should be renamed at a suitable point in the future" | byteArraySize hash low | <primitive: 'primitiveStringHash' module: 'MiscPrimitivePlugin'> self var: #aHash declareC: 'int speciesHash'. self var: #aByteArray declareC: 'unsigned char *aByteArray'. byteArraySize _ aByteArray size. hash _ speciesHash bitAnd: 16rFFFFFFF. 1 to: byteArraySize do: [:pos | hash _ hash + (aByteArray basicAt: pos). "Begin hashMultiply" low _ hash bitAnd: 16383. hash _ (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF. ]. ^ hash! ! Model subclass: #CPUWatcher instanceVariableNames: 'tally watcher threshold' classVariableNames: 'CurrentCPUWatcher' poolDictionaries: '' category: 'Tools-Process Browser'! !CPUWatcher commentStamp: '<historical>' prior: 0! CPUWatcher implements a simple runaway process monitoring tool that will suspend a process that is taking up too much of Squeak's time and allow user interaction. By default it watches for a Process that is taking more than 80% of the time; this threshold can be changed. CPUWatcher can also be used to show cpu percentages for each process from within the ProcessBrowser. CPUWatcher startMonitoring. "process period 20 seconds, sample rate 100 msec" CPUWatcher current monitorProcessPeriod: 10 sampleRate: 20. CPUWatcher current threshold: 0.5. "change from 80% to 50%" CPUWatcher stopMonitoring. ! !CPUWatcher methodsFor: 'process operations' stamp: 'nk 3/8/2001 17:13'! debugProcess: aProcess | uiPriority oldPriority | uiPriority _ Processor activeProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority _ ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !CPUWatcher methodsFor: 'process operations' stamp: 'nk 3/8/2001 17:27'! debugProcess: aProcess fromMenu: aMenuMorph aMenuMorph delete. self debugProcess: aProcess.! ! !CPUWatcher methodsFor: 'process operations' stamp: 'nk 3/8/2001 17:21'! resumeProcess: aProcess fromMenu: aMenuMorph aMenuMorph delete. ProcessBrowser resumeProcess: aProcess.! ! !CPUWatcher methodsFor: 'process operations' stamp: 'nk 3/8/2001 17:24'! terminateProcess: aProcess fromMenu: aMenuMorph aMenuMorph delete. ProcessBrowser terminateProcess: aProcess.! ! !CPUWatcher methodsFor: 'porcine capture' stamp: 'nk 3/8/2001 20:47'! catchThePig: aProcess | rules | "nickname, allow-stop, allow-debug" rules _ ProcessBrowser nameAndRulesFor: aProcess. (ProcessBrowser isUIProcess: aProcess) ifTrue: [ "aProcess debugWithTitle: 'Interrupted from the CPUWatcher'." ] ifFalse: [ rules second ifFalse: [ ^self ]. ProcessBrowser suspendProcess: aProcess. self openWindowForSuspendedProcess: aProcess ] ! ! !CPUWatcher methodsFor: 'porcine capture' stamp: 'nk 3/8/2001 16:05'! findThePig "tally has been updated. Look at it to see if there is a bad process. This runs at a very high priority, so make it fast" | countAndProcess | countAndProcess _ tally sortedCounts first. (countAndProcess key / tally size > self threshold) ifTrue: [ | proc | proc _ countAndProcess value. proc == Processor backgroundProcess ifTrue: [ ^self ]. "idle process? OK" self catchThePig: proc ]. ! ! !CPUWatcher methodsFor: 'porcine capture' stamp: 'nk 3/8/2001 18:34'! openMVCWindowForSuspendedProcess: aProcess ProcessBrowser new openAsMVC.! ! !CPUWatcher methodsFor: 'porcine capture' stamp: 'BG 10/29/2003 01:06'! openWindowForSuspendedProcess: aProcess Smalltalk isMorphic ifTrue: [ ] ifFalse: [ [ self openMVCWindowForSuspendedProcess: aProcess ] forkAt: Processor userSchedulingPriority ] ! ! !CPUWatcher methodsFor: 'startup-shutdown' stamp: 'nk 3/14/2001 08:39'! monitorProcessPeriod: secs sampleRate: msecs self stopMonitoring. watcher _ [ [ | promise | promise _ Processor tallyCPUUsageFor: secs every: msecs. tally _ promise value. promise _ nil. self findThePig. ] repeat ] forkAt: Processor highestPriority. Processor yield ! ! !CPUWatcher methodsFor: 'startup-shutdown' stamp: 'nk 3/14/2001 08:07'! startMonitoring self monitorProcessPeriod: 20 sampleRate: 100! ! !CPUWatcher methodsFor: 'startup-shutdown' stamp: 'nk 3/8/2001 16:24'! stopMonitoring watcher ifNotNil: [ ProcessBrowser terminateProcess: watcher. watcher _ nil. ]! ! !CPUWatcher methodsFor: 'accessing' stamp: 'nk 3/14/2001 07:56'! isMonitoring ^watcher notNil! ! !CPUWatcher methodsFor: 'accessing' stamp: 'nk 3/8/2001 18:36'! tally ^tally copy! ! !CPUWatcher methodsFor: 'accessing' stamp: 'nk 3/8/2001 18:49'! threshold "What fraction of the time can a process be the active process before we stop it?" ^threshold! ! !CPUWatcher methodsFor: 'accessing' stamp: 'nk 3/8/2001 18:38'! threshold: thresh "What fraction of the time can a process be the active process before we stop it?" threshold _ (thresh max: 0.02) min: 1.0! ! !CPUWatcher methodsFor: 'accessing' stamp: 'nk 3/14/2001 08:26'! watcherProcess ^watcher! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CPUWatcher class instanceVariableNames: ''! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/8/2001 18:45'! current ^CurrentCPUWatcher ! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/14/2001 08:28'! currentWatcherProcess ^CurrentCPUWatcher ifNotNil: [ CurrentCPUWatcher watcherProcess ] ! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/8/2001 21:43'! dumpTallyOnTranscript self current ifNotNil: [ ProcessBrowser dumpTallyOnTranscript: self current tally ]! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 6/18/2003 07:15'! initialize "CPUWatcher initialize" Smalltalk addToStartUpList: self. Smalltalk addToShutDownList: self.! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/14/2001 08:06'! isMonitoring ^CurrentCPUWatcher notNil and: [ CurrentCPUWatcher isMonitoring ] ! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 10/31/2001 10:50'! monitorPreferenceChanged Preferences cpuWatcherEnabled ifTrue: [ self startMonitoring ] ifFalse: [ self stopMonitoring ]! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 6/18/2003 07:14'! shutDown self stopMonitoring.! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/14/2001 08:17'! startMonitoring "CPUWatcher startMonitoring" ^self startMonitoringPeriod: 20 rate: 100 threshold: 0.8! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/14/2001 08:16'! startMonitoringPeriod: pd rate: rt threshold: th "CPUWatcher startMonitoring" CurrentCPUWatcher ifNotNil: [ ^CurrentCPUWatcher startMonitoring. ]. CurrentCPUWatcher _ (self new) monitorProcessPeriod: pd sampleRate: rt; threshold: th; yourself. ^CurrentCPUWatcher ! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 6/18/2003 07:14'! startUp self monitorPreferenceChanged.! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'nk 3/14/2001 08:05'! stopMonitoring "CPUWatcher stopMonitoring" CurrentCPUWatcher ifNotNil: [ CurrentCPUWatcher stopMonitoring. ]. CurrentCPUWatcher _ nil. ! ! FileStreamException subclass: #CannotDeleteFileException instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! ParseNode subclass: #CascadeNode instanceVariableNames: 'receiver messages' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !CascadeNode commentStamp: '<historical>' prior: 0! The first message has the common receiver, the rest have receiver == nil, which signifies cascading.! !CascadeNode methodsFor: 'initialize-release'! receiver: receivingObject messages: msgs " Transcript show: 'abc'; cr; show: 'def' " receiver _ receivingObject. messages _ msgs! ! !CascadeNode methodsFor: 'code generation'! emitForValue: stack on: aStream receiver emitForValue: stack on: aStream. 1 to: messages size - 1 do: [:i | aStream nextPut: Dup. stack push: 1. (messages at: i) emitForValue: stack on: aStream. aStream nextPut: Pop. stack pop: 1]. messages last emitForValue: stack on: aStream! ! !CascadeNode methodsFor: 'code generation'! sizeForValue: encoder | size | size _ (receiver sizeForValue: encoder) + (messages size - 1 * 2). messages do: [:aMessage | size _ size + (aMessage sizeForValue: encoder)]. ^size! ! !CascadeNode methodsFor: 'printing'! printOn: aStream indent: level self printOn: aStream indent: level precedence: 0! ! !CascadeNode methodsFor: 'printing' stamp: 'di 4/25/2000 19:17'! printOn: aStream indent: level precedence: p p > 0 ifTrue: [aStream nextPut: $(]. messages first printReceiver: receiver on: aStream indent: level. 1 to: messages size do: [:i | (messages at: i) printOn: aStream indent: level. i < messages size ifTrue: [aStream nextPut: $;. messages first precedence >= 2 ifTrue: [aStream crtab: level + 1]]]. p > 0 ifTrue: [aStream nextPut: $)]! ! !CascadeNode methodsFor: 'accessing' stamp: 'tk 10/22/2000 16:55'! receiver ^receiver! ! Object subclass: #Categorizer instanceVariableNames: 'categoryArray categoryStops elementArray' classVariableNames: 'Default NullCategory' poolDictionaries: '' category: 'Kernel-Classes'! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! addCategory: newCategory ^ self addCategory: newCategory before: nil ! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! addCategory: catString before: nextCategory "Add a new category named heading. If default category exists and is empty, remove it. If nextCategory is nil, then add the new one at the end, otherwise, insert it before nextCategory." | index newCategory | newCategory _ catString asSymbol. (categoryArray indexOf: newCategory) > 0 ifTrue: [^self]. "heading already exists, so done" index _ categoryArray indexOf: nextCategory ifAbsent: [categoryArray size + 1]. categoryArray _ categoryArray copyReplaceFrom: index to: index-1 with: (Array with: newCategory). categoryStops _ categoryStops copyReplaceFrom: index to: index-1 with: (Array with: (index = 1 ifTrue: [0] ifFalse: [categoryStops at: index-1])). "remove empty default category" (newCategory ~= Default and: [(self listAtCategoryNamed: Default) isEmpty]) ifTrue: [self removeCategory: Default]! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! allMethodSelectors "give a list of all method selectors." ^ elementArray copy sort! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:29'! categories "Answer an Array of categories (names)." categoryArray isNil ifTrue: [^ nil]. (categoryArray size = 1 and: [categoryArray first = Default & (elementArray size = 0)]) ifTrue: [^Array with: NullCategory]. ^categoryArray! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! categories: anArray "Reorder my categories to be in order of the argument, anArray. If the resulting organization does not include all elements, then give an error." | newCategories newStops newElements catName list runningTotal | newCategories _ Array new: anArray size. newStops _ Array new: anArray size. newElements _ Array new: 0. runningTotal _ 0. 1 to: anArray size do: [:i | catName _ (anArray at: i) asSymbol. list _ self listAtCategoryNamed: catName. newElements _ newElements, list. newCategories at: i put: catName. newStops at: i put: (runningTotal _ runningTotal + list size)]. elementArray do: [:element | "check to be sure all elements are included" (newElements includes: element) ifFalse: [^self error: 'New categories must match old ones']]. "Everything is good, now update my three arrays." categoryArray _ newCategories. categoryStops _ newStops. elementArray _ newElements! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! categoryOfElement: element "Answer the category associated with the argument, element." | index | index _ self numberOfCategoryOfElement: element. index = 0 ifTrue: [^nil] ifFalse: [^categoryArray at: index]! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:36'! changeFromCategorySpecs: categorySpecs "Tokens is an array of categorySpecs as scanned from a browser 'reorganize' pane, or built up by some other process, such as a scan of an environment." | oldElements newElements newCategories newStops currentStop temp ii cc catSpec | oldElements _ elementArray asSet. newCategories _ Array new: categorySpecs size. newStops _ Array new: categorySpecs size. currentStop _ 0. newElements _ WriteStream on: (Array new: 16). 1 to: categorySpecs size do: [:i | catSpec _ categorySpecs at: i. newCategories at: i put: catSpec first asSymbol. catSpec allButFirst asSortedCollection do: [:elem | (oldElements remove: elem ifAbsent: [nil]) notNil ifTrue: [newElements nextPut: elem. currentStop _ currentStop+1]]. newStops at: i put: currentStop]. "Ignore extra elements but don't lose any existing elements!!" oldElements _ oldElements collect: [:elem | Array with: (self categoryOfElement: elem) with: elem]. newElements _ newElements contents. categoryArray _ newCategories. (cc _ categoryArray asSet) size = categoryArray size ifFalse: ["has duplicate element" temp _ categoryArray asOrderedCollection. temp removeAll: categoryArray asSet asOrderedCollection. temp do: [:dup | ii _ categoryArray indexOf: dup. [dup _ (dup,' #2') asSymbol. cc includes: dup] whileTrue. cc add: dup. categoryArray at: ii put: dup]]. categoryStops _ newStops. elementArray _ newElements. oldElements do: [:pair | self classify: pair last under: pair first].! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! changeFromString: aString "Parse the argument, aString, and make this be the receiver's structure." | categorySpecs | categorySpecs _ Scanner new scanTokens: aString. "If nothing was scanned and I had no elements before, then default me" (categorySpecs isEmpty and: [elementArray isEmpty]) ifTrue: [^ self setDefaultList: Array new]. ^ self changeFromCategorySpecs: categorySpecs! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! classify: element under: heading self classify: element under: heading suppressIfDefault: true! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:54'! classify: element under: heading suppressIfDefault: aBoolean "Store the argument, element, in the category named heading. If aBoolean is true, then invoke special logic such that the classification is NOT done if the new heading is the Default and the element already had a non-Default classification -- useful for filein" | catName catIndex elemIndex realHeading | ((heading = NullCategory) or: [heading == nil]) ifTrue: [realHeading _ Default] ifFalse: [realHeading _ heading asSymbol]. (catName _ self categoryOfElement: element) = realHeading ifTrue: [^ self]. "done if already under that category" catName ~~ nil ifTrue: [(aBoolean and: [realHeading = Default]) ifTrue: [^ self]. "return if non-Default category already assigned in memory" self removeElement: element]. "remove if in another category" (categoryArray indexOf: realHeading) = 0 ifTrue: [self addCategory: realHeading]. catIndex _ categoryArray indexOf: realHeading. elemIndex _ catIndex > 1 ifTrue: [categoryStops at: catIndex - 1] ifFalse: [0]. [(elemIndex _ elemIndex + 1) <= (categoryStops at: catIndex) and: [element >= (elementArray at: elemIndex)]] whileTrue. "elemIndex is now the index for inserting the element. Do the insertion before it." elementArray _ elementArray copyReplaceFrom: elemIndex to: elemIndex-1 with: (Array with: element). "add one to stops for this and later categories" catIndex to: categoryArray size do: [:i | categoryStops at: i put: (categoryStops at: i) + 1]. (self listAtCategoryNamed: Default) size = 0 ifTrue: [self removeCategory: Default]! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! classifyAll: aCollection under: heading aCollection do: [:element | self classify: element under: heading]! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:20'! elementCategoryDict | dict firstIndex lastIndex | elementArray isNil ifTrue: [^ nil]. dict _ Dictionary new: elementArray size. 1to: categoryStops size do: [:cat | firstIndex _ self firstIndexOfCategoryNumber: cat. lastIndex _ self lastIndexOfCategoryNumber: cat. firstIndex to: lastIndex do: [:el | dict at: (elementArray at: el) put: (categoryArray at: cat)]. ]. ^ dict.! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! listAtCategoryNamed: categoryName "Answer the array of elements associated with the name, categoryName." | i | i _ categoryArray indexOf: categoryName ifAbsent: [^Array new]. ^self listAtCategoryNumber: i! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/6/2004 13:51'! listAtCategoryNumber: anInteger "Answer the array of elements stored at the position indexed by anInteger. Answer nil if anInteger is larger than the number of categories." | firstIndex lastIndex | (anInteger < 1 or: [anInteger > categoryStops size]) ifTrue: [^ nil]. firstIndex _ self firstIndexOfCategoryNumber: anInteger. lastIndex _ self lastIndexOfCategoryNumber: anInteger. ^elementArray copyFrom: firstIndex to: lastIndex! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! numberOfCategoryOfElement: element "Answer the index of the category with which the argument, element, is associated." | categoryIndex elementIndex | categoryIndex _ 1. elementIndex _ 0. [(elementIndex _ elementIndex + 1) <= elementArray size] whileTrue: ["point to correct category" [elementIndex > (categoryStops at: categoryIndex)] whileTrue: [categoryIndex _ categoryIndex + 1]. "see if this is element" element = (elementArray at: elementIndex) ifTrue: [^categoryIndex]]. ^0! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! removeCategory: cat "Remove the category named, cat. Create an error notificiation if the category has any elements in it." | index lastStop | index _ categoryArray indexOf: cat ifAbsent: [^self]. lastStop _ index = 1 ifTrue: [0] ifFalse: [categoryStops at: index - 1]. (categoryStops at: index) - lastStop > 0 ifTrue: [^self error: 'cannot remove non-empty category']. categoryArray _ categoryArray copyReplaceFrom: index to: index with: Array new. categoryStops _ categoryStops copyReplaceFrom: index to: index with: Array new. categoryArray size = 0 ifTrue: [categoryArray _ Array with: Default. categoryStops _ Array with: 0] ! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! removeElement: element "Remove the selector, element, from all categories." | categoryIndex elementIndex nextStop newElements | categoryIndex _ 1. elementIndex _ 0. nextStop _ 0. "nextStop keeps track of the stops in the new element array" newElements _ WriteStream on: (Array new: elementArray size). [(elementIndex _ elementIndex + 1) <= elementArray size] whileTrue: [[elementIndex > (categoryStops at: categoryIndex)] whileTrue: [categoryStops at: categoryIndex put: nextStop. categoryIndex _ categoryIndex + 1]. (elementArray at: elementIndex) = element ifFalse: [nextStop _ nextStop + 1. newElements nextPut: (elementArray at: elementIndex)]]. [categoryIndex <= categoryStops size] whileTrue: [categoryStops at: categoryIndex put: nextStop. categoryIndex _ categoryIndex + 1]. elementArray _ newElements contents! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! removeEmptyCategories "Remove empty categories." | categoryIndex currentStop keptCategories keptStops | keptCategories _ WriteStream on: (Array new: 16). keptStops _ WriteStream on: (Array new: 16). currentStop _ categoryIndex _ 0. [(categoryIndex _ categoryIndex + 1) <= categoryArray size] whileTrue: [(categoryStops at: categoryIndex) > currentStop ifTrue: [keptCategories nextPut: (categoryArray at: categoryIndex). keptStops nextPut: (currentStop _ categoryStops at: categoryIndex)]]. categoryArray _ keptCategories contents. categoryStops _ keptStops contents. categoryArray size = 0 ifTrue: [categoryArray _ Array with: Default. categoryStops _ Array with: 0] "ClassOrganizer allInstancesDo: [:co | co removeEmptyCategories]."! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! renameCategory: oldCatString toBe: newCatString "Rename a category. No action if new name already exists, or if old name does not exist." | index oldCategory newCategory | oldCategory _ oldCatString asSymbol. newCategory _ newCatString asSymbol. (categoryArray indexOf: newCategory) > 0 ifTrue: [^ self]. "new name exists, so no action" (index _ categoryArray indexOf: oldCategory) = 0 ifTrue: [^ self]. "old name not found, so no action" categoryArray _ categoryArray copy. "need to change identity so smart list update will notice the change" categoryArray at: index put: newCategory! ! !Categorizer methodsFor: 'accessing' stamp: 'NS 4/5/2004 17:44'! sortCategories | privateCategories publicCategories newCategories | privateCategories _ self categories select: [:one | (one findString: 'private' startingAt: 1 caseSensitive: false) = 1]. publicCategories _ self categories copyWithoutAll: privateCategories. newCategories _ publicCategories asSortedCollection asOrderedCollection addAll: privateCategories asSortedCollection; asArray. self categories: newCategories! ! !Categorizer methodsFor: 'printing' stamp: 'NS 4/5/2004 17:44'! printOn: aStream "Refer to the comment in Object|printOn:." | elementIndex | elementIndex _ 1. 1 to: categoryArray size do: [:i | aStream nextPut: $(. (categoryArray at: i) asString printOn: aStream. [elementIndex <= (categoryStops at: i)] whileTrue: [aStream space; nextPutAll: (elementArray at: elementIndex). elementIndex _ elementIndex + 1]. aStream nextPut: $); cr]! ! !Categorizer methodsFor: 'printing' stamp: 'NS 4/5/2004 17:44'! printOnStream: aStream "Refer to the comment in Object|printOn:." | elementIndex | elementIndex _ 1. 1 to: categoryArray size do: [:i | aStream print: '('; write:(categoryArray at:i). " is the asString redundant? " [elementIndex <= (categoryStops at: i)] whileTrue: [aStream print:' '; write:(elementArray at: elementIndex). elementIndex _ elementIndex + 1]. aStream print:')'. aStream cr]! ! !Categorizer methodsFor: 'fileIn/Out' stamp: 'NS 4/5/2004 17:44'! scanFrom: aStream "Reads in the organization from the next chunk on aStream. Categories or elements not found in the definition are not affected. New elements are ignored." self changeFromString: aStream nextChunk. aStream skipStyleChunk.! ! !Categorizer methodsFor: 'private' stamp: 'NS 4/5/2004 17:44'! elementArray ^ elementArray! ! !Categorizer methodsFor: 'private' stamp: 'NS 4/6/2004 13:51'! firstIndexOfCategoryNumber: anInteger anInteger < 1 ifTrue: [^ nil]. ^ (anInteger > 1 ifTrue: [(categoryStops at: anInteger - 1) + 1] ifFalse: [1]).! ! !Categorizer methodsFor: 'private' stamp: 'NS 4/6/2004 13:52'! lastIndexOfCategoryNumber: anInteger anInteger > categoryStops size ifTrue: [^ nil]. ^ categoryStops at: anInteger! ! !Categorizer methodsFor: 'private' stamp: 'NS 4/5/2004 17:50'! setDefaultList: aSortedCollection categoryArray _ Array with: Default. categoryStops _ Array with: aSortedCollection size. elementArray _ aSortedCollection asArray! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Categorizer class instanceVariableNames: ''! !Categorizer class methodsFor: 'class initialization' stamp: 'NS 4/5/2004 17:44'! allCategory "Return a symbol that represents the virtual all methods category." ^ '-- all --' asSymbol! ! !Categorizer class methodsFor: 'class initialization' stamp: 'NS 4/5/2004 17:44'! default ^ Default! ! !Categorizer class methodsFor: 'class initialization' stamp: 'NS 4/6/2004 11:48'! initialize " self initialize " Default _ 'as yet unclassified' asSymbol. NullCategory _ 'no messages' asSymbol.! ! !Categorizer class methodsFor: 'class initialization' stamp: 'NS 4/5/2004 17:44'! nullCategory ^ NullCategory! ! !Categorizer class methodsFor: 'instance creation' stamp: 'NS 4/5/2004 17:44'! defaultList: aSortedCollection "Answer an instance of me with initial elements from the argument, aSortedCollection." ^self new setDefaultList: aSortedCollection! ! !Categorizer class methodsFor: 'documentation' stamp: 'NS 4/5/2004 17:44'! documentation "Instances consist of an Array of category names (categoryArray), each of which refers to an Array of elements (elementArray). This association is made through an Array of stop indices (categoryStops), each of which is the index in elementArray of the last element (if any) of the corresponding category. For example: categories _ Array with: 'firstCat' with: 'secondCat' with: 'thirdCat'. stops _ Array with: 1 with: 4 with: 4. elements _ Array with: #a with: #b with: #c with: #d. This means that category firstCat has only #a, secondCat has #b, #c, and #d, and thirdCat has no elements. This means that stops at: stops size must be the same as elements size." ! ! CodeHolder subclass: #ChangeList instanceVariableNames: 'changeList list listIndex listSelections file lostMethodPointer showsVersions' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeList commentStamp: '<historical>' prior: 0! A ChangeList represents a list of changed methods that reside on a file in fileOut format. The classes and methods in my list are not necessarily in this image!! Used as the model for both Version Lists and Changed Methods (in Screen Menu, Changes...). Note that the two kinds of window have different controller classes!!!! It holds three lists: changeList - a list of ChangeRecords list - a list of one-line printable headers listSelections - a list of Booleans (true = selected, false = not selected) multiple OK. listIndex Items that are removed (removeDoits, remove an item) are removed from all three lists. Most recently clicked item is the one showing in the bottom pane.! !ChangeList methodsFor: 'initialization-release'! addItem: item text: text | cr | cr _ Character cr. changeList addLast: item. list addLast: (text collect: [:x | x = cr ifTrue: [$/] ifFalse: [x]])! ! !ChangeList methodsFor: 'initialization-release' stamp: 'sw 1/7/2000 12:42'! changeListButtonSpecs ^#( ('select all' selectAll 'select all entries') ('deselect all' deselectAll 'deselect all entries') ('select conflicts' selectAllConflicts 'select all methods that occur in any change set') ('file in selections' fileInSelections 'file in all selected entries') )! ! !ChangeList methodsFor: 'initialization-release' stamp: 'sw 9/5/2001 13:53'! initialize "Initialize a blank ChangeList. Set the contentsSymbol to reflect whether diffs will initally be shown or not" contentsSymbol _ Preferences diffsInChangeList ifTrue: [self defaultDiffsSymbol] ifFalse: [#source]. changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. super initialize! ! !ChangeList methodsFor: 'initialization-release' stamp: 'sbw 12/30/1999 11:02'! optionalButtonHeight ^ 15! ! !ChangeList methodsFor: 'initialization-release' stamp: 'sw 11/13/2001 08:50'! optionalButtonsView "Answer the a View containing the optional buttons" | view bHeight vWidth first offset previousView bWidth button | vWidth _ 200. bHeight _ self optionalButtonHeight. previousView _ nil. offset _ 0. first _ true. view _ View new model: self; window: (0 @ 0 extent: vWidth @ bHeight). self changeListButtonSpecs do: [:triplet | button _ PluggableButtonView on: self getState: nil action: triplet second. button label: triplet first asParagraph. bWidth _ button label boundingBox width // 2. button window: (offset@0 extent: bWidth@bHeight); borderWidthLeft: 0 right: 1 top: 0 bottom: 0. offset _ offset + bWidth. first ifTrue: [view addSubView: button. first _ false.] ifFalse: [view addSubView: button toRightOf: previousView]. previousView _ button]. button _ PluggableButtonView on: self getState: #showingAnyKindOfDiffs action: #toggleDiffing. button label: 'diffs' asParagraph; window: (offset@0 extent: (vWidth - offset)@bHeight). view addSubView: button toRightOf: previousView. ^ view! ! !ChangeList methodsFor: 'initialization-release' stamp: 'sw 8/15/2002 22:34'! wantsPrettyDiffOption "Answer whether pretty-diffs are meaningful for this tool" ^ true! ! !ChangeList methodsFor: 'scanning' stamp: 'sw 1/15/98 21:56'! scanCategory "Scan anything that involves more than one chunk; method name is historical only" | itemPosition item tokens stamp isComment anIndex | itemPosition _ file position. item _ file nextChunk. isComment _ (item includesSubString: 'commentStamp:'). (isComment or: [item includesSubString: 'methodsFor:']) ifFalse: ["Maybe a preamble, but not one we recognize; bail out with the preamble trick" ^ self addItem: (ChangeRecord new file: file position: itemPosition type: #preamble) text: ('preamble: ' , item contractTo: 50)]. tokens _ Scanner new scanTokens: item. tokens size >= 3 ifTrue: [stamp _ ''. anIndex _ tokens indexOf: #stamp: ifAbsent: [nil]. anIndex ifNotNil: [stamp _ tokens at: (anIndex + 1)]. tokens second == #methodsFor: ifTrue: [^ self scanCategory: tokens third class: tokens first meta: false stamp: stamp]. tokens third == #methodsFor: ifTrue: [^ self scanCategory: tokens fourth class: tokens first meta: true stamp: stamp]]. tokens second == #commentStamp: ifTrue: [stamp _ tokens third. self addItem: (ChangeRecord new file: file position: file position type: #classComment class: tokens first category: nil meta: false stamp: stamp) text: 'class comment for ' , tokens first, (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp]). file nextChunk. ^ file skipStyleChunk]! ! !ChangeList methodsFor: 'scanning' stamp: 'di 1/13/98 16:56'! scanCategory: category class: class meta: meta stamp: stamp | itemPosition method | [itemPosition _ file position. method _ file nextChunk. file skipStyleChunk. method size > 0] "done when double terminators" whileTrue: [self addItem: (ChangeRecord new file: file position: itemPosition type: #method class: class category: category meta: meta stamp: stamp) text: 'method: ' , class , (meta ifTrue: [' class '] ifFalse: [' ']) , (Parser new parseSelector: method) , (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp])]! ! !ChangeList methodsFor: 'scanning' stamp: 'sw 10/19/1999 15:13'! scanFile: aFile from: startPosition to: stopPosition | itemPosition item prevChar | file _ aFile. changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. file position: startPosition. 'Scanning ', aFile localName, '...' displayProgressAt: Sensor cursorPoint from: startPosition to: stopPosition during: [:bar | [file position < stopPosition] whileTrue: [bar value: file position. [file atEnd not and: [file peek isSeparator]] whileTrue: [prevChar _ file next]. (file peekFor: $!!) ifTrue: [(prevChar = Character cr or: [prevChar = Character lf]) ifTrue: [self scanCategory]] ifFalse: [itemPosition _ file position. item _ file nextChunk. file skipStyleChunk. item size > 0 ifTrue: [self addItem: (ChangeRecord new file: file position: itemPosition type: #doIt) text: 'do it: ' , (item contractTo: 50)]]]]. listSelections _ Array new: list size withAll: false! ! !ChangeList methodsFor: 'menu actions' stamp: 'jm 5/3/1998 19:15'! acceptFrom: aView aView controller text = aView controller initialText ifFalse: [ aView flash. ^ self inform: 'You can only accept this version as-is. If you want to edit, copy the text to a browser']. (aView setText: aView controller text from: self) ifTrue: [aView ifNotNil: [aView controller accept]]. "initialText" ! ! !ChangeList methodsFor: 'menu actions' stamp: 'nk 1/7/2004 11:08'! browseAllVersionsOfSelections "Opens a Versions browser on all the currently selected methods, showing each alongside all of their historical versions." | oldSelection aList | oldSelection _ self listIndex. aList _ OrderedCollection new. Cursor read showWhile: [ 1 to: changeList size do: [:i | (listSelections at: i) ifTrue: [ listIndex _ i. self browseVersions. aList add: i. ]]]. listIndex _ oldSelection. aList size == 0 ifTrue: [^ self inform: 'no selected methods have in-memory counterparts']. ! ! !ChangeList methodsFor: 'menu actions' stamp: 'RAA 5/28/2001 11:37'! browseCurrentVersionsOfSelections "Opens a message-list browser on the current in-memory versions of all methods that are currently seleted" | aClass aChange aList | aList _ OrderedCollection new. Cursor read showWhile: [ 1 to: changeList size do: [:i | (listSelections at: i) ifTrue: [ aChange _ changeList at: i. (aChange type = #method and: [(aClass _ aChange methodClass) notNil and: [aClass includesSelector: aChange methodSelector]]) ifTrue: [ aList add: ( MethodReference new setStandardClass: aClass methodSymbol: aChange methodSelector ) ]]]]. aList size == 0 ifTrue: [^ self inform: 'no selected methods have in-memory counterparts']. MessageSet openMessageList: aList name: 'Current versions of selected methods in ', file localName! ! !ChangeList methodsFor: 'menu actions' stamp: 'nk 1/7/2004 10:23'! browseVersions | change class browser | listIndex = 0 ifTrue: [^ nil ]. change _ changeList at: listIndex. ((class _ change methodClass) notNil and: [class includesSelector: change methodSelector]) ifFalse: [ ^nil ]. browser _ super browseVersions. browser ifNotNil: [ browser addedChangeRecord: change ]. ^browser! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 1/25/2001 07:22'! changeListKey: aChar from: view "Respond to a Command key in the list pane." aChar == $D ifTrue: [^ self toggleDiffing]. aChar == $a ifTrue: [^ self selectAll]. ^ self arrowKey: aChar from: view! ! !ChangeList methodsFor: 'menu actions' stamp: 'BG 10/28/2003 20:46'! changeListMenu: aMenu "Fill aMenu up so that it comprises the primary changelist-browser menu" aMenu addList: #( ('fileIn selections' fileInSelections 'import the selected items into the image') ('fileOut selections... ' fileOutSelections 'create a new file containing the selected items') - ('compare to current' compareToCurrentVersion 'open a separate window which shows the text differences between the on-file version and the in-image version.' ) ('toggle diffing (D)' toggleDiffing 'start or stop showing diffs in the code pane.') - ('select conflicts with any changeset' selectAllConflicts 'select methods in the file which also occur in any change-set in the system') ('select conflicts with current changeset' selectConflicts 'select methods in the file which also occur in the current change-set') ('select conflicts with...' selectConflictsWith 'allows you to designate a file or change-set against which to check for code conflicts.') - ('select unchanged methods' selectUnchangedMethods 'select methods in the file whose in-image versions are the same as their in-file counterparts' ) ('select new methods' selectNewMethods 'select methods in the file that do not current occur in the image') ('select methods for this class' selectMethodsForThisClass 'select all methods in the file that belong to the currently-selected class') - ('select all (a)' selectAll 'select all the items in the list') ('deselect all' deselectAll 'deselect all the items in the list') ('invert selections' invertSelections 'select every item that is not currently selected, and deselect every item that *is* currently selected') - ('browse current versions of selections' browseCurrentVersionsOfSelections 'open a message-list browser showing the current (in-image) counterparts of the selected methods') ('destroy current methods of selections' destroyCurrentCodeOfSelections 'remove (*destroy*) the in-image counterparts of all selected methods') - ('remove doIts' removeDoIts 'remove all items that are doIts rather than methods') ('remove older versions' removeOlderMethodVersions 'remove all but the most recent versions of methods in the list') ('remove up-to-date versions' removeExistingMethodVersions 'remove all items whose code is the same as the counterpart in-image code') ('remove selected items' removeSelections 'remove the selected items from the change-list') ('remove unselected items' removeNonSelections 'remove all the items not currently selected from the change-list')). ^ aMenu ! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 5/20/2001 21:18'! compareToCurrentVersion "If the current selection corresponds to a method in the system, then spawn a window showing the diffs as text" | change class s1 s2 | listIndex = 0 ifTrue: [^ self]. change _ changeList at: listIndex. ((class _ change methodClass) notNil and: [class includesSelector: change methodSelector]) ifTrue: [s1 _ (class sourceCodeAt: change methodSelector) asString. s2 _ change string. s1 = s2 ifTrue: [^ self inform: 'Exact Match']. (StringHolder new textContents: (TextDiffBuilder buildDisplayPatchFrom: s1 to: s2 inClass: class prettyDiffs: self showingPrettyDiffs)) openLabel: 'Comparison to Current Version'] ifFalse: [self flash]! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 1/25/2001 08:38'! deselectAll "Deselect all items in the list pane, and clear the code pane" listIndex _ 0. listSelections atAllPut: false. self changed: #allSelections. self contentsChanged! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 1/25/2001 09:04'! destroyCurrentCodeOfSelections "Actually remove from the system any in-memory methods with class and selector identical to items current selected. This may seem rather arcane but believe me it has its great uses, when trying to split out code. To use effectively, first file out a change set that you wish to split off. Then open a ChangeList browser on that fileout. Now look through the methods, and select any of them which you want to remove completely from the system, then issue this command. For those methods where you have made changes to pre-existing versions, of course, you won't want to remove them from the system, so use this mechanism with care!!" | aClass aChange aList | aList _ OrderedCollection new. 1 to: changeList size do: [:index | (listSelections at: index) ifTrue: [aChange _ changeList at: index. (aChange type = #method and: [(aClass _ aChange methodClass) notNil and: [aClass includesSelector: aChange methodSelector]]) ifTrue: [aList add: {aClass. aChange methodSelector}]]]. aList size > 0 ifTrue: [(self confirm: 'Warning!! This will actually remove ', aList size printString, ' method(s) from the system!!') ifFalse: [^ self]]. aList do: [:aPair | Transcript cr; show: 'Removed: ', aPair first printString, '.', aPair second. aPair first removeSelector: aPair second]! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 10/11/1999 17:10'! fileInSelections | any | any _ false. listSelections with: changeList do: [:selected :item | selected ifTrue: [any _ true. item fileIn]]. any ifFalse: [self inform: 'nothing selected, so nothing done']! ! !ChangeList methodsFor: 'menu actions' stamp: 'sma 2/5/2000 19:13'! fileOutSelections | f | f _ FileStream newFileNamed: (FillInTheBlank request: 'Enter file name' initialAnswer: 'Filename.st'). f ifNil: [^ self]. f header; timeStamp. listSelections with: changeList do: [:selected :item | selected ifTrue: [item fileOutOn: f]]. f close! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 1/25/2001 08:35'! invertSelections "Invert the selectedness of each item in the changelist" listSelections _ listSelections collect: [ :ea | ea not]. listIndex _ 0. self changed: #allSelections. self contentsChanged! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 10/11/1999 17:18'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If I can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (#accept == selector) ifTrue: [otherTarget isMorph ifFalse: [^ self acceptFrom: otherTarget view]]. "weird special case just for mvc changlist" ^ super perform: selector orSendTo: otherTarget! ! !ChangeList methodsFor: 'menu actions' stamp: 'tk 4/8/98 12:38'! removeDoIts "Remove doits from the receiver, other than initializes. 1/26/96 sw" | newChangeList newList | newChangeList _ OrderedCollection new. newList _ OrderedCollection new. changeList with: list do: [:chRec :str | (chRec type ~~ #doIt or: [str endsWith: 'initialize']) ifTrue: [newChangeList add: chRec. newList add: str]]. newChangeList size < changeList size ifTrue: [changeList _ newChangeList. list _ newList. listIndex _ 0. listSelections _ Array new: list size withAll: false]. self changed: #list. ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ar 2/24/2001 18:29'! removeExistingMethodVersions "Remove all up to date version of entries from the receiver" | newChangeList newList str keep cls sel | newChangeList _ OrderedCollection new. newList _ OrderedCollection new. changeList with: list do:[:chRec :strNstamp | keep _ true. (cls _ chRec methodClass) ifNotNil:[ str _ chRec string. sel _ cls parserClass new parseSelector: str. keep _ (cls sourceCodeAt: sel ifAbsent:['']) asString ~= str. ]. keep ifTrue:[ newChangeList add: chRec. newList add: strNstamp]]. newChangeList size < changeList size ifTrue: [changeList _ newChangeList. list _ newList. listIndex _ 0. listSelections _ Array new: list size withAll: false]. self changed: #list! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 9/18/2000 12:21'! removeNonSelections "Remove the unselected items from the receiver." | newChangeList newList | newChangeList _ OrderedCollection new. newList _ OrderedCollection new. 1 to: changeList size do: [:i | (listSelections at: i) ifTrue: [newChangeList add: (changeList at: i). newList add: (list at: i)]]. newChangeList size == 0 ifTrue: [^ self inform: 'That would remove everything. Why would you want to do that?']. newChangeList size < changeList size ifTrue: [changeList _ newChangeList. list _ newList. listIndex _ 0. listSelections _ Array new: list size withAll: false]. self changed: #list ! ! !ChangeList methodsFor: 'menu actions' stamp: 'di 6/13/97 23:10'! removeOlderMethodVersions "Remove older versions of entries from the receiver." | newChangeList newList found str | newChangeList _ OrderedCollection new. newList _ OrderedCollection new. found _ OrderedCollection new. changeList reverseWith: list do: [:chRec :strNstamp | str _ strNstamp copyUpTo: $;. (found includes: str) ifFalse: [found add: str. newChangeList add: chRec. newList add: strNstamp]]. newChangeList size < changeList size ifTrue: [changeList _ newChangeList reversed. list _ newList reversed. listIndex _ 0. listSelections _ Array new: list size withAll: false]. self changed: #list! ! !ChangeList methodsFor: 'menu actions'! removeSelections "Remove the selected items from the receiver. 9/18/96 sw" | newChangeList newList | newChangeList _ OrderedCollection new. newList _ OrderedCollection new. 1 to: changeList size do: [:i | (listSelections at: i) ifFalse: [newChangeList add: (changeList at: i). newList add: (list at: i)]]. newChangeList size < changeList size ifTrue: [changeList _ newChangeList. list _ newList. listIndex _ 0. listSelections _ Array new: list size withAll: false]. self changed: #list ! ! !ChangeList methodsFor: 'menu actions'! selectAll listIndex _ 0. listSelections atAllPut: true. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 6/6/2001 12:54'! selectAllConflicts "Selects all method definitions in the receiver which are also in any existing change set in the system. This makes no statement about whether the content of the methods differ, only whether there is a change represented." | aClass aChange | Cursor read showWhile: [1 to: changeList size do: [:i | aChange _ changeList at: i. listSelections at: i put: (aChange type = #method and: [(aClass _ aChange methodClass) notNil and: [ChangeSorter doesAnyChangeSetHaveClass: aClass andSelector: aChange methodSelector]])]]. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions' stamp: 'sd 5/23/2003 14:24'! selectConflicts "Selects all method definitions for which there is ALSO an entry in changes" | change class | Cursor read showWhile: [1 to: changeList size do: [:i | change _ changeList at: i. listSelections at: i put: (change type = #method and: [(class _ change methodClass) notNil and: [(ChangeSet current atSelector: change methodSelector class: class) ~~ #none]])]]. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions'! selectConflicts: changeSetOrList "Selects all method definitions for which there is ALSO an entry in the specified changeSet or changList" | change class systemChanges | Cursor read showWhile: [(changeSetOrList isKindOf: ChangeSet) ifTrue: [ 1 to: changeList size do: [:i | change _ changeList at: i. listSelections at: i put: (change type = #method and: [(class _ change methodClass) notNil and: [(changeSetOrList atSelector: change methodSelector class: class) ~~ #none]])]] ifFalse: ["a ChangeList" 1 to: changeList size do: [:i | change _ changeList at: i. listSelections at: i put: (change type = #method and: [(class _ change methodClass) notNil and: [changeSetOrList list includes: (list at: i)]])]] ]. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions' stamp: 'di 4/6/2001 09:03'! selectConflictsWith "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" | aStream all index | aStream _ WriteStream on: (String new: 200). (all _ ChangeSorter allChangeSets copy) do: [:sel | aStream nextPutAll: (sel name contractTo: 40); cr]. ChangeList allSubInstancesDo: [:sel | aStream nextPutAll: (sel file name); cr. all addLast: sel]. aStream skip: -1. index _ (PopUpMenu labels: aStream contents) startUp. index > 0 ifTrue: [ self selectConflicts: (all at: index)]. ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ls 11/14/1998 14:30'! selectMethodsForThisClass | name | self currentChange ifNil: [ ^self ]. name _ self currentChange methodClassName. name ifNil: [ ^self ]. ^self selectSuchThat: [ :change | change methodClassName = name ].! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 12/3/2002 22:27'! selectNewMethods "Selects all method definitions for which there is no counterpart method in the current image" | change class | Cursor read showWhile: [1 to: changeList size do: [:i | change _ changeList at: i. listSelections at: i put: ((change type = #method and: [((class _ change methodClass) isNil) or: [(class includesSelector: change methodSelector) not]]))]]. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions' stamp: 'sw 1/7/2000 15:04'! selectSuchThat "query the user for a selection criterio. By Lex Spoon. NB: the UI for invoking this from a changelist browser is currently commented out; to reenfranchise it, you'll need to mild editing to ChangeList method #changeListMenu:" | code block | code _ FillInTheBlank request: 'selection criteria for a change named aChangeRecord?\For instance, ''aChangeRecord category = ''System-Network''''' withCRs. code isEmpty ifTrue: [^ self ]. block _ Compiler evaluate: '[:aChangeRecord | ', code, ']'. self selectSuchThat: block! ! !ChangeList methodsFor: 'menu actions' stamp: 'ls 5/12/1999 07:56'! selectSuchThat: aBlock "select all changes for which block returns true" listSelections _ changeList collect: [ :change | aBlock value: change ]. self changed: #allSelections! ! !ChangeList methodsFor: 'menu actions' stamp: 'nk 1/7/2004 09:16'! selectUnchangedMethods "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" | change class | Cursor read showWhile: [1 to: changeList size do: [:i | change _ changeList at: i. listSelections at: i put: ((change type = #method and: [(class _ change methodClass) notNil]) and: [(class includesSelector: change methodSelector) and: [change string withBlanksCondensed = (class sourceCodeAt: change methodSelector) asString withBlanksCondensed ]])]]. self changed: #allSelections! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 6/18/2001 10:44'! annotation "Answer the string to be shown in an annotation pane. Make plain that the annotation is associated with the current in-image version of the code, not of the selected disk-based version, and if the corresponding method is missing from the in-image version, mention that fact." | annot aChange aClass | annot _ super annotation. annot asString = '------' ifTrue: [^ annot]. ^ ((aChange _ self currentChange) notNil and: [aChange methodSelector notNil]) ifFalse: [annot] ifTrue: [((aClass _ aChange methodClass) isNil or: [(aClass includesSelector: aChange methodSelector) not]) ifTrue: [aChange methodClassName, ' >> ', aChange methodSelector, ' is not present in the current image.'] ifFalse: ['current version: ', annot]]! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 9/5/2001 13:52'! contents "Answer the contents string, obeying diffing directives if needed" ^ self showingAnyKindOfDiffs ifFalse: [self undiffedContents] ifTrue: [self showsVersions ifTrue: [self diffedVersionContents] ifFalse: [self contentsDiffedFromCurrent]]! ! !ChangeList methodsFor: 'viewing access' stamp: 'tk 4/10/1998 09:25'! contents: aString listIndex = 0 ifTrue: [self changed: #flash. ^ false]. lostMethodPointer ifNotNil: [^ self restoreDeletedMethod]. self okToChange "means not dirty" ifFalse: ["is dirty" self inform: 'This is a view of a method on a file.\Please cancel your changes. You may\accept, but only when the method is untouched.' withCRs. ^ false]. "Can't accept changes here. Method text must be unchanged!!" (changeList at: listIndex) fileIn. ^ true! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 5/19/2001 10:59'! contentsDiffedFromCurrent "Answer the contents diffed forward from current (in-memory) method version" | aChange aClass | listIndex = 0 ifTrue: [^ '']. aChange _ changeList at: listIndex. ^ ((aChange type == #method and: [(aClass _ aChange methodClass) notNil]) and: [aClass includesSelector: aChange methodSelector]) ifTrue: [Utilities methodDiffFor: aChange text class: aClass selector: aChange methodSelector prettyDiffs: self showingPrettyDiffs] ifFalse: [(changeList at: listIndex) text]! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 11/13/2001 09:12'! contentsSymbolQuints "Answer a list of quintuplets representing information on the alternative views available in the code pane" ^ self sourceAndDiffsQuintsOnly! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 6/7/2001 23:54'! diffedVersionContents "Answer diffed version contents, maybe pretty maybe not" | change class earlier later | (listIndex = 0 or: [changeList size < listIndex]) ifTrue: [^ '']. change _ changeList at: listIndex. later _ change text. class _ change methodClass. (listIndex == changeList size or: [class == nil]) ifTrue: [^ later]. earlier _ (changeList at: listIndex + 1) text. ^ TextDiffBuilder buildDisplayPatchFrom: earlier to: later inClass: class prettyDiffs: self showingPrettyDiffs! ! !ChangeList methodsFor: 'viewing access'! list ^ list! ! !ChangeList methodsFor: 'viewing access'! listIndex ^ listIndex! ! !ChangeList methodsFor: 'viewing access'! listSelectionAt: index ^ listSelections at: index! ! !ChangeList methodsFor: 'viewing access' stamp: 'di 1/13/1999 14:59'! listSelectionAt: index put: value ^ listSelections at: index put: value! ! !ChangeList methodsFor: 'viewing access' stamp: 'NS 1/28/2004 11:18'! restoreDeletedMethod "If lostMethodPointer is not nil, then this is a version browser for a method that has been removed. In this case we want to establish a sourceCode link to prior versions. We do this by installing a dummy method with the correct source code pointer prior to installing this version." | dummyMethod class selector | dummyMethod _ CompiledMethod toReturnSelf setSourcePointer: lostMethodPointer. class _ (changeList at: listIndex) methodClass. selector _ (changeList at: listIndex) methodSelector. class addSelectorSilently: selector withMethod: dummyMethod. (changeList at: listIndex) fileIn. "IF for some reason, the dummy remains, remove it, but (N.B.!!) we might not get control back if the compile (fileIn above) fails." (class compiledMethodAt: selector) == dummyMethod ifTrue: [class basicRemoveSelector: selector]. ^ true! ! !ChangeList methodsFor: 'viewing access' stamp: 'nk 2/26/2004 13:50'! selectedClass ^(self selectedClassOrMetaClass ifNil: [ ^nil ]) theNonMetaClass ! ! !ChangeList methodsFor: 'viewing access' stamp: 'sma 2/5/2000 19:09'! selectedClassOrMetaClass | c | ^ (c _ self currentChange) ifNotNil: [c methodClass]! ! !ChangeList methodsFor: 'viewing access' stamp: 'sma 2/5/2000 19:10'! selectedMessageName | c | ^ (c _ self currentChange) ifNotNil: [c methodSelector]! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 1/28/1999 12:30'! toggleListIndex: newListIndex listIndex ~= 0 ifTrue: [listSelections at: listIndex put: false]. newListIndex ~= 0 ifTrue: [listSelections at: newListIndex put: true]. listIndex _ newListIndex. self changed: #listIndex. self contentsChanged! ! !ChangeList methodsFor: 'viewing access' stamp: 'sw 1/25/1999 14:45'! undiffedContents ^ listIndex = 0 ifTrue: [''] ifFalse: [(changeList at: listIndex) text]! ! !ChangeList methodsFor: 'accessing'! changeList ^ changeList! ! !ChangeList methodsFor: 'accessing' stamp: 'ls 5/12/1999 07:55'! currentChange "return the current change being viewed, or nil if none" listIndex = 0 ifTrue: [ ^nil ]. ^changeList at: listIndex! ! !ChangeList methodsFor: 'accessing'! file ^file! ! !ChangeList methodsFor: 'accessing' stamp: 'TPR 11/28/1998 17:38'! listHasSingleEntry "does the list of changes have only a single item?" ^list size = 1! ! !ChangeList methodsFor: 'accessing' stamp: 'tk 6/21/1999 20:43'! listSelections listSelections ifNil: [ list ifNotNil: [ listSelections _ Array new: list size withAll: false]]. ^ listSelections! ! !ChangeList methodsFor: 'accessing' stamp: 'di 6/15/97 15:13'! setLostMethodPointer: sourcePointer lostMethodPointer _ sourcePointer! ! !ChangeList methodsFor: 'accessing' stamp: 'sw 10/19/1999 15:11'! showsVersions ^ false! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ChangeList class instanceVariableNames: ''! !ChangeList class methodsFor: 'public access' stamp: 'di 1/18/2001 15:30'! browseFile: fileName "ChangeList browseFile: 'AutoDeclareFix.st'" "Opens a changeList on the file named fileName" ^ self browseStream: (FileStream readOnlyFileNamed: fileName)! ! !ChangeList class methodsFor: 'public access' stamp: 'HK 4/18/2002 15:02'! browseRecent: charCount "ChangeList browseRecent: 5000" "Opens a changeList on the end of the changes log file" ^ self browseRecent: charCount on: (SourceFiles at: 2) ! ! !ChangeList class methodsFor: 'public access' stamp: 'HK 4/18/2002 15:02'! browseRecent: charCount on: origChangesFile "Opens a changeList on the end of the specified changes log file" | changeList end changesFile | changesFile _ origChangesFile readOnlyCopy. end _ changesFile size. Cursor read showWhile: [changeList _ self new scanFile: changesFile from: (0 max: end - charCount) to: end]. changesFile close. self open: changeList name: 'Recent changes' multiSelect: true! ! !ChangeList class methodsFor: 'public access' stamp: 'sd 11/16/2003 14:10'! browseRecentLog "ChangeList browseRecentLog" "Prompt with a menu of how far back to go to browse the current image's changes log file" ^ self browseRecentLogOn: (SourceFiles at: 2) startingFrom: SmalltalkImage current lastQuitLogPosition! ! !ChangeList class methodsFor: 'public access' stamp: 'nk 7/8/2003 13:56'! browseRecentLogOn: origChangesFile "figure out where the last snapshot or quit was, then browse the recent entries." | end done block pos chunk changesFile positions prevBlock | changesFile _ origChangesFile readOnlyCopy. positions _ SortedCollection new. end _ changesFile size. prevBlock _ end. block _ end - 1024 max: 0. done _ false. [done or: [positions size > 0]] whileFalse: [changesFile position: block. "ignore first fragment" changesFile nextChunk. [changesFile position < prevBlock] whileTrue: [pos _ changesFile position. chunk _ changesFile nextChunk. ((chunk indexOfSubCollection: '----' startingAt: 1) = 1) ifTrue: [ ({ '----QUIT'. '----SNAPSHOT' } anySatisfy: [ :str | chunk beginsWith: str ]) ifTrue: [positions add: pos]]]. block = 0 ifTrue: [done _ true] ifFalse: [prevBlock _ block. block _ block - 1024 max: 0]]. changesFile close. positions isEmpty ifTrue: [self inform: 'File ' , changesFile name , ' does not appear to be a changes file'] ifFalse: [self browseRecentLogOn: origChangesFile startingFrom: positions last]! ! !ChangeList class methodsFor: 'public access' stamp: 'sw 1/2/2003 21:39'! browseRecentLogOn: origChangesFile startingFrom: initialPos "Prompt with a menu of how far back to go when browsing a changes file." | end banners positions pos chunk i changesFile | changesFile _ origChangesFile readOnlyCopy. banners _ OrderedCollection new. positions _ OrderedCollection new. end _ changesFile size. pos _ initialPos. [pos = 0 or: [banners size > 20]] whileFalse: [changesFile position: pos. chunk _ changesFile nextChunk. i _ chunk indexOfSubCollection: 'priorSource: ' startingAt: 1. i > 0 ifTrue: [positions addLast: pos. banners addLast: (chunk copyFrom: 5 to: i - 2). pos _ Number readFrom: (chunk copyFrom: i + 13 to: chunk size)] ifFalse: [pos _ 0]]. changesFile close. banners size == 0 ifTrue: [^ self inform: 'this image has never been saved since changes were compressed']. pos _ (SelectionMenu labelList: banners selections: positions) startUpWithCaption: 'Browse as far back as...'. pos == nil ifTrue: [^ self]. self browseRecent: end - pos on: origChangesFile! ! !ChangeList class methodsFor: 'public access' stamp: 'nb 6/17/2003 12:25'! browseRecentLogOnPath: fullName "figure out where the last snapshot or quit was, then browse the recent entries." fullName ifNotNil: [self browseRecentLogOn: (FileStream readOnlyFileNamed: fullName)] ifNil: [Beeper beep] ! ! !ChangeList class methodsFor: 'public access' stamp: 'di 1/18/2001 15:23'! browseStream: changesFile "Opens a changeList on a fileStream" | changeList charCount | changesFile readOnly. charCount _ changesFile size. charCount > 1000000 ifTrue: [(self confirm: 'The file ', changesFile name , ' is really long (' , charCount printString , ' characters). Would you prefer to view only the last million characters?') ifTrue: [charCount _ 1000000]]. Cursor read showWhile: [changeList _ self new scanFile: changesFile from: changesFile size-charCount to: changesFile size]. changesFile close. self open: changeList name: changesFile localName , ' log' multiSelect: true! ! !ChangeList class methodsFor: 'public access' stamp: 'sd 11/16/2003 14:11'! getRecentLocatorWithPrompt: aPrompt "Prompt with a menu of how far back to go. Return nil if user backs out. Otherwise return the number of characters back from the end of the .changes file the user wishes to include" "ChangeList getRecentPosition" | end changesFile banners positions pos chunk i | changesFile _ (SourceFiles at: 2) readOnlyCopy. banners _ OrderedCollection new. positions _ OrderedCollection new. end _ changesFile size. pos _ SmalltalkImage current lastQuitLogPosition. [pos = 0 or: [banners size > 20]] whileFalse: [changesFile position: pos. chunk _ changesFile nextChunk. i _ chunk indexOfSubCollection: 'priorSource: ' startingAt: 1. i > 0 ifTrue: [positions addLast: pos. banners addLast: (chunk copyFrom: 5 to: i-2). pos _ Number readFrom: (chunk copyFrom: i+13 to: chunk size)] ifFalse: [pos _ 0]]. changesFile close. pos _ (SelectionMenu labelList: banners selections: positions) startUpWithCaption: aPrompt. pos == nil ifTrue: [^ nil]. ^ end - pos! ! !ChangeList class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:46'! open: aChangeList name: aString multiSelect: multiSelect "Create a standard system view for the messageSet, whose label is aString. The listView may be either single or multiple selection type" | topView listHeight annoHeight optButtonHeight codeHeight aListView underPane annotationPane buttonsView aBrowserCodeView | listHeight _ 70. annoHeight _ 10. optButtonHeight _ aChangeList optionalButtonHeight. codeHeight _ 110. topView _ (StandardSystemView new) model: aChangeList; label: aString; minimumSize: 200 @ 120; borderWidth: 1. aListView _ (multiSelect ifTrue: [PluggableListViewOfMany on: aChangeList list: #list primarySelection: #listIndex changePrimarySelection: #toggleListIndex: listSelection: #listSelectionAt: changeListSelection: #listSelectionAt:put: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])] ifFalse: [PluggableListView on: aChangeList list: #list selected: #listIndex changeSelected: #toggleListIndex: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])]). aListView window: (0 @ 0 extent: 200 @ listHeight). topView addSubView: aListView. underPane _ aListView. aChangeList wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: aChangeList text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0 @ 0 extent: 200 @ 10). topView addSubView: annotationPane below: underPane. underPane _ annotationPane. codeHeight _ codeHeight - annoHeight]. aChangeList wantsOptionalButtons ifTrue: [buttonsView _ aChangeList optionalButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. codeHeight _ codeHeight - optButtonHeight]. aBrowserCodeView _ PluggableTextView on: aChangeList text: #contents accept: #contents: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. aBrowserCodeView controller: ReadOnlyTextController new; window: (0 @ 0 extent: 200 @ codeHeight). topView addSubView: aBrowserCodeView below: underPane. topView controller open.! ! !ChangeList class methodsFor: 'initialize-release' stamp: 'hg 8/3/2000 18:14'! initialize FileList registerFileReader: self! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'md 10/22/2003 16:13'! browseChangesFile: fullName "Browse the selected file in fileIn format." fullName ifNotNil: [ChangeList browseStream: (FileStream readOnlyFileNamed: fullName)] ifNil: [Beeper beep]! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:49'! fileReaderServicesForFile: fullName suffix: suffix | services | services _ OrderedCollection new. (FileStream isSourceFileSuffix: suffix) | (suffix = '*') ifTrue: [ services add: self serviceBrowseChangeFile ]. (suffix = 'changes') | (suffix = '*') ifTrue: [ services add: self serviceBrowseDotChangesFile ]. ^services! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'nk 4/29/2004 10:35'! serviceBrowseChangeFile "Answer a service for opening a changelist browser on a file" ^ (SimpleServiceEntry provider: self label: 'changelist browser' selector: #browseStream: description: 'open a changelist tool on this file' buttonLabel: 'changes') argumentGetter: [ :fileList | fileList readOnlyStream ]! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'sw 7/4/2002 18:37'! serviceBrowseDotChangesFile "Answer a service for opening a changelist browser on the tail end of a .changes file" ^ SimpleServiceEntry provider: self label: 'recent changes in file' selector: #browseRecentLogOnPath: description: 'open a changelist tool on recent changes in file' buttonLabel: 'recent changes'! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:49'! services "Answer potential file services associated with this class" ^ { self serviceBrowseChangeFile. self serviceBrowseDotChangesFile. }! ! !ChangeList class methodsFor: 'class initialization' stamp: 'SD 11/15/2001 22:21'! unload FileList unregisterFileReader: self ! ! Object subclass: #ChangeRecord instanceVariableNames: 'file position type class category meta stamp' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeRecord commentStamp: '<historical>' prior: 0! A ChangeRecord represents a change recorded on a file in fileOut format. It includes a type (more needs to be done here), and additional information for certain types such as method defs which need class and category.! !ChangeRecord methodsFor: 'access'! category ^category! ! !ChangeRecord methodsFor: 'access' stamp: 'nk 1/7/2004 10:28'! fileName ^(file ifNotNil: [ file name ]) ifNil: [ '<no file>' ]! ! !ChangeRecord methodsFor: 'access' stamp: 'sw 10/20/2002 02:53'! fileOutOn: aFileStream "File the receiver out on the given file stream" | aString | type == #method ifTrue: [aFileStream nextPut: $!!. aString _ class asString , (meta ifTrue: [' class methodsFor: '] ifFalse: [' methodsFor: ']) , category asString printString. stamp ifNotNil: [aString _ aString, ' stamp: ''', stamp, '''']. aFileStream nextChunkPut: aString. aFileStream cr]. type == #preamble ifTrue: [aFileStream nextPut: $!!]. type == #classComment ifTrue: [aFileStream nextPut: $!!. aFileStream nextChunkPut: class asString, ' commentStamp: ', stamp storeString. aFileStream cr]. aFileStream nextChunkPut: self string. type == #method ifTrue: [aFileStream nextChunkPut: ' ']. aFileStream cr! ! !ChangeRecord methodsFor: 'access'! isMetaClassChange ^meta! ! !ChangeRecord methodsFor: 'access'! methodClass | methodClass | type == #method ifFalse: [^ nil]. (Smalltalk includesKey: class asSymbol) ifFalse: [^ nil]. methodClass _ Smalltalk at: class asSymbol. meta ifTrue: [^ methodClass class] ifFalse: [^ methodClass]! ! !ChangeRecord methodsFor: 'access'! methodClassName ^class! ! !ChangeRecord methodsFor: 'access'! methodSelector type == #method ifFalse: [^ nil]. ^ Parser new parseSelector: self string! ! !ChangeRecord methodsFor: 'access' stamp: '6/6/97 08:56 dhhi'! stamp ^ stamp! ! !ChangeRecord methodsFor: 'access' stamp: 'tk 9/7/2000 15:09'! stamp: threePartString stamp _ threePartString! ! !ChangeRecord methodsFor: 'access' stamp: 'di 1/13/98 16:57'! string | string | file openReadOnly. file position: position. string _ file nextChunk. file close. ^ string! ! !ChangeRecord methodsFor: 'access' stamp: 'tk 6/23/1999 08:20'! text | text | ^ file ifNil: [''] ifNotNil: [ file openReadOnly. file position: position. text _ file nextChunkText. file close. text]! ! !ChangeRecord methodsFor: 'access' stamp: 'nk 11/25/2003 09:44'! timeStamp "Answer a TimeStamp that corresponds to my (text) stamp" | tokens date time | tokens := self stamp findTokens: Character separators. ^ tokens size > 2 ifTrue: [[date := Date fromString: (tokens at: tokens size - 1). time := Time fromString: tokens last. TimeStamp date: date time: time] on: Error do: [:ex | ex return: (TimeStamp fromSeconds: 0)]] ifFalse: [TimeStamp fromSeconds: 0]! ! !ChangeRecord methodsFor: 'access'! type ^ type! ! !ChangeRecord methodsFor: 'initialization'! file: f position: p type: t file _ f. position _ p. type _ t! ! !ChangeRecord methodsFor: 'initialization' stamp: '6/6/97 08:48 dhhi'! file: f position: p type: t class: c category: cat meta: m stamp: s self file: f position: p type: t. class _ c. category _ cat. meta _ m. stamp _ s! ! !ChangeRecord methodsFor: 'initialization' stamp: 'nk 11/26/2002 12:07'! fileIn "File the receiver in. If I represent a method or a class-comment, file the method in and make a note of it in the recent-submissions list; if I represent a do-it, then, well, do it." | methodClass s aSelector | Cursor read showWhile: [(methodClass _ self methodClass) notNil ifTrue: [methodClass compile: self text classified: category withStamp: stamp notifying: nil. (aSelector _ self methodSelector) ifNotNil: [Utilities noteMethodSubmission: aSelector forClass: methodClass]]. (type == #doIt) ifTrue: [((s _ self string) beginsWith: '----') ifFalse: [Compiler evaluate: s]]. (type == #classComment) ifTrue: [ | cls | (cls _ Smalltalk at: class asSymbol) comment: self text stamp: stamp. Utilities noteMethodSubmission: #Comment forClass: cls ]]! ! Object subclass: #ChangeSet instanceVariableNames: 'name preamble postscript revertable isolationSet isolatedProject changeRecords structures superclasses' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeSet commentStamp: '<historical>' prior: 0! ChangeSets keep track of the changes made to a system, so they can be written on a file as source code (a "fileOut"). Every project has an associated changeSet. For simple projects, a different changeSet may be designated to capture changes at any time. This implementation of ChangeSet is capable of remembering and manipulating methods for which the classes are not present in the system. However at the present time, this capability is not used in normal rearranging and fileOuts, but only for invoking and revoking associated with isolation layers. For isolated projects (see Project class comment), the changeSet binding is semi-permanent. Every project exists in an isolation layer defined by its closest enclosing parent (or itself) that is isolated. If a project is not isolated, then changes reported to its designated changeSet must also be reported to the permanent changeSet for that layer, designated in the isolated project. This ensures that that outer project will be able to revert all changes upon exit. Note that only certain changes may be reverted. Classes may not be added, removed, renamed or reshaped except in the layer in which they are defined because these operations on non-local classes are not revertable. If a Squeak Project is established as being isolated, then its associated changeSet will be declared to be revertable. In this case all changes stored can be reverted. The changeSet associated with an isolated project is tied to that project, and cannot be edited in a changeSorter. ------ name - a String used to name the changeSet, and thus any associated project or fileOut. preamble and postscript: two strings that serve as prefix (useful for documentation) and suffix (useful for doits) to the fileout of the changeSet. revertable - a Boolean If this variable is true, then all of the changes recorded by this changeSet can be reverted. isolationSet - a ChangeSet or nil The isolationSet is the designated changeSet for an isolation layer. If this changeSet is an isolationSet, then this variable will be nil. If not, then it points to the isolationSet for this layer, and all changes reported here will also be reported to the isolationSet. isolatedProject - a Project or nil If this is an isolationSet, then this variable points to the project with which it is associated. changeRecords - Dictionary {class name -> a ClassChangeRecord}. These classChangeRecords (qv) remember all of the system changes. structures - Dictionary {#Rectangle -> #(<classVersionInteger> 'origin' 'corner')}. Of the names of the instances variables before any changes for all classes in classChanges, and all of their superclasses. In the same format used in SmartRefStream. Inst var names are strings. superclasses - Dictionary {#Rectangle -> #Object}. Of all classes in classChanges, and all of their superclasses. Structures and superclasses save the instance variable names of this class and all of its superclasses. Later we can tell how it changed and write a conversion method. The conversion method is used when old format objects are brought in from the disk from ImageSegment files (.extSeg) or SmartRefStream files (.obj .morph .bo .sp). NOTE: It should be fairly simple, by adding a bit more information to the classChangeRecords, to reconstruct the information now stored in 'structures' and 'superclasses'. This would be a welcome simplification. ! !ChangeSet methodsFor: 'initialize-release' stamp: 'di 3/29/2000 20:42'! beIsolationSetFor: aProject self isEmpty ifFalse: [self error: 'Must be empty at the start.']. isolatedProject _ aProject. revertable _ true.! ! !ChangeSet methodsFor: 'initialize-release' stamp: 'di 4/1/2000 12:00'! clear "Reset the receiver to be empty. " changeRecords _ Dictionary new. preamble _ nil. postscript _ nil! ! !ChangeSet methodsFor: 'initialize-release' stamp: 'di 4/6/2001 09:40'! initialize "Initialize the receiver to be empty." name ifNil: [^ self error: 'All changeSets must be registered, as in ChangeSorter newChangeSet']. revertable _ false. self clear. ! ! !ChangeSet methodsFor: 'initialize-release'! isMoribund "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" ^ name == nil ! ! !ChangeSet methodsFor: 'initialize-release' stamp: 'sw 3/6/1999 09:31'! veryDeepCopyWith: deepCopier "Return self; this is NOT the way to launch new change sets!! Having this method here allows Change Sorters to be in parts bins"! ! !ChangeSet methodsFor: 'initialize-release' stamp: 'di 3/23/2000 12:14'! wither "The receiver is to be clobbered. Clear it out. 2/7/96 sw" self clear. name _ nil! ! !ChangeSet methodsFor: 'initialize-release' stamp: 'di 9/21/2000 15:29'! zapHistory "Much stronger than trimHistory, but it should still leave the changeSet in good shape. Must not be done on revertable changeSets ChangeSet allInstancesDo: [:cs | cs zapHistory]." revertable ifTrue: [^ self]. "No can do" changeRecords do: [:chgRecord | chgRecord zapHistory]! ! !ChangeSet methodsFor: 'change logging' stamp: 'di 3/29/2000 13:10'! addClass: class "Include indication that a new class was created." class wantsChangeSetLogging ifFalse: [^ self]. isolationSet ifNotNil: ["If there is an isolation layer above me, inform it as well." isolationSet addClass: class]. self atClass: class add: #new. self atClass: class add: #change. self addCoherency: class name! ! !ChangeSet methodsFor: 'change logging' stamp: 'NS 1/19/2004 18:30'! changeClass: class from: oldClass "Remember that a class definition has been changed. Record the original structure, so that a conversion method can be built." class wantsChangeSetLogging ifFalse: [^ self]. isolationSet ifNotNil: ["If there is an isolation layer above me, inform it as well." isolationSet changeClass: class from: oldClass]. class isMeta ifFalse: [self atClass: class add: #change] "normal" ifTrue: [((self classChangeAt: class theNonMetaClass name) includes: #add) ifTrue: [self atClass: class add: #add] "When a class is defined, the metaclass is not recorded, even though it was added. A further change is really just part of the original add." ifFalse: [self atClass: class add: #change]]. self addCoherency: class name. (self changeRecorderFor: class) notePriorDefinition: oldClass. self noteClassStructure: oldClass! ! !ChangeSet methodsFor: 'change logging' stamp: 'NS 4/12/2004 22:44'! event: anEvent "Hook for SystemChangeNotifier" (anEvent isRemoved and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self noteRemovalOf: anEvent item]. (anEvent isAdded and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self addClass: anEvent item]. (anEvent isModified and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [anEvent anyChanges ifTrue: [self changeClass: anEvent item from: anEvent oldItem]]. (anEvent isCommented and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self commentClass: anEvent item]. (anEvent isAdded and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: nil]. (anEvent isModified and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: anEvent oldItem]. (anEvent isRemoved and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [self removeSelector: anEvent itemSelector class: anEvent itemClass priorMethod: anEvent item lastMethodInfo: {anEvent item sourcePointer. anEvent itemProtocol}]. (anEvent isRenamed and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self renameClass: anEvent item as: anEvent newName]. (anEvent isReorganized and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self reorganizeClass: anEvent item]. (anEvent isRecategorized and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [self reorganizeClass: anEvent itemClass].! ! !ChangeSet methodsFor: 'change logging' stamp: 'di 3/29/2000 11:08'! noteNewMethod: newMethod forClass: class selector: selector priorMethod: methodOrNil class wantsChangeSetLogging ifFalse: [^ self]. isolationSet ifNotNil: ["If there is an isolation layer above me, inform it as well." isolationSet noteNewMethod: newMethod forClass: class selector: selector priorMethod: methodOrNil]. (self changeRecorderFor: class) noteNewMethod: newMethod selector: selector priorMethod: methodOrNil ! ! !ChangeSet methodsFor: 'change logging' stamp: 'di 3/29/2000 12:29'! removeSelector: selector class: class priorMethod: priorMethod lastMethodInfo: info "Include indication that a method has been forgotten. info is a pair of the source code pointer and message category for the method that was removed." class wantsChangeSetLogging ifFalse: [^ self]. isolationSet ifNotNil: ["If there is an isolation layer above me, inform it as well." isolationSet removeSelector: selector class: class priorMethod: priorMethod lastMethodInfo: info]. (self changeRecorderFor: class) noteRemoveSelector: selector priorMethod: priorMethod lastMethodInfo: info ! ! !ChangeSet methodsFor: 'change logging' stamp: 'tk 6/8/2001 09:27'! renameClass: class as: newName "Include indication that a class has been renamed." | recorder | isolationSet ifNotNil: ["If there is an isolation layer above me, inform it as well." isolationSet renameClass: class as: newName]. (recorder _ self changeRecorderFor: class) noteChangeType: #rename; noteNewName: newName asSymbol. "store under new name (metaclass too)" changeRecords at: newName put: recorder. changeRecords removeKey: class name. self noteClassStructure: class. recorder _ changeRecords at: class class name ifAbsent: [^ nil]. changeRecords at: (newName, ' class') put: recorder. changeRecords removeKey: class class name. recorder noteNewName: newName , ' class'! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 4/1/2000 09:25'! compileAll: newClass from: oldClass "If I have changes for this class, recompile them" (changeRecords at: newClass ifAbsent: [^ self]) compileAll: newClass from: oldClass ! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 3/29/2000 14:47'! invoke "Do the first part of the invoke operation -- no particular hurry." changeRecords do: [:changeRecord | changeRecord invokePhase1]. "Complete the invoke process -- this must be very simple." "Replace method dicts for any method changes." changeRecords do: [:changeRecord | changeRecord invokePhase2]. Behavior flushCache. ! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 4/13/2000 12:47'! isolatedProject "Return the isolated project for which I am the changeSet." ^ isolatedProject! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 3/29/2000 13:59'! isolationSet: setOrNil setOrNil == self ifTrue: [isolationSet _ nil] "Means this IS the isolation set" ifFalse: [isolationSet _ setOrNil]! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 3/29/2000 14:47'! revoke "Do the first part of the revoke operation -- this must be very simple." "Replace original method dicts if there are method changes." changeRecords do: [:changeRecord | changeRecord revokePhase1]. Behavior flushCache. "Complete the revoke process -- no particular hurry." changeRecords do: [:changeRecord | changeRecord revokePhase2]. ! ! !ChangeSet methodsFor: 'isolation layers' stamp: 'di 3/23/2000 12:00'! uninstall self halt. ! ! !ChangeSet methodsFor: 'accessing' stamp: 'BJP 4/24/2001 00:23'! author | author | self assurePreambleExists. author _ self preambleString lineNumber: 3. author _ author copyFrom: 8 to: author size. "Strip the 'Author:' prefix. Ugly ugly." ^author withBlanksTrimmed. ! ! !ChangeSet methodsFor: 'accessing' stamp: 'di 4/1/2000 12:00'! classRemoves ^ changeRecords keys select: [:className | (changeRecords at: className) isClassRemoval]! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 9/3/2008 11:02'! editPostscript "edit the receiver's postscript, in a separate window. " | deps found | self assurePostscriptExists. deps _ postscript dependents select: [:m | m isKindOf: StandardSystemView]. deps size > 0 ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [found _ deps detect: [:obj | (obj isKindOf: StandardSystemView) and: [ScheduledControllers scheduledControllers includes: obj controller]] ifNone: [nil]. found ifNotNil: [^ ScheduledControllers activateController: found controller]]. . self inform: 'Caution -- there', (deps size isOrAreStringWith: 'other window'), ' already open on this postscript elsewhere']. postscript openLabel: 'Postscript for ChangeSet named ', name! ! !ChangeSet methodsFor: 'accessing' stamp: 'sw 6/29/1999 14:44'! hasPostscript ^ postscript notNil! ! !ChangeSet methodsFor: 'accessing' stamp: 'di 4/1/2000 12:00'! methodChanges | methodChangeDict changeTypes | methodChangeDict _ Dictionary new. changeRecords associationsDo: [:assn | changeTypes _ assn value methodChangeTypes. changeTypes isEmpty ifFalse: [methodChangeDict at: assn key put: changeTypes]]. ^ methodChangeDict! ! !ChangeSet methodsFor: 'accessing' stamp: 'di 3/29/2000 16:22'! methodInfoFromRemoval: classAndSelector ^ (self changeRecorderFor: classAndSelector first) infoFromRemoval: classAndSelector last! ! !ChangeSet methodsFor: 'accessing'! name "The name of this changeSet. 2/7/96 sw: If name is nil, we've got garbage. Help to identify." ^ name == nil ifTrue: ['<no name -- garbage?>'] ifFalse: [name]! ! !ChangeSet methodsFor: 'accessing'! name: anObject name _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'sw 6/29/1999 20:51'! postscriptHasDependents ^ postscript dependents size > 0! ! !ChangeSet methodsFor: 'accessing'! printOn: aStream "2/7/96 sw: provide the receiver's name in the printout" super printOn: aStream. aStream nextPutAll: ' named ', self name! ! !ChangeSet methodsFor: 'accessing' stamp: 'MPW 1/1/1901 22:02'! printOnStream: aStream "2/7/96 sw: provide the receiver's name in the printout" super printOnStream: aStream. aStream print: ' named ', self name! ! !ChangeSet methodsFor: 'accessing' stamp: 'sw 6/29/1999 14:48'! removePostscript postscript _ nil! ! !ChangeSet methodsFor: 'accessing' stamp: 'tk 6/8/1999 22:25'! structures ^structures! ! !ChangeSet methodsFor: 'accessing' stamp: 'tk 6/8/1999 22:25'! superclasses ^superclasses! ! !ChangeSet methodsFor: 'testing' stamp: 'RAA 10/1/2000 12:28'! belongsToAProject Smalltalk at: #Project ifPresent: [:projClass | projClass allProjects do: [:proj | proj projectChangeSet == self ifTrue: [^ true]]]. ^ false! ! !ChangeSet methodsFor: 'testing' stamp: 'sw 8/10/2002 22:21'! containsMethodAtPosition: aFilePosition "Answer whether the receiver contains the method logged at the given file position" "class: aClassSymbol" "(need class parameter to speed up?)" "<- dew 9/6/2001" changeRecords values do: [:classChangeRecord | classChangeRecord methodChanges values do: [:methodChangeRecord | | changeType | changeType _ methodChangeRecord changeType. ((changeType == #add or: [changeType == #change]) and: [methodChangeRecord currentMethod notNil and: [methodChangeRecord currentMethod filePosition = aFilePosition]]) ifTrue: [^ true]]]. ^ false! ! !ChangeSet methodsFor: 'testing' stamp: 'RAA 11/13/2000 17:15'! correspondingProject "If the receiver is the current change set for any project, answer it, else answer nil" ^Project allProjects detect: [ :proj | proj projectChangeSet == self ] ifNone: [nil] ! ! !ChangeSet methodsFor: 'testing' stamp: 'RAA 10/19/2000 13:17'! isEmpty "Answer whether the receiver contains any elements." changeRecords ifNil: [^true]. ^ changeRecords isEmpty ! ! !ChangeSet methodsFor: 'testing' stamp: 'nk 7/2/2003 10:47'! methodsWithoutClassifications "Return a collection representing methods in the receiver which have not been categorized" | slips notClassified aSelector | notClassified _ {'as yet unclassified' asSymbol. #all}. slips _ OrderedCollection new. self changedClasses do: [:aClass | (self methodChangesAtClass: aClass name) associationsDo: [:mAssoc | (aClass selectors includes: (aSelector _ mAssoc key)) ifTrue: [(notClassified includes: (aClass organization categoryOfElement: aSelector)) ifTrue: [slips add: aClass name , ' ' , aSelector]]]]. ^ slips "Smalltalk browseMessageList: (ChangeSet current methodsWithoutClassifications) name: 'unclassified methods'"! ! !ChangeSet methodsFor: 'testing' stamp: 'sw 8/3/1998 16:25'! okayToRemove ^ self okayToRemoveInforming: true! ! !ChangeSet methodsFor: 'testing' stamp: 'sd 5/23/2003 14:24'! okayToRemoveInforming: aBoolean "Answer whether it is okay to remove the receiver. If aBoolean is true, inform the receiver if it is not okay" | aName | aName _ self name. self == self class current ifTrue: [aBoolean ifTrue: [self inform: 'Cannot remove "', aName, '" because it is the current change set.']. ^ false]. self belongsToAProject ifTrue: [aBoolean ifTrue: [self inform: 'Cannot remove "', aName, '" because it belongs to a project.']. ^ false]. ^ true ! ! !ChangeSet methodsFor: 'testing' stamp: 'RAA 9/27/2000 22:40'! projectsBelongedTo "Answer a list of all the projects for which the receiver is the current change set" ^ Project allProjects select: [:proj | proj projectChangeSet == self] ! ! !ChangeSet methodsFor: 'converting' stamp: 'RAA 12/20/2000 16:02'! convertApril2000: varDict using: smartRefStrm | cls info selector pair classChanges methodChanges methodRemoves classRemoves | "These variables are automatically stored into the new instance: ('name' 'preamble' 'postscript' 'structures' 'superclasses' ). This method is for additional changes. It initializes the isolation variables, and then duplicates the logic fo assimilateAllChangesFoundIn:." revertable _ false. isolationSet _ nil. isolatedProject _ nil. changeRecords _ Dictionary new. classChanges _ varDict at: 'classChanges'. classChanges keysDo: [:className | (cls _ Smalltalk classNamed: className) ifNotNil: [info _ classChanges at: className ifAbsent: [Set new]. info do: [:each | self atClass: cls add: each]]]. methodChanges _ varDict at: 'methodChanges'. methodRemoves _ varDict at: 'methodRemoves'. methodChanges keysDo: [:className | (cls _ Smalltalk classNamed: className) ifNotNil: [info _ methodChanges at: className ifAbsent: [Dictionary new]. info associationsDo: [:assoc | selector _ assoc key. (assoc value == #remove or: [assoc value == #addedThenRemoved]) ifTrue: [assoc value == #addedThenRemoved ifTrue: [self atSelector: selector class: cls put: #add]. pair _ methodRemoves at: {cls name. selector} ifAbsent: [nil] . self removeSelector: selector class: cls priorMethod: nil lastMethodInfo: pair] ifFalse: [self atSelector: selector class: cls put: assoc value]]]]. classRemoves _ varDict at: 'classRemoves'. classRemoves do: [:className | self noteRemovalOf: className]. ! ! !ChangeSet methodsFor: 'converting' stamp: 'RAA 12/20/2000 17:57'! convertToCurrentVersion: varDict refStream: smartRefStrm "major change - 4/4/2000" varDict at: 'classChanges' ifPresent: [ :x | self convertApril2000: varDict using: smartRefStrm ]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! !ChangeSet methodsFor: 'method changes' stamp: 'sw 12/28/2000 18:08'! adoptSelector: aSelector forClass: aClass "Adopt the given selector/class combination as a change in the receiver" self noteNewMethod: (aClass methodDictionary at: aSelector) forClass: aClass selector: aSelector priorMethod: nil! ! !ChangeSet methodsFor: 'method changes' stamp: 'di 3/29/2000 11:01'! atSelector: selector class: class put: changeType (selector == #DoIt or: [selector == #DoItIn:]) ifTrue: [^ self]. (self changeRecorderFor: class) atSelector: selector put: changeType. ! ! !ChangeSet methodsFor: 'method changes' stamp: 'sd 4/16/2003 09:15'! browseMessagesWithPriorVersions "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" | aList | aList _ self messageListForChangesWhich: [ :aClass :aSelector | (VersionsBrowser versionCountForSelector: aSelector class: aClass) > 1 ] ifNone: [^self inform: 'None!!']. self systemNavigation browseMessageList: aList name: self name, ' methods that have prior versions'! ! !ChangeSet methodsFor: 'method changes' stamp: 'sw 6/26/2001 12:15'! changedMessageList "Used by a message set browser to access the list view information." | messageList classNameInFull classNameInParts | messageList _ OrderedCollection new. changeRecords associationsDo: [:clAssoc | classNameInFull _ clAssoc key asString. classNameInParts _ classNameInFull findTokens: ' '. (clAssoc value allChangeTypes includes: #comment) ifTrue: [messageList add: (MethodReference new setClassSymbol: classNameInParts first asSymbol classIsMeta: false methodSymbol: #Comment stringVersion: classNameInFull, ' Comment')]. clAssoc value methodChangeTypes associationsDo: [:mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse: [messageList add: (MethodReference new setClassSymbol: classNameInParts first asSymbol classIsMeta: classNameInParts size > 1 methodSymbol: mAssoc key stringVersion: classNameInFull, ' ' , mAssoc key)]]]. ^ messageList asSortedArray! ! !ChangeSet methodsFor: 'method changes' stamp: 'tk 6/7/1999 18:57'! changedMessageListAugmented "Even added classes have all messages in changedMessageList." ^ self changedMessageList asArray! ! !ChangeSet methodsFor: 'method changes' stamp: 'sw 4/19/2001 19:45'! hasAnyChangeForSelector: aSelector "Answer whether the receiver has any change under the given selector, whether it be add, change, or remove, for any class" changeRecords do: [:aRecord | (aRecord changedSelectors includes: aSelector) ifTrue: [^ true]]. ^ false! ! !ChangeSet methodsFor: 'method changes' stamp: 'RAA 5/28/2001 12:05'! messageListForChangesWhich: aBlock ifNone: ifEmptyBlock | answer | answer _ self changedMessageListAugmented select: [ :each | aBlock value: each actualClass value: each methodSymbol ]. answer isEmpty ifTrue: [^ifEmptyBlock value]. ^answer ! ! !ChangeSet methodsFor: 'method changes' stamp: 'di 4/1/2000 12:00'! methodChangesAtClass: className "Return an old-style dictionary of method change types." ^(changeRecords at: className ifAbsent: [^ Dictionary new]) methodChangeTypes! ! !ChangeSet methodsFor: 'method changes' stamp: 'di 4/4/2000 11:14'! removeSelectorChanges: selector class: class "Remove all memory of changes associated with the argument, selector, in this class." | chgRecord | (chgRecord _ changeRecords at: class name ifAbsent: [^ self]) removeSelector: selector. chgRecord hasNoChanges ifTrue: [changeRecords removeKey: class name]! ! !ChangeSet methodsFor: 'method changes' stamp: 'SqR 6/13/2000 19:16'! selectorsInClass: aClassName "Used by a ChangeSorter to access the list methods." ^ (changeRecords at: aClassName ifAbsent: [^#()]) changedSelectors! ! !ChangeSet methodsFor: 'class changes' stamp: 'di 4/1/2000 12:00'! changedClassNames "Answer a OrderedCollection of the names of changed or edited classes. DOES include removed classes. Sort alphabetically." ^ changeRecords keysSortedSafely ! ! !ChangeSet methodsFor: 'class changes' stamp: 'di 3/23/2000 08:12'! changedClasses "Answer an OrderedCollection of changed or edited classes. Does not include removed classes. Sort alphabetically by name." "Much faster to sort names first, then convert back to classes. Because metaclasses reconstruct their name at every comparison in the sorted collection. 8/91 sw chgd to filter out non-existent classes (triggered by problems with class-renames" ^ self changedClassNames collect: [:className | Smalltalk classNamed: className] thenSelect: [:aClass | aClass notNil]! ! !ChangeSet methodsFor: 'class changes' stamp: 'di 4/1/2000 12:00'! classChangeAt: className "Return what we know about class changes to this class." ^ (changeRecords at: className ifAbsent: [^ Set new]) allChangeTypes! ! !ChangeSet methodsFor: 'class changes' stamp: 'NS 1/26/2004 09:46'! commentClass: class "Include indication that a class comment has been changed." class wantsChangeSetLogging ifFalse: [^ self]. self atClass: class add: #comment! ! !ChangeSet methodsFor: 'class changes' stamp: 'nk 6/26/2002 12:30'! containsClass: aClass ^ self changedClasses includes: aClass! ! !ChangeSet methodsFor: 'class changes' stamp: 'RAA 6/16/2000 15:13'! fatDefForClass: class | newDef oldDef oldStrm newStrm outStrm oldVars newVars addedVars | newDef _ class definition. oldDef _ (self changeRecorderFor: class) priorDefinition. oldDef ifNil: [^ newDef]. oldDef = newDef ifTrue: [^ newDef]. oldStrm _ ReadStream on: oldDef. newStrm _ ReadStream on: newDef. outStrm _ WriteStream on: (String new: newDef size * 2). "Merge inst vars from old and new defs..." oldStrm upToAll: 'instanceVariableNames'; upTo: $'. outStrm nextPutAll: (newStrm upToAll: 'instanceVariableNames'); nextPutAll: 'instanceVariableNames:'. newStrm peek = $: ifTrue: [newStrm next]. "may or may not be there, but already written" outStrm nextPutAll: (newStrm upTo: $'); nextPut: $'. oldVars _ (oldStrm upTo: $') findTokens: Character separators. newVars _ (newStrm upTo: $') findTokens: Character separators. addedVars _ oldVars asSet addAll: newVars; removeAll: oldVars; asOrderedCollection. oldVars , addedVars do: [:var | outStrm nextPutAll: var; space]. outStrm nextPut: $'. class isMeta ifFalse: ["Merge class vars from old and new defs..." oldStrm upToAll: 'classVariableNames:'; upTo: $'. outStrm nextPutAll: (newStrm upToAll: 'classVariableNames:'); nextPutAll: 'classVariableNames:'; nextPutAll: (newStrm upTo: $'); nextPut: $'. oldVars _ (oldStrm upTo: $') findTokens: Character separators. newVars _ (newStrm upTo: $') findTokens: Character separators. addedVars _ oldVars asSet addAll: newVars; removeAll: oldVars; asOrderedCollection. oldVars , addedVars do: [:var | outStrm nextPutAll: var; space]. outStrm nextPut: $']. outStrm nextPutAll: newStrm upToEnd. ^ outStrm contents ! ! !ChangeSet methodsFor: 'class changes' stamp: 'tk 6/9/1999 19:54'! noteClassForgotten: className "Remove from structures if class is not a superclass of some other one we are remembering" structures ifNil: [^ self]. Smalltalk at: className ifPresent: [:cls | cls subclasses do: [:sub | (structures includesKey: sub) ifTrue: [ ^ self]]]. "No delete" structures removeKey: className ifAbsent: [].! ! !ChangeSet methodsFor: 'class changes' stamp: 'tk 6/9/1999 21:51'! noteClassStructure: aClass "Save the instance variable names of this class and all of its superclasses. Later we can tell how it changed and write a conversion method. The conversion method is used when old format objects are brought in from the disk from ImageSegment files (.extSeg) or SmartRefStream files (.obj .morph .bo .sp)." | clsName | aClass ifNil: [^ self]. structures ifNil: [structures _ Dictionary new. superclasses _ Dictionary new]. clsName _ (aClass name asLowercase beginsWith: 'anobsolete') ifTrue: [(aClass name copyFrom: 11 to: aClass name size) asSymbol] ifFalse: [aClass name]. (structures includesKey: clsName) ifFalse: [ structures at: clsName put: ((Array with: aClass classVersion), (aClass allInstVarNames)). superclasses at: clsName put: aClass superclass name]. "up the superclass chain" aClass superclass ifNotNil: [self noteClassStructure: aClass superclass]. ! ! !ChangeSet methodsFor: 'class changes' stamp: 'NS 1/19/2004 17:49'! noteRemovalOf: class "The class is about to be removed from the system. Adjust the receiver to reflect that fact." class wantsChangeSetLogging ifFalse: [^ self]. (self changeRecorderFor: class) noteChangeType: #remove fromClass: class. changeRecords removeKey: class class name ifAbsent: [].! ! !ChangeSet methodsFor: 'class changes'! reorganizeClass: class "Include indication that a class was reorganized." self atClass: class add: #reorganize! ! !ChangeSet methodsFor: 'class changes' stamp: 'di 5/16/2000 09:03'! trimHistory "Drop non-essential history: methods added and then removed, as well as rename and reorganization of newly-added classes." changeRecords do: [:chgRecord | chgRecord trimHistory]! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/4/2000 09:37'! absorbClass: className from: otherChangeSet "Absorb into the receiver all the changes found in the class in the other change set. *** Classes renamed in otherChangeSet may have problems" | cls | (self changeRecorderFor: className) assimilateAllChangesIn: (otherChangeSet changeRecorderFor: className). (cls _ Smalltalk classNamed: className) ifNotNil: [self absorbStructureOfClass: cls from: otherChangeSet]. ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 3/23/2000 11:52'! absorbMethod: selector class: aClass from: aChangeSet "Absorb into the receiver all the changes for the method in the class in the other change set." | info | info _ aChangeSet methodChanges at: aClass name ifAbsent: [Dictionary new]. self atSelector: selector class: aClass put: (info at: selector). ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'sw 1/30/2001 15:41'! absorbStructureOfClass: aClass from: otherChangeSet "Absorb into the receiver all the structure and superclass info in the other change set. Used to write conversion methods." | sup next | otherChangeSet structures ifNil: [^ self]. (otherChangeSet structures includesKey: aClass name) ifFalse: [^ self]. structures ifNil: [structures _ Dictionary new. superclasses _ Dictionary new]. sup _ aClass name. [(structures includesKey: sup) ifTrue: ["use what is here" true] ifFalse: [self flag: #noteToDan. "sw 1/30/2001 13:57 emergency workaround -- a case arose where the otherChangeSet's structures did not have the key, and it gummed up the works." (otherChangeSet structures includesKey: sup) ifTrue: [structures at: sup put: (otherChangeSet structures at: sup)]. next _ otherChangeSet superclasses at: sup. superclasses at: sup put: next. (sup _ next) = 'nil'] ] whileFalse. ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/4/2000 11:21'! assimilateAllChangesFoundIn: otherChangeSet "Make all changes in otherChangeSet take effect on self as if they happened just now." otherChangeSet changedClassNames do: [:className | self absorbClass: className from: otherChangeSet] ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/8/2000 23:16'! editPreamble "edit the receiver's preamble, in a separate window. " self assurePreambleExists. preamble openLabel: 'Preamble for ChangeSet named ', name! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/4/2000 11:49'! expungeEmptyClassChangeEntries changeRecords keysAndValuesRemove: [:className :classRecord | classRecord hasNoChanges]! ! !ChangeSet methodsFor: 'moving changes' stamp: 'sw 4/19/2000 16:17'! expungeUniclasses changeRecords keysAndValuesRemove: [:className :classRecord | className endsWithDigit]! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/4/2000 12:40'! forgetAllChangesFoundIn: otherChangeSet "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. To use: in a change sorter, copy over all the changes you want into some new change set, then use the subtract-other-side feature to subtract those changes from the larger change set, and continue in this manner." otherChangeSet == self ifTrue: [^ self]. otherChangeSet changedClassNames do: [:className | self forgetChangesForClass: className in: otherChangeSet]. self expungeEmptyClassChangeEntries. " Old code... aChangeSet changedClassNames do: [:className | (cls _ Smalltalk classNamed: className) ~~ nil ifTrue: [itsMethodChanges _ aChangeSet methodChanges at: className ifAbsent: [Dictionary new]. itsMethodChanges associationsDo: [:assoc | self forgetChange: assoc value forSelector: assoc key class: cls]. myClassChange _ self classChangeAt: className. myClassChange size > 0 ifTrue: [(aChangeSet classChangeAt: className) do: [:aChange | myClassChange remove: aChange ifAbsent: []]]. self noteClassForgotten: className]]. aChangeSet classRemoves do: [:className | (recorder _ changeRecords at: className ifAbsent: []) ifNotNil: [recorder forgetClassRemoval]]. self expungeEmptyClassChangeEntries " ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/4/2000 12:04'! forgetChangesForClass: className in: otherChangeSet "See forgetAllChangesFoundIn:. Used in culling changeSets." (self changeRecorderFor: className) forgetChangesIn: (otherChangeSet changeRecorderFor: className). self noteClassForgotten: className ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'sw 3/5/1999 19:27'! hasPreamble ^ preamble notNil! ! !ChangeSet methodsFor: 'moving changes' stamp: 'nk 3/30/2002 09:13'! methodsWithAnyInitialsOtherThan: myInits "Return a collection of method refs whose author appears to be different from the given one, even historically" | slips method aTimeStamp | slips _ Set new. self changedClasses do: [:aClass | (self methodChangesAtClass: aClass name) associationsDo: [ :mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse: [method _ aClass compiledMethodAt: mAssoc key ifAbsent: [nil]. method ifNotNil: [ (aClass changeRecordsAt: mAssoc key) do: [ :chg | aTimeStamp _ chg stamp. (aTimeStamp notNil and: [(aTimeStamp beginsWith: myInits) not]) ifTrue: [slips add: aClass name , ' ' , mAssoc key]]]]]]. ^ slips! ! !ChangeSet methodsFor: 'moving changes' stamp: 'nk 7/2/2003 10:47'! methodsWithInitialsOtherThan: myInits "Return a collection of method refs whose author appears to be different from the given one" | slips method aTimeStamp | slips _ OrderedCollection new. self changedClasses do: [:aClass | (self methodChangesAtClass: aClass name) associationsDo: [:mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse: [method _ aClass compiledMethodAt: mAssoc key ifAbsent: [nil]. method ifNotNil: [((aTimeStamp _ Utilities timeStampForMethod: method) notNil and: [(aTimeStamp beginsWith: myInits) not]) ifTrue: [slips add: aClass name , ' ' , mAssoc key]]]]]. ^ slips "Smalltalk browseMessageList: (ChangeSet current methodsWithInitialsOtherThan: 'sw') name: 'authoring problems'"! ! !ChangeSet methodsFor: 'moving changes' stamp: 'nk 7/2/2003 10:47'! methodsWithoutComments "Return a collection representing methods in the receiver which have no precode comments" | slips | slips _ OrderedCollection new. self changedClasses do: [:aClass | (self methodChangesAtClass: aClass name) associationsDo: [:mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse: [(aClass selectors includes: mAssoc key) ifTrue: [(aClass firstPrecodeCommentFor: mAssoc key) isEmptyOrNil ifTrue: [slips add: aClass name , ' ' , mAssoc key]]]]]. ^ slips "Smalltalk browseMessageList: (ChangeSet current methodsWithoutComments) name: 'methods lacking comments'"! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/1/2000 12:00'! removeClassAndMetaClassChanges: class "Remove all memory of changes associated with this class and its metaclass. 7/18/96 sw" changeRecords removeKey: class name ifAbsent: []. changeRecords removeKey: class class name ifAbsent: []. ! ! !ChangeSet methodsFor: 'moving changes' stamp: 'di 4/1/2000 12:00'! removeClassChanges: class "Remove all memory of changes associated with this class" | cname | (class isKindOf: String) ifTrue: [ cname _ class ] ifFalse: [ cname _ class name ]. changeRecords removeKey: cname ifAbsent: []. self noteClassForgotten: cname.! ! !ChangeSet methodsFor: 'moving changes' stamp: 'sw 3/5/1999 19:32'! removePreamble preamble _ nil! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'tk 6/8/2001 20:28'! askAddedInstVars: classList | pairList pairClasses index pls newStruct oldStruct | "Ask the author whether these newly added inst vars need to be non-nil" pairList _ OrderedCollection new. pairClasses _ OrderedCollection new. "Class version numbers: If it must change, something big happened. Do need a conversion method then. Ignore them here." classList do: [:cls | newStruct _ (cls allInstVarNames). oldStruct _ (structures at: cls name ifAbsent: [#(0), newStruct]) allButFirst. newStruct do: [:instVarName | (oldStruct includes: instVarName) ifFalse: [ pairList add: cls name, ' ', instVarName. pairClasses add: cls]]]. pairList isEmpty ifTrue: [^ #()]. [index _ PopUpMenu withCaption: 'These instance variables were added. When an old project comes in, newly added instance variables will have the value nil. Click on items to remove them from the list. Click on any for which nil is an OK value.' chooseFrom: pairList, #('all of these need a non-nil value' 'all of these are OK with a nil value'). (index <= (pls _ pairList size)) & (index > 0) ifTrue: [ pairList removeAt: index. pairClasses removeAt: index]. index = (pls + 2) ifTrue: ["all are OK" ^ #()]. pairList isEmpty | (index = (pls + 1)) "all need conversion, exit"] whileFalse. ^ pairClasses asSet asArray "non redundant"! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'tk 6/8/2001 20:29'! askRemovedInstVars: classList | pairList pairClasses index pls newStruct oldStruct | "Ask the author whether these newly removed inst vars need to have their info saved" pairList _ OrderedCollection new. pairClasses _ OrderedCollection new. "Class version numbers: If it must change, something big happened. Do need a conversion method then. Ignore them here." classList do: [:cls | newStruct _ (cls allInstVarNames). oldStruct _ (structures at: cls name ifAbsent: [#(0), newStruct]) allButFirst. oldStruct do: [:instVarName | (newStruct includes: instVarName) ifFalse: [ pairList add: cls name, ' ', instVarName. pairClasses add: cls]]]. pairList isEmpty ifTrue: [^ #()]. [index _ PopUpMenu withCaption: 'These instance variables were removed. When an old project comes in, instance variables that have been removed will lose their contents. Click on items to remove them from the list. Click on any whose value is unimportant and need not be saved.' chooseFrom: pairList, #('all of these need a conversion method' 'all of these have old values that can be erased'). (index <= (pls _ pairList size)) & (index > 0) ifTrue: [ pairList removeAt: index. pairClasses removeAt: index]. index = (pls + 2) ifTrue: ["all are OK" ^ #()]. pairList isEmpty | (index = (pls + 1)) "all need conversion, exit"] whileFalse. ^ pairClasses asSet asArray "non redundant"! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'tk 6/8/2001 11:12'! askRenames: renamed addTo: msgSet using: smart | list rec ans oldStruct newStruct | "Go through the renamed classes. Ask the user if it could be in a project. Add a method in SmartRefStream, and a conversion method in the new class." list _ OrderedCollection new. renamed do: [:cls | rec _ changeRecords at: cls name. rec priorName ifNotNil: [ ans _ PopUpMenu withCaption: 'You renamed class ', rec priorName, ' to be ', rec thisName, '.\Could an instance of ', rec priorName, ' be in a project on someone''s disk?' chooseFrom: #('Yes, write code to convert those instances' 'No, no instances are in projects'). ans = 1 ifTrue: [ oldStruct _ structures at: rec priorName ifAbsent: [nil]. newStruct _ (Array with: cls classVersion), (cls allInstVarNames). oldStruct ifNotNil: [ smart writeConversionMethodIn: cls fromInstVars: oldStruct to: newStruct renamedFrom: rec priorName. smart writeClassRename: cls name was: rec priorName. list add: cls name, ' convertToCurrentVersion:refStream:']] ifFalse: [structures removeKey: rec priorName ifAbsent: []]]]. list isEmpty ifTrue: [^ msgSet]. msgSet messageList ifNil: [msgSet initializeMessageList: list] ifNotNil: [list do: [:item | msgSet addItem: item]]. ^ msgSet! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 9/11/1998 16:13'! assurePostscriptExists "Make sure there is a StringHolder holding the postscript. " "NOTE: FileIn recognizes the postscript by the line with Postscript: on it" postscript == nil ifTrue: [postscript _ StringHolder new contents: '"Postscript: Leave the line above, and replace the rest of this comment by a useful one. Executable statements should follow this comment, and should be separated by periods, with no exclamation points (!!). Be sure to put any further comments in double-quotes, like this one." ']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 4/7/1999 17:45'! assurePreambleExists "Make sure there is a StringHolder holding the preamble; if it's found to have reverted to empty contents, put up the template" (preamble == nil or: [preamble contents isEmptyOrNil]) ifTrue: [preamble _ StringHolder new contents: self preambleTemplate]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/16/2003 09:15'! checkForAlienAuthorship "Check to see if there are any methods in the receiver that have author initials other than that of the current author, and open a browser on all found" | aList initials | (initials _ Utilities authorInitialsPerSe) ifNil: [^ self inform: 'No author initials set in this image']. (aList _ self methodsWithInitialsOtherThan: initials) size > 0 ifFalse: [^ self inform: 'All methods in "', self name, '" have authoring stamps which start with "', initials, '"'] ifTrue: [self systemNavigation browseMessageList: aList name: 'methods in "', self name, '" whose authoring stamps do not start with "', initials, '"']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/16/2003 09:16'! checkForAnyAlienAuthorship "Check to see if there are any versions of any methods in the receiver that have author initials other than that of the current author, and open a browser on all found" | aList initials | (initials _ Utilities authorInitialsPerSe) ifNil: [^ self inform: 'No author initials set in this image']. (aList _ self methodsWithAnyInitialsOtherThan: initials) size > 0 ifFalse: [^ self inform: 'All versions of all methods in "', self name, '" have authoring stamps which start with "', initials, '"'] ifTrue: [self systemNavigation browseMessageList: aList name: 'methods in "', self name, '" with any authoring stamps not starting with "', initials, '"']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:51'! checkForConversionMethods "See if any conversion methods are needed" | oldStruct newStruct tell choice list need sel renamed rec nn | Preferences conversionMethodsAtFileOut ifFalse: [^ self]. "Check preference" structures ifNil: [^ self]. list _ OrderedCollection new. renamed _ OrderedCollection new. self changedClasses do: [:class | need _ (self atClass: class includes: #new) not. need ifTrue: ["Renamed classes." (self atClass: class includes: #rename) ifTrue: [ rec _ changeRecords at: class name. rec priorName ifNotNil: [ (structures includesKey: rec priorName) ifTrue: [ renamed add: class. need _ false]]]]. need ifTrue: [need _ (self atClass: class includes: #change)]. need ifTrue: [oldStruct _ structures at: class name ifAbsent: [need _ false. #()]]. need ifTrue: [ newStruct _ (Array with: class classVersion), (class allInstVarNames). need _ (oldStruct ~= newStruct)]. need ifTrue: [sel _ #convertToCurrentVersion:refStream:. (#(add change) includes: (self atSelector: sel class: class)) ifFalse: [ list add: class]]. ]. list isEmpty & renamed isEmpty ifTrue: [^ self]. "Ask user if want to do this" tell _ 'If there might be instances of ', (list asArray, renamed asArray) printString, '\in a project (.pr file) on someone''s disk, \please ask to write a conversion method.\' withCRs, 'After you edit the conversion method, you''ll need to fileOut again.\' withCRs, 'The preference conversionMethodsAtFileOut in category "fileout" controls this feature.'. choice _ (PopUpMenu labels: 'Write a conversion method by editing a prototype These classes are not used in any object file. fileOut my changes now. I''m too busy. fileOut my changes now. Don''t ever ask again. fileOut my changes now.') startUpWithCaption: tell. choice = 4 ifTrue: [Preferences disable: #conversionMethodsAtFileOut]. choice = 2 ifTrue: ["Don't consider this class again in the changeSet" list do: [:cls | structures removeKey: cls name ifAbsent: []]. renamed do: [:cls | nn _ (changeRecords at: cls name) priorName. structures removeKey: nn ifAbsent: []]]. choice ~= 1 ifTrue: [^ self]. "exit if choice 2,3,4" self error:'No support for writing conversion methods in this stripped image'! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 3/26/2000 10:06'! checkForSlips "Return a collection of method refs with possible debugging code in them." | slips method | slips _ OrderedCollection new. self changedClasses do: [:aClass | (self methodChangesAtClass: aClass name) associationsDo: [:mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse: [method _ aClass compiledMethodAt: mAssoc key ifAbsent: [nil]. method ifNotNil: [method hasReportableSlip ifTrue: [slips add: aClass name , ' ' , mAssoc key]]]]]. ^ slips! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/16/2003 09:16'! checkForUnclassifiedMethods "Open a message list browser on all methods in the current change set that have not been categorized," | aList | (aList _ self methodsWithoutClassifications) size > 0 ifFalse: [^ self inform: 'All methods in "', self name, '" are categorized.'] ifTrue: [self systemNavigation browseMessageList: aList name: 'methods in "', self name, '" which have not been categorized']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 7/19/2002 20:21'! checkForUncommentedClasses "Check to see if any classes involved in this change set do not have class comments. Open up a browser showing all such classes." | aList | aList _ self changedClasses select: [:aClass | aClass theNonMetaClass organization classComment isEmptyOrNil] thenCollect: [:aClass | aClass theNonMetaClass name]. aList size > 0 ifFalse: [^ self inform: 'All classes involved in this change set have class comments'] ifTrue: [ClassListBrowser new initForClassesNamed: aList asSet asSortedArray title: 'Classes in Change Set ', self name, ': classes that lack class comments']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/16/2003 09:16'! checkForUncommentedMethods | aList | "Check to see if there are any methods in the receiver that have no comments, and open a browser on all found" (aList _ self methodsWithoutComments) size > 0 ifFalse: [^ self inform: 'All methods in "', self name, '" have comments'] ifTrue: [self systemNavigation browseMessageList: aList name: 'methods in "', self name, '" that lack comments']! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/29/2003 20:19'! checkForUnsentMessages "Check the change set for unsent messages, and if any are found, open up a message-list browser on them" | nameLine allChangedSelectors augList unsent | nameLine _ '"' , self name , '"'. allChangedSelectors _ Set new. (augList _ self changedMessageListAugmented) do: [:each | each isValid ifTrue: [allChangedSelectors add: each methodSymbol]]. unsent _ self systemNavigation allUnSentMessagesIn: allChangedSelectors. unsent size = 0 ifTrue: [^ self inform: 'There are no unsent messages in change set ' , nameLine]. self systemNavigation browseMessageList: (augList select: [:each | unsent includes: each methodSymbol]) name: 'Unsent messages in ' , nameLine! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'FBS 1/6/2004 16:59'! chooseSubjectPrefixForEmail | subjectIndex | subjectIndex _ (PopUpMenu labels: 'Bug fix [FIX]\Enhancement [ENH]\Goodie [GOODIE]\Test suite [TEST]\None of the above (will not be archived)' withCRs) startUpWithCaption: 'What type of change set\are you submitting to the list?' withCRs. ^ #('[CS] ' '[FIX] ' '[ENH] ' '[GOODIE] ' '[TEST] ' '[CS] ') at: subjectIndex + 1! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'nk 10/15/2003 09:55'! defaultChangeSetDirectory ^self class defaultChangeSetDirectory! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'nk 1/4/2004 17:07'! fileOut "File out the receiver, to a file whose name is a function of the change-set name and either of the date & time or chosen to have a unique numeric tag, depending on the preference 'changeSetVersionNumbers'" | file slips nameToUse | self checkForConversionMethods. ChangeSet promptForDefaultChangeSetDirectoryIfNecessary. nameToUse := Preferences changeSetVersionNumbers ifTrue: [self defaultChangeSetDirectory nextNameFor: self name extension: 'cs'] ifFalse: [(self name , FileDirectory dot , Utilities dateTimeSuffix , FileDirectory dot , 'cs') asFileName]. (Preferences warningForMacOSFileNameLength and: [nameToUse size > 31]) ifTrue: [nameToUse := FillInTheBlank request: (nameToUse , '\has ' , nameToUse size asString , ' letters - too long for Mac OS.\Suggested replacement is:') withCRs initialAnswer: (nameToUse contractTo: 30). nameToUse = '' ifTrue: [^ self]]. Cursor write showWhile: [[file := self defaultChangeSetDirectory newFileNamed: nameToUse. file header; timeStamp. self fileOutPreambleOn: file. self fileOutOn: file. self fileOutPostscriptOn: file. file trailer] ensure: [file close]]. Preferences checkForSlips ifFalse: [^ self]. slips := self checkForSlips. (slips size > 0 and: [(PopUpMenu withCaption: 'Methods in this fileOut have halts or references to the Transcript or other ''slips'' in them. Would you like to browse them?' chooseFrom: 'Ignore\Browse slips') = 2]) ifTrue: [self systemNavigation browseMessageList: slips name: 'Possible slips in ' , name]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 3/28/2000 09:35'! fileOutChangesFor: class on: stream "Write out all the method changes for this class." | changes | changes _ Set new. (self methodChangesAtClass: class name) associationsDo: [:mAssoc | (mAssoc value = #remove or: [mAssoc value = #addedThenRemoved]) ifFalse: [changes add: mAssoc key]]. changes isEmpty ifFalse: [class fileOutChangedMessages: changes on: stream. stream cr]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/23/2001 13:29'! fileOutOn: stream "Write out all the changes the receiver knows about" | classList | (self isEmpty and: [stream isKindOf: FileStream]) ifTrue: [self inform: 'Warning: no changes to file out']. classList _ ChangeSet superclassOrder: self changedClasses asOrderedCollection. "First put out rename, max classDef and comment changes." classList do: [:aClass | self fileOutClassDefinition: aClass on: stream]. "Then put out all the method changes" classList do: [:aClass | self fileOutChangesFor: aClass on: stream]. "Finally put out removals, final class defs and reorganization if any" classList reverseDo: [:aClass | self fileOutPSFor: aClass on: stream]. self classRemoves asSortedCollection do: [:aClassName | stream nextChunkPut: 'Smalltalk removeClassNamed: #', aClassName; cr].! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 5/8/2000 20:47'! fileOutPSFor: class on: stream "Write out removals and initialization for this class." | dict changeType classRecord currentDef | classRecord _ changeRecords at: class name ifAbsent: [^ self]. dict _ classRecord methodChangeTypes. dict keysSortedSafely do: [:key | changeType _ dict at: key. (#(remove addedThenRemoved) includes: changeType) ifTrue: [stream nextChunkPut: class name, ' removeSelector: ', key storeString; cr] ifFalse: [(key = #initialize and: [class isMeta]) ifTrue: [stream nextChunkPut: class soleInstance name, ' initialize'; cr]]]. ((classRecord includesChangeType: #change) and: [(currentDef _ class definition) ~= (self fatDefForClass: class)]) ifTrue: [stream command: 'H3'; nextChunkPut: currentDef; cr; command: '/H3']. (classRecord includesChangeType: #reorganize) ifTrue: [class fileOutOrganizationOn: stream. stream cr]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 3/29/1999 13:35'! fileOutPostscriptOn: stream "If the receiver has a postscript, put it out onto the stream. " | aString | aString _ self postscriptString. (aString ~~ nil and: [aString size > 0]) ifTrue: [stream nextChunkPut: aString "surroundedBySingleQuotes". stream cr; cr]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 3/29/1999 14:58'! fileOutPreambleOn: stream "If the receiver has a preamble, put it out onto the stream. " | aString | aString _ self preambleString. (aString ~~ nil and: [aString size > 0]) ifTrue: [stream nextChunkPut: aString "surroundedBySingleQuotes". stream cr; cr]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 4/16/2003 09:16'! lookForSlips "Scan the receiver for changes that the user may regard as slips to be remedied" | slips nameLine msg | nameLine _ ' "', self name, '" '. (slips _ self checkForSlips) size == 0 ifTrue: [^ self inform: 'No slips detected in change set', nameLine]. msg _ slips size == 1 ifTrue: [ 'One method in change set', nameLine, 'has a halt, reference to the Transcript, and/or some other ''slip'' in it. Would you like to browse it? ?'] ifFalse: [ slips size printString, ' methods in change set', nameLine, 'have halts or references to the Transcript or other ''slips'' in them. Would you like to browse them?']. (PopUpMenu withCaption: msg chooseFrom: 'Ignore\Browse slips') = 2 ifTrue: [self systemNavigation browseMessageList: slips name: 'Possible slips in ', name]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:16'! postscriptString "Answer the string representing the postscript. " ^ postscript == nil ifTrue: [postscript] ifFalse: [postscript contents asString]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'! postscriptString: aString "Establish aString as the new contents of the postscript. " postscript _ StringHolder new contents: aString! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:08'! preambleString "Answer the string representing the preamble" ^ preamble == nil ifTrue: [preamble] ifFalse: [preamble contents asString]! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'! preambleString: aString "Establish aString as the new contents of the preamble. " preamble _ StringHolder new contents: aString! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'nk 7/2/2003 10:47'! preambleTemplate "Answer a string that will form the default contents for a change set's preamble. Just a first stab at what the content should be." ^ String streamContents: [:strm | strm nextPutAll: '"Change Set:'. "NOTE: fileIn recognizes preambles by this string." strm tab;tab; nextPutAll: self name. strm cr; nextPutAll: 'Date:'; tab; tab; tab; nextPutAll: Date today printString. strm cr; nextPutAll: 'Author:'; tab; tab; tab; nextPutAll: Preferences defaultAuthorName. strm cr; cr; nextPutAll: '<your descriptive text goes here>"'] "ChangeSet current preambleTemplate"! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 3/30/2001 13:47'! setPreambleToSay: aString "Make aString become the preamble of this change set" preamble _ StringHolder new contents: aString! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 9/24/1999 12:33'! summaryString "Answer the string summarizing this changeSet" ^ self summaryStringDelta: 0 " To summarize all recent changeSets on a file... (FileStream newFileNamed: 'Summaries.txt') nextPutAll: (String streamContents: [:s | (ChangeSorter changeSetsNamedSuchThat: [:name | name first isDigit and: [name initialIntegerOrNil >= 948]]) do: [:cs | s nextPutAll: cs summaryString; cr]]); close To list all changeSets with a certain string in the preamble... (FileStream newFileNamed: 'MyUpdates.txt') nextPutAll: (String streamContents: [:s | ChangeSorter gatherChangeSetRevertables do: [:cs | (cs preambleString notNil and: [cs preambleString includesSubString: 'Author Name']) ifTrue: [s nextPutAll: cs summaryString; cr]]]); close "! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'di 9/24/1999 12:27'! summaryStringDelta: delta "Answer the string summarizing this changeSet" | ps s2 date author line intName | ^ String streamContents: [:s | intName _ self name splitInteger. intName first isNumber ifTrue: [s nextPutAll: (intName first + delta) printString , intName last] ifFalse: [s nextPutAll: intName first "weird convention of splitInteger"]. (ps _ self preambleString) ifNil: [s cr] ifNotNil: [s2 _ ReadStream on: ps. s2 match: 'Date:'; skipSeparators. date _ s2 upTo: Character cr. s2 match: 'Author:'; skipSeparators. author _ s2 upTo: Character cr. s nextPutAll: ' -- '; nextPutAll: author; nextPutAll: ' -- '; nextPutAll: date; cr. [s2 atEnd] whileFalse: [line _ s2 upTo: Character cr. (line isEmpty or: [line = '"']) ifFalse: [s nextPutAll: line; cr]]]]. ! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sd 1/16/2004 21:31'! verboseFileOut "File out the receiver, to a file whose name is a function of the change-set name and either of the date & time or chosen to have a unique numeric tag, depending on the preference 'changeSetVersionNumbers'" ChangeSet current fileOut. Transcript cr; show: 'Changes filed out ', Date dateAndTimeNow printString! ! !ChangeSet methodsFor: 'private' stamp: 'di 3/23/2000 08:37'! addCoherency: className "SqR!! 19980923: If I recreate the class then don't remove it" (self changeRecorderFor: className) checkCoherence. " classRemoves remove: className ifAbsent: []. (classChanges includesKey: className) ifTrue: [(classChanges at: className) remove: #remove ifAbsent: []] "! ! !ChangeSet methodsFor: 'private' stamp: 'di 3/28/2000 14:40'! atClass: class add: changeType (self changeRecorderFor: class) noteChangeType: changeType fromClass: class! ! !ChangeSet methodsFor: 'private' stamp: 'di 4/1/2000 12:00'! atClass: class includes: changeType ^(changeRecords at: class name ifAbsent: [^false]) includesChangeType: changeType! ! !ChangeSet methodsFor: 'private' stamp: 'di 4/1/2000 12:00'! atSelector: selector class: class ^ (changeRecords at: class name ifAbsent: [^ #none]) atSelector: selector ifAbsent: [^ #none]! ! !ChangeSet methodsFor: 'private' stamp: 'di 3/29/2000 20:46'! changeRecorderFor: class | cname | (class isKindOf: String) ifTrue: [ cname _ class ] ifFalse: [ cname _ class name ]. "Later this will init the changeRecords so according to whether they should be revertable." ^ changeRecords at: cname ifAbsent: [^ changeRecords at: cname put: (ClassChangeRecord new initFor: cname revertable: revertable)]! ! !ChangeSet methodsFor: 'private' stamp: 'ssa 9/3/2008 10:28'! fileOutClassDefinition: class on: stream "Write out class definition for the given class on the given stream, if the class definition was added or changed." (self atClass: class includes: #rename) ifTrue: [stream nextChunkPut: 'Smalltalk renameClassNamed: #', (self oldNameFor: class), ' as: #', class name; cr]. (self atClass: class includes: #change) ifTrue: [ "fat definition only needed for changes" stream command: 'H3'; nextChunkPut: (self fatDefForClass: class); cr; command: '/H3'. ] ifFalse: [ (self atClass: class includes: #add) ifTrue: [ "use current definition for add" stream command: 'H3'; nextChunkPut: class definition; cr; command: '/H3'. ]. ]. (self atClass: class includes: #comment) ifTrue: [class theNonMetaClass organization putCommentOnFile: stream numbered: 0 moveSource: false forClass: class theNonMetaClass. stream cr]. ! ! !ChangeSet methodsFor: 'private' stamp: 'di 4/1/2000 12:00'! oldNameFor: class ^ (changeRecords at: class name) priorName! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ChangeSet class instanceVariableNames: 'current'! !ChangeSet class methodsFor: 'current changeset' stamp: 'sd 5/22/2003 19:59'! browseChangedMessages "Create and schedule a message browser on each method that has been changed." current isEmpty ifTrue: [^ self inform: 'There are no changed messages in the current change set.']. ChangedMessageSet openFor: current! ! !ChangeSet class methodsFor: 'current changeset' stamp: 'sd 5/22/2003 21:53'! current "return the current changeset" ^ current! ! !ChangeSet class methodsFor: 'current changeset' stamp: 'sd 5/22/2003 22:24'! currentChangeSetString "ChangeSet current currentChangeSetString" ^ 'Current Change Set: ', self current name! ! !ChangeSet class methodsFor: 'current changeset' stamp: 'NS 1/16/2004 14:49'! newChanges: aChangeSet "Set the system ChangeSet to be the argument, aChangeSet. Tell the current project that aChangeSet is now its change set. When called from Project enter:, the setChangeSet: call is redundant but harmless; when called from code that changes the current-change-set from within a project, it's vital" SystemChangeNotifier uniqueInstance noMoreNotificationsFor: current. current isolationSet: nil. current _ aChangeSet. SystemChangeNotifier uniqueInstance notify: aChangeSet ofAllSystemChangesUsing: #event:. Smalltalk currentProjectDo: [:proj | proj setChangeSet: aChangeSet. aChangeSet isolationSet: proj isolationSet]! ! !ChangeSet class methodsFor: 'current changeset' stamp: 'sd 5/22/2003 22:18'! noChanges "Initialize the system ChangeSet." current initialize! ! !ChangeSet class methodsFor: 'defaults' stamp: 'nk 7/18/2004 16:13'! defaultChangeSetDirectory "Answer the directory in which to store ChangeSets. Answer the default directory if the preferred directory doesn't exist." | dir directoryName | directoryName := Preferences parameterAt: #defaultChangeSetDirectoryName ifAbsentPut: ['']. dir := directoryName isEmptyOrNil ifTrue: [ FileDirectory default ] ifFalse: [ FileDirectory default directoryNamed: directoryName ]. dir exists ifTrue: [^ dir]. ^ FileDirectory default! ! !ChangeSet class methodsFor: 'defaults' stamp: 'nk 3/24/2004 15:52'! defaultChangeSetDirectory: dirOrName "Set the Preference for storing change sets to the given directory or name (possibly relative). Rewrite directory names below the default directory as relative names. If dirOrName is an empty string, use the default directory." "ChangeSet defaultChangeSetDirectory: 'changeSets'" | dirName defaultFullName | dirName := dirOrName isString ifTrue: [FileDirectory default fullNameFor: dirOrName] ifFalse: [dirOrName fullName]. defaultFullName := FileDirectory default fullName. dirName = defaultFullName ifTrue: [dirName := ''] ifFalse: [(dirName beginsWith: defaultFullName , FileDirectory slash) ifTrue: [dirName := dirName copyFrom: defaultFullName size + 2 to: dirName size]]. Preferences setParameter: #defaultChangeSetDirectoryName to: dirName! ! !ChangeSet class methodsFor: 'defaults' stamp: 'dgd 9/6/2003 19:56'! defaultName ^ self uniqueNameLike: 'Unnamed' translated! ! !ChangeSet class methodsFor: 'defaults' stamp: 'BG 8/18/2004 15:19'! promptForDefaultChangeSetDirectoryIfNecessary "Check the Preference (if any), and prompt the user to change it if necessary. The default if the Preference is unset is the current directory. Answer the directory." "ChangeSet promptForDefaultChangeSetDirectoryIfNecessary" | choice directoryName dir | directoryName := Preferences parameterAt: #defaultChangeSetDirectoryName ifAbsentPut: ['']. [dir := FileDirectory default directoryNamed: directoryName. dir exists] whileFalse: [choice := PopUpMenu withCaption: ('The preferred change set directory (''{1}'') does not exist. Create it or use the default directory ({2})?' translated format: { directoryName. FileDirectory default pathName }) chooseFrom: (#('Create directory' 'Use default directory and forget preference' 'Choose another directory' ) collect: [ :ea | ea translated ]). choice = 1 ifTrue: [dir assureExistence ]. choice = 3 ifTrue: [dir := FileList modalFolderSelector. directoryName := dir ifNil: [ '' ] ifNotNil: [dir pathName ]]]. self defaultChangeSetDirectory: directoryName. ^dir! ! !ChangeSet class methodsFor: 'defaults' stamp: 'di 4/5/2001 21:31'! uniqueNameLike: aString | try | 1 to: 999999 do: [:i | try _ aString , i printString. (ChangeSorter changeSetNamed: try) ifNil: [^ try]]! ! !ChangeSet class methodsFor: 'fileIn/Out' stamp: 'SqR 11/14/2000 11:36'! doWeFileOut: aClass given: aSet cache: cache | aClassAllSuperclasses aClassSoleInstanceAllSuperclasses | aClassAllSuperclasses _ cache at: aClass ifAbsent: [cache at: aClass put: aClass allSuperclasses asArray]. (aSet includesAnyOf: aClassAllSuperclasses) ifTrue: [^false]. aClass isMeta ifFalse: [^true]. (aSet includes: aClass soleInstance) ifTrue: [^false]. aClassSoleInstanceAllSuperclasses _ cache at: aClass soleInstance ifAbsent: [cache at: aClass soleInstance put: aClass soleInstance allSuperclasses asArray]. (aSet includesAnyOf: aClassSoleInstanceAllSuperclasses) ifTrue: [^false]. ^true! ! !ChangeSet class methodsFor: 'fileIn/Out' stamp: 'SqR 11/14/2000 11:37'! superclassOrder: classes "Arrange the classes in the collection, classes, in superclass order so the classes can be properly filed in. Do it in sets instead of ordered collections. SqR 4/12/2000 22:04" | all list aClass inclusionSet aClassIndex cache | list _ classes copy. "list is indexable" inclusionSet _ list asSet. cache _ Dictionary new. all _ OrderedCollection new: list size. list size timesRepeat: [ aClassIndex _ list findFirst: [:one | one isNil not and: [self doWeFileOut: one given: inclusionSet cache: cache]]. aClass _ list at: aClassIndex. all addLast: aClass. inclusionSet remove: aClass. list at: aClassIndex put: nil ]. ^all! ! !ChangeSet class methodsFor: 'instance creation' stamp: 'di 4/6/2001 09:43'! basicNewNamed: aName ^ (self basicNew name: aName) initialize! ! !ChangeSet class methodsFor: 'instance creation' stamp: 'di 4/6/2001 10:02'! new "All current changeSets must be registered in the AllChangeSets collection. Due to a quirk of history, this is maintained as class variable of ChangeSorter." ^ ChangeSorter basicNewChangeSet: ChangeSet defaultName! ! ChangeSorter subclass: #ChangeSetBrowser instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeSetBrowser commentStamp: '<historical>' prior: 0! A tool allowing you to browse the methods of a single change set.! !ChangeSetBrowser methodsFor: 'initialization' stamp: 'BG 10/28/2003 20:47'! addModelItemsToWindowMenu: aMenu "Add model-related items to the given window menu" | oldTarget | oldTarget _ aMenu defaultTarget. aMenu defaultTarget: self. aMenu addLine. aMenu add: 'rename change set' action: #rename. aMenu add: 'make changes go to me' action: #newCurrent. aMenu addLine. aMenu add: 'file out' action: #fileOut. aMenu add: 'browse methods' action: #browseChangeSet. aMenu addLine. myChangeSet hasPreamble ifTrue: [aMenu add: 'edit preamble' action: #addPreamble. aMenu add: 'remove preamble' action: #removePreamble] ifFalse: [aMenu add: 'add preamble' action: #addPreamble]. myChangeSet hasPostscript ifTrue: [aMenu add: 'edit postscript...' action: #editPostscript. aMenu add: 'remove postscript' action: #removePostscript] ifFalse: [aMenu add: 'add postscript...' action: #editPostscript]. aMenu addLine. aMenu add: 'destroy change set' action: #remove. aMenu addLine. aMenu addLine. aMenu add: 'more...' action: #offerShiftedChangeSetMenu. aMenu defaultTarget: oldTarget. ^ aMenu! ! !ChangeSetBrowser methodsFor: 'initialization' stamp: 'sw 3/14/2001 10:03'! wantsAnnotationPane "This kind of browser always wants annotation panes, so answer true" ^ true! ! !ChangeSetBrowser methodsFor: 'initialization' stamp: 'sw 3/9/2001 15:02'! wantsOptionalButtons "Sure, why not?" ^ true! ! !ChangeSetBrowser methodsFor: 'menu' stamp: 'sw 3/12/2001 14:07'! offerUnshiftedChangeSetMenu "The user chose 'more' from the shifted window menu; go back to the regular window menu" self containingWindow ifNotNil: [self containingWindow offerWindowMenu] ! ! !ChangeSetBrowser methodsFor: 'menu' stamp: 'BG 10/28/2003 20:47'! shiftedChangeSetMenu: aMenu "Set up aMenu to hold items relating to the change-set-list pane when the shift key is down" aMenu add: 'conflicts with other change sets' action: #browseMethodConflicts. aMenu balloonTextForLastItem: 'Browse all methods that occur both in this change set and in at least one other change set.'. aMenu addLine. aMenu add: 'check for slips' action: #lookForSlips. aMenu balloonTextForLastItem: 'Check this change set for halts and references to Transcript.'. aMenu add: 'check for unsent messages' action: #checkForUnsentMessages. aMenu balloonTextForLastItem: 'Check this change set for messages that are not sent anywhere in the system'. aMenu add: 'check for uncommented methods' action: #checkForUncommentedMethods. aMenu balloonTextForLastItem: 'Check this change set for methods that do not have comments'. aMenu add: 'check for uncommented classes' action: #checkForUncommentedClasses. aMenu balloonTextForLastItem: 'Check for classes with code in this changeset which lack class comments'. Utilities authorInitialsPerSe isEmptyOrNil ifFalse: [aMenu add: 'check for other authors' action: #checkForAlienAuthorship. aMenu balloonTextForLastItem: 'Check this change set for methods whose current authoring stamp does not start with "', Utilities authorInitials, '"'. aMenu add: 'check for any other authors' action: #checkForAnyAlienAuthorship. aMenu balloonTextForLastItem: 'Check this change set for methods any of whose previous authoring stamps do not start with "', Utilities authorInitials, '"']. aMenu add: 'check for uncategorized methods' action: #checkForUnclassifiedMethods. aMenu balloonTextForLastItem: 'Check to see if any methods in the selected change set have not yet been assigned to a category. If any are found, open a browser on them.'. aMenu addLine. aMenu add: 'inspect change set' action: #inspectChangeSet. aMenu balloonTextForLastItem: 'Open an inspector on this change set. (There are some details in a change set which you don''t see in a change sorter.)'. aMenu add: 'update' action: #update. aMenu balloonTextForLastItem: 'Update the display for this change set. (This is done automatically when you activate this window, so is seldom needed.)'. aMenu add: 'go to change set''s project' action: #goToChangeSetsProject. aMenu balloonTextForLastItem: 'If this change set is currently associated with a Project, go to that project right now.'. aMenu add: 'trim history' action: #trimHistory. aMenu balloonTextForLastItem: ' Drops any methods added and then removed, as well as renaming and reorganization of newly-added classes. NOTE: can cause confusion if later filed in over an earlier version of these changes'. aMenu add: 'clear this change set' action: #clearChangeSet. aMenu balloonTextForLastItem: 'Reset this change set to a pristine state where it holds no information. CAUTION: this is destructive and irreversible!!'. aMenu add: 'expunge uniclasses' action: #expungeUniclasses. aMenu balloonTextForLastItem: 'Remove from the change set all memory of uniclasses, e.g. classes added on behalf of etoys, fabrik, etc., whose classnames end with a digit.'. aMenu add: 'uninstall this change set' action: #uninstallChangeSet. aMenu balloonTextForLastItem: 'Attempt to uninstall this change set. CAUTION: this may not work completely and is irreversible!!'. aMenu addLine. aMenu add: 'more...' action: #offerUnshiftedChangeSetMenu. aMenu balloonTextForLastItem: 'Takes you back to the primary change-set menu.'. ^ aMenu! ! ElementCategory subclass: #ChangeSetCategory instanceVariableNames: 'membershipSelector' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeSetCategory commentStamp: '<historical>' prior: 0! A ChangeSetCategory represents a list of change sets to be shown in a ChangeSorter. It computes whether a given change set is in the list by sending its membershipSelector to ChangeSorter (i.e. the class object) with the change set as message argument.! !ChangeSetCategory methodsFor: 'initialization' stamp: 'sw 3/30/2001 12:35'! membershipSelector: aSelector "Set the membershipSelector" membershipSelector _ aSelector! ! !ChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:11'! acceptsManualAdditions "Answer whether the user is allowed manually to manipulate the contents of the change-set-category." ^ false! ! !ChangeSetCategory methodsFor: 'queries' stamp: 'sw 3/30/2001 14:39'! changeSetList "Answer the list of change-set names in the category" | aChangeSet | self reconstituteList. keysInOrder size == 0 ifTrue: ["don't tolerate emptiness, because ChangeSorters gag when they have no change-set selected" aChangeSet _ ChangeSorter assuredChangeSetNamed: 'New Changes'. self elementAt: aChangeSet name put: aChangeSet]. ^ keysInOrder reversed! ! !ChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/5/2001 17:26'! hasChangeForClassName: aClassName selector: aSelector otherThanIn: excludedChangeSet "Answer whether any change set in this category, other than the excluded one, has a change marked for the given class and selector" self elementsInOrder do: [:aChangeSet | (aChangeSet ~~ excludedChangeSet and: [((aChangeSet methodChangesAtClass: aClassName) includesKey: aSelector)]) ifTrue: [^ true]]. ^ false! ! !ChangeSetCategory methodsFor: 'queries' stamp: 'sw 3/30/2001 14:04'! includesChangeSet: aChangeSet "Answer whether the receiver includes aChangeSet in its retrieval list" ^ ChangeSorter perform: membershipSelector with: aChangeSet! ! !ChangeSetCategory methodsFor: 'services' stamp: 'sd 1/16/2004 21:37'! fileOutAllChangeSets "File out all the nonempty change sets in the current category, suppressing the checks for slips that might otherwise ensue. Obtain user confirmation before undertaking this possibly prodigious task." | aList | aList _ self elementsInOrder select: [:aChangeSet | aChangeSet isEmpty not]. aList size == 0 ifTrue: [^ self inform: 'sorry, all the change sets in this category are empty']. (self confirm: 'This will result in filing out ', aList size printString, ' change set(s) Are you certain you want to do this?') ifFalse: [^ self]. Preferences setFlag: #checkForSlips toValue: false during: [ChangeSorter fileOutChangeSetsNamed: (aList collect: [:m | m name]) asSortedArray]! ! !ChangeSetCategory methodsFor: 'services' stamp: 'BG 10/28/2003 20:38'! fillAggregateChangeSet "Create a change-set named Aggregate and pour into it all the changes in all the change-sets of the currently-selected category" | aggChangeSet | aggChangeSet _ ChangeSorter assuredChangeSetNamed: #Aggregate. aggChangeSet clear. aggChangeSet setPreambleToSay: '"Change Set: Aggregate Created at ', Time now printString, ' on ', Date today printString, ' by combining all the changes in all the change sets in the category ', categoryName printString, '"'. (self elementsInOrder copyWithout: aggChangeSet) do: [:aChangeSet | aggChangeSet assimilateAllChangesFoundIn: aChangeSet]. ! ! !ChangeSetCategory methodsFor: 'miscellaneous' stamp: 'sd 5/23/2003 14:25'! defaultChangeSetToShow "Answer the name of a change-set to show" ^ ChangeSet current! ! !ChangeSetCategory methodsFor: 'miscellaneous' stamp: 'di 4/6/2001 10:37'! reconstituteList "Clear out the receiver's elements and rebuild them" | newMembers | "First determine newMembers and check if they have not changed..." newMembers _ ChangeSorter allChangeSets select: [:aChangeSet | ChangeSorter perform: membershipSelector with: aChangeSet]. (newMembers collect: [:cs | cs name]) = keysInOrder ifTrue: [^ self "all current"]. "Things have changed. Need to recompute the whole category" self clear. newMembers do: [:aChangeSet | self fasterElementAt: aChangeSet name asSymbol put: aChangeSet] ! ! ChangeSetCategory subclass: #ChangeSetCategoryWithParameters instanceVariableNames: 'parameters' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ChangeSetCategoryWithParameters methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2002 12:34'! acceptsManualAdditions "Answer whether the user is allowed manually to manipulate the contents of the change-set-category." ^ true! ! !ChangeSetCategoryWithParameters methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2002 12:43'! addChangeSet: aChangeSet self inform: 'sorry, you can''t do that'! ! !ChangeSetCategoryWithParameters methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2002 12:08'! includesChangeSet: aChangeSet "Answer whether the receiver includes aChangeSet in its retrieval list" ^ ChangeSorter perform: membershipSelector withArguments: { aChangeSet } , parameters! ! !ChangeSetCategoryWithParameters methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2002 12:04'! parameters: anArray parameters _ anArray! ! !ChangeSetCategoryWithParameters methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2002 12:16'! reconstituteList "Clear out the receiver's elements and rebuild them" | newMembers | "First determine newMembers and check if they have not changed..." newMembers _ ChangeSorter allChangeSets select: [:aChangeSet | ChangeSorter perform: membershipSelector withArguments: { aChangeSet }, parameters]. (newMembers collect: [:cs | cs name]) = keysInOrder ifTrue: [^ self "all current"]. "Things have changed. Need to recompute the whole category" self clear. newMembers do: [:aChangeSet | self fasterElementAt: aChangeSet name asSymbol put: aChangeSet]! ! CodeHolder subclass: #ChangeSorter instanceVariableNames: 'parent myChangeSet currentClassName currentSelector priorChangeSetList changeSetCategory' classVariableNames: 'AllChangeSets ChangeSetCategories ChangeSetNamesInRelease PreviousSet RecentUpdateMarker' poolDictionaries: '' category: 'Tools-Changes'! !ChangeSorter commentStamp: '<historical>' prior: 0! I display a ChangeSet. Two of me are in a DualChangeSorter.! !ChangeSorter methodsFor: 'creation' stamp: 'BG 11/26/2003 14:18'! open "ChangeSorterPluggable new open" | topView | topView _ StandardSystemView new. topView model: self. myChangeSet ifNil: [self myChangeSet: ChangeSet current]. topView label: self labelString. topView borderWidth: 1; minimumSize: 360@360. self openView: topView offsetBy: 0@0. topView controller open. ! ! !ChangeSorter methodsFor: 'creation' stamp: 'sw 2/26/2001 12:00'! openView: topView offsetBy: offset "Add a set of change sorter views to the given top view offset by the given amount. To create a single change sorter, call this once with an offset of 0@0. To create a dual change sorter, call it twice with offsets of 0@0 and 360@0." | classView messageView codeView cngSetListView basePane annoPane annoHeight | contents _ ''. annoHeight _ 20. self addDependent: topView. "so it will get changed: #relabel" cngSetListView _ PluggableListViewByItem on: self list: #changeSetList selected: #currentCngSet changeSelected: #showChangeSetNamed: menu: #changeSetMenu:shifted: keystroke: #changeSetListKey:from:. cngSetListView window: ((0@0 extent: 180@100) translateBy: offset). topView addSubView: cngSetListView. classView _ PluggableListViewByItem on: self list: #classList selected: #currentClassName changeSelected: #currentClassName: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classView window: ((0@0 extent: 180@100) translateBy: offset). topView addSubView: classView toRightOf: cngSetListView. messageView _ PluggableListViewByItem on: self list: #messageList selected: #currentSelector changeSelected: #currentSelector: menu: #messageMenu:shifted: keystroke: #messageListKey:from:. messageView menuTitleSelector: #messageListSelectorTitle. messageView window: ((0@0 extent: 360@100) translateBy: offset). topView addSubView: messageView below: cngSetListView. self wantsAnnotationPane ifFalse: [basePane _ messageView] ifTrue: [annoPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annoPane window: ((0@0 extent: 360@annoHeight) translateBy: offset). topView addSubView: annoPane below: messageView. basePane _ annoPane]. codeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. codeView window: ((0 @ 0 extent: 360 @ 180) translateBy: offset). topView addSubView: codeView below: basePane.! ! !ChangeSorter methodsFor: 'creation' stamp: 'sw 3/29/2001 14:46'! setDefaultChangeSetCategory "Set a default ChangeSetCategory for the receiver, and answer it" ^ changeSetCategory _ self class changeSetCategoryNamed: #All! ! !ChangeSorter methodsFor: 'creation' stamp: 'tk 12/7/1999 12:53'! veryDeepFixupWith: deepCopier super veryDeepFixupWith: deepCopier. parent _ deepCopier references at: parent ifAbsent: [parent]. self updateIfNecessary! ! !ChangeSorter methodsFor: 'creation' stamp: 'sw 3/29/2001 13:01'! veryDeepInner: deepCopier "Copy all of my instance variables. Some need to be not copied at all, but shared." super veryDeepInner: deepCopier. "parent _ parent. Weakly copied" "myChangeSet _ myChangeSet. Weakly copied" currentClassName _ currentClassName veryDeepCopyWith: deepCopier. "currentSelector _ currentSelector. Symbol" priorChangeSetList _ priorChangeSetList veryDeepCopyWith: deepCopier. changeSetCategory _ changeSetCategory. ! ! !ChangeSorter methodsFor: 'access' stamp: 'tk 4/29/1998 08:22'! changeSet ^ myChangeSet! ! !ChangeSorter methodsFor: 'access' stamp: 'sw 3/29/2001 14:45'! changeSetCategory "Answer the current changeSetCategory object that governs which change sets are shown in this ChangeSorter" ^ changeSetCategory ifNil: [self setDefaultChangeSetCategory]! ! !ChangeSorter methodsFor: 'access' stamp: 'sw 1/27/2000 11:19'! changeSetCurrentlyDisplayed ^ myChangeSet! ! !ChangeSorter methodsFor: 'access' stamp: 'tk 4/30/1998 13:37'! label ^ self labelString! ! !ChangeSorter methodsFor: 'access' stamp: 'sd 5/23/2003 14:25'! labelString "The label for my entire window. The large button that displays my name is gotten via mainButtonName" ^ String streamContents: [:aStream | aStream nextPutAll: (ChangeSet current == myChangeSet ifTrue: ['Changes go to "', myChangeSet name, '"'] ifFalse: ['ChangeSet: ', myChangeSet name]). (self changeSetCategory categoryName ~~ #All) ifTrue: [aStream nextPutAll: ' - ', self parenthesizedCategoryName]]! ! !ChangeSorter methodsFor: 'access' stamp: 'sma 11/11/2000 23:28'! modelWakeUp "A window with me as model is being entered. Make sure I am up-to-date with the changeSets." self canDiscardEdits ifTrue: [self update]! ! !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:43'! myChangeSet: anObject myChangeSet _ anObject! ! !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:42'! parent ^ parent! ! !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:42'! parent: anObject parent _ anObject! ! !ChangeSorter methodsFor: 'access' stamp: 'sw 3/29/2001 22:51'! parenthesizedCategoryName "Answer my category name in parentheses" ^ ' (', self changeSetCategory categoryName, ')'! ! !ChangeSorter methodsFor: 'access' stamp: 'sw 1/28/1999 12:31'! showChangeSet: chgSet myChangeSet == chgSet ifFalse: [ myChangeSet _ chgSet. currentClassName _ nil. currentSelector _ nil]. self changed: #relabel. self changed: #currentCngSet. "new -- list of sets" self changed: #mainButtonName. "old, button" self changed: #classList. self changed: #messageList. self setContents. self contentsChanged.! ! !ChangeSorter methodsFor: 'access' stamp: 'di 4/5/2001 21:20'! showChangeSetNamed: aName self showChangeSet: (ChangeSorter changeSetNamed: aName) ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/6/1999 23:22'! addPreamble myChangeSet assurePreambleExists. self okToChange ifTrue: [currentClassName _ nil. currentSelector _ nil. self showChangeSet: myChangeSet]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 16:30'! addToCategoryOpposite "Add the current change set to the category viewed on the opposite side, if it's of the sort to accept things like that" | categoryOpposite | categoryOpposite _ (parent other: self) changeSetCategory. categoryOpposite acceptsManualAdditions ifTrue: [categoryOpposite addChangeSet: myChangeSet. categoryOpposite reconstituteList. self update] ifFalse: [self inform: 'sorry, this command only makes sense if the category showing on the opposite side is a static category whose members are manually maintained']! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:27'! browseChangeSet "Open a message list browser on the new and changed methods in the current change set" ChangedMessageSet openFor: myChangeSet ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'RAA 5/28/2001 12:06'! browseMethodConflicts "Check to see if any other change set also holds changes to any methods in the selected change set; if so, open a browser on all such." | aList | aList _ myChangeSet messageListForChangesWhich: [ :aClass :aSelector | (ChangeSorter allChangeSetsWithClass: aClass selector: aSelector) size > 1 ] ifNone: [^ self inform: 'No other change set has changes for any method in this change set.']. MessageSet openMessageList: aList name: 'Methods in "', myChangeSet name, '" that are also in other change sets (', aList size printString, ')' ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 8/12/2002 17:29'! categorySubmenu: aMenu shifted: shiftedIgnored "Fill aMenu with less-frequently-needed category items" aMenu title: 'Change set category'. aMenu addStayUpItem. aMenu addList: #( ('make a new category...' makeNewCategory 'Creates a new change-set-category (you will be asked to supply a name) which will start out its life with this change set in it') ('make a new category with class...' makeNewCategoryShowingClassChanges 'Creates a new change-set-category that includes change sets that change a particular class (you will be asked to supply a name)') ('rename this category' renameCategory 'Rename this change-set category. Only applies when the current category being shown is a manually-maintained, user-defined category, such as you can create for yourself by choosing "make a new category..." from this same menu.') ('remove this category' removeCategory 'Remove this change-set category. Only applies when the current category being shown is a manually-maintained, user-defined category, such as you can create for yourself by choosing "make a new category..." from this same menu.') ('show categories of this changeset' showCategoriesOfChangeSet 'Show a list of all the change-set categories that contain this change-set; if the you choose one of the categories from this pop-up, that category will be installed in this change sorter') -). parent ifNotNil: [aMenu addList: #( ('add change set to category opposite' addToCategoryOpposite 'Adds this change set to the category on the other side of the change sorter. Only applies if the category shown on the opposite side is a manually-maintained, user-defined category, such as you can create for yourself by choosing "make a new category..." from this same menu.'))]. aMenu addList: #( ('remove change set from this category' removeFromCategory 'Removes this change set from the current category. Only applies when the current category being shown is a manually-maintained, user-defined category, such as you can create for yourself by choosing "make a new category..." from this same menu.') - ('file out category''s change sets' fileOutAllChangeSets 'File out every change set in this category that has anything in it. The usual checks for slips are suppressed when this command is done.') ('set recent-updates marker' setRecentUpdatesMarker 'Allows you to specify a number that will demarcate which updates are considered "recent" and which are not. This will govern which updates are included in the RecentUpdates category in a change sorter') ('fill aggregate change set' fillAggregateChangeSet 'Creates a change-set named Aggregate into which all the changes in all the change sets in this category will be copied.') - ('back to main menu' offerUnshiftedChangeSetMenu 'Takes you back to the shifted change-set menu.') ('back to shifted menu' offerShiftedChangeSetMenu 'Takes you back to the primary change-set menu.')). ^ aMenu! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/30/2001 00:00'! changeSetList "Answer a list of ChangeSet names to be shown in the change sorter." ^ self changeSetCategory changeSetList! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/17/2002 11:37'! changeSetListKey: aChar from: view "Respond to a Command key. I am a model with a listView that has a list of changeSets." aChar == $b ifTrue: [^ self browseChangeSet]. aChar == $B ifTrue: [^ self openChangeSetBrowser]. aChar == $c ifTrue: [^ self copyAllToOther]. aChar == $D ifTrue: [^ self toggleDiffing]. aChar == $f ifTrue: [^ self findCngSet]. aChar == $m ifTrue: [^ self newCurrent]. aChar == $n ifTrue: [^ self newSet]. aChar == $o ifTrue: [^ self fileOut]. aChar == $p ifTrue: [^ self addPreamble]. aChar == $r ifTrue: [^ self rename]. aChar == $s ifTrue: [^ self chooseChangeSetCategory]. aChar == $x ifTrue: [^ self remove]. aChar == $- ifTrue: [^ self subtractOtherSide]. ^ self messageListKey: aChar from: view! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/29/2003 08:09'! changeSetMenu: aMenu shifted: isShifted "Set up aMenu to hold commands for the change-set-list pane. This could be for a single or double changeSorter" isShifted ifTrue: [^ self shiftedChangeSetMenu: aMenu]. Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu title: 'Change Set: ' , myChangeSet name]. aMenu add: 'make changes go to me (m)' action: #newCurrent. aMenu addLine. aMenu add: 'new change set... (n)' action: #newSet. aMenu add: 'find...(f)' action: #findCngSet. aMenu add: 'show category... (s)' action: #chooseChangeSetCategory. aMenu balloonTextForLastItem: 'Lets you choose which change sets should be listed in this change sorter'. aMenu add: 'select change set...' action: #chooseCngSet. aMenu addLine. aMenu add: 'rename change set (r)' action: #rename. aMenu add: 'file out (o)' action: #fileOut. " aMenu add: 'mail to list' action: #mailOut. " aMenu add: 'browse methods (b)' action: #browseChangeSet. aMenu add: 'browse change set (B)' action: #openChangeSetBrowser. aMenu addLine. parent ifNotNil: [aMenu add: 'copy all to other side (c)' action: #copyAllToOther. aMenu add: 'submerge into other side' action: #submergeIntoOtherSide. aMenu add: 'subtract other side (-)' action: #subtractOtherSide. aMenu addLine]. myChangeSet hasPreamble ifTrue: [aMenu add: 'edit preamble (p)' action: #addPreamble. aMenu add: 'remove preamble' action: #removePreamble] ifFalse: [aMenu add: 'add preamble (p)' action: #addPreamble]. myChangeSet hasPostscript ifTrue: [aMenu add: 'edit postscript...' action: #editPostscript. aMenu add: 'remove postscript' action: #removePostscript] ifFalse: [aMenu add: 'add postscript...' action: #editPostscript]. aMenu addLine. aMenu add: 'category functions...' action: #offerCategorySubmenu. aMenu balloonTextForLastItem: 'Various commands relating to change-set-categories'. aMenu addLine. aMenu add: 'destroy change set (x)' action: #remove. aMenu addLine. aMenu add: 'more...' action: #offerShiftedChangeSetMenu. ^ aMenu! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 10/30/2000 10:48'! checkForAlienAuthorship "Open a message list browser on all uncommented methods in the current change set that have alien authorship" myChangeSet checkForAlienAuthorship ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'nk 3/30/2002 08:56'! checkForAnyAlienAuthorship "Open a message list browser on all uncommented methods in the current change set that have alien authorship, even historically" myChangeSet checkForAnyAlienAuthorship ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/29/2001 12:47'! checkForUnclassifiedMethods "Open a message list browser on all methods in the current change set that have not been categorized" myChangeSet checkForUnclassifiedMethods ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/18/2002 17:58'! checkForUncommentedClasses "Open a class list browser on classes in the change set that lack class comments" myChangeSet checkForUncommentedClasses! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 10/30/2000 10:39'! checkForUncommentedMethods "Open a message list browser on all uncommented methods in the current change set" myChangeSet checkForUncommentedMethods ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 10/27/1999 14:20'! checkForUnsentMessages "Open a message list browser on all unsent messages in the current change set" myChangeSet checkForUnsentMessages ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/8/1999 13:36'! checkThatSidesDiffer: escapeBlock "If the change sets on both sides of the dual sorter are the same, put up an error message and escape via escapeBlock, else proceed happily" (myChangeSet == (parent other: self) changeSet) ifTrue: [self inform: 'This command requires that the change sets selected on the two sides of the change sorter *not* be the same.'. ^ escapeBlock value] ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/28/2003 20:47'! chooseChangeSetCategory "Present the user with a list of change-set-categories and let her choose one" | cats aMenu result | self okToChange ifFalse: [^ self]. cats _ ChangeSetCategories elementsInOrder. aMenu _ SelectionMenu labels: (cats collect: [:cat | cat categoryName]) selections: cats. result _ aMenu startUp. result ifNotNil: [changeSetCategory _ result. self changed: #changeSetList. (self changeSetList includes: myChangeSet name) ifFalse: [self showChangeSet: (ChangeSorter changeSetNamed: self changeSetList first)]. self changed: #relabel]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 4/5/2001 17:56'! chooseCngSet "Present the user with an alphabetical list of change set names, and let her choose one" | changeSetsSortedAlphabetically chosen | self okToChange ifFalse: [^ self]. changeSetsSortedAlphabetically _ self changeSetList asSortedCollection: [:a :b | a asLowercase withoutLeadingDigits < b asLowercase withoutLeadingDigits]. chosen _ (SelectionMenu selections: changeSetsSortedAlphabetically) startUp. chosen ifNil: [^ self]. self showChangeSet: (ChangeSorter changeSetNamed: chosen)! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 1/28/1999 12:30'! clearChangeSet "Clear out the current change set, after getting a confirmation." | message | self okToChange ifFalse: [^ self]. myChangeSet isEmpty ifFalse: [message _ 'Are you certain that you want to\forget all the changes in this set?' withCRs. (self confirm: message) ifFalse: [^ self]]. myChangeSet clear. self changed: #classList. self changed: #messageList. self setContents. self contentsChanged. ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 1/27/2000 11:21'! copyAllToOther "Copy this entire change set into the one on the other side" | companionSorter | self checkThatSidesDiffer: [^ self]. (companionSorter _ parent other: self) changeSetCurrentlyDisplayed assimilateAllChangesFoundIn: myChangeSet. companionSorter changed: #classList. "Later the changeSet itself will notice..." companionSorter changed: #messageList! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 6/5/1998 06:47'! currentCngSet ^ myChangeSet name! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 08:06'! editPostscript "Allow the user to edit the receiver's change-set's postscript -- in a separate window" myChangeSet editPostscript! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 08:06'! editPreamble "Allow the user to edit the receiver's change-set's preamble -- in a separate window." myChangeSet editPreamble! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/19/2000 16:18'! expungeUniclasses "remove all memory of uniclasses in the receiver" self okToChange ifFalse: [^ self]. myChangeSet expungeUniclasses. self changed: #classList. self changed: #messageList. ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'nk 1/4/2004 17:07'! fileIntoNewChangeSet "Obtain a file designation from the user, and file its contents into a new change set whose name is a function of the filename. Show the new set and leave the current changeSet unaltered." | aNewChangeSet stream | self okToChange ifFalse: [^ self]. ChangeSet promptForDefaultChangeSetDirectoryIfNecessary. stream := StandardFileMenu oldFileStreamFrom: ChangeSet defaultChangeSetDirectory. stream ifNil: [^ self]. aNewChangeSet := self class newChangesFromStream: stream named: (FileDirectory localNameFor: stream name). aNewChangeSet ifNotNil: [self showChangeSet: aNewChangeSet]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 6/10/1999 12:44'! fileOut "File out the current change set." myChangeSet fileOut. parent modelWakeUp. "notice object conversion methods created" ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/30/2001 00:57'! fileOutAllChangeSets "File out all nonempty change sets in the current category, probably" self changeSetCategory fileOutAllChangeSets! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/30/2001 01:26'! fillAggregateChangeSet "Create a change-set named Aggregate and pour into it all the changes in all the change-sets of the currently-selected category" self changeSetCategory fillAggregateChangeSet! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'nb 6/17/2003 12:25'! findCngSet "Search for a changeSet by name. Pop up a menu of all changeSets whose name contains the string entered by the user. If only one matches, then the pop-up menu is bypassed" | index pattern candidates nameList | self okToChange ifFalse: [^ self]. pattern _ FillInTheBlank request: 'ChangeSet name or fragment?'. pattern isEmpty ifTrue: [^ self]. nameList _ self changeSetList asSet. candidates _ AllChangeSets select: [:c | (nameList includes: c name) and: [c name includesSubstring: pattern caseSensitive: false]]. candidates size = 0 ifTrue: [^ Beeper beep]. candidates size = 1 ifTrue: [^ self showChangeSet: candidates first]. index _ (PopUpMenu labels: (candidates collect: [:each | each name]) asStringWithCr) startUp. index = 0 ifFalse: [self showChangeSet: (candidates at: index)]. ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 10/26/1999 14:24'! goToChangeSetsProject "Transport the user to a project which bears the selected changeSet as its current changeSet" | aProject | (aProject _ myChangeSet correspondingProject) ifNotNil: [aProject enter: false revert: false saveForRevert: false] ifNil: [self inform: 'Has no project']! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 1/10/1999 01:01'! inspectChangeSet "Open a message list browser on the new and changed methods in the current change set" myChangeSet inspectWithLabel: 'Change set: ', myChangeSet name ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 2/17/1999 11:05'! lookForSlips "Open a message list browser on the new and changed methods in the current change set" myChangeSet lookForSlips ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'dvf 5/13/2000 05:08'! mailOut "Create a mail with a gzipped attachment holding out the current change set. " myChangeSet mailOut. parent modelWakeUp! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:10'! mainButtonName ^ myChangeSet name! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 16:43'! makeNewCategory "Create a new, static change-set category, which will be populated entirely by change sets that have been manually placed in it" | catName aCategory | catName _ FillInTheBlank request: 'Please give the new category a name' initialAnswer: ''. catName isEmptyOrNil ifTrue: [^ self]. catName _ catName asSymbol. (ChangeSetCategories includesKey: catName) ifTrue: [^ self inform: 'Sorry, there is already a category of that name']. aCategory _ StaticChangeSetCategory new categoryName: catName. ChangeSetCategories elementAt: catName put: aCategory. aCategory addChangeSet: myChangeSet. self showChangeSetCategory: aCategory! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'nk 6/26/2002 12:28'! makeNewCategoryShowingClassChanges "Create a new, static change-set category, which will be populated entirely by change sets that have been manually placed in it" | catName aCategory clsName | clsName _ self selectedClass ifNotNil: [self selectedClass name ] ifNil: ['']. clsName _ FillInTheBlank request: 'Which class?' initialAnswer: clsName. clsName isEmptyOrNil ifTrue: [^ self]. catName _ ('Changes to ', clsName) asSymbol. (ChangeSetCategories includesKey: catName) ifTrue: [^ self inform: 'Sorry, there is already a category of that name']. aCategory _ ChangeSetCategoryWithParameters new categoryName: catName. aCategory membershipSelector: #changeSet:containsClass: ; parameters: { clsName }. ChangeSetCategories elementAt: catName put: aCategory. aCategory reconstituteList. self showChangeSetCategory: aCategory! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'RAA 5/28/2001 12:07'! methodConflictsWithOppositeCategory "Check to see if ANY change set on the other side shares any methods with the selected change set; if so, open a browser on all such." | aList otherCategory | otherCategory _ (parent other: self) changeSetCategory. aList _ myChangeSet messageListForChangesWhich: [ :aClass :aSelector | aClass notNil and: [otherCategory hasChangeForClassName: aClass name selector: aSelector otherThanIn: myChangeSet] ] ifNone: [^ self inform: 'There are no methods that appear both in this change set and in any change set (other than this one) on the other side.']. MessageSet openMessageList: aList name: 'Methods in "', myChangeSet name, '" also in some other change set in category ', otherCategory categoryName,' (', aList size printString, ')' ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'RAA 5/28/2001 12:07'! methodConflictsWithOtherSide "Check to see if the change set on the other side shares any methods with the selected change set; if so, open a browser on all such." | aList other | self checkThatSidesDiffer: [^ self]. other _ (parent other: self) changeSet. aList _ myChangeSet messageListForChangesWhich: [ :aClass :aSelector | aClass notNil and: [(other methodChangesAtClass: aClass name) includesKey: aSelector] ] ifNone: [^ self inform: 'There are no methods that appear both in this change set and in the one on the other side.']. MessageSet openMessageList: aList name: 'Methods in "', myChangeSet name, '" that are also in ', other name,' (', aList size printString, ')' ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sd 5/23/2003 15:15'! newCurrent "make my change set be the current one that changes go into" ChangeSet newChanges: myChangeSet. self update. "Because list of changes in a category may thus have changed" self changed: #relabel.! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 16:26'! newSet "Create a new changeSet and show it., making it the current one. Reject name if already in use." | aSet | self okToChange ifFalse: [^ self]. aSet _ self class newChangeSet. aSet ifNotNil: [self changeSetCategory acceptsManualAdditions ifTrue: [changeSetCategory addChangeSet: aSet]. self update. (changeSetCategory includesChangeSet: aSet) ifTrue: [self showChangeSet: aSet]. self changed: #relabel]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 17:41'! offerCategorySubmenu "Offer a menu of category-related items" self offerMenuFrom: #categorySubmenu:shifted: shifted: false! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 2/27/2001 21:55'! offerShiftedChangeSetMenu "Offer the shifted version of the change set menu" self offerMenuFrom: #changeSetMenu:shifted: shifted: true! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/6/2001 14:41'! offerUnshiftedChangeSetMenu "Offer the unshifted version of the change set menu" self offerMenuFrom: #changeSetMenu:shifted: shifted: false! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/29/2003 00:38'! openChangeSetBrowser "Open a ChangeSet browser on the current change set" Smalltalk isMorphic ifFalse: [self browseChangeSet] "msg-list browser only" ifTrue: []! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 12/13/2003 18:14'! promoteToTopChangeSet "Move the selected change-set to the top of the list" self class promoteToTop: myChangeSet. (parent ifNil: [self]) modelWakeUp! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 6/14/1998 12:00'! remove "Completely destroy my change set. Check if it's OK first" self okToChange ifFalse: [^ self]. self removePrompting: true. self update! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 20:03'! removeCategory "Remove the current category" | itsName | self changeSetCategory acceptsManualAdditions ifFalse: [^ self inform: 'sorry, you can only remove manually-added categories.']. (self confirm: 'Really remove the change-set-category named ', (itsName _ changeSetCategory categoryName), '?') ifFalse: [^ self]. ChangeSetCategories removeElementAt: itsName. self setDefaultChangeSetCategory. self update! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'MU 7/1/2002 18:38'! removeContainedInClassCategories | matchExpression | myChangeSet removePreamble. matchExpression := FillInTheBlank request: 'Enter class category name (wildcard is ok)' initialAnswer: 'System-*'. (SystemOrganization categories select: [:each | matchExpression match: each]) do: [:eachCat | | classNames | classNames := SystemOrganization listAtCategoryNamed: eachCat. classNames do: [:eachClassName | myChangeSet removeClassChanges: eachClassName. myChangeSet removeClassChanges: eachClassName , ' class']. self showChangeSet: myChangeSet]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 16:31'! removeFromCategory "Add the current change set to the category viewed on the opposite side, if it's of the sort to accept things like that" | aCategory | (aCategory _ self changeSetCategory) acceptsManualAdditions ifTrue: [aCategory removeElementAt: myChangeSet name. aCategory reconstituteList. self update] ifFalse: [self inform: 'sorry, this command only makes sense for static categories whose members are manually maintained']! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 6/29/1999 20:53'! removePostscript (myChangeSet hasPostscript and: [myChangeSet postscriptHasDependents]) ifTrue: [^ self inform: 'Cannot remove the postscript right now because there is at least one window open on that postscript. Close that window and try again.']. myChangeSet removePostscript. self showChangeSet: myChangeSet! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/5/1999 19:32'! removePreamble myChangeSet removePreamble. self showChangeSet: myChangeSet! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sd 5/23/2003 14:26'! removePrompting: doPrompt "Completely destroy my change set. Check if it's OK first, and if doPrompt is true, get the user to confirm his intentions first." | message aName changeSetNumber msg | aName _ myChangeSet name. myChangeSet okayToRemove ifFalse: [^ self]. "forms current changes for some project" (myChangeSet isEmpty or: [doPrompt not]) ifFalse: [message _ 'Are you certain that you want to remove (destroy) the change set named "', aName, '" ?'. (self confirm: message) ifFalse: [^ self]]. doPrompt ifTrue: [msg _ myChangeSet hasPreamble ifTrue: [myChangeSet hasPostscript ifTrue: ['a preamble and a postscript'] ifFalse: ['a preamble']] ifFalse: [myChangeSet hasPostscript ifTrue: ['a postscript'] ifFalse: ['']]. msg isEmpty ifFalse: [(self confirm: 'Caution!! This change set has ', msg, ' which will be lost if you destroy the change set. Do you really want to go ahead with this?') ifFalse: [^ self]]]. "Go ahead and remove the change set" changeSetNumber _ myChangeSet name initialIntegerOrNil. changeSetNumber ifNotNil: [SystemVersion current unregisterUpdate: changeSetNumber]. ChangeSorter removeChangeSet: myChangeSet. self showChangeSet: ChangeSet current.! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'nb 6/17/2003 12:25'! rename "Store a new name string into the selected ChangeSet. reject duplicate name; allow user to back out" | newName | newName _ FillInTheBlank request: 'New name for this change set' initialAnswer: myChangeSet name. (newName = myChangeSet name or: [newName size == 0]) ifTrue: [^ Beeper beep]. (self class changeSetNamed: newName) ifNotNil: [^ Utilities inform: 'Sorry that name is already used']. myChangeSet name: newName. self update. self changed: #mainButtonName. self changed: #relabel.! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 4/11/2001 18:18'! renameCategory "Obtain a new name for the category and, if acceptable, apply it" | catName oldName | self changeSetCategory acceptsManualAdditions ifFalse: [^ self inform: 'sorry, you can only rename manually-added categories.']. catName _ FillInTheBlank request: 'Please give the new category a name' initialAnswer: (oldName _ changeSetCategory categoryName). catName isEmptyOrNil ifTrue: [^ self]. (catName _ catName asSymbol) = oldName ifTrue: [^ self inform: 'no change.']. (ChangeSetCategories includesKey: catName) ifTrue: [^ self inform: 'Sorry, there is already a category of that name']. changeSetCategory categoryName: catName. ChangeSetCategories removeElementAt: oldName. ChangeSetCategories elementAt: catName put: changeSetCategory. self update! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/5/2001 11:03'! reorderChangeSets "apply a standard reordering -- let the class handle this" ^ self class reorderChangeSets! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/28/2003 20:37'! setRecentUpdatesMarker "Allow the user to change the recent-updates marker" | result | result _ FillInTheBlank request: ('Enter the lowest change-set number that you wish to consider "recent"? (note: highest change-set number in this image at this time is ', self class highestNumberedChangeSet asString, ')') initialAnswer: self class recentUpdateMarker asString. (result notNil and: [result startsWithDigit]) ifTrue: [self class recentUpdateMarker: result asInteger.]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/28/2003 20:48'! shiftedChangeSetMenu: aMenu "Set up aMenu to hold items relating to the change-set-list pane when the shift key is down" "CONFLICTS SECTION" aMenu add: 'conflicts with other change sets' action: #browseMethodConflicts. aMenu balloonTextForLastItem: 'Browse all methods that occur both in this change set and in at least one other change set.'. parent ifNotNil: [aMenu add: 'conflicts with change set opposite' action: #methodConflictsWithOtherSide. aMenu balloonTextForLastItem: 'Browse all methods that occur both in this change set and in the one on the opposite side of the change sorter.'. aMenu add: 'conflicts with category opposite' action: #methodConflictsWithOppositeCategory. aMenu balloonTextForLastItem: 'Browse all methods that occur both in this change set and in ANY change set in the category list on the opposite side of this change sorter, other of course than this change set itself. (Caution -- this could be VERY slow)']. aMenu addLine. "CHECKS SECTION" aMenu add: 'check for slips' action: #lookForSlips. aMenu balloonTextForLastItem: 'Check this change set for halts and references to Transcript.'. aMenu add: 'check for unsent messages' action: #checkForUnsentMessages. aMenu balloonTextForLastItem: 'Check this change set for messages that are not sent anywhere in the system'. aMenu add: 'check for uncommented methods' action: #checkForUncommentedMethods. aMenu balloonTextForLastItem: 'Check this change set for methods that do not have comments'. aMenu add: 'check for uncommented classes' action: #checkForUncommentedClasses. aMenu balloonTextForLastItem: 'Check for classes with code in this changeset which lack class comments'. Utilities authorInitialsPerSe isEmptyOrNil ifFalse: [aMenu add: 'check for other authors' action: #checkForAlienAuthorship. aMenu balloonTextForLastItem: 'Check this change set for methods whose current authoring stamp does not start with "', Utilities authorInitials, '"'. aMenu add: 'check for any other authors' action: #checkForAnyAlienAuthorship. aMenu balloonTextForLastItem: 'Check this change set for methods any of whose authoring stamps do not start with "', Utilities authorInitials, '"']. aMenu add: 'check for uncategorized methods' action: #checkForUnclassifiedMethods. aMenu balloonTextForLastItem: 'Check to see if any methods in the selected change set have not yet been assigned to a category. If any are found, open a browser on them.'. aMenu addLine. aMenu add: 'inspect change set' action: #inspectChangeSet. aMenu balloonTextForLastItem: 'Open an inspector on this change set. (There are some details in a change set which you don''t see in a change sorter.)'. aMenu add: 'update' action: #update. aMenu balloonTextForLastItem: 'Update the display for this change set. (This is done automatically when you activate this window, so is seldom needed.)'. aMenu add: 'go to change set''s project' action: #goToChangeSetsProject. aMenu balloonTextForLastItem: 'If this change set is currently associated with a Project, go to that project right now.'. aMenu add: 'promote to top of list' action: #promoteToTopChangeSet. aMenu balloonTextForLastItem: 'Make this change set appear first in change-set lists in all change sorters.'. aMenu add: 'trim history' action: #trimHistory. aMenu balloonTextForLastItem: ' Drops any methods added and then removed, as well as renaming and reorganization of newly-added classes. NOTE: can cause confusion if later filed in over an earlier version of these changes'. aMenu add: 'clear this change set' action: #clearChangeSet. aMenu balloonTextForLastItem: 'Reset this change set to a pristine state where it holds no information. CAUTION: this is destructive and irreversible!!'. aMenu add: 'expunge uniclasses' action: #expungeUniclasses. aMenu balloonTextForLastItem: 'Remove from the change set all memory of uniclasses, e.g. classes added on behalf of etoys, fabrik, etc., whose classnames end with a digit.'. aMenu add: 'uninstall this change set' action: #uninstallChangeSet. aMenu balloonTextForLastItem: 'Attempt to uninstall this change set. CAUTION: this may not work completely and is irreversible!!'. aMenu addLine. aMenu add: 'file into new...' action: #fileIntoNewChangeSet. aMenu balloonTextForLastItem: 'Load a fileout from disk and place its changes into a new change set (seldom needed -- much better to do this from a file-list browser these days.)'. aMenu add: 'reorder all change sets' action: #reorderChangeSets. aMenu balloonTextForLastItem: 'Applies a standard reordering of all change-sets in the system -- at the bottom will come the sets that come with the release; next will come all the numbered updates; finally, at the top, will come all other change sets'. aMenu addLine. aMenu add: 'more...' action: #offerUnshiftedChangeSetMenu. aMenu balloonTextForLastItem: 'Takes you back to the primary change-set menu.'. ^ aMenu! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/28/2003 20:51'! showCategoriesOfChangeSet "Show a list of all the categories in which the selected change-set occurs at the moment. Install the one the user chooses, if any." Smalltalk isMorphic ifFalse: [self inform: 'Only available in morphic, right now, sorry. It would not take much to make this also work in mvc, so if you are inclined to do that, thanks in advance...'] ifTrue: []! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 3/30/2001 13:27'! showChangeSetCategory: aChangeSetCategory "Show the given change-set category" changeSetCategory _ aChangeSetCategory. self changed: #changeSetList. (self changeSetList includes: myChangeSet name) ifFalse: [self showChangeSet: (ChangeSorter changeSetNamed: self changeSetList first)]. self changed: #relabel! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 4/5/2001 21:22'! submergeIntoOtherSide "Copy the contents of the receiver to the other side, then remove the receiver -- all after checking that all is well." | other message nextToView i | self checkThatSidesDiffer: [^ self]. self okToChange ifFalse: [^ self]. other _ (parent other: self) changeSet. other == myChangeSet ifTrue: [^ self inform: 'Both sides are the same!!']. myChangeSet isEmpty ifTrue: [^ self inform: 'Nothing to copy. To remove, simply choose "remove".']. myChangeSet okayToRemove ifFalse: [^ self]. message _ 'Please confirm: copy all changes in "', myChangeSet name, '" into "', other name, '" and then destroy the change set named "', myChangeSet name, '"?'. (self confirm: message) ifFalse: [^ self]. (myChangeSet hasPreamble or: [myChangeSet hasPostscript]) ifTrue: [(self confirm: 'Caution!! This change set has a preamble or a postscript or both. If you submerge it into the other side, these will be lost. Do you really want to go ahead with this?') ifFalse: [^ self]]. other assimilateAllChangesFoundIn: myChangeSet. nextToView _ ((AllChangeSets includes: myChangeSet) and: [(i _ AllChangeSets indexOf: myChangeSet) < AllChangeSets size]) ifTrue: [AllChangeSets at: i+1] ifFalse: [other]. self removePrompting: false. self showChangeSet: nextToView. parent modelWakeUp. ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/8/1999 12:32'! subtractOtherSide "Subtract the changes found on the other side from the requesting side." self checkThatSidesDiffer: [^ self]. myChangeSet forgetAllChangesFoundIn: ((parent other: self) changeSet). self showChangeSet: myChangeSet! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 5/12/2000 15:03'! trimHistory "Drop non-essential history (rename, reorg, method removals) from newly-added classes." myChangeSet trimHistory ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 3/8/2000 14:18'! uninstallChangeSet "Attempt to uninstall the current change set, after confirmation." self okToChange ifFalse: [^ self]. (self confirm: 'Uninstalling a changeSet is unreliable at best. It will only work if the changeSet consists only of single changes, additions and removals of methods, and if no subsequent changes have been to any of them. No changes to classes will be undone. The changeSet will be cleared after uninstallation. Do you still wish to attempt to uninstall this changeSet?') ifFalse: [^ self]. myChangeSet uninstall. self changed: #relabel. self changed: #classList. self changed: #messageList. self setContents. self contentsChanged. ! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 6/21/1998 13:02'! update "recompute all of my panes" self updateIfNecessary. parent ifNotNil: [(parent other: self) updateIfNecessary]! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'di 6/20/2001 09:37'! updateIfNecessary "Recompute all of my panes." | newList | self okToChange ifFalse: [^ self]. myChangeSet ifNil: [^ self]. "Has been known to happen though shouldn't" (myChangeSet isMoribund or: [(changeSetCategory notNil and: [changeSetCategory includesChangeSet: myChangeSet]) not]) ifTrue: [self changed: #changeSetList. ^ self showChangeSet: self changeSetCategory defaultChangeSetToShow]. newList _ self changeSetList. (priorChangeSetList == nil or: [priorChangeSetList ~= newList]) ifTrue: [priorChangeSetList _ newList. self changed: #changeSetList]. self showChangeSet: myChangeSet! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 3/29/2001 15:19'! classList "Computed. View should try to preserve selections, even though index changes" ^ myChangeSet ifNotNil: [myChangeSet changedClassNames] ifNil: [OrderedCollection new] ! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 3/5/2001 18:24'! classListKey: aChar from: view "Respond to a Command key in the class-list pane." aChar == $x ifTrue: [^ self removeClass]. aChar == $d ifTrue: [^ self forgetClass]. ^ self messageListKey: aChar from: view "picks up b,h,p"! ! !ChangeSorter methodsFor: 'class list' stamp: 'BG 10/28/2003 20:48'! classListMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the class list" aMenu title: 'class list'. (parent notNil and: [shifted not]) ifTrue: [aMenu addList: #( "These two only apply to dual change sorters" ('copy class chgs to other side' copyClassToOther) ('move class chgs to other side' moveClassToOther))]. aMenu addList: (shifted ifFalse: [#( - ('delete class from change set (d)' forgetClass) ('remove class from system (x)' removeClass) - ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' spawnHierarchy) ('browse protocol (p)' browseFullProtocol) - ('printOut' printOutClass) ('fileOut' fileOutClass) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' browseClassVarRefs) ('class vars' browseClassVariables) ('class refs (N)' browseClassRefs) - ('more...' offerShiftedClassListMenu))] ifTrue: [#( - ('unsent methods' browseUnusedMethods) ('unreferenced inst vars' showUnreferencedInstVars) ('unreferenced class vars' showUnreferencedClassVars) - ('sample instance' makeSampleInstance) ('inspect instances' inspectInstances) ('inspect subinstances' inspectSubInstances) - ('more...' offerUnshiftedClassListMenu ))]). ^ aMenu! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 2/26/2001 12:00'! classMenu: aMenu "Set up aMenu for the class-list. Retained for backward compatibility with old change sorters in image segments" ^ self classListMenu: aMenu shifted: false! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 3/6/2001 12:40'! classMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the class list. Retained for bkwd compatibility" ^ self classListMenu: aMenu shifted: shifted! ! !ChangeSorter methodsFor: 'class list' stamp: 'nb 6/17/2003 12:25'! copyClassToOther "Place these changes in the other changeSet also" | otherSorter otherChangeSet | self checkThatSidesDiffer: [^ self]. self okToChange ifFalse: [^ Beeper beep]. currentClassName ifNil: [^ Beeper beep]. otherSorter _ parent other: self. otherChangeSet _ otherSorter changeSet. otherChangeSet absorbClass: self selectedClassOrMetaClass name from: myChangeSet. otherSorter showChangeSet: otherChangeSet.! ! !ChangeSorter methodsFor: 'class list' stamp: 'tk 4/24/1998 09:14'! currentClassName ^ currentClassName! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 1/28/1999 12:30'! currentClassName: aString currentClassName _ aString. currentSelector _ nil. "fix by wod" self changed: #currentClassName. self changed: #messageList. self setContents. self contentsChanged.! ! !ChangeSorter methodsFor: 'class list' stamp: 'kfr 6/16/2000 16:27'! fileOutClass "this is a hack!!!! makes a new change set, called the class name, adds author initials to try to make a unique change set name, files it out and removes it. kfr 16 june 2000" | aSet | "File out the selected class set." aSet _ self class newChangeSet: currentClassName. aSet absorbClass: self selectedClassOrMetaClass name from: myChangeSet. aSet fileOut. self class removeChangeSet: aSet. parent modelWakeUp. "notice object conversion methods created" ! ! !ChangeSorter methodsFor: 'class list' stamp: 'ls 8/12/1998 23:47'! forgetClass "Remove all mention of this class from the changeSet" self okToChange ifFalse: [^ self]. currentClassName ifNotNil: [ myChangeSet removeClassChanges: currentClassName. currentClassName _ nil. currentSelector _ nil. self showChangeSet: myChangeSet]. ! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 3/5/2001 18:30'! messageListKey: aChar from: view "Respond to a Command key in the message-list pane." aChar == $d ifTrue: [^ self forget]. super messageListKey: aChar from: view! ! !ChangeSorter methodsFor: 'class list' stamp: 'nb 6/17/2003 12:25'! moveClassToOther "Place class changes in the other changeSet and remove them from this one" self checkThatSidesDiffer: [^ self]. (self okToChange and: [currentClassName notNil]) ifFalse: [^ Beeper beep]. self copyClassToOther. self forgetClass! ! !ChangeSorter methodsFor: 'class list' stamp: 'sw 12/7/1998 09:43'! selectedClass "Answer the currently-selected class. If there is no selection, or if the selection refers to a class no longer extant, return nil" | c | ^ currentClassName ifNotNil: [(c _ self selectedClassOrMetaClass) ifNotNil: [c theNonMetaClass]]! ! !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/7/1998 13:48'! selectedClassOrMetaClass "Careful, the class may have been removed!!" | cName | currentClassName ifNil: [^ nil]. (currentClassName endsWith: ' class') ifTrue: [cName _ (currentClassName copyFrom: 1 to: currentClassName size-6) asSymbol. ^ (Smalltalk at: cName ifAbsent: [^nil]) class] ifFalse: [cName _ currentClassName asSymbol. ^ Smalltalk at: cName ifAbsent: [nil]]! ! !ChangeSorter methodsFor: 'message list' stamp: 'di 3/23/2000 13:34'! browseVersions "Create and schedule a changelist browser on the versions of the selected message." | class selector method category pair sourcePointer | (selector _ self selectedMessageName) ifNil: [^ self]. class _ self selectedClassOrMetaClass. (class includesSelector: selector) ifTrue: [method _ class compiledMethodAt: selector. category _ class whichCategoryIncludesSelector: selector. sourcePointer _ nil] ifFalse: [pair _ myChangeSet methodInfoFromRemoval: {class name. selector}. pair ifNil: [^ nil]. sourcePointer _ pair first. method _ CompiledMethod toReturnSelf setSourcePointer: sourcePointer. category _ pair last]. VersionsBrowser browseVersionsOf: method class: self selectedClass meta: class isMeta category: category selector: selector lostMethodPointer: sourcePointer. ! ! !ChangeSorter methodsFor: 'message list' stamp: 'sw 7/8/1999 12:31'! copyMethodToOther "Place this change in the other changeSet also" | other cls sel | self checkThatSidesDiffer: [^ self]. currentSelector ifNotNil: [other _ (parent other: self) changeSet. cls _ self selectedClassOrMetaClass. sel _ currentSelector asSymbol. other absorbMethod: sel class: cls from: myChangeSet. (parent other: self) showChangeSet: other] ! ! !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/24/1998 09:15'! currentSelector ^ currentSelector! ! !ChangeSorter methodsFor: 'message list' stamp: 'sw 1/28/1999 12:31'! currentSelector: messageName currentSelector _ messageName. self changed: #currentSelector. self setContents. self contentsChanged.! ! !ChangeSorter methodsFor: 'message list' stamp: 'di 6/22/1998 02:08'! forget "Drop this method from the changeSet" self okToChange ifFalse: [^ self]. currentSelector ifNotNil: [ myChangeSet removeSelectorChanges: self selectedMessageName class: self selectedClassOrMetaClass. currentSelector _ nil. self showChangeSet: myChangeSet]! ! !ChangeSorter methodsFor: 'message list' stamp: 'di 4/25/2000 10:33'! messageList | probe newSelectors | currentClassName ifNil: [^ #()]. probe _ (currentClassName endsWith: ' class') ifTrue: [currentClassName] ifFalse: [currentClassName asSymbol]. newSelectors _ myChangeSet selectorsInClass: probe. (newSelectors includes: currentSelector) ifFalse: [currentSelector _ nil]. ^ newSelectors asSortedCollection ! ! !ChangeSorter methodsFor: 'message list' stamp: 'sw 3/9/2001 14:27'! messageListMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the message list; could be for a single or double changeSorter" ^ self messageMenu: aMenu shifted: shifted! ! !ChangeSorter methodsFor: 'message list' stamp: 'BG 10/28/2003 20:48'! messageMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the message list; could be for a single or double changeSorter" shifted ifTrue: [^ self shiftedMessageMenu: aMenu]. aMenu title: 'message list'. parent ifNotNil: [aMenu addList: #( ('copy method to other side' copyMethodToOther) ('move method to other side' moveMethodToOther))]. aMenu addList: #( ('delete method from changeSet (d)' forget) - ('remove method from system (x)' removeMessage) - ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' spawnHierarchy) ('browse method (O)' openSingleMessageBrowser) ('browse protocol (p)' browseFullProtocol) - ('fileOut' fileOutMessage) ('printOut' printOutMessage) - ('senders of... (n)' browseSendersOfMessages) ('implementors of... (m)' browseMessages) ('inheritance (i)' methodHierarchy) ('versions (v)' browseVersions) - ('more...' shiftedYellowButtonActivity)). ^ aMenu ! ! !ChangeSorter methodsFor: 'message list' stamp: 'nb 6/17/2003 12:25'! moveMethodToOther "Place this change in the other changeSet and remove it from this side" | other cls sel | self checkThatSidesDiffer: [^ self]. self okToChange ifFalse: [^ Beeper beep]. currentSelector ifNotNil: [other _ (parent other: self) changeSet. other == myChangeSet ifTrue: [^ self beep]. cls _ self selectedClassOrMetaClass. sel _ currentSelector asSymbol. other absorbMethod: sel class: cls from: myChangeSet. (parent other: self) showChangeSet: other. self forget "removes the method from this side"] ! ! !ChangeSorter methodsFor: 'message list' stamp: 'di 6/21/1998 23:13'! removeFromCurrentChanges "Redisplay after removal in case we are viewing the current changeSet" super removeFromCurrentChanges. currentSelector _ nil. self showChangeSet: myChangeSet! ! !ChangeSorter methodsFor: 'message list' stamp: 'sd 5/11/2003 18:38'! removeMessage "Remove the selected msg from the system. Real work done by the parent, a ChangeSorter" | confirmation sel | self okToChange ifFalse: [^ self]. currentSelector ifNotNil: [confirmation _ self systemNavigation confirmRemovalOf: (sel _ self selectedMessageName) on: self selectedClassOrMetaClass. confirmation == 3 ifTrue: [^ self]. self selectedClassOrMetaClass removeSelector: sel. self update. confirmation == 2 ifTrue: [self systemNavigation browseAllCallsOn: sel]]! ! !ChangeSorter methodsFor: 'message list' stamp: 'jm 5/4/1998 07:32'! selectedMessageName currentSelector ifNil: [^ nil]. ^ currentSelector asSymbol! ! !ChangeSorter methodsFor: 'message list' stamp: 'BG 11/1/2003 13:24'! shiftedMessageMenu: aMenu "Arm the menu so that it holds items appropriate to the message-list while the shift key is down. Answer the menu." ^ aMenu addList: #( - ('toggle diffing (D)' toggleDiffing) ('implementors of sent messages' browseAllMessages) ('change category...' changeCategory) - ('sample instance' makeSampleInstance) ('inspect instances' inspectInstances) ('inspect subinstances' inspectSubInstances) - ('change sets with this method' findMethodInChangeSets) ('revert to previous version' revertToPreviousVersion) ('revert & remove from changes' revertAndForget) - ('more...' unshiftedYellowButtonActivity))! ! !ChangeSorter methodsFor: 'code pane' stamp: 'tk 5/10/1999 17:24'! contents: aString notifying: aController "Compile the code in aString. Notify aController of any syntax errors. Create an error if the category of the selected message is unknown. Answer false if the compilation fails. Otherwise, if the compilation created a new method, deselect the current selection. Then answer true." | category selector class oldSelector | (class _ self selectedClassOrMetaClass) ifNil: [(myChangeSet preambleString == nil or: [aString size == 0]) ifTrue: [ ^ false]. (aString count: [:char | char == $"]) odd ifTrue: [self inform: 'unmatched double quotes in preamble'] ifFalse: [(Scanner new scanTokens: aString) size > 0 ifTrue: [ self inform: 'Part of the preamble is not within double-quotes. To put a double-quote inside a comment, type two double-quotes in a row. (Ignore this warning if you are including a doIt in the preamble.)']]. myChangeSet preambleString: aString. self currentSelector: nil. "forces update with no 'unsubmitted chgs' feedback" ^ true]. oldSelector _ self selectedMessageName. category _ class organization categoryOfElement: oldSelector. selector _ class compile: aString classified: category notifying: aController. selector ifNil: [^ false]. (self messageList includes: selector) ifTrue: [self currentSelector: selector] ifFalse: [self currentSelector: oldSelector]. self update. ^ true! ! !ChangeSorter methodsFor: 'code pane' stamp: 'sw 11/13/2001 07:35'! setContents "return the source code that shows in the bottom pane" | sel class strm changeType | self clearUserEditFlag. currentClassName ifNil: [^ contents _ myChangeSet preambleString ifNil: ['']]. class _ self selectedClassOrMetaClass. (sel _ currentSelector) == nil ifFalse: [changeType _ (myChangeSet atSelector: (sel _ sel asSymbol) class: class). changeType == #remove ifTrue: [^ contents _ 'Method has been removed (see versions)']. changeType == #addedThenRemoved ifTrue: [^ contents _ 'Added then removed (see versions)']. class ifNil: [^ contents _ 'Method was added, but cannot be found!!']. (class includesSelector: sel) ifFalse: [^ contents _ 'Method was added, but cannot be found!!']. contents _ class sourceCodeAt: sel. (#(prettyPrint colorPrint prettyDiffs altSyntax) includes: contentsSymbol) ifTrue: [contents _ class compilerClass new format: contents in: class notifying: nil contentsSymbol: contentsSymbol]. self showingAnyKindOfDiffs ifTrue: [contents _ self diffFromPriorSourceFor: contents]. ^ contents _ contents asText makeSelectorBoldIn: class] ifTrue: [strm _ WriteStream on: (String new: 100). (myChangeSet classChangeAt: currentClassName) do: [:each | each = #remove ifTrue: [strm nextPutAll: 'Entire class was removed.'; cr]. each = #addedThenRemoved ifTrue: [strm nextPutAll: 'Class was added then removed.']. each = #rename ifTrue: [strm nextPutAll: 'Class name was changed.'; cr]. each = #add ifTrue: [strm nextPutAll: 'Class definition was added.'; cr]. each = #change ifTrue: [strm nextPutAll: 'Class definition was changed.'; cr]. each = #reorganize ifTrue: [strm nextPutAll: 'Class organization was changed.'; cr]. each = #comment ifTrue: [strm nextPutAll: 'New class comment.'; cr. ]]. ^ contents _ strm contents].! ! !ChangeSorter methodsFor: 'code pane' stamp: 'sw 11/13/2001 07:34'! toggleDiffing "Toggle whether diffs should be shown in the code pane" self okToChange ifTrue: [super toggleDiffing. self changed: #contents. self update] ! ! !ChangeSorter methodsFor: 'code pane' stamp: 'JW 2/2/2001 21:41'! wantsOptionalButtons "No optional buttons for ChangeSorter" ^false! ! !ChangeSorter methodsFor: 'annotation' stamp: 'sw 2/22/2001 10:35'! addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream "Add an annotation detailing the prior versions count. Specially handled here for the case of a selector no longer in the system, whose prior version is pointed to by the lost-method pointer in the change held on to by the changeset" (aClass includesSelector: aSelector) ifTrue: [^ super addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream]. aStream nextPutAll: ((myChangeSet methodInfoFromRemoval: {aClass name. aSelector}) ifNil: ['no prior versions'] ifNotNil: ['version(s) retrievable here']), self annotationSeparator! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ChangeSorter class instanceVariableNames: ''! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 21:33'! allChangeSetNames ^ self allChangeSets collect: [:c | c name]! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 21:27'! allChangeSets "Return the list of all current ChangeSets" ^ AllChangeSets! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 21:34'! allChangeSetsWithClass: class selector: selector class ifNil: [^ #()]. ^ self allChangeSets select: [:cs | (cs atSelector: selector class: class) ~~ #none]! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'nk 6/26/2002 12:39'! changeSet: aChangeSet containsClass: aClass | theClass | theClass _ Smalltalk classNamed: aClass. theClass ifNil: [^ false]. ^ aChangeSet containsClass: theClass! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 19:42'! changeSetNamed: aName "Return the change set of the given name, or nil if none found. 1/22/96 sw" ^ AllChangeSets detect: [:aChangeSet | aChangeSet name = aName] ifNone: [nil]! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 19:42'! changeSetsNamedSuchThat: nameBlock "(ChangeSorter changeSetsNamedSuchThat: [:name | name first isDigit and: [name initialInteger >= 373]]) do: [:cs | AllChangeSets remove: cs wither]" ^ AllChangeSets select: [:aChangeSet | nameBlock value: aChangeSet name]! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/6/2001 09:49'! existingOrNewChangeSetNamed: aName | newSet | ^(self changeSetNamed: aName) ifNil: [ newSet _ ChangeSet basicNewNamed: aName. AllChangeSets add: newSet. newSet ]! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/3/2000 14:51'! gatherChangeSets "ChangeSorter gatherChangeSets" "Collect any change sets created in other projects" | allChangeSets obsolete | allChangeSets _ AllChangeSets asSet. ChangeSet allSubInstances do: [:each | (allChangeSets includes: each) == (obsolete _ each isMoribund) ifTrue:[ obsolete ifTrue: ["Was included and is obsolete." AllChangeSets remove: each] ifFalse: ["Was not included and is not obsolete." AllChangeSets add: each]]]. ^ AllChangeSets ! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'sw 8/20/1999 10:27'! highestNumberedChangeSet "ChangeSorter highestNumberedChangeSet" | aList | aList _ (self allChangeSetNames select: [:aString | aString startsWithDigit] thenCollect: [:aString | aString initialIntegerOrNil]). ^ (aList size > 0) ifTrue: [aList max] ifFalse: [nil] ! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'di 4/5/2001 21:37'! mostRecentChangeSetWithChangeForClass: class selector: selector | hits | hits _ self allChangeSets select: [:cs | (cs atSelector: selector class: class) ~~ #none]. hits isEmpty ifTrue: [^ 'not in any change set']. ^ 'recent cs: ', hits last name! ! !ChangeSorter class methodsFor: 'enumerating' stamp: 'BG 10/28/2003 20:38'! promoteToTop: aChangeSet "make aChangeSet the first in the list from now on" AllChangeSets remove: aChangeSet ifAbsent: [^ self]. AllChangeSets add: aChangeSet.! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 16:01'! belongsInAdditions: aChangeSet "Answer whether a change set belongs in the Additions category, which is fed by all change sets that are neither numbered nor in the initial release" ^ (((self belongsInProjectsInRelease: aChangeSet) or: [self belongsInNumbered: aChangeSet])) not! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:38'! belongsInAll: aChangeSet "Answer whether a change set belongs in the All category" ^ true ! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:47'! belongsInMyInitials: aChangeSet "Answer whether a change set belongs in the MyInitials category. " ^ aChangeSet name endsWith: ('-', Utilities authorInitials)! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:45'! belongsInNumbered: aChangeSet "Answer whether a change set belongs in the Numbered category. " ^ aChangeSet name startsWithDigit! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:49'! belongsInProjectChangeSets: aChangeSet "Answer whether a change set belongs in the MyInitials category. " ^ aChangeSet belongsToAProject! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:44'! belongsInProjectsInRelease: aChangeSet "Answer whether a change set belongs in the ProjectsInRelease category. You can hand-tweak this to suit your working style. This just covers the space of project names in the 2.9, 3.0, and 3.1a systems" | aString | ^ ((aString _ aChangeSet name) beginsWith: 'Play With Me') or: [self changeSetNamesInReleaseImage includes: aString]! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 12:56'! belongsInRecentUpdates: aChangeSet "Answer whether a change set belongs in the RecentUpdates category." ^ aChangeSet name startsWithDigit and: [aChangeSet name asInteger >= self recentUpdateMarker]! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/29/2001 14:44'! changeSetCategoryNamed: aName "Answer the changeSetCategory of the given name, or nil if none" ^ ChangeSetCategories elementAt: aName asSymbol ! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 4/16/2002 00:47'! changeSetNamesInReleaseImage "Answer a list of names of project change sets that come pre-shipped in the latest sytem release. On the brink of shipping a new release, call 'ChangeSorter noteChangeSetsInRelease' " ^ ChangeSetNamesInRelease ifNil: [ChangeSetNamesInRelease _ self changeSetNamesInThreeOh]! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 4/16/2002 00:45'! changeSetNamesInThreeOh "Hard-coded: answer a list of names of project change sets that came pre-shipped in Squeak 3.0" ^ #('The Worlds of Squeak' 'Fun with Morphic' 'Games' 'Fun With Music' 'Building with Squeak' 'Squeak and the Internet' 'Squeak in 3D' 'More About Sound' ) ! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:41'! initialize "Initialize the class variables" AllChangeSets == nil ifTrue: [AllChangeSets _ OrderedCollection new]. self gatherChangeSets. ChangeSetCategories ifNil: [self initializeChangeSetCategories]. RecentUpdateMarker _ 0. "ChangeSorter initialize" FileList registerFileReader: self. self registerInFlapsRegistry. ! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 3/30/2001 13:30'! initializeChangeSetCategories "Initialize the set of change-set categories" "ChangeSorter initializeChangeSetCategories" | aCategory | ChangeSetCategories _ ElementCategory new categoryName: #ChangeSetCategories. aCategory _ ChangeSetCategory new categoryName: #All. aCategory membershipSelector: #belongsInAll:. aCategory documentation: 'All change sets known to the system'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #Additions. aCategory membershipSelector: #belongsInAdditions:. aCategory documentation: 'All unnumbered change sets except those representing projects in the system as initially released.'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #MyInitials. aCategory membershipSelector: #belongsInMyInitials:. aCategory documentation: 'All change sets whose names end with the current author''s initials.'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #Numbered. aCategory membershipSelector: #belongsInNumbered:. aCategory documentation: 'All change sets whose names start with a digit -- normally these will be the official updates to the system.'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #ProjectChangeSets. aCategory membershipSelector: #belongsInProjectChangeSets:. aCategory documentation: 'All change sets that are currently associated with projects present in the system right now.'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #ProjectsInRelease. aCategory membershipSelector: #belongsInProjectsInRelease:. aCategory documentation: 'All change sets belonging to projects that were shipped in the initial release of this version of Squeak'. ChangeSetCategories addCategoryItem: aCategory. aCategory _ ChangeSetCategory new categoryName: #RecentUpdates. aCategory membershipSelector: #belongsInRecentUpdates:. aCategory documentation: 'Updates whose numbers are at or beyond the number I have designated as the earliest one to qualify as Recent'. ChangeSetCategories addCategoryItem: aCategory. ChangeSetCategories elementsInOrder do: [:anElem | anElem reconstituteList] ! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'sw 4/16/2002 00:47'! noteChangeSetsInRelease "Freshly compute what the change sets in the release are; to be called manually just before a release" ChangeSetNamesInRelease _ (Project allProjects collect: [:p | p name]) asSet asOrderedCollection. "ChangeSorter noteChangeSetsInRelease"! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:42'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(ChangeSorter prototypicalToolWindow 'Change Set' 'A tool that allows you to view and manipulate all the code changes in a single change set') forFlapNamed: 'Tools']! ! !ChangeSorter class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:32'! unload "Unload the receiver from global registries" self environment at: #FileList ifPresent: [:cl | cl unregisterFileReader: self]. self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !ChangeSorter class methodsFor: 'adding' stamp: 'di 4/6/2001 09:46'! basicNewChangeSet: newName | newSet | newName ifNil: [^ nil]. (self changeSetNamed: newName) ifNotNil: [self inform: 'Sorry that name is already used'. ^ nil]. newSet _ ChangeSet basicNewNamed: newName. AllChangeSets add: newSet. ^ newSet! ! !ChangeSorter class methodsFor: 'adding' stamp: 'sd 5/23/2003 15:15'! newChangeSet "Prompt the user for a name, and establish a new change set of that name (if ok), making it the current changeset. Return nil of not ok, else return the actual changeset." | newName newSet | newName _ FillInTheBlank request: 'Please name the new change set:' initialAnswer: ChangeSet defaultName. newName isEmptyOrNil ifTrue: [^ nil]. newSet _ self basicNewChangeSet: newName. newSet ifNotNil: [ChangeSet newChanges: newSet]. ^ newSet! ! !ChangeSorter class methodsFor: 'adding' stamp: 'sma 11/11/2000 23:23'! newChangeSet: aName "Makes a new change set called aName, add author initials to try to ensure a unique change set name." | newName | newName _ aName , FileDirectory dot , Utilities authorInitials. ^ self basicNewChangeSet: newName! ! !ChangeSorter class methodsFor: 'adding' stamp: 'sd 5/23/2003 15:15'! newChangesFromStream: aStream named: aName "File in the code from the stream into a new change set whose name is derived from aName. Leave the 'current change set' unchanged. Return the new change set or nil on failure." | oldChanges newName newSet | oldChanges _ ChangeSet current. PreviousSet _ oldChanges name. "so a Bumper update can find it" newName _ aName sansPeriodSuffix. newSet _ self basicNewChangeSet: newName. [newSet ifNotNil: [ChangeSet newChanges: newSet. aStream fileInAnnouncing: 'Loading ', newName, '...'. Transcript cr; show: 'File ', aName, ' successfully filed in to change set ', newName]. aStream close] ensure: [ ChangeSet newChanges: oldChanges]. ^ newSet! ! !ChangeSorter class methodsFor: 'removing' stamp: 'sw 1/6/2001 06:21'! deleteChangeSetsNumberedLowerThan: anInteger "Delete all changes sets whose names start with integers smaller than anInteger" ChangeSorter removeChangeSetsNamedSuchThat: [:aName | aName first isDigit and: [aName initialIntegerOrNil < anInteger]]. "ChangeSorter deleteChangeSetsNumberedLowerThan: (ChangeSorter highestNumberedChangeSet name initialIntegerOrNil - 500)" ! ! !ChangeSorter class methodsFor: 'removing' stamp: 'sw 8/18/1999 09:44'! removeChangeSet: aChangeSet "Remove the given changeSet. Caller must assure that it's cool to do this" AllChangeSets remove: aChangeSet ifAbsent: []. aChangeSet wither ! ! !ChangeSorter class methodsFor: 'removing' stamp: 'di 4/5/2001 21:12'! removeChangeSetsNamedSuchThat: nameBlock (ChangeSorter changeSetsNamedSuchThat: nameBlock) do: [:cs | self removeChangeSet: cs]! ! !ChangeSorter class methodsFor: 'removing' stamp: 'di 4/5/2001 21:13'! removeEmptyUnnamedChangeSets "Remove all change sets that are empty, whose names start with Unnamed, and which are not nailed down by belonging to a Project." "ChangeSorter removeEmptyUnnamedChangeSets" | toGo | (toGo _ (self changeSetsNamedSuchThat: [:csName | csName beginsWith: 'Unnamed']) select: [:cs | cs isEmpty and: [cs okayToRemoveInforming: false]]) do: [:cs | self removeChangeSet: cs]. self inform: toGo size printString, ' change set(s) removed.'! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 3/30/2001 13:43'! assuredChangeSetNamed: aName "Answer a change set of the given name. If one already exists, answer that, else create a new one and answer it." | existing | ^ (existing _ self changeSetNamed: aName) ifNotNil: [existing] ifNil: [self basicNewChangeSet: aName]! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 5/23/2001 13:30'! browseChangeSetsWithClass: class selector: selector "Put up a menu comprising a list of change sets that hold changes for the given class and selector. If the user selects one, open a single change-sorter onto it" | hits index | hits _ self allChangeSets select: [:cs | (cs atSelector: selector class: class) ~~ #none]. hits isEmpty ifTrue: [^ self inform: class name, '.', selector , ' is not in any change set']. index _ hits size == 1 ifTrue: [1] ifFalse: [(PopUpMenu labelArray: (hits collect: [:cs | cs name]) lines: #()) startUp]. index = 0 ifTrue: [^ self]. (ChangeSorter new myChangeSet: (hits at: index)) open. ! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 5/23/2001 13:31'! browseChangeSetsWithSelector: aSelector "Put up a list of all change sets that contain an addition, deletion, or change of any method with the given selector" | hits index | hits _ self allChangeSets select: [:cs | cs hasAnyChangeForSelector: aSelector]. hits isEmpty ifTrue: [^ self inform: aSelector , ' is not in any change set']. index _ hits size == 1 ifTrue: [1] ifFalse: [(PopUpMenu labelArray: (hits collect: [:cs | cs name]) lines: #()) startUp]. index = 0 ifTrue: [^ self]. (ChangeSetBrowser new myChangeSet: (hits at: index)) open "ChangeSorter browseChangeSetsWithSelector: #clearPenTrails" ! ! !ChangeSorter class methodsFor: 'services' stamp: 'di 4/5/2001 21:36'! buildAggregateChangeSet "Establish a change-set named Aggregate which bears the union of all the changes in all the existing change-sets in the system (other than any pre-existing Aggregate). This can be useful when wishing to discover potential conflicts between a disk-resident change-set and an image. Formerly very useful, now some of its unique contributions have been overtaken by new features" | aggregateChangeSet | aggregateChangeSet _ self existingOrNewChangeSetNamed: 'Aggregate'. aggregateChangeSet clear. self allChangeSets do: [:aChangeSet | aChangeSet == aggregateChangeSet ifFalse: [aggregateChangeSet assimilateAllChangesFoundIn: aChangeSet]] "ChangeSorter buildAggregateChangeSet" ! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 6/6/2001 12:51'! countOfChangeSetsWithClass: aClass andSelector: aSelector "Answer how many change sets record a change for the given class and selector" ^ (self allChangeSetsWithClass: aClass selector: aSelector) size! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 6/6/2001 12:52'! doesAnyChangeSetHaveClass: aClass andSelector: aSelector "Answer whether any known change set bears a change for the given class and selector" ^ (self countOfChangeSetsWithClass: aClass andSelector: aSelector) > 0! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 3/30/2001 00:30'! recentUpdateMarker "Answer the number representing the threshold of what counts as 'recent' for an update number. This allow you to use the RecentUpdates category in a ChangeSorter to advantage" ^ RecentUpdateMarker ifNil: [RecentUpdateMarker _ 0]! ! !ChangeSorter class methodsFor: 'services' stamp: 'sw 3/30/2001 00:30'! recentUpdateMarker: aNumber "Set the recent update marker as indicated" ^ RecentUpdateMarker _ aNumber! ! !ChangeSorter class methodsFor: 'services' stamp: 'BG 10/28/2003 20:38'! reorderChangeSets "Change the order of the change sets to something more convenient: First come the project changesets that come with the release. These are mostly empty. Next come all numbered updates. Next come all remaining changesets In a ChangeSorter, they will appear in the reversed order." "ChangeSorter reorderChangeSets" | newHead newMid newTail | newHead _ OrderedCollection new. newMid _ OrderedCollection new. newTail _ OrderedCollection new. AllChangeSets do: [:aChangeSet | (self belongsInProjectsInRelease: aChangeSet) ifTrue: [newHead add: aChangeSet] ifFalse: [(self belongsInNumbered: aChangeSet) ifTrue: [newMid add: aChangeSet] ifFalse: [newTail add: aChangeSet]]]. AllChangeSets _ newHead, newMid, newTail.! ! !ChangeSorter class methodsFor: 'services' stamp: 'sd 5/23/2003 14:27'! secondaryChangeSet "Answer a likely change set to use as the second initial one in a Dual Change Sorter. " AllChangeSets size = 1 ifTrue: [^ AllChangeSets first]. AllChangeSets last == ChangeSet current ifTrue: [^ AllChangeSets at: (AllChangeSets size - 1)] ifFalse: [^ AllChangeSets last]! ! !ChangeSorter class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:33'! fileIntoNewChangeSet: fullName "File in all of the contents of the currently selected file, if any, into a new change set." | fn ff | fullName ifNil: [^ Beeper beep]. ff _ FileStream readOnlyFileNamed: (fn _ fullName). ((FileDirectory extensionFor: fn) sameAs: 'html') ifTrue: [ff _ ff asHtml]. self newChangesFromStream: ff named: (FileDirectory localNameFor: fn)! ! !ChangeSorter class methodsFor: 'fileIn/Out' stamp: 'sd 2/6/2002 21:29'! fileReaderServicesForFile: fullName suffix: suffix ^(suffix = 'st') | (suffix = 'cs') | (suffix = '*') ifTrue: [ self services] ifFalse: [#()]! ! !ChangeSorter class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 01:36'! serviceFileIntoNewChangeSet "Answer a service for installing a file into a new change set" ^ SimpleServiceEntry provider: self label: 'install into new change set' selector: #fileIntoNewChangeSet: description: 'install the file as a body of code in the image: create a new change set and file-in the selected file into it' buttonLabel: 'install'! ! !ChangeSorter class methodsFor: 'fileIn/Out' stamp: 'sd 2/1/2002 22:47'! services ^ Array with: self serviceFileIntoNewChangeSet ! ! !ChangeSorter class methodsFor: 'utilities' stamp: 'sd 1/16/2004 21:36'! fileOutChangeSetsNamed: nameList "File out the list of change sets whose names are provided" "ChangeSorter fileOutChangeSetsNamed: #('New Changes' 'miscTidies-sw')" | notFound aChangeSet infoString empty | notFound _ OrderedCollection new. empty _ OrderedCollection new. nameList do: [:aName | (aChangeSet _ self changeSetNamed: aName) ifNotNil: [aChangeSet isEmpty ifTrue: [empty add: aName] ifFalse: [aChangeSet fileOut]] ifNil: [notFound add: aName]]. infoString _ (nameList size - notFound size) printString, ' change set(s) filed out'. notFound size > 0 ifTrue: [infoString _ infoString, ' ', notFound size printString, ' change set(s) not found:'. notFound do: [:aName | infoString _ infoString, ' ', aName]]. empty size > 0 ifTrue: [infoString _ infoString, ' ', empty size printString, ' change set(s) were empty:'. empty do: [:aName | infoString _ infoString, ' ', aName]]. self inform: infoString! ! MessageSet subclass: #ChangedMessageSet instanceVariableNames: 'changeSet' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !ChangedMessageSet commentStamp: '<historical>' prior: 0! A ChangedMessageSet is a message set associated with a change-set; it bears an entry for every method added or changed in the change set, as well as for every class-comment of which the change-set bears a note.! !ChangedMessageSet methodsFor: 'initialization'! changeSet: aChangeSet changeSet _ aChangeSet! ! !ChangedMessageSet methodsFor: 'acceptance' stamp: 'sw 6/26/2001 11:42'! contents: aString notifying: aController "Accept the string as new source for the current method, and make certain the annotation pane gets invalidated" | existingSelector existingClass superResult newSelector | existingSelector _ self selectedMessageName. existingClass _ self selectedClassOrMetaClass. superResult _ super contents: aString notifying: aController. superResult ifTrue: "succeeded" [newSelector _ Parser new parseSelector: aString. newSelector ~= existingSelector ifTrue: "Selector changed -- maybe an addition" [self reformulateList. self changed: #messageList. self messageList doWithIndex: [:aMethodReference :anIndex | (aMethodReference actualClass == existingClass and: [aMethodReference methodSymbol == newSelector]) ifTrue: [self messageListIndex: anIndex]]]]. ^ superResult! ! !ChangedMessageSet methodsFor: 'message list' stamp: 'sw 1/28/2001 20:59'! growable "Answer whether the receiver can be changed by manual additions & deletions" ^ false! ! !ChangedMessageSet methodsFor: 'reformulation' stamp: 'sw 6/26/2001 11:20'! reformulateList "Reformulate the message list of the receiver" self initializeMessageList: (changeSet changedMessageListAugmented select: [:each | each isValid]) ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ChangedMessageSet class instanceVariableNames: ''! !ChangedMessageSet class methodsFor: 'as yet unclassified' stamp: 'RAA 5/29/2001 10:19'! openFor: aChangeSet "Open up a ChangedMessageSet browser on the given change set; this is a conventional message-list browser whose message-list consists of all the methods in aChangeSet. After any method submission, the message list is refigured, making it plausibly dynamic" | messageSet | messageSet _ aChangeSet changedMessageListAugmented select: [ :each | each isValid]. self openMessageList: messageSet name: 'Methods in Change Set ', aChangeSet name autoSelect: nil changeSet: aChangeSet! ! !ChangedMessageSet class methodsFor: 'as yet unclassified' stamp: 'BG 10/28/2003 20:51'! openMessageList: messageList name: labelString autoSelect: autoSelectString changeSet: aChangeSet | messageSet | messageSet _ self messageList: messageList. messageSet changeSet: aChangeSet. messageSet autoSelectString: autoSelectString. Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers scheduleActive: (self open: messageSet name: labelString)]! ! Magnitude subclass: #Character instanceVariableNames: 'value' classVariableNames: 'CharacterTable ClassificationTable LetterBits LowercaseBit UppercaseBit' poolDictionaries: '' category: 'Collections-Text'! !Character commentStamp: '<historical>' prior: 0! 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.! !Character methodsFor: 'accessing'! asciiValue "Answer the value of the receiver that represents its ascii encoding." ^value! ! !Character methodsFor: 'accessing'! digitValue "Answer 0-9 if the receiver is $0-$9, 10-35 if it is $A-$Z, and < 0 otherwise. This is used to parse literal numbers of radix 2-36." value <= $9 asciiValue ifTrue: [^value - $0 asciiValue]. value >= $A asciiValue ifTrue: [value <= $Z asciiValue ifTrue: [^value - $A asciiValue + 10]]. ^ -1! ! !Character methodsFor: 'comparing'! < aCharacter "Answer true if the receiver's value < aCharacter's value." ^self asciiValue < aCharacter asciiValue! ! !Character methodsFor: 'comparing'! = aCharacter "Primitive. Answer true if the receiver and the argument are the same object (have the same object pointer) and false otherwise. Optional. See Object documentation whatIsAPrimitive." <primitive: 110> ^self == aCharacter! ! !Character methodsFor: 'comparing'! > aCharacter "Answer true if the receiver's value > aCharacter's value." ^self asciiValue > aCharacter asciiValue! ! !Character methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^value! ! !Character methodsFor: 'testing'! isAlphaNumeric "Answer whether the receiver is a letter or a digit." ^self isLetter or: [self isDigit]! ! !Character methodsFor: 'testing'! isDigit "Answer whether the receiver is a digit." ^value >= 48 and: [value <= 57]! ! !Character methodsFor: 'testing' stamp: 'dgd 8/24/2003 14:50'! isLetter "Answer whether the receiver is a letter." ^ (ClassificationTable at: value + 1) anyMask: LetterBits! ! !Character methodsFor: 'testing' stamp: 'dgd 8/24/2003 14:51'! isLowercase "Answer whether the receiver is a lowercase letter. (The old implementation answered whether the receiver is not an uppercase letter.)" ^ ((ClassificationTable at: value + 1) bitAnd: LowercaseBit) = LowercaseBit! ! !Character methodsFor: 'testing' stamp: 'dgd 8/24/2003 14:52'! isSafeForHTTP "whether a character is 'safe', or needs to be escaped when used, eg, in a URL" ^ value < 128 and: [self isAlphaNumeric or: ['.~-_' includes: self]]! ! !Character methodsFor: 'testing'! isSeparator "Answer whether the receiver is one of the separator characters--space, cr, tab, line feed, or form feed." value = 32 ifTrue: [^true]. "space" value = 13 ifTrue: [^true]. "cr" value = 9 ifTrue: [^true]. "tab" value = 10 ifTrue: [^true]. "line feed" value = 12 ifTrue: [^true]. "form feed" ^false! ! !Character methodsFor: 'testing' stamp: 'di 4/3/1999 00:38'! isSpecial "Answer whether the receiver is one of the special characters" ^'+-/\*~<>=@,%|&?!!' includes: self! ! !Character methodsFor: 'testing' stamp: 'dgd 8/24/2003 14:52'! isUppercase "Answer whether the receiver is an uppercase letter. (The old implementation answered whether the receiver is not a lowercase letter.)" ^ ((ClassificationTable at: value + 1) bitAnd: UppercaseBit) = UppercaseBit! ! !Character methodsFor: 'testing'! isVowel "Answer whether the receiver is one of the vowels, AEIOU, in upper or lower case." ^'AEIOU' includes: self asUppercase! ! !Character methodsFor: 'testing'! tokenish "Answer whether the receiver is a valid token-character--letter, digit, or colon." ^self isLetter or: [self isDigit or: [self = $:]]! ! !Character methodsFor: 'copying' stamp: 'tk 12/9/2000 11:46'! clone "Answer with the receiver, because Characters are unique."! ! !Character methodsFor: 'copying'! copy "Answer with the receiver because Characters are unique."! ! !Character methodsFor: 'copying'! deepCopy "Answer with the receiver because Characters are unique."! ! !Character methodsFor: 'copying' stamp: 'tk 1/7/1999 16:50'! veryDeepCopyWith: deepCopier "Return self. I can't be copied."! ! !Character methodsFor: 'printing'! hex ^ String with: ('0123456789ABCDEF' at: value//16+1) with: ('0123456789ABCDEF' at: value\\16+1)! ! !Character methodsFor: 'printing'! isLiteral ^true! ! !Character methodsFor: 'printing'! printOn: aStream aStream nextPut: $$. aStream nextPut: self! ! !Character methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:04'! printOnStream: aStream aStream print:'$', (String with:self).! ! !Character methodsFor: 'printing'! storeOn: aStream "Character literals are preceded by '$'." aStream nextPut: $$; nextPut: self! ! !Character methodsFor: 'converting'! asCharacter "Answer the receiver itself." ^self! ! !Character methodsFor: 'converting' stamp: 'ls 9/5/1998 01:18'! asIRCLowercase "convert to lowercase, using IRC's rules" self == $[ ifTrue: [ ^ ${ ]. self == $] ifTrue: [ ^ $} ]. self == $\ ifTrue: [ ^ $| ]. ^self asLowercase! ! !Character methodsFor: 'converting'! asInteger "Answer the value of the receiver." ^value! ! !Character methodsFor: 'converting' stamp: 'dgd 8/24/2003 14:53'! asLowercase "If the receiver is uppercase, answer its matching lowercase Character." ^ Character value: ((ClassificationTable at: value + 1) bitAnd: 255)! ! !Character methodsFor: 'converting' stamp: 'sma 3/11/2000 17:21'! asString ^ String with: self! ! !Character methodsFor: 'converting' stamp: 'raa 5/26/2001 09:54'! asSymbol "Answer a Symbol consisting of the receiver as the only element." ^Symbol internCharacter: self! ! !Character methodsFor: 'converting' stamp: 'tk 9/4/2000 12:05'! asText ^ self asString asText! ! !Character methodsFor: 'converting' stamp: 'dgd 8/24/2003 14:53'! asUppercase "If the receiver is lowercase, answer its matching uppercase Character." ^ Character value: (((ClassificationTable at: value + 1) bitShift: -8) bitAnd: 255)! ! !Character methodsFor: 'converting' stamp: 'sma 3/15/2000 22:57'! isoToSqueak "Convert receiver from iso8895-1 (actually CP1252) to mac encoding. Does not do lf/cr conversion!! Characters not available in MacRoman encoding have been remapped to their base characters or to $?." value < 128 ifTrue: [^ self]. ^ Character value: (#( 219 63 226 196 227 201 160 224 246 228 83 220 206 63 90 63 "80-8F" 63 212 213 210 211 165 208 209 247 170 115 221 207 63 122 217 "90-9F" 202 193 162 163 63 180 124 164 172 169 187 199 194 45 168 248 "A0-AF" 161 177 50 51 171 181 166 225 252 49 188 200 63 63 63 192 "B0-BF" 203 231 229 204 128 129 174 130 233 131 230 232 237 234 235 236 "C0-CF" 63 132 241 238 239 205 133 42 175 244 242 243 134 89 63 167 "D0-DF" 136 135 137 139 138 140 190 141 143 142 144 145 147 146 148 149 "E0-EF" 63 150 152 151 153 155 154 214 191 157 156 158 159 121 63 216 "F0-FF" ) at: value - 127)! ! !Character methodsFor: 'converting' stamp: 'bf 3/9/2000 16:52'! squeakToIso "Convert from mac to iso8895-1 encoding. Does not do lf/cr conversion!!" value < 128 ifTrue: [^self]. ^ Character value: (#(196 197 199 201 209 214 220 225 224 226 228 227 229 231 233 232 234 235 237 236 238 239 241 243 242 244 246 245 250 249 251 252 185 176 162 163 167 130 182 223 174 169 142 180 168 173 198 216 141 177 178 179 165 181 166 183 184 160 188 170 186 189 230 248 191 161 172 146 128 129 140 171 187 131 190 192 195 213 145 147 208 132 150 148 149 144 247 215 255 221 152 151 134 153 222 164 136 135 137 139 138 194 202 193 203 200 205 206 207 204 211 212 240 210 218 219 217 155 154 133 143 157 156 158 159 253 254 175) at: value - 127)! ! !Character methodsFor: 'converting'! to: other "Answer with a collection in ascii order -- $a to: $z" ^ (self asciiValue to: other asciiValue) collect: [:ascii | Character value: ascii]! ! !Character methodsFor: 'object fileIn' stamp: 'tk 1/17/2000 11:27'! comeFullyUpOnReload: smartRefStream "Use existing an Character. Don't use the new copy." ^ self class value: value! ! !Character methodsFor: 'object fileIn' stamp: 'tk 2/16/2001 14:52'! objectForDataStream: refStrm "I am being collected for inclusion in a segment. Do not include Characters!! Let them be in outPointers." refStrm insideASegment ifFalse: ["Normal use" ^ self] ifTrue: ["recording objects to go into an ImageSegment" "remove it from references. Do not trace." refStrm references removeKey: self ifAbsent: []. ^ nil] ! ! !Character methodsFor: '*packageinfo-base' stamp: 'ab 5/31/2003 17:15'! escapeEntities #($< '<' $> '>' $& '&') pairsDo: [:k :v | self = k ifTrue: [^ v]]. ^ String with: self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Character class instanceVariableNames: ''! !Character class methodsFor: 'class initialization' stamp: 'dgd 8/24/2003 14:47'! initialize "Create the table of unique Characters." self initializeClassificationTable! ! !Character class methodsFor: 'class initialization' stamp: 'dgd 8/24/2003 15:10'! initializeClassificationTable " Initialize the classification table. The classification table is a compact encoding of upper and lower cases of characters with - bits 0-7: The lower case value of this character. - bits 8-15: The upper case value of this character. - bit 16: lowercase bit (e.g., isLowercase == true) - bit 17: uppercase bit (e.g., isUppercase == true) " | ch1 ch2 | LowercaseBit := 1 bitShift: 16. UppercaseBit := 1 bitShift: 17. "Initialize the letter bits (e.g., isLetter == true)" LetterBits := LowercaseBit bitOr: UppercaseBit. ClassificationTable := Array new: 256. "Initialize the defaults (neither lower nor upper case)" 0 to: 255 do:[:i| ClassificationTable at: i+1 put: (i bitShift: 8) + i. ]. "Initialize character pairs (upper-lower case)" #( "Basic roman" ($A $a) ($B $b) ($C $c) ($D $d) ($E $e) ($F $f) ($G $g) ($H $h) ($I $i) ($J $j) ($K $k) ($L $l) ($M $m) ($N $n) ($O $o) ($P $p) ($Q $q) ($R $r) ($S $s) ($T $t) ($U $u) ($V $v) ($W $w) ($X $x) ($Y $y) ($Z $z) "International" ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) "International - Spanish" ($ $) ($ $) ($ $) ($ $) "International - PLEASE CHECK" ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ($ $) ) do:[:pair| ch1 := pair first asciiValue. ch2 := pair last asciiValue. ClassificationTable at: ch1+1 put: (ch1 bitShift: 8) + ch2 + UppercaseBit. ClassificationTable at: ch2+1 put: (ch1 bitShift: 8) + ch2 + LowercaseBit. ]. "Initialize a few others for which we only have lower case versions." #($ $ $ $) do:[:char| ch1 := char asciiValue. ClassificationTable at: ch1+1 put: (ch1 bitShift: 8) + ch1 + LowercaseBit. ]. ! ! !Character class methodsFor: 'instance creation' stamp: 'ls 8/15/1998 06:56'! allCharacters ^ (0 to: 255) collect: [:v | Character value: v] ! ! !Character class methodsFor: 'instance creation'! digitValue: x "Answer the Character whose digit value is x. For example, answer $9 for x=9, $0 for x=0, $A for x=10, $Z for x=35." | index | index _ x asInteger. ^CharacterTable at: (index < 10 ifTrue: [48 + index] ifFalse: [55 + index]) + 1! ! !Character class methodsFor: 'instance creation'! new "Creating new characters is not allowed." self error: 'cannot create new characters'! ! !Character class methodsFor: 'instance creation'! separators ^ #(32 "space" 13 "cr" 9 "tab" 10 "line feed" 12 "form feed") collect: [:v | Character value: v] ! ! !Character class methodsFor: 'instance creation'! value: anInteger "Answer the Character whose value is anInteger." ^CharacterTable at: anInteger + 1! ! !Character class methodsFor: 'accessing untypeable characters'! backspace "Answer the Character representing a backspace." ^self value: 8! ! !Character class methodsFor: 'accessing untypeable characters'! cr "Answer the Character representing a carriage return." ^self value: 13! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! delete ^ self value: 127! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! end ^ self value: 4! ! !Character class methodsFor: 'accessing untypeable characters'! enter "Answer the Character representing enter." ^self value: 3! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'sma 3/15/2000 22:33'! euro "The Euro currency sign, that E with two dashes. The key code is a wild guess" ^ Character value: 219! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! home ^ self value: 1! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! insert ^ self value: 5! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ls 9/8/1998 22:15'! lf "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters'! linefeed "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'sma 3/11/2000 20:47'! nbsp "non-breakable space." ^ Character value: 202! ! !Character class methodsFor: 'accessing untypeable characters'! newPage "Answer the Character representing a form feed." ^self value: 12! ! !Character class methodsFor: 'accessing untypeable characters'! space "Answer the Character representing a space." ^self value: 32! ! !Character class methodsFor: 'accessing untypeable characters'! tab "Answer the Character representing a tab." ^self value: 9! ! !Character class methodsFor: 'constants' stamp: 'rhi 9/8/2000 14:57'! alphabet "($a to: $z) as: String" ^ 'abcdefghijklmnopqrstuvwxyz' copy! ! !Character class methodsFor: 'constants'! characterTable "Answer the class variable in which unique Characters are stored." ^CharacterTable! ! Rectangle subclass: #CharacterBlock instanceVariableNames: 'stringIndex text textLine' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !CharacterBlock commentStamp: '<historical>' prior: 0! My instances contain information about displayed characters. They are used to return the results of methods: Paragraph characterBlockAtPoint: aPoint and Paragraph characterBlockForIndex: stringIndex. Any recomposition or movement of a Paragraph can make the instance obsolete.! !CharacterBlock methodsFor: 'accessing' stamp: 'di 6/7/2000 17:33'! copy "Overridden because Rectangle does a deepCopy, which goes nuts with the text" ^ self clone! ! !CharacterBlock methodsFor: 'accessing'! stringIndex "Answer the position of the receiver in the string it indexes." ^stringIndex! ! !CharacterBlock methodsFor: 'comparing'! < aCharacterBlock "Answer whether the string index of the receiver precedes that of aCharacterBlock." ^stringIndex < aCharacterBlock stringIndex! ! !CharacterBlock methodsFor: 'comparing'! <= aCharacterBlock "Answer whether the string index of the receiver does not come after that of aCharacterBlock." ^(self > aCharacterBlock) not! ! !CharacterBlock methodsFor: 'comparing'! = aCharacterBlock self species = aCharacterBlock species ifTrue: [^stringIndex = aCharacterBlock stringIndex] ifFalse: [^false]! ! !CharacterBlock methodsFor: 'comparing'! > aCharacterBlock "Answer whether the string index of the receiver comes after that of aCharacterBlock." ^aCharacterBlock < self! ! !CharacterBlock methodsFor: 'comparing'! >= aCharacterBlock "Answer whether the string index of the receiver does not precede that of aCharacterBlock." ^(self < aCharacterBlock) not! ! !CharacterBlock methodsFor: 'comparing' stamp: 'th 9/17/2002 11:54'! max: aCharacterBlock aCharacterBlock ifNil:[^self]. ^aCharacterBlock > self ifTrue:[ aCharacterBlock] ifFalse:[self].! ! !CharacterBlock methodsFor: 'comparing' stamp: 'th 9/17/2002 11:54'! min: aCharacterBlock aCharacterBlock ifNil:[^self]. ^aCharacterBlock < self ifTrue:[ aCharacterBlock] ifFalse:[self].! ! !CharacterBlock methodsFor: 'printing' stamp: 'di 12/2/97 19:15'! printOn: aStream aStream nextPutAll: 'a CharacterBlock with index '. stringIndex printOn: aStream. (text ~~ nil and: [text size> 0 and: [stringIndex between: 1 and: text size]]) ifTrue: [aStream nextPutAll: ' and character '. (text at: stringIndex) printOn: aStream]. aStream nextPutAll: ' and rectangle '. super printOn: aStream. textLine ifNotNil: [aStream cr; nextPutAll: ' in '. textLine printOn: aStream]. ! ! !CharacterBlock methodsFor: 'private'! moveBy: aPoint "Change the corner positions of the receiver so that its area translates by the amount defined by the argument, aPoint." origin _ origin + aPoint. corner _ corner + aPoint! ! !CharacterBlock methodsFor: 'private' stamp: 'di 10/23/97 22:33'! stringIndex: anInteger text: aText topLeft: topLeft extent: extent stringIndex _ anInteger. text _ aText. super setOrigin: topLeft corner: topLeft + extent ! ! CharacterScanner subclass: #CharacterBlockScanner instanceVariableNames: 'characterPoint characterIndex lastCharacter lastCharacterExtent lastSpaceOrTabExtent nextLeftMargin specialWidth' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !CharacterBlockScanner commentStamp: '<historical>' prior: 0! 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.! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'RAA 2/25/2001 14:55'! cr "Answer a CharacterBlock that specifies the current location of the mouse relative to a carriage return stop condition that has just been encountered. The ParagraphEditor convention is to denote selections by CharacterBlocks, sometimes including the carriage return (cursor is at the end) and sometimes not (cursor is in the middle of the text)." ((characterIndex ~= nil and: [characterIndex > text size]) or: [(line last = text size) and: [(destY + line lineHeight) < characterPoint y]]) ifTrue: ["When off end of string, give data for next character" destY _ destY + line lineHeight. lastCharacter _ nil. characterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ destY. lastIndex _ lastIndex + 1. self lastCharacterExtentSetX: 0. ^ true]. lastCharacter _ CR. characterPoint _ destX @ destY. self lastCharacterExtentSetX: rightMargin - destX. ^true! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 12/15/2001 23:28'! crossedX "Text display has wrapping. The scanner just found a character past the x location of the cursor. We know that the cursor is pointing at a character or before one." | leadingTab currentX | characterIndex == nil ifFalse: [ "If the last character of the last line is a space, and it crosses the right margin, then locating the character block after it is impossible without this hack." characterIndex > text size ifTrue: [ lastIndex _ characterIndex. characterPoint _ (nextLeftMargin ifNil: [leftMargin]) @ (destY + line lineHeight). ^true]]. characterPoint x <= (destX + (lastCharacterExtent x // 2)) ifTrue: [lastCharacter _ (text at: lastIndex). characterPoint _ destX @ destY. ^true]. lastIndex >= line last ifTrue: [lastCharacter _ (text at: line last). characterPoint _ destX @ destY. ^true]. "Pointing past middle of a character, return the next character." lastIndex _ lastIndex + 1. lastCharacter _ text at: lastIndex. currentX _ destX + lastCharacterExtent x + kern. self lastCharacterExtentSetX: (font widthOf: lastCharacter). characterPoint _ currentX @ destY. lastCharacter = Space ifFalse: [^ true]. "Yukky if next character is space or tab." alignment = Justified ifTrue: [self lastCharacterExtentSetX: (lastCharacterExtent x + (line justifiedPadFor: (spaceCount + 1))). ^ true]. true ifTrue: [^ true]. "NOTE: I find no value to the following code, and so have defeated it - DI" "See tabForDisplay for illumination on the following awfulness." leadingTab _ true. line first to: lastIndex - 1 do: [:index | (text at: index) ~= Tab ifTrue: [leadingTab _ false]]. (alignment ~= Justified or: [leadingTab]) ifTrue: [self lastCharacterExtentSetX: (textStyle nextTabXFrom: currentX leftMargin: leftMargin rightMargin: rightMargin) - currentX] ifFalse: [self lastCharacterExtentSetX: (((currentX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount))) - currentX) max: 0)]. ^ true! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 12/15/2001 23:28'! endOfRun "Before arriving at the cursor location, the selection has encountered an end of run. Answer false if the selection continues, true otherwise. Set up indexes for building the appropriate CharacterBlock." | runLength lineStop | ((characterIndex ~~ nil and: [runStopIndex < characterIndex and: [runStopIndex < text size]]) or: [characterIndex == nil and: [lastIndex < line last]]) ifTrue: ["We're really at the end of a real run." runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)). characterIndex ~~ nil ifTrue: [lineStop _ characterIndex "scanning for index"] ifFalse: [lineStop _ line last "scanning for point"]. (runStopIndex _ lastIndex + (runLength - 1)) > lineStop ifTrue: [runStopIndex _ lineStop]. self setStopConditions. ^false]. lastCharacter _ text at: lastIndex. characterPoint _ destX @ destY. ((lastCharacter = Space and: [alignment = Justified]) or: [lastCharacter = Tab and: [lastSpaceOrTabExtent notNil]]) ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent]. characterIndex ~~ nil ifTrue: ["If scanning for an index and we've stopped on that index, then we back destX off by the width of the character stopped on (it will be pointing at the right side of the character) and return" runStopIndex = characterIndex ifTrue: [self characterPointSetX: destX - lastCharacterExtent x. ^true]. "Otherwise the requested index was greater than the length of the string. Return string size + 1 as index, indicate further that off the string by setting character to nil and the extent to 0." lastIndex _ lastIndex + 1. lastCharacter _ nil. self lastCharacterExtentSetX: 0. ^true]. "Scanning for a point and either off the end of the line or off the end of the string." runStopIndex = text size ifTrue: ["off end of string" lastIndex _ lastIndex + 1. lastCharacter _ nil. self lastCharacterExtentSetX: 0. ^true]. "just off end of line without crossing x" lastIndex _ lastIndex + 1. ^true! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:51'! paddedSpace "When the line is justified, the spaces will not be the same as the font's space character. A padding of extra space must be considered in trying to find which character the cursor is pointing at. Answer whether the scanning has crossed the cursor." | pad | pad _ 0. spaceCount _ spaceCount + 1. pad _ line justifiedPadFor: spaceCount. lastSpaceOrTabExtent _ lastCharacterExtent copy. self lastSpaceOrTabExtentSetX: spaceWidth + pad. (destX + lastSpaceOrTabExtent x) >= characterPoint x ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy. ^self crossedX]. lastIndex _ lastIndex + 1. destX _ destX + lastSpaceOrTabExtent x. ^ false ! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 1/8/2000 14:32'! setFont specialWidth _ nil. super setFont! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 12/15/2001 23:28'! setStopConditions "Set the font and the stop conditions for the current run." self setFont. alignment = Justified ifTrue:[ "Make a local copy of stop conditions so we don't modify the default" stopConditions == DefaultStopConditions ifTrue:[stopConditions _ stopConditions copy]. stopConditions at: Space asciiValue + 1 put: #paddedSpace]! ! !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'ar 12/15/2001 23:28'! tab | currentX | currentX _ (alignment == Justified and: [self leadingTab not]) ifTrue: "imbedded tabs in justified text are weird" [destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX] ifFalse: [textStyle nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin]. lastSpaceOrTabExtent _ lastCharacterExtent copy. self lastSpaceOrTabExtentSetX: (currentX - destX max: 0). currentX >= characterPoint x ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy. ^ self crossedX]. destX _ currentX. lastIndex _ lastIndex + 1. ^false! ! !CharacterBlockScanner methodsFor: 'private' stamp: 'ar 12/19/2001 11:24'! buildCharacterBlockIn: para | lineIndex runLength lineStop done stopCondition | "handle nullText" (para numberOfLines = 0 or: [text size = 0]) ifTrue: [^ CharacterBlock new stringIndex: 1 "like being off end of string" text: para text topLeft: (para leftMarginForDisplayForLine: 1 alignment: (alignment ifNil:[textStyle alignment])) @ para compositionRectangle top extent: 0 @ textStyle lineGrid]. "find the line" lineIndex _ para lineIndexOfTop: characterPoint y. destY _ para topAtLineIndex: lineIndex. line _ para lines at: lineIndex. rightMargin _ para rightMarginForDisplay. (lineIndex = para numberOfLines and: [(destY + line lineHeight) < characterPoint y]) ifTrue: ["if beyond lastLine, force search to last character" self characterPointSetX: rightMargin] ifFalse: [characterPoint y < (para compositionRectangle) top ifTrue: ["force search to first line" characterPoint _ (para compositionRectangle) topLeft]. characterPoint x > rightMargin ifTrue: [self characterPointSetX: rightMargin]]. destX _ (leftMargin _ para leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment])). nextLeftMargin_ para leftMarginForDisplayForLine: lineIndex+1 alignment: (alignment ifNil:[textStyle alignment]). lastIndex _ line first. self setStopConditions. "also sets font" runLength _ (text runLengthFor: line first). characterIndex == nil ifTrue: [lineStop _ line last "characterBlockAtPoint"] ifFalse: [lineStop _ characterIndex "characterBlockForIndex"]. (runStopIndex _ lastIndex + (runLength - 1)) > lineStop ifTrue: [runStopIndex _ lineStop]. lastCharacterExtent _ 0 @ line lineHeight. spaceCount _ 0. done _ false. self handleIndentation. [done] whileFalse: [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex in: text string rightX: characterPoint x stopConditions: stopConditions kern: kern. "see setStopConditions for stopping conditions for character block operations." self lastCharacterExtentSetX: (font widthOf: (text at: lastIndex)). (self perform: stopCondition) ifTrue: [characterIndex == nil ifTrue: ["characterBlockAtPoint" ^ CharacterBlock new stringIndex: lastIndex text: text topLeft: characterPoint + (font descentKern @ 0) extent: lastCharacterExtent] ifFalse: ["characterBlockForIndex" ^ CharacterBlock new stringIndex: lastIndex text: text topLeft: characterPoint + ((font descentKern) - kern @ 0) extent: lastCharacterExtent]]]! ! !CharacterBlockScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:34'! characterPointSetX: xVal characterPoint _ xVal @ characterPoint y! ! !CharacterBlockScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:34'! lastCharacterExtentSetX: xVal lastCharacterExtent _ xVal @ lastCharacterExtent y! ! !CharacterBlockScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:34'! lastSpaceOrTabExtentSetX: xVal lastSpaceOrTabExtent _ xVal @ lastSpaceOrTabExtent y! ! !CharacterBlockScanner methodsFor: 'scanning' stamp: 'ar 5/17/2000 19:14'! characterBlockAtPoint: aPoint in: aParagraph "Answer a CharacterBlock for character in aParagraph at point aPoint. It is assumed that aPoint has been transformed into coordinates appropriate to the text's destination form rectangle and the composition rectangle." self initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle. characterPoint _ aPoint. ^self buildCharacterBlockIn: aParagraph! ! !CharacterBlockScanner methodsFor: 'scanning' stamp: 'ar 5/17/2000 19:14'! characterBlockForIndex: targetIndex in: aParagraph "Answer a CharacterBlock for character in aParagraph at targetIndex. The coordinates in the CharacterBlock will be appropriate to the intersection of the destination form rectangle and the composition rectangle." self initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle. characterIndex _ targetIndex. characterPoint _ aParagraph rightMarginForDisplay @ (aParagraph topAtLineIndex: (aParagraph lineIndexOfCharacterIndex: characterIndex)). ^self buildCharacterBlockIn: aParagraph! ! !CharacterBlockScanner methodsFor: 'scanning' stamp: 'hmm 2/2/2001 15:07'! indentationLevel: anInteger super indentationLevel: anInteger. nextLeftMargin _ leftMargin. indentationLevel timesRepeat: [ nextLeftMargin _ textStyle nextTabXFrom: nextLeftMargin leftMargin: leftMargin rightMargin: rightMargin]! ! !CharacterBlockScanner methodsFor: 'scanning' stamp: 'ar 12/16/2001 19:27'! placeEmbeddedObject: anchoredMorph "Workaround: The following should really use #textAnchorType" anchoredMorph relativeTextAnchorPosition ifNotNil:[^true]. (super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false]. specialWidth _ anchoredMorph width. ^ true! ! Object subclass: #CharacterScanner instanceVariableNames: 'destX lastIndex xTable map destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks' classVariableNames: 'DefaultStopConditions' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !CharacterScanner commentStamp: '<historical>' prior: 0! 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.! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:27'! addEmphasis: code "Set the bold-ital-under-strike emphasis." emphasisCode _ emphasisCode bitOr: code! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:27'! addKern: kernDelta "Set the current kern amount." kern _ kern + kernDelta! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 5/17/2000 17:13'! initializeFromParagraph: aParagraph clippedBy: clippingRectangle text _ aParagraph text. textStyle _ aParagraph textStyle. ! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:27'! setActualFont: aFont "Set the basal font to an isolated font reference." font _ aFont! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 12/15/2001 23:31'! setAlignment: style alignment _ style. ! ! !CharacterScanner methodsFor: 'private' stamp: 'di 9/3/2000 13:47'! setFont | priorFont | "Set the font and other emphasis." priorFont _ font. text == nil ifFalse:[ emphasisCode _ 0. kern _ 0. indentationLevel _ 0. alignment _ textStyle alignment. font _ nil. (text attributesAt: lastIndex forStyle: textStyle) do: [:att | att emphasizeScanner: self]]. font == nil ifTrue: [self setFont: textStyle defaultFontIndex]. font _ font emphasized: emphasisCode. priorFont ifNotNil: [destX _ destX + priorFont descentKern]. destX _ destX - font descentKern. "NOTE: next statement should be removed when clipping works" leftMargin ifNotNil: [destX _ destX max: leftMargin]. kern _ kern - font baseKern. "Install various parameters from the font." spaceWidth _ font widthOf: Space. xTable _ font xTable. map _ font characterToGlyphMap. stopConditions _ DefaultStopConditions.! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:28'! setFont: fontNumber "Set the font by number from the textStyle." self setActualFont: (textStyle fontAt: fontNumber)! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:28'! text: t textStyle: ts text _ t. textStyle _ ts! ! !CharacterScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:28'! textColor: ignored "Overridden in DisplayScanner"! ! !CharacterScanner methodsFor: 'scanning' stamp: 'RAA 5/4/2001 13:53'! columnBreak ^true! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 12/17/2001 01:50'! embeddedObject | savedIndex | savedIndex _ lastIndex. text attributesAt: lastIndex do:[:attr| attr anchoredMorph ifNotNil:[ "Following may look strange but logic gets reversed. If the morph fits on this line we're not done (return false for true) and if the morph won't fit we're done (return true for false)" (self placeEmbeddedObject: attr anchoredMorph) ifFalse:[^true]]]. lastIndex _ savedIndex + 1. "for multiple(!!) embedded morphs" ^false! ! !CharacterScanner methodsFor: 'scanning' stamp: 'hmm 7/15/2000 22:40'! handleIndentation self indentationLevel timesRepeat: [ self plainTab]! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 5/17/2000 18:20'! indentationLevel "return the number of tabs that are currently being placed at the beginning of each line" ^indentationLevel ifNil:[0]! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 1/8/2000 14:23'! indentationLevel: anInteger "set the number of tabs to put at the beginning of each line" indentationLevel _ anInteger! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 1/8/2000 14:23'! leadingTab "return true if only tabs lie to the left" line first to: lastIndex do: [:i | (text at: i) == Tab ifFalse: [^ false]]. ^ true! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 12/31/2001 00:52'! measureString: aString inFont: aFont from: startIndex to: stopIndex "WARNING: In order to use this method the receiver has to be set up using #initializeStringMeasurer" destX _ destY _ lastIndex _ 0. xTable _ aFont xTable. map _ aFont characterToGlyphMap. self scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999 stopConditions: stopConditions kern: 0. ^destX! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 12/16/2001 19:27'! placeEmbeddedObject: anchoredMorph "Place the anchoredMorph or return false if it cannot be placed. In any event, advance destX by its width." | w | "Workaround: The following should really use #textAnchorType" anchoredMorph relativeTextAnchorPosition ifNotNil:[^true]. destX _ destX + (w _ anchoredMorph width). (destX > rightMargin and: [(leftMargin + w) <= rightMargin]) ifTrue: ["Won't fit, but would on next line" ^ false]. lastIndex _ lastIndex + 1. self setFont. "Force recalculation of emphasis for next run" ^ true! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 12/15/2001 23:28'! plainTab "This is the basic method of adjusting destX for a tab." destX _ (alignment == Justified and: [self leadingTab not]) ifTrue: "embedded tabs in justified text are weird" [destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX] ifFalse: [textStyle nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin]! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ar 12/17/2001 02:08'! scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta "Primitive. This is the inner loop of text display--but see scanCharactersFrom: to:rightX: which would get the string, stopConditions and displaying from the instance. March through source String from startIndex to stopIndex. If any character is flagged with a non-nil entry in stops, then return the corresponding value. Determine width of each character from xTable, indexed by map. If dextX would exceed rightX, then return stops at: 258. Advance destX by the width of the character. If stopIndex has been reached, then return stops at: 257. Optional. See Object documentation whatIsAPrimitive." | ascii nextDestX char | <primitive: 103> lastIndex _ startIndex. [lastIndex <= stopIndex] whileTrue: [char _ (sourceString at: lastIndex). ascii _ char asciiValue + 1. (stops at: ascii) == nil ifFalse: [^stops at: ascii]. "Note: The following is querying the font about the width since the primitive may have failed due to a non-trivial mapping of characters to glyphs or a non-existing xTable." nextDestX _ destX + (font widthOf: char). nextDestX > rightX ifTrue: [^stops at: CrossedX]. destX _ nextDestX + kernDelta. lastIndex _ lastIndex + 1]. lastIndex _ stopIndex. ^stops at: EndOfRun! ! !CharacterScanner methodsFor: 'initialize' stamp: 'ls 1/14/2002 21:26'! initialize destX _ destY _ leftMargin _ 0.! ! !CharacterScanner methodsFor: 'initialize' stamp: 'ar 12/31/2001 00:52'! initializeStringMeasurer stopConditions _ Array new: 258. stopConditions at: CrossedX put: #crossedX. stopConditions at: EndOfRun put: #endOfRun. ! ! !CharacterScanner methodsFor: 'accessing' stamp: 'ssa 8/19/2008 21:15'! destX: x destX := x! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CharacterScanner class instanceVariableNames: ''! !CharacterScanner class methodsFor: 'class initialization' stamp: 'ar 12/17/2001 02:17'! initialize "CharacterScanner initialize" "NewCharacterScanner initialize" | stopConditions | stopConditions _ Array new: 258. stopConditions atAllPut: nil. stopConditions at: 1+1 put: #embeddedObject. stopConditions at: Space asciiValue + 1 put: nil. stopConditions at: Tab asciiValue + 1 put: #tab. stopConditions at: CR asciiValue + 1 put: #cr. stopConditions at: EndOfRun put: #endOfRun. stopConditions at: CrossedX put: #crossedX. DefaultStopConditions _ stopConditions.! ! Collection subclass: #CharacterSet instanceVariableNames: 'map' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !CharacterSet commentStamp: '<historical>' prior: 0! A set of characters. Lookups for inclusion are very fast.! !CharacterSet methodsFor: 'collection ops' stamp: 'ls 8/17/1998 20:33'! add: aCharacter map at: aCharacter asciiValue+1 put: 1.! ! !CharacterSet methodsFor: 'collection ops' stamp: 'ls 8/17/1998 20:41'! do: aBlock "evaluate aBlock with each character in the set" Character allCharacters do: [ :c | (self includes: c) ifTrue: [ aBlock value: c ] ] ! ! !CharacterSet methodsFor: 'collection ops' stamp: 'ls 8/17/1998 20:31'! includes: aCharacter ^(map at: aCharacter asciiValue + 1) > 0! ! !CharacterSet methodsFor: 'collection ops' stamp: 'ls 8/17/1998 20:34'! remove: aCharacter map at: aCharacter asciiValue + 1 put: 0! ! !CharacterSet methodsFor: 'conversion' stamp: 'ls 8/17/1998 20:39'! complement "return a character set containing precisely the characters the receiver does not" | set | set _ CharacterSet allCharacters. self do: [ :c | set remove: c ]. ^set! ! !CharacterSet methodsFor: 'comparison' stamp: 'tk 7/5/2001 21:58'! = anObject ^self species == anObject species and: [ self byteArrayMap = anObject byteArrayMap ]! ! !CharacterSet methodsFor: 'comparison' stamp: 'ls 8/17/1998 20:46'! hash ^self byteArrayMap hash! ! !CharacterSet methodsFor: 'comparison' stamp: 'tk 7/5/2001 21:57'! species ^CharacterSet! ! !CharacterSet methodsFor: 'private' stamp: 'ls 8/17/1998 20:35'! byteArrayMap "return a ByteArray mapping each ascii value to a 1 if that ascii value is in the set, and a 0 if it isn't. Intended for use by primitives only" ^map! ! !CharacterSet methodsFor: 'private' stamp: 'ls 8/17/1998 20:30'! initialize map _ ByteArray new: 256 withAll: 0.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CharacterSet class instanceVariableNames: ''! !CharacterSet class methodsFor: 'instance creation' stamp: 'ls 8/17/1998 20:42'! allCharacters "return a set containing all characters" | set | set _ self empty. 0 to: 255 do: [ :ascii | set add: (Character value: ascii) ]. ^set! ! !CharacterSet class methodsFor: 'instance creation' stamp: 'ls 8/17/1998 20:36'! empty "return an empty set of characters" ^super new initialize! ! !CharacterSet class methodsFor: 'instance creation' stamp: 'ls 1/3/1999 12:52'! newFrom: aCollection | newCollection | newCollection _ self new. newCollection addAll: aCollection. ^newCollection! ! !CharacterSet class methodsFor: 'instance creation' stamp: 'ls 8/18/1998 00:40'! separators "return a set containing just the whitespace characters" | set | set _ self empty. set addAll: Character separators. ^set! ! SharedPool subclass: #ChronologyConstants instanceVariableNames: 'seconds offset jdn nanos' classVariableNames: 'DayNames DaysInMonth MonthNames NanosInMillisecond NanosInSecond SecondsInDay SecondsInHour SecondsInMinute SqueakEpoch' poolDictionaries: '' category: 'Kernel-Chronology'! !ChronologyConstants commentStamp: 'brp 3/12/2004 14:34' prior: 0! ChronologyConstants is a SharedPool for the constants used by the Kernel-Chronology classes.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ChronologyConstants class instanceVariableNames: ''! !ChronologyConstants class methodsFor: 'as yet unclassified' stamp: 'brp 9/25/2003 10:49'! initialize "ChronologyConstants initialize" SqueakEpoch _ 2415386. "Julian day number of 1 Jan 1901" SecondsInDay _ 86400. SecondsInHour _ 3600. SecondsInMinute _ 60. NanosInSecond _ 10 raisedTo: 9. NanosInMillisecond _ 10 raisedTo: 6. DayNames _ #(Sunday Monday Tuesday Wednesday Thursday Friday Saturday). MonthNames _ #(January February March April May June July August September October November December). DaysInMonth _ #(31 28 31 30 31 30 31 31 30 31 30 31). ! ! Arc subclass: #Circle instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Circle commentStamp: '<historical>' prior: 0! I represent a full circle. I am made from four Arcs.! !Circle methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm 1 to: 4 do: [:i | super quadrant: i. super displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm]! ! !Circle methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm 1 to: 4 do: [:i | super quadrant: i. super displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm]! ! !Circle methodsFor: 'display box access'! computeBoundingBox ^center - radius + form offset extent: form extent + (radius * 2) asPoint! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Circle class instanceVariableNames: ''! !Circle class methodsFor: 'examples'! exampleOne "Click any button somewhere on the screen. The point will be the center of the circcle of radius 150." | aCircle aForm | aForm _ Form extent: 1@30. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 150. aCircle center: Sensor waitButton. aCircle displayOn: Display "Circle exampleOne"! ! !Circle class methodsFor: 'examples'! exampleTwo "Designate a rectangular area that should be used as the brush for displaying the circle. Click any button at a point on the screen which will be the center location for the circle. The curve will be displayed with a long black form." | aCircle aForm | aForm _ Form fromUser. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 150. aCircle center: Sensor waitButton. aCircle displayOn: Display at: 0 @ 0 rule: Form reverse "Circle exampleTwo"! ! ClassDescription subclass: #Class instanceVariableNames: 'subclasses name classPool sharedPools environment category' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !Class commentStamp: '<historical>' prior: 0! I add a number of facilities to those in ClassDescription: A set of all my subclasses (defined in ClassDescription, but only used here and below) A name by which I can be found in a SystemDictionary A classPool for class variables shared between this class and its metaclass A list of sharedPools which probably should be supplanted by some better mechanism. 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. The slot 'subclasses' is a redundant structure. It is never used during execution, but is used by the development system to simplify or speed certain operations. ! !Class methodsFor: 'initialize-release' stamp: 'hg 10/30/2001 13:38'! deactivate "A remnant from the 3.3a modules work, retained . Does nothing, but may be overridden in Metaclasses."! ! !Class methodsFor: 'initialize-release' stamp: 'ar 5/17/2003 14:14'! declare: varString "Declare class variables common to all instances. Answer whether recompilation is advisable." | newVars conflicts | newVars _ (Scanner new scanFieldNames: varString) collect: [:x | x asSymbol]. newVars do: [:var | var first isLowercase ifTrue: [self error: var, ' class variable name should be capitalized; proceed to include anyway.']]. conflicts _ false. classPool == nil ifFalse: [(classPool keys reject: [:x | newVars includes: x]) do: [:var | self removeClassVarName: var]]. (newVars reject: [:var | self classPool includesKey: var]) do: [:var | "adding" "check if new vars defined elsewhere" (self bindingOf: var) notNil ifTrue: [self error: var , ' is defined elsewhere'. conflicts _ true]]. newVars size > 0 ifTrue: [classPool _ self classPool. "in case it was nil" newVars do: [:var | classPool declare: var from: Undeclared]]. ^conflicts! ! !Class methodsFor: 'initialize-release' stamp: 'ar 9/10/1999 17:34'! obsolete "Change the receiver and all of its subclasses to an obsolete class." self == Object ifTrue:[^self error:'Object is NOT obsolete']. name _ 'AnObsolete' , name. Object class instSize + 1 to: self class instSize do: [:i | self instVarAt: i put: nil]. "Store nil over class instVars." classPool _ nil. sharedPools _ nil. self class obsolete. super obsolete. ! ! !Class methodsFor: 'initialize-release' stamp: 'ar 3/1/2001 22:28'! removeFromSystem "Forget the receiver from the Smalltalk global dictionary. Any existing instances will refer to an obsolete version of the receiver." self removeFromSystem: true.! ! !Class methodsFor: 'initialize-release' stamp: 'NS 1/16/2004 15:16'! removeFromSystem: logged "Forget the receiver from the Smalltalk global dictionary. Any existing instances will refer to an obsolete version of the receiver." "keep the class name and category for triggering the system change message. If we wait to long, then we get obsolete information which is not what we want." "tell class to deactivate and unload itself-- two separate events in the module system" self deactivate; unload. self superclass ifNotNil: ["If we have no superclass there's nothing to be remembered" self superclass addObsoleteSubclass: self]. self environment forgetClass: self logged: logged. self obsolete.! ! !Class methodsFor: 'initialize-release' stamp: 'sd 3/28/2003 16:09'! sharing: poolString "Set up sharedPools. Answer whether recompilation is advisable." | oldPools found | oldPools _ self sharedPools. sharedPools _ OrderedCollection new. (Scanner new scanFieldNames: poolString) do: [:poolName | sharedPools add: (self environment at: poolName asSymbol ifAbsent:[ (self confirm: 'The pool dictionary ', poolName,' does not exist.', '\Do you want it automatically created?' withCRs) ifTrue:[self environment at: poolName asSymbol put: Dictionary new] ifFalse:[^self error: poolName,' does not exist']])]. sharedPools isEmpty ifTrue: [sharedPools _ nil]. oldPools do: [:pool | found _ false. self sharedPools do: [:p | p == pool ifTrue: [found _ true]]. found ifFalse: [^ true "A pool got deleted"]]. ^ false! ! !Class methodsFor: 'initialize-release' stamp: 'NS 4/6/2004 15:32'! superclass: sup methodDict: md format: ft name: nm organization: org instVarNames: nilOrArray classPool: pool sharedPools: poolSet "Answer an instance of me, a new class, using the arguments of the message as the needed information. Must only be sent to a new instance; else we would need Object flushCache." superclass _ sup. methodDict _ md. format _ ft. name _ nm. instanceVariables _ nilOrArray. classPool _ pool. sharedPools _ poolSet. self organization: org.! ! !Class methodsFor: 'initialize-release' stamp: 'ar 7/20/1999 11:23'! superclass: aClass methodDictionary: mDict format: fmt "Basic initialization of the receiver" super superclass: aClass methodDictionary: mDict format: fmt. subclasses _ nil. "Important for moving down the subclasses field into Class" ! ! !Class methodsFor: 'initialize-release' stamp: 'hg 12/12/2001 12:00'! unload "Sent when a the class is removed. Does nothing, but may be overridden by (class-side) subclasses." ! ! !Class methodsFor: 'accessing'! classPool "Answer the dictionary of class variables." classPool == nil ifTrue: [^Dictionary new] ifFalse: [^classPool]! ! !Class methodsFor: 'accessing'! name "Answer the name of the receiver." name == nil ifTrue: [^super name] ifFalse: [^name]! ! !Class methodsFor: 'testing'! hasMethods "Answer a Boolean according to whether any methods are defined for the receiver (includes whether there are methods defined in the receiver's metaclass)." ^super hasMethods or: [self class hasMethods]! ! !Class methodsFor: 'testing' stamp: 'ar 7/15/1999 15:36'! isObsolete "Return true if the receiver is obsolete." ^(self environment at: name ifAbsent:[nil]) ~~ self! ! !Class methodsFor: 'testing' stamp: 'tk 8/12/1999 15:47'! isSystemDefined "Answer true if the receiver is a system-defined class, and not a UniClass (an instance-specific lightweight class)" ^ self == self officialClass! ! !Class methodsFor: 'testing' stamp: 'tk 8/12/1999 15:49'! officialClass "I am not a UniClass. (See Player officialClass). Return the class you use to make new subclasses." ^ self! ! !Class methodsFor: 'copying' stamp: 'di 2/17/2000 22:43'! copy | newClass | newClass _ self class copy new superclass: superclass methodDict: self methodDict copy format: format name: name organization: self organization copy instVarNames: instanceVariables copy classPool: classPool copy sharedPools: sharedPools. Class instSize+1 to: self class instSize do: [:offset | newClass instVarAt: offset put: (self instVarAt: offset)]. ^ newClass! ! !Class methodsFor: 'class name' stamp: 'sw 12/1/2000 20:39'! externalName "Answer a name by which the receiver can be known." ^ name! ! !Class methodsFor: 'class name' stamp: 'sw 12/18/2000 15:50'! nameForViewer "Answer the name to be shown in the header of a viewer looking at the receiver" ^ self name ifNil: ['Unnamed class']! ! !Class methodsFor: 'class name' stamp: 'NS 1/15/2004 15:41'! rename: aString "The new name of the receiver is the argument, aString." | newName | (newName _ aString asSymbol) ~= self name ifFalse: [^ self]. (self environment includesKey: newName) ifTrue: [^ self error: newName , ' already exists']. (Undeclared includesKey: newName) ifTrue: [self inform: 'There are references to, ' , aString printString , ' from Undeclared. Check them after this change.']. self environment renameClass: self as: newName. name _ newName! ! !Class methodsFor: 'class name' stamp: 'sw 12/1/2000 20:40'! uniqueNameForReference "Answer a unique name by which the receiver can be referred to from user scripts, for example" ^ name! ! !Class methodsFor: 'instance variables' stamp: 'sw 12/26/2003 19:30'! addInstVarName: aString "Add the argument, aString, as one of the receiver's instance variables." ^(ClassBuilder new) name: self name inEnvironment: self environment subclassOf: superclass type: self typeOfClass instanceVariableNames: self instanceVariablesString, ' ', aString classVariableNames: self classVariablesString poolDictionaries: self sharedPoolsString category: self category ! ! !Class methodsFor: 'class variables' stamp: 'NS 1/27/2004 14:19'! addClassVarName: aString "Add the argument, aString, as a class variable of the receiver. Signal an error if the first character of aString is not capitalized, or if it is already a variable named in the class." | symbol oldState | oldState _ self copy. aString first isLowercase ifTrue: [^self error: aString, ' class variable name should be capitalized; proceed to include anyway.']. symbol _ aString asSymbol. self withAllSubclasses do: [:subclass | (subclass bindingOf: symbol) ifNotNil:[ ^ self error: aString , ' is already used as a variable name in class ' , subclass name]]. classPool == nil ifTrue: [classPool _ Dictionary new]. (classPool includesKey: symbol) ifFalse: ["Pick up any refs in Undeclared" classPool declare: symbol from: Undeclared. SystemChangeNotifier uniqueInstance classDefinitionChangedFrom: oldState to: self]! ! !Class methodsFor: 'class variables'! allClassVarNames "Answer a Set of the names of the receiver's class variables, including those defined in the superclasses of the receiver." | aSet | superclass == nil ifTrue: [^self classVarNames] "This is the keys so it is a new Set." ifFalse: [aSet _ superclass allClassVarNames. aSet addAll: self classVarNames. ^aSet]! ! !Class methodsFor: 'class variables'! classVarNames "Answer a Set of the names of the class variables defined in the receiver." ^self classPool keys! ! !Class methodsFor: 'class variables' stamp: 'jm 7/24/1999 12:58'! removeClassVarName: aString "Remove the class variable whose name is the argument, aString, from the names defined in the receiver, a class. Create an error notification if aString is not a class variable or if it is still being used in the code of the class." | aSymbol | aSymbol _ aString asSymbol. (classPool includesKey: aSymbol) ifFalse: [^self error: aString, ' is not a class variable']. self withAllSubclasses do:[:subclass | (Array with: subclass with: subclass class) do:[:classOrMeta | (classOrMeta whichSelectorsReferTo: (classPool associationAt: aSymbol)) isEmpty ifFalse: [ (self confirm: (aString,' is still used in code of class ', classOrMeta name, '.\Is it okay to move it to Undeclared?') withCRs) ifTrue:[^Undeclared declare: aSymbol from: classPool] ifFalse:[^self]]]]. classPool removeKey: aSymbol. classPool isEmpty ifTrue: [classPool _ nil]. ! ! !Class methodsFor: 'pool variables'! allSharedPools "Answer a Set of the pools the receiver shares, including those defined in the superclasses of the receiver." | aSet | ^ superclass == nil ifTrue: [self sharedPools copy] ifFalse: [aSet _ superclass allSharedPools. aSet addAll: self sharedPools. aSet]! ! !Class methodsFor: 'pool variables'! sharedPools "Answer a Set of the pool dictionaries declared in the receiver." sharedPools == nil ifTrue: [^OrderedCollection new] ifFalse: [^sharedPools]! ! !Class methodsFor: 'compiling' stamp: 'ar 5/17/2003 14:06'! bindingOf: varName "Answer the binding of some variable resolved in the scope of the receiver" | aSymbol binding | aSymbol := varName asSymbol. "First look in classVar dictionary." binding := self classPool bindingOf: aSymbol. binding ifNotNil:[^binding]. "Next look in shared pools." self sharedPools do:[:pool | binding := pool bindingOf: aSymbol. binding ifNotNil:[^binding]. ]. "Next look in declared environment." binding := self environment bindingOf: aSymbol. binding ifNotNil:[^binding]. "Finally look higher up the superclass chain and fail at the end." superclass == nil ifTrue: [^ nil] ifFalse: [^ superclass bindingOf: aSymbol]. ! ! !Class methodsFor: 'compiling' stamp: 'ar 7/14/1999 04:56'! compileAll super compileAll. self class compileAll.! ! !Class methodsFor: 'compiling'! compileAllFrom: oldClass "Recompile all the methods in the receiver's method dictionary (not the subclasses). Also recompile the methods in the metaclass." super compileAllFrom: oldClass. self class compileAllFrom: oldClass class! ! !Class methodsFor: 'compiling' stamp: 'sd 3/28/2003 15:24'! possibleVariablesFor: misspelled continuedFrom: oldResults | results | results _ misspelled correctAgainstDictionary: self classPool continuedFrom: oldResults. self sharedPools do: [:pool | results _ misspelled correctAgainstDictionary: pool continuedFrom: results ]. superclass == nil ifTrue: [ ^ misspelled correctAgainstDictionary: self environment continuedFrom: results ] ifFalse: [ ^ superclass possibleVariablesFor: misspelled continuedFrom: results ]! ! !Class methodsFor: 'subclass creation' stamp: 'ar 7/15/1999 18:57'! subclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver)." ^(ClassBuilder new) superclass: self subclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat ! ! !Class methodsFor: 'subclass creation' stamp: 'ar 7/15/1999 18:57'! variableByteSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have indexable byte-sized nonpointer variables." ^(ClassBuilder new) superclass: self variableByteSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat ! ! !Class methodsFor: 'subclass creation' stamp: 'ar 7/15/1999 18:56'! variableSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have indexable pointer variables." ^(ClassBuilder new) superclass: self variableSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat ! ! !Class methodsFor: 'subclass creation' stamp: 'ar 7/15/1999 18:56'! variableWordSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have indexable word-sized nonpointer variables." ^(ClassBuilder new) superclass: self variableWordSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat ! ! !Class methodsFor: 'subclass creation' stamp: 'dwh 11/20/1999 23:44'! weakSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have weak indexable pointer variables." ^(ClassBuilder new) superclass: self weakSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !Class methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 09:58'! fileOut "Create a file whose name is the name of the receiver with '.st' as the extension, and file a description of the receiver onto it." ^ self fileOutAsHtml: false! ! !Class methodsFor: 'fileIn/Out' stamp: 'tk 3/7/2001 13:57'! fileOutAsHtml: useHtml "File a description of the receiver onto a new file whose base name is the name of the receiver." | fileStream | fileStream _ useHtml ifTrue: [(FileStream newFileNamed: self name, FileDirectory dot, 'html') asHtml] ifFalse: [FileStream newFileNamed: self name, FileDirectory dot, 'st']. fileStream header; timeStamp. self sharedPools size > 0 ifTrue: [ self shouldFileOutPools ifTrue: [self fileOutSharedPoolsOn: fileStream]]. self fileOutOn: fileStream moveSource: false toFile: 0. fileStream trailer; close. "DeepCopier new checkVariables." ! ! !Class methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:32'! fileOutInitializerOn: aStream ^self class fileOutInitializerOn: aStream! ! !Class methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:30'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." ^self fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex initializing: true! ! !Class methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:29'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex initializing: aBool "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." Transcript cr; show: name. super fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex. self class nonTrivial ifTrue: [aFileStream cr; nextPutAll: '"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!!'; cr; cr. self class fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex initializing: aBool]! ! !Class methodsFor: 'fileIn/Out' stamp: 'tpr 5/30/2003 13:01'! fileOutPool: aPool onFileStream: aFileStream | aPoolName aValue | (aPool isKindOf: SharedPool class) ifTrue:[^self notify: 'we do not fileout SharedPool type shared pools for now']. aPoolName _ self environment keyAtIdentityValue: aPool. Transcript cr; show: aPoolName. aFileStream nextPutAll: 'Transcript show: ''' , aPoolName , '''; cr!!'; cr. aFileStream nextPutAll: 'Smalltalk at: #' , aPoolName , ' put: Dictionary new!!'; cr. aPool keys asSortedCollection do: [ :aKey | aValue _ aPool at: aKey. aFileStream nextPutAll: aPoolName , ' at: #''' , aKey asString , '''', ' put: '. (aValue isKindOf: Number) ifTrue: [aValue printOn: aFileStream] ifFalse: [aFileStream nextPutAll: '('. aValue printOn: aFileStream. aFileStream nextPutAll: ')']. aFileStream nextPutAll: '!!'; cr]. aFileStream cr! ! !Class methodsFor: 'fileIn/Out' stamp: 'sd 3/28/2003 15:24'! fileOutSharedPoolsOn: aFileStream "file out the shared pools of this class after prompting the user about each pool" | poolsToFileOut | poolsToFileOut _ self sharedPools select: [:aPool | (self shouldFileOutPool: (self environment keyAtIdentityValue: aPool))]. poolsToFileOut do: [:aPool | self fileOutPool: aPool onFileStream: aFileStream]. ! ! !Class methodsFor: 'fileIn/Out'! shouldFileOutPool: aPoolName "respond with true if the user wants to file out aPoolName" ^self confirm: ('FileOut the sharedPool ', aPoolName, '?')! ! !Class methodsFor: 'fileIn/Out'! shouldFileOutPools "respond with true if the user wants to file out the shared pools" ^self confirm: 'FileOut selected sharedPools?'! ! !Class methodsFor: 'accessing class hierarchy' stamp: 'tk 10/17/1999 13:31'! addSubclass: aSubclass "Make the argument, aSubclass, be one of the subclasses of the receiver. Create an error notification if the argument's superclass is not the receiver." aSubclass superclass ~~ self ifTrue: [^self error: aSubclass name , ' is not my subclass']. subclasses == nil ifTrue: [subclasses _ Array with: aSubclass. ^self]. subclasses do:[:cl| cl == aSubclass ifTrue:[^self]]. "Already my subclass" subclasses _ subclasses copyWith: aSubclass.! ! !Class methodsFor: 'accessing class hierarchy' stamp: 'ar 7/14/1999 10:54'! removeSubclass: aSubclass "If the argument, aSubclass, is one of the receiver's subclasses, remove it." subclasses == nil ifFalse: [subclasses _ subclasses copyWithout: aSubclass. subclasses isEmpty ifTrue: [subclasses _ nil]]. ! ! !Class methodsFor: 'accessing class hierarchy' stamp: 'ar 7/14/1999 11:00'! subclasses "Answer a Set containing the receiver's subclasses." ^subclasses == nil ifTrue: [#()] ifFalse: [subclasses copy]! ! !Class methodsFor: 'accessing class hierarchy' stamp: 'ar 7/14/1999 11:00'! subclassesDo: aBlock "Evaluate the argument, aBlock, for each of the receiver's immediate subclasses." subclasses == nil ifFalse:[subclasses do: aBlock]! ! !Class methodsFor: 'accessing class hierarchy' stamp: 'tk 8/18/1999 17:42'! subclassesDoGently: aBlock "Evaluate the argument, aBlock, for each of the receiver's immediate subclasses." subclasses == nil ifFalse: [subclasses do: aBlock]! ! !Class methodsFor: 'private' stamp: 'ar 7/15/1999 15:37'! setName: aSymbol "Private - set the name of the class" name _ aSymbol.! ! !Class methodsFor: 'organization' stamp: 'di 11/16/1999 16:25'! environment environment == nil ifTrue: [^ super environment]. ^ environment! ! !Class methodsFor: 'organization' stamp: 'di 12/23/1999 11:42'! environment: anEnvironment environment _ anEnvironment! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Class class instanceVariableNames: ''! !Class class methodsFor: 'instance creation' stamp: 'di 6/7/2000 22:01'! template: aSystemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class." ^ self templateForSubclassOf: Object name category: aSystemCategoryName ! ! !Class class methodsFor: 'instance creation' stamp: 'di 6/7/2000 21:57'! templateForSubclassOf: priorClassName category: systemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class, given that the class previously looked at was as given" Preferences printAlternateSyntax ifTrue: [^ priorClassName asString, ' subclass (#NameOfSubclass) instanceVariableNames ('''') classVariableNames ('''') poolDictionaries ('''') category (''' , systemCategoryName asString , ''')'] ifFalse: [^ priorClassName asString, ' subclass: #NameOfSubclass instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: ''' , systemCategoryName asString , '''']! ! Object subclass: #ClassBuilder instanceVariableNames: 'environ classMap instVarMap progress maxClassIndex currentClassIndex' classVariableNames: 'QuietMode' poolDictionaries: '' category: 'Kernel-Classes'! !ClassBuilder commentStamp: 'ar 2/27/2003 22:55' prior: 0! Responsible for creating a new class or changing the format of an existing class (from a class definition in a browser or a fileIn). This includes validating the definition, computing the format of instances, creating or modifying the accompanying Metaclass, setting up the class and metaclass objects themselves, registering the class as a global, recompiling methods, modifying affected subclasses, mutating existing instances to the new format, and more. You typically only need to use or modify this class, or even know how it works, when making fundamental changes to how the Smalltalk system and language works. Implementation notes: ClassBuilder relies on the assumption that it can see ALL subclasses of some class. If there are any existing subclasses of some class, regardless of whether they have instances or not, regardless of whether they are considered obsolete or not, ClassBuilder MUST SEE THEM. ! !ClassBuilder methodsFor: 'initialize' stamp: 'ar 3/3/2001 00:29'! doneCompiling: aClass "The receiver has finished modifying the class hierarchy. Do any necessary cleanup." aClass doneCompiling. Behavior flushObsoleteSubclasses.! ! !ClassBuilder methodsFor: 'initialize' stamp: 'ar 8/29/1999 12:32'! initialize environ _ Smalltalk. instVarMap _ IdentityDictionary new.! ! !ClassBuilder methodsFor: 'class definition' stamp: 'NS 1/21/2004 09:20'! class: oldClass instanceVariableNames: instVarString unsafe: unsafe "This is the basic initialization message to change the definition of an existing Metaclass" | instVars newClass needNew copyOfOldClass | environ _ oldClass environment. instVars _ Scanner new scanFieldNames: instVarString. unsafe ifFalse:[ "Run validation checks so we know that we have a good chance for recompilation" (self validateInstvars: instVars from: oldClass forSuper: oldClass superclass) ifFalse:[^nil]. (self validateSubclassFormat: oldClass typeOfClass from: oldClass forSuper: oldClass superclass extra: instVars size) ifFalse:[^nil]]. "See if we need a new subclass or not" needNew _ self needsSubclassOf: oldClass superclass type: oldClass typeOfClass instanceVariables: instVars from: oldClass. needNew ifNil:[^nil]. "some error" needNew ifFalse:[^oldClass]. "no new class needed" "Create the new class" copyOfOldClass _ oldClass copy. newClass _ self newSubclassOf: oldClass superclass type: oldClass typeOfClass instanceVariables: instVars from: oldClass. newClass _ self recompile: false from: oldClass to: newClass mutate: false. self doneCompiling: newClass. SystemChangeNotifier uniqueInstance classDefinitionChangedFrom: copyOfOldClass to: newClass. ^newClass! ! !ClassBuilder methodsFor: 'class definition' stamp: 'ar 8/29/1999 15:34'! name: className inEnvironment: env subclassOf: newSuper type: type instanceVariableNames: instVarString classVariableNames: classVarString poolDictionaries: poolString category: category "Define a new class in the given environment" ^self name: className inEnvironment: env subclassOf: newSuper type: type instanceVariableNames: instVarString classVariableNames: classVarString poolDictionaries: poolString category: category unsafe: false! ! !ClassBuilder methodsFor: 'class definition' stamp: 'NS 1/20/2004 19:46'! name: className inEnvironment: env subclassOf: newSuper type: type instanceVariableNames: instVarString classVariableNames: classVarString poolDictionaries: poolString category: category unsafe: unsafe "Define a new class in the given environment. If unsafe is true do not run any validation checks. This facility is provided to implement important system changes." | oldClass newClass organization instVars classVars force needNew oldCategory copyOfOldClass newCategory | environ _ env. instVars _ Scanner new scanFieldNames: instVarString. classVars _ (Scanner new scanFieldNames: classVarString) collect: [:x | x asSymbol]. "Validate the proposed name" unsafe ifFalse:[(self validateClassName: className) ifFalse:[^nil]]. oldClass _ env at: className ifAbsent:[nil]. oldClass isBehavior ifFalse:[oldClass _ nil]. "Already checked in #validateClassName:" copyOfOldClass _ oldClass copy. unsafe ifFalse:[ "Run validation checks so we know that we have a good chance for recompilation" (self validateSuperclass: newSuper forSubclass: oldClass) ifFalse:[^nil]. (self validateInstvars: instVars from: oldClass forSuper: newSuper) ifFalse:[^nil]. (self validateClassvars: classVars from: oldClass forSuper: newSuper) ifFalse:[^nil]. (self validateSubclassFormat: type from: oldClass forSuper: newSuper extra: instVars size) ifFalse:[^nil]]. "See if we need a new subclass" needNew _ self needsSubclassOf: newSuper type: type instanceVariables: instVars from: oldClass. needNew == nil ifTrue:[^nil]. "some error" (needNew and:[unsafe not]) ifTrue:[ "Make sure we don't redefine any dangerous classes" (self tooDangerousClasses includes: oldClass name) ifTrue:[ self error: oldClass name, ' cannot be changed'. ]. "Check if the receiver should not be redefined" (oldClass ~~ nil and:[oldClass shouldNotBeRedefined]) ifTrue:[ self notify: oldClass name asText allBold, ' should not be redefined!! \Proceed to store over it.' withCRs]]. needNew ifTrue:[ "Create the new class" newClass _ self newSubclassOf: newSuper type: type instanceVariables: instVars from: oldClass. newClass == nil ifTrue:[^nil]. "Some error" newClass setName: className. ] ifFalse:[ "Reuse the old class" newClass _ oldClass. ]. "Install the class variables and pool dictionaries... " force _ (newClass declare: classVarString) | (newClass sharing: poolString). "... classify ..." newCategory _ category asSymbol. organization _ environ ifNotNil:[environ organization]. oldClass isNil ifFalse: [oldCategory := (organization categoryOfElement: oldClass name) asSymbol]. organization classify: newClass name under: newCategory. newClass environment: environ. "... recompile ..." newClass _ self recompile: force from: oldClass to: newClass mutate: false. "... export if not yet done ..." (environ at: newClass name ifAbsent:[nil]) == newClass ifFalse:[ [environ at: newClass name put: newClass] on: AttemptToWriteReadOnlyGlobal do:[:ex| ex resume: true]. Smalltalk flushClassNameCache. ]. self doneCompiling: newClass. "... notify interested clients ..." oldClass isNil ifTrue: [ SystemChangeNotifier uniqueInstance classAdded: newClass inCategory: newCategory. ^ newClass]. SystemChangeNotifier uniqueInstance classDefinitionChangedFrom: copyOfOldClass to: newClass. newCategory ~= oldCategory ifTrue: [SystemChangeNotifier uniqueInstance class: newClass recategorizedFrom: oldCategory to: category]. ^newClass! ! !ClassBuilder methodsFor: 'class definition' stamp: 'ar 9/22/2002 02:57'! needsSubclassOf: newSuper type: type instanceVariables: instVars from: oldClass "Answer whether we need a new subclass to conform to the requested changes" | newFormat | "Compute the format of the new class" newFormat _ self computeFormat: type instSize: instVars size forSuper: newSuper ccIndex: (oldClass ifNil:[0] ifNotNil:[oldClass indexIfCompact]). newFormat == nil ifTrue:[^nil]. "Check if we really need a new subclass" oldClass ifNil:[^true]. "yes, it's a new class" newSuper == oldClass superclass ifFalse:[^true]. "yes, it's a superclass change" newFormat = oldClass format ifFalse:[^true]. "yes, it's a format change" instVars = oldClass instVarNames ifFalse:[^true]. "yes, it's an iVar change" ^false ! ! !ClassBuilder methodsFor: 'class definition' stamp: 'ar 2/27/2003 22:56'! newSubclassOf: newSuper type: type instanceVariables: instVars from: oldClass "Create a new subclass of the given superclass with the given specification." | newFormat newClass | "Compute the format of the new class" newFormat _ self computeFormat: type instSize: instVars size forSuper: newSuper ccIndex: (oldClass ifNil:[0] ifNotNil:[oldClass indexIfCompact]). newFormat == nil ifTrue:[^nil]. (oldClass == nil or:[oldClass isMeta not]) ifTrue:[newClass _ self privateNewSubclassOf: newSuper from: oldClass] ifFalse:[newClass _ oldClass clone]. newClass superclass: newSuper methodDictionary: MethodDictionary new format: newFormat; setInstVarNames: instVars. oldClass ifNotNil:[ newClass organization: oldClass organization. "Recompile the new class" oldClass hasMethods ifTrue:[newClass compileAllFrom: oldClass]. self recordClass: oldClass replacedBy: newClass. ]. (oldClass == nil or:[oldClass isObsolete not]) ifTrue:[newSuper addSubclass: newClass] ifFalse:[newSuper addObsoleteSubclass: newClass]. ^newClass! ! !ClassBuilder methodsFor: 'class definition' stamp: 'NS 1/21/2004 09:53'! recompile: force from: oldClass to: newClass mutate: forceMutation "Do the necessary recompilation after changine oldClass to newClass. If required (e.g., when oldClass ~~ newClass) mutate oldClass to newClass and all its subclasses. If forceMutation is true force a mutation even if oldClass and newClass are the same." oldClass == nil ifTrue:[^ newClass]. (newClass == oldClass and:[force not and:[forceMutation not]]) ifTrue:[ ^newClass]. currentClassIndex _ 0. maxClassIndex _ oldClass withAllSubclasses size. (oldClass == newClass and:[forceMutation not]) ifTrue:[ "Recompile from newClass without mutating" self informUserDuring:[ newClass isSystemDefined ifFalse:[progress _ nil]. newClass withAllSubclassesDo:[:cl| self showProgressFor: cl. cl compileAll]]. ^newClass]. "Recompile and mutate oldClass to newClass" self informUserDuring:[ newClass isSystemDefined ifFalse:[progress _ nil]. self mutate: oldClass to: newClass. ]. ^oldClass "now mutated to newClass"! ! !ClassBuilder methodsFor: 'class format' stamp: 'ar 9/10/1999 12:55'! computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. Return the format or nil if there is any problem." | instSize isVar isWords isPointers isWeak | instSize _ newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). instSize > 254 ifTrue:[ self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #compiledMethod ifTrue:[^CompiledMethod instSpec]. type == #normal ifTrue:[isVar _ isWeak _ false. isWords _ isPointers _ true]. type == #bytes ifTrue:[isVar _ true. isWords _ isPointers _ isWeak _ false]. type == #words ifTrue:[isVar _ isWords _ true. isPointers _ isWeak _ false]. type == #variable ifTrue:[isVar _ isPointers _ isWords _ true. isWeak _ false]. type == #weak ifTrue:[isVar _ isWeak _ isWords _ isPointers _ true]. (isPointers not and:[instSize > 0]) ifTrue:[ self error:'A non-pointer class cannot have instance variables'. ^nil]. ^(self format: instSize variable: isVar words: isWords pointers: isPointers weak: isWeak) + (ccIndex bitShift: 11).! ! !ClassBuilder methodsFor: 'class format' stamp: 'ar 7/11/1999 06:39'! format: nInstVars variable: isVar words: isWords pointers: isPointers weak: isWeak "Compute the format for the given instance specfication." | cClass instSpec sizeHiBits fmt | self flag: #instSizeChange. " Smalltalk browseAllCallsOn: #instSizeChange. Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. " " NOTE: This code supports the backward-compatible extension to 8 bits of instSize. For now the format word is... <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> But when we revise the image format, it should become... <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> " sizeHiBits _ (nInstVars+1) // 64. cClass _ 0. "for now" instSpec _ isWeak ifTrue:[4] ifFalse:[isPointers ifTrue: [isVar ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] ifFalse: [isWords ifTrue: [6] ifFalse: [8]]]. fmt _ sizeHiBits. fmt _ (fmt bitShift: 5) + cClass. fmt _ (fmt bitShift: 4) + instSpec. fmt _ (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" fmt _ (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" ^fmt! ! !ClassBuilder methodsFor: 'validation' stamp: 'ar 7/13/1999 05:26'! validateClassName: aString "Validate the new class name" aString first isUppercase ifFalse:[ self error: 'Class names must be capitalized'. ^false]. environ at: aString ifPresent:[:old| (old isKindOf: Behavior) ifFalse:[ self notify: aString asText allBold, ' already exists!!\Proceed will store over it.' withCRs]]. ^true! ! !ClassBuilder methodsFor: 'validation' stamp: 'ar 7/15/1999 13:48'! validateClassvars: classVarArray from: oldClass forSuper: newSuper "Check if any of the classVars of oldClass conflict with the new superclass" | usedNames classVars temp | classVarArray isEmpty ifTrue:[^true]. "Okay" "Validate the class var names" usedNames _ classVarArray asSet. usedNames size = classVarArray size ifFalse:[ classVarArray do:[:var| usedNames remove: var ifAbsent:[temp _ var]]. self error: temp,' is multiply defined'. ^false]. (usedNames includesAnyOf: self reservedNames) ifTrue:[ self reservedNames do:[:var| (usedNames includes: var) ifTrue:[temp _ var]]. self error: temp,' is a reserved name'. ^false]. newSuper == nil ifFalse:[ usedNames _ newSuper allClassVarNames asSet. classVarArray do:[:iv| (usedNames includes: iv) ifTrue:[ newSuper withAllSuperclassesDo:[:cl| (cl classVarNames includes: iv) ifTrue:[temp _ cl]]. self error: iv, ' is already defined in ', temp name. ^false]]]. oldClass == nil ifFalse:[ usedNames _ Set new: 20. oldClass allSubclassesDo:[:cl| usedNames addAll: cl classVarNames]. classVars _ classVarArray. newSuper == nil ifFalse:[classVars _ classVars, newSuper allClassVarNames asArray]. classVars do:[:iv| (usedNames includes: iv) ifTrue:[ self error: iv, ' is already defined in a subclass of ', oldClass name. ^false]]]. ^true! ! !ClassBuilder methodsFor: 'validation' stamp: 'ajh 10/17/2002 11:10'! validateInstvars: instVarArray from: oldClass forSuper: newSuper "Check if any of the instVars of oldClass conflict with the new superclass" | instVars usedNames temp | instVarArray isEmpty ifTrue:[^true]. "Okay" newSuper allowsSubInstVars ifFalse: [ self error: newSuper printString, ' does not allow subclass inst vars. See allowsSubInstVars.'. ^ false]. "Validate the inst var names" usedNames _ instVarArray asSet. usedNames size = instVarArray size ifFalse:[ instVarArray do:[:var| usedNames remove: var ifAbsent:[temp _ var]]. self error: temp,' is multiply defined'. ^false]. (usedNames includesAnyOf: self reservedNames) ifTrue:[ self reservedNames do:[:var| (usedNames includes: var) ifTrue:[temp _ var]]. self error: temp,' is a reserved name'. ^false]. newSuper == nil ifFalse:[ usedNames _ newSuper allInstVarNames asSet. instVarArray do:[:iv| (usedNames includes: iv) ifTrue:[ newSuper withAllSuperclassesDo:[:cl| (cl instVarNames includes: iv) ifTrue:[temp _ cl]]. self error: iv,' is already defined in ', temp name. ^false]]]. oldClass == nil ifFalse:[ usedNames _ Set new: 20. oldClass allSubclassesDo:[:cl| usedNames addAll: cl instVarNames]. instVars _ instVarArray. newSuper == nil ifFalse:[instVars _ instVars, newSuper allInstVarNames]. instVars do:[:iv| (usedNames includes: iv) ifTrue:[ self error: iv, ' is already defined in a subclass of ', oldClass name. ^false]]]. ^true! ! !ClassBuilder methodsFor: 'validation' stamp: 'bkv 4/2/2003 17:13'! validateSubclass: subclass canKeepLayoutFrom: oldClass forSubclassFormat: newType "Returns whether the immediate subclasses of oldClass can keep its layout" "Note: Squeak does not appear to model classFormat relationships.. so I'm putting some logic here. bkv 4/2/2003" "isWeak implies isVariant" (oldClass isVariable and: [ subclass isWeak ]) ifFalse: [ "In general we discourage format mis-matches" (subclass typeOfClass == newType) ifFalse: [ self error: subclass name,' cannot be recompiled'. ^ false ]]. ^ true! ! !ClassBuilder methodsFor: 'validation' stamp: 'BG 1/5/2004 20:29'! validateSubclassFormat: newType from: oldClass forSuper: newSuper extra: newInstSize "Validate the # of instVars and the format of the subclasses" | deltaSize | oldClass == nil ifTrue: [^ true]. "No subclasses" "Compute the # of instvars needed for all subclasses" deltaSize _ newInstSize. (oldClass notNil) ifTrue: [deltaSize _ deltaSize - oldClass instVarNames size]. (newSuper notNil) ifTrue: [deltaSize _ deltaSize + newSuper instSize]. (oldClass notNil and: [oldClass superclass notNil]) ifTrue: [deltaSize _ deltaSize - oldClass superclass instSize]. (oldClass == nil) ifTrue: [ (deltaSize > 254) ifTrue: [ self error: 'More than 254 instance variables'. ^ false]. ^ true]. oldClass withAllSubclassesDo: [:sub | ( sub instSize + deltaSize > 254 ) ifTrue: [ self error: sub name,' has more than 254 instance variables'. ^ false] ]. newType ~~ #normal ifTrue: ["And check if the immediate subclasses of oldClass can keep its layout" oldClass subclassesDo: [:sub | self validateSubclass: sub canKeepLayoutFrom: oldClass forSubclassFormat: newType] ]. ^ true! ! !ClassBuilder methodsFor: 'validation' stamp: 'ar 7/15/1999 13:50'! validateSuperclass: aSuperClass forSubclass: aClass "Check if it is okay to use aSuperClass as the superclass of aClass" aClass == nil ifTrue:["New class" (aSuperClass == nil or:[aSuperClass isBehavior and:[aSuperClass isMeta not]]) ifFalse:[self error: aSuperClass name,' is not a valid superclass'. ^false]. ^true]. aSuperClass == aClass superclass ifTrue:[^true]. "No change" (aClass isMeta) "Not permitted - meta class hierarchy is derived from class hierarchy" ifTrue:[^self error: aClass name, ' must inherit from ', aClass superclass name]. "Check for circular references" (aSuperClass ~~ nil and:[aSuperClass == aClass or:[aSuperClass inheritsFrom: aClass]]) ifTrue:[self error: aSuperClass name,' inherits from ', aClass name. ^false]. ^true! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 8/29/1999 13:03'! informUserDuring: aBlock self class isSilent ifTrue:[^aBlock value]. Utilities informUserDuring:[:bar| progress _ bar. aBlock value]. progress _ nil.! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 2/27/2003 22:56'! privateNewSubclassOf: newSuper "Create a new meta and non-meta subclass of newSuper" "WARNING: This method does not preserve the superclass/subclass invariant!!" | newSuperMeta newMeta | newSuperMeta _ newSuper ifNil:[Class] ifNotNil:[newSuper class]. newMeta _ Metaclass new. newMeta superclass: newSuperMeta methodDictionary: MethodDictionary new format: newSuperMeta format. ^newMeta new ! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 2/27/2003 22:56'! privateNewSubclassOf: newSuper from: oldClass "Create a new meta and non-meta subclass of newSuper using oldClass as template" "WARNING: This method does not preserve the superclass/subclass invariant!!" | newSuperMeta oldMeta newMeta | oldClass ifNil:[^self privateNewSubclassOf: newSuper]. newSuperMeta _ newSuper ifNil:[Class] ifNotNil:[newSuper class]. oldMeta _ oldClass class. newMeta _ oldMeta clone. newMeta superclass: newSuperMeta methodDictionary: MethodDictionary new format: (self computeFormat: oldMeta typeOfClass instSize: oldMeta instVarNames size forSuper: newSuperMeta ccIndex: 0); setInstVarNames: oldMeta instVarNames; organization: oldMeta organization. "Recompile the meta class" oldMeta hasMethods ifTrue:[newMeta compileAllFrom: oldMeta]. "Record the meta class change" self recordClass: oldMeta replacedBy: newMeta. "And create a new instance" ^newMeta adoptInstance: oldClass from: oldMeta! ! !ClassBuilder methodsFor: 'private' stamp: 'NS 1/27/2004 14:21'! recordClass: oldClass replacedBy: newClass "Keep the changes up to date when we're moving instVars around" (instVarMap includesKey: oldClass name) ifTrue:[ SystemChangeNotifier uniqueInstance classDefinitionChangedFrom: oldClass to: newClass. ].! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 7/15/1999 13:39'! reservedNames "Return a list of names that must not be used for variables" ^#('self' 'super' 'thisContext' 'true' 'false' 'nil' self super thisContext true false nil).! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 3/5/2001 12:00'! showProgressFor: aClass "Announce that we're processing aClass" progress == nil ifTrue:[^self]. aClass isObsolete ifTrue:[^self]. currentClassIndex _ currentClassIndex + 1. (aClass hasMethods and: [aClass wantsRecompilationProgressReported]) ifTrue: [progress value: ('Recompiling ', aClass name,' (', currentClassIndex printString,'/', maxClassIndex printString,')')]! ! !ClassBuilder methodsFor: 'private' stamp: 'ar 8/29/1999 15:43'! tooDangerousClasses "Return a list of class names which will not be modified in the public interface" ^#( "Object will break immediately" Object "Contexts and their superclasses" InstructionStream ContextPart BlockContext MethodContext "Superclasses of basic collections" Collection SequenceableCollection ArrayedCollection "Collections known to the VM" Array Bitmap String Symbol ByteArray CompiledMethod TranslatedMethod "Basic Numbers" Magnitude Number SmallInteger Float "Misc other" LookupKey Association Link Point Rectangle Behavior PositionableStream UndefinedObject ) ! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 8/29/1999 15:38'! class: oldClass instanceVariableNames: instVarString "This is the basic initialization message to change the definition of an existing Metaclass" oldClass isMeta ifFalse:[^self error: oldClass name, 'is not a Metaclass']. ^self class: oldClass instanceVariableNames: instVarString unsafe: false! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 7/19/1999 23:29'! superclass: newSuper subclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class." ^self name: t inEnvironment: newSuper environment subclassOf: newSuper type: newSuper typeOfClass instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 7/19/1999 23:29'! superclass: aClass variableByteSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class in which the subclass is to have indexable byte-sized nonpointer variables." (aClass instSize > 0) ifTrue: [^self error: 'cannot make a byte subclass of a class with named fields']. (aClass isVariable and: [aClass isWords]) ifTrue: [^self error: 'cannot make a byte subclass of a class with word fields']. (aClass isVariable and: [aClass isPointers]) ifTrue: [^self error: 'cannot make a byte subclass of a class with pointer fields']. ^self name: t inEnvironment: aClass environment subclassOf: aClass type: #bytes instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 7/19/1999 23:29'! superclass: aClass variableSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class in which the subclass is to have indexable pointer variables." aClass isBits ifTrue: [^self error: 'cannot make a pointer subclass of a class with non-pointer fields']. ^self name: t inEnvironment: aClass environment subclassOf: aClass type: #variable instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 7/19/1999 23:30'! superclass: aClass variableWordSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class in which the subclass is to have indexable word-sized nonpointer variables." (aClass instSize > 0) ifTrue: [^self error: 'cannot make a word subclass of a class with named fields']. (aClass isVariable and: [aClass isBytes]) ifTrue: [^self error: 'cannot make a word subclass of a class with byte fields']. (aClass isVariable and: [aClass isPointers]) ifTrue: [^self error: 'cannot make a word subclass of a class with pointer fields']. ^self name: t inEnvironment: aClass environment subclassOf: aClass type: #words instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !ClassBuilder methodsFor: 'public' stamp: 'ar 7/19/1999 23:30'! superclass: aClass weakSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have weak indexable pointer variables." aClass isBits ifTrue: [^self error: 'cannot make a pointer subclass of a class with non-pointer fields']. ^self name: t inEnvironment: aClass environment subclassOf: aClass type: #weak instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !ClassBuilder methodsFor: 'class mutation' stamp: 'ar 2/27/2003 22:44'! mutate: oldClass to: newClass "Mutate the old class and subclasses into newClass and subclasses. Note: This method is slightly different from: #mutate:toSuper: since here we are at the root of reshaping and have two distinct roots." | newSubclass | self showProgressFor: oldClass. "Convert the subclasses" oldClass subclasses do:[:oldSubclass| newSubclass _ self reshapeClass: oldSubclass toSuper: newClass. self mutate: oldSubclass to: newSubclass. ]. "And any obsolete ones" oldClass obsoleteSubclasses do:[:oldSubclass| oldSubclass ifNotNil:[ newSubclass _ self reshapeClass: oldSubclass toSuper: newClass. self mutate: oldSubclass to: newSubclass. ]. ]. self update: oldClass to: newClass. ^newClass! ! !ClassBuilder methodsFor: 'class mutation' stamp: 'ar 9/22/2002 03:16'! reshapeClass: oldClass toSuper: newSuper "Reshape the given class to the new super class. Recompile all the methods in the newly created class. Answer the new class." | instVars | "ar 9/22/2002: The following is a left-over from some older code. I do *not* know why we uncompact oldClass here. If you do, then please let me know so I can put a comment here..." oldClass becomeUncompact. instVars _ instVarMap at: oldClass name ifAbsent:[oldClass instVarNames]. ^self newSubclassOf: newSuper type: oldClass typeOfClass instanceVariables: instVars from: oldClass! ! !ClassBuilder methodsFor: 'class mutation' stamp: 'ar 2/27/2003 23:42'! update: oldClass to: newClass "Convert oldClass, all its instances and possibly its meta class into newClass, instances of newClass and possibly its meta class. The process is surprisingly simple in its implementation and surprisingly complex in its nuances and potentially bad side effects. We can rely on two assumptions (which are critical): #1: The method #updateInstancesFrom: will not create any lasting pointers to 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do a become of the old vs. the new instances and therefore it will not create pointers to *new* instances before the #become: which are *old* afterwards) #2: The non-preemptive execution of the critical piece of code guarantees that nobody can get a hold by 'other means' (such as process interruption and reflection) on the old instances. Given the above two, we know that after #updateInstancesFrom: there are no pointer to any old instances. After the forwarding become there will be no pointers to the old class or meta class either. Meaning that if we throw in a nice fat GC at the end of the critical block, everything will be gone (but see the comment right there). There's no need to worry. " | meta | meta _ oldClass isMeta. "Note: Everything from here on will run without the ability to get interrupted to prevent any other process to create new instances of the old class." [ "Note: The following removal may look somewhat obscure and needs an explanation. When we mutate the class hierarchy we create new classes for any existing subclass. So it may look as if we don't have to remove the old class from its superclass. However, at the top of the hierarchy (the first class we reshape) that superclass itself is not newly created so therefore it will hold both the oldClass and newClass in its (obsolete or not) subclasses. Since the #become: below will transparently replace the pointers to oldClass with newClass the superclass would have newClass in its subclasses TWICE. With rather unclear effects if we consider that we may convert the meta-class hierarchy itself (which is derived from the non-meta class hierarchy). Due to this problem ALL classes are removed from their superclass just prior to converting them. Here, breaking the superclass/subclass invariant really doesn't matter since we will effectively remove the oldClass (become+GC) just a few lines below." oldClass superclass removeSubclass: oldClass. oldClass superclass removeObsoleteSubclass: oldClass. "Convert the instances of oldClass into instances of newClass" newClass updateInstancesFrom: oldClass. meta ifTrue:[oldClass becomeForward: newClass] ifFalse:[(Array with: oldClass with: oldClass class) elementsForwardIdentityTo: (Array with: newClass with: newClass class)]. Smalltalk garbageCollect. "Warning: Read this before you even think about removing the GC. Yes, it slows us down. Quite heavily if you have a large image. However, there's no good and simple alternative here, since unfortunately, #become: does change class pointers. What happens is that after the above become all of the instances of the old class will have a class pointer identifying them as instances of newClass. If we get our hands on any of these instances we will break immediately since their expected instance layout (that of its class, e.g., newClass) will not match their actual instance layout (that of oldClass). And getting your hands on any of those instances is really simple - just reshaping one class two times in rapid succession will do it. Reflection techniques, interrupts, etc. will only add to this problem. In the case of Metaclass things get even worse since when we recompile the entire class hierarchy we will recompile both, Metaclass and its instances (and some of its instances will have the old and some the new layout). The only easy solution to this problem would be to 'fix up' the class pointers of the old instances to point to the old class (using primitiveChangeClassTo:). But this won't work either - as we do a one-way become we would have to search the entire object memory for the oldClass and couldn't even clearly identify it unless we give it some 'special token' which sounds quite error-prone. If you really need to get rid of the GC here are some alternatives: On the image level, one could create a copy of the oldClass before becoming it into the new class and, after becoming it, 'fix up' the old instances. That would certainly work but it sounds quite complex, as we need to make sure we're not breaking any of the superclass/subclass meta/non-meta class variants. Alternatively, fix up #becomeForward on the VM-level to 'dump the source objects' of #become. This would be quite doable (just 'convert' them into a well known special class such as bitmap) yet it has problems if (accidentally or not) one of the objects in #become: appears on 'both sides of the fence' (right now, this will work ... in a way ... even though the consequences are unclear). Another alternative is to provide a dedicated primitive for this (instead of using it implicitly in become) which would allow us to dump all the existing instances right here. This is equivalent to a more general primitiveChangeClassTo: and might be worthwhile but it would likely have to keep in mind the differences between bits and pointer thingies etc. Since all of the alternatives seem rather complex and magical compared to a straight-forward GC it seems best to stick with the GC solution for now. If someone has a real need to fix this problem, that person will likely be motivated enough to check out the alternatives. Personally I'd probably go for #1 (copy the old class and remap the instances to it) since it's a solution that could be easily reverted from within the image if there's any problem with it." ] valueUnpreemptively. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ClassBuilder class instanceVariableNames: ''! !ClassBuilder class methodsFor: 'accessing' stamp: 'ar 7/15/1999 18:48'! isSilent ^QuietMode == true! ! Object subclass: #ClassCategoryReader instanceVariableNames: 'class category changeStamp' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !ClassCategoryReader commentStamp: '<historical>' prior: 0! I represent a mechanism for retrieving class descriptions stored on a file.! !ClassCategoryReader methodsFor: 'fileIn/Out' stamp: 'tk 12/15/97 16:26'! scanFrom: aStream "File in methods from the stream, aStream." | methodText | [methodText _ aStream nextChunkText. methodText size > 0] whileTrue: [class compile: methodText classified: category withStamp: changeStamp notifying: (SyntaxError new category: category)]! ! !ClassCategoryReader methodsFor: 'private' stamp: '6/5/97 di'! setClass: aClass category: aCategory ^ self setClass: aClass category: aCategory changeStamp: String new ! ! !ClassCategoryReader methodsFor: 'private' stamp: '6/5/97 di'! setClass: aClass category: aCategory changeStamp: aString class _ aClass. category _ aCategory. changeStamp _ aString ! ! !ClassCategoryReader methodsFor: 'private' stamp: 'ajh 1/18/2002 01:14'! theClass ^ class! ! Object subclass: #ClassChangeRecord instanceVariableNames: 'inForce revertable changeTypes thisDefinition priorDefinition thisName priorName thisOrganization priorOrganization thisComment priorComment thisMD priorMD methodChanges' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ClassChangeRecord commentStamp: '<historical>' prior: 0! A ClassChangeRecorder keeps track of most substantive changes premissible in a project, isolated or not. Structure: inForce a boolean Tells whether these changes are in effect. true for all changeSets in and above the current project. It should be sufficient only to record this for the changeSet as a whole, but this redundancy could help in error recovery. classIsLocal a boolean True if and only if this class is defined in this layer of the project structure. changeTypes an identitySet Summarizes which changes have been made in this class. Values include #comment, #reorganize, #rename, and the four more summarized below. thisName a string Retains the class name for this layer. priorName a string Preserves the prior name. thisComment a text Retains the class comment for this layer. priorComment a text Preserves the prior comment. thisOrganization a classOrganizer Retains the class organization for this layer. priorOrganization a classOrganizer Preserves the prior organization. thisMD a methodDictionary Used to prepare changes for nearly atomic invocation of this layer (see below). priorMD a methodDictionary Preserves the state of an altered class as it exists in the next outer layer of the project structure. methodChanges a dictionary of classChangeRecords Retains all the method changes for this layer. Four of the possible changeTypes are maintained in a mutually exclusive set, analogously to MethodChangeRecords. Here is a simple summary of the relationship between these four changeType symbols and the recording of prior state | prior == nil | prior not nil --------- |---------------------------- |-------------------- add | add | change --------- |---------------------------- |-------------------- remove | addedThenRemoved | remove A classChangeRecorder is notified of changes by the method noteMethodChange: <ClassChangeRecord>. ClassChangeRecorders are designed to invoke a set of changes relative to the definition of a class in an prior layer. It is important that both invocation and revocation of these changes take place in a nearly atomic fashion so that interdependent changes will be adopted as a whole, and so that only one flush of the method cache should be necessary. A further reason for revocation to be simple is that it may be requested as an attempt to recover from an error in a project that is failing.! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 4/2/2000 21:39'! allChangeTypes | chgs | (priorName ~~ nil and: [changeTypes includes: #rename]) ifTrue: [(chgs _ changeTypes copy) add: 'oldName: ' , priorName. ^ chgs]. ^ changeTypes! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 4/2/2000 21:59'! assimilateAllChangesIn: otherRecord | selector changeRecord changeType | otherRecord isClassRemoval ifTrue: [^ self noteChangeType: #remove]. otherRecord allChangeTypes do: [:chg | self noteChangeType: chg fromClass: self realClass]. otherRecord methodChanges associationsDo: [:assn | selector _ assn key. changeRecord _ assn value. changeType _ changeRecord changeType. (changeType == #remove or: [changeType == #addedThenRemoved]) ifTrue: [changeType == #addedThenRemoved ifTrue: [self atSelector: selector put: #add]. self noteRemoveSelector: selector priorMethod: nil lastMethodInfo: changeRecord methodInfoFromRemoval] ifFalse: [self atSelector: selector put: changeType]]. ! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 3/28/2000 10:59'! hasNoChanges ^ changeTypes isEmpty and: [methodChanges isEmpty]! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 3/24/2000 09:36'! includesChangeType: changeType changeType == #new ifTrue: [^ changeTypes includes: #add]. "Backwd compat" ^ changeTypes includes: changeType! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 3/28/2000 15:14'! noteChangeType: changeSymbol ^ self noteChangeType: changeSymbol fromClass: nil! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'sw 4/3/2001 14:16'! noteChangeType: changeSymbol fromClass: class (changeSymbol = #new or: [changeSymbol = #add]) ifTrue: [changeTypes add: #add. changeTypes remove: #change ifAbsent: []. revertable _ false. ^ self]. changeSymbol = #change ifTrue: [(changeTypes includes: #add) ifTrue: [^ self]. ^ changeTypes add: changeSymbol]. changeSymbol == #addedThenRemoved ifTrue: [^ self]. "An entire class was added but then removed" changeSymbol = #comment ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #reorganize ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #rename ifTrue: [^ changeTypes add: changeSymbol]. (changeSymbol beginsWith: 'oldName: ') ifTrue: ["Must only be used when assimilating other changeSets" (changeTypes includes: #add) ifTrue: [^ self]. priorName _ changeSymbol copyFrom: 'oldName: ' size + 1 to: changeSymbol size. ^ changeTypes add: #rename]. changeSymbol = #remove ifTrue: [(changeTypes includes: #add) ifTrue: [changeTypes add: #addedThenRemoved] ifFalse: [changeTypes add: #remove]. ^ changeTypes removeAllFoundIn: #(add change comment reorganize)]. self error: 'Unrecognized changeType'! ! !ClassChangeRecord methodsFor: 'all changes' stamp: 'di 5/16/2000 08:43'! trimHistory "Drop non-essential history." "Forget methods added and later removed" methodChanges keysAndValuesRemove: [:sel :chgRecord | chgRecord changeType == #addedThenRemoved]. "Forget renaming and reorganization of newly-added classes." (changeTypes includes: #add) ifTrue: [changeTypes removeAllFoundIn: #(rename reorganize)]. ! ! !ClassChangeRecord methodsFor: 'isolation layers' stamp: 'di 3/29/2000 22:00'! invokePhase1 | selector changeRecord type elements | revertable ifFalse: [^ self]. inForce ifTrue: [self error: 'Can invoke only when not in force.']. "Do the first part of the invoke operation -- no particular hurry." "Save the outer method dictionary for quick revert of method changes." priorMD _ self realClass methodDict. "Prepare a methodDictionary for switcheroo." thisMD _ self realClass methodDict copy. methodChanges associationsDo: [:assn | selector _ assn key. changeRecord _ assn value. type _ changeRecord changeType. type = #remove ifTrue: [thisMD removeKey: selector]. type = #add ifTrue: [thisMD at: selector put: changeRecord currentMethod]. type = #change ifTrue: [thisMD at: selector put: changeRecord currentMethod]. ]. "Replace the original organization (and comment)." priorOrganization _ self realClass organization. thisOrganization elementArray copy do: [:sel | (thisMD includesKey: sel) ifFalse: [thisOrganization removeElement: sel]]. #(DoIt DoItIn:) do: [:sel | thisMD removeKey: sel ifAbsent: []]. thisOrganization elementArray size = thisMD size ifFalse: [elements _ thisOrganization elementArray asSet. thisMD keysDo: [:sel | (elements includes: sel) ifFalse: [thisOrganization classify: sel under: (priorOrganization categoryOfElement: sel)]]]. self realClass organization: thisOrganization. ! ! !ClassChangeRecord methodsFor: 'isolation layers' stamp: 'di 3/29/2000 14:50'! invokePhase2 revertable ifFalse: [^ self]. "Do the second part of the revert operation. This must be very simple." "Replace original method dicts if there are method changes." self realClass methodDictionary: thisMD. "zap. Must flush Cache in outer loop." inForce _ true. ! ! !ClassChangeRecord methodsFor: 'isolation layers' stamp: 'di 3/30/2000 18:03'! realClass "Return the actual class (or meta), as determined from my name." thisName ifNil: [^ nil]. (thisName endsWith: ' class') ifTrue: [^ (Smalltalk at: (thisName copyFrom: 1 to: thisName size - 6) asSymbol ifAbsent: [^ nil]) class] ifFalse: [^ Smalltalk at: thisName ifAbsent: [^ nil]]! ! !ClassChangeRecord methodsFor: 'isolation layers' stamp: 'di 3/29/2000 14:50'! revokePhase1 revertable ifFalse: [^ self]. inForce ifFalse: [self error: 'Can revoke only when in force.']. "Do the first part of the revoke operation. This must be very simple." "Replace original method dict if there are method changes." self realClass methodDictionary: priorMD "zap. Must flush Cache in outer loop."! ! !ClassChangeRecord methodsFor: 'isolation layers' stamp: 'di 3/29/2000 14:50'! revokePhase2 revertable ifFalse: [^ self]. "Replace the original organization (and comment)." thisOrganization _ self realClass organization. self realClass organization: priorOrganization. inForce _ false. ! ! !ClassChangeRecord methodsFor: 'definition' stamp: 'di 3/27/2000 22:06'! checkCoherence "If I recreate the class then don't remove it" (changeTypes includes: #remove) ifTrue: [changeTypes remove: #remove. changeTypes add: #change]. (changeTypes includes: #addedThenRemoved) ifTrue: [changeTypes remove: #addedThenRemoved. changeTypes add: #add]. ! ! !ClassChangeRecord methodsFor: 'definition' stamp: 'di 3/27/2000 22:08'! notePriorDefinition: oldClass oldClass ifNil: [^ self]. priorDefinition ifNil: [priorDefinition _ oldClass definition]! ! !ClassChangeRecord methodsFor: 'definition' stamp: 'di 3/28/2000 09:12'! priorDefinition ^ priorDefinition! ! !ClassChangeRecord methodsFor: 'rename' stamp: 'di 5/8/2000 20:39'! noteNewName: newName thisName _ newName! ! !ClassChangeRecord methodsFor: 'rename' stamp: 'di 3/24/2000 09:38'! priorName ^ priorName! ! !ClassChangeRecord methodsFor: 'rename' stamp: 'tk 6/8/2001 09:11'! thisName ^ thisName! ! !ClassChangeRecord methodsFor: 'removal' stamp: 'di 4/4/2000 12:49'! forgetChangesIn: otherRecord "See forgetAllChangesFoundIn:. Used in culling changeSets." | cls otherMethodChanges selector actionToSubtract | (cls _ self realClass) == nil ifTrue: [^ self]. "We can do better now, though..." otherMethodChanges _ otherRecord methodChangeTypes. otherMethodChanges associationsDo: [:assoc | selector _ assoc key. actionToSubtract _ assoc value. (cls includesSelector: selector) ifTrue: [(#(add change) includes: actionToSubtract) ifTrue: [methodChanges removeKey: selector ifAbsent: []]] ifFalse: [(#(remove addedThenRemoved) includes: actionToSubtract) ifTrue: [methodChanges removeKey: selector ifAbsent: []]]]. changeTypes isEmpty ifFalse: [changeTypes removeAllFoundIn: otherRecord allChangeTypes. (changeTypes includes: #rename) ifFalse: [changeTypes removeAllSuchThat: [:x | x beginsWith: 'oldName: ']]]! ! !ClassChangeRecord methodsFor: 'removal' stamp: 'di 4/1/2000 23:05'! isClassRemoval "NOTE: there are other removals with changeType #addedThenRemoved, but this message is used to write out removals in fileOut, and those cases should not be written out." ^ (changeTypes includes: #remove) or: [changeTypes includes: #removeClass]! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/28/2000 10:38'! atSelector: selector ifAbsent: absentBlock ^ (methodChanges at: selector ifAbsent: absentBlock) changeType! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/28/2000 11:01'! atSelector: selector put: changeType (self findOrMakeMethodChangeAt: selector priorMethod: nil) noteChangeType: changeType! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/28/2000 10:07'! changedSelectors "Return a set of the changed or removed selectors." ^ methodChanges keys! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 4/1/2000 10:45'! compileAll: newClass from: oldClass "Something about this class has changed. Locally retained methods must be recompiled. NOTE: You might think that if this changeSet is in force, then we can just note the new methods but a lower change set may override and be in force which would mean that only the overriding copies go recompiled. Just do it." | sel changeType changeRecord newMethod | methodChanges associationsDo: [:assn | sel _ assn key. changeRecord _ assn value. changeType _ changeRecord changeType. (changeType == #add or: [changeType == #change]) ifTrue: [newMethod _ newClass recompileNonResidentMethod: changeRecord currentMethod atSelector: sel from: oldClass. changeRecord noteNewMethod: newMethod]]! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/28/2000 11:01'! findOrMakeMethodChangeAt: selector priorMethod: priorMethod ^ methodChanges at: selector ifAbsent: [methodChanges at: selector put: (MethodChangeRecord new priorMethod: priorMethod)]! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/29/2000 16:26'! infoFromRemoval: selector ^ (methodChanges at: selector ifAbsent: [^ nil]) methodInfoFromRemoval ! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/24/2000 09:46'! methodChangeTypes "Return an old-style dictionary of method change types." | dict selector record | dict _ IdentityDictionary new. methodChanges associationsDo: [:assn | selector _ assn key. record _ assn value. dict at: selector put: record changeType]. ^ dict! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 4/1/2000 23:49'! methodChanges ^ methodChanges! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/28/2000 23:28'! noteNewMethod: newMethod selector: selector priorMethod: methodOrNil | methodChange | methodChange _ self findOrMakeMethodChangeAt: selector priorMethod: methodOrNil. methodOrNil == nil ifTrue: [methodChange noteChangeType: #add] ifFalse: [methodChange noteChangeType: #change]. methodChange noteNewMethod: newMethod. ! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'di 3/23/2000 23:00'! noteRemoveSelector: selector priorMethod: priorMethod lastMethodInfo: infoOrNil | methodChange | methodChange _ self findOrMakeMethodChangeAt: selector priorMethod: priorMethod. methodChange changeType == #add ifTrue: [methodChange noteChangeType: #addedThenRemoved] ifFalse: [methodChange noteChangeType: #remove]. infoOrNil ifNotNil: ["Save the source code pointer and category so can still browse old versions" methodChange noteMethodInfoFromRemoval: infoOrNil] ! ! !ClassChangeRecord methodsFor: 'method changes' stamp: 'sw 8/14/2002 11:11'! removeSelector: selector "Remove all memory of changes associated with the argument, selector, in this class." selector == #Comment ifTrue: [changeTypes remove: #comment ifAbsent: []] ifFalse: [methodChanges removeKey: selector ifAbsent: []]! ! !ClassChangeRecord methodsFor: 'initialization' stamp: 'di 4/5/2000 08:11'! initFor: className revertable: isRevertable inForce _ isRevertable. changeTypes _ IdentitySet new. methodChanges _ IdentityDictionary new. priorName _ thisName _ className. revertable _ isRevertable and: [self realClass notNil]. revertable ifTrue: [priorMD _ self realClass methodDict copy. priorOrganization _ self realClass organization deepCopy]. ! ! !ClassChangeRecord methodsFor: 'initialization' stamp: 'di 9/21/2000 12:34'! zapHistory "Drop all recorded information not needed to simply keep track of what has been changed. Saves a lot of space." methodChanges do: [:r | r noteNewMethod: nil]. "Drop all refes to old methods" thisOrganization _ nil. priorOrganization _ nil. thisComment _ nil. priorComment _ nil. thisMD _ nil. priorMD _ nil.! ! ClassCategoryReader subclass: #ClassCommentReader instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !ClassCommentReader methodsFor: 'as yet unclassified' stamp: 'sw 7/31/2002 10:40'! scanFrom: aStream "File in the class comment from aStream. Not string-i-fied, just a text, exactly as it is in the browser. Move to changes file." class theNonMetaClass classComment: (aStream nextChunkText) stamp: changeStamp "Writes it on the disk and saves a RemoteString ref"! ! VersionsBrowser subclass: #ClassCommentVersionsBrowser instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !ClassCommentVersionsBrowser commentStamp: 'asm 8/13/2002 23:20' prior: 0! A class-comment-versions-browser tool! !ClassCommentVersionsBrowser methodsFor: 'menu' stamp: 'asm 8/13/2002 21:33'! compareToCurrentVersion "If the current selection corresponds to a method in the system, then spawn a window showing the diffs as text" | change s1 s2 | listIndex = 0 ifTrue: [^ self]. change _ changeList at: listIndex. s1 _ classOfMethod organization classComment. s2 _ change string. s1 = s2 ifTrue: [^ self inform: 'Exact Match']. (StringHolder new textContents: (TextDiffBuilder buildDisplayPatchFrom: s1 to: s2 inClass: classOfMethod prettyDiffs: self showingPrettyDiffs)) openLabel: 'Comparison to Current Version'! ! !ClassCommentVersionsBrowser methodsFor: 'menu' stamp: 'sd 4/16/2003 08:52'! openSingleMessageBrowser | mr | "Create and schedule a message list browser populated only by the currently selected message" mr _ MethodReference new setStandardClass: self selectedClass methodSymbol: #Comment. self systemNavigation browseMessageList: (Array with: mr) name: mr asStringOrText autoSelect: nil! ! !ClassCommentVersionsBrowser methodsFor: 'menu' stamp: 'BG 10/28/2003 20:48'! versionsMenu: aMenu "Fill aMenu with menu items appropriate to the receiver" ^ aMenu addList: #( ('compare to current' compareToCurrentVersion 'compare selected version to the current version') ('revert to selected version' fileInSelections 'resubmit the selected version, so that it becomes the current version') ('remove from changes' removeMethodFromChanges 'remove this method from the current change set, if present') ('edit current method (O)' openSingleMessageBrowser 'open a single-message browser on the current version of this method') - ('toggle diffing (D)' toggleDiffing 'toggle whether or not diffs should be shown here') ('update list' reformulateList 'reformulate the list of versions, in case it somehow got out of synch with reality') - ('help...' offerVersionsHelp 'provide an explanation of the use of this tool')) ! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'asm 8/13/2002 22:26'! diffedVersionContents "Answer diffed version contents, maybe pretty maybe not" | change class earlier later | (listIndex = 0 or: [changeList size < listIndex]) ifTrue: [^ '']. change _ changeList at: listIndex. later _ change text. class _ self selectedClass. (listIndex == changeList size or: [class == nil]) ifTrue: [^ later]. earlier _ (changeList at: listIndex + 1) text. ^ TextDiffBuilder buildDisplayPatchFrom: earlier to: later inClass: class prettyDiffs: self showingPrettyDiffs! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'asm 8/13/2002 21:28'! reformulateList classOfMethod organization classComment ifNil: [^ self]. self scanVersionsOf: classOfMethod. self changed: #list. "for benefit of mvc" listIndex _ 1. self changed: #listIndex. self contentsChanged! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'asm 1/3/2003 16:06'! scanVersionsOf: class "Scan for all past versions of the class comment of the given class" | oldCommentRemoteStr sourceFilesCopy position prevPos stamp preamble tokens prevFileIndex | classOfMethod _ class. oldCommentRemoteStr _ class organization commentRemoteStr. currentCompiledMethod _ oldCommentRemoteStr. selectorOfMethod _ #Comment. changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. oldCommentRemoteStr ifNil:[^ nil] ifNotNil: [oldCommentRemoteStr sourcePointer]. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. position _ oldCommentRemoteStr position. file _ sourceFilesCopy at: oldCommentRemoteStr sourceFileNumber. [position notNil & file notNil] whileTrue: [file position: (0 max: position-150). " Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. prevPos _ nil. stamp _ ''. (preamble findString: 'commentStamp:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble. (tokens at: tokens size-3) = #commentStamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos]] ifFalse: ["The stamp get lost, maybe after a condenseChanges" stamp _ '<historical>']. self addItem: (ChangeRecord new file: file position: position type: #classComment class: class name category: nil meta: class stamp: stamp) text: stamp , ' ' , class name , ' class comment'. prevPos = 0 ifTrue:[prevPos _ nil]. position _ prevPos. prevPos notNil ifTrue:[file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'asm 8/13/2002 21:33'! updateListsAndCodeIn: aWindow | aComment | aComment _ classOfMethod organization commentRemoteStr. aComment == currentCompiledMethod ifFalse: ["Do not attempt to formulate if there is no source pointer. It probably means it has been recompiled, but the source hasn't been written (as during a display of the 'save text simply?' confirmation)." aComment last ~= 0 ifTrue: [self reformulateList]]. ^ true ! ! !ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'sw 8/17/2002 21:57'! classCommentIndicated "Answer whether the receiver is pointed at a class comment" ^ true! ! !ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'sw 8/15/2002 22:38'! contentsSymbolQuints "Answer a list of quintuplets representing information on the alternative views available in the code pane" ^ #( (source togglePlainSource showingPlainSourceString 'source' 'the textual source code as writen') (showDiffs toggleRegularDiffing showingRegularDiffsString 'showDiffs' 'the textual source diffed from its prior version'))! ! !ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'asm 8/13/2002 22:14'! priorSourceOrNil "If the currently-selected method has a previous version, return its source, else return nil" | aClass aSelector changeRecords | (aClass _ self selectedClass) ifNil: [^ nil]. (aSelector _ self selectedMessageName) ifNil: [^ nil]. changeRecords _ self class commentRecordsOf: self selectedClass. (changeRecords == nil or: [changeRecords size <= 1]) ifTrue: [^ nil]. ^ (changeRecords at: 2) string ! ! !ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'asm 8/13/2002 20:59'! selectedClass "Answer the class currently selected in the browser. In the case of a VersionsBrowser, the class and selector are always the same, regardless of which version is selected and indeed whether or not any entry is selected in the list pane" ^ classOfMethod! ! !ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'sw 8/15/2002 22:35'! wantsPrettyDiffOption "Answer whether pretty-diffs are meaningful for this tool" ^ false! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ClassCommentVersionsBrowser class instanceVariableNames: ''! !ClassCommentVersionsBrowser class methodsFor: 'instance creation' stamp: 'asm 8/12/2002 22:46'! browseCommentOf: class | changeList | Cursor read showWhile: [changeList _ self new scanVersionsOf: class. changeList ifNil: [^ self inform: 'No versions available']. self open: changeList name: 'Recent versions of ',class name,'''s comments' multiSelect: false ] ! ! !ClassCommentVersionsBrowser class methodsFor: 'utilities' stamp: 'asm 8/13/2002 22:09'! commentRecordsOf: aClass "Return a list of ChangeRecords for all versions of the method at selector. Source code can be retrieved by sending string to any one. Return nil if the method is absent." | aList | aList _ self new scanVersionsOf: aClass. ^ aList ifNotNil: [aList changeList]! ! !ClassCommentVersionsBrowser class methodsFor: 'utilities' stamp: 'asm 8/13/2002 20:54'! timeStampFor: aSelector class: aClass reverseOrdinal: anInteger "Answer the time stamp corresponding to some version of the given method, nil if none. The reverseOrdinal parameter is interpreted as: 1 = current version; 2 = last-but-one version, etc." | aChangeList | aChangeList _ self new scanVersionsOf: aClass. ^ aChangeList ifNil: [nil] ifNotNil: [aChangeList list size >= anInteger ifTrue: [(aChangeList changeList at: anInteger) stamp] ifFalse: [nil]]! ! Behavior subclass: #ClassDescription instanceVariableNames: 'instanceVariables organization' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !ClassDescription commentStamp: '<historical>' prior: 0! I add a number of facilities to basic Behaviors: Named instance variables Category organization for methods The notion of a name of this class (implemented as subclass responsibility) The maintenance of a ChangeSet, and logging changes on a file Most of the mechanism for fileOut. I am an abstract class, in particular, my facilities are intended for inheritance by two subclasses, Class and Metaclass. The slots 'organization' and 'methodDict' should ONLY be accessed by message in order for things to work during ImageSegment>>discoverActiveClasses (q.v.).! !ClassDescription methodsFor: 'initialize-release' stamp: 'ar 11/22/1999 10:09'! doneCompiling "A ClassBuilder has finished the compilation of the receiver. This message is a notification for a class that needs to do some cleanup / reinitialization after it has been recompiled."! ! !ClassDescription methodsFor: 'initialize-release' stamp: 'NS 4/6/2004 15:32'! obsolete "Make the receiver obsolete." superclass removeSubclass: self. self organization: nil. super obsolete.! ! !ClassDescription methodsFor: 'initialize-release' stamp: 'NS 4/6/2004 15:31'! superclass: aClass methodDictionary: mDict format: fmt "Basic initialization of the receiver" super superclass: aClass methodDictionary: mDict format: fmt. instanceVariables _ nil. self organization: nil.! ! !ClassDescription methodsFor: 'initialize-release' stamp: 'ar 3/1/2001 23:25'! updateInstances: oldInstances from: oldClass isMeta: isMeta "Recreate any existing instances of the argument, oldClass, as instances of the receiver, which is a newly changed class. Permute variables as necessary. Return the array of old instances (none of which should be pointed to legally by anyone but the array)." "If there are any contexts having an old instance as receiver it might crash the system because the layout has changed, and the method only knows about the old layout." | map variable instSize newInstances | oldInstances isEmpty ifTrue:[^#()]. "no instances to convert" isMeta ifTrue: [ oldInstances size = 1 ifFalse:[^self error:'Metaclasses can only have one instance']. self soleInstance class == self ifTrue:[ ^self error:'Metaclasses can only have one instance']]. map _ self instVarMappingFrom: oldClass. variable _ self isVariable. instSize _ self instSize. newInstances _ Array new: oldInstances size. 1 to: oldInstances size do:[:i| newInstances at: i put: ( self newInstanceFrom: (oldInstances at: i) variable: variable size: instSize map: map)]. "Now perform a bulk mutation of old instances into new ones" oldInstances elementsExchangeIdentityWith: newInstances. ^newInstances "which are now old"! ! !ClassDescription methodsFor: 'initialize-release' stamp: 'BG 10/29/2003 09:09'! updateInstancesFrom: oldClass "Recreate any existing instances of the argument, oldClass, as instances of the receiver, which is a newly changed class. Permute variables as necessary. Return the array of old instances (none of which should be pointed to legally by anyone but the array)." "ar 7/15/1999: The updating below is possibly dangerous. If there are any contexts having an old instance as receiver it might crash the system if the new receiver in which the context is executed has a different layout. See bottom below for a simple example:" | oldInstances | oldInstances _ oldClass allInstances asArray. oldInstances _ self updateInstances: oldInstances from: oldClass isMeta: self isMeta. "Now fix up instances in segments that are out on the disk." " ImageSegment allSubInstancesDo: [:seg | seg segUpdateInstancesOf: oldClass toBe: self isMeta: self isMeta]. " ^oldInstances " | crashingBlock class | class _ Object subclass: #CrashTestDummy instanceVariableNames: 'instVar' classVariableNames: '' poolDictionaries: '' category: 'Crash-Test'. class compile:'instVar: value instVar _ value'. class compile:'crashingBlock ^[instVar]'. crashingBlock _ (class new) instVar: 42; crashingBlock. Object subclass: #CrashTestDummy instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Crash-Test'. crashingBlock. crashingBlock value. " ! ! !ClassDescription methodsFor: 'accessing' stamp: 'sd 6/27/2003 23:57'! classVersion "Default. Any class may return a later version to inform readers that use ReferenceStream. 8/17/96 tk" "This method allows you to distinguish between class versions when the shape of the class hasn't changed (when there's no change in the instVar names). In the conversion methods you usually can tell by the inst var names what old version you have. In a few cases, though, the same inst var names were kept but their interpretation changed (like in the layoutFrame). By changing the class version when you keep the same instVars you can warn older and newer images that they have to convert." ^ 0! ! !ClassDescription methodsFor: 'accessing' stamp: 'di 2/9/2000 17:54'! comment "Answer the receiver's comment. (If missing, supply a template) " | aString | aString _ self theNonMetaClass organization classComment. aString isEmpty ifFalse: [^ aString]. ^ 'Main comment stating the purpose of this class and relevant relationship to other classes. Possible useful expressions for doIt or printIt. Structure: instVar1 type -- comment about the purpose of instVar1 instVar2 type -- comment about the purpose of instVar2 Any further useful comments about the general approach of this implementation.'! ! !ClassDescription methodsFor: 'accessing' stamp: 'NS 1/27/2004 14:54'! comment: aStringOrText "Set the receiver's comment to be the argument, aStringOrText." self theNonMetaClass classComment: aStringOrText.! ! !ClassDescription methodsFor: 'accessing' stamp: 'NS 1/27/2004 14:54'! comment: aStringOrText stamp: aStamp "Set the receiver's comment to be the argument, aStringOrText." self theNonMetaClass classComment: aStringOrText stamp: aStamp.! ! !ClassDescription methodsFor: 'accessing' stamp: 'ls 10/28/2003 12:32'! hasComment "return whether this class truly has a comment other than the default" | org | org := self theNonMetaClass organization. ^org classComment notNil and: [ org classComment isEmpty not ]. ! ! !ClassDescription methodsFor: 'accessing'! theNonMetaClass "Sent to a class or metaclass, always return the class" ^self! ! !ClassDescription methodsFor: 'copying' stamp: 'di 2/17/2000 22:35'! copy: sel from: class classified: cat "Install the method associated with the first arugment, sel, a message selector, found in the method dictionary of the second argument, class, as one of the receiver's methods. Classify the message under the third argument, cat." | code category | "Useful when modifying an existing class" code _ class sourceMethodAt: sel. code == nil ifFalse: [cat == nil ifTrue: [category _ class organization categoryOfElement: sel] ifFalse: [category _ cat]. (self methodDict includesKey: sel) ifTrue: [code asString = (self sourceMethodAt: sel) asString ifFalse: [self error: self name , ' ' , sel , ' will be redefined if you proceed.']]. self compile: code classified: category]! ! !ClassDescription methodsFor: 'copying'! copyAll: selArray from: class classified: cat "Install all the methods found in the method dictionary of the second argument, class, as the receiver's methods. Classify the messages under the third argument, cat." selArray do: [:s | self copy: s from: class classified: cat]! ! !ClassDescription methodsFor: 'copying'! copyAllCategoriesFrom: aClass "Specify that the categories of messages for the receiver include all of those found in the class, aClass. Install each of the messages found in these categories into the method dictionary of the receiver, classified under the appropriate categories." aClass organization categories do: [:cat | self copyCategory: cat from: aClass]! ! !ClassDescription methodsFor: 'copying'! copyCategory: cat from: class "Specify that one of the categories of messages for the receiver is cat, as found in the class, class. Copy each message found in this category." self copyCategory: cat from: class classified: cat! ! !ClassDescription methodsFor: 'copying'! copyCategory: cat from: aClass classified: newCat "Specify that one of the categories of messages for the receiver is the third argument, newCat. Copy each message found in the category cat in class aClass into this new category." self copyAll: (aClass organization listAtCategoryNamed: cat) from: aClass classified: newCat! ! !ClassDescription methodsFor: 'printing' stamp: 'lr 11/24/2003 17:21'! classVariablesString "Answer a string of my class variable names separated by spaces." ^String streamContents: [ :stream | self classPool keys asSortedCollection do: [ :each | stream nextPutAll: each ] separatedBy: [ stream space ] ]! ! !ClassDescription methodsFor: 'printing' stamp: 'lr 11/24/2003 17:20'! instanceVariablesString "Answer a string of my instance variable names separated by spaces." ^String streamContents: [ :stream | self instVarNames do: [ :each | stream nextPutAll: each ] separatedBy: [ stream space ] ]! ! !ClassDescription methodsFor: 'printing'! printOn: aStream aStream nextPutAll: self name! ! !ClassDescription methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:05'! printOnStream: aStream aStream print: self name! ! !ClassDescription methodsFor: 'printing' stamp: 'lr 11/24/2003 17:24'! sharedPoolsString "Answer a string of my shared pool names separated by spaces." ^String streamContents: [ :stream | self sharedPools do: [ :each | stream nextPutAll: (self environment keyAtIdentityValue: each ifAbsent: [ 'private' ]) ] separatedBy: [ stream space ] ]! ! !ClassDescription methodsFor: 'printing'! storeOn: aStream "Classes and Metaclasses have global names." aStream nextPutAll: self name! ! !ClassDescription methodsFor: 'instance variables'! addInstVarName: aString "Add the argument, aString, as one of the receiver's instance variables." self subclassResponsibility! ! !ClassDescription methodsFor: 'instance variables' stamp: 'sw 10/23/2000 18:05'! allInstVarNamesEverywhere "Answer the set of inst var names used by the receiver, all superclasses, and all subclasses" | aList | aList _ OrderedCollection new. (self allSuperclasses , self withAllSubclasses asOrderedCollection) do: [:cls | aList addAll: cls instVarNames]. ^ aList asSet "BorderedMorph allInstVarNamesEverywhere"! ! !ClassDescription methodsFor: 'instance variables' stamp: 'di 11/9/1998 20:21'! checkForInstVarsOK: instVarString "Return true if instVarString does no include any names used in a subclass" | instVarArray | instVarArray _ Scanner new scanFieldNames: instVarString. self allSubclasses do: [:cl | cl instVarNames do: [:n | (instVarArray includes: n) ifTrue: [self error: n , ' is already used in ' , cl name. ^ false]]]. ^ true! ! !ClassDescription methodsFor: 'instance variables' stamp: 'sw 9/28/1999 17:04'! chooseInstVarAlphabeticallyThenDo: aBlock | allVars index | "Put up a menu of all the instance variables in the receiver, presented in alphabetical order, and when the user chooses one, evaluate aBlock with the chosen variable as its parameter." allVars _ self allInstVarNames asSortedArray. allVars isEmpty ifTrue: [^ self inform: 'There are no instance variables']. index _ (PopUpMenu labelArray: allVars lines: #()) startUpWithCaption: 'Instance variables in ', self name. index = 0 ifTrue: [^ self]. aBlock value: (allVars at: index)! ! !ClassDescription methodsFor: 'instance variables' stamp: 'ls 12/5/1999 13:40'! chooseInstVarThenDo: aBlock "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. If the list is 6 or larger, then offer an alphabetical formulation as an alternative. triggered by a 'show alphabetically' item at the top of the list." | lines labelStream vars allVars index count offerAlpha | (count _ self allInstVarNames size) = 0 ifTrue: [^ self inform: 'There are no instance variables.']. allVars _ OrderedCollection new. lines _ OrderedCollection new. labelStream _ WriteStream on: (String new: 200). (offerAlpha _ count > 5) ifTrue: [lines add: 1. allVars add: 'show alphabetically'. labelStream nextPutAll: allVars first; cr]. self withAllSuperclasses reverseDo: [:class | vars _ class instVarNames. vars do: [:var | labelStream nextPutAll: var; cr. allVars add: var]. vars isEmpty ifFalse: [lines add: allVars size]]. labelStream skip: -1 "cut last CR". (lines size > 0 and: [lines last = allVars size]) ifTrue: [lines removeLast]. "dispense with inelegant line beneath last item" index _ (PopUpMenu labels: labelStream contents lines: lines) startUpWithCaption: 'Instance variables in ', self name. index = 0 ifTrue: [^ self]. (index = 1 and: [offerAlpha]) ifTrue: [^ self chooseInstVarAlphabeticallyThenDo: aBlock]. aBlock value: (allVars at: index)! ! !ClassDescription methodsFor: 'instance variables' stamp: 'sw 5/27/1999 16:46'! classThatDefinesInstanceVariable: instVarName (instanceVariables notNil and: [instanceVariables includes: instVarName asString]) ifTrue: [^ self]. ^ superclass ifNotNil: [superclass classThatDefinesInstanceVariable: instVarName]! ! !ClassDescription methodsFor: 'instance variables'! instVarNames "Answer an Array of the receiver's instance variable names." instanceVariables == nil ifTrue: [^#()] ifFalse: [^instanceVariables]! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'NS 1/28/2004 14:12'! addAndClassifySelector: selector withMethod: compiledMethod inProtocol: category notifying: requestor | priorMethodOrNil | priorMethodOrNil _ self compiledMethodAt: selector ifAbsent: [nil]. self addSelectorSilently: selector withMethod: compiledMethod. SystemChangeNotifier uniqueInstance doSilently: [self organization classify: selector under: category]. priorMethodOrNil isNil ifTrue: [SystemChangeNotifier uniqueInstance methodAdded: compiledMethod selector: selector inProtocol: category class: self requestor: requestor] ifFalse: [SystemChangeNotifier uniqueInstance methodChangedFrom: priorMethodOrNil to: compiledMethod selector: selector inClass: self requestor: requestor].! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'NS 1/28/2004 14:10'! addSelector: selector withMethod: compiledMethod notifying: requestor | priorMethodOrNil | priorMethodOrNil _ self compiledMethodAt: selector ifAbsent: [nil]. self addSelectorSilently: selector withMethod: compiledMethod. priorMethodOrNil isNil ifTrue: [SystemChangeNotifier uniqueInstance methodAdded: compiledMethod selector: selector inClass: self requestor: requestor] ifFalse: [SystemChangeNotifier uniqueInstance methodChangedFrom: priorMethodOrNil to: compiledMethod selector: selector inClass: self requestor: requestor].! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'sw 1/5/2001 06:53'! allMethodCategoriesIntegratedThrough: mostGenericClass "Answer a list of all the method categories of the receiver and all its superclasses, up through mostGenericClass" | aColl | aColl _ OrderedCollection new. self withAllSuperclasses do: [:aClass | (aClass includesBehavior: mostGenericClass) ifTrue: [aColl addAll: aClass organization categories]]. aColl remove: 'no messages' asSymbol ifAbsent: []. ^ (aColl asSet asSortedCollection: [:a :b | a asLowercase < b asLowercase]) asArray "ColorTileMorph allMethodCategoriesIntegratedThrough: TileMorph"! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'sw 12/11/2000 14:00'! isUniClass "Answer whether the receiver is a uniclass." ^ self name endsWithDigit! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'di 3/7/2001 17:05'! recoverFromMDFault "This method handles methodDict faults to support, eg, discoverActiveClasses (qv)." (organization isMemberOf: Array) ifFalse: [^ self error: 'oops']. methodDict _ organization first. organization _ organization second. ! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'sd 3/28/2003 15:32'! recoverFromMDFaultWithTrace "This method handles emthodDict faults to support, eg, discoverActiveClasses (qv)." self recoverFromMDFault. self environment at: #MDFaultDict ifPresent: [:faultDict | faultDict at: self name put: (String streamContents: [:strm | (thisContext stackOfSize: 20) do: [:item | strm print: item; cr]])] "Execute the following statement to induce MD fault tracing. This means that, not only will all active classes be recorded but, after a test run, MDFaultDict will contain, for every class used, a stack trace showing how it came to be used. This statement should be executed just prior to any such text, in order to clear the traces. Smalltalk at: #MDFaultDict put: Dictionary new. "! ! !ClassDescription methodsFor: 'accessing method dictionary'! removeCategory: aString "Remove each of the messages categorized under aString in the method dictionary of the receiver. Then remove the category aString." | categoryName | categoryName _ aString asSymbol. (self organization listAtCategoryNamed: categoryName) do: [:sel | self removeSelector: sel]. self organization removeCategory: categoryName! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'NS 4/7/2004 13:33'! removeSelector: selector | priorMethod priorProtocol | "Remove the message whose selector is given from the method dictionary of the receiver, if it is there. Answer nil otherwise." priorMethod _ self compiledMethodAt: selector ifAbsent: [^ nil]. priorProtocol _ self whichCategoryIncludesSelector: selector. SystemChangeNotifier uniqueInstance doSilently: [ self organization removeElement: selector]. super removeSelector: selector. SystemChangeNotifier uniqueInstance methodRemoved: priorMethod selector: selector inProtocol: priorProtocol class: self.! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'sw 5/18/1999 10:11'! ultimateSourceCodeAt: selector ifAbsent: aBlock "Return the source code at selector, deferring to superclass if necessary" ^ self sourceCodeAt: selector ifAbsent: [superclass ifNil: [aBlock value] ifNotNil: [superclass ultimateSourceCodeAt: selector ifAbsent: aBlock]]! ! !ClassDescription methodsFor: 'organization'! category "Answer the system organization category for the receiver." ^SystemOrganization categoryOfElement: self name! ! !ClassDescription methodsFor: 'organization' stamp: 'rw 8/2/2003 11:05'! category: cat "Categorize the receiver under the system category, cat, removing it from any previous categorization." | oldCat | oldCat := self category. (cat isKindOf: String) ifTrue: [SystemOrganization classify: self name under: cat asSymbol] ifFalse: [self errorCategoryName]. SystemChangeNotifier uniqueInstance class: self recategorizedFrom: oldCat to: cat asSymbol! ! !ClassDescription methodsFor: 'organization' stamp: 'BG 11/11/2003 09:51'! compactOrganization "Remove the organization of this class by message categories. This is typically done to save space in small systems. Classes and methods created or filed in subsequently will, nonetheless, be organized" organization notNil ifTrue: [organization updateFor: self]. self isMeta ifFalse: [self class compactOrganization]! ! !ClassDescription methodsFor: 'organization' stamp: 'NS 4/7/2004 13:33'! forgetDoIts "get rid of old DoIt methods and bogus entries in the ClassOrganizer." SystemChangeNotifier uniqueInstance doSilently: [ self organization removeElement: #DoIt; removeElement: #DoItIn:. ]. super forgetDoIts.! ! !ClassDescription methodsFor: 'organization' stamp: 'NS 4/6/2004 15:46'! organization "Answer the instance of ClassOrganizer that represents the organization of the messages of the receiver." organization ifNil: [self organization: (ClassOrganizer defaultList: self methodDict keys asSortedCollection asArray)]. (organization isMemberOf: Array) ifTrue: [self recoverFromMDFaultWithTrace]. "Making sure that subject is set correctly. It should not be necessary." organization ifNotNil: [organization setSubject: self]. ^ organization! ! !ClassDescription methodsFor: 'organization' stamp: 'NS 4/6/2004 15:26'! organization: aClassOrg "Install an instance of ClassOrganizer that represents the organization of the messages of the receiver." aClassOrg ifNotNil: [aClassOrg setSubject: self]. organization _ aClassOrg! ! !ClassDescription methodsFor: 'organization' stamp: 'di 7/17/97 00:06'! whichCategoryIncludesSelector: aSelector "Answer the category of the argument, aSelector, in the organization of the receiver, or answer nil if the receiver does not inlcude this selector." (self includesSelector: aSelector) ifTrue: [^ self organization categoryOfElement: aSelector] ifFalse: [^nil]! ! !ClassDescription methodsFor: 'organization' stamp: 'NS 4/6/2004 15:30'! zapOrganization "Remove the organization of this class by message categories. This is typically done to save space in small systems. Classes and methods created or filed in subsequently will, nonetheless, be organized" self organization: nil. self isMeta ifFalse: [self class zapOrganization]! ! !ClassDescription methodsFor: 'compiling'! acceptsLoggingOfCompilation "weird name is so that it will come lexically before #compile, so that a clean build can make it through. 7/7/96 sw" ^ true! ! !ClassDescription methodsFor: 'compiling'! compile: code classified: heading "Compile the argument, code, as source code in the context of the receiver and install the result in the receiver's method dictionary under the classification indicated by the second argument, heading. nil is to be notified if an error occurs. The argument code is either a string or an object that converts to a string or a PositionableStream on an object that converts to a string." ^self compile: code classified: heading notifying: (SyntaxError new category: heading)! ! !ClassDescription methodsFor: 'compiling' stamp: 'sw 8/21/97 00:26'! compile: text classified: category notifying: requestor | stamp | stamp _ self acceptsLoggingOfCompilation ifTrue: [Utilities changeStamp] ifFalse: [nil]. ^ self compile: text classified: category withStamp: stamp notifying: requestor ! ! !ClassDescription methodsFor: 'compiling' stamp: 'di 5/4/2001 11:35'! compile: text classified: category withStamp: changeStamp notifying: requestor ^ self compile: text classified: category withStamp: changeStamp notifying: requestor logSource: self acceptsLoggingOfCompilation! ! !ClassDescription methodsFor: 'compiling' stamp: 'NS 1/28/2004 14:25'! compile: text classified: category withStamp: changeStamp notifying: requestor logSource: logSource | methodAndNode | methodAndNode _ self basicCompile: text asString notifying: requestor trailer: self defaultMethodTrailer ifFail: [^nil]. logSource ifTrue: [ self logMethodSource: text forMethodWithNode: methodAndNode inCategory: category withStamp: changeStamp notifying: requestor. ]. self addAndClassifySelector: methodAndNode selector withMethod: methodAndNode method inProtocol: category notifying: requestor. self theNonMetaClass noteCompilationOf: methodAndNode selector meta: self isMeta. ^ methodAndNode selector! ! !ClassDescription methodsFor: 'compiling'! compile: code notifying: requestor "Refer to the comment in Behavior|compile:notifying:." ^self compile: code classified: ClassOrganizer default notifying: requestor! ! !ClassDescription methodsFor: 'compiling' stamp: 'NS 1/28/2004 14:45'! compileSilently: code classified: category "Compile the code and classify the resulting method in the given category, leaving no trail in the system log, nor in any change set, nor in the 'recent submissions' list. This should only be used when you know for sure that the compilation will succeed." ^ self compileSilently: code classified: category notifying: nil.! ! !ClassDescription methodsFor: 'compiling' stamp: 'NS 1/28/2004 14:45'! compileSilently: code classified: category notifying: requestor "Compile the code and classify the resulting method in the given category, leaving no trail in the system log, nor in any change set, nor in the 'recent submissions' list. This should only be used when you know for sure that the compilation will succeed." ^ SystemChangeNotifier uniqueInstance doSilently: [self compile: code classified: category withStamp: nil notifying: requestor logSource: false].! ! !ClassDescription methodsFor: 'compiling' stamp: 'sw 9/25/2001 02:11'! noteCompilationOf: aSelector meta: isMeta "A hook allowing some classes to react to recompilation of certain selectors"! ! !ClassDescription methodsFor: 'compiling' stamp: 'NS 1/28/2004 14:48'! wantsChangeSetLogging "Answer whether code submitted for the receiver should be remembered by the changeSet mechanism. 7/12/96 sw" ^ true! ! !ClassDescription methodsFor: 'compiling' stamp: 'sw 7/31/2000 12:55'! wantsRecompilationProgressReported "Answer whether the receiver would like progress of its recompilation reported interactively to the user." ^ true! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 9/8/1998 14:44'! classComment: aString "Store the comment, aString or Text or RemoteString, associated with the class we are orgainzing. Empty string gets stored only if had a non-empty one before." ^ self classComment: aString stamp: '<historical>'! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'NS 4/8/2004 11:35'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr | (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance classCommented: self. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr _ self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr _ oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file _ SourceFiles at: 2) ifNotNil: [file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header _ String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance classCommented: self. ! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 9/2/1998 14:22'! commentStamp: changeStamp self organization commentStamp: changeStamp. ^ self commentStamp: changeStamp prior: 0! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/13/97 14:21'! commentStamp: changeStamp prior: indexAndOffset "Prior source link ignored when filing in." ^ ClassCommentReader new setClass: self category: #Comment changeStamp: changeStamp ! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/7/2000 22:46'! definition "Answer a String that defines the receiver in good old ST-80." ^ self definitionST80! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'ls 10/9/2001 00:12'! definitionST80 "Answer a String that defines the receiver." | aStream path | aStream _ WriteStream on: (String new: 300). superclass == nil ifTrue: [aStream nextPutAll: 'ProtoObject'] ifFalse: [path _ ''. self environment scopeFor: superclass name from: nil envtAndPathIfFound: [:envt :remotePath | path _ remotePath]. aStream nextPutAll: path , superclass name]. aStream nextPutAll: self kindOfSubclass; store: self name. aStream cr; tab; nextPutAll: 'instanceVariableNames: '; store: self instanceVariablesString. aStream cr; tab; nextPutAll: 'classVariableNames: '; store: self classVariablesString. aStream cr; tab; nextPutAll: 'poolDictionaries: '; store: self sharedPoolsString. aStream cr; tab; nextPutAll: 'category: '; store: (SystemOrganization categoryOfElement: self name) asString. superclass ifNil: [ aStream nextPutAll: '.'; cr. aStream nextPutAll: self name. aStream space; nextPutAll: 'superclass: nil'. ]. ^ aStream contents! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'ls 10/9/2001 00:12'! definitionST80: isST80 "Answer a String that defines the receiver." | aStream path | isST80 ifTrue: [^ self definitionST80]. aStream _ WriteStream on: (String new: 300). superclass == nil ifTrue: [aStream nextPutAll: 'ProtoObject'] ifFalse: [path _ ''. self environment scopeFor: superclass name from: nil envtAndPathIfFound: [:envt :remotePath | path _ remotePath]. aStream nextPutAll: path , superclass name]. aStream nextPutKeyword: self kindOfSubclass withArg: self name. aStream cr; tab; nextPutKeyword: 'instanceVariableNames: ' withArg: self instanceVariablesString. aStream cr; tab; nextPutKeyword: 'classVariableNames: 'withArg: self classVariablesString. aStream cr; tab; nextPutKeyword: 'poolDictionaries: ' withArg: self sharedPoolsString. aStream cr; tab; nextPutKeyword: 'category: ' withArg: (SystemOrganization categoryOfElement: self name) asString. superclass ifNil: [ aStream nextPutAll: '.'; cr. aStream nextPutAll: self name. aStream space; nextPutAll: 'superclass (nil)'. ]. ^ aStream contents! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 10:06'! fileOutCategory: catName ^ self fileOutCategory: catName asHtml: false! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 10:05'! fileOutCategory: catName asHtml: useHtml "FileOut the named category, possibly in Html format." | fileStream | fileStream _ useHtml ifTrue: [(FileStream newFileNamed: self name , '-' , catName , '.html') asHtml] ifFalse: [FileStream newFileNamed: self name , '-' , catName , '.st']. fileStream header; timeStamp. self fileOutCategory: catName on: fileStream moveSource: false toFile: 0. fileStream trailer; close! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 10/15/1999 14:45'! fileOutCategory: aSymbol on: aFileStream moveSource: moveSource toFile: fileIndex "File a description of the receiver's category, aString, onto aFileStream. If moveSource, is true, then set the method source pointer to the new file position. Note when this method is called with moveSource=true, it is condensing the .sources file, and should only write one preamble per method category." | selectors | aFileStream cr. selectors := (aSymbol asString = ClassOrganizer allCategory) ifTrue: [ self organization allMethodSelectors ] ifFalse: [ self organization listAtCategoryNamed: aSymbol ]. "Overridden to preserve author stamps in sources file regardless" selectors do: [:sel | self printMethodChunk: sel withPreamble: true on: aFileStream moveSource: moveSource toFile: fileIndex]. ^ self! ! !ClassDescription methodsFor: 'fileIn/Out'! fileOutChangedMessages: aSet on: aFileStream "File a description of the messages of the receiver that have been changed (i.e., are entered into the argument, aSet) onto aFileStream." self fileOutChangedMessages: aSet on: aFileStream moveSource: false toFile: 0! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/26/97 21:41'! fileOutChangedMessages: aSet on: aFileStream moveSource: moveSource toFile: fileIndex "File a description of the messages of this class that have been changed (i.e., are entered into the argument, aSet) onto aFileStream. If moveSource, is true, then set the method source pointer to the new file position. Note when this method is called with moveSource=true, it is condensing the .changes file, and should only write a preamble for every method." | org sels | (org _ self organization) categories do: [:cat | sels _ (org listAtCategoryNamed: cat) select: [:sel | aSet includes: sel]. sels do: [:sel | self printMethodChunk: sel withPreamble: true on: aFileStream moveSource: moveSource toFile: fileIndex]]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 15:52'! fileOutMethod: selector "Write source code of a single method on a file. Make up a name for the file." self fileOutMethod: selector asHtml: false! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 8/1/2002 14:39'! fileOutMethod: selector asHtml: useHtml "Write source code of a single method on a file in .st or .html format" | fileStream nameBody | (selector == #Comment) ifTrue: [^ self inform: 'Sorry, cannot file out class comment in isolation.']. (self includesSelector: selector) ifFalse: [^ self error: 'Selector ', selector asString, ' not found']. nameBody _ self name , '-' , (selector copyReplaceAll: ':' with: ''). fileStream _ useHtml ifTrue: [(FileStream newFileNamed: nameBody , '.html') asHtml] ifFalse: [FileStream newFileNamed: nameBody , '.st']. fileStream header; timeStamp. self printMethodChunk: selector withPreamble: true on: fileStream moveSource: false toFile: 0. fileStream close! ! !ClassDescription methodsFor: 'fileIn/Out'! fileOutOn: aFileStream "File a description of the receiver on aFileStream." self fileOutOn: aFileStream moveSource: false toFile: 0! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 1/15/98 23:38'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." aFileStream command: 'H3'. aFileStream nextChunkPut: self definition. aFileStream command: '/H3'. self organization putCommentOnFile: aFileStream numbered: fileIndex moveSource: moveSource forClass: self. self organization categories do: [:heading | self fileOutCategory: heading on: aFileStream moveSource: moveSource toFile: fileIndex]! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 20:35'! fileOutOrganizationOn: aFileStream "File a description of the receiver's organization on aFileStream." aFileStream cr; nextPut: $!!. aFileStream nextChunkPut: self name, ' reorganize'; cr. aFileStream nextChunkPut: self organization printString; cr! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/29/97 13:00'! methodsFor: categoryName "Answer a ClassCategoryReader for compiling the messages in the category, categoryName, of the receiver." ^ ClassCategoryReader new setClass: self category: categoryName asSymbol "(False methodsFor: 'logical operations') inspect"! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/13/97 13:51'! methodsFor: categoryName stamp: changeStamp ^ self methodsFor: categoryName stamp: (Utilities fixStamp: changeStamp) prior: 0! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 8/15/1998 22:02'! methodsFor: categoryName stamp: changeStamp prior: indexAndOffset "Prior source link ignored when filing in." ^ ClassCategoryReader new setClass: self category: categoryName asSymbol changeStamp: changeStamp "Most importantly, return the new ClassCategoryReader, so a fileIn will let it seize control. So method will be placed in the proper category. See the transfer of control where ReadWriteStream fileIn calls scanFrom:"! ]style[(65 333 22 17)f1b,f1,f1LReadWriteStream fileIn;,f1! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 1/2/2003 21:50'! moveChangesTo: newFile "Used in the process of condensing changes, this message requests that the source code of all methods of the receiver that have been changed should be moved to newFile." | changes | changes _ self methodDict keys select: [:sel | (self methodDict at: sel) fileIndex > 1]. self fileOutChangedMessages: changes on: newFile moveSource: true toFile: 2! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 4/4/1999 11:43'! printCategoryChunk: category on: aFileStream withStamp: changeStamp priorMethod: priorMethod "Print a method category preamble. This must have a category name. It may have an author/date stamp, and it may have a prior source link. If it has a prior source link, it MUST have a stamp, even if it is empty." "The current design is that changeStamps and prior source links are preserved in the changes file. All fileOuts include changeStamps. Condensing sources, however, eliminates all stamps (and links, natch)." aFileStream cr; command: 'H3'; nextPut: $!!. aFileStream nextChunkPut: (String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' methodsFor: '; print: category asString. (changeStamp ~~ nil and: [changeStamp size > 0 or: [priorMethod ~~ nil]]) ifTrue: [strm nextPutAll: ' stamp: '; print: changeStamp]. priorMethod ~~ nil ifTrue: [strm nextPutAll: ' prior: '; print: priorMethod sourcePointer]]). aFileStream command: '/H3'.! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'RAA 5/5/2000 09:08'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble _ self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble _ '']. method _ self methodDict at: selector. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos _ method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: (self decompilerClass new decompile: selector in: self method: method) decompileString] ifFalse: [sourceFile _ SourceFiles at: method fileIndex. sourceFile position: oldPos. preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile]. "Copy the method chunk" newPos _ outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "The following chunk may have ]style[" sourceFile peek == $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos _ outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'NS 4/8/2004 11:32'! putClassCommentToCondensedChangesFile: aFileStream "Called when condensing changes. If the receiver has a class comment, and if that class comment does not reside in the .sources file, then write it to the given filestream, with the resulting RemoteString being reachable from the source file #2. Note that any existing backpointer into the .sources file is lost by this process -- a situation that maybe should be fixed someday." | header aStamp aCommentRemoteStr | self isMeta ifTrue: [^ self]. "bulletproofing only" ((aCommentRemoteStr _ self organization commentRemoteStr) isNil or: [aCommentRemoteStr sourceFileNumber == 1]) ifTrue: [^ self]. aFileStream cr; nextPut: $!!. header _ String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. (aStamp _ self organization commentStamp ifNil: ['<historical>']) storeOn: strm. strm nextPutAll: ' prior: 0']. aFileStream nextChunkPut: header. aFileStream cr. self organization classComment: (RemoteString newString: self organization classComment onFileNumber: 2 toFile: aFileStream) stamp: aStamp! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'NS 4/7/2004 23:01'! reorganize "During fileIn, !!Rectangle reorganize!! allows Rectangle to seize control and treat the next chunk as its organization. See the transfer of control where ReadWriteStream fileIn calls scanFrom:" ^self organization! ]style[(10 156 22 38)f1b,f1,f1LReadWriteStream fileIn;,f1! ! !ClassDescription methodsFor: 'private'! errorCategoryName self error: 'Category name must be a String'! ! !ClassDescription methodsFor: 'private' stamp: 'ar 7/11/1999 11:41'! instVarMappingFrom: oldClass "Return the mapping from instVars of oldClass to new class that is used for converting old instances of oldClass." | oldInstVarNames | oldInstVarNames _ oldClass allInstVarNames. ^self allInstVarNames collect: [:instVarName | oldInstVarNames indexOf: instVarName]. ! ! !ClassDescription methodsFor: 'private' stamp: 'NS 1/28/2004 14:22'! logMethodSource: aText forMethodWithNode: aCompiledMethodWithNode inCategory: category withStamp: changeStamp notifying: requestor | priorMethodOrNil newText | priorMethodOrNil := self compiledMethodAt: aCompiledMethodWithNode selector ifAbsent: []. newText _ ((requestor == nil or: [requestor isKindOf: SyntaxError]) not and: [Preferences confirmFirstUseOfStyle]) ifTrue: [aText askIfAddStyle: priorMethodOrNil req: requestor] ifFalse: [aText]. aCompiledMethodWithNode method putSource: newText fromParseNode: aCompiledMethodWithNode node class: self category: category withStamp: changeStamp inFile: 2 priorMethod: priorMethodOrNil.! ! !ClassDescription methodsFor: 'private' stamp: 'ar 7/10/1999 11:17'! newInstanceFrom: oldInstance variable: variable size: instSize map: map "Create a new instance of the receiver based on the given old instance. The supplied map contains a mapping of the old instVar names into the receiver's instVars" | new | variable ifTrue: [new _ self basicNew: oldInstance basicSize] ifFalse: [new _ self basicNew]. 1 to: instSize do: [:offset | (map at: offset) > 0 ifTrue: [new instVarAt: offset put: (oldInstance instVarAt: (map at: offset))]]. variable ifTrue: [1 to: oldInstance basicSize do: [:offset | new basicAt: offset put: (oldInstance basicAt: offset)]]. ^new! ! !ClassDescription methodsFor: 'private' stamp: 'ar 7/15/1999 17:04'! setInstVarNames: instVarArray "Private - for class initialization only" | required | required _ self instSize. superclass notNil ifTrue:[required _ required - superclass instSize]. instVarArray size = required ifFalse:[^self error: required printString, ' instvar names are required']. instVarArray isEmpty ifTrue:[instanceVariables _ nil] ifFalse:[instanceVariables _ instVarArray asArray].! ! !ClassDescription methodsFor: 'accessing class hierarchy' stamp: 'ar 7/14/1999 10:57'! printSubclassesOn: aStream level: level "As part of the algorithm for printing a description of the receiver, print the subclass on the file stream, aStream, indenting level times." | subclassNames | aStream crtab: level. aStream nextPutAll: self name. aStream space; print: self instVarNames. self == Class ifTrue: [aStream crtab: level + 1; nextPutAll: '[ ... all the Metaclasses ... ]'. ^self]. subclassNames _ self subclasses asSortedCollection:[:c1 :c2| c1 name <= c2 name]. "Print subclasses in alphabetical order" subclassNames do: [:subclass | subclass printSubclassesOn: aStream level: level + 1]! ! !ClassDescription methodsFor: 'accessing class hierarchy' stamp: 'di 7/21/1999 11:05'! subclasses ^ Array new! ! !ClassDescription methodsFor: 'accessing class hierarchy' stamp: 'ar 7/10/1999 08:22'! subclassesDo: aBlock "Evaluate the argument, aBlock, for each of the receiver's immediate subclasses." ^self subclasses do: aBlock! ! TextDiffBuilder subclass: #ClassDiffBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !ClassDiffBuilder methodsFor: 'initialize'! split: aString | lines in out c | lines := OrderedCollection new. in := ReadStream on: aString. out := WriteStream on: String new. [in atEnd] whileFalse:[ (c := in next) isSeparator ifTrue:[ out nextPut: c. lines add: out contents. out reset. ] ifFalse:[ out nextPut: c. ]. ]. out position = 0 ifFalse:[ lines add: out contents. ]. ^lines! ! !ClassDiffBuilder methodsFor: 'printing' stamp: 'nk 4/24/2004 08:49'! printPatchSequence: ps on: aStream | type line | ps do: [:assoc | type := assoc key. line := assoc value. aStream withAttributes: (self attributesOf: type) do: [aStream nextPutAll: line]]! ! HierarchyBrowser subclass: #ClassListBrowser instanceVariableNames: 'defaultTitle' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !ClassListBrowser commentStamp: '<historical>' prior: 0! A ClassListBrowser displays the code for an arbitrary list of classes. ClassListBrowser example1. "all classes that have the string 'Pluggable' in their names" ClassListBrowser example2. "all classes whose names start with the letter S" ClassListBrowser example3. "all variable classes" ClassListBrowser example4. "all classes with more than 100 methods" ClassListBrowser example5. "all classes that lack class comments" ClassListBrowser example6. "all classes that have class instance variables" ClassListBrowser new initForClassesNamed: #(Browser Boolean) title: 'Browser and Boolean!!'. ! !ClassListBrowser methodsFor: 'initialization' stamp: 'sw 7/18/2002 22:43'! initForClassesNamed: nameList title: aTitle "Initialize the receiver for the class-name-list and title provided" self systemOrganizer: SystemOrganization. metaClassIndicated _ false. defaultTitle _ aTitle. classList _ nameList copy. self class openBrowserView: (self openSystemCatEditString: nil) label: aTitle "ClassListBrowser new initForClassesNamed: #(Browser CategoryViewer) title: 'Frogs'"! ! !ClassListBrowser methodsFor: 'title' stamp: 'sw 7/18/2002 22:42'! defaultTitle: aTitle "Set the browser's default title" defaultTitle _ aTitle! ! !ClassListBrowser methodsFor: 'title' stamp: 'sw 7/18/2002 22:43'! labelString "Answer the label strilng to use on the browser" ^ defaultTitle ifNil: [super labelString]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ClassListBrowser class instanceVariableNames: ''! !ClassListBrowser class methodsFor: 'examples' stamp: 'sw 7/27/2002 16:01'! example1 "Put up a ClassListBrowser that shows all classes that have the string 'Pluggable' in their names" self browseClassesSatisfying: [:cl | cl name includesSubString: 'Pluggable'] title: 'Pluggables' "ClassListBrowser example1" ! ! !ClassListBrowser class methodsFor: 'examples' stamp: 'sd 4/17/2003 21:21'! example2 "Put up a ClassListBrowser that shows all classes whose names start with the letter S" self new initForClassesNamed: (self systemNavigation allClasses collect: [:c | c name] thenSelect: [:aName | aName first == $S]) title: 'All classes starting with S' "ClassListBrowser example2"! ! !ClassListBrowser class methodsFor: 'examples' stamp: 'sw 7/27/2002 16:03'! example3 "Put up a ClassListBrowser that shows all Variable classes" self browseClassesSatisfying: [:c | c isVariable] title: 'All Variable classes' "ClassListBrowser example3" ! ! !ClassListBrowser class methodsFor: 'examples' stamp: 'sw 7/27/2002 16:04'! example4 "Put up a ClassListBrowser that shows all classes implementing more than 100 methods" self browseClassesSatisfying: [:c | (c selectors size + c class selectors size) > 100] title: 'Classes with more than 100 methods' "ClassListBrowser example4" ! ! !ClassListBrowser class methodsFor: 'examples' stamp: 'sw 7/27/2002 14:32'! example5 "Put up a ClassListBrowser that shows all classes that lack class comments" self browseClassesSatisfying: [:c | c organization classComment isEmptyOrNil] title: 'Classes lacking class comments' "ClassListBrowser example5" ! ! !ClassListBrowser class methodsFor: 'examples' stamp: 'sw 7/27/2002 14:33'! example6 "Put up a ClassListBrowser that shows all classes that have class instance variables" self browseClassesSatisfying: [:c | c class instVarNames size > 0] title: 'Classes that define class-side instance variables' "ClassListBrowser example6"! ! !ClassListBrowser class methodsFor: 'instance creation' stamp: 'sd 4/17/2003 21:21'! browseClassesSatisfying: classBlock title: aTitle "Put up a ClassListBrowser showing all classes that satisfy the classBlock." self new initForClassesNamed: (self systemNavigation allClasses select: [:c | (classBlock value: c) == true] thenCollect: [:c | c name]) title: aTitle! ! BasicClassOrganizer subclass: #ClassOrganizer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !ClassOrganizer commentStamp: 'NS 4/6/2004 16:13' prior: 0! I represent method categorization information for classes. The handling of class comments has gone through a tortuous evolution. Grandfathered class comments (before late aug 98) have no time stamps, and historically, fileouts of class comments always substituted the timestamp reflecting the author and date/time at the moment of fileout; and historically any timestamps in a filed out class comment were dropped on the floor, with the author & time prevailing at the moment of filein being substituted. Such grandfathered comments now go out on fileouts with '<historical>' timestamp; class comments created after the 8/98 changes will have their correct timestamps preserved, though there is not yet a decent ui for reading those stamps other than filing out and looking at the file; nor is there yet any ui for browsing and recovering past versions of such comments. Everything in good time!!! !ClassOrganizer methodsFor: 'private' stamp: 'NS 4/7/2004 10:15'! notifyOfChangedCategoriesFrom: oldCollectionOrNil to: newCollectionOrNil (self hasSubject and: [oldCollectionOrNil ~= newCollectionOrNil]) ifTrue: [SystemChangeNotifier uniqueInstance classReorganized: self subject].! ! !ClassOrganizer methodsFor: 'private' stamp: 'NS 4/7/2004 23:02'! notifyOfChangedCategoryFrom: oldNameOrNil to: newNameOrNil (self hasSubject and: [oldNameOrNil ~= newNameOrNil]) ifTrue: [SystemChangeNotifier uniqueInstance classReorganized: self subject].! ! !ClassOrganizer methodsFor: 'private' stamp: 'NS 4/7/2004 22:52'! notifyOfChangedSelector: element from: oldCategory to: newCategory (self hasSubject and: [(oldCategory ~= newCategory)]) ifTrue: [ SystemChangeNotifier uniqueInstance selector: element recategorizedFrom: oldCategory to: newCategory inClass: self subject ].! ! !ClassOrganizer methodsFor: 'private' stamp: 'NS 4/12/2004 20:56'! notifyOfChangedSelectorsOldDict: oldDictionaryOrNil newDict: newDictionaryOrNil | newCat | (oldDictionaryOrNil isNil and: [newDictionaryOrNil isNil]) ifTrue: [^ self]. oldDictionaryOrNil isNil ifTrue: [ newDictionaryOrNil keysAndValuesDo: [:el :cat | self notifyOfChangedSelector: el from: nil to: cat]. ^ self. ]. newDictionaryOrNil isNil ifTrue: [ oldDictionaryOrNil keysAndValuesDo: [:el :cat | self notifyOfChangedSelector: el from: cat to: nil]. ^ self. ]. oldDictionaryOrNil keysAndValuesDo: [:el :cat | newCat _ newDictionaryOrNil at: el. self notifyOfChangedSelector: el from: cat to: newCat. ].! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:37'! addCategory: catString before: nextCategory | oldCategories | oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super addCategory: catString before: nextCategory]. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/15/2004 12:28'! changeFromCategorySpecs: categorySpecs | oldDict oldCategories | oldDict _ self elementCategoryDict. oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super changeFromCategorySpecs: categorySpecs]. self notifyOfChangedSelectorsOldDict: oldDict newDict: self elementCategoryDict. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:37'! classify: element under: heading suppressIfDefault: aBoolean | oldCat newCat | oldCat _ self categoryOfElement: element. SystemChangeNotifier uniqueInstance doSilently: [ super classify: element under: heading suppressIfDefault: aBoolean]. newCat _ self categoryOfElement: element. self notifyOfChangedSelector: element from: oldCat to: newCat.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:37'! removeCategory: cat | oldCategories | oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super removeCategory: cat]. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:37'! removeElement: element | oldCat | oldCat _ self categoryOfElement: element. SystemChangeNotifier uniqueInstance doSilently: [ super removeElement: element]. self notifyOfChangedSelector: element from: oldCat to: (self categoryOfElement: element).! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:38'! removeEmptyCategories | oldCategories | oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super removeEmptyCategories]. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:38'! renameCategory: oldCatString toBe: newCatString | oldCat newCat oldElementsBefore oldElementsAfter | oldCat _ oldCatString asSymbol. newCat _ newCatString asSymbol. oldElementsBefore _ self listAtCategoryNamed: oldCat. SystemChangeNotifier uniqueInstance doSilently: [ super renameCategory: oldCatString toBe: newCatString]. oldElementsAfter _ (self listAtCategoryNamed: oldCat) asSet. oldElementsBefore do: [:each | (oldElementsAfter includes: each) ifFalse: [self notifyOfChangedSelector: each from: oldCat to: newCat]. ]. self notifyOfChangedCategoryFrom: oldCat to: newCat.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/12/2004 20:57'! setDefaultList: aSortedCollection | oldDict oldCategories | oldDict _ self elementCategoryDict. oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super setDefaultList: aSortedCollection]. self notifyOfChangedSelectorsOldDict: oldDict newDict: self elementCategoryDict. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/7/2004 10:38'! sortCategories | oldCategories | oldCategories _ self categories copy. SystemChangeNotifier uniqueInstance doSilently: [ super sortCategories]. self notifyOfChangedCategoriesFrom: oldCategories to: self categories.! ! !ClassOrganizer methodsFor: 'updating' stamp: 'BG 10/31/2003 20:44'! updateFor: aClass | stream selector changed | changed := false. stream := ReadStream on: elementArray copy. [stream atEnd] whileFalse: [selector := stream next. (aClass methodDictionary includesKey: selector) ifFalse: [self removeElement: selector. changed := true]. ]. changed ifTrue: [self removeEmptyCategories.]! ! Object subclass: #Clipboard instanceVariableNames: 'contents recent' classVariableNames: 'Default' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !Clipboard commentStamp: '<historical>' prior: 0! The Clipboard class implements a basic buffering scheme for text. The currently selected text is also exported to the OS so that text can be copied from and to other applications. Commonly only a single instance is used (the default clipboard) but applications are free to use other than the default clipboard if necessary.! !Clipboard methodsFor: 'initialize' stamp: 'ar 1/15/2001 18:34'! initialize contents _ '' asText. recent _ OrderedCollection new.! ! !Clipboard methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:32'! chooseRecentClipping "Clipboard chooseRecentClipping" "Choose by menu from among the recent clippings" recent ifNil: [^ nil]. ^ (SelectionMenu labelList: (recent collect: [:txt | ((txt asString contractTo: 50) copyReplaceAll: Character cr asString with: '\') copyReplaceAll: Character tab asString with: '|']) selections: recent) startUp. ! ! !Clipboard methodsFor: 'accessing' stamp: 'RAA 2/6/2001 11:18'! clipboardText "Return the text currently in the clipboard. If the system clipboard is empty, or if it differs from the Smalltalk clipboard text, use the Smalltalk clipboard. This is done since (a) the Mac clipboard gives up on very large chunks of text and (b) since not all platforms support the notion of a clipboard." | s | s _ self primitiveClipboardText. (s isEmpty or: [s = contents asString]) ifTrue: [^ contents] ifFalse: [^ s asText]! ! !Clipboard methodsFor: 'accessing' stamp: 'RAA 2/6/2001 11:21'! clipboardText: text "Set text currently on the clipboard. Also export to OS" contents _ text. self noteRecentClipping: text asText. self primitiveClipboardText: text asString! ! !Clipboard methodsFor: 'primitives' stamp: 'ar 1/15/2001 18:28'! primitiveClipboardText "Get the current clipboard text. Return the empty string if the primitive fails." <primitive: 141> ^ ''! ! !Clipboard methodsFor: 'primitives' stamp: 'ar 1/15/2001 18:30'! primitiveClipboardText: aString "Set the current clipboard text to the given string." <primitive: 141> "don't fail if the primitive is not implemented"! ! !Clipboard methodsFor: 'private' stamp: 'ar 1/15/2001 18:34'! noteRecentClipping: text "Keep most recent clippings in a queue for pasteRecent (paste... command)" text isEmpty ifTrue: [^ self]. text size > 50000 ifTrue: [^ self]. (recent includes: text) ifTrue: [^ self]. recent addFirst: text. [recent size > 5] whileTrue: [recent removeLast]. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Clipboard class instanceVariableNames: ''! !Clipboard class methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:45'! chooseRecentClipping "Clipboard chooseRecentClipping" "Choose by menu from among the recent clippings" ^self default chooseRecentClipping! ! !Clipboard class methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:35'! clipboardText "Clipboard clipboardText" ^self default clipboardText.! ! !Clipboard class methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:35'! clipboardText: aText ^self default clipboardText: aText! ! !Clipboard class methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:33'! default ^Default ifNil:[Default _ self new].! ! !Clipboard class methodsFor: 'accessing' stamp: 'ar 1/15/2001 18:48'! default: aClipboard "So that clients can switch between different default clipboards" Default _ aClipboard.! ! StringHolder subclass: #CodeHolder instanceVariableNames: 'currentCompiledMethod contentsSymbol' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !CodeHolder commentStamp: '<historical>' prior: 0! An ancestor class for all models which can show code. Eventually, much of the code that currently resides in StringHolder which only applies to code-holding StringHolders might get moved down here.! !CodeHolder methodsFor: 'annotation' stamp: 'sw 2/22/2001 10:00'! addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream "add an annotation detailing the prior versions count" | versionsCount | versionsCount _ VersionsBrowser versionCountForSelector: aSelector class: aClass. aStream nextPutAll: ((versionsCount > 1 ifTrue: [versionsCount == 2 ifTrue: ['1 prior version'] ifFalse: [versionsCount printString, ' prior versions']] ifFalse: ['no prior versions']), self annotationSeparator)! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 1/25/2001 06:40'! annotation "Provide a line of content for an annotation pane, representing information about the method associated with the selected class and selector in the receiver." | aSelector aClass | ((aSelector _ self selectedMessageName) == nil or: [(aClass _ self selectedClassOrMetaClass) == nil]) ifTrue: [^ '------']. ^ self annotationForSelector: aSelector ofClass: aClass! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 9/11/2002 21:30'! annotationForClassCommentFor: aClass "Provide a line of content for an annotation pane, given that the receiver is pointing at the clas comment of the given class." | aStamp nonMeta | aStamp _ (nonMeta _ aClass theNonMetaClass) organization commentStamp. ^ aStamp ifNil: [nonMeta name, ' has no class comment'] ifNotNil: ['class comment for ', nonMeta name, (aStamp = '<historical>' ifFalse: [' - ', aStamp] ifTrue: [''])]! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 8/26/2002 10:19'! annotationForClassDefinitionFor: aClass "Provide a line of content for an annotation pane, given that the receiver is pointing at the class definition of the given class." ^ 'Class definition for ', aClass name! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 8/26/2002 10:19'! annotationForHierarchyFor: aClass "Provide a line of content for an annotation pane, given that the receiver is pointing at the hierarchy of the given class." ^ 'Hierarchy for ', aClass name! ! !CodeHolder methodsFor: 'annotation' stamp: 'sd 4/29/2003 11:54'! annotationForSelector: aSelector ofClass: aClass "Provide a line of content for an annotation pane, representing information about the given selector and class" | stamp sendersCount implementorsCount aCategory separator aString aList aComment aStream requestList | aSelector == #Comment ifTrue: [^ self annotationForClassCommentFor: aClass]. aSelector == #Definition ifTrue: [^ self annotationForClassDefinitionFor: aClass]. aSelector == #Hierarchy ifTrue: [^ self annotationForHierarchyFor: aClass]. aStream _ ReadWriteStream on: ''. requestList _ self annotationRequests. separator _ requestList size > 1 ifTrue: [self annotationSeparator] ifFalse: ['']. requestList do: [:aRequest | aRequest == #firstComment ifTrue: [aComment _ aClass firstCommentAt: aSelector. aComment isEmptyOrNil ifFalse: [aStream nextPutAll: aComment , separator]]. aRequest == #masterComment ifTrue: [aComment _ aClass supermostPrecodeCommentFor: aSelector. aComment isEmptyOrNil ifFalse: [aStream nextPutAll: aComment , separator]]. aRequest == #documentation ifTrue: [aComment _ aClass precodeCommentOrInheritedCommentFor: aSelector. aComment isEmptyOrNil ifFalse: [aStream nextPutAll: aComment , separator]]. aRequest == #timeStamp ifTrue: [stamp _ self timeStamp. aStream nextPutAll: (stamp size > 0 ifTrue: [stamp , separator] ifFalse: ['no timeStamp' , separator])]. aRequest == #messageCategory ifTrue: [aCategory _ aClass organization categoryOfElement: aSelector. aCategory ifNotNil: ["woud be nil for a method no longer present, e.g. in a recent-submissions browser" aStream nextPutAll: aCategory , separator]]. aRequest == #sendersCount ifTrue: [sendersCount _ (self systemNavigation allCallsOn: aSelector) size. sendersCount _ sendersCount == 1 ifTrue: ['1 sender'] ifFalse: [sendersCount printString , ' senders']. aStream nextPutAll: sendersCount , separator]. aRequest == #implementorsCount ifTrue: [implementorsCount _ self systemNavigation numberOfImplementorsOf: aSelector. implementorsCount _ implementorsCount == 1 ifTrue: ['1 implementor'] ifFalse: [implementorsCount printString , ' implementors']. aStream nextPutAll: implementorsCount , separator]. aRequest == #priorVersionsCount ifTrue: [self addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream]. aRequest == #priorTimeStamp ifTrue: [stamp _ VersionsBrowser timeStampFor: aSelector class: aClass reverseOrdinal: 2. stamp ifNotNil: [aStream nextPutAll: 'prior time stamp: ' , stamp , separator]]. aRequest == #recentChangeSet ifTrue: [aString _ ChangeSorter mostRecentChangeSetWithChangeForClass: aClass selector: aSelector. aString size > 0 ifTrue: [aStream nextPutAll: aString , separator]]. aRequest == #allChangeSets ifTrue: [aList _ ChangeSorter allChangeSetsWithClass: aClass selector: aSelector. aList size > 0 ifTrue: [aList size = 1 ifTrue: [aStream nextPutAll: 'only in change set '] ifFalse: [aStream nextPutAll: 'in change sets: ']. aList do: [:aChangeSet | aStream nextPutAll: aChangeSet name , ' ']] ifFalse: [aStream nextPutAll: 'in no change set']. aStream nextPutAll: separator]]. ^ aStream contents! ! !CodeHolder methodsFor: 'annotation' stamp: 'RAA 1/13/2001 07:20'! annotationPaneMenu: aMenu shifted: shifted ^ aMenu labels: 'change pane size' lines: #() selections: #(toggleAnnotationPaneSize)! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 9/27/1999 14:13'! annotationRequests ^ Preferences defaultAnnotationRequests! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 2/22/2001 10:02'! annotationSeparator "Answer the separator to be used between annotations" ^ ' '! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 9/28/2001 08:43'! defaultAnnotationPaneHeight "Answer the receiver's preferred default height for new annotation panes." ^ Preferences parameterAt: #defaultAnnotationPaneHeight ifAbsentPut: [25]! ! !CodeHolder methodsFor: 'annotation' stamp: 'sw 9/28/2001 08:44'! defaultButtonPaneHeight "Answer the user's preferred default height for new button panes." ^ Preferences parameterAt: #defaultButtonPaneHeight ifAbsentPut: [25]! ! !CodeHolder methodsFor: 'categories' stamp: 'sd 2/1/2004 17:56'! categoryFromUserWithPrompt: aPrompt for: aClass "self new categoryFromUserWithPrompt: 'testing' for: SystemDictionary" | labels myCategories reject lines cats newName menuIndex | labels _ OrderedCollection with: 'new...'. labels addAll: (myCategories _ aClass organization categories asSortedCollection: [:a :b | a asLowercase < b asLowercase]). reject _ myCategories asSet. reject add: ClassOrganizer nullCategory; add: ClassOrganizer default. lines _ OrderedCollection with: 1 with: (myCategories size + 1). aClass allSuperclasses do: [:cls | cats _ cls organization categories reject: [:cat | reject includes: cat]. cats isEmpty ifFalse: [lines add: labels size. labels addAll: (cats asSortedCollection: [:a :b | a asLowercase < b asLowercase]). reject addAll: cats]]. newName _ (labels size = 1 or: [menuIndex _ (PopUpMenu labelArray: labels lines: lines) startUpWithCaption: aPrompt. menuIndex = 0 ifTrue: [^ nil]. menuIndex = 1]) ifTrue: [FillInTheBlank request: 'Please type new category name' initialAnswer: 'category name'] ifFalse: [labels at: menuIndex]. ^ newName ifNotNil: [newName asSymbol]! ! !CodeHolder methodsFor: 'categories' stamp: 'sd 2/1/2004 17:55'! categoryOfCurrentMethod "Answer the category that owns the current method. If unable to determine a category, answer nil." | aClass aSelector | ^ (aClass _ self selectedClassOrMetaClass) ifNotNil: [(aSelector _ self selectedMessageName) ifNotNil: [aClass whichCategoryIncludesSelector: aSelector]]! ! !CodeHolder methodsFor: 'categories' stamp: 'sd 2/1/2004 17:55'! changeCategory "Present a menu of the categories of messages for the current class, and let the user choose a new category for the current message" | aClass aSelector | (aClass _ self selectedClassOrMetaClass) ifNotNil: [(aSelector _ self selectedMessageName) ifNotNil: [(self letUserReclassify: aSelector in: aClass) ifTrue: ["ChangeSet current reorganizeClass: aClass." "Decided on further review that the above, when present, could cause more unexpected harm than good" self methodCategoryChanged]]]! ! !CodeHolder methodsFor: 'categories' stamp: 'sd 2/1/2004 17:54'! letUserReclassify: anElement in: aClass "Put up a list of categories and solicit one from the user. Answer true if user indeed made a change, else false" | currentCat newCat | currentCat _ aClass organization categoryOfElement: anElement. newCat _ self categoryFromUserWithPrompt: 'choose category (currently "', currentCat, '")' for: aClass. (newCat ~~ nil and: [newCat ~= currentCat]) ifTrue: [aClass organization classify: anElement under: newCat suppressIfDefault: false. ^ true] ifFalse: [^ false]! ! !CodeHolder methodsFor: 'categories' stamp: 'sw 9/27/1999 14:11'! methodCategoryChanged self changed: #annotation! ! !CodeHolder methodsFor: 'categories' stamp: 'sw 3/22/2000 23:04'! selectedMessageCategoryName "Answer the name of the message category of the message of the currently selected context." ^ self selectedClass organization categoryOfElement: self selectedMessageName! ! !CodeHolder methodsFor: 'contents' stamp: 'sw 12/11/2000 10:42'! commentContents "documentation for the selected method" | poss aClass aSelector | ^ (poss _ (aClass _ self selectedClassOrMetaClass) ifNil: ['----'] ifNotNil: [(aSelector _ self selectedMessageName) ifNil: ['---'] ifNotNil: [(aClass precodeCommentOrInheritedCommentFor: aSelector)", String cr, String cr, self timeStamp" "which however misses comments that are between the temps declaration and the body of the method; those are picked up by aClass commentOrInheritedCommentFor: aSelector but that method will get false positives from comments *anywhere* in the method source"]]) isEmptyOrNil ifTrue: [aSelector ifNotNil: [((aClass methodHeaderFor: aSelector), ' Has no comment') asText makeSelectorBoldIn: aClass] ifNil: ['Hamna']] ifFalse: [aSelector ifNotNil: [((aClass methodHeaderFor: aSelector), ' ', poss) asText makeSelectorBoldIn: aClass] ifNil: [poss]]! ! !CodeHolder methodsFor: 'contents' stamp: 'di 10/1/2001 22:25'! contents "Answer the source code or documentation for the selected method" self showingByteCodes ifTrue: [^ self selectedBytecodes]. self showingDocumentation ifTrue: [^ self commentContents]. ^ self selectedMessage! ! !CodeHolder methodsFor: 'contents' stamp: 'rhi 12/3/2001 22:25'! contentsChanged super contentsChanged. self changed: #annotation! ! !CodeHolder methodsFor: 'contents' stamp: 'sw 5/20/2001 10:21'! contentsSymbol "Answer a symbol indicating what kind of content should be shown for the method; for normal showing of source code, this symbol is #source. A nil value in the contentsSymbol slot will be set to #source by this method" ^ contentsSymbol ifNil: [contentsSymbol _ Preferences printAlternateSyntax ifTrue: [#altSyntax] ifFalse: [Preferences browseWithPrettyPrint ifTrue: [Preferences colorWhenPrettyPrinting ifTrue: [#colorPrint] ifFalse: [#prettyPrint]] ifFalse: [#source]]]! ! !CodeHolder methodsFor: 'contents' stamp: 'sw 11/29/2000 09:51'! contentsSymbol: aSymbol "Set the contentsSymbol as indicated. #source means to show source code, #comment means to show the first comment found in the source code" contentsSymbol _ aSymbol! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 7/30/2001 16:31'! abbreviatedWordingFor: aButtonSelector "Answer the abbreviated form of wording, from a static table which you're welcome to edit. Answer nil if there is no entry -- in which case the long firm will be used on the corresponding browser button." #( (browseMethodFull 'browse') (browseSendersOfMessages 'senders') (browseMessages 'impl') (browseVersions 'vers') (methodHierarchy 'inher') (classHierarchy 'hier') (browseInstVarRefs 'iVar') (browseClassVarRefs 'cVar') (offerMenu 'menu')) do: [:pair | pair first == aButtonSelector ifTrue: [^ pair second]]. ^ nil! ! !CodeHolder methodsFor: 'commands' stamp: 'sd 5/23/2003 14:35'! adoptMessageInCurrentChangeset "Add the receiver's method to the current change set if not already there" self setClassAndSelectorIn: [:cl :sel | cl ifNotNil: [ChangeSet current adoptSelector: sel forClass: cl. self changed: #annotation]] ! ! !CodeHolder methodsFor: 'commands' stamp: 'sd 4/16/2003 09:33'! browseImplementors "Create and schedule a message set browser on all implementors of the currently selected message selector. Do nothing if no message is selected." | aMessageName | (aMessageName _ self selectedMessageName) ifNotNil: [self systemNavigation browseAllImplementorsOf: aMessageName]! ! !CodeHolder methodsFor: 'commands' stamp: 'nk 6/26/2003 21:43'! browseSenders "Create and schedule a message set browser on all senders of the currently selected message selector. Of there is no message currently selected, offer a type-in" self sendQuery: #browseAllCallsOn: to: self systemNavigation! ! !CodeHolder methodsFor: 'commands' stamp: 'BG 10/28/2003 20:51'! copyUpOrCopyDown "Used to copy down code from a superclass to a subclass or vice-versa in one easy step, if you know what you're doing. Prompt the user for which class to copy down or copy up to, then spawn a fresh browser for that class, with the existing code planted in it, and with the existing method category also established." | | Smalltalk isMorphic ifFalse: [^ self inform: 'Sorry, for the moment you have to be in Morphic to use this feature.'].! ! !CodeHolder methodsFor: 'commands' stamp: 'BG 10/28/2003 20:51'! makeSampleInstance | aClass nonMetaClass anInstance | (aClass _ self selectedClassOrMetaClass) ifNil: [^ self]. nonMetaClass _ aClass theNonMetaClass. anInstance _ self sampleInstanceOfSelectedClass. (anInstance isNil and: [nonMetaClass ~~ UndefinedObject]) ifTrue: [^ self inform: 'Sorry, cannot make an instance of ', nonMetaClass name]. (Smalltalk isMorphic and: [anInstance isMorph]) ifTrue: [] ifFalse: [anInstance inspectWithLabel: 'An instance of ', nonMetaClass name]! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 5/18/2001 17:51'! offerMenu "Offer a menu to the user from the bar of tool buttons" self offerDurableMenuFrom: #messageListMenu:shifted: shifted: false! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 2/27/2001 12:14'! offerShiftedClassListMenu "Offer the shifted class-list menu." ^ self offerMenuFrom: #classListMenu:shifted: shifted: true! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 2/27/2001 12:15'! offerUnshiftedClassListMenu "Offer the shifted class-list menu." ^ self offerMenuFrom: #classListMenu:shifted: shifted: false! ! !CodeHolder methodsFor: 'commands' stamp: 'nb 6/17/2003 12:25'! removeClass "Remove the selected class from the system, at interactive user request. Make certain the user really wants to do this, since it is not reversible. Answer true if removal actually happened." | message className classToRemove result | self okToChange ifFalse: [^ false]. classToRemove _ self selectedClassOrMetaClass ifNil: [Beeper beep. ^ false]. classToRemove _ classToRemove theNonMetaClass. className _ classToRemove name. message _ 'Are you certain that you want to REMOVE the class ', className, ' from the system?'. (result _ self confirm: message) ifTrue: [classToRemove subclasses size > 0 ifTrue: [(self confirm: 'class has subclasses: ' , message) ifFalse: [^ false]]. classToRemove removeFromSystem. self changed: #classList. true]. ^ result! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 3/6/2001 15:18'! shiftedYellowButtonActivity "Offer the shifted selector-list menu" ^ self offerMenuFrom: #messageListMenu:shifted: shifted: true! ! !CodeHolder methodsFor: 'commands' stamp: 'sd 4/29/2003 13:09'! showUnreferencedClassVars "Search for all class variables known to the selected class, and put up a list of those that have no references anywhere in the system. The search includes superclasses, so that you don't need to navigate your way to the class that defines each class variable in order to determine whether it is unreferenced" | cls aList aReport | (cls _ self selectedClass) ifNil: [^ self]. aList _ self systemNavigation allUnreferencedClassVariablesOf: cls. aList size == 0 ifTrue: [^ self inform: 'There are no unreferenced class variables in ' , cls name]. aReport _ String streamContents: [:aStream | aStream nextPutAll: 'Unreferenced class variable(s) in ' , cls name; cr. aList do: [:el | aStream tab; nextPutAll: el; cr]]. Transcript cr; show: aReport. (SelectionMenu labels: aList selections: aList) startUpWithCaption: 'Unreferenced class variables in ' , cls name! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 9/26/2001 01:55'! showUnreferencedInstVars "Search for all instance variables known to the selected class, and put up a list of those that have no references anywhere in the system. The search includes superclasses, so that you don't need to navigate your way to the class that defines each inst variable in order to determine whether it is unreferenced" | cls aList aReport | (cls _ self selectedClassOrMetaClass) ifNil: [^ self]. aList _ cls allUnreferencedInstanceVariables. aList size == 0 ifTrue: [^ self inform: 'There are no unreferenced instance variables in ', cls name]. aReport _ String streamContents: [:aStream | aStream nextPutAll: 'Unreferenced instance variable(s) in ', cls name; cr. aList do: [:el | aStream tab; nextPutAll: el; cr]]. Transcript cr; show: aReport. (SelectionMenu labels: aList selections: aList) startUpWithCaption: 'Unreferenced instance variables in ', cls name! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 2/22/2001 06:38'! spawn: aString "Create and schedule a spawned message category browser for the currently selected message category. The initial text view contains the characters in aString. In the spawned browser, preselect the current selector (if any) as the going-in assumption, though upon acceptance this will often change" | newBrowser aCategory aClass | (aClass _ self selectedClassOrMetaClass) isNil ifTrue: [^ aString isEmptyOrNil ifFalse: [(Workspace new contents: aString) openLabel: 'spawned workspace']]. (aCategory _ self categoryOfCurrentMethod) ifNil: [self buildClassBrowserEditString: aString] ifNotNil: [newBrowser _ Browser new setClass: aClass selector: self selectedMessageName. self suggestCategoryToSpawnedBrowser: newBrowser. Browser openBrowserView: (newBrowser openMessageCatEditString: aString) label: 'category "', aCategory, '" in ', newBrowser selectedClassOrMetaClassName]! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 12/4/2000 12:07'! spawnFullProtocol "Create and schedule a new protocol browser on the currently selected class or meta." | aClassOrMetaclass | (aClassOrMetaclass _ self selectedClassOrMetaClass) ifNotNil: [ProtocolBrowser openFullProtocolForClass: aClassOrMetaclass]! ! !CodeHolder methodsFor: 'commands' stamp: 'BG 10/28/2003 20:52'! spawnHierarchy "Create and schedule a new hierarchy browser on the currently selected class or meta." | newBrowser aSymbol aBehavior messageCatIndex selectedClassOrMetaClass | (selectedClassOrMetaClass _ self selectedClassOrMetaClass) ifNil: [^ self]. newBrowser _ HierarchyBrowser new initHierarchyForClass: selectedClassOrMetaClass. ((aSymbol _ self selectedMessageName) notNil and: [(MessageSet isPseudoSelector: aSymbol) not]) ifTrue: [aBehavior _ selectedClassOrMetaClass. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. newBrowser messageCategoryListIndex: messageCatIndex + 1. newBrowser messageListIndex: ((aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol)]. Browser openBrowserView: (newBrowser openSystemCatEditString: nil) label: newBrowser labelString. ! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 5/8/2000 14:24'! spawnProtocol | aClassOrMetaclass | "Create and schedule a new protocol browser on the currently selected class or meta." (aClassOrMetaclass _ self selectedClassOrMetaClass) ifNotNil: [ProtocolBrowser openSubProtocolForClass: aClassOrMetaclass]! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 3/20/2001 15:10'! spawnToClass: aClass "Used to copy down code from a superclass to a subclass in one easy step, if you know what you're doing. Spawns a new message-category browser for the indicated class, populating it with the source code seen in the current tool." | aCategory newBrowser org | (aCategory _ self categoryOfCurrentMethod) ifNil: [self buildClassBrowserEditString: self contents] ifNotNil: [((org _ aClass organization) categories includes: aCategory) ifFalse: [org addCategory: aCategory]. newBrowser _ Browser new setClass: aClass selector: nil. newBrowser selectMessageCategoryNamed: aCategory. Browser openBrowserView: (newBrowser openMessageCatEditString: self contents) label: 'category "', aCategory, '" in ', newBrowser selectedClassOrMetaClassName]! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 3/20/2001 15:11'! spawnToCollidingClass: aClass "Potentially used to copy down code from a superclass to a subclass in one easy step, in the case where the given class already has its own version of code, which would consequently be clobbered if the spawned code were accepted." self inform: 'That would be destructive of some pre-existing code already in that class for this selector. For the moment, we will not let you do this to yourself.'! ! !CodeHolder methodsFor: 'commands' stamp: 'sw 3/6/2001 15:19'! unshiftedYellowButtonActivity "Offer the unshifted shifted selector-list menu" ^ self offerMenuFrom: #messageListMenu:shifted: shifted: false! ! !CodeHolder methodsFor: 'construction' stamp: 'sw 1/4/2001 12:34'! buildClassBrowserEditString: aString "Create and schedule a new class browser for the current selection, with initial textual contents set to aString. This is used specifically in spawning where a class is established but a method-category is not." | newBrowser | newBrowser _ Browser new. newBrowser setClass: self selectedClassOrMetaClass selector: nil. newBrowser editSelection: #newMessage. Browser openBrowserView: (newBrowser openOnClassWithEditString: aString) label: 'Class Browser: ', self selectedClassOrMetaClass name ! ! !CodeHolder methodsFor: 'controls' stamp: 'BG 10/29/2003 09:43'! buttonWithSelector: aSelector "If receiver has a control button with the given action selector answer it, else answer nil. morphic only at this point" ^nil! ! !CodeHolder methodsFor: 'controls' stamp: 'sw 5/19/2001 01:12'! codePaneProvenanceString "Answer a string that reports on code-pane-provenance" | symsAndWordings | (symsAndWordings _ self contentsSymbolQuints) do: [:aQuad | contentsSymbol == aQuad first ifTrue: [^ aQuad fourth]]. ^ symsAndWordings first fourth "default to plain source, for example if nil as initially"! ! !CodeHolder methodsFor: 'controls' stamp: 'sw 11/13/2001 07:48'! contentsSymbolQuints "Answer a list of quintuplets representing information on the alternative views available in the code pane first element: the contentsSymbol used second element: the selector to call when this item is chosen. third element: the selector to call to obtain the wording of the menu item. fourth element: the wording to represent this view fifth element: balloon help A hypen indicates a need for a seperator line in a menu of such choices" ^ #( (source togglePlainSource showingPlainSourceString 'source' 'the textual source code as writen') (documentation toggleShowDocumentation showingDocumentationString 'documentation' 'the first comment in the method') - (prettyPrint togglePrettyPrint prettyPrintString 'prettyPrint' 'the method source presented in a standard text format') (colorPrint toggleColorPrint colorPrintString 'colorPrint' 'the method source in a standard text format with colors to distinguish structural parts') (altSyntax toggleAltSyntax showingAltSyntaxString 'altSyntax' 'alternative syntax') - (showDiffs toggleRegularDiffing showingRegularDiffsString 'showDiffs' 'the textual source diffed from its prior version') (prettyDiffs togglePrettyDiffing showingPrettyDiffsString 'prettyDiffs' 'formatted textual source diffed from formatted form of prior version') - (decompile toggleDecompile showingDecompileString 'decompile' 'source code decompiled from byteCodes') (byteCodes toggleShowingByteCodes showingByteCodesString 'byteCodes' 'the bytecodes that comprise the compiled method') - (tiles toggleShowingTiles showingTilesString 'tiles' 'universal tiles representing the method'))! ! !CodeHolder methodsFor: 'controls' stamp: 'sw 1/5/2001 07:19'! decorateButtons "Change screen feedback for any buttons in the UI of the receiver that may wish it. Initially, it is only the Inheritance button that is decorated, but one can imagine others." self decorateForInheritance ! ! !CodeHolder methodsFor: 'controls' stamp: 'nk 7/6/2003 08:29'! decorateForInheritance "Check to see if the currently-viewed method has a super send or an override, and if so, change screen feedback, unless the #decorateBrowserButtons says not to." | aColor aButton flags | (aButton _ self inheritanceButton) ifNil: [^ self]. ((currentCompiledMethod isKindOf: CompiledMethod) and: [Preferences decorateBrowserButtons]) ifFalse: [^aButton offColor: Color transparent]. "This table duplicates the old logic, but adds two new colors for the cases where there is a superclass definition, but this method doesn't call it." flags _ 0. self isThisAnOverride ifTrue: [ flags _ flags bitOr: 4 ]. currentCompiledMethod sendsToSuper ifTrue: [ flags _ flags bitOr: 2 ]. self isThereAnOverride ifTrue: [ flags _ flags bitOr: 1 ]. aColor _ { Color transparent. Color tan lighter. Color green muchLighter. Color blue muchLighter. Color red muchLighter. "has super but doesn't call it" (Color r: 0.94 g: 0.823 b: 0.673). "has sub; has super but doesn't call it" Color green muchLighter. Color blue muchLighter. } at: flags + 1. aButton offColor: aColor! ! !CodeHolder methodsFor: 'controls' stamp: 'sw 1/25/2001 14:44'! inheritanceButton "If receiver has an Inheritance button, answer it, else answer nil. morphic only at this point" ^ self buttonWithSelector: #methodHierarchy! ! !CodeHolder methodsFor: 'controls' stamp: 'nk 7/7/2003 11:39'! optionalButtonPairs "Answer a tuple (formerly pairs) defining buttons, in the format: button label selector to send help message" | aList | aList _ #( ('browse' browseMethodFull 'view this method in a browser') ('senders' browseSendersOfMessages 'browse senders of...') ('implementors' browseMessages 'browse implementors of...') ('versions' browseVersions 'browse versions')), (Preferences decorateBrowserButtons ifTrue: [{#('inheritance' methodHierarchy 'browse method inheritance green: sends to super tan: has override(s) mauve: both of the above pink: is an override but doesn''t call super pinkish tan: has override(s), also is an override but doesn''t call super' )}] ifFalse: [{#('inheritance' methodHierarchy 'browse method inheritance')}]), #( ('hierarchy' classHierarchy 'browse class hierarchy') ('inst vars' browseInstVarRefs 'inst var refs...') ('class vars' browseClassVarRefs 'class var refs...')). ^ aList! ! !CodeHolder methodsFor: 'controls' stamp: 'sw 11/13/2001 09:12'! sourceAndDiffsQuintsOnly "Answer a list of quintuplets representing information on the alternative views available in the code pane for the case where the only plausible choices are showing source or either of the two kinds of diffs" ^ #( (source togglePlainSource showingPlainSourceString 'source' 'the textual source code as writen') (showDiffs toggleRegularDiffing showingRegularDiffsString 'showDiffs' 'the textual source diffed from its prior version') (prettyDiffs togglePrettyDiffing showingPrettyDiffsString 'prettyDiffs' 'formatted textual source diffed from formatted form of prior version'))! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 9/5/2001 13:36'! defaultDiffsSymbol "Answer the code symbol to use when generically switching to diffing" ^ Preferences diffsWithPrettyPrint ifTrue: [#prettyDiffs] ifFalse: [#showDiffs]! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/20/2001 21:14'! diffFromPriorSourceFor: sourceCode "If there is a prior version of source for the selected method, return a diff, else just return the source code" | prior | ^ (prior _ self priorSourceOrNil) ifNil: [sourceCode] ifNotNil: [TextDiffBuilder buildDisplayPatchFrom: prior to: sourceCode inClass: self selectedClass prettyDiffs: self showingPrettyDiffs]! ! !CodeHolder methodsFor: 'diffs' stamp: 'BG 10/29/2003 07:56'! restoreTextualCodingPane "If the receiver is showing tiles, restore the textual coding pane" contentsSymbol _ #source.! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:49'! showDiffs "Answer whether the receiver is showing diffs of source code. The preferred protocol here is #showingRegularDiffs, but this message is still sent by some preexisting buttons so is retained." ^ contentsSymbol == #showDiffs ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 9/5/2001 13:36'! showDiffs: aBoolean "Set whether I'm showing diffs as indicated; use the global preference to determine which kind of diffs to institute." self showingAnyKindOfDiffs ifFalse: [aBoolean ifTrue: [contentsSymbol _ self defaultDiffsSymbol]] ifTrue: [aBoolean ifFalse: [contentsSymbol _ #source]]. self setContentsToForceRefetch. self contentsChanged! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/22/2001 18:25'! showPrettyDiffs: aBoolean "Set whether I'm showing pretty diffs as indicated" self showingPrettyDiffs ifFalse: [aBoolean ifTrue: [contentsSymbol _ #prettyDiffs]] ifTrue: [aBoolean ifFalse: [contentsSymbol _ #source]]. self setContentsToForceRefetch. self contentsChanged! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:50'! showRegularDiffs: aBoolean "Set whether I'm showing regular diffs as indicated" self showingRegularDiffs ifFalse: [aBoolean ifTrue: [contentsSymbol _ #showDiffs]] ifTrue: [aBoolean ifFalse: [contentsSymbol _ #source]]. self setContentsToForceRefetch. self contentsChanged! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 9/5/2001 13:32'! showingAnyKindOfDiffs "Answer whether the receiver is currently set to show any kind of diffs" ^ #(showDiffs prettyDiffs) includes: contentsSymbol! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 09:10'! showingDiffsString "Answer a string representing whether I'm showing diffs. Not sent any more but retained so that prexisting buttons that sent this will not raise errors." ^ (self showingRegularDiffs ifTrue: ['<yes>'] ifFalse: ['<no>']), 'showDiffs'! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/19/2001 00:07'! showingPrettyDiffs "Answer whether the receiver is showing pretty diffs of source code" ^ contentsSymbol == #prettyDiffs ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/22/2001 16:41'! showingPrettyDiffsString "Answer a string representing whether I'm showing pretty diffs" ^ (self showingPrettyDiffs ifTrue: ['<yes>'] ifFalse: ['<no>']), 'prettyDiffs'! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:07'! showingRegularDiffs "Answer whether the receiver is showing regular diffs of source code" ^ contentsSymbol == #showDiffs ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:43'! showingRegularDiffsString "Answer a string representing whether I'm showing regular diffs" ^ (self showingRegularDiffs ifTrue: ['<yes>'] ifFalse: ['<no>']), 'showDiffs'! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/18/2001 23:50'! toggleColorPrint "Toggle whether color-print is in effect in the code pane" self restoreTextualCodingPane. self okToChange ifTrue: [self showingColorPrint ifTrue: [contentsSymbol _ #source] ifFalse: [contentsSymbol _ #colorPrint]. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 1/18/2001 13:58'! toggleDiff "Retained for backward compatibility with existing buttons in existing images" self toggleDiffing! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:30'! toggleDiffing "Toggle whether diffs should be shown in the code pane. If any kind of diffs were being shown, stop showing diffs. If no kind of diffs were being shown, start showing whatever kind of diffs are called for by default." | wasShowingDiffs | self okToChange ifTrue: [wasShowingDiffs _ self showingAnyKindOfDiffs. self restoreTextualCodingPane. self showDiffs: wasShowingDiffs not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/18/2001 19:57'! togglePlainSource "Toggle whether plain source shown in the code pane" | wasShowingPlainSource | self okToChange ifTrue: [wasShowingPlainSource _ self showingPlainSource. self restoreTextualCodingPane. wasShowingPlainSource ifTrue: [self showDocumentation: true] ifFalse: [contentsSymbol _ #source]. self setContentsToForceRefetch. self changed: #contents] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/19/2001 00:02'! togglePrettyDiffing "Toggle whether pretty-diffing should be shown in the code pane" | wasShowingDiffs | self okToChange ifTrue: [wasShowingDiffs _ self showingPrettyDiffs. self restoreTextualCodingPane. self showPrettyDiffs: wasShowingDiffs not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 5/18/2001 19:54'! togglePrettyPrint "Toggle whether pretty-print is in effectin the code pane" self restoreTextualCodingPane. self okToChange ifTrue: [self showingPrettyPrint ifTrue: [contentsSymbol _ #source] ifFalse: [contentsSymbol _ #prettyPrint]. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:27'! toggleRegularDiffing "Toggle whether regular-diffing should be shown in the code pane" | wasShowingDiffs | self okToChange ifTrue: [wasShowingDiffs _ self showingRegularDiffs. self restoreTextualCodingPane. self showRegularDiffs: wasShowingDiffs not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'diffs' stamp: 'sw 11/13/2001 07:24'! wantsDiffFeedback "Answer whether the receiver is showing diffs of source code" ^ self showingAnyKindOfDiffs! ! !CodeHolder methodsFor: 'misc' stamp: 'nk 4/10/2001 07:52'! getSelectorAndSendQuery: querySelector to: queryPerformer "Obtain a selector relevant to the current context, and then send the querySelector to the queryPerformer with the selector obtained as its argument. If no message is currently selected, then obtain a method name from a user type-in" self getSelectorAndSendQuery: querySelector to: queryPerformer with: { }. ! ! !CodeHolder methodsFor: 'misc' stamp: 'nk 4/10/2001 07:53'! getSelectorAndSendQuery: querySelector to: queryPerformer with: queryArgs "Obtain a selector relevant to the current context, and then send the querySelector to the queryPerformer with the selector obtained and queryArgs as its arguments. If no message is currently selected, then obtain a method name from a user type-in" | strm array | strm _ WriteStream on: (array _ Array new: queryArgs size + 1). strm nextPut: nil. strm nextPutAll: queryArgs. self selectedMessageName ifNil: [ | selector | selector _ FillInTheBlank request: 'Type selector:' initialAnswer: 'flag:'. ^ selector isEmptyOrNil ifFalse: [ (Symbol hasInterned: selector ifTrue: [ :aSymbol | array at: 1 put: aSymbol. queryPerformer perform: querySelector withArguments: array]) ifFalse: [ self inform: 'no such selector'] ] ]. self selectMessageAndEvaluate: [:selector | array at: 1 put: selector. queryPerformer perform: querySelector withArguments: array ]! ! !CodeHolder methodsFor: 'misc' stamp: 'nk 7/6/2003 07:49'! isThereAnOverride "Answer whether any subclass of my selected class implements my selected selector" | aName aClass | aName _ self selectedMessageName ifNil: [^ false]. aClass _ self selectedClassOrMetaClass. aClass allSubclassesDo: [ :cls | (cls includesSelector: aName) ifTrue: [ ^true ]]. ^ false! ! !CodeHolder methodsFor: 'misc' stamp: 'nk 7/6/2003 07:52'! isThisAnOverride "Answer whether any superclass of my selected class implements my selected selector" | aName aClass | aName _ self selectedMessageName ifNil: [^ false]. aClass _ self selectedClassOrMetaClass. aClass allSuperclassesDo: [ :cls | (cls includesSelector: aName) ifTrue: [ ^true ]]. ^ false! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 9/27/2001 01:26'! modelWakeUpIn: aWindow "The window has been activated. Respond to possible changes that may have taken place while it was inactive" self updateListsAndCodeIn: aWindow. self decorateButtons. self refreshAnnotation. super modelWakeUpIn: aWindow! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 11/13/2001 07:42'! okayToAccept "Answer whether it is okay to accept the receiver's input" self showingDocumentation ifTrue: [self inform: 'Sorry, for the moment you can only submit changes here when you are showing source. Later, you will be able to edit the isolated comment here and save it back, but only if YOU implement it!!.'. ^ false]. self showingAnyKindOfDiffs ifFalse: [^ true]. ^ SelectionMenu confirm: 'Caution!! You are "showing diffs" here, so there is a danger that some of the text in the code pane is contaminated by the "diff" display' trueChoice: 'accept anyway -- I''ll take my chances' falseChoice: 'um, let me reconsider' ! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 9/27/1999 14:09'! priorSourceOrNil "If the currently-selected method has a previous version, return its source, else return nil" | aClass aSelector changeRecords | (aClass _ self selectedClassOrMetaClass) ifNil: [^ nil]. (aSelector _ self selectedMessageName) ifNil: [^ nil]. changeRecords _ aClass changeRecordsAt: aSelector. (changeRecords == nil or: [changeRecords size <= 1]) ifTrue: [^ nil]. ^ (changeRecords at: 2) string ! ! !CodeHolder methodsFor: 'misc' stamp: 'BG 11/1/2003 13:26'! refreshAnnotation "If the receiver has an annotation pane that does not bear unaccepted edits, refresh it" (self dependents detect: [:m | (m inheritsFromAnyIn: #('PluggableTextView')) and: [m getTextSelector == #annotation]] ifNone: [nil]) ifNotNilDo: [:aPane | aPane hasUnacceptedEdits ifFalse: [aPane update: #annotation]]! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 5/22/2001 16:47'! refusesToAcceptCode "Answer whether receiver, given its current contentsSymbol, could accept code happily if asked to" ^ (#(byteCodes documentation altSyntax tiles) includes: self contentsSymbol)! ! !CodeHolder methodsFor: 'misc' stamp: 'tk 9/9/2000 21:08'! releaseCachedState "Can always be found again. Don't write on a file." currentCompiledMethod _ nil.! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 5/8/2000 12:34'! sampleInstanceOfSelectedClass | aClass | "Return a sample instance of the class currently being pointed at" (aClass _ self selectedClassOrMetaClass) ifNil: [^ nil]. ^ aClass theNonMetaClass initializedInstance! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 3/19/2001 06:06'! sendQuery: querySelector to: queryPerformer "Apply a query to the primary selector associated with the current context. If no such selection exists, obtain one by user type-in. Then send querySelector to queryPerformer with the selector as its argument." | aSelector aString | aSelector _ self selectedMessageName ifNil: [aString _FillInTheBlank request: 'Type selector:' initialAnswer: 'flag:'. ^ aString isEmptyOrNil ifFalse: [(Symbol hasInterned: aString ifTrue: [:aSymbol | queryPerformer perform: querySelector with: aSymbol]) ifFalse: [self inform: 'no such selector']]]. queryPerformer perform: querySelector with: aSelector! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 12/28/2000 15:32'! setClassAndSelectorIn: csBlock "Evaluate csBlock with my selected class and and selector as its arguments; provide nil arguments if I don't have a method currently selected" | aName | (aName _ self selectedMessageName) ifNil: [csBlock value: nil value: nil] ifNotNil: [csBlock value: self selectedClassOrMetaClass value: aName] ! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 2/22/2001 06:37'! suggestCategoryToSpawnedBrowser: aBrowser "aBrowser is a message-category browser being spawned from the receiver. Tell it what it needs to know to get its category info properly set up." aBrowser setOriginalCategoryIndexForCurrentMethod! ! !CodeHolder methodsFor: 'misc' stamp: 'sw 3/20/2001 09:26'! useSelector: incomingSelector orGetSelectorAndSendQuery: querySelector to: queryPerformer "If incomingSelector is not nil, use it, else obtain a selector from user type-in. Using the determined selector, send the query to the performer provided." | aSelector | incomingSelector ifNotNil: [queryPerformer perform: querySelector with: incomingSelector] ifNil: [aSelector _FillInTheBlank request: 'Type selector:' initialAnswer: 'flag:'. aSelector isEmptyOrNil ifFalse: [(Symbol hasInterned: aSelector ifTrue: [:aSymbol | queryPerformer perform: querySelector with: aSymbol]) ifFalse: [self inform: 'no such selector']]]! ! !CodeHolder methodsFor: 'self-updating' stamp: 'sw 7/31/2002 13:11'! didCodeChangeElsewhere "Determine whether the code for the currently selected method and class has been changed somewhere else." | aClass aSelector aCompiledMethod | currentCompiledMethod ifNil: [^ false]. (aClass _ self selectedClassOrMetaClass) ifNil: [^ false]. (aSelector _ self selectedMessageName) ifNil: [^ false]. aSelector == #Comment ifTrue: [^ currentCompiledMethod ~~ aClass organization commentRemoteStr]. ^ ((aCompiledMethod _ aClass compiledMethodAt: aSelector ifAbsent: [^ false]) ~~ currentCompiledMethod) and: [aCompiledMethod last ~= 0 "either not yet installed" or: [currentCompiledMethod last = 0 "or these methods don't have source pointers"]] ! ! !CodeHolder methodsFor: 'self-updating' stamp: 'sw 10/19/1999 08:37'! stepIn: aSystemWindow self updateListsAndCodeIn: aSystemWindow! ! !CodeHolder methodsFor: 'self-updating' stamp: 'sw 2/14/2001 15:34'! updateCodePaneIfNeeded "If the code for the currently selected method has changed underneath me, then update the contents of my code pane unless it holds unaccepted edits" self didCodeChangeElsewhere ifTrue: [self hasUnacceptedEdits ifFalse: [self setContentsToForceRefetch. self contentsChanged] ifTrue: [self changed: #codeChangedElsewhere]]! ! !CodeHolder methodsFor: 'self-updating' stamp: 'sw 10/19/1999 14:14'! updateListsAndCodeIn: aWindow super updateListsAndCodeIn: aWindow. self updateCodePaneIfNeeded! ! !CodeHolder methodsFor: 'self-updating' stamp: 'sw 10/20/1999 12:22'! wantsStepsIn: aWindow ^ Preferences smartUpdating! ! !CodeHolder methodsFor: 'what to show' stamp: 'ssa 9/3/2008 11:02'! addContentsTogglesTo: aMenu "Add updating menu toggles governing contents to aMenu." self contentsSymbolQuints do: [:aQuint | aQuint == #- ifTrue: [aMenu addLine] ifFalse: [Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu add: (('<yes>*' match: (self perform: aQuint third)) ifTrue: ['*'] ifFalse: ['']), aQuint fourth target: self selector: #contentsSymbol: argumentList: { aQuint first } ]]]! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/22/2001 16:36'! colorPrintString "Answer whether the receiver is showing colorPrint" ^ (self showingColorPrint ifTrue: ['<yes>'] ifFalse: ['<no>']) , 'colorPrint'! ! !CodeHolder methodsFor: 'what to show' stamp: 'ssa 9/3/2008 10:29'! offerWhatToShowMenu "Offer a menu governing what to show" | aMenu | Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu := CustomMenu new. self addContentsTogglesTo: aMenu. aMenu title: 'What to show' translated. aMenu invokeOn: self. self changed: #contents ]! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/22/2001 16:36'! prettyPrintString "Answer whether the receiver is showing pretty-print" ^ ((contentsSymbol == #prettyPrint) ifTrue: ['<yes>'] ifFalse: ['<no>']), 'prettyPrint'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 2/14/2001 15:25'! setContentsToForceRefetch "Set the receiver's contents such that on the next update the contents will be formulated afresh. This is a critical and obscure difference between Browsers on the one hand and MessageSets on the other, and has over the years been the source of much confusion and much difficulty. By centralizing the different handling here, we don't need so many idiosyncratic overrides in MessageSet any more" contents _ nil! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 09:26'! showAltSyntax: aBoolean "Set the decompile toggle as indicated" self contentsSymbol: (aBoolean ifFalse: [#source] ifTrue: [#altSyntax])! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 21:13'! showByteCodes: aBoolean "Get into or out of bytecode-showoing mode" self okToChange ifFalse: [^ self changed: #flash]. aBoolean ifTrue: [contentsSymbol _ #byteCodes] ifFalse: [contentsSymbol == #byteCodes ifTrue: [contentsSymbol _ #source]]. self contentsChanged! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 12/5/2000 11:32'! showComment "Answer whether the receiver should show documentation rather than, say, source code" ^ self contentsSymbol == #documentation ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 09:14'! showDecompile: aBoolean "Set the decompile toggle as indicated" self contentsSymbol: (aBoolean ifFalse: [#source] ifTrue: [#decompile])! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 12/5/2000 12:25'! showDocumentation: aBoolean "Set the showDocumentation toggle as indicated" self contentsSymbol: (aBoolean ifFalse: [#source] ifTrue: [#documentation])! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 09:27'! showingAltSyntax "Answer whether the receiver should show alt syntax rather than, say, source code" ^ self contentsSymbol == #altSyntax ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/22/2001 16:37'! showingAltSyntaxString "Answer a string characerizing whether altSyntax is showing" ^ (self showingAltSyntax ifTrue: ['<yes>'] ifFalse: ['<no>']), 'altSyntax'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 18:05'! showingByteCodes "Answer whether the receiver is showing bytecodes" ^ contentsSymbol == #byteCodes! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/22/2001 18:28'! showingByteCodesString "Answer whether the receiver is showing bytecodes" ^ (self showingByteCodes ifTrue: ['<yes>'] ifFalse: ['<no>']), 'byteCodes'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 23:50'! showingColorPrint "Answer whether the receiver is showing color-pretty-print" ^ contentsSymbol == #colorPrint! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 06:52'! showingDecompile "Answer whether the receiver should show decompile rather than, say, source code" ^ self contentsSymbol == #decompile ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 06:50'! showingDecompileString "Answer a string characerizing whether decompilation is showing" ^ (self showingDecompile ifTrue: ['<yes>'] ifFalse: ['<no>']), 'decompile'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 12/5/2000 12:12'! showingDocumentation "Answer whether the receiver should show documentation rather than, say, source code" ^ self contentsSymbol == #documentation ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 20:05'! showingDocumentationString "Answer a string characerizing whether documentation is showing" ^ (self showingDocumentation ifTrue: ['<yes>'] ifFalse: ['<no>']), 'documentation'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 19:43'! showingPlainSource "Answer whether the receiver is showing plain source" ^ contentsSymbol == #source! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/22/2001 09:31'! showingPlainSourceString "Answer a string telling whether the receiver is showing plain source" ^ (self showingPlainSource ifTrue: ['<yes>'] ifFalse: ['<no>']), 'source'! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 18:36'! showingPrettyPrint "Answer whether the receiver is showing pretty-print" ^ contentsSymbol == #prettyPrint! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 12/5/2000 11:48'! showingSource "Answer whether the receiver is currently showing source code" ^ self contentsSymbol == #source ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 09:28'! toggleAltSyntax "Toggle the setting of the showingAltSyntax flag, unless there are unsubmitted edits that the user declines to discard" | wasShowing | self okToChange ifTrue: [wasShowing _ self showingAltSyntax. self restoreTextualCodingPane. self showAltSyntax: wasShowing not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/20/2001 06:48'! toggleDecompile "Toggle the setting of the showingDecompile flag, unless there are unsubmitted edits that the user declines to discard" | wasShowing | self okToChange ifTrue: [wasShowing _ self showingDecompile. self restoreTextualCodingPane. self showDecompile: wasShowing not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 20:15'! toggleShowDocumentation "Toggle the setting of the showingDocumentation flag, unless there are unsubmitted edits that the user declines to discard" | wasShowing | self okToChange ifTrue: [wasShowing _ self showingDocumentation. self restoreTextualCodingPane. self showDocumentation: wasShowing not. self setContentsToForceRefetch. self contentsChanged] ! ! !CodeHolder methodsFor: 'what to show' stamp: 'sw 5/18/2001 20:09'! toggleShowingByteCodes "Toggle whether the receiver is showing bytecodes" self restoreTextualCodingPane. self showByteCodes: self showingByteCodes not. self setContentsToForceRefetch. self contentsChanged! ! !CodeHolder methodsFor: 'tiles' stamp: 'ssa 9/3/2008 11:03'! addModelItemsToWindowMenu: aMenu "Add model-related item to the window menu" super addModelItemsToWindowMenu: aMenu. ! ! !CodeHolder methodsFor: 'tiles' stamp: 'rhi 1/4/2002 11:15'! showTiles: aBoolean "Set the showingTiles as indicated. The fact that there are initially no senders of this reflects that fact that initially this trait is only directly settable through the UI; later there may be senders, such as if one wanted to set a system up so that all newly-opened browsers showed tiles rather than text." aBoolean ifTrue: [contentsSymbol _ #tiles] ifFalse: [contentsSymbol == #tiles ifTrue: [contentsSymbol _ #source]]. self setContentsToForceRefetch. self changed: #contents! ! !CodeHolder methodsFor: 'tiles' stamp: 'sw 2/3/2001 00:10'! showingTiles "Answer whether the receiver is currently showing tiles" ^ contentsSymbol == #tiles ! ! !CodeHolder methodsFor: 'tiles' stamp: 'sw 5/20/2001 21:12'! showingTilesString "Answer a string characterizing whether tiles are currently showing or not" ^ (self showingTiles ifTrue: ['<yes>'] ifFalse: ['<no>']), 'tiles'! ! !CodeHolder methodsFor: 'categories & search pane' stamp: 'sw 3/7/2001 12:22'! searchPane "Answer the search pane associated with the receiver in its window, or nil if none. Morphic only" ^ self textPaneWithSelector: #lastSearchString! ! !CodeHolder methodsFor: 'message list' stamp: 'nk 6/19/2004 16:50'! decompiledSourceIntoContents "For backwards compatibility." ^self decompiledSourceIntoContentsWithTempNames: (Sensor leftShiftDown not) ! ! !CodeHolder methodsFor: 'message list' stamp: 'nk 6/19/2004 16:41'! decompiledSourceIntoContentsWithTempNames: showTempNames "Obtain a source string by decompiling the method's code, and place that source string into my contents. Also return the string. Get temps from source file if showTempNames is true." | tempNames class selector method | class := self selectedClassOrMetaClass. selector := self selectedMessageName. "Was method deleted while in another project?" method := class compiledMethodAt: selector ifAbsent: [^ '']. currentCompiledMethod := method. (showTempNames not or: [method fileIndex > 0 and: [(SourceFiles at: method fileIndex) isNil]]) ifTrue: [ "Emergency or no source file -- decompile without temp names " contents := (class decompilerClass new decompile: selector in: class method: method) decompileString] ifFalse: [tempNames := (class compilerClass new parse: method getSourceFromFile asString in: class notifying: nil) tempNames. contents := ((class decompilerClass new withTempNames: tempNames) decompile: selector in: class method: method) decompileString]. contents := contents asText makeSelectorBoldIn: class. ^ contents copy! ! !CodeHolder methodsFor: 'message list' stamp: 'sw 8/16/2002 23:23'! selectedBytecodes "Answer text to show in a code pane when in showing-byte-codes mode" ^ (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName ifAbsent: [^ '' asText]) symbolic asText! ! !CodeHolder methodsFor: 'message list' stamp: 'nk 6/19/2004 16:46'! selectedMessage "Answer a copy of the source code for the selected message. This generic version is probably actually never reached, since every subclass probably reimplements and does not send to super. In time, ideally, most, or all, reimplementors would vanish and all would defer instead to a universal version right here. Everything in good time." | class selector method | contents ifNotNil: [^ contents copy]. self showingDecompile ifTrue: [^ self decompiledSourceIntoContentsWithTempNames: Sensor leftShiftDown not ]. class _ self selectedClassOrMetaClass. (class isNil or: [(selector _ self selectedMessageName) isNil]) ifTrue: [^ '']. method _ class compiledMethodAt: selector ifAbsent: [^ '']. "method deleted while in another project" currentCompiledMethod _ method. ^ contents _ (self showComment ifFalse: [self sourceStringPrettifiedAndDiffed] ifTrue: [ self commentContents]) copy asText makeSelectorBoldIn: class! ! !CodeHolder methodsFor: 'message list' stamp: 'sw 7/23/2002 13:05'! sourceStringPrettifiedAndDiffed "Answer a copy of the source code for the selected message, transformed by diffing and pretty-printing exigencies" | class selector sourceString | class _ self selectedClassOrMetaClass. selector _ self selectedMessageName. (class isNil or: [selector isNil]) ifTrue: [^ 'missing']. sourceString _ class ultimateSourceCodeAt: selector ifAbsent: [^ 'error']. self validateMessageSource: sourceString forSelector: selector. (#(prettyPrint colorPrint prettyDiffs altSyntax) includes: contentsSymbol) ifTrue: [sourceString _ class compilerClass new format: sourceString in: class notifying: nil contentsSymbol: contentsSymbol]. self showingAnyKindOfDiffs ifTrue: [sourceString _ self diffFromPriorSourceFor: sourceString]. ^ sourceString! ! !CodeHolder methodsFor: 'message list' stamp: 'sd 9/30/2003 14:01'! validateMessageSource: sourceString forSelector: aSelector "Check whether there is evidence that method source is invalid" | sourcesName | (self selectedClass compilerClass == Object compilerClass and: [(sourceString asString findString: aSelector keywords first ) ~= 1]) ifTrue: [sourcesName _ FileDirectory localNameFor: SmalltalkImage current sourcesName. self inform: 'There may be a problem with your sources file!! The source code for every method should (usually) start with the method selector but this is not the case with this method!! You may proceed with caution but it is recommended that you get a new source file. This can happen if you download the "' , sourcesName , '" file, or the ".changes" file you use, as TEXT. It must be transfered in BINARY mode, even if it looks like a text file, to preserve the CR line ends. Mac users: This may have been caused by Stuffit Expander. To prevent the files above to be converted to Mac line ends when they are expanded, do this: Start the program, then from Preferences... in the File menu, choose the Cross Platform panel, then select "Never" and press OK. Then expand the compressed archive again. (Occasionally, the source code for a method may legitimately start with a non-alphabetic character -- for example, Behavior method #formalHeaderPartsFor:. In such rare cases, you can happily disregard this warning.)'].! ! !CodeHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 09:33'! messageListKey: aChar from: view "Respond to a Command key. I am a model with a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection." | sel class | aChar == $D ifTrue: [^ self toggleDiffing]. sel _ self selectedMessageName. aChar == $m ifTrue: "These next two put up a type in if no message selected" [^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation]. aChar == $n ifTrue: [^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation]. "The following require a class selection" (class _ self selectedClassOrMetaClass) ifNil: [^ self arrowKey: aChar from: view]. aChar == $b ifTrue: [^ Browser fullOnClass: class selector: sel]. aChar == $N ifTrue: [^ self browseClassRefs]. aChar == $i ifTrue: [^ self methodHierarchy]. aChar == $h ifTrue: [^ self classHierarchy]. aChar == $p ifTrue: [^ self browseFullProtocol]. "The following require a method selection" sel ifNotNil: [aChar == $o ifTrue: [^ self fileOutMessage]. aChar == $c ifTrue: [^ self copySelector]. aChar == $v ifTrue: [^ self browseVersions]. aChar == $O ifTrue: [^ self openSingleMessageBrowser]. aChar == $x ifTrue: [^ self removeMessage]. (aChar == $C and: [self canShowMultipleMessageCategories]) ifTrue: [^ self showHomeCategory]]. ^ self arrowKey: aChar from: view! ! !CodeHolder methodsFor: 'message category functions' stamp: 'sw 10/8/2001 14:19'! canShowMultipleMessageCategories "Answer whether the receiver is capable of showing multiple message categories" ^ false! ! Object subclass: #Collection instanceVariableNames: '' classVariableNames: 'MutexForPicking RandomForPicking' poolDictionaries: '' category: 'Collections-Abstract'! !Collection commentStamp: '<historical>' prior: 0! I am the abstract superclass of all classes that represent a group of elements.! !Collection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:33'! anyOne "Answer a representative sample of the receiver. This method can be helpful when needing to preinfer the nature of the contents of semi-homogeneous collections." self emptyCheck. self do: [:each | ^ each]! ! !Collection methodsFor: 'accessing' stamp: 'sd 11/4/2003 22:05'! atRandom "Answer a random element of the receiver. 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." ^ self class mutexForPicking critical: [ self atRandom: self class randomForPicking ] "Examples: #('one' 'or' 'the' 'other') atRandom (1 to: 10) atRandom 'Just pick one of these letters at random' atRandom #(3 7 4 9 21) asSet atRandom (just to show it also works for Sets) "! ! !Collection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:41'! capacity "Answer the current capacity of the receiver." ^ self size! ! !Collection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:34'! size "Answer how many elements the receiver contains." | tally | tally _ 0. self do: [:each | tally _ tally + 1]. ^ tally! ! !Collection methodsFor: 'adapting' stamp: 'di 11/6/1998 13:34'! adaptToCollection: rcvr andSend: selector "If I am involved in arithmetic with another Collection, return a Collection of the results of each element combined with the scalar in that expression." rcvr isSequenceable & self isSequenceable ifFalse: [self error: 'Only sequenceable collections may be combined arithmetically']. ^ rcvr with: self collect: [:rcvrElement :myElement | rcvrElement perform: selector with: myElement]! ! !Collection methodsFor: 'adapting' stamp: 'di 11/9/1998 12:16'! adaptToNumber: rcvr andSend: selector "If I am involved in arithmetic with a scalar, return a Collection of the results of each element combined with the scalar in that expression." ^ self collect: [:element | rcvr perform: selector with: element]! ! !Collection methodsFor: 'adapting' stamp: 'di 11/6/1998 13:37'! adaptToPoint: rcvr andSend: selector "If I am involved in arithmetic with a scalar, return a Collection of the results of each element combined with the scalar in that expression." ^ self collect: [:element | rcvr perform: selector with: element]! ! !Collection methodsFor: 'adapting' stamp: 'di 11/6/1998 13:37'! adaptToString: rcvr andSend: selector "If I am involved in arithmetic with a String, convert it to a Number." ^ rcvr asNumber perform: selector with: self! ! !Collection methodsFor: 'adding'! add: newObject "Include newObject as one of the receiver's elements. Answer newObject. ArrayedCollections cannot respond to this message." self subclassResponsibility! ! !Collection methodsFor: 'adding' stamp: 'sma 5/12/2000 17:21'! add: newObject withOccurrences: anInteger "Add newObject anInteger times to the receiver. Answer newObject." anInteger timesRepeat: [self add: newObject]. ^ newObject! ! !Collection methodsFor: 'adding' stamp: 'sma 5/12/2000 17:26'! addAll: aCollection "Include all the elements of aCollection as the receiver's elements. Answer aCollection. Actually, any object responding to #do: can be used as argument." aCollection do: [:each | self add: each]. ^ aCollection! ! !Collection methodsFor: 'adding' stamp: 'sma 5/12/2000 17:23'! addIfNotPresent: anObject "Include anObject as one of the receiver's elements, but only if there is no such element already. Anwser anObject." (self includes: anObject) ifFalse: [self add: anObject]. ^ anObject! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:53'! * arg ^ arg adaptToCollection: self andSend: #*! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:53'! + arg ^ arg adaptToCollection: self andSend: #+! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:53'! - arg ^ arg adaptToCollection: self andSend: #-! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:53'! / arg ^ arg adaptToCollection: self andSend: #/! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:54'! // arg ^ arg adaptToCollection: self andSend: #//! ! !Collection methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:54'! \\ arg ^ arg adaptToCollection: self andSend: #\\! ! !Collection methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 00:17'! raisedTo: arg ^ arg adaptToCollection: self andSend: #raisedTo:! ! !Collection methodsFor: 'comparing' stamp: 'SqR 8/3/2000 13:36'! hash "Answer an integer hash value for the receiver such that, -- the hash value of an unchanged object is constant over time, and -- two equal objects have equal hash values" | hash | hash _ self species hash. self size <= 10 ifTrue: [self do: [:elem | hash _ hash bitXor: elem hash]]. ^hash bitXor: self size hash! ! !Collection methodsFor: 'converting' stamp: 'sma 5/6/2000 20:22'! asArray "Answer an Array whose elements are the elements of the receiver. Implementation note: Cannot use ''Array withAll: self'' as that only works for SequenceableCollections which support the replacement primitive." | array index | array _ Array new: self size. index _ 0. self do: [:each | array at: (index _ index + 1) put: each]. ^ array! ! !Collection methodsFor: 'converting' stamp: 'sma 5/6/2000 20:10'! asBag "Answer a Bag whose elements are the elements of the receiver." ^ Bag withAll: self! ! !Collection methodsFor: 'converting' stamp: 'sma 5/6/2000 20:22'! asByteArray "Answer a ByteArray whose elements are the elements of the receiver. Implementation note: Cannot use ''ByteArray withAll: self'' as that only works for SequenceableCollections which support the replacement primitive." | array index | array _ ByteArray new: self size. index _ 0. self do: [:each | array at: (index _ index + 1) put: each]. ^ array! ! !Collection methodsFor: 'converting' stamp: 'sma 5/6/2000 20:26'! asCharacterSet "Answer a CharacterSet whose elements are the unique elements of the receiver. The reciever should only contain characters." ^ CharacterSet newFrom: self! ! !Collection methodsFor: 'converting' stamp: 'ar 9/22/2000 10:12'! asIdentitySet ^(IdentitySet new: self size) addAll: self; yourself! ! !Collection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:43'! asOrderedCollection "Answer an OrderedCollection whose elements are the elements of the receiver. The order in which elements are added depends on the order in which the receiver enumerates its elements. In the case of unordered collections, the ordering is not necessarily the same for multiple requests for the conversion." ^ self as: OrderedCollection! ! !Collection methodsFor: 'converting' stamp: 'sma 5/6/2000 20:29'! asSet "Answer a Set whose elements are the unique elements of the receiver." ^ Set withAll: self! ! !Collection methodsFor: 'converting' stamp: 'LC 6/18/2001 18:46'! asSkipList: aSortBlock "Answer a SkipList whose elements are the elements of the receiver. The sort order is defined by the argument, aSortBlock." | skipList | skipList _ SortedCollection new: self size. skipList sortBlock: aSortBlock. skipList addAll: self. ^ skipList! ! !Collection methodsFor: 'converting'! asSortedArray "Return a copy of the receiver in sorted order, as an Array. 6/10/96 sw" ^ self asSortedCollection asArray! ! !Collection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:44'! asSortedCollection "Answer a SortedCollection whose elements are the elements of the receiver. The sort order is the default less than or equal." ^ self as: SortedCollection! ! !Collection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:46'! asSortedCollection: aSortBlock "Answer a SortedCollection whose elements are the elements of the receiver. The sort order is defined by the argument, aSortBlock." | aSortedCollection | aSortedCollection _ SortedCollection new: self size. aSortedCollection sortBlock: aSortBlock. aSortedCollection addAll: self. ^ aSortedCollection! ! !Collection methodsFor: 'converting' stamp: 'hg 12/26/2001 23:53'! topologicallySortedUsing: aSortBlock "Answer a SortedCollection whose elements are the elements of the receiver, but topologically sorted. The topological order is defined by the argument, aSortBlock." | aSortedCollection | aSortedCollection _ SortedCollection new: self size. aSortedCollection sortBlock: aSortBlock. self do: [:each | aSortedCollection addLast: each]. "avoids sorting" ^ aSortedCollection sortTopologically ! ! !Collection methodsFor: 'copying' stamp: 'al 12/12/2003 14:31'! , aCollection ^self copy addAll: aCollection; yourself! ! !Collection methodsFor: 'copying' stamp: 'sma 5/12/2000 14:41'! copyWith: newElement "Answer a new collection with newElement added (as last element if sequenceable)." ^ self copy add: newElement; yourself! ! !Collection methodsFor: 'copying' stamp: 'ar 2/11/2001 01:55'! copyWithDependent: newElement "Answer a new collection with newElement added (as last element if sequenceable)." ^self copyWith: newElement! ! !Collection methodsFor: 'copying' stamp: 'sma 5/12/2000 14:43'! copyWithout: oldElement "Answer a copy of the receiver that does not contain any elements equal to oldElement." ^ self reject: [:each | each = oldElement] "Examples: 'fred the bear' copyWithout: $e #(2 3 4 5 5 6) copyWithout: 5 "! ! !Collection methodsFor: 'copying' stamp: 'sma 5/12/2000 18:08'! copyWithoutAll: aCollection "Answer a copy of the receiver that does not contain any elements equal to those in aCollection." ^ self reject: [:each | aCollection includes: each]! ! !Collection methodsFor: 'enumerating' stamp: 'sma 4/30/2000 11:17'! allSatisfy: aBlock "Evaluate aBlock with the elements of the receiver. If aBlock returns false for any element return false. Otherwise return true." self do: [:each | (aBlock value: each) ifFalse: [^ false]]. ^ true! ! !Collection methodsFor: 'enumerating' stamp: 'sma 4/30/2000 11:17'! anySatisfy: aBlock "Evaluate aBlock with the elements of the receiver. If aBlock returns true for any element return true. Otherwise return false." self do: [:each | (aBlock value: each) ifTrue: [^ true]]. ^ false! ! !Collection methodsFor: 'enumerating'! associationsDo: aBlock "Evaluate aBlock for each of the receiver's elements (key/value associations). If any non-association is within, the error is not caught now, but later, when a key or value message is sent to it." self do: aBlock! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:45'! collect: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect the resulting values into a collection like the receiver. Answer the new collection." | newCollection | newCollection _ self species new. self do: [:each | newCollection add: (aBlock value: each)]. ^ newCollection! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:51'! collect: collectBlock thenSelect: selectBlock "Utility method to improve readability." ^ (self collect: collectBlock) select: selectBlock! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:52'! count: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the number of elements that answered true." | sum | sum _ 0. self do: [:each | (aBlock value: each) ifTrue: [sum _ sum + 1]]. ^ sum! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:20'! detect: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the first element for which aBlock evaluates to true." ^ self detect: aBlock ifNone: [self errorNotFound: aBlock]! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:52'! detect: aBlock ifNone: exceptionBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the first element for which aBlock evaluates to true. If none evaluate to true, then evaluate the argument, exceptionBlock." self do: [:each | (aBlock value: each) ifTrue: [^ each]]. ^ exceptionBlock value! ! !Collection methodsFor: 'enumerating'! detectMax: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the element for which aBlock evaluates to the highest magnitude. If collection empty, return nil. This method might also be called elect:." | maxElement maxValue val | self do: [:each | maxValue == nil ifFalse: [ (val _ aBlock value: each) > maxValue ifTrue: [ maxElement _ each. maxValue _ val]] ifTrue: ["first element" maxElement _ each. maxValue _ aBlock value: each]. "Note that there is no way to get the first element that works for all kinds of Collections. Must test every one."]. ^ maxElement! ! !Collection methodsFor: 'enumerating'! detectMin: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the element for which aBlock evaluates to the lowest number. If collection empty, return nil." | minElement minValue val | self do: [:each | minValue == nil ifFalse: [ (val _ aBlock value: each) < minValue ifTrue: [ minElement _ each. minValue _ val]] ifTrue: ["first element" minElement _ each. minValue _ aBlock value: each]. "Note that there is no way to get the first element that works for all kinds of Collections. Must test every one."]. ^ minElement! ! !Collection methodsFor: 'enumerating'! detectSum: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Return the sum of the answers." | sum | sum _ 0. self do: [:each | sum _ (aBlock value: each) + sum]. ^ sum! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 17:52'! difference: aCollection "Answer the set theoretic difference of two collections." ^ self reject: [:each | aCollection includes: each]! ! !Collection methodsFor: 'enumerating'! do: aBlock "Evaluate aBlock with each of the receiver's elements as the argument." self subclassResponsibility! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:57'! do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." | beforeFirst | beforeFirst _ true. self do: [:each | beforeFirst ifTrue: [beforeFirst _ false] ifFalse: [separatorBlock value]. elementBlock value: each]! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:59'! do: aBlock without: anItem "Enumerate all elements in the receiver. Execute aBlock for those elements that are not equal to the given item" ^ self do: [:each | anItem = each ifFalse: [aBlock value: each]]! ! !Collection methodsFor: 'enumerating'! inject: thisValue into: binaryBlock "Accumulate a running value associated with evaluating the argument, binaryBlock, with the current value of the argument, thisValue, and the receiver as block arguments. For instance, to sum the numeric elements of a collection, aCollection inject: 0 into: [:subTotal :next | subTotal + next]." | nextValue | nextValue _ thisValue. self do: [:each | nextValue _ binaryBlock value: nextValue value: each]. ^nextValue! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 17:52'! intersection: aCollection "Answer the set theoretic intersection of two collections." ^ self select: [:each | aCollection includes: each]! ! !Collection methodsFor: 'enumerating' stamp: 'gh 9/18/2001 15:59'! noneSatisfy: aBlock "Evaluate aBlock with the elements of the receiver. If aBlock returns false for all elements return true. Otherwise return false" self do: [:item | (aBlock value: item) ifTrue: [^ false]]. ^ true! ! !Collection methodsFor: 'enumerating'! reject: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect into a new collection like the receiver only those elements for which aBlock evaluates to false. Answer the new collection." ^self select: [:element | (aBlock value: element) == false]! ! !Collection methodsFor: 'enumerating'! select: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect into a new collection like the receiver, only those elements for which aBlock evaluates to true. Answer the new collection." | newCollection | newCollection _ self species new. self do: [:each | (aBlock value: each) ifTrue: [newCollection add: each]]. ^newCollection! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:59'! select: selectBlock thenCollect: collectBlock "Utility method to improve readability." ^ (self select: selectBlock) collect: collectBlock! ! !Collection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 17:54'! union: aCollection "Answer the set theoretic union of two collections." ^ self asSet addAll: aCollection; yourself! ! !Collection methodsFor: 'filter streaming' stamp: 'sma 5/12/2000 12:07'! contents ^ self! ! !Collection methodsFor: 'filter streaming' stamp: 'sma 5/12/2000 12:08'! flattenOnStream: aStream ^ aStream writeCollection: self! ! !Collection methodsFor: 'filter streaming' stamp: 'sma 5/12/2000 12:07'! write: anObject ^ self add: anObject! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:51'! abs "Absolute value of all elements in the collection" ^ self collect: [:a | a abs]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:20'! arcCos ^self collect: [:each | each arcCos]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:20'! arcSin ^self collect: [:each | each arcSin]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:20'! arcTan ^self collect: [:each | each arcTan]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:57'! average ^ self sum / self size! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:51'! ceiling ^ self collect: [:a | a ceiling]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:20'! cos ^self collect: [:each | each cos]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:20'! degreeCos ^self collect: [:each | each degreeCos]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:21'! degreeSin ^self collect: [:each | each degreeSin]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:21'! exp ^self collect: [:each | each exp]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:51'! floor ^ self collect: [:a | a floor]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:21'! ln ^self collect: [:each | each ln]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:52'! log ^ self collect: [:each | each log]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:58'! max ^ self inject: self anyOne into: [:max :each | max max: each]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 16:00'! median ^ self asSortedCollection median! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 16:00'! min ^ self inject: self anyOne into: [:min :each | min min: each]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:52'! negated "Negated value of all elements in the collection" ^ self collect: [:a | a negated]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 16:00'! range ^ self max - self min! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:53'! reciprocal "Return the reciever full of reciprocated elements" ^ self collect: [:a | a reciprocal]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:53'! rounded ^ self collect: [:a | a rounded]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:23'! sign ^self collect: [:each | each sign]! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:22'! sin ^self collect: [:each | each sin]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:53'! sqrt ^ self collect: [:each | each sqrt]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:53'! squared ^ self collect: [:each | each * each]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 16:02'! sum "This is implemented using a variant of the normal inject:into: pattern. The reason for this is that it is not known whether we're in the normal number line, i.e. whether 0 is a good initial value for the sum. Consider a collection of measurement objects, 0 would be the unitless value and would not be appropriate to add with the unit-ed objects." | sum sample | sample _ self anyOne. sum _ self inject: sample into: [:accum :each | accum + each]. ^ sum - sample! ! !Collection methodsFor: 'math functions' stamp: 'raok 10/22/2002 00:22'! tan ^self collect: [:each | each tan]! ! !Collection methodsFor: 'math functions' stamp: 'TAG 11/6/1998 15:54'! truncated ^ self collect: [:a | a truncated]! ! !Collection methodsFor: 'printing' stamp: 'sma 6/1/2000 09:39'! printElementsOn: aStream aStream nextPut: $(. self do: [:element | aStream print: element; space]. self isEmpty ifFalse: [aStream skip: -1]. aStream nextPut: $)! ! !Collection methodsFor: 'printing' stamp: 'sma 6/1/2000 09:41'! printNameOn: aStream super printOn: aStream! ! !Collection methodsFor: 'printing' stamp: 'sma 6/1/2000 09:41'! printOn: aStream "Append a sequence of characters that identify the receiver to aStream." self printNameOn: aStream. self printElementsOn: aStream! ! !Collection methodsFor: 'printing'! storeOn: aStream "Refer to the comment in Object|storeOn:." | noneYet | aStream nextPutAll: '(('. aStream nextPutAll: self class name. aStream nextPutAll: ' new)'. noneYet _ true. self do: [:each | noneYet ifTrue: [noneYet _ false] ifFalse: [aStream nextPut: $;]. aStream nextPutAll: ' add: '. aStream store: each]. noneYet ifFalse: [aStream nextPutAll: '; yourself']. aStream nextPut: $)! ! !Collection methodsFor: 'private'! emptyCheck self isEmpty ifTrue: [self errorEmptyCollection]! ! !Collection methodsFor: 'private'! errorEmptyCollection self error: 'this collection is empty'! ! !Collection methodsFor: 'private'! errorNoMatch self error: 'collection sizes do not match'! ! !Collection methodsFor: 'private' stamp: 'sma 5/12/2000 11:22'! errorNotFound: anObject "Actually, this should raise a special Exception not just an error." self error: 'Object is not in the collection.'! ! !Collection methodsFor: 'private' stamp: 'yo 6/29/2004 13:14'! errorNotKeyed self error: ('Instances of {1} do not respond to keyed accessing messages.' translated format: {self class name}) ! ! !Collection methodsFor: 'private'! toBraceStack: itsSize "Push receiver's elements onto the stack of thisContext sender. Error if receiver does not have itsSize elements or if receiver is unordered. Do not call directly: this is called by {a. b} _ ... constructs." self size ~= itsSize ifTrue: [self error: 'Trying to store ', self size printString, ' values into ', itsSize printString, ' variables.']. thisContext sender push: itsSize fromIndexable: self! ! !Collection methodsFor: 'removing' stamp: 'sma 5/12/2000 11:22'! remove: oldObject "Remove oldObject from the receiver's elements. Answer oldObject unless no element is equal to oldObject, in which case, raise an error. ArrayedCollections cannot respond to this message." ^ self remove: oldObject ifAbsent: [self errorNotFound: oldObject]! ! !Collection methodsFor: 'removing' stamp: 'sma 5/12/2000 11:14'! remove: oldObject ifAbsent: anExceptionBlock "Remove oldObject from the receiver's elements. If several of the elements are equal to oldObject, only one is removed. If no element is equal to oldObject, answer the result of evaluating anExceptionBlock. Otherwise, answer the argument, oldObject. ArrayedCollections cannot respond to this message." self subclassResponsibility! ! !Collection methodsFor: 'removing' stamp: 'sma 5/12/2000 11:14'! removeAll: aCollection "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification. ArrayedCollections cannot respond to this message." aCollection do: [:each | self remove: each]. ^ aCollection! ! !Collection methodsFor: 'removing' stamp: 'sma 5/12/2000 11:16'! removeAllFoundIn: aCollection "Remove each element of aCollection which is present in the receiver from the receiver. Answer aCollection. No error is raised if an element isn't found. ArrayedCollections cannot respond to this message." aCollection do: [:each | self remove: each ifAbsent: []]. ^ aCollection! ! !Collection methodsFor: 'removing' stamp: 'sma 5/12/2000 11:19'! removeAllSuchThat: aBlock "Evaluate aBlock for each element and remove all that elements from the receiver for that aBlock evaluates to true. Use a copy to enumerate collections whose order changes when an element is removed (i.e. Sets)." self copy do: [:each | (aBlock value: each) ifTrue: [self remove: each]]! ! !Collection methodsFor: 'testing' stamp: 'ls 3/27/2000 17:25'! identityIncludes: anObject "Answer whether anObject is one of the receiver's elements." self do: [:each | anObject == each ifTrue: [^true]]. ^false! ! !Collection methodsFor: 'testing' stamp: 'jf 12/1/2003 15:37'! ifEmpty: aBlock "Evaluate the block if I'm empty" ^ self isEmpty ifTrue: aBlock! ! !Collection methodsFor: 'testing' stamp: 'md 1/30/2004 15:11'! ifEmpty: emptyBlock ifNotEmpty: notEmptyBlock "Evaluate emptyBlock if I'm empty, notEmptyBlock otherwise" ^ self isEmpty ifTrue: emptyBlock ifFalse: [notEmptyBlock valueWithPossibleArgs: {self}]! ! !Collection methodsFor: 'testing' stamp: 'md 1/30/2004 15:08'! ifNotEmpty: aBlock "Evaluate the block unless I'm empty" ^self isEmpty ifFalse: [aBlock valueWithPossibleArgs: {self}]. ! ! !Collection methodsFor: 'testing' stamp: 'md 1/30/2004 15:11'! ifNotEmpty: notEmptyBlock ifEmpty: emptyBlock "Evaluate emptyBlock if I'm empty, notEmptyBlock otherwise" ^ self isEmpty ifFalse: [notEmptyBlock valueWithPossibleArgs: {self}] ifTrue: emptyBlock! ! !Collection methodsFor: 'testing' stamp: 'sma 5/12/2000 14:07'! includes: anObject "Answer whether anObject is one of the receiver's elements." ^ self anySatisfy: [:each | each = anObject]! ! !Collection methodsFor: 'testing'! includesAllOf: aCollection "Answer whether all the elements of aCollection are in the receiver." aCollection do: [:elem | (self includes: elem) ifFalse: [^ false]]. ^ true! ! !Collection methodsFor: 'testing'! includesAnyOf: aCollection "Answer whether any element of aCollection is one of the receiver's elements." aCollection do: [:elem | (self includes: elem) ifTrue: [^ true]]. ^ false! ! !Collection methodsFor: 'testing' stamp: 'sw 8/12/97 20:59'! includesSubstringAnywhere: testString "Answer whether the receiver includes, anywhere in its nested structure, a string that has testString as a substring" self do: [:element | (element isKindOf: String) ifTrue: [(element includesSubString: testString) ifTrue: [^ true]]. (element isKindOf: Collection) ifTrue: [(element includesSubstringAnywhere: testString) ifTrue: [^ true]]]. ^ false "#(first (second third) ((allSentMessages ('Elvis' includes:)))) includesSubstringAnywhere: 'lvi'"! ! !Collection methodsFor: 'testing' stamp: 'ar 8/17/1999 19:43'! isCollection "Return true if the receiver is some sort of Collection and responds to basic collection messages such as #size and #do:" ^true! ! !Collection methodsFor: 'testing'! isEmpty "Answer whether the receiver contains any elements." ^self size = 0! ! !Collection methodsFor: 'testing' stamp: 'bf 3/10/2000 09:29'! isEmptyOrNil "Answer whether the receiver contains any elements, or is nil. Useful in numerous situations where one wishes the same reaction to an empty collection or to nil" ^ self isEmpty! ! !Collection methodsFor: 'testing' stamp: 'di 11/6/1998 09:16'! isSequenceable ^ false! ! !Collection methodsFor: 'testing' stamp: 'dgd 4/4/2004 12:14'! isZero "Answer whether the receiver is zero" ^ false! ! !Collection methodsFor: 'testing' stamp: 'sma 5/12/2000 17:49'! notEmpty "Answer whether the receiver contains any elements." ^ self isEmpty not! ! !Collection methodsFor: 'testing'! occurrencesOf: anObject "Answer how many of the receiver's elements are equal to anObject." | tally | tally _ 0. self do: [:each | anObject = each ifTrue: [tally _ tally + 1]]. ^tally! ! !Collection methodsFor: '*packageinfo-base' stamp: 'ab 9/30/2002 19:26'! gather: aBlock ^ Array streamContents: [:stream | self do: [:ea | stream nextPutAll: (aBlock value: ea)]]! ! !Collection methodsFor: '*connectors-truncation and round-off' stamp: 'nk 12/30/2003 15:47'! roundTo: quantum ^self collect: [ :ea | ea roundTo: quantum ]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Collection class instanceVariableNames: ''! !Collection class methodsFor: 'instance creation' stamp: 'apb 10/15/2000 22:05'! ofSize: n "Create a new collection of size n with nil as its elements. This method exists because OrderedCollection new: n creates an empty collection, not one of size n." ^ self new: n! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 19:58'! with: anObject "Answer an instance of me containing anObject." ^ self new add: anObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:01'! with: firstObject with: secondObject "Answer an instance of me containing the two arguments as elements." ^ self new add: firstObject; add: secondObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:03'! with: firstObject with: secondObject with: thirdObject "Answer an instance of me containing the three arguments as elements." ^ self new add: firstObject; add: secondObject; add: thirdObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:06'! with: firstObject with: secondObject with: thirdObject with: fourthObject "Answer an instance of me, containing the four arguments as the elements." ^ self new add: firstObject; add: secondObject; add: thirdObject; add: fourthObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:06'! with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject "Answer an instance of me, containing the five arguments as the elements." ^ self new add: firstObject; add: secondObject; add: thirdObject; add: fourthObject; add: fifthObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:06'! with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject with: sixthObject "Answer an instance of me, containing the six arguments as the elements." ^ self new add: firstObject; add: secondObject; add: thirdObject; add: fourthObject; add: fifthObject; add: sixthObject; yourself! ! !Collection class methodsFor: 'instance creation' stamp: 'sma 5/6/2000 20:07'! withAll: aCollection "Create a new collection containing all the elements from aCollection." ^ (self new: aCollection size) addAll: aCollection; yourself! ! !Collection class methodsFor: 'private' stamp: 'lr 11/4/2003 12:07'! initialize "Set up a Random number generator to be used by atRandom when the user does not feel like creating his own Random generator." RandomForPicking _ Random new. MutexForPicking _ Semaphore forMutualExclusion! ! !Collection class methodsFor: 'private' stamp: 'lr 11/4/2003 12:08'! mutexForPicking ^ MutexForPicking! ! !Collection class methodsFor: 'private' stamp: 'sma 5/12/2000 12:31'! randomForPicking ^ RandomForPicking! ! Object subclass: #Color instanceVariableNames: 'rgb cachedDepth cachedBitPattern' classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow' poolDictionaries: '' category: 'Graphics-Primitives'! !Color commentStamp: '<historical>' prior: 0! 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) 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: r amount of red, a Float between 0.0 and 1.0. g amount of green, a Float between 0.0 and 1.0. b amount of blue, a Float between 0.0 and 1.0. (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.) 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) A color is essentially immutable. Once you set red, green, and blue, you cannot change them. Instead, create a new Color and use it. 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. Here are some fun things to run in when your screen has color: Pen new mandala: 30 diameter: Display height-100. Pen new web "Draw with the mouse, opt-click to end" Display fillWhite. Pen new hilberts: 5. Form toothpaste: 30 "Draw with mouse, opt-click to end" You might also want to try the comment in Form>class>examples>tinyText... Messages: 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. + add two colors - subtract two colors * 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. / divide a color by a factor or an array of three factors. 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. hue Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360. saturation Returns the saturation of the color. 0.0 to 1.0 brightness Returns the brightness of the color. 0.0 to 1.0 name Look to see if this Color has a name. display Show a swatch of this color tracking the cursor. lightShades: thisMany An array of thisMany colors from white to the receiver. darkShades: thisMany An array of thisMany colors from black to the receiver. Array is of length num. mix: color2 shades: thisMany An array of thisMany colors from the receiver to color2. wheel: thisMany An array of thisMany colors around the color wheel starting and ending at the receiver. 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. Messages to Class Color. red: r green: g blue: b Return a color with the given r, g, and b components. r: g: b: Same as above, for fast typing. hue: h saturation: s brightness: b Create a color with the given hue, saturation, and brightness. pink blue red ... Many colors have messages that return an instance of Color. canUnderstand: #brown Returns true if #brown is a defined color. names An OrderedCollection of the names of the colors. named: #notAllThatGray put: aColor Add a new color to the list and create an access message and a class variable for it. fromUser Shows the palette of colors available at this display depth. Click anywhere to return the color you clicked on. hotColdShades: thisMany An array of thisMany colors showing temperature from blue to red to white hot. 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. 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. (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)! !Color methodsFor: 'access'! alpha "Return the opacity ('alpha') value of opaque so that normal colors can be compared to TransparentColors." ^ 1.0 ! ! !Color methodsFor: 'access'! blue "Return the blue component of this color, a float in the range [0.0..1.0]." ^ self privateBlue asFloat / ComponentMax! ! !Color methodsFor: 'access'! brightness "Return the brightness of this color, a float in the range [0.0..1.0]." ^ ((self privateRed max: self privateGreen) max: self privateBlue) asFloat / ComponentMax! ! !Color methodsFor: 'access'! green "Return the green component of this color, a float in the range [0.0..1.0]." ^ self privateGreen asFloat / ComponentMax! ! !Color methodsFor: 'access'! hue "Return the hue of this color, an angle in the range [0.0..360.0]." | r g b max min span h | r _ self privateRed. g _ self privateGreen. b _ self privateBlue. max _ ((r max: g) max: b). min _ ((r min: g) min: b). span _ (max - min) asFloat. span = 0.0 ifTrue: [ ^ 0.0 ]. r = max ifTrue: [ h _ ((g - b) asFloat / span) * 60.0. ] ifFalse: [ g = max ifTrue: [ h _ 120.0 + (((b - r) asFloat / span) * 60.0). ] ifFalse: [ h _ 240.0 + (((r - g) asFloat / span) * 60.0). ]. ]. h < 0.0 ifTrue: [ h _ 360.0 + h ]. ^ h! ! !Color methodsFor: 'access'! luminance "Return the luminance of this color, a brightness value weighted by the human eye's color sensitivity." ^ ((299 * self privateRed) + (587 * self privateGreen) + (114 * self privateBlue)) / (1000 * ComponentMax) ! ! !Color methodsFor: 'access'! red "Return the red component of this color, a float in the range [0.0..1.0]." ^ self privateRed asFloat / ComponentMax! ! !Color methodsFor: 'access'! saturation "Return the saturation of this color, a value between 0.0 and 1.0." | r g b max min | r _ self privateRed. g _ self privateGreen. b _ self privateBlue. max _ min _ r. g > max ifTrue: [max _ g]. b > max ifTrue: [max _ b]. g < min ifTrue: [min _ g]. b < min ifTrue: [min _ b]. max = 0 ifTrue: [ ^ 0.0 ] ifFalse: [ ^ (max - min) asFloat / max asFloat ]. ! ! !Color methodsFor: 'equality' stamp: 'di 1/6/1999 20:26'! = aColor "Return true if the receiver equals the given color. This method handles TranslucentColors, too." aColor isColor ifFalse: [^ false]. ^ aColor privateRGB = rgb and: [aColor privateAlpha = self privateAlpha] ! ! !Color methodsFor: 'equality' stamp: 'di 9/27/2000 08:07'! diff: theOther "Returns a number between 0.0 and 1.0" ^ ((self privateRed - theOther privateRed) abs + (self privateGreen - theOther privateGreen) abs + (self privateBlue - theOther privateBlue) abs) / 3.0 / ComponentMax! ! !Color methodsFor: 'equality'! hash ^ rgb! ! !Color methodsFor: 'queries' stamp: 'sw 9/27/2001 17:26'! basicType "Answer a symbol representing the inherent type of the receiver" ^ #Color! ! !Color methodsFor: 'queries' stamp: 'ar 1/14/1999 15:27'! isBitmapFill ^false! ! !Color methodsFor: 'queries' stamp: 'ar 11/12/1998 19:43'! isBlack "Return true if the receiver represents black" ^rgb = 0! ! !Color methodsFor: 'queries'! isColor ^ true ! ! !Color methodsFor: 'queries' stamp: 'ar 6/18/1999 06:58'! isGradientFill ^false! ! !Color methodsFor: 'queries' stamp: 'ar 11/12/1998 19:44'! isGray "Return true if the receiver represents a shade of gray" ^(self privateRed = self privateGreen) and:[self privateRed = self privateBlue]! ! !Color methodsFor: 'queries' stamp: 'ar 4/20/2001 04:33'! isOpaque ^true! ! !Color methodsFor: 'queries' stamp: 'ar 6/18/1999 07:57'! isOrientedFill "Return true if the receiver keeps an orientation (e.g., origin, direction, and normal)" ^false! ! !Color methodsFor: 'queries' stamp: 'ar 11/7/1998 20:20'! isSolidFill ^true! ! !Color methodsFor: 'queries' stamp: 'di 12/30/1998 14:33'! isTranslucent ^ false ! ! !Color methodsFor: 'queries' stamp: 'di 1/3/1999 12:23'! isTranslucentColor "This means: self isTranslucent, but isTransparent not" ^ false! ! !Color methodsFor: 'queries'! isTransparent ^ false ! ! !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'! * aNumber "Answer this color with its RGB multiplied by the given number. " "(Color brown * 2) display" ^ Color basicNew setPrivateRed: (self privateRed * aNumber) asInteger green: (self privateGreen * aNumber) asInteger blue: (self privateBlue * aNumber) asInteger ! ! !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'! + aColor "Answer this color mixed with the given color in an additive color space. " "(Color blue + Color green) display" ^ Color basicNew setPrivateRed: self privateRed + aColor privateRed green: self privateGreen + aColor privateGreen blue: self privateBlue + aColor privateBlue ! ! !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'! - aColor "Answer aColor is subtracted from the given color in an additive color space. " "(Color white - Color red) display" ^ Color basicNew setPrivateRed: self privateRed - aColor privateRed green: self privateGreen - aColor privateGreen blue: self privateBlue - aColor privateBlue ! ! !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:07'! / aNumber "Answer this color with its RGB divided by the given number. " "(Color red / 2) display" ^ Color basicNew setPrivateRed: (self privateRed / aNumber) asInteger green: (self privateGreen / aNumber) asInteger blue: (self privateBlue / aNumber) asInteger ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/19/2002 23:50'! adjustBrightness: brightness "Adjust the relative brightness of this color. (lowest value is 0.005 so that hue information is not lost)" ^ Color h: self hue s: self saturation v: (self brightness + brightness min: 1.0 max: 0.005) alpha: self alpha! ! !Color methodsFor: 'transformations' stamp: 'dew 3/19/2002 23:51'! adjustSaturation: saturation brightness: brightness "Adjust the relative saturation and brightness of this color. (lowest value is 0.005 so that hue information is not lost)" ^ Color h: self hue s: (self saturation + saturation min: 1.0 max: 0.005) v: (self brightness + brightness min: 1.0 max: 0.005) alpha: self alpha! ! !Color methodsFor: 'transformations' stamp: 'sma 6/25/2000 15:36'! alpha: alphaValue "Answer a new Color with the given amount of opacity ('alpha')." alphaValue = 1.0 ifFalse: [^ TranslucentColor basicNew setRgb: rgb alpha: alphaValue]! ! !Color methodsFor: 'transformations' stamp: 'tk 7/4/2000 11:55'! alphaMixed: proportion with: aColor "Answer this color mixed with the given color. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix. For example, 0.9 would yield a color close to the receiver. This method uses RGB interpolation; HSV interpolation can lead to surprises. Mixes the alphas (for transparency) also." | frac1 frac2 | frac1 _ proportion asFloat min: 1.0 max: 0.0. frac2 _ 1.0 - frac1. ^ Color r: self red * frac1 + (aColor red * frac2) g: self green * frac1 + (aColor green * frac2) b: self blue * frac1 + (aColor blue * frac2) alpha: self alpha * frac1 + (aColor alpha * frac2)! ! !Color methodsFor: 'transformations' stamp: 'RAA 6/2/2000 08:47'! atLeastAsLuminentAs: aFloat | revisedColor | revisedColor _ self. [revisedColor luminance < aFloat] whileTrue: [revisedColor _ revisedColor slightlyLighter]. ^revisedColor ! ! !Color methodsFor: 'transformations' stamp: 'nk 3/8/2004 09:43'! atMostAsLuminentAs: aFloat | revisedColor | revisedColor _ self. [revisedColor luminance > aFloat] whileTrue: [revisedColor _ revisedColor slightlyDarker]. ^revisedColor ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/23/2002 01:38'! blacker ^ self alphaMixed: 0.8333 with: Color black ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/19/2002 23:54'! dansDarker "Return a darker shade of the same color. An attempt to do better than the current darker method. (now obsolete, since darker has been changed to do this. -dew)" ^ Color h: self hue s: self saturation v: (self brightness - 0.16 max: 0.0)! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:40'! darker "Answer a darker shade of this color." ^ self adjustBrightness: -0.08! ! !Color methodsFor: 'transformations' stamp: 'dew 3/8/2002 00:13'! duller ^ self adjustSaturation: -0.03 brightness: -0.2! ! !Color methodsFor: 'transformations' stamp: 'dew 1/23/2002 20:19'! lighter "Answer a lighter shade of this color." ^ self adjustSaturation: -0.03 brightness: 0.08! ! !Color methodsFor: 'transformations' stamp: 'tk 7/4/2000 12:00'! mixed: proportion with: aColor "Mix with another color and do not preserve transpareny. Only use this for extracting the RGB value and mixing it. All other callers should use instead: aColor alphaMixed: proportion with: anotherColor " | frac1 frac2 | frac1 _ proportion asFloat min: 1.0 max: 0.0. frac2 _ 1.0 - frac1. ^ Color r: self red * frac1 + (aColor red * frac2) g: self green * frac1 + (aColor green * frac2) b: self blue * frac1 + (aColor blue * frac2)! ! !Color methodsFor: 'transformations' stamp: 'dew 1/19/2002 01:29'! muchDarker ^ self alphaMixed: 0.5 with: Color black ! ! !Color methodsFor: 'transformations' stamp: 'tk 7/4/2000 12:07'! muchLighter ^ self alphaMixed: 0.233 with: Color white ! ! !Color methodsFor: 'transformations' stamp: 'ar 6/19/1999 00:36'! negated "Return an RGB inverted color" ^Color r: 1.0 - self red g: 1.0 - self green b: 1.0 - self blue! ! !Color methodsFor: 'transformations' stamp: 'di 9/27/2000 08:14'! orColorUnlike: theOther "If this color is a lot like theOther, then return its complement, otherwide, return self" (self diff: theOther) < 0.3 ifTrue: [^ theOther negated] ifFalse: [^ self]! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:42'! paler "Answer a paler shade of this color." ^ self adjustSaturation: -0.09 brightness: 0.09 ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:43'! slightlyDarker ^ self adjustBrightness: -0.03 ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:43'! slightlyLighter ^ self adjustSaturation: -0.01 brightness: 0.03! ! !Color methodsFor: 'transformations' stamp: 'dew 1/19/2002 01:25'! slightlyWhiter ^ self alphaMixed: 0.85 with: Color white ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:44'! twiceDarker "Answer a significantly darker shade of this color." ^ self adjustBrightness: -0.15! ! !Color methodsFor: 'transformations' stamp: 'dew 3/4/2002 01:45'! twiceLighter "Answer a significantly lighter shade of this color." ^ self adjustSaturation: -0.06 brightness: 0.15! ! !Color methodsFor: 'transformations' stamp: 'tk 7/4/2000 12:07'! veryMuchLighter ^ self alphaMixed: 0.1165 with: Color white ! ! !Color methodsFor: 'transformations' stamp: 'dew 3/23/2002 01:38'! whiter ^ self alphaMixed: 0.8333 with: Color white ! ! !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'! darkShades: thisMany "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. " "Color showColors: (Color red darkShades: 12)" ^ self class black mix: self shades: thisMany ! ! !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'! lightShades: thisMany "An array of thisMany colors from white to self. Very useful for displaying color based on a variable in your program. " "Color showColors: (Color red lightShades: 12)" ^ self class white mix: self shades: thisMany ! ! !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'! mix: color2 shades: thisMany "Return an array of thisMany colors from self to color2. Very useful for displaying color based on a variable in your program. " "Color showColors: (Color red mix: Color green shades: 12)" | redInc greenInc blueInc rr gg bb c out | thisMany = 1 ifTrue: [^ Array with: color2]. redInc _ color2 red - self red / (thisMany-1). greenInc _ color2 green - self green / (thisMany-1). blueInc _ color2 blue - self blue / (thisMany-1). rr _ self red. gg _ self green. bb _ self blue. out _ (1 to: thisMany) collect: [:num | c _ Color r: rr g: gg b: bb. rr _ rr + redInc. gg _ gg + greenInc. bb _ bb + blueInc. c]. out at: out size put: color2. "hide roundoff errors" ^ out ! ! !Color methodsFor: 'groups of shades' stamp: 'di 10/23/2000 09:45'! wheel: thisMany "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. " | sat bri hue step c | sat _ self saturation. bri _ self brightness. hue _ self hue. step _ 360.0 / (thisMany max: 1). ^ (1 to: thisMany) collect: [:num | c _ Color h: hue s: sat v: bri. "hue is taken mod 360" hue _ hue + step. c]. " (Color wheel: 8) withIndexDo: [:c :i | Display fill: (i*10@20 extent: 10@20) fillColor: c] "! ! !Color methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:14'! byteEncode: aStream aStream print: '('; print: self class name; print: ' r: '; write: (self red roundTo: 0.001); print: ' g: '; write: (self green roundTo: 0.001); print: ' b: '; write: (self blue roundTo: 0.001) ; print: ')'. ! ! !Color methodsFor: 'printing' stamp: 'bf 5/25/2000 16:52'! printOn: aStream | name | (name _ self name) ifNotNil: [^ aStream nextPutAll: 'Color '; nextPutAll: name]. self storeOn: aStream. ! ! !Color methodsFor: 'printing'! shortPrintString "Return a short (but less precise) print string for use where space is tight." | s | s _ WriteStream on: ''. s nextPutAll: '(' , self class name; nextPutAll: ' r: '; nextPutAll: (self red roundTo: 0.01) printString; nextPutAll: ' g: '; nextPutAll: (self green roundTo: 0.01) printString; nextPutAll: ' b: '; nextPutAll: (self blue roundTo: 0.01) printString; nextPutAll: ')'. ^ s contents ! ! !Color methodsFor: 'printing' stamp: 'mir 7/21/1999 11:41'! storeArrayOn: aStream aStream nextPutAll: '#('. self storeArrayValuesOn: aStream. aStream nextPutAll: ') ' ! ! !Color methodsFor: 'printing' stamp: 'mir 7/21/1999 11:41'! storeArrayValuesOn: aStream (self red roundTo: 0.001) storeOn: aStream. aStream space. (self green roundTo: 0.001) storeOn: aStream. aStream space. (self blue roundTo: 0.001) storeOn: aStream. ! ! !Color methodsFor: 'printing' stamp: 'di 9/27/2000 13:34'! storeOn: aStream aStream nextPutAll: '(' , self class name; nextPutAll: ' r: '; print: (self red roundTo: 0.001); nextPutAll: ' g: '; print: (self green roundTo: 0.001); nextPutAll: ' b: '; print: (self blue roundTo: 0.001); nextPutAll: ')'. ! ! !Color methodsFor: 'other' stamp: 'sw 2/16/98 03:42'! colorForInsets ^ self! ! !Color methodsFor: 'other' stamp: 'tk 6/14/96'! display "Show a swatch of this color tracking the cursor until the next mouseClick. " "Color red display" | f | f _ Form extent: 40@20 depth: Display depth. f fillColor: self. Cursor blank showWhile: [f follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]! ! !Color methodsFor: 'other' stamp: 'jm 12/4/97 10:24'! name "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color." ColorNames do: [:name | (Color perform: name) = self ifTrue: [^ name]]. ^ nil ! ! !Color methodsFor: 'other' stamp: 'ar 8/16/2001 12:47'! raisedColor ^ self! ! !Color methodsFor: 'other' stamp: 'jm 12/4/97 10:27'! rgbTriplet "Color fromUser rgbTriplet" ^ Array with: (self red roundTo: 0.01) with: (self green roundTo: 0.01) with: (self blue roundTo: 0.01) ! ! !Color methodsFor: 'conversions' stamp: 'ar 11/2/1998 12:19'! asColor "Convert the receiver into a color" ^self! ! !Color methodsFor: 'conversions' stamp: 'TBn 6/15/2000 20:37'! asColorref "Convert the receiver into a colorref" ^(self red * 255) asInteger + ((self green * 255) asInteger << 8) + ((self green * 255) asInteger << 16)! ! !Color methodsFor: 'conversions' stamp: 'sw 10/27/1999 10:51'! asNontranslucentColor ^ self! ! !Color methodsFor: 'conversions' stamp: 'di 3/25/2000 10:13'! balancedPatternForDepth: depth "A generalization of bitPatternForDepth: as it exists. Generates a 2x2 stipple of color. The topLeft and bottomRight pixel are closest approx to this color" | pv1 pv2 mask1 mask2 pv3 c | (depth == cachedDepth and:[cachedBitPattern size = 2]) ifTrue: [^ cachedBitPattern]. (depth between: 4 and: 16) ifFalse: [^ self bitPatternForDepth: depth]. cachedDepth _ depth. pv1 _ self pixelValueForDepth: depth. " Subtract error due to pv1 to get pv2. pv2 _ (self - (err1 _ (Color colorFromPixelValue: pv1 depth: depth) - self)) pixelValueForDepth: depth. Subtract error due to 2 pv1's and pv2 to get pv3. pv3 _ (self - err1 - err1 - ((Color colorFromPixelValue: pv2 depth: depth) - self)) pixelValueForDepth: depth. " "Above two statements computed faster by the following..." pv2 _ (c _ self - ((Color colorFromPixelValue: pv1 depth: depth) - self)) pixelValueForDepth: depth. pv3 _ (c + (c - (Color colorFromPixelValue: pv2 depth: depth))) pixelValueForDepth: depth. "Return to a 2-word bitmap that encodes a 2x2 stipple of the given pixelValues." mask1 _ (#(- - - 16r01010101 - - - "replicates every other 4 bits" 16r00010001 - - - - - - - "replicates every other 8 bits" 16r00000001) at: depth). "replicates every other 16 bits" mask2 _ (#(- - - 16r10101010 - - - "replicates the other 4 bits" 16r01000100 - - - - - - - "replicates the other 8 bits" 16r00010000) at: depth). "replicates the other 16 bits" ^ cachedBitPattern _ Bitmap with: (mask1*pv1) + (mask2*pv2) with: (mask1*pv3) + (mask2*pv1)! ! !Color methodsFor: 'conversions' stamp: 'hmm 4/25/2000 09:40'! bitPatternForDepth: depth "Return a Bitmap, possibly containing a stipple pattern, that best represents this color at the given depth. BitBlt calls this method to convert colors into Bitmaps. The resulting Bitmap may be multiple words to represent a stipple pattern of several lines. " "See also: pixelValueAtDepth: -- value for single pixel pixelWordAtDepth: -- a 32-bit word filled with the pixel value" "Details: The pattern for the most recently requested depth is cached." "Note for depths > 2, there are stippled and non-stippled versions (generated with #balancedPatternForDepth: and #bitPatternForDepth:, respectively). The stippled versions don't work with the window bit caching of StandardSystemView, so we make sure that for these depths, only unstippled patterns are returned" (depth == cachedDepth and: [depth <= 2 or: [cachedBitPattern size = 1]]) ifTrue: [^ cachedBitPattern]. cachedDepth _ depth. depth > 2 ifTrue: [^ cachedBitPattern _ Bitmap with: (self pixelWordForDepth: depth)]. depth = 1 ifTrue: [^ cachedBitPattern _ self halfTonePattern1]. depth = 2 ifTrue: [^ cachedBitPattern _ self halfTonePattern2]. ! ! !Color methodsFor: 'conversions'! closestPixelValue1 "Return the nearest approximation to this color for a monochrome Form." "fast special cases" rgb = 0 ifTrue: [^ 1]. "black" rgb = 16r3FFFFFFF ifTrue: [^ 0]. "white" self luminance > 0.5 ifTrue: [^ 0] "white" ifFalse: [^ 1]. "black" ! ! !Color methodsFor: 'conversions'! closestPixelValue2 "Return the nearest approximation to this color for a 2-bit deep Form." | lum | "fast special cases" rgb = 0 ifTrue: [^ 1]. "black" rgb = 16r3FFFFFFF ifTrue: [^ 2]. "opaque white" lum _ self luminance. lum < 0.2 ifTrue: [^ 1]. "black" lum > 0.6 ifTrue: [^ 2]. "opaque white" ^ 3 "50% gray" ! ! !Color methodsFor: 'conversions'! closestPixelValue4 "Return the nearest approximation to this color for a 4-bit deep Form." | bIndex | "fast special cases" rgb = 0 ifTrue: [^ 1]. "black" rgb = 16r3FFFFFFF ifTrue: [^ 2]. "opaque white" rgb = PureRed privateRGB ifTrue: [^ 4]. rgb = PureGreen privateRGB ifTrue: [^ 5]. rgb = PureBlue privateRGB ifTrue: [^ 6]. rgb = PureCyan privateRGB ifTrue: [^ 7]. rgb = PureYellow privateRGB ifTrue: [^ 8]. rgb = PureMagenta privateRGB ifTrue: [^ 9]. bIndex _ (self luminance * 8.0) rounded. "bIndex in [0..8]" ^ #( 1 "black" 10 "1/8 gray" 11 "2/8 gray" 12 "3/8 gray" 3 "4/8 gray" 13 "5/8 gray" 14 "6/8 gray" 15 "7/8 gray" 2 "opaque white" ) at: bIndex + 1. ! ! !Color methodsFor: 'conversions'! closestPixelValue8 "Return the nearest approximation to this color for an 8-bit deep Form." "fast special cases" rgb = 0 ifTrue: [^ 1]. "black" rgb = 16r3FFFFFFF ifTrue: [^ 255]. "white" self saturation < 0.2 ifTrue: [ ^ GrayToIndexMap at: (self privateGreen >> 2) + 1. "nearest gray" ] ifFalse: [ "compute nearest entry in the color cube" ^ 40 + ((((self privateRed * 5) + HalfComponentMask) // ComponentMask) * 36) + ((((self privateBlue * 5) + HalfComponentMask) // ComponentMask) * 6) + (((self privateGreen * 5) + HalfComponentMask) // ComponentMask)]. ! ! !Color methodsFor: 'conversions' stamp: 'di 9/2/97 20:21'! dominantColor ^ self! ! !Color methodsFor: 'conversions' stamp: 'di 6/23/97 23:27'! halfTonePattern1 "Return a halftone-pattern to approximate luminance levels on 1-bit deep Forms." | lum | lum _ self luminance. lum < 0.1 ifTrue: [^ Bitmap with: 16rFFFFFFFF]. "black" lum < 0.4 ifTrue: [^ Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE]. "dark gray" lum < 0.6 ifTrue: [^ Bitmap with: 16r55555555 with: 16rAAAAAAAA]. "medium gray" lum < 0.9 ifTrue: [^ Bitmap with: 16r44444444 with: 16r11111111]. "light gray" ^ Bitmap with: 0 "1-bit white" ! ! !Color methodsFor: 'conversions'! halfTonePattern2 "Return a halftone-pattern to approximate luminance levels on 2-bit deep Forms." | lum | lum _ self luminance. lum < 0.125 ifTrue: [^ Bitmap with: 16r55555555]. "black" lum < 0.25 ifTrue: [^ Bitmap with: 16r55555555 with: 16rDDDDDDDD]. "1/8 gray" lum < 0.375 ifTrue: [^ Bitmap with: 16rDDDDDDDD with: 16r77777777]. "2/8 gray" lum < 0.5 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16r77777777]. "3/8 gray" lum < 0.625 ifTrue: [^ Bitmap with: 16rFFFFFFFF]. "4/8 gray" lum < 0.75 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16rBBBBBBBB]. "5/8 gray" lum < 0.875 ifTrue: [^ Bitmap with: 16rEEEEEEEE with: 16rBBBBBBBB]. "6/8 gray" lum < 1.0 ifTrue: [^ Bitmap with: 16rAAAAAAAA with: 16rBBBBBBBB]. "7/8 gray" ^ Bitmap with: 16rAAAAAAAA "opaque white" "handy expression for computing patterns for 2x2 tiles; set p to a string of 4 letters (e.g., 'wggw' for a gray-and- white checkerboard) and print the result of evaluating: | p d w1 w2 | p _ 'wggw'. d _ Dictionary new. d at: $b put: '01'. d at: $w put: '10'. d at: $g put: '11'. w1 _ (d at: (p at: 1)), (d at: (p at: 2)). w1 _ '2r', w1, w1, w1, w1, w1, w1, w1, w1, ' hex'. w2 _ (d at: (p at: 3)), (d at: (p at: 4)). w2 _ '2r', w2, w2, w2, w2, w2, w2, w2, w2, ' hex'. Array with: (Compiler evaluate: w1) with: (Compiler evaluate: w2) "! ! !Color methodsFor: 'conversions' stamp: 'tk 4/24/97'! indexInMap: aColorMap "Return the index corresponding to this color in the given color map. RGB colors are truncated to 3-, 4-, or 5-bits per color component when indexing into such a colorMap. " aColorMap size = 2 ifTrue: [^ (self pixelValueForDepth: 1) + 1]. aColorMap size = 4 ifTrue: [^ (self pixelValueForDepth: 2) + 1]. aColorMap size = 16 ifTrue: [^ (self pixelValueForDepth: 4) + 1]. aColorMap size = 256 ifTrue: [^ (self pixelValueForDepth: 8) + 1]. aColorMap size = 512 ifTrue: [^ (self pixelValueForDepth: 9) + 1]. aColorMap size = 4096 ifTrue: [^ (self pixelValueForDepth: 12) + 1]. aColorMap size = 32768 ifTrue: [^ (self pixelValueForDepth: 16) + 1]. self error: 'unknown pixel depth'. ! ! !Color methodsFor: 'conversions' stamp: 'bf 4/18/2001 16:25'! makeForegroundColor "Make a foreground color contrasting with me" ^self luminance >= 0.5 ifTrue: [Color black] ifFalse: [Color white]! ! !Color methodsFor: 'conversions' stamp: 'ar 5/15/2001 16:12'! pixelValue32 "Note: pixelWord not pixelValue so we include translucency" ^self pixelWordForDepth: 32! ! !Color methodsFor: 'conversions' stamp: 'jm 1/26/2001 15:11'! pixelValueForDepth: d "Returns an integer representing the bits that appear in a single pixel of this color in a Form of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32. Contrast with pixelWordForDepth: and bitPatternForDepth:, which return either a 32-bit word packed with the given pixel value or a multiple-word Bitmap containing a pattern. The inverse is the class message colorFromPixelValue:depth:" "Details: For depths of 8 or less, the result is a colorMap index. For depths of 16 and 32, it is a direct color value with 5 or 8 bits per color component." "Transparency: The pixel value zero is reserved for transparent. For depths greater than 8, black maps to the darkest possible blue." | rgbBlack val | d = 8 ifTrue: [^ self closestPixelValue8]. "common case" d < 8 ifTrue: [ d = 4 ifTrue: [^ self closestPixelValue4]. d = 2 ifTrue: [^ self closestPixelValue2]. d = 1 ifTrue: [^ self closestPixelValue1]]. rgbBlack _ 1. "closest black that is not transparent in RGB" d = 16 ifTrue: [ "five bits per component; top bits ignored" val _ (((rgb bitShift: -15) bitAnd: 16r7C00) bitOr: ((rgb bitShift: -10) bitAnd: 16r03E0)) bitOr: ((rgb bitShift: -5) bitAnd: 16r001F). ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]]. d = 32 ifTrue: [ "eight bits per component; top 8 bits set to all ones (opaque alpha)" val _ LargePositiveInteger new: 4. val at: 3 put: ((rgb bitShift: -22) bitAnd: 16rFF). val at: 2 put: ((rgb bitShift: -12) bitAnd: 16rFF). val at: 1 put: ((rgb bitShift: -2) bitAnd: 16rFF). val = 0 ifTrue: [val at: 1 put: 1]. "closest non-transparent black" val at: 4 put: 16rFF. "opaque alpha" ^ val]. d = 12 ifTrue: [ "for indexing a color map with 4 bits per color component" val _ (((rgb bitShift: -18) bitAnd: 16r0F00) bitOr: ((rgb bitShift: -12) bitAnd: 16r00F0)) bitOr: ((rgb bitShift: -6) bitAnd: 16r000F). ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]]. d = 9 ifTrue: [ "for indexing a color map with 3 bits per color component" val _ (((rgb bitShift: -21) bitAnd: 16r01C0) bitOr: ((rgb bitShift: -14) bitAnd: 16r0038)) bitOr: ((rgb bitShift: -7) bitAnd: 16r0007). ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]]. self error: 'unknown pixel depth: ', d printString ! ! !Color methodsFor: 'conversions' stamp: 'di 11/30/1998 09:03'! pixelWordFor: depth filledWith: pixelValue "Return to a 32-bit word that concatenates enough copies of the given pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1." | halfword | depth = 32 ifTrue: [^ pixelValue]. depth = 16 ifTrue: [halfword _ pixelValue] ifFalse: [halfword _ pixelValue * (#(16rFFFF "replicates at every bit" 16r5555 - "replicates every 2 bits" 16r1111 - - - "replicates every 4 bits" 16r0101) at: depth) "replicates every 8 bits"]. ^ halfword bitOr: (halfword bitShift: 16)! ! !Color methodsFor: 'conversions'! pixelWordForDepth: depth "Return to a 32-bit word that concatenates enough copies of the receiver's pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1." | pixelValue | pixelValue _ self pixelValueForDepth: depth. ^ self pixelWordFor: depth filledWith: pixelValue ! ! !Color methodsFor: 'conversions' stamp: 'ar 1/14/1999 15:28'! scaledPixelValue32 "Return the alpha scaled pixel value for depth 32" ^self pixelWordForDepth: 32! ! !Color methodsFor: 'private'! attemptToMutateError "A color is immutable. Once a color's red, green, and blue have been initialized, you cannot change them. Instead, create a new Color and use it." self error: 'Color objects are immutable once created' ! ! !Color methodsFor: 'private'! flushCache "Flush my cached bit pattern." cachedDepth _ nil. cachedBitPattern _ nil. ! ! !Color methodsFor: 'private'! privateAlpha "Private!! Return the raw alpha value for opaque. Used only for equality testing." ^ 255! ! !Color methodsFor: 'private'! privateBlue "Private!! Return the internal representation of my blue component." ^ rgb bitAnd: ComponentMask! ! !Color methodsFor: 'private'! privateGreen "Private!! Return the internal representation of my green component. Replaced >> by bitShift: 0 -. SqR!! 2/25/1999 23:08" ^ (rgb bitShift: 0 - GreenShift) bitAnd: ComponentMask! ! !Color methodsFor: 'private'! privateRGB "Private!! Return the internal representation of my RGB components." ^ rgb ! ! !Color methodsFor: 'private'! privateRed "Private!! Return the internal representation of my red component." ^ (rgb bitShift: 0 - RedShift) bitAnd: ComponentMask! ! !Color methodsFor: 'private'! setHue: hue saturation: saturation brightness: brightness "Initialize this color to the given hue, saturation, and brightness. See the comment in the instance creation method for details." | s v hf i f p q t | s _ (saturation asFloat max: 0.0) min: 1.0. v _ (brightness asFloat max: 0.0) min: 1.0. "zero saturation yields gray with the given brightness" s = 0.0 ifTrue: [ ^ self setRed: v green: v blue: v ]. hf _ hue asFloat. (hf < 0.0 or: [hf >= 360.0]) ifTrue: [hf _ hf - ((hf quo: 360.0) asFloat * 360.0)]. hf _ hf / 60.0. i _ hf asInteger. "integer part of hue" f _ hf fractionPart. "fractional part of hue" p _ (1.0 - s) * v. q _ (1.0 - (s * f)) * v. t _ (1.0 - (s * (1.0 - f))) * v. 0 = i ifTrue: [ ^ self setRed: v green: t blue: p ]. 1 = i ifTrue: [ ^ self setRed: q green: v blue: p ]. 2 = i ifTrue: [ ^ self setRed: p green: v blue: t ]. 3 = i ifTrue: [ ^ self setRed: p green: q blue: v ]. 4 = i ifTrue: [ ^ self setRed: t green: p blue: v ]. 5 = i ifTrue: [ ^ self setRed: v green: p blue: q ]. self error: 'implementation error'. ! ! !Color methodsFor: 'private' stamp: 'di 11/2/97 12:19'! setPrivateRed: r green: g blue: b "Initialize this color's r, g, and b components to the given values in the range [0..ComponentMax]. Encoded in a single variable as 3 integers in [0..1023]." rgb == nil ifFalse: [self attemptToMutateError]. rgb _ ((r min: ComponentMask max: 0) bitShift: RedShift) + ((g min: ComponentMask max: 0) bitShift: GreenShift) + (b min: ComponentMask max: 0). cachedDepth _ nil. cachedBitPattern _ nil. ! ! !Color methodsFor: 'private' stamp: 'ls 9/24/1999 20:04'! setRGB: rgb0 rgb == nil ifFalse: [self attemptToMutateError]. rgb _ rgb0! ! !Color methodsFor: 'private'! setRed: r green: g blue: b "Initialize this color's r, g, and b components to the given values in the range [0.0..1.0]. Encoded in a single variable as 3 integers in [0..1023]." rgb == nil ifFalse: [self attemptToMutateError]. rgb _ (((r * ComponentMax) rounded bitAnd: ComponentMask) bitShift: RedShift) + (((g * ComponentMax) rounded bitAnd: ComponentMask) bitShift: GreenShift) + ((b * ComponentMax) rounded bitAnd: ComponentMask). cachedDepth _ nil. cachedBitPattern _ nil. ! ! !Color methodsFor: 'private'! setRed: r green: g blue: b range: range "Initialize this color's r, g, and b components to the given values in the range [0..r]." rgb == nil ifFalse: [self attemptToMutateError]. rgb _ ((((r * ComponentMask) // range) bitAnd: ComponentMask) bitShift: RedShift) + ((((g * ComponentMask) // range) bitAnd: ComponentMask) bitShift: GreenShift) + (((b * ComponentMask) // range) bitAnd: ComponentMask). cachedDepth _ nil. cachedBitPattern _ nil. ! ! !Color methodsFor: 'copying' stamp: 'tk 8/19/1998 16:12'! veryDeepCopyWith: deepCopier "Return self. I am immutable in the Morphic world. Do not record me."! ! !Color methodsFor: 'Morphic menu' stamp: 'dgd 10/17/2003 12:10'! addFillStyleMenuItems: aMenu hand: aHand from: aMorph "Add the items for changing the current fill style of the receiver" aMenu add: 'change color...' translated target: self selector: #changeColorIn:event: argument: aMorph! ! !Color methodsFor: 'Morphic menu' stamp: 'ar 10/5/2000 18:50'! changeColorIn: aMorph event: evt "Note: This is just a workaround to make sure we don't use the old color inst var" aMorph changeColorTarget: aMorph selector: #fillStyle: originalColor: self hand: evt hand! ! !Color methodsFor: '*morphic-Postscript Canvases'! encodePostscriptOn: aStream aStream setrgbcolor:self. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Color class instanceVariableNames: ''! !Color class methodsFor: 'instance creation' stamp: 'sw 2/26/2002 10:46'! colorFrom: parm "Return an instantiated color from parm. If parm is already a color, return it, else return the result of my performing it if it's a symbol or, if it is a list, it can either be an array of three numbers, which will be interpreted as RGB values, or a list of symbols, the first of which is sent to me and then the others of which are in turn sent to the prior result, thus allowing entries of the form #(blue darker). Else just return the thing" | aColor firstParm | (parm isKindOf: Color) ifTrue: [^ parm]. (parm isKindOf: Symbol) ifTrue: [^ self perform: parm]. ((parm isKindOf: SequenceableCollection) and: [parm size > 0]) ifTrue: [firstParm _ parm first. (firstParm isKindOf: Number) ifTrue: [^ self fromRgbTriplet: parm]. aColor _ self colorFrom: firstParm. parm doWithIndex: [:sym :ind | ind > 1 ifTrue: [aColor _ aColor perform: sym]]. ^ aColor]. ^ parm " Color colorFrom: #(blue darker) Color colorFrom: Color blue darker Color colorFrom: #blue Color colorFrom: #(0.0 0.0 1.0) "! ! !Color class methodsFor: 'instance creation' stamp: 'tk 8/15/2001 11:03'! colorFromPixelValue: p depth: d "Convert a pixel value for the given display depth into a color." "Details: For depths of 8 or less, the pixel value is simply looked up in a table. For greater depths, the color components are extracted and converted into a color." | r g b alpha | d = 8 ifTrue: [^ IndexedColors at: (p bitAnd: 16rFF) + 1]. d = 4 ifTrue: [^ IndexedColors at: (p bitAnd: 16r0F) + 1]. d = 2 ifTrue: [^ IndexedColors at: (p bitAnd: 16r03) + 1]. d = 1 ifTrue: [^ IndexedColors at: (p bitAnd: 16r01) + 1]. (d = 16) | (d = 15) ifTrue: [ "five bits per component" r _ (p bitShift: -10) bitAnd: 16r1F. g _ (p bitShift: -5) bitAnd: 16r1F. b _ p bitAnd: 16r1F. (r = 0 and: [g = 0]) ifTrue: [ b = 0 ifTrue: [^Color transparent]. b = 1 ifTrue: [^Color black]]. ^ Color r: r g: g b: b range: 31]. d = 32 ifTrue: [ "eight bits per component; 8 bits of alpha" r _ (p bitShift: -16) bitAnd: 16rFF. g _ (p bitShift: -8) bitAnd: 16rFF. b _ p bitAnd: 16rFF. alpha _ p bitShift: -24. alpha = 0 ifTrue: [^Color transparent]. (r = 0 and: [g = 0 and: [b = 0]]) ifTrue: [^Color transparent]. alpha < 255 ifTrue: [^ (Color r: r g: g b: b range: 255) alpha: (alpha asFloat / 255.0)] ifFalse: [^ (Color r: r g: g b: b range: 255)]]. d = 12 ifTrue: [ "four bits per component" r _ (p bitShift: -8) bitAnd: 16rF. g _ (p bitShift: -4) bitAnd: 16rF. b _ p bitAnd: 16rF. ^ Color r: r g: g b: b range: 15]. d = 9 ifTrue: [ "three bits per component" r _ (p bitShift: -6) bitAnd: 16r7. g _ (p bitShift: -3) bitAnd: 16r7. b _ p bitAnd: 16r7. ^ Color r: r g: g b: b range: 7]. self error: 'unknown pixel depth: ', d printString ! ! !Color class methodsFor: 'instance creation' stamp: 'mir 7/21/1999 11:54'! fromArray: colorDef colorDef size == 3 ifTrue: [^self r: (colorDef at: 1) g: (colorDef at: 2) b: (colorDef at: 3)]. colorDef size == 0 ifTrue: [^Color transparent]. colorDef size == 4 ifTrue: [^(TranslucentColor r: (colorDef at: 1) g: (colorDef at: 2) b: (colorDef at: 3)) alpha: (colorDef at: 4)]. self error: 'Undefined color definition'! ! !Color class methodsFor: 'instance creation' stamp: 'sw 8/8/97 22:03'! fromRgbTriplet: list ^ self r: list first g: list second b: list last! ! !Color class methodsFor: 'instance creation' stamp: 'dvf 6/16/2000 17:48'! fromString: aString "for HTML color spec: #FFCCAA or white/black" "Color fromString: '#FFCCAA'. Color fromString: 'white'. Color fromString: 'orange'" | aColorHex red green blue | aString isEmptyOrNil ifTrue: [^ Color white]. aString first = $# ifTrue: [aColorHex _ aString copyFrom: 2 to: aString size] ifFalse: [aColorHex _ aString]. [aColorHex size = 6 ifTrue: [aColorHex _ aColorHex asUppercase. red _ ('16r', (aColorHex copyFrom: 1 to: 2)) asNumber/255. green _ ('16r', (aColorHex copyFrom: 3 to: 4)) asNumber/255. blue _ ('16r', (aColorHex copyFrom: 5 to: 6)) asNumber/255. ^ self r: red g: green b: blue]] ifError: [:err :rcvr | "not a hex color triplet" ]. "try to match aColorHex with known named colors" aColorHex _ aColorHex asLowercase. ^self perform: (ColorNames detect: [:i | i asString asLowercase = aColorHex] ifNone: [#white])! ! !Color class methodsFor: 'instance creation' stamp: 'jm 12/4/97 13:05'! gray: brightness "Return a gray shade with the given brightness in the range [0.0..1.0]." ^ self basicNew setRed: brightness green: brightness blue: brightness ! ! !Color class methodsFor: 'instance creation'! h: hue s: saturation v: brightness "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, (Color h: 0 s: 1 v: 1) is pure red." "Note: By convention, brightness is abbreviated 'v' to to avoid confusion with blue." ^ self basicNew setHue: hue saturation: saturation brightness: brightness! ! !Color class methodsFor: 'instance creation' stamp: 'dew 3/19/2002 23:49'! h: h s: s v: v alpha: alpha ^ (self h: h s: s v: v) alpha: alpha! ! !Color class methodsFor: 'instance creation'! new ^ self r: 0.0 g: 0.0 b: 0.0! ! !Color class methodsFor: 'instance creation' stamp: 'jm 12/4/97 13:04'! r: r g: g b: b "Return a color with the given r, g, and b components in the range [0.0..1.0]." ^ self basicNew setRed: r green: g blue: b ! ! !Color class methodsFor: 'instance creation'! r: r g: g b: b alpha: alpha ^ (self r: r g: g b: b) alpha: alpha! ! !Color class methodsFor: 'instance creation'! r: r g: g b: b range: range "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)." ^ self basicNew setRed: r green: g blue: b range: range! ! !Color class methodsFor: 'instance creation'! random "Return a random color that isn't too dark or under-saturated." ^ self basicNew setHue: (360.0 * RandomStream next) saturation: (0.3 + (RandomStream next * 0.7)) brightness: (0.4 + (RandomStream next * 0.6))! ! !Color class methodsFor: 'class initialization'! initialize "Color initialize" "Details: Externally, the red, green, and blue components of color are floats in the range [0.0..1.0]. Internally, they are represented as integers in the range [0..ComponentMask] packing into a small integer to save space and to allow fast hashing and equality testing. For a general description of color representations for computer graphics, including the relationship between the RGB and HSV color models used here, see Chapter 17 of Foley and van Dam, Fundamentals of Interactive Computer Graphics, Addison-Wesley, 1982." ComponentMask _ 1023. HalfComponentMask _ 512. "used to round up in integer calculations" ComponentMax _ 1023.0. "a Float used to normalize components" RedShift _ 20. GreenShift _ 10. BlueShift _ 0. PureRed _ self r: 1 g: 0 b: 0. PureGreen _ self r: 0 g: 1 b: 0. PureBlue _ self r: 0 g: 0 b: 1. PureYellow _ self r: 1 g: 1 b: 0. PureCyan _ self r: 0 g: 1 b: 1. PureMagenta _ self r: 1 g: 0 b: 1. RandomStream _ Random new. self initializeIndexedColors. self initializeGrayToIndexMap. self initializeNames. self initializeHighLights. ! ! !Color class methodsFor: 'class initialization'! initializeGrayToIndexMap "Build an array of gray values available in the 8-bit colormap. This array is indexed by a gray level between black (1) and white (256) and returns the pixel value for the corresponding gray level." "Note: This method must be called after initializeIndexedColors, since it uses IndexedColors." "Color initializeGrayToIndexMap" | grayLevels grayIndices c distToClosest dist indexOfClosest | "record the level and index of each gray in the 8-bit color table" grayLevels _ OrderedCollection new. grayIndices _ OrderedCollection new. "Note: skip the first entry, which is reserved for transparent" 2 to: IndexedColors size do: [:i | c _ IndexedColors at: i. c saturation = 0.0 ifTrue: [ "c is a gray" grayLevels add: (c privateBlue) >> 2. "top 8 bits; R, G, and B are the same" grayIndices add: i - 1]]. "pixel values are zero-based" grayLevels _ grayLevels asArray. grayIndices _ grayIndices asArray. "for each gray level in [0..255], select the closest match" GrayToIndexMap _ ByteArray new: 256. 0 to: 255 do: [:level | distToClosest _ 10000. "greater than distance to any real gray" 1 to: grayLevels size do: [:i | dist _ (level - (grayLevels at: i)) abs. dist < distToClosest ifTrue: [ distToClosest _ dist. indexOfClosest _ grayIndices at: i]]. GrayToIndexMap at: (level + 1) put: indexOfClosest]. ! ! !Color class methodsFor: 'class initialization' stamp: 'tk 6/22/96'! initializeHighLights "Create a set of Bitmaps for quickly reversing areas of the screen without converting colors. " "Color initializeHighLights" | t | t _ Array new: 32. t at: 1 put: (Bitmap with: 16rFFFFFFFF). t at: 2 put: (Bitmap with: 16rFFFFFFFF). t at: 4 put: (Bitmap with: 16r55555555). t at: 8 put: (Bitmap with: 16r7070707). t at: 16 put: (Bitmap with: 16rFFFFFFFF). t at: 32 put: (Bitmap with: 16rFFFFFFFF). HighLightBitmaps _ t. ! ! !Color class methodsFor: 'class initialization'! initializeIndexedColors "Build an array of colors corresponding to the fixed colormap used for display depths of 1, 2, 4, or 8 bits." "Color initializeIndexedColors" | a index grayVal | a _ Array new: 256. "1-bit colors (monochrome)" a at: 1 put: (Color r: 1.0 g: 1.0 b: 1.0). "white or transparent" a at: 2 put: (Color r: 0.0 g: 0.0 b: 0.0). "black" "additional colors for 2-bit color" a at: 3 put: (Color r: 1.0 g: 1.0 b: 1.0). "opaque white" a at: 4 put: (Color r: 0.5 g: 0.5 b: 0.5). "1/2 gray" "additional colors for 4-bit color" a at: 5 put: (Color r: 1.0 g: 0.0 b: 0.0). "red" a at: 6 put: (Color r: 0.0 g: 1.0 b: 0.0). "green" a at: 7 put: (Color r: 0.0 g: 0.0 b: 1.0). "blue" a at: 8 put: (Color r: 0.0 g: 1.0 b: 1.0). "cyan" a at: 9 put: (Color r: 1.0 g: 1.0 b: 0.0). "yellow" a at: 10 put: (Color r: 1.0 g: 0.0 b: 1.0). "magenta" a at: 11 put: (Color r: 0.125 g: 0.125 b: 0.125). "1/8 gray" a at: 12 put: (Color r: 0.25 g: 0.25 b: 0.25). "2/8 gray" a at: 13 put: (Color r: 0.375 g: 0.375 b: 0.375). "3/8 gray" a at: 14 put: (Color r: 0.625 g: 0.625 b: 0.625). "5/8 gray" a at: 15 put: (Color r: 0.75 g: 0.75 b: 0.75). "6/8 gray" a at: 16 put: (Color r: 0.875 g: 0.875 b: 0.875). "7/8 gray" "additional colors for 8-bit color" "24 more shades of gray (1/32 increments but not repeating 1/8 increments)" index _ 17. 1 to: 31 do: [:v | (v \\ 4) = 0 ifFalse: [ grayVal _ v / 32.0. a at: index put: (Color r: grayVal g: grayVal b: grayVal). index _ index + 1]]. "The remainder of color table defines a color cube with six steps for each primary color. Note that the corners of this cube repeat previous colors, but this simplifies the mapping between RGB colors and color map indices. This color cube spans indices 40 through 255 (indices 41-256 in this 1-based array)." 0 to: 5 do: [:r | 0 to: 5 do: [:g | 0 to: 5 do: [:b | index _ 41 + ((36 * r) + (6 * b) + g). index > 256 ifTrue: [ self error: 'index out of range in color table compuation']. a at: index put: (Color r: r g: g b: b range: 5)]]]. IndexedColors _ a. ! ! !Color class methodsFor: 'class initialization' stamp: 'dwh 7/7/1999 23:57'! initializeNames "Name some colors." "Color initializeNames" ColorNames _ OrderedCollection new. self named: #black put: (Color r: 0 g: 0 b: 0). self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125). self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25). self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375). self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5). self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625). self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75). self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875). self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0). self named: #red put: (Color r: 1.0 g: 0 b: 0). self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0). self named: #green put: (Color r: 0 g: 1.0 b: 0). self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0). self named: #blue put: (Color r: 0 g: 0 b: 1.0). self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0). self named: #brown put: (Color r: 0.6 g: 0.2 b: 0). self named: #orange put: (Color r: 1.0 g: 0.6 b: 0). self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8). self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8). self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6). self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0). self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0). self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0). self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2). self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4). self named: #transparent put: (TranslucentColor new alpha: 0.0). self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range: 255). self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range: 255). self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range: 255). self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range: 255). self named: #paleRed put: (Color r: 255 g: 230 b: 230 range: 255). self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range: 255). self named: #paleTan put: (Color r: 235 g: 224 b: 199 range: 255). self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range: 255). self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range: 255). self named: #palePeach put: (Color r: 255 g: 237 b: 213 range: 255). ! ! !Color class methodsFor: 'class initialization' stamp: 'ar 2/16/2000 21:56'! initializeTranslucentPatterns "Color initializeTranslucentPatterns" | mask bits pattern patternList | TranslucentPatterns _ Array new: 8. #(1 2 4 8) do:[:d| patternList _ Array new: 5. mask _ (1 bitShift: d) - 1. bits _ 2 * d. [bits >= 32] whileFalse: [ mask _ mask bitOr: (mask bitShift: bits). "double the length of mask" bits _ bits + bits]. "0% pattern" pattern _ Bitmap with: 0 with: 0. patternList at: 1 put: pattern. "25% pattern" pattern _ Bitmap with: mask with: 0. patternList at: 2 put: pattern. "50% pattern" pattern _ Bitmap with: mask with: mask bitInvert32. patternList at: 3 put: pattern. "75% pattern" pattern _ Bitmap with: mask with: 16rFFFFFFFF. patternList at: 4 put: pattern. "100% pattern" pattern _ Bitmap with: 16rFFFFFFFF with: 16rFFFFFFFF. patternList at: 5 put: pattern. TranslucentPatterns at: d put: patternList. ].! ! !Color class methodsFor: 'class initialization' stamp: 'tk 6/13/96'! named: newName put: aColor "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 colorNames) returns a list of all color names. " | str cap sym accessor csym | (aColor isKindOf: self) ifFalse: [^ self error: 'not a Color']. str _ newName asString. sym _ str asSymbol. cap _ str capitalized. csym _ cap asSymbol. (self class canUnderstand: sym) ifFalse: [ "define access message" accessor _ str, (String with: Character cr with: Character tab), '^', cap. self class compile: accessor classified: 'named colors']. (self classPool includesKey: csym) ifFalse: [ self addClassVarName: cap]. (ColorNames includes: sym) ifFalse: [ ColorNames add: sym]. ^ self classPool at: csym put: aColor! ! !Color class methodsFor: 'examples'! colorRampForDepth: depth extent: aPoint "Returns a form of the given size showing R, G, B, and gray ramps for the given depth. Useful for testing color conversions between different depths." "(Color colorRampForDepth: Display depth extent: 256@80) display" "(Color colorRampForDepth: 32 extent: 256@80) displayOn: Display at: 0@0 rule: Form paint" | f dx dy r | f _ Form extent: aPoint depth: depth. dx _ aPoint x // 256. dy _ aPoint y // 4. 0 to: 255 do: [:i | r _ (dx * i)@0 extent: dx@dy. f fill: r fillColor: (Color r: i g: 0 b: 0 range: 255). r _ r translateBy: 0@dy. f fill: r fillColor: (Color r: 0 g: i b: 0 range: 255). r _ r translateBy: 0@dy. f fill: r fillColor: (Color r: 0 g: 0 b: i range: 255). r _ r translateBy: 0@dy. f fill: r fillColor: (Color r: i g: i b: i range: 255)]. ^ f ! ! !Color class methodsFor: 'examples' stamp: 'tk 6/19/96'! hotColdShades: thisMany "An array of thisMany colors showing temperature from blue to red to white hot. (Later improve this by swinging in hue.) " "Color showColors: (Color hotColdShades: 25)" | n s1 s2 s3 s4 s5 | thisMany < 5 ifTrue: [^ self error: 'must be at least 5 shades']. n _ thisMany // 5. s1 _ self white mix: self yellow shades: (thisMany - (n*4)). s2 _ self yellow mix: self red shades: n+1. s2 _ s2 copyFrom: 2 to: n+1. s3 _ self red mix: self green darker shades: n+1. s3 _ s3 copyFrom: 2 to: n+1. s4 _ self green darker mix: self blue shades: n+1. s4 _ s4 copyFrom: 2 to: n+1. s5 _ self blue mix: self black shades: n+1. s5 _ s5 copyFrom: 2 to: n+1. ^ s1, s2, s3, s4, s5 ! ! !Color class methodsFor: 'examples'! showColorCube "Show a 12x12x12 color cube." "Color showColorCube" 0 to: 11 do: [:r | 0 to: 11 do: [:g | 0 to: 11 do: [:b | Display fill: (((r*60) + (b*5)) @ (g*5) extent: 5@5) fillColor: (Color r: r g: g b: b range: 11)]]]. ! ! !Color class methodsFor: 'examples'! showColors: colorList "Display the given collection of colors across the top of the Display." | w r | w _ Display width // colorList size. r _ 0@0 extent: w@((w min: 30) max: 10). colorList do: [:c | Display fill: r fillColor: c. r _ r translateBy: w@0]. ! ! !Color class methodsFor: 'examples'! showHSVPalettes "Shows a palette of hues, varying the saturation and brightness for each one. Best results are with depths 16 and 32." "Color showHSVPalettes" | left top c | left _ top _ 0. 0 to: 179 by: 15 do: [:h | 0 to: 10 do: [:s | left _ (h * 4) + (s * 4). 0 to: 10 do: [:v | c _ Color h: h s: s asFloat / 10.0 v: v asFloat / 10.0. top _ (v * 4). Display fill: (left@top extent: 4@4) fillColor: c. c _ Color h: h + 180 s: s asFloat / 10.0 v: v asFloat / 10.0. top _ (v * 4) + 50. Display fill: (left@top extent: 4@4) fillColor: c]]]. ! ! !Color class methodsFor: 'examples'! showHuesInteractively "Shows a palette of hues at a (saturation, brightness) point determined by the mouse position. Click the mouse button to exit and return the selected (saturation, brightness) point." "Color showHuesInteractively" | p s v | [Sensor anyButtonPressed] whileFalse: [ p _ Sensor cursorPoint. s _ p x asFloat / 300.0. v _ p y asFloat / 300.0. self showColors: (self wheel: 12 saturation: s brightness: v)]. ^ (s min: 1.0) @ (v min: 1.0)! ! !Color class methodsFor: 'examples'! wheel: thisMany "Return a collection of thisMany colors evenly spaced around the color wheel." "Color showColors: (Color wheel: 12)" ^ Color wheel: thisMany saturation: 0.9 brightness: 0.7 ! ! !Color class methodsFor: 'examples'! wheel: thisMany saturation: s brightness: v "Return a collection of thisMany colors evenly spaced around the color wheel, all of the given saturation and brightness." "Color showColors: (Color wheel: 12 saturation: 0.4 brightness: 1.0)" "Color showColors: (Color wheel: 12 saturation: 0.8 brightness: 0.5)" ^ (Color h: 0.0 s: s v: v) wheel: thisMany ! ! !Color class methodsFor: 'named colors'! black ^Black! ! !Color class methodsFor: 'named colors'! blue ^Blue! ! !Color class methodsFor: 'named colors'! brown ^Brown! ! !Color class methodsFor: 'named colors'! cyan ^Cyan! ! !Color class methodsFor: 'named colors'! darkGray ^DarkGray! ! !Color class methodsFor: 'named colors'! gray ^Gray! ! !Color class methodsFor: 'named colors'! green ^Green! ! !Color class methodsFor: 'named colors'! lightBlue ^LightBlue! ! !Color class methodsFor: 'named colors'! lightBrown ^LightBrown! ! !Color class methodsFor: 'named colors'! lightCyan ^LightCyan! ! !Color class methodsFor: 'named colors'! lightGray ^LightGray! ! !Color class methodsFor: 'named colors'! lightGreen ^LightGreen! ! !Color class methodsFor: 'named colors'! lightMagenta ^LightMagenta! ! !Color class methodsFor: 'named colors'! lightOrange ^LightOrange! ! !Color class methodsFor: 'named colors'! lightRed ^LightRed! ! !Color class methodsFor: 'named colors'! lightYellow ^LightYellow! ! !Color class methodsFor: 'named colors'! magenta ^Magenta! ! !Color class methodsFor: 'named colors'! orange ^Orange! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleBlue ^PaleBlue! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleBuff ^PaleBuff! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleGreen ^PaleGreen! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleMagenta ^PaleMagenta! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleOrange ^PaleOrange! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! palePeach ^PalePeach! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleRed ^PaleRed! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleTan ^PaleTan! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! paleYellow ^PaleYellow! ! !Color class methodsFor: 'named colors'! red ^Red! ! !Color class methodsFor: 'named colors' stamp: 'wod 5/24/1998 01:56'! tan ^ Color r: 0.8 g: 0.8 b: 0.5! ! !Color class methodsFor: 'named colors'! transparent ^Transparent! ! !Color class methodsFor: 'named colors'! veryDarkGray ^VeryDarkGray! ! !Color class methodsFor: 'named colors'! veryLightGray ^VeryLightGray! ! !Color class methodsFor: 'named colors' stamp: 'dwh 7/7/1999 23:56'! veryPaleRed ^VeryPaleRed! ! !Color class methodsFor: 'named colors'! veryVeryDarkGray ^VeryVeryDarkGray! ! !Color class methodsFor: 'named colors'! veryVeryLightGray ^VeryVeryLightGray! ! !Color class methodsFor: 'named colors'! white ^White! ! !Color class methodsFor: 'named colors'! yellow ^Yellow! ! !Color class methodsFor: 'colormaps' stamp: 'jm 5/2/1999 07:24'! cachedColormapFrom: sourceDepth to: destDepth "Return a cached colormap for mapping between the given depths. Always return a real colormap, not nil; this allows the client to get an identity colormap that can then be copied and modified to do color transformations." "Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!" "Note: The colormap cache may be cleared by evaluating 'Color shutDown'." | srcIndex map | CachedColormaps class == Array ifFalse: [CachedColormaps _ (1 to: 9) collect: [:i | Array new: 32]]. srcIndex _ sourceDepth. sourceDepth > 8 ifTrue: [srcIndex _ 9]. (map _ (CachedColormaps at: srcIndex) at: destDepth) ~~ nil ifTrue: [^ map]. map _ self computeColormapFrom: sourceDepth to: destDepth. (CachedColormaps at: srcIndex) at: destDepth put: map. ^ map ! ! !Color class methodsFor: 'colormaps'! colorMapIfNeededFrom: sourceDepth to: destDepth "Return a colormap for mapping between the given depths, or nil if no colormap is needed." "Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!" sourceDepth = destDepth ifTrue: [^ nil]. "not needed if depths are the same" (sourceDepth >= 16) & (destDepth >= 16) ifTrue: [ "mapping is done in BitBlt by zero-filling or truncating each color component" ^ nil]. ^ Color cachedColormapFrom: sourceDepth to: destDepth ! ! !Color class methodsFor: 'colormaps' stamp: 'jm 3/25/1999 19:48'! computeColormapFrom: sourceDepth to: destDepth "Compute a colorMap for translating between the given depths. A colormap is a Bitmap whose entries contain the pixel values for the destination depth. Typical clients use cachedColormapFrom:to: instead." | map bitsPerColor | sourceDepth < 16 ifTrue: [ "source is 1-, 2-, 4-, or 8-bit indexed color" map _ (IndexedColors copyFrom: 1 to: (1 bitShift: sourceDepth)) collect: [:c | c pixelValueForDepth: destDepth]. map _ map as: Bitmap. ] ifFalse: [ "source is 16-bit or 32-bit RGB" destDepth > 8 ifTrue: [bitsPerColor _ 5] "retain maximum color resolution" ifFalse: [bitsPerColor _ 4]. map _ self computeRGBColormapFor: destDepth bitsPerColor: bitsPerColor]. "Note: zero is transparent except when source depth is one-bit deep" sourceDepth > 1 ifTrue: [map at: 1 put: 0]. ^ map ! ! !Color class methodsFor: 'colormaps' stamp: 'jm 12/4/97 15:25'! computeRGBColormapFor: destDepth bitsPerColor: bitsPerColor "Compute a colorMap for translating from 16-bit or 32-bit RGB color to the given depth, using the given number of of bits per color component." | mask map c | (#(3 4 5) includes: bitsPerColor) ifFalse: [self error: 'BitBlt only supports 3, 4, or 5 bits per color component']. mask _ (1 bitShift: bitsPerColor) - 1. map _ Bitmap new: (1 bitShift: (3 * bitsPerColor)). 0 to: map size - 1 do: [:i | c _ Color r: ((i bitShift: 0 - (2 * bitsPerColor)) bitAnd: mask) g: ((i bitShift: 0 - bitsPerColor) bitAnd: mask) b: ((i bitShift: 0) bitAnd: mask) range: mask. map at: i + 1 put: (c pixelValueForDepth: destDepth)]. map at: 1 put: (Color transparent pixelWordForDepth: destDepth). "zero always transparent" ^ map ! ! !Color class methodsFor: 'other'! colorNames "Return a collection of color names." ^ ColorNames! ! !Color class methodsFor: 'other'! indexedColors ^ IndexedColors! ! !Color class methodsFor: 'other' stamp: 'di 3/29/1999 13:33'! maskingMap: depth "Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero. Cache the most recently used map." | sizeNeeded | depth <= 8 ifTrue: [sizeNeeded _ 1 bitShift: depth] ifFalse: [sizeNeeded _ 4096]. (MaskingMap == nil or: [MaskingMap size ~= sizeNeeded]) ifTrue: [MaskingMap _ Bitmap new: sizeNeeded withAll: 16rFFFFFFFF. MaskingMap at: 1 put: 0. "transparent"]. ^ MaskingMap ! ! !Color class methodsFor: 'other'! pixelScreenForDepth: depth "Return a 50% stipple containing alternating pixels of all-zeros and all-ones to be used as a mask at the given depth." | mask bits | mask _ (1 bitShift: depth) - 1. bits _ 2 * depth. [bits >= 32] whileFalse: [ mask _ mask bitOr: (mask bitShift: bits). "double the length of mask" bits _ bits + bits]. ^ Bitmap with: mask with: mask bitInvert32 ! ! !Color class methodsFor: 'other'! quickHighLight: depth "Quickly return a Bitblt-ready raw colorValue for highlighting areas. 6/22/96 tk" ^ HighLightBitmaps at: depth! ! !Color class methodsFor: 'other'! shutDown "Color shutDown" ColorChart _ nil. "Palette of colors for the user to pick from" CachedColormaps _ nil. "Maps to translate between color depths" MaskingMap _ nil. "Maps all colors except transparent to black for creating a mask" ! ! !Color class methodsFor: 'other' stamp: 'ar 2/16/2000 21:56'! translucentMaskFor: alphaValue depth: d "Return a pattern representing a mask usable for stipple transparency" ^(TranslucentPatterns at: d) at: ((alphaValue min: 1.0 max: 0.0) * 4) rounded + 1! ! !Color class methodsFor: 'color from user' stamp: 'jm 12/5/97 18:35'! colorPaletteForDepth: depth extent: chartExtent "Display a palette of colors sorted horizontally by hue and vertically by lightness. Useful for eyeballing the color gamut of the display, or for choosing a color interactively." "Note: It is slow to build this palette, so it should be cached for quick access." "(Color colorPaletteForDepth: 16 extent: 190@60) display" | basicHue x y c startHue palette transHt vSteps transCaption grayWidth hSteps | palette _ Form extent: chartExtent depth: depth. transCaption _ "(DisplayText text: 'no color' asText textStyle: (TextConstants at: #ComicPlain)) form storeString" (Form extent: 34@9 depth: 1 fromArray: #(0 0 256 0 256 0 3808663859 2147483648 2491688266 2147483648 2491688266 0 2491688266 0 2466486578 0 0 0) offset: 0@0). transHt _ transCaption height. palette fillWhite: (0@0 extent: palette width@transHt). palette fillBlack: (0@transHt extent: palette width@1). transCaption displayOn: palette at: palette boundingBox topCenter - ((transCaption width // 2)@0). grayWidth _ 10. startHue _ 338.0. vSteps _ palette height - transHt // 2. hSteps _ palette width - grayWidth. x _ 0. startHue to: startHue + 360.0 by: 360.0/hSteps do: [:h | basicHue _ Color h: h asFloat s: 1.0 v: 1.0. y _ transHt+1. 0 to: vSteps do: [:n | c _ basicHue mixed: (n asFloat / vSteps asFloat) with: Color white. palette fill: (x@y extent: 1@1) fillColor: c. y _ y + 1]. 1 to: vSteps do: [:n | c _ Color black mixed: (n asFloat / vSteps asFloat) with: basicHue. palette fill: (x@y extent: 1@1) fillColor: c. y _ y + 1]. x _ x + 1]. y _ transHt + 1. 1 to: vSteps * 2 do: [:n | c _ Color black mixed: (n asFloat / (vSteps*2) asFloat) with: Color white. palette fill: (x@y extent: 10@1) fillColor: c. y _ y + 1]. ^ palette ! ! !Color class methodsFor: 'color from user' stamp: 'jm 1/19/1999 11:33'! colorTest: depth extent: chartExtent colorMapper: colorMapper "Create a palette of colors sorted horizontally by hue and vertically by lightness. Useful for eyeballing the color gamut of the display, or for choosing a color interactively." "Note: It is slow to build this palette, so it should be cached for quick access." "(Color colorTest: 32 extent: 570@180 colorMapper: [:c | c]) display" "(Color colorTest: 32 extent: 570@180 colorMapper: [:c | Color r: (c red * 7) asInteger / 7 g: (c green * 7) asInteger / 7 b: (c blue * 3) asInteger / 3]) display" "(Color colorTest: 32 extent: 570@180 colorMapper: [:c | Color r: (c red * 5) asInteger / 5 g: (c green * 5) asInteger / 5 b: (c blue * 5) asInteger / 5]) display" "(Color colorTest: 32 extent: 570@180 colorMapper: [:c | Color r: (c red * 15) asInteger / 15 g: (c green * 15) asInteger / 15 b: (c blue * 15) asInteger / 15]) display" "(Color colorTest: 32 extent: 570@180 colorMapper: [:c | Color r: (c red * 31) asInteger / 31 g: (c green * 31) asInteger / 31 b: (c blue * 31) asInteger / 31]) display" | basicHue x y c startHue palette transHt vSteps transCaption grayWidth hSteps | palette _ Form extent: chartExtent depth: depth. transCaption _ "(DisplayText text: 'no color' asText textStyle: (TextConstants at: #ComicPlain)) form storeString" (Form extent: 34@9 depth: 1 fromArray: #(0 0 256 0 256 0 3808663859 2147483648 2491688266 2147483648 2491688266 0 2491688266 0 2466486578 0 0 0) offset: 0@0). transHt _ transCaption height. palette fillWhite: (0@0 extent: palette width@transHt). palette fillBlack: (0@transHt extent: palette width@1). transCaption displayOn: palette at: palette boundingBox topCenter - ((transCaption width // 2)@0). grayWidth _ 10. startHue _ 338.0. vSteps _ palette height - transHt // 2. hSteps _ palette width - grayWidth. x _ 0. startHue to: startHue + 360.0 by: 360.0/hSteps do: [:h | basicHue _ Color h: h asFloat s: 1.0 v: 1.0. y _ transHt+1. 0 to: vSteps do: [:n | c _ basicHue mixed: (n asFloat / vSteps asFloat) with: Color white. c _ colorMapper value: c. palette fill: (x@y extent: 1@1) fillColor: c. y _ y + 1]. 1 to: vSteps do: [:n | c _ Color black mixed: (n asFloat / vSteps asFloat) with: basicHue. c _ colorMapper value: c. palette fill: (x@y extent: 1@1) fillColor: c. y _ y + 1]. x _ x + 1]. y _ transHt + 1. 1 to: vSteps * 2 do: [:n | c _ Color black mixed: (n asFloat / (vSteps*2) asFloat) with: Color white. c _ colorMapper value: c. palette fill: (x@y extent: 10@1) fillColor: c. y _ y + 1]. ^ palette ! ! !Color class methodsFor: 'color from user' stamp: 'di 4/13/1999 14:30'! fromUser "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette." "Note: Since the color chart is cached, you may need to do 'ColorChart _ nil' after changing the oldColorPaletteForDepth:extent: method." "Color fromUser" | d startPt save tr oldColor c here s | d _ Display depth. ((ColorChart == nil) or: [ColorChart depth ~= Display depth]) ifTrue: [ColorChart _ self oldColorPaletteForDepth: d extent: (2 * 144)@80]. Sensor cursorPoint y < Display center y ifTrue: [startPt _ 0@(Display boundingBox bottom - ColorChart height)] ifFalse: [startPt _ 0@0]. save _ Form fromDisplay: (startPt extent: ColorChart extent). ColorChart displayAt: startPt. tr _ ColorChart extent - (50@19) corner: ColorChart extent. tr _ tr translateBy: startPt. oldColor _ nil. [Sensor anyButtonPressed] whileFalse: [ c _ Display colorAt: (here _ Sensor cursorPoint). (tr containsPoint: here) ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c] ifTrue: [ c _ Color transparent. Display fill: (0@61+startPt extent: 20@19) fillColor: Color white]. c = oldColor ifFalse: [ Display fillWhite: (20@61 + startPt extent: 135@19). c isTransparent ifTrue: [s _ 'transparent'] ifFalse: [s _ c shortPrintString. s _ s copyFrom: 7 to: s size - 1]. s displayAt: 20@61 + startPt. oldColor _ c]]. save displayAt: startPt. Sensor waitNoButton. ^ c ! ! !Color class methodsFor: 'color from user' stamp: 'di 4/13/1999 14:28'! oldColorPaletteForDepth: depth extent: paletteExtent "Returns a form of the given size showing a color palette for the given depth." "(Color oldColorPaletteForDepth: Display depth extent: 720@100) display" | c p f nSteps rect w h q | f _ Form extent: paletteExtent depth: depth. f fill: f boundingBox fillColor: Color white. nSteps _ depth > 8 ifTrue: [12] ifFalse: [6]. w _ paletteExtent x // (nSteps * nSteps). h _ paletteExtent y - 20 // nSteps. 0 to: nSteps-1 do: [:r | 0 to: nSteps-1 do: [:g | 0 to: nSteps-1 do: [:b | c _ Color r: r g: g b: b range: nSteps - 1. rect _ ((r * nSteps * w) + (b * w)) @ (g * h) extent: w@(h + 1). f fill: rect fillColor: c]]]. q _ Quadrangle origin: paletteExtent - (50@19) corner: paletteExtent. q displayOn: f. 'Trans.' displayOn: f at: q origin + (9@1). w _ ((paletteExtent x - q width - 130) // 64) max: 1. p _ paletteExtent x - q width - (64 * w) - 1 @ (paletteExtent y - 19). 0 to: 63 do: [:v | c _ Color r: v g: v b: v range: 63. f fill: ((v * w)@0 + p extent: (w + 1)@19) fillColor: c]. ^ f ! ! ArrayedCollection variableWordSubclass: #ColorArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !ColorArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 20:03'! at: index ^(super at: index) asColorOfDepth: 32! ! !ColorArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 20:04'! at: index put: aColor ^super at: index put: (aColor pixelWordForDepth: 32).! ! !ColorArray methodsFor: 'converting' stamp: 'ar 3/3/2001 20:06'! asColorArray ^self! ! !ColorArray methodsFor: 'converting' stamp: 'RAA 3/8/2001 06:24'! bytesPerElement ^4! ! Form subclass: #ColorForm instanceVariableNames: 'colors cachedDepth cachedColormap' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !ColorForm commentStamp: '<historical>' prior: 0! ColorForm is a normal Form plus a color map of up to 2^depth Colors. Typically, one reserves one entry in the color map for transparent. This allows 1, 3, 15, or 255 non-transparent colors in ColorForms of depths 1, 2, 4, and 8 bits per pixel. ColorForms don't support depths greater than 8 bits because that would require excessively large color maps with little real benefit, since 16-bit and 32-bit depths already support thousands and millions of colors. ColorForms have several uses: 1) Precise colors. You can have up to 256 true colors, instead being limited to the 8-bit color palette. 2) Easy transparency. Just store (Color transparent) at the desired position in the color map. 3) Cheap color remapping by changing the color map. A color map is an Array of up to 2^depth Color objects. A Bitmap colorMap is automatically computed and cached for rapid display. Note that if you change the color map, you must resubmit it via the colors: method to flush this cache. ColorForms can be a bit tricky. Note that: a) When you BitBlt from one ColorForm to another, you must remember to copy the color map of the source ColorForm to the destination ColorForm. b) A ColorForm's color map is an array of depth-independent Color objects. BitBlt requires a BitMap of actual pixel values, adjusted to the destination depth. These are different things!! ColorForms automatically maintain a cache of the BitBlt-style color map corresponding to the colors array for the last depth on which the ColorForm was displayed, so there should be little need for clients to work with BitBlt-style color maps. c) The default map for 8 bit depth has black in the first entry, not transparent. Say (cform colors at: 1 put: Color transparent). ! !ColorForm methodsFor: 'accessing' stamp: 'jm 11/14/97 17:39'! colors "Return my color palette." self ensureColorArrayExists. ^ colors ! ! !ColorForm methodsFor: 'accessing' stamp: 'ar 5/17/2001 15:45'! colors: colorList "Set my color palette to the given collection." | colorArray colorCount newColors | colorList ifNil: [ colors _ cachedDepth _ cachedColormap _ nil. ^ self]. colorArray _ colorList asArray. colorCount _ colorArray size. newColors _ Array new: (1 bitShift: self depth). 1 to: newColors size do: [:i | i <= colorCount ifTrue: [newColors at: i put: (colorArray at: i)] ifFalse: [newColors at: i put: Color transparent]]. colors _ newColors. cachedDepth _ nil. cachedColormap _ nil. ! ! !ColorForm methodsFor: 'accessing' stamp: 'mir 7/21/1999 11:51'! colorsFromArray: colorArray | colorList | colorList _ colorArray collect: [:colorDef | Color fromArray: colorDef]. self colors: colorList! ! !ColorForm methodsFor: 'displaying' stamp: 'ar 5/14/2001 23:32'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm aDisplayMedium copyBits: self boundingBox from: self at: aDisplayPoint + self offset clippingBox: clipRectangle rule: rule fillColor: aForm map: (self colormapIfNeededFor: aDisplayMedium). ! ! !ColorForm methodsFor: 'displaying' stamp: 'di 7/17/97 10:04'! displayOnPort: port at: location port copyForm: self to: location rule: Form paint! ! !ColorForm methodsFor: 'displaying' stamp: 'ar 12/14/2001 18:14'! maskingMap "Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero." | maskingMap | maskingMap _ Bitmap new: (1 bitShift: depth) withAll: 16rFFFFFFFF. 1 to: colors size do:[:i| (colors at: i) isTransparent ifTrue:[maskingMap at: i put: 0]. ]. colors size+1 to: maskingMap size do:[:i| maskingMap at: i put: 0]. ^maskingMap! ! !ColorForm methodsFor: 'pixel accessing' stamp: 'jm 11/14/97 17:25'! colorAt: aPoint "Return the color of the pixel at aPoint." ^ self colors at: (self pixelValueAt: aPoint) + 1 ! ! !ColorForm methodsFor: 'pixel accessing' stamp: 'jm 11/14/97 17:25'! colorAt: aPoint put: aColor "Store the given color into the pixel at aPoint. The given color must match one of the colors in the receiver's colormap." | i | i _ self colors indexOf: aColor ifAbsent: [^ self error: 'trying to use a color that is not in my colormap']. self pixelValueAt: aPoint put: i - 1. ! ! !ColorForm methodsFor: 'pixel accessing' stamp: 'tk 10/21/97 12:27'! isTransparentAt: aPoint "Return true if the receiver is transparent at the given point." ^ (self colorAt: aPoint) isTransparent ! ! !ColorForm methodsFor: 'pixel accessing' stamp: 'ar 5/28/2000 12:06'! pixelValueAt: aPoint "Return the raw pixel value at the given point. Typical clients use colorAt: to get a Color." "Details: To get the raw pixel value, be sure the peeker's colorMap is nil." ^ (BitBlt current bitPeekerFromForm: self) colorMap: nil; pixelAt: aPoint ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'di 11/11/1998 13:20'! asGrayScale "Return a grayscale ColorForm computed by mapping each color into its grayscale equivalent" ^ self copy colors: (colors collect: [:c | c isTransparent ifTrue: [c] ifFalse: [Color gray: c luminance]])! ! !ColorForm methodsFor: 'color manipulation' stamp: 'ar 5/17/2001 15:44'! colormapIfNeededForDepth: destDepth "Return a colormap for displaying the receiver at the given depth, or nil if no colormap is needed." | newMap | colors == nil ifTrue: [ "use the standard colormap" ^ Color colorMapIfNeededFrom: self depth to: destDepth]. (destDepth = cachedDepth and:[cachedColormap isColormap not]) ifTrue: [^ cachedColormap]. newMap _ Bitmap new: colors size. 1 to: colors size do: [:i | newMap at: i put: ((colors at: i) pixelValueForDepth: destDepth)]. cachedDepth _ destDepth. ^ cachedColormap _ newMap. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'jm 4/18/98 20:34'! colorsUsed "Return a list of the colors actually used by this ColorForm." | myColor list | myColor _ self colors. list _ OrderedCollection new. self tallyPixelValues doWithIndex: [:count :i | count > 0 ifTrue: [list add: (myColor at: i)]]. ^ list asArray ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'jm 11/16/97 11:18'! ensureTransparentColor "Ensure that the receiver (a) includes Color transparent in its color map and (b) that the entry for Color transparent is the first entry in its color map." | i | self error: 'not yet implemented'. (colors includes: Color transparent) ifTrue: [ (colors indexOf: Color transparent) = 1 ifTrue: [^ self]. "shift the entry for color transparent"] ifFalse: [ i _ self unusedColormapEntry. i = 0 ifTrue: [self error: 'no color map entry is available']. colors at: i put: Color transparent. "shift the entry for color transparent"]. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'di 8/28/1998 15:48'! indexOfColor: aColor "Return the index of aColor in my color array" self ensureColorArrayExists. ^ colors indexOf: aColor ifAbsent: [0]! ! !ColorForm methodsFor: 'color manipulation' stamp: 'jm 10/19/1998 10:52'! mapColor: oldColor to: newColor "Replace all occurances of the given color with the given new color in my color map." self ensureColorArrayExists. 1 to: colors size do: [:i | (colors at: i) = oldColor ifTrue: [colors at: i put: newColor]]. self clearColormapCache. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'jm 11/16/97 09:08'! replaceColor: oldColor with: newColor "Replace all occurances of the given color with the given new color in my color map." self ensureColorArrayExists. 1 to: colors size do: [:i | (colors at: i) = oldColor ifTrue: [colors at: i put: newColor]]. self clearColormapCache. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 15:42'! replaceColorAt: aPoint with: newColor "Replace a color map entry with newColor. The entry replaced is the one used by aPoint. If there are are two entries in the colorMap for the oldColor, just replace ONE!!!! There are often two whites or two blacks, and this is what you want, when replacing one." | oldIndex | self ensureColorArrayExists. oldIndex _ self pixelValueAt: aPoint. colors at: oldIndex+1 put: newColor. self clearColormapCache. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'di 8/28/1998 15:49'! replaceColorAtIndex: index with: newColor "Replace a color map entry with newColor." self ensureColorArrayExists. colors at: index put: newColor. cachedColormap == nil ifFalse: [cachedColormap at: index put: (newColor pixelValueForDepth: cachedDepth)]! ! !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 11:26'! transparentAllPixelsLike: aPoint "Make all occurances of the given pixel value transparent. Very useful when two entries in the colorMap have the same value. This only changes ONE." self replaceColorAt: aPoint with: Color transparent. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 11:27'! transparentColor: aColor "Make all occurances of the given color transparent. Note: for colors like black and white, which have two entries in the colorMap, this changes BOTH of them. Not always what you want." self replaceColor: aColor with: Color transparent. ! ! !ColorForm methodsFor: 'color manipulation' stamp: 'ar 5/28/2000 12:06'! twoToneFromDisplay: aRectangle backgroundColor: bgColor "Copy one-bit deep ColorForm from the Display using a color map that maps all colors except the background color to black. Used for caching the contents of inactive MVC windows." | map | (width = aRectangle width and: [height = aRectangle height]) ifFalse: [self setExtent: aRectangle extent depth: depth]. "make a color map mapping the background color to zero and all other colors to one" map _ Bitmap new: (1 bitShift: (Display depth min: 9)). 1 to: map size do: [:i | map at: i put: 16rFFFFFFFF]. map at: (bgColor indexInMap: map) put: 0. (BitBlt current toForm: self) destOrigin: 0@0; sourceForm: Display; sourceRect: aRectangle; combinationRule: Form over; colorMap: map; copyBits. ! ! !ColorForm methodsFor: 'copying' stamp: 'RAA 8/14/2000 10:45'! asCursorForm ^ (self asFormOfDepth: 32) offset: offset; as: StaticForm! ! !ColorForm methodsFor: 'copying' stamp: 'di 11/12/2001 15:37'! blankCopyOf: aRectangle scaledBy: scale | newForm | newForm _ super blankCopyOf: aRectangle scaledBy: scale. colors ifNotNil: [newForm colors: colors copy]. ^ newForm! ! !ColorForm methodsFor: 'copying' stamp: 'ar 5/28/2000 12:06'! copy: aRect "Return a new ColorForm containing the portion of the receiver delineated by aRect." | newForm | newForm _ self class extent: aRect extent depth: depth. ((BitBlt current destForm: newForm sourceForm: self fillColor: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: aRect origin extent: aRect extent clipRect: newForm boundingBox) colorMap: nil) copyBits. colors ifNotNil: [newForm colors: colors copy]. ^ newForm ! ! !ColorForm methodsFor: 'copying' stamp: 'jm 2/27/98 09:38'! deepCopy ^ self shallowCopy bits: bits copy; offset: offset copy; colors: colors ! ! !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 09:07'! clearColormapCache cachedDepth _ nil. cachedColormap _ nil. ! ! !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 09:12'! depth: bitsPerPixel bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits']. super depth: bitsPerPixel. ! ! !ColorForm methodsFor: 'private' stamp: 'ar 5/17/2001 15:44'! ensureColorArrayExists "Return my color palette." colors ifNil: [ self depth > 8 ifTrue: [^ self error: 'ColorForms only support depths up to 8 bits']. self colors: (Color indexedColors copyFrom: 1 to: (1 bitShift: self depth))]. ! ! !ColorForm methodsFor: 'private' stamp: 'jm 4/5/1999 10:11'! setColors: colorArray cachedColormap: aBitmap depth: anInteger "Semi-private. Set the color array, cached colormap, and cached colormap depth to avoid having to recompute the colormap when switching color palettes in animations." colors _ colorArray. cachedDepth _ anInteger. cachedColormap _ aBitmap. ! ! !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 08:37'! setExtent: extent depth: bitsPerPixel "Create a virtual bit map with the given extent and bitsPerPixel." bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits']. super setExtent: extent depth: bitsPerPixel. ! ! !ColorForm methodsFor: 'private' stamp: 'jm 2/24/98 18:53'! unusedColormapEntry "Return the index of an unused color map entry, or zero if there isn't one." | tallies | tallies _ self tallyPixelValues. 1 to: tallies size do: [:i | (tallies at: i) = 0 ifTrue: [^ i]]. ^ 0 ! ! !ColorForm methodsFor: 'scaling, rotation' stamp: 'ar 3/15/1999 14:28'! flipBy: direction centerAt: aPoint | oldColors newForm | oldColors _ colors. self colors: nil. newForm _ super flipBy: direction centerAt: aPoint. self colors: oldColors. newForm colors: oldColors. ^newForm ! ! !ColorForm methodsFor: 'scaling, rotation' stamp: 'RAA 8/5/2000 18:12'! scaledToSize: newExtent "super method did not seem to work so well on ColorForms" ^(self asFormOfDepth: 16) scaledToSize: newExtent! ! !ColorForm methodsFor: 'fileIn/Out' stamp: 'ar 3/3/2001 20:07'! hibernate "Make myself take up less space. See comment in Form>hibernate." super hibernate. self clearColormapCache. colors ifNotNil:[colors _ colors asColorArray].! ! !ColorForm methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:46'! readAttributesFrom: aBinaryStream super readAttributesFrom: aBinaryStream. colors _ ColorArray new: (2 raisedTo: depth). 1 to: colors size do: [:idx | colors basicAt: idx put: (aBinaryStream nextLittleEndianNumber: 4). ]. ! ! !ColorForm methodsFor: 'fileIn/Out' stamp: 'bf 5/25/2000 16:31'! storeOn: aStream aStream nextPut: $(. super storeOn: aStream. aStream cr; tab; nextPutAll: 'colorsFromArray: #('. self colors do: [:color | color storeArrayOn: aStream]. aStream nextPutAll: ' ))'.! ! !ColorForm methodsFor: 'fileIn/Out' stamp: 'ar 3/3/2001 20:07'! unhibernate colors ifNotNil:[colors _ colors asArray]. ^super unhibernate. ! ! !ColorForm methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:42'! writeAttributesOn: file | colorArray | super writeAttributesOn: file. colorArray _ self colors asColorArray. 1 to: (2 raisedTo: depth) do: [:idx | file nextLittleEndianNumber: 4 put: (colorArray basicAt: idx). ] ! ! !ColorForm methodsFor: 'postscript generation'! asFormWithSingleTransparentColors | transparentIndexes | transparentIndexes _ self transparentColorIndexes. transparentIndexes size <= 1 ifTrue:[^self] ifFalse:[^self mapTransparencies:transparentIndexes].! ! !ColorForm methodsFor: 'postscript generation'! decodeArray ^self depth = 1 ifTrue:['[1 0]'] ifFalse:['[0 255]'].! ! !ColorForm methodsFor: 'postscript generation'! getTransparencyUnificationLUT | lut transparentIndex | lut _ Array new:colors size. transparentIndex _ self indexOfColor:Color transparent. 1 to: colors size do: [ :i | lut at:i put:(((colors at:i) = Color transparent) ifTrue:[transparentIndex] ifFalse:[i])]. ! ! !ColorForm methodsFor: 'postscript generation'! mapTransparencies:transparentIndexes ^self deepCopy mapColors:transparentIndexes to:(transparentIndexes at:1).! ! !ColorForm methodsFor: 'postscript generation'! setColorspaceOn:aStream self depth = 1 ifTrue:[ aStream print:'/DeviceRGB setcolorspace 0 setgray'; cr. ] ifFalse:[ aStream print:'[ /Indexed /DeviceRGB '; write:self colors size-1; print:' <'. (self colormapIfNeededForDepth: 32 ) storeBits:20 to:0 on:aStream. aStream print:'> ] setcolorspace'; cr.]. ! ! !ColorForm methodsFor: 'postscript generation'! transparentColorIndexes ^(1 to: colors size) select: [ :index | (colors at:index) isTransparent ]. ! ! !ColorForm methodsFor: 'color mapping' stamp: 'ar 5/17/2001 15:44'! colormapIfNeededFor: destForm | newMap color pv | (self hasNonStandardPalette or:[destForm hasNonStandardPalette]) ifFalse:[ ^self colormapIfNeededForDepth: destForm depth. ]. colors == nil ifTrue: [ "use the standard colormap" ^ super colormapIfNeededFor: destForm]. (destForm depth = cachedDepth and:[cachedColormap isColormap]) ifTrue: [^ cachedColormap]. newMap _ WordArray new: (1 bitShift: self depth). 1 to: colors size do: [:i | color _ colors at: i. pv _ destForm pixelValueFor: color. (pv = 0 and:[color isTransparent not]) ifTrue:[pv _ 1]. newMap at: i put: pv]. cachedDepth _ destForm depth. ^cachedColormap _ ColorMap shifts: nil masks: nil colors: newMap.! ! !ColorForm methodsFor: 'testing' stamp: 'ar 5/27/2001 16:34'! isColorForm ^true! ! !ColorForm methodsFor: 'testing' stamp: 'ar 2/10/2004 17:18'! isTranslucent "Answer whether this form may be translucent" ^true! ! !ColorForm methodsFor: '*morphic-Postscript Canvases' stamp: 'sma 6/14/2000 14:20'! encodePostscriptOn: aStream self unhibernate. aStream print: '% form contains '; write: (colors select: [:c | c = Color transparent]) size; print: ' transparent colors'; cr. ^ self asFormWithSingleTransparentColors printPostscript: aStream operator: (self depth = 1 ifTrue: ['imagemask'] ifFalse: [(self indexOfColor: Color transparent) printString , ' transparentimage'])! ! !ColorForm methodsFor: '*morphic-Postscript Canvases'! printPostscript:aStream aStream nextPutAll:'% form contains '; print:((colors select:[:c| c=Color transparent]) size); nextPutAll:' transparent colors'; cr. ^self asFormWithSingleTransparentColors printPostscript:aStream operator:(self depth=1 ifTrue:['imagemask'] ifFalse:[ (self indexOfColor:Color transparent) printString ,' transparentimage']) . ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ColorForm class instanceVariableNames: ''! !ColorForm class methodsFor: 'as yet unclassified' stamp: 'nk 4/17/2004 19:44'! mappingWhiteToTransparentFrom: aFormOrCursor "Return a ColorForm copied from the given Form or Cursor with white mapped to transparent." | f map | aFormOrCursor depth <= 8 ifFalse: [ ^ self error: 'argument depth must be 8-bits per pixel or less']. (aFormOrCursor isColorForm) ifTrue: [ f _ aFormOrCursor deepCopy. map _ aFormOrCursor colors. ] ifFalse: [ f _ ColorForm extent: aFormOrCursor extent depth: aFormOrCursor depth. f copyBits: aFormOrCursor boundingBox from: aFormOrCursor at: 0@0 clippingBox: aFormOrCursor boundingBox rule: Form over fillColor: nil. map _ Color indexedColors copyFrom: 1 to: (1 bitShift: aFormOrCursor depth)]. map _ map collect: [:c | c = Color white ifTrue: [Color transparent] ifFalse: [c]]. f colors: map. ^ f ! ! !ColorForm class methodsFor: 'as yet unclassified'! twoToneFromDisplay: aRectangle using: oldForm backgroundColor: bgColor "Return a 1-bit deep ColorForm copied from the given rectangle of the display. All colors except the background color will be mapped to black." | f | ((oldForm ~~ nil) and: [oldForm extent = aRectangle extent]) ifTrue: [ f _ oldForm fromDisplay: aRectangle. ] ifFalse: [ f _ ColorForm extent: aRectangle extent depth: 1. f twoToneFromDisplay: aRectangle backgroundColor: bgColor. f colors: (Array with: bgColor with: Color black)]. ^ f ! ! Object subclass: #ColorMap instanceVariableNames: 'shifts masks colors' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:54'! alphaMask ^masks at: 4! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:31'! alphaShift ^shifts at: 4! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:39'! at: index ^colors at: index! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:39'! at: index put: value ^colors at: index put: value! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:31'! blueMask ^masks at: 3! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:31'! blueShift ^shifts at: 3! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 2/10/2000 17:12'! colors ^colors! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:32'! greenMask ^masks at: 2! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:32'! greenShift ^shifts at: 2! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 5/28/2000 22:08'! inverseMap "Return the inverse map of the receiver" | newMasks newShifts | colors ifNotNil:[^self error:'Not yet implemented']. newMasks _ WriteStream on: (Array new: 4). newShifts _ WriteStream on: (Array new: 4). masks with: shifts do:[:mask :shift| newMasks nextPut: (mask bitShift: shift). newShifts nextPut: shift negated]. ^ColorMap shifts: newShifts contents masks: newMasks contents! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 5/27/2000 19:16'! masks ^masks! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:36'! redMask ^masks at: 1! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 1/16/2000 15:37'! redShift ^shifts at: 1! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 5/27/2000 20:48'! rgbaBitMasks "Return the rgba bit masks for the receiver" ^masks asArray with: shifts collect:[:m :s| m bitShift: s]! ! !ColorMap methodsFor: 'accessing' stamp: 'ar 5/27/2000 19:16'! shifts ^shifts! ! !ColorMap methodsFor: 'pixel mapping' stamp: 'ar 5/15/2001 16:12'! mapPixel: pixelValue "Perform a forward pixel mapping operation" | pv | (shifts == nil and:[masks == nil]) ifFalse:[ pv _ (((pixelValue bitAnd: self redMask) bitShift: self redShift) bitOr: ((pixelValue bitAnd: self greenMask) bitShift: self greenShift)) bitOr: (((pixelValue bitAnd: self blueMask) bitShift: self blueShift) bitOr: ((pixelValue bitAnd: self alphaMask) bitShift: self alphaShift)). ] ifTrue:[pv _ pixelValue]. colors ifNotNil:[pv _ colors at: pv]. "Need to check for translucency else Form>>paint goes gaga" pv = 0 ifTrue:[pixelValue = 0 ifFalse:[pv _ 1]]. ^pv! ! !ColorMap methodsFor: 'pixel mapping' stamp: 'ar 6/8/2000 20:36'! mappingTo: aColorMap "Compute a new color map through the receiver and aColorMap. Both maps are assumed to be mappings into canonical ARGB space" | fixedMap | self = aColorMap ifTrue:[^nil]. "No mapping needed" aColorMap isIndexed ifTrue:[^nil]. "We can't compute mappings to an indexed map yet" fixedMap _ self class mappingFrom: self rgbaBitMasks to: aColorMap rgbaBitMasks. self isIndexed ifFalse:[^fixedMap]. "If the receiver is indexed then we need to map the colors as well" self flag: #untested. ^ColorMap shifts: fixedMap shifts masks: fixedMap masks colors: (colors collect:[:pv| aColorMap pixelMap: pv]). ! ! !ColorMap methodsFor: 'pixel mapping' stamp: 'ar 5/15/2001 16:12'! pixelMap: pixelValue "Perform a reverse pixel mapping operation" | pv | colors == nil ifTrue:[pv _ pixelValue] ifFalse:[pv _ colors at: pixelValue]. (shifts == nil and:[masks == nil]) ifFalse:[pv _ (((pv bitAnd: self redMask) bitShift: self redShift) bitOr: ((pv bitAnd: self greenMask) bitShift: self greenShift)) bitOr: (((pv bitAnd: self blueMask) bitShift: self blueShift) bitOr: ((pv bitAnd: self alphaMask) bitShift: self alphaShift))]. "Need to check for translucency else Form>>paint goes gaga" pv = 0 ifTrue:[pixelValue = 0 ifFalse:[pv _ 1]]. ^pv! ! !ColorMap methodsFor: 'private' stamp: 'ar 2/22/2000 16:47'! setShifts: shiftArray masks: maskArray colors: colorArray shiftArray ifNotNil:[shifts _ shiftArray asIntegerArray]. maskArray ifNotNil:[masks _ maskArray asWordArray]. colorArray ifNotNil:[colors _ colorArray asWordArray].! ! !ColorMap methodsFor: 'testing' stamp: 'ar 5/25/2000 19:41'! isColormap ^true! ! !ColorMap methodsFor: 'testing' stamp: 'ar 5/27/2000 19:06'! isFixed "Return true if the receiver does not use a lookup mechanism for pixel mapping" ^self isIndexed not! ! !ColorMap methodsFor: 'testing' stamp: 'ar 5/27/2000 19:06'! isIndexed "Return true if the receiver uses a lookup mechanism for pixel mapping" ^colors notNil! ! !ColorMap methodsFor: 'comparing' stamp: 'tk 7/5/2001 21:59'! = aColorMap "Return true if the receiver is equal to aColorMap" self species == aColorMap species ifFalse:[^false]. self isIndexed == aColorMap isIndexed ifFalse:[^false]. ^self colors = aColorMap colors and:[ self shifts = aColorMap shifts and:[ self masks = aColorMap masks]]! ! !ColorMap methodsFor: 'comparing' stamp: 'ar 5/27/2000 19:29'! hash "Hash is re-implemented because #= is re-implemented" ^colors hash bitXor: (shifts hash bitXor: masks hash)! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ColorMap class instanceVariableNames: ''! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 2/22/2000 14:08'! colors: colorArray ^self new setShifts: nil masks: nil colors: colorArray! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/27/2000 20:09'! mapBitsFrom: srcBitMask to: dstBitMask "Return an array consisting of the shift and the mask for mapping component values out of srcBitMask and into dstBitMask. While this computation is somewhat complicated it eases the batch conversion of all the pixels in BitBlt." | srcBits dstBits srcLow srcHigh dstLow dstHigh bits mask shift | (srcBitMask = 0 or:[dstBitMask = 0]) ifTrue:[^#(0 0)]. "Zero mask and shift" "Compute low and high bit position for source and dest bit mask" srcLow _ srcBitMask lowBit - 1. srcHigh _ srcBitMask highBit. dstLow _ dstBitMask lowBit - 1. dstHigh _ dstBitMask highBit. "Compute the number of bits in source and dest bit mask" srcBits _ srcHigh - srcLow. dstBits _ dstHigh - dstLow. "Compute the maximum number of bits we can transfer inbetween" bits _ srcBits min: dstBits. "Compute the (unshifted) transfer mask" mask _ (1 bitShift: bits) - 1. "Shift the transfer mask to the mask the highest n bits of srcBitMask" mask _ mask bitShift: (srcHigh - bits). "Compute the delta shift so that the most significant bit of the source bit mask falls on the most significant bit of the dest bit mask. Note that delta is used for #bitShift: so shift > 0 : shift right shift < 0 : shift left e.g., if dstHigh > srcHigh we need to shift left and if dstHigh < srcHigh we need to shift right. This leads to:" shift _ dstHigh - srcHigh. "And that's all we need" ^Array with: shift with: mask! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/27/2000 19:41'! mappingFrom: srcBitMasks to: dstBitMasks "Return a color map mapping from the array of source bit masks to the array of dest bit masks." | shifts masks shiftAndMask | shifts _ IntegerArray new: 4. masks _ WordArray new: 4. 1 to: 4 do:[:i| shiftAndMask _ self mapBitsFrom: (srcBitMasks at: i) to: (dstBitMasks at: i). shifts at: i put: (shiftAndMask at: 1). masks at: i put: (shiftAndMask at: 2). ]. ^self shifts: shifts masks: masks! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/27/2000 20:08'! mappingFromARGB: dstBitMasks "Return a ColorMap mapping from canonical ARGB space into dstBitMasks" ^self mappingFrom: #(16rFF0000 16rFF00 16rFF 16rFF000000) to: dstBitMasks! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 1/16/2000 16:02'! shifts: shiftArray masks: maskArray ^self shifts: shiftArray masks: maskArray colors: nil.! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 1/16/2000 16:02'! shifts: shiftArray masks: maskArray colors: colorArray ^self new setShifts: shiftArray masks: maskArray colors: colorArray! ! StandardSystemView subclass: #ColorSystemView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !ColorSystemView methodsFor: 'as yet unclassified'! cacheBitsAsTwoTone ^ false! ! !ColorSystemView methodsFor: 'as yet unclassified' stamp: 'di 2/26/98 08:58'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible." bitsValid ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [super displayDeEmphasized] ! ! AbstractEvent subclass: #CommentedEvent instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !CommentedEvent methodsFor: 'testing' stamp: 'rw 7/1/2003 11:37'! isCommented ^true! ! !CommentedEvent methodsFor: 'printing' stamp: 'rw 7/1/2003 11:37'! printEventKindOn: aStream aStream nextPutAll: 'Commented'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CommentedEvent class instanceVariableNames: ''! !CommentedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:08'! changeKind ^#Commented! ! !CommentedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 11:20'! supportedKinds ^Array with: self classKind! ! ByteArray variableByteSubclass: #CompiledMethod instanceVariableNames: '' classVariableNames: 'BlockNodeCache LargeFrame SmallFrame SpecialConstants TempNameCache' poolDictionaries: '' category: 'Kernel-Methods'! !CompiledMethod commentStamp: 'ls 7/5/2003 13:48' prior: 0! My instances are methods suitable for interpretation by the virtual machine. This is the only class in the system whose instances intermix both indexable pointer fields and indexable integer fields. The current format of a CompiledMethod is as follows: header (4 bytes) literals (4 bytes each) bytecodes (variable) trailer (variable) The header is a 30-bit integer with the following format: (index 0) 9 bits: main part of primitive number (#primitive) (index 9) 8 bits: number of literals (#numLiterals) (index 17) 1 bit: whether a large frame size is needed (#frameSize) (index 18) 6 bits: number of temporary variables (#numTemps) (index 24) 4 bits: number of arguments to the method (#numArgs) (index 28) 1 bit: high-bit of primitive number (#primitive) (index 29) 1 bit: flag bit, ignored by the VM (#flag) The trailer has two variant formats. In the first variant, the last byte is at least 252 and the last four bytes represent a source pointer into one of the sources files (see #sourcePointer). In the second variant, the last byte is less than 252, and the last several bytes are a compressed version of the names of the method's temporary variables. The number of bytes used for this purpose is the value of the last byte in the method. ! !CompiledMethod methodsFor: 'initialize-release'! copyWithTrailerBytes: bytes "Testing: (CompiledMethod compiledMethodAt: #copyWithTrailerBytes:) tempNamesPut: 'copy end ' " | copy end start | start _ self initialPC. end _ self endPC. copy _ CompiledMethod newMethod: end - start + 1 + bytes size header: self header. 1 to: self numLiterals do: [:i | copy literalAt: i put: (self literalAt: i)]. start to: end do: [:i | copy at: i put: (self at: i)]. 1 to: bytes size do: [:i | copy at: end + i put: (bytes at: i)]. ^ copy! ! !CompiledMethod methodsFor: 'initialize-release' stamp: 'di 10/22/1999 13:14'! needsFrameSize: newFrameSize "Set the largeFrameBit to accomodate the newFrameSize" | largeFrameBit header | largeFrameBit _ 16r20000. (self numTemps + newFrameSize) > LargeFrame ifTrue: [^ self error: 'Cannot compile -- stack including temps is too deep']. header _ self objectAt: 1. (header bitAnd: largeFrameBit) ~= 0 ifTrue: [header _ header - largeFrameBit]. self objectAt: 1 put: header + ((self numTemps + newFrameSize) > SmallFrame ifTrue: [largeFrameBit] ifFalse: [0])! ! !CompiledMethod methodsFor: 'accessing' stamp: 'rw 5/12/2003 11:12'! defaultSelector "Invent and answer an appropriate message selector (a Symbol) for me, that is, one that will parse with the correct number of arguments." | aStream | aStream _ WriteStream on: (String new: 16). aStream nextPutAll: 'DoIt'. 1 to: self numArgs do: [:i | aStream nextPutAll: 'with:']. ^aStream contents asSymbol! ! !CompiledMethod methodsFor: 'accessing'! endPC "Answer the index of the last bytecode." | flagByte | flagByte _ self last. flagByte = 0 ifTrue: ["If last byte = 0, may be either 0, 0, 0, 0 or just 0" 1 to: 4 do: [:i | (self at: self size - i) = 0 ifFalse: [^ self size - i]]]. flagByte < 252 ifTrue: ["Magic sources (tempnames encoded in last few bytes)" ^ self size - self last - 1]. "Normal 4-byte source pointer" ^ self size - 4! ! !CompiledMethod methodsFor: 'accessing' stamp: 'di 1/2/1999 17:00'! flushCache "Tell the interpreter to remove all references to this method from its method lookup cache, if it has one. This primitive must be called whenever a method is defined or removed. NOTE: Only one of two selective flush methods needs to be used. Squeak 2.2 and earlier uses 119 (See Symbol flushCache). Squeak 2.3 and later uses 116 (See CompiledMethod flushCache)." <primitive: 116> ! ! !CompiledMethod methodsFor: 'accessing' stamp: 'di 10/23/1999 22:00'! frameSize "Answer the size of temporary frame needed to run the receiver." "NOTE: Versions 2.7 and later use two sizes of contexts." (self header noMask: 16r20000) ifTrue: [^ SmallFrame] ifFalse: [^ LargeFrame] ! ! !CompiledMethod methodsFor: 'accessing'! initialPC "Answer the program counter for the receiver's first bytecode." ^ (self numLiterals + 1) * 4 + 1! ! !CompiledMethod methodsFor: 'accessing' stamp: 'ar 6/2/1998 16:26'! numArgs "Answer the number of arguments the receiver takes." ^ (self header bitShift: -24) bitAnd: 16r0F! ! !CompiledMethod methodsFor: 'accessing'! numLiterals "Answer the number of literals used by the receiver." ^ (self header bitShift: -9) bitAnd: 16rFF! ! !CompiledMethod methodsFor: 'accessing'! numTemps "Answer the number of temporary variables used by the receiver." ^ (self header bitShift: -18) bitAnd: 16r3F! ! !CompiledMethod methodsFor: 'accessing' stamp: 'ls 6/22/2000 14:35'! primitive "Answer the primitive index associated with the receiver. Zero indicates that this is not a primitive method. We currently allow 10 bits of primitive index, but they are in two places for backward compatibility. The time to unpack is negligible, since the reconstituted full index is stored in the method cache." | primBits | primBits _ self header bitAnd: 16r100001FF. ^ (primBits bitAnd: 16r1FF) + (primBits bitShift: -19) ! ! !CompiledMethod methodsFor: 'accessing'! returnField "Answer the index of the instance variable returned by a quick return method." | prim | prim _ self primitive. prim < 264 ifTrue: [self error: 'only meaningful for quick-return'] ifFalse: [^ prim - 264]! ! !CompiledMethod methodsFor: 'accessing' stamp: 'sw 8/15/97 16:17'! selector "This is slow, so don't call it frivolously" ^ self who last! ! !CompiledMethod methodsFor: 'accessing' stamp: 'ajh 11/17/2001 14:30'! trailer | end trailer | end _ self endPC. trailer _ ByteArray new: self size - end. end + 1 to: self size do: [:i | trailer at: i - end put: (self at: i)]. ^ trailer! ! !CompiledMethod methodsFor: 'comparing' stamp: 'ar 8/16/2001 13:24'! = method | myLits otherLits | "Answer whether the receiver implements the same code as the argument, method." (method isKindOf: CompiledMethod) ifFalse: [^false]. self size = method size ifFalse: [^false]. self header = method header ifFalse: [^false]. self initialPC to: self endPC do: [:i | (self at: i) = (method at: i) ifFalse: [^false]]. (myLits _ self literals) = (otherLits _ method literals) ifFalse: [myLits size = otherLits size ifFalse: [^ false]. "Dont bother checking FFI and named primitives" (#(117 120) includes: self primitive) ifTrue: [^ true]. myLits with: otherLits do: [:lit1 :lit2 | lit1 = lit2 ifFalse: [(lit1 isVariableBinding) ifTrue: ["Associations match if value is equal, since associations used for super may have key = nil or name of class." lit1 value == lit2 value ifFalse: [^ false]] ifFalse: [(lit1 isMemberOf: Float) ifTrue: ["Floats match if values are close, due to roundoff error." (lit1 closeTo: lit2) ifFalse: [^ false]] ifFalse: ["any other discrepancy is a failure" ^ false]]]]]. ^ true! ! !CompiledMethod methodsFor: 'testing' stamp: 'sw 5/3/2001 15:06'! hasReportableSlip "Answer whether the receiver contains anything that should be brought to the attention of the author when filing out. Customize the lists here to suit your preferences. If slips do not get reported in spite of your best efforts here, make certain that the Preference 'checkForSlips' is set to true." | assoc | #(doOnlyOnce: halt halt: hottest printDirectlyToDisplay toRemove personal urgent) do: [:aLit | (self hasLiteral: aLit) ifTrue: [^ true]]. #(Transcript AA BB CC DD EE) do: [:aSymbol | (assoc _ (Smalltalk associationAt: aSymbol ifAbsent: [nil])) ifNotNil: [(self hasLiteral: assoc) ifTrue: [^ true]]]. ^ false! ! !CompiledMethod methodsFor: 'testing' stamp: 'md 11/21/2003 12:15'! isCompiledMethod ^ true! ! !CompiledMethod methodsFor: 'testing' stamp: 'di 12/26/1998 21:31'! isQuick "Answer whether the receiver is a quick return (of self or of an instance variable)." ^ self primitive between: 256 and: 519! ! !CompiledMethod methodsFor: 'testing' stamp: 'ar 6/2/1998 16:11'! isReturnField "Answer whether the receiver is a quick return of an instance variable." ^ self primitive between: 264 and: 519! ! !CompiledMethod methodsFor: 'testing'! isReturnSelf "Answer whether the receiver is a quick return of self." ^ self primitive = 256! ! !CompiledMethod methodsFor: 'testing'! isReturnSpecial "Answer whether the receiver is a quick return of self or constant." ^ self primitive between: 256 and: 263! ! !CompiledMethod methodsFor: 'printing' stamp: 'sw 7/29/2002 02:24'! dateMethodLastSubmitted "Answer a Date object indicating when a method was last submitted. If there is no date stamp, return nil" "(CompiledMethod compiledMethodAt: #dateMethodLastSubmitted) dateMethodLastSubmitted" | aStamp tokens | aStamp _ self timeStamp. tokens _ aStamp findBetweenSubStrs: ' '. "space is expected delimiter, but cr is sometimes seen, though of mysterious provenance" ^ tokens size > 1 ifTrue: [[tokens second asDate] ifError: [nil]] ifFalse: [nil]! ! !CompiledMethod methodsFor: 'printing' stamp: 'sma 2/12/2000 14:01'! decompileString | clAndSel cl sel | clAndSel _ self who. clAndSel = #(unknown unknown) ifTrue: [cl _ Object. sel _ #xxxUnknown. self numArgs >= 1 ifTrue: [sel _ sel , ':'. 2 to: self numArgs do: [:i | sel _ sel , 'with:']. sel _ sel asSymbol]] ifFalse: [cl _ clAndSel first. sel _ clAndSel last]. ^ (cl decompilerClass new decompile: sel in: cl method: self) decompileString! ! !CompiledMethod methodsFor: 'printing' stamp: 'ajh 2/9/2003 14:17'! longPrintOn: aStream "List of all the byte codes in a method with a short description of each" self longPrintOn: aStream indent: 0! ! !CompiledMethod methodsFor: 'printing' stamp: 'ar 6/28/2003 00:08'! longPrintOn: aStream indent: tabs "List of all the byte codes in a method with a short description of each" self isQuick ifTrue: [self isReturnSpecial ifTrue: [^ aStream tab: tabs; nextPutAll: 'Quick return ' , (#('self' 'true' 'false' 'nil' '-1' '0' '1' '2') at: self primitive - 255)]. ^ aStream nextPutAll: 'Quick return field ' , self returnField printString , ' (0-based)']. self primitive = 0 ifFalse: [ aStream tab: tabs. self printPrimitiveOn: aStream. ]. (InstructionPrinter on: self) indent: tabs; printInstructionsOn: aStream. ! ! !CompiledMethod methodsFor: 'printing' stamp: 'sma 6/1/2000 09:45'! printOn: aStream "Overrides method inherited from the byte arrayed collection." self printNameOn: aStream. aStream space; nextPutAll: self identityHashPrintString! ! !CompiledMethod methodsFor: 'printing' stamp: 'MPW 1/1/1901 22:09'! printOnStream: aStream "Overrides method inherited from the byte arrayed collection." aStream print: 'a CompiledMethod'! ! !CompiledMethod methodsFor: 'printing' stamp: 'ar 11/28/1999 19:37'! printPrimitiveOn: aStream "Print the primitive on aStream" | primIndex primDecl | primIndex _ self primitive. primIndex = 0 ifTrue:[^self]. primIndex = 120 "External call spec" ifTrue:[^aStream print: (self literalAt: 1); cr]. aStream nextPutAll: '<primitive: '. primIndex = 117 ifTrue:[ primDecl _ self literalAt: 1. aStream nextPut: $'; nextPutAll: (primDecl at: 2); nextPut:$'. (primDecl at: 1) notNil ifTrue:[ aStream nextPutAll:' module:'; nextPut:$'; nextPutAll: (primDecl at: 1); nextPut:$'. ]. ] ifFalse:[aStream print: primIndex]. aStream nextPut: $>; cr! ! !CompiledMethod methodsFor: 'printing'! storeOn: aStream | noneYet | aStream nextPutAll: '(('. aStream nextPutAll: self class name. aStream nextPutAll: ' newMethod: '. aStream store: self size - self initialPC + 1. aStream nextPutAll: ' header: '. aStream store: self header. aStream nextPut: $). noneYet _ self storeElementsFrom: self initialPC to: self endPC on: aStream. 1 to: self numLiterals do: [:index | noneYet ifTrue: [noneYet _ false] ifFalse: [aStream nextPut: $;]. aStream nextPutAll: ' literalAt: '. aStream store: index. aStream nextPutAll: ' put: '. aStream store: (self literalAt: index)]. noneYet ifFalse: [aStream nextPutAll: '; yourself']. aStream nextPut: $)! ! !CompiledMethod methodsFor: 'printing' stamp: 'sw 7/29/2002 02:21'! timeStamp "Answer the authoring time-stamp for the given method, retrieved from the sources or changes file. Answer the empty string if no time stamp is available." "(CompiledMethod compiledMethodAt: #timeStamp) timeStamp" | position file preamble stamp tokens tokenCount | self fileIndex == 0 ifTrue: [^ String new]. "no source pointer for this method" position _ self filePosition. file _ SourceFiles at: self fileIndex. file ifNil: [^ String new]. "sources file not available" "file does not exist happens in secure mode" file _ [file readOnlyCopy] on: FileDoesNotExistException do:[:ex| nil]. file ifNil: [^ String new]. file position: (0 max: position - 150). "Skip back to before the preamble" [file position < (position - 1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. stamp _ String new. tokens _ (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [Scanner new scanTokens: preamble] ifFalse: [Array new "ie cant be back ref"]. (((tokenCount _ tokens size) between: 7 and: 8) and: [(tokens at: tokenCount - 5) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount - 2]]. ((tokenCount between: 5 and: 6) and: [(tokens at: tokenCount - 3) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount]]. file close. ^ stamp ! ! !CompiledMethod methodsFor: 'printing' stamp: 'dvf 8/23/2003 11:50'! who "Answer an Array of the class in which the receiver is defined and the selector to which it corresponds." | sel | self systemNavigation allBehaviorsDo: [:class | (sel := class methodDict keyAtIdentityValue: self ifAbsent: [nil]) ifNotNil: [^Array with: class with: sel]]. ^Array with: #unknown with: #unknown! ! !CompiledMethod methodsFor: 'literals' stamp: 'di 10/17/97 22:38'! hasLiteral: literal "Answer whether the receiver references the argument, literal." <primitive: 132> "a fast primitive operation equivalent to..." 2 to: self numLiterals + 1 do: [:index | literal == (self objectAt: index) ifTrue: [^ true]]. ^ false! ! !CompiledMethod methodsFor: 'literals' stamp: 'di 8/15/97 09:51'! hasLiteralSuchThat: litBlock "Answer true if litBlock returns true for any literal in this method, even if imbedded in array structure." | lit | 2 to: self numLiterals + 1 do: [:index | lit _ self objectAt: index. (litBlock value: lit) ifTrue: [^ true]. (lit class == Array and: [lit hasLiteralSuchThat: litBlock]) ifTrue: [^ true]]. ^false! ! !CompiledMethod methodsFor: 'literals' stamp: 'sma 6/3/2000 21:39'! hasLiteralThorough: literal "Answer true if any literal in this method is literal, even if embedded in array structure." | lit | 2 to: self numLiterals + 1 do: [:index | (lit _ self objectAt: index) == literal ifTrue: [^ true]. (lit class == Array and: [lit hasLiteral: literal]) ifTrue: [^ true]]. ^ false! ! !CompiledMethod methodsFor: 'literals'! header "Answer the word containing the information about the form of the receiver and the form of the context needed to run the receiver." ^self objectAt: 1! ! !CompiledMethod methodsFor: 'literals' stamp: 'ajh 2/9/2003 13:15'! headerDescription "Answer a description containing the information about the form of the receiver and the form of the context needed to run the receiver." | s | s _ '' writeStream. self header printOn: s. s cr; nextPutAll: '"primitive: '. self primitive printOn: s. s cr; nextPutAll: ' numArgs: '. self numArgs printOn: s. s cr; nextPutAll: ' numTemps: '. self numTemps printOn: s. s cr; nextPutAll: ' numLiterals: '. self numLiterals printOn: s. s cr; nextPutAll: ' frameSize: '. self frameSize printOn: s. s cr; nextPutAll: ' isClosureCompiled: '. self isClosureCompiled printOn: s. s nextPut: $"; cr. ^ s contents! ! !CompiledMethod methodsFor: 'literals'! literalAt: index "Answer the literal indexed by the argument." ^self objectAt: index + 1! ! !CompiledMethod methodsFor: 'literals'! literalAt: index put: value "Replace the literal indexed by the first argument with the second argument. Answer the second argument." ^self objectAt: index + 1 put: value! ! !CompiledMethod methodsFor: 'literals'! literals "Answer an Array of the literals referenced by the receiver." | literals numberLiterals | literals _ Array new: (numberLiterals _ self numLiterals). 1 to: numberLiterals do: [:index | literals at: index put: (self objectAt: index + 1)]. ^literals! ! !CompiledMethod methodsFor: 'literals'! objectAt: index "Primitive. Answer the method header (if index=1) or a literal (if index >1) from the receiver. Essential. See Object documentation whatIsAPrimitive." <primitive: 68> self primitiveFailed! ! !CompiledMethod methodsFor: 'literals'! objectAt: index put: value "Primitive. Store the value argument into a literal in the receiver. An index of 2 corresponds to the first literal. Fails if the index is less than 2 or greater than the number of literals. Answer the value as the result. Normally only the compiler sends this message, because only the compiler stores values in CompiledMethods. Essential. See Object documentation whatIsAPrimitive." <primitive: 69> self primitiveFailed! ! !CompiledMethod methodsFor: 'scanning'! messages "Answer a Set of all the message selectors sent by this method." | scanner aSet | aSet _ Set new. scanner _ InstructionStream on: self. scanner scanFor: [:x | scanner addSelectorTo: aSet. false "keep scanning"]. ^aSet! ! !CompiledMethod methodsFor: 'scanning'! readsField: varIndex "Answer whether the receiver loads the instance variable indexed by the argument." self isReturnField ifTrue: [^self returnField + 1 = varIndex]. varIndex <= 16 ifTrue: [^ self scanFor: varIndex - 1]. varIndex <= 64 ifTrue: [^ self scanLongLoad: varIndex - 1]. ^ self scanVeryLongLoad: 64 offset: varIndex - 1! ! !CompiledMethod methodsFor: 'scanning'! scanFor: byte "Answer whether the receiver contains the argument as a bytecode." ^ (InstructionStream on: self) scanFor: [:instr | instr = byte] " Smalltalk browseAllSelect: [:m | m scanFor: 134] "! ! !CompiledMethod methodsFor: 'scanning'! scanLongLoad: extension "Answer whether the receiver contains a long load whose extension is the argument." | scanner | scanner _ InstructionStream on: self. ^scanner scanFor: [:instr | instr = 128 and: [scanner followingByte = extension]]! ! !CompiledMethod methodsFor: 'scanning'! scanLongStore: extension "Answer whether the receiver contains a long store whose extension is the argument." | scanner | scanner _ InstructionStream on: self. ^scanner scanFor: [:instr | (instr = 129 or: [instr = 130]) and: [scanner followingByte = extension]]! ! !CompiledMethod methodsFor: 'scanning'! scanVeryLongLoad: extension offset: offset "Answer whether the receiver contains a long load whose extension is the argument." | scanner | scanner _ InstructionStream on: self. ^ scanner scanFor: [:instr | (instr = 132 and: [scanner followingByte = extension]) and: [scanner thirdByte = offset]]! ! !CompiledMethod methodsFor: 'scanning' stamp: 'di 6/25/97 19:08'! scanVeryLongStore: extension offset: offset "Answer whether the receiver contains a long load with the given offset. Note that the constant +32 is the known difference between a store and a storePop for instVars, and it will always fail on literal variables, but these only use store (followed by pop) anyway." | scanner ext | scanner _ InstructionStream on: self. ^ scanner scanFor: [:instr | (instr = 132 and: [(ext _ scanner followingByte) = extension or: ["might be a store/pop into rcvr" ext = (extension+32)]]) and: [scanner thirdByte = offset]]! ! !CompiledMethod methodsFor: 'scanning'! sendsToSuper "Answer whether the receiver sends any message to super." | scanner | scanner _ InstructionStream on: self. ^ scanner scanFor: [:instr | instr = 16r85 or: [instr = 16r84 and: [scanner followingByte between: 16r20 and: 16r3F]]]! ! !CompiledMethod methodsFor: 'scanning' stamp: 'di 12/26/1998 21:30'! writesField: field "Answer whether the receiver stores into the instance variable indexed by the argument." self isQuick ifTrue: [^ false]. field <= 8 ifTrue: [^ (self scanFor: 96 + field - 1) or: [self scanLongStore: field - 1]]. field <= 64 ifTrue: [^ self scanLongStore: field - 1]. ^ self scanVeryLongStore: 160 offset: field - 1! ! !CompiledMethod methodsFor: 'source code management'! cacheTempNames: names TempNameCache _ Association key: self value: names! ! !CompiledMethod methodsFor: 'source code management' stamp: 'tk 12/7/2000 12:28'! checkOKToAdd: size at: filePosition "Issue several warnings as the end of the changes file approaches its limit, and finally halt with an error when the end is reached." | fileSizeLimit margin | fileSizeLimit _ 16r2000000. 3 to: 1 by: -1 do: [:i | margin _ i*100000. (filePosition + size + margin) > fileSizeLimit ifTrue: [(filePosition + margin) > fileSizeLimit ifFalse: [self inform: 'WARNING: your changes file is within ' , margin printString , ' characters of its size limit. You should take action soon to reduce its size. You may proceed.']] ifFalse: [^ self]]. (filePosition + size > fileSizeLimit) ifFalse: [^ self]. self error: 'You have reached the size limit of the changes file. You must take action now to reduce it. Close this error. Do not attempt to proceed.'! ! !CompiledMethod methodsFor: 'source code management' stamp: 'di 1/7/2004 15:32'! copyWithTempNames: tempNames | tempStr compressed | tempStr _ String streamContents: [:strm | tempNames do: [:n | strm nextPutAll: n; space]]. compressed := self qCompress: tempStr firstTry: true. compressed ifNil: ["failure case (tempStr too big) will just decompile with tNN names" ^ self copyWithTrailerBytes: #(0 0 0 0)]. ^ self copyWithTrailerBytes: compressed! ! !CompiledMethod methodsFor: 'source code management' stamp: 'hmm 4/26/2000 20:44'! fileIndex ^SourceFiles fileIndexFromSourcePointer: self sourcePointer! ! !CompiledMethod methodsFor: 'source code management' stamp: 'hmm 4/26/2000 20:45'! filePosition ^SourceFiles filePositionFromSourcePointer: self sourcePointer! ! !CompiledMethod methodsFor: 'source code management' stamp: 'di 12/26/1998 22:34'! getSourceFor: selector in: class "Retrieve or reconstruct the source code for this method." | source flagByte | flagByte _ self last. (flagByte = 0 or: [flagByte = 251 "some source-less methods have flag = 251, rest = 0" and: [((1 to: 3) collect: [:i | self at: self size - i]) = #(0 0 0)]]) ifTrue: ["No source pointer -- decompile without temp names" ^ (class decompilerClass new decompile: selector in: class method: self) decompileString]. flagByte < 252 ifTrue: ["Magic sources -- decompile with temp names" ^ ((class decompilerClass new withTempNames: self tempNames) decompile: selector in: class method: self) decompileString]. "Situation normal; read the sourceCode from the file" (source _ self getSourceFromFile) == nil ifFalse: [^ source]. "Something really wrong -- decompile blind (no temps)" ^ (class decompilerClass new decompile: selector in: class method: self) decompileString! ! !CompiledMethod methodsFor: 'source code management' stamp: 'tk 12/12/97 13:03'! getSourceFromFile "Read the source code from file, determining source file index and file position from the last 3 bytes of this method." | position | (position _ self filePosition) = 0 ifTrue: [^ nil]. ^ (RemoteString newFileNumber: self fileIndex position: position) text! ! !CompiledMethod methodsFor: 'source code management' stamp: 'ajh 7/21/2003 09:45'! holdsTempNames "Are tempNames stored in trailer bytes" | flagByte | flagByte _ self last. (flagByte = 0 or: [flagByte = 251 "some source-less methods have flag = 251, rest = 0" and: [((1 to: 3) collect: [:i | self at: self size - i]) = #(0 0 0)]]) ifTrue: [^ false]. "No source pointer & no temp names" flagByte < 252 ifTrue: [^ true]. "temp names compressed" ^ false "Source pointer" ! ! !CompiledMethod methodsFor: 'source code management' stamp: '6/5/97 di'! putSource: sourceStr fromParseNode: methodNode class: class category: catName withStamp: changeStamp inFile: fileIndex priorMethod: priorMethod ^ self putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: [:file | class printCategoryChunk: catName on: file withStamp: changeStamp priorMethod: priorMethod. file cr]! ! !CompiledMethod methodsFor: 'source code management' stamp: 'NS 1/16/2004 15:39'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString st80str | (SourceFiles == nil or: [(file _ SourceFiles at: fileIndex) == nil]) ifTrue: [^ self become: (self copyWithTempNames: methodNode tempNames)]. SmalltalkImage current assureStartupStampLogged. file setToEnd. preambleBlock value: file. "Write the preamble" (methodNode isKindOf: DialectMethodNode) ifTrue: ["This source was parsed from an alternate syntax. We must convert to ST80 before logging it." st80str _ (DialectStream dialect: #ST80 contents: [:strm | methodNode printOn: strm]) asString. remoteString _ RemoteString newString: st80str onFileNumber: fileIndex toFile: file] ifFalse: [remoteString _ RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file]. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex! ! !CompiledMethod methodsFor: 'source code management' stamp: 'di 1/7/2004 15:32'! qCompress: str firstTry: firstTry "A very simple text compression routine designed for method temp names. Most common 12 chars get values 0-11 packed in one 4-bit nibble; others get values 12-15 (2 bits) * 16 plus next nibble. Last char of str must be a space so it may be dropped without consequence if output ends on odd nibble. Normal call is with firstTry == true." | charTable odd ix oddNibble names shorterStr maybe | charTable _ "Character encoding table must match qDecompress:" ' eatrnoislcm bdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'. ^ ByteArray streamContents: [:strm | odd _ true. "Flag for odd or even nibble out" oddNibble _ nil. str do: [:char | ix _ (charTable indexOf: char) - 1. (ix <= 12 ifTrue: [Array with: ix] ifFalse: [Array with: ix//16+12 with: ix\\16]) do: [:nibble | (odd _ odd not) ifTrue: [strm nextPut: oddNibble*16 + nibble] ifFalse: [oddNibble _ nibble]]]. strm position > 251 ifTrue: ["Only values 1...251 are available for the flag byte that signals compressed temps. See the logic in endPC." "Before giving up completely, we attempt to encode most of the temps, but with the last few shortened to tNN-style names." firstTry ifFalse: [^ nil "already tried --give up now"]. names _ str findTokens: ' '. names size < 8 ifTrue: [^ nil "weird case -- give up now"]. 4 to: names size//2 by: 4 do: [:i | shorterStr _ String streamContents: [:s | 1 to: names size - i do: [:j | s nextPutAll: (names at: j); space]. 1 to: i do: [:j | s nextPutAll: 't' , j printString; space]]. (maybe _ self qCompress: shorterStr firstTry: false) ifNotNil: [^ maybe]]. ^ nil]. strm nextPut: strm position] " | m s | m _ CompiledMethod new. s _ 'charTable odd ix oddNibble '. ^ Array with: s size with: (m qCompress: s) size with: (m qDecompress: (m qCompress: s)) " ! ! !CompiledMethod methodsFor: 'source code management'! qDecompress: byteArray "Decompress strings compressed by qCompress:. Most common 12 chars get values 0-11 packed in one 4-bit nibble; others get values 12-15 (2 bits) * 16 plus next nibble" | charTable extended ext | charTable _ "Character encoding table must match qCompress:" ' eatrnoislcm bdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'. ^ String streamContents: [:strm | extended _ false. "Flag for 2-nibble characters" byteArray do: [:byte | (Array with: byte//16 with: byte\\16) do: [:nibble | extended ifTrue: [strm nextPut: (charTable at: ext*16+nibble + 1). extended _ false] ifFalse: [nibble < 12 ifTrue: [strm nextPut: (charTable at: nibble + 1)] ifFalse: [ext _ nibble-12. extended _ true]]]]]! ! !CompiledMethod methodsFor: 'source code management' stamp: 'hmm 4/26/2000 21:00'! setSourcePointer: srcPointer srcPointer = 0 ifTrue: [ self at: self size put: 0. ^self]. (srcPointer between: 16r1000000 and: 16r4FFFFFF) ifFalse: [self error: 'Source pointer out of range']. self at: self size put: (srcPointer bitShift: -24) + 251. 1 to: 3 do: [:i | self at: self size-i put: ((srcPointer bitShift: (i-3)*8) bitAnd: 16rFF)]! ! !CompiledMethod methodsFor: 'source code management' stamp: 'hmm 4/26/2000 21:02'! setSourcePosition: position inFile: fileIndex self setSourcePointer: (SourceFiles sourcePointerFromFileIndex: fileIndex andPosition: position)! ! !CompiledMethod methodsFor: 'source code management' stamp: 'ajh 8/13/2002 18:19'! sourceClass "Get my receiver class (method class) from the preamble of my source. Return nil if not found." ^ [(Compiler evaluate: (self sourceFileStream backChunk "blank"; backChunk "preamble")) theClass] on: Error do: [nil]! ! !CompiledMethod methodsFor: 'source code management' stamp: 'ajh 8/13/2002 18:18'! sourceFileStream "Answer the sources file stream with position set at the beginning of my source string" | pos | (pos _ self filePosition) = 0 ifTrue: [^ nil]. ^ (RemoteString newFileNumber: self fileIndex position: pos) fileStream! ! !CompiledMethod methodsFor: 'source code management' stamp: 'hmm 4/26/2000 20:44'! sourcePointer "Answer the integer which can be used to find the source file and position for this method. The returned value is either 0 (if no source is stored) or a number between 16r1000000 and 16r4FFFFFF. The actual interpretation of this number is up to the SourceFileArray stored in the global variable SourceFiles." | pos | self last < 252 ifTrue: [^ 0 "no source"]. pos _ self last - 251. self size - 1 to: self size - 3 by: -1 do: [:i | pos _ pos * 256 + (self at: i)]. ^pos! ! !CompiledMethod methodsFor: 'source code management' stamp: 'ajh 7/21/2003 00:29'! tempNames | byteCount bytes | self holdsTempNames ifFalse: [ ^ (1 to: self numTemps) collect: [:i | 't', i printString] ]. byteCount _ self at: self size. byteCount = 0 ifTrue: [^ Array new]. bytes _ (ByteArray new: byteCount) replaceFrom: 1 to: byteCount with: self startingAt: self size - byteCount. ^ (self qDecompress: bytes) findTokens: ' '! ! !CompiledMethod methodsFor: 'file in/out' stamp: 'tk 10/6/2000 14:22'! readDataFrom: aDataStream size: varsOnDisk "Fill in my fields. My header and number of literals are already installed. Must read both objects for the literals and bytes for the bytecodes." self error: 'Must use readMethod'.! ! !CompiledMethod methodsFor: 'file in/out' stamp: 'tk 8/19/1998 16:20'! veryDeepCopyWith: deepCopier "Return self. I am always shared. Do not record me. Only use this for blocks. Normally methodDictionaries should not be copied this way."! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 5/28/2003 01:10'! blockNodeIn: homeMethodNode "Return the block node for self" homeMethodNode ifNil: [ ^ self decompilerClass new decompileBlock: self]. homeMethodNode ir compiledMethod. "generate method" homeMethodNode nodesDo: [:node | (node isBlock and: [node scope isInlined not and: [node ir compiledMethod = self]]) ifTrue: [ BlockNodeCache _ self -> node. ^ node] ]. self errorNodeNotFound! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 2/9/2003 19:45'! decompile "Return the decompiled parse tree that represents self" ^ self decompileClass: nil selector: nil! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 2/9/2003 19:44'! decompileClass: aClass selector: selector "Return the decompiled parse tree that represents self" ^ self decompilerClass new decompile: selector in: aClass method: self! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ar 6/28/2003 00:05'! decompilerClass ^Decompiler ! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 2/9/2003 13:11'! isClosureCompiled "Return true if this method was compiled with the new closure compiler, Parser2 (compiled while Preference compileBlocksAsClosures was true). Return false if it was compiled with the old compiler." ^ self header < 0! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 2/9/2003 00:22'! methodNode "Return the parse tree that represents self" ^ self methodNodeDecompileClass: nil selector: nil! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ajh 12/13/2003 18:30'! methodNodeDecompileClass: aClass selector: selector "Return the parse tree that represents self" | source | ^ (source _ self getSourceFromFile) ifNil: [self decompileClass: aClass selector: selector] ifNotNil: [self parserClass new parse: source class: (aClass ifNil: [self sourceClass])]! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'nk 2/20/2004 15:59'! methodNodeFormattedAndDecorated: decorate "Return the parse tree that represents self" ^ self methodNodeFormattedDecompileClass: nil selector: nil decorate: decorate! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'nk 2/20/2004 15:58'! methodNodeFormattedDecompileClass: aClass selector: selector decorate: decorated "Return the parse tree that represents self, using pretty-printed source text if possible." | source sClass node | source := self getSourceFromFile. sClass _ aClass ifNil: [self sourceClass]. source ifNil: [ ^self decompileClass: sClass selector: selector]. source _ sClass compilerClass new format: source in: sClass notifying: nil decorated: decorated. node _ sClass parserClass new parse: source class: sClass. node sourceText: source. ^node! ! !CompiledMethod methodsFor: 'decompiling' stamp: 'ar 6/28/2003 00:05'! parserClass ^Parser! ! !CompiledMethod methodsFor: 'breakpoints' stamp: 'emm 5/30/2002 09:22'! hasBreakpoint ^BreakpointManager methodHasBreakpoint: self! ! !CompiledMethod methodsFor: 'user interface' stamp: 'ajh 2/3/2003 19:18'! inspectorClass ^ CompiledMethodInspector! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CompiledMethod class instanceVariableNames: ''! !CompiledMethod class methodsFor: 'class initialization' stamp: 'ajh 2/3/2003 21:16'! initialize "CompiledMethod initialize" "Initialize class variables specifying the size of the temporary frame needed to run instances of me." SmallFrame _ 16. "Context range for temps+stack" LargeFrame _ 56. self classPool at: #BlockNodeCache ifAbsentPut: [nil->nil].! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'tk 9/9/2000 20:36'! basicNew: size self error: 'CompiledMethods may only be created with newMethod:header:' ! ! !CompiledMethod class methodsFor: 'instance creation'! new "This will not make a meaningful method, but it could be used to invoke some otherwise useful method in this class." ^ self newMethod: 0 header: 0! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'tk 1/21/2000 15:25'! new: size self error: 'CompiledMethods may only be created with newMethod:header:'! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'di 5/25/2000 06:37'! newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex "Answer an instance of me. The header is specified by the message arguments. The remaining parts are not as yet determined." | largeBit primBits method | nTemps > 64 ifTrue: [^ self error: 'Cannot compile -- too many temporary variables']. largeBit _ (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0]. primBits _ primitiveIndex <= 16r1FF ifTrue: [primitiveIndex] ifFalse: ["For now the high 2 bits of primitive no. are in high bits of header" (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r600) bitShift: 19)]. method _ self newMethod: numberOfBytes + trailer size header: (nArgs bitShift: 24) + (nTemps bitShift: 18) + (largeBit bitShift: 17) + (nLits bitShift: 9) + primBits. 1 to: trailer size do: "Copy the source code trailer to the end" [:i | method at: method size - trailer size + i put: (trailer at: i)]. ^ method! ! !CompiledMethod class methodsFor: 'instance creation'! newMethod: numberOfBytes header: headerWord "Primitive. Answer an instance of me. The number of literals (and other information) is specified the headerWord. The first argument specifies the number of fields for bytecodes in the method. Fail if either argument is not a SmallInteger, or if numberOfBytes is negative. Once the header of a method is set by this primitive, it cannot be changed in any way. Essential. See Object documentation whatIsAPrimitive." <primitive: 79> (numberOfBytes isInteger and: [headerWord isInteger and: [numberOfBytes >= 0]]) ifTrue: [ "args okay; space must be low" Smalltalk signalLowSpace. "retry if user proceeds" ^ self newMethod: numberOfBytes header: headerWord ]. ^self primitiveFailed! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'di 5/25/2000 06:43'! toReturnConstant: index trailerBytes: trailer "Answer an instance of me that is a quick return of the constant indexed in (true false nil -1 0 1 2)." ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 + index ! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'di 5/25/2000 06:44'! toReturnField: field trailerBytes: trailer "Answer an instance of me that is a quick return of the instance variable indexed by the argument, field." ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 264 + field ! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'di 5/25/2000 06:51'! toReturnSelf "Answer an instance of me that is a quick return of the instance (^self)." ^ self toReturnSelfTrailerBytes: #(0 0 0 0)! ! !CompiledMethod class methodsFor: 'instance creation' stamp: 'di 5/25/2000 06:44'! toReturnSelfTrailerBytes: trailer "Answer an instance of me that is a quick return of the instance (^self)." ^ self newBytes: 0 trailerBytes: trailer nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 ! ! Inspector subclass: #CompiledMethodInspector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !CompiledMethodInspector methodsFor: 'accessing' stamp: 'ajh 1/18/2003 13:47'! fieldList | keys | keys _ OrderedCollection new. keys add: 'self'. keys add: 'all bytecodes'. keys add: 'header'. 1 to: object numLiterals do: [ :i | keys add: 'literal', i printString ]. object initialPC to: object size do: [ :i | keys add: i printString ]. ^ keys asArray ! ! !CompiledMethodInspector methodsFor: 'selecting' stamp: 'ajh 3/20/2003 00:17'! contentsIsString "Hacked so contents empty when deselected" ^ #(0 2 3) includes: selectionIndex! ! !CompiledMethodInspector methodsFor: 'selecting' stamp: 'ajh 1/18/2003 13:56'! selection | bytecodeIndex | selectionIndex = 0 ifTrue: [^ '']. selectionIndex = 1 ifTrue: [^ object ]. selectionIndex = 2 ifTrue: [^ object symbolic]. selectionIndex = 3 ifTrue: [^ object headerDescription]. selectionIndex <= (object numLiterals + 3) ifTrue: [ ^ object objectAt: selectionIndex - 2 ]. bytecodeIndex _ selectionIndex - object numLiterals - 3. ^ object at: object initialPC + bytecodeIndex - 1! ! !CompiledMethodInspector methodsFor: 'selecting' stamp: 'ajh 3/20/2001 11:56'! selectionUnmodifiable "Answer if the current selected variable is unmodifiable via acceptance in the code pane. For most inspectors, no selection and a selection of self (selectionIndex = 1) are unmodifiable" ^ true! ! Object subclass: #CompiledMethodWithNode instanceVariableNames: 'node method' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !CompiledMethodWithNode methodsFor: 'private' stamp: 'NS 1/28/2004 09:03'! method: aCompiledMethod method _ aCompiledMethod! ! !CompiledMethodWithNode methodsFor: 'private' stamp: 'NS 1/28/2004 09:04'! node: aMethodNode node _ aMethodNode! ! !CompiledMethodWithNode methodsFor: 'accessing' stamp: 'NS 1/28/2004 09:03'! method ^ method! ! !CompiledMethodWithNode methodsFor: 'accessing' stamp: 'NS 1/28/2004 09:04'! node ^ node! ! !CompiledMethodWithNode methodsFor: 'accessing' stamp: 'NS 1/28/2004 09:04'! selector ^ self node selector! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CompiledMethodWithNode class instanceVariableNames: ''! !CompiledMethodWithNode class methodsFor: 'instance creation' stamp: 'NS 1/28/2004 09:05'! generateMethodFromNode: aMethodNode trailer: bytes ^ self method: (aMethodNode generate: bytes) node: aMethodNode.! ! !CompiledMethodWithNode class methodsFor: 'instance creation' stamp: 'NS 1/28/2004 09:05'! method: aCompiledMethod node: aMethodNode ^ self new method: aCompiledMethod; node: aMethodNode.! ! Object subclass: #Compiler instanceVariableNames: 'sourceStream requestor class context parserClass cacheDoItNode' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !Compiler commentStamp: '<historical>' prior: 0! 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.! !Compiler methodsFor: 'error handling'! interactive "Answer whether there is a requestor of the compiler who should be informed that an error occurred." ^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not! ! !Compiler methodsFor: 'error handling'! notify: aString "Refer to the comment in Object|notify:." ^self notify: aString at: sourceStream position + 1! ! !Compiler methodsFor: 'error handling' stamp: 'LC 1/6/2002 13:53'! notify: aString at: location "Refer to the comment in Object|notify:." requestor == nil ifTrue: [^SyntaxErrorNotification inClass: class withCode: (sourceStream contents copyReplaceFrom: location to: location - 1 with: aString) doitFlag: false] ifFalse: [^requestor notify: aString at: location in: sourceStream]! ! !Compiler methodsFor: 'public access'! compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock "Answer a MethodNode for the argument, textOrStream. If the MethodNode can not be created, notify the argument, aRequestor; if aRequestor is nil, evaluate failBlock instead. The MethodNode is the root of a parse tree. It can be told to generate a CompiledMethod to be installed in the method dictionary of the argument, aClass." self from: textOrStream class: aClass context: nil notifying: aRequestor. ^self translate: sourceStream noPattern: false ifFail: failBlock! ! !Compiler methodsFor: 'public access' stamp: 'vb 8/13/2001 23:11'! compileNoPattern: textOrStream in: aClass context: aContext notifying: aRequestor ifFail: failBlock "Similar to #compile:in:notifying:ifFail:, but the compiled code is expected to be a do-it expression, with no message pattern." self from: textOrStream class: aClass context: aContext notifying: aRequestor. ^self translate: sourceStream noPattern: true ifFail: failBlock! ! !Compiler methodsFor: 'public access' stamp: 'sd 1/19/2004 20:58'! evaluate: aString in: aContext to: aReceiver "evaluate aString in the given context, and return the result. 2/2/96 sw" | result | result _ self evaluate: aString in: aContext to: aReceiver notifying: nil ifFail: [^ #failedDoit]. ^ result! ! !Compiler methodsFor: 'public access' stamp: 'NS 1/19/2004 09:05'! evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock ^ self evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock logged: false.! ! !Compiler methodsFor: 'public access' stamp: 'NS 1/28/2004 11:19'! evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock logged: logFlag "Compiles the sourceStream into a parse tree, then generates code into a method. This method is then installed in the receiver's class so that it can be invoked. In other words, if receiver is not nil, then the text can refer to instance variables of that receiver (the Inspector uses this). If aContext is not nil, the text can refer to temporaries in that context (the Debugger uses this). If aRequestor is not nil, then it will receive a notify:at: message before the attempt to evaluate is aborted. Finally, the compiled method is invoked from here as DoIt or (in the case of evaluation in aContext) DoItIn:. The method is subsequently removed from the class, but this will not get done if the invocation causes an error which is terminated. Such garbage can be removed by executing: Smalltalk allBehaviorsDo: [:cl | cl removeSelector: #DoIt; removeSelector: #DoItIn:]." | methodNode method value selector | class _ (aContext == nil ifTrue: [receiver] ifFalse: [aContext receiver]) class. self from: textOrStream class: class context: aContext notifying: aRequestor. methodNode _ self translate: sourceStream noPattern: true ifFail: [^failBlock value]. method _ methodNode generate: #(0 0 0 0). self interactive ifTrue: [method _ method copyWithTempNames: methodNode tempNames]. selector _ context isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. class addSelectorSilently: selector withMethod: method. value _ context isNil ifTrue: [receiver DoIt] ifFalse: [receiver DoItIn: context]. InMidstOfFileinNotification signal ifFalse: [class basicRemoveSelector: selector]. logFlag ifTrue: [SystemChangeNotifier uniqueInstance evaluated: sourceStream contents context: aContext]. ^ value.! ! !Compiler methodsFor: 'public access' stamp: 'sw 5/20/2001 10:01'! format: textOrStream in: aClass notifying: aRequestor contentsSymbol: aSymbol "Compile a parse tree from the argument, textOrStream. Answer a string containing the original code, formatted nicely. If aBoolean is true, then decorate the resulting text with color and hypertext actions" | aNode | self from: textOrStream class: aClass context: nil notifying: aRequestor. aNode _ self format: sourceStream noPattern: false ifFail: [^ nil]. aSymbol == #colorPrint ifTrue: [^ aNode asColorizedSmalltalk80Text]. aSymbol == #altSyntax "Alan's current explorations for alternate syntax - 2000/2001" ifTrue: [^ aNode asAltSyntaxText]. ^ aNode decompileString! ! !Compiler methodsFor: 'public access' stamp: 'sw 11/7/1999 00:11'! format: textOrStream in: aClass notifying: aRequestor decorated: aBoolean "Compile a parse tree from the argument, textOrStream. Answer a string containing the original code, formatted nicely. If aBoolean is true, then decorate the resulting text with color and hypertext actions" | aNode | self from: textOrStream class: aClass context: nil notifying: aRequestor. aNode _ self format: sourceStream noPattern: false ifFail: [^ nil]. ^ aBoolean ifTrue: [aNode decompileText] ifFalse: [aNode decompileString]! ! !Compiler methodsFor: 'public access' stamp: 'di 4/24/2000 07:46'! parse: textOrStream in: aClass notifying: req "Compile the argument, textOrStream, with respect to the class, aClass, and answer the MethodNode that is the root of the resulting parse tree. Notify the argument, req, if an error occurs. The failBlock is defaulted to an empty block." ^ self parse: textOrStream in: aClass notifying: req dialect: false! ! !Compiler methodsFor: 'public access' stamp: 'ajh 9/14/2002 18:47'! parse: textOrStream in: aClass notifying: req dialect: useDialect "Compile the argument, textOrStream, with respect to the class, aClass, and answer the MethodNode that is the root of the resulting parse tree. Notify the argument, req, if an error occurs. The failBlock is defaulted to an empty block." self from: textOrStream class: aClass context: nil notifying: req. ^ ((useDialect and: [RequestAlternateSyntaxSetting signal]) ifTrue: [self dialectParserClass] ifFalse: [self parserClass]) new parse: sourceStream class: class noPattern: false context: context notifying: requestor ifFail: []! ! !Compiler methodsFor: 'private' stamp: 'ar 6/28/2003 00:05'! dialectParserClass ^DialectParser! ! !Compiler methodsFor: 'private' stamp: 'ajh 1/21/2003 12:44'! format: aStream noPattern: noPattern ifFail: failBlock | tree | tree _ self parserClass new parse: aStream class: class noPattern: noPattern context: context notifying: requestor ifFail: [^ failBlock value]. ^ tree! ! !Compiler methodsFor: 'private'! from: textOrStream class: aClass context: aContext notifying: req (textOrStream isKindOf: PositionableStream) ifTrue: [sourceStream _ textOrStream] ifFalse: [sourceStream _ ReadStream on: textOrStream asString]. class _ aClass. context _ aContext. requestor _ req! ! !Compiler methodsFor: 'private' stamp: 'ajh 1/21/2003 12:44'! parserClass ^ parserClass! ! !Compiler methodsFor: 'private' stamp: 'ajh 9/19/2002 02:20'! parserClass: aParserClass parserClass _ aParserClass. cacheDoItNode _ true. ! ! !Compiler methodsFor: 'private' stamp: 'ajh 1/21/2003 12:45'! translate: aStream noPattern: noPattern ifFail: failBlock | tree | tree _ self parserClass new parse: aStream class: class noPattern: noPattern context: context notifying: requestor ifFail: [^ failBlock value]. ^ tree! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Compiler class instanceVariableNames: ''! !Compiler class methodsFor: 'accessing' stamp: 'ajh 1/21/2003 12:39'! new ^ super new parserClass: self parserClass! ! !Compiler class methodsFor: 'accessing'! parserClass "Return a parser class to use for parsing method headers." ^Parser! ! !Compiler class methodsFor: 'evaluating' stamp: 'NS 1/19/2004 10:07'! evaluate: textOrString "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, a Syntax Error view is created rather than notifying any requestor. Compilation is carried out with respect to nil, i.e., no object, and the invocation is not logged." ^self evaluate: textOrString for: nil logged: false! ! !Compiler class methodsFor: 'evaluating'! evaluate: textOrString for: anObject logged: logFlag "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, a Syntax Error view is created rather than notifying any requestor." ^self evaluate: textOrString for: anObject notifying: nil logged: logFlag! ! !Compiler class methodsFor: 'evaluating' stamp: 'NS 1/19/2004 09:50'! evaluate: textOrString for: anObject notifying: aController logged: logFlag "Compile and execute the argument, textOrString with respect to the class of anObject. If a compilation error occurs, notify aController. If both compilation and execution are successful then, if logFlag is true, log (write) the text onto a system changes file so that it can be replayed if necessary." ^ self new evaluate: textOrString in: nil to: anObject notifying: aController ifFail: [^nil] logged: logFlag.! ! !Compiler class methodsFor: 'evaluating'! evaluate: textOrString logged: logFlag "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, a Syntax Error view is created rather than notifying any requestor. Compilation is carried out with respect to nil, i.e., no object." ^self evaluate: textOrString for: nil logged: logFlag! ! !Compiler class methodsFor: 'evaluating'! evaluate: textOrString notifying: aController logged: logFlag "See Compiler|evaluate:for:notifying:logged:. Compilation is carried out with respect to nil, i.e., no object." ^self evaluate: textOrString for: nil notifying: aController logged: logFlag! ! CharacterScanner subclass: #CompositionScanner instanceVariableNames: 'spaceX spaceIndex lineHeight baseline lineHeightAtSpace baselineAtSpace' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !CompositionScanner commentStamp: '<historical>' prior: 0! CompositionScanners are used to measure text and determine where line breaks and space padding should occur.! !CompositionScanner methodsFor: 'scanning' stamp: 'hmm 7/20/2000 18:24'! composeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph "Answer an instance of TextLineInterval that represents the next line in the paragraph." | runLength done stopCondition | destX _ spaceX _ leftMargin _ aParagraph leftMarginForCompositionForLine: lineIndex. destY _ 0. rightMargin _ aParagraph rightMarginForComposition. leftMargin >= rightMargin ifTrue: [self error: 'No room between margins to compose']. lastIndex _ startIndex. "scanning sets last index" lineHeight _ textStyle lineGrid. "may be increased by setFont:..." baseline _ textStyle baseline. self setStopConditions. "also sets font" self handleIndentation. runLength _ text runLengthFor: startIndex. runStopIndex _ (lastIndex _ startIndex) + (runLength - 1). line _ TextLineInterval start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0. spaceCount _ 0. done _ false. [done] whileFalse: [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex in: text string rightX: rightMargin stopConditions: stopConditions kern: kern. "See setStopConditions for stopping conditions for composing." (self perform: stopCondition) ifTrue: [^line lineHeight: lineHeight + textStyle leading baseline: baseline + textStyle leading]]! ! !CompositionScanner methodsFor: 'scanning' stamp: 'ar 1/8/2000 14:36'! setActualFont: aFont "Keep track of max height and ascent for auto lineheight" | descent | super setActualFont: aFont. lineHeight == nil ifTrue: [descent _ font descent. baseline _ font ascent. lineHeight _ baseline + descent] ifFalse: [descent _ lineHeight - baseline max: font descent. baseline _ baseline max: font ascent. lineHeight _ lineHeight max: baseline + descent]! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'RAA 5/4/2001 13:52'! columnBreak "Answer true. Set up values for the text line interval currently being composed." line stop: lastIndex. spaceX _ destX. line paddingWidth: rightMargin - spaceX. ^true! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:54'! cr "Answer true. Set up values for the text line interval currently being composed." line stop: lastIndex. spaceX _ destX. line paddingWidth: rightMargin - spaceX. ^true! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:54'! crossedX "There is a word that has fallen across the right edge of the composition rectangle. This signals the need for wrapping which is done to the last space that was encountered, as recorded by the space stop condition." spaceCount >= 1 ifTrue: ["The common case. First back off to the space at which we wrap." line stop: spaceIndex. lineHeight _ lineHeightAtSpace. baseline _ baselineAtSpace. spaceCount _ spaceCount - 1. spaceIndex _ spaceIndex - 1. "Check to see if any spaces preceding the one at which we wrap. Double space after punctuation, most likely." [(spaceCount > 1 and: [(text at: spaceIndex) = Space])] whileTrue: [spaceCount _ spaceCount - 1. "Account for backing over a run which might change width of space." font _ text fontAt: spaceIndex withStyle: textStyle. spaceIndex _ spaceIndex - 1. spaceX _ spaceX - (font widthOf: Space)]. line paddingWidth: rightMargin - spaceX. line internalSpaces: spaceCount] ifFalse: ["Neither internal nor trailing spaces -- almost never happens." lastIndex _ lastIndex - 1. [destX <= rightMargin] whileFalse: [destX _ destX - (font widthOf: (text at: lastIndex)). lastIndex _ lastIndex - 1]. spaceX _ destX. line paddingWidth: rightMargin - destX. line stop: (lastIndex max: line first)]. ^true! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:54'! endOfRun "Answer true if scanning has reached the end of the paragraph. Otherwise step conditions (mostly install potential new font) and answer false." | runLength | lastIndex = text size ifTrue: [line stop: lastIndex. spaceX _ destX. line paddingWidth: rightMargin - destX. ^true] ifFalse: [runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)). runStopIndex _ lastIndex + (runLength - 1). self setStopConditions. ^false] ! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 12/17/2001 02:13'! placeEmbeddedObject: anchoredMorph | descent | "Workaround: The following should really use #textAnchorType" anchoredMorph relativeTextAnchorPosition ifNotNil:[^true]. (super placeEmbeddedObject: anchoredMorph) ifFalse: ["It doesn't fit" "But if it's the first character then leave it here" lastIndex < line first ifFalse:[ line stop: lastIndex-1. ^ false]]. descent _ lineHeight - baseline. lineHeight _ lineHeight max: anchoredMorph height. baseline _ lineHeight - descent. line stop: lastIndex. ^ true! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'BG 10/29/2003 10:20'! setFont super setFont. stopConditions == DefaultStopConditions ifTrue:[stopConditions _ stopConditions copy]. stopConditions at: Space asciiValue + 1 put: #space. wantsColumnBreaks == true ifTrue: [ stopConditions at: "TextComposer characterForColumnBreak asciiValue" 1 + 1 put: #columnBreak. ]. ! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/8/2000 14:37'! setStopConditions "Set the font and the stop conditions for the current run." self setFont! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:55'! space "Record left x and character index of the space character just encounted. Used for wrap-around. Answer whether the character has crossed the right edge of the composition rectangle of the paragraph." spaceX _ destX. destX _ spaceX + spaceWidth. spaceIndex _ lastIndex. lineHeightAtSpace _ lineHeight. baselineAtSpace _ baseline. lastIndex _ lastIndex + 1. spaceCount _ spaceCount + 1. destX > rightMargin ifTrue: [^self crossedX]. ^false ! ! !CompositionScanner methodsFor: 'stop conditions' stamp: 'ar 1/9/2000 13:59'! tab "Advance destination x according to tab settings in the paragraph's textStyle. Answer whether the character has crossed the right edge of the composition rectangle of the paragraph." destX _ textStyle nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin. destX > rightMargin ifTrue: [^self crossedX]. lastIndex _ lastIndex + 1. ^false ! ! !CompositionScanner methodsFor: 'accessing' stamp: 'ar 1/8/2000 14:35'! rightX "Meaningful only when a line has just been composed -- refers to the line most recently composed. This is a subtrefuge to allow for easy resizing of a composition rectangle to the width of the maximum line. Useful only when there is only one line in the form or when each line is terminated by a carriage return. Handy for sizing menus and lists." ^spaceX! ! !CompositionScanner methodsFor: 'intialize-release' stamp: 'ar 5/17/2000 19:14'! forParagraph: aParagraph "Initialize the receiver for scanning the given paragraph." self initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle. ! ! ReadWriteStream subclass: #CompressedSourceStream instanceVariableNames: 'segmentFile segmentSize nSegments segmentTable segmentIndex dirty endOfFile' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !CompressedSourceStream commentStamp: 'di 11/3/2003 17:58' prior: 0! I implement a file format that compresses segment by segment to allow incremental writing and browsing. Note that the file can only be written at the end. Structure: segmentFile The actual compressed file. segmentSize This is the quantum of compression. The virtual file is sliced up into segments of this size. nSegments The maximum number of segments to which this file can be grown. endOfFile The user's endOfFile pointer. segmentTable When a file is open, this table holds the physical file positions of the compressed segments. segmentIndex Index of the most recently accessed segment. Inherited from ReadWriteStream... collection The segment buffer, uncompressed position This is the position *local* to the current segment buffer readLimit ReadLimit for the current buffer writeLimit WriteLimit for the current buffer Great care must be exercised to distinguish between the position relative to the segment buffer and the full file position (and, or course, the segment file position ;-). The implementation defaults to a buffer size of 20k, and a max file size of 34MB (conveniently chosen to be greater than the current 33MB limit of source code pointers). The format of the file is as follows: segmentSize 4 bytes nSegments 4 bytes endOfFile 4 bytes segmentTable 4 bytes * (nSegments+1) beginning of first compressed segment It is possible to override the default allocation by sending the message #segmentSize:nSegments: immediately after opening a new file for writing, as follows: bigFile _ (CompressedSourceStream on: (FileStream newFileNamed: 'biggy.stc')) segmentSize: 50000 maxSize: 200000000 The difference between segment table entries reveals the size of each compressed segment. When a file is being written, it may lack the final segment, but any flush, position:, or close will force a dirty segment to be written.! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/1/2003 22:36'! binary self error: 'Compressed source files are ascii to the user (though binary underneath)'! ! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/1/2003 22:36'! close self flush. segmentFile close! ! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/3/2003 17:54'! openOn: aFile "Open the receiver." segmentFile _ aFile. segmentFile binary. segmentFile size > 0 ifTrue: [self readHeaderInfo. "If file exists, then read the parameters"] ifFalse: [self segmentSize: 20000 maxSize: 34000000. "Otherwise write default values"]! ! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/3/2003 10:13'! openReadOnly segmentFile openReadOnly! ! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/5/2003 22:41'! readHeaderInfo | valid a b | segmentFile position: 0. segmentSize _ segmentFile nextNumber: 4. nSegments _ segmentFile nextNumber: 4. endOfFile _ segmentFile nextNumber: 4. segmentFile size < (nSegments+1 + 3 * 4) ifTrue: "Check for reasonable segment info" [self error: 'This file is not in valid compressed source format']. segmentTable _ (1 to: nSegments+1) collect: [:x | segmentFile nextNumber: 4]. segmentTable first ~= self firstSegmentLoc ifTrue: [self error: 'This file is not in valid compressed source format']. valid _ true. 1 to: nSegments do: "Check that segment offsets are ascending" [:i | a _ segmentTable at: i. b _ segmentTable at: i+1. (a = 0 and: [b ~= 0]) ifTrue: [valid _ false]. (a ~= 0 and: [b ~= 0]) ifTrue: [b <= a ifTrue: [valid _ false]]]. valid ifFalse: [self error: 'This file is not in valid compressed source format']. dirty _ false. self position: 0.! ! !CompressedSourceStream methodsFor: 'open/close' stamp: 'di 11/3/2003 10:09'! readOnlyCopy ^ self class on: segmentFile readOnlyCopy! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/3/2003 00:41'! atEnd position >= readLimit ifFalse: [^ false]. "more in segment" ^ self position >= endOfFile "more in file"! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/1/2003 22:48'! contentsOfEntireFile | contents | self position: 0. contents _ self next: self size. self close. ^ contents! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/1/2003 19:50'! flush dirty ifTrue: ["Write buffer, compressed, to file, and also write the segment offset and eof" self writeSegment].! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/20/2003 12:03'! next <primitive: 65> position >= readLimit ifTrue: [^ (self next: 1) at: 1] ifFalse: [^ collection at: (position _ position + 1)]! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/2/2003 11:45'! next: n | str | n <= (readLimit - position) ifTrue: ["All characters are available in buffer" str _ collection copyFrom: position + 1 to: position + n. position _ position + n. ^ str]. "Read limit could be segment boundary or real end of file" (readLimit + self segmentOffset) = endOfFile ifTrue: ["Real end of file -- just return what's available" ^ self next: readLimit - position]. "Read rest of segment. Then (after positioning) read what remains" str _ self next: readLimit - position. self position: self position. ^ str , (self next: n - str size) ! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/2/2003 11:27'! nextPut: char "Slow, but we don't often write, and then not a lot" self nextPutAll: char asString. ^ char! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/2/2003 12:06'! nextPutAll: str | n nInSeg | n _ str size. n <= (writeLimit - position) ifTrue: ["All characters fit in buffer" collection replaceFrom: position + 1 to: position + n with: str. dirty _ true. position _ position + n. readLimit _ readLimit max: position. endOfFile _ endOfFile max: self position. ^ str]. "Write what fits in segment. Then (after positioning) write what remains" nInSeg _ writeLimit - position. nInSeg = 0 ifTrue: [self position: self position. self nextPutAll: str] ifFalse: [self nextPutAll: (str first: nInSeg). self position: self position. self nextPutAll: (str allButFirst: nInSeg)] ! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/2/2003 09:27'! position ^ position + self segmentOffset! ! !CompressedSourceStream methodsFor: 'access' stamp: 'di 11/1/2003 11:41'! size ^ endOfFile ifNil: [0]! ! !CompressedSourceStream methodsFor: 'private' stamp: 'di 11/2/2003 09:35'! firstSegmentLoc "First segment follows 3 header words and segment table" ^ (3 + nSegments+1) * 4! ! !CompressedSourceStream methodsFor: 'private' stamp: 'di 11/2/2003 09:24'! segmentOffset ^ segmentIndex - 1 * segmentSize! ! !CompressedSourceStream methodsFor: 'private' stamp: 'di 11/5/2003 22:41'! segmentSize: segSize maxSize: maxSize "Note that this method can be called after the initial open, provided that no writing has yet taken place. This is how to override the default segmentation." self size = 0 ifFalse: [self error: 'Cannot set parameters after the first write']. segmentFile position: 0. segmentFile nextNumber: 4 put: (segmentSize _ segSize). segmentFile nextNumber: 4 put: (nSegments _ maxSize // segSize + 2). segmentFile nextNumber: 4 put: (endOfFile _ 0). segmentTable _ Array new: nSegments+1 withAll: 0. segmentTable at: 1 put: self firstSegmentLoc. "Loc of first segment, always." segmentTable do: [:i | segmentFile nextNumber: 4 put: i]. segmentIndex _ 1. collection _ String new: segmentSize. writeLimit _ segmentSize. readLimit _ 0. position _ 0. endOfFile _ 0. self writeSegment. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CompressedSourceStream class instanceVariableNames: ''! !CompressedSourceStream class methodsFor: 'as yet unclassified' stamp: 'di 11/1/2003 22:58'! on: aFile ^ self basicNew openOn: aFile! ! InstructionStream subclass: #ContextPart instanceVariableNames: 'stackp' classVariableNames: 'PrimitiveFailToken QuickStep' poolDictionaries: '' category: 'Kernel-Methods'! !ContextPart commentStamp: '<historical>' prior: 0! 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. 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, Transcript show: (ContextPart runSimulated: [3 factorial]) printString.! !ContextPart methodsFor: 'accessing'! client "Answer the client, that is, the object that sent the message that created this context." ^sender receiver! ! !ContextPart methodsFor: 'accessing'! home "Answer the context in which the receiver was defined." self subclassResponsibility! ! !ContextPart methodsFor: 'accessing'! method "Answer the method of this context." self subclassResponsibility! ! !ContextPart methodsFor: 'accessing' stamp: 'ajh 2/9/2003 00:21'! methodNode | selector methodClass | selector _ self receiver class selectorAtMethod: self method setClass: [:mclass | methodClass _ mclass]. ^ self method methodNodeDecompileClass: methodClass selector: selector! ! !ContextPart methodsFor: 'accessing' stamp: 'nk 2/20/2004 16:50'! methodNodeFormattedAndDecorated: decorate "Answer a method node made from pretty-printed (and colorized, if decorate is true) source text." | selector methodClass | selector _ self receiver class selectorAtMethod: self method setClass: [:mclass | methodClass _ mclass]. ^ self method methodNodeFormattedDecompileClass: methodClass selector: selector decorate: decorate! ! !ContextPart methodsFor: 'accessing'! receiver "Answer the receiver of the message that created this context." self subclassResponsibility! ! !ContextPart methodsFor: 'accessing'! tempAt: index "Answer the value of the temporary variable whose index is the argument, index." self subclassResponsibility! ! !ContextPart methodsFor: 'accessing'! tempAt: index put: value "Store the argument, value, as the temporary variable whose index is the argument, index." self subclassResponsibility! ! !ContextPart methodsFor: 'instruction decoding'! doDup "Simulate the action of a 'duplicate top of stack' bytecode." self push: self top! ! !ContextPart methodsFor: 'instruction decoding'! doPop "Simulate the action of a 'remove top of stack' bytecode." self pop! ! !ContextPart methodsFor: 'instruction decoding'! jump: distance "Simulate the action of a 'unconditional jump' bytecode whose offset is the argument, distance." pc _ pc + distance! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'ajh 7/6/2003 20:38'! jump: distance if: condition "Simulate the action of a 'conditional jump' bytecode whose offset is the argument, distance, and whose condition is the argument, condition." | bool | bool _ self pop. (bool == true or: [bool == false]) ifFalse: [ ^self send: #mustBeBooleanIn: to: bool with: {self} super: false]. (bool eqv: condition) ifTrue: [self jump: distance]! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'ajh 1/24/2003 16:35'! methodReturnConstant: value "Simulate the action of a 'return constant' bytecode whose value is the argument, value. This corresponds to a source expression like '^0'." ^ self return: value from: self home! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'ajh 1/24/2003 16:34'! methodReturnReceiver "Simulate the action of a 'return receiver' bytecode. This corresponds to the source expression '^self'." ^ self return: self receiver from: self home! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'ajh 1/24/2003 16:34'! methodReturnTop "Simulate the action of a 'return top of stack' bytecode. This corresponds to source expressions like '^something'." ^ self return: self pop from: self home! ! !ContextPart methodsFor: 'instruction decoding'! popIntoLiteralVariable: value "Simulate the action of bytecode that removes the top of the stack and stores it into a literal variable of my method." value value: self pop! ! !ContextPart methodsFor: 'instruction decoding'! popIntoReceiverVariable: offset "Simulate the action of bytecode that removes the top of the stack and stores it into an instance variable of my receiver." self receiver instVarAt: offset + 1 put: self pop! ! !ContextPart methodsFor: 'instruction decoding'! popIntoTemporaryVariable: offset "Simulate the action of bytecode that removes the top of the stack and stores it into one of my temporary variables." self home at: offset + 1 put: self pop! ! !ContextPart methodsFor: 'instruction decoding'! pushActiveContext "Simulate the action of bytecode that pushes the the active context on the top of its own stack." self push: self! ! !ContextPart methodsFor: 'instruction decoding'! pushConstant: value "Simulate the action of bytecode that pushes the constant, value, on the top of the stack." self push: value! ! !ContextPart methodsFor: 'instruction decoding'! pushLiteralVariable: value "Simulate the action of bytecode that pushes the contents of the literal variable whose index is the argument, index, on the top of the stack." self push: value value! ! !ContextPart methodsFor: 'instruction decoding'! pushReceiver "Simulate the action of bytecode that pushes the active context's receiver on the top of the stack." self push: self receiver! ! !ContextPart methodsFor: 'instruction decoding'! pushReceiverVariable: offset "Simulate the action of bytecode that pushes the contents of the receiver's instance variable whose index is the argument, index, on the top of the stack." self push: (self receiver instVarAt: offset + 1)! ! !ContextPart methodsFor: 'instruction decoding'! pushTemporaryVariable: offset "Simulate the action of bytecode that pushes the contents of the temporary variable whose index is the argument, index, on the top of the stack." self push: (self home at: offset + 1)! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'ajh 3/5/2004 03:44'! return: value from: aSender "For simulation. Roll back self to aSender and return value from it. Execute any unwind blocks on the way. ASSUMES aSender is a sender of self" | newTop ctxt | aSender isDead ifTrue: [ ^ self send: #cannotReturn: to: self with: {value} super: false]. newTop _ aSender sender. ctxt _ self findNextUnwindContextUpTo: newTop. ctxt ifNotNil: [ ^ self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false]. self releaseTo: newTop. newTop ifNotNil: [newTop push: value]. ^ newTop ! ! !ContextPart methodsFor: 'instruction decoding' stamp: 'hmm 7/17/2001 20:52'! send: selector super: superFlag numArgs: numArgs "Simulate the action of bytecodes that send a message with selector, selector. The argument, superFlag, tells whether the receiver of the message was specified with 'super' in the source method. The arguments of the message are found in the top numArgs locations on the stack and the receiver just below them." | receiver arguments answer | arguments _ Array new: numArgs. numArgs to: 1 by: -1 do: [ :i | arguments at: i put: self pop]. receiver _ self pop. selector == #doPrimitive:method:receiver:args: ifTrue: [answer _ receiver doPrimitive: (arguments at: 1) method: (arguments at: 2) receiver: (arguments at: 3) args: (arguments at: 4). self push: answer. ^self]. QuickStep == self ifTrue: [ QuickStep _ nil. ^self quickSend: selector to: receiver with: arguments super: superFlag]. ^self send: selector to: receiver with: arguments super: superFlag! ! !ContextPart methodsFor: 'instruction decoding'! storeIntoLiteralVariable: value "Simulate the action of bytecode that stores the top of the stack into a literal variable of my method." value value: self top! ! !ContextPart methodsFor: 'instruction decoding'! storeIntoReceiverVariable: offset "Simulate the action of bytecode that stores the top of the stack into an instance variable of my receiver." self receiver instVarAt: offset + 1 put: self top! ! !ContextPart methodsFor: 'instruction decoding'! storeIntoTemporaryVariable: offset "Simulate the action of bytecode that stores the top of the stack into one of my temporary variables." self home at: offset + 1 put: self top! ! !ContextPart methodsFor: 'debugger access' stamp: 'ajh 9/25/2001 00:12'! contextStack "Answer an Array of the contexts on the receiver's sender chain." ^self stackOfSize: 100000! ! !ContextPart methodsFor: 'debugger access' stamp: 'ls 12/5/1999 13:43'! mclass "Answer the class in which the receiver's method was found." | mclass | self receiver class selectorAtMethod: self method setClass: [:mc | mclass _ mc ]. ^mclass! ! !ContextPart methodsFor: 'debugger access' stamp: 'ajh 9/7/2002 21:15'! methodSelector "Answer the selector of the method that created the receiver." ^self receiver class selectorAtMethod: self method setClass: [:ignored]! ! !ContextPart methodsFor: 'debugger access'! pc "Answer the index of the next bytecode to be executed." ^pc! ! !ContextPart methodsFor: 'debugger access'! release "Remove information from the receiver and all of the contexts on its sender chain in order to break circularities." self releaseTo: nil! ! !ContextPart methodsFor: 'debugger access'! releaseTo: caller "Remove information from the receiver and the contexts on its sender chain up to caller in order to break circularities." | c s | c _ self. [c == nil or: [c == caller]] whileFalse: [s _ c sender. c singleRelease. c _ s]! ! !ContextPart methodsFor: 'debugger access'! selector "Answer the selector of the method that created the receiver." ^self receiver class selectorAtMethod: self method setClass: [:ignored]! ! !ContextPart methodsFor: 'debugger access'! sender "Answer the context that sent the message that created the receiver." ^sender! ! !ContextPart methodsFor: 'debugger access' stamp: 'di 8/31/1999 09:42'! shortStack "Answer a String showing the top ten contexts on my sender chain." ^ String streamContents: [:strm | (self stackOfSize: 10) do: [:item | strm print: item; cr]]! ! !ContextPart methodsFor: 'debugger access' stamp: 'ajh 1/24/2003 00:03'! singleRelease "Remove information from the receiver in order to break circularities." stackp == nil ifFalse: [1 to: stackp do: [:i | self at: i put: nil]]. sender _ nil. pc _ nil. ! ! !ContextPart methodsFor: 'debugger access' stamp: 'ar 7/9/1999 19:01'! sourceCode | selector methodClass | selector _ self receiver class selectorAtMethod: self method setClass: [:mclass | methodClass _ mclass]. ^self method getSourceFor: selector in: methodClass "Note: The above is a bit safer than ^ methodClass sourceCodeAt: selector which may fail if the receiver's method has been changed in the debugger (e.g., the method is no longer in the methodDict and thus the above selector is something like #Doit:with:with:with:) but the source code is still available."! ! !ContextPart methodsFor: 'debugger access' stamp: 'tfei 3/20/2000 00:51'! stackOfSize: limit "Answer an OrderedCollection of the top 'limit' contexts on the receiver's sender chain." | a stack cachedStackTop newLimit | stack _ OrderedCollection new. stack addLast: (a _ self). [(a _ a sender) ~~ nil and: [stack size < limit]] whileTrue: [a hideFromDebugger ifFalse: [stack addLast: a]. a cachesStack ifTrue: [cachedStackTop := a cachedStackTop]]. ^cachedStackTop == nil ifTrue: [stack] ifFalse: [newLimit := limit - stack size. newLimit > 0 ifTrue: [stack addAllLast: (cachedStackTop stackOfSize: newLimit); yourself] ifFalse: [stack]]! ! !ContextPart methodsFor: 'debugger access'! swapSender: coroutine "Replace the receiver's sender with coroutine and answer the receiver's previous sender. For use in coroutining." | oldSender | oldSender _ sender. sender _ coroutine. ^oldSender! ! !ContextPart methodsFor: 'debugger access' stamp: 'ajh 2/9/2003 12:25'! tempNames "Answer an OrderedCollection of the names of the receiver's temporary variables, which are strings." ^ self methodNode tempNames! ! !ContextPart methodsFor: 'debugger access'! tempsAndValues "Return a string of the temporary variabls and their current values" | aStream | aStream _ WriteStream on: (String new: 100). self tempNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab. (self tempAt: index) printOn: aStream. aStream cr]. ^aStream contents! ! !ContextPart methodsFor: 'controlling'! activateMethod: newMethod withArgs: args receiver: rcvr class: class "Answer a ContextPart initialized with the arguments." ^MethodContext sender: self receiver: rcvr method: newMethod arguments: args! ! !ContextPart methodsFor: 'controlling' stamp: 'di 10/23/1999 17:03'! blockCopy: numArgs "Primitive. Distinguish a block of code from its enclosing method by creating a new BlockContext for that block. The compiler inserts into all methods that contain blocks the bytecodes to send the message blockCopy:. Do not use blockCopy: in code that you write!! Only the compiler can decide to send the message blockCopy:. Fail if numArgs is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 80> ^ (BlockContext newForMethod: self home method) home: self home startpc: pc + 2 nargs: numArgs! ! !ContextPart methodsFor: 'controlling'! hasSender: context "Answer whether the receiver is strictly above context on the stack." | s | self == context ifTrue: [^false]. s _ sender. [s == nil] whileFalse: [s == context ifTrue: [^true]. s _ s sender]. ^false! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 3/25/2004 00:07'! jump "Abandon thisContext and resume self instead (using the same current process). You may want to save thisContext's sender before calling this so you can jump back to it. Self MUST BE a top context (ie. a suspended context or a abandoned context that was jumped out of). A top context already has its return value on its stack (see Interpreter>>primitiveSuspend and other suspending primitives). thisContext's sender is converted to a top context (by pushing a nil return value on its stack) so it can be jump back to." | top | "Make abandoned context a top context (has return value (nil)) so it can be jumped back to" thisContext sender push: nil. "Pop self return value then return it to self (since we jump to self by returning to it)" stackp = 0 ifTrue: [self stepToSendOrReturn]. stackp = 0 ifTrue: [self push: nil]. "must be quick return self/constant" top _ self pop. thisContext privSender: self. ^ top! ! !ContextPart methodsFor: 'controlling' stamp: 'di 1/11/1999 22:40'! pop "Answer the top of the receiver's stack and remove the top of the stack." | val | val _ self at: stackp. self stackp: stackp - 1. ^ val! ! !ContextPart methodsFor: 'controlling' stamp: 'di 1/11/1999 22:39'! push: val "Push val on the receiver's stack." self stackp: stackp + 1. self at: stackp put: val! ! !ContextPart methodsFor: 'controlling' stamp: 'hmm 7/17/2001 20:57'! quickSend: selector to: receiver with: arguments super: superFlag "Send the given selector with arguments in an environment which closely resembles the non-simulating environment, with an interjected unwind-protected block to catch nonlocal returns. Attention: don't get lost!!" | oldSender contextToReturnTo result lookupClass | contextToReturnTo _ self. lookupClass _ superFlag ifTrue: [(self method literalAt: self method numLiterals) value superclass] ifFalse: [receiver class]. [oldSender _ thisContext sender swapSender: self. result _ receiver perform: selector withArguments: arguments inSuperclass: lookupClass. thisContext sender swapSender: oldSender] ifCurtailed: [ contextToReturnTo _ thisContext sender receiver. "The block context returning nonlocally" contextToReturnTo jump: -1. "skip to front of return bytecode causing this unwind" contextToReturnTo nextByte = 16r7C ifTrue: [ "If it was a returnTop, push the value to be returned. Otherwise the value is implicit in the bytecode" contextToReturnTo push: (thisContext sender tempAt: 1)]. thisContext swapSender: thisContext home sender. "Make this block return to the method's sender" contextToReturnTo]. contextToReturnTo push: result. ^contextToReturnTo! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 5/20/2004 17:32'! restart "Unwind thisContext to self and resume from beginning. Execute unwind blocks when unwinding. ASSUMES self is a sender of thisContext" | ctxt unwindBlock | self isDead ifTrue: [self cannotReturn: nil to: self]. self privRefresh. ctxt _ thisContext. [ ctxt _ ctxt findNextUnwindContextUpTo: self. ctxt isNil ] whileFalse: [ unwindBlock _ ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: self. self jump. ! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 6/27/2003 22:17'! resume "Roll back thisContext to self and resume. Execute unwind blocks when rolling back. ASSUMES self is a sender of thisContext" self resume: nil! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 5/20/2004 17:32'! resume: value "Unwind thisContext to self and resume with value as result of last send. Execute unwind blocks when unwinding. ASSUMES self is a sender of thisContext" | ctxt unwindBlock | self isDead ifTrue: [self cannotReturn: value to: self]. ctxt _ thisContext. [ ctxt _ ctxt findNextUnwindContextUpTo: self. ctxt isNil ] whileFalse: [ unwindBlock _ ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: self. ^ value ! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 1/21/2003 19:27'! return "Unwind until my sender is on top" self return: self receiver! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 5/20/2004 17:27'! return: value "Unwind thisContext to self and return value to self's sender. Execute any unwind blocks while unwinding. ASSUMES self is a sender of thisContext" sender ifNil: [self cannotReturn: value to: sender]. sender resume: value! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 5/20/2004 17:20'! runUntilErrorOrReturnFrom: aSender "ASSUMES aSender is a sender of self. Execute self's stack until aSender returns or an unhandled exception is raised. Return a pair containing the new top context and a possibly nil exception. The exception is not nil if it was raised before aSender returned and it was not handled. The exception is returned rather than openning the debugger, giving the caller the choice of how to handle it." "Self is run by jumping directly to it (the active process abandons thisContext and executes self). However, before jumping to self we insert an ensure block under aSender that jumps back to thisContext when evaluated. We also insert an exception handler under aSender that jumps back to thisContext when an unhandled exception is raised. In either case, the inserted ensure and exception handler are removed once control jumps back to thisContext." | error ctxt here topContext | here _ thisContext. "Insert ensure and exception handler contexts under aSender" error _ nil. ctxt _ aSender insertSender: (ContextPart contextOn: UnhandledError do: [:ex | error ifNil: [ error _ ex exception. topContext _ thisContext. ex resumeUnchecked: here jump] ifNotNil: [ex pass] ]). ctxt _ ctxt insertSender: (ContextPart contextEnsure: [error ifNil: [ topContext _ thisContext. here jump] ]). self jump. "Control jumps to self" "Control resumes here once above ensure block or exception handler is executed" ^ error ifNil: [ "No error was raised, remove ensure context by stepping until popped" [ctxt isDead] whileFalse: [topContext _ topContext stepToCallee]. {topContext. nil} ] ifNotNil: [ "Error was raised, remove inserted above contexts then return signaler context" aSender terminateTo: ctxt sender. "remove above ensure and handler contexts" {topContext. error} ]. ! ! !ContextPart methodsFor: 'controlling' stamp: 'di 11/26/1999 19:34'! send: selector to: rcvr with: args super: superFlag "Simulate the action of sending a message with selector, selector, and arguments, args, to receiver. The argument, superFlag, tells whether the receiver of the message was specified with 'super' in the source method." | class meth val | class _ superFlag ifTrue: [(self method literalAt: self method numLiterals) value superclass] ifFalse: [rcvr class]. meth _ class lookupSelector: selector. meth == nil ifTrue: [^ self send: #doesNotUnderstand: to: rcvr with: (Array with: (Message selector: selector arguments: args)) super: superFlag] ifFalse: [val _ self tryPrimitiveFor: meth receiver: rcvr args: args. val == PrimitiveFailToken ifFalse: [^ val]. (selector == #doesNotUnderstand: and: [class == ProtoObject]) ifTrue: [^ self error: 'Simulated message ' , (args at: 1) selector , ' not understood']. ^ self activateMethod: meth withArgs: args receiver: rcvr class: class]! ! !ContextPart methodsFor: 'controlling' stamp: 'ajh 1/24/2003 00:56'! terminate "Make myself unresumable." sender _ nil. pc _ nil. ! ! !ContextPart methodsFor: 'controlling' stamp: 'ar 3/6/2001 14:26'! terminateTo: previousContext "Terminate all the Contexts between me and previousContext, if previousContext is on my Context stack. Make previousContext my sender." | currentContext sendingContext | <primitive: 196> (self hasSender: previousContext) ifTrue: [ currentContext _ sender. [currentContext == previousContext] whileFalse: [ sendingContext _ currentContext sender. currentContext terminate. currentContext _ sendingContext]]. sender _ previousContext! ! !ContextPart methodsFor: 'controlling'! top "Answer the top of the receiver's stack." ^self at: stackp! ! !ContextPart methodsFor: 'printing' stamp: 'ajh 3/17/2003 09:25'! printOn: aStream | selector class mclass | self method == nil ifTrue: [^ super printOn: aStream]. selector _ (class _ self receiver class) selectorAtMethod: self method setClass: [:c | mclass _ c]. selector == #? ifTrue: [aStream nextPut: $?; print: self method who. ^self]. aStream nextPutAll: class name. mclass == class ifFalse: [aStream nextPut: $(. aStream nextPutAll: mclass name. aStream nextPut: $)]. aStream nextPutAll: '>>'. aStream nextPutAll: selector. selector = #doesNotUnderstand: ifTrue: [ aStream space. (self tempAt: 1) selector printOn: aStream. ]. ! ! !ContextPart methodsFor: 'system simulation'! step "Simulate the execution of the receiver's next bytecode. Answer the context that would be the active context after this bytecode." ^self interpretNextInstructionFor: self! ! !ContextPart methodsFor: 'system simulation' stamp: 'ajh 1/24/2003 22:54'! stepToCallee "Step to callee or sender" | ctxt | ctxt _ self. [(ctxt _ ctxt step) == self] whileTrue. ^ ctxt! ! !ContextPart methodsFor: 'system simulation' stamp: 'hmm 7/30/2001 20:48'! stepToSendOrReturn "Simulate the execution of bytecodes until either sending a message or returning a value to the receiver (that is, until switching contexts)." | ctxt | [self willReallySend | self willReturn | self willStore] whileFalse: [ ctxt _ self step. ctxt == self ifFalse: [self halt. "Caused by mustBeBoolean handling" ^ctxt]]! ! !ContextPart methodsFor: 'private' stamp: 'ajh 5/20/2004 16:27'! activateReturn: aContext value: value "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender" ^ self activateMethod: ContextPart theReturnMethod withArgs: {value} receiver: aContext class: aContext class! ! !ContextPart methodsFor: 'private' stamp: 'ajh 6/29/2003 15:32'! cannotReturn: result to: homeContext "The receiver tried to return result to homeContext that no longer exists." ^ BlockCannotReturn new result: result; deadHome: homeContext; signal! ! !ContextPart methodsFor: 'private' stamp: 'ajh 1/24/2003 00:50'! cut: aContext "Cut aContext and its senders from my sender chain" | ctxt callee | ctxt _ self. [ctxt == aContext] whileFalse: [ callee _ ctxt. ctxt _ ctxt sender. ctxt ifNil: [aContext ifNotNil: [self error: 'aContext not a sender']]. ]. callee privSender: nil. ! ! !ContextPart methodsFor: 'private' stamp: 'hg 10/2/2001 20:44'! doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and arguments are given as arguments to this message." | value | <primitive: 19> "Simulation guard" "If successful, push result and return resuming context, else ^ PrimitiveFailToken" (primitiveIndex = 19) ifTrue:[ Debugger openContext: self label:'Code simulation error' contents: nil]. (primitiveIndex = 80 and: [receiver isKindOf: ContextPart]) ifTrue: [^self push: ((BlockContext newForMethod: receiver home method) home: receiver home startpc: pc + 2 nargs: (arguments at: 1))]. (primitiveIndex = 81 and: [receiver isMemberOf: BlockContext]) ifTrue: [^receiver pushArgs: arguments from: self]. primitiveIndex = 83 "afr 9/11/1998 19:50" ifTrue: [^ self send: arguments first to: receiver with: arguments allButFirst super: false]. primitiveIndex = 84 "afr 9/11/1998 19:50" ifTrue: [^ self send: arguments first to: receiver with: (arguments at: 2) super: false]. arguments size > 6 ifTrue: [^ PrimitiveFailToken]. primitiveIndex = 117 ifTrue:[value _ self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] ifFalse:[value _ receiver tryPrimitive: primitiveIndex withArgs: arguments]. value == PrimitiveFailToken ifTrue: [^ PrimitiveFailToken] ifFalse: [^ self push: value]! ! !ContextPart methodsFor: 'private' stamp: 'ajh 7/21/2003 09:59'! insertSender: aContext "Insert aContext and its sender chain between me and my sender. Return new callee of my original sender." | ctxt | ctxt _ aContext bottomContext. ctxt privSender: self sender. self privSender: aContext. ^ ctxt! ! !ContextPart methodsFor: 'private' stamp: 'ajh 1/23/2003 22:35'! privSender: aContext sender _ aContext! ! !ContextPart methodsFor: 'private' stamp: 'di 1/11/1999 10:12'! push: numObjects fromIndexable: anIndexableCollection "Push the elements of anIndexableCollection onto the receiver's stack. Do not call directly. Called indirectly by {1. 2. 3} constructs." 1 to: numObjects do: [:i | self push: (anIndexableCollection at: i)]! ! !ContextPart methodsFor: 'private' stamp: 'di 10/23/1999 17:31'! stackp: newStackp "Storing into the stack pointer is a potentially dangerous thing. This primitive stores nil into any cells that become accessible as a result, and it performs the entire operation atomically." "Once this primitive is implemented, failure code should cause an error" <primitive: 76> self error: 'stackp store failure'. " stackp == nil ifTrue: [stackp _ 0]. newStackp > stackp 'effectively checks that it is a number' ifTrue: [oldStackp _ stackp. stackp _ newStackp. 'Nil any newly accessible cells' oldStackp + 1 to: stackp do: [:i | self at: i put: nil]] ifFalse: [stackp _ newStackp] "! ! !ContextPart methodsFor: 'private' stamp: 'ar 5/25/2000 20:41'! tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments "Hack. Attempt to execute the named primitive from the given compiled method" | selector theMethod spec | arguments size > 8 ifTrue:[^PrimitiveFailToken]. selector _ #( tryNamedPrimitive tryNamedPrimitive: tryNamedPrimitive:with: tryNamedPrimitive:with:with: tryNamedPrimitive:with:with:with: tryNamedPrimitive:with:with:with:with: tryNamedPrimitive:with:with:with:with:with: tryNamedPrimitive:with:with:with:with:with:with: tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. theMethod _ aReceiver class lookupSelector: selector. theMethod == nil ifTrue:[^PrimitiveFailToken]. spec _ theMethod literalAt: 1. spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1. ^aReceiver perform: selector withArguments: arguments! ! !ContextPart methodsFor: 'private' stamp: 'ar 5/25/2000 20:45'! tryPrimitiveFor: method receiver: receiver args: arguments "If this method has a primitive index, then run the primitive and return its result. Otherwise (and also if the primitive fails) return PrimitiveFailToken, as an indication that the method should be activated and run as bytecodes." | primIndex | (primIndex _ method primitive) = 0 ifTrue: [^ PrimitiveFailToken]. ^ self doPrimitive: primIndex method: method receiver: receiver args: arguments! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'TPR 8/28/2000 19:27'! findNextHandlerContextStarting "Return the next handler marked context, returning nil if there is none. Search starts with self and proceeds up to nil." | ctx | <primitive: 197> ctx _ self. [ctx isHandlerContext ifTrue:[^ctx]. (ctx _ ctx sender) == nil ] whileFalse. ^nil! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'TPR 8/23/2000 16:37'! findNextUnwindContextUpTo: aContext "Return the next unwind marked above the receiver, returning nil if there is none. Search proceeds up to but not including aContext." | ctx | <primitive: 195> ctx _ self. [(ctx _ ctx sender) == nil or: [ctx == aContext]] whileFalse: [ ctx isUnwindContext ifTrue: [^ctx]]. ^nil! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'ajh 6/27/2003 20:47'! handleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception then execute my handle block (second arg), otherwise forward this message to the next handler context. If none left, execute exception's defaultAction (see nil>>handleSignal:)." | val | (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) ifFalse: [ ^ self nextHandlerContext handleSignal: exception]. exception privHandlerContext: self contextTag. self tempAt: 3 put: false. "disable self while executing handle block" val _ [(self tempAt: 2) valueWithPossibleArgs: {exception}] ensure: [self tempAt: 3 put: true]. self return: val. "return from self if not otherwise directed in handle block" ! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'tpr 2/24/2001 21:29'! isHandlerContext ^false! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'TPR 8/28/2000 15:45'! isUnwindContext ^false! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'ajh 2/1/2003 00:20'! nextHandlerContext ^ self sender findNextHandlerContextStarting! ! !ContextPart methodsFor: 'private-debugger' stamp: 'tfei 3/19/2000 23:24'! cachesStack ^false! ! !ContextPart methodsFor: 'query' stamp: 'ajh 1/24/2003 12:35'! blockHome ^ self! ! !ContextPart methodsFor: 'query' stamp: 'ajh 7/21/2003 09:59'! bottomContext "Return the last context (the first context invoked) in my sender chain" ^ self findContextSuchThat: [:c | c sender isNil]! ! !ContextPart methodsFor: 'query' stamp: 'ajh 1/24/2003 00:12'! findContextSuchThat: testBlock "Search self and my sender chain for first one that satisfies testBlock. Return nil if none satisfy" | ctxt | ctxt _ self. [ctxt isNil] whileFalse: [ (testBlock value: ctxt) ifTrue: [^ ctxt]. ctxt _ ctxt sender. ]. ^ nil! ! !ContextPart methodsFor: 'query' stamp: 'ajh 1/24/2003 19:42'! hasContext: aContext "Answer whether aContext is me or one of my senders" ^ (self findContextSuchThat: [:c | c == aContext]) notNil! ! !ContextPart methodsFor: 'query' stamp: 'ajh 1/24/2003 00:04'! isDead "Has self finished" ^ pc isNil! ! !ContextPart methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:42'! errorReportOn: foo! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ContextPart class instanceVariableNames: ''! !ContextPart class methodsFor: 'simulation' stamp: 'di 2/10/1999 22:15'! initialize "A unique object to be returned when a primitive fails during simulation" PrimitiveFailToken _ Object new ! ! !ContextPart class methodsFor: 'simulation' stamp: 'di 2/10/1999 22:15'! primitiveFailToken ^ PrimitiveFailToken! ! !ContextPart class methodsFor: 'instance creation' stamp: 'di 10/23/1999 17:09'! basicNew: size self error: 'Contexts must only be created with newForMethod:'! ! !ContextPart class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 00:30'! initializedInstance ^ nil! ! !ContextPart class methodsFor: 'instance creation' stamp: 'di 10/23/1999 17:09'! new self error: 'Contexts must only be created with newForMethod:'! ! !ContextPart class methodsFor: 'instance creation' stamp: 'di 10/23/1999 17:09'! new: size self error: 'Contexts must only be created with newForMethod:'! ! !ContextPart class methodsFor: 'instance creation' stamp: 'di 10/23/1999 17:55'! newForMethod: aMethod "This is the only method for creating new contexts, other than primitive cloning. Any other attempts, such as inherited methods like shallowCopy, should be avoided or must at least be rewritten to determine the proper size from the method being activated. This is because asking a context its size (even basicSize!!) will not return the real object size but only the number of fields currently accessible, as determined by stackp." ^ super basicNew: aMethod frameSize! ! !ContextPart class methodsFor: 'special context creation' stamp: 'ajh 1/24/2003 14:31'! contextEnsure: block "Create an #ensure: context that is ready to return from executing its receiver" | ctxt chain | ctxt _ thisContext. [chain _ thisContext sender cut: ctxt. ctxt jump] ensure: block. "jump above will resume here without unwinding chain" ^ chain! ! !ContextPart class methodsFor: 'special context creation' stamp: 'ajh 1/24/2003 14:31'! contextOn: exceptionClass do: block "Create an #on:do: context that is ready to return from executing its receiver" | ctxt chain | ctxt _ thisContext. [chain _ thisContext sender cut: ctxt. ctxt jump] on: exceptionClass do: block. "jump above will resume here without unwinding chain" ^ chain! ! !ContextPart class methodsFor: 'special context creation' stamp: 'ajh 5/20/2004 16:25'! theReturnMethod | meth | meth _ self lookupSelector: #return:. meth primitive = 0 ifFalse: [^ self error: 'expected #return: to not be a primitive']. ^ meth! ! Inspector subclass: #ContextVariablesInspector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Debugger'! !ContextVariablesInspector commentStamp: '<historical>' prior: 0! 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.! !ContextVariablesInspector methodsFor: 'accessing'! fieldList "Refer to the comment in Inspector|fieldList." object == nil ifTrue: [^Array with: 'thisContext']. ^(Array with: 'thisContext' with: 'all temp vars') , object tempNames! ! !ContextVariablesInspector methodsFor: 'accessing' stamp: 'ajh 1/31/2003 15:45'! inspect: anObject "Initialize the receiver so that it is inspecting anObject. There is no current selection." self initialize. object _ anObject. selectionIndex _ 0. contents _ ''! ! !ContextVariablesInspector methodsFor: 'selecting'! replaceSelectionValue: anObject "Refer to the comment in Inspector|replaceSelectionValue:." selectionIndex = 1 ifTrue: [^object] ifFalse: [^object tempAt: selectionIndex - 2 put: anObject]! ! !ContextVariablesInspector methodsFor: 'selecting' stamp: 'ar 5/29/1998 18:32'! selection "Refer to the comment in Inspector|selection." selectionIndex = 0 ifTrue:[^'']. selectionIndex = 1 ifTrue: [^object]. selectionIndex = 2 ifTrue: [^object tempsAndValues] ifFalse: [^object tempAt: selectionIndex - 2]! ! !ContextVariablesInspector methodsFor: 'code'! doItContext ^object! ! !ContextVariablesInspector methodsFor: 'code'! doItReceiver ^object receiver! ! Object subclass: #ControlManager instanceVariableNames: 'scheduledControllers activeController activeControllerProcess screenController newTopClicked' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !ControlManager commentStamp: '<historical>' prior: 0! 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.! !ControlManager methodsFor: 'initialize-release'! initialize "Initialize the receiver to refer to only the background controller." | screenView | screenController _ ScreenController new. screenView _ FormView new. screenView model: (InfiniteForm with: Color gray) controller: screenController. screenView window: Display boundingBox. scheduledControllers _ OrderedCollection with: screenController! ! !ControlManager methodsFor: 'initialize-release'! release "Refer to the comment in Object|release." scheduledControllers == nil ifFalse: [scheduledControllers do: [:controller | (controller isKindOf: Controller) ifTrue: [controller view release] ifFalse: [controller release]]. scheduledControllers _ nil]! ! !ControlManager methodsFor: 'accessing'! activeController "Answer the currently active controller." ^activeController! ! !ControlManager methodsFor: 'accessing' stamp: 'ar 6/5/1998 21:49'! activeController: aController "Set aController to be the currently active controller. Give the user control in it." <primitive: 19> "Simulation guard" activeController _ aController. (activeController == screenController) ifFalse: [self promote: activeController]. activeControllerProcess _ [activeController startUp. self searchForActiveController] newProcess. activeControllerProcess priority: Processor userSchedulingPriority. activeControllerProcess resume! ! !ControlManager methodsFor: 'accessing'! activeControllerNoTerminate: aController andProcess: aProcess "Set aController to be the currently active controller and aProcess to be the the process that handles controller scheduling activities in the system. This message differs from activeController:andProcess: in that it does not send controlTerminate to the currently active controller." self inActiveControllerProcess ifTrue: [aController~~nil ifTrue: [(scheduledControllers includes: aController) ifTrue: [self promote: aController] ifFalse: [self error: 'Old controller not scheduled']]. activeController _ aController. activeController == nil ifFalse: [activeController controlInitialize]. activeControllerProcess _ aProcess. activeControllerProcess resume] ifFalse: [self error: 'New active controller process must be set from old one'] ! ! !ControlManager methodsFor: 'accessing'! activeControllerProcess "Answer the process that is currently handling controller scheduling activities in the system." ^activeControllerProcess! ! !ControlManager methodsFor: 'accessing'! controllerSatisfying: aBlock "Return the first scheduled controller which satisfies the 1-argument boolean-valued block, or nil if none. 7/25/96 sw" scheduledControllers do: [:aController | (aBlock value: aController) == true ifTrue: [^ aController]]. ^ nil! ! !ControlManager methodsFor: 'accessing'! controllerWhoseModelSatisfies: aBlock "Return the first scheduled controller whose model satisfies the 1-argument boolean-valued block, or nil if none. 5/6/96 sw" scheduledControllers do: [:aController | (aBlock value: aController model) == true ifTrue: [^ aController]]. ^ nil! ! !ControlManager methodsFor: 'accessing' stamp: 'sw 5/4/2001 23:20'! controllersSatisfying: aBlock "Return a list of scheduled controllers satisfying aBlock" ^ (scheduledControllers ifNil: [^ #()]) select: [:aController | (aBlock value: aController) == true]! ! !ControlManager methodsFor: 'accessing'! includes: aController ^ scheduledControllers includes: aController! ! !ControlManager methodsFor: 'accessing'! noteNewTop newTopClicked _ true! ! !ControlManager methodsFor: 'accessing'! scheduledControllers "Answer a copy of the ordered collection of scheduled controllers." ^scheduledControllers copy! ! !ControlManager methodsFor: 'accessing' stamp: 'di 10/4/97 09:05'! scheduledWindowControllers "Same as scheduled controllers, but without ScreenController. Avoids null views just after closing, eg, a debugger." ^ scheduledControllers select: [:c | c ~~ screenController and: [c view ~~ nil]]! ! !ControlManager methodsFor: 'accessing'! screenController ^ screenController! ! !ControlManager methodsFor: 'accessing'! windowOriginsInUse "Answer a collection of the origins of windows currently on the screen in the current project. 5/21/96 sw" ^ self scheduledWindowControllers collect: [:aController | aController view displayBox origin].! ! !ControlManager methodsFor: 'scheduling'! activateController: aController "Make aController, which must already be a scheduled controller, the active window. 5/8/96 sw" self activeController: aController. (activeController view labelDisplayBox intersect: Display boundingBox) area < 200 ifTrue: [activeController move]. Processor terminateActive! ! !ControlManager methodsFor: 'scheduling'! activateTranscript "There is known to be a Transcript open in the current project; activate it. 2/5/96 sw" | itsController | itsController _ scheduledControllers detect: [:controller | controller model == Transcript] ifNone: [^ self]. self activeController: itsController. (activeController view labelDisplayBox intersect: Display boundingBox) area < 200 ifTrue: [activeController move]. Processor terminateActive! ! !ControlManager methodsFor: 'scheduling' stamp: 'di 5/19/1998 09:03'! findWindow "Present a menu of window titles, and activate the one that gets chosen." ^ self findWindowSatisfying: [:c | true]! ! !ControlManager methodsFor: 'scheduling' stamp: 'wod 6/17/1998 15:46'! findWindowSatisfying: aBlock "Present a menu of window titles, and activate the one that gets chosen" | sortAlphabetically controllers listToUse labels index | sortAlphabetically _ Sensor shiftPressed. controllers _ OrderedCollection new. scheduledControllers do: [:controller | controller == screenController ifFalse: [(aBlock value: controller) ifTrue: [controllers addLast: controller]]]. controllers size == 0 ifTrue: [^ self]. listToUse _ sortAlphabetically ifTrue: [controllers asSortedCollection: [:a :b | a view label < b view label]] ifFalse: [controllers]. labels _ String streamContents: [:strm | listToUse do: [:controller | strm nextPutAll: (controller view label contractTo: 40); cr]. strm skip: -1 "drop last cr"]. index _ (PopUpMenu labels: labels) startUp. index > 0 ifTrue: [self activateController: (listToUse at: index)]. ! ! !ControlManager methodsFor: 'scheduling'! inActiveControllerProcess "Answer whether the active scheduling process is the actual active process in the system." ^activeControllerProcess == Processor activeProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'ar 11/19/1998 18:31'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | suspendingList newActiveController | (suspendingList _ activeControllerProcess suspendingList) == nil ifTrue: [activeControllerProcess == Processor activeProcess ifTrue: [activeControllerProcess suspend]] ifFalse: [suspendingList remove: activeControllerProcess ifAbsent:[]. activeControllerProcess offList]. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController _ (Debugger openInterrupt: labelString onProcess: activeControllerProcess) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !ControlManager methodsFor: 'scheduling'! promote: aController "Make aController be the first scheduled controller in the ordered collection." scheduledControllers remove: aController. scheduledControllers addFirst: aController! ! !ControlManager methodsFor: 'scheduling' stamp: 'RAA 7/7/2000 09:22'! resetActiveController "When saving a morphic project whose parent is mvc, we need to set this up first" activeController _ nil. activeControllerProcess _ Processor activeProcess. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ar 6/5/1998 21:48'! scheduleActive: aController "Make aController be scheduled as the active controller. Presumably the active scheduling process asked to schedule this controller and that a new process associated this controller takes control. So this is the last act of the active scheduling process." <primitive: 19> "Simulation guard" self scheduleActiveNoTerminate: aController. Processor terminateActive! ! !ControlManager methodsFor: 'scheduling'! scheduleActiveNoTerminate: aController "Make aController be the active controller. Presumably the process that requested the new active controller wants to keep control to do more activites before the new controller can take control. Therefore, do not terminate the currently active process." self schedulePassive: aController. self scheduled: aController from: Processor activeProcess! ! !ControlManager methodsFor: 'scheduling'! scheduleOnBottom: aController "Make aController be scheduled as a scheduled controller, but not the active one. Put it at the end of the ordered collection of controllers." scheduledControllers addLast: aController! ! !ControlManager methodsFor: 'scheduling'! schedulePassive: aController "Make aController be scheduled as a scheduled controller, but not the active one. Put it at the beginning of the ordered collection of controllers." scheduledControllers addFirst: aController! ! !ControlManager methodsFor: 'scheduling'! searchForActiveController "Find a scheduled controller that wants control and give control to it. If none wants control, then see if the System Menu has been requested." | aController | activeController _ nil. activeControllerProcess _ Processor activeProcess. self activeController: self nextActiveController. Processor terminateActive! ! !ControlManager methodsFor: 'scheduling' stamp: 'ajh 12/31/2001 15:15'! spawnNewProcess self activeController: self screenController! ! !ControlManager methodsFor: 'scheduling'! unschedule: aController "Remove the view, aController, from the collection of scheduled controllers." scheduledControllers remove: aController ifAbsent: []! ! !ControlManager methodsFor: 'scheduling'! windowFromUser "Present a menu of window titles, and returns the StandardSystemController belonging to the one that gets chosen, or nil if none" | controllers labels index | controllers _ OrderedCollection new. labels _ String streamContents: [:strm | scheduledControllers do: [:controller | controller == screenController ifFalse: [controllers addLast: controller. strm nextPutAll: (controller view label contractTo: 40); cr]]. strm skip: -1 "drop last cr"]. index _ (PopUpMenu labels: labels) startUp. ^ index > 0 ifTrue: [controllers at: index] ifFalse: [nil]! ! !ControlManager methodsFor: 'displaying'! backgroundForm: aForm screenController view model: aForm. ScheduledControllers restore " QDPen new mandala: 30 diameter: 640. ScheduledControllers backgroundForm: (Form fromDisplay: Display boundingBox). ScheduledControllers backgroundForm: (InfiniteForm with: Form gray). "! ! !ControlManager methodsFor: 'displaying' stamp: 'di 2/26/98 08:58'! restore "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." scheduledControllers first view uncacheBits. "assure refresh" self unschedule: screenController; scheduleOnBottom: screenController. screenController view window: Display boundingBox; displayDeEmphasized. self scheduledWindowControllers reverseDo: [:aController | aController view displayDeEmphasized]. ! ! !ControlManager methodsFor: 'displaying' stamp: 'hmm 1/5/2000 07:00'! restore: aRectangle "Restore all windows visible in aRectangle" ^ self restore: aRectangle without: nil! ! !ControlManager methodsFor: 'displaying' stamp: 'ssa 8/26/2008 08:55'! restore: aRectangle below: index without: aView "Restore all windows visible in aRectangle, but without aView" | view | view := (scheduledControllers at: index) view. view == aView ifTrue: [index >= scheduledControllers size ifTrue: [^ self]. ^ self restore: aRectangle below: index+1 without: aView]. view isNil ifTrue:[^self]. view displayOn: ((BitBlt current toForm: Display) clipRect: aRectangle). index >= scheduledControllers size ifTrue: [^ self]. (aRectangle areasOutside: view windowBox) do: [:rect | self restore: rect below: index + 1 without: aView]! ! !ControlManager methodsFor: 'displaying' stamp: 'hmm 12/30/1999 19:35'! restore: aRectangle without: aView "Restore all windows visible in aRectangle" Display deferUpdates: true. self restore: aRectangle below: 1 without: aView. Display deferUpdates: false; forceToScreen: aRectangle! ! !ControlManager methodsFor: 'displaying'! updateGray "From Georg Gollmann - 11/96. tell the Screen Controller's model to use the currently-preferred desktop color." "ScheduledControllers updateGray" (screenController view model isMemberOf: InfiniteForm) ifTrue: [screenController view model: (InfiniteForm with: Preferences desktopColor)]! ! !ControlManager methodsFor: 'private'! nextActiveController "Answer the controller that would like control. If there was a click outside the active window, it's the top window that now has the mouse, otherwise it's just the top window." (newTopClicked notNil and: [newTopClicked]) ifTrue: [newTopClicked _ false. ^ scheduledControllers detect: [:aController | aController isControlWanted] ifNone: [scheduledControllers first]] ifFalse: [^ scheduledControllers first]! ! !ControlManager methodsFor: 'private'! scheduled: aController from: aProcess activeControllerProcess==aProcess ifTrue: [activeController ~~ nil ifTrue: [activeController controlTerminate]. aController centerCursorInView. self activeController: aController]! ! !ControlManager methodsFor: 'private' stamp: 'sw 12/6/1999 23:40'! unCacheWindows scheduledControllers ifNotNil: [scheduledControllers do: [:aController | aController view uncacheBits]]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ControlManager class instanceVariableNames: ''! !ControlManager class methodsFor: 'exchange'! newScheduler: controlManager "When switching projects, the control scheduler has to be exchanged. The active one is the one associated with the current project." Smalltalk at: #ScheduledControllers put: controlManager. ScheduledControllers restore. controlManager searchForActiveController! ! !ControlManager class methodsFor: 'snapshots' stamp: 'di 2/4/1999 15:16'! shutDown "Saves space in snapshots" Smalltalk isMorphic ifFalse: [ScheduledControllers unCacheWindows]! ! !ControlManager class methodsFor: 'snapshots' stamp: 'di 2/4/1999 09:00'! startUp Smalltalk isMorphic ifFalse: [ScheduledControllers restore]! ! Object subclass: #Controller instanceVariableNames: 'model view sensor lastActivityTime' classVariableNames: 'MinActivityLapse' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !Controller commentStamp: '<historical>' prior: 0! 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.! !Controller methodsFor: 'initialize-release'! initialize "Initialize the state of the receiver. Subclasses should include 'super initialize' when redefining this message to insure proper initialization." sensor _ InputSensor default! ! !Controller methodsFor: 'initialize-release'! release "Breaks the cycle between the receiver and its view. It is usually not necessary to send release provided the receiver's view has been properly released independently." model _ nil. view ~~ nil ifTrue: [view controller: nil. view _ nil]! ! !Controller methodsFor: 'model access'! model "Answer the receiver's model which is the same as the model of the receiver's view." ^model! ! !Controller methodsFor: 'model access'! model: aModel "Controller|model: and Controller|view: are sent by View|controller: in order to coordinate the links between the model, view, and controller. In ordinary usage, the receiver is created and passed as the parameter to View|controller: so that the receiver's model and view links can be set up by the view." model _ aModel! ! !Controller methodsFor: 'view access'! inspectView view notNil ifTrue: [^ view inspect]! ! !Controller methodsFor: 'view access'! view "Answer the receiver's view." ^view! ! !Controller methodsFor: 'view access'! view: aView "Controller|view: and Controller|model: are sent by View|controller: in order to coordinate the links between the model, view, and controller. In ordinary usage, the receiver is created and passed as the parameter to View|controller: and the receiver's model and view links are set up automatically by the view." view _ aView! ! !Controller methodsFor: 'sensor access'! sensor "Answer the receiver's sensor. Subclasses may use other objects that are not instances of Sensor or its subclasses if more general kinds of input/output functions are required." ^sensor! ! !Controller methodsFor: 'sensor access'! sensor: aSensor "Set the receiver's sensor to aSensor." sensor _ aSensor! ! !Controller methodsFor: 'basic control sequence'! controlInitialize "Sent by Controller|startUp as part of the standard control sequence, it provides a place in the standard control sequence for initializing the receiver (taking into account the current state of its model and view). It should be redefined in subclasses to perform some specific action." ^self! ! !Controller methodsFor: 'basic control sequence' stamp: 'ls 7/11/1998 06:33'! controlLoop "Sent by Controller|startUp as part of the standard control sequence. Controller|controlLoop sends the message Controller|isControlActive to test for loop termination. As long as true is returned, the loop continues. When false is returned, the loop ends. Each time through the loop, the message Controller|controlActivity is sent." [self isControlActive] whileTrue: [ self interActivityPause. self controlActivity. Processor yield]! ! !Controller methodsFor: 'basic control sequence'! controlTerminate "Provide a place in the standard control sequence for terminating the receiver (taking into account the current state of its model and view). It should be redefined in subclasses to perform some specific action." ^self! ! !Controller methodsFor: 'basic control sequence' stamp: 'RAA 1/30/2001 19:06'! interActivityPause "if we are looping quickly, insert a short delay. Thus if we are just doing UI stuff, we won't take up much CPU" | currentTime wait | MinActivityLapse ifNotNil: [ lastActivityTime ifNotNil: [ currentTime _ Time millisecondClockValue. wait _ lastActivityTime + MinActivityLapse - currentTime. wait > 0 ifTrue: [ wait <= MinActivityLapse "big waits happen after a snapshot" ifTrue: [DisplayScreen checkForNewScreenSize. (Delay forMilliseconds: wait) wait ]. ]. ]. ]. lastActivityTime _ Time millisecondClockValue.! ! !Controller methodsFor: 'basic control sequence'! startUp "Give control to the receiver. The default control sequence is to initialize (see Controller|controlInitialize), to loop (see Controller|controlLoop), and then to terminate (see Controller|controlTerminate). After this sequence, control is returned to the sender of Control|startUp. The receiver's control sequence is used to coordinate the interaction of its view and model. In general, this consists of polling the sensor for user input, testing the input with respect to the current display of the view, and updating the model to reflect intended changes." self controlInitialize. self controlLoop. self controlTerminate! ! !Controller methodsFor: 'basic control sequence'! terminateAndInitializeAround: aBlock "1/12/96 sw" self controlTerminate. aBlock value. self controlInitialize! ! !Controller methodsFor: 'control defaults'! controlActivity "Pass control to the next control level (that is, to the Controller of a subView of the receiver's view) if possible. It is sent by Controller|controlLoop each time through the main control loop. It should be redefined in a subclass if some other action is needed." self controlToNextLevel! ! !Controller methodsFor: 'control defaults'! controlToNextLevel "Pass control to the next control level (that is, to the Controller of a subView of the receiver's view) if possible. The receiver finds the subView (if any) of its view whose inset display box (see View|insetDisplayBox) contains the sensor's cursor point. The Controller of this subView is then given control if it answers true in response to the message Controller|isControlWanted." | aView | aView _ view subViewWantingControl. aView ~~ nil ifTrue: [aView controller startUp]! ! !Controller methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:23'! isControlActive "Answer whether receiver wishes to continue evaluating its controlLoop method. It is sent by Controller|controlLoop in order to determine when the receiver's control loop should terminate, and should be redefined in a subclass if some special condition for terminating the main control loop is needed." ^ self viewHasCursor and: [sensor blueButtonPressed not and: [sensor yellowButtonPressed not]]! ! !Controller methodsFor: 'control defaults'! isControlWanted "Answer whether the cursor is inside the inset display box (see View|insetDisplayBox) of the receiver's view. It is sent by Controller|controlNextLevel in order to determine whether or not control should be passed to this receiver from the Controller of the superView of this receiver's view." ^self viewHasCursor! ! !Controller methodsFor: 'cursor'! centerCursorInView "Position sensor's mousePoint (which is assumed to be connected to the cursor) to the center of its view's inset display box (see Sensor|mousePoint: and View|insetDisplayBox)." ^sensor cursorPoint: view insetDisplayBox center! ! !Controller methodsFor: 'cursor' stamp: 'sw 7/13/1999 18:42'! viewHasCursor "Answer whether the cursor point of the receiver's sensor lies within the inset display box of the receiver's view (see View|insetDisplayBox). Controller|viewHasCursor is normally used in internal methods." ^ view ifNotNil: [view containsPoint: sensor cursorPoint] ifNil: [false]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Controller class instanceVariableNames: ''! !Controller class methodsFor: 'initialization' stamp: 'ls 7/13/1998 00:47'! MinActivityLapse: milliseconds "minimum time to delay between calls to controlActivity" MinActivityLapse _ milliseconds ifNotNil: [ milliseconds rounded ].! ! !Controller class methodsFor: 'initialization' stamp: 'ssa 8/15/2008 09:40'! initialize "Controller initialize" self MinActivityLapse: 50.! ! StandardFileStream subclass: #CrLfFileStream instanceVariableNames: 'lineEndConvention' classVariableNames: 'Cr CrLf Lf LineEndDefault LineEndStrings LookAheadCount' poolDictionaries: '' category: 'System-Files'! !CrLfFileStream commentStamp: 'ls 11/10/2002 13:32' prior: 0! I am the same as a regular file stream, except that when I am in text mode, I will automatically convert line endings between the underlying platform's convention, and Squeak's convention of carriage-return only. The goal is that Squeak text files can be treated as OS text files, and vice versa. In binary mode, I behave identically to a StandardFileStream. To enable CrLfFileStream as the default file stream class for an entire image, modify FileStream class concreteStream . There are two caveats on programming with CrLfFileStream. First, the choice of text mode versus binary mode affects which characters are visible in Squeak, and no longer just affects whether those characters are returned as Character's or as Integer's. Thus the choice of mode needs to be made very carefully, and must be based on intent instead of convenience of representation. The methods asString, asByteArray, asCharacter, and asInteger can be used to convert between character and integer representations. (Arguably, file streams should accept either strings or characters in nextPut: and nextPutAll:, but that is not the case right now.) Second, arithmetic on positions no longer works, because one character that Squeak sees (carriage return) could map to two characters in the underlying file (carriage return plus line feed, on MS Windows and MS DOS). Comparison between positions still works. (This caveat could perhaps be fixed by maintaining a map between Squeak positions and positions in the underlying file, but it is complicated. Consider, for example, updates to the middle of the file. Also, consider that text files are rarely updated in the middle of the file, and that general random access to a text file is rarely very useful. If general random access with specific file counts is desired, then the file is starting to sound like a binary file instead of a text file.) ! ]style[(448 31 1371 6 32)f1,f1LFileStream class concreteStream;,f1,f1i,f1! !CrLfFileStream methodsFor: 'open/close' stamp: 'ar 1/20/98 16:15'! open: aFileName forWrite: writeMode "Open the receiver. If writeMode is true, allow write, else access will be read-only. " | result | result _ super open: aFileName forWrite: writeMode. result ifNotNil: [self detectLineEndConvention]. ^ result! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:16'! ascii super ascii. self detectLineEndConvention! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:16'! binary super binary. lineEndConvention _ nil! ! !CrLfFileStream methodsFor: 'access' stamp: 'ls 7/10/1998 23:35'! detectLineEndConvention "Detect the line end convention used in this stream. The result may be either #cr, #lf or #crlf." | char numRead pos | self isBinary ifTrue: [^ self error: 'Line end conventions are not used on binary streams']. lineEndConvention _ LineEndDefault. "Default if nothing else found" numRead _ 0. pos _ super position. [super atEnd not and: [numRead < LookAheadCount]] whileTrue: [char _ super next. char = Lf ifTrue: [super position: pos. ^ lineEndConvention _ #lf]. char = Cr ifTrue: [super peek = Lf ifTrue: [lineEndConvention _ #crlf] ifFalse: [lineEndConvention _ #cr]. super position: pos. ^ lineEndConvention]. numRead _ numRead + 1]. super position: pos. ^ lineEndConvention! ! !CrLfFileStream methodsFor: 'access' stamp: 'ls 11/5/1998 23:37'! next | char secondChar | char _ super next. self isBinary ifTrue: [^char]. char == Cr ifTrue: [secondChar _ super next. secondChar ifNotNil: [secondChar == Lf ifFalse: [self skip: -1]]. ^Cr]. char == Lf ifTrue: [^Cr]. ^char! ! !CrLfFileStream methodsFor: 'access' stamp: 'ls 12/29/1998 17:15'! next: n | string peekChar | string _ super next: n. string size = 0 ifTrue: [ ^string ]. self isBinary ifTrue: [ ^string ]. "if we just read a CR, and the next character is an LF, then skip the LF" ( string last = Character cr ) ifTrue: [ peekChar _ super next. "super peek doesn't work because it relies on #next" peekChar ~= Character lf ifTrue: [ super position: (super position - 1) ]. ]. string _ string withSqueakLineEndings. string size = n ifTrue: [ ^string ]. "string shrunk due to embedded crlfs; make up the difference" ^string, (self next: n - string size)! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:18'! nextPut: char (lineEndConvention notNil and: [char = Cr]) ifTrue: [super nextPutAll: (LineEndStrings at: lineEndConvention)] ifFalse: [super nextPut: char]. ^ char! ! !CrLfFileStream methodsFor: 'access' stamp: 'ar 1/20/98 16:18'! nextPutAll: aString super nextPutAll: (self convertStringFromCr: aString). ^ aString ! ! !CrLfFileStream methodsFor: 'access' stamp: 'wod 6/18/1998 13:52'! peek "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. " | next pos | self atEnd ifTrue: [^ nil]. pos _ self position. next _ self next. self position: pos. ^ next! ! !CrLfFileStream methodsFor: 'access' stamp: 'wod 11/5/1998 14:15'! upTo: aCharacter | newStream char | newStream _ WriteStream on: (String new: 100). [(char _ self next) isNil or: [char == aCharacter]] whileFalse: [newStream nextPut: char]. ^ newStream contents ! ! !CrLfFileStream methodsFor: 'private' stamp: 'ar 1/20/98 16:21'! convertStringFromCr: aString | inStream outStream | lineEndConvention ifNil: [^ aString]. lineEndConvention == #cr ifTrue: [^ aString]. lineEndConvention == #lf ifTrue: [^ aString copy replaceAll: Cr with: Lf]. "lineEndConvention == #crlf" inStream _ ReadStream on: aString. outStream _ WriteStream on: (String new: aString size). [inStream atEnd] whileFalse: [outStream nextPutAll: (inStream upTo: Cr). (inStream atEnd not or: [aString last = Cr]) ifTrue: [outStream nextPutAll: CrLf]]. ^ outStream contents! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CrLfFileStream class instanceVariableNames: ''! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToCR "CrLfFileStream defaultToCR" LineEndDefault := #cr.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToCRLF "CrLfFileStream defaultToCRLF" LineEndDefault := #crlf.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:10'! defaultToLF "CrLfFileStream defaultToLF" LineEndDefault := #lf.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'ar 1/20/98 16:13'! guessDefaultLineEndConvention "Lets try to guess the line end convention from what we know about the path name delimiter from FileDirectory." FileDirectory pathNameDelimiter = $: ifTrue:[^self defaultToCR]. FileDirectory pathNameDelimiter = $/ ifTrue:[^self defaultToLF]. FileDirectory pathNameDelimiter = $\ ifTrue:[^self defaultToCRLF]. "in case we don't know" ^self defaultToCR! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'di 2/4/1999 09:16'! initialize "CrLfFileStream initialize" Cr := Character cr. Lf := Character lf. CrLf := String with: Cr with: Lf. LineEndStrings := Dictionary new. LineEndStrings at: #cr put: (String with: Character cr). LineEndStrings at: #lf put: (String with: Character lf). LineEndStrings at: #crlf put: (String with: Character cr with: Character lf). LookAheadCount := 2048. Smalltalk addToStartUpList: self. self startUp.! ! !CrLfFileStream class methodsFor: 'class initialization' stamp: 'djp 1/28/1999 22:08'! startUp self guessDefaultLineEndConvention! ! Form subclass: #Cursor instanceVariableNames: '' classVariableNames: 'BlankCursor BottomLeftCursor BottomRightCursor CornerCursor CrossHairCursor CurrentCursor DownCursor MarkerCursor MenuCursor MoveCursor NormalCursor OriginCursor ReadCursor ResizeLeftCursor ResizeTopCursor ResizeTopLeftCursor ResizeTopRightCursor RightArrowCursor SquareCursor TopLeftCursor TopRightCursor UpCursor WaitCursor WebLinkCursor WriteCursor XeqCursor' poolDictionaries: '' category: 'Graphics-Display Objects'! !Cursor commentStamp: '<historical>' prior: 0! I am a Form that is a possible appearance for a mouse cursor. My size is always 16x16, ever since the original implementation on the Alto. There are many examples available in the "current cursor" category of class methods. For example, "Cursor normal" and "Cursor wait". For example: Cursor wait show ! !Cursor methodsFor: 'updating' stamp: 'ls 6/17/2002 12:00'! changed: aParameter "overriden to reinstall the cursor if it is the active cursor, in case the appearance has changed. (Is this used anywhere? Do cursors really change in place these days?)" self == CurrentCursor ifTrue: [self beCursor]. super changed: aParameter! ! !Cursor methodsFor: 'displaying' stamp: 'ls 6/17/2002 11:56'! show "Make the hardware's mouse cursor look like the receiver" Sensor currentCursor: self! ! !Cursor methodsFor: 'displaying' stamp: 'bf 10/13/1999 13:05'! showWhile: aBlock "While evaluating the argument, aBlock, make the receiver be the cursor shape." | oldcursor | oldcursor _ Sensor currentCursor. self show. ^aBlock ensure: [oldcursor show] ! ! !Cursor methodsFor: 'printing'! printOn: aStream self storeOn: aStream base: 2! ! !Cursor methodsFor: 'testing' stamp: 'bf 2/2/1999 19:34'! hasMask ^false! ! !Cursor methodsFor: 'converting' stamp: 'RAA 8/14/2000 10:14'! asCursorForm | form | form _ StaticForm extent: self extent depth: 8. form fillShape: self fillColor: Color black at: offset negated. ^ form offset: offset! ! !Cursor methodsFor: 'converting' stamp: 'bf 2/2/1999 19:32'! withMask ^CursorWithMask derivedFrom: self! ! !Cursor methodsFor: 'primitives'! beCursor "Primitive. Tell the interpreter to use the receiver as the current cursor image. Fail if the receiver does not match the size expected by the hardware. Essential. See Object documentation whatIsAPrimitive." <primitive: 101> self primitiveFailed! ! !Cursor methodsFor: 'primitives' stamp: 'jm 9/22/1998 23:33'! beCursorWithMask: maskForm "Primitive. Tell the interpreter to use the receiver as the current cursor image with the given mask Form. Both the receiver and the mask should have extent 16@16 and a depth of one. The mask and cursor bits are combined as follow: mask cursor effect 0 0 transparent (underlying pixel shows through) 1 1 opaque black 1 0 opaque white 0 1 invert the underlying pixel" "Essential. See Object documentation whatIsAPrimitive." <primitive: 101> self primitiveFailed ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Cursor class instanceVariableNames: ''! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 18:57'! initBottomLeft BottomLeftCursor _ (Cursor extent: 16@16 fromArray: #( 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1111111111111111 2r1111111111111111) offset: 0@-16). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 18:57'! initBottomRight BottomRightCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r1111111111111111 2r1111111111111111) offset: -16@-16). ! ! !Cursor class methodsFor: 'class initialization'! initCorner CornerCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r1111111111111111 2r1111111111111111) offset: -16@-16). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 7/12/2003 21:02'! initCrossHair CrossHairCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0111111111111100 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000000000000 2r0) offset: -7@-7). ! ! !Cursor class methodsFor: 'class initialization'! initDown DownCursor _ (Cursor extent: 16@16 fromArray: #( 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r1111110000000000 2r111100000000000 2r11000000000000 2r0 2r0 2r0 2r0 2r0 2r0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization'! initMarker MarkerCursor _ Cursor extent: 16@16 fromArray: #( 2r0111000000000000 2r1111100000000000 2r1111100000000000 2r0111000000000000 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: 0@0. ! ! !Cursor class methodsFor: 'class initialization' stamp: 'di 7/30/2001 10:32'! initMenu MenuCursor _ (Cursor extent: 16@16 fromArray: #( 2r1111111111100000 2r1000000000100000 2r1010011000100000 2r1000000000100000 2r1101001101100000 2r1111111111100000 2r1000000000100000 2r1011001010100000 2r1000000000100000 2r1010110010100000 2r1000000000100000 2r1010010100100000 2r1000000000100000 2r1111111111100000 0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 7/12/2003 21:10'! initMove MoveCursor _ Cursor extent: 16@16 fromArray: #( 2r1111111111111100 2r1111111111111100 2r1100001100001100 2r1100001100001100 2r1100001100001100 2r1100001100001100 2r1111111111111100 2r1111111111111100 2r1100001100001100 2r1100001100001100 2r1100001100001100 2r1100001100001100 2r1111111111111100 2r1111111111111100 0) offset: 0@0. ! ! !Cursor class methodsFor: 'class initialization'! initNormal NormalCursor _ (Cursor extent: 16@16 fromArray: #( 2r1000000000000000 2r1100000000000000 2r1110000000000000 2r1111000000000000 2r1111100000000000 2r1111110000000000 2r1111111000000000 2r1111100000000000 2r1111100000000000 2r1001100000000000 2r0000110000000000 2r0000110000000000 2r0000011000000000 2r0000011000000000 2r0000001100000000 2r0000001100000000) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'di 10/8/1998 17:04'! initNormalWithMask "Cursor initNormalWithMask. Cursor normal show" "Next two lines work simply for any cursor..." self initNormal. NormalCursor _ CursorWithMask derivedFrom: NormalCursor. "But for a good looking cursor, you have to tweak things..." NormalCursor _ (CursorWithMask extent: 16@16 depth: 1 fromArray: #( 0 1073741824 1610612736 1879048192 2013265920 2080374784 2113929216 2130706432 2080374784 2080374784 1275068416 100663296 100663296 50331648 50331648 0) offset: -1@-1) setMaskForm: (Form extent: 16@16 depth: 1 fromArray: #( 3221225472 3758096384 4026531840 4160749568 4227858432 4261412864 4278190080 4286578688 4278190080 4261412864 4261412864 3472883712 251658240 125829120 125829120 50331648) offset: 0@0).! ! !Cursor class methodsFor: 'class initialization'! initOrigin OriginCursor _ (Cursor extent: 16@16 fromArray: #( 2r1111111111111111 2r1111111111111111 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 7/12/2003 22:55'! initRead ReadCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000000000000 2r0001000000001000 2r0010100000010100 2r0100000000100000 2r1111101111100000 2r1000010000100000 2r1000010000100000 2r1011010110100000 2r0111101111000000 2r0 2r0 2r0 2r0 2r0 2r0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'dew 2/14/2004 01:24'! initResizeLeft ResizeLeftCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000001001000000 2r0000001001000000 2r0000001001000000 2r0000101001010000 2r0001101001011000 2r0011101001011100 2r0111111001111110 2r0011101001011100 2r0001101001011000 2r0000101001010000 2r0000001001000000 2r0000001001000000 2r0000001001000000 2r0000001001000000 2r0000000000000000 ) offset: -7@-7 ) withMask ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 4/3/2004 11:46'! initResizeTop "Cursor initResizeTop" ResizeTopCursor _ (Cursor extent: 16@16 fromArray: #( 2r000000100000000 2r000001110000000 2r000011111000000 2r000111111100000 2r000000100000000 2r111111111111100 2r000000000000000 2r000000000000000 2r111111111111100 2r000000100000000 2r000111111100000 2r000011111000000 2r000001110000000 2r000000100000000 2r000000000000000) offset: -7@-7) withMask! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 18:59'! initResizeTopLeft ResizeTopLeftCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0111110000010000 2r0111100000100000 2r0111000001000100 2r0110100010001000 2r0100010100010000 2r0000001000100000 2r0000010001000000 2r0000100010000000 2r0001000100100010 2r0010001000010110 2r0000010000001110 2r0000100000011110 2r0000000000111110 2r0000000000000000 2r0000000000000000) offset: -7@-7) withMask! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 19:00'! initResizeTopRight ResizeTopRightCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000100000111110 2r0000010000011110 2r0010001000001110 2r0001000100010110 2r0000100010100010 2r0000010001000000 2r0000001000100000 2r0000000100010000 2r0100010010001000 2r0110100001000100 2r0111000000100000 2r0111100000010000 2r0111110000000000 2r0000000000000000 2r0000000000000000) offset: -7@-7) withMask.! ! !Cursor class methodsFor: 'class initialization'! initRightArrow RightArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r100000000000 2r111000000000 2r1111111110000000 2r111000000000 2r100000000000 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: 0@0). "Cursor initRightArrow"! ! !Cursor class methodsFor: 'class initialization'! initSquare SquareCursor _ (Cursor extent: 16@16 fromArray: #( 2r0 2r0 2r0 2r0 2r0 2r0000001111000000 2r0000001111000000 2r0000001111000000 2r0000001111000000 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: -8@-8). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 19:01'! initTopLeft TopLeftCursor _ (Cursor extent: 16@16 fromArray: #( 2r1111111111111111 2r1111111111111111 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000 2r1100000000000000) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 19:02'! initTopRight TopRightCursor _ (Cursor extent: 16@16 fromArray: #( 2r1111111111111111 2r1111111111111111 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011 2r0000000000000011) offset: -16@0). ! ! !Cursor class methodsFor: 'class initialization'! initUp UpCursor _ (Cursor extent: 16@16 fromArray: #( 2r11000000000000 2r111100000000000 2r1111110000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r11000000000000 2r0 2r0 2r0 2r0 2r0 2r0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 7/12/2003 21:27'! initWait WaitCursor _ (Cursor extent: 16@16 fromArray: #( 2r1111111111111100 2r1000000000000100 2r0100000000001000 2r0010000000010000 2r0001110011100000 2r0000111111000000 2r0000011110000000 2r0000011110000000 2r0000100101000000 2r0001000100100000 2r0010000110010000 2r0100001111001000 2r1000111111110100 2r1111111111111100 0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'kfr 7/12/2003 22:52'! initWrite WriteCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000011000 2r0000000000111100 2r0000000001001000 2r0000000010010000 2r0000000100100000 2r0000001001000100 2r0000010010000100 2r0000100100001100 2r0001001000010000 2r0010010000010000 2r0111100000001000 2r0101000011111000 2r1110000110000000 2r0111111100000000 2r0 2r0) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization'! initXeq XeqCursor _ (Cursor extent: 16@16 fromArray: #( 2r1000000000010000 2r1100000000010000 2r1110000000111000 2r1111000111111111 2r1111100011000110 2r1111110001000100 2r1111111001111100 2r1111000001101100 2r1101100011000110 2r1001100010000010 2r0000110000000000 2r0000110000000000 2r0000011000000000 2r0000011000000000 2r0000001100000000 2r0000001100000000) offset: 0@0). ! ! !Cursor class methodsFor: 'class initialization' stamp: 'JMM 10/21/2003 19:04'! initialize "Create all the standard cursors..." self initOrigin. self initRightArrow. self initMenu. self initCorner. self initRead. self initWrite. self initWait. BlankCursor _ Cursor new. self initXeq. self initSquare. self initNormalWithMask. self initCrossHair. self initMarker. self initUp. self initDown. self initMove. self initBottomLeft. self initBottomRight. self initResizeLeft. self initResizeTop. self initResizeTopLeft. self initResizeTopRight. self initTopLeft. self initTopRight. self makeCursorsWithMask. "Cursor initialize" ! ! !Cursor class methodsFor: 'class initialization' stamp: 'bf 2/2/1999 19:33'! makeCursorsWithMask "Cursor initialize;makeCursorsWithMask" self classPool associationsDo: [:var | var value hasMask ifFalse: [var value: var value withMask]] ! ! !Cursor class methodsFor: 'class initialization'! startUp self currentCursor: self currentCursor! ! !Cursor class methodsFor: 'instance creation'! extent: extentPoint fromArray: anArray offset: offsetPoint "Answer a new instance of me with width and height specified by extentPoint, offset by offsetPoint, and bits from anArray. NOTE: This has been kluged to take an array of 16-bit constants, and shift them over so they are left-justified in a 32-bit bitmap" extentPoint = (16 @ 16) ifTrue: [^ super extent: extentPoint fromArray: (anArray collect: [:bits | bits bitShift: 16]) offset: offsetPoint] ifFalse: [self error: 'cursors must be 16@16']! ! !Cursor class methodsFor: 'instance creation' stamp: 'di 10/6/1998 13:53'! new ^ self extent: 16 @ 16 fromArray: (Array new: 16 withAll: 0) offset: 0 @ 0 "Cursor new bitEdit show"! ! !Cursor class methodsFor: 'current cursor'! currentCursor "Answer the instance of Cursor that is the one currently displayed." ^CurrentCursor! ! !Cursor class methodsFor: 'current cursor' stamp: 'di 10/6/1998 13:57'! currentCursor: aCursor "Make the instance of cursor, aCursor, be the current cursor. Display it. Create an error if the argument is not a Cursor." (aCursor isKindOf: self) ifTrue: [CurrentCursor _ aCursor. aCursor beCursor] ifFalse: [self error: 'The new cursor must be an instance of class Cursor']! ! !Cursor class methodsFor: 'constants'! blank "Answer the instance of me that is all white." ^BlankCursor! ! !Cursor class methodsFor: 'constants' stamp: 'JMM 10/21/2003 19:13'! bottomLeft "Cursor bottomLeft showWhile: [Sensor waitButton]" ^BottomLeftCursor ! ! !Cursor class methodsFor: 'constants' stamp: 'JMM 10/21/2003 19:13'! bottomRight "Cursor bottomRight showWhile: [Sensor waitButton]" ^BottomRightCursor ! ! !Cursor class methodsFor: 'constants'! corner "Answer the instance of me that is the shape of the bottom right corner of a rectangle." ^CornerCursor! ! !Cursor class methodsFor: 'constants'! crossHair "Answer the instance of me that is the shape of a cross." ^CrossHairCursor! ! !Cursor class methodsFor: 'constants'! down "Answer the instance of me that is the shape of an arrow facing downward." ^DownCursor! ! !Cursor class methodsFor: 'constants'! execute "Answer the instance of me that is the shape of an arrow slanted left with a star next to it." ^XeqCursor! ! !Cursor class methodsFor: 'constants'! menu "Answer the instance of me that is the shape of a menu." ^MenuCursor! ! !Cursor class methodsFor: 'constants'! move "Answer the instance of me that is the shape of a cross inside a square." ^MoveCursor! ! !Cursor class methodsFor: 'constants'! normal "Answer the instance of me that is the shape of an arrow slanted left." ^NormalCursor! ! !Cursor class methodsFor: 'constants'! origin "Answer the instance of me that is the shape of the top left corner of a rectangle." ^OriginCursor! ! !Cursor class methodsFor: 'constants'! read "Answer the instance of me that is the shape of eyeglasses." ^ReadCursor! ! !Cursor class methodsFor: 'constants'! rightArrow "Answer the instance of me that is the shape of an arrow pointing to the right." ^RightArrowCursor! ! !Cursor class methodsFor: 'constants' stamp: 'JMM 10/21/2003 19:01'! topLeft "Cursor topLeft showWhile: [Sensor waitButton]" ^ TopLeftCursor! ! !Cursor class methodsFor: 'constants' stamp: 'JMM 10/21/2003 19:02'! topRight "Cursor topRight showWhile: [Sensor waitButton]" ^ TopRightCursor! ! !Cursor class methodsFor: 'constants'! up "Answer the instance of me that is the shape of an arrow facing upward." ^UpCursor! ! !Cursor class methodsFor: 'constants' stamp: 'sw 8/15/97 13:28'! wait "Answer the instance of me that is the shape of an Hourglass (was in the shape of three small balls)." ^WaitCursor! ! !Cursor class methodsFor: 'constants'! write "Answer the instance of me that is the shape of a pen writing." ^WriteCursor! ! Cursor subclass: #CursorWithMask instanceVariableNames: 'maskForm' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !CursorWithMask commentStamp: '<historical>' prior: 0! A Cursor which additionally has a 16x16 transparency bitmap called a "mask". See the comment of beCursorWithMask: for details on how the mask is treated.! ]style[(97 17 40)f3,f3LCursor beCursorWithMask:;,f3! !CursorWithMask methodsFor: 'mask' stamp: 'bf 2/2/1999 19:34'! hasMask ^true! ! !CursorWithMask methodsFor: 'mask' stamp: 'di 10/8/1998 16:46'! setMaskForm: aForm maskForm _ aForm! ! !CursorWithMask methodsFor: 'mask' stamp: 'bf 2/2/1999 19:30'! storeOn: aStream base: anInteger aStream nextPut: $(. super storeOn: aStream base: anInteger. aStream nextPutAll: ' setMaskForm: '. maskForm storeOn: aStream base: anInteger. aStream nextPut: $)! ! !CursorWithMask methodsFor: 'mask' stamp: 'bf 2/2/1999 19:31'! withMask ^self! ! !CursorWithMask methodsFor: 'primitives' stamp: 'di 10/6/1998 15:16'! beCursor maskForm unhibernate. ^ self beCursorWithMask: maskForm! ! !CursorWithMask methodsFor: 'converting' stamp: 'RAA 8/14/2000 10:14'! asCursorForm | form | form _ StaticForm extent: self extent depth: 8. form fillShape: maskForm fillColor: Color white. form fillShape: self fillColor: Color black at: offset negated. ^ form offset: offset! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CursorWithMask class instanceVariableNames: ''! !CursorWithMask class methodsFor: 'as yet unclassified' stamp: 'di 2/18/1999 08:56'! derivedFrom: aForm "Cursor initNormalWithMask. Cursor normal show" "aForm is presumably a cursor" | cursor mask ext | ext _ aForm extent. cursor _ self extent: ext. cursor copy: (1@1 extent: ext) from: 0@0 in: aForm rule: Form over. mask _ Form extent: ext. (1@1) eightNeighbors do: [:p | mask copy: (p extent: ext) from: 0@0 in: aForm rule: Form under]. cursor setMaskForm: mask. cursor offset: ((aForm offset - (1@1)) max: ext negated). ^ cursor! ! Path subclass: #CurveFitter instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !CurveFitter commentStamp: '<historical>' prior: 0! 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.! !CurveFitter methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm | pa pb k s p1 p2 p3 line | line _ Line new. line form: self form. collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points']. p1 _ self firstPoint. p2 _ self secondPoint. p3 _ self thirdPoint. s _ Path new. s add: p1. pa _ p2 - p1. pb _ p3 - p2. k _ 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20. "k is a guess as to how many line segments to use to approximate the curve." 1 to: k do: [:i | s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)]. s add: p3. 1 to: s size - 1 do: [:i | line beginPoint: (s at: i). line endPoint: (s at: i + 1). line displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm]! ! !CurveFitter methodsFor: 'displaying' stamp: '6/9/97 10:16 di'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm | transformedPath newCurveFitter | transformedPath _ aTransformation applyTo: self. newCurveFitter _ CurveFitter new. newCurveFitter firstPoint: transformedPath firstPoint. newCurveFitter secondPoint: transformedPath secondPoint. newCurveFitter thirdPoint: transformedPath thirdPoint. newCurveFitter form: self form. newCurveFitter displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRect rule: anInteger fillColor: aForm! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CurveFitter class instanceVariableNames: ''! !CurveFitter class methodsFor: 'instance creation'! new | newSelf | newSelf _ super new: 3. newSelf add: 0@0. newSelf add: 0@0. newSelf add: 0@0. ^newSelf! ! !CurveFitter class methodsFor: 'examples' stamp: '6/9/97 10:16 di'! example "Designate three locations on the screen by clicking any button. The curve determined by the points will be displayed with a long black form." | aCurveFitter aForm | aForm _ Form extent: 1@30. "make a long thin Form for display " aForm fillBlack. "turn it black" aCurveFitter _ CurveFitter new. aCurveFitter form: aForm. "set the form for display" "collect three Points and show them on the dispaly" aCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aCurveFitter firstPoint. aCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aCurveFitter secondPoint. aCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aCurveFitter thirdPoint. aCurveFitter displayOn: Display "display the CurveFitter" "CurveFitter example"! ! SelectionMenu subclass: #CustomMenu instanceVariableNames: 'labels dividers lastDivider title targets arguments' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !CustomMenu commentStamp: '<historical>' prior: 0! I am used to build menus on-the-fly. I maintain lists of menu items, actions (usually symbols to be sent as messages), and menu section dividing lines to which my clients may append new entries and lines by sending me the messages: add: aString action: anAction addLine After the menu is constructed, it may be invoked with one of the following messages: startUp: initialSelection startUp I am a subclass of ActionMenu, so I inherit a number of instance variables. The ones I am particularly concerned with are: items _ an OrderedCollection of strings to appear in the menu selectors _ an OrderedCollection of Symbols to be used as message selectors lineArray _ an OrderedCollection of line positions lastLine _ used to keep track of the last line to avoid making duplicate entries in lineArray! !CustomMenu methodsFor: 'initialize-release' stamp: 'sumim 2/10/2002 01:26'! initialize labels _ OrderedCollection new. selections _ OrderedCollection new. dividers _ OrderedCollection new. lastDivider _ 0. targets _ OrderedCollection new. arguments _ OrderedCollection new ! ! !CustomMenu methodsFor: 'initialize-release' stamp: 'sw 8/18/1998 12:01'! title: aTitle title _ aTitle! ! !CustomMenu methodsFor: 'construction' stamp: 'dhhi 9/14/2000 22:39'! add: aString action: actionItem "Add the given string as the next menu item. If it is selected, the given action (usually but not necessarily a symbol) will be returned to the client." | s | aString ifNil: [^ self addLine]. s _ String new: aString size + 2. s at: 1 put: Character space. s replaceFrom: 2 to: s size - 1 with: aString. s at: s size put: Character space. labels addLast: s. selections addLast: actionItem.! ! !CustomMenu methodsFor: 'construction'! addLine "Append a line to the menu after the last entry. Suppress duplicate lines." (lastDivider ~= selections size) ifTrue: [ lastDivider _ selections size. dividers addLast: lastDivider].! ! !CustomMenu methodsFor: 'construction' stamp: 'sw 2/27/2001 07:52'! addList: listOfTuplesAndDashes "Add a menu item to the receiver for each tuple in the given list of the form (<what to show> <selector>). Add a line for each dash (-) in the list. The tuples may have an optional third element, providing balloon help for the item, but such an element is ignored in mvc." listOfTuplesAndDashes do: [:aTuple | aTuple == #- ifTrue: [self addLine] ifFalse: [self add: aTuple first action: aTuple second]] "CustomMenu new addList: #( ('apples' buyApples) ('oranges' buyOranges) - ('milk' buyMilk)); startUp" ! ! !CustomMenu methodsFor: 'construction' stamp: 'sw 8/12/2002 17:14'! addStayUpItem "For compatibility with MenuMorph. Here it is a no-op"! ! !CustomMenu methodsFor: 'construction' stamp: 'sw 7/20/1999 18:47'! balloonTextForLastItem: aString "Vacuous backstop provided for compatibility with MorphicMenu"! ! !CustomMenu methodsFor: 'construction' stamp: 'jm 8/20/1998 08:34'! labels: aString font: aFont lines: anArrayOrNil "This method allows the receiver to accept old-style SelectionMenu creation messages. It should be used only for backward compatibility during the MVC-to-Morphic transition. New code should be written using the other menu construction protocol such as addList:." | labelList linesArray | labelList _ (aString findTokens: String cr) asArray. anArrayOrNil ifNil: [linesArray _ #()] ifNotNil: [linesArray _ anArrayOrNil]. 1 to: labelList size do: [:i | self add: (labelList at: i) action: (labelList at: i). (linesArray includes: i) ifTrue: [self addLine]]. font ifNotNil: [font _ aFont]. ! ! !CustomMenu methodsFor: 'construction' stamp: 'di 8/20/1998 09:24'! labels: labelList lines: linesArray selections: selectionsArray "This method allows the receiver to accept old-style SelectionMenu creation messages. It should be used only for backward compatibility during the MVC-to-Morphic transition. New code should be written using the other menu construction protocol such as addList:." "Labels can be either a sting with embedded crs, or a collection of strings." | labelArray | (labelList isMemberOf: String) ifTrue: [labelArray _ labelList findTokens: String cr] ifFalse: [labelArray _ labelList]. 1 to: labelArray size do: [:i | self add: (labelArray at: i) action: (selectionsArray at: i). (linesArray includes: i) ifTrue: [self addLine]]. ! ! !CustomMenu methodsFor: 'invocation' stamp: 'sw 2/17/2002 04:48'! invokeOn: targetObject "Pop up this menu and return the result of sending to the target object the selector corresponding to the menu item selected by the user. Return nil if no item is selected. If the chosen selector has arguments, obtain them from my arguments" ^ self invokeOn: targetObject orSendTo: nil! ! !CustomMenu methodsFor: 'invocation' stamp: 'sw 11/16/2002 23:45'! invokeOn: targetObject orSendTo: anObject "Pop up this menu and return the result of sending to the target object the selector corresponding to the menu item selected by the user. Return nil if no item is selected. If the chosen selector has arguments, obtain appropriately. If the recipient does not respond to the resulting message, send it to the alternate object provided" | aSelector anIndex recipient | ^ (aSelector _ self startUp) ifNotNil: [anIndex _ self selection. recipient _ ((targets _ self targets) isEmptyOrNil or: [anIndex > targets size]) ifTrue: [targetObject] ifFalse: [targets at: anIndex]. aSelector numArgs == 0 ifTrue: [recipient perform: aSelector orSendTo: anObject] ifFalse: [recipient perform: aSelector withArguments: (self arguments at: anIndex)]]! ! !CustomMenu methodsFor: 'invocation'! startUp "Build and invoke this menu with no initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen." ^ self startUp: nil! ! !CustomMenu methodsFor: 'invocation' stamp: 'sw 8/18/1998 12:01'! startUp: initialSelection "Build and invoke this menu with the given initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen." ^ self startUp: initialSelection withCaption: title! ! !CustomMenu methodsFor: 'invocation'! startUp: initialSelection withCaption: caption "Build and invoke this menu with the given initial selection and caption. Answer the selection associated with the menu item chosen by the user or nil if none is chosen." self build. (initialSelection notNil) ifTrue: [self preSelect: initialSelection]. ^ super startUpWithCaption: caption! ! !CustomMenu methodsFor: 'invocation' stamp: 'sw 7/31/97 19:31'! startUpWithCaption: caption "Build and invoke this menu with no initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen; use the provided caption" ^ self startUp: nil withCaption: caption! ! !CustomMenu methodsFor: 'compatibility' stamp: 'ads 2/20/2003 08:59'! add: aString subMenu: aMenu target: target selector: aSymbol argumentList: argList "Create a sub-menu with the given label. This isn't really a sub-menu the way Morphic does it; it'll just pop up another menu." self add: aString target: aMenu selector: #invokeOn: argumentList: argList asArray.! ! !CustomMenu methodsFor: 'compatibility' stamp: 'sumim 2/10/2002 01:23'! add: aString target: target selector: aSymbol argument: arg "Append a menu item with the given label. If the item is selected, it will send the given selector to the target object with the given argument." self add: aString target: target selector: aSymbol argumentList: (Array with: arg)! ! !CustomMenu methodsFor: 'compatibility' stamp: 'sumim 2/10/2002 01:18'! add: aString target: target selector: aSymbol argumentList: argList "Append a menu item with the given label. If the item is selected, it will send the given selector to the target object with the given arguments. If the selector takes one more argument than the number of arguments in the given list, then the triggering event is supplied as as the last argument." self add: aString action: aSymbol. targets addLast: target. arguments addLast: argList asArray ! ! !CustomMenu methodsFor: 'compatibility' stamp: 'nk 2/15/2004 16:19'! addService: aService for: serviceUser "Append a menu item with the given service. If the item is selected, it will perform the given service." aService addServiceFor: serviceUser toMenu: self.! ! !CustomMenu methodsFor: 'compatibility' stamp: 'nk 2/15/2004 16:02'! addServices2: services for: served extraLines: linesArray services withIndexDo: [:service :i | service addServiceFor: served toMenu: self. (linesArray includes: i) ifTrue: [self addLine] ]! ! !CustomMenu methodsFor: 'compatibility' stamp: 'sumim 2/10/2002 01:20'! addServices: services for: served extraLines: linesArray services withIndexDo: [:service :i | self addService: service for: served. (linesArray includes: i) | service useLineAfter ifTrue: [self addLine]]! ! !CustomMenu methodsFor: 'private' stamp: 'sw 12/10/1999 11:21'! build "Turn myself into an invokable ActionMenu." | stream | stream _ WriteStream on: (String new). labels do: [:label | stream nextPutAll: label; cr]. (labels isEmpty) ifFalse: [stream skip: -1]. "remove final cr" super labels: stream contents font: MenuStyle defaultFont lines: dividers! ! !CustomMenu methodsFor: 'private' stamp: 'di 4/14/1999 21:28'! preSelect: action "Pre-select and highlight the menu item associated with the given action." | i | i _ selections indexOf: action ifAbsent: [^ self]. marker ifNil: [self computeForm]. marker _ marker align: marker topLeft with: (marker left)@(frame inside top + (marker height * (i - 1))). selection _ i.! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! arguments arguments isNil ifTrue:[arguments := OrderedCollection new]. ^arguments! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! selections selections isNil ifTrue:[selections := OrderedCollection new]. ^selections! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! targets targets isNil ifTrue:[targets := OrderedCollection new]. ^targets! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CustomMenu class instanceVariableNames: ''! !CustomMenu class methodsFor: 'example' stamp: 'sw 11/8/1999 17:27'! example "CustomMenu example" | menu | menu _ CustomMenu new. menu add: 'apples' action: #apples. menu add: 'oranges' action: #oranges. menu addLine. menu addLine. "extra lines ignored" menu add: 'peaches' action: #peaches. menu addLine. menu add: 'pears' action: #pears. menu addLine. ^ menu startUp: #apples "NB: The following is equivalent to the above, but uses the compact #fromArray: consruct: (CustomMenu fromArray: #( ('apples' apples) ('oranges' oranges) - - ('peaches' peaches) - ('pears' pears) -)) startUp: #apples"! ! Timespan subclass: #Date instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !Date commentStamp: '<historical>' prior: 0! Instances of Date are Timespans with duration of 1 day. Their default creation assumes a start of midnight in the local time zone.! !Date methodsFor: 'printing' stamp: 'brp 7/27/2003 16:07'! mmddyyyy "Answer the receiver rendered in standard U.S.A format mm/dd/yyyy. Note that the name here is slightly misleading -- the month and day numbers don't show leading zeros, so that for example February 1 1996 is 2/1/96" ^ self printFormat: #(2 1 3 $/ 1 1)! ! !Date methodsFor: 'printing' stamp: 'brp 7/27/2003 16:06'! printFormat: formatArray "Answer a String describing the receiver using the argument formatArray." | aStream | aStream _ WriteStream on: (String new: 16). self printOn: aStream format: formatArray. ^ aStream contents! ! !Date methodsFor: 'printing' stamp: 'BP 3/23/2001 12:27'! printOn: aStream self printOn: aStream format: #(1 2 3 $ 3 1 )! ! !Date methodsFor: 'printing' stamp: 'brp 7/27/2003 16:05'! printOn: aStream format: formatArray "Print a description of the receiver on aStream using the format denoted the argument, formatArray: #(item item item sep monthfmt yearfmt twoDigits) items: 1=day 2=month 3=year will appear in the order given, separated by sep which is eaither an ascii code or character. monthFmt: 1=09 2=Sep 3=September yearFmt: 1=1996 2=96 digits: (missing or)1=9 2=09. See the examples in printOn: and mmddyy" | gregorian twoDigits element monthFormat | gregorian _ self dayMonthYearDo: [ :d :m :y | {d. m. y} ]. twoDigits _ formatArray size > 6 and: [(formatArray at: 7) > 1]. 1 to: 3 do: [ :i | element := formatArray at: i. element = 1 ifTrue: [twoDigits ifTrue: [aStream nextPutAll: (gregorian first asString padded: #left to: 2 with: $0)] ifFalse: [gregorian first printOn: aStream]]. element = 2 ifTrue: [monthFormat := formatArray at: 5. monthFormat = 1 ifTrue: [twoDigits ifTrue: [aStream nextPutAll: (gregorian middle asString padded: #left to: 2 with: $0)] ifFalse: [gregorian middle printOn: aStream]]. monthFormat = 2 ifTrue: [aStream nextPutAll: ((Month nameOfMonth: gregorian middle) copyFrom: 1 to: 3)]. monthFormat = 3 ifTrue: [aStream nextPutAll: (Month nameOfMonth: gregorian middle)]]. element = 3 ifTrue: [(formatArray at: 6) = 1 ifTrue: [gregorian last printOn: aStream] ifFalse: [aStream nextPutAll: ((gregorian last \\ 100) asString padded: #left to: 2 with: $0)]]. i < 3 ifTrue: [(formatArray at: 4) ~= 0 ifTrue: [aStream nextPut: (formatArray at: 4) asCharacter]]] ! ! !Date methodsFor: 'printing' stamp: 'BP 3/23/2001 12:27'! storeOn: aStream aStream print: self printString; nextPutAll: ' asDate'! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 22:09'! addDays: dayCount ^ (self asDateAndTime + (dayCount days)) asDate! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:08'! asSeconds "Answer the seconds since the Squeak epoch: 1 January 1901" ^ start asSeconds! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:08'! leap "Answer whether the receiver's year is a leap year." ^ start isLeapYear ifTrue: [1] ifFalse: [0].! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 1/16/2004 14:30'! previous: dayName "Answer the previous date whose weekday name is dayName." | days | days _ 7 + self weekdayIndex - (self class dayOfWeek: dayName) \\ 7. days = 0 ifTrue: [ days _ 7 ]. ^ self subtractDays: days ! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:09'! subtractDate: aDate "Answer the number of days between self and aDate" ^ (self start - aDate asDateAndTime) days! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 22:05'! subtractDays: dayCount ^ (self asDateAndTime - (dayCount days)) asDate! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 8/24/2003 12:04'! weekday "Answer the name of the day of the week on which the receiver falls." ^ self dayOfWeekName! ! !Date methodsFor: 'smalltalk-80' stamp: 'brp 8/24/2003 12:04'! weekdayIndex "Sunday=1, ... , Saturday=7" ^ self dayOfWeek! ! !Date methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:10'! asDate ^ self! ! !Date methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:10'! dayMonthYearDo: aBlock "Supply integers for day, month and year to aBlock and return the result" ^ start dayMonthYearDo: aBlock! ! !Date methodsFor: 'squeak protocol' stamp: 'avi 2/21/2004 18:12'! month ^ self asMonth! ! !Date methodsFor: 'squeak protocol' stamp: 'avi 2/29/2004 13:10'! monthIndex ^ super month! ! !Date methodsFor: 'deprecated' stamp: 'brp 8/5/2003 18:36'! day: dayInteger year: yearInteger ^ self deprecated: 'Obsolete' ! ! !Date methodsFor: 'deprecated' stamp: 'brp 8/5/2003 18:37'! firstDayOfMonthIndex: monthIndex ^ self deprecated: 'Obsolete' ! ! !Date methodsFor: 'deprecated' stamp: 'brp 8/5/2003 18:41'! julianDayNumber: anInteger "Set the number of days elapsed since midnight GMT on January 1st, 4713 B.C." self deprecated: 'Obsolete'. ! ! !Date methodsFor: 'deprecated' stamp: 'brp 8/5/2003 18:34'! mmddyy "Please use mmddyyyy instead, so dates in 2000 will be unambiguous" ^ self deprecated: 'Use #mmddyyyy'; printFormat: #(2 1 3 $/ 1 2) ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Date class instanceVariableNames: ''! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 8/24/2003 00:00'! dateAndTimeNow "Answer an Array whose with Date today and Time now." ^ Time dateAndTimeNow! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:35'! dayOfWeek: dayName ^ Week indexOfDay: dayName! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:59'! daysInMonth: monthName forYear: yearInteger ^ Month daysInMonth: monthName forYear: yearInteger. ! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:53'! daysInYear: yearInteger ^ Year daysInYear: yearInteger.! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 1/16/2004 14:35'! firstWeekdayOfMonth: month year: year "Answer the weekday index of the first day in <month> in the <year>." ^ (self newDay: 1 month: month year: year) weekdayIndex ! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:01'! fromDays: dayCount "Days since 1 January 1901" ^ self julianDayNumber: dayCount + SqueakEpoch! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:02'! fromSeconds: seconds "Answer an instance of me which is 'seconds' seconds after January 1, 1901." ^ self fromDays: ((Duration seconds: seconds) days)! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:39'! indexOfMonth: aMonthName ^ Month indexOfMonth: aMonthName. ! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:56'! leapYear: yearInteger ^ Year leapYear: yearInteger! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:37'! nameOfDay: dayIndex ^ Week nameOfDay: dayIndex ! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:40'! nameOfMonth: anIndex ^ Month nameOfMonth: anIndex. ! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:02'! newDay: day month: month year: year ^ self year: year month: month day: day! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:01'! newDay: dayCount year: yearInteger ^ self year: yearInteger day: dayCount! ! !Date class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:01'! today ^ self current! ! !Date class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:03'! fromString: aString "Answer an instance of created from a string with format dd.mm.yyyy." ^ self readFrom: aString readStream. ! ! !Date class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 18:25'! julianDayNumber: aJulianDayNumber ^ self starting: (DateAndTime julianDayNumber: aJulianDayNumber)! ! !Date class methodsFor: 'squeak protocol' stamp: 'brp 7/1/2003 09:21'! readFrom: aStream "Read a Date from the stream in any of the forms: <day> <monthName> <year> (5 April 1982; 5-APR-82) <monthName> <day> <year> (April 5, 1982) <monthNumber> <day> <year> (4/5/82) <day><monthName><year> (5APR82)" | day month year | aStream peek isDigit ifTrue: [day := Integer readFrom: aStream]. [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. aStream peek isLetter ifTrue: ["number/name... or name..." month := WriteStream on: (String new: 10). [aStream peek isLetter] whileTrue: [month nextPut: aStream next]. month := month contents. day isNil ifTrue: ["name/number..." [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. day := Integer readFrom: aStream]] ifFalse: ["number/number..." month := Month nameOfMonth: day. day := Integer readFrom: aStream]. [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. year := Integer readFrom: aStream. year < 10 ifTrue: [year := 2000 + year] ifFalse: [ year < 1900 ifTrue: [ year := 1900 + year]]. ^ self year: year month: month day: day! ! !Date class methodsFor: 'squeak protocol' stamp: 'BP 3/23/2001 12:36'! starting: aDateAndTime ^super starting: (aDateAndTime midnight) duration: (Duration days: 1) ! ! !Date class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 22:03'! year: year day: dayOfYear ^ self starting: (DateAndTime year: year day: dayOfYear) ! ! !Date class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 22:02'! year: year month: month day: day ^ self starting: (DateAndTime year: year month: month day: day) ! ! Magnitude subclass: #DateAndTime instanceVariableNames: 'seconds offset jdn nanos' classVariableNames: 'LocalTimeZone' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !DateAndTime commentStamp: 'brp 5/13/2003 08:07' prior: 0! I represent a point in UTC time as defined by ISO 8601. I have zero duration. My implementation uses three SmallIntegers and a Duration: jdn - julian day number. seconds - number of seconds since midnight. nanos - the number of nanoseconds since the second. offset - duration from UTC. The nanosecond attribute is almost always zero but it defined for full ISO compliance and is suitable for timestamping. ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 7/9/2005 08:45'! + operand "operand conforms to protocol Duration" | ticks | ticks _ self ticks + (operand asDuration ticks) . ^ self class basicNew ticks: ticks offset: self offset; yourself. ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 1/9/2004 05:39'! - operand "operand conforms to protocol DateAndTime or protocol Duration" ^ (operand respondsTo: #asDateAndTime) ifTrue: [ | lticks rticks | lticks _ self asLocal ticks. rticks _ operand asDateAndTime asLocal ticks. Duration seconds: (SecondsInDay *(lticks first - rticks first)) + (lticks second - rticks second) nanoSeconds: (lticks third - rticks third) ] ifFalse: [ self + (operand negated) ]. ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'nk 3/30/2004 09:09'! < comparand "comparand conforms to protocol DateAndTime, or can be converted into something that conforms." | lticks rticks comparandAsDateAndTime | comparandAsDateAndTime := comparand asDateAndTime. offset = comparandAsDateAndTime offset ifTrue: [lticks := self ticks. rticks := comparandAsDateAndTime ticks] ifFalse: [lticks := self asUTC ticks. rticks := comparandAsDateAndTime asUTC ticks]. ^ lticks first < rticks first or: [lticks first > rticks first ifTrue: [false] ifFalse: [lticks second < rticks second or: [lticks second > rticks second ifTrue: [false] ifFalse: [lticks third < rticks third]]]] ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'nk 3/30/2004 08:49'! = comparand "comparand conforms to protocol DateAndTime, or can be converted into something that conforms." | comparandAsDateAndTime | self == comparand ifTrue: [^ true]. [comparandAsDateAndTime := comparand asDateAndTime] on: MessageNotUnderstood do: [^ false]. ^ self offset = comparandAsDateAndTime offset ifTrue: [self ticks = comparandAsDateAndTime ticks] ifFalse: [self asUTC ticks = comparandAsDateAndTime asUTC ticks] ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 13:11'! asLocal ^ (self offset = self class localOffset) ifTrue: [self] ifFalse: [self utcOffset: self class localOffset] ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 13:12'! asUTC ^ self utcOffset: 0! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 21:03'! dayOfMonth "Answer which day of the month is represented by the receiver." ^ self dayMonthYearDo: [ :d :m :y | d ]! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/24/2003 12:25'! dayOfWeek "Sunday=1, ... , Saturday=7" ^ (jdn + 1 rem: 7) + 1! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:28'! dayOfWeekName ^ Week nameOfDay: self dayOfWeek ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:29'! dayOfYear ^ jdn - (Year year: self year) start julianDayNumber + 1 ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 15:49'! hash ^ self asUTC ticks hash ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:29'! hour ^ self hour24 ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:29'! hour24 ^ (Duration seconds: seconds) hours ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:29'! isLeapYear ^ Year isLeapYear: self year. ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:30'! minute ^ (Duration seconds: seconds) minutes ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 21:05'! month ^ self dayMonthYearDo: [ :d :m :y | m ].! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:30'! monthName ^ Month nameOfMonth: self month ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:30'! offset ^ offset ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 21:09'! offset: anOffset "Answer a <DateAndTime> equivalent to the receiver but with its local time being offset from UTC by offset." ^ self class basicNew ticks: self ticks offset: anOffset asDuration; yourself ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:31'! second ^ (Duration seconds: seconds) seconds ! ! !DateAndTime methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 21:05'! year ^ self dayMonthYearDo: [ :d :m :y | y ]! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 23:56'! asDate ^ Date starting: self ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:46'! asDateAndTime ^ self ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:47'! asDuration "Answer the duration since midnight" ^ Duration seconds: seconds nanoSeconds: nanos ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:47'! asMonth ^ Month starting: self ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:45'! asNanoSeconds "Answer the number of nanoseconds since midnight" ^ self asDuration asNanoSeconds ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 8/24/2003 00:00'! asTime ^ Time seconds: seconds nanoSeconds: nanos! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 8/24/2003 00:02'! asTimeStamp ^ self as: TimeStamp! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:47'! asYear ^ Year starting: self ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:47'! dayMonthYearDo: aBlock "Evaluation the block with three arguments: day month, year." | l n i j dd mm yyyy | l := jdn + 68569. n := 4 * l // 146097. l := l - (146097 * n + 3 // 4). i := 4000 * (l + 1) // 1461001. l := l - (1461 * i // 4) + 31. j := 80 * l // 2447. dd := l - (2447 * j // 80). l := j // 11. mm := j + 2 - (12 * l). yyyy := 100 * (n - 49) + i + l. ^ aBlock value: dd value: mm value: yyyy.! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:49'! duration ^ Duration zero ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:49'! julianDayNumber ^ jdn ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:48'! midnight "Answer a DateAndTime starting at midnight local time" ^ self dayMonthYearDo: [ :d :m :y | self class year: y month: m day: d ]! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:50'! nanoSecond ^ nanos ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'nk 3/12/2004 10:03'! printHMSOn: aStream "Print just hh:mm:ss" aStream nextPutAll: (self hour asString padded: #left to: 2 with: $0); nextPut: $:; nextPutAll: (self minute asString padded: #left to: 2 with: $0); nextPut: $:; nextPutAll: (self second asString padded: #left to: 2 with: $0). ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'nk 3/12/2004 10:38'! printOn: aStream "Print as per ISO 8601 sections 5.3.3 and 5.4.1. Prints either: 'YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for positive years) or '-YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for negative years)" ^self printOn: aStream withLeadingSpace: false ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'nk 3/12/2004 10:37'! printOn: aStream withLeadingSpace: printLeadingSpaceToo "Print as per ISO 8601 sections 5.3.3 and 5.4.1. If printLeadingSpaceToo is false, prints either: 'YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for positive years) or '-YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for negative years) If printLeadingSpaceToo is true, prints either: ' YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for positive years) or '-YYYY-MM-DDThh:mm:ss.s+ZZ:zz:z' (for negative years) " self printYMDOn: aStream withLeadingSpace: printLeadingSpaceToo. aStream nextPut: $T. self printHMSOn: aStream. self nanoSecond ~= 0 ifTrue: [ | z ps | ps := self nanoSecond printString padded: #left to: 9 with: $0. z := ps findLast: [ :c | c asciiValue > $0 asciiValue ]. ps from: 1 to: z do: [ :c | aStream nextPut: c ] ]. aStream nextPut: (offset positive ifTrue: [$+] ifFalse: [$-]); nextPutAll: (offset hours abs asString padded: #left to: 2 with: $0); nextPut: $:; nextPutAll: (offset minutes abs asString padded: #left to: 2 with: $0). offset seconds = 0 ifFalse: [ aStream nextPut: $:; nextPutAll: (offset seconds abs truncated asString) ]. ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'nk 3/12/2004 10:29'! printYMDOn: aStream withLeadingSpace: printLeadingSpaceToo "Print just the year, month, and day on aStream. If printLeadingSpaceToo is true, then print as: ' YYYY-MM-DD' (if the year is positive) or '-YYYY-MM-DD' (if the year is negative) otherwise print as: 'YYYY-MM-DD' or '-YYYY-MM-DD' " | year month day | self dayMonthYearDo: [ :d :m :y | year := y. month := m. day := d ]. year negative ifTrue: [ aStream nextPut: $- ] ifFalse: [ printLeadingSpaceToo ifTrue: [ aStream space ]]. aStream nextPutAll: (year abs asString padded: #left to: 4 with: $0); nextPut: $-; nextPutAll: (month asString padded: #left to: 2 with: $0); nextPut: $-; nextPutAll: (day asString padded: #left to: 2 with: $0) ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:50'! to: anEnd "Answer a Timespan. anEnd conforms to protocol DateAndTime or protocol Timespan" ^ Timespan starting: self ending: (anEnd asDateAndTime). ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 15:57'! to: anEnd by: aDuration "Answer a Timespan. anEnd conforms to protocol DateAndTime or protocol Timespan" ^ (Schedule starting: self ending: (anEnd asDateAndTime)) schedule: (Array with: aDuration asDuration); yourself. ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 16:01'! to: anEnd by: aDuration do: aBlock "Answer a Timespan. anEnd conforms to protocol DateAndTime or protocol Timespan" ^ (self to: anEnd by: aDuration) scheduleDo: aBlock ! ! !DateAndTime methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:37'! utcOffset: anOffset "Answer a <DateAndTime> equivalent to the receiver but offset from UTC by anOffset" | equiv | equiv _ self + (anOffset asDuration - self offset). ^ equiv ticks: (equiv ticks) offset: anOffset asDuration; yourself ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 21:03'! asSeconds "Return the number of seconds since the Squeak epoch" ^ (self - (self class epoch)) asSeconds ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 17:53'! day ^ self dayOfYear! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 07:48'! daysInMonth "Answer the number of days in the month represented by the receiver." ^ self asMonth daysInMonth ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 07:48'! daysInYear "Answer the number of days in the year represented by the receiver." ^ self asYear daysInYear ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 15:44'! daysLeftInYear "Answer the number of days in the year after the date of the receiver." ^ self daysInYear - self dayOfYear ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 15:44'! firstDayOfMonth ^ self asMonth start day! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 18:30'! hours ^ self hour! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 1/7/2004 15:45'! minutes ^ self minute! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 07:50'! monthIndex ^ self month ! ! !DateAndTime methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 18:31'! seconds ^ self second! ! !DateAndTime methodsFor: 'private' stamp: 'brp 8/23/2003 15:45'! ticks "Private - answer an array with our instance variables. Assumed to be UTC " ^ Array with: jdn with: seconds with: nanos .! ! !DateAndTime methodsFor: 'private' stamp: 'nk 3/30/2004 09:38'! ticks: ticks offset: utcOffset "ticks is {julianDayNumber. secondCount. nanoSeconds}" | normalize | normalize := [ :i :base | | tick div quo rem | tick := ticks at: i. div := tick digitDiv: base neg: tick negative. quo := div first normalize. rem := div second normalize. rem < 0 ifTrue: [ quo := quo - 1. rem := base + rem ]. ticks at: (i-1) put: ((ticks at: i-1) + quo). ticks at: i put: rem ]. normalize value: 3 value: NanosInSecond. normalize value: 2 value: SecondsInDay. jdn _ ticks first. seconds _ ticks second. nanos := ticks third. offset := utcOffset. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DateAndTime class instanceVariableNames: ''! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:32'! clockPrecision "One nanosecond precision" ^ Duration nanoSeconds: 1 ! ! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'avi 2/21/2004 19:03'! now ^ self basicNew ticks: (Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: self totalSeconds nanoSeconds: 0) ticks offset: self localOffset; yourself ! ! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'brp 7/27/2003 15:25'! year: year day: dayOfYear hour: hour minute: minute second: second ^ self year: year day: dayOfYear hour: hour minute: minute second: second offset: self localOffset. ! ! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'brp 7/27/2003 15:28'! year: year day: dayOfYear hour: hour minute: minute second: second offset: offset "Return a DataAndTime" | y d | y _ self year: year month: 1 day: 1 hour: hour minute: minute second: second nanoSecond: 0 offset: offset. d _ Duration days: (dayOfYear - 1). ^ y + d! ! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 21:00'! year: year month: month day: day hour: hour minute: minute second: second "Return a DateAndTime" ^ self year: year month: month day: day hour: hour minute: minute second: second offset: self localOffset ! ! !DateAndTime class methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:36'! year: year month: month day: day hour: hour minute: minute second: second offset: offset ^ self year: year month: month day: day hour: hour minute: minute second: second nanoSecond: 0 offset: offset ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:36'! current ^ self now ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 16:12'! date: aDate time: aTime ^ self year: aDate year day: aDate dayOfYear hour: aTime hour minute: aTime minute second: aTime second ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp` 8/24/2003 19:11'! epoch "Answer a DateAndTime representing the Squeak epoch: 1 January 1901" ^ self julianDayNumber: SqueakEpoch ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 07:36'! fromString: aString ^ self readFrom: (ReadStream on: aString) ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 21:08'! julianDayNumber: aJulianDayNumber ^ self basicNew ticks: aJulianDayNumber days ticks offset: self localOffset; yourself ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 9/4/2003 06:40'! localOffset "Answer the duration we are offset from UTC" ^ self localTimeZone offset ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 9/4/2003 06:39'! localTimeZone "Answer the local time zone" ^ LocalTimeZone ifNil: [ LocalTimeZone _ TimeZone default ] ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:09'! midnight ^ self now midnight ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:57'! new "Answer a DateAndTime representing the Squeak epoch: 1 January 1901" ^ self epoch ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:58'! readFrom: aStream | bc year month day hour minute second nanos offset buffer ch | aStream peek = $- ifTrue: [ aStream next. bc _ -1] ifFalse: [bc _ 1]. year _ (aStream upTo: $-) asInteger * bc. month _ (aStream upTo: $-) asInteger. day _ (aStream upTo: $T) asInteger. hour _ (aStream upTo: $:) asInteger. buffer _ '00:'. ch _ nil. minute _ WriteStream on: buffer. [ aStream atEnd | (ch = $:) | (ch = $+) | (ch = $-) ] whileFalse: [ ch _ minute nextPut: aStream next. ]. (ch isNil or: [ch isDigit]) ifTrue: [ ch _ $: ]. minute _ ((ReadStream on: buffer) upTo: ch) asInteger. buffer _ '00.'. second _ WriteStream on: buffer. [ aStream atEnd | (ch = $.) | (ch = $+) | (ch = $-) ] whileFalse: [ ch _ second nextPut: aStream next. ]. (ch isNil or: [ch isDigit]) ifTrue: [ ch _ $. ]. second _ ((ReadStream on: buffer) upTo: ch) asInteger. buffer _ '00000000+'. nanos _ WriteStream on: buffer. [ aStream atEnd | (ch = $+) | (ch = $-) ] whileFalse: [ ch _ nanos nextPut: aStream next. ]. (ch isNil or: [ch isDigit]) ifTrue: [ ch _ $+ ]. nanos _ ((ReadStream on: buffer) upTo: ch) asInteger. aStream atEnd ifTrue: [ offset _ self localOffset ] ifFalse: [offset _ Duration fromString: (ch asString, '0:', aStream upToEnd). (offset = self localOffset) ifTrue: [ offset _ self localOffset ]]. ^ self year: year month: month day: day hour: hour minute: minute second: second nanoSecond: nanos offset: offset. " '-1199-01-05T20:33:14.321-05:00' asDateAndTime ' 2002-05-16T17:20:45.00000001+01:01' asDateAndTime ' 2002-05-16T17:20:45.00000001' asDateAndTime ' 2002-05-16T17:20' asDateAndTime ' 2002-05-16T17:20:45' asDateAndTime ' 2002-05-16T17:20:45+01:57' asDateAndTime ' 2002-05-16T17:20:45-02:34' asDateAndTime ' 2002-05-16T17:20:45+00:00' asDateAndTime ' 1997-04-26T01:02:03+01:02:3' asDateAndTime " ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:09'! today ^ self midnight ! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:53'! year: year day: dayOfYear "Return a DateAndTime" ^ self year: year day: dayOfYear hour: 0 minute: 0 second: 0! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:54'! year: year month: month day: day "Return a DateAndTime, midnight local time" ^ self year: year month: month day: day hour: 0 minute: 0! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:54'! year: year month: month day: day hour: hour minute: minute "Return a DateAndTime" ^ self year: year month: month day: day hour: hour minute: minute second: 0! ! !DateAndTime class methodsFor: 'squeak protocol' stamp: 'brp 1/7/2004 15:39'! year: year month: month day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset "Return a DateAndTime" | monthIndex p q r s julianDayNumber since | monthIndex _ month isInteger ifTrue: [month] ifFalse: [Month indexOfMonth: month]. p _ (monthIndex - 14) quo: 12. q _ year + 4800 + p. r _ monthIndex - 2 - (12 * p). s _ (year + 4900 + p) quo: 100. julianDayNumber _ ( (1461 * q) quo: 4 ) + ( (367 * r) quo: 12 ) - ( (3 * s) quo: 4 ) + ( day - 32075 ). since _ Duration days: julianDayNumber hours: hour minutes: minute seconds: second nanoSeconds: nanoCount. ^ self basicNew ticks: since ticks offset: offset; yourself.! ! !DateAndTime class methodsFor: 'smalltalk-80' stamp: 'brp` 8/24/2003 19:09'! fromSeconds: seconds "Answer a DateAndTime since the Squeak epoch: 1 January 1901" | since | since _ Duration days: SqueakEpoch hours: 0 minutes: 0 seconds: seconds. ^ self basicNew ticks: since ticks offset: self localOffset; yourself. ! ! !DateAndTime class methodsFor: 'smalltalk-80' stamp: 'brp 8/24/2003 00:00'! millisecondClockValue ^ Time millisecondClockValue! ! !DateAndTime class methodsFor: 'smalltalk-80' stamp: 'brp 8/24/2003 00:01'! totalSeconds ^ Time totalSeconds! ! CodeHolder subclass: #Debugger instanceVariableNames: 'interruptedProcess interruptedController contextStack contextStackTop contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC sourceMap tempNames savedCursor isolationHead failedProject errorWasInUIProcess labelString theMethodNode' classVariableNames: 'ContextStackKeystrokes ErrorRecursion' poolDictionaries: '' category: 'Tools-Debugger'! !Debugger commentStamp: '<historical>' prior: 0! I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context. Special note on recursive errors: Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery. * A recursive error is detected. * The current project is queried for an isolationHead * Changes in the isolationHead are revoked * The parent project of isolated project is returned to * The debugger is opened there and execution resumes. If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. ! !Debugger methodsFor: 'initialize' stamp: 'RAA 1/30/2001 13:05'! buildMVCDebuggerViewLabel: aString minSize: aPoint "Build an MVC debugger view around the receiver, and return the StandardSystemView thus created." | topView stackListView stackCodeView rcvrVarView rcvrValView ctxtVarView ctxtValView deltaY underPane annotationPane buttonsView oldContextStackIndex | oldContextStackIndex _ contextStackIndex. self expandStack. "Sets contextStackIndex to zero." contextStackIndex _ oldContextStackIndex. topView _ StandardSystemView new model: self. topView borderWidth: 1. stackListView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #toggleContextStackIndex: menu: #contextStackMenu:shifted: keystroke: #contextStackKey:from:. stackListView menuTitleSelector: #messageListSelectorTitle. stackListView window: (0 @ 0 extent: 150 @ 50). topView addSubView: stackListView. deltaY _ 0. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 150@self optionalAnnotationHeight). topView addSubView: annotationPane below: stackListView. deltaY _ deltaY + self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [underPane _ stackListView]. self wantsOptionalButtons ifTrue: [buttonsView _ self buildMVCOptionalButtonsButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. deltaY _ deltaY + self optionalButtonHeight]. stackCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. stackCodeView window: (0 @ 0 extent: 150 @ (75 - deltaY)). topView addSubView: stackCodeView below: underPane. rcvrVarView _ PluggableListView on: self receiverInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. rcvrVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: rcvrVarView below: stackCodeView. rcvrValView _ PluggableTextView on: self receiverInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. rcvrValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: rcvrValView toRightOf: rcvrVarView. ctxtVarView _ PluggableListView on: self contextVariablesInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. ctxtVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: ctxtVarView toRightOf: rcvrValView. ctxtValView _ PluggableTextView on: self contextVariablesInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. ctxtValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: ctxtValView toRightOf: ctxtVarView. topView label: aString. topView minimumSize: aPoint. ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'sw 1/16/2002 20:03'! buildMVCNotifierButtonView | aView bHeight priorButton buttonView | aView _ View new model: self. bHeight _ self notifierButtonHeight. aView window: (0@0 extent: 350@bHeight). priorButton _ nil. self preDebugButtonQuads do: [:aSpec | buttonView _ PluggableButtonView on: self getState: nil action: aSpec second. buttonView label: aSpec first; insideColor: (Color perform: aSpec third) muchLighter lighter; borderWidthLeft: 1 right: 1 top: 0 bottom: 0; window: (0@0 extent: 117@bHeight). priorButton ifNil: [aView addSubView: buttonView] ifNotNil: [aView addSubView: buttonView toRightOf: priorButton]. priorButton _ buttonView]. ^ aView! ! !Debugger methodsFor: 'initialize' stamp: 'rhi 12/20/2000 16:50'! buildMVCNotifierViewLabel: aString message: messageString minSize: aPoint | topView notifyView buttonView x y bHeight | self expandStack. topView _ StandardSystemView new model: self. topView borderWidth: 1. buttonView _ self buildMVCNotifierButtonView. topView addSubView: buttonView. notifyView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #debugAt: menu: nil keystroke: nil. x _ 350 max: (aPoint x). y _ ((4 * 15) + 16) max: (aPoint y - 16 - self optionalButtonHeight). bHeight _ self optionalButtonHeight. y _ y - bHeight. notifyView window: (0@0 extent: x@y). topView addSubView: notifyView below: buttonView; label: aString; minimumSize: aPoint. ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'hmm 7/30/2001 17:25'! buildMVCOptionalButtonsButtonsView | aView bHeight offset aButtonView wid pairs windowWidth previousView | aView _ View new model: self. bHeight _ self optionalButtonHeight. windowWidth _ 150. aView window: (0@0 extent: windowWidth@bHeight). offset _ 0. pairs _ self optionalButtonPairs. previousView _ nil. pairs do: [:pair | aButtonView _ PluggableButtonView on: self getState: nil action: pair second. pair second = pairs last second ifTrue: [wid _ windowWidth - offset] ifFalse: [aButtonView borderWidthLeft: 0 right: 1 top: 0 bottom: 0. wid _ windowWidth // (pairs size)]. aButtonView label: pair first asParagraph; insideColor: Color red muchLighter lighter; window: (offset@0 extent: wid@bHeight). offset _ offset + wid. pair second = pairs first second ifTrue: [aView addSubView: aButtonView] ifFalse: [aView addSubView: aButtonView toRightOf: previousView]. previousView _ aButtonView]. ^ aView! ! !Debugger methodsFor: 'initialize' stamp: 'ab 2/25/2004 18:59'! customButtonSpecs "Answer an array of elements of the form wording, selector, help-message, that characterize the custom button row of a debugger." | list | list _ #(('Proceed' proceed 'close the debugger and proceed.') ('Restart' restart 'reset this context to its start.') ('Into' send 'step Into message sends') ('Over' doStep 'step Over message sends') ('Through' stepIntoBlock 'step into a block') ('Full Stack' fullStack 'show full stack') ('Where' where 'select current pc range')). Preferences restartAlsoProceeds ifTrue: [list _ list collect: [:each | each second == #restart ifTrue: [each copy at: 3 put: 'proceed from the beginning of this context.'; yourself] ifFalse: [each]]]. ^ list! ! !Debugger methodsFor: 'initialize' stamp: 'kfr 10/4/2000 22:13'! debugAt: anInteger self toggleContextStackIndex: anInteger. ^ self debug.! ! !Debugger methodsFor: 'initialize' stamp: 'tk 5/9/2003 11:20'! initialExtent "Make the full debugger longer!!" dependents size < 9 ifTrue: [^ super initialExtent]. "Pre debug window" RealEstateAgent standardWindowExtent y < 400 "a tiny screen" ifTrue: [^ super initialExtent]. ^ 600@700 ! ! !Debugger methodsFor: 'initialize' stamp: 'sw 12/28/1999 13:07'! notifierButtonHeight ^ 18! ! !Debugger methodsFor: 'initialize' stamp: 'BG 10/28/2003 20:40'! openFullNoSuspendLabel: aString "Create and schedule a full debugger with the given label. Do not terminate the current active process." | topView | topView _ self buildMVCDebuggerViewLabel: aString minSize: 300@200. topView controller openNoTerminate. ^ topView ! ! !Debugger methodsFor: 'initialize' stamp: 'BG 10/28/2003 20:39'! openNotifierContents: msgString label: label "Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired." "NOTE: When this method returns, a new process has been scheduled to run the windows, and thus this notifier, but the previous active porcess has not been suspended. The sender will do this." | msg topView p | Sensor flushKeyboard. savedCursor _ Sensor currentCursor. Sensor currentCursor: Cursor normal. (label beginsWith: 'Space is low') ifTrue: [msg _ self lowSpaceChoices, (msgString ifNil: [''])] ifFalse: [msg _ msgString]. isolationHead ifNotNil: ["We have already revoked the isolation layer -- now jump to the parent project." msg _ self isolationRecoveryAdvice, msgString. failedProject _ Project current. isolationHead parent enterForEmergencyRecovery]. Display fullScreen. topView _ self buildMVCNotifierViewLabel: label message: thisContext sender sender shortStack minSize: 350@((14 * 5) + 16 + self optionalButtonHeight). ScheduledControllers activeController ifNil: [p _ Display boundingBox center] ifNotNil: [p _ ScheduledControllers activeController view displayBox center]. topView controller openNoTerminateDisplayAt: (p max: (200@60)). ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'sbw 12/23/1999 09:50'! optionalAnnotationHeight ^ 10! ! !Debugger methodsFor: 'initialize' stamp: 'sbw 12/23/1999 08:31'! optionalButtonHeight ^ 10! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/3/2008 15:34'! optionalButtonPairs "Actually, return triples. In mvc (until someone deals with this) only the custom debugger-specific buttons are shown, but in morphic, the standard code-tool buttons are provided in addition to the custom buttons" ^ Smalltalk isMorphic ifFalse: [self customButtonSpecs] ifTrue: []! ! !Debugger methodsFor: 'initialize' stamp: 'mir 11/10/2003 15:13'! preDebugButtonQuads ^Preferences eToyFriendly ifTrue: [ #(('Store log' storeLog blue 'write a log of the encountered problem' ) ('Abandon' abandon black 'abandon this execution by closing this window') ('Debug' debug red 'bring up a debugger'))] ifFalse: [ #(('Proceed' proceed blue 'continue execution' ) ('Abandon' abandon black 'abandon this execution by closing this window') ('Debug' debug red 'bring up a debugger'))] ! ! !Debugger methodsFor: 'initialize' stamp: 'jm 8/20/1998 18:31'! release self windowIsClosing. super release. ! ! !Debugger methodsFor: 'initialize' stamp: 'sw 1/24/2001 21:22'! wantsOptionalButtons "The debugger benefits so majorly from the optional buttons that we put them up regardless of the global setting. Some traditionalists will want to change this method manually!!" ^ true! ! !Debugger methodsFor: 'initialize' stamp: 'ajh 3/5/2004 21:31'! windowIsClosing "My window is being closed; clean up. Restart the low space watcher." interruptedProcess == nil ifTrue: [^ self]. interruptedProcess terminate. interruptedProcess _ nil. interruptedController _ nil. contextStack _ nil. contextStackTop _ nil. receiverInspector _ nil. contextVariablesInspector _ nil. Smalltalk installLowSpaceWatcher. "restart low space handler" ! ! !Debugger methodsFor: 'accessing' stamp: 'di 10/9/1998 17:15'! contents "Depending on the current selection, different information is retrieved. Answer a string description of that information. This information is the method in the currently selected context." contents == nil ifTrue: [^ String new]. ^ contents copy! ! !Debugger methodsFor: 'accessing' stamp: 'ajh 3/5/2004 01:20'! contents: aText notifying: aController "The retrieved information has changed and its source must now be updated. In this case, the retrieved information is the method of the selected context." | selector classOfMethod category h ctxt | contextStackIndex = 0 ifTrue: [^ false]. self selectedContext isExecutingBlock ifTrue: [h := self selectedContext finalBlockHome. h ifNil: [self inform: 'Method not found for block, can''t edit'. ^ false]. (self confirm: 'I will have to revert to the method from which this block originated. Is that OK?') ifTrue: [self resetContext: h] ifFalse: [^ false]]. classOfMethod := self selectedClass. category := self selectedMessageCategoryName. selector := self selectedClass parserClass new parseSelector: aText. selector == self selectedMessageName ifFalse: [self inform: 'can''t change selector'. ^ false]. selector := classOfMethod compile: aText classified: category notifying: aController. selector ifNil: [^ false]. "compile cancelled" contents := aText. ctxt := interruptedProcess popTo: self selectedContext. ctxt == self selectedContext ifFalse: [ self inform: 'Method saved, but current context unchanged because of unwind error. Click OK to see error'. ] ifTrue: [ interruptedProcess restartTopWith: (classOfMethod compiledMethodAt: selector); stepToSendOrReturn. contextVariablesInspector object: nil. theMethodNode := Preferences browseWithPrettyPrint ifTrue: [ctxt methodNodeFormattedAndDecorated: Preferences colorWhenPrettyPrinting] ifFalse: [ctxt methodNode]. sourceMap := theMethodNode sourceMap. tempNames := theMethodNode tempNames. ]. self resetContext: ctxt. ^ true! ! !Debugger methodsFor: 'accessing'! contextVariablesInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context." ^contextVariablesInspector! ! !Debugger methodsFor: 'accessing'! interruptedContext "Answer the suspended context of the interrupted process." ^contextStackTop! ! !Debugger methodsFor: 'accessing' stamp: 'hmm 7/16/2001 21:54'! labelString ^labelString! ! !Debugger methodsFor: 'accessing' stamp: 'hmm 7/16/2001 21:54'! labelString: aString labelString _ aString. self changed: #relabel! ! !Debugger methodsFor: 'accessing'! proceedValue: anObject "Set the value to be returned to the selected context when the interrupted process proceeds." proceedValue _ anObject! ! !Debugger methodsFor: 'accessing'! receiver "Answer the receiver of the selected context, if any. Answer nil otherwise." contextStackIndex = 0 ifTrue: [^nil] ifFalse: [^self selectedContext receiver]! ! !Debugger methodsFor: 'accessing'! receiverInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context's receiver." ^receiverInspector! ! !Debugger methodsFor: 'notifier menu' stamp: 'BG 10/28/2003 20:40'! debug "Open a full DebuggerView." | topView | topView _ self topView. topView model: nil. "so close won't release me." topView controller controlTerminate. topView deEmphasize; erase. "a few hacks to get the scroll selection artifacts out when we got here by clicking in the list" topView subViewWantingControl ifNotNil: [ topView subViewWantingControl controller controlTerminate ]. topView controller status: #closed. self openFullNoSuspendLabel: topView label. topView controller closeAndUnscheduleNoErase. Processor terminateActive. ! ! !Debugger methodsFor: 'context stack (message list)'! contextStackIndex "Answer the index of the selected context." ^contextStackIndex! ! !Debugger methodsFor: 'context stack (message list)'! contextStackList "Answer the array of contexts." ^contextStackList! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'tk 4/17/1998 18:05'! expandStack "A Notifier is being turned into a full debugger. Show a substantial amount of stack in the context pane." self newStack: (contextStackTop stackOfSize: 20). contextStackIndex _ 0. receiverInspector _ Inspector inspect: nil. contextVariablesInspector _ ContextVariablesInspector inspect: nil. proceedValue _ nil! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ajh 9/25/2001 00:14'! fullyExpandStack "Expand the stack to include all of it, rather than the first four or five contexts." self okToChange ifFalse: [^ self]. self newStack: contextStackTop contextStack. self changed: #contextStackList! ! !Debugger methodsFor: 'context stack (message list)'! messageListIndex "Answer the index of the currently selected context." ^contextStackIndex! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'nk 2/20/2004 15:55'! selectedMessage "Answer the source code of the currently selected context." contents := theMethodNode sourceText. ^ contents := contents asText makeSelectorBold! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ajh 9/7/2002 21:15'! selectedMessageName "Answer the message selector of the currently selected context." ^self selectedContext methodSelector! ! !Debugger methodsFor: 'context stack (message list)'! toggleContextStackIndex: anInteger "If anInteger is the same as the index of the selected context, deselect it. Otherwise, the context whose index is anInteger becomes the selected context." self contextStackIndex: (contextStackIndex = anInteger ifTrue: [0] ifFalse: [anInteger]) oldContextWas: (contextStackIndex = 0 ifTrue: [nil] ifFalse: [contextStack at: contextStackIndex])! ! !Debugger methodsFor: 'context stack menu' stamp: 'sw 12/28/1999 13:04'! abandon "abandon the debugger from its pre-debug notifier" self abandon: self topView! ! !Debugger methodsFor: 'context stack menu' stamp: 'sw 12/28/1999 13:05'! abandon: aTopView "abandon the notifier represented by aTopView" aTopView controller close! ! !Debugger methodsFor: 'context stack menu' stamp: 'sd 3/4/2004 20:39'! askForCategoryIn: aClass default: aString | categories index category | categories := OrderedCollection with: 'new ...'. categories addAll: (aClass allMethodCategoriesIntegratedThrough: Object). index := PopUpMenu withCaption: 'Please provide a good category for the new method!!' translated chooseFrom: categories. index = 0 ifTrue: [^ aString]. category := index = 1 ifTrue: [FillInTheBlank request: 'Enter category name:'] ifFalse: [categories at: index]. ^ category isEmpty ifTrue: [^ aString] ifFalse: [category]! ! !Debugger methodsFor: 'context stack menu' stamp: 'wod 5/15/1998 00:24'! browseMessages "Present a menu of all messages sent by the currently selected message. Open a message set browser of all implementors of the message chosen. Do nothing if no message is chosen." contextStackIndex = 0 ifTrue: [^ self]. super browseMessages.! ! !Debugger methodsFor: 'context stack menu' stamp: 'wod 5/15/1998 00:23'! browseSendersOfMessages "Present a menu of the currently selected message, as well as all messages sent by it. Open a message set browser of all implementors of the message chosen." contextStackIndex = 0 ifTrue: [^ self]. super browseSendersOfMessages! ! !Debugger methodsFor: 'context stack menu' stamp: 'sw 9/14/2001 00:26'! browseVersions "Create and schedule a message set browser on all versions of the currently selected message selector." | class selector | class _ self selectedClassOrMetaClass. selector _ self selectedMessageName. VersionsBrowser browseVersionsOf: (class compiledMethodAt: selector) class: self selectedClass theNonMetaClass meta: class isMeta category: self selectedMessageCategoryName selector: selector! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/6/98 23:00'! buildMessageBrowser "Create and schedule a message browser on the current method." contextStackIndex = 0 ifTrue: [^ self]. ^ Browser openMessageBrowserForClass: self selectedClassOrMetaClass selector: self selectedMessageName editString: nil! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/18/1998 09:24'! contextStackKey: aChar from: view "Respond to a keystroke in the context list" | selector | selector _ ContextStackKeystrokes at: aChar ifAbsent: [nil]. selector ifNil: [self messageListKey: aChar from: view] ifNotNil: [self perform: selector]! ! !Debugger methodsFor: 'context stack menu' stamp: 'ssa 9/3/2008 11:23'! contextStackMenu: aMenu shifted: shifted "Set up the menu appropriately for the context-stack-list, either shifted or unshifted as per the parameter provided" ^ shifted ifFalse: [self selectedContext selector = #doesNotUnderstand: ifTrue: [aMenu add: 'implement in...' subMenu: (self populateImplementInMenu: (Smalltalk isMorphic ifTrue: [] ifFalse: [CustomMenu new])) target: nil selector: nil argumentList: #(nil)]. aMenu labels: 'fullStack (f) restart (r) proceed (p) step (t) step through (T) send (e) where (w) peel to first like this senders of... (n) implementors of... (m) inheritance (i) versions (v) inst var refs... inst var defs... class var refs... class variables class refs (N) browse full (b) file out more...' lines: #(8 12 14 17 20) selections: #(fullStack restart proceed doStep stepIntoBlock send where peelToFirst browseSendersOfMessages browseMessages methodHierarchy browseVersions browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables browseClassRefs browseMethodFull fileOutMessage shiftedYellowButtonActivity)] ifTrue: [aMenu labels: 'browse class hierarchy browse class browse method (O) implementors of sent messages change sets with this method inspect instances inspect subinstances revert to previous version remove from current change set revert & remove from changes more...' lines: #(5 7 10) selections: #(classHierarchy browseClass openSingleMessageBrowser browseAllMessages findMethodInChangeSets inspectInstances inspectSubInstances revertToPreviousVersion removeFromCurrentChanges revertAndForget unshiftedYellowButtonActivity)] ! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 7/6/2003 21:06'! doStep "Send the selected message in the accessed method, and regain control after the invoked method returns." | currentContext newContext | self okToChange ifFalse: [^ self]. self checkContextSelection. currentContext _ self selectedContext. newContext _ interruptedProcess completeStep: currentContext. newContext == currentContext ifTrue: [ newContext _ interruptedProcess stepToSendOrReturn]. self contextStackIndex > 1 ifTrue: [self resetContext: newContext] ifFalse: [newContext == currentContext ifTrue: [self changed: #contentsSelection. self updateInspectors] ifFalse: [self resetContext: newContext]]. ! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/15/1998 16:55'! down "move down the context stack to the previous (enclosing) context" self toggleContextStackIndex: contextStackIndex+1! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/17/1998 18:06'! fullStack "Change from displaying the minimal stack to a full one." self contextStackList size > 20 "Already expanded" ifTrue: [self changed: #flash] ifFalse: [self contextStackIndex = 0 ifFalse: [ self toggleContextStackIndex: self contextStackIndex]. self fullyExpandStack]! ! !Debugger methodsFor: 'context stack menu' stamp: 'sd 3/4/2004 20:39'! implement: aMessage inClass: aClass | category | category := self askForCategoryIn: aClass default: 'as yet unclassified'. aClass compile: aMessage createStubMethod classified: category. self selectedContext privRefreshWith: (aClass lookupSelector: aMessage selector). self resetContext: self selectedContext. self contextStackIndex: 1 oldContextWas: nil ! ! !Debugger methodsFor: 'context stack menu' stamp: 'sw 3/16/2001 17:20'! messageListMenu: aMenu shifted: shifted "The context-stack menu takes the place of the message-list menu in the debugger, so pass it on" ^ self contextStackMenu: aMenu shifted: shifted! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 3/4/2004 23:10'! peelToFirst "Peel the stack back to the second occurance of the currently selected message. Very useful for an infinite recursion. Gets back to the second call so you can see one complete recursion cycle, and how it was called at the beginning. Also frees a lot of space!!" | upperGuy meth second ctxt | contextStackIndex = 0 ifTrue: [^ Beeper beep]. "self okToChange ifFalse: [^ self]." upperGuy _ contextStack at: contextStackIndex. meth _ upperGuy method. contextStackIndex+1 to: contextStack size do: [:ind | (contextStack at: ind) method == meth ifTrue: [ second _ upperGuy. upperGuy _ contextStack at: ind]]. second ifNil: [second _ upperGuy]. ctxt _ interruptedProcess popTo: self selectedContext. ctxt == self selectedContext ifTrue: [self resetContext: second] ifFalse: [self resetContext: ctxt]. "unwind error" ! ! !Debugger methodsFor: 'context stack menu' stamp: 'ads 2/20/2003 08:46'! populateImplementInMenu: aMenu | msg | msg _ self selectedContext at: 1. self selectedContext receiver class withAllSuperclasses do: [:each | aMenu add: each name target: self selector: #implement:inClass: argumentList: (Array with: msg with: each)]. ^ aMenu ! ! !Debugger methodsFor: 'context stack menu' stamp: 'di 5/5/1998 00:07'! proceed "Proceed execution of the receiver's model, starting after the expression at which an interruption occurred." Smalltalk okayToProceedEvenIfSpaceIsLow ifTrue: [ self proceed: self topView]. ! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 1/24/2003 12:29'! proceed: aTopView "Proceed from the interrupted state of the currently selected context. The argument is the topView of the receiver. That view is closed." self okToChange ifFalse: [^ self]. self checkContextSelection. self resumeProcess: aTopView! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 3/4/2004 23:14'! restart "Proceed from the initial state of the currently selected context. The argument is a controller on a view of the receiver. That view is closed." "Closing now depends on a preference #restartAlsoProceeds - hmm 9/7/2001 16:46" | ctxt noUnwindError | self okToChange ifFalse: [^ self]. self checkContextSelection. ctxt _ interruptedProcess popTo: self selectedContext. noUnwindError _ false. ctxt == self selectedContext ifTrue: [ noUnwindError _ true. interruptedProcess restartTop; stepToSendOrReturn]. self resetContext: ctxt. (Preferences restartAlsoProceeds and: [noUnwindError]) ifTrue: [self proceed]. ! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 1/24/2003 12:29'! send "Send the selected message in the accessed method, and take control in the method invoked to allow further step or send." self okToChange ifFalse: [^ self]. self checkContextSelection. interruptedProcess step: self selectedContext. self resetContext: interruptedProcess stepToSendOrReturn. ! ! !Debugger methodsFor: 'context stack menu' stamp: 'ajh 1/24/2003 12:46'! stepIntoBlock "Send messages until you return to the present method context. Used to step into a block in the method." interruptedProcess stepToHome: self selectedContext. self resetContext: interruptedProcess stepToSendOrReturn.! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/15/1998 16:55'! up "move up the context stack to the next (enclosed) context" contextStackIndex > 1 ifTrue: [self toggleContextStackIndex: contextStackIndex-1]! ! !Debugger methodsFor: 'context stack menu' stamp: 'nk 2/6/2001 19:34'! where "Select the expression whose evaluation was interrupted." selectingPC _ true. self contextStackIndex: contextStackIndex oldContextWas: self selectedContext ! ! !Debugger methodsFor: 'code pane' stamp: 'tk 4/15/1998 18:31'! contentsSelection ^ self pcRange! ! !Debugger methodsFor: 'code pane'! doItContext "Answer the context in which a text selection can be evaluated." contextStackIndex = 0 ifTrue: [^super doItContext] ifFalse: [^self selectedContext]! ! !Debugger methodsFor: 'code pane'! doItReceiver "Answer the object that should be informed of the result of evaluating a text selection." ^self receiver! ! !Debugger methodsFor: 'code pane' stamp: 'tk 5/2/1998 10:04'! pc ^ self pcRange! ! !Debugger methodsFor: 'code pane' stamp: 'nk 2/20/2004 15:35'! pcRange "Answer the indices in the source code for the method corresponding to the selected context's program counter value." | i pc end | (selectingPC and: [contextStackIndex ~= 0]) ifFalse: [^1 to: 0]. sourceMap ifNil: [sourceMap _ theMethodNode sourceMap. tempNames _ theMethodNode tempNames. self selectedContext method cacheTempNames: tempNames]. (sourceMap size = 0 or: [ self selectedContext isDead ]) ifTrue: [^1 to: 0]. Smalltalk at: #RBProgramNode ifPresent:[:nodeClass| (theMethodNode isKindOf: nodeClass) ifTrue: [ pc _ contextStackIndex = 1 ifTrue: [self selectedContext pc] ifFalse: [self selectedContext previousPc]. i _ sourceMap findLast:[:pcRange | pcRange key <= pc]. i = 0 ifTrue:[^ 1 to: 0]. ^ (sourceMap at: i) value ]. ]. pc_ self selectedContext pc - (("externalInterrupt" true and: [contextStackIndex=1]) ifTrue: [1] ifFalse: [2]). i _ sourceMap indexForInserting: (Association key: pc value: nil). i < 1 ifTrue: [^1 to: 0]. i > sourceMap size ifTrue: [end _ sourceMap inject: 0 into: [:prev :this | prev max: this value last]. ^ end+1 to: end]. ^(sourceMap at: i) value! ! !Debugger methodsFor: 'code pane menu' stamp: 'tk 4/17/1998 17:25'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." | result | (#(debug proceed) includes: selector) "When I am a notifier window" ifTrue: [^ self perform: selector] ifFalse: [result _ super perform: selector orSendTo: otherTarget. selector == #doIt ifTrue: [ result ~~ #failedDoit ifTrue: [self proceedValue: result]]. ^ result]! ! !Debugger methodsFor: 'message category list'! selectedMessageCategoryName "Answer the name of the message category of the message of the currently selected context." ^self selectedClass organization categoryOfElement: self selectedMessageName! ! !Debugger methodsFor: 'class list'! selectedClass "Answer the class in which the currently selected context's method was found." ^self selectedContext mclass! ! !Debugger methodsFor: 'class list'! selectedClassOrMetaClass "Answer the class in which the currently selected context's method was found." ^self selectedContext mclass! ! !Debugger methodsFor: 'dependents access' stamp: 'di 1/14/1999 09:28'! step "Update the inspectors." receiverInspector ifNotNil: [receiverInspector step]. contextVariablesInspector ifNotNil: [contextVariablesInspector step]. ! ! !Debugger methodsFor: 'dependents access' stamp: 'hmm 7/15/2001 19:48'! updateInspectors "Update the inspectors on the receiver's variables." receiverInspector == nil ifFalse: [receiverInspector update]. contextVariablesInspector == nil ifFalse: [contextVariablesInspector update]! ! !Debugger methodsFor: 'dependents access' stamp: 'di 1/14/1999 09:25'! wantsSteps ^ true! ! !Debugger methodsFor: 'private' stamp: 'yo 8/12/2003 16:34'! checkContextSelection contextStackIndex = 0 ifTrue: [self contextStackIndex: 1 oldContextWas: nil]. ! ! !Debugger methodsFor: 'private' stamp: 'nk 2/20/2004 16:51'! contextStackIndex: anInteger oldContextWas: oldContext "Change the context stack index to anInteger, perhaps in response to user selection." | newMethod | contextStackIndex := anInteger. anInteger = 0 ifTrue: [currentCompiledMethod := theMethodNode := tempNames := sourceMap := contents := nil. self changed: #contextStackIndex. self decorateButtons. self contentsChanged. contextVariablesInspector object: nil. receiverInspector object: self receiver. ^ self]. (newMethod := oldContext == nil or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)]) ifTrue: [tempNames := sourceMap := nil. theMethodNode := Preferences browseWithPrettyPrint ifTrue: [ self selectedContext methodNodeFormattedAndDecorated: Preferences colorWhenPrettyPrinting ] ifFalse: [ self selectedContext methodNode ]. contents := self selectedMessage. self contentsChanged. self pcRange "will compute tempNamesunless noFrills"]. self changed: #contextStackIndex. self decorateButtons. tempNames == nil ifTrue: [tempNames := self selectedClassOrMetaClass parserClass new parseArgsAndTemps: contents notifying: nil]. contextVariablesInspector object: self selectedContext. receiverInspector object: self receiver. newMethod ifFalse: [self changed: #contentsSelection]! ! !Debugger methodsFor: 'private'! externalInterrupt: aBoolean externalInterrupt _ aBoolean ! ! !Debugger methodsFor: 'private' stamp: 'tk 8/17/2000 15:36'! isolationRecoveryAdvice "Return a notifier message string to be presented in case of recovery from recursive error by revoking the changes in an isolation layer. This surely ranks as one of Squeak's longer help messages." ^ 'Warning!! You have encountered a recursive error situation. Don''t panic, but do read the following advice. If you were just fooling around, the simplest thing to do is to quit and NOT save, and restart Squeak. If you care about recovery, then read on... In the process of diagnosing one error, further errors occurred, making it impossible to give you a debugger to work with. Squeak has jumped to an outer project where many of the objects and code changes that might have caused this problem are not involved in normal operation. If you are looking at this window, chances are that this first level of recovery was successful. If there are changes you care a lot about, try to save them now. Then, hopefully, from the state in this debugger, you can determine what the problem was and fix it. Do not save this image until you are confident of its recovery. You are no longer in the world that is damaged. The two most likely causes of recursive errors are malformed objects (for instance a corrupt value encountered in any display of the desktop) and recurring code errors (such as a change that causes errors in any attempt to display the desktop). In the case of malformed objects, you can attempt to repair them by altering various bindings in the corrupted environment. Open this debugger and examine the state of the objects closest to the error. In the case of code errors, note that you are no longer in a world where the erroneous code is in effect. The only simple option available is for you to browse to the changeSet for the project in distress, and remove one or more of the changes (later it will be possible to edit the code remotely from here). If you feel you have repaired the problem, then you may proceed from this debugger. This will put you back in the project that failed with the changes that failed for another try. Note that the debugger from which you are proceeding is the second one that occurred; you will likely find the first one waiting for you when you reenter the failed project!! Also note that if your error occurred while displaying a morph, it may now be flagged as undisplayable (red with yellow cross); if so, use the morph debug menu to choose ''start drawing again''. If you have not repaired the problem, you should close this debugger and delete the failed project after retrieving whatever may be of value in it. Good luck. - The Squeak Fairy Godmother PS: If you feel you need the help of a quantum mechanic, do NOT close this window. Instead, the best thing to do (after saving anything that seems safe to save) would be to use the ''save as...'' command in the world menu, and give it a new image name, such as OOPS. There is a good chance that someone who knows their way around Squeak can help you out. '! ! !Debugger methodsFor: 'private' stamp: 'jm 5/1/1998 16:20'! lowSpaceChoices "Return a notifier message string to be presented when space is running low." ^ 'Warning!! Squeak is almost out of memory!! Low space detection is now disabled. It will be restored when you close or proceed from this error notifier. Don''t panic, but do proceed with caution. Here are some suggestions: If you suspect an infinite recursion (the same methods calling each other again and again), then close this debugger, and fix the problem. If you want this computation to finish, then make more space available (read on) and choose "proceed" in this debugger. Here are some ways to make more space available... > Close any windows that are not needed. > Get rid of some large objects (e.g., images). > Leave this window on the screen, choose "save as..." from the screen menu, quit, restart the Squeak VM with a larger memory allocation, then restart the image you just saved, and choose "proceed" in this window. If you want to investigate further, choose "debug" in this window. Do not use the debugger "fullStack" command unless you are certain that the stack is not very deep. (Trying to show the full stack will definitely use up all remaining memory if the low-space problem is caused by an infinite recursion!!). ' ! ! !Debugger methodsFor: 'private'! newStack: stack | oldStack diff | oldStack _ contextStack. contextStack _ stack. (oldStack == nil or: [oldStack last ~~ stack last]) ifTrue: [contextStackList _ contextStack collect: [:ctx | ctx printString]. ^ self]. "May be able to re-use some of previous list" diff _ stack size - oldStack size. contextStackList _ diff <= 0 ifTrue: [contextStackList copyFrom: 1-diff to: oldStack size] ifFalse: [diff > 1 ifTrue: [contextStack collect: [:ctx | ctx printString]] ifFalse: [(Array with: stack first printString) , contextStackList]]! ! !Debugger methodsFor: 'private' stamp: 'di 4/14/2000 16:24'! process: aProcess controller: aController context: aContext ^ self process: aProcess controller: aController context: aContext isolationHead: nil! ! !Debugger methodsFor: 'private' stamp: 'ssa 9/3/2008 11:03'! process: aProcess controller: aController context: aContext isolationHead: projectOrNil super initialize. Smalltalk at: #MessageTally ifPresentAndInMemory: [:c | c new close]. contents _ nil. interruptedProcess _ aProcess. interruptedController _ aController. contextStackTop _ aContext. self newStack: (contextStackTop stackOfSize: 1). contextStackIndex _ 1. externalInterrupt _ false. selectingPC _ true. isolationHead _ projectOrNil. ! ! !Debugger methodsFor: 'private' stamp: 'ajh 9/25/2001 00:14'! resetContext: aContext "Used when a new context becomes top-of-stack, for instance when the method of the selected context is re-compiled, or the simulator steps or returns to a new method. There is room for much optimization here, first to save recomputing the whole stack list (and text), and secondly to avoid recomposing all that text (by editing the paragraph instead of recreating it)." | oldContext | oldContext _ self selectedContext. contextStackTop _ aContext. self newStack: contextStackTop contextStack. self changed: #contextStackList. self contextStackIndex: 1 oldContextWas: oldContext. self changed: #content.! ! !Debugger methodsFor: 'private' stamp: 'ssa 9/3/2008 11:04'! resumeProcess: aTopView Smalltalk isMorphic ifFalse: [aTopView erase]. savedCursor ifNotNil: [Sensor currentCursor: savedCursor]. isolationHead ifNotNil: [failedProject enterForEmergencyRecovery. isolationHead invoke. isolationHead _ nil]. interruptedProcess isTerminated ifFalse: [ Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers activeControllerNoTerminate: interruptedController andProcess: interruptedProcess]]. "if old process was terminated, just terminate current one" interruptedProcess _ nil. "Before delete, so release doesn't terminate it" Smalltalk isMorphic ifTrue: [] ifFalse: [aTopView controller closeAndUnscheduleNoErase]. Smalltalk installLowSpaceWatcher. "restart low space handler" errorWasInUIProcess == false ifFalse: [Processor terminateActive]! ! !Debugger methodsFor: 'private'! selectedContext contextStackIndex = 0 ifTrue: [^contextStackTop] ifFalse: [^contextStack at: contextStackIndex]! ! !Debugger methodsFor: 'as yet unclassified' stamp: 'nk 8/6/2003 13:52'! codePaneMenu: aMenu shifted: shifted aMenu add: 'run to here' target: self selector: #runToSelection: argument: thisContext sender receiver selectionInterval. aMenu addLine. super codePaneMenu: aMenu shifted: shifted. ^aMenu.! ! !Debugger methodsFor: 'as yet unclassified' stamp: 'nk 5/31/2003 07:38'! runToSelection: selectionInterval | currentContext | self pc first >= selectionInterval first ifTrue: [ ^self ]. currentContext _ self selectedContext. [ currentContext == self selectedContext and: [ self pc first < selectionInterval first ] ] whileTrue: [ self doStep ].! ! !Debugger methodsFor: 'breakpoints' stamp: 'emm 5/30/2002 10:08'! toggleBreakOnEntry "Install or uninstall a halt-on-entry breakpoint" | selectedMethod | self selectedClassOrMetaClass isNil ifTrue:[^self]. selectedMethod := self selectedClassOrMetaClass >> self selectedMessageName. selectedMethod hasBreakpoint ifTrue: [BreakpointManager unInstall: selectedMethod] ifFalse: [BreakpointManager installInClass: self selectedClassOrMetaClass selector: self selectedMessageName].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Debugger class instanceVariableNames: ''! !Debugger class methodsFor: 'class initialization' stamp: 'hg 9/29/2001 20:24'! initialize ErrorRecursion _ false. ContextStackKeystrokes _ Dictionary new at: $e put: #send; at: $t put: #doStep; at: $T put: #stepIntoBlock; at: $p put: #proceed; at: $r put: #restart; at: $f put: #fullStack; at: $w put: #where; yourself. "Debugger initialize"! ! !Debugger class methodsFor: 'class initialization' stamp: 'BG 10/30/2003 20:37'! openContext: aContext label: aString contents: contentsStringOrNil | isolationHead | "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." <primitive: 19> "Simulation guard" ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue: [Smalltalk logError: aString inContext: aContext to: 'SqueakDebug.log']. ErrorRecursion ifTrue: [ErrorRecursion _ false. "(isolationHead _ CurrentProjectRefactoring currentIsolationHead) ifNil: [self primitiveError: aString] ifNotNil: [isolationHead revoke]"]. ErrorRecursion _ true. self informExistingDebugger: aContext label: aString. (Debugger context: aContext isolationHead: nil) openNotifierContents: contentsStringOrNil label: aString. ErrorRecursion _ false. Processor activeProcess suspend. ! ! !Debugger class methodsFor: 'instance creation' stamp: 'di 4/14/2000 16:29'! context: aContext "Answer an instance of me for debugging the active process starting with the given context." ^ self context: aContext isolationHead: nil! ! !Debugger class methodsFor: 'instance creation' stamp: 'di 4/14/2000 16:29'! context: aContext isolationHead: isolationHead "Answer an instance of me for debugging the active process starting with the given context." ^ self new process: Processor activeProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: aContext isolationHead: isolationHead ! ! !Debugger class methodsFor: 'instance creation' stamp: 'hmm 8/3/2001 13:05'! informExistingDebugger: aContext label: aString "Walking the context chain, we try to find out if we're in a debugger stepping situation. If we find the relevant contexts, we must rearrange them so they look just like they would if the methods were excuted outside of the debugger." | ctx quickStepMethod oldSender baseContext | ctx _ thisContext. quickStepMethod _ ContextPart compiledMethodAt: #quickSend:to:with:super:. [ctx sender == nil or: [ctx sender method == quickStepMethod]] whileFalse: [ctx _ ctx sender]. ctx sender == nil ifTrue: [^self]. baseContext _ ctx. "baseContext is now the context created by the #quickSend... method." oldSender _ ctx _ ctx sender home sender. "oldSender is the context which originally sent the #quickSend... method" [ctx == nil or: [ctx receiver isKindOf: self]] whileFalse: [ctx _ ctx sender]. ctx == nil ifTrue: [^self]. "ctx is the context of the Debugger method #doStep" ctx receiver labelString: aString. ctx receiver externalInterrupt: false; proceedValue: aContext receiver. baseContext swapSender: baseContext sender sender sender. "remove intervening contexts" thisContext swapSender: oldSender. "make myself return to debugger" ErrorRecursion _ false. ^aContext! ! !Debugger class methodsFor: 'opening' stamp: 'hg 10/2/2001 20:45'! openInterrupt: aString onProcess: interruptedProcess "Open a notifier in response to an interrupt. An interrupt occurs when the user types the interrupt key (cmd-. on Macs, ctrl-c or alt-. on other systems) or when the low-space watcher detects that memory is low." | debugger | <primitive: 19> "Simulation guard" debugger _ self new. debugger process: interruptedProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers activeControllerProcess == interruptedProcess]) ifTrue: [ScheduledControllers activeController]) context: interruptedProcess suspendedContext. debugger externalInterrupt: true. Preferences logDebuggerStackToFile ifTrue: [(aString includesSubString: 'Space') & (aString includesSubString: 'low') ifTrue: [ Smalltalk logError: aString inContext: debugger interruptedContext to:'LowSpaceDebug.log']]. ^ debugger openNotifierContents: nil label: aString ! ! !Debugger class methodsFor: 'opening' stamp: 'ssa 9/3/2008 11:06'! openOn: process context: context label: title contents: contentsStringOrNil fullView: bool "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." | controller | Smalltalk isMorphic ifTrue: [] ifFalse: [controller _ ScheduledControllers activeControllerProcess == process ifTrue: [ScheduledControllers activeController]]. [ [ | debugger | debugger _ self new process: process controller: controller context: context. bool ifTrue: [debugger openFullNoSuspendLabel: title] ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]. Preferences logDebuggerStackToFile ifTrue: [ Smalltalk logError: title inContext: context to: 'SqueakDebug.log']. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"]. ] on: Error do: [:ex | self primitiveError: 'Orginal error: ', title asString, '. Debugger error: ', ([ex description] on: Error do: ['a ', ex class printString]), ':' ] ] fork. process suspend. ! ! InstructionStream subclass: #Decompiler instanceVariableNames: 'constructor method instVars tempVars constTable stack statements lastPc exit lastJumpPc lastReturnPc limit hasValue blockStackBase' classVariableNames: 'ArgumentFlag CascadeFlag CaseFlag IfNilFlag' poolDictionaries: '' category: 'System-Compiler'! !Decompiler commentStamp: '<historical>' prior: 0! I decompile a method in three phases: Reverser: postfix byte codes -> prefix symbolic codes (nodes and atoms) Parser: prefix symbolic codes -> node tree (same as the compiler) Printer: node tree -> text (done by the nodes)! !Decompiler methodsFor: 'initialize-release' stamp: 'ajh 7/21/2003 01:14'! initSymbols: aClass | nTemps namedTemps | constructor method: method class: aClass literals: method literals. constTable _ constructor codeConstants. instVars _ Array new: aClass instSize. nTemps _ method numTemps. namedTemps _ tempVars ifNil: [method tempNames]. tempVars _ (1 to: nTemps) collect: [:i | i <= namedTemps size ifTrue: [constructor codeTemp: i - 1 named: (namedTemps at: i)] ifFalse: [constructor codeTemp: i - 1]]! ! !Decompiler methodsFor: 'initialize-release'! withTempNames: tempNameArray tempVars _ tempNameArray! ! !Decompiler methodsFor: 'control' stamp: 'tao 8/20/97 22:51'! blockForCaseTo: end "Decompile a range of code as in statementsForCaseTo:, but return a block node." | exprs block oldBase | oldBase _ blockStackBase. blockStackBase _ stack size. exprs _ self statementsForCaseTo: end. block _ constructor codeBlock: exprs returns: lastReturnPc = lastPc. blockStackBase _ oldBase. lastReturnPc _ -1. "So as not to mislead outer calls" ^block! ! !Decompiler methodsFor: 'control'! blockTo: end "Decompile a range of code as in statementsTo:, but return a block node." | exprs block oldBase | oldBase _ blockStackBase. blockStackBase _ stack size. exprs _ self statementsTo: end. block _ constructor codeBlock: exprs returns: lastReturnPc = lastPc. blockStackBase _ oldBase. lastReturnPc _ -1. "So as not to mislead outer calls" ^block! ! !Decompiler methodsFor: 'control'! checkForBlock: receiver "We just saw a blockCopy: message. Check for a following block." | savePc jump args argPos block | receiver == constructor codeThisContext ifFalse: [^false]. savePc _ pc. (jump _ self interpretJump) notNil ifFalse: [pc _ savePc. ^nil]. "Definitely a block" jump _ jump + pc. argPos _ statements size. [self willStorePop] whileTrue: [stack addLast: ArgumentFlag. "Flag for doStore:" self interpretNextInstructionFor: self]. args _ Array new: statements size - argPos. 1 to: args size do: "Retrieve args" [:i | args at: i put: statements removeLast. (args at: i) scope: -1 "flag args as block temps"]. block _ self blockTo: jump. stack addLast: (constructor codeArguments: args block: block). ^true! ! !Decompiler methodsFor: 'control' stamp: 'tao 8/20/97 22:51'! statementsForCaseTo: end "Decompile the method from pc up to end and return an array of expressions. If at run time this block will leave a value on the stack, set hasValue to true. If the block ends with a jump or return, set exit to the destination of the jump, or the end of the method; otherwise, set exit = end. Leave pc = end. Note that stack initially contains a CaseFlag which will be removed by a subsequent Pop instruction, so adjust the StackPos accordingly." | blockPos stackPos t | blockPos _ statements size. stackPos _ stack size - 1. "Adjust for CaseFlag" [pc < end] whileTrue: [lastPc _ pc. limit _ end. "for performs" self interpretNextInstructionFor: self]. "If there is an additional item on the stack, it will be the value of this block." (hasValue _ stack size > stackPos) ifTrue: [statements addLast: stack removeLast]. lastJumpPc = lastPc ifFalse: [exit _ pc]. ^self popTo: blockPos! ! !Decompiler methodsFor: 'control'! statementsTo: end "Decompile the method from pc up to end and return an array of expressions. If at run time this block will leave a value on the stack, set hasValue to true. If the block ends with a jump or return, set exit to the destination of the jump, or the end of the method; otherwise, set exit = end. Leave pc = end." | blockPos stackPos t | blockPos _ statements size. stackPos _ stack size. [pc < end] whileTrue: [lastPc _ pc. limit _ end. "for performs" self interpretNextInstructionFor: self]. "If there is an additional item on the stack, it will be the value of this block." (hasValue _ stack size > stackPos) ifTrue: [statements addLast: stack removeLast]. lastJumpPc = lastPc ifFalse: [exit _ pc]. ^self popTo: blockPos! ! !Decompiler methodsFor: 'instruction decoding'! blockReturnTop "No action needed"! ! !Decompiler methodsFor: 'instruction decoding' stamp: 'md 11/14/2003 16:28'! case: dist "statements = keyStmts CascadeFlag keyValueBlock ... keyStmts" | nextCase end thenJump stmtStream elements b node cases otherBlock | nextCase _ pc + dist. end _ limit. "Now add CascadeFlag & keyValueBlock to statements" statements addLast: stack removeLast. stack addLast: CaseFlag. "set for next pop" statements addLast: (self blockForCaseTo: nextCase). stack last == CaseFlag ifTrue: "Last case" ["ensure jump is within block (in case thenExpr returns wierdly I guess)" stack removeLast. "get rid of CaseFlag" thenJump _ exit <= end ifTrue: [exit] ifFalse: [nextCase]. stmtStream _ ReadStream on: (self popTo: stack removeLast). elements _ OrderedCollection new. b _ OrderedCollection new. [stmtStream atEnd] whileFalse: [(node _ stmtStream next) == CascadeFlag ifTrue: [elements addLast: (constructor codeMessage: (constructor codeBlock: b returns: false) selector: (constructor codeSelector: #-> code: #macro) arguments: (Array with: stmtStream next)). b _ OrderedCollection new] ifFalse: [b addLast: node]]. b size > 0 ifTrue: [self error: 'Bad cases']. cases _ constructor codeBrace: elements. otherBlock _ self blockTo: thenJump. stack addLast: (constructor codeMessage: stack removeLast selector: (constructor codeSelector: #caseOf:otherwise: code: #macro) arguments: (Array with: cases with: otherBlock))]! ! !Decompiler methodsFor: 'instruction decoding'! doDup stack last == CascadeFlag ifFalse: ["Save position and mark cascade" stack addLast: statements size. stack addLast: CascadeFlag]. stack addLast: CascadeFlag! ! !Decompiler methodsFor: 'instruction decoding' stamp: 'di 2/5/2000 09:34'! doPop stack isEmpty ifTrue: ["Ignore pop in first leg of ifNil for value" ^ self]. stack last == CaseFlag ifTrue: [stack removeLast] ifFalse: [statements addLast: stack removeLast].! ! !Decompiler methodsFor: 'instruction decoding'! doStore: stackOrBlock "Only called internally, not from InstructionStream. StackOrBlock is stack for store, statements for storePop." | var expr | var _ stack removeLast. expr _ stack removeLast. stackOrBlock addLast: (expr == ArgumentFlag ifTrue: [var] ifFalse: [constructor codeAssignTo: var value: expr])! ! !Decompiler methodsFor: 'instruction decoding'! jump: dist exit _ pc + dist. lastJumpPc _ lastPc! ! !Decompiler methodsFor: 'instruction decoding' stamp: 'di 2/6/2000 08:46'! jump: dist if: condition | savePc elseDist sign elsePc elseStart end cond ifExpr thenBlock elseBlock thenJump elseJump condHasValue b isIfNil saveStack | stack last == CascadeFlag ifTrue: [^ self case: dist]. elsePc _ lastPc. elseStart _ pc + dist. end _ limit. "Check for bfp-jmp to invert condition. Don't be fooled by a loop with a null body." sign _ condition. savePc _ pc. ((elseDist _ self interpretJump) notNil and: [elseDist >= 0 and: [elseStart = pc]]) ifTrue: [sign _ sign not. elseStart _ pc + elseDist]. pc _ savePc. ifExpr _ stack removeLast. (stack size > 0 and: [stack last == IfNilFlag]) ifTrue: [stack removeLast. isIfNil _ true] ifFalse: [isIfNil _ false]. saveStack _ stack. stack _ OrderedCollection new. thenBlock _ self blockTo: elseStart. condHasValue _ hasValue or: [isIfNil]. "ensure jump is within block (in case thenExpr returns)" thenJump _ exit <= end ifTrue: [exit] ifFalse: [elseStart]. "if jump goes back, then it's a loop" thenJump < elseStart ifTrue: ["Must be a while loop... thenJump will jump to the beginning of the while expr. In the case of while's with a block in the condition, the while expr should include more than just the last expression: find all the statements needed by re-decompiling." stack _ saveStack. pc _ thenJump. b _ self statementsTo: elsePc. "discard unwanted statements from block" b size - 1 timesRepeat: [statements removeLast]. statements addLast: (constructor codeMessage: (constructor codeBlock: b returns: false) selector: (constructor codeSelector: (sign ifTrue: [#whileFalse:] ifFalse: [#whileTrue:]) code: #macro) arguments: (Array with: thenBlock)). pc _ elseStart. self convertToDoLoop] ifFalse: ["Must be a conditional..." elseBlock _ self blockTo: thenJump. elseJump _ exit. "if elseJump is backwards, it is not part of the elseExpr" elseJump < elsePc ifTrue: [pc _ lastPc]. isIfNil ifTrue: [cond _ constructor codeMessage: ifExpr ifNilReceiver selector: (sign ifTrue: [constructor codeSelector: #ifNotNil: code: #macro] ifFalse: [constructor codeSelector: #ifNil: code: #macro]) arguments: (Array with: thenBlock)] ifFalse: [cond _ constructor codeMessage: ifExpr selector: (constructor codeSelector: #ifTrue:ifFalse: code: #macro) arguments: (sign ifTrue: [Array with: elseBlock with: thenBlock] ifFalse: [Array with: thenBlock with: elseBlock])]. stack _ saveStack. condHasValue ifTrue: [stack addLast: cond] ifFalse: [statements addLast: cond]]! ! !Decompiler methodsFor: 'instruction decoding'! methodReturnConstant: value self pushConstant: value; methodReturnTop! ! !Decompiler methodsFor: 'instruction decoding'! methodReturnReceiver self pushReceiver; methodReturnTop! ! !Decompiler methodsFor: 'instruction decoding' stamp: 'th 3/17/2000 20:48'! methodReturnTop | last | last _ stack removeLast "test test" asReturnNode. stack size > blockStackBase "get effect of elided pop before return" ifTrue: [statements addLast: stack removeLast]. exit _ method size + 1. lastJumpPc _ lastReturnPc _ lastPc. statements addLast: last! ! !Decompiler methodsFor: 'instruction decoding'! popIntoLiteralVariable: value self pushLiteralVariable: value; doStore: statements! ! !Decompiler methodsFor: 'instruction decoding'! popIntoReceiverVariable: offset self pushReceiverVariable: offset; doStore: statements! ! !Decompiler methodsFor: 'instruction decoding'! popIntoTemporaryVariable: offset self pushTemporaryVariable: offset; doStore: statements! ! !Decompiler methodsFor: 'instruction decoding'! pushActiveContext stack addLast: constructor codeThisContext! ! !Decompiler methodsFor: 'instruction decoding'! pushConstant: value | node | node _ value == true ifTrue: [constTable at: 2] ifFalse: [value == false ifTrue: [constTable at: 3] ifFalse: [value == nil ifTrue: [constTable at: 4] ifFalse: [constructor codeAnyLiteral: value]]]. stack addLast: node! ! !Decompiler methodsFor: 'instruction decoding'! pushLiteralVariable: assoc stack addLast: (constructor codeAnyLitInd: assoc)! ! !Decompiler methodsFor: 'instruction decoding'! pushReceiver stack addLast: (constTable at: 1)! ! !Decompiler methodsFor: 'instruction decoding'! pushReceiverVariable: offset | var | (var _ instVars at: offset + 1) == nil ifTrue: ["Not set up yet" instVars at: offset + 1 put: (var _ constructor codeInst: offset)]. stack addLast: var! ! !Decompiler methodsFor: 'instruction decoding'! pushTemporaryVariable: offset stack addLast: (tempVars at: offset + 1)! ! !Decompiler methodsFor: 'instruction decoding' stamp: 'di 1/29/2000 08:38'! send: selector super: superFlag numArgs: numArgs | args rcvr selNode msgNode messages | args _ Array new: numArgs. (numArgs to: 1 by: -1) do: [:i | args at: i put: stack removeLast]. rcvr _ stack removeLast. superFlag ifTrue: [rcvr _ constructor codeSuper]. (selector == #blockCopy: and: [self checkForBlock: rcvr]) ifFalse: [selNode _ constructor codeAnySelector: selector. rcvr == CascadeFlag ifTrue: ["May actually be a cascade or an ifNil: for value." self willJumpIfFalse ifTrue: "= generated by a case macro" [selector == #= ifTrue: [" = signals a case statement..." statements addLast: args first. stack addLast: rcvr. "restore CascadeFlag" ^ self]. selector == #== ifTrue: [" == signals an ifNil: for value..." stack removeLast; removeLast. rcvr _ stack removeLast. stack addLast: IfNilFlag; addLast: (constructor codeMessage: rcvr selector: selNode arguments: args). ^ self]. self error: 'bad case: ', selector] ifFalse: [(self willJumpIfTrue and: [selector == #==]) ifTrue: [" == signals an ifNotNil: for value..." stack removeLast; removeLast. rcvr _ stack removeLast. stack addLast: IfNilFlag; addLast: (constructor codeMessage: rcvr selector: selNode arguments: args). ^ self]. msgNode _ constructor codeCascadedMessage: selNode arguments: args]. stack last == CascadeFlag ifFalse: ["Last message of a cascade" statements addLast: msgNode. messages _ self popTo: stack removeLast. "Depth saved by first dup" msgNode _ constructor codeCascade: stack removeLast messages: messages]] ifFalse: [msgNode _ constructor codeMessage: rcvr selector: selNode arguments: args]. stack addLast: msgNode]! ! !Decompiler methodsFor: 'instruction decoding'! storeIntoLiteralVariable: assoc self pushLiteralVariable: assoc; doStore: stack! ! !Decompiler methodsFor: 'instruction decoding'! storeIntoReceiverVariable: offset self pushReceiverVariable: offset; doStore: stack! ! !Decompiler methodsFor: 'instruction decoding'! storeIntoTemporaryVariable: offset self pushTemporaryVariable: offset; doStore: stack! ! !Decompiler methodsFor: 'public access'! decompile: aSelector in: aClass method: aMethod "Answer a MethodNode that is the root of the parse tree for the argument, aMethod, which is the CompiledMethod associated with the message, aSelector. Variables are determined with respect to the argument, aClass." ^self decompile: aSelector in: aClass method: aMethod using: DecompilerConstructor new! ! !Decompiler methodsFor: 'public access' stamp: 'LC 1/6/2002 15:50'! decompileBlock: aBlock "Original version timestamp: sn 1/26/98 18:27 (Don't know who's sn?) " "Decompile aBlock, returning the result as a BlockNode. Show temp names from source if available." "Decompiler new decompileBlock: [3 + 4]" | startpc end homeClass blockNode tempNames home source | (home _ aBlock home) ifNil: [^ nil]. method _ home method. (homeClass _ home who first) == #unknown ifTrue: [^ nil]. constructor _ DecompilerConstructor new. method fileIndex ~~ 0 ifTrue: ["got any source code?" source _ [method getSourceFromFile] on: Error do: [:ex | ^ nil]. tempNames _ ([homeClass compilerClass new parse: source in: homeClass notifying: nil] on: (Smalltalk classNamed: 'SyntaxErrorNotification') do: [:ex | ^ nil]) tempNames. self withTempNames: tempNames]. self initSymbols: homeClass. startpc _ aBlock startpc. end _ (method at: startpc - 2) \\ 16 - 4 * 256 + (method at: startpc - 1) + startpc - 1. stack _ OrderedCollection new: method frameSize. statements _ OrderedCollection new: 20. super method: method pc: startpc - 5. blockNode _ self blockTo: end. stack isEmpty ifFalse: [self error: 'stack not empty']. ^ blockNode statements first! ! !Decompiler methodsFor: 'public access'! tempAt: offset "Needed by BraceConstructor<PopIntoTemporaryVariable" ^tempVars at: offset + 1! ! !Decompiler methodsFor: 'private' stamp: 'di 2/6/2000 11:06'! convertToDoLoop "If statements contains the pattern var _ startExpr. [var <= limit] whileTrue: [...statements... var _ var + incConst] then replace this by startExpr to: limit by: incConst do: [:var | ...statements...]" | initStmt toDoStmt limitStmt | statements size < 2 ifTrue: [^ self]. initStmt _ statements at: statements size-1. (toDoStmt _ statements last toDoFromWhileWithInit: initStmt) == nil ifTrue: [^ self]. initStmt variable scope: -1. "Flag arg as block temp" statements removeLast; removeLast; addLast: toDoStmt. "Attempt further conversion of the pattern limitVar _ limitExpr. startExpr to: limitVar by: incConst do: [:var | ...statements...] to startExpr to: limitExpr by: incConst do: [:var | ...statements...]" statements size < 2 ifTrue: [^ self]. limitStmt _ statements at: statements size-1. ((limitStmt isMemberOf: AssignmentNode) and: [limitStmt variable isTemp and: [limitStmt variable == toDoStmt arguments first and: [self methodRefersOnlyOnceToTemp: limitStmt variable fieldOffset]]]) ifFalse: [^ self]. toDoStmt arguments at: 1 put: limitStmt value. limitStmt variable scope: -2. "Flag limit var so it won't print" statements removeLast; removeLast; addLast: toDoStmt. ! ! !Decompiler methodsFor: 'private' stamp: 'ajh 11/15/2003 01:21'! decompile: aSelector in: aClass method: aMethod using: aConstructor | block | constructor _ aConstructor. method _ aMethod. self initSymbols: aClass. "create symbol tables" method isQuick ifTrue: [block _ self quickMethod] ifFalse: [stack _ OrderedCollection new: method frameSize. statements _ OrderedCollection new: 20. super method: method pc: method initialPC. block _ self blockTo: method endPC + 1. stack isEmpty ifFalse: [self error: 'stack not empty']]. ^constructor codeMethod: aSelector block: block tempVars: tempVars primitive: method primitive class: aClass! ! !Decompiler methodsFor: 'private' stamp: 'di 2/6/2000 08:49'! interpretNextInstructionFor: client | code varNames | "Change false here will trace all state in Transcript." true ifTrue: [^ super interpretNextInstructionFor: client]. varNames _ Decompiler allInstVarNames. code _ (self method at: pc) radix: 16. Transcript cr; cr; print: pc; space; nextPutAll: '<' , (code copyFrom: 4 to: code size) , '>'. 8 to: varNames size do: [:i | i <= 10 ifTrue: [Transcript cr] ifFalse: [Transcript space; space]. Transcript nextPutAll: (varNames at: i); nextPutAll: ': '; print: (self instVarAt: i)]. Transcript endEntry. ^ super interpretNextInstructionFor: client! ! !Decompiler methodsFor: 'private' stamp: 'di 2/6/2000 10:55'! methodRefersOnlyOnceToTemp: offset | nRefs byteCode extension scanner | nRefs _ 0. offset <= 15 ifTrue: [byteCode _ 16 + offset. (InstructionStream on: method) scanFor: [:instr | instr = byteCode ifTrue: [nRefs _ nRefs + 1]. nRefs > 1]] ifFalse: [extension _ 64 + offset. scanner _ InstructionStream on: method. scanner scanFor: [:instr | (instr = 128 and: [scanner followingByte = extension]) ifTrue: [nRefs _ nRefs + 1]. nRefs > 1]]. ^ nRefs = 1 ! ! !Decompiler methodsFor: 'private'! popTo: oldPos | t | t _ Array new: statements size - oldPos. (t size to: 1 by: -1) do: [:i | t at: i put: statements removeLast]. ^t! ! !Decompiler methodsFor: 'private' stamp: 'di 12/26/1998 21:29'! quickMethod | | method isReturnSpecial ifTrue: [^ constructor codeBlock: (Array with: (constTable at: method primitive - 255)) returns: true]. method isReturnField ifTrue: [^ constructor codeBlock: (Array with: (constructor codeInst: method returnField)) returns: true]. self error: 'improper short method'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Decompiler class instanceVariableNames: ''! !Decompiler class methodsFor: 'class initialization' stamp: 'di 1/28/2000 22:21'! initialize CascadeFlag _ 'cascade'. "A unique object" CaseFlag _ 'case'. "Ditto" ArgumentFlag _ 'argument'. "Ditto" IfNilFlag _ 'ifNil'. "Ditto" "Decompiler initialize"! ! ParseNode subclass: #DecompilerConstructor instanceVariableNames: 'method instVars nArgs literalValues tempVars' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !DecompilerConstructor commentStamp: '<historical>' prior: 0! I construct the node tree for a Decompiler.! !DecompilerConstructor methodsFor: 'initialize-release'! method: aMethod class: aClass literals: literals method _ aMethod. instVars _ aClass allInstVarNames. nArgs _ method numArgs. literalValues _ literals! ! !DecompilerConstructor methodsFor: 'constructor'! codeAnyLitInd: association ^VariableNode new name: association key key: association index: 0 type: LdLitIndType! ! !DecompilerConstructor methodsFor: 'constructor'! codeAnyLiteral: value ^LiteralNode new key: value index: 0 type: LdLitType! ! !DecompilerConstructor methodsFor: 'constructor'! codeAnySelector: selector ^SelectorNode new key: selector index: 0 type: SendType! ! !DecompilerConstructor methodsFor: 'constructor'! codeArguments: args block: block ^block arguments: args! ! !DecompilerConstructor methodsFor: 'constructor'! codeAssignTo: variable value: expression ^AssignmentNode new variable: variable value: expression! ! !DecompilerConstructor methodsFor: 'constructor' stamp: 'sma 3/3/2000 13:34'! codeBlock: statements returns: returns ^ BlockNode statements: statements returns: returns! ! !DecompilerConstructor methodsFor: 'constructor'! codeBrace: elements ^BraceNode new elements: elements! ! !DecompilerConstructor methodsFor: 'constructor' stamp: 'di 11/19/1999 11:06'! codeCascade: receiver messages: messages ^ (BraceNode new matchBraceStreamReceiver: receiver messages: messages) ifNil: [CascadeNode new receiver: receiver messages: messages]! ! !DecompilerConstructor methodsFor: 'constructor'! codeCascadedMessage: selector arguments: arguments ^self codeMessage: nil selector: selector arguments: arguments! ! !DecompilerConstructor methodsFor: 'constructor'! codeConstants "Answer with an array of the objects representing self, true, false, nil, -1, 0, 1, 2." ^(Array with: NodeSelf with: NodeTrue with: NodeFalse with: NodeNil) , ((-1 to: 2) collect: [:i | LiteralNode new key: i code: LdMinus1 + i + 1])! ! !DecompilerConstructor methodsFor: 'constructor'! codeInst: index ^VariableNode new name: (instVars at: index + 1) index: index type: LdInstType! ! !DecompilerConstructor methodsFor: 'constructor' stamp: 'sma 2/5/2000 12:37'! codeMessage: receiver selector: selector arguments: arguments | symbol node | symbol _ selector key. (node _ BraceNode new matchBraceWithReceiver: receiver selector: symbol arguments: arguments) ifNotNil: [^ node]. (node _ self decodeIfNilWithReceiver: receiver selector: symbol arguments: arguments) ifNotNil: [^ node]. ^ MessageNode new receiver: receiver selector: selector arguments: arguments precedence: symbol precedence! ! !DecompilerConstructor methodsFor: 'constructor' stamp: 'ajh 11/15/2003 01:20'! codeMethod: selector block: block tempVars: vars primitive: primitive class: class | node methodTemps | node _ self codeSelector: selector code: nil. tempVars _ vars. methodTemps _ tempVars select: [:t | t scope >= 0]. ^MethodNode new selector: node arguments: (methodTemps copyFrom: 1 to: nArgs) precedence: selector precedence temporaries: (methodTemps copyFrom: nArgs + 1 to: methodTemps size) block: block encoder: (Encoder new initScopeAndLiteralTables temps: tempVars literals: literalValues class: class) primitive: primitive! ! !DecompilerConstructor methodsFor: 'constructor'! codeSelector: sel code: code ^SelectorNode new key: sel code: code! ! !DecompilerConstructor methodsFor: 'constructor'! codeSuper ^NodeSuper! ! !DecompilerConstructor methodsFor: 'constructor'! codeTemp: index ^ TempVariableNode new name: 't' , (index + 1) printString index: index type: LdTempType scope: 0! ! !DecompilerConstructor methodsFor: 'constructor'! codeTemp: index named: tempName ^ TempVariableNode new name: tempName index: index type: LdTempType scope: 0! ! !DecompilerConstructor methodsFor: 'constructor'! codeThisContext ^NodeThisContext! ! !DecompilerConstructor methodsFor: 'constructor' stamp: 'di 1/28/2000 21:23'! decodeIfNilWithReceiver: receiver selector: selector arguments: arguments selector == #ifTrue:ifFalse: ifFalse: [^ nil]. (receiver isMessage: #== receiver: nil arguments: [:argNode | argNode == NodeNil]) ifFalse: [^ nil]. ^ (MessageNode new receiver: receiver selector: (SelectorNode new key: #ifTrue:ifFalse: code: #macro) arguments: arguments precedence: 3) noteSpecialSelector: #ifNil:ifNotNil:! ! StandardSystemController subclass: #DeferredActionStandardSystemController instanceVariableNames: 'queue' classVariableNames: '' poolDictionaries: '' category: 'Tools-Process Browser'! !DeferredActionStandardSystemController commentStamp: '<historical>' prior: 0! This is a StandardSystemController that can queue up objects to be evaluated before its control loop.! !DeferredActionStandardSystemController methodsFor: 'as yet unclassified' stamp: 'nk 10/28/2000 22:28'! addDeferredUIMessage: valuableObject queue nextPut: valuableObject! ! !DeferredActionStandardSystemController methodsFor: 'as yet unclassified' stamp: 'nk 10/28/2000 22:27'! controlActivity [queue isEmpty] whileFalse: [queue next value]. ^super controlActivity! ! !DeferredActionStandardSystemController methodsFor: 'as yet unclassified' stamp: 'nk 10/28/2000 22:28'! initialize super initialize. queue _ SharedQueue new.! ! Object subclass: #Delay instanceVariableNames: 'delayDuration resumptionTime delaySemaphore beingWaitedOn' classVariableNames: 'AccessProtect ActiveDelay ActiveDelayStartTime SuspendedDelays TimingSemaphore' poolDictionaries: '' category: 'Kernel-Processes'! !Delay commentStamp: 'ls 10/14/2003 11:46' prior: 0! I am the main way that a process may pause for some amount of time. The simplest usage is like this: (Delay forSeconds: 5) wait. An instance of Delay responds to the message 'wait' by suspending the caller's process for a certain amount of time. The duration of the pause is specified when the Delay is created with the message forMilliseconds: or forSeconds:. A Delay can be used again when the current wait has finished. For example, a clock process might repeatedly wait on a one-second Delay. The maximum delay is (SmallInteger maxVal // 2) milliseconds, or about six days. A delay in progress when an image snapshot is saved is resumed when the snapshot is re-started. Delays work across millisecond clock roll-overs. For a more complex example, see #testDelayOf:for:rect: .! ]style[(763 22 2)f1,f1LDelay class testDelayOf:for:rect:;,f1! !Delay methodsFor: 'delaying' stamp: 'nk 3/14/2001 08:52'! isExpired ^delaySemaphore isSignaled. ! ! !Delay methodsFor: 'delaying' stamp: 'jm 9/12/97 09:10'! wait "Schedule this Delay, then wait on its semaphore. The current process will be suspended for the amount of time specified when this Delay was created." self schedule. delaySemaphore wait. ! ! !Delay methodsFor: 'private' stamp: 'ar 7/18/2001 20:28'! activate "Private!! Make the receiver the Delay to be awoken when the next timer interrupt occurs. This method should only be called from a block protected by the AccessProtect semaphore." ActiveDelay _ self. ActiveDelayStartTime _ Time millisecondClockValue. ActiveDelayStartTime > resumptionTime ifTrue:[ ActiveDelay signalWaitingProcess. SuspendedDelays isEmpty ifTrue:[ ActiveDelay _ nil. ActiveDelayStartTime _ nil. ] ifFalse:[SuspendedDelays removeFirst activate]. ] ifFalse:[ TimingSemaphore initSignals. Delay primSignal: TimingSemaphore atMilliseconds: resumptionTime. ].! ! !Delay methodsFor: 'private' stamp: 'jm 9/11/97 14:49'! adjustResumptionTimeOldBase: oldBaseTime newBase: newBaseTime "Private!! Adjust the value of the system's millisecond clock at which this Delay will be awoken. Used to adjust resumption times after a snapshot or clock roll-over." resumptionTime _ newBaseTime + (resumptionTime - oldBaseTime). ! ! !Delay methodsFor: 'private' stamp: 'jm 9/11/97 11:54'! resumptionTime "Answer the value of the system's millisecondClock at which the receiver's suspended Process will resume." ^ resumptionTime ! ! !Delay methodsFor: 'private' stamp: 'jm 9/12/97 11:10'! schedule "Private!! Schedule this Delay, but return immediately rather than waiting. The receiver's semaphore will be signalled when its delay duration has elapsed." beingWaitedOn ifTrue: [self error: 'This Delay has already been scheduled.']. AccessProtect critical: [ beingWaitedOn _ true. resumptionTime _ Time millisecondClockValue + delayDuration. ActiveDelay == nil ifTrue: [self activate] ifFalse: [ resumptionTime < ActiveDelay resumptionTime ifTrue: [ SuspendedDelays add: ActiveDelay. self activate] ifFalse: [SuspendedDelays add: self]]]. ! ! !Delay methodsFor: 'private' stamp: 'jm 9/12/97 08:56'! setDelay: millisecondCount forSemaphore: aSemaphore "Private!! Initialize this delay to signal the given semaphore after the given number of milliseconds." delayDuration _ millisecondCount. delaySemaphore _ aSemaphore. beingWaitedOn _ false. ! ! !Delay methodsFor: 'private' stamp: 'jm 9/11/97 11:54'! signalWaitingProcess "The delay time has elapsed; signal the waiting process." beingWaitedOn _ false. delaySemaphore signal. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Delay class instanceVariableNames: ''! !Delay class methodsFor: 'instance creation' stamp: 'jm 9/15/97 17:09'! forMilliseconds: anInteger "Return a new Delay for the given number of milliseconds. Sending 'wait' to this Delay will cause the sender's process to be suspended for approximately that length of time." anInteger < 0 ifTrue: [self error: 'delay times cannot be negative']. ^ self new setDelay: anInteger forSemaphore: Semaphore new ! ! !Delay class methodsFor: 'instance creation' stamp: 'di 6/16/1999 23:04'! forSeconds: aNumber "Return a new Delay for the given number of seconds. Sending 'wait' to this Delay will cause the sender's process to be suspended for approximately that length of time." aNumber < 0 ifTrue: [self error: 'delay times cannot be negative']. ^ self new setDelay: (aNumber * 1000) asInteger forSemaphore: Semaphore new ! ! !Delay class methodsFor: 'snapshotting' stamp: 'jm 9/11/97 14:59'! restoreResumptionTimes "Private!! Restore the resumption times of all scheduled Delays after a snapshot or clock roll-over. This method should be called only while the AccessProtect semaphore is held." | newBaseTime | newBaseTime _ Time millisecondClockValue. SuspendedDelays do: [:d | d adjustResumptionTimeOldBase: 0 newBase: newBaseTime]. ActiveDelay == nil ifFalse: [ ActiveDelay adjustResumptionTimeOldBase: 0 newBase: newBaseTime. ActiveDelay activate]. ! ! !Delay class methodsFor: 'snapshotting' stamp: 'jm 9/11/97 15:15'! saveResumptionTimes "Private!! Record the resumption times of all Delays relative to a base time of zero. This is done prior to snapshotting or adjusting the resumption times after a clock roll-over. This method should be called only while the AccessProtect semaphore is held." | oldBaseTime | oldBaseTime _ Time millisecondClockValue. ActiveDelay == nil ifFalse: [ oldBaseTime < ActiveDelayStartTime ifTrue: [oldBaseTime _ ActiveDelayStartTime]. "clock rolled over" ActiveDelay adjustResumptionTimeOldBase: oldBaseTime newBase: 0]. SuspendedDelays do: [:d | d adjustResumptionTimeOldBase: oldBaseTime newBase: 0]. ! ! !Delay class methodsFor: 'snapshotting' stamp: 'jm 9/11/97 15:00'! shutDown "Suspend the active delay, if any, before snapshotting. It will be reactived when the snapshot is resumed." "Details: This prevents a timer interrupt from waking up the active delay in the midst snapshoting, since the active delay will be restarted when resuming the snapshot and we don't want to process the delay twice." AccessProtect wait. self primSignal: nil atMilliseconds: 0. self saveResumptionTimes. ! ! !Delay class methodsFor: 'snapshotting' stamp: 'jm 9/11/97 15:01'! startUp "Restart active delay, if any, when resuming a snapshot." self restoreResumptionTimes. ActiveDelay == nil ifFalse: [ActiveDelay activate]. AccessProtect signal. ! ! !Delay class methodsFor: 'timer process' stamp: 'jm 9/11/97 15:15'! startTimerInterruptWatcher "Reset the class variables that keep track of active Delays and re-start the timer interrupt watcher process. Any currently scheduled delays are forgotten." "Delay startTimerInterruptWatcher" | p | self primSignal: nil atMilliseconds: 0. TimingSemaphore == nil ifFalse: [TimingSemaphore terminateProcess]. TimingSemaphore _ Semaphore new. AccessProtect _ Semaphore forMutualExclusion. SuspendedDelays _ SortedCollection sortBlock: [:d1 :d2 | d1 resumptionTime <= d2 resumptionTime]. ActiveDelay _ nil. p _ [self timerInterruptWatcher] newProcess. p priority: Processor timingPriority. p resume. ! ! !Delay class methodsFor: 'timer process' stamp: 'jm 9/11/97 15:13'! timerInterruptWatcher "This loop runs in its own process. It waits for a timer interrupt and wakes up the active delay. Note that timer interrupts are only enabled when there are active delays." [true] whileTrue: [ TimingSemaphore wait. AccessProtect critical: [ ActiveDelay == nil ifFalse: [ ActiveDelay signalWaitingProcess. Time millisecondClockValue < ActiveDelayStartTime ifTrue: [ "clock wrapped" self saveResumptionTimes. self restoreResumptionTimes]]. SuspendedDelays isEmpty ifTrue: [ ActiveDelay _ nil. ActiveDelayStartTime _ nil] ifFalse: [ SuspendedDelays removeFirst activate]]]. ! ! !Delay class methodsFor: 'primitives' stamp: 'jm 9/11/97 10:54'! primSignal: aSemaphore atMilliseconds: aSmallInteger "Signal the semaphore when the millisecond clock reaches the value of the second argument. Fail if the first argument is neither a Semaphore nor nil. Essential. See Object documentation whatIsAPrimitive." <primitive: 136> self primitiveFailed ! ! Array weakSubclass: #DependentsArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !DependentsArray commentStamp: '<historical>' prior: 0! An array of (weak) dependents of some object.! !DependentsArray methodsFor: 'copying' stamp: 'ar 2/24/2001 17:30'! copyWith: newElement "Re-implemented to not copy any niled out dependents" ^self class streamContents:[:s| self do:[:item| s nextPut: item]. s nextPut: newElement].! ! !DependentsArray methodsFor: 'copying' stamp: 'nk 3/11/2004 09:34'! size ^self inject: 0 into: [ :count :dep | dep ifNotNil: [ count _ count + 1 ]]! ! !DependentsArray methodsFor: 'enumerating' stamp: 'nk 3/11/2004 09:34'! do: aBlock "Refer to the comment in Collection|do:." | dep | 1 to: self basicSize do:[:i| (dep _ self at: i) ifNotNil:[aBlock value: dep]].! ! !DependentsArray methodsFor: 'enumerating' stamp: 'ar 2/11/2001 01:50'! select: aBlock "Refer to the comment in Collection|select:." | aStream | aStream _ WriteStream on: (self species new: self size). self do:[:obj| (aBlock value: obj) ifTrue: [aStream nextPut: obj]]. ^ aStream contents! ! Warning subclass: #Deprecation instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !Deprecation commentStamp: 'dew 5/21/2003 17:46' prior: 0! This Warning is signalled by methods which are deprecated. The use of Object>>#deprecatedExplanation: aString and Object>>#deprecated: aBlock explanation: aString is recommended. Idiom: Imagine I want to deprecate the message #foo. foo ^ 'foo' I can replace it with: foo self deprecatedExplanation: 'The method #foo was not good. Use Bar>>newFoo instead.' ^ 'foo' Or, for certain cases such as when #foo implements a primitive, #foo can be renamed to #fooDeprecated. fooDeprecated ^ <primitive> foo ^ self deprecated: [self fooDeprecated] explanation: 'The method #foo was not good. Use Bar>>newFoo instead.' ! MethodNode subclass: #DialectMethodNode instanceVariableNames: 'dialect' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !DialectMethodNode commentStamp: '<historical>' prior: 0! The purpose of this class is to carry along with theinformation in a regular method node the further information that it was parsed from an laternate dialect of Squeak. Which dialect that was is carried as a symbol in the dialect variable.! !DialectMethodNode methodsFor: 'as yet unclassified' stamp: 'di 4/13/2000 20:46'! setDialect: dialectSymbol dialect _ dialectSymbol! ! Parser subclass: #DialectParser instanceVariableNames: 'dialect' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !DialectParser commentStamp: '<historical>' prior: 0! This Parser is part of a package designed to allow for experiments with alternatives to ST-80 syntax. The particular alternative offered by this parser eliminates colons, left-arrows and up-arrows, and adds prefix keywords for common control constructs. ST-80 SQ-00 ------- ------- a + b between: c and: c + 4 a + b between (c) and (c + 4) a _ 3.0 Set a to 3.0 ^ self size + 3 Return self size + 3 a > b Test (a > b) ifTrue: ['greater'] ifTrue ['greater'] ifFalse: ['less'] ifFalse ['less'] 1 to: 9 do: Repeat (1) to (9) do [:i | Transcript cr; show: i] [Set i. | Transcript cr; show (i)] The use of prefix keywords is currently ad-hoc; in other words they are built into the parser, and there is not a way to define a method pattern to include a prefix keyword. Most of the work has been done to support this, though, as selectors can now have the form #:prefix:kwd1:kwd2: and they will respond appropriately to #keywords and #numArgs. A test method in the class ensures that every method in the system can be pretty-printed in the alternative syntax, and that compiling the resulting text produces exactly the same bytecodes as the original method.! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 4/23/2000 22:18'! assignment: varNode " 'set' (var) 'to' (expression) => AssignmentNode." | loc | (loc _ varNode assignmentCheck: encoder at: prevMark + requestorOffset) >= 0 ifTrue: [^self notify: 'Cannot store into' at: loc]. varNode nowHasDef. self advance. " to " self expression ifFalse: [^self expected: 'Expression']. parseNode _ AssignmentNode new variable: varNode value: parseNode from: encoder. ^ true! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 6/13/2000 00:34'! blockExpression "[ ({:var} |) (| {temps} |) (statements) ] => BlockNode." | variableNodes temporaryBlockVariables | variableNodes _ OrderedCollection new. "Gather parameters." (self matchToken: 'With') ifTrue: [[self match: #period] whileFalse: [variableNodes addLast: (encoder autoBind: self argumentName)]]. temporaryBlockVariables _ self temporaryBlockVariables. self statements: variableNodes innerBlock: true. parseNode temporaries: temporaryBlockVariables. (self match: #rightBracket) ifFalse: [^ self expected: 'Period or right bracket']. "The scope of the parameters and temporary block variables is no longer active." temporaryBlockVariables do: [:variable | variable scope: -1]. variableNodes do: [:variable | variable scope: -1]! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 4/22/2000 17:11'! expression ^ self expressionWithInitialKeyword: '' ! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 6/7/2000 09:51'! expressionWithInitialKeyword: kwdIfAny | checkpoint | (hereType == #word and: [here = 'Set' and: [tokenType == #word]]) ifTrue: ["Parse assignment statement 'Set' var 'to' expression" checkpoint _ self checkpoint. self advance. token = 'to' ifTrue: [^ self assignment: self variable] ifFalse: [self revertToCheckpoint: checkpoint]]. self matchKeyword ifTrue: ["It's an initial keyword." kwdIfAny isEmpty ifFalse: [self error: 'compiler logic error']. ^ self expressionWithInitialKeyword: ':' , self advance , ':']. hereType == #leftBrace ifTrue: [self braceExpression] ifFalse: [self primaryExpression ifFalse: [^ false]]. (self messagePart: 3 repeat: true initialKeyword: kwdIfAny) ifTrue: [hereType == #semicolon ifTrue: [self cascade]]. ^ true! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 4/25/2000 22:36'! matchKeyword "Return true if we are looking at a keyword (and its argument)." hereType == #word ifFalse: [^ false]. tokenType == #leftParenthesis ifTrue: [^ true]. tokenType == #leftBracket ifTrue: [^ true]. tokenType == #leftBrace ifTrue: [^ true]. ^ false! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 6/11/2000 15:27'! matchReturn ^ self matchToken: 'Answer'! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 4/22/2000 16:56'! messagePart: level repeat: repeat ^ self messagePart: level repeat: repeat initialKeyword: ''! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'hmm 7/16/2001 20:12'! messagePart: level repeat: repeat initialKeyword: kwdIfAny | start receiver selector args precedence words keywordStart | [receiver _ parseNode. (self matchKeyword and: [level >= 3]) ifTrue: [start _ self startOfNextToken. selector _ WriteStream on: (String new: 32). selector nextPutAll: kwdIfAny. args _ OrderedCollection new. words _ OrderedCollection new. [self matchKeyword] whileTrue: [keywordStart _ self startOfNextToken + requestorOffset. selector nextPutAll: self advance , ':'. words addLast: (keywordStart to: hereEnd + requestorOffset). self primaryExpression ifFalse: [^ self expected: 'Argument']. args addLast: parseNode]. (Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence _ 3] ifFalse: [((hereType == #binary or: [hereType == #verticalBar]) and: [level >= 2]) ifTrue: [start _ self startOfNextToken. selector _ self advance asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args _ Array with: parseNode. precedence _ 2] ifFalse: [(hereType == #word and: [(#(leftParenthesis leftBracket leftBrace) includes: tokenType) not]) ifTrue: [start _ self startOfNextToken. selector _ self advance. args _ #(). words _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). (Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence _ 1] ifFalse: [^args notNil]]]. parseNode _ MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 5/30/2000 22:01'! newMethodNode ^ DialectMethodNode new setDialect: #SQ00! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 4/5/2000 17:02'! parseArgsAndTemps: aString notifying: req "Parse the argument, aString, notifying req if an error occurs. Otherwise, answer a two-element Array containing Arrays of strings (the argument names and temporary variable names)." aString == nil ifTrue: [^#()]. doitFlag _ false. "Don't really know if a doit or not!!" ^self initPattern: aString notifying: req return: [:pattern | (pattern at: 2) , self temporaries]! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'di 6/11/2000 15:27'! pattern: fromDoit inContext: ctxt " unarySelector | binarySelector arg | keyword arg {keyword arg} => {selector, arguments, precedence}." | args selector checkpoint | doitFlag _ fromDoit. fromDoit ifTrue: [ctxt == nil ifTrue: [^ {#DoIt. {}. 1}] ifFalse: [^ {#DoItIn:. {encoder encodeVariable: 'homeContext'}. 3}]]. "NOTE: there is now an ambiguity between keywordSelector (argName) -and- unarySelector (first expression). Also, there is an amibuity (if there are no temp declarations) between keywordSelector (argName) -and- PrefixKeyword (some expression). We use duct tape for now." (hereType == #word and: [tokenType == #leftParenthesis]) ifTrue: [checkpoint _ self checkpoint. "in case we have to back out" selector _ WriteStream on: (String new: 32). args _ OrderedCollection new. [hereType == #word and: [tokenType == #leftParenthesis and: [here first isLowercase or: [(#('Test' 'Repeat' 'Answer') includes: here) not]]]] whileTrue: [selector nextPutAll: self advance , ':'. "selector part" self advance. "open paren" (args size = 0 and: [tokenType ~~ #rightParenthesis]) ifTrue: ["This is really a unary selector on a method that begins with a parenthesized expression. Back out now" self revertToCheckpoint: checkpoint. ^ {self advance asSymbol. {}. 1}]. args addLast: (encoder bindArg: self argumentName). (self match: #rightParenthesis) ifFalse: [^ self expected: 'right parenthesis']]. ^ {selector contents asSymbol. args. 3}]. hereType == #word ifTrue: [^ {self advance asSymbol. {}. 1}]. (hereType == #binary or: [hereType == #verticalBar]) ifTrue: [selector _ self advance asSymbol. args _ Array with: (encoder bindArg: self argumentName). ^ {selector. args. 2}]. ^ self expected: 'Message pattern'! ! !DialectParser methodsFor: 'as yet unclassified' stamp: 'hmm 7/16/2001 20:09'! temporaries " [ 'Use' (variable)* '.' ]" | vars theActualText | (self matchToken: #'Use') ifFalse: ["no temps" doitFlag ifTrue: [requestor ifNil: [tempsMark _ 1] ifNotNil: [tempsMark _ requestor selectionInterval first]. ^ #()]. tempsMark _ prevEnd+1. tempsMark > 0 ifTrue: [theActualText _ source contents. [tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]] whileTrue: [tempsMark _ tempsMark + 1]]. ^ #()]. vars _ OrderedCollection new. [hereType == #word] whileTrue: [vars addLast: (encoder bindTemp: self advance)]. (self match: #period) ifTrue: [tempsMark _ prevMark. ^ vars]. ^ self expected: 'Period'! ! TextStream subclass: #DialectStream instanceVariableNames: 'dialect colorTable' classVariableNames: 'ST80ColorTable Sq00ColorTable' poolDictionaries: '' category: 'System-Compiler'! !DialectStream methodsFor: 'color/style' stamp: 'sw 5/20/2001 11:20'! colorTable "Answer the table to use to determine colors" ^ colorTable ifNil: [colorTable _ dialect == #SQ00 ifTrue: [Sq00ColorTable] ifFalse: [ST80ColorTable]]! ! !DialectStream methodsFor: 'color/style' stamp: 'sw 5/20/2001 21:05'! withColor: colorSymbol emphasis: emphasisSymbol do: aBlock "Evaluate the given block with the given color and style text attribute" ^ self withAttributes: {TextColor color: (Color perform: colorSymbol). TextEmphasis perform: emphasisSymbol} do: aBlock! ! !DialectStream methodsFor: 'color/style' stamp: 'sw 5/20/2001 11:30'! withStyleFor: elementType do: aBlock "Evaluate aBlock with appropriate emphasis and color for the given elementType" | colorAndStyle | colorAndStyle _ self colorTable at: elementType. ^ self withColor: colorAndStyle first emphasis: colorAndStyle second do: aBlock! ! !DialectStream methodsFor: 'access' stamp: 'di 4/5/2000 08:48'! dialect ^ dialect! ! !DialectStream methodsFor: 'access' stamp: 'di 4/5/2000 08:48'! setDialect: dialectSymbol dialect _ dialectSymbol! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DialectStream class instanceVariableNames: ''! !DialectStream class methodsFor: 'class initialization' stamp: 'sw 5/20/2001 11:27'! initialize "Initialize the color tables" self initializeST80ColorTable. self initializeSq00ColorTable. "DialectStream initialize" ! ! !DialectStream class methodsFor: 'class initialization' stamp: 'sw 5/20/2001 21:09'! initializeST80ColorTable "Initiialize the colors that characterize the ST80 dialect" ST80ColorTable _ IdentityDictionary new. #( (temporaryVariable blue italic) (methodArgument blue normal) (methodSelector black bold) (blockArgument red normal) (comment brown normal) (variable magenta normal) (literal tan normal) (keyword darkGray bold) (prefixKeyword veryDarkGray bold) (setOrReturn black bold)) do: [:aTriplet | ST80ColorTable at: aTriplet first put: aTriplet allButFirst] "DialectStream initialize"! ! !DialectStream class methodsFor: 'class initialization' stamp: 'sw 5/20/2001 11:25'! initializeSq00ColorTable "Initiialize the colors that characterize the Sq00 dialect" Sq00ColorTable _ IdentityDictionary new. #( (temporaryVariable black normal) (methodArgument black normal) (methodSelector black bold) (blockArgument black normal) (comment brown normal) (variable black normal) (literal blue normal) (keyword darkGray bold) (prefixKeyword veryDarkGray bold) (setOrReturn black bold)) do: [:aTriplet | Sq00ColorTable at: aTriplet first put: aTriplet allButFirst]! ! !DialectStream class methodsFor: 'instance creation' stamp: 'sw 5/20/2001 21:07'! dialect: dialectSymbol contents: blockWithArg "Evaluate blockWithArg on a DialectStream of the given description" | stream | stream _ self on: (Text new: 400). stream setDialect: dialectSymbol. blockWithArg value: stream. ^ stream contents! ! Set subclass: #Dictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !Dictionary commentStamp: '<historical>' prior: 0! I represent a set of elements that can be viewed from one of two perspectives: a set of associations, or a container 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. I inherit many operations from Set.! !Dictionary methodsFor: 'accessing'! associationAt: key ^ self associationAt: key ifAbsent: [self errorKeyNotFound]! ! !Dictionary methodsFor: 'accessing'! associationAt: key ifAbsent: aBlock "Answer the association with the given key. If key is not found, return the result of evaluating aBlock." | index assoc | index _ self findElementOrNil: key. assoc _ array at: index. nil == assoc ifTrue: [ ^ aBlock value ]. ^ assoc! ! !Dictionary methodsFor: 'accessing' stamp: 'tk 4/9/1999 10:22'! associationDeclareAt: aKey "Return an existing association, or create and return a new one. Needed as a single message by ImageSegment.prepareToBeSaved." | existing | ^ self associationAt: aKey ifAbsent: [ (Undeclared includesKey: aKey) ifTrue: [existing _ Undeclared associationAt: aKey. Undeclared removeKey: aKey. self add: existing] ifFalse: [self add: aKey -> false]]! ! !Dictionary methodsFor: 'accessing' stamp: 'dvf 9/17/2003 16:03'! associations "Answer a Collection containing the receiver's associations." | out | out _ WriteStream on: (Array new: self size). self associationsDo: [:value | out nextPut: value]. ^ out contents! ! !Dictionary methodsFor: 'accessing'! at: key "Answer the value associated with the key." ^ self at: key ifAbsent: [self errorKeyNotFound]! ! !Dictionary methodsFor: 'accessing' stamp: 'sma 5/12/2000 14:59'! at: key ifAbsent: aBlock "Answer the value associated with the key or, if key isn't found, answer the result of evaluating aBlock." | assoc | assoc _ array at: (self findElementOrNil: key). assoc ifNil: [^ aBlock value]. ^ assoc value! ! !Dictionary methodsFor: 'accessing' stamp: 'sma 5/12/2000 15:01'! at: key ifAbsentPut: aBlock "Return the value at the given key. If key is not included in the receiver store the result of evaluating aBlock as new value." ^ self at: key ifAbsent: [self at: key put: aBlock value]! ! !Dictionary methodsFor: 'accessing' stamp: 'jm 5/15/1998 07:20'! at: key ifPresent: aBlock "Lookup the given key in the receiver. If it is present, answer the value of evaluating the given block with the value associated with the key. Otherwise, answer nil." | v | v _ self at: key ifAbsent: [^ nil]. ^ aBlock value: v ! ! !Dictionary methodsFor: 'accessing' stamp: 'di 3/7/2001 15:29'! at: key ifPresentAndInMemory: aBlock "Lookup the given key in the receiver. If it is present, answer the value of evaluating the given block with the value associated with the key. Otherwise, answer nil." | v | v _ self at: key ifAbsent: [^ nil]. v isInMemory ifFalse: [^ nil]. ^ aBlock value: v ! ! !Dictionary methodsFor: 'accessing' stamp: 'sma 5/12/2000 15:00'! at: key put: anObject "Set the value at key to be anObject. If key is not found, create a new entry for key and set is value to anObject. Answer anObject." | index assoc | index _ self findElementOrNil: key. assoc _ array at: index. assoc ifNil: [self atNewIndex: index put: (Association key: key value: anObject)] ifNotNil: [assoc value: anObject]. ^ anObject! ! !Dictionary methodsFor: 'accessing' stamp: 'ar 2/13/1999 21:16'! keyAtIdentityValue: value "Answer the key that is the external name for the argument, value. If there is none, answer nil. Note: There can be multiple keys with the same value. Only one is returned." ^self keyAtIdentityValue: value ifAbsent: [self errorValueNotFound]! ! !Dictionary methodsFor: 'accessing' stamp: 'ar 2/13/1999 21:16'! keyAtIdentityValue: value ifAbsent: exceptionBlock "Answer the key that is the external name for the argument, value. If there is none, answer the result of evaluating exceptionBlock. Note: There can be multiple keys with the same value. Only one is returned." self associationsDo: [:association | value == association value ifTrue: [^association key]]. ^exceptionBlock value! ! !Dictionary methodsFor: 'accessing'! keyAtValue: value "Answer the key that is the external name for the argument, value. If there is none, answer nil." ^self keyAtValue: value ifAbsent: [self errorValueNotFound]! ! !Dictionary methodsFor: 'accessing' stamp: 'tk 2/18/97'! keyAtValue: value ifAbsent: exceptionBlock "Answer the key that is the external name for the argument, value. If there is none, answer the result of evaluating exceptionBlock. : Use =, not ==, so stings like 'this' can be found. Note that MethodDictionary continues to use == so it will be fast." self associationsDo: [:association | value = association value ifTrue: [^association key]]. ^exceptionBlock value! ! !Dictionary methodsFor: 'accessing'! keys "Answer a Set containing the receiver's keys." | aSet | aSet _ Set new: self size. self keysDo: [:key | aSet add: key]. ^ aSet! ! !Dictionary methodsFor: 'accessing' stamp: 'sma 6/18/2000 12:56'! keysSortedSafely "Answer a SortedCollection containing the receiver's keys." | sortedKeys | sortedKeys _ SortedCollection new: self size. sortedKeys sortBlock: [:x :y | "Should really be use <obj, string, num> compareSafely..." ((x isString and: [y isString]) or: [x isNumber and: [y isNumber]]) ifTrue: [x < y] ifFalse: [x class == y class ifTrue: [x printString < y printString] ifFalse: [x class name < y class name]]]. self keysDo: [:each | sortedKeys addLast: each]. ^ sortedKeys reSort! ! !Dictionary methodsFor: 'accessing' stamp: 'ar 7/11/1999 07:28'! values "Answer a Collection containing the receiver's values." | out | out _ WriteStream on: (Array new: self size). self valuesDo: [:value | out nextPut: value]. ^ out contents! ! !Dictionary methodsFor: 'testing' stamp: 'bf 8/20/1999 15:07'! hasContentsInExplorer ^self isEmpty not! ! !Dictionary methodsFor: 'testing'! includes: anObject self do: [:each | anObject = each ifTrue: [^true]]. ^false! ! !Dictionary methodsFor: 'testing' stamp: 'sw 2/14/2000 14:34'! includesIdentity: anObject "Answer whether anObject is one of the values of the receiver. Contrast #includes: in which there is only an equality check, here there is an identity check" self do: [:each | anObject == each ifTrue: [^ true]]. ^ false! ! !Dictionary methodsFor: 'testing' stamp: 'RAA 8/23/2001 12:56'! includesKey: key "Answer whether the receiver has a key equal to the argument, key." self at: key ifAbsent: [^false]. ^true! ! !Dictionary methodsFor: 'testing' stamp: 'sw 3/23/2000 01:12'! keyForIdentity: anObject "If anObject is one of the values of the receive, return its key, else return nil. Contrast #keyAtValue: in which there is only an equality check, here there is an identity check" self associationsDo: [:assoc | assoc value == anObject ifTrue: [^ assoc key]]. ^ nil! ! !Dictionary methodsFor: 'testing'! occurrencesOf: anObject "Answer how many of the receiver's elements are equal to anObject." | count | count _ 0. self do: [:each | anObject = each ifTrue: [count _ count + 1]]. ^count! ! !Dictionary methodsFor: 'adding'! add: anAssociation | index element | index _ self findElementOrNil: anAssociation key. element _ array at: index. element == nil ifTrue: [self atNewIndex: index put: anAssociation] ifFalse: [element value: anAssociation value]. ^ anAssociation! ! !Dictionary methodsFor: 'adding' stamp: 'raok 12/17/2003 16:01'! addAll: aKeyedCollection aKeyedCollection == self ifFalse: [ aKeyedCollection keysAndValuesDo: [:key :value | self at: key put: value]]. ^aKeyedCollection! ! !Dictionary methodsFor: 'adding'! declare: key from: aDictionary "Add key to the receiver. If key already exists, do nothing. If aDictionary includes key, then remove it from aDictionary and use its association as the element of the receiver." (self includesKey: key) ifTrue: [^ self]. (aDictionary includesKey: key) ifTrue: [self add: (aDictionary associationAt: key). aDictionary removeKey: key] ifFalse: [self add: key -> nil]! ! !Dictionary methodsFor: 'removing' stamp: 'di 4/4/2000 11:47'! keysAndValuesRemove: keyValueBlock "Removes all entries for which keyValueBlock returns true." "When removing many items, you must not do it while iterating over the dictionary, since it may be changing. This method takes care of tallying the removals in a first pass, and then performing all the deletions afterward. Many places in the sytem could be simplified by using this method." | removals | removals _ OrderedCollection new. self associationsDo: [:assoc | (keyValueBlock value: assoc key value: assoc value) ifTrue: [removals add: assoc key]]. removals do: [:aKey | self removeKey: aKey]! ! !Dictionary methodsFor: 'removing'! remove: anObject self shouldNotImplement! ! !Dictionary methodsFor: 'removing'! remove: anObject ifAbsent: exceptionBlock self shouldNotImplement! ! !Dictionary methodsFor: 'removing'! removeKey: key "Remove key from the receiver. If key is not in the receiver, notify an error." ^ self removeKey: key ifAbsent: [self errorKeyNotFound]! ! !Dictionary methodsFor: 'removing'! removeKey: key ifAbsent: aBlock "Remove key (and its associated value) from the receiver. If key is not in the receiver, answer the result of evaluating aBlock. Otherwise, answer the value externally named by key." | index assoc | index _ self findElementOrNil: key. assoc _ array at: index. assoc == nil ifTrue: [ ^ aBlock value ]. array at: index put: nil. tally _ tally - 1. self fixCollisionsFrom: index. ^ assoc value! ! !Dictionary methodsFor: 'removing'! removeUnreferencedKeys "Undeclared removeUnreferencedKeys" ^ self unreferencedKeys do: [:key | self removeKey: key].! ! !Dictionary methodsFor: 'removing' stamp: 'dvf 8/23/2003 11:51'! unreferencedKeys "TextConstants unreferencedKeys" | n | ^'Scanning for references . . .' displayProgressAt: Sensor cursorPoint from: 0 to: self size during: [:bar | n := 0. self keys select: [:key | bar value: (n := n + 1). (self systemNavigation allCallsOn: (self associationAt: key)) isEmpty]]! ! !Dictionary methodsFor: 'enumerating'! associationsDo: aBlock "Evaluate aBlock for each of the receiver's elements (key/value associations)." super do: aBlock! ! !Dictionary methodsFor: 'enumerating'! collect: aBlock "Evaluate aBlock with each of my values as the argument. Collect the resulting values into a collection that is like me. Answer with the new collection." | newCollection | newCollection _ OrderedCollection new: self size. self do: [:each | newCollection add: (aBlock value: each)]. ^ newCollection! ! !Dictionary methodsFor: 'enumerating'! do: aBlock super do: [:assoc | aBlock value: assoc value]! ! !Dictionary methodsFor: 'enumerating' stamp: 'ar 7/11/1999 08:04'! keysAndValuesDo: aBlock ^self associationsDo:[:assoc| aBlock value: assoc key value: assoc value].! ! !Dictionary methodsFor: 'enumerating'! keysDo: aBlock "Evaluate aBlock for each of the receiver's keys." self associationsDo: [:association | aBlock value: association key]! ! !Dictionary methodsFor: 'enumerating'! select: aBlock "Evaluate aBlock with each of my values as the argument. Collect into a new dictionary, only those associations for which aBlock evaluates to true." | newCollection | newCollection _ self species new. self associationsDo: [:each | (aBlock value: each value) ifTrue: [newCollection add: each]]. ^newCollection! ! !Dictionary methodsFor: 'enumerating' stamp: 'dtl 2/17/2003 09:48'! valuesDo: aBlock "Evaluate aBlock for each of the receiver's values." self associationsDo: [:association | aBlock value: association value]! ! !Dictionary methodsFor: 'printing' stamp: 'MPW 1/4/1901 08:33'! flattenOnStream:aStream ^aStream writeDictionary:self. ! ! !Dictionary methodsFor: 'printing' stamp: 'sma 6/1/2000 09:52'! printElementsOn: aStream aStream nextPut: $(. self keysSortedSafely do: [:key | aStream print: key; nextPutAll: '->'; print: (self at: key); space]. aStream nextPut: $)! ! !Dictionary methodsFor: 'printing'! storeOn: aStream | noneYet | aStream nextPutAll: '(('. aStream nextPutAll: self class name. aStream nextPutAll: ' new)'. noneYet _ true. self associationsDo: [:each | noneYet ifTrue: [noneYet _ false] ifFalse: [aStream nextPut: $;]. aStream nextPutAll: ' add: '. aStream store: each]. noneYet ifFalse: [aStream nextPutAll: '; yourself']. aStream nextPut: $)! ! !Dictionary methodsFor: 'private' stamp: 'raok 4/22/2002 12:09'! copy "Must copy the associations, or later store will affect both the original and the copy" ^ self shallowCopy withArray: (array collect: [:assoc | assoc ifNil: [nil] ifNotNil: [Association key: assoc key value: assoc value]])! ! !Dictionary methodsFor: 'private'! errorKeyNotFound self error: 'key not found'! ! !Dictionary methodsFor: 'private'! errorValueNotFound self error: 'value not found'! ! !Dictionary methodsFor: 'private'! keyAt: index "May be overridden by subclasses so that fixCollisions will work" | assn | assn _ array at: index. assn == nil ifTrue: [^ nil] ifFalse: [^ assn key]! ! !Dictionary methodsFor: 'private'! noCheckAdd: anObject "Must be defined separately for Dictionary because (self findElementOrNil:) expects a key, not an association. 9/7/96 tk" array at: (self findElementOrNil: anObject key) put: anObject. tally _ tally + 1! ! !Dictionary methodsFor: 'private'! rehash "Smalltalk rehash." | newSelf | newSelf _ self species new: self size. self associationsDo: [:each | newSelf noCheckAdd: each]. array _ newSelf array! ! !Dictionary methodsFor: 'private'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element key = anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element key = anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !Dictionary methodsFor: 'private'! valueAtNewKey: aKey put: anObject atIndex: index declareFrom: aDictionary "Support for coordinating class variable and global declarations with variables that have been put in Undeclared so as to redirect all references to the undeclared variable." (aDictionary includesKey: aKey) ifTrue: [self atNewIndex: index put: ((aDictionary associationAt: aKey) value: anObject). aDictionary removeKey: aKey] ifFalse: [self atNewIndex: index put: (Association key: aKey value: anObject)]! ! !Dictionary methodsFor: 'user interface' stamp: 'tk 4/12/1998 08:54'! inspect "Open a DictionaryInspector on the receiver. Use basicInspect to get a normal (less useful) type of inspector." DictionaryInspector openOn: self withEvalPane: true! ! !Dictionary methodsFor: 'user interface' stamp: 'tk 4/12/1998 08:54'! inspectWithLabel: aLabel "Open a DictionaryInspector on the receiver. Use basicInspect to get a normal (less useful) type of inspector." DictionaryInspector openOn: self withEvalPane: true withLabel: aLabel! ! !Dictionary methodsFor: '*Compiler' stamp: 'ar 5/17/2003 14:07'! bindingOf: varName ^self associationAt: varName ifAbsent:[nil]! ! !Dictionary methodsFor: '*Compiler' stamp: 'ar 5/18/2003 20:33'! bindingsDo: aBlock ^self associationsDo: aBlock! ! !Dictionary methodsFor: 'comparing' stamp: 'raok 6/10/2002 15:29'! = aDictionary "Two dictionaries are equal if (a) they are the same 'kind' of thing. (b) they have the same set of keys. (c) for each (common) key, they have the same value". (aDictionary isKindOf: Dictionary) ifFalse: [^false]. self size = aDictionary size ifFalse: [^false]. self associationsDo: [:assoc| (aDictionary at: assoc key ifAbsent: [^false]) = assoc value ifFalse: [^false]]. ^true ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Dictionary class instanceVariableNames: ''! !Dictionary class methodsFor: 'instance creation'! newFrom: aDict "Answer an instance of me containing the same associations as aDict. Error if any key appears twice." | newDictionary | newDictionary _ self new: aDict size. aDict associationsDo: [:x | (newDictionary includesKey: x key) ifTrue: [self error: 'Duplicate key: ', x key printString] ifFalse: [newDictionary add: x]]. ^ newDictionary " NewDictionary newFrom: {1->#a. 2->#b. 3->#c} {1->#a. 2->#b. 3->#c} as: NewDictionary NewDictionary newFrom: {1->#a. 2->#b. 1->#c} {1->#a. 2->#b. 1->#c} as: NewDictionary "! ! Inspector subclass: #DictionaryInspector instanceVariableNames: 'keyArray' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !DictionaryInspector methodsFor: 'accessing'! fieldList ^ keyArray collect: [ :key | key printString ]! ! !DictionaryInspector methodsFor: 'accessing'! inspect: aDictionary "Initialize the receiver so that it is inspecting aDictionary. There is no current selection." self initialize. (aDictionary isKindOf: Dictionary) ifFalse: [^ self error: 'DictionaryInspectors can only inspect dictionaries' ]. object _ aDictionary. contents _ ''. self calculateKeyArray! ! !DictionaryInspector methodsFor: 'selecting' stamp: 'tk 4/11/1998 13:09'! addEntry: aKey object at: aKey put: nil. self calculateKeyArray. selectionIndex _ keyArray indexOf: aKey. self changed: #inspectObject. self changed: #fieldList. self update! ! !DictionaryInspector methodsFor: 'selecting' stamp: 'di 3/8/2000 09:14'! calculateKeyArray "Recalculate the KeyArray from the object being inspected" keyArray _ object keysSortedSafely asArray. selectionIndex _ 0. ! ! !DictionaryInspector methodsFor: 'selecting' stamp: 'di 9/22/1998 21:25'! contentsIsString "Hacked so contents empty when deselected" ^ (selectionIndex = 0)! ! !DictionaryInspector methodsFor: 'selecting'! replaceSelectionValue: anObject ^ object at: (keyArray at: selectionIndex) put: anObject! ! !DictionaryInspector methodsFor: 'selecting' stamp: 'ar 12/7/1999 18:12'! selection selectionIndex = 0 ifTrue: [^ '']. ^ object at: (keyArray at: selectionIndex) ifAbsent:[nil]! ! !DictionaryInspector methodsFor: 'selecting'! selectionUnmodifiable "For dicionary inspectors, any selection is modifiable" ^ selectionIndex <= 0! ! !DictionaryInspector methodsFor: 'menu' stamp: 'tk 4/12/1998 08:15'! addEntry | newKey aKey | newKey _ FillInTheBlank request: 'Enter new key, then type RETURN. (Expression will be evaluated for value.) Examples: #Fred ''a string'' 3+4'. aKey _ Compiler evaluate: newKey. object at: aKey put: nil. self calculateKeyArray. selectionIndex _ keyArray indexOf: aKey. self changed: #inspectObject. self changed: #fieldList. self update! ! !DictionaryInspector methodsFor: 'menu' stamp: 'ar 1/15/2001 18:37'! copyName "Copy the name of the current variable, so the user can paste it into the window below and work with is. If collection, do (xxx at: 1). " | sel | sel _ '(self at: ', (String streamContents: [:strm | (keyArray at: selectionIndex) storeOn: strm]) , ')'. Clipboard clipboardText: sel asText. "no undo allowed"! ! !DictionaryInspector methodsFor: 'menu' stamp: 'ssa 9/3/2008 11:06'! dictionaryMenu: aMenu "Set up the key-list menu for a dictionary inspector" aMenu title: 'Dictionary key'. ^ aMenu addList: #( ('inspect' inspectSelection) ('copy name' copyName) ('references' selectionReferences) ('objects pointing to this value' objectReferencesToSelection) ('senders of this key' sendersOfSelectedKey) - ('refresh view' calculateKeyArray) - ('add key' addEntry) ('rename key' renameEntry) ('remove' removeSelection) - ('basic inspect' inspectBasic))! ! !DictionaryInspector methodsFor: 'menu' stamp: 'tk 4/12/1998 08:19'! removeSelection selectionIndex = 0 ifTrue: [^ self changed: #flash]. object removeKey: (keyArray at: selectionIndex). selectionIndex _ 0. contents _ ''. self calculateKeyArray. self changed: #inspectObject. self changed: #fieldList. self changed: #selection. self changed: #selectionIndex.! ! !DictionaryInspector methodsFor: 'menu' stamp: 'tk 10/18/2002 16:41'! renameEntry | newKey aKey value | value _ object at: (keyArray at: selectionIndex). newKey _ FillInTheBlank request: 'Enter new key, then type RETURN. (Expression will be evaluated for value.) Examples: #Fred ''a string'' 3+4' initialAnswer: (keyArray at: selectionIndex) printString. aKey _ Compiler evaluate: newKey. object removeKey: (keyArray at: selectionIndex). object at: aKey put: value. self calculateKeyArray. selectionIndex _ keyArray indexOf: aKey. self changed: #inspectObject. self changed: #fieldList. self update! ! !DictionaryInspector methodsFor: 'menu' stamp: 'nk 6/26/2003 21:43'! selectionReferences "Create a browser on all references to the association of the current selection." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. object class == MethodDictionary ifTrue: [^ self changed: #flash]. self systemNavigation browseAllCallsOn: (object associationAt: (keyArray at: selectionIndex)). ! ! !DictionaryInspector methodsFor: 'menu' stamp: 'wiz 5/16/2004 13:05'! sendersOfSelectedKey "Create a browser on all senders of the selected key" | aKey | self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ((aKey := keyArray at: selectionIndex) isKindOf: Symbol) ifFalse: [^ self changed: #flash]. object class == MethodDictionary ifTrue: [^ self changed: #flash]. SystemNavigation default browseAllCallsOn: aKey! ! ArrayedCollection subclass: #DirectoryEntry instanceVariableNames: 'name creationTime modificationTime dirFlag fileSize' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !DirectoryEntry commentStamp: '<historical>' prior: 0! an entry in a directory; a reference to either a file or a directory.! !DirectoryEntry methodsFor: 'access' stamp: 'ls 7/15/1998 21:37'! creationTime "time the entry was created. (what's its type?)" ^creationTime! ! !DirectoryEntry methodsFor: 'access' stamp: 'ls 7/15/1998 21:38'! fileSize "size of the entry, if it's a file" ^fileSize! ! !DirectoryEntry methodsFor: 'access' stamp: 'ls 7/15/1998 21:38'! isDirectory "whether this entry represents a directory" ^dirFlag! ! !DirectoryEntry methodsFor: 'access' stamp: 'ls 7/15/1998 21:37'! modificationTime "time the entry was last modified" ^modificationTime! ! !DirectoryEntry methodsFor: 'access' stamp: 'ls 7/15/1998 21:37'! name "name of the entry" ^name! ! !DirectoryEntry methodsFor: 'access-compatibility' stamp: 'ls 7/15/1998 22:29'! at: index "compatibility interface" "self halt: 'old-style access to DirectoryEntry'" index = 1 ifTrue: [ ^self name ]. index = 2 ifTrue: [ ^self creationTime ]. index = 3 ifTrue: [ ^self modificationTime ]. index = 4 ifTrue:[ ^self isDirectory ]. index = 5 ifTrue:[ ^self fileSize ]. self error: 'invalid index specified'.! ! !DirectoryEntry methodsFor: 'access-compatibility' stamp: 'ls 7/15/1998 22:16'! size ^5! ! !DirectoryEntry methodsFor: 'private-initialization' stamp: 'ls 7/15/1998 21:42'! privateName: name0 creationTime: creationTime0 modificationTime: modificationTime0 isDirectory: isDirectory0 fileSize: fileSize0 name _ name0. creationTime _ creationTime0. modificationTime _ modificationTime0. dirFlag _ isDirectory0. fileSize _ fileSize0.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DirectoryEntry class instanceVariableNames: ''! !DirectoryEntry class methodsFor: 'instance creation' stamp: 'ls 7/15/1998 21:42'! fromArray: array ^self name: (array at: 1) creationTime: (array at: 2) modificationTime: (array at: 3) isDirectory: (array at: 4) fileSize: (array at: 5) ! ! !DirectoryEntry class methodsFor: 'instance creation' stamp: 'ls 7/15/1998 21:41'! name: name0 creationTime: creationTime modificationTime: modificationTime isDirectory: isDirectory fileSize: fileSize ^self new privateName: name0 creationTime: creationTime modificationTime: modificationTime isDirectory: isDirectory fileSize: fileSize! ! DisplayObject subclass: #DisplayMedium instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !DisplayMedium commentStamp: '<historical>' prior: 0! 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.! !DisplayMedium methodsFor: 'coloring'! fill: aRectangle fillColor: aForm "Replace a rectangular area of the receiver with the pattern described by aForm according to the rule over." self fill: aRectangle rule: Form over fillColor: aForm! ! !DisplayMedium methodsFor: 'coloring'! fill: aRectangle rule: anInteger fillColor: aForm "Replace a rectangular area of the receiver with the pattern described by aForm according to the rule anInteger." self subclassResponsibility! ! !DisplayMedium methodsFor: 'coloring'! fillBlack "Set all bits in the receiver to black (ones)." self fill: self boundingBox fillColor: Color black! ! !DisplayMedium methodsFor: 'coloring'! fillBlack: aRectangle "Set all bits in the receiver's area defined by aRectangle to black (ones)." self fill: aRectangle rule: Form over fillColor: Color black! ! !DisplayMedium methodsFor: 'coloring'! fillColor: aColor "Set all pixels in the receiver to the color. Must be a correct color for this depth of medium. TK 1 Jun 96" self fill: self boundingBox fillColor: aColor! ! !DisplayMedium methodsFor: 'coloring'! fillGray "Set all bits in the receiver to gray." self fill: self boundingBox fillColor: Color gray! ! !DisplayMedium methodsFor: 'coloring'! fillGray: aRectangle "Set all bits in the receiver's area defined by aRectangle to the gray mask." self fill: aRectangle rule: Form over fillColor: Color gray! ! !DisplayMedium methodsFor: 'coloring'! fillShape: aShapeForm fillColor: aColor "Fill a region corresponding to 1 bits in aShapeForm with aColor" ^ self fillShape: aShapeForm fillColor: aColor at: 0@0! ! !DisplayMedium methodsFor: 'coloring' stamp: 'ar 5/28/2000 12:06'! fillShape: aShapeForm fillColor: aColor at: location "Fill a region corresponding to 1 bits in aShapeForm with aColor" ((BitBlt current destForm: self sourceForm: aShapeForm fillColor: aColor combinationRule: Form paint destOrigin: location + aShapeForm offset sourceOrigin: 0@0 extent: self extent clipRect: self boundingBox) colorMap: (Bitmap with: 0 with: 16rFFFFFFFF)) copyBits! ! !DisplayMedium methodsFor: 'coloring'! fillWhite "Set all bits in the form to white." self fill: self boundingBox fillColor: Color white. ! ! !DisplayMedium methodsFor: 'coloring'! fillWhite: aRectangle "Set all bits in the receiver's area defined by aRectangle to white." self fill: aRectangle rule: Form over fillColor: Color white. ! ! !DisplayMedium methodsFor: 'coloring'! fillWithColor: aColor "Fill the receiver's bounding box with the given color." self fill: self boundingBox fillColor: aColor. ! ! !DisplayMedium methodsFor: 'coloring' stamp: 'jm 6/18/1999 19:01'! reverse "Change all the bits in the receiver that are white to black, and the ones that are black to white." self fill: self boundingBox rule: Form reverse fillColor: (Color quickHighLight: self depth)! ! !DisplayMedium methodsFor: 'coloring' stamp: 'jm 6/18/1999 19:00'! reverse: aRectangle "Change all the bits in the receiver's area that intersects with aRectangle that are white to black, and the ones that are black to white." self fill: aRectangle rule: Form reverse fillColor: (Color quickHighLight: self depth)! ! !DisplayMedium methodsFor: 'coloring'! reverse: aRectangle fillColor: aMask "Change all the bits in the receiver's area that intersects with aRectangle according to the mask. Black does not necessarily turn to white, rather it changes with respect to the rule and the bit in a corresponding mask location. Bound to give a surprise." self fill: aRectangle rule: Form reverse fillColor: aMask! ! !DisplayMedium methodsFor: 'bordering'! border: aRectangle width: borderWidth "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses black for drawing the border." self border: aRectangle width: borderWidth fillColor: Color black. ! ! !DisplayMedium methodsFor: 'bordering'! border: aRectangle width: borderWidth fillColor: aHalfTone "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: Form over fillColor: aHalfTone! ! !DisplayMedium methodsFor: 'bordering'! border: aRectangle width: borderWidth rule: combinationRule fillColor: aHalfTone "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: combinationRule fillColor: aHalfTone! ! !DisplayMedium methodsFor: 'bordering'! border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone "Paint a border whose rectangular area is defined by aRectangle. The width of each edge of the border is determined by the four coordinates of insets. Uses aHalfTone and combinationRule for drawing the border." (aRectangle areasOutside: (aRectangle insetBy: insets)) do: [:edgeStrip | self fill: edgeStrip rule: combinationRule fillColor: aHalfTone]! ! !DisplayMedium methodsFor: 'displaying'! copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm "Make up a BitBlt table and copy the bits." self subclassResponsibility! ! !DisplayMedium methodsFor: 'displaying' stamp: 'hmm 9/16/2000 21:27'! deferUpdatesIn: aRectangle while: aBlock "DisplayScreen overrides with something more involved..." ^aBlock value! ! !DisplayMedium methodsFor: 'displaying'! drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm "Draw line by copying the argument, sourceForm, starting at location beginPoint and ending at endPoint, clipped by the rectangle, clipRect. The rule and mask for copying are the arguments anInteger and aForm." self subclassResponsibility! ! Object subclass: #DisplayObject instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !DisplayObject commentStamp: '<historical>' prior: 0! The abstract protocol for most display primitives that are used by Views for presenting information on the screen.! !DisplayObject methodsFor: 'accessing'! extent "Answer the point that represents the width and height of the receiver's bounding box." ^self boundingBox extent! ! !DisplayObject methodsFor: 'accessing'! height "Answer the number that represents the height of the receiver's bounding box." ^self boundingBox height! ! !DisplayObject methodsFor: 'accessing'! offset "Answer the amount by which the receiver should be offset when it is displayed or its position is tested." self subclassResponsibility! ! !DisplayObject methodsFor: 'accessing'! offset: aPoint "Set the amount by which the receiver's position is offset." ^self! ! !DisplayObject methodsFor: 'accessing'! relativeRectangle "Answer a Rectangle whose top left corner is the receiver's offset position and whose width and height are the same as the receiver." ^Rectangle origin: self offset extent: self extent! ! !DisplayObject methodsFor: 'accessing'! width "Answer the number that represents the width of the receiver's bounding box." ^self boundingBox width! ! !DisplayObject methodsFor: 'truncation and round off'! rounded "Convert the offset of the receiver to integer coordinates." self offset: self offset rounded! ! !DisplayObject methodsFor: 'transforming'! align: alignmentPoint with: relativePoint "Translate the receiver's offset such that alignmentPoint aligns with relativePoint." self offset: (self offset translateBy: relativePoint - alignmentPoint)! ! !DisplayObject methodsFor: 'transforming'! scaleBy: aPoint "Scale the receiver's offset by aPoint." self offset: (self offset scaleBy: aPoint)! ! !DisplayObject methodsFor: 'transforming'! translateBy: aPoint "Translate the receiver's offset." self offset: (self offset translateBy: aPoint)! ! !DisplayObject methodsFor: 'display box access'! boundingBox "Answer the rectangular area that represents the boundaries of the receiver's space of information." ^self computeBoundingBox! ! !DisplayObject methodsFor: 'display box access'! center ^ self boundingBox center! ! !DisplayObject methodsFor: 'display box access'! computeBoundingBox "Answer the rectangular area that represents the boundaries of the receiver's area for displaying information. This is the primitive for computing the area if it is not already known." self subclassResponsibility! ! !DisplayObject methodsFor: 'display box access'! initialExtent "Included here for when a FormView is being opened as a window. (4@4) covers border widths." ^ self extent + (4@4) ! ! !DisplayObject methodsFor: 'displaying-generic'! displayAt: aDisplayPoint "Display the receiver located at aDisplayPoint with default settings for the displayMedium, rule and halftone." self displayOn: Display at: aDisplayPoint clippingBox: Display boundingBox rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium "Simple default display in order to see the receiver in the upper left corner of screen." self displayOn: aDisplayMedium at: 0 @ 0! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium at: aDisplayPoint "Display the receiver located at aDisplayPoint with default settings for rule and halftone." self displayOn: aDisplayMedium at: aDisplayPoint clippingBox: aDisplayMedium boundingBox rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle "Display the receiver located at aDisplayPoint with default settings for rule and halftone. Information to be displayed must be confined to the area that intersects with clipRectangle." self displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "This is the basic display primitive for graphic display objects. Display the receiver located at aDisplayPoint with rule, ruleInteger, and mask, aForm. Information to be displayed must be confined to the area that intersects with clipRectangle." self subclassResponsibility! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium at: aDisplayPoint rule: ruleInteger "Display the receiver located at aPoint with default setting for the halftone and clippingBox." self displayOn: aDisplayMedium at: aDisplayPoint clippingBox: aDisplayMedium boundingBox rule: ruleInteger fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle "Display primitive for the receiver where a DisplayTransformation is provided as an argument. Alignment is defaulted to the receiver's rectangle. Information to be displayed must be confined to the area that intersects with clipRectangle." self displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: self relativeRectangle center with: self relativeRectangle center rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint "Display primitive where a DisplayTransformation is provided as an argument, rule is over and mask is Form black. Information to be displayed must be confined to the area that intersects with clipRectangle." self displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm "Display the receiver where a DisplayTransformation is provided as an argument, rule is ruleInteger and mask is aForm. Translate by relativePoint-alignmentPoint. Information to be displayed must be confined to the area that intersects with clipRectangle." | absolutePoint | absolutePoint _ displayTransformation applyTo: relativePoint. self displayOn: aDisplayMedium at: (absolutePoint - alignmentPoint) clippingBox: clipRectangle rule: ruleInteger fillColor: aForm ! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle fixedPoint: aPoint "Display the receiver where a DisplayTransformation is provided as an argument, rule is over and mask is Form black. No translation. Information to be displayed must be confined to the area that intersects with clipRectangle." self displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: aPoint with: aPoint rule: Form over fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "Display the receiver where a DisplayTransformation is provided as an argument, rule is ruleInteger and mask is aForm. No translation. Information to be displayed must be confined to the area that intersects with clipRectangle." self displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: self relativeRectangle origin with: self relativeRectangle origin rule: ruleInteger fillColor: aForm! ! !DisplayObject methodsFor: 'displaying-generic'! displayOnPort: aPort self displayOnPort: aPort at: 0@0! ! !DisplayObject methodsFor: 'displaying-generic' stamp: 'jm 10/21/97 16:56'! displayOnPort: port at: location rule: rule port copyForm: self to: location rule: rule. ! ! !DisplayObject methodsFor: 'displaying-generic'! followCursor "Just show the Form following the mouse. 6/21/96 tk" Cursor blank showWhile: [self follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]] ! ! !DisplayObject methodsFor: 'displaying-Display'! display "Display the receiver on the Display at location 0,0." self displayOn: Display! ! !DisplayObject methodsFor: 'displaying-Display'! follow: locationBlock while: durationBlock "Move an image around on the Display. Restore the background continuously without causing flashing. The argument, locationBlock, supplies each new location, and the argument, durationBlock, supplies true to continue, and then false to stop. 8/20/96 sw: call follow:while:bitsBehind: to do the real work. Note that th method now returns the final bits behind as method value." | bitsBehind loc | bitsBehind _ Form fromDisplay: ((loc _ locationBlock value) extent: self extent). ^ self follow: locationBlock while: durationBlock bitsBehind: bitsBehind startingLoc: loc! ! !DisplayObject methodsFor: 'displaying-Display' stamp: 'ar 5/28/2000 12:06'! follow: locationBlock while: durationBlock bitsBehind: initialBitsBehind startingLoc: loc "Move an image around on the Display. Restore the background continuously without causing flashing. The argument, locationBlock, supplies each new location, and the argument, durationBlock, supplies true to continue or false to stop. This variant takes the bitsBehind as an input argument, and returns the final saved saved bits as method value." | location rect1 save1 save1Blt buffer bufferBlt newLoc rect2 bothRects | location _ loc. rect1 _ location extent: self extent. save1 _ initialBitsBehind. save1Blt _ BitBlt current toForm: save1. buffer _ Form extent: self extent*2 depth: Display depth. "Holds overlapping region" bufferBlt _ BitBlt current toForm: buffer. Display deferUpdates: true. self displayOn: Display at: location rule: Form paint. Display deferUpdates: false; forceToScreen: (location extent: self extent). [durationBlock value] whileTrue: [ newLoc _ locationBlock value. newLoc ~= location ifTrue: [ rect2 _ newLoc extent: self extent. bothRects _ rect1 merge: rect2. (rect1 intersects: rect2) ifTrue: [ "when overlap, buffer background for both rectangles" bufferBlt copyFrom: bothRects in: Display to: 0@0. bufferBlt copyFrom: save1 boundingBox in: save1 to: rect1 origin - bothRects origin. "now buffer is clean background; get new bits for save1" save1Blt copy: (0@0 extent: self extent) from: rect2 origin - bothRects origin in: buffer. self displayOnPort: bufferBlt at: rect2 origin - bothRects origin rule: Form paint. Display deferUpdates: true. Display copy: bothRects from: 0@0 in: buffer rule: Form over. Display deferUpdates: false; forceToScreen: bothRects] ifFalse: [ "when no overlap, do the simple thing (both rects might be too big)" Display deferUpdates: true. Display copy: (location extent: save1 extent) from: 0@0 in: save1 rule: Form over. save1Blt copyFrom: rect2 in: Display to: 0@0. self displayOn: Display at: newLoc rule: Form paint. Display deferUpdates: false; forceToScreen: (location extent: save1 extent); forceToScreen: (newLoc extent: self extent)]. location _ newLoc. rect1 _ rect2]]. ^ save1 displayOn: Display at: location ! ! !DisplayObject methodsFor: 'displaying-Display' stamp: 'di 9/12/97 11:09'! isTransparent ^ false! ! !DisplayObject methodsFor: 'displaying-Display'! slideFrom: startPoint to: stopPoint nSteps: nSteps "does not display at the first point, but does at the last" | i p delta | i_0. p_ startPoint. delta _ (stopPoint-startPoint) // nSteps. ^ self follow: [p_ p+delta] while: [(i_i+1) < nSteps]! ! !DisplayObject methodsFor: 'displaying-Display' stamp: 'jm 10/22/97 07:43'! slideFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs "Slide this object across the display over the given number of steps, pausing for the given number of milliseconds after each step." "Note: Does not display at the first point, but does at the last." | i p delta | i _ 0. p _ startPoint. delta _ (stopPoint - startPoint) / nSteps asFloat. ^ self follow: [(p _ p + delta) truncated] while: [ (Delay forMilliseconds: milliSecs) wait. (i _ i + 1) < nSteps] ! ! !DisplayObject methodsFor: 'displaying-Display' stamp: 'di 10/19/97 12:05'! slideFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs andStay: stayAtEnd "Does not display at the first point, but does at the last. Moreover, if stayAtEnd is true, it leaves the dragged image at the stopPoint" | i done | i _ 0. ^ self follow: [startPoint + ((stopPoint-startPoint) * i // nSteps)] while: [milliSecs ifNotNil: [(Delay forMilliseconds: milliSecs) wait]. ((done _ (i _ i+1) > nSteps) and: [stayAtEnd]) ifTrue: [^ self "Return without clearing the image"]. done not]! ! !DisplayObject methodsFor: 'displaying-Display' stamp: 'sr 6/6/2000 05:37'! slideWithFirstFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs "Slide this object across the display over the given number of steps, pausing for the given number of milliseconds after each step." "Note: Does display at the first point and at the last." | i p delta | i _ 0. delta _ stopPoint - startPoint / nSteps asFloat. p _ startPoint - delta. ^ self follow: [(p _ p + delta) truncated] while: [(Delay forMilliseconds: milliSecs) wait. (i _ i + 1) <= nSteps]! ! !DisplayObject methodsFor: 'fileIn/Out'! writeOnFileNamed: fileName "Saves the receiver on the file fileName in the format: fileCode, depth, extent, offset, bits." | file | file _ FileStream newFileNamed: fileName. file binary. file nextPut: 2. "file code = 2" self writeOn: file. file close " | f | [(f _ Form fromUser) boundingBox area>25] whileTrue: [f writeOnFileNamed: 'test.form'. (Form newFromFileNamed: 'test.form') display]. "! ! !DisplayObject methodsFor: 'fileIn/Out' stamp: 'tk 2/19/1999 07:20'! writeUncompressedOnFileNamed: fileName "Saves the receiver on the file fileName in the format: fileCode, depth, extent, offset, bits." | file | file _ FileStream newFileNamed: fileName. file binary. file nextPut: 2. "file code = 2" self writeUncompressedOn: file. file close " | f | [(f _ Form fromUser) boundingBox area>25] whileTrue: [f writeUncompressedOnFileNamed: 'test.form'. (Form fromBinaryStream: (FileStream oldFileNamed: 'test.form')) display]. "! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DisplayObject class instanceVariableNames: ''! !DisplayObject class methodsFor: 'fileIn/Out' stamp: 'mdr 8/31/2000 19:11'! collectionFromFileNamed: fileName "Answer a collection of Forms read from the external file named fileName. The file format is: fileCode, {depth, extent, offset, bits}." | formList f fileCode | formList _ OrderedCollection new. f _ (FileStream readOnlyFileNamed: fileName) binary. fileCode _ f next. fileCode = 1 ifTrue: [ [f atEnd] whileFalse: [formList add: (self new readFromOldFormat: f)]] ifFalse: [ fileCode = 2 ifFalse: [self error: 'unknown Form file format'. ^ formList]. [f atEnd] whileFalse: [formList add: (self new readFrom: f)]]. f close. ^ formList ! ! !DisplayObject class methodsFor: 'fileIn/Out'! writeCollection: coll onFileNamed: fileName "Saves a collection of Forms on the file fileName in the format: fileCode, {depth, extent, offset, bits}." | file | file _ FileStream newFileNamed: fileName. file binary. file nextPut: 2. "file code = 2" coll do: [:f | f writeOn: file]. file close " | f c | c _ OrderedCollection new. [(f _ Form fromUser) boundingBox area>25] whileTrue: [c add: f]. Form writeCollection: c onFileNamed: 'test.forms'. c _ Form collectionFromFileNamed: 'test.forms'. 1 to: c size do: [:i | (c at: i) displayAt: 0@(i*100)]. "! ! CharacterScanner subclass: #DisplayScanner instanceVariableNames: 'bitBlt lineY runX foregroundColor backgroundColor fillBlt lineHeight paragraph paragraphColor morphicOffset ignoreColorChanges' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !DisplayScanner commentStamp: '<historical>' prior: 0! My instances are used to scan text and display it on the screen or in a hidden form.! !DisplayScanner methodsFor: 'scanning' stamp: 'ar 12/17/2001 13:28'! placeEmbeddedObject: anchoredMorph anchoredMorph relativeTextAnchorPosition ifNotNil:[ anchoredMorph position: anchoredMorph relativeTextAnchorPosition + (anchoredMorph owner textBounds origin x @ 0) - (0@morphicOffset y) + (0@lineY). ^true ]. (super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false]. anchoredMorph isMorph ifTrue: [ anchoredMorph position: ((destX - anchoredMorph width)@lineY) - morphicOffset ] ifFalse: [ destY _ lineY. runX _ destX. anchoredMorph displayOn: bitBlt destForm at: destX - anchoredMorph width @ destY clippingBox: bitBlt clipRect ]. ^ true! ! !DisplayScanner methodsFor: 'private' stamp: 'ar 5/17/2000 19:26'! setDestForm: df bitBlt setDestForm: df.! ! !DisplayScanner methodsFor: 'private' stamp: 'di 9/3/2000 16:13'! setFont foregroundColor _ paragraphColor. super setFont. "Sets font and emphasis bits, and maybe foregroundColor" font installOn: bitBlt foregroundColor: foregroundColor backgroundColor: Color transparent. text ifNotNil:[destY _ lineY + line baseline - font ascent]! ! !DisplayScanner methodsFor: 'private' stamp: 'ar 1/8/2000 14:51'! textColor: textColor ignoreColorChanges ifTrue: [^ self]. foregroundColor _ textColor! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'ar 1/8/2000 14:42'! cr "When a carriage return is encountered, simply increment the pointer into the paragraph." lastIndex_ lastIndex + 1. ^false! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'di 9/3/2000 16:24'! crossedX "This condition will sometimes be reached 'legally' during display, when, for instance the space that caused the line to wrap actually extends over the right boundary. This character is allowed to display, even though it is technically outside or straddling the clipping ectangle since it is in the normal case not visible and is in any case appropriately clipped by the scanner." ^ true ! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'di 9/3/2000 16:24'! endOfRun "The end of a run in the display case either means that there is actually a change in the style (run code) to be associated with the string or the end of this line has been reached." | runLength | lastIndex = line last ifTrue: [^true]. runX _ destX. runLength _ text runLengthFor: (lastIndex _ lastIndex + 1). runStopIndex _ lastIndex + (runLength - 1) min: line last. self setStopConditions. ^ false! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'di 9/3/2000 16:20'! paddedSpace "Each space is a stop condition when the alignment is right justified. Padding must be added to the base width of the space according to which space in the line this space is and according to the amount of space that remained at the end of the line when it was composed." spaceCount _ spaceCount + 1. destX _ destX + spaceWidth + (line justifiedPadFor: spaceCount). lastIndex _ lastIndex + 1. ^ false! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'hmm 7/16/2000 08:23'! plainTab | oldX | oldX _ destX. super plainTab. fillBlt == nil ifFalse: [fillBlt destX: oldX destY: destY width: destX - oldX height: font height; copyBits]! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'ar 12/15/2001 23:28'! setStopConditions "Set the font and the stop conditions for the current run." self setFont. alignment = Justified ifTrue:[ "Make a local copy of stop conditions so we don't modify the default" stopConditions == DefaultStopConditions ifTrue:[stopConditions _ stopConditions copy]. stopConditions at: Space asciiValue + 1 put: #paddedSpace]! ! !DisplayScanner methodsFor: 'stop conditions' stamp: 'hmm 7/16/2000 08:23'! tab self plainTab. lastIndex _ lastIndex + 1. ^ false! ! !DisplayScanner methodsFor: 'MVC-compatibility' stamp: 'BG 12/15/2003 13:02'! displayLines: linesInterval in: aParagraph clippedBy: visibleRectangle "The central display routine. The call on the primitive (scanCharactersFrom:to:in:rightX:) will be interrupted according to an array of stop conditions passed to the scanner at which time the code to handle the stop condition is run and the call on the primitive continued until a stop condition returns true (which means the line has terminated)." | runLength done stopCondition leftInRun startIndex string lastPos | "leftInRun is the # of characters left to scan in the current run; when 0, it is time to call 'self setStopConditions'" morphicOffset _ 0@0. leftInRun _ 0. self initializeFromParagraph: aParagraph clippedBy: visibleRectangle. ignoreColorChanges _ false. paragraph _ aParagraph. foregroundColor _ paragraphColor _ aParagraph foregroundColor. backgroundColor _ aParagraph backgroundColor. aParagraph backgroundColor isTransparent ifTrue: [fillBlt _ nil] ifFalse: [fillBlt _ bitBlt copy. "Blt to fill spaces, tabs, margins" fillBlt sourceForm: nil; sourceOrigin: 0@0. fillBlt fillColor: aParagraph backgroundColor]. rightMargin _ aParagraph rightMarginForDisplay. lineY _ aParagraph topAtLineIndex: linesInterval first. bitBlt destForm deferUpdatesIn: visibleRectangle while: [ linesInterval do: [:lineIndex | leftMargin _ aParagraph leftMarginForDisplayForLine: lineIndex alignment: (alignment ifNil:[textStyle alignment]). destX _ (runX _ leftMargin). line _ aParagraph lines at: lineIndex. lineHeight _ line lineHeight. fillBlt == nil ifFalse: [fillBlt destX: visibleRectangle left destY: lineY width: visibleRectangle width height: lineHeight; copyBits]. lastIndex _ line first. leftInRun <= 0 ifTrue: [self setStopConditions. "also sets the font" leftInRun _ text runLengthFor: line first]. destY _ lineY + line baseline - font ascent. "Should have happened in setFont" runLength _ leftInRun. runStopIndex _ lastIndex + (runLength - 1) min: line last. leftInRun _ leftInRun - (runStopIndex - lastIndex + 1). spaceCount _ 0. done _ false. string _ text string. self handleIndentation. [done] whileFalse:[ startIndex _ lastIndex. lastPos _ destX@destY. stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex in: string rightX: rightMargin stopConditions: stopConditions kern: kern. lastIndex >= startIndex ifTrue:[ font displayString: string on: bitBlt from: startIndex to: lastIndex at: lastPos kern: kern]. "see setStopConditions for stopping conditions for displaying." done _ self perform: stopCondition]. fillBlt == nil ifFalse: [kern ~= 0 ifTrue: [destX := destX - kern]. fillBlt destX: destX destY: lineY width: visibleRectangle right-destX height: lineHeight; copyBits]. lineY _ lineY + lineHeight]]! ! !DisplayScanner methodsFor: 'MVC-compatibility' stamp: 'BEO 8/7/2002 16:13'! initializeFromParagraph: aParagraph clippedBy: clippingRectangle super initializeFromParagraph: aParagraph clippedBy: clippingRectangle. bitBlt _ BitBlt current toForm: aParagraph destinationForm. bitBlt sourceX: 0; width: 0. "Init BitBlt so that the first call to a primitive will not fail" bitBlt combinationRule: ((Display depth = 1) ifTrue: [aParagraph rule] ifFalse: [Form paint]). bitBlt colorMap: (Bitmap with: 0 "Assumes 1-bit deep fonts" with: (bitBlt destForm pixelValueFor: aParagraph foregroundColor)). bitBlt clipRect: clippingRectangle! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DisplayScanner class instanceVariableNames: ''! !DisplayScanner class methodsFor: 'queries' stamp: 'ar 5/17/2000 17:39'! defaultFont ^ TextStyle defaultFont! ! Form subclass: #DisplayScreen instanceVariableNames: 'clippingBox extraRegions' classVariableNames: 'DeferringUpdates DisplayChangeSignature ScreenSave' poolDictionaries: '' category: 'Graphics-Display Objects'! !DisplayScreen commentStamp: '<historical>' prior: 0! 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. 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. To change the depth of your Display... Display newDepth: 16. Display newDepth: 8. Display newDepth: 1. 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. 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. ! !DisplayScreen methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:07'! copyBits: rect from: sf at: destOrigin clippingBox: clipRect rule: cr fillColor: hf (BitBlt current destForm: self sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: rect origin extent: rect extent clipRect: (clipRect intersect: clippingBox)) copyBits! ! !DisplayScreen methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:07'! copyBits: rect from: sf at: destOrigin clippingBox: clipRect rule: cr fillColor: hf map: map ((BitBlt current destForm: self sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: rect origin extent: rect extent clipRect: (clipRect intersect: clippingBox)) colorMap: map) copyBits! ! !DisplayScreen methodsFor: 'displaying' stamp: 'jm 5/22/1998 01:23'! flash: aRectangle "Flash the area of the screen defined by the given rectangle." self reverse: aRectangle. self forceDisplayUpdate. (Delay forMilliseconds: 100) wait. self reverse: aRectangle. self forceDisplayUpdate. ! ! !DisplayScreen methodsFor: 'other'! boundingBox clippingBox == nil ifTrue: [clippingBox _ super boundingBox]. ^ clippingBox! ! !DisplayScreen methodsFor: 'other'! clippingTo: aRect do: aBlock "Display clippingTo: Rectangle fromUser do: [ScheduledControllers restore: Display fullBoundingBox]" | saveClip | saveClip _ clippingBox. clippingBox _ aRect. aBlock value. clippingBox _ saveClip! ! !DisplayScreen methodsFor: 'other' stamp: 'hmm 6/18/2000 19:16'! deferUpdates: aBoolean | wasDeferred | "Set the deferUpdates flag in the virtual machine. When this flag is true, BitBlt operations on the Display are not automatically propagated to the screen. If this underlying platform does not support deferred updates, this primitive will fail. Answer whether updates were deferred before if the primitive succeeds, nil if it fails." wasDeferred _ DeferringUpdates == true. DeferringUpdates _ aBoolean. ^(self primitiveDeferUpdates: aBoolean) ifNotNil: [wasDeferred]! ! !DisplayScreen methodsFor: 'other' stamp: 'hmm 2/2/2001 10:14'! deferUpdatesIn: aRectangle while: aBlock | result | (self deferUpdates: true) ifTrue: [^aBlock value]. result _ aBlock value. self deferUpdates: false. self forceToScreen: aRectangle. ^result! ! !DisplayScreen methodsFor: 'other' stamp: 'jm 5/21/1998 23:48'! forceDisplayUpdate "On platforms that buffer screen updates, force the screen to be updated immediately. On other platforms, or if the primitive is not implemented, do nothing." <primitive: 231> "do nothing if primitive fails"! ! !DisplayScreen methodsFor: 'other' stamp: 'jm 5/19/1998 17:50'! forceToScreen: aRectangle "Force the given rectangular section of the Display to be copied to the screen. The primitive call does nothing if the primitive is not implemented. Typically used when the deferUpdates flag in the virtual machine is on; see deferUpdates:." self primShowRectLeft: aRectangle left right: aRectangle right top: aRectangle top bottom: aRectangle bottom. ! ! !DisplayScreen methodsFor: 'other'! fullBoundingBox ^ super boundingBox! ! !DisplayScreen methodsFor: 'other'! fullScreen "Display fullScreen" ScreenSave notNil ifTrue: [Display _ ScreenSave]. clippingBox _ super boundingBox! ! !DisplayScreen methodsFor: 'other' stamp: 'sd 6/7/2003 19:46'! fullScreenMode: aBoolean "On platforms that support it, set full-screen mode to the value of the argument. (Note: you'll need to restore the Display after calling this primitive." "Display fullScreenMode: true. Display newDepth: Display depth" <primitive: 233> self primitiveFailed ! ! !DisplayScreen methodsFor: 'other'! height ^ self boundingBox height! ! !DisplayScreen methodsFor: 'other' stamp: 'ar 5/5/1999 23:44'! newDepth: pixelSize " Display newDepth: 8. Display newDepth: 1. " (self supportsDisplayDepth: pixelSize) ifFalse:[^self inform:'Display depth ', pixelSize printString, ' is not supported on this system']. self newDepthNoRestore: pixelSize. self restore.! ! !DisplayScreen methodsFor: 'other' stamp: 'hmm 6/18/2000 19:14'! primitiveDeferUpdates: aBoolean "Set the deferUpdates flag in the virtual machine. When this flag is true, BitBlt operations on the Display are not automatically propagated to the screen. If this underlying platform does not support deferred updates, this primitive will fail. Answer the receiver if the primitive succeeds, nil if it fails." <primitive: 126> ^ nil "answer nil if primitive fails" ! ! !DisplayScreen methodsFor: 'other'! replacedBy: aForm do: aBlock "Permits normal display to draw on aForm instead of the display." ScreenSave _ self. Display _ aForm. aBlock value. Display _ self. ScreenSave _ nil.! ! !DisplayScreen methodsFor: 'other' stamp: 'BG 10/28/2003 20:53'! restore Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers unCacheWindows; restore].! ! !DisplayScreen methodsFor: 'other' stamp: 'BG 10/28/2003 20:53'! restoreAfter: aBlock "Evaluate the block, wait for a mouse click, and then restore the screen." aBlock value. Sensor waitButton. Smalltalk isMorphic ifTrue: [] ifFalse: [(ScheduledControllers restore; activeController) view emphasize]! ! !DisplayScreen methodsFor: 'other' stamp: 'ar 5/17/2001 21:02'! supportedDisplayDepths "Return all pixel depths supported on the current host platform." ^#(1 2 4 8 16 32 -1 -2 -4 -8 -16 -32) select: [:d | self supportsDisplayDepth: d]! ! !DisplayScreen methodsFor: 'other' stamp: 'ar 5/5/1999 23:45'! supportsDisplayDepth: pixelDepth "Return true if this pixel depth is supported on the current host platform. Primitive. Optional." <primitive: 91> ^#(1 2 4 8 16 32) includes: pixelDepth! ! !DisplayScreen methodsFor: 'other'! usableArea "Answer the usable area of the receiver. 5/22/96 sw." ^ self boundingBox deepCopy! ! !DisplayScreen methodsFor: 'other'! width ^ self boundingBox width! ! !DisplayScreen methodsFor: 'private'! beDisplay "Primitive. Tell the interpreter to use the receiver as the current display image. Fail if the form is too wide to fit on the physical display. Essential. See Object documentation whatIsAPrimitive." <primitive: 102> self primitiveFailed! ! !DisplayScreen methodsFor: 'private' stamp: 'di 3/3/1999 10:00'! copyFrom: aForm "Take on all state of aForm, with complete sharing" super copyFrom: aForm. clippingBox _ super boundingBox! ! !DisplayScreen methodsFor: 'private' stamp: 'ar 5/25/2000 23:43'! findAnyDisplayDepth "Return any display depth that is supported on this system." ^self findAnyDisplayDepthIfNone:[ "Ugh .... now this is a biggie - a system that does not support any of the Squeak display depths at all." Smalltalk logError:'Fatal error: This system has no support for any display depth at all.' inContext: thisContext to: 'SqueakDebug.log'. Smalltalk quitPrimitive. "There is no way to continue from here" ].! ! !DisplayScreen methodsFor: 'private' stamp: 'ar 5/17/2001 21:03'! findAnyDisplayDepthIfNone: aBlock "Return any display depth that is supported on this system. If there is none, evaluate aBlock." #(1 2 4 8 16 32 -1 -2 -4 -8 -16 -32) do:[:bpp| (self supportsDisplayDepth: bpp) ifTrue:[^bpp]. ]. ^aBlock value! ! !DisplayScreen methodsFor: 'private' stamp: 'ar 5/17/2001 15:44'! newDepthNoRestore: pixelSize "Change depths. Check if there is enough space!! , di" | area need | pixelSize = depth ifTrue: [^ self "no change"]. pixelSize abs < self depth ifFalse: ["Make sure there is enough space" area _ Display boundingBox area. "pixels" Smalltalk isMorphic ifFalse: [ScheduledControllers scheduledWindowControllers do: [:aController | "This should be refined..." aController view cacheBitsAsTwoTone ifFalse: [area _ area + aController view windowBox area]]]. need _ (area * (pixelSize abs - self depth) // 8) "new bytes needed" + Smalltalk lowSpaceThreshold. (Smalltalk garbageCollectMost <= need and: [Smalltalk garbageCollect <= need]) ifTrue: [self error: 'Insufficient free space']]. self setExtent: self extent depth: pixelSize. Smalltalk isMorphic ifFalse: [ScheduledControllers updateGray]. DisplayScreen startUp! ! !DisplayScreen methodsFor: 'private' stamp: 'jm 6/3/1998 13:00'! primRetryShowRectLeft: l right: r top: t bottom: b "Copy the given rectangular section of the Display to to the screen. This primitive is not implemented on all platforms. Do nothing if it fails. " <primitive: 127> "do nothing if primitive fails" ! ! !DisplayScreen methodsFor: 'private' stamp: 'jm 6/3/1998 13:02'! primShowRectLeft: l right: r top: t bottom: b "Copy the given rectangular section of the Display to to the screen. This primitive is not implemented on all platforms. If this fails, retry integer coordinates." <primitive: 127> "if this fails, coerce coordinates to integers and try again" self primRetryShowRectLeft: l truncated right: r rounded top: t truncated bottom: b rounded. ! ! !DisplayScreen methodsFor: 'private' stamp: 'RAA 11/27/1999 15:48'! setExtent: aPoint depth: bitsPerPixel "DisplayScreen startUp" "This method is critical. If the setExtent fails, there will be no proper display on which to show the error condition..." "ar 5/1/1999: ... and that is exactly why we check for the available display depths first." "RAA 27 Nov 99 - if depth and extent are the same and acceptable, why go through this. also - record when we change so worlds can tell if it is time to repaint" (depth == bitsPerPixel and: [aPoint = self extent and: [self supportsDisplayDepth: bitsPerPixel]]) ifFalse: [ bits _ nil. "Free up old bitmap in case space is low" DisplayChangeSignature _ (DisplayChangeSignature ifNil: [0]) + 1. (self supportsDisplayDepth: bitsPerPixel) ifTrue:[super setExtent: aPoint depth: bitsPerPixel] ifFalse:["Search for a suitable depth" super setExtent: aPoint depth: self findAnyDisplayDepth]. ]. clippingBox _ super boundingBox! ! !DisplayScreen methodsFor: 'initialize-release' stamp: 'ar 5/26/2000 00:07'! release "I am no longer Display. Release any resources if necessary"! ! !DisplayScreen methodsFor: 'initialize-release' stamp: 'ar 5/28/2000 11:25'! shutDown "Minimize Display memory saved in image" self setExtent: 240@120 depth: depth! ! !DisplayScreen methodsFor: 'testing' stamp: 'ar 5/25/2000 23:34'! isDisplayScreen ^true! ! !DisplayScreen methodsFor: 'blitter defaults' stamp: 'ar 5/28/2000 12:01'! defaultBitBltClass "Return the BitBlt version to use when I am active" ^BitBlt! ! !DisplayScreen methodsFor: 'blitter defaults' stamp: 'BG 10/29/2003 08:33'! defaultCanvasClass "Return the WarpBlt version to use when I am active" ^BitBlt! ! !DisplayScreen methodsFor: 'blitter defaults' stamp: 'ar 5/28/2000 12:01'! defaultWarpBltClass "Return the WarpBlt version to use when I am active" ^WarpBlt! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DisplayScreen class instanceVariableNames: ''! !DisplayScreen class methodsFor: 'display box access'! boundingBox "Answer the bounding box for the form representing the current display screen." ^Display boundingBox! ! !DisplayScreen class methodsFor: 'display box access' stamp: 'BG 10/28/2003 20:54'! checkForNewScreenSize "Check whether the screen size has changed and if so take appropriate actions" Display extent = DisplayScreen actualScreenSize ifTrue: [^ self]. DisplayScreen startUp. Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers restore; searchForActiveController]! ! !DisplayScreen class methodsFor: 'snapshots'! actualScreenSize <primitive: 106> ^ 640@480! ! !DisplayScreen class methodsFor: 'snapshots' stamp: 'ar 5/28/2000 11:26'! shutDown "Minimize Display memory saved in image" Display shutDown.! ! !DisplayScreen class methodsFor: 'snapshots' stamp: 'ar 5/17/2001 15:50'! startUp "DisplayScreen startUp" Display setExtent: self actualScreenSize depth: Display nativeDepth. Display beDisplay! ! DisplayObject subclass: #DisplayText instanceVariableNames: 'text textStyle offset form foreColor backColor' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Display Objects'! !DisplayText commentStamp: '<historical>' prior: 0! 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.! !DisplayText methodsFor: 'accessing'! alignedTo: alignPointSelector "Return a copy with offset according to alignPointSelector which is one of... #(topLeft, topCenter, topRight, leftCenter, center, etc)" | boundingBox | boundingBox _ 0@0 corner: self form extent. ^ self shallowCopy offset: (0@0) - (boundingBox perform: alignPointSelector)! ! !DisplayText methodsFor: 'accessing'! fontsUsed "Return a list of all fonts used currently in this text. 8/19/96 tk" ^ text runs values asSet collect: [:each | textStyle fontAt: each]! ! !DisplayText methodsFor: 'accessing'! form "Answer the form into which the receiver's display bits are cached." form == nil ifTrue: [self composeForm]. ^form! ! !DisplayText methodsFor: 'accessing'! lineGrid "Answer the relative space between lines of the receiver's text." ^textStyle lineGrid! ! !DisplayText methodsFor: 'accessing'! numberOfLines "Answer the number of lines of text in the receiver." ^self height // text lineGrid! ! !DisplayText methodsFor: 'accessing'! offset "Refer to the comment in DisplayObject|offset." ^offset! ! !DisplayText methodsFor: 'accessing'! offset: aPoint "Refer to the comment in DisplayObject|offset:." offset _ aPoint! ! !DisplayText methodsFor: 'accessing'! string "Answer the string of the characters displayed by the receiver." ^text string! ! !DisplayText methodsFor: 'accessing'! text "Answer the text displayed by the receiver." ^text! ! !DisplayText methodsFor: 'accessing'! text: aText "Set the receiver to display the argument, aText." text _ aText. form _ nil. self changed. ! ! !DisplayText methodsFor: 'accessing'! textStyle "Answer the style by which the receiver displays its text." ^textStyle! ! !DisplayText methodsFor: 'accessing'! textStyle: aTextStyle "Set the style by which the receiver should display its text." textStyle _ aTextStyle. form _ nil. self changed. ! ! !DisplayText methodsFor: 'displaying' stamp: 'yo 6/23/2003 20:05'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "For TT font, rule 34 is used if possible." "Refer to the comment in DisplayObject|displayOn:at:clippingBox:rule:mask:." | form1 rule | form1 _ self form. rule _ (ruleInteger = Form over and: [backColor isTransparent]) ifTrue: [form1 depth = 32 ifTrue: [rule _ 34] ifFalse: [Form paint]] ifFalse: [ruleInteger]. form1 depth = 32 ifTrue: [rule _ 34]. form1 displayOn: aDisplayMedium at: aDisplayPoint + offset clippingBox: clipRectangle rule: rule fillColor: aForm! ! !DisplayText methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm "Refer to the comment in DisplayObject|displayOn:transformation:clippingBox:align:with:rule:mask:." | absolutePoint | absolutePoint _ displayTransformation applyTo: relativePoint. absolutePoint _ absolutePoint x asInteger @ absolutePoint y asInteger. self displayOn: aDisplayMedium at: absolutePoint - alignmentPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm! ! !DisplayText methodsFor: 'displaying'! displayOnPort: aPort at: location self form displayOnPort: aPort at: location + offset! ! !DisplayText methodsFor: 'display box access'! boundingBox "Refer to the comment in DisplayObject|boundingBox." ^self form boundingBox! ! !DisplayText methodsFor: 'display box access'! computeBoundingBox "Compute minimum enclosing rectangle around characters." | character font width carriageReturn lineWidth lineHeight | carriageReturn _ Character cr. width _ lineWidth _ 0. font _ textStyle defaultFont. lineHeight _ textStyle lineGrid. 1 to: text size do: [:i | character _ text at: i. character = carriageReturn ifTrue: [lineWidth _ lineWidth max: width. lineHeight _ lineHeight + textStyle lineGrid. width _ 0] ifFalse: [width _ width + (font widthOf: character)]]. lineWidth _ lineWidth max: width. ^offset extent: lineWidth @ lineHeight! ! !DisplayText methodsFor: 'converting' stamp: 'tk 10/21/97 12:28'! asParagraph "Answer a Paragraph whose text and style are identical to that of the receiver." | para | para _ Paragraph withText: text style: textStyle. para foregroundColor: foreColor backgroundColor: backColor. backColor isTransparent ifTrue: [para rule: Form paint]. ^ para! ! !DisplayText methodsFor: 'private' stamp: 'BG 10/28/2003 20:54'! composeForm Smalltalk isMorphic ifTrue: [] ifFalse: [form _ self asParagraph asForm]! ! !DisplayText methodsFor: 'private'! setText: aText textStyle: aTextStyle offset: aPoint text _ aText. textStyle _ aTextStyle. offset _ aPoint. form _ nil! ! !DisplayText methodsFor: 'color'! backgroundColor backColor == nil ifTrue: [^ Color transparent]. ^ backColor! ! !DisplayText methodsFor: 'color'! foregroundColor foreColor == nil ifTrue: [^ Color black]. ^ foreColor! ! !DisplayText methodsFor: 'color'! foregroundColor: cf backgroundColor: cb foreColor _ cf. backColor _ cb! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DisplayText class instanceVariableNames: ''! !DisplayText class methodsFor: 'instance creation'! text: aText "Answer an instance of me such that the text displayed is aText according to the system's default text style." ^self new setText: aText textStyle: DefaultTextStyle copy offset: 0 @ 0! ! !DisplayText class methodsFor: 'instance creation'! text: aText textStyle: aTextStyle "Answer an instance of me such that the text displayed is aText according to the style specified by aTextStyle." ^self new setText: aText textStyle: aTextStyle offset: 0 @ 0! ! !DisplayText class methodsFor: 'instance creation'! text: aText textStyle: aTextStyle offset: aPoint "Answer an instance of me such that the text displayed is aText according to the style specified by aTextStyle. The display of the information should be offset by the amount given as the argument, aPoint." ^self new setText: aText textStyle: aTextStyle offset: aPoint! ! !DisplayText class methodsFor: 'examples' stamp: 'tk 11/28/2001 16:03'! example "Continually prints two lines of text wherever you point with the cursor. Terminate by pressing any button on the mouse." | tx | tx _ 'this is a line of characters and this is the second line.' asDisplayText. tx foregroundColor: Color black backgroundColor: Color transparent. tx _ tx alignedTo: #center. [Sensor anyButtonPressed] whileFalse: [tx displayOn: Display at: Sensor cursorPoint] "DisplayText example."! ! View subclass: #DisplayTextView instanceVariableNames: 'rule mask editParagraph centered' classVariableNames: '' poolDictionaries: '' category: 'ST80-Views'! !DisplayTextView commentStamp: '<historical>' prior: 0! I represent a view of an instance of DisplayText.! !DisplayTextView methodsFor: 'initialize-release'! initialize "Refer to the comment in View|initialize." super initialize. centered _ false! ! !DisplayTextView methodsFor: 'accessing'! centered centered _ true. self centerText! ! !DisplayTextView methodsFor: 'accessing'! fillColor "Answer an instance of class Form that is to be used as the mask when displaying the receiver's model (a DisplayText)." ^ mask! ! !DisplayTextView methodsFor: 'accessing'! fillColor: aForm "Set aForm to be the mask used when displaying the receiver's model." mask _ aForm! ! !DisplayTextView methodsFor: 'accessing'! isCentered ^centered! ! !DisplayTextView methodsFor: 'accessing'! mask "Answer an instance of class Form that is to be used as the mask when displaying the receiver's model (a DisplayText)." ^ mask! ! !DisplayTextView methodsFor: 'accessing'! rule "Answer a number from 0 to 15 that indicates which of the sixteen display rules is to be used when copying the receiver's model (a DisplayText) onto the display screen." rule == nil ifTrue: [^self defaultRule] ifFalse: [^rule]! ! !DisplayTextView methodsFor: 'accessing'! rule: anInteger "Set anInteger to be the rule used when displaying the receiver's model." rule _ anInteger! ! !DisplayTextView methodsFor: 'controller access'! defaultController "Refer to the comment in View|defaultController." ^self defaultControllerClass newParagraph: editParagraph! ! !DisplayTextView methodsFor: 'controller access'! defaultControllerClass "Refer to the comment in View|defaultControllerClass." ^ParagraphEditor! ! !DisplayTextView methodsFor: 'window access'! defaultWindow "Refer to the comment in View|defaultWindow." ^self inverseDisplayTransform: (editParagraph boundingBox expandBy: 6 @ 6)! ! !DisplayTextView methodsFor: 'window access'! window: aWindow "Refer to the comment in View|window:." super window: aWindow. self centerText! ! !DisplayTextView methodsFor: 'model access'! model: aDisplayText "Refer to the comment in View|model:." super model: aDisplayText. editParagraph _ model asParagraph. self centerText! ! !DisplayTextView methodsFor: 'displaying'! display "Refer to the comment in View|display." self isUnlocked ifTrue: [self positionText]. super display! ! !DisplayTextView methodsFor: 'displaying'! displayView "Refer to the comment in View|displayView." self clearInside. (self controller isKindOf: ParagraphEditor ) ifTrue: [controller changeParagraph: editParagraph]. editParagraph foregroundColor: self foregroundColor backgroundColor: self backgroundColor. self isCentered ifTrue: [editParagraph displayOn: Display transformation: self displayTransformation clippingBox: self insetDisplayBox fixedPoint: editParagraph boundingBox center] ifFalse: [editParagraph displayOn: Display]! ! !DisplayTextView methodsFor: 'displaying'! uncacheBits "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"! ! !DisplayTextView methodsFor: 'deEmphasizing'! deEmphasizeView "Refer to the comment in View|deEmphasizeView." (self controller isKindOf: ParagraphEditor) ifTrue: [controller deselect]! ! !DisplayTextView methodsFor: 'private'! centerText self isCentered ifTrue: [editParagraph align: editParagraph boundingBox center with: self getWindow center]! ! !DisplayTextView methodsFor: 'private'! defaultRule ^Form over! ! !DisplayTextView methodsFor: 'private'! positionText | box | box _ (self displayBox insetBy: 6@6) origin extent: editParagraph boundingBox extent. editParagraph wrappingBox: box clippingBox: box. self centerText! ! !DisplayTextView methodsFor: 'lock access'! lock "Refer to the comment in View|lock. Must do what would be done by displaying..." self isUnlocked ifTrue: [self positionText]. super lock! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DisplayTextView class instanceVariableNames: ''! !DisplayTextView class methodsFor: 'examples'! example2 "Create a standarad system view with two parts, one editable, the other not." | topView aDisplayTextView | topView _ StandardSystemView new. topView label: 'Text Editor'. aDisplayTextView _ self new model: 'test string label' asDisplayText. aDisplayTextView controller: NoController new. aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidthLeft: 2 right: 0 top: 2 bottom: 2. topView addSubView: aDisplayTextView. aDisplayTextView _ self new model: 'test string' asDisplayText. aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidth: 2. topView addSubView: aDisplayTextView align: aDisplayTextView viewport topLeft with: topView lastSubView viewport topRight. topView controller open "DisplayTextView example2"! ! !DisplayTextView class methodsFor: 'examples'! example3 "Create a passive view of some text on the screen." | view | view_ self new model: 'this is a test of one line and the second line' asDisplayText. view translateBy: 100@100. view borderWidth: 2. view display. view release "DisplayTextView example3"! ! !DisplayTextView class methodsFor: 'examples'! example4 "Create four passive views of some text on the screen with fat borders." | view | view_ self new model: 'this is a test of one line and the second line' asDisplayText. view translateBy: 100@100. view borderWidth: 5. view display. 3 timesRepeat: [view translateBy: 100@100. view display]. view release "DisplayTextView example4"! ! AbstractEvent subclass: #DoItEvent instanceVariableNames: 'context' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !DoItEvent methodsFor: 'testing' stamp: 'rw 7/14/2003 10:15'! isDoIt ^true! ! !DoItEvent methodsFor: 'printing' stamp: 'rw 7/14/2003 10:15'! printEventKindOn: aStream aStream nextPutAll: 'DoIt'! ! !DoItEvent methodsFor: 'private-accessing' stamp: 'rw 7/14/2003 11:29'! context: aContext context := aContext! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DoItEvent class instanceVariableNames: ''! !DoItEvent class methodsFor: 'accessing' stamp: 'rw 7/14/2003 10:19'! changeKind ^#DoIt! ! !DoItEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:23'! supportedKinds ^ Array with: self expressionKind! ! !DoItEvent class methodsFor: 'instance creation' stamp: 'NS 1/19/2004 09:47'! expression: stringOrStream context: aContext | instance | instance := self item: stringOrStream kind: AbstractEvent expressionKind. instance context: aContext. ^instance! ! FileDirectory subclass: #DosFileDirectory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !DosFileDirectory commentStamp: '<historical>' prior: 0! I represent a DOS or Windows FileDirectory. ! !DosFileDirectory methodsFor: 'as yet unclassified' stamp: 'di 6/18/1998 08:57'! checkName: aFileName fixErrors: fixing "Check if the file name contains any invalid characters" | fName badChars hasBadChars | fName _ super checkName: aFileName fixErrors: fixing. badChars _ #( $: $< $> $| $/ $\ $? $* $") asSet. hasBadChars _ fName includesAnyOf: badChars. (hasBadChars and:[fixing not]) ifTrue:[^self error:'Invalid file name']. hasBadChars ifFalse:[^ fName]. ^ fName collect: [:char | (badChars includes: char) ifTrue:[$#] ifFalse:[char]]! ! !DosFileDirectory methodsFor: 'as yet unclassified' stamp: 'bf 3/21/2000 17:06'! setPathName: pathString "Ensure pathString is absolute - relative directories aren't supported on all platforms." (pathString isEmpty or: [pathString first = $\ or: [pathString size >= 2 and: [pathString second = $: and: [pathString first isLetter]]]]) ifTrue: [^ super setPathName: pathString]. self error: 'Fully qualified path expected'! ! !DosFileDirectory methodsFor: 'path access' stamp: 'je 11/8/2000 20:02'! driveName "return a possible drive letter and colon at the start of a Path name, empty string otherwise" | firstTwoChars | ( pathName size >= 2 ) ifTrue: [ firstTwoChars _ (pathName copyFrom: 1 to: 2). (self class isDrive: firstTwoChars) ifTrue: [^firstTwoChars] ]. ^''! ! !DosFileDirectory methodsFor: 'path access' stamp: 'nk 7/18/2004 17:26'! fullNameFor: fileName "Return a corrected, fully-qualified name for the given file name. If the given name is already a full path (i.e., it contains a delimiter character), assume it is already a fully-qualified name. Otherwise, prefix it with the path to this directory. In either case, correct the local part of the file name." fileName ifNil:[^fileName]. "Check for fully qualified names" ((fileName size >= 2 and: [fileName first isLetter and: [fileName second = $:]]) or: [(fileName beginsWith: '\\') and: [(fileName occurrencesOf: $\) >= 2]]) ifTrue:[^fileName]. ^super fullNameFor: fileName! ! !DosFileDirectory methodsFor: 'path access' stamp: 'je 11/8/2000 19:57'! fullPathFor: path "Return the fully-qualified path name for the given file." path isEmpty ifTrue:[^pathName]. (path at: 1) = $\ ifTrue:[ (path size >= 2 and:[(path at: 2) = $\]) ifTrue:[^path]. "e.g., \\pipe\" ^self driveName , path "e.g., \windows\"]. (path size >= 2 and:[(path at: 2) = $: and:[path first isLetter]]) ifTrue:[^path]. "e.g., c:" ^pathName, self slash, path! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DosFileDirectory class instanceVariableNames: ''! !DosFileDirectory class methodsFor: 'platform specific' stamp: 'ar 5/1/1999 01:48'! isCaseSensitive "Return true if file names are treated case sensitive" ^false! ! !DosFileDirectory class methodsFor: 'platform specific' stamp: 'ar 3/6/2004 03:46'! isDrive: fullName "Answer whether the given full name describes a 'drive', e.g., one of the root directories of a Win32 file system. We allow two forms here - the classic one where a drive is specified by a letter followed by a colon, e.g., 'C:', 'D:' etc. and the network share form starting with double-backslashes e.g., '\\server'." ^ (fullName size = 2 and: [fullName first isLetter and: [fullName last = $:]]) or: [(fullName beginsWith: '\\') and: [(fullName occurrencesOf: $\) = 2]]! ! !DosFileDirectory class methodsFor: 'platform specific' stamp: 'jm 5/8/1998 20:45'! maxFileNameLength ^ 255 ! ! !DosFileDirectory class methodsFor: 'platform specific' stamp: 'jm 12/4/97 22:57'! pathNameDelimiter ^ $\ ! ! !DosFileDirectory class methodsFor: 'platform specific' stamp: 'ar 3/6/2004 04:14'! splitName: fullName to: pathAndNameBlock "Take the file name and convert it to the path name of a directory and a local file name within that directory. IMPORTANT NOTE: For 'drives', e.g., roots of the file system on Windows we treat the full name of that 'drive' as the local name rather than the path. This is because conceptually, all of these 'drives' hang off the virtual root of the entire Squeak file system, specified by FileDirectory root. In order to be consistent with, e.g., DosFileDirectory localNameFor: 'C:\Windows' -> 'Windows' DosFileDirectory dirPathFor: 'C:\Windows' -> 'C:' we expect the following to be true: DosFileDirectory localNameFor: 'C:' -> 'C:' DosFileDirectory dirPathFor: 'C:'. -> '' DosFileDirectory localNameFor: '\\server' -> '\\server'. DosFileDirectory dirPathFor: '\\server' -> ''. so that in turn the following relations hold: | fd | fd := DosFileDirectory on: 'C:\Windows'. fd containingDirectory includes: fd localName. fd := DosFileDirectory on: 'C:'. fd containingDirectory includes: fd localName. fd := DosFileDirectory on: '\\server'. fd containingDirectory includes: fd localName. " (self isDrive: fullName) ifTrue: [^ pathAndNameBlock value:'' value: fullName]. ^ super splitName: fullName to: pathAndNameBlock! ! Model subclass: #DualChangeSorter instanceVariableNames: 'leftCngSorter rightCngSorter' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !DualChangeSorter commentStamp: '<historical>' prior: 0! This class presents a view of a two change sets at once, and supports copying changes between change sets. ! !DualChangeSorter methodsFor: 'initialization' stamp: 'di 5/20/1998 21:44'! okToChange ^ leftCngSorter okToChange & rightCngSorter okToChange! ! !DualChangeSorter methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:07'! open | topView | leftCngSorter _ ChangeSorter new myChangeSet: ChangeSet current. leftCngSorter parent: self. rightCngSorter _ ChangeSorter new myChangeSet: ChangeSorter secondaryChangeSet. rightCngSorter parent: self. topView _ (StandardSystemView new) model: self; borderWidth: 1. topView label: leftCngSorter label. topView minimumSize: 300 @ 200. leftCngSorter openView: topView offsetBy: 0@0. rightCngSorter openView: topView offsetBy: 360@0. topView controller open. ! ! !DualChangeSorter methodsFor: 'initialization'! release leftCngSorter release. rightCngSorter release.! ! !DualChangeSorter methodsFor: 'other'! isLeftSide: theOne "Which side am I?" ^ theOne == leftCngSorter! ! !DualChangeSorter methodsFor: 'other' stamp: 'sd 5/23/2003 14:38'! labelString "The window label" | leftName rightName changesName | leftName _ leftCngSorter changeSetCategory categoryName. rightName _ rightCngSorter changeSetCategory categoryName. changesName _ 'Changes go to "', ChangeSet current name, '"'. ^ ((leftName ~~ #All) or: [rightName ~~ #All]) ifTrue: ['(', leftName, ') - ', changesName, ' - (', rightName, ')'] ifFalse: [changesName]! ! !DualChangeSorter methodsFor: 'other' stamp: 'tk 5/8/1998 16:30'! modelWakeUp "A window with me as model is being entered. Make sure I am up-to-date with the changeSets." "Dumb way" leftCngSorter canDiscardEdits ifTrue: [leftCngSorter update] "does both" ifFalse: [rightCngSorter update]. ! ! !DualChangeSorter methodsFor: 'other'! other: theOne "Return the other side's ChangeSorter" ^ theOne == leftCngSorter ifTrue: [rightCngSorter] ifFalse: [leftCngSorter]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DualChangeSorter class instanceVariableNames: ''! !DualChangeSorter class methodsFor: 'opening' stamp: 'sw 3/24/1999 17:50'! open "Open a new instance of the receiver's class" self new open! ! !DualChangeSorter class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:44'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(DualChangeSorter prototypicalToolWindow 'Change Sorter' 'Shows two change sets side by side') forFlapNamed: 'Tools']! ! !DualChangeSorter class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:33'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! Magnitude subclass: #Duration instanceVariableNames: 'nanos seconds' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !Duration commentStamp: '<historical>' prior: 0! I represent a duration of time. I have nanosecond precision ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:59'! * operand "operand is a Number" ^ self class nanoSeconds: ( (self asNanoSeconds * operand) asInteger). ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:59'! + operand "operand is a Duration" ^ self class nanoSeconds: (self asNanoSeconds + operand asNanoSeconds) ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:59'! - operand "operand is a Duration" ^ self + operand negated ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:00'! / operand "operand is a Duration or a Number" ^ operand isNumber ifTrue: [ self class nanoSeconds: (self asNanoSeconds / operand) asInteger ] ifFalse: [ self asNanoSeconds / operand asDuration asNanoSeconds ] . ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:00'! < comparand ^ self asNanoSeconds < comparand asNanoSeconds ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 1/9/2004 06:25'! = comparand "Answer whether the argument is a <Duration> representing the same period of time as the receiver." ^ self == comparand ifTrue: [true] ifFalse: [self species = comparand species ifTrue: [self asNanoSeconds = comparand asNanoSeconds] ifFalse: [false] ]! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! abs ^ self class seconds: seconds abs nanoSeconds: nanos abs ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! asDuration ^ self ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! asSeconds ^ seconds ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 1/7/2004 16:20'! days "Answer the number of days the receiver represents." ^ seconds quo: SecondsInDay ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! hash ^seconds bitXor: nanos ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! hours "Answer the number of hours the receiver represents." ^ (seconds rem: SecondsInDay) quo: SecondsInHour ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:01'! minutes "Answer the number of minutes the receiver represents." ^ (seconds rem: SecondsInHour) quo: SecondsInMinute ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:02'! negated ^ self class seconds: seconds negated nanoSeconds: nanos negated ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:02'! negative ^ self positive not ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:02'! positive ^ seconds = 0 ifTrue: [ nanos positive ] ifFalse: [ seconds positive ] ! ! !Duration methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 10:03'! seconds "Answer the number of seconds the receiver represents." ^ (seconds rem: SecondsInMinute) + (nanos / NanosInSecond)! ! !Duration methodsFor: 'initialize-release' stamp: 'nk 3/30/2004 10:01'! initialize self seconds: 0 nanoSeconds: 0. ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 14:29'! // operand "operand is a Duration or a Number" ^ operand isNumber ifTrue: [ self class nanoSeconds: (self asNanoSeconds // operand) asInteger ] ifFalse: [ self asNanoSeconds // operand asDuration asNanoSeconds ] ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 15:07'! \\ operand "modulo. Remainder defined in terms of //. Answer a Duration with the same sign as aDuration. operand is a Duration or a Number." ^ operand isNumber ifTrue: [ self class nanoSeconds: (self asNanoSeconds \\ operand) ] ifFalse: [ self - (operand * (self // operand)) ] ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:03'! asNanoSeconds ^ (seconds * NanosInSecond) + nanos ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:03'! nanoSeconds ^ nanos ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 13:22'! printOn: aStream "Format as per ANSI 5.8.2.16: [-]D:HH:MM:SS[.S]" | d h m s n | d _ self days abs. h _ self hours abs. m _ self minutes abs. s _ self seconds abs truncated. n _ self nanoSeconds abs. self negative ifTrue: [ aStream nextPut: $- ]. d printOn: aStream. aStream nextPut: $:. h < 10 ifTrue: [ aStream nextPut: $0. ]. h printOn: aStream. aStream nextPut: $:. m < 10 ifTrue: [ aStream nextPut: $0. ]. m printOn: aStream. aStream nextPut: $:. s < 10 ifTrue: [ aStream nextPut: $0. ]. s printOn: aStream. n = 0 ifFalse: [ | z ps | aStream nextPut: $.. ps _ n printString padded: #left to: 9 with: $0. z _ ps findLast: [ :c | c asciiValue > $0 asciiValue ]. ps from: 1 to: z do: [ :c | aStream nextPut: c ] ]. ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 15:42'! roundTo: aDuration "e.g. if the receiver is 5 minutes, 37 seconds, and aDuration is 2 minutes, answer 6 minutes." ^ self class nanoSeconds: (self asNanoSeconds roundTo: aDuration asNanoSeconds) ! ! !Duration methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 15:38'! truncateTo: aDuration "e.g. if the receiver is 5 minutes, 37 seconds, and aDuration is 2 minutes, answer 4 minutes." ^ self class nanoSeconds: (self asNanoSeconds truncateTo: aDuration asNanoSeconds) ! ! !Duration methodsFor: 'private' stamp: 'brp 7/27/2003 15:08'! seconds: secondCount nanoSeconds: nanoCount "Private - only used by Duration class" seconds _ secondCount. nanos _ nanoCount! ! !Duration methodsFor: 'private' stamp: 'brp 9/25/2003 14:42'! storeOn: aStream aStream nextPut: $(; nextPutAll: self className; nextPutAll: ' seconds: '; print: seconds; nextPutAll: ' nanoSeconds: '; print: nanos; nextPut: $). ! ! !Duration methodsFor: 'private' stamp: 'brp 8/23/2003 20:31'! ticks "Answer an array {days. seconds. nanoSeconds}. Used by DateAndTime and Time" ^ Array with: self days with: (self hours * 3600) + (self minutes * 60 ) + (self seconds truncated) with: self nanoSeconds! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Duration class instanceVariableNames: ''! !Duration class methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 07:55'! days: days hours: hours minutes: minutes seconds: seconds ^ self days: days hours: hours minutes: minutes seconds: seconds nanoSeconds: 0.! ! !Duration class methodsFor: 'ansi protocol' stamp: 'nk 3/30/2004 10:05'! seconds: aNumber ^ (self basicNew) seconds: aNumber nanoSeconds: 0; yourself. ! ! !Duration class methodsFor: 'ansi protocol' stamp: 'nk 3/30/2004 10:06'! zero ^ (self basicNew) seconds: 0 nanoSeconds: 0; yourself. ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:00'! days: aNumber ^ self days: aNumber hours: 0 minutes: 0 seconds: 0 nanoSeconds: 0! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 1/7/2004 15:38'! days: days hours: hours minutes: minutes seconds: seconds nanoSeconds: nanos ^ self nanoSeconds: ( ( (days * SecondsInDay) + (hours * SecondsInHour) + (minutes * SecondsInMinute) + seconds ) * NanosInSecond ) + nanos. ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 5/16/2003 11:29'! fromString: aString ^ self readFrom: (ReadStream on: aString) ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:00'! hours: aNumber ^ self days: 0 hours: aNumber minutes: 0 seconds: 0 nanoSeconds: 0! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:01'! minutes: aNumber ^ self days: 0 hours: 0 minutes: aNumber seconds: 0 nanoSeconds: 0! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 5/21/2003 08:27'! nanoSeconds: nanos ^ self new seconds: (nanos quo: NanosInSecond) nanoSeconds: (nanos rem: NanosInSecond) rounded; yourself. ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 12:47'! readFrom: aStream "Formatted as per ANSI 5.8.2.16: [-]D:HH:MM:SS[.S] To assiste DateAndTime>>#readFrom: SS may be unpadded or absent." | sign days hours minutes seconds nanos ws ch | sign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1]. days _ (aStream upTo: $:) asInteger sign: sign. hours _ (aStream upTo: $:) asInteger sign: sign. minutes _ (aStream upTo: $:) asInteger sign: sign. aStream atEnd ifTrue: [seconds _ 0. nanos _ 0] ifFalse: [ ws _ String new writeStream. [ch _ aStream next. (ch isNil) | (ch = $.)] whileFalse: [ ws nextPut: ch ]. seconds _ ws contents asInteger sign: sign. ws reset. 9 timesRepeat: [ ch _ aStream next. ws nextPut: (ch ifNil: [$0] ifNotNil: [ch]) ]. nanos _ ws contents asInteger sign: sign]. ^ self days: days hours: hours minutes: minutes seconds: seconds nanoSeconds: nanos. " '0:00:00:00' asDuration '0:00:00:00.000000001' asDuration '0:00:00:00.999999999' asDuration '0:00:00:00.100000000' asDuration '0:00:00:00.10' asDuration '0:00:00:00.1' asDuration '0:00:00:01' asDuration '0:12:45:45' asDuration '1:00:00:00' asDuration '365:00:00:00' asDuration '-7:09:12:06.10' asDuration '+0:01:02' asDuration '+0:01:02:3' asDuration " ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 15:01'! seconds: seconds nanoSeconds: nanos ^ self days: 0 hours: 0 minutes: 0 seconds: seconds nanoSeconds: nanos ! ! !Duration class methodsFor: 'squeak protocol' stamp: 'brp 8/6/2003 18:54'! weeks: aNumber ^ self days: (aNumber * 7) hours: 0 minutes: 0 seconds: 0 nanoSeconds: 0 ! ! ObjectWithDocumentation subclass: #ElementCategory instanceVariableNames: 'categoryName keysInOrder elementDictionary' classVariableNames: '' poolDictionaries: '' category: 'Protocols-Kernel'! !ElementCategory commentStamp: '<historical>' prior: 0! ElementCategory Contains a list of elements that affords keyed access but also has an inherent order. Add items to the category by sending it elementAt:put:. Obtain the elements in order by sending #elementsInOrder Obtain the value of an element at a given key by sending #elementAt:! !ElementCategory methodsFor: 'elements' stamp: 'sw 12/1/2000 22:46'! elementAt: aKey "Answer the element at the given key" ^ elementDictionary at: aKey ifAbsent: [nil]! ! !ElementCategory methodsFor: 'elements' stamp: 'sw 1/26/2001 22:54'! elementAt: sym put: element "Add symbol at the end of my sorted list (unless it is already present), and put the element in the dictionary" (keysInOrder includes: sym) ifFalse: [keysInOrder add: sym]. ^ elementDictionary at: sym put: element! ! !ElementCategory methodsFor: 'elements' stamp: 'sw 9/12/2001 22:59'! elementSymbol "Answer the element symbol for the receiver. Here, the categoryName dominates" ^ categoryName! ! !ElementCategory methodsFor: 'elements' stamp: 'sw 12/1/2000 22:47'! elementsInOrder "Answer the elements in order" ^ keysInOrder collect: [:aKey | elementDictionary at: aKey]! ! !ElementCategory methodsFor: 'elements' stamp: 'sw 4/3/2001 11:06'! fasterElementAt: sym put: element "Add symbol at the end of my sorted list and put the element in the dictionary. This variant adds the key at the end of the keys list without checking whether it already exists." keysInOrder add: sym. ^ elementDictionary at: sym put: element! ! !ElementCategory methodsFor: 'elements' stamp: 'sw 4/11/2001 20:08'! removeElementAt: aKey "Remove the element at the given key" elementDictionary removeKey: aKey ifAbsent: [^ self]. keysInOrder remove: aKey ifAbsent: []! ! !ElementCategory methodsFor: 'copying' stamp: 'sw 12/1/2000 22:45'! copy "Answer a copy of the receiver" ^ super copy copyFrom: self! ! !ElementCategory methodsFor: 'copying' stamp: 'sw 12/1/2000 22:46'! copyFrom: donor "Copy the receiver's contents from the donor" keysInOrder _ donor keysInOrder. elementDictionary _ donor copyOfElementDictionary! ! !ElementCategory methodsFor: 'copying' stamp: 'sw 12/1/2000 22:46'! copyOfElementDictionary "Answer a copy of the element dictionary" ^ elementDictionary copy! ! !ElementCategory methodsFor: 'keys' stamp: 'sw 12/11/2000 15:36'! includesKey: aKey "Answer whether the receiver's dictionary holds the given key" ^ elementDictionary includesKey: aKey! ! !ElementCategory methodsFor: 'keys' stamp: 'sw 12/1/2000 22:47'! keysInOrder "Answer the keys in their sorted order" ^ keysInOrder copy! ! !ElementCategory methodsFor: 'category name' stamp: 'sw 1/26/2001 22:45'! categoryName "Answer the formal name of the category" ^ categoryName! ! !ElementCategory methodsFor: 'category name' stamp: 'sw 1/26/2001 22:46'! categoryName: aName "Set the category name" categoryName _ aName! ! !ElementCategory methodsFor: 'initialization' stamp: 'sw 3/30/2001 00:12'! addCategoryItem: anItem "Add the item at the end, obtaining its key from itself (it must respond to #categoryName)" self elementAt: anItem categoryName put: anItem! ! !ElementCategory methodsFor: 'initialization' stamp: 'sw 3/28/2001 19:46'! clear "Clear the receiber's keysInOrder and elementDictionary" keysInOrder _ OrderedCollection new. elementDictionary _ IdentityDictionary new! ! !ElementCategory methodsFor: 'initialization' stamp: 'sw 3/28/2001 19:47'! initialize "Initialize the receiver (automatically called when instances are created via 'new')" super initialize. self clear! ! !ElementCategory methodsFor: 'printing' stamp: 'sw 1/26/2001 22:47'! printOn: aStream "Append to the argument, aStream, a sequence of characters that identifies the receiver." super printOn: aStream. categoryName ifNotNil: [aStream nextPutAll: ' named ', categoryName asString]! ! !ElementCategory methodsFor: 'translation' stamp: 'dgd 12/4/2003 20:22'! translated "answer the receiver translated to the current language" ^ self class new categoryName: categoryName asString translated asSymbol! ! Object subclass: #ElementTranslation instanceVariableNames: 'wording helpMessage naturalLanguageSymbol' classVariableNames: '' poolDictionaries: '' category: 'Protocols-Kernel'! !ElementTranslation methodsFor: 'access' stamp: 'sw 5/22/2001 10:34'! helpMessage "Answer the helpMessage" ^ helpMessage! ! !ElementTranslation methodsFor: 'access' stamp: 'sw 5/22/2001 10:33'! wording "Answer the wording" ^ wording! ! !ElementTranslation methodsFor: 'initialization' stamp: 'sw 9/12/2001 23:00'! language "Answer the natural language symbol of the receiver" ^ naturalLanguageSymbol ifNil: [naturalLanguageSymbol _ #English]! ! !ElementTranslation methodsFor: 'initialization' stamp: 'sw 9/12/2001 10:15'! wording: aWording helpMessage: aHelpMessage language: aLanguageSymbol "Set state directly" wording _ aWording. helpMessage _ aHelpMessage. naturalLanguageSymbol _ aLanguageSymbol! ! !ElementTranslation methodsFor: 'printing' stamp: 'sw 9/12/2001 16:08'! printOn: aStream "Print the receiver on the stream" aStream nextPutAll: '('. super printOn: aStream. aStream nextPutAll: ' language: ', naturalLanguageSymbol asString, ' wording: ', wording asString, ')'! ! !ElementTranslation methodsFor: 'translation' stamp: 'dgd 12/4/2003 20:22'! translated "answer the receiver translated to the current language" | translatedWording translatedHelpMessage | translatedWording := wording isNil ifFalse: [wording asString translated]. translatedHelpMessage := helpMessage isNil ifFalse: [helpMessage asString translated]. "" ^ self class new wording: translatedWording helpMessage: translatedHelpMessage language: self currentWorld currentNaturalLanguage! ! ParseNode subclass: #Encoder instanceVariableNames: 'scopeTable nTemps supered requestor class literalStream selectorSet litIndSet litSet sourceRanges globalSourceRanges' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !Encoder commentStamp: '<historical>' prior: 0! 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.! !Encoder methodsFor: 'initialize-release'! fillDict: dict with: nodeClass mapping: keys to: codeArray | codeStream | codeStream _ ReadStream on: codeArray. keys do: [:key | dict at: key put: (nodeClass new name: key key: key code: codeStream next)]! ! !Encoder methodsFor: 'initialize-release' stamp: 'di 12/4/1999 22:22'! init: aClass context: aContext notifying: req | node n homeNode indexNode | requestor _ req. class _ aClass. nTemps _ 0. supered _ false. self initScopeAndLiteralTables. n _ -1. class allInstVarNames do: [:variable | node _ VariableNode new name: variable index: (n _ n + 1) type: LdInstType. scopeTable at: variable put: node]. aContext == nil ifFalse: [homeNode _ self bindTemp: 'homeContext'. "first temp = aContext passed as arg" n _ 0. aContext tempNames do: [:variable | indexNode _ self encodeLiteral: (n _ n + 1). node _ MessageAsTempNode new receiver: homeNode selector: #tempAt: arguments: (Array with: indexNode) precedence: 3 from: self. scopeTable at: variable put: node]]. sourceRanges _ Dictionary new: 32. globalSourceRanges _ OrderedCollection new: 32. ! ! !Encoder methodsFor: 'initialize-release'! initScopeAndLiteralTables scopeTable _ StdVariables copy. litSet _ StdLiterals copy. selectorSet _ StdSelectors copy. litIndSet _ Dictionary new: 16. literalStream _ WriteStream on: (Array new: 32)! ! !Encoder methodsFor: 'initialize-release'! noteSuper supered _ true! ! !Encoder methodsFor: 'initialize-release'! release requestor _ nil! ! !Encoder methodsFor: 'initialize-release' stamp: 'ajh 7/21/2003 00:53'! temps: tempVars literals: lits class: cl "Decompile." supered _ false. class _ cl. nTemps _ tempVars size. tempVars do: [:node | scopeTable at: node name put: node]. literalStream _ ReadStream on: lits. literalStream position: lits size. sourceRanges _ Dictionary new: 32. globalSourceRanges _ OrderedCollection new: 32. ! ! !Encoder methodsFor: 'encoding'! cantStoreInto: varName ^StdVariables includesKey: varName! ! !Encoder methodsFor: 'encoding'! encodeLiteral: object ^self name: object key: (class literalScannedAs: object notifying: self) class: LiteralNode type: LdLitType set: litSet! ! !Encoder methodsFor: 'encoding'! encodeSelector: selector ^self name: selector key: selector class: SelectorNode type: SendType set: selectorSet! ! !Encoder methodsFor: 'encoding' stamp: 'di 12/4/1999 20:09'! encodeVariable: name ^ self encodeVariable: name sourceRange: nil ifUnknown: [ self undeclared: name ]! ! !Encoder methodsFor: 'encoding' stamp: 'RAA 2/5/2001 10:44'! encodeVariable: name sourceRange: range ifUnknown: action | varNode | varNode _ scopeTable at: name ifAbsent: [(self lookupInPools: name ifFound: [:assoc | varNode _ self global: assoc name: name]) ifTrue: [varNode] ifFalse: [action value]]. range ifNotNil: [ name first isUppercase ifTrue: [globalSourceRanges addLast: { name. range. false }]. ]. (varNode isTemp and: [varNode scope < 0]) ifTrue: [ OutOfScopeNotification signal ifFalse: [ ^self notify: 'out of scope']. ]. ^ varNode! ! !Encoder methodsFor: 'encoding'! litIndex: literal | p | p _ literalStream position. p = 256 ifTrue: [self notify: 'More than 256 literals referenced. You must split or otherwise simplify this method. The 257th literal is: ', literal printString. ^nil]. "Would like to show where it is in the source code, but that info is hard to get." literalStream nextPut: literal. ^ p! ! !Encoder methodsFor: 'encoding' stamp: 'di 1/7/2000 15:24'! sharableLitIndex: literal "Special access prevents multiple entries for post-allocated super send special selectors" | p | p _ literalStream originalContents indexOf: literal. p = 0 ifFalse: [^ p-1]. ^ self litIndex: literal ! ! !Encoder methodsFor: 'encoding' stamp: 'tk 4/20/1999 15:41'! undeclared: name | sym | requestor interactive ifTrue: [ requestor requestor == #error: ifTrue: [requestor error: 'Undeclared']. ^ self notify: 'Undeclared']. Transcript show: ' (' , name , ' is Undeclared) '. sym _ name asSymbol. Undeclared at: sym put: nil. ^self global: (Undeclared associationAt: sym) name: sym! ! !Encoder methodsFor: 'temps'! autoBind: name "Declare a block argument as a temp if not already declared." | node | node _ scopeTable at: name ifAbsent: [(self lookupInPools: name ifFound: [:assoc | assoc]) ifTrue: [self notify: 'Name already used in a Pool or Global']. ^ (self reallyBind: name) nowHasDef nowHasRef scope: 1]. node isTemp ifTrue: [node scope >= 0 ifTrue: [^ self notify: 'Name already used in this method']. node nowHasDef nowHasRef scope: 1] ifFalse: [^ self notify: 'Name already used in this class']. ^node! ! !Encoder methodsFor: 'temps' stamp: 'di 10/12/1999 16:53'! bindAndJuggle: name | node nodes first thisCode | node _ self reallyBind: name. "Declared temps must precede block temps for decompiler and debugger to work right" nodes _ self tempNodes. (first _ nodes findFirst: [:n | n scope > 0]) > 0 ifTrue: [node == nodes last ifFalse: [self error: 'logic error']. thisCode _ (nodes at: first) code. first to: nodes size - 1 do: [:i | (nodes at: i) key: (nodes at: i) key code: (nodes at: i+1) code]. nodes last key: nodes last key code: thisCode]. ^ node! ! !Encoder methodsFor: 'temps' stamp: 'jm 9/18/97 21:06'! bindArg: name "Declare an argument." | node | nTemps >= 15 ifTrue: [^self notify: 'Too many arguments']. node _ self bindTemp: name. ^ node nowHasDef nowHasRef! ! !Encoder methodsFor: 'temps' stamp: 'crl 2/26/1999 12:18'! bindBlockTemp: name "Declare a temporary block variable; complain if it's not a field or class variable." | node | node _ scopeTable at: name ifAbsent: [^self reallyBind: name]. node isTemp ifTrue: [ node scope >= 0 ifTrue: [^ self notify: 'Name already used in this method']. node scope: 0] ifFalse: [^self notify: 'Name already used in this class']. ^node ! ! !Encoder methodsFor: 'temps' stamp: 'ar 7/12/1999 00:24'! bindTemp: name "Declare a temporary; error not if a field or class variable." scopeTable at: name ifPresent:[:node| "When non-interactive raise the error only if its a duplicate" (node isTemp or:[requestor interactive]) ifTrue:[^self notify:'Name is already defined'] ifFalse:[Transcript show: '(', name, ' is shadowed)']]. ^self reallyBind: name! ! !Encoder methodsFor: 'temps'! maxTemp ^nTemps! ! !Encoder methodsFor: 'temps'! newTemp: name nTemps _ nTemps + 1. ^ TempVariableNode new name: name index: nTemps - 1 type: LdTempType scope: 0! ! !Encoder methodsFor: 'results'! allLiterals supered ifTrue: [self litIndex: (self associationFor: class)]. ^ literalStream contents! ! !Encoder methodsFor: 'results' stamp: 'ar 2/13/1999 21:18'! associationFor: aClass | name | name _ Smalltalk keyAtIdentityValue: aClass ifAbsent: [^Association new value: aClass]. ^Smalltalk associationAt: name! ! !Encoder methodsFor: 'results'! literals "Should only be used for decompiling primitives" ^ literalStream contents! ! !Encoder methodsFor: 'results' stamp: 'di 10/12/1999 16:12'! tempNames ^ self tempNodes collect: [:node | (node isMemberOf: MessageAsTempNode) ifTrue: [scopeTable keyAtValue: node] ifFalse: [node key]]! ! !Encoder methodsFor: 'results' stamp: 'di 10/12/1999 15:31'! tempNodes | tempNodes | tempNodes _ SortedCollection sortBlock: [:n1 :n2 | n1 code <= n2 code]. scopeTable associationsDo: [:assn | assn value isTemp ifTrue: [tempNodes add: assn value]]. ^ tempNodes! ! !Encoder methodsFor: 'results' stamp: 'di 10/12/1999 17:15'! unusedTempNames | unused name | unused _ OrderedCollection new. scopeTable associationsDo: [:assn | (assn value isUnusedTemp) ifTrue: [name _ assn value key. name ~= 'homeContext' ifTrue: [unused add: name]]]. ^ unused! ! !Encoder methodsFor: 'error handling'! notify: string "Put a separate notifier on top of the requestor's window" | req | requestor == nil ifFalse: [req _ requestor. self release. req notify: string]. ^false! ! !Encoder methodsFor: 'error handling'! notify: string at: location | req | requestor == nil ifFalse: [req _ requestor. self release. req notify: string at: location]. ^false! ! !Encoder methodsFor: 'error handling'! requestor: req "Often the requestor is a BrowserCodeController" requestor _ req! ! !Encoder methodsFor: 'source mapping'! noteSourceRange: range forNode: node sourceRanges at: node put: range! ! !Encoder methodsFor: 'source mapping' stamp: 'RAA 8/21/1999 06:52'! rawSourceRanges ^ sourceRanges ! ! !Encoder methodsFor: 'source mapping'! sourceMap "Answer with a sorted set of associations (pc range)." ^ (sourceRanges keys collect: [:key | Association key: key pc value: (sourceRanges at: key)]) asSortedCollection! ! !Encoder methodsFor: 'private'! classEncoding "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." ^ class! ! !Encoder methodsFor: 'private' stamp: 'ar 8/14/2001 23:12'! global: ref name: name ^self name: name key: ref class: LiteralVariableNode type: LdLitIndType set: litIndSet! ! !Encoder methodsFor: 'private' stamp: 'ar 5/17/2003 14:16'! lookupInPools: varName ifFound: assocBlock Symbol hasInterned: varName ifTrue:[:sym| (class bindingOf: sym) ifNotNilDo:[:assoc| assocBlock value: assoc. ^true]. (Preferences valueOfFlag: #lenientScopeForGlobals) "**Temporary**" ifTrue: [^ Smalltalk lenientScopeHas: sym ifTrue: assocBlock] ifFalse: [^ false]]. (class bindingOf: varName) ifNotNilDo:[:assoc| assocBlock value: assoc. ^true]. ^false! ! !Encoder methodsFor: 'private'! name: name key: key class: leafNodeClass type: type set: dict | node | ^dict at: key ifAbsent: [node _ leafNodeClass new name: name key: key index: nil type: type. dict at: key put: node. ^node]! ! !Encoder methodsFor: 'private'! possibleVariablesFor: proposedVariable | results | results _ proposedVariable correctAgainstDictionary: scopeTable continuedFrom: nil. proposedVariable first isUppercase ifTrue: [ results _ class possibleVariablesFor: proposedVariable continuedFrom: results ]. ^ proposedVariable correctAgainst: nil continuedFrom: results. ! ! !Encoder methodsFor: 'private'! reallyBind: name | node | node _ self newTemp: name. scopeTable at: name put: node. ^node! ! Error subclass: #EndOfStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Extensions'! !EndOfStream commentStamp: '<historical>' prior: 0! Signalled when ReadStream>>next encounters a premature end.! !EndOfStream methodsFor: 'description' stamp: 'hh 5/17/2000 00:30'! isResumable "EndOfStream is resumable, so ReadStream>>next can answer" ^ true! ! !EndOfStream methodsFor: 'exceptionDescription' stamp: 'RAA 5/17/2000 03:10'! defaultAction "Answer ReadStream>>next default reply." ^ nil! ! Exception subclass: #Error instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !Error commentStamp: '<historical>' prior: 0! >From the ANSI standard: This protocol describes the behavior of instances of class Error. These are used to represent error conditions that prevent the normal continuation of processing. Actual error exceptions used by an application may be subclasses of this class. As Error is explicitly specified to be subclassable, conforming implementations must implement its behavior in a non-fragile manner. Additional notes: Error>defaultAction uses an explicit test for the presence of the Debugger class to decide whether or not it is in development mode. In the future, TFEI hopes to enhance the semantics of #defaultAction to improve support for pluggable default handlers.! !Error methodsFor: 'private' stamp: 'ajh 2/1/2003 00:54'! isResumable "Determine whether an exception is resumable." ^ false! ! !Error methodsFor: 'exceptionDescription' stamp: 'ajh 9/4/2002 19:24'! defaultAction "No one has handled this error, but now give them a chance to decide how to debug it. If none handle this either then open debugger (see UnhandedError-defaultAction)" UnhandledError signalForException: self! ! Object subclass: #EventManager instanceVariableNames: 'actionMap' classVariableNames: 'ActionMaps' poolDictionaries: '' category: 'System-Object Events'! !EventManager methodsFor: 'copying' stamp: 'reThink 3/3/2001 10:22'! copy | answer | answer := super copy. answer release. ^answer! ! !EventManager methodsFor: 'accessing' stamp: 'reThink 2/18/2001 15:37'! actionMap ^actionMap == nil ifTrue: [self createActionMap] ifFalse: [actionMap]! ! !EventManager methodsFor: 'accessing' stamp: 'reThink 3/3/2001 10:07'! changedEventSelector ^#changed:! ! !EventManager methodsFor: 'accessing' stamp: 'reThink 2/18/2001 15:39'! releaseActionMap actionMap := nil! ! !EventManager methodsFor: 'accessing' stamp: 'reThink 3/3/2001 10:07'! updateEventSelector ^#update:! ! !EventManager methodsFor: 'accessing' stamp: 'reThink 2/18/2001 15:38'! updateableActionMap actionMap == nil ifTrue: [actionMap := self createActionMap]. ^actionMap! ! !EventManager methodsFor: 'dependents access' stamp: 'reThink 3/3/2001 10:07'! addDependent: anObject "Make the given object one of the receiver's dependents." self when: self changedEventSelector send: self updateEventSelector to: anObject. ^anObject! ! !EventManager methodsFor: 'dependents access' stamp: 'reThink 3/3/2001 10:07'! breakDependents "Remove all of the receiver's dependents." self removeActionsForEvent: self changedEventSelector! ! !EventManager methodsFor: 'dependents access' stamp: 'reThink 3/3/2001 10:18'! dependents ^(self actionSequenceForEvent: self changedEventSelector) asSet collect: [:each | each receiver]! ! !EventManager methodsFor: 'dependents access' stamp: 'reThink 3/3/2001 10:07'! removeDependent: anObject "Remove the given object as one of the receiver's dependents." self removeActionsWithReceiver: anObject forEvent: self changedEventSelector. ^ anObject! ! !EventManager methodsFor: 'updating' stamp: 'reThink 3/3/2001 10:20'! changed: aParameter "Receiver changed. The change is denoted by the argument aParameter. Usually the argument is a Symbol that is part of the dependent's change protocol. Inform all of the dependents." self triggerEvent: self changedEventSelector with: aParameter! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! EventManager class instanceVariableNames: ''! !EventManager class methodsFor: 'accessing' stamp: 'reThink 2/18/2001 14:42'! actionMapFor: anObject ^self actionMaps at: anObject ifAbsent: [self createActionMap]! ! !EventManager class methodsFor: 'accessing' stamp: 'rww 10/2/2001 07:20'! actionMaps ActionMaps == nil ifTrue: [ActionMaps := WeakIdentityKeyDictionary new]. ^ActionMaps! ! !EventManager class methodsFor: 'accessing' stamp: 'reThink 2/25/2001 08:52'! updateableActionMapFor: anObject ^self actionMaps at: anObject ifAbsentPut: [self createActionMap]! ! !EventManager class methodsFor: 'releasing' stamp: 'reThink 2/18/2001 15:34'! releaseActionMapFor: anObject self actionMaps removeKey: anObject ifAbsent: []! ! !EventManager class methodsFor: 'initialize-release' stamp: 'rw 2/10/2002 13:09'! flushEvents "Object flushEvents" | msgSet | self actionMaps keysAndValuesDo:[:rcvr :evtDict| rcvr ifNotNil:[ "make sure we don't modify evtDict while enumerating" evtDict keys do:[:evtName| msgSet _ evtDict at: evtName ifAbsent:[nil]. (msgSet == nil) ifTrue:[rcvr removeActionsForEvent: evtName]]]]. EventManager actionMaps finalizeValues. ! ! InputSensor subclass: #EventSensor instanceVariableNames: 'mouseButtons mousePosition keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore' classVariableNames: 'EventPollPeriod EventTicklerProcess' poolDictionaries: 'EventSensorConstants' category: 'Kernel-Processes'! !EventSensor commentStamp: 'nk 4/13/2004 11:18' prior: 0! EventSensor is a replacement for InputSensor based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design. For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events. On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM. Instance variables: mouseButtons <Integer> - mouse button state as replacement for primMouseButtons mousePosition <Point> - mouse position as replacement for primMousePt keyboardBuffer <SharedQueue> - keyboard input buffer interruptKey <Integer> - currently defined interrupt key interruptSemaphore <Semaphore> - the semaphore signaled when the interruptKey is detected eventQueue <SharedQueue> - an optional event queue for event driven applications inputSemaphore <Semaphore>- the semaphore signaled by the VM if asynchronous event notification is supported lastEventPoll <Integer> - the last millisecondClockValue at which we called fetchMoreEvents hasInputSemaphore <Boolean> - true if my inputSemaphore has actually been signaled at least once. Class variables: EventPollPeriod <Integer> - the number of milliseconds to wait between polling for more events in the userInterruptHandler. EventTicklerProcess <Process> - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds). Event format: The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported. Currently, the following events are defined: Null event ============= The Null event is returned when the ST side asks for more events but no more events are available. Structure: [1] - event type 0 [2-8] - unused Mouse event structure ========================== Mouse events are generated when mouse input is detected. Structure: [1] - event type 1 [2] - time stamp [3] - mouse x position [4] - mouse y position [5] - button state; bitfield with the following entries: 1 - yellow (e.g., right) button 2 - blue (e.g., middle) button 4 - red (e.g., left) button [all other bits are currently undefined] [6] - modifier keys; bitfield with the following entries: 1 - shift key 2 - ctrl key 4 - (Mac specific) option key 8 - Cmd/Alt key [all other bits are currently undefined] [7] - reserved. [8] - reserved. Keyboard events ==================== Keyboard events are generated when keyboard input is detected. [1] - event type 2 [2] - time stamp [3] - character code For now the character code is in Mac Roman encoding. [4] - press state; integer with the following meaning 0 - character 1 - key press (down) 2 - key release (up) [5] - modifier keys (same as in mouse events) [6] - reserved. [7] - reserved. [8] - reserved. ! !EventSensor methodsFor: 'accessing' stamp: 'ar 7/23/2000 14:37'! eventQueue "Return the current event queue" ^eventQueue! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 4/12/2004 19:36'! eventTicklerProcess "Answer my event tickler process, if any" ^EventTicklerProcess! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/6/2004 14:48'! flushAllButDandDEvents | newQueue oldQueue | newQueue _ SharedQueue new. self eventQueue ifNil: [eventQueue := newQueue. ^self]. oldQueue _ self eventQueue. [oldQueue size > 0] whileTrue: [| item type | item _ oldQueue next. type _ item at: 1. type = EventTypeDragDropFiles ifTrue: [ newQueue nextPut: item]]. eventQueue := newQueue. ! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/7/2001 17:13'! flushEvents eventQueue ifNotNil:[eventQueue flush].! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 19:21'! initialize "Initialize the receiver" mouseButtons := 0. mousePosition := 0 @ 0. keyboardBuffer := SharedQueue new. self setInterruptKey: (interruptKey ifNil: [$. asciiValue bitOr: 16r0800 ]). "cmd-." interruptSemaphore := (Smalltalk specialObjectsArray at: 31) ifNil: [Semaphore new]. self flushAllButDandDEvents. inputSemaphore := Semaphore new. hasInputSemaphore := false.! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 20:13'! shutDown super shutDown. EventTicklerProcess ifNotNil: [ EventTicklerProcess terminate. EventTicklerProcess _ nil. ]. inputSemaphore ifNotNil:[Smalltalk unregisterExternalObject: inputSemaphore]. ! ! !EventSensor methodsFor: 'initialize' stamp: 'BG 8/18/2004 12:12'! startUp "Run the I/O process" self initialize. self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. " Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. " "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! ! !EventSensor methodsFor: 'mouse' stamp: 'ar 5/18/2003 18:27'! createMouseEvent "create and return a new mouse event from the current mouse position; this is useful for restarting normal event queue processing after manual polling" | buttons modifiers pos mapped eventBuffer | eventBuffer _ Array new: 8. buttons _ self primMouseButtons. pos _ self primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. eventBuffer at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ eventBuffer! ! !EventSensor methodsFor: 'private' stamp: 'nk 4/12/2004 20:16'! eventTickler "Poll infrequently to make sure that the UI process is not been stuck. If it has been stuck, then spin the event loop so that I can detect the interrupt key." | delay | delay := Delay forMilliseconds: self class eventPollPeriod. self lastEventPoll. "ensure not nil." [| delta | [ delay wait. delta := Time millisecondClockValue - lastEventPoll. (delta < 0 or: [delta > self class eventPollPeriod]) ifTrue: ["force check on rollover" self fetchMoreEvents]] on: Error do: [:ex | ]. true ] whileTrue.! ! !EventSensor methodsFor: 'private' stamp: 'di 10/1/2001 20:52'! flushNonKbdEvents eventQueue ifNil: [^ self]. eventQueue flushAllSuchThat: [:buf | (self isKbdEvent: buf) not] ! ! !EventSensor methodsFor: 'private' stamp: 'nk 6/21/2004 10:40'! installEventTickler "Initialize the interrupt watcher process. Terminate the old process if any." "Sensor installEventTickler" EventTicklerProcess ifNotNil: [EventTicklerProcess terminate]. EventTicklerProcess _ [self eventTickler] forkAt: Processor lowIOPriority. ! ! !EventSensor methodsFor: 'private' stamp: 'di 10/1/2001 20:51'! isKbdEvent: buf ^ (buf at: 1) = EventTypeKeyboard and: [(buf at: 4) = EventKeyChar]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/18/2004 13:21'! lastEventPoll "Answer the last clock value at which fetchMoreEvents was called." ^lastEventPoll ifNil: [ lastEventPoll _ Time millisecondClockValue ]! ! !EventSensor methodsFor: 'private' stamp: 'ar 7/23/2000 00:34'! primInterruptSemaphore: aSemaphore "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." interruptSemaphore _ aSemaphore. "backward compatibility: use the old primitive which is obsolete now" super primInterruptSemaphore: aSemaphore! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:41'! primKbdNext "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | evtBuf | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse:[^ keyboardBuffer next]. eventQueue ifNotNil: [evtBuf _ eventQueue nextOrNilSuchThat: [:buf | self isKbdEvent: buf]. self flushNonKbdEvents]. ^ evtBuf ifNotNil: [evtBuf at: 3] ! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:41'! primKbdPeek "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | char | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse: [^ keyboardBuffer peek]. char _ nil. eventQueue ifNotNil: [eventQueue nextOrNilSuchThat: "NOTE: must not return out of this block, so loop to end" [:buf | (self isKbdEvent: buf) ifTrue: [char ifNil: [char _ buf at: 3]]. false "NOTE: block value must be false so Queue won't advance"]]. ^ char! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:42'! primMouseButtons self fetchMoreEvents. self flushNonKbdEvents. ^ mouseButtons! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:41'! primMousePt self fetchMoreEvents. self flushNonKbdEvents. ^ mousePosition! ! !EventSensor methodsFor: 'private' stamp: 'ls 10/23/2000 14:14'! primSetInterruptKey: anInteger "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>." interruptKey _ anInteger. "backward compatibility: use the old primitive which is obsolete now" super primSetInterruptKey: anInteger! ! !EventSensor methodsFor: 'private-I/O' stamp: 'nk 4/12/2004 20:01'! fetchMoreEvents "Fetch more events from the VM" | eventBuffer type | "Reset input semaphore so clients can wait for the next events after this one." inputSemaphore isSignaled ifTrue: [ hasInputSemaphore _ true. inputSemaphore initSignals ]. "Remember the last time that I checked for events." lastEventPoll := Time millisecondClockValue. eventBuffer := Array new: 8. [self primGetNextEvent: eventBuffer. type := eventBuffer at: 1. type = EventTypeNone] whileFalse: [self processEvent: eventBuffer]. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:12'! mapButtons: buttons modifiers: modifiers "Map the buttons to yellow or blue based on the given modifiers. If only the red button is pressed, then map Ctrl-RedButton -> BlueButton. Cmd-RedButton -> YellowButton. " (buttons = RedButtonBit) ifFalse:[^buttons]. (modifiers allMask: CtrlKeyBit) ifTrue:[^BlueButtonBit]. (modifiers allMask: CommandKeyBit) ifTrue:[^YellowButtonBit]. ^buttons! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 8/16/2000 22:06'! primGetNextEvent: array "Store the next OS event available into the provided array. Essential. If the VM is not event driven the ST code will fall back to the old-style mechanism and use the state based primitives instead." | kbd buttons modifiers pos mapped | <primitive: 94> "Simulate the events" array at: 1 put: EventTypeNone. "assume no more events" "First check for keyboard" kbd _ super primKbdNext. kbd = nil ifFalse:[ "simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^self]. "Then check for mouse" buttons _ super primMouseButtons. pos _ super primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. (pos = mousePosition and:[(mapped bitOr: (modifiers bitShift: 3)) = mouseButtons]) ifTrue:[^self]. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:16'! primSetInputSemaphore: semaIndex "Set the input semaphore the VM should use for asynchronously signaling the availability of events. Primitive. Optional." <primitive: 93> ^nil! ! !EventSensor methodsFor: 'private-I/O' stamp: 'nk 2/11/2002 12:18'! processEvent: evt "Process a single event. This method is run at high priority." | type | type _ evt at: 1. "Check if the event is a user interrupt" (type = EventTypeKeyboard and:[(evt at: 4) = 0 and:[ ((evt at: 3) bitOr: ((evt at: 5) bitShift: 8)) = interruptKey]]) ifTrue:["interrupt key is meta - not reported as event" ^interruptSemaphore signal]. "Store the event in the queue if there's any" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1)]. type = EventTypeKeyboard ifTrue: ["swap ctrl/alt keys" KeyDecodeTable at: { evt at: 3 . evt at: 5 } ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]]. self queueEvent: evt. "Update state for InputSensor." EventTypeMouse = type ifTrue:[self processMouseEvent: evt]. EventTypeKeyboard = type ifTrue:[self processKeyboardEvent: evt]! ! !EventSensor methodsFor: 'private-I/O' stamp: 'nk 4/11/2001 18:28'! processKeyboardEvent: evt "process a keyboard event, updating InputSensor state" | charCode pressCode | "Never update keyboardBuffer if we have an eventQueue active" mouseButtons _ (mouseButtons bitAnd: 7) bitOr: ((evt at: 5) bitShift: 3). eventQueue ifNotNil:[^self]. charCode _ evt at: 3. charCode = nil ifTrue:[^self]. "extra characters not handled in MVC" pressCode _ evt at: 4. pressCode = EventKeyChar ifFalse:[^self]. "key down/up not handled in MVC" "mix in modifiers" charCode _ charCode bitOr: ((evt at: 5) bitShift: 8). keyboardBuffer nextPut: charCode.! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 8/16/2000 22:07'! processMouseEvent: evt "process a mouse event, updating InputSensor state" | modifiers buttons mapped | mousePosition _ (evt at: 3) @ (evt at: 4). buttons _ evt at: 5. modifiers _ evt at: 6. mapped _ self mapButtons: buttons modifiers: modifiers. mouseButtons _ mapped bitOr: (modifiers bitShift: 3).! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/23/2000 14:55'! queueEvent: evt "Queue the given event in the event queue (if any). Note that the event buffer must be copied since it will be reused later on." eventQueue ifNil:[^self]. eventQueue nextPut: evt clone.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! EventSensor class instanceVariableNames: ''! !EventSensor class methodsFor: 'class initialization' stamp: 'nk 4/12/2004 18:55'! eventPollPeriod ^EventPollPeriod ifNil: [ EventPollPeriod _ 500 ].! ! !EventSensor class methodsFor: 'class initialization' stamp: 'ar 7/23/2000 15:06'! install "EventSensor install" "Install an EventSensor in place of the current Sensor." | newSensor | Sensor shutDown. newSensor _ self new. newSensor startUp. "Note: We must use #become: here to replace all references to the old sensor with the new one, since Sensor is referenced from all the existing controllers." Sensor becomeForward: newSensor. "done"! ! SharedPool subclass: #EventSensorConstants instanceVariableNames: '' classVariableNames: 'BlueButtonBit CommandKeyBit CtrlKeyBit EventKeyChar EventKeyDown EventKeyUp EventTypeDragDropFiles EventTypeKeyboard EventTypeMouse EventTypeNone OptionKeyBit RedButtonBit ShiftKeyBit YellowButtonBit' poolDictionaries: '' category: 'Kernel-Processes'! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! EventSensorConstants class instanceVariableNames: ''! !EventSensorConstants class methodsFor: 'pool initialization' stamp: 'ar 5/18/2003 18:26'! initialize "EventSensorConstants initialize" RedButtonBit := 4. BlueButtonBit := 2. YellowButtonBit := 1. ShiftKeyBit := 1. CtrlKeyBit := 2. OptionKeyBit := 4. CommandKeyBit := 8. "Types of events" EventTypeNone := 0. EventTypeMouse := 1. EventTypeKeyboard := 2. EventTypeDragDropFiles := 3. "Press codes for keyboard events" EventKeyChar := 0. EventKeyDown := 1. EventKeyUp := 2. ! ! Object subclass: #Exception instanceVariableNames: 'messageText tag signalContext handlerContext outerContext' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !Exception commentStamp: '<historical>' prior: 0! This is the main class used to implement the exception handling system (EHS). It plays two distinct roles: that of the exception, and that of the exception handler. More specifically, it implements the bulk of the protocols laid out in the ANSI specification - those protocol names are reflected in the message categories. Exception is an abstract class. Instances should neither be created nor trapped. In most cases, subclasses should inherit from Error or Notification rather than directly from Exception. In implementing this EHS, The Fourth Estate Inc. incorporated some ideas and code from Craig Latta's EHS. His insights were crucial in allowing us to implement BlockContext>>valueUninterruptably (and by extension, #ensure: and #ifCurtailed:), and we imported the following methods with little or no modification: ContextPart>>terminateTo: ContextPart>>terminate MethodContext>>receiver: MethodContext>>answer: Thanks, Craig!!! !Exception methodsFor: 'handling' stamp: 'ajh 2/1/2003 01:33'! pass "Yield control to the enclosing exception action for the receiver." handlerContext nextHandlerContext handleSignal: self! ! !Exception methodsFor: 'handling' stamp: 'ajh 1/13/2002 15:09'! resume "Return from the message that signaled the receiver." self resume: nil! ! !Exception methodsFor: 'handling' stamp: 'ajh 1/13/2002 15:14'! resume: resumptionValue "Return resumptionValue as the value of the signal message." self isResumable ifFalse: [IllegalResumeAttempt signal]. self resumeUnchecked: resumptionValue! ! !Exception methodsFor: 'handling' stamp: 'ajh 6/27/2003 22:30'! resumeUnchecked: resumptionValue "Return resumptionValue as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer." | ctxt | outerContext ifNil: [ signalContext return: resumptionValue ] ifNotNil: [ ctxt _ outerContext. outerContext _ ctxt tempAt: 1. "prevOuterContext in #outer" ctxt return: resumptionValue ]. ! ! !Exception methodsFor: 'handling' stamp: 'ajh 9/30/2001 15:33'! return "Return nil as the value of the block protected by the active exception handler." self return: nil! ! !Exception methodsFor: 'handling' stamp: 'ajh 1/29/2003 13:37'! return: returnValue "Return the argument as the value of the block protected by the active exception handler." handlerContext return: returnValue! ! !Exception methodsFor: 'printing' stamp: 'pnm 8/16/2000 14:53'! description "Return a textual description of the exception." | desc mt | desc := self class name asString. ^(mt := self messageText) == nil ifTrue: [desc] ifFalse: [desc, ': ', mt]! ! !Exception methodsFor: 'printing' stamp: 'ajh 9/30/2001 15:33'! messageText "Return an exception's message text." ^messageText! ! !Exception methodsFor: 'printing' stamp: 'ajh 9/30/2001 15:33'! printOn: stream stream nextPutAll: self description! ! !Exception methodsFor: 'printing' stamp: 'ajh 10/22/2001 14:24'! receiver ^ self signalerContext receiver! ! !Exception methodsFor: 'printing' stamp: 'ar 6/28/2003 00:13'! signalerContext "Find the first sender of signal(:)" ^ signalContext findContextSuchThat: [:ctxt | (ctxt receiver == self or: [ctxt receiver == self class]) not]! ! !Exception methodsFor: 'signaling' stamp: 'ajh 9/30/2001 15:33'! messageText: signalerText "Set an exception's message text." messageText := signalerText! ! !Exception methodsFor: 'signaling' stamp: 'ajh 2/1/2003 01:33'! signal "Ask ContextHandlers in the sender chain to handle this signal. The default is to execute and return my defaultAction." signalContext _ thisContext contextTag. ^ thisContext nextHandlerContext handleSignal: self! ! !Exception methodsFor: 'signaling' stamp: 'ajh 9/30/2001 20:13'! signal: signalerText "Signal the occurrence of an exceptional condition with a specified textual description." self messageText: signalerText. ^ self signal! ! !Exception methodsFor: 'priv handling' stamp: 'ajh 9/30/2001 15:33'! defaultAction "The default action taken if the exception is signaled." self subclassResponsibility! ! !Exception methodsFor: 'priv handling' stamp: 'ajh 2/1/2003 00:58'! isResumable "Determine whether an exception is resumable." ^ true! ! !Exception methodsFor: 'priv handling' stamp: 'ajh 1/29/2003 13:44'! privHandlerContext: aContextTag handlerContext _ aContextTag! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Exception class instanceVariableNames: ''! !Exception class methodsFor: 'exceptionInstantiator' stamp: 'ajh 9/30/2001 21:54'! signal "Signal the occurrence of an exceptional condition." ^ self new signal! ! !Exception class methodsFor: 'exceptionInstantiator' stamp: 'ajh 9/30/2001 21:54'! signal: signalerText "Signal the occurrence of an exceptional condition with a specified textual description." ^ self new signal: signalerText! ! !Exception class methodsFor: 'exceptionSelector' stamp: 'ajh 9/30/2001 15:33'! , anotherException "Create an exception set." ^ExceptionSet new add: self; add: anotherException; yourself! ! !Exception class methodsFor: 'exceptionSelector' stamp: 'ajh 8/5/2003 11:33'! handles: exception "Determine whether an exception handler will accept a signaled exception." ^ exception isKindOf: self! ! Object subclass: #ExceptionSet instanceVariableNames: 'exceptions' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !ExceptionSet commentStamp: '<historical>' prior: 0! An ExceptionSet is a grouping of exception handlers which acts as a single handler. Within the group, the most recently added handler will be the last handler found during a handler search (in the case where more than one handler in the group is capable of handling a given exception). ! !ExceptionSet methodsFor: 'private' stamp: 'tfei 7/16/1999 1:07'! add: anException exceptions add: anException! ! !ExceptionSet methodsFor: 'private' stamp: 'tfei 3/23/1999 14:07'! initialize exceptions := OrderedCollection new! ! !ExceptionSet methodsFor: 'exceptionSelector' stamp: 'tfei 6/4/1999 18:37'! , anException "Return an exception set that contains the receiver and the argument exception. This is commonly used to specify a set of exception selectors for an exception handler." self add: anException. ^self! ! !ExceptionSet methodsFor: 'exceptionSelector' stamp: 'pnm 8/16/2000 15:15'! handles: anException "Determine whether an exception handler will accept a signaled exception." exceptions do: [:ex | (ex handles: anException) ifTrue: [^true]]. ^false! ! Object subclass: #ExternalSemaphoreTable instanceVariableNames: '' classVariableNames: 'ProtectTable' poolDictionaries: '' category: 'System-Support'! !ExternalSemaphoreTable commentStamp: '<historical>' prior: 0! By John M McIntosh johnmci@smalltalkconsulting.com This class was written to mange the external semaphore table. When I was writing a Socket test server I discovered various race conditions on the access to the externalSemaphore table. This new class uses class side methods to restrict access using a mutex semaphore. It seemed cleaner to deligate the reponsibility here versus adding more code and another class variable to SystemDictionary Note that in Smalltalk recreateSpecialObjectsArray we still directly play with the table.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ExternalSemaphoreTable class instanceVariableNames: ''! !ExternalSemaphoreTable class methodsFor: 'accessing' stamp: 'JMM 6/6/2000 20:36'! clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." ProtectTable critical: [Smalltalk specialObjectsArray at: 39 put: Array new]. ! ! !ExternalSemaphoreTable class methodsFor: 'accessing' stamp: 'JMM 6/6/2000 20:44'! registerExternalObject: anObject ^ ProtectTable critical: [self safelyRegisterExternalObject: anObject] ! ! !ExternalSemaphoreTable class methodsFor: 'accessing' stamp: 'JMM 6/6/2000 20:57'! safelyRegisterExternalObject: anObject "Register the given object in the external objects array and return its index. If it is already there, just return its index." | objects firstEmptyIndex obj sz newObjects | objects _ Smalltalk specialObjectsArray at: 39. "find the first empty slot" firstEmptyIndex _ 0. 1 to: objects size do: [:i | obj _ objects at: i. obj == anObject ifTrue: [^ i]. "object already there, just return its index" (obj == nil and: [firstEmptyIndex = 0]) ifTrue: [firstEmptyIndex _ i]]. "if no empty slots, expand the array" firstEmptyIndex = 0 ifTrue: [ sz _ objects size. newObjects _ objects species new: sz + 20. "grow linearly" newObjects replaceFrom: 1 to: sz with: objects startingAt: 1. firstEmptyIndex _ sz + 1. Smalltalk specialObjectsArray at: 39 put: newObjects. objects _ newObjects]. objects at: firstEmptyIndex put: anObject. ^ firstEmptyIndex ! ! !ExternalSemaphoreTable class methodsFor: 'accessing' stamp: 'JMM 6/6/2000 20:59'! safelyUnregisterExternalObject: anObject "Unregister the given object in the external objects array. Do nothing if it isn't registered. JMM change to return if we clear the element, since it should only appear once in the array" | objects | anObject ifNil: [^ self]. objects _ Smalltalk specialObjectsArray at: 39. 1 to: objects size do: [:i | (objects at: i) == anObject ifTrue: [objects at: i put: nil. ^self]]. ! ! !ExternalSemaphoreTable class methodsFor: 'accessing' stamp: 'JMM 6/6/2000 20:45'! unregisterExternalObject: anObject ProtectTable critical: [self safelyUnregisterExternalObject: anObject] ! ! !ExternalSemaphoreTable class methodsFor: 'initialize' stamp: 'JMM 6/6/2000 20:32'! initialize ProtectTable _ Semaphore forMutualExclusion! ! Object subclass: #FakeClassPool instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !FakeClassPool commentStamp: '<historical>' prior: 0! 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.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FakeClassPool class instanceVariableNames: ''! !FakeClassPool class methodsFor: 'as yet unclassified' stamp: 'di 5/10/1998 21:32'! adopt: classOrNil "Temporarily use the classPool and sharedPools of another class" classOrNil == nil ifTrue: [classPool _ nil. sharedPools _ nil] ifFalse: [classPool _ classOrNil classPool. sharedPools _ classOrNil sharedPools] ! ! Boolean subclass: #False instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !False commentStamp: '<historical>' prior: 0! False defines the behavior of its single instance, false -- logical negation. Notice how the truth-value checks become direct message sends, without the need for explicit testing. Be aware however that most of these methods are not sent as real messages in normal use. Most are inline coded by the compiler as test and jump bytecodes - avoiding the overhead of the full message sends. So simply redefining these methods here will have no effect.! !False methodsFor: 'logical operations'! & alternativeObject "Evaluating conjunction -- answer false since receiver is false." ^self! ! !False methodsFor: 'logical operations'! not "Negation -- answer true since the receiver is false." ^true! ! !False methodsFor: 'logical operations'! | aBoolean "Evaluating disjunction (OR) -- answer with the argument, aBoolean." ^aBoolean! ! !False methodsFor: 'controlling'! and: alternativeBlock "Nonevaluating conjunction -- answer with false since the receiver is false." ^self! ! !False methodsFor: 'controlling'! ifFalse: alternativeBlock "Answer the value of alternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^alternativeBlock value! ! !False methodsFor: 'controlling'! ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock "Answer the value of falseAlternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^falseAlternativeBlock value! ! !False methodsFor: 'controlling'! ifTrue: alternativeBlock "Since the condition is false, answer the value of the false alternative, which is nil. Execution does not actually reach here because the expression is compiled in-line." ^nil! ! !False methodsFor: 'controlling'! ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock "Answer the value of falseAlternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^falseAlternativeBlock value! ! !False methodsFor: 'controlling'! or: alternativeBlock "Nonevaluating disjunction -- answer value of alternativeBlock." ^alternativeBlock value! ! !False methodsFor: 'printing'! printOn: aStream aStream nextPutAll: 'false'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! False class instanceVariableNames: ''! !False class methodsFor: 'as yet unclassified' stamp: 'sw 5/8/2000 11:09'! initializedInstance ^ false! ! Browser subclass: #FileContentsBrowser instanceVariableNames: 'packages infoString' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !FileContentsBrowser commentStamp: '<historical>' prior: 0! I am a class browser view on a fileout (either a source file (.st) or change set (.cs)). I do not actually load the code into to the system, nor do I alter the classes in the image. Use me to vet code in a comfortable way before loading it into your image. From a FileList, I can be invoked by selecting a source file and selecting the "browse code" menu item from the yellow button menu. I use PseudoClass, PseudoClassOrganizers, and PseudoMetaclass to model the class structure of the source file.! !FileContentsBrowser methodsFor: 'accessing'! contents self updateInfoView. (editSelection == #newClass and:[self selectedPackage notNil]) ifTrue: [^self selectedPackage packageInfo]. editSelection == #editClass ifTrue:[^self modifiedClassDefinition]. ^super contents! ! !FileContentsBrowser methodsFor: 'accessing' stamp: 'sw 5/23/2001 14:28'! contents: input notifying: aController "The retrieved information has changed and its source must now be updated. The information can be a variety of things, depending on the list selections (such as templates for class or message definition, methods) or the user menu commands (such as definition, comment, hierarchy). Answer the result of updating the source." | aString aText theClass | aString _ input asString. aText _ input asText. editSelection == #editComment ifTrue: [theClass _ self selectedClass. theClass ifNil: [self inform: 'You must select a class before giving it a comment.'. ^ false]. theClass comment: aText. ^ true]. editSelection == #editMessageCategories ifTrue: [^ self changeMessageCategories: aString]. self inform:'You cannot change the current selection'. ^false ! ! !FileContentsBrowser methodsFor: 'accessing'! packages ^packages! ! !FileContentsBrowser methodsFor: 'accessing'! packages: aDictionary packages := aDictionary.! ! !FileContentsBrowser methodsFor: 'accessing'! selectedPackage | cat | cat := self selectedSystemCategoryName. cat isNil ifTrue:[^nil]. ^self packages at: cat asString ifAbsent:[nil]! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 5/24/1998 20:37'! removeClass | class | classListIndex = 0 ifTrue: [^ self]. class _ self selectedClass. (self confirm:'Are you certain that you want to delete the class ', class name, '?') ifFalse:[^self]. self selectedPackage removeClass: class. self classListIndex: 0. self changed: #classList.! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'ar 8/2/2003 21:00'! removeMessage | messageName | messageListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. messageName _ self selectedMessageName. (self selectedClass confirmRemovalOf: messageName) ifFalse: [^ false]. self selectedClassOrMetaClass removeMethod: self selectedMessageName. self messageListIndex: 0. self setClassOrganizer. "In case organization not cached" self changed: #messageList! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 5/24/1998 20:51'! removeMessageCategory "If a message category is selected, create a Confirmer so the user can verify that the currently selected message category should be removed from the system. If so, remove it." | messageCategoryName | messageCategoryListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. messageCategoryName _ self selectedMessageCategoryName. (self messageList size = 0 or: [self confirm: 'Are you sure you want to remove this method category and all its methods?']) ifFalse: [^ self]. self selectedClassOrMetaClass removeCategory: messageCategoryName. self messageCategoryListIndex: 0. self changed: #messageCategoryList.! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 5/24/1998 20:52'! removePackage systemCategoryListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. (self confirm: 'Are you sure you want to remove this package and all its classes?') ifFalse:[^self]. (systemOrganizer listAtCategoryNamed: self selectedSystemCategoryName) do:[:el| systemOrganizer removeElement: el]. self packages removeKey: self selectedPackage packageName. systemOrganizer removeCategory: self selectedSystemCategoryName. self systemCategoryListIndex: 0. self changed: #systemCategoryList! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 2/3/1999 18:47'! removeUnmodifiedCategories | theClass | self okToChange ifFalse: [^self]. theClass _ self selectedClass. theClass isNil ifTrue: [^self]. Cursor wait showWhile: [theClass removeUnmodifiedMethods: theClass selectors. theClass metaClass removeUnmodifiedMethods: theClass metaClass selectors]. self messageCategoryListIndex: 0. self changed: #messageCategoryList.! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 5/24/1998 20:37'! removeUnmodifiedClasses | packageList | self okToChange ifFalse:[^self]. packageList := self selectedPackage isNil ifTrue:[self packages] ifFalse:[Array with: self selectedPackage]. packageList do:[:package| package classes copy do:[:theClass| Cursor wait showWhile:[ theClass removeAllUnmodified. ]. theClass hasChanges ifFalse:[ package removeClass: theClass. ]. ]]. self classListIndex: 0. self changed: #classList.! ! !FileContentsBrowser methodsFor: 'removing' stamp: 'wod 2/3/1999 18:47'! removeUnmodifiedMethods | theClass cat | self okToChange ifFalse:[^self]. theClass := self selectedClassOrMetaClass. theClass isNil ifTrue:[^self]. cat := self selectedMessageCategoryName. cat isNil ifTrue:[^self]. Cursor wait showWhile:[ theClass removeUnmodifiedMethods: (theClass organization listAtCategoryNamed: cat). ]. self messageListIndex: 0. self changed: #messageList.! ! !FileContentsBrowser methodsFor: 'class list' stamp: 'sma 5/6/2000 18:48'! browseMethodFull | myClass | (myClass _ self selectedClassOrMetaClass) ifNotNil: [Browser fullOnClass: myClass realClass selector: self selectedMessageName]! ! !FileContentsBrowser methodsFor: 'class list'! classList "Answer an array of the class names of the selected category. Answer an empty array if no selection exists." (systemCategoryListIndex = 0 or:[self selectedPackage isNil]) ifTrue: [^Array new] ifFalse: [^self selectedPackage classes keys asSortedCollection].! ! !FileContentsBrowser methodsFor: 'class list'! findClass | pattern foundClass classNames index foundPackage | self okToChange ifFalse: [^ self classNotFound]. pattern _ (FillInTheBlank request: 'Class Name?') asLowercase. pattern isEmpty ifTrue: [^ self]. classNames := Set new. self packages do:[:p| classNames addAll: p classes keys]. classNames := classNames asArray select: [:n | (n asLowercase indexOfSubCollection: pattern startingAt: 1) > 0]. classNames isEmpty ifTrue: [^ self]. index _ classNames size == 1 ifTrue: [1] ifFalse: [(PopUpMenu labelArray: classNames lines: #()) startUp]. index = 0 ifTrue: [^ self]. foundPackage := nil. foundClass := nil. self packages do:[:p| (p classes includesKey: (classNames at: index)) ifTrue:[ foundClass := p classes at: (classNames at: index). foundPackage := p]]. foundClass isNil ifTrue:[^self]. self systemCategoryListIndex: (self systemCategoryList indexOf: foundPackage packageName asSymbol). self classListIndex: (self classList indexOf: foundClass name). ! ! !FileContentsBrowser methodsFor: 'class list' stamp: 'wod 5/24/1998 20:37'! renameClass | oldName newName | classListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. oldName _ self selectedClass name. newName _ (self request: 'Please type new class name' initialAnswer: oldName) asSymbol. (newName isEmpty or:[newName = oldName]) ifTrue: [^ self]. (self selectedPackage classes includesKey: newName) ifTrue: [^ self error: newName , ' already exists in the package']. systemOrganizer classify: newName under: self selectedSystemCategoryName. systemOrganizer removeElement: oldName. self selectedPackage renameClass: self selectedClass to: newName. self changed: #classList. self classListIndex: ((systemOrganizer listAtCategoryNamed: self selectedSystemCategoryName) indexOf: newName). ! ! !FileContentsBrowser methodsFor: 'class list'! selectedClass "Answer the class that is currently selected. Answer nil if no selection exists." self selectedClassName == nil ifTrue: [^nil]. ^self selectedPackage classAt: self selectedClassName! ! !FileContentsBrowser methodsFor: 'edit pane' stamp: 'dew 9/22/2001 23:06'! selectedBytecodes "Compile the source code for the selected message selector and extract and return the bytecode listing." | class selector | class _ self selectedClassOrMetaClass. selector _ self selectedMessageName. contents _ class sourceCodeAt: selector. contents _ Compiler new parse: contents in: class notifying: nil. contents _ contents generate: #(0 0 0 0). ^ contents symbolic asText! ! !FileContentsBrowser methodsFor: 'edit pane' stamp: 'sw 11/13/2001 08:41'! selectedMessage "Answer a copy of the source code for the selected message selector." | class selector | class _ self selectedClassOrMetaClass. selector _ self selectedMessageName. contents _ class sourceCodeAt: selector. Preferences browseWithPrettyPrint ifTrue: [contents _ Compiler new format: contents in: class notifying: nil decorated: Preferences colorWhenPrettyPrinting]. self showingAnyKindOfDiffs ifTrue: [contents _ self methodDiffFor: contents class: self selectedClass selector: self selectedMessageName meta: self metaClassIndicated]. ^ contents asText makeSelectorBoldIn: class! ! !FileContentsBrowser methodsFor: 'diffs' stamp: 'sw 5/20/2001 21:03'! methodDiffFor: aString class: aPseudoClass selector: selector meta: meta "Answer the diff between the current copy of the given class/selector/meta for the string provided" | theClass source | theClass _ Smalltalk at: aPseudoClass name ifAbsent: [^ aString copy]. meta ifTrue: [theClass _ theClass class]. (theClass includesSelector: selector) ifFalse: [^ aString copy]. source _ theClass sourceCodeAt: selector. ^ Cursor wait showWhile: [TextDiffBuilder buildDisplayPatchFrom: source to: aString inClass: theClass prettyDiffs: self showingPrettyDiffs]! ! !FileContentsBrowser methodsFor: 'diffs'! modifiedClassDefinition | pClass rClass old new diff | pClass := self selectedClassOrMetaClass. pClass hasDefinition ifFalse:[^pClass definition]. rClass := Smalltalk at: self selectedClass name asSymbol ifAbsent:[nil]. rClass isNil ifTrue:[^pClass definition]. self metaClassIndicated ifTrue:[ rClass := rClass class]. old := rClass definition. new := pClass definition. Cursor wait showWhile:[ diff := ClassDiffBuilder buildDisplayPatchFrom: old to: new ]. ^diff! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut'! fileInClass Cursor read showWhile:[ self selectedClass fileIn. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 6/16/1998 17:14'! fileInMessage self selectedMessageName ifNil: [^self]. Cursor read showWhile: [ self selectedClassOrMetaClass fileInMethod: self selectedMessageName. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 2/3/1999 18:46'! fileInMessageCategories Cursor read showWhile:[ self selectedClassOrMetaClass fileInCategory: self selectedMessageCategoryName. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 5/13/1998 12:50'! fileInPackage Cursor read showWhile:[ self selectedPackage fileIn. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'nb 6/17/2003 12:25'! fileIntoNewChangeSet | p ff | (p _ self selectedPackage) ifNil: [^ Beeper beep]. ff _ StandardFileStream readOnlyFileNamed: p fullPackageName. ChangeSorter newChangesFromStream: ff named: p packageName! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut'! fileOutClass Cursor write showWhile:[ self selectedClass fileOut. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 6/16/1998 17:14'! fileOutMessage self selectedMessageName ifNil: [^self]. Cursor write showWhile: [ self selectedClassOrMetaClass fileOutMethod: self selectedMessageName].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 2/3/1999 18:46'! fileOutMessageCategories Cursor write showWhile:[ self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName. ].! ! !FileContentsBrowser methodsFor: 'fileIn/fileOut' stamp: 'wod 5/13/1998 14:19'! fileOutPackage Cursor write showWhile:[ self selectedPackage fileOut. ].! ! !FileContentsBrowser methodsFor: 'infoView' stamp: 'sma 5/6/2000 19:19'! extraInfo ^ (self methodDiffFor: (self selectedClassOrMetaClass sourceCodeAt: self selectedMessageName) class: self selectedClass selector: self selectedMessageName meta: self metaClassIndicated) unembellished ifTrue: [' - identical'] ifFalse: [' - modified']! ! !FileContentsBrowser methodsFor: 'infoView'! infoString ^infoString isNil ifTrue:[infoString := StringHolder new] ifFalse:[infoString]! ! !FileContentsBrowser methodsFor: 'infoView' stamp: 'sma 5/6/2000 18:26'! infoViewContents | theClass | editSelection == #newClass ifTrue: [^ self packageInfo: self selectedPackage]. self selectedClass isNil ifTrue: [^ '']. theClass _ Smalltalk at: self selectedClass name asSymbol ifAbsent: []. editSelection == #editClass ifTrue: [^ theClass notNil ifTrue: ['Class exists already in the system'] ifFalse: ['New class']]. editSelection == #editMessage ifFalse: [^ '']. (theClass notNil and: [self metaClassIndicated]) ifTrue: [theClass _ theClass class]. ^ (theClass notNil and: [theClass includesSelector: self selectedMessageName]) ifTrue: ['Method already exists' , self extraInfo] ifFalse: ['New method']! ! !FileContentsBrowser methodsFor: 'infoView'! packageInfo: p | nClasses newClasses oldClasses | p isNil ifTrue:[^'']. nClasses := newClasses := oldClasses := 0. p classes do:[:cls| nClasses := nClasses + 1. (Smalltalk includesKey: (cls name asSymbol)) ifTrue:[oldClasses := oldClasses + 1] ifFalse:[newClasses := newClasses + 1]]. ^nClasses printString,' classes (', newClasses printString, ' new / ', oldClasses printString, ' modified)'! ! !FileContentsBrowser methodsFor: 'infoView' stamp: 'BG 10/28/2003 20:55'! updateInfoView Smalltalk isMorphic ifFalse: [ self infoString contents: self infoViewContents. self infoString changed].! ! !FileContentsBrowser methodsFor: 'metaclass' stamp: 'asm 10/6/2003 11:29'! selectedClassOrMetaClass "Answer the selected class or metaclass." | cls | self metaClassIndicated ifTrue: [^ (cls _ self selectedClass) ifNotNil: [cls metaClass]] ifFalse: [^ self selectedClass]! ! !FileContentsBrowser methodsFor: 'metaclass'! setClassOrganizer "Install whatever organization is appropriate" | theClass | classOrganizer _ nil. metaClassOrganizer _ nil. classListIndex = 0 ifTrue: [^ self]. classOrganizer _ (theClass _ self selectedClass) organization. metaClassOrganizer _ theClass metaClass organization. ! ! !FileContentsBrowser methodsFor: 'other' stamp: 'bkv 8/13/2003 23:59'! browseSenders "Create and schedule a message set browser on all senders of the currently selected message selector. Do nothing if no message is selected." messageListIndex ~= 0 ifTrue: [self systemNavigation browseAllCallsOn: self selectedMessageName]! ! !FileContentsBrowser methodsFor: 'other' stamp: 'dew 9/20/2001 19:03'! browseVersions "Create and schedule a message set browser on all versions of the currently selected message selector." | class selector | (selector _ self selectedMessageName) ifNotNil: [class _ self selectedClassOrMetaClass. (class exists and: [class realClass includesSelector: selector]) ifTrue: [VersionsBrowser browseVersionsOf: (class realClass compiledMethodAt: selector) class: class realClass theNonMetaClass meta: class realClass isMeta category: self selectedMessageCategoryName selector: selector]]! ! !FileContentsBrowser methodsFor: 'other'! changeMessageCategories: aString "The characters in aString represent an edited version of the the message categories for the selected class. Update this information in the system and inform any dependents that the categories have been changed. This message is invoked because the user had issued the categories command and edited the message categories. Then the user issued the accept command." self classOrMetaClassOrganizer changeFromString: aString. self unlock. self editClass. self classListIndex: classListIndex. ^ true! ! !FileContentsBrowser methodsFor: 'other' stamp: 'asm 5/30/2003 18:11'! didCodeChangeElsewhere "Determine whether the code for the currently selected method and class has been changed somewhere else." | aClass | (aClass _ self selectedClassOrMetaClass) ifNil: [^ false]. (aClass isKindOf: PseudoClass) ifTrue: [^ false]. "class not installed" ^super didCodeChangeElsewhere! ! !FileContentsBrowser methodsFor: 'other' stamp: 'sw 10/1/2001 11:16'! labelString "Answer the string for the window title" ^ 'File Contents Browser ', (self selectedSystemCategoryName ifNil: [''])! ! !FileContentsBrowser methodsFor: 'other' stamp: 'sma 2/6/2000 12:27'! methodHierarchy (self selectedClassOrMetaClass isNil or: [self selectedClassOrMetaClass hasDefinition]) ifFalse: [super methodHierarchy]! ! !FileContentsBrowser methodsFor: 'creation' stamp: 'BG 10/28/2003 20:55'! createViews "Create a pluggable version of all the views for a Browser, including views and controllers." | hasSingleFile width topView packageListView classListView switchView messageCategoryListView messageListView browserCodeView infoView | contentsSymbol _ self defaultDiffsSymbol. "#showDiffs or #prettyDiffs" (hasSingleFile _ self packages size = 1) ifTrue: [width _ 150] ifFalse: [width _ 200]. (topView _ StandardSystemView new) model: self; borderWidth: 1. "label and minSize taken care of by caller" hasSingleFile ifTrue: [ self systemCategoryListIndex: 1. packageListView _ PluggableListView on: self list: #systemCategorySingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #packageListMenu: keystroke: #packageListKey:from:. packageListView window: (0 @ 0 extent: width @ 12)] ifFalse: [ packageListView _ PluggableListView on: self list: #systemCategoryList selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex: menu: #packageListMenu: keystroke: #packageListKey:from:. packageListView window: (0 @ 0 extent: 50 @ 70)]. topView addSubView: packageListView. classListView _ PluggableListView on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 50 @ 62). hasSingleFile ifTrue: [topView addSubView: classListView below: packageListView] ifFalse: [topView addSubView: classListView toRightOf: packageListView]. switchView _ self buildInstanceClassSwitchView. switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu: keystroke: #messageListKey:from:. messageListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: width@110). topView addSubView: browserCodeView below: (hasSingleFile ifTrue: [switchView] ifFalse: [packageListView]). infoView _ StringHolderView new model: self infoString; window: (0@0 extent: width@12); borderWidth: 1. topView addSubView: infoView below: browserCodeView. ^ topView ! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'sma 5/6/2000 18:36'! classListMenu: aMenu ^ aMenu labels: 'definition comment browse full (b) class refs (N) fileIn fileOut rename... remove remove existing' lines: #(2 4 6 8) selections: #(editClass editComment browseMethodFull browseClassRefs fileInClass fileOutClass renameClass removeClass removeUnmodifiedCategories) ! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'tpr 3/11/2001 21:26'! classListMenu: aMenu shifted: ignored "Answer the class list menu, ignoring the state of the shift key in this case" ^ self classListMenu: aMenu! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'sw 11/13/2001 09:12'! contentsSymbolQuints "Answer a list of quintuplets representing information on the alternative views available in the code pane. For the file-contents browser, the choices are restricted to source and the two diffing options" ^ self sourceAndDiffsQuintsOnly! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'wod 5/13/1998 17:39'! messageCategoryMenu: aMenu ^ aMenu labels: 'fileIn fileOut reorganize add item... rename... remove remove existing' lines: #(2 3 6) selections: #(fileInMessageCategories fileOutMessageCategories editMessageCategories addCategory renameCategory removeMessageCategory removeUnmodifiedMethods)! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'sma 2/6/2000 12:28'! messageListMenu: aMenu ^ aMenu labels: 'fileIn fileOut senders (n) implementors (m) method inheritance (h) versions (v) remove' lines: #(2 6) selections: #(fileInMessage fileOutMessage browseSenders browseImplementors methodHierarchy browseVersions removeMessage).! ! !FileContentsBrowser methodsFor: 'menus' stamp: 'sma 4/22/2000 20:52'! packageListMenu: aMenu ^ aMenu labels: 'find class... (f) fileIn file into new changeset fileOut remove remove existing' lines: #(1 4 5) selections: #(findClass fileInPackage fileIntoNewChangeSet fileOutPackage removePackage removeUnmodifiedClasses)! ! !FileContentsBrowser methodsFor: 'keys' stamp: 'sma 5/6/2000 18:48'! classListKey: aChar from: view aChar == $b ifTrue: [^ self browseMethodFull]. aChar == $N ifTrue: [^ self browseClassRefs]. self packageListKey: aChar from: view! ! !FileContentsBrowser methodsFor: 'keys' stamp: 'sma 5/6/2000 18:50'! messageListKey: aChar from: view aChar == $b ifTrue: [^ self browseMethodFull]. super messageListKey: aChar from: view! ! !FileContentsBrowser methodsFor: 'keys' stamp: 'sma 2/6/2000 12:05'! packageListKey: aChar from: view aChar == $f ifTrue: [^ self findClass]. self arrowKey: aChar from: view! ! !FileContentsBrowser methodsFor: 'initialize-release' stamp: 'dew 9/15/2001 16:19'! defaultBrowserTitle ^ 'File Contents Browser'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileContentsBrowser class instanceVariableNames: ''! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nb 6/17/2003 12:25'! browseFile: aFilename "Open a file contents browser on a file of the given name" aFilename ifNil: [^ Beeper beep]. self browseFiles: (Array with: aFilename)! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'dew 8/2/2000 20:02'! browseFiles: fileList | package organizer packageDict browser | Cursor wait showWhile: [ packageDict _ Dictionary new. organizer _ SystemOrganizer defaultList: Array new. fileList do: [:fileName | package _ FilePackage fromFileNamed: fileName. packageDict at: package packageName put: package. organizer classifyAll: package classes keys under: package packageName]. (browser := self new) systemOrganizer: organizer; packages: packageDict]. self openBrowserView: browser createViews label: 'File Contents Browser'. ! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nk 2/17/2004 19:26'! browseStream: aStream self browseStream: aStream named: aStream name! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nk 2/17/2004 19:25'! browseStream: aStream named: aString | package organizer packageDict browser | Cursor wait showWhile: [ packageDict _ Dictionary new. organizer _ SystemOrganizer defaultList: Array new. package _ (FilePackage new fullName: aString; fileInFrom: aStream). packageDict at: package packageName put: package. organizer classifyAll: package classes keys under: package packageName. (browser := self new) systemOrganizer: organizer; packages: packageDict]. self openBrowserView: browser createViews label: 'File Contents Browser'. ! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nk 2/17/2004 19:18'! fileReaderServicesForFile: fullName suffix: suffix ((FileStream isSourceFileSuffix: suffix) or: [ suffix = '*' ]) ifTrue: [ ^Array with: self serviceBrowseCode]. ^(fullName endsWith: 'cs.gz') ifTrue: [ Array with: self serviceBrowseCompressedCode ] ifFalse: [#()] ! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'SD 11/14/2001 22:13'! selectAndBrowseFile: aFileList "When no file are selected you can ask to browse several of them" | selectionPattern files | selectionPattern := FillInTheBlank request:'What files?' initialAnswer: aFileList pattern. files _ (aFileList directory fileNamesMatching: selectionPattern) collect: [:each | aFileList directory fullNameFor: each]. FileContentsBrowser browseFiles: files. ! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nk 4/29/2004 10:35'! serviceBrowseCode "Answer the service of opening a file-contents browser" ^ (SimpleServiceEntry provider: self label: 'code-file browser' selector: #browseStream: description: 'open a "file-contents browser" on this file, allowing you to view and selectively load its code' buttonLabel: 'code') argumentGetter: [ :fileList | fileList readOnlyStream ]! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'nk 4/29/2004 10:35'! serviceBrowseCompressedCode "Answer a service for opening a changelist browser on a file" ^ (SimpleServiceEntry provider: self label: 'code-file browser' selector: #browseCompressedCodeStream: description: 'open a "file-contents browser" on this file, allowing you to view and selectively load its code' buttonLabel: 'code') argumentGetter: [ :fileList | fileList readOnlyStream ]! ! !FileContentsBrowser class methodsFor: 'instance creation' stamp: 'sd 2/1/2002 21:40'! services ^ Array with: self serviceBrowseCode ! ! !FileContentsBrowser class methodsFor: 'class initialization' stamp: 'hg 8/3/2000 18:17'! initialize FileList registerFileReader: self! ! !FileContentsBrowser class methodsFor: 'class initialization' stamp: 'SD 11/15/2001 22:21'! unload FileList unregisterFileReader: self ! ! Object subclass: #FileDirectory instanceVariableNames: 'pathName' classVariableNames: 'DefaultDirectory DirectoryClass StandardMIMEMappings' poolDictionaries: '' category: 'System-Files'! !FileDirectory commentStamp: '<historical>' prior: 0! A FileDirectory represents a folder or directory in the underlying platform's file system. It carries a fully-qualified path name for the directory it represents, and can enumerate the files and directories within that directory. 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". Each entry is an array of five items: <name> <creationTime> <modificationTime> <dirFlag> <fileSize> The times are given in seconds, and can be converted to a time and date via Time>dateAndTimeFromSeconds:. See the comment in lookupEntry:... which provides primitive access to this information. ! !FileDirectory methodsFor: 'path access' stamp: 'ar 12/18/1999 01:01'! fullPathFor: path ^path isEmpty ifTrue:[pathName] ifFalse:[path]! ! !FileDirectory methodsFor: 'path access' stamp: 'tk 5/18/1998 22:29'! on: fullPath "Return another instance" ^ self class on: fullPath! ! !FileDirectory methodsFor: 'path access' stamp: 'jm 12/5/97 12:18'! pathName "Return the path from the root of the file system to this directory." ^ pathName ! ! !FileDirectory methodsFor: 'path access' stamp: 'jm 12/5/97 12:19'! pathNameDelimiter "Return the delimiter character for this kind of directory. This depends on the current platform." ^ self class pathNameDelimiter ! ! !FileDirectory methodsFor: 'path access' stamp: 'jm 12/5/97 12:17'! pathParts "Return the path from the root of the file system to this directory as an array of directory names." ^ pathName findTokens: self pathNameDelimiter asString ! ! !FileDirectory methodsFor: 'path access' stamp: 'ar 12/18/1999 00:36'! slash ^self class slash! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'tk 5/19/1998 09:03'! fileNamed: localFileName "Open the file with the given name in this directory for writing." ^ FileStream concreteStream fileNamed: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'dew 10/26/2000 02:08'! forceNewFileNamed: localFileName "Open the file with the given name in this directory for writing. If it already exists, delete it first without asking." ^ FileStream concreteStream forceNewFileNamed: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'tk 5/19/1998 09:03'! newFileNamed: localFileName "Create a new file with the given name in this directory." ^ FileStream concreteStream newFileNamed: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'tk 5/19/1998 09:03'! oldFileNamed: localFileName "Open the existing file with the given name in this directory." ^ FileStream concreteStream oldFileNamed: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'tpr 10/13/2003 12:34'! oldFileOrNoneNamed: fileName "If the file exists, answer a read-only FileStream on it. If it doesn't, answer nil." ^ FileStream oldFileOrNoneNamed: fileName ! ! !FileDirectory methodsFor: 'file stream creation' stamp: 'tk 5/19/1998 09:03'! readOnlyFileNamed: localFileName "Open the existing file with the given name in this directory for read-only access." ^ FileStream concreteStream readOnlyFileNamed: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 1/5/98 20:49'! containingDirectory "Return the directory containing this directory." ^ FileDirectory on: (FileDirectory dirPathFor: pathName) ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'tpr 10/13/2003 10:58'! directoryEntryFor: filenameOrPath "Answer the directory entry for the given file or path. Sorta like a poor man's stat()." | fName dir | DirectoryClass splitName: filenameOrPath to:[:filePath :name | fName _ name. filePath isEmpty ifTrue: [dir _ self] ifFalse: [dir _ FileDirectory on: filePath]]. self isCaseSensitive ifTrue:[^dir entries detect:[:entry| entry name = fName] ifNone:[nil]] ifFalse:[^dir entries detect:[:entry| entry name sameAs: fName] ifNone:[nil]]! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 15:46'! directoryNamed: localFileName "Return the subdirectory of this directory with the given name." ^ FileDirectory on: (self fullNameFor: localFileName) ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 15:44'! directoryNames "Return a collection of names for the subdirectories of this directory." "FileDirectory default directoryNames" ^ (self entries select: [:entry | entry at: 4]) collect: [:entry | entry first] ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 12:23'! entries "Return a collection of directory entries for the files and directories in this directory. Each entry is a five-element array: (<name><creationTime><modificationTime><dirFlag><fileSize>). See primLookupEntryIn:index: for further details." "FileDirectory default entries" ^ self directoryContentsFor: pathName ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 15:39'! fileAndDirectoryNames "FileDirectory default fileAndDirectoryNames" ^ self entries collect: [:entry | entry first] ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 15:44'! fileNames "Return a collection of names for the files (but not directories) in this directory." "FileDirectory default fileNames" ^ (self entries select: [:entry | (entry at: 4) not]) collect: [:entry | entry first] ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'ar 3/15/2001 23:20'! fullName "Return the full name of this directory." ^pathName! ! !FileDirectory methodsFor: 'enumeration' stamp: 'jm 12/5/97 15:39'! keysDo: nameBlock "Evaluate the given block for each file or directory name in this directory." ^ self fileAndDirectoryNames do: nameBlock ! ! !FileDirectory methodsFor: 'enumeration' stamp: 'ar 2/6/2001 15:48'! localName "Return the local name of this directory." ^FileDirectory localNameFor: pathName! ! !FileDirectory methodsFor: 'testing' stamp: 'tpr 2/17/2004 19:56'! directoryExists: filenameOrPath "Answer true if a directory of the given name exists. The given name may be either a full path name or a local directory within this directory." "FileDirectory default directoryExists: FileDirectory default pathName" | fName dir | DirectoryClass splitName: filenameOrPath to: [:filePath :name | fName _ name. filePath isEmpty ifTrue: [dir _ self] ifFalse: [dir _ self directoryNamed: filePath]]. ^dir exists and: [ self isCaseSensitive ifTrue:[dir directoryNames includes: fName] ifFalse:[dir directoryNames anySatisfy: [:name| name sameAs: fName]]]. ! ! !FileDirectory methodsFor: 'testing' stamp: 'nk 11/30/2002 14:06'! exists "Answer whether the directory exists" | result | result _ self primLookupEntryIn: pathName index: 1. ^ result ~= #badDirectoryPath! ! !FileDirectory methodsFor: 'testing' stamp: 'tpr 10/13/2003 10:59'! fileExists: filenameOrPath "Answer true if a file of the given name exists. The given name may be either a full path name or a local file within this directory." "FileDirectory default fileExists: Smalltalk sourcesName" | fName dir | DirectoryClass splitName: filenameOrPath to: [:filePath :name | fName _ name. filePath isEmpty ifTrue: [dir _ self] ifFalse: [dir _ FileDirectory on: filePath]]. self isCaseSensitive ifTrue:[^dir fileNames includes: fName] ifFalse:[^dir fileNames anySatisfy: [:name| name sameAs: fName]]. ! ! !FileDirectory methodsFor: 'testing' stamp: 'di 11/21/1999 20:17'! includesKey: localName "Answer true if this directory includes a file or directory of the given name. Note that the name should be a local file name, in contrast with fileExists:, which takes either local or full-qualified file names." "(FileDirectory on: Smalltalk vmPath) includesKey: 'SqueakV2.sources'" self isCaseSensitive ifTrue:[^ self fileAndDirectoryNames includes: localName] ifFalse:[^ self fileAndDirectoryNames anySatisfy: [:str| str sameAs: localName]].! ! !FileDirectory methodsFor: 'testing' stamp: 'ar 5/30/2001 21:42'! isAFileNamed: fName ^FileStream isAFileNamed: (self fullNameFor: fName)! ! !FileDirectory methodsFor: 'testing' stamp: 'ar 5/1/1999 01:51'! isCaseSensitive "Return true if file names are treated case sensitive" ^self class isCaseSensitive! ! !FileDirectory methodsFor: 'file operations' stamp: 'MPH 10/15/2000 12:43'! copyFile: fileStream1 toFile: fileStream2 | buffer | buffer _ String new: 50000. [fileStream1 atEnd] whileFalse: [fileStream2 nextPutAll: (fileStream1 nextInto: buffer)]. ! ! !FileDirectory methodsFor: 'file operations' stamp: 'dew 10/26/2000 02:23'! copyFileWithoutOverwriteConfirmationNamed: fileName1 toFileNamed: fileName2 "Copy the contents of the existing file with the first name into a file with the second name (which may or may not exist). If the second file exists, force an overwrite without confirming. Both files are assumed to be in this directory." "FileDirectory default copyFileWithoutOverwriteConfirmationNamed: 'todo.txt' toFileNamed: 'todocopy.txt'" | file1 file2 | fileName1 = fileName2 ifTrue: [^ self]. file1 _ (self readOnlyFileNamed: fileName1) binary. file2 _ (self forceNewFileNamed: fileName2) binary. self copyFile: file1 toFile: file2. file1 close. file2 close.! ! !FileDirectory methodsFor: 'file operations' stamp: 'jm 12/4/97 22:55'! createDirectory: localFileName "Create a directory with the given name in this directory. Fail if the name is bad or if a file or directory with that name already exists." self primCreateDirectory: (self fullNameFor: localFileName). ! ! !FileDirectory methodsFor: 'file operations' stamp: 'jm 4/9/1999 18:02'! deleteDirectory: localDirName "Delete the directory with the given name in this directory. Fail if the path is bad or if a directory by that name does not exist." self primDeleteDirectory: (self fullNameFor: localDirName). ! ! !FileDirectory methodsFor: 'file operations' stamp: 'jm 12/5/97 16:33'! deleteFileNamed: localFileName "Delete the file with the given name in this directory." self deleteFileNamed: localFileName ifAbsent: []. ! ! !FileDirectory methodsFor: 'file operations' stamp: 'ar 12/12/2001 15:56'! deleteFileNamed: localFileName ifAbsent: failBlock "Delete the file of the given name if it exists, else evaluate failBlock. If the first deletion attempt fails do a GC to force finalization of any lost references. ar 3/21/98 17:53" | fullName | fullName _ self fullNameFor: localFileName. (StandardFileStream retryWithGC:[self primDeleteFileNamed: (self fullNameFor: localFileName)] until:[:result| result notNil] forFileNamed: fullName) == nil ifTrue: [^failBlock value]. ! ! !FileDirectory methodsFor: 'file operations' stamp: 'tpr 10/13/2003 10:59'! fileOrDirectoryExists: filenameOrPath "Answer true if either a file or a directory file of the given name exists. The given name may be either a full path name or a local name within this directory." "FileDirectory default fileOrDirectoryExists: Smalltalk sourcesName" | fName dir | DirectoryClass splitName: filenameOrPath to: [:filePath :name | fName _ name. filePath isEmpty ifTrue: [dir _ self] ifFalse: [dir _ FileDirectory on: filePath]]. ^ (dir includesKey: fName) or: [ fName = '' and:[ dir entries size > 1]]! ! !FileDirectory methodsFor: 'file operations' stamp: 'ar 12/12/2001 15:57'! rename: oldFileName toBe: newFileName | selection oldName newName | "Rename the file of the given name to the new name. Fail if there is no file of the old name or if there is an existing file with the new name." "Modified for retry after GC ar 3/21/98 18:09" oldName _ self fullNameFor: oldFileName. newName _ self fullNameFor: newFileName. (StandardFileStream retryWithGC:[self primRename: oldName to: newName] until:[:result| result notNil] forFileNamed: oldName) ~~ nil ifTrue:[^self]. (self fileExists: oldFileName) ifFalse:[ ^self error:'Attempt to rename a non-existent file'. ]. (self fileExists: newFileName) ifTrue:[ selection _ (PopUpMenu labels: 'delete old version cancel') startUpWithCaption: 'Trying to rename a file to be ', newFileName , ' and it already exists.'. selection = 1 ifTrue: [self deleteFileNamed: newFileName. ^ self rename: oldFileName toBe: newFileName]]. ^self error:'Failed to rename file'.! ! !FileDirectory methodsFor: 'file operations' stamp: 'jm 3/27/98 06:40'! setMacFileNamed: fileName type: typeString creator: creatorString "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. Does nothing on other platforms (where the underlying primitive is a noop)." "FileDirectory default setMacFileNamed: 'foo' type: 'TEXT' creator: 'ttxt'" self primSetMacFileNamed: (self fullNameFor: fileName) type: typeString creator: creatorString. ! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'jm 5/8/1998 20:48'! checkName: aFileName fixErrors: fixing "Check a string aFileName for validity as a file name. Answer the original file name if it is valid. If the name is not valid (e.g., it is too long or contains illegal characters) and fixing is false, raise an error. If fixing is true, fix the name (usually by truncating and/or tranforming characters), and answer the corrected name. The default behavior is just to truncate the name to the maximum length for this platform. Subclasses can do any kind of checking and correction appropriate for their platform." | maxLength | aFileName size = 0 ifTrue: [self error: 'zero length file name']. maxLength _ self class maxFileNameLength. aFileName size > maxLength ifTrue: [ fixing ifTrue: [^ aFileName contractTo: maxLength] ifFalse: [self error: 'file name is too long']]. ^ aFileName ! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'jm 12/4/97 21:01'! fileNamesMatching: pat "FileDirectory default fileNamesMatching: '*'" ^ self fileNames select: [:name | pat match: name] ! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'tpr 10/13/2003 10:59'! fullNameFor: fileName "Return a corrected, fully-qualified name for the given file name. If the given name is already a full path (i.e., it contains a delimiter character), assume it is already a fully-qualified name. Otherwise, prefix it with the path to this directory. In either case, correct the local part of the file name." "Details: Note that path relative to a directory, such as '../../foo' are disallowed by this algorithm. Also note that this method is tolerent of a nil argument -- is simply returns nil in this case." | correctedLocalName prefix | fileName ifNil: [^ nil]. DirectoryClass splitName: fileName to: [:filePath :localName | correctedLocalName _ localName isEmpty ifFalse: [self checkName: localName fixErrors: true] ifTrue: [localName]. prefix _ self fullPathFor: filePath]. prefix isEmpty ifTrue: [^correctedLocalName]. prefix last = self pathNameDelimiter ifTrue:[^ prefix, correctedLocalName] ifFalse:[^ prefix, self slash, correctedLocalName]! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'djp 10/27/1999 09:01'! nextNameFor: baseFileName extension: extension "Assumes a file name includes a version number encoded as '.' followed by digits preceding the file extension. Increment the version number and answer the new file name. If a version number is not found, set the version to 1 and answer a new file name" | files splits version | files _ self fileNamesMatching: (baseFileName,'*', self class dot, extension). splits _ files collect: [:file | self splitNameVersionExtensionFor: file] thenSelect: [:split | (split at: 1) = baseFileName]. splits _ splits asSortedCollection: [:a :b | (a at: 2) < (b at: 2)]. splits isEmpty ifTrue: [version _ 1] ifFalse: [version _ (splits last at: 2) + 1]. ^ (baseFileName, '.', version asString, self class dot, extension) asFileName! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'djp 10/27/1999 08:58'! splitNameVersionExtensionFor: fileName " answer an array with the root name, version # and extension. See comment in nextSequentialNameFor: for more details" | baseName version extension i j | baseName _ self class baseNameFor: fileName. extension _ self class extensionFor: fileName. i _ j _ baseName findLast: [:c | c isDigit not]. i = 0 ifTrue: [version _ 0] ifFalse: [(baseName at: i) = $. ifTrue: [version _ (baseName copyFrom: i+1 to: baseName size) asNumber. j _ j - 1] ifFalse: [version _ 0]. baseName _ baseName copyFrom: 1 to: j]. ^ Array with: baseName with: version with: extension! ! !FileDirectory methodsFor: 'file name utilities' stamp: 'gk 2/10/2004 13:23'! url "Convert my path into a file:// type url String." ^self asUrl toText! ! !FileDirectory methodsFor: 'printing' stamp: 'jm 12/4/97 19:41'! printOn: aStream "Refer to the comment in Object|printOn:." aStream nextPutAll: self class name. aStream nextPutAll: ' on '. pathName printOn: aStream. ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 5/30/2001 20:49'! directoryContentsFor: fullPath "Return a collection of directory entries for the files and directories in the directory with the given path. See primLookupEntryIn:index: for further details." "FileDirectory default directoryContentsFor: ''" | entries index done entryArray | entries _ OrderedCollection new: 200. index _ 1. done _ false. [done] whileFalse: [ entryArray _ self primLookupEntryIn: fullPath index: index. #badDirectoryPath = entryArray ifTrue: [ ^(InvalidDirectoryError pathName: pathName) signal]. entryArray == nil ifTrue: [done _ true] ifFalse: [entries addLast: (DirectoryEntry fromArray: entryArray)]. index _ index + 1]. ^ entries asArray ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primCreateDirectory: fullPath "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." <primitive: 'primitiveDirectoryCreate' module: 'FilePlugin'> self primitiveFailed ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primDeleteDirectory: fullPath "Delete the directory named by the given path. Fail if the path is bad or if a directory by that name does not exist." <primitive: 'primitiveDirectoryDelete' module: 'FilePlugin'> self primitiveFailed ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primDeleteFileNamed: aFileName "Delete the file of the given name. Return self if the primitive succeeds, nil otherwise." <primitive: 'primitiveFileDelete' module: 'FilePlugin'> ^ nil ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primLookupEntryIn: fullPath index: index "Look up the index-th entry of the directory with the given fully-qualified path (i.e., starting from the root of the file hierarchy) and return an array containing: <name> <creationTime> <modificationTime> <dirFlag> <fileSize> The empty string enumerates the top-level files or drives. (For example, on Unix, the empty path enumerates the contents of '/'. On Macs and PCs, it enumerates the mounted volumes/drives.) 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 path is bad." <primitive: 'primitiveDirectoryLookup' module: 'FilePlugin'> ^ #badDirectoryPath ! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primRename: oldFileFullName to: newFileFullName "Rename the file of the given name to the new name. Fail if there is no file of the old name or if there is an existing file with the new name. Changed to return nil instead of failing ar 3/21/98 18:04" <primitive: 'primitiveFileRename' module: 'FilePlugin'> ^nil! ! !FileDirectory methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primSetMacFileNamed: fileName type: typeString creator: creatorString "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. This primitive is Mac specific; it is a noop on other platforms." <primitive: 'primitiveDirectorySetMacTypeAndCreator' module: 'FilePlugin'> self primitiveFailed ! ! !FileDirectory methodsFor: 'private' stamp: 'jm 12/4/97 22:44'! setPathName: pathString pathName _ pathString. ! ! !FileDirectory methodsFor: 'file directory' stamp: 'hg 2/2/2002 16:37'! assureExistence "Make sure the current directory exists. If necessary, create all parts in between" self containingDirectory assureExistenceOfPath: self localName! ! !FileDirectory methodsFor: 'file directory' stamp: 'nk 3/13/2003 10:18'! assureExistenceOfPath: localPath "Make sure the local directory exists. If necessary, create all parts in between" localPath isEmpty ifTrue: [ ^self ]. "Assumed to exist" (self directoryExists: localPath) ifTrue: [^ self]. "exists" "otherwise check parent first and then create local dir" self containingDirectory assureExistenceOfPath: self localName. self createDirectory: localPath! ! !FileDirectory methodsFor: 'file directory' stamp: 'RAA 7/28/2000 13:47'! localNameFor: fullName "Return the local part the given name." ^self class localNameFor: fullName! ! !FileDirectory methodsFor: 'file directory' stamp: 'tk 12/13/1999 18:55'! sleep "Leave the FileList window. Do nothing. Disk directories do not have to be shut down." ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileDirectory class instanceVariableNames: ''! !FileDirectory class methodsFor: 'instance creation' stamp: 'jm 12/4/97 19:24'! default "Answer the default directory." ^ DefaultDirectory ! ! !FileDirectory class methodsFor: 'instance creation' stamp: 'ls 9/10/1998 00:59'! forFileName: aString | path | path _ self dirPathFor: aString. path isEmpty ifTrue: [^ self default]. ^ self on: path ! ! !FileDirectory class methodsFor: 'instance creation' stamp: 'tpr 10/13/2003 10:49'! on: pathString "Return a new file directory for the given path, of the appropriate FileDirectory subclass for the current OS platform." | pathName | DirectoryClass ifNil: [self setDefaultDirectoryClass]. "If path ends with a delimiter (: or /) then remove it" ((pathName _ pathString) endsWith: self pathNameDelimiter asString) ifTrue: [ pathName _ pathName copyFrom: 1 to: pathName size - 1]. ^ DirectoryClass new setPathName: pathName ! ! !FileDirectory class methodsFor: 'instance creation' stamp: 'jm 12/4/97 23:29'! root "Answer the root directory." ^ self on: '' ! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'tpr 3/6/2004 20:18'! baseNameFor: fileName "Return the given file name without its extension, if any. We have to remember that many (most?) OSs allow extension separators within directory names and so the leaf filename needs to be extracted, trimmed and rejoined. Yuck" "The test is FileDirectory baseNameFor: ((FileDirectory default directoryNamed: 'foo.bar') fullNameFor:'blim.blam') should end 'foo.bar/blim' (or as appropriate for your platform AND FileDirectory baseNameFor: ((FileDirectory default directoryNamed: 'foo.bar') fullNameFor:'blim') should be the same and NOT 'foo' Oh, and FileDirectory baseNameFor: 'foo.bar' should be 'foo' not '/foo' " | delim i leaf | self splitName: fileName to: [:path : fn| delim _ DirectoryClass extensionDelimiter. i _ fn findLast: [:c | c = delim]. leaf _ i = 0 ifTrue: [fn] ifFalse: [fn copyFrom: 1 to: i - 1]. path isEmpty ifTrue:[^leaf]. ^path, self slash, leaf] ! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'TPR 5/10/1998 21:32'! changeSuffix "if 'changes' is not suitable, override this message to return something that is ok" ^'changes'! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'jf 2/7/2004 17:22'! checkName: fileName fixErrors: flag "Check a string fileName for validity as a file name on the current default file system. Answer the original file name if it is valid. If the name is not valid (e.g., it is too long or contains illegal characters) and fixing is false, raise an error. If fixing is true, fix the name (usually by truncating and/or tranforming characters), and answer the corrected name. The default behavior is to truncate the name to 31 chars. Subclasses can do any kind of checking and correction appropriate to the underlying platform." ^ DefaultDirectory checkName: fileName fixErrors: flag ! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'tpr 10/13/2003 10:59'! dirPathFor: fullName "Return the directory part the given name." DirectoryClass splitName: fullName to: [:dirPath :localName | ^ dirPath]! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'ar 4/7/2002 15:47'! directoryEntryFor: filenameOrPath ^self default directoryEntryFor: filenameOrPath! ! !FileDirectory class methodsFor: 'name utilities'! extensionFor: fileName "Return the extension of given file name, if any." | delim i | delim _ DirectoryClass extensionDelimiter. i _ fileName findLast: [:c | c = delim]. i = 0 ifTrue: [^ ''] ifFalse: [^ fileName copyFrom: i + 1 to: fileName size]. ! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'TPR 5/10/1998 21:31'! imageSuffix "if 'image' is not suitable, override this message to return something that is ok" ^'image'! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'tpr 10/13/2003 10:59'! localNameFor: fullName "Return the local part the given name." DirectoryClass splitName: fullName to: [:dirPath :localName | ^ localName]! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'bf 3/22/2000 18:04'! splitName: fullName to: pathAndNameBlock "Take the file name and convert it to the path name of a directory and a local file name within that directory. FileName must be of the form: <dirPath><delimiter><localName>, where <dirPath><delimiter> is optional. The <dirPath> part may contain delimiters." | delimiter i dirName localName | delimiter _ self pathNameDelimiter. (i _ fullName findLast: [:c | c = delimiter]) = 0 ifTrue: [dirName _ String new. localName _ fullName] ifFalse: [dirName _ fullName copyFrom: 1 to: (i - 1 max: 1). localName _ fullName copyFrom: i + 1 to: fullName size]. ^ pathAndNameBlock value: dirName value: localName! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'ssa 9/3/2008 11:25'! startUp "Establish the platform-specific FileDirectory subclass. Do any platform-specific startup." self setDefaultDirectoryClass. self setDefaultDirectory: (self dirPathFor: SmalltalkImage current imageName). Preferences startInUntrustedDirectory ifTrue:[ DefaultDirectory assureExistence]. SmalltalkImage current openSourceFiles. ! ! !FileDirectory class methodsFor: 'create/delete file' stamp: 'tk 1/13/98 17:21'! deleteFilePath: fullPathToAFile "Delete the file after finding its directory" | dir | dir _ self on: (self dirPathFor: fullPathToAFile). dir deleteFileNamed: (self localNameFor: fullPathToAFile). ! ! !FileDirectory class methodsFor: 'system start up' stamp: 'tpr 10/9/2003 16:27'! openChanges: changesName forImage: imageName "find the changes file by looking in a) the directory derived from the image name b) the DefaultDirectory (which will normally be the directory derived from the image name or the SecurityManager's choice) If an old file is not found in either place, check for a read-only file in the same places. If that fails, return nil" | changes fd | "look for the changes file or an alias to it in the image directory" fd _ FileDirectory on: (FileDirectory dirPathFor: imageName). (fd fileExists: changesName) ifTrue: [changes _ fd oldFileNamed: changesName]. changes ifNotNil:[^changes]. "look for the changes in the default directory" fd _ DefaultDirectory. (fd fileExists: changesName) ifTrue: [changes _ fd oldFileNamed: changesName]. changes ifNotNil:[^changes]. "look for read-only changes in the image directory" fd _ FileDirectory on: (FileDirectory dirPathFor: imageName). (fd fileExists: changesName) ifTrue: [changes _ fd readOnlyFileNamed: changesName]. changes ifNotNil:[^changes]. "look for read-only changes in the default directory" fd _ DefaultDirectory. (fd fileExists: changesName) ifTrue: [changes _ fd readOnlyFileNamed: changesName]. "this may be nil if the last try above failed to open a file" ^changes ! ! !FileDirectory class methodsFor: 'system start up' stamp: 'tpr 12/15/2003 12:02'! openSources: sourcesName andChanges: changesName forImage: imageName "Open the changes and sources files and install them in SourceFiles. Inform the user of problems regarding write permissions or CR/CRLF mixups." "Note: SourcesName and imageName are full paths; changesName is a local name." | sources changes msg wmsg | msg _ 'Squeak cannot locate &fileRef. Please check that the file is named properly and is in the same directory as this image. Further explanation can found in the startup window, ''How Squeak Finds Source Code''.'. wmsg _ 'Squeak cannot write to &fileRef. Please check that you have write permission for this file. You won''t be able to save this image correctly until you fix this.'. sources _ self openSources: sourcesName forImage: imageName. changes _ self openChanges: changesName forImage: imageName. ((sources == nil or: [sources atEnd]) and: [Preferences valueOfFlag: #warnIfNoSourcesFile]) ifTrue: [SmalltalkImage current platformName = 'Mac OS' ifTrue: [msg _ msg , ' Make sure the sources file is not an Alias.']. self inform: (msg copyReplaceAll: '&fileRef' with: 'the sources file named ' , sourcesName)]. (changes == nil and: [Preferences valueOfFlag: #warnIfNoChangesFile]) ifTrue: [self inform: (msg copyReplaceAll: '&fileRef' with: 'the changes file named ' , changesName)]. ((Preferences valueOfFlag: #warnIfNoChangesFile) and: [changes notNil]) ifTrue: [changes isReadOnly ifTrue: [self inform: (wmsg copyReplaceAll: '&fileRef' with: 'the changes file named ' , changesName)]. ((changes next: 200) includesSubString: String crlf) ifTrue: [self inform: 'The changes file named ' , changesName , ' has been injured by an unpacking utility. Crs were changed to CrLfs. Please set the preferences in your decompressing program to "do not convert text files" and unpack the system again.']]. SourceFiles _ Array with: sources with: changes! ! !FileDirectory class methodsFor: 'system start up' stamp: 'tpr 2/17/2004 19:59'! openSources: fullSourcesName forImage: imageName "We first do a check to see if a compressed version ofthe sources file is present. Open the .sources file read-only after searching in: a) the directory where the VM lives b) the directory where the image came from c) the DefaultDirectory (which is likely the same as b unless the SecurityManager has changed it). " | sources fd sourcesName | (fullSourcesName endsWith: 'sources') ifTrue: ["Look first for a sources file in compressed format." sources _ self openSources: (fullSourcesName allButLast: 7) , 'stc' forImage: imageName. sources ifNotNil: [^ CompressedSourceStream on: sources]]. sourcesName _ FileDirectory localNameFor: fullSourcesName. "look for the sources file or an alias to it in the VM's directory" fd _ FileDirectory on: SmalltalkImage current vmPath. (fd fileExists: sourcesName) ifTrue: [sources _ fd readOnlyFileNamed: sourcesName]. sources ifNotNil: [^ sources]. "look for the sources file or an alias to it in the image directory" fd _ FileDirectory on: (FileDirectory dirPathFor: imageName). (fd fileExists: sourcesName) ifTrue: [sources _ fd readOnlyFileNamed: sourcesName]. sources ifNotNil: [^ sources]. "look for the sources in the current directory" fd _ DefaultDirectory. (fd fileExists: sourcesName) ifTrue: [sources _ fd readOnlyFileNamed: sourcesName]. "sources may still be nil here" ^sources ! ! !FileDirectory class methodsFor: 'system start up' stamp: 'tpr 10/13/2003 10:49'! setDefaultDirectory: directoryName "Initialize the default directory to the directory supplied. This method is called when the image starts up, very early in the #startUp sequence." DefaultDirectory _ self on: directoryName.! ! !FileDirectory class methodsFor: 'system start up' stamp: 'tpr 10/13/2003 10:39'! setDefaultDirectoryClass "Initialize the default directory class to suit this platform. This method is called when the image starts up - it needs to be right at the front of the list of the startup sequence" DirectoryClass _ self activeDirectoryClass ! ! !FileDirectory class methodsFor: 'system start up' stamp: 'sd 11/16/2003 13:13'! shutDown SmalltalkImage current closeSourceFiles. ! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 08:17'! dot "Return a one-character string containing the filename extension delimiter for this platform (i.e., the local equivalent of 'dot')" ^ self extensionDelimiter asString ! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 06:57'! extensionDelimiter "Return the character used to delimit filename extensions on this platform. Most platforms use the period (.) character." ^ $. ! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'ar 5/1/1999 01:48'! isCaseSensitive "Return true if file names are treated case sensitive" ^true! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'jm 5/8/1998 20:45'! maxFileNameLength ^ 31 ! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'TPR 5/12/1998 22:49'! pathNameDelimiter "return the active directory class's directory seperator character" ^ DirectoryClass pathNameDelimiter! ! !FileDirectory class methodsFor: 'platform specific' stamp: 'ar 4/18/1999 18:18'! slash ^ self pathNameDelimiter asString! ! !FileDirectory class methodsFor: 'private' stamp: 'TPR 5/10/1998 21:47'! activeDirectoryClass "Return the concrete FileDirectory subclass for the platform on which we are currently running." FileDirectory allSubclasses do: [:class | class isActiveDirectoryClass ifTrue: [^ class]]. "no responding subclass; use FileDirectory" ^ FileDirectory ! ! !FileDirectory class methodsFor: 'private' stamp: 'TPR 5/10/1998 21:40'! isActiveDirectoryClass "Does this class claim to be that properly active subclass of FileDirectory for this platform? Default test is whether the primPathNameDelimiter matches the one for this class. Other tests are possible" ^self pathNameDelimiter = self primPathNameDelimiter ! ! !FileDirectory class methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primPathNameDelimiter "Return the path delimiter for the underlying platform's file system." <primitive: 'primitiveDirectoryDelimitor' module: 'FilePlugin'> self primitiveFailed ! ! FileStreamException subclass: #FileDoesNotExistException instanceVariableNames: 'readOnly' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !FileDoesNotExistException methodsFor: 'accessing' stamp: 'mir 7/25/2000 16:41'! readOnly ^readOnly == true! ! !FileDoesNotExistException methodsFor: 'accessing' stamp: 'mir 7/25/2000 16:40'! readOnly: aBoolean readOnly _ aBoolean! ! !FileDoesNotExistException methodsFor: 'exceptionDescription' stamp: 'mir 7/25/2000 18:22'! defaultAction "The default action taken if the exception is signaled." ^self readOnly ifTrue: [StandardFileStream readOnlyFileDoesNotExistUserHandling: self fileName] ifFalse: [StandardFileStream fileDoesNotExistUserHandling: self fileName] ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileDoesNotExistException class instanceVariableNames: ''! !FileDoesNotExistException class methodsFor: 'examples' stamp: 'mir 2/29/2000 11:44'! example "FileDoesNotExistException example" | result | result _ [(StandardFileStream readOnlyFileNamed: 'error42.log') contentsOfEntireFile] on: FileDoesNotExistException do: [:ex | 'No error log']. Transcript show: result; cr! ! FileStreamException subclass: #FileExistsException instanceVariableNames: 'fileClass' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !FileExistsException methodsFor: 'accessing' stamp: 'LC 10/24/2001 21:49'! fileClass ^ fileClass ifNil: [StandardFileStream]! ! !FileExistsException methodsFor: 'accessing' stamp: 'LC 10/24/2001 21:42'! fileClass: aClass fileClass _ aClass! ! !FileExistsException methodsFor: 'exceptionDescription' stamp: 'LC 10/24/2001 21:50'! defaultAction "The default action taken if the exception is signaled." ^ self fileClass fileExistsUserHandling: self fileName ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileExistsException class instanceVariableNames: ''! !FileExistsException class methodsFor: 'exceptionInstantiator' stamp: 'LC 10/24/2001 21:50'! fileName: aFileName fileClass: aClass ^ self new fileName: aFileName; fileClass: aClass! ! StringHolder subclass: #FileList instanceVariableNames: 'fileName directory volList volListIndex list listIndex pattern sortMode brevityState' classVariableNames: 'FileReaderRegistry RecentDirs' poolDictionaries: '' category: 'Tools-FileList'! !FileList commentStamp: 'nk 11/26/2002 11:52' prior: 0! I am model that can be used to navigate the host file system. By omitting the volume list, file list, and template panes from the view, I can also be used as the model for an editor on an individual file. The FileList now provides a registration mechanism to which any tools the filelist uses ***MUST*** register. This way it is possible to dynamically load or unload a new tool and have the FileList automatically updated. This change supports a decomposition of Squeak and removes a problem with dead reference to classes after a major shrink. Tools should implement the following methods (look for implementors in the image): #fileReaderServicesForFile:suffix: (appropriate services for given file, takes a file name and a lowercased suffix) #services (all provided services, to be displayed in full list) These methods both return a collection of SimpleServiceEntry instances. These contain a class, a menu label and a method selector having one argument. They may also provide separate button labels and description. The argument to the specified method will be a string representing the full name of a file when one is selected or the file list itself when there is no selected file. Tools must register with the FileList calling the class method #registerFileReader: when they load. They also must call #unregisterFileReader: when they unload. There is a testSuite called FileListTest that presents some examples. Stef (I do not like really this distinction passing always a file list could be better) Old Comments: FileLists can now see FTP servers anywhere on the net. In the volume list menu: fill in server info... Gives you a form to register a new ftp server you want to use. open server... Choose a server to connect to. local disk Go back to looking at your local volume. Still undone (you can contribute code): [ ] Using a Proxy server to get out through a firewall. What is the convention for proxy servers with FTP? [ ] Fill in the date and size info in the list of remote files. Allow sorting by it. New smarts needed in (ServerDirectory fileNameFormattedFrom:sizePad:sortMode:). [ ] Currently the FileList has no way to delete a directory. Since you can't select a directory without going into it, it would have to be deleting the current directory. Which would usually be empty.! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/19/2003 10:08'! acceptDroppingMorph: aTransferMorph event: evt inMorph: dest | oldName oldEntry destDirectory newName newEntry baseName response | destDirectory _ self dropDestinationDirectory: dest event: evt. oldName _ aTransferMorph passenger. baseName _ FileDirectory localNameFor: oldName. newName _ destDirectory fullNameFor: baseName. newName = oldName ifTrue: [ "Transcript nextPutAll: 'same as old name'; cr." ^ true ]. oldEntry _ FileDirectory directoryEntryFor: oldName. newEntry _ FileDirectory directoryEntryFor: newName. newEntry ifNotNil: [ | msg | msg _ String streamContents: [ :s | s nextPutAll: 'destination file '; nextPutAll: newName; nextPutAll: ' exists already,'; cr; nextPutAll: 'and is '; nextPutAll: (oldEntry modificationTime < newEntry modificationTime ifTrue: [ 'newer' ] ifFalse: [ 'not newer' ]); nextPutAll: ' than source file '; nextPutAll: oldName; nextPut: $.; cr; nextPutAll: 'Overwrite file '; nextPutAll: newName; nextPut: $? ]. response _ self confirm: msg. response ifFalse: [ ^false ]. ]. aTransferMorph shouldCopy ifTrue: [ self primitiveCopyFileNamed: oldName to: newName ] ifFalse: [ directory rename: oldName toBe: newName ]. self updateFileList; fileListIndex: 0. aTransferMorph source model ~= self ifTrue: [ aTransferMorph source model updateFileList; fileListIndex: 0 ]. "Transcript nextPutAll: 'copied'; cr." ^true! ! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/14/2003 12:58'! dragPassengerFor: item inMorph: dragSource ^self directory fullNameFor: ((self fileNameFromFormattedItem: item contents copy) copyReplaceAll: self folderString with: ''). ! ! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/14/2003 11:16'! dragTransferTypeForMorph: aMorph ^#file! ! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/15/2003 13:07'! dropDestinationDirectory: dest event: evt "Answer a FileDirectory representing the drop destination in the volume list morph dest" | index dir delim path | index _ volList indexOf: (dest itemFromPoint: evt position) contents. index = 1 ifTrue: [dir _ FileDirectory on: ''] ifFalse: [delim _ directory pathNameDelimiter. path _ String streamContents: [:str | 2 to: index do: [:d | str nextPutAll: (volList at: d) withBlanksTrimmed. d < index ifTrue: [str nextPut: delim]]. nil]. dir _ directory on: path]. ^ dir! ! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/15/2003 21:58'! isDirectoryList: aMorph ^aMorph getListSelector == #volumeList! ! !FileList methodsFor: 'drag''n''drop' stamp: 'nk 6/12/2004 16:17'! primitiveCopyFileNamed: srcName to: dstName "Copied from VMMaker code. This really ought to be a facility in file system. The major annoyance here is that file types and permissions are not handled by current Squeak code. NOTE that this will clobber the destination file!!" | buffer src dst | <primitive: 'primitiveFileCopyNamedTo' module:'FileCopyPlugin'> "primitiveExternalCall" "If the plugin doesn't do it, go the slow way and lose the filetype info" "This method may signal FileDoesNotExistException if either the source or dest files cannnot be opened; possibly permissions or bad name problems" [[src _ FileStream readOnlyFileNamed: srcName] on: FileDoesNotExistException do: [^ self error: ('could not open file ', srcName)]. [dst _ FileStream forceNewFileNamed: dstName] on: FileDoesNotExistException do: [^ self error: ('could not open file ', dstName)]. buffer _ String new: 50000. [src atEnd] whileFalse: [dst nextPutAll: (src nextInto: buffer)]] ensure: [src ifNotNil: [src close]. dst ifNotNil: [dst close]]! ! !FileList methodsFor: 'file list'! fileList "Answer the list of files in the current volume." ^ list! ! !FileList methodsFor: 'file list'! fileListIndex "Answer the index of the currently selected file." ^ listIndex! ! !FileList methodsFor: 'file list' stamp: 'BG 10/29/2003 10:05'! fileListIndex: anInteger "Select the file name having the given index, and display its contents." | item name | self okToChange ifFalse: [^ self]. listIndex := anInteger. listIndex = 0 ifTrue: [fileName := nil] ifFalse: [item := self fileNameFromFormattedItem: (list at: anInteger). (item endsWith: self folderString) ifTrue: ["remove [...] folder string and open the folder" name := item copyFrom: 1 to: item size - self folderString size. listIndex := 0. brevityState := #FileList. self addPath: name. name first = $^ ifTrue: [self halt. "self directory: (ServerDirectory serverNamed: name allButFirst)"] ifFalse: [volListIndex = 1 ifTrue: [name _ name, directory slash]. self directory: (directory directoryNamed: name)]] ifFalse: [fileName := item]]. "open the file selected" brevityState := #needToGetBrief. self changed: #fileListIndex. self changed: #contents. self updateButtonRow! ! !FileList methodsFor: 'file list' stamp: 'sd 2/14/2002 16:58'! fileName ^ fileName! ! !FileList methodsFor: 'file list' stamp: 'nk 4/29/2004 10:34'! readOnlyStream "Answer a read-only stream on the selected file. For the various stream-reading services." ^self directory ifNotNilDo: [ :dir | dir readOnlyFileNamed: self fileName ]! ! !FileList methodsFor: 'file list menu' stamp: 'RAA 2/2/2002 08:18'! dirAndFileName ^{directory. fileName}! ! !FileList methodsFor: 'file list menu' stamp: 'dgd 9/19/2003 11:20'! fileContentsMenu: aMenu shifted: shifted "Construct aMenu to have items appropriate for the file browser's code pane, given the shift state provided" | shiftMenu services maybeLine extraLines | shifted ifTrue: [shiftMenu _ ParagraphEditor shiftedYellowButtonMenu. ^ aMenu labels: shiftMenu labelString lines: shiftMenu lineArray selections: shiftMenu selections]. fileName ifNotNil: [services _ OrderedCollection new. (#(briefHex briefFile needToGetBriefHex needToGetBrief) includes: brevityState) ifTrue: [services add: self serviceGet]. (#(fullHex briefHex needToGetFullHex needToGetBriefHex) includes: brevityState) ifFalse: [services add: self serviceGetHex]. maybeLine _ services size. (#('st' 'cs') includes: self suffixOfSelectedFile) ifTrue: [services addAll: (self servicesFromSelectorSpecs: #(fileIntoNewChangeSet: fileIn: browseChangesFile: browseFile:))]. extraLines _ OrderedCollection new. maybeLine > 0 ifTrue: [extraLines add: maybeLine]. services size > maybeLine ifTrue: [extraLines add: services size]. aMenu addServices: services for: self fullName extraLines: extraLines]. aMenu addList: { {'find...(f)' translated. #find}. {'find again (g)' translated. #findAgain}. {'set search string (h)' translated. #setSearchString}. #-. {'do again (j)' translated. #again}. {'undo (z)' translated. #undo}. #-. {'copy (c)' translated. #copySelection}. {'cut (x)' translated. #cut}. {'paste (v)' translated. #paste}. {'paste...' translated. #pasteRecent}. #-. {'do it (d)' translated. #doIt}. {'print it (p)' translated. #printIt}. {'inspect it (i)' translated. #inspectIt}. {'fileIn selection (G)' translated. #fileItIn}. #-. {'accept (s)' translated. #accept}. {'cancel (l)' translated. #cancel}. #-. {'more...' translated. #shiftedYellowButtonActivity}}. ^ aMenu ! ! !FileList methodsFor: 'file list menu' stamp: 'LEG 10/24/2001 15:37'! fileListMenu: aMenu fileName ifNil: [^ self noFileSelectedMenu: aMenu] ifNotNil: [^ self fileSelectedMenu: aMenu]. ! ! !FileList methodsFor: 'file list menu' stamp: 'nk 11/16/2002 13:00'! fileSelectedMenu: aMenu | firstItems secondItems thirdItems n1 n2 n3 services | firstItems _ self itemsForFile: self fullName. secondItems _ self itemsForAnyFile. thirdItems _ self itemsForNoFile. n1 _ firstItems size. n2 _ n1 + secondItems size. n3 _ n2 + thirdItems size. services _ firstItems, secondItems, thirdItems, self serviceAllFileOptions. services do: [ :svc | svc addDependent: self ]. ^ aMenu addServices2: services for: self extraLines: (Array with: n1 with: n2 with: n3) ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 9/3/2008 11:18'! fullFileListMenu: aMenu shifted: aBoolean "Fill the menu with all possible items for the file list pane, regardless of selection." | services servicesPlus extraLines linePointer | aMenu title: 'all possible file operations'. servicesPlus := self servicesFromSelectorSpecs: #( fromFileName: openFromFile: - openOn: fileIntoNewChangeSet: fileIn: browseChangesFile: browseRecentLogOnPath: - viewContents: saveContents: openOn: - removeLineFeeds: ). extraLines _ OrderedCollection new. linePointer _ 1. services _ OrderedCollection new. servicesPlus doWithIndex: [:svc :ind | svc == #- ifTrue: [extraLines add: linePointer - 1] ifFalse: [services add: svc. linePointer _ linePointer + 1]]. aMenu addServices: services for: self fullName extraLines: extraLines! ! !FileList methodsFor: 'file list menu' stamp: 'sw 11/8/2003 13:32'! itemsForAnyFile "Answer a list of universal services that could apply to any file" | services | services := OrderedCollection new: 4. services add: self serviceCopyName. services add: self serviceRenameFile. services add: self serviceDeleteFile. services add: self serviceViewContentsInWorkspace. ^ services! ! !FileList methodsFor: 'file list menu' stamp: 'nk 12/7/2002 12:56'! itemsForFile: fullName "Answer a list of services appropriate for a file of the given full name" | suffix | suffix _ self class suffixOf: fullName. ^ (self class itemsForFile: fullName) , (self myServicesForFile: fullName suffix: suffix)! ! !FileList methodsFor: 'file list menu' stamp: 'sd 1/31/2002 12:08'! itemsForNoFile | services | services := OrderedCollection new: 6. services add: self serviceSortByName. services add: self serviceSortBySize. services add: (self serviceSortByDate useLineAfter: true). (self isFileSelected not and: [self class isReaderNamedRegistered: #FileContentsBrowser]) ifTrue:[ services add: (self serviceBrowseCodeFiles useLineAfter: true)]. services add: self serviceAddNewFile. services add: self serviceAddNewDirectory. ^ services ! ! !FileList methodsFor: 'file list menu' stamp: 'BG 11/2/2003 21:04'! myServicesForFile: fullName suffix: suffix ^(FileStream isSourceFileSuffix: suffix) ifTrue: [ #() ] ifFalse: [ #() ]! ! !FileList methodsFor: 'file list menu' stamp: 'SD 11/8/2001 20:34'! noFileSelectedMenu: aMenu ^ aMenu addServices: self itemsForNoFile for: self extraLines: #() ! ! !FileList methodsFor: 'file list menu' stamp: 'sw 2/27/2001 13:52'! offerAllFileOptions "Put up a menu offering all possible file options, whatever the suffix of the current selection may be. Specially useful if you're wanting to keep the menu up" self offerMenuFrom: #fullFileListMenu:shifted: shifted: true! ! !FileList methodsFor: 'file list menu' stamp: 'nk 12/7/2002 12:57'! suffixOfSelectedFile "Answer the file extension of the receiver's selected file" ^ self class suffixOf: self fullName.! ! !FileList methodsFor: 'file menu action' stamp: 'dgd 12/27/2003 12:18'! addNew: aString byEvaluating: aBlock "A parameterization of earlier versions of #addNewDirectory and #addNewFile. Fixes the bug in each that pushing the cancel button in the FillInTheBlank dialog gave a walkback." | response newName index ending | self okToChange ifFalse: [^ self]. (response := FillInTheBlank request: ('New {1} Name?' translated format: {aString translated}) initialAnswer: ('{1}Name' translated format: {aString translated})) isEmpty ifTrue: [^ self]. newName := response asFileName. Cursor wait showWhile: [ aBlock value: newName]. self updateFileList. index := list indexOf: newName. index = 0 ifTrue: [ending := ') ',newName. index := list findFirst: [:line | line endsWith: ending]]. self fileListIndex: index. ! ! !FileList methodsFor: 'file menu action' stamp: 'sge 11/28/1999 09:04'! addNewDirectory self addNew: 'Directory' byEvaluating: [:newName | directory createDirectory: newName] ! ! !FileList methodsFor: 'file menu action' stamp: 'sge 11/28/1999 09:04'! addNewFile self addNew: 'File' byEvaluating: [:newName | (directory newFileNamed: newName) close] ! ! !FileList methodsFor: 'file menu action' stamp: 'dgd 9/21/2003 17:37'! deleteFile "Delete the currently selected file" listIndex = 0 ifTrue: [^ self]. (self confirm: ('Really delete {1}?' translated format:{fileName})) ifFalse: [^ self]. directory deleteFileNamed: fileName. self updateFileList. brevityState _ #FileList. self get! ! !FileList methodsFor: 'file menu action' stamp: 'jm 5/3/1998 18:03'! get "Get contents of file again, it may have changed. Do this by making the cancel string be the contents, and doing a cancel." Cursor read showWhile: [ self okToChange ifFalse: [^ nil]. brevityState == #briefHex ifTrue: [brevityState _ #needToGetFullHex] ifFalse: [brevityState _ #needToGetFull]. self changed: #contents]. ! ! !FileList methodsFor: 'file menu action' stamp: 'jm 5/3/1998 18:04'! getHex "Get contents of file again, and display in Hex. Do this by making the cancel string be the contents, and doing a cancel." Cursor read showWhile: [ brevityState _ #needToGetBriefHex. self changed: #contents]. ! ! !FileList methodsFor: 'file menu action' stamp: 'dgd 12/27/2003 12:20'! renameFile "Rename the currently selected file" | newName response | listIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. (response _ FillInTheBlank request: 'NewFileName?' translated initialAnswer: fileName) isEmpty ifTrue: [^ self]. newName _ response asFileName. newName = fileName ifTrue: [^ self]. directory rename: fileName toBe: newName. self updateFileList. listIndex _ list findFirst: [:item | (self fileNameFromFormattedItem: item) = newName]. listIndex > 0 ifTrue: [fileName _ newName]. self changed: #fileListIndex. ! ! !FileList methodsFor: 'file menu action' stamp: 'di 4/15/98 12:36'! sortByDate self resort: #date! ! !FileList methodsFor: 'file menu action' stamp: 'di 4/15/98 12:37'! sortByName self resort: #name! ! !FileList methodsFor: 'file menu action' stamp: 'di 4/15/98 12:36'! sortBySize self resort: #size! ! !FileList methodsFor: 'file menu action' stamp: 'sd 2/1/2002 20:02'! spawn: code "Open a simple Edit window" listIndex = 0 ifTrue: [^ self]. self class openEditorOn: (directory readOnlyFileNamed: fileName) "read only just for initial look" editString: code! ! !FileList methodsFor: 'initialization' stamp: 'sw 11/30/2002 00:05'! buttonSelectorsToSuppress "Answer a list of action selectors whose corresponding services we would prefer *not* to have appear in the filelist's button pane; this can be hand-jimmied to suit personal taste." ^ #(removeLineFeeds: addFileToNewZip: compressFile: putUpdate:)! ! !FileList methodsFor: 'initialization' stamp: 'BG 12/13/2002 15:32'! directory: dir "Set the path of the volume to be displayed." self okToChange ifFalse: [^ self]. self modelSleep. directory _ dir. self modelWakeUp. sortMode == nil ifTrue: [sortMode _ #date]. volList _ ((Array with: '[]'), directory pathParts) "Nesting suggestion from RvL" withIndexCollect: [:each :i | ( String new: i-1 withAll: $ ), each]. volListIndex := volList size. self changed: #relabel. self changed: #volumeList. self pattern: pattern! ! !FileList methodsFor: 'initialization' stamp: 'sw 2/26/2002 00:37'! dynamicButtonServices "Answer services for buttons that may come and go in the button pane, depending on selection" ^ fileName isEmptyOrNil ifTrue: [#()] ifFalse: [ | toReject | toReject _ self buttonSelectorsToSuppress. (self itemsForFile: self fullName) reject: [:svc | toReject includes: svc selector]]! ! !FileList methodsFor: 'initialization' stamp: 'tk 5/18/1998 17:22'! labelString ^ directory pathName contractTo: 50! ! !FileList methodsFor: 'initialization' stamp: 'tk 12/17/1999 18:00'! modelSleep "User has exited or collapsed the window -- close any remote connection." directory ifNotNil: [directory sleep]! ! !FileList methodsFor: 'initialization' stamp: 'BG 10/29/2003 10:06'! modelWakeUp "User has entered or expanded the window -- reopen any remote connection." " (directory isKindOf: ServerDirectory) ifTrue: [directory wakeUp] " "It would be good to implement a null method wakeUp on the root of directory"! ! !FileList methodsFor: 'initialization' stamp: 'sbw 12/30/1999 15:53'! optionalButtonHeight ^ 15! ! !FileList methodsFor: 'initialization' stamp: 'sw 2/17/2002 00:07'! optionalButtonSpecs "Answer a list of services underlying the optional buttons in their initial inception." ^ {self serviceSortByName. self serviceSortByDate. self serviceSortBySize}! ! !FileList methodsFor: 'initialization' stamp: 'sw 2/17/2002 05:39'! optionalButtonView "Answer a view of optional buttons" | aView bHeight windowWidth offset previousView aButtonView wid services sel allServices | aView _ View new model: self. bHeight _ self optionalButtonHeight. windowWidth _ 120. aView window: (0 @ 0 extent: windowWidth @ bHeight). offset _ 0. allServices _ self universalButtonServices. services _ allServices copyFrom: 1 to: (allServices size min: 5). previousView _ nil. services do: [:service | sel _ service selector. aButtonView _ sel asString numArgs = 0 ifTrue: [PluggableButtonView on: service provider getState: (service extraSelector == #none ifFalse: [service extraSelector]) action: sel] ifFalse: [PluggableButtonView on: service provider getState: (service extraSelector == #none ifFalse: [service extraSelector]) action: sel getArguments: #fullName from: self]. service selector = services last selector ifTrue: [wid _ windowWidth - offset] ifFalse: [aButtonView borderWidthLeft: 0 right: 1 top: 0 bottom: 0. wid _ windowWidth // services size - 2]. aButtonView label: service buttonLabel asParagraph; window: (offset @ 0 extent: wid @ bHeight). offset _ offset + wid. service selector = services first selector ifTrue: [aView addSubView: aButtonView] ifFalse: [aView addSubView: aButtonView toRightOf: previousView]. previousView _ aButtonView]. ^ aView! ! !FileList methodsFor: 'initialization' stamp: 'di 5/11/1999 22:25'! release self modelSleep! ! !FileList methodsFor: 'initialization' stamp: 'tk 5/21/1998 12:28'! setFileStream: aStream "Used to initialize a spawned file editor. Sets directory too." self directory: aStream directory. fileName _ aStream localName. pattern _ '*'. listIndex _ 1. "pretend a file is selected" aStream close. brevityState _ #needToGetBrief. self changed: #contents. ! ! !FileList methodsFor: 'initialization' stamp: 'sw 2/17/2002 05:38'! universalButtonServices "Answer a list of services underlying the universal buttons in their initial inception. For the moment, only the sorting buttons are shown." ^ {self serviceSortByName. self serviceSortByDate. self serviceSortBySize}! ! !FileList methodsFor: 'initialization' stamp: 'BG 10/28/2003 20:45'! updateButtonRow "Dynamically update the contents of the button row, if any." ! ! !FileList methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'! copyName listIndex = 0 ifTrue: [^ self]. Clipboard clipboardText: self fullName asText. ! ! !FileList methodsFor: 'own services' stamp: 'sw 2/15/2002 19:07'! serviceAddNewDirectory "Answer a service entry characterizing the 'add new directory' command" ^ SimpleServiceEntry provider: self label: 'add new directory' selector: #addNewDirectory description: 'adds a new, empty directory (folder)' ! ! !FileList methodsFor: 'own services' stamp: 'sw 2/11/2002 23:36'! serviceAddNewFile "Answer a service entry characterizing the 'add new file' command" ^ SimpleServiceEntry provider: self label: 'add new file' selector: #addNewFile description: 'create a new,. empty file, and add it to the current directory.'! ! !FileList methodsFor: 'own services' stamp: 'sd 1/31/2002 22:12'! serviceAllFileOptions ^ {SimpleServiceEntry provider: self label: 'more...' selector: #offerAllFileOptions description: 'show all the options available'}! ! !FileList methodsFor: 'own services' stamp: 'sw 2/17/2002 01:36'! serviceBroadcastUpdate "Answer a service for broadcasting a file as an update" ^ SimpleServiceEntry provider: self label: 'broadcast as update' selector: #putUpdate: description: 'broadcast file as update' buttonLabel: 'broadcast'! ! !FileList methodsFor: 'own services' stamp: 'sd 1/31/2002 22:24'! serviceBrowseCodeFiles self flag: #stef. "Here we are breaking the registration mechanism by a direct reference to the fileContentsBrowser. The problem is that service is waiting for a filename and here this specific vicous service is used when no file is selected. I think that we should change that" ^ SimpleServiceEntry provider: FileContentsBrowser label: 'browse code files' selector: #selectAndBrowseFile:! ! !FileList methodsFor: 'own services' stamp: 'sd 1/31/2002 22:16'! serviceCopyName ^ (SimpleServiceEntry provider: self label: 'copy name to clipboard' selector: #copyName description:'copy name to clipboard' )! ! !FileList methodsFor: 'own services' stamp: 'sd 1/31/2002 21:17'! serviceDeleteFile ^ (SimpleServiceEntry provider: self label: 'delete' selector: #deleteFile) description: 'delete the seleted item'! ! !FileList methodsFor: 'own services' stamp: 'sw 2/16/2002 01:39'! serviceGet "Answer a service for getting the entire file" ^ (SimpleServiceEntry provider: self label: 'get entire file' selector: #get description: 'if the file has only been partially read in, because it is very large, read the entire file in at this time.')! ! !FileList methodsFor: 'own services' stamp: 'sd 2/1/2002 20:50'! serviceGetHex ^ (SimpleServiceEntry provider: self label: 'view as hex' selector: #getHex description: 'view as hex') ! ! !FileList methodsFor: 'own services' stamp: 'sd 1/31/2002 22:15'! serviceRenameFile ^ (SimpleServiceEntry provider: self label: 'rename' selector: #renameFile description: 'rename file')! ! !FileList methodsFor: 'own services' stamp: 'sw 2/16/2002 01:39'! serviceSortByDate "Answer a service for sorting by date" ^ (SimpleServiceEntry new provider: self label: 'by date' selector: #sortByDate description: 'sort entries by date') extraSelector: #sortingByDate; buttonLabel: 'date'! ! !FileList methodsFor: 'own services' stamp: 'sw 2/16/2002 01:39'! serviceSortByName "Answer a service for soring by name" ^ (SimpleServiceEntry new provider: self label: 'by name' selector: #sortByName description: 'sort entries by name') extraSelector: #sortingByName; buttonLabel: 'name'! ! !FileList methodsFor: 'own services' stamp: 'sw 2/16/2002 01:40'! serviceSortBySize "Answer a service for sorting by size" ^ (SimpleServiceEntry provider: self label: 'by size' selector: #sortBySize description: 'sort entries by size') extraSelector: #sortingBySize; buttonLabel: 'size'! ! !FileList methodsFor: 'own services' stamp: 'sw 11/8/2003 13:34'! serviceViewContentsInWorkspace "Answer a service for viewing the contents of a file in a workspace" ^ (SimpleServiceEntry provider: self label: 'workspace with contents' selector: #viewContentsInWorkspace) description: 'open a new Workspace whose contents are set to the contents of this file'! ! !FileList methodsFor: 'own services' stamp: 'sw 2/15/2002 20:19'! servicesFromSelectorSpecs: symbolArray "Answer an array of services represented by the incoming symbols, eliminating any that do not have a currently-registered service. Pass the symbol #- along unchanged to serve as a separator between services" "FileList new servicesFromSelectorSpecs: #(fileIn: fileIntoNewChangeSet: browseChangesFile:)" | res services col | col := OrderedCollection new. services := self class allRegisteredServices, (self myServicesForFile: #dummy suffix: '*'). symbolArray do: [:sel | sel == #- ifTrue: [col add: sel] ifFalse: [res := services detect: [:each | each selector = sel] ifNone: [nil]. res notNil ifTrue: [col add: res]]]. ^ col! ! !FileList methodsFor: 'own services' stamp: 'sw 11/8/2003 13:39'! viewContentsInWorkspace "View the contents of my selected file in a new workspace" | aString aFileStream aName | aString _ (aFileStream _ directory readOnlyFileNamed: self fullName) contentsOfEntireFile. aName _ aFileStream localName. aFileStream close. (Workspace new contents: aString) openLabel: 'Workspace from ', aName! ! !FileList methodsFor: 'to be transformed in registration' stamp: 'sw 11/30/2002 15:38'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If it's one of the three sort-by items, handle it specially. If I can respond myself, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." ^ (#(sortByDate sortBySize sortByName) includes: selector) ifTrue: [self resort: selector] ifFalse: [(#(get getHex copyName openImageInWindow importImage renameFile deleteFile addNewFile) includes: selector) ifTrue: [self perform: selector] ifFalse: [super perform: selector orSendTo: otherTarget]]! ! !FileList methodsFor: 'to be transformed in registration' stamp: 'BG 10/29/2003 10:07'! removeServer | choice names | self flag: #ViolateNonReferenceToOtherClasses. names := #(). "ServerDirectory serverNames asSortedArray." choice := (SelectionMenu labelList: names selections: names) startUp. choice == nil ifTrue: [^ self]. "ServerDirectory removeServerNamed: choice"! ! !FileList methodsFor: 'to be transformed in registration' stamp: 'BG 10/29/2003 10:04'! volumeMenu: aMenu ^ aMenu labels: 'recent... remove server... delete directory...' lines: # (1 2) selections: #(recentDirs removeServer deleteDirectory) ! ! !FileList methodsFor: 'updating' stamp: 'sw 11/30/2002 16:49'! update: aParameter "Receive a change notice from an object of whom the receiver is a dependent" (aParameter == #fileListChanged) ifTrue: [self updateFileList]. super update: aParameter! ! !FileList methodsFor: 'volume list and pattern' stamp: 'tpr 11/28/2003 11:44'! deleteDirectory "Remove the currently selected directory" | localDirName | directory entries size = 0 ifFalse:[^self inform:'Directory must be empty']. localDirName _ directory localName. (self confirm: 'Really delete ' , localDirName , '?') ifFalse: [^ self]. self volumeListIndex: self volumeListIndex-1. directory deleteDirectory: localDirName. self updateFileList.! ! !FileList methodsFor: 'volume list and pattern' stamp: 'SD 11/11/2001 13:59'! directory ^ directory! ! !FileList methodsFor: 'volume list and pattern' stamp: 'ls 7/25/1998 01:15'! fileNameFormattedFrom: entry sizePad: sizePad "entry is a 5-element array of the form: (name creationTime modificationTime dirFlag fileSize)" | sizeStr nameStr dateStr | nameStr _ (entry at: 4) ifTrue: [entry first , self folderString] ifFalse: [entry first]. dateStr _ ((Date fromSeconds: (entry at: 3) ) printFormat: #(3 2 1 $. 1 1 2)) , ' ' , (String streamContents: [:s | (Time fromSeconds: (entry at: 3) \\ 86400) print24: true on: s]). sizeStr _ (entry at: 5) asStringWithCommas. sortMode = #name ifTrue: [^ nameStr , ' (' , dateStr , ' ' , sizeStr , ')']. sortMode = #date ifTrue: [^ '(' , dateStr , ' ' , sizeStr , ') ' , nameStr]. sortMode = #size ifTrue: [^ '(' , ((sizeStr size to: sizePad) collect: [:i | $ ]) , sizeStr , ' ' , dateStr , ') ' , nameStr]. ! ! !FileList methodsFor: 'volume list and pattern' stamp: 'BG 10/29/2003 10:06'! listForPattern: pat "Make the list be those file names which match the pattern." | sizePad newList | newList _ (self entriesMatching: pat) asSortedCollection: self sortBlock. sizePad _ (newList inject: 0 into: [:mx :entry | mx max: (entry at: 5)]) asStringWithCommas size - 1. newList _ newList collect: [ :e | self fileNameFormattedFrom: e sizePad: sizePad ]. volList size = 1 ifTrue: ["Include known servers along with other desktop volumes" ^ newList asArray ", (ServerDirectory serverNames collect: [:n | '^' , n , self folderString])"]. ^ newList asArray! ! !FileList methodsFor: 'volume list and pattern' stamp: 'tk 4/7/98 15:26'! pattern ^ pattern ifNil: ['*'] ! ! !FileList methodsFor: 'volume list and pattern' stamp: 'jm 5/3/1998 19:01'! pattern: textOrStringOrNil textOrStringOrNil ifNil: [pattern _ '*'] ifNotNil: [pattern _ textOrStringOrNil asString]. self updateFileList. ^ true ! ! !FileList methodsFor: 'volume list and pattern' stamp: 'sw 3/6/1999 11:39'! veryDeepFixupWith: deepCopier super veryDeepFixupWith: deepCopier. volListIndex _ 1. self directory: FileDirectory default. self updateFileList! ! !FileList methodsFor: 'volume list and pattern' stamp: 'jm 5/3/1998 18:20'! volumeList "Answer the current list of volumes." ^ volList ! ! !FileList methodsFor: 'volume list and pattern' stamp: 'jm 5/3/1998 18:21'! volumeListIndex "Answer the index of the currently selected volume." ^ volListIndex ! ! !FileList methodsFor: 'volume list and pattern' stamp: 'sw 2/21/2002 02:01'! volumeListIndex: index "Select the volume name having the given index." | delim path | volListIndex := index. index = 1 ifTrue: [self directory: (FileDirectory on: '')] ifFalse: [delim := directory pathNameDelimiter. path := String streamContents: [:strm | 2 to: index do: [:i | strm nextPutAll: (volList at: i) withBlanksTrimmed. i < index ifTrue: [strm nextPut: delim]]]. self directory: (directory on: path)]. brevityState := #FileList. self addPath: path. self changed: #fileList. self changed: #contents. self updateButtonRow! ! !FileList methodsFor: 'private' stamp: 'stp 12/11/1999 20:05'! addPath: aString "Add the given string to the list of recently visited directories." | full | aString ifNil: [^self]. full := String streamContents: [ :strm | 2 to: volList size do: [ :i | strm nextPutAll: (volList at: i) withBlanksTrimmed. strm nextPut: FileDirectory pathNameDelimiter]]. full := full, aString. "Remove and super-directories of aString from the collection." RecentDirs removeAllSuchThat: [ :aDir | ((aDir, '*') match: full)]. "If a sub-directory is in the list, do nothing." (RecentDirs detect: [ :aDir | ((full, '*') match: aDir)] ifNone: [nil]) ifNotNil: [^self]. [RecentDirs size >= 10] whileTrue: [RecentDirs removeFirst]. RecentDirs addLast: full! ! !FileList methodsFor: 'private' stamp: 'di 8/16/1998 09:26'! contents "Answer the contents of the file, reading it first if needed." "Possible brevityState values: FileList, fullFile, briefFile, needToGetFull, needToGetBrief, fullHex, briefHex, needToGetFullHex, needToGetBriefHex" (listIndex = 0) | (brevityState == #FileList) ifTrue: [^ self defaultContents]. "no file selected" brevityState == #fullFile ifTrue: [^ contents]. brevityState == #fullHex ifTrue: [^ contents]. brevityState == #briefFile ifTrue: [^ contents]. brevityState == #briefHex ifTrue: [^ contents]. brevityState == #needToGetFullHex ifTrue: [^ self readContentsHex: false]. brevityState == #needToGetBriefHex ifTrue: [^ self readContentsHex: true]. brevityState == #needToGetFull ifTrue: [^ self readContentsBrief: false]. brevityState == #needToGetBrief ifTrue: [^ self readContentsBrief: true]. "default" self halt: 'unknown state ' , brevityState printString! ! !FileList methodsFor: 'private' stamp: 'dgd 12/27/2003 12:22'! defaultContents contents _ list == nil ifTrue: [String new] ifFalse: [String streamContents: [:s | s nextPutAll: 'NO FILE SELECTED' translated; cr. s nextPutAll: ' -- Folder Summary --' translated; cr. list do: [:item | s nextPutAll: item; cr]]]. brevityState _ #FileList. ^ contents! ! !FileList methodsFor: 'private' stamp: 'sma 11/11/2000 17:00'! entriesMatching: patternString "Answer a list of directory entries which match the patternString. The patternString may consist of multiple patterns separated by ';'. Each pattern can include a '*' or '#' as wildcards - see String>>match:" | entries patterns | entries _ directory entries. patterns _ patternString findTokens: ';'. (patterns anySatisfy: [:each | each = '*']) ifTrue: [^ entries]. ^ entries select: [:entry | entry isDirectory or: [patterns anySatisfy: [:each | each match: entry first]]]! ! !FileList methodsFor: 'private' stamp: 'rhi 9/8/2001 02:17'! fileNameFromFormattedItem: item "Extract fileName and folderString from a formatted fileList item string" | from to | self sortingByName ifTrue: [ from _ item lastIndexOf: $( ifAbsent: [0]. to _ item lastIndexOf: $) ifAbsent: [0]] ifFalse: [ from _ item indexOf: $( ifAbsent: [0]. to _ item indexOf: $) ifAbsent: [0]]. ^ (from * to = 0 ifTrue: [item] ifFalse: [item copyReplaceFrom: from to: to with: '']) withBlanksTrimmed! ! !FileList methodsFor: 'private'! folderString ^ ' [...]'! ! !FileList methodsFor: 'private' stamp: 'sw 1/7/2003 17:08'! fullName "Answer the full name for the currently selected file; answer nil if no file is selected." ^ fileName ifNotNil: [directory ifNil: [FileDirectory default fullNameFor: fileName] ifNotNil: [directory fullNameFor: fileName]] ! ! !FileList methodsFor: 'private' stamp: 'SD 11/14/2001 21:59'! isFileSelected "return if a file is currently selected" ^ fileName isNil not! ! !FileList methodsFor: 'private' stamp: 'BG 11/11/2003 14:21'! listForPatterns: anArray "Make the list be those file names which match the pattern." | sizePad newList | newList _ Set new. anArray do: [ :pat | newList addAll: (self entriesMatching: pat) ]. newList _ (SortedCollection sortBlock: self sortBlock) addAll: newList; yourself. sizePad _ (newList inject: 0 into: [:mx :entry | mx max: (entry at: 5)]) asStringWithCommas size - 1. newList _ newList collect: [ :e | self fileNameFormattedFrom: e sizePad: sizePad ]. volList size = 1 ifTrue: ["Include known servers along with other desktop volumes" "^ newList asArray , (ServerDirectory serverNames collect: [:n | '^' , n , self folderString])"]. ^ newList asArray! ! !FileList methodsFor: 'private' stamp: 'dgd 12/27/2003 12:24'! put: aText "Private - put the supplied text onto the file" | ff type | brevityState == #fullFile ifTrue: [ff _ directory newFileNamed: self fullName. Cursor write showWhile: [ff nextPutAll: aText asString; close]. fileName = ff localName ifTrue: [contents _ aText asString] ifFalse: [self updateFileList]. "user renamed the file" ^ true "accepted"]. listIndex = 0 ifTrue: [self inform: 'No fileName is selected' translated. ^ false "failed"]. type _ 'These'. brevityState = #briefFile ifTrue: [type _ 'Abbreviated']. brevityState = #briefHex ifTrue: [type _ 'Abbreviated']. brevityState = #fullHex ifTrue: [type _ 'Hexadecimal']. brevityState = #FileList ifTrue: [type _ 'Directory']. self inform: ('{1} contents cannot meaningfully be saved at present.' translated format:{type translated}). ^ false "failed" ! ! !FileList methodsFor: 'private' stamp: 'BG 10/29/2003 10:07'! readContentsBrief: brevityFlag "Read the contents of the receiver's selected file, unless it is too long, in which case show just the first 5000 characters. Don't create a file if it doesn't already exist." | f fileSize first5000 | brevityFlag ifTrue: [ "(directory isKindOf: ServerDirectory) ifTrue: [^ self readServerBrief]"]. f _ directory oldFileOrNoneNamed: self fullName. f ifNil: [^ 'For some reason, this file cannot be read']. (brevityFlag not or: [(fileSize _ f size) <= 100000]) ifTrue: [contents _ f contentsOfEntireFile. brevityState _ #fullFile. "don't change till actually read" ^ contents]. "if brevityFlag is true, don't display long files when first selected" first5000 _ f next: 5000. f close. contents _ 'File ''', fileName, ''' is ', fileSize printString, ' bytes long. You may use the ''get'' command to read the entire file. Here are the first 5000 characters... ------------------------------------------ ', first5000 , ' ------------------------------------------ ... end of the first 5000 characters.'. brevityState _ #briefFile. "don't change till actually read" ^ contents. ! ! !FileList methodsFor: 'private' stamp: 'dgd 12/27/2003 12:11'! readContentsHex: brevity "retrieve the contents from the external file unless it is too long. Don't create a file here. Check if exists." | f size data hexData s | f := directory oldFileOrNoneNamed: self fullName. f == nil ifTrue: [^ 'For some reason, this file cannot be read' translated]. ((size := f size)) > 5000 & brevity ifTrue: [data := f next: 10000. f close. brevityState := #briefHex] ifFalse: [data := f contentsOfEntireFile. brevityState := #fullHex]. s := WriteStream on: (String new: data size*4). 0 to: data size-1 by: 16 do: [:loc | s nextPutAll: loc hex; space; nextPut: $(; print: loc; nextPut: $); space; tab. loc+1 to: (loc+16 min: data size) do: [:i | s nextPutAll: (data at: i) hex; space]. s cr]. hexData := s contents. ^ contents := ((size > 5000) & brevity ifTrue: ['File ''{1}'' is {2} bytes long. You may use the ''get'' command to read the entire file. Here are the first 5000 characters... ------------------------------------------ {3} ------------------------------------------ ... end of the first 5000 characters.' translated format: {fileName. size. hexData}] ifFalse: [hexData]). ! ! !FileList methodsFor: 'private' stamp: 'dgd 12/27/2003 12:09'! readServerBrief | lString sizeStr fsize ff first5000 parts | "If file on server is known to be long, just read the beginning. Cheat badly by reading the fileList string." listIndex = 0 ifTrue: [^ self]. "Get size from file list entry" lString := list at: listIndex. parts := lString findTokens: '()'. sortMode = #name ifTrue: [sizeStr := (parts second findTokens: ' ') third]. sortMode = #date ifTrue: [sizeStr := (parts first findTokens: ' ') third]. sortMode = #size ifTrue: [sizeStr := (parts first findTokens: ' ') first]. fsize := (sizeStr copyWithout: $,) asNumber. fsize <= 50000 ifTrue: [ff := directory oldFileOrNoneNamed: self fullName. ff ifNil: [^ 'For some reason, this file cannot be read' translated]. contents := ff contentsOfEntireFile. brevityState := #fullFile. "don't change till actually read" ^ contents]. "if brevityFlag is true, don't display long files when first selected" first5000 := directory getOnly: 3500 from: fileName. contents := 'File ''{1}'' is {2} bytes long. You may use the ''get'' command to read the entire file. Here are the first 3500 characters... ------------------------------------------ {3} ------------------------------------------ ... end of the first 3500 characters.' translated format: {fileName. sizeStr. first5000}. brevityState := #briefFile. "don't change till actually read" ^ contents. ! ! !FileList methodsFor: 'private' stamp: 'stp 12/11/1999 20:03'! recentDirs "Put up a menu and let the user select from the list of recently visited directories." | dirName | RecentDirs isEmpty ifTrue: [^self]. dirName := (SelectionMenu selections: RecentDirs) startUp. dirName == nil ifTrue: [^self]. self directory: (FileDirectory on: dirName)! ! !FileList methodsFor: 'private' stamp: 'SD 11/8/2001 21:11'! registeredFileReaderClasses "return the list of classes that provide file reader services" ^ self class registeredFileReaderClasses! ! !FileList methodsFor: 'private' stamp: 'sw 11/30/2002 16:34'! resort: newMode "Re-sort the list of files." | name | listIndex > 0 ifTrue: [name _ self fileNameFromFormattedItem: (list at: listIndex)]. sortMode _ newMode. self pattern: pattern. name ifNotNil: [ fileName _ name. listIndex _ list findFirst: [:item | (self fileNameFromFormattedItem: item) = name. ]. self changed: #fileListIndex]. listIndex = 0 ifTrue: [self changed: #contents]. self updateButtonRow ! ! !FileList methodsFor: 'private' stamp: 'sma 11/11/2000 17:04'! sortBlock "Answer block to decide what order to display the directory entries." ^ [ :x :y | (x isDirectory = y isDirectory) ifTrue: [ "sort by user-specified criterion" sortMode = #name ifTrue: [(x name compare: y name) <= 2] ifFalse: [ sortMode = #date ifTrue: [ x modificationTime = y modificationTime ifTrue: [ (x name compare: y name) <= 2 ] ifFalse: [ x modificationTime > y modificationTime ] ] ifFalse: [ "size" x fileSize = y fileSize ifTrue: [ (x name compare: y name) <= 2 ] ifFalse: [ x fileSize > y fileSize ] ] ] ] ifFalse: [ "directories always precede files" x isDirectory ] ]! ! !FileList methodsFor: 'private' stamp: 'sw 1/7/2000 15:58'! sortingByDate ^ sortMode == #date! ! !FileList methodsFor: 'private' stamp: 'sw 1/7/2000 15:57'! sortingByName ^ sortMode == #name! ! !FileList methodsFor: 'private' stamp: 'sw 1/7/2000 15:58'! sortingBySize ^ sortMode == #size! ! !FileList methodsFor: 'private' stamp: 'nk 12/10/2002 07:57'! updateFileList "Update my files list with file names in the current directory that match the pattern. The pattern string may have embedded newlines or semicolons; these separate different patterns." | patterns | patterns _ OrderedCollection new. Cursor wait showWhile: [ (pattern findTokens: (String with: Character cr with: Character lf with: $;)) do: [ :each | (each includes: $*) | (each includes: $#) ifTrue: [ patterns add: each] ifFalse: [each isEmpty ifTrue: [ patterns add: '*'] ifFalse: [ patterns add: '*' , each , '*']]]. list _ self listForPatterns: patterns. listIndex _ 0. volListIndex _ volList size. fileName _ nil. contents _ ''. self changed: #volumeListIndex. self changed: #fileList. self updateButtonRow]! ! !FileList methodsFor: 'obsolete methods' stamp: 'BG 10/28/2003 20:56'! loadCRDictionary self error: 'should not be used keep for temporary documentation'. Smalltalk isMorphic ifFalse: [self beep. ^ self inform: 'Only available within morphic'].! ! !FileList methodsFor: 'obsolete methods' stamp: 'BG 10/28/2003 20:55'! loadCRDisplayProperties self error: 'should not be used keep for temporary documentation'. Smalltalk isMorphic ifFalse: [self beep. ^ self inform: 'Only available within morphic'].! ! !FileList methodsFor: 'obsolete methods' stamp: 'BG 10/28/2003 20:56'! openModelintoAlice "If a Wonderland exists, load this model into it as an actor. If it doesn't, make one first" self error: 'should not be used keep for temporary documentation'. Smalltalk isMorphic ifFalse: [^self error: 'Only works in Morphic - sorry!!']. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileList class instanceVariableNames: ''! !FileList class methodsFor: 'instance creation' stamp: 'sw 9/28/2001 09:21'! defaultButtonPaneHeight "Answer the user's preferred default height for new button panes." ^ Preferences parameterAt: #defaultButtonPaneHeight ifAbsentPut: [25]! ! !FileList class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:56'! open "Open a view of an instance of me on the default directory." "FileList open" | dir aFileList topView volListView templateView fileListView fileContentsView underPane pHeight | dir _ FileDirectory default. aFileList _ self new directory: dir. topView _ StandardSystemView new. topView model: aFileList; label: dir pathName; minimumSize: 200@200. topView borderWidth: 1. volListView _ PluggableListView on: aFileList list: #volumeList selected: #volumeListIndex changeSelected: #volumeListIndex: menu: #volumeMenu:. volListView autoDeselect: false. volListView window: (0@0 extent: 80@45). topView addSubView: volListView. templateView _ PluggableTextView on: aFileList text: #pattern accept: #pattern:. templateView askBeforeDiscardingEdits: false. templateView window: (0@0 extent: 80@15). topView addSubView: templateView below: volListView. aFileList wantsOptionalButtons ifTrue: [underPane _ aFileList optionalButtonView. underPane isNil ifTrue: [pHeight _ 60] ifFalse: [ topView addSubView: underPane toRightOf: volListView. pHeight _ 60 - aFileList optionalButtonHeight]] ifFalse: [underPane _ nil. pHeight _ 60]. fileListView _ PluggableListView on: aFileList list: #fileList selected: #fileListIndex changeSelected: #fileListIndex: menu: #fileListMenu:. fileListView window: (0@0 extent: 120@pHeight). underPane isNil ifTrue: [topView addSubView: fileListView toRightOf: volListView] ifFalse: [topView addSubView: fileListView below: underPane]. fileListView controller terminateDuringSelect: true. "Pane to left may change under scrollbar" fileContentsView _ PluggableTextView on: aFileList text: #contents accept: #put: readSelection: #contentsSelection menu: #fileContentsMenu:shifted:. fileContentsView window: (0@0 extent: 200@140). topView addSubView: fileContentsView below: templateView. topView controller open! ! !FileList class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:41'! openEditorOn: aFileStream editString: editString "Open an editor on the given FileStream." | fileModel topView fileContentsView | fileModel _ FileList new setFileStream: aFileStream. "closes the stream" topView _ StandardSystemView new. topView model: fileModel; label: aFileStream fullName; minimumSize: 180@120. topView borderWidth: 1. fileContentsView _ PluggableTextView on: fileModel text: #contents accept: #put: readSelection: #contentsSelection menu: #fileContentsMenu:shifted:. fileContentsView window: (0@0 extent: 180@120). topView addSubView: fileContentsView. editString ifNotNil: [fileContentsView editString: editString. fileContentsView hasUnacceptedEdits: true]. topView controller open. ! ! !FileList class methodsFor: 'instance creation' stamp: 'SD 11/8/2001 21:20'! openFileDirectly | aResult | (aResult _ StandardFileMenu oldFile) ifNotNil: [self openEditorOn: (aResult directory readOnlyFileNamed: aResult name) editString: nil]! ! !FileList class methodsFor: 'class initialization' stamp: 'dvf 8/23/2003 12:17'! initialize "FileList initialize" RecentDirs := OrderedCollection new. (self systemNavigation allClassesImplementing: #fileReaderServicesForFile:suffix:) do: [:providerMetaclass | self registerFileReader: providerMetaclass soleInstance]! ! !FileList class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:47'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(FileList prototypicalToolWindow 'File List' 'A File List is a tool for browsing folders and files on disks and on ftp types.') forFlapNamed: 'Tools']! ! !FileList class methodsFor: 'class initialization' stamp: 'asm 4/08/2003 12:15'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !FileList class methodsFor: 'file reader registration' stamp: 'sd 2/1/2002 21:30'! allRegisteredServices "self allRegisteredServices" | col | col := OrderedCollection new. self registeredFileReaderClasses do: [:each | col addAll: (each services)]. ^ col! ! !FileList class methodsFor: 'file reader registration' stamp: 'sd 1/31/2002 21:42'! detectService: aBlock ifNone: anotherBlock "self detectService: [:each | each selector = #fileIn:] ifNone: [nil]" ^ self allRegisteredServices detect: aBlock ifNone: anotherBlock! ! !FileList class methodsFor: 'file reader registration' stamp: 'SD 11/11/2001 13:53'! isReaderNamedRegistered: aSymbol "return if a given reader class has been registered. Note that this is on purpose that the argument is a symbol and not a class" ^ (self registeredFileReaderClasses collect: [:each | each name]) includes: aSymbol ! ! !FileList class methodsFor: 'file reader registration' stamp: 'nk 12/7/2002 12:53'! itemsForFile: fullName "Answer a list of services appropriate for a file of the given full name" | services suffix | suffix _ self suffixOf: fullName. services _ OrderedCollection new. self registeredFileReaderClasses do: [:reader | reader ifNotNil: [services addAll: (reader fileReaderServicesForFile: fullName suffix: suffix)]]. ^ services! ! !FileList class methodsFor: 'file reader registration' stamp: 'SD 11/8/2001 21:17'! registerFileReader: aProviderClass "register the given class as providing services for reading files" | registeredReaders | registeredReaders := self registeredFileReaderClasses. (registeredReaders includes: aProviderClass) ifFalse: [ registeredReaders addLast: aProviderClass ]! ! !FileList class methodsFor: 'file reader registration' stamp: 'SD 11/8/2001 21:11'! registeredFileReaderClasses FileReaderRegistry ifNil: [FileReaderRegistry _ OrderedCollection new]. ^ FileReaderRegistry ! ! !FileList class methodsFor: 'file reader registration' stamp: 'nk 12/7/2002 12:52'! suffixOf: aName "Answer the file extension of the given file" ^ aName ifNil: [''] ifNotNil: [(FileDirectory extensionFor: aName) asLowercase]! ! !FileList class methodsFor: 'file reader registration' stamp: 'SD 11/8/2001 21:18'! unregisterFileReader: aProviderClass "unregister the given class as providing services for reading files" self registeredFileReaderClasses remove: aProviderClass ifAbsent: [nil]! ! SimpleServiceEntry subclass: #FileModifyingSimpleServiceEntry instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !FileModifyingSimpleServiceEntry commentStamp: 'nk 11/26/2002 12:03' prior: 0! I represent a service that may change the contents of a directory. Such changes include: * file creation * file deletion * file modification! !FileModifyingSimpleServiceEntry methodsFor: 'as yet unclassified' stamp: 'nk 11/26/2002 12:08'! performServiceFor: anObject | retval | retval _ super performServiceFor: anObject. self changed: #fileListChanged. ^retval "is this used anywhere?"! ! Object subclass: #FilePackage instanceVariableNames: 'fullName sourceSystem classes doIts classOrder' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !FilePackage methodsFor: 'accessing'! classAt: className ^self classes at: className! ! !FilePackage methodsFor: 'accessing'! classes ^classes! ! !FilePackage methodsFor: 'accessing' stamp: 'pnm 8/23/2000 17:10'! fullName: aString fullName := aString! ! !FilePackage methodsFor: 'accessing'! fullPackageName ^fullName! ! !FilePackage methodsFor: 'accessing'! packageInfo ^String streamContents:[:s| s nextPutAll:'Package: '. s nextPutAll: self fullPackageName; cr; cr. sourceSystem isEmpty ifFalse:[ s nextPutAll: sourceSystem; cr; cr]. doIts isEmpty ifFalse:[ s nextPutAll:'Unresolvable doIts:'; cr; cr. doIts do:[:chgRec| s nextPut:$!!; nextPutAll: chgRec string; nextPut: $!!; cr]]].! ! !FilePackage methodsFor: 'accessing' stamp: 'pnm 8/23/2000 17:12'! packageName ^FileDirectory localNameFor: self fullPackageName! ! !FilePackage methodsFor: 'accessing'! removeClass: aPseudoClass (self classes removeKey: aPseudoClass name). classOrder copy do:[:cls| cls name = aPseudoClass name ifTrue:[ classOrder remove: cls]. ].! ! !FilePackage methodsFor: 'accessing' stamp: 'ar 2/5/2004 15:11'! removeDoIts doIts := OrderedCollection new.! ! !FilePackage methodsFor: 'accessing'! renameClass: aPseudoClass to: newName | oldName | oldName := aPseudoClass name. self classes removeKey: oldName. self classes at: newName put: aPseudoClass. aPseudoClass renameTo: newName.! ! !FilePackage methodsFor: 'initialize' stamp: 'ar 2/5/2004 15:14'! fromFileNamed: aName | stream | fullName := aName. stream := FileStream readOnlyFileNamed: aName. [self fileInFrom: stream] ensure:[stream close].! ! !FilePackage methodsFor: 'initialize' stamp: 'pnm 8/23/2000 14:48'! initialize classes := Dictionary new. classOrder := OrderedCollection new. sourceSystem := ''. doIts := OrderedCollection new.! ! !FilePackage methodsFor: 'private'! classDefinition: string with: chgRec | tokens theClass | tokens := Scanner new scanTokens: string. tokens size = 11 ifFalse:[^doIts add: chgRec]. theClass := self getClass: (tokens at: 3). theClass definition: string. classOrder add: theClass.! ! !FilePackage methodsFor: 'private'! getClass: className | pseudoClass | (classes includesKey: className) ifTrue:[ ^classes at: className. ]. pseudoClass := PseudoClass new. pseudoClass name: className. classes at: className put: pseudoClass. ^pseudoClass.! ! !FilePackage methodsFor: 'private'! metaClassDefinition: string with: chgRec | tokens theClass | tokens := Scanner new scanTokens: string. theClass := self getClass: (tokens at: 1). theClass metaClass definition: string. classOrder add: theClass metaClass.! ! !FilePackage methodsFor: 'private'! msgClassComment: string with: chgRec | tokens theClass | tokens := Scanner new scanTokens: string. (tokens size = 3 and:[(tokens at: 3) class == String]) ifTrue:[ theClass := self getClass: tokens first. ^theClass commentString: tokens last]. (tokens size = 4 and:[(tokens at: 3) asString = 'class' and:[(tokens at: 4) class == String]]) ifTrue:[ theClass := self getClass: tokens first. theClass metaClass commentString: tokens last]. ! ! !FilePackage methodsFor: 'private'! possibleSystemSource: chgRec | tokens | sourceSystem isEmpty ifTrue:[ tokens := Scanner new scanTokens: chgRec string. (tokens size = 1 and:[tokens first class == String]) ifTrue:[ sourceSystem := tokens first. ^self]]. doIts add: chgRec.! ! !FilePackage methodsFor: 'private'! removedMethod: string with: chgRec | class tokens | tokens := Scanner new scanTokens: string. (tokens size = 3 and:[(tokens at: 2) == #removeSelector: ]) ifTrue:[ class := self getClass: (tokens at: 1). ^class removeSelector: (tokens at: 3). ]. (tokens size = 4 and:[(tokens at: 2) == #class and:[(tokens at: 3) == #removeSelector:]]) ifTrue:[ class := self getClass: (tokens at: 1). ^class metaClass removeSelector: (tokens at: 4). ]. doIts add: chgRec! ! !FilePackage methodsFor: 'change record types'! classComment: chgRec (self getClass: chgRec methodClassName) classComment: chgRec! ! !FilePackage methodsFor: 'change record types'! doIt: chgRec | string | string := chgRec string. ('*ubclass:*instanceVariableNames:*classVariableNames:*poolDictionaries:*category:*' match: string) ifTrue:[^self classDefinition: string with: chgRec]. ('* class*instanceVariableNames:*' match: string) ifTrue:[^self metaClassDefinition: string with: chgRec]. ('* removeSelector: *' match: string) ifTrue:[^self removedMethod: string with: chgRec]. ('* comment:*' match: string) ifTrue:[^self msgClassComment: string with: chgRec]. ('* initialize' match: string) ifTrue:[^self]. "Initialization is done based on class>>initialize" ('''From *' match: string) ifTrue:[^self possibleSystemSource: chgRec]. doIts add: chgRec.! ! !FilePackage methodsFor: 'change record types'! method: chgRec (self getClass: chgRec methodClassName) methodChange: chgRec! ! !FilePackage methodsFor: 'change record types'! preamble: chgRec self doIt: chgRec! ! !FilePackage methodsFor: 'fileIn/fileOut' stamp: 'wod 4/15/98 15:57'! askForDoits | menu choice choices | choices := #('do not process' 'at the beginning' 'at the end' 'cancel'). menu _ SelectionMenu selections: choices. choice := nil. [choices includes: choice] whileFalse: [ choice _ menu startUpWithCaption: 'The package contains unprocessed doIts. When would like to process those?']. ^choices indexOf: choice! ! !FilePackage methodsFor: 'fileIn/fileOut' stamp: 'wod 4/15/98 16:00'! fileIn | doitsMark | doitsMark := 1. doIts isEmpty ifFalse:[doitsMark := self askForDoits]. doitsMark = 4 ifTrue: [^nil]. doitsMark = 2 ifTrue:[self fileInDoits]. classOrder do:[:cls| cls fileInDefinition. ]. classes do:[:cls| Transcript cr; show:'Filing in ', cls name. cls fileInMethods. cls hasMetaclass ifTrue:[cls metaClass fileInMethods]. ]. doitsMark = 3 ifTrue:[self fileInDoits].! ! !FilePackage methodsFor: 'fileIn/fileOut'! fileInDoits doIts do:[:chgRec| chgRec fileIn].! ! !FilePackage methodsFor: 'fileIn/fileOut' stamp: 'tk 3/7/2001 13:57'! fileOut | fileName stream | fileName := FillInTheBlank request: 'Enter the file name' initialAnswer:''. stream := FileStream newFileNamed: fileName. sourceSystem isEmpty ifFalse:[ stream nextChunkPut: sourceSystem printString;cr ]. self fileOutOn: stream. stream cr; cr. self classes do:[:cls| cls needsInitialize ifTrue:[ stream cr; nextChunkPut: cls name,' initialize']]. stream cr. stream close. "DeepCopier new checkVariables." ! ! !FilePackage methodsFor: 'fileIn/fileOut'! fileOutDoits: aStream doIts do:[:chgRec| chgRec fileOutOn: aStream].! ! !FilePackage methodsFor: 'fileIn/fileOut' stamp: 'wod 4/15/98 15:59'! fileOutOn: aStream | doitsMark | doitsMark := 1. doIts isEmpty ifFalse:[doitsMark := self askForDoits]. doitsMark = 4 ifTrue: [^nil]. doitsMark = 2 ifTrue:[self fileOutDoits: aStream]. classOrder do:[:cls| cls fileOutDefinitionOn: aStream. ]. classes do:[:cls| cls fileOutMethodsOn: aStream. cls hasMetaclass ifTrue:[cls metaClass fileOutMethodsOn: aStream]. ]. doitsMark = 3 ifTrue:[self fileOutDoits: aStream].! ! !FilePackage methodsFor: 'reading' stamp: 'pnm 8/23/2000 17:24'! fileInFrom: aStream | chgRec changes | changes := (ChangeList new scanFile: aStream from: 0 to: aStream size) changeList. aStream close. ('Processing ', self packageName) displayProgressAt: Sensor cursorPoint from: 1 to: changes size during:[:bar| 1 to: changes size do:[:i| bar value: i. chgRec := changes at: i. self perform: (chgRec type copyWith: $:) asSymbol with: chgRec. ]. ].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FilePackage class instanceVariableNames: ''! !FilePackage class methodsFor: 'instance creation'! fromFileNamed: aName ^self new fromFileNamed: aName! ! ReadWriteStream subclass: #FileStream instanceVariableNames: 'rwmode' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !FileStream commentStamp: '<historical>' prior: 0! 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. 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. *** On DOS, files cannot be shortened!! *** To overwrite a file with a shorter one, first delete the old file (FileDirectory deleteFilePath: 'Hard Disk:aFolder:dataFolder:foo') or (aFileDirectory deleteFileNamed: 'foo'). Then write your new shorter version.! !FileStream methodsFor: 'accessing' stamp: 'ar 8/6/2001 18:34'! contents "Return the contents of the receiver. Do not close or otherwise touch the receiver. Return data in whatever mode the receiver is in (e.g., binary or text)." | s savePos | savePos _ self position. self position: 0. s _ self next: self size. self position: savePos. ^s! ! !FileStream methodsFor: 'accessing'! contentsOfEntireFile "Read all of the contents of the receiver." | s binary | self readOnly. binary _ self isBinary. self reset. "erases knowledge of whether it is binary" binary ifTrue: [self binary]. s _ self next: self size. self close. ^s! ! !FileStream methodsFor: 'accessing'! next (position >= readLimit and: [self atEnd]) ifTrue: [^nil] ifFalse: [^collection at: (position _ position + 1)]! ! !FileStream methodsFor: 'accessing'! next: anInteger | newCollection howManyRead increment | newCollection _ collection species new: anInteger. howManyRead _ 0. [howManyRead < anInteger] whileTrue: [self atEnd ifTrue: [(howManyRead + 1) to: anInteger do: [:i | newCollection at: i put: (self next)]. ^newCollection]. increment _ (readLimit - position) min: (anInteger - howManyRead). newCollection replaceFrom: (howManyRead + 1) to: (howManyRead _ howManyRead + increment) with: collection startingAt: (position + 1). position _ position + increment]. ^newCollection! ! !FileStream methodsFor: 'accessing'! nextPut: aByte "1/31/96 sw: subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'accessing'! nextPutAll: aCollection "1/31/96 sw: made subclass responsibility" self subclassResponsibility! ! !FileStream methodsFor: 'accessing'! size "Answer the size of the file in characters. 1/31/96 sw: made subclass responsibility" self subclassResponsibility! ! !FileStream methodsFor: 'testing'! atEnd "Answer true if the current position is >= the end of file position. 1/31/96 sw: subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'positioning'! position "Answer the current character position in the file. 1/31/96 sw: subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'positioning'! position: pos "Set the current character position in the file to pos. 1/31/96 sw: made subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'positioning'! reset "Set the current character position to the beginning of the file. 1/31/96 sw: subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'positioning'! setToEnd "Set the current character position to the end of the File. The same as self position: self size. 1/31/96 sw: made subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'positioning'! skip: n "Set the character position to n characters from the current position. Error if not enough characters left in the file 1/31/96 sw: made subclassResponsibility." self subclassResponsibility! ! !FileStream methodsFor: 'printing' stamp: 'tk 12/5/2001 09:12'! longPrintOn: aStream "Do nothing, so it will print short. Called to print the error file. If the error was in a file operation, we can't read the contents of that file. Just print its name instead." ! ! !FileStream methodsFor: 'printing' stamp: 'tk 12/5/2001 09:32'! longPrintOn: aStream limitedTo: sizeLimit indent: indent "Do nothing, so it will print short. Called to print the error file. If the error was in a file operation, we can't read the contents of that file. Just print its name instead." aStream cr! ! !FileStream methodsFor: 'printing'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' on '. self file printOn: aStream! ! !FileStream methodsFor: 'editing' stamp: 'di 5/20/1998 23:20'! edit "Create and schedule an editor on this file." FileList openEditorOn: self editString: nil. ! ! !FileStream methodsFor: 'file open/close' stamp: 'jm 9/21/1998 13:02'! close "Close this file." self subclassResponsibility ! ! !FileStream methodsFor: 'file open/close' stamp: 'jm 9/21/1998 13:02'! closed "Answer true if this file is closed." self subclassResponsibility ! ! !FileStream methodsFor: 'file open/close' stamp: 'jm 9/21/1998 13:03'! flush "When writing, flush the current buffer out to disk." self subclassResponsibility ! ! !FileStream methodsFor: 'file open/close' stamp: 'jm 9/21/1998 13:04'! reopen "Ensure that the receiver is open, re-open it if necessary." "Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened." self subclassResponsibility ! ! !FileStream methodsFor: 'file modes' stamp: 'jm 9/21/1998 13:01'! ascii "Set this file to ascii (text) mode." self subclassResponsibility ! ! !FileStream methodsFor: 'file modes' stamp: 'jm 9/21/1998 12:59'! binary "Set this file to binary mode." self subclassResponsibility ! ! !FileStream methodsFor: 'file modes' stamp: 'jm 9/21/1998 12:59'! readOnly "Set this file's mode to read-only." self subclassResponsibility ! ! !FileStream methodsFor: 'file modes' stamp: 'jm 9/21/1998 13:01'! text "Set this file to text (ascii) mode." self ascii. ! ! !FileStream methodsFor: 'file accessing'! file "Answer the file for the page the receiver is streaming over. 1/31/96 sw: made subclass responsibility" self subclassResponsibility! ! !FileStream methodsFor: 'file accessing' stamp: 'jm 12/5/97 12:53'! localName ^ FileDirectory localNameFor: self name ! ! !FileStream methodsFor: 'file accessing'! name "Answer the name of the file for the page the receiver is streaming over. 1/31/96 sw: made subclassResponsibility" self subclassResponsibility! ! !FileStream methodsFor: 'file accessing' stamp: 'gk 2/10/2004 13:21'! url "Convert my path into a file:// type url String." ^self asUrl toText! ! !FileStream methodsFor: 'fileIn/Out' stamp: 'sw 11/19/1998 16:42'! fileIn "Guarantee that the receiver is readOnly before fileIn for efficiency and to eliminate remote sharing conflicts." self readOnly. self fileInAnnouncing: 'Loading ', self localName! ! !FileStream methodsFor: 'fileIn/Out' stamp: 'di 10/31/2001 12:07'! fileIntoNewChangeSet "File all of my contents into a new change set." self readOnly. ChangeSorter newChangesFromStream: self named: (self localName) ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileStream class instanceVariableNames: ''! !FileStream class methodsFor: 'instance creation'! fileNamed: fileName ^ self concreteStream fileNamed: (self fullName: fileName)! ! !FileStream class methodsFor: 'instance creation' stamp: 'tpr 10/16/2001 12:49'! forceNewFileNamed: fileName "Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, delete it without asking before creating the new file." ^self concreteStream forceNewFileNamed: fileName! ! !FileStream class methodsFor: 'instance creation'! fullName: fileName ^ FileDirectory default fullNameFor: fileName! ! !FileStream class methodsFor: 'instance creation' stamp: 'TPR 8/26/1999 10:49'! isAFileNamed: fName "return whether a file exists with the given name" ^self concreteStream isAFileNamed: (self fullName: fName)! ! !FileStream class methodsFor: 'instance creation' stamp: 'di 2/15/98 14:03'! new ^ self basicNew! ! !FileStream class methodsFor: 'instance creation'! newFileNamed: fileName ^ self concreteStream newFileNamed: (self fullName: fileName)! ! !FileStream class methodsFor: 'instance creation'! oldFileNamed: fileName ^ self concreteStream oldFileNamed: (self fullName: fileName)! ! !FileStream class methodsFor: 'instance creation' stamp: 'jm 5/8/1998 21:53'! oldFileOrNoneNamed: fileName "If the file exists, answer a read-only FileStream on it. If it doesn't, answer nil." | fullName | fullName _ self fullName: fileName. (self concreteStream isAFileNamed: fullName) ifTrue: [^ self concreteStream readOnlyFileNamed: fullName] ifFalse: [^ nil]. ! ! !FileStream class methodsFor: 'instance creation'! readOnlyFileNamed: fileName ^ self concreteStream readOnlyFileNamed: (self fullName: fileName)! ! !FileStream class methodsFor: 'concrete classes' stamp: 'ls 7/11/1998 02:58'! concreteStream "Who should we really direct class queries to? " ^ StandardFileStream "may change this to CrLfFileStream"! ! !FileStream class methodsFor: 'initialize-release' stamp: 'hg 8/3/2000 18:00'! initialize FileList registerFileReader: self! ! !FileStream class methodsFor: 'file reader services' stamp: 'ssa 9/3/2008 10:33'! fileIn: fullName "File in the entire contents of the file specified by the name provided" | fn ff | fullName ifNil: [^ Beeper beep]. ff _ self readOnlyFileNamed: (fn _ fullName). ((FileDirectory extensionFor: fn) sameAs: 'html') ifTrue: [ff _ ff asHtml]. ff fileIn! ! !FileStream class methodsFor: 'file reader services' stamp: 'nk 7/16/2003 15:49'! fileReaderServicesForFile: fullName suffix: suffix "Answer services for the given file" ^ ((self isSourceFileSuffix: suffix) or: [ suffix = '*' ]) ifTrue: [{self serviceRemoveLineFeeds. self serviceFileIn}] ifFalse: [#()]! ! !FileStream class methodsFor: 'file reader services' stamp: 'hg 8/3/2000 18:13'! isSourceFileSuffix: suffix ^(suffix = 'st') | (suffix = 'cs') | (suffix = '*') ! ! !FileStream class methodsFor: 'file reader services' stamp: 'LEG 10/24/2001 23:35'! removeLineFeeds: fullName | fileContents | fileContents _ (CrLfFileStream readOnlyFileNamed: fullName) contentsOfEntireFile. (StandardFileStream newFileNamed: fullName) nextPutAll: fileContents; close.! ! !FileStream class methodsFor: 'file reader services' stamp: 'sw 2/17/2002 01:38'! serviceFileIn "Answer a service for filing in an entire file" ^ SimpleServiceEntry provider: self label: 'fileIn entire file' selector: #fileIn: description: 'file in the entire contents of the file, which is expected to contain Smalltalk code in fileout ("chunk") format' buttonLabel: 'filein'! ! !FileStream class methodsFor: 'file reader services' stamp: 'nk 11/26/2002 12:49'! serviceRemoveLineFeeds "Answer a service for removing linefeeds from a file" ^ FileModifyingSimpleServiceEntry provider: self label: 'remove line feeds' selector: #removeLineFeeds: description: 'remove line feeds in file' buttonLabel: 'remove lfs'! ! !FileStream class methodsFor: 'file reader services' stamp: 'sd 2/1/2002 22:28'! services ^ Array with: self serviceRemoveLineFeeds with: self serviceFileIn ! ! !FileStream class methodsFor: 'class initialization' stamp: 'SD 11/15/2001 22:21'! unload FileList unregisterFileReader: self ! ! Error subclass: #FileStreamException instanceVariableNames: 'fileName' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !FileStreamException methodsFor: 'exceptionBuilder' stamp: 'mir 2/23/2000 20:13'! fileName: aFileName fileName _ aFileName! ! !FileStreamException methodsFor: 'exceptionDescription' stamp: 'mir 2/25/2000 17:29'! fileName ^fileName! ! !FileStreamException methodsFor: 'exceptionDescription' stamp: 'mir 2/23/2000 20:13'! isResumable "Determine whether an exception is resumable." ^true! ! !FileStreamException methodsFor: 'exceptionDescription' stamp: 'mir 2/23/2000 20:14'! messageText "Return an exception's message text." ^messageText == nil ifTrue: [fileName printString] ifFalse: [messageText]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FileStreamException class instanceVariableNames: ''! !FileStreamException class methodsFor: 'exceptionInstantiator' stamp: 'mir 2/23/2000 20:12'! fileName: aFileName ^self new fileName: aFileName! ! StringHolder subclass: #FillInTheBlank instanceVariableNames: 'acceptOnCR done responseUponCancel' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !FillInTheBlank commentStamp: '<historical>' prior: 0! I represent a prompt for string input from the user. The user is asked to type in and edit a string. The resulting string is supplied as the argument to a client-supplied action block. ! !FillInTheBlank methodsFor: 'initialize-release' stamp: 'sw 1/31/2000 14:42'! initialize super initialize. acceptOnCR _ false. done _ false. responseUponCancel _ '' ! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'jm 4/28/1998 06:18'! acceptOnCR "Answer whether a carriage return should cause input to be accepted." ^ acceptOnCR ! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'jm 4/28/1998 06:18'! acceptOnCR: aBoolean acceptOnCR _ aBoolean. ! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'jm 5/6/1998 15:13'! done "Answer whether the user has ended the interaction." ^ done ! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'jm 5/6/1998 15:13'! done: aBoolean done _ aBoolean. ! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'sw 1/31/2000 14:45'! responseUponCancel: resp responseUponCancel _ resp! ! !FillInTheBlank methodsFor: 'accessing' stamp: 'sw 1/31/2000 14:47'! setResponseForCancel self contents: responseUponCancel! ! !FillInTheBlank methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:59'! convertToCurrentVersion: varDict refStream: smartRefStrm varDict at: 'responseUponCancel' ifAbsent: [responseUponCancel _ '']. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! !FillInTheBlank methodsFor: 'private' stamp: 'sma 6/18/2000 10:54'! show: fillInView | savedArea | savedArea _ Form fromDisplay: fillInView displayBox. fillInView display. contents isEmpty ifFalse: [fillInView lastSubView controller selectFrom: 1 to: contents size]. (fillInView lastSubView containsPoint: Sensor cursorPoint) ifFalse: [fillInView lastSubView controller centerCursorInView]. fillInView controller startUp. fillInView release. savedArea displayOn: Display at: fillInView viewport topLeft. ^ contents! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FillInTheBlank class instanceVariableNames: ''! !FillInTheBlank class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:57'! multiLineRequest: queryString centerAt: aPoint initialAnswer: defaultAnswer answerHeight: answerHeight "Create a multi-line instance of me whose question is queryString with the given initial answer. Invoke it centered at the given point, and answer the string the user accepts. Answer nil if the user cancels. An empty string returned means that the ussr cleared the editing area and then hit 'accept'. Because multiple lines are invited, we ask that the user use the ENTER key, or (in morphic anyway) hit the 'accept' button, to submit; that way, the return key can be typed to move to the next line. NOTE: The ENTER key does not work on Windows platforms." "FillInTheBlank multiLineRequest: 'Enter several lines; end input by accepting or canceling via menu or press Alt+s/Alt+l' centerAt: Display center initialAnswer: 'Once upon a time...' answerHeight: 200" | model fillInView | model _ self new initialize. model contents: defaultAnswer. model responseUponCancel: nil. model acceptOnCR: false. fillInView _ self fillInTheBlankViewClass multiLineOn: model message: queryString centerAt: aPoint answerHeight: answerHeight. ^ model show: fillInView! ! !FillInTheBlank class methodsFor: 'instance creation' stamp: 'ar 3/18/2001 00:53'! request: queryString "Create an instance of me whose question is queryString. Invoke it centered at the cursor, and answer the string the user accepts. Answer the empty string if the user cancels." "FillInTheBlank request: 'Your name?'" ^ self request: queryString initialAnswer: '' centerAt: (ActiveHand ifNil:[Sensor]) cursorPoint! ! !FillInTheBlank class methodsFor: 'instance creation' stamp: 'ar 3/18/2001 00:54'! request: queryString initialAnswer: defaultAnswer "Create an instance of me whose question is queryString with the given initial answer. Invoke it centered at the given point, and answer the string the user accepts. Answer the empty string if the user cancels." "FillInTheBlank request: 'What is your favorite color?' initialAnswer: 'red, no blue. Ahhh!!'" ^ self request: queryString initialAnswer: defaultAnswer centerAt: (ActiveHand ifNil:[Sensor]) cursorPoint! ! !FillInTheBlank class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:57'! request: queryString initialAnswer: defaultAnswer centerAt: aPoint "Create an instance of me whose question is queryString with the given initial answer. Invoke it centered at the given point, and answer the string the user accepts. Answer the empty string if the user cancels." "FillInTheBlank request: 'Type something, then type CR.' initialAnswer: 'yo ho ho!!' centerAt: Display center" | model fillInView | model _ self new initialize. model contents: defaultAnswer. fillInView _ self fillInTheBlankViewClass on: model message: queryString centerAt: aPoint. ^ model show: fillInView! ! !FillInTheBlank class methodsFor: 'private' stamp: 'sma 6/18/2000 10:47'! fillInTheBlankViewClass "By factoring out this class references, it becomes possible to discard MVC by simply removing this class. All calls to this method needs to be protected by 'Smalltalk isMorphic' tests." ^ FillInTheBlankView! ! StringHolderController subclass: #FillInTheBlankController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !FillInTheBlankController commentStamp: '<historical>' prior: 0! I am the controller for a FillInTheBlankView. Based on a flag in the view, I can either accept the input string when a carriage return is typed, or I can allow multiple lines of input that is accepted by either typing enter or by invoking the 'accept' command. ! !FillInTheBlankController methodsFor: 'basic control sequence' stamp: 'th 9/17/2002 16:46'! controlInitialize model acceptOnCR ifFalse: [^ super controlInitialize]. self setMark: self markBlock stringIndex. self setPoint: self pointBlock stringIndex. self initializeSelection. beginTypeInBlock _ nil. ! ! !FillInTheBlankController methodsFor: 'basic control sequence' stamp: 'jm 5/6/1998 15:11'! controlTerminate | topController | super controlTerminate. topController _ view topView controller. topController ifNotNil: [topController close]. ! ! !FillInTheBlankController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 14:45'! isControlActive ^ self isControlWanted! ! !FillInTheBlankController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 14:45'! isControlWanted ^ model done not! ! !FillInTheBlankController methodsFor: 'other' stamp: 'jm 5/6/1998 15:13'! accept super accept. model done: true. ! ! !FillInTheBlankController methodsFor: 'other' stamp: 'sw 1/31/2000 14:47'! cancel model setResponseForCancel. super cancel. model done: true. ! ! !FillInTheBlankController methodsFor: 'other' stamp: 'jm 4/28/1998 06:25'! dispatchOnCharacter: char with: typeAheadStream "Accept the current input if the user hits the carriage return or the enter key." (model acceptOnCR and: [(char = Character cr) | (char = Character enter)]) ifTrue: [ sensor keyboard. "absorb the character" self accept. ^ true] ifFalse: [ ^ super dispatchOnCharacter: char with: typeAheadStream]. ! ! !FillInTheBlankController methodsFor: 'other' stamp: 'jm 4/28/1998 08:01'! processYellowButton "Suppress yellow-button menu if acceptOnCR is true." model acceptOnCR ifFalse: [^ super processYellowButton]. ! ! StringHolderView subclass: #FillInTheBlankView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !FillInTheBlankView commentStamp: '<historical>' prior: 0! I am a view of a FillInTheBlank. I display a query and an editable view of the user's reply string. ! !FillInTheBlankView methodsFor: 'controller access' stamp: 'jm 4/28/1998 06:37'! defaultControllerClass ^ FillInTheBlankController ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FillInTheBlankView class instanceVariableNames: ''! !FillInTheBlankView class methodsFor: 'instance creation' stamp: 'jm 4/28/1998 08:35'! multiLineOn: aFillInTheBlank message: queryString centerAt: aPoint answerHeight: answerHeight "Answer an instance of me on aFillInTheBlank asking the question queryString. Allow the reply to be multiple lines, and make the user input view the given height." | messageView answerView topView | messageView _ DisplayTextView new model: queryString asDisplayText; borderWidthLeft: 2 right: 2 top: 2 bottom: 0; controller: NoController new. messageView window: (0@0 extent: (messageView window extent max: 200@30)); centered. answerView _ self new model: aFillInTheBlank; window: (0@0 extent: (messageView window width@answerHeight)); borderWidth: 2. topView _ View new model: aFillInTheBlank. topView controller: ModalController new. topView addSubView: messageView. topView addSubView: answerView below: messageView. topView align: topView viewport center with: aPoint. topView window: (0 @ 0 extent: (messageView window width) @ (messageView window height + answerView window height)). topView translateBy: (topView displayBox amountToTranslateWithin: Display boundingBox). ^ topView ! ! !FillInTheBlankView class methodsFor: 'instance creation' stamp: 'jm 4/28/1998 08:22'! on: aFillInTheBlank message: queryString centerAt: aPoint "Answer an instance of me on aFillInTheBlank for a single line of input in response to the question queryString." aFillInTheBlank acceptOnCR: true. ^ self multiLineOn: aFillInTheBlank message: queryString centerAt: aPoint answerHeight: 40 ! ! Number variableWordSubclass: #Float instanceVariableNames: '' classVariableNames: 'E Epsilon Halfpi Infinity Ln10 Ln2 MaxVal MaxValLn MinValLogBase2 NaN NegativeInfinity NegativeZero Pi RadiansPerDegree Sqrt2 Twopi' poolDictionaries: '' category: 'Kernel-Numbers'! !Float commentStamp: '<historical>' prior: 0! My instances represent IEEE-754 floating-point double-precision numbers. They have about 16 digits of accuracy and their range is between plus and minus 10^307. Some valid examples are: 8.0 13.3 0.3 2.5e6 1.27e-30 1.27e-31 -12.987654e12 Mainly: no embedded blanks, little e for tens power, and a digit on both sides of the decimal point. It is actually possible to specify a radix for Squeak Float constants. This is great for teaching about numbers, but may be confusing to the average reader: 3r20.2 --> 6.66666666666667 8r20.2 --> 16.25 If you don't have access to the definition of IEEE-754, you can figure out what is going on by printing various simple values in Float hex. It may help you to know that the basic format is... sign 1 bit exponent 11 bits with bias of 1023 (16r3FF) to produce an exponent in the range -1023 .. +1024 - 16r000: significand = 0: Float zero significand ~= 0: Denormalized number (exp = -1024, no hidden '1' bit) - 16r7FF: significand = 0: Infinity significand ~= 0: Not A Number (NaN) representation mantissa 53 bits, but only 52 are stored (20 in the first word, 32 in the second). This is because a normalized mantissa, by definition, has a 1 to the right of its floating point, and IEEE-754 omits this redundant bit to gain an extra bit of precision instead. People talk about the mantissa without its leading one as the FRACTION, and with its leading 1 as the SIGNFICAND. The single-precision format is... sign 1 bit exponent 8 bits, with bias of 127, to represent -126 to +127 - 0x0 and 0xFF reserved for Float zero (mantissa is ignored) - 16r7F reserved for Float underflow/overflow (mantissa is ignored) mantissa 24 bits, but only 23 are stored This format is used in FloatArray (qv), and much can be learned from the conversion routines, Float asIEEE32BitWord, and Float class fromIEEE32Bit:. Thanks to Rich Harmon for asking many questions and to Tim Olson, Bruce Cohen, Rick Zaccone and others for the answers that I have collected here.! ]style[(680 9 1189 21 6 26 149)f1,f1LFloat hex;,f1,f1LFloat asIEEE32BitWord;,f1,f1LFloat class fromIEEE32Bit:;,f1! !Float methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:54'! * aNumber "Primitive. Answer the result of multiplying the receiver by aNumber. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 49> ^ aNumber adaptToFloat: self andSend: #*! ! !Float methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:22'! + aNumber "Primitive. Answer the sum of the receiver and aNumber. Essential. Fail if the argument is not a Float. See Object documentation whatIsAPrimitive." <primitive: 41> ^ aNumber adaptToFloat: self andSend: #+! ! !Float methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:55'! - aNumber "Primitive. Answer the difference between the receiver and aNumber. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 42> ^ aNumber adaptToFloat: self andSend: #-! ! !Float methodsFor: 'arithmetic' stamp: 'hh 10/3/2000 11:46'! / aNumber "Primitive. Answer the result of dividing receiver by aNumber. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 50> aNumber isZero ifTrue: [^(ZeroDivide dividend: self) signal]. ^ aNumber adaptToFloat: self andSend: #/! ! !Float methodsFor: 'arithmetic'! abs "This is faster than using Number abs." self < 0.0 ifTrue: [^ 0.0 - self] ifFalse: [^ self]! ! !Float methodsFor: 'arithmetic'! negated "Answer a Number that is the negation of the receiver." ^0.0 - self! ! !Float methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! reciprocal #Numeric. "Changed 200/01/19 For ANSI <number> support." self = 0 ifTrue: ["<- Chg" ^ (ZeroDivide dividend: self) signal"<- Chg"]. "<- Chg" ^ 1.0 / self! ! !Float methodsFor: 'mathematical functions'! arcCos "Answer the angle in radians." ^ Halfpi - self arcSin! ! !Float methodsFor: 'mathematical functions' stamp: 'jsp 2/25/1999 11:15'! arcSin "Answer the angle in radians." ((self < -1.0) or: [self > 1.0]) ifTrue: [self error: 'Value out of range']. ((self = -1.0) or: [self = 1.0]) ifTrue: [^ Halfpi * self] ifFalse: [^ (self / (1.0 - (self * self)) sqrt) arcTan]! ! !Float methodsFor: 'mathematical functions'! arcTan "Answer the angle in radians. Optional. See Object documentation whatIsAPrimitive." | theta eps step sinTheta cosTheta | <primitive: 57> "Newton-Raphson" self < 0.0 ifTrue: [ ^ 0.0 - (0.0 - self) arcTan ]. "first guess" theta _ (self * Halfpi) / (self + 1.0). "iterate" eps _ Halfpi * Epsilon. step _ theta. [(step * step) > eps] whileTrue: [ sinTheta _ theta sin. cosTheta _ theta cos. step _ (sinTheta * cosTheta) - (self * cosTheta * cosTheta). theta _ theta - step]. ^ theta! ! !Float methodsFor: 'mathematical functions' stamp: 'jsp 3/30/1999 12:38'! arcTan: denominator "Answer the angle in radians. Optional. See Object documentation whatIsAPrimitive." | result | (self = 0.0) ifTrue: [ (denominator > 0.0) ifTrue: [ result _ 0 ] ifFalse: [ result _ Pi ] ] ifFalse: [(denominator = 0.0) ifTrue: [ (self > 0.0) ifTrue: [ result _ Halfpi ] ifFalse: [ result _ Halfpi negated ] ] ifFalse: [ (denominator > 0) ifTrue: [ result _ (self / denominator) arcTan ] ifFalse: [ result _ ((self / denominator) arcTan) + Pi ] ]. ]. ^ result.! ! !Float methodsFor: 'mathematical functions'! cos "Answer the cosine of the receiver taken as an angle in radians." ^ (self + Halfpi) sin! ! !Float methodsFor: 'mathematical functions'! degreeCos "Answer the cosine of the receiver taken as an angle in degrees." ^ self degreesToRadians cos! ! !Float methodsFor: 'mathematical functions'! degreeSin "Answer the sine of the receiver taken as an angle in degrees." ^ self degreesToRadians sin! ! !Float methodsFor: 'mathematical functions'! exp "Answer E raised to the receiver power. Optional. See Object documentation whatIsAPrimitive." | base fract correction delta div | <primitive: 59> "Taylor series" "check the special cases" self < 0.0 ifTrue: [^ (self negated exp) reciprocal]. self = 0.0 ifTrue: [^ 1]. self abs > MaxValLn ifTrue: [self error: 'exp overflow']. "get first approximation by raising e to integer power" base _ E raisedToInteger: (self truncated). "now compute the correction with a short Taylor series" "fract will be 0..1, so correction will be 1..E" "in the worst case, convergance time is logarithmic with 1/Epsilon" fract _ self fractionPart. fract = 0.0 ifTrue: [ ^ base ]. "no correction required" correction _ 1.0 + fract. delta _ fract * fract / 2.0. div _ 2.0. [delta > Epsilon] whileTrue: [ correction _ correction + delta. div _ div + 1.0. delta _ delta * fract / div]. correction _ correction + delta. ^ base * correction! ! !Float methodsFor: 'mathematical functions' stamp: 'jm 3/27/98 06:28'! floorLog: radix "Answer the floor of the log base radix of the receiver." ^ (self log: radix) floor ! ! !Float methodsFor: 'mathematical functions'! ln "Answer the natural logarithm of the receiver. Optional. See Object documentation whatIsAPrimitive." | expt n mant x div pow delta sum eps | <primitive: 58> "Taylor series" self <= 0.0 ifTrue: [self error: 'ln is only defined for x > 0.0']. "get a rough estimate from binary exponent" expt _ self exponent. n _ Ln2 * expt. mant _ self timesTwoPower: 0 - expt. "compute fine correction from mantinssa in Taylor series" "mant is in the range [0..2]" "we unroll the loop to avoid use of abs" x _ mant - 1.0. div _ 1.0. pow _ delta _ sum _ x. x _ x negated. "x <= 0" eps _ Epsilon * (n abs + 1.0). [delta > eps] whileTrue: [ "pass one: delta is positive" div _ div + 1.0. pow _ pow * x. delta _ pow / div. sum _ sum + delta. "pass two: delta is negative" div _ div + 1.0. pow _ pow * x. delta _ pow / div. sum _ sum + delta]. ^ n + sum "2.718284 ln 1.0"! ! !Float methodsFor: 'mathematical functions'! log "Answer the base 10 logarithm of the receiver." ^ self ln / Ln10! ! !Float methodsFor: 'mathematical functions' stamp: 'AFi 11/23/2002 21:06'! raisedTo: aNumber "Answer the receiver raised to aNumber." aNumber isInteger ifTrue: ["Do the special case of integer power" ^ self raisedToInteger: aNumber]. self < 0.0 ifTrue: [ ArithmeticError signal: ' raised to a non-integer power' ]. 0.0 = aNumber ifTrue: [^ 1.0]. "special case for exponent = 0.0" (self= 0.0) | (aNumber = 1.0) ifTrue: [^ self]. "special case for self = 1.0" ^ (self ln * aNumber asFloat) exp "otherwise use logarithms" ! ! !Float methodsFor: 'mathematical functions' stamp: 'tao 4/19/98 23:22'! reciprocalFloorLog: radix "Quick computation of (self log: radix) floor, when self < 1.0. Avoids infinite recursion problems with denormalized numbers" | adjust scale n | adjust _ 0. scale _ 1.0. [(n _ radix / (self * scale)) isInfinite] whileTrue: [scale _ scale * radix. adjust _ adjust + 1]. ^ ((n floorLog: radix) + adjust) negated! ! !Float methodsFor: 'mathematical functions' stamp: 'tao 10/15/97 14:23'! reciprocalLogBase2 "optimized for self = 10, for use in conversion for printing" ^ self = 10.0 ifTrue: [Ln2 / Ln10] ifFalse: [Ln2 / self ln]! ! !Float methodsFor: 'mathematical functions'! sin "Answer the sine of the receiver taken as an angle in radians. Optional. See Object documentation whatIsAPrimitive." | sum delta self2 i | <primitive: 56> "Taylor series" "normalize to the range [0..Pi/2]" self < 0.0 ifTrue: [^ (0.0 - ((0.0 - self) sin))]. self > Twopi ifTrue: [^ (self \\ Twopi) sin]. self > Pi ifTrue: [^ (0.0 - (self - Pi) sin)]. self > Halfpi ifTrue: [^ (Pi - self) sin]. "unroll loop to avoid use of abs" sum _ delta _ self. self2 _ 0.0 - (self * self). i _ 2.0. [delta > Epsilon] whileTrue: [ "once" delta _ (delta * self2) / (i * (i + 1.0)). i _ i + 2.0. sum _ sum + delta. "twice" delta _ (delta * self2) / (i * (i + 1.0)). i _ i + 2.0. sum _ sum + delta]. ^ sum! ! !Float methodsFor: 'mathematical functions' stamp: 'RAH 4/25/2000 19:49'! sqrt "Answer the square root of the receiver. Optional. See Object documentation whatIsAPrimitive." | exp guess eps delta | <primitive: 55> #Numeric. "Changed 200/01/19 For ANSI <number> support." "Newton-Raphson" self <= 0.0 ifTrue: [self = 0.0 ifTrue: [^ 0.0] ifFalse: ["v Chg" ^ FloatingPointException signal: 'undefined if less than zero.']]. "first guess is half the exponent" exp := self exponent // 2. guess := self timesTwoPower: 0 - exp. "get eps value" eps := guess * Epsilon. eps := eps * eps. delta := self - (guess * guess) / (guess * 2.0). [delta * delta > eps] whileTrue: [guess := guess + delta. delta := self - (guess * guess) / (guess * 2.0)]. ^ guess! ! !Float methodsFor: 'mathematical functions'! tan "Answer the tangent of the receiver taken as an angle in radians." ^ self sin / self cos! ! !Float methodsFor: 'mathematical functions'! timesTwoPower: anInteger "Primitive. Answer with the receiver multiplied by 2.0 raised to the power of the argument. Optional. See Object documentation whatIsAPrimitive." <primitive: 54> anInteger < -29 ifTrue: [^ self * (2.0 raisedToInteger: anInteger)]. anInteger < 0 ifTrue: [^ self / (1 bitShift: (0 - anInteger)) asFloat]. anInteger < 30 ifTrue: [^ self * (1 bitShift: anInteger) asFloat]. ^ self * (2.0 raisedToInteger: anInteger)! ! !Float methodsFor: 'comparing' stamp: 'di 11/6/1998 13:55'! < aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is less than the argument. Otherwise return false. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 43> ^ aNumber adaptToFloat: self andSend: #<! ! !Float methodsFor: 'comparing' stamp: 'di 11/6/1998 13:55'! <= aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is less than or equal to the argument. Otherwise return false. Fail if the argument is not a Float. Optional. See Object documentation whatIsAPrimitive." <primitive: 45> ^ aNumber adaptToFloat: self andSend: #<=! ! !Float methodsFor: 'comparing' stamp: 'di 11/6/1998 13:56'! = aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is equal to the argument. Otherwise return false. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 47> aNumber isNumber ifFalse: [^ false]. ^ aNumber adaptToFloat: self andSend: #=! ! !Float methodsFor: 'comparing' stamp: 'di 11/6/1998 13:57'! > aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is greater than the argument. Otherwise return false. Fail if the argument is not a Float. Essential. See Object documentation whatIsAPrimitive." <primitive: 44> ^ aNumber adaptToFloat: self andSend: #>! ! !Float methodsFor: 'comparing' stamp: 'di 11/6/1998 13:57'! >= aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is greater than or equal to the argument. Otherwise return false. Fail if the argument is not a Float. Optional. See Object documentation whatIsAPrimitive. " <primitive: 46> ^ aNumber adaptToFloat: self andSend: #>! ! !Float methodsFor: 'comparing' stamp: 'tk 11/27/1999 21:47'! closeTo: num "are these two numbers close?" | fuzz ans | num isNumber ifFalse: [ [ans _ self = num] ifError: [:aString :aReceiver | ^ false]. ^ ans]. self = 0.0 ifTrue: [^ num abs < 0.0001]. num = 0.0 ifTrue: [^ self abs < 0.0001]. self isNaN == num isNaN ifFalse: [^ false]. self isInfinite == num isInfinite ifFalse: [^ false]. fuzz := (self abs max: num abs) * 0.0001. ^ (self - num) abs <= fuzz! ! !Float methodsFor: 'comparing' stamp: 'jm 4/28/1998 01:04'! hash "Hash is reimplemented because = is implemented. Both words of the float are used; 8 bits are removed from each end to clear most of the exponent regardless of the byte ordering. (The bitAnd:'s ensure that the intermediate results do not become a large integer.) Slower than the original version in the ratios 12:5 to 2:1 depending on values. (DNS, 11 May, 1997)" ^ (((self basicAt: 1) bitAnd: 16r00FFFF00) + ((self basicAt: 2) bitAnd: 16r00FFFF00)) bitShift: -8 ! ! !Float methodsFor: 'comparing'! ~= aNumber "Primitive. Compare the receiver with the argument and return true if the receiver is not equal to the argument. Otherwise return false. Fail if the argument is not a Float. Optional. See Object documentation whatIsAPrimitive." <primitive: 48> ^super ~= aNumber! ! !Float methodsFor: 'testing' stamp: 'bf 8/20/1999 12:56'! hasContentsInExplorer ^false! ! !Float methodsFor: 'testing'! isFloat ^ true! ! !Float methodsFor: 'testing' stamp: 'jm 4/30/1998 13:50'! isInfinite "Return true if the receiver is positive or negative infinity." ^ self = Infinity or: [self = NegativeInfinity] ! ! !Float methodsFor: 'testing'! isLiteral ^true! ! !Float methodsFor: 'testing' stamp: 'tao 10/10/97 16:39'! isNaN "simple, byte-order independent test for Not-a-Number" ^ self ~= self! ! !Float methodsFor: 'testing' stamp: 'ar 6/9/2000 18:56'! isPowerOfTwo "Return true if the receiver is an integral power of two. Floats never return true here." ^false! ! !Float methodsFor: 'testing'! isZero ^self = 0.0! ! !Float methodsFor: 'testing' stamp: 'jm 4/28/1998 01:10'! sign "Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0. Handle IEEE-754 negative-zero by reporting a sign of -1" self > 0 ifTrue: [^ 1]. (self < 0 or: [((self at: 1) bitShift: -31) = 1]) ifTrue: [^ -1]. ^ 0! ! !Float methodsFor: 'truncation and round off'! exponent "Primitive. Consider the receiver to be represented as a power of two multiplied by a mantissa (between one and two). Answer with the SmallInteger to whose power two is raised. Optional. See Object documentation whatIsAPrimitive." | positive | <primitive: 53> self >= 1.0 ifTrue: [^self floorLog: 2]. self > 0.0 ifTrue: [positive _ (1.0 / self) exponent. self = (1.0 / (1.0 timesTwoPower: positive)) ifTrue: [^positive negated] ifFalse: [^positive negated - 1]]. self = 0.0 ifTrue: [^-1]. ^self negated exponent! ! !Float methodsFor: 'truncation and round off'! fractionPart "Primitive. Answer a Float whose value is the difference between the receiver and the receiver's asInteger value. Optional. See Object documentation whatIsAPrimitive." <primitive: 52> ^self - self truncated asFloat! ! !Float methodsFor: 'truncation and round off'! integerPart "Answer a Float whose value is the receiver's truncated value." ^self - self fractionPart! ! !Float methodsFor: 'truncation and round off' stamp: 'tk 12/30/2000 20:04'! reduce "If self is close to an integer, return that integer" (self closeTo: self rounded) ifTrue: [^ self rounded]! ! !Float methodsFor: 'truncation and round off'! rounded "Answer the integer nearest the receiver." self >= 0.0 ifTrue: [^(self + 0.5) truncated] ifFalse: [^(self - 0.5) truncated]! ! !Float methodsFor: 'truncation and round off' stamp: 'tao 4/19/98 13:14'! significand ^ self timesTwoPower: (self exponent negated)! ! !Float methodsFor: 'truncation and round off' stamp: 'tao 4/19/98 14:27'! significandAsInteger | exp sig | exp _ self exponent. sig _ (((self at: 1) bitAnd: 16r000FFFFF) bitShift: 32) bitOr: (self at: 2). exp > -1023 ifTrue: [sig _ sig bitOr: (1 bitShift: 52)]. ^ sig.! ! !Float methodsFor: 'truncation and round off' stamp: 'di 7/1/1998 23:01'! truncated "Answer with a SmallInteger equal to the value of the receiver without its fractional part. The primitive fails if the truncated value cannot be represented as a SmallInteger. In that case, the code below will compute a LargeInteger truncated value. Essential. See Object documentation whatIsAPrimitive. " <primitive: 51> (self isInfinite or: [self isNaN]) ifTrue: [self error: 'Cannot truncate this number']. self abs < 2.0e16 ifTrue: ["Fastest way when it may not be an integer" ^ (self quo: 1073741823.0) * 1073741823 + (self rem: 1073741823.0) truncated] ifFalse: [^ self asTrueFraction. "Extract all bits of the mantissa and shift if necess"]! ! !Float methodsFor: 'converting' stamp: 'di 11/6/1998 13:38'! adaptToFraction: rcvr andSend: selector "If I am involved in arithmetic with a Fraction, convert it to a Float." ^ rcvr asFloat perform: selector with: self! ! !Float methodsFor: 'converting' stamp: 'di 11/6/1998 13:07'! adaptToInteger: rcvr andSend: selector "If I am involved in arithmetic with an Integer, convert it to a Float." ^ rcvr asFloat perform: selector with: self! ! !Float methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector "Convert receiverScaledDecimal to a Float and do the arithmetic. receiverScaledDecimal arithmeticOpSelector self." #Numeric. "add 200/01/19 For ScaledDecimal support." ^ receiverScaledDecimal asFloat perform: arithmeticOpSelector with: self! ! !Float methodsFor: 'converting'! asApproximateFraction "Answer a Fraction approximating the receiver. This conversion uses the continued fraction method to approximate a floating point number." | num1 denom1 num2 denom2 int frac newD temp | num1 _ self asInteger. "The first of two alternating numerators" denom1 _ 1. "The first of two alternating denominators" num2 _ 1. "The second numerator" denom2 _ 0. "The second denominator--will update" int _ num1. "The integer part of self" frac _ self fractionPart. "The fractional part of self" [frac = 0] whileFalse: ["repeat while the fractional part is not zero" newD _ 1.0 / frac. "Take reciprocal of the fractional part" int _ newD asInteger. "get the integer part of this" frac _ newD fractionPart. "and save the fractional part for next time" temp _ num2. "Get old numerator and save it" num2 _ num1. "Set second numerator to first" num1 _ num1 * int + temp. "Update first numerator" temp _ denom2. "Get old denominator and save it" denom2 _ denom1. "Set second denominator to first" denom1 _ int * denom1 + temp. "Update first denominator" 10000000000.0 < denom1 ifTrue: ["Is ratio past float precision? If so, pick which of the two ratios to use" num2 = 0.0 ifTrue: ["Is second denominator 0?" ^ Fraction numerator: num1 denominator: denom1]. ^ Fraction numerator: num2 denominator: denom2]]. "If fractional part is zero, return the first ratio" denom1 = 1 ifTrue: ["Am I really an Integer?" ^ num1 "Yes, return Integer result"] ifFalse: ["Otherwise return Fraction result" ^ Fraction numerator: num1 denominator: denom1]! ! !Float methodsFor: 'converting'! asFloat "Answer the receiver itself." ^self! ! !Float methodsFor: 'converting' stamp: 'sma 5/3/2000 21:46'! asFraction ^ self asTrueFraction ! ! !Float methodsFor: 'converting' stamp: 'di 2/8/1999 12:51'! asIEEE32BitWord "Convert the receiver into a 32 bit Integer value representing the same number in IEEE 32 bit format. Used for conversion in FloatArrays only." | word1 word2 sign mantissa exponent destWord | self = 0.0 ifTrue:[^0]. word1 _ self basicAt: 1. word2 _ self basicAt: 2. mantissa _ (word2 bitShift: -29) + ((word1 bitAnd: 16rFFFFF) bitShift: 3). exponent _ ((word1 bitShift: -20) bitAnd: 16r7FF) - 1023 + 127. exponent < 0 ifTrue:[^0]. "Underflow" exponent > 254 ifTrue:["Overflow" exponent _ 255. mantissa _ 0]. sign _ word1 bitAnd: 16r80000000. destWord _ (sign bitOr: (exponent bitShift: 23)) bitOr: mantissa. ^ destWord! ! !Float methodsFor: 'converting' stamp: 'di 7/1/1998 22:20'! asTrueFraction " Answer a fraction that EXACTLY represents self, a double precision IEEE floating point number. Floats are stored in the same form on all platforms. (Does not handle gradual underflow or NANs.) By David N. Smith with significant performance improvements by Luciano Esteban Notarfrancesco. (Version of 11April97)" | shifty sign expPart exp fraction fractionPart result zeroBitsCount | self isInfinite ifTrue: [self error: 'Cannot represent infinity as a fraction']. self isNaN ifTrue: [self error: 'Cannot represent Not-a-Number as a fraction']. " Extract the bits of an IEEE double float " shifty := ((self basicAt: 1) bitShift: 32) + (self basicAt: 2). " Extract the sign and the biased exponent " sign := (shifty bitShift: -63) = 0 ifTrue: [1] ifFalse: [-1]. expPart := (shifty bitShift: -52) bitAnd: 16r7FF. " Extract fractional part; answer 0 if this is a true 0.0 value " fractionPart := shifty bitAnd: 16r000FFFFFFFFFFFFF. ( expPart=0 and: [ fractionPart=0 ] ) ifTrue: [ ^ 0 ]. " Replace omitted leading 1 in fraction " fraction := fractionPart bitOr: 16r0010000000000000. "Unbias exponent: 16r3FF is bias; 52 is fraction width" exp := 16r3FF + 52 - expPart. " Form the result. When exp>52, the exponent is adjusted by the number of trailing zero bits in the fraction to minimize the (huge) time otherwise spent in #gcd:. " exp negative ifTrue: [ result := sign * fraction bitShift: exp negated ] ifFalse: [ zeroBitsCount _ fraction lowBit - 1. exp := exp - zeroBitsCount. exp <= 0 ifTrue: [ zeroBitsCount := zeroBitsCount + exp. "exp := 0." " Not needed; exp not refernced again " result := sign * fraction bitShift: zeroBitsCount negated ] ifFalse: [ result := Fraction numerator: (sign * fraction bitShift: zeroBitsCount negated) denominator: (1 bitShift: exp) ] ]. "Low cost validation omitted after extensive testing" "(result asFloat = self) ifFalse: [self error: 'asTrueFraction validation failed']." ^ result ! ! !Float methodsFor: 'converting'! degreesToRadians "Answer the receiver in radians. Assumes the receiver is in degrees." ^self * RadiansPerDegree! ! !Float methodsFor: 'converting' stamp: 'tao 10/10/97 16:38'! isInf "simple, byte-order independent test for +/- Infinity" ^ self = (self * 1.5 + 1.0)! ! !Float methodsFor: 'converting'! radiansToDegrees "Answer the receiver in degrees. Assumes the receiver is in radians." ^self / RadiansPerDegree! ! !Float methodsFor: 'copying'! deepCopy ^self copy! ! !Float methodsFor: 'copying'! shallowCopy ^self + 0.0! ! !Float methodsFor: 'copying' stamp: 'tk 8/19/1998 16:08'! veryDeepCopyWith: deepCopier "Return self. Do not record me." ^ self clone! ! !Float methodsFor: 'printing' stamp: 'tao 4/22/98 11:58'! absPrintOn: aStream base: base "Print my value on a stream in the given base. Assumes that my value is strictly positive; negative numbers, zero, and NaNs have already been handled elsewhere. Based upon the algorithm outlined in: Robert G. Burger and R. Kent Dybvig Printing Floating Point Numbers Quickly and Accurately ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation June 1996. This version performs all calculations with Floats instead of LargeIntegers, and loses about 3 lsbs of accuracy compared to an exact conversion." | significantBits fBase exp baseExpEstimate r s mPlus mMinus scale d tc1 tc2 fixedFormat decPointCount | self isInfinite ifTrue: [aStream nextPutAll: 'Infinity'. ^ self]. significantBits _ 50. "approximately 3 lsb's of accuracy loss during conversion" fBase _ base asFloat. exp _ self exponent. baseExpEstimate _ (exp * fBase reciprocalLogBase2 - 1.0e-10) ceiling. exp >= 0 ifTrue: [r _ self. s _ 1.0. mPlus _ 1.0 timesTwoPower: exp - significantBits. mMinus _ self significand ~= 1.0 ifTrue: [mPlus] ifFalse: [mPlus / 2.0]] ifFalse: [r _ self timesTwoPower: significantBits. s _ 1.0 timesTwoPower: significantBits. mMinus _ 1.0 timesTwoPower: (exp max: -1024). mPlus _ (exp = MinValLogBase2) | (self significand ~= 1.0) ifTrue: [mMinus] ifFalse: [mMinus * 2.0]]. baseExpEstimate >= 0 ifTrue: [s _ s * (fBase raisedToInteger: baseExpEstimate). exp = 1023 ifTrue: "scale down to prevent overflow to Infinity during conversion" [r _ r / fBase. s _ s / fBase. mPlus _ mPlus / fBase. mMinus _ mMinus / fBase]] ifFalse: [exp < -1023 ifTrue: "scale up to prevent denorm reciprocals overflowing to Infinity" [d _ (53 * fBase reciprocalLogBase2 - 1.0e-10) ceiling. scale _ fBase raisedToInteger: d. r _ r * scale. mPlus _ mPlus * scale. mMinus _ mMinus * scale. scale _ fBase raisedToInteger: (baseExpEstimate + d) negated] ifFalse: [scale _ fBase raisedToInteger: baseExpEstimate negated]. s _ s / scale]. (r + mPlus >= s) ifTrue: [baseExpEstimate _ baseExpEstimate + 1] ifFalse: [s _ s / fBase]. (fixedFormat _ baseExpEstimate between: -3 and: 6) ifTrue: [decPointCount _ baseExpEstimate. baseExpEstimate <= 0 ifTrue: [aStream nextPutAll: ('0.000000' truncateTo: 2 - baseExpEstimate)]] ifFalse: [decPointCount _ 1]. [d _ (r / s) truncated. r _ r - (d * s). (tc1 _ r <= mMinus) | (tc2 _ r + mPlus >= s)] whileFalse: [aStream nextPut: (Character digitValue: d). r _ r * fBase. mPlus _ mPlus * fBase. mMinus _ mMinus * fBase. decPointCount _ decPointCount - 1. decPointCount = 0 ifTrue: [aStream nextPut: $.]]. tc2 ifTrue: [tc1 not | (tc1 & (r*2.0 >= s)) ifTrue: [d _ d + 1]]. aStream nextPut: (Character digitValue: d). decPointCount > 0 ifTrue: [decPointCount - 1 to: 1 by: -1 do: [:i | aStream nextPut: $0]. aStream nextPutAll: '.0']. fixedFormat ifFalse: [aStream nextPut: $e. aStream nextPutAll: (baseExpEstimate - 1) printString]! ! !Float methodsFor: 'printing'! hex "If ya really want to know..." | word nibble | ^ String streamContents: [:strm | 1 to: 2 do: [:i | word _ self at: i. 1 to: 8 do: [:s | nibble _ (word bitShift: -8+s*4) bitAnd: 16rF. strm nextPut: ('0123456789ABCDEF' at: nibble+1)]]] " (-2.0 to: 2.0) collect: [:f | f hex] "! ! !Float methodsFor: 'printing' stamp: 'tao 4/19/98 23:31'! printOn: aStream base: base "Handle sign, zero, and NaNs; all other values passed to absPrintOn:base:" self isNaN ifTrue: [aStream nextPutAll: 'NaN'. ^ self]. "check for NaN before sign" self > 0.0 ifTrue: [self absPrintOn: aStream base: base] ifFalse: [self sign = -1 ifTrue: [aStream nextPutAll: '-']. self = 0.0 ifTrue: [aStream nextPutAll: '0.0'. ^ self] ifFalse: [self negated absPrintOn: aStream base: base]]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Float class instanceVariableNames: ''! !Float class methodsFor: 'class initialization' stamp: 'jm 4/30/1998 13:48'! initialize "Float initialize" "Constants from Computer Approximations, pp. 182-183: Pi = 3.14159265358979323846264338327950288 Pi/2 = 1.57079632679489661923132169163975144 Pi*2 = 6.28318530717958647692528676655900576 Pi/180 = 0.01745329251994329576923690768488612 2.0 ln = 0.69314718055994530941723212145817657 2.0 sqrt = 1.41421356237309504880168872420969808" Pi _ 3.14159265358979323846264338327950288. Halfpi _ Pi / 2.0. Twopi _ Pi * 2.0. RadiansPerDegree _ Pi / 180.0. Ln2 _ 0.69314718055994530941723212145817657. Ln10 _ 10.0 ln. Sqrt2 _ 1.41421356237309504880168872420969808. E _ 2.718281828459045235360287471353. Epsilon _ 0.000000000001. "Defines precision of mathematical functions" MaxVal _ 1.7976931348623159e308. MaxValLn _ 709.782712893384. MinValLogBase2 _ -1074. Infinity _ MaxVal * MaxVal. NegativeInfinity _ 0.0 - Infinity. NaN _ Infinity - Infinity. NegativeZero _ 1.0 / Infinity negated. ! ! !Float class methodsFor: 'instance creation' stamp: 'di 2/8/1999 12:58'! fromIEEE32Bit: word "Convert the given 32 bit word (which is supposed to be a positive 32bit value) from a 32bit IEEE floating point representation into an actual Squeak float object (being 64bit wide). Should only be used for conversion in FloatArrays or likewise objects." | sign mantissa exponent newFloat | word negative ifTrue: [^ self error:'Cannot deal with negative numbers']. word = 0 ifTrue:[^ 0.0]. mantissa _ word bitAnd: 16r7FFFFF. exponent _ ((word bitShift: -23) bitAnd: 16rFF) - 127. sign _ word bitAnd: 16r80000000. exponent = 128 ifTrue:["Either NAN or INF" mantissa = 0 ifFalse:[^ Float nan]. sign = 0 ifTrue:[^ Float infinity] ifFalse:[^ Float infinity negated]]. "Create new float" newFloat _ self new: 2. newFloat basicAt: 1 put: ((sign bitOr: (1023 + exponent bitShift: 20)) bitOr: (mantissa bitShift: -3)). newFloat basicAt: 2 put: ((mantissa bitAnd: 7) bitShift: 29). ^newFloat! ! !Float class methodsFor: 'instance creation'! readFrom: aStream "Answer a new Float as described on the stream, aStream." ^(super readFrom: aStream) asFloat! ! !Float class methodsFor: 'constants' stamp: 'tao 4/23/98 11:37'! infinity "Answer the value used to represent an infinite magnitude" ^ Infinity! ! !Float class methodsFor: 'constants' stamp: 'tao 4/23/98 11:38'! nan "Answer the canonical value used to represent Not-A-Number" ^ NaN! ! !Float class methodsFor: 'constants' stamp: 'tao 4/23/98 12:05'! negativeZero ^ NegativeZero! ! !Float class methodsFor: 'constants' stamp: 'RAH 4/25/2000 19:49'! one #Numeric. "add 200/01/19 For <number> protocol support." ^ 1.0! ! !Float class methodsFor: 'constants'! pi "Answer the constant, Pi." ^Pi! ! !Float class methodsFor: 'plugin generation' stamp: 'bf 3/16/2000 19:06'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asFloatValueFrom: anInteger on: aStream! ! !Float class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:05'! ccg: cg generateCoerceToOopFrom: aNode on: aStream cg generateCoerceToFloatObjectFrom: aNode on: aStream! ! !Float class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:10'! ccg: cg generateCoerceToValueFrom: aNode on: aStream cg generateCoerceToFloatValueFrom: aNode on: aStream! ! !Float class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 17:08'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asFloatValueFrom: anInteger! ! !Float class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 11:22'! ccgCanConvertFrom: anObject ^anObject class == self! ! !Float class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:09'! ccgDeclareCForVar: aSymbolOrString ^'double ', aSymbolOrString! ! ArrayedCollection variableWordSubclass: #FloatArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !FloatArray commentStamp: '<historical>' prior: 0! FloatArrays store 32bit IEEE floating point numbers.! !FloatArray methodsFor: 'accessing' stamp: 'ar 2/2/2001 15:47'! at: index <primitive: 'primitiveAt' module: 'FloatArrayPlugin'> ^Float fromIEEE32Bit: (self basicAt: index)! ! !FloatArray methodsFor: 'accessing' stamp: 'ar 2/2/2001 15:47'! at: index put: value <primitive: 'primitiveAtPut' module: 'FloatArrayPlugin'> value isFloat ifTrue:[self basicAt: index put: value asIEEE32BitWord] ifFalse:[self at: index put: value asFloat]. ^value! ! !FloatArray methodsFor: 'accessing' stamp: 'ar 11/2/1998 12:19'! defaultElement "Return the default element of the receiver" ^0.0! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:33'! * anObject ^self clone *= anObject! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:49'! *= anObject ^anObject isNumber ifTrue:[self primMulScalar: anObject asFloat] ifFalse:[self primMulArray: anObject]! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:33'! + anObject ^self clone += anObject! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:48'! += anObject ^anObject isNumber ifTrue:[self primAddScalar: anObject asFloat] ifFalse:[self primAddArray: anObject]! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:33'! - anObject ^self clone -= anObject! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:49'! -= anObject ^anObject isNumber ifTrue:[self primSubScalar: anObject asFloat] ifFalse:[self primSubArray: anObject]! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/14/1998 22:34'! / anObject ^self clone /= anObject! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 10/7/1998 19:58'! /= anObject ^anObject isNumber ifTrue:[self primDivScalar: anObject asFloat] ifFalse:[self primDivArray: anObject]! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/7/2001 23:07'! adaptToNumber: rcvr andSend: selector "If I am involved in arithmetic with a Number. If possible, convert it to a float and perform the (more efficient) primitive operation." selector == #+ ifTrue:[^self + rcvr]. selector == #* ifTrue:[^self * rcvr]. selector == #- ifTrue:[^self negated += rcvr]. selector == #/ ifTrue:[^self * (1.0 / rcvr)]. ^super adaptToNumber: rcvr andSend: selector! ! !FloatArray methodsFor: 'arithmetic' stamp: 'ar 9/7/2001 23:04'! negated ^self clone *= -1! ! !FloatArray methodsFor: 'comparing' stamp: 'ar 2/2/2001 15:47'! = aFloatArray | length | <primitive: 'primitiveEqual' module: 'FloatArrayPlugin'> aFloatArray class = self class ifFalse: [^ false]. length _ self size. length = aFloatArray size ifFalse: [^ false]. 1 to: self size do: [:i | (self at: i) = (aFloatArray at: i) ifFalse: [^ false]]. ^ true! ! !FloatArray methodsFor: 'comparing' stamp: 'ar 5/3/2001 13:02'! hash | result | <primitive:'primitiveHashArray' module: 'FloatArrayPlugin'> result _ 0. 1 to: self size do:[:i| result _ result + (self basicAt: i) ]. ^result bitAnd: 16r1FFFFFFF! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primAddArray: floatArray <primitive: 'primitiveAddFloatArray' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) + (floatArray at: i)].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primAddScalar: scalarValue <primitive: 'primitiveAddScalar' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) + scalarValue].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primDivArray: floatArray <primitive: 'primitiveDivFloatArray' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) / (floatArray at: i)].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primDivScalar: scalarValue <primitive: 'primitiveDivScalar' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) / scalarValue].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primMulArray: floatArray <primitive: 'primitiveMulFloatArray' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) * (floatArray at: i)].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primMulScalar: scalarValue <primitive: 'primitiveMulScalar' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) * scalarValue].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primSubArray: floatArray <primitive: 'primitiveSubFloatArray' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) - (floatArray at: i)].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'ar 2/2/2001 15:47'! primSubScalar: scalarValue <primitive: 'primitiveSubScalar' module: 'FloatArrayPlugin'> 1 to: self size do:[:i| self at: i put: (self at: i) - scalarValue].! ! !FloatArray methodsFor: 'primitives-plugin' stamp: 'jcg 6/12/2003 17:54'! sum <primitive: 'primitiveSum' module: 'FloatArrayPlugin'> ^ super sum! ! !FloatArray methodsFor: 'converting' stamp: 'ar 9/14/1998 23:46'! asFloatArray ^self! ! !FloatArray methodsFor: 'private' stamp: 'ar 10/9/1998 11:27'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> super replaceFrom: start to: stop with: replacement startingAt: repStart! ! !FloatArray methodsFor: 'user interface' stamp: 'ar 2/13/1999 21:33'! inspect "Open a OrderedCollectionInspector on the receiver. Use basicInspect to get a normal (less useful) type of inspector." OrderedCollectionInspector openOn: self withEvalPane: true! ! !FloatArray methodsFor: 'user interface' stamp: 'ar 2/13/1999 21:33'! inspectWithLabel: aLabel "Open a OrderedCollectionInspector on the receiver. Use basicInspect to get a normal (less useful) type of inspector." OrderedCollectionInspector openOn: self withEvalPane: true withLabel: aLabel! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FloatArray class instanceVariableNames: ''! !FloatArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:17'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asFloatPtrFrom: anInteger on: aStream! ! !FloatArray class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 17:07'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asWBFloatPtrFrom: anInteger! ! !FloatArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:14'! ccgDeclareCForVar: aSymbolOrString ^'float *', aSymbolOrString! ! ArithmeticError subclass: #FloatingPointException instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! DisplayMedium subclass: #Form instanceVariableNames: 'bits width height depth offset' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !Form commentStamp: 'ls 1/4/2004 17:16' prior: 0! 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. 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. Forms are indexed starting at 0 instead of 1; thus, the top-left pixel of a Form has coordinates 0@0. Forms are combined using BitBlt. See the comment in class BitBlt. Forms that repeat many times to fill a large destination are InfiniteForms. colorAt: x@y Returns the abstract Color at this location displayAt: x@y shows this form on the screen displayOn: aMedium at: x@y shows this form in a Window, a Form, or other DisplayMedium fillColor: aColor Set all the pixels to the color. edit launch an editor to change the bits of this form. pixelValueAt: x@y The encoded color. The encoding depends on the depth. ! ]style[(223 6 62 5 374 6 11 23 64 12 382)f1,f1LBitmap Definition;,f1,f1LColor Definition;,f1,f1LBitBlt Definition;,f1,f1LBitBlt Comment;,f1,f1LInfiniteForm Definition;,f1! !Form methodsFor: 'accessing'! bits "Answer the receiver's Bitmap containing its bits." ^ bits! ! !Form methodsFor: 'accessing'! bits: aBitmap "Reset the Bitmap containing the receiver's bits." bits _ aBitmap! ! !Form methodsFor: 'accessing' stamp: 'ar 5/17/2001 15:41'! bitsSize | pixPerWord | depth == nil ifTrue: [depth _ 1]. pixPerWord _ 32 // self depth. ^ width + pixPerWord - 1 // pixPerWord * height! ! !Form methodsFor: 'accessing' stamp: 'tk 3/9/97'! center "Note that offset is ignored here. Are we really going to embrace offset? " ^ (width @ height) // 2! ! !Form methodsFor: 'accessing' stamp: 'ar 5/28/2000 12:03'! defaultCanvasClass "Return the default canvas used for drawing onto the receiver" ^Display defaultCanvasClass! ! !Form methodsFor: 'accessing' stamp: 'ar 5/17/2001 15:45'! depth ^ depth < 0 ifTrue:[0-depth] ifFalse:[depth]! ! !Form methodsFor: 'accessing'! depth: bitsPerPixel (bitsPerPixel > 32 or: [(bitsPerPixel bitAnd: bitsPerPixel-1) ~= 0]) ifTrue: [self halt: 'bitsPerPixel must be 1, 2, 4, 8, 16 or 32']. depth _ bitsPerPixel! ! !Form methodsFor: 'accessing' stamp: 'ar 5/27/2000 16:56'! displayScreen "Return the display screen the receiver is allocated on. Forms in general are Squeak internal and not allocated on any particular display." ^nil! ! !Form methodsFor: 'accessing'! extent ^ width @ height! ! !Form methodsFor: 'accessing'! form "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" ^ self! ! !Form methodsFor: 'accessing' stamp: 'ar 5/28/2000 12:03'! getCanvas "Return a Canvas that can be used to draw onto the receiver" ^self defaultCanvasClass on: self! ! !Form methodsFor: 'accessing' stamp: 'ar 5/28/2000 00:48'! hasBeenModified "Return true if something *might* have been drawn into the receiver" ^(bits == nil or:[bits class == ByteArray]) not "Read the above as: If the receiver has forgotten its contents (bits == nil) or is still hibernated it can't be modified."! ! !Form methodsFor: 'accessing' stamp: 'ar 5/28/2000 00:48'! hasBeenModified: aBool "Change the receiver to reflect the modification state" aBool ifTrue:[^self unhibernate]. self shouldPreserveContents ifTrue:[self hibernate] ifFalse:[bits _ nil]! ! !Form methodsFor: 'accessing'! height ^ height! ! !Form methodsFor: 'accessing' stamp: 'ar 5/17/2001 15:50'! nativeDepth "Return the 'native' depth of the receiver, e.g., including the endianess" ^depth! ! !Form methodsFor: 'accessing' stamp: 'ar 2/16/2000 22:00'! offset ^offset ifNil:[0@0]! ! !Form methodsFor: 'accessing'! offset: aPoint offset _ aPoint! ! !Form methodsFor: 'accessing'! size "Should no longer be used -- use bitsSize instead. length of variable part of instance." ^ super size! ! !Form methodsFor: 'accessing'! width ^ width! ! !Form methodsFor: 'analyzing'! cgForPixelValue: pv orNot: not "Return the center of gravity for all pixels of value pv. Note: If orNot is true, then produce the center of gravity for all pixels that are DIFFERENT from the supplied (background) value" | pixCount weighted xAndY | xAndY _ (Array with: (self xTallyPixelValue: pv orNot: not) with: (self yTallyPixelValue: pv orNot: not)) collect: [:profile | "For both x and y profiles..." pixCount _ 0. weighted _ 0. profile doWithIndex: [:t :i | pixCount _ pixCount + t. weighted _ weighted + (t*i)]. pixCount = 0 "Produce average of nPixels weighted by coordinate" ifTrue: [0.0] ifFalse: [weighted asFloat / pixCount asFloat - 1.0]]. ^ xAndY first @ xAndY last " | f cg | [Sensor anyButtonPressed] whileFalse: [f _ Form fromDisplay: (Sensor cursorPoint extent: 50@50). cg _ f cgForPixelValue: (Color black pixelValueForDepth: f depth) orNot: false. f displayAt: 0@0. Display fill: (cg extent: 2@2) fillColor: Color red]. ScheduledControllers restore "! ! !Form methodsFor: 'analyzing' stamp: 'jm 12/5/97 19:48'! colorsUsed "Return a list of the Colors this form uses." | tallies tallyDepth usedColors | tallies _ self tallyPixelValues. tallyDepth _ (tallies size log: 2) asInteger. usedColors _ OrderedCollection new. tallies doWithIndex: [:count :i | count > 0 ifTrue: [ usedColors add: (Color colorFromPixelValue: i - 1 depth: tallyDepth)]]. ^ usedColors asArray ! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/17/2001 15:40'! dominantColor | tally max maxi | self depth > 16 ifTrue: [^(self asFormOfDepth: 16) dominantColor]. tally _ self tallyPixelValues. max _ maxi _ 0. tally withIndexDo: [:n :i | n > max ifTrue: [max _ n. maxi _ i]]. ^ Color colorFromPixelValue: maxi - 1 depth: self depth! ! !Form methodsFor: 'analyzing'! innerPixelRectFor: pv orNot: not "Return a rectangle describing the smallest part of me that includes all pixels of value pv. Note: If orNot is true, then produce a copy that includes all pixels that are DIFFERENT from the supplied (background) value" | xTally yTally | xTally _ self xTallyPixelValue: pv orNot: not. yTally _ self yTallyPixelValue: pv orNot: not. ^ ((xTally findFirst: [:t | t>0]) - 1) @ ((yTally findFirst: [:t | t>0]) - 1) corner: (xTally findLast: [:t | t>0])@(yTally findLast: [:t | t>0])! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/17/2001 15:40'! pixelCompare: aRect with: otherForm at: otherLoc "Compare the selected bits of this form (those within aRect) against those in a similar rectangle of otherFrom. Return the sum of the absolute value of the differences of the color values of every pixel. Obviously, this is most useful for rgb (16- or 32-bit) pixels but, in the case of 8-bits or less, this will return the sum of the differing bits of the corresponding pixel values (somewhat less useful)" | pixPerWord temp | pixPerWord _ 32//self depth. (aRect left\\pixPerWord = 0 and: [aRect right\\pixPerWord = 0]) ifTrue: ["If word-aligned, use on-the-fly difference" ^ (BitBlt current toForm: self) copy: aRect from: otherLoc in: otherForm fillColor: nil rule: 32]. "Otherwise, combine in a word-sized form and then compute difference" temp _ self copy: aRect. temp copy: aRect from: otherLoc in: otherForm rule: 21. ^ (BitBlt current toForm: temp) copy: aRect from: otherLoc in: nil fillColor: (Bitmap with: 0) rule: 32 " Dumb example prints zero only when you move over the original rectangle... | f diff | f _ Form fromUser. [Sensor anyButtonPressed] whileFalse: [diff _ f pixelCompare: f boundingBox with: Display at: Sensor cursorPoint. diff printString , ' ' displayAt: 0@0] "! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/17/2001 15:42'! primCountBits "Count the non-zero pixels of this form." self depth > 8 ifTrue: [^(self asFormOfDepth: 8) primCountBits]. ^ (BitBlt current toForm: self) fillColor: (Bitmap with: 0); destRect: (0@0 extent: width@height); combinationRule: 32; copyBits! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/17/2001 15:37'! rectangleEnclosingPixelsNotOfColor: aColor "Answer the smallest rectangle enclosing all the pixels of me that are different from the given color. Useful for extracting a foreground graphic from its background." | cm slice copyBlt countBlt top bottom newH left right | "map the specified color to 1 and all others to 0" cm _ Bitmap new: (1 bitShift: (self depth min: 15)). cm primFill: 1. cm at: (aColor indexInMap: cm) put: 0. "build a 1-pixel high horizontal slice and BitBlts for counting pixels of interest" slice _ Form extent: width@1 depth: 1. copyBlt _ (BitBlt current toForm: slice) sourceForm: self; combinationRule: Form over; destX: 0 destY: 0 width: width height: 1; colorMap: cm. countBlt _ (BitBlt current toForm: slice) fillColor: (Bitmap with: 0); destRect: (0@0 extent: slice extent); combinationRule: 32. "scan in from top and bottom" top _ (0 to: height) detect: [:y | copyBlt sourceOrigin: 0@y; copyBits. countBlt copyBits > 0] ifNone: [^ 0@0 extent: 0@0]. bottom _ (height - 1 to: top by: -1) detect: [:y | copyBlt sourceOrigin: 0@y; copyBits. countBlt copyBits > 0]. "build a 1-pixel wide vertical slice and BitBlts for counting pixels of interest" newH _ bottom - top + 1. slice _ Form extent: 1@newH depth: 1. copyBlt _ (BitBlt current toForm: slice) sourceForm: self; combinationRule: Form over; destX: 0 destY: 0 width: 1 height: newH; colorMap: cm. countBlt _ (BitBlt current toForm: slice) fillColor: (Bitmap with: 0); destRect: (0@0 extent: slice extent); combinationRule: 32. "scan in from left and right" left _ (0 to: width) detect: [:x | copyBlt sourceOrigin: x@top; copyBits. countBlt copyBits > 0]. right _ (width - 1 to: left by: -1) detect: [:x | copyBlt sourceOrigin: x@top; copyBits. countBlt copyBits > 0]. ^ left@top corner: (right + 1)@(bottom + 1) ! ! !Form methodsFor: 'analyzing' stamp: 'jm 6/18/1999 18:41'! tallyPixelValues "Answer a Bitmap whose elements contain the number of pixels in this Form with the pixel value corresponding to their index. Note that the pixels of multiple Forms can be tallied together using tallyPixelValuesInRect:into:." ^ self tallyPixelValuesInRect: self boundingBox into: (Bitmap new: (1 bitShift: (self depth min: 15))) " Move a little rectangle around the screen and print its tallies... | r tallies nonZero | Cursor blank showWhile: [ [Sensor anyButtonPressed] whileFalse: [r _ Sensor cursorPoint extent: 10@10. Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil. tallies _ (Display copy: r) tallyPixelValues. nonZero _ (1 to: tallies size) select: [:i | (tallies at: i) > 0] thenCollect: [:i | (tallies at: i) -> (i-1)]. nonZero printString , ' ' displayAt: 0@0. Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil]] " ! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/28/2000 12:09'! tallyPixelValuesInRect: destRect into: valueTable "Tally the selected pixels of this Form into valueTable, a Bitmap of depth 2^depth similar to a color map. Answer valueTable." (BitBlt current toForm: self) sourceForm: self; "src must be given for color map ops" sourceOrigin: 0@0; tallyMap: valueTable; combinationRule: 33; destRect: destRect; copyBits. ^ valueTable " Move a little rectangle around the screen and print its tallies... | r tallies nonZero | Cursor blank showWhile: [ [Sensor anyButtonPressed] whileFalse: [r _ Sensor cursorPoint extent: 10@10. Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil. tallies _ (Display copy: r) tallyPixelValues. nonZero _ (1 to: tallies size) select: [:i | (tallies at: i) > 0] thenCollect: [:i | (tallies at: i) -> (i-1)]. nonZero printString , ' ' displayAt: 0@0. Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil]] "! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/28/2000 12:09'! xTallyPixelValue: pv orNot: not "Return an array of the number of pixels with value pv by x-value. Note that if not is true, then this will tally those different from pv." | cm slice countBlt copyBlt | cm _ self newColorMap. "Map all colors but pv to zero" not ifTrue: [cm atAllPut: 1]. "... or all but pv to one" cm at: pv+1 put: 1 - (cm at: pv+1). slice _ Form extent: 1@height. copyBlt _ (BitBlt current destForm: slice sourceForm: self halftoneForm: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: 0@0 extent: 1 @ slice height clipRect: slice boundingBox) colorMap: cm. countBlt _ (BitBlt current toForm: slice) fillColor: (Bitmap with: 0); destRect: (0@0 extent: slice extent); combinationRule: 32. ^ (0 to: width-1) collect: [:x | copyBlt sourceOrigin: x@0; copyBits. countBlt copyBits]! ! !Form methodsFor: 'analyzing' stamp: 'ar 5/28/2000 12:09'! yTallyPixelValue: pv orNot: not "Return an array of the number of pixels with value pv by y-value. Note that if not is true, then this will tally those different from pv." | cm slice copyBlt countBlt | cm _ self newColorMap. "Map all colors but pv to zero" not ifTrue: [cm atAllPut: 1]. "... or all but pv to one" cm at: pv+1 put: 1 - (cm at: pv+1). slice _ Form extent: width@1. copyBlt _ (BitBlt current destForm: slice sourceForm: self halftoneForm: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: 0@0 extent: slice width @ 1 clipRect: slice boundingBox) colorMap: cm. countBlt _ (BitBlt current toForm: slice) fillColor: (Bitmap with: 0); destRect: (0@0 extent: slice extent); combinationRule: 32. ^ (0 to: height-1) collect: [:y | copyBlt sourceOrigin: 0@y; copyBits. countBlt copyBits]! ! !Form methodsFor: 'bordering' stamp: 'ar 5/28/2000 12:07'! border: rect width: borderWidth rule: rule fillColor: fillColor "Paint a border whose rectangular area is defined by rect. The width of the border of each side is borderWidth. Uses fillColor for drawing the border." | blt | blt _ (BitBlt current toForm: self) combinationRule: rule; fillColor: fillColor. blt sourceOrigin: 0@0. blt destOrigin: rect origin. blt width: rect width; height: borderWidth; copyBits. blt destY: rect corner y - borderWidth; copyBits. blt destY: rect origin y + borderWidth. blt height: rect height - borderWidth - borderWidth; width: borderWidth; copyBits. blt destX: rect corner x - borderWidth; copyBits! ! !Form methodsFor: 'bordering' stamp: 'ar 5/17/2001 15:42'! borderFormOfWidth: borderWidth sharpCorners: sharpen "Smear this form around and then subtract the original to produce an outline. If sharpen is true, then cause right angles to be outlined by right angles (takes an additional diagonal smears ANDed with both horizontal and vertical smears)." | smearForm bigForm smearPort all cornerForm cornerPort nbrs | self depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms." bigForm _ self deepCopy. all _ bigForm boundingBox. smearForm _ Form extent: self extent. smearPort _ BitBlt current toForm: smearForm. sharpen ifTrue: [cornerForm _ Form extent: self extent. cornerPort _ BitBlt current toForm: cornerForm]. nbrs _ (0@0) fourNeighbors. 1 to: borderWidth do: [:i | "Iterate to get several layers of 'skin'" nbrs do: [:d | "Smear the self in 4 directions to grow each layer of skin" smearPort copyForm: bigForm to: d rule: Form under]. sharpen ifTrue: ["Special treatment to smear sharp corners" nbrs with: ((2 to: 5) collect: [:i2 | nbrs atWrap: i2]) do: [:d1 :d2 | "Copy corner points diagonally" cornerPort copyForm: bigForm to: d1+d2 rule: Form over. "But only preserve if there were dots on either side" cornerPort copyForm: bigForm to: d1+d1+d2 rule: Form and. cornerPort copyForm: bigForm to: d1+d2+d2 rule: Form and. smearPort copyForm: cornerForm to: 0@0 rule: Form under]. ]. bigForm copy: all from: 0@0 in: smearForm rule: Form over. ]. "Now erase the original shape to obtain the outline" bigForm copy: all from: 0@0 in: self rule: Form erase. ^ bigForm! ! !Form methodsFor: 'bordering'! borderWidth: anInteger "Set the width of the border for the receiver to be anInteger and paint it using black as the border color." self border: self boundingBox width: anInteger fillColor: Color black! ! !Form methodsFor: 'bordering'! borderWidth: anInteger color: aMask "Set the width of the border for the receiver to be anInteger and paint it using aMask as the border color." self border: self boundingBox width: anInteger fillColor: aMask! ! !Form methodsFor: 'bordering'! borderWidth: anInteger fillColor: aMask "Set the width of the border for the receiver to be anInteger and paint it using aMask as the border color." self border: self boundingBox width: anInteger fillColor: aMask! ! !Form methodsFor: 'bordering' stamp: 'di 10/21/2001 09:39'! shapeBorder: aColor width: borderWidth "A simplified version for shapes surrounded by transparency (as SketchMorphs). Note also this returns a new form that may be larger, and does not affect the original." | shapeForm borderForm newForm | newForm _ Form extent: self extent + (borderWidth*2) depth: self depth. newForm fillColor: Color transparent. self displayOn: newForm at: (0@0) + borderWidth. "First identify the shape in question as a B/W form" shapeForm _ (newForm makeBWForm: Color transparent) reverse. "Now find the border of that shape" borderForm _ shapeForm borderFormOfWidth: borderWidth sharpCorners: false. "Finally use that shape as a mask to paint the border with color" ^ newForm fillShape: borderForm fillColor: aColor! ! !Form methodsFor: 'bordering'! shapeBorder: aColor width: borderWidth interiorPoint: interiorPoint sharpCorners: sharpen internal: internal "Identify the shape (region of identical color) at interiorPoint, and then add an outline of width=borderWidth and color=aColor. If sharpen is true, then cause right angles to be outlined by right angles. If internal is true, then produce a border that lies within the identified shape. Thus one can put an internal border around the whole background, thus effecting a normal border around every other foreground image." | shapeForm borderForm interiorColor | "First identify the shape in question as a B/W form" interiorColor _ self colorAt: interiorPoint. shapeForm _ (self makeBWForm: interiorColor) reverse findShapeAroundSeedBlock: [:form | form pixelValueAt: interiorPoint put: 1]. "Reverse the image to grow the outline inward" internal ifTrue: [shapeForm reverse]. "Now find the border fo that shape" borderForm _ shapeForm borderFormOfWidth: borderWidth sharpCorners: sharpen. "Finally use that shape as a mask to paint the border with color" self fillShape: borderForm fillColor: aColor! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! balancedPatternFor: aColor "Return the pixel word for representing the given color on the receiver" self hasNonStandardPalette ifTrue:[^self bitPatternFor: aColor] ifFalse:[^aColor balancedPatternForDepth: self depth]! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! bitPatternFor: aColor "Return the pixel word for representing the given color on the receiver" aColor isColor ifFalse:[^aColor bitPatternForDepth: self depth]. self hasNonStandardPalette ifTrue:[^Bitmap with: (self pixelWordFor: aColor)] ifFalse:[^aColor bitPatternForDepth: self depth]! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! colormapFromARGB "Return a ColorMap mapping from canonical ARGB space into the receiver. Note: This version is optimized for Squeak forms." | map nBits | self hasNonStandardPalette ifTrue:[^ColorMap mappingFromARGB: self rgbaBitMasks]. self depth <= 8 ifTrue:[ map _ Color colorMapIfNeededFrom: 32 to: self depth. map size = 512 ifTrue:[nBits _ 3]. map size = 4096 ifTrue:[nBits _ 4]. map size = 32768 ifTrue:[nBits _ 5]. ^ColorMap shifts: (Array with: 3 * nBits - 24 with: 2 * nBits - 16 with: 1 * nBits - 8 with: 0) masks: (Array with: (1 << nBits) - 1 << (24 - nBits) with: (1 << nBits) - 1 << (16 - nBits) with: (1 << nBits) - 1 << (8 - nBits) with: 0) colors: map]. self depth = 16 ifTrue:[ ^ColorMap shifts: #(-9 -6 -3 0) masks: #(16rF80000 16rF800 16rF8 0)]. self depth = 32 ifTrue:[ ^ColorMap shifts: #(0 0 0 0) masks: #(16rFF0000 16rFF00 16rFF 16rFF000000)]. self error:'Bad depth'! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/16/2001 22:23'! colormapIfNeededFor: destForm "Return a ColorMap mapping from the receiver to destForm." (self hasNonStandardPalette or:[destForm hasNonStandardPalette]) ifTrue:[^self colormapFromARGB mappingTo: destForm colormapFromARGB] ifFalse:[^self colormapIfNeededForDepth: destForm depth]! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/17/2001 15:42'! colormapIfNeededForDepth: destDepth "Return a colormap for displaying the receiver at the given depth, or nil if no colormap is needed." self depth = destDepth ifTrue: [^ nil]. "not needed if depths are the same" ^ Color colorMapIfNeededFrom: self depth to: destDepth ! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! colormapToARGB "Return a ColorMap mapping from the receiver into canonical ARGB space." self hasNonStandardPalette ifTrue:[^self colormapFromARGB inverseMap]. self depth <= 8 ifTrue:[ ^ColorMap shifts: #(0 0 0 0) masks: #(16rFF0000 16rFF00 16rFF 16rFF000000) colors: (Color colorMapIfNeededFrom: self depth to: 32)]. self depth = 16 ifTrue:[ ^ColorMap shifts: #( 9 6 3 0) masks: #(16r7C00 16r3E0 16r1F 0)]. self depth = 32 ifTrue:[ ^ColorMap shifts: #(0 0 0 0) masks: #(16rFF0000 16rFF00 16rFF 16rFF000000)]. self error:'Bad depth'! ! !Form methodsFor: 'color mapping'! makeBWForm: foregroundColor "Map this form into a B/W form with 1's in the foreground regions." | bwForm map | bwForm _ Form extent: self extent. map _ self newColorMap. "All non-foreground go to 0's" map at: (foregroundColor indexInMap: map) put: 1. bwForm copyBits: self boundingBox from: self at: 0@0 colorMap: map. ^ bwForm! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/17/2001 15:38'! mapColor: oldColor to: newColor "Make all pixels of the given color in this Form to the given new color." "Warnings: This method modifies the receiver. It may lose some color accuracy on 32-bit Forms, since the transformation uses a color map with only 15-bit resolution." | map | map _ (Color cachedColormapFrom: self depth to: self depth) copy. map at: (oldColor indexInMap: map) put: (newColor pixelWordForDepth: self depth). (BitBlt current toForm: self) sourceForm: self; sourceOrigin: 0@0; combinationRule: Form over; destX: 0 destY: 0 width: width height: height; colorMap: map; copyBits. ! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/17/2001 15:40'! mapColors: oldColorBitsCollection to: newColorBits "Make all pixels of the given color in this Form to the given new color." "Warnings: This method modifies the receiver. It may lose some color accuracy on 32-bit Forms, since the transformation uses a color map with only 15-bit resolution." | map | self depth < 16 ifTrue: [map _ (Color cachedColormapFrom: self depth to: self depth) copy] ifFalse: [ "use maximum resolution color map" "source is 16-bit or 32-bit RGB; use colormap with 5 bits per color component" map _ Color computeRGBColormapFor: self depth bitsPerColor: 5]. oldColorBitsCollection do:[ :oldColor | map at: oldColor put: newColorBits]. (BitBlt current toForm: self) sourceForm: self; sourceOrigin: 0@0; combinationRule: Form over; destX: 0 destY: 0 width: width height: height; colorMap: map; copyBits. ! ! !Form methodsFor: 'color mapping' stamp: 'ar 12/14/2001 18:11'! maskingMap "Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero." ^Color maskingMap: self depth! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/17/2001 15:41'! newColorMap "Return an uninitialized color map array appropriate to this Form's depth." ^ Bitmap new: (1 bitShift: (self depth min: 15)) ! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! pixelValueFor: aColor "Return the pixel word for representing the given color on the receiver" self hasNonStandardPalette ifTrue:[^self colormapFromARGB mapPixel: (aColor pixelValueForDepth: 32)] ifFalse:[^aColor pixelValueForDepth: self depth]! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/15/2001 16:16'! pixelWordFor: aColor "Return the pixel word for representing the given color on the receiver" | basicPattern | self hasNonStandardPalette ifFalse:[^aColor pixelWordForDepth: self depth]. basicPattern _ self pixelValueFor: aColor. self depth = 32 ifTrue:[^basicPattern] ifFalse:[^aColor pixelWordFor: self depth filledWith: basicPattern]! ! !Form methodsFor: 'color mapping' stamp: 'di 10/16/2001 15:23'! reducedPaletteOfSize: nColors "Return an array of colors of size nColors, such that those colors represent well the pixel values actually found in this form." | threshold tallies colorTallies dist delta palette cts top cluster | tallies _ self tallyPixelValues. "An array of tallies for each pixel value" threshold _ width * height // 500. "Make an array of (color -> tally) for all tallies over threshold" colorTallies _ Array streamContents: [:s | tallies withIndexDo: [:v :i | v >= threshold ifTrue: [s nextPut: (Color colorFromPixelValue: i-1 depth: depth) -> v]]]. "Extract a set of clusters by picking the top tally, and then removing all others whose color is within dist of it. Iterate the process, adjusting dist until we get nColors." dist _ 0.2. delta _ dist / 2. [cts _ colorTallies copy. palette _ Array streamContents: [:s | [cts isEmpty] whileFalse: [top _ cts detectMax: [:a | a value]. cluster _ cts select: [:a | (a key diff: top key) < dist]. s nextPut: top key -> (cluster detectSum: [:a | a value]). cts _ cts copyWithoutAll: cluster]]. palette size = nColors or: [delta < 0.001]] whileFalse: [palette size > nColors ifTrue: [dist _ dist + delta] ifFalse: [dist _ dist - delta]. delta _ delta / 2]. ^ palette collect: [:a | a key] ! ! !Form methodsFor: 'color mapping' stamp: 'ar 5/27/2000 20:14'! rgbaBitMasks "Return the masks for specifying the R,G,B, and A components in the receiver" self depth <= 8 ifTrue:[^#(16rFF0000 16rFF00 16rFF 16rFF000000)]. self depth = 16 ifTrue:[^#(16r7C00 16r3E0 16r1F 16r0)]. self depth = 32 ifTrue:[^#(16rFF0000 16rFF00 16rFF 16rFF000000)]. self error:'Bad depth for form'! ! !Form methodsFor: 'converting' stamp: 'jm 11/12/97 19:28'! as8BitColorForm "Simple conversion of zero pixels to transparent. Force it to 8 bits." | f map | f _ ColorForm extent: self extent depth: 8. self displayOn: f at: self offset negated. map _ Color indexedColors copy. map at: 1 put: Color transparent. f colors: map. f offset: self offset. ^ f ! ! !Form methodsFor: 'converting' stamp: 'RAA 8/14/2000 10:13'! asCursorForm ^ self as: StaticForm! ! !Form methodsFor: 'converting' stamp: 'ar 6/16/2002 17:44'! asFormOfDepth: d | newForm | d = self depth ifTrue:[^self]. newForm _ Form extent: self extent depth: d. (BitBlt current toForm: newForm) colorMap: (self colormapIfNeededFor: newForm); copy: (self boundingBox) from: 0@0 in: self fillColor: nil rule: Form over. ^newForm! ! !Form methodsFor: 'converting' stamp: 'ar 5/17/2001 15:39'! asGrayScale "Assume the receiver is a grayscale image. Return a grayscale ColorForm computed by extracting the brightness levels of one color component. This technique allows a 32-bit Form to be converted to an 8-bit ColorForm to save space while retaining a full 255 levels of gray. (The usual colormapping technique quantizes to 8, 16, or 32 levels, which loses information.)" | f32 srcForm result map bb grays | self depth = 32 ifFalse: [ f32 _ Form extent: width@height depth: 32. self displayOn: f32. ^ f32 asGrayScale]. self unhibernate. srcForm _ Form extent: (width * 4)@height depth: 8. srcForm bits: bits. result _ ColorForm extent: width@height depth: 8. map _ Bitmap new: 256. 2 to: 256 do: [:i | map at: i put: i - 1]. map at: 1 put: 1. "map zero pixel values to near-black" bb _ (BitBlt current toForm: result) sourceForm: srcForm; combinationRule: Form over; colorMap: map. 0 to: width - 1 do: [:dstX | bb sourceRect: (((dstX * 4) + 2)@0 extent: 1@height); destOrigin: dstX@0; copyBits]. "final BitBlt to zero-out pixels that were truely transparent in the original" map _ Bitmap new: 512. map at: 1 put: 16rFF. (BitBlt current toForm: result) sourceForm: self; sourceRect: self boundingBox; destOrigin: 0@0; combinationRule: Form erase; colorMap: map; copyBits. grays _ (0 to: 255) collect: [:brightness | Color gray: brightness asFloat / 255.0]. grays at: 1 put: Color transparent. result colors: grays. ^ result ! ! !Form methodsFor: 'converting' stamp: 'jm 4/5/1999 19:20'! colorReduced "Return a color-reduced ColorForm version of the receiver, if possible, or the receiver itself if not." | tally tallyDepth colorCount newForm cm oldPixelValues newFormColors nextColorIndex c | tally _ self tallyPixelValues asArray. tallyDepth _ (tally size log: 2) asInteger. colorCount _ 0. tally do: [:n | n > 0 ifTrue: [colorCount _ colorCount + 1]]. (tally at: 1) = 0 ifTrue: [colorCount _ colorCount + 1]. "include transparent" colorCount > 256 ifTrue: [^ self]. "cannot reduce" newForm _ self formForColorCount: colorCount. "build an array of just the colors used, and a color map to translate old pixel values to their indices into this color array" cm _ Bitmap new: tally size. oldPixelValues _ self colormapIfNeededForDepth: 32. newFormColors _ Array new: colorCount. newFormColors at: 1 put: Color transparent. nextColorIndex _ 2. 2 to: cm size do: [:i | (tally at: i) > 0 ifTrue: [ oldPixelValues = nil ifTrue: [c _ Color colorFromPixelValue: i - 1 depth: tallyDepth] ifFalse: [c _ Color colorFromPixelValue: (oldPixelValues at: i) depth: 32]. newFormColors at: nextColorIndex put: c. cm at: i put: nextColorIndex - 1. "pixel values are zero-based indices" nextColorIndex _ nextColorIndex + 1]]. "copy pixels into new ColorForm, mapping to new pixel values" newForm copyBits: self boundingBox from: self at: 0@0 clippingBox: self boundingBox rule: Form over fillColor: nil map: cm. newForm colors: newFormColors. newForm offset: offset. ^ newForm ! ! !Form methodsFor: 'converting' stamp: 'di 10/16/2001 19:23'! copyWithColorsReducedTo: nColors "Note: this has not been engineered. There are better solutions in the literature." | palette colorMap pc closest | palette _ self reducedPaletteOfSize: nColors. colorMap _ (1 to: (1 bitShift: depth)) collect: [:i | pc _ Color colorFromPixelValue: i-1 depth: depth. closest _ palette detectMin: [:c | c diff: pc]. closest pixelValueForDepth: depth]. ^ self deepCopy copyBits: self boundingBox from: self at: 0@0 colorMap: (colorMap as: Bitmap) ! ! !Form methodsFor: 'converting' stamp: 'ar 7/23/1999 17:04'! orderedDither32To16 "Do an ordered dithering for converting from 32 to 16 bit depth." | ditherMatrix ii out inBits outBits index pv dmv r di dmi dmo g b pvOut outIndex | self depth = 32 ifFalse:[^self error:'Must be 32bit for this']. ditherMatrix _ #( 0 8 2 10 12 4 14 6 3 11 1 9 15 7 13 5). ii _ (0 to: 31) collect:[:i| i]. out _ Form extent: self extent depth: 16. inBits _ self bits. outBits _ out bits. index _ outIndex _ 0. pvOut _ 0. 0 to: self height-1 do:[:y| 0 to: self width-1 do:[:x| pv _ inBits at: (index _ index + 1). dmv _ ditherMatrix at: (y bitAnd: 3) * 4 + (x bitAnd: 3) + 1. r _ pv bitAnd: 255. di _ r * 496 bitShift: -8. dmi _ di bitAnd: 15. dmo _ di bitShift: -4. r _ dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo]. g _ (pv bitShift: -8) bitAnd: 255. di _ g * 496 bitShift: -8. dmi _ di bitAnd: 15. dmo _ di bitShift: -4. g _ dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo]. b _ (pv bitShift: -16) bitAnd: 255. di _ b * 496 bitShift: -8. dmi _ di bitAnd: 15. dmo _ di bitShift: -4. b _ dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo]. pvOut _ (pvOut bitShift: 16) + (b bitShift: 10) + (g bitShift: 5) + r. (x bitAnd: 1) = 1 ifTrue:[ outBits at: (outIndex _ outIndex+1) put: pvOut. pvOut _ 0]. ]. (self width bitAnd: 1) = 1 ifTrue:[ outBits at: (outIndex _ outIndex+1) put: (pvOut bitShift: -16). pvOut _ 0]. ]. ^out! ! !Form methodsFor: 'copying' stamp: 'RAA 9/28/1999 11:20'! blankCopyOf: aRectangle scaledBy: scale ^ self class extent: (aRectangle extent * scale) truncated depth: depth! ! !Form methodsFor: 'copying' stamp: 'ar 6/9/2000 18:59'! contentsOfArea: aRect "Return a new form which derives from the portion of the original form delineated by aRect." ^self contentsOfArea: aRect into: (self class extent: aRect extent depth: depth).! ! !Form methodsFor: 'copying' stamp: 'ar 6/9/2000 19:00'! contentsOfArea: aRect into: newForm "Return a new form which derives from the portion of the original form delineated by aRect." ^ newForm copyBits: aRect from: self at: 0@0 clippingBox: newForm boundingBox rule: Form over fillColor: nil! ! !Form methodsFor: 'copying'! copy: aRect "Return a new form which derives from the portion of the original form delineated by aRect." | newForm | newForm _ self class extent: aRect extent depth: depth. ^ newForm copyBits: aRect from: self at: 0@0 clippingBox: newForm boundingBox rule: Form over fillColor: nil! ! !Form methodsFor: 'copying' stamp: 'ar 5/28/2000 12:08'! copy: destRectangle from: sourcePt in: sourceForm rule: rule "Make up a BitBlt table and copy the bits." (BitBlt current toForm: self) copy: destRectangle from: sourcePt in: sourceForm fillColor: nil rule: rule! ! !Form methodsFor: 'copying'! copy: sourceRectangle from: sourceForm to: destPt rule: rule ^ self copy: (destPt extent: sourceRectangle extent) from: sourceRectangle topLeft in: sourceForm rule: rule! ! !Form methodsFor: 'copying' stamp: 'ar 5/28/2000 12:08'! copyBits: sourceForm at: destOrigin translucent: factor "Make up a BitBlt table and copy the bits with the given colorMap." (BitBlt current destForm: self sourceForm: sourceForm halftoneForm: nil combinationRule: 30 destOrigin: destOrigin sourceOrigin: 0@0 extent: sourceForm extent clipRect: self boundingBox) copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255) " | f f2 f3 | f _ Form fromUser. f2 _ Form fromDisplay: (0@0 extent: f extent). f3 _ f2 deepCopy. 0.0 to: 1.0 by: 1.0/32 do: [:t | f3 _ f2 deepCopy. f3 copyBits: f at: 0@0 translucent: t. f3 displayAt: 0@0. (Delay forMilliseconds: 100) wait]. "! ! !Form methodsFor: 'copying' stamp: 'ar 5/28/2000 12:08'! copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm "Make up a BitBlt table and copy the bits." (BitBlt current destForm: self sourceForm: sourceForm fillColor: aForm combinationRule: rule destOrigin: destOrigin sourceOrigin: sourceRect origin extent: sourceRect extent clipRect: clipRect) copyBits! ! !Form methodsFor: 'copying' stamp: 'ar 5/28/2000 12:08'! copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm map: map "Make up a BitBlt table and copy the bits. Use a colorMap." ((BitBlt current destForm: self sourceForm: sourceForm fillColor: aForm combinationRule: rule destOrigin: destOrigin sourceOrigin: sourceRect origin extent: sourceRect extent clipRect: clipRect) colorMap: map) copyBits! ! !Form methodsFor: 'copying' stamp: 'ar 5/28/2000 12:08'! copyBits: sourceRect from: sourceForm at: destOrigin colorMap: map "Make up a BitBlt table and copy the bits with the given colorMap." ((BitBlt current destForm: self sourceForm: sourceForm halftoneForm: nil combinationRule: Form over destOrigin: destOrigin sourceOrigin: sourceRect origin extent: sourceRect extent clipRect: self boundingBox) colorMap: map) copyBits! ! !Form methodsFor: 'copying' stamp: 'jm 2/27/98 09:35'! deepCopy ^ self shallowCopy bits: bits copy; offset: offset copy ! ! !Form methodsFor: 'copying' stamp: 'tk 8/19/1998 16:11'! veryDeepCopyWith: deepCopier "Return self. I am immutable in the Morphic world. Do not record me." ^ self! ! !Form methodsFor: 'display box access'! boundingBox ^ Rectangle origin: 0 @ 0 corner: width @ height! ! !Form methodsFor: 'display box access'! computeBoundingBox ^ Rectangle origin: 0 @ 0 corner: width @ height! ! !Form methodsFor: 'displaying' stamp: 'ar 2/13/2001 22:13'! displayInterpolatedIn: aRectangle on: aForm "Display the receiver on aForm, using interpolation if necessary. Form fromUser displayInterpolatedOn: Display. Note: When scaling we attempt to use bilinear interpolation based on the 3D engine. If the engine is not there then we use WarpBlt. " | engine adjustedR | self extent = aRectangle extent ifTrue:[^self displayOn: aForm at: aRectangle origin]. Smalltalk at: #B3DRenderEngine ifPresent:[:engineClass| engine _ (engineClass defaultForPlatformOn: aForm)]. engine ifNil:[ "We've got no bilinear interpolation. Use WarpBlt instead" (WarpBlt current toForm: aForm) sourceForm: self destRect: aRectangle; combinationRule: 3; cellSize: 2; warpBits. ^self ]. "Otherwise use the 3D engine for our purposes" "there seems to be a slight bug in B3D which the following adjusts for" adjustedR _ (aRectangle withRight: aRectangle right + 1) translateBy: 0@1. engine viewport: adjustedR. engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white). engine texture: self. engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect). engine finish.! ! !Form methodsFor: 'displaying' stamp: 'ar 2/13/2001 22:12'! displayInterpolatedOn: aForm "Display the receiver on aForm, using interpolation if necessary. Form fromUser displayInterpolatedOn: Display. Note: When scaling we attempt to use bilinear interpolation based on the 3D engine. If the engine is not there then we use WarpBlt. " | engine | self extent = aForm extent ifTrue:[^self displayOn: aForm]. Smalltalk at: #B3DRenderEngine ifPresent:[:engineClass| engine _ (engineClass defaultForPlatformOn: aForm)]. engine ifNil:[ "We've got no bilinear interpolation. Use WarpBlt instead" (WarpBlt current toForm: aForm) sourceForm: self destRect: aForm boundingBox; combinationRule: 3; cellSize: 2; warpBits. ^self ]. "Otherwise use the 3D engine for our purposes" engine viewport: aForm boundingBox. engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white). engine texture: self. engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect). engine finish.! ! !Form methodsFor: 'displaying' stamp: 'ar 5/14/2001 23:33'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm aDisplayMedium copyBits: self boundingBox from: self at: aDisplayPoint + self offset clippingBox: clipRectangle rule: rule fillColor: aForm map: (self colormapIfNeededFor: aDisplayMedium). ! ! !Form methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm "Graphically, it means nothing to scale a Form by floating point values. Because scales and other display parameters are kept in floating point to minimize round off errors, we are forced in this routine to round off to the nearest integer." | absolutePoint scale magnifiedForm | absolutePoint _ displayTransformation applyTo: relativePoint. absolutePoint _ absolutePoint x asInteger @ absolutePoint y asInteger. displayTransformation noScale ifTrue: [magnifiedForm _ self] ifFalse: [scale _ displayTransformation scale. scale _ scale x @ scale y. (1@1 = scale) ifTrue: [scale _ nil. magnifiedForm _ self] ifFalse: [magnifiedForm _ self magnify: self boundingBox by: scale]]. magnifiedForm displayOn: aDisplayMedium at: absolutePoint - alignmentPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm! ! !Form methodsFor: 'displaying'! displayOnPort: port at: location port copyForm: self to: location rule: Form over! ! !Form methodsFor: 'displaying' stamp: 'ar 5/17/2001 15:40'! displayResourceFormOn: aForm "a special display method for blowing up resource thumbnails" | engine tx cmap blitter | self extent = aForm extent ifTrue:[^self displayOn: aForm]. Smalltalk at: #B3DRenderEngine ifPresentAndInMemory: [:engineClass | engine _ engineClass defaultForPlatformOn: aForm]. engine ifNil:[ "We've got no bilinear interpolation. Use WarpBlt instead" (WarpBlt current toForm: aForm) sourceForm: self destRect: aForm boundingBox; combinationRule: 3; cellSize: 2; warpBits. ^self ]. tx _ self asTexture. (blitter _ BitBlt current toForm: tx) sourceForm: self; destRect: aForm boundingBox; sourceOrigin: 0@0; combinationRule: Form paint. "map transparency to current World background color" (World color respondsTo: #pixelWordForDepth:) ifTrue: [ cmap _ Bitmap new: (self depth <= 8 ifTrue: [1 << self depth] ifFalse: [4096]). cmap at: 1 put: (tx pixelWordFor: World color). blitter colorMap: cmap. ]. blitter copyBits. engine viewport: aForm boundingBox. engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white). engine texture: tx. engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect). engine finish. "the above, using bilinear interpolation doesn't leave transparent pixel values intact" (WarpBlt current toForm: aForm) sourceForm: self destRect: aForm boundingBox; combinationRule: Form and; colorMap: (Color maskingMap: self depth); warpBits.! ! !Form methodsFor: 'displaying' stamp: 'ar 3/2/2001 21:32'! displayScaledOn: aForm "Display the receiver on aForm, scaling if necessary. Form fromUser displayScaledOn: Display. " self extent = aForm extent ifTrue:[^self displayOn: aForm]. (WarpBlt current toForm: aForm) sourceForm: self destRect: aForm boundingBox; combinationRule: Form paint; cellSize: 2; warpBits.! ! !Form methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:08'! drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm "Refer to the comment in DisplayMedium|drawLine:from:to:clippingBox:rule:mask:." | dotSetter | "set up an instance of BitBlt for display" dotSetter _ BitBlt current destForm: self sourceForm: sourceForm fillColor: aForm combinationRule: anInteger destOrigin: beginPoint sourceOrigin: 0 @ 0 extent: sourceForm extent clipRect: clipRect. dotSetter drawFrom: beginPoint to: endPoint! ! !Form methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:08'! paintBits: sourceForm at: destOrigin translucent: factor "Make up a BitBlt table and copy the bits with the given colorMap." (BitBlt current destForm: self sourceForm: sourceForm halftoneForm: nil combinationRule: 31 destOrigin: destOrigin sourceOrigin: 0@0 extent: sourceForm extent clipRect: self boundingBox) copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255) " | f f2 f3 | f _ Form fromUser. f replaceColor: f peripheralColor withColor: Color transparent. f2 _ Form fromDisplay: (0@0 extent: f extent). f3 _ f2 deepCopy. 0.0 to: 1.0 by: 1.0/32 do: [:t | f3 _ f2 deepCopy. f3 paintBits: f at: 0@0 translucent: t. f3 displayAt: 0@0. (Delay forMilliseconds: 100) wait]. "! ! !Form methodsFor: 'displaying' stamp: 'BG 10/28/2003 20:58'! setAsBackground "Set this form as a background image." Smalltalk isMorphic ifFalse: [ScheduledControllers screenController model form: self. Display restoreAfter: []]! ! !Form methodsFor: 'encoding' stamp: 'RAA 7/29/2000 09:01'! addDeltasFrom: previousForm (BitBlt destForm: self sourceForm: previousForm fillColor: nil combinationRule: Form reverse destOrigin: 0@0 sourceOrigin: 0@0 extent: self extent clipRect: self boundingBox) copyBits. ^self! ! !Form methodsFor: 'encoding' stamp: 'RAA 7/29/2000 09:01'! deltaFrom: previousForm | newForm | newForm _ previousForm deepCopy. (BitBlt destForm: newForm sourceForm: self fillColor: nil combinationRule: Form reverse destOrigin: 0@0 sourceOrigin: 0@0 extent: self extent clipRect: self boundingBox) copyBits. ^newForm! ! !Form methodsFor: 'encoding' stamp: 'RAA 8/1/2000 06:15'! deltaFrom: smallerForm at: offsetInMe | newForm | newForm _ smallerForm deepCopy. (BitBlt destForm: newForm sourceForm: self fillColor: nil combinationRule: Form reverse destOrigin: 0@0 sourceOrigin: offsetInMe extent: smallerForm extent clipRect: newForm boundingBox) copyBits. ^newForm! ! !Form methodsFor: 'encoding' stamp: 'RAA 8/13/2000 15:32'! encodeForRemoteCanvas | header binaryForm | "encode into a bitstream for use with RemoteCanvas. The format does not require invoking the Compiler" header := String streamContents: [ :str | str "nextPutAll: 'F|';" nextPutAll: self depth printString; nextPut: $,; nextPutAll: self width printString; nextPut: $,; nextPutAll: self height printString; nextPut: $|. ]. binaryForm := ByteArray streamContents: [ :str | self unhibernate. bits writeOn: str. ]. ^header, binaryForm asString ! ! !Form methodsFor: 'fileIn/Out' stamp: 'di 8/5/1998 11:37'! hibernate "Replace my bitmap with a compactly encoded representation (a ByteArray). It is vital that BitBlt and any other access to the bitmap (such as writing to a file) not be used when in this state. Since BitBlt will fail if the bitmap size is wrong (not = bitsSize), we do not allow replacement by a byteArray of the same (or larger) size." "NOTE: This method copies code from Bitmap compressToByteArray so that it can nil out the old bits during the copy, thus avoiding 2x need for extra storage." | compactBits lastByte | (bits isMemberOf: Bitmap) ifFalse: [^ self "already hibernated or weird state"]. compactBits _ ByteArray new: (bits size*4) + 7 + (bits size//1984*3). lastByte _ bits compress: bits toByteArray: compactBits. lastByte < (bits size*4) ifTrue: [bits _ nil. "Let GC reclaim the old bits before the copy if necessary" bits _ compactBits copyFrom: 1 to: lastByte]! ! !Form methodsFor: 'fileIn/Out' stamp: 'di 3/15/1999 14:50'! printOn: aStream aStream nextPutAll: self class name; nextPut: $(; print: width; nextPut: $x; print: height; nextPut: $x; print: depth; nextPut: $). ! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:44'! readAttributesFrom: aBinaryStream | offsetX offsetY | depth _ aBinaryStream next. (self depth isPowerOfTwo and: [self depth between: 1 and: 32]) ifFalse: [self error: 'invalid depth; bad Form file?']. width _ aBinaryStream nextWord. height _ aBinaryStream nextWord. offsetX _ aBinaryStream nextWord. offsetY _ aBinaryStream nextWord. offsetX > 32767 ifTrue: [offsetX _ offsetX - 65536]. offsetY > 32767 ifTrue: [offsetY _ offsetY - 65536]. offset _ Point x: offsetX y: offsetY. ! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:43'! readBitsFrom: aBinaryStream bits _ Bitmap newFromStream: aBinaryStream. bits size = self bitsSize ifFalse: [self error: 'wrong bitmap size; bad Form file?']. ^ self ! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:44'! readFrom: aBinaryStream "Reads the receiver from the given binary stream with the format: depth, extent, offset, bits." self readAttributesFrom: aBinaryStream. self readBitsFrom: aBinaryStream! ! !Form methodsFor: 'fileIn/Out' stamp: 'jm 3/27/98 16:54'! readFromOldFormat: aBinaryStream "Read a Form in the original ST-80 format." | w h offsetX offsetY newForm theBits pos | self error: 'this method must be updated to read into 32-bit word bitmaps'. w _ aBinaryStream nextWord. h _ aBinaryStream nextWord. offsetX _ aBinaryStream nextWord. offsetY _ aBinaryStream nextWord. offsetX > 32767 ifTrue: [offsetX _ offsetX - 65536]. offsetY > 32767 ifTrue: [offsetY _ offsetY - 65536]. newForm _ Form extent: w @ h offset: offsetX @ offsetY. theBits _ newForm bits. pos _ 0. 1 to: w + 15 // 16 do: [:j | 1 to: h do: [:i | theBits at: (pos _ pos+1) put: aBinaryStream nextWord]]. newForm bits: theBits. ^ newForm ! ! !Form methodsFor: 'fileIn/Out' stamp: 'ar 2/24/2001 22:39'! replaceByResource: aForm "Replace the receiver by some resource that just got loaded" (self extent = aForm extent and:[self depth = aForm depth]) ifTrue:[ bits _ aForm bits. ].! ! !Form methodsFor: 'fileIn/Out' stamp: 'nk 12/31/2003 16:06'! store15To24HexBitsOn:aStream | buf i lineWidth | "write data for 16-bit form, optimized for encoders writing directly to files to do one single file write rather than 12. I'm not sure I understand the significance of the shifting pattern, but I think I faithfully translated it from the original" lineWidth _ 0. buf _ String new: 12. bits do: [:word | i _ 0. "upper pixel" buf at: (i _ i + 1) put: ((word bitShift: -27) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -32) bitAnd: 8) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -22) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -27) bitAnd: 8) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -17) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -22) bitAnd: 8) asHexDigit. "lower pixel" buf at: (i _ i + 1) put: ((word bitShift: -11) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -16) bitAnd: 8) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -6) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -11) bitAnd: 8) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -1) bitAnd: 15) asHexDigit. buf at: (i _ i + 1) put: ((word bitShift: -6) bitAnd: 8) asHexDigit. aStream nextPutAll: buf. lineWidth _ lineWidth + 12. lineWidth > 100 ifTrue: [ aStream cr. lineWidth _ 0 ]. "#( 31 26 21 15 10 5 ) do:[:startBit | ]" ].! ! !Form methodsFor: 'fileIn/Out'! store32To24HexBitsOn:aStream ^self storeBits:20 to:0 on:aStream.! ! !Form methodsFor: 'fileIn/Out'! storeBits:startBit to:stopBit on:aStream bits storeBits:startBit to:stopBit on:aStream.! ! !Form methodsFor: 'fileIn/Out'! storeBitsOn:aStream base:anInteger bits do: [:word | anInteger = 10 ifTrue: [aStream space] ifFalse: [aStream crtab: 2]. word printOn: aStream base: anInteger]. ! ! !Form methodsFor: 'fileIn/Out'! storeHexBitsOn:aStream ^self storeBits:28 to:0 on:aStream.! ! !Form methodsFor: 'fileIn/Out'! storeOn: aStream self storeOn: aStream base: 10! ! !Form methodsFor: 'fileIn/Out'! storeOn: aStream base: anInteger "Store the receiver out as an expression that can be evaluated to recreate a Form with the same contents as the original." self unhibernate. aStream nextPut: $(. aStream nextPutAll: self species name. aStream crtab: 1. aStream nextPutAll: 'extent: '. self extent printOn: aStream. aStream crtab: 1. aStream nextPutAll: 'depth: '. self depth printOn: aStream. aStream crtab: 1. aStream nextPutAll: 'fromArray: #('. self storeBitsOn:aStream base:anInteger. aStream nextPut: $). aStream crtab: 1. aStream nextPutAll: 'offset: '. self offset printOn: aStream. aStream nextPut: $). ! ! !Form methodsFor: 'fileIn/Out' stamp: 'ar 3/3/2001 15:50'! unhibernate "If my bitmap has been compressed into a ByteArray, then expand it now, and return true." | resBits | bits isForm ifTrue:[ resBits _ bits. bits _ Bitmap new: self bitsSize. resBits displayResourceFormOn: self. ^true]. bits == nil ifTrue:[bits _ Bitmap new: self bitsSize. ^true]. (bits isMemberOf: ByteArray) ifTrue: [bits _ Bitmap decompressFromByteArray: bits. ^ true]. ^ false! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:35'! writeAttributesOn: file self unhibernate. file nextPut: depth. file nextWordPut: width. file nextWordPut: height. file nextWordPut: ((self offset x) >=0 ifTrue: [self offset x] ifFalse: [self offset x + 65536]). file nextWordPut: ((self offset y) >=0 ifTrue: [self offset y] ifFalse: [self offset y + 65536]). ! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:35'! writeBitsOn: file bits writeOn: file! ! !Form methodsFor: 'fileIn/Out' stamp: 'mu 8/17/2003 00:36'! writeOn: file "Write the receiver on the file in the format depth, extent, offset, bits." self writeAttributesOn: file. self writeBitsOn: file! ! !Form methodsFor: 'fileIn/Out' stamp: 'di 7/6/1998 23:00'! writeOnMovie: file "Write just my bits on the file." self unhibernate. bits writeUncompressedOn: file! ! !Form methodsFor: 'fileIn/Out' stamp: 'tk 2/19/1999 07:30'! writeUncompressedOn: file "Write the receiver on the file in the format depth, extent, offset, bits. Warning: Caller must put header info on file!! Use writeUncompressedOnFileNamed: instead." self unhibernate. file binary. file nextPut: depth. file nextWordPut: width. file nextWordPut: height. file nextWordPut: ((self offset x) >=0 ifTrue: [self offset x] ifFalse: [self offset x + 65536]). file nextWordPut: ((self offset y) >=0 ifTrue: [self offset y] ifFalse: [self offset y + 65536]). bits writeUncompressedOn: file! ! !Form methodsFor: 'filling' stamp: 'di 2/19/1999 07:07'! anyShapeFill "Fill the interior of the outermost outlined region in the receiver, a 1-bit deep form. Typically the resulting form is used with fillShape:fillColor: to paint a solid color. See also convexShapeFill:" | shape | "Draw a seed line around the edge and fill inward from the outside." shape _ self findShapeAroundSeedBlock: [:f | f borderWidth: 1]. "Reverse so that this becomes solid in the middle" shape _ shape reverse. "Finally erase any bits from the original so the fill is only elsewhere" shape copy: shape boundingBox from: self to: 0@0 rule: Form erase. ^ shape! ! !Form methodsFor: 'filling'! bitPatternForDepth: suspectedDepth "Only called when a Form is being used as a fillColor. Use a Pattern or InfiniteForm instead for this purpose. 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" ^ self! ! !Form methodsFor: 'filling' stamp: 'di 9/11/1998 16:25'! convexShapeFill: aMask "Fill the interior of the outtermost outlined region in the receiver. The outlined region must not be concave by more than 90 degrees. Typically aMask is Color black, to produce a solid fill. then the resulting form is used with fillShape: to paint a solid color. See also anyShapeFill" | destForm tempForm | destForm _ Form extent: self extent. destForm fillBlack. tempForm _ Form extent: self extent. (0@0) fourNeighbors do: [:dir | "Smear self in all 4 directions, and AND the result" self displayOn: tempForm at: (0@0) - self offset. tempForm smear: dir distance: (dir dotProduct: tempForm extent) abs. tempForm displayOn: destForm at: 0@0 clippingBox: destForm boundingBox rule: Form and fillColor: nil]. destForm displayOn: self at: 0@0 clippingBox: self boundingBox rule: Form over fillColor: aMask! ! !Form methodsFor: 'filling' stamp: 'di 10/17/2001 10:09'! eraseShape: bwForm "use bwForm as a mask to clear all pixels where bwForm has 1's" ((BitBlt current destForm: self sourceForm: bwForm fillColor: nil combinationRule: Form erase1bitShape "Cut a hole in the picture with my mask" destOrigin: bwForm offset sourceOrigin: 0@0 extent: self extent clipRect: self boundingBox) colorMap: (Bitmap with: 0 with: 16rFFFFFFFF)) copyBits. ! ! !Form methodsFor: 'filling' stamp: 'ar 5/28/2000 12:08'! fill: aRectangle rule: anInteger fillColor: aForm "Replace a rectangular area of the receiver with the pattern described by aForm according to the rule anInteger." (BitBlt current toForm: self) copy: aRectangle from: 0@0 in: nil fillColor: aForm rule: anInteger! ! !Form methodsFor: 'filling'! fillFromXColorBlock: colorBlock "Horizontal Gradient Fill. Supply relative x in [0.0 ... 1.0] to colorBlock, and paint each pixel with the color that comes back" | xRel | 0 to: width-1 do: [:x | xRel _ x asFloat / (width-1) asFloat. self fill: (x@0 extent: 1@height) fillColor: (colorBlock value: xRel)] " ((Form extent: 100@100 depth: Display depth) fillFromXColorBlock: [:x | Color r: x g: 0.0 b: 0.5]) display "! ! !Form methodsFor: 'filling' stamp: 'ar 5/17/2001 15:38'! fillFromXYColorBlock: colorBlock "General Gradient Fill. Supply relative x and y in [0.0 ... 1.0] to colorBlock, and paint each pixel with the color that comes back" | poker yRel xRel | poker _ BitBlt current bitPokerToForm: self. 0 to: height-1 do: [:y | yRel _ y asFloat / (height-1) asFloat. 0 to: width-1 do: [:x | xRel _ x asFloat / (width-1) asFloat. poker pixelAt: x@y put: ((colorBlock value: xRel value: yRel) pixelWordForDepth: self depth)]] " | d | ((Form extent: 100@20 depth: Display depth) fillFromXYColorBlock: [:x :y | d _ 1.0 - (x - 0.5) abs - (y - 0.5) abs. Color r: d g: 0 b: 1.0-d]) display "! ! !Form methodsFor: 'filling'! fillFromYColorBlock: colorBlock "Vertical Gradient Fill. Supply relative y in [0.0 ... 1.0] to colorBlock, and paint each pixel with the color that comes back" | yRel | 0 to: height-1 do: [:y | yRel _ y asFloat / (height-1) asFloat. self fill: (0@y extent: width@1) fillColor: (colorBlock value: yRel)] " ((Form extent: 100@100 depth: Display depth) fillFromYColorBlock: [:y | Color r: y g: 0.0 b: 0.5]) display "! ! !Form methodsFor: 'filling' stamp: 'ar 5/17/2001 15:38'! findShapeAroundSeedBlock: seedBlock "Build a shape that is black in any region marked by seedBlock. SeedBlock will be supplied a form, in which to blacken various pixels as 'seeds'. Then the seeds are smeared until there is no change in the smear when it fills the region, ie, when smearing hits a black border and thus goes no further." | smearForm previousSmear all count smearPort | self depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms." all _ self boundingBox. smearForm _ Form extent: self extent. smearPort _ BitBlt current toForm: smearForm. seedBlock value: smearForm. "Blacken seeds to be smeared" smearPort copyForm: self to: 0@0 rule: Form erase. "Clear any in black" previousSmear _ smearForm deepCopy. count _ 1. [count = 10 and: "check for no change every 10 smears" [count _ 1. previousSmear copy: all from: 0@0 in: smearForm rule: Form reverse. previousSmear isAllWhite]] whileFalse: [smearPort copyForm: smearForm to: 1@0 rule: Form under. smearPort copyForm: smearForm to: -1@0 rule: Form under. "After horiz smear, trim around the region border" smearPort copyForm: self to: 0@0 rule: Form erase. smearPort copyForm: smearForm to: 0@1 rule: Form under. smearPort copyForm: smearForm to: 0@-1 rule: Form under. "After vert smear, trim around the region border" smearPort copyForm: self to: 0@0 rule: Form erase. count _ count+1. count = 9 ifTrue: "Save penultimate smear for comparison" [previousSmear copy: all from: 0@0 in: smearForm rule: Form over]]. "Now paint the filled region in me with aHalftone" ^ smearForm! ! !Form methodsFor: 'filling' stamp: 'ar 5/14/2001 23:46'! floodFill2: aColor at: interiorPoint "Fill the shape (4-connected) at interiorPoint. The algorithm is based on Paul Heckbert's 'A Seed Fill Algorithm', Graphic Gems I, Academic Press, 1990. NOTE: This is a less optimized variant for flood filling which is precisely along the lines of Heckbert's algorithm. For almost all cases #floodFill:at: will be faster (see the comment there) but this method is left in both as reference and as a fallback if such a strange case is encountered in reality." | peeker poker stack old new x y top x1 x2 dy left goRight | peeker _ BitBlt current bitPeekerFromForm: self. poker _ BitBlt current bitPokerToForm: self. stack _ OrderedCollection new: 50. "read old pixel value" old _ peeker pixelAt: interiorPoint. "compute new value" new _ self pixelValueFor: aColor. old = new ifTrue:[^self]. "no point, is there?!!" x _ interiorPoint x. y _ interiorPoint y. (y >= 0 and:[y < height]) ifTrue:[ stack addLast: {y. x. x. 1}. "y, left, right, dy" stack addLast: {y+1. x. x. -1}]. [stack isEmpty] whileFalse:[ top _ stack removeLast. y _ top at: 1. x1 _ top at: 2. x2 _ top at: 3. dy _ top at: 4. y _ y + dy. "Segment of scanline (y-dy) for x1 <= x <= x2 was previously filled. Now explore adjacent pixels in scanline y." x _ x1. [x >= 0 and:[(peeker pixelAt: x@y) = old]] whileTrue:[ poker pixelAt: x@y put: new. x _ x - 1]. goRight _ x < x1. left _ x+1. (left < x1 and:[y-dy >= 0 and:[y-dy < height]]) ifTrue:[stack addLast: {y. left. x1-1. 0-dy}]. goRight ifTrue:[x _ x1 + 1]. [ goRight ifTrue:[ [x < width and:[(peeker pixelAt: x@y) = old]] whileTrue:[ poker pixelAt: x@y put: new. x _ x + 1]. (y+dy >= 0 and:[y+dy < height]) ifTrue:[stack addLast: {y. left. x-1. dy}]. (x > (x2+1) and:[y-dy >= 0 and:[y-dy >= 0]]) ifTrue:[stack addLast: {y. x2+1. x-1. 0-dy}]]. [(x _ x + 1) <= x2 and:[(peeker pixelAt: x@y) ~= old]] whileTrue. left _ x. goRight _ true. x <= x2] whileTrue. ]. ! ! !Form methodsFor: 'filling' stamp: 'di 10/20/2001 10:09'! floodFillMapFrom: sourceForm to: scanlineForm mappingColorsWithin: dist to: centerPixVal "This is a helper routine for floodFill. It's written for clarity (scanning the entire map using colors) rather than speed (which would require hacking rgb components in the nieghborhood of centerPixVal. Note that some day a better proximity metric would be (h s v) where tolerance could be reduced in hue." | colorMap centerColor | scanlineForm depth = 32 ifFalse: [self error: 'depth 32 assumed']. "First get a modifiable identity map" colorMap _ (Color cachedColormapFrom: sourceForm depth to: scanlineForm depth) copy. centerColor _ Color colorFromPixelValue: (centerPixVal bitOr: 16rFFe6) depth: scanlineForm depth. "Now replace all entries that are close to the centerColor" 1 to: colorMap size do: [:i | ((Color colorFromPixelValue: ((colorMap at: i) bitOr: 16rFFe6) depth: scanlineForm depth) diff: centerColor) <= dist ifTrue: [colorMap at: i put: centerPixVal]]. ^ colorMap! ! !Form methodsFor: 'filling' stamp: 'di 10/17/2001 10:10'! shapeFill: aColor interiorPoint: interiorPoint "Identify the shape (region of identical color) at interiorPoint, and then fill that shape with the new color, aColor : modified di's original method such that it returns the bwForm, for potential use by the caller" | bwForm interiorPixVal map ppd color ind | self depth = 1 ifTrue: [^ self shapeFill: aColor seedBlock: [:form | form pixelValueAt: interiorPoint put: 1]]. "First map this form into a B/W form with 0's in the interior region." "bwForm _ self makeBWForm: interiorColor." "won't work for two whites" interiorPixVal _ self pixelValueAt: interiorPoint. bwForm _ Form extent: self extent. map _ Bitmap new: (1 bitShift: (self depth min: 12)). "Not calling newColorMap. All non-foreground go to 0. Length is 2 to 4096." ppd _ self depth. "256 long color map in depth 8 is not one of the following cases" 3 to: 5 do: [:bitsPerColor | (2 raisedTo: bitsPerColor*3) = map size ifTrue: [ppd _ bitsPerColor*3]]. "ready for longer maps than 512" ppd <= 8 ifTrue: [map at: interiorPixVal+1 put: 1] ifFalse: [interiorPixVal = 0 ifFalse: [color _ Color colorFromPixelValue: interiorPixVal depth: self depth. ind _ color pixelValueForDepth: ppd. map at: ind+1 put: 1] ifTrue: [map at: 1 put: 1]]. bwForm copyBits: self boundingBox from: self at: 0@0 colorMap: map. bwForm reverse. "Make interior region be 0's" "Now fill the interior region and return that shape" bwForm _ bwForm findShapeAroundSeedBlock: [:form | form pixelValueAt: interiorPoint put: 1]. "Finally use that shape as a mask to flood the region with color" self eraseShape: bwForm. self fillShape: bwForm fillColor: aColor. ^ bwForm! ! !Form methodsFor: 'filling' stamp: 'ar 5/17/2001 15:38'! shapeFill: aColor seedBlock: seedBlock self depth > 1 ifTrue: [self error: 'This call only meaningful for B/W forms']. (self findShapeAroundSeedBlock: seedBlock) displayOn: self at: 0@0 clippingBox: self boundingBox rule: Form under fillColor: aColor ! ! !Form methodsFor: 'image manipulation' stamp: 'ar 5/17/2001 15:40'! replaceColor: oldColor withColor: newColor "Replace one color with another everywhere is this form" | cm newInd target ff | self depth = 32 ifTrue: [cm _ (Color cachedColormapFrom: 16 to: 32) copy] ifFalse: [cm _ Bitmap new: (1 bitShift: (self depth min: 15)). 1 to: cm size do: [:i | cm at: i put: i - 1]]. newInd _ newColor pixelValueForDepth: self depth. cm at: (oldColor pixelValueForDepth: (self depth min: 16))+1 put: newInd. target _ newColor isTransparent ifTrue: [ff _ Form extent: self extent depth: depth. ff fillWithColor: newColor. ff] ifFalse: [self]. (BitBlt current toForm: target) sourceForm: self; sourceOrigin: 0@0; combinationRule: Form paint; destX: 0 destY: 0 width: width height: height; colorMap: cm; copyBits. newColor = Color transparent ifTrue: [target displayOn: self].! ! !Form methodsFor: 'image manipulation' stamp: 'ar 5/28/2000 12:09'! smear: dir distance: dist "Smear any black pixels in this form in the direction dir in Log N steps" | skew bb | bb _ BitBlt current destForm: self sourceForm: self fillColor: nil combinationRule: Form under destOrigin: 0@0 sourceOrigin: 0@0 extent: self extent clipRect: self boundingBox. skew _ 1. [skew < dist] whileTrue: [bb destOrigin: dir*skew; copyBits. skew _ skew+skew]! ! !Form methodsFor: 'image manipulation' stamp: 'jm 6/30/1999 15:36'! trimBordersOfColor: aColor "Answer a copy of this Form with each edge trimmed in to the first pixel that is not of the given color. (That is, border strips of the given color are removed)." | r | r _ self rectangleEnclosingPixelsNotOfColor: aColor. ^ self copy: r ! ! !Form methodsFor: 'initialize-release' stamp: 'ar 5/17/2001 22:54'! allocateForm: extentPoint "Allocate a new form which is similar to the receiver and can be used for accelerated blts" ^Form extent: extentPoint depth: self nativeDepth! ! !Form methodsFor: 'initialize-release' stamp: 'ar 5/26/2000 00:46'! finish "If there are any pending operations on the receiver complete them. Do not return before all modifications have taken effect."! ! !Form methodsFor: 'initialize-release' stamp: 'ar 5/26/2000 00:45'! flush "If there are any pending operations on the receiver start doing them. In time, they will show up on the receiver but not necessarily immediately after this method returns."! ! !Form methodsFor: 'initialize-release'! fromDisplay: aRectangle "Create a virtual bit map from a user specified rectangular area on the display screen. Reallocates bitmap only if aRectangle ~= the receiver's extent." (width = aRectangle width and: [height = aRectangle height]) ifFalse: [self setExtent: aRectangle extent depth: depth]. self copyBits: (aRectangle origin extent: self extent) from: Display at: 0 @ 0 clippingBox: self boundingBox rule: Form over fillColor: nil! ! !Form methodsFor: 'initialize-release' stamp: 'ar 5/28/2000 18:45'! shutDown "The system is going down. Try to preserve some space" self hibernate! ! !Form methodsFor: 'initialize-release' stamp: 'ar 6/16/2002 18:39'! swapEndianness "Swap from big to little endian pixels and vice versa" depth := 0 - depth.! ! !Form methodsFor: 'other' stamp: 'ar 12/12/2003 18:24'! fixAlpha "Fix the alpha channel if the receiver is 32bit" | bb | self depth = 32 ifFalse:[^self]. bb := BitBlt toForm: self. bb combinationRule: 40 "fixAlpha:with:". bb copyBits.! ! !Form methodsFor: 'other' stamp: 'jm 9/27/97 21:02'! formForColorCount: colorCount "Return a ColorForm of sufficient depth to represent the given number of colors. The maximum number of colors is 256." colorCount > 256 ifTrue: [^ self error: 'too many colors']. colorCount > 16 ifTrue: [^ ColorForm extent: self extent depth: 8]. colorCount > 4 ifTrue: [^ ColorForm extent: self extent depth: 4]. colorCount > 2 ifTrue: [^ ColorForm extent: self extent depth: 2]. ^ ColorForm extent: self extent depth: 1 ! ! !Form methodsFor: 'other' stamp: 'sw 5/3/2001 16:23'! graphicForViewerTab "Answer the graphic to be used in the tab of a viewer open on me" ^ self! ! !Form methodsFor: 'other' stamp: 'jm 1/6/98 10:37'! primPrintHScale: hScale vScale: vScale landscape: aBoolean "On platforms that support it, this primitive prints the receiver, assumed to be a Form, to the default printer." "(Form extent: 10@10) primPrintHScale: 1.0 vScale: 1.0 landscape: true" <primitive: 232> self primitiveFailed ! ! !Form methodsFor: 'other' stamp: 'RAA 1/30/2002 16:42'! relativeTextAnchorPosition ^nil "so forms can be in TextAnchors"! ! !Form methodsFor: 'pixel access' stamp: 'ar 5/17/2001 15:42'! colorAt: aPoint "Return the color in the pixel at the given point. " ^ Color colorFromPixelValue: (self pixelValueAt: aPoint) depth: self depth ! ! !Form methodsFor: 'pixel access' stamp: 'ar 5/14/2001 23:46'! colorAt: aPoint put: aColor "Store a Color into the pixel at coordinate aPoint. " self pixelValueAt: aPoint put: (self pixelValueFor: aColor). "[Sensor anyButtonPressed] whileFalse: [Display colorAt: Sensor cursorPoint put: Color red]" ! ! !Form methodsFor: 'pixel access' stamp: 'ar 5/17/2001 15:39'! isTransparentAt: aPoint "Return true if the receiver is transparent at the given point." self depth = 1 ifTrue: [^ false]. "no transparency at depth 1" ^ (self pixelValueAt: aPoint) = (self pixelValueFor: Color transparent) ! ! !Form methodsFor: 'pixel access' stamp: 'ar 5/28/2000 12:08'! pixelValueAt: aPoint "Return the raw pixel value at the given point. This pixel value depends on the receiver's depth. Typical clients use colorAt: to get a Color. " ^ (BitBlt current bitPeekerFromForm: self) pixelAt: aPoint ! ! !Form methodsFor: 'pixel access' stamp: 'ar 5/28/2000 12:08'! pixelValueAt: aPoint put: pixelValue "Store the given raw pixel value at the given point. Typical clients use colorAt:put: to store a color. " (BitBlt current bitPokerToForm: self) pixelAt: aPoint put: pixelValue. ! ! !Form methodsFor: 'postscript generation' stamp: 'ar 5/17/2001 15:36'! bitsPerComponent ^self depth <= 8 ifTrue:[self depth] ifFalse:[8]. ! ! !Form methodsFor: 'postscript generation' stamp: 'mpw 11/14/1999 22:22'! bytesPerRow ^ self numComponents * self paddedWidth * self bitsPerComponent / 8.! ! !Form methodsFor: 'postscript generation' stamp: 'ar 5/17/2001 15:39'! decodeArray ^self depth <= 8 ifTrue:['[1 0]'] ifFalse:['[0 1 0 1 0 1 ]']. ! ! !Form methodsFor: 'postscript generation' stamp: 'RAA 4/20/2001 15:40'! encodePostscriptOn: aStream self unhibernate. "since current Postscript support treats 8-bit forms as 0 to 255 gray scale, convert to 16 first so we get more faithful results" self depth <= 8 ifTrue: [^(self asFormOfDepth: 16) encodePostscriptOn: aStream]. ^ self printPostscript: aStream operator: (self depth = 1 ifTrue: ['imagemask'] ifFalse: ['image'])! ! !Form methodsFor: 'postscript generation' stamp: 'ar 5/17/2001 15:43'! numComponents ^self depth <= 8 ifTrue:[1] ifFalse:[3]. ! ! !Form methodsFor: 'postscript generation'! paddedWidth ^ (self width + (self rowPadding-1)// self rowPadding) * self rowPadding.! ! !Form methodsFor: 'postscript generation' stamp: 'nk 12/31/2003 15:46'! printPostscript: aStream operator: operator aStream preserveStateDuring: [:inner | inner rectclip: (0 @ 0 extent: width @ height). self setColorspaceOn: inner. inner print: '[ '; cr; print: '/ImageType 1'; cr; print: '/ImageMatrix [1 0 0 1 0 0]'; cr; print: '/MultipleDataSources false'; cr; print: '/DataSource level1 { { currentfile '; write: self bytesPerRow; print: ' string readhexstring pop }} bind { currentfile /ASCIIHexDecode filter } ifelse'; cr; print: '/Width '; write: self paddedWidth; cr; print: '/Height '; write: self height; cr; print: '/Decode '; print: self decodeArray; cr; print: '/BitsPerComponent '; write: self bitsPerComponent; cr; print: 'makeDict '; print: operator; cr. self storePostscriptHexOn: inner. inner print: $>; cr. inner cr]. aStream cr! ! !Form methodsFor: 'postscript generation' stamp: 'mpw 11/15/1999 08:34'! rowPadding ^ 32 // self depth! ! !Form methodsFor: 'postscript generation'! setColorspaceOn:aStream self numComponents = 1 ifTrue:[aStream print:'/DeviceGray setcolorspace 0 setgray'; cr.] ifFalse:[aStream print:'/DeviceRGB setcolorspace'; cr.].! ! !Form methodsFor: 'postscript generation' stamp: 'nk 12/31/2003 15:46'! storePostscriptHexOn: inner self depth <= 8 ifTrue: [self storeHexBitsOn: inner]. self depth = 16 ifTrue: [self store15To24HexBitsOn: inner]. self depth = 32 ifTrue: [self store32To24HexBitsOn: inner]! ! !Form methodsFor: 'resources' stamp: 'ar 12/9/2002 16:04'! readNativeResourceFrom: byteStream | img aStream | (byteStream isKindOf: FileStream) ifTrue:[ "Ugly, but ImageReadWriter will send #reset which is implemented as #reopen and we may not be able to do so." aStream _ RWBinaryOrTextStream with: byteStream contents. ] ifFalse:[ aStream _ byteStream. ]. img _ [ImageReadWriter formFromStream: aStream] on: Error do:[:ex| nil]. img ifNil:[^nil]. (img isColorForm and:[self isColorForm]) ifTrue:[ | cc | cc := img colors. img colors: nil. img displayOn: self. img colors: cc. ] ifFalse:[ img displayOn: self. ]. img _ nil.! ! !Form methodsFor: 'resources' stamp: 'sd 6/28/2003 09:48'! readResourceFrom: aStream "Store a resource representation of the receiver on aStream. Must be specific to the receiver so that no code is filed out." | bitsSize msb | (aStream next: 4) asString = self resourceTag ifFalse:[ aStream position: aStream position - 4. ^self readNativeResourceFrom: aStream]. width _ aStream nextNumber: 4. height _ aStream nextNumber: 4. depth _ aStream nextNumber: 4. bitsSize _ aStream nextNumber: 4. bitsSize = 0 ifFalse:[ bits _ aStream next: bitsSize. ^self]. msb _ (aStream nextNumber: 4) = 1. bitsSize _ aStream nextNumber: 4. bits _ Bitmap new: self bitsSize. (Form extent: width@height depth: depth bits: (aStream next: bitsSize * 4)) displayOn: self. msb = Smalltalk isBigEndian ifFalse:[ Bitmap swapBytesIn: bits from: 1 to: bits size. ].! ! !Form methodsFor: 'resources' stamp: 'ar 2/27/2001 14:56'! resourceTag ^'FORM'! ! !Form methodsFor: 'resources' stamp: 'sd 9/30/2003 13:41'! storeResourceOn: aStream "Store a resource representation of the receiver on aStream. Must be specific to the receiver so that no code is filed out." self hibernate. aStream nextPutAll: self resourceTag asByteArray. "tag" aStream nextNumber: 4 put: width. aStream nextNumber: 4 put: height. aStream nextNumber: 4 put: depth. (bits isMemberOf: ByteArray) ifFalse:[ "must store bitmap" aStream nextNumber: 4 put: 0. "tag" aStream nextNumber: 4 put: (SmalltalkImage current isBigEndian ifTrue:[1] ifFalse:[0]). ]. aStream nextNumber: 4 put: bits size. aStream nextPutAll: bits. ! ! !Form methodsFor: 'scaling, rotation' stamp: 'ar 5/14/2001 23:33'! flipBy: direction centerAt: aPoint "Return a copy of the receiver flipped either #vertical or #horizontal." | newForm quad | newForm _ self class extent: self extent depth: depth. quad _ self boundingBox innerCorners. quad _ (direction = #vertical ifTrue: [#(2 1 4 3)] ifFalse: [#(4 3 2 1)]) collect: [:i | quad at: i]. (WarpBlt current toForm: newForm) sourceForm: self; colorMap: (self colormapIfNeededFor: newForm); combinationRule: 3; copyQuad: quad toRect: newForm boundingBox. newForm offset: (self offset flipBy: direction centerAt: aPoint). ^ newForm " [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) flipBy: #vertical centerAt: 0@0) display] " "Consistency test... | f f2 p | [Sensor anyButtonPressed] whileFalse: [f _ Form fromDisplay: ((p _ Sensor cursorPoint) extent: 31@41). Display fillBlack: (p extent: 31@41). f2 _ f flipBy: #vertical centerAt: 0@0. (f2 flipBy: #vertical centerAt: 0@0) displayAt: p] " ! ! !Form methodsFor: 'scaling, rotation'! magnify: aRectangle by: scale "Answer a Form created as a scaling of the receiver. Scale may be a Float, and may be greater or less than 1.0." ^ self magnify: aRectangle by: scale smoothing: 1 "Dynamic test... [Sensor anyButtonPressed] whileFalse: [(Display magnify: (Sensor cursorPoint extent: 31@41) by: 5@3) display] " "Scaling test... | f cp | f _ Form fromDisplay: (Rectangle originFromUser: 100@100). Display restoreAfter: [Sensor waitNoButton. [Sensor anyButtonPressed] whileFalse: [cp _ Sensor cursorPoint. (f magnify: f boundingBox by: (cp x asFloat@cp y asFloat)/f extent) display]] " "Consistency test... | f f2 p | [Sensor anyButtonPressed] whileFalse: [f _ Form fromDisplay: ((p _ Sensor cursorPoint) extent: 31@41). Display fillBlack: (p extent: 31@41). f2 _ f magnify: f boundingBox by: 5@3. (f2 shrink: f2 boundingBox by: 5@3) displayAt: p] " ! ! !Form methodsFor: 'scaling, rotation' stamp: 'ar 5/14/2001 23:33'! magnify: aRectangle by: scale smoothing: cellSize "Answer a Form created as a scaling of the receiver. Scale may be a Float, and may be greater or less than 1.0." | newForm | newForm _ self blankCopyOf: aRectangle scaledBy: scale. (WarpBlt current toForm: newForm) sourceForm: self; colorMap: (self colormapIfNeededFor: newForm); cellSize: cellSize; "installs a new colormap if cellSize > 1" combinationRule: 3; copyQuad: aRectangle innerCorners toRect: newForm boundingBox. ^ newForm "Dynamic test... [Sensor anyButtonPressed] whileFalse: [(Display magnify: (Sensor cursorPoint extent: 131@81) by: 0.5 smoothing: 2) display] " "Scaling test... | f cp | f _ Form fromDisplay: (Rectangle originFromUser: 100@100). Display restoreAfter: [Sensor waitNoButton. [Sensor anyButtonPressed] whileFalse: [cp _ Sensor cursorPoint. (f magnify: f boundingBox by: (cp x asFloat@cp y asFloat)/f extent smoothing: 2) display]] "! ! !Form methodsFor: 'scaling, rotation' stamp: 'di 8/17/1998 22:17'! magnifyBy: scale "Answer a Form created as a scaling of the receiver. Scale may be a Float, and may be greater or less than 1.0." ^ self magnify: self boundingBox by: scale smoothing: (scale < 1 ifTrue: [2] ifFalse: [1])! ! !Form methodsFor: 'scaling, rotation'! rotateBy: deg "Rotate the receiver by the indicated number of degrees." "rot is the destination form, bit enough for any angle." ^ self rotateBy: deg smoothing: 1 " | a f | f _ Form fromDisplay: (0@0 extent: 200@200). a _ 0. [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: (a _ a+5)) display]. f display "! ! !Form methodsFor: 'scaling, rotation' stamp: 'ar 5/14/2001 23:33'! rotateBy: direction centerAt: aPoint "Return a rotated copy of the receiver. direction = #none, #right, #left, or #pi" | newForm quad rot | direction == #none ifTrue: [^ self]. newForm _ self class extent: (direction = #pi ifTrue: [width@height] ifFalse: [height@width]) depth: depth. quad _ self boundingBox innerCorners. rot _ #(right pi left) indexOf: direction. (WarpBlt current toForm: newForm) sourceForm: self; colorMap: (self colormapIfNeededFor: newForm); combinationRule: 3; copyQuad: ((1+rot to: 4+rot) collect: [:i | quad atWrap: i]) toRect: newForm boundingBox. newForm offset: (self offset rotateBy: direction centerAt: aPoint). ^ newForm " [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: #left centerAt: 0@0) display] " "Consistency test... | f f2 p | [Sensor anyButtonPressed] whileFalse: [f _ Form fromDisplay: ((p _ Sensor cursorPoint) extent: 31@41). Display fillBlack: (p extent: 31@41). f2 _ f rotateBy: #left centerAt: 0@0. (f2 rotateBy: #right centerAt: 0@0) displayAt: p] " ! ! !Form methodsFor: 'scaling, rotation' stamp: 'ar 5/14/2001 23:33'! rotateBy: deg magnify: scale smoothing: cellSize "Rotate the receiver by the indicated number of degrees and magnify. " "rot is the destination form, big enough for any angle." | side rot warp r1 pts p bigSide | side _ 1 + ((width*width) + (height*height)) asFloat sqrt asInteger. bigSide _ (side * scale) rounded. rot _ Form extent: bigSide@bigSide depth: self depth. warp _ (WarpBlt current toForm: rot) sourceForm: self; colorMap: (self colormapIfNeededFor: rot); cellSize: cellSize; "installs a new colormap if cellSize > 1" combinationRule: Form paint. r1 _ (0@0 extent: side@side) align: (side@side)//2 with: self boundingBox center. "Rotate the corners of the source rectangle." pts _ r1 innerCorners collect: [:pt | p _ pt - r1 center. (r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @ (r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))]. warp copyQuad: pts toRect: rot boundingBox. ^ rot " | a f | f _ Form fromDisplay: (0@0 extent: 200@200). a _ 0. [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: (a _ a+5) magnify: 0.75 smoothing: 2) display]. f display "! ! !Form methodsFor: 'scaling, rotation' stamp: 'ar 5/14/2001 23:34'! rotateBy: deg smoothing: cellSize "Rotate the receiver by the indicated number of degrees." "rot is the destination form, bit enough for any angle." | side rot warp r1 pts p center | side _ 1 + ((width*width) + (height*height)) asFloat sqrt asInteger. rot _ Form extent: side@side depth: self depth. center _ rot extent // 2. "Now compute the sin and cos constants for the rotation angle." warp _ (WarpBlt current toForm: rot) sourceForm: self; colorMap: (self colormapIfNeededFor: rot); cellSize: cellSize; "installs a new colormap if cellSize > 1" combinationRule: Form over. r1 _ rot boundingBox align: center with: self boundingBox center. pts _ r1 innerCorners collect: [:pt | p _ pt - r1 center. (r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @ (r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))]. warp copyQuad: pts toRect: rot boundingBox. ^ rot " | a f | f _ Form fromDisplay: (0@0 extent: 200@200). a _ 0. [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: (a _ a+5) smoothing: 2) display]. f display "! ! !Form methodsFor: 'scaling, rotation' stamp: 'RAA 7/13/2000 12:09'! scaledToSize: newExtent | scale | newExtent = self extent ifTrue: [^self]. scale _ newExtent x / self width min: newExtent y / self height. ^self magnify: self boundingBox by: scale smoothing: 2. ! ! !Form methodsFor: 'scaling, rotation'! shrink: aRectangle by: scale | scalePt | scalePt _ scale asPoint. ^ self magnify: aRectangle by: (1.0 / scalePt x asFloat) @ (1.0 / scalePt y asFloat)! ! !Form methodsFor: 'testing' stamp: 'RAA 1/19/2001 15:04'! appearsToBeSameCostumeAs: anotherForm (anotherForm isKindOf: self class) ifFalse: [^false]. anotherForm depth = self depth ifFalse: [^false]. ^anotherForm bits = bits ! ! !Form methodsFor: 'testing' stamp: 'ar 5/15/2001 16:14'! hasNonStandardPalette "Return true if the receiver has a non-standard palette. Non-standard means that RGBA components may be located at positions differing from the standard Squeak RGBA layout at the receiver's depth." ^false! ! !Form methodsFor: 'testing' stamp: 'di 3/2/98 12:42'! isAllWhite "Answer whether all bits in the receiver are white (=0)." self unhibernate. 1 to: bits size do: [:i | (bits at: i) = 0 ifFalse: [^ false]]. ^ true! ! !Form methodsFor: 'testing' stamp: 'ar 5/17/2001 15:46'! isBigEndian "Return true if the receiver contains big endian pixels, meaning the left-most pixel is stored in the most significant bits of a word." ^depth > 0! ! !Form methodsFor: 'testing' stamp: 'ar 5/28/2000 14:58'! isBltAccelerated: ruleInteger for: sourceForm "Return true if the receiver can perform accelerated blts operations by itself" ^false! ! !Form methodsFor: 'testing' stamp: 'ar 5/28/2000 15:04'! isDisplayScreen ^false! ! !Form methodsFor: 'testing' stamp: 'ar 5/27/2000 16:54'! isExternalForm ^false! ! !Form methodsFor: 'testing' stamp: 'ar 5/28/2000 14:58'! isFillAccelerated: ruleInteger for: aColor "Return true if the receiver can perform accelerated fill operations by itself" ^false! ! !Form methodsFor: 'testing' stamp: 'ar 10/30/2000 23:23'! isForm ^true! ! !Form methodsFor: 'testing' stamp: 'ar 5/17/2001 15:47'! isLittleEndian "Return true if the receiver contains little endian pixels, meaning the left-most pixel is stored in the least significant bits of a word." ^depth < 0! ! !Form methodsFor: 'testing' stamp: 'RAA 8/14/2000 10:00'! isStatic ^false! ! !Form methodsFor: 'testing' stamp: 'ar 2/10/2004 17:18'! isTranslucent "Answer whether this form may be translucent" ^self depth = 32! ! !Form methodsFor: 'testing' stamp: 'ar 5/28/2000 14:58'! shouldPreserveContents "Return true if the receiver should preserve it's contents when flagged to be clean. Most forms can not be trivially restored by some drawing operation but some may." ^true! ! !Form methodsFor: 'transitions' stamp: 'jm 5/21/1998 23:46'! fadeImage: otherImage at: topLeft indexAndMaskDo: indexAndMaskBlock "This fade uses halftones as a blending hack. Zeros in the halftone produce the original image (self), and ones in the halftone produce the 'otherImage'. IndexAndMaskBlock gets evaluated prior to each cycle, and the resulting boolean determines whether to continue cycling." | index imageRect maskForm resultForm | imageRect _ otherImage boundingBox. resultForm _ self copy: (topLeft extent: imageRect extent). maskForm _ Form extent: 32@32. index _ 0. [indexAndMaskBlock value: (index _ index+1) value: maskForm] whileTrue: [maskForm reverse. resultForm copyBits: imageRect from: resultForm at: 0@0 clippingBox: imageRect rule: Form over fillColor: maskForm. maskForm reverse. resultForm copyBits: imageRect from: otherImage at: 0@0 clippingBox: imageRect rule: Form under fillColor: maskForm. self copyBits: imageRect from: resultForm at: topLeft clippingBox: self boundingBox rule: Form over fillColor: nil. Display forceDisplayUpdate]! ! !Form methodsFor: 'transitions' stamp: 'ar 5/17/2001 15:42'! fadeImageCoarse: otherImage at: topLeft "Display fadeImageCoarse: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40" | pix j d | d _ self depth. ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | i=1 ifTrue: [pix _ (1 bitShift: d) - 1. 1 to: 8//d-1 do: [:q | pix _ pix bitOr: (pix bitShift: d*4)]]. i <= 16 ifTrue: [j _ i-1//4+1. (0 to: 28 by: 4) do: [:k | mask bits at: j+k put: ((mask bits at: j+k) bitOr: (pix bitShift: i-1\\4*d))]. "mask display." true] ifFalse: [false]]! ! !Form methodsFor: 'transitions' stamp: 'ar 5/17/2001 15:41'! fadeImageFine: otherImage at: topLeft "Display fadeImageFine: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40" | pix j ii d | d _ self depth. ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | i=1 ifTrue: [pix _ (1 bitShift: d) - 1. 1 to: 8//d-1 do: [:q | pix _ pix bitOr: (pix bitShift: d*4)]]. i <= 16 ifTrue: [ii _ #(0 10 2 8 7 13 5 15 1 11 3 9 6 12 4 14) at: i. j _ ii//4+1. (0 to: 28 by: 4) do: [:k | mask bits at: j+k put: ((mask bits at: j+k) bitOr: (pix bitShift: ii\\4*d))]. true] ifFalse: [false]]! ! !Form methodsFor: 'transitions'! fadeImageHor: otherImage at: topLeft "Display fadeImageHor: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10" ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | mask fill: (0@(mask height//2-i) extent: mask width@(i*2)) fillColor: Color black. (i*2) <= mask width]! ! !Form methodsFor: 'transitions'! fadeImageHorFine: otherImage at: topLeft "Display fadeImageHorFine: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10" ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | mask fill: (0@(i-1) extent: mask width@1) fillColor: Color black. mask fill: (0@(i-1+16) extent: mask width@1) fillColor: Color black. (i*2) <= mask width]! ! !Form methodsFor: 'transitions'! fadeImageSquares: otherImage at: topLeft "Display fadeImageSquares: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40" ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | mask fill: ((16-i) asPoint extent: (i*2) asPoint) fillColor: Color black. i <= 16]! ! !Form methodsFor: 'transitions' stamp: 'ar 5/17/2001 15:39'! fadeImageVert: otherImage at: topLeft "Display fadeImageVert: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10" | d | d _ self depth. ^ self fadeImage: otherImage at: topLeft indexAndMaskDo: [:i :mask | mask fill: ((mask width//2//d-i*d)@0 extent: i*2*d@mask height) fillColor: Color black. i <= (mask width//d)]! ! !Form methodsFor: 'transitions' stamp: 'jm 6/1/1998 10:55'! pageImage: otherImage at: topLeft corner: corner "Produce a page-turning illusion that gradually reveals otherImage located at topLeft in this form. Corner specifies which corner, as 1=topLeft, 2=topRight, 3=bottomRight, 4=bottomLeft." | bb maskForm resultForm delta maskLoc maskRect stepSize cornerSel smallRect | stepSize _ 10. bb _ otherImage boundingBox. resultForm _ self copy: (topLeft extent: bb extent). maskForm _ Form extent: ((otherImage width min: otherImage height) + stepSize) asPoint. "maskLoc _ starting loc rel to topLeft" otherImage width > otherImage height ifTrue: ["wide image; motion is horizontal." (corner between: 2 and: 3) not ifTrue: ["motion is to the right" delta _ 1@0. maskLoc _ bb topLeft - (corner = 1 ifTrue: [maskForm width@0] ifFalse: [maskForm width@stepSize])] ifFalse: ["motion is to the left" delta _ -1@0. maskLoc _ bb topRight - (corner = 2 ifTrue: [0@0] ifFalse: [0@stepSize])]] ifFalse: ["tall image; motion is vertical." corner <= 2 ifTrue: ["motion is downward" delta _ 0@1. maskLoc _ bb topLeft - (corner = 1 ifTrue: [0@maskForm height] ifFalse: [stepSize@maskForm height])] ifFalse: ["motion is upward" delta _ 0@-1. maskLoc _ bb bottomLeft - (corner = 3 ifTrue: [stepSize@0] ifFalse: [0@0])]]. "Build a solid triangle in the mask form" (Pen newOnForm: maskForm) in: [:p | corner even "Draw 45-degree line" ifTrue: [p place: 0@0; turn: 135; go: maskForm width*3//2] ifFalse: [p place: 0@(maskForm height-1); turn: 45; go: maskForm width*3//2]]. maskForm smear: delta negated distance: maskForm width. "Copy the mask to full resolution for speed. Make it be the reversed so that it can be used for ORing in the page-corner color" maskForm _ (Form extent: maskForm extent depth: otherImage depth) copyBits: maskForm boundingBox from: maskForm at: 0@0 colorMap: (Bitmap with: 16rFFFFFFFF with: 0). "Now move the triangle maskForm across the resultForm selecting the triangular part of otherImage to display, and across the resultForm, selecting the part of the original image to erase." cornerSel _ #(topLeft topRight bottomRight bottomLeft) at: corner. 1 to: (otherImage width + otherImage height // stepSize)+1 do: [:i | "Determine the affected square" maskRect _ (maskLoc extent: maskForm extent) intersect: bb. ((maskLoc x*delta x) + (maskLoc y*delta y)) < 0 ifTrue: [smallRect _ 0@0 extent: (maskRect width min: maskRect height) asPoint. maskRect _ smallRect align: (smallRect perform: cornerSel) with: (maskRect perform: cornerSel)]. "AND otherForm with triangle mask, and OR into result" resultForm copyBits: bb from: otherImage at: 0@0 clippingBox: maskRect rule: Form over fillColor: nil. resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc clippingBox: maskRect rule: Form erase fillColor: nil. resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc clippingBox: maskRect rule: Form under fillColor: Color lightBrown. "Now update Display in a single BLT." self copyBits: maskRect from: resultForm at: topLeft + maskRect topLeft clippingBox: self boundingBox rule: Form over fillColor: nil. Display forceDisplayUpdate. maskLoc _ maskLoc + (delta*stepSize)] " 1 to: 4 do: [:corner | Display pageImage: (Form fromDisplay: (10@10 extent: 200@300)) reverse at: 10@10 corner: corner] " ! ! !Form methodsFor: 'transitions' stamp: 'ar 5/28/2000 12:12'! pageWarp: otherImage at: topLeft forward: forward "Produce a page-turning illusion that gradually reveals otherImage located at topLeft in this form. forward == true means turn pages toward you, else away. [ignored for now]" | pageRect oldPage nSteps buffer p leafRect sourceQuad warp oldBottom d | pageRect _ otherImage boundingBox. oldPage _ self copy: (pageRect translateBy: topLeft). (forward ifTrue: [oldPage] ifFalse: [otherImage]) border: pageRect widthRectangle: (Rectangle left: 0 right: 2 top: 1 bottom: 1) rule: Form over fillColor: Color black. oldBottom _ self copy: ((pageRect bottomLeft + topLeft) extent: (pageRect width@(pageRect height//4))). nSteps _ 8. buffer _ Form extent: otherImage extent + (0@(pageRect height//4)) depth: self depth. d _ pageRect topLeft + (0@(pageRect height//4)) - pageRect topRight. 1 to: nSteps-1 do: [:i | forward ifTrue: [buffer copy: pageRect from: otherImage to: 0@0 rule: Form over. p _ pageRect topRight + (d * i // nSteps)] ifFalse: [buffer copy: pageRect from: oldPage to: 0@0 rule: Form over. p _ pageRect topRight + (d * (nSteps-i) // nSteps)]. buffer copy: oldBottom boundingBox from: oldBottom to: pageRect bottomLeft rule: Form over. leafRect _ pageRect topLeft corner: p x @ (pageRect bottom + p y). sourceQuad _ Array with: pageRect topLeft with: pageRect bottomLeft + (0@p y) with: pageRect bottomRight with: pageRect topRight - (0@p y). warp _ (WarpBlt current toForm: buffer) clipRect: leafRect; sourceForm: (forward ifTrue: [oldPage] ifFalse: [otherImage]); combinationRule: Form paint. warp copyQuad: sourceQuad toRect: leafRect. self copy: buffer boundingBox from: buffer to: topLeft rule: Form over. Display forceDisplayUpdate]. buffer copy: pageRect from: otherImage to: 0@0 rule: Form over. buffer copy: oldBottom boundingBox from: oldBottom to: pageRect bottomLeft rule: Form over. self copy: buffer boundingBox from: buffer to: topLeft rule: Form over. Display forceDisplayUpdate. " 1 to: 4 do: [:corner | Display pageWarp: (Form fromDisplay: (10@10 extent: 200@300)) reverse at: 10@10 forward: false] " ! ! !Form methodsFor: 'transitions' stamp: 'jm 5/21/1998 23:46'! slideImage: otherImage at: topLeft delta: delta "Display slideImage: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40 delta: 3@-4" | bb nSteps clipRect | bb _ otherImage boundingBox. clipRect _ topLeft extent: otherImage extent. nSteps _ 1. delta x = 0 ifFalse: [nSteps _ nSteps max: (bb width//delta x abs) + 1]. delta y = 0 ifFalse: [nSteps _ nSteps max: (bb height//delta y abs) + 1]. 1 to: nSteps do: [:i | self copyBits: bb from: otherImage at: delta*(i-nSteps) + topLeft clippingBox: clipRect rule: Form paint fillColor: nil. Display forceDisplayUpdate]! ! !Form methodsFor: 'transitions' stamp: 'jm 6/18/1998 12:57'! wipeImage: otherImage at: topLeft clippingBox: clipBox rectForIndex: rectForIndexBlock | i clipRect t rectOrList waitTime | i _ 0. clipRect _ topLeft extent: otherImage extent. clipBox ifNotNil: [clipRect _ clipRect intersect: clipBox]. [rectOrList _ rectForIndexBlock value: (i _ i + 1). rectOrList == nil] whileFalse: [ t _ Time millisecondClockValue. rectOrList asOrderedCollection do: [:r | self copyBits: r from: otherImage at: topLeft + r topLeft clippingBox: clipRect rule: Form over fillColor: nil]. Display forceDisplayUpdate. waitTime _ 3 - (Time millisecondClockValue - t). waitTime > 0 ifTrue: ["(Delay forMilliseconds: waitTime) wait"]]. ! ! !Form methodsFor: 'transitions' stamp: 'jm 10/16/97 15:21'! wipeImage: otherImage at: topLeft delta: delta "Display wipeImage: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40 delta: 0@-2" self wipeImage: otherImage at: topLeft delta: delta clippingBox: nil. ! ! !Form methodsFor: 'transitions' stamp: 'jm 10/16/97 15:17'! wipeImage: otherImage at: topLeft delta: delta clippingBox: clipBox | wipeRect bb nSteps | bb _ otherImage boundingBox. wipeRect _ delta x = 0 ifTrue: [delta y = 0 ifTrue: [nSteps _ 1. bb "allow 0@0"] ifFalse: [ nSteps _ bb height//delta y abs + 1. "Vertical movement" delta y > 0 ifTrue: [bb topLeft extent: bb width@delta y] ifFalse: [bb bottomLeft+delta extent: bb width@delta y negated]]] ifFalse: [nSteps _ bb width//delta x abs + 1. "Horizontal movement" delta x > 0 ifTrue: [bb topLeft extent: delta x@bb height] ifFalse: [bb topRight+delta extent: delta x negated@bb height]]. ^ self wipeImage: otherImage at: topLeft clippingBox: clipBox rectForIndex: [:i | i <= nSteps ifTrue: [wipeRect translateBy: (delta* (i-1))] ifFalse: [nil]]! ! !Form methodsFor: 'transitions' stamp: 'di 1/28/1999 09:20'! zoomIn: goingIn orOutTo: otherImage at: topLeft vanishingPoint: vp "Display zoomInTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40. Display zoomOutTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40." | nSteps j bigR lilR minTime startTime lead | nSteps _ 16. minTime _ 500. "milliseconds" startTime _ Time millisecondClockValue. ^ self wipeImage: otherImage at: topLeft clippingBox: nil rectForIndex: [:i | "i runs from 1 to nsteps" i > nSteps ifTrue: [nil "indicates all done"] ifFalse: ["If we are going too fast, delay for a bit" lead _ startTime + (i-1*minTime//nSteps) - Time millisecondClockValue. lead > 10 ifTrue: [(Delay forMilliseconds: lead) wait]. "Return an array with the difference rectangles for this step." j _ goingIn ifTrue: [i] ifFalse: [nSteps+1-i]. bigR _ vp - (vp*(j)//nSteps) corner: vp + (otherImage extent-vp*(j)//nSteps). lilR _ vp - (vp*(j-1)//nSteps) corner: vp + (otherImage extent-vp*(j-1)//nSteps). bigR areasOutside: lilR]]! ! !Form methodsFor: 'transitions' stamp: 'di 3/2/98 09:14'! zoomInTo: otherImage at: topLeft "Display zoomInTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40" ^ self zoomIn: true orOutTo: otherImage at: topLeft vanishingPoint: otherImage extent//2+topLeft! ! !Form methodsFor: 'transitions' stamp: 'di 3/2/98 09:15'! zoomOutTo: otherImage at: topLeft "Display zoomOutTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40" ^ self zoomIn: false orOutTo: otherImage at: topLeft vanishingPoint: otherImage extent//2+topLeft! ! !Form methodsFor: 'private' stamp: 'tk 3/13/2000 15:21'! hackBits: bitThing "This method provides an initialization so that BitBlt may be used, eg, to copy ByteArrays and other non-pointer objects efficiently. The resulting form looks 4 wide, 8 deep, and bitThing-size-in-words high." width _ 4. depth _ 8. bitThing class isBits ifFalse: [self error: 'bitThing must be a non-pointer object']. bitThing class isBytes ifTrue: [height _ bitThing basicSize // 4] ifFalse: [height _ bitThing basicSize]. bits _ bitThing! ! !Form methodsFor: 'private'! initFromArray: array "Fill the bitmap from array. If the array is shorter, then cycle around in its contents until the bitmap is filled." | ax aSize array32 i j word16 | ax _ 0. aSize _ array size. aSize > bits size ifTrue: ["backward compatibility with old 16-bit bitmaps and their forms" array32 _ Array new: height * (width + 31 // 32). i _ j _ 0. 1 to: height do: [:y | 1 to: width+15//16 do: [:x16 | word16 _ array at: (i _ i + 1). x16 odd ifTrue: [array32 at: (j _ j+1) put: (word16 bitShift: 16)] ifFalse: [array32 at: j put: ((array32 at: j) bitOr: word16)]]]. ^ self initFromArray: array32]. 1 to: bits size do: [:index | (ax _ ax + 1) > aSize ifTrue: [ax _ 1]. bits at: index put: (array at: ax)]! ! !Form methodsFor: 'private' stamp: 'ar 12/19/2000 16:23'! privateFloodFillValue: aColor "Private. Compute the pixel value in the receiver's depth but take into account implicit color conversions by BitBlt." | f1 f2 bb | f1 _ Form extent: 1@1 depth: depth. f2 _ Form extent: 1@1 depth: 32. bb _ BitBlt toForm: f1. bb fillColor: aColor; destRect: (0@0 corner: 1@1); combinationRule: 3; copyBits. bb _ BitBlt toForm: f2. bb sourceForm: f1; sourceOrigin: 0@0; destRect: (0@0 corner: 1@1); combinationRule: 3; copyBits. ^f2 pixelValueAt: 0@0.! ! !Form methodsFor: 'private' stamp: '6/9/97 16:10 di'! setExtent: extent depth: bitsPerPixel "Create a virtual bit map with the given extent and bitsPerPixel." width _ extent x asInteger. width < 0 ifTrue: [width _ 0]. height _ extent y asInteger. height < 0 ifTrue: [height _ 0]. depth _ bitsPerPixel. bits _ Bitmap new: self bitsSize! ! !Form methodsFor: 'private' stamp: 'ar 5/28/2000 15:49'! setExtent: extent depth: bitsPerPixel bits: bitmap "Create a virtual bit map with the given extent and bitsPerPixel." width _ extent x asInteger. width < 0 ifTrue: [width _ 0]. height _ extent y asInteger. height < 0 ifTrue: [height _ 0]. depth _ bitsPerPixel. (bits isNil or:[self bitsSize = bitmap size]) ifFalse:[^self error:'Bad dimensions']. bits _ bitmap! ! !Form methodsFor: 'private' stamp: 'ar 10/30/2000 23:22'! setResourceBits: aForm "Private. Really. Used for setting the 'resource bits' when externalizing some form" bits _ aForm.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Form class instanceVariableNames: ''! !Form class methodsFor: 'instance creation' stamp: 'ar 5/28/2000 12:07'! dotOfSize: diameter "Create a form which contains a round black dot." | radius form bb rect centerX centerY centerYBias centerXBias radiusSquared xOverY maxy dx | radius _ diameter//2. form _ self extent: diameter@diameter offset: (0@0) - (radius@radius). bb _ (BitBlt current toForm: form) sourceX: 0; sourceY: 0; combinationRule: Form over; fillColor: Color black. rect _ form boundingBox. centerX _ rect center x. centerY _ rect center y. centerYBias _ rect height odd ifTrue: [0] ifFalse: [1]. centerXBias _ rect width odd ifTrue: [0] ifFalse: [1]. radiusSquared _ (rect height asFloat / 2.0) squared - 0.01. xOverY _ rect width asFloat / rect height asFloat. maxy _ rect height - 1 // 2. "First do the inner fill, and collect x values" 0 to: maxy do: [:dy | dx _ ((radiusSquared - (dy * dy) asFloat) sqrt * xOverY) truncated. bb destX: centerX - centerXBias - dx destY: centerY - centerYBias - dy width: dx + dx + centerXBias + 1 height: 1; copyBits. bb destY: centerY + dy; copyBits]. ^ form " Time millisecondsToRun: [1 to: 20 do: [:i | (Form dotOfSize: i) displayAt: (i*20)@(i*20)]] "! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:27'! extent: extentPoint "Answer an instance of me with a blank bitmap of depth 1." ^ self extent: extentPoint depth: 1 ! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:36'! extent: extentPoint depth: bitsPerPixel "Answer an instance of me with blank bitmap of the given dimensions and depth." ^ self basicNew setExtent: extentPoint depth: bitsPerPixel ! ! !Form class methodsFor: 'instance creation' stamp: 'ar 10/9/1998 23:44'! extent: extentPoint depth: bitsPerPixel bits: aBitmap "Answer an instance of me with blank bitmap of the given dimensions and depth." ^ self basicNew setExtent: extentPoint depth: bitsPerPixel bits: aBitmap! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:35'! extent: extentPoint depth: bitsPerPixel fromArray: anArray offset: offsetPoint "Answer an instance of me with a pixmap of the given depth initialized from anArray." ^ (self extent: extentPoint depth: bitsPerPixel) offset: offsetPoint; initFromArray: anArray ! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:33'! extent: extentPoint fromArray: anArray offset: offsetPoint "Answer an instance of me of depth 1 with bitmap initialized from anArray." ^ (self extent: extentPoint depth: 1) offset: offsetPoint; initFromArray: anArray ! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:28'! extent: extentPoint fromStipple: fourNibbles "Answer an instance of me with bitmap initialized from a repeating 4x4 bit stipple encoded in a 16-bit constant." | nibble | ^ (self extent: extentPoint depth: 1) initFromArray: ((1 to: 4) collect: [:i | nibble _ (fourNibbles bitShift: -4*(4-i)) bitAnd: 16rF. 16r11111111 * nibble]) "fill 32 bits with each 4-bit nibble" ! ! !Form class methodsFor: 'instance creation' stamp: 'jm 3/27/98 16:26'! extent: extentPoint offset: offsetPoint "Answer an instance of me with a blank bitmap of depth 1." ^ (self extent: extentPoint depth: 1) offset: offsetPoint ! ! !Form class methodsFor: 'instance creation' stamp: 'BG 11/11/2003 14:19'! fromBinaryStream: aBinaryStream "Read a Form or ColorForm from given file, using the first byte of the file to guess its format. Currently handles: GIF, uncompressed BMP, and both old and new DisplayObject writeOn: formats, JPEG, and PCX. Return nil if the file could not be read or was of an unrecognized format." | firstByte | aBinaryStream binary. firstByte _ aBinaryStream next. firstByte = 1 ifTrue: [ "old Squeakform format" ^ self new readFromOldFormat: aBinaryStream]. firstByte = 2 ifTrue: [ "new Squeak form format" ^ self new readFrom: aBinaryStream]. "Try for JPG, GIF, or PCX..." "Note: The following call closes the stream." self halt. " ^ ImageReadWriter formFromStream: aBinaryStream " ! ! !Form class methodsFor: 'instance creation'! fromDisplay: aRectangle "Answer an instance of me with bitmap initialized from the area of the display screen defined by aRectangle." ^ (self extent: aRectangle extent depth: Display depth) fromDisplay: aRectangle! ! !Form class methodsFor: 'instance creation'! fromDisplay: aRectangle using: oldForm "Like fromDisplay: only if oldForm is the right size, copy into it and answer it instead." ((oldForm ~~ nil) and: [oldForm extent = aRectangle extent]) ifTrue: [oldForm fromDisplay: aRectangle. ^ oldForm] ifFalse: [^ self fromDisplay: aRectangle]! ! !Form class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:58'! fromFileNamed: fileName "Read a Form or ColorForm from the given file." | file form | file _ (FileStream readOnlyFileNamed: fileName) binary. form _ self fromBinaryStream: file. file close. ^ form ! ! !Form class methodsFor: 'instance creation'! fromUser "Answer an instance of me with bitmap initialized from the area of the display screen designated by the user. The grid for selecting an area is 1@1." ^self fromUser: 1 @ 1! ! !Form class methodsFor: 'instance creation'! fromUser: aPoint "Answer an instance of me with bitmap initialized from the area of the display screen designated by the user. The grid for selecting an area is aPoint." ^ self fromDisplay: (Rectangle fromUser: aPoint)! ! !Form class methodsFor: 'instance creation' stamp: 'jm 12/5/97 19:32'! fromUserWithExtent: anExtent "Answer an instance of me with bitmap initialized from the area of the display screen whose origin is designated by the user and whose size is anExtent" ^ self fromDisplay: (Rectangle originFromUser: anExtent) "(Form fromUserWithExtent: 50@50) displayAt: 10@10"! ! !Form class methodsFor: 'mode constants'! and "Answer the integer denoting the logical 'and' combination rule." ^1! ! !Form class methodsFor: 'mode constants'! blend "Answer the integer denoting BitBlt's alpha blend combination rule." ^24! ! !Form class methodsFor: 'mode constants' stamp: 'di 12/31/1998 14:02'! blendAlpha "Answer the integer denoting BitBlt's blend-with-constant-alpha rule." ^ 30! ! !Form class methodsFor: 'mode constants'! erase "Answer the integer denoting mode erase." ^4! ! !Form class methodsFor: 'mode constants'! erase1bitShape "Answer the integer denoting mode erase." ^ 26! ! !Form class methodsFor: 'mode constants'! oldErase1bitShape "Answer the integer denoting mode erase." ^ 17! ! !Form class methodsFor: 'mode constants'! oldPaint "Answer the integer denoting the 'paint' combination rule." ^16! ! !Form class methodsFor: 'mode constants'! over "Answer the integer denoting mode over." ^3! ! !Form class methodsFor: 'mode constants'! paint "Answer the integer denoting the 'paint' combination rule." ^25! ! !Form class methodsFor: 'mode constants' stamp: 'di 12/31/1998 14:02'! paintAlpha "Answer the integer denoting BitBlt's paint-with-constant-alpha rule." ^ 31! ! !Form class methodsFor: 'mode constants'! reverse "Answer the integer denoting mode reverse." ^6! ! !Form class methodsFor: 'mode constants' stamp: 'hg 1/29/2001 17:28'! rgbMul "Answer the integer denoting 'Multiply each color component, their values regarded as fractions of 1' rule." ^ 37! ! !Form class methodsFor: 'mode constants'! under "Answer the integer denoting mode under." ^7! ! !Form class methodsFor: 'examples'! exampleBorder "Form exampleBorder" "This example demonstrates the border finding algorithm. Start by having the user sketch on the screen (end with option-click) and then select a rectangular area of the screen which includes all of the area to be filled. Finally, (with crosshair cursor), the user points at the interior of the region to be outlined, and the region begins with that place as its seed." | f r interiorPoint | Form exampleSketch. "sketch a little area with an enclosed region" r _ Rectangle fromUser. f _ Form fromDisplay: r. Cursor crossHair showWhile: [interiorPoint _ Sensor waitButton - r origin]. Cursor execute showWhile: [f shapeBorder: Color blue width: 2 interiorPoint: interiorPoint sharpCorners: false internal: false]. f displayOn: Display at: r origin ! ! !Form class methodsFor: 'examples'! exampleEdits "In Form category editing are messages edit and bitEdit that make it possible to create editors on instances of Form. This is the general form editor: | f | f _ Form fromUser. f edit. This is the general bit editor: | f | f _ Form fromUser. f bitEdit."! ! !Form class methodsFor: 'examples'! exampleMagnify | f m | f _ Form fromUser. m _ f magnify: f boundingBox by: 5 @ 5. m displayOn: Display at: Sensor waitButton "Form exampleMagnify."! ! !Form class methodsFor: 'examples'! exampleShrink | f s | f _ Form fromUser. s _ f shrink: f boundingBox by: 2 @ 5. s displayOn: Display at: Sensor waitButton "Form exampleShrink."! ! !Form class methodsFor: 'examples'! exampleSketch "This is a simple drawing algorithm to get a sketch on the display screen. Draws whenever mouse button down. Ends with option-click." | aPen color | aPen _ Pen new. color _ 0. [Sensor yellowButtonPressed] whileFalse: [aPen place: Sensor cursorPoint; color: (color _ color + 1). [Sensor redButtonPressed] whileTrue: [aPen goto: Sensor cursorPoint]]. Sensor waitNoButton. "Form exampleSketch"! ! !Form class methodsFor: 'examples'! exampleSpaceFill "Form exampleSpaceFill" "This example demonstrates the area filling algorithm. Starts by having the user sketch on the screen (ended by option-click) and then select a rectangular area of the screen which includes all of the area to be filled. Finally, (with crosshair cursor), the user points at the interior of some region to be filled, and the filling begins with that place as its seed." | f r interiorPoint | Form exampleSketch. "sketch a little area with an enclosed region" r _ Rectangle fromUser. f _ Form fromDisplay: r. Cursor crossHair showWhile: [interiorPoint _ Sensor waitButton - r origin]. Cursor execute showWhile: [f shapeFill: Color gray interiorPoint: interiorPoint]. f displayOn: Display at: r origin ! ! !Form class methodsFor: 'examples'! makeStar "See the similar example in OpaqueForm" | sampleForm pen | sampleForm _ Form extent: 50@50. "Make a form" pen _ Pen newOnForm: sampleForm. pen place: 24@50; turn: 18. "Draw a 5-pointed star on it." 1 to: 5 do: [:i | pen go: 19; turn: 72; go: 19; turn: -144]. ^ sampleForm " Form makeStar follow: [Sensor cursorPoint] while: [Sensor noButtonPressed] "! ! !Form class methodsFor: 'examples' stamp: 'tk 7/4/2000 12:08'! toothpaste: diam "Display restoreAfter: [Form toothpaste: 30]" "Draws wormlike lines by laying down images of spheres. See Ken Knowlton, Computer Graphics, vol. 15 no. 4 p352. Draw with mouse button down; terminate by option-click." | facade ball filter point queue port color q colors colr colr2 | colors _ Display depth = 1 ifTrue: [Array with: Color black] ifFalse: [Color red wheel: 12]. facade _ Form extent: diam@diam offset: (diam//-2) asPoint. (Form dotOfSize: diam) displayOn: facade at: (diam//2) asPoint clippingBox: facade boundingBox rule: Form under fillColor: Color white. #(1 2 3) do: [:x | "simulate facade by circles of gray" (Form dotOfSize: x*diam//5) displayOn: facade at: (diam*2//5) asPoint clippingBox: facade boundingBox rule: Form under fillColor: (Color perform: (#(black gray lightGray) at: x)). "facade displayAt: 50*x@50"]. ball _ Form dotOfSize: diam. color _ 8. [ true ] whileTrue: [port _ BitBlt current toForm: Display. "Expand 1-bit forms to any pixel depth" port colorMap: (Bitmap with: 0 with: 16rFFFFFFFF). queue _ OrderedCollection new: 32. 16 timesRepeat: [queue addLast: -20@-20]. Sensor waitButton. Sensor yellowButtonPressed ifTrue: [^ self]. filter _ Sensor cursorPoint. colr _ colors atWrap: (color _ color + 5). "choose increment relatively prime to colors size" colr2 _ colr alphaMixed: 0.3 with: Color white. [Sensor redButtonPressed or: [queue size > 0]] whileTrue: [filter _ filter * 4 + Sensor cursorPoint // 5. point _ Sensor redButtonPressed ifTrue: [filter] ifFalse: [-20@-20]. port copyForm: ball to: point rule: Form paint fillColor: colr. (q _ queue removeFirst) == nil ifTrue: [^ self]. "exit" Display depth = 1 ifTrue: [port copyForm: facade to: q rule: Form erase] ifFalse: [port copyForm: facade to: q rule: Form paint fillColor: colr2]. Sensor redButtonPressed ifTrue: [queue addLast: point]]]. ! ! !Form class methodsFor: 'examples'! xorHack: size "Display restoreAfter: [Form xorHack: 256]" "Draw a smiley face or stick figure, and end with option-click. Thereafter image gets 'processed' as long as you have button down. If you stop at just the right time, you'll see you figure upside down, and at the end of a full cycle, you'll see it perfectly restored. Dude -- this works in color too!!" | rect form i bb | rect _ 5@5 extent: size@size. Display fillWhite: rect; border: (rect expandBy: 2) width: 2. Display border: (rect topRight - (0@2) extent: rect extent*2 + 4) width: 2. Form exampleSketch. form _ Form fromDisplay: rect. bb _ form boundingBox. i _ 0. [Sensor yellowButtonPressed] whileFalse: [[Sensor redButtonPressed] whileTrue: [i _ i + 1. (Array with: 0@1 with: 0@-1 with: 1@0 with: -1@0) do: [:d | form copyBits: bb from: form at: d clippingBox: bb rule: Form reverse fillColor: nil]. form displayAt: rect topLeft. i+2\\size < 4 ifTrue: [(Delay forMilliseconds: 300) wait]]. (form magnify: form boundingBox by: 2@2) displayAt: rect topRight + (2@0). Sensor waitButton].! ! !Form class methodsFor: 'shut down' stamp: 'ar 5/28/2000 23:35'! shutDown "Form shutDown" "Compress all instances in the system. Will decompress on demand..." Form allInstancesDo: [:f | f hibernate]. ColorForm allInstancesDo: [:f | f hibernate].! ! !Form class methodsFor: 'BMP file reading' stamp: 'ar 6/16/2002 17:41'! fromBMPFile: aBinaryStream "Obsolete" ^self fromBinaryStream: aBinaryStream.! ! !Form class methodsFor: 'BMP file reading' stamp: 'ar 6/16/2002 17:41'! fromBMPFileNamed: fileName "Obsolete" ^self fromFileNamed: fileName ! ! !Form class methodsFor: 'initialize-release' stamp: 'hg 8/3/2000 16:25'! initialize FileList registerFileReader: self! ! !Form class methodsFor: 'fileIn/Out' stamp: 'hg 8/3/2000 16:26'! openAsBackground: fullName "Set an image as a background image. Support Squeak's common file format (GIF, JPG, PNG, 'Form stoteOn: (run coded)' and BMP)" (self fromFileNamed: fullName) setAsBackground! ! !Form class methodsFor: 'fileIn/Out' stamp: 'BG 10/28/2003 20:58'! openImageInWindow: fullName "Handle five file formats: GIF, JPG, PNG, Form stoteOn: (run coded), and BMP. Fail if file format is not recognized." | image myStream | myStream _ (FileStream readOnlyFileNamed: fullName) binary. image _ self fromBinaryStream: myStream. myStream close. Smalltalk isMorphic ifFalse: [FormView open: image named: fullName]! ! !Form class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 01:38'! serviceImageAsBackground "Answer a service for setting the desktop background from a given graphical file's contents" ^ SimpleServiceEntry provider: self label: 'use graphic as background' selector: #openAsBackground: description: 'use the graphic as the background for the desktop' buttonLabel: 'background'! ! !Form class methodsFor: 'fileIn/Out' stamp: 'sw 2/17/2002 00:31'! serviceOpenImageInWindow "Answer a service for opening a graphic in a window" ^ SimpleServiceEntry provider: self label: 'open graphic in a window' selector: #openImageInWindow: description: 'open a graphic file in a window' buttonLabel: 'open'! ! !Form class methodsFor: 'class initialization' stamp: 'SD 11/15/2001 22:21'! unload FileList unregisterFileReader: self ! ! View subclass: #FormView instanceVariableNames: 'rule mask' classVariableNames: '' poolDictionaries: '' category: 'ST80-Views'! !FormView commentStamp: '<historical>' prior: 0! I represent a view of a Form.! !FormView methodsFor: 'accessing'! fillColor "Answer an instance of class Form that is the mask used when displaying the receiver's model (a Form) on the display screen (see BitBlt for the meaning of this mask)." ^ mask! ! !FormView methodsFor: 'accessing'! fillColor: aForm "Set the display mask for displaying the receiver's model to be the argument, aForm." mask _ aForm! ! !FormView methodsFor: 'accessing'! mask "Answer an instance of class Form that is the mask used when displaying the receiver's model (a Form) on the display screen (see BitBlt for the meaning of this mask)." ^ mask! ! !FormView methodsFor: 'accessing'! rule "Answer a number from 0 to 15 that indicates which of the sixteen display rules (logical function of two boolean values) is to be used when copying the receiver's model (a Form) onto the display screen." rule == nil ifTrue: [^self defaultRule] ifFalse: [^rule]! ! !FormView methodsFor: 'accessing'! rule: anInteger "Set the display rule for the receiver to be the argument, anInteger." rule _ anInteger! ! !FormView methodsFor: 'controller access' stamp: 'ssa 10/8/2008 13:14'! defaultControllerClass ^ NoController! ! !FormView methodsFor: 'model access'! changeValueAt: location put: anInteger "The receiver's model is a form which has an array of bits. Change the bit at index, location, to be anInteger (either 1 or 0). Inform all objects that depend on the model that it has changed." model pixelValueAt: location put: anInteger. model changed: self! ! !FormView methodsFor: 'window access'! defaultWindow "Refer to the comment in View|defaultWindow." ^(Rectangle origin: 0 @ 0 extent: model extent) expandBy: borderWidth! ! !FormView methodsFor: 'window access'! windowBox "For comaptibility with Control manager (see senders)" ^ self insetDisplayBox! ! !FormView methodsFor: 'displaying'! displayOn: aPort model displayOnPort: aPort at: self displayBox origin! ! !FormView methodsFor: 'displaying' stamp: 'hmm 7/21/97 20:45'! displayView "Refer to the comment in View|displayView." | oldOffset | super displayView. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: insideColor]. oldOffset _ model offset. model offset: "borderWidth origin" 0@0. model displayOn: Display transformation: self displayTransformation clippingBox: self insetDisplayBox rule: self rule fillColor: self fillColor. model offset: oldOffset! ! !FormView methodsFor: 'displaying'! uncacheBits "Placed vacuously here so that when ControlManager>>restore calls uncacheBits for a project with no windows, we don't hang. 1/24/96 sw"! ! !FormView methodsFor: 'displaying'! updateDisplay "overridden by subclass"! ! !FormView methodsFor: 'updating'! update: aFormView "Refer to the comment in View|update:." self == aFormView ifFalse: [self display]! ! !FormView methodsFor: 'menu messages'! accept "The receiver's model is set to the working version, the one in which edits are carried out." ^self! ! !FormView methodsFor: 'menu messages'! cancel "Set the working form to be a copy of the model." ^self! ! !FormView methodsFor: 'private'! defaultRule "The default display rule is 3=over or storing." ^Form over! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! FormView class instanceVariableNames: ''! !FormView class methodsFor: 'examples'! exampleOne "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. " | f view | f _ Form fromUser. view _ self new model: f. view translateBy: 60 @ 40. view borderWidth: 2. view display. view release "FormView exampleOne"! ! !FormView class methodsFor: 'examples'! exampleTwo "Frame a Form (specified by the user) that is scaled by 2. The border is 2 bits in width. Displays at location 60, 40." | f view | f _ Form fromUser. view _ self new model: f. view scaleBy: 2.0. view translateBy: 60 @ 40. view borderWidth: 2. view display. view release "FormView exampleTwo"! ! !FormView class methodsFor: 'examples' stamp: 'BG 12/5/2003 14:45'! open: aForm named: aString "FormView open: ((Form extent: 100@100) borderWidth: 1) named: 'Squeak' " "Open a window whose model is aForm and whose label is aString." | topView aView | topView _ StandardSystemView new. topView model: aForm. topView label: aString. topView minimumSize: aForm extent; maximumSize: aForm extent. aView _ FormView new. aView model: aForm. aView window: (aForm boundingBox expandBy: 2). aView borderWidthLeft: 2 right: 2 top: 2 bottom: 2. topView addSubView: aView. topView controller open! ! Number subclass: #Fraction instanceVariableNames: 'numerator denominator' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !Fraction commentStamp: '<historical>' prior: 0! Fraction provides methods for dealing with fractions like 1/3 as fractions (not as 0.33333...). All public arithmetic operations answer reduced fractions (see examples). instance variables: 'numerator denominator ' Examples: (note the parentheses required to get the right answers in Smalltalk and Squeak): (2/3) + (2/3) (2/3) + (1/2) "answers shows the reduced fraction" (2/3) raisedToInteger: 5 "fractions also can have exponents" ! !Fraction methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:58'! * aNumber "Answer the result of multiplying the receiver by aNumber." | d1 d2 | aNumber isFraction ifTrue: [d1 _ numerator gcd: aNumber denominator. d2 _ denominator gcd: aNumber numerator. (d2 = denominator and: [d1 = aNumber denominator]) ifTrue: [^ numerator // d1 * (aNumber numerator // d2)]. ^ Fraction numerator: numerator // d1 * (aNumber numerator // d2) denominator: denominator // d2 * (aNumber denominator // d1)]. ^ aNumber adaptToFraction: self andSend: #*! ! !Fraction methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:58'! + aNumber "Answer the sum of the receiver and aNumber." | n d d1 d2 | aNumber isFraction ifTrue: [d _ denominator gcd: aNumber denominator. n _ numerator * (d1 _ aNumber denominator // d) + (aNumber numerator * (d2 _ denominator // d)). d1 _ d1 * d2. n _ n // (d2 _ n gcd: d). (d _ d1 * (d // d2)) = 1 ifTrue: [^ n]. ^ Fraction numerator: n denominator: d]. ^ aNumber adaptToFraction: self andSend: #+! ! !Fraction methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:58'! - aNumber "Answer the difference between the receiver and aNumber." aNumber isFraction ifTrue: [^ self + aNumber negated]. ^ aNumber adaptToFraction: self andSend: #-! ! !Fraction methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:58'! / aNumber "Answer the result of dividing the receiver by aNumber." aNumber isFraction ifTrue: [^self * aNumber reciprocal]. ^ aNumber adaptToFraction: self andSend: #/! ! !Fraction methodsFor: 'arithmetic'! negated "Refer to the comment in Number|negated." ^ Fraction numerator: numerator negated denominator: denominator! ! !Fraction methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! reciprocal "Refer to the comment in Number|reciprocal." #Numeric. "Changed 200/01/19 For ANSI <number> support." numerator = 0 ifTrue: [^ (ZeroDivide dividend: self) signal"<- Chg"]. numerator = 1 ifTrue: [^ denominator]. numerator = -1 ifTrue: [^ denominator negated]. ^ Fraction numerator: denominator denominator: numerator! ! !Fraction methodsFor: 'comparing' stamp: 'di 11/6/1998 13:58'! < aNumber aNumber isFraction ifTrue: [^ numerator * aNumber denominator < (aNumber numerator * denominator)]. ^ aNumber adaptToFraction: self andSend: #<! ! !Fraction methodsFor: 'comparing' stamp: 'di 8/31/1999 10:33'! = aNumber aNumber isNumber ifFalse: [^ false]. aNumber isFraction ifTrue: [numerator = 0 ifTrue: [^ aNumber numerator = 0]. ^ (numerator * aNumber denominator) = (aNumber numerator * denominator) "Note: used to just compare num and denom, but this fails for improper fractions"]. ^ aNumber adaptToFraction: self andSend: #=! ! !Fraction methodsFor: 'comparing' stamp: 'SqR 8/3/2000 13:33'! hash "Hash is reimplemented because = is implemented." ^numerator hash bitXor: denominator hash! ! !Fraction methodsFor: 'truncation and round off'! truncated "Refer to the comment in Number|truncated." ^numerator quo: denominator! ! !Fraction methodsFor: 'converting' stamp: 'di 11/6/1998 13:10'! adaptToInteger: rcvr andSend: selector "If I am involved in arithmetic with an Integer, convert it to a Fraction." ^ rcvr asFraction perform: selector with: self! ! !Fraction methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector "Convert receiverScaledDecimal to a Fraction and do the arithmetic. receiverScaledDecimal arithmeticOpSelector self." #Numeric. "add 200/01/19 For ScaledDecimal support." ^ receiverScaledDecimal asFraction perform: arithmeticOpSelector with: self! ! !Fraction methodsFor: 'converting' stamp: 'mrm 10/10/2000 22:58'! asFloat "Answer a Float that closely approximates the value of the receiver. Ideally, answer the Float that most closely approximates the receiver." | nScaleBits dScaleBits nScaled dScaled | "Scale the numerator by throwing away all but the top 8 digits (57 to 64 significant bits) then making that a Float. This keeps all of the precision of a Float (53 significand bits) but guarantees that we do not exceed the range representable as a Float (about 2 to the 1024th)" nScaleBits _ 8 * ((numerator digitLength - 8) max: 0). nScaled _ (numerator bitShift: nScaleBits negated) asFloat. "Scale the denominator the same way." dScaleBits _ 8 * ((denominator digitLength - 8) max: 0). dScaled _ (denominator bitShift: dScaleBits negated) asFloat. "Divide the scaled numerator and denominator to make the right mantissa, then scale to correct the exponent." ^ (nScaled / dScaled) timesTwoPower: (nScaleBits - dScaleBits).! ! !Fraction methodsFor: 'converting'! asFraction "Answer the receiver itself." ^self! ! !Fraction methodsFor: 'converting'! isFraction ^ true! ! !Fraction methodsFor: 'printing'! printOn: aStream aStream nextPut: $(. numerator printOn: aStream. aStream nextPut: $/. denominator printOn: aStream. aStream nextPut: $). ! ! !Fraction methodsFor: 'private'! denominator ^denominator! ! !Fraction methodsFor: 'private'! numerator ^numerator! ! !Fraction methodsFor: 'private'! reduced | gcd numer denom | numerator = 0 ifTrue: [^0]. gcd _ numerator gcd: denominator. numer _ numerator // gcd. denom _ denominator // gcd. denom = 1 ifTrue: [^numer]. ^Fraction numerator: numer denominator: denom! ! !Fraction methodsFor: 'private' stamp: 'tfei 4/12/1999 12:45'! setNumerator: n denominator: d d = 0 ifTrue: [^(ZeroDivide dividend: n) signal] ifFalse: [numerator _ n asInteger. denominator _ d asInteger abs. "keep sign in numerator" d < 0 ifTrue: [numerator _ numerator negated]]! ! !Fraction methodsFor: 'mathematical functions' stamp: 'LC 4/22/1998 14:03'! raisedToInteger: anInteger "See Number | raisedToInteger:" anInteger = 0 ifTrue: [^ 1]. anInteger < 0 ifTrue: [^ self reciprocal raisedToInteger: anInteger negated]. ^ Fraction numerator: (numerator raisedToInteger: anInteger) denominator: (denominator raisedToInteger: anInteger)! ! !Fraction methodsFor: 'mathematical functions' stamp: 'LC 4/22/1998 14:05'! squared "See Fraction (Number) | squared" ^ Fraction numerator: numerator squared denominator: denominator squared! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Fraction class instanceVariableNames: ''! !Fraction class methodsFor: 'instance creation' stamp: 'di 8/31/1999 10:16'! numerator: numInteger denominator: denInteger "Answer an instance of me (numInteger/denInteger). NOTE: This primitive initialization method will not reduce improper fractions, so normal usage should be coded as, eg, (Fraction numerator: a denominator: b) reduced or, more simply, as a / b." ^self new setNumerator: numInteger denominator: denInteger! ! !Fraction class methodsFor: 'constants' stamp: 'RAH 4/25/2000 19:49'! one #Numeric. "add 200/01/19 For <number> protocol support." ^ self numerator: 1 denominator: 1! ! ImageReadWriter subclass: #GIFReadWriter instanceVariableNames: 'width height bitsPerPixel colorPalette rowByteSize xpos ypos pass interlace codeSize clearCode eoiCode freeCode maxCode prefixTable suffixTable remainBitCount bufByte bufStream transparentIndex mapOf32 localColorTable delay loopCount offset' classVariableNames: 'Extension ImageSeparator Terminator' poolDictionaries: '' category: 'Graphics-Files'! !GIFReadWriter commentStamp: '<historical>' prior: 0! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. Used with permission. Modified for use in Squeak.! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:43'! delay: aNumberOrNil "Set delay for next image in hundredth (1/100) of seconds" delay := aNumberOrNil! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:39'! loopCount: aNumber "Set looping. This must be done before any image is written!!" loopCount := aNumber! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'sd 1/30/2004 15:18'! nextImage "Read in the next GIF image from the stream. Read it all into memory first for speed." | f thisImageColorTable | stream class == ReadWriteStream ifFalse: [ stream binary. self on: (ReadWriteStream with: (stream contentsOfEntireFile))]. localColorTable _ nil. self readHeader. f _ self readBody. self close. f == nil ifTrue: [^ self error: 'corrupt GIF file']. thisImageColorTable _ localColorTable ifNil: [colorPalette]. transparentIndex ifNotNil: [ transparentIndex + 1 > thisImageColorTable size ifTrue: [ thisImageColorTable _ thisImageColorTable forceTo: transparentIndex + 1 paddingWith: Color white ]. thisImageColorTable at: transparentIndex + 1 put: Color transparent ]. f colors: thisImageColorTable. ^ f ! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'nk 4/17/2004 19:44'! nextPutImage: aForm | f newF | aForm unhibernate. f _ aForm colorReduced. "minimize depth" f depth > 8 ifTrue: [ "Not enough color space; do it the hard way." f _ f asFormOfDepth: 8]. f depth < 8 ifTrue: [ "writeBitData: expects depth of 8" newF _ f class extent: f extent depth: 8. (f isColorForm) ifTrue: [ newF copyBits: f boundingBox from: f at: 0@0 clippingBox: f boundingBox rule: Form over fillColor: nil map: nil. newF colors: f colors] ifFalse: [f displayOn: newF]. f _ newF]. (f isColorForm) ifTrue: [ (f colorsUsed includes: Color transparent) ifTrue: [ transparentIndex _ (f colors indexOf: Color transparent) - 1]] ifFalse: [transparentIndex _ nil]. width _ f width. height _ f height. bitsPerPixel _ f depth. colorPalette _ f colormapIfNeededForDepth: 32. interlace _ false. self writeHeader. self writeBitData: f bits. ! ! !GIFReadWriter methodsFor: 'accessing' stamp: '6/18/97 13:18 '! setStream: aStream "Feed it in from an existing source" stream _ aStream! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'di 9/15/1998 09:53'! understandsImageFormat ^('abc' collect: [:x | stream next asCharacter]) = 'GIF'! ! !GIFReadWriter methodsFor: 'private-encoding'! flushCode self flushBits! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'tk 9/14/97 16:25'! readPixelFrom: bits "Since bits is a Bitmap with 32 bit values, watch out for the padding at the end of each row. But, GIF format already wants padding to 32 bit boundary!! OK as is. tk 9/14/97" | pixel | ypos >= height ifTrue: [^nil]. pixel _ bits byteAt: (ypos * rowByteSize + xpos + 1). self updatePixelPosition. ^pixel! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:21'! writeBitData: bits "using modified Lempel-Ziv Welch algorithm." | maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel index disp nomatch | pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ width * 8 + 31 // 32 * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ WriteStream on: (ByteArray new: 256). maxBits _ 12. maxMaxCode _ 1 bitShift: maxBits. tSize _ 5003. prefixTable _ Array new: tSize. suffixTable _ Array new: tSize. initCodeSize _ bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. self nextPut: initCodeSize. self setParameters: initCodeSize. tShift _ 0. fCode _ tSize. [fCode < 65536] whileTrue: [tShift _ tShift + 1. fCode _ fCode * 2]. tShift _ 8 - tShift. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self writeCodeAndCheckCodeSize: clearCode. ent _ self readPixelFrom: bits. [(pixel _ self readPixelFrom: bits) == nil] whileFalse: [ fCode _ (pixel bitShift: maxBits) + ent. index _ ((pixel bitShift: tShift) bitXor: ent) + 1. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index] ifFalse: [nomatch _ true. (suffixTable at: index) >= 0 ifTrue: [disp _ tSize - index + 1. index = 1 ifTrue: [disp _ 1]. "probe" [(index _ index - disp) < 1 ifTrue: [index _ index + tSize]. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index. nomatch _ false. "continue whileFalse:"]. nomatch and: [(suffixTable at: index) > 0]] whileTrue: ["probe"]]. "nomatch" nomatch ifTrue: [self writeCodeAndCheckCodeSize: ent. ent _ pixel. freeCode < maxMaxCode ifTrue: [prefixTable at: index put: freeCode. suffixTable at: index put: fCode. freeCode _ freeCode + 1] ifFalse: [self writeCodeAndCheckCodeSize: clearCode. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self setParameters: initCodeSize]]]]. prefixTable _ suffixTable _ nil. self writeCodeAndCheckCodeSize: ent. self writeCodeAndCheckCodeSize: eoiCode. self flushCode. self nextPut: 0. "zero-length packet" ! ! !GIFReadWriter methodsFor: 'private-encoding'! writeCode: aCode self nextBitsPut: aCode! ! !GIFReadWriter methodsFor: 'private-encoding'! writeCodeAndCheckCodeSize: aCode self writeCode: aCode. self checkCodeSize! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:38'! writeHeader | byte | stream position = 0 ifTrue: [ "For first image only" self nextPutAll: 'GIF89a' asByteArray. self writeWord: width. "Screen Width" self writeWord: height. "Screen Height" byte _ 16r80. "has color map" byte _ byte bitOr: ((bitsPerPixel - 1) bitShift: 5). "color resolution" byte _ byte bitOr: bitsPerPixel - 1. "bits per pixel" self nextPut: byte. self nextPut: 0. "background color." self nextPut: 0. "reserved" colorPalette do: [:pixelValue | self nextPut: ((pixelValue bitShift: -16) bitAnd: 255); nextPut: ((pixelValue bitShift: -8) bitAnd: 255); nextPut: (pixelValue bitAnd: 255)]. loopCount notNil ifTrue: [ "Write a Netscape loop chunk" self nextPut: Extension. self nextPutAll: #(255 11 78 69 84 83 67 65 80 69 50 46 48 3 1) asByteArray. self writeWord: loopCount. self nextPut: 0]]. delay notNil | transparentIndex notNil ifTrue: [ self nextPut: Extension; nextPutAll: #(16rF9 4) asByteArray; nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [9]); writeWord: (delay isNil ifTrue: [0] ifFalse: [delay]); nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [transparentIndex]); nextPut: 0]. self nextPut: ImageSeparator. self writeWord: 0. "Image Left" self writeWord: 0. "Image Top" self writeWord: width. "Image Width" self writeWord: height. "Image Height" byte _ interlace ifTrue: [16r40] ifFalse: [0]. self nextPut: byte. ! ! !GIFReadWriter methodsFor: 'private-encoding'! writeWord: aWord self nextPut: (aWord bitAnd: 255). self nextPut: ((aWord bitShift: -8) bitAnd: 255). ^aWord! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'mir 11/19/2003 12:19'! readBitData "using modified Lempel-Ziv Welch algorithm." | outCodes outCount bitMask initCodeSize code curCode oldCode inCode finChar i bytes f c packedBits hasLocalColor localColorSize maxOutCodes | maxOutCodes _ 4096. offset := self readWord@self readWord. "Image Left@Image Top" width _ self readWord. height _ self readWord. "--- Local Color Table Flag 1 Bit Interlace Flag 1 Bit Sort Flag 1 Bit Reserved 2 Bits Size of Local Color Table 3 Bits ----" packedBits _ self next. interlace _ (packedBits bitAnd: 16r40) ~= 0. hasLocalColor _ (packedBits bitAnd: 16r80) ~= 0. localColorSize _ 1 bitShift: ((packedBits bitAnd: 16r7) + 1). hasLocalColor ifTrue: [localColorTable _ self readColorTable: localColorSize]. pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ ((width + 3) // 4) * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ ReadStream on: ByteArray new. outCodes _ ByteArray new: maxOutCodes + 1. outCount _ 0. bitMask _ (1 bitShift: bitsPerPixel) - 1. prefixTable _ Array new: 4096. suffixTable _ Array new: 4096. initCodeSize _ self next. self setParameters: initCodeSize. bitsPerPixel > 8 ifTrue: [^self error: 'never heard of a GIF that deep']. bytes _ ByteArray new: rowByteSize * height. [(code _ self readCode) = eoiCode] whileFalse: [code = clearCode ifTrue: [self setParameters: initCodeSize. curCode _ oldCode _ code _ self readCode. finChar _ curCode bitAnd: bitMask. "Horrible hack to avoid running off the end of the bitmap. Seems to cure problem reading some gifs!!? tk 6/24/97 20:16" xpos = 0 ifTrue: [ ypos < height ifTrue: [ bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]] ifFalse: [bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]. self updatePixelPosition] ifFalse: [curCode _ inCode _ code. curCode >= freeCode ifTrue: [curCode _ oldCode. outCodes at: (outCount _ outCount + 1) put: finChar]. [curCode > bitMask] whileTrue: [outCount > maxOutCodes ifTrue: [^self error: 'corrupt GIF file (OutCount)']. outCodes at: (outCount _ outCount + 1) put: (suffixTable at: curCode + 1). curCode _ prefixTable at: curCode + 1]. finChar _ curCode bitAnd: bitMask. outCodes at: (outCount _ outCount + 1) put: finChar. i _ outCount. [i > 0] whileTrue: ["self writePixel: (outCodes at: i) to: bits" bytes at: (ypos * rowByteSize) + xpos + 1 put: (outCodes at: i). self updatePixelPosition. i _ i - 1]. outCount _ 0. prefixTable at: freeCode + 1 put: oldCode. suffixTable at: freeCode + 1 put: finChar. oldCode _ inCode. freeCode _ freeCode + 1. self checkCodeSize]]. prefixTable _ suffixTable _ nil. f _ ColorForm extent: width@height depth: 8. f bits copyFromByteArray: bytes. "Squeak can handle depths 1, 2, 4, and 8" bitsPerPixel > 4 ifTrue: [^ f]. "reduce depth to save space" c _ ColorForm extent: width@height depth: (bitsPerPixel = 3 ifTrue: [4] ifFalse: [bitsPerPixel]). f displayOn: c. ^ c ! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'KLC 1/25/2004 14:04'! readBody "Read the GIF blocks. Modified to return a form. " | form extype block blocksize packedFields delay1 | form _ nil. [stream atEnd] whileFalse: [ block _ self next. block = Terminator ifTrue: [^ form]. block = ImageSeparator ifTrue: [ form isNil ifTrue: [form _ self readBitData] ifFalse: [self skipBitData]. ] ifFalse: [ block = Extension ifFalse: [^ form "^ self error: 'Unknown block type'"]. "Extension block" extype _ self next. "extension type" extype = 16rF9 ifTrue: [ "graphics control" self next = 4 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. "==== Reserved 3 Bits Disposal Method 3 Bits User Input Flag 1 Bit Transparent Color Flag 1 Bit ===" packedFields _ self next. delay1 := self next. "delay time 1" delay := (self next*256 + delay1) *10. "delay time 2" transparentIndex _ self next. (packedFields bitAnd: 1) = 0 ifTrue: [transparentIndex _ nil]. self next = 0 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. ] ifFalse: [ "Skip blocks" [(blocksize _ self next) > 0] whileTrue: [ "Read the block and ignore it and eat the block terminator" self next: blocksize]]]]! ! !GIFReadWriter methodsFor: 'private-decoding'! readCode ^self nextBits! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:48'! readColorTable: numberOfEntries | array r g b | array _ Array new: numberOfEntries. 1 to: array size do: [ :i | r _ self next. g _ self next. b _ self next. array at: i put: (Color r: r g: g b: b range: 255) ]. ^array! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:49'! readHeader | is89 byte hasColorMap | (self hasMagicNumber: 'GIF87a' asByteArray) ifTrue: [is89 _ false] ifFalse: [(self hasMagicNumber: 'GIF89a' asByteArray) ifTrue: [is89 _ true] ifFalse: [^ self error: 'This does not appear to be a GIF file']]. self readWord. "skip Screen Width" self readWord. "skip Screen Height" byte _ self next. hasColorMap _ (byte bitAnd: 16r80) ~= 0. bitsPerPixel _ (byte bitAnd: 7) + 1. byte _ self next. "skip background color." self next ~= 0 ifTrue: [is89 ifFalse: [^self error: 'corrupt GIF file (screen descriptor)']]. hasColorMap ifTrue: [colorPalette _ self readColorTable: (1 bitShift: bitsPerPixel)] ifFalse: ["Transcript cr; show: 'GIF file does not have a color map.'." colorPalette _ nil "Palette monochromeDefault"].! ! !GIFReadWriter methodsFor: 'private-decoding'! readWord ^self next + (self next bitShift: 8)! ! !GIFReadWriter methodsFor: 'private-decoding'! skipBitData | misc blocksize | self readWord. "skip Image Left" self readWord. "skip Image Top" self readWord. "width" self readWord. "height" misc _ self next. (misc bitAnd: 16r80) = 0 ifFalse: [ "skip colormap" 1 to: (1 bitShift: (misc bitAnd: 7) + 1) do: [:i | self next; next; next]]. self next. "minimum code size" [(blocksize _ self next) > 0] whileTrue: [self next: blocksize]! ! !GIFReadWriter methodsFor: 'private-bits access'! flushBits remainBitCount = 0 ifFalse: [self nextBytePut: bufByte. remainBitCount _ 0]. self flushBuffer! ! !GIFReadWriter methodsFor: 'private-bits access'! nextBits | integer readBitCount shiftCount byte | integer _ 0. remainBitCount = 0 ifTrue: [readBitCount _ 8. shiftCount _ 0] ifFalse: [readBitCount _ remainBitCount. shiftCount _ remainBitCount - 8]. [readBitCount < codeSize] whileTrue: [byte _ self nextByte. byte == nil ifTrue: [^eoiCode]. integer _ integer + (byte bitShift: shiftCount). shiftCount _ shiftCount + 8. readBitCount _ readBitCount + 8]. (remainBitCount _ readBitCount - codeSize) = 0 ifTrue: [byte _ self nextByte] ifFalse: [byte _ self peekByte]. byte == nil ifTrue: [^eoiCode]. ^(integer + (byte bitShift: shiftCount)) bitAnd: maxCode! ! !GIFReadWriter methodsFor: 'private-bits access'! nextBitsPut: anInteger | integer writeBitCount shiftCount | shiftCount _ 0. remainBitCount = 0 ifTrue: [writeBitCount _ 8. integer _ anInteger] ifFalse: [writeBitCount _ remainBitCount. integer _ bufByte + (anInteger bitShift: 8 - remainBitCount)]. [writeBitCount < codeSize] whileTrue: [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255). shiftCount _ shiftCount - 8. writeBitCount _ writeBitCount + 8]. (remainBitCount _ writeBitCount - codeSize) = 0 ifTrue: [self nextBytePut: (integer bitShift: shiftCount)] ifFalse: [bufByte _ integer bitShift: shiftCount]. ^anInteger! ! !GIFReadWriter methodsFor: 'private-packing'! fillBuffer | packSize | packSize _ self next. bufStream _ ReadStream on: (self next: packSize)! ! !GIFReadWriter methodsFor: 'private-packing'! flushBuffer bufStream isEmpty ifTrue: [^self]. self nextPut: bufStream size. self nextPutAll: bufStream contents. bufStream _ WriteStream on: (ByteArray new: 256)! ! !GIFReadWriter methodsFor: 'private-packing'! nextByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream next! ! !GIFReadWriter methodsFor: 'private-packing'! nextBytePut: aByte bufStream nextPut: aByte. bufStream size >= 254 ifTrue: [self flushBuffer]! ! !GIFReadWriter methodsFor: 'private-packing'! peekByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream peek! ! !GIFReadWriter methodsFor: 'private'! checkCodeSize (freeCode > maxCode and: [codeSize < 12]) ifTrue: [codeSize _ codeSize + 1. maxCode _ (1 bitShift: codeSize) - 1]! ! !GIFReadWriter methodsFor: 'private'! setParameters: initCodeSize clearCode _ 1 bitShift: initCodeSize. eoiCode _ clearCode + 1. freeCode _ clearCode + 2. codeSize _ initCodeSize + 1. maxCode _ (1 bitShift: codeSize) - 1! ! !GIFReadWriter methodsFor: 'private'! updatePixelPosition (xpos _ xpos + 1) >= width ifFalse: [^self]. xpos _ 0. interlace ifFalse: [ypos _ ypos + 1. ^self]. pass = 0 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 4]. ^self]. pass = 1 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 2]. ^self]. pass = 2 ifTrue: [(ypos _ ypos + 4) >= height ifTrue: [pass _ pass + 1. ypos _ 1]. ^self]. pass = 3 ifTrue: [ypos _ ypos + 2. ^self]. ^self error: 'can''t happen'! ! !GIFReadWriter methodsFor: 'stream access' stamp: 'bf 5/29/2003 01:23'! close "Write terminator" self nextPut: Terminator. ^super close! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GIFReadWriter class instanceVariableNames: ''! !GIFReadWriter class methodsFor: 'class initialization'! initialize "GIFReadWriter initialize" ImageSeparator _ $, asInteger. Extension _ $!! asInteger. Terminator _ $; asInteger. ! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'bf 5/29/2003 01:56'! exampleAnim "GIFReadWriter exampleAnim" | writer extent center | writer := GIFReadWriter on: (FileStream newFileNamed: 'anim.gif'). writer loopCount: 20. "Repeat 20 times" writer delay: 10. "Wait 10/100 seconds" extent := 42@42. center := extent / 2. Cursor write showWhile: [ [2 to: center x - 1 by: 2 do: [:r | "Make a fancy anim without using Canvas - inefficient as hell" | image | image := ColorForm extent: extent depth: 8. 0.0 to: 359.0 do: [:theta | image colorAt: (center + (Point r: r degrees: theta)) rounded put: Color red]. writer nextPutImage: image] ] ensure: [writer close]].! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'sd 9/27/2003 19:01'! grabScreenAndSaveOnDisk "GIFReaderWriter grabScreenAndSaveOnDisk" | form fileName | form _ Form fromUser. form bits size = 0 ifTrue: [^ self beep]. fileName _ FileDirectory default nextNameFor: 'Squeak' extension: 'gif'. Utilities informUser: 'Writing ' , fileName during: [GIFReadWriter putForm: form onFileNamed: fileName].! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" self allSubclasses detect: [:cls | cls wantsToHandleGIFs ] ifNone: ["if none of my subclasses wants , then i''ll have to do" ^ #('gif' )]. ^ #( )! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! wantsToHandleGIFs ^ false! ! Exception subclass: #Halt instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Extensions'! !Halt commentStamp: '<historical>' prior: 0! Halt is provided to support Object>>halt.! !Halt methodsFor: 'description' stamp: 'tfei 5/10/1999 14:24'! isResumable ^true! ! !Halt methodsFor: 'priv handling' stamp: 'ajh 8/5/2003 11:30'! defaultAction "No one has handled this error, but now give them a chance to decide how to debug it. If none handle this either then open debugger (see UnhandedError-defaultAction)" UnhandledError signalForException: self! ! Browser subclass: #HierarchyBrowser instanceVariableNames: 'classList centralClass' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !HierarchyBrowser methodsFor: 'initialization' stamp: 'sw 5/8/2000 01:28'! changed: sym sym == #classList ifTrue: [self updateAfterClassChange]. super changed: sym! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'tk 4/3/98 11:09'! classListIndex: newIndex "Cause system organization to reflect appropriate category" | newClassName ind | newIndex ~= 0 ifTrue: [newClassName _ (classList at: newIndex) copyWithout: $ . systemCategoryListIndex _ systemOrganizer numberOfCategoryOfElement: newClassName]. ind _ super classListIndex: newIndex. self changed: #systemCategorySingleton. ^ ind! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'dew 9/15/2001 16:19'! defaultBrowserTitle ^ 'Hierarchy Browser'! ! !HierarchyBrowser methodsFor: 'initialization'! initAlphabeticListing | tab stab index | self systemOrganizer: SystemOrganization. metaClassIndicated _ false. classList _ Smalltalk classNames.! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'sw 5/8/2000 01:02'! initHierarchyForClass: aClassOrMetaClass | tab stab index nonMetaClass | centralClass _ aClassOrMetaClass. nonMetaClass _ aClassOrMetaClass theNonMetaClass. self systemOrganizer: SystemOrganization. metaClassIndicated _ aClassOrMetaClass isMeta. classList _ OrderedCollection new. tab _ ''. nonMetaClass allSuperclasses reverseDo: [:aClass | classList add: tab , aClass name. tab _ tab , ' ']. index _ classList size + 1. nonMetaClass allSubclassesWithLevelDo: [:aClass :level | stab _ ''. 1 to: level do: [:i | stab _ stab , ' ']. classList add: tab , stab , aClass name] startingLevel: 0. self classListIndex: index! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'tk 4/5/98 10:29'! openEditString: aString "Create a pluggable version of all the views for a HierarchyBrowser, including views and controllers. The top list view is of the currently selected system class category--a single item list." ^ self openSystemCatEditString: aString! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'sw 11/8/1999 09:38'! potentialClassNames "Answer the names of all the classes that could be viewed in this browser" ^ self classList collect: [:aName | aName copyWithout: $ ]! ! !HierarchyBrowser methodsFor: 'initialization'! selectClass: classNotMeta | name | name _ classNotMeta name. self classListIndex: (self classList findFirst: [:each | (each endsWith: name) and: [each size = name size or: [(each at: each size - name size) isSeparator]]])! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'sw 12/4/96'! selectedClassName "Answer the name of the class currently selected. di bug fix for the case where name cannot be found -- return nil rather than halt" | aName | aName _ super selectedClassName. ^ aName == nil ifTrue: [aName] ifFalse: [(aName copyWithout: $ ) asSymbol]! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'di 4/26/2000 20:20'! systemCategorySingleton | cls | cls _ self selectedClass. ^ cls ifNil: [Array new] ifNotNil: [Array with: cls category]! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'rhi 12/2/2001 21:32'! updateAfterClassChange "It is possible that some the classes comprising the hierarchy have changed, so reinitialize the entire browser." (centralClass notNil and: [centralClass isObsolete not]) ifTrue: [self initHierarchyForClass: centralClass]! ! !HierarchyBrowser methodsFor: 'menu messages' stamp: 'tk 4/7/98 13:53'! buildClassBrowserEditString: aString "Create and schedule a new class browser for the current selection, if one exists, with initial textual contents set to aString." self spawnHierarchy! ! !HierarchyBrowser methodsFor: 'menu messages' stamp: 'tk 4/3/98 11:22'! removeSystemCategory "If a class category is selected, create a Confirmer so the user can verify that the currently selected class category and all of its classes should be removed from the system. If so, remove it." self inform: 'Use a normal Browser, in which you can see the entire category you are trying to remove.'! ! !HierarchyBrowser methodsFor: 'menu messages' stamp: 'sw 11/8/1999 13:35'! systemCatSingletonKey: aChar from: aView ^ self systemCatListKey: aChar from: aView! ! !HierarchyBrowser methodsFor: 'menu messages' stamp: 'sw 11/8/1999 14:08'! systemCatSingletonMenu: aMenu ^ aMenu labels: 'find class... (f) browse printOut fileOut update rename... remove' lines: #(1 4) selections: #(findClass buildSystemCategoryBrowser printOutSystemCategory fileOutSystemCategory updateSystemCategories renameSystemCategory removeSystemCategory ) ! ! !HierarchyBrowser methodsFor: 'class list' stamp: 'sw 3/24/2002 01:55'! assureSelectionsShow "This is a workaround for the fact that a hierarchy browser, when launched, often does not show the selected class" | saveCatIndex saveMsgIndex | saveCatIndex _ messageCategoryListIndex. saveMsgIndex _ messageListIndex. self classListIndex: classListIndex. self messageCategoryListIndex: saveCatIndex. self messageListIndex: saveMsgIndex! ! !HierarchyBrowser methodsFor: 'class list' stamp: 'mir 3/22/2000 13:02'! classList classList _ classList select: [:each | Smalltalk includesKey: each withBlanksTrimmed asSymbol]. ^ classList! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! HierarchyBrowser class instanceVariableNames: ''! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'dew 9/15/2001 16:19'! newFor: aClass "Open a new HierarchyBrowser on the given class" | newBrowser | newBrowser _ HierarchyBrowser new initHierarchyForClass: aClass. Browser openBrowserView: (newBrowser openSystemCatEditString: nil) label: newBrowser labelString "HierarchyBrowser newFor: Boolean"! ! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'sw 10/23/2000 18:20'! newFor: aClass labeled: aLabel "Open a new HierarchyBrowser on the given class, using aLabel as the window title." | newBrowser | newBrowser _ HierarchyBrowser new initHierarchyForClass: aClass. Browser openBrowserView: (newBrowser openSystemCatEditString: nil) label: aLabel "HierarchyBrowser newFor: Boolean labeled: 'Testing'"! ! Bag subclass: #IdentityBag instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !IdentityBag commentStamp: '<historical>' prior: 0! Like a Bag, except that items are compared with #== instead of #= . See the comment of IdentitySet for more information. ! ]style[(88 11 23)f3,f3LIdentitySet Comment;,f3! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! IdentityBag class instanceVariableNames: ''! !IdentityBag class methodsFor: 'instance creation' stamp: 'nk 3/17/2001 09:53'! contentsClass ^IdentityDictionary! ! Dictionary subclass: #IdentityDictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !IdentityDictionary commentStamp: 'ls 06/15/02 22:35' prior: 0! Like a Dictionary, except that keys are compared with #== instead of #= . See the comment of IdentitySet for more information.! ]style[(94 11 22)f1,f1LIdentitySet Comment;,f1! !IdentityDictionary methodsFor: 'private' stamp: 'di 12/1/1999 20:54'! keyAtValue: value ifAbsent: exceptionBlock "Answer the key that is the external name for the argument, value. If there is none, answer the result of evaluating exceptionBlock." self associationsDo: [:association | value == association value ifTrue: [^ association key]]. ^ exceptionBlock value! ! !IdentityDictionary methodsFor: 'private' stamp: 'di 10/1/97 20:51'! keys "Answer a Set containing the receiver's keys." | aSet | aSet _ IdentitySet new: self size. self keysDo: [:key | aSet add: key]. ^ aSet! ! !IdentityDictionary methodsFor: 'private' stamp: 'jm 2/18/98 13:18'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | finish hash start element | finish _ array size. finish > 4096 ifTrue: [hash _ anObject identityHash * (finish // 4096)] ifFalse: [hash _ anObject identityHash]. start _ (hash \\ array size) + 1. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element key == anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element key == anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! Set subclass: #IdentitySet instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !IdentitySet commentStamp: 'sw 1/14/2003 22:35' prior: 0! The same as a Set, except that items are compared using #== instead of #=. Almost any class named IdentityFoo is the same as Foo except for the way items are compared. In Foo, #= is used, while in IdentityFoo, #== is used. That is, identity collections will treat items as the same only if they have the same identity. For example, note that copies of a string are equal: ('abc' copy) = ('abc' copy) but they are not identitcal: ('abc' copy) == ('abc' copy) A regular Set will only include equal objects once: | aSet | aSet := Set new. aSet add: 'abc' copy. aSet add: 'abc' copy. aSet An IdentitySet will include multiple equal objects if they are not identical: | aSet | aSet := IdentitySet new. aSet add: 'abc' copy. aSet add: 'abc' copy. aSet ! !IdentitySet methodsFor: 'private' stamp: 'jm 2/18/98 13:19'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | finish hash start element | finish _ array size. finish > 4096 ifTrue: [hash _ anObject identityHash * (finish // 4096)] ifFalse: [hash _ anObject identityHash]. start _ (hash \\ array size) + 1. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !IdentitySet methodsFor: 'converting' stamp: 'ar 9/22/2000 10:13'! asIdentitySet ^self! ! Exception subclass: #IllegalResumeAttempt instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !IllegalResumeAttempt commentStamp: '<historical>' prior: 0! This class is private to the EHS implementation. An instance of it is signaled whenever an attempt is made to resume from an exception which answers false to #isResumable.! !IllegalResumeAttempt methodsFor: 'comment' stamp: 'ajh 9/4/2002 19:24'! defaultAction "No one has handled this error, but now give them a chance to decide how to debug it. If none handle this either then open debugger (see UnhandedError-defaultAction)" UnhandledError signalForException: self! ! !IllegalResumeAttempt methodsFor: 'comment' stamp: 'ajh 2/1/2003 00:57'! isResumable ^ false! ! Object subclass: #ImageReadWriter instanceVariableNames: 'stream' classVariableNames: 'ImageNotStoredSignal MagicNumberErrorSignal' poolDictionaries: '' category: 'Graphics-Files'! !ImageReadWriter commentStamp: '<historical>' prior: 0! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. I am an abstract class to provide for encoding and/or decoding an image on a stream. Instance Variables: stream <ReadStream | WriteStream> stream for image storages Class Variables: ImageNotStoredSignal <Signal> image not stored error signal MagicNumberErrorSignal <Signal> magic number error signal Subclasses must implement the following messages: accessing nextImage nextPutImage: testing canUnderstand (added tao 10/26/97)! !ImageReadWriter methodsFor: 'accessing'! nextImage "Dencoding an image on stream and answer the image." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'accessing'! nextPutImage: anImage "Encoding anImage on stream." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'stream access'! atEnd ^stream atEnd! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'sd 1/30/2004 15:18'! close stream close! ! !ImageReadWriter methodsFor: 'stream access'! contents ^stream contents! ! !ImageReadWriter methodsFor: 'stream access'! cr ^stream nextPut: Character cr asInteger! ! !ImageReadWriter methodsFor: 'stream access'! lf "PPM and PBM are used LF as CR." ^stream nextPut: Character lf asInteger! ! !ImageReadWriter methodsFor: 'stream access'! next ^stream next! ! !ImageReadWriter methodsFor: 'stream access'! next: size ^stream next: size! ! !ImageReadWriter methodsFor: 'stream access'! nextLong "Read a 32-bit quantity from the input stream." ^(stream next bitShift: 24) + (stream next bitShift: 16) + (stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access'! nextLongPut: a32BitW "Write out a 32-bit integer as 32 bits." stream nextPut: ((a32BitW bitShift: -24) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -16) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a32BitW bitAnd: 16rFF). ^a32BitW! ! !ImageReadWriter methodsFor: 'stream access'! nextPut: aByte ^stream nextPut: aByte! ! !ImageReadWriter methodsFor: 'stream access'! nextPutAll: aByteArray ^stream nextPutAll: aByteArray! ! !ImageReadWriter methodsFor: 'stream access'! nextWord "Read a 16-bit quantity from the input stream." ^(stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access'! nextWordPut: a16BitW "Write out a 16-bit integer as 16 bits." stream nextPut: ((a16BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a16BitW bitAnd: 16rFF). ^a16BitW! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'tao 10/23/97 18:00'! peekFor: aValue ^stream peekFor: aValue! ! !ImageReadWriter methodsFor: 'stream access'! position ^stream position! ! !ImageReadWriter methodsFor: 'stream access'! position: anInteger ^stream position: anInteger! ! !ImageReadWriter methodsFor: 'stream access'! size ^stream size! ! !ImageReadWriter methodsFor: 'stream access'! skip: anInteger ^stream skip: anInteger! ! !ImageReadWriter methodsFor: 'stream access'! space ^stream nextPut: Character space asInteger! ! !ImageReadWriter methodsFor: 'stream access'! tab ^stream nextPut: Character tab asInteger! ! !ImageReadWriter methodsFor: 'private'! changePadOfBits: bits width: width height: height depth: depth from: oldPad to: newPad "Change padding size of bits." | srcRowByteSize dstRowByteSize newBits srcRowBase rowEndOffset | (#(8 16 32) includes: oldPad) ifFalse: [^self error: 'Invalid pad: ', oldPad printString]. (#(8 16 32) includes: newPad) ifFalse: [^self error: 'Invalid pad: ', newPad printString]. srcRowByteSize _ width * depth + oldPad - 1 // oldPad * (oldPad / 8). srcRowByteSize * height = bits size ifFalse: [^self error: 'Incorrect bitmap array size.']. dstRowByteSize _ width * depth + newPad - 1 // newPad * (newPad / 8). newBits _ ByteArray new: dstRowByteSize * height. srcRowBase _ 1. rowEndOffset _ dstRowByteSize - 1. 1 to: newBits size by: dstRowByteSize do: [:dstRowBase | newBits replaceFrom: dstRowBase to: dstRowBase + rowEndOffset with: bits startingAt: srcRowBase. srcRowBase _ srcRowBase + srcRowByteSize]. ^newBits! ! !ImageReadWriter methodsFor: 'private'! hasMagicNumber: aByteArray | position | position _ stream position. ((stream size - position) >= aByteArray size and: [(stream next: aByteArray size) = aByteArray]) ifTrue: [^true]. stream position: position. ^false! ! !ImageReadWriter methodsFor: 'private' stamp: 'sd 1/30/2004 15:18'! on: aStream (stream _ aStream) reset. stream binary. "Note that 'reset' makes a file be text. Must do this after."! ! !ImageReadWriter methodsFor: 'private'! unpackBits: bits depthTo8From: depth with: width height: height pad: pad "Unpack bits of depth 1, 2, or 4 image to it of depth 8 image." | bitMask pixelInByte bitsWidth upBitsWidth stopWidth trailingSize upBits bitIndex upBitIndex val | (#(1 2 4) includes: depth) ifFalse: [^self error: 'depth must be 1, 2, or 4']. (#(8 16 32) includes: pad) ifFalse: [^self error: 'pad must be 8, 16, or 32']. bitMask _ (1 bitShift: depth) - 1. pixelInByte _ 8 / depth. bitsWidth _ width * depth + pad - 1 // pad * (pad / 8). upBitsWidth _ width * 8 + pad - 1 // pad * (pad / 8). stopWidth _ width * depth + 7 // 8. trailingSize _ width - (stopWidth - 1 * pixelInByte). upBits _ ByteArray new: upBitsWidth * height. 1 to: height do: [:i | bitIndex _ i - 1 * bitsWidth. upBitIndex _ i - 1 * upBitsWidth. 1 to: stopWidth - 1 do: [:j | val _ bits at: (bitIndex _ bitIndex + 1). upBitIndex _ upBitIndex + pixelInByte. 1 to: pixelInByte do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. val _ (bits at: (bitIndex _ bitIndex + 1)) bitShift: depth negated * (pixelInByte - trailingSize). upBitIndex _ upBitIndex + trailingSize. 1 to: trailingSize do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. ^ upBits ! ! !ImageReadWriter methodsFor: 'testing' stamp: 'tao 10/27/97 09:26'! understandsImageFormat "Test to see if the image stream format is understood by this decoder. This should be implemented in each subclass of ImageReadWriter so that a proper decoder can be selected without ImageReadWriter having to know about all possible image file types." ^ false! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ImageReadWriter class instanceVariableNames: ''! !ImageReadWriter class methodsFor: 'instance creation'! on: aStream "Answer an instance of the receiver for encoding and/or decoding images on the given." ^ self new on: aStream ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:59'! allTypicalFileExtensions "Answer a collection of file extensions (lowercase) which files that my subclasses can read might commonly have" "ImageReadWriter allTypicalFileExtensions" | extensions | extensions _ Set new. self allSubclassesDo: [ :cls | extensions addAll: cls typicalFileExtensions ]. ^extensions! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ls 9/15/1998 19:08'! formFromFileNamed: fileName "Answer a ColorForm stored on the file with the given name." | stream | stream _ FileStream readOnlyFileNamed: fileName. ^self formFromStream: stream! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'sd 1/30/2004 15:18'! formFromStream: aBinaryStream "Answer a ColorForm stored on the given stream. closes the stream" | reader readerClass form | readerClass _ self withAllSubclasses detect: [:subclass | subclass understandsImageFormat: aBinaryStream] ifNone: [ aBinaryStream close. ^self error: 'image format not recognized']. reader _ readerClass new on: aBinaryStream reset. Cursor read showWhile: [ form _ reader nextImage. reader close]. ^ form ! ! !ImageReadWriter class methodsFor: 'image reading/writing'! putForm: aForm onFileNamed: fileName "Store the given form on a file of the given name." | writer | writer _ self on: (FileStream newFileNamed: fileName) binary. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'tk 9/13/97 16:13'! putForm: aForm onStream: aWriteStream "Store the given form on a file of the given name." | writer | writer _ self on: aWriteStream. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:55'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#()! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ar 6/16/2002 17:33'! understandsImageFormat: aStream ^(self new on: aStream) understandsImageFormat! ! Notification subclass: #InMidstOfFileinNotification instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !InMidstOfFileinNotification methodsFor: 'as yet unclassified' stamp: 'RAA 5/28/2001 17:07'! defaultAction self resume: false! ! DisplayObject subclass: #InfiniteForm instanceVariableNames: 'patternForm' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !InfiniteForm commentStamp: '<historical>' prior: 0! I represent a Form obtained by replicating a pattern form indefinitely in all directions.! !InfiniteForm methodsFor: 'accessing' stamp: 'mjg 7/9/2001 14:12'! asColor ^ patternForm dominantColor! ! !InfiniteForm methodsFor: 'accessing'! asForm ^ patternForm! ! !InfiniteForm methodsFor: 'accessing' stamp: 'di 9/2/97 20:21'! dominantColor ^ patternForm dominantColor! ! !InfiniteForm methodsFor: 'accessing'! offset "Refer to the comment in DisplayObject|offset." ^0 @ 0! ! !InfiniteForm methodsFor: 'displaying' stamp: 'sw 2/16/98 03:42'! colorForInsets ^ Color transparent! ! !InfiniteForm methodsFor: 'displaying' stamp: 'nk 4/17/2004 19:48'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "This is the real display message, but it doesn't get used until the new display protocol is installed." | targetBox patternBox bb | (patternForm isForm) ifFalse: [^ aDisplayMedium fill: clipRectangle rule: ruleInteger fillColor: patternForm]. "Do it iteratively" targetBox _ aDisplayMedium boundingBox intersect: clipRectangle. patternBox _ patternForm boundingBox. bb _ BitBlt current destForm: aDisplayMedium sourceForm: patternForm fillColor: aForm combinationRule: ruleInteger destOrigin: 0@0 sourceOrigin: 0@0 extent: patternBox extent clipRect: clipRectangle. bb colorMap: (patternForm colormapIfNeededFor: aDisplayMedium). (targetBox left truncateTo: patternBox width) to: targetBox right - 1 by: patternBox width do: [:x | (targetBox top truncateTo: patternBox height) to: targetBox bottom - 1 by: patternBox height do: [:y | bb destOrigin: x@y; copyBits]]! ! !InfiniteForm methodsFor: 'displaying' stamp: 'nk 4/17/2004 19:48'! displayOnPort: aPort at: offset | targetBox patternBox savedMap top left | self flag: #bob. "this *may* not get called at the moment. I have been trying to figure out the right way for this to work and am using #displayOnPort:offsetBy: as my current offering - Bob" (patternForm isForm) ifFalse: [ "patternForm is a Pattern or Color; just use it as a mask for BitBlt" ^ aPort fill: aPort clipRect fillColor: patternForm rule: Form over]. "do it iteratively" targetBox _ aPort clipRect. patternBox _ patternForm boundingBox. savedMap _ aPort colorMap. aPort sourceForm: patternForm; fillColor: nil; combinationRule: Form paint; sourceRect: (0@0 extent: patternBox extent); colorMap: (patternForm colormapIfNeededFor: aPort destForm). top _ (targetBox top truncateTo: patternBox height) "- (offset y \\ patternBox height)". left _ (targetBox left truncateTo: patternBox width) "- (offset x \\ patternBox width)". left to: (targetBox right - 1) by: patternBox width do: [:x | top to: (targetBox bottom - 1) by: patternBox height do: [:y | aPort destOrigin: x@y; copyBits]]. aPort colorMap: savedMap. ! ! !InfiniteForm methodsFor: 'displaying' stamp: 'ar 8/16/2001 12:47'! raisedColor ^ Color transparent! ! !InfiniteForm methodsFor: 'display box access'! computeBoundingBox "Refer to the comment in DisplayObject|computeBoundingBox." ^0 @ 0 corner: SmallInteger maxVal @ SmallInteger maxVal! ! !InfiniteForm methodsFor: 'private'! form: aForm patternForm _ aForm! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'bolot 9/15/1999 10:13'! bitPatternForDepth: suspectedDepth ^ patternForm! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:56'! direction ^patternForm width @ 0! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:54'! form "Bitmap fills respond to #form" ^patternForm! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:54'! isBitmapFill ^true! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:54'! isGradientFill ^false! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:59'! isOrientedFill ^true! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:54'! isSolidFill ^false! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 9/2/1999 14:32'! isTranslucent "Return true since the bitmap may be translucent and we don't really want to check" ^true! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:57'! normal ^0 @ patternForm height! ! !InfiniteForm methodsFor: 'fillstyle protocol' stamp: 'ar 7/2/1999 14:56'! origin ^0@0! ! !InfiniteForm methodsFor: 'as yet unclassified' stamp: 'RAA 6/1/2000 10:50'! addFillStyleMenuItems: aMenu hand: aHand from: aMorph "Add the items for changing the current fill style of the receiver" "prevents a walkback when control menu is built for morph with me as color"! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! InfiniteForm class instanceVariableNames: ''! !InfiniteForm class methodsFor: 'instance creation'! with: aForm "Answer an instance of me whose pattern form is the argument, aForm." ^self new form: aForm! ! Object subclass: #InputSensor instanceVariableNames: '' classVariableNames: 'ButtonDecodeTable InterruptSemaphore InterruptWatcherProcess KeyDecodeTable' poolDictionaries: '' category: 'Kernel-Processes'! !InputSensor commentStamp: '<historical>' prior: 0! An InputSensor is an interface to the user input devices. There is at least one (sub)instance of InputSensor named Sensor in the system. Class variables: ButtonDecodeTable <ByteArray> - maps mouse buttons as reported by the VM to ones reported in the events. KeyDecodeTable <Dictionary<SmallInteger->SmallInteger>> - maps some keys and their modifiers to other keys (used for instance to map Ctrl-X to Alt-X) InterruptSemaphore <Semaphore> - signalled by the the VM and/or the event loop upon receiving an interrupt keystroke. InterruptWatcherProcess <Process> - waits on the InterruptSemaphore and then responds as appropriate.! !InputSensor methodsFor: 'accessing' stamp: 'ar 10/11/2000 17:34'! eventQueue ^nil! ! !InputSensor methodsFor: 'accessing' stamp: 'ar 10/11/2000 17:35'! eventQueue: aSharedQueue ! ! !InputSensor methodsFor: 'accessing' stamp: 'JMM 10/5/2001 12:54'! flushAllButDandDEvents! ! !InputSensor methodsFor: 'cursor' stamp: 'di 4/13/2000 12:15'! currentCursor "The current cursor is maintained in class Cursor." ^ Cursor currentCursor! ! !InputSensor methodsFor: 'cursor' stamp: 'di 4/13/2000 12:16'! currentCursor: newCursor "The current cursor is maintained in class Cursor." Cursor currentCursor: newCursor.! ! !InputSensor methodsFor: 'cursor'! cursorPoint "Answer a Point indicating the cursor location." ^self mousePoint! ! !InputSensor methodsFor: 'cursor'! cursorPoint: aPoint "Set aPoint to be the current cursor location." ^self primCursorLocPut: aPoint! ! !InputSensor methodsFor: 'initialize' stamp: 'ar 9/26/2000 21:35'! flushEvents "Do nothing"! ! !InputSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 19:45'! shutDown InterruptWatcherProcess ifNotNil: [ InterruptWatcherProcess terminate. InterruptWatcherProcess _ nil ].! ! !InputSensor methodsFor: 'initialize' stamp: 'ar 7/23/2000 00:00'! startUp self installInterruptWatcher.! ! !InputSensor methodsFor: 'keyboard'! flushKeyboard "Remove all characters from the keyboard buffer." [self keyboardPressed] whileTrue: [self keyboard]! ! !InputSensor methodsFor: 'keyboard'! keyboard "Answer the next character from the keyboard." ^ self characterForKeycode: self primKbdNext! ! !InputSensor methodsFor: 'keyboard'! keyboardPeek "Answer the next character in the keyboard buffer without removing it, or nil if it is empty." ^ self characterForKeycode: self primKbdPeek! ! !InputSensor methodsFor: 'keyboard'! keyboardPressed "Answer true if keystrokes are available." ^self primKbdPeek notNil! ! !InputSensor methodsFor: 'modifier keys'! commandKeyPressed "Answer whether the command key on the keyboard is being held down." ^ self primMouseButtons anyMask: 64! ! !InputSensor methodsFor: 'modifier keys'! controlKeyPressed "Answer whether the control key on the keyboard is being held down." ^ self primMouseButtons anyMask: 16! ! !InputSensor methodsFor: 'modifier keys'! leftShiftDown "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." ^ self primMouseButtons anyMask: 8! ! !InputSensor methodsFor: 'modifier keys' stamp: 'jm 5/21/1998 16:13'! shiftPressed "Answer whether the shift key on the keyboard is being held down." ^ self primMouseButtons anyMask: 8 ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:24'! anyButtonPressed "Answer whether at least one mouse button is currently being pressed." ^ self primMouseButtons anyMask: 7 ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:24'! blueButtonPressed "Answer whether only the blue mouse button is being pressed. This is the third mouse button or cmd+click on the Mac." ^ (self primMouseButtons bitAnd: 7) = 1 ! ! !InputSensor methodsFor: 'mouse'! mousePoint "Answer a Point indicating the coordinates of the current mouse location." ^self primMousePt! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:02'! noButtonPressed "Answer whether any mouse button is not being pressed." ^self anyButtonPressed not ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:16'! redButtonPressed "Answer true if only the red mouse button is being pressed. This is the first mouse button, usually the left one." ^ (self primMouseButtons bitAnd: 7) = 4 ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:22'! waitButton "Wait for the user to press any mouse button and then answer with the current location of the cursor." | delay | delay _ Delay forMilliseconds: 50. [self anyButtonPressed] whileFalse: [ delay wait ]. ^self cursorPoint ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:22'! waitButtonOrKeyboard "Wait for the user to press either any mouse button or any key. Answer the current cursor location or nil if a keypress occured." | delay | delay := Delay forMilliseconds: 50. [self anyButtonPressed] whileFalse: [delay wait. self keyboardPressed ifTrue: [^ nil]]. ^ self cursorPoint ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:25'! waitNoButton "Wait for the user to release any mouse button and then answer the current location of the cursor." | delay | delay _ Delay forMilliseconds: 50. [self anyButtonPressed] whileTrue: [ delay wait]. ^self cursorPoint ! ! !InputSensor methodsFor: 'mouse' stamp: 'nk 3/17/2004 07:05'! yellowButtonPressed "Answer whether only the yellow mouse button is being pressed. This is the second mouse button or option+click on the Mac." ^ (self primMouseButtons bitAnd: 7) = 2 ! ! !InputSensor methodsFor: 'tablet' stamp: 'jm 4/13/1999 11:02'! tabletExtent "Answer the full tablet extent in tablet coordinates." | params | params _ self primTabletGetParameters: 1. params ifNil: [^ self error: 'no tablet available']. ^ (params at: 1)@(params at: 2) ! ! !InputSensor methodsFor: 'tablet' stamp: 'jm 4/13/1999 11:12'! tabletPoint "Answer the current position of the first tablet pointing device (pen, puck, or eraser) in tablet coordinates." | data | data _ self primTabletRead: 1. "state of first/primary pen" ^ (data at: 3) @ (data at: 4) ! ! !InputSensor methodsFor: 'tablet' stamp: 'jm 4/12/1999 13:05'! tabletPressure "Answer the current pressure of the first tablet pointing device (pen, puck, or eraser), a number between 0.0 (no pressure) and 1.0 (max pressure)" | params data | params _ self primTabletGetParameters: 1. params ifNil: [^ self]. data _ self primTabletRead: 1. "state of first/primary pen" ^ (data at: 10) asFloat / ((params at: 10) - 1) ! ! !InputSensor methodsFor: 'user interrupts' stamp: 'nk 4/12/2004 19:36'! eventTicklerProcess "Answer my event tickler process, if any" ^nil! ! !InputSensor methodsFor: 'user interrupts' stamp: 'nk 6/21/2004 10:41'! installInterruptWatcher "Initialize the interrupt watcher process. Terminate the old process if any." "Sensor installInterruptWatcher" InterruptWatcherProcess ifNotNil: [InterruptWatcherProcess terminate]. InterruptSemaphore _ Semaphore new. InterruptWatcherProcess _ [self userInterruptWatcher] forkAt: Processor lowIOPriority. self primInterruptSemaphore: InterruptSemaphore.! ! !InputSensor methodsFor: 'user interrupts' stamp: 'nk 10/28/2000 20:33'! interruptWatcherProcess "Answer my interrupt watcher process, if any" ^InterruptWatcherProcess! ! !InputSensor methodsFor: 'user interrupts'! setInterruptKey: anInteger "Register the given keycode as the user interrupt key." self primSetInterruptKey: anInteger. ! ! !InputSensor methodsFor: 'user interrupts' stamp: 'di 2/4/1999 15:24'! userInterruptWatcher "Wait for user interrupts and open a notifier on the active process when one occurs." [true] whileTrue: [ InterruptSemaphore wait. Display deferUpdates: false. Smalltalk at: #SoundPlayer ifPresent: [:theClass | theClass shutDown]. Smalltalk handleUserInterrupt] ! ! !InputSensor methodsFor: 'private'! characterForKeycode: keycode "Map the given keycode to a Smalltalk character object. Encoding: A keycode is 12 bits: <4 modifer bits><8 bit ISO character> Modifier bits are: <command><option><control><shift>" "NOTE: the command and option keys are specific to the Macintosh and may not have equivalents on other platforms." keycode = nil ifTrue: [ ^nil ]. keycode class = Character ifTrue: [ ^keycode ]. "to smooth the transition!!" ^ Character value: (keycode bitAnd: 16rFF)! ! !InputSensor methodsFor: 'private'! primCursorLocPut: aPoint "If the primitive fails, try again with a rounded point." <primitive: 91> ^ self primCursorLocPutAgain: aPoint rounded! ! !InputSensor methodsFor: 'private'! primCursorLocPutAgain: aPoint "Do nothing if primitive is not implemented." <primitive: 91> ^ self! ! !InputSensor methodsFor: 'private' stamp: 'ar 7/23/2000 15:38'! primInterruptSemaphore: aSemaphore "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." <primitive: 134> ^self primitiveFailed "Note: This primitive is obsolete with the new event driven architecture in which EventSensor can handle the interrupts itself. However, for supporting older images running on newer VMs the primitive must still be implemented."! ! !InputSensor methodsFor: 'private'! primKbdNext <primitive: 108> ^ nil! ! !InputSensor methodsFor: 'private'! primKbdPeek <primitive: 109> ^ nil! ! !InputSensor methodsFor: 'private'! primMouseButtons <primitive: 107> ^ 0! ! !InputSensor methodsFor: 'private'! primMousePt "Primitive. Poll the mouse to find out its position. Return a Point. Fail if event-driven tracking is used instead of polling. Optional. See Object documentation whatIsAPrimitive." <primitive: 90> ^ 0@0! ! !InputSensor methodsFor: 'private' stamp: 'ar 7/23/2000 15:38'! primSetInterruptKey: anInteger "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>." <primitive: 133> ^self primitiveFailed "Note: This primitive is obsolete with the new event driven architecture in which EventSensor can handle the interrupts itself. However, for supporting older images running on newer VMs the primitive must still be implemented."! ! !InputSensor methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primTabletGetParameters: cursorIndex "Answer the pen tablet parameters. For parameters that differ from cursor to cursor, answer those associated with the cursor having the given index. Answer nil if there is no pen tablet. The parameters are: 1. tablet width, in tablet units 2. tablet height, in tablet units 3. number of tablet units per inch 4. number of cursors (pens, pucks, etc; some tablets have more than one) 5. this cursor index 6. and 7. x scale and x offset for scaling tablet coordintes (e.g., to fit the screen) 8. and 9. y scale and y offset for scaling tablet coordintes (e.g., to fit the screen) 10. number of pressure levels 11. presure threshold needed close pen tip switch 12. number of pen tilt angles" <primitive: 'primitiveGetTabletParameters' module: 'JoystickTabletPlugin'> ^ nil ! ! !InputSensor methodsFor: 'private' stamp: 'ar 2/2/2001 15:09'! primTabletRead: cursorIndex "Answer the pen tablet data for the cursor having the given index. Answer nil if there is no pen tablet. The data is: 1. index of the cursor to which this data applies 2. timestamp of the last state chance for this cursor 3., 4., and 5. x, y, and z coordinates of the cursor (z is typically 0) 6. and 7. xTilt and yTilt of the cursor; (signed) 8. type of cursor (0 = unknown, 1 = pen, 2 = puck, 3 = eraser) 9. cursor buttons 10. cursor pressure, downward 11. cursor pressure, tangential 12. flags" <primitive: 'primitiveReadTablet' module: 'JoystickTabletPlugin'> self primitiveFailed ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! InputSensor class instanceVariableNames: ''! !InputSensor class methodsFor: 'public'! default "Answer the default system InputSensor, Sensor." ^ Sensor! ! !InputSensor class methodsFor: 'public' stamp: 'nk 7/11/2002 07:09'! installDuplicateKeyEntryFor: c | key | key _ c asInteger. "first do control->alt key" KeyDecodeTable at: { key bitAnd: 16r9F . 2 } put: { key . 8 }. "then alt->alt key" KeyDecodeTable at: { key . 8 } put: { key . 8 } ! ! !InputSensor class methodsFor: 'public' stamp: 'nk 2/11/2002 12:39'! installSwappedKeyEntryFor: c | key | key _ c asInteger. "first do control->alt key" KeyDecodeTable at: { key bitAnd: 16r9F . 2 } put: { key . 8 }. "then alt->control key" KeyDecodeTable at: { key . 8 } put: { key bitAnd: 16r9F . 2 }! ! !InputSensor class methodsFor: 'class initialization' stamp: 'nk 7/11/2002 07:41'! defaultCrossPlatformKeys "Answer a list of key letters that are used for common editing operations on different platforms." ^{ $c . $x . $v . $a . $s . $f . $g . $z } ! ! !InputSensor class methodsFor: 'class initialization' stamp: 'nk 7/11/2002 07:41'! installKeyDecodeTable "Create a decode table that swaps some keys if Preferences swapControlAndAltKeys is set" KeyDecodeTable _ Dictionary new. Preferences duplicateControlAndAltKeys ifTrue: [ self defaultCrossPlatformKeys do: [ :c | self installDuplicateKeyEntryFor: c ] ]. Preferences swapControlAndAltKeys ifTrue: [ self defaultCrossPlatformKeys do: [ :c | self installSwappedKeyEntryFor: c ] ]. ! ! !InputSensor class methodsFor: 'class initialization' stamp: 'nk 2/10/2002 11:55'! installMouseDecodeTable "Create a decode table that swaps the lowest-order 2 bits if Preferences swapMouseButtons is set" ButtonDecodeTable _ Preferences swapMouseButtons ifTrue: [ByteArray withAll: ((0 to: 255) collect: [:ea | ((ea bitAnd: 1) << 1 bitOr: (ea bitAnd: 2) >> 1) bitOr: (ea bitAnd: 16rFC) ])] ifFalse: [ByteArray withAll: (0 to: 255)]! ! !InputSensor class methodsFor: 'system startup' stamp: 'nk 6/21/2004 10:36'! shutDown self default shutDown.! ! !InputSensor class methodsFor: 'system startup' stamp: 'nk 2/10/2002 11:57'! startUp self installMouseDecodeTable. self installKeyDecodeTable. self default startUp! ! StringHolder subclass: #Inspector instanceVariableNames: 'object selectionIndex timeOfLastListUpdate selectionUpdateTime' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !Inspector commentStamp: '<historical>' prior: 0! 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.! !Inspector methodsFor: 'accessing'! baseFieldList "Answer an Array consisting of 'self' and the instance variable names of the inspected object." ^ (Array with: 'self' with: 'all inst vars') , object class allInstVarNames! ! !Inspector methodsFor: 'accessing'! fieldList "Answer the base field list plus an abbreviated list of indices." object class isVariable ifFalse: [^ self baseFieldList]. ^ self baseFieldList , (object basicSize <= (self i1 + self i2) ifTrue: [(1 to: object basicSize) collect: [:i | i printString]] ifFalse: [(1 to: self i1) , (object basicSize-(self i2-1) to: object basicSize) collect: [:i | i printString]])! ! !Inspector methodsFor: 'accessing'! i1 "This is the max index shown before skipping to the last i2 elements of very long arrays" ^ 100! ! !Inspector methodsFor: 'accessing'! i2 "This is the number of elements to show at the end of very long arrays" ^ 10! ! !Inspector methodsFor: 'accessing' stamp: 'sw 5/22/96'! initialExtent "Answer the desired extent for the receiver when it is first opened on the screen. " ^ 250 @ 200! ! !Inspector methodsFor: 'accessing' stamp: 'ajh 2/3/2003 19:19'! inspect: anObject "Initialize the receiver so that it is inspecting anObject. There is no current selection." | c | c _ anObject inspectorClass. (self class ~= c and: [self class format = c format]) ifTrue: [ self primitiveChangeClassTo: c basicNew]. self initialize. object _ anObject. selectionIndex _ 0. contents _ ''! ! !Inspector methodsFor: 'accessing' stamp: 'svp 3/14/2000 21:57'! modelWakeUpIn: aWindow | newText | self updateListsAndCodeIn: aWindow. newText _ self contentsIsString ifTrue: [newText _ self selection] ifFalse: ["keep it short to reduce time to compute it" self selectionPrintString ]. newText = contents ifFalse: [contents _ newText. self changed: #contents]! ! !Inspector methodsFor: 'accessing' stamp: 'sw 10/30/1999 23:59'! noteSelectionIndex: anInteger for: aSymbol aSymbol == #fieldList ifTrue: [selectionIndex _ anInteger]! ! !Inspector methodsFor: 'accessing'! object "Answer the object being inspected by the receiver." ^object! ! !Inspector methodsFor: 'accessing' stamp: 'hg 10/14/2001 16:20'! object: anObject "Set anObject to be the object being inspected by the receiver." | oldIndex | anObject == object ifTrue: [self update] ifFalse: [oldIndex _ selectionIndex <= 2 ifTrue: [selectionIndex] ifFalse: [0]. self inspect: anObject. oldIndex _ oldIndex min: self fieldList size. self changed: #inspectObject. oldIndex > 0 ifTrue: [self toggleIndex: oldIndex]. self changed: #fieldList. self changed: #contents]! ! !Inspector methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:37'! selectedClass "Answer the class of the receiver's current selection" self selectionUnmodifiable ifTrue: [^ object class]. ^ self selection class! ! !Inspector methodsFor: 'accessing' stamp: 'svp 3/14/2000 21:57'! stepAt: millisecondClockValue in: aWindow | newText | (Preferences smartUpdating and: [(millisecondClockValue - self timeOfLastListUpdate) > 8000]) "Not more often than once every 8 seconds" ifTrue: [self updateListsAndCodeIn: aWindow. timeOfLastListUpdate _ millisecondClockValue]. newText _ self contentsIsString ifTrue: [newText _ self selection] ifFalse: ["keep it short to reduce time to compute it" self selectionPrintString ]. newText = contents ifFalse: [contents _ newText. self changed: #contents]! ! !Inspector methodsFor: 'accessing' stamp: 'sma 6/15/2000 16:48'! stepTimeIn: aSystemWindow ^ (selectionUpdateTime ifNil: [0]) * 10 max: 1000! ! !Inspector methodsFor: 'accessing' stamp: 'sw 10/20/1999 15:54'! timeOfLastListUpdate ^ timeOfLastListUpdate ifNil: [timeOfLastListUpdate _ 0]! ! !Inspector methodsFor: 'accessing' stamp: 'tk 4/10/1998 11:28'! trash "What goes in the bottom pane" ^ ''! ! !Inspector methodsFor: 'accessing' stamp: 'tk 6/11/1998 22:23'! trash: newText "Don't save it" ^ true! ! !Inspector methodsFor: 'accessing' stamp: 'hmm 7/12/2001 20:35'! update "Reshow contents, assuming selected value may have changed." selectionIndex = 0 ifFalse: [self contentsIsString ifTrue: [contents _ self selection] ifFalse: [contents _ self selectionPrintString]. self changed: #contents. self changed: #selection. self changed: #selectionIndex]! ! !Inspector methodsFor: 'accessing' stamp: 'di 1/13/1999 14:36'! wantsSteps ^ true! ! !Inspector methodsFor: 'selecting' stamp: 'tk 4/13/1998 09:19'! accept: aString | result | result _ self doItReceiver class evaluatorClass new evaluate: (ReadStream on: aString) in: self doItContext to: self doItReceiver notifying: nil "fix this" ifFail: [^ false]. result == #failedDoit ifFalse: [contents _ result printString. self replaceSelectionValue: result. "may put contents back" self changed: #contents. ^ true]. ^ false! ! !Inspector methodsFor: 'selecting' stamp: 'di 9/22/1998 21:24'! contentsIsString "Hacked so contents empty when deselected and = long printString when item 2" ^ (selectionIndex = 2) | (selectionIndex = 0)! ! !Inspector methodsFor: 'selecting' stamp: 'tk 4/13/1998 09:23'! replaceSelectionValue: anObject "The receiver has a list of variables of its inspected object. One of these is selected. The value of the selected variable is set to the value, anObject." | basicIndex si | selectionIndex <= 2 ifTrue: [ self toggleIndex: (si _ selectionIndex). self toggleIndex: si. ^ object]. object class isVariable ifFalse: [^ object instVarAt: selectionIndex - 2 put: anObject]. basicIndex _ selectionIndex - 2 - object class instSize. (object basicSize <= (self i1 + self i2) or: [basicIndex <= self i1]) ifTrue: [^object basicAt: basicIndex put: anObject] ifFalse: [^object basicAt: object basicSize - (self i1 + self i2) + basicIndex put: anObject]! ! !Inspector methodsFor: 'selecting' stamp: 'hg 10/8/2000 14:46'! selectedSlotName ^ self fieldList at: self selectionIndex! ! !Inspector methodsFor: 'selecting' stamp: 'tk 4/10/1998 17:57'! selection "The receiver has a list of variables of its inspected object. One of these is selected. Answer the value of the selected variable." | basicIndex | selectionIndex = 0 ifTrue: [^ '']. selectionIndex = 1 ifTrue: [^ object]. selectionIndex = 2 ifTrue: [^ object longPrintString]. (selectionIndex - 2) <= object class instSize ifTrue: [^ object instVarAt: selectionIndex - 2]. basicIndex _ selectionIndex - 2 - object class instSize. (object basicSize <= (self i1 + self i2) or: [basicIndex <= self i1]) ifTrue: [^ object basicAt: basicIndex] ifFalse: [^ object basicAt: object basicSize - (self i1 + self i2) + basicIndex]! ! !Inspector methodsFor: 'selecting'! selectionIndex "The receiver has a list of variables of its inspected object. One of these is selected. Answer the index into the list of the selected variable." ^selectionIndex! ! !Inspector methodsFor: 'selecting' stamp: 'sma 6/15/2000 16:45'! selectionPrintString | text nm | selectionUpdateTime _ [text _ [self selection printStringLimitedTo: 5000] on: Error do: [nm _ self selectionIndex < 3 ifTrue: ['self'] ifFalse: [self selectedSlotName]. text _ ('<error in printString: evaluate "' , nm , ' printString" to debug>') asText. text addAttribute: TextColor red from: 1 to: text size. text]] timeToRun. ^ text! ! !Inspector methodsFor: 'selecting'! selectionUnmodifiable "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" ^ selectionIndex <= 2! ! !Inspector methodsFor: 'selecting' stamp: 'sma 6/15/2000 16:50'! toggleIndex: anInteger "The receiver has a list of variables of its inspected object. One of these is selected. If anInteger is the index of this variable, then deselect it. Otherwise, make the variable whose index is anInteger be the selected item." selectionUpdateTime _ 0. selectionIndex = anInteger ifTrue: ["same index, turn off selection" selectionIndex _ 0. contents _ ''] ifFalse: ["different index, new selection" selectionIndex _ anInteger. self contentsIsString ifTrue: [contents _ self selection] ifFalse: [contents _ self selectionPrintString]]. self changed: #selection. self changed: #contents. self changed: #selectionIndex.! ! !Inspector methodsFor: 'code'! doItReceiver "Answer the object that should be informed of the result of evaluating a text selection." ^object! ! !Inspector methodsFor: 'menu commands' stamp: 'BG 10/29/2003 08:14'! addCollectionItemsTo: aMenu "If the current selection is an appropriate collection, add items to aMenu that cater to that kind of selection" | sel | ((((sel _ self selection) isMemberOf: Array) or: [sel isMemberOf: OrderedCollection]) and: [sel size > 0]) ifTrue: [ aMenu addList: #( ('inspect element...' inspectElement))]. ! ! !Inspector methodsFor: 'menu commands' stamp: 'BG 10/28/2003 21:00'! browseFullProtocol "Open up a protocol-category browser on the value of the receiver's current selection. If in mvc, an old-style protocol browser is opened instead." Smalltalk isMorphic ifFalse: [^ self spawnProtocol].! ! !Inspector methodsFor: 'menu commands' stamp: 'nk 7/24/2003 10:11'! chasePointers | saved | self selectionIndex == 0 ifTrue: [^ self changed: #flash]. saved _ self object. [self object: nil. (Smalltalk includesKey: #PointerFinder) ifTrue: [PointerFinder on: saved] ifFalse: [self objectReferencesToSelection]] ensure: [self object: saved]! ! !Inspector methodsFor: 'menu commands' stamp: 'tk 4/10/1998 17:53'! classOfSelection "Answer the class of the receiver's current selection" self selectionUnmodifiable ifTrue: [^ object class]. ^ self selection class! ! !Inspector methodsFor: 'menu commands' stamp: 'sd 4/15/2003 16:14'! classVarRefs "Request a browser of methods that store into a chosen instance variable" | aClass | (aClass _ self classOfSelection) ifNotNil: [self systemNavigation browseClassVarRefs: aClass]. ! ! !Inspector methodsFor: 'menu commands' stamp: 'ar 1/15/2001 18:38'! copyName "Copy the name of the current variable, so the user can paste it into the window below and work with is. If collection, do (xxx at: 1). " | sel aClass | self selectionUnmodifiable ifTrue: [^ self changed: #flash]. (aClass _ self object class) isVariable ifTrue: [^ self changed: #flash]. sel _ aClass allInstVarNames at: selectionIndex - 2. (self selection isKindOf: Collection) ifTrue: [sel _ '(',sel,' at: 1)']. Clipboard clipboardText: sel asText. "no undo allowed"! ! !Inspector methodsFor: 'menu commands' stamp: 'sd 4/15/2003 16:14'! defsOfSelection "Open a browser on all defining references to the selected instance variable, if that's what currently selected. " | aClass sel | self selectionUnmodifiable ifTrue: [^ self changed: #flash]. (aClass _ self object class) isVariable ifTrue: [^ self changed: #flash]. sel _ aClass allInstVarNames at: self selectionIndex - 2. self systemNavigation browseAllStoresInto: sel from: aClass! ! !Inspector methodsFor: 'menu commands' stamp: 'BG 10/28/2003 21:00'! fieldListMenu: aMenu "Arm the supplied menu with items for the field-list of the receiver" aMenu addList: #( ('inspect (i)' inspectSelection)). self addCollectionItemsTo: aMenu. aMenu addList: #( - ('method refs to this inst var' referencesToSelection) ('methods storing into this inst var' defsOfSelection) ('objects pointing to this value' objectReferencesToSelection) ('chase pointers' chasePointers) - ('browse full (b)' browseMethodFull) ('browse class' browseClass) ('browse hierarchy' classHierarchy) ('browse protocol (p)' browseFullProtocol) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' classVarRefs) ('class variables' browseClassVariables) ('class refs (N)' browseClassRefs) - ('copy name (c)' copyName) ('basic inspect' inspectBasic)). ^ aMenu " - ('alias for this value' aliasForValue) ('watcher for this slot' watcherForSlot)" ! ! !Inspector methodsFor: 'menu commands' stamp: 'tk 4/12/1998 08:49'! inspectBasic "Bring up a non-special inspector" selectionIndex = 0 ifTrue: [^ object basicInspect]. self selection basicInspect! ! !Inspector methodsFor: 'menu commands' stamp: 'BG 11/1/2003 22:25'! inspectElement | sel selSize countString count | "Create and schedule an Inspector on an element of the receiver's model's currently selected collection." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ((sel _ self selection) isKindOf: SequenceableCollection) ifFalse: [ ^ sel inspect]. (selSize _ sel size) == 1 ifTrue: [^ sel first inspect]. selSize <= 15 ifTrue: [count _ (SelectionMenu selections: (1 to: selSize) asArray) startUpWithCaption: 'which element?'. count ifNil: [^ self] ifNotNil: [^ (sel at: count) inspect]]. countString _ FillInTheBlank request: 'Which element? (1 - ', selSize printString, ')' initialAnswer: '1'. countString isEmptyOrNil ifTrue: [^ self]. count _ Integer readFrom: (ReadStream on: countString). (count > 0 and: [count <= selSize]) ifTrue: [(sel at: count) inspect] ifFalse: [self beep]! ! !Inspector methodsFor: 'menu commands' stamp: 'sw 1/14/2000 13:39'! inspectSelection "Create and schedule an Inspector on the receiver's model's currently selected object." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ^ self selection inspect! ! !Inspector methodsFor: 'menu commands' stamp: 'BG 8/18/2004 17:07'! inspectorKey: aChar from: view "Respond to a Command key issued while the cursor is over my field list" aChar == $i ifTrue: [^ self selection inspect]. aChar == $I ifTrue: [^ self selection explore]. aChar == $b ifTrue: [^ self browseMethodFull]. aChar == $h ifTrue: [^ self classHierarchy]. aChar == $c ifTrue: [^ self copyName]. aChar == $p ifTrue: [^ self browseFullProtocol]. aChar == $N ifTrue: [^ self browseClassRefs]. "aChar == $t ifTrue: [^ self tearOffTile]." aChar == $v ifTrue: [^ self viewerForValue]. ^ self arrowKey: aChar from: view! ! !Inspector methodsFor: 'menu commands' stamp: 'sd 4/16/2003 11:41'! objectReferencesToSelection "Open a list inspector on all the objects that point to the value of the selected instance variable, if any. " self selectionIndex == 0 ifTrue: [^ self changed: #flash]. self systemNavigation browseAllObjectReferencesTo: self selection except: (Array with: self object) ifNone: [:obj | self changed: #flash]. ! ! !Inspector methodsFor: 'menu commands' stamp: 'sd 4/15/2003 16:14'! referencesToSelection "Open a browser on all references to the selected instance variable, if that's what currently selected. 1/25/96 sw" | aClass sel | self selectionUnmodifiable ifTrue: [^ self changed: #flash]. (aClass _ self object class) isVariable ifTrue: [^ self changed: #flash]. sel _ aClass allInstVarNames at: self selectionIndex - 2. self systemNavigation browseAllAccessesTo: sel from: aClass! ! !Inspector methodsFor: 'menu commands' stamp: 'sw 12/11/2000 15:52'! spawnFullProtocol "Spawn a window showing full protocol for the receiver's selection" | objectToRepresent | objectToRepresent _ self selectionIndex == 0 ifTrue: [object] ifFalse: [self selection]. ProtocolBrowser openFullProtocolForClass: objectToRepresent class! ! !Inspector methodsFor: 'menu commands' stamp: 'sw 12/11/2000 15:52'! spawnProtocol "Spawn a protocol on browser on the receiver's selection" | objectToRepresent | objectToRepresent _ self selectionIndex == 0 ifTrue: [object] ifFalse: [self selection]. ProtocolBrowser openSubProtocolForClass: objectToRepresent class! ! !Inspector methodsFor: 'menu commands' stamp: 'sw 10/23/2000 18:27'! viewerForValue "Open up a viewer on the value of the receiver's current selection" | objectToRepresent | objectToRepresent _ self selectionIndex == 0 ifTrue: [object] ifFalse: [self selection]. objectToRepresent beViewed ! ! !Inspector methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:47'! convertToCurrentVersion: varDict refStream: smartRefStrm timeOfLastListUpdate ifNil: [timeOfLastListUpdate _ 0]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Inspector class instanceVariableNames: ''! !Inspector class methodsFor: 'instance creation' stamp: 'sw 1/19/1999 14:38'! horizontalDividerProportion ^ 0.3! ! !Inspector class methodsFor: 'instance creation'! inspect: anObject "Answer an instance of me to provide an inspector for anObject." ^self new inspect: anObject! ! !Inspector class methodsFor: 'instance creation'! openOn: anObject withEvalPane: withEval "Create and schedule an instance of me on the model, anInspector. " ^ self openOn: anObject withEvalPane: withEval withLabel: anObject defaultLabelForInspector! ! !Inspector class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 14:56'! openOn: anObject withEvalPane: withEval withLabel: label ^ self openOn: anObject withEvalPane: withEval withLabel: label valueViewClass: PluggableTextView ! ! !Inspector class methodsFor: 'instance creation' stamp: 'di 2/16/2000 10:52'! openOn: anObject withEvalPane: withEval withLabel: label valueViewClass: valueViewClass | topView inspector listView valueView evalView | inspector _ self inspect: anObject. topView _ StandardSystemView new model: inspector. topView borderWidth: 1. listView _ PluggableListView on: inspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. (inspector isMemberOf: DictionaryInspector) ifTrue: [listView menu: #dictionaryMenu:]. listView window: (0 @ 0 extent: 40 @ 40). topView addSubView: listView. valueView _ valueViewClass new. "PluggableTextView or PluggableFormView" (valueView respondsTo: #getText) ifTrue: [ valueView on: inspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:]. (valueViewClass inheritsFrom: FormView) ifTrue: [ valueView model: inspector]. valueView window: (0 @ 0 extent: 75 @ 40). topView addSubView: valueView toRightOf: listView. withEval ifTrue: [evalView _ PluggableTextView new on: inspector text: #trash accept: #trash: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. evalView window: (0 @ 0 extent: 115 @ 20). evalView askBeforeDiscardingEdits: false. topView addSubView: evalView below: listView]. topView label: label. topView minimumSize: 180 @ 120. topView setUpdatablePanesFrom: #(fieldList). topView controller open! ! !Inspector class methodsFor: 'instance creation' stamp: 'sw 1/19/1999 14:38'! verticalDividerProportion ^ 0.7! ! Inspector subclass: #InspectorBrowser instanceVariableNames: 'fieldList msgList msgListIndex' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/16/1998 15:51'! fieldList fieldList ifNotNil: [^ fieldList]. ^ (fieldList _ super fieldList)! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/16/1998 15:52'! inspect: anObject "Initialize the receiver so that it is inspecting anObject." fieldList _ nil. super inspect: anObject. msgListIndex _ 0. self changed: #msgText! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/17/1998 10:19'! msgList msgList ifNotNil: [^ msgList]. ^ (msgList _ object class selectors asSortedCollection asArray)! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/16/1998 14:18'! msgListIndex ^msgListIndex! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/16/1998 14:38'! msgText msgListIndex = 0 ifTrue: [^ nil]. ^ object class sourceCodeAt: (msgList at: msgListIndex)! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 4/18/1998 09:48'! step | list fieldString msg | (list _ super fieldList) = fieldList ifFalse: [fieldString _ selectionIndex > 0 ifTrue: [fieldList at: selectionIndex] ifFalse: [nil]. fieldList _ list. selectionIndex _ fieldList indexOf: fieldString ifAbsent: [0]. self changed: #fieldList. self changed: #selectionIndex]. list _ msgList. msgList _ nil. "force recomputation" list = self msgList ifFalse: [msg _ msgListIndex > 0 ifTrue: [list at: msgListIndex] ifFalse: [nil]. msgListIndex _ msgList indexOf: msg ifAbsent: [0]. self changed: #msgList. self changed: #msgListIndex]. super step! ! !InspectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 1/14/1999 09:01'! wantsSteps ^ true! ! Object subclass: #InstructionClient instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !InstructionClient commentStamp: 'md 4/8/2003 12:50' prior: 0! My job is to make it easier to implement clients for InstructionStream. See InstVarRefLocator as an example. ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! blockReturnTop "Return Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! doDup "Duplicate Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! doPop "Remove Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! jump: offset "Unconditional Jump bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! jump: offset if: condition "Conditional Jump bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! methodReturnConstant: value "Return Constant bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:02'! methodReturnReceiver "Return Self bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! methodReturnTop "Return Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! popIntoLiteralVariable: anAssociation "Remove Top Of Stack And Store Into Literal Variable bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! popIntoReceiverVariable: offset "Remove Top Of Stack And Store Into Instance Variable bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! popIntoTemporaryVariable: offset "Remove Top Of Stack And Store Into Temporary Variable bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! pushActiveContext "Push Active Context On Top Of Its Own Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! pushConstant: value "Push Constant, value, on Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! pushLiteralVariable: anAssociation "Push Contents Of anAssociation On Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! pushReceiver "Push Active Context's Receiver on Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:03'! pushReceiverVariable: offset "Push Contents Of the Receiver's Instance Variable Whose Index is the argument, offset, On Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:04'! pushTemporaryVariable: offset "Push Contents Of Temporary Variable Whose Index Is the argument, offset, On Top Of Stack bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:04'! send: selector super: supered numArgs: numberArguments "Send Message With Selector, selector, bytecode. The argument, supered, indicates whether the receiver of the message is specified with 'super' in the source method. The arguments of the message are found in the top numArguments locations on the stack and the receiver just below them." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:04'! storeIntoLiteralVariable: anAssociation "Store Top Of Stack Into Literal Variable Of Method bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:04'! storeIntoReceiverVariable: offset "Store Top Of Stack Into Instance Variable Of Method bytecode." ! ! !InstructionClient methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 13:04'! storeIntoTemporaryVariable: offset "Store Top Of Stack Into Temporary Variable Of Method bytecode." ! ! InstructionClient subclass: #InstructionPrinter instanceVariableNames: 'method scanner stream oldPC indent' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !InstructionPrinter commentStamp: 'md 4/8/2003 12:47' prior: 0! 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 variable method is used to hold the method being printed.! !InstructionPrinter methodsFor: 'accessing' stamp: 'ajh 6/27/2003 22:25'! indent ^ indent ifNil: [0]! ! !InstructionPrinter methodsFor: 'accessing' stamp: 'md 4/8/2003 11:20'! method ^method.! ! !InstructionPrinter methodsFor: 'accessing' stamp: 'md 4/8/2003 11:20'! method: aMethod method := aMethod.! ! !InstructionPrinter methodsFor: 'initialize-release' stamp: 'ajh 2/9/2003 14:16'! indent: numTabs indent _ numTabs! ! !InstructionPrinter methodsFor: 'initialize-release' stamp: 'md 4/8/2003 11:19'! printInstructionsOn: aStream "Append to the stream, aStream, a description of each bytecode in the instruction stream." | end | stream _ aStream. scanner _ InstructionStream on: method. end _ method endPC. oldPC _ scanner pc. [scanner pc <= end] whileTrue: [scanner interpretNextInstructionFor: self]! ! !InstructionPrinter methodsFor: 'instruction decoding'! blockReturnTop "Print the Return Top Of Stack bytecode." self print: 'blockReturn'! ! !InstructionPrinter methodsFor: 'instruction decoding'! doDup "Print the Duplicate Top Of Stack bytecode." self print: 'dup'! ! !InstructionPrinter methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 12:14'! doPop "Print the Remove Top Of Stack bytecode." self print: 'pop'! ! !InstructionPrinter methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 11:13'! jump: offset "Print the Unconditional Jump bytecode." self print: 'jumpTo: ' , (scanner pc + offset) printString! ! !InstructionPrinter methodsFor: 'instruction decoding' stamp: 'md 4/8/2003 11:13'! jump: offset if: condition "Print the Conditional Jump bytecode." self print: (condition ifTrue: ['jumpTrue: '] ifFalse: ['jumpFalse: ']) , (scanner pc + offset) printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! methodReturnConstant: value "Print the Return Constant bytecode." self print: 'return: ' , value printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! methodReturnReceiver "Print the Return Self bytecode." self print: 'returnSelf'! ! !InstructionPrinter methodsFor: 'instruction decoding'! methodReturnTop "Print the Return Top Of Stack bytecode." self print: 'returnTop'! ! !InstructionPrinter methodsFor: 'instruction decoding'! popIntoLiteralVariable: anAssociation "Print the Remove Top Of Stack And Store Into Literal Variable bytecode." self print: 'popIntoLit: ' , anAssociation key! ! !InstructionPrinter methodsFor: 'instruction decoding'! popIntoReceiverVariable: offset "Print the Remove Top Of Stack And Store Into Instance Variable bytecode." self print: 'popIntoRcvr: ' , offset printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! popIntoTemporaryVariable: offset "Print the Remove Top Of Stack And Store Into Temporary Variable bytecode." self print: 'popIntoTemp: ' , offset printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! pushActiveContext "Print the Push Active Context On Top Of Its Own Stack bytecode." self print: 'pushThisContext: '! ! !InstructionPrinter methodsFor: 'instruction decoding'! pushLiteralVariable: anAssociation "Print the Push Contents Of anAssociation On Top Of Stack bytecode." self print: 'pushLit: ' , anAssociation key! ! !InstructionPrinter methodsFor: 'instruction decoding'! pushReceiver "Print the Push Active Context's Receiver on Top Of Stack bytecode." self print: 'self'! ! !InstructionPrinter methodsFor: 'instruction decoding'! pushReceiverVariable: offset "Print the Push Contents Of the Receiver's Instance Variable Whose Index is the argument, offset, On Top Of Stack bytecode." self print: 'pushRcvr: ' , offset printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! pushTemporaryVariable: offset "Print the Push Contents Of Temporary Variable Whose Index Is the argument, offset, On Top Of Stack bytecode." self print: 'pushTemp: ' , offset printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! send: selector super: supered numArgs: numberArguments "Print the Send Message With Selector, selector, bytecode. The argument, supered, indicates whether the receiver of the message is specified with 'super' in the source method. The arguments of the message are found in the top numArguments locations on the stack and the receiver just below them." self print: (supered ifTrue: ['superSend: '] ifFalse: ['send: ']) , selector! ! !InstructionPrinter methodsFor: 'instruction decoding'! storeIntoLiteralVariable: anAssociation "Print the Store Top Of Stack Into Literal Variable Of Method bytecode." self print: 'storeIntoLit: ' , anAssociation key! ! !InstructionPrinter methodsFor: 'instruction decoding'! storeIntoReceiverVariable: offset "Print the Store Top Of Stack Into Instance Variable Of Method bytecode." self print: 'storeIntoRcvr: ' , offset printString! ! !InstructionPrinter methodsFor: 'instruction decoding'! storeIntoTemporaryVariable: offset "Print the Store Top Of Stack Into Temporary Variable Of Method bytecode." self print: 'storeIntoTemp: ' , offset printString! ! !InstructionPrinter methodsFor: 'printing' stamp: 'ajh 6/27/2003 22:26'! print: instruction "Append to the receiver a description of the bytecode, instruction." | code | stream tab: self indent; print: oldPC; space. stream nextPut: $<. oldPC to: scanner pc - 1 do: [:i | code _ (method at: i) radix: 16. stream nextPut: (code size < 5 ifTrue: [$0] ifFalse: [code at: 4]). stream nextPut: code last; space]. stream skip: -1. stream nextPut: $>. stream space. stream nextPutAll: instruction. stream cr. oldPC _ scanner pc. "(InstructionPrinter compiledMethodAt: #print:) symbolic." ! ! !InstructionPrinter methodsFor: 'printing' stamp: 'ajh 6/27/2003 22:26'! pushConstant: obj "Print the Push Constant, obj, on Top Of Stack bytecode." self print: 'pushConstant: ' , (String streamContents: [:s | (obj isKindOf: LookupKey) ifFalse: [s withStyleFor: #literal do: [obj printOn: s]] ifTrue: [obj key ifNotNil: [s nextPutAll: '##'; nextPutAll: obj key] ifNil: [s nextPutAll: '###'; nextPutAll: obj value soleInstance name]] ]). (obj isKindOf: CompiledMethod) ifTrue: [ obj longPrintOn: stream indent: self indent + 2. ^ self]. Smalltalk at: #BlockClosure ifPresent:[:aClass| (obj isKindOf: aClass) ifTrue: [ obj method longPrintOn: stream indent: self indent + 2. ^ self]].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! InstructionPrinter class instanceVariableNames: ''! !InstructionPrinter class methodsFor: 'printing' stamp: 'md 4/8/2003 11:19'! on: aMethod ^self new method: aMethod. ! ! !InstructionPrinter class methodsFor: 'printing'! printClass: class "Create a file whose name is the argument followed by '.bytes'. Store on the file the symbolic form of the compiled methods of the class." | file | file _ FileStream newFileNamed: class name , '.bytes'. class selectors do: [:sel | file cr; nextPutAll: sel; cr. (self on: (class compiledMethodAt: sel)) printInstructionsOn: file]. file close "InstructionPrinter printClass: Parser." ! ! Object subclass: #InstructionStream instanceVariableNames: 'sender pc' classVariableNames: 'SpecialConstants' poolDictionaries: '' category: 'Kernel-Methods'! !InstructionStream commentStamp: '<historical>' prior: 0! 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.! !InstructionStream methodsFor: 'testing'! willJumpIfFalse "Answer whether the next bytecode is a jump-if-false." | byte | byte _ self method at: pc. ^(byte between: 152 and: 159) or: [byte between: 172 and: 175]! ! !InstructionStream methodsFor: 'testing' stamp: 'di 1/29/2000 14:42'! willJumpIfTrue "Answer whether the next bytecode is a jump-if-true." | byte | byte _ self method at: pc. ^ byte between: 168 and: 171! ! !InstructionStream methodsFor: 'testing' stamp: 'sn 8/22/97 21:55'! willReallySend "Answer whether the next bytecode is a real message-send, not blockCopy:." | byte | byte _ self method at: pc. byte < 128 ifTrue: [^false]. byte == 200 ifTrue: [^false]. byte >= 176 ifTrue: [^true]. "special send or short send" ^byte between: 131 and: 134 "long sends"! ! !InstructionStream methodsFor: 'testing'! willReturn "Answer whether the next bytecode is a return." ^(self method at: pc) between: 120 and: 125! ! !InstructionStream methodsFor: 'testing' stamp: 'hmm 7/15/2001 22:00'! willStore "Answer whether the next bytecode is a store or store-pop" | byte | byte _ self method at: pc. ^(byte between: 96 and: 132) and: [ byte <= 111 or: [byte >= 129 and: [ byte <= 130 or: [byte = 132 and: [ (self method at: pc+1) >= 160]]]]]! ! !InstructionStream methodsFor: 'testing'! willStorePop "Answer whether the next bytecode is a store-pop." | byte | byte _ self method at: pc. ^byte = 130 or: [byte between: 96 and: 111]! ! !InstructionStream methodsFor: 'decoding' stamp: 'ajh 7/29/2001 20:45'! atEnd ^ pc > self method endPC! ! !InstructionStream methodsFor: 'decoding'! interpretJump | byte | byte _ self method at: pc. (byte between: 144 and: 151) ifTrue: [pc _ pc + 1. ^byte - 143]. (byte between: 160 and: 167) ifTrue: [pc _ pc + 2. ^(byte - 164) * 256 + (self method at: pc - 1)]. ^nil! ! !InstructionStream methodsFor: 'decoding'! interpretNextInstructionFor: client "Send to the argument, client, a message that specifies the type of the next instruction." | byte type offset method | method _ self method. byte _ method at: pc. type _ byte // 16. offset _ byte \\ 16. pc _ pc+1. type=0 ifTrue: [^client pushReceiverVariable: offset]. type=1 ifTrue: [^client pushTemporaryVariable: offset]. type=2 ifTrue: [^client pushConstant: (method literalAt: offset+1)]. type=3 ifTrue: [^client pushConstant: (method literalAt: offset+17)]. type=4 ifTrue: [^client pushLiteralVariable: (method literalAt: offset+1)]. type=5 ifTrue: [^client pushLiteralVariable: (method literalAt: offset+17)]. type=6 ifTrue: [offset<8 ifTrue: [^client popIntoReceiverVariable: offset] ifFalse: [^client popIntoTemporaryVariable: offset-8]]. type=7 ifTrue: [offset=0 ifTrue: [^client pushReceiver]. offset<8 ifTrue: [^client pushConstant: (SpecialConstants at: offset)]. offset=8 ifTrue: [^client methodReturnReceiver]. offset<12 ifTrue: [^client methodReturnConstant: (SpecialConstants at: offset-8)]. offset=12 ifTrue: [^client methodReturnTop]. offset=13 ifTrue: [^client blockReturnTop]. offset>13 ifTrue: [^self error: 'unusedBytecode']]. type=8 ifTrue: [^self interpretExtension: offset in: method for: client]. type=9 ifTrue: "short jumps" [offset<8 ifTrue: [^client jump: offset+1]. ^client jump: offset-8+1 if: false]. type=10 ifTrue: "long jumps" [byte_ method at: pc. pc_ pc+1. offset<8 ifTrue: [^client jump: offset-4*256 + byte]. ^client jump: (offset bitAnd: 3)*256 + byte if: offset<12]. type=11 ifTrue: [^client send: (Smalltalk specialSelectorAt: offset+1) super: false numArgs: (Smalltalk specialNargsAt: offset+1)]. type=12 ifTrue: [^client send: (Smalltalk specialSelectorAt: offset+17) super: false numArgs: (Smalltalk specialNargsAt: offset+17)]. type>12 ifTrue: [^client send: (method literalAt: offset+1) super: false numArgs: type-13]! ! !InstructionStream methodsFor: 'scanning'! addSelectorTo: set "If this instruction is a send, add its selector to set." | byte literalNumber byte2 | byte _ self method at: pc. byte < 128 ifTrue: [^self]. byte >= 176 ifTrue: ["special byte or short send" byte >= 208 ifTrue: [set add: (self method literalAt: (byte bitAnd: 15) + 1)] ifFalse: [set add: (Smalltalk specialSelectorAt: byte - 176 + 1)]] ifFalse: [(byte between: 131 and: 134) ifTrue: [byte2 _ self method at: pc + 1. byte = 131 ifTrue: [set add: (self method literalAt: byte2 \\ 32 + 1)]. byte = 132 ifTrue: [byte2 < 64 ifTrue: [set add: (self method literalAt: (self method at: pc + 2) + 1)]]. byte = 133 ifTrue: [set add: (self method literalAt: byte2 \\ 32 + 1)]. byte = 134 ifTrue: [set add: (self method literalAt: byte2 \\ 64 + 1)]]]! ! !InstructionStream methodsFor: 'scanning'! followingByte "Answer the next bytecode." ^self method at: pc + 1! ! !InstructionStream methodsFor: 'scanning'! method "Answer the compiled method that supplies the receiver's bytecodes." ^sender "method access when used alone (not as part of a context)"! ! !InstructionStream methodsFor: 'scanning'! nextByte "Answer the next bytecode." ^self method at: pc! ! !InstructionStream methodsFor: 'scanning' stamp: 'ajh 7/18/2003 21:32'! nextInstruction "Return the next bytecode instruction as a message that an InstructionClient would understand. This advances the pc by one instruction." ^ self interpretNextInstructionFor: MessageCatcher new! ! !InstructionStream methodsFor: 'scanning'! pc "Answer the index of the next bytecode." ^pc! ! !InstructionStream methodsFor: 'scanning' stamp: 'ajh 7/18/2003 21:29'! previousPc | currentPc dummy prevPc | currentPc _ pc. pc _ self method initialPC. dummy _ MessageCatcher new. [pc = currentPc] whileFalse: [ prevPc _ pc. self interpretNextInstructionFor: dummy. ]. ^ prevPc! ! !InstructionStream methodsFor: 'scanning'! scanFor: scanBlock "Answer the index of the first bytecode for which scanBlock answer true when supplied with that bytecode." | method end byte type | method _ self method. end _ method endPC. [pc <= end] whileTrue: [(scanBlock value: (byte _ method at: pc)) ifTrue: [^true]. type _ byte // 16. pc _ type = 8 ifTrue: ["extensions" pc + (#(2 2 2 2 3 2 2 1 1 1 ) at: byte \\ 16 + 1)] ifFalse: [type = 10 ifTrue: [pc + 2"long jumps"] ifFalse: [pc + 1]]]. ^false! ! !InstructionStream methodsFor: 'scanning' stamp: 'hmm 7/29/2001 21:25'! skipBackBeforeJump "Assuming that the receiver is positioned jast after a jump, skip back one or two bytes, depending on the size of the previous jump instruction." | strm short | strm _ InstructionStream on: self method. (strm scanFor: [:byte | ((short _ byte between: 152 and: 159) or: [byte between: 168 and: 175]) and: [strm pc = (short ifTrue: [pc-1] ifFalse: [pc-2])]]) ifFalse: [self error: 'Where''s the jump??']. self jump: (short ifTrue: [-1] ifFalse: [-2]). ! ! !InstructionStream methodsFor: 'scanning'! thirdByte "Answer the next bytecode." ^self method at: pc + 2! ! !InstructionStream methodsFor: 'private'! interpretExtension: offset in: method for: client | type offset2 byte2 byte3 | offset <=6 ifTrue: ["Extended op codes 128-134" byte2 _ method at: pc. pc _ pc + 1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type _ byte2 // 64. offset2 _ byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^ client pushReceiverVariable: offset2]. type = 1 ifTrue: [^ client pushTemporaryVariable: offset2]. type = 2 ifTrue: [^ client pushConstant: (method literalAt: offset2 + 1)]. type = 3 ifTrue: [^ client pushLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 1 ifTrue: [type = 0 ifTrue: [^ client storeIntoReceiverVariable: offset2]. type = 1 ifTrue: [^ client storeIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^ client storeIntoLiteralVariable: (method literalAt: offset2 + 1)]]. offset = 2 ifTrue: [type = 0 ifTrue: [^ client popIntoReceiverVariable: offset2]. type = 1 ifTrue: [^ client popIntoTemporaryVariable: offset2]. type = 2 ifTrue: [self error: 'illegalStore']. type = 3 ifTrue: [^ client popIntoLiteralVariable: (method literalAt: offset2 + 1)]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^ client send: (method literalAt: byte2 \\ 32 + 1) super: false numArgs: byte2 // 32]. offset = 4 ifTrue: "Double extended do-anything" [byte3 _ method at: pc. pc _ pc + 1. type _ byte2 // 32. type = 0 ifTrue: [^ client send: (method literalAt: byte3 + 1) super: false numArgs: byte2 \\ 32]. type = 1 ifTrue: [^ client send: (method literalAt: byte3 + 1) super: true numArgs: byte2 \\ 32]. type = 2 ifTrue: [^ client pushReceiverVariable: byte3]. type = 3 ifTrue: [^ client pushConstant: (method literalAt: byte3 + 1)]. type = 4 ifTrue: [^ client pushLiteralVariable: (method literalAt: byte3 + 1)]. type = 5 ifTrue: [^ client storeIntoReceiverVariable: byte3]. type = 6 ifTrue: [^ client popIntoReceiverVariable: byte3]. type = 7 ifTrue: [^ client storeIntoLiteralVariable: (method literalAt: byte3 + 1)]]. offset = 5 ifTrue: "Single extended send to super" [^ client send: (method literalAt: byte2 \\ 32 + 1) super: true numArgs: byte2 // 32]. offset = 6 ifTrue: "Second extended send" [^ client send: (method literalAt: byte2 \\ 64 + 1) super: false numArgs: byte2 // 64]]. offset = 7 ifTrue: [^ client doPop]. offset = 8 ifTrue: [^ client doDup]. offset = 9 ifTrue: [^ client pushActiveContext]. self error: 'unusedBytecode'! ! !InstructionStream methodsFor: 'private'! method: method pc: startpc sender _ method. "allows this class to stand alone as a method scanner" pc _ startpc! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! InstructionStream class instanceVariableNames: ''! !InstructionStream class methodsFor: 'class initialization'! initialize "Initialize an array of special constants returned by single-bytecode returns." SpecialConstants _ (Array with: true with: false with: nil) , (Array with: -1 with: 0 with: 1 with: 2) "InstructionStream initialize." ! ! !InstructionStream class methodsFor: 'instance creation'! on: method "Answer an instance of me on the argument, method." ^self new method: method pc: method initialPC! ! Number subclass: #Integer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !Integer commentStamp: '<historical>' prior: 0! I am a common abstract superclass for all Integer implementations. My implementation subclasses are SmallInteger, LargePositiveInteger, and LargeNegativeInteger. Integer division consists of: / exact division, answers a fraction if result is not a whole integer // answers an Integer, rounded towards negative infinity \\ is modulo rounded towards negative infinity quo: truncated division, rounded towards zero! !Integer methodsFor: 'testing'! even "Refer to the comment in Number|even." ^((self digitAt: 1) bitAnd: 1) = 0! ! !Integer methodsFor: 'testing'! isInteger "True for all subclasses of Integer." ^ true! ! !Integer methodsFor: 'testing' stamp: 'ar 6/9/2000 18:56'! isPowerOfTwo "Return true if the receiver is an integral power of two." ^ (self bitAnd: self-1) = 0! ! !Integer methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:59'! * aNumber "Refer to the comment in Number * " aNumber isInteger ifTrue: [^ self digitMultiply: aNumber neg: self negative ~~ aNumber negative]. ^ aNumber adaptToInteger: self andSend: #*! ! !Integer methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:59'! + aNumber "Refer to the comment in Number + " aNumber isInteger ifTrue: [self negative == aNumber negative ifTrue: [^ (self digitAdd: aNumber) normalize] ifFalse: [^ self digitSubtract: aNumber]]. ^ aNumber adaptToInteger: self andSend: #+! ! !Integer methodsFor: 'arithmetic' stamp: 'di 11/6/1998 13:59'! - aNumber "Refer to the comment in Number - " aNumber isInteger ifTrue: [self negative == aNumber negative ifTrue: [^ self digitSubtract: aNumber] ifFalse: [^ (self digitAdd: aNumber) normalize]]. ^ aNumber adaptToInteger: self andSend: #-! ! !Integer methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:00'! / aNumber "Refer to the comment in Number / " | quoRem | aNumber isInteger ifTrue: [quoRem _ self digitDiv: aNumber abs "*****I've added abs here*****" neg: self negative ~~ aNumber negative. (quoRem at: 2) = 0 ifTrue: [^ (quoRem at: 1) normalize] ifFalse: [^ (Fraction numerator: self denominator: aNumber) reduced]]. ^ aNumber adaptToInteger: self andSend: #/! ! !Integer methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! // aNumber | q | #Numeric. "Changed 200/01/19 For ANSI support." aNumber = 0 ifTrue: [^ (ZeroDivide dividend: self) signal"<- Chg"]. self = 0 ifTrue: [^ 0]. q := self quo: aNumber. "Refer to the comment in Number|//." (q negative ifTrue: [q * aNumber ~= self] ifFalse: [q = 0 and: [self negative ~= aNumber negative]]) ifTrue: [^ q - 1"Truncate towards minus infinity."] ifFalse: [^ q]! ! !Integer methodsFor: 'arithmetic'! alignedTo: anInteger "Answer the smallest number not less than receiver that is a multiple of anInteger." ^(self+anInteger-1//anInteger)*anInteger "5 alignedTo: 2" "12 alignedTo: 3"! ! !Integer methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:00'! quo: aNumber "Refer to the comment in Number quo: " | ng quo | aNumber isInteger ifTrue: [ng _ self negative == aNumber negative == false. quo _ (self digitDiv: (aNumber class == SmallInteger ifTrue: [aNumber abs] ifFalse: [aNumber]) neg: ng) at: 1. ^ quo normalize]. ^ aNumber adaptToInteger: self andSend: #quo:! ! !Integer methodsFor: 'comparing' stamp: 'di 11/6/1998 14:00'! < aNumber aNumber isInteger ifTrue: [self negative == aNumber negative ifTrue: [self negative ifTrue: [^ (self digitCompare: aNumber) > 0] ifFalse: [^ (self digitCompare: aNumber) < 0]] ifFalse: [^ self negative]]. ^ aNumber adaptToInteger: self andSend: #<! ! !Integer methodsFor: 'comparing' stamp: 'di 11/6/1998 14:00'! = aNumber aNumber isNumber ifFalse: [^ false]. aNumber isInteger ifTrue: [aNumber negative == self negative ifTrue: [^ (self digitCompare: aNumber) = 0] ifFalse: [^ false]]. ^ aNumber adaptToInteger: self andSend: #=! ! !Integer methodsFor: 'comparing' stamp: 'di 11/6/1998 14:00'! > aNumber aNumber isInteger ifTrue: [self negative == aNumber negative ifTrue: [self negative ifTrue: [^(self digitCompare: aNumber) < 0] ifFalse: [^(self digitCompare: aNumber) > 0]] ifFalse: [^ aNumber negative]]. ^ aNumber adaptToInteger: self andSend: #>! ! !Integer methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^(self lastDigit bitShift: 8) + (self digitAt: 1)! ! !Integer methodsFor: 'truncation and round off' stamp: 'lr 11/4/2003 12:14'! atRandom "Answer a random integer from 1 to self. This implementation uses a shared generator. Heavy users should their own implementation or use Interval>atRandom: directly." self = 0 ifTrue: [ ^0 ]. self < 0 ifTrue: [ ^self negated atRandom negated ]. ^Collection mutexForPicking critical: [ self atRandom: Collection randomForPicking ]! ! !Integer methodsFor: 'truncation and round off' stamp: 'sma 5/12/2000 12:35'! atRandom: aGenerator "Answer a random integer from 1 to self picked from aGenerator." ^ aGenerator nextInt: self! ! !Integer methodsFor: 'truncation and round off'! ceiling "Refer to the comment in Number|ceiling."! ! !Integer methodsFor: 'truncation and round off'! floor "Refer to the comment in Number|floor."! ! !Integer methodsFor: 'truncation and round off'! normalize "SmallInts OK; LgInts override" ^ self! ! !Integer methodsFor: 'truncation and round off'! rounded "Refer to the comment in Number|rounded."! ! !Integer methodsFor: 'truncation and round off'! truncated "Refer to the comment in Number|truncated."! ! !Integer methodsFor: 'enumerating'! timesRepeat: aBlock "Evaluate the argument, aBlock, the number of times represented by the receiver." | count | count _ 1. [count <= self] whileTrue: [aBlock value. count _ count + 1]! ! !Integer methodsFor: 'mathematical functions' stamp: 'di 4/22/1998 14:45'! factorial "Answer the factorial of the receiver." self = 0 ifTrue: [^ 1]. self > 0 ifTrue: [^ self * (self - 1) factorial]. self error: 'Not valid for negative integers'! ! !Integer methodsFor: 'mathematical functions' stamp: 'LC 6/17/1998 19:22'! gcd: anInteger "See Knuth, Vol 2, 4.5.2, Algorithm L" "Initialize" | higher u v k uHat vHat a b c d vPrime vPrimePrime q t | higher _ SmallInteger maxVal highBit. u _ self abs max: (v _ anInteger abs). v _ self abs min: v. [v class == SmallInteger] whileFalse: [(uHat _ u bitShift: (k _ higher - u highBit)) class == SmallInteger ifFalse: [k _ k - 1. uHat _ uHat bitShift: -1]. vHat _ v bitShift: k. a _ 1. b _ 0. c _ 0. d _ 1. "Test quotient" [(vPrime _ vHat + d) ~= 0 and: [(vPrimePrime _ vHat + c) ~= 0 and: [(q _ uHat + a // vPrimePrime) = (uHat + b // vPrime)]]] whileTrue: ["Emulate Euclid" c _ a - (q * (a _ c)). d _ b - (q * (b _ d)). vHat _ uHat - (q * (uHat _ vHat))]. "Multiprecision step" b = 0 ifTrue: [v _ u rem: (u _ v)] ifFalse: [t _ u * a + (v * b). v _ u * c + (v * d). u _ t]]. ^ v gcd: u! ! !Integer methodsFor: 'mathematical functions'! lcm: n "Answer the least common multiple of the receiver and n." ^self // (self gcd: n) * n! ! !Integer methodsFor: 'mathematical functions' stamp: 'tk 7/30/97 13:08'! take: kk "Return the number of combinations of (self) elements taken kk at a time. For 6 take 3, this is 6*5*4 / (1*2*3). Zero outside of Pascal's triangle. Use a trick to go faster." " 6 take: 3 " | num denom | kk < 0 ifTrue: [^ 0]. kk > self ifTrue: [^ 0]. num _ 1. self to: (kk max: self-kk) + 1 by: -1 do: [:factor | num _ num * factor]. denom _ 1. 1 to: (kk min: self-kk) do: [:factor | denom _ denom * factor]. ^ num // denom! ! !Integer methodsFor: 'bit manipulation'! << shiftAmount "left shift" shiftAmount < 0 ifTrue: [self error: 'negative arg']. ^ self bitShift: shiftAmount! ! !Integer methodsFor: 'bit manipulation' stamp: 'dwh 8/18/1999 21:57'! >> shiftAmount "right shift" shiftAmount < 0 ifTrue: [self error: 'negative arg']. ^ self bitShift: 0 - shiftAmount! ! !Integer methodsFor: 'bit manipulation'! allMask: mask "Treat the argument as a bit mask. Answer whether all of the bits that are 1 in the argument are 1 in the receiver." ^mask = (self bitAnd: mask)! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 11/29/2000 14:32'! anyBitOfMagnitudeFrom: start to: stopArg "Tests for any magnitude bits in the interval from start to stopArg." "Primitive fixed in LargeIntegers v1.2. If you have an earlier version comment out the primitive call (using this ST method then)." | magnitude firstDigitIx lastDigitIx rightShift leftShift stop | <primitive: 'primAnyBitFromTo' module:'LargeIntegers'> start < 1 | (stopArg < 1) ifTrue: [^ self error: 'out of range']. magnitude _ self abs. stop _ stopArg min: magnitude highBit. start > stop ifTrue: [^ false]. firstDigitIx _ start - 1 // 8 + 1. lastDigitIx _ stop - 1 // 8 + 1. rightShift _ (start - 1 \\ 8) negated. leftShift _ 7 - (stop - 1 \\ 8). firstDigitIx = lastDigitIx ifTrue: [| digit mask | mask _ (255 bitShift: rightShift negated) bitAnd: (255 bitShift: leftShift negated). digit _ magnitude digitAt: firstDigitIx. ^ (digit bitAnd: mask) ~= 0]. ((magnitude digitAt: firstDigitIx) bitShift: rightShift) ~= 0 ifTrue: [^ true]. firstDigitIx + 1 to: lastDigitIx - 1 do: [:ix | (magnitude digitAt: ix) ~= 0 ifTrue: [^ true]]. (((magnitude digitAt: lastDigitIx) bitShift: leftShift) bitAnd: 255) ~= 0 ifTrue: [^ true]. ^ false! ! !Integer methodsFor: 'bit manipulation'! anyMask: mask "Treat the argument as a bit mask. Answer whether any of the bits that are 1 in the argument are 1 in the receiver." ^0 ~= (self bitAnd: mask)! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 3/13/2000 17:47'! bitAnd: n "Answer an Integer whose bits are the logical AND of the receiver's bits and those of the argument, n." | norm | <primitive: 'primDigitBitAnd' module:'LargeIntegers'> norm _ n normalize. ^ self digitLogic: norm op: #bitAnd: length: (self digitLength max: norm digitLength)! ! !Integer methodsFor: 'bit manipulation' stamp: 'di 4/30/1998 10:32'! bitClear: aMask "Answer an Integer equal to the receiver, except with all bits cleared that are set in aMask." ^ (self bitOr: aMask) - aMask! ! !Integer methodsFor: 'bit manipulation' stamp: 'wb 4/28/1998 12:17'! bitInvert "Answer an Integer whose bits are the logical negation of the receiver's bits. Numbers are interpreted as having 2's-complement representation." ^ -1 - self! ! !Integer methodsFor: 'bit manipulation'! bitInvert32 "Answer the 32-bit complement of the receiver." ^ self bitXor: 16rFFFFFFFF! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 3/13/2000 17:47'! bitOr: n "Answer an Integer whose bits are the logical OR of the receiver's bits and those of the argument, n." | norm | <primitive: 'primDigitBitOr' module:'LargeIntegers'> norm _ n normalize. ^ self digitLogic: norm op: #bitOr: length: (self digitLength max: norm digitLength)! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 6/9/2000 10:09'! bitShift: shiftCount "Answer an Integer whose value (in twos-complement representation) is the receiver's value (in twos-complement representation) shifted left by the number of bits indicated by the argument. Negative arguments shift right. Zeros are shifted in from the right in left shifts." | magnitudeShift | magnitudeShift _ self bitShiftMagnitude: shiftCount. ^ ((self negative and: [shiftCount negative]) and: [self anyBitOfMagnitudeFrom: 1 to: shiftCount negated]) ifTrue: [magnitudeShift - 1] ifFalse: [magnitudeShift]! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 6/9/2000 14:02'! bitShiftMagnitude: shiftCount "Answer an Integer whose value (in magnitude representation) is the receiver's value (in magnitude representation) shifted left by the number of bits indicated by the argument. Negative arguments shift right. Zeros are shifted in from the right in left shifts." | rShift | <primitive: 'primDigitBitShiftMagnitude' module:'LargeIntegers'> shiftCount >= 0 ifTrue: [^ self digitLshift: shiftCount]. rShift _ 0 - shiftCount. ^ (self digitRshift: (rShift bitAnd: 7) bytes: (rShift bitShift: -3) lookfirst: self digitLength) normalize! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 3/13/2000 17:47'! bitXor: n "Answer an Integer whose bits are the logical XOR of the receiver's bits and those of the argument, n." | norm | <primitive: 'primDigitBitXor' module:'LargeIntegers'> norm _ n normalize. ^ self digitLogic: norm op: #bitXor: length: (self digitLength max: norm digitLength)! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:13'! highBit "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. Raise an error if the receiver is negative, since negative integers are defined to have an infinite number of leading 1's in 2's-complement arithmetic. Use >>highBitOfMagnitude if you want to get the highest bit of the magnitude." ^ self subclassResponsibility! ! !Integer methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 01:55'! highBitOfMagnitude "Answer the index of the high order bit of the magnitude of the receiver, or zero if the receiver is zero." ^ self subclassResponsibility! ! !Integer methodsFor: 'bit manipulation' stamp: 'jm 2/19/98 12:11'! lowBit "Answer the index of the low order bit of this number." | index | self = 0 ifTrue: [ ^ 0 ]. index := 1. [ (self digitAt: index) = 0 ] whileTrue: [ index := index + 1 ]. ^ (self digitAt: index) lowBit + (8 * (index - 1))! ! !Integer methodsFor: 'bit manipulation'! noMask: mask "Treat the argument as a bit mask. Answer whether none of the bits that are 1 in the argument are 1 in the receiver." ^0 = (self bitAnd: mask)! ! !Integer methodsFor: 'converting' stamp: 'di 11/6/1998 13:43'! adaptToFraction: rcvr andSend: selector "If I am involved in arithmetic with a Fraction, convert me to a Fraction." ^ rcvr perform: selector with: self asFraction! ! !Integer methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector "Convert me to a ScaledDecimal and do the arithmetic. receiverScaledDecimal arithmeticOpSelector self." #Numeric. "add 200/01/19 For ScaledDecimal support." ^ receiverScaledDecimal perform: arithmeticOpSelector with: (self asScaledDecimal: 0)! ! !Integer methodsFor: 'converting'! asCharacter "Answer the Character whose value is the receiver." ^Character value: self! ! !Integer methodsFor: 'converting' stamp: 'ar 10/31/1998 23:04'! asColorOfDepth: d "Return a color value representing the receiver as color of the given depth" ^Color colorFromPixelValue: self depth: d! ! !Integer methodsFor: 'converting' stamp: 'di 1/13/1999 12:45'! asFloat "Answer a Float that represents the value of the receiver. Optimized to process only the significant digits of a LargeInteger. SqR: 11/30/1998 21:11" | sum firstByte shift | shift _ 0. sum _ 0.0. firstByte _ self size - 7 max: 1. firstByte to: self size do: [:byteIndex | sum _ ((self digitAt: byteIndex) asFloat timesTwoPower: shift) + sum. shift _ shift + 8]. ^sum * self sign asFloat timesTwoPower: firstByte - 1 * 8! ! !Integer methodsFor: 'converting'! asFraction "Answer a Fraction that represents value of the the receiver." ^Fraction numerator: self denominator: 1! ! !Integer methodsFor: 'converting' stamp: 'ls 5/26/1998 20:53'! asHexDigit ^'0123456789ABCDEF' at: self+1! ! !Integer methodsFor: 'converting'! asInteger "Answer with the receiver itself." ^self ! ! !Integer methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! asScaledDecimal: scaleNotUsed "The number of significant digits of the answer is the same as the number of decimal digits in the receiver. The scale of the answer is 0." #Numeric. "add 200/01/19 For <integer> protocol." ^ ScaledDecimal newFromNumber: self scale: 0! ! !Integer methodsFor: 'converting' stamp: 'brp 5/13/2003 10:12'! asYear ^ Year year: self ! ! !Integer methodsFor: 'printing' stamp: 'sw 11/24/1998 14:53'! asStringWithCommas "123456789 asStringWithCommas" "-123456789 asStringWithCommas" | digits | digits _ self abs printString. ^ String streamContents: [:strm | self sign = -1 ifTrue: [strm nextPut: $-]. 1 to: digits size do: [:i | strm nextPut: (digits at: i). (i < digits size and: [(i - digits size) \\ 3 = 0]) ifTrue: [strm nextPut: $,]]]! ! !Integer methodsFor: 'printing' stamp: 'sw 11/13/1999 23:00'! asTwoCharacterString "Answer a two-character string representing the receiver, with leading zero if required. Intended for use with integers in the range 0 to 99, but plausible replies given for other values too" ^ (self >= 0 and: [self < 10]) ifTrue: ['0', self printString] ifFalse: [self printString copyFrom: 1 to: 2] " 2 asTwoCharacterString 11 asTwoCharacterString 1943 asTwoCharacterString 0 asTwoCharacterString -2 asTwoCharacterString -234 asTwoCharacterString "! ! !Integer methodsFor: 'printing' stamp: 'tk 4/1/2002 11:30'! asWords "SmallInteger maxVal asWords" | mils minus three num answer milCount | self = 0 ifTrue: [^'zero']. mils _ #('' ' thousand' ' million' ' billion' ' trillion' ' quadrillion' ' quintillion' ' sextillion' ' septillion' ' octillion' ' nonillion' ' decillion' ' undecillion' ' duodecillion' ' tredecillion' ' quattuordecillion' ' quindecillion' ' sexdecillion' ' septendecillion' ' octodecillion' ' novemdecillion' ' vigintillion'). num _ self. minus _ ''. self < 0 ifTrue: [ minus _ 'negative '. num _ num negated. ]. answer _ String new. milCount _ 1. [num > 0] whileTrue: [ three _ (num \\ 1000) threeDigitName. num _ num // 1000. three isEmpty ifFalse: [ answer isEmpty ifFalse: [ answer _ ', ',answer ]. answer _ three,(mils at: milCount),answer. ]. milCount _ milCount + 1. ]. ^minus,answer! ! !Integer methodsFor: 'printing'! hex ^ self printStringBase: 16! ! !Integer methodsFor: 'printing'! hex8 "16r3333 hex8" | hex | hex _ self hex. "16rNNN" hex size < 11 ifTrue: [^ hex copyReplaceFrom: 4 to: 3 with: ('00000000' copyFrom: 1 to: 11-hex size)] ifFalse: [^ hex]! ! !Integer methodsFor: 'printing'! isLiteral ^true! ! !Integer methodsFor: 'printing' stamp: 'gk 11/26/2003 10:26'! printOn: aStream base: base "Print a representation of the receiver on the stream <aStream> in base <base> where 2 <= <baseInteger> <= 16. If <base> is other than 10 it is written first separated by $r followed by the number like for example: 16rFCE2" | current letters digits quo i | self < 0 ifTrue: [ aStream nextPut: $-. ^self negated printOn: aStream base: base]. digits _ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'. base = 10 ifFalse: [aStream print: base; nextPut: $r]. current _ self. i _ self digitLength * 8. letters _ String new: i. [current < base] whileFalse: [quo _ current quo: base. letters at: i put: (digits at: (current - (quo * base)) + 1). i _ i - 1. current _ quo]. letters at: i put: (digits at: current + 1). aStream nextPutAll: (letters copyFrom: i to: letters size)! ! !Integer methodsFor: 'printing'! radix: radix "Answer a String representing the receiver as a base radix integer." ^ self printStringBase: radix! ! !Integer methodsFor: 'system primitives' stamp: 'tk 3/24/1999 20:26'! lastDigit "Answer the last digit of the integer base 256. LargePositiveInteger uses bytes of base two number, and each is a 'digit'." ^self digitAt: self digitLength! ! !Integer methodsFor: 'system primitives'! replaceFrom: start to: stop with: replacement startingAt: repStart | j | "Catches failure if LgInt replace primitive fails" j _ repStart. start to: stop do: [:i | self digitAt: i put: (replacement digitAt: j). j _ j+1]! ! !Integer methodsFor: 'private'! copyto: x | stop | stop _ self digitLength min: x digitLength. ^ x replaceFrom: 1 to: stop with: self startingAt: 1! ! !Integer methodsFor: 'private' stamp: 'sr 1/23/2000 05:41'! digitAdd: arg | len arglen accum sum | <primitive: 'primDigitAdd' module:'LargeIntegers'> accum _ 0. (len _ self digitLength) < (arglen _ arg digitLength) ifTrue: [len _ arglen]. "Open code max: for speed" sum _ Integer new: len neg: self negative. 1 to: len do: [:i | accum _ (accum bitShift: -8) + (self digitAt: i) + (arg digitAt: i). sum digitAt: i put: (accum bitAnd: 255)]. accum > 255 ifTrue: [sum _ sum growby: 1. sum at: sum digitLength put: (accum bitShift: -8)]. ^ sum! ! !Integer methodsFor: 'private' stamp: 'sr 1/23/2000 05:43'! digitCompare: arg "Compare the magnitude of self with that of arg. Return a code of 1, 0, -1 for self >, = , < arg" | len arglen argDigit selfDigit | <primitive: 'primDigitCompare' module:'LargeIntegers'> len _ self digitLength. (arglen _ arg digitLength) ~= len ifTrue: [arglen > len ifTrue: [^ -1] ifFalse: [^ 1]]. [len > 0] whileTrue: [(argDigit _ arg digitAt: len) ~= (selfDigit _ self digitAt: len) ifTrue: [argDigit < selfDigit ifTrue: [^ 1] ifFalse: [^ -1]]. len _ len - 1]. ^ 0! ! !Integer methodsFor: 'private' stamp: 'sr 6/8/2000 01:28'! digitDiv: arg neg: ng "Answer with an array of (quotient, remainder)." | quo rem ql d div dh dnh dl qhi qlo j l hi lo r3 a t | <primitive: 'primDigitDivNegative' module:'LargeIntegers'> arg = 0 ifTrue: [^ (ZeroDivide dividend: self) signal]. "TFEI added this line" l _ self digitLength - arg digitLength + 1. l <= 0 ifTrue: [^ Array with: 0 with: self]. "shortcut against #highBit" d _ 8 - arg lastDigit highBitOfPositiveReceiver. div _ arg digitLshift: d. div _ div growto: div digitLength + 1. "shifts so high order word is >=128" rem _ self digitLshift: d. rem digitLength = self digitLength ifTrue: [rem _ rem growto: self digitLength + 1]. "makes a copy and shifts" quo _ Integer new: l neg: ng. dl _ div digitLength - 1. "Last actual byte of data" ql _ l. dh _ div digitAt: dl. dnh _ dl = 1 ifTrue: [0] ifFalse: [div digitAt: dl - 1]. 1 to: ql do: [:k | "maintain quo*arg+rem=self" "Estimate rem/div by dividing the leading to bytes of rem by dh." "The estimate is q = qhi*16+qlo, where qhi and qlo are nibbles." j _ rem digitLength + 1 - k. "r1 _ rem digitAt: j." (rem digitAt: j) = dh ifTrue: [qhi _ qlo _ 15 "i.e. q=255"] ifFalse: ["Compute q = (r1,r2)//dh, t = (r1,r2)\\dh. Note that r1,r2 are bytes, not nibbles. Be careful not to generate intermediate results exceeding 13 bits." "r2 _ (rem digitAt: j - 1)." t _ ((rem digitAt: j) bitShift: 4) + ((rem digitAt: j - 1) bitShift: -4). qhi _ t // dh. t _ (t \\ dh bitShift: 4) + ((rem digitAt: j - 1) bitAnd: 15). qlo _ t // dh. t _ t \\ dh. "Next compute (hi,lo) _ q*dnh" hi _ qhi * dnh. lo _ qlo * dnh + ((hi bitAnd: 15) bitShift: 4). hi _ (hi bitShift: -4) + (lo bitShift: -8). lo _ lo bitAnd: 255. "Correct overestimate of q. Max of 2 iterations through loop -- see Knuth vol. 2" r3 _ j < 3 ifTrue: [0] ifFalse: [rem digitAt: j - 2]. [(t < hi or: [t = hi and: [r3 < lo]]) and: ["i.e. (t,r3) < (hi,lo)" qlo _ qlo - 1. lo _ lo - dnh. lo < 0 ifTrue: [hi _ hi - 1. lo _ lo + 256]. hi >= dh]] whileTrue: [hi _ hi - dh]. qlo < 0 ifTrue: [qhi _ qhi - 1. qlo _ qlo + 16]]. "Subtract q*div from rem" l _ j - dl. a _ 0. 1 to: div digitLength do: [:i | hi _ (div digitAt: i) * qhi. lo _ a + (rem digitAt: l) - ((hi bitAnd: 15) bitShift: 4) - ((div digitAt: i) * qlo). rem digitAt: l put: lo - (lo // 256 * 256). "sign-tolerant form of (lo bitAnd: 255)" a _ lo // 256 - (hi bitShift: -4). l _ l + 1]. a < 0 ifTrue: ["Add div back into rem, decrease q by 1" qlo _ qlo - 1. l _ j - dl. a _ 0. 1 to: div digitLength do: [:i | a _ (a bitShift: -8) + (rem digitAt: l) + (div digitAt: i). rem digitAt: l put: (a bitAnd: 255). l _ l + 1]]. quo digitAt: quo digitLength + 1 - k put: (qhi bitShift: 4) + qlo]. rem _ rem digitRshift: d bytes: 0 lookfirst: dl. ^ Array with: quo with: rem! ! !Integer methodsFor: 'private' stamp: 'hmm 1/7/2002 20:55'! digitLogic: arg op: op length: len | result neg1 neg2 rneg z1 z2 rz b1 b2 b | neg1 _ self negative. neg2 _ arg negative. rneg _ ((neg1 ifTrue: [-1] ifFalse: [0]) perform: op with: (neg2 ifTrue: [-1] ifFalse: [0])) < 0. result _ Integer new: len neg: rneg. rz _ z1 _ z2 _ true. 1 to: result digitLength do: [:i | b1 _ self digitAt: i. neg1 ifTrue: [b1 _ z1 ifTrue: [b1 = 0 ifTrue: [0] ifFalse: [z1 _ false. 256 - b1]] ifFalse: [255 - b1]]. b2 _ arg digitAt: i. neg2 ifTrue: [b2 _ z2 ifTrue: [b2 = 0 ifTrue: [0] ifFalse: [z2 _ false. 256 - b2]] ifFalse: [255 - b2]]. b _ b1 perform: op with: b2. result digitAt: i put: (rneg ifTrue: [rz ifTrue: [b = 0 ifTrue: [0] ifFalse: [rz _ false. 256 - b]] ifFalse: [255 - b]] ifFalse: [b])]. ^ result normalize! ! !Integer methodsFor: 'private' stamp: 'sr 6/8/2000 01:30'! digitLshift: shiftCount | carry rShift mask len result digit byteShift bitShift highBit | (highBit _ self highBitOfMagnitude) = 0 ifTrue: [^ 0]. len _ highBit + shiftCount + 7 // 8. result _ Integer new: len neg: self negative. byteShift _ shiftCount // 8. bitShift _ shiftCount \\ 8. bitShift = 0 ifTrue: ["Fast version for byte-aligned shifts" ^ result replaceFrom: byteShift + 1 to: len with: self startingAt: 1]. carry _ 0. rShift _ bitShift - 8. mask _ 255 bitShift: 0 - bitShift. 1 to: byteShift do: [:i | result digitAt: i put: 0]. 1 to: len - byteShift do: [:i | digit _ self digitAt: i. result digitAt: i + byteShift put: (((digit bitAnd: mask) bitShift: bitShift) bitOr: carry). carry _ digit bitShift: rShift]. ^ result! ! !Integer methodsFor: 'private' stamp: 'sr 1/23/2000 05:46'! digitMultiply: arg neg: ng | prod prodLen carry digit k ab | <primitive: 'primDigitMultiplyNegative' module:'LargeIntegers'> (arg digitLength = 1 and: [(arg digitAt: 1) = 0]) ifTrue: [^ 0]. (self digitLength = 1 and: [(self digitAt: 1) = 0]) ifTrue: [^ 0]. prodLen _ self digitLength + arg digitLength. prod _ Integer new: prodLen neg: ng. "prod starts out all zero" 1 to: self digitLength do: [:i | (digit _ self digitAt: i) ~= 0 ifTrue: [k _ i. carry _ 0. "Loop invariant: 0<=carry<=0377, k=i+j-1" 1 to: arg digitLength do: [:j | ab _ (arg digitAt: j) * digit + carry + (prod digitAt: k). carry _ ab bitShift: -8. prod digitAt: k put: (ab bitAnd: 255). k _ k + 1]. prod digitAt: k put: carry]]. ^ prod normalize! ! !Integer methodsFor: 'private'! digitRshift: anInteger bytes: b lookfirst: a "Shift right 8*b+anInteger bits, 0<=n<8. Discard all digits beyond a, and all zeroes at or below a." | n x r f m digit count i | n _ 0 - anInteger. x _ 0. f _ n + 8. i _ a. m _ 255 bitShift: 0 - f. digit _ self digitAt: i. [((digit bitShift: n) bitOr: x) = 0 and: [i ~= 1]] whileTrue: [x _ digit bitShift: f "Can't exceed 8 bits". i _ i - 1. digit _ self digitAt: i]. i <= b ifTrue: [^Integer new: 0 neg: self negative]. "All bits lost" r _ Integer new: i - b neg: self negative. count _ i. x _ (self digitAt: b + 1) bitShift: n. b + 1 to: count do: [:j | digit _ self digitAt: j + 1. r digitAt: j - b put: (((digit bitAnd: m) bitShift: f) bitOr: x) "Avoid values > 8 bits". x _ digit bitShift: n]. ^r! ! !Integer methodsFor: 'private' stamp: 'sr 1/23/2000 05:46'! digitSubtract: arg | smaller larger z sum sl al ng | <primitive: 'primDigitSubtract' module:'LargeIntegers'> sl _ self digitLength. al _ arg digitLength. (sl = al ifTrue: [[(self digitAt: sl) = (arg digitAt: sl) and: [sl > 1]] whileTrue: [sl _ sl - 1]. al _ sl. (self digitAt: sl) < (arg digitAt: sl)] ifFalse: [sl < al]) ifTrue: [larger _ arg. smaller _ self. ng _ self negative == false. sl _ al] ifFalse: [larger _ self. smaller _ arg. ng _ self negative]. sum _ Integer new: sl neg: ng. z _ 0. "Loop invariant is -1<=z<=1" 1 to: sl do: [:i | z _ z + (larger digitAt: i) - (smaller digitAt: i). sum digitAt: i put: z - (z // 256 * 256). "sign-tolerant form of (z bitAnd: 255)" z _ z // 256]. ^ sum normalize! ! !Integer methodsFor: 'private'! growby: n ^self growto: self digitLength + n! ! !Integer methodsFor: 'private'! growto: n ^self copyto: (self species new: n)! ! !Integer methodsFor: 'benchmarks' stamp: 'jm 11/20/1998 07:06'! benchFib "Handy send-heavy benchmark" "(result // seconds to run) = approx calls per second" " | r t | t _ Time millisecondsToRun: [r _ 26 benchFib]. (r * 1000) // t" "138000 on a Mac 8100/100" ^ self < 2 ifTrue: [1] ifFalse: [(self-1) benchFib + (self-2) benchFib + 1] ! ! !Integer methodsFor: 'benchmarks' stamp: 'di 4/11/1999 11:20'! benchmark "Handy bytecode-heavy benchmark" "(500000 // time to run) = approx bytecodes per second" "5000000 // (Time millisecondsToRun: [10 benchmark]) * 1000" "3059000 on a Mac 8100/100" | size flags prime k count | size _ 8190. 1 to: self do: [:iter | count _ 0. flags _ (Array new: size) atAllPut: true. 1 to: size do: [:i | (flags at: i) ifTrue: [prime _ i+1. k _ i + prime. [k <= size] whileTrue: [flags at: k put: false. k _ k + prime]. count _ count + 1]]]. ^ count! ! !Integer methodsFor: 'benchmarks' stamp: 'dwh 11/21/1999 16:40'! tinyBenchmarks "Report the results of running the two tiny Squeak benchmarks. ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results" "0 tinyBenchmarks" "On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec" "On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec" | t1 t2 r n1 n2 | n1 _ 1. [t1 _ Time millisecondsToRun: [n1 benchmark]. t1 < 1000] whileTrue:[n1 _ n1 * 2]. "Note: #benchmark's runtime is about O(n)" n2 _ 28. [t2 _ Time millisecondsToRun: [r _ n2 benchFib]. t2 < 1000] whileTrue:[n2 _ n2 + 1]. "Note: #benchFib's runtime is about O(k^n), where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...." ^ ((n1 * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', ((r * 1000) // t2) printString, ' sends/sec'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Integer class instanceVariableNames: ''! !Integer class methodsFor: 'instance creation' stamp: 'tk 4/20/1999 14:18'! basicNew self == Integer ifTrue: [ ^ self error: 'Integer is an abstract class. Make a concrete subclass.']. ^ super basicNew! ! !Integer class methodsFor: 'instance creation' stamp: 'sw 5/8/2000 11:05'! initializedInstance ^ 2468! ! !Integer class methodsFor: 'instance creation' stamp: 'tk 4/18/1999 22:01'! new self == Integer ifTrue: [ ^ self error: 'Integer is an abstract class. Make a concrete subclass.']. ^ super new! ! !Integer class methodsFor: 'instance creation'! new: length neg: neg "Answer an instance of a large integer whose size is length. neg is a flag determining whether the integer is negative or not." neg ifTrue: [^LargeNegativeInteger new: length] ifFalse: [^LargePositiveInteger new: length]! ! !Integer class methodsFor: 'instance creation'! readFrom: aStream "Answer a new Integer as described on the stream, aStream. Embedded radix specifiers not allowed - use Number readFrom: for that." ^self readFrom: aStream base: 10! ! !Integer class methodsFor: 'instance creation' stamp: 'ls 6/23/1999 20:37'! readFrom: aStream base: base "Answer an instance of one of my concrete subclasses. Initial minus sign accepted, and bases > 10 use letters A-Z. Embedded radix specifiers not allowed--use Number readFrom: for that. Answer zero (not an error) if there are no digits." | digit value neg startPos | neg _ aStream peekFor: $-. neg ifFalse: [aStream peekFor: $+]. value _ 0. startPos _ aStream position. [aStream atEnd] whileFalse: [digit _ aStream next digitValue. (digit < 0 or: [digit >= base]) ifTrue: [aStream skip: -1. aStream position = startPos ifTrue: [self error: 'At least one digit expected here']. neg ifTrue: [^ value negated]. ^ value] ifFalse: [value _ value * base + digit]]. neg ifTrue: [^ value negated]. ^ value! ! !Integer class methodsFor: 'prime numbers' stamp: 'ar 10/6/2001 02:38'! largePrimesUpTo: max do: aBlock "Evaluate aBlock with all primes up to maxValue. The Algorithm is adapted from http://www.rsok.com/~jrm/printprimes.html It encodes prime numbers much more compactly than #primesUpTo: 38.5 integer per byte (2310 numbers per 60 byte) allow for some fun large primes. (all primes up to SmallInteger maxVal can be computed within ~27MB of memory; the regular #primesUpTo: would require 4 *GIGA*bytes). Note: The algorithm could be re-written to produce the first primes (which require the longest time to sieve) faster but only at the cost of clarity." | limit flags maskBitIndex bitIndex maskBit byteIndex index primesUpTo2310 indexLimit | limit _ max asInteger - 1. indexLimit _ max sqrt truncated + 1. "Create the array of flags." flags _ ByteArray new: (limit + 2309) // 2310 * 60 + 60. flags atAllPut: 16rFF. "set all to true" "Compute the primes up to 2310" primesUpTo2310 _ self primesUpTo: 2310. "Create a mapping from 2310 integers to 480 bits (60 byte)" maskBitIndex _ Array new: 2310. bitIndex _ -1. "for pre-increment" maskBitIndex at: 1 put: (bitIndex _ bitIndex + 1). maskBitIndex at: 2 put: (bitIndex _ bitIndex + 1). 1 to: 5 do:[:i| aBlock value: (primesUpTo2310 at: i)]. index _ 6. 2 to: 2309 do:[:n| [(primesUpTo2310 at: index) < n] whileTrue:[index _ index + 1]. n = (primesUpTo2310 at: index) ifTrue:[ maskBitIndex at: n+1 put: (bitIndex _ bitIndex + 1). ] ifFalse:[ "if modulo any of the prime factors of 2310, then could not be prime" (n \\ 2 = 0 or:[n \\ 3 = 0 or:[n \\ 5 = 0 or:[n \\ 7 = 0 or:[n \\ 11 = 0]]]]) ifTrue:[maskBitIndex at: n+1 put: 0] ifFalse:[maskBitIndex at: n+1 put: (bitIndex _ bitIndex + 1)]. ]. ]. "Now the real work begins... Start with 13 since multiples of 2,3,5,7,11 are handled by the storage method; increment by 2 for odd numbers only." 13 to: limit by: 2 do:[:n| (maskBit _ maskBitIndex at: (n \\ 2310 + 1)) = 0 ifFalse:["not a multiple of 2,3,5,7,11" byteIndex _ n // 2310 * 60 + (maskBit-1 bitShift: -3) + 1. bitIndex _ 1 bitShift: (maskBit bitAnd: 7). ((flags at: byteIndex) bitAnd: bitIndex) = 0 ifFalse:["not marked -- n is prime" aBlock value: n. "Start with n*n since any integer < n has already been sieved (e.g., any multiple of n with a number k < n has been cleared when k was sieved); add 2 * i to avoid even numbers and mark all multiples of this prime. Note: n < indexLimit below limits running into LargeInts -- nothing more." n < indexLimit ifTrue:[ index _ n * n. (index bitAnd: 1) = 0 ifTrue:[index _ index + n]. [index <= limit] whileTrue:[ (maskBit _ maskBitIndex at: (index \\ 2310 + 1)) = 0 ifFalse:[ byteIndex _ (index // 2310 * 60) + (maskBit-1 bitShift: -3) + 1. maskBit _ 255 - (1 bitShift: (maskBit bitAnd: 7)). flags at: byteIndex put: ((flags at: byteIndex) bitAnd: maskBit). ]. index _ index + (2 * n)]. ]. ]. ]. ]. ! ! !Integer class methodsFor: 'prime numbers' stamp: 'ar 10/6/2001 19:33'! primesUpTo: max "Return a list of prime integers up to the given integer." "Integer primesUpTo: 100" ^Array streamContents:[:s| self primesUpTo: max do:[:prime| s nextPut: prime]]! ! !Integer class methodsFor: 'prime numbers' stamp: 'ar 10/6/2001 19:33'! primesUpTo: max do: aBlock "Compute aBlock with all prime integers up to the given integer." "Integer primesUpTo: 100" | limit flags prime k | limit _ max asInteger - 1. "Fall back into #largePrimesUpTo:do: if we'd require more than 100k of memory; the alternative will only requre 1/154th of the amount we need here and is almost as fast." limit > 25000 ifTrue:[^self largePrimesUpTo: max do: aBlock]. flags _ (Array new: limit) atAllPut: true. 1 to: limit do: [:i | (flags at: i) ifTrue: [ prime _ i + 1. k _ i + prime. [k <= limit] whileTrue: [ flags at: k put: false. k _ k + prime]. aBlock value: prime]]. ! ! !Integer class methodsFor: 'constants' stamp: 'RAH 4/25/2000 19:49'! one #Numeric. "add 200/01/19 For <number> protocol support." ^ 1! ! ArrayedCollection variableWordSubclass: #IntegerArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !IntegerArray commentStamp: '<historical>' prior: 0! IntegerArrays store 32bit signed Integer values. Negative values are stored as 2's complement.! !IntegerArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:40'! at: index | word | <primitive: 165> word _ self basicAt: index. word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations" ^word >= 16r80000000 "Negative?!!" ifTrue:["word - 16r100000000" (word bitInvert32 + 1) negated] ifFalse:[word]! ! !IntegerArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:40'! at: index put: anInteger | word | <primitive: 166> anInteger < 0 ifTrue:["word _ 16r100000000 + anInteger" word _ (anInteger + 1) negated bitInvert32] ifFalse:[word _ anInteger]. self basicAt: index put: word. ^anInteger! ! !IntegerArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 23:34'! atAllPut: anInteger | word | anInteger < 0 ifTrue:["word _ 16r100000000 + anInteger" word _ (anInteger + 1) negated bitInvert32] ifFalse:[word _ anInteger]. self primFill: word.! ! !IntegerArray methodsFor: 'accessing' stamp: 'ar 11/2/1998 12:19'! defaultElement "Return the default element of the receiver" ^0! ! !IntegerArray methodsFor: 'converting' stamp: 'ar 10/10/1998 16:18'! asIntegerArray ^self! ! !IntegerArray methodsFor: 'private' stamp: 'ar 3/3/2001 23:34'! primFill: aPositiveInteger "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." <primitive: 145> self errorImproperStore.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! IntegerArray class instanceVariableNames: ''! !IntegerArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:17'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asIntPtrFrom: anInteger on: aStream! ! !IntegerArray class methodsFor: 'plugin generation' stamp: 'acg 9/25/1999 15:00'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asIntPtrFrom: anInteger andThen: (cg ccgValBlock: 'isWords')! ! !IntegerArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:18'! ccgDeclareCForVar: aSymbolOrString ^'int *', aSymbolOrString! ! SequenceableCollection subclass: #Interval instanceVariableNames: 'start stop step' classVariableNames: '' poolDictionaries: '' category: 'Collections-Sequenceable'! !Interval commentStamp: '<historical>' prior: 0! I represent a finite arithmetic progression.! !Interval methodsFor: 'accessing'! at: anInteger "Answer the anInteger'th element." (anInteger >= 1 and: [anInteger <= self size]) ifTrue: [^start + (step * (anInteger - 1))] ifFalse: [self errorSubscriptBounds: anInteger]! ! !Interval methodsFor: 'accessing'! at: anInteger put: anObject "Storing into an Interval is not allowed." self error: 'you can not store into an interval'! ! !Interval methodsFor: 'accessing' stamp: 'stp 8/19/2000 23:52'! extent "Answer the max - min of the receiver interval." "(10 to: 50) extent" ^stop - start! ! !Interval methodsFor: 'accessing'! first "Refer to the comment in SequenceableCollection|first." ^start! ! !Interval methodsFor: 'accessing' stamp: 'rpj 11/30/1999 11:04'! includes: aNumber "Determine if aNumber is an element of this interval." ^ (self rangeIncludes: aNumber) and: [ self valuesInclude: aNumber ]! ! !Interval methodsFor: 'accessing'! increment "Answer the receiver's interval increment." ^step! ! !Interval methodsFor: 'accessing'! last "Refer to the comment in SequenceableCollection|last." ^stop - (stop - start \\ step)! ! !Interval methodsFor: 'accessing' stamp: 'di 12/6/1999 11:00'! rangeIncludes: aNumber "Return true if the number lies in the interval between start and stop." step >= 0 ifTrue: [^ aNumber between: start and: stop] ifFalse: [^ aNumber between: stop and: start] ! ! !Interval methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:38'! size "Answer how many elements the receiver contains." step < 0 ifTrue: [start < stop ifTrue: [^ 0] ifFalse: [^ stop - start // step + 1]] ifFalse: [stop < start ifTrue: [^ 0] ifFalse: [^ stop - start // step + 1]]! ! !Interval methodsFor: 'comparing' stamp: 'rhi 8/14/2003 10:08'! = anObject ^ self == anObject ifTrue: [true] ifFalse: [anObject isInterval ifTrue: [start = anObject first and: [step = anObject increment and: [self last = anObject last]]] ifFalse: [super = anObject]]! ! !Interval methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^(((start hash bitShift: 2) bitOr: stop hash) bitShift: 1) bitOr: self size! ! !Interval methodsFor: 'comparing'! hashMappedBy: map "My hash is independent of my oop." ^self hash! ! !Interval methodsFor: 'adding'! add: newObject "Adding to an Interval is not allowed." self shouldNotImplement! ! !Interval methodsFor: 'removing'! remove: newObject "Removing from an Interval is not allowed." self error: 'elements cannot be removed from an Interval'! ! !Interval methodsFor: 'copying'! copy "Return a copy of me. Override the superclass because my species is Array and copy, as inherited from SequenceableCollection, uses copyFrom:to:, which creates a new object of my species." ^self shallowCopy! ! !Interval methodsFor: 'copying' stamp: 'sma 3/3/2000 13:18'! shallowCopy "Without this method, #copy would return an array instead of a new interval. The whole problem is burried in the class hierarchy and every fix will worsen the problem, so once the whole issue is resolved one should come back to this method fix it." ^ self class from: start to: stop by: step! ! !Interval methodsFor: 'enumerating'! collect: aBlock | nextValue result | result _ self species new: self size. nextValue _ start. 1 to: result size do: [:i | result at: i put: (aBlock value: nextValue). nextValue _ nextValue + step]. ^ result! ! !Interval methodsFor: 'enumerating'! do: aBlock | aValue | aValue _ start. step < 0 ifTrue: [[stop <= aValue] whileTrue: [aBlock value: aValue. aValue _ aValue + step]] ifFalse: [[stop >= aValue] whileTrue: [aBlock value: aValue. aValue _ aValue + step]]! ! !Interval methodsFor: 'enumerating' stamp: 'dtl 5/31/2003 16:45'! permutationsDo: aBlock "Repeatly value aBlock with a single copy of the receiver. Reorder the copy so that aBlock is presented all (self size factorial) possible permutations." "(1 to: 4) permutationsDo: [:each | Transcript cr; show: each printString]" self asArray permutationsDo: aBlock ! ! !Interval methodsFor: 'enumerating'! reverseDo: aBlock "Evaluate aBlock for each element of my interval, in reverse order." | aValue | aValue _ stop. step < 0 ifTrue: [[start >= aValue] whileTrue: [aBlock value: aValue. aValue _ aValue - step]] ifFalse: [[start <= aValue] whileTrue: [aBlock value: aValue. aValue _ aValue - step]]! ! !Interval methodsFor: 'printing' stamp: 'sma 6/1/2000 09:50'! printOn: aStream aStream nextPut: $(; print: start; nextPutAll: ' to: '; print: stop. step ~= 1 ifTrue: [aStream nextPutAll: ' by: '; print: step]. aStream nextPut: $)! ! !Interval methodsFor: 'printing'! storeOn: aStream "This is possible because we know numbers store and print the same." self printOn: aStream! ! !Interval methodsFor: 'private'! setFrom: startInteger to: stopInteger by: stepInteger start _ startInteger. stop _ stopInteger. step _ stepInteger! ! !Interval methodsFor: 'private'! species ^Array! ! !Interval methodsFor: 'private' stamp: 'di 4/24/2000 13:56'! valuesInclude: aNumber "Private - answer whether or not aNumber is one of the enumerated values in this interval." | val | val _ (aNumber - self first) asFloat / self increment. ^ val fractionPart abs < (step * 1.0e-10)! ! !Interval methodsFor: 'testing' stamp: 'rhi 8/12/2003 09:52'! isInterval ^ true! ! !Interval methodsFor: 'arithmetic' stamp: 'ajh 3/13/2003 15:45'! + number ^ start + number to: stop + number by: step! ! !Interval methodsFor: 'arithmetic' stamp: 'ajh 3/13/2003 15:46'! - number ^ start - number to: stop - number by: step! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Interval class instanceVariableNames: ''! !Interval class methodsFor: 'instance creation'! from: startInteger to: stopInteger "Answer an instance of me, starting at startNumber, ending at stopNumber, and with an interval increment of 1." ^self new setFrom: startInteger to: stopInteger by: 1! ! !Interval class methodsFor: 'instance creation'! from: startInteger to: stopInteger by: stepInteger "Answer an instance of me, starting at startNumber, ending at stopNumber, and with an interval increment of stepNumber." ^self new setFrom: startInteger to: stopInteger by: stepInteger! ! !Interval class methodsFor: 'instance creation'! new "Primitive. Create and answer with a new instance of the receiver (a class) with no indexable fields. Fail if the class is indexable. Override SequenceableCollection new. Essential. See Object documentation whatIsAPrimitive." <primitive: 70> self isVariable ifTrue: [ ^ self new: 0 ]. "space must be low" Smalltalk signalLowSpace. ^ self new "retry if user proceeds" ! ! !Interval class methodsFor: 'instance creation' stamp: 'md 1/14/2004 11:42'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." | newInterval n | (n := aCollection size) <= 1 ifTrue: [ n = 0 ifTrue: [^self from: 1 to: 0]. ^self from: aCollection first to: aCollection last]. newInterval := self from: aCollection first to: aCollection last by: (aCollection last - aCollection first) // (n - 1). aCollection ~= newInterval ifTrue: [self error: 'The argument is not an arithmetic progression']. ^newInterval " Interval newFrom: {1. 2. 3} {33. 5. -23} as: Interval {33. 5. -22} as: Interval (an error) (-4 to: -12 by: -1) as: Interval "! ! Error subclass: #InvalidDirectoryError instanceVariableNames: 'pathName' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !InvalidDirectoryError methodsFor: 'accessing' stamp: 'ar 5/30/2001 20:44'! pathName ^pathName! ! !InvalidDirectoryError methodsFor: 'accessing' stamp: 'ar 5/30/2001 20:45'! pathName: badPathName pathName _ badPathName! ! !InvalidDirectoryError methodsFor: 'exceptionDescription' stamp: 'ar 5/30/2001 20:49'! defaultAction "Return an empty list as the default action of signaling the occurance of an invalid directory." ^#()! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! InvalidDirectoryError class instanceVariableNames: ''! !InvalidDirectoryError class methodsFor: 'exceptionInstantiator' stamp: 'ar 5/30/2001 20:49'! pathName: badPathName ^self new pathName: badPathName! ! LargePositiveInteger variableByteSubclass: #LargeNegativeInteger instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !LargeNegativeInteger commentStamp: '<historical>' prior: 0! Just like LargePositiveInteger, but represents a negative number.! !LargeNegativeInteger methodsFor: 'arithmetic'! abs ^ self negated! ! !LargeNegativeInteger methodsFor: 'arithmetic'! negated ^ self copyto: (LargePositiveInteger new: self digitLength)! ! !LargeNegativeInteger methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:10'! highBit "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. Raise an error if the receiver is negative, since negative integers are defined to have an infinite number of leading 1's in 2's-complement arithmetic. Use >>highBitOfMagnitude if you want to get the highest bit of the magnitude." ^ self shouldNotImplement! ! !LargeNegativeInteger methodsFor: 'converting' stamp: 'ar 5/17/2000 16:10'! normalize "Check for leading zeroes and return shortened copy if so" | sLen val len oldLen minVal | <primitive: 'primNormalizeNegative' module:'LargeIntegers'> "First establish len = significant length" len _ oldLen _ self digitLength. [len = 0 ifTrue: [^0]. (self digitAt: len) = 0] whileTrue: [len _ len - 1]. "Now check if in SmallInteger range" sLen _ 4 "SmallInteger minVal digitLength". len <= sLen ifTrue: [minVal _ SmallInteger minVal. (len < sLen or: [(self digitAt: sLen) < minVal lastDigit]) ifTrue: ["If high digit less, then can be small" val _ 0. len to: 1 by: -1 do: [:i | val _ (val *256) - (self digitAt: i)]. ^ val]. 1 to: sLen do: "If all digits same, then = minVal" [:i | (self digitAt: i) = (minVal digitAt: i) ifFalse: ["Not so; return self shortened" len < oldLen ifTrue: [^ self growto: len] ifFalse: [^ self]]]. ^ minVal]. "Return self, or a shortened copy" len < oldLen ifTrue: [^ self growto: len] ifFalse: [^ self]! ! !LargeNegativeInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:18'! negative "Answer whether the receiver is mathematically negative." ^ true! ! !LargeNegativeInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:00'! positive "Answer whether the receiver is positive or equal to 0. (ST-80 protocol). See also strictlyPositive" ^ false! ! !LargeNegativeInteger methodsFor: 'testing' stamp: 'jm 3/27/98 06:19'! sign "Optimization. Answer -1 since receiver is less than 0." ^ -1 ! ! !LargeNegativeInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:03'! strictlyPositive "Answer whether the receiver is mathematically positive." ^ false! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! LargeNegativeInteger class instanceVariableNames: ''! !LargeNegativeInteger class methodsFor: 'as yet unclassified' stamp: 'sw 5/8/2000 12:05'! initializedInstance ^ -9876543210987654321 copy! ! Integer variableByteSubclass: #LargePositiveInteger instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !LargePositiveInteger commentStamp: '<historical>' prior: 0! I represent positive integers of more than 30 bits (ie, >= 1073741824). These values are beyond the range of SmallInteger, and are encoded here as an array of 8-bit digits. Care must be taken, when new values are computed, that any result that COULD BE a SmallInteger IS a SmallInteger (see normalize). Note that the bit manipulation primitives, bitAnd:, bitShift:, etc., = and ~= run without failure (and therefore fast) if the value fits in 32 bits. This is a great help to the simulator.! !LargePositiveInteger methodsFor: 'arithmetic'! * anInteger "Primitive. Multiply the receiver by the argument and answer with an Integer result. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive. " <primitive: 29> ^super * anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! + anInteger "Primitive. Add the receiver to the argument and answer with an Integer result. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 21> ^super + anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! - anInteger "Primitive. Subtract the argument from the receiver and answer with an Integer result. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 22> ^super - anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! / anInteger "Primitive. Divide the receiver by the argument and answer with the result if the division is exact. Fail if the result is not a whole integer. Fail if the argument is 0. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive. " <primitive: 30> ^super / anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! // anInteger "Primitive. Divide the receiver by the argument and return the result. Round the result down towards negative infinity to make it a whole integer. Fail if the argument is 0. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive. " <primitive: 32> ^super // anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! \\ anInteger "Primitive. Take the receiver modulo the argument. The result is the remainder rounded towards negative infinity, of the receiver divided by the argument. Fail if the argument is 0. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 31> ^super \\ anInteger! ! !LargePositiveInteger methodsFor: 'arithmetic'! abs! ! !LargePositiveInteger methodsFor: 'arithmetic'! negated ^ (self copyto: (LargeNegativeInteger new: self digitLength)) normalize "Need to normalize to catch SmallInteger minVal"! ! !LargePositiveInteger methodsFor: 'arithmetic'! quo: anInteger "Primitive. Divide the receiver by the argument and return the result. Round the result down towards zero to make it a whole integer. Fail if the argument is 0. Fail if either the argument or the result is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 33> ^super quo: anInteger! ! !LargePositiveInteger methodsFor: 'bit manipulation'! bitAnd: anInteger "Primitive. Answer an Integer whose bits are the logical AND of the receiver's bits and those of the argument. Fail if the receiver or argument is greater than 32 bits. See Object documentation whatIsAPrimitive." <primitive: 14> ^ super bitAnd: anInteger! ! !LargePositiveInteger methodsFor: 'bit manipulation'! bitOr: anInteger "Primitive. Answer an Integer whose bits are the logical OR of the receiver's bits and those of the argument. Fail if the receiver or argument is greater than 32 bits. See Object documentation whatIsAPrimitive." <primitive: 15> ^ super bitOr: anInteger! ! !LargePositiveInteger methodsFor: 'bit manipulation'! bitShift: anInteger "Primitive. Answer an Integer whose value (in twos-complement representation) is the receiver's value (in twos-complement representation) shifted left by the number of bits indicated by the argument. Negative arguments shift right. Zeros are shifted in from the right in left shifts. The sign bit is extended in right shifts. Fail if the receiver or result is greater than 32 bits. See Object documentation whatIsAPrimitive." <primitive: 17> ^super bitShift: anInteger! ! !LargePositiveInteger methodsFor: 'bit manipulation'! bitXor: anInteger "Primitive. Answer an Integer whose bits are the logical XOR of the receiver's bits and those of the argument. Fail if the receiver or argument is greater than 32 bits. See Object documentation whatIsAPrimitive." <primitive: 16> ^ super bitXor: anInteger! ! !LargePositiveInteger methodsFor: 'bit manipulation' stamp: 'SqR 9/18/2000 15:17'! hashMultiply "Truncate to 28 bits and try again" ^(self bitAnd: 16rFFFFFFF) hashMultiply! ! !LargePositiveInteger methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:11'! highBit "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. Raise an error if the receiver is negative, since negative integers are defined to have an infinite number of leading 1's in 2's-complement arithmetic. Use >>highBitOfMagnitude if you want to get the highest bit of the magnitude." ^ self highBitOfMagnitude! ! !LargePositiveInteger methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:15'! highBitOfMagnitude "Answer the index of the high order bit of the magnitude of the receiver, or zero if the receiver is zero. This method is used for LargeNegativeIntegers as well, since Squeak's LargeIntegers are sign/magnitude." | realLength lastDigit | realLength _ self digitLength. [(lastDigit _ self digitAt: realLength) = 0] whileTrue: [(realLength _ realLength - 1) = 0 ifTrue: [^ 0]]. ^ lastDigit highBitOfPositiveReceiver + (8 * (realLength - 1))! ! !LargePositiveInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:18'! negative "Answer whether the receiver is mathematically negative." ^ false! ! !LargePositiveInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:00'! positive "Answer whether the receiver is positive or equal to 0. (ST-80 protocol). See also strictlyPositive" ^ true! ! !LargePositiveInteger methodsFor: 'testing' stamp: 'jm 3/27/98 06:19'! sign "Optimization. Answer 1 since receiver is greater than 0." ^ 1 ! ! !LargePositiveInteger methodsFor: 'testing' stamp: 'di 4/23/1998 11:02'! strictlyPositive "Answer whether the receiver is mathematically positive." ^ true! ! !LargePositiveInteger methodsFor: 'comparing'! < anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is less than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 23> ^super < anInteger! ! !LargePositiveInteger methodsFor: 'comparing'! <= anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is less than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 25> ^super <= anInteger! ! !LargePositiveInteger methodsFor: 'comparing'! = anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is equal to the argument. Otherwise answer false. Fail if the receiver or argument is negative or greater than 32 bits. Optional. See Object documentation whatIsAPrimitive." <primitive: 7> ^ super = anInteger! ! !LargePositiveInteger methodsFor: 'comparing'! > anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 24> ^super > anInteger! ! !LargePositiveInteger methodsFor: 'comparing'! >= anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger or a LargePositiveInteger less than 2-to-the-30th (1073741824). Optional. See Object documentation whatIsAPrimitive." <primitive: 26> ^super >= anInteger! ! !LargePositiveInteger methodsFor: 'comparing' stamp: 'SqR 8/13/2002 10:52'! hash ^ByteArray hashBytes: self startingWith: self species hash! ! !LargePositiveInteger methodsFor: 'comparing'! ~= anInteger "Primitive. Compare the receiver with the argument and answer true if the receiver is equal to the argument. Otherwise answer false. Fail if the receiver or argument is negative or greater than 32 bits. Optional. See Object documentation whatIsAPrimitive." <primitive: 8> ^ super ~= anInteger! ! !LargePositiveInteger methodsFor: 'converting' stamp: 'ar 5/17/2000 16:09'! normalize "Check for leading zeroes and return shortened copy if so" | sLen val len oldLen | <primitive: 'primNormalizePositive' module:'LargeIntegers'> "First establish len = significant length" len _ oldLen _ self digitLength. [len = 0 ifTrue: [^0]. (self digitAt: len) = 0] whileTrue: [len _ len - 1]. "Now check if in SmallInteger range" sLen _ SmallInteger maxVal digitLength. (len <= sLen and: [(self digitAt: sLen) <= (SmallInteger maxVal digitAt: sLen)]) ifTrue: ["If so, return its SmallInt value" val _ 0. len to: 1 by: -1 do: [:i | val _ (val *256) + (self digitAt: i)]. ^ val]. "Return self, or a shortened copy" len < oldLen ifTrue: [^ self growto: len] ifFalse: [^ self]! ! !LargePositiveInteger methodsFor: 'system primitives' stamp: 'tk 3/24/1999 20:28'! digitAt: index "Primitive. Answer the value of an indexable field in the receiver. LargePositiveInteger uses bytes of base two number, and each is a 'digit' base 256. Fail if the argument (the index) is not an Integer or is out of bounds. Essential. See Object documentation whatIsAPrimitive." <primitive: 60> self digitLength < index ifTrue: [^0] ifFalse: [^super at: index]! ! !LargePositiveInteger methodsFor: 'system primitives'! digitAt: index put: value "Primitive. Store the second argument (value) in the indexable field of the receiver indicated by index. Fail if the value is negative or is larger than 255. Fail if the index is not an Integer or is out of bounds. Answer the value that was stored. Essential. See Object documentation whatIsAPrimitive." <primitive: 61> ^super at: index put: value! ! !LargePositiveInteger methodsFor: 'system primitives'! digitLength "Primitive. Answer the number of indexable fields in the receiver. This value is the same as the largest legal subscript. Essential. See Object documentation whatIsAPrimitive." <primitive: 62> self primitiveFailed! ! !LargePositiveInteger methodsFor: 'system primitives'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> ^ super replaceFrom: start to: stop with: replacement startingAt: repStart! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! LargePositiveInteger class instanceVariableNames: ''! !LargePositiveInteger class methodsFor: 'testing' stamp: 'sw 5/8/2000 12:05'! initializedInstance ^ 12345678901234567 copy! ! ParseNode subclass: #LeafNode instanceVariableNames: 'key code' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !LeafNode commentStamp: '<historical>' prior: 0! I represent a leaf node of the compiler parse tree. I am abstract. Types (defined in class ParseNode): 1 LdInstType (which uses class VariableNode) 2 LdTempType (which uses class VariableNode) 3 LdLitType (which uses class LiteralNode) 4 LdLitIndType (which uses class VariableNode) 5 SendType (which uses class SelectorNode). Note that Squeak departs slightly from the Blue Book bytecode spec. In order to allow access to more than 63 literals and instance variables, bytecode 132 has been redefined as DoubleExtendedDoAnything: byte2 byte3 Operation (hi 3 bits) (lo 5 bits) 0 nargs lit index Send Literal Message 0-255 1 nargs lit index Super-Send Lit Msg 0-255 2 ignored rcvr index Push Receiver Variable 0-255 3 ignored lit index Push Literal Constant 0-255 4 ignored lit index Push Literal Variable 0-255 5 ignored rcvr index Store Receiver Variable 0-255 6 ignored rcvr index Store-pop Receiver Variable 0-255 7 ignored lit index Store Literal Variable 0-255 This has allowed bytecode 134 also to be redefined as a second extended send that can access literals up to 64 for nargs up to 3 without needing three bytes. It is just like 131, except that the extension byte is aallllll instead of aaalllll, where aaa are bits of argument count, and lll are bits of literal index.! !LeafNode methodsFor: 'initialize-release'! key: object code: byte key _ object. code _ byte! ! !LeafNode methodsFor: 'initialize-release'! key: object index: i type: type self key: object code: (self code: i type: type)! ! !LeafNode methodsFor: 'initialize-release'! name: ignored key: object code: byte key _ object. code _ byte! ! !LeafNode methodsFor: 'initialize-release'! name: literal key: object index: i type: type self key: object index: i type: type! ! !LeafNode methodsFor: 'accessing'! key ^key! ! !LeafNode methodsFor: 'code generation'! code ^code! ! !LeafNode methodsFor: 'code generation'! emitForEffect: stack on: strm ^self! ! !LeafNode methodsFor: 'code generation'! emitLong: mode on: aStream "Emit extended variable access." | type index | code < 256 ifTrue: [code < 16 ifTrue: [type _ 0. index _ code] ifFalse: [code < 32 ifTrue: [type _ 1. index _ code - 16] ifFalse: [code < 96 ifTrue: [type _ code // 32 + 1. index _ code \\ 32] ifFalse: [self error: 'Sends should be handled in SelectorNode']]]] ifFalse: [index _ code \\ 256. type _ code // 256 - 1]. index <= 63 ifTrue: [aStream nextPut: mode. ^ aStream nextPut: type * 64 + index]. "Compile for Double-exetended Do-anything instruction..." mode = LoadLong ifTrue: [aStream nextPut: DblExtDoAll. aStream nextPut: (#(64 0 96 128) at: type+1). "Cant be temp (type=1)" ^ aStream nextPut: index]. mode = Store ifTrue: [aStream nextPut: DblExtDoAll. aStream nextPut: (#(160 0 0 224) at: type+1). "Cant be temp or const (type=1 or 2)" ^ aStream nextPut: index]. mode = StorePop ifTrue: [aStream nextPut: DblExtDoAll. aStream nextPut: (#(192 0 0 0) at: type+1). "Can only be inst" ^ aStream nextPut: index]. ! ! !LeafNode methodsFor: 'code generation'! reserve: encoder "If this is a yet unused literal of type -code, reserve it." code < 0 ifTrue: [code _ self code: (encoder litIndex: key) type: 0 - code]! ! !LeafNode methodsFor: 'code generation'! sizeForEffect: encoder ^0! ! !LeafNode methodsFor: 'code generation'! sizeForValue: encoder self reserve: encoder. code < 256 ifTrue: [^ 1]. (code \\ 256) <= 63 ifTrue: [^ 2]. ^ 3! ! !LeafNode methodsFor: 'private'! code: index type: type index isNil ifTrue: [^type negated]. (CodeLimits at: type) > index ifTrue: [^(CodeBases at: type) + index]. ^type * 256 + index! ! !LeafNode methodsFor: 'copying' stamp: 'tk 10/20/2000 11:45'! veryDeepFixupWith: deepCopier "If fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!!!" super veryDeepFixupWith: deepCopier. key _ deepCopier references at: key ifAbsent: [key]. ! ! !LeafNode methodsFor: 'copying' stamp: 'tk 10/20/2000 11:41'! veryDeepInner: deepCopier "Copy all of my instance variables. Some need to be not copied at all, but shared. Warning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment." super veryDeepInner: deepCopier. "key _ key. Weakly copied" code _ code veryDeepCopyWith: deepCopier. ! ! WriteStream subclass: #LimitedWriteStream instanceVariableNames: 'limit limitBlock' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !LimitedWriteStream commentStamp: '<historical>' prior: 0! A LimitedWriteStream is a specialized WriteStream that has a maximum size of the collection it streams over. When this limit is reached a special limitBlock is executed. This can for example be used to "bail out" of lengthy streaming operations before they have finished. For a simple example take a look at the universal Object printString. The message SequenceableCollection class streamContents:limitedTo: creates a LimitedWriteStream. In this case it prevents very large (or possibly recursive) object structures to "overdo" their textual representation. ! ]style[(323 18 15 54 151)f1,f1LObject printString;,f1,f1LSequenceableCollection class streamContents:limitedTo:;,f1! !LimitedWriteStream methodsFor: 'as yet unclassified' stamp: 'BG 3/13/2004 13:18'! nextPutAll: aCollection | newEnd | collection class == aCollection class ifFalse: [^ super nextPutAll: aCollection ]. newEnd _ position + aCollection size. newEnd > limit ifTrue: [ super nextPutAll: (aCollection copyFrom: 1 to: (limit - position max: 0)). ^ limitBlock value. ]. newEnd > writeLimit ifTrue: [ self growTo: newEnd + 10 ]. collection replaceFrom: position+1 to: newEnd with: aCollection startingAt: 1. position _ newEnd.! ! !LimitedWriteStream methodsFor: 'as yet unclassified' stamp: 'di 10/28/2001 12:49'! pastEndPut: anObject collection size >= limit ifTrue: [limitBlock value]. "Exceptional return" ^ super pastEndPut: anObject! ! !LimitedWriteStream methodsFor: 'as yet unclassified' stamp: 'di 6/20/97 09:07'! setLimit: sizeLimit limitBlock: aBlock "Limit the numer of elements this stream will write..." limit _ sizeLimit. "Execute this (typically ^ contents) when that limit is exceded" limitBlock _ aBlock! ! !LimitedWriteStream methodsFor: 'accessing' stamp: 'BG 3/13/2004 16:03'! nextPut: anObject "Ensure that the limit is not exceeded" position >= limit ifTrue: [limitBlock value] ifFalse: [super nextPut: anObject]. ! ! Object subclass: #LimitingLineStreamWrapper instanceVariableNames: 'stream line limitingBlock position' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Collections-Streams'! !LimitingLineStreamWrapper commentStamp: '<historical>' prior: 0! I'm a wrapper for a stream optimized for line-by-line access using #nextLine. My instances can be nested. I read one line ahead. Reading terminates when the stream ends, or if the limitingBlock evaluated with the line answers true. To skip the delimiting line for further reading use #skipThisLine. Character-based reading (#next) is permitted, too. Send #updatePosition when switching from line-based reading. See examples at the class side. --bf 2/19/1999 12:52! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 14:25'! delimiter: aString "Set limitBlock to check for a delimiting string. Be unlimiting if nil" self limitingBlock: (aString caseOf: { [nil] -> [[:aLine | false]]. [''] -> [[:aLine | aLine size = 0]] } otherwise: [[:aLine | aLine beginsWith: aString]]) ! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 19:16'! limitingBlock: aBlock "The limitingBlock is evaluated with a line to check if this line terminates the stream" limitingBlock _ aBlock fixTemps. self updatePosition! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 2/19/1999 11:45'! linesUpToEnd | elements ln | elements _ OrderedCollection new. [(ln _ self nextLine) isNil] whileFalse: [ elements add: ln]. ^elements! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 14:37'! next "Provide character-based access" position isNil ifTrue: [^nil]. position < line size ifTrue: [^line at: (position _ position + 1)]. line _ stream nextLine. self updatePosition. ^ Character cr! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 14:09'! nextLine | thisLine | self atEnd ifTrue: [^nil]. thisLine _ line. line _ stream nextLine. ^thisLine ! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 16:53'! skipThisLine line _ stream nextLine. self updatePosition. ! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 2/19/1999 11:47'! upToEnd | ln | ^String streamContents: [:strm | [(ln _ self nextLine) isNil] whileFalse: [ strm nextPutAll: ln; cr]]! ! !LimitingLineStreamWrapper methodsFor: 'accessing' stamp: 'bf 11/24/1998 14:37'! updatePosition "Call this before doing character-based access" position _ self atEnd ifFalse: [0]! ! !LimitingLineStreamWrapper methodsFor: 'testing' stamp: 'bf 11/13/1998 16:55'! atEnd ^line isNil or: [limitingBlock value: line]! ! !LimitingLineStreamWrapper methodsFor: 'stream protocol' stamp: 'bf 11/13/1998 17:00'! close ^stream close! ! !LimitingLineStreamWrapper methodsFor: 'printing' stamp: 'bf 11/24/1998 13:39'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' on '. stream printOn: aStream! ! !LimitingLineStreamWrapper methodsFor: 'private' stamp: 'bf 11/24/1998 14:30'! setStream: aStream delimiter: aString stream _ aStream. line _ stream nextLine. self delimiter: aString. "sets position" ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! LimitingLineStreamWrapper class instanceVariableNames: ''! !LimitingLineStreamWrapper class methodsFor: 'instance creation' stamp: 'bf 11/24/1998 14:31'! on: aStream delimiter: aString ^self new setStream: aStream delimiter: aString ! ! !LimitingLineStreamWrapper class methodsFor: 'examples' stamp: 'bf 2/19/1999 11:48'! example1 "LimitingLineStreamWrapper example1" "Separate chunks of text delimited by a special string" | inStream msgStream messages | inStream _ self exampleStream. msgStream _ LimitingLineStreamWrapper on: inStream delimiter: 'From '. messages _ OrderedCollection new. [inStream atEnd] whileFalse: [ msgStream skipThisLine. messages add: msgStream upToEnd]. ^messages ! ! !LimitingLineStreamWrapper class methodsFor: 'examples' stamp: 'bf 2/19/1999 12:46'! example2 "LimitingLineStreamWrapper example2" "Demo nesting wrappers - get header lines from some messages" | inStream msgStream headers headerStream | inStream _ self exampleStream. msgStream _ LimitingLineStreamWrapper on: inStream delimiter: 'From '. headers _ OrderedCollection new. [inStream atEnd] whileFalse: [ msgStream skipThisLine. "Skip From" headerStream _ LimitingLineStreamWrapper on: msgStream delimiter: ''. headers add: headerStream linesUpToEnd. [msgStream nextLine isNil] whileFalse. "Skip Body" ]. ^headers ! ! !LimitingLineStreamWrapper class methodsFor: 'examples' stamp: 'bf 2/19/1999 12:44'! exampleStream ^ReadStream on: 'From me@somewhere From: me To: you Subject: Test Test From you@elsewhere From: you To: me Subject: Re: test okay '! ! Path subclass: #Line instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Line commentStamp: '<historical>' prior: 0! I represent the line segment specified by two points.! !Line methodsFor: 'accessing'! beginPoint "Answer the first end point of the receiver." ^self first! ! !Line methodsFor: 'accessing'! beginPoint: aPoint "Set the first end point of the receiver to be the argument, aPoint. Answer aPoint." self at: 1 put: aPoint. ^aPoint! ! !Line methodsFor: 'accessing'! endPoint "Answer the last end point of the receiver." ^self last! ! !Line methodsFor: 'accessing'! endPoint: aPoint "Set the first end point of the receiver to be the argument, aPoint. Answer aPoint." self at: 2 put: aPoint. ^aPoint! ! !Line methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm "The form associated with this Path will be displayed, according to one of the sixteen functions of two logical variables (rule), at each point on the Line. Also the source form will be first anded with aForm as a mask. Does not effect the state of the Path." collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points']. aDisplayMedium drawLine: self form from: self beginPoint + aPoint to: self endPoint + aPoint clippingBox: clipRect rule: anInteger fillColor: aForm! ! !Line methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm | newPath newLine | newPath _ aTransformation applyTo: self. newLine _ Line new. newLine beginPoint: newPath firstPoint. newLine endPoint: newPath secondPoint. newLine form: self form. newLine displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRect rule: anInteger fillColor: aForm! ! !Line methodsFor: 'displaying'! displayOnPort: aPort at: aPoint aPort sourceForm: self form; combinationRule: Form under; fillColor: nil. aPort drawFrom: collectionOfPoints first + aPoint to: collectionOfPoints last + aPoint! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Line class instanceVariableNames: ''! !Line class methodsFor: 'instance creation'! new | newSelf | newSelf _ super new: 2. newSelf add: 0@0. newSelf add: 0@0. ^newSelf! ! !Line class methodsFor: 'examples'! example "Designate two places on the screen by clicking any mouse button. A straight path with a square black form will be displayed connecting the two selected points." | aLine aForm | aForm _ Form extent: 20@20. "make a form one quarter of inch square" aForm fillBlack. "turn it black" aLine _ Line new. aLine form: aForm. "use the black form for display" aLine beginPoint: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aLine beginPoint. aLine endPoint: Sensor waitButton. aLine displayOn: Display. "display the line" "Line example"! ! Path subclass: #LinearFit instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !LinearFit commentStamp: '<historical>' prior: 0! I represent a piece-wise linear approximation to a set of points in the plane.! !LinearFit methodsFor: 'displaying' stamp: 'jrm 9/7/1999 22:16'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm | line | line _ Line new. line form: self form. 1 to: self size - 1 do: [:i | line beginPoint: (self at: i). line endPoint: (self at: i + 1). line displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm]! ! !LinearFit methodsFor: 'displaying' stamp: 'jrm 9/7/1999 23:00'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm | transformedPath | "get the scaled and translated Path." transformedPath _ aTransformation applyTo: self. transformedPath displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRect rule: anInteger fillColor: aForm! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! LinearFit class instanceVariableNames: ''! !LinearFit class methodsFor: 'examples'! example "Select points on a Path using the red button. Terminate by selecting any other button. Creates a Path from the points and displays it as a piece-wise linear approximation." | aLinearFit aForm flag | aLinearFit _ LinearFit new. aForm _ Form extent: 1 @ 40. aForm fillBlack. aLinearFit form: aForm. flag _ true. [flag] whileTrue: [Sensor waitButton. Sensor redButtonPressed ifTrue: [aLinearFit add: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aLinearFit last] ifFalse: [flag_false]]. aLinearFit displayOn: Display "LinearFit example"! ! Object subclass: #Link instanceVariableNames: 'nextLink' classVariableNames: '' poolDictionaries: '' category: 'Collections-Support'! !Link commentStamp: '<historical>' prior: 0! 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.! !Link methodsFor: 'accessing'! nextLink "Answer the link to which the receiver points." ^nextLink! ! !Link methodsFor: 'accessing'! nextLink: aLink "Store the argument, aLink, as the link to which the receiver refers. Answer aLink." ^nextLink _ aLink! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Link class instanceVariableNames: ''! !Link class methodsFor: 'instance creation' stamp: 'apb 10/3/2000 15:55'! nextLink: aLink "Answer an instance of me referring to the argument, aLink." ^self new nextLink: aLink; yourself! ! SequenceableCollection subclass: #LinkedList instanceVariableNames: 'firstLink lastLink' classVariableNames: '' poolDictionaries: '' category: 'Collections-Sequenceable'! !LinkedList commentStamp: '<historical>' prior: 0! 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.! !LinkedList methodsFor: 'accessing' stamp: 'ajh 8/6/2002 15:46'! at: index | i | i _ 0. self do: [:link | (i _ i + 1) = index ifTrue: [^ link]]. ^ self errorSubscriptBounds: index! ! !LinkedList methodsFor: 'accessing'! first "Answer the first link. Create an error notification if the receiver is empty." self emptyCheck. ^firstLink! ! !LinkedList methodsFor: 'accessing'! last "Answer the last link. Create an error notification if the receiver is empty." self emptyCheck. ^lastLink! ! !LinkedList methodsFor: 'testing'! isEmpty ^firstLink == nil! ! !LinkedList methodsFor: 'adding'! add: aLink "Add aLink to the end of the receiver's list. Answer aLink." ^self addLast: aLink! ! !LinkedList methodsFor: 'adding' stamp: 'ajh 8/22/2002 14:17'! add: link before: otherLink | aLink | firstLink == otherLink ifTrue: [^ self addFirst: link]. aLink _ firstLink. [aLink == nil] whileFalse: [ aLink nextLink == otherLink ifTrue: [ link nextLink: aLink nextLink. aLink nextLink: link. ^ link ]. aLink _ aLink nextLink. ]. ^ self errorNotFound: otherLink! ! !LinkedList methodsFor: 'adding'! addFirst: aLink "Add aLink to the beginning of the receiver's list. Answer aLink." self isEmpty ifTrue: [lastLink _ aLink]. aLink nextLink: firstLink. firstLink _ aLink. ^aLink! ! !LinkedList methodsFor: 'adding'! addLast: aLink "Add aLink to the end of the receiver's list. Answer aLink." self isEmpty ifTrue: [firstLink _ aLink] ifFalse: [lastLink nextLink: aLink]. lastLink _ aLink. ^aLink! ! !LinkedList methodsFor: 'removing'! remove: aLink ifAbsent: aBlock "Remove aLink from the receiver. If it is not there, answer the result of evaluating aBlock." | tempLink | aLink == firstLink ifTrue: [firstLink _ aLink nextLink. aLink == lastLink ifTrue: [lastLink _ nil]] ifFalse: [tempLink _ firstLink. [tempLink == nil ifTrue: [^aBlock value]. tempLink nextLink == aLink] whileFalse: [tempLink _ tempLink nextLink]. tempLink nextLink: aLink nextLink. aLink == lastLink ifTrue: [lastLink _ tempLink]]. aLink nextLink: nil. ^aLink! ! !LinkedList methodsFor: 'removing'! removeFirst "Remove the first element and answer it. If the receiver is empty, create an error notification." | oldLink | self emptyCheck. oldLink _ firstLink. firstLink == lastLink ifTrue: [firstLink _ nil. lastLink _ nil] ifFalse: [firstLink _ oldLink nextLink]. oldLink nextLink: nil. ^oldLink! ! !LinkedList methodsFor: 'removing'! removeLast "Remove the receiver's last element and answer it. If the receiver is empty, create an error notification." | oldLink aLink | self emptyCheck. oldLink _ lastLink. firstLink == lastLink ifTrue: [firstLink _ nil. lastLink _ nil] ifFalse: [aLink _ firstLink. [aLink nextLink == oldLink] whileFalse: [aLink _ aLink nextLink]. aLink nextLink: nil. lastLink _ aLink]. oldLink nextLink: nil. ^oldLink! ! !LinkedList methodsFor: 'enumerating'! do: aBlock | aLink | aLink _ firstLink. [aLink == nil] whileFalse: [aBlock value: aLink. aLink _ aLink nextLink]! ! !LinkedList methodsFor: 'enumerating' stamp: 'ajh 8/6/2002 16:39'! species ^ Array! ! ScrollController subclass: #ListController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !ListController commentStamp: '<historical>' prior: 0! 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.! !ListController methodsFor: 'control defaults' stamp: 'bf 4/14/1999 12:41'! controlActivity self scrollByKeyboard ifTrue: [^self]. self processKeyboard. super controlActivity. ! ! !ListController methodsFor: 'marker adjustment'! computeMarkerRegion "Refer to the comment in ScrollController|computeMarkerRegion." | viewList | viewList _ view list. viewList compositionRectangle height = 0 ifTrue: [^ 0@0 extent: Preferences scrollBarWidth@scrollBar inside height]. ^ 0@0 extent: Preferences scrollBarWidth@ ((viewList clippingRectangle height asFloat / viewList compositionRectangle height * scrollBar inside height) rounded min: scrollBar inside height)! ! !ListController methodsFor: 'marker adjustment'! markerDelta | viewList | viewList _ view list. viewList compositionRectangle height == 0 ifTrue: [ ^ (marker top - scrollBar inside top) - scrollBar inside height ]. ^ (marker top - scrollBar inside top) - ((viewList clippingRectangle top - viewList compositionRectangle top) asFloat / viewList compositionRectangle height asFloat * scrollBar inside height asFloat) rounded ! ! !ListController methodsFor: 'scrolling'! scrollAmount "Refer to the comment in ScrollController|scrollAmount." ^sensor cursorPoint y - scrollBar inside top! ! !ListController methodsFor: 'scrolling'! scrollView: anInteger "Scroll the view and highlight the selection if it just came into view" | wasClipped | wasClipped _ view isSelectionBoxClipped. (view scrollBy: anInteger) ifTrue: [view isSelectionBoxClipped ifFalse: [wasClipped ifTrue: "Selection came into view" [view displaySelectionBox]]. ^ true] ifFalse: [^ false]! ! !ListController methodsFor: 'scrolling'! viewDelta "Refer to the comment in ScrollController|viewDelta." | viewList | viewList _ view list. ^(viewList clippingRectangle top - viewList compositionRectangle top - ((marker top - scrollBar inside top) asFloat / scrollBar inside height asFloat * viewList compositionRectangle height asFloat)) roundTo: viewList lineGrid! ! !ListController methodsFor: 'selecting' stamp: 'tk 4/1/98 10:33'! redButtonActivity | noSelectionMovement oldSelection selection nextSelection pt scrollFlag firstTime | noSelectionMovement _ true. scrollFlag _ false. oldSelection _ view selection. firstTime _ true. [sensor redButtonPressed | firstTime] whileTrue: [selection _ view findSelection: (pt _ sensor cursorPoint). firstTime _ false. selection == nil ifTrue: "Maybe out of box - check for auto-scroll" [pt y < view insetDisplayBox top ifTrue: [self scrollView: view list lineGrid. scrollFlag _ true. selection _ view firstShown]. pt y > view insetDisplayBox bottom ifTrue: [self scrollView: view list lineGrid negated. scrollFlag _ true. selection _ view lastShown]]. selection == nil ifFalse: [view moveSelectionBox: (nextSelection _ selection). nextSelection ~= oldSelection ifTrue: [noSelectionMovement _ false]]]. nextSelection ~~ nil & (nextSelection = oldSelection ifTrue: [noSelectionMovement] ifFalse: [true]) ifTrue: [self changeModelSelection: nextSelection]. scrollFlag ifTrue: [self moveMarker]! ! !ListController methodsFor: 'private'! changeModelSelection: anInteger model toggleListIndex: anInteger! ! !ListController methodsFor: 'menu messages' stamp: 'acg 9/18/1999 14:09'! processKeyboard "Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | sensor keyboardPressed ifFalse: [^ self]. keyEvent := sensor keyboard asciiValue. oldSelection := view selection. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view clippingBox height // view list lineGrid. keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [model okToChange ifTrue: [self changeModelSelection: nextSelection. self moveMarker]] ! ! Paragraph subclass: #ListParagraph instanceVariableNames: '' classVariableNames: 'ListStyle' poolDictionaries: '' category: 'ST80-Support'! !ListParagraph commentStamp: '<historical>' prior: 0! 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.! !ListParagraph methodsFor: 'composition'! composeAll "No composition is necessary once the ListParagraph is created." lastLine isNil ifTrue: [lastLine _ 0]. "Because composeAll is called once in the process of creating the ListParagraph." ^compositionRectangle width! ! !ListParagraph methodsFor: 'private'! trimLinesTo: lastLineInteger "Since ListParagraphs are not designed to be changed, we can cut back the lines field to lastLineInteger." lastLine _ lastLineInteger. lines _ lines copyFrom: 1 to: lastLine! ! !ListParagraph methodsFor: 'private' stamp: 'di 7/13/97 16:56'! withArray: anArray "Modifies self to contain the list of strings in anArray" | startOfLine endOfLine lineIndex aString | lines _ Array new: 20. lastLine _ 0. startOfLine _ 1. endOfLine _ 1. lineIndex _ 0. anArray do: [:item | endOfLine _ startOfLine + item size. "this computation allows for a cr after each line..." "...but later we will adjust for no cr after last line" lineIndex _ lineIndex + 1. self lineAt: lineIndex put: ((TextLineInterval start: startOfLine stop: endOfLine internalSpaces: 0 paddingWidth: 0) lineHeight: textStyle lineGrid baseline: textStyle baseline). startOfLine _ endOfLine + 1]. endOfLine _ endOfLine - 1. "endOfLine is now the total size of the text" self trimLinesTo: lineIndex. aString _ String new: endOfLine. anArray with: lines do: [:item :interval | aString replaceFrom: interval first to: interval last - 1 with: item asString startingAt: 1. interval last <= endOfLine ifTrue: [aString at: interval last put: Character cr]]. lineIndex > 0 ifTrue: [(lines at: lineIndex) stop: endOfLine]. "adjust for no cr after last line" self text: aString asText. anArray with: lines do: [:item :interval | item isText ifTrue: [text replaceFrom: interval first to: interval last - 1 with: item]]. self updateCompositionHeight! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ListParagraph class instanceVariableNames: ''! !ListParagraph class methodsFor: 'instance creation' stamp: 'jm 9/20/1998 17:10'! withArray: anArray style: aTextStyleOrNil "Convert an array of strings into a ListParagraph using the given TextStyle." aTextStyleOrNil ifNil: [^ (super withText: Text new style: ListStyle) withArray: anArray] ifNotNil: [^ (super withText: Text new style: aTextStyleOrNil) withArray: anArray]. ! ! !ListParagraph class methodsFor: 'initialization' stamp: 'sw 12/10/1999 10:37'! initialize "ListParagraph initialize" | aFont | "Allow different line spacing for lists" aFont _ Preferences standardListFont. ListStyle _ aFont textStyle copy consistOnlyOf: aFont. ListStyle gridForFont: 1 withLead: 1! ! !ListParagraph class methodsFor: 'style' stamp: 'sw 12/10/1999 10:43'! standardListStyle ^ ListStyle! ! View subclass: #ListView instanceVariableNames: 'list selection topDelimiter bottomDelimiter isEmpty textStyle' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !ListView commentStamp: '<historical>' prior: 0! 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.! !ListView methodsFor: 'initialize-release'! initialize "Refer to the comment in View|initialize." super initialize. topDelimiter _ '------------'. bottomDelimiter _ '------------'. isEmpty _ true. self list: Array new! ! !ListView methodsFor: 'font access' stamp: 'sw 12/9/1999 18:07'! font ^ self assuredTextStyle fontNamed: textStyle fontNames first ! ! !ListView methodsFor: 'font access' stamp: 'jm 9/20/1998 19:44'! font: aFontOrNil aFontOrNil ifNil: [textStyle _ nil] ifNotNil: [ textStyle _ TextStyle fontArray: (Array with: aFontOrNil). textStyle gridForFont: 1 withLead: 1]. self changed: #list. "update display" ! ! !ListView methodsFor: 'list access' stamp: 'sw 12/10/1999 10:43'! assuredTextStyle ^ textStyle ifNil: [textStyle _ ListParagraph standardListStyle] ! ! !ListView methodsFor: 'list access'! list "Answer the list of items the receiver displays." ^list! ! !ListView methodsFor: 'list access' stamp: 'sw 12/9/1999 18:06'! list: anArray "Set the list of items the receiver displays to be anArray." | arrayCopy i | isEmpty _ anArray isEmpty. arrayCopy _ Array new: (anArray size + 2). arrayCopy at: 1 put: topDelimiter. arrayCopy at: arrayCopy size put: bottomDelimiter. i _ 2. anArray do: [:el | arrayCopy at: i put: el. i _ i+1]. arrayCopy _ arrayCopy copyWithout: nil. list _ ListParagraph withArray: arrayCopy style: self assuredTextStyle. selection _ 0. self positionList. ! ! !ListView methodsFor: 'list access'! reset "Set the list of items displayed to be empty." isEmpty _ true. self list: Array new! ! !ListView methodsFor: 'list access'! resetAndDisplayView "Set the list of items displayed to be empty and redisplay the receiver." isEmpty ifFalse: [self reset. self displayView]! ! !ListView methodsFor: 'list access'! selection: selIndex selection _ selIndex! ! !ListView methodsFor: 'delimiters'! bottomDelimiter "Answer the string used to indicate the bottom of the list." ^bottomDelimiter! ! !ListView methodsFor: 'delimiters'! bottomDelimiter: aString "Set the string used to indicate the bottom of the list." bottomDelimiter _ aString! ! !ListView methodsFor: 'delimiters'! noBottomDelimiter "Set the string used to indicate the bottom of the list to be nothing." bottomDelimiter _ nil! ! !ListView methodsFor: 'delimiters'! noTopDelimiter "Set the string used to indicate the top of the list to be nothing." topDelimiter _ nil! ! !ListView methodsFor: 'delimiters'! topDelimiter "Answer the string used to indicate the top of the list." ^topDelimiter! ! !ListView methodsFor: 'delimiters'! topDelimiter: aString "Set the string used to indicate the top of the list." topDelimiter _ aString! ! !ListView methodsFor: 'displaying'! deEmphasizeSelectionBox self displaySelectionBox! ! !ListView methodsFor: 'displaying'! display "Refer to the comment in View.display." (self isUnlocked and: [self clippingBox ~= list clippingRectangle]) ifTrue: "Recompose the list if the window changed" [selection isNil ifTrue: [selection _ 0]. self positionList]. super display! ! !ListView methodsFor: 'displaying'! displaySelectionBox "If the receiver has a selection and that selection is visible on the display screen, then highlight it." selection ~= 0 ifTrue: [Display reverse: (self selectionBox intersect: self clippingBox)]! ! !ListView methodsFor: 'displaying'! displayView "Refer to the comment in View|displayView." self clearInside. list foregroundColor: self foregroundColor backgroundColor: self backgroundColor. list displayOn: Display! ! !ListView methodsFor: 'displaying'! scrollBy: anInteger "Scroll up by this amount adjusted by lineSpacing and list limits" | maximumAmount minimumAmount amount wasClipped | maximumAmount _ 0 max: list clippingRectangle top - list compositionRectangle top. minimumAmount _ 0 min: list clippingRectangle bottom - list compositionRectangle bottom. amount _ (anInteger min: maximumAmount) max: minimumAmount. amount ~= 0 ifTrue: [list scrollBy: amount negated. ^ true] ifFalse: [^ false] "Return false if no scrolling took place"! ! !ListView methodsFor: 'displaying'! scrollSelectionIntoView "Selection is assumed to be on and clipped out of view. Uses controller scrollView to keep selection right" | delta | (delta _ self insetDisplayBox bottom - self selectionBox bottom) < 0 ifTrue: [^ self controller scrollView: delta - (list lineGrid-1)]. "up" (delta _ self insetDisplayBox top - self selectionBox top) > 0 ifTrue: [^ self controller scrollView: delta + 1] "down"! ! !ListView methodsFor: 'deEmphasizing'! deEmphasizeView "Refer to the comment in View|deEmphasizeView." ^ self deEmphasizeSelectionBox! ! !ListView methodsFor: 'deEmphasizing'! emphasizeView "List emphasis is its own inverse." ^ self deEmphasizeView! ! !ListView methodsFor: 'controller access'! defaultControllerClass "Refer to the comment in View|defaultControllerClass." ^ListController! ! !ListView methodsFor: 'display box access'! boundingBox "Refer to the comment in View|boundingBox." ^list boundingBox! ! !ListView methodsFor: 'display box access' stamp: 'mkd 11/4/1999 14:31'! isSelectionBoxClipped "Answer whether there is a selection and whether the selection is visible on the screen." ^ selection ~= 0 and: [(self selectionBox intersects: (self clippingBox insetBy: (Rectangle left: 0 right: 0 top: 1 bottom: 0))) not]! ! !ListView methodsFor: 'clipping box access'! clippingBox "Answer the rectangle in which the model can be displayed--this is the insetDisplayBox inset by the height of a line for an item." ^self insetDisplayBox insetBy: (Rectangle left: 0 right: 0 top: 0 bottom: self insetDisplayBox height \\ list lineGrid)! ! !ListView methodsFor: 'selecting'! deselect "If the receiver has a selection, then it is highlighted. Remove the highlighting." selection ~= 0 ifTrue: [Display reverse: (self selectionBox intersect: self clippingBox)]! ! !ListView methodsFor: 'selecting'! findSelection: aPoint "Determine which selection is displayed in an area containing the point, aPoint. Answer the selection if one contains the point, answer nil otherwise." | trialSelection | (self clippingBox containsPoint: aPoint) ifFalse: [^nil]. trialSelection _ aPoint y - list compositionRectangle top // list lineGrid + 1. topDelimiter == nil ifFalse: [trialSelection _ trialSelection - 1]. (trialSelection < 1) | (trialSelection > self maximumSelection) ifTrue: [^ nil] ifFalse: [^ trialSelection]! ! !ListView methodsFor: 'selecting'! maximumSelection "Answer which selection is the last possible one." ^ list numberOfLines - (topDelimiter == nil ifTrue: [0] ifFalse: [1]) - (bottomDelimiter == nil ifTrue: [0] ifFalse: [1])! ! !ListView methodsFor: 'selecting'! minimumSelection "Answer which selection is the first possible one." ^ 1! ! !ListView methodsFor: 'selecting'! moveSelectionBox: anInteger "Presumably the selection has changed to be anInteger. Deselect the previous selection and display the new one, highlighted." selection ~= anInteger ifTrue: [self deselect. selection _ anInteger. self displaySelectionBox]. self isSelectionBoxClipped ifTrue: [self scrollSelectionIntoView]! ! !ListView methodsFor: 'selecting' stamp: 'di 5/22/1998 00:25'! numSelectionsInView ^ self clippingBox height // self list lineGrid! ! !ListView methodsFor: 'selecting'! selection "Answer the receiver's current selection." ^selection! ! !ListView methodsFor: 'selecting'! selectionBox "Answer the rectangle in which the current selection is displayed." ^(self insetDisplayBox left @ (list compositionRectangle top + self selectionBoxOffset) extent: self insetDisplayBox width @ list lineGrid) insetBy: (Rectangle left: 1 right: 1 top: 1 bottom: 0)! ! !ListView methodsFor: 'selecting'! selectionBoxOffset "Answer an integer that determines the y position for the display box of the current selection." ^ (selection - 1 + (topDelimiter == nil ifTrue: [0] ifFalse: [1])) * list lineGrid! ! !ListView methodsFor: 'updating'! update: aSymbol "Refer to the comment in View|update:." aSymbol == #list ifTrue: [self list: model list. self displayView. ^self]. aSymbol == #listIndex ifTrue: [self moveSelectionBox: model listIndex. ^self]! ! !ListView methodsFor: 'private'! firstShown "Return the index of the top item currently visible" | trial | trial _ self findSelection: self insetDisplayBox topLeft. ^ trial == nil ifTrue: [1] ifFalse: [trial]! ! !ListView methodsFor: 'private'! lastShown "Return the index of the bottom item currently visible" | trial bottomMargin | bottomMargin _ self insetDisplayBox height \\ list lineGrid. trial _ self findSelection: self insetDisplayBox bottomLeft - (0@bottomMargin). trial == nil ifTrue: [trial _ self findSelection: self insetDisplayBox bottomLeft - (0@(list lineGrid+bottomMargin))]. ^ trial == nil ifTrue: [list numberOfLines - 2] ifFalse: [trial]! ! !ListView methodsFor: 'private'! positionList list wrappingBox: self wrappingBox clippingBox: self clippingBox ! ! !ListView methodsFor: 'private'! wrappingBox | aRectangle | aRectangle _ self insetDisplayBox. selection = 0 ifTrue: [^aRectangle topLeft + (4 @ 0) extent: list compositionRectangle extent] ifFalse: [^aRectangle left + 4 @ (aRectangle top - (self selectionBoxOffset min: ((list height - aRectangle height + list lineGrid truncateTo: list lineGrid) max: 0))) extent: list compositionRectangle extent]! ! !ListView methodsFor: 'lock access'! lock "Refer to the comment in view|lock. Must do at least what display would do to lock the view." (self isUnlocked and: [self clippingBox ~= list clippingRectangle]) ifTrue: "Recompose the list if the window changed" [self positionList]. super lock! ! Dictionary subclass: #LiteralDictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !LiteralDictionary commentStamp: '<historical>' prior: 0! 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! !LiteralDictionary methodsFor: 'as yet unclassified' stamp: 'yo 1/27/2001 05:06'! arrayEquality: x and: y x size = y size ifFalse: [^ false]. x with: y do: [:e1 :e2 | (self literalEquality: e1 and: e2) ifFalse: [^ false] ]. ^true. ! ! !LiteralDictionary methodsFor: 'as yet unclassified' stamp: 'yo 1/27/2001 05:13'! literalEquality: x and: y ^ (x class = Array and: [y class = Array]) ifTrue: [ self arrayEquality: x and: y. ] ifFalse: [ (x class == y class) and: [x = y] ]. ! ! !LiteralDictionary methodsFor: 'as yet unclassified' stamp: 'yo 1/27/2001 05:10'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [self literalEquality: element key and: anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [self literalEquality: element key and: anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! LeafNode subclass: #LiteralNode instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !LiteralNode commentStamp: '<historical>' prior: 0! I am a parse tree leaf representing a literal string or number.! !LiteralNode methodsFor: 'code generation'! emitForValue: stack on: strm code < 256 ifTrue: [strm nextPut: code] ifFalse: [self emitLong: LoadLong on: strm]. stack push: 1! ! !LiteralNode methodsFor: 'testing'! isConstantNumber ^ key isNumber! ! !LiteralNode methodsFor: 'testing' stamp: 'di 4/5/2000 11:13'! isLiteral ^ true! ! !LiteralNode methodsFor: 'testing'! isSpecialConstant ^ code between: LdTrue and: LdMinus1+3! ! !LiteralNode methodsFor: 'testing'! literalValue ^key! ! !LiteralNode methodsFor: 'printing' stamp: 'ar 8/16/2001 13:27'! printOn: aStream indent: level (key isVariableBinding) ifTrue: [key key isNil ifTrue: [aStream nextPutAll: '###'; nextPutAll: key value soleInstance name] ifFalse: [aStream nextPutAll: '##'; nextPutAll: key key]] ifFalse: [aStream withStyleFor: #literal do: [key storeOn: aStream]]! ! VariableNode subclass: #LiteralVariableNode instanceVariableNames: 'splNode' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !LiteralVariableNode methodsFor: 'code generation' stamp: 'ar 8/16/2001 12:12'! emitLoad: stack on: strm splNode ifNil:[^super emitLoad: stack on: strm]. code < 256 ifTrue: [strm nextPut: code] ifFalse: [self emitLong: LoadLong on: strm]. stack push: 1.! ! !LiteralVariableNode methodsFor: 'code generation' stamp: 'ar 8/16/2001 12:12'! emitStore: stack on: strm splNode ifNil:[^super emitStore: stack on: strm]. splNode emit: stack args: 1 on: strm super: false.! ! !LiteralVariableNode methodsFor: 'code generation' stamp: 'ar 8/16/2001 12:12'! emitStorePop: stack on: strm splNode ifNil:[^super emitStorePop: stack on: strm]. self emitStore: stack on: strm. strm nextPut: Pop. stack pop: 1.! ! !LiteralVariableNode methodsFor: 'code generation' stamp: 'ar 8/21/2001 13:21'! sizeForStore: encoder | index | (key isVariableBinding and:[key isSpecialWriteBinding]) ifFalse:[^super sizeForStore: encoder]. code < 0 ifTrue:[ index _ self index. code _ self code: index type: LdLitType]. splNode _ encoder encodeSelector: #value:. ^(splNode size: encoder args: 1 super: false) + (super sizeForValue: encoder)! ! !LiteralVariableNode methodsFor: 'code generation' stamp: 'ar 8/21/2001 13:21'! sizeForStorePop: encoder | index | (key isVariableBinding and:[key isSpecialWriteBinding]) ifFalse:[^super sizeForStorePop: encoder]. code < 0 ifTrue:[ index _ self index. code _ self code: index type: LdLitType]. splNode _ encoder encodeSelector: #value:. ^(splNode size: encoder args: 1 super: false) + (super sizeForValue: encoder) + 1! ! Magnitude subclass: #LookupKey instanceVariableNames: 'key' classVariableNames: '' poolDictionaries: '' category: 'Collections-Support'! !LookupKey commentStamp: '<historical>' prior: 0! I represent a key for looking up entries in a data structure. Subclasses of me, such as Association, typically represent dictionary entries.! !LookupKey methodsFor: 'accessing'! key "Answer the lookup key of the receiver." ^key! ! !LookupKey methodsFor: 'accessing'! key: anObject "Store the argument, anObject, as the lookup key of the receiver." key _ anObject! ! !LookupKey methodsFor: 'accessing' stamp: 'ajh 3/24/2003 21:14'! name ^ self key isString ifTrue: [self key] ifFalse: [self key printString]! ! !LookupKey methodsFor: 'comparing'! < aLookupKey "Refer to the comment in Magnitude|<." ^key < aLookupKey key! ! !LookupKey methodsFor: 'comparing'! = aLookupKey self species = aLookupKey species ifTrue: [^key = aLookupKey key] ifFalse: [^false]! ! !LookupKey methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^key hash! ! !LookupKey methodsFor: 'comparing'! hashMappedBy: map "Answer what my hash would be if oops changed according to map." ^key hashMappedBy: map! ! !LookupKey methodsFor: 'comparing' stamp: 'di 9/27/97 20:45'! identityHashMappedBy: map "Answer what my hash would be if oops changed according to map." ^ key identityHashMappedBy: map! ! !LookupKey methodsFor: 'printing'! printOn: aStream key printOn: aStream! ! !LookupKey methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 02:35'! writeOnFilterStream: aStream aStream write:key.! ! !LookupKey methodsFor: 'testing' stamp: 'ar 8/14/2001 22:39'! isVariableBinding "Return true if I represent a literal variable binding" ^true! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! LookupKey class instanceVariableNames: ''! !LookupKey class methodsFor: 'instance creation'! key: aKey "Answer an instance of me with the argument as the lookup up." ^self new key: aKey! ! FileDirectory subclass: #MacFileDirectory instanceVariableNames: '' classVariableNames: 'TypeToMimeMappings' poolDictionaries: '' category: 'System-Files'! !MacFileDirectory commentStamp: '<historical>' prior: 0! I represent a Macintosh FileDirectory. ! !MacFileDirectory methodsFor: 'file operations' stamp: 'nk 3/13/2003 09:01'! fullPathFor: path "Return the fully-qualified path name for the given file." path isEmptyOrNil ifTrue: [^ pathName]. (self class isAbsolute: path) ifTrue: [^ path]. pathName = '' "Root dir?" ifTrue: [ ^path]. ^(path first = $:) ifTrue: [ pathName, path ] ifFalse: [pathName , ':' , path]! ! !MacFileDirectory methodsFor: 'as yet unclassified' stamp: 'hmm 3/25/2004 21:57'! fullNameFor: fileName "Return a corrected, fully-qualified name for the given file name. If the given name is already a full path (i.e., it contains a delimiter character), assume it is already a fully-qualified name. Otherwise, prefix it with the path to this directory. In either case, correct the local part of the file name." "Details: Note that path relative to a directory, such as '../../foo' are disallowed by this algorithm. Also note that this method is tolerent of a nil argument -- is simply returns nil in this case." "Fix by hmm: for a file in the root directory of a volume on MacOS, the filePath (name of the directory) is not recognizable as an absolute path anymore (it has no delimiters). Therefore, the original fileName is tested for absoluteness, and the filePath is only made absolute if the original fileName was not absolute" | correctedLocalName prefix | fileName isEmptyOrNil ifTrue: [^ fileName]. DirectoryClass splitName: fileName to: [:filePath :localName | correctedLocalName _ localName isEmpty ifFalse: [self checkName: localName fixErrors: true] ifTrue: [localName]. prefix _ (DirectoryClass isAbsolute: fileName) ifTrue: [filePath] ifFalse: [self fullPathFor: filePath]]. prefix isEmpty ifTrue: [^correctedLocalName]. prefix last = self pathNameDelimiter ifTrue:[^ prefix, correctedLocalName] ifFalse:[^ prefix, self slash, correctedLocalName]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MacFileDirectory class instanceVariableNames: ''! !MacFileDirectory class methodsFor: 'platform specific' stamp: 'md 10/26/2003 13:06'! isActiveDirectoryClass ^ super isActiveDirectoryClass and: [(SmalltalkImage current getSystemAttribute: 1201) isNil or: [(SmalltalkImage current getSystemAttribute: 1201) asNumber <= 31]]! ! !MacFileDirectory class methodsFor: 'platform specific' stamp: 'di 5/11/1999 08:53'! isCaseSensitive "Mac OS ignores the case of file names" ^ false! ! !MacFileDirectory class methodsFor: 'platform specific' stamp: 'hg 9/28/2001 15:23'! maxFileNameLength ^31! ! !MacFileDirectory class methodsFor: 'platform specific' stamp: 'jm 12/4/97 22:57'! pathNameDelimiter ^ $: ! ! !MacFileDirectory class methodsFor: 'class initialization' stamp: 'nk 12/5/2002 11:17'! isAbsolute: fileName "Return true if the given fileName is absolute. The rules are: If a path begins with a colon, it is relative. Otherwise, If it contains a colon anywhere, it is absolute and the first component is the volume name. Otherwise, It is relative." ^fileName first ~= $: and: [ fileName includes: $: ]! ! MacFileDirectory subclass: #MacHFSPlusFileDirectory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MacHFSPlusFileDirectory class instanceVariableNames: ''! !MacHFSPlusFileDirectory class methodsFor: 'platform specific' stamp: 'md 10/26/2003 13:06'! isActiveDirectoryClass "Ok, lets see if we support HFS Plus file names, the long ones" ^ (self pathNameDelimiter = self primPathNameDelimiter) and: [(SmalltalkImage current getSystemAttribute: 1201) notNil and: [(SmalltalkImage current getSystemAttribute: 1201) asNumber > 31]]! ! !MacHFSPlusFileDirectory class methodsFor: 'platform specific' stamp: 'JMM 11/14/1935 00:02'! maxFileNameLength ^ 255! ! Object subclass: #Magnitude instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Magnitudes'! !Magnitude commentStamp: '<historical>' prior: 0! Magnitude has methods for dealing with linearly ordered collections. Subclasses represent dates, times, and numbers. Example for interval-testing (answers a Boolean): 7 between: 5 and: 10 No instance-variables. ! !Magnitude methodsFor: 'comparing'! < aMagnitude "Answer whether the receiver is less than the argument." ^self subclassResponsibility! ! !Magnitude methodsFor: 'comparing'! <= aMagnitude "Answer whether the receiver is less than or equal to the argument." ^(self > aMagnitude) not! ! !Magnitude methodsFor: 'comparing'! = aMagnitude "Compare the receiver with the argument and answer with true if the receiver is equal to the argument. Otherwise answer false." ^self subclassResponsibility! ! !Magnitude methodsFor: 'comparing'! > aMagnitude "Answer whether the receiver is greater than the argument." ^aMagnitude < self! ! !Magnitude methodsFor: 'comparing'! >= aMagnitude "Answer whether the receiver is greater than or equal to the argument." ^(self < aMagnitude) not! ! !Magnitude methodsFor: 'comparing'! between: min and: max "Answer whether the receiver is less than or equal to the argument, max, and greater than or equal to the argument, min." ^self >= min and: [self <= max]! ! !Magnitude methodsFor: 'comparing'! hash "Hash must be redefined whenever = is redefined." ^self subclassResponsibility! ! !Magnitude methodsFor: 'comparing'! hashMappedBy: map "My hash is independent of my oop." ^self hash! ! !Magnitude methodsFor: 'testing'! max: aMagnitude "Answer the receiver or the argument, whichever has the greater magnitude." self > aMagnitude ifTrue: [^self] ifFalse: [^aMagnitude]! ! !Magnitude methodsFor: 'testing'! min: aMagnitude "Answer the receiver or the argument, whichever has the lesser magnitude." self < aMagnitude ifTrue: [^self] ifFalse: [^aMagnitude]! ! !Magnitude methodsFor: 'testing'! min: aMin max: aMax ^ (self min: aMin) max: aMax! ! Collection subclass: #Matrix instanceVariableNames: 'nrows ncols contents' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !Matrix commentStamp: '<historical>' prior: 0! I represent a two-dimensional array, rather like Array2D. There are three main differences between me and Array2D: (1) Array2D inherits from ArrayedCollection, but isn't one. A lot of things that should work do not work in consequence of this. (2) Array2D uses "at: column at: row" index order, which means that nothing you write using it is likely to work either. I use the almost universal "at: row at: column" order, so it is much easier to adapt code from other languages without going doolally. (3) Array2D lets you specify the class of the underlying collection, I don't. Structure: nrows : a non-negative integer saying how many rows there are. ncols : a non-negative integer saying how many columns there are. contents : an Array holding the elements in row-major order. That is, for a 2x3 array the contents are (11 12 13 21 22 23). Array2D uses column major order. You can specify the class of 'contents' when you create a new Array2D, but Matrix always gives you an Array. There is a reason for this. In strongly typed languages like Haskell and Clean, 'unboxed arrays' save you both space AND time. But in Squeak, while WordArray and FloatArray and so on do save space, it costs time to use them. A LOT of time. I've measured aFloatArray sum running nearly twice as slow as anArray sum. The reason is that whenever you fetch an element from an Array, that's all that happens, but when you fetch an element from aFloatArray, a whole new Float gets allocated to hold the value. This takes time and churns memory. So the paradox is that if you want fast numerical stuff, DON'T use unboxed arrays!! Another reason for always insisting on an Array is that letting it be something else would make things like #, and #,, rather more complicated. Always using Array is the simplest thing that could possibly work, and it works rather well. I was trying to patch Array2D to make more things work, but just couldn't get my head around the subscript order. That's why I made Matrix. Element-wise matrix arithmetic works; you can freely mix matrices and numbers but don't try to mix matrices and arrays (yet). Matrix multiplication, using the symbol +* (derived from APL's +.x), works between (Matrix or Array) +* (Matrix or Array). Don't try to use a number as an argument of +*. Matrix * Number and Number * Matrix work fine, so you don't need +* with numbers. Still to come: oodles of stuff. Gaussian elimination maybe, other stuff probably not. ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:37'! anyOne ^contents anyOne! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:37'! at: row at: column ^contents at: (self indexForRow: row andColumn: column)! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:40'! at: row at: column put: value ^contents at: (self indexForRow: row andColumn: column) put: value! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:42'! atAllPut: value contents atAllPut: value! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:43'! atRandom ^contents atRandom ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:43'! atRandom: aGenerator ^contents atRandom: aGenerator! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:44'! columnCount ^ncols! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:48'! identityIndexOf: anElement ^self identityIndexOf: anElement ifAbsent: [0@0] ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:48'! identityIndexOf: anElement ifAbsent: anExceptionBlock ^self rowAndColumnForIndex: (contents identityIndexOf: anElement ifAbsent: [^anExceptionBlock value]) ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/22/2002 13:13'! indexOf: anElement "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer 0@0. This kind of perverse result is provided by analogy with SequenceableCollection>>indexOf:. The order in which the receiver are searched is UNSPECIFIED except that it is the same as the order used by #indexOf:ifAbsent: and #readStream." ^self indexOf: anElement ifAbsent: [0@0] ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/22/2002 13:10'! indexOf: anElement ifAbsent: anExceptionBlock "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer the result of anExceptionBlock." ^self rowAndColumnForIndex: (contents indexOf: anElement ifAbsent: [^anExceptionBlock value]) ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:49'! replaceAll: oldObject with: newObject contents replaceAll: oldObject with: newObject! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:44'! rowCount ^nrows! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:49'! size ^contents size! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 10/21/2002 23:32'! atRow: row (row between: 1 and: nrows) ifFalse: [self error: '1st subscript out of range']. ^contents copyFrom: (row-1)*ncols+1 to: row*ncols! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/22/2002 12:42'! atRow: row put: aCollection |p| aCollection size = ncols ifFalse: [self error: 'wrong row size']. p _ (self indexForRow: row andColumn: 1)-1. aCollection do: [:each | contents at: (p _ p+1) put: each]. ^aCollection! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 10/22/2002 00:13'! transposed self assert: [nrows = ncols]. ^self indicesCollect: [:row :column | self at: column at: row]! ! !Matrix methodsFor: 'adding' stamp: 'raok 10/21/2002 22:53'! add: newObject self shouldNotImplement! ! !Matrix methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:01'! +* aCollection "Premultiply aCollection by self. aCollection should be an Array or Matrix. The name of this method is APL's +.x squished into Smalltalk syntax." ^aCollection preMultiplyByMatrix: self ! ! !Matrix methodsFor: 'arithmetic' stamp: 'raok 11/28/2002 14:22'! preMultiplyByArray: a "Answer a +* self where a is an Array." nrows = 1 ifFalse: [self error: 'dimensions do not conform']. ^Matrix rows: a size columns: ncols tabulate: [:row :col | (a at: row) * (contents at: col)] ! ! !Matrix methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:02'! preMultiplyByMatrix: m "Answer m +* self where m is a Matrix." |s| nrows = m columnCount ifFalse: [self error: 'dimensions do not conform']. ^Matrix rows: m rowCount columns: ncols tabulate: [:row :col | s _ 0. 1 to: nrows do: [:k | s _ (m at: row at: k) * (self at: k at: col) + s]. s]! ! !Matrix methodsFor: 'comparing' stamp: 'raok 11/22/2002 12:58'! = aMatrix ^aMatrix class == self class and: [ aMatrix rowCount = nrows and: [ aMatrix columnCount = ncols and: [ aMatrix privateContents = contents]]]! ! !Matrix methodsFor: 'comparing' stamp: 'raok 11/22/2002 13:14'! hash "I'm really not sure what would be a good hash function here. The essential thing is that it must be compatible with #=, and this satisfies that requirement." ^contents hash! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:57'! asArray ^contents shallowCopy! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:57'! asBag ^contents asBag! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asByteArray ^contents asByteArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asCharacterSet ^contents asCharacterSet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asFloatArray ^contents asFloatArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asIdentitySet ^contents asIdentitySet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asIntegerArray ^contents asIntegerArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asOrderedCollection ^contents asOrderedCollection! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asSet ^contents asSet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asSortedArray ^contents asSortedArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:59'! asSortedCollection ^contents asSortedCollection! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:59'! asSortedCollection: aBlock ^contents asSortedCollection: aBlock! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asWordArray ^contents asWordArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 11/22/2002 13:02'! readStream "Answer a ReadStream that returns all the elements of the receiver in some UNSPECIFIED order." ^ReadStream on: contents! ! !Matrix methodsFor: 'copying' stamp: 'raok 11/22/2002 12:57'! , aMatrix "Answer a new matrix having the same number of rows as the receiver and aMatrix, its columns being the columns of the receiver followed by the columns of aMatrix." |newCont newCols anArray oldCols a b c| self assert: [nrows = aMatrix rowCount]. newCont _ Array new: self size + aMatrix size. anArray _ aMatrix privateContents. oldCols _ aMatrix columnCount. newCols _ ncols + oldCols. a _ b _ c _ 1. 1 to: nrows do: [:r | newCont replaceFrom: a to: a+ncols-1 with: contents startingAt: b. newCont replaceFrom: a+ncols to: a+newCols-1 with: anArray startingAt: c. a _ a + newCols. b _ b + ncols. c _ c + oldCols]. ^self class rows: nrows columns: newCols contents: newCont ! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:07'! copy ^self class rows: nrows columns: ncols contents: contents copy! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:07'! shallowCopy ^self class rows: nrows columns: ncols contents: contents shallowCopy! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:27'! shuffled ^self class rows: nrows columns: ncols contents: (contents shuffled)! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:27'! shuffledBy: aRandom ^self class rows: nrows columns: ncols contents: (contents shuffledBy: aRandom)! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:41'! collect: aBlock "Answer a new matrix with transformed elements; transformations should be independent." ^self class rows: nrows columns: ncols contents: (contents collect: aBlock)! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! difference: aCollection "Union is in because the result is always a Set. Difference and intersection are out because the result is like the receiver, and with irregular seleection that cannot be." self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:40'! do: aBlock "Pass elements to aBlock one at a time in row-major order." contents do: aBlock! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/23/2002 20:57'! indicesCollect: aBlock |r i| r _ Array new: nrows * ncols. i _ 0. 1 to: nrows do: [:row | 1 to: ncols do: [:column | r at: (i _ i+1) put: (aBlock value: row value: column)]]. ^self class rows: nrows columns: ncols contents: r! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! intersection: aCollection "Union is in because the result is always a Set. Difference and intersection are out because the result is like the receiver, and with irregular seleection that cannot be." self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! reject: aBlock self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! select: aBlock self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/22/2002 00:15'! with: aCollection collect: aBlock "aCollection must support #at:at: and be at least as large as the receiver." ^self withIndicesCollect: [:each :row :column | aBlock value: each value: (aCollection at: row at: column)] ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:53'! with: aCollection do: aBlock "aCollection must support #at:at: and be at least as large as the receiver." self withIndicesDo: [:each :row :column | aBlock value: each value: (aCollection at: row at: column)]. ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:52'! withIndicesCollect: aBlock |i r| i _ 0. r _ contents shallowCopy. 1 to: nrows do: [:row | 1 to: ncols do: [:column | i _ i+1. r at: i put: (aBlock value: (r at: i) value: row value: column)]]. ^self class rows: nrows columns: ncols contents: r ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:52'! withIndicesDo: aBlock |i| i _ 0. 1 to: nrows do: [:row | 1 to: ncols do: [:column | aBlock value: (contents at: (i _ i+1)) value: row value: column]]. ! ! !Matrix methodsFor: 'printing' stamp: 'raok 10/21/2002 23:22'! storeOn: aStream aStream nextPut: $(; nextPutAll: self class name; nextPutAll: ' rows: '; store: nrows; nextPutAll: ' columns: '; store: ncols; nextPutAll: ' contents: '; store: contents; nextPut: $)! ! !Matrix methodsFor: 'removing' stamp: 'raok 10/21/2002 22:54'! remove: anObject ifAbsent: anExceptionBlock self shouldNotImplement! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! identityIncludes: anObject ^contents identityIncludes: anObject! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:23'! includes: anObject ^contents includes: anObject! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! includesAllOf: aCollection ^contents includesAllOf: aCollection! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! includesAnyOf: aCollection ^contents includesAnyOf: aCollection! ! !Matrix methodsFor: 'testing' stamp: 'raok 11/22/2002 13:03'! isSequenceable "LIE so that arithmetic on matrices will work. What matters for arithmetic is not that there should be random indexing but that the structure should be stable and independent of the values of the elements. #isSequenceable is simply the wrong question to ask." ^true! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:25'! occurrencesOf: anObject ^contents occurrencesOf: anObject! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 22:40'! indexForRow: row andColumn: column (row between: 1 and: nrows) ifFalse: [self error: '1st subscript out of range']. (column between: 1 and: ncols) ifFalse: [self error: '2nd subscript out of range']. ^(row-1) * ncols + column! ! !Matrix methodsFor: 'private' stamp: 'raok 11/22/2002 12:56'! privateContents "Only used in #, #,, and #= so far. It used to be called #contents, but that clashes with Collection>>contents." ^contents! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 22:47'! rowAndColumnForIndex: index |t| t _ index - 1. ^(t // ncols + 1)@(t \\ ncols + 1)! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 23:05'! rows: rows columns: columns contents: anArray self assert: [rows isInteger and: [rows >= 0]]. self assert: [columns isInteger and: [columns >= 0]]. self assert: [rows * columns = anArray size]. nrows _ rows. ncols _ columns. contents _ anArray. ^self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Matrix class instanceVariableNames: ''! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 00:06'! new: dim "Answer a dim*dim matrix. Is this an abuse of #new:? The argument is NOT a size." ^self rows: dim columns: dim! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 00:04'! rows: rows columns: columns ^self rows: rows columns: columns contents: (Array new: rows*columns)! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 19:51'! rows: rows columns: columns tabulate: aBlock "Answer a new Matrix of the given dimensions where result at: i at: j is aBlock value: i value: j" |a i| a _ Array new: rows*columns. i _ 0. 1 to: rows do: [:row | 1 to: columns do: [:column | a at: (i _ i+1) put: (aBlock value: row value: column)]]. ^self rows: rows columns: columns contents: a ! ! !Matrix class methodsFor: 'private' stamp: 'raok 10/21/2002 23:06'! rows: rows columns: columns contents: contents ^self new rows: rows columns: columns contents: contents! ! Object subclass: #Message instanceVariableNames: 'selector args lookupClass' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !Message commentStamp: '<historical>' prior: 0! I represent a selector and its argument values. 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.! !Message methodsFor: 'accessing'! argument "Answer the first (presumably sole) argument" ^args at: 1! ! !Message methodsFor: 'accessing'! argument: newValue "Change the first argument to newValue and answer self" args at: 1 put: newValue! ! !Message methodsFor: 'accessing'! arguments "Answer the arguments of the receiver." ^args! ! !Message methodsFor: 'accessing' stamp: 'ajh 10/9/2001 16:32'! lookupClass ^ lookupClass! ! !Message methodsFor: 'accessing'! selector "Answer the selector of the receiver." ^selector! ! !Message methodsFor: 'accessing'! sends: aSelector "answer whether this message's selector is aSelector" ^selector == aSelector! ! !Message methodsFor: 'printing' stamp: 'ajh 10/9/2001 15:31'! printOn: stream args isEmpty ifTrue: [^ stream nextPutAll: selector]. args with: selector keywords do: [:arg :word | stream nextPutAll: word. stream space. arg printOn: stream. stream space. ]. stream skip: -1. ! ! !Message methodsFor: 'printing' stamp: 'sma 6/1/2000 10:01'! storeOn: aStream "Refer to the comment in Object|storeOn:." aStream nextPut: $(; nextPutAll: self class name; nextPutAll: ' selector: '; store: selector; nextPutAll: ' arguments: '; store: args; nextPut: $)! ! !Message methodsFor: 'private' stamp: 'ajh 3/9/2003 19:25'! setSelector: aSymbol selector _ aSymbol. ! ! !Message methodsFor: 'private'! setSelector: aSymbol arguments: anArray selector _ aSymbol. args _ anArray! ! !Message methodsFor: 'sending' stamp: 'di 3/25/1999 21:54'! sentTo: receiver "answer the result of sending this message to receiver" lookupClass == nil ifTrue: [^ receiver perform: selector withArguments: args] ifFalse: [^ receiver perform: selector withArguments: args inSuperclass: lookupClass]! ! !Message methodsFor: 'stub creation' stamp: 'ads 7/21/2003 17:33'! createStubMethod | argNames aOrAn argName arg argClassName | argNames _ Set new. ^ String streamContents: [ :s | self selector keywords doWithIndex: [ :key :i | s nextPutAll: key. ((key last = $:) or: [self selector isInfix]) ifTrue: [ arg _ self arguments at: i. argClassName _ (arg isKindOf: Class) ifTrue: ['Class'] ifFalse: [arg class name]. aOrAn _ argClassName first isVowel ifTrue: ['an'] ifFalse: ['a']. argName _ aOrAn, argClassName. [argNames includes: argName] whileTrue: [argName _ argName, i asString]. argNames add: argName. s nextPutAll: ' '; nextPutAll: argName; space ]. ]. s cr; tab. s nextPutAll: 'self shouldBeImplemented' ]! ! !Message methodsFor: 'as yet unclassified' stamp: 'md 11/14/2003 17:37'! pushReceiver! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Message class instanceVariableNames: ''! !Message class methodsFor: 'instance creation'! selector: aSymbol "Answer an instance of me with unary selector, aSymbol." ^self new setSelector: aSymbol arguments: (Array new: 0)! ! !Message class methodsFor: 'instance creation'! selector: aSymbol argument: anObject "Answer an instance of me whose selector is aSymbol and single argument is anObject." ^self new setSelector: aSymbol arguments: (Array with: anObject)! ! !Message class methodsFor: 'instance creation'! selector: aSymbol arguments: anArray "Answer an instance of me with selector, aSymbol, and arguments, anArray." ^self new setSelector: aSymbol arguments: anArray! ! MessageNode subclass: #MessageAsTempNode instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !MessageAsTempNode commentStamp: '<historical>' prior: 0! This node represents accesses to temporary variables for do-its in the debugger. Since they execute in another context, they must send a message to the original context to access the value of the temporary variable in that context.! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:38'! asStorableNode: encoder "This node is a message masquerading as a temporary variable. It currently has the form {homeContext tempAt: offset}. We need to generate code for {expr storeAt: offset inTempFrame: homeContext}, where the expr, the block argument, is already on the stack. This, in turn will get turned into {homeContext tempAt: offset put: expr} at runtime if nobody disturbs storeAt:inTempFrame: in Object (not clean)" ^ MessageAsTempNode new receiver: nil "suppress code generation for reciever already on stack" selector: #storeAt:inTempFrame: arguments: (arguments copyWith: receiver) precedence: precedence from: encoder! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 10/12/1999 17:29'! code "Allow synthetic temp nodes to be sorted by code" ^ arguments first literalValue! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! emitStorePop: stack on: codeStream "This node has the form {expr storeAt: offset inTempFrame: homeContext}, where the expr, the block argument, is already on the stack." ^ self emitForEffect: stack on: codeStream! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:35'! isTemp "Masquerading for debugger access to temps." ^ true! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! nowHasDef "For compatibility with temp scope protocol" ! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! nowHasRef "For compatibility with temp scope protocol" ! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! scope "For compatibility with temp scope protocol" ^ -1! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! scope: ignored "For compatibility with temp scope protocol" ! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:39'! sizeForStorePop: encoder "This node has the form {expr storeAt: offset inTempFrame: homeContext}, where the expr, the block argument, is already on the stack." ^ self sizeForEffect: encoder! ! !MessageAsTempNode methodsFor: 'access to remote temps' stamp: 'di 3/22/1999 09:40'! store: expr from: encoder "ctxt tempAt: n -> ctxt tempAt: n put: expr (see Assignment). For assigning into temps of a context being debugged." selector key ~= #tempAt: ifTrue: [^self error: 'cant transform this message']. ^ MessageAsTempNode new receiver: receiver selector: #tempAt:put: arguments: (arguments copyWith: expr) precedence: precedence from: encoder! ! ProtoObject subclass: #MessageCatcher instanceVariableNames: 'echoToTranscript' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Contexts'! !MessageCatcher commentStamp: '<historical>' prior: 0! Any message sent to me is returned as a Message object. "Message catcher" creates an instance of me. ! !MessageCatcher methodsFor: 'as yet unclassified' stamp: 'ajh 9/26/2002 12:24'! doesNotUnderstand: aMessage echoToTranscript == true ifTrue: [Transcript show: aMessage printString; cr]. ^ aMessage! ! MessageSet subclass: #MessageNames instanceVariableNames: 'searchString selectorList selectorListIndex' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !MessageNames methodsFor: 'search' stamp: 'sd 4/20/2003 14:28'! computeSelectorListFromSearchString "Compute selector list from search string" | raw sorted | searchString _ searchString asString copyWithout: $ . selectorList _ Cursor wait showWhile: [raw _ Symbol selectorsContaining: searchString. sorted _ raw as: SortedCollection. sorted sortBlock: [:x :y | x asLowercase <= y asLowercase]. sorted asArray]. selectorList size > 19 ifFalse: ["else the following filtering is considered too expensive. This 19 should be a system-maintained Parameter, someday" selectorList _ self systemNavigation allSelectorsWithAnyImplementorsIn: selectorList]. ^ selectorList! ! !MessageNames methodsFor: 'search' stamp: 'sw 7/28/2001 00:32'! doSearchFrom: aPane "The user hit the Search button -- treat it as a synonym for the user having hit the Return or Enter (or cmd-s) in the type-in pane" aPane accept. aPane selectAll! ! !MessageNames methodsFor: 'search' stamp: 'sw 7/28/2001 00:43'! searchString "Answer the current searchString, initializing it if need be" | pane | searchString isEmptyOrNil ifTrue: [searchString _ 'type here, then hit Search'. pane _ self containingWindow findDeepSubmorphThat: [:m | m knownName = 'Search'] ifAbsent: ["this happens during window creation" ^ searchString]. pane setText: searchString. pane setTextMorphToSelectAllOnMouseEnter. pane selectAll]. ^ searchString! ! !MessageNames methodsFor: 'search' stamp: 'sw 7/28/2001 02:18'! searchString: aString notifying: aController "Take what the user typed and find all selectors containing it" searchString _ aString asString copyWithout: $ . self containingWindow setLabel: 'Message names containing "', searchString asLowercase, '"'. selectorList _ nil. self changed: #selectorList. self changed: #messageList. ^ true! ! !MessageNames methodsFor: 'search' stamp: 'sd 4/20/2003 14:28'! showOnlyImplementedSelectors "Caution -- can be slow!! Filter my selector list down such that it only shows selectors that are actually implemented somewhere in the system." self okToChange ifTrue: [Cursor wait showWhile: [selectorList _ self systemNavigation allSelectorsWithAnyImplementorsIn: selectorList. self changed: #selectorList. self changed: #messageList]]! ! !MessageNames methodsFor: 'selection' stamp: 'sw 7/24/2001 01:46'! selection "Answer the item in the list that is currently selected, or nil if no selection is present" ^ self messageList at: messageListIndex ifAbsent: [nil]! ! !MessageNames methodsFor: 'selector list' stamp: 'sd 4/19/2003 12:12'! messageList "Answer the receiver's message list, computing it if necessary. The way to force a recomputation is to set the messageList to nil" messageList ifNil: [messageList _ selectorListIndex == 0 ifTrue: [#()] ifFalse: [self systemNavigation allImplementorsOf: (selectorList at: selectorListIndex)]. self messageListIndex: (messageList size > 0 ifTrue: [1] ifFalse: [0])]. ^ messageList! ! !MessageNames methodsFor: 'selector list' stamp: 'sw 7/24/2001 01:46'! selectorList "Answer the selectorList" selectorList ifNil: [self computeSelectorListFromSearchString. selectorListIndex _ selectorList size > 0 ifTrue: [1] ifFalse: [0]. messageList _ nil]. ^ selectorList! ! !MessageNames methodsFor: 'selector list' stamp: 'sw 7/24/2001 01:55'! selectorListIndex "Answer the selectorListIndex" ^ selectorListIndex! ! !MessageNames methodsFor: 'selector list' stamp: 'sw 7/24/2001 01:59'! selectorListIndex: anInteger "Set the selectorListIndex as specified, and propagate consequences" selectorListIndex _ anInteger. selectorListIndex = 0 ifTrue: [^ self]. messageList _ nil. self changed: #selectorListIndex. self changed: #messageList! ! !MessageNames methodsFor: 'selector list' stamp: 'sw 7/24/2001 01:58'! selectorListMenu: aMenu "Answer the menu associated with the selectorList" aMenu addList: #( ('senders (n)' browseSenders 'browse senders of the chosen selector') ('copy selector to clipboard' copyName 'copy the chosen selector to the clipboard, for subsequent pasting elsewhere') - ('show only implemented selectors' showOnlyImplementedSelectors 'remove from the selector-list all symbols that do not represent implemented methods')). ^ aMenu! ! !MessageNames methodsFor: 'selector list' stamp: 'sw 7/24/2001 01:47'! selectorListMenuTitle "Answer the title to supply for the menu belonging to the selector-list pane" ^ 'Click on any item in the list to see all implementors of it'! ! !MessageNames methodsFor: 'initialization' stamp: 'sw 7/24/2001 01:35'! selectorListKey: aChar from: view "Respond to a Command key in the message-list pane." aChar == $n ifTrue: [^ self browseSenders]. aChar == $c ifTrue: [^ self copyName]. aChar == $b ifTrue: [^ self browseMethodFull]. ! ! !MessageNames methodsFor: 'message list menu' stamp: 'sw 8/15/2002 17:24'! copyName "Copy the current selector to the clipboard" | selector | (selector _ self selectorList at: selectorListIndex ifAbsent: [nil]) ifNotNil: [Clipboard clipboardText: selector asString asText]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MessageNames class instanceVariableNames: ''! !MessageNames class methodsFor: 'instance creation' stamp: 'sw 7/28/2001 00:56'! prototypicalToolWindow "Answer an example of myself seen in a tool window, for the benefit of parts-launching tools" ^ self methodBrowserSearchingFor: nil! ! !MessageNames class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:53'! initialize self registerInFlapsRegistry. ! ! !MessageNames class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 12:53'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(MessageNames prototypicalToolWindow 'Message Names' 'A tool for finding, viewing, and editing all methods whose names contain a given character sequence.') forFlapNamed: 'Tools']! ! !MessageNames class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:37'! unload "Unload the receiver from global registries" self environment at: #FileList ifPresent: [:cl | cl unregisterFileReader: self]. self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! ParseNode subclass: #MessageNode instanceVariableNames: 'receiver selector precedence special arguments sizes equalNode caseErrorNode' classVariableNames: 'MacroEmitters MacroPrinters MacroSelectors MacroSizers MacroTransformers StdTypers ThenFlag' poolDictionaries: '' category: 'System-Compiler'! !MessageNode commentStamp: '<historical>' prior: 0! I represent a receiver and its message. Precedence codes: 1 unary 2 binary 3 keyword 4 other If special>0, I compile special code in-line instead of sending messages with literal methods as remotely copied contexts.! !MessageNode methodsFor: 'initialize-release' stamp: 'di 6/6/2000 23:24'! receiver: rcvr selector: selNode arguments: args precedence: p "Decompile." self receiver: rcvr arguments: args precedence: p. self noteSpecialSelector: selNode key. selector _ selNode. "self pvtCheckForPvtSelector: encoder" "We could test code being decompiled, but the compiler should've checked already. And where to send the complaint?"! ! !MessageNode methodsFor: 'initialize-release' stamp: 'di 6/6/2000 23:27'! receiver: rcvr selector: aSelector arguments: args precedence: p from: encoder "Compile." | theSelector | self receiver: rcvr arguments: args precedence: p. aSelector = #:Repeat:do: ifTrue: [theSelector _ #do:] ifFalse: [theSelector _ aSelector]. self noteSpecialSelector: theSelector. (self transform: encoder) ifTrue: [selector isNil ifTrue: [selector _ SelectorNode new key: (MacroSelectors at: special) code: #macro]] ifFalse: [selector _ encoder encodeSelector: theSelector. rcvr == NodeSuper ifTrue: [encoder noteSuper]]. self pvtCheckForPvtSelector: encoder! ! !MessageNode methodsFor: 'initialize-release'! receiver: rcvr selector: selName arguments: args precedence: p from: encoder sourceRange: range "Compile." encoder noteSourceRange: range forNode: self. ^self receiver: rcvr selector: selName arguments: args precedence: p from: encoder! ! !MessageNode methodsFor: 'initialize-release' stamp: 'tk 10/26/2000 15:37'! selector: sel selector _ sel! ! !MessageNode methodsFor: 'testing'! canCascade ^(receiver == NodeSuper or: [special > 0]) not! ! !MessageNode methodsFor: 'testing'! isComplex ^(special between: 1 and: 10) or: [arguments size > 2 or: [receiver isComplex]]! ! !MessageNode methodsFor: 'testing'! isMessage: selSymbol receiver: rcvrPred arguments: argsPred "Answer whether selector is selSymbol, and the predicates rcvrPred and argsPred evaluate to true with respect to receiver and the list of arguments. If selSymbol or either predicate is nil, it means 'don't care'. Note that argsPred takes numArgs arguments. All block arguments are ParseNodes." ^(selSymbol isNil or: [selSymbol==selector key]) and: [(rcvrPred isNil or: [rcvrPred value: receiver]) and: [(argsPred isNil or: [argsPred valueWithArguments: arguments])]]! ! !MessageNode methodsFor: 'testing'! isReturningIf ^(special between: 3 and: 4) and: [arguments first returns and: [arguments last returns]]! ! !MessageNode methodsFor: 'testing'! toDoIncrement: variable (receiver = variable and: [selector key = #+]) ifFalse: [^ nil]. arguments first isConstantNumber ifTrue: [^ arguments first] ifFalse: [^ nil]! ! !MessageNode methodsFor: 'testing'! toDoLimit: variable (receiver = variable and: [selector key = #<= or: [selector key = #>=]]) ifTrue: [^ arguments first] ifFalse: [^ nil]! ! !MessageNode methodsFor: 'cascading'! cascadeReceiver "Nil out rcvr (to indicate cascade) and return what it had been." | rcvr | rcvr _ receiver. receiver _ nil. ^rcvr! ! !MessageNode methodsFor: 'macro transformations' stamp: 'di 6/11/2000 16:09'! noteSpecialSelector: selectorSymbol " special > 0 denotes specially treated messages. " "Deconvert initial keywords from SQ2K" special _ #(:Test:Yes: :Test:No: :Test:Yes:No: :Test:No:Yes: and: or: :Until:do: :While:do: whileFalse whileTrue :Repeat:to:do: :Repeat:to:by:do: ) indexOf: selectorSymbol. special > 0 ifTrue: [^ self]. special _ MacroSelectors indexOf: selectorSymbol. ! ! !MessageNode methodsFor: 'macro transformations' stamp: 'sma 3/3/2000 13:37'! toDoFromWhileWithInit: initStmt "Return nil, or a to:do: expression equivalent to this whileTrue:" | variable increment limit toDoBlock body test | (selector key == #whileTrue: and: [(initStmt isMemberOf: AssignmentNode) and: [initStmt variable isTemp]]) ifFalse: [^ nil]. body _ arguments last statements. variable _ initStmt variable. increment _ body last toDoIncrement: variable. (increment == nil or: [receiver statements size ~= 1]) ifTrue: [^ nil]. test _ receiver statements first. "Note: test chould really be checked that <= or >= comparison jibes with the sign of the (constant) increment" ((test isMemberOf: MessageNode) and: [(limit _ test toDoLimit: variable) notNil]) ifFalse: [^ nil]. toDoBlock _ BlockNode statements: body allButLast returns: false. toDoBlock arguments: (Array with: variable). ^ MessageNode new receiver: initStmt value selector: (SelectorNode new key: #to:by:do: code: #macro) arguments: (Array with: limit with: increment with: toDoBlock) precedence: precedence! ! !MessageNode methodsFor: 'macro transformations'! transform: encoder special = 0 ifTrue: [^false]. (self perform: (MacroTransformers at: special) with: encoder) ifTrue: [^true] ifFalse: [special _ 0. ^false]! ! !MessageNode methodsFor: 'macro transformations'! transformAnd: encoder (self transformBoolean: encoder) ifTrue: [arguments _ Array with: (arguments at: 1) with: (BlockNode withJust: NodeFalse). ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations'! transformBoolean: encoder ^self checkBlock: (arguments at: 1) as: 'argument' from: encoder! ! !MessageNode methodsFor: 'macro transformations'! transformIfFalse: encoder (self transformBoolean: encoder) ifTrue: [arguments _ Array with: (BlockNode withJust: NodeNil) with: (arguments at: 1). ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations' stamp: 'acg 1/28/2000 00:48'! transformIfFalseIfTrue: encoder ((self checkBlock: (arguments at: 1) as: 'False arg' from: encoder) and: [self checkBlock: (arguments at: 2) as: 'True arg' from: encoder]) ifTrue: [selector _ #ifTrue:ifFalse:. arguments swap: 1 with: 2. ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations' stamp: 'di 4/24/2000 13:32'! transformIfNil: encoder (self transformBoolean: encoder) ifFalse: [^ false]. (MacroSelectors at: special) = #ifNotNil: ifTrue: [(self checkBlock: arguments first as: 'ifNotNil arg' from: encoder) ifFalse: [^ false]. "Transform 'ifNotNil: [stuff]' to 'ifNil: [nil] ifNotNil: [stuff]'. Slightly better code and more consistent with decompilation." self noteSpecialSelector: #ifNil:ifNotNil:. selector _ SelectorNode new key: (MacroSelectors at: special) code: #macro. arguments _ {BlockNode withJust: NodeNil. arguments first}. (self transform: encoder) ifFalse: [self error: 'compiler logic error']. ^ true] ifFalse: [^ self checkBlock: arguments first as: 'ifNil arg' from: encoder] ! ! !MessageNode methodsFor: 'macro transformations' stamp: 'acg 1/28/2000 21:49'! transformIfNilIfNotNil: encoder ((self checkBlock: (arguments at: 1) as: 'Nil arg' from: encoder) and: [self checkBlock: (arguments at: 2) as: 'NotNil arg' from: encoder]) ifTrue: [selector _ SelectorNode new key: #ifTrue:ifFalse: code: #macro. receiver _ MessageNode new receiver: receiver selector: #== arguments: (Array with: NodeNil) precedence: 2 from: encoder. ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations' stamp: 'acg 1/28/2000 21:50'! transformIfNotNilIfNil: encoder ((self checkBlock: (arguments at: 1) as: 'NotNil arg' from: encoder) and: [self checkBlock: (arguments at: 2) as: 'Nil arg' from: encoder]) ifTrue: [selector _ SelectorNode new key: #ifTrue:ifFalse: code: #macro. receiver _ MessageNode new receiver: receiver selector: #== arguments: (Array with: NodeNil) precedence: 2 from: encoder. arguments swap: 1 with: 2. ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations'! transformIfTrue: encoder (self transformBoolean: encoder) ifTrue: [arguments _ Array with: (arguments at: 1) with: (BlockNode withJust: NodeNil). ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations' stamp: 'acg 1/27/2000 22:29'! transformIfTrueIfFalse: encoder ^(self checkBlock: (arguments at: 1) as: 'True arg' from: encoder) and: [self checkBlock: (arguments at: 2) as: 'False arg' from: encoder]! ! !MessageNode methodsFor: 'macro transformations'! transformOr: encoder (self transformBoolean: encoder) ifTrue: [arguments _ Array with: (BlockNode withJust: NodeTrue) with: (arguments at: 1). ^true] ifFalse: [^false]! ! !MessageNode methodsFor: 'macro transformations' stamp: 'hmm 7/15/2001 22:22'! transformToDo: encoder " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: " | limit increment block initStmt test incStmt limitInit blockVar myRange blockRange | "First check for valid arguments" ((arguments last isMemberOf: BlockNode) and: [arguments last numberOfArguments = 1]) ifFalse: [^ false]. arguments last firstArgument isVariableReference ifFalse: [^ false]. "As with debugger remote vars" arguments size = 3 ifTrue: [increment _ arguments at: 2. (increment isConstantNumber and: [increment literalValue ~= 0]) ifFalse: [^ false]] ifFalse: [increment _ encoder encodeLiteral: 1]. arguments size < 3 ifTrue: "transform to full form" [selector _ SelectorNode new key: #to:by:do: code: #macro]. "Now generate auxiliary structures" myRange _ encoder rawSourceRanges at: self ifAbsent: [1 to: 0]. block _ arguments last. blockRange _ encoder rawSourceRanges at: block ifAbsent: [1 to: 0]. blockVar _ block firstArgument. initStmt _ AssignmentNode new variable: blockVar value: receiver. limit _ arguments at: 1. limit isVariableReference | limit isConstantNumber ifTrue: [limitInit _ nil] ifFalse: "Need to store limit in a var" [limit _ encoder autoBind: blockVar key , 'LimiT'. limit scope: -2. "Already done parsing block" limitInit _ AssignmentNode new variable: limit value: (arguments at: 1)]. test _ MessageNode new receiver: blockVar selector: (increment key > 0 ifTrue: [#<=] ifFalse: [#>=]) arguments: (Array with: limit) precedence: precedence from: encoder sourceRange: (myRange first to: blockRange first). incStmt _ AssignmentNode new variable: blockVar value: (MessageNode new receiver: blockVar selector: #+ arguments: (Array with: increment) precedence: precedence from: encoder) from: encoder sourceRange: (myRange last to: myRange last). arguments _ (Array with: limit with: increment with: block) , (Array with: initStmt with: test with: incStmt with: limitInit). ^ true! ! !MessageNode methodsFor: 'macro transformations'! transformWhile: encoder (self checkBlock: receiver as: 'receiver' from: encoder) ifFalse: [^ false]. arguments size = 0 "transform bodyless form to body form" ifTrue: [selector _ SelectorNode new key: (special = 10 ifTrue: [#whileTrue:] ifFalse: [#whileFalse:]) code: #macro. arguments _ Array with: (BlockNode withJust: NodeNil). ^ true] ifFalse: [^ self transformBoolean: encoder]! ! !MessageNode methodsFor: 'code generation' stamp: 'tao 8/20/97 22:24'! emitCase: stack on: strm value: forValue | braceNode sizeStream thenSize elseSize | forValue not ifTrue: [^super emitForEffect: stack on: strm]. braceNode _ arguments first. sizeStream _ ReadStream on: sizes. receiver emitForValue: stack on: strm. braceNode casesForwardDo: [:keyNode :valueNode :last | thenSize _ sizeStream next. elseSize _ sizeStream next. last ifFalse: [strm nextPut: Dup. stack push: 1]. keyNode emitForEvaluatedValue: stack on: strm. equalNode emit: stack args: 1 on: strm. self emitBranchOn: false dist: thenSize pop: stack on: strm. last ifFalse: [strm nextPut: Pop. stack pop: 1]. valueNode emitForEvaluatedValue: stack on: strm. last ifTrue: [stack pop: 1]. valueNode returns ifFalse: [self emitJump: elseSize on: strm]]. arguments size = 2 ifTrue: [arguments last emitForEvaluatedValue: stack on: strm] "otherwise: [...]" ifFalse: [NodeSelf emitForValue: stack on: strm. caseErrorNode emit: stack args: 0 on: strm]! ! !MessageNode methodsFor: 'code generation' stamp: 'hmm 7/28/2001 14:39'! emitForEffect: stack on: strm "For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly." special > 0 ifTrue: [pc _ 0. self perform: (MacroEmitters at: special) with: stack with: strm with: false] ifFalse: [super emitForEffect: stack on: strm]! ! !MessageNode methodsFor: 'code generation' stamp: 'hmm 7/28/2001 14:40'! emitForValue: stack on: strm "For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly." special > 0 ifTrue: [pc _ 0. self perform: (MacroEmitters at: special) with: stack with: strm with: true] ifFalse: [receiver ~~ nil ifTrue: [receiver emitForValue: stack on: strm]. arguments do: [:argument | argument emitForValue: stack on: strm]. selector emit: stack args: arguments size on: strm super: receiver == NodeSuper. pc _ strm position]! ! !MessageNode methodsFor: 'code generation' stamp: 'hmm 7/28/2001 14:23'! emitIf: stack on: strm value: forValue | thenExpr thenSize elseExpr elseSize | thenSize _ sizes at: 1. elseSize _ sizes at: 2. (forValue not and: [(elseSize*thenSize) > 0]) ifTrue: "Two-armed IFs forEffect share a single pop" [^ super emitForEffect: stack on: strm]. thenExpr _ arguments at: 1. elseExpr _ arguments at: 2. receiver emitForValue: stack on: strm. forValue ifTrue: "Code all forValue as two-armed" [self emitBranchOn: false dist: thenSize pop: stack on: strm. pc _ strm position. thenExpr emitForEvaluatedValue: stack on: strm. stack pop: 1. "then and else alternate; they don't accumulate" thenExpr returns not ifTrue: "Elide jump over else after a return" [self emitJump: elseSize on: strm]. elseExpr emitForEvaluatedValue: stack on: strm] ifFalse: "One arm is empty here (two-arms code forValue)" [thenSize > 0 ifTrue: [self emitBranchOn: false dist: thenSize pop: stack on: strm. pc _ strm position. thenExpr emitForEvaluatedEffect: stack on: strm] ifFalse: [self emitBranchOn: true dist: elseSize pop: stack on: strm. pc _ strm position. elseExpr emitForEvaluatedEffect: stack on: strm]]! ! !MessageNode methodsFor: 'code generation' stamp: 'ajh 7/31/2003 11:26'! emitIfNil: stack on: strm value: forValue | theNode theSize theSelector | theNode _ arguments first. theSize _ sizes at: 1. theSelector _ #ifNotNil:. receiver emitForValue: stack on: strm. forValue ifTrue: [strm nextPut: Dup. stack push: 1]. strm nextPut: LdNil. stack push: 1. equalNode emit: stack args: 1 on: strm. self emitBranchOn: (selector key == theSelector) dist: theSize pop: stack on: strm. pc _ strm position. forValue ifTrue: [strm nextPut: Pop. stack pop: 1. theNode emitForEvaluatedValue: stack on: strm] ifFalse: [theNode emitForEvaluatedEffect: stack on: strm].! ! !MessageNode methodsFor: 'code generation' stamp: 'hmm 7/28/2001 14:42'! emitToDo: stack on: strm value: forValue " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: " | loopSize initStmt limitInit test block incStmt blockSize | initStmt _ arguments at: 4. limitInit _ arguments at: 7. test _ arguments at: 5. block _ arguments at: 3. incStmt _ arguments at: 6. blockSize _ sizes at: 1. loopSize _ sizes at: 2. limitInit == nil ifFalse: [limitInit emitForEffect: stack on: strm]. initStmt emitForEffect: stack on: strm. test emitForValue: stack on: strm. self emitBranchOn: false dist: blockSize pop: stack on: strm. pc _ strm position. block emitForEvaluatedEffect: stack on: strm. incStmt emitForEffect: stack on: strm. self emitJump: 0 - loopSize on: strm. forValue ifTrue: [strm nextPut: LdNil. stack push: 1]! ! !MessageNode methodsFor: 'code generation' stamp: 'hmm 7/28/2001 14:36'! emitWhile: stack on: strm value: forValue " L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2: " | cond stmt stmtSize loopSize | cond _ receiver. stmt _ arguments at: 1. stmtSize _ sizes at: 1. loopSize _ sizes at: 2. cond emitForEvaluatedValue: stack on: strm. self emitBranchOn: (selector key == #whileFalse:) "Bfp for whileTrue" dist: stmtSize pop: stack on: strm. "Btp for whileFalse" pc _ strm position. stmt emitForEvaluatedEffect: stack on: strm. self emitJump: 0 - loopSize on: strm. forValue ifTrue: [strm nextPut: LdNil. stack push: 1]! ! !MessageNode methodsFor: 'code generation'! pc "Used by encoder source mapping." pc==nil ifTrue: [^0] ifFalse: [^pc]! ! !MessageNode methodsFor: 'code generation' stamp: 'tao 8/20/97 22:25'! sizeCase: encoder value: forValue | braceNode sizeIndex thenSize elseSize | forValue not ifTrue: [^super sizeForEffect: encoder]. equalNode _ encoder encodeSelector: #=. braceNode _ arguments first. sizes _ Array new: 2 * braceNode numElements. sizeIndex _ sizes size. elseSize _ arguments size = 2 ifTrue: [arguments last sizeForEvaluatedValue: encoder] "otherwise: [...]" ifFalse: [caseErrorNode _ encoder encodeSelector: #caseError. 1 + (caseErrorNode size: encoder args: 0 super: false)]. "self caseError" braceNode casesReverseDo: [:keyNode :valueNode :last | sizes at: sizeIndex put: elseSize. thenSize _ valueNode sizeForEvaluatedValue: encoder. last ifFalse: [thenSize _ thenSize + 1]. "Pop" valueNode returns ifFalse: [thenSize _ thenSize + (self sizeJump: elseSize)]. sizes at: sizeIndex-1 put: thenSize. last ifFalse: [elseSize _ elseSize + 1]. "Dup" elseSize _ elseSize + (keyNode sizeForEvaluatedValue: encoder) + (equalNode size: encoder args: 1 super: false) + (self sizeBranchOn: false dist: thenSize) + thenSize. sizeIndex _ sizeIndex - 2]. ^(receiver sizeForValue: encoder) + elseSize ! ! !MessageNode methodsFor: 'code generation'! sizeForEffect: encoder special > 0 ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: false]. ^super sizeForEffect: encoder! ! !MessageNode methodsFor: 'code generation'! sizeForValue: encoder | total argSize | special > 0 ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: true]. receiver == NodeSuper ifTrue: [selector _ selector copy "only necess for splOops"]. total _ selector size: encoder args: arguments size super: receiver == NodeSuper. receiver == nil ifFalse: [total _ total + (receiver sizeForValue: encoder)]. sizes _ arguments collect: [:arg | argSize _ arg sizeForValue: encoder. total _ total + argSize. argSize]. ^total! ! !MessageNode methodsFor: 'code generation'! sizeIf: encoder value: forValue | thenExpr elseExpr branchSize thenSize elseSize | thenExpr _ arguments at: 1. elseExpr _ arguments at: 2. (forValue or: [(thenExpr isJust: NodeNil) or: [elseExpr isJust: NodeNil]]) not "(...not ifTrue: avoids using ifFalse: alone during this compile)" ifTrue: "Two-armed IFs forEffect share a single pop" [^ super sizeForEffect: encoder]. forValue ifTrue: "Code all forValue as two-armed" [elseSize _ elseExpr sizeForEvaluatedValue: encoder. thenSize _ (thenExpr sizeForEvaluatedValue: encoder) + (thenExpr returns ifTrue: [0] "Elide jump over else after a return" ifFalse: [self sizeJump: elseSize]). branchSize _ self sizeBranchOn: false dist: thenSize] ifFalse: "One arm is empty here (two-arms code forValue)" [(elseExpr isJust: NodeNil) ifTrue: [elseSize _ 0. thenSize _ thenExpr sizeForEvaluatedEffect: encoder. branchSize _ self sizeBranchOn: false dist: thenSize] ifFalse: [thenSize _ 0. elseSize _ elseExpr sizeForEvaluatedEffect: encoder. branchSize _ self sizeBranchOn: true dist: elseSize]]. sizes _ Array with: thenSize with: elseSize. ^ (receiver sizeForValue: encoder) + branchSize + thenSize + elseSize! ! !MessageNode methodsFor: 'code generation' stamp: 'acg 1/28/2000 22:00'! sizeIfNil: encoder value: forValue | theNode theSize theSelector | equalNode _ encoder encodeSelector: #==. sizes _ Array new: 1. theNode _ arguments first. theSelector _ #ifNotNil:. forValue ifTrue: [sizes at: 1 put: (theSize _ (1 "pop" + (theNode sizeForEvaluatedValue: encoder))). ^(receiver sizeForValue: encoder) + 2 "Dup. LdNil" + (equalNode size: encoder args: 1 super: false) + (self sizeBranchOn: (selector key == theSelector) dist: theSize) + theSize] ifFalse: [sizes at: 1 put: (theSize _ (theNode sizeForEvaluatedEffect: encoder)). ^(receiver sizeForValue: encoder) + 1 "LdNil" + (equalNode size: encoder args: 1 super: false) + (self sizeBranchOn: (selector key == theSelector) dist: theSize) + theSize] ! ! !MessageNode methodsFor: 'code generation'! sizeToDo: encoder value: forValue " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: " | loopSize initStmt test block incStmt blockSize blockVar initSize limitInit | block _ arguments at: 3. blockVar _ block firstArgument. initStmt _ arguments at: 4. test _ arguments at: 5. incStmt _ arguments at: 6. limitInit _ arguments at: 7. initSize _ initStmt sizeForEffect: encoder. limitInit == nil ifFalse: [initSize _ initSize + (limitInit sizeForEffect: encoder)]. blockSize _ (block sizeForEvaluatedEffect: encoder) + (incStmt sizeForEffect: encoder) + 2. "+2 for Jmp backward" loopSize _ (test sizeForValue: encoder) + (self sizeBranchOn: false dist: blockSize) + blockSize. sizes _ Array with: blockSize with: loopSize. ^ initSize + loopSize + (forValue ifTrue: [1] ifFalse: [0]) " +1 for value (push nil) "! ! !MessageNode methodsFor: 'code generation'! sizeWhile: encoder value: forValue "L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only); justStmt, wholeLoop, justJump." | cond stmt stmtSize loopSize branchSize | cond _ receiver. stmt _ arguments at: 1. stmtSize _ (stmt sizeForEvaluatedEffect: encoder) + 2. branchSize _ self sizeBranchOn: (selector key == #whileFalse:) "Btp for whileFalse" dist: stmtSize. loopSize _ (cond sizeForEvaluatedValue: encoder) + branchSize + stmtSize. sizes _ Array with: stmtSize with: loopSize. ^ loopSize " +1 for value (push nil) " + (forValue ifTrue: [1] ifFalse: [0])! ! !MessageNode methodsFor: 'printing' stamp: 'RAA 2/15/2001 19:25'! macroPrinter special > 0 ifTrue: [^MacroPrinters at: special]. ^nil ! ! !MessageNode methodsFor: 'printing'! precedence ^precedence! ! !MessageNode methodsFor: 'printing' stamp: 'di 4/24/2000 10:32'! printCaseOn: aStream indent: level "receiver caseOf: {[key]->[value]. ...} otherwise: [otherwise]" | braceNode otherwise extra | braceNode _ arguments first. otherwise _ arguments last. (arguments size = 1 or: [otherwise isJustCaseError]) ifTrue: [otherwise _ nil]. receiver printOn: aStream indent: level precedence: 3. aStream dialect = #SQ00 ifTrue: [aStream nextPutAll: ' caseOf ('] ifFalse: [aStream nextPutAll: ' caseOf: ']. braceNode isVariableReference ifTrue: [braceNode printOn: aStream indent: level] ifFalse: [aStream nextPutAll: '{'; crtab: level + 1. braceNode casesForwardDo: [:keyNode :valueNode :last | keyNode printOn: aStream indent: level + 1. aStream nextPutAll: ' -> '. valueNode isComplex ifTrue: [aStream crtab: level + 2. extra _ 1] ifFalse: [extra _ 0]. valueNode printOn: aStream indent: level + 1 + extra. last ifTrue: [aStream nextPut: $}] ifFalse: [aStream nextPut: $.; crtab: level + 1]]]. aStream dialect = #SQ00 ifTrue: [aStream nextPutAll: ')']. otherwise isNil ifFalse: [aStream dialect = #SQ00 ifTrue: [aStream crtab: level + 1; nextPutAll: ' otherwise ('] ifFalse: [aStream crtab: level + 1; nextPutAll: ' otherwise: ']. otherwise isComplex ifTrue: [aStream crtab: level + 2. extra _ 1] ifFalse: [extra _ 0]. otherwise printOn: aStream indent: level + 1 + extra. aStream dialect = #SQ00 ifTrue: [aStream nextPutAll: ')']]! ! !MessageNode methodsFor: 'printing' stamp: 'di 5/1/2000 23:20'! printIfNil: aStream indent: level self printReceiver: receiver on: aStream indent: level. ^self printKeywords: selector key arguments: (Array with: arguments first) on: aStream indent: level! ! !MessageNode methodsFor: 'printing' stamp: 'di 5/1/2000 23:20'! printIfNilNotNil: aStream indent: level self printReceiver: receiver ifNilReceiver on: aStream indent: level. (arguments first isJust: NodeNil) ifTrue: [^ self printKeywords: #ifNotNil: arguments: { arguments second } on: aStream indent: level]. (arguments second isJust: NodeNil) ifTrue: [^ self printKeywords: #ifNil: arguments: { arguments first } on: aStream indent: level]. ^ self printKeywords: #ifNil:ifNotNil: arguments: arguments on: aStream indent: level! ! !MessageNode methodsFor: 'printing' stamp: 'RAA 2/16/2001 15:12'! printIfOn: aStream indent: level aStream dialect = #SQ00 ifTrue: ["Convert to if-then-else" (arguments last isJust: NodeNil) ifTrue: [aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: 'Test ']. self printParenReceiver: receiver on: aStream indent: level + 1. ^ self printKeywords: #Yes: arguments: (Array with: arguments first) on: aStream indent: level prefix: true]. (arguments last isJust: NodeFalse) ifTrue: [self printReceiver: receiver on: aStream indent: level. ^ self printKeywords: #and: arguments: (Array with: arguments first) on: aStream indent: level]. (arguments first isJust: NodeNil) ifTrue: [aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: 'Test ']. self printParenReceiver: receiver on: aStream indent: level + 1. ^ self printKeywords: #No: arguments: (Array with: arguments last) on: aStream indent: level prefix: true]. (arguments first isJust: NodeTrue) ifTrue: [self printReceiver: receiver on: aStream indent: level. ^ self printKeywords: #or: arguments: (Array with: arguments last) on: aStream indent: level]. aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: 'Test ']. self printParenReceiver: receiver on: aStream indent: level + 1. ^ self printKeywords: #Yes:No: arguments: arguments on: aStream indent: level prefix: true]. receiver ifNotNil: [ receiver printOn: aStream indent: level + 1 precedence: precedence. ]. (arguments last isJust: NodeNil) ifTrue: [^ self printKeywords: #ifTrue: arguments: (Array with: arguments first) on: aStream indent: level]. (arguments last isJust: NodeFalse) ifTrue: [^ self printKeywords: #and: arguments: (Array with: arguments first) on: aStream indent: level]. (arguments first isJust: NodeNil) ifTrue: [^ self printKeywords: #ifFalse: arguments: (Array with: arguments last) on: aStream indent: level]. (arguments first isJust: NodeTrue) ifTrue: [^ self printKeywords: #or: arguments: (Array with: arguments last) on: aStream indent: level]. self printKeywords: #ifTrue:ifFalse: arguments: arguments on: aStream indent: level! ! !MessageNode methodsFor: 'printing' stamp: 'di 6/11/2000 15:08'! printKeywords: key arguments: args on: aStream indent: level ^ self printKeywords: key arguments: args on: aStream indent: level prefix: false ! ! !MessageNode methodsFor: 'printing' stamp: 'di 6/11/2000 15:07'! printKeywords: key arguments: args on: aStream indent: level prefix: isPrefix | keywords indent noColons arg kwd hasBrackets doCrTab | args size = 0 ifTrue: [aStream space; nextPutAll: key. ^ self]. keywords _ key keywords. noColons _ aStream dialect = #SQ00 and: [keywords first endsWith: ':']. doCrTab _ args size > 2 or: [{receiver} , args inject: false into: [:was :thisArg | was or: [(thisArg isKindOf: BlockNode) or: [(thisArg isKindOf: MessageNode) and: [thisArg precedence >= 3]]]]]. 1 to: (args size min: keywords size) do: [:i | arg _ args at: i. kwd _ keywords at: i. doCrTab ifTrue: [aStream crtab: level+1. indent _ 1] "newline after big args" ifFalse: [aStream space. indent _ 0]. noColons ifTrue: [aStream withStyleFor: (isPrefix ifTrue: [#prefixKeyword] ifFalse: [#keyword]) do: [aStream nextPutAll: kwd allButLast; space]. hasBrackets _ (arg isKindOf: BlockNode) or: [arg isKindOf: BlockNode]. hasBrackets ifFalse: [aStream nextPutAll: '(']] ifFalse: [aStream nextPutAll: kwd; space]. arg printOn: aStream indent: level + 1 + indent precedence: (precedence = 2 ifTrue: [1] ifFalse: [precedence]). noColons ifTrue: [hasBrackets ifFalse: [aStream nextPutAll: ')']]]! ! !MessageNode methodsFor: 'printing' stamp: 'RAA 2/16/2001 15:12'! printOn: aStream indent: level | leadingKeyword | "may not need this check anymore - may be fixed by the #receiver: change" special ifNil: [^aStream nextPutAll: '** MessageNode with nil special **']. (special > 0) ifTrue: [self perform: self macroPrinter with: aStream with: level] ifFalse: [selector key first = $: ifTrue: [leadingKeyword _ selector key keywords first. aStream nextPutAll: leadingKeyword; space. self printReceiver: receiver on: aStream indent: level. self printKeywords: (selector key allButFirst: leadingKeyword size + 1) arguments: arguments on: aStream indent: level] ifFalse: [(aStream dialect = #SQ00 and: [selector key == #do:]) ifTrue: ["Add prefix keyword" aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: 'Repeat ']. self printParenReceiver: receiver on: aStream indent: level + 1. self printKeywords: selector key arguments: arguments on: aStream indent: level prefix: true] ifFalse: [self printReceiver: receiver on: aStream indent: level. self printKeywords: selector key arguments: arguments on: aStream indent: level]]]! ! !MessageNode methodsFor: 'printing' stamp: 'di 5/30/2000 23:17'! printOn: strm indent: level precedence: outerPrecedence | parenthesize | parenthesize _ precedence > outerPrecedence or: [outerPrecedence = 3 and: [precedence = 3 "both keywords"]]. parenthesize ifTrue: [strm nextPutAll: '('. self printOn: strm indent: level. strm nextPutAll: ')'] ifFalse: [self printOn: strm indent: level]! ! !MessageNode methodsFor: 'printing' stamp: 'di 6/7/2000 08:28'! printParenReceiver: rcvr on: aStream indent: level (rcvr isKindOf: BlockNode) ifTrue: [^ rcvr printOn: aStream indent: level]. aStream nextPutAll: '('. rcvr printOn: aStream indent: level. aStream nextPutAll: ')' ! ! !MessageNode methodsFor: 'printing' stamp: 'di 5/30/2000 23:06'! printReceiver: rcvr on: aStream indent: level rcvr ifNil: [^ self]. "Force parens around keyword receiver of kwd message" (precedence = 3 and: [aStream dialect = #SQ00]) ifTrue: [rcvr printOn: aStream indent: level precedence: precedence - 1] ifFalse: [rcvr printOn: aStream indent: level precedence: precedence] ! ! !MessageNode methodsFor: 'printing' stamp: 'di 6/11/2000 15:12'! printToDoOn: aStream indent: level | limitNode | aStream dialect = #SQ00 ifTrue: ["Add prefix keyword" aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: 'Repeat ']. self printParenReceiver: receiver on: aStream indent: level + 1] ifFalse: [self printReceiver: receiver on: aStream indent: level]. (arguments last == nil or: [(arguments last isMemberOf: AssignmentNode) not]) ifTrue: [limitNode _ arguments first] ifFalse: [limitNode _ arguments last value]. (selector key = #to:by:do: and: [(arguments at: 2) isConstantNumber and: [(arguments at: 2) key = 1]]) ifTrue: [self printKeywords: #to:do: arguments: (Array with: limitNode with: (arguments at: 3)) on: aStream indent: level prefix: true] ifFalse: [self printKeywords: selector key arguments: (Array with: limitNode) , arguments allButFirst on: aStream indent: level prefix: true]! ! !MessageNode methodsFor: 'printing' stamp: 'di 6/11/2000 15:12'! printWhileOn: aStream indent: level aStream dialect = #SQ00 ifTrue: ["Add prefix keyword" aStream withStyleFor: #prefixKeyword do: [aStream nextPutAll: (selector key == #whileTrue: ifTrue: ['While '] ifFalse: ['Until '])]. self printParenReceiver: receiver on: aStream indent: level + 1. self printKeywords: #do: arguments: arguments on: aStream indent: level prefix: true] ifFalse: [self printReceiver: receiver on: aStream indent: level. (arguments first isJust: NodeNil) ifTrue: [selector _ SelectorNode new key: (selector key == #whileTrue: ifTrue: [#whileTrue] ifFalse: [#whileFalse]) code: #macro. arguments _ Array new]. self printKeywords: selector key arguments: arguments on: aStream indent: level]! ! !MessageNode methodsFor: 'private' stamp: 'hg 10/2/2001 21:08'! checkBlock: node as: nodeName from: encoder node canBeSpecialArgument ifTrue: [^node isMemberOf: BlockNode]. ((node isKindOf: BlockNode) and: [node numberOfArguments > 0]) ifTrue: [^encoder notify: '<- ', nodeName , ' of ' , (MacroSelectors at: special) , ' must be a 0-argument block'] ifFalse: [^encoder notify: '<- ', nodeName , ' of ' , (MacroSelectors at: special) , ' must be a block or variable']! ! !MessageNode methodsFor: 'private' stamp: 'acg 1/28/2000 00:57'! ifNilReceiver ^receiver! ! !MessageNode methodsFor: 'private' stamp: 'tk 8/2/1999 18:40'! pvtCheckForPvtSelector: encoder "If the code being compiled is trying to send a private message (e.g. 'pvtCheckForPvtSelector:') to anyone other than self, then complain to encoder." selector isPvtSelector ifTrue: [receiver isSelfPseudoVariable ifFalse: [encoder notify: 'Private messages may only be sent to self']].! ! !MessageNode methodsFor: 'private'! receiver: rcvr arguments: args precedence: p receiver _ rcvr. arguments _ args. sizes _ Array new: arguments size. precedence _ p! ! !MessageNode methodsFor: 'private'! transformCase: encoder | caseNode | caseNode _ arguments first. (caseNode isKindOf: BraceNode) ifTrue: [^(caseNode blockAssociationCheck: encoder) and: [arguments size = 1 or: [self checkBlock: arguments last as: 'otherwise arg' from: encoder]]]. (caseNode canBeSpecialArgument and: [(caseNode isMemberOf: BlockNode) not]) ifTrue: [^false]. "caseOf: variable" ^encoder notify: 'caseOf: argument must be a brace construct or a variable'! ! !MessageNode methodsFor: 'equation translation'! arguments ^arguments! ! !MessageNode methodsFor: 'equation translation' stamp: 'tk 10/27/2000 15:11'! arguments: list arguments _ list! ! !MessageNode methodsFor: 'equation translation'! receiver ^receiver! ! !MessageNode methodsFor: 'equation translation' stamp: 'RAA 2/14/2001 14:07'! receiver: val "14 feb 2001 - removed return arrow" receiver _ val! ! !MessageNode methodsFor: 'equation translation'! selector ^selector! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MessageNode class instanceVariableNames: ''! !MessageNode class methodsFor: 'class initialization' stamp: 'acg 1/28/2000 21:58'! initialize "MessageNode initialize" MacroSelectors _ #(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue: and: or: whileFalse: whileTrue: whileFalse whileTrue to:do: to:by:do: caseOf: caseOf:otherwise: ifNil: ifNotNil: ifNil:ifNotNil: ifNotNil:ifNil:). MacroTransformers _ #(transformIfTrue: transformIfFalse: transformIfTrueIfFalse: transformIfFalseIfTrue: transformAnd: transformOr: transformWhile: transformWhile: transformWhile: transformWhile: transformToDo: transformToDo: transformCase: transformCase: transformIfNil: transformIfNil: transformIfNilIfNotNil: transformIfNotNilIfNil:). MacroEmitters _ #(emitIf:on:value: emitIf:on:value: emitIf:on:value: emitIf:on:value: emitIf:on:value: emitIf:on:value: emitWhile:on:value: emitWhile:on:value: emitWhile:on:value: emitWhile:on:value: emitToDo:on:value: emitToDo:on:value: emitCase:on:value: emitCase:on:value: emitIfNil:on:value: emitIfNil:on:value: emitIf:on:value: emitIf:on:value:). MacroSizers _ #(sizeIf:value: sizeIf:value: sizeIf:value: sizeIf:value: sizeIf:value: sizeIf:value: sizeWhile:value: sizeWhile:value: sizeWhile:value: sizeWhile:value: sizeToDo:value: sizeToDo:value: sizeCase:value: sizeCase:value: sizeIfNil:value: sizeIfNil:value: sizeIf:value: sizeIf:value: ). MacroPrinters _ #(printIfOn:indent: printIfOn:indent: printIfOn:indent: printIfOn:indent: printIfOn:indent: printIfOn:indent: printWhileOn:indent: printWhileOn:indent: printWhileOn:indent: printWhileOn:indent: printToDoOn:indent: printToDoOn:indent: printCaseOn:indent: printCaseOn:indent: printIfNil:indent: printIfNil:indent: printIfNilNotNil:indent: printIfNilNotNil:indent:)! ! Error subclass: #MessageNotUnderstood instanceVariableNames: 'message receiver' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !MessageNotUnderstood commentStamp: '<historical>' prior: 0! This exception is provided to support Object>>doesNotUnderstand:.! !MessageNotUnderstood methodsFor: 'exceptionBuilder' stamp: 'pnm 8/16/2000 15:03'! message: aMessage message := aMessage! ! !MessageNotUnderstood methodsFor: 'exceptionBuilder' stamp: 'ab 8/22/2003 11:56'! messageText "Return an exception's message text." ^messageText == nil ifTrue: [message == nil ifTrue: [super messageText] ifFalse: [message lookupClass printString, '>>', message selector asString]] ifFalse: [messageText]! ! !MessageNotUnderstood methodsFor: 'exceptionBuilder' stamp: 'ajh 10/9/2001 16:38'! receiver: obj receiver _ obj! ! !MessageNotUnderstood methodsFor: 'exceptionDescription' stamp: 'tfei 6/4/1999 18:30'! isResumable "Determine whether an exception is resumable." ^true! ! !MessageNotUnderstood methodsFor: 'exceptionDescription' stamp: 'ajh 10/9/2001 16:39'! receiver "Answer the receiver that did not understand the message" ^ receiver! ! Browser subclass: #MessageSet instanceVariableNames: 'messageList autoSelectString growable' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !MessageSet commentStamp: '<historical>' prior: 0! 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.! !MessageSet methodsFor: 'message list' stamp: 'BG 11/1/2003 14:51'! addExtraShiftedItemsTo: aMenu "The shifted selector-list menu is being built. Add items specific to MessageSet" self growable ifTrue: [aMenu addList: #( - ('remove from this browser' removeMessageFromBrowser) )]. aMenu add: 'sort by date' action: #sortByDate! ! !MessageSet methodsFor: 'message list' stamp: 'tk 5/1/2001 18:14'! addItem: classAndMethod "Append a classAndMethod string to the list. Select the new item." "Do some checks on the input?" self okToChange ifFalse: [^ self]. messageList add: classAndMethod. self changed: #messageList. self messageListIndex: messageList size.! ! !MessageSet methodsFor: 'message list' stamp: 'sw 1/28/2001 20:56'! growable "Answer whether the receiver is capable of growing/shrinking dynamically" ^ growable ~~ false! ! !MessageSet methodsFor: 'message list' stamp: 'sw 12/6/2000 07:12'! growable: aBoolean "Give or take away the growable trait; when a message set is growable, methods submitted within it will be added to its message list" growable _ aBoolean! ! !MessageSet methodsFor: 'message list'! messageList "Answer the current list of messages." ^messageList! ! !MessageSet methodsFor: 'message list' stamp: 'nk 2/14/2004 15:10'! messageListIndex: anInteger "Set the index of the selected item to be anInteger." messageListIndex _ anInteger. contents _ messageListIndex ~= 0 ifTrue: [self selectedMessage] ifFalse: ['']. self changed: #messageListIndex. "update my selection" self editSelection: #editMessage. self contentsChanged. (messageListIndex ~= 0 and: [autoSelectString notNil]) ifTrue: [self changed: #autoSelect]. self decorateButtons ! ! !MessageSet methodsFor: 'message list' stamp: 'sbw 12/30/1999 17:19'! optionalButtonHeight ^ 15! ! !MessageSet methodsFor: 'message list' stamp: 'sma 3/3/2000 11:17'! selectedMessageName "Answer the name of the currently selected message." "wod 6/16/1998: answer nil if none are selected." messageListIndex = 0 ifTrue: [^ nil]. ^ self setClassAndSelectorIn: [:class :selector | ^ selector]! ! !MessageSet methodsFor: 'message list' stamp: 'sw 8/1/2002 18:18'! sortByDate "Sort the message-list by date of time-stamp" | assocs aCompiledMethod aDate inOrder | assocs _ messageList collect: [:aRef | aDate _ aRef methodSymbol == #Comment ifTrue: [aRef actualClass organization dateCommentLastSubmitted] ifFalse: [aCompiledMethod _ aRef actualClass compiledMethodAt: aRef methodSymbol ifAbsent: [nil]. aCompiledMethod ifNotNil: [aCompiledMethod dateMethodLastSubmitted]]. aRef -> (aDate ifNil: [Date fromString: '01/01/1996'])]. "The dawn of Squeak history" inOrder _ assocs asSortedCollection: [:a :b | a value < b value]. messageList _ inOrder asArray collect: [:assoc | assoc key]. self changed: #messageList! ! !MessageSet methodsFor: 'message functions' stamp: 'sw 12/11/2000 15:51'! deleteFromMessageList: aMessage "Delete the given message from the receiver's message list" messageList _ messageList copyWithout: aMessage! ! !MessageSet methodsFor: 'message functions' stamp: 'sw 2/24/1999 18:31'! methodCategoryChanged self changed: #annotation! ! !MessageSet methodsFor: 'message functions' stamp: 'sw 12/1/2000 11:54'! reformulateList "The receiver's messageList has been changed; rebuild it" super reformulateList. self initializeMessageList: messageList. self changed: #messageList. self changed: #messageListIndex. self contentsChanged ! ! !MessageSet methodsFor: 'message functions' stamp: 'nk 6/26/2003 21:44'! removeMessage "Remove the selected message from the system. 1/15/96 sw" | messageName confirmation | messageListIndex = 0 ifTrue: [^ self]. self okToChange ifFalse: [^ self]. messageName _ self selectedMessageName. confirmation _ self systemNavigation confirmRemovalOf: messageName on: self selectedClassOrMetaClass. confirmation == 3 ifTrue: [^ self]. self selectedClassOrMetaClass removeSelector: messageName. self deleteFromMessageList: self selection. self reformulateList. confirmation == 2 ifTrue: [self systemNavigation browseAllCallsOn: messageName]! ! !MessageSet methodsFor: 'message functions' stamp: 'sw 1/12/2001 00:19'! removeMessageFromBrowser "Remove the selected message from the browser." messageListIndex = 0 ifTrue: [^ self]. self deleteFromMessageList: self selection. self reformulateList. self adjustWindowTitleAfterFiltering ! ! !MessageSet methodsFor: 'class list'! metaClassIndicated "Answer the boolean flag that indicates whether this is a class method." ^ self selectedClassOrMetaClass isMeta! ! !MessageSet methodsFor: 'class list'! selectedClass "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" | aClass | ^ (aClass _ self selectedClassOrMetaClass) == nil ifTrue: [nil] ifFalse: [aClass theNonMetaClass]! ! !MessageSet methodsFor: 'class list' stamp: 'tk 4/4/98 18:50'! selectedClassName "Answer the name of class of the currently selected message. Answer nil if no selection exists." | cls | (cls _ self selectedClass) ifNil: [^ nil]. ^ cls name! ! !MessageSet methodsFor: 'class list'! selectedClassOrMetaClass "Answer the currently selected class (or metaclass)." messageListIndex = 0 ifTrue: [^nil]. self setClassAndSelectorIn: [:c :s | ^c]! ! !MessageSet methodsFor: 'class list'! selectedMessageCategoryName "Answer the name of the selected message category or nil." messageListIndex = 0 ifTrue: [^ nil]. ^ self selectedClassOrMetaClass organization categoryOfElement: self selectedMessageName! ! !MessageSet methodsFor: 'contents' stamp: 'di 10/1/2001 22:26'! contents "Answer the contents of the receiver" ^ contents == nil ifTrue: [currentCompiledMethod _ nil. ''] ifFalse: [messageListIndex = 0 ifTrue: [currentCompiledMethod _ nil. contents] ifFalse: [self showingByteCodes ifTrue: [self selectedBytecodes] ifFalse: [self selectedMessage]]]! ! !MessageSet methodsFor: 'contents' stamp: 'nk 6/19/2004 16:47'! selectedMessage "Answer the source method for the currently selected message." | source | self setClassAndSelectorIn: [:class :selector | class ifNil: [^ 'Class vanished']. selector first isUppercase ifTrue: [selector == #Comment ifTrue: [currentCompiledMethod _ class organization commentRemoteStr. ^ class comment]. selector == #Definition ifTrue: [^ class definitionST80: Preferences printAlternateSyntax not]. selector == #Hierarchy ifTrue: [^ class printHierarchy]]. source _ class sourceMethodAt: selector ifAbsent: [currentCompiledMethod _ nil. ^ 'Missing']. self showingDecompile ifTrue: [^ self decompiledSourceIntoContentsWithTempNames: Sensor leftShiftDown not ]. currentCompiledMethod _ class compiledMethodAt: selector ifAbsent: [nil]. self showingDocumentation ifTrue: [^ self commentContents]. source _ self sourceStringPrettifiedAndDiffed. ^ source asText makeSelectorBoldIn: class]! ! !MessageSet methodsFor: 'contents' stamp: 'sw 2/14/2001 15:25'! setContentsToForceRefetch "Set the receiver's contents such that on the next update the contents will be formulated afresh. This is a critical and obscure difference between Browsers on the one hand and MessageSets on the other, and has over the years been the source of much confusion and much difficulty. By centralizing the different handling here, we don't need so many idiosyncratic overrides in MessageSet any more" contents _ ''! ! !MessageSet methodsFor: 'private' stamp: 'sw 1/11/2001 09:16'! adjustWindowTitleAfterFiltering "Set the title of the receiver's window, if any, to reflect the just-completed filtering" | aWindow existingLabel newLabel | (aWindow _ self containingWindow) ifNil: [^ self]. (existingLabel _ aWindow label) isEmptyOrNil ifTrue: [^ self]. (((existingLabel size < 3) or: [existingLabel last ~~ $]]) or: [(existingLabel at: (existingLabel size - 1)) isDigit not]) ifTrue: [^ self]. existingLabel size to: 1 by: -1 do: [:anIndex | ((existingLabel at: anIndex) == $[) ifTrue: [newLabel _ (existingLabel copyFrom: 1 to: anIndex), 'Filtered: ', messageList size printString, ']'. ^ aWindow setLabel: newLabel]] ! ! !MessageSet methodsFor: 'private'! autoSelectString "Return the string to be highlighted when making new selections" ^ autoSelectString! ! !MessageSet methodsFor: 'private'! autoSelectString: aString "Set the string to be highlighted when making new selections" autoSelectString _ aString! ! !MessageSet methodsFor: 'private' stamp: 'sw 7/31/2002 12:58'! contents: aString notifying: aController "Compile the code in aString. Notify aController of any syntax errors. Answer false if the compilation fails. Otherwise, if the compilation created a new method, deselect the current selection. Then answer true." | category selector class oldSelector | self okayToAccept ifFalse: [^ false]. self setClassAndSelectorIn: [:c :os | class _ c. oldSelector _ os]. class ifNil: [^ false]. (oldSelector ~~ nil and: [oldSelector first isUppercase]) ifTrue: [oldSelector = #Comment ifTrue: [class comment: aString stamp: Utilities changeStamp. self changed: #annotation. self clearUserEditFlag. ^ false]. oldSelector = #Definition ifTrue: ["self defineClass: aString notifying: aController." class subclassDefinerClass evaluate: aString notifying: aController logged: true. self clearUserEditFlag. ^ false]. oldSelector = #Hierarchy ifTrue: [self inform: 'To change the hierarchy, edit the class definitions'. ^ false]]. "Normal method accept" category _ class organization categoryOfElement: oldSelector. selector _ class compile: aString classified: category notifying: aController. selector == nil ifTrue: [^ false]. self noteAcceptanceOfCodeFor: selector. selector == oldSelector ifFalse: [self reformulateListNoting: selector]. contents _ aString copy. self changed: #annotation. ^ true! ! !MessageSet methodsFor: 'private' stamp: 'ff 12/13/2003 02:38'! initializeMessageList: anArray | s | messageList _ OrderedCollection new. anArray do: [ :each | MessageSet parse: each toClassAndSelector: [ :class :sel | class ifNotNil: [ s _ class name , ' ' , sel , ' {' , ((class organization categoryOfElement: sel) ifNil: ['']) , '}'. messageList add: ( MethodReference new setClass: class methodSymbol: sel stringVersion: s ) ] ] ]. messageListIndex _ messageList isEmpty ifTrue: [0 ] ifFalse: [1]. contents _ ''! ! !MessageSet methodsFor: 'private' stamp: 'sw 6/13/2001 00:59'! openAsMorphNamed: labelString inWorld: aWorld "Open the receiver in a morphic window in the given world" (self inMorphicWindowLabeled: labelString) openInWorld: aWorld! ! !MessageSet methodsFor: 'private' stamp: 'sw 12/28/2000 14:28'! selection "Answer the item in the list that is currently selected, or nil if no selection is present" ^ messageList at: messageListIndex ifAbsent: [nil]! ! !MessageSet methodsFor: 'private' stamp: 'RAA 5/29/2001 10:12'! setClassAndSelectorIn: csBlock | sel | "Decode strings of the form <className> [class] <selectorName>." self flag: #mref. "compatibility with pre-MethodReference lists" sel _ self selection. ^(sel isKindOf: MethodReference) ifTrue: [ sel setClassAndSelectorIn: csBlock ] ifFalse: [ MessageSet parse: sel toClassAndSelector: csBlock ]! ! !MessageSet methodsFor: 'private' stamp: 'sw 1/11/2001 09:18'! setFilteredList: newList "Establish newList as the new list if appropriate, and adjust the window title accordingly; if the new list is of the same size as the old, warn and do nothing" newList size == 0 ifTrue: [^ self inform: 'Nothing would be left in the list if you did that']. newList size == messageList size ifTrue: [^ self inform: 'That leaves the list unchanged']. self initializeMessageList: newList. self adjustWindowTitleAfterFiltering! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 1/19/2001 16:47'! augmentMessageList "Allow the user to add to the list of messages." self notYetImplemented ! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 1/11/2001 09:33'! filterFrom: aBlock "Filter the receiver's list down to only those items that satisfy aBlock, which takes a class an a selector as its arguments." | newList | newList _ messageList select: [:anElement | self class parse: anElement toClassAndSelector: aBlock]. self setFilteredList: newList! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 12:55'! filterToAnyChangeSet "Filter down only to messages present in ANY change set" self filterFrom: [:aClass :aSelector | ChangeSorter doesAnyChangeSetHaveClass: aClass andSelector: aSelector] ! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/10/2001 14:45'! filterToCommentedMethods "Filter the receiver's list down to only those items which have comments" self filterFrom: [:aClass :aSelector | (aClass selectors includes: aSelector) and: [(aClass firstPrecodeCommentFor: aSelector) isEmptyOrNil not]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 2/14/2001 18:30'! filterToCurrentAuthor "Filter down only to messages with my initials as most recent author" | myInitials aMethod aTimeStamp | (myInitials _ Utilities authorInitialsPerSe) ifNil: [^ self inform: 'No author initials set in this image']. self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [aMethod _ aClass compiledMethodAt: aSelector ifAbsent: [nil]. aMethod notNil and: [(aTimeStamp _ Utilities timeStampForMethod: aMethod) notNil and: [aTimeStamp beginsWith: myInitials]]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sd 5/23/2003 14:38'! filterToCurrentChangeSet "Filter the receiver's list down to only those items in the current change set" self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [(ChangeSet current atSelector: aSelector class: aClass) ~~ #none]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/10/2001 14:33'! filterToImplementorsOf "Filter the receiver's list down to only those items with a given selector" | aFragment inputWithBlanksTrimmed | aFragment _ FillInTheBlank request: 'type selector:' initialAnswer: ''. aFragment isEmptyOrNil ifTrue: [^ self]. inputWithBlanksTrimmed _ aFragment withBlanksTrimmed. Symbol hasInterned: inputWithBlanksTrimmed ifTrue: [:aSymbol | self filterFrom: [:aClass :aSelector | aSelector == aSymbol]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 15:14'! filterToMessagesInChangesFile "Filter down only to messages whose source code risides in the Changes file. This allows one to ignore long-standing methods that live in the .sources file." | cm | self filterFrom: [:aClass :aSelector | aClass notNil and: [aSelector notNil and: [(self class isPseudoSelector: aSelector) not and: [(cm _ aClass compiledMethodAt: aSelector ifAbsent: [nil]) notNil and: [cm fileIndex ~~ 1]]]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 15:15'! filterToMessagesInSourcesFile "Filter down only to messages whose source code resides in the .sources file." | cm | self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [(self class isPseudoSelector: aSelector) not and: [(cm _ aClass compiledMethodAt: aSelector ifAbsent: [nil]) notNil and: [cm fileIndex == 1]]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 14:10'! filterToMessagesThat "Allow the user to type in a block which will be" | reply | reply _ FillInTheBlank multiLineRequest: 'Type your block here' centerAt: Sensor cursorPoint initialAnswer: '[:aClass :aSelector | ]' answerHeight: 200. reply isEmptyOrNil ifTrue: [^ self]. self filterFrom: (Compiler evaluate: reply) ! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 2/13/2001 12:02'! filterToMessagesWithHardenedClasses "Filter the receiver's list down to only those items representing methods of hardened classes, as opposed to uniclasses" self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [aClass isUniClass not]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/12/2001 22:25'! filterToMessagesWithPriorVersions "Filter down only to messages which have at least one prior version" self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [(self class isPseudoSelector: aSelector) not and: [(VersionsBrowser versionCountForSelector: aSelector class: aClass) > 1]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 15:12'! filterToMessagesWithoutPriorVersions "Filter down only to messages which have no prior version stored" self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [(self class isPseudoSelector: aSelector) not and: [(VersionsBrowser versionCountForSelector: aSelector class: aClass) <= 1]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 6/6/2001 13:07'! filterToNotAnyChangeSet "Filter down only to messages present in NO change set" self filterFrom: [:aClass :aSelector | (ChangeSorter doesAnyChangeSetHaveClass: aClass andSelector: aSelector) not] ! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 2/14/2001 18:24'! filterToNotCurrentAuthor "Filter down only to messages not stamped with my initials" | myInitials aMethod aTimeStamp | (myInitials _ Utilities authorInitialsPerSe) ifNil: [^ self inform: 'No author initials set in this image']. self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [aMethod _ aClass compiledMethodAt: aSelector ifAbsent: [nil]. aMethod notNil and: [(aTimeStamp _ Utilities timeStampForMethod: aMethod) isNil or: [(aTimeStamp beginsWith: myInitials) not]]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sd 5/23/2003 14:38'! filterToNotCurrentChangeSet "Filter the receiver's list down to only those items not in the current change set" self filterFrom: [:aClass :aSelector | (aClass notNil and: [aSelector notNil]) and: [(ChangeSet current atSelector: aSelector class: aClass) == #none]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/10/2001 14:34'! filterToNotImplementorsOf "Filter the receiver's list down to only those items whose selector is NOT one solicited from the user." | aFragment inputWithBlanksTrimmed | aFragment _ FillInTheBlank request: 'type selector: ' initialAnswer: ''. aFragment isEmptyOrNil ifTrue: [^ self]. inputWithBlanksTrimmed _ aFragment withBlanksTrimmed. Symbol hasInterned: inputWithBlanksTrimmed ifTrue: [:aSymbol | self filterFrom: [:aClass :aSelector | aSelector ~~ aSymbol]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/12/2001 13:11'! filterToNotSendersOf "Filter the receiver's list down to only those items which do not send a given selector" | aFragment inputWithBlanksTrimmed aMethod | aFragment _ FillInTheBlank request: 'type selector:' initialAnswer: ''. aFragment isEmptyOrNil ifTrue: [^ self]. inputWithBlanksTrimmed _ aFragment withBlanksTrimmed. Symbol hasInterned: inputWithBlanksTrimmed ifTrue: [:aSymbol | self filterFrom: [:aClass :aSelector | (aMethod _ aClass compiledMethodAt: aSelector) isNil or: [(aMethod hasLiteralThorough: aSymbol) not]]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 1/19/2001 15:58'! filterToSendersOf "Filter the receiver's list down to only those items which send a given selector" | aFragment inputWithBlanksTrimmed aMethod | aFragment _ FillInTheBlank request: 'type selector:' initialAnswer: ''. aFragment isEmptyOrNil ifTrue: [^ self]. inputWithBlanksTrimmed _ aFragment withBlanksTrimmed. Symbol hasInterned: inputWithBlanksTrimmed ifTrue: [:aSymbol | self filterFrom: [:aClass :aSelector | (aMethod _ aClass compiledMethodAt: aSelector) notNil and: [aMethod hasLiteralThorough: aSymbol]]] ! ! !MessageSet methodsFor: 'filtering' stamp: 'sw 8/10/2001 14:43'! filterToUncommentedMethods "Filter the receiver's list down to only those items which lack comments" self filterFrom: [:aClass :aSelector | (aClass selectors includes: aSelector) and: [(aClass firstPrecodeCommentFor: aSelector) isEmptyOrNil]]! ! !MessageSet methodsFor: 'filtering' stamp: 'sd 4/29/2003 12:24'! filterToUnsentMessages "Filter the receiver's list down to only those items which have no senders" self filterFrom: [:aClass :aSelector | (self systemNavigation allCallsOn: aSelector) isEmpty]! ! !MessageSet methodsFor: 'message category functions' stamp: 'sw 10/8/2001 14:10'! canShowMultipleMessageCategories "Answer whether the receiver is capable of showing multiple message categories" ^ false! ! !MessageSet methodsFor: 'metaclass' stamp: 'sw 8/15/2002 22:23'! classCommentIndicated "Answer true iff we're viewing the class comment." ^ self selectedMessageName == #Comment! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MessageSet class instanceVariableNames: ''! !MessageSet class methodsFor: 'instance creation'! messageList: anArray "Answer an instance of me with message list anArray." ^self new initializeMessageList: anArray! ! !MessageSet class methodsFor: 'instance creation' stamp: 'BG 10/29/2003 08:40'! open: aMessageSet name: aString "Create a standard system view for the messageSet, aMessageSet, whose label is aString." | topView aListView aBrowserCodeView aTextView underPane y buttonsView winWidth | winWidth _ 200. topView _ (StandardSystemView new) model: aMessageSet. topView label: aString. topView minimumSize: winWidth @ 120. topView borderWidth: 1. aListView _ PluggableListView on: aMessageSet list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. aListView menuTitleSelector: #messageListSelectorTitle. aListView window: (0 @ 0 extent: winWidth @ 100). topView addSubView: aListView. aMessageSet wantsAnnotationPane ifTrue: [aTextView _ PluggableTextView on: aMessageSet text: #annotation accept: nil readSelection: nil menu: nil. aTextView window: (0 @ 0 extent: winWidth @ 24). topView addSubView: aTextView below: aListView. underPane _ aTextView. y _ 300 - 24. aTextView askBeforeDiscardingEdits: false] ifFalse: [underPane _ aListView. y _ 300]. aMessageSet wantsOptionalButtons ifTrue: [buttonsView _ aMessageSet buildOptionalButtonsView. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. y _ y - aMessageSet optionalButtonHeight]. aBrowserCodeView _ PluggableTextView on: aMessageSet text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. aBrowserCodeView window: (0 @ 0 extent: winWidth @ y). topView addSubView: aBrowserCodeView below: underPane. topView setUpdatablePanesFrom: #(messageList). topView controller open! ! !MessageSet class methodsFor: 'instance creation'! openMessageList: anArray name: aString "Create a standard system view for the message set on the list, anArray. The label of the view is aString." self open: (self messageList: anArray) name: aString! ! !MessageSet class methodsFor: 'instance creation' stamp: 'ssa 9/3/2008 11:07'! openMessageList: messageList name: labelString autoSelect: autoSelectString "Open a system view for a MessageSet on messageList. 1/24/96 sw: the there-are-no msg now supplied by my sender" | messageSet | messageSet _ self messageList: messageList. messageSet autoSelectString: autoSelectString. ScheduledControllers scheduleActive: (self open: messageSet name: labelString)! ! !MessageSet class methodsFor: 'utilities' stamp: 'RAA 5/29/2001 10:19'! extantMethodsIn: aListOfMethodRefs "Answer the subset of the incoming list consisting only of those message markers that refer to methods actually in the current image" self flag: #mref. "may be removed in second round" ^ aListOfMethodRefs select: [:aToken | self parse: aToken toClassAndSelector: [ :aClass :aSelector | aClass notNil and: [aClass includesSelector: aSelector] ] ]! ! !MessageSet class methodsFor: 'utilities' stamp: 'sw 6/6/2001 15:09'! isPseudoSelector: aSelector "Answer whether the given selector is a special marker" ^ #(Comment Definition Hierarchy) includes: aSelector! ! !MessageSet class methodsFor: 'utilities' stamp: 'bkv 4/2/2003 11:33'! parse: methodRef toClassAndSelector: csBlock "Decode strings of the form <className> [class] <selectorName>." | tuple cl | self flag: #mref. "compatibility with pre-MethodReference lists" methodRef ifNil: [^ csBlock value: nil value: nil]. (methodRef isKindOf: MethodReference) ifTrue: [ ^methodRef setClassAndSelectorIn: csBlock ]. methodRef isEmpty ifTrue: [^ csBlock value: nil value: nil]. tuple _ methodRef asString findTokens: ' .'. cl _ Smalltalk atOrBelow: tuple first asSymbol ifAbsent: [^ csBlock value: nil value: nil]. (tuple size = 2 or: [tuple size > 2 and: [(tuple at: 2) ~= 'class']]) ifTrue: [^ csBlock value: cl value: (tuple at: 2) asSymbol] ifFalse: [^ csBlock value: cl class value: (tuple at: 3) asSymbol]! ! Magnitude subclass: #MessageTally instanceVariableNames: 'class method tally receivers senders time gcStats maxClassNameSize maxClassPlusSelectorSize maxTabs' classVariableNames: 'DefaultPollPeriod ObservedProcess Timer' poolDictionaries: '' category: 'Tools-Debugger'! !MessageTally commentStamp: 'nk 3/8/2004 12:43' prior: 0! My instances observe and report the amount of time spent in methods. NOTE: a higher-level user interface (combining the MessageTally result tree with a method browser) is available from TimeProfileBrowser. MessageTally provides two different strategies available for profiling: * spyOn: and friends use a high-priority Process to interrupt the block or process being spied on at periodic intervals. The interrupted call stack is then examined for caller information. * tallySends: and friends use the interpreter simulator to run the block, recording every method call. The two give you different results: * spyOn: gives you a view of where the time is being spent in your program, at least on a rough statistical level (assuming you've run the block for long enough and have a high enough poll rate). If you're trying to optimize your code, start here and optimize the methods where most of the time is being spent first. * tallySends: gives you accurate counts of how many times methods get called, and by exactly which route. If you're debugging, or trying to figure out if a given method is getting called too many times, this is your tool. You can change the printing format (that is, the whitespace and string compression) by using these instance methods: maxClassNameSize: maxClassPlusSelectorSize: maxTabs: You can change the default polling period (initially set to 1) by calling MessageTally defaultPollPeriod: numberOfMilliseconds Q: How do you interpret MessageTally>>tallySends A: The methods #tallySends and #spyOn: measure two very different quantities, but broken down in the same who-called-who format. #spyOn: is approximate, but more indicative of real time spent, whereas #tallySends is exact and a precise record of how many times each method got executed.! !MessageTally methodsFor: 'comparing'! < aMessageTally "Refer to the comment in Magnitude|<." ^tally > aMessageTally tally! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:05'! = aMessageTally self species == aMessageTally species ifFalse: [^ false]. ^ aMessageTally method == method! ! !MessageTally methodsFor: 'comparing'! > aMessageTally "Refer to the comment in Magnitude|>." ^tally < aMessageTally tally! ! !MessageTally methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^method asOop! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:04'! species ^MessageTally! ! !MessageTally methodsFor: 'initialize-release'! close (Timer isMemberOf: Process) ifTrue: [Timer terminate]. Timer _ ObservedProcess _ nil. class _ method _ tally _ receivers _ nil! ! !MessageTally methodsFor: 'initialize-release' stamp: 'nk 3/8/2004 12:29'! initialize maxClassNameSize _ self class defaultMaxClassNameSize. maxClassPlusSelectorSize _ self class defaultMaxClassPlusSelectorSize. maxTabs _ self class defaultMaxTabs.! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:14'! printOn: aStream | aSelector className aClass | (class isNil or: [method isNil]) ifTrue: [^super printOn: aStream]. aSelector := class selectorAtMethod: method setClass: [:c | aClass := c]. className := aClass name contractTo: self maxClassNameSize. aStream nextPutAll: className; nextPutAll: ' >> '; nextPutAll: (aSelector contractTo: self maxClassPlusSelectorSize - className size)! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassNameSize ^maxClassNameSize! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassPlusSelectorSize ^maxClassPlusSelectorSize! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 12:06'! tally "Answer the receiver's number of tally." ^tally! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 11:47'! time "Answer the receiver's run time." ^time! ! !MessageTally methodsFor: 'private'! method ^method! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MessageTally class instanceVariableNames: ''! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassNameSize "Return the default maximum width of the class name alone" ^30! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassPlusSelectorSize "Return the default maximum width of the class plus selector together (not counting the '>>')" ^60! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:26'! defaultMaxTabs "Return the default number of tabs after which leading white space is compressed" ^18! ! ClassDescription subclass: #Metaclass instanceVariableNames: 'thisClass' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Classes'! !Metaclass commentStamp: '<historical>' prior: 0! 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. [Subtle] In general, the superclass hierarchy for metaclasses parallels that for classes. Thus, Integer superclass == Number, and Integer class superclass == Number class. 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, Object superclass == nil, and Object class superclass == Class. [Subtle detail] A class is know by name to an environment. Typically this is the SystemDictionary named Smalltalk. If we ever make lightweight classes that are not in Smalltalk, they must be in some environment. Specifically, the code that sets 'wasPresent' in name:inEnvironment:subclassOf:instanceVariableNames:variable:words:pointers:classVariableNames:poolDictionaries:category:comment:changed: must continue to work.! !Metaclass methodsFor: 'initialize-release' stamp: 'ar 7/13/1999 04:52'! adoptInstance: oldInstance from: oldMetaClass "Recreate any existing instances of the argument, oldClass, as instances of the receiver, which is a newly changed class. Permute variables as necessary." thisClass class == self ifTrue:[^self error:'Metaclasses have only one instance']. oldMetaClass isMeta ifFalse:[^self error:'Argument must be Metaclass']. oldInstance class == oldMetaClass ifFalse:[^self error:'Not the class of argument']. ^thisClass _ self newInstanceFrom: oldInstance variable: self isVariable size: self instSize map: (self instVarMappingFrom: oldMetaClass)! ! !Metaclass methodsFor: 'initialize-release' stamp: 'ar 7/15/1999 18:56'! instanceVariableNames: instVarString "Declare additional named variables for my instance." ^(ClassBuilder new) class: self instanceVariableNames: instVarString! ! !Metaclass methodsFor: 'accessing' stamp: 'ar 7/11/1999 08:14'! allInstances thisClass class == self ifTrue:[^Array with: thisClass]. ^super allInstances! ! !Metaclass methodsFor: 'accessing' stamp: 'ar 7/11/1999 05:19'! environment ^thisClass environment! ! !Metaclass methodsFor: 'accessing'! isMeta ^ true! ! !Metaclass methodsFor: 'accessing' stamp: 'tk 6/17/1998 09:48'! isSystemDefined "Answer false if I am a UniClass (an instance-specific lightweight class)" ^ true! ! !Metaclass methodsFor: 'accessing'! name "Answer a String that is the name of the receiver, either 'Metaclass' or the name of the receiver's class followed by ' class'." thisClass == nil ifTrue: [^'a Metaclass'] ifFalse: [^thisClass name , ' class']! ! !Metaclass methodsFor: 'accessing'! soleInstance "The receiver has only one instance. Answer it." ^thisClass! ! !Metaclass methodsFor: 'accessing'! theNonMetaClass "Sent to a class or metaclass, always return the class" ^thisClass! ! !Metaclass methodsFor: 'copying'! copy "Make a copy of the receiver without a list of subclasses. Share the reference to the sole instance." | copy t | t _ thisClass. thisClass _ nil. copy _ super copy. thisClass _ t. ^copy! ! !Metaclass methodsFor: 'copying' stamp: 'tk 8/19/1998 16:16'! veryDeepCopyWith: deepCopier "Return self. Must be created, not copied. Do not record me."! ! !Metaclass methodsFor: 'instance creation' stamp: 'nk 11/9/2003 10:00'! new "The receiver can only have one instance. Create it or complain that one already exists." thisClass class ~~ self ifTrue: [^thisClass _ self basicNew] ifFalse: [self error: 'A Metaclass should only have one instance!!']! ! !Metaclass methodsFor: 'instance variables'! addInstVarName: aString "Add the argument, aString, as one of the receiver's instance variables." | fullString | fullString _ aString. self instVarNames do: [:aString2 | fullString _ aString2 , ' ' , fullString]. self instanceVariableNames: fullString! ! !Metaclass methodsFor: 'pool variables'! classPool "Answer the dictionary of class variables." ^thisClass classPool! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 9/19/2002 23:44'! addObsoleteSubclass: aClass "Do nothing."! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 7/11/1999 15:43'! addSubclass: aClass "Do nothing."! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 9/19/2002 23:44'! obsoleteSubclasses "Answer the receiver's subclasses." thisClass == nil ifTrue:[^#()]. ^thisClass obsoleteSubclasses select:[:aSubclass| aSubclass isMeta not] thenCollect:[:aSubclass| aSubclass class] "Metaclass allInstancesDo: [:m | Compiler evaluate: 'subclasses_nil' for: m logged: false]"! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 9/19/2002 23:44'! removeObsoleteSubclass: aClass "Do nothing."! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 7/11/1999 15:43'! removeSubclass: aClass "Do nothing."! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 7/14/1999 11:19'! subclasses "Answer the receiver's subclasses." thisClass == nil ifTrue:[^#()]. ^thisClass subclasses select:[:aSubclass| aSubclass isMeta not] thenCollect:[:aSubclass| aSubclass class] "Metaclass allInstancesDo: [:m | Compiler evaluate: 'subclasses_nil' for: m logged: false]"! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'ar 7/9/1999 14:11'! subclassesDo: aBlock "Evaluate aBlock for each of the receiver's immediate subclasses." thisClass subclassesDo:[:aSubclass| "The following test is for Class class which has to exclude the Metaclasses being subclasses of Class." aSubclass isMeta ifFalse:[aBlock value: aSubclass class]].! ! !Metaclass methodsFor: 'class hierarchy' stamp: 'tk 8/18/1999 17:37'! subclassesDoGently: aBlock "Evaluate aBlock for each of the receiver's immediate subclasses." thisClass subclassesDo: [:aSubclass | "The following test is for Class class which has to exclude the Metaclasses being subclasses of Class." aSubclass isInMemory ifTrue: [ aSubclass isMeta ifFalse: [aBlock value: aSubclass class]]].! ! !Metaclass methodsFor: 'compiling'! acceptsLoggingOfCompilation "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" ^ thisClass acceptsLoggingOfCompilation! ! !Metaclass methodsFor: 'compiling' stamp: 'ar 5/18/2003 18:13'! bindingOf: varName ^thisClass classBindingOf: varName! ! !Metaclass methodsFor: 'compiling'! possibleVariablesFor: misspelled continuedFrom: oldResults ^ thisClass possibleVariablesFor: misspelled continuedFrom: oldResults ! ! !Metaclass methodsFor: 'compiling'! wantsChangeSetLogging "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" ^ thisClass wantsChangeSetLogging! ! !Metaclass methodsFor: 'compiling' stamp: 'sw 7/31/2000 14:29'! wantsRecompilationProgressReported "The metaclass follows the rule of the class itself." ^ thisClass wantsRecompilationProgressReported! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'sma 6/25/2000 16:30'! definitionST80 "Refer to the comment in ClassDescription|definition." ^ String streamContents: [:strm | strm print: self; crtab; nextPutAll: 'instanceVariableNames: '; store: self instanceVariablesString]! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'di 6/7/2000 22:50'! definitionST80: isST80 "Refer to the comment in ClassDescription|definition." isST80 ifTrue: [^ self definitionST80]. ^ String streamContents: [:strm | strm print: self; nextPutKeyword: ' instanceVariableNames: ' withArg: self instanceVariablesString]! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'di 2/17/2000 22:33'! fileOutInitializerOn: aStream (self methodDict includesKey: #initialize) ifTrue: [aStream cr. aStream nextChunkPut: thisClass name , ' initialize'].! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:31'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex ^self fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex initializing: true! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'di 2/17/2000 22:33'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex initializing: aBool super fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex. (aBool and:[moveSource not and: [self methodDict includesKey: #initialize]]) ifTrue: [aFileStream cr. aFileStream cr. aFileStream nextChunkPut: thisClass name , ' initialize'. aFileStream cr]! ! !Metaclass methodsFor: 'fileIn/Out' stamp: 'di 2/17/2000 22:33'! nonTrivial "Answer whether the receiver has any methods or instance variables." ^ self instVarNames size > 0 or: [self methodDict size > 0]! ! !Metaclass methodsFor: 'testing' stamp: 'ar 9/10/1999 17:41'! canZapMethodDictionary "Return true if it is safe to zap the method dictionary on #obsolete" thisClass == nil ifTrue:[^true] ifFalse:[^thisClass canZapMethodDictionary]! ! !Metaclass methodsFor: 'testing' stamp: 'ar 7/11/1999 07:27'! isObsolete "Return true if the receiver is obsolete" ^thisClass == nil "Either no thisClass" or:[thisClass class ~~ self "or I am not the class of thisClass" or:[thisClass isObsolete]] "or my instance is obsolete"! ! !Metaclass methodsFor: 'enumerating' stamp: 'ar 7/15/1999 16:43'! allInstancesDo: aBlock "There should be only one" thisClass class == self ifTrue:[^aBlock value: thisClass]. ^super allInstancesDo: aBlock! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Metaclass class instanceVariableNames: ''! !Metaclass class methodsFor: 'anti-corruption' stamp: 'di 11/24/1999 13:30'! isScarySelector: newbieSelector "Return true if newbieSelector is already a part of Metaclass protocol." (Metaclass includesSelector: newbieSelector) ifTrue: [^ true]. (ClassDescription includesSelector: newbieSelector) ifTrue: [^ true]. (Behavior includesSelector: newbieSelector) ifTrue: [^ true]. ^ false ! ! Object subclass: #MethodChangeRecord instanceVariableNames: 'changeType currentMethod infoFromRemoval' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !MethodChangeRecord commentStamp: '<historical>' prior: 0! MethodChangeRecords are used to record method changes. Here is a simple summary of the relationship between the changeType symbol and the recording of prior state | prior == nil | prior not nil --------- |---------------------------- |-------------------- add | add | change --------- |---------------------------- |-------------------- remove | addedThenRemoved | remove Structure: changeType symbol -- as summarized above currentMethod method This is the current version of the method. It can be used to assert this change upon entry to a layer. infoFromRemoval -- an array of size 2. The first element is the source index of the last version of the method. The second element is the category in which it was defined, so it can be put back there if re-accepted from a version browser. Note that the above states each have an associated revoke action: add --> remove change --> change back remove --> add back addedThenRemoved --> no change However all of these are accomplished trivially by restoring the original method dictionary.! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/1/2000 12:02'! changeType ^ changeType! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 3/28/2000 23:34'! currentMethod ^ currentMethod! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/1/2000 12:02'! methodInfoFromRemoval "Return an array with the source index of the last version of the method, and the category in which it was defined (so it can be put back there if re-accepted from a version browser)." (changeType == #remove or: [changeType == #addedThenRemoved]) ifTrue: [^ infoFromRemoval] ifFalse: [^ nil]! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/4/2000 11:05'! noteChangeType: newChangeType (changeType == #addedThenRemoved and: [newChangeType == #change]) ifTrue: [changeType _ #add] ifFalse: [changeType _ newChangeType]! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/1/2000 11:05'! noteMethodInfoFromRemoval: info "Store an array with the source index of the last version of the method, and the category in which it was defined (so it can be put back there if re-accepted from a version browser)." infoFromRemoval _ info! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 3/28/2000 23:32'! noteNewMethod: newMethod currentMethod _ newMethod! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/1/2000 12:02'! printOn: strm super printOn: strm. strm nextPutAll: ' ('; print: changeType; nextPutAll: ')'! ! !MethodChangeRecord methodsFor: 'as yet unclassified' stamp: 'di 4/1/2000 10:47'! priorMethod: ignored "We do not save original versions of changed methods because we only revoke changes at the level of entire classes, and that is done by restoration of the entire methodDictionary."! ! ContextPart variableSubclass: #MethodContext instanceVariableNames: 'method receiverMap receiver' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !MethodContext commentStamp: '<historical>' prior: 0! 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. 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. MethodContexts must only be created using the method newForMethod:. Note that it is impossible to determine the real object size of a MethodContext except by asking for the frameSize of its method. Any fields above the stack pointer (stackp) are truly invisible -- even (and especially!!) to the garbage collector. Any store into stackp other than by the primitive method stackp: is potentially fatal.! !MethodContext methodsFor: 'initialize-release' stamp: 'ajh 1/23/2003 20:27'! privRefresh "Reinitialize the receiver so that it is in the state it was at its creation." pc _ method initialPC. self stackp: method numTemps. method numArgs+1 to: method numTemps do: [:i | self tempAt: i put: nil]! ! !MethodContext methodsFor: 'initialize-release' stamp: 'ajh 5/22/2003 16:28'! privRefreshWith: aCompiledMethod "Reinitialize the receiver as though it had been for a different method. Used by a Debugger when one of the methods to which it refers is recompiled." method _ aCompiledMethod. receiverMap _ nil. self privRefresh! ! !MethodContext methodsFor: 'accessing' stamp: 'ajh 1/31/2003 16:55'! blockHome "If executing closure, search senders for method containing my closure method. If not found return nil." | m | self isExecutingBlock ifFalse: [^ self]. self sender ifNil: [^ nil]. m _ self method. ^ self sender findContextSuchThat: [:c | c method hasLiteralThorough: m]! ! !MethodContext methodsFor: 'accessing' stamp: 'ajh 1/31/2003 23:29'! finalBlockHome "If executing closure, search senders for original method containing my closure method. If not found return nil." | h | self isExecutingBlock ifFalse: [^ self]. ^ (h _ self blockHome) ifNotNil: [h finalBlockHome]! ! !MethodContext methodsFor: 'accessing'! home "Refer to the comment in ContextPart|home." ^self! ! !MethodContext methodsFor: 'accessing' stamp: 'ar 6/28/2003 00:04'! isExecutingBlock "Is this executing a block versus a method" | r | Smalltalk at: #BlockClosure ifPresent:[:aClass| ^((r _ self receiver) isKindOf: aClass) and: [r method == self method] ]. ^false! ! !MethodContext methodsFor: 'accessing'! method ^method! ! !MethodContext methodsFor: 'accessing' stamp: 'ajh 2/9/2003 00:08'! methodNode | h | ^ self isExecutingBlock ifTrue: [self method blockNodeIn: ((h _ self blockHome) ifNotNil: [h methodNode])] ifFalse: [super methodNode]! ! !MethodContext methodsFor: 'accessing'! receiver "Refer to the comment in ContextPart|receiver." ^receiver! ! !MethodContext methodsFor: 'accessing'! tempAt: index "Refer to the comment in ContextPart|tempAt:." ^self at: index! ! !MethodContext methodsFor: 'accessing'! tempAt: index put: value "Refer to the comment in ContextPart|tempAt:put:." ^self at: index put: value! ! !MethodContext methodsFor: 'private' stamp: 'di 1/14/1999 22:30'! instVarAt: index put: value index = 3 ifTrue: [self stackp: value. ^ value]. ^ super instVarAt: index put: value! ! !MethodContext methodsFor: 'private' stamp: 'ikp 12/23/1999 15:56'! setSender: s receiver: r method: m arguments: args "Create the receiver's initial state." sender _ s. receiver _ r. method _ m. receiverMap _ nil. pc _ method initialPC. self stackp: method numTemps. 1 to: args size do: [:i | self at: i put: (args at: i)]! ! !MethodContext methodsFor: 'private' stamp: 'ajh 8/13/2002 13:34'! startpc ^ self method initialPC! ! !MethodContext methodsFor: 'private-exceptions' stamp: 'hg 10/2/2001 20:43'! cannotReturn: result Debugger openContext: thisContext label: 'computation has been terminated' contents: nil! ! !MethodContext methodsFor: 'private-exceptions' stamp: 'tpr 2/24/2001 22:05'! isHandlerContext "is this context for method that is marked?" ^method primitive = 199! ! !MethodContext methodsFor: 'private-exceptions' stamp: 'tpr 2/24/2001 22:05'! isUnwindContext "is this context for method that is marked?" ^method primitive = 198! ! !MethodContext methodsFor: 'private-exceptions' stamp: 'tfei 3/23/1999 13:00'! receiver: r receiver := r! ! !MethodContext methodsFor: 'private-debugger' stamp: 'tfei 3/19/2000 23:55'! cachedStackTop "WARNING - this method depends on a very dirty trick, viz. snitching information off the variable stack of a particular CompiledMethod. So if you add/remove a temp in BlockContext>>valueUninterruptably, this method will fail, probably with some horrible consequences I'd rather not think through just now ... assumption is that the variable declaration in that method looks like: | sendingContext result homeSender |" ^self tempAt: 3! ! !MethodContext methodsFor: 'private-debugger' stamp: 'ajh 1/24/2003 23:38'! cachesStack ^ false "^self selector == #valueUninterruptably and: [self receiver class == BlockContext]"! ! !MethodContext methodsFor: 'private-debugger' stamp: 'tfei 3/20/2000 00:24'! hideFromDebugger | sndr sndrHome | ^self cachesStack or: [(sndr := self sender) ~~ nil and: [(sndrHome := sndr home) ~~ nil and: [sndrHome cachesStack]]]! ! !MethodContext methodsFor: 'printing' stamp: 'ajh 1/31/2003 20:34'! printOn: aStream | h | self isExecutingBlock ifFalse: [^ super printOn: aStream]. h _ self blockHome. h ifNil: [^ aStream nextPutAll: '[]']. aStream nextPutAll: '[] from '. h printOn: aStream! ! !MethodContext methodsFor: 'printing' stamp: 'emm 5/30/2002 14:07'! printString "Answer an emphasized string in case of a breakpoint method" ^self method hasBreakpoint ifTrue:[(super printString , ' [break]') asText allBold] ifFalse:[super printString]! ! !MethodContext methodsFor: 'printing' stamp: 'LC 1/6/2002 11:13'! who | sel mcls | self method ifNil: [^ Array with: #unknown with: #unknown]. sel _ self receiver class selectorAtMethod: self method setClass: [:c | mcls _ c]. sel == #? ifTrue: [^ self method who]. ^ Array with: mcls with: sel ! ! !MethodContext methodsFor: 'closure support' stamp: 'ar 6/28/2003 00:15'! contextTag "Context tags may be used for referring to contexts instead of contexts themselves as they can be copied and will continue to work in other processes (continuations). By default, we use the context itself to as its tag." ^self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MethodContext class instanceVariableNames: ''! !MethodContext class methodsFor: 'instance creation' stamp: 'di 10/23/1999 17:06'! sender: s receiver: r method: m arguments: args "Answer an instance of me with attributes set to the arguments." ^(self newForMethod: m) setSender: s receiver: r method: m arguments: args! ! Dictionary variableSubclass: #MethodDictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !MethodDictionary commentStamp: '<historical>' prior: 0! I am just like a normal Dictionary, except that I am implemented differently. Each Class has an instances of MethodDictionary to hold the correspondence between selectors (names of methods) and methods themselves. In a normal Dictionary, the instance variable 'array' holds an array of Associations. Since there are thousands of methods in the system, these Associations waste space. Each MethodDictionary is a variable object, with the list of keys (selector Symbols) in the variable part of the instance. The variable 'array' holds the values, which are CompiledMethods.! !MethodDictionary methodsFor: 'accessing'! add: anAssociation ^ self at: anAssociation key put: anAssociation value! ! !MethodDictionary methodsFor: 'accessing'! at: key ifAbsent: aBlock | index | index _ self findElementOrNil: key. (self basicAt: index) == nil ifTrue: [ ^ aBlock value ]. ^ array at: index! ! !MethodDictionary methodsFor: 'accessing' stamp: 'ar 10/12/2000 17:25'! at: key put: value "Set the value at key to be value." | index | index _ self findElementOrNil: key. (self basicAt: index) == nil ifTrue: [tally _ tally + 1. self basicAt: index put: key] ifFalse: [(array at: index) flushCache]. array at: index put: value. self fullCheck. ^ value! ! !MethodDictionary methodsFor: 'accessing' stamp: 'tk 6/30/2000 00:14'! includesKey: aSymbol "This override assumes that pointsTo is a fast primitive" aSymbol ifNil: [^ false]. ^ super pointsTo: aSymbol! ! !MethodDictionary methodsFor: 'accessing' stamp: 'ar 2/13/1999 21:17'! keyAtIdentityValue: value ifAbsent: exceptionBlock "Answer the key whose value equals the argument, value. If there is none, answer the result of evaluating exceptionBlock." | theKey | 1 to: self basicSize do: [:index | value == (array at: index) ifTrue: [(theKey _ self basicAt: index) == nil ifFalse: [^ theKey]]]. ^ exceptionBlock value! ! !MethodDictionary methodsFor: 'accessing' stamp: 'ar 2/13/1999 21:00'! keyAtValue: value ifAbsent: exceptionBlock "Answer the key whose value equals the argument, value. If there is none, answer the result of evaluating exceptionBlock." | theKey | 1 to: self basicSize do: [:index | value = (array at: index) ifTrue: [(theKey _ self basicAt: index) == nil ifFalse: [^ theKey]]]. ^ exceptionBlock value! ! !MethodDictionary methodsFor: 'removing'! removeKey: key ifAbsent: errorBlock "The interpreter might be using this MethodDict while this method is running!! Therefore we perform the removal in a copy, and then atomically become that copy" | copy | copy _ self copy. copy removeDangerouslyKey: key ifAbsent: [^ errorBlock value]. self become: copy! ! !MethodDictionary methodsFor: 'enumeration'! associationsDo: aBlock | key | tally = 0 ifTrue: [^ self]. 1 to: self basicSize do: [:i | (key _ self basicAt: i) == nil ifFalse: [aBlock value: (Association key: key value: (array at: i))]]! ! !MethodDictionary methodsFor: 'enumeration' stamp: 'to 1/14/98 10:13'! do: aBlock tally = 0 ifTrue: [^ self]. 1 to: self basicSize do: [:i | (self basicAt: i) == nil ifFalse: [aBlock value: (array at: i)]] ! ! !MethodDictionary methodsFor: 'enumeration' stamp: 'ar 7/11/1999 08:05'! keysAndValuesDo: aBlock "Enumerate the receiver with all the keys and values passed to the block" | key | tally = 0 ifTrue: [^ self]. 1 to: self basicSize do: [:i | (key _ self basicAt: i) == nil ifFalse: [aBlock value: key value: (array at: i)] ]! ! !MethodDictionary methodsFor: 'enumeration'! keysDo: aBlock | key | tally = 0 ifTrue: [^ self]. 1 to: self basicSize do: [:i | (key _ self basicAt: i) == nil ifFalse: [aBlock value: key]]! ! !MethodDictionary methodsFor: 'enumeration' stamp: 'ar 7/11/1999 07:29'! valuesDo: aBlock | value | tally = 0 ifTrue: [^ self]. 1 to: self basicSize do: [:i | (value _ array at: i) == nil ifFalse: [aBlock value: value]]! ! !MethodDictionary methodsFor: 'private' stamp: 'tk 8/21/97 16:26'! copy ^ self shallowCopy withArray: array shallowCopy! ! !MethodDictionary methodsFor: 'private' stamp: 'di 11/4/97 20:11'! grow | newSelf key | newSelf _ self species new: self basicSize. "This will double the size" 1 to: self basicSize do: [:i | key _ self basicAt: i. key == nil ifFalse: [newSelf at: key put: (array at: i)]]. self become: newSelf! ! !MethodDictionary methodsFor: 'private'! keyAt: index ^ self basicAt: index! ! !MethodDictionary methodsFor: 'private'! rehash | newSelf key | newSelf _ self species new: self size. 1 to: self basicSize do: [:i | key _ self basicAt: i. key == nil ifFalse: [newSelf at: key put: (array at: i)]]. self become: newSelf! ! !MethodDictionary methodsFor: 'private' stamp: 'RAA 12/17/2000 11:11'! rehashWithoutBecome | newSelf key | newSelf _ self species new: self size. 1 to: self basicSize do: [:i | key _ self basicAt: i. key == nil ifFalse: [newSelf at: key put: (array at: i)]]. ^newSelf! ! !MethodDictionary methodsFor: 'private'! removeDangerouslyKey: key ifAbsent: aBlock "This is not really dangerous. But if normal removal were done WHILE a MethodDict were being used, the system might crash. So instead we make a copy, then do this operation (which is NOT dangerous in a copy that is not being used), and then use the copy after the removal." | index element | index _ self findElementOrNil: key. (self basicAt: index) == nil ifTrue: [ ^ aBlock value ]. element _ array at: index. array at: index put: nil. self basicAt: index put: nil. tally _ tally - 1. self fixCollisionsFrom: index. ^ element! ! !MethodDictionary methodsFor: 'private'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (anObject identityHash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ self basicAt: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ self basicAt: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !MethodDictionary methodsFor: 'private'! swap: oneIndex with: otherIndex | element | element _ self basicAt: oneIndex. self basicAt: oneIndex put: (self basicAt: otherIndex). self basicAt: otherIndex put: element. super swap: oneIndex with: otherIndex. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MethodDictionary class instanceVariableNames: ''! !MethodDictionary class methodsFor: 'instance creation' stamp: 'RAA 5/29/2001 09:53'! new "change the default size to be a bit bigger to help reduce the number of #grows while filing in" ^self new: 16! ! !MethodDictionary class methodsFor: 'instance creation' stamp: 'di 11/4/97 20:11'! new: nElements "Create a Dictionary large enough to hold nElements without growing. Note that the basic size must be a power of 2. It is VITAL (see grow) that size gets doubled if nElements is a power of 2" | size | size _ 1 bitShift: nElements highBit. ^ (self basicNew: size) init: size! ! Object subclass: #MethodFinder instanceVariableNames: 'data answers selector argMap thisData mapStage mapList expressions cachedClass cachedArgNum cachedSelectorLists' classVariableNames: 'AddAndRemove Approved Blocks Dangerous' poolDictionaries: '' category: 'Kernel-Methods'! !MethodFinder commentStamp: '<historical>' prior: 0! Find a method in the system from a set of examples. Done by brute force, trying every possible selector. Errors are skipped over using ( [3 + 'xyz'] ifError: [^ false] ). Submit an array of the form ((data1 data2) answer (data1 data2) answer). MethodFinder methodFor: #( (4 3) 7 (0 5) 5 (5 5) 10). answer: 'data1 + data2' More generally, use the brace notation to construct live examples. The program tries data1 as the receiver, and tries all other permutations of the data for the receiver and args, and tries leaving out one argument, and uses all selectors data understands, and uses all selectors in all od data's superclasses. Floating point values must be precise to 0.01 percent, or (X * 0.0001). If you get an error, you have probably discovered a selector that needs to be removed from the Approved list. See MethodFinder.initialize. Please email the Squeak Team. Only considers 0, 1, 2, and 3 argument messages. The argument data may have 1 to 5 entries, but only a max of 4 used at a time. For now, we only test messages that use given number of args or one fewer. For example, this data (100 true 0.6) would test the receiver plus two args, and the receiver plus one arg, but not any other patterns. Three sets of selectors: Approved, AddAndRemove, and Blocks selectors. When testing a selector in AddAndRemove, deepCopy the receiver. We do not handle selectors that modify an argument (printOn: etc.). Blocks is a set of (selector argNumber) where that argument must be a block. For perform, the selector is tested. It must be in the Approved list. do: is not on the Approved list. It does not produce a result that can be tested. Type 'do' into the upper pane of the Selector Finder to find messages list that. [Later, allow the user to supply a block that tests the answer, not just the literal answer.] MethodFinder methodFor: { { true. [3]. [4]}. 3}. Later allow this to work without the blocks around 3 and 4.! !MethodFinder methodsFor: 'initialize' stamp: 'tk 7/1/2000 23:11'! cleanInputs: dataAndAnswerString "Find an remove common mistakes. Complain when ill formed." | fixed ddd rs places | ddd _ dataAndAnswerString. fixed _ false. rs _ ReadStream on: ddd, ' '. places _ OrderedCollection new. [rs upToAll: '#true'. rs atEnd] whileFalse: [places addFirst: rs position-4]. places do: [:pos | ddd _ ddd copyReplaceFrom: pos to: pos with: ''. fixed _ true]. "remove #" rs _ ReadStream on: ddd. places _ OrderedCollection new. [rs upToAll: '#false'. rs atEnd] whileFalse: [places addFirst: rs position-5]. places do: [:pos | ddd _ ddd copyReplaceFrom: pos to: pos with: ''. fixed _ true]. "remove #" fixed ifTrue: [self inform: '#(true false) are Symbols, not Booleans. Next time use { true. false }.']. fixed _ false. rs _ ReadStream on: ddd. places _ OrderedCollection new. [rs upToAll: '#nil'. rs atEnd] whileFalse: [places addFirst: rs position-3]. places do: [:pos | ddd _ ddd copyReplaceFrom: pos to: pos with: ''. fixed _ true]. "remove #" fixed ifTrue: [self inform: '#nil is a Symbol, not the authentic UndefinedObject. Next time use nil instead of #nil']. ^ ddd ! ! !MethodFinder methodsFor: 'initialize' stamp: 'md 11/14/2003 16:47'! copy: mthFinder addArg: aConstant | more | "Copy inputs and answers, add an additional data argument to the inputs. The same constant for every example" more _ Array with: aConstant. data _ mthFinder data collect: [:argList | argList, more]. answers _ mthFinder answers. self load: nil. ! ! !MethodFinder methodsFor: 'initialize' stamp: 'tk 5/18/2001 19:23'! initialize "The methods we are allowed to use. (MethodFinder new initialize) " Approved _ Set new. AddAndRemove _ Set new. Blocks _ Set new. "These modify an argument and are not used by the MethodFinder: longPrintOn: printOn: storeOn: sentTo: storeOn:base: printOn:base: absPrintExactlyOn:base: absPrintOn:base: absPrintOn:base:digitCount: writeOn: writeScanOn: possibleVariablesFor:continuedFrom: printOn:format:" "Object" #("in class, instance creation" categoryForUniclasses chooseUniqueClassName initialInstance isSystemDefined newFrom: officialClass readCarefullyFrom: "accessing" at: basicAt: basicSize bindWithTemp: in: size yourself "testing" basicType ifNil: ifNil:ifNotNil: ifNotNil: ifNotNil:ifNil: isColor isFloat isFraction isInMemory isInteger isMorph isNil isNumber isPoint isPseudoContext isText isTransparent isWebBrowser knownName notNil pointsTo: wantsSteps "comparing" = == closeTo: hash hashMappedBy: identityHash identityHashMappedBy: identityHashPrintString ~= ~~ "copying" clone copy shallowCopy "dependents access" canDiscardEdits dependents hasUnacceptedEdits "updating" changed changed: okToChange update: windowIsClosing "printing" fullPrintString isLiteral longPrintString printString storeString stringForReadout stringRepresentation "class membership" class isKindOf: isKindOf:orOf: isMemberOf: respondsTo: xxxClass "error handling" "user interface" addModelMenuItemsTo:forMorph:hand: defaultBackgroundColor defaultLabelForInspector fullScreenSize initialExtent modelWakeUp mouseUpBalk: newTileMorphRepresentative windowActiveOnFirstClick windowReqNewLabel: "system primitives" asOop instVarAt: instVarNamed: "private" "associating" -> "converting" as: asOrderedCollection asString "casing" caseOf: caseOf:otherwise: "binding" bindingOf: "macpal" contentsChanged currentEvent currentHand currentWorld flash ifKindOf:thenDo: instanceVariableValues scriptPerformer "flagging" flag: "translation support" "objects from disk" "finalization" ) do: [:sel | Approved add: sel]. #(at:add: at:modify: at:put: basicAt:put: "NOT instVar:at:" "message handling" perform: perform:orSendTo: perform:with: perform:with:with: perform:with:with:with: perform:withArguments: perform:withArguments:inSuperclass: ) do: [:sel | AddAndRemove add: sel]. "Boolean, True, False, UndefinedObject" #("logical operations" & eqv: not xor: | "controlling" and: ifFalse: ifFalse:ifTrue: ifTrue: ifTrue:ifFalse: or: "copying" "testing" isEmptyOrNil) do: [:sel | Approved add: sel]. "Behavior" #("initialize-release" "accessing" compilerClass decompilerClass evaluatorClass format methodDict parserClass sourceCodeTemplate subclassDefinerClass "testing" instSize instSpec isBits isBytes isFixed isPointers isVariable isWeak isWords "copying" "printing" defaultNameStemForInstances printHierarchy "creating class hierarchy" "creating method dictionary" "instance creation" basicNew basicNew: new new: "accessing class hierarchy" allSubclasses allSubclassesWithLevelDo:startingLevel: allSuperclasses subclasses superclass withAllSubclasses withAllSuperclasses "accessing method dictionary" allSelectors changeRecordsAt: compiledMethodAt: compiledMethodAt:ifAbsent: firstCommentAt: lookupSelector: selectors selectorsDo: selectorsWithArgs: "slow but useful ->" sourceCodeAt: sourceCodeAt:ifAbsent: sourceMethodAt: sourceMethodAt:ifAbsent: "accessing instances and variables" allClassVarNames allInstVarNames allSharedPools classVarNames instVarNames instanceCount sharedPools someInstance subclassInstVarNames "testing class hierarchy" inheritsFrom: kindOfSubclass "testing method dictionary" canUnderstand: classThatUnderstands: hasMethods includesSelector: scopeHas:ifTrue: whichClassIncludesSelector: whichSelectorsAccess: whichSelectorsReferTo: whichSelectorsReferTo:special:byte: whichSelectorsStoreInto: "enumerating" "user interface" "private" indexIfCompact) do: [:sel | Approved add: sel]. "ClassDescription" #("initialize-release" "accessing" classVersion isMeta name theNonMetaClass "copying" "printing" classVariablesString instanceVariablesString sharedPoolsString "instance variables" checkForInstVarsOK: "method dictionary" "organization" category organization whichCategoryIncludesSelector: "compiling" acceptsLoggingOfCompilation wantsChangeSetLogging "fileIn/Out" definition "private" ) do: [:sel | Approved add: sel]. "Class" #("initialize-release" "accessing" classPool "testing" "copying" "class name" "instance variables" "class variables" classVarAt: classVariableAssociationAt: "pool variables" "compiling" "subclass creation" "fileIn/Out" ) do: [:sel | Approved add: sel]. "Metaclass" #("initialize-release" "accessing" isSystemDefined soleInstance "copying" "instance creation" "instance variables" "pool variables" "class hierarchy" "compiling" "fileIn/Out" nonTrivial ) do: [:sel | Approved add: sel]. "Context, BlockContext" #(receiver client method receiver tempAt: "debugger access" mclass pc selector sender shortStack sourceCode tempNames tempsAndValues "controlling" "printing" "system simulation" "initialize-release" "accessing" hasMethodReturn home numArgs "evaluating" value value:ifError: value:value: value:value:value: value:value:value:value: valueWithArguments: "controlling" "scheduling" "instruction decoding" "printing" "private" "system simulation" ) do: [:sel | Approved add: sel]. #(value: "<- Association has it as a store" ) do: [:sel | AddAndRemove add: sel]. "Message" #("inclass, instance creation" selector: selector:argument: selector:arguments: "accessing" argument argument: arguments sends: "printing" "sending" ) do: [:sel | Approved add: sel]. #("private" setSelector:arguments:) do: [:sel | AddAndRemove add: sel]. "Magnitude" #("comparing" < <= > >= between:and: "testing" max: min: min:max: ) do: [:sel | Approved add: sel]. "Date, Time" #("in class, instance creation" fromDays: fromSeconds: fromString: newDay:month:year: newDay:year: today "in class, general inquiries" dateAndTimeNow dayOfWeek: daysInMonth:forYear: daysInYear: firstWeekdayOfMonth:year: indexOfMonth: leapYear: nameOfDay: nameOfMonth: "accessing" day leap monthIndex monthName weekday year "arithmetic" addDays: subtractDate: subtractDays: "comparing" "inquiries" dayOfMonth daysInMonth daysInYear daysLeftInYear firstDayOfMonth previous: "converting" asSeconds "printing" mmddyy mmddyyyy printFormat: "private" firstDayOfMonthIndex: weekdayIndex "in class, instance creation" fromSeconds: now "in class, general inquiries" dateAndTimeFromSeconds: dateAndTimeNow millisecondClockValue millisecondsToRun: totalSeconds "accessing" hours minutes seconds "arithmetic" addTime: subtractTime: "comparing" "printing" intervalString print24 "converting") do: [:sel | Approved add: sel]. #("private" hours: hours:minutes:seconds: day:year: ) do: [:sel | AddAndRemove add: sel]. "Number" #("in class" readFrom:base: "arithmetic" * + - / // \\ abs negated quo: reciprocal rem: "mathematical functions" arcCos arcSin arcTan arcTan: cos exp floorLog: ln log log: raisedTo: raisedToInteger: sin sqrt squared tan "truncation and round off" ceiling detentBy:atMultiplesOf:snap: floor roundTo: roundUpTo: rounded truncateTo: truncated "comparing" "testing" even isDivisibleBy: isInf isInfinite isNaN isZero negative odd positive sign strictlyPositive "converting" @ asInteger asNumber asPoint asSmallAngleDegrees degreesToRadians radiansToDegrees "intervals" to: to:by: "printing" printStringBase: storeStringBase: ) do: [:sel | Approved add: sel]. "Integer" #("in class" primesUpTo: "testing" isPowerOfTwo "arithmetic" alignedTo: "comparing" "truncation and round off" atRandom normalize "enumerating" timesRepeat: "mathematical functions" degreeCos degreeSin factorial gcd: lcm: take: "bit manipulation" << >> allMask: anyMask: bitAnd: bitClear: bitInvert bitInvert32 bitOr: bitShift: bitXor: lowBit noMask: "converting" asCharacter asColorOfDepth: asFloat asFraction asHexDigit "printing" asStringWithCommas hex hex8 radix: "system primitives" lastDigit replaceFrom:to:with:startingAt: "private" "benchmarks" ) do: [:sel | Approved add: sel]. "SmallInteger, LargeNegativeInteger, LargePositiveInteger" #("arithmetic" "bit manipulation" highBit "testing" "comparing" "copying" "converting" "printing" "system primitives" digitAt: digitLength "private" fromString:radix: ) do: [:sel | Approved add: sel]. #(digitAt:put: ) do: [:sel | AddAndRemove add: sel]. "Float" #("arithmetic" "mathematical functions" reciprocalFloorLog: reciprocalLogBase2 timesTwoPower: "comparing" "testing" "truncation and round off" exponent fractionPart integerPart significand significandAsInteger "converting" asApproximateFraction asIEEE32BitWord asTrueFraction "copying") do: [:sel | Approved add: sel]. "Fraction, Random" #(denominator numerator reduced next nextValue) do: [:sel | Approved add: sel]. #(setNumerator:denominator:) do: [:sel | AddAndRemove add: sel]. "Collection" #("accessing" anyOne "testing" includes: includesAllOf: includesAnyOf: includesSubstringAnywhere: isEmpty isSequenceable occurrencesOf: "enumerating" collect: collect:thenSelect: count: detect: detect:ifNone: detectMax: detectMin: detectSum: inject:into: reject: select: select:thenCollect: "converting" asBag asCharacterSet asSet asSortedArray asSortedCollection asSortedCollection: "printing" "private" maxSize "arithmetic" "math functions" average max median min range sum) do: [:sel | Approved add: sel]. #("adding" add: addAll: addIfNotPresent: "removing" remove: remove:ifAbsent: removeAll: removeAllFoundIn: removeAllSuchThat: remove:ifAbsent:) do: [:sel | AddAndRemove add: sel]. "SequenceableCollection" #("comparing" hasEqualElements: "accessing" allButFirst allButLast at:ifAbsent: atAll: atPin: atRandom: atWrap: fifth first fourth identityIndexOf: identityIndexOf:ifAbsent: indexOf: indexOf:ifAbsent: indexOf:startingAt:ifAbsent: indexOfSubCollection:startingAt: indexOfSubCollection:startingAt:ifAbsent: last second sixth third "removing" "copying" , copyAfterLast: copyAt:put: copyFrom:to: copyReplaceAll:with: copyReplaceFrom:to:with: copyUpTo: copyUpToLast: copyWith: copyWithout: copyWithoutAll: forceTo:paddingWith: shuffled sortBy: "enumerating" collectWithIndex: findFirst: findLast: pairsCollect: with:collect: withIndexCollect: polynomialEval: "converting" asArray asDictionary asFloatArray asIntegerArray asStringWithCr asWordArray reversed "private" copyReplaceAll:with:asTokens: ) do: [:sel | Approved add: sel]. #( swap:with:) do: [:sel | AddAndRemove add: sel]. "ArrayedCollection, Bag" #("private" defaultElement "sorting" isSorted "accessing" cumulativeCounts sortedCounts sortedElements "testing" "adding" add:withOccurrences: "removing" "enumerating" ) do: [:sel | Approved add: sel]. #( mergeSortFrom:to:by: sort sort: add: add:withOccurrences: "private" setDictionary ) do: [:sel | AddAndRemove add: sel]. "Other messages that modify the receiver" #(atAll:put: atAll:putAll: atAllPut: atWrap:put: replaceAll:with: replaceFrom:to:with: removeFirst removeLast) do: [:sel | AddAndRemove add: sel]. self initialize2. " MethodFinder new initialize. MethodFinder new organizationFiltered: Set " ! ! !MethodFinder methodsFor: 'initialize' stamp: 'ads 3/29/2003 17:12'! initialize2 "The methods we are allowed to use. (MethodFinder new initialize) " "Set" #("in class" sizeFor: "testing" "adding" "removing" "enumerating" "private" array findElementOrNil: "accessing" someElement) do: [:sel | Approved add: sel]. "Dictionary, IdentityDictionary, IdentitySet" #("accessing" associationAt: associationAt:ifAbsent: at:ifPresent: keyAtIdentityValue: keyAtIdentityValue:ifAbsent: keyAtValue: keyAtValue:ifAbsent: keys "testing" includesKey: ) do: [:sel | Approved add: sel]. #(removeKey: removeKey:ifAbsent: ) do: [:sel | AddAndRemove add: sel]. "LinkedList, Interval, MappedCollection" #("in class" from:to: from:to:by: "accessing" contents) do: [:sel | Approved add: sel]. #( "adding" addFirst: addLast:) do: [:sel | AddAndRemove add: sel]. "OrderedCollection, SortedCollection" #("accessing" after: before: "copying" copyEmpty "adding" growSize "removing" "enumerating" "private" "accessing" sortBlock) do: [:sel | Approved add: sel]. #("adding" add:after: add:afterIndex: add:before: addAllFirst: addAllLast: addFirst: addLast: "removing" removeAt: removeFirst removeLast "accessing" sortBlock:) do: [:sel | AddAndRemove add: sel]. "Character" #("in class, instance creation" allCharacters digitValue: new separators "accessing untypeable characters" backspace cr enter lf linefeed nbsp newPage space tab "constants" alphabet characterTable "accessing" asciiValue digitValue "comparing" "testing" isAlphaNumeric isDigit isLetter isLowercase isSafeForHTTP isSeparator isSpecial isUppercase isVowel tokenish "copying" "converting" asIRCLowercase asLowercase asUppercase ) do: [:sel | Approved add: sel]. "String" #("in class, instance creation" crlf fromPacked: "primitives" findFirstInString:inSet:startingAt: indexOfAscii:inString:startingAt: "internet" valueOfHtmlEntity: "accessing" byteAt: endsWithDigit findAnySubStr:startingAt: findBetweenSubStrs: findDelimiters:startingAt: findString:startingAt: findString:startingAt:caseSensitive: findTokens: findTokens:includes: findTokens:keep: includesSubString: includesSubstring:caseSensitive: indexOf:startingAt: indexOfAnyOf: indexOfAnyOf:ifAbsent: indexOfAnyOf:startingAt: indexOfAnyOf:startingAt:ifAbsent: lineCorrespondingToIndex: lineCount lineNumber: skipAnySubStr:startingAt: skipDelimiters:startingAt: startsWithDigit "comparing" alike: beginsWith: caseSensitiveLessOrEqual: charactersExactlyMatching: compare: crc16 endsWith: endsWithAnyOf: sameAs: startingAt:match:startingAt: "copying" copyReplaceTokens:with: padded:to:with: "converting" asByteArray asDate asDisplayText asFileName asHtml asLegalSelector asPacked asParagraph asText asTime asUnHtml asUrl asUrlRelativeTo: capitalized compressWithTable: contractTo: correctAgainst: encodeForHTTP initialIntegerOrNil keywords quoted sansPeriodSuffix splitInteger stemAndNumericSuffix substrings surroundedBySingleQuotes truncateWithElipsisTo: withBlanksTrimmed withFirstCharacterDownshifted withNoLineLongerThan: withSeparatorsCompacted withoutLeadingDigits withoutTrailingBlanks "displaying" "printing" "system primitives" compare:with:collated: "Celeste" withCRs "internet" decodeMimeHeader decodeQuotedPrintable unescapePercents withInternetLineEndings withSqueakLineEndings withoutQuoting "testing" isAllSeparators lastSpacePosition "paragraph support" indentationIfBlank: "arithmetic" ) do: [:sel | Approved add: sel]. #(byteAt:put: translateToLowercase match:) do: [:sel | AddAndRemove add: sel]. "Symbol" #("in class, private" hasInterned:ifTrue: "access" morePossibleSelectorsFor: possibleSelectorsFor: selectorsContaining: thatStarts:skipping: "accessing" "comparing" "copying" "converting" "printing" "testing" isInfix isKeyword isPvtSelector isUnary) do: [:sel | Approved add: sel]. "Array" #("comparing" "converting" evalStrings "printing" "private" hasLiteralSuchThat:) do: [:sel | Approved add: sel]. "Array2D" #("access" at:at: atCol: atCol:put: atRow: extent extent:fromArray: height width width:height:type:) do: [:sel | Approved add: sel]. #(at:at:add: at:at:put: atRow:put: ) do: [:sel | AddAndRemove add: sel]. "ByteArray" #("accessing" doubleWordAt: wordAt: "platform independent access" longAt:bigEndian: shortAt:bigEndian: unsignedLongAt:bigEndian: unsignedShortAt:bigEndian: "converting") do: [:sel | Approved add: sel]. #(doubleWordAt:put: wordAt:put: longAt:put:bigEndian: shortAt:put:bigEndian: unsignedLongAt:put:bigEndian: unsignedShortAt:put:bigEndian: ) do: [:sel | AddAndRemove add: sel]. "FloatArray" "Dont know what happens when prims not here" false ifTrue: [#("accessing" "arithmetic" *= += -= /= "comparing" "primitives-plugin" primAddArray: primAddScalar: primDivArray: primDivScalar: primMulArray: primMulScalar: primSubArray: primSubScalar: "primitives-translated" primAddArray:withArray:from:to: primMulArray:withArray:from:to: primSubArray:withArray:from:to: "converting" "private" "user interface") do: [:sel | Approved add: sel]. ]. "IntegerArray, WordArray" "RunArray" #("in class, instance creation" runs:values: scanFrom: "accessing" runLengthAt: "adding" "copying" "private" runs values) do: [:sel | Approved add: sel]. #(coalesce addLast:times: repeatLast:ifEmpty: repeatLastIfEmpty: ) do: [:sel | AddAndRemove add: sel]. "Stream -- many operations change its state" #("testing" atEnd) do: [:sel | Approved add: sel]. #("accessing" next: nextMatchAll: nextMatchFor: upToEnd next:put: nextPut: nextPutAll: "printing" print: printHtml: ) do: [:sel | AddAndRemove add: sel]. "PositionableStream" #("accessing" contentsOfEntireFile originalContents peek peekFor: "testing" "positioning" position ) do: [:sel | Approved add: sel]. #(nextDelimited: nextLine upTo: position: reset resetContents setToEnd skip: skipTo: upToAll: ) do: [:sel | AddAndRemove add: sel]. "Because it is so difficult to test the result of an operation on a Stream (you have to supply another Stream in the same state), we don't support Streams beyond the basics. We want to find the messages that convert Streams to other things." "ReadWriteStream" #("file status" closed) do: [:sel | Approved add: sel]. #("accessing" next: on: ) do: [:sel | AddAndRemove add: sel]. "WriteStream" #("in class, instance creation" on:from:to: with: with:from:to: ) do: [:sel | Approved add: sel]. #("positioning" resetToStart "character writing" crtab crtab:) do: [:sel | AddAndRemove add: sel]. "LookupKey, Association, Link" #("accessing" key nextLink) do: [:sel | Approved add: sel]. #(key: key:value: nextLink:) do: [:sel | AddAndRemove add: sel]. "Point" #("in class, instance creation" r:degrees: x:y: "accessing" x y "comparing" "arithmetic" "truncation and round off" "polar coordinates" degrees r theta "point functions" bearingToPoint: crossProduct: dist: dotProduct: eightNeighbors flipBy:centerAt: fourNeighbors grid: nearestPointAlongLineFrom:to: nearestPointOnLineFrom:to: normal normalized octantOf: onLineFrom:to: onLineFrom:to:within: quadrantOf: rotateBy:centerAt: transposed unitVector "converting" asFloatPoint asIntegerPoint corner: extent: rect: "transforming" adhereTo: rotateBy:about: scaleBy: scaleFrom:to: translateBy: "copying" "interpolating" interpolateTo:at:) do: [:sel | Approved add: sel]. "Rectangle" #("in class, instance creation" center:extent: encompassing: left:right:top:bottom: merging: origin:corner: origin:extent: "accessing" area bottom bottomCenter bottomLeft bottomRight boundingBox center corner corners innerCorners left leftCenter origin right rightCenter top topCenter topLeft topRight "comparing" "rectangle functions" adjustTo:along: amountToTranslateWithin: areasOutside: bordersOn:along: encompass: expandBy: extendBy: forPoint:closestSideDistLen: insetBy: insetOriginBy:cornerBy: intersect: merge: pointNearestTo: quickMerge: rectanglesAt:height: sideNearestTo: translatedToBeWithin: withBottom: withHeight: withLeft: withRight: withSide:setTo: withTop: withWidth: "testing" containsPoint: containsRect: hasPositiveExtent intersects: isTall isWide "truncation and round off" "transforming" align:with: centeredBeneath: newRectFrom: squishedWithin: "copying" ) do: [:sel | Approved add: sel]. "Color" #("in class, instance creation" colorFrom: colorFromPixelValue:depth: fromRgbTriplet: gray: h:s:v: r:g:b: r:g:b:alpha: r:g:b:range: "named colors" black blue brown cyan darkGray gray green lightBlue lightBrown lightCyan lightGray lightGreen lightMagenta lightOrange lightRed lightYellow magenta orange red transparent veryDarkGray veryLightGray veryVeryDarkGray veryVeryLightGray white yellow "other" colorNames indexedColors pixelScreenForDepth: quickHighLight: "access" alpha blue brightness green hue luminance red saturation "equality" "queries" isBitmapFill isBlack isGray isSolidFill isTranslucent isTranslucentColor "transformations" alpha: dansDarker darker lighter mixed:with: muchLighter slightlyDarker slightlyLighter veryMuchLighter alphaMixed:with: "groups of shades" darkShades: lightShades: mix:shades: wheel: "printing" shortPrintString "other" colorForInsets rgbTriplet "conversions" asB3DColor asColor balancedPatternForDepth: bitPatternForDepth: closestPixelValue1 closestPixelValue2 closestPixelValue4 closestPixelValue8 dominantColor halfTonePattern1 halfTonePattern2 indexInMap: pixelValueForDepth: pixelWordFor:filledWith: pixelWordForDepth: scaledPixelValue32 "private" privateAlpha privateBlue privateGreen privateRGB privateRed "copying" ) do: [:sel | Approved add: sel]. " For each selector that requires a block argument, add (selector argNum) to the set Blocks." "ourClasses _ #(Object Boolean True False UndefinedObject Behavior ClassDescription Class Metaclass MethodContext BlockContext Message Magnitude Date Time Number Integer SmallInteger LargeNegativeInteger LargePositiveInteger Float Fraction Random Collection SequenceableCollection ArrayedCollection Bag Set Dictionary IdentityDictionary IdentitySet LinkedList Interval MappedCollection OrderedCollection SortedCollection Character String Symbol Array Array2D ByteArray FloatArray IntegerArray WordArray RunArray Stream PositionableStream ReadWriteStream WriteStream LookupKey Association Link Point Rectangle Color). ourClasses do: [:clsName | cls _ Smalltalk at: clsName. (cls selectors) do: [:aSel | ((Approved includes: aSel) or: [AddAndRemove includes: aSel]) ifTrue: [ (cls formalParametersAt: aSel) withIndexDo: [:tName :ind | (tName endsWith: 'Block') ifTrue: [ Blocks add: (Array with: aSel with: ind)]]]]]. " #((timesRepeat: 1 ) (indexOf:ifAbsent: 2 ) (pairsCollect: 1 ) (mergeSortFrom:to:by: 3 ) (ifNotNil:ifNil: 1 ) (ifNotNil:ifNil: 2 ) (ifNil: 1 ) (at:ifAbsent: 2 ) (ifNil:ifNotNil: 1 ) (ifNil:ifNotNil: 2 ) (ifNotNil: 1 ) (at:modify: 2 ) (identityIndexOf:ifAbsent: 2 ) (sort: 1 ) (sortBlock: 1 ) (detectMax: 1 ) (repeatLastIfEmpty: 1 ) (allSubclassesWithLevelDo:startingLevel: 1 ) (keyAtValue:ifAbsent: 2 ) (in: 1 ) (ifTrue: 1 ) (or: 1 ) (select: 1 ) (inject:into: 2 ) (ifKindOf:thenDo: 2 ) (forPoint:closestSideDistLen: 2 ) (value:ifError: 2 ) (selectorsDo: 1 ) (removeAllSuchThat: 1 ) (keyAtIdentityValue:ifAbsent: 2 ) (detectMin: 1 ) (detect:ifNone: 1 ) (ifTrue:ifFalse: 1 ) (ifTrue:ifFalse: 2 ) (detect:ifNone: 2 ) (hasLiteralSuchThat: 1 ) (indexOfAnyOf:ifAbsent: 2 ) (reject: 1 ) (newRectFrom: 1 ) (removeKey:ifAbsent: 2 ) (at:ifPresent: 2 ) (associationAt:ifAbsent: 2 ) (withIndexCollect: 1 ) (repeatLast:ifEmpty: 2 ) (findLast: 1 ) (indexOf:startingAt:ifAbsent: 3 ) (remove:ifAbsent: 2 ) (ifFalse:ifTrue: 1 ) (ifFalse:ifTrue: 2 ) (caseOf:otherwise: 2 ) (count: 1 ) (collect: 1 ) (sortBy: 1 ) (and: 1 ) (asSortedCollection: 1 ) (with:collect: 2 ) (sourceCodeAt:ifAbsent: 2 ) (detect: 1 ) (scopeHas:ifTrue: 2 ) (collectWithIndex: 1 ) (compiledMethodAt:ifAbsent: 2 ) (bindWithTemp: 1 ) (detectSum: 1 ) (indexOfSubCollection:startingAt:ifAbsent: 3 ) (findFirst: 1 ) (sourceMethodAt:ifAbsent: 2 ) (collect:thenSelect: 1 ) (collect:thenSelect: 2 ) (select:thenCollect: 1 ) (select:thenCollect: 2 ) (ifFalse: 1 ) (indexOfAnyOf:startingAt:ifAbsent: 3 ) (indentationIfBlank: 1 ) ) do: [:anArray | Blocks add: anArray]. self initialize3. " MethodFinder new initialize. MethodFinder new organizationFiltered: TranslucentColor class " "Do not forget class messages for each of these classes" ! ! !MethodFinder methodsFor: 'initialize' stamp: 'tk 4/1/2002 11:33'! initialize3 "additional selectors to consider" #(asWords threeDigitName ) do: [:sel | Approved add: sel].! ! !MethodFinder methodsFor: 'initialize' stamp: 'tk 12/29/2000 13:22'! load: dataWithAnswers "Find a function that takes the data and gives the answers. Odd list entries are data for it, even ones are the answers. nil input means data and answers were supplied already." " (MethodFinder new) load: #( (4 3) 7 (-10 5) -5 (-3 11) 8); findMessage " dataWithAnswers ifNotNil: [ data _ Array new: dataWithAnswers size // 2. 1 to: data size do: [:ii | data at: ii put: (dataWithAnswers at: ii*2-1)]. answers _ Array new: data size. 1 to: answers size do: [:ii | answers at: ii put: (dataWithAnswers at: ii*2)]]. data do: [:list | (list isKindOf: SequenceableCollection) ifFalse: [ ^ self inform: 'first and third items are not Arrays']. ]. argMap _ (1 to: data first size) asArray. data do: [:list | list size = argMap size ifFalse: [ self inform: 'data arrays must all be the same size']]. argMap size > 4 ifTrue: [self inform: 'No more than a receiver and three arguments allowed']. "Really only test receiver and three args." thisData _ data copy. mapStage _ mapList _ nil. ! ! !MethodFinder methodsFor: 'initialize' stamp: 'tk 4/24/1999 19:34'! test3 "find the modification of the caracter table" (#x at: 1) asciiValue = 120 ifFalse: [self error: 'Character table mod'].! ! !MethodFinder methodsFor: 'arg maps' stamp: 'tk 5/18/1999 14:46'! makeAllMaps "Make a giant list of all permutations of the args. To find the function, we will try these permutations of the input data. receiver, args." | ii | mapList _ Array new: argMap size factorial. ii _ 1. argMap permutationsDo: [:perm | mapList at: ii put: perm copy. ii _ ii + 1]. mapStage _ 1. "about to be bumped"! ! !MethodFinder methodsFor: 'arg maps' stamp: 'tk 4/24/1999 19:29'! mapData "Force the data through the map (permutation) to create the data to test." thisData _ data collect: [:realData | argMap collect: [:ind | realData at: ind]]. ! ! !MethodFinder methodsFor: 'arg maps' stamp: 'tk 5/24/1999 16:31'! permuteArgs "Run through ALL the permutations. First one was as presented." data first size <= 1 ifTrue: [^ false]. "no other way" mapList ifNil: [self makeAllMaps]. mapStage _ mapStage + 1. mapStage > mapList size ifTrue: [^ false]. argMap _ mapList at: mapStage. self mapData. ^ true ! ! !MethodFinder methodsFor: 'search' stamp: 'tk 1/8/2001 18:18'! exceptions "Handle some very slippery selectors. asSymbol -- want to be able to produce it, but do not want to make every string submitted into a Symbol!!" | aSel | answers first class == Symbol ifFalse: [^ self]. thisData first first class == String ifFalse: [^ self]. aSel _ #asSymbol. (self testPerfect: aSel) ifTrue: [ selector add: aSel. expressions add: (String streamContents: [:strm | strm nextPutAll: 'data', argMap first printString. aSel keywords doWithIndex: [:key :ind | strm nextPutAll: ' ',key. (key last == $:) | (key first isLetter not) ifTrue: [strm nextPutAll: ' data', (argMap at: ind+1) printString]]])]. ! ! !MethodFinder methodsFor: 'search' stamp: 'tk 1/8/2001 18:35'! findMessage "Control the search." data do: [:alist | (alist isKindOf: SequenceableCollection) ifFalse: [ ^ OrderedCollection with: 'first and third items are not Arrays']]. Approved ifNil: [self initialize]. "Sets of allowed selectors" expressions _ OrderedCollection new. self search: true. "multi" expressions isEmpty ifTrue: [^ OrderedCollection with: 'no single method does that function']. expressions class = String ifTrue: [^ OrderedCollection with: expressions]. ^ expressions! ! !MethodFinder methodsFor: 'search' stamp: 'tk 4/12/2001 10:47'! insertConstants "see if one of several known expressions will do it. C is the constant we discover here." "C data1+C data1*C data1//C (data1*C1 + C2) (data1 = C) (data1 ~= C) (data1 <= C) (data1 >= C) (data1 mod C)" thisData size >= 2 ifFalse: [^ false]. "need 2 examples" (thisData at: 1) size = 1 ifFalse: [^ false]. "only one arg, data1" self const ifTrue: [^ true]. self constUsingData1Value ifTrue: [^ true]. "(data1 ?? const), where const is one of the values of data1" " == ~~ ~= = <= >= " self allNumbers ifFalse: [^ false]. self constMod ifTrue: [^ true]. self constPlus ifTrue: [^ true]. self constMult ifTrue: [^ true]. self constDiv ifTrue: [^ true]. self constLinear ifTrue: [^ true]. ^ false! ! !MethodFinder methodsFor: 'search' stamp: 'tk 12/29/2000 12:54'! search: multi "if Multi is true, collect all selectors that work." | old | selector _ OrderedCollection new. "list of them" old _ Preferences autoAccessors. Preferences disableGently: #autoAccessors. self simpleSearch. multi not & (selector isEmpty not) ifTrue: [old ifTrue: [Preferences enableGently: #autoAccessors]. ^ selector]. [self permuteArgs] whileTrue: [self simpleSearch. multi not & (selector isEmpty not) ifTrue: [old ifTrue: [Preferences enableGently: #autoAccessors]. ^ selector]]. self insertConstants. old ifTrue: [Preferences enableGently: #autoAccessors]. "(selector isEmpty not) ifTrue: [^ selector]]. expression is the answer, not a selector" ^ #()! ! !MethodFinder methodsFor: 'search' stamp: 'tk 1/8/2001 17:53'! searchForOne "Look for and return just one answer" expressions _ OrderedCollection new. self search: false. "non-multi" ^ expressions ! ! !MethodFinder methodsFor: 'search' stamp: 'tk 1/8/2001 18:17'! simpleSearch "Run through first arg's class' selectors, looking for one that works." | class supers listOfLists | self exceptions. class _ thisData first first class. "Cache the selectors for the receiver class" (class == cachedClass and: [cachedArgNum = ((argMap size) - 1)]) ifTrue: [listOfLists _ cachedSelectorLists] ifFalse: [supers _ class withAllSuperclasses. listOfLists _ OrderedCollection new. supers do: [:cls | listOfLists add: (cls selectorsWithArgs: (argMap size) - 1)]. cachedClass _ class. cachedArgNum _ (argMap size) - 1. cachedSelectorLists _ listOfLists]. listOfLists do: [:selectorList | selectorList do: [:aSel | (selector includes: aSel) ifFalse: [ ((Approved includes: aSel) or: [AddAndRemove includes: aSel]) ifTrue: [ (self testPerfect: aSel) ifTrue: [ selector add: aSel. expressions add: (String streamContents: [:strm | strm nextPutAll: 'data', argMap first printString. aSel keywords doWithIndex: [:key :ind | strm nextPutAll: ' ',key. (key last == $:) | (key first isLetter not) ifTrue: [strm nextPutAll: ' data', (argMap at: ind+1) printString]]]) ]]]]]. ! ! !MethodFinder methodsFor: 'search' stamp: 'tk 4/30/1999 14:22'! testPerfect: aSelector "Try this selector!! Return true if it answers every example perfectly. Take the args in the order they are. Do not permute them. Survive errors. later cache arg lists." | sz argList val rec activeSel perform | "Transcript cr; show: aSelector. debug" perform _ aSelector beginsWith: 'perform:'. sz _ argMap size. 1 to: thisData size do: [:ii | "each example set of args" argList _ (thisData at: ii) copyFrom: 2 to: sz. perform ifFalse: [activeSel _ aSelector] ifTrue: [activeSel _ argList first. "what will be performed" ((Approved includes: activeSel) or: [AddAndRemove includes: activeSel]) ifFalse: [^ false]. "not approved" aSelector == #perform:withArguments: ifTrue: [activeSel numArgs = (argList at: 2) basicSize "avoid error" ifFalse: [^ false]] ifFalse: [activeSel numArgs = (aSelector numArgs - 1) ifFalse: [^ false]]]. 1 to: sz do: [:num | (Blocks includes: (Array with: activeSel with: num)) ifTrue: [ (argList at: num) class == BlockContext ifFalse: [^ false]]]. rec _ (AddAndRemove includes: activeSel) ifTrue: [(thisData at: ii) first class == Symbol ifTrue: [^ false]. "vulnerable to modification" (thisData at: ii) first copyTwoLevel] "protect from damage" ifFalse: [(thisData at: ii) first]. val _ [rec perform: aSelector withArguments: argList] ifError: [:aString :aReceiver | "self test3." "self test2: (thisData at: ii)." ^ false]. "self test3." "self test2: (thisData at: ii)." ((answers at: ii) closeTo: val) ifFalse: [^ false]. ]. ^ true! ! !MethodFinder methodsFor: 'access' stamp: 'tk 12/29/2000 13:39'! answers ^ answers! ! !MethodFinder methodsFor: 'access' stamp: 'tk 12/29/2000 13:39'! data ^ data! ! !MethodFinder methodsFor: 'access' stamp: 'tk 12/29/2000 13:20'! expressions ^ expressions! ! !MethodFinder methodsFor: 'access' stamp: 'tk 1/4/2001 17:18'! selectors "Note the inst var does not have an S on the end" ^ selector! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 12/29/2000 22:34'! allNumbers "Return true if all answers and all data are numbers." answers do: [:aa | aa isNumber ifFalse: [^ false]]. thisData do: [:vec | vec do: [:nn | nn isNumber ifFalse: [^ false]]]. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/18/2001 22:45'! const | const | "See if (^ constant) is the answer" "quick test" ((const _ answers at: 1) closeTo: (answers at: 2)) ifFalse: [^ false]. 3 to: answers size do: [:ii | (const closeTo: (answers at: ii)) ifFalse: [^ false]]. expressions add: '^ ', const printString. selector add: #yourself. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/8/2001 17:49'! constDiv | const subTest got | "See if (data1 // C) is the answer" const _ ((thisData at: 1) at: 1) // (answers at: 1). "May not be right!!" got _ (subTest _ MethodFinder new copy: self addArg: const) searchForOne isEmpty not. got ifFalse: [^ false]. "replace data2 with const in expressions" subTest expressions do: [:exp | expressions add: (exp copyReplaceAll: 'data2' with: const printString)]. selector addAll: subTest selectors. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/8/2001 17:47'! constLinear | const subTest got denom num slope offset | "See if (data1 * C1) + C2 is the answer. In the form #(C2 C1) polynomialEval: data1 " denom _ ((thisData at: 2) at: 1) - ((thisData at: 1) at: 1). denom = 0 ifTrue: [^ false]. "will divide by it" num _ (answers at: 2) - (answers at: 1). slope := (num asFloat / denom) reduce. offset := ((answers at: 2) - (((thisData at: 2) at: 1) * slope)) reduce. const _ Array with: offset with: slope. got _ (subTest _ MethodFinder new copy: self addArg: const) searchForOne isEmpty not. got ifFalse: [^ false]. "replace data2 with const in expressions" subTest expressions do: [:exp | expressions add: (exp copyReplaceAll: 'data2' with: const printString)]. selector addAll: subTest selectors. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/18/2001 22:46'! constMod | subTest low | "See if mod, (data1 \\ C) is the answer" low _ answers max. low+1 to: low+20 do: [:const | subTest _ MethodFinder new copy: self addArg: const. (subTest testPerfect: #\\) ifTrue: [ expressions add: 'data1 \\ ', const printString. selector add: #\\. ^ true]]. ^ false! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/8/2001 17:49'! constMult | const subTest got | "See if (data1 * C) is the answer" ((thisData at: 1) at: 1) = 0 ifTrue: [^ false]. const _ ((answers at: 1) asFloat / ((thisData at: 1) at: 1)) reduce. got _ (subTest _ MethodFinder new copy: self addArg: const) searchForOne isEmpty not. got ifFalse: [^ false]. "replace data2 with const in expressions" subTest expressions do: [:exp | expressions add: (exp copyReplaceAll: 'data2' with: const printString)]. selector addAll: subTest selectors. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 1/8/2001 17:48'! constPlus | const subTest got | "See if (data1 + C) is the answer" const _ (answers at: 1) - ((thisData at: 1) at: 1). got _ (subTest _ MethodFinder new copy: self addArg: const) searchForOne isEmpty not. got ifFalse: [^ false]. "replace data2 with const in expressions" subTest expressions do: [:exp | expressions add: (exp copyReplaceAll: 'data2' with: const printString)]. selector addAll: subTest selectors. ^ true! ! !MethodFinder methodsFor: 'find a constant' stamp: 'tk 4/9/2001 17:59'! constUsingData1Value | const subTest got | "See if (data1 <= C) or (data1 >= C) is the answer" "quick test" ((answers at: 1) class superclass == Boolean) ifFalse: [^ false]. 2 to: answers size do: [:ii | ((answers at: ii) class superclass == Boolean) ifFalse: [^ false]]. thisData do: [:datums | const _ datums first. "use data as a constant!!" got _ (subTest _ MethodFinder new copy: self addArg: const) searchForOne isEmpty not. got ifTrue: [ "replace data2 with const in expressions" subTest expressions do: [:exp | expressions add: (exp copyReplaceAll: 'data2' with: const printString)]. selector addAll: subTest selectors. ^ true]]. ^ false! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MethodFinder class instanceVariableNames: ''! !MethodFinder class methodsFor: 'as yet unclassified' stamp: 'BG 10/29/2003 09:52'! methodFor: dataAndAnswers "Return a Squeak expression that computes these answers. (This method is called by the comment in the bottom pane of a MethodFinder. Do not delete this method.)" | resultOC resultString | resultOC _ (self new) load: dataAndAnswers; findMessage. resultString _ String streamContents: [:strm | resultOC do: [:exp | strm nextPut: $(; nextPutAll: exp; nextPut: $); space]]. ^ resultString! ! CodeHolder subclass: #MethodHolder instanceVariableNames: 'methodClass methodSelector' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !MethodHolder methodsFor: 'menu' stamp: 'dgd 8/30/2003 21:54'! addModelMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph aCustomMenu addLine. aCustomMenu add: 'whose script is this?' translated target: self action: #identifyScript ! ! !MethodHolder methodsFor: 'menu' stamp: 'ssa 9/4/2008 15:23'! doItReceiver "If there is an instance associated with me, answer it, for true mapping of self. If not, then do what other code-bearing tools do, viz. give access to the class vars." ^ self selectedClass ifNil: [FakeClassPool new]! ! !MethodHolder methodsFor: 'miscellaneous' stamp: 'sw 3/28/2002 00:36'! changeMethodSelectorTo: aSelector "Change my method selector as noted. Reset currentCompiledMethod" methodSelector _ aSelector. currentCompiledMethod _ methodClass compiledMethodAt: aSelector ifAbsent: [nil]! ! !MethodHolder methodsFor: 'miscellaneous' stamp: 'tk 8/30/2000 13:07'! compiledMethod ^ methodClass compiledMethodAt: methodSelector! ! !MethodHolder methodsFor: 'miscellaneous' stamp: 'sw 10/23/1999 23:01'! identifyScript | msg aPlayer | msg _ methodClass isUniClass ifTrue: [aPlayer _ methodClass someInstance. aPlayer costume ifNotNil: ['This holds code for a script named ', methodSelector, ' belonging to an object named ', aPlayer externalName] ifNil: ['This formerly held code for a script named ', methodSelector, ' for a Player who once existed but now is moribund.']] ifFalse: ['This holds code for the method named ', methodSelector, ' for class ', methodClass name]. self inform: msg! ! !MethodHolder methodsFor: 'miscellaneous' stamp: 'sw 10/21/1999 13:05'! methodClass: aClass methodSelector: aSelector methodClass _ aClass. methodSelector _ aSelector. currentCompiledMethod _ aClass compiledMethodAt: aSelector ifAbsent: [nil]! ! !MethodHolder methodsFor: 'miscellaneous' stamp: 'tk 8/30/2000 13:08'! versions "Return a VersionsBrowser (containing a list of ChangeRecords) of older versions of this method." ^ VersionsBrowser new scanVersionsOf: self compiledMethod class: self selectedClass meta: methodClass isMeta category: self selectedMessageCategoryName "(classOfMethod whichCategoryIncludesSelector: selectorOfMethod)" selector: methodSelector! ! !MethodHolder methodsFor: 'contents' stamp: 'nk 6/19/2004 16:47'! contents "Answer the contents, with due respect for my contentsSymbol" contents _ methodClass sourceCodeAt: methodSelector ifAbsent: ['']. currentCompiledMethod _ methodClass compiledMethodAt: methodSelector ifAbsent: [nil]. self showingDecompile ifTrue: [^ self decompiledSourceIntoContentsWithTempNames: Sensor leftShiftDown not ]. self showingDocumentation ifTrue: [^ self commentContents]. ^ contents _ self sourceStringPrettifiedAndDiffed asText makeSelectorBoldIn: methodClass! ! !MethodHolder methodsFor: 'contents' stamp: 'sw 10/21/1999 13:06'! contents: input notifying: aController | selector | (selector _ Parser new parseSelector: input asText) ifNil: [self inform: 'Sorry - invalid format for the method name and arguments -- cannot accept.'. ^ false]. selector == methodSelector ifFalse: [self inform: 'You cannot change the name of the method here -- it must continue to be ', methodSelector. ^ false]. selector _ methodClass compile: input asText classified: self selectedMessageCategoryName notifying: aController. selector == nil ifTrue: [^ false]. contents _ input asString copy. currentCompiledMethod _ methodClass compiledMethodAt: methodSelector. ^ true! ! !MethodHolder methodsFor: 'selection' stamp: 'sw 10/21/1999 09:40'! selectedClass ^ methodClass theNonMetaClass! ! !MethodHolder methodsFor: 'selection' stamp: 'sw 10/27/1999 14:30'! selectedClassOrMetaClass ^ methodClass! ! !MethodHolder methodsFor: 'selection' stamp: 'sw 10/21/1999 10:16'! selectedMessageCategoryName ^ methodClass organization categoryOfElement: methodSelector! ! !MethodHolder methodsFor: 'selection' stamp: 'sw 10/21/1999 09:39'! selectedMessageName ^ methodSelector! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! MethodHolder class instanceVariableNames: ''! !MethodHolder class methodsFor: 'instance creation' stamp: 'sw 10/23/2000 18:55'! makeIsolatedCodePaneForClass: aClass selector: aSelector "Create, and place in the morphic Hand, an isolated code pane bearing source code for the given class and selector" (self isolatedCodePaneForClass: aClass selector: aSelector) openInHand! ! ObjectWithDocumentation subclass: #MethodInterface instanceVariableNames: 'selector argumentVariables resultSpecification receiverType attributeKeywords defaultStatus' classVariableNames: '' poolDictionaries: '' category: 'Protocols-Kernel'! !MethodInterface commentStamp: '<historical>' prior: 0! A MethodInterface describes the interface for a single method. The most generic form is not bound to any particular class or object but rather describes an idealized interface. selector A symbol - the selector being described argumentSpecifications A list of specifications for the formal arguments of the method resultSpecification A characterization of the return value of the method userLevel attributeKeywords A list of symbols, comprising keywords that the user wishes to see on the screen for this method defaultStatus The status to apply to new instances of the class by default (#ticking, #paused, #normal, etc.) ! !MethodInterface methodsFor: 'initialization' stamp: 'sw 3/10/2001 00:38'! argumentVariables "Answer the list of argumentVariables of the interface" ^ argumentVariables ifNil: [argumentVariables _ OrderedCollection new]! ! !MethodInterface methodsFor: 'initialization' stamp: 'sw 3/9/2001 17:00'! initialize "Initialize the receiver" super initialize. attributeKeywords _ OrderedCollection new. defaultStatus _ #normal. argumentVariables _ OrderedCollection new ! ! !MethodInterface methodsFor: 'access' stamp: 'sw 3/8/2001 16:29'! companionSetterSelector "If there is a companion setter selector, anwer it, else answer nil" ^ resultSpecification ifNotNil: [resultSpecification companionSetterSelector]! ! !MethodInterface methodsFor: 'access' stamp: 'sw 9/13/2001 16:42'! elementSymbol "Answer the element symbol, for the purposes of translation" ^ selector! ! !MethodInterface methodsFor: 'access' stamp: 'sw 9/12/2001 14:05'! elementWording "Answer the wording to be shown on friendly tiles representing the receiver; by default, it is just the same as the method selector itself, but anything special-cased via #wordingForOperator:, and all getters/setters of slots, are transformed into somethingfriendlier here" ^ self translatedToPrevailingLanguage wording! ! !MethodInterface methodsFor: 'access' stamp: 'sw 4/5/2001 22:21'! printOn: aStream "print the receiver on a stream. Overridden to provide details about wording, selector, result type, and companion setter." super printOn: aStream. aStream nextPutAll: ' - wording: ''', self elementWording asString, ''' selector: #', selector asString. self argumentVariables size > 0 ifTrue: [aStream nextPutAll: 'Arguments: '. argumentVariables doWithIndex: [:aVariable :anIndex | aStream nextPutAll: 'argument #', anIndex printString, ' name = ', aVariable variableName asString, ', type = ', aVariable variableType]]. resultSpecification ifNotNil: [aStream nextPutAll: ' result type = ', resultSpecification resultType asString. resultSpecification companionSetterSelector ifNotNil: [aStream nextPutAll: ' setter = ', resultSpecification companionSetterSelector asString]] ! ! !MethodInterface methodsFor: 'access' stamp: 'sw 3/10/2001 00:38'! resultType "Answer the result type" ^ resultSpecification ifNotNil: [resultSpecification type] ifNil: [#unknown]! ! !MethodInterface methodsFor: 'access' stamp: 'sw 1/23/2001 18:37'! selector "Answer the receiver's selector" ^ selector! ! !MethodInterface methodsFor: 'initialize-release' stamp: 'ar 3/3/2001 19:38'! releaseCachedState "Sent by player"! ! ParseNode subclass: #MethodNode instanceVariableNames: 'selectorOrFalse precedence arguments block literals primitive encoder temporaries sourceText' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !MethodNode commentStamp: '<historical>' prior: 0! I am the root of the parse tree.! !MethodNode methodsFor: 'initialize-release' stamp: 'tk 8/3/1999 12:47'! block ^ block! ! !MethodNode methodsFor: 'initialize-release' stamp: 'ajh 1/24/2003 17:37'! selector: symbol selectorOrFalse _ symbol! ! !MethodNode methodsFor: 'initialize-release'! selector: selOrFalse arguments: args precedence: p temporaries: temps block: blk encoder: anEncoder primitive: prim "Initialize the receiver with respect to the arguments given." encoder _ anEncoder. selectorOrFalse _ selOrFalse. precedence _ p. arguments _ args. temporaries _ temps. block _ blk. primitive _ prim! ! !MethodNode methodsFor: 'initialize-release' stamp: 'ajh 1/22/2003 17:53'! sourceText: stringOrText sourceText _ stringOrText! ! !MethodNode methodsFor: 'code generation'! encoder ^ encoder! ! !MethodNode methodsFor: 'code generation' stamp: 'di 5/25/2000 06:48'! generate: trailer "The receiver is the root of a parse tree. Answer a CompiledMethod. The argument, trailer, is the references to the source code that is stored with every CompiledMethod." | blkSize nLits stack strm nArgs method | self generate: trailer ifQuick: [:m | method _ m. method cacheTempNames: self tempNames. ^ method]. nArgs _ arguments size. blkSize _ block sizeForEvaluatedValue: encoder. literals _ encoder allLiterals. (nLits _ literals size) > 255 ifTrue: [^self error: 'Too many literals referenced']. method _ CompiledMethod "Dummy to allocate right size" newBytes: blkSize trailerBytes: trailer nArgs: nArgs nTemps: encoder maxTemp nStack: 0 nLits: nLits primitive: primitive. strm _ ReadWriteStream with: method. strm position: method initialPC - 1. stack _ ParseStack new init. block emitForEvaluatedValue: stack on: strm. stack position ~= 1 ifTrue: [^self error: 'Compiler stack discrepancy']. strm position ~= (method size - trailer size) ifTrue: [^self error: 'Compiler code size discrepancy']. method needsFrameSize: stack size. 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)]. method cacheTempNames: self tempNames. ^ method! ! !MethodNode methodsFor: 'code generation' stamp: 'di 5/25/2000 06:45'! generate: trailer ifQuick: methodBlock | v | (primitive = 0 and: [arguments size = 0 and: [block isQuick]]) ifFalse: [^ self]. v _ block code. v < 0 ifTrue: [^ self]. v = LdSelf ifTrue: [^ methodBlock value: (CompiledMethod toReturnSelfTrailerBytes: trailer)]. (v between: LdTrue and: LdMinus1 + 3) ifTrue: [^ methodBlock value: (CompiledMethod toReturnConstant: v - LdSelf trailerBytes: trailer)]. v < ((CodeBases at: LdInstType) + (CodeLimits at: LdInstType)) ifTrue: [^ methodBlock value: (CompiledMethod toReturnField: v trailerBytes: trailer)]. v // 256 = 1 ifTrue: [^ methodBlock value: (CompiledMethod toReturnField: v \\ 256 trailerBytes: trailer)]! ! !MethodNode methodsFor: 'code generation' stamp: 'ajh 3/24/2003 14:51'! generateNative: trailer "The receiver is the root of a parse tree. Answer a CompiledMethod. The argument, trailer, is the references to the source code that is stored with every CompiledMethod." | blkSize nLits stack strm nArgs method | self generate: trailer ifQuick: [:m | method _ m. method cacheTempNames: self tempNames. ^ method]. nArgs _ arguments size. blkSize _ block sizeForEvaluatedValue: encoder. literals _ encoder allLiterals. (nLits _ literals size) > 255 ifTrue: [^self error: 'Too many literals referenced']. method _ CompiledMethod "Dummy to allocate right size" newBytes: blkSize trailerBytes: trailer nArgs: nArgs nTemps: encoder maxTemp nStack: 0 nLits: nLits primitive: primitive. strm _ ReadWriteStream with: method. strm position: method initialPC - 1. stack _ ParseStack new init. block emitForEvaluatedValue: stack on: strm. stack position ~= 1 ifTrue: [^self error: 'Compiler stack discrepancy']. strm position ~= (method size - trailer size) ifTrue: [^self error: 'Compiler code size discrepancy']. method needsFrameSize: stack size. 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)]. method cacheTempNames: self tempNames. ^ method! ! !MethodNode methodsFor: 'code generation' stamp: 'ajh 7/6/2003 15:25'! parserClass "Which parser produces this class of parse node" ^ Parser! ! !MethodNode methodsFor: 'code generation'! selector "Answer the message selector for the method represented by the receiver." (selectorOrFalse isMemberOf: Symbol) ifTrue: [^selectorOrFalse]. ^selectorOrFalse key! ! !MethodNode methodsFor: 'code generation' stamp: 'ajh 7/6/2003 15:26'! sourceMap "Answer a SortedCollection of associations of the form: pc (byte offset in me) -> sourceRange (an Interval) in source text." | methNode | methNode _ self. sourceText ifNil: [ "No source, use decompile string as source to map from" methNode _ self parserClass new parse: self decompileString class: self methodClass ]. methNode generateNative: #(0 0 0 0). "set bytecodes to map to" ^ methNode encoder sourceMap! ! !MethodNode methodsFor: 'converting' stamp: 'sw 5/20/2001 10:01'! asAltSyntaxText "Answer a string description of the parse tree whose root is the receiver, using the alternative syntax" ^ DialectStream dialect: #SQ00 contents: [:strm | self printOn: strm]! ! !MethodNode methodsFor: 'converting' stamp: 'sw 5/20/2001 10:00'! asColorizedSmalltalk80Text "Answer a colorized Smalltalk-80-syntax string description of the parse tree whose root is the receiver." ^ DialectStream dialect: #ST80 contents: [:strm | self printOn: strm]! ! !MethodNode methodsFor: 'converting' stamp: 'di 4/13/2000 21:09'! decompileString "Answer a string description of the parse tree whose root is the receiver." ^ (DialectStream dialect: #ST80 contents: [:strm | self printOn: strm]) asString ! ! !MethodNode methodsFor: 'converting' stamp: 'di 4/5/2000 10:07'! decompileText "Answer a string description of the parse tree whose root is the receiver." ^ DialectStream dialect: (Preferences printAlternateSyntax ifTrue: [#SQ00] ifFalse: [#ST80]) contents: [:strm | self printOn: strm]! ! !MethodNode methodsFor: 'printing' stamp: 'ajh 1/22/2003 17:39'! methodClass ^ encoder classEncoding! ! !MethodNode methodsFor: 'printing' stamp: 'di 6/13/2000 00:46'! printOn: aStream precedence = 1 ifTrue: [aStream nextPutAll: self selector] ifFalse: [self selector keywords with: arguments do: [:kwd :arg | aStream dialect = #SQ00 ifTrue: [(kwd endsWith: ':') ifTrue: [aStream withStyleFor: #methodSelector do: [aStream nextPutAll: kwd allButLast]. aStream nextPutAll: ' ('] ifFalse: [aStream withStyleFor: #methodSelector do: [aStream nextPutAll: kwd]. aStream space]] ifFalse: [aStream nextPutAll: kwd; space]. aStream withStyleFor: #methodArgument do: [aStream nextPutAll: arg key]. (aStream dialect = #SQ00 and: [kwd endsWith: ':']) ifTrue: [aStream nextPutAll: ') '] ifFalse: [aStream space]]]. comment == nil ifFalse: [aStream crtab: 1. self printCommentOn: aStream indent: 1]. temporaries size > 0 ifTrue: [aStream crtab: 1. aStream dialect = #SQ00 ifTrue: [aStream withStyleFor: #setOrReturn do: [aStream nextPutAll: 'Use']] ifFalse: [aStream nextPutAll: '|']. aStream withStyleFor: #temporaryVariable do: [temporaries do: [:temp | aStream space; nextPutAll: temp key]]. aStream dialect = #SQ00 ifTrue: [aStream nextPutAll: '.'] ifFalse: [aStream nextPutAll: ' |']]. primitive > 0 ifTrue: [(primitive between: 255 and: 519) ifFalse: " Dont decompile <prim> for, eg, ^ self " [aStream crtab: 1. self printPrimitiveOn: aStream]]. aStream crtab: 1. ^ block printStatementsOn: aStream indent: 0! ! !MethodNode methodsFor: 'printing' stamp: 'ar 2/13/2001 21:15'! printPrimitiveOn: aStream "Print the primitive on aStream" | primIndex primDecl | primIndex _ primitive. primIndex = 0 ifTrue: [^ self]. primIndex = 120 ifTrue: ["External call spec" ^ aStream print: encoder literals first]. aStream nextPutAll: '<primitive: '. primIndex = 117 ifTrue: [primDecl _ encoder literals at: 1. aStream nextPut: $'; nextPutAll: (primDecl at: 2); nextPut: $'. (primDecl at: 1) notNil ifTrue: [aStream nextPutAll: ' module:'; nextPut: $'; nextPutAll: (primDecl at: 1); nextPut: $']] ifFalse: [aStream print: primIndex]. aStream nextPut: $>. Smalltalk at: #Interpreter ifPresent:[:cls| aStream nextPutAll: ' "' , ((cls classPool at: #PrimitiveTable) at: primIndex + 1) , '" '].! ! !MethodNode methodsFor: 'printing' stamp: 'ajh 1/24/2003 17:41'! sourceText ^ sourceText ifNil: [self printString]! ! !MethodNode methodsFor: 'printing'! tempNames ^ encoder tempNames! ! !MethodNode methodsFor: 'tiles' stamp: 'RAA 8/20/1999 19:56'! rawSourceRanges self generate: #(0 0 0 0). ^encoder rawSourceRanges! ! Object subclass: #MethodReference instanceVariableNames: 'classSymbol classIsMeta methodSymbol stringVersion' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 07:42'! actualClass | actualClass | actualClass _ Smalltalk atOrBelow: classSymbol ifAbsent: [^nil]. classIsMeta ifTrue: [^actualClass class]. ^actualClass ! ! !MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 06:19'! asStringOrText ^stringVersion! ! !MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:11'! classIsMeta ^classIsMeta! ! !MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'! classSymbol ^classSymbol! ! !MethodReference methodsFor: 'queries' stamp: 'cwp 7/7/2003 17:44'! isValid "Answer whether the receiver represents a current selector or Comment" | aClass | (#(DoIt DoItIn:) includes: methodSymbol) ifTrue: [^ false]. (aClass _ self actualClass) ifNil: [^ false]. ^ (aClass includesSelector: methodSymbol) or: [methodSymbol == #Comment]! ! !MethodReference methodsFor: 'queries' stamp: 'RAA 5/28/2001 08:10'! methodSymbol ^methodSymbol! ! !MethodReference methodsFor: 'queries' stamp: 'sw 11/5/2001 00:53'! printOn: aStream "Print the receiver on a stream" super printOn: aStream. aStream nextPutAll: ' ', self actualClass name, ' >> ', methodSymbol! ! !MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 08:06'! setClass: aClass methodSymbol: methodSym stringVersion: aString classSymbol _ aClass theNonMetaClass name. classIsMeta _ aClass isMeta. methodSymbol _ methodSym. stringVersion _ aString.! ! !MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 07:34'! setClassAndSelectorIn: csBlock ^csBlock value: self actualClass value: methodSymbol! ! !MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 06:04'! setClassSymbol: classSym classIsMeta: isMeta methodSymbol: methodSym stringVersion: aString classSymbol _ classSym. classIsMeta _ isMeta. methodSymbol _ methodSym. stringVersion _ aString.! ! !MethodReference methodsFor: 'setting' stamp: 'RAA 5/28/2001 11:34'! setStandardClass: aClass methodSymbol: methodSym classSymbol _ aClass theNonMetaClass name. classIsMeta _ aClass isMeta. methodSymbol _ methodSym. stringVersion _ aClass name , ' ' , methodSym.! ! !MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'! stringVersion ^stringVersion! ! !MethodReference methodsFor: 'string version' stamp: 'RAA 5/29/2001 14:44'! stringVersion: aString stringVersion _ aString! ! !MethodReference methodsFor: 'comparisons' stamp: 'RAA 5/28/2001 11:56'! <= anotherMethodReference classSymbol < anotherMethodReference classSymbol ifTrue: [^true]. classSymbol > anotherMethodReference classSymbol ifTrue: [^false]. classIsMeta = anotherMethodReference classIsMeta ifFalse: [^classIsMeta not]. ^methodSymbol <= anotherMethodReference methodSymbol ! ! !MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/7/2003 13:18'! = anotherMethodReference "Answer whether the receiver and the argument represent the same object." ^ self species == anotherMethodReference species and: [self classSymbol = anotherMethodReference classSymbol] and: [self classIsMeta = anotherMethodReference classIsMeta] and: [self methodSymbol = anotherMethodReference methodSymbol]! ! !MethodReference methodsFor: 'comparisons' stamp: 'dgd 3/8/2003 11:54'! hash "Answer a SmallInteger whose value is related to the receiver's identity." ^ (self species hash bitXor: self classSymbol hash) bitXor: self methodSymbol hash! ! !MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'! category ^ self actualClass organization categoryOfElement: methodSymbol! ! !MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'! sourceCode ^ self actualClass sourceCodeAt: methodSymbol! ! Controller subclass: #ModalController instanceVariableNames: 'modeActive' classVariableNames: '' poolDictionaries: '' category: 'ST80-Framework'! !ModalController commentStamp: '<historical>' prior: 0! I am a controller that puts the poor user into a mode by not relinquishing control. However, I do pass control onto my underlings. Some underling is expected to end the mode by sending me 'close'. Watch out Larry Tesler, the mode lives on... ! !ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:05'! close "This is how we leave the mode." modeActive _ false. ! ! !ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:02'! controlInitialize modeActive _ true. ^ super controlInitialize ! ! !ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'! isControlActive ^ modeActive ! ! !ModalController methodsFor: 'as yet unclassified' stamp: 'jm 5/1/1998 07:00'! isControlWanted ^ modeActive ! ! StandardSystemView subclass: #ModalSystemWindowView instanceVariableNames: 'modalBorder' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !ModalSystemWindowView commentStamp: '<historical>' prior: 0! I am a view for a Modal System Window. I vary from StandardSystemView, of which I am a subclass in a few ways: (1) I use ModalController as my default controller; (2) When asked to update with the symbol #close, I direct the controller to close; (3) I display a slightly different title bar with no control boxes.! !ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/18/2000 20:41'! borderWidth: anObject modalBorder _ false. ^super borderWidth: anObject! ! !ModalSystemWindowView methodsFor: 'initialize-release' stamp: 'acg 2/19/2000 00:50'! initialize "Refer to the comment in View|initialize." super initialize. self borderWidth: 5. self noLabel. modalBorder _ true.! ! !ModalSystemWindowView methodsFor: 'modal dialog' stamp: 'BG 12/13/2002 11:33'! doModalDialog | savedArea | self resizeInitially. self resizeTo: ((self windowBox) align: self windowBox center with: Display boundingBox aboveCenter). savedArea _ Form fromDisplay: self windowBox. self displayEmphasized. self controller startUp. self release. savedArea displayOn: Display at: self windowOrigin. ! ! !ModalSystemWindowView methodsFor: 'controller access' stamp: 'acg 2/9/2000 00:58'! defaultControllerClass ^ModalController! ! !ModalSystemWindowView methodsFor: 'label access' stamp: 'acg 2/9/2000 08:35'! backgroundColor ^Color lightYellow! ! !ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/18/2000 20:24'! display super display. self displayLabelBackground: false. self displayLabelText. ! ! !ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/19/2000 00:59'! displayBorder "Display the receiver's border (using the receiver's borderColor)." modalBorder ifFalse: [^super displayBorder]. Display border: self displayBox widthRectangle: (1@1 corner: 2@2) rule: Form over fillColor: Color black. Display border: (self displayBox insetBy: (1@1 corner: 2@2)) widthRectangle: (4@4 corner: 3@3) rule: Form over fillColor: (Color r: 16rEA g: 16rEA b: 16rEA). ! ! !ModalSystemWindowView methodsFor: 'displaying' stamp: 'acg 2/9/2000 07:21'! displayLabelBoxes "Modal dialogs don't have closeBox or growBox." ! ! !ModalSystemWindowView methodsFor: 'model access' stamp: 'acg 2/9/2000 00:57'! update: aSymbol aSymbol = #close ifTrue: [^self controller close]. ^super update: aSymbol! ! Object subclass: #Model instanceVariableNames: 'dependents' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !Model commentStamp: '<historical>' prior: 0! Provides a superclass for classes that function as models. The only behavior provided is fast dependents maintenance, which bypasses the generic DependentsFields mechanism. 1/23/96 sw! !Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:26'! canDiscardEdits "Answer true if none of the views on this model has unaccepted edits that matter." dependents ifNil: [^ true]. ^ super canDiscardEdits ! ! !Model methodsFor: 'dependents' stamp: 'BG 10/29/2003 08:37'! containingWindow "Answer the window that holds the receiver. The dependents technique is odious and may not be airtight, if multiple windows have the same model." ^ self dependents detect: [:d | (d isKindOf: StandardSystemView) and: [d model == self]] ifNone: [nil]! ! !Model methodsFor: 'dependents' stamp: 'jm 3/24/98 15:12'! hasUnacceptedEdits "Answer true if any of the views on this model has unaccepted edits." dependents == nil ifTrue: [^ false]. ^ super hasUnacceptedEdits ! ! !Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'! myDependents ^ dependents! ! !Model methodsFor: 'dependents' stamp: 'sma 2/29/2000 19:54'! myDependents: aCollectionOrNil dependents _ aCollectionOrNil! ! !Model methodsFor: 'dependents' stamp: 'BG 10/28/2003 21:00'! topView "Find the first top view on me. Is there any danger of their being two with the same model? Any danger from ungarbage collected old views? Ask if schedulled?" dependents ifNil: [^ nil]. dependents do: [:v | v superView ifNil: [v model == self ifTrue: [^ v]]]. ^ nil ! ! !Model methodsFor: 'text links' stamp: 'RAA 5/29/2001 11:14'! addItem: classAndMethod "Make a linked message list and put this method in it" | list | self flag: #mref. "classAndMethod is a String" MessageSet parse: classAndMethod toClassAndSelector: [ :class :sel | class ifNil: [^self]. list _ OrderedCollection with: ( MethodReference new setClass: class methodSymbol: sel stringVersion: classAndMethod ). MessageSet openMessageList: list name: 'Linked by HyperText'. ] ! ! !Model methodsFor: 'menus' stamp: 'di 4/11/98 11:34'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." "default is that the editor does all" ^ otherTarget perform: selector.! ! !Model methodsFor: 'menus' stamp: 'tk 4/17/1998 17:28'! selectedClass "All owners of TextViews are asked this during a doIt" ^ nil! ! !Model methodsFor: 'menus' stamp: 'zz 3/2/2004 23:49'! step "Default for morphic models is no-op"! ! !Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'! trash "What should be displayed if a trash pane is restored to initial state" ^ ''! ! !Model methodsFor: 'menus' stamp: 'sw 12/15/2000 13:21'! trash: ignored "Whatever the user submits to the trash, it need not be saved." ^ true! ! !Model methodsFor: 'keyboard' stamp: 'BG 10/29/2003 08:54'! arrowKey: aChar from: view "Process the up and down arrows in a list pane. Note that the listView tells us what index variable, how to get the list, and how to move the index. Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | (#(1 4 11 12 30 31) includes: (keyEvent _ aChar asciiValue)) ifFalse: [ ^ self]. oldSelection := view getCurrentSelectionIndex. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view numSelectionsInView. "get this exactly??" keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [self okToChange ifTrue: [view changeModelSelection: nextSelection. "view controller moveMarker"]] ! ! !Model methodsFor: 'copying' stamp: 'tk 10/21/2002 12:59'! veryDeepFixupWith: deepCopier "See if the dependents are being copied also. If so, point at the new copies. (The dependent has self as its model.) Dependents handled in class Object, when the model is not a Model, are fixed up in Object veryDeepCopy." | originalDependents refs newDependent | super veryDeepFixupWith: deepCopier. originalDependents _ dependents. originalDependents ifNil: [ ^self. ]. dependents _ nil. refs _ deepCopier references. originalDependents do: [:originalDependent | newDependent _ refs at: originalDependent ifAbsent: []. newDependent ifNotNil: [self addDependent: newDependent]]! ]style[(29 206 19 395)f1b,f1,f1LObject veryDeepCopy;,f1! ! !Model methodsFor: 'copying' stamp: 'RB 9/20/2001 16:25'! veryDeepInner: deepCopier "Shallow copy dependents and fix them later" ! ! ModifiedEvent subclass: #ModifiedClassDefinitionEvent instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'! classVarNames ^ item classVarNames asSet! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'! instVarNames ^ item instVarNames asSet! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:30'! oldClassVarNames ^ oldItem classVarNames asSet! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:29'! oldInstVarNames ^ oldItem instVarNames asSet! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'! oldSharedPools ^ oldItem sharedPools! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:31'! sharedPools ^ item sharedPools! ! !ModifiedClassDefinitionEvent methodsFor: 'accessing' stamp: 'NS 1/20/2004 19:28'! superclass ^ item superclass! ! !ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/26/2004 09:33'! anyChanges ^ self isSuperclassModified or: [self areInstVarsModified or: [self areClassVarsModified or: [self areSharedPoolsModified]]]! ! !ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:31'! areClassVarsModified ^ self classVarNames ~= self oldClassVarNames! ! !ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:30'! areInstVarsModified ^ self instVarNames ~= self oldInstVarNames! ! !ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:32'! areSharedPoolsModified ^ self sharedPools ~= self oldSharedPools! ! !ModifiedClassDefinitionEvent methodsFor: 'testing' stamp: 'NS 1/20/2004 19:29'! isSuperclassModified ^ item superclass ~~ oldItem superclass! ! !ModifiedClassDefinitionEvent methodsFor: 'printing' stamp: 'NS 1/21/2004 09:25'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' Super: '; print: self isSuperclassModified; nextPutAll: ' InstVars: '; print: self areInstVarsModified; nextPutAll: ' ClassVars: '; print: self areClassVarsModified; nextPutAll: ' SharedPools: '; print: self areSharedPoolsModified.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ModifiedClassDefinitionEvent class instanceVariableNames: ''! !ModifiedClassDefinitionEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 11:52'! classDefinitionChangedFrom: oldClass to: newClass | instance | instance := self item: newClass kind: self classKind. instance oldItem: oldClass. ^instance! ! !ModifiedClassDefinitionEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:26'! supportedKinds "All the kinds of items that this event can take." ^ Array with: self classKind! ! AbstractEvent subclass: #ModifiedEvent instanceVariableNames: 'oldItem' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !ModifiedEvent methodsFor: 'testing' stamp: 'NS 1/19/2004 15:09'! isModified ^true! ! !ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 15:10'! printEventKindOn: aStream aStream nextPutAll: 'Modified'! ! !ModifiedEvent methodsFor: 'printing' stamp: 'NS 1/19/2004 17:57'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' oldItem: '; print: oldItem.! ! !ModifiedEvent methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:08'! oldItem ^ oldItem! ! !ModifiedEvent methodsFor: 'private-accessing' stamp: 'NS 1/19/2004 15:08'! oldItem: anItem oldItem _ anItem! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ModifiedEvent class instanceVariableNames: ''! !ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/19/2004 15:10'! changeKind ^#Modified! ! !ModifiedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:25'! supportedKinds "All the kinds of items that this event can take." ^ Array with: self classKind with: self methodKind with: self categoryKind with: self protocolKind! ! !ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/20/2004 19:37'! classDefinitionChangedFrom: oldClass to: newClass ^ ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass! ! !ModifiedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 11:40'! methodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor | instance | instance := self method: newMethod selector: aSymbol class: aClass requestor: requestor. instance oldItem: oldMethod. ^ instance! ! Timespan subclass: #Month instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !Month commentStamp: 'brp 5/13/2003 09:48' prior: 0! I represent a month.! !Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:04'! asMonth ^ self ! ! !Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'! daysInMonth ^ self duration days.! ! !Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'! index ^ self monthIndex ! ! !Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'! name ^ self monthName ! ! !Month methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:05'! printOn: aStream aStream nextPutAll: self monthName, ' ', self year printString.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Month class instanceVariableNames: ''! !Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:22'! month: month year: year "Create a Month for the given <year> and <month>. <month> may be a number or a String with the name of the month. <year> should be with 4 digits." ^ self starting: (DateAndTime year: year month: month day: 1) ! ! !Month class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:21'! readFrom: aStream | m y c | m _ (ReadWriteStream with: '') reset. [(c _ aStream next) isSeparator] whileFalse: [m nextPut: c]. [(c _ aStream next) isSeparator] whileTrue. y _ (ReadWriteStream with: '') reset. y nextPut: c. [aStream atEnd] whileFalse: [y nextPut: aStream next]. ^ self month: m contents year: y contents "Month readFrom: 'July 1998' readStream" ! ! !Month class methodsFor: 'squeak protocol' stamp: 'brp 7/1/2003 13:59'! starting: aDateAndTime duration: aDuration "Override - a each month has a defined duration" | start adjusted days | start _ aDateAndTime asDateAndTime. adjusted _ DateAndTime year: start year month: start month day: 1. days _ self daysInMonth: adjusted month forYear: adjusted year. ^ super starting: adjusted duration: (Duration days: days)! ! !Month class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:27'! daysInMonth: indexOrName forYear: yearInteger | index | index _ indexOrName isInteger ifTrue: [indexOrName] ifFalse: [self indexOfMonth: indexOrName]. ^ (DaysInMonth at: index) + ((index = 2 and: [Year isLeapYear: yearInteger]) ifTrue: [1] ifFalse: [0])! ! !Month class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 09:29'! indexOfMonth: aMonthName 1 to: 12 do: [ :i | (aMonthName, '*' match: (MonthNames at: i)) ifTrue: [^i] ]. self error: aMonthName , ' is not a recognized month name'.! ! !Month class methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 09:02'! nameOfMonth: anIndex ^ MonthNames at: anIndex.! ! Controller subclass: #MouseMenuController instanceVariableNames: 'redButtonMenu redButtonMessages' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !MouseMenuController commentStamp: '<historical>' prior: 0! 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.! !MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'! release super release. redButtonMenu release! ! !MouseMenuController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 15:54'! reset "Eliminate references to all mouse button menus." redButtonMenu _ nil. redButtonMessages _ nil! ! !MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:28'! controlActivity "Refer to the comment in Controller|controlActivity." | cursorPoint | cursorPoint _ sensor cursorPoint. super controlActivity. (cursorPoint = sensor cursorPoint and: [self viewHasCursor]) ifTrue: [sensor redButtonPressed ifTrue: [^ self redButtonActivity]. sensor yellowButtonPressed ifTrue: [^ self yellowButtonActivity]. sensor blueButtonPressed ifTrue: [^ self blueButtonActivity]]! ! !MouseMenuController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 11:24'! isControlActive "In contrast to class Controller, only blue button but not yellow button events will end the receiver's control loop." ^ self viewHasCursor and: [sensor blueButtonPressed not]! ! !MouseMenuController methodsFor: 'menu setup'! redButtonMenu: aSystemMenu redButtonMessages: anArray "Initialize the pop-up menu that should appear when the user presses the red mouse button to be aSystemMenu. The corresponding messages that should be sent are listed in the array, anArray." redButtonMenu release. redButtonMenu _ aSystemMenu. redButtonMessages _ anArray! ! !MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 15:01'! blueButtonActivity "This normally opens the window menu. It is a no-op here as only the StandardSystemController deals with that kind of menus."! ! !MouseMenuController methodsFor: 'menu messages'! performMenuMessage: aSelector "Perform a menu command by sending self the message aSelector. Default does nothing special." ^self perform: aSelector! ! !MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:56'! redButtonActivity "Determine which item in the red button pop-up menu is selected. If one is selected, then send the corresponding message to the object designated as the menu message receiver." | index | redButtonMenu ~~ nil ifTrue: [index _ redButtonMenu startUp. index ~= 0 ifTrue: [self perform: (redButtonMessages at: index)]] ifFalse: [super controlActivity]! ! !MouseMenuController methodsFor: 'menu messages' stamp: 'sma 3/11/2000 14:59'! yellowButtonActivity "This normally opens a popup menu. Determine the selected item and, if one is selected, then send the corresponding message to either the model or the receiver." ^ self pluggableYellowButtonActivity: sensor leftShiftDown! ! !MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:36'! getPluggableYellowButtonMenu: shiftKeyState ^ view getMenu: shiftKeyState! ! !MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 2/17/2002 04:35'! pluggableYellowButtonActivity: shiftKeyState "Invoke the model's popup menu." | menu | (menu _ self getPluggableYellowButtonMenu: shiftKeyState) ifNil: [sensor waitNoButton] ifNotNil: [self terminateAndInitializeAround: [menu invokeOn: model orSendTo: self]]! ! !MouseMenuController methodsFor: 'pluggable menus' stamp: 'sw 3/22/2001 12:03'! shiftedTextPaneMenuRequest "The user chose the more... branch from the text-pane menu." ^ self pluggableYellowButtonActivity: true! ! !MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'! shiftedYellowButtonActivity "Invoke the model's special popup menu." ^ self pluggableYellowButtonActivity: true! ! !MouseMenuController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 12:37'! unshiftedYellowButtonActivity "Invoke the model's normal popup menu." ^ self pluggableYellowButtonActivity: false! ! Controller subclass: #NoController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Framework'! !NoController commentStamp: '<historical>' prior: 0! I represent a controller that never wants control. I am the controller for views that are non-interactive.! !NoController methodsFor: 'basic control sequence'! startUp "I do nothing." ^self! ! !NoController methodsFor: 'control defaults'! isControlActive "Refer to the comment in Controller|isControlActive." ^false! ! !NoController methodsFor: 'control defaults'! isControlWanted "Refer to the comment in Controller|isControlWanted." ^false! ! Error subclass: #NonBooleanReceiver instanceVariableNames: 'object' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'! object ^object! ! !NonBooleanReceiver methodsFor: 'accessing' stamp: 'hmm 7/29/2001 21:30'! object: anObject object _ anObject! ! !NonBooleanReceiver methodsFor: 'signaledException' stamp: 'hmm 7/29/2001 21:37'! isResumable ^true! ! Exception subclass: #Notification instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !Notification commentStamp: '<historical>' prior: 0! A Notification is an indication that something interesting has occurred. If it is not handled, it will pass by without effect.! !Notification methodsFor: 'exceptionDescription' stamp: 'pnm 8/16/2000 15:04'! defaultAction "No action is taken. The value nil is returned as the value of the message that signaled the exception." ^nil! ! !Notification methodsFor: 'exceptionDescription' stamp: 'tfei 6/4/1999 18:17'! isResumable "Answer true. Notification exceptions by default are specified to be resumable." ^true! ! Magnitude subclass: #Number instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !Number commentStamp: '<historical>' prior: 0! Class Number holds the most general methods for dealing with numbers. Subclasses Float, Fraction, and Integer, and their subclasses, provide concrete representations of a numeric quantity. All of Number's subclasses participate in a simple type coercion mechanism that supports mixed-mode arithmetic and comparisons. It works as follows: If self<typeA> op: arg<typeB> fails because of incompatible types, then it is retried in the following guise: (arg adaptTypeA: self) op: arg adaptToTypeA. This gives the arg of typeB an opportunity to resolve the incompatibility, knowing exactly what two types are involved. If self is more general, then arg will be converted, and viceVersa. This mechanism is extensible to any new number classes that one might wish to add to Squeak. The only requirement is that every subclass of Number must support a pair of conversion methods specific to each of the other subclasses of Number.! !Number methodsFor: 'arithmetic'! * aNumber "Answer the result of multiplying the receiver by aNumber." self subclassResponsibility! ! !Number methodsFor: 'arithmetic'! + aNumber "Answer the sum of the receiver and aNumber." self subclassResponsibility! ! !Number methodsFor: 'arithmetic'! - aNumber "Answer the difference between the receiver and aNumber." self subclassResponsibility! ! !Number methodsFor: 'arithmetic'! / aNumber "Answer the result of dividing the receiver by aNumber." self subclassResponsibility! ! !Number methodsFor: 'arithmetic'! // aNumber "Integer quotient defined by division with truncation toward negative infinity. 9//4 = 2, -9//4 = -3. -0.9//0.4 = -3. \\ answers the remainder from this division." ^(self / aNumber) floor! ! !Number methodsFor: 'arithmetic'! \\ aNumber "modulo. Remainder defined in terms of //. Answer a Number with the same sign as aNumber. e.g. 9\\4 = 1, -9\\4 = 3, 9\\-4 = -3, 0.9\\0.4 = 0.1." ^self - (self // aNumber * aNumber)! ! !Number methodsFor: 'arithmetic'! abs "Answer a Number that is the absolute value (positive magnitude) of the receiver." self < 0 ifTrue: [^self negated] ifFalse: [^self]! ! !Number methodsFor: 'arithmetic'! negated "Answer a Number that is the negation of the receiver." ^0 - self! ! !Number methodsFor: 'arithmetic'! quo: aNumber "Integer quotient defined by division with truncation toward zero. -9 quo: 4 = -2, -0.9 quo: 0.4 = -2. rem: answers the remainder from this division." ^(self / aNumber) truncated! ! !Number methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! reciprocal "Answer 1 divided by the receiver. Create an error notification if the receiver is 0." #Numeric. "Changed 200/01/19 For ANSI <number> support." self = 0 ifTrue: [^ (ZeroDivide dividend: self) signal"<- Chg"]. ^ 1 / self! ! !Number methodsFor: 'arithmetic'! rem: aNumber "Remainder defined in terms of quo:. Answer a Number with the same sign as self. e.g. 9 rem: 4 = 1, -9 rem: 4 = -1. 0.9 rem: 0.4 = 0.1." ^self - ((self quo: aNumber) * aNumber)! ! !Number methodsFor: 'mathematical functions'! arcCos "The receiver is the cosine of an angle. Answer the angle measured in radians." ^self asFloat arcCos! ! !Number methodsFor: 'mathematical functions'! arcSin "The receiver is the sine of an angle. Answer the angle measured in radians." ^self asFloat arcSin! ! !Number methodsFor: 'mathematical functions'! arcTan "The receiver is the tangent of an angle. Answer the angle measured in radians." ^self asFloat arcTan! ! !Number methodsFor: 'mathematical functions' stamp: 'jsp 2/24/1999 15:20'! arcTan: denominator "The receiver is the tangent of an angle. Answer the angle measured in radians." ^(self asFloat) arcTan: denominator.! ! !Number methodsFor: 'mathematical functions'! cos "The receiver represents an angle measured in radians. Answer its cosine." ^self asFloat cos! ! !Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'! degreeCos "Answer the cosine of the receiver taken as an angle in degrees." ^ (90 + self) degreeSin! ! !Number methodsFor: 'mathematical functions' stamp: 'sd 3/5/2004 10:04'! degreeSin "Answer the sine of the receiver taken as an angle in degrees." ^ self asFloat degreesToRadians sin! ! !Number methodsFor: 'mathematical functions'! exp "Answer the exponential of the receiver as a floating point number." ^self asFloat exp! ! !Number methodsFor: 'mathematical functions' stamp: 'jm 3/27/98 06:16'! floorLog: radix "Answer the floor of the log base radix of the receiver." ^ self asFloat floorLog: radix ! ! !Number methodsFor: 'mathematical functions' stamp: 'ar 8/31/2000 20:05'! interpolateTo: aNumber at: param ^self + (aNumber - self * param)! ! !Number methodsFor: 'mathematical functions'! ln "Answer the natural log of the receiver." ^self asFloat ln! ! !Number methodsFor: 'mathematical functions' stamp: 'di 9/8/1998 17:10'! log "Answer the base-10 log of the receiver." ^self asFloat log! ! !Number methodsFor: 'mathematical functions'! log: aNumber "Answer the log base aNumber of the receiver." ^self ln / aNumber ln! ! !Number methodsFor: 'mathematical functions' stamp: 'RJ 3/15/1999 19:35'! raisedTo: aNumber "Answer the receiver raised to aNumber." aNumber isInteger ifTrue: ["Do the special case of integer power" ^ self raisedToInteger: aNumber]. self < 0 ifTrue: [ self error: self printString, ' raised to a non-integer power' ]. aNumber = 0 ifTrue: [^ 1]. "Special case of exponent=0" (self = 0) | (aNumber = 1) ifTrue: [^ self]. "Special case of exponent=1" ^ (aNumber * self ln) exp "Otherwise use logarithms"! ! !Number methodsFor: 'mathematical functions' stamp: 'RAH 4/25/2000 19:49'! raisedToInteger: operand "Answer the receiver raised to the power operand, an Integer." | count result | #Numeric. "Changed 200/01/19 For ANSI <number> support." operand isInteger ifFalse: [^ ArithmeticError signal: 'parameter is not an Integer'"<- Chg"]. operand = 0 ifTrue: [^ self class one]. operand = 1 ifTrue: [^ self]. operand < 0 ifTrue: [^ (self raisedToInteger: operand negated) reciprocal]. count := 1. [(count := count + count) < operand] whileTrue. result := self class one. [count > 0] whileTrue: [result := result * result. (operand bitAnd: count) = 0 ifFalse: [result := result * self]. count := count bitShift: -1]. ^ result! ! !Number methodsFor: 'mathematical functions'! sin "The receiver represents an angle measured in radians. Answer its sine." ^self asFloat sin! ! !Number methodsFor: 'mathematical functions'! sqrt "Answer the square root of the receiver." ^self asFloat sqrt! ! !Number methodsFor: 'mathematical functions'! squared "Answer the receiver multipled by itself." ^self * self! ! !Number methodsFor: 'mathematical functions'! tan "The receiver represents an angle measured in radians. Answer its tangent." ^self asFloat tan! ! !Number methodsFor: 'truncation and round off'! ceiling "Answer the integer nearest the receiver toward positive infinity." self <= 0.0 ifTrue: [^self truncated] ifFalse: [^self negated floor negated]! ! !Number methodsFor: 'truncation and round off' stamp: 'di 2/19/98 21:58'! detentBy: detent atMultiplesOf: grid snap: snap "Map all values that are within detent/2 of any multiple of grid to that multiple. Otherwise, if snap is true, return self, meaning that the values in the dead zone will never be returned. If snap is false, then expand the range between dead zones so that it covers the range between multiples of the grid, and scale the value by that factor." | r1 r2 | r1 _ self roundTo: grid. "Nearest multiple of grid" (self roundTo: detent) = r1 ifTrue: [^ r1]. "Snap to that multiple..." snap ifTrue: [^ self]. "...or return self" r2 _ self < r1 "Nearest end of dead zone" ifTrue: [r1 - (detent asFloat/2)] ifFalse: [r1 + (detent asFloat/2)]. "Scale values between dead zones to fill range between multiples" ^ r1 + ((self - r2) * grid asFloat / (grid - detent)) " (170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: true] (170 to: 190 by: 2) collect: [:a | a detentBy: 10 atMultiplesOf: 90 snap: false] (3.9 to: 4.1 by: 0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: true] (-3.9 to: -4.1 by: -0.02) collect: [:a | a detentBy: 0.1 atMultiplesOf: 1.0 snap: false] "! ! !Number methodsFor: 'truncation and round off'! floor "Answer the integer nearest the receiver toward negative infinity." | truncation | truncation _ self truncated. self >= 0 ifTrue: [^truncation]. self = truncation ifTrue: [^truncation] ifFalse: [^truncation - 1]! ! !Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'! fractionPart "Answer the fractional part of the receiver." #Numeric. "2000/03/04 Harmon R. Added ANSI <number> protocol" ^ self - self truncated! ! !Number methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'! integerPart "Answer the integer part of the receiver." #Numeric. "2000/03/04 Harmon R. Added ANSI <number> protocol" ^ self truncated! ! !Number methodsFor: 'truncation and round off'! reduce "If self is close to an integer, return that integer" ^ self! ! !Number methodsFor: 'truncation and round off' stamp: 'di 10/4/1999 08:08'! roundTo: quantum "Answer the nearest number that is a multiple of quantum." ^(self / quantum) rounded * quantum! ! !Number methodsFor: 'truncation and round off'! roundUpTo: aNumber "Answer the next multiple of aNumber toward infinity that is nearest the receiver." ^(self/aNumber) ceiling * aNumber! ! !Number methodsFor: 'truncation and round off'! rounded "Answer the integer nearest the receiver." ^(self + (self sign / 2)) truncated! ! !Number methodsFor: 'truncation and round off'! truncateTo: aNumber "Answer the next multiple of aNumber toward zero that is nearest the receiver." ^(self quo: aNumber) * aNumber! ! !Number methodsFor: 'truncation and round off'! truncated "Answer an integer nearest the receiver toward zero." ^self quo: 1! ! !Number methodsFor: 'testing' stamp: 'sw 9/27/2001 17:26'! basicType "Answer a symbol representing the inherent type of the receiver" ^ #Number! ! !Number methodsFor: 'testing'! even "Answer whether the receiver is an even number." ^self \\ 2 = 0! ! !Number methodsFor: 'testing' stamp: 'sw 12/30/1998 13:21'! isDivisibleBy: aNumber aNumber = 0 ifTrue: [^ false]. aNumber isInteger ifFalse: [^ false]. ^ (self \\ aNumber) = 0! ! !Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'! isInf ^ false! ! !Number methodsFor: 'testing' stamp: 'tao 4/19/98 23:33'! isInfinite ^ false! ! !Number methodsFor: 'testing' stamp: 'tao 10/10/97 16:36'! isNaN ^ false! ! !Number methodsFor: 'testing'! isNumber ^ true! ! !Number methodsFor: 'testing'! isZero ^self = 0! ! !Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:18'! negative "Answer whether the receiver is mathematically negative." ^ self < 0! ! !Number methodsFor: 'testing'! odd "Answer whether the receiver is an odd number." ^self even == false! ! !Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:17'! positive "Answer whether the receiver is positive or equal to 0. (ST-80 protocol). See also strictlyPositive" ^ self >= 0! ! !Number methodsFor: 'testing'! sign "Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0." self > 0 ifTrue: [^1]. self < 0 ifTrue: [^-1]. ^0! ! !Number methodsFor: 'testing' stamp: 'di 4/23/1998 11:02'! strictlyPositive "Answer whether the receiver is mathematically positive." ^ self > 0! ! !Number methodsFor: 'converting'! @ y "Primitive. Answer a Point whose x value is the receiver and whose y value is the argument. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 18> ^Point x: self y: y! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:43'! adaptToCollection: rcvr andSend: selector "If I am involved in arithmetic with a Collection, return a Collection of the results of each element combined with me in that expression." ^ rcvr collect: [:element | element perform: selector with: self]! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:21'! adaptToFloat: rcvr andSend: selector "If I am involved in arithmetic with a Float, convert me to a Float." ^ rcvr perform: selector with: self asFloat! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'! adaptToFraction: rcvr andSend: selector "If I am involved in arithmetic with a Fraction, convert us and evaluate exprBlock." ^ self subclassResponsibility! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'! adaptToInteger: rcvr andSend: selector "If I am involved in arithmetic with a Integer, convert us and evaluate exprBlock." ^ self subclassResponsibility! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:44'! adaptToPoint: rcvr andSend: selector "If I am involved in arithmetic with a Point, convert me to a Point." ^ rcvr perform: selector with: self@self! ! !Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToScaledDecimal: receiverScaledDecimal andSend: arithmeticOpSelector "Do any required conversion and then the arithmetic. receiverScaledDecimal arithmeticOpSelector self." #Numeric. "add 200/01/19 For ScaledDecimal support." ^ self subclassResponsibility! ! !Number methodsFor: 'converting' stamp: 'di 11/6/1998 13:45'! adaptToString: rcvr andSend: selector "If I am involved in arithmetic with a String, convert it to a Number." ^ rcvr asNumber perform: selector with: self! ! !Number methodsFor: 'converting' stamp: 'brp 5/13/2003 10:13'! asDuration ^ Duration nanoSeconds: self asInteger ! ! !Number methodsFor: 'converting'! asInteger "Answer an Integer nearest the receiver toward zero." ^self truncated! ! !Number methodsFor: 'converting' stamp: 'sw 2/16/1999 18:15'! asNumber ^ self! ! !Number methodsFor: 'converting'! asPoint "Answer a Point with the receiver as both coordinates; often used to supply the same value in two dimensions, as with symmetrical gridding or scaling." ^self @ self! ! !Number methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! asScaledDecimal: scale "Answer a scaled decimal number, with a fractional precision of scale, approximating the receiver." #Numeric. "add 200/01/19 For number protocol." ^ ScaledDecimal newFromNumber: self scale: scale! ! !Number methodsFor: 'converting' stamp: 'sw 9/8/97 16:30'! asSmallAngleDegrees "Return the receiver normalized to lie within the range (-180, 180)" | pos | pos _ self \\ 360. pos > 180 ifTrue: [pos _ pos - 360]. ^ pos "#(-500 -300 -150 -5 0 5 150 300 500 1200) collect: [:n | n asSmallAngleDegrees]"! ! !Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:12'! day ^ self sign days! ! !Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'! days ^ Duration days: self! ! !Number methodsFor: 'converting'! degreesToRadians "The receiver is assumed to represent degrees. Answer the conversion to radians." ^self asFloat degreesToRadians! ! !Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:28'! hour ^ self sign hours ! ! !Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'! hours ^ Duration hours: self! ! !Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:16'! minute ^ self sign minutes ! ! !Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:56'! minutes ^ Duration minutes: self! ! !Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:27'! nanoSecond ^ self sign nanoSeconds ! ! !Number methodsFor: 'converting' stamp: 'brp 5/16/2003 08:52'! nanoSeconds ^ Duration nanoSeconds: self.! ! !Number methodsFor: 'converting'! radiansToDegrees "The receiver is assumed to represent radians. Answer the conversion to degrees." ^self asFloat radiansToDegrees! ! !Number methodsFor: 'converting' stamp: 'brp 1/9/2004 06:17'! second ^ self sign seconds ! ! !Number methodsFor: 'converting' stamp: 'brp 5/16/2003 07:57'! seconds ^ Duration seconds: self! ! !Number methodsFor: 'converting' stamp: 'brp 5/21/2003 08:20'! sign: aNumber "Return a Number with the same sign as aNumber" ^ aNumber positive ifTrue: [self abs] ifFalse: [self abs negated].! ! !Number methodsFor: 'intervals'! to: stop "Answer an Interval from the receiver up to the argument, stop, incrementing by 1." ^Interval from: self to: stop by: 1! ! !Number methodsFor: 'intervals'! to: stop by: step "Answer an Interval from the receiver up to the argument, stop, incrementing by step." ^Interval from: self to: stop by: step! ! !Number methodsFor: 'intervals' stamp: 'tao 1/30/1999 08:58'! to: stop by: step do: aBlock "Normally compiled in-line, and therefore not overridable. Evaluate aBlock for each element of the interval (self to: stop by: step)." | nextValue | nextValue _ self. step = 0 ifTrue: [self error: 'step must be non-zero']. step < 0 ifTrue: [[stop <= nextValue] whileTrue: [aBlock value: nextValue. nextValue _ nextValue + step]] ifFalse: [[stop >= nextValue] whileTrue: [aBlock value: nextValue. nextValue _ nextValue + step]]! ! !Number methodsFor: 'intervals'! to: stop do: aBlock "Normally compiled in-line, and therefore not overridable. Evaluate aBlock for each element of the interval (self to: stop by: 1)." | nextValue | nextValue _ self. [nextValue <= stop] whileTrue: [aBlock value: nextValue. nextValue _ nextValue + 1]! ! !Number methodsFor: 'printing'! defaultLabelForInspector "Answer the default label to be used for an Inspector window on the receiver." ^ super defaultLabelForInspector, ': ', self printString! ! !Number methodsFor: 'printing' stamp: 'sw 6/29/1999 21:10'! isOrAreStringWith: aNoun | result | result _ self = 1 ifTrue: [' is one '] ifFalse: [self = 0 ifTrue: [' are no '] ifFalse: [' are ', self printString, ' ']]. result _ result, aNoun. self = 1 ifFalse: [result _ result, 's']. ^ result "#(0 1 2 98.6) do: [:num | Transcript cr; show: 'There', (num isOrAreStringWith: 'way'), ' to skin a cat']"! ! !Number methodsFor: 'printing'! printOn: aStream "Default print radix is 10" self printOn: aStream base: 10! ! !Number methodsFor: 'printing'! printStringBase: base ^ String streamContents: [:strm | self printOn: strm base: base]! ! !Number methodsFor: 'printing'! storeOn: aStream "Normal printing is OK for storing" self printOn: aStream! ! !Number methodsFor: 'printing'! storeOn: aStream base: base "Append my printed representation to aStream, incuding the base." self printOn: aStream base: base! ! !Number methodsFor: 'printing'! storeStringBase: base ^ String streamContents: [:strm | self storeOn: strm base: base]! ! !Number methodsFor: 'printing' stamp: 'sw 7/1/1998 12:33'! stringForReadout ^ self rounded printString! ! !Number methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'! closeTo: num "are these two numbers close?" | ans | num isFloat ifTrue: [^ num closeTo: self asFloat]. [ans _ self = num] ifError: [:aString :aReceiver | ^ false]. ^ ans! ! !Number methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'! byteEncode:aStream ^aStream writeNumber:self. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Number class instanceVariableNames: ''! !Number class methodsFor: 'instance creation' stamp: 'bf 12/9/1998 19:21'! readFrom: stringOrStream "Answer a number as described on aStream. The number may include a leading radix specification, as in 16rFADE" | value base aStream sign | aStream _ (stringOrStream isMemberOf: String) ifTrue: [ReadStream on: stringOrStream] ifFalse: [stringOrStream]. (aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan]. sign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1]. (aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign]. base _ 10. value _ Integer readFrom: aStream base: base. (aStream peekFor: $r) ifTrue: ["<base>r<integer>" (base _ value) < 2 ifTrue: [^self error: 'Invalid radix']. (aStream peekFor: $-) ifTrue: [sign _ sign negated]. value _ Integer readFrom: aStream base: base]. ^ self readRemainderOf: value from: aStream base: base withSign: sign.! ! !Number class methodsFor: 'instance creation' stamp: 'tao 4/23/98 12:24'! readFrom: stringOrStream base: base "Answer a number as described on aStream in the given number base." | aStream sign | aStream _ (stringOrStream isMemberOf: String) ifTrue: [ReadStream on: stringOrStream] ifFalse: [stringOrStream]. (aStream nextMatchAll: 'NaN') ifTrue: [^ Float nan]. sign _ (aStream peekFor: $-) ifTrue: [-1] ifFalse: [1]. (aStream nextMatchAll: 'Infinity') ifTrue: [^ Float infinity * sign]. ^ self readRemainderOf: (Integer readFrom: aStream base: base) from: aStream base: base withSign: sign! ! !Number class methodsFor: 'instance creation' stamp: 'RAH 4/25/2000 19:49'! readRemainderOf: integerPart from: aStream base: base withSign: sign "Read optional fractional part and exponent, and return the final result" | value fraction fractionDigits fracpos peekChar scale | #Numeric. "Changed 200/01/19 For ANSI Numeric Literals support." value := integerPart. fractionDigits := 0. (aStream peekFor: $.) ifTrue: ["<integer>.<fraction>" (aStream atEnd not and: [aStream peek digitValue between: 0 and: base - 1]) ifTrue: [fracpos := aStream position. fraction := Integer readFrom: aStream base: base. fraction := fraction asFloat / (base raisedTo: aStream position - fracpos). fractionDigits := aStream position - fracpos. value := value asFloat + fraction] ifFalse: ["oops - just <integer>." aStream skip: -1. "un-gobble the period" ^ value * sign"Number readFrom: '3r-22.2'"]]. peekChar := aStream peek. "<number>(e|d|q)<exponent>>" peekChar = $e | (peekChar = $d) | (peekChar = $q) ifTrue: [aStream next. value := value * (base raisedTo: (Integer readFrom: aStream))] ifFalse: [peekChar = $s ifTrue: ["<number>s[<scale>]" aStream next. (aStream atEnd not and: ["<number>s<scale>" aStream peek digitValue between: 0 and: 10]) ifTrue: [scale := Integer readFrom: aStream]. scale isNil ifTrue: ["<number>s" fractionDigits = 0 ifTrue: ["<integer>s" scale := 0] ifFalse: ["<integer>.<fraction>s" scale := fractionDigits]]. value := ScaledDecimal newFromNumber: value scale: scale]]. (value isFloat and: [value = 0.0 and: [sign = -1]]) ifTrue: [^ Float negativeZero] ifFalse: [^ value * sign]! ! ProtoObject subclass: #Object instanceVariableNames: '' classVariableNames: 'DependentsFields' poolDictionaries: '' category: 'Kernel-Objects'! !Object commentStamp: '<historical>' prior: 0! Object is the root class for almost all of the other classes in the class hierarchy. The exceptions are ProtoObject (the superclass of Object) and its subclasses. Class Object provides default behavior common to all normal objects, such as access, copying, comparison, error handling, message sending, and reflection. Also utility messages that all objects should respond to are defined here. Object has no instance variables, nor should any be added. This is due to several classes of objects that inherit from Object that have special implementations (SmallInteger and UndefinedObject for example) or the VM knows about and depends on the structure and layout of certain standard classes. Class Variables: DependentsFields an IdentityDictionary Provides a virtual 'dependents' field so that any object may have one or more dependent views, synchronized by the changed:/update: protocol. Note that class Model has a real slot for its dependents, and overrides the associated protocol with more efficient implementations. EventsFields an IdentityDictionary that maps each object to its dependents. Registers a message send (consisting of a selector and a receiver object) which should be performed when anEventSymbol is triggered by the receiver. Part of a new event notification framework which could eventually replace the existing changed/update mechanism. It is intended to be compatible with Dolphin Smalltalk and VSE as much as possible. Because Object is the root of the inheritance tree, methods are often defined in Object to give all objects special behaviors needed by certain subsystems or applications, or to respond to certain general test messages such as isMorph.! !Object methodsFor: 'accessing' stamp: 'sw 4/30/1998 12:18'! addInstanceVarNamed: aName withValue: aValue "Add an instance variable named aName and give it value aValue" self class addInstVarName: aName asString. self instVarAt: self class instSize put: aValue! ! !Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 11:39'! at: index "Primitive. Assumes receiver is indexable. Answer the value of an indexable element in the receiver. Fail if the argument index is not an Integer or is out of bounds. Essential. See Object documentation whatIsAPrimitive." <primitive: 60> index isInteger ifTrue: [self class isVariable ifTrue: [self errorSubscriptBounds: index] ifFalse: [self errorNotIndexable]]. index isNumber ifTrue: [^self at: index asInteger] ifFalse: [self errorNonIntegerIndex]! ! !Object methodsFor: 'accessing'! at: index modify: aBlock "Replace the element of the collection with itself transformed by the block" ^ self at: index put: (aBlock value: (self at: index))! ! !Object methodsFor: 'accessing' stamp: 'yo 6/29/2004 13:08'! at: index put: value "Primitive. Assumes receiver is indexable. Store the argument value in the indexable element of the receiver indicated by index. Fail if the index is not an Integer or is out of bounds. Or fail if the value is not of the right type for this kind of collection. Answer the value that was stored. Essential. See Object documentation whatIsAPrimitive." <primitive: 61> index isInteger ifTrue: [self class isVariable ifTrue: [(index >= 1 and: [index <= self size]) ifTrue: [self errorImproperStore] ifFalse: [self errorSubscriptBounds: index]] ifFalse: [self errorNotIndexable]]. index isNumber ifTrue: [^self at: index asInteger put: value] ifFalse: [self errorNonIntegerIndex]! ! !Object methodsFor: 'accessing'! basicAt: index "Primitive. Assumes receiver is indexable. Answer the value of an indexable element in the receiver. Fail if the argument index is not an Integer or is out of bounds. Essential. Do not override in a subclass. See Object documentation whatIsAPrimitive." <primitive: 60> index isInteger ifTrue: [self errorSubscriptBounds: index]. index isNumber ifTrue: [^self basicAt: index asInteger] ifFalse: [self errorNonIntegerIndex]! ! !Object methodsFor: 'accessing'! basicAt: index put: value "Primitive. Assumes receiver is indexable. Store the second argument value in the indexable element of the receiver indicated by index. Fail if the index is not an Integer or is out of bounds. Or fail if the value is not of the right type for this kind of collection. Answer the value that was stored. Essential. Do not override in a subclass. See Object documentation whatIsAPrimitive." <primitive: 61> index isInteger ifTrue: [(index >= 1 and: [index <= self size]) ifTrue: [self errorImproperStore] ifFalse: [self errorSubscriptBounds: index]]. index isNumber ifTrue: [^self basicAt: index asInteger put: value] ifFalse: [self errorNonIntegerIndex]! ! !Object methodsFor: 'accessing'! basicSize "Primitive. Answer the number of indexable variables in the receiver. This value is the same as the largest legal subscript. Essential. Do not override in any subclass. See Object documentation whatIsAPrimitive." <primitive: 62> "The number of indexable fields of fixed-length objects is 0" ^0 ! ! !Object methodsFor: 'accessing'! bindWithTemp: aBlock ^ aBlock value: self value: nil! ! !Object methodsFor: 'accessing' stamp: 'md 12/12/2003 16:25'! doIfNotNil: aBlock self deprecated: 'use ifNotNilDo:'. ^ self ifNotNilDo: aBlock ! ! !Object methodsFor: 'accessing' stamp: 'di 11/8/2000 21:04'! ifNotNilDo: aBlock "Evaluate the given block with the receiver as its argument." ^ aBlock value: self ! ! !Object methodsFor: 'accessing' stamp: 'ajh 1/21/2003 12:59'! in: aBlock "Evaluate the given block with the receiver as its argument." ^ aBlock value: self ! ! !Object methodsFor: 'accessing' stamp: 'sw 10/17/2000 11:15'! presenter "Answer the presenter object associated with the receiver. For morphs, there is in effect a clear containment hierarchy of presenters (accessed via their association with PasteUpMorphs); for arbitrary objects the hook is simply via the current world, at least at present." ^ self currentWorld presenter! ! !Object methodsFor: 'accessing'! readFromString: aString "Create an object based on the contents of aString." ^self readFrom: (ReadStream on: aString)! ! !Object methodsFor: 'accessing' stamp: 'di 3/29/1999 13:10'! size "Primitive. Answer the number of indexable variables in the receiver. This value is the same as the largest legal subscript. Essential. See Object documentation whatIsAPrimitive." <primitive: 62> self class isVariable ifFalse: [self errorNotIndexable]. ^ 0! ! !Object methodsFor: 'accessing'! yourself "Answer self."! ! !Object methodsFor: 'associating'! -> anObject "Answer an Association between self and anObject" ^Association new key: self value: anObject! ! !Object methodsFor: 'binding'! bindingOf: aString ^nil! ! !Object methodsFor: 'casing'! caseOf: aBlockAssociationCollection "The elements of aBlockAssociationCollection are associations between blocks. Answer the evaluated value of the first association in aBlockAssociationCollection whose evaluated key equals the receiver. If no match is found, report an error." ^ self caseOf: aBlockAssociationCollection otherwise: [self caseError] "| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z" "| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z" "The following are compiled in-line:" "#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}" "#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}"! ! !Object methodsFor: 'casing'! caseOf: aBlockAssociationCollection otherwise: aBlock "The elements of aBlockAssociationCollection are associations between blocks. Answer the evaluated value of the first association in aBlockAssociationCollection whose evaluated key equals the receiver. If no match is found, answer the result of evaluating aBlock." aBlockAssociationCollection associationsDo: [:assoc | (assoc key value = self) ifTrue: [^assoc value value]]. ^ aBlock value "| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]" "| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]" "The following are compiled in-line:" "#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]" "#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"! ! !Object methodsFor: 'class membership'! class "Primitive. Answer the object which is the receiver's class. Essential. See Object documentation whatIsAPrimitive." <primitive: 111> self primitiveFailed! ! !Object methodsFor: 'class membership' stamp: 'sw 9/27/2001 15:51'! inheritsFromAnyIn: aList "Answer whether the receiver inherits from any class represented by any element in the list. The elements of the list can be classes, class name symbols, or strings representing possible class names. This allows speculative membership tests to be made even when some of the classes may not be known to the current image, and even when their names are not interned symbols." | aClass | aList do: [:elem | Symbol hasInterned: elem asString ifTrue: [:elemSymbol | (((aClass _ Smalltalk at: elemSymbol ifAbsent: [nil]) isKindOf: Class) and: [self isKindOf: aClass]) ifTrue: [^ true]]]. ^ false " {3. true. 'olive'} do: [:token | {{#Number. #Boolean}. {Number. Boolean }. {'Number'. 'Boolean'}} do: [:list | Transcript cr; show: token asString, ' list element provided as a ', list first class name, ' - ', (token inheritsFromAnyIn: list) asString]] "! ! !Object methodsFor: 'class membership'! isKindOf: aClass "Answer whether the class, aClass, is a superclass or class of the receiver." self class == aClass ifTrue: [^true] ifFalse: [^self class inheritsFrom: aClass]! ! !Object methodsFor: 'class membership' stamp: 'sw 2/16/98 02:08'! isKindOf: aClass orOf: anotherClass "Answer whether either of the classes, aClass or anotherClass,, is a superclass or class of the receiver. A convenience; could be somewhat optimized" ^ (self isKindOf: aClass) or: [self isKindOf: anotherClass]! ! !Object methodsFor: 'class membership'! isMemberOf: aClass "Answer whether the receiver is an instance of the class, aClass." ^self class == aClass! ! !Object methodsFor: 'class membership'! respondsTo: aSymbol "Answer whether the method dictionary of the receiver's class contains aSymbol as a message selector." ^self class canUnderstand: aSymbol! ! !Object methodsFor: 'class membership' stamp: 'tk 10/21/1998 12:38'! xxxClass "For subclasses of nil, such as ObjectOut" ^ self class! ! !Object methodsFor: 'comparing'! = anObject "Answer whether the receiver and the argument represent the same object. If = is redefined in any subclass, consider also redefining the message hash." ^self == anObject! ! !Object methodsFor: 'comparing' stamp: 'tk 4/16/1999 18:26'! closeTo: anObject "Answer whether the receiver and the argument represent the same object. If = is redefined in any subclass, consider also redefining the message hash." | ans | [ans _ self = anObject] ifError: [:aString :aReceiver | ^ false]. ^ ans! ! !Object methodsFor: 'comparing'! hash "Answer a SmallInteger whose value is related to the receiver's identity. May be overridden, and should be overridden in any classes that define = " ^ self identityHash! ! !Object methodsFor: 'comparing' stamp: 'pm 9/23/97 09:36'! hashMappedBy: map "Answer what my hash would be if oops changed according to map." ^map newHashFor: self! ! !Object methodsFor: 'comparing' stamp: 'di 9/27/97 20:23'! identityHashMappedBy: map "Answer what my hash would be if oops changed according to map." ^map newHashFor: self! ! !Object methodsFor: 'comparing' stamp: 'sw 8/20/1998 12:34'! identityHashPrintString "'fred' identityHashPrintString" ^ '(', self identityHash printString, ')'! ! !Object methodsFor: 'comparing' stamp: 'ajh 2/2/2002 15:02'! literalEqual: other ^ self class == other class and: [self = other]! ! !Object methodsFor: 'comparing'! ~= anObject "Answer whether the receiver and the argument do not represent the same object." ^self = anObject == false! ! !Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'! adaptToFloat: rcvr andSend: selector "If no method has been provided for adapting an object to a Float, then it may be adequate to simply adapt it to a number." ^ self adaptToNumber: rcvr andSend: selector! ! !Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:14'! adaptToFraction: rcvr andSend: selector "If no method has been provided for adapting an object to a Fraction, then it may be adequate to simply adapt it to a number." ^ self adaptToNumber: rcvr andSend: selector! ! !Object methodsFor: 'converting' stamp: 'di 11/9/1998 12:15'! adaptToInteger: rcvr andSend: selector "If no method has been provided for adapting an object to a Integer, then it may be adequate to simply adapt it to a number." ^ self adaptToNumber: rcvr andSend: selector! ! !Object methodsFor: 'converting'! as: aSimilarClass "Create an object of class aSimilarClass that has similar contents to the receiver." ^ aSimilarClass newFrom: self! ! !Object methodsFor: 'converting' stamp: 'rw 4/27/2002 07:48'! asActionSequence ^WeakActionSequence with: self! ! !Object methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'! asActionSequenceTrappingErrors ^WeakActionSequenceTrappingErrors with: self! ! !Object methodsFor: 'converting' stamp: 'sma 5/12/2000 17:39'! asOrderedCollection "Answer an OrderedCollection with the receiver as its only element." ^ OrderedCollection with: self! ! !Object methodsFor: 'converting'! asString "Answer a string that represents the receiver." ^ self printString ! ! !Object methodsFor: 'converting' stamp: 'ajh 3/11/2003 10:27'! asStringOrText "Answer a string that represents the receiver." ^ self printString ! ! !Object methodsFor: 'converting' stamp: 'RAA 8/2/1999 12:41'! complexContents ^self! ! !Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:37'! mustBeBoolean "Catches attempts to test truth of non-Booleans. This message is sent from the VM. The sending context is rewound to just before the jump causing this exception." ^ self mustBeBooleanIn: thisContext sender! ! !Object methodsFor: 'converting' stamp: 'ajh 7/6/2003 20:40'! mustBeBooleanIn: context "context is the where the non-boolean error occurred. Rewind context to before jump then raise error." | proceedValue | context skipBackBeforeJump. proceedValue _ NonBooleanReceiver new object: self; signal: 'proceed for truth.'. ^ proceedValue ~~ false! ! !Object methodsFor: 'converting' stamp: 'sw 3/26/2001 12:12'! printDirectlyToDisplay "For debugging: write the receiver's printString directly to the display at (0, 100); senders of this are detected by the check-for-slips mechanism." self asString displayAt: 0@100 "StringMorph someInstance printDirectlyToDisplay"! ! !Object methodsFor: 'converting' stamp: 'RAA 3/31/1999 12:13'! withoutListWrapper ^self! ! !Object methodsFor: 'copying'! clone <primitive: 148> self primitiveFailed! ! !Object methodsFor: 'copying' stamp: 'ajh 8/18/2001 21:25'! copy "Answer another instance just like the receiver. Subclasses typically override postCopy; they typically do not override shallowCopy." ^self shallowCopy postCopy! ! !Object methodsFor: 'copying' stamp: 'tk 8/20/1998 16:01'! copyAddedStateFrom: anotherObject "Copy over the values of instance variables added by the receiver's class from anotherObject to the receiver. These will be remapped in mapUniClasses, if needed." self class superclass instSize + 1 to: self class instSize do: [:index | self instVarAt: index put: (anotherObject instVarAt: index)]! ! !Object methodsFor: 'copying' stamp: 'tpr 2/14/2004 21:53'! copyFrom: anotherObject "Copy to myself all instance variables I have in common with anotherObject. This is dangerous because it ignores an object's control over its own inst vars. " | mine his | <primitive: 168> mine _ self class allInstVarNames. his _ anotherObject class allInstVarNames. 1 to: (mine size min: his size) do: [:ind | (mine at: ind) = (his at: ind) ifTrue: [ self instVarAt: ind put: (anotherObject instVarAt: ind)]]. self class isVariable & anotherObject class isVariable ifTrue: [ 1 to: (self basicSize min: anotherObject basicSize) do: [:ind | self basicAt: ind put: (anotherObject basicAt: ind)]].! ! !Object methodsFor: 'copying' stamp: 'ajh 5/23/2002 00:38'! copySameFrom: otherObject "Copy to myself all instance variables named the same in otherObject. This ignores otherObject's control over its own inst vars." | myInstVars otherInstVars match | myInstVars _ self class allInstVarNames. otherInstVars _ otherObject class allInstVarNames. myInstVars doWithIndex: [:each :index | (match _ otherInstVars indexOf: each) > 0 ifTrue: [self instVarAt: index put: (otherObject instVarAt: match)]]. 1 to: (self basicSize min: otherObject basicSize) do: [:i | self basicAt: i put: (otherObject basicAt: i)]. ! ! !Object methodsFor: 'copying' stamp: 'tk 4/20/1999 14:44'! copyTwoLevel "one more level than a shallowCopy" | newObject class index | class _ self class. newObject _ self clone. newObject == self ifTrue: [^ self]. class isVariable ifTrue: [index _ self basicSize. [index > 0] whileTrue: [newObject basicAt: index put: (self basicAt: index) shallowCopy. index _ index - 1]]. index _ class instSize. [index > 0] whileTrue: [newObject instVarAt: index put: (self instVarAt: index) shallowCopy. index _ index - 1]. ^newObject! ! !Object methodsFor: 'copying'! deepCopy "Answer a copy of the receiver with its own copy of each instance variable." | newObject class index | class _ self class. (class == Object) ifTrue: [^self]. class isVariable ifTrue: [index _ self basicSize. newObject _ class basicNew: index. [index > 0] whileTrue: [newObject basicAt: index put: (self basicAt: index) deepCopy. index _ index - 1]] ifFalse: [newObject _ class basicNew]. index _ class instSize. [index > 0] whileTrue: [newObject instVarAt: index put: (self instVarAt: index) deepCopy. index _ index - 1]. ^newObject! ! !Object methodsFor: 'copying' stamp: 'hg 11/23/1999 13:43'! initialDeepCopierSize "default value is 4096; other classes may override this, esp. for smaller (=faster) sizes" ^4096! ! !Object methodsFor: 'copying' stamp: 'ajh 1/27/2003 18:45'! postCopy "self is a shallow copy, subclasses should copy fields as necessary to complete the full copy" ^ self! ! !Object methodsFor: 'copying' stamp: 'jm 11/14/97 11:08'! shallowCopy "Answer a copy of the receiver which shares the receiver's instance variables." | class newObject index | <primitive: 148> class _ self class. class isVariable ifTrue: [index _ self basicSize. newObject _ class basicNew: index. [index > 0] whileTrue: [newObject basicAt: index put: (self basicAt: index). index _ index - 1]] ifFalse: [newObject _ class basicNew]. index _ class instSize. [index > 0] whileTrue: [newObject instVarAt: index put: (self instVarAt: index). index _ index - 1]. ^ newObject! ! !Object methodsFor: 'copying' stamp: 'tk 5/13/2003 19:39'! veryDeepCopyUsing: copier "Do a complete tree copy using a dictionary. An object in the tree twice is only copied once. All references to the object in the copy of the tree will point to the new copy. Same as veryDeepCopy except copier (with dictionary) is supplied. ** do not delete this method, even if it has no callers **" | new refs newDep newModel | new _ self veryDeepCopyWith: copier. copier mapUniClasses. copier references associationsDo: [:assoc | assoc value veryDeepFixupWith: copier]. "Fix dependents" refs _ copier references. DependentsFields associationsDo: [:pair | pair value do: [:dep | (newDep _ refs at: dep ifAbsent: [nil]) ifNotNil: [ newModel _ refs at: pair key ifAbsent: [pair key]. newModel addDependent: newDep]]]. ^ new! ! !Object methodsFor: 'copying' stamp: 'tk 3/11/2003 14:12'! veryDeepCopyWith: deepCopier "Copy me and the entire tree of objects I point to. An object in the tree twice is copied once, and both references point to him. deepCopier holds a dictionary of objects we have seen. Some classes refuse to be copied. Some classes are picky about which fields get deep copied." | class index sub subAss new uc sup has mine | deepCopier references at: self ifPresent: [:newer | ^ newer]. "already did him" class _ self class. class isMeta ifTrue: [^ self]. "a class" new _ self clone. (class isSystemDefined not and: [deepCopier newUniClasses "allowed"]) ifTrue: [ uc _ deepCopier uniClasses at: class ifAbsent: [nil]. uc ifNil: [ deepCopier uniClasses at: class put: (uc _ self copyUniClassWith: deepCopier). deepCopier references at: class put: uc]. "remember" new _ uc new. new copyFrom: self]. "copy inst vars in case any are weak" deepCopier references at: self put: new. "remember" (class isVariable and: [class isPointers]) ifTrue: [index _ self basicSize. [index > 0] whileTrue: [sub _ self basicAt: index. (subAss _ deepCopier references associationAt: sub ifAbsent: [nil]) ifNil: [new basicAt: index put: (sub veryDeepCopyWith: deepCopier)] ifNotNil: [new basicAt: index put: subAss value]. index _ index - 1]]. "Ask each superclass if it wants to share (weak copy) any inst vars" new veryDeepInner: deepCopier. "does super a lot" "other superclasses want all inst vars deep copied" sup _ class. index _ class instSize. [has _ sup compiledMethodAt: #veryDeepInner: ifAbsent: [nil]. has _ has ifNil: [class isSystemDefined not "is a uniClass"] ifNotNil: [true]. mine _ sup instVarNames. has ifTrue: [index _ index - mine size] "skip inst vars" ifFalse: [1 to: mine size do: [:xx | sub _ self instVarAt: index. (subAss _ deepCopier references associationAt: sub ifAbsent: [nil]) "use association, not value, so nil is an exceptional value" ifNil: [new instVarAt: index put: (sub veryDeepCopyWith: deepCopier)] ifNotNil: [new instVarAt: index put: subAss value]. index _ index - 1]]. (sup _ sup superclass) == nil] whileFalse. new rehash. "force Sets and Dictionaries to rehash" ^ new ! ! !Object methodsFor: 'copying' stamp: 'tk 1/6/1999 17:39'! veryDeepFixupWith: deepCopier "I have no fields and no superclass. Catch the super call." ! ! !Object methodsFor: 'copying' stamp: 'tk 9/4/2001 10:30'! veryDeepInner: deepCopier "No special treatment for inst vars of my superclasses. Override when some need to be weakly copied. Object>>veryDeepCopyWith: will veryDeepCopy any inst var whose class does not actually define veryDeepInner:" ! ! !Object methodsFor: 'creation' stamp: 'sw 1/29/2002 21:43'! asMorph "Open a morph, as best one can, on the receiver" ^ self asString asMorph " 234 asMorph (ScriptingSystem formAtKey: #TinyMenu) asMorph 'fred' asMorph " ! ! !Object methodsFor: 'creation' stamp: 'sw 1/29/2002 21:45'! openAsMorph "Open a morph, as best one can, on the receiver" ^ self asMorph openInHand " 234 openAsMorph (ScriptingSystem formAtKey: #TinyMenu) openAsMorph 'fred' openAsMorph "! ! !Object methodsFor: 'dependents access' stamp: 'ar 2/11/2001 01:55'! addDependent: anObject "Make the given object one of the receiver's dependents." | dependents | dependents _ self dependents. (dependents includes: anObject) ifFalse: [self myDependents: (dependents copyWithDependent: anObject)]. ^ anObject! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:53'! breakDependents "Remove all of the receiver's dependents." self myDependents: nil! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:26'! canDiscardEdits "Answer true if none of the views on this model has unaccepted edits that matter." self dependents do: [:each | each canDiscardEdits ifFalse: [^ false]] without: self. ^ true! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:58'! dependents "Answer a collection of objects that are 'dependent' on the receiver; that is, all objects that should be notified if the receiver changes." ^ self myDependents ifNil: [#()]! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:59'! hasUnacceptedEdits "Answer true if any of the views on this object has unaccepted edits." self dependents do: [:each | each hasUnacceptedEdits ifTrue: [^ true]] without: self. ^ false! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:55'! myDependents "Private. Answer a list of all the receiver's dependents." ^ DependentsFields at: self ifAbsent: []! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 19:52'! myDependents: aCollectionOrNil "Private. Set (or remove) the receiver's dependents list." aCollectionOrNil ifNil: [DependentsFields removeKey: self ifAbsent: []] ifNotNil: [DependentsFields at: self put: aCollectionOrNil]! ! !Object methodsFor: 'dependents access' stamp: 'reThink 2/18/2001 17:06'! release "Remove references to objects that may refer to the receiver. This message should be overridden by subclasses with any cycles, in which case the subclass should also include the expression super release." self releaseActionMap! ! !Object methodsFor: 'dependents access' stamp: 'sma 2/29/2000 20:23'! removeDependent: anObject "Remove the given object as one of the receiver's dependents." | dependents | dependents _ self dependents reject: [:each | each == anObject]. self myDependents: (dependents isEmpty ifFalse: [dependents]). ^ anObject! ! !Object methodsFor: 'deprecated' stamp: 'md 12/12/2003 17:02'! beep: soundName "Make the given sound, unless the making of sound is disabled in Preferences." self deprecated: 'Use SampledSound>>playSoundNamed: instead.'. Preferences soundsEnabled ifTrue: [self playSoundNamed: soundName] ! ! !Object methodsFor: 'deprecated' stamp: 'gk 2/24/2004 08:50'! beepPrimitive "Deprecated. Beep in the absence of sound support." self deprecated: 'Use Beeper class>>beep or Beeper class>>beepPrimitive instead.'. Beeper beepPrimitive! ! !Object methodsFor: 'drag and drop' stamp: 'bh 9/16/2001 18:10'! acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph ^false.! ! !Object methodsFor: 'drag and drop' stamp: 'mir 5/16/2000 11:35'! dragAnimationFor: item transferMorph: transferMorph "Default do nothing"! ! !Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:20'! dragPassengerFor: item inMorph: dragSource ^item! ! !Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:11'! dragTransferType ^nil! ! !Object methodsFor: 'drag and drop' stamp: 'panda 4/28/2000 16:05'! dragTransferTypeForMorph: dragSource ^nil! ! !Object methodsFor: 'drag and drop' stamp: 'mir 5/8/2000 17:19'! wantsDroppedMorph: aMorph event: anEvent inMorph: destinationLM ^false! ! !Object methodsFor: 'error handling' stamp: 'sma 5/6/2000 19:35'! assert: aBlock "Throw an assertion error if aBlock does not evaluates to true." aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']! ! !Object methodsFor: 'error handling'! caseError "Report an error from an in-line or explicit case statement." self error: 'Case not found, and no otherwise clause'! ! !Object methodsFor: 'error handling' stamp: 'sma 5/28/2000 15:48'! confirm: queryString "Put up a yes/no menu with caption queryString. Answer true if the response is yes, false if no. This is a modal question--the user must respond yes or no." "nil confirm: 'Are you hungry?'" ^ PopUpMenu confirm: queryString! ! !Object methodsFor: 'error handling' stamp: 'sma 5/28/2000 15:55'! confirm: aString orCancel: cancelBlock "Put up a yes/no/cancel menu with caption aString. Answer true if the response is yes, false if no. If cancel is chosen, evaluate cancelBlock. This is a modal question--the user must respond yes or no." ^ PopUpMenu confirm: aString orCancel: cancelBlock! ! !Object methodsFor: 'error handling' stamp: 'dew 10/6/2003 18:20'! deprecated: anExplanationString "Warn that the sending method has been deprecated." Preferences showDeprecationWarnings ifTrue: [Deprecation signal: thisContext sender printString, ' has been deprecated. ', anExplanationString]! ! !Object methodsFor: 'error handling' stamp: 'dew 10/7/2003 00:26'! deprecated: anExplanationString block: aBlock "Warn that the sender has been deprecated. Answer the value of aBlock on resumption. (Note that #deprecated: is usually the preferred method.)" Preferences showDeprecationWarnings ifTrue: [Deprecation signal: thisContext sender printString, ' has been deprecated. ', anExplanationString]. ^ aBlock value. ! ! !Object methodsFor: 'error handling' stamp: 'sd 11/13/2003 21:11'! deprecated: aBlock explanation: aString "This method is OBSOLETE. Use #deprecated:block: instead." self deprecated: 'Use Object>>deprecated:block: instead of deprecated:explanation:.'. Preferences showDeprecationWarnings ifTrue: [Deprecation signal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})]. ^ aBlock value. ! ! !Object methodsFor: 'error handling' stamp: 'sd 11/13/2003 21:10'! deprecatedExplanation: aString "This method is OBSOLETE. Use #deprecated: instead." self deprecated: 'Use Object>>deprecated: instead of deprecatedExplanation:.'. Preferences showDeprecationWarnings ifTrue: [Deprecation signal: ('{1} has been deprecated. {2}' translated format: {thisContext sender printString. aString})]! ! !Object methodsFor: 'error handling' stamp: 'ajh 10/9/2001 17:21'! doesNotUnderstand: aMessage "Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector)." "Testing: (3 activeProcess)" (Preferences autoAccessors and: [self tryToDefineVariableAccess: aMessage]) ifTrue: [^ aMessage sentTo: self]. ^ MessageNotUnderstood new message: aMessage; receiver: self; signal! ! !Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:55'! error: aString "Throw a generic Error exception." ^Error new signal: aString! ! !Object methodsFor: 'error handling' stamp: 'ar 2/13/2001 20:49'! externalCallFailed "A call to an external function has failed." ^(Smalltalk at: #ExternalFunction ifAbsent:[^self error: 'FFI not installed']) externalCallFailed! ! !Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:54'! halt "This is the typical message to use for inserting breakpoints during debugging. It behaves like halt:, but does not call on halt: in order to avoid putting this message on the stack. Halt is especially useful when the breakpoint message is an arbitrary one." Halt signal! ! !Object methodsFor: 'error handling' stamp: 'tfei 4/12/1999 12:59'! halt: aString "This is the typical message to use for inserting breakpoints during debugging. It creates and schedules a Notifier with the argument, aString, as the label." Halt new signal: aString! ! !Object methodsFor: 'error handling' stamp: 'bf 9/27/1999 17:14'! handles: exception "This method exists to break an endless loop in Exception>>findHandlerFrom: if the exception is invalid" ^false! ! !Object methodsFor: 'error handling' stamp: 'hg 10/2/2001 20:49'! notify: aString "Create and schedule a Notifier with the argument as the message in order to request confirmation before a process can proceed." Warning signal: aString "nil notify: 'confirmation message'"! ! !Object methodsFor: 'error handling'! notify: aString at: location "Create and schedule a Notifier with the argument as the message in order to request confirmation before a process can proceed. Subclasses can override this and insert an error message at location within aString." self notify: aString "nil notify: 'confirmation message' at: 12"! ! !Object methodsFor: 'error handling' stamp: 'sw 5/23/2001 13:43'! notifyWithLabel: aString "Create and schedule a Notifier with aString as the window label as well as the contents of the window, in order to request confirmation before a process can proceed." Debugger openContext: thisContext label: aString contents: aString "nil notifyWithLabel: 'let us see if this works'"! ! !Object methodsFor: 'error handling'! primitiveFailed "Announce that a primitive has failed and there is no appropriate Smalltalk code to run." self error: 'a primitive has failed'! ! !Object methodsFor: 'error handling' stamp: 'AFi 2/8/2003 22:52'! shouldBeImplemented "Announce that this message should be implemented" self error: 'This message should be implemented'! ! !Object methodsFor: 'error handling'! shouldNotImplement "Announce that, although the receiver inherits this message, it should not implement it." self error: 'This message is not appropriate for this object'! ! !Object methodsFor: 'error handling' stamp: 'ajh 9/7/2002 21:20'! subclassResponsibility "This message sets up a framework for the behavior of the class' subclasses. Announce that the subclass should have implemented this message." self error: 'My subclass should have overridden ', thisContext sender methodSelector printString! ! !Object methodsFor: 'error handling' stamp: 'tk 6/18/2001 15:04'! tryToDefineVariableAccess: aMessage "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." | ask newMessage sel canDo classOrSuper | aMessage arguments size > 1 ifTrue: [^ false]. sel _ aMessage selector asString. "works for 0 args" aMessage arguments size = 1 ifTrue: [ sel last = $: ifFalse: [^ false]. sel _ sel copyWithout: $:]. canDo _ false. classOrSuper _ self class. [((classOrSuper instVarNames includes: sel) ifTrue: [canDo _ true. nil] ifFalse: [classOrSuper _ classOrSuper superclass]) == nil] whileFalse. canDo ifFalse: [classOrSuper _ self class. [((classOrSuper classVarNames includes: sel) ifTrue: [canDo _ true. nil] ifFalse: [classOrSuper _ classOrSuper superclass]) == nil] whileFalse]. canDo ifFalse: [^ false]. ask _ self confirm: 'A ', thisContext sender sender receiver class printString, ' wants to ', (aMessage arguments size = 1 ifTrue: ['write into'] ifFalse: ['read from']), ' ', sel ,' in class ', classOrSuper printString, '. Define a this access message?'. ask ifTrue: [ aMessage arguments size = 1 ifTrue: [newMessage _ aMessage selector, ' anObject ', sel, ' _ anObject'] ifFalse: [newMessage _ aMessage selector, ' ^', aMessage selector]. classOrSuper compile: newMessage classified: 'accessing' notifying: nil]. ^ ask! ! !Object methodsFor: 'evaluating' stamp: 'reThink 3/12/2001 18:14'! value ^self! ! !Object methodsFor: 'evaluating' stamp: 'reThink 2/18/2001 15:23'! valueWithArguments: aSequenceOfArguments ^self! ! !Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'! actionForEvent: anEventSelector "Answer the action to be evaluated when <anEventSelector> has been triggered." | actions | actions := self actionMap at: anEventSelector asSymbol ifAbsent: [nil]. actions ifNil: [^nil]. ^ actions asMinimalRepresentation! ! !Object methodsFor: 'events-accessing' stamp: 'nk 12/20/2002 17:48'! actionForEvent: anEventSelector ifAbsent: anExceptionBlock "Answer the action to be evaluated when <anEventSelector> has been triggered." | actions | actions := self actionMap at: anEventSelector asSymbol ifAbsent: [nil]. actions ifNil: [^anExceptionBlock value]. ^ actions asMinimalRepresentation! ! !Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 14:43'! actionMap ^EventManager actionMapFor: self! ! !Object methodsFor: 'events-accessing' stamp: 'rw 4/27/2002 08:35'! actionSequenceForEvent: anEventSelector ^(self actionMap at: anEventSelector asSymbol ifAbsent: [^WeakActionSequence new]) asActionSequence! ! !Object methodsFor: 'events-accessing' stamp: 'SqR 6/28/2001 13:19'! actionsDo: aBlock self actionMap do: aBlock! ! !Object methodsFor: 'events-accessing' stamp: 'rw 2/10/2002 13:05'! createActionMap ^IdentityDictionary new! ! !Object methodsFor: 'events-accessing' stamp: 'SqR 2/19/2001 14:04'! hasActionForEvent: anEventSelector "Answer true if there is an action associated with anEventSelector" ^(self actionForEvent: anEventSelector) notNil! ! !Object methodsFor: 'events-accessing' stamp: 'reThink 2/18/2001 15:29'! setActionSequence: actionSequence forEvent: anEventSelector | action | action := actionSequence asMinimalRepresentation. action == nil ifTrue: [self removeActionsForEvent: anEventSelector] ifFalse: [self updateableActionMap at: anEventSelector asSymbol put: action]! ! !Object methodsFor: 'events-accessing' stamp: 'reThink 2/25/2001 08:50'! updateableActionMap ^EventManager updateableActionMapFor: self! ! !Object methodsFor: 'events-registering' stamp: 'reThink 2/18/2001 15:04'! when: anEventSelector evaluate: anAction | actions | actions := self actionSequenceForEvent: anEventSelector. (actions includes: anAction) ifTrue: [^ self]. self setActionSequence: (actions copyWith: anAction) forEvent: anEventSelector! ! !Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'! when: anEventSelector send: aMessageSelector to: anObject self when: anEventSelector evaluate: (WeakMessageSend receiver: anObject selector: aMessageSelector)! ! !Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'! when: anEventSelector send: aMessageSelector to: anObject with: anArg self when: anEventSelector evaluate: (WeakMessageSend receiver: anObject selector: aMessageSelector arguments: (Array with: anArg))! ! !Object methodsFor: 'events-registering' stamp: 'rww 12/30/2002 10:37'! when: anEventSelector send: aMessageSelector to: anObject withArguments: anArgArray self when: anEventSelector evaluate: (WeakMessageSend receiver: anObject selector: aMessageSelector arguments: anArgArray)! ! !Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'! releaseActionMap EventManager releaseActionMapFor: self! ! !Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'! removeAction: anAction forEvent: anEventSelector self removeActionsSatisfying: [:action | action = anAction] forEvent: anEventSelector! ! !Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:33'! removeActionsForEvent: anEventSelector | map | map := self actionMap. map removeKey: anEventSelector asSymbol ifAbsent: []. map isEmpty ifTrue: [self releaseActionMap]! ! !Object methodsFor: 'events-removing' stamp: 'nk 8/25/2003 21:46'! removeActionsSatisfying: aBlock self actionMap keys do: [:eachEventSelector | self removeActionsSatisfying: aBlock forEvent: eachEventSelector ]! ! !Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:31'! removeActionsSatisfying: aOneArgBlock forEvent: anEventSelector self setActionSequence: ((self actionSequenceForEvent: anEventSelector) reject: [:anAction | aOneArgBlock value: anAction]) forEvent: anEventSelector! ! !Object methodsFor: 'events-removing' stamp: 'rw 7/29/2003 17:18'! removeActionsWithReceiver: anObject self actionMap copy keysDo: [:eachEventSelector | self removeActionsSatisfying: [:anAction | anAction receiver == anObject] forEvent: eachEventSelector ]! ! !Object methodsFor: 'events-removing' stamp: 'reThink 2/18/2001 15:36'! removeActionsWithReceiver: anObject forEvent: anEventSelector self removeActionsSatisfying: [:anAction | anAction receiver == anObject] forEvent: anEventSelector! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:22'! triggerEvent: anEventSelector "Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action." ^(self actionForEvent: anEventSelector) value! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 17:09'! triggerEvent: anEventSelector ifNotHandled: anExceptionBlock "Evaluate all actions registered for <anEventSelector>. Return the value of the last registered action." ^(self actionForEvent: anEventSelector ifAbsent: [^anExceptionBlock value]) value ! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'! triggerEvent: anEventSelector with: anObject ^self triggerEvent: anEventSelector withArguments: (Array with: anObject)! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 14:59'! triggerEvent: anEventSelector with: anObject ifNotHandled: anExceptionBlock ^self triggerEvent: anEventSelector withArguments: (Array with: anObject) ifNotHandled: anExceptionBlock! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'! triggerEvent: anEventSelector withArguments: anArgumentList ^(self actionForEvent: anEventSelector) valueWithArguments: anArgumentList! ! !Object methodsFor: 'events-triggering' stamp: 'reThink 2/18/2001 15:21'! triggerEvent: anEventSelector withArguments: anArgumentList ifNotHandled: anExceptionBlock ^(self actionForEvent: anEventSelector ifAbsent: [^anExceptionBlock value]) valueWithArguments: anArgumentList! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:42'! byteEncode:aStream self flattenOnStream:aStream. ! ! !Object methodsFor: 'filter streaming'! drawOnCanvas:aStream self flattenOnStream:aStream. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:31'! elementSeparator ^nil.! ! !Object methodsFor: 'filter streaming'! encodePostscriptOn:aStream self byteEncode:aStream. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:07'! flattenOnStream:aStream self writeOnFilterStream:aStream. ! ! !Object methodsFor: 'filter streaming' stamp: 'mpw 6/22/1930 22:56'! fullDrawPostscriptOn:aStream ^aStream fullDraw:self. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:51'! printOnStream:aStream self byteEncode:aStream. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:49'! putOn:aStream ^aStream nextPut:self. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:53'! storeOnStream:aStream self printOnStream:aStream. ! ! !Object methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:06'! writeOnFilterStream:aStream aStream writeObject:self. ! ! !Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:26'! actAsExecutor "Prepare the receiver to act as executor for any resources associated with it" self breakDependents! ! !Object methodsFor: 'finalization' stamp: 'ar 3/20/98 22:19'! executor "Return an object which can act as executor for finalization of the receiver" ^self shallowCopy actAsExecutor! ! !Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:10'! finalizationRegistry "Answer the finalization registry associated with the receiver." ^WeakRegistry default! ! !Object methodsFor: 'finalization' stamp: 'ar 3/21/98 16:27'! finalize "Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority."! ! !Object methodsFor: 'finalization' stamp: 'ar 3/21/98 18:38'! retryWithGC: execBlock until: testBlock "Retry execBlock as long as testBlock returns false. Do an incremental GC after the first try, a full GC after the second try." | blockValue | blockValue := execBlock value. (testBlock value: blockValue) ifTrue:[^blockValue]. Smalltalk garbageCollectMost. blockValue := execBlock value. (testBlock value: blockValue) ifTrue:[^blockValue]. Smalltalk garbageCollect. ^execBlock value.! ! !Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:14'! toFinalizeSend: aSelector to: aFinalizer with: aResourceHandle "When I am finalized (e.g., garbage collected) close the associated resource handle by sending aSelector to the appropriate finalizer (the guy who knows how to get rid of the resource). WARNING: Neither the finalizer nor the resource handle are allowed to reference me. If they do, then I will NEVER be garbage collected. Since this cannot be validated here, it is up to the client to make sure this invariant is not broken." self == aFinalizer ifTrue:[self error: 'I cannot finalize myself']. self == aResourceHandle ifTrue:[self error: 'I cannot finalize myself']. ^self finalizationRegistry add: self executor: (ObjectFinalizer new receiver: aFinalizer selector: aSelector argument: aResourceHandle)! ! !Object methodsFor: 'flagging' stamp: 'sw 8/4/97 16:49'! isThisEverCalled ^ self isThisEverCalled: thisContext sender printString! ! !Object methodsFor: 'flagging'! isThisEverCalled: msg "Send this message, with some useful printable argument, from methods or branches of methods which you believe are never reached. 2/5/96 sw" self halt: 'This is indeed called: ', msg printString! ! !Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'! logEntry Transcript show: 'Entered ', thisContext sender printString; cr. ! ! !Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:23'! logExecution Transcript show: 'Executing ', thisContext sender printString; cr. ! ! !Object methodsFor: 'flagging' stamp: 'jm 3/18/98 17:22'! logExit Transcript show: 'Exited ', thisContext sender printString; cr. ! ! !Object methodsFor: 'macpal' stamp: 'sw 5/7/1998 23:00'! codeStrippedOut: messageString "When a method is stripped out for external release, it is replaced by a method that calls this" self halt: 'Code stripped out -- ', messageString, '-- do not proceed.'! ! !Object methodsFor: 'macpal' stamp: 'sw 1/28/1999 17:31'! contentsChanged self changed: #contents! ! !Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:03'! currentEvent "Answer the current Morphic event. This method never returns nil." ^ActiveEvent ifNil:[self currentHand lastEvent]! ! !Object methodsFor: 'macpal' stamp: 'ar 3/18/2001 00:03'! currentHand "Return a usable HandMorph -- the one associated with the object's current environment. This method will always return a hand, even if it has to conjure one up as a last resort. If a particular hand is actually handling events at the moment (such as a remote hand or a ghost hand), it will be returned." ^ActiveHand! ! !Object methodsFor: 'macpal' stamp: 'BG 10/29/2003 08:43'! currentWorld "Answer a morphic world that is the current UI focus. If in an embedded world, it's that world. If in a morphic project, it's that project's world. If in an mvc project, it is the topmost morphic-mvc-window's worldMorph. If in an mvc project that has no morphic-mvc-windows, then it's just some existing worldmorph instance. If in an mvc project in a Squeak that has NO WorldMorph instances, one is created. This method will never return nil, it will always return its best effort at returning a relevant world morph, but if need be -- if there are no worlds anywhere, it will create a new one." | aView aSubview | ActiveWorld ifNotNil:[^ActiveWorld]. World ifNotNil:[^World]. aView _ ScheduledControllers controllerSatisfying: [:ctrl | (aSubview _ ctrl view firstSubView) notNil and: [aSubview model isMorph and: [aSubview model isWorldMorph]]]. ^aView ifNotNil: [aSubview model] ifNil: [].! ! !Object methodsFor: 'macpal' stamp: 'jm 5/6/1998 22:35'! flash "Do nothing." ! ! !Object methodsFor: 'macpal' stamp: 'sw 10/13/97 16:38'! ifKindOf: aClass thenDo: aBlock ^ (self isKindOf: aClass) ifTrue: [aBlock value: self]! ! !Object methodsFor: 'macpal' stamp: 'sw 6/16/1998 15:07'! instanceVariableValues "Answer a collection whose elements are the values of those instance variables of the receiver which were added by the receiver's class" | c | c _ OrderedCollection new. self class superclass instSize + 1 to: self class instSize do: [:i | c add: (self instVarAt: i)]. ^ c! ! !Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:29'! isUniversalTiles "Return true if I (my world) uses universal tiles. This message can be called in places where the current World is not known, such as when writing out a project. For more information about the project-writing subtlety addressed by this protocol, kindly contact Ted Kaehler." ^ Preferences universalTiles! ! !Object methodsFor: 'macpal' stamp: 'sw 10/24/2000 07:04'! objectRepresented "most objects represent themselves; this provides a hook for aliases to grab on to" ^ self! ! !Object methodsFor: 'macpal' stamp: 'gk 2/23/2004 20:51'! playSoundNamed: soundName "Deprecated. Play the sound with the given name." self deprecated: 'Use "SoundService default playSoundNamed: aName" instead.'. SoundService default playSoundNamed: soundName! ! !Object methodsFor: 'macpal' stamp: 'sw 5/22/2001 18:31'! refusesToAcceptCode "Answer whether the receiver is a code-bearing instrument which at the moment refuses to allow its contents to be submitted" ^ false ! ! !Object methodsFor: 'macpal' stamp: 'jm 2/24/1999 12:40'! scriptPerformer ^ self ! ! !Object methodsFor: 'macpal' stamp: 'sw 3/20/2001 13:40'! slotInfo "Answer a list of slot-information objects. Initally only provides useful info for players" ^ Dictionary new! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'! perform: aSymbol "Send the unary selector, aSymbol, to the receiver. Fail if the number of arguments expected by the selector is not zero. Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 83> ^ self perform: aSymbol withArguments: (Array new: 0)! ! !Object methodsFor: 'message handling' stamp: 'sw 10/30/1998 18:27'! perform: selector orSendTo: otherTarget "If I wish to intercept and handle selector myself, do it; else send it to otherTarget" ^ otherTarget perform: selector! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'! perform: aSymbol with: anObject "Send the selector, aSymbol, to the receiver with anObject as its argument. Fail if the number of arguments expected by the selector is not one. Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 83> ^ self perform: aSymbol withArguments: (Array with: anObject)! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:52'! perform: aSymbol with: firstObject with: secondObject "Send the selector, aSymbol, to the receiver with the given arguments. Fail if the number of arguments expected by the selector is not two. Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 83> ^ self perform: aSymbol withArguments: (Array with: firstObject with: secondObject)! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:51'! perform: aSymbol with: firstObject with: secondObject with: thirdObject "Send the selector, aSymbol, to the receiver with the given arguments. Fail if the number of arguments expected by the selector is not three. Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 83> ^ self perform: aSymbol withArguments: (Array with: firstObject with: secondObject with: thirdObject)! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 07:55'! perform: selector withArguments: argArray "Send the selector, aSymbol, to the receiver with arguments in argArray. Fail if the number of arguments expected by the selector does not match the size of argArray. Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 84> ^ self perform: selector withArguments: argArray inSuperclass: self class! ! !Object methodsFor: 'message handling' stamp: 'di 3/26/1999 08:00'! perform: selector withArguments: argArray inSuperclass: lookupClass "NOTE: This is just like perform:withArguments:, except that the message lookup process begins, not with the receivers's class, but with the supplied superclass instead. It will fail if lookupClass cannot be found among the receiver's superclasses. Primitive. Essential. See Object documentation whatIsAPrimitive." <primitive: 100> (selector isMemberOf: Symbol) ifFalse: [^ self error: 'selector argument must be a Symbol']. (selector numArgs = argArray size) ifFalse: [^ self error: 'incorrect number of arguments']. (self class == lookupClass or: [self class inheritsFrom: lookupClass]) ifFalse: [^ self error: 'lookupClass is not in my inheritance chain']. self primitiveFailed! ! !Object methodsFor: 'message handling' stamp: 'NS 1/28/2004 11:19'! withArgs: argArray executeMethod: compiledMethod "Execute compiledMethod against the receiver and args in argArray" | selector | <primitive: 188> selector _ Symbol new. self class addSelectorSilently: selector withMethod: compiledMethod. ^ [self perform: selector withArguments: argArray] ensure: [self class basicRemoveSelector: selector]! ! !Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:46'! comeFullyUpOnReload: smartRefStream "Normally this read-in object is exactly what we want to store. 7/26/96 tk" ^ self! ! !Object methodsFor: 'objects from disk' stamp: 'RAA 12/20/2000 16:51'! convertToCurrentVersion: varDict refStream: smartRefStrm "subclasses should implement if they wish to convert old instances to modern ones"! ! !Object methodsFor: 'objects from disk' stamp: 'RAA 1/10/2001 14:02'! indexIfCompact ^0 "helps avoid a #respondsTo: in publishing"! ! !Object methodsFor: 'objects from disk' stamp: 'tk 2/24/1999 11:08'! objectForDataStream: refStrm "Return an object to store on an external data stream." ^ self! ! !Object methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 12:05'! readDataFrom: aDataStream size: varsOnDisk "Fill in the fields of self based on the contents of aDataStream. Return self. Read in the instance-variables written by Object>>storeDataOn:. NOTE: This method must send beginReference: before reading any objects from aDataStream that might reference it. Allow aDataStream to have fewer inst vars. See SmartRefStream." | cntInstVars cntIndexedVars | cntInstVars _ self class instSize. self class isVariable ifTrue: [cntIndexedVars _ varsOnDisk - cntInstVars. cntIndexedVars < 0 ifTrue: [ self error: 'Class has changed too much. Define a convertxxx method']] ifFalse: [cntIndexedVars _ 0. cntInstVars _ varsOnDisk]. "OK if fewer than now" aDataStream beginReference: self. 1 to: cntInstVars do: [:i | self instVarAt: i put: aDataStream next]. 1 to: cntIndexedVars do: [:i | self basicAt: i put: aDataStream next]. "Total number read MUST be equal to varsOnDisk!!" ^ self "If we ever return something other than self, fix calls on (super readDataFrom: aDataStream size: anInteger)"! ! !Object methodsFor: 'printing' stamp: 'di 6/20/97 08:57'! fullPrintString "Answer a String whose characters are a description of the receiver." ^ String streamContents: [:s | self printOn: s]! ! !Object methodsFor: 'printing'! isLiteral "Answer whether the receiver has a literal text form recognized by the compiler." ^false! ! !Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:28'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables." self class allInstVarNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab; print: (self instVarAt: index); cr]! ! !Object methodsFor: 'printing' stamp: 'tk 10/19/2001 11:18'! longPrintOn: aStream limitedTo: sizeLimit indent: indent "Append to the argument, aStream, the names and values of all of the receiver's instance variables. Limit is the length limit for each inst var." self class allInstVarNames doWithIndex: [:title :index | indent timesRepeat: [aStream tab]. aStream nextPutAll: title; nextPut: $:; space; tab; nextPutAll: ((self instVarAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1)); cr]! ! !Object methodsFor: 'printing' stamp: 'tk 10/16/2001 19:41'! longPrintString "Answer a String whose characters are a description of the receiver." | str | str _ String streamContents: [:aStream | self longPrintOn: aStream]. "Objects without inst vars should return something" ^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! ! !Object methodsFor: 'printing' stamp: 'sw 3/7/2001 13:14'! nominallyUnsent: aSelectorSymbol "From within the body of a method which is not formally sent within the system, but which you intend to have remain in the system (for potential manual invocation, or for documentation, or perhaps because it's sent by commented-out-code that you anticipate uncommenting out someday, send this message, with the selector itself as the argument. This will serve two purposes: (1) The method will not be returned by searches for unsent selectors (because it, in a manner of speaking, sends itself). (2) You can locate all such methods by browsing senders of #nominallyUnsent:" false ifTrue: [self flag: #nominallyUnsent:] "So that this method itself will appear to be sent" ! ! !Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:31'! printOn: aStream "Append to the argument, aStream, a sequence of characters that identifies the receiver." | title | title _ self class name. aStream nextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']); nextPutAll: title! ! !Object methodsFor: 'printing' stamp: 'sma 6/1/2000 09:22'! printString "Answer a String whose characters are a description of the receiver. If you want to print without a character limit, use fullPrintString." ^ self printStringLimitedTo: 50000! ! !Object methodsFor: 'printing' stamp: 'tk 5/7/1999 16:20'! printStringLimitedTo: limit "Answer a String whose characters are a description of the receiver. If you want to print without a character limit, use fullPrintString." | limitedString | limitedString _ String streamContents: [:s | self printOn: s] limitedTo: limit. limitedString size < limit ifTrue: [^ limitedString]. ^ limitedString , '...etc...'! ! !Object methodsFor: 'printing' stamp: 'sw 10/17/2000 11:16'! reportableSize "Answer a string that reports the size of the receiver -- useful for showing in a list view, for example" ^ (self basicSize + self class instSize) printString! ! !Object methodsFor: 'printing'! storeOn: aStream "Append to the argument aStream a sequence of characters that is an expression whose evaluation creates an object similar to the receiver." aStream nextPut: $(. self class isVariable ifTrue: [aStream nextPutAll: '(', self class name, ' basicNew: '; store: self basicSize; nextPutAll: ') '] ifFalse: [aStream nextPutAll: self class name, ' basicNew']. 1 to: self class instSize do: [:i | aStream nextPutAll: ' instVarAt: '; store: i; nextPutAll: ' put: '; store: (self instVarAt: i); nextPut: $;]. 1 to: self basicSize do: [:i | aStream nextPutAll: ' basicAt: '; store: i; nextPutAll: ' put: '; store: (self basicAt: i); nextPut: $;]. aStream nextPutAll: ' yourself)' ! ! !Object methodsFor: 'printing' stamp: 'di 6/20/97 09:12'! storeString "Answer a String representation of the receiver from which the receiver can be reconstructed." ^ String streamContents: [:s | self storeOn: s]! ! !Object methodsFor: 'printing' stamp: 'sw 5/2/1998 13:55'! stringForReadout ^ self stringRepresentation! ! !Object methodsFor: 'printing'! stringRepresentation "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" ^ self printString ! ! !Object methodsFor: 'scripting' stamp: 'ar 3/17/2001 20:11'! adaptedToWorld: aWorld "If I refer to a world or a hand, return the corresponding items in the new world." ^self! ! !Object methodsFor: 'scripting' stamp: 'RAA 3/5/2001 18:13'! contentsGetz: x self contents: x! ! !Object methodsFor: 'scripting' stamp: 'sw 3/10/2000 13:57'! defaultFloatPrecisionFor: aGetSelector "Answer a number indicating the default float precision to be used in a numeric readout for which the receiver is the model." ^ 1! ! !Object methodsFor: 'scripting' stamp: 'RAA 3/9/2001 17:08'! evaluateUnloggedForSelf: aCodeString ^Compiler evaluate: aCodeString for: self logged: false! ! !Object methodsFor: 'scripting' stamp: 'sw 2/6/2003 18:05'! methodInterfacesForCategory: aCategorySymbol inVocabulary: aVocabulary limitClass: aLimitClass "Return a list of methodInterfaces for the receiver in the given category, given a vocabulary. aCategorySymbol is the inherent category symbol, not necessarily the wording as expressed in the vocabulary." | categorySymbol | categorySymbol _ aCategorySymbol asSymbol. (categorySymbol == ScriptingSystem nameForInstanceVariablesCategory) ifTrue: "user-defined instance variables" [^ self methodInterfacesForInstanceVariablesCategoryIn: aVocabulary]. (categorySymbol == ScriptingSystem nameForScriptsCategory) ifTrue: "user-defined scripts" [^ self methodInterfacesForScriptsCategoryIn: aVocabulary]. ^ (self usableMethodInterfacesIn: (aVocabulary methodInterfacesInCategory: (aVocabulary translatedWordingFor: categorySymbol) forInstance: self ofClass: self class limitClass: aLimitClass)) "all others"! ! !Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:54'! methodInterfacesForInstanceVariablesCategoryIn: aVocabulary "Return a collection of methodInterfaces for the instance-variables category. The vocabulary parameter, at present anyway, is not used. And for non-players, the method is at present vacuous in any case" ^ OrderedCollection new! ! !Object methodsFor: 'scripting' stamp: 'sw 8/3/2001 13:53'! methodInterfacesForScriptsCategoryIn: aVocabulary "Answer a list of method interfaces for the category #scripts, as seen in a viewer or other tool. The vocabulary argument is not presently used. Also, at present, only Players really do anyting interesting here." ^ OrderedCollection new! ! !Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'! selfWrittenAsIll ^self! ! !Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'! selfWrittenAsIm ^self! ! !Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'! selfWrittenAsMe ^self! ! !Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:37'! selfWrittenAsMy ^self! ! !Object methodsFor: 'scripting' stamp: 'RAA 2/16/2001 19:38'! selfWrittenAsThis ^self! ! !Object methodsFor: 'system primitives'! asOop "Primitive. Answer a SmallInteger whose value is half of the receiver's object pointer (interpreting object pointers as 16-bit signed quantities). Fail if the receiver is a SmallInteger. Essential. See Object documentation whatIsAPrimitive." <primitive: 75> self primitiveFailed! ! !Object methodsFor: 'system primitives' stamp: 'di 1/9/1999 15:19'! becomeForward: otherObject "Primitive. All variables in the entire system that used to point to the receiver now point to the argument. Fails if either argument is a SmallInteger." (Array with: self) elementsForwardIdentityTo: (Array with: otherObject)! ! !Object methodsFor: 'system primitives' stamp: 'zz 3/3/2004 23:53'! becomeForward: otherObject copyHash: copyHash "Primitive. All variables in the entire system that used to point to the receiver now point to the argument. If copyHash is true, the argument's identity hash bits will be set to those of the receiver. Fails if either argument is a SmallInteger." (Array with: self) elementsForwardIdentityTo: (Array with: otherObject) copyHash: copyHash! ! !Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 10:59'! className "Answer a string characterizing the receiver's class, for use in list views for example" ^ self class name asString! ! !Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:04'! creationStamp "Answer a string which reports the creation particulars of the receiver. Intended perhaps for list views, but this is presently a feature not easily accessible" ^ '<no creation stamp>'! ! !Object methodsFor: 'system primitives'! instVarAt: index "Primitive. Answer a fixed variable in an object. The numbering of the variables corresponds to the named instance variables. Fail if the index is not an Integer or is not the index of a fixed variable. Essential. See Object documentation whatIsAPrimitive." <primitive: 73> "Access beyond fixed variables." ^self basicAt: index - self class instSize ! ! !Object methodsFor: 'system primitives'! instVarAt: anInteger put: anObject "Primitive. Store a value into a fixed variable in the receiver. The numbering of the variables corresponds to the named instance variables. Fail if the index is not an Integer or is not the index of a fixed variable. Answer the value stored as the result. Using this message violates the principle that each object has sovereign control over the storing of values into its instance variables. Essential. See Object documentation whatIsAPrimitive." <primitive: 74> "Access beyond fixed fields" ^self basicAt: anInteger - self class instSize put: anObject! ! !Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:09'! instVarNamed: aString "Return the value of the instance variable in me with that name. Slow and unclean, but very useful. " ^ self instVarAt: (self class allInstVarNames indexOf: aString asString) ! ! !Object methodsFor: 'system primitives' stamp: 'sw 10/16/2000 11:10'! instVarNamed: aString put: aValue "Store into the value of the instance variable in me of that name. Slow and unclean, but very useful. " ^ self instVarAt: (self class allInstVarNames indexOf: aString asString) put: aValue ! ! !Object methodsFor: 'system primitives' stamp: 'sw 10/17/2000 11:12'! oopString "Answer a string that represents the oop of the receiver" ^ self asOop printString! ! !Object methodsFor: 'system primitives' stamp: 'ar 3/2/2001 01:34'! primitiveChangeClassTo: anObject "Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. Note: The primitive will fail in most cases that you think might work. This is mostly because of a) the difference between compact and non-compact classes, and b) because of differences in the format. As an example, '(Array new: 3) primitiveChangeClassTo: Morph basicNew' would fail for three of the reasons mentioned above. Array is compact, Morph is not (failure #1). Array is variable and Morph is fixed (different format - failure #2). Morph is a fixed-field-only object and the array is too short (failure #3). The facility is really provided for certain, very specific applications (mostly related to classes changing shape) and not for casual use." <primitive: 115> self primitiveFailed! ! !Object methodsFor: 'system primitives'! someObject "Primitive. Answer the first object in the enumeration of all objects." <primitive: 138> self primitiveFailed.! ! !Object methodsFor: 'testing' stamp: 'sw 9/26/2001 11:58'! basicType "Answer a symbol representing the inherent type of the receiver" ^ #Object! ! !Object methodsFor: 'testing' stamp: 'sw 5/3/2001 16:19'! beViewed "Open up a viewer on the receiver. The Presenter is invited to decide just how to present this viewer" self uniqueNameForReference. "So the viewer will have something nice to refer to" self presenter viewObject: self! ! !Object methodsFor: 'testing' stamp: 'sw 10/16/2000 11:01'! costumes "Answer a list of costumes associated with the receiver. The appearance of this method in class Object serves only as a backstop, probably only transitionally" ^ nil! ! !Object methodsFor: 'testing' stamp: 'sw 1/12/98 18:09'! haltIfNil! ! !Object methodsFor: 'testing' stamp: 'ar 7/9/1999 18:18'! isBehavior "Return true if the receiver is a behavior. Note: Do not override in any class except behavior." ^false! ! !Object methodsFor: 'testing' stamp: 'ajh 1/21/2003 13:15'! isBlock ^ false! ! !Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'! isBlockClosure ^ false! ! !Object methodsFor: 'testing' stamp: 'ar 8/17/1999 19:43'! isCollection "Return true if the receiver is some sort of Collection and responds to basic collection messages such as #size and #do:" ^false! ! !Object methodsFor: 'testing'! isColor "Answer true if receiver is a Color. False by default." ^ false ! ! !Object methodsFor: 'testing' stamp: 'nk 4/17/2004 19:43'! isColorForm ^false! ! !Object methodsFor: 'testing' stamp: 'md 11/21/2003 12:14'! isCompiledMethod ^ false! ! !Object methodsFor: 'testing' stamp: 'di 11/9/1998 09:38'! isFloat "Overridden to return true in Float, natch" ^ false! ! !Object methodsFor: 'testing' stamp: 'ar 10/30/2000 23:22'! isForm ^false! ! !Object methodsFor: 'testing' stamp: 'len 1/13/98 21:18'! isFraction "Answer true if the receiver is a Fraction." ^ false! ! !Object methodsFor: 'testing' stamp: 'rhi 8/14/2003 08:51'! isHeap ^ false! ! !Object methodsFor: 'testing'! isInteger "Overridden to return true in Integer." ^ false! ! !Object methodsFor: 'testing' stamp: 'rhi 8/12/2003 09:52'! isInterval ^ false! ! !Object methodsFor: 'testing' stamp: 'nk 4/25/2002 08:04'! isMessageSend ^false ! ! !Object methodsFor: 'testing'! isMorph ^ false! ! !Object methodsFor: 'testing' stamp: 'ar 9/13/2000 15:37'! isMorphicEvent ^false! ! !Object methodsFor: 'testing' stamp: 'gm 2/22/2003 12:56'! isMorphicModel "Return true if the receiver is a morphic model" ^false ! ! !Object methodsFor: 'testing'! isNumber "Overridden to return true in Number, natch" ^ false! ! !Object methodsFor: 'testing' stamp: 'di 11/6/1998 08:04'! isPoint "Overridden to return true in Point." ^ false! ! !Object methodsFor: 'testing' stamp: 'ikp 9/26/97 14:45'! isPseudoContext ^false! ! !Object methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'! isStream "Return true if the receiver responds to the stream protocol" ^false ! ! !Object methodsFor: 'testing' stamp: 'sma 6/15/2000 15:48'! isString "Overridden to return true in String, natch" ^ false! ! !Object methodsFor: 'testing' stamp: 'md 4/30/2003 15:30'! isSymbol ^ false ! ! !Object methodsFor: 'testing' stamp: 'jam 3/9/2003 15:10'! isSystemWindow "answer whatever the receiver is a SystemWindow" ^ false! ! !Object methodsFor: 'testing'! isText ^ false! ! !Object methodsFor: 'testing' stamp: 'tk 10/21/97 12:45'! isTransparent ^ false! ! !Object methodsFor: 'testing' stamp: 'ar 8/14/2001 23:19'! isVariableBinding "Return true if I represent a literal variable binding" ^false ! ! !Object methodsFor: 'testing' stamp: 'ls 7/14/1998 21:45'! isWebBrowser "whether this object is a web browser. See class: Scamper" ^false! ! !Object methodsFor: 'testing' stamp: 'sw 10/27/2000 06:58'! knownName "If a formal name has been handed out for this object, answer it, else nil" ^ Preferences capitalizedReferences ifTrue: [References keyAtValue: self ifAbsent: [nil]] ifFalse: [nil]! ! !Object methodsFor: 'testing' stamp: 'sw 9/27/96'! name "Answer a name for the receiver. This is used generically in the title of certain inspectors, such as the referred-to inspector, and specificially by various subsystems. By default, we let the object just print itself out.. " ^ self printString! ! !Object methodsFor: 'testing' stamp: 'sw 11/19/2001 13:28'! nameForViewer "Answer a name to be shown in a Viewer that is viewing the receiver" | aName | (aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName]. (aName _ self knownName) ifNotNil: [^ aName]. ^ [(self asString copyWithout: Character cr) truncateTo: 27] ifError: [:msg :rcvr | ^ self class name printString]! ! !Object methodsFor: 'testing'! notNil "Coerces nil to false and everything else to true." ^true! ! !Object methodsFor: 'testing' stamp: 'sw 2/27/2002 14:55'! renameTo: newName "If the receiver has an inherent idea about its own name, it should take action here. Any object that might be pointed to in the References dictionary might get this message sent to it upon reload"! ! !Object methodsFor: 'testing' stamp: 'sw 1/18/2001 13:43'! showDiffs "Answer whether the receiver, serving as the model of a text-bearing entity, is 'showing differences' -- if it is, the editor may wish to show special feedback" ^ false! ! !Object methodsFor: 'testing' stamp: 'sw 10/20/1999 14:52'! stepAt: millisecondClockValue in: aWindow ^ self stepIn: aWindow! ! !Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:16'! stepIn: aWindow ^ self step! ! !Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:21'! stepTime ^ 1000 "milliseconds -- default backstop for objects serving as models of system windows"! ! !Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:22'! stepTimeIn: aSystemWindow ^ 1000 "milliseconds -- default backstop for objects serving as models of system windows"! ! !Object methodsFor: 'testing' stamp: 'sw 5/3/2001 18:22'! vocabularyDemanded "Answer a vocabulary that the receiver insists be used when it is looked at in a Viewer. This allows specific classes to insist on specific custom vocabularies" ^ nil! ! !Object methodsFor: 'testing' stamp: 'sw 11/13/2001 07:26'! wantsDiffFeedback "Answer whether the receiver, serving as the model of a text-bearing entity, would like for 'diffs' green pane-border feedback to be shown" ^ false! ! !Object methodsFor: 'testing' stamp: 'di 1/8/1999 15:04'! wantsSteps "Overridden by morphic classes whose instances want to be stepped, or by model classes who want their morphic views to be stepped." ^ false! ! !Object methodsFor: 'testing' stamp: 'sw 10/19/1999 08:26'! wantsStepsIn: aSystemWindow ^ self wantsSteps! ! !Object methodsFor: 'translation support'! inline: inlineFlag "For translation only; noop when running in Smalltalk."! ! !Object methodsFor: 'translation support'! var: varSymbol declareC: declString "For translation only; noop when running in Smalltalk."! ! !Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'! capturedState "May be overridden in subclasses." ^ self shallowCopy ! ! !Object methodsFor: 'undo' stamp: 'di 9/12/2000 08:15'! redoFromCapturedState: st "May be overridden in subclasses. See also capturedState" self undoFromCapturedState: st "Simple cases are symmetric" ! ! !Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'! refineRedoTarget: target selector: aSymbol arguments: arguments in: refineBlock "Any object can override this method to refine its redo specification" ^ refineBlock value: target value: aSymbol value: arguments! ! !Object methodsFor: 'undo' stamp: 'sw 11/16/2000 14:42'! refineUndoTarget: target selector: aSymbol arguments: arguments in: refineBlock "Any object can override this method to refine its undo specification" ^ refineBlock value: target value: aSymbol value: arguments! ! !Object methodsFor: 'undo' stamp: 'di 9/11/2000 20:32'! undoFromCapturedState: st "May be overridden in subclasses. See also capturedState" self copyFrom: st ! ! !Object methodsFor: 'updating'! changed "Receiver changed in a general way; inform all the dependents by sending each dependent an update: message." self changed: self! ! !Object methodsFor: 'updating'! changed: aParameter "Receiver changed. The change is denoted by the argument aParameter. Usually the argument is a Symbol that is part of the dependent's change protocol. Inform all of the dependents." self dependents do: [:aDependent | aDependent update: aParameter]! ! !Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:12'! changed: anAspect with: anObject "Receiver changed. The change is denoted by the argument anAspect. Usually the argument is a Symbol that is part of the dependent's change protocol. Inform all of the dependents. Also pass anObject for additional information." self dependents do: [:aDependent | aDependent update: anAspect with: anObject]! ! !Object methodsFor: 'updating' stamp: 'sw 10/12/1999 18:15'! handledListVerification "When a self-updating PluggableListMorph lazily checks to see the state of affairs, it first gives its model an opportunity to handle the list verification itself (this is appropriate for some models, such as VersionsBrowser); if a list's model has indeed handled things itself, it returns true here" ^ false! ! !Object methodsFor: 'updating' stamp: 'sw 10/31/1999 00:15'! noteSelectionIndex: anInteger for: aSymbol "backstop"! ! !Object methodsFor: 'updating'! okToChange "Allows a controller to ask this of any model" ^ true! ! !Object methodsFor: 'updating' stamp: 'sma 2/29/2000 20:05'! update: aParameter "Receive a change notice from an object of whom the receiver is a dependent. The default behavior is to do nothing; a subclass might want to change itself in some way." ^ self! ! !Object methodsFor: 'updating' stamp: 'nk 2/17/2004 11:13'! update: anAspect with: anObject "Receive a change notice from an object of whom the receiver is a dependent. The default behavior is to call update:, which by default does nothing; a subclass might want to change itself in some way." ^ self update: anAspect! ! !Object methodsFor: 'updating' stamp: 'sw 10/19/1999 14:39'! updateListsAndCodeIn: aWindow self canDiscardEdits ifFalse: [^ self]. aWindow updatablePanes do: [:aPane | aPane verifyContents]! ! !Object methodsFor: 'updating' stamp: 'jm 8/20/1998 18:26'! windowIsClosing "This message is used to inform a models that its window is closing. Most models do nothing, but some, such as the Debugger, must do some cleanup. Note that this mechanism must be used with care by models that support multiple views, since one view may be closed while others left open." ! ! !Object methodsFor: 'user interface' stamp: 'sw 10/4/1999 08:13'! addModelItemsToWindowMenu: aMenu "aMenu is being constructed to be presented to the user in response to the user's pressing on the menu widget in the title bar of a morphic window. Here, the model is given the opportunity to add any model-specific items to the menu, whose default target is the SystemWindow itself."! ! !Object methodsFor: 'user interface' stamp: 'sw 10/5/1998 14:39'! addModelMenuItemsTo: aCustomMenu forMorph: aMorph hand: aHandMorph "The receiver serves as the model for aMorph; a menu is being constructed for the morph, and here the receiver is able to add its own items" ! ! !Object methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:43'! asExplorerString ^ self printString! ! !Object methodsFor: 'user interface' stamp: 'gk 2/24/2004 08:49'! beep "Deprecated." self deprecated: 'Use Beeper class>>beep instead.'. Beeper beep! ! !Object methodsFor: 'user interface' stamp: 'sw 7/13/1999 15:53'! defaultBackgroundColor "Answer the color to be used as the base window color for a window whose model is an object of the receiver's class" ^ Preferences windowColorFor: self class name! ! !Object methodsFor: 'user interface'! defaultLabelForInspector "Answer the default label to be used for an Inspector window on the receiver." ^ self class name! ! !Object methodsFor: 'user interface' stamp: 'sw 8/15/97 17:25'! fullScreenSize "Answer the size to which a window displaying the receiver should be set" | adj | adj _ (3 * Preferences scrollBarWidth) @ 0. ^ Rectangle origin: adj extent: (DisplayScreen actualScreenSize - adj)! ! !Object methodsFor: 'user interface' stamp: 'RAA 6/21/1999 11:27'! hasContentsInExplorer ^self basicSize > 0 or: [self class allInstVarNames isEmpty not] ! ! !Object methodsFor: 'user interface' stamp: 'sma 5/28/2000 15:59'! inform: aString "Display a message for the user to read and then dismiss. 6/9/96 sw" aString isEmptyOrNil ifFalse: [PopUpMenu inform: aString]! ! !Object methodsFor: 'user interface'! initialExtent "Answer the desired extent for the receiver when a view on it is first opened on the screen. 5/22/96 sw: in the absence of any override, obtain from RealEstateAgent" ^ RealEstateAgent standardWindowExtent! ! !Object methodsFor: 'user interface'! inspectWithLabel: aLabel Inspector openOn: self withEvalPane: true withLabel: aLabel! ! !Object methodsFor: 'user interface' stamp: 'sw 6/12/2001 11:09'! launchPartVia: aSelector "Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins" | aMorph | aMorph _ self perform: aSelector. aMorph setProperty: #beFullyVisibleAfterDrop toValue: true. aMorph openInHand! ! !Object methodsFor: 'user interface' stamp: 'ar 12/14/2001 20:08'! launchPartVia: aSelector label: aString "Obtain a morph by sending aSelector to self, and attach it to the morphic hand. This provides a general protocol for parts bins" | aMorph | aMorph _ self perform: aSelector. aMorph setNameTo: aString. aMorph setProperty: #beFullyVisibleAfterDrop toValue: true. aMorph openInHand! ! !Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:26'! modelSleep "A window with me as model is being exited or collapsed or closed. Default response is no-op" ! ! !Object methodsFor: 'user interface' stamp: 'di 5/11/1999 22:01'! modelWakeUp "A window with me as model is being entered or expanded. Default response is no-op" ! ! !Object methodsFor: 'user interface' stamp: 'sw 10/16/1999 22:45'! modelWakeUpIn: aWindow "A window with me as model is being entered or expanded. Default response is no-op" self modelWakeUp! ! !Object methodsFor: 'user interface' stamp: 'sw 3/8/1999 15:27'! mouseUpBalk: evt "A button I own got a mouseDown, but the user moved out before letting up. Certain kinds of objects (so-called 'radio buttons', for example, and other structures that must always have some selection, e.g. PaintBoxMorph) wish to take special action in this case; this default does nothing." ! ! !Object methodsFor: 'user interface' stamp: 'jcg 11/1/2001 13:13'! notYetImplemented self inform: 'Not yet implemented (', thisContext sender printString, ')'! ! !Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'! windowActiveOnFirstClick "Return true if my window should be active on first click." ^ false! ! !Object methodsFor: 'user interface' stamp: 'di 6/10/1998 15:06'! windowReqNewLabel: labelString "My window's title has been edited. Return true if this is OK, and override for further behavior." ^ true! ! !Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:35'! assureUniClass "If the receiver is not yet an instance of a uniclass, create a uniclass for it and make the receiver become an instance of that class." | anInstance | self belongsToUniClass ifTrue: [^ self]. anInstance _ self class instanceOfUniqueClass. self become: (self as: anInstance class). ^ anInstance! ! !Object methodsFor: 'viewer' stamp: 'sw 10/16/2000 10:41'! belongsToUniClass "Answer whether the receiver belongs to a uniclass. For the moment (this is not entirely satisfactory) this is precisely equated with the classname ending in a digit" ^ self class name endsWithDigit! ! !Object methodsFor: 'viewer' stamp: 'sw 12/11/2000 15:37'! browseOwnClassSubProtocol "Open up a ProtocolBrowser on the subprotocol of the receiver" ProtocolBrowser openSubProtocolForClass: self class ! ! !Object methodsFor: 'viewer' stamp: 'sw 8/3/2001 22:08'! categoriesForVocabulary: aVocabulary limitClass: aLimitClass "Answer a list of categories of methods for the receiver when using the given vocabulary, given that one considers only methods that are implemented not further away than aLimitClass" ^ aVocabulary categoryListForInstance: self ofClass: self class limitClass: aLimitClass! ! !Object methodsFor: 'viewer' stamp: 'sw 10/25/2000 07:20'! chooseNewNameForReference "Offer an opportunity for the receiver, presumed already to be known in the References registry, to be renamed" | nameSym current newName | current _ References keyAtValue: self ifAbsent: [^ self error: 'not found in References']. newName _ FillInTheBlank request: 'Please enter new name' initialAnswer: current. "Want to user some better way of determining the validity of the chosen identifier, and also want to give more precise diagnostic if the string the user types in is not acceptable. Work to be done here." newName isEmpty ifTrue: [^ nil]. ((Scanner isLiteralSymbol: newName) and: [(newName includes: $:) not]) ifTrue: [nameSym _ newName capitalized asSymbol. (((References includesKey: nameSym) not and: [(Smalltalk includesKey: nameSym) not]) and: [(ScriptingSystem allKnownClassVariableNames includes: nameSym) not]) ifTrue: [(References associationAt: current) key: nameSym. References rehash. ^ nameSym]]. self inform: 'Sorry, that name is not available.'. ^ nil! ! !Object methodsFor: 'viewer' stamp: 'sw 2/14/2000 14:24'! defaultNameStemForInstances "Answer a basis for names of default instances of the receiver. The default is to let the class specify, but certain instances will want to override. (PasteUpMorphs serving as Worlds come to mind" ^ self class defaultNameStemForInstances! ! !Object methodsFor: 'viewer' stamp: 'sw 5/22/2001 16:53'! elementTypeFor: aStringOrSymbol vocabulary: aVocabulary "Answer a symbol characterizing what kind of element aStringOrSymbol represents. Realistically, at present, this always just returns #systemScript; a prototyped but not-incorporated architecture supported use of a leading colon to characterize an inst var of a system class, and for the moment we still see its remnant here." self flag: #deferred. "a loose end in the non-player case" ^ #systemScript! ! !Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:04'! externalName "Answer an external name by which the receiver is known. Generic implementation here is a transitional backstop. probably" ^ self nameForViewer! ! !Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:06'! graphicForViewerTab "When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Answer a form or a morph to serve that purpose. A generic image is used for arbitrary objects, but note my reimplementors" ^ ScriptingSystem formAtKey: 'Image'! ! !Object methodsFor: 'viewer' stamp: 'sw 5/4/2001 07:08'! hasUserDefinedSlots "Answer whether the receiver has any user-defined slots, in the omniuser sense of the term. This is needed to allow Viewers to look at any object, not just at Players." ^ false! ! !Object methodsFor: 'viewer' stamp: 'sw 9/26/2001 11:58'! initialTypeForSlotNamed: aName "Answer the initial type to be ascribed to the given instance variable" ^ #Object! ! !Object methodsFor: 'viewer' stamp: 'ar 5/26/2001 16:13'! isPlayerLike "Return true if the receiver is a player-like object" ^false! ! !Object methodsFor: 'viewer' stamp: 'sw 10/24/2000 11:36'! newScriptorAround: aPhraseTileMorph "Sprout a scriptor around aPhraseTileMorph, thus making a new script. This is where generalized scriptors will be threaded in" ^ nil! ! !Object methodsFor: 'viewer' stamp: 'sw 1/22/2001 15:20'! renameScript: oldSelector "prompt the user for a new selector and apply it. Presently only works for players" self notYetImplemented! ! !Object methodsFor: 'viewer' stamp: 'sw 10/17/2000 11:27'! uniqueInstanceVariableNameLike: aString excluding: takenNames "Answer a nice instance-variable name to be added to the receiver which resembles aString, making sure it does not coincide with any element in takenNames" | okBase uniqueName usedNames | usedNames _ self class allInstVarNamesEverywhere. usedNames removeAllFoundIn: self class instVarNames. usedNames addAll: takenNames. okBase _ Utilities wellFormedInstanceVariableNameFrom: aString. uniqueName _ Utilities keyLike: okBase satisfying: [:aKey | (usedNames includes: aKey) not]. ^ uniqueName! ! !Object methodsFor: 'viewer' stamp: 'sw 11/21/2001 15:16'! uniqueNameForReference "Answer a nice name by which the receiver can be referred to by other objects. At present this uses a global References dictionary to hold the database of references, but in due course this will need to acquire some locality" | aName nameSym stem knownClassVars | (aName _ self uniqueNameForReferenceOrNil) ifNotNil: [^ aName]. (stem _ self knownName) ifNil: [stem _ self defaultNameStemForInstances asString]. stem _ stem select: [:ch | ch isLetter or: [ch isDigit]]. stem size == 0 ifTrue: [stem _ 'A']. stem first isLetter ifFalse: [stem _ 'A', stem]. stem _ stem capitalized. knownClassVars _ ScriptingSystem allKnownClassVariableNames. aName _ Utilities keyLike: stem satisfying: [:jinaLake | nameSym _ jinaLake asSymbol. ((References includesKey: nameSym) not and: [(Smalltalk includesKey: nameSym) not]) and: [(knownClassVars includes: nameSym) not]]. References at: (aName _ aName asSymbol) put: self. ^ aName! ! !Object methodsFor: 'viewer' stamp: 'sw 3/15/2004 23:53'! uniqueNameForReferenceFrom: proposedName "Answer a satisfactory symbol, similar to the proposedName but obeying the rules, to represent the receiver" | aName nameSym stem okay | proposedName = self uniqueNameForReferenceOrNil ifTrue: [^ proposedName]. "No change" stem _ proposedName select: [:ch | ch isLetter or: [ch isDigit]]. stem size == 0 ifTrue: [stem _ 'A']. stem first isLetter ifFalse: [stem _ 'A', stem]. stem _ stem capitalized. aName _ Utilities keyLike: stem satisfying: [:jinaLake | nameSym _ jinaLake asSymbol. okay _ true. self class scopeHas: nameSym ifTrue: [:x | okay _ false "don't use it"]. okay]. ^ aName asSymbol! ! !Object methodsFor: 'viewer' stamp: 'sw 3/15/2004 23:01'! uniqueNameForReferenceOrNil "If the receiver has a unique name for reference, return it here, else return nil" ^ References keyAtValue: self ifAbsent: [nil]! ! !Object methodsFor: 'viewer' stamp: 'ar 5/16/2001 01:40'! updateThresholdForGraphicInViewerTab "When a Viewer is open on the receiver, its tab needs some graphic to show to the user. Computing this graphic can take quite some time so we want to make the update frequency depending on how long it takes to compute the thumbnail. The threshold returned by this method defines that the viewer will update at most every 'threshold * timeItTakesToDraw' milliseconds. Thus, if the time for computing the receiver's thumbnail is 200 msecs and the the threshold is 10, the viewer will update at most every two seconds." ^20 "seems to be a pretty good general choice"! ! !Object methodsFor: 'viewer' stamp: 'sw 3/9/2001 13:48'! usableMethodInterfacesIn: aListOfMethodInterfaces "Filter aList, returning a subset list of apt phrases" ^ aListOfMethodInterfaces ! ! !Object methodsFor: 'private'! errorImproperStore "Create an error notification that an improper store was attempted." self error: 'Improper store into indexable object'! ! !Object methodsFor: 'private'! errorNonIntegerIndex "Create an error notification that an improper object was used as an index." self error: 'only integers should be used as indices'! ! !Object methodsFor: 'private' stamp: 'yo 6/29/2004 11:37'! errorNotIndexable "Create an error notification that the receiver is not indexable." self error: ('Instances of {1} are not indexable' translated format: {self class name})! ! !Object methodsFor: 'private'! errorSubscriptBounds: index "Create an error notification that an improper integer was used as an index." self error: 'subscript is out of bounds: ' , index printString! ! !Object methodsFor: 'private' stamp: 'BG 10/28/2003 21:01'! primitiveError: aString "This method is called when the error handling results in a recursion in calling on error: or halt or halt:." | context | Sensor eventQueue: nil. "Or else we won't get keyboard and possibly run out of memory" (String streamContents: [:s | s nextPutAll: '***System error handling failed***'. s cr; nextPutAll: aString. context _ thisContext sender sender. 20 timesRepeat: [context == nil ifFalse: [s cr; print: (context _ context sender)]]. s cr; nextPutAll: '-------------------------------'. s cr; nextPutAll: 'Type CR to enter an emergency evaluator.'. s cr; nextPutAll: 'Type any other character to restart.']) displayAt: 0 @ 0. [Sensor keyboardPressed] whileFalse. Sensor keyboard = Character cr ifTrue: [Transcripter emergencyEvaluator]. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController]! ! !Object methodsFor: 'private'! species "Answer the preferred class for reconstructing the receiver. For example, collections create new collections whenever enumeration messages such as collect: or select: are invoked. The new kind of collection is determined by the species of the original collection. Species and class are not always the same. For example, the species of Interval is Array." ^self class! ! !Object methodsFor: 'private'! storeAt: offset inTempFrame: aContext "This message had to get sent to an expression already on the stack as a Block argument being accessed by the debugger. Just re-route it to the temp frame." ^ aContext tempAt: offset put: self! ! !Object methodsFor: '*system-support' stamp: 'dvf 8/23/2003 12:27'! systemNavigation ^ SystemNavigation default! ! !Object methodsFor: 'Breakpoint' stamp: 'bkv 7/1/2003 12:33'! break "This is a simple message to use for inserting breakpoints during debugging. The debugger is opened by sending a signal. This gives a chance to restore invariants related to multiple processes." BreakPoint signal. "nil break."! ! !Object methodsFor: 'inspecting' stamp: 'ajh 1/31/2003 15:49'! basicInspect "Create and schedule an Inspector in which the user can examine the receiver's variables. This method should not be overriden." BasicInspector openOn: self withEvalPane: false! ! !Object methodsFor: 'inspecting' stamp: 'ajh 2/3/2003 19:19'! inspect "Create and schedule an Inspector in which the user can examine the receiver's variables." self inspectorClass openOn: self withEvalPane: true! ! !Object methodsFor: 'inspecting' stamp: 'ajh 2/3/2003 19:18'! inspectorClass ^ Inspector! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitAddDependent: anObject self addDependent: anObject! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitChanged: anAspect self changed: anAspect! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitRemoveDependent: anObject self removeDependent: anObject! ! !Object methodsFor: '*tools-browser' stamp: 'mu 3/6/2004 15:13'! browse self systemNavigation browseClass: self class! ! !Object methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 16:00'! browseHierarchy self systemNavigation browseHierarchy: self class! ! !Object methodsFor: 'debugging' stamp: 'ssa 8/8/2008 17:25'! print Transcript cr;show: self printString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Object class instanceVariableNames: ''! !Object class methodsFor: 'instance creation' stamp: 'sw 1/23/2003 09:45'! categoryForUniclasses "Answer the default system category into which to place unique-class instances" ^ 'UserObjects'! ! !Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'! chooseUniqueClassName | i className | i _ 1. [className _ (self name , i printString) asSymbol. Smalltalk includesKey: className] whileTrue: [i _ i + 1]. ^ className! ! !Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:22'! initialInstance "Answer the first instance of the receiver, generate an error if there is one already" "self instanceCount > 0 ifTrue: [self error: 'instance(s) already exist.']." "Debugging test that is very slow" ^ self new! ! !Object class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 09:30'! initializedInstance ^ self new! ! !Object class methodsFor: 'instance creation' stamp: 'sw 10/16/2000 10:58'! instanceOfUniqueClass "Answer an instance of a unique subclass of the receiver" ^ self instanceOfUniqueClassWithInstVarString: '' andClassInstVarString: ''! ! !Object class methodsFor: 'instance creation' stamp: 'tk 8/22/1998 08:27'! instanceOfUniqueClassWithInstVarString: instVarString andClassInstVarString: classInstVarString "Create a unique class for the receiver, and answer an instance of it" ^ (self newUniqueClassInstVars: instVarString classInstVars: classInstVarString) initialInstance! ! !Object class methodsFor: 'instance creation' stamp: 'sw 10/23/1999 22:51'! isUniClass ^ false! ! !Object class methodsFor: 'instance creation' stamp: 'ajh 5/23/2002 00:35'! newFrom: aSimilarObject "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." ^ (self isVariable ifTrue: [self basicNew: aSimilarObject basicSize] ifFalse: [self basicNew] ) copySameFrom: aSimilarObject! ! !Object class methodsFor: 'instance creation' stamp: 'tk 6/29/1998 12:11'! newUniqueClassInstVars: instVarString classInstVars: classInstVarString "Create a unique class for the receiver" | aName aClass | self isSystemDefined ifFalse: [^ superclass newUniqueClassInstVars: instVarString classInstVars: classInstVarString]. aName _ self chooseUniqueClassName. aClass _ self subclass: aName instanceVariableNames: instVarString classVariableNames: '' poolDictionaries: '' category: self categoryForUniclasses. classInstVarString size > 0 ifTrue: [aClass class instanceVariableNames: classInstVarString]. ^ aClass! ! !Object class methodsFor: 'instance creation' stamp: 'sw 7/28/97 15:56'! newUserInstance "Answer an instance of an appropriate class to serve as a user object in the containment hierarchy" ^ self instanceOfUniqueClass! ! !Object class methodsFor: 'instance creation' stamp: 'tk 4/20/1999 15:46'! readCarefullyFrom: textOrString "Create an object based on the contents of textOrString. Return an error instead of putting up a SyntaxError window." | object ok | ok _ (textOrString isKindOf: Stream) or: [textOrString isKindOf: String]. (ok or: [textOrString isKindOf: Text]) ifFalse: [^ self error: 'expected String or Text']. object _ Compiler evaluate: textOrString for: nil notifying: #error: "signal we want errors" logged: false. (object isKindOf: self) ifFalse: [self error: self name, ' expected']. ^object! ! !Object class methodsFor: 'instance creation' stamp: 'tk 4/18/1999 07:05'! readFrom: aStream "Create an object based on the contents of aStream." | object ok | ok _ (aStream isKindOf: Stream) or: [aStream isKindOf: String]. (ok or: [aStream isKindOf: Text]) ifFalse: [^ self error: 'expected String or Text']. object _ Compiler evaluate: aStream. (object isKindOf: self) ifFalse: [self error: self name, ' expected']. ^object! ! !Object class methodsFor: 'documentation'! howToModifyPrimitives "You are allowed to write methods which specify primitives, but please use caution. If you make a subclass of a class which contains a primitive method, the subclass inherits the primitive. The message which is implemented primitively may be overridden in the subclass (E.g., see at:put: in String's subclass Symbol). The primitive behavior can be invoked using super (see Symbol string:). A class which attempts to mimic the behavior of another class without being its subclass may or may not be able to use the primitives of the original class. In general, if the instance variables read or written by a primitive have the same meanings and are in the same fields in both classes, the primitive will work. For certain frequently used 'special selectors', the compiler emits a send-special-selector bytecode instead of a send-message bytecode. Special selectors were created because they offer two advantages. Code which sends special selectors compiles into fewer bytes than normal. For some pairs of receiver classes and special selectors, the interpreter jumps directly to a primitive routine without looking up the method in the class. This is much faster than a normal message lookup. A selector which is a special selector solely in order to save space has a normal behavior. Methods whose selectors are special in order to gain speed contain the comment, 'No Lookup'. When the interpreter encounters a send-special-selector bytecode, it checks the class of the receiver and the selector. If the class-selector pair is a no-lookup pair, then the interpreter swiftly jumps to the routine which implements the corresponding primitive. (A special selector whose receiver is not of the right class to make a no-lookup pair, is looked up normally). The pairs are listed below. No-lookup methods contain a primitive number specification, <primitive: xx>, which is redundant. Since the method is not normally looked up, deleting the primitive number specification cannot prevent this primitive from running. If a no-lookup primitive fails, the method is looked up normally, and the expressions in it are executed. No Lookup pairs of (class, selector) SmallInteger with any of + - * / \\ bitOr: bitShift: bitAnd: // SmallInteger with any of = ~= > < >= <= Any class with == Any class with @ Point with either of x y ContextPart with blockCopy: BlockContext with either of value value: " self error: 'comment only'! ! !Object class methodsFor: 'documentation'! whatIsAPrimitive "Some messages in the system are responded to primitively. A primitive response is performed directly by the interpreter rather than by evaluating expressions in a method. The methods for these messages indicate the presence of a primitive response by including <primitive: xx> before the first expression in the method. Primitives exist for several reasons. Certain basic or 'primitive' operations cannot be performed in any other way. Smalltalk without primitives can move values from one variable to another, but cannot add two SmallIntegers together. Many methods for arithmetic and comparison between numbers are primitives. Some primitives allow Smalltalk to communicate with I/O devices such as the disk, the display, and the keyboard. Some primitives exist only to make the system run faster; each does the same thing as a certain Smalltalk method, and its implementation as a primitive is optional. When the Smalltalk interpreter begins to execute a method which specifies a primitive response, it tries to perform the primitive action and to return a result. If the routine in the interpreter for this primitive is successful, it will return a value and the expressions in the method will not be evaluated. If the primitive routine is not successful, the primitive 'fails', and the Smalltalk expressions in the method are executed instead. These expressions are evaluated as though the primitive routine had not been called. The Smalltalk code that is evaluated when a primitive fails usually anticipates why that primitive might fail. If the primitive is optional, the expressions in the method do exactly what the primitive would have done (See Number @). If the primitive only works on certain classes of arguments, the Smalltalk code tries to coerce the argument or appeals to a superclass to find a more general way of doing the operation (see SmallInteger +). If the primitive is never supposed to fail, the expressions signal an error (see SmallInteger asFloat). Each method that specifies a primitive has a comment in it. If the primitive is optional, the comment will say 'Optional'. An optional primitive that is not implemented always fails, and the Smalltalk expressions do the work instead. If a primitive is not optional, the comment will say, 'Essential'. Some methods will have the comment, 'No Lookup'. See Object howToModifyPrimitives for an explanation of special selectors which are not looked up. For the primitives for +, -, *, and bitShift: in SmallInteger, and truncated in Float, the primitive constructs and returns a 16-bit LargePositiveInteger when the result warrants it. Returning 16-bit LargePositiveIntegers from these primitives instead of failing is optional in the same sense that the LargePositiveInteger arithmetic primitives are optional. The comments in the SmallInteger primitives say, 'Fails if result is not a SmallInteger', even though the implementor has the option to construct a LargePositiveInteger. For further information on primitives, see the 'Primitive Methods' part of the chapter on the formal specification of the interpreter in the Smalltalk book." self error: 'comment only'! ! !Object class methodsFor: 'private' stamp: 'mir 8/22/2001 15:20'! releaseExternalSettings "Do nothing as a default"! ! !Object class methodsFor: 'objects from disk' stamp: 'tk 1/8/97'! createFrom: aSmartRefStream size: varsOnDisk version: instVarList "Create an instance of me so objects on the disk can be read in. Tricky part is computing the size if variable. Inst vars will be filled in later. " ^ self isVariable ifFalse: [self basicNew] ifTrue: ["instVarList is names of old class's inst vars plus a version number" self basicNew: (varsOnDisk - (instVarList size - 1))] ! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:05'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asNakedOopFrom: anInteger on: aStream! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 13:01'! ccg: cg generateCoerceToOopFrom: aNode on: aStream cg emitCExpression: aNode on: aStream! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:10'! ccg: cg generateCoerceToValueFrom: aNode on: aStream cg emitCExpression: aNode on: aStream! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 16:09'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asKindOf: self from: anInteger! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 11:12'! ccgCanConvertFrom: anObject ^anObject isKindOf: self! ! !Object class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 00:19'! ccgDeclareCForVar: aSymbolOrString ^'int ', aSymbolOrString! ! !Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 02:00'! flushDependents DependentsFields keysAndValuesDo:[:key :dep| key ifNotNil:[key removeDependent: nil]. ]. DependentsFields finalizeValues.! ! !Object class methodsFor: 'class initialization' stamp: 'rw 2/10/2002 13:09'! flushEvents "Object flushEvents" EventManager flushEvents. ! ! !Object class methodsFor: 'class initialization' stamp: 'rww 10/2/2001 07:35'! initialize "Object initialize" DependentsFields ifNil:[self initializeDependentsFields].! ! !Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:41'! initializeDependentsFields "Object initialize" DependentsFields _ WeakIdentityKeyDictionary new. ! ! !Object class methodsFor: 'class initialization' stamp: 'ar 2/11/2001 01:45'! reInitializeDependentsFields "Object reInitializeDependentsFields" | oldFields | oldFields _ DependentsFields. DependentsFields _ WeakIdentityKeyDictionary new. oldFields keysAndValuesDo:[:obj :deps| deps do:[:d| obj addDependent: d]]. ! ! Object subclass: #ObjectFinalizer instanceVariableNames: 'receiver selector arguments' classVariableNames: '' poolDictionaries: '' category: 'System-Finalization'! !ObjectFinalizer methodsFor: 'initialize' stamp: 'ar 5/19/2003 20:12'! receiver: aReceiver selector: aSelector argument: anObject receiver := aReceiver. selector := aSelector. arguments := Array with: anObject! ! !ObjectFinalizer methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:13'! finalize "Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority." [receiver perform: selector withArguments: arguments] on: Error do:[:ex| ex return]. ! ! Object subclass: #ObjectWithDocumentation instanceVariableNames: 'authoringStamp properties elementSymbol naturalLanguageTranslations' classVariableNames: '' poolDictionaries: '' category: 'Protocols-Kernel'! !ObjectWithDocumentation commentStamp: '<historical>' prior: 0! ObjectWithDocumentation - an abstract superclass for objects that allows maintenance of an authoring stamp, a body of documentation, and a properties dictionary. The Properties implementation has not happened yet -- it would closely mirror the implemenation of properties in the MorphExtension, for example.! !ObjectWithDocumentation methodsFor: 'initialization' stamp: 'sw 1/29/2001 09:28'! initialize "Initialize the receiver (automatically called when instances are created via 'new')" authoringStamp _ Utilities changeStampPerSe ! ! !ObjectWithDocumentation methodsFor: 'documentation' stamp: 'sw 11/5/2001 15:36'! documentation: maneno "Set the receiver's documentation, in the current langauge" | wording | wording _ self wording. self absorbTranslation: (ElementTranslation new wording: wording helpMessage: maneno language: #English) ! ! !ObjectWithDocumentation methodsFor: 'queries' stamp: 'sw 9/12/2001 14:36'! documentation "Answer the receiver's documentation" ^ self translatedToPrevailingLanguage helpMessage! ! !ObjectWithDocumentation methodsFor: 'queries' stamp: 'sw 9/12/2001 15:13'! wording "Answer the receiver's wording" ^ self translatedToPrevailingLanguage wording! ! !ObjectWithDocumentation methodsFor: 'translation' stamp: 'sw 9/12/2001 23:03'! absorbTranslation: anElementTranslation "Absorb the given translation, which could overlay a prior version" naturalLanguageTranslations ifNil: [naturalLanguageTranslations _ OrderedCollection new]. naturalLanguageTranslations removeAllSuchThat: [:tr | tr language == anElementTranslation language]. naturalLanguageTranslations add: anElementTranslation! ! !ObjectWithDocumentation methodsFor: 'translation' stamp: 'dgd 2/24/2004 20:02'! translatedToLanguage: languageSymbol "Answer an ElementTranslation object in the prevailing natural language, or, if none found, in English" | fallback elSym el wrd doc | elSym := self elementSymbol. ^ naturalLanguageTranslations isEmptyOrNil ifTrue: [(el := self elementSymbol) ifNotNil: [((el beginsWith: 'get') and: [elSym size > 3]) ifTrue: [wrd := (elSym copyFrom: 4 to: elSym size) withFirstCharacterDownshifted. doc := 'get value of ' , elSym] ifFalse: [((elSym beginsWith: 'set') and: [elSym size > 4]) ifTrue: [wrd := (elSym copyFrom: 4 to: elSym size - 1) withFirstCharacterDownshifted. doc := 'set value of ' , elSym] ifFalse: [wrd := ScriptingSystem wordingForOperator: elSym. doc := nil]]]. ^ ElementTranslation new wording: wrd helpMessage: doc language: #English] ifFalse: [naturalLanguageTranslations do: [:aTranslation | aTranslation language == languageSymbol ifTrue: [^ aTranslation]. aTranslation language == #English ifTrue: [fallback := aTranslation]]. fallback ifNil: [ElementCategory new categoryName: elSym]]! ! !ObjectWithDocumentation methodsFor: 'translation' stamp: 'dgd 12/4/2003 19:09'! translatedToPrevailingLanguage "Answer an ElementTranslation object in the prevailing natural language, or, if none found, in English" ^ Preferences translationWithBabel ifTrue:[ self translatedToPrevailingLanguageUsingBabel ] ifFalse:[ self translatedToLanguage:self currentWorld currentNaturalLanguage] ! ! !ObjectWithDocumentation methodsFor: 'translation' stamp: 'dgd 12/4/2003 19:14'! translatedToPrevailingLanguageUsingBabel "Answer an ElementTranslation object in the prevailing natural language using the Babel mechanism" | elSym | elSym := self elementSymbol. "" elSym isNil ifFalse: ["" ((elSym beginsWith: 'get') and: [elSym size > 3]) ifTrue: ["" ^ ElementTranslation new wording: (elSym allButFirst: 3) withFirstCharacterDownshifted translated helpMessage: ('get value of {1}' translated format: {elSym}) language: self currentWorld currentNaturalLanguage]. "" ((elSym beginsWith: 'set') and: [elSym size > 4]) ifTrue: ["" ^ ElementTranslation new wording: (elSym allButFirst: 3) withFirstCharacterDownshifted translated helpMessage: ('set value of {1}' translated format: {elSym}) language: self currentWorld currentNaturalLanguage]]. "" ^ (self translatedToLanguage: #English) translated! ! !ObjectWithDocumentation methodsFor: 'miscellaneous' stamp: 'sw 9/12/2001 23:03'! elementSymbol "Answer the receiver's element symbol" ^ elementSymbol! ! Switch subclass: #OneOnSwitch instanceVariableNames: 'connection' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !OneOnSwitch commentStamp: '<historical>' prior: 0! 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.! !OneOnSwitch methodsFor: 'initialize-release'! release super release. self isConnectionSet ifTrue: [connection removeDependent: self]! ! !OneOnSwitch methodsFor: 'state'! turnOn "Does nothing if it is already on. If it is not, it is set to 'on', its dependents are notified of the change, its connection is notified, and its action is executed." self isOff ifTrue: [on _ true. self changed. self notifyConnection. self doAction: onAction]! ! !OneOnSwitch methodsFor: 'connection'! connection "Answer the object that connects the receiver to other Switches." ^connection! ! !OneOnSwitch methodsFor: 'connection'! isConnectionSet "Answer whether the receiver is connected to an object that coordinates updates among switches." connection == nil ifTrue: [^false] ifFalse: [^true]! ! !OneOnSwitch methodsFor: 'connection'! notifyConnection "Send the receiver's connection (if it exists) the message 'changed: self' in order for the connection to broadcast the change to other objects connected by the connection." self isConnectionSet ifTrue: [self connection changed: self]! ! !OneOnSwitch methodsFor: 'updating'! update: aOneOnSwitch "Does nothing if aOneOnSwitch is identical to this object. If it is not, this object is turned off. This message is sent by the connection (an Object) when some related OneOnSwitch (possibly this one) has changed. This allows a group of related OneOnSwitches to maintain the constraint that at most one will be on at any time." self ~~ aOneOnSwitch ifTrue: [self turnOff]! ! SequenceableCollection subclass: #OrderedCollection instanceVariableNames: 'array firstIndex lastIndex' classVariableNames: '' poolDictionaries: '' category: 'Collections-Sequenceable'! !OrderedCollection commentStamp: '<historical>' prior: 0! I represent a collection of objects ordered by the collector.! !OrderedCollection methodsFor: 'accessing'! at: anInteger "Answer my element at index anInteger. at: is used by a knowledgeable client to access an existing element" (anInteger < 1 or: [anInteger + firstIndex - 1 > lastIndex]) ifTrue: [self errorNoSuchElement] ifFalse: [^ array at: anInteger + firstIndex - 1]! ! !OrderedCollection methodsFor: 'accessing'! at: anInteger put: anObject "Put anObject at element index anInteger. at:put: cannot be used to append, front or back, to an ordered collection; it is used by a knowledgeable client to replace an element." | index | index _ anInteger asInteger. (index < 1 or: [index + firstIndex - 1 > lastIndex]) ifTrue: [self errorNoSuchElement] ifFalse: [^array at: index + firstIndex - 1 put: anObject]! ! !OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:42'! capacity "Answer the current capacity of the receiver." ^ array size! ! !OrderedCollection methodsFor: 'accessing'! inspect "Open an OrderedCollectionInspector on the receiver. Use basicInspect to get a normal type of inspector." OrderedCollectionInspector openOn: self withEvalPane: true! ! !OrderedCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:39'! size "Answer how many elements the receiver contains." ^ lastIndex - firstIndex + 1! ! !OrderedCollection methodsFor: 'copying'! copyEmpty "Answer a copy of the receiver that contains no elements." ^self species new! ! !OrderedCollection methodsFor: 'copying' stamp: 'di 12/12/2000 10:15'! copyFrom: startIndex to: endIndex "Answer a copy of the receiver that contains elements from position startIndex to endIndex." | targetCollection | endIndex < startIndex ifTrue: [^self species new: 0]. targetCollection _ self species new: endIndex + 1 - startIndex. startIndex to: endIndex do: [:index | targetCollection addLast: (self at: index)]. ^ targetCollection! ! !OrderedCollection methodsFor: 'copying'! copyReplaceFrom: start to: stop with: replacementCollection "Answer a copy of the receiver with replacementCollection's elements in place of the receiver's start'th to stop'th elements. This does not expect a 1-1 map from replacementCollection to the start to stop elements, so it will do an insert or append." | newOrderedCollection delta startIndex stopIndex | "if start is less than 1, ignore stop and assume this is inserting at the front. if start greater than self size, ignore stop and assume this is appending. otherwise, it is replacing part of me and start and stop have to be within my bounds. " delta _ 0. startIndex _ start. stopIndex _ stop. start < 1 ifTrue: [startIndex _ stopIndex _ 0] ifFalse: [startIndex > self size ifTrue: [startIndex _ stopIndex _ self size + 1] ifFalse: [(stopIndex < (startIndex - 1) or: [stopIndex > self size]) ifTrue: [self errorOutOfBounds]. delta _ stopIndex - startIndex + 1]]. newOrderedCollection _ self species new: self size + replacementCollection size - delta. 1 to: startIndex - 1 do: [:index | newOrderedCollection add: (self at: index)]. 1 to: replacementCollection size do: [:index | newOrderedCollection add: (replacementCollection at: index)]. stopIndex + 1 to: self size do: [:index | newOrderedCollection add: (self at: index)]. ^newOrderedCollection! ! !OrderedCollection methodsFor: 'copying'! copyWith: newElement "Answer a copy of the receiver that is 1 bigger than the receiver and includes the argument, newElement, at the end." | newCollection | newCollection _ self copy. newCollection add: newElement. ^newCollection! ! !OrderedCollection methodsFor: 'copying' stamp: 'sw 1/26/96'! reversed "Answer a copy of the receiver with element order reversed. " | newCol | newCol _ self species new. self reverseDo: [:elem | newCol addLast: elem]. ^ newCol "#(2 3 4 'fred') reversed"! ! !OrderedCollection methodsFor: 'adding'! add: newObject ^self addLast: newObject! ! !OrderedCollection methodsFor: 'adding'! add: newObject after: oldObject "Add the argument, newObject, as an element of the receiver. Put it in the sequence just succeeding oldObject. Answer newObject." | index | index _ self find: oldObject. self insert: newObject before: index + 1. ^newObject! ! !OrderedCollection methodsFor: 'adding' stamp: 'di 3/15/1999 14:01'! add: newObject afterIndex: index "Add the argument, newObject, as an element of the receiver. Put it in the sequence just after index. Answer newObject." self insert: newObject before: firstIndex + index. ^ newObject! ! !OrderedCollection methodsFor: 'adding'! add: newObject before: oldObject "Add the argument, newObject, as an element of the receiver. Put it in the sequence just preceding oldObject. Answer newObject." | index | index _ self find: oldObject. self insert: newObject before: index. ^newObject! ! !OrderedCollection methodsFor: 'adding' stamp: 'BG 1/9/2004 12:30'! add: newObject beforeIndex: index "Add the argument, newObject, as an element of the receiver. Put it in the sequence just before index. Answer newObject." self add: newObject afterIndex: index - 1. ^ newObject! ! !OrderedCollection methodsFor: 'adding' stamp: 'sma 5/12/2000 11:26'! addAll: aCollection "Add each element of aCollection at my end. Answer aCollection." ^ self addAllLast: aCollection! ! !OrderedCollection methodsFor: 'adding'! addAllFirst: anOrderedCollection "Add each element of anOrderedCollection at the beginning of the receiver. Answer anOrderedCollection." anOrderedCollection reverseDo: [:each | self addFirst: each]. ^anOrderedCollection! ! !OrderedCollection methodsFor: 'adding' stamp: 'sw 3/1/2001 11:03'! addAllFirstUnlessAlreadyPresent: anOrderedCollection "Add each element of anOrderedCollection at the beginning of the receiver, preserving the order, but do not add any items that are already in the receiver. Answer anOrderedCollection." anOrderedCollection reverseDo: [:each | (self includes: each) ifFalse: [self addFirst: each]]. ^ anOrderedCollection! ! !OrderedCollection methodsFor: 'adding'! addAllLast: anOrderedCollection "Add each element of anOrderedCollection at the end of the receiver. Answer anOrderedCollection." anOrderedCollection do: [:each | self addLast: each]. ^anOrderedCollection! ! !OrderedCollection methodsFor: 'adding'! addFirst: newObject "Add newObject to the beginning of the receiver. Answer newObject." firstIndex = 1 ifTrue: [self makeRoomAtFirst]. firstIndex _ firstIndex - 1. array at: firstIndex put: newObject. ^ newObject! ! !OrderedCollection methodsFor: 'adding'! addLast: newObject "Add newObject to the end of the receiver. Answer newObject." lastIndex = array size ifTrue: [self makeRoomAtLast]. lastIndex _ lastIndex + 1. array at: lastIndex put: newObject. ^ newObject! ! !OrderedCollection methodsFor: 'adding' stamp: 'ajh 5/22/2003 12:03'! at: index ifAbsentPut: block "Return value at index, however, if value does not exist (nil or out of bounds) then add block's value at index (growing self if necessary)" | v | index <= self size ifTrue: [ ^ (v _ self at: index) ifNotNil: [v] ifNil: [self at: index put: block value] ]. [self size < index] whileTrue: [self add: nil]. ^ self at: index put: block value! ! !OrderedCollection methodsFor: 'adding'! grow "Become larger. Typically, a subclass has to override this if the subclass adds instance variables." | newArray | newArray _ Array new: self size + self growSize. newArray replaceFrom: 1 to: array size with: array startingAt: 1. array _ newArray! ! !OrderedCollection methodsFor: 'adding'! growSize ^ array size max: 2! ! !OrderedCollection methodsFor: 'removing'! remove: oldObject ifAbsent: absentBlock | index | index _ firstIndex. [index <= lastIndex] whileTrue: [oldObject = (array at: index) ifTrue: [self removeIndex: index. ^ oldObject] ifFalse: [index _ index + 1]]. ^ absentBlock value! ! !OrderedCollection methodsFor: 'removing' stamp: 'raok 4/27/2001 15:35'! removeAllSuchThat: aBlock "Remove each element of the receiver for which aBlock evaluates to true. The method in Collection is O(N^2), this is O(N)." | n | n _ firstIndex. firstIndex to: lastIndex do: [:index | (aBlock value: (array at: index)) ifFalse: [ array at: n put: (array at: index). n _ n + 1]]. n to: lastIndex do: [:index | array at: index put: nil]. lastIndex _ n - 1! ! !OrderedCollection methodsFor: 'removing' stamp: 'ar 5/22/2000 12:19'! removeAt: index | removed | removed _ self at: index. self removeIndex: index + firstIndex - 1. ^removed! ! !OrderedCollection methodsFor: 'removing'! removeFirst "Remove the first element of the receiver and answer it. If the receiver is empty, create an error notification." | firstObject | self emptyCheck. firstObject _ array at: firstIndex. array at: firstIndex put: nil. firstIndex _ firstIndex + 1. ^ firstObject! ! !OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:37'! removeFirst: n "Remove first n object into an array" | list | list _ Array new: n. 1 to: n do: [:i | list at: i put: self removeFirst]. ^ list! ! !OrderedCollection methodsFor: 'removing'! removeLast "Remove the last element of the receiver and answer it. If the receiver is empty, create an error notification." | lastObject | self emptyCheck. lastObject _ array at: lastIndex. array at: lastIndex put: nil. lastIndex _ lastIndex - 1. ^ lastObject! ! !OrderedCollection methodsFor: 'removing' stamp: 'ajh 6/22/2003 14:36'! removeLast: n "Remove last n object into an array with last in last position" | list | list _ Array new: n. n to: 1 by: -1 do: [:i | list at: i put: self removeLast]. ^ list! ! !OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'! collect: aBlock "Evaluate aBlock with each of my elements as the argument. Collect the resulting values into a collection that is like me. Answer the new collection. Override superclass in order to use addLast:, not at:put:." | newCollection | newCollection _ self species new: self size. firstIndex to: lastIndex do: [:index | newCollection addLast: (aBlock value: (array at: index))]. ^ newCollection! ! !OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/18/2000 17:34'! collect: aBlock from: fromIndex to: toIndex "Override superclass in order to use addLast:, not at:put:." | result | (fromIndex < 1 or:[toIndex + firstIndex - 1 > lastIndex]) ifTrue: [^self errorNoSuchElement]. result _ self species new: toIndex - fromIndex + 1. firstIndex + fromIndex - 1 to: firstIndex + toIndex - 1 do: [:index | result addLast: (aBlock value: (array at: index))]. ^ result ! ! !OrderedCollection methodsFor: 'enumerating'! do: aBlock "Override the superclass for performance reasons." | index | index _ firstIndex. [index <= lastIndex] whileTrue: [aBlock value: (array at: index). index _ index + 1]! ! !OrderedCollection methodsFor: 'enumerating'! reverseDo: aBlock "Override the superclass for performance reasons." | index | index _ lastIndex. [index >= firstIndex] whileTrue: [aBlock value: (array at: index). index _ index - 1]! ! !OrderedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:13'! select: aBlock "Evaluate aBlock with each of my elements as the argument. Collect into a new collection like the receiver, only those elements for which aBlock evaluates to true." | newCollection element | newCollection _ self copyEmpty. firstIndex to: lastIndex do: [:index | (aBlock value: (element _ array at: index)) ifTrue: [newCollection addLast: element]]. ^ newCollection! ! !OrderedCollection methodsFor: 'enumerating' stamp: 'di 8/31/1999 13:13'! with: otherCollection collect: twoArgBlock "Collect and return the result of evaluating twoArgBlock with corresponding elements from this collection and otherCollection." | result | otherCollection size = self size ifFalse: [self error: 'otherCollection must be the same size']. result _ self species new: self size. 1 to: self size do: [:index | result addLast: (twoArgBlock value: (self at: index) value: (otherCollection at: index))]. ^ result! ! !OrderedCollection methodsFor: 'enumerating' stamp: 'bf 5/16/2000 16:30'! withIndexCollect: elementAndIndexBlock "Just like with:collect: except that the iteration index supplies the second argument to the block. Override superclass in order to use addLast:, not at:put:." | newCollection | newCollection _ self species new: self size. firstIndex to: lastIndex do: [:index | newCollection addLast: (elementAndIndexBlock value: (array at: index) value: index - firstIndex + 1)]. ^ newCollection! ! !OrderedCollection methodsFor: 'private'! collector "Private" ^ array! ! !OrderedCollection methodsFor: 'private'! errorConditionNotSatisfied self error: 'no element satisfies condition'! ! !OrderedCollection methodsFor: 'private'! errorNoSuchElement self error: 'attempt to index non-existent element in an ordered collection'! ! !OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:26'! find: oldObject " This method answers an index in the range firstIndex .. lastIndex, which is meant for internal use only. Never use this method in your code, the methods for public use are: #indexOf: #indexOf:ifAbsent: " | index | index _ firstIndex. [index <= lastIndex] whileTrue: [(array at: index) = oldObject ifTrue: [^ index]. index _ index + 1]. self errorNotFound: oldObject! ! !OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:29'! insert: anObject before: spot " spot is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection. Never use this method in your code, it is meant for private use by OrderedCollection only. The methods for use are: #add:before: to insert an object before another object #add:beforeIndex: to insert an object before a given position. " | "index" delta spotIndex| spotIndex _ spot. delta _ spotIndex - firstIndex. firstIndex = 1 ifTrue: [self makeRoomAtFirst. spotIndex _ firstIndex + delta]. firstIndex _ firstIndex - 1. array replaceFrom: firstIndex to: spotIndex - 2 with: array startingAt: firstIndex + 1. array at: spotIndex - 1 put: anObject. " index _ firstIndex _ firstIndex - 1. [index < (spotIndex - 1)] whileTrue: [array at: index put: (array at: index + 1). index _ index + 1]. array at: index put: anObject." ^ anObject! ! !OrderedCollection methodsFor: 'private'! makeRoomAtFirst | delta index | delta _ array size - self size. delta = 0 ifTrue: [self grow. delta _ array size - self size]. lastIndex = array size ifTrue: [^ self]. "just in case we got lucky" index _ array size. [index > delta] whileTrue: [array at: index put: (array at: index - delta + firstIndex - 1). array at: index - delta + firstIndex - 1 put: nil. index _ index - 1]. firstIndex _ delta + 1. lastIndex _ array size! ! !OrderedCollection methodsFor: 'private'! makeRoomAtLast | newLast delta | newLast _ self size. array size - self size = 0 ifTrue: [self grow]. (delta _ firstIndex - 1) = 0 ifTrue: [^ self]. "we might be here under false premises or grow did the job for us" 1 to: newLast do: [:index | array at: index put: (array at: index + delta). array at: index + delta put: nil]. firstIndex _ 1. lastIndex _ newLast! ! !OrderedCollection methodsFor: 'private' stamp: 'BG 1/9/2004 12:28'! removeIndex: removedIndex " removedIndex is an index in the range firstIndex .. lastIndex, such an index is not known from outside the collection. Never use this method in your code, it is meant for private use by OrderedCollection only. The method for public use is: #removeAt: " array replaceFrom: removedIndex to: lastIndex - 1 with: array startingAt: removedIndex+1. array at: lastIndex put: nil. lastIndex _ lastIndex - 1.! ! !OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'! reset firstIndex _ array size // 3 max: 1. lastIndex _ firstIndex - 1! ! !OrderedCollection methodsFor: 'private' stamp: 'ar 4/16/1999 07:59'! resetTo: index firstIndex _ index. lastIndex _ firstIndex - 1! ! !OrderedCollection methodsFor: 'private' stamp: 'di 11/14/97 12:54'! setCollection: anArray array _ anArray. self reset! ! !OrderedCollection methodsFor: 'private' stamp: 'apb 10/15/2000 18:10'! setContents: anArray array _ anArray. firstIndex _ 1. lastIndex _ array size.! ! !OrderedCollection methodsFor: 'testing' stamp: 'bf 8/20/1999 15:08'! hasContentsInExplorer ^self isEmpty not! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! OrderedCollection class instanceVariableNames: ''! !OrderedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:41'! new ^ self new: 10! ! !OrderedCollection class methodsFor: 'instance creation' stamp: 'sma 5/12/2000 17:42'! new: anInteger ^ super new setCollection: (Array new: anInteger)! ! !OrderedCollection class methodsFor: 'instance creation'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." | newCollection | newCollection _ self new: aCollection size. newCollection addAll: aCollection. ^newCollection " OrderedCollection newFrom: {1. 2. 3} {1. 2. 3} as: OrderedCollection {4. 2. 7} as: SortedCollection "! ! !OrderedCollection class methodsFor: 'instance creation' stamp: 'apb 10/15/2000 22:02'! ofSize: n "Create a new collection of size n with nil as its elements. This method exists because OrderedCollection new: n creates an empty collection, not one of size n." | collection | collection _ self new: n. collection setContents: (collection collector). ^ collection ! ! Inspector subclass: #OrderedCollectionInspector instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Inspector'! !OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'dew 9/19/2001 03:27'! fieldList object ifNil: [ ^ OrderedCollection new]. ^ self baseFieldList , (object size <= (self i1 + self i2) ifTrue: [(1 to: object size) collect: [:i | i printString]] ifFalse: [(1 to: self i1) , (object size-(self i2-1) to: object size) collect: [:i | i printString]]) " OrderedCollection new inspect (OrderedCollection newFrom: #(3 5 7 123)) inspect (OrderedCollection newFrom: (1 to: 1000)) inspect "! ! !OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:38'! replaceSelectionValue: anObject "The receiver has a list of variables of its inspected object. One of these is selected. The value of the selected variable is set to the value, anObject." (selectionIndex - 2) <= object class instSize ifTrue: [^ super replaceSelectionValue: anObject]. object at: self selectedObjectIndex put: anObject! ! !OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:28'! selectedObjectIndex "Answer the index of the inspectee's collection that the current selection refers to." | basicIndex | basicIndex _ selectionIndex - 2 - object class instSize. ^ (object size <= (self i1 + self i2) or: [basicIndex <= self i1]) ifTrue: [basicIndex] ifFalse: [object size - (self i1 + self i2) + basicIndex]! ! !OrderedCollectionInspector methodsFor: 'as yet unclassified' stamp: 'sw 9/16/97 22:39'! selection "The receiver has a list of variables of its inspected object. One of these is selected. Answer the value of the selected variable." (selectionIndex - 2) <= object class instSize ifTrue: [^ super selection]. ^ object at: self selectedObjectIndex! ! Notification subclass: #OutOfScopeNotification instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !OutOfScopeNotification methodsFor: 'as yet unclassified' stamp: 'RAA 2/5/2001 10:41'! defaultAction self resume: false! ! Browser subclass: #PackagePaneBrowser instanceVariableNames: 'package packageListIndex packageList' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !PackagePaneBrowser commentStamp: '<historical>' prior: 0! A package browser represents a hierarchical query path through an organization of class and method information. It parses class categories into a two-level hierarchy on the first '-' character, giving "packages" (e.g., Magnitude, Collections, Graphics, etc.), and "categories" (e.g., Magnitude-General and Magnitude-Number). Instance Variables: package <Symbol> the "category header," e.g., #Magnitudes or #Collections packageListIndex <Integer> The index in the package list packageList <OrderedCollection of String> the list of package names ! !PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'sw 1/13/2000 16:45'! defaultBrowserTitle ^ 'Package Browser'! ! !PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'stp 10/06/1998 22:02'! systemOrganizer: aSystemOrganizer "Initialize the receiver as a perspective on the system organizer, aSystemOrganizer. Typically there is only one--the system variable SystemOrganization." super systemOrganizer: aSystemOrganizer . packageListIndex := 0! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:35'! categoryExistsForPackage ^ self hasPackageSelected and: [(systemOrganizer categories indexOf: self package asSymbol) ~= 0] ! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:24'! hasPackageSelected ^ packageListIndex ~= 0! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'BG 10/30/2003 21:09'! openEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers." "PackageBrowser openBrowser" | packageListView systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView annotationPane underPane y optionalButtonsView | topView := StandardSystemView new model: self. topView borderWidth: 1. "label and minSize taken care of by caller" packageListView := PluggableListView on: self list: #packageList selected: #packageListIndex changeSelected: #packageListIndex: menu: #packageMenu:. packageListView window: (0 @ 0 extent: 20 @ 70). topView addSubView: packageListView. systemCategoryListView := PluggableListView on: self list: #systemCategoryList selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex: menu: #systemCategoryMenu:. systemCategoryListView window: (20 @ 0 extent: 30 @ 70). topView addSubView: systemCategoryListView. classListView := PluggableListView on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu:shifted:. classListView window: (0 @ 0 extent: 50 @ 62). topView addSubView: classListView toRightOf: systemCategoryListView. switchView := self buildInstanceClassSwitchView. switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageCategoryListView := PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. messageListView := PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView window: (0 @ 0 extent: 50 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: packageListView. underPane _ annotationPane. y _ 110 - self optionalAnnotationHeight] ifFalse: [underPane _ packageListView. y _ 110]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView := PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. ^ topView! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'JF 7/30/2003 12:25'! package "Answer the receiver's 'package'." ^ self hasPackageSelected ifFalse: [nil] ifTrue: [self packageList at: packageListIndex] ! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 20:36'! packageList "Answer a list of the packages in the current system organization." | str cats stream | str := Set new: 100. stream := WriteStream on: (Array new: 100). systemOrganizer categories do: [ :categ | cats := categ asString copyUpTo: $-. (str includes: cats) ifFalse: [str add: cats. stream nextPut: cats]]. ^stream contents! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/05/1998 19:48'! packageListIndex "Answer the index of the current package selection." ^packageListIndex! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 12/01/1998 02:46'! packageListIndex: anInteger "Set anInteger to be the index of the current package selection." packageListIndex := anInteger. anInteger = 0 ifFalse: [package := self packageList at: packageListIndex]. messageCategoryListIndex := 0. systemCategoryListIndex := 0. messageListIndex := 0. classListIndex := 0. self setClassOrganizer. self changed: #packageSelectionChanged. self changed: #packageListIndex. "update my selection" self changed: #systemCategoryList. "update the category list" self systemCategoryListIndex: 0. "update category list selection" ! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'stp 10/06/1998 19:59'! packageMenu: aMenu "Answer a Menu of operations on class packages to be displayed when the operate menu button is pressed." ^aMenu labels: 'find class...\recent classes...\reorganize\update' withCRs lines: #(2) selections: #(#findClass #recent #editSystemCategories #updatePackages)! ! !PackagePaneBrowser methodsFor: 'package list' stamp: 'nk 2/14/2004 15:09'! updatePackages "Update the contents of the package list." self editSelection: #none. self changed: #packageList. self changed: #package. self packageListIndex: 0 ! ! !PackagePaneBrowser methodsFor: 'system category list' stamp: 'JF 7/30/2003 12:23'! hasSystemCategorySelected ^ systemCategoryListIndex ~= 0! ! !PackagePaneBrowser methodsFor: 'system category list' stamp: 'stp 01/13/2000 12:59'! selectCategoryForClass: theClass "Set the package and category lists to display the given class." | cat | cat := theClass category. self packageListIndex: (self packageList indexOf: (cat copyUpTo: $-)). self systemCategoryListIndex: (self systemCategoryList indexOf: (cat copyFrom: ((cat indexOf: $- ifAbsent: [0]) + 1) to: cat size)).! ! !PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/20/1999 20:16'! selectedSystemCategoryName "Answer the name of the selected system category or nil." systemCategoryListIndex = 0 ifTrue: [^nil]. packageListIndex = 0 ifTrue: [^ self systemCategoryList at: systemCategoryListIndex]. ^ self package , '-' , (self systemCategoryList at: systemCategoryListIndex)! ! !PackagePaneBrowser methodsFor: 'system category list' stamp: 'di 12/16/1999 16:14'! systemCategoryList "Answer the sequenceable collection containing the class categories that the receiver accesses." | prefix | packageListIndex = 0 ifTrue: [^ systemOrganizer categories]. prefix := self package, '-'. ^ Array streamContents: [:strm | systemOrganizer categories do: [ :cat | (cat beginsWith: prefix) ifTrue: [strm nextPut: (cat copyFrom: prefix size + 1 to: cat size)]]]! ! !PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:26'! classList "Answer an array of the class names of the selected category. Answer an empty array if no selection exists." ^ self hasSystemCategorySelected ifFalse: [self packageClasses] ifTrue: [systemOrganizer listAtCategoryNumber: (systemOrganizer categories indexOf: self selectedSystemCategoryName asSymbol)]! ! !PackagePaneBrowser methodsFor: 'class list' stamp: 'JF 7/30/2003 12:36'! packageClasses ^ self categoryExistsForPackage ifFalse: [Array new] ifTrue: [systemOrganizer listAtCategoryNumber: (systemOrganizer categories indexOf: self package asSymbol)]! ! !PackagePaneBrowser methodsFor: 'class list' stamp: 'ak 6/4/2000 09:07'! selectedClass "Answer the class that is currently selected. Answer nil if no selection exists." | name envt | (name _ self selectedClassName) ifNil: [^ nil]. "(envt _ self selectedEnvironment) ifNil: [^ nil]." envt_(Smalltalk environmentForCategory: self selectedSystemCategoryName). ^ envt at: name! ! !PackagePaneBrowser methodsFor: 'dragNDrop util' stamp: 'ls 6/22/2001 23:21'! dstCategoryDstListMorph: dstListMorph internal: internal | dropItem | ^ internal & (dstListMorph getListSelector == #systemCategoryList) ifTrue: [(dropItem _ dstListMorph potentialDropItem) ifNotNil: [(self package , '-' , dropItem) asSymbol]] ifFalse: [self selectedSystemCategoryName]! ! !PackagePaneBrowser methodsFor: 'dragNDrop' stamp: 'mir 5/29/2000 11:54'! changeCategoryForClass: class srcSystemCategory: srcSystemCategorySel atListMorph: dstListMorph internal: internal copy: copyFlag "only move semantic" | newClassCategory success | self flag: #stringSymbolProblem. success _ copyFlag not ifFalse: [^ false]. newClassCategory _ self dstCategoryDstListMorph: dstListMorph internal: internal. (success _ newClassCategory notNil & (newClassCategory ~= class category)) ifTrue: [class category: newClassCategory. self changed: #classList. internal ifFalse: [self selectClass: class]]. ^ success! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PackagePaneBrowser class instanceVariableNames: ''! !PackagePaneBrowser class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 13:15'! initialize self registerInFlapsRegistry.! ! !PackagePaneBrowser class methodsFor: 'class initialization' stamp: 'asm 4/10/2003 13:15'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(PackagePaneBrowser prototypicalToolWindow 'Packages' 'Package Browser: like a System Browser, except that if has extra level of categorization in the top-left pane, such that class-categories are further organized into groups called "packages"') forFlapNamed: 'Tools']! ! !PackagePaneBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:38'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'! !Paragraph commentStamp: '<historical>' prior: 0! I represent displayable text that has been decoraged with margin alignment, line leading, and tab settings.! !Paragraph methodsFor: 'accessing'! backgroundColor backColor == nil ifTrue: [^ Color white]. ^ backColor! ! !Paragraph methodsFor: 'accessing'! clippingRectangle "Answer the rectangle, defined in absolute coordinates, whose intersection with the destinationForm is the area in which the characters are constrained to display." ^clippingRectangle! ! !Paragraph methodsFor: 'accessing' stamp: 'di 10/5/97 15:33'! clippingRectangle: clipRect clippingRectangle _ clipRect! ! !Paragraph methodsFor: 'accessing'! compositionRectangle "Answer the rectangle whose width is the dimension, modified by indents and tabsLevels, against which line wraparound is measured. The height of the compositionRectangle is reset each time recomposition is required." ^compositionRectangle! ! !Paragraph methodsFor: 'accessing'! compositionRectangle: compRectangle "Set the rectangle whose width is the dimension, modified by indents and tabsLevels, against which line wraparound is measured." compositionRectangle _ compRectangle. self composeAll! ! !Paragraph methodsFor: 'accessing'! destinationForm "Answer the Form into which the characters are scanned." ^destinationForm! ! !Paragraph methodsFor: 'accessing'! fillColor "Answer the Form with which each character is combined by the scanner before applying the rule for display." ^mask! ! !Paragraph methodsFor: 'accessing'! fillColor: maskForm "Set the argument, maskForm, to be the form with which each character is combined by the scanner before applying the rule for display." mask _ maskForm! ! !Paragraph methodsFor: 'accessing'! height "Answer the height of the composition rectangle." ^compositionRectangle height! ! !Paragraph methodsFor: 'accessing'! indentationOfLineIndex: lineIndex ifBlank: aBlock "Answer the number of leading tabs in the line at lineIndex. If there are no visible characters, pass the number of tabs to aBlock and return its value. If the line is word-wrap overflow, back up a line and recur." | arrayIndex first last reader leadingTabs lastSeparator cr tab ch | cr _ Character cr. tab _ Character tab. arrayIndex _ lineIndex. [first _ (lines at: arrayIndex) first. first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: "word wrap" [arrayIndex _ arrayIndex - 1]. last _ (lines at: lastLine) last. reader _ ReadStream on: text string from: first to: last. leadingTabs _ 0. [reader atEnd not and: [(ch _ reader next) == tab]] whileTrue: [leadingTabs _ leadingTabs + 1]. lastSeparator _ first - 1 + leadingTabs. [reader atEnd not and: [ch isSeparator and: [ch ~~ cr]]] whileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next]. lastSeparator = last | (ch == cr) ifTrue: [^aBlock value: leadingTabs]. ^leadingTabs! ! !Paragraph methodsFor: 'accessing'! mask "Answer the Form with which each character is combined by the scanner before applying the rule for display." ^mask! ! !Paragraph methodsFor: 'accessing'! numberOfLines "Answer the number of lines of text in the receiver." ^lastLine! ! !Paragraph methodsFor: 'accessing' stamp: 'ar 5/18/2000 18:34'! replaceFrom: start to: stop with: aText displaying: displayBoolean "Replace the receiver's text starting at position start, stopping at stop, by the characters in aText. It is expected that most requirements for modifications to the receiver will call this code. Certainly all cut's or paste's." | compositionScanner obsoleteLines obsoleteLastLine firstLineIndex lastLineIndex startLine stopLine replacementRange visibleRectangle startIndex newLine done newStop obsoleteY newY moveRectangle | text replaceFrom: start to: stop with: aText. "Update the text." lastLine = 0 ifTrue: ["if lines have never been set up, measure them and display all the lines falling in the visibleRectangle" self composeAll. displayBoolean ifTrue: [^ self displayLines: (1 to: lastLine)]]. "save -- things get pretty mashed as we go along" obsoleteLines _ lines copy. obsoleteLastLine _ lastLine. "find the starting and stopping lines" firstLineIndex _ startLine _ self lineIndexOfCharacterIndex: start. stopLine _ self lineIndexOfCharacterIndex: stop. "how many characters being inserted or deleted -- negative if aText size is < characterInterval size." replacementRange _ aText size - (stop - start + 1). "Give ourselves plenty of elbow room." compositionRectangle _ compositionRectangle withHeight: (textStyle lineGrid * 9999). "build a boundingBox of the actual screen space in question -- we'll need it later" visibleRectangle _ (clippingRectangle intersect: compositionRectangle) intersect: destinationForm boundingBox. compositionScanner _ CompositionScanner new forParagraph: self. "Initialize a scanner." "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." startIndex _ (lines at: firstLineIndex) first. startLine > 1 ifTrue: [newLine _ compositionScanner composeLine: startLine - 1 fromCharacterIndex: (lines at: startLine - 1) first inParagraph: self. (lines at: startLine - 1) = newLine ifFalse: ["start in line preceding the one with the starting character" startLine _ startLine - 1. self lineAt: startLine put: newLine. startIndex _ newLine last + 1]]. startIndex > text size ifTrue: ["nil lines after a deletion -- remeasure last line below" self trimLinesTo: (firstLineIndex - 1 max: 0). text size = 0 ifTrue: ["entire text deleted -- clear visibleRectangle and return." displayBoolean ifTrue: [destinationForm fill: visibleRectangle rule: rule fillColor: self backgroundColor]. self updateCompositionHeight. ^self]]. "Now we really get to it." done _ false. lastLineIndex _ stopLine. [done or: [startIndex > text size]] whileFalse: [self lineAt: firstLineIndex put: (newLine _ compositionScanner composeLine: firstLineIndex fromCharacterIndex: startIndex inParagraph: self). [(lastLineIndex > obsoleteLastLine or: ["no more old lines to compare with?" newLine last < (newStop _ (obsoleteLines at: lastLineIndex) last + replacementRange)]) or: [done]] whileFalse: [newStop = newLine last ifTrue: ["got the match" "get source and dest y's for moving the unchanged lines" obsoleteY _ self topAtLineIndex: lastLineIndex + 1 using: obsoleteLines and: obsoleteLastLine. newY _ self topAtLineIndex: firstLineIndex + 1. stopLine _ firstLineIndex. done _ true. "Fill in the new line vector with the old unchanged lines. Update their starting and stopping indices on the way." ((lastLineIndex _ lastLineIndex + 1) to: obsoleteLastLine) do: [:upDatedIndex | self lineAt: (firstLineIndex _ firstLineIndex + 1) put: ((obsoleteLines at: upDatedIndex) slide: replacementRange)]. "trim off obsolete lines, if any" self trimLinesTo: firstLineIndex] ifFalse: [lastLineIndex _ lastLineIndex + 1]]. startIndex _ newLine last + 1. firstLineIndex _ firstLineIndex + 1]. "Now the lines are up to date -- Whew!!. What remains is to move the 'unchanged' lines and display those which have changed." displayBoolean "Not much to do if not displaying" ifFalse: [^ self updateCompositionHeight]. startIndex > text size ifTrue: ["If at the end of previous lines simply display lines from the line in which the first character of the replacement occured through the end of the paragraph." self updateCompositionHeight. self displayLines: (startLine to: (stopLine _ firstLineIndex min: lastLine)). destinationForm "Clear out area at the bottom" fill: ((visibleRectangle left @ (self topAtLineIndex: lastLine + 1) extent: visibleRectangle extent) intersect: visibleRectangle) rule: rule fillColor: self backgroundColor] ifFalse: [newY ~= obsoleteY ifTrue: ["Otherwise first move the unchanged lines within the visibleRectangle with a good old bitblt." moveRectangle _ visibleRectangle left @ (obsoleteY max: visibleRectangle top) corner: visibleRectangle corner. destinationForm copyBits: moveRectangle from: destinationForm at: moveRectangle origin + (0 @ (newY-obsoleteY)) clippingBox: visibleRectangle rule: Form over fillColor: nil]. "Then display the altered lines." self displayLines: (startLine to: stopLine). newY < obsoleteY ifTrue: [(self topAtLineIndex: obsoleteLastLine+1 using: obsoleteLines and: obsoleteLastLine) > visibleRectangle bottom ifTrue: ["A deletion may have 'pulled' previously undisplayed lines into the visibleRectangle. If so, display them." self displayLines: ((self lineIndexOfTop: visibleRectangle bottom - (obsoleteY - newY)) to: (self lineIndexOfTop: visibleRectangle bottom))]. "Clear out obsolete material at the bottom of the visibleRectangle." destinationForm fill: ((visibleRectangle left @ ((self bottomAtLineIndex: lastLine) + 1) extent: visibleRectangle extent) intersect: visibleRectangle) "How about just corner: ??" rule: rule fillColor: self backgroundColor]. (newY > obsoleteY and: [obsoleteY < visibleRectangle top]) ifTrue: ["An insertion may have 'pushed' previously undisplayed lines into the visibleRectangle. If so, display them." self displayLines: ((self lineIndexOfTop: visibleRectangle top) to: (self lineIndexOfTop: visibleRectangle top + (newY-obsoleteY)))]. self updateCompositionHeight]! ! !Paragraph methodsFor: 'accessing'! rule "Answer the rule according to which character display behaves. For example, rule may equal over, under, reverse." ^rule! ! !Paragraph methodsFor: 'accessing'! rule: ruleInteger "Set the rule according to which character display behaves." rule _ ruleInteger! ! !Paragraph methodsFor: 'accessing' stamp: 'sw 10/29/1999 18:11'! stringAtLineNumber: aNumber (aNumber > lastLine or: [aNumber < 1]) ifTrue: [^ nil]. ^ (text string copyFrom: (lines at: aNumber) first to: (lines at: aNumber) last) copyWithout: Character cr! ! !Paragraph methodsFor: 'accessing'! text: aText "Set the argument, aText, to be the text for the receiver." text _ aText. self composeAll! ! !Paragraph methodsFor: 'displaying'! displayOn: aDisplayMedium "Because Paragraphs cache so much information, computation is avoided and displayAt: 0@0 is not appropriate here." self displayOn: aDisplayMedium at: compositionRectangle topLeft clippingBox: clippingRectangle rule: rule fillColor: mask! ! !Paragraph methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint "Use internal clippingRect; destination cliping is done during actual display." self displayOn: aDisplayMedium at: aPoint clippingBox: (clippingRectangle translateBy: aPoint - compositionRectangle topLeft) rule: rule fillColor: mask! ! !Paragraph methodsFor: 'displaying'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "Default display message when aDisplayPoint is in absolute screen coordinates." rule _ ruleInteger. mask _ aForm. clippingRectangle _ clipRectangle. compositionRectangle _ aDisplayPoint extent: compositionRectangle extent. (lastLine == nil or: [lastLine < 1]) ifTrue: [self composeAll]. self displayOn: aDisplayMedium lines: (1 to: lastLine)! ! !Paragraph methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm self "Assumes offset has been set!!!!!!!!!!" displayOn: aDisplayMedium at: (offset + (displayTransformation applyTo: relativePoint) - alignmentPoint) rounded clippingBox: clipRectangle rule: ruleInteger fillColor: aForm. ! ! !Paragraph methodsFor: 'display box access'! boundingBox ^offset extent: compositionRectangle extent! ! !Paragraph methodsFor: 'display box access'! computeBoundingBox ^offset extent: compositionRectangle extent! ! !Paragraph methodsFor: 'composition' stamp: 'ar 5/18/2000 18:34'! composeAll "Compose a collection of characters into a collection of lines." | startIndex stopIndex lineIndex maximumRightX compositionScanner | lines _ Array new: 32. lastLine _ 0. maximumRightX _ 0. text size = 0 ifTrue: [compositionRectangle _ compositionRectangle withHeight: 0. ^maximumRightX]. startIndex _ lineIndex _ 1. stopIndex _ text size. compositionScanner _ CompositionScanner new forParagraph: self. [startIndex > stopIndex] whileFalse: [self lineAt: lineIndex put: (compositionScanner composeLine: lineIndex fromCharacterIndex: startIndex inParagraph: self). maximumRightX _ compositionScanner rightX max: maximumRightX. startIndex _ (lines at: lineIndex) last + 1. lineIndex _ lineIndex + 1]. self updateCompositionHeight. self trimLinesTo: lineIndex - 1. ^ maximumRightX! ! !Paragraph methodsFor: 'composition'! wrappingBox: compositionRect clippingBox: clippingRect "Set the composition rectangle for the receiver so that the lines wrap within the rectangle, compositionRect, and the display of the text is clipped by the rectangle, clippingRect." self compositionRectangle: compositionRect copy text: text style: textStyle offset: offset. clippingRectangle _ clippingRect copy! ! !Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'! characterBlockAtPoint: aPoint "Answer a CharacterBlock for characters in the text at point aPoint. It is assumed that aPoint has been transformed into coordinates appropriate to the receiver's destinationForm rectangle and the compositionRectangle." ^CharacterBlockScanner new characterBlockAtPoint: aPoint in: self! ! !Paragraph methodsFor: 'character location' stamp: 'ar 5/18/2000 18:33'! characterBlockForIndex: targetIndex "Answer a CharacterBlock for character in the text at targetIndex. The coordinates in the CharacterBlock will be appropriate to the intersection of the destinationForm rectangle and the compositionRectangle." ^CharacterBlockScanner new characterBlockForIndex: targetIndex in: self! ! !Paragraph methodsFor: 'character location' stamp: 'di 10/5/1998 12:59'! defaultCharacterBlock ^ CharacterBlock new stringIndex: 1 text: text topLeft: compositionRectangle topLeft extent: 0 @ 0! ! !Paragraph methodsFor: 'selecting' stamp: 'ar 5/28/2000 12:10'! caretFormForDepth: depth "Return a caret form for the given depth." "(Paragraph new caretFormForDepth: Display depth) displayOn: Display at: 0@0 rule: Form reverse" | box f bb map | box _ CaretForm boundingBox. f _ Form extent: box extent depth: depth. map _ (Color cachedColormapFrom: CaretForm depth to: depth) copy. map at: 1 put: (Color transparent pixelValueForDepth: depth). map at: 2 put: (Color quickHighLight: depth) first. "pixel value for reversing" bb _ BitBlt current toForm: f. bb sourceForm: CaretForm; sourceRect: box; destOrigin: 0@0; colorMap: map; combinationRule: Form over; copyBits. ^ f! ! !Paragraph methodsFor: 'selecting' stamp: 'dvf 10/1/2003 13:28'! clickAt: clickPoint for: model controller: aController "Give sensitive text a chance to fire. Display flash: (100@100 extent: 100@100)." | startBlock action range box boxes | action _ false. startBlock _ self characterBlockAtPoint: clickPoint. (text attributesAt: startBlock stringIndex forStyle: textStyle) do: [:att | att mayActOnClick ifTrue: [range _ text rangeOf: att startingAt: startBlock stringIndex. boxes _ self selectionRectsFrom: (self characterBlockForIndex: range first) to: (self characterBlockForIndex: range last+1). box _ boxes detect: [:each | each containsPoint: clickPoint] ifNone: [^ action]. Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [aController terminateAndInitializeAround: [(att actOnClickFor: model in: self at: clickPoint editor: aController) ifTrue: [action _ true]]]]]. ^ action! ! !Paragraph methodsFor: 'selecting'! extendSelectionAt: beginBlock endBlock: endBlock "Answer with an Array of two CharacterBlocks that represent the text selection that the user makes." (self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock ifTrue: [^self mouseMovedFrom: beginBlock pivotBlock: endBlock showingCaret: (beginBlock = endBlock)] ifFalse: [^self mouseMovedFrom: endBlock pivotBlock: beginBlock showingCaret: (beginBlock = endBlock)] ! ! !Paragraph methodsFor: 'selecting' stamp: 'th 9/19/2002 17:27'! extendSelectionMark: markBlock pointBlock: pointBlock "Answer with an Array of two CharacterBlocks that represent the text selection that the user makes." true ifTrue:[^self mouseMovedFrom: pointBlock pivotBlock: markBlock showingCaret:(pointBlock = markBlock)] ifFalse: [ | beginBlock endBlock | beginBlock _ markBlock min: pointBlock. endBlock _ markBlock max: endBlock. (self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock ifTrue: [^self mouseMovedFrom: beginBlock pivotBlock: endBlock showingCaret: (beginBlock = endBlock)] ifFalse: [^self mouseMovedFrom: endBlock pivotBlock: beginBlock showingCaret: (beginBlock = endBlock)] ] ! ! !Paragraph methodsFor: 'selecting' stamp: 'jm 7/1/1999 12:31'! hiliteRect: rect | highlightColor | highlightColor _ Color quickHighLight: destinationForm depth. rect ifNotNil: [ destinationForm fill: rect rule: Form reverse fillColor: highlightColor. "destinationForm fill: (rect translateBy: 1@1) rule: Form reverse fillColor: highlightColor" ]. ! ! !Paragraph methodsFor: 'selecting' stamp: 'jm 7/8/97 12:25'! mouseMovedFrom: beginBlock pivotBlock: pivotBlock showingCaret: caretOn | startBlock stopBlock showingCaret | stopBlock _ startBlock _ beginBlock. showingCaret _ caretOn. [Sensor redButtonPressed] whileTrue: [stopBlock _ self characterBlockAtPoint: Sensor cursorPoint. stopBlock = startBlock ifFalse: [showingCaret ifTrue: [showingCaret _ false. self reverseFrom: pivotBlock to: pivotBlock]. ((startBlock >= pivotBlock and: [stopBlock >= pivotBlock]) or: [startBlock <= pivotBlock and: [stopBlock <= pivotBlock]]) ifTrue: [self reverseFrom: startBlock to: stopBlock. startBlock _ stopBlock] ifFalse: [self reverseFrom: startBlock to: pivotBlock. self reverseFrom: pivotBlock to: stopBlock. startBlock _ stopBlock]. (clippingRectangle containsRect: stopBlock) ifFalse: [stopBlock top < clippingRectangle top ifTrue: [self scrollBy: stopBlock top - clippingRectangle top withSelectionFrom: pivotBlock to: stopBlock] ifFalse: [self scrollBy: stopBlock bottom + textStyle lineGrid - clippingRectangle bottom withSelectionFrom: pivotBlock to: stopBlock]]]]. pivotBlock = stopBlock ifTrue: [showingCaret ifFalse: "restore caret" [self reverseFrom: pivotBlock to: pivotBlock]]. ^ Array with: pivotBlock with: stopBlock! ! !Paragraph methodsFor: 'selecting'! mouseSelect "Answer with an Array of two CharacterBlocks that represent the text selection that the user makes. Return quickly if the button is noticed up to make double-click more responsive." | pivotBlock startBlock stopBlock origPoint stillDown | stillDown _ Sensor redButtonPressed. pivotBlock _ startBlock _ stopBlock _ self characterBlockAtPoint: (origPoint _ Sensor cursorPoint). stillDown _ stillDown and: [Sensor redButtonPressed]. self reverseFrom: startBlock to: startBlock. [stillDown and: [Sensor cursorPoint = origPoint]] whileTrue: [stillDown _ Sensor redButtonPressed]. (stillDown and: [clippingRectangle containsPoint: Sensor cursorPoint]) ifFalse: [^Array with: pivotBlock with: stopBlock]. ^ self mouseMovedFrom: startBlock pivotBlock: pivotBlock showingCaret: true! ! !Paragraph methodsFor: 'selecting'! mouseSelect: clickPoint "Track text selection and answer with an Array of two CharacterBlocks." | startBlock | startBlock _ self characterBlockAtPoint: clickPoint. self reverseFrom: startBlock to: startBlock. ^ self mouseMovedFrom: startBlock pivotBlock: startBlock showingCaret: true! ! !Paragraph methodsFor: 'selecting'! reverseFrom: characterBlock1 to: characterBlock2 "Reverse area between the two character blocks given as arguments." | visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline caret | characterBlock1 = characterBlock2 ifTrue: [lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex. baseline _ lineNo = 0 ifTrue: [textStyle baseline] ifFalse: [(lines at: lineNo) baseline]. caret _ self caretFormForDepth: Display depth. ^ caret "Use a caret to indicate null selection" displayOn: destinationForm at: characterBlock1 topLeft + (-3 @ baseline) clippingBox: clippingRectangle rule: (false "Display depth>8" ifTrue: [9 "not-reverse"] ifFalse: [Form reverse]) fillColor: nil]. visibleRectangle _ (clippingRectangle intersect: compositionRectangle) "intersect: destinationForm boundingBox" "not necessary". characterBlock1 top = characterBlock2 top ifTrue: [characterBlock1 left < characterBlock2 left ifTrue: [initialRectangle _ (characterBlock1 topLeft corner: characterBlock2 bottomLeft) intersect: visibleRectangle] ifFalse: [initialRectangle _ (characterBlock2 topLeft corner: characterBlock1 bottomLeft) intersect: visibleRectangle]] ifFalse: [characterBlock1 top < characterBlock2 top ifTrue: [initialRectangle _ (characterBlock1 topLeft corner: visibleRectangle right @ characterBlock1 bottom) intersect: visibleRectangle. characterBlock1 bottom = characterBlock2 top ifTrue: [finalRectangle _ (visibleRectangle left @ characterBlock2 top corner: characterBlock2 bottomLeft) intersect: visibleRectangle] ifFalse: [interiorRectangle _ (visibleRectangle left @ characterBlock1 bottom corner: visibleRectangle right @ characterBlock2 top) intersect: visibleRectangle. finalRectangle _ (visibleRectangle left @ characterBlock2 top corner: characterBlock2 bottomLeft) intersect: visibleRectangle]] ifFalse: [initialRectangle _ (visibleRectangle left @ characterBlock1 top corner: characterBlock1 bottomLeft) intersect: visibleRectangle. characterBlock1 top = characterBlock2 bottom ifTrue: [finalRectangle _ (characterBlock2 topLeft corner: visibleRectangle right @ characterBlock2 bottom) intersect: visibleRectangle] ifFalse: [interiorRectangle _ (visibleRectangle left @ characterBlock2 bottom corner: visibleRectangle right @ characterBlock1 top) intersect: visibleRectangle. finalRectangle _ (characterBlock2 topLeft corner: visibleRectangle right @ characterBlock2 bottom) intersect: visibleRectangle]]]. self hiliteRect: initialRectangle. self hiliteRect: interiorRectangle. self hiliteRect: finalRectangle.! ! !Paragraph methodsFor: 'selecting' stamp: 'di 12/1/97 04:43'! selectionRectsFrom: characterBlock1 to: characterBlock2 "Return an array of rectangles representing the area between the two character blocks given as arguments." | visibleRectangle initialRectangle interiorRectangle finalRectangle lineNo baseline | characterBlock1 = characterBlock2 ifTrue: [lineNo _ self lineIndexOfCharacterIndex: characterBlock1 stringIndex. baseline _ lineNo = 0 ifTrue: [textStyle baseline] ifFalse: [(lines at: lineNo) baseline]. ^ Array with: (characterBlock1 topLeft extent: 1 @ baseline)]. visibleRectangle _ clippingRectangle intersect: compositionRectangle. characterBlock1 top = characterBlock2 top ifTrue: [characterBlock1 left < characterBlock2 left ifTrue: [initialRectangle _ (characterBlock1 topLeft corner: characterBlock2 bottomLeft) intersect: visibleRectangle] ifFalse: [initialRectangle _ (characterBlock2 topLeft corner: characterBlock1 bottomLeft) intersect: visibleRectangle]] ifFalse: [characterBlock1 top < characterBlock2 top ifTrue: [initialRectangle _ (characterBlock1 topLeft corner: visibleRectangle right @ characterBlock1 bottom) intersect: visibleRectangle. characterBlock1 bottom = characterBlock2 top ifTrue: [finalRectangle _ (visibleRectangle left @ characterBlock2 top corner: characterBlock2 bottomLeft) intersect: visibleRectangle] ifFalse: [interiorRectangle _ (visibleRectangle left @ characterBlock1 bottom corner: visibleRectangle right @ characterBlock2 top) intersect: visibleRectangle. finalRectangle _ (visibleRectangle left @ characterBlock2 top corner: characterBlock2 bottomLeft) intersect: visibleRectangle]] ifFalse: [initialRectangle _ (visibleRectangle left @ characterBlock1 top corner: characterBlock1 bottomLeft) intersect: visibleRectangle. characterBlock1 top = characterBlock2 bottom ifTrue: [finalRectangle _ (characterBlock2 topLeft corner: visibleRectangle right @ characterBlock2 bottom) intersect: visibleRectangle] ifFalse: [interiorRectangle _ (visibleRectangle left @ characterBlock2 bottom corner: visibleRectangle right @ characterBlock1 top) intersect: visibleRectangle. finalRectangle _ (characterBlock2 topLeft corner: visibleRectangle right @ characterBlock2 bottom) intersect: visibleRectangle]]]. ^ (Array with: initialRectangle with: interiorRectangle with: finalRectangle) select: [:rect | rect notNil]! ! !Paragraph methodsFor: 'scrolling'! scrollBy: heightToMove ^ self scrollBy: heightToMove withSelectionFrom: nil to: nil! ! !Paragraph methodsFor: 'scrolling' stamp: 'hmm 9/16/2000 21:30'! scrollBy: heightToMove withSelectionFrom: startBlock to: stopBlock "Translate the composition rectangle up (dy<0) by heightToMove. Repainting text as necessary, and selection if blocks not nil. Return true unless scrolling limits have been reached." | max min amount | max _ 0 max: "cant scroll up more than dist to (top of) bottom line" compositionRectangle bottom - textStyle lineGrid - clippingRectangle top. min _ 0 min: "cant scroll down more than top is above clipRect" compositionRectangle top - clippingRectangle top. amount _ ((heightToMove truncateTo: textStyle lineGrid) min: max) max: min. amount ~= 0 ifTrue: [destinationForm deferUpdatesIn: clippingRectangle while: [ self scrollUncheckedBy: amount withSelectionFrom: startBlock to: stopBlock]. ^ true] ifFalse: [^ false]! ! !Paragraph methodsFor: 'scrolling'! scrollDelta "By comparing this before and after, you know if scrolling happened" ^ clippingRectangle top - compositionRectangle top! ! !Paragraph methodsFor: 'scrolling'! scrollUncheckedBy: heightToMove withSelectionFrom: startBlock to: stopBlock "Scroll by the given amount. Copy bits where possible, display the rest. If selection blocks are not nil, then select the newly visible text as well." | savedClippingRectangle delta | delta _ 0 @ (0 - heightToMove). compositionRectangle _ compositionRectangle translateBy: delta. startBlock == nil ifFalse: [startBlock moveBy: delta. stopBlock moveBy: delta]. savedClippingRectangle _ clippingRectangle. clippingRectangle _ clippingRectangle intersect: Display boundingBox. heightToMove abs >= clippingRectangle height ifTrue: ["Entire visible region must be repainted" self displayLines: (1 to: lastLine) affectedRectangle: clippingRectangle] ifFalse: ["Copy bits where possible / display the rest" destinationForm copyBits: clippingRectangle from: destinationForm at: clippingRectangle topLeft + delta clippingBox: clippingRectangle rule: Form over fillColor: nil. "Set clippingRectangle to 'vacated' area for lines 'pulled' into view." clippingRectangle _ heightToMove < 0 ifTrue: "On the top" [clippingRectangle topLeft corner: clippingRectangle topRight + delta] ifFalse: "At the bottom" [clippingRectangle bottomLeft + delta corner: clippingRectangle bottomRight]. self displayLines: (1 to: lastLine) "Refresh vacated region" affectedRectangle: clippingRectangle]. startBlock == nil ifFalse: [self reverseFrom: startBlock to: stopBlock]. "And restore the clippingRectangle to its original value. " clippingRectangle _ savedClippingRectangle! ! !Paragraph methodsFor: 'alignment'! centered "Set the alignment for the style with which the receiver displays its text so that text is centered in the composition rectangle." textStyle alignment: Centered! ! !Paragraph methodsFor: 'alignment'! justified "Set the alignment for the style with which the receiver displays its text so that the characters in each of text end on an even border in the composition rectangle." textStyle alignment: Justified! ! !Paragraph methodsFor: 'alignment'! leftFlush "Set the alignment for the style with which the receiver displays its text so that the characters in each of text begin on an even border in the composition rectangle. This is also known as ragged-right." textStyle alignment: LeftFlush! ! !Paragraph methodsFor: 'alignment'! rightFlush "Set the alignment for the style with which the receiver displays its text so that the characters in each of text end on an even border in the composition rectangle but the beginning of each line does not. This is also known as ragged-left." textStyle alignment: RightFlush! ! !Paragraph methodsFor: 'alignment'! toggleAlignment "Set the alignment for the style with which the receiver displays its text so that it moves from centered to justified to leftFlush to rightFlush and back to centered again." textStyle alignment: textStyle alignment + 1! ! !Paragraph methodsFor: 'indicating'! flash "Complement twice the visible area in which the receiver displays." Display flash: clippingRectangle! ! !Paragraph methodsFor: 'indicating'! outline "Display a border around the visible area in which the receiver presents its text." clippingRectangle bottom <= compositionRectangle bottom ifTrue: [Display border: (clippingRectangle intersect: compositionRectangle) width: 2] ifFalse: [Display border: (clippingRectangle intersect: destinationForm boundingBox) width: 2]. ! ! !Paragraph methodsFor: 'utilities'! clearVisibleRectangle "Display the area in which the receiver presents its text so that the area is all one tone--in this case, all white." destinationForm fill: clippingRectangle rule: rule fillColor: self backgroundColor! ! !Paragraph methodsFor: 'utilities'! deepCopy "Don't want to copy the destForm (Display) or fonts in the TextStyle. 9/13/96 tk" | new | new _ self copy. new textStyle: textStyle copy. new destinationForm: destinationForm. new lines: lines copy. new text: text deepCopy. ^ new! ! !Paragraph methodsFor: 'utilities'! destinationForm: destForm destinationForm _ destForm! ! !Paragraph methodsFor: 'utilities'! fit "Make the bounding rectangle of the receiver contain all the text without changing the width of the receiver's composition rectangle." [(self lineIndexOfTop: clippingRectangle top) = 1] whileFalse: [self scrollBy: (0-1)*textStyle lineGrid]. self updateCompositionHeight. clippingRectangle _ clippingRectangle withBottom: compositionRectangle bottom! ! !Paragraph methodsFor: 'utilities'! lines: lineArray lines _ lineArray! ! !Paragraph methodsFor: 'utilities'! visibleRectangle "May be less than the clippingRectangle if text ends part way down. Also some fearful history includes Display intersection; it shouldn't be necessary" ^ (clippingRectangle intersect: compositionRectangle) intersect: destinationForm boundingBox! ! !Paragraph methodsFor: 'converting' stamp: 'yo 6/23/2003 19:05'! asForm "Answer a Form made up of the bits that represent the receiver's displayable text." | theForm oldBackColor oldForeColor | textStyle isTTCStyle ifTrue: [ theForm _ (Form extent: compositionRectangle extent depth: 32) offset: offset. ] ifFalse: [ theForm _ (ColorForm extent: compositionRectangle extent) offset: offset; colors: (Array with: (backColor == nil ifTrue: [Color transparent] ifFalse: [backColor]) with: (foreColor == nil ifTrue: [Color black] ifFalse: [foreColor])). ]. oldBackColor _ backColor. oldForeColor _ foreColor. backColor _ Color white. foreColor _ Color black. self displayOn: theForm at: 0@0 clippingBox: theForm boundingBox rule: Form over fillColor: nil. backColor _ oldBackColor. foreColor _ oldForeColor. ^ theForm "Example: | p | p _ 'Abc' asParagraph. p foregroundColor: Color red backgroundColor: Color black. p asForm displayOn: Display at: 30@30 rule: Form over" ! ! !Paragraph methodsFor: 'converting'! asString "Answer the string of characters of the receiver's text." ^text string! ! !Paragraph methodsFor: 'converting'! asText "Answer the receiver's text." ^text! ! !Paragraph methodsFor: 'private'! bottomAtLineIndex: lineIndex "Answer the bottom y of given line." | y | y _ compositionRectangle top. lastLine = 0 ifTrue: [^ y + textStyle lineGrid]. 1 to: (lineIndex min: lastLine) do: [:i | y _ y + (lines at: i) lineHeight]. ^ y ! ! !Paragraph methodsFor: 'private' stamp: 'tk 9/30/96'! compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint compositionRectangle _ compositionRect copy. text _ aText. textStyle _ aTextStyle. rule _ DefaultRule. mask _ nil. "was DefaultMask " marginTabsLevel _ 0. destinationForm _ Display. offset _ aPoint. ^self composeAll! ! !Paragraph methodsFor: 'private'! compositionRectangleDelta "A handy number -- mostly for scrolling." ^compositionRectangle top - clippingRectangle top! ! !Paragraph methodsFor: 'private'! displayLines: linesInterval ^ self displayLines: linesInterval affectedRectangle: self visibleRectangle! ! !Paragraph methodsFor: 'private' stamp: 'ar 5/18/2000 18:34'! displayLines: linesInterval affectedRectangle: affectedRectangle "This is the first level workhorse in the display portion of the TextForm routines. It checks to see which lines in the interval are actually visible, has the CharacterScanner display only those, clears out the areas in which display will occur, and clears any space remaining in the visibleRectangle following the space occupied by lastLine." | lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom | "Save some time by only displaying visible lines" firstLineIndex _ self lineIndexOfTop: affectedRectangle top. firstLineIndex < linesInterval first ifTrue: [firstLineIndex _ linesInterval first]. lastLineIndex _ self lineIndexOfTop: affectedRectangle bottom - 1. lastLineIndex > linesInterval last ifTrue: [linesInterval last > lastLine ifTrue: [lastLineIndex _ lastLine] ifFalse: [lastLineIndex _ linesInterval last]]. lastLineIndexBottom _ (self bottomAtLineIndex: lastLineIndex). ((Rectangle origin: affectedRectangle left @ (topY _ self topAtLineIndex: firstLineIndex) corner: affectedRectangle right @ lastLineIndexBottom) intersects: affectedRectangle) ifTrue: [ " . . . (skip to clear-below if no lines displayed)" DisplayScanner new displayLines: (firstLineIndex to: lastLineIndex) in: self clippedBy: affectedRectangle]. lastLineIndex = lastLine ifTrue: [destinationForm "Clear out white space below last line" fill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top) corner: affectedRectangle bottomRight) rule: rule fillColor: self backgroundColor]! ! !Paragraph methodsFor: 'private'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | saveDestinationForm _ destinationForm. destinationForm _ aDisplayMedium. self displayLines: lineInterval. destinationForm _ saveDestinationForm! ! !Paragraph methodsFor: 'private'! leftMarginForCompositionForLine: lineIndex "Build the left margin for composition of a line. Depends upon marginTabsLevel and the indent." | indent | lineIndex = 1 ifTrue: [indent _ textStyle firstIndent] ifFalse: [indent _ textStyle restIndent]. ^indent + (textStyle leftMarginTabAt: marginTabsLevel)! ! !Paragraph methodsFor: 'private' stamp: 'ar 12/15/2001 23:29'! leftMarginForDisplayForLine: lineIndex alignment: alignment "Build the left margin for display of a line. Depends upon leftMarginForComposition, compositionRectangle left and the alignment." | pad | (alignment = LeftFlush or: [alignment = Justified]) ifTrue: [^compositionRectangle left + (self leftMarginForCompositionForLine: lineIndex)]. "When called from character location code and entire string has been cut, there are no valid lines, hence following nil check." (lineIndex <= lines size and: [(lines at: lineIndex) notNil]) ifTrue: [pad _ (lines at: lineIndex) paddingWidth] ifFalse: [pad _ compositionRectangle width - textStyle firstIndent - textStyle rightIndent]. alignment = Centered ifTrue: [^compositionRectangle left + (self leftMarginForCompositionForLine: lineIndex) + (pad // 2)]. alignment = RightFlush ifTrue: [^compositionRectangle left + (self leftMarginForCompositionForLine: lineIndex) + pad]. self error: ['no such alignment']! ! !Paragraph methodsFor: 'private'! lineAt: indexInteger put: aTextLineInterval "Store a line, track last, and grow lines if necessary." indexInteger > lastLine ifTrue: [lastLine _ indexInteger]. lastLine > lines size ifTrue: [lines _ lines , (Array new: lines size)]. ^lines at: indexInteger put: aTextLineInterval! ! !Paragraph methodsFor: 'private'! lineIndexOfCharacterIndex: characterIndex "Answer the line index for a given characterIndex." 1 to: lastLine do: [:lineIndex | (lines at: lineIndex) last >= characterIndex ifTrue: [^lineIndex]]. ^lastLine! ! !Paragraph methodsFor: 'private'! lineIndexOfTop: top "Answer the line index at a given top y." | y line | lastLine = 0 ifTrue: [^ 1]. y _ compositionRectangle top. 1 to: lastLine do: [:i | line _ lines at: i. (y _ y + line lineHeight) > top ifTrue: [^ i]]. ^ lastLine ! ! !Paragraph methodsFor: 'private'! lines ^lines! ! !Paragraph methodsFor: 'private'! moveBy: delta compositionRectangle _ compositionRectangle translateBy: delta. clippingRectangle _ clippingRectangle translateBy: delta. ! ! !Paragraph methodsFor: 'private'! rightMarginForComposition "Build the right margin for a line. Depends upon compositionRectangle width, marginTabsLevel, and right indent." ^compositionRectangle width - (textStyle rightMarginTabAt: marginTabsLevel) - textStyle rightIndent! ! !Paragraph methodsFor: 'private'! rightMarginForDisplay "Build the right margin for a line. Depends upon compositionRectangle rightSide, marginTabsLevel, and right indent." ^compositionRectangle right - textStyle rightIndent - (textStyle rightMarginTabAt: marginTabsLevel)! ! !Paragraph methodsFor: 'private'! setWithText: aText style: aTextStyle "Set text and adjust bounding rectangles to fit." | shrink compositionWidth unbounded | unbounded _ Rectangle origin: 0 @ 0 extent: 9999@9999. compositionWidth _ self setWithText: aText style: aTextStyle compositionRectangle: unbounded clippingRectangle: unbounded. compositionRectangle _ compositionRectangle withWidth: compositionWidth. clippingRectangle _ compositionRectangle copy. shrink _ unbounded width - compositionWidth. "Shrink padding widths accordingly" 1 to: lastLine do: [:i | (lines at: i) paddingWidth: (lines at: i) paddingWidth - shrink]! ! !Paragraph methodsFor: 'private'! setWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect "Set text and using supplied parameters. Answer max composition width." clippingRectangle _ clipRect copy. ^self compositionRectangle: compRect text: aText style: aTextStyle offset: 0 @ 0! ! !Paragraph methodsFor: 'private'! setWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: cf backColor: cb "Set text and using supplied parameters. Answer max composition width." clippingRectangle _ clipRect copy. self foregroundColor: cf backgroundColor: cb. ^ self compositionRectangle: compRect text: aText style: aTextStyle offset: 0 @ 0! ! !Paragraph methodsFor: 'private'! topAtLineIndex: lineIndex "Answer the top y of given line." | y | y _ compositionRectangle top. lastLine = 0 ifTrue: [lineIndex > 0 ifTrue: [^ y + textStyle lineGrid]. ^ y]. 1 to: (lineIndex-1 min: lastLine) do: [:i | y _ y + (lines at: i) lineHeight]. ^ y ! ! !Paragraph methodsFor: 'private'! topAtLineIndex: lineIndex using: otherLines and: otherLastLine "Answer the top y of given line." | y | y _ compositionRectangle top. otherLastLine = 0 ifTrue: [^ y]. 1 to: (lineIndex-1 min: otherLastLine) do: [:i | y _ y + (otherLines at: i) lineHeight]. ^ y ! ! !Paragraph methodsFor: 'private'! trimLinesTo: lastLineInteger (lastLineInteger + 1 to: lastLine) do: [:i | lines at: i put: nil]. (lastLine _ lastLineInteger) < (lines size // 2) ifTrue: [lines _ lines copyFrom: 1 to: lines size - (lines size // 2)]! ! !Paragraph methodsFor: 'private'! updateCompositionHeight "Mainly used to insure that intersections with compositionRectangle work." compositionRectangle _ compositionRectangle withHeight: (self bottomAtLineIndex: lastLine) - compositionRectangle top. (text size ~= 0 and: [(text at: text size) = CR]) ifTrue: [compositionRectangle _ compositionRectangle withHeight: compositionRectangle height + (lines at: lastLine) lineHeight]! ! !Paragraph methodsFor: 'private' stamp: 'di 8/30/97 11:14'! withClippingRectangle: clipRect do: aBlock | saveClip | saveClip _ clippingRectangle. clippingRectangle _ clipRect. aBlock value. clippingRectangle _ saveClip! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Paragraph class instanceVariableNames: ''! !Paragraph class methodsFor: 'instance creation'! new "Do not allow an uninitialized view. Create with text that has no characters." ^self withText: '' asText! ! !Paragraph class methodsFor: 'instance creation'! withText: aText "Answer an instance of me with text set to aText and style set to the system's default text style." ^self withText: aText style: DefaultTextStyle copy! ! !Paragraph class methodsFor: 'instance creation'! withText: aText style: aTextStyle "Answer an instance of me with text set to aText and style set to aTextStyle." ^super new setWithText: aText style: aTextStyle! ! !Paragraph class methodsFor: 'instance creation'! withText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: c1 backColor: c2 "Answer an instance of me with text set to aText and style set to aTextStyle, composition rectangle is compRect and the clipping rectangle is clipRect." | para | para _ super new. para setWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: c1 backColor: c2. ^para! ! !Paragraph class methodsFor: 'examples' stamp: 'tk 9/30/96'! example "This simple example illustrates how to display a few lines of text on the screen at the current cursor point. Fixed. " | para point | point _ Sensor waitButton. para _ 'This is the first line of characters and this is the second line.' asParagraph. para displayOn: Display at: point. "Paragraph example"! ! ScrollController subclass: #ParagraphEditor instanceVariableNames: 'paragraph startBlock stopBlock beginTypeInBlock emphasisHere initialText selectionShowing otherInterval lastParenLocation' classVariableNames: 'ChangeText CmdActions FindText Keyboard ShiftCmdActions TextEditorYellowButtonMenu UndoInterval UndoMessage UndoParagraph UndoSelection Undone' poolDictionaries: 'TextConstants' category: 'Kernel-ST80 Remnants'! !ParagraphEditor commentStamp: '<historical>' prior: 0! 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.! !ParagraphEditor methodsFor: 'initialize-release'! changeParagraph: aParagraph "Install aParagraph as the one to be edited by the receiver." UndoParagraph == paragraph ifTrue: [UndoParagraph _ nil]. paragraph _ aParagraph. self resetState! ! !ParagraphEditor methodsFor: 'initialize-release' stamp: 'th 10/21/2003 15:49'! resetState "Establish the initial conditions for editing the paragraph: place caret before first character, set the emphasis to that of the first character, and save the paragraph for purposes of canceling." stopBlock _ paragraph defaultCharacterBlock. self pointBlock: stopBlock copy. beginTypeInBlock _ nil. UndoInterval _ otherInterval _ 1 to: 0. self setEmphasisHere. selectionShowing _ false. initialText _ paragraph text copy! ! !ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 5/15/2000 13:51'! stateArray ^ {ChangeText. FindText. UndoInterval. UndoMessage. UndoParagraph. UndoSelection. Undone. self selectionInterval. self startOfTyping. emphasisHere}! ! !ParagraphEditor methodsFor: 'initialize-release' stamp: 'di 10/5/1998 17:03'! stateArrayPut: stateArray | sel | ChangeText _ stateArray at: 1. FindText _ stateArray at: 2. UndoInterval _ stateArray at: 3. UndoMessage _ stateArray at: 4. UndoParagraph _ stateArray at: 5. UndoSelection _ stateArray at: 6. Undone _ stateArray at: 7. sel _ stateArray at: 8. self selectFrom: sel first to: sel last. beginTypeInBlock _ stateArray at: 9. emphasisHere _ stateArray at: 10.! ! !ParagraphEditor methodsFor: 'accessing' stamp: 'tk 4/21/1998 09:55'! initialText ^ initialText! ! !ParagraphEditor methodsFor: 'accessing'! replace: oldInterval with: newText and: selectingBlock "Replace the text in oldInterval with newText and execute selectingBlock to establish the new selection. Create an undoAndReselect:redoAndReselect: undoer to allow perfect undoing." | undoInterval | undoInterval _ self selectionInterval. undoInterval = oldInterval ifFalse: [self selectInterval: oldInterval]. UndoSelection _ self selection. self zapSelectionWith: newText. selectingBlock value. otherInterval _ self selectionInterval. self undoer: #undoAndReselect:redoAndReselect: with: undoInterval with: otherInterval! ! !ParagraphEditor methodsFor: 'accessing'! replaceSelectionWith: aText "Remember the selection text in UndoSelection. Deselect, and replace the selection text by aText. Remember the resulting selectionInterval in UndoInterval and PriorInterval. Set up undo to use UndoReplace." beginTypeInBlock ~~ nil ifTrue: [^self zapSelectionWith: aText]. "called from old code" UndoSelection _ self selection. self zapSelectionWith: aText. self undoer: #undoReplace! ! !ParagraphEditor methodsFor: 'accessing'! setSearch: aString "Set the FindText and ChangeText to seek aString; except if already seeking aString, leave ChangeText alone so again will repeat last replacement." FindText string = aString ifFalse: [FindText _ ChangeText _ aString asText]! ! !ParagraphEditor methodsFor: 'accessing'! text "Answer the text of the paragraph being edited." ^paragraph text! ! !ParagraphEditor methodsFor: 'accessing' stamp: 'jm 3/18/98 20:38'! userHasEdited "Note that the user has edited my text. Here it is just a noop so that the Character Recognizer won't fail when used with a vanilla ParagrahEditor." ! ! !ParagraphEditor methodsFor: 'controlling'! controlInitialize super controlInitialize. self recomputeInterval. self initializeSelection. beginTypeInBlock _ nil! ! !ParagraphEditor methodsFor: 'controlling'! controlTerminate self closeTypeIn. "Must call to establish UndoInterval" super controlTerminate. self deselect! ! !ParagraphEditor methodsFor: 'controlling' stamp: 'sma 3/11/2000 15:17'! normalActivity self processKeyboard. self processMouseButtons! ! !ParagraphEditor methodsFor: 'scrolling'! computeMarkerRegion "Refer to the comment in ScrollController|computeMarkerRegion." paragraph compositionRectangle height = 0 ifTrue: [^0@0 extent: Preferences scrollBarWidth @ scrollBar inside height] ifFalse: [^0@0 extent: Preferences scrollBarWidth @ ((paragraph clippingRectangle height asFloat / self scrollRectangleHeight * scrollBar inside height) rounded min: scrollBar inside height)]! ! !ParagraphEditor methodsFor: 'scrolling'! markerDelta ^marker top - scrollBar top - ((paragraph clippingRectangle top - paragraph compositionRectangle top) asFloat / (self scrollRectangleHeight max: 1) asFloat * scrollBar height asFloat) rounded! ! !ParagraphEditor methodsFor: 'scrolling'! scrollAmount "Refer to the comment in ScrollController|scrollAmount." ^sensor cursorPoint y - scrollBar top! ! !ParagraphEditor methodsFor: 'scrolling'! scrollBar ^ scrollBar! ! !ParagraphEditor methodsFor: 'scrolling' stamp: 'BG 12/12/2003 15:31'! scrollBy: heightToMove "Move the paragraph by heightToMove, and reset the text selection." ^ paragraph scrollBy: heightToMove withSelectionFrom: self pointBlock to: self markBlock! ! !ParagraphEditor methodsFor: 'scrolling'! scrollRectangleHeight ^paragraph compositionRectangle height + paragraph lineGrid! ! !ParagraphEditor methodsFor: 'scrolling'! scrollToBottom "Scroll so that the tail end of the text is visible in the view. 5/6/96 sw" self scrollView: (paragraph clippingRectangle bottom - paragraph compositionRectangle bottom)! ! !ParagraphEditor methodsFor: 'scrolling'! scrollToTop "Scroll so that the paragraph is at the top of the view." self scrollView: (paragraph clippingRectangle top - paragraph compositionRectangle top)! ! !ParagraphEditor methodsFor: 'scrolling'! scrollView: anInteger "Paragraph scrolling uses opposite polarity" ^ self scrollBy: anInteger negated! ! !ParagraphEditor methodsFor: 'scrolling'! updateMarker "A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph." self moveMarkerTo: self computeMarkerRegion! ! !ParagraphEditor methodsFor: 'scrolling'! viewDelta "Refer to the comment in ScrollController|viewDelta." ^paragraph clippingRectangle top - paragraph compositionRectangle top - ((marker top - scrollBar inside top) asFloat / scrollBar inside height asFloat * self scrollRectangleHeight asFloat) roundTo: paragraph lineGrid! ! !ParagraphEditor methodsFor: 'sensor access'! processBlueButton "The user pressed the blue button on the mouse. Determine what action to take." ^self! ! !ParagraphEditor methodsFor: 'sensor access'! processKeyboard "Determine whether the user pressed the keyboard. If so, read the keys." sensor keyboardPressed ifTrue: [self readKeyboard]! ! !ParagraphEditor methodsFor: 'sensor access'! processMouseButtons "Determine whether the user pressed any mouse button. For each possible button, determine what actions to take." sensor redButtonPressed ifTrue: [self processRedButton]. sensor yellowButtonPressed ifTrue: [self processYellowButton]. sensor blueButtonPressed ifTrue: [self processBlueButton]! ! !ParagraphEditor methodsFor: 'sensor access' stamp: 'th 9/19/2002 18:24'! processRedButton "The user pressed a red mouse button, meaning create a new text selection. Highlighting the selection is carried out by the paragraph itself. Double clicking causes a selection of the area between the nearest enclosing delimitors." | selectionBlocks clickPoint oldDelta oldInterval previousMarkBlock previousPointBlock | clickPoint _ sensor cursorPoint. (view containsPoint: clickPoint) ifFalse: [^ self]. (paragraph clickAt: clickPoint for: model controller: self) ifTrue: [^ self]. oldInterval _ self selectionInterval. previousMarkBlock _ self markBlock. previousPointBlock _ self pointBlock. oldDelta _ paragraph scrollDelta. sensor leftShiftDown ifFalse: [self deselect. self closeTypeIn. selectionBlocks _ paragraph mouseSelect: clickPoint] ifTrue: [selectionBlocks _ paragraph extendSelectionMark: self markBlock pointBlock: self pointBlock. self closeTypeIn]. selectionShowing _ true. self markBlock: (selectionBlocks at: 1). self pointBlock: (selectionBlocks at: 2). (self hasCaret and: [previousMarkBlock = self markBlock and: [previousPointBlock = self pointBlock]]) ifTrue: [self selectWord]. oldDelta ~= paragraph scrollDelta "case of autoscroll" ifTrue: [self updateMarker]. self setEmphasisHere. (self isDisjointFrom: oldInterval) ifTrue: [otherInterval _ oldInterval]! ! !ParagraphEditor methodsFor: 'sensor access'! processYellowButton "User pressed the yellow button on the mouse. Determine what actions to take." self yellowButtonActivity! ! !ParagraphEditor methodsFor: 'displaying'! display "Redisplay the paragraph." | selectionState | selectionState _ selectionShowing. self deselect. paragraph foregroundColor: view foregroundColor backgroundColor: view backgroundColor; displayOn: Display. selectionState ifTrue: [self select]! ! !ParagraphEditor methodsFor: 'displaying'! flash "Causes the view of the paragraph to complement twice in succession." paragraph flash! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'jm 5/3/1998 19:19'! accept "Save the current text of the text being edited as the current acceptable version for purposes of canceling." initialText _ paragraph text copy. ! ! !ParagraphEditor methodsFor: 'menu messages'! again "Text substitution. If the left shift key is down, the substitution is made throughout the entire Paragraph. Otherwise, only the next possible substitution is made. Undoer & Redoer: #undoAgain:andReselect:typedKey:." "If last command was also 'again', use same keys as before" self againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:)! ! !ParagraphEditor methodsFor: 'menu messages'! align "Align text according to the next greater alignment value--cycling among left flush, right flush, center, justified. No effect on the undoability of the pre preceding command." paragraph toggleAlignment. paragraph displayOn: Display. self recomputeInterval! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 4/24/2001 12:22'! browseChangeSetsWithSelector "Determine which, if any, change sets have at least one change for the selected selector, independent of class" | aSelector | self lineSelectAndEmptyCheck: [^ self]. (aSelector _ self selectedSelector) == nil ifTrue: [^ view flash]. self terminateAndInitializeAround: [ChangeSorter browseChangeSetsWithSelector: aSelector]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 1/16/2004 21:14'! browseClassFromIt "Launch a hierarchy browser for the class indicated by the current selection. If multiple classes matching the selection exist, let the user choose among them." | aClass | self lineSelectAndEmptyCheck: [^ self]. aClass _ Utilities classFromPattern: (self selection string copyWithout: Character cr) withCaption: 'choose a class to browse...'. aClass ifNil: [^ view flash]. self terminateAndInitializeAround: [self systemNavigation spawnHierarchyForClass: aClass selector: nil]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 09:42'! browseIt "Launch a browser for the current selection, if appropriate" | aSymbol anEntry brow | Preferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt]. self lineSelectAndEmptyCheck: [^ self]. (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash]. self terminateAndInitializeAround: [aSymbol first isUppercase ifTrue: [anEntry _ (Smalltalk at: aSymbol ifAbsent: [ self systemNavigation browseAllImplementorsOf: aSymbol. ^ nil]). anEntry isNil ifTrue: [^ view flash]. (anEntry isKindOf: Class) ifFalse: [anEntry _ anEntry class]. brow _ Preferences browseToolClass new. brow setClass: anEntry selector: nil. brow class openBrowserView: (brow openEditString: nil) label: 'System Browser'] ifFalse: [ self systemNavigation browseAllImplementorsOf: aSymbol]]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 6/23/1998 11:08'! browseItHere "Retarget the receiver's window to look at the selected class, if appropriate. 3/1/96 sw" | aSymbol foundClass b | (((b _ model) isKindOf: Browser) and: [b couldBrowseAnyClass]) ifFalse: [^ view flash]. model okToChange ifFalse: [^ view flash]. self selectionInterval isEmpty ifTrue: [self selectWord]. (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash]. self terminateAndInitializeAround: [foundClass _ (Smalltalk at: aSymbol ifAbsent: [nil]). foundClass isNil ifTrue: [^ view flash]. (foundClass isKindOf: Class) ifTrue: [model systemCategoryListIndex: (model systemCategoryList indexOf: foundClass category). model classListIndex: (model classList indexOf: foundClass name)]]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 1/15/98 12:57'! cancel "Restore the text of the paragraph to be the text saved since initialization or the last accept. Undoer & Redoer: undoAndReselect:redoAndReselect:. This used to call controlTerminate and controlInitialize but this seemed illogical. Sure enough, nobody overrode them who had cancel in the menu, and if anybody really cared they could override cancel." UndoSelection _ paragraph text. self undoer: #undoAndReselect:redoAndReselect: with: self selectionInterval with: (1 to: 0). view ifNotNil: [view clearInside]. self changeParagraph: (paragraph text: initialText). UndoParagraph _ paragraph. otherInterval _ UndoInterval _ 1 to: initialText size. "so undo will replace all" paragraph displayOn: Display. self selectAt: 1. self scrollToTop ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 12/17/2001 12:54'! changeAlignment | aList reply | aList _ #(leftFlush centered justified rightFlush). reply _ (SelectionMenu labelList: aList selections: aList) startUp. reply ifNil:[^self]. self setAlignment: reply. paragraph composeAll. self recomputeSelection. self mvcRedisplay. ^ true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'fc 2/19/2004 22:09'! changeEmphasis | aList reply | aList _ #(normal bold italic narrow underlined struckOut). reply _ (SelectionMenu labelList: aList selections: aList) startUp. reply ~~ nil ifTrue: [self setEmphasis: reply. paragraph composeAll. self recomputeSelection. self mvcRedisplay]. ^ true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'fc 2/19/2004 22:09'! changeEmphasisOrAlignment | aList reply | aList _ #(normal bold italic narrow underlined struckOut leftFlush centered rightFlush justified). reply _ (SelectionMenu labelList: aList lines: #(6) selections: aList) startUp. reply ~~ nil ifTrue: [(#(leftFlush centered rightFlush justified) includes: reply) ifTrue: [paragraph perform: reply. self recomputeInterval] ifFalse: [self setEmphasis: reply. paragraph composeAll. self recomputeSelection. self mvcRedisplay]]. ^ true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'md 10/22/2003 15:27'! changeStyle "Let user change styles for the current text pane Moved from experimentalCommand to its own method " | aList reply style | aList _ StrikeFont actualFamilyNames. aList addFirst: 'DefaultTextStyle'. reply _ (SelectionMenu labelList: aList lines: #(1) selections: aList) startUp. reply ifNotNil: [(style _ TextStyle named: reply) ifNil: [Beeper beep. ^ true]. paragraph textStyle: style copy. paragraph composeAll. self recomputeSelection. self mvcRedisplay]. ^ true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'RAA 3/15/2001 12:10'! changeStyleTo: aNewStyle paragraph textStyle: aNewStyle. paragraph composeAll. self recomputeSelection. ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 9/27/1999 11:54'! chooseAlignment self changeAlignment! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/15/2003 22:40'! classCommentsContainingIt "Open a browser class comments which contain the current selection somewhere in them." self lineSelectAndEmptyCheck: [^ self]. self terminateAndInitializeAround: [ self systemNavigation browseClassCommentsWithString: self selection string]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'dvf 8/23/2003 11:51'! classNamesContainingIt "Open a browser on classes whose names contain the selected string" self lineSelectAndEmptyCheck: [^self]. self systemNavigation browseClassesWithNamesContaining: self selection string caseSensitive: Sensor leftShiftDown! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:37'! clipboardText ^ Clipboard clipboardText! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'! clipboardText: text ^ Clipboard clipboardText: text! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:38'! clipboardTextPut: text ^ Clipboard clipboardText: text! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 11/23/1998 15:21'! compareToClipboard "Check to see if whether the receiver's text is the same as the text currently on the clipboard, and inform the user." | s1 s2 | s1 _ self clipboardText string. s2 _ paragraph text string. s1 = s2 ifTrue: [^ self inform: 'Exact match']. (StringHolder new textContents: (TextDiffBuilder buildDisplayPatchFrom: s1 to: s2)) openLabel: 'Comparison to Clipboard Text'! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 15:09'! copySelection "Copy the current selection and store it in the paste buffer, unless a caret. Undoer & Redoer: undoCutCopy" self lineSelectAndEmptyCheck: [^ self]. "Simulate 'substitute: self selection' without locking the controller" UndoSelection _ self selection. self undoer: #undoCutCopy: with: self clipboardText. UndoInterval _ self selectionInterval. self clipboardTextPut: UndoSelection! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 8/1/97 16:33'! cut "Cut out the current selection and redisplay the paragraph if necessary. Undoer & Redoer: undoCutCopy:" self lineSelectAndEmptyCheck: [^ self]. self replaceSelectionWith: self nullText. self undoer: #undoCutCopy: with: self clipboardText. self clipboardTextPut: UndoSelection! ! !ParagraphEditor methodsFor: 'menu messages'! exchange "See comment in exchangeWith:" self exchangeWith: otherInterval! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:34'! experimentalCommand "Use for experimental command-key implementation. Using this, you can try things out without forever needing to reinitialize the ParagraphEditor." self prettyPrint. ^ true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ls 10/10/1999 11:36'! explain "Try to shed some light on what kind of entity the current selection is. The selection must be a single token or construct. Insert the answer after the selection. Send private messages whose names begin with 'explain' that return a string if they recognize the selection, else nil." | string tiVars cgVars selectors delimitors numbers sorry reply symbol | Cursor execute showWhile: [sorry _ '"Sorry, I can''t explain that. Please select a single token, construct, or special character.'. sorry _ sorry , (view canDiscardEdits ifFalse: [' Also, please cancel or accept."'] ifTrue: ['"']). (string _ self selection asString) isEmpty ifTrue: [reply _ ''] ifFalse: [string _ self explainScan: string. "Remove space, tab, cr" "Temps and Instance vars need only test strings that are all letters" (string detect: [:char | (char isLetter or: [char isDigit]) not] ifNone: []) ifNil: [tiVars _ self explainTemp: string. tiVars == nil ifTrue: [tiVars _ self explainInst: string]]. (tiVars == nil and: [model respondsTo: #explainSpecial:]) ifTrue: [tiVars _ model explainSpecial: string]. tiVars == nil ifTrue: [tiVars _ ''] ifFalse: [tiVars _ tiVars , '\' withCRs]. "Context, Class, Pool, and Global vars, and Selectors need only test symbols" (Symbol hasInterned: string ifTrue: [:s | symbol _ s]) ifTrue: [cgVars _ self explainCtxt: symbol. cgVars == nil ifTrue: [cgVars _ self explainClass: symbol. cgVars == nil ifTrue: [cgVars _ self explainGlobal: symbol]]. "See if it is a Selector (sent here or not)" selectors _ self explainMySel: symbol. selectors == nil ifTrue: [selectors _ self explainPartSel: string. selectors == nil ifTrue: [ selectors _ self explainAnySel: symbol]]] ifFalse: [selectors _ self explainPartSel: string]. cgVars == nil ifTrue: [cgVars _ ''] ifFalse: [cgVars _ cgVars , '\' withCRs]. selectors == nil ifTrue: [selectors _ ''] ifFalse: [selectors _ selectors , '\' withCRs]. string size = 1 ifTrue: ["single special characters" delimitors _ self explainChar: string] ifFalse: ["matched delimitors" delimitors _ self explainDelimitor: string]. numbers _ self explainNumber: string. numbers == nil ifTrue: [numbers _ '']. delimitors == nil ifTrue: [delimitors _ '']. reply _ tiVars , cgVars , selectors , delimitors , numbers]. reply size = 0 ifTrue: [reply _ sorry]. self afterSelectionInsertAndSelect: reply]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:41'! fileItIn "Make a Stream on the text selection and fileIn it. 1/24/96 sw: moved here from FileController; this function can be useful from any text window that shows stuff in chunk format" | selection | selection _ self selection. self terminateAndInitializeAround: [(ReadWriteStream on: selection string from: 1 to: selection size) fileIn]. ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 10/5/1998 21:55'! find "Prompt the user for a string to search for, and search the receiver from the current selection onward for it. 1/26/96 sw" | reply | reply _ FillInTheBlank request: 'Find what? ' initialAnswer: ''. reply size == 0 ifTrue: [^ self]. self setSearch: reply. ChangeText _ FindText. "Implies no replacement to againOnce: method" self againOrSame: true ! ! !ParagraphEditor methodsFor: 'menu messages'! findAgain "Find the text-to-find again. 1/24/96 sw" self againOrSame: true! ! !ParagraphEditor methodsFor: 'menu messages'! fit "Make the bounding rectangle of the paragraph contain all the text while not changing the width of the view of the paragraph. No effect on undoability of the preceding command." paragraph clearVisibleRectangle. paragraph fit. paragraph displayOn: Display; outline. self recomputeInterval! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 09:42'! implementorsOfIt "Open an implementors browser on the selected selector" | aSelector | self lineSelectAndEmptyCheck: [^ self]. (aSelector _ self selectedSelector) == nil ifTrue: [^ view flash]. self terminateAndInitializeAround: [ self systemNavigation browseAllImplementorsOf: aSelector]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:12'! lineSelectAndEmptyCheck: returnBlock "If the current selection is an insertion point, expand it to be the entire current line; if after that's done the selection is still empty, then evaluate the returnBlock, which will typically consist of '[^ self]' in the caller -- check senders of this method to understand this." self selectLine. "if current selection is an insertion point, then first select the entire line in which occurs before proceeding" self hasSelection ifFalse: [self flash. ^ returnBlock value]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:31'! methodNamesContainingIt "Open a browser on methods names containing the selected string" self lineSelectAndEmptyCheck: [^ self]. Cursor wait showWhile: [self terminateAndInitializeAround: [self systemNavigation browseMethodsWhoseNamesContain: self selection string withBlanksTrimmed]]. Cursor normal show! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/15/2003 22:35'! methodSourceContainingIt "Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source). EXTREMELY slow!!" self lineSelectAndEmptyCheck: [^ self]. (self confirm: 'This will take a few minutes. Shall I proceed?') ifFalse: [^ self]. self systemNavigation browseMethodsWithSourceString: self selection string! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:28'! methodStringsContainingit "Open a browser on methods which contain the current selection as part of a string constant." self lineSelectAndEmptyCheck: [^ self]. self terminateAndInitializeAround: [self systemNavigation browseMethodsWithString: self selection string]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 10/2/97 11:34'! mvcRedisplay "Overridable by subclasses that do their own display" Display fill: paragraph clippingRectangle fillColor: view backgroundColor. "very brute force" self display! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/20/2002 11:21'! paste "Paste the text from the shared buffer over the current selection and redisplay if necessary. Undoer & Redoer: undoAndReselect." self replace: self selectionInterval with: self clipboardText and: [self selectAt: self pointIndex]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ar 1/15/2001 18:36'! pasteRecent "Paste an item chose from RecentClippings." | clipping | (clipping _ Clipboard chooseRecentClipping) ifNil: [^ self]. Clipboard clipboardText: clipping. ^ self paste! ! !ParagraphEditor methodsFor: 'menu messages'! performMenuMessage: aSelector "If a menu command is invoked, typeIn must be closed first, the selection must be unhighlighted before and rehighlighted after, and the marker must be updated." self closeTypeIn. self deselect. super performMenuMessage: aSelector. self selectAndScroll. self updateMarker! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 1/19/2004 20:59'! presentSpecialMenu "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" | reply items | self terminateAndInitializeAround: [reply _ (PopUpMenu labelArray: (items _ self specialMenuItems) lines: #()) startUp. reply = 0 ifTrue: [^ self]. Compiler new evaluate: (items at: reply) in: [] to: self] ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'! prettyPrint self prettyPrint: false! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:41'! prettyPrint: decorated "Reformat the contents of the receiver's view (a Browser)." | selectedClass newText | model selectedMessageCategoryName ifNil: [^ view flash]. selectedClass _ model selectedClassOrMetaClass. newText _ selectedClass compilerClass new format: self text in: selectedClass notifying: self decorated: decorated. newText ifNotNil: [self deselect; selectInvisiblyFrom: 1 to: paragraph text size. self replaceSelectionWith: (newText asText makeSelectorBoldIn: selectedClass). self selectAt: 1]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sma 5/28/2000 09:40'! prettyPrintWithColor self prettyPrint: true! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'dew 3/7/2000 21:06'! printerSetup TextPrinter defaultTextPrinter inspect ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 11:47'! referencesToIt "Open a references browser on the selected symbol" | aSymbol | self selectLine. ((aSymbol _ self selectedSymbol) == nil or: [(Smalltalk includesKey: aSymbol) not]) ifTrue: [^ view flash]. self terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: (Smalltalk associationAt: self selectedSymbol)]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'BG 11/1/2003 14:27'! saveContentsInFile "Save the receiver's contents string to a file, prompting the user for a file-name. Suggest a reasonable file-name." | fileName stringToSave parentWindow labelToUse suggestedName lastIndex | stringToSave _ paragraph text string. stringToSave size == 0 ifTrue: [^ self inform: 'nothing to save.']. parentWindow _ self model dependents detect: [:dep | dep isKindOf: StandardSystemView] ifNone: [nil]. labelToUse _ parentWindow ifNil: ['Untitled'] ifNotNil: [parentWindow label]. suggestedName _ nil. #(('Decompressed contents of: ' '.gz')) do: "can add more here..." [:leaderTrailer | (labelToUse beginsWith: leaderTrailer first) ifTrue: [suggestedName _ labelToUse copyFrom: leaderTrailer first size + 1 to: labelToUse size. (labelToUse endsWith: leaderTrailer last) ifTrue: [suggestedName _ suggestedName copyFrom: 1 to: suggestedName size - leaderTrailer last size] ifFalse: [lastIndex _ suggestedName lastIndexOf: $. ifAbsent: [0]. (lastIndex = 0 or: [lastIndex = 1]) ifFalse: [suggestedName _ suggestedName copyFrom: 1 to: lastIndex - 1]]]]. suggestedName ifNil: [suggestedName _ labelToUse, '.text']. fileName _ FillInTheBlank request: 'File name?' initialAnswer: suggestedName. fileName isEmptyOrNil ifFalse: [(FileStream newFileNamed: fileName) nextPutAll: stringToSave; close]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'bf 10/13/1999 09:09'! selectedSelector "Try to make a selector out of the current text selection" ^self selection string findSelector! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:27'! selectedSymbol "Return the currently selected symbol, or nil if none. Spaces, tabs and returns are ignored" | aString | self hasCaret ifTrue: [^ nil]. aString _ self selection string copyWithoutAll: {Character space. Character cr. Character tab}. aString size == 0 ifTrue: [^ nil]. Symbol hasInterned: aString ifTrue: [:sym | ^ sym]. ^ nil! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'gm 2/16/2003 20:38'! sendContentsToPrinter | textToPrint printer parentWindow | textToPrint := paragraph text. textToPrint size == 0 ifTrue: [^self inform: 'nothing to print.']. printer := TextPrinter defaultTextPrinter. parentWindow := self model dependents detect: [:dep | dep isSystemWindow] ifNone: [nil]. parentWindow isNil ifTrue: [printer documentTitle: 'Untitled'] ifFalse: [printer documentTitle: parentWindow label]. printer printText: textToPrint! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sd 4/16/2003 19:30'! sendersOfIt "Open a senders browser on the selected selector" | aSelector | self lineSelectAndEmptyCheck: [^ self]. (aSelector _ self selectedSelector) == nil ifTrue: [^ view flash]. self terminateAndInitializeAround: [self systemNavigation browseAllCallsOn: aSelector]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/18/2002 17:28'! setAlignment: aSymbol | attr interval | attr _ TextAlignment perform: aSymbol. interval _ self encompassLine: self selectionInterval. paragraph replaceFrom: interval first to: interval last with: ((paragraph text copyFrom: interval first to: interval last) addAttribute: attr) displaying: true. ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'th 9/19/2002 18:27'! setSearchString "Make the current selection, if any, be the current search string." self hasCaret ifTrue: [view flash. ^ self]. self setSearch: self selection string! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 5/20/1998 22:41'! spawn "Create and schedule a message browser for the code of the model's selected message. Retain any edits that have not yet been accepted." | code | code _ paragraph text string. self cancel. model spawn: code.! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'di 9/7/1999 08:44'! spawnWorkspace | toUse | self selectLine. toUse _ self selection asString. toUse size > 0 ifFalse: [toUse _ paragraph text string. toUse size > 0 ifFalse: [^ self flash]]. "NB: BrowserCodeController's version does a cancel here" self terminateAndInitializeAround: [Utilities openScratchWorkspaceLabeled: 'Untitled' contents: toUse]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'sw 4/29/96'! specialMenuItems "Refer to comment under #presentSpecialMenu. . : added objectsReferencingIt," ^ #( 'Transcript cr; show: ''testing''' 'view superView model inspect' 'view superView model browseObjClass' 'view display' 'self inspect' 'view backgroundColor: Color fromUser' 'view topView inspect' 'self compareToClipboard' 'view insideColor: Form white' 'self objectsReferencingIt' ) ! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'SqR 11/14/2000 12:15'! undo "Reset the state of the paragraph prior to the previous edit. If another ParagraphEditor instance did that edit, UndoInterval is invalid; just recover the contents of the undo-buffer at the start of the paragraph." sensor flushKeyboard. "a way to flush stuck keys" self closeTypeIn. UndoParagraph == paragraph ifFalse: "Can't undo another paragraph's edit" [UndoMessage _ Message selector: #undoReplace. UndoInterval _ 1 to: 0. Undone _ true]. UndoInterval ~= self selectionInterval ifTrue: "blink the actual target" [self selectInterval: UndoInterval; deselect]. "Leave a signal of which phase is in progress" UndoParagraph _ Undone ifTrue: [#redoing] ifFalse: [#undoing]. UndoMessage sentTo: self. UndoParagraph _ paragraph! ! !ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/26/2003 22:02'! explainAnySel: symbol "Is this any message selector?" | list reply | list _ self systemNavigation allClassesImplementing: symbol. list size = 0 ifTrue: [^nil]. list size < 12 ifTrue: [reply _ ' is a message selector which is defined in these classes ' , list printString] ifFalse: [reply _ ' is a message selector which is defined in many classes']. ^'"' , symbol , reply , '."' , '\' withCRs, 'SystemNavigation new browseAllImplementorsOf: #' , symbol! ! !ParagraphEditor methodsFor: 'explain' stamp: 'di 1/30/2002 21:09'! explainChar: string "Does string start with a special character?" | char | char _ string at: 1. 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 class Float)."']. char = $' ifTrue: [^'"The characters between two single quotes are made into an instance of class String"']. char = $" ifTrue: [^'"Double quotes enclose a comment. Smalltalk ignores everything between double quotes."']. 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. It contains literal constants."']. (char = $( or: [char = $)]) ifTrue: [^'"Expressions enclosed in parenthesis are evaluated first"']. (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."']. (char = ${ or: [char = $}]) ifTrue: [^ '"A sequence of expressions separated by periods, when enclosed in curly braces, are evaluated to yield the elements of a new Array"']. (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."']. char = $^ ifTrue: [^'"Uparrow means return from this method. The value returned is the expression following the ^"']. 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."']. char = $_ ifTrue: [^'"Left arrow means assignment. The value of the expression after the left arrow is stored into the variable before it."']. char = $; ifTrue: [^'"Semicolon means cascading. The message after the semicolon is sent to the same object which received the message before the semicolon."']. 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).', '\\' withCRs, '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)."']. char = $$ ifTrue: [^'"The single character following a dollar sign is made into an instance of class Character"']. char = $- ifTrue: [^'"A minus sign in front of a number means a negative number."']. char = $e ifTrue: [^'"An e in the middle of a number means that the exponent follows."']. 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."']. char = Character space ifTrue: [^'"the space Character"']. char = Character tab ifTrue: [^'"the tab Character"']. char = Character cr ifTrue: [^'"the carriage return Character"']. ^nil! ! !ParagraphEditor methodsFor: 'explain' stamp: 'nk 6/10/2004 07:02'! explainClass: symbol "Is symbol a class variable or a pool variable?" | class reply classes | (model respondsTo: #selectedClassOrMetaClass) ifFalse: [^ nil]. (class _ model selectedClassOrMetaClass) ifNil: [^ nil]. "no class is selected" (class isKindOf: Metaclass) ifTrue: [class _ class soleInstance]. classes _ (Array with: class) , class allSuperclasses. "class variables" reply _ classes detect: [:each | (each classVarNames detect: [:name | symbol = name] ifNone: []) ~~ nil] ifNone: []. reply == nil ifFalse: [^ '"is a class variable, defined in class ' , reply printString , '"\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , reply printString , ' classPool associationAt: #' , symbol , ').']. "pool variables" classes do: [:each | (each sharedPools detect: [:pool | (pool includesKey: symbol) and: [reply _ pool. true]] ifNone: []) ~~ nil]. reply ifNil: [(Undeclared includesKey: symbol) ifTrue: [^ '"is an undeclared variable.' , '"\' withCRs , 'SystemNavigation new browseAllCallsOn: (Undeclared associationAt: #' , symbol , ').']] ifNotNil: [classes _ WriteStream on: Array new. self systemNavigation allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply] ifNone: []) ~~ nil ifTrue: [classes nextPut: each]]. "Perhaps not print whole list of classes if too long. (unlikely)" ^ '"is a pool variable from the pool ' , (Smalltalk keyAtIdentityValue: reply) asString , ', which is used by the following classes ' , classes contents printString , '"\' withCRs , 'SystemNavigation new browseAllCallsOn: (' , (Smalltalk keyAtIdentityValue: reply) asString , ' bindingOf: #' , symbol , ').']. ^ nil! ! !ParagraphEditor methodsFor: 'explain' stamp: 'sw 5/3/1998 14:32'! explainCtxt: symbol "Is symbol a context variable?" | reply classes text cls | symbol = #nil ifTrue: [reply _ '"is a constant. It is the only instance of class UndefinedObject. nil is the initial value of all variables."']. symbol = #true ifTrue: [reply _ '"is a constant. It is the only instance of class True and is the receiver of many control messages."']. symbol = #false ifTrue: [reply _ '"is a constant. It is the only instance of class False and is the receiver of many control messages."']. symbol = #thisContext ifTrue: [reply _ '"is a context variable. Its value is always the MethodContext which is executing this method."']. (model respondsTo: #selectedClassOrMetaClass) ifTrue: [ cls _ model selectedClassOrMetaClass]. cls ifNil: [^ reply]. "no class known" symbol = #self ifTrue: [classes _ cls withAllSubclasses. classes size > 12 ifTrue: [text _ cls printString , ' or a subclass'] ifFalse: [classes _ classes printString. text _ 'one of these classes' , (classes copyFrom: 4 to: classes size)]. reply _ '"is the receiver of this message; an instance of ' , text , '"']. symbol = #super ifTrue: [reply _ '"is just like self. Messages to super are looked up in the superclass (' , cls superclass printString , ')"']. ^reply! ! !ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/29/2003 20:07'! explainGlobal: symbol "Is symbol a global variable?" | reply classes | reply _ Smalltalk at: symbol ifAbsent: [^nil]. (reply class == Dictionary or:[reply isKindOf: SharedPool class]) ifTrue: [classes _ Set new. self systemNavigation allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply] ifNone: []) ~~ nil ifTrue: [classes add: each]]. classes _ classes printString. ^'"is a global variable. It is a pool which is used by the following classes ' , (classes allButFirst: 5) , '"']. (reply isKindOf: Behavior) ifTrue: [^'"is a global variable. ' , symbol , ' is a class in category ', reply category, '."', '\' withCRs, 'Browser newOnClass: ' , symbol , '.']. symbol == #Smalltalk ifTrue: [^'"is a global. Smalltalk is the only instance of SystemDictionary and holds all global variables."']. ^'"is a global variable. ' , symbol , ' is ' , reply printString , '"'! ! !ParagraphEditor methodsFor: 'explain' stamp: 'tpr 5/12/2004 16:22'! explainInst: string "Is string an instance variable of this class?" | classes cls | (model respondsTo: #selectedClassOrMetaClass) ifTrue: [ cls _ model selectedClassOrMetaClass]. cls ifNil: [^ nil]. "no class known" classes _ (Array with: cls) , cls allSuperclasses. classes _ classes detect: [:each | (each instVarNames detect: [:name | name = string] ifNone: []) ~~ nil] ifNone: [^nil]. classes _ classes printString. ^ '"is an instance variable of the receiver; defined in class ' , classes , '"\' withCRs , classes , ' systemNavigation browseAllAccessesTo: ''' , string , ''' from: ', classes, '.'! ! !ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'! explainMySel: symbol "Is symbol the selector of this method? Is it sent by this method? If not, then expalin will call (explainPartSel:) to see if it is a fragment of a selector sent here. If not, explain will call (explainAnySel:) to catch any selector. " | lits classes msg | (model respondsTo: #selectedMessageName) ifFalse: [^ nil]. (msg _ model selectedMessageName) ifNil: [^nil]. "not in a message" classes _ self systemNavigation allClassesImplementing: symbol. classes size > 12 ifTrue: [classes _ 'many classes'] ifFalse: [classes _ 'these classes ' , classes printString]. msg = symbol ifTrue: [^ '"' , symbol , ' is the selector of this very method!! It is defined in ', classes , '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''."'] ifFalse: [lits _ (model selectedClassOrMetaClass compiledMethodAt: msg) messages. (lits detect: [:each | each == symbol] ifNone: []) == nil ifTrue: [^nil]. ^ '"' , symbol , ' is a message selector which is defined in ', classes , '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''."'].! ! !ParagraphEditor methodsFor: 'explain' stamp: 'apb 1/5/2000 16:56'! explainNumber: string "Is string a Number?" | strm c | (c _ string at: 1) isDigit ifFalse: [(c = $- and: [string size > 1 and: [(string at: 2) isDigit]]) ifFalse: [^nil]]. strm _ ReadStream on: string. c _ Number readFrom: strm. strm atEnd ifFalse: [^nil]. c printString = string ifTrue: [^'"' , string , ' is a ' , c class name , '"'] ifFalse: [^'"' , string , ' (= ' , c printString , ') is a ' , c class name , '"']! ! !ParagraphEditor methodsFor: 'explain' stamp: 'nb 5/6/2003 16:54'! explainPartSel: string "Is this a fragment of a multiple-argument selector sent in this method?" | lits whole reply classes s msg | (model respondsTo: #selectedMessageName) ifFalse: [^ nil]. (msg _ model selectedMessageName) ifNil: [^ nil]. "not in a message" string last == $: ifFalse: [^ nil]. "Name of this method" lits _ Array with: msg. (whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string] ifNone: []) ~~ nil] ifNone: []) ~~ nil ifTrue: [reply _ ', which is the selector of this very method!!'. s _ '. To see the other definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''."'] ifFalse: ["Selectors called from this method" lits _ (model selectedClassOrMetaClass compiledMethodAt: msg) messages. (whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string] ifNone: []) ~~ nil] ifNone: []) ~~ nil ifFalse: [string = 'primitive:' ifTrue: [^self explainChar: '<'] ifFalse: [^nil]]. reply _ '.'. s _ '. To see the definitions, go to the message list pane, get the menu from the top of the scroll bar, and select ''implementors of...''."']. classes _ self systemNavigation allClassesImplementing: whole. classes size > 12 ifTrue: [classes _ 'many classes'] ifFalse: [classes _ 'these classes ' , classes printString]. ^ '"' , string , ' is one part of the message selector ' , whole, reply , ' It is defined in ' , classes , s! ! !ParagraphEditor methodsFor: 'explain'! explainScan: string "Remove beginning and trailing space, tab, cr. 1/15/96 sw: copied intact from BrowserCodeController" | c beg end | beg _ 1. end _ string size. [beg = end ifTrue: [^string copyFrom: 1 to: 1]. "if all blank, tell about the first" c _ string at: beg. c = Character space or: [c = Character tab or: [c = Character cr]]] whileTrue: [beg _ beg + 1]. [c _ string at: end. c = Character space or: [c = Character tab or: [c = Character cr]]] whileTrue: [end _ end - 1]. ^string copyFrom: beg to: end "Return purely visible characters"! ! !ParagraphEditor methodsFor: 'explain' stamp: 'tk 4/1/98 14:19'! explainTemp: string "Is string the name of a temporary variable (or block argument variable)?" | selectedClass tempNames i reply methodNode method msg | (model respondsTo: #selectedMessageName) ifFalse: [^ nil]. (msg _ model selectedMessageName) ifNil: [^nil]. "not in a message" selectedClass _ model selectedClassOrMetaClass. tempNames _ selectedClass parserClass new parseArgsAndTemps: model selectedMessage notifying: nil. method _ selectedClass compiledMethodAt: msg. (i _ tempNames findFirst: [:each | each = string]) = 0 ifTrue: [ (method numTemps > tempNames size) ifTrue: ["It must be an undeclared block argument temporary" methodNode _ selectedClass compilerClass new parse: model selectedMessage in: selectedClass notifying: nil. tempNames _ methodNode tempNames] ifFalse: [^nil]]. (i _ tempNames findFirst: [:each | each = string]) > 0 ifTrue: [i > method numArgs ifTrue: [reply _ '"is a temporary variable in this method"'] ifFalse: [reply _ '"is an argument to this method"']]. ^reply! ! !ParagraphEditor methodsFor: 'editing keys'! align: characterStream "Triggered by Cmd-u; cycle through alignment alternatives. 8/11/96 sw" sensor keyboard. "flush character" self align. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! browseIt: characterStream "Triggered by Cmd-B; browse the thing represented by the current selection, if plausible. 1/18/96 sw" sensor keyboard. "flush character" self browseIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! browseItHere: characterStream "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" sensor keyboard. "flush character" self browseItHere. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:40'! cancel: characterStream "Cancel unsubmitted changes. Flushes typeahead. 1/12/96 sw 1/22/96 sw: put in control terminate/init" sensor keyboard. self terminateAndInitializeAround: [self cancel]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'BG 10/29/2003 08:00'! changeEmphasis: characterStream "Change the emphasis of the current selection or prepare to accept characters with the change in emphasis. Emphasis change amounts to a font change. Keeps typeahead." | keyCode attribute oldAttributes index thisSel colors extras indexOfOldAttributes | "control 0..9 -> 0..9" keyCode _ ('0123456789-=' indexOf: sensor keyboard ifAbsent: [1]) - 1. "grab the old set of attributes" indexOfOldAttributes _ startBlock stringIndex < stopBlock stringIndex ifTrue: [ startBlock stringIndex ] ifFalse: [ "if selection is empty, look on character to the left; this is consistent with setEmphasisHere" (startBlock stringIndex - 1) max: 1 ]. oldAttributes _ paragraph text attributesAt: indexOfOldAttributes forStyle: paragraph textStyle. thisSel _ self selection. "Decipher keyCodes for Command 0-9..." (keyCode between: 1 and: 5) ifTrue: [attribute _ TextFontChange fontNumber: keyCode]. keyCode = 6 ifTrue: [colors _ #(black magenta red yellow green blue cyan white). extras _ false "not a system window" ifTrue: [#()] ifFalse: [#('Link to comment of class' 'Link to definition of class' 'Link to hierarchy of class' 'Link to method')]. index _ (PopUpMenu labelArray: colors , #('choose color...' 'Do it' 'Print it'), extras, #('be a web URL link' 'Edit hidden info' 'Copy hidden info') lines: (Array with: colors size +1)) startUp. index = 0 ifTrue: [^ true]. index <= colors size ifTrue: [attribute _ TextColor color: (Color perform: (colors at: index))] ifFalse: [index _ index - colors size - 1. "Re-number!!!!!!" index = 0 ifTrue: [attribute _ self chooseColor]. index = 1 ifTrue: [attribute _ TextDoIt new. thisSel _ attribute analyze: self selection asString]. index = 2 ifTrue: [attribute _ TextPrintIt new. thisSel _ attribute analyze: self selection asString]. (extras size = 0) & (index > 2) ifTrue: [index _ index + 5]. "skip those" index = 3 ifTrue: [attribute _ TextLink new. thisSel _ attribute analyze: self selection asString with: 'Comment']. index = 4 ifTrue: [attribute _ TextLink new. thisSel _ attribute analyze: self selection asString with: 'Definition']. index = 5 ifTrue: [attribute _ TextLink new. thisSel _ attribute analyze: self selection asString with: 'Hierarchy']. index = 6 ifTrue: [attribute _ TextLink new. thisSel _ attribute analyze: self selection asString]. " index = 7 ifTrue: [attribute _ TextURL new. thisSel _ attribute analyze: self selection asString]. " index = 8 ifTrue: ["Edit hidden info" thisSel _ self hiddenInfo. "includes selection" attribute _ TextEmphasis normal]. index = 9 ifTrue: ["Copy hidden info" self copyHiddenInfo. ^ true]. "no other action" thisSel ifNil: [^ true]]. "Could not figure out what to link to" ]. (keyCode between: 7 and: 11) ifTrue: [sensor leftShiftDown ifTrue: [keyCode = 10 ifTrue: [attribute _ TextKern kern: -1]. keyCode = 11 ifTrue: [attribute _ TextKern kern: 1]] ifFalse: [attribute _ TextEmphasis perform: (#(bold italic narrow underlined struckOut) at: keyCode - 6). oldAttributes do: [:att | (att dominates: attribute) ifTrue: [attribute turnOff]]]]. (keyCode = 0) ifTrue: [attribute _ TextEmphasis normal]. beginTypeInBlock ~~ nil ifTrue: "only change emphasisHere while typing" [self insertTypeAhead: characterStream] ifFalse: [self replaceSelectionWith: (thisSel asText addAttribute: attribute)]. emphasisHere _ Text addAttribute: attribute toArray: oldAttributes. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 11:58'! changeLfToCr: characterStream "Replace all LFs by CRs. Triggered by Cmd-U -- useful when getting code from FTP sites" | cr lf | sensor keyboard. "flush the triggering cmd-key character" cr _ Character cr. lf _ Character linefeed. self replaceSelectionWith: (Text fromString: (self selection string collect: [:c | c = lf ifTrue: [cr] ifFalse: [c]])). ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 09:11'! chooseColor "Make a new Text Color Attribute, let the user pick a color, and return the attribute. This is the non-Morphic version." ^ TextColor color: (Color fromUser)! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:31'! compareToClipboard: characterStream "Compare the receiver to the text on the clipboard. Flushes typeahead. 5/1/96 sw" sensor keyboard. self terminateAndInitializeAround: [self compareToClipboard]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'tk 5/7/2001 08:47'! copyHiddenInfo "In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden info. Copy that to the clipboard. You can paste it and see what it is. Usually enclosed in <>." ^ self clipboardTextPut: self hiddenInfo asText! ! !ParagraphEditor methodsFor: 'editing keys'! copySelection: characterStream "Copy the current text selection. Flushes typeahead." sensor keyboard. "flush character" self copySelection. ^true! ! !ParagraphEditor methodsFor: 'editing keys'! cut: characterStream "Cut out the current text selection. Flushes typeahead." sensor keyboard. "flush character" self cut. ^true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:23'! doIt: characterStream "Called when user hits cmd-d. Select the current line, if relevant, then evaluate and execute. 2/1/96 sw. 2/29/96 sw: don't call selectLine; it's done by doIt now" sensor keyboard. self terminateAndInitializeAround: [self doIt]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/20/2002 11:41'! duplicate: characterStream "Paste the current selection over the prior selection, if it is non-overlapping and legal. Flushes typeahead. Undoer & Redoer: undoAndReselect." sensor keyboard. self closeTypeIn. (self hasSelection and: [self isDisjointFrom: otherInterval]) ifTrue: "Something to duplicate" [self replace: otherInterval with: self selection and: [self selectAt: self pointIndex]] ifFalse: [view flash]. ^true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:01'! enclose: characterStream "Insert or remove bracket characters around the current selection. Flushes typeahead." | char left right startIndex stopIndex oldSelection which text | char _ sensor keyboard. self closeTypeIn. startIndex _ self startIndex. stopIndex _ self stopIndex. oldSelection _ self selection. which _ '([<{"''' indexOf: char ifAbsent: [ ^true ]. left _ '([<{"''' at: which. right _ ')]>}"''' at: which. text _ paragraph text. ((startIndex > 1 and: [stopIndex <= text size]) and: [(text at: startIndex-1) = left and: [(text at: stopIndex) = right]]) ifTrue: ["already enclosed; strip off brackets" self selectFrom: startIndex-1 to: stopIndex. self replaceSelectionWith: oldSelection] ifFalse: ["not enclosed; enclose by matching brackets" self replaceSelectionWith: (Text string: (String with: left), oldSelection string ,(String with: right) emphasis: emphasisHere). self selectFrom: startIndex+1 to: stopIndex]. ^true! ! !ParagraphEditor methodsFor: 'editing keys'! exchange: characterStream "Exchange the current and prior selections. Keeps typeahead." sensor keyboard. "Flush character" self closeTypeIn: characterStream. self exchange. ^true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 4/24/2001 12:28'! fileItIn: characterStream "File in the selection; invoked via a keyboard shortcut, -- for now, cmd-shift-G." sensor keyboard. "flush character" self terminateAndInitializeAround: [self fileItIn]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:31'! hiddenInfo "In TextLinks, TextDoits, TextColor, and TextURLs, there is hidden info. Return the entire string that was used by Cmd-6 to create this text attribute. Usually enclosed in < >." | attrList | attrList _ paragraph text attributesAt: (self pointIndex + self markIndex)//2 forStyle: paragraph textStyle. attrList do: [:attr | (attr isKindOf: TextAction) ifTrue: [^ self selection asString, '<', attr info, '>']]. "If none of the above" attrList do: [:attr | attr class == TextColor ifTrue: [^ self selection asString, '<', attr color printString, '>']]. ^ self selection asString, '[No hidden info]'! ! !ParagraphEditor methodsFor: 'editing keys'! implementorsOfIt: characterStream "Triggered by Cmd-m; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw" sensor keyboard. "flush character" self implementorsOfIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:28'! inOutdent: characterStream delta: delta "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" | cr realStart realStop lines startLine stopLine start stop adjustStart indentation size numLines inStream newString outStream | sensor keyboard. "Flush typeahead" cr _ Character cr. "Operate on entire lines, but remember the real selection for re-highlighting later" realStart _ self startIndex. realStop _ self stopIndex - 1. "Special case a caret on a line of its own, including weird case at end of paragraph" (realStart > realStop and: [realStart < 2 or: [(paragraph string at: realStart - 1) == cr]]) ifTrue: [delta < 0 ifTrue: [view flash] ifFalse: [self replaceSelectionWith: Character tab asSymbol asText. self selectAt: realStart + 1]. ^true]. lines _ paragraph lines. startLine _ paragraph lineIndexOfCharacterIndex: realStart. stopLine _ paragraph lineIndexOfCharacterIndex: (realStart max: realStop). start _ (lines at: startLine) first. stop _ (lines at: stopLine) last. "Pin the start of highlighting unless the selection starts a line" adjustStart _ realStart > start. "Find the indentation of the least-indented non-blank line; never outdent more" indentation _ (startLine to: stopLine) inject: 1000 into: [:m :l | m _ m min: (paragraph indentationOfLineIndex: l ifBlank: [:tabs | 1000])]. size _ stop + 1 - start. numLines _ stopLine + 1 - startLine. inStream _ ReadStream on: paragraph string from: start to: stop. newString _ String new: size + ((numLines * delta) max: 0). outStream _ ReadWriteStream on: newString. "This subroutine does the actual work" self indent: delta fromStream: inStream toStream: outStream. "Adjust the range that will be highlighted later" adjustStart ifTrue: [realStart _ (realStart + delta) max: start]. realStop _ realStop + outStream position - size. "Prepare for another iteration" indentation _ indentation + delta. size _ outStream position. inStream _ outStream setFrom: 1 to: size. outStream == nil ifTrue: "tried to outdent but some line(s) were already left flush" [view flash] ifFalse: [self selectInvisiblyFrom: start to: stop. size = newString size ifFalse: [newString _ outStream contents]. self replaceSelectionWith: newString asText]. self selectFrom: realStart to: realStop. "highlight only the original range" ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! indent: characterStream "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" ^ self inOutdent: characterStream delta: 1! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'! inspectIt: characterStream "Inspect the selection -- invoked via cmd-i. If there is no current selection, use the current line. 1/17/96 sw 2/29/96 sw: don't call selectLine; it's done by inspectIt now" sensor keyboard. "flush character" self terminateAndInitializeAround: [self inspectIt]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 12:06'! makeCapitalized: characterStream "Force the current selection to uppercase. Triggered by Cmd-X." | prev | sensor keyboard. "flush the triggering cmd-key character" prev _ $-. "not a letter" self replaceSelectionWith: (Text fromString: (self selection string collect: [:c | prev _ prev isLetter ifTrue: [c asLowercase] ifFalse: [c asUppercase]])). ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 5/28/1998 12:00'! makeLowercase: characterStream "Force the current selection to lowercase. Triggered by Cmd-X." sensor keyboard. "flush the triggering cmd-key character" self replaceSelectionWith: (Text fromString: (self selection string asLowercase)). ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ls 11/10/2002 12:11'! makeUppercase: characterStream "Force the current selection to uppercase. Triggered by Cmd-Y." sensor keyboard. "flush the triggering cmd-key character" self replaceSelectionWith: (Text fromString: (self selection string asUppercase)). ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 8/1/97 15:18'! methodNamesContainingIt: characterStream "Browse methods whose selectors containing the selection in their names" sensor keyboard. "flush character" self methodNamesContainingIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 9/9/97 16:44'! methodStringsContainingIt: characterStream "Invoked from cmd-E -- open a browser on all methods holding string constants containing it. Flushes typeahead. " sensor keyboard. self methodStringsContainingit. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! noop: characterStream "Unimplemented keyboard command; just ignore it." sensor keyboard. "flush character" ^ true ! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 1/19/2000 11:14'! offerFontMenu "Present a menu of available fonts, and if one is chosen, apply it to the current selection. Use only names of Fonts of this paragraph " | aList reply | aList _ paragraph textStyle fontNamesWithPointSizes. reply _ (SelectionMenu labelList: aList selections: aList) startUp. reply ~~ nil ifTrue: [self replaceSelectionWith: (Text string: self selection asString attribute: (TextFontChange fontNumber: (aList indexOf: reply)))] ! ! !ParagraphEditor methodsFor: 'editing keys'! offerFontMenu: characterStream "The user typed the command key that requests a font change; Offer the font menu. 5/27/96 sw Keeps typeahead. (?? should flush?)" sensor keyboard. "flush character" self closeTypeIn: characterStream. self offerFontMenu. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! outdent: characterStream "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" ^ self inOutdent: characterStream delta: -1! ! !ParagraphEditor methodsFor: 'editing keys'! paste: characterStream "Replace the current text selection by the text in the shared buffer. Keeps typeahead." sensor keyboard. "flush character" self closeTypeIn: characterStream. self paste. ^true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:48'! pasteInitials: characterStream "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. Keeps typeahead." sensor keyboard. "flush character" self closeTypeIn: characterStream. self replace: self selectionInterval with: (Text fromString: Utilities changeStamp) and: [self selectAt: self stopIndex]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:25'! printIt: characterStream "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 2/29/96 sw: don't call selectLine now, since it's called by doIt" sensor keyboard. "flush character" self terminateAndInitializeAround: [self printIt]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! referencesToIt: characterStream "Triggered by Cmd-N; browse references to the current selection" sensor keyboard. "flush character" self referencesToIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'! save: characterStream "Submit the current text. Equivalent to 'accept' 1/18/96 sw Keeps typeahead." sensor keyboard. "flush character" self closeTypeIn: characterStream. self terminateAndInitializeAround: [self accept]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys'! sendersOfIt: characterStream "Triggered by Cmd-n; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw" sensor keyboard. "flush character" self sendersOfIt. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'yo 5/27/2004 13:56'! setEmphasis: emphasisSymbol "Change the emphasis of the current selection." | oldAttributes attribute | oldAttributes _ paragraph text attributesAt: self selectionInterval first forStyle: paragraph textStyle. attribute _ TextEmphasis perform: emphasisSymbol. (emphasisSymbol == #normal) ifFalse: [oldAttributes do: [:att | (att dominates: attribute) ifTrue: [attribute turnOff]]]. self replaceSelectionWith: (self selection addAttribute: attribute)! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/18/2002 16:20'! shiftEnclose: characterStream "Insert or remove bracket characters around the current selection. Flushes typeahead." | char left right startIndex stopIndex oldSelection which text | char _ sensor keyboard. char = $9 ifTrue: [ char _ $( ]. char = $, ifTrue: [ char _ $< ]. char = $[ ifTrue: [ char _ ${ ]. char = $' ifTrue: [ char _ $" ]. char asciiValue = 27 ifTrue: [ char _ ${ ]. "ctrl-[" self closeTypeIn. startIndex _ self startIndex. stopIndex _ self stopIndex. oldSelection _ self selection. which _ '([<{"''' indexOf: char ifAbsent: [1]. left _ '([<{"''' at: which. right _ ')]>}"''' at: which. text _ paragraph text. ((startIndex > 1 and: [stopIndex <= text size]) and: [(text at: startIndex-1) = left and: [(text at: stopIndex) = right]]) ifTrue: ["already enclosed; strip off brackets" self selectFrom: startIndex-1 to: stopIndex. self replaceSelectionWith: oldSelection] ifFalse: ["not enclosed; enclose by matching brackets" self replaceSelectionWith: (Text string: (String with: left), oldSelection string ,(String with: right) emphasis: emphasisHere). self selectFrom: startIndex+1 to: stopIndex]. ^true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'di 9/7/1999 08:43'! spawnIt: characterStream "Triggered by Cmd-o; spawn a new code window, if it makes sense." sensor keyboard. self terminateAndInitializeAround: [self spawn]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'th 9/19/2002 18:00'! swapChars: characterStream "Triggered byCmd-Y;. Swap two characters, either those straddling the insertion point, or the two that comprise the selection. Suggested by Ted Kaehler. " | currentSelection aString chars | sensor keyboard. "flush the triggering cmd-key character" (chars _ self selection) size == 0 ifTrue: [currentSelection _ self pointIndex. self selectMark: currentSelection - 1 point: currentSelection] ifFalse: [chars size == 2 ifFalse: [view flash. ^ true] ifTrue: [currentSelection _ self pointIndex - 1]]. aString _ self selection string. self replaceSelectionWith: (Text string: aString reversed emphasis: emphasisHere). self selectAt: currentSelection + 1. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'sw 11/2/1998 15:50'! tempCommand: characterStream "Experimental. Triggered by Cmd-t; put trial cmd-key commands here to see how they work, before hanging them on their own cmd accelerators." Sensor keyboard. self experimentalCommand. ^ true "sensor keyboard. self spawnWorkspace. ^ true"! ! !ParagraphEditor methodsFor: 'editing keys'! undo: characterStream "Undo the last edit. Keeps typeahead, so undo twice is a full redo." sensor keyboard. "flush character" self closeTypeIn: characterStream. self undo. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:51'! comment "All key actions that are neither editing nor typing actions have to send closeTypeIn at first. See comment in openTypeIn closeTypeIn"! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:08'! cursorDown: characterStream "Private - Move cursor from position in current line to same position in next line. If next line too short, put at end. If shift key down, select." self closeTypeIn: characterStream. self moveCursor:[:position | self sameColumn: position newLine:[:line | line + 1] forward: true] forward: true specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 10/28/2003 10:47'! cursorEnd: characterStream "Private - Move cursor end of current line." | string | self closeTypeIn: characterStream. string _ paragraph text string. self moveCursor: [:position | Preferences wordStyleCursorMovement ifTrue:[| targetLine | targetLine _ paragraph lines at:(paragraph lineIndexOfCharacterIndex: position). targetLine = paragraph lines last ifTrue:[targetLine last + 1] ifFalse:[targetLine last]] ifFalse:[ string indexOf: Character cr startingAt: position ifAbsent:[string size + 1]]] forward: true specialBlock:[:dummy | string size + 1]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/20/2002 12:14'! cursorHome: characterStream "Private - Move cursor from position in current line to beginning of current line. If control key is pressed put cursor at beginning of text" | string | string _ paragraph text string. self moveCursor: [ :position | Preferences wordStyleCursorMovement ifTrue:[ (paragraph lines at:(paragraph lineIndexOfCharacterIndex: position)) first] ifFalse:[ (string lastIndexOf: Character cr startingAt: position - 1 ifAbsent:[0]) + 1]] forward: false specialBlock: [:dummy | 1]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:07'! cursorLeft: characterStream "Private - Move cursor left one character if nothing selected, otherwise move cursor to beginning of selection. If the shift key is down, start selecting or extending current selection. Don't allow cursor past beginning of text" self closeTypeIn: characterStream. self moveCursor:[:position | position - 1 max: 1] forward: false specialBlock:[:position | self previousWord: position]. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'! cursorPageDown: characterStream self closeTypeIn: characterStream. self moveCursor: [:position | self sameColumn: position newLine:[:lineNo | lineNo + self pageHeight] forward: true] forward: true specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:09'! cursorPageUp: characterStream self closeTypeIn: characterStream. self moveCursor: [:position | self sameColumn: position newLine:[:lineNo | lineNo - self pageHeight] forward: false] forward: false specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 9/19/2002 20:01'! cursorRight: characterStream "Private - Move cursor right one character if nothing selected, otherwise move cursor to end of selection. If the shift key is down, start selecting characters or extending already selected characters. Don't allow cursor past end of text" self closeTypeIn: characterStream. self moveCursor: [:position | position + 1] forward: true specialBlock:[:position | self nextWord: position]. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 11/18/2002 17:15'! cursorUp: characterStream "Private - Move cursor from position in current line to same position in prior line. If prior line too short, put at end" self closeTypeIn: characterStream. self moveCursor: [:position | self sameColumn: position newLine:[:line | line - 1] forward: false] forward: false specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'BG 10/28/2003 21:01'! escapeToDesktop: characterStream "Pop up a morph to field keyboard input in the context of the desktop" ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'dvf 12/8/2001 00:46'! raiseContextMenu: characterStream "AFAIK, this is never called in morphic, because a subclass overrides it. Which is good, because a ParagraphEditor doesn't know about Morphic and thus duplicates the text-editing actions that really belong in the specific application, not the controller. So the context menu this would raise is likely to be out of date." self yellowButtonActivity. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'! selectCurrentTypeIn: characterStream "Select what would be replaced by an undo (e.g., the last typeIn)." | prior | self closeTypeIn: characterStream. prior _ otherInterval. sensor keyboard. "flush character" self closeTypeIn: characterStream. self selectInterval: UndoInterval. otherInterval _ prior. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'sma 12/15/1999 11:46'! selectWord: characterStream sensor keyboard. self closeTypeIn: characterStream. self selectWord. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'th 1/21/2000 18:55'! setSearchString: characterStream "Establish the current selection as the current search string." | aString | self closeTypeIn: characterStream. sensor keyboard. self lineSelectAndEmptyCheck: [^ true]. aString _ self selection string. aString size == 0 ifTrue: [self flash] ifFalse: [self setSearch: aString]. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:22'! argAdvance: characterStream "Invoked by Ctrl-a. Useful after Ctrl-q. Search forward from the end of the selection for a colon followed by a space. Place the caret after the space. If none are found, place the caret at the end of the text. Does not affect the undoability of the previous command." | start | sensor keyboard. "flush character" self closeTypeIn: characterStream. start _ paragraph text findString: ': ' startingAt: self stopIndex. start = 0 ifTrue: [start _ paragraph text size + 1]. self selectAt: start + 2. ^true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 10/21/2003 15:46'! backWord: characterStream "If the selection is not a caret, delete it and leave it in the backspace buffer. Else if there is typeahead, delete it. Else, delete the word before the caret." | startIndex | sensor keyboard. characterStream isEmpty ifTrue: [self hasCaret ifTrue: "a caret, delete at least one character" [startIndex _ 1 max: self markIndex - 1. [startIndex > 1 and: [(paragraph text at: startIndex - 1) asCharacter tokenish]] whileTrue: [startIndex _ startIndex - 1]] ifFalse: "a non-caret, just delete it" [startIndex _ self markIndex]. self backTo: startIndex] ifFalse: [characterStream reset]. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:23'! backspace: characterStream "Backspace over the last character." | startIndex | sensor leftShiftDown ifTrue: [^ self backWord: characterStream]. characterStream isEmpty ifTrue: [startIndex _ self markIndex + (self hasCaret ifTrue: [0] ifFalse: [1]). [sensor keyboardPressed and: [sensor keyboardPeek asciiValue = 8]] whileTrue: [ "process multiple backspaces" sensor keyboard. startIndex _ 1 max: startIndex - 1. ]. self backTo: startIndex] ifFalse: [sensor keyboard. characterStream skip: -1]. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! changeStyle: characterStream "Put up the style-change menu" sensor keyboard. "flush character" self closeTypeIn: characterStream. self changeStyle. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/20/2002 11:25'! crWithIndent: characterStream "Replace the current text selection with CR followed by as many tabs as on the current line (+/- bracket count) -- initiated by Shift-Return." | char s i tabCount | sensor keyboard. "flush character" s _ paragraph string. i _ self stopIndex. tabCount _ 0. [(i _ i-1) > 0 and: [(char _ s at: i) ~= Character cr]] whileTrue: "Count tabs and brackets (but not a leading bracket)" [(char = Character tab and: [i < s size and: [(s at: i+1) ~= $[ ]]) ifTrue: [tabCount _ tabCount + 1]. char = $[ ifTrue: [tabCount _ tabCount + 1]. char = $] ifTrue: [tabCount _ tabCount - 1]]. characterStream crtab: tabCount. "Now inject CR with tabCount tabs" ^ false! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 4/30/2001 21:20'! cursorTopHome: characterStream "Put cursor at beginning of text -- invoked from cmd-H shortcut, useful for keyboards that have no home key." sensor keyboard. self selectAt: 1. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! displayIfFalse: characterStream "Replace the current text selection with the text 'ifFalse:'--initiated by ctrl-f." sensor keyboard. "flush character" characterStream nextPutAll: 'ifFalse:'. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! displayIfTrue: characterStream "Replace the current text selection with the text 'ifTrue:'--initiated by ctrl-t." sensor keyboard. "flush character" characterStream nextPutAll: 'ifTrue:'. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! doAgainMany: characterStream "Do the previous thing again repeatedly. 1/26/96 sw" sensor keyboard. "flush character" self closeTypeIn: characterStream. self againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:) many: true. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! doAgainOnce: characterStream "Do the previous thing again once. 1/26/96 sw" sensor keyboard. "flush character" self closeTypeIn: characterStream. self again. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! find: characterStream "Prompt the user for what to find, then find it, searching from the current selection onward. 1/24/96 sw" sensor keyboard. "flush character" self closeTypeIn: characterStream. self find. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! findAgain: characterStream "Find the desired text again. 1/24/96 sw" sensor keyboard. "flush character" self closeTypeIn: characterStream. self findAgain. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/18/2002 11:39'! forwardDelete: characterStream "Delete forward over the next character. Make Undo work on the whole type-in, not just the one char. wod 11/3/1998: If there was a selection use #zapSelectionWith: rather than #backspace: which was 'one off' in deleting the selection. Handling of things like undo or typeIn area were not fully considered." | startIndex usel upara uinterval ind stopIndex | startIndex _ self mark. startIndex > paragraph text size ifTrue: [sensor keyboard. ^ false]. self hasSelection ifTrue: ["there was a selection" sensor keyboard. self zapSelectionWith: self nullText. ^ false]. "Null selection - do the delete forward" beginTypeInBlock == nil "no previous typing. openTypeIn" ifTrue: [self openTypeIn. UndoSelection _ self nullText]. uinterval _ UndoInterval deepCopy. upara _ UndoParagraph deepCopy. stopIndex := startIndex. (sensor keyboard asciiValue = 127 and: [sensor leftShiftDown]) ifTrue: [stopIndex := (self nextWord: stopIndex) - 1]. self selectFrom: startIndex to: stopIndex. self replaceSelectionWith: self nullText. self selectFrom: startIndex to: startIndex-1. UndoParagraph _ upara. UndoInterval _ uinterval. UndoMessage selector == #noUndoer ifTrue: [ (UndoSelection isText) ifTrue: [ usel _ UndoSelection. ind _ startIndex. "UndoInterval startIndex" usel replaceFrom: usel size + 1 to: usel size with: (UndoParagraph text copyFrom: ind to: ind). UndoParagraph text replaceFrom: ind to: ind with: self nullText]]. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! normalCharacter: characterStream "A nonspecial character is to be added to the stream of characters." characterStream nextPut: sensor keyboard. ^false! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 18:25'! querySymbol: characterStream "Invoked by Ctrl-q to query the Symbol table and display alternate symbols. See comment in completeSymbol:lastOffering: for details." sensor keyboard. "flush character" self closeTypeIn: characterStream. "keep typeahead" self hasCaret ifTrue: "Ctrl-q typed when a caret" [self perform: #completeSymbol:lastOffering: withArguments: ((UndoParagraph == paragraph and: [UndoMessage sends: #undoQuery:lastOffering:]) ifTrue: [UndoMessage arguments] "repeated Ctrl-q" ifFalse: [Array with: nil with: nil])] "initial Ctrl-q" ifFalse: "Ctrl-q typed when statements were highlighted" [view flash]. ^true! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! search: characterStream "Invoked by Ctrl-S. Same as 'again', but always uses the existing FindText and ChangeText regardless of the last edit." sensor keyboard. "flush character" self closeTypeIn: characterStream. self againOrSame: true. "true means use same keys" ^true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'sw 8/29/2000 14:58'! selectAll "Make the selection be all the characters of the receiver" self selectFrom: 1 to: paragraph text string size! ! !ParagraphEditor methodsFor: 'typing/selecting keys'! selectAll: characterStream "select everything, invoked by cmd-a. 1/17/96 sw" sensor keyboard. "flush character" self closeTypeIn: characterStream. self selectFrom: 1 to: paragraph text string size. ^ true! ! !ParagraphEditor methodsFor: 'typing/selecting keys' stamp: 'th 9/19/2002 17:34'! simulatedBackspace "Backspace over the last character, derived from hand-char recognition. 2/5/96 sw" | startIndex | startIndex _ self markIndex + (self hasSelection ifTrue: [1] ifFalse: [0]). startIndex _ 1 max: startIndex - 1. self backTo: startIndex. ^ false! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 17:36'! backTo: startIndex "During typing, backspace to startIndex. Deleted characters fall into three clusters, from left to right in the text: (1) preexisting characters that were backed over; (2) newly typed characters that were backed over (excluding typeahead, which never even appears); (3) preexisting characters that were highlighted before typing began. If typing has not yet been opened, open it and watch for the first and third cluster. If typing has been opened, watch for the first and second cluster. Save characters from the first and third cluster in UndoSelection. Tally characters from the first cluster in UndoMessage's parameter. Delete all the clusters. Do not alter Undoer or UndoInterval (except via openTypeIn). The code is shorter than the comment." | saveLimit newBackovers | saveLimit _ beginTypeInBlock ifNil: [self openTypeIn. UndoSelection _ self nullText. self stopIndex] ifNotNil: [self startOfTyping]. self setMark: startIndex. startIndex < saveLimit ifTrue: [newBackovers _ self startOfTyping - startIndex. beginTypeInBlock _ self startIndex. UndoSelection replaceFrom: 1 to: 0 with: (paragraph text copyFrom: startIndex to: saveLimit - 1). UndoMessage argument: (UndoMessage argument ifNil: [1]) + newBackovers]. self zapSelectionWith: self nullText. self unselect! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 17:40'! closeTypeIn "See comment in openTypeIn. It is important to call closeTypeIn before executing any non-typing key, making a new selection, etc. It is called automatically for menu commands. Typing commands can call 'closeTypeIn: aCharacterStream' instead of this to save typeahead. Undoer & Redoer: undoAndReselect:redoAndReselect:." | begin stop | beginTypeInBlock == nil ifFalse: [(UndoMessage sends: #noUndoer) ifTrue: "should always be true, but just in case..." [begin _ self startOfTyping. stop _ self stopIndex. self undoer: #undoAndReselect:redoAndReselect: with: (begin + UndoMessage argument to: begin + UndoSelection size - 1) with: (stop to: stop - 1). UndoInterval _ begin to: stop - 1]. beginTypeInBlock _ nil]! ! !ParagraphEditor methodsFor: 'typing support'! closeTypeIn: characterStream "Call instead of closeTypeIn when you want typeahead to be inserted before the control character is executed, e.g., from Ctrl-V." self insertTypeAhead: characterStream. self closeTypeIn! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'di 9/7/1999 11:26'! dispatchOnEnterWith: typeAheadStream "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. " sensor keyboard. "consume enter key" self terminateAndInitializeAround: [ sensor commandKeyPressed ifTrue: [self printIt.] ifFalse: [self closeTypeIn: typeAheadStream. self accept]. ]. ^ true! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'di 6/14/1998 13:08'! doneTyping beginTypeInBlock _ nil! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'! insertTypeAhead: typeAhead typeAhead position = 0 ifFalse: [self zapSelectionWith: (Text string: typeAhead contents emphasis: emphasisHere). typeAhead reset. self unselect]! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:48'! openTypeIn "Set up UndoSelection to null text (to be added to by readKeyboard and backTo:), beginTypeInBlock to keep track of the leftmost backspace, and UndoParameter to tally how many deleted characters were backspaced over rather than 'cut'. You can't undo typing until after closeTypeIn." beginTypeInBlock == nil ifTrue: [UndoSelection _ self nullText. self undoer: #noUndoer with: 0. beginTypeInBlock _ self startIndex]! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/19/2002 18:26'! readKeyboard "Key struck on the keyboard. Find out which one and, if special, carry out the associated special action. Otherwise, add the character to the stream of characters. Undoer & Redoer: see closeTypeIn." | typeAhead char | typeAhead _ WriteStream on: (String new: 128). [sensor keyboardPressed] whileTrue: [self deselect. [sensor keyboardPressed] whileTrue: [char _ sensor keyboardPeek. (self dispatchOnCharacter: char with: typeAhead) ifTrue: [self doneTyping. self setEmphasisHere. ^self selectAndScroll; updateMarker]. self openTypeIn]. self hasSelection ifTrue: "save highlighted characters" [UndoSelection _ self selection]. self zapSelectionWith: (Text string: typeAhead contents emphasis: emphasisHere). typeAhead reset. self unselect. sensor keyboardPressed ifFalse: [self selectAndScroll. sensor keyboardPressed ifFalse: [self updateMarker]]]! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/18/2002 16:49'! setEmphasisHere emphasisHere _ (paragraph text attributesAt: (self pointIndex - 1 max: 1) forStyle: paragraph textStyle) select: [:att | att mayBeExtended]! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'th 9/17/2002 16:23'! simulatedKeystroke: char "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." self deselect. self openTypeIn. self markBlock = self pointBlock ifFalse: [UndoSelection _ self selection]. self zapSelectionWith: (Text string: char asString emphasis: emphasisHere). self userHasEdited. self unselect. self selectAndScroll. self updateMarker. view ifNotNil: [view topView uncacheBits "in mvc, this makes sure the recognized character shows up in the pane right now; in morphic, a different mechanism is used for the same effect -- see TextMorphEditor method #recognizeCharactersWhileMouseIn:"] ! ! !ParagraphEditor methodsFor: 'typing support' stamp: 'di 10/6/1998 08:45'! startOfTyping "Compatibility during change from characterBlock to integer" beginTypeInBlock == nil ifTrue: [^ nil]. beginTypeInBlock isNumber ifTrue: [^ beginTypeInBlock]. "Last line for compatibility during change from CharacterBlock to Integer." ^ beginTypeInBlock stringIndex ! ! !ParagraphEditor methodsFor: 'undoers'! undoAgain: indices andReselect: home typedKey: wasTypedKey "The last command was again. Undo it. Redoer: itself." | findSize substText index subject | (self isRedoing & wasTypedKey) ifTrue: "redelete search key" [self selectInterval: home. self zapSelectionWith: self nullText]. findSize _ (self isRedoing ifTrue: [FindText] ifFalse: [ChangeText]) size. substText _ self isUndoing ifTrue: [FindText] ifFalse: [ChangeText]. (self isUndoing ifTrue: [indices size to: 1 by: -1] ifFalse: [1 to: indices size]) do: [:i | index _ indices at: i. (subject _ index to: index + findSize - 1) = self selectionInterval ifFalse: [self selectInterval: subject]. FindText == ChangeText ifFalse: [self zapSelectionWith: substText]]. self isUndoing ifTrue: "restore selection to where it was when 'again' was invoked" [wasTypedKey ifTrue: "search started by typing key at a caret; restore it" [self selectAt: home first. self zapSelectionWith: FindText. self selectAt: home last + 1] ifFalse: [self selectInterval: home]]. self undoMessage: UndoMessage forRedo: self isUndoing! ! !ParagraphEditor methodsFor: 'undoers'! undoAndReselect: undoHighlight redoAndReselect: redoHighlight "Undo typing, cancel, paste, and other operations that are like replaces but the selection is not the whole restored text after undo, redo, or both. undoHighlight is selected after this phase and redoHighlight after the next phase. Redoer: itself." self replace: self selectionInterval with: UndoSelection and: [self selectInterval: undoHighlight]. self undoMessage: (UndoMessage argument: redoHighlight) forRedo: self isUndoing ! ! !ParagraphEditor methodsFor: 'undoers'! undoCutCopy: oldPasteBuffer "Undo of a cut, copy, or any edit that changed CurrentSelection. Be sure undo-copy does not lock the model. Redoer: itself, so never isRedoing." | recentCut | recentCut _ self clipboardText. UndoSelection size = UndoInterval size ifFalse: [self replaceSelectionWith: UndoSelection]. self clipboardTextPut: oldPasteBuffer. self undoer: #undoCutCopy: with: recentCut! ! !ParagraphEditor methodsFor: 'undoers' stamp: 'th 9/19/2002 18:46'! undoQuery: hintText lastOffering: selectorOrNil "Undo ctrl-q. selectorOrNil (if not nil) is the previously offered selector. hintText is the original hint. Redoer: completeSymbol." self zapSelectionWith: UndoSelection. self undoMessage: (Message selector: #completeSymbol:lastOffering: arguments: UndoMessage arguments) forRedo: true. self selectAt: self stopIndex! ! !ParagraphEditor methodsFor: 'undoers'! undoReplace "Undo of any command that replaced a selection by other text that it left highlighted, and that is undone and redone by simple reversal of the operation. This is the most common Undoer; call replaceSelectionWith: to get this setup. Redoer: itself, so never isRedoing." self replaceSelectionWith: UndoSelection! ! !ParagraphEditor methodsFor: 'undo support'! isDoing "Call from a doer/undoer/redoer any time to see which it is." ^(self isUndoing | self isRedoing) not! ! !ParagraphEditor methodsFor: 'undo support'! isRedoing "Call from a doer/undoer/redoer any time to see which it is." ^UndoParagraph == #redoing! ! !ParagraphEditor methodsFor: 'undo support'! isUndoing "Call from a doer/undoer/redoer any time to see which it is." ^UndoParagraph == #undoing! ! !ParagraphEditor methodsFor: 'undo support'! noUndoer "The Undoer to use when the command can not be undone. Checked for specially by readKeyboard." UndoMessage _ Message selector: #noUndoer! ! !ParagraphEditor methodsFor: 'undo support'! undoMessage: aMessage forRedo: aBoolean "Call this from an undoer/redoer to set up UndoMessage as the corresponding redoer/undoer. Also set up UndoParagraph, as well as the state variable Undone. It is assumed that UndoInterval has been established (generally by zapSelectionWith:) and that UndoSelection has been saved (generally by replaceSelectionWith: or replace:With:and:)." self isDoing ifTrue: [UndoParagraph _ paragraph]. UndoMessage _ aMessage. Undone _ aBoolean! ! !ParagraphEditor methodsFor: 'undo support'! undoer: aSelector "See comment in undoMessage:. Use this version when aSelector has no arguments, and you are doing or redoing and want to prepare for undoing." self undoMessage: (Message selector: aSelector) forRedo: false! ! !ParagraphEditor methodsFor: 'undo support'! undoer: aSelector with: arg1 "See comment in undoMessage:. Use this version when aSelector has one argument, and you are doing or redoing and want to prepare for undoing." self undoMessage: (Message selector: aSelector argument: arg1) forRedo: false! ! !ParagraphEditor methodsFor: 'undo support'! undoer: aSelector with: arg1 with: arg2 "See comment in undoMessage:. Use this version when aSelector has two arguments, and you are doing or redoing and want to prepare for undoing." self undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2)) forRedo: false! ! !ParagraphEditor methodsFor: 'undo support'! undoer: aSelector with: arg1 with: arg2 with: arg3 "See comment in undoMessage:. Use this version when aSelector has three arguments, and you are doing or redoing and want to prepare for undoing." self undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2 with: arg3)) forRedo: false! ! !ParagraphEditor methodsFor: 'current selection'! deselect "If the text selection is visible on the screen, reverse its highlight." selectionShowing ifTrue: [self reverseSelection]! ! !ParagraphEditor methodsFor: 'current selection'! initializeSelection "Do the initial activity when starting up the receiver. For example, in the ParagraphEditor highlight the current selection." self select! ! !ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/20/2002 11:41'! recomputeInterval "The same characters are selected but their coordinates may have changed." self computeIntervalFrom: self mark to: self pointIndex - 1! ! !ParagraphEditor methodsFor: 'current selection'! recomputeSelection "Redetermine the selection according to the start and stop block indices; do not highlight." self deselect; recomputeInterval! ! !ParagraphEditor methodsFor: 'current selection' stamp: 'BG 12/12/2003 12:50'! reverseSelection "Reverse the valence of the current selection highlighting." selectionShowing _ selectionShowing not. paragraph reverseFrom: self pointBlock to: self markBlock! ! !ParagraphEditor methodsFor: 'current selection'! select "If the text selection is visible on the screen, highlight it." selectionShowing ifFalse: [self reverseSelection]! ! !ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:47'! selectAndScroll "Scroll until the selection is in the view and then highlight it." | lineHeight deltaY clippingRectangle endBlock | self select. endBlock _ self stopBlock. lineHeight _ paragraph textStyle lineGrid. clippingRectangle _ paragraph clippingRectangle. deltaY _ endBlock top - clippingRectangle top. deltaY >= 0 ifTrue: [deltaY _ endBlock bottom - clippingRectangle bottom max: 0]. "check if stopIndex below bottom of clippingRectangle" deltaY ~= 0 ifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight) * deltaY sign]! ! !ParagraphEditor methodsFor: 'current selection' stamp: 'th 9/19/2002 18:48'! selectAndScrollToTop "Scroll until the selection is in the view and then highlight it." | lineHeight deltaY clippingRectangle | self select. lineHeight _ paragraph textStyle lineGrid. clippingRectangle _ paragraph clippingRectangle. deltaY _ self stopBlock top - clippingRectangle top. deltaY ~= 0 ifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight) * deltaY sign]! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:37'! adjustSelection: directionBlock "Helper function for Cursor movement. Always moves point thus allowing selections to shrink. " "See also expandSelection:" "Accepts a one argument Block that computes the new postion given an old one." | newPosition | newPosition _ directionBlock value: self pointIndex. self selectMark: self markIndex point: newPosition. ^true.! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 10/28/2003 12:11'! afterSelectionInsertAndSelect: aString self insertAndSelect: aString at: self stopIndex ! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/17/2002 16:11'! computeIntervalFrom: start to: stop "Select the designated characters, inclusive. Make no visual changes." self setMark: start. self setPoint: stop + 1.! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:21'! correctFrom: start to: stop with: aString "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." | wasShowing userSelection delta loc | aString = '#insert period' ifTrue: [loc _ start. [(loc _ loc-1)>0 and: [(paragraph text string at: loc) isSeparator]] whileTrue: [loc _ loc-1]. ^ self correctFrom: loc+1 to: loc with: '.']. (wasShowing _ selectionShowing) ifTrue: [ self reverseSelection ]. userSelection _ self selectionInterval. self selectInvisiblyFrom: start to: stop. self replaceSelectionWith: aString asText. delta _ aString size - (stop - start + 1). self selectInvisiblyFrom: userSelection first + (userSelection first > start ifFalse: [ 0 ] ifTrue: [ delta ]) to: userSelection last + (userSelection last > start ifFalse: [ 0 ] ifTrue: [ delta ]). wasShowing ifTrue: [ self reverseSelection ]. ! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:21'! encompassLine: anInterval "Return an interval that encompasses the entire line" | string left right | string _ paragraph text string. left _ (string lastIndexOf: Character cr startingAt: anInterval first - 1 ifAbsent:[0]) + 1. right _ (string indexOf: Character cr startingAt: anInterval last + 1 ifAbsent: [string size + 1]) - 1. ^left to: right! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'di 12/17/1998 09:41'! insertAndSelect: aString at: anInteger self replace: (anInteger to: anInteger - 1) with: (Text string: (' ' , aString) attributes: emphasisHere) and: [self selectAndScroll]! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/6/1998 15:25'! nextTokenFrom: start direction: dir "simple token-finder for compiler automated corrections" | loc str | loc _ start + dir. str _ paragraph text string. [(loc between: 1 and: str size) and: [(str at: loc) isSeparator]] whileTrue: [loc _ loc + dir]. ^ loc! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/20/1998 08:31'! notify: aString at: anInteger in: aStream "The compilation of text failed. The syntax error is noted as the argument, aString. Insert it in the text at starting character position anInteger." self insertAndSelect: aString at: (anInteger max: 1)! ! !ParagraphEditor methodsFor: 'new selection'! selectAt: characterIndex "Deselect, then place the caret before the character at characterIndex. Be sure it is in view." self selectFrom: characterIndex to: characterIndex - 1! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:50'! selectFrom: start to: stop "Deselect, then select the specified characters inclusive. Be sure the selection is in view." (start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse: [self deselect. self selectInvisiblyFrom: start to: stop]. self selectAndScroll! ! !ParagraphEditor methodsFor: 'new selection'! selectInterval: anInterval "Deselect, then select the specified characters inclusive. Be sure the selection is in view." self selectFrom: anInterval first to: anInterval last! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'di 5/9/1998 20:59'! selectInvisiblyFrom: start to: stop "Select the designated characters, inclusive. Make no visual changes." ^ self computeIntervalFrom: start to: stop! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:17'! selectInvisiblyMark: mark point: point "Select the designated characters, inclusive. Make no visual changes." ^ self computeIntervalFrom: mark to: point! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 17:17'! selectLine "Make the receiver's selection, if it currently consists of an insertion point only, encompass the current line." self hasSelection ifTrue:[^self]. self selectInterval: (self encompassLine: self selectionInterval)! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 14:18'! selectMark: mark point: point "Deselect, then select the specified characters inclusive. Be sure the selection is in view." (mark = self markIndex and: [point + 1 = self pointIndex]) ifFalse: [self deselect. self selectInvisiblyMark: mark point: point]. self selectAndScroll! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/19/2002 18:49'! selectPrecedingIdentifier "Invisibly select the identifier that ends at the end of the selection, if any." | string sep stop tok | tok _ false. string _ paragraph text string. stop _ self stopIndex - 1. [stop > 0 and: [(string at: stop) isSeparator]] whileTrue: [stop _ stop - 1]. sep _ stop. [sep > 0 and: [(string at: sep) tokenish]] whileTrue: [tok _ true. sep _ sep - 1]. tok ifTrue: [self selectInvisiblyFrom: sep + 1 to: stop]! ! !ParagraphEditor methodsFor: 'new selection' stamp: 'th 9/18/2002 16:51'! selectWord "Select delimited text or word--the result of double-clicking." | openDelimiter closeDelimiter direction match level leftDelimiters rightDelimiters string here hereChar start stop | string _ paragraph text string. here _ self pointIndex. (here between: 2 and: string size) ifFalse: ["if at beginning or end, select entire string" ^self selectFrom: 1 to: string size]. leftDelimiters _ '([{<''" '. rightDelimiters _ ')]}>''" '. openDelimiter _ string at: here - 1. match _ leftDelimiters indexOf: openDelimiter. match > 0 ifTrue: ["delimiter is on left -- match to the right" start _ here. direction _ 1. here _ here - 1. closeDelimiter _ rightDelimiters at: match] ifFalse: [openDelimiter _ string at: here. match _ rightDelimiters indexOf: openDelimiter. match > 0 ifTrue: ["delimiter is on right -- match to the left" stop _ here - 1. direction _ -1. closeDelimiter _ leftDelimiters at: match] ifFalse: ["no delimiters -- select a token" direction _ -1]]. level _ 1. [level > 0 and: [direction > 0 ifTrue: [here < string size] ifFalse: [here > 1]]] whileTrue: [hereChar _ string at: (here _ here + direction). match = 0 ifTrue: ["token scan goes left, then right" hereChar tokenish ifTrue: [here = 1 ifTrue: [start _ 1. "go right if hit string start" direction _ 1]] ifFalse: [direction < 0 ifTrue: [start _ here + 1. "go right if hit non-token" direction _ 1] ifFalse: [level _ 0]]] ifFalse: ["bracket match just counts nesting level" hereChar = closeDelimiter ifTrue: [level _ level - 1"leaving nest"] ifFalse: [hereChar = openDelimiter ifTrue: [level _ level + 1"entering deeper nest"]]]]. level > 0 ifTrue: ["in case ran off string end" here _ here + direction]. direction > 0 ifTrue: [self selectFrom: start to: here - 1] ifFalse: [self selectFrom: here + 1 to: stop]! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:48'! againOnce: indices "Find the next occurrence of FindText. If none, answer false. Append the start index of the occurrence to the stream indices, and, if ChangeText is not the same object as FindText, replace the occurrence by it. Note that the search is case-sensitive for replacements, otherwise not." | where | where _ paragraph text findString: FindText startingAt: self stopIndex caseSensitive: ((ChangeText ~~ FindText) or: [Preferences caseSensitiveFinds]). where = 0 ifTrue: [^ false]. self deselect; selectInvisiblyFrom: where to: where + FindText size - 1. ChangeText ~~ FindText ifTrue: [self zapSelectionWith: ChangeText]. indices nextPut: where. self selectAndScroll. ^ true! ! !ParagraphEditor methodsFor: 'private'! againOrSame: useOldKeys "Subroutine of search: and again. If useOldKeys, use same FindText and ChangeText as before. 1/26/96 sw: real worked moved to againOrSame:many:" ^ self againOrSame: useOldKeys many: sensor leftShiftDown! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:53'! againOrSame: useOldKeys many: many "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." | home indices wasTypedKey | home _ self selectionInterval. "what was selected when 'again' was invoked" "If new keys are to be picked..." useOldKeys ifFalse: "Choose as FindText..." [FindText _ UndoSelection. "... the last thing replaced." "If the last command was in another paragraph, ChangeText is set..." paragraph == UndoParagraph ifTrue: "... else set it now as follows." [UndoInterval ~= home ifTrue: [self selectInterval: UndoInterval]. "blink" ChangeText _ ((UndoMessage sends: #undoCutCopy:) and: [self hasSelection]) ifTrue: [FindText] "== objects signal no model-locking by 'undo copy'" ifFalse: [self selection]]]. "otherwise, change text is last-replaced text" (wasTypedKey _ FindText size = 0) ifTrue: "just inserted at a caret" [home _ self selectionInterval. self replaceSelectionWith: self nullText. "delete search key..." FindText _ ChangeText] "... and search for it, without replacing" ifFalse: "Show where the search will start" [home last = self selectionInterval last ifFalse: [self selectInterval: home]]. "Find and Change, recording start indices in the array" indices _ WriteStream on: (Array new: 20). "an array to store change locs" [(self againOnce: indices) & many] whileTrue. "<-- this does the work" indices isEmpty ifTrue: "none found" [self flash. wasTypedKey ifFalse: [^self]]. (many | wasTypedKey) ifFalse: "after undo, select this replacement" [home _ self startIndex to: self startIndex + UndoSelection size - 1]. self undoer: #undoAgain:andReselect:typedKey: with: indices contents with: home with: wasTypedKey! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 18:16'! completeSymbol: hintText lastOffering: selectorOrNil "Invoked by Ctrl-q when there is only a caret. Do selector-completion, i.e., try to replace the preceding identifier by a selector that begins with those characters & has as many keywords as possible. Leave two spaces after each colon (only one after the last) as space for arguments. Put the caret after the space after the first keyword. If the user types Ctrl-q again immediately, choose a different selector. Undoer: #undoQuery:lastOffering:; Redoer: itself. If redoing, just redisplay the last offering, selector[OrNil]." | firstTime input prior caret newStart sym kwds outStream | firstTime _ self isRedoing ifTrue: [prior _ sym _ selectorOrNil. true] ifFalse: [hintText isNil]. firstTime ifTrue: "Initial Ctrl-q (or redo)" [caret _ self startIndex. self selectPrecedingIdentifier. input _ self selection] ifFalse: "Repeated Ctrl-q" [caret _ UndoInterval first + hintText size. self selectInvisiblyFrom: UndoInterval first to: UndoInterval last. input _ hintText. prior _ selectorOrNil]. (input size ~= 0 and: [sym ~~ nil or: [(sym _ Symbol thatStarts: input string skipping: prior) ~~ nil]]) ifTrue: "found something to offer" [newStart _ self startIndex. outStream _ WriteStream on: (String new: 2 * sym size). 1 to: (kwds _ sym keywords) size do: [:i | outStream nextPutAll: (kwds at: i). i = 1 ifTrue: [caret _ newStart + outStream contents size + 1]. outStream nextPutAll: (i < kwds size ifTrue: [' '] ifFalse: [' '])]. UndoSelection _ input. self deselect; zapSelectionWith: outStream contents asText. self undoer: #undoQuery:lastOffering: with: input with: sym] ifFalse: "no more matches" [firstTime ifFalse: "restore original text & set up for a redo" [UndoSelection _ self selection. self deselect; zapSelectionWith: input. self undoer: #completeSymbol:lastOffering: with: input with: prior. Undone _ true]. view flash]. self selectAt: caret! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/18/2002 16:49'! exchangeWith: prior "If the prior selection is non-overlapping and legal, exchange the text of it with the current selection and leave the currently selected text selected in the location of the prior selection (or leave a caret after a non-caret if it was exchanged with a caret). If both selections are carets, flash & do nothing. Don't affect the paste buffer. Undoer: itself; Redoer: Undoer." | start stop before selection priorSelection delta altInterval | start _ self startIndex. stop _ self stopIndex - 1. ((prior first <= prior last) | (start <= stop) "Something to exchange" and: [self isDisjointFrom: prior]) ifTrue: [before _ prior last < start. selection _ self selection. priorSelection _ paragraph text copyFrom: prior first to: prior last. delta _ before ifTrue: [0] ifFalse: [priorSelection size - selection size]. self zapSelectionWith: priorSelection. self selectFrom: prior first + delta to: prior last + delta. delta _ before ifTrue: [stop - prior last] ifFalse: [start - prior first]. self zapSelectionWith: selection. altInterval _ prior first + delta to: prior last + delta. self undoer: #exchangeWith: with: altInterval. "If one was a caret, make it otherInterval & leave the caret after the other" prior first > prior last ifTrue: [self selectAt: UndoInterval last + 1]. otherInterval _ start > stop ifTrue: [self selectAt: altInterval last + 1. UndoInterval] ifFalse: [altInterval]] ifFalse: [view flash]! ! !ParagraphEditor methodsFor: 'private' stamp: 'raok 11/15/2001 14:01'! explainDelimitor: string "Is string enclosed in delimitors?" | str | (string at: 1) isLetter ifTrue: [^nil]. "only special chars" (string first = string last) ifTrue: [^ self explainChar: (String with: string first)] ifFalse: [(string first = $( and: [string last = $)]) ifTrue: [^ self explainChar: (String with: string first)]. (string first = $[ and: [string last = $]]) ifTrue: [^ self explainChar: (String with: string first)]. (string first = ${ and: [string last = $}]) ifTrue: [^ self explainChar: (String with: string first)]. (string first = $< and: [string last = $>]) ifTrue: [^ self explainChar: (String with: string first)]. (string first = $# and: [string last = $)]) ifTrue: [^'"An instance of class Array. The Numbers, Characters, or Symbols between the parenthesis are the elements of the Array."']. string first = $# ifTrue: [^'"An instance of class Symbol."']. (string first = $$ and: [string size = 2]) ifTrue: [^'"An instance of class Character. This one is the character ', (String with: string last), '."']. (string first = $:) ifTrue: [str _ string allButFirst. (self explainTemp: str) ~~ nil ifTrue: [^'"An argument to this block will be bound to the temporary variable ', str, '."']]]. ^ nil! ! !ParagraphEditor methodsFor: 'private' stamp: 'tk 7/14/2000 12:15'! getPluggableYellowButtonMenu: shiftKeyState | customMenu | ^ ((view ~~ nil) and: [(customMenu _ view getMenu: shiftKeyState) notNil]) ifTrue: [customMenu] ifFalse: [shiftKeyState ifTrue: [self class shiftedYellowButtonMenu] ifFalse: [self class yellowButtonMenu]]! ! !ParagraphEditor methodsFor: 'private'! indent: delta fromStream: inStream toStream: outStream "Append the contents of inStream to outStream, adding or deleting delta or -delta tabs at the beginning, and after every CR except a final CR. Do not add tabs to totally empty lines, and be sure nothing but tabs are removed from lines." | ch skip cr tab prev atEnd | cr _ Character cr. tab _ Character tab. delta > 0 ifTrue: "shift right" [prev _ cr. [ch _ (atEnd _ inStream atEnd) ifTrue: [cr] ifFalse: [inStream next]. (prev == cr and: [ch ~~ cr]) ifTrue: [delta timesRepeat: [outStream nextPut: tab]]. atEnd] whileFalse: [outStream nextPut: ch. prev _ ch]] ifFalse: "shift left" [skip _ delta. "a negative number" [inStream atEnd] whileFalse: [((ch _ inStream next) == tab and: [skip < 0]) ifFalse: [outStream nextPut: ch]. skip _ ch == cr ifTrue: [delta] ifFalse: [skip + 1]]]! ! !ParagraphEditor methodsFor: 'private' stamp: 'cmm 4/9/2004 14:00'! isDisjointFrom: anInterval "Answer true if anInterval is a caret not touching or within the current interval, or if anInterval is a non-caret that does not overlap the current selection." | fudge | fudge _ anInterval size = 0 ifTrue: [1] ifFalse: [0]. ^(anInterval last + fudge < self startIndex or: [anInterval first - fudge >= self stopIndex]) ! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 11/24/2002 17:13'! lines "Other than my member paragraph i compute lines based on logical line breaks, not optical (which may change due to line wrapping of the editor)" | lines string index lineIndex stringSize | string _ paragraph text string. "Empty strings have no lines at all. Think of something." string isEmpty ifTrue:[^{#(1 0 0)}]. stringSize _ string size. lines _ OrderedCollection new: (string size // 15). index _ 0. lineIndex _ 0. string linesDo:[:line | lines addLast: (Array with: (index _ index + 1) with: (lineIndex _ lineIndex + 1) with: (index _ index + line size min: stringSize))]. "Special workaround for last line empty." string last == Character cr "lines last last < stringSize" ifTrue:[lines addLast:{stringSize +1. lineIndex+1. stringSize}]. ^lines! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 19:57'! moveCursor: directionBlock forward: forward specialBlock: specialBlock "Private - Move cursor. directionBlock is a one argument Block that computes the new Position from a given one. specialBlock is a one argumentBlock that computes the new position from a given one under the alternate semantics. Note that directionBlock always is evaluated first." | shift indices newPosition | shift _ sensor leftShiftDown. indices _ self setIndices: shift forward: forward. newPosition _ directionBlock value: (indices at: #moving). (sensor commandKeyPressed or:[sensor controlKeyPressed]) ifTrue: [newPosition _ specialBlock value: newPosition]. sensor keyboard. shift ifTrue: [self selectMark: (indices at: #fixed) point: newPosition - 1] ifFalse: [self selectAt: newPosition]! ! !ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:32'! nextWord: position | string index | string _ paragraph text string. index _ position. [(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]] whileTrue: [index _ index + 1]. [(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]] whileTrue: [index _ index + 1]. ^ index! ! !ParagraphEditor methodsFor: 'private'! nullText ^Text string: '' emphasis: emphasisHere! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/20/2002 11:09'! pageHeight | howManyLines visibleHeight totalHeight ratio | howManyLines _ paragraph numberOfLines. visibleHeight _ self visibleHeight. totalHeight _ self totalTextHeight. ratio _ visibleHeight / totalHeight. ^(ratio * howManyLines) rounded - 2! ! !ParagraphEditor methodsFor: 'private' stamp: 'sma 12/15/1999 11:33'! previousWord: position | string index | string _ paragraph text string. index _ position. [(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric not]] whileTrue: [index _ index - 1]. [(index between: 1 and: string size) and: [(string at: index) isAlphaNumeric]] whileTrue: [index _ index - 1]. ^ index + 1! ! !ParagraphEditor methodsFor: 'private' stamp: 'BG 4/29/2004 11:19'! sameColumn: start newLine: lineBlock forward: isForward "Private - Compute the index in my text with the line number derived from lineBlock," " a one argument block accepting the old line number. The position inside the line will be preserved as good as possible" "The boolean isForward is used in the border case to determine if we should move to the beginning or the end of the line." | wordStyle column currentLine offsetAtTargetLine targetEOL lines numberOfLines currentLineNumber targetLineNumber | wordStyle _ Preferences wordStyleCursorMovement. wordStyle ifTrue: [ lines _ paragraph lines. numberOfLines := paragraph numberOfLines. currentLineNumber _ paragraph lineIndexOfCharacterIndex: start. currentLine _ lines at: currentLineNumber] ifFalse: [ lines _ self lines. numberOfLines := lines size. currentLine _ lines detect:[:lineInterval | lineInterval last >= start] ifNone:[lines last]. currentLineNumber _ currentLine second]. column _ start - currentLine first. targetLineNumber _ ((lineBlock value: currentLineNumber) max: 1) min: numberOfLines. offsetAtTargetLine _ (lines at: targetLineNumber) first. targetEOL _ (lines at: targetLineNumber) last + (targetLineNumber == numberOfLines ifTrue:[1]ifFalse:[0]). targetLineNumber == currentLineNumber "No movement or movement failed. Move to beginning or end of line." ifTrue:[^isForward ifTrue:[targetEOL] ifFalse:[offsetAtTargetLine]]. ^offsetAtTargetLine + column min: targetEOL.! ! !ParagraphEditor methodsFor: 'private' stamp: 'th 9/19/2002 19:02'! setIndices: shiftPressed forward: forward "Little helper method that sets the moving and fixed indices according to some flags." | indices | indices _ Dictionary new. (shiftPressed and:[Preferences selectionsMayShrink]) ifTrue: [ indices at: #moving put: self pointIndex. indices at: #fixed put: self markIndex ] ifFalse: [ forward ifTrue:[ indices at: #moving put: self stopIndex. indices at: #fixed put: self startIndex. ] ifFalse: [ indices at: #moving put: self startIndex. indices at: #fixed put: self stopIndex. ] ]. ^indices! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'vb 8/13/2001 23:41'! compileSelectionFor: anObject in: evalContext | methodNode method | methodNode _ [Compiler new compileNoPattern: self selectionAsStream in: anObject class context: evalContext notifying: self ifFail: [^nil]] on: OutOfScopeNotification do: [:ex | ex resume: true]. method _ methodNode generate: #(0 0 0 0). ^method copyWithTempNames: methodNode tempNames! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'NS 1/28/2004 11:19'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector _ evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig _ evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context _ guineaPig suspendedContext. debugger _ Debugger new process: guineaPig controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: context isolationHead: nil. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'vb 8/13/2001 23:38'! debugIt | method receiver context | (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. receiver _ model doItReceiver. context _ model doItContext] ifFalse: [receiver _ context _ nil]. self lineSelectAndEmptyCheck: [^self]. method _ self compileSelectionFor: receiver in: context. method notNil ifTrue: [self debug: method receiver: receiver in: context]. FakeClassPool adopt: nil! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:38'! doIt "Set the context to include pool vars of the model. Then evaluate." ^ self evaluateSelection. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'gk 3/3/2004 17:15'! evaluateSelection "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | self lineSelectAndEmptyCheck: [^ '']. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [ rcvr class evaluatorClass new evaluate: self selectionAsStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'di 9/7/1999 11:25'! inspectIt "1/13/96 sw: minor fixup" | result | result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [result inspect]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'sd 4/16/2003 11:41'! objectsReferencingIt "Open a list inspector on all objects that reference the object that results when the current selection is evaluated. " | result | self terminateAndInitializeAround: [ result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [self systemNavigation browseAllObjectReferencesTo: result except: #() ifNone: [:obj | view topView flash]]. ]! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'di 5/10/1998 21:52'! printIt "Treat the current text selection as an expression; evaluate it. Insert the description of the result of evaluation after the selection and then make this description the new text selection." | result | result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [self afterSelectionInsertAndSelect: result printString]! ! !ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'BG 6/1/2003 09:43'! offerMenuFromEsc: aStream sensor keyboard. " consume the character " self yellowButtonActivity. ^true "tell the caller that the character was processed "! ! !ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:40'! totalTextHeight ^paragraph boundingBox height! ! !ParagraphEditor methodsFor: 'as yet unclassified' stamp: 'sbw 10/13/1999 22:33'! visibleHeight ^paragraph clippingRectangle height! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'! hasCaret ^self markBlock = self pointBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:22'! hasSelection ^self hasCaret not! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:13'! mark ^ self markBlock stringIndex! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'! markBlock ^ stopBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'! markBlock: aCharacterBlock stopBlock _ aCharacterBlock. ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'! markIndex ^ self markBlock stringIndex! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'! pointBlock ^ startBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 10/21/2003 15:49'! pointBlock: aCharacterBlock startBlock _ aCharacterBlock. ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 12:31'! pointIndex ^ self pointBlock stringIndex! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 17:28'! selection "Answer the text in the paragraph that is currently selected." ^paragraph text copyFrom: self startIndex to: self stopIndex - 1 ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:10'! selectionAsStream "Answer a ReadStream on the text in the paragraph that is currently selected." ^ReadWriteStream on: paragraph string from: self startIndex to: self stopIndex - 1! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 16:18'! selectionInterval "Answer the interval that is currently selected." ^self startIndex to: self stopIndex - 1 ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'! setMark: anIndex self markBlock: (paragraph characterBlockForIndex: anIndex) ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:02'! setPoint: anIndex self pointBlock: (paragraph characterBlockForIndex: anIndex) ! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:10'! startBlock ^ self pointBlock min: self markBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'! startBlock: aCharacterBlock self markBlock: aCharacterBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'! startIndex ^ self startBlock stringIndex! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:14'! stopBlock ^ self pointBlock max: self markBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 13:10'! stopBlock: aCharacterBlock self pointBlock: aCharacterBlock! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/18/2002 14:27'! stopIndex ^ self stopBlock stringIndex! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/17/2002 16:23'! unselect self markBlock: self pointBlock copy.! ! !ParagraphEditor methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:12'! zapSelectionWith: aText "Deselect, and replace the selection text by aText. Remember the resulting selectionInterval in UndoInterval and otherInterval. Do not set up for undo." | start stop | self deselect. start _ self startIndex. stop _ self stopIndex. (aText isEmpty and: [stop > start]) ifTrue: ["If deleting, then set emphasisHere from 1st character of the deletion" emphasisHere _ (paragraph text attributesAt: start forStyle: paragraph textStyle) select: [:att | att mayBeExtended]]. (start = stop and: [aText size = 0]) ifFalse: [paragraph replaceFrom: start to: stop - 1 with: aText displaying: true. self computeIntervalFrom: start to: start + aText size - 1. UndoInterval _ otherInterval _ self selectionInterval]! ! !ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/7/2002 03:51'! blinkParenAt: parenLocation self text addAttribute: TextEmphasis bold from: parenLocation to: parenLocation. lastParenLocation _ parenLocation.! ! !ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/7/2002 04:03'! blinkPrevParen | openDelimiter closeDelimiter level string here hereChar | string _ paragraph text string. here _ startBlock stringIndex. openDelimiter _ sensor keyboardPeek. closeDelimiter _ '([{' at: (')]}' indexOf: openDelimiter). level _ 1. [level > 0 and: [here > 2]] whileTrue: [hereChar _ string at: (here _ here - 1). hereChar = closeDelimiter ifTrue: [level _ level - 1. level = 0 ifTrue: [^ self blinkParenAt: here]] ifFalse: [hereChar = openDelimiter ifTrue: [level _ level + 1]]].! ! !ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/10/2002 00:30'! clearParens lastParenLocation ifNotNil: [self text string size >= lastParenLocation ifTrue: [ self text removeAttribute: TextEmphasis bold from: lastParenLocation to: lastParenLocation]] ! ! !ParagraphEditor methodsFor: 'parenblinking' stamp: 'AB 1/8/2002 03:30'! dispatchOnCharacter: char with: typeAheadStream "Carry out the action associated with this character, if any. Type-ahead is passed so some routines can flush or use it." | honorCommandKeys | self clearParens. char asciiValue = 13 ifTrue: [ ^ sensor controlKeyPressed ifTrue: [self normalCharacter: typeAheadStream] ifFalse: [self crWithIndent: typeAheadStream]]. ((honorCommandKeys _ Preferences cmdKeysInText) and: [char = Character enter]) ifTrue: [^ self dispatchOnEnterWith: typeAheadStream]. "Special keys overwrite crtl+key combinations - at least on Windows. To resolve this conflict, assume that keys other than cursor keys aren't used together with Crtl." ((self class specialShiftCmdKeys includes: char asciiValue) and: [char asciiValue < 27]) ifTrue: [^ sensor controlKeyPressed ifTrue: [self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream] ifFalse: [self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]]. "backspace, and escape keys (ascii 8 and 27) are command keys" ((honorCommandKeys and: [sensor commandKeyPressed]) or: [self class specialShiftCmdKeys includes: char asciiValue]) ifTrue: [^ sensor leftShiftDown ifTrue: [self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream] ifFalse: [self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream]]. "the control key can be used to invoke shift-cmd shortcuts" (honorCommandKeys and: [sensor controlKeyPressed]) ifTrue: [^ self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream]. (')]}' includes: char) ifTrue: [self blinkPrevParen]. ^ self perform: #normalCharacter: with: typeAheadStream! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ParagraphEditor class instanceVariableNames: ''! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'sw 5/27/2000 00:03'! abandonChangeText "Call this to get out of the maddening situation in which the system keeps aggressively trying to do a replacement that you no longer wish to make, every time you make choose a new method in a list." ChangeText _ FindText "ParagraphEditor abandonChangeText" ! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'ar 1/15/2001 18:47'! initialize "Initialize the keyboard shortcut maps and the shared buffers for copying text across views and managing again and undo. Marked this method changed to trigger reinit" "ParagraphEditor initialize" UndoSelection _ FindText _ ChangeText _ Text new. UndoMessage _ Message selector: #halt. self initializeCmdKeyShortcuts. self initializeShiftCmdKeyShortcuts. self initializeTextEditorMenus ! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'BG 10/28/2003 17:46'! initializeTextEditorMenus "Initialize the yellow button pop-up menu and corresponding messages." "ParagraphEditor initializeTextEditorMenus" TextEditorYellowButtonMenu _ SelectionMenu labels: 'find...(f) find again (g) set search string (h) do again (j) undo (z) copy (c) cut (x) paste (v) paste... do it (d) print it (p) inspect it (i) debug it accept (s) cancel (l) show bytecodes more...' lines: #(3 5 9 13 15 16) selections: #(find findAgain setSearchString again undo copySelection cut paste pasteRecent doIt printIt inspectIt debugIt accept cancel showBytecodes shiftedTextPaneMenuRequest).! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'BG 11/1/2003 14:29'! shiftedYellowButtonMenu "Answer the menu to be presented when the yellow button is pressed while the shift key is down" ^ SelectionMenu fromArray: #( ('set font... (k)' offerFontMenu) ('set style... (K)' changeStyle) ('set alignment...' chooseAlignment) - ('explain' explain) ('pretty print' prettyPrint) ('pretty print with color' prettyPrintWithColor) ('file it in (G)' fileItIn) ('recognizer (r)' recognizeCharacters) ('spawn (o)' spawn) " - ('definition of word' wordDefinition) ('verify spelling of word' verifyWordSpelling) ('spell check it' spellCheckIt) ('translate it' translateIt) ('choose language' languagePrefs) " - ('browse it (b)' browseIt) ('senders of it (n)' sendersOfIt) ('implementors of it (m)' implementorsOfIt) ('references to it (N)' referencesToIt) - ('selectors containing it (W)' methodNamesContainingIt) ('method strings with it (E)' methodStringsContainingit) ('method source with it' methodSourceContainingIt) ('class names containing it' classNamesContainingIt) ('class comments with it' classCommentsContainingIt) ('change sets with it' browseChangeSetsWithSelector) - ('save contents to file...' saveContentsInFile) - ('special menu...' presentSpecialMenu) ('more...' yellowButtonActivity))! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'tk 3/31/98 16:25'! yellowButtonMenu ^ TextEditorYellowButtonMenu! ! !ParagraphEditor class methodsFor: 'class initialization' stamp: 'di 4/17/1999 00:33'! yellowButtonMessages ^ TextEditorYellowButtonMenu selections! ! !ParagraphEditor class methodsFor: 'instance creation'! new "Answer a new instance of me with a null Paragraph to be edited." | aParagraphEditor | aParagraphEditor _ super new. aParagraphEditor initialize. aParagraphEditor changeParagraph: '' asParagraph. ^aParagraphEditor! ! !ParagraphEditor class methodsFor: 'instance creation'! newParagraph: aParagraph "Answer an instance of me with aParagraph as the text to be edited." | aParagraphEditor | aParagraphEditor _ super new. aParagraphEditor initialize. aParagraphEditor changeParagraph: aParagraph. ^aParagraphEditor! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sw 12/7/2001 22:54'! initializeCmdKeyShortcuts "Initialize the (unshifted) command-key (or alt-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "ParagraphEditor initialize" | cmdMap cmds | cmdMap := Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: 1 + 1 put: #cursorHome:. "home key" cmdMap at: 4 + 1 put: #cursorEnd:. "end key" cmdMap at: 8 + 1 put: #backspace:. "ctrl-H or delete key" cmdMap at: 11 + 1 put: #cursorPageUp:. "page up key" cmdMap at: 12 + 1 put: #cursorPageDown:. "page down key" cmdMap at: 13 + 1 put: #crWithIndent:. "cmd-Return" cmdMap at: 27 + 1 put: #offerMenuFromEsc:. "escape key" cmdMap at: 28 + 1 put: #cursorLeft:. "left arrow key" cmdMap at: 29 + 1 put: #cursorRight:. "right arrow key" cmdMap at: 30 + 1 put: #cursorUp:. "up arrow key" cmdMap at: 31 + 1 put: #cursorDown:. "down arrow key" cmdMap at: 32 + 1 put: #selectWord:. "space bar key" cmdMap at: 127 + 1 put: #forwardDelete:. "del key" '0123456789-=' do: [:char | cmdMap at: char asciiValue + 1 put: #changeEmphasis:]. '([{''"<' do: [:char | cmdMap at: char asciiValue + 1 put: #enclose:]. cmdMap at: $, asciiValue + 1 put: #shiftEnclose:. cmds := #($a #selectAll: $b #browseIt: $c #copySelection: $d #doIt: $e #exchange: $f #find: $g #findAgain: $h #setSearchString: $i #inspectIt: $j #doAgainOnce: $k #offerFontMenu: $l #cancel: $m #implementorsOfIt: $n #sendersOfIt: $o #spawnIt: $p #printIt: $q #querySymbol: $r #recognizer: $s #save: $t #tempCommand: $u #align: $v #paste: $w #backWord: $x #cut: $y #swapChars: $z #undo:). 1 to: cmds size by: 2 do: [:i | cmdMap at: (cmds at: i) asciiValue + 1 put: (cmds at: i + 1)]. CmdActions := cmdMap! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sw 12/9/2001 21:33'! initializeShiftCmdKeyShortcuts "Initialize the shift-command-key (or control-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "wod 11/3/1998: Fix setting of cmdMap for shifted keys to actually use the capitalized versions of the letters. TPR 2/18/99: add the plain ascii values back in for those VMs that don't return the shifted values." | cmdMap cmds | "shift-command and control shortcuts" cmdMap _ Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: ( 1 + 1) put: #cursorHome:. "home key" cmdMap at: ( 4 + 1) put: #cursorEnd:. "end key" cmdMap at: ( 8 + 1) put: #forwardDelete:. "ctrl-H or delete key" cmdMap at: (11 + 1) put: #cursorPageUp:. "page up key" cmdMap at: (12 + 1) put: #cursorPageDown:. "page down key" cmdMap at: (13 + 1) put: #crWithIndent:. "ctrl-Return" cmdMap at: (27 + 1) put: #offerMenuFromEsc:. "escape key" cmdMap at: (28 + 1) put: #cursorLeft:. "left arrow key" cmdMap at: (29 + 1) put: #cursorRight:. "right arrow key" cmdMap at: (30 + 1) put: #cursorUp:. "up arrow key" cmdMap at: (31 + 1) put: #cursorDown:. "down arrow key" cmdMap at: (32 + 1) put: #selectWord:. "space bar key" cmdMap at: (45 + 1) put: #changeEmphasis:. "cmd-sh-minus" cmdMap at: (61 + 1) put: #changeEmphasis:. "cmd-sh-plus" cmdMap at: (127 + 1) put: #forwardDelete:. "del key" "Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $(" '9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ]. "({< and double-quote" "Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command." "NB: sw 12/9/2001 commented out the idiosyncratic line just below, which was grabbing shift-esc in the text editor and hence which argued with the wish to have shift-esc be a universal gesture for escaping the local context and calling up the desktop menu." "cmdMap at: (27 + 1) put: #shiftEnclose:." "ctrl-[" "'""''(' do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose:]." cmds _ #( $a argAdvance: $b browseItHere: $c compareToClipboard: $d duplicate: $e methodStringsContainingIt: $f displayIfFalse: $g fileItIn: $h cursorTopHome: $i exploreIt: $j doAgainMany: $k changeStyle: $l outdent: $m selectCurrentTypeIn: $n referencesToIt: $p makeProjectLink: $r indent: $s search: $t displayIfTrue: $u changeLfToCr: $v pasteInitials: $w methodNamesContainingIt: $x makeLowercase: $y makeUppercase: $z makeCapitalized: ). 1 to: cmds size by: 2 do: [ :i | cmdMap at: ((cmds at: i) asciiValue + 1) put: (cmds at: i + 1). "plain keys" cmdMap at: ((cmds at: i) asciiValue - 32 + 1) put: (cmds at: i + 1). "shifted keys" cmdMap at: ((cmds at: i) asciiValue - 96 + 1) put: (cmds at: i + 1). "ctrl keys" ]. ShiftCmdActions _ cmdMap! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'sbw 10/8/1999 21:42'! specialShiftCmdKeys "Private - return array of key codes that represent single keys acting as if shift-command were also being pressed" ^#( 1 "home" 3 "enter" 4 "end" 8 "backspace" 11 "page up" 12 "page down" 27 "escape" 28 "left arrow" 29 "right arrow" 30 "up arrow" 31 "down arrow" 127 "delete" )! ! Object subclass: #ParseNode instanceVariableNames: 'comment pc' classVariableNames: 'Bfp BtpLong CodeBases CodeLimits DblExtDoAll Dup EndMethod EndRemote Jmp JmpLimit JmpLong LdFalse LdInstLong LdInstType LdLitIndType LdLitType LdMinus1 LdNil LdSelf LdSuper LdTempType LdThisContext LdTrue LoadLong LongLongDoAll NodeFalse NodeNil NodeSelf NodeSuper NodeThisContext NodeTrue Pop Send SendLimit SendLong SendLong2 SendPlus SendType ShortStoP StdLiterals StdSelectors StdVariables Store StorePop' poolDictionaries: '' category: 'System-Compiler'! !ParseNode commentStamp: '<historical>' prior: 0! 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.! !ParseNode methodsFor: 'testing'! assignmentCheck: encoder at: location "For messageNodes masquerading as variables for the debugger. For now we let this through - ie we allow stores ev into args. Should check against numArgs, though." ^ -1! ! !ParseNode methodsFor: 'testing'! canBeSpecialArgument "Can I be an argument of (e.g.) ifTrue:?" ^false! ! !ParseNode methodsFor: 'testing'! canCascade ^false! ! !ParseNode methodsFor: 'testing'! isComplex "Used for pretty printing to determine whether to start a new line" ^false! ! !ParseNode methodsFor: 'testing'! isConstantNumber "Overridden in LiteralNode" ^false! ! !ParseNode methodsFor: 'testing' stamp: 'di 4/5/2000 11:14'! isLiteral ^ false! ! !ParseNode methodsFor: 'testing'! isMessage: selSymbol receiver: rcvrPred arguments: argsPred "See comment in MessageNode." ^false! ! !ParseNode methodsFor: 'testing'! isReturnSelf ^false! ! !ParseNode methodsFor: 'testing'! isReturningIf ^false! ! !ParseNode methodsFor: 'testing' stamp: 'tk 8/2/1999 18:39'! isSelfPseudoVariable "Overridden in VariableNode." ^false! ! !ParseNode methodsFor: 'testing'! isSpecialConstant ^ false! ! !ParseNode methodsFor: 'testing' stamp: 'di 10/12/1999 15:28'! isTemp ^ false! ! !ParseNode methodsFor: 'testing'! isUndefTemp ^ false! ! !ParseNode methodsFor: 'testing'! isUnusedTemp ^ false! ! !ParseNode methodsFor: 'testing'! isVariableReference ^false! ! !ParseNode methodsFor: 'testing'! nowHasDef "Ignored in all but VariableNode"! ! !ParseNode methodsFor: 'testing'! nowHasRef "Ignored in all but VariableNode"! ! !ParseNode methodsFor: 'testing'! toDoIncrement: ignored "Only meant for Messages or Assignments - else return nil" ^ nil! ! !ParseNode methodsFor: 'code generation'! emitBranchOn: condition dist: dist pop: stack on: strm stack pop: 1. dist = 0 ifTrue: [^ strm nextPut: Pop]. condition ifTrue: [self emitLong: dist code: BtpLong on: strm] ifFalse: [self emitShortOrLong: dist code: Bfp on: strm]! ! !ParseNode methodsFor: 'code generation'! emitForEffect: stack on: strm self emitForValue: stack on: strm. strm nextPut: Pop. stack pop: 1! ! !ParseNode methodsFor: 'code generation'! emitForReturn: stack on: strm self emitForValue: stack on: strm. strm nextPut: EndMethod! ! !ParseNode methodsFor: 'code generation'! emitJump: dist on: strm dist = 0 ifFalse: [self emitShortOrLong: dist code: Jmp on: strm]! ! !ParseNode methodsFor: 'code generation'! emitLong: dist code: longCode on: aStream "Force a two-byte jump." | code distance | code _ longCode. distance _ dist. distance < 0 ifTrue: [distance _ distance + 1024. code _ code - 4] ifFalse: [distance > 1023 ifTrue: [distance _ -1]]. distance < 0 ifTrue: [self error: 'A block compiles more than 1K bytes of code'] ifFalse: [aStream nextPut: distance // 256 + code. aStream nextPut: distance \\ 256]! ! !ParseNode methodsFor: 'code generation'! emitShortOrLong: dist code: shortCode on: strm (1 <= dist and: [dist <= JmpLimit]) ifTrue: [strm nextPut: shortCode + dist - 1] ifFalse: [self emitLong: dist code: shortCode + (JmpLong-Jmp) on: strm]! ! !ParseNode methodsFor: 'code generation' stamp: 'hmm 7/15/2001 21:34'! pc "Used by encoder source mapping." pc==nil ifTrue: [^0] ifFalse: [^pc]! ! !ParseNode methodsFor: 'code generation'! sizeBranchOn: condition dist: dist dist = 0 ifTrue: [^1]. ^ condition ifTrue: [2] "Branch on true is always 2 bytes" ifFalse: [self sizeShortOrLong: dist]! ! !ParseNode methodsFor: 'code generation'! sizeForEffect: encoder ^(self sizeForValue: encoder) + 1! ! !ParseNode methodsFor: 'code generation'! sizeForReturn: encoder ^(self sizeForValue: encoder) + 1! ! !ParseNode methodsFor: 'code generation'! sizeJump: dist dist = 0 ifTrue: [^0]. ^self sizeShortOrLong: dist! ! !ParseNode methodsFor: 'code generation'! sizeShortOrLong: dist (1 <= dist and: [dist <= JmpLimit]) ifTrue: [^1]. ^2! ! !ParseNode methodsFor: 'encoding'! encodeSelector: selector ^nil! ! !ParseNode methodsFor: 'comment'! comment ^comment! ! !ParseNode methodsFor: 'comment'! comment: newComment comment _ newComment! ! !ParseNode methodsFor: 'converting'! asReturnNode ^ReturnNode new expr: self! ! !ParseNode methodsFor: 'printing' stamp: 'di 4/5/2000 15:11'! printCommentOn: aStream indent: indent | thisComment | comment == nil ifTrue: [^ self]. aStream withStyleFor: #comment do: [1 to: comment size do: [:index | index > 1 ifTrue: [aStream crtab: indent]. aStream nextPut: $". thisComment _ comment at: index. self printSingleComment: thisComment on: aStream indent: indent. aStream nextPut: $"]]. comment _ nil! ! !ParseNode methodsFor: 'printing' stamp: 'di 4/19/2000 11:58'! printOn: aStream "Refer to the comment in Object|printOn:." aStream nextPutAll: '{'. aStream nextPutAll: ((DialectStream dialect: #ST80 contents: [:strm | self printOn: strm indent: 0]) asString). aStream nextPutAll: '}'! ! !ParseNode methodsFor: 'printing'! printOn: aStream indent: anInteger "If control gets here, avoid recursion loop." super printOn: aStream! ! !ParseNode methodsFor: 'printing'! printOn: aStream indent: level precedence: p self printOn: aStream indent: level! ! !ParseNode methodsFor: 'private' stamp: 'sma 5/28/2000 10:47'! nextWordFrom: aStream setCharacter: aBlock | outStream char | outStream _ WriteStream on: (String new: 16). [(aStream peekFor: Character space) or: [aStream peekFor: Character tab]] whileTrue. [aStream atEnd or: [char _ aStream next. char = Character cr or: [char = Character space]]] whileFalse: [outStream nextPut: char]. aBlock value: char. ^ outStream contents! ! !ParseNode methodsFor: 'private' stamp: 'sma 5/28/2000 10:45'! printSingleComment: aString on: aStream indent: indent "Print the comment string, assuming it has been indented indent tabs. Break the string at word breaks, given the widths in the default font, at 450 points." | readStream word position lineBreak font wordWidth tabWidth spaceWidth lastChar | readStream _ ReadStream on: aString. font _ TextStyle default defaultFont. tabWidth _ TextConstants at: #DefaultTab. spaceWidth _ font widthOf: Character space. position _ indent * tabWidth. lineBreak _ 450. [readStream atEnd] whileFalse: [word _ self nextWordFrom: readStream setCharacter: [:lc | lastChar _ lc]. wordWidth _ word inject: 0 into: [:width :char | width + (font widthOf: char)]. position _ position + wordWidth. position > lineBreak ifTrue: [aStream crtab: indent. position _ indent * tabWidth + wordWidth + spaceWidth. lastChar = Character cr ifTrue: [[readStream peekFor: Character tab] whileTrue]. word isEmpty ifFalse: [aStream nextPutAll: word; space]] ifFalse: [aStream nextPutAll: word. readStream atEnd ifFalse: [position _ position + spaceWidth. aStream space]. lastChar = Character cr ifTrue: [aStream crtab: indent. position _ indent * tabWidth. [readStream peekFor: Character tab] whileTrue]]]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ParseNode class instanceVariableNames: ''! !ParseNode class methodsFor: 'class initialization'! initialize "ParseNode initialize. VariableNode initialize" LdInstType _ 1. LdTempType _ 2. LdLitType _ 3. LdLitIndType _ 4. SendType _ 5. CodeBases _ #(0 16 32 64 208 ). CodeLimits _ #(16 16 32 32 16 ). LdSelf _ 112. LdTrue _ 113. LdFalse _ 114. LdNil _ 115. LdMinus1 _ 116. LoadLong _ 128. Store _ 129. StorePop _ 130. ShortStoP _ 96. SendLong _ 131. DblExtDoAll _ 132. SendLong2 _ 134. LdSuper _ 133. Pop _ 135. Dup _ 136. LdThisContext _ 137. EndMethod _ 124. EndRemote _ 125. Jmp _ 144. Bfp _ 152. JmpLimit _ 8. JmpLong _ 164. "code for jmp 0" BtpLong _ 168. SendPlus _ 176. Send _ 208. SendLimit _ 16! ! Object subclass: #ParseStack instanceVariableNames: 'position length' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !ParseStack commentStamp: '<historical>' prior: 0! I keep track of the current and high position of the stack that will be needed by code being compiled.! !ParseStack methodsFor: 'initialize-release'! init length _ position _ 0! ! !ParseStack methodsFor: 'accessing'! pop: n (position _ position - n) < 0 ifTrue: [self error: 'Parse stack underflow']! ! !ParseStack methodsFor: 'accessing'! push: n (position _ position + n) > length ifTrue: [length _ position]! ! !ParseStack methodsFor: 'accessing'! size ^length! ! !ParseStack methodsFor: 'results'! position ^position! ! !ParseStack methodsFor: 'printing'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' at '; print: position; nextPutAll: ' of '; print: length! ! Scanner subclass: #Parser instanceVariableNames: 'here hereType hereMark hereEnd prevMark prevEnd encoder requestor parseNode failBlock requestorOffset tempsMark doitFlag' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !Parser commentStamp: '<historical>' prior: 0! I parse Smalltalk syntax and create a MethodNode that is the root of the parse tree. I look one token ahead.! !Parser methodsFor: 'public access'! encoder ^ encoder! ! !Parser methodsFor: 'public access' stamp: 'ajh 1/22/2003 16:51'! parse: sourceStreamOrString class: behavior ^ self parse: sourceStreamOrString readStream class: behavior noPattern: false context: nil notifying: nil ifFail: [self parseError]! ! !Parser methodsFor: 'public access' stamp: 'BG 11/27/2003 10:27'! parse: sourceStream class: class noPattern: noPattern context: ctxt notifying: req ifFail: aBlock "Answer a MethodNode for the argument, sourceStream, that is the root of a parse tree. Parsing is done with respect to the argument, class, to find instance, class, and pool variables; and with respect to the argument, ctxt, to find temporary variables. Errors in parsing are reported to the argument, req, if not nil; otherwise aBlock is evaluated. The argument noPattern is a Boolean that is true if the the sourceStream does not contain a method header (i.e., for DoIts)." | methNode repeatNeeded myStream parser s p | (req notNil and: [RequestAlternateSyntaxSetting signal and: [(sourceStream isKindOf: FileStream) not]]) ifTrue: [parser _ self as: DialectParser] ifFalse: [parser _ self]. myStream _ sourceStream. [repeatNeeded _ false. p _ myStream position. s _ myStream upToEnd. myStream position: p. parser init: myStream notifying: req failBlock: [^ aBlock value]. doitFlag _ noPattern. failBlock_ aBlock. [methNode _ parser method: noPattern context: ctxt encoder: (Encoder new init: class context: ctxt notifying: parser)] on: ParserRemovedUnusedTemps do: [ :ex | repeatNeeded _ true. myStream _ ReadStream on: requestor text string. ex resume]. repeatNeeded] whileTrue. encoder _ failBlock _ requestor _ parseNode _ nil. "break cycles & mitigate refct overflow" methNode sourceText: s. ^ methNode! ! !Parser methodsFor: 'public access' stamp: 'RAA 6/14/2000 13:50'! parseArgsAndTemps: aString notifying: req "Parse the argument, aString, notifying req if an error occurs. Otherwise, answer a two-element Array containing Arrays of strings (the argument names and temporary variable names)." (req notNil and: [RequestAlternateSyntaxSetting signal]) ifTrue: [^ (self as: DialectParser) parseArgsAndTemps: aString notifying: req]. aString == nil ifTrue: [^#()]. doitFlag _ false. "Don't really know if a doit or not!!" ^self initPattern: aString notifying: req return: [:pattern | (pattern at: 2) , self temporaries]! ! !Parser methodsFor: 'public access'! parseSelector: aString "Answer the message selector for the argument, aString, which should parse successfully up to the temporary declaration or the end of the method header." ^self initPattern: aString notifying: nil return: [:pattern | pattern at: 1]! ! !Parser methodsFor: 'expression types'! argumentName hereType == #word ifFalse: [^self expected: 'Argument name']. ^self advance! ! !Parser methodsFor: 'expression types' stamp: 'hmm 7/16/2001 18:47'! assignment: varNode " var '_' expression => AssignmentNode." | loc start | (loc _ varNode assignmentCheck: encoder at: prevMark + requestorOffset) >= 0 ifTrue: [^self notify: 'Cannot store into' at: loc]. start _ self startOfNextToken. varNode nowHasDef. self advance. self expression ifFalse: [^self expected: 'Expression']. parseNode _ AssignmentNode new variable: varNode value: parseNode from: encoder sourceRange: (start to: self endOfLastToken). ^true! ! !Parser methodsFor: 'expression types' stamp: 'hmm 7/17/2001 21:03'! blockExpression "[ ({:var} |) (| {temps} |) (statements) ] => BlockNode." | variableNodes temporaryBlockVariables start | variableNodes _ OrderedCollection new. start _ prevMark + requestorOffset. "Gather parameters." [self match: #colon] whileTrue: [variableNodes addLast: (encoder autoBind: self argumentName)]. (variableNodes size > 0 & (hereType ~~ #rightBracket) and: [(self match: #verticalBar) not]) ifTrue: [^self expected: 'Vertical bar']. temporaryBlockVariables _ self temporaryBlockVariables. self statements: variableNodes innerBlock: true. parseNode temporaries: temporaryBlockVariables. (self match: #rightBracket) ifFalse: [^self expected: 'Period or right bracket']. encoder noteSourceRange: (self endOfLastToken to: self endOfLastToken) forNode: parseNode. "The scope of the parameters and temporary block variables is no longer active." temporaryBlockVariables do: [:variable | variable scope: -1]. variableNodes do: [:variable | variable scope: -1]! ! !Parser methodsFor: 'expression types' stamp: 'di 3/8/2000 09:36'! braceExpression " { elements } => BraceNode." | elements locations loc more | elements _ OrderedCollection new. locations _ OrderedCollection new. self advance. more _ hereType ~~ #rightBrace. [more] whileTrue: [loc _ hereMark + requestorOffset. self expression ifTrue: [elements addLast: parseNode. locations addLast: loc] ifFalse: [^self expected: 'Variable or expression']. (self match: #period) ifTrue: [more _ hereType ~~ #rightBrace] ifFalse: [more _ false]]. parseNode _ BraceNode new elements: elements sourceLocations: locations. (self match: #rightBrace) ifFalse: [^self expected: 'Period or right brace']. ^true! ! !Parser methodsFor: 'expression types'! cascade " {; message} => CascadeNode." | rcvr msgs | parseNode canCascade ifFalse: [^self expected: 'Cascading not']. rcvr _ parseNode cascadeReceiver. msgs _ OrderedCollection with: parseNode. [self match: #semicolon] whileTrue: [parseNode _ rcvr. (self messagePart: 3 repeat: false) ifFalse: [^self expected: 'Cascade']. parseNode canCascade ifFalse: [^self expected: '<- No special messages']. parseNode cascadeReceiver. msgs addLast: parseNode]. parseNode _ CascadeNode new receiver: rcvr messages: msgs! ! !Parser methodsFor: 'expression types' stamp: 'di 11/19/1999 07:43'! expression (hereType == #word and: [tokenType == #leftArrow]) ifTrue: [^ self assignment: self variable]. hereType == #leftBrace ifTrue: [self braceExpression] ifFalse: [self primaryExpression ifFalse: [^ false]]. (self messagePart: 3 repeat: true) ifTrue: [hereType == #semicolon ifTrue: [self cascade]]. ^ true! ! !Parser methodsFor: 'expression types'! messagePart: level repeat: repeat | start receiver selector args precedence words keywordStart | [receiver _ parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start _ self startOfNextToken. selector _ WriteStream on: (String new: 32). args _ OrderedCollection new. words _ OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart _ self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. (Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence _ 3] ifFalse: [((hereType == #binary or: [hereType == #verticalBar]) and: [level >= 2]) ifTrue: [start _ self startOfNextToken. selector _ self advance asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args _ Array with: parseNode. precedence _ 2] ifFalse: [hereType == #word ifTrue: [start _ self startOfNextToken. selector _ self advance. args _ #(). words _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). (Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence _ 1] ifFalse: [^args notNil]]]. parseNode _ MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! ! !Parser methodsFor: 'expression types' stamp: 'di 5/30/2000 22:06'! method: doit context: ctxt encoder: encoderToUse " pattern [ | temporaries ] block => MethodNode." | sap blk prim temps messageComment methodNode | encoder _ encoderToUse. sap _ self pattern: doit inContext: ctxt. "sap={selector, arguments, precedence}" (sap at: 2) do: [:argNode | argNode isArg: true]. temps _ self temporaries. messageComment _ currentComment. currentComment _ nil. prim _ doit ifTrue: [0] ifFalse: [self primitive]. self statements: #() innerBlock: doit. blk _ parseNode. doit ifTrue: [blk returnLast] ifFalse: [blk returnSelfIfNoOther]. hereType == #doIt ifFalse: [^self expected: 'Nothing more']. self interactive ifTrue: [self removeUnusedTemps]. methodNode _ self newMethodNode comment: messageComment. ^ methodNode selector: (sap at: 1) arguments: (sap at: 2) precedence: (sap at: 3) temporaries: temps block: blk encoder: encoder primitive: prim! ! !Parser methodsFor: 'expression types' stamp: 'di 5/30/2000 21:59'! newMethodNode ^ MethodNode new! ! !Parser methodsFor: 'expression types' stamp: 'di 4/5/2000 16:52'! pattern: fromDoit inContext: ctxt " unarySelector | binarySelector arg | keyword arg {keyword arg} => {selector, arguments, precedence}." | args selector | doitFlag _ fromDoit. fromDoit ifTrue: [ctxt == nil ifTrue: [^ {#DoIt. {}. 1}] ifFalse: [^ {#DoItIn:. {encoder encodeVariable: 'homeContext'}. 3}]]. hereType == #word ifTrue: [^ {self advance asSymbol. {}. 1}]. (hereType == #binary or: [hereType == #verticalBar]) ifTrue: [selector _ self advance asSymbol. args _ Array with: (encoder bindArg: self argumentName). ^ {selector. args. 2}]. hereType == #keyword ifTrue: [selector _ WriteStream on: (String new: 32). args _ OrderedCollection new. [hereType == #keyword] whileTrue: [selector nextPutAll: self advance. args addLast: (encoder bindArg: self argumentName)]. ^ {selector contents asSymbol. args. 3}]. ^ self expected: 'Message pattern'! ! !Parser methodsFor: 'expression types'! primaryExpression hereType == #word ifTrue: [parseNode _ self variable. (parseNode isUndefTemp and: [self interactive]) ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal]]) ifTrue: [parseNode _ encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number]) ifTrue: [self advance. parseNode _ encoder encodeLiteral: self advance negated. ^true]. ^false! ! !Parser methodsFor: 'expression types' stamp: 'di 6/7/2000 08:45'! statements: argNodes innerBlock: inner | stmts returns start more blockComment | stmts _ OrderedCollection new. "give initial comment to block, since others trail statements" blockComment _ currentComment. currentComment _ nil. returns _ false. more _ hereType ~~ #rightBracket. [more] whileTrue: [start _ self startOfNextToken. (returns _ self matchReturn) ifTrue: [self expression ifFalse: [^self expected: 'Expression to return']. self addComment. stmts addLast: (parseNode isReturningIf ifTrue: [parseNode] ifFalse: [ReturnNode new expr: parseNode encoder: encoder sourceRange: (start to: self endOfLastToken)])] ifFalse: [self expression ifTrue: [self addComment. stmts addLast: parseNode] ifFalse: [self addComment. stmts size = 0 ifTrue: [stmts addLast: (encoder encodeVariable: (inner ifTrue: ['nil'] ifFalse: ['self']))]]]. returns ifTrue: [self match: #period. (hereType == #rightBracket or: [hereType == #doIt]) ifFalse: [^self expected: 'End of block']]. more _ returns not and: [self match: #period]]. parseNode _ BlockNode new arguments: argNodes statements: stmts returns: returns from: encoder. parseNode comment: blockComment. ^ true! ! !Parser methodsFor: 'expression types' stamp: 'sw 9/6/2001 15:30'! temporaries " [ '|' (variable)* '|' ]" | vars theActualText | (self match: #verticalBar) ifFalse: ["no temps" doitFlag ifTrue: [requestor ifNil: [tempsMark _ 1] ifNotNil: [tempsMark _ requestor selectionInterval first]. ^ #()]. tempsMark _ (prevEnd ifNil: [0]) + 1. tempsMark _ hereMark "formerly --> prevMark + prevToken". tempsMark > 0 ifTrue: [theActualText _ source contents. [tempsMark < theActualText size and: [(theActualText at: tempsMark) isSeparator]] whileTrue: [tempsMark _ tempsMark + 1]]. ^ #()]. vars _ OrderedCollection new. [hereType == #word] whileTrue: [vars addLast: (encoder bindTemp: self advance)]. (self match: #verticalBar) ifTrue: [tempsMark _ prevMark. ^ vars]. ^ self expected: 'Vertical bar'! ! !Parser methodsFor: 'expression types' stamp: 'crl 2/26/1999 12:22'! temporaryBlockVariables "Scan and answer temporary block variables." | variables | (self match: #verticalBar) ifFalse: [ "There are't any temporary variables." ^#()]. variables _ OrderedCollection new. [hereType == #word] whileTrue: [variables addLast: (encoder bindBlockTemp: self advance)]. (self match: #verticalBar) ifTrue: [^variables]. ^self expected: 'Vertical bar'! ! !Parser methodsFor: 'expression types' stamp: 'di 12/4/1999 21:04'! variable | varName varStart varEnd | varStart _ self startOfNextToken + requestorOffset. varName _ self advance. varEnd _ self endOfLastToken + requestorOffset. ^ encoder encodeVariable: varName sourceRange: (varStart to: varEnd) ifUnknown: [self correctVariable: varName interval: (varStart to: varEnd)]! ! !Parser methodsFor: 'scanning' stamp: 'hmm 7/16/2001 20:12'! advance | this | prevMark _ hereMark. prevEnd _ hereEnd. this _ here. here _ token. hereType _ tokenType. hereMark _ mark. hereEnd _ source position - (source atEnd ifTrue: [hereChar == 30 asCharacter ifTrue: [0] ifFalse: [1]] ifFalse: [2]). self scanToken. "Transcript show: 'here: ', here printString, ' mark: ', hereMark printString, ' end: ', hereEnd printString; cr." ^this! ! !Parser methodsFor: 'scanning' stamp: 'hmm 7/16/2001 19:23'! endOfLastToken ^ prevEnd ifNil: [mark]! ! !Parser methodsFor: 'scanning'! match: type "Answer with true if next tokens type matches." hereType == type ifTrue: [self advance. ^true]. ^false! ! !Parser methodsFor: 'scanning' stamp: 'di 6/7/2000 08:44'! matchReturn ^ self match: #upArrow! ! !Parser methodsFor: 'scanning'! matchToken: thing "Matches the token, not its type." here = thing ifTrue: [self advance. ^true]. ^false! ! !Parser methodsFor: 'scanning'! startOfNextToken "Return starting position in source of next token." hereType == #doIt ifTrue: [^source position + 1]. ^hereMark! ! !Parser methodsFor: 'temps'! bindArg: name ^ self bindTemp: name! ! !Parser methodsFor: 'temps'! bindTemp: name ^name! ! !Parser methodsFor: 'error handling' stamp: 'hmm 7/18/2001 21:45'! expected: aString "Notify a problem at token 'here'." tokenType == #doIt ifTrue: [hereMark _ hereMark + 1]. hereType == #doIt ifTrue: [hereMark _ hereMark + 1]. ^ self notify: aString , ' expected' at: hereMark + requestorOffset! ! !Parser methodsFor: 'error handling'! fail | exitBlock | encoder == nil ifFalse: [encoder release. encoder _ nil]. "break cycle" exitBlock _ failBlock. failBlock _ nil. ^exitBlock value! ! !Parser methodsFor: 'error handling'! interactive ^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not! ! !Parser methodsFor: 'error handling'! notify: aString "Notify problem at token before 'here'." ^self notify: aString at: prevMark + requestorOffset! ! !Parser methodsFor: 'error handling' stamp: 'LC 1/6/2002 14:30'! notify: string at: location requestor isNil ifTrue: [(encoder == self or: [encoder isNil]) ifTrue: [^ self fail "failure setting up syntax error"]. SyntaxErrorNotification inClass: encoder classEncoding withCode: (source contents copyReplaceFrom: location to: location - 1 with: string , ' ->') doitFlag: doitFlag] ifFalse: [requestor notify: string , ' ->' at: location in: source]. ^self fail! ! !Parser methodsFor: 'error handling' stamp: 'di 2/9/1999 15:43'! offEnd: aString "Notify a problem beyond 'here' (in lookAhead token). Don't be offEnded!!" requestorOffset == nil ifTrue: [^ self notify: aString at: mark] ifFalse: [^ self notify: aString at: mark + requestorOffset] ! ! !Parser methodsFor: 'error correction' stamp: 'di 12/1/2000 14:39'! correctSelector: proposedKeyword wordIntervals: spots exprInterval: expInt ifAbort: abortAction "Correct the proposedKeyword to some selector symbol, correcting the original text if such action is indicated. abortAction is invoked if 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." | alternatives aStream choice correctSelector userSelection lines firstLine | "If we can't ask the user, assume that the keyword will be defined later" self interactive ifFalse: [ ^ proposedKeyword asSymbol ]. userSelection _ requestor selectionInterval. requestor selectFrom: spots first first to: spots last last. requestor select. alternatives _ Symbol possibleSelectorsFor: proposedKeyword. aStream _ WriteStream on: (String new: 200). aStream nextPutAll: (proposedKeyword contractTo: 35); cr. firstLine _ 1. alternatives do: [:sel | aStream nextPutAll: (sel contractTo: 35); nextPut: Character cr]. aStream nextPutAll: 'cancel'. lines _ Array with: firstLine with: (alternatives size + firstLine). choice _ (PopUpMenu labels: aStream contents lines: lines) startUpWithCaption: 'Unknown selector, please confirm, correct, or cancel'. (choice = 0) | (choice > (lines at: 2)) ifTrue: [ ^ abortAction value ]. requestor deselect. requestor selectInvisiblyFrom: userSelection first to: userSelection last. choice = 1 ifTrue: [ ^ proposedKeyword asSymbol ]. correctSelector _ alternatives at: choice - 1. self substituteSelector: correctSelector keywords wordIntervals: spots. ((proposedKeyword last ~~ $:) and: [correctSelector last == $:]) ifTrue: [ ^ abortAction value]. ^ correctSelector. ! ! !Parser methodsFor: 'error correction' stamp: 'md 3/13/2004 17:12'! correctVariable: proposedVariable interval: spot "Correct the proposedVariable to a known variable, or declare it as a new variable if such action is requested. We support declaring lowercase variables as temps or inst-vars, and uppercase variables as Globals or ClassVars, depending on whether the context is nil (class=UndefinedObject). Spot is the interval within the test stream of the variable. rr 3/4/2004 10:26 : adds the option to define a new class. " | tempIvar labels actions lines alternatives binding userSelection choice action | "Check if this is an i-var, that has been corrected already (ugly)" (encoder classEncoding instVarNames includes: proposedVariable) ifTrue: [ ^LiteralVariableNode new name: proposedVariable index: (encoder classEncoding instVarNames indexOf: proposedVariable) - 1 type: 1; yourself ]. "If we can't ask the user for correction, make it undeclared" self interactive ifFalse: [ ^encoder undeclared: proposedVariable ]. "First check to see if the requestor knows anything about the variable" tempIvar _ proposedVariable first isLowercase. (tempIvar and: [ (binding _ requestor bindingOf: proposedVariable) notNil ]) ifTrue: [ ^encoder global: binding name: proposedVariable ]. userSelection _ requestor selectionInterval. requestor selectFrom: spot first to: spot last. requestor select. "Build the menu with alternatives" labels _ OrderedCollection new. actions _ OrderedCollection new. lines _ OrderedCollection new. alternatives _ encoder possibleVariablesFor: proposedVariable. tempIvar ifTrue: [ labels add: 'declare temp'. actions add: [ self declareTempAndPaste: proposedVariable ]. labels add: 'declare instance'. actions add: [ self declareInstVar: proposedVariable ] ] ifFalse: [ labels add: 'define new class'. actions add: [self defineClass: proposedVariable]. labels add: 'declare global'. actions add: [ self declareGlobal: proposedVariable ]. encoder classEncoding == UndefinedObject ifFalse: [ labels add: 'declare class variable'. actions add: [ self declareClassVar: proposedVariable ] ] ]. lines add: labels size. alternatives do: [ :each | labels add: each. actions add: [ self substituteWord: each wordInterval: spot offset: 0. encoder encodeVariable: each ] fixTemps ]. lines add: labels size. labels add: 'cancel'. "Display the pop-up menu" choice _ (PopUpMenu labelArray: labels asArray lines: lines asArray) startUpWithCaption: 'Unknown variable: ', proposedVariable, ' please correct, or cancel:'. action _ actions at: choice ifAbsent: [ ^self fail ]. "Execute the selected action" requestor deselect. requestor selectInvisiblyFrom: userSelection first to: userSelection last. ^action value! ! !Parser methodsFor: 'error correction'! declareClassVar: name | sym class | sym _ name asSymbol. class _ encoder classEncoding. class _ class theNonMetaClass. "not the metaclass" class addClassVarName: name. ^ encoder global: (class classPool associationAt: sym) name: sym! ! !Parser methodsFor: 'error correction'! declareGlobal: name | sym | sym _ name asSymbol. Smalltalk at: sym put: nil. ^ encoder global: (Smalltalk associationAt: sym) name: sym! ! !Parser methodsFor: 'error correction' stamp: 'rr 3/6/2004 16:07'! declareInstVar: name " rr 3/6/2004 16:06 : adds the line to correctly compute the index. uncommented the option in the caller." | index | encoder classEncoding addInstVarName: name. index _ encoder classEncoding instVarNames indexOf: name. encoder classEncoding allSuperclassesDo: [:cls | index := index + cls instVarNames size]. ^LiteralVariableNode new name: name index: index - 1 type: 1; yourself ! ! !Parser methodsFor: 'error correction' stamp: 'RAA 6/5/2001 11:57'! declareTempAndPaste: name | insertion delta theTextString characterBeforeMark | theTextString _ requestor text string. characterBeforeMark _ theTextString at: tempsMark-1 ifAbsent: [$ ]. (theTextString at: tempsMark) = $| ifTrue: [ "Paste it before the second vertical bar" insertion _ name, ' '. characterBeforeMark isSeparator ifFalse: [ insertion _ ' ', insertion]. delta _ 0. ] ifFalse: [ "No bars - insert some with CR, tab" insertion _ '| ' , name , ' |',String cr. delta _ 2. "the bar and CR" characterBeforeMark = Character tab ifTrue: [ insertion _ insertion , String tab. delta _ delta + 1. "the tab" ]. ]. tempsMark _ tempsMark + (self substituteWord: insertion wordInterval: (tempsMark to: tempsMark-1) offset: 0) - delta. ^ encoder bindAndJuggle: name! ! !Parser methodsFor: 'error correction' stamp: 'rr 3/4/2004 10:57'! defineClass: className "prompts the user to define a new class, asks for it's category, and lets the users edit further the definition" | sym cat def d2 | sym := className asSymbol. cat := FillInTheBlank request: 'Enter class category : ' initialAnswer: 'Unknown'. cat ifEmpty: [cat := 'Unknown']. def := 'Object subclass: #', sym, ' instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: ''' , cat, ''''. d2 := FillInTheBlank request: 'Edit class definition : ' initialAnswer: def. d2 ifEmpty: [d2 := def]. Compiler evaluate: d2. ^ encoder global: (Smalltalk associationAt: sym) name: sym! ! !Parser methodsFor: 'error correction'! queryUndefined | varStart varName | varName _ parseNode key. varStart _ self endOfLastToken + requestorOffset - varName size + 1. requestor selectFrom: varStart to: varStart + varName size - 1; select. ((PopUpMenu labels: 'yes no') startUpWithCaption: ((varName , ' appears to be undefined at this point. Proceed anyway?') asText makeBoldFrom: 1 to: varName size)) = 1 ifFalse: [^ self fail]! ! !Parser methodsFor: 'error correction' stamp: 'sw 5/23/2001 13:55'! removeUnusedTemps "Scan for unused temp names, and prompt the user about the prospect of removing each one found" | str end start madeChanges | madeChanges _ false. str _ requestor text string. ((tempsMark between: 1 and: str size) and: [(str at: tempsMark) = $|]) ifFalse: [^ self]. encoder unusedTempNames do: [:temp | ((PopUpMenu labels: 'yes\no' withCRs) startUpWithCaption: ((temp , ' appears to be unused in this method. OK to remove it?') asText makeBoldFrom: 1 to: temp size)) = 1 ifTrue: [(encoder encodeVariable: temp) isUndefTemp ifTrue: [end _ tempsMark. ["Beginning at right temp marker..." start _ end - temp size + 1. end < temp size or: [temp = (str copyFrom: start to: end) and: [(str at: start-1) isSeparator & (str at: end+1) isSeparator]]] whileFalse: ["Search left for the unused temp" end _ requestor nextTokenFrom: end direction: -1]. end < temp size ifFalse: [(str at: start-1) = $ ifTrue: [start _ start-1]. requestor correctFrom: start to: end with: ''. str _ str copyReplaceFrom: start to: end with: ''. madeChanges _ true. tempsMark _ tempsMark - (end-start+1)]] ifFalse: [self inform: 'You''ll first have to remove the statement where it''s stored into']]]. madeChanges ifTrue: [ParserRemovedUnusedTemps signal]! ! !Parser methodsFor: 'error correction'! substituteSelector: selectorParts wordIntervals: spots "Substitute the correctSelector into the (presuamed interactive) receiver." | offset | offset _ 0. selectorParts with: spots do: [ :word :interval | offset _ self substituteWord: word wordInterval: interval offset: offset ] ! ! !Parser methodsFor: 'error correction'! substituteWord: correctWord wordInterval: spot offset: o "Substitute the correctSelector into the (presuamed interactive) receiver." requestor correctFrom: (spot first + o) to: (spot last + o) with: correctWord. requestorOffset _ requestorOffset + correctWord size - spot size. ^ o + correctWord size - spot size! ! !Parser methodsFor: 'private'! addComment parseNode ~~ nil ifTrue: [parseNode comment: currentComment. currentComment _ nil]! ! !Parser methodsFor: 'private'! init: sourceStream notifying: req failBlock: aBlock requestor _ req. failBlock _ aBlock. super scan: sourceStream. prevMark _ hereMark _ mark. requestorOffset _ 0. self advance! ! !Parser methodsFor: 'private'! initPattern: aString notifying: req return: aBlock | result | self init: (ReadStream on: aString asString) notifying: req failBlock: [^nil]. encoder _ self. result _ aBlock value: (self pattern: false inContext: nil). encoder _ failBlock _ nil. "break cycles" ^result! ! !Parser methodsFor: 'primitives'! allocateLiteral: lit encoder litIndex: lit! ! !Parser methodsFor: 'primitives' stamp: 'md 11/14/2003 16:53'! externalFunctionDeclaration "Parse the function declaration for a call to an external library." | descriptorClass callType retType externalName args argType module fn | descriptorClass _ Smalltalk at: #ExternalFunction ifAbsent:[nil]. descriptorClass == nil ifTrue:[^0]. callType _ descriptorClass callingConventionFor: here. callType == nil ifTrue:[^0]. "Parse return type" self advance. retType _ self externalType: descriptorClass. retType == nil ifTrue:[^self expected:'return type']. "Parse function name or index" externalName _ here. (self match: #string) ifTrue:[externalName _ externalName asSymbol] ifFalse:[(self match:#number) ifFalse:[^self expected:'function name or index']]. (self matchToken:'(' asSymbol) ifFalse:[^self expected:'argument list']. args _ WriteStream on: Array new. [here == #')'] whileFalse:[ argType _ self externalType: descriptorClass. argType == nil ifTrue:[^self expected:'argument']. argType isVoid & argType isPointerType not ifFalse:[args nextPut: argType]. ]. (self matchToken:')' asSymbol) ifFalse:[^self expected:')']. (self matchToken: 'module:') ifTrue:[ module _ here. (self match: #string) ifFalse:[^self expected: 'String']. module _ module asSymbol]. Smalltalk at: #ExternalLibraryFunction ifPresent:[:xfn| fn _ xfn name: externalName module: module callType: callType returnType: retType argumentTypes: args contents. self allocateLiteral: fn. ]. ^120! ! !Parser methodsFor: 'primitives' stamp: 'ar 12/2/1999 16:49'! externalType: descriptorClass "Parse an return an external type" | xType | xType _ descriptorClass atomicTypeNamed: here. xType == nil ifTrue:["Look up from class scope" Symbol hasInterned: here ifTrue:[:sym| xType _ descriptorClass structTypeNamed: sym]]. xType == nil ifTrue:[ "Raise an error if user is there" self interactive ifTrue:[^nil]. "otherwise go over it silently" xType _ descriptorClass forceTypeNamed: here]. self advance. (self matchToken:#*) ifTrue:[^xType asPointerType] ifFalse:[^xType]! ! !Parser methodsFor: 'primitives'! primitive | n | (self matchToken: #<) ifFalse: [^ 0]. n _ self primitiveDeclarations. (self matchToken: #>) ifFalse: [^ self expected: '>']. ^ n! ! !Parser methodsFor: 'primitives' stamp: 'ar 11/16/1999 22:01'! primitiveDeclarations | prim module | (self matchToken: 'primitive:') ifFalse:[^self externalFunctionDeclaration]. prim _ here. (self match: #number) ifTrue:[^prim]. "Indexed primitives" (self match: #string) ifFalse:[^self expected:'Integer or String']. (self matchToken: 'module:') ifTrue:[ module _ here. (self match: #string) ifFalse:[^self expected: 'String']. module _ module asSymbol]. (self allocateLiteral: (Array with: module with: prim asSymbol with: 0 with: 0)). ^117! ! Notification subclass: #ParserRemovedUnusedTemps instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! DisplayObject subclass: #Path instanceVariableNames: 'form collectionOfPoints' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Path commentStamp: '<historical>' prior: 0! 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.! !Path methodsFor: 'accessing'! at: index "Answer the point on the receiver's path at position index." ^collectionOfPoints at: index! ! !Path methodsFor: 'accessing'! at: index put: aPoint "Store the argument, aPoint, as the point on the receiver's path at position index." ^collectionOfPoints at: index put: aPoint! ! !Path methodsFor: 'accessing'! first "Answer the first point on the receiver's path; included to correspond to OrderedCollection protocol." ^collectionOfPoints first! ! !Path methodsFor: 'accessing'! firstPoint "Answer the first point on the receiver's path." ^collectionOfPoints first! ! !Path methodsFor: 'accessing'! firstPoint: aPoint "Replace the first element of the receiver with the new value aPoint. Answer the argument aPoint." collectionOfPoints at: 1 put: aPoint. ^aPoint! ! !Path methodsFor: 'accessing'! form "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black form (a black dot)." | aForm | form == nil ifTrue: [aForm _ Form extent: 1 @ 1. aForm fillBlack. ^aForm] ifFalse: [^form]! ! !Path methodsFor: 'accessing'! form: aForm "Make the argument, aForm, be the receiver's form." form _ aForm! ! !Path methodsFor: 'accessing'! last "Answer the last point on the receiver's path; included to correspond to OrderedCollection protocol." ^collectionOfPoints last! ! !Path methodsFor: 'accessing'! offset "There are basically two kinds of display objects in the system: those that, when asked to transform themselves, create a new object; and those that side effect themselves by maintaining a record of the transformation request (typically an offset). Path, like Rectangle and Point, is a display object of the first kind." self shouldNotImplement! ! !Path methodsFor: 'accessing'! secondPoint "Answer the second element of the receiver." ^collectionOfPoints at: 2! ! !Path methodsFor: 'accessing'! secondPoint: aPoint "Replace the second element of the receiver with the new value aPoint. Answer the argument aPoint." collectionOfPoints at: 2 put: aPoint. ^aPoint! ! !Path methodsFor: 'accessing'! size "Answer the length of the receiver." ^collectionOfPoints size! ! !Path methodsFor: 'accessing'! thirdPoint "Answer the third element of the receiver." ^collectionOfPoints at: 3! ! !Path methodsFor: 'accessing'! thirdPoint: aPoint "Replace the third element of the receiver with the new value aPoint. Answer the argument aPoint." collectionOfPoints at: 3 put: aPoint. ^aPoint! ! !Path methodsFor: 'testing'! isEmpty ^collectionOfPoints isEmpty! ! !Path methodsFor: 'displaying'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "Display this Path--offset by aPoint, clipped by clipRect and the form associated with this Path will be displayedr according to one of the sixteen functions of two logical variables (rule). Also the source form will be first anded with aForm as a mask. Does not effect the state of the Path" collectionOfPoints do: [:element | self form displayOn: aDisplayMedium at: element + aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm]! ! !Path methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm "Displays this path, translated and scaled by aTransformation. Get the scaled and translated Path." | newPath transformedPath | transformedPath _ displayTransformation applyTo: self. newPath _ Path new. transformedPath do: [:point | newPath add: point]. newPath form: self form. newPath displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRectangle rule: ruleInteger fillColor: aForm! ! !Path methodsFor: 'display box access'! computeBoundingBox "Refer to the comment in DisplayObject|computeBoundingBox." | box | box _ Rectangle origin: (self at: 1) extent: 0 @ 0. collectionOfPoints do: [:aPoint | box _ box merge: (Rectangle origin: aPoint extent: 0 @ 0)]. ^box! ! !Path methodsFor: 'transforming' stamp: 'jrm 9/1/1999 21:26'! scaleBy: aPoint "Answers a new Path scaled by aPoint. Does not affect the current data in this Path." | newPath | newPath _ self species new: self size. newPath form: self form. collectionOfPoints do: [:element | newPath add: (element scaleBy: aPoint)]. ^newPath! ! !Path methodsFor: 'transforming' stamp: 'jrm 9/1/1999 21:28'! translateBy: aPoint "Answers a new Path whose elements are translated by aPoint. Does not affect the elements of this Path." | newPath | newPath _ self species new: self size. newPath form: self form. collectionOfPoints do: [:element | newPath add: (element translateBy: aPoint)]. ^newPath! ! !Path methodsFor: 'adding'! add: aPoint "Include aPoint as one of the receiver's elements." collectionOfPoints add: aPoint! ! !Path methodsFor: 'removing' stamp: 'di 4/4/2000 12:33'! removeAllSuchThat: aBlock "Evaluate aBlock for each element of the receiver. Remove each element for which aBlock evaluates to true." collectionOfPoints removeAllSuchThat: aBlock. ! ! !Path methodsFor: 'enumerating'! collect: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect the resulting values into a path that is like the receiver. Answer the new path." | newCollection | newCollection _ collectionOfPoints collect: aBlock. newCollection form: self form. ^newCollection! ! !Path methodsFor: 'enumerating'! select: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect into a new path like the receiver only those elements for which aBlock evaluates to true. Answer the new path." | newCollection | newCollection _ collectionOfPoints select: aBlock. newCollection form: self form. ^newCollection! ! !Path methodsFor: 'private'! initializeCollectionOfPoints collectionOfPoints _ OrderedCollection new! ! !Path methodsFor: 'private'! initializeCollectionOfPoints: anInteger collectionOfPoints _ OrderedCollection new: anInteger! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Path class instanceVariableNames: ''! !Path class methodsFor: 'instance creation'! new ^self basicNew initializeCollectionOfPoints! ! !Path class methodsFor: 'instance creation'! new: anInteger ^self basicNew initializeCollectionOfPoints: anInteger! ! !Path class methodsFor: 'examples'! example "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. " | aPath aForm pl fl flag | aForm _ Form extent: 2 @ 40. "creates a form one inch long" aForm fillBlack. "turns it black" aPath _ Path new. aPath form: aForm. "use the long black form for displaying" flag _ true. [flag] whileTrue: [Sensor waitButton. Sensor redButtonPressed ifTrue: [aPath add: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: aPath last] ifFalse: [flag _ false]]. Display fillWhite. aPath displayOn: Display. "the original path" pl _ aPath translateBy: 0 @ 100. fl _ Form extent: 40 @ 40. fl fillGray. pl form: fl. pl displayOn: Display. "the translated path" Sensor waitNoButton "Path example"! ! BitBlt subclass: #Pen instanceVariableNames: 'location direction penDown' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Pen commentStamp: '<historical>' prior: 0! My instances can scribble on the screen or some other Form, drawing and printing at any angle. Since I am a BitBlt, the drawing can be done with an arbitary source Form. ! !Pen methodsFor: 'initialize-release' stamp: 'jm 4/28/1998 04:02'! defaultNib: widthInteger "Nib is the tip of a pen. This sets up the pen, with a nib of width widthInteger. You can also set the shape of the pen nib using: roundNib: widthInteger, or squareNib: widthInteger, or sourceForm: aForm" "Example: | bic | bic _ Pen new sourceForm: Cursor normal. bic combinationRule: Form paint; turn: 90. 10 timesRepeat: [bic down; go: 3; up; go: 10]." self color: Color black. self squareNib: widthInteger. ! ! !Pen methodsFor: 'initialize-release' stamp: 'jm 4/28/1998 04:03'! roundNib: diameter "Makes this pen draw with a round dot of the given diameter." self sourceForm: (Form dotOfSize: diameter). combinationRule _ Form paint. ! ! !Pen methodsFor: 'initialize-release' stamp: 'jm 4/28/1998 04:03'! squareNib: widthInteger "Makes this pen draw with a square nib of the given width." self sourceForm: (Form extent: widthInteger @widthInteger) fillBlack. self combinationRule: Form over. "a bit faster than paint mode" ! ! !Pen methodsFor: 'accessing' stamp: 'ssa 2/25/2008 19:58'! destForm: aForm destForm := aForm! ! !Pen methodsFor: 'accessing'! direction "Answer the receiver's current direction. 0 is towards the top of the screen." ^direction! ! !Pen methodsFor: 'accessing'! location "Answer where the receiver is currently located." ^location! ! !Pen methodsFor: 'operations' stamp: 'jm 4/28/1998 03:40'! color: aColorOrInteger "Set the pen to the given color or to a color chosen from a fixed set of colors." | count c | aColorOrInteger isInteger ifTrue: [ destForm depth = 1 ifTrue: [^ self fillColor: Color black]. count _ 19. "number of colors in color wheel" c _ (Color red wheel: count) at: ((aColorOrInteger * 7) \\ count) + 1] ifFalse: [c _ aColorOrInteger]. "assume aColorOrInteger is a Color" self fillColor: c. ! ! !Pen methodsFor: 'operations'! down "Set the state of the receiver's pen to down (drawing)." penDown _ true! ! !Pen methodsFor: 'operations'! go: distance "Move the pen in its current direction a number of bits equal to the argument, distance. If the pen is down, a line will be drawn using the receiver's form source as the shape of the drawing brush." self goto: (direction degreeCos @ direction degreeSin) * distance + location! ! !Pen methodsFor: 'operations' stamp: 'di 11/4/97 20:11'! goto: aPoint "Move the receiver to position aPoint. If the pen is down, a line will be drawn from the current position to the new one using the receiver's form source as the shape of the drawing brush. The receiver's set direction does not change." | old | old _ location. location _ aPoint. penDown ifTrue: [self drawFrom: old rounded to: location rounded] "NOTE: This should be changed so it does NOT draw the first point, so as not to overstrike at line junctions. At the same time, place should draw a single dot if the pen is down, as should down (put-pen-down) if it was not down before."! ! !Pen methodsFor: 'operations'! home "Place the receiver at the center of its frame." location _ destForm boundingBox center! ! !Pen methodsFor: 'operations'! north "Set the receiver's direction to facing toward the top of the display screen." direction _ 270! ! !Pen methodsFor: 'operations'! place: aPoint "Set the receiver at position aPoint. No lines are drawn." location _ aPoint! ! !Pen methodsFor: 'operations' stamp: 'ar 5/28/2000 12:10'! print: str withFont: font "Print the given string in the given font at the current heading" | lineStart form charStart rowStart scale wasDown bb pix | scale _ sourceForm width. wasDown _ penDown. lineStart _ location. str do: [:char | char = Character cr ifTrue: [self place: lineStart; up; turn: 90; go: font height*scale; turn: -90; down] ifFalse: [form _ font characterFormAt: char. charStart _ location. wasDown ifTrue: [ self up; turn: -90; go: font descent*scale; turn: 90; down. 0 to: form height-1 do: [:y | rowStart _ location. bb _ BitBlt current bitPeekerFromForm: form. pix _ RunArray newFrom: ((0 to: form width-1) collect: [:x | bb pixelAt: x@y]). pix runs with: pix values do: [:run :value | value = 0 ifTrue: [self up; go: run*scale; down] ifFalse: [self go: run*scale]]. self place: rowStart; up; turn: 90; go: scale; turn: -90; down]. ]. self place: charStart; up; go: form width*scale; down]. ]. wasDown ifFalse: [self up] " Display restoreAfter: [Pen new squareNib: 2; color: Color red; turn: 45; print: 'The owl and the pussycat went to sea in a beautiful pea green boat.' withFont: TextStyle defaultFont] "! ! !Pen methodsFor: 'operations'! turn: degrees "Change the direction that the receiver faces by an amount equal to the argument, degrees." direction _ direction + degrees! ! !Pen methodsFor: 'operations'! up "Set the state of the receiver's pen to up (no drawing)." penDown _ false! ! !Pen methodsFor: 'geometric designs' stamp: 'di 6/11/1998 22:01'! dragon: n "Display restoreAfter: [Display fillWhite. Pen new dragon: 10]." "Display restoreAfter: [Display fillWhite. 1 to: 4 do: [:i | Pen new color: i; turn: 90*i; dragon: 10]]" "Draw a dragon curve of order n in the center of the screen." n = 0 ifTrue: [self go: 5] ifFalse: [n > 0 ifTrue: [self dragon: n - 1; turn: 90; dragon: 1 - n] ifFalse: [self dragon: -1 - n; turn: -90; dragon: 1 + n]] ! ! !Pen methodsFor: 'geometric designs'! hilbert: n side: s "Draw an nth level Hilbert curve with side length s in the center of the screen. Write directly into the display's bitmap only. A Hilbert curve is a space-filling curve." | a m | n = 0 ifTrue: [^self turn: 180]. n > 0 ifTrue: [a _ 90. m _ n - 1] ifFalse: [a _ -90. m _ n + 1]. self turn: a. self hilbert: 0 - m side: s. self turn: a; go: s. self hilbert: m side: s. self turn: 0 - a; go: s; turn: 0 - a. self hilbert: m side: s. self go: s; turn: a. self hilbert: 0 - m side: s. self turn: a " (Pen new) hilbert: 3 side: 8. (Pen new sourceForm: Cursor wait) combinationRule: Form under; hilbert: 3 side: 25. "! ! !Pen methodsFor: 'geometric designs'! hilberts: n "Display restoreAfter: [Display fillWhite. Pen new hilberts: 5]" "Draws n levels of nested Hilbert curves" | s | self up; turn: 90; go: 128; down. 1 to: n do: [:i | s _ 256 bitShift: 0 - i. self defaultNib: n - i * 2 + 1. self color: i+1. self up; go: 0 - s / 2; turn: -90; go: s / 2; turn: 90; down. self hilbert: i side: s. self go: s. self hilbert: i side: s. self go: s]! ! !Pen methodsFor: 'geometric designs'! mandala: npoints "Display restoreAfter: [Pen new mandala: 30]" "On a circle of diameter d, place npoints number of points. Draw all possible connecting lines between the circumferential points." | l points d | Display fillWhite. d _ Display height-50. l _ 3.14 * d / npoints. self home; up; turn: -90; go: d // 2; turn: 90; go: 0 - l / 2; down. points _ Array new: npoints. 1 to: npoints do: [:i | points at: i put: location rounded. self go: l; turn: 360.0 / npoints]. npoints // 2 to: 1 by: -1 do: [:i | self color: i. 1 to: npoints do: [:j | self place: (points at: j). self goto: (points at: j + i - 1 \\ npoints + 1)]] ! ! !Pen methodsFor: 'geometric designs' stamp: 'jm 5/6/1998 22:26'! spiral: n angle: a "Draw a double squiral (see Papert, MindStorms), where each design is made by moving the receiver a distance of n after turning the amount + or -a." 1 to: n do: [:i | self color: i * 2. self go: i; turn: a] " Display restoreAfter: [ Display fillWhite. Pen new spiral: 200 angle: 89; home; spiral: 200 angle: -89]. "! ! !Pen methodsFor: 'geometric designs' stamp: 'jm 8/1/97 11:42'! web "Display restoreAfter: [Pen new web]" "Draw pretty web-like patterns from the mouse movement on the screen. Press the mouse button to draw, option-click to exit. By Dan Ingalls and Mark Lentczner. " | history newPoint ancientPoint lastPoint filter color | "self erase." color _ 1. [ true ] whileTrue: [ history _ OrderedCollection new. Sensor waitButton. Sensor yellowButtonPressed ifTrue: [^ self]. filter _ lastPoint _ Sensor mousePoint. 20 timesRepeat: [ history addLast: lastPoint ]. self color: (color _ color + 1). [ Sensor redButtonPressed ] whileTrue: [ newPoint _ Sensor mousePoint. (newPoint = lastPoint) ifFalse: [ ancientPoint _ history removeFirst. filter _ filter * 4 + newPoint // 5. self place: filter. self goto: ancientPoint. lastPoint _ newPoint. history addLast: filter ] ] ]! ! !Pen methodsFor: 'private' stamp: 'di 6/11/1998 16:09'! location: aPoint direction: aFloat penDown: aBoolean location _ aPoint. direction _ aFloat. penDown _ aBoolean! ! !Pen methodsFor: 'private'! sourceForm: aForm (aForm depth = 1 and: [destForm depth > 1]) ifTrue: ["Map 1-bit source to all ones for color mask" colorMap _ Bitmap with: 0 with: 16rFFFFFFFF] ifFalse: [colorMap _ nil]. ^ super sourceForm: aForm! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Pen class instanceVariableNames: ''! !Pen class methodsFor: 'instance creation'! new ^ self newOnForm: Display! ! !Pen class methodsFor: 'instance creation'! newOnForm: aForm | pen | pen _ super new. pen setDestForm: aForm. pen sourceOrigin: 0@0. pen home. pen defaultNib: 1. pen north. pen down. ^ pen! ! !Pen class methodsFor: 'examples' stamp: 'jm 5/6/1998 22:28'! example "Draw a spiral with a pen that is 2 pixels wide." "Display restoreAfter: [Pen example]" | bic | bic _ self new. bic defaultNib: 2. bic color: Color blue. bic combinationRule: Form over. 1 to: 100 do: [:i | bic go: i*4. bic turn: 89]. ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'ar 5/14/2001 23:35'! feltTip: width cellSize: cellSize "Warning: This example potentially uses a large amount of memory--it creates a Form with cellSize squared bits for every Display pixel." "In this example, all drawing is done into a large, monochrome Form and then scaled down onto the Display using smoothing. The larger the cell size, the more possible shades of gray can be generated, and the smoother the resulting line appears. A cell size of 8 yields 64 possible grays, while a cell size of 16 gives 256 levels, which is about the maximum number of grays that the human visual system can distinguish. The width parameter determines the maximum line thickness. Requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." "Pen feltTip: 2.7 cellSize: 8" | tabletScale bitForm pen warp p srcR dstR nibSize startP r | tabletScale _ self tabletScaleFactor. bitForm _ Form extent: Display extent * cellSize depth: 1. pen _ Pen newOnForm: bitForm. pen color: Color black. warp _ (WarpBlt current toForm: Display) sourceForm: bitForm; colorMap: (bitForm colormapIfNeededFor: Display); cellSize: cellSize; combinationRule: Form over. Display fillColor: Color white. Display restoreAfter: [ [Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [ p _ (Sensor tabletPoint * cellSize * tabletScale) rounded. nibSize _ (Sensor tabletPressure * (cellSize * width)) rounded. nibSize > 0 ifTrue: [ pen squareNib: nibSize. startP _ pen location. pen goto: p. r _ startP rect: pen location. dstR _ (r origin // cellSize) corner: ((r corner + nibSize + (cellSize - 1)) // cellSize). srcR _ (dstR origin * cellSize) corner: (dstR corner * cellSize). warp copyQuad: srcR innerCorners toRect: dstR] ifFalse: [ pen place: p]]]. ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'jm 4/13/1999 11:20'! inkBrush "Similar to simplePressurePen, but this example uses the average of the recent pen pressure values. The effect is that of a Japanese ink brush that comes up gradually off the paper as the brush is lifted, causing end (and beginning) of each stroke to taper. Requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." "Pen inkBrush" | tabletScale historyMSecs pressureHistory pen now currentPressure sum averagePressure p | tabletScale _ self tabletScaleFactor. historyMSecs _ 120. pressureHistory _ OrderedCollection new. pen _ Pen newOnForm: Display. pen color: Color black. Display fillColor: Color white. Display restoreAfter: [ [Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [ "compute the average pressure over last historyMSecs milliseconds" now _ Time millisecondClockValue. currentPressure _ (20.0 * Sensor tabletPressure) rounded. pressureHistory addLast: (Array with: now with: currentPressure). [pressureHistory size > 0 and: [(pressureHistory first first + historyMSecs) < now]] whileTrue: [pressureHistory removeFirst]. "prune old entries" sum _ pressureHistory inject: 0 into: [:t :e | t + e last]. averagePressure _ sum // pressureHistory size. p _ (Sensor tabletPoint * tabletScale) rounded. averagePressure > 0 ifTrue: [ pen roundNib: averagePressure. pen goto: p] ifFalse: [ pen place: p]]]. ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'jm 4/13/1999 11:13'! simplePressurePen "An example of using a pressure sensitive pen to control the thickness of the pen. This requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." "Pen simplePressurePen" | tabletScale pen pressure p | tabletScale _ self tabletScaleFactor. pen _ Pen newOnForm: Display. pen color: Color black. Display fillColor: Color white. Display restoreAfter: [ [Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [ p _ (Sensor tabletPoint * tabletScale) rounded. pressure _ (15.0 * Sensor tabletPressure) rounded. pressure > 0 ifTrue: [ pen roundNib: pressure. pen goto: p] ifFalse: [ pen place: p]]]. ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'jm 4/13/1999 11:12'! tabletScaleFactor "Answer a Point that scales tablet coordinates to Display coordinates, where the full extent of the tablet maps to the extent of the entire Display." | tabletExtent | tabletExtent _ Sensor tabletExtent. ^ (Display width asFloat / tabletExtent x) @ (Display height asFloat / tabletExtent y) ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'jm 4/12/1999 12:51'! testMouseTracking "A very simple example of drawing using the mouse. Compare the tracking speed of this example with that of testTabletTracking. Mouse down to draw a stroke, shift-mouse to exit." "Pen testMouseTracking" | pen p | pen _ Pen newOnForm: Display. pen roundNib: 8. pen color: Color black. Display fillColor: Color white. Display restoreAfter: [ [Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [ p _ Sensor cursorPoint. Sensor anyButtonPressed ifTrue: [pen goto: p] ifFalse: [ pen color: Color random. pen place: p]]]. ! ! !Pen class methodsFor: 'tablet drawing examples' stamp: 'jm 4/13/1999 11:21'! testTabletTracking "A very simple example of drawing using the pen of a digitizing tablet such as a Wacom ArtZ tablet. This requires the optional tablet support primitives which may not be supported on all platforms. Compare the tracking speed of this example with that of testMouseTracking. On a Macintosh, the tablet primitives provide roughly 120 samples/second versus only 60 mouse samples/second, and the difference is noticable. Works best in full screen mode. Mouse down to draw a stroke, shift-mouse to exit." "Pen testTabletTracking" | tabletScale pen p | tabletScale _ self tabletScaleFactor. pen _ Pen newOnForm: Display. pen roundNib: 8. pen color: Color black. Display fillColor: Color white. Display restoreAfter: [ [Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [ p _ (Sensor tabletPoint * tabletScale) rounded. Sensor tabletPressure > 0 ifTrue: [pen goto: p] ifFalse: [ pen color: Color random. pen place: p]]]. ! ! Controller subclass: #PluggableButtonController instanceVariableNames: 'selector arguments shownAsComplemented' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableButtonController commentStamp: '<historical>' prior: 0! The controller for Buttons. Not meant to be used with buttons that have mouseOver feeback when the button is not pressed. Use mouseEnter/mouseLeave for that. ! !PluggableButtonController methodsFor: 'basic control sequence' stamp: 'acg 3/13/2000 08:49'! controlInitialize "Provide feedback indicating that button has been entered with the mouse down. If triggerOnMouseDown is true, then do the button action on mouse down--and don't bother with the feedback since the action happens immediately." sensor anyButtonPressed ifFalse: [^ self]. view triggerOnMouseDown ifTrue: [sensor yellowButtonPressed ifTrue: [self yellowButtonActivity] ifFalse: [view performAction]] ifFalse: [view toggleMouseOverFeedback. shownAsComplemented _ true]! ! !PluggableButtonController methodsFor: 'basic control sequence' stamp: 'acg 3/13/2000 08:44'! controlTerminate "Reverse the feedback displayed by controlInitialize, if any. Perform the button action if necessary." view ifNotNil: [view triggerOnMouseDown ifFalse: [shownAsComplemented ifTrue: [view toggleMouseOverFeedback]. self viewHasCursor ifTrue: [view performAction]]]! ! !PluggableButtonController methodsFor: 'control defaults' stamp: 'sma 5/28/2000 16:29'! controlActivity shownAsComplemented ifNil: [^ self]. shownAsComplemented = self viewHasCursor ifFalse: [view ifNotNil: [view toggleMouseOverFeedback]. shownAsComplemented _ shownAsComplemented not]! ! !PluggableButtonController methodsFor: 'control defaults' stamp: 'acg 3/13/2000 08:26'! isControlActive ^ sensor anyButtonPressed! ! !PluggableButtonController methodsFor: 'control defaults' stamp: 'tk 4/29/1998 10:47'! isControlWanted "sensor flushKeyboard." self viewHasCursor & sensor anyButtonPressed ifFalse: [^ false]. view askBeforeChanging ifTrue: [^ model okToChange] "ask before changing" ifFalse: [^ true]. ! ! !PluggableButtonController methodsFor: 'button activity' stamp: 'di 9/7/1999 08:44'! yellowButtonActivity "Invoke the model's menu. This is option-click, NOT the normal button press." | menu | menu _ view getMenu: false. menu == nil ifTrue: [sensor waitNoButton] ifFalse: [self terminateAndInitializeAround: [menu invokeOn: model]]. ! ! View subclass: #PluggableButtonView instanceVariableNames: 'label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown complemented argumentsProvider argumentsSelector' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableButtonView commentStamp: '<historical>' prior: 0! A PluggableButtonView is a combination of an indicator for a boolean value stored in its model and an action button. The action of a button is often, but not always, to toggle the boolean value that it shows. Its pluggable selectors are: getStateSelector fetch a boolean value from the model actionSelector invoke this button's action on the model Either of the above selectors can be nil, meaning that the model does not supply behavior for the given action, and the default behavior should be used. For example, if getStateSelector is nil, then this button shows the state of a read-only boolean that is always false. The model informs a pluggable view of changes by sending #changed: to itself with getStateSelector as a parameter. The view tells the model when the button is pressed by sending actionSelector. Options: askBeforeChanging have model ask user before allowing change that could lose edits triggerOnMouseDown do button action on mouse down (vs. up) transition shortcutCharacter a place to record an optional shortcut key ! !PluggableButtonView methodsFor: 'initialize-release' stamp: 'jm 5/2/1998 15:20'! initialize super initialize. label _ nil. getStateSelector _ nil. actionSelector _ nil. getLabelSelector _ nil. getMenuSelector _ nil. shortcutCharacter _ nil. askBeforeChanging _ false. triggerOnMouseDown _ false. complemented _ false. ! ! !PluggableButtonView methodsFor: 'initialize-release' stamp: 'sw 2/17/2002 05:32'! on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor label: labelSel menu: menuSel self initialize. self model: anObject. getStateSelector _ getStateSel. actionSelector _ actionSel. argumentsSelector _ getArgumentsSel. argumentsProvider _ argsProvidor. getLabelSelector _ labelSel. getMenuSelector _ menuSel! ! !PluggableButtonView methodsFor: 'initialize-release' stamp: 'tk 4/29/1998 11:18'! on: anObject getState: getStateSel action: actionSel label: labelSel menu: menuSel self initialize. self model: anObject. getStateSelector _ getStateSel. actionSelector _ actionSel. getLabelSelector _ labelSel. getMenuSelector _ menuSel.! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jrm 6/1/1998 21:53'! action: aSymbol "Set actionSelector to be the action defined by aSymbol." actionSelector _ aSymbol ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/2/98 18:53'! askBeforeChanging ^ askBeforeChanging ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/7/98 19:17'! askBeforeChanging: aBoolean "If this preference is turned on, then give the model an opportunity to ask the user before accepting a change that might cause unaccepted edits to be lost." askBeforeChanging _ aBoolean. ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/2/98 17:38'! label "Answer the DisplayObject used as this button's label." ^ label ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'nk 4/17/2004 19:49'! label: aStringOrDisplayObject "Label this button with the given String or DisplayObject." ((aStringOrDisplayObject isKindOf: Paragraph) or: [aStringOrDisplayObject isForm]) ifTrue: [label _ aStringOrDisplayObject] ifFalse: [label _ aStringOrDisplayObject asParagraph]. self centerLabel. ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/2/98 17:43'! shortcutCharacter "Return the Character to be used as a shortcut to turn on this switch, or nil if this switch doesn't have a keyboard shortcut." ^ shortcutCharacter ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/2/98 17:43'! shortcutCharacter: aCharacter "Set the character to be used as a keyboard shortcut for turning on this switch." shortcutCharacter _ aCharacter. ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/2/98 19:26'! triggerOnMouseDown ^ triggerOnMouseDown ! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'jm 4/7/98 19:16'! triggerOnMouseDown: aBoolean "If this preference is turned on, then trigger my action immediately when the mouse goes down." triggerOnMouseDown _ aBoolean. ! ! !PluggableButtonView methodsFor: 'controller access' stamp: 'jm 4/2/98 17:39'! defaultControllerClass ^ PluggableButtonController ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'jm 4/2/98 18:49'! deEmphasizeView self getModelState ifTrue: [self displayNormal]. ! ! !PluggableButtonView methodsFor: 'displaying'! display "Sets the PluggableButtonView mode to 'normal', displays the border, displays the inside and, if its model is 'on', complements the inside." self displayBorder. self displayView. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'jm 4/4/98 20:49'! displayComplemented "Complement the receiver if it isn't already." complemented ifFalse: [ complemented _ true. Display reverse: self insetDisplayBox]. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'jm 4/2/98 18:43'! displayNormal "Complement the receiver if its mode is 'complemented'." complemented ifTrue: [ complemented _ false. Display reverse: self insetDisplayBox]. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'acg 2/23/2000 00:18'! displayView "Displays this switch and its label, if any." self clearInside. label ifNotNil: [ (label isKindOf: Paragraph) ifTrue: [ label foregroundColor: self foregroundColor backgroundColor: self backgroundColor]. label displayOn: Display at: label boundingBox topLeft clippingBox: self insetDisplayBox]. complemented _ false.! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'jm 4/4/98 20:41'! emphasizeView self getModelState ifTrue: [self displayComplemented]. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'jm 4/5/98 12:54'! toggleMouseOverFeedback "Complement the label (or a portion of the displayBox if no label is defined) to show that the mouse is over this button. This feedback can be removed by a second call to this method." Display reverse: self insetDisplayBox fillColor: Color gray. Display reverse: (self insetDisplayBox insetBy: 2) fillColor: Color gray. ! ! !PluggableButtonView methodsFor: 'other' stamp: 'jm 4/7/98 19:12'! defaultWindow "Return a rectangle large enough to contain this button's label. If this button is label-less, just return the standard View default window." label == nil ifTrue: [^ super defaultWindow] ifFalse: [^ label boundingBox expandBy: 6]. ! ! !PluggableButtonView methodsFor: 'other' stamp: 'sw 2/17/2002 05:32'! performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed." argumentsSelector ifNil: [actionSelector ifNotNil: [model perform: actionSelector]] ifNotNil: [model perform: actionSelector withArguments: (Array with: (argumentsProvider perform: argumentsSelector))]! ! !PluggableButtonView methodsFor: 'other' stamp: 'tk 4/27/1998 21:23'! update: aParameter aParameter == getLabelSelector ifTrue: [ getLabelSelector ifNotNil: [ self label: (model perform: getLabelSelector). self displayView]]. self getModelState ifTrue: [self displayComplemented] ifFalse: [self displayNormal]. ! ! !PluggableButtonView methodsFor: 'other' stamp: 'jm 4/7/98 19:12'! window: aWindow "Center my label when my window changes." super window: aWindow. self centerLabel. ! ! !PluggableButtonView methodsFor: 'private' stamp: 'nk 4/17/2004 19:49'! centerAlignLabelWith: aPoint "Align the center of the label with aPoint." | alignPt | alignPt _ label boundingBox center. (label isKindOf: Paragraph) ifTrue: [alignPt _ alignPt + (0@(label textStyle leading))]. (label isForm) ifTrue: [label offset: 0 @ 0]. label align: alignPt with: aPoint ! ! !PluggableButtonView methodsFor: 'private' stamp: 'acg 2/23/2000 00:10'! centerLabel "If there is a label, align its center with the center of the insetDisplayBox" label ifNotNil: [self centerAlignLabelWith: self insetDisplayBox center]. ! ! !PluggableButtonView methodsFor: 'private' stamp: 'di 6/26/1998 11:04'! getMenu: shiftKeyDown "Answer the menu for this view, supplying an empty menu to be filled in. If the menu selector takes an extra argument, pass in the current state of the shift key." | menu | getMenuSelector == nil ifTrue: [^ nil]. menu _ CustomMenu new. getMenuSelector numArgs = 1 ifTrue: [^ model perform: getMenuSelector with: menu]. getMenuSelector numArgs = 2 ifTrue: [^ model perform: getMenuSelector with: menu with: shiftKeyDown]. ^ self error: 'The getMenuSelector must be a 1- or 2-keyword symbol' ! ! !PluggableButtonView methodsFor: 'private' stamp: 'jm 4/4/98 20:50'! getModelState "Answer the result of sending the receiver's model the getStateSelector message." getStateSelector == nil ifTrue: [^ false] ifFalse: [^ model perform: getStateSelector]. ! ! !PluggableButtonView methodsFor: 'private' stamp: 'acg 2/23/2000 00:09'! insetDisplayBox "Answer the receiver's inset display box. The inset display box is the intersection of the receiver's window, tranformed to display coordinates, and the inset display box of the superView, inset by the border width. The inset display box represents the region of the display screen in which the inside of the receiver (all except the border) is displayed. If the receiver is totally clipped by the display screen and its superView, the resulting Rectangle will be invalid." insetDisplayBox ifNil: [insetDisplayBox _ self computeInsetDisplayBox. self centerLabel]. ^insetDisplayBox! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PluggableButtonView class instanceVariableNames: ''! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'jm 8/14/1998 16:19'! on: anObject ^ self on: anObject getState: #isOn action: #switch ! ! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'tk 4/29/1998 11:19'! on: anObject getState: getStateSel action: actionSel ^ self new on: anObject getState: getStateSel action: actionSel label: nil menu: nil! ! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'sumim 2/15/2002 17:18'! on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor ^ self new on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor label: nil menu: nil! ! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'tk 4/29/1998 11:19'! on: anObject getState: getStateSel action: actionSel label: labelSel ^ self new on: anObject getState: getStateSel action: actionSel label: labelSel menu: nil! ! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'tk 4/29/1998 11:18'! on: anObject getState: getStateSel action: actionSel label: labelSel menu: menuSel ^ self new on: anObject getState: getStateSel action: actionSel label: labelSel menu: menuSel! ! !PluggableButtonView class methodsFor: 'example' stamp: 'jm 4/7/98 19:55'! example "PluggableButtonView example" | s1 s2 s3 b1 b2 b3 topView | s1 _ Switch new. s2 _ Switch new turnOn. s3 _ Switch new. s2 onAction: [s3 turnOff]. s3 onAction: [s2 turnOff]. b1 _ (PluggableButtonView on: s1 getState: #isOn action: #switch) label: 'S1'. b2 _ (PluggableButtonView on: s2 getState: #isOn action: #turnOn) label: 'S2'. b3 _ (PluggableButtonView on: s3 getState: #isOn action: #turnOn) label: 'S3'. b1 borderWidth: 1. b2 borderWidth: 1. b3 borderWidth: 1. topView _ StandardSystemView new label: 'Switch Test'; addSubView: b1; addSubView: b2 toRightOf: b1; addSubView: b3 toRightOf: b2. topView controller open. ! ! Dictionary subclass: #PluggableDictionary instanceVariableNames: 'hashBlock equalBlock' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !PluggableDictionary commentStamp: '<historical>' prior: 0! Class PluggableDictionary allows the redefinition of hashing and equality by clients. This is in particular useful if the clients know about specific properties of the objects stored in the dictionary. See the class comment of PluggableSet for an example. Instance variables: hashBlock <BlockContext> A one argument block used for hashing the elements. equalBlock <BlockContext> A two argument block used for comparing the elements. ! !PluggableDictionary methodsFor: 'accessing' stamp: 'ar 11/12/1998 18:46'! equalBlock "Return the block used for comparing the elements in the receiver." ^equalBlock! ! !PluggableDictionary methodsFor: 'accessing' stamp: 'ar 11/27/1998 23:55'! equalBlock: aBlock "Set a new equality block. The block must accept two arguments and return true if the argumets are considered to be equal, false otherwise" equalBlock _ aBlock.! ! !PluggableDictionary methodsFor: 'accessing' stamp: 'ar 11/12/1998 18:46'! hashBlock "Return the block used for hashing the elements in the receiver." ^hashBlock! ! !PluggableDictionary methodsFor: 'accessing' stamp: 'ar 11/12/1998 18:46'! hashBlock: aBlock "Set a new hash block. The block must accept one argument and must return the hash value of the given argument." hashBlock _ aBlock.! ! !PluggableDictionary methodsFor: 'accessing' stamp: 'dvf 6/10/2000 19:34'! keys "Answer a Set containing the receiver's keys." | aSet | aSet _ PluggableSet new: self size. self equalBlock ifNotNil: [aSet equalBlock: self equalBlock fixTemps]. self hashBlock ifNotNil: [aSet hashBlock: self hashBlock fixTemps]. self keysDo: [:key | aSet add: key]. ^ aSet! ! !PluggableDictionary methodsFor: 'copying' stamp: 'ar 11/12/1998 18:48'! copy ^super copy postCopyBlocks! ! !PluggableDictionary methodsFor: 'copying' stamp: 'dvf 6/10/2000 19:35'! postCopyBlocks hashBlock _ hashBlock copy. equalBlock _ equalBlock copy. "Fix temps in case we're referring to outside stuff" hashBlock ifNotNil: [hashBlock fixTemps]. equalBlock ifNotNil: [equalBlock fixTemps]! ! !PluggableDictionary methodsFor: 'private' stamp: 'dvf 6/11/2000 01:33'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (hashBlock ifNil: [anObject hash] ifNotNil: [hashBlock value: anObject]) \\ array size + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [equalBlock ifNil: [element key = anObject] ifNotNil: [equalBlock value: element key value: anObject]]) ifTrue: [^ index]]. "Search from 1 to where we started." 1 to: start - 1 do: [:index | ((element _ array at: index) == nil or: [equalBlock ifNil: [element key = anObject] ifNotNil: [equalBlock value: element key value: anObject]]) ifTrue: [^ index]]. ^ 0"No match AND no empty slot"! ! FileList subclass: #PluggableFileList instanceVariableNames: 'accepted fileFilterBlock canAcceptBlock validateBlock newFiles prompt resultBlock' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !PluggableFileList commentStamp: '<historical>' prior: 0! I am a model for a modal dialog akin to "Standard File Services" on various modern GUI operating systems. My protocol includes some methods to maintain upward compatibility with StandardFileMenu, which I hope to replace. Sample doIts: "StandardFileDialog getFolder"-- ask user to select folder, answer corresponding FileDirectory "StandardFileDialog getFile" -- ask user to select file, answer corresponding FileStream "StandardFileDialog putFile" -- ask user to create new file, answer FileStream In addition to the instance variables inhereted from FileList, of which I am a subclass, I am pluggable via the following instance variables: prompt <String> Display a prompt between the buttons. resultBlock <BlockContext> Passed a file directory and a file name, answer the result to be answered by the dialog. canAcceptBlock <BlockContext> Answer whether the accept button should be "active" fileFilterBlock <BlockContext> Passed a file directory entry, answer whether the entry should be added to the list. The list can be further filtered (but not expanded) by the user through the pattern. validateBlock <BlockContent> Passed a file directory entry, a file name and a collection of newly created files, answer whether the dialog selection is valid. validateBlock is checked after the user has pressed accept, for example to ask if the user really meant to delete a file. newFiles <OrderedCollection> newFiles is an OrderedCollection of fileNames of files added by the user to the current directory since the user last entered same! !PluggableFileList methodsFor: 'initialize-release' stamp: 'acg 2/12/2000 21:44'! defaultBackgroundColor ^Color lightYellow! ! !PluggableFileList methodsFor: 'initialize-release' stamp: 'acg 2/12/2000 14:52'! initialize prompt _ 'Select File'. directory _ FileDirectory default. newFiles _ OrderedCollection new. fileFilterBlock _ PluggableFileList allFilesAndFoldersFileFilter. canAcceptBlock _ PluggableFileList fileNameSelectedAcceptBlock. resultBlock _ PluggableFileList pathNameResultBlock. validateBlock _ PluggableFileList checkExistingFileValidateBlock. ! ! !PluggableFileList methodsFor: 'initialize-release' stamp: 'acg 2/9/2000 01:28'! open ^self openLabel: directory pathName! ! !PluggableFileList methodsFor: 'initialize-release' stamp: 'acg 2/19/2000 01:10'! openLabel: aString "Open a view of an instance of me." "StandardFileDialog new open" | topView volListView templateView fileListView fileStringView leftButtonView middleButtonView rightButtonView | self directory: directory. topView _ (PluggableFileListView new) model: self. volListView _ PluggableListView on: self list: #volumeList selected: #volumeListIndex changeSelected: #volumeListIndex: menu: #volumeMenu:. volListView autoDeselect: false. volListView window: (0@0 extent: 80@45). topView addSubView: volListView. templateView _ PluggableTextView on: self text: #pattern accept: #pattern:. templateView askBeforeDiscardingEdits: false. templateView window: (0@0 extent: 80@15). topView addSubView: templateView below: volListView. fileListView _ PluggableListView on: self list: #fileList selected: #fileListIndex changeSelected: #fileListIndex: menu: #fileListMenu:. fileListView window: (0@0 extent: 120@60). topView addSubView: fileListView toRightOf: volListView. fileListView controller terminateDuringSelect: true. "Pane to left may change under scrollbar" "fileStringView _ PluggableTextView on: self text: #fileString accept: #fileString:. fileStringView askBeforeDiscardingEdits: false. fileStringView window: (0@0 extent: 200@15). topView addSubView: fileStringView below: templateView." fileStringView _ templateView. leftButtonView _ PluggableButtonView on: self getState: nil action: #leftButtonPressed. leftButtonView label: 'Cancel'; backgroundColor: Color red; borderWidth: 3; window: (0@0 extent: 50@15). middleButtonView _ PluggableButtonView on: self getState: nil action: nil. middleButtonView label: prompt; window: (0@0 extent: 100@15); borderWidth: 1; controller: NoController new. rightButtonView _ PluggableButtonView on: self getState: nil action: #rightButtonPressed. rightButtonView label: 'Accept'; backgroundColor: (self canAccept ifTrue: [Color green] ifFalse: [Color lightYellow]); borderWidth: (self canAccept ifTrue: [3] ifFalse: [1]); window: (0@0 extent: 50@15). self canAccept ifFalse: [rightButtonView controller: NoController new]. topView acceptButtonView: rightButtonView. topView addSubView: leftButtonView below: fileStringView; addSubView: middleButtonView toRightOf: leftButtonView; addSubView: rightButtonView toRightOf: middleButtonView. self changed: #getSelectionSel. topView doModalDialog. ^self result ! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/13/2000 15:33'! beAccepted ^accepted _ true! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/9/2000 09:10'! canAccept ^canAcceptBlock value: directory value: fileName! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/9/2000 00:52'! canAcceptBlock: aBlock ^canAcceptBlock _ aBlock! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/9/2000 07:33'! fileFilterBlock: aBlock ^fileFilterBlock _ aBlock! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/18/2000 21:21'! fileListIndex self changed: #fileString. ^super fileListIndex! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/18/2000 21:21'! fileVolumeIndex self changed: #fileString. ^super fileVolumeIndex! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/9/2000 00:28'! prompt: aString prompt _ aString! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/9/2000 00:31'! resultBlock: aBlock ^resultBlock _ aBlock! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/13/2000 15:28'! validate ^validateBlock value: directory value: fileName value: newFiles! ! !PluggableFileList methodsFor: 'accessing' stamp: 'acg 2/10/2000 08:02'! validateBlock: aBlock ^validateBlock _ aBlock! ! !PluggableFileList methodsFor: 'accepting/cancelling' stamp: 'acg 2/9/2000 01:05'! leftButtonPressed accepted _ false. self changed: #close. ! ! !PluggableFileList methodsFor: 'accepting/cancelling' stamp: 'acg 2/14/2000 22:40'! leftButtonState ^true! ! !PluggableFileList methodsFor: 'accepting/cancelling' stamp: 'acg 2/9/2000 00:38'! result accepted ifFalse: [^nil]. ^resultBlock value: directory value: fileName! ! !PluggableFileList methodsFor: 'accepting/cancelling' stamp: 'acg 2/10/2000 07:58'! rightButtonPressed (canAcceptBlock value: directory value: fileName) ifFalse: [^nil]. (validateBlock value: directory value: fileName value: newFiles) ifFalse: [^nil]. accepted _ true. self changed: #close! ! !PluggableFileList methodsFor: 'accepting/cancelling' stamp: 'acg 2/14/2000 22:43'! rightButtonState ^self canAccept! ! !PluggableFileList methodsFor: 'file list menu' stamp: 'acg 2/10/2000 07:47'! addNew: aString byEvaluating: aBlock "A parameterization of earlier versions of #addNewDirectory and #addNewFile. Fixes the bug in each that pushing the cancel button in the FillInTheBlank dialog gave a walkback." | response newName index ending | self okToChange ifFalse: [^ self]. (response _ FillInTheBlank request: 'New ',aString,' Name?' initialAnswer: aString,'Name') isEmpty ifTrue: [^ self]. newName _ response asFileName. Cursor wait showWhile: [ aBlock value: newName]. self updateFileList. index _ list indexOf: newName. index = 0 ifTrue: [ending _ ') ',newName. index _ list findFirst: [:line | line endsWith: ending]]. self fileListIndex: index. newFiles add: newName ! ! !PluggableFileList methodsFor: 'file list menu' stamp: 'asm 8/25/2003 18:37'! fileSelectedMenu: aMenu | firstItems secondItems thirdItems n1 n2 n3 services | firstItems _ self itemsForFile: self fullName asLowercase. secondItems _ self itemsForAnyFile. thirdItems _ self itemsForNoFile. n1 _ firstItems size. n2 _ n1 + secondItems size. n3 _ n2 + thirdItems size. services _ firstItems, secondItems, thirdItems, (OrderedCollection with: (SimpleServiceEntry provider: self label: 'more...' selector: #offerAllFileOptions)). ^ aMenu addServices2: services for: self extraLines: (Array with: n1 with: n2 with: n3) ! ! !PluggableFileList methodsFor: 'file list menu' stamp: 'BG 12/13/2002 10:00'! itemsForNoFile ^(OrderedCollection new: 5) add: self serviceSortByName; add: self serviceSortBySize; add: self serviceSortByDate; add: self serviceAddNewFile; add: self serviceAddNewDirectory; yourself! ! !PluggableFileList methodsFor: 'file list menu' stamp: 'BG 10/29/2003 10:08'! listForPattern: pat "Make the list be those file names which match the pattern." | entries sizePad newList allFiles | entries _ directory entries select: fileFilterBlock. sizePad _ (entries inject: 0 into: [:mx :entry | mx max: (entry at: 5)]) asStringWithCommas size - 1. newList _ (SortedCollection new: 30) sortBlock: self sortBlock. allFiles _ pat = '*'. entries do: [:entry | "<dirflag><name><creationTime><modificationTime><fileSize>" (allFiles or: [entry isDirectory or: [pat match: entry first]]) ifTrue: [newList add: entry]]. newList _ newList collect: [ :e | self fileNameFormattedFrom: e sizePad: sizePad ]. volList size = 1 ifTrue: ["Include known servers along with other desktop volumes" ^ newList asArray" , (ServerDirectory serverNames collect: [:n | '^' , n , self folderString])"]. newFiles _ OrderedCollection new. ^ newList asArray.! ! !PluggableFileList methodsFor: 'file string' stamp: 'acg 2/18/2000 21:23'! fileString fileName ifNil: [^directory pathName]. ^directory fullNameFor: fileName! ! !PluggableFileList methodsFor: 'file string' stamp: 'acg 2/19/2000 01:02'! fileString: aString "| textName index ending | textName _ aString asString. (FileDirectory default fileExists: textName) ifTrue: [self directory: (FileDirectory forFileName: textName). index _ list indexOf: (FileDirectory localNameFor: textName). index = 0 ifTrue: [ending _ ') ', (FileDirectory localNameFor: textName). index _ list findFirst: [:line | line endsWith: ending]]. self fileListIndex: index]. (FileDirectory default directoryExists: textName) ifTrue: [self directory: (FileDirectory on: textName)]." self changed: #fileString. self changed: #contents. ^true! ! !PluggableFileList methodsFor: 'StandardFileMenu' stamp: 'ar 3/18/2001 00:55'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: (ActiveHand ifNil:[Sensor cursorPoint]).! ! !PluggableFileList methodsFor: 'StandardFileMenu' stamp: 'acg 2/12/2000 15:35'! startUpWithCaption: aString at: location self prompt: aString. ^self open! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PluggableFileList class instanceVariableNames: ''! !PluggableFileList class methodsFor: 'instance creation' stamp: 'acg 2/12/2000 14:52'! getFilePathNameDialog ^(self new) validateBlock: PluggableFileList alwaysValidateBlock; yourself! ! !PluggableFileList class methodsFor: 'instance creation' stamp: 'acg 2/12/2000 14:52'! getFilePathNameDialogWithExistenceCheck ^(self new) prompt: 'Select New File:'; validateBlock: PluggableFileList checkExistingFileValidateBlock; yourself! ! !PluggableFileList class methodsFor: 'instance creation' stamp: 'acg 2/12/2000 14:52'! getFolderDialog ^(self new) prompt: 'Select a Folder'; fileFilterBlock: PluggableFileList allFoldersFileFilter; canAcceptBlock: PluggableFileList alwaysAcceptBlock; resultBlock: PluggableFileList directoryResultBlock; validateBlock: PluggableFileList alwaysValidateBlock; yourself! ! !PluggableFileList class methodsFor: 'instance creation' stamp: 'acg 2/9/2000 00:34'! open ^self new open! ! !PluggableFileList class methodsFor: 'standard dialog operations' stamp: 'acg 2/10/2000 08:24'! getFile | result | result _ self getFilePathName. ^result ifNotNil: [FileStream oldFileNamed: result]! ! !PluggableFileList class methodsFor: 'standard dialog operations' stamp: 'acg 2/10/2000 08:31'! getFilePathName ^self getFilePathNameDialog open! ! !PluggableFileList class methodsFor: 'standard dialog operations' stamp: 'acg 2/10/2000 08:29'! getFilePathNameWithExistenceCheck ^self getFilePathNameDialogWithExistenceCheck open! ! !PluggableFileList class methodsFor: 'standard dialog operations' stamp: 'acg 2/9/2000 01:16'! getFolder ^self getFolderDialog open! ! !PluggableFileList class methodsFor: 'standard dialog operations' stamp: 'acg 2/10/2000 08:29'! putFile | result | result _ self getFilePathNameWithExistenceCheck. ^result ifNotNil: [FileDirectory deleteFilePath: result. FileStream newFileNamed: result]! ! !PluggableFileList class methodsFor: 'resultBlocks' stamp: 'acg 2/10/2000 08:19'! directoryResultBlock ^[:theDirectory :theFileName | theDirectory]! ! !PluggableFileList class methodsFor: 'resultBlocks' stamp: 'acg 2/10/2000 08:07'! fileNameResultBlock ^[:theDirectory :theFileName | theFileName]! ! !PluggableFileList class methodsFor: 'resultBlocks' stamp: 'acg 2/10/2000 08:07'! pathNameResultBlock ^[:theDirectory :theFileName | theFileName ifNil: [theDirectory pathName] ifNotNil: [theDirectory fullNameFor: theFileName]]. ! ! !PluggableFileList class methodsFor: 'resultBlocks' stamp: 'acg 2/12/2000 15:08'! sfmResultBlock ^[:theDirectory :theFileName | StandardFileMenuResult directory: theDirectory name: theFileName]! ! !PluggableFileList class methodsFor: 'canAcceptBlocks' stamp: 'acg 2/10/2000 08:18'! alwaysAcceptBlock ^[:theDirectory :theFileName | true]! ! !PluggableFileList class methodsFor: 'canAcceptBlocks' stamp: 'acg 2/10/2000 08:10'! fileNameSelectedAcceptBlock ^[:theDirectory :theFileName | theFileName isNil not]! ! !PluggableFileList class methodsFor: 'validateBlocks' stamp: 'acg 2/10/2000 08:27'! alwaysValidateBlock ^[:theDirectory :theFileName :theNewFiles | true].! ! !PluggableFileList class methodsFor: 'validateBlocks' stamp: 'acg 2/12/2000 14:52'! checkExistingFileValidateBlock ^[:theDirectory :theFileName :theNewFiles | (theNewFiles includes: theFileName) or: [(PluggableFileList okToOverwrite: theFileName)]].! ! !PluggableFileList class methodsFor: 'validateBlocks' stamp: 'acg 2/12/2000 14:52'! existingFileValidateBlock ^[:theDirectory :theFileName :theNewFiles | (theNewFiles includes: theFileName) or: [(PluggableFileList okToOverwrite: theFileName)]].! ! !PluggableFileList class methodsFor: 'validateBlocks' stamp: 'acg 2/10/2000 08:05'! okToOpen: aFileNameString without: aSuffixString "Answer whether user confirms that it is ok to overwrite the file named in aString" ^ 1 = ((PopUpMenu labels: 'overwrite that file select another file') startUpWithCaption: aFileNameString, ' already exists.') ! ! !PluggableFileList class methodsFor: 'validateBlocks' stamp: 'acg 2/10/2000 07:55'! okToOverwrite: aString "Answer whether user confirms that it is ok to overwrite the file named in aString" ^ 1 = ((PopUpMenu labels: 'overwrite that file select another file') startUpWithCaption: aString, ' already exists.') ! ! !PluggableFileList class methodsFor: 'fileFilterBlocks' stamp: 'acg 2/10/2000 08:16'! allFilesAndFoldersFileFilter ^[:each | true]! ! !PluggableFileList class methodsFor: 'fileFilterBlocks' stamp: 'acg 2/10/2000 08:17'! allFoldersFileFilter ^[:each | each isDirectory]! ! !PluggableFileList class methodsFor: 'StandardFileMenu' stamp: 'BG 12/13/2002 15:31'! newFileMenu: aDirectory "For compatibility with StandardFileMenu for now, answer a StandardFileMenuResult" ^(self getFilePathNameDialogWithExistenceCheck) resultBlock: self sfmResultBlock; directory: aDirectory; yourself! ! !PluggableFileList class methodsFor: 'StandardFileMenu' stamp: 'BG 12/13/2002 15:32'! oldFileMenu: aDirectory "For compatibility with StandardFileMenu for now, answer a StandardFileMenuResult" ^(self getFilePathNameDialog) resultBlock: self sfmResultBlock; directory: aDirectory; yourself! ! ModalSystemWindowView subclass: #PluggableFileListView instanceVariableNames: 'acceptButtonView' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !PluggableFileListView commentStamp: '<historical>' prior: 0! I provide aview for PluggableFileList! !PluggableFileListView methodsFor: 'as yet unclassified' stamp: 'acg 2/9/2000 08:57'! acceptButtonView: aView ^acceptButtonView _ aView! ! !PluggableFileListView methodsFor: 'as yet unclassified' stamp: 'acg 2/18/2000 20:52'! label: aString super label: aString. self noLabel! ! !PluggableFileListView methodsFor: 'as yet unclassified' stamp: 'acg 2/9/2000 08:55'! update: aSymbol (aSymbol = #volumeListIndex or: [aSymbol = #fileListIndex]) ifTrue: [self updateAcceptButton]. ^super update: aSymbol! ! !PluggableFileListView methodsFor: 'as yet unclassified' stamp: 'acg 2/9/2000 09:40'! updateAcceptButton self model canAccept ifTrue: [acceptButtonView backgroundColor: Color green; borderWidth: 3; controller: acceptButtonView defaultController] ifFalse: [acceptButtonView backgroundColor: Color lightYellow; borderWidth: 1; controller: NoController new]. acceptButtonView display.! ! ListController subclass: #PluggableListController instanceVariableNames: 'terminateDuringSelect' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableListController methodsFor: 'initialization' stamp: 'di 5/25/1998 10:15'! initialize super initialize. self terminateDuringSelect: false! ! !PluggableListController methodsFor: 'control defaults' stamp: 'tk 4/1/98 09:40'! redButtonActivity model okToChange "Don't change selection if model refuses to unlock" ifTrue: [^ super redButtonActivity]! ! !PluggableListController methodsFor: 'private' stamp: 'di 5/25/1998 10:20'! changeModelSelection: anInteger "Let the view handle this." terminateDuringSelect ifTrue: [self controlTerminate]. view changeModelSelection: anInteger. terminateDuringSelect ifTrue: [self controlInitialize].! ! !PluggableListController methodsFor: 'private' stamp: 'sma 3/11/2000 15:38'! processKeyboard sensor keyboardPressed ifTrue: [view handleKeystroke: sensor keyboard] ifFalse: [super processKeyboard]! ! !PluggableListController methodsFor: 'private' stamp: 'di 5/25/1998 10:14'! terminateDuringSelect: trueOrFalse terminateDuringSelect _ trueOrFalse! ! PluggableListController subclass: #PluggableListControllerOfMany instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableListControllerOfMany methodsFor: 'control defaults' stamp: 'tpr 10/4/2001 22:19'! redButtonActivity | selection firstHit turningOn lastSelection pt scrollFlag | model okToChange ifFalse: [^ self]. "Don't change selection if model refuses to unlock" firstHit _ true. scrollFlag _ false. lastSelection _ 0. [sensor redButtonPressed] whileTrue: [selection _ view findSelection: (pt _ sensor cursorPoint). selection == nil ifTrue: "Maybe out of box - check for auto-scroll" [pt y < view insetDisplayBox top ifTrue: [self scrollView: view list lineGrid. scrollFlag _ true. selection _ view firstShown]. pt y > view insetDisplayBox bottom ifTrue: [self scrollView: view list lineGrid negated. scrollFlag _ true. selection _ view lastShown]]. (selection == nil or: [selection = lastSelection]) ifFalse: [firstHit ifTrue: [firstHit _ false. turningOn _ (view listSelectionAt: selection) not]. view selection: selection. (view listSelectionAt: selection) == turningOn ifFalse: [view displaySelectionBox. view listSelectionAt: selection put: turningOn]. lastSelection _ selection]]. selection notNil ifTrue: ["Normal protocol delivers change, so unchange first (ugh)" view listSelectionAt: selection put: (view listSelectionAt: selection) not. self changeModelSelection: selection]. scrollFlag ifTrue: [self moveMarker]! ! !PluggableListControllerOfMany methodsFor: 'scrolling' stamp: 'tk 4/8/98 11:09'! scrollView: anInteger "Need to minimize the selections which get recomputed" | oldLimit | oldLimit _ anInteger > 0 ifTrue: [view firstShown] ifFalse: [view lastShown]. (view scrollBy: anInteger) ifTrue: [anInteger > 0 "Highlight selections brought into view" ifTrue: [view highlightFrom: view firstShown to: (oldLimit-1 min: view lastShown)] ifFalse: [view highlightFrom: (oldLimit+1 max: view firstShown) to: view lastShown]. ^ true] ifFalse: [^ false]! ! ListView subclass: #PluggableListView instanceVariableNames: 'getListSelector getSelectionSelector setSelectionSelector getMenuSelector getMenuTitleSelector keystrokeActionSelector autoDeselect items' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableListView commentStamp: '<historical>' prior: 0! A pluggable list view gets its content from the model. This allows the same kind of view to be used in different situations, thus avoiding a proliferation of gratuitous view and controller classes. Selector usage is: getListSel fetch the list of items (strings) to be displayed getSelectionSel get the currently selected item setSelectionSel set the currently selected item (takes an argument) getMenuSel get the pane-specific, 'yellow-button' menu keyActionSel process a keystroke typed in this pane (takes an argument) Any of the above selectors can be nil, meaning that the model does not supply behavior for the given action, and the default behavior should be used. However, if getListSel is nil, the default behavior just provides an empty list, which makes for a rather dull list view!! The model informs a pluggable view of changes by sending #changed: to itself with getListSel or getSelectionSel as a parameter. The view informs the model of selection changes by sending setSelectionSel to it with the newly selected item as a parameter, and invokes menu and keyboard actions on the model via getMenuSel and keyActionSel. Pluggability allows a single model object to have pluggable list views on multiple aspects of itself. For example, an object representing one personal music library might be organized as a three-level hierarchy: the types of music, the titles within a given type, and the songs on a given title. Pluggability allows one to easily build a multipane browser for this object with separate list views for the music type, title, and song. AutoDeselect is a feature, normally set to true, that will tell the model that there is no selection if you click on an item that is currently selected. If autoDeselect is false, then the model will simply be told to select the same item again.! !PluggableListView methodsFor: 'initialization' stamp: 'di 4/10/98 09:56'! autoDeselect: trueOrFalse "Enable/disable autoDeselect (see class comment)" autoDeselect _ trueOrFalse.! ! !PluggableListView methodsFor: 'initialization' stamp: 'jm 9/20/1998 19:48'! font: aFontOrNil super font: aFontOrNil. self list: self getList. "update display" ! ! !PluggableListView methodsFor: 'initialization' stamp: 'di 6/20/2001 09:58'! list: arrayOfStrings "Set the receivers items to be the given list of strings The instance variable 'items' holds the original list. The instance variable 'list' is a paragraph constructed from this list." ((items == arrayOfStrings) "fastest" or: [items = arrayOfStrings]) ifTrue: [^ self]. items _ arrayOfStrings. isEmpty _ arrayOfStrings isEmpty. "add top and bottom delimiters" list _ ListParagraph withArray: (Array streamContents: [:s | s nextPut: topDelimiter. arrayOfStrings do: [:item | item == nil ifFalse: [(item isMemberOf: MethodReference) "A very specific fix for MVC" ifTrue: [s nextPut: item asStringOrText] ifFalse: [s nextPut: item]]]. s nextPut: bottomDelimiter]) style: self assuredTextStyle. selection _ self getCurrentSelectionIndex. self positionList.! ! !PluggableListView methodsFor: 'initialization' stamp: 'tk 4/12/1998 08:25'! menu: getMenuSel getMenuSelector _ getMenuSel! ! !PluggableListView methodsFor: 'initialization' stamp: 'sw 8/18/1998 12:04'! menuTitleSelector: getMenuTitleSel getMenuTitleSelector _ getMenuTitleSel! ! !PluggableListView methodsFor: 'initialization' stamp: 'di 4/10/98 09:55'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel self model: anObject. getListSelector _ getListSel. getSelectionSelector _ getSelectionSel. setSelectionSelector _ setSelectionSel. getMenuSelector _ getMenuSel. keystrokeActionSelector _ keyActionSel. autoDeselect _ true. self borderWidth: 1. self list: self getList.! ! !PluggableListView methodsFor: 'model access' stamp: 'di 5/6/1998 20:52'! changeModelSelection: anInteger "Change the model's selected item index to be anInteger." | newIndex | newIndex _ anInteger. (autoDeselect == nil or: [autoDeselect]) ifTrue: [getSelectionSelector ifNotNil: [(model perform: getSelectionSelector) = anInteger ifTrue: ["Click on existing selection deselects" newIndex _ 0]]]. setSelectionSelector ifNotNil: [model perform: setSelectionSelector with: newIndex].! ! !PluggableListView methodsFor: 'model access' stamp: 'di 5/6/1998 20:52'! getCurrentSelectionIndex "Answer the index of the current selection." getSelectionSelector == nil ifTrue: [^ 0]. ^ model perform: getSelectionSelector! ! !PluggableListView methodsFor: 'model access'! getList "Answer the list to be displayed." | lst | getListSelector == nil ifTrue: [^ #()]. lst _ model perform: getListSelector. lst == nil ifTrue: [^ #()]. ^ lst! ! !PluggableListView methodsFor: 'model access' stamp: 'tk 4/2/98 13:36'! getListSelector ^ getListSelector! ! !PluggableListView methodsFor: 'model access' stamp: 'sw 8/18/1998 12:07'! getMenu: shiftKeyDown "Answer the menu for this text view, supplying an empty menu to be filled in. If the menu selector takes an extra argument, pass in the current state of the shift key." | menu aMenu | getMenuSelector == nil ifTrue: [^ nil]. menu _ CustomMenu new. getMenuSelector numArgs = 1 ifTrue: [aMenu _ model perform: getMenuSelector with: menu. getMenuTitleSelector ifNotNil: [aMenu title: (model perform: getMenuTitleSelector)]. ^ aMenu]. getMenuSelector numArgs = 2 ifTrue: [aMenu _ model perform: getMenuSelector with: menu with: shiftKeyDown. getMenuTitleSelector ifNotNil: [aMenu title: (model perform: getMenuTitleSelector)]. ^ aMenu]. ^ self error: 'The getMenuSelector must be a 1- or 2-keyword symbol'! ! !PluggableListView methodsFor: 'model access' stamp: 'tk 4/21/1998 08:26'! handleKeystroke: aCharacter "Answer the menu for this list view." | args | keystrokeActionSelector == nil ifTrue: [^ nil]. controller controlTerminate. (args _ keystrokeActionSelector numArgs) = 1 ifTrue: [model perform: keystrokeActionSelector with: aCharacter. ^ controller controlInitialize]. args = 2 ifTrue: [model perform: keystrokeActionSelector with: aCharacter with: self. ^ controller controlInitialize]. ^ self error: 'The keystrokeActionSelector must be a 1- or 2-keyword symbol'! ! !PluggableListView methodsFor: 'model access' stamp: 'sw 10/9/1998 08:24'! setSelectionSelectorIs: aSelector ^ aSelector == setSelectionSelector! ! !PluggableListView methodsFor: 'controller access' stamp: 'jm 3/11/98 17:17'! defaultControllerClass ^ PluggableListController ! ! !PluggableListView methodsFor: 'updating' stamp: 'di 5/25/1998 10:24'! update: aSymbol "Refer to the comment in View|update:." aSymbol == getListSelector ifTrue: [self list: self getList. self displayView. self displaySelectionBox. ^self]. aSymbol == getSelectionSelector ifTrue: [^ self moveSelectionBox: self getCurrentSelectionIndex]. ! ! !PluggableListView methodsFor: 'updating' stamp: 'BG 1/22/2004 13:15'! verifyContents | newItems existingSelection anIndex | "Called on window reactivation to react to possible structural changes. Update contents if necessary." newItems _ self getList. ((items == newItems) "fastest" or: [items = newItems]) ifTrue: [^ self]. self flash. "list has changed beneath us; could get annoying, but hell" existingSelection _ list stringAtLineNumber: (selection + (topDelimiter ifNil: [0] ifNotNil: [1])). "account for cursed ------ row" self list: newItems. (newItems size > 0 and: [newItems first isKindOf: Symbol]) ifTrue: [existingSelection _ existingSelection asSymbol]. (anIndex _ newItems indexOf: existingSelection ifAbsent: [nil]) ifNotNil: [model noteSelectionIndex: anIndex for: getListSelector.] ifNil: [self changeModelSelection: 0]. selection := 0. " to display the list without selection " self displayView. self update: getSelectionSelector. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PluggableListView class instanceVariableNames: ''! !PluggableListView class methodsFor: 'instance creation' stamp: 'tk 4/17/1998 20:41'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self new on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: nil keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'tk 4/17/1998 20:41'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self new on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self new on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel ! ! PluggableListView subclass: #PluggableListViewByItem instanceVariableNames: 'itemList' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableListViewByItem methodsFor: 'as yet unclassified' stamp: 'di 5/6/1998 16:28'! changeModelSelection: anInteger "Change the model's selected item to be the one at the given index." | item | setSelectionSelector ifNotNil: [ item _ (anInteger = 0 ifTrue: [nil] ifFalse: [itemList at: anInteger]). model perform: setSelectionSelector with: item]. ! ! !PluggableListViewByItem methodsFor: 'as yet unclassified' stamp: 'di 5/6/1998 16:27'! getCurrentSelectionIndex "Answer the index of the current selection." | item | getSelectionSelector == nil ifTrue: [^ 0]. item _ model perform: getSelectionSelector. ^ itemList findFirst: [ :x | x = item] ! ! !PluggableListViewByItem methodsFor: 'as yet unclassified' stamp: 'sw 12/9/1999 18:07'! list: arrayOfStrings "Set the receivers items to be the given list of strings." "Note: the instance variable 'items' holds the original list. The instance variable 'list' is a paragraph constructed from this list." itemList _ arrayOfStrings. isEmpty _ arrayOfStrings isEmpty. "add top and bottom delimiters" list _ ListParagraph withArray: (Array streamContents: [:s | s nextPut: topDelimiter. arrayOfStrings do: [:item | item == nil ifFalse: [s nextPut: item]]. s nextPut: bottomDelimiter]) style: self assuredTextStyle. selection _ self getCurrentSelectionIndex. self positionList.! ! PluggableListView subclass: #PluggableListViewOfMany instanceVariableNames: 'getSelectionListSelector setSelectionListSelector' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableListViewOfMany methodsFor: 'displaying' stamp: 'tpr 10/4/2001 21:34'! deEmphasizeView "Refer to the comment in View|deEmphasizeView." selection _ 0. 1 to: self maximumSelection do: [:i | selection _ i. (self listSelectionAt: i) ifTrue: [self deEmphasizeSelectionBox]]. selection _ 0! ! !PluggableListViewOfMany methodsFor: 'displaying' stamp: 'tpr 10/4/2001 21:34'! highlightFrom: start to: stop (start == nil or: [stop == nil]) ifTrue: [^ self displayView]. start to: stop do: [:i | selection _ i. (self listSelectionAt: selection) ifTrue: [self displaySelectionBox]]. selection _ 0! ! !PluggableListViewOfMany methodsFor: 'displaying' stamp: 'tk 4/6/98 20:42'! scrollBy: anInteger "This is a possible way to intercept what ListOfManyController did to get multiple selections to show. Feel to replace this." | ans | ans _ super scrollBy: anInteger. " self displaySelectionBox." ^ ans! ! !PluggableListViewOfMany methodsFor: 'selecting' stamp: 'tpr 10/4/2001 22:17'! listSelectionAt: index getSelectionListSelector ifNil:[^false]. ^model perform: getSelectionListSelector with: index! ! !PluggableListViewOfMany methodsFor: 'selecting' stamp: 'tpr 10/4/2001 22:17'! listSelectionAt: index put: value setSelectionListSelector ifNil:[^false]. ^model perform: setSelectionListSelector with: index with: value! ! !PluggableListViewOfMany methodsFor: 'selecting' stamp: 'tk 4/6/98 15:43'! moveSelectionBox: anInteger "Presumably the selection has changed to be anInteger. Deselect the previous selection and display the new one, highlighted." selection ~= anInteger ifTrue: [selection _ anInteger. self displaySelectionBox]! ! !PluggableListViewOfMany methodsFor: 'selecting' stamp: 'tk 4/6/98 15:43'! selection "Have to override normal controller smarts about deselection" ^ 0! ! !PluggableListViewOfMany methodsFor: 'updating' stamp: 'tk 4/8/98 13:12'! update: aSymbol aSymbol == getListSelector ifTrue: [self list: self getList. ^ self displayView; emphasizeView]. aSymbol == getSelectionSelector ifTrue: [^ self displayView; emphasizeView]. aSymbol == #allSelections ifTrue: [^ self displayView; emphasizeView]. ^ super update: aSymbol! ! !PluggableListViewOfMany methodsFor: 'controller access' stamp: 'di 5/17/1998 22:48'! defaultControllerClass ^ PluggableListControllerOfMany ! ! !PluggableListViewOfMany methodsFor: 'initialization' stamp: 'tpr 10/8/2001 20:53'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel "setup a whole load of pluggability options" getSelectionListSelector _ getListSel. setSelectionListSelector _ setListSel. super on: anObject list: listSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PluggableListViewOfMany class instanceVariableNames: ''! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'tpr 10/8/2001 20:53'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel ^ self new on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: #arrowKey:from: "default"! ! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'tpr 10/8/2001 20:52'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel ^ self new on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel! ! Set subclass: #PluggableSet instanceVariableNames: 'hashBlock equalBlock' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !PluggableSet commentStamp: '<historical>' prior: 0! PluggableSets allow the redefinition of hashing and equality by clients. This is in particular useful if the clients know about specific properties of the objects stored in the set which in turn can heavily improve the performance of sets and dictionaries. Instance variables: hashBlock <BlockContext> A one argument block used for hashing the elements. equalBlock <BlockContext> A two argument block used for comparing the elements. Example: Adding 1000 integer points in the range (0@0) to: (100@100) to a set. | rnd set max pt | set _ Set new: 1000. rnd _ Random new. max _ 100. Time millisecondsToRun:[ 1 to: 1000 do:[:i| pt _ (rnd next * max) truncated @ (rnd next * max) truncated. set add: pt. ]. ]. The above is way slow since the default hashing function of points leads to an awful lot of collisions in the set. And now the same, with a somewhat different hash function: | rnd set max pt | set _ PluggableSet new: 1000. set hashBlock:[:item| (item x bitShift: 16) + item y]. rnd _ Random new. max _ 100. Time millisecondsToRun:[ 1 to: 1000 do:[:i| pt _ (rnd next * max) truncated @ (rnd next * max) truncated. set add: pt. ]. ]. ! !PluggableSet methodsFor: 'accessing' stamp: 'ar 11/12/1998 18:43'! equalBlock "Return the block used for comparing the elements in the receiver." ^equalBlock! ! !PluggableSet methodsFor: 'accessing' stamp: 'ar 11/27/1998 23:55'! equalBlock: aBlock "Set a new equality block. The block must accept two arguments and return true if the argumets are considered equal, false otherwise" equalBlock _ aBlock.! ! !PluggableSet methodsFor: 'accessing' stamp: 'ar 11/12/1998 18:43'! hashBlock "Return the block used for hashing the elements in the receiver." ^hashBlock! ! !PluggableSet methodsFor: 'accessing' stamp: 'ar 11/12/1998 19:02'! hashBlock: aBlock "Set a new hash block. The block must accept one argument and return the hash value of the given argument." hashBlock _ aBlock.! ! !PluggableSet methodsFor: 'copying' stamp: 'ar 11/12/1998 18:47'! copy ^super copy postCopyBlocks! ! !PluggableSet methodsFor: 'copying' stamp: 'dvf 6/10/2000 19:34'! postCopyBlocks hashBlock _ hashBlock copy. equalBlock _ equalBlock copy. "Fix temps in case we're referring to outside stuff" hashBlock ifNotNil: [hashBlock fixTemps]. equalBlock ifNotNil: [equalBlock fixTemps]! ! !PluggableSet methodsFor: 'private' stamp: 'dvf 6/11/2000 00:54'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (hashBlock ifNil: [anObject hash] ifNotNil: [hashBlock value: anObject]) \\ array size + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [equalBlock ifNil: [element = anObject] ifNotNil: [equalBlock value: element value: anObject]]) ifTrue: [^ index]]. "Search from 1 to where we started." 1 to: start - 1 do: [:index | ((element _ array at: index) == nil or: [equalBlock ifNil: [element = anObject] ifNotNil: [equalBlock value: element value: anObject]]) ifTrue: [^ index]]. ^ 0"No match AND no empty slot"! ! StringHolderController subclass: #PluggableTextController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableTextController methodsFor: 'transcript' stamp: 'di 6/3/1998 20:46'! appendEntry "Append the text in the model's writeStream to the editable text. " self deselect. paragraph text size > model characterLimit ifTrue: ["Knock off first half of text" self selectInvisiblyFrom: 1 to: paragraph text size // 2. self replaceSelectionWith: Text new]. self selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size. self replaceSelectionWith: model contents asText. self selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size! ! !PluggableTextController methodsFor: 'transcript' stamp: 'sma 3/15/2000 21:39'! bsText self changeText: (self text copyFrom: 1 to: (self text size - 1 max: 0))! ! !PluggableTextController methodsFor: 'transcript' stamp: 'di 5/13/1998 14:16'! changeText: aText "The paragraph to be edited is changed to aText." paragraph text: aText. self resetState. self selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size. self selectAndScroll. self deselect! ! !PluggableTextController methodsFor: 'transcript' stamp: 'di 6/3/1998 20:42'! doOccluded: actionBlock | paneRect rectSet bottomStrip | paneRect _ paragraph clippingRectangle. paragraph withClippingRectangle: (paneRect withHeight: 0) do: [actionBlock value. self scrollIn: paneRect]. view topView isCollapsed ifTrue: [^ self]. rectSet _ self visibleAreas. bottomStrip _ paneRect withTop: paragraph compositionRectangle bottom + 1. rectSet do: [:rect | (bottomStrip intersects: rect) ifTrue: ["The subsequent displayOn should clear this strip but it doesnt" Display fill: (bottomStrip intersect: rect) fillColor: paragraph backgroundColor]. paragraph withClippingRectangle: rect do: [paragraph displayOn: Display]]! ! !PluggableTextController methodsFor: 'transcript' stamp: 'th 9/20/2002 11:26'! scrollIn: scrollRect "Altered from selectAndScroll so can use with null clipRect" "Scroll until the selection is in the view and then highlight it." | deltaY | deltaY _ self stopBlock top - scrollRect top. deltaY >= 0 ifTrue: [deltaY _ self stopBlock bottom - scrollRect bottom max: 0]. "check if stopIndex below bottom of scrollRect" deltaY ~= 0 ifTrue: [self scrollBy: (deltaY abs + paragraph lineGrid - 1) * deltaY sign]! ! !PluggableTextController methodsFor: 'transcript' stamp: 'di 5/7/1998 22:23'! visibleAreas "Transcript dependents last controller visibleAreas" | visibleAreas rect remnants myTopController | myTopController _ self view topView controller. visibleAreas _ Array with: view insetDisplayBox. myTopController view uncacheBits. ScheduledControllers scheduledWindowControllers do: [:c | c == myTopController ifTrue: [^ visibleAreas]. rect _ c view windowBox. remnants _ OrderedCollection new. visibleAreas do: [:a | remnants addAll: (a areasOutside: rect)]. visibleAreas _ remnants]. ^ visibleAreas! ! !PluggableTextController methodsFor: 'as yet unclassified' stamp: 'dgd 9/21/2003 17:47'! accept view hasUnacceptedEdits ifFalse: [^ view flash]. view hasEditingConflicts ifTrue: [(self confirm: 'Caution!! This method may have been changed elsewhere since you started editing it here. Accept anyway?' translated) ifFalse: [^ self flash]]. (view setText: paragraph text from: self) ifTrue: [initialText _ paragraph text copy. view ifNotNil: [view hasUnacceptedEdits: false]] . ! ! !PluggableTextController methodsFor: 'as yet unclassified' stamp: 'tk 3/31/98 20:49'! userHasEdited "Note that the user has edited my text." view hasUnacceptedEdits: true! ! !PluggableTextController methodsFor: 'as yet unclassified' stamp: 'tk 3/31/98 20:49'! userHasNotEdited "Note that my text is free of user edits." view hasUnacceptedEdits: false! ! !PluggableTextController methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:37'! selectForTopFrom: start to: stop "Deselect, then select the specified characters inclusive. Be sure the selection is in view." self selectFrom: start to: stop scroll: #selectAndScrollToTop! ! !PluggableTextController methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:37'! selectFrom: start to: stop "Deselect, then select the specified characters inclusive. Be sure the selection is in view." self selectFrom: start to: stop scroll: #selectAndScroll! ! !PluggableTextController methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:35'! selectFrom: start to: stop scroll: scrollCommand "Deselect, then select the specified characters inclusive. Be sure the selection is in view." (start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse: [view superView ifNotNil: [self deselect]. self selectInvisiblyFrom: start to: stop]. view superView ifNotNil: [self perform: scrollCommand]! ! StringHolderView subclass: #PluggableTextView instanceVariableNames: 'getTextSelector setTextSelector getSelectionSelector getMenuSelector hasEditingConflicts' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !PluggableTextView commentStamp: '<historical>' prior: 0! A PluggableTextView gets its content from the model. This allows the same kind of view to be used in different situations, thus avoiding a proliferation of gratuitous view and controller classes. See the class comment for PluggableListView. Selectors are: getTextSel fetch the original text from the model setTextSel submit new text to the model when user "accepts" getSelectionSel get the current text selection range getMenuSel get the pane-specific, 'yellow-button' menu Any of the above selectors can be nil, meaning that the model does not supply behavior for the given action, and the default behavior should be used. For example, if setTextSel is nil then this view is consider read-only. The model informs a pluggable view of changes by sending #changed: to itself with getTextSel as a parameter. The view informs the model of selection changes by sending setTextSel to it with the newly selected item as a parameter, and invokes menu actions on the model via getMenuSel. ! !PluggableTextView methodsFor: 'initialization' stamp: 'jm 3/29/98 07:24'! defaultControllerClass ^ PluggableTextController ! ! !PluggableTextView methodsFor: 'initialization' stamp: 'sw 10/29/1999 21:02'! initialize super initialize. hasEditingConflicts _ false! ! !PluggableTextView methodsFor: 'initialization' stamp: 'tk 4/6/98 10:51'! on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel self model: anObject. getTextSelector _ getTextSel. setTextSelector _ setTextSel. getSelectionSelector _ getSelectionSel. getMenuSelector _ getMenuSel. self borderWidth: 1. self editString: self getText. self setSelection: self getSelection. ! ! !PluggableTextView methodsFor: 'initialization' stamp: 'jm 3/29/98 07:25'! setSelection: sel controller selectFrom: sel first to: sel last. ! ! !PluggableTextView methodsFor: 'model access' stamp: 'di 6/26/1998 11:06'! getMenu: shiftKeyDown "Answer the menu for this text view, supplying an empty menu to be filled in. If the menu selector takes an extra argument, pass in the current state of the shift key." | menu | getMenuSelector == nil ifTrue: [^ nil]. menu _ CustomMenu new. getMenuSelector numArgs = 1 ifTrue: [^ model perform: getMenuSelector with: menu]. getMenuSelector numArgs = 2 ifTrue: [^ model perform: getMenuSelector with: menu with: shiftKeyDown]. ^ self error: 'The getMenuSelector must be a 1- or 2-keyword symbol'! ! !PluggableTextView methodsFor: 'model access' stamp: 'sw 1/16/1999 14:31'! getSelection "Answer the model's selection interval." getSelectionSelector == nil ifTrue: [^ 1 to: 0]. "null selection" ^ getSelectionSelector ifNotNil: [model perform: getSelectionSelector] ! ! !PluggableTextView methodsFor: 'model access' stamp: 'tk 4/1/98 08:32'! getText "Answer the list to be displayed." | txt | getTextSelector == nil ifTrue: [^ Text new]. txt _ model perform: getTextSelector. txt == nil ifTrue: [^ Text new]. self hasUnacceptedEdits: false. "clean now" ^ txt! ! !PluggableTextView methodsFor: 'model access' stamp: 'tk 3/31/98 15:58'! getTextSelector "This is sent to the model to find out what text to display" ^ getTextSelector! ! !PluggableTextView methodsFor: 'model access' stamp: 'jm 5/3/1998 19:29'! isReadOnlyView ^ setTextSelector == nil ! ! !PluggableTextView methodsFor: 'model access' stamp: 'jm 8/20/1998 11:55'! model: aLockedModel "Refer to the comment in View|model:." self model: aLockedModel controller: controller. self editString: self getText. ! ! !PluggableTextView methodsFor: 'model access' stamp: 'di 3/10/98 13:51'! setText: textToAccept from: ctlr "Inform the model of text to be accepted, and return true if OK. Any errors should be reported to the controller, ctlr." setTextSelector == nil ifTrue: [^ true]. setTextSelector numArgs = 2 ifTrue: [^ model perform: setTextSelector with: textToAccept with: ctlr] ifFalse: [^ model perform: setTextSelector with: textToAccept]! ! !PluggableTextView methodsFor: 'model access' stamp: 'di 4/27/1998 12:46'! updateDisplayContents self editString: self getText. self displayView. self setSelection: self getSelection. ! ! !PluggableTextView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:03'! hasEditingConflicts "Return true if a conflicting edit to the same code (typically) is known to have occurred after the current contents started getting edited" ^ hasEditingConflicts == true! ! !PluggableTextView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:04'! hasEditingConflicts: aBoolean hasEditingConflicts _ aBoolean! ! !PluggableTextView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:04'! hasUnacceptedEdits: aBoolean super hasUnacceptedEdits: aBoolean. aBoolean ifFalse: [hasEditingConflicts _ false]! ! !PluggableTextView methodsFor: 'updating' stamp: 'tk 5/23/2001 12:26'! update: aSymbol "Refer to the comment in View|update:. Do nothing if the given symbol does not match any action. " aSymbol == #wantToChange ifTrue: [self canDiscardEdits ifFalse: [self promptForCancel]. ^ self]. aSymbol == #flash ifTrue: [^ controller flash]. aSymbol == getTextSelector ifTrue: [^ self updateDisplayContents]. aSymbol == getSelectionSelector ifTrue: [^ self setSelection: self getSelection]. aSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false]. (aSymbol == #autoSelect and: [getSelectionSelector ~~ nil]) ifTrue: [ParagraphEditor abandonChangeText. "no replacement!!" ^ controller setSearch: model autoSelectString; againOrSame: true]. aSymbol == #appendEntry ifTrue: [^ controller doOccluded: [controller appendEntry]]. aSymbol == #clearText ifTrue: [^ controller doOccluded: [controller changeText: Text new]]. aSymbol == #bs ifTrue: [^ controller doOccluded: [controller bsText]]. aSymbol == #codeChangedElsewhere ifTrue: [^ self hasEditingConflicts: true] ! ! !PluggableTextView methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:48'! convertToCurrentVersion: varDict refStream: smartRefStrm hasEditingConflicts ifNil: [hasEditingConflicts _ false]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! !PluggableTextView methodsFor: 'controller access' stamp: 'BG 11/26/2003 16:06'! selectionInterval ^self controller selectionInterval! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PluggableTextView class instanceVariableNames: ''! !PluggableTextView class methodsFor: 'instance creation' stamp: 'jm 3/29/98 07:24'! on: anObject text: getTextSel accept: setTextSel ^ self on: anObject text: getTextSel accept: setTextSel readSelection: nil menu: nil ! ! !PluggableTextView class methodsFor: 'instance creation' stamp: 'jm 3/29/98 07:24'! on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel ^ self new on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel ! ! Object subclass: #Point instanceVariableNames: 'x y' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Point commentStamp: '<historical>' prior: 0! I represent an x-y pair of numbers usually designating a location on the screen.! !Point methodsFor: 'accessing'! x "Answer the x coordinate." ^x! ! !Point methodsFor: 'accessing'! y "Answer the y coordinate." ^y! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:01'! * arg "Answer a Point that is the product of the receiver and arg." arg isPoint ifTrue: [^ (x * arg x) @ (y * arg y)]. ^ arg adaptToPoint: self andSend: #*! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:01'! + arg "Answer a Point that is the sum of the receiver and arg." arg isPoint ifTrue: [^ (x + arg x) @ (y + arg y)]. ^ arg adaptToPoint: self andSend: #+! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:02'! - arg "Answer a Point that is the difference of the receiver and arg." arg isPoint ifTrue: [^ (x - arg x) @ (y - arg y)]. ^ arg adaptToPoint: self andSend: #-! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:02'! / arg "Answer a Point that is the quotient of the receiver and arg." arg isPoint ifTrue: [^ (x / arg x) @ (y / arg y)]. ^ arg adaptToPoint: self andSend: #/! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:02'! // arg "Answer a Point that is the quotient of the receiver and arg." arg isPoint ifTrue: [^ (x // arg x) @ (y // arg y)]. ^ arg adaptToPoint: self andSend: #//! ! !Point methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:02'! \\ arg "Answer a Point that is the mod of the receiver and arg." arg isPoint ifTrue: [^ (x \\ arg x) @ (y \\ arg y)]. ^ arg adaptToPoint: self andSend: #\\! ! !Point methodsFor: 'arithmetic'! abs "Answer a Point whose x and y are the absolute values of the receiver's x and y." ^ x abs @ y abs! ! !Point methodsFor: 'comparing'! < aPoint "Answer whether the receiver is above and to the left of aPoint." ^x < aPoint x and: [y < aPoint y]! ! !Point methodsFor: 'comparing'! <= aPoint "Answer whether the receiver is neither below nor to the right of aPoint." ^x <= aPoint x and: [y <= aPoint y]! ! !Point methodsFor: 'comparing'! = aPoint self species = aPoint species ifTrue: [^x = aPoint "Refer to the comment in Object|=." x and: [y = aPoint y]] ifFalse: [^false]! ! !Point methodsFor: 'comparing'! > aPoint "Answer whether the receiver is below and to the right of aPoint." ^x > aPoint x and: [y > aPoint y]! ! !Point methodsFor: 'comparing'! >= aPoint "Answer whether the receiver is neither above nor to the left of aPoint." ^x >= aPoint x and: [y >= aPoint y]! ! !Point methodsFor: 'comparing' stamp: 'SqR 11/3/2000 17:08'! hash "Hash is reimplemented because = is implemented." ^(x hash hashMultiply + y hash) hashMultiply! ! !Point methodsFor: 'comparing'! hashMappedBy: map "My hash is independent of my oop." ^self hash! ! !Point methodsFor: 'comparing'! max: aPoint "Answer the lower right corner of the rectangle uniquely defined by the receiver and the argument, aPoint." ^ (x max: aPoint x) @ (y max: aPoint y)! ! !Point methodsFor: 'comparing'! min: aPoint "Answer the upper left corner of the rectangle uniquely defined by the receiver and the argument, aPoint." ^ (x min: aPoint x) @ (y min: aPoint y)! ! !Point methodsFor: 'comparing'! min: aMin max: aMax ^ (self min: aMin) max: aMax! ! !Point methodsFor: 'converting' stamp: 'di 11/6/1998 13:45'! adaptToCollection: rcvr andSend: selector "If I am involved in arithmetic with a Collection, return a Collection of the results of each element combined with me in that expression." ^ rcvr collect: [:element | element perform: selector with: self]! ! !Point methodsFor: 'converting' stamp: 'di 11/9/1998 12:44'! adaptToNumber: rcvr andSend: selector "If I am involved in arithmetic with an Integer, convert it to a Point." ^ rcvr@rcvr perform: selector with: self! ! !Point methodsFor: 'converting' stamp: 'di 11/6/1998 13:47'! adaptToString: rcvr andSend: selector "If I am involved in arithmetic with a String, convert it to a Number." ^ rcvr asNumber perform: selector with: self! ! !Point methodsFor: 'converting'! asFloatPoint ^ x asFloat @ y asFloat! ! !Point methodsFor: 'converting'! asIntegerPoint ^ x asInteger @ y asInteger! ! !Point methodsFor: 'converting'! asPoint "Answer the receiver itself." ^self! ! !Point methodsFor: 'converting'! corner: aPoint "Answer a Rectangle whose origin is the receiver and whose corner is aPoint. This is one of the infix ways of expressing the creation of a rectangle." ^Rectangle origin: self corner: aPoint! ! !Point methodsFor: 'converting'! extent: aPoint "Answer a Rectangle whose origin is the receiver and whose extent is aPoint. This is one of the infix ways of expressing the creation of a rectangle." ^Rectangle origin: self extent: aPoint! ! !Point methodsFor: 'converting' stamp: 'di 11/6/1998 07:45'! isPoint ^ true! ! !Point methodsFor: 'converting' stamp: 'di 12/3/97 19:00'! rect: aPoint "Answer a Rectangle that encompasses the receiver and aPoint. This is the most general infix way to create a rectangle." ^ Rectangle origin: (self min: aPoint) corner: (self max: aPoint)! ! !Point methodsFor: 'copying'! deepCopy "Implemented here for better performance." ^x deepCopy @ y deepCopy! ! !Point methodsFor: 'copying' stamp: 'tk 8/19/1998 16:05'! veryDeepCopyWith: deepCopier "Return self. I am immutable in the Morphic world. Do not record me."! ! !Point methodsFor: 'geometry' stamp: 'laza 1/24/2000 03:44'! isInsideCircle: a with: b with: c "Returns TRUE if self is inside the circle defined by the points a, b, c. See Guibas and Stolfi (1985) p.107" ^ (a dotProduct: a) * (b triangleArea: c with: self) - ((b dotProduct: b) * (a triangleArea: c with: self)) + ((c dotProduct: c) * (a triangleArea: b with: self)) - ((self dotProduct: self) * (a triangleArea: b with: c)) > 0.0! ! !Point methodsFor: 'geometry' stamp: 'laza 1/6/2000 10:30'! sideOf: otherPoint "Returns #left, #right or #center if the otherPoint lies to the left, right or on the line given by the vector from 0@0 to self" | side | side _ (self crossProduct: otherPoint) sign. ^ {#right. #center. #left} at: side + 2 ! ! !Point methodsFor: 'geometry' stamp: 'ar 4/6/2000 18:37'! to: end1 intersects: start2 to: end2 "Returns true if the linesegment from start1 (=self) to end1 intersects with the segment from start2 to end2, otherwise false." | start1 sideStart sideEnd | start1 _ self. (((start1 = start2 or: [end1 = end2]) or: [start1 = end2]) or: [start2 = end1]) ifTrue: [^ true]. sideStart _ start1 to: end1 sideOf: start2. sideEnd _ start1 to: end1 sideOf: end2. sideStart = sideEnd ifTrue: [^ false]. sideStart _ start2 to: end2 sideOf: start1. sideEnd _ start2 to: end2 sideOf: end1. sideStart = sideEnd ifTrue: [^ false]. ^ true! ! !Point methodsFor: 'geometry' stamp: 'laza 1/5/2000 11:50'! to: end sideOf: otherPoint "Returns #left, #right, #center if the otherPoint lies to the left, right or on the line given by the vector from self to end" ^ end - self sideOf: otherPoint - self! ! !Point methodsFor: 'geometry' stamp: 'laza 1/17/2000 15:47'! triangleArea: b with: c "Returns twice the area of the oriented triangle (a, b, c), i.e., the area is positive if the triangle is oriented counterclockwise" ^ b x - self x * (c y - self y) - (b y - self y * (c x - self x))! ! !Point methodsFor: 'interpolating' stamp: 'jsp 3/22/1999 16:31'! interpolateTo: end at: amountDone "Interpolate between the instance and end after the specified amount has been done (0 - 1)." ^ self + ((end - self) * amountDone).! ! !Point methodsFor: 'point functions' stamp: 'sw 2/15/98 02:27'! bearingToPoint: anotherPoint "Return the bearing, in degrees, from the receiver to anotherPoint. Adapted from Playground, where the ultimate provenance of the algorithm was a wild earlier method of Jay Fenton's which I never checked carefully, but the thing has always seemed to work" | deltaX deltaY | deltaX := anotherPoint x - x. deltaY := anotherPoint y - y. deltaX abs < 0.001 ifTrue: [^ deltaY > 0 ifTrue: [180] ifFalse: [0]]. ^ ((deltaX >= 0 ifTrue: [90] ifFalse: [270]) - ((deltaY / deltaX) arcTan negated * 57.2957795131)) rounded ! ! !Point methodsFor: 'point functions' stamp: 'ar 10/30/1998 03:05'! crossProduct: aPoint "Answer a number that is the cross product of the receiver and the argument, aPoint." ^ (x * aPoint y) - (y * aPoint x)! ! !Point methodsFor: 'point functions'! dist: aPoint "Answer the distance between aPoint and the receiver." ^(aPoint - self) r! ! !Point methodsFor: 'point functions' stamp: 'di 9/11/1998 16:22'! dotProduct: aPoint "Answer a number that is the dot product of the receiver and the argument, aPoint. That is, the two points are multipled and the coordinates of the result summed." ^ (x * aPoint x) + (y * aPoint y)! ! !Point methodsFor: 'point functions'! eightNeighbors ^ (Array with: self + (1@0) with: self + (1@1) with: self + (0@1) with: self + (-1@1)) , (Array with: self + (-1@0) with: self + (-1@-1) with: self + (0@-1) with: self + (1@-1)) ! ! !Point methodsFor: 'point functions' stamp: 'di 6/11/97 16:08'! flipBy: direction centerAt: c "Answer a Point which is flipped according to the direction about the point c. Direction must be #vertical or #horizontal." direction == #vertical ifTrue: [^ x @ (c y * 2 - y)]. direction == #horizontal ifTrue: [^ (c x * 2 - x) @ y]. self error: 'unrecognizable direction'! ! !Point methodsFor: 'point functions'! fourNeighbors ^ Array with: self + (1@0) with: self + (0@1) with: self + (-1@0) with: self + (0@-1) ! ! !Point methodsFor: 'point functions'! grid: aPoint "Answer a Point to the nearest rounded grid modules specified by aPoint." | newX newY | newX _ x + (aPoint x // 2) truncateTo: aPoint x. newY _ y + (aPoint y // 2) truncateTo: aPoint y. ^newX @ newY! ! !Point methodsFor: 'point functions' stamp: 'ar 5/22/2001 23:46'! insideTriangle: p1 with: p2 with: p3 "Return true if the receiver is within the triangle defined by the three coordinates. Note: This method computes the barycentric coordinates for the receiver and tests those coordinates." | p0 b0 b1 b2 b3 | p0 _ self. b0 _ ((p2 x - p1 x) * (p3 y - p1 y)) - ((p3 x - p1 x) * (p2 y - p1 y)). b0 isZero ifTrue:[^false]. "degenerate" b0 _ 1.0 / b0. b1 _ (((p2 x - p0 x) * (p3 y - p0 y)) - ((p3 x - p0 x) * (p2 y - p0 y))) * b0. b2 _ (((p3 x - p0 x) * (p1 y - p0 y)) - ((p1 x - p0 x) * (p3 y - p0 y))) * b0. b3 _ (((p1 x - p0 x) * (p2 y - p0 y)) - ((p2 x - p0 x) * (p1 y - p0 y))) * b0. b1 < 0.0 ifTrue:[^false]. b2 < 0.0 ifTrue:[^false]. b3 < 0.0 ifTrue:[^false]. ^true ! ! !Point methodsFor: 'point functions' stamp: 'di 12/1/97 12:37'! nearestPointAlongLineFrom: p1 to: p2 "Note this will give points beyond the endpoints. Streamlined by Gerardo Richarte 11/3/97" | x21 y21 t x1 y1 | p1 x = p2 x ifTrue: [^ p1 x @ y]. p1 y = p2 y ifTrue: [^ x @ p1 y]. x1 _ p1 x asFloat. y1 _ p1 y asFloat. x21 _ p2 x asFloat - x1. y21 _ p2 y asFloat - y1. t _ ((y asFloat - y1 / x21) + (x asFloat - x1 / y21)) / ((x21 / y21) + (y21 / x21)). ^ (x1 + (t * x21)) @ (y1 + (t * y21)) " | old new | Pen new place: 200@100; goto: (old _ 500@300). Display reverse: (old extent: 10@10). [Sensor anyButtonPressed] whileFalse: [(new _ (Sensor cursorPoint nearestPointAlongLineFrom: 200@100 to: 500@300) ) = old ifFalse: [Display reverse: (old extent: 10@10). Display reverse: ((old _ new) extent: 10@10)]] " ! ! !Point methodsFor: 'point functions' stamp: 'di 12/1/97 12:40'! nearestPointOnLineFrom: p1 to: p2 "This will not give points beyond the endpoints" ^ (self nearestPointAlongLineFrom: p1 to: p2) adhereTo: (p1 rect: p2)! ! !Point methodsFor: 'point functions'! normal "Answer a Point representing the unit vector rotated 90 deg clockwise." | n | n _ y negated @ x. ^n / (n x * n x + (n y * n y)) sqrt! ! !Point methodsFor: 'point functions' stamp: 'ar 8/26/2001 22:15'! normalized "Optimized for speed -- ar 8/26/2001" | r | r _ ((x*x) + (y * y)) sqrt. ^(x / r) @ (y / r)! ! !Point methodsFor: 'point functions' stamp: 'laza 12/13/1999 11:43'! octantOf: otherPoint "Return 1..8 indicating relative direction to otherPoint. 1=ESE, 2=SSE, ... etc. clockwise to 8=ENE" "[Sensor anyButtonPressed] whileFalse: [(Display boundingBox center octantOf: Sensor cursorPoint) printString displayAt: 0@0]" | quad moreHoriz | (x = otherPoint x and: [y > otherPoint y]) ifTrue: [^ 6]. "special case" (y = otherPoint y and: [x < otherPoint x]) ifTrue: [^ 8]. quad _ self quadrantOf: otherPoint. moreHoriz _ (x - otherPoint x) abs >= (y - otherPoint y) abs. (quad even eqv: moreHoriz) ifTrue: [^ quad * 2] ifFalse: [^ quad * 2 - 1]! ! !Point methodsFor: 'point functions' stamp: 'di 12/1/97 12:12'! onLineFrom: p1 to: p2 ^ self onLineFrom: p1 to: p2 within: 2! ! !Point methodsFor: 'point functions' stamp: 'jm 2/24/98 08:34'! onLineFrom: p1 to: p2 within: epsilon "Answer true if the receiver lies on the given line segment between p1 and p2 within a small epsilon." "is this point within the box spanning p1 and p2 expanded by epsilon? (optimized)" p1 x < p2 x ifTrue: [ ((x < (p1 x - epsilon)) or: [x > (p2 x + epsilon)]) ifTrue: [^ false]] ifFalse: [ ((x < (p2 x - epsilon)) or: [x > (p1 x + epsilon)]) ifTrue: [^ false]]. p1 y < p2 y ifTrue: [ ((y < (p1 y - epsilon)) or: [y > (p2 y + epsilon)]) ifTrue: [^ false]] ifFalse: [ ((y < (p2 y - epsilon)) or: [y > (p1 y + epsilon)]) ifTrue: [^ false]]. "it's in the box; is it on the line?" ^ (self dist: (self nearestPointAlongLineFrom: p1 to: p2)) <= epsilon! ! !Point methodsFor: 'point functions' stamp: '6/9/97 14:51 di'! quadrantOf: otherPoint "Return 1..4 indicating relative direction to otherPoint. 1 is downRight, 2=downLeft, 3=upLeft, 4=upRight" ^ x <= otherPoint x ifTrue: [y < otherPoint y ifTrue: [1] ifFalse: [4]] ifFalse: [y <= otherPoint y ifTrue: [2] ifFalse: [3]] " [Sensor anyButtonPressed] whileFalse: [(Display boundingBox center quadrantOf: Sensor cursorPoint) printString displayAt: 0@0] "! ! !Point methodsFor: 'point functions' stamp: 'di 6/11/97 15:12'! rotateBy: direction centerAt: c "Answer a Point which is rotated according to direction, about the point c. Direction must be one of #right (CW), #left (CCW) or #pi (180 degrees)." | offset | offset _ self - c. direction == #right ifTrue: [^ (offset y negated @ offset x) + c]. direction == #left ifTrue: [^ (offset y @ offset x negated) + c]. direction == #pi ifTrue: [^ c - offset]. self error: 'unrecognizable direction'! ! !Point methodsFor: 'point functions' stamp: 'ar 4/18/1999 05:17'! sortsBefore: otherPoint "Return true if the receiver sorts before the other point" ^y = otherPoint y ifTrue:[x <= otherPoint x] ifFalse:[y <= otherPoint y]! ! !Point methodsFor: 'point functions' stamp: 'ar 5/23/2001 21:29'! squaredDistanceTo: aPoint "Answer the distance between aPoint and the receiver." | delta | delta _ aPoint - self. ^delta dotProduct: delta! ! !Point methodsFor: 'point functions' stamp: 'ar 11/12/1998 01:44'! transposed ^y@x! ! !Point methodsFor: 'polar coordinates' stamp: 'di 6/12/97 12:18'! degrees "Answer the angle the receiver makes with origin in degrees. right is 0; down is 90." | tan theta | x = 0 ifTrue: [y >= 0 ifTrue: [^ 90.0] ifFalse: [^ 270.0]] ifFalse: [tan _ y asFloat / x asFloat. theta _ tan arcTan. x >= 0 ifTrue: [y >= 0 ifTrue: [^ theta radiansToDegrees] ifFalse: [^ 360.0 + theta radiansToDegrees]] ifFalse: [^ 180.0 + theta radiansToDegrees]]! ! !Point methodsFor: 'polar coordinates'! r "Answer the receiver's radius in polar coordinate system." ^(self dotProduct: self) sqrt! ! !Point methodsFor: 'polar coordinates'! theta "Answer the angle the receiver makes with origin in radians. right is 0; down is 90." | tan theta | x = 0 ifTrue: [y >= 0 ifTrue: [^1.5708"90.0 degreesToRadians"] ifFalse: [^4.71239"270.0 degreesToRadians"]] ifFalse: [tan _ y asFloat / x asFloat. theta _ tan arcTan. x >= 0 ifTrue: [y >= 0 ifTrue: [^theta] ifFalse: [^360.0 degreesToRadians + theta]] ifFalse: [^180.0 degreesToRadians + theta]]! ! !Point methodsFor: 'printing' stamp: 'sw 9/27/2001 17:26'! basicType "Answer a symbol representing the inherent type of the receiver" ^ #Point! ! !Point methodsFor: 'printing'! printOn: aStream "The receiver prints on aStream in terms of infix notation." x printOn: aStream. aStream nextPut: $@. y printOn: aStream! ! !Point methodsFor: 'printing'! storeOn: aStream "x@y printed form is good for storing too" self printOn: aStream! ! !Point methodsFor: 'private' stamp: 'ar 4/4/1999 00:40'! bitShiftPoint: bits x _ x bitShift: bits. y _ y bitShift: bits.! ! !Point methodsFor: 'private' stamp: 'tk 10/4/2001 16:16'! setR: rho degrees: degrees | radians | radians _ degrees asFloat degreesToRadians. x _ rho asFloat * radians cos. y _ rho asFloat * radians sin.! ! !Point methodsFor: 'private' stamp: 'sw 3/21/2000 13:24'! setX: xValue setY: yValue x _ xValue. y _ yValue! ! !Point methodsFor: 'transforming' stamp: 'di 4/30/1998 11:16'! adhereTo: aRectangle "If the receiver lies outside aRectangle, return the nearest point on the boundary of the rectangle, otherwise return self." (aRectangle containsPoint: self) ifTrue: [^ self]. ^ ((x max: aRectangle left) min: aRectangle right) @ ((y max: aRectangle top) min: aRectangle bottom)! ! !Point methodsFor: 'transforming' stamp: 'ar 8/26/2001 22:14'! negated "Answer a point whose x and y coordinates are the negatives of those of the receiver. 6/6/96 sw" "Optimized for speed -- ar 8/26/2001" ^ (0 - x) @ (0 - y)! ! !Point methodsFor: 'transforming'! rotateBy: angle about: center "Even though Point.theta is measured CW, this rotates with the more conventional CCW interpretateion of angle." | p r theta | p _ self - center. r _ p r. theta _ angle asFloat - p theta. ^ (center x asFloat + (r * theta cos)) @ (center y asFloat - (r * theta sin))! ! !Point methodsFor: 'transforming'! scaleBy: factor "Answer a Point scaled by factor (an instance of Point)." ^(factor x * x) @ (factor y * y)! ! !Point methodsFor: 'transforming' stamp: 'di 12/4/97 14:34'! scaleFrom: rect1 to: rect2 "Produce a point stretched according to the stretch from rect1 to rect2" ^ rect2 topLeft + (((x-rect1 left) * rect2 width // rect1 width) @ ((y-rect1 top) * rect2 height // rect1 height))! ! !Point methodsFor: 'transforming'! translateBy: delta "Answer a Point translated by delta (an instance of Point)." ^(delta x + x) @ (delta y + y)! ! !Point methodsFor: 'truncation and round off' stamp: 'jm 6/3/1998 12:21'! rounded "Answer a Point that is the receiver's x and y rounded. Answer the receiver if its coordinates are already integral." (x isInteger and: [y isInteger]) ifTrue: [^ self]. ^ x rounded @ y rounded ! ! !Point methodsFor: 'truncation and round off'! truncateTo: grid "Answer a Point that is the receiver's x and y truncated to grid x and grid y." | gridPoint | gridPoint _ grid asPoint. ^(x truncateTo: gridPoint x) @ (y truncateTo: gridPoint y)! ! !Point methodsFor: 'truncation and round off' stamp: 'jm 5/29/1998 15:53'! truncated "Answer a Point whose x and y coordinates are integers. Answer the receiver if its coordinates are already integral." (x isInteger and: [y isInteger]) ifTrue: [^ self]. ^ x truncated @ y truncated ! ! !Point methodsFor: 'testing' stamp: 'ar 10/29/2000 19:02'! isZero ^x isZero and:[y isZero]! ! !Point methodsFor: '*morphic-Postscript Canvases'! encodePostscriptOn:aStream aStream writePoint:self.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Point class instanceVariableNames: ''! !Point class methodsFor: 'instance creation' stamp: 'sw 9/20/97 15:34'! fromUser Sensor waitNoButton. Cursor crossHair show. Sensor waitButton. Cursor normal show. ^ Sensor cursorPoint "Point fromUser"! ! !Point class methodsFor: 'instance creation' stamp: 'tk 10/4/2001 16:17'! r: rho degrees: degrees "Answer an instance of me with polar coordinates rho and theta." ^self new setR: rho degrees: degrees! ! !Point class methodsFor: 'instance creation'! x: xInteger y: yInteger "Answer an instance of me with coordinates xInteger and yInteger." ^self new setX: xInteger setY: yInteger! ! Model subclass: #PointerFinder instanceVariableNames: 'goal parents toDo toDoNext hasGemStone pointerList objectList parentsSize todoSize depth pointerListIndex' classVariableNames: '' poolDictionaries: '' category: 'Tools-Debugger'! !PointerFinder commentStamp: '<historical>' prior: 0! I can search for reasons why a certain object isn't garbage collected. I'm a quick port of a VisualWorks program written by Hans-Martin Mosner. Call me as shown below. I'll search for a path from a global variable to the given object, presenting it in a small morphic UI. Examples: PointerFinder on: self currentHand PointerFinder on: StandardSystemView someInstance Now, let's see why this image contains more HandMorphs as expected... HandMorph allInstancesDo: [:e | PointerFinder on: e]! !PointerFinder methodsFor: 'application' stamp: 'sma 6/6/2000 18:58'! buildList | list obj parent object key | list := OrderedCollection new. obj := goal. [list addFirst: obj. obj := parents at: obj ifAbsent: []. obj == nil] whileFalse. list removeFirst. parent := Smalltalk. objectList := OrderedCollection new. pointerList := OrderedCollection new. [list isEmpty] whileFalse: [object := list removeFirst. key := nil. (parent isKindOf: Dictionary) ifTrue: [list size >= 2 ifTrue: [key := parent keyAtValue: list second ifAbsent: []. key == nil ifFalse: [object := list removeFirst; removeFirst. pointerList add: key printString , ' -> ' , object class name]]]. key == nil ifTrue: [parent class == object ifTrue: [key := 'CLASS']. key == nil ifTrue: [1 to: parent class instSize do: [:i | key == nil ifTrue: [(parent instVarAt: i) == object ifTrue: [key := parent class allInstVarNames at: i]]]]. key == nil ifTrue: [1 to: parent basicSize do: [:i | key == nil ifTrue: [(parent basicAt: i) == object ifTrue: [key := i printString]]]]. key == nil ifTrue: [(parent isMorph and: [object isKindOf: Array]) ifTrue: [key := 'submorphs?']]. key == nil ifTrue: [key := '???']. pointerList add: key , ': ' , object class name]. objectList add: object. parent := object]! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/6/2000 23:08'! follow: anObject from: parentObject anObject == goal ifTrue: [parents at: anObject put: parentObject. ^ true]. anObject isLiteral ifTrue: [^ false]. anObject class isPointers ifFalse: [^ false]. anObject class isWeak ifTrue: [^ false]. (parents includesKey: anObject) ifTrue: [^ false]. parents at: anObject put: parentObject. toDoNext add: anObject. ^ false! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/6/2000 10:01'! followObject: anObject (self follow: anObject class from: anObject) ifTrue: [^ true]. 1 to: anObject class instSize do: [:i | (self follow: (anObject instVarAt: i) from: anObject) ifTrue: [^ true]]. 1 to: anObject basicSize do: [:i | (self follow: (anObject basicAt: i) from: anObject) ifTrue: [^ true]]. ^ false! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/6/2000 09:52'! goal: anObject goal _ anObject! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/7/2000 00:19'! initialize parents _ IdentityDictionary new: 20000. parents at: Smalltalk put: nil. parents at: Processor put: nil. parents at: self put: nil. toDo _ OrderedCollection new: 5000. toDo add: Smalltalk. toDoNext _ OrderedCollection new: 5000! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/7/2000 00:19'! isLiteral "Horrible hack to omit other Pointer Finders from scanning." ^ true! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/7/2000 00:17'! search Smalltalk garbageCollect. self initialize. Cursor wait showWhile: [ [[toDo isEmpty or: [self followObject: toDo removeFirst]] whileFalse. toDo isEmpty and: [toDoNext isEmpty not]] whileTrue: [toDo _ toDoNext. toDoNext _ OrderedCollection new: 5000]]. self buildList! ! !PointerFinder methodsFor: 'application' stamp: 'sma 6/6/2000 19:10'! update ('done: ' , parents size asString , ' todo: ' , toDo size asString , ' ') displayAt: 0@0! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/7/2000 00:23'! arrowKey: key from: aController key = $i ifTrue: [^ self inspectObject]. ^ super arrowKey: key from: aController! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/6/2000 23:48'! initialExtent ^ 300 @ 300! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'nb 6/17/2003 12:25'! inspectObject pointerListIndex = 0 ifTrue: [^ Beeper beep]. (objectList at: pointerListIndex) inspect! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/7/2000 00:15'! perform: selector orSendTo: otherTarget selector == #inspectObject ifTrue: [^ self inspectObject]. selector == #searchAgain ifTrue: [^ self searchAgain]. ^ super perform: selector orSendTo: otherTarget! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/6/2000 23:49'! pointerList ^ pointerList asArray! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/6/2000 23:27'! pointerListIndex ^ pointerListIndex ifNil: [0]! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/6/2000 23:51'! pointerListIndex: anInteger pointerListIndex _ anInteger. self changed: #pointerListIndex! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'sma 6/7/2000 00:16'! searchAgain self pointerListIndex: 0. self search. self changed: #pointerList! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PointerFinder class instanceVariableNames: ''! !PointerFinder class methodsFor: 'instance creation' stamp: 'sma 6/6/2000 23:52'! on: anObject ^ self new goal: anObject; search; open! ! Object subclass: #PopUpMenu instanceVariableNames: 'labelString font lineArray frame form marker selection' classVariableNames: 'CacheMenuForms MenuStyle' poolDictionaries: '' category: 'Tools-Menus'! !PopUpMenu commentStamp: '<historical>' prior: 0! 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.! !PopUpMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 11:44'! center "Answer the point at the center of the receiver's rectangular area." ^ frame center! ! !PopUpMenu methodsFor: 'accessing' stamp: 'di 4/20/1999 14:33'! frameHeight "Designed to avoid the entire frame computation (includes MVC form), since the menu may well end up being displayed in Morphic anyway." | nItems | frame ifNotNil: [^ frame height]. nItems _ 1 + (labelString occurrencesOf: Character cr). ^ (nItems * MenuStyle lineGrid) + 4 "border width"! ! !PopUpMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 14:55'! labelString ^ labelString! ! !PopUpMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 14:55'! lineArray ^ lineArray! ! !PopUpMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 12:32'! nItems ^ (labelString occurrencesOf: Character cr) + 1! ! !PopUpMenu methodsFor: 'accessing' stamp: 'sw 3/12/2002 21:37'! startUpLeftFlush "Build and invoke this menu with no initial selection. By Jerry Archibald, 4/01. If in MVC, align menus items with the left margin. Answer the selection associated with the menu item chosen by the user or nil if none is chosen. The mechanism for getting left-flush appearance in mvc leaves a tiny possibility for misadventure: if the user, in mvc, puts up the jump-to-project menu, then hits cmd period while it is up, then puts up a second jump-to-project menu before dismissing or proceeding through the debugger, it's possible for mvc popup-menus thereafter to appear left-aligned rather than centered; this very unlikely condition can be cleared by evaluating 'PopUpMenu alignment: 2'" | saveAlignment result | Smalltalk isMorphic ifFalse: [saveAlignment _ PopUpMenu alignment. PopUpMenu leftFlush]. [result _ self startUp] ensure: [Smalltalk isMorphic ifFalse: [PopUpMenu alignment: saveAlignment]]. ^ result! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'sma 6/1/2000 13:04'! controlActivity "Do whatever a menu must do - now with keyboard support." | didNotMove downPos | didNotMove _ true. Sensor anyButtonPressed ifFalse: [didNotMove _ false. Sensor waitButtonOrKeyboard]. Sensor keyboardPressed ifFalse: [self manageMarker]. (didNotMove and: [selection = 0]) ifTrue: [downPos _ Sensor cursorPoint. [didNotMove and: [Sensor anyButtonPressed]] whileTrue: [(downPos dist: Sensor cursorPoint) < 2 ifFalse: [didNotMove _ false]]. didNotMove ifTrue: [Sensor waitButtonOrKeyboard]]. [Sensor keyboardPressed] whileTrue: [self readKeyboard ifTrue: [^ self]. Sensor waitButtonOrKeyboard]. [Sensor anyButtonPressed] whileTrue: [self manageMarker]! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'sma 6/1/2000 10:55'! readKeyboard "Keyboard support for menus. ESC will abort the menu, Space or CR will select an item. Cursor up and cursor down will change the selection. Any other key will either select an item whose label starts with that character or select the next matching label. Answer true if the menu should be closed and false otherwise." | ch labels occurences | ch _ Sensor keyboard asciiValue. (ch = 13 or: [ch = 32]) ifTrue: [^ true]. ch = 27 ifTrue: [self setSelection: 0. ^ true]. ch = 30 ifTrue: [self setSelection: (selection <= 1 ifTrue: [self nItems] ifFalse: [selection - 1])]. ch = 31 ifTrue: [self setSelection: selection \\ self nItems + 1]. ch _ ch asCharacter asLowercase. labels _ labelString findTokens: Character cr asString. occurences _ 0. 1 + selection to: selection + labels size do: [:index | | i | i _ index - 1 \\ labels size + 1. (labels at: i) withBlanksTrimmed first asLowercase = ch ifTrue: [(occurences _ occurences + 1) = 1 ifTrue: [self setSelection: i]]]. ^ occurences = 1! ! !PopUpMenu methodsFor: 'basic control sequence'! startUp "Display and make a selection from the receiver as long as the button is pressed. Answer the current selection." ^ self startUpWithCaption: nil! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ar 3/18/2001 00:55'! startUpCenteredWithCaption: captionOrNil "Differs from startUpWithCaption: by appearing with cursor in the menu, and thus ready to act on mouseUp, without requiring user tweak to confirm" ^ self startUpWithCaption: captionOrNil at: (ActiveHand ifNil:[Sensor]) cursorPoint - (20@0)! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'sw 12/17/2001 17:26'! startUpSegmented: segmentHeight withCaption: captionOrNil at: location allowKeyboard: aBoolean "This menu is too big to fit comfortably on the screen. Break it up into smaller chunks, and manage the relative indices. Inspired by a special-case solution by Reinier van Loon. The boolean parameter indicates whether the menu should be given keyboard focus (if in morphic)" " (PopUpMenu labels: (String streamContents: [:s | 1 to: 100 do: [:i | s print: i; cr]. s skip: -1]) lines: (5 to: 100 by: 5)) startUpWithCaption: 'Give it a whirl...'. " | nLines nLinesPer allLabels from to subset subLines index | frame ifNil: [self computeForm]. allLabels := labelString findTokens: Character cr asString. nLines _ allLabels size. lineArray ifNil: [lineArray _ Array new]. nLinesPer _ segmentHeight // marker height - 3. from := 1. [ true ] whileTrue: [to := (from + nLinesPer) min: nLines. subset := allLabels copyFrom: from to: to. subset add: (to = nLines ifTrue: ['start over...'] ifFalse: ['more...']) before: subset first. subLines _ lineArray select: [:n | n >= from] thenCollect: [:n | n - (from-1) + 1]. subLines _ (Array with: 1) , subLines. index := (PopUpMenu labels: subset asStringWithCr lines: subLines) startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean. index = 1 ifTrue: [from := to + 1. from > nLines ifTrue: [ from := 1 ]] ifFalse: [index = 0 ifTrue: [^ 0]. ^ from + index - 2]]! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ar 3/18/2001 00:55'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: (ActiveHand ifNil:[Sensor]) cursorPoint! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ar 12/27/2001 22:47'! startUpWithCaption: captionOrNil at: location "Display the menu, with caption if supplied. Wait for the mouse button to go down, then track the selection as long as the button is pressed. When the button is released, answer the index of the current selection, or zero if the mouse is not released over any menu item. Location specifies the desired topLeft of the menu body rectangle." ^ self startUpWithCaption: captionOrNil at: location allowKeyboard: Preferences menuKeyboardControl! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'BG 10/28/2003 21:02'! startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean "Display the menu, with caption if supplied. Wait for the mouse button to go down, then track the selection as long as the button is pressed. When the button is released, Answer the index of the current selection, or zero if the mouse is not released over any menu item. Location specifies the desired topLeft of the menu body rectangle. The final argument indicates whether the menu should seize the keyboard focus in order to allow the user to navigate it via the keyboard." | maxHeight | maxHeight _ Display height*3//4. self frameHeight > maxHeight ifTrue: [^ self startUpSegmented: maxHeight withCaption: captionOrNil at: location allowKeyboard: aBoolean]. frame ifNil: [self computeForm]. Cursor normal showWhile: [self displayAt: location withCaption: captionOrNil during: [self controlActivity]]. ^ selection! ! !PopUpMenu methodsFor: 'displaying' stamp: 'sw 12/10/1999 09:55'! displayAt: aPoint withCaption: captionOrNil during: aBlock "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." | delta savedArea captionForm captionSave outerFrame captionText tFrame frameSaveLoc captionBox | marker ifNil: [self computeForm]. frame _ frame align: marker leftCenter with: aPoint + (2@0). outerFrame _ frame. captionOrNil notNil ifTrue: [captionText _ (DisplayText text: captionOrNil asText textStyle: MenuStyle copy centered) foregroundColor: Color black backgroundColor: Color white. tFrame _ captionText boundingBox insetBy: -2. outerFrame _ frame merge: (tFrame align: tFrame bottomCenter with: frame topCenter + (0@2))]. delta _ outerFrame amountToTranslateWithin: Display boundingBox. frame right > Display boundingBox right ifTrue: [delta _ 0 - frame width @ delta y]. frame _ frame translateBy: delta. captionOrNil notNil ifTrue: [captionForm _ captionText form. captionBox _ captionForm boundingBox expandBy: 4. captionBox _ captionBox align: captionBox bottomCenter with: frame topCenter + (0@2). captionSave _ Form fromDisplay: captionBox. Display border: captionBox width: 4 fillColor: Color white. Display border: captionBox width: 2 fillColor: Color black. captionForm displayAt: captionBox topLeft + 4]. marker _ marker align: marker leftCenter with: aPoint + delta + (2@0). savedArea _ Form fromDisplay: frame. self menuForm displayOn: Display at: (frameSaveLoc _ frame topLeft). selection ~= 0 ifTrue: [Display reverse: marker]. Cursor normal showWhile: [aBlock value]. savedArea displayOn: Display at: frameSaveLoc. captionOrNil notNil ifTrue: [captionSave displayOn: Display at: captionBox topLeft]! ! !PopUpMenu methodsFor: 'marker adjustment' stamp: 'di 4/13/1999 17:42'! manageMarker "If the cursor is inside the receiver's frame, then highlight the marked item. Otherwise no item is to be marked." | pt | "Don't let pt get far from display box, so scrolling will go all the way" pt _ Sensor cursorPoint adhereTo: (Display boundingBox expandBy: 1). (frame inside containsPoint: pt) ifTrue: ["Need to cache the form for reasonable scrolling performance" ((Display boundingBox insetBy: 0@3) containsPoint: pt) ifFalse: [pt _ pt - (self scrollIntoView: pt)]. self markerOn: pt] ifFalse: [self markerOff]! ! !PopUpMenu methodsFor: 'marker adjustment' stamp: 'sma 5/28/2000 15:27'! markerOff "No item is selected. Reverse the highlight if any item has been marked as selected." self setSelection: 0! ! !PopUpMenu methodsFor: 'marker adjustment' stamp: 'sma 6/1/2000 13:01'! markerOn: aPoint "The item whose bounding area contains aPoint should be marked as selected. Highlight its area and set the selection to its index." selection = 0 | (marker containsPoint: aPoint) not ifTrue: [selection = 0 & (marker containsPoint: aPoint) ifTrue: [Display reverse: marker] ifFalse: [selection > 0 ifTrue: [Display reverse: marker]. marker _ marker align: marker topLeft with: marker left @ (self markerTop: aPoint). Display reverse: marker]]. selection _ marker top - frame top // marker height + 1! ! !PopUpMenu methodsFor: 'marker adjustment'! markerTop: aPoint "Answer aPoint, gridded to lines in the receiver." ^(aPoint y - frame inside top truncateTo: font height) + frame inside top! ! !PopUpMenu methodsFor: 'marker adjustment' stamp: 'di 3/9/98 19:46'! scrollIntoView: cursorLoc | dy | dy _ 0. cursorLoc y < 2 ifTrue: [dy _ font height]. cursorLoc y > (Display height-3) ifTrue: [dy _ font height negated]. dy = 0 ifTrue: [^ 0@0]. self markerOff. frame _ frame translateBy: 0@dy. marker _ marker translateBy: 0@dy. self menuForm displayOn: Display at: frame topLeft. ^ 0@dy! ! !PopUpMenu methodsFor: 'private' stamp: 'BG 8/17/2005 18:01'! computeForm "Compute and answer a Form to be displayed for this menu." | borderInset paraForm menuForm inside | borderInset _ 4@4. paraForm _ (DisplayText text: (Text string: labelString attribute: TextEmphasis normal) textStyle: MenuStyle) form. menuForm _ Form extent: paraForm extent + (borderInset * 2) depth: paraForm depth. menuForm fill: (0 @ 0 extent: menuForm extent) rule: Form over fillColor: Color white. menuForm borderWidth: 2. paraForm displayOn: menuForm at: borderInset. lineArray == nil ifFalse: [lineArray do: [ :line | menuForm fillBlack: (4 @ ((line * font height) + borderInset y) extent: (menuForm width - 8 @ 1))]]. frame _ Quadrangle new. frame region: menuForm boundingBox. frame borderWidth: 4. inside _ frame inside. marker _ inside topLeft extent: (inside width @ MenuStyle lineGrid). selection _ 1. ^ form _ menuForm ! ! !PopUpMenu methodsFor: 'private'! computeLabelParagraph "Answer a Paragraph containing this menu's labels, one per line and centered." ^ Paragraph withText: labelString asText style: MenuStyle! ! !PopUpMenu methodsFor: 'private' stamp: 'di 4/13/1999 16:21'! labels: aString font: aFont lines: anArray labelString _ aString. font _ aFont. lineArray _ anArray. ! ! !PopUpMenu methodsFor: 'private' stamp: 'di 4/13/1999 17:51'! menuForm "Answer a Form to be displayed for this menu." form == nil ifTrue: [self computeForm]. ^ form! ! !PopUpMenu methodsFor: 'private' stamp: 'BG 8/17/2005 17:57'! rescan "Cause my form to be recomputed after a font change." labelString == nil ifTrue: [labelString _ 'NoText!!']. self labels: labelString font: (MenuStyle fontAt: MenuStyle defaultFontIndex) lines: lineArray. frame _ marker _ form _ nil. "PopUpMenu allSubInstancesDo: [:m | m rescan]"! ! !PopUpMenu methodsFor: 'selecting' stamp: 'sma 5/28/2000 12:27'! selection "Answer the current selection." ^ selection! ! !PopUpMenu methodsFor: 'selecting' stamp: 'sma 6/1/2000 11:01'! setSelection: index | newSelection | selection = index ifTrue: [^ self]. newSelection _ (0 max: index) min: frame height // marker height. selection > 0 ifTrue: [Display reverse: marker]. marker _ marker translateBy: 0 @ (newSelection - selection * marker height). selection _ newSelection. selection > 0 ifTrue: [Display reverse: marker]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PopUpMenu class instanceVariableNames: ''! !PopUpMenu class methodsFor: 'class initialization' stamp: 'jla 4/2/2001 20:41'! alignment ^ MenuStyle alignment! ! !PopUpMenu class methodsFor: 'class initialization' stamp: 'jla 4/2/2001 20:46'! alignment: anAlignment ^ MenuStyle alignment: anAlignment! ! !PopUpMenu class methodsFor: 'class initialization' stamp: 'BG 8/17/2005 18:01'! initialize "PopUpMenu initialize" (MenuStyle _ TextStyle default copy) defaultFontIndex: 3; gridForFont: MenuStyle defaultFontIndex withLead: 0; centered. PopUpMenu allSubInstancesDo: [:m | m rescan]! ! !PopUpMenu class methodsFor: 'class initialization' stamp: 'jla 4/2/2001 20:56'! leftFlush MenuStyle leftFlush! ! !PopUpMenu class methodsFor: 'class initialization' stamp: 'sw 4/17/2001 13:12'! setMenuFontTo: aFont "Set the menu font as indicated" MenuStyle _ aFont textStyle copy consistOnlyOf: aFont. MenuStyle gridForFont: 1 withLead: 0; centered. self allSubInstancesDo: [:m | m rescan]! ! !PopUpMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 15:44'! labelArray: labelArray "Answer an instance of me whose items are in labelArray." ^ self labelArray: labelArray lines: nil! ! !PopUpMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 15:43'! labelArray: labelArray lines: lineArray "Answer an instance of me whose items are in labelArray, with lines drawn after each item indexed by anArray. 2/1/96 sw" labelArray isEmpty ifTrue: [self error: 'Menu must not be zero size']. ^ self labels: (String streamContents: [:stream | labelArray do: [:each | stream nextPutAll: each; cr]. stream skip: -1 "remove last CR"]) lines: lineArray "Example: (PopUpMenu labelArray: #('frog' 'and' 'toad') lines: #()) startUp"! ! !PopUpMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 15:36'! labels: aString "Answer an instance of me whose items are in aString." ^ self labels: aString lines: nil! ! !PopUpMenu class methodsFor: 'instance creation' stamp: 'sw 12/6/1999 17:55'! labels: aString lines: anArray "Answer an instance of me whose items are in aString, with lines drawn after each item indexed by anArray." ^ self new labels: aString font: MenuStyle defaultFont lines: anArray! ! !PopUpMenu class methodsFor: 'instance creation' stamp: 'tk 7/12/2000 17:29'! withCaption: cap chooseFrom: labels "Simply put up a menu. Get the args in the right order with the caption first. labels may be either an array of items or a string with CRs in it. May use backslashes for returns." (labels isKindOf: String) ifTrue: [^ (self labels: labels withCRs lines: nil) startUpWithCaption: cap withCRs] ifFalse: [^ (self labelArray: labels lines: nil) startUpWithCaption: cap withCRs]! ! !PopUpMenu class methodsFor: 'dialogs' stamp: 'dgd 9/5/2003 18:24'! confirm: queryString "Put up a yes/no menu with caption queryString. Answer true if the response is yes, false if no. This is a modal question--the user must respond yes or no." "PopUpMenu confirm: 'Are you hungry?'" ^ self confirm: queryString trueChoice: 'Yes' translated falseChoice: 'No' translated! ! !PopUpMenu class methodsFor: 'dialogs' stamp: 'dgd 9/5/2003 18:23'! confirm: queryString orCancel: cancelBlock "Put up a yes/no/cancel menu with caption aString. Answer true if the response is yes, false if no. If cancel is chosen, evaluate cancelBlock. This is a modal question--the user must respond yes or no." "PopUpMenu confirm: 'Reboot universe' orCancel: [^'Nevermind']" | menu choice | menu _ PopUpMenu labelArray: {'Yes' translated. 'No' translated. 'Cancel' translated}. choice _ menu startUpWithCaption: queryString. choice = 1 ifTrue: [^ true]. choice = 2 ifTrue: [^ false]. ^ cancelBlock value! ! !PopUpMenu class methodsFor: 'dialogs' stamp: 'sma 6/5/2000 09:12'! confirm: queryString trueChoice: trueChoice falseChoice: falseChoice "Put up a yes/no menu with caption queryString. The actual wording for the two choices will be as provided in the trueChoice and falseChoice parameters. Answer true if the response is the true-choice, false if it's the false-choice. This is a modal question -- the user must respond one way or the other." "PopUpMenu confirm: 'Are you hungry?' trueChoice: 'yes, I''m famished' falseChoice: 'no, I just ate'" | menu choice | menu _ PopUpMenu labelArray: {trueChoice. falseChoice}. [(choice _ menu startUpWithCaption: queryString) isNil] whileTrue. ^ choice = 1! ! !PopUpMenu class methodsFor: 'dialogs' stamp: 'dgd 9/5/2003 18:34'! inform: aString "PopUpMenu inform: 'I like Squeak'" (PopUpMenu labels: ' OK ' translated) startUpWithCaption: aString! ! !PopUpMenu class methodsFor: 'dialogs' stamp: 'sma 5/28/2000 15:57'! notify: message "Deprecated. Use #inform: instead." self inform: message! ! Stream subclass: #PositionableStream instanceVariableNames: 'collection position readLimit' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !PositionableStream commentStamp: '<historical>' prior: 0! 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.! !PositionableStream methodsFor: 'accessing' stamp: 'ajh 1/18/2002 01:03'! back "Go back one element and return it. Use indirect messages in case I am a StandardFileStream" self position = 0 ifTrue: [self errorCantGoBack]. self position = 1 ifTrue: [self position: 0. ^ nil]. self skip: -2. ^ self next ! ! !PositionableStream methodsFor: 'accessing'! contents "Answer with a copy of my collection from 1 to readLimit." ^collection copyFrom: 1 to: readLimit! ! !PositionableStream methodsFor: 'accessing' stamp: 'sw 3/10/98 13:55'! contentsOfEntireFile "For non-file streams" ^ self contents! ! !PositionableStream methodsFor: 'accessing' stamp: 'tk 9/23/2001 01:14'! last "Return the final element in the receiver" ^ collection at: position! ! !PositionableStream methodsFor: 'accessing' stamp: 'sw 3/10/98 13:55'! next: anInteger "Answer the next anInteger elements of my collection. Must override because default uses self contents species, which might involve a large collection." | newArray | newArray _ collection species new: anInteger. 1 to: anInteger do: [:index | newArray at: index put: self next]. ^newArray! ! !PositionableStream methodsFor: 'accessing' stamp: 'ar 12/23/1999 14:58'! next: n into: aCollection "Read n objects into the given collection. Return aCollection or a partial copy if less than n elements have been read." ^self next: n into: aCollection startingAt: 1! ! !PositionableStream methodsFor: 'accessing' stamp: 'ar 12/23/1999 14:54'! next: n into: aCollection startingAt: startIndex "Read n objects into the given collection. Return aCollection or a partial copy if less than n elements have been read." | obj | 0 to: n-1 do:[:i| (obj _ self next) == nil ifTrue:[^aCollection copyFrom: 1 to: startIndex+i-1]. aCollection at: startIndex+i put: obj]. ^aCollection! ! !PositionableStream methodsFor: 'accessing' stamp: 'tk 3/27/98 08:44'! nextDelimited: terminator "Answer the contents of the receiver, up to the next terminator character. Doubled terminators indicate an embedded terminator character. For example: 'this '' was a quote'. Start postioned before the initial terminator." | out ch | out _ WriteStream on: (String new: 1000). self atEnd ifTrue: [^ '']. self next == terminator ifFalse: [self skip: -1]. "absorb initial terminator" [(ch _ self next) == nil] whileFalse: [ (ch == terminator) ifTrue: [ self peek == terminator ifTrue: [ self next. "skip doubled terminator" ] ifFalse: [ ^ out contents "terminator is not doubled; we're done!!" ]. ]. out nextPut: ch. ]. ^ out contents! ! !PositionableStream methodsFor: 'accessing' stamp: 'ar 12/23/1999 14:53'! nextInto: aCollection "Read the next elements of the receiver into aCollection. Return aCollection or a partial copy if less than aCollection size elements have been read." ^self next: aCollection size into: aCollection startingAt: 1.! ! !PositionableStream methodsFor: 'accessing' stamp: 'bf 11/24/1998 13:35'! nextLine "Answer next line (may be empty), or nil if at end" self atEnd ifTrue: [^nil]. ^self upTo: Character cr! ! !PositionableStream methodsFor: 'accessing' stamp: 'nk 3/18/2004 08:52'! nextWordsInto: aBitmap "Fill the word based buffer from my collection. Stored on stream as Big Endian. Optimized for speed. Read in BigEndian, then restoreEndianness." | blt pos source byteSize | collection class isBytes ifFalse: [^ self next: aBitmap size into: aBitmap startingAt: 1]. byteSize := aBitmap byteSize. "is the test on collection basicSize \\ 4 necessary?" ((self position bitAnd: 3) = 0 and: [ (collection basicSize bitAnd: 3) = 0]) ifTrue: [source := collection. pos := self position. self skip: byteSize] ifFalse: ["forced to copy it into a buffer" source := self next: byteSize. pos := 0]. "Now use BitBlt to copy the bytes to the bitmap." blt := (BitBlt current toForm: (Form new hackBits: aBitmap)) sourceForm: (Form new hackBits: source). blt combinationRule: Form over. "store" blt sourceX: 0; sourceY: pos // 4; height: byteSize // 4; width: 4. blt destX: 0; destY: 0. blt copyBits. "And do whatever the bitmap needs to do to convert from big-endian order." aBitmap restoreEndianness. ^ aBitmap "May be WordArray, ColorArray, etc" ! ! !PositionableStream methodsFor: 'accessing'! originalContents "Answer the receiver's actual contents collection, NOT a copy. 1/29/96 sw" ^ collection! ! !PositionableStream methodsFor: 'accessing'! peek "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil." | nextObject | self atEnd ifTrue: [^nil]. nextObject _ self next. position _ position - 1. ^nextObject! ! !PositionableStream methodsFor: 'accessing' stamp: 'ajh 1/18/2002 01:02'! peekBack "Return the element at the previous position, without changing position. Use indirect messages in case self is a StandardFileStream." | element | element _ self back. self skip: 1. ^ element! ! !PositionableStream methodsFor: 'accessing'! peekFor: anObject "Answer false and do not move over the next element if it is not equal to the argument, anObject, or if the receiver is at the end. Answer true and increment the position for accessing elements, if the next element is equal to anObject." | nextObject | self atEnd ifTrue: [^false]. nextObject _ self next. "peek for matching element" anObject = nextObject ifTrue: [^true]. "gobble it if found" position _ position - 1. ^false! ! !PositionableStream methodsFor: 'accessing'! upTo: anObject "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of anObject in the receiver. If anObject is not in the collection, answer the entire rest of the receiver." | newStream element | newStream _ WriteStream on: (collection species new: 100). [self atEnd or: [(element _ self next) = anObject]] whileFalse: [newStream nextPut: element]. ^newStream contents! ! !PositionableStream methodsFor: 'accessing' stamp: 'tk 7/18/1999 17:10'! upToAll: aCollection "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of aCollection. If aCollection is not in the stream, answer the entire rest of the stream." | startPos endMatch result | startPos _ self position. (self match: aCollection) ifTrue: [endMatch _ self position. self position: startPos. result _ self next: endMatch - startPos - aCollection size. self position: endMatch. ^ result] ifFalse: [self position: startPos. ^ self upToEnd]! ! !PositionableStream methodsFor: 'accessing' stamp: 'BG 2/19/2004 14:06'! upToEnd "Answer a subcollection from the current access position through the last element of the receiver." | newStream | newStream _ WriteStream on: (collection species new: 100). [self atEnd] whileFalse: [ newStream nextPut: self next ]. ^ newStream contents! ! !PositionableStream methodsFor: 'testing'! atEnd "Primitive. Answer whether the receiver can access any more objects. Optional. See Object documentation whatIsAPrimitive." <primitive: 67> ^position >= readLimit! ! !PositionableStream methodsFor: 'testing' stamp: 'ar 1/2/2000 17:24'! isBinary "Return true if the receiver is a binary byte stream" ^collection class == ByteArray! ! !PositionableStream methodsFor: 'testing'! isEmpty "Answer whether the receiver's contents has no elements." ^position = 0! ! !PositionableStream methodsFor: 'positioning' stamp: 'hmm 10/22/1999 21:18'! match: subCollection "Set the access position of the receiver to be past the next occurrence of the subCollection. Answer whether subCollection is found. No wildcards, and case does matter." | pattern startMatch | pattern _ ReadStream on: subCollection. startMatch _ nil. [pattern atEnd] whileFalse: [self atEnd ifTrue: [^ false]. (self next) = (pattern next) ifTrue: [pattern position = 1 ifTrue: [startMatch _ self position]] ifFalse: [pattern position: 0. startMatch ifNotNil: [ self position: startMatch. startMatch _ nil]]]. ^ true ! ! !PositionableStream methodsFor: 'positioning'! position "Answer the current position of accessing the sequence of objects." ^position! ! !PositionableStream methodsFor: 'positioning'! position: anInteger "Set the current position for accessing the objects to be anInteger, as long as anInteger is within the bounds of the receiver's contents. If it is not, create an error notification." anInteger >= 0 & (anInteger <= readLimit) ifTrue: [position _ anInteger] ifFalse: [self positionError]! ! !PositionableStream methodsFor: 'positioning'! reset "Set the receiver's position to the beginning of the sequence of objects." position _ 0! ! !PositionableStream methodsFor: 'positioning' stamp: 'sw 3/10/98 13:55'! resetContents "Set the position and limits to 0." position _ 0. readLimit _ 0! ! !PositionableStream methodsFor: 'positioning'! setToEnd "Set the position of the receiver to the end of the sequence of objects." position _ readLimit! ! !PositionableStream methodsFor: 'positioning' stamp: 'RAH 6/29/2000 05:44'! skip: anInteger "Skips the next amount objects in the receiver's future sequence values." "2000/06/23 Harmon, R. Changed for ANSI <gettableStream> protocol." #Stream. self position: (self position + (anInteger min: (self contents size - self position))) ! ! !PositionableStream methodsFor: 'positioning'! skipTo: anObject "Set the access position of the receiver to be past the next occurrence of anObject. Answer whether anObject is found." [self atEnd] whileFalse: [self next = anObject ifTrue: [^true]]. ^false! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'ajh 1/18/2002 01:02'! backChunk "Answer the contents of the receiver back to the previous terminator character. Doubled terminators indicate an embedded terminator character." | terminator out ch | terminator _ $!!. out _ WriteStream on: (String new: 1000). [(ch _ self back) == nil] whileFalse: [ (ch == terminator) ifTrue: [ self peekBack == terminator ifTrue: [ self back. "skip doubled terminator" ] ifFalse: [ ^ out contents reversed "we're done!!" ]. ]. out nextPut: ch. ]. ^ out contents reversed! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'sd 5/23/2003 14:40'! checkForPreamble: chunk ((chunk beginsWith: '"Change Set:') and: [ChangeSet current preambleString == nil]) ifTrue: [ChangeSet current preambleString: chunk]. ((chunk beginsWith: '"Postscript:') and: [ChangeSet current postscriptString == nil]) ifTrue: [ChangeSet current postscriptString: chunk]. ! ! !PositionableStream methodsFor: 'fileIn/Out'! command: aString "Overridden by HtmlFileStream to append commands directly without translation. 4/5/96 tk" "We ignore any HTML commands. Do nothing"! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 2/3/98 14:44'! copyMethodChunkFrom: aStream "Copy the next chunk from aStream (must be different from the receiver)." | chunk | chunk _ aStream nextChunkText. chunk runs values size = 1 "Optimize for unembellished text" ifTrue: [self nextChunkPut: chunk asString] ifFalse: [self nextChunkPutWithStyle: chunk]! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 09:16'! copyPreamble: preamble from: aStream "Look for a changeStamp for this method by peeking backward. Write a method preamble, with that stamp if found." | terminator methodPos p last50 stamp i | terminator _ $!!. "Look back to find stamp in old preamble, such as... Polygon methodsFor: 'private' stamp: 'di 6/25/97 21:42' prior: 34957598!! " methodPos _ aStream position. aStream position: (p _ 0 max: methodPos-50). last50 _ aStream next: methodPos - p. stamp _ String new. (i _ last50 findString: 'stamp:' startingAt: 1) > 0 ifTrue: [stamp _ (last50 copyFrom: i+8 to: last50 size) copyUpTo: $']. "Write the new preamble, with old stamp if any." self cr; nextPut: terminator. self nextChunkPut: (String streamContents: [:strm | strm nextPutAll: preamble. stamp size > 0 ifTrue: [strm nextPutAll: ' stamp: '; print: stamp]]). self cr! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'mir 7/26/2000 13:28'! fileIn "This is special for reading expressions from text that has been formatted with exclamation delimitors. The expressions are read and passed to the Compiler. Answer the result of compilation." ^ self fileInAnnouncing: 'Reading ' , self name! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'NS 1/28/2004 11:22'! fileInAnnouncing: announcement "This is special for reading expressions from text that has been formatted with exclamation delimitors. The expressions are read and passed to the Compiler. Answer the result of compilation. Put up a progress report with the given announcement as the title." | val chunk | announcement displayProgressAt: Sensor cursorPoint from: 0 to: self size during: [:bar | [self atEnd] whileFalse: [bar value: self position. self skipSeparators. [val := (self peekFor: $!!) ifTrue: [(Compiler evaluate: self nextChunk logged: false) scanFrom: self] ifFalse: [chunk := self nextChunk. self checkForPreamble: chunk. Compiler evaluate: chunk logged: true]] on: InMidstOfFileinNotification do: [:ex | ex resume: true]. self skipStyleChunk]. self close]. "Note: The main purpose of this banner is to flush the changes file." SmalltalkImage current logChange: '----End fileIn of ' , self name , '----'. self flag: #ThisMethodShouldNotBeThere. "sd" Smalltalk forgetDoIts. ^val! ! !PositionableStream methodsFor: 'fileIn/Out'! header "If the stream requires a standard header, override this message. See HtmlFileStream"! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 2/3/98 14:29'! nextChunk "Answer the contents of the receiver, up to the next terminator character. Doubled terminators indicate an embedded terminator character." | terminator out ch | terminator _ $!!. out _ WriteStream on: (String new: 1000). self skipSeparators. [(ch _ self next) == nil] whileFalse: [ (ch == terminator) ifTrue: [ self peek == terminator ifTrue: [ self next. "skip doubled terminator" ] ifFalse: [ ^ out contents "terminator is not doubled; we're done!!" ]. ]. out nextPut: ch. ]. ^ out contents! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 1/13/98 16:54'! nextChunkText "Deliver the next chunk as a Text. Decode the following ]style[ chunk if present. Position at start of next real chunk." | string runsRaw strm runs peek | "Read the plain text" string _ self nextChunk. "Test for ]style[ tag" peek _ self skipSeparatorsAndPeekNext. peek = $] ifFalse: [^ string asText]. "no tag" (self upTo: $[) = ']style' ifFalse: [^ string asText]. "different tag" "Read and decode the style chunk" runsRaw _ self nextChunk. "style encoding" strm _ ReadStream on: runsRaw from: 1 to: runsRaw size. runs _ RunArray scanFrom: strm. ^ Text basicNew setString: string setRunsChecking: runs. ! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 6/13/97 12:00'! skipSeparators [self atEnd] whileFalse: [self next isSeparator ifFalse: [^ self position: self position-1]]! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'di 1/13/98 16:08'! skipSeparatorsAndPeekNext "A special function to make nextChunk fast" | peek | [self atEnd] whileFalse: [(peek _ self next) isSeparator ifFalse: [self position: self position-1. ^ peek]]! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'tk 12/29/97 12:37'! skipStyleChunk "Get to the start of the next chunk that is not a style for the previous chunk" | pos | pos _ self position. self skipSeparators. self peek == $] ifTrue: [(self upTo: $[) = ']text' "old -- no longer needed" "now positioned past the open bracket" ifFalse: [self nextChunk]] "absorb ]style[ and its whole chunk" ifFalse: [self position: pos] "leave untouched" ! ! !PositionableStream methodsFor: 'fileIn/Out'! trailer "If the stream requires a standard trailer, override this message. See HtmlFileStream"! ! !PositionableStream methodsFor: 'fileIn/Out'! unCommand "If this read stream is at a <, then skip up to just after the next >. For removing html commands." | char | [self peek = $<] whileTrue: ["begin a block" [self atEnd == false and: [self next ~= $>]] whileTrue. "absorb characters" ]. ! ! !PositionableStream methodsFor: 'private'! on: aCollection collection _ aCollection. readLimit _ aCollection size. position _ 0. self reset! ! !PositionableStream methodsFor: 'private'! positionError "Since I am not necessarily writable, it is up to my subclasses to override position: if expanding the collection is preferrable to giving this error." self error: 'Attempt to set the position of a PositionableStream out of bounds'! ! !PositionableStream methodsFor: 'private'! setFrom: newStart to: newStop position _ newStart - 1. readLimit _ newStop! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'sw 3/10/98 13:55'! nextInt32 "Read a 32-bit signed integer from the next 4 bytes" | s | s _ 0. 1 to: 4 do: [:i | s _ (s bitShift: 8) + self next]. (s bitAnd: 16r80000000) = 0 ifTrue: [^ s] ifFalse: [^ -1 - s bitInvert32]! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'sw 3/10/98 13:55'! nextInt32Put: int32 "Write a signed integer to the next 4 bytes" | pos | pos _ int32 < 0 ifTrue: [(0-int32) bitInvert32 + 1] ifFalse: [int32]. 1 to: 4 do: [:i | self nextPut: (pos digitAt: 5-i)]. ^ int32! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'jm 4/9/98 21:36'! nextLittleEndianNumber: n "Answer the next n bytes as a positive Integer or LargePositiveInteger, where the bytes are ordered from least significant to most significant." | bytes s | bytes _ self next: n. s _ 0. n to: 1 by: -1 do: [:i | s _ (s bitShift: 8) bitOr: (bytes at: i)]. ^ s ! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'di 12/6/1999 10:13'! nextLittleEndianNumber: n put: value "Answer the next n bytes as a positive Integer or LargePositiveInteger, where the bytes are ordered from least significant to most significant." | bytes | bytes _ ByteArray new: n. 1 to: n do: [: i | bytes at: i put: (value digitAt: i)]. self nextPutAll: bytes! ! !PositionableStream methodsFor: 'nonhomogeneous accessing'! nextNumber: n "Answer the next n bytes as a positive Integer or LargePositiveInteger." | s | s _ 0. 1 to: n do: [:i | s _ (s bitShift: 8) bitOr: self next asInteger]. ^ s normalize! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'sw 3/10/98 13:55'! nextNumber: n put: v "Append to the receiver the argument, v, which is a positive SmallInteger or a LargePositiveInteger, as the next n bytes. Possibly pad with leading zeros." 1 to: n do: [:i | self nextPut: (v digitAt: n+1-i)]. ^ v ! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'sw 3/10/98 13:55'! nextWord "Answer the next two bytes from the receiver as an Integer." | high low | high _ self next. high==nil ifTrue: [^false]. low _ self next. low==nil ifTrue: [^false]. ^(high asInteger bitShift: 8) + low asInteger! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'sw 3/10/98 13:55'! nextWordPut: aWord "Append to the receiver an Integer as the next two bytes." self nextPut: ((aWord bitShift: -8) bitAnd: 255). self nextPut: (aWord bitAnd: 255). ^aWord! ! !PositionableStream methodsFor: 'data get/put' stamp: 'jm 9/5/2001 07:35'! string "Answer the next string from this (binary) stream." | size | size _ self uint16. ^ (self next: size) asString ! ! !PositionableStream methodsFor: 'data get/put' stamp: 'jm 9/5/2001 12:09'! string: aString "Store the given string on this (binary) stream. The string must contain 65535 or fewer characters." aString size > 16rFFFF ifTrue: [self error: 'string too long for this format']. self uint16: aString size. self nextPutAll: aString asByteArray. ! ! !PositionableStream methodsFor: 'data get/put' stamp: 'jm 8/20/2001 07:53'! uint16 "Answer the next unsigned, 16-bit integer from this (binary) stream." | n | n _ self next. n _ (n bitShift: 8) + (self next). ^ n ! ! !PositionableStream methodsFor: 'data get/put' stamp: 'jm 8/20/2001 07:53'! uint16: anInteger "Store the given unsigned, 16-bit integer on this (binary) stream." (anInteger < 0) | (anInteger >= 16r10000) ifTrue: [self error: 'outside unsigned 16-bit integer range']. self nextPut: (anInteger digitAt: 2). self nextPut: (anInteger digitAt: 1). ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PositionableStream class instanceVariableNames: ''! !PositionableStream class methodsFor: 'instance creation'! on: aCollection "Answer an instance of me, streaming over the elements of aCollection." ^self basicNew on: aCollection! ! !PositionableStream class methodsFor: 'instance creation'! on: aCollection from: firstIndex to: lastIndex "Answer an instance of me, streaming over the elements of aCollection starting with the element at firstIndex and ending with the one at lastIndex." ^self basicNew on: (aCollection copyFrom: firstIndex to: lastIndex)! ! Object subclass: #Preference instanceVariableNames: 'name value defaultValue helpString localToProject categoryList changeInformee changeSelector' classVariableNames: '' poolDictionaries: '' category: 'System-Support'! !Preference commentStamp: 'sw 1/14/2003 22:33' prior: 0! Represents a true/false flag that is under user control and which can be interrogated by a call to Preferences name a symbol, the formal name of the preference. value a boolean, the current value defaultValue the default value of the preference helpString string or text, constituting the help message localToProject boolean, whether each project holds its own version categoryList list of categories under which to offer this changeInformee whom, if anyone, to inform if the value changes: changeSelector what selector to send to the changeInformee when the value changes! !Preference methodsFor: 'initialization' stamp: 'sw 3/5/2002 14:12'! name: aName defaultValue: aValue helpString: aString localToProject: projectBoolean categoryList: aList changeInformee: informee changeSelector: aChangeSelector "Initialize the preference from the given values. There is an extra tolerence here for the symbols #true, #false, and #nil, which are interpreted, when appropriate, as meaning true, false, and nil" name _ aName asSymbol. defaultValue _ aValue == true or: [aValue = #true]. value _ defaultValue. helpString _ aString. localToProject _ projectBoolean == true or: [projectBoolean = #true]. categoryList _ (aList ifNil: [OrderedCollection with: #unclassified]) collect: [:elem | elem asSymbol]. changeInformee _ (informee == nil or: [informee == #nil]) ifTrue: [nil] ifFalse: [(informee isKindOf: Symbol) ifTrue: [Smalltalk at: informee] ifFalse: [informee]]. changeSelector _ aChangeSelector! ! !Preference methodsFor: 'menu' stamp: 'sw 4/13/2001 00:01'! copyName "Copy the name of the given preference to the clipboard" Clipboard clipboardText: name asString asText! ! !Preference methodsFor: 'menu' stamp: 'sw 4/10/2001 15:02'! name "Answer this preference's name" ^ name! ! !Preference methodsFor: 'value' stamp: 'sw 4/10/2001 15:01'! defaultValue "Answer this preference's defaultValue" ^ defaultValue! ! !Preference methodsFor: 'value' stamp: 'sw 4/10/2001 15:35'! preferenceValue "Answer the current value of the preference" ^ value! ! !Preference methodsFor: 'value' stamp: 'sw 4/12/2001 23:28'! preferenceValue: aValue "set the value as indicated, and invoke the change selector if appropriate" | oldValue | oldValue _ value. value _ aValue. oldValue ~~ value ifTrue: [self notifyInformeeOfChange]! ! !Preference methodsFor: 'value' stamp: 'sw 4/12/2001 23:28'! rawValue: aValue "set the value as indicated, with no side effects" value _ aValue! ! !Preference methodsFor: 'value' stamp: 'sw 4/12/2001 00:04'! restoreDefaultValue "restore the default value to the preference" value _ defaultValue! ! !Preference methodsFor: 'value' stamp: 'sw 4/12/2001 00:04'! togglePreferenceValue "Toggle whether the value of the preference" value _ value not. self notifyInformeeOfChange! ! !Preference methodsFor: 'local to project' stamp: 'sw 4/10/2001 01:14'! localToProject "Answer whether this preference is project-local" ^ localToProject! ! !Preference methodsFor: 'change notification' stamp: 'sw 4/12/2001 00:03'! notifyInformeeOfChange "If there is a changeInformee, notify her that I have changed value" changeInformee ifNotNil: [changeInformee perform: changeSelector]! ! !Preference methodsFor: 'debugging' stamp: 'sw 4/13/2001 00:05'! printOn: aStream "Print a string decribing the receiver to the given stream" super printOn: aStream. aStream nextPutAll: name storeString, ' ', value storeString! ! !Preference methodsFor: 'as yet unclassified' stamp: 'BG 10/31/2003 14:32'! changeInformee ^changeInformee! ! !Preference methodsFor: 'as yet unclassified' stamp: 'BG 10/31/2003 14:47'! deleteInformee changeInformee := nil! ! Object subclass: #Preferences instanceVariableNames: '' classVariableNames: 'DesktopColor DictionaryOfPreferences Parameters' poolDictionaries: '' category: 'System-Support'! !Preferences commentStamp: '<historical>' prior: 0! 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. To open the control panel: Preferences openFactoredPanel To read how to use the panel (and how to make a preference be per-project): Preferences giveHelpWithPreferences All messages are on the class side. To query a a preference: Preferences logDebuggerStackToFile or some people prefer the more verbose Preferences valueOfFlag: #logDebuggerStackToFile You can make up a new preference any time. Do not define a new message in Preferences class. Accessor methods are compiled automatically when you add a preference as illustrated below: To add a preference (e.g. in the Postscript of a fileout): Preferences addPreference: #samplePreference categories: #(general browsing) default: true balloonHelp: 'This is an example of a preference added by a do-it' projectLocal: false changeInformee: nil changeSelector: nil. To change a preference programatically: Preferences disable: #logDebuggerStackToFile. Or to turn it on, Preferences enable: #logDebuggerStackToFile. ! ]style[(220 29 81 35 812)f1,f1dPreferences openFactoredPanel;;,f1,f1dPreferences giveHelpWithPreferences;;,f1! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Preferences class instanceVariableNames: ''! !Preferences class methodsFor: 'add preferences' stamp: 'sw 4/10/2001 14:55'! addPreference: prefSymbol categories: categoryList default: defaultValue balloonHelp: helpString "Add an item repreesenting the given preference symbol to the system" self addPreference: prefSymbol categories: categoryList default: defaultValue balloonHelp: helpString projectLocal: false changeInformee: nil changeSelector: nil! ! !Preferences class methodsFor: 'add preferences' stamp: 'sw 8/19/2001 08:28'! addPreference: prefSymbol categories: categoryList default: aValue balloonHelp: helpString projectLocal: localBoolean changeInformee: informeeSymbol changeSelector: aChangeSelector "Add or replace a preference as indicated. Reuses the preexisting Preference object for this symbol, if there is one, so that UI artifacts that interact with it will remain valid." | aPreference | aPreference _ DictionaryOfPreferences at: prefSymbol ifAbsent: [Preference new]. aPreference name: prefSymbol defaultValue: aValue helpString: helpString localToProject: localBoolean categoryList: categoryList changeInformee: informeeSymbol changeSelector: aChangeSelector. DictionaryOfPreferences at: prefSymbol put: aPreference. self compileAccessMethodForPreference: aPreference! ! !Preferences class methodsFor: 'add preferences' stamp: 'sw 2/5/2001 22:20'! addPreference: prefSymbol category: categorySymbol default: defaultValue balloonHelp: helpString "Add the given preference, putting it in the given category, with the given default value, and with the given balloon help" self addPreference: prefSymbol categories: {categorySymbol} default: defaultValue balloonHelp: helpString ! ! !Preferences class methodsFor: 'fonts' stamp: 'laza 3/25/2004 23:10'! chooseCodeFont "Not currently sent, but once protocols are sorted out so that we can disriminate on whether a text object being launched is for code or not, will be reincorporated" self chooseFontWithPrompt: 'standard code font' andSendTo: self withSelector: #setCodeFontTo: highlight: self standardCodeFont.! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 8/18/2004 14:53'! chooseFontWithPrompt: aPrompt andSendTo: aReceiver withSelector: aSelector highlight: currentFont TextStyle mvcPromptForFont: aPrompt andSendTo: aReceiver withSelector: aSelector! ! !Preferences class methodsFor: 'fonts' stamp: 'laza 3/25/2004 23:11'! chooseListFont self chooseFontWithPrompt: 'standard list font' andSendTo: self withSelector: #setListFontTo: highlight: self standardListFont! ! !Preferences class methodsFor: 'fonts' stamp: 'laza 3/25/2004 23:11'! chooseMenuFont self chooseFontWithPrompt: 'standard menu font' andSendTo: self withSelector: #setMenuFontTo: highlight: self standardMenuFont! ! !Preferences class methodsFor: 'fonts' stamp: 'laza 3/25/2004 23:11'! chooseSystemFont self chooseFontWithPrompt: 'Default text font' andSendTo: self withSelector: #setSystemFontTo: highlight: (TextConstants at: #DefaultTextStyle) defaultFont! ! !Preferences class methodsFor: 'fonts' stamp: 'laza 3/25/2004 23:11'! chooseWindowTitleFont self chooseFontWithPrompt: 'window title font' andSendTo: self withSelector: #setWindowTitleFontTo: highlight: self windowTitleFont! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/30/2003 21:20'! presentMvcFontConfigurationMenu | aMenu result | aMenu _ CustomMenu new. aMenu title: 'Standard System Fonts'. aMenu add: 'default text font...' action: #chooseSystemFont. aMenu add: 'list font...' action: #chooseListFont. aMenu add: 'menu font...' action: #chooseMenuFont. aMenu add: 'window-title font...' action: #chooseWindowTitleFont. "aMenu add: 'code font...' action: #chooseCodeFont." aMenu addLine. aMenu add: 'restore default font choices' action: #restoreDefaultFonts. (result _ aMenu startUp) ifNotNil: [self perform: result] ! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/30/2003 21:20'! restoreDefaultFonts "Preferences restoreDefaultFonts" #( (setButtonFontTo: ComicBold 16) "(setCodeFontTo: NewYork 12)" "Later" (setListFontTo: NewYork 12) (setMenuFontTo: NewYork 12) (setWindowTitleFontTo: NewYork 15) (setSystemFontTo: NewYork 12)) do: [:triplet | self perform: triplet first with: (StrikeFont familyName: triplet second size: triplet third)]. Smalltalk at: #BalloonMorph ifPresent: [:thatClass | thatClass setBalloonFontTo: (StrikeFont familyName: #ComicPlain size: 12)]. "Note: The standardCodeFont is not currently used -- the default font is instead; later hopefully we can split the code font out as a separate choice, but only after we're able to have the protocols reorganized such that we can know whether it's code or not when we launch the text object. Note: The standard button font is reset by this code but is not otherwise settable by a public UI (too many things can go afoul) "! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 22:06'! setButtonFontTo: aFont Parameters at: #standardButtonFont put: aFont! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/28/2003 19:52'! setCodeFontTo: aFont "Not currently sent, but once protocols are sorted out so that we can discriminate on whether a text object being launched is for code or not, might deserve to be reincorporated" Parameters at: #standardCodeFont put: aFont. ! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/28/2003 19:52'! setListFontTo: aFont "Set the list font as indicated" Parameters at: #standardListFont put: aFont. ListParagraph initialize. ! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 18:04'! setMenuFontTo: aFont Parameters at: #standardMenuFont put: aFont. PopUpMenu setMenuFontTo: aFont! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/28/2003 19:52'! setSystemFontTo: aFont "Establish the default text font and style" | aStyle newDefaultStyle | aFont ifNil: [^ self]. aStyle _ aFont textStyle ifNil: [^ self]. newDefaultStyle _ aStyle copy. newDefaultStyle defaultFontIndex: (aStyle fontIndexOf: aFont). TextConstants at: #DefaultTextStyle put: newDefaultStyle. ! ! !Preferences class methodsFor: 'fonts' stamp: 'BG 10/28/2003 19:52'! setWindowTitleFontTo: aFont "Set the window-title font to be as indicated" Parameters at: #windowTitleFont put: aFont. StandardSystemView setLabelStyle.! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 16:13'! standardButtonFont "Answer an attractive font to use for buttons" "Answer the font to be used for textual flap tab labels" ^ Parameters at: #standardButtonFont ifAbsent: [Parameters at: #standardButtonFont put: (StrikeFont familyName: #ComicBold size: 16)]! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 16:58'! standardCodeFont "Answer the font to be used in code" ^ Parameters at: #standardCodeFont ifAbsent: [Parameters at: #standardCodeFont put: TextStyle defaultFont]! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 16:09'! standardListFont "Answer the font to be used in lists" ^ Parameters at: #standardListFont ifAbsent: [Parameters at: #standardListFont put: TextStyle defaultFont]! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 16:58'! standardMenuFont "Answer the font to be used in menus" ^ Parameters at: #standardMenuFont ifAbsent: [Parameters at: #standardMenuFont put: TextStyle defaultFont]! ! !Preferences class methodsFor: 'fonts' stamp: 'sw 12/8/1999 16:10'! windowTitleFont "Answer the standard font to use for window titles" ^ Parameters at: #windowTitleFont ifAbsent: [Parameters at: #windowTitleFont put: (StrikeFont familyName: #NewYork size: 15)]! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 4/12/2001 23:29'! disable: aSymbol "Shorthand access to enabling a preference of the given name. If there is none in the image, conjure one up" | aPreference | aPreference _ self preferenceAt: aSymbol ifAbsent: [self addPreference: aSymbol category: 'unclassified' default: false balloonHelp: 'this preference was added idiosyncratically and has no help message.'. self preferenceAt: aSymbol]. aPreference preferenceValue: false! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 1/19/2000 13:51'! disableGently: preferenceNameSymbol "Unlike #disable:, this on does not reset the CategoryInfo cache" self setPreference: preferenceNameSymbol toValue: false! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 11/11/1998 11:40'! doesNotUnderstand: aMessage "Look up the message selector as a flag." aMessage arguments size > 0 ifTrue: [^ super doesNotUnderstand: aMessage]. ^ self valueOfFlag: aMessage selector ! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 1/19/2000 13:53'! enableGently: preferenceNameSymbol "Unlike #enable:, this one does not reset the CategoryInfo cache" self setPreference: preferenceNameSymbol toValue: true! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 4/12/2001 23:29'! setPreference: prefSymbol toValue: aBoolean "Set the given preference to the given value, and answer that value" ^ (self preferenceAt: prefSymbol ifAbsent: [^ aBoolean]) preferenceValue: aBoolean! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 4/12/2001 00:04'! togglePreference: prefSymbol "Toggle the given preference" (self preferenceAt: prefSymbol ifAbsent: [self error: 'unknown preference: ', prefSymbol]) togglePreferenceValue! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 4/13/2001 01:07'! valueOfFlag: aFlagName "Answer the value of the given flag" ^ (self preferenceAt: aFlagName ifAbsent: [^ false]) preferenceValue! ! !Preferences class methodsFor: 'get/set' stamp: 'sw 4/13/2001 01:07'! valueOfFlag: aFlagName ifAbsent: booleanValuedBlock "Answer the value of the given flag" ^ (self preferenceAt: aFlagName ifAbsent: [^ booleanValuedBlock value]) preferenceValue! ! !Preferences class methodsFor: 'hard-coded prefs' stamp: 'ar 1/31/2001 17:06'! browseToolClass ^ Preferences browserShowsPackagePane ifTrue: [PackagePaneBrowser] ifFalse: [Browser]! ! !Preferences class methodsFor: 'hard-coded prefs' stamp: 'programmatic 7/15/1999 09:55'! cmdKeysInText "compiled programatically -- return hard-coded preference value" ^ true! ! !Preferences class methodsFor: 'initialization' stamp: 'sw 4/10/2001 15:28'! chooseInitialSettings "Restore the default choices for all of the standard Preferences." self allPreferenceObjects do: [:aPreference | aPreference restoreDefaultValue]. Project current installProjectPreferences! ! !Preferences class methodsFor: 'initialization' stamp: 'NS 1/28/2004 14:43'! compileAccessMethodForPreference: aPreference "Compile an accessor method for the given preference" self class compileSilently: (aPreference name, ' ^ self valueOfFlag: #', aPreference name, ' ifAbsent: [', aPreference defaultValue storeString, ']') classified: 'standard queries'! ! !Preferences class methodsFor: 'misc' stamp: 'sw 10/6/1999 15:20'! addModelItemsToWindowMenu: aMenu aMenu addLine. aMenu add: 'restore default preference settings' target: self action: #chooseInitialSettings. aMenu add: 'restore default text highlighting' target: self action: #initializeTextHighlightingParameters! ! !Preferences class methodsFor: 'misc' stamp: 'sw 1/4/2001 06:56'! setFlag: prefSymbol toValue: aBoolean during: aBlock "Set the flag to the given value for the duration of aBlock" | existing | existing _ self valueOfFlag: prefSymbol. existing == aBoolean ifFalse: [self setPreference: prefSymbol toValue: aBoolean]. aBlock value. existing == aBoolean ifFalse: [self setPreference: prefSymbol toValue: existing]! ! !Preferences class methodsFor: 'misc' stamp: 'dgd 10/17/2003 12:14'! soundEnablingString ^ self soundsEnabled ifFalse: ['turn sound on' translated] ifTrue: ['turn sound off' translated]! ! !Preferences class methodsFor: 'misc' stamp: 'dgd 9/21/2003 13:46'! staggerPolicyString "Answer the string to be shown in a menu to represent the stagger-policy status" ^ ((self valueOfFlag: #reverseWindowStagger) ifTrue: ['<yes>'] ifFalse: ['<no>']), 'stagger windows' translated! ! !Preferences class methodsFor: 'misc' stamp: 'sw 6/11/1999 20:49'! toggleWindowPolicy self togglePreference: #reverseWindowStagger! ! !Preferences class methodsFor: 'misc' stamp: 'sw 8/29/2000 16:12'! wantsChangeSetLogging "Answer whether method changes in the receiver should be logged to current change set. This circumlocution avoids such logging for programmatically-compiled methods in Preferences, removing an annoyance" ^ Utilities authorInitialsPerSe ~= 'programmatic'! ! !Preferences class methodsFor: 'parameters' stamp: 'sw 2/17/1999 00:40'! defaultAnnotationRequests ^ Parameters at: #MethodAnnotations ifAbsent: [self setDefaultAnnotationInfo] "Preferences annotationInfo"! ! !Preferences class methodsFor: 'parameters' stamp: 'sma 6/1/2000 12:08'! defaultAuthorName "Answer the author name to be planted, by default, in a changeset-preamble template. You can hard-code this to hold your name, thus saving you time when writing the preambles of subsequent changesets" ^ Utilities authorName! ! !Preferences class methodsFor: 'parameters' stamp: 'jhm 10/15/97 17:31'! desktopColor "Answer the desktop color. Initialize it if necessary." DesktopColor == nil ifTrue: [DesktopColor _ Color gray]. ^ DesktopColor ! ! !Preferences class methodsFor: 'parameters' stamp: 'jhm 10/15/97 17:31'! desktopColor: aColor "Record a new desktop color preference." DesktopColor _ aColor. ! ! !Preferences class methodsFor: 'parameters' stamp: 'sw 2/7/2001 14:37'! parameterAt: aKey ifAbsent: aBlock "Answer the parameter saved at the given key; if there is no such key in the Parameters dictionary, evaluate aBlock" ^ Parameters at: aKey ifAbsent: [aBlock value]! ! !Preferences class methodsFor: 'parameters' stamp: 'sw 9/28/2001 08:40'! parameterAt: aKey ifAbsentPut: defaultValueBlock "Return the Parameter setting at the given key. If there is no entry for this key in the Parameters dictionary, create one with the value of defaultValueBlock as its value" ^ Parameters at: aKey ifAbsentPut: defaultValueBlock! ! !Preferences class methodsFor: 'parameters'! scrollBarColor "Answer the preferred color for scroll bar elevators." ^ Color gray! ! !Preferences class methodsFor: 'parameters'! scrollBarWidth "Answer the preferred width for scroll bars." ^ 8! ! !Preferences class methodsFor: 'parameters' stamp: 'sw 2/17/1999 00:41'! setDefaultAnnotationInfo "Preferences setDefaultAnnotationInfo" ^ Parameters at: #MethodAnnotations put: #(timeStamp messageCategory implementorsCount allChangeSets)! ! !Preferences class methodsFor: 'parameters' stamp: 'stp 01/13/2000 13:29'! setParameter: paramName to: paramValue "Set the given field in the parameters dictionary." Parameters at: paramName put: paramValue! ! !Preferences class methodsFor: 'personalization' stamp: 'sw 4/18/2002 18:02'! restorePersonalPreferences "Restore all the user's saved personal preference settings" | savedPrefs | savedPrefs _ self parameterAt: #PersonalDictionaryOfPreferences ifAbsent: [^ self inform: 'There are no personal preferences saved in this image yet']. savedPrefs associationsDo: [:assoc | (self preferenceAt: assoc key ifAbsent: [nil]) ifNotNilDo: [:pref | pref preferenceValue: assoc value preferenceValue]]! ! !Preferences class methodsFor: 'preference-object access' stamp: 'sw 4/13/2001 00:06'! allPreferenceObjects "Answer a list of all the Preference objects registered in the system" ^ DictionaryOfPreferences values! ! !Preferences class methodsFor: 'preference-object access' stamp: 'sw 4/13/2001 01:06'! preferenceAt: aSymbol "Answer the Preference object at the given symbol, or nil if not there" ^ DictionaryOfPreferences at: aSymbol ifAbsent: [nil]! ! !Preferences class methodsFor: 'preference-object access' stamp: 'sw 4/13/2001 01:06'! preferenceAt: aSymbol ifAbsent: aBlock "Answer the Preference object at the given symbol, or the value of aBlock if not present" ^ DictionaryOfPreferences at: aSymbol ifAbsent: [aBlock value]! ! !Preferences class methodsFor: 'preferences panel' stamp: 'sw 9/15/1999 09:15'! initialExtent ^ (Preferences inboardScrollbars and: [Smalltalk isMorphic]) ifFalse: [219 @ 309] ifTrue: [232 @ 309]! ! !Preferences class methodsFor: 'preferences panel' stamp: 'sw 4/11/2001 23:55'! inspectPreferences "Open a window on the current preferences dictionary, allowing the user to inspect and change the current preference settings. This is fallen back upon if Morphic is not present" "Preferences inspectPreferences" DictionaryOfPreferences inspectWithLabel: 'Preferences' ! ! !Preferences class methodsFor: 'preferences panel' stamp: 'BG 10/30/2003 21:17'! openPreferencesInspector "Open a window on the current set of preferences choices, allowing the user to view and change their settings" self inspectPreferences! ! !Preferences class methodsFor: 'standard queries'! alphabeticalProjectMenu ^ self valueOfFlag: #alphabeticalProjectMenu ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! alternativeBrowseIt ^ self valueOfFlag: #alternativeBrowseIt ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! annotationPanes ^ self valueOfFlag: #annotationPanes ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! ansiAssignmentOperatorWhenPrettyPrinting ^ self valueOfFlag: #ansiAssignmentOperatorWhenPrettyPrinting ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! autoAccessors ^ self valueOfFlag: #autoAccessors ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! automaticPlatformSettings ^ self valueOfFlag: #automaticPlatformSettings ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! browseWithPrettyPrint ^ self valueOfFlag: #browseWithPrettyPrint ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! browserShowsPackagePane ^ self valueOfFlag: #browserShowsPackagePane ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! capitalizedReferences ^ self valueOfFlag: #capitalizedReferences ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! caseSensitiveFinds ^ self valueOfFlag: #caseSensitiveFinds ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! changeSetVersionNumbers ^ self valueOfFlag: #changeSetVersionNumbers ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! checkForSlips ^ self valueOfFlag: #checkForSlips ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! clickOnLabelToEdit ^ self valueOfFlag: #clickOnLabelToEdit ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! cmdDotEnabled ^ self valueOfFlag: #cmdDotEnabled ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! colorWhenPrettyPrinting ^ self valueOfFlag: #colorWhenPrettyPrinting ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! confirmFirstUseOfStyle ^ self valueOfFlag: #confirmFirstUseOfStyle ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! conversionMethodsAtFileOut ^ self valueOfFlag: #conversionMethodsAtFileOut ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! cpuWatcherEnabled ^ self valueOfFlag: #cpuWatcherEnabled ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! decorateBrowserButtons ^ self valueOfFlag: #decorateBrowserButtons ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! diffsInChangeList ^ self valueOfFlag: #diffsInChangeList ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! diffsWithPrettyPrint ^ self valueOfFlag: #diffsWithPrettyPrint ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! duplicateControlAndAltKeys ^ self valueOfFlag: #duplicateControlAndAltKeys ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! eToyFriendly ^ self valueOfFlag: #eToyFriendly ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! ignoreStyleIfOnlyBold ^ self valueOfFlag: #ignoreStyleIfOnlyBold ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! inboardScrollbars ^ self valueOfFlag: #inboardScrollbars ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! logDebuggerStackToFile ^ self valueOfFlag: #logDebuggerStackToFile ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! menuKeyboardControl ^ self valueOfFlag: #menuKeyboardControl ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! optionalButtons ^ self valueOfFlag: #optionalButtons ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! printAlternateSyntax ^ self valueOfFlag: #printAlternateSyntax ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! projectZoom ^ self valueOfFlag: #projectZoom ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! projectsSentToDisk ^ self valueOfFlag: #projectsSentToDisk ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! restartAlsoProceeds ^ self valueOfFlag: #restartAlsoProceeds ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! reverseWindowStagger ^ self valueOfFlag: #reverseWindowStagger ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! selectionsMayShrink ^ self valueOfFlag: #selectionsMayShrink ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! showDeprecationWarnings ^ self valueOfFlag: #showDeprecationWarnings ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! showSharedFlaps ^ self valueOfFlag: #showSharedFlaps ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! smartUpdating ^ self valueOfFlag: #smartUpdating ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! soundsEnabled ^ self valueOfFlag: #soundsEnabled ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! startInUntrustedDirectory ^ self valueOfFlag: #startInUntrustedDirectory ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! swapControlAndAltKeys ^ self valueOfFlag: #swapControlAndAltKeys ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! swapMouseButtons ^ self valueOfFlag: #swapMouseButtons ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! thoroughSenders ^ self valueOfFlag: #thoroughSenders ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! timeStampsInMenuTitles ^ self valueOfFlag: #timeStampsInMenuTitles ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! translationWithBabel ^ self valueOfFlag: #translationWithBabel ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! twentyFourHourFileStamps ^ self valueOfFlag: #twentyFourHourFileStamps ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! universalTiles ^ self valueOfFlag: #universalTiles ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! warnIfNoChangesFile ^ self valueOfFlag: #warnIfNoChangesFile ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! warnIfNoSourcesFile ^ self valueOfFlag: #warnIfNoSourcesFile ifAbsent: [true]! ! !Preferences class methodsFor: 'standard queries'! warningForMacOSFileNameLength ^ self valueOfFlag: #warningForMacOSFileNameLength ifAbsent: [false]! ! !Preferences class methodsFor: 'standard queries'! wordStyleCursorMovement ^ self valueOfFlag: #wordStyleCursorMovement ifAbsent: [true]! ! !Preferences class methodsFor: 'text highlighting' stamp: 'sw 9/7/1999 13:07'! initializeTextHighlightingParameters "Preferences initializeTextHighlightingParameters" Parameters at: #insertionPointColor put: (Color r: 0.4 g: 1.0 b: 0). Parameters at: #textHighlightColor put: (Color r: 0.4 g: 1.0 b: 0).! ! !Preferences class methodsFor: 'text highlighting' stamp: 'sw 9/7/1999 12:53'! insertionPointColor ^ Parameters at: #insertionPointColor! ! !Preferences class methodsFor: 'text highlighting' stamp: 'sw 9/7/1999 12:53'! textHighlightColor ^ Parameters at: #textHighlightColor! ! !Preferences class methodsFor: 'themes' stamp: 'sw 5/2/2002 10:45'! personal "Settings saved (by sometime earlier having hit the 'Save Current Settings as my Personal Preferences' in a Preferences panel) as my personal preferences" self restorePersonalPreferences! ! !Preferences class methodsFor: 'window colors' stamp: 'sw 2/26/2002 13:56'! installBrightWindowColors "Install the factory-provided default window colors for all tools" "Preferences installBrightWindowColors" self installWindowColorsVia: [:aSpec | aSpec brightColor]! ! !Preferences class methodsFor: 'window colors' stamp: 'sw 2/26/2002 13:59'! installWindowColorsVia: colorSpecBlock "Install windows colors using colorSpecBlock to deliver the color source for each element; the block is handed a WindowColorSpec object" "Preferences installBrightWindowColors" | windowColorDict | (Parameters includesKey: #windowColors) ifFalse: [Parameters at: #windowColors put: IdentityDictionary new]. windowColorDict _ Parameters at: #windowColors. self windowColorTable do: [:aColorSpec | windowColorDict at: aColorSpec classSymbol put: (Color colorFrom: (colorSpecBlock value: aColorSpec))]! ! !Preferences class methodsFor: 'window colors' stamp: 'sw 7/13/1999 16:03'! windowColorFor: aModelClassName | classToCheck windowColors | (Parameters includesKey: #windowColors) ifFalse: [Parameters at: #windowColors put: IdentityDictionary new. self installBrightWindowColors]. classToCheck _ Smalltalk at: aModelClassName. windowColors _ Parameters at: #windowColors. [windowColors includesKey: classToCheck name] whileFalse: [classToCheck _ classToCheck superclass]. ^ windowColors at: classToCheck name ifAbsent: [Color white] ! ! !Preferences class methodsFor: 'window colors' stamp: 'dvf 8/23/2003 12:18'! windowColorTable "Answer a list of WindowColorSpec objects, one for each tool to be represented in the window-color panel" ^ (((self systemNavigation allClassesImplementing: #windowColorSpecification) collect: [:aClass | aClass theNonMetaClass windowColorSpecification]) asSortedCollection: [:specOne :specTwo | specOne wording < specTwo wording]) asArray "Preferences windowColorTable"! ! !Preferences class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:18'! initialize self registerInFlapsRegistry. ! ! !Preferences class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:20'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(Preferences preferencesControlPanel 'Preferences' 'Allows you to control numerous options') forFlapNamed: 'Tools'. cl registerQuad: #(Preferences annotationEditingWindow 'Annotations' 'Allows you to specify the annotations to be shown in the annotation panes of browsers, etc.') forFlapNamed: 'Tools'.]! ! !Preferences class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:38'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !Preferences class methodsFor: 'as yet unclassified' stamp: 'BG 10/31/2003 14:46'! removeObsoleteInstances "Preferences removeObsoleteInstances" | oc | oc := OrderedCollection new. Preference allInstances collect: [:item | ( item changeInformee notNil and: [item changeInformee isObsolete]) ifTrue: [item deleteInformee] ].! ! TextDiffBuilder subclass: #PrettyTextDiffBuilder instanceVariableNames: 'sourceClass' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !PrettyTextDiffBuilder methodsFor: 'initialize' stamp: 'nk 10/29/2000 12:16'! sourceClass: aClass sourceClass _ aClass.! ! !PrettyTextDiffBuilder methodsFor: 'initialize' stamp: 'nk 10/29/2000 12:20'! split: aString | formatted | formatted _ sourceClass compilerClass new format: aString in: sourceClass notifying: nil decorated: false. ^super split: formatted! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PrettyTextDiffBuilder class instanceVariableNames: ''! !PrettyTextDiffBuilder class methodsFor: 'instance creation' stamp: 'nk 10/29/2000 12:35'! from: srcString to: dstString inClass: srcClass ^ (self new sourceClass: srcClass) from: srcString to: dstString ! ]style[(6 9 5 9 10 8 6 4 18 8 8 9 5 9 3)f1b,f1cblack;b,f1b,f1cblack;b,f1b,f1cblack;b,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1! ! Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Processes'! !Process commentStamp: '<historical>' prior: 0! 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. (If anyone ever makes a subclass of Process, be sure to use allSubInstances in anyProcessesAbove:.)! !Process methodsFor: 'changing process state' stamp: 'tpr 2/14/2001 10:00'! primitiveResume "Primitive. Allow the process that the receiver represents to continue. Put the receiver in line to become the activeProcess. Fail if the receiver is already waiting in a queue (in a Semaphore or ProcessScheduler). Essential. See Object documentation whatIsAPrimitive." <primitive: 87> self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'ajh 7/20/2003 22:51'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." <primitive: 88> self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'tpr 2/14/2001 10:03'! resume "Allow the process that the receiver represents to continue. Put the receiver in line to become the activeProcess. Check for a nil suspendedContext, which indicates a previously terminated Process that would cause a vm crash if the resume attempt were permitted" suspendedContext ifNil: [^ self primitiveFailed]. ^ self primitiveResume! ! !Process methodsFor: 'changing process state' stamp: 'ajh 7/20/2003 22:47'! suspend "Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes." self isActiveProcess ifTrue: [ myList _ nil. self primitiveSuspend. ] ifFalse: [ myList ifNotNil: [ myList remove: self ifAbsent: []. myList _ nil]. ] ! ! !Process methodsFor: 'changing process state' stamp: 'nk 6/21/2004 14:07'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock | self isActiveProcess ifTrue: [ ctxt _ thisContext. [ ctxt _ ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ unwindBlock _ ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. myList _ nil. self primitiveSuspend. ] ifFalse: [ myList ifNotNil: [ myList remove: self ifAbsent: []. myList _ nil]. suspendedContext ifNotNil: [ ctxt _ self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/24/2003 16:14'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" ^ suspendedContext _ suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 3/5/2004 03:13'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | ctxt _ suspendedContext. suspendedContext _ nil. "disable this process while running its stack in active process below" pair _ ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext _ pair first. error _ pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/24/2003 10:16'! completeStep: aContext "Resume self until aContext is on top, or if already on top, complete next step" | callee | self suspendedContext == aContext ifFalse: [ ^ self complete: (self calleeOf: aContext)]. callee _ self step. callee == aContext ifTrue: [^ callee]. aContext isDead ifTrue: [^ self suspendedContext]. "returned" ^ self complete: callee "finish send"! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 3/5/2004 03:26'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | self == Processor activeProcess ifTrue: [^ self error: 'The active process cannot pop contexts']. callee _ (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/23/2003 20:40'! restartTop "Rollback top context and replace with new method. Assumes self is suspended" suspendedContext privRefresh! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/23/2003 20:33'! restartTopWith: method "Rollback top context and replace with new method. Assumes self is suspended" suspendedContext privRefreshWith: method. ! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 3/5/2004 03:26'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." suspendedContext == aContext ifTrue: [ ^ suspendedContext _ aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/24/2003 10:17'! step ^ suspendedContext _ suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/31/2003 14:45'! step: aContext "Resume self until aContext is on top, or if already on top, do next step" ^ self suspendedContext == aContext ifTrue: [self step] ifFalse: [self complete: (self calleeOf: aContext)]! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/23/2003 22:06'! stepToCallee "Step until top context changes" | ctxt | ctxt _ suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext _ suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 7/18/2003 22:13'! stepToHome: aContext "Resume self until the home of top context is aContext. Top context may be a block context." | home ctxt | home _ aContext home. [ ctxt _ self step. home == ctxt home. ] whileFalse: [ home isDead ifTrue: [^ self suspendedContext]. ]. ^ self suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'ajh 1/24/2003 10:17'! stepToSendOrReturn ^ suspendedContext _ suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'accessing' stamp: 'ajh 1/24/2003 14:53'! calleeOf: aContext "Return the context whose sender is aContext. Return nil if aContext is on top. Raise error if aContext is not in process chain." suspendedContext == aContext ifTrue: [^ nil]. ^ (suspendedContext findContextSuchThat: [:c | c sender == aContext]) ifNil: [self error: 'aContext not in process chain']! ! !Process methodsFor: 'accessing' stamp: 'ajh 1/24/2003 19:44'! isActiveProcess ^ self == Processor activeProcess! ! !Process methodsFor: 'accessing' stamp: 'nk 10/28/2000 19:55'! isSuspended ^myList isNil! ! !Process methodsFor: 'accessing' stamp: 'ajh 3/4/2004 22:18'! isTerminated self isActiveProcess ifTrue: [^ false]. ^ suspendedContext isNil or: [ suspendedContext == suspendedContext bottomContext and: [ suspendedContext pc > suspendedContext startpc]]! ! !Process methodsFor: 'accessing' stamp: 'svp 12/5/2002 14:42'! name ^name ifNil: [ self hash asString forceTo: 5 paddingStartWith: $ ]! ! !Process methodsFor: 'accessing' stamp: 'svp 12/5/2002 14:42'! name: aString name _ aString! ! !Process methodsFor: 'accessing'! offList "Inform the receiver that it has been taken off a list that it was suspended on. This is to break a backpointer." myList _ nil! ! !Process methodsFor: 'accessing'! priority "Answer the priority of the receiver." ^priority! ! !Process methodsFor: 'accessing' stamp: 'ar 7/8/2001 17:04'! priority: anInteger "Set the receiver's priority to anInteger." (anInteger >= Processor lowestPriority and:[anInteger <= Processor highestPriority]) ifTrue: [priority _ anInteger] ifFalse: [self error: 'Invalid priority: ', anInteger printString]! ! !Process methodsFor: 'accessing'! suspendedContext "Answer the context the receiver has suspended." ^suspendedContext! ! !Process methodsFor: 'accessing'! suspendingList "Answer the list on which the receiver has been suspended." ^myList! ! !Process methodsFor: 'printing' stamp: 'nk 10/28/2000 07:33'! browserPrintString ^self browserPrintStringWith: suspendedContext! ! !Process methodsFor: 'printing' stamp: 'svp 12/5/2002 14:45'! browserPrintStringWith: anObject | stream | stream _ WriteStream on: (String new: 100). stream nextPut: $(. priority printOn: stream. self isSuspended ifTrue: [stream nextPut: $s]. stream nextPutAll: ') '. stream nextPutAll: self name. stream nextPut: $:. stream space. stream nextPutAll: anObject asString. ^ stream contents! ! !Process methodsFor: 'printing' stamp: 'ajh 10/2/2001 14:36'! longPrintOn: stream | ctxt | super printOn: stream. stream cr. ctxt _ self suspendedContext. [ctxt == nil] whileFalse: [ stream space. ctxt printOn: stream. stream cr. ctxt _ ctxt sender. ]. ! ! !Process methodsFor: 'printing'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' in '. suspendedContext printOn: aStream! ! !Process methodsFor: 'private'! suspendedContext: aContext suspendedContext _ aContext! ! !Process methodsFor: 'objects from disk' stamp: 'tk 9/28/2000 15:46'! objectForDataStream: refStrm "I am not allowed to be written on an object file." refStrm replace: self with: nil. ^ nil! ! !Process methodsFor: 'debugging' stamp: 'nk 10/29/2000 13:43'! debug self debugWithTitle: 'Debug'.! ! !Process methodsFor: 'debugging' stamp: 'ajh 7/20/2003 23:54'! debug: context title: title "Open debugger on self with context shown on top" self debug: context title: title full: false. ! ! !Process methodsFor: 'debugging' stamp: 'ajh 7/20/2003 23:53'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt _ self isActiveProcess ifTrue: [thisContext] ifFalse: [self suspendedContext]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. Debugger openOn: self context: context label: title contents: nil fullView: bool. ! ! !Process methodsFor: 'debugging' stamp: 'ajh 7/20/2003 23:55'! debugWithTitle: title "Open debugger on self" | context | context _ self isActiveProcess ifTrue: [thisContext] ifFalse: [self suspendedContext]. self debug: context title: title full: true. ! ! !Process methodsFor: 'signaling' stamp: 'svp 9/19/2003 18:41'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self isActiveProcess ifFalse: [^self]. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'svp 9/19/2003 18:42'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self isActiveProcess ifTrue: [^anException signal]. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Process class instanceVariableNames: ''! !Process class methodsFor: 'instance creation'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess _ self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. ^newProcess! ! Model subclass: #ProcessBrowser instanceVariableNames: 'selectedProcess selectedContext methodText processList processListIndex stackList stackListIndex sourceMap selectedClass selectedSelector searchString autoUpdateProcess deferredMessageRecipient lastUpdate startedCPUWatcher' classVariableNames: 'Browsers SuspendedProcesses' poolDictionaries: '' category: 'Tools-Process Browser'! !ProcessBrowser commentStamp: '<historical>' prior: 0! Change Set: ProcessBrowser Date: 14 March 2000 Author: Ned Konz email: ned@bike-nomad.com This is distributed under the Squeak License. Added 14 March: CPUWatcher integration automatically start and stop CPUWatcher added CPUWatcher to process list menu Added 29 October: MVC version 2.8, 2.7 compatibility rearranged menus added pointer inspection and chasing added suspend/resume recognized more well-known processes misc. bug fixes Added 26 October: highlight pc in source code Added 27 October: added 'signal semaphore' added 'inspect receiver', 'explore receiver', 'message tally' to stack list menu added 'find context', 'next context' to process list menu added 'change priority' and 'debug' choices to process list menu 27 October mods by Bob Arning: alters process display in Ned's ProcessBrowser to - show process priority - drop 'a Process in' that appears on each line - show in priority order - prettier names for known processes - fix to Utilities to forget update downloading process when it ends (1 less dead process) - correct stack dump for the active process ! !ProcessBrowser methodsFor: 'accessing'! processList ^ processList! ! !ProcessBrowser methodsFor: 'accessing'! processListIndex ^ processListIndex! ! !ProcessBrowser methodsFor: 'accessing'! processListIndex: index processListIndex _ index. selectedProcess _ processList at: index ifAbsent: []. self updateStackList. self changed: #processListIndex.! ! !ProcessBrowser methodsFor: 'accessing' stamp: 'nk 2/16/2001 13:39'! selectedMethod ^ methodText ifNil: [methodText _ selectedContext ifNil: [''] ifNotNil: [| pcRange | methodText _ [ selectedContext sourceCode ] ifError: [ :err :rcvr | 'error getting method text' ]. pcRange _ self pcRange. methodText asText addAttribute: TextColor red from: pcRange first to: pcRange last; addAttribute: TextEmphasis bold from: pcRange first to: pcRange last]]! ! !ProcessBrowser methodsFor: 'accessing' stamp: 'ajh 9/7/2002 21:22'! selectedSelector "Answer the class in which the currently selected context's method was found." ^ selectedSelector ifNil: [selectedSelector _ selectedContext receiver ifNil: [| who | who _ selectedContext method. selectedClass _ who first. who last] ifNotNil: [selectedContext methodSelector]]! ! !ProcessBrowser methodsFor: 'accessing'! stackList ^ stackList! ! !ProcessBrowser methodsFor: 'accessing'! stackListIndex ^ stackListIndex! ! !ProcessBrowser methodsFor: 'accessing' stamp: 'nk 10/28/2000 08:57'! stackListIndex: index stackListIndex _ index. selectedContext _ nil. (stackList notNil and: [index > 0]) ifTrue: [selectedContext _ stackList at: index ifAbsent: []]. sourceMap _ nil. selectedClass _ nil. selectedSelector _ nil. methodText _ nil. self changed: #stackListIndex. self changed: #selectedMethod! ! !ProcessBrowser methodsFor: 'accessing' stamp: 'nk 10/28/2000 08:36'! text ^methodText! ! !ProcessBrowser methodsFor: 'initialize-release' stamp: 'nk 10/31/2001 10:54'! initialize methodText _ ''. stackListIndex _ 0. searchString _ ''. lastUpdate _ 0. startedCPUWatcher _ Preferences cpuWatcherEnabled and: [ self startCPUWatcher ]. self updateProcessList; processListIndex: 1! ! !ProcessBrowser methodsFor: 'initialize-release' stamp: 'nk 3/14/2001 09:26'! startCPUWatcher "Answers whether I started the CPUWatcher" | pw | pw _ Smalltalk at: #CPUWatcher ifAbsent: [ ^self ]. pw ifNotNil: [ pw isMonitoring ifFalse: [ pw startMonitoringPeriod: 5 rate: 100 threshold: 0.85. self setUpdateCallbackAfter: 7. ^true ] ]. ^false ! ! !ProcessBrowser methodsFor: 'initialize-release' stamp: 'nk 3/14/2001 09:26'! stopCPUWatcher | pw | pw _ Smalltalk at: #CPUWatcher ifAbsent: [ ^self ]. pw ifNotNil: [ pw stopMonitoring. self updateProcessList. startedCPUWatcher _ false. "so a manual restart won't be killed later" ] ! ! !ProcessBrowser methodsFor: 'initialize-release' stamp: 'nk 3/14/2001 08:03'! windowIsClosing startedCPUWatcher ifTrue: [ CPUWatcher stopMonitoring ]! ! !ProcessBrowser methodsFor: 'menus' stamp: 'nk 10/26/2000 23:31'! selectedClass "Answer the class in which the currently selected context's method was found." ^ selectedClass ifNil: [selectedClass _ selectedContext receiver ifNil: [| who | who _ selectedContext method who. selectedSelector _ who last. who first] ifNotNil: [selectedContext mclass]]! ! !ProcessBrowser methodsFor: 'message handling' stamp: 'nk 10/28/2000 20:53'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ super perform: selector orSendTo: otherTarget]! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 17:02'! changePriority | str newPriority nameAndRules | nameAndRules _ self nameAndRulesForSelectedProcess. nameAndRules third ifFalse: [PopUpMenu inform: 'Nope, won''t change priority of ' , nameAndRules first. ^ self]. str _ FillInTheBlank request: 'New priority' initialAnswer: selectedProcess priority asString. newPriority _ str asNumber asInteger. newPriority ifNil: [^ self]. (newPriority < 1 or: [newPriority > Processor highestPriority]) ifTrue: [PopUpMenu inform: 'Bad priority'. ^ self]. self class setProcess: selectedProcess toPriority: newPriority. self updateProcessList! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 10/29/2000 10:18'! chasePointers | saved | selectedProcess ifNil: [^ self]. saved _ selectedProcess. [selectedProcess _ nil. (Smalltalk includesKey: #PointerFinder) ifTrue: [PointerFinder on: saved] ifFalse: [self inspectPointers]] ensure: [selectedProcess _ saved]! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 16:37'! debugProcess | nameAndRules | nameAndRules _ self nameAndRulesForSelectedProcess. nameAndRules third ifFalse: [PopUpMenu inform: 'Nope, won''t debug ' , nameAndRules first. ^ self]. self class debugProcess: selectedProcess.! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 10/29/2000 10:17'! inspectPointers | tc pointers | selectedProcess ifNil: [^ self]. tc _ thisContext. pointers _ Smalltalk pointersTo: selectedProcess except: {self processList. tc. self}. pointers isEmpty ifTrue: [^ self]. OrderedCollectionInspector openOn: pointers withEvalPane: false withLabel: 'Objects pointing to ' , selectedProcess browserPrintString ! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 13:35'! nameAndRulesFor: aProcess "Answer a nickname and two flags: allow-stop, and allow-debug" aProcess == autoUpdateProcess ifTrue: [ ^{'my auto-update process'. true. true} ]. ^self class nameAndRulesFor: aProcess ! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 10/28/2000 20:31'! nameAndRulesForSelectedProcess "Answer a nickname and two flags: allow-stop, and allow-debug" ^self nameAndRulesFor: selectedProcess! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 13:23'! resumeProcess selectedProcess ifNil: [^ self]. self class resumeProcess: selectedProcess. self updateProcessList! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 10/29/2000 09:58'! signalSemaphore (selectedProcess suspendingList isKindOf: Semaphore) ifFalse: [^ self]. [selectedProcess suspendingList signal] fork. (Delay forMilliseconds: 300) wait. "Hate to make the UI wait, but it's convenient..." self updateProcessList! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 13:21'! suspendProcess | nameAndRules | selectedProcess isSuspended ifTrue: [^ self]. nameAndRules _ self nameAndRulesForSelectedProcess. nameAndRules second ifFalse: [PopUpMenu inform: 'Nope, won''t suspend ' , nameAndRules first. ^ self]. self class suspendProcess: selectedProcess. self updateProcessList! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 3/8/2001 13:25'! terminateProcess | nameAndRules | nameAndRules _ self nameAndRulesForSelectedProcess. nameAndRules second ifFalse: [PopUpMenu inform: 'Nope, won''t kill ' , nameAndRules first. ^ self]. self class terminateProcess: selectedProcess. self updateProcessList! ! !ProcessBrowser methodsFor: 'process actions' stamp: 'nk 10/29/2000 08:56'! wasProcessSuspendedByProcessBrowser: aProcess ^self class suspendedProcesses includesKey: aProcess! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/27/2000 09:24'! exploreProcess selectedProcess explore! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/27/2000 11:53'! findContext | initialProcessIndex initialStackIndex found | initialProcessIndex _ self processListIndex. initialStackIndex _ self stackListIndex. searchString _ FillInTheBlank request: 'Enter a string to search for in the process stack lists' initialAnswer: searchString. searchString isEmpty ifTrue: [^ false]. self processListIndex: 1. self stackListIndex: 1. found _ self nextContext. found ifFalse: [self processListIndex: initialProcessIndex. self stackListIndex: initialStackIndex]. ^ found! ! !ProcessBrowser methodsFor: 'process list'! inspectProcess selectedProcess inspect! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/27/2000 11:52'! nextContext | initialProcessIndex initialStackIndex found | searchString isEmpty ifTrue: [ ^false ]. initialProcessIndex _ self processListIndex. initialStackIndex _ self stackListIndex. found _ false. initialProcessIndex to: self processList size do: [:pi | found ifFalse: [self processListIndex: pi. self stackNameList withIndexDo: [:name :si | (found not and: [pi ~= initialProcessIndex or: [si > initialStackIndex]]) ifTrue: [(name includesSubString: searchString) ifTrue: [self stackListIndex: si. found _ true]]]]]. found ifFalse: [self processListIndex: initialProcessIndex. self stackListIndex: initialStackIndex]. ^ found! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/28/2000 08:19'! notify: errorString at: location in: aStream "A syntax error happened when I was trying to highlight my pc. Raise a signal so that it can be ignored." Warning signal: 'syntax error'! ]style[(8 11 5 8 5 7 3 107 2 7 23)f1b,f1cblack;b,f1b,f1cblack;b,f1b,f1cblack;b,f1,f1c142040000,f1,f1cblack;,f1! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/28/2000 20:30'! prettyNameForProcess: aProcess | nameAndRules | nameAndRules _ self nameAndRulesFor: aProcess. ^ aProcess browserPrintStringWith: nameAndRules first! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 10/29/2000 10:20'! processListKey: aKey from: aView ^ aKey caseOf: { [$i] -> [self inspectProcess]. [$I] -> [self exploreProcess]. [$c] -> [self chasePointers]. [$P] -> [self inspectPointers]. [$t] -> [self terminateProcess]. [$r] -> [self resumeProcess]. [$s] -> [self suspendProcess]. [$d] -> [self debugProcess]. [$p] -> [self changePriority]. [$m] -> [self messageTally]. [$f] -> [self findContext]. [$g] -> [self nextContext]. [$a] -> [self toggleAutoUpdate]. [$u] -> [self updateProcessList]. [$S] -> [self signalSemaphore]. [$k] -> [self moreStack]} otherwise: [self arrowKey: aKey from: aView]! ! !ProcessBrowser methodsFor: 'process list' stamp: 'LC 1/7/2002 16:35'! processListMenu: menu | pw | selectedProcess ifNotNil: [| nameAndRules | nameAndRules _ self nameAndRulesForSelectedProcess. menu addList: {{'inspect (i)'. #inspectProcess}. {'explore (I)'. #exploreProcess}. {'inspect Pointers (P)'. #inspectPointers}}. (Smalltalk includesKey: #PointerFinder) ifTrue: [ menu add: 'chase pointers (c)' action: #chasePointers. ]. nameAndRules second ifTrue: [menu add: 'terminate (t)' action: #terminateProcess. selectedProcess isSuspended ifTrue: [menu add: 'resume (r)' action: #resumeProcess] ifFalse: [menu add: 'suspend (s)' action: #suspendProcess]]. nameAndRules third ifTrue: [menu addList: {{'change priority (p)'. #changePriority}. {'debug (d)'. #debugProcess}}]. menu addList: {{'profile messages (m)'. #messageTally}}. (selectedProcess suspendingList isKindOf: Semaphore) ifTrue: [menu add: 'signal Semaphore (S)' action: #signalSemaphore]. menu add: 'full stack (k)' action: #moreStack. menu addLine]. menu addList: {{'find context... (f)'. #findContext}. {'find again (g)'. #nextContext}}. menu addLine. menu add: (self isAutoUpdating ifTrue: ['turn off auto-update (a)'] ifFalse: ['turn on auto-update (a)']) action: #toggleAutoUpdate. menu add: 'update list (u)' action: #updateProcessList. pw _ Smalltalk at: #CPUWatcher ifAbsent: []. pw ifNotNil: [ menu addLine. pw isMonitoring ifTrue: [ menu add: 'stop CPUWatcher' action: #stopCPUWatcher ] ifFalse: [ menu add: 'start CPUWatcher' action: #startCPUWatcher ] ]. ^ menu! ! !ProcessBrowser methodsFor: 'process list' stamp: 'nk 6/21/2004 09:59'! processNameList "since processList is a WeakArray, we have to strengthen the result" | pw tally | pw _ Smalltalk at: #CPUWatcher ifAbsent: [ ]. tally _ pw ifNotNil: [ pw current ifNotNil: [ pw current tally ] ]. ^ (processList asOrderedCollection copyWithout: nil) collect: [:each | | percent | percent _ tally ifNotNil: [ ((((tally occurrencesOf: each) * 100.0 / tally size) roundTo: 1) asString padded: #left to: 2 with: $ ), '% ' ] ifNil: [ '' ]. percent, (self prettyNameForProcess: each) ] ! ! !ProcessBrowser methodsFor: 'process list' stamp: 'ajh 7/21/2003 10:11'! updateProcessList | oldSelectedProcess newIndex now | now _ Time millisecondClockValue. now - lastUpdate < 500 ifTrue: [^ self]. "Don't update too fast" lastUpdate _ now. oldSelectedProcess _ selectedProcess. processList _ selectedProcess _ selectedSelector _ nil. Smalltalk garbageCollectMost. "lose defunct processes" processList _ Process allSubInstances reject: [:each | each isTerminated]. processList _ processList sortBy: [:a :b | a priority >= b priority]. processList _ WeakArray withAll: processList. newIndex _ processList indexOf: oldSelectedProcess ifAbsent: [0]. self changed: #processNameList. self processListIndex: newIndex! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/28/2000 16:49'! browseContext selectedContext ifNil: [^ self]. Browser newOnClass: self selectedClass selector: self selectedSelector! ]style[(13 30 4 4 7 42 4 17)f1b,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'RAA 10/27/2000 15:21'! changeStackListTo: aCollection stackList _ aCollection. self changed: #stackNameList. self stackListIndex: 0! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/27/2000 09:28'! exploreContext selectedContext explore! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/27/2000 09:41'! exploreReceiver selectedContext ifNotNil: [ selectedContext receiver explore ]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 7/8/2000 20:23'! inspectContext selectedContext inspect! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/27/2000 09:41'! inspectReceiver selectedContext ifNotNil: [selectedContext receiver inspect]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'BG 10/29/2003 10:17'! messageTally | secString secs | secString _ FillInTheBlank request: 'Profile for how many seconds?' initialAnswer: '4'. secs _ secString asNumber asInteger. (secs isNil or: [secs isZero]) ifTrue: [^ self]. ! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/28/2000 12:13'! moreStack self updateStackList: 2000! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 7/4/2003 19:55'! pcRange "Answer the indices in the source code for the method corresponding to the selected context's program counter value." | i methodNode pc end tempNames | methodText isEmptyOrNil ifTrue: [^ 1 to: 0]. sourceMap == nil ifTrue: [self selectedClass == #unknown ifTrue: [^ 1 to: 0]. [[methodNode _ self selectedClass compilerClass new parse: methodText in: self selectedClass notifying: self ] on: Warning do: [:ex | methodText _ ('(syntax error) ' , ex description , String cr , methodText) asText. ex return]] on: Error do: [:ex | methodText _ ('(parse error) ' , ex description , String cr , methodText) asText. ex return]. methodNode ifNil: [sourceMap _ nil. ^ 1 to: 0]. sourceMap _ methodNode sourceMap. tempNames _ methodNode tempNames. selectedContext method cacheTempNames: tempNames]. (sourceMap size = 0 or: [ selectedContext isDead ]) ifTrue: [^ 1 to: 0]. pc _ selectedContext pc. pc _ pc - 2. i _ sourceMap indexForInserting: (Association key: pc value: nil). i < 1 ifTrue: [^ 1 to: 0]. i > sourceMap size ifTrue: [end _ sourceMap inject: 0 into: [:prev :this | prev max: this value last]. ^ end + 1 to: end]. ^ (sourceMap at: i) value! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/28/2000 16:53'! stackListMenu: aMenu | menu | selectedContext ifNil: [^ aMenu]. menu _ aMenu labels: 'inspect context (c) explore context (C) inspect receiver (i) explore receiver (I) browse (b)' lines: #(2 4 ) selections: #(#inspectContext #exploreContext #inspectReceiver #exploreReceiver #browseContext ). ^ menu! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/28/2000 16:18'! stackNameList ^ stackList ifNil: [#()] ifNotNil: [stackList collect: [:each | each asString]]! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 7/8/2000 20:24'! updateStackList self updateStackList: 20! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'nk 10/28/2000 09:00'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight _ stackList at: stackListIndex]. selectedProcess == Processor activeProcess ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext _ selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ]style[(17 5 4 30 4 15 13 4 20 3 29 14 3 4 12 12 3 9 5 14 4 15 4 9 26 4 25 11 14 5 15 16 3 15 22 16 13 4 20 3 17 4 27 16 14 5 6 4 20 9 13 1 17 9 10 12 2)f1b,f1cblack;b,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblue;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblue;,f1,f1cblack;,f1,f1cblack;,f1! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 10/28/2000 21:48'! isAutoUpdating ^autoUpdateProcess notNil and: [ autoUpdateProcess isSuspended not ]! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 6/18/2003 07:20'! isAutoUpdatingPaused ^autoUpdateProcess notNil and: [ autoUpdateProcess isSuspended ]! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 6/18/2003 07:20'! pauseAutoUpdate self isAutoUpdating ifTrue: [ autoUpdateProcess suspend ]. self updateProcessList! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 3/14/2001 09:08'! setUpdateCallbackAfter: seconds deferredMessageRecipient ifNotNil: [ | d | d _ Delay forSeconds: seconds. [ d wait. d _ nil. deferredMessageRecipient addDeferredUIMessage: [self updateProcessList] ] fork ]! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 6/18/2003 07:21'! startAutoUpdate self isAutoUpdatingPaused ifTrue: [ ^autoUpdateProcess resume ]. self isAutoUpdating ifFalse: [| delay | delay _ Delay forSeconds: 2. autoUpdateProcess _ [[self hasView] whileTrue: [delay wait. deferredMessageRecipient ifNotNil: [ deferredMessageRecipient addDeferredUIMessage: [self updateProcessList]] ifNil: [ self updateProcessList ]]. autoUpdateProcess _ nil] fork]. self updateProcessList! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 6/18/2003 07:22'! stopAutoUpdate autoUpdateProcess ifNotNil: [ autoUpdateProcess terminate. autoUpdateProcess _ nil]. self updateProcessList! ! !ProcessBrowser methodsFor: 'updating' stamp: 'nk 10/28/2000 21:50'! toggleAutoUpdate self isAutoUpdating ifTrue: [ self stopAutoUpdate ] ifFalse: [ self startAutoUpdate ]. ! ! !ProcessBrowser methodsFor: 'views' stamp: 'nk 10/28/2000 11:44'! hasView ^self dependents isEmptyOrNil not! ! !ProcessBrowser methodsFor: 'views' stamp: 'nk 3/14/2001 09:04'! openAsMVC "Create a pluggable version of me, answer a window" | window processListView stackListView methodTextView | window _ StandardSystemView new model: self controller: (deferredMessageRecipient _ DeferredActionStandardSystemController new). window borderWidth: 1. processListView _ PluggableListView on: self list: #processNameList selected: #processListIndex changeSelected: #processListIndex: menu: #processListMenu: keystroke: #processListKey:from:. processListView window: (0 @ 0 extent: 300 @ 200). window addSubView: processListView. stackListView _ PluggableListView on: self list: #stackNameList selected: #stackListIndex changeSelected: #stackListIndex: menu: #stackListMenu: keystroke: #stackListKey:from:. stackListView window: (300 @ 0 extent: 300 @ 200). window addSubView: stackListView toRightOf: processListView. methodTextView _ PluggableTextView on: self text: #selectedMethod accept: nil readSelection: nil menu: nil. methodTextView askBeforeDiscardingEdits: false. methodTextView window: (0 @ 200 corner: 600 @ 400). window addSubView: methodTextView below: processListView. window setUpdatablePanesFrom: #(#processNameList #stackNameList ). window label: 'Process Browser'. window minimumSize: 300 @ 200. window subViews do: [:each | each controller]. window controller open. startedCPUWatcher ifTrue: [ self setUpdateCallbackAfter: 7 ]. ^ window! ! !ProcessBrowser methodsFor: 'views' stamp: 'nk 10/28/2000 16:53'! stackListKey: aKey from: aView ^ aKey caseOf: { [$c] -> [self inspectContext]. [$C] -> [self exploreContext]. [$i] -> [self inspectReceiver]. [$I] -> [self exploreReceiver]. [$b] -> [self browseContext]} otherwise: [self arrowKey: aKey from: aView]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProcessBrowser class instanceVariableNames: ''! !ProcessBrowser class methodsFor: 'instance creation' stamp: 'BG 10/29/2003 00:38'! open "ProcessBrowser open" "Create and schedule a ProcessBrowser." Smalltalk garbageCollect. ^ Smalltalk isMorphic ifTrue: [ ] ifFalse: [ self new openAsMVC ]! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 3/8/2001 17:09'! debugProcess: aProcess self resumeProcess: aProcess. aProcess debugWithTitle: 'Interrupted from the Process Browser'. ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'ssa 9/3/2008 11:08'! isUIProcess: aProcess ^aProcess == ScheduledControllers activeControllerProcess ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 4/12/2004 19:37'! nameAndRulesFor: aProcess "Answer a nickname and two flags: allow-stop, and allow-debug" ^ [aProcess caseOf: { [] -> [{'no process'. false. false}]. [Smalltalk lowSpaceWatcherProcess] -> [{'the low space watcher'. false. false}]. [WeakArray runningFinalizationProcess] -> [{'the WeakArray finalization process'. false. false}]. [Processor activeProcess] -> [{'the UI process'. false. true}]. [Processor backgroundProcess] -> [{'the idle process'. false. false}]. [Sensor interruptWatcherProcess] -> [{'the user interrupt watcher'. false. false}]. [Sensor eventTicklerProcess] -> [{'the event tickler'. false. false}]. [Project uiProcess] -> [{'the inactive Morphic UI process'. false. false}]. [Smalltalk at: #SoundPlayer ifPresent: [:sp | sp playerProcess]] -> [{'the Sound Player'. false. false}]. [ScheduledControllers ifNotNil: [ScheduledControllers activeControllerProcess]] -> [{'the inactive MVC controller process'. false. true}]. [Smalltalk at: #CPUWatcher ifPresent: [:cw | cw currentWatcherProcess]] -> [{'the CPUWatcher'. false. false}]} otherwise: [(aProcess priority = Processor timingPriority and: [aProcess suspendedContext receiver == Delay]) ifTrue: [{'the timer interrupt watcher'. false. false}] ifFalse: [{aProcess suspendedContext asString. true. true}]]] ifError: [:err :rcvr | {aProcess suspendedContext asString. true. true}]! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 2/12/2002 10:09'! resumeProcess: aProcess | priority | priority _ self suspendedProcesses removeKey: aProcess ifAbsent: [aProcess priority]. aProcess priority: priority. aProcess suspendedContext ifNotNil: [ aProcess resume ] ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 3/8/2001 17:07'! setProcess: aProcess toPriority: priority | oldPriority | oldPriority _ self suspendedProcesses at: aProcess ifAbsent: [ ]. oldPriority ifNotNil: [ self suspendedProcesses at: aProcess put: priority ]. aProcess priority: priority. ^oldPriority! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'dew 9/16/2001 01:53'! suspendProcess: aProcess | priority | priority _ aProcess priority. self suspendedProcesses at: aProcess put: priority. "Need to take the priority down below the caller's so that it can keep control after signaling the Semaphore" (aProcess suspendingList isKindOf: Semaphore) ifTrue: [aProcess priority: Processor lowestPriority. aProcess suspendingList signal]. [aProcess suspend] on: Error do: [:ex | self suspendedProcesses removeKey: aProcess]. aProcess priority: priority. ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 10/29/2000 08:55'! suspendedProcesses "Answer a collection of processes that my instances have suspended. This is so that they don't get garbage collected." ^ SuspendedProcesses ifNil: [SuspendedProcesses _ IdentityDictionary new]! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 3/8/2001 13:25'! terminateProcess: aProcess aProcess ifNotNil: [ self suspendedProcesses removeKey: aProcess ifAbsent: []. aProcess terminate ]. ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'nk 3/8/2001 13:26'! wasProcessSuspendedByProcessBrowser: aProcess ^self suspendedProcesses includesKey: aProcess! ! !ProcessBrowser class methodsFor: 'CPU utilization' stamp: 'nk 3/14/2001 08:59'! dumpTallyOnTranscript: tally "tally is from ProcessorScheduler>>tallyCPUUsageFor: Dumps lines with percentage of time, hash of process, and a friendly name" tally sortedCounts do: [ :assoc | | procName | procName _ (self nameAndRulesFor: assoc value) first. Transcript print: (((assoc key / tally size) * 100.0) roundTo: 1); nextPutAll: '% '; print: assoc value identityHash; space; nextPutAll: procName; cr. ]. Transcript flush.! ! !ProcessBrowser class methodsFor: 'CPU utilization' stamp: 'nk 3/8/2001 12:49'! tallyCPUUsageFor: seconds "Compute CPU usage using a 10-msec sample for the given number of seconds, then dump the usage statistics on the Transcript. The UI is free to continue, meanwhile" "ProcessBrowser tallyCPUUsageFor: 10" ^self tallyCPUUsageFor: seconds every: 10! ! !ProcessBrowser class methodsFor: 'CPU utilization' stamp: 'BG 10/29/2003 01:07'! tallyCPUUsageFor: seconds every: msec "Compute CPU usage using a msec millisecond sample for the given number of seconds, then dump the usage statistics on the Transcript. The UI is free to continue, meanwhile" "ProcessBrowser tallyCPUUsageFor: 10 every: 100" | promise | promise _ Processor tallyCPUUsageFor: seconds every: msec. [ | tally | tally _ promise value. Smalltalk isMorphic ifTrue: [ ] ifFalse: [ [ Transcript open ] forkAt: Processor userSchedulingPriority. [ (Delay forSeconds: 1) wait. self dumpTallyOnTranscript: tally ] forkAt: Processor userSchedulingPriority.] ] fork.! ! !ProcessBrowser class methodsFor: 'class initialization' stamp: 'nk 6/18/2003 07:31'! initialize "ProcessBrowser initialize" Browsers ifNil: [ Browsers _ WeakSet new ]. SuspendedProcesses ifNil: [ SuspendedProcesses _ IdentityDictionary new ]. Smalltalk addToStartUpList: self. Smalltalk addToShutDownList: self. self registerInFlapsRegistry.! ! !ProcessBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 10:22'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(ProcessBrowser prototypicalToolWindow 'Processes' 'A Process Browser shows you all the running processes') forFlapNamed: 'Tools'.]! ! !ProcessBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:39'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !ProcessBrowser class methodsFor: 'as yet unclassified' stamp: 'nk 6/18/2003 07:32'! shutDown Browsers do: [ :ea | ea isAutoUpdating ifTrue: [ ea pauseAutoUpdate ]]! ! !ProcessBrowser class methodsFor: 'as yet unclassified' stamp: 'nk 6/18/2003 07:32'! startUp Browsers do: [ :ea | ea isAutoUpdatingPaused ifTrue: [ ea startAutoUpdate ]]! ! Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'! !ProcessorScheduler commentStamp: '<historical>' prior: 0! My single instance, named Processor, coordinates the use of the physical processor by all Processes requiring service.! !ProcessorScheduler methodsFor: 'accessing'! activePriority "Answer the priority level of the currently running Process." ^activeProcess priority! ! !ProcessorScheduler methodsFor: 'accessing'! activeProcess "Answer the currently running Process." ^activeProcess! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'nk 10/27/2000 16:27'! backgroundProcess "Answer the background process" ^ BackgroundProcess! ! !ProcessorScheduler methodsFor: 'accessing'! highestPriority "Answer the number of priority levels currently available for use." ^quiescentProcessLists size! ! !ProcessorScheduler methodsFor: 'removing'! remove: aProcess ifAbsent: aBlock "Remove aProcess from the list on which it is waiting for the processor and answer aProcess. If it is not waiting, evaluate aBlock." (quiescentProcessLists at: aProcess priority) remove: aProcess ifAbsent: aBlock. ^aProcess! ! !ProcessorScheduler methodsFor: 'process state change'! terminateActive "Terminate the process that is currently running." activeProcess terminate! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'tpr 4/28/2004 17:53'! yield "Give other Processes at the current priority a chance to run." | semaphore | <primitive: 167> semaphore _ Semaphore new. [semaphore signal] fork. semaphore wait! ! !ProcessorScheduler methodsFor: 'priority names'! lowIOPriority "Answer the priority at which most input/output processes should run. Examples are the process handling input from the user (keyboard, pointing device, etc.) and the process distributing input from a network." ^LowIOPriority! ! !ProcessorScheduler methodsFor: 'priority names' stamp: 'ar 7/8/2001 17:02'! lowestPriority "Return the lowest priority that is allowed with the scheduler" ^SystemRockBottomPriority! ! !ProcessorScheduler methodsFor: 'priority names'! timingPriority "Answer the priority at which the system processes keeping track of real time should run." ^TimingPriority! ! !ProcessorScheduler methodsFor: 'priority names'! userInterruptPriority "Answer the priority at which user processes desiring immediate service should run. Processes run at this level will preempt the window scheduler and should, therefore, not consume the processor forever." ^UserInterruptPriority! ! !ProcessorScheduler methodsFor: 'priority names'! userSchedulingPriority "Answer the priority at which the window scheduler should run." ^UserSchedulingPriority! ! !ProcessorScheduler methodsFor: 'CPU usage tally' stamp: 'nk 3/8/2001 12:56'! nextReadyProcess quiescentProcessLists reverseDo: [ :list | list isEmpty ifFalse: [ | proc | proc _ list first. proc suspendedContext ifNotNil: [ ^proc ]]]. ^nil! ! !ProcessorScheduler methodsFor: 'CPU usage tally' stamp: 'nk 3/8/2001 12:48'! tallyCPUUsageFor: seconds "Start a high-priority process that will tally the next ready process for the given number of seconds. Answer a Block that will return the tally (a Bag) after the task is complete" ^self tallyCPUUsageFor: seconds every: 10 ! ! !ProcessorScheduler methodsFor: 'CPU usage tally' stamp: 'nk 3/17/2001 10:06'! tallyCPUUsageFor: seconds every: msec "Start a high-priority process that will tally the next ready process for the given number of seconds. Answer a Block that will return the tally (a Bag) after the task is complete" | tally sem delay endDelay | tally _ IdentityBag new: 200. delay _ Delay forMilliseconds: msec truncated. endDelay _ Delay forSeconds: seconds. endDelay schedule. sem _ Semaphore new. [ [ endDelay isExpired ] whileFalse: [ delay wait. tally add: Processor nextReadyProcess ]. sem signal. ] forkAt: self highestPriority. ^[ sem wait. tally ]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProcessorScheduler class instanceVariableNames: ''! !ProcessorScheduler class methodsFor: 'class initialization' stamp: 'ar 7/8/2001 16:39'! initialize SystemRockBottomPriority _ 10. SystemBackgroundPriority _ 20. UserBackgroundPriority _ 30. UserSchedulingPriority _ 40. UserInterruptPriority _ 50. LowIOPriority _ 60. HighIOPriority _ 70. TimingPriority _ 80. "ProcessorScheduler initialize."! ! !ProcessorScheduler class methodsFor: 'instance creation'! new "New instances of ProcessorScheduler should not be created." self error: 'New ProcessSchedulers should not be created since the integrity of the system depends on a unique scheduler'! ! !ProcessorScheduler class methodsFor: 'background process' stamp: 'jm 9/11/97 10:44'! idleProcess "A default background process which is invisible." [true] whileTrue: [self relinquishProcessorForMicroseconds: 1000]! ! !ProcessorScheduler class methodsFor: 'background process' stamp: 'jm 9/3/97 11:17'! relinquishProcessorForMicroseconds: anInteger "Platform specific. This primitive is used to return processor cycles to the host operating system when Squeak's idle process is running (i.e., when no other Squeak process is runnable). On some platforms, this primitive causes the entire Squeak application to sleep for approximately the given number of microseconds. No Squeak process can run while the Squeak application is sleeping, even if some external event makes it runnable. On the Macintosh, this primitive simply calls GetNextEvent() to give other applications a chance to run. On platforms without a host operating system, it does nothing. This primitive should not be used to add pauses to a Squeak process; use a Delay instead." <primitive: 230> "don't fail if primitive is not implemented, just do nothing" ! ! !ProcessorScheduler class methodsFor: 'background process' stamp: 'di 2/4/1999 08:45'! startUp "Install a background process of the lowest possible priority that is always runnable." "Details: The virtual machine requires that there is aways some runnable process that can be scheduled; this background process ensures that this is the case." Smalltalk installLowSpaceWatcher. BackgroundProcess == nil ifFalse: [BackgroundProcess terminate]. BackgroundProcess _ [self idleProcess] newProcess. BackgroundProcess priority: SystemRockBottomPriority. BackgroundProcess resume. ! ! Exception subclass: #ProgressInitiationException instanceVariableNames: 'workBlock maxVal minVal aPoint progressTitle' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !ProgressInitiationException commentStamp: '<historical>' prior: 0! I provide a way to alter the behavior of the old-style progress notifier in String. See examples in: ProgressInitiationException testWithout. ProgressInitiationException testWith. ! !ProgressInitiationException methodsFor: 'as yet unclassified' stamp: 'RAA 6/6/2000 18:46'! defaultAction | delta savedArea captionText textFrame barFrame outerFrame result range lastW w | barFrame _ aPoint - (75@10) corner: aPoint + (75@10). captionText _ DisplayText text: progressTitle asText allBold. captionText foregroundColor: Color black backgroundColor: Color white. textFrame _ captionText boundingBox insetBy: -4. textFrame _ textFrame align: textFrame bottomCenter with: barFrame topCenter + (0@2). outerFrame _ barFrame merge: textFrame. delta _ outerFrame amountToTranslateWithin: Display boundingBox. barFrame _ barFrame translateBy: delta. textFrame _ textFrame translateBy: delta. outerFrame _ outerFrame translateBy: delta. savedArea _ Form fromDisplay: outerFrame. Display fillBlack: barFrame; fillWhite: (barFrame insetBy: 2). Display fillBlack: textFrame; fillWhite: (textFrame insetBy: 2). captionText displayOn: Display at: textFrame topLeft + (4@4). range _ maxVal = minVal ifTrue: [1] ifFalse: [maxVal - minVal]. "Avoid div by 0" lastW _ 0. result _ workBlock value: "Supply the bar-update block for evaluation in the work block" [:barVal | w _ ((barFrame width-4) asFloat * ((barVal-minVal) asFloat / range min: 1.0)) asInteger. w ~= lastW ifTrue: [ Display fillGray: (barFrame topLeft + (2@2) extent: w@16). lastW _ w]]. savedArea displayOn: Display at: outerFrame topLeft. self resume: result! ! !ProgressInitiationException methodsFor: 'as yet unclassified' stamp: 'RAA 5/15/2000 11:43'! display: argString at: argPoint from: argMinVal to: argMaxVal during: argWorkBlock progressTitle _ argString. aPoint _ argPoint. minVal _ argMinVal. maxVal _ argMaxVal. workBlock _ argWorkBlock. ^self signal! ! !ProgressInitiationException methodsFor: 'as yet unclassified' stamp: 'RAA 5/15/2000 12:39'! isResumable ^true! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProgressInitiationException class instanceVariableNames: ''! !ProgressInitiationException class methodsFor: 'signalling' stamp: 'ajh 1/22/2003 23:51'! display: aString at: aPoint from: minVal to: maxVal during: workBlock ^ self new display: aString at: aPoint from: minVal to: maxVal during: workBlock! ! Model subclass: #Project instanceVariableNames: 'world changeSet transcript parentProject previousProject displayDepth viewSize thumbnail nextProject guards projectParameters isolatedHead inForce version urlList environment lastDirectory lastSavedAtSeconds projectPreferenceFlagDictionary resourceManager' classVariableNames: 'AllProjects CurrentProject GoalFreePercent GoalNotMoreThan UIProcess' poolDictionaries: '' category: 'System-Support'! !Project commentStamp: '<historical>' prior: 0! A Project stores the state of a complete Squeak desktop, including the windows, and the currently active changeSet. A project knows who its parent project is. When you change projects, whether by entering or exiting, the screen state of the project being exited is saved in that project. A project is retained by its view in the parent world. It is effectively named by the name of its changeSet, which can be changed either by renaming in a changeSorter, or by editing the label of its view from the parent project. As the site of major context switch, Projects are the locus of swapping between the old MVC and the new Morphic worlds. The distinction is based on whether the variable 'world' contains a WorldMorph or a ControlManager. Saving and Loading Projects may be stored on the disk in external format. (Project named: 'xxx') exportSegment, or choose 'store project on file...'. Projects may be loaded from a server and stored back. Storing on a server never overwrites; it always makes a new version. A project remembers the url of where it lives in urlList. The list is length one, for now. The url may point to a local disk instead of a server. All projects that the user looks at, are cached in the Squeaklet folder. Sorted by server. The cache holds the most recent version only. Isolation When you accept a method, the entire system feels the change, except projects that are "isolated". In an isolated project, all new global variables (including new classes) are stored in the project-local environment, and all changes to preexisting classes are revoked when you leave the project. When you enter another project, that project's changes are invoked. Invocation and revocation are handled efficiently by swapping pointers. To make a project be isolated, choose 'isolate changes of this project' from the 'changes...' section of the screen menu. You can use an isolated project for making dangerous change to a system, and you can get out if it crashes. A foreign application can have the separate environment it wants. Also, you can freeze part of the system for a demo that you don't want to disturb. An isolated project shares methods with all subprojects inside it, unless they are isolated themselves. Each isolated project is the head of a tree of projects with which it shares all methods. You may 'assert' all changes ever made in the current project to take effect above this project. This amounts to exporting all the globals in the current environment, and zapping the revocation lists to that the current state of the world will remain in force upon exit from this project. [Later: A project may be 'frozen'. Asserts do not apply to it after that. (Great for demos.) You should be informed when an assert was blocked in a frozen project.] Class definitions are layered by the isolation mechanism. You are only allowed to change the shape of a class in projects that lie within its isolation scope. All versions of the methods are recompiled, in all projects. If you remove an inst var that is in use in an isolated project, it will become an Undeclared global. It is best not to remove an inst var when it is being used in another isolated project. [If we recompile them all, why can't we diagnose the problem before allowing the change??] Senders and Implementors do not see versions of a method in isolated projects. [again, we might want to make this possible at a cost]. When you ask for versions of a method, you will not get the history in other isolated projects. Moving methods and classes between changeSets, and merging changeSets has no effect on which methods are in force. But, when you look at a changeSet from a different isolated project, the methods will contain code that is not in force. A changeSet is just a list of method names, and does not keep separate copies of any code. When finer grained assertion is needed, use the method (aProject assertClass: aClass from: thisProject warn: warnConflicts). How isolated changes work: The first time a class changes, store its MethodDictionary object. Keep parallel arrays of associations to Classes and MethodDictionaries. Traverse these and install them when you enter an "ioslated project". When you leave, store this project's own MethodDictionaries there. To do an assert, we must discover which methods changed here, and which changed only in the project we are asserting into. There is one copy of the 'virgin' method dictionaries in the system. It is always being temporarily stored by the currently inForce isolated project. isolatedHead - true for the top project, and for each isolated project. false or nil for any subproject that shares all methods with its parent project. inForce - true if my methods are installed now. false if I am dormant. [is this equivalent to self == Project Current?] classArray - list of associations to classes methodDictArray - the method dictionaries of those classes before we started changing methods. They hang onto the original compiledMethods. (If this project is dormant, it contains the method dictionaries of those classes as they will be here, in this project). orgArray - the class organizations of the classes in classArray. UsingIsolation (class variable) - No longer used. When you want to save a project in export format from within that very project, it gets tricky. We set two flags in parentProject, exit to it, and let parentProject write the project. ProjectViewMorph in parentProject checks in its step method, does the store, clears the flags, and reenters the subProject. ! !Project methodsFor: 'initialization' stamp: 'sw 11/5/1998 21:28'! backgroundColorForMvcProject ^ Color r: 1.0 g: 1.0 b: 0.065! ! !Project methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:08'! defaultBackgroundColor ^ self isMorphic ifTrue: [] ifFalse: [self backgroundColorForMvcProject]! ! !Project methodsFor: 'initialization'! initialExtent ^ (Display extent // 6) + (0@17)! ! !Project methodsFor: 'initialization' stamp: 'di 4/14/1999 13:55'! initialProject self saveState. parentProject _ self. previousProject _ nextProject _ nil! ! !Project methodsFor: 'initialization' stamp: 'di 4/6/2001 10:30'! initialize "Initialize the project, seting the CurrentProject as my parentProject and initializing my project preferences from those of the CurrentProject" changeSet _ ChangeSet new. transcript _ TranscriptStream new. displayDepth _ Display depth. parentProject _ CurrentProject. isolatedHead _ false. self initializeProjectPreferences ! ! !Project methodsFor: 'initialization' stamp: 'ar 5/16/2001 17:08'! installNewDisplay: extent depth: depth "When entering a new project, install a new Display if necessary." ^Display setExtent: extent depth: depth! ! !Project methodsFor: 'initialization' stamp: 'RAA 6/21/2000 22:59'! setChangeSet: aChangeSet isolatedHead == true ifTrue: [^ self]. "ChangeSet of an isolated project cannot be changed" changeSet _ aChangeSet ! ! !Project methodsFor: 'initialization' stamp: 'di 3/29/2000 14:16'! setProjectHolder: aProject self initialize. world _ ControlManager new. ! ! !Project methodsFor: 'initialization' stamp: 'di 6/10/1998 13:54'! windowActiveOnFirstClick ^ true! ! !Project methodsFor: 'initialization' stamp: 'di 6/12/1998 15:58'! windowReqNewLabel: newLabel newLabel isEmpty ifTrue: [^ false]. newLabel = changeSet name ifTrue: [^ true]. (ChangeSorter changeSetNamed: newLabel) == nil ifFalse: [self inform: 'Sorry that name is already used'. ^ false]. changeSet name: newLabel. ^ true! ! !Project methodsFor: 'accessing' stamp: 'tk 4/5/2000 16:29'! changeSet ^ changeSet! ! !Project methodsFor: 'accessing' stamp: 'jla 5/28/2001 21:50'! children "Answer a list of all the subprojects of the receiver" | children | children _ OrderedCollection new. Project allProjects do: [ :p | (self == p parent and: [self ~~ p]) ifTrue: [ children add: p ]]. ^ children " Project topProject children "! ! !Project methodsFor: 'accessing'! displayDepth: newDepth displayDepth _ newDepth! ! !Project methodsFor: 'accessing' stamp: 'tk 2/24/2000 13:51'! environment ^ environment! ! !Project methodsFor: 'accessing' stamp: 'RAA 6/3/2000 10:23'! isCurrentProject ^self == CurrentProject! ! !Project methodsFor: 'accessing' stamp: 'tk 9/22/1999 18:32'! isMorphic "Complexity is because #isMVC is lazily installed" ^ world isInMemory ifTrue: [world isMorph] ifFalse: [(self projectParameters at: #isMVC ifAbsent: [false]) not]! ! !Project methodsFor: 'accessing' stamp: 'di 3/29/2000 15:37'! isTopProject "Return true only if this is the top project (its own parent). Also include the test here for malformed project hierarchy." parentProject == self ifTrue: [^ true]. parentProject == nil ifTrue: [self error: 'No project should have a nil parent']. ^ false! ! !Project methodsFor: 'accessing' stamp: 'tk 6/26/1998 22:17'! labelString ^ changeSet name! ! !Project methodsFor: 'accessing' stamp: 'di 7/19/1999 15:06'! name changeSet == nil ifTrue: [^ 'no name']. ^ changeSet name! ! !Project methodsFor: 'accessing' stamp: 'jla 5/28/2001 20:01'! nameAdjustedForDepth "Answer the name of the project, prepended with spaces reflecting the receiver's depth from the top project" " Project current nameAdjustedForDepth " | stream | stream _ WriteStream on: String new. self depth timesRepeat: [2 timesRepeat: [stream nextPut: $ ]]. stream nextPutAll: self name. ^ stream contents! ! !Project methodsFor: 'accessing' stamp: 'sw 2/15/1999 12:12'! nextProject ^ nextProject ! ! !Project methodsFor: 'accessing' stamp: 'di 3/6/98 10:22'! parent ^ parentProject! ! !Project methodsFor: 'accessing' stamp: 'jm 5/20/1998 23:31'! previousProject ^ previousProject ! ! !Project methodsFor: 'accessing'! projectChangeSet ^ changeSet! ! !Project methodsFor: 'accessing' stamp: 'ssa 9/3/2008 11:21'! renameTo: newName | | newName = self name ifFalse: [ version _ nil. self changeSet name: newName. ].! ! !Project methodsFor: 'accessing' stamp: 'di 4/14/1999 13:59'! setParent: newParent parentProject _ newParent. nextProject _ previousProject _ nil.! ! !Project methodsFor: 'accessing' stamp: 'di 1/21/98 11:06'! setViewSize: aPoint viewSize _ aPoint! ! !Project methodsFor: 'accessing' stamp: 'di 1/21/98 11:07'! thumbnail ^ thumbnail! ! !Project methodsFor: 'accessing' stamp: 'jla 5/28/2001 21:51'! withChildrenDo: aBlock "Evaluate the block first with the receiver as argument, then, recursively and depth first, with each of the receiver's children as argument" aBlock value: self. self children do: [:p | p withChildrenDo: [:c | aBlock value: c]]! ! !Project methodsFor: 'accessing'! world ^ world! ! !Project methodsFor: 'menu messages' stamp: 'BG 10/28/2003 21:03'! assureNavigatorPresenceMatchesPreference "Make sure that the current project conforms to the presence/absence of the navigator" Smalltalk isMorphic ifFalse: [^ self].! ! !Project methodsFor: 'menu messages' stamp: 'tk 10/26/1999 14:25'! enter "Enter the new project" self enter: (CurrentProject parent == self) revert: false saveForRevert: false.! ! !Project methodsFor: 'menu messages' stamp: 'ssa 9/3/2008 11:09'! enter: returningFlag revert: revertFlag saveForRevert: saveForRevert "Install my ChangeSet, Transcript, and scheduled views as current globals. If returningFlag is true, we will return to the project from whence the current project was entered; don't change its previousProject link in this case. If saveForRevert is true, save the ImageSegment of the project being left. If revertFlag is true, make stubs for the world of the project being left. If revertWithoutAsking is true in the project being left, then always revert." | showZoom old forceRevert response seg newProcess | self isCurrentProject ifTrue: [^ self]. "Check the guards" guards ifNotNil: [guards := guards reject: [:obj | obj isNil]. guards do: [:obj | obj okayToEnterProject ifFalse: [^ self]]]. CurrentProject world triggerEvent: #aboutToLeaveWorld. forceRevert := false. CurrentProject rawParameters ifNil: [revertFlag ifTrue: [^ self inform: 'nothing to revert to']] ifNotNil: [saveForRevert ifFalse: [forceRevert := CurrentProject projectParameters at: #revertWithoutAsking ifAbsent: [false]]]. forceRevert not & revertFlag ifTrue: [response := SelectionMenu confirm: 'Are you sure you want to destroy this Project\ and revert to an older version?\\(From the parent project, click on this project''s thumbnail.)' withCRs trueChoice: 'Revert to saved version' falseChoice: 'Cancel'. response ifFalse: [^ self]]. revertFlag | forceRevert ifTrue: [seg := CurrentProject projectParameters at: #revertToMe ifAbsent: [^ self inform: 'nothing to revert to']] ifFalse: [CurrentProject finalExitActions. CurrentProject makeThumbnail. returningFlag == #specialReturn ifTrue: [ProjectHistory forget: CurrentProject. "this guy is irrelevant" Project forget: CurrentProject] ifFalse: [ProjectHistory remember: CurrentProject]]. revertFlag | saveForRevert | forceRevert ifFalse: [(Preferences valueOfFlag: #projectsSentToDisk) ifTrue: [self storeToMakeRoom]]. CurrentProject abortResourceLoading. CurrentProject saveProjectPreferences. "Update the display depth and make a thumbnail of the current project" CurrentProject displayDepth: Display depth. old := CurrentProject. "for later" "Show the project transition. Note: The project zoom is run in the context of the old project, so that eventual errors can be handled accordingly" displayDepth == nil ifTrue: [displayDepth := Display depth]. self installNewDisplay: Display extent depth: displayDepth. (showZoom := self showZoom) ifTrue: [self displayZoom: CurrentProject parent ~~ self]. (world isMorph and: [world hasProperty: #letTheMusicPlay]) ifTrue: [world removeProperty: #letTheMusicPlay] ifFalse: [Smalltalk at: #ScorePlayer ifPresentAndInMemory: [:playerClass | playerClass allSubInstancesDo: [:player | player pause]]]. returningFlag == #specialReturn ifTrue: [old removeChangeSetIfPossible. "keep this stuff from accumulating" nextProject := nil] ifFalse: [returningFlag ifTrue: [nextProject := CurrentProject] ifFalse: [previousProject := CurrentProject]]. CurrentProject saveState. CurrentProject isolationHead == self isolationHead ifFalse: [self invokeFrom: CurrentProject]. CurrentProject := self. self installProjectPreferences. ChangeSet newChanges: changeSet. TranscriptStream newTranscript: transcript. Sensor flushKeyboard. ProjectHistory remember: CurrentProject. world isMorph ifTrue: [] ifFalse: [World := nil. "Signifies MVC" Smalltalk at: #ScheduledControllers put: world]. saveForRevert ifTrue: [Smalltalk garbageCollect. "let go of pointers" old storeSegment. "result _" old world isInMemory ifTrue: ['Can''t seem to write the project.'] ifFalse: [old projectParameters at: #revertToMe put: old world xxxSegment clone]. 'Project written.']. "original is for coming back in and continuing." revertFlag | forceRevert ifTrue: [seg clone revert]. "non-cloned one is for reverting again later" self removeParameter: #exportState. "Complete the enter: by launching a new process" world isMorph ifFalse: [newProcess := [ScheduledControllers resetActiveController. "in case of walkback in #restore" showZoom ifFalse: [ScheduledControllers restore]. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process and its referenced morphs" Processor terminateActive]! ! !Project methodsFor: 'menu messages' stamp: 'BG 10/30/2003 21:26'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject _ self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World _ world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World _ nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess _ Processor activeProcess. ! ! !Project methodsFor: 'menu messages'! fileOut changeSet fileOut! ! !Project methodsFor: 'menu messages' stamp: 'BG 10/29/2003 01:09'! finalExitActions world isMorph ifTrue: [ ]. ! ! !Project methodsFor: 'menu messages' stamp: 'sw 4/19/2001 12:58'! installProjectPreferences "Install the settings of all preferences presently held individually by projects in the receiver's projectPreferenceFlagDictionary" | localValue | Preferences allPreferenceObjects do: [:aPreference | aPreference localToProject ifTrue: [localValue _ self projectPreferenceFlagDictionary at: aPreference name ifAbsent: [nil]. localValue ifNotNil: [aPreference rawValue: localValue]]]! ! !Project methodsFor: 'menu messages' stamp: 'BG 10/28/2003 20:07'! makeThumbnail "Make a thumbnail image of this project from the Display." world isMorph ifTrue: [world displayWorldSafely]. "clean pending damage" viewSize ifNil: [viewSize _ Display extent // 8]. thumbnail _ Form extent: viewSize depth: Display depth. (WarpBlt current toForm: thumbnail) sourceForm: Display; cellSize: 2; "installs a colormap" combinationRule: Form over; copyQuad: (Display boundingBox) innerCorners toRect: (0@0 extent: viewSize). ^thumbnail ! ! !Project methodsFor: 'menu messages' stamp: 'sw 4/12/2001 22:29'! saveProjectPreferences "Preserve the settings of all preferences presently held individually by projects in the receiver's projectPreferenceFlagDictionary" Preferences allPreferenceObjects do: [:aPreference | aPreference localToProject ifTrue: [projectPreferenceFlagDictionary at: aPreference name put: aPreference preferenceValue]]! ! !Project methodsFor: 'menu messages' stamp: 'BG 11/26/2003 23:15'! saveState "Save the current state in me prior to leaving this project" changeSet := ChangeSet current. thumbnail ifNotNil: [thumbnail hibernate]. Smalltalk isMorphic ifFalse: [world := ScheduledControllers. ScheduledControllers unCacheWindows]. Sensor flushAllButDandDEvents. "Will be reinstalled by World>>install" transcript := Transcript! ! !Project methodsFor: 'menu messages' stamp: 'BG 10/29/2003 09:53'! viewLocFor: exitedProject "Look for a view of the exitedProject, and return its center" | ctlr | world isMorph ifTrue: [] ifFalse: [ctlr _ world controllerWhoseModelSatisfies: [:p | p == exitedProject]. ctlr ifNotNil: [^ ctlr view windowBox center]]. ^ Sensor cursorPoint. "default result" ! ! !Project methodsFor: 'release' stamp: 'di 9/28/1999 23:46'! addDependent: aMorph "Projects do not keep track of their dependents, lest they point into other projects and thus foul up the tree structure for image segmentation." ^ self "Ignore this request"! ! !Project methodsFor: 'release' stamp: 'sw 7/6/1998 11:16'! canDiscardEdits "Don't regard a window of mine as one to be discarded as part of a 'closeUnchangedWindows' sweep" ^ false! ! !Project methodsFor: 'release' stamp: 'RAA 5/10/2001 12:58'! deletingProject: aProject "Clear my previousProject link if it points at the given Project, which is being deleted." self flag: #bob. "zapping projects" parentProject == aProject ifTrue: [ parentProject _ parentProject parent ]. previousProject == aProject ifTrue: [previousProject _ nil]. nextProject == aProject ifTrue: [nextProject _ nil] ! ! !Project methodsFor: 'release' stamp: 'ssa 9/3/2008 11:09'! okToChange "Answer whether the window in which the project is housed can be dismissed -- which is destructive. We never clobber a project without confirmation" | ok | self subProjects size >0 ifTrue: [self inform: 'The project ', self name printString, ' contains sub-projects. You must remove these explicitly before removing their parent.'. ^ false]. ok _ world isMorph not and: [world scheduledControllers size <= 1]. ok ifFalse: [self isMorphic ifTrue: []]. "view from elsewhere. just delete it." ok _ (self confirm: 'Really delete the project ', self name printString, ' and all its windows?'). ok ifFalse: [^ false]. self removeChangeSetIfPossible. "do this last since it will render project inaccessible to #allProjects and their ilk" ProjectHistory forget: self. Project deletingProject: self. ^ true ! ! !Project methodsFor: 'release' stamp: 'RAA 6/7/2000 09:24'! release self flag: #bob. "this can be trouble if Projects are reused before garbage collection" world == nil ifFalse: [world release. world _ nil]. ^ super release! ! !Project methodsFor: 'release' stamp: 'RAA 5/10/2001 13:06'! removeChangeSetIfPossible | itsName | changeSet ifNil: [^self]. changeSet isEmpty ifFalse: [^self]. (changeSet projectsBelongedTo copyWithout: self) isEmpty ifFalse: [^self]. itsName _ changeSet name. ChangeSorter removeChangeSet: changeSet. "Transcript cr; show: 'project change set ', itsName, ' deleted.'" ! ! !Project methodsFor: 'release' stamp: 'BG 10/28/2003 21:04'! subProjects "Answer a list of all the subprojects of the receiver. This is nastily idiosyncratic." ^ self isMorphic ifFalse: [(world controllersSatisfying: [:m | m model isKindOf: Project]) collect: [:c | c model]] ! ! !Project methodsFor: 'printing' stamp: 'jm 5/21/1998 07:40'! printOn: aStream aStream nextPutAll: 'a Project(', self name, ')'. ! ! !Project methodsFor: 'file in/out' stamp: 'BG 10/29/2003 00:50'! beep ! ! !Project methodsFor: 'file in/out' stamp: 'BG 10/29/2003 08:18'! currentVersionNumber version ifNil: [^0]. version isInteger ifTrue:[^version]. "version _ Base64MimeConverter decodeInteger: version unescapePercents." ^version! ! !Project methodsFor: 'file in/out' stamp: 'ar 2/27/2001 13:44'! projectExtension ^self class projectExtension! ! !Project methodsFor: 'file in/out' stamp: 'tk 10/26/1999 14:23'! revert | | "Exit this project and do not save it. Warn user unless in dangerous projectRevertNoAsk mode. Exit to the parent project. Do a revert on a clone of the segment, to allow later reverts." projectParameters ifNil: [^ self inform: 'nothing to revert to']. parentProject enter: false revert: true saveForRevert: false. "does not return!!" ! ! !Project methodsFor: 'file in/out' stamp: 'BG 10/29/2003 09:10'! saveAs "Forget where stored before, and store. Will ask user where." "self forgetExistingURL. self storeOnServer. "! ! !Project methodsFor: 'file in/out' stamp: 'BG 10/29/2003 09:16'! storeSegment "Store my project out on the disk as an ImageSegment. Keep the outPointers in memory. Name it <project name>.seg. *** Caller must be holding (Project alInstances) to keep subprojects from going out. ***" (World == world) ifTrue: [^ false]. "self inform: 'Can''t send the current world out'." world isInMemory ifFalse: [^ false]. "already done" world isMorph ifFalse: [ self projectParameters at: #isMVC put: true. ^ false]. "Only Morphic projects for now" world ifNil: [^ false]. world presenter ifNil: [^ false]. ! ! !Project methodsFor: 'file in/out' stamp: 'md 10/22/2003 17:54'! storeToMakeRoom "Write out enough projects to fulfill the space goals. Include the size of the project about to come in." | params memoryEnd goalFree cnt gain proj skip tried | GoalFreePercent ifNil: [GoalFreePercent _ 33]. GoalNotMoreThan ifNil: [GoalNotMoreThan _ 20000000]. params _ SmalltalkImage current getVMParameters. memoryEnd _ params at: 3. " youngSpaceEnd _ params at: 2. free _ memoryEnd - youngSpaceEnd. " goalFree _ GoalFreePercent asFloat / 100.0 * memoryEnd. goalFree _ goalFree min: GoalNotMoreThan. world isInMemory ifFalse: ["enough room to bring it in" goalFree _ goalFree + (self projectParameters at: #segmentSize ifAbsent: [0])]. cnt _ 30. gain _ Smalltalk garbageCollectMost. "skip a random number of projects that are in memory" proj _ self. skip _ 6 atRandom. [proj _ proj nextInstance ifNil: [Project someInstance]. proj world isInMemory ifTrue: [skip _ skip - 1]. skip > 0] whileTrue. cnt _ 0. tried _ 0. [gain > goalFree] whileFalse: [ proj _ proj nextInstance ifNil: [Project someInstance]. proj storeSegment ifTrue: ["Yes, did send its morphs to the disk" gain _ gain + (proj projectParameters at: #segmentSize ifAbsent: [20000]). "a guess" Beeper beep. (cnt _ cnt + 1) > 5 ifTrue: [^ self]]. "put out 5 at most" (tried _ tried + 1) > 23 ifTrue: [^ self]]. "don't get stuck in a loop"! ! !Project methodsFor: 'file in/out' stamp: 'mir 6/25/2001 10:55'! url | firstURL | "compose my url on the server" urlList isEmptyOrNil ifTrue: [^'']. firstURL _ urlList first. firstURL isEmpty ifFalse: [ firstURL last == $/ ifFalse: [firstURL _ firstURL, '/']]. ^ firstURL, self versionedFileName ! ! !Project methodsFor: 'file in/out' stamp: 'mir 6/21/2001 15:45'! versionForFileName "Project current versionForFileName" ^self class versionForFileName: self currentVersionNumber! ! !Project methodsFor: 'file in/out' stamp: 'mir 6/21/2001 15:43'! versionedFileName "Project current versionedFileName" ^String streamContents:[:s| s nextPutAll: self name. s nextPutAll: FileDirectory dot. s nextPutAll: self versionForFileName. s nextPutAll: FileDirectory dot. s nextPutAll: self projectExtension. ] ! ! !Project methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:49'! convertToCurrentVersion: varDict refStream: smartRefStrm isolatedHead ifNil: [isolatedHead _ false]. inForce ifNil: [inForce _ false]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! !Project methodsFor: 'project parameters' stamp: 'sw 4/24/2001 11:58'! initializeProjectParameters "Initialize the project parameters." projectParameters _ IdentityDictionary new. ^ projectParameters! ! !Project methodsFor: 'project parameters' stamp: 'di 11/16/2001 21:08'! initializeProjectPreferences "Initialize the project's preferences from currently-prevailing preferences that are currently being held in projects in this system" projectPreferenceFlagDictionary _ Project current projectPreferenceFlagDictionary deepCopy. "Project overrides in the new project start out being the same set of overrides in the calling project" Preferences allPreferenceObjects do: "in case we missed some" [:aPreference | aPreference localToProject ifTrue: [(projectPreferenceFlagDictionary includesKey: aPreference name) ifFalse: [projectPreferenceFlagDictionary at: aPreference name put: aPreference preferenceValue]]]. self isMorphic ifFalse: [self flapsSuppressed: true]. (Project current projectParameterAt: #disabledGlobalFlapIDs ifAbsent: [nil]) ifNotNilDo: [:idList | self projectParameterAt: #disabledGlobalFlapIDs put: idList copy] ! ! !Project methodsFor: 'project parameters' stamp: 'sw 2/16/2001 22:35'! noteThatParameter: prefSymbol justChangedTo: aBoolean "Provides a hook so that a user's toggling of a project parameter might precipitate some immediate action" ! ! !Project methodsFor: 'project parameters' stamp: 'ar 5/25/2000 23:23'! parameterAt: aSymbol ifAbsent: aBlock projectParameters ifNil:[^aBlock value]. ^projectParameters at: aSymbol ifAbsent: aBlock! ! !Project methodsFor: 'project parameters' stamp: 'sw 2/15/2001 14:32'! projectParameterAt: aSymbol ifAbsent: aBlock "Answer the project parameter stored at the given symbol, or the result of evaluating the block" ^ self projectParameters at: aSymbol ifAbsent: [aBlock value]! ! !Project methodsFor: 'project parameters' stamp: 'sw 2/17/2001 21:36'! projectParameterAt: aSymbol put: aValue "Set the given project parameter to the given value" self projectParameters at: aSymbol put: aValue. self noteThatParameter: aSymbol justChangedTo: aValue. ^ aValue! ! !Project methodsFor: 'project parameters' stamp: 'sw 4/22/1999 15:14'! projectParameters ^ projectParameters ifNil: [self initializeProjectParameters]! ! !Project methodsFor: 'project parameters' stamp: 'sw 2/16/2001 22:25'! projectPreferenceAt: aSymbol ifAbsent: aBlock "Answer the project preference stored at the given symbol, or the result of evaluating the block" ^ self projectPreferenceFlagDictionary at: aSymbol ifAbsent: [aBlock value]! ! !Project methodsFor: 'project parameters' stamp: 'sw 2/16/2001 22:23'! projectPreferenceFlagDictionary "Answer the dictionary that holds the project preferences, creating it if necessary" ^ projectPreferenceFlagDictionary ifNil: [projectPreferenceFlagDictionary _ IdentityDictionary new]! ! !Project methodsFor: 'project parameters' stamp: 'tk 10/26/1999 13:55'! rawParameters ^ projectParameters! ! !Project methodsFor: 'project parameters' stamp: 'ar 6/2/1999 05:29'! removeParameter: aKey projectParameters ifNil:[^self]. projectParameters removeKey: aKey ifAbsent:[].! ! !Project methodsFor: 'flaps support' stamp: 'BG 10/29/2003 08:42'! flapsSuppressed: aBoolean "Make the setting of the flag that governs whether global flaps are suppressed in the project be as indicated and add or remove the actual flaps" self projectPreferenceFlagDictionary at: #showSharedFlaps put: aBoolean not. self == Project current "Typical case" ifTrue: [Preferences setPreference: #showSharedFlaps toValue: aBoolean not] ifFalse: "Anomalous case where this project is not the current one." [aBoolean ifTrue: [] ifFalse: [Smalltalk isMorphic ifTrue: []]]. Project current assureNavigatorPresenceMatchesPreference! ! !Project methodsFor: 'flaps support' stamp: 'sw 4/24/2001 11:02'! showSharedFlaps "Answer whether shared flaps are shown or suppressed in this project" | result | result _ Preferences showSharedFlaps. ^ self == Project current ifTrue: [result] ifFalse: [self projectPreferenceAt: #showSharedFlaps ifAbsent: [result]]! ! !Project methodsFor: 'displaying' stamp: 'ar 5/28/2000 19:43'! displayZoom: entering "Show the project transition when entering a new project" | newDisplay vanishingPoint | "Play the flash transition if any." self projectParameters at: #flashTransition ifPresent:[:dict| dict at: CurrentProject ifPresent:[:player| ^player playProjectTransitionFrom: CurrentProject to: self entering: entering]]. "Show animated zoom to new display" newDisplay _ self imageForm. entering ifTrue: [vanishingPoint _ Sensor cursorPoint] ifFalse: [vanishingPoint _ self viewLocFor: CurrentProject]. Display zoomIn: entering orOutTo: newDisplay at: 0@0 vanishingPoint: vanishingPoint.! ! !Project methodsFor: 'displaying' stamp: 'ar 6/2/1999 01:58'! imageForm ^self imageFormOfSize: Display extent depth: (displayDepth ifNil:[Display depth])! ! !Project methodsFor: 'displaying' stamp: 'BG 10/29/2003 08:31'! imageFormOfSize: extentPoint depth: d | newDisplay | newDisplay _ DisplayScreen extent: extentPoint depth: d. Display replacedBy: newDisplay do:[ world restore. "MVC" ]. ^newDisplay! ! !Project methodsFor: 'displaying' stamp: 'sw 1/12/2000 18:44'! showZoom "Decide if user wants a zoom transition, and if there is enough memory to do it." ^ Preferences projectZoom and: "Only show zoom if there is room for both displays plus a megabyte" [Smalltalk garbageCollectMost > (Display boundingBox area*displayDepth //8+1000000)]! ! !Project methodsFor: 'isolation layers' stamp: 'di 4/1/2000 09:22'! compileAll: newClass from: oldClass "Make sure that shadowed methods in isolation layers get recompiled. Traversal is done elsewhere. This simply handles the current project." isolatedHead == true ifFalse: [^ self]. "only isolated projects need to act on this." changeSet compileAll: newClass from: oldClass! ! !Project methodsFor: 'isolation layers' stamp: 'RAA 9/27/2000 18:53'! compileAllIsolated: newClass from: oldClass "Whenever a recompile is needed in a class, look in other isolated projects for saved methods and recompile them also. At the time this method is called, the recompilation has already been done for the project now in force." Project allProjects do: [:proj | proj compileAll: newClass from: oldClass]. ! ! !Project methodsFor: 'isolation layers' stamp: 'di 3/29/2000 16:04'! invoke "Install all methods changed here into method dictionaries. Make my versions be the ones that will be called." isolatedHead ifFalse: [^ self error: 'This isnt an isolation layer.']. inForce ifTrue: [^ self error: 'This layer is already in force.']. changeSet invoke. inForce _ true.! ! !Project methodsFor: 'isolation layers' stamp: 'di 3/29/2000 15:49'! invokeFrom: otherProject "Revoke the changes in force for this project, and then invoke those in force for otherProject. This method shortens the process to the shortest path up then down through the isolation layers." | pathUp pathDown | pathUp _ otherProject layersToTop. "Full paths to top" pathDown _ self layersToTop. "Shorten paths to nearest common ancestor" [pathUp isEmpty not and: [pathDown isEmpty not and: [pathUp last == pathDown last]]] whileTrue: [pathUp removeLast. pathDown removeLast]. "Now revoke changes up from otherProject and invoke down to self." pathUp do: [:p | p revoke]. pathDown reverseDo: [:p | p invoke]. ! ! !Project methodsFor: 'isolation layers' stamp: 'di 4/4/2000 21:10'! isolationHead "Go up the parent chain and find the nearest isolated project." isolatedHead == true ifTrue: [^ self]. self isTopProject ifTrue: [^ nil]. ^ parentProject isolationHead! ! !Project methodsFor: 'isolation layers' stamp: 'di 3/29/2000 17:00'! isolationSet "Return the changeSet for this isolation layer or nil" isolatedHead == true ifTrue: [^ changeSet]. self isTopProject ifTrue: [^ nil]. "At the top, but not isolated" ^ parentProject isolationSet ! ! !Project methodsFor: 'isolation layers' stamp: 'di 3/29/2000 15:40'! layersToTop "Return an OrderedCollection of all the projects that are isolation layers from this one up to the top of the project hierarchy, inclusive." | layers | self isTopProject ifTrue: [layers _ OrderedCollection new] ifFalse: [layers _ parentProject layersToTop]. isolatedHead ifTrue: [layers addFirst: self]. ^ layers ! ! !Project methodsFor: 'isolation layers' stamp: 'di 3/29/2000 16:06'! revoke "Take back all methods changed here. Install the original method dictionaries and organizations. The orignal method versions will now be the ones used." isolatedHead ifFalse: [^ self error: 'This isnt an isolation layer.']. inForce ifFalse: [^ self error: 'This layer should have been in force.']. changeSet revoke. inForce _ false. ! ! !Project methodsFor: 'OBSOLETE' stamp: 'RAA 6/3/2000 19:01'! obsolete self flag: #obsolete. "instance variable exitFlag is no longer used activeProcess is on the way out "! ! !Project methodsFor: 'resources' stamp: 'ar 3/2/2001 17:25'! abortResourceLoading "Abort loading resources" resourceManager ifNil:[^self]. resourceManager stopDownload.! ! !Project methodsFor: 'active process' stamp: 'jla 4/2/2001 15:12'! depth "Return the depth of this project from the top. topProject = 0, next = 1, etc." "Project current depth." | depth topProject project | depth _ 0. topProject _ Project topProject. project _ self. [project ~= topProject] whileTrue: [project _ project parent. depth _ depth + 1]. ^ depth! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Project class instanceVariableNames: ''! !Project class methodsFor: 'class initialization' stamp: 'RAA 6/3/2000 18:50'! initialize "This is the Top Project." CurrentProject ifNil: [CurrentProject _ super new initialProject. Project spawnNewProcessAndTerminateOld: true]. "Project initialize"! ! !Project class methodsFor: 'class initialization' stamp: 'RAA 12/17/2000 12:37'! rebuildAllProjects "Project rebuildAllProjects" AllProjects _ nil. self allProjects.! ! !Project class methodsFor: 'instance creation' stamp: 'RAA 11/16/2000 12:07'! new | new | new _ super new. new setProjectHolder: CurrentProject. self addingProject: new. ^new! ! !Project class methodsFor: 'instance creation' stamp: 'RAA 9/27/2000 13:41'! uiProcess ^ UIProcess! ! !Project class methodsFor: 'utilities' stamp: 'ssa 9/3/2008 11:11'! addItem: item toMenu: menu selection: action project: aProject menu add: item action: action! ! !Project class methodsFor: 'utilities' stamp: 'RAA 11/16/2000 12:04'! addingProject: newProject (self allProjects includes: newProject) ifTrue: [^self]. AllProjects _ self allProjects copyWith: newProject.! ! !Project class methodsFor: 'utilities' stamp: 'di 6/10/1999 11:30'! allNamesAndProjects ^ (self allProjects asSortedCollection: [:p1 :p2 | p1 name asLowercase < p2 name asLowercase]) collect: [:aProject | Array with: aProject name with: aProject]! ! !Project class methodsFor: 'utilities' stamp: 'RAA 11/13/2000 17:14'! allProjects ^AllProjects ifNil: [ Smalltalk garbageCollect. AllProjects _ self allSubInstances select: [:p | p name notNil]. ].! ! !Project class methodsFor: 'utilities' stamp: 'jla 5/28/2001 21:48'! allProjectsOrdered "Answer a list of all projects in hierarchical order, depth first" | allProjects | allProjects _ OrderedCollection new. Project topProject withChildrenDo: [:p | allProjects add: p]. ^ allProjects " Project allProjectsOrdered "! ! !Project class methodsFor: 'utilities' stamp: 'sw 11/24/2002 10:57'! buildJumpToMenu: menu "Make the supplied menu offer a list of potential projects, consisting of: * The previous-project chain * The next project, if any * The parent project, if any * All projects, alphabetically or hierarchically" | prev listed i next toAdd | listed _ OrderedCollection with: CurrentProject. i _ 0. "The previous Project chain" prev _ CurrentProject previousProject. [(prev ~~ nil and: [(listed includes: prev) not])] whileTrue: [i _ i + 1. listed add: prev. self addItem: prev name , ' (back ' , i printString , ')' toMenu: menu selection: ('%back' , i printString) project: prev. prev _ prev previousProject]. i > 0 ifTrue: [menu addLine]. "Then the next Project" (((next _ CurrentProject nextProject) ~~ nil) and: [(listed includes: next) not]) ifTrue: [self addItem: (next name, ' (forward 1)') toMenu: menu selection: next name project: next]. next ~~ nil ifTrue: [menu addLine]. "Then the parent" CurrentProject isTopProject ifFalse: [self addItem: CurrentProject parent name , ' (parent)' toMenu: menu selection: #parent project: CurrentProject parent. menu addLine]. "Finally all the projects, in hierarchical or alphabetical order:" (Preferences alphabeticalProjectMenu ifTrue: [Project allNamesAndProjects] ifFalse: [Project hierarchyOfNamesAndProjects]) do: [:aPair | toAdd _ aPair last isCurrentProject ifTrue: [aPair first, ' (current)'] ifFalse: [aPair first]. self addItem: toAdd toMenu: menu selection: aPair first project: aPair last]. ^ menu! ! !Project class methodsFor: 'utilities' stamp: 'BG 10/29/2003 09:18'! deletingProject: outgoingProject Project allProjects do: [:p | p deletingProject: outgoingProject]. "ones that are in" AllProjects _ self allProjects copyWithout: outgoingProject.! ! !Project class methodsFor: 'utilities' stamp: 'RAA 12/26/2000 12:42'! forget: aProject AllProjects _ self allProjects reject: [ :x | x == aProject]. ! ! !Project class methodsFor: 'utilities' stamp: 'jla 5/28/2001 21:43'! hierarchyOfNamesAndProjects "Answer a list of all project names, with each entry preceded by white space commensurate with its depth beneath the top project" ^ self allProjectsOrdered collect: [:project | Array with: project nameAdjustedForDepth with: project]! ! !Project class methodsFor: 'utilities' stamp: 'BG 10/28/2003 21:04'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label." Smalltalk isMorphic ifFalse: [^ ScheduledControllers interruptName: labelString].! ! !Project class methodsFor: 'utilities' stamp: 'jla 4/2/2001 20:34'! jumpToProject "Project jumpToProject" "Present a list of potential projects and enter the one selected." self jumpToSelection: (self buildJumpToMenu: CustomMenu new) startUpLeftFlush! ! !Project class methodsFor: 'utilities' stamp: 'jla 4/2/2001 15:57'! jumpToSelection: selection "Enter the project corresponding to this menu selection." "Project jumpToProject" | nBack prev pr | selection ifNil: [^ self]. (selection beginsWith: '%back') ifTrue: [nBack _ (selection copyFrom: 6 to: selection size) asNumber. prev _ CurrentProject previousProject. 1 to: nBack-1 do: [:i | prev ifNotNil: [prev _ prev previousProject]]. prev ifNotNil: [prev enter: true revert: false saveForRevert: false]]. selection = #parent ifTrue: [CurrentProject parent enter: false revert: false saveForRevert: false. ^ self]. (pr _ Project namedWithDepth: selection) ifNil: [^ self]. pr enter: false revert: false saveForRevert: false! ! !Project class methodsFor: 'utilities' stamp: 'tk 3/10/2000 21:10'! named: projName "Answer the project with the given name, or nil if there is no project of that given name." "(Project named: 'New Changes') enter" ^ self allProjects detect: [:proj | proj name = projName] ifNone: [nil] ! ! !Project class methodsFor: 'utilities' stamp: 'jla 4/2/2001 15:57'! namedWithDepth: projName "Answer the project with the given name, or nil if there is no project of that given name." "(Project named: 'New Changes') enter" ^ self allProjects detect: [:proj | proj name = projName or: [proj nameAdjustedForDepth = projName]] ifNone: [nil]! ! !Project class methodsFor: 'utilities' stamp: 'RAA 6/3/2000 18:28'! resumeProcess: aProcess "Adopt aProcess as the project process -- probably because of proceeding from a debugger" UIProcess _ aProcess. UIProcess resume! ! !Project class methodsFor: 'utilities' stamp: 'tk 10/26/1999 14:25'! returnToPreviousProject "Return to the project from which this project was entered. Do nothing if the current project has no link to its previous project." | prevProj | prevProj _ CurrentProject previousProject. prevProj ifNotNil: [prevProj enter: true revert: false saveForRevert: false]. ! ! !Project class methodsFor: 'utilities' stamp: 'RAA 6/3/2000 18:49'! spawnNewProcess UIProcess _ [ [World doOneCycle. Processor yield. false] whileFalse: []. ] newProcess priority: Processor userSchedulingPriority. UIProcess resume! ! !Project class methodsFor: 'utilities' stamp: 'RAA 6/3/2000 18:49'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor activeProcess suspend]! ! !Project class methodsFor: 'utilities' stamp: 'RAA 9/27/2000 19:00'! topProject "Answer the top project. There is only one" ^ self allProjects detect: [:p | p isTopProject]! ! !Project class methodsFor: 'utilities' stamp: 'mir 6/21/2001 15:44'! versionForFileName: version "Project versionForFileName: 7" | v | ^String streamContents:[:s| v _ version printString. v size < 3 ifTrue:[v _ '0', v]. v size < 3 ifTrue:[v _ '0', v]. s nextPutAll: v. ] ! ! !Project class methodsFor: 'constants'! current "Answer the project that is currently being used." ^CurrentProject! ! !Project class methodsFor: 'squeaklet on server' stamp: 'ar 2/27/2001 13:43'! projectExtension ^'pr'! ! StandardSystemController subclass: #ProjectController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !ProjectController methodsFor: 'control activity' stamp: 'tk 10/26/1999 14:26'! redButtonActivity | index | view isCollapsed ifTrue: [^ super redButtonActivity]. (view insetDisplayBox containsPoint: Sensor cursorPoint) ifFalse: [^ super redButtonActivity]. index _ (PopUpMenu labelArray: #('enter' 'jump to project...') lines: #()) startUpCenteredWithCaption: nil. index = 0 ifTrue: [^ self]. "save size on enter for thumbnail on exit" model setViewSize: view insetDisplayBox extent. index = 1 ifTrue: [^ model enter: false revert: false saveForRevert: false]. index = 2 ifTrue: [Project jumpToProject. ^ self]. ! ! Model subclass: #ProjectHistory instanceVariableNames: 'mostRecent' classVariableNames: 'ChangeCounter CurrentHistory' poolDictionaries: '' category: 'System-Support'! !ProjectHistory methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 15:57'! changed ChangeCounter _ (ChangeCounter ifNil: [0]) + 1. super changed.! ! !ProjectHistory methodsFor: 'as yet unclassified' stamp: 'RAA 9/27/2000 20:27'! forget: aProject | newTuple | newTuple _ { aProject name. aProject thumbnail. aProject url. WeakArray with: aProject. }. mostRecent _ mostRecent reject: [ :each | each fourth first == aProject or: [ each fourth first isNil & (each first = newTuple first) ]. ]. self changed. ^newTuple! ! !ProjectHistory methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 15:27'! initialize mostRecent _ OrderedCollection new. ! ! !ProjectHistory methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:17'! remember: aProject | newTuple | newTuple _ self forget: aProject. mostRecent addFirst: newTuple. mostRecent size > 10 ifTrue: [mostRecent _ mostRecent copyFrom: 1 to: 10]. self changed! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProjectHistory class instanceVariableNames: ''! !ProjectHistory class methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 15:27'! currentHistory ^CurrentHistory ifNil: [CurrentHistory _ self new initialize].! ! !ProjectHistory class methodsFor: 'as yet unclassified' stamp: 'RAA 7/12/2000 10:16'! forget: aProject self currentHistory forget: aProject ! ! !ProjectHistory class methodsFor: 'as yet unclassified' stamp: 'RAA 7/10/2000 15:31'! remember: aProject self currentHistory remember: aProject ! ! StandardSystemView subclass: #ProjectView instanceVariableNames: '' classVariableNames: 'ArmsLengthCmd' poolDictionaries: '' category: 'ST80-Support'! !ProjectView methodsFor: 'initialization'! defaultControllerClass ^ ProjectController! ! !ProjectView methodsFor: 'initialization' stamp: 'sw 8/4/1998 19:15'! maybeRelabel: newLabel "If the change set name given by newLabel is already in use, do nothing; else relabel the view" (newLabel isEmpty or: [newLabel = self label]) ifTrue: [^ self]. (ChangeSorter changeSetNamed: newLabel) == nil ifFalse: [^ self]. self relabel: newLabel! ! !ProjectView methodsFor: 'initialization' stamp: 'di 5/6/1998 17:03'! relabel: newLabel (newLabel isEmpty or: [newLabel = self label]) ifTrue: [^ self]. (ChangeSorter changeSetNamed: newLabel) == nil ifFalse: [self inform: 'Sorry that name is already used'. ^ self]. model projectChangeSet name: newLabel. super relabel: newLabel! ! !ProjectView methodsFor: 'initialization' stamp: 'sw 1/11/2000 15:30'! uncacheBits super uncacheBits. self label ~= model name ifTrue: [self setLabelTo: model name]! ! !ProjectView methodsFor: 'displaying' stamp: 'tk 4/19/2000 17:15'! armsLengthCommand: aCommand "Set up a save to be done after the subproject exits to here. displayOn: checks it." ArmsLengthCmd _ aCommand.! ! !ProjectView methodsFor: 'displaying'! cacheBitsAsTwoTone ^ false! ! !ProjectView methodsFor: 'displaying' stamp: 'tk 6/21/2000 16:22'! displayDeEmphasized | cmd | "Display this view with emphasis off. Check for a command that could not be executed in my subproject. Once it is done, remove the trigger." super displayDeEmphasized. ArmsLengthCmd ifNil: [^ self]. ArmsLengthCmd first == model ifFalse: [^ self]. "not ours" cmd _ ArmsLengthCmd second. ArmsLengthCmd _ nil. model "project" perform: cmd. model "project" enter. ! ! !ProjectView methodsFor: 'displaying' stamp: 'sw 1/11/2000 15:32'! displayView super displayView. self label = model name ifFalse: [self setLabelTo: model name]. self isCollapsed ifTrue: [^ self]. model thumbnail ifNil: [^ self]. self insetDisplayBox extent = model thumbnail extent ifTrue: [model thumbnail displayAt: self insetDisplayBox topLeft] ifFalse: [(model thumbnail magnify: model thumbnail boundingBox by: self insetDisplayBox extent asFloatPoint / model thumbnail extent) displayAt: self insetDisplayBox topLeft] ! ! !ProjectView methodsFor: 'displaying' stamp: 'sw 9/14/1998 13:01'! release super release. Smalltalk garbageCollect! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProjectView class instanceVariableNames: ''! !ProjectView class methodsFor: 'as yet unclassified'! open: aProject "Answer an instance of me for the argument, aProject. It is created on the display screen." | topView | topView _ self new model: aProject. topView minimumSize: 50 @ 30. topView borderWidth: 2. topView controller open! ! !ProjectView class methodsFor: 'as yet unclassified' stamp: 'RAA 7/25/2000 10:35'! openAndEnter: aProject "Answer an instance of me for the argument, aProject. It is created on the display screen." | topView | topView _ self new model: aProject. topView minimumSize: 50 @ 30. topView borderWidth: 2. topView window: (RealEstateAgent initialFrameFor: topView world: nil). ScheduledControllers schedulePassive: topView controller. aProject enter: false revert: false saveForRevert: false! ! ProtoObject subclass: #ProtoObject instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'. ProtoObject superclass: nil! !ProtoObject commentStamp: '<historical>' prior: 0! ProtoObject establishes minimal behavior required of any object in Squeak, even objects that should balk at normal object behavior. Generally these are proxy objects designed to read themselves in from the disk, or to perform some wrapper behavior, before responding to a message. Current examples are ObjectOut and ImageSegmentRootStub, and one could argue that ObjectTracer should also inherit from this class. ProtoObject has no instance variables, nor should any be added.! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:23'! ifNil: nilBlock "Return self, or evaluate the block if I'm == nil (q.v.)" ^ self! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:25'! ifNil: nilBlock ifNotNil: ifNotNilBlock "Evaluate the block, unless I'm == nil (q.v.)" ^ ifNotNilBlock value! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:25'! ifNotNil: ifNotNilBlock "Evaluate the block, unless I'm == nil (q.v.)" ^ ifNotNilBlock value! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:25'! ifNotNil: ifNotNilBlock ifNil: nilBlock "If I got here, I am not nil, so evaluate the block ifNotNilBlock" ^ ifNotNilBlock value! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:57'! isInMemory "All normal objects are." ^ true! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:26'! isNil "Coerces nil to true and everything else to false." ^false! ! !ProtoObject methodsFor: 'testing' stamp: 'md 11/24/1999 19:58'! pointsTo: anObject "This method returns true if self contains a pointer to anObject, and returns false otherwise" <primitive: 132> 1 to: self class instSize do: [:i | (self instVarAt: i) == anObject ifTrue: [^ true]]. 1 to: self basicSize do: [:i | (self basicAt: i) == anObject ifTrue: [^ true]]. ^ false! ! !ProtoObject methodsFor: 'comparing' stamp: 'md 11/24/1999 19:27'! == anObject "Primitive. Answer whether the receiver and the argument are the same object (have the same object pointer). Do not redefine the message == in any other class!! Essential. No Lookup. Do not override in any subclass. See Object documentation whatIsAPrimitive." <primitive: 110> self primitiveFailed! ! !ProtoObject methodsFor: 'comparing' stamp: 'md 11/24/1999 19:27'! identityHash "Answer a SmallInteger whose value is related to the receiver's identity. This method must not be overridden, except by SmallInteger. Primitive. Fails if the receiver is a SmallInteger. Essential. See Object documentation whatIsAPrimitive. Do not override." <primitive: 75> self primitiveFailed! ! !ProtoObject methodsFor: 'comparing' stamp: 'md 11/24/1999 19:27'! ~~ anObject "Answer whether the receiver and the argument are not the same object (do not have the same object pointer)." self == anObject ifTrue: [^ false] ifFalse: [^ true]! ! !ProtoObject methodsFor: 'system primitives' stamp: 'md 11/24/1999 19:30'! become: otherObject "Primitive. Swap the object pointers of the receiver and the argument. All variables in the entire system that used to point to the receiver now point to the argument, and vice-versa. Fails if either object is a SmallInteger" (Array with: self) elementsExchangeIdentityWith: (Array with: otherObject)! ! !ProtoObject methodsFor: 'system primitives' stamp: 'ajh 1/13/2002 17:02'! cannotInterpret: aMessage "Handle the fact that there was an attempt to send the given message to the receiver but a null methodDictionary was encountered while looking up the message selector. Hopefully this is the result of encountering a stub for a swapped out class which induces this exception on purpose." "If this is the result of encountering a swap-out stub, then simulating the lookup in Smalltalk should suffice to install the class properly, and the message may be resent." (self class lookupSelector: aMessage selector) == nil ifFalse: ["Simulated lookup succeeded -- resend the message." ^ aMessage sentTo: self]. "Could not recover by simulated lookup -- it's an error" Error signal: 'MethodDictionary fault'. "Try again in case an error handler fixed things" ^ aMessage sentTo: self! ! !ProtoObject methodsFor: 'system primitives' stamp: 'ajh 10/9/2001 17:20'! doesNotUnderstand: aMessage ^ MessageNotUnderstood new message: aMessage; receiver: self; signal! ! !ProtoObject methodsFor: 'system primitives' stamp: 'md 11/24/1999 19:58'! nextInstance "Primitive. Answer the next instance after the receiver in the enumeration of all instances of this class. Fails if all instances have been enumerated. Essential. See Object documentation whatIsAPrimitive." <primitive: 78> ^nil! ! !ProtoObject methodsFor: 'system primitives' stamp: 'md 11/24/1999 19:58'! nextObject "Primitive. Answer the next object after the receiver in the enumeration of all objects. Return 0 when all objects have been enumerated." <primitive: 139> self primitiveFailed.! ! !ProtoObject methodsFor: 'objects from disk' stamp: 'md 11/24/1999 20:03'! rehash "Do nothing. Here so sending this to a Set does not have to do a time consuming respondsTo:"! ! !ProtoObject methodsFor: 'debugging' stamp: 'sw 10/26/2000 14:29'! doOnlyOnce: aBlock "If the 'one-shot' mechanism is armed, evaluate aBlock once and disarm the one-shot mechanism. To rearm the mechanism, evaluate 'self rearmOneShot' manually." (Smalltalk at: #OneShotArmed ifAbsent: [true]) ifTrue: [Smalltalk at: #OneShotArmed put: false. aBlock value]! ! !ProtoObject methodsFor: 'debugging' stamp: 'sw 4/28/2000 14:41'! flag: aSymbol "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: self flag: #returnHereUrgently Then, to retrieve all such messages, browse all senders of #returnHereUrgently."! ! !ProtoObject methodsFor: 'initialize-release' stamp: 'md 11/18/2003 10:33'! initialize "Subclasses should redefine this method to perform initializations on instance creation"! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:20'! tryNamedPrimitive "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:20'! tryNamedPrimitive: arg1 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:20'! tryNamedPrimitive: arg1 with: arg2 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:20'! tryNamedPrimitive: arg1 with: arg2 with: arg3 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:20'! tryNamedPrimitive: arg1 with: arg2 with: arg3 with: arg4 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:21'! tryNamedPrimitive: arg1 with: arg2 with: arg3 with: arg4 with: arg5 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:21'! tryNamedPrimitive: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:21'! tryNamedPrimitive: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 with: arg7 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:21'! tryNamedPrimitive: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 with: arg7 with: arg8 "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive:'' module:''> ^ ContextPart primitiveFailToken! ! !ProtoObject methodsFor: 'apply primitives' stamp: 'ajh 1/31/2003 22:21'! tryPrimitive: primIndex withArgs: argumentArray "This method is a template that the Smalltalk simulator uses to execute primitives. See Object documentation whatIsAPrimitive." <primitive: 118> ^ ContextPart primitiveFailToken! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProtoObject class instanceVariableNames: ''! !ProtoObject class methodsFor: 'as yet unclassified' stamp: 'sw 5/5/2000 09:31'! initializedInstance ^ nil! ! MessageSet subclass: #ProtocolBrowser instanceVariableNames: 'selectedClass selectedSelector' classVariableNames: 'TextMenu' poolDictionaries: '' category: 'Tools-Browser'! !ProtocolBrowser commentStamp: '<historical>' prior: 0! An instance of ProtocolBrowser shows the methods a class understands--inherited or implemented at this level--as a "flattened" list.! !ProtocolBrowser methodsFor: 'accessing' stamp: 'di 7/13/97 16:33'! getList "Answer the receiver's message list." ^ messageList! ! !ProtocolBrowser methodsFor: 'accessing' stamp: 'sw 1/28/2001 21:01'! growable "Answer whether the receiver is subject to manual additions and deletions" ^ false! ! !ProtocolBrowser methodsFor: 'accessing' stamp: 'di 7/13/97 16:33'! list "Answer the receiver's message list." ^ messageList! ! !ProtocolBrowser methodsFor: 'accessing' stamp: 'di 7/13/97 16:35'! selector "Answer the receiver's selected selector." ^ selectedSelector! ! !ProtocolBrowser methodsFor: 'accessing' stamp: 'di 7/13/97 16:35'! selector: aString "Set the currently selected message selector to be aString." selectedSelector := aString. self changed: #selector! ! !ProtocolBrowser methodsFor: 'accessing' stamp: 'di 7/13/97 16:35'! setSelector: aString "Set the currently selected message selector to be aString." selectedSelector := aString! ! !ProtocolBrowser methodsFor: 'private' stamp: 'nk 8/18/2001 18:16'! initListFrom: selectorCollection highlighting: aClass "Make up the messageList with items from aClass in boldface." | defClass item | messageList := OrderedCollection new. selectorCollection do: [ :selector | defClass := aClass whichClassIncludesSelector: selector. item _ selector, ' (' , defClass name , ')'. defClass == aClass ifTrue: [item _ item asText allBold]. messageList add: ( MethodReference new setClass: defClass methodSymbol: selector stringVersion: item ) ]. selectedClass _ aClass.! ! !ProtocolBrowser methodsFor: 'private' stamp: 'di 7/13/97 16:26'! on: aClass "Initialize with the entire protocol for the class, aClass." self initListFrom: aClass allSelectors asSortedCollection highlighting: aClass! ! !ProtocolBrowser methodsFor: 'private' stamp: 'di 11/26/1999 19:39'! onSubProtocolOf: aClass "Initialize with the entire protocol for the class, aClass, but excluding those inherited from Object." | selectors | selectors := Set new. aClass withAllSuperclasses do: [:each | (each == Object or: [each == ProtoObject]) ifFalse: [selectors addAll: each selectors]]. self initListFrom: selectors asSortedCollection highlighting: aClass! ! !ProtocolBrowser methodsFor: 'private' stamp: 'RAA 5/28/2001 11:07'! setClassAndSelectorIn: csBlock "Decode strings of the form <selectorName> (<className> [class])" | i classAndSelString selString sel | sel _ self selection ifNil: [^ csBlock value: nil value: nil]. (sel isKindOf: MethodReference) ifTrue: [ sel setClassAndSelectorIn: csBlock ] ifFalse: [ selString _ sel asString. i _ selString indexOf: $(. "Rearrange to <className> [class] <selectorName> , and use MessageSet" classAndSelString _ (selString copyFrom: i + 1 to: selString size - 1) , ' ' , (selString copyFrom: 1 to: i - 1) withoutTrailingBlanks. MessageSet parse: classAndSelString toClassAndSelector: csBlock. ]. ! ! !ProtocolBrowser methodsFor: 'class list' stamp: 'nk 4/10/2001 08:16'! selectedClassOrMetaClass ^selectedClass! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ProtocolBrowser class instanceVariableNames: ''! !ProtocolBrowser class methodsFor: 'instance creation' stamp: 'di 7/13/97 15:15'! openFullProtocolForClass: aClass "Create and schedule a browser for the entire protocol of the class." "ProtocolBrowser openFullProtocolForClass: ProtocolBrowser." | aPBrowser label | aPBrowser := ProtocolBrowser new on: aClass. label := 'Entire protocol of: ', aClass name. self open: aPBrowser name: label! ! !ProtocolBrowser class methodsFor: 'instance creation' stamp: 'di 7/13/97 15:15'! openSubProtocolForClass: aClass "Create and schedule a browser for the entire protocol of the class." "ProtocolBrowser openSubProtocolForClass: ProtocolBrowser." | aPBrowser label | aPBrowser := ProtocolBrowser new onSubProtocolOf: aClass. label := 'Sub-protocol of: ', aClass name. self open: aPBrowser name: label! ! Object subclass: #PseudoClass instanceVariableNames: 'name definition organization source metaClass' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !PseudoClass commentStamp: '<historical>' prior: 0! I provide an inert model of a Class, used by FileContentsBrowser to manipulate filedout code. Instead of a method dictionary or selectors onto CompiledMethods, I have a dictionary ("source") of selectors onto ChangeRecords, which were, in the case of FileContentsBrowser, parsed from a source or change set file.! !PseudoClass methodsFor: 'class'! classComment: aChangeRecord self organization classComment: aChangeRecord! ! !PseudoClass methodsFor: 'class' stamp: 'di 1/13/1999 12:00'! classPool self exists ifFalse: [^ nil]. ^ self realClass classPool! ! !PseudoClass methodsFor: 'class' stamp: 'BJP 4/23/2001 13:50'! comment | rStr | rStr := self organization commentRemoteStr. ^rStr isNil ifTrue:[self name,' has not been commented in this file'] ifFalse:[rStr string]! ! !PseudoClass methodsFor: 'class'! comment: aString self commentString: aString.! ! !PseudoClass methodsFor: 'class' stamp: 'ar 2/5/2004 15:18'! commentString ^self comment asString! ! !PseudoClass methodsFor: 'class'! commentString: aString self classComment: aString asText. "Just wrap it"! ! !PseudoClass methodsFor: 'class' stamp: 'LC 10/8/2001 04:46'! definition | link linkText defText | ^definition ifNil: [defText _ Text fromString: 'There is no class definition for '. link _ TextLink new. linkText _ link analyze: self name with: 'Definition'. linkText _ Text string: (linkText ifNil: ['']) attribute: link. defText append: linkText; append: ' in this file'].! ! !PseudoClass methodsFor: 'class'! definition: aString definition := aString! ! !PseudoClass methodsFor: 'class'! metaClass ^metaClass ifNil:[metaClass := PseudoMetaclass new name: (self name)].! ! !PseudoClass methodsFor: 'class' stamp: 'nk 2/18/2004 18:30'! renameTo: aString self hasDefinition ifTrue:[ self isMeta ifTrue:[ self definition: (self definition copyReplaceAll: name,' class' with: aString, ' class'). ] ifFalse:[ self definition: (self definition copyReplaceAll:'ubclass: #',name with:'ubclass: #', aString)]]. name := aString. metaClass ifNotNil:[metaClass renameTo: aString].! ! !PseudoClass methodsFor: 'class' stamp: 'di 1/13/1999 12:00'! sharedPools self exists ifFalse: [^ nil]. ^ self realClass sharedPools! ! !PseudoClass methodsFor: 'accessing' stamp: 'nk 4/29/2004 06:59'! allCallsOn ^ (self realClass ifNil: [ ^#() ]) allCallsOn! ! !PseudoClass methodsFor: 'accessing' stamp: 'sma 6/16/1999 22:59'! allInstVarNames ^#()! ! !PseudoClass methodsFor: 'accessing' stamp: 'nk 2/18/2004 18:32'! allSuperclasses ^ (self realClass ifNil: [ ^#() ]) allSuperclasses! ! !PseudoClass methodsFor: 'accessing' stamp: 'sma 4/28/2000 17:24'! compilerClass ^ (Smalltalk at: name ifAbsent: [^ Compiler]) compilerClass! ! !PseudoClass methodsFor: 'accessing'! fullName ^self name! ! !PseudoClass methodsFor: 'accessing' stamp: 'nk 3/9/2004 10:24'! instVarNames ^ #()! ! !PseudoClass methodsFor: 'accessing'! name ^name! ! !PseudoClass methodsFor: 'accessing'! name: anObject name _ anObject! ! !PseudoClass methodsFor: 'accessing' stamp: 'NS 4/6/2004 15:46'! organization organization ifNil: [organization _ PseudoClassOrganizer defaultList: SortedCollection new]. "Making sure that subject is set correctly. It should not be necessary." organization setSubject: self. ^ organization! ! !PseudoClass methodsFor: 'accessing' stamp: 'nk 2/18/2004 18:32'! realClass ^Smalltalk at: self name asSymbol ifAbsent: []! ! !PseudoClass methodsFor: 'accessing' stamp: 'wod 5/19/1998 17:42'! theNonMetaClass "Sent to a class or metaclass, always return the class" ^self! ! !PseudoClass methodsFor: 'removing'! removeAllUnmodified | stClass | self exists ifFalse:[^self]. self removeUnmodifiedMethods: self selectors. stClass := self realClass. (self hasDefinition and:[stClass definition = self definition]) ifTrue:[definition := nil]. (self hasComment and:[stClass comment asString = self commentString]) ifTrue:[ self classComment: nil]. metaClass isNil ifFalse:[metaClass removeAllUnmodified].! ! !PseudoClass methodsFor: 'removing'! removeUnmodifiedMethods: aCollection | stClass | self exists ifFalse:[^self]. stClass := self realClass. aCollection do:[:sel| (self sourceCodeAt: sel) = (stClass sourceCodeAt: sel ifAbsent:['']) asString ifTrue:[ self removeMethod: sel. ]. ]. self organization removeEmptyCategories.! ! !PseudoClass methodsFor: 'private' stamp: 'nk 2/18/2004 18:33'! allSubclassesWithLevelDo: classAndLevelBlock startingLevel: level ^ (self realClass ifNil: [ ^self ]) allSubclassesWithLevelDo: classAndLevelBlock startingLevel: level! ! !PseudoClass methodsFor: 'private'! confirmRemovalOf: aString ^self confirm:'Remove ',aString,' ?'! ! !PseudoClass methodsFor: 'private'! evaluate: aString ^Compiler evaluate: aString for: nil logged: true! ! !PseudoClass methodsFor: 'private'! makeSureSuperClassExists: aString | theClass | theClass := Smalltalk at: (aString asSymbol) ifAbsent:[nil]. theClass ifNotNil:[^true]. ^self confirm: 'The super class ',aString,' does not exist in the system. Use nil instead?'.! ! !PseudoClass methodsFor: 'private' stamp: 'ajh 1/21/2003 13:03'! parserClass ^ Compiler parserClass! ! !PseudoClass methodsFor: 'testing'! exists ^(Smalltalk at: self name asSymbol ifAbsent:[^false]) isKindOf: Behavior! ! !PseudoClass methodsFor: 'testing'! hasChanges self sourceCode isEmpty ifFalse:[^true]. self organization hasNoComment ifFalse:[^true]. definition isNil ifFalse:[^true]. metaClass isNil ifFalse:[^metaClass hasChanges]. ^false! ! !PseudoClass methodsFor: 'testing'! hasComment ^self organization commentRemoteStr notNil! ! !PseudoClass methodsFor: 'testing'! hasDefinition ^definition notNil! ! !PseudoClass methodsFor: 'testing'! hasMetaclass ^metaClass notNil! ! !PseudoClass methodsFor: 'testing' stamp: 'nk 2/18/2004 18:30'! isMeta ^false! ! !PseudoClass methodsFor: 'testing'! needsInitialize ^self hasMetaclass and:[ self metaClass selectors includes: #initialize]! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileIn "FileIn the receiver" self hasDefinition ifTrue:[self fileInDefinition]. self fileInMethods: self selectors. metaClass ifNotNil:[metaClass fileIn]. self needsInitialize ifTrue:[ self evaluate: self name,' initialize'. ].! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileInCategory: aCategory ^self fileInMethods: (self organization listAtCategoryNamed: aCategory)! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileInDefinition (self makeSureSuperClassExists: (definition copyUpTo: Character space)) ifFalse:[^self]. self hasDefinition ifTrue:[ Transcript cr; show:'Defining ', self name. self evaluate: self definition]. self exists ifFalse:[^self]. self hasComment ifTrue:[self realClass classComment: self comment].! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileInMethod: selector ^self fileInMethods: (Array with: selector)! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileInMethods ^self fileInMethods: self selectors! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileInMethods: aCollection "FileIn all methods with selectors taken from aCollection" | theClass cat | self exists ifFalse:[^self classNotDefined]. theClass := self realClass. aCollection do:[:sel| cat := self organization categoryOfElement: sel. cat = self removedCategoryName ifFalse:[ theClass compile: (self sourceCodeAt: sel) classified: cat withStamp: (self stampAt: sel) notifying: nil. ]. ].! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileOut | f | f := (FileStream newFileNamed: self name,'.st'). self fileOutOn: f. self needsInitialize ifTrue:[ f cr; nextChunkPut: self name,' initialize'. ]. f close! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileOutCategory: categoryName | f | f := (FileStream newFileNamed: self name,'-',categoryName,'.st'). self fileOutMethods: (self organization listAtCategoryNamed: categoryName) on: f. f close ! ! !PseudoClass methodsFor: 'fileIn/fileOut' stamp: 'hg 9/6/2000 12:45'! fileOutDefinitionOn: aStream self hasDefinition ifFalse:[^self]. aStream nextChunkPut: self definition; cr. self hasComment ifTrue: [aStream cr. self organization commentRemoteStr fileOutOn: aStream]! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileOutMethod: selector | f | f := (FileStream newFileNamed: self name,'-', selector, '.st'). self fileOutMethods: (Array with: selector) on: f. f close! ! !PseudoClass methodsFor: 'fileIn/fileOut' stamp: 'ar 2/7/2004 01:04'! fileOutMethods: aCollection on: aStream "FileOut all methods with selectors taken from aCollection" | cat categories | categories := Dictionary new. aCollection do:[:sel| cat := self organization categoryOfElement: sel. cat = self removedCategoryName ifFalse:[ (categories includesKey: cat) ifFalse:[categories at: cat put: Set new]. (categories at: cat) add: sel]. ]. categories associationsDo:[:assoc| cat := assoc key. assoc value do:[:sel| aStream cr. (self sourceCode at: sel) fileOutOn: aStream. ]. ].! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileOutMethodsOn: aStream ^self fileOutMethods: self selectors on: aStream.! ! !PseudoClass methodsFor: 'fileIn/fileOut'! fileOutOn: aStream "FileOut the receiver" self fileOutDefinitionOn: aStream. metaClass ifNotNil:[metaClass fileOutDefinitionOn: aStream]. self fileOutMethods: self selectors on: aStream. metaClass ifNotNil:[metaClass fileOutMethods: metaClass selectors on: aStream].! ! !PseudoClass methodsFor: 'errors'! classNotDefined ^self inform: self name,' is not defined in the system. You have to define this class first.'.! ! !PseudoClass methodsFor: 'categories'! removeCategory: selector (self organization listAtCategoryNamed: selector) do:[:sel| self organization removeElement: sel. self sourceCode removeKey: sel. ]. self organization removeCategory: selector.! ! !PseudoClass methodsFor: 'categories'! removedCategoryName ^'*** removed methods ***' asSymbol! ! !PseudoClass methodsFor: 'categories'! whichCategoryIncludesSelector: aSelector "Answer the category of the argument, aSelector, in the organization of the receiver, or answer nil if the receiver does not inlcude this selector." ^ self organization categoryOfElement: aSelector! ! !PseudoClass methodsFor: 'methods' stamp: 'sma 6/1/2000 14:54'! addMethodChange: aChangeRecord | selector | selector _ self parserClass new parseSelector: aChangeRecord string. self organization classify: selector under: aChangeRecord category. self sourceCodeAt: selector put: aChangeRecord! ! !PseudoClass methodsFor: 'methods'! methodChange: aChangeRecord aChangeRecord isMetaClassChange ifTrue:[ ^self metaClass addMethodChange: aChangeRecord. ] ifFalse:[ ^self addMethodChange: aChangeRecord. ]. ! ! !PseudoClass methodsFor: 'methods'! removeMethod: selector self organization removeElement: selector. self sourceCode removeKey: selector. ! ! !PseudoClass methodsFor: 'methods'! removeSelector: aSelector | catName | catName := self removedCategoryName. self organization addCategory: catName before: self organization categories first. self organization classify: aSelector under: catName. self sourceCodeAt: aSelector put:'methodWasRemoved' asText.! ! !PseudoClass methodsFor: 'methods'! selectors ^self sourceCode keys! ! !PseudoClass methodsFor: 'methods'! sourceCode ^source ifNil:[source := Dictionary new]! ! !PseudoClass methodsFor: 'methods'! sourceCodeAt: sel ^(self sourceCode at: sel) string! ! !PseudoClass methodsFor: 'methods'! sourceCodeAt: sel put: object self sourceCode at: sel put: object! ! !PseudoClass methodsFor: 'methods'! sourceCodeTemplate ^''! ! !PseudoClass methodsFor: 'methods'! stampAt: selector ^(self sourceCode at: selector) stamp! ! !PseudoClass methodsFor: 'printing' stamp: 'sma 6/17/1999 00:00'! literalScannedAs: scannedLiteral notifying: requestor ^ scannedLiteral! ! !PseudoClass methodsFor: 'printing' stamp: 'ar 2/5/2004 16:04'! printOn: aStream super printOn: aStream. aStream nextPut:$(; print: name; nextPut:$)! ! !PseudoClass methodsFor: 'testing method dictionary' stamp: 'ar 5/17/2003 14:06'! bindingOf: varName self exists ifTrue:[ (self realClass bindingOf: varName) ifNotNilDo:[:binding| ^binding]. ]. ^Smalltalk bindingOf: varName asSymbol! ! BasicClassOrganizer subclass: #PseudoClassOrganizer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !PseudoClassOrganizer methodsFor: 'comment accessing' stamp: 'NS 4/6/2004 16:44'! classComment "Answer the comment associated with the object that refers to the receiver." classComment == nil ifTrue: [^'']. ^classComment! ! !PseudoClassOrganizer methodsFor: 'comment accessing' stamp: 'NS 4/6/2004 16:44'! classComment: aChangeRecord classComment := aChangeRecord! ! !PseudoClassOrganizer methodsFor: 'accessing' stamp: 'NS 4/6/2004 12:27'! setDefaultList: aCollection super setDefaultList: aCollection. self classComment: nil.! ! ProtoObject variableSubclass: #PseudoContext instanceVariableNames: 'fixed fields never accessed from smalltalk' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'. PseudoContext superclass: nil! !PseudoContext commentStamp: '<historical>' prior: 0! I represent cached context state within the virtual machine. I have the same format as normal method and block contexts, but my fields are never referenced directly from Smalltalk. Whenever a message is sent to me I will magically transform myself into a real context which will respond to all the usual messages. I rely on the fact that block and method contexts have exactly the same number of fixed fields.! !PseudoContext methodsFor: 'testing' stamp: 'ikp 9/26/97 14:45'! isPseudoContext ^true! ! !PseudoContext methodsFor: 'system primitives' stamp: 'ikp 10/20/97 15:36'! nextObject "See Object>>nextObject." <primitive: 139> self primitiveFailed.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PseudoContext class instanceVariableNames: ''! !PseudoContext class methodsFor: 'class initialization' stamp: 'ikp 1/10/98 02:33'! initialize "It's tricky to do the necessary stuff with the regular file-in machinery." PseudoContext superclass = nil ifFalse: [ (Smalltalk confirm: 'Shall I convert PseudoContext into a compact subclass of nil? ("yes" is almost always the correct response)') ifTrue: [ PseudoContext becomeCompact. PseudoContext superclass removeSubclass: PseudoContext. PseudoContext superclass: nil]]. Smalltalk recreateSpecialObjectsArray. Smalltalk specialObjectsArray size = 41 ifFalse: [self error: 'Please check size of special objects array!!']! ! !PseudoContext class methodsFor: 'filing out' stamp: 'ikp 9/26/97 14:45'! definition "Our superclass is really nil, but this causes problems when we try to become compact after filing in for the first time. Fake the superclass as Object, and repair the situation during class initialisation." | defn | defn _ super definition. ^(defn beginsWith: 'nil ') ifTrue: ['Object' , (defn copyFrom: 4 to: defn size)] ifFalse: [defn].! ! PseudoClass subclass: #PseudoMetaclass instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !PseudoMetaclass methodsFor: 'accessing'! fullName ^self name,' class'! ! !PseudoMetaclass methodsFor: 'accessing'! realClass ^super realClass class! ! !PseudoMetaclass methodsFor: 'accessing' stamp: 'FBS 3/4/2004 14:17'! theNonMetaClass "Sent to a class or metaclass, always return the class" ^self realClass theNonMetaClass! ! !PseudoMetaclass methodsFor: 'testing' stamp: 'nk 2/18/2004 18:30'! isMeta ^true! ! Rectangle subclass: #Quadrangle instanceVariableNames: 'borderWidth borderColor insideColor' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Quadrangle commentStamp: '<historical>' prior: 0! I represent a particular kind of Rectangle that has a border and inside color.! !Quadrangle methodsFor: 'initialize-release'! initialize "Initialize the region to a null Rectangle, the borderWidth to 1, the borderColor to black, and the insideColor to white." origin _ 0 @ 0. corner _ 0 @ 0. borderWidth _ 1. borderColor _ Color black. insideColor _ Color white. ! ! !Quadrangle methodsFor: 'bordering'! borderWidth "Answer the borderWidth of the receiver." ^borderWidth! ! !Quadrangle methodsFor: 'bordering'! borderWidth: anInteger "Set the borderWidth of the receiver to anInteger." borderWidth _ anInteger! ! !Quadrangle methodsFor: 'bordering'! borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4 "Set the border width of the receiver to a Rectangle that represents the left, right, top, and bottom border widths." borderWidth _ anInteger1 @ anInteger3 corner: anInteger2 @ anInteger4! ! !Quadrangle methodsFor: 'bordering'! inside "Answer a Rectangle that is the receiver inset by the borderWidth." ^self insetBy: borderWidth! ! !Quadrangle methodsFor: 'bordering'! insideColor "Answer the form that is the insideColor of the receiver." ^insideColor! ! !Quadrangle methodsFor: 'bordering'! insideColor: aColor "Set the insideColor of the receiver to aColor, a Form." insideColor _ aColor! ! !Quadrangle methodsFor: 'bordering'! region "Answer a Rectangle that defines the area of the receiver." ^origin corner: corner! ! !Quadrangle methodsFor: 'bordering'! region: aRectangle "Set the rectangular area of the receiver to aRectangle." origin _ aRectangle origin. corner _ aRectangle corner! ! !Quadrangle methodsFor: 'rectangle functions'! intersect: aRectangle "Answer a new Quadrangle whose region is the intersection of the receiver's area and aRectangle. 5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality." ^ self class region: (super intersect: aRectangle) borderWidth: borderWidth borderColor: borderColor insideColor: insideColor! ! !Quadrangle methodsFor: 'transforming'! align: aPoint1 with: aPoint2 "Answer a new Quadrangle translated by aPoint2 - aPoint1. 5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality." ^ self class region: (super translateBy: aPoint2 - aPoint1) borderWidth: borderWidth borderColor: borderColor insideColor: insideColor! ! !Quadrangle methodsFor: 'transforming'! alignedTo: alignPointSelector "Return a copy with offset according to alignPointSelector which is one of... #(topLeft, topCenter, topRight, leftCenter, center, etc) 5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality." ^ self class region: (super translateBy: (0@0) - (self perform: alignPointSelector)) borderWidth: borderWidth borderColor: borderColor insideColor: insideColor! ! !Quadrangle methodsFor: 'transforming'! scaleBy: aPoint "Answer a new Quadrangle scaled by aPoint. 5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality." ^ self class region: (super scaleBy: aPoint) borderWidth: borderWidth borderColor: borderColor insideColor: insideColor! ! !Quadrangle methodsFor: 'transforming'! translateBy: aPoint "Answer a new Quadrangle translated by aPoint. 5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality." ^ self class region: (super translateBy: aPoint) borderWidth: borderWidth borderColor: borderColor insideColor: insideColor! ! !Quadrangle methodsFor: 'displaying-generic'! displayOn: aDisplayMedium "Display the border and insideRegion of the receiver." borderWidth ~~ 0 ifTrue: [aDisplayMedium border: self region widthRectangle: borderWidth rule: Form over fillColor: borderColor]. insideColor ~~ nil ifTrue: [aDisplayMedium fill: self inside fillColor: insideColor]! ! !Quadrangle methodsFor: 'displaying-generic'! displayOn: aDisplayMedium transformation: aWindowingTransformation clippingBox: aRectangle "Display the border and region of the receiver so that it is scaled and translated with respect to aWindowingTransformation. The displayed information should be clipped so that only information with the area determined by aRectangle is displayed." | screenRectangle | screenRectangle _ (aWindowingTransformation applyTo: self) intersect: aRectangle. borderWidth ~~ 0 & (insideColor ~~ nil) ifTrue: [aDisplayMedium fill: screenRectangle fillColor: Color black "borderColor". aDisplayMedium fill: (screenRectangle insetBy: borderWidth) fillColor: insideColor]! ! !Quadrangle methodsFor: 'displaying-generic'! displayOnPort: aPort at: p "Display the border and insideRegion of the receiver." (insideColor == nil or: [borderWidth <= 0]) ifFalse: [aPort fill: (self region translateBy: p) fillColor: borderColor rule: Form over]. insideColor == nil ifFalse: [aPort fill: (self inside translateBy: p) fillColor: insideColor rule: Form over]! ! !Quadrangle methodsFor: 'displaying-Display'! display "Display the border and insideRegion of the receiver on the Display." self displayOn: Display! ! !Quadrangle methodsFor: 'private'! setRegion: aRectangle borderWidth: anInteger borderColor: aMask1 insideColor: aMask2 origin _ aRectangle origin. corner _ aRectangle corner. borderWidth _ anInteger. borderColor _ aMask1. insideColor _ aMask2! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Quadrangle class instanceVariableNames: ''! !Quadrangle class methodsFor: 'instance creation'! region: aRectangle borderWidth: anInteger borderColor: aMask1 insideColor: aMask2 "Answer an instance of me with rectangle, border width and color, and inside color determined by the arguments." ^super new setRegion: aRectangle borderWidth: anInteger borderColor: aMask1 insideColor: aMask2! ! ReadWriteStream subclass: #RWBinaryOrTextStream instanceVariableNames: 'isBinary' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !RWBinaryOrTextStream commentStamp: '<historical>' prior: 0! A simulation of a FileStream, but living totally in memory. Hold the contents of a file or web page from the network. Can then fileIn like a normal FileStream. Need to be able to switch between binary and text, as a FileStream does, without recopying the whole collection. Convert to binary upon input and output. Always keep as text internally.! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/25/97 13:22'! ascii isBinary _ false! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/20/97 19:46'! binary isBinary _ true! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/21/97 12:49'! contents "Answer with a copy of my collection from 1 to readLimit." | newArray | isBinary ifFalse: [^ super contents]. "String" readLimit _ readLimit max: position. newArray _ ByteArray new: readLimit. ^ newArray replaceFrom: 1 to: readLimit with: collection startingAt: 1.! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'jm 11/4/97 08:25'! contentsOfEntireFile "For compatibility with file streams." ^ self contents! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/20/97 19:47'! isBinary ^ isBinary! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 12/13/97 13:07'! next | byte | ^ isBinary ifTrue: [byte _ super next. byte ifNil: [nil] ifNotNil: [byte asciiValue]] ifFalse: [super next]. ! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 2/7/2000 15:34'! next: anInteger "Answer the next anInteger elements of my collection. Must override to get class right." | newArray | newArray _ (isBinary ifTrue: [ByteArray] ifFalse: [String]) new: anInteger. ^ self nextInto: newArray! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'ls 3/27/2000 22:24'! next: n into: aCollection startingAt: startIndex "Read n objects into the given collection. Return aCollection or a partial copy if less than n elements have been read." "Overriden for efficiency" | max | max _ (readLimit - position) min: n. aCollection replaceFrom: startIndex to: startIndex+max-1 with: collection startingAt: position+1. position _ position + max. max = n ifTrue:[^aCollection] ifFalse:[^aCollection copyFrom: 1 to: startIndex+max-1]! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/20/97 07:38'! nextPut: charOrByte super nextPut: charOrByte asCharacter! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/21/97 13:04'! reset "Set the receiver's position to the beginning of the sequence of objects." super reset. isBinary ifNil: [isBinary _ false]. collection class == ByteArray ifTrue: ["Store as String and convert as needed." collection _ collection asString. isBinary _ true]. ! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'tk 6/20/97 19:47'! text isBinary _ false! ! !RWBinaryOrTextStream methodsFor: 'as yet unclassified' stamp: 'ar 3/5/2001 12:12'! upToEnd "Must override to get class right." | newArray | newArray _ (isBinary ifTrue: [ByteArray] ifFalse: [String]) new: self size - self position. ^ self nextInto: newArray! ! !RWBinaryOrTextStream methodsFor: 'writing' stamp: 'ar 8/12/2003 16:54'! nextPutAll: aCollection ^super nextPutAll: aCollection asString! ! Object subclass: #Random instanceVariableNames: 'seed a m q r' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !Random commentStamp: 'md 4/26/2003 16:32' prior: 0! This Random Number Generator graciously contributed by David N. Smith. It is an adaptation of the Park-Miller RNG which uses Floats to avoid the need for LargeInteger arithmetic. If you just want a quick random integer, use: 10 atRandom Every integer interval can give a random number: (6 to: 12) atRandom SequenceableCollections can give randomly selected elements: 'pick one of these letters randomly' atRandom SequenceableCollections also respond to shuffled, as in: ($A to: $Z) shuffled The correct way to use class Random is to store one in an instance or class variable: myGenerator _ Random new. Then use it every time you need another number between 0.0 and 1.0 (excluding) myGenerator next You can also generate a positive integer myGenerator nextInt: 10! !Random methodsFor: 'initialization' stamp: 'di 8/6/1999 15:32'! initialize " Set a reasonable Park-Miller starting seed " [seed := (Time millisecondClockValue bitAnd: 16r3FFFFFFF) bitXor: self hash. seed = 0] whileTrue: ["Try again if ever get a seed = 0"]. a := 16r000041A7 asFloat. " magic constant = 16807 " m := 16r7FFFFFFF asFloat. " magic constant = 2147483647 " q := (m quo: a) asFloat. r := (m \\ a) asFloat. ! ! !Random methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:25'! next "Answer a random Float in the interval [0 to 1)." ^ (seed _ self nextValue) / m! ! !Random methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:45'! next: anInteger ^ self next: anInteger into: (Array new: anInteger)! ! !Random methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:46'! next: anInteger into: anArray 1 to: anInteger do: [:index | anArray at: index put: self next]. ^ anArray! ! !Random methodsFor: 'accessing' stamp: 'dns 8/26/2001 18:43'! nextInt: anInteger "Answer a random integer in the interval [1, anInteger]." anInteger strictlyPositive ifFalse: [ self error: 'Range must be positive' ]. ^ (self next * anInteger) truncated + 1! ! !Random methodsFor: 'private' stamp: 'sma 5/12/2000 12:28'! nextValue "This method generates random instances of Integer in the interval 0 to 16r7FFFFFFF. This method does NOT update the seed; repeated sends answer the same value. The algorithm is described in detail in 'Random Number Generators: Good Ones Are Hard to Find' by Stephen K. Park and Keith W. Miller (Comm. Asso. Comp. Mach., 31(10):1192--1201, 1988)." | lo hi aLoRHi answer | hi _ (seed quo: q) asFloat. lo _ seed - (hi * q). " = seed rem: q" aLoRHi _ (a * lo) - (r * hi). answer _ (aLoRHi > 0.0) ifTrue: [aLoRHi] ifFalse: [aLoRHi + m]. ^ answer! ! PluggableTextController subclass: #ReadOnlyTextController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'ST80-Pluggable Views'! !ReadOnlyTextController methodsFor: 'as yet unclassified' stamp: 'di 5/7/1998 13:41'! accept "Overridden to allow accept of clean text" (view setText: paragraph text from: self) ifTrue: [initialText _ paragraph text copy. view ifNotNil: [view hasUnacceptedEdits: false]]. ! ! !ReadOnlyTextController methodsFor: 'as yet unclassified' stamp: 'di 5/7/1998 14:02'! userHasEdited "Ignore this -- I stay clean"! ! !ReadOnlyTextController methodsFor: 'as yet unclassified' stamp: 'di 5/7/1998 13:45'! zapSelectionWith: aText view flash "no edits allowed"! ! LookupKey subclass: #ReadOnlyVariableBinding instanceVariableNames: 'value' classVariableNames: '' poolDictionaries: '' category: 'Collections-Support'! !ReadOnlyVariableBinding methodsFor: 'accessing' stamp: 'ar 8/14/2001 23:09'! value ^value! ! !ReadOnlyVariableBinding methodsFor: 'accessing' stamp: 'ar 8/17/2001 18:03'! value: aValue (AttemptToWriteReadOnlyGlobal signal: 'Cannot store into read-only bindings') == true ifTrue:[ value _ aValue. ].! ! !ReadOnlyVariableBinding methodsFor: 'testing' stamp: 'ar 8/14/2001 23:08'! isSpecialWriteBinding "Return true if this variable binding is write protected, e.g., should not be accessed primitively but rather by sending #value: messages" ^true! ! !ReadOnlyVariableBinding methodsFor: 'private' stamp: 'ar 8/14/2001 23:11'! privateSetKey: aKey value: aValue key _ aKey. value _ aValue! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ReadOnlyVariableBinding class instanceVariableNames: ''! !ReadOnlyVariableBinding class methodsFor: 'instance creation' stamp: 'ar 8/14/2001 23:11'! key: key value: aValue ^self new privateSetKey: key value: aValue! ! PositionableStream subclass: #ReadStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !ReadStream commentStamp: '<historical>' prior: 0! I represent an accessor for a sequence of objects that can only read objects from the sequence.! !ReadStream methodsFor: 'accessing'! ascii! ! !ReadStream methodsFor: 'accessing'! binary! ! !ReadStream methodsFor: 'accessing'! next "Primitive. Answer the next object in the Stream represented by the receiver. Fail if the collection of this stream is not an Array or a String. Fail if the stream is positioned at its end, or if the position is out of bounds in the collection. Optional. See Object documentation whatIsAPrimitive." <primitive: 65> position >= readLimit ifTrue: [^nil] ifFalse: [^collection at: (position _ position + 1)]! ! !ReadStream methodsFor: 'accessing' stamp: 'ls 8/16/1998 00:46'! next: anInteger "Answer the next anInteger elements of my collection. overriden for efficiency" | ans endPosition | endPosition _ position + anInteger min: readLimit. ans _ collection copyFrom: position+1 to: endPosition. position _ endPosition. ^ans ! ! !ReadStream methodsFor: 'accessing' stamp: 'ar 12/23/1999 15:01'! next: n into: aCollection startingAt: startIndex "Read n objects into the given collection. Return aCollection or a partial copy if less than n elements have been read." | max | max _ (readLimit - position) min: n. aCollection replaceFrom: startIndex to: startIndex+max-1 with: collection startingAt: position+1. position _ position + max. max = n ifTrue:[^aCollection] ifFalse:[^aCollection copyFrom: 1 to: startIndex+max-1]! ! !ReadStream methodsFor: 'accessing'! nextPut: anObject self shouldNotImplement! ! !ReadStream methodsFor: 'accessing' stamp: 'ajh 9/5/2002 22:11'! readStream "polymorphic with SequenceableCollection. Return self" ^ self! ! !ReadStream methodsFor: 'accessing' stamp: 'ar 11/2/1998 12:20'! size "Compatibility with other streams (e.g., FileStream)" ^readLimit! ! !ReadStream methodsFor: 'accessing' stamp: 'ls 9/12/1998 00:59'! upTo: anObject "fast version using indexOf:" | start end | start _ position+1. end _ collection indexOf: anObject startingAt: start ifAbsent: [ 0 ]. "not present--return rest of the collection" end = 0 ifTrue: [ ^self upToEnd ]. "skip to the end and return the data passed over" position _ end. ^collection copyFrom: start to: (end-1)! ! !ReadStream methodsFor: 'accessing' stamp: 'ls 9/12/1998 00:59'! upToEnd | start | start _ position+1. position _ collection size. ^collection copyFrom: start to: position! ! !ReadStream methodsFor: 'private'! on: aCollection from: firstIndex to: lastIndex | len | collection _ aCollection. readLimit _ lastIndex > (len _ collection size) ifTrue: [len] ifFalse: [lastIndex]. position _ firstIndex <= 1 ifTrue: [0] ifFalse: [firstIndex - 1]! ! !ReadStream methodsFor: 'file stream compatibility' stamp: 'nk 12/13/2002 12:00'! localName ^'ReadStream'! ! !ReadStream methodsFor: 'file stream compatibility' stamp: 'nk 12/13/2002 12:01'! openReadOnly! ! !ReadStream methodsFor: 'file stream compatibility' stamp: 'nk 12/13/2002 12:00'! readOnly! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ReadStream class instanceVariableNames: ''! !ReadStream class methodsFor: 'instance creation'! on: aCollection from: firstIndex to: lastIndex "Answer with a new instance streaming over a copy of aCollection from firstIndex to lastIndex." ^self basicNew on: aCollection from: firstIndex to: lastIndex! ! WriteStream subclass: #ReadWriteStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !ReadWriteStream commentStamp: '<historical>' prior: 0! I represent an accessor for a sequence of objects. My instances can both read and store objects.! !ReadWriteStream methodsFor: 'accessing'! contents "Answer with a copy of my collection from 1 to readLimit." readLimit _ readLimit max: position. ^collection copyFrom: 1 to: readLimit! ! !ReadWriteStream methodsFor: 'accessing'! name ^ 'a stream' "for fileIn compatibility"! ! !ReadWriteStream methodsFor: 'accessing'! next "Primitive. Return the next object in the Stream represented by the receiver. Fail if the collection of this stream is not an Array or a String. Fail if the stream is positioned at its end, or if the position is out of bounds in the collection. Optional. See Object documentation whatIsAPrimitive." <primitive: 65> "treat me as a FIFO" position >= readLimit ifTrue: [^nil] ifFalse: [^collection at: (position _ position + 1)]! ! !ReadWriteStream methodsFor: 'accessing' stamp: 'ar 8/5/2003 02:23'! next: anInteger "Answer the next anInteger elements of my collection. overriden for efficiency" | ans endPosition | readLimit := readLimit max: position. endPosition _ position + anInteger min: readLimit. ans _ collection copyFrom: position+1 to: endPosition. position _ endPosition. ^ans ! ! !ReadWriteStream methodsFor: 'file status'! close "Presumably sets the status of the receiver to be closed. This message does nothing at this level, but is included for FileStream compatibility." ^self! ! !ReadWriteStream methodsFor: 'file status'! closed "If you have close (for FileStream compatibility), you must respond to closed. The result in nonsense here. TK 29 May 96" ^ false! ! !ReadWriteStream methodsFor: 'fileIn/Out' stamp: 'sd 5/23/2003 14:41'! fileOutChanges "Append to the receiver a description of all class changes." Cursor write showWhile: [self header; timeStamp. ChangeSet current fileOutOn: self. self trailer; close]! ! !ReadWriteStream methodsFor: 'converting' stamp: 'ajh 9/14/2002 20:37'! readStream "polymorphic with SequenceableCollection. Return self" ^ self! ! !ReadWriteStream methodsFor: 'testing' stamp: 'tk 11/29/2001 12:47'! = other (self class == ReadWriteStream and: [other class == ReadWriteStream]) ifFalse: [ ^ super = other]. "does an identity test. Don't read contents of FileStream" ^ self position = other position and: [self contents = other contents]! ! !ReadWriteStream methodsFor: 'testing' stamp: 'tk 12/2/2001 17:13'! hash self class == ReadWriteStream ifFalse: [^ super hash]. ^ (self position + readLimit + 53) hash! ! Object subclass: #RealEstateAgent instanceVariableNames: '' classVariableNames: 'ReverseStaggerOffset StaggerOffset StaggerOrigin StandardSize StandardWindowOrigins' poolDictionaries: '' category: 'System-Support'! !RealEstateAgent commentStamp: '<historical>' prior: 0! 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! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RealEstateAgent class instanceVariableNames: ''! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'BG 10/29/2003 09:53'! assignCollapseFrameFor: aSSView "Offer up a location along the left edge of the screen for a collapsed SSView. Make sure it doesn't overlap any other collapsed frames." | grid otherFrames topLeft viewBox collapsedFrame extent newFrame verticalBorderDistance top | grid _ 8. verticalBorderDistance _ 8. aSSView isMorph ifTrue: [] ifFalse: [otherFrames _ ScheduledControllers scheduledWindowControllers collect: [:aController | aController view ~= aSSView ifTrue: [aController view collapsedFrame]] thenSelect: [:rect | rect notNil]. viewBox _ Display boundingBox]. collapsedFrame _ aSSView collapsedFrame. extent _ collapsedFrame notNil ifTrue: [collapsedFrame extent] ifFalse: [aSSView isMorph ifTrue: [aSSView getRawLabel width + aSSView labelWidgetAllowance @ (aSSView labelHeight + 2)] ifFalse: [(aSSView labelText extent x + 70) @ aSSView labelHeight min: aSSView labelDisplayBox extent]]. collapsedFrame notNil ifTrue: [(otherFrames anySatisfy: [:f | collapsedFrame intersects: f]) ifFalse: ["non overlapping" ^ collapsedFrame]]. top _ viewBox top + verticalBorderDistance. [topLeft _ viewBox left @ top. newFrame _ topLeft extent: extent. newFrame bottom <= (viewBox height - verticalBorderDistance)] whileTrue: [(otherFrames anySatisfy: [:w | newFrame intersects: w]) ifFalse: ["no overlap" ^ newFrame]. top _ top + grid]. "If all else fails... (really to many wins here)" ^ 0 @ 0 extent: extent! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 10:48'! assignCollapsePointFor: aSSView "Offer up a location along the left edge of the screen for a collapsed SSView. Make sure it doesn't overlap any other collapsed frames." | grid otherFrames y free topLeft viewBox | grid _ 24. "should be mult of 8, since manual move is gridded by 8" aSSView isMorph ifTrue: [] ifFalse: [otherFrames _ ScheduledControllers scheduledWindowControllers collect: [:aController | aController view collapsedFrame] thenSelect: [:rect | rect notNil]. viewBox _ Display boundingBox]. y _ viewBox top. [(y _ y + grid) <= (viewBox height - grid)] whileTrue: [topLeft _ viewBox left@y. free _ true. otherFrames do: [:w | free _ free & (topLeft ~= w topLeft)]. free ifTrue: [^ topLeft]]. "If all else fails..." ^ 0 @ 0! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'BG 10/29/2003 09:54'! initialFrameFor: aView initialExtent: initialExtent world: aWorld "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." | allOrigins screenRight screenBottom putativeOrigin putativeFrame allowedArea staggerOrigin otherFrames | Preferences reverseWindowStagger ifTrue: [^ self strictlyStaggeredInitialFrameFor: aView initialExtent: initialExtent world: aWorld]. allowedArea _ self maximumUsableAreaInWorld: aWorld. screenRight _ allowedArea right. screenBottom _ allowedArea bottom. otherFrames _ Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers scheduledWindowControllers select: [:aController | aController view ~~ nil] thenCollect: [:aController | aController view isCollapsed ifTrue: [aController view expandedFrame] ifFalse: [aController view displayBox]]]. allOrigins _ otherFrames collect: [:f | f origin]. (self standardPositionsInWorld: aWorld) do: "First see if one of the standard positions is free" [:aPosition | (allOrigins includes: aPosition) ifFalse: [^ (aPosition extent: initialExtent) squishedWithin: allowedArea]]. staggerOrigin _ (self standardPositionsInWorld: aWorld) first. "Fallback: try offsetting from top left" putativeOrigin _ staggerOrigin. [putativeOrigin _ putativeOrigin + StaggerOffset. putativeFrame _ putativeOrigin extent: initialExtent. (putativeFrame bottom < screenBottom) and: [putativeFrame right < screenRight]] whileTrue: [(allOrigins includes: putativeOrigin) ifFalse: [^ (putativeOrigin extent: initialExtent) squishedWithin: allowedArea]]. ^ (self scrollBarSetback @ self screenTopSetback extent: initialExtent) squishedWithin: allowedArea! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 5/25/2000 08:13'! initialFrameFor: aView world: aWorld "Find a plausible initial screen area for the supplied view. See called method." ^ self initialFrameFor: aView initialExtent: aView initialExtent world: aWorld! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'tk 11/26/1998 09:34'! initialize "Initialize the class variables in the receiver. 5/22/96 sw" "RealEstateAgent initialize" StaggerOffset _ 6 @ 20. ReverseStaggerOffset _ -6 @ 20. StaggerOrigin _ 200 @ 30. StandardSize _ 600@400.! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:11'! maximumUsableArea | allowedArea | allowedArea _ Display usableArea. ^allowedArea ! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 5/25/2000 08:42'! maximumUsableAreaInWorld: aWorldOrNil | allowedArea | allowedArea _ Display usableArea. aWorldOrNil ifNotNil: [allowedArea _ allowedArea intersect: aWorldOrNil viewBox]. ^allowedArea ! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:12'! screenTopSetback Smalltalk isMorphic ifTrue: [] ifFalse: [^ 18]! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:12'! scrollBarSetback Smalltalk isMorphic ifTrue: [] "width = 16; inset from border by 3" ifFalse: [^ 24]! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 5/25/2000 08:43'! standardPositionsInWorld: aWorldOrNil "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. " | anArea aList midX midY | anArea _ self maximumUsableAreaInWorld: aWorldOrNil. midX _ self scrollBarSetback + ((anArea width - self scrollBarSetback) // 2). midY _ self screenTopSetback + ((anArea height - self screenTopSetback) // 2). aList _ OrderedCollection with: (self scrollBarSetback @ self screenTopSetback). self windowColumnsDesired > 1 ifTrue: [aList add: (midX @ self screenTopSetback)]. self windowRowsDesired > 1 ifTrue: [aList add: (self scrollBarSetback @ (midY+self screenTopSetback)). self windowColumnsDesired > 1 ifTrue: [aList add: (midX @ (midY+self screenTopSetback))]]. ^ aList! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 11/21/1999 22:55'! standardWindowExtent "Answer the standard default extent for new windows. " | effectiveExtent width strips height grid allowedArea maxLevel | effectiveExtent _ self maximumUsableArea extent - (self scrollBarSetback @ self screenTopSetback). Preferences reverseWindowStagger ifTrue: ["NOTE: following copied from strictlyStaggeredInitialFrameFor:" allowedArea _ self maximumUsableArea insetBy: ( self scrollBarSetback @ self screenTopSetback extent: 0@0 ). "Number to be staggered at each corner (less on small screens)" maxLevel _ allowedArea area > 300000 ifTrue: [3] ifFalse: [2]. "Amount by which to stagger (less on small screens)" grid _ allowedArea area > 500000 ifTrue: [40] ifFalse: [20]. ^ (allowedArea extent - (grid*(maxLevel+1*2) + (grid//2))) min: StandardSize "600@400"]. width _ (strips _ self windowColumnsDesired) > 1 ifTrue: [effectiveExtent x // strips] ifFalse: [(3 * effectiveExtent x) // 4]. height _ (strips _ self windowRowsDesired) > 1 ifTrue: [effectiveExtent y // strips] ifFalse: [(3 * effectiveExtent y) //4]. ^ width @ height "RealEstateAgent standardWindowExtent"! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'BG 10/29/2003 09:54'! strictlyStaggeredInitialFrameFor: aStandardSystemView initialExtent: initialExtent world: aWorld "This method implements a staggered window placement policy that I (di) like. Basically it provides for up to 4 windows, staggered from each of the 4 corners. The windows are staggered so that there will always be a corner visible." | allowedArea grid initialFrame otherFrames cornerSel corner delta putativeCorner free maxLevel | allowedArea _(self maximumUsableAreaInWorld: aWorld) insetBy: (self scrollBarSetback @ self screenTopSetback extent: 0@0). "Number to be staggered at each corner (less on small screens)" maxLevel _ allowedArea area > 300000 ifTrue: [3] ifFalse: [2]. "Amount by which to stagger (less on small screens)" grid _ allowedArea area > 500000 ifTrue: [40] ifFalse: [20]. initialFrame _ 0@0 extent: ((initialExtent "min: (allowedArea extent - (grid*(maxLevel+1*2) + (grid//2)))) min: 600@400")). otherFrames _ Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers scheduledWindowControllers select: [:aController | aController view ~~ nil] thenCollect: [:aController | aController view isCollapsed ifTrue: [aController view expandedFrame] ifFalse: [aController view displayBox]]]. 0 to: maxLevel do: [:level | 1 to: 4 do: [:ci | cornerSel _ #(topLeft topRight bottomRight bottomLeft) at: ci. corner _ allowedArea perform: cornerSel. "The extra grid//2 in delta helps to keep title tabs distinct" delta _ (maxLevel-level*grid+(grid//2)) @ (level*grid). 1 to: ci-1 do: [:i | delta _ delta rotateBy: #right centerAt: 0@0]. "slow way" putativeCorner _ corner + delta. free _ true. otherFrames do: [:w | free _ free & ((w perform: cornerSel) ~= putativeCorner)]. free ifTrue: [^ (initialFrame align: (initialFrame perform: cornerSel) with: putativeCorner) squishedWithin: allowedArea]]]. "If all else fails..." ^ (self scrollBarSetback @ self screenTopSetback extent: initialFrame extent) squishedWithin: allowedArea! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 11/21/1999 22:54'! windowColumnsDesired "Answer how many separate vertical columns of windows are wanted. 5/22/96 sw" ^ Preferences reverseWindowStagger ifTrue: [1] ifFalse: [(self maximumUsableArea width > 640) ifTrue: [2] ifFalse: [1]]! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'RAA 11/21/1999 22:54'! windowRowsDesired "Answer how many separate horizontal rows of windows are wanted. 5/22/96 sw" ^ Preferences reverseWindowStagger ifTrue: [1] ifFalse: [(self maximumUsableArea height > 480) ifTrue: [2] ifFalse: [1]]! ! AbstractEvent subclass: #RecategorizedEvent instanceVariableNames: 'oldCategory' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !RecategorizedEvent methodsFor: 'testing' stamp: 'rw 7/1/2003 19:51'! isRecategorized ^true! ! !RecategorizedEvent methodsFor: 'printing' stamp: 'rw 7/2/2003 09:12'! printEventKindOn: aStream aStream nextPutAll: 'Recategorized'! ! !RecategorizedEvent methodsFor: 'accessing' stamp: 'rw 7/1/2003 20:08'! oldCategory: aCategoryName oldCategory := aCategoryName! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RecategorizedEvent class instanceVariableNames: ''! !RecategorizedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:09'! changeKind ^#Recategorized! ! !RecategorizedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 11:20'! supportedKinds ^Array with: self classKind with: self methodKind! ! !RecategorizedEvent class methodsFor: 'instance creation' stamp: 'rw 7/9/2003 14:21'! class: aClass category: cat oldCategory: oldName ^(self class: aClass category: cat) oldCategory: oldName! ! !RecategorizedEvent class methodsFor: 'instance creation' stamp: 'rw 7/31/2003 16:35'! method: aMethod protocol: prot class: aClass oldProtocol: oldName ^(self method: aMethod protocol: prot class: aClass) oldCategory: oldName! ! MessageSet subclass: #RecentMessageSet instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !RecentMessageSet commentStamp: 'sw 8/1/2002 17:40' prior: 0! RecentMessageSet is a message set that shows the most recently-submitted methods, in chronological order.! !RecentMessageSet methodsFor: 'contents' stamp: 'sw 10/19/1999 17:33'! contents: c notifying: n | result | result _ super contents: c notifying: n. result == true ifTrue: [self reformulateList]. ^ result! ! !RecentMessageSet methodsFor: 'update' stamp: 'sw 1/28/2001 20:59'! growable "Answer whether the receiver can be changed by manual additions & deletions" ^ false! ! !RecentMessageSet methodsFor: 'update' stamp: 'RAA 5/29/2001 10:19'! reformulateList | myList | "Reformulate the receiver's list. Exclude methods now deleted" myList _ Utilities recentMethodSubmissions reversed select: [ :each | each isValid]. self initializeMessageList: myList. self messageListIndex: (messageList size min: 1). "0 or 1" self changed: #messageList. self changed: #messageListIndex! ! !RecentMessageSet methodsFor: 'update' stamp: 'RAA 5/29/2001 10:42'! updateListsAndCodeIn: aWindow | recentFromUtilities | "RAA 20 june 2000 - a recent change to how messages were displayed in the list caused them not to match what was stored in Utilities. This caused the recent submissions to be continuously updated. The hack below fixed that problem" self flag: #mref. "in second pass, use simpler test" self canDiscardEdits ifFalse: [^ self]. recentFromUtilities _ Utilities mostRecentlySubmittedMessage,' '. (messageList first asStringOrText asString beginsWith: recentFromUtilities) ifFalse: [self reformulateList] ifTrue: [self updateCodePaneIfNeeded]! ! !RecentMessageSet methodsFor: 'selection'! maybeSetSelection "After a browser's message list is changed, this message is dispatched to the model, to give it a chance to refigure a selection" self messageListIndex: 1! ! !RecentMessageSet methodsFor: 'message list' stamp: 'sw 7/28/2002 23:20'! addExtraShiftedItemsTo: aMenu "The shifted selector-list menu is being built. Overridden here to defeat the presence of the items that add or change order, since RecentMessageSet defines methods & order explicitly based on external criteria" aMenu add: 'set size of recent history...' action: #setRecentHistorySize! ! !RecentMessageSet methodsFor: 'message list' stamp: 'sw 7/28/2002 23:50'! setRecentHistorySize "Let the user specify the recent history size" | aReply aNumber | aReply _ FillInTheBlank request: 'How many recent methods should be maintained?' initialAnswer: Utilities numberOfRecentSubmissionsToStore asString. aReply isEmptyOrNil ifFalse: [aNumber _ aReply asNumber rounded. (aNumber > 1 and: [aNumber <= 1000]) ifTrue: [Utilities numberOfRecentSubmissionsToStore: aNumber. self inform: 'Okay, ', aNumber asString, ' is the new size of the recent method history'] ifFalse: [self inform: 'Sorry, must be a number between 2 & 1000']] ! ! !RecentMessageSet methodsFor: 'message functions' stamp: 'BG 11/1/2003 13:27'! messageListMenu: aMenu shifted: shifted "Answer the message-list menu" shifted ifTrue: [^ self shiftedMessageListMenu: aMenu]. aMenu addList:#( ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' classHierarchy) ('browse method (O)' openSingleMessageBrowser) ('browse protocol (p)' browseFullProtocol) - ('fileOut (o)' fileOutMessage) ('printOut' printOutMessage) ('copy selector (c)' copySelector) - ('senders of... (n)' browseSendersOfMessages) ('implementors of... (m)' browseMessages) ('inheritance (i)' methodHierarchy) ('versions (v)' browseVersions) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' browseClassVarRefs) ('class variables' browseClassVariables) ('class refs (N)' browseClassRefs) - ('remove method (x)' removeMessage) ('remove from RecentSubmissions' removeFromRecentSubmissions) - ('more...' shiftedYellowButtonActivity)). ^ aMenu! ! !RecentMessageSet methodsFor: 'message functions' stamp: 'sw 9/26/2002 18:09'! removeFromRecentSubmissions "Remove the currently-selected method from the RecentSubmissions list" | aClass methodSym | ((aClass _ self selectedClassOrMetaClass) notNil and: [(methodSym _ self selectedMessageName) notNil]) ifTrue: [Utilities purgeFromRecentSubmissions: (MethodReference new setStandardClass: aClass methodSymbol: methodSym). self reformulateList]! ! Object subclass: #Rectangle instanceVariableNames: 'origin corner' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Rectangle commentStamp: '<historical>' prior: 0! 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.! !Rectangle methodsFor: 'accessing' stamp: 'acg 2/23/2000 00:52'! aboveCenter "Answer the point slightly above the center of the receiver." ^self topLeft + self bottomRight // (2@3)! ! !Rectangle methodsFor: 'accessing' stamp: 'di 11/17/2001 14:01'! area "Answer the receiver's area, the product of width and height." | w | (w _ self width) <= 0 ifTrue: [^ 0]. ^ w * self height max: 0! ! !Rectangle methodsFor: 'accessing'! bottom "Answer the position of the receiver's bottom horizontal line." ^corner y! ! !Rectangle methodsFor: 'accessing' stamp: 'ar 10/26/2000 22:17'! bottom: aNumber ^origin corner: corner x @ aNumber! ! !Rectangle methodsFor: 'accessing'! bottomCenter "Answer the point at the center of the bottom horizontal line of the receiver." ^self center x @ self bottom! ! !Rectangle methodsFor: 'accessing'! bottomLeft "Answer the point at the left edge of the bottom horizontal line of the receiver." ^origin x @ corner y! ! !Rectangle methodsFor: 'accessing'! bottomRight "Answer the point at the right edge of the bottom horizontal line of the receiver." ^corner! ! !Rectangle methodsFor: 'accessing'! boundingBox ^ self! ! !Rectangle methodsFor: 'accessing'! center "Answer the point at the center of the receiver." ^self topLeft + self bottomRight // 2! ! !Rectangle methodsFor: 'accessing'! corner "Answer the point at the bottom right corner of the receiver." ^corner! ! !Rectangle methodsFor: 'accessing'! corners "Return an array of corner points in the order of a quadrilateral spec for WarpBlt." ^ Array with: self topLeft with: self bottomLeft with: self bottomRight with: self topRight ! ! !Rectangle methodsFor: 'accessing'! extent "Answer with a rectangle with origin 0@0 and corner the receiver's width @ the receiver's height." ^corner - origin! ! !Rectangle methodsFor: 'accessing'! height "Answer the height of the receiver." ^corner y - origin y! ! !Rectangle methodsFor: 'accessing'! innerCorners "Return an array of inner corner points, ie, the most extreme pixels included, in the order of a quadrilateral spec for WarpBlt" | r1 | r1 _ self topLeft corner: self bottomRight - (1@1). ^ Array with: r1 topLeft with: r1 bottomLeft with: r1 bottomRight with: r1 topRight! ! !Rectangle methodsFor: 'accessing'! left "Answer the position of the receiver's left vertical line." ^origin x! ! !Rectangle methodsFor: 'accessing' stamp: 'ar 10/26/2000 22:16'! left: aNumber ^aNumber @ origin y corner: corner! ! !Rectangle methodsFor: 'accessing'! leftCenter "Answer the point at the center of the receiver's left vertical line." ^self left @ self center y! ! !Rectangle methodsFor: 'accessing'! origin "Answer the point at the top left corner of the receiver." ^origin! ! !Rectangle methodsFor: 'accessing'! right "Answer the position of the receiver's right vertical line." ^corner x! ! !Rectangle methodsFor: 'accessing' stamp: 'ar 10/26/2000 22:17'! right: aNumber ^origin corner: aNumber @ corner y! ! !Rectangle methodsFor: 'accessing'! rightCenter "Answer the point at the center of the receiver's right vertical line." ^self right @ self center y! ! !Rectangle methodsFor: 'accessing'! top "Answer the position of the receiver's top horizontal line." ^origin y! ! !Rectangle methodsFor: 'accessing' stamp: 'ar 10/26/2000 22:17'! top: aNumber ^origin x @ aNumber corner: corner! ! !Rectangle methodsFor: 'accessing'! topCenter "Answer the point at the center of the receiver's top horizontal line." ^self center x @ self top! ! !Rectangle methodsFor: 'accessing'! topLeft "Answer the point at the top left corner of the receiver's top horizontal line." ^origin ! ! !Rectangle methodsFor: 'accessing'! topRight "Answer the point at the top right corner of the receiver's top horizontal line." ^corner x @ origin y! ! !Rectangle methodsFor: 'accessing'! width "Answer the width of the receiver." ^corner x - origin x! ! !Rectangle methodsFor: 'comparing'! = aRectangle "Answer true if the receiver's species, origin and corner match aRectangle's." self species = aRectangle species ifTrue: [^origin = aRectangle origin and: [corner = aRectangle corner]] ifFalse: [^false]! ! !Rectangle methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^origin hash bitXor: corner hash! ! !Rectangle methodsFor: 'comparing'! hashMappedBy: map "My hash is independent of my oop." ^self hash! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 10/22/1998 16:11'! adjustTo: newRect along: side "Return a copy adjusted to fit a neighbor that has changed size." side = #left ifTrue: [^ self withRight: newRect left]. side = #right ifTrue: [^ self withLeft: newRect right]. side = #top ifTrue: [^ self withBottom: newRect top]. side = #bottom ifTrue: [^ self withTop: newRect bottom].! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ar 1/5/2002 18:04'! allAreasOutsideList: aCollection do: aBlock "Enumerate aBlock with all areas of the receiver not overlapping any rectangle in the given collection" ^self allAreasOutsideList: aCollection startingAt: 1 do: aBlock! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ar 1/5/2002 18:03'! allAreasOutsideList: aCollection startingAt: startIndex do: aBlock "Enumerate aBlock with all areas of the receiver not overlapping any rectangle in the given collection" | yOrigin yCorner aRectangle index rr | index _ startIndex. "Find the next intersecting rectangle from aCollection" [index <= aCollection size ifFalse:[^aBlock value: self]. aRectangle _ aCollection at: index. origin <= aRectangle corner and: [aRectangle origin <= corner]] whileFalse:[index _ index + 1]. "aRectangle is intersecting; process it" aRectangle origin y > origin y ifTrue: [rr _ origin corner: corner x @ (yOrigin _ aRectangle origin y). rr allAreasOutsideList: aCollection startingAt: index+1 do: aBlock] ifFalse: [yOrigin _ origin y]. aRectangle corner y < corner y ifTrue: [rr _ origin x @ (yCorner _ aRectangle corner y) corner: corner. rr allAreasOutsideList: aCollection startingAt: index+1 do: aBlock] ifFalse: [yCorner _ corner y]. aRectangle origin x > origin x ifTrue: [rr _ origin x @ yOrigin corner: aRectangle origin x @ yCorner. rr allAreasOutsideList: aCollection startingAt: index+1 do: aBlock]. aRectangle corner x < corner x ifTrue: [rr _ aRectangle corner x @ yOrigin corner: corner x @ yCorner. rr allAreasOutsideList: aCollection startingAt: index+1 do: aBlock].! ! !Rectangle methodsFor: 'rectangle functions'! amountToTranslateWithin: aRectangle "Answer a Point, delta, such that self + delta is forced within aRectangle." "Altered so as to prefer to keep self topLeft inside when all of self cannot be made to fit 7/27/96 di" | dx dy | dx _ 0. dy _ 0. self right > aRectangle right ifTrue: [dx _ aRectangle right - self right]. self bottom > aRectangle bottom ifTrue: [dy _ aRectangle bottom - self bottom]. (self left + dx) < aRectangle left ifTrue: [dx _ aRectangle left - self left]. (self top + dy) < aRectangle top ifTrue: [dy _ aRectangle top - self top]. ^ dx@dy! ! !Rectangle methodsFor: 'rectangle functions'! areasOutside: aRectangle "Answer an Array of Rectangles comprising the parts of the receiver not intersecting aRectangle." | areas yOrigin yCorner | "Make sure the intersection is non-empty" (origin <= aRectangle corner and: [aRectangle origin <= corner]) ifFalse: [^Array with: self]. areas _ OrderedCollection new. aRectangle origin y > origin y ifTrue: [areas addLast: (origin corner: corner x @ (yOrigin _ aRectangle origin y))] ifFalse: [yOrigin _ origin y]. aRectangle corner y < corner y ifTrue: [areas addLast: (origin x @ (yCorner _ aRectangle corner y) corner: corner)] ifFalse: [yCorner _ corner y]. aRectangle origin x > origin x ifTrue: [areas addLast: (origin x @ yOrigin corner: aRectangle origin x @ yCorner)]. aRectangle corner x < corner x ifTrue: [areas addLast: (aRectangle corner x @ yOrigin corner: corner x @ yCorner)]. ^areas! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 10/21/1998 16:00'! bordersOn: her along: herSide (herSide = #right and: [self left = her right]) | (herSide = #left and: [self right = her left]) ifTrue: [^ (self top max: her top) < (self bottom min: her bottom)]. (herSide = #bottom and: [self top = her bottom]) | (herSide = #top and: [self bottom = her top]) ifTrue: [^ (self left max: her left) < (self right min: her right)]. ^ false! ! !Rectangle methodsFor: 'rectangle functions'! encompass: aPoint "Answer a Rectangle that contains both the receiver and aPoint. 5/30/96 sw" ^ Rectangle origin: (origin min: aPoint) corner: (corner max: aPoint)! ! !Rectangle methodsFor: 'rectangle functions'! expandBy: delta "Answer a Rectangle that is outset from the receiver by delta. delta is a Rectangle, Point, or scalar." (delta isKindOf: Rectangle) ifTrue: [^Rectangle origin: origin - delta origin corner: corner + delta corner] ifFalse: [^Rectangle origin: origin - delta corner: corner + delta]! ! !Rectangle methodsFor: 'rectangle functions'! extendBy: delta "Answer a Rectangle with the same origin as the receiver, but whose corner is offset by delta. delta is a Rectangle, Point, or scalar." (delta isKindOf: Rectangle) ifTrue: [^Rectangle origin: origin corner: corner + delta corner] ifFalse: [^Rectangle origin: origin corner: corner + delta]! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 10/21/1998 16:11'! forPoint: aPoint closestSideDistLen: sideDistLenBlock "Evaluate the block with my side (symbol) closest to aPoint, the approx distance of aPoint from that side, and the length of the side (or 0 if aPoint is beyond the side)" | side | side _ self sideNearestTo: aPoint. side == #right ifTrue: [^ sideDistLenBlock value: side value: (self right - aPoint x) abs value: ((aPoint y between: self top and: self bottom) ifTrue: [self height] ifFalse: [0])]. side == #left ifTrue: [^ sideDistLenBlock value: side value: (self left - aPoint x) abs value: ((aPoint y between: self top and: self bottom) ifTrue: [self height] ifFalse: [0])]. side == #bottom ifTrue: [^ sideDistLenBlock value: side value: (self bottom - aPoint y) abs value: ((aPoint x between: self left and: self right) ifTrue: [self width] ifFalse: [0])]. side == #top ifTrue: [^ sideDistLenBlock value: side value: (self top - aPoint y) abs value: ((aPoint x between: self left and: self right) ifTrue: [self width] ifFalse: [0])].! ! !Rectangle methodsFor: 'rectangle functions'! insetBy: delta "Answer a Rectangle that is inset from the receiver by delta. delta is a Rectangle, Point, or scalar." (delta isKindOf: Rectangle) ifTrue: [^Rectangle origin: origin + delta origin corner: corner - delta corner] ifFalse: [^Rectangle origin: origin + delta corner: corner - delta]! ! !Rectangle methodsFor: 'rectangle functions'! insetOriginBy: originDeltaPoint cornerBy: cornerDeltaPoint "Answer a Rectangle that is inset from the receiver by a given amount in the origin and corner." ^Rectangle origin: origin + originDeltaPoint corner: corner - cornerDeltaPoint! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ar 11/12/2000 19:10'! intersect: aRectangle "Answer a Rectangle that is the area in which the receiver overlaps with aRectangle. Optimized for speed; old code read: ^Rectangle origin: (origin max: aRectangle origin) corner: (corner min: aRectangle corner) " | aPoint left right top bottom | aPoint _ aRectangle origin. aPoint x > origin x ifTrue:[left _ aPoint x] ifFalse:[left _ origin x]. aPoint y > origin y ifTrue:[top _ aPoint y] ifFalse:[top _ origin y]. aPoint _ aRectangle corner. aPoint x < corner x ifTrue:[right _ aPoint x] ifFalse:[right _ corner x]. aPoint y < corner y ifTrue:[bottom _ aPoint y] ifFalse:[bottom _ corner y]. ^Rectangle origin: (left@top) corner: (right@bottom) ! ! !Rectangle methodsFor: 'rectangle functions'! merge: aRectangle "Answer a Rectangle that contains both the receiver and aRectangle." ^Rectangle origin: (origin min: aRectangle origin) corner: (corner max: aRectangle corner)! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ar 10/29/2000 02:41'! outsetBy: delta "Answer a Rectangle that is outset from the receiver by delta. delta is a Rectangle, Point, or scalar." (delta isKindOf: Rectangle) ifTrue: [^Rectangle origin: origin - delta origin corner: corner + delta corner] ifFalse: [^Rectangle origin: origin - delta corner: corner + delta]! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 4/30/1998 11:22'! pointNearestTo: aPoint "Return the point on my border closest to aPoint" | side | (self containsPoint: aPoint) ifTrue: [side _ self sideNearestTo: aPoint. side == #right ifTrue: [^ self right @ aPoint y]. side == #left ifTrue: [^ self left @ aPoint y]. side == #bottom ifTrue: [^ aPoint x @ self bottom]. side == #top ifTrue: [^ aPoint x @ self top]] ifFalse: [^ aPoint adhereTo: self]! ! !Rectangle methodsFor: 'rectangle functions'! quickMerge: aRectangle "Answer the receiver if it encloses the given rectangle or the merge of the two rectangles if it doesn't. THis method is an optimization to reduce extra rectangle creations." | useRcvr rOrigin rCorner minX maxX minY maxY | useRcvr _ true. rOrigin _ aRectangle topLeft. rCorner _ aRectangle bottomRight. minX _ rOrigin x < origin x ifTrue: [useRcvr _ false. rOrigin x] ifFalse: [origin x]. maxX _ rCorner x > corner x ifTrue: [useRcvr _ false. rCorner x] ifFalse: [corner x]. minY _ rOrigin y < origin y ifTrue: [useRcvr _ false. rOrigin y] ifFalse: [origin y]. maxY _ rCorner y > corner y ifTrue: [useRcvr _ false. rCorner y] ifFalse: [corner y]. useRcvr ifTrue: [^ self] ifFalse: [^ Rectangle origin: minX@minY corner: maxX@maxY]. ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 10/20/97 23:01'! rectanglesAt: y height: ht (y+ht) > self bottom ifTrue: [^ Array new]. ^ Array with: (origin x @ y corner: corner x @ (y+ht))! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 10/21/1998 15:09'! sideNearestTo: aPoint | distToLeft distToRight distToTop distToBottom closest side | distToLeft _ aPoint x - self left. distToRight _ self right - aPoint x. distToTop _ aPoint y - self top. distToBottom _ self bottom - aPoint y. closest _ distToLeft. side _ #left. distToRight < closest ifTrue: [closest _ distToRight. side _ #right]. distToTop < closest ifTrue: [closest _ distToTop. side _ #top]. distToBottom < closest ifTrue: [closest _ distToBottom. side _ #bottom]. ^ side " | r | r _ Rectangle fromUser. Display border: r width: 1. [Sensor anyButtonPressed] whileFalse: [(r sideNearestTo: Sensor cursorPoint) , ' ' displayAt: 0@0] "! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 11:39'! subDivideBy: aPoint "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom). columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 12:24'! subDivideRoundedBy: aPoint "ssa - round the orign and extent points" "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom) rounded. columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'rectangle functions'! translatedToBeWithin: aRectangle "Answer a copy of the receiver that does not extend beyond aRectangle. 7/8/96 sw" ^ self translateBy: (self amountToTranslateWithin: aRectangle)! ! !Rectangle methodsFor: 'rectangle functions'! withBottom: y "Return a copy of me with a different bottom y" ^ origin x @ origin y corner: corner x @ y! ! !Rectangle methodsFor: 'rectangle functions'! withHeight: height "Return a copy of me with a different height" ^ origin corner: corner x @ (origin y + height)! ! !Rectangle methodsFor: 'rectangle functions'! withLeft: x "Return a copy of me with a different left x" ^ x @ origin y corner: corner x @ corner y! ! !Rectangle methodsFor: 'rectangle functions'! withRight: x "Return a copy of me with a different right x" ^ origin x @ origin y corner: x @ corner y! ! !Rectangle methodsFor: 'rectangle functions'! withSide: side setTo: value "return a copy with side set to value" ^ self perform: (#(withLeft: withRight: withTop: withBottom: ) at: (#(left right top bottom) indexOf: side)) with: value! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'di 9/8/1999 21:25'! withSideOrCorner: side setToPoint: newPoint "Return a copy with side set to newPoint" ^ self withSideOrCorner: side setToPoint: newPoint minExtent: 0@0! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'bf 9/10/1999 16:16'! withSideOrCorner: side setToPoint: newPoint minExtent: minExtent "Return a copy with side set to newPoint" ^self withSideOrCorner: side setToPoint: newPoint minExtent: minExtent limit: ((#(left top) includes: side) ifTrue: [SmallInteger minVal] ifFalse: [SmallInteger maxVal])! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'bf 9/10/1999 16:07'! withSideOrCorner: side setToPoint: newPoint minExtent: minExtent limit: limit "Return a copy with side set to newPoint" side = #top ifTrue: [^ self withTop: (newPoint y min: corner y - minExtent y max: limit + minExtent y)]. side = #bottom ifTrue: [^ self withBottom: (newPoint y min: limit - minExtent y max: origin y + minExtent y)]. side = #left ifTrue: [^ self withLeft: (newPoint x min: corner x - minExtent x max: limit + minExtent x)]. side = #right ifTrue: [^ self withRight: (newPoint x min: limit - minExtent x max: origin x + minExtent x)]. side = #topLeft ifTrue: [^ (newPoint min: corner - minExtent) corner: self bottomRight]. side = #bottomRight ifTrue: [^ self topLeft corner: (newPoint max: origin + minExtent)]. side = #bottomLeft ifTrue: [^ self topRight rect: ((newPoint x min: corner x - minExtent x) @ (newPoint y max: origin y + minExtent y))]. side = #topRight ifTrue: [^ self bottomLeft rect: ((newPoint x max: origin x + minExtent x) @ (newPoint y min: corner y - minExtent y))].! ! !Rectangle methodsFor: 'rectangle functions'! withTop: y "Return a copy of me with a different top y" ^ origin x @ y corner: corner x @ corner y! ! !Rectangle methodsFor: 'rectangle functions'! withWidth: width "Return a copy of me with a different width" ^ origin corner: (origin x + width) @ corner y! ! !Rectangle methodsFor: 'testing'! containsPoint: aPoint "Answer whether aPoint is within the receiver." ^origin <= aPoint and: [aPoint < corner]! ! !Rectangle methodsFor: 'testing'! containsRect: aRect "Answer whether aRect is within the receiver (OK to coincide)." ^ aRect origin >= origin and: [aRect corner <= corner] ! ! !Rectangle methodsFor: 'testing'! hasPositiveExtent ^ (corner x > origin x) and: [corner y > origin y]! ! !Rectangle methodsFor: 'testing' stamp: 'ar 9/10/2000 15:29'! intersects: aRectangle "Answer whether aRectangle intersects the receiver anywhere." "Optimized; old code answered: (origin max: aRectangle origin) < (corner min: aRectangle corner)" | rOrigin rCorner | rOrigin _ aRectangle origin. rCorner _ aRectangle corner. rCorner x <= origin x ifTrue: [^ false]. rCorner y <= origin y ifTrue: [^ false]. rOrigin x >= corner x ifTrue: [^ false]. rOrigin y >= corner y ifTrue: [^ false]. ^ true ! ! !Rectangle methodsFor: 'testing'! isTall ^ self height > self width! ! !Rectangle methodsFor: 'testing'! isWide ^ self width > self height! ! !Rectangle methodsFor: 'testing' stamp: 'ar 10/29/2000 19:03'! isZero ^origin isZero and:[corner isZero]! ! !Rectangle methodsFor: 'truncation and round off'! rounded "Answer a Rectangle whose origin and corner are rounded." ^Rectangle origin: origin rounded corner: corner rounded! ! !Rectangle methodsFor: 'truncation and round off'! truncateTo: grid "Answer a Rectangle whose origin and corner are truncated to grid x and grid y." ^Rectangle origin: (origin truncateTo: grid) corner: (corner truncateTo: grid)! ! !Rectangle methodsFor: 'truncation and round off' stamp: 'jm 5/29/1998 15:53'! truncated "Answer a Rectangle whose origin and corner have any fractional parts removed. Answer the receiver if its coordinates are already integral." (origin x isInteger and: [origin y isInteger and: [corner x isInteger and: [corner y isInteger]]]) ifTrue: [^ self]. ^ Rectangle origin: origin truncated corner: corner truncated ! ! !Rectangle methodsFor: 'transforming'! align: aPoint1 with: aPoint2 "Answer a Rectangle that is a translated by aPoint2 - aPoint1." ^self translateBy: aPoint2 - aPoint1! ! !Rectangle methodsFor: 'transforming'! centeredBeneath: aRectangle "Move the reciever so that its top center point coincides with the bottom center point of aRectangle. 5/20/96 sw:" ^ self align: self topCenter with: aRectangle bottomCenter! ! !Rectangle methodsFor: 'transforming' stamp: 'di 6/11/97 16:24'! flipBy: direction centerAt: aPoint "Return a copy flipped #vertical or #horizontal, about aPoint." ^ (origin flipBy: direction centerAt: aPoint) rect: (corner flipBy: direction centerAt: aPoint)! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 9/3/2008 11:12'! newRectButtonPressedDo: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous. Only tracks while mouse is down." | rect newRect buttonNow delay | delay _ Delay forMilliseconds: 10. buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow] whileTrue: [delay wait. buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Smalltalk isMorphic ifTrue: []. Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 9/3/2008 11:12'! newRectFrom: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous" | rect newRect buttonStart buttonNow delay | delay _ Delay forMilliseconds: 10. buttonStart _ buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow == buttonStart] whileTrue: [delay wait. buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'di 6/11/97 15:11'! rotateBy: direction centerAt: aPoint "Return a copy rotated #right, #left, or #pi about aPoint" ^ (origin rotateBy: direction centerAt: aPoint) rect: (corner rotateBy: direction centerAt: aPoint)! ! !Rectangle methodsFor: 'transforming'! scaleBy: scale "Answer a Rectangle scaled by scale, a Point or a scalar." ^Rectangle origin: origin * scale corner: corner * scale! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/27/2008 04:43'! scaleByRect: scale "Answer a Rectangle scaled by scale, a rectangle." ^Rectangle origin: origin * scale origin corner: corner * scale corner! ! !Rectangle methodsFor: 'transforming'! scaleFrom: rect1 to: rect2 "Produce a rectangle stretched according to the stretch from rect1 to rect2" ^ (origin scaleFrom: rect1 to: rect2) corner: (corner scaleFrom: rect1 to: rect2)! ! !Rectangle methodsFor: 'transforming' stamp: 'sw 5/21/96'! squishedWithin: aRectangle "Return an adjustment of the receiver that fits within aRectangle by reducing its size, not by changing its origin. " ^ origin corner: (corner min: aRectangle bottomRight) "(50 @ 50 corner: 160 @ 100) squishedWithin: (20 @ 10 corner: 90 @ 85)" ! ! !Rectangle methodsFor: 'transforming'! translateBy: factor "Answer a Rectangle translated by factor, a Point or a scalar." ^Rectangle origin: origin + factor corner: corner + factor! ! !Rectangle methodsFor: 'transforming' stamp: 'nk 7/5/2003 08:31'! translatedAndSquishedToBeWithin: aRectangle "Return an adjustment of the receiver that fits within aRectangle by - translating it to be within aRectangle if necessary, then - reducing its size, if necessary" ^ (self translatedToBeWithin: aRectangle) squishedWithin: aRectangle! ! !Rectangle methodsFor: 'printing'! printOn: aStream "Refer to the comment in Object|printOn:." origin printOn: aStream. aStream nextPutAll: ' corner: '. corner printOn: aStream! ! !Rectangle methodsFor: 'printing' stamp: 'MPW 1/4/1901 08:18'! propertyListOn: aStream " {x=a; y=b; width=c; height=d} " aStream print:'{ x='; write:origin x; print:' y='; write:origin y; print:' width='; write:self extent x; print:' height='; write:self extent y; print:'};'. ! ! !Rectangle methodsFor: 'printing'! storeOn: aStream "printed form is good for storing too" self printOn: aStream! ! !Rectangle methodsFor: 'private'! setOrigin: topLeft corner: bottomRight origin _ topLeft. corner _ bottomRight! ! !Rectangle methodsFor: 'FMP' stamp: 'RAA 6/1/1999 17:41'! deltaToEnsureInOrCentered: r extra: aNumber | dX dY halfXDiff halfYDiff | dX _ dY _ 0. halfXDiff _ (r width - self width * aNumber) truncated. halfYDiff _ (r height - self height * aNumber) truncated. self left < r left ifTrue: [dX _ self left - r left - halfXDiff] ifFalse: [self right > r right ifTrue: [dX _ self right - r right + halfXDiff]]. self top < r top ifTrue: [dY _ self top - r top - halfYDiff] ifFalse: [self bottom > r bottom ifTrue: [dY _ self bottom - r bottom + halfYDiff]]. ^dX @ dY ! ! !Rectangle methodsFor: '*nebraska-Morphic-Remote' stamp: 'RAA 7/31/2000 16:39'! encodeForRemoteCanvasB | encoded | encoded := Bitmap new: 4. encoded at: 1 put: origin x asInteger. encoded at: 2 put: origin y asInteger. encoded at: 3 put: corner x asInteger. encoded at: 4 put: corner y asInteger. ^encoded! ! !Rectangle methodsFor: '*morphic-Postscript Canvases' stamp: 'mpw 8/9/1930 08:00'! encodePostscriptOn:aStream aStream write:self origin; print:' '; write:self extent; print:' '.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Rectangle class instanceVariableNames: ''! !Rectangle class methodsFor: 'instance creation' stamp: 'tk 3/9/97'! center: centerPoint extent: extentPoint "Answer an instance of me whose center is centerPoint and width by height is extentPoint. " ^self origin: centerPoint - (extentPoint//2) extent: extentPoint! ! !Rectangle class methodsFor: 'instance creation' stamp: 'di 12/1/97 10:42'! encompassing: listOfPoints "A number of callers of encompass: should use this method." | topLeft bottomRight | topLeft _ bottomRight _ nil. listOfPoints do: [:p | topLeft == nil ifTrue: [topLeft _ bottomRight _ p] ifFalse: [topLeft _ topLeft min: p. bottomRight _ bottomRight max: p]]. ^ topLeft corner: bottomRight! ! !Rectangle class methodsFor: 'instance creation'! fromUser "Answer an instance of me that is determined by having the user designate the top left and bottom right corners. The gridding for user selection is 1@1." ^self fromUser: 1 @ 1! ! !Rectangle class methodsFor: 'instance creation'! fromUser: gridPoint "Answer a Rectangle that is determined by having the user designate the top left and bottom right corners. The cursor reamins linked with the sensor, but the outline is kept gridded." | originRect | originRect _ Cursor origin showWhile: [((Sensor cursorPoint grid: gridPoint) extent: 0@0) newRectFrom: [:f | (Sensor cursorPoint grid: gridPoint) extent: 0@0]]. ^ Cursor corner showWhile: [originRect newRectFrom: [:f | f origin corner: (Sensor cursorPoint grid: gridPoint)]]! ! !Rectangle class methodsFor: 'instance creation'! left: leftNumber right: rightNumber top: topNumber bottom: bottomNumber "Answer an instance of me whose left, right, top, and bottom coordinates are determined by the arguments." ^ self new setOrigin: leftNumber @ topNumber corner: rightNumber @ bottomNumber! ! !Rectangle class methodsFor: 'instance creation' stamp: 'btr 2/14/2003 16:29'! merging: listOfRects "A number of callers of merge: should use this method." | minX minY maxX maxY | listOfRects do: [:r | minX ifNil: [minX _ r topLeft x. minY _ r topLeft y. maxX _ r bottomRight x. maxY _ r bottomRight y] ifNotNil: [minX _ minX min: r topLeft x. minY _ minY min: r topLeft y. maxX _ maxX max: r bottomRight x. maxY _ maxY max: r bottomRight y]]. ^ minX@minY corner: maxX@maxY! ! !Rectangle class methodsFor: 'instance creation'! origin: originPoint corner: cornerPoint "Answer an instance of me whose corners (top left and bottom right) are determined by the arguments." ^self new setOrigin: originPoint corner: cornerPoint! ! !Rectangle class methodsFor: 'instance creation'! origin: originPoint extent: extentPoint "Answer an instance of me whose top left corner is originPoint and width by height is extentPoint." ^self new setOrigin: originPoint corner: originPoint + extentPoint! ! !Rectangle class methodsFor: 'instance creation'! originFromUser: extentPoint "Answer an instance of me that is determined by having the user designate the top left corner. The width and height are determined by extentPoint. The gridding for user selection is 1@1." ^self originFromUser: extentPoint grid: 1 @ 1! ! !Rectangle class methodsFor: 'instance creation'! originFromUser: extentPoint grid: gridPoint "Answer an instance of me that is determined by having the user designate the top left corner. The width and height are determined by extentPoint. The gridding for user selection is scaleFactor. Assumes that the sender has determined an extent that is a proper multiple of scaleFactor." ^ Cursor origin showWhile: [((Sensor cursorPoint grid: gridPoint) extent: extentPoint) newRectFrom: [:f | (Sensor cursorPoint grid: gridPoint) extent: extentPoint]]. ! ! Object subclass: #RemoteString instanceVariableNames: 'sourceFileNumber filePositionHi' classVariableNames: 'CurrentTextAttStructure CurrentTextAttVersion TextAttributeStructureVersions' poolDictionaries: '' category: 'System-Files'! !RemoteString commentStamp: '<historical>' prior: 0! My instances provide an external file reference to a piece of text. It may be the sourceCode of a method, or the class comments of a class. The changes file or file-in file usually has a chunk that is just the source string of a method: max: aNumber ^ self > aNumber ifTrue: [self] ifFalse: [aNumber]!! I can return either a String or a Text. Some a chunk is followed by a second chunk (beginning with ]style[) containing style information. The encoding is like this: max: aNumber ^ self > aNumber ifTrue: [self] ifFalse: [aNumber]!! ]style[(14 50 312)f1,f1b,f1LInteger +;i!! Allowed TextAttributes are TextFontChange, TextEmphasis, TextColor, TextDoIt, TextKern, TextLink, TextURL. TextFontReference and TextAnchor are not supported. See PositionableStream nextChunkText and RunArray class scanFrom:.! ]style[(748 32 5 24 1)f1,f1LPositionableStream nextChunkText;,f1,f1LRunArray class scanFrom:;,f1! !RemoteString methodsFor: 'accessing' stamp: 'ajh 1/18/2002 01:04'! fileStream "Answer the file stream with position set at the beginning of my string" | theFile | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile _ SourceFiles at: sourceFileNumber. theFile position: filePositionHi. ^ theFile! ! !RemoteString methodsFor: 'accessing' stamp: 'nk 11/26/2002 12:05'! last ^self string ifNotNilDo: [ :s | s last ]! ! !RemoteString methodsFor: 'accessing'! position "Answer the location of the string on a file." ^ filePositionHi! ! !RemoteString methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:28'! setSourcePointer: aSourcePointer sourceFileNumber _ SourceFiles fileIndexFromSourcePointer: aSourcePointer. filePositionHi _ SourceFiles filePositionFromSourcePointer: aSourcePointer! ! !RemoteString methodsFor: 'accessing'! sourceFileNumber "Answer the index of the file on which the string is stored." ^sourceFileNumber! ! !RemoteString methodsFor: 'accessing' stamp: 'hmm 4/26/2000 20:47'! sourcePointer sourceFileNumber ifNil: [^ 0]. ^SourceFiles sourcePointerFromFileIndex: sourceFileNumber andPosition: filePositionHi! ! !RemoteString methodsFor: 'accessing' stamp: 'di 1/13/98 16:57'! string "Answer the receiver's string if remote files are enabled." | theFile | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^'']. theFile _ SourceFiles at: sourceFileNumber. theFile position: filePositionHi. ^ theFile nextChunk! ! !RemoteString methodsFor: 'accessing' stamp: 'tk 1/21/95 17:55'! text "Answer the receiver's string asText if remote files are enabled." | theFile | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile _ SourceFiles at: sourceFileNumber. theFile position: filePositionHi. ^ theFile nextChunkText! ! !RemoteString methodsFor: 'private'! fileNumber: fileNumber position: position sourceFileNumber _ fileNumber. filePositionHi _ position! ! !RemoteString methodsFor: 'private'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile _ SourceFiles at: fileNumber. theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile]! ! !RemoteString methodsFor: 'private' stamp: 'tk 12/12/97 10:41'! string: aStringOrText onFileNumber: fileNumber toFile: aFileStream "Store this as the receiver's text if source files exist. If aStringOrText is a Text, store a marker with the string part, and then store the runs of TextAttributes in the next chunk." | position | position _ aFileStream position. self fileNumber: fileNumber position: position. aFileStream nextChunkPutWithStyle: aStringOrText "^ self (important)"! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RemoteString class instanceVariableNames: ''! !RemoteString class methodsFor: 'as yet unclassified' stamp: 'tk 12/11/97 10:35'! initialize "Derive the current TextAttributes classes object structure" self new makeNewTextAttVersion! ! !RemoteString class methodsFor: 'as yet unclassified'! newFileNumber: sourceIndex position: anInteger "Answer an instance of me fora file indexed by sourceIndex, at the position anInteger. Assume that the string is already stored on the file and the instance will be used to access it." ^self new fileNumber: sourceIndex position: anInteger! ! !RemoteString class methodsFor: 'as yet unclassified'! newString: aString onFileNumber: sourceIndex "Answer an instance of me for string, aString, on file indexed by sourceIndex. Put the string on the file and create the remote reference." ^self new string: aString onFileNumber: sourceIndex! ! !RemoteString class methodsFor: 'as yet unclassified'! newString: aString onFileNumber: sourceIndex toFile: aFileStream "Answer an instance of me for string, aString, on file indexed by sourceIndex. Put the string on the file, aFileStream, and create the remote reference. Assume that the index corresponds properly to aFileStream." ^self new string: aString onFileNumber: sourceIndex toFile: aFileStream! ! AbstractEvent subclass: #RemovedEvent instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !RemovedEvent methodsFor: 'testing' stamp: 'rw 6/30/2003 08:35'! isRemoved ^true! ! !RemovedEvent methodsFor: 'printing' stamp: 'rw 6/30/2003 09:31'! printEventKindOn: aStream aStream nextPutAll: 'Removed'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RemovedEvent class instanceVariableNames: ''! !RemovedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:09'! changeKind ^#Removed! ! !RemovedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:28'! supportedKinds "All the kinds of items that this event can take." ^ Array with: self classKind with: self methodKind with: self categoryKind with: self protocolKind! ! AbstractEvent subclass: #RenamedEvent instanceVariableNames: 'newName oldName' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !RenamedEvent methodsFor: 'printing' stamp: 'rw 7/1/2003 11:34'! printEventKindOn: aStream aStream nextPutAll: 'Renamed'! ! !RenamedEvent methodsFor: 'testing' stamp: 'rw 7/1/2003 11:34'! isRenamed ^true! ! !RenamedEvent methodsFor: 'accessing' stamp: 'NS 1/27/2004 12:18'! newName ^ newName! ! !RenamedEvent methodsFor: 'accessing' stamp: 'NS 1/27/2004 12:18'! newName: aName newName := aName! ! !RenamedEvent methodsFor: 'accessing' stamp: 'rw 7/1/2003 12:01'! oldName: aName oldName := aName! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RenamedEvent class instanceVariableNames: ''! !RenamedEvent class methodsFor: 'accessing' stamp: 'rw 7/10/2003 12:09'! changeKind ^#Renamed! ! !RenamedEvent class methodsFor: 'accessing' stamp: 'NS 1/20/2004 12:30'! supportedKinds "All the kinds of items that this event can take." ^ Array with: self classKind with: self categoryKind with: self protocolKind! ! !RenamedEvent class methodsFor: 'instance creation' stamp: 'NS 1/27/2004 12:19'! class: aClass category: cat oldName: oldName newName: newName ^(self class: aClass category: cat) oldName: oldName; newName: newName! ! AbstractEvent subclass: #ReorganizedEvent instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !ReorganizedEvent methodsFor: 'testing' stamp: 'NS 1/27/2004 12:44'! isReorganized ^ true! ! !ReorganizedEvent methodsFor: 'printing' stamp: 'NS 1/27/2004 12:44'! printEventKindOn: aStream aStream nextPutAll: 'Reorganized'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ReorganizedEvent class instanceVariableNames: ''! !ReorganizedEvent class methodsFor: 'accessing' stamp: 'NS 1/27/2004 12:46'! changeKind ^#Reorganized! ! !ReorganizedEvent class methodsFor: 'accessing' stamp: 'NS 1/27/2004 12:46'! supportedKinds ^Array with: self classKind! ! Notification subclass: #RequestAlternateSyntaxSetting instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !RequestAlternateSyntaxSetting commentStamp: '<historical>' prior: 0! I provide a way to override the current setting of the alternate syntax preference. I am used when filing in code to insure that the Smalltalk-80 preference is used regardless of what the user likes to see in her browsers.! !RequestAlternateSyntaxSetting methodsFor: 'as yet unclassified' stamp: 'RAA 6/14/2000 13:41'! defaultAction self resume: Preferences printAlternateSyntax! ! ParseNode subclass: #ReturnNode instanceVariableNames: 'expr' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !ReturnNode commentStamp: '<historical>' prior: 0! I represent an expression of the form ^expr.! !ReturnNode methodsFor: 'initialize-release'! expr: e expr _ e! ! !ReturnNode methodsFor: 'initialize-release'! expr: e encoder: encoder sourceRange: range expr _ e. encoder noteSourceRange: range forNode: self! ! !ReturnNode methodsFor: 'converting'! asReturnNode! ! !ReturnNode methodsFor: 'testing'! isReturnSelf ^expr == NodeSelf! ! !ReturnNode methodsFor: 'testing'! isSpecialConstant ^expr isSpecialConstant! ! !ReturnNode methodsFor: 'testing'! isVariableReference ^expr isVariableReference! ! !ReturnNode methodsFor: 'code generation'! code ^expr code! ! !ReturnNode methodsFor: 'code generation'! emitForReturn: stack on: strm expr emitForReturn: stack on: strm. pc _ strm position! ! !ReturnNode methodsFor: 'code generation'! emitForValue: stack on: strm expr emitForReturn: stack on: strm. pc _ strm position! ! !ReturnNode methodsFor: 'code generation'! pc "Used by encoder source mapping." ^pc! ! !ReturnNode methodsFor: 'code generation'! sizeForReturn: encoder ^expr sizeForReturn: encoder! ! !ReturnNode methodsFor: 'code generation'! sizeForValue: encoder ^expr sizeForReturn: encoder! ! !ReturnNode methodsFor: 'printing' stamp: 'di 6/11/2000 15:28'! printOn: aStream indent: level aStream dialect = #SQ00 ifTrue: ["Add prefix keyword" aStream withStyleFor: #setOrReturn do: [aStream nextPutAll: 'Answer ']. expr printOn: aStream indent: level] ifFalse: [aStream nextPutAll: '^ '. expr printOn: aStream indent: level]. expr printCommentOn: aStream indent: level. ! ! ArrayedCollection subclass: #RunArray instanceVariableNames: 'runs values lastIndex lastRun lastOffset' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !RunArray commentStamp: '<historical>' prior: 0! 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" length that denotes the number of consecutive occurrences of the value. My two important variables are runs An array of how many elements are in each run values An array of what the value is over those elements The variables lastIndex, lastRun and lastOffset cache the last access so that streaming through RunArrays is not an N-squared process. Many complexities of access can be bypassed by using the method RunArray withStartStopAndValueDo:! ]style[(615 33)f1,f1LRunArray withStartStopAndValueDo:;! !RunArray methodsFor: 'accessing' stamp: 'di 1/15/1999 00:04'! = otherArray "Test if all my elements are equal to those of otherArray" (otherArray isMemberOf: RunArray) ifFalse: [^ self hasEqualElements: otherArray]. "Faster test between two RunArrays" ^ (runs hasEqualElements: otherArray runs) and: [values hasEqualElements: otherArray values]! ! !RunArray methodsFor: 'accessing'! at: index self at: index setRunOffsetAndValue: [:run :offset :value | ^value]! ! !RunArray methodsFor: 'accessing' stamp: 'ar 10/16/2001 18:56'! first ^values at: 1! ! !RunArray methodsFor: 'accessing' stamp: 'ar 10/16/2001 18:56'! last ^values at: values size! ! !RunArray methodsFor: 'accessing'! runLengthAt: index "Answer the length remaining in run beginning at index." self at: index setRunOffsetAndValue: [:run :offset :value | ^(runs at: run) - offset]! ! !RunArray methodsFor: 'accessing'! size | size | size _ 0. 1 to: runs size do: [:i | size _ size + (runs at: i)]. ^size! ! !RunArray methodsFor: 'accessing' stamp: 'di 11/10/97 13:34'! withStartStopAndValueDo: aBlock | start stop | start _ 1. runs with: values do: [:len : val | stop _ start + len - 1. aBlock value: start value: stop value: val. start _ stop + 1] ! ! !RunArray methodsFor: 'adding' stamp: 'ar 10/16/2001 18:47'! addFirst: value "Add value as the first element of the receiver." lastIndex _ nil. "flush access cache" (runs size=0 or: [values first ~= value]) ifTrue: [runs _ {1}, runs. values _ {value}, values] ifFalse: [runs at: 1 put: runs first+1]! ! !RunArray methodsFor: 'adding' stamp: 'ar 10/16/2001 20:25'! addLast: value "Add value as the last element of the receiver." lastIndex _ nil. "flush access cache" (runs size=0 or: [values last ~= value]) ifTrue: [runs _ runs copyWith: 1. values _ values copyWith: value] ifFalse: [runs at: runs size put: runs last+1]! ! !RunArray methodsFor: 'adding' stamp: 'ar 10/16/2001 18:47'! addLast: value times: times "Add value as the last element of the receiver, the given number of times" times = 0 ifTrue: [ ^self ]. lastIndex _ nil. "flush access cache" (runs size=0 or: [values last ~= value]) ifTrue: [runs _ runs copyWith: times. values _ values copyWith: value] ifFalse: [runs at: runs size put: runs last+times]! ! !RunArray methodsFor: 'adding' stamp: 'tk 1/28/98 09:28'! coalesce "Try to combine adjacent runs" | ind | ind _ 2. [ind > values size] whileFalse: [ (values at: ind-1) = (values at: ind) ifFalse: [ind _ ind + 1] ifTrue: ["two are the same, combine them" values _ values copyReplaceFrom: ind to: ind with: #(). runs at: ind-1 put: (runs at: ind-1) + (runs at: ind). runs _ runs copyReplaceFrom: ind to: ind with: #(). "self error: 'needed to combine runs' "]]. ! ! !RunArray methodsFor: 'adding' stamp: 'BG 6/12/2003 11:07'! rangeOf: attr startingAt: startPos "Answer an interval that gives the range of attr at index position startPos. An empty interval with start value startPos is returned when the attribute attr is not present at position startPos. self size > 0 is assumed, it is the responsibility of the caller to test for emptiness of self. Note that an attribute may span several adjancent runs. " self at: startPos setRunOffsetAndValue: [:run :offset :value | ^(value includes: attr) ifFalse: [startPos to: startPos - 1] ifTrue: [ | firstRelevantPosition lastRelevantPosition idxOfCandidateRun | lastRelevantPosition := startPos - offset + (runs at: run) - 1. firstRelevantPosition := startPos - offset. idxOfCandidateRun := run + 1. [idxOfCandidateRun <= runs size and: [(values at: idxOfCandidateRun) includes: attr]] whileTrue: [lastRelevantPosition := lastRelevantPosition + (runs at: idxOfCandidateRun). idxOfCandidateRun := idxOfCandidateRun + 1]. idxOfCandidateRun := run - 1. [idxOfCandidateRun >= 1 and: [(values at: idxOfCandidateRun) includes: attr]] whileTrue: [firstRelevantPosition := firstRelevantPosition - (runs at: idxOfCandidateRun). idxOfCandidateRun := idxOfCandidateRun - 1]. firstRelevantPosition to: lastRelevantPosition] ]! ! !RunArray methodsFor: 'adding' stamp: 'ar 10/16/2001 18:48'! repeatLast: times ifEmpty: defaultBlock "add the last value back again, the given number of times. If we are empty, add (defaultBlock value)" times = 0 ifTrue: [^self ]. lastIndex _ nil. "flush access cache" (runs size=0) ifTrue: [runs _ runs copyWith: times. values _ values copyWith: defaultBlock value] ifFalse: [runs at: runs size put: runs last+times] ! ! !RunArray methodsFor: 'adding' stamp: 'ar 10/16/2001 18:48'! repeatLastIfEmpty: defaultBlock "add the last value back again. If we are empty, add (defaultBlock value)" lastIndex _ nil. "flush access cache" (runs size=0) ifTrue:[ runs _ runs copyWith: 1. values _ values copyWith: defaultBlock value] ifFalse: [runs at: runs size put: runs last+1]! ! !RunArray methodsFor: 'copying' stamp: 'ar 10/16/2001 18:57'! , aRunArray "Answer a new RunArray that is a concatenation of the receiver and aRunArray." | new newRuns | (aRunArray isMemberOf: RunArray) ifFalse: [new _ self copy. "attempt to be sociable" aRunArray do: [:each | new addLast: each]. ^new]. runs size = 0 ifTrue: [^aRunArray copy]. aRunArray runs size = 0 ifTrue: [^self copy]. (values at: values size) ~= (aRunArray values at: 1) ifTrue: [^RunArray runs: runs , aRunArray runs values: values , aRunArray values]. newRuns _ runs copyReplaceFrom: runs size to: runs size with: aRunArray runs. newRuns at: runs size put: (runs at: runs size) + (aRunArray runs at: 1). ^RunArray runs: newRuns values: (values copyReplaceFrom: values size to: values size with: aRunArray values)! ! !RunArray methodsFor: 'copying' stamp: 'ls 10/10/1999 13:15'! copyFrom: start to: stop | newRuns run1 run2 offset1 offset2 | stop < start ifTrue: [^RunArray new]. self at: start setRunOffsetAndValue: [:r :o :value1 | run1 _ r. offset1 _ o. value1]. self at: stop setRunOffsetAndValue: [:r :o :value2 | run2 _ r. offset2 _ o. value2]. run1 = run2 ifTrue: [newRuns _ Array with: offset2 - offset1 + 1] ifFalse: [newRuns _ runs copyFrom: run1 to: run2. newRuns at: 1 put: (newRuns at: 1) - offset1. newRuns at: newRuns size put: offset2 + 1]. ^RunArray runs: newRuns values: (values copyFrom: run1 to: run2)! ! !RunArray methodsFor: 'copying'! copyReplaceFrom: start to: stop with: replacement ^(self copyFrom: 1 to: start - 1) , replacement , (self copyFrom: stop + 1 to: self size)! ! !RunArray methodsFor: 'printing' stamp: 'sma 6/1/2000 09:47'! printOn: aStream self printNameOn: aStream. aStream nextPutAll: ' runs: '; print: runs; nextPutAll: ' values: '; print: values! ! !RunArray methodsFor: 'printing'! storeOn: aStream aStream nextPut: $(. aStream nextPutAll: self class name. aStream nextPutAll: ' runs: '. runs storeOn: aStream. aStream nextPutAll: ' values: '. values storeOn: aStream. aStream nextPut: $)! ! !RunArray methodsFor: 'printing'! writeOn: aStream aStream nextWordPut: runs size. 1 to: runs size do: [:x | aStream nextWordPut: (runs at: x). aStream nextWordPut: (values at: x)]! ! !RunArray methodsFor: 'printing' stamp: 'tk 12/16/97 09:18'! writeScanOn: strm "Write out the format used for text runs in source files. (14 50 312)f1,f1b,f1LInteger +;i" strm nextPut: $(. runs do: [:rr | rr printOn: strm. strm space]. strm skip: -1; nextPut: $). values do: [:vv | vv do: [:att | att writeScanOn: strm]. strm nextPut: $,]. strm skip: -1. "trailing comma"! ! !RunArray methodsFor: 'private'! at: index setRunOffsetAndValue: aBlock "Supply all run information to aBlock." "Tolerates index=0 and index=size+1 for copyReplace: " | run limit offset | limit _ runs size. (lastIndex == nil or: [index < lastIndex]) ifTrue: "cache not loaded, or beyond index - start over" [run _ 1. offset _ index-1] ifFalse: "cache loaded and before index - start at cache" [run _ lastRun. offset _ lastOffset + (index-lastIndex)]. [run <= limit and: [offset >= (runs at: run)]] whileTrue: [offset _ offset - (runs at: run). run _ run + 1]. lastIndex _ index. "Load cache for next access" lastRun _ run. lastOffset _ offset. run > limit ifTrue: ["adjustment for size+1" run _ run - 1. offset _ offset + (runs at: run)]. ^aBlock value: run "an index into runs and values" value: offset "zero-based offset from beginning of this run" value: (values at: run) "value for this run"! ! !RunArray methodsFor: 'private'! mapValues: mapBlock "NOTE: only meaningful to an entire set of runs" values _ values collect: [:val | mapBlock value: val]! ! !RunArray methodsFor: 'private'! runs ^runs! ! !RunArray methodsFor: 'private' stamp: 'ar 10/16/2001 18:47'! setRuns: newRuns setValues: newValues lastIndex _ nil. "flush access cache" runs _ newRuns asArray. values _ newValues asArray.! ! !RunArray methodsFor: 'private'! values "Answer the values in the receiver." ^values! ! !RunArray methodsFor: 'enumerating' stamp: 'ar 12/17/2001 00:00'! runsFrom: start to: stop do: aBlock "Evaluate aBlock with all existing runs in the range from start to stop" | run value index | start > stop ifTrue:[^self]. self at: start setRunOffsetAndValue:[:firstRun :offset :firstValue| run _ firstRun. value _ firstValue. index _ start + (runs at: run) - offset. [aBlock value: value. index <= stop] whileTrue:[ run _ run + 1. value _ values at: run. index _ index + (runs at: run)]]. ! ! !RunArray methodsFor: 'converting' stamp: 'BG 6/8/2003 15:17'! reversed ^self class runs: runs reversed values: values reversed! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! RunArray class instanceVariableNames: ''! !RunArray class methodsFor: 'instance creation' stamp: 'ar 10/16/2001 19:03'! new ^self runs: Array new values: Array new! ! !RunArray class methodsFor: 'instance creation' stamp: 'ar 10/16/2001 19:04'! new: size withAll: value "Answer a new instance of me, whose every element is equal to the argument, value." size = 0 ifTrue: [^self new]. ^self runs: (Array with: size) values: (Array with: value)! ! !RunArray class methodsFor: 'instance creation'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." | newCollection | newCollection _ self new. aCollection do: [:x | newCollection addLast: x]. ^newCollection " RunArray newFrom: {1. 2. 2. 3} {1. $a. $a. 3} as: RunArray ({1. $a. $a. 3} as: RunArray) values "! ! !RunArray class methodsFor: 'instance creation'! readFrom: aStream "Answer an instance of me as described on the stream, aStream." | size runs values | size _ aStream nextWord. runs _ Array new: size. values _ Array new: size. 1 to: size do: [:x | runs at: x put: aStream nextWord. values at: x put: aStream nextWord]. ^ self runs: runs values: values! ! !RunArray class methodsFor: 'instance creation'! runs: newRuns values: newValues "Answer an instance of me with runs and values specified by the arguments." | instance | instance _ self basicNew. instance setRuns: newRuns setValues: newValues. ^instance! ! !RunArray class methodsFor: 'instance creation' stamp: 'ssa 9/3/2008 11:15'! scanFrom: strm "Read the style section of a fileOut or sources file. nextChunk has already been done. We need to return a RunArray of TextAttributes of various kinds. These are written by the implementors of writeScanOn:" | rr vv aa this | (strm peekFor: $( ) ifFalse: [^ nil]. rr _ OrderedCollection new. [strm skipSeparators. strm peekFor: $)] whileFalse: [rr add: (Number readFrom: strm)]. vv _ OrderedCollection new. "Value array" aa _ OrderedCollection new. "Attributes list" [(this _ strm next) == nil] whileFalse: [ this == $, ifTrue: [vv add: aa asArray. aa _ OrderedCollection new]. this == $a ifTrue: [aa add: (TextAlignment new alignment: (Integer readFrom: strm))]. this == $f ifTrue: [aa add: (TextFontChange new fontNumber: (Integer readFrom: strm))]. this == $F ifTrue: [aa add: (TextFontReference new toFont: (StrikeFont familyName: (strm upTo: $#) size: (Integer readFrom: strm)))]. this == $b ifTrue: [aa add: (TextEmphasis bold)]. this == $i ifTrue: [aa add: (TextEmphasis italic)]. this == $u ifTrue: [aa add: (TextEmphasis underlined)]. this == $= ifTrue: [aa add: (TextEmphasis struckOut)]. this == $n ifTrue: [aa add: (TextEmphasis normal)]. this == $- ifTrue: [aa add: (TextKern kern: -1)]. this == $+ ifTrue: [aa add: (TextKern kern: 1)]. this == $c ifTrue: [aa add: (TextColor scanFrom: strm)]. "color" this == $L ifTrue: [aa add: (TextLink scanFrom: strm)]. "L not look like 1" " this == $R ifTrue: [aa add: (TextURL scanFrom: strm)]." "R capitalized so it can follow a number" " this == $q ifTrue: [aa add: (TextSqkPageLink scanFrom: strm)]. " " this == $p ifTrue: [aa add: (TextSqkProjectLink scanFrom: strm)]. " this == $P ifTrue: [aa add: (TextPrintIt scanFrom: strm)]. this == $d ifTrue: [aa add: (TextDoIt scanFrom: strm)]. "space, cr do nothing" ]. aa size > 0 ifTrue: [vv add: aa asArray]. ^ self runs: rr asArray values: vv asArray " RunArray scanFrom: (ReadStream on: '(14 50 312)f1,f1b,f1LInteger +;i') "! ! Number subclass: #ScaledDecimal instanceVariableNames: 'fraction scale' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !ScaledDecimal commentStamp: '<historical>' prior: 0! ScaledDecimal provides a numeric representation of fixed point decimal numbers able to accurately represent decimal fractions. It supports unbounded precision, with no limit to the number of digits before and after the decimal point. ScaledDecimal complies with the ANSI protocols: Object number ScaledDecimal ???? #todo. "finish protocol list." Implementation Notes: I implemented ScaledDecimal with the decimal fraction stored in instance variables numerator and denominator, and the number of digits after the decimal point in fractionalDigit as a positive Integer. I implemented operations by first coercing the aurguments to fractions, doing the operations, then coercing the result to the proper numeric representation when necessary and scale. This is because I assume the Fraction class is more likely to implement them correctly. Richard A. Harmon ! !ScaledDecimal methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToFraction: receiver andSend: arithmeticOpSelector "Convert me to a Fraction and do the arithmetic. receiver arithmeticOpSelector self." ^ receiver perform: arithmeticOpSelector with: fraction! ! !ScaledDecimal methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! adaptToInteger: receiver andSend: arithmeticOpSelector "Convert receiver to a ScaledDecimal and do the arithmetic. receiver arithmeticOpSelector self." ^ (receiver asScaledDecimal: 0) perform: arithmeticOpSelector with: self! ! !ScaledDecimal methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! asFloat "Reimplementation - Number 'converting' method." ^ fraction asFloat! ! !ScaledDecimal methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! asFraction "Implementation - Number 'converting' method." ^ fraction! ! !ScaledDecimal methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! asScaledDecimal: scaleIn "Reimplementation - Number 'converting' method." ^ ScaledDecimal newFromNumber: fraction scale: scaleIn! ! !ScaledDecimal methodsFor: 'printing' stamp: 'RAH 4/25/2000 19:49'! printOn: aStream "Reimplementation - Object 'printing' method." | aFraction tmpFractionPart | self < 0 ifTrue: [aStream nextPut: $-]. aFraction := fraction abs. aStream nextPutAll: aFraction truncated printString. scale = 0 ifTrue: [^ aStream nextPutAll: 's0']. aStream nextPut: $.. tmpFractionPart := aFraction fractionPart. 1 to: scale do: [:dummy | tmpFractionPart := tmpFractionPart * 10. aStream nextPut: (Character digitValue: tmpFractionPart truncated). tmpFractionPart := tmpFractionPart fractionPart]. aStream nextPut: $s. scale printOn: aStream! ! !ScaledDecimal methodsFor: 'printing' stamp: 'RAH 4/25/2000 19:49'! printString "Reimplementation - Number 'printing' method." | tempStream | tempStream := WriteStream on: (String new: 10). self printOn: tempStream. ^ tempStream contents! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'AFi 11/23/2002 19:12'! * operand "Implementation of Number 'arithmetic' method." (operand isKindOf: ScaledDecimal) ifTrue: [^ ScaledDecimal newFromNumber: fraction * operand asFraction scale: (scale max: operand scale)]. ^ operand adaptToScaledDecimal: self andSend: #*! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'AFi 11/23/2002 19:12'! + operand "Implementation of Number 'arithmetic' method." (operand isKindOf: ScaledDecimal) ifTrue: [^ ScaledDecimal newFromNumber: fraction + operand asFraction scale: (scale max: operand scale)]. ^ operand adaptToScaledDecimal: self andSend: #+! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'AFi 11/23/2002 19:12'! - operand "Implementation of Number 'arithmetic' method." (operand isKindOf: ScaledDecimal) ifTrue: [^ ScaledDecimal newFromNumber: fraction - operand asFraction scale: (scale max: operand scale)]. ^ operand adaptToScaledDecimal: self andSend: #-! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'AFi 11/23/2002 19:12'! / operand "Implementation of Number 'arithmetic' method." #ScalDec. "Protocol: ANSI <number>." operand = 0 ifTrue: [^ (ZeroDivide dividend: self) signal]. (operand isKindOf: ScaledDecimal) ifTrue: [^ ScaledDecimal newFromNumber: fraction / operand asFraction scale: (scale max: operand scale)]. ^ operand adaptToScaledDecimal: self andSend: #/! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! // operand "Answer the integer quotient after dividing the receiver by operand with truncation towards negative infinity." ^ fraction // operand! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! negated "Reimplementation of Number 'arithmetic' method." ^ ScaledDecimal newFromNumber: fraction negated scale: scale! ! !ScaledDecimal methodsFor: 'arithmetic' stamp: 'RAH 4/25/2000 19:49'! reciprocal "Reimplementation of Number 'arithmetic' method." self = 0 ifTrue: [^ (ZeroDivide dividend: 1) signal]. ^ ScaledDecimal newFromNumber: fraction reciprocal scale: scale! ! !ScaledDecimal methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'! fractionPart "Answer the fractional part of the receiver." ^ ScaledDecimal newFromNumber: fraction fractionPart scale: scale! ! !ScaledDecimal methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'! integerPart "Answer the fractional part of the receiver." ^ ScaledDecimal newFromNumber: fraction integerPart scale: scale! ! !ScaledDecimal methodsFor: 'truncation and round off' stamp: 'RAH 4/25/2000 19:49'! truncated "Reimplementation of Number 'truncation and round off' method." ^ fraction truncated! ! !ScaledDecimal methodsFor: 'comparing' stamp: 'AFi 11/23/2002 19:12'! < operand "Implementation of Number 'comparing' method." (operand isKindOf: ScaledDecimal) ifTrue: [^ fraction < operand asFraction]. ^ operand adaptToScaledDecimal: self andSend: #<! ! !ScaledDecimal methodsFor: 'comparing' stamp: 'AFi 11/23/2002 19:13'! = comparand "Implementation of Number 'comparing' method." comparand isNumber ifFalse: [^ false]. (comparand isKindOf: ScaledDecimal) ifTrue: [^ fraction = comparand asFraction]. ^ comparand adaptToScaledDecimal: self andSend: #=! ! !ScaledDecimal methodsFor: 'comparing' stamp: 'RAH 4/25/2000 19:49'! hash "Reimplementation of Object 'comparing' method." ^ fraction hash! ! !ScaledDecimal methodsFor: 'comparing' stamp: 'RAH 4/25/2000 19:49'! isZero "Answer whether the receiver is equal to its class' zero" ^ fraction numerator = 0! ! !ScaledDecimal methodsFor: 'private' stamp: 'RAH 4/25/2000 19:49'! denominator "Private - Answer an Integer, the denominator part of the receiver." ^ fraction denominator! ! !ScaledDecimal methodsFor: 'private' stamp: 'RAH 4/25/2000 19:49'! numerator "Private - Answer an Integer, the numerator part of the receiver." ^ fraction numerator! ! !ScaledDecimal methodsFor: 'private' stamp: 'RAH 4/25/2000 19:49'! scale "Private - Answer a integer which represents the total number of digits used to represent the fraction part of the receiver, including trailing zeroes. " ^ scale! ! !ScaledDecimal methodsFor: 'private' stamp: 'RAH 4/25/2000 19:49'! setFraction: fractionIn scale: scaleIn "Private - Set the fraction to fractionIn and the total number of digits used to represent the fraction part of the receiver, including trailing zeroes, to the Integer scaleIn." fraction := fractionIn. scale := scaleIn! ! !ScaledDecimal methodsFor: 'mathematical functions' stamp: 'RAH 4/25/2000 19:49'! squared "Reimplementation - Number 'mathematical functions' method." "not used ->" ^ ScaledDecimal newFromNumber: fraction squared scale: scale! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ScaledDecimal class instanceVariableNames: ''! !ScaledDecimal class methodsFor: 'instance creation' stamp: 'RAH 4/25/2000 19:49'! newFromNumber: aNumber scale: scaleIn "Answer a new instance of me." | temp | temp := self basicNew. temp setFraction: aNumber asFraction scale: scaleIn. ^ temp! ! !ScaledDecimal class methodsFor: 'constants' stamp: 'RAH 4/25/2000 19:49'! one "Answer the receiver's representation of one." ^ self newFromNumber: 1 scale: 0! ! !ScaledDecimal class methodsFor: 'constants' stamp: 'RAH 4/25/2000 19:49'! zero "Answer the receiver's representation of zero." ^ self newFromNumber: 0 scale: 0! ! Object subclass: #Scanner instanceVariableNames: 'source mark hereChar aheadChar token tokenType currentComment buffer typeTable' classVariableNames: 'TypeTable' poolDictionaries: '' category: 'System-Compiler'! !Scanner commentStamp: '<historical>' prior: 0! 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.! !Scanner methodsFor: 'initialize-release'! initScanner buffer _ WriteStream on: (String new: 40). typeTable _ TypeTable! ! !Scanner methodsFor: 'initialize-release'! scan: inputStream "Bind the input stream, fill the character buffers and first token buffer." source _ inputStream. self step. self step. self scanToken! ! !Scanner methodsFor: 'public access'! scanFieldNames: stringOrArray "Answer an Array of Strings that are the identifiers in the input string, stringOrArray. If passed an Array, just answer with that Array, i.e., assume it has already been scanned." | strm | (stringOrArray isMemberOf: Array) ifTrue: [^stringOrArray]. self scan: (ReadStream on: stringOrArray asString). strm _ WriteStream on: (Array new: 10). [tokenType = #doIt] whileFalse: [tokenType = #word ifTrue: [strm nextPut: token]. self scanToken]. ^strm contents "Scanner new scanFieldNames: 'abc def ghi' ('abc' 'def' 'ghi' )"! ! !Scanner methodsFor: 'public access'! scanTokens: textOrString "Answer an Array that has been tokenized as though the input text, textOrString, had appeared between the array delimitors #( and ) in a Smalltalk literal expression." self scan: (ReadStream on: textOrString asString). self scanLitVec. ^token "Scanner new scanTokens: 'identifier keyword: 8r31 ''string'' .'"! ! !Scanner methodsFor: 'expression types'! advance | prevToken | prevToken _ token. self scanToken. ^prevToken! ! !Scanner methodsFor: 'expression types' stamp: 'di 4/23/2000 22:15'! checkpoint "Return a copy of all changeable state. See revertToCheckpoint:" ^ {self clone. source clone. currentComment copy}! ! !Scanner methodsFor: 'expression types' stamp: 'di 4/23/2000 22:11'! revertToCheckpoint: checkpoint "Revert to the state when checkpoint was made." | myCopy | myCopy _ checkpoint first. 1 to: self class instSize do: [:i | self instVarAt: i put: (myCopy instVarAt: i)]. source _ checkpoint second. currentComment _ checkpoint third! ! !Scanner methodsFor: 'expression types' stamp: 'avi 2/16/2004 21:28'! scanLitVec | s | s _ WriteStream on: (Array new: 16). [tokenType = #rightParenthesis or: [tokenType = #doIt]] whileFalse: [tokenType = #leftParenthesis ifTrue: [self scanToken; scanLitVec] ifFalse: [tokenType = #word | (tokenType = #keyword) | (tokenType = #colon) ifTrue: [self scanLitWord. token = #true ifTrue: [token _ true]. token = #false ifTrue: [token _ false]. token = #nil ifTrue: [token _ nil]] ifFalse: [(token == #- and: [(typeTable at: hereChar asciiValue) = #xDigit]) ifTrue: [self scanToken. token _ token negated]]]. s nextPut: token. self scanToken]. token _ s contents! ! !Scanner methodsFor: 'expression types'! scanLitWord "Accumulate keywords and asSymbol the result." | t | [(typeTable at: hereChar asciiValue) = #xLetter] whileTrue: [t _ token. self xLetter. token _ t , token]. token _ token asSymbol! ! !Scanner methodsFor: 'expression types'! scanToken [(tokenType _ typeTable at: hereChar asciiValue) == #xDelimiter] whileTrue: [self step]. "Skip delimiters fast, there almost always is one." mark _ source position - 1. (tokenType at: 1) = $x "x as first letter" ifTrue: [self perform: tokenType "means perform to compute token & type"] ifFalse: [token _ self step asSymbol "else just unique the first char"]. ^token! ! !Scanner methodsFor: 'expression types'! step | c | c _ hereChar. hereChar _ aheadChar. source atEnd ifTrue: [aheadChar _ 30 asCharacter "doit"] ifFalse: [aheadChar _ source next]. ^c! ! !Scanner methodsFor: 'multi-character scans' stamp: 'SqR 8/23/2000 16:20'! xBinary tokenType _ #binary. token _ self step asSymbol. [(typeTable at: hereChar asciiValue) = #xBinary and: [hereChar ~= $-]] whileTrue: [token _ (token , (String with: self step)) asSymbol]! ! !Scanner methodsFor: 'multi-character scans' stamp: 'md 11/14/2003 17:14'! xColon "Allow := for assignment by converting to #_ " aheadChar = $= ifTrue: [self step. tokenType _ #leftArrow. self step. ^ token _ #'_']. "Otherwise, just do what normal scan of colon would do" tokenType _ #colon. ^ token _ self step asSymbol! ! !Scanner methodsFor: 'multi-character scans'! xDelimiter "Ignore blanks, etc." self scanToken! ! !Scanner methodsFor: 'multi-character scans' stamp: 'tao 4/23/98 12:55'! xDigit "Form a number." tokenType _ #number. (aheadChar = 30 asCharacter and: [source atEnd and: [source skip: -1. source next ~= 30 asCharacter]]) ifTrue: [source skip: -1 "Read off the end last time"] ifFalse: [source skip: -2]. token _ [Number readFrom: source] ifError: [:err :rcvr | self offEnd: err]. self step; step! ! !Scanner methodsFor: 'multi-character scans'! xDollar "Form a Character literal." self step. "pass over $" token _ self step. tokenType _ #number "really should be Char, but rest of compiler doesn't know"! ! !Scanner methodsFor: 'multi-character scans' stamp: 'wod 1/10/98 00:43'! xDoubleQuote "Collect a comment." "wod 1/10/98: Allow 'empty' comments by testing the first character for $"" rather than blindly adding it to the comment being collected." | aStream stopChar | stopChar _ 30 asCharacter. aStream _ WriteStream on: (String new: 200). self step. [hereChar == $"] whileFalse: [(hereChar == stopChar and: [source atEnd]) ifTrue: [^self offEnd: 'Unmatched comment quote']. aStream nextPut: self step.]. self step. currentComment == nil ifTrue: [currentComment _ OrderedCollection with: aStream contents] ifFalse: [currentComment add: aStream contents]. self scanToken! ! !Scanner methodsFor: 'multi-character scans' stamp: 'di 4/22/2000 16:36'! xLetter "Form a word or keyword." | type | buffer reset. [(type _ typeTable at: hereChar asciiValue) == #xLetter or: [type == #xDigit]] whileTrue: ["open code step for speed" buffer nextPut: hereChar. hereChar _ aheadChar. source atEnd ifTrue: [aheadChar _ 30 asCharacter "doit"] ifFalse: [aheadChar _ source next]]. (type == #colon or: [type == #xColon and: [aheadChar ~= $=]]) ifTrue: [buffer nextPut: self step. ["Allow any number of embedded colons in literal symbols" (typeTable at: hereChar asciiValue) == #xColon] whileTrue: [buffer nextPut: self step]. tokenType _ #keyword] ifFalse: [tokenType _ #word]. token _ buffer contents! ! !Scanner methodsFor: 'multi-character scans' stamp: 'hmm 7/18/2001 21:55'! xLitQuote "Symbols and vectors: #(1 (4 5) 2 3) #ifTrue:ifFalse: #'abc'." | start | start _ mark. self step. "litQuote" self scanToken. tokenType = #leftParenthesis ifTrue: [self scanToken; scanLitVec. mark _ start+1. tokenType == #doIt ifTrue: [self offEnd: 'Unmatched parenthesis']] ifFalse: [(#(word keyword colon ) includes: tokenType) ifTrue: [self scanLitWord] ifFalse: [(tokenType==#literal) ifTrue: [(token isMemberOf: Symbol) ifTrue: "##word" [token _ token "May want to move toward ANSI here"]] ifFalse: [tokenType==#string ifTrue: [token _ token asSymbol]]]]. mark _ start. tokenType _ #literal " #(Pen) #Pen #'Pen' ##Pen ###Pen "! ! !Scanner methodsFor: 'multi-character scans'! xSingleQuote "String." self step. buffer reset. [hereChar = $' and: [aheadChar = $' ifTrue: [self step. false] ifFalse: [true]]] whileFalse: [buffer nextPut: self step. (hereChar = 30 asCharacter and: [source atEnd]) ifTrue: [^self offEnd: 'Unmatched string quote']]. self step. token _ buffer contents. tokenType _ #string! ! !Scanner methodsFor: 'error handling'! notify: string "Refer to the comment in Object|notify:." self error: string! ! !Scanner methodsFor: 'error handling'! offEnd: aString "Parser overrides this" ^self notify: aString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Scanner class instanceVariableNames: ''! !Scanner class methodsFor: 'class initialization' stamp: 'dgd 8/24/2003 14:55'! initialize | newTable | newTable _ Array new: 256 withAll: #xBinary. "default" newTable atAll: #(9 10 12 13 32 ) put: #xDelimiter. "tab lf ff cr space" newTable atAll: ($0 asciiValue to: $9 asciiValue) put: #xDigit. 1 to: 255 do: [:index | (Character value: index) isLetter ifTrue: [newTable at: index put: #xLetter]]. newTable at: 30 put: #doIt. newTable at: $" asciiValue put: #xDoubleQuote. newTable at: $# asciiValue put: #xLitQuote. newTable at: $$ asciiValue put: #xDollar. newTable at: $' asciiValue put: #xSingleQuote. newTable at: $: asciiValue put: #xColon. newTable at: $( asciiValue put: #leftParenthesis. newTable at: $) asciiValue put: #rightParenthesis. newTable at: $. asciiValue put: #period. newTable at: $; asciiValue put: #semicolon. newTable at: $[ asciiValue put: #leftBracket. newTable at: $] asciiValue put: #rightBracket. newTable at: ${ asciiValue put: #leftBrace. newTable at: $} asciiValue put: #rightBrace. newTable at: $^ asciiValue put: #upArrow. newTable at: $_ asciiValue put: #leftArrow. newTable at: $| asciiValue put: #verticalBar. TypeTable _ newTable "bon voyage!!" "Scanner initialize"! ! !Scanner class methodsFor: 'instance creation'! new ^super new initScanner! ! !Scanner class methodsFor: 'testing' stamp: 'bf 4/27/2000 12:56'! isLiteralSymbol: aSymbol "Test whether a symbol can be stored as # followed by its characters. Symbols created internally with asSymbol may not have this property, e.g. '3' asSymbol." | i ascii type | i _ aSymbol size. i = 0 ifTrue: [^ false]. i = 1 ifTrue: [('$''"()#0123456789' includes: (aSymbol at: 1)) ifTrue: [^ false] ifFalse: [^ true]]. ascii _ (aSymbol at: 1) asciiValue. "TypeTable should have been origined at 0 rather than 1 ..." ascii = 0 ifTrue: [^ false]. type _ TypeTable at: ascii. (type == #xColon or: [type == #verticalBar]) ifTrue: [^ i = 1]. type == #xBinary ifTrue: [[i > 1] whileTrue: [ascii _ (aSymbol at: i) asciiValue. ascii = 0 ifTrue: [^ false]. (TypeTable at: ascii) == #xBinary ifFalse: [^ false]. i _ i - 1]. ^ true]. type == #xLetter ifTrue: [[i > 1] whileTrue: [ascii _ (aSymbol at: i) asciiValue. ascii = 0 ifTrue: [^ false]. type _ TypeTable at: ascii. (type == #xLetter or: [type == #xDigit or: [type == #xColon]]) ifFalse: [^ false]. i _ i - 1]. ^ true]. ^ false! ! Timespan subclass: #Schedule instanceVariableNames: 'schedule' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Chronology'! !Schedule commentStamp: 'brp 5/13/2003 09:48' prior: 0! I represent a powerful class for implementing recurring schedules.! !Schedule methodsFor: 'enumerating' stamp: 'brp 5/13/2003 09:50'! between: aStart and: anEnd do: aBlock | element end i | end _ self end min: anEnd. element _ self start. i _ 1. [ element < aStart ] whileTrue: [ element _ element + (schedule at: i). i _ i + 1. (i > schedule size) ifTrue: [i _ 1]]. i _ 1. [ element <= end ] whileTrue: [ aBlock value: element. element _ element + (schedule at: i). i _ i + 1. (i > schedule size) ifTrue: [i _ 1]] . ! ! !Schedule methodsFor: 'enumerating' stamp: 'brp 5/13/2003 09:50'! schedule ^ schedule ! ! !Schedule methodsFor: 'enumerating' stamp: 'brp 5/13/2003 09:50'! schedule: anArrayOfDurations schedule _ anArrayOfDurations ! ! !Schedule methodsFor: 'enumerating' stamp: 'brp 5/13/2003 09:51'! scheduleDo: aBlock self between: (self start) and: (self end) do: aBlock. ! ! !Schedule methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:38'! includes: aDateAndTime | dt | dt _ aDateAndTime asDateAndTime. self scheduleDo: [ :e | e = dt ifTrue: [^true] ]. ^ false. ! ! Controller subclass: #ScreenController instanceVariableNames: '' classVariableNames: 'LastScreenModeSelected' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !ScreenController commentStamp: '<historical>' prior: 0! 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. (ScheduledControllers screenController) is the way to find me.! !ScreenController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:21'! controlActivity "Any button opens the screen's menu. If the shift key is down, do find window." sensor leftShiftDown ifTrue: [^ self findWindow]. (self projectScreenMenu invokeOn: self) ifNil: [super controlActivity]! ! !ScreenController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:06'! isControlActive ^ self isControlWanted! ! !ScreenController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:05'! isControlWanted ^ self viewHasCursor and: [sensor anyButtonPressed]! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 2/15/1999 16:18'! aboutThisSystem Smalltalk aboutThisSystem! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 6/11/1999 20:25'! bitCachingString ^ StandardSystemView cachingBits ifTrue: ['don''t save bits (compact)'] ifFalse: ['save bits (fast)']! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 5/23/2003 15:17'! browseChangedMessages ChangeSet browseChangedMessages! ! !ScreenController methodsFor: 'menu messages'! browseRecentLog "Open a changelist browser on changes submitted since the last snapshot. 1/17/96 sw" ChangeList browseRecentLog! ! !ScreenController methodsFor: 'menu messages'! browseRecentSubmissions "Open a method-list browser on recently-submitted methods. 5/16/96 sw" Utilities browseRecentSubmissions! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 6/11/1999 20:50'! changeWindowPolicy Preferences toggleWindowPolicy! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:12'! chooseDirtyBrowser "Put up a list of browsers with unsubmitted edits and activate the one selected by the user, if any." "ScheduledControllers screenController chooseDirtyBrowser" ScheduledControllers findWindowSatisfying: [:c | (c model isKindOf: Browser) and: [c model canDiscardEdits not]]. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:13'! chooseDirtyWindow "Put up a list of windows with unaccepted edits and let the user chose one to activate." "ScheduledControllers screenController chooseDirtyWindow" ScheduledControllers findWindowSatisfying: [:c | c model canDiscardEdits not]. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:13'! closeUnchangedWindows "Close any window that doesn't have unaccepted input." | clean | (SelectionMenu confirm: 'Do you really want to close all windows except those with unaccepted edits?') ifFalse: [^ self]. clean _ ScheduledControllers scheduledControllers select: [:c | c model canDiscardEdits and: [(c isKindOf: ScreenController) not]]. clean do: [:c | c closeAndUnscheduleNoTerminate]. self restoreDisplay. ! ! !ScreenController methodsFor: 'menu messages'! collapseAll "Collapses all open windows" ScheduledControllers scheduledControllers do: [:controller | controller == self ifFalse: [controller view isCollapsed ifFalse: [controller collapse. controller view deEmphasize]]]! ! !ScreenController methodsFor: 'menu messages'! commonRequests "Put up a popup of common requests, and perform whatever the user request. 2/1/96 sw" Utilities offerCommonRequests! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 12/10/1999 11:29'! configureFonts Preferences presentMvcFontConfigurationMenu! ! !ScreenController methodsFor: 'menu messages'! editPreferences "Open up a Preferences inspector. 2/7/96 sw" Preferences openPreferencesInspector! ! !ScreenController methodsFor: 'menu messages'! emergencyCollapse "Emergency collapse of a selected window" | controller | (controller _ ScheduledControllers windowFromUser) notNil ifTrue: [controller collapse. controller view deEmphasize]! ! !ScreenController methodsFor: 'menu messages'! expandAll "Reopens all collapsed windows" ScheduledControllers scheduledControllers reverseDo: [:controller | controller == self ifFalse: [controller view isCollapsed ifTrue: [controller view expand] ifFalse: [controller view displayDeEmphasized]]]! ! !ScreenController methodsFor: 'menu messages'! fastWindows StandardSystemView cachingBits ifTrue: [StandardSystemView dontCacheBits] ifFalse: [StandardSystemView doCacheBits]! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 2/3/2000 16:23'! fileForRecentLog Smalltalk writeRecentToFile! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 1/16/2004 21:32'! fileOutChanges ChangeSet current verboseFileOut.! ! !ScreenController methodsFor: 'menu messages'! findWindow "Put up a menu of all windows on the screen, and let the user select one. 1/18/96 sw: the real work devolved to ControlManager>>findWindowSatisfying:" ScheduledControllers findWindowSatisfying: [:c | true]! ! !ScreenController methodsFor: 'menu messages' stamp: 'nk 6/17/2003 14:39'! fontSizeSummary TextStyle fontSizeSummary! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 6/7/2003 19:49'! fullScreenOff Display fullScreenMode: (LastScreenModeSelected _ false). DisplayScreen checkForNewScreenSize. self restoreDisplay. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 6/7/2003 19:49'! fullScreenOn Display fullScreenMode: (LastScreenModeSelected _ true). DisplayScreen checkForNewScreenSize. self restoreDisplay.! ! !ScreenController methodsFor: 'menu messages' stamp: 'nk 2/15/2004 09:37'! garbageCollect "Do a garbage collection, and report results to the user." Utilities garbageCollectAndReport! ! !ScreenController methodsFor: 'menu messages' stamp: 'jm 5/20/1998 23:28'! jumpToProject Project jumpToProject. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 5/23/2003 14:41'! lookForSlips ChangeSet current lookForSlips! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 7/18/1999 20:54'! lookUpDefinition Utilities lookUpDefinition! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 9/4/1998 10:17'! newChangeSet ChangeSorter newChangeSet! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 4/6/98 23:14'! openBrowser "Create and schedule a Browser view for browsing code." Browser openBrowser! ! !ScreenController methodsFor: 'menu messages'! openChangeManager "Open a dual change sorter. For looking at two change sets at once." DualChangeSorter new open! ! !ScreenController methodsFor: 'menu messages'! openCommandKeyHelp "1/18/96 sw Open a window that explains command-keys" Utilities openCommandKeyHelp! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 6/9/1999 12:30'! openFile FileList openFileDirectly! ! !ScreenController methodsFor: 'menu messages'! openFileList "Create and schedule a FileList view for specifying files to access." FileList open! ! !ScreenController methodsFor: 'menu messages' stamp: 'ar 1/31/2001 17:06'! openPackageBrowser "Create and schedule a Browser view for browsing code." PackagePaneBrowser openBrowser! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 9/4/2008 15:11'! openProcessBrowser "Create and schedule" ProcessBrowser open! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 4/24/2001 12:00'! openProject "Create and schedule a Project." | proj | Smalltalk at: #ProjectView ifPresent: [:c | proj _ Project new. c open: proj]. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 8/31/1998 16:18'! openSelectorBrowser "Create and schedule a selector fragment window." SelectorBrowser new open! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 7/6/1998 18:59'! openSimpleChangeSorter ChangeSorter new open! ! !ScreenController methodsFor: 'menu messages'! openStandardWorkspace "Open a standard, throwaway window chock full of useful expressions. 1/17/96 sw" Utilities openStandardWorkspace! ! !ScreenController methodsFor: 'menu messages' stamp: 'di 5/8/1998 12:49'! openTranscript "Create and schedule the System Transcript." Transcript open! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 5/4/1998 17:25'! openWorkspace "Create and schedule workspace." Workspace open! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 11/16/2003 14:17'! quit SmalltalkImage current snapshot: (self confirm: 'Save changes before quitting?' translated orCancel: [^ self]) andQuit: true! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 9/3/2008 11:12'! restoreDisplay "Clear the screen to gray and then redisplay all the scheduled views." Display extent = DisplayScreen actualScreenSize ifFalse: [DisplayScreen startUp. ScheduledControllers unCacheWindows]. ScheduledControllers restore! ! !ScreenController methodsFor: 'menu messages' stamp: 'jm 5/22/1998 06:45'! returnToPreviousProject Project returnToPreviousProject. ! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 11/16/2003 13:17'! saveAs ^ SmalltalkImage current saveAs! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 5/10/96'! setAuthorInitials "Put up a dialog allowing the user to specify the author's initials. " Utilities setAuthorInitials! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 11/26/96'! setDesktopColor "Let the user choose a new color for the desktop. Based on an idea by Georg Gollmann. " Preferences desktopColor: Color fromUser. ScheduledControllers updateGray; restore! ! !ScreenController methodsFor: 'menu messages' stamp: 'bf 9/18/1999 20:01'! setDisplayDepth "Let the user choose a new depth for the display. " | result | (result _ (SelectionMenu selections: Display supportedDisplayDepths) startUpWithCaption: 'Choose a display depth (it is currently ' , Display depth printString , ')') == nil ifFalse: [Display newDepth: result]! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 11/16/2003 14:17'! snapshot SmalltalkImage current snapshot: true andQuit: false! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 11/16/2003 14:17'! snapshotAndQuit "Snapshot and quit without bother the user further. 2/4/96 sw" SmalltalkImage current snapshot: true andQuit: true! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 6/11/1999 20:01'! soundEnablingString ^ Preferences soundEnablingString! ! !ScreenController methodsFor: 'menu messages' stamp: 'bf 3/16/2000 18:26'! soundOnOrOff Preferences setPreference: #soundsEnabled toValue: Preferences soundsEnabled not! ! !ScreenController methodsFor: 'menu messages' stamp: 'sw 6/11/1999 20:23'! staggerPolicyString ^ Preferences staggerPolicyString! ! !ScreenController methodsFor: 'menu messages' stamp: 'sd 9/30/2003 13:53'! vmStatistics "Open a string view on a report of vm statistics" (StringHolder new contents: SmalltalkImage current vmStatisticsReportString) openLabel: 'VM Statistics'! ! !ScreenController methodsFor: 'cursor'! centerCursorInView "Override so this doesn't happen when taking control"! ! !ScreenController methodsFor: 'nested menus' stamp: 'BG 10/30/2003 21:19'! appearanceMenu "Answer the appearance menu to be put up as a screen submenu" ^ SelectionMenu labelList: #('system fonts...' 'full screen on' 'full screen off' 'set display depth...' 'set desktop color...' ) lines: #(1 3) selections: #( configureFonts fullScreenOn fullScreenOff setDisplayDepth setDesktopColor) " ScreenController new appearanceMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'BG 10/30/2003 20:39'! changesMenu "Answer a menu for changes-related items" ^ SelectionMenu labelList: #( 'simple change sorter' 'dual change sorter' 'file out current change set' 'create new change set...' 'browse changed methods' 'check change set for slips' 'browse recent submissions' 'recently logged changes...' 'recent log file...' ) lines: #(2 6 ) selections: #( openSimpleChangeSorter openChangeManager fileOutChanges newChangeSet browseChangedMessages lookForSlips browseRecentSubmissions browseRecentLog fileForRecentLog) " ScreenController new changesMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'BG 11/2/2003 20:57'! helpMenu "Answer the help menu to be put up as a screen submenu" ^ SelectionMenu labelList: #( 'about this system...' 'preferences...' 'command-key help' 'font size summary' 'useful expressions' 'view graphical imports'), (Array with: (Preferences soundsEnabled ifFalse: ['turn sound on'] ifTrue: ['turn sound off'])) , #( 'definition for...' 'set author initials...' 'vm statistics' 'space left') lines: #(2 4 8) selections: #( aboutThisSystem editPreferences openCommandKeyHelp fontSizeSummary openStandardWorkspace viewImageImports soundOnOrOff lookUpDefinition setAuthorInitials vmStatistics garbageCollect) " ScreenController new helpMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 9/4/2008 15:11'! openMenu ^ SelectionMenu labelList: #( 'browser' 'package browser' 'method finder' 'process browser' 'workspace' 'file list' 'file...' 'transcript' 'simple change sorter' 'dual change sorter' 'mvc project' ) lines: #(8 10 ) selections: #( openBrowser openPackageBrowser openSelectorBrowser openProcessBrowser openWorkspace openFileList openFile openTranscript openSimpleChangeSorter openChangeManager openProject ) " ScreenController new openMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'sma 3/11/2000 12:23'! popUpMenuFor: aSymbol (self perform: aSymbol) invokeOn: self! ! !ScreenController methodsFor: 'nested menus' stamp: 'sw 7/13/1999 18:07'! presentAppearanceMenu self popUpMenuFor: #appearanceMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'sw 7/6/1998 21:14'! presentChangesMenu self popUpMenuFor: #changesMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'sw 7/6/1998 21:15'! presentHelpMenu self popUpMenuFor: #helpMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'sw 7/6/1998 21:15'! presentOpenMenu self popUpMenuFor: #openMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'sw 7/6/1998 21:16'! presentWindowMenu self popUpMenuFor: #windowMenu! ! !ScreenController methodsFor: 'nested menus' stamp: 'BG 10/28/2003 10:38'! projectScreenMenu "Answer the project screen menu." ^ SelectionMenu labelList: #( 'previous project' 'jump to project...' 'restore display' 'open...' 'windows...' 'changes...' 'help...' 'appearance...' 'do...' 'save' 'save as...' 'save and quit' 'quit') lines: #(3 9) selections: #( returnToPreviousProject jumpToProject restoreDisplay presentOpenMenu presentWindowMenu presentChangesMenu presentHelpMenu presentAppearanceMenu commonRequests snapshot saveAs snapshotAndQuit quit ) " ScreenController new projectScreenMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'BG 10/28/2003 10:57'! windowMenu "Answer a menu for windows-related items. " ^ SelectionMenu labelList: #( 'find window...' 'find changed browsers...' 'find changed windows...' 'collapse all windows' 'expand all windows' 'close unchanged windows' ) , (Array with: self bitCachingString with: self staggerPolicyString) lines: #(3 6) selections: #( findWindow chooseDirtyBrowser chooseDirtyWindow collapseAll expandAll closeUnchangedWindows fastWindows changeWindowPolicy) " ScreenController new windowMenu startUp "! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ScreenController class instanceVariableNames: ''! !ScreenController class methodsFor: 'as yet unclassified' stamp: 'RAA 7/15/2000 09:28'! lastScreenModeSelected ^LastScreenModeSelected! ! MouseMenuController subclass: #ScrollController instanceVariableNames: 'scrollBar marker savedArea menuBar savedMenuBarArea' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !ScrollController commentStamp: '<historical>' prior: 0! 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. 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.! !ScrollController methodsFor: 'initialize-release'! initialize super initialize. scrollBar _ Quadrangle new. scrollBar borderWidthLeft: 2 right: 0 top: 2 bottom: 2. marker _ Quadrangle new. marker insideColor: Preferences scrollBarColor. menuBar _ Quadrangle new. menuBar borderWidthLeft: 2 right: 0 top: 2 bottom: 2.! ! !ScrollController methodsFor: 'basic control sequence'! controlInitialize "Recompute scroll bars. Save underlying image unless it is already saved." | | super controlInitialize. scrollBar region: (0 @ 0 extent: 24 @ view apparentDisplayBox height). scrollBar insideColor: view backgroundColor. marker region: self computeMarkerRegion. scrollBar _ scrollBar align: scrollBar topRight with: view apparentDisplayBox topLeft. marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2). savedArea isNil ifTrue: [savedArea _ Form fromDisplay: scrollBar]. scrollBar displayOn: Display. "Show a border around yellow-button (menu) region" " yellowBar _ Rectangle left: self yellowLine right: scrollBar right + 1 top: scrollBar top bottom: scrollBar bottom. Display border: yellowBar width: 1 mask: Form veryLightGray. " self moveMarker ! ! !ScrollController methodsFor: 'basic control sequence'! controlTerminate super controlTerminate. savedArea notNil ifTrue: [savedArea displayOn: Display at: scrollBar topLeft. savedArea _ nil].! ! !ScrollController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:17'! controlActivity self scrollByKeyboard ifTrue: [^ self]. self scrollBarContainsCursor ifTrue: [self scroll] ifFalse: [self normalActivity]! ! !ScrollController methodsFor: 'control defaults' stamp: 'ar 3/24/2000 00:45'! isControlActive super isControlActive ifTrue: [^ true]. sensor blueButtonPressed ifTrue: [^ false]. ^ (scrollBar inside merge: view insetDisplayBox) containsPoint: sensor cursorPoint! ! !ScrollController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:31'! isControlWanted ^ self viewHasCursor! ! !ScrollController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:16'! normalActivity super controlActivity! ! !ScrollController methodsFor: 'scrolling'! anyButtonActivity "deal with red button down in scrollBar beyond yellowLine" self yellowButtonActivity! ! !ScrollController methodsFor: 'scrolling'! downLine "if cursor before downLine, display down cursor and scroll down on button down" ^scrollBar left + 6 ! ! !ScrollController methodsFor: 'scrolling' stamp: 'ls 7/11/1998 06:33'! scroll "Check to see whether the user wishes to jump, scroll up, or scroll down." | savedCursor | savedCursor _ sensor currentCursor. [self scrollBarContainsCursor] whileTrue: [self interActivityPause. sensor cursorPoint x <= self downLine ifTrue: [self scrollDown] ifFalse: [sensor cursorPoint x <= self upLine ifTrue: [self scrollAbsolute] ifFalse: [sensor cursorPoint x <= self yellowLine ifTrue: [self scrollUp] ifFalse: [sensor cursorPoint x <= scrollBar right ifTrue: "Might not be, with touch pen" [self changeCursor: Cursor menu. sensor anyButtonPressed ifTrue: [self changeCursor: savedCursor. self anyButtonActivity]]]]]]. savedCursor show! ! !ScrollController methodsFor: 'scrolling'! scrollAmount "Answer the number of bits of y-coordinate should be scrolled. This is a default determination based on the view's preset display transformation." ^((view inverseDisplayTransform: sensor cursorPoint) - (view inverseDisplayTransform: scrollBar inside topCenter)) y! ! !ScrollController methodsFor: 'scrolling' stamp: 'th 12/11/1999 16:57'! scrollByKeyboard | keyEvent | keyEvent _ sensor keyboardPeek. keyEvent ifNil: [^ false]. (sensor controlKeyPressed or:[sensor commandKeyPressed]) ifFalse: [^ false]. keyEvent asciiValue = 30 ifTrue: [sensor keyboard. self scrollViewDown ifTrue: [self moveMarker]. ^ true]. keyEvent asciiValue = 31 ifTrue: [sensor keyboard. self scrollViewUp ifTrue: [self moveMarker]. ^ true]. ^ false! ! !ScrollController methodsFor: 'scrolling'! scrollView "The scroll bar jump method was used so that the view should be updated to correspond to the location of the scroll bar gray area. Return true only if scrolling took place." ^ self scrollView: self viewDelta! ! !ScrollController methodsFor: 'scrolling'! scrollView: anInteger "Tell the reciever's view to scroll by anInteger amount. Return true only if scrolling actually resulted." (view scrollBy: 0 @ ((anInteger min: view window top - view boundingBox top) max: view window top - view boundingBox bottom)) ifTrue: [view clearInside; display. ^ true] ifFalse: [^ false]! ! !ScrollController methodsFor: 'scrolling'! scrollViewDown "Scroll the receiver's view down the default amount. Return true only if scrolling actually took place." ^ self scrollView: self scrollAmount! ! !ScrollController methodsFor: 'scrolling'! scrollViewUp "Scroll the receiver's view up the default amount. Return true only if scrolling actually took place." ^ self scrollView: self scrollAmount negated! ! !ScrollController methodsFor: 'scrolling'! upDownLine "Check to see whether the user wishes to jump, scroll up, or scroll down." ^scrollBar left + 12! ! !ScrollController methodsFor: 'scrolling'! upLine "if cursor beyond upLine, display up cursor and scroll up on button down" ^scrollBar left + 12! ! !ScrollController methodsFor: 'scrolling'! viewDelta "Answer an integer that indicates how much the view should be scrolled. The scroll bar has been moved and now the view must be so the amount to scroll is computed as a ratio of the current scroll bar position." ^view window top - view boundingBox top - ((marker top - scrollBar inside top) asFloat / scrollBar inside height asFloat * view boundingBox height asFloat) rounded! ! !ScrollController methodsFor: 'scrolling'! yellowLine "Check to see whether the user wishes to jump, scroll up, or scroll down." ^scrollBar left + 16! ! !ScrollController methodsFor: 'cursor'! changeCursor: aCursor "The current cursor should be set to be aCursor." sensor currentCursor ~~ aCursor ifTrue: [aCursor show]! ! !ScrollController methodsFor: 'cursor'! markerContainsCursor "Answer whether the gray area inside the scroll bar area contains the cursor." ^marker inside containsPoint: sensor cursorPoint! ! !ScrollController methodsFor: 'cursor'! menuBarContainsCursor "Answer whether the cursor is anywhere within the menu bar area." ^ menuBar notNil and: [menuBar containsPoint: sensor cursorPoint]! ! !ScrollController methodsFor: 'cursor'! scrollBarContainsCursor "Answer whether the cursor is anywhere within the scroll bar area." ^scrollBar containsPoint: sensor cursorPoint! ! !ScrollController methodsFor: 'marker adjustment'! computeMarkerRegion "Answer the rectangular area in which the gray area of the scroll bar should be displayed." ^0@0 extent: Preferences scrollBarWidth @ ((view window height asFloat / view boundingBox height * scrollBar inside height) rounded min: scrollBar inside height)! ! !ScrollController methodsFor: 'marker adjustment'! markerDelta ^ marker top - scrollBar inside top - ((view window top - view boundingBox top) asFloat / view boundingBox height asFloat * scrollBar inside height asFloat) rounded! ! !ScrollController methodsFor: 'marker adjustment'! markerRegion: aRectangle "Set the area defined by aRectangle as the marker. Fill it with gray tone." Display fill: marker fillColor: scrollBar insideColor. marker region: aRectangle. marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2) ! ! !ScrollController methodsFor: 'marker adjustment'! moveMarker "The view window has changed. Update the marker." self moveMarker: self markerDelta negated anchorMarker: nil! ! !ScrollController methodsFor: 'marker adjustment'! moveMarker: anInteger anchorMarker: anchorMarker "Update the marker so that is is translated by an amount corresponding to a distance of anInteger, constrained within the boundaries of the scroll bar. If anchorMarker ~= nil, display the border around the area where the marker first went down." Display fill: marker fillColor: scrollBar insideColor. anchorMarker = nil ifFalse: [Display border: anchorMarker width: 1 fillColor: Color gray]. marker _ marker translateBy: 0 @ ((anInteger min: scrollBar inside bottom - marker bottom) max: scrollBar inside top - marker top). marker displayOn: Display! ! !ScrollController methodsFor: 'marker adjustment'! moveMarkerTo: aRectangle "Same as markerRegion: aRectangle; moveMarker, except a no-op if the marker would not move." (aRectangle height = marker height and: [self viewDelta = 0]) ifFalse: [self markerRegion: aRectangle. self moveMarker]! ! !ScrollController methodsFor: 'private'! scrollAbsolute | markerOutline oldY markerForm | self changeCursor: Cursor rightArrow. oldY _ -1. sensor anyButtonPressed ifTrue: [markerOutline _ marker deepCopy. markerForm _ Form fromDisplay: marker. Display fill: marker fillColor: scrollBar insideColor. Display border: markerOutline width: 1 fillColor: Color gray. markerForm follow: [oldY ~= sensor cursorPoint y ifTrue: [oldY _ sensor cursorPoint y. marker _ marker translateBy: 0 @ ((oldY - marker center y min: scrollBar inside bottom - marker bottom) max: scrollBar inside top - marker top). self scrollView]. marker origin] while: [sensor anyButtonPressed]. Display fill: markerOutline fillColor: scrollBar insideColor. self moveMarker]! ! !ScrollController methodsFor: 'private'! scrollDown | markerForm firstTime | self changeCursor: Cursor down. sensor anyButtonPressed ifTrue: [markerForm _ Form fromDisplay: marker. Display fill: marker fillColor: scrollBar insideColor. firstTime _ true. markerForm follow: [self scrollViewDown ifTrue: [marker _ marker translateBy: 0 @ ((self markerDelta negated min: scrollBar inside bottom - marker bottom) max: scrollBar inside top - marker top). firstTime ifTrue: [ "pause before scrolling repeatedly" (Delay forMilliseconds: 250) wait. firstTime _ false. ] ifFalse: [ (Delay forMilliseconds: 50) wait. ]. ]. marker origin] while: [sensor anyButtonPressed]. self moveMarker.]! ! !ScrollController methodsFor: 'private'! scrollUp | markerForm firstTime | self changeCursor: Cursor up. sensor anyButtonPressed ifTrue: [markerForm _ Form fromDisplay: marker. Display fill: marker fillColor: scrollBar insideColor. firstTime _ true. markerForm follow: [self scrollViewUp ifTrue: [marker _ marker translateBy: 0 @ ((self markerDelta negated min: scrollBar inside bottom - marker bottom) max: scrollBar inside top - marker top). firstTime ifTrue: [ "pause before scrolling repeatedly" (Delay forMilliseconds: 250) wait. firstTime _ false. ] ifFalse: [ (Delay forMilliseconds: 50) wait. ]. ]. marker origin] while: [sensor anyButtonPressed]. self moveMarker.]! ! CompositionScanner subclass: #SegmentScanner instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !SegmentScanner methodsFor: 'as yet unclassified' stamp: 'ar 5/18/2000 16:48'! setFont super setFont. "Make a local copy of stop conditions so we don't modify the default" stopConditions == DefaultStopConditions ifTrue:[stopConditions _ stopConditions copy]. stopConditions at: Space asciiValue + 1 put: nil.! ! PopUpMenu subclass: #SelectionMenu instanceVariableNames: 'selections' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !SelectionMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 11:38'! selections ^ selections! ! !SelectionMenu methodsFor: 'accessing' stamp: 'sma 5/28/2000 11:38'! selections: selectionArray selections _ selectionArray! ! !SelectionMenu methodsFor: 'basic control sequence' stamp: 'sma 5/28/2000 15:28'! invokeOn: targetObject "Pop up this menu and return the result of sending to the target object the selector corresponding to the menu item selected by the user. Return nil if no item is selected." | sel | sel _ self startUp. sel = nil ifFalse: [^ targetObject perform: sel]. ^ nil "Example: (SelectionMenu labels: 'sin cos neg' lines: #() selections: #(sin cos negated)) invokeOn: 0.7"! ! !SelectionMenu methodsFor: 'basic control sequence' stamp: 'sw 12/17/2001 17:26'! startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean "Overridden to return value returned by manageMarker. The boolean parameter indicates whether the menu should be given keyboard focus (if in morphic)" | index | index _ super startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean. (selections = nil or: [(index between: 1 and: selections size) not]) ifTrue: [^ nil]. ^ selections at: index! ! !SelectionMenu methodsFor: 'invocation' stamp: 'sw 11/18/2002 16:24'! invokeOn: targetObject orSendTo: anObject "Pop up the receiver, obtaining a selector; return the result of having the target object perform the selector. If it dos not understand the selector, give the alternate object a chance" | aSelector | ^ (aSelector _ self startUp) ifNotNil: [(targetObject respondsTo: aSelector) ifTrue: [targetObject perform: aSelector] ifFalse: [anObject perform: aSelector]]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SelectionMenu class instanceVariableNames: ''! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sw 11/8/1999 17:52'! fromArray: anArray "Construct a menu from anArray. The elements of anArray must be either: * A pair of the form: <label> <selector> or * The 'dash' (or 'minus sign') symbol Refer to the example at the bottom of the method" | labelList lines selections anIndex | labelList _ OrderedCollection new. lines _ OrderedCollection new. selections _ OrderedCollection new. anIndex _ 0. anArray do: [:anElement | anElement size == 1 ifTrue: [(anElement == #-) ifFalse: [self error: 'badly-formed menu constructor']. lines add: anIndex] ifFalse: [anElement size == 2 ifFalse: [self error: 'badly-formed menu constructor']. anIndex _ anIndex + 1. labelList add: anElement first. selections add: anElement second]]. ^ self labelList: labelList lines: lines selections: selections "(SelectionMenu fromArray: #( ('first label' moja) ('second label' mbili) - ('third label' tatu) - ('fourth label' nne) ('fifth label' tano))) startUp"! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:04'! labelList: labelList lines: lines selections: selections ^ (self labelArray: labelList lines: lines) selections: selections! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:04'! labelList: labelList selections: selections ^ self labelList: labelList lines: #() selections: selections! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:09'! labels: labels lines: linesArray "Answer an instance of me whose items are in labels, with lines drawn after each item indexed by linesArray. Labels can be either a string with embedded CRs, or a collection of strings." (labels isKindOf: String) ifTrue: [^ super labels: labels lines: linesArray] ifFalse: [^ super labelArray: labels lines: linesArray]! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:09'! labels: labels lines: linesArray selections: selectionsArray "Answer an instance of me whose items are in labels, with lines drawn after each item indexed by linesArray. Labels can be either a string with embedded CRs, or a collection of strings. Record the given array of selections corresponding to the items in labels." ^ (self labels: labels lines: linesArray) selections: selectionsArray! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:10'! labels: labels selections: selectionsArray "Answer an instance of me whose items are in labels, recording the given array of selections corresponding to the items in labels." ^ self labels: labels lines: #() selections: selectionsArray! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:10'! selections: selectionsArray "Answer an instance of me whose labels and selections are identical." ^ self selections: selectionsArray lines: nil! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'sma 5/28/2000 16:10'! selections: selectionsArray lines: linesArray "Answer an instance of me whose labels and selections are identical." ^ self labelList: (selectionsArray collect: [:each | each asString]) lines: linesArray selections: selectionsArray! ! StringHolder subclass: #SelectorBrowser instanceVariableNames: 'selectorIndex selectorList classListIndex classList' classVariableNames: '' poolDictionaries: '' category: 'Tools-Browser'! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 12/1/2000 10:38'! byExample "The comment in the bottom pane" false ifTrue: [MethodFinder methodFor: #( (4 3) 7 (0 5) 5 (5 5) 10)]. "to keep the method methodFor: from being removed from the system" ^ 'Type a fragment of a selector in the top pane. Accept it. Or, use an example to find a method in the system. Type receiver, args, and answer in the top pane with periods between the items. 3. 4. 7 Or, in this pane, use examples to find a method in the system. Select the line of code and choose "print it". MethodFinder methodFor: #( (4 3) 7 (0 5) 5 (5 5) 10). This will discover (data1 + data2). You supply inputs and answers and the system will find the method. Each inner array is a list of inputs. It contains the receiver and zero or more arguments. For Booleans and any computed arguments, use brace notation. MethodFinder methodFor: { {1. 3}. true. {20. 10}. false}. This will discover the expressions (data1 < data2), (data2 > data1), and many others. MethodFinder methodFor: { {''29 Apr 1999'' asDate}. ''Thursday''. {''30 Apr 1999'' asDate}. ''Friday'' }. This will discover the expression (data1 weekday) Receiver and arguments do not have to be in the right order. See MethodFinder.verify for more examples.'! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 3/29/1999 22:12'! byExample: newText "Don't save it" ^ true! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/26/1998 14:20'! classList ^ classList! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/26/1998 14:23'! classListIndex ^ classListIndex! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'sw 10/9/1998 08:26'! classListIndex: anInteger classListIndex _ anInteger. classListIndex > 0 ifTrue: [self dependents do: [:dep | ((dep isKindOf: PluggableListView) and: [dep setSelectionSelectorIs: #classListIndex:]) ifTrue: [dep controller controlTerminate]]. Browser fullOnClass: self selectedClass selector: self selectedMessageName. "classListIndex _ 0"] ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/26/1998 14:33'! classListSelectorTitle ^ 'Class List Menu'! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 5/22/2001 21:37'! contents: aString notifying: aController "Take what the user typed and find all selectors containing it" | tokens raw sorted | contents _ aString. classList _ #(). classListIndex _ 0. selectorIndex _ 0. tokens _ contents asString findTokens: ' .'. selectorList _ Cursor wait showWhile: [ tokens size = 1 ifTrue: [raw _ (Symbol selectorsContaining: contents asString). sorted _ raw as: SortedCollection. sorted sortBlock: [:x :y | x asLowercase <= y asLowercase]. sorted asArray] ifFalse: [self quickList]]. "find selectors from a single example of data" self changed: #messageList. self changed: #classList. ^ true! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'sd 4/16/2003 09:45'! implementors | aSelector | (aSelector _ self selectedMessageName) ifNotNil: [self systemNavigation browseAllImplementorsOf: aSelector]! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'di 11/9/1999 10:07'! initialExtent ^ 350@250 ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 1/8/2001 18:21'! listFromResult: resultOC "ResultOC is of the form #('(data1 op data2)' '(...)'). Answer a sorted array." (resultOC first beginsWith: 'no single method') ifTrue: [^ #()]. ^ resultOC sortBy: [:a :b | (a copyFrom: 6 to: a size) < (b copyFrom: 6 to: b size)]. ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'md 11/14/2003 17:19'! markMatchingClasses "If an example is used, mark classes matching the example instance with an asterisk." | unmarkedClassList firstPartOfSelector receiverString receiver | self flag: #mref. "allows for old-fashioned style" "Only 'example' queries can be marked." (contents asString includes: $.) ifFalse: [^ self]. unmarkedClassList _ classList copy. "Get the receiver object of the selected statement in the message list." firstPartOfSelector _ (Scanner new scanTokens: (selectorList at: selectorIndex)) second. receiverString _ (ReadStream on: (selectorList at: selectorIndex)) upToAll: firstPartOfSelector. receiver _ Compiler evaluate: receiverString. unmarkedClassList do: [ :classAndMethod | | class | (classAndMethod isKindOf: MethodReference) ifTrue: [ (receiver isKindOf: classAndMethod actualClass) ifTrue: [ classAndMethod stringVersion: '*', classAndMethod stringVersion. ] ] ifFalse: [ class _ Compiler evaluate: ((ReadStream on: classAndMethod) upToAll: firstPartOfSelector). (receiver isKindOf: class) ifTrue: [ classList add: '*', classAndMethod. classList remove: classAndMethod ] ]. ]. ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/26/1998 14:19'! messageList "Find all the selectors containing what the user typed in." ^ selectorList! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/26/1998 10:58'! messageListIndex "Answer the index of the selected message selector." ^ selectorIndex! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'sd 4/19/2003 12:13'! messageListIndex: anInteger "Set the selected message selector to be the one indexed by anInteger. Find all classes it is in." selectorIndex _ anInteger. selectorIndex = 0 ifTrue: [^ self]. classList _ self systemNavigation allImplementorsOf: self selectedMessageName. self markMatchingClasses. classListIndex _ 0. self changed: #messageListIndex. "update my selection" self changed: #classList! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'sma 2/6/2000 11:42'! messageListKey: aChar from: view "Respond to a command key. Handle (m) and (n) here, else defer to the StringHolder behaviour." aChar == $m ifTrue: [^ self implementors]. aChar == $n ifTrue: [^ self senders]. super messageListKey: aChar from: view ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'BG 10/29/2003 00:38'! open "Create a Browser that lets you type part of a selector, shows a list of selectors, shows the classes of the one you chose, and spwns a full browser on it. SelectorBrowser new open " | selectorListView typeInView topView classListView exampleView | selectorIndex _ classListIndex _ 0. topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" typeInView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. typeInView window: (0@0 extent: 50@14); askBeforeDiscardingEdits: false. topView addSubView: typeInView. selectorListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #selectorMenu: keystroke: #messageListKey:from:. selectorListView menuTitleSelector: #selectorMenuTitle. selectorListView window: (0 @ 0 extent: 50 @ 46). topView addSubView: selectorListView below: typeInView. classListView _ PluggableListView on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: nil "never anything selected" keystroke: #arrowKey:from:. classListView menuTitleSelector: #classListSelectorTitle. classListView window: (0 @ 0 extent: 50 @ 60). topView addSubView: classListView toRightOf: typeInView. exampleView _ PluggableTextView on: self text: #byExample accept: #byExample: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. exampleView window: (0@0 extent: 100@40); askBeforeDiscardingEdits: false. topView addSubView: exampleView below: selectorListView. topView label: 'Method Finder'. "topView minimumSize: 350@250; maximumSize: 350@250." topView subViews do: [:each | each controller]. topView controller open. ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 1/8/2001 18:37'! quickList "Compute the selectors for the single example of receiver and args, in the very top pane" | data result resultArray newExp dataStrings mf dataObjects aa | data _ contents asString. "delete trailing period. This should be fixed in the Parser!!" [data last isSeparator] whileTrue: [data _ data allButLast]. data last = $. ifTrue: [data _ data allButLast]. "Eval" mf _ MethodFinder new. data _ mf cleanInputs: data. "remove common mistakes" dataObjects _ Compiler evaluate: '{', data, '}'. "#( data1 data2 result )" dataStrings _ (Compiler new parse: 'zort ' , data in: Object notifying: nil) block statements allButLast collect: [:node | String streamContents: [:strm | (node isKindOf: MessageNode) ifTrue: [strm nextPut: $(]. node printOn: strm indent: 0. (node isKindOf: MessageNode) ifTrue: [strm nextPut: $)].]]. dataObjects size < 2 ifTrue: [self inform: 'If you are giving an example of receiver, \args, and result, please put periods between the parts.\Otherwise just type one selector fragment' withCRs. ^#()]. dataObjects _ Array with: dataObjects allButLast with: dataObjects last. "#( (data1 data2) result )" result _ mf load: dataObjects; findMessage. (result first beginsWith: 'no single method') ifFalse: [ aa _ self testObjects: dataObjects strings: dataStrings. dataObjects _ aa second. dataStrings _ aa third]. resultArray _ self listFromResult: result. resultArray isEmpty ifTrue: [self inform: result first]. dataStrings size = (dataObjects first size + 1) ifTrue: [resultArray _ resultArray collect: [:expression | newExp _ expression. dataObjects first withIndexDo: [:lit :i | newExp _ newExp copyReplaceAll: 'data', i printString with: (dataStrings at: i)]. newExp, ' --> ', dataStrings last]]. ^ resultArray! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'bf 10/13/1999 11:58'! searchResult: anExternalSearchResult self contents: ''. classList _ #(). classListIndex _ 0. selectorIndex _ 0. selectorList _ self listFromResult: anExternalSearchResult. self changed: #messageList. self changed: #classList. Smalltalk isMorphic ifTrue: [self changed: #contents.]. ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 5/29/2001 14:39'! selectedClass "Answer the currently selected class." | pairString | self flag: #mref. "allows for old-fashioned style" classListIndex = 0 ifTrue: [^nil]. pairString _ classList at: classListIndex. (pairString isKindOf: MethodReference) ifTrue: [ ^pairString actualClass ]. (pairString includes: $*) ifTrue: [pairString _ pairString allButFirst]. MessageSet parse: pairString toClassAndSelector: [:cls :sel | ^ cls].! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 8/27/1998 17:48'! selectedClassName "Answer the name of the currently selected class." classListIndex = 0 ifTrue: [^nil]. ^ self selectedClass name! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'md 11/14/2003 17:21'! selectedMessageName "Answer the name of the currently selected message." | example tokens | selectorIndex = 0 ifTrue: [^nil]. example _ selectorList at: selectorIndex. tokens _ Scanner new scanTokens: example. tokens size = 1 ifTrue: [^ tokens first]. tokens first == #'^' ifTrue: [^ nil]. (tokens second includes: $:) ifTrue: [^ example findSelector]. Symbol hasInterned: tokens second ifTrue: [:aSymbol | ^ aSymbol]. ^ nil! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'mjg 8/19/1999 12:30'! selectorList: anExternalList self contents: ''. classList _ #(). classListIndex _ 0. selectorIndex _ 0. selectorList _ anExternalList. self changed: #messageList. self changed: #classList. Smalltalk isMorphic ifTrue: [self changed: #contents.]. ! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'hh 1/20/2000 00:15'! selectorMenu: aMenu ^ aMenu labels: 'senders (n) implementors (m) copy selector to clipboard' lines: #() selections: #(senders implementors copyName)! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'sw 9/2/1998 16:37'! selectorMenuTitle ^ self selectedMessageName ifNil: ['<no selection>']! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'nk 6/26/2003 21:44'! senders | aSelector | (aSelector _ self selectedMessageName) ifNotNil: [self systemNavigation browseAllCallsOn: aSelector]! ! !SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'tk 1/18/2001 23:15'! testObjects: dataObjects strings: dataStrings | dataObjs dataStrs selectors classes didUnmodifiedAnswer answerMod do ds result ddo dds | "Try to make substitutions in the user's inputs and search for the selector again. 1 no change to answer. 2 answer Array -> OrderedCollection. 2 answer Character -> String 4 answer Symbol or String of len 1 -> Character For each of these, try straight, and try converting args: Character -> String Symbol or String of len 1 -> Character Return array with result, dataObjects, dataStrings. Don't ever do a find on the same set of data twice." dataObjs _ dataObjects. dataStrs _ dataStrings. selectors _ {#asString. #first. #asOrderedCollection}. classes _ {Character. String. Array}. didUnmodifiedAnswer _ false. selectors withIndexDo: [:ansSel :ansInd | "Modify the answer object" answerMod _ false. do _ dataObjs copyTwoLevel. ds _ dataStrs copy. (dataObjs last isKindOf: (classes at: ansInd)) ifTrue: [ ((ansSel ~~ #first) or: [dataObjs last size = 1]) ifTrue: [ do at: do size put: (do last perform: ansSel). "asString" ds at: ds size put: ds last, ' ', ansSel. result _ MethodFinder new load: do; findMessage. (result first beginsWith: 'no single method') ifFalse: [ "found a selector!!" ^ Array with: result first with: do with: ds]. answerMod _ true]]. selectors allButLast withIndexDo: [:argSel :argInd | "Modify an argument object" "for args, no reason to do Array -> OrderedCollection. Identical protocol." didUnmodifiedAnswer not | answerMod ifTrue: [ ddo _ do copyTwoLevel. dds _ ds copy. dataObjs first withIndexDo: [:arg :ind | (arg isKindOf: (classes at: argInd)) ifTrue: [ ((argSel ~~ #first) or: [arg size = 1]) ifTrue: [ ddo first at: ind put: ((ddo first at: ind) perform: argSel). "asString" dds at: ind put: (dds at: ind), ' ', argSel. result _ MethodFinder new load: ddo; findMessage. (result first beginsWith: 'no single method') ifFalse: [ "found a selector!!" ^ Array with: result first with: ddo with: dds] . didUnmodifiedAnswer not & answerMod not ifTrue: [ didUnmodifiedAnswer _ true]. ]]]]]. ]. ^ Array with: 'no single method does that function' with: dataObjs with: dataStrs! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SelectorBrowser class instanceVariableNames: ''! !SelectorBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:01'! initialize self registerInFlapsRegistry. ! ! !SelectorBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 11:03'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(SelectorBrowser prototypicalToolWindow 'Method Finder' 'A tool for discovering methods by providing sample values for arguments and results') forFlapNamed: 'Tools'] ! ! !SelectorBrowser class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:40'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! LeafNode subclass: #SelectorNode instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !SelectorNode commentStamp: '<historical>' prior: 0! I am a parse tree leaf representing a selector.! !SelectorNode methodsFor: 'code generation'! emit: stack args: nArgs on: strm self emit: stack args: nArgs on: strm super: false! ! !SelectorNode methodsFor: 'code generation'! emit: stack args: nArgs on: aStream super: supered | index | stack pop: nArgs. (supered not and: [code - Send < SendLimit and: [nArgs < 3]]) ifTrue: ["short send" code < Send ifTrue: [^ aStream nextPut: code "special"] ifFalse: [^ aStream nextPut: nArgs * 16 + code]]. index _ code < 256 ifTrue: [code - Send] ifFalse: [code \\ 256]. (index <= 31 and: [nArgs <= 7]) ifTrue: ["extended (2-byte) send [131 and 133]" aStream nextPut: SendLong + (supered ifTrue: [2] ifFalse: [0]). ^ aStream nextPut: nArgs * 32 + index]. (supered not and: [index <= 63 and: [nArgs <= 3]]) ifTrue: ["new extended (2-byte) send [134]" aStream nextPut: SendLong2. ^ aStream nextPut: nArgs * 64 + index]. "long (3-byte) send" aStream nextPut: DblExtDoAll. aStream nextPut: nArgs + (supered ifTrue: [32] ifFalse: [0]). aStream nextPut: index! ! !SelectorNode methodsFor: 'code generation' stamp: 'di 1/7/2000 12:32'! size: encoder args: nArgs super: supered | index | self reserve: encoder. (supered not and: [code - Send < SendLimit and: [nArgs < 3]]) ifTrue: [^1]. "short send" (supered and: [code < Send]) ifTrue: ["super special:" code _ self code: (encoder sharableLitIndex: key) type: 5]. index _ code < 256 ifTrue: [code - Send] ifFalse: [code \\ 256]. (index <= 31 and: [nArgs <= 7]) ifTrue: [^ 2]. "medium send" (supered not and: [index <= 63 and: [nArgs <= 3]]) ifTrue: [^ 2]. "new medium send" ^ 3 "long send"! ! !SelectorNode methodsFor: 'printing' stamp: 'di 11/8/2000 10:04'! printOn: aStream indent: level aStream withStyleFor: #keyword do: [key == nil ifTrue: [aStream nextPutAll: '<key==nil>'] ifFalse: [aStream nextPutAll: key]]! ! !SelectorNode methodsFor: 'inappropriate'! emitForEffect: stack on: strm self shouldNotImplement! ! !SelectorNode methodsFor: 'inappropriate'! emitForValue: stack on: strm self shouldNotImplement! ! !SelectorNode methodsFor: 'inappropriate'! sizeForEffect: encoder self shouldNotImplement! ! !SelectorNode methodsFor: 'inappropriate'! sizeForValue: encoder self shouldNotImplement! ! !SelectorNode methodsFor: 'testing'! isPvtSelector "Answer if this selector node is a private message selector." ^key isPvtSelector! ! LinkedList subclass: #Semaphore instanceVariableNames: 'excessSignals' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Processes'! !Semaphore commentStamp: '<historical>' prior: 0! 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.! !Semaphore methodsFor: 'initialize-release'! initSignals "Consume any excess signals the receiver may have accumulated." excessSignals _ 0.! ! !Semaphore methodsFor: 'initialize-release'! terminateProcess "Terminate the process waiting on this semaphore, if any." self isEmpty ifFalse: [ self removeFirst terminate ].! ! !Semaphore methodsFor: 'communication'! signal "Primitive. Send a signal through the receiver. If one or more processes have been suspended trying to receive a signal, allow the first one to proceed. If no process is waiting, remember the excess signal. Essential. See Object documentation whatIsAPrimitive." <primitive: 85> self primitiveFailed "self isEmpty ifTrue: [excessSignals _ excessSignals+1] ifFalse: [Processor resume: self removeFirstLink]" ! ! !Semaphore methodsFor: 'communication'! wait "Primitive. The active Process must receive a signal through the receiver before proceeding. If no signal has been sent, the active Process will be suspended until one is sent. Essential. See Object documentation whatIsAPrimitive." <primitive: 86> self primitiveFailed "excessSignals>0 ifTrue: [excessSignals _ excessSignals-1] ifFalse: [self addLastLink: Processor activeProcess suspend]" ! ! !Semaphore methodsFor: 'mutual exclusion' stamp: 'mir 9/22/2001 10:54'! critical: mutuallyExcludedBlock "Evaluate mutuallyExcludedBlock only if the receiver is not currently in the process of running the critical: message. If the receiver is, evaluate mutuallyExcludedBlock after the other critical: message is finished." | blockValue | self wait. [blockValue _ mutuallyExcludedBlock value] ensure: [self signal]. ^blockValue! ! !Semaphore methodsFor: 'mutual exclusion' stamp: 'ar 10/8/1998 11:16'! critical: mutuallyExcludedBlock ifError: errorBlock "Evaluate mutuallyExcludedBlock only if the receiver is not currently in the process of running the critical: message. If the receiver is, evaluate mutuallyExcludedBlock after the other critical: message is finished." | blockValue hasError errMsg errRcvr | self wait. hasError _ false. blockValue _ [mutuallyExcludedBlock value] ifError:[:msg :rcvr| hasError _ true. errMsg _ msg. errRcvr _ rcvr]. hasError ifTrue:[ self signal. ^errorBlock value: errMsg value: errRcvr]. self signal. ^blockValue! ! !Semaphore methodsFor: 'comparing' stamp: 'sma 4/22/2000 18:48'! = anObject ^ self == anObject! ! !Semaphore methodsFor: 'comparing' stamp: 'sma 4/22/2000 18:48'! hash ^ self identityHash! ! !Semaphore methodsFor: 'testing' stamp: 'ar 3/2/2001 16:51'! isSignaled "Return true if this semaphore is currently signaled" ^excessSignals > 0! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Semaphore class instanceVariableNames: ''! !Semaphore class methodsFor: 'instance creation'! forMutualExclusion "Answer an instance of me that contains a single signal. This new instance can now be used for mutual exclusion (see the critical: message to Semaphore)." ^self new signal! ! !Semaphore class methodsFor: 'instance creation'! new "Answer a new instance of Semaphore that contains no signals." ^self basicNew initSignals! ! Collection subclass: #SequenceableCollection instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Abstract'! !SequenceableCollection commentStamp: '<historical>' prior: 0! 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.! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 18:00'! after: target "Answer the element after target. Raise an error if target is not in the receiver, or if there are no elements after it." ^ self after: target ifAbsent: [self errorNotFound: target]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 18:02'! after: target ifAbsent: exceptionBlock "Answer the element after target. Answer the result of evaluation the exceptionBlock if target is not in the receiver, or if there are no elements after it." | index | index _ self indexOf: target. ^ index == 0 ifTrue: [exceptionBlock value] ifFalse: [index = self size ifTrue: [self errorLastObject: target] ifFalse: [self at: index + 1]]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:34'! allButFirst "Answer a copy of the receiver containing all but the first element. Raise an error if there are not enough elements." ^ self allButFirst: 1! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:35'! allButFirst: n "Answer a copy of the receiver containing all but the first n elements. Raise an error if there are not enough elements." ^ self copyFrom: n + 1 to: self size! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:35'! allButLast "Answer a copy of the receiver containing all but the last element. Raise an error if there are not enough elements." ^ self allButLast: 1! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:35'! allButLast: n "Answer a copy of the receiver containing all but the last n elements. Raise an error if there are not enough elements." ^ self copyFrom: 1 to: self size - n! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:33'! anyOne ^ self first! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:11'! at: index ifAbsent: exceptionBlock "Answer the element at my position index. If I do not contain an element at index, answer the result of evaluating the argument, exceptionBlock." (index between: 1 and: self size) ifTrue: [^ self at: index]. ^ exceptionBlock value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'raok 11/22/2002 12:34'! at: index incrementBy: value ^self at: index put: (self at: index) + value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'apb 11/4/2000 22:51'! atAll: indexArray "Answer a new collection like the receiver which contains all elements of the receiver at the indices of indexArray." "#('one' 'two' 'three' 'four') atAll: #(3 2 4)" | newCollection | newCollection _ self species ofSize: indexArray size. 1 to: indexArray size do: [:index | newCollection at: index put: (self at: (indexArray at: index))]. ^ newCollection! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:17'! atAll: aCollection put: anObject "Put anObject at every index specified by the elements of aCollection." aCollection do: [:index | self at: index put: anObject]. ^ anObject! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:18'! atAll: indexArray putAll: valueArray "Store the elements of valueArray into the slots of this collection selected by indexArray." indexArray with: valueArray do: [:index :value | self at: index put: value]. ^ valueArray! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:45'! atAllPut: anObject "Put anObject at every one of the receiver's indices." | size | (size _ self size) > 26 "first method faster from 27 accesses and on" ifTrue: [self from: 1 to: size put: anObject] ifFalse: [1 to: size do: [:index | self at: index put: anObject]]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ajh 6/27/2002 17:53'! atLast: indexFromEnd "Return element at indexFromEnd from the last position. atLast: 1, returns the last element" ^ self atLast: indexFromEnd ifAbsent: [self errorIndexOutOfRange]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ajh 6/27/2002 17:52'! atLast: indexFromEnd ifAbsent: block "Return element at indexFromEnd from the last position. atLast: 1 ifAbsent: [] returns the last element" ^ self at: self size + 1 - indexFromEnd ifAbsent: block! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ajh 6/27/2002 18:10'! atLast: indexFromEnd put: obj "Set the element at indexFromEnd from the last position. atLast: 1 put: obj, sets the last element" ^ self at: self size + 1 - indexFromEnd put: obj! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'di 11/6/1998 14:32'! atPin: index "Return the index'th element of me if possible. Return the first or last element if index is out of bounds." index < 1 ifTrue: [^ self first]. index > self size ifTrue: [^ self last]. ^ self at: index! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 12:50'! atRandom: aGenerator "Answer a random element of the receiver. Uses aGenerator which should be kept by the user in a variable and used 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." ^ self at: (aGenerator nextInt: self size)! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:51'! atWrap: index "Answer the index'th element of the receiver. If index is out of bounds, let it wrap around from the end to the beginning until it is in bounds." ^ self at: index - 1 \\ self size + 1! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:52'! atWrap: index put: value "Store value into the index'th element of the receiver. If index is out of bounds, let it wrap around from the end to the beginning until it is in bounds. Answer value." ^ self at: index - 1 \\ self size + 1 put: value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 18:04'! before: target "Answer the receiver's element immediately before target. Raise an error if target is not an element of the receiver, or if there are no elements before it (i.e. it is the first element)." ^ self before: target ifAbsent: [self errorNotFound: target]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 18:06'! before: target ifAbsent: exceptionBlock "Answer the receiver's element immediately before target. Answer the result of evaluating the exceptionBlock if target is not an element of the receiver, or if there are no elements before it." | index | index _ self indexOf: target. ^ index == 0 ifTrue: [exceptionBlock value] ifFalse: [index == 1 ifTrue: [self errorFirstObject: target] ifFalse: [self at: index - 1]]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sw 9/8/2000 11:23'! eighth "Answer the eighth element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 8! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:57'! fifth "Answer the fifth element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 5! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'di 6/2/2000 09:16'! first "Answer the first element of the receiver. Raise an error if the collection is empty." self size = 0 ifTrue: [self errorEmptyCollection]. ^ self at: 1! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:31'! first: n "Answer the first n elements of the receiver. Raise an error if there are not enough elements." ^ self copyFrom: 1 to: n! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:58'! fourth "Answer the fourth element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 4! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'SqR 10/30/2000 22:06'! from: startIndex to: endIndex put: anObject "Put anObject in all indexes between startIndex and endIndex. Very fast. Faster than to:do: for more than 26 positions. Answer anObject" | written toWrite thisWrite | startIndex > endIndex ifTrue: [^self]. self at: startIndex put: anObject. written _ 1. toWrite _ endIndex - startIndex + 1. [written < toWrite] whileTrue: [ thisWrite _ written min: toWrite - written. self replaceFrom: startIndex + written to: startIndex + written + thisWrite - 1 with: self startingAt: startIndex. written _ written + thisWrite ]. ^anObject! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 8/14/1998 21:20'! identityIndexOf: anElement "Answer the index of anElement within the receiver. If the receiver does not contain anElement, answer 0." ^self identityIndexOf: anElement ifAbsent: [0]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 8/14/1998 21:21'! identityIndexOf: anElement ifAbsent: exceptionBlock "Answer the index of anElement within the receiver. If the receiver does not contain anElement, answer the result of evaluating the argument, exceptionBlock." 1 to: self size do: [:i | (self at: i) == anElement ifTrue: [^ i]]. ^ exceptionBlock value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:46'! indexOf: anElement "Answer the index of the first occurence of anElement within the receiver. If the receiver does not contain anElement, answer 0." ^ self indexOf: anElement ifAbsent: [0]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:47'! indexOf: anElement ifAbsent: exceptionBlock "Answer the index of the first occurence of anElement within the receiver. If the receiver does not contain anElement, answer the result of evaluating the argument, exceptionBlock." ^ self indexOf: anElement startingAt: 1 ifAbsent: exceptionBlock! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:47'! indexOf: anElement startingAt: start ifAbsent: exceptionBlock "Answer the index of the first occurence of anElement after start within the receiver. If the receiver does not contain anElement, answer the result of evaluating the argument, exceptionBlock." start to: self size do: [:index | (self at: index) = anElement ifTrue: [^ index]]. ^ exceptionBlock value! ! !SequenceableCollection methodsFor: 'accessing'! indexOfSubCollection: aSubCollection startingAt: anIndex "Answer the index of the receiver's first element, such that that element equals the first element of aSubCollection, and the next elements equal the rest of the elements of aSubCollection. Begin the search at element anIndex of the receiver. If no such match is found, answer 0." ^self indexOfSubCollection: aSubCollection startingAt: anIndex ifAbsent: [0]! ! !SequenceableCollection methodsFor: 'accessing'! indexOfSubCollection: sub startingAt: start ifAbsent: exceptionBlock "Answer the index of the receiver's first element, such that that element equals the first element of sub, and the next elements equal the rest of the elements of sub. Begin the search at element start of the receiver. If no such match is found, answer the result of evaluating argument, exceptionBlock." | first index | sub isEmpty ifTrue: [^ exceptionBlock value]. first _ sub first. start to: self size - sub size + 1 do: [:startIndex | (self at: startIndex) = first ifTrue: [index _ 1. [(self at: startIndex+index-1) = (sub at: index)] whileTrue: [index = sub size ifTrue: [^startIndex]. index _ index+1]]]. ^ exceptionBlock value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:43'! integerAt: index "Return the integer at the given index" ^self at: index! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 3/3/2001 22:43'! integerAt: index put: value "Return the integer at the given index" ^self at: index put: value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'di 6/2/2000 09:15'! last "Answer the last element of the receiver. Raise an error if the collection is empty." | size | (size _ self size) = 0 ifTrue: [self errorEmptyCollection]. ^ self at: size! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 6/1/2000 15:30'! last: n "Answer the last n elements of the receiver. Raise an error if there are not enough elements." | size | size _ self size. ^ self copyFrom: size - n + 1 to: size! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 12/16/2001 01:06'! lastIndexOf: anElement "Answer the index of the last occurence of anElement within the receiver. If the receiver does not contain anElement, answer 0." ^ self lastIndexOf: anElement startingAt: self size ifAbsent: [0]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 12/16/2001 01:06'! lastIndexOf: anElement ifAbsent: exceptionBlock "Answer the index of the last occurence of anElement within the receiver. If the receiver does not contain anElement, answer the result of evaluating the argument, exceptionBlock." ^self lastIndexOf: anElement startingAt: self size ifAbsent: exceptionBlock! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 12/16/2001 01:05'! lastIndexOf: anElement startingAt: lastIndex ifAbsent: exceptionBlock "Answer the index of the last occurence of anElement within the receiver. If the receiver does not contain anElement, answer the result of evaluating the argument, exceptionBlock." lastIndex to: 1 by: -1 do: [:index | (self at: index) = anElement ifTrue: [^ index]]. ^ exceptionBlock value! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'bf 10/13/1999 10:01'! middle "Answer the middle element of the receiver." self emptyCheck. ^ self at: self size // 2 + 1! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sw 9/7/2000 18:10'! ninth "Answer the ninth element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 9! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'ar 1/20/98 16:22'! replaceAll: oldObject with: newObject "Replace all occurences of oldObject with newObject" | index | index _ self indexOf: oldObject startingAt: 1 ifAbsent: [0]. [index = 0] whileFalse: [self at: index put: newObject. index _ self indexOf: oldObject startingAt: index + 1 ifAbsent: [0]]! ! !SequenceableCollection methodsFor: 'accessing'! replaceFrom: start to: stop with: replacement "This destructively replaces elements from start to stop in the receiver. Answer the receiver itself. Use copyReplaceFrom:to:with: for insertion/deletion which may alter the size of the result." replacement size = (stop - start + 1) ifFalse: [self error: 'Size of replacement doesnt match']. ^self replaceFrom: start to: stop with: replacement startingAt: 1! ! !SequenceableCollection methodsFor: 'accessing'! replaceFrom: start to: stop with: replacement startingAt: repStart "This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the sequenceable collection, replacementCollection. Answer the receiver. No range checks are performed." | index repOff | repOff _ repStart - start. index _ start - 1. [(index _ index + 1) <= stop] whileTrue: [self at: index put: (replacement at: repOff + index)]! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:58'! second "Answer the second element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 2! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sw 9/7/2000 18:11'! seventh "Answer the seventh element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 7! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:59'! sixth "Answer the sixth element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 6! ! !SequenceableCollection methodsFor: 'accessing'! swap: oneIndex with: anotherIndex "Move the element at oneIndex to anotherIndex, and vice-versa." | element | element _ self at: oneIndex. self at: oneIndex put: (self at: anotherIndex). self at: anotherIndex put: element! ! !SequenceableCollection methodsFor: 'accessing' stamp: 'sma 5/12/2000 13:58'! third "Answer the third element of the receiver. Raise an error if there are not enough elements." ^ self checkedAt: 3! ! !SequenceableCollection methodsFor: 'comparing' stamp: 'sma 5/12/2000 14:04'! = otherCollection "Answer true if the receiver is equivalent to the otherCollection. First test for identity, then rule out different species and sizes of collections. As a last resort, examine each element of the receiver and the otherCollection." self == otherCollection ifTrue: [^ true]. self species == otherCollection species ifFalse: [^ false]. ^ self hasEqualElements: otherCollection! ! !SequenceableCollection methodsFor: 'comparing' stamp: 'tk 12/6/2000 11:39'! hasEqualElements: otherCollection "Answer whether the receiver's size is the same as otherCollection's size, and each of the receiver's elements equal the corresponding element of otherCollection. This should probably replace the current definition of #= ." | size | (otherCollection isKindOf: SequenceableCollection) ifFalse: [^ false]. (size _ self size) = otherCollection size ifFalse: [^ false]. 1 to: size do: [:index | (self at: index) = (otherCollection at: index) ifFalse: [^ false]]. ^ true! ! !SequenceableCollection methodsFor: 'comparing' stamp: 'SqR 8/3/2000 13:39'! hash | hash | hash _ self species hash. 1 to: self size do: [:i | hash _ (hash + (self at: i) hash) hashMultiply]. ^hash! ! !SequenceableCollection methodsFor: 'converting' stamp: 'TAG 11/6/1998 15:55'! @ aCollection ^ self with: aCollection collect: [:a :b | a @ b]! ! !SequenceableCollection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:32'! asArray "Answer an Array whose elements are the elements of the receiver." ^ Array withAll: self! ! !SequenceableCollection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:36'! asByteArray "Answer a ByteArray whose elements are the elements of the receiver." ^ ByteArray withAll: self! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ar 3/3/2001 20:06'! asColorArray ^ColorArray withAll: self! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ar 9/14/1998 23:47'! asFloatArray "Answer a FloatArray whose elements are the elements of the receiver, in the same order." | floatArray | floatArray _ FloatArray new: self size. 1 to: self size do:[:i| floatArray at: i put: (self at: i) asFloat ]. ^floatArray! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ar 10/10/1998 16:19'! asIntegerArray "Answer an IntegerArray whose elements are the elements of the receiver, in the same order." | intArray | intArray _ IntegerArray new: self size. 1 to: self size do:[:i| intArray at: i put: (self at: i)]. ^intArray! ! !SequenceableCollection methodsFor: 'converting' stamp: 'djm 11/20/1998 05:44'! asStringWithCr "Convert to a string with returns between items. Elements are usually strings. Useful for labels for PopUpMenus." | labelStream | labelStream _ WriteStream on: (String new: 200). self do: [:each | (each isKindOf: String) ifTrue: [labelStream nextPutAll: each; cr] ifFalse: [each printOn: labelStream. labelStream cr]]. self size > 0 ifTrue: [labelStream skip: -1]. ^ labelStream contents! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ar 10/10/1998 16:20'! asWordArray "Answer a WordArray whose elements are the elements of the receiver, in the same order." | wordArray | wordArray _ WordArray new: self size. 1 to: self size do:[:i| wordArray at: i put: (self at: i)]. ^wordArray! ! !SequenceableCollection methodsFor: 'converting' stamp: 'raok 6/23/2003 12:51'! concatenation |result index| result _ Array new: (self inject: 0 into: [:sum :each | sum + each size]). index _ 0. self do: [:each | each do: [:item | result at: (index _ index+1) put: item]]. ^result! ! !SequenceableCollection methodsFor: 'converting' stamp: 'di 11/6/1998 09:35'! isSequenceable ^ true! ! !SequenceableCollection methodsFor: 'converting' stamp: 'sma 5/12/2000 12:51'! readStream ^ ReadStream on: self! ! !SequenceableCollection methodsFor: 'converting' stamp: 'sma 5/12/2000 17:56'! reverse ^ self reversed! ! !SequenceableCollection methodsFor: 'converting' stamp: 'jm 4/27/98 04:09'! reversed "Answer a copy of the receiver with element order reversed." "Example: 'frog' reversed" | n result src | n _ self size. result _ self species new: n. src _ n + 1. 1 to: n do: [:i | result at: i put: (self at: (src _ src - 1))]. ^ result ! ! !SequenceableCollection methodsFor: 'converting' stamp: 'sma 5/12/2000 12:52'! writeStream ^ WriteStream on: self! ! !SequenceableCollection methodsFor: 'copying' stamp: 'di 1/16/98 16:40'! , otherCollection "Concatenate two Strings or Collections." ^ self copyReplaceFrom: self size + 1 to: self size with: otherCollection " #(2 4 6 8) , #(who do we appreciate) ((2989 printStringBase: 16) copyFrom: 4 to: 6) , ' boy!!' "! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:05'! copyAfter: anElement "Answer a copy of the receiver from after the first occurence of anElement up to the end. If no such element exists, answer an empty copy." ^ self allButFirst: (self indexOf: anElement ifAbsent: [^ self copyEmpty])! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:05'! copyAfterLast: anElement "Answer a copy of the receiver from after the last occurence of anElement up to the end. If no such element exists, answer an empty copy." ^ self allButFirst: (self lastIndexOf: anElement ifAbsent: [^ self copyEmpty])! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:07'! copyEmpty ^ self species new: 0! ! !SequenceableCollection methodsFor: 'copying'! copyFrom: start to: stop "Answer a copy of a subset of the receiver, starting from element at index start until element at index stop." | newSize | newSize _ stop - start + 1. ^(self species new: newSize) replaceFrom: 1 to: newSize with: self startingAt: start! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:06'! copyLast: num "Deprecated. Use #last:" ^ self last: num! ! !SequenceableCollection methodsFor: 'copying'! copyReplaceAll: oldSubstring with: newSubstring "Default is not to do token matching. See also String copyReplaceTokens:with:" ^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: false "'How now brown cow?' copyReplaceAll: 'ow' with: 'ello'" "'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Pile'"! ! !SequenceableCollection methodsFor: 'copying' stamp: 'ar 10/16/2001 19:03'! copyReplaceFrom: start to: stop with: replacementCollection "Answer a copy of the receiver satisfying the following conditions: If stop is less than start, then this is an insertion; stop should be exactly start-1, start = 1 means insert before the first character, start = size+1 means append after last character. Otherwise, this is a replacement; start and stop have to be within the receiver's bounds." | newSequenceableCollection newSize endReplacement | newSize _ self size - (stop - start + 1) + replacementCollection size. endReplacement _ start - 1 + replacementCollection size. newSequenceableCollection _ self species new: newSize. start > 1 ifTrue:[ newSequenceableCollection replaceFrom: 1 to: start - 1 with: self startingAt: 1]. start <= endReplacement ifTrue:[ newSequenceableCollection replaceFrom: start to: endReplacement with: replacementCollection startingAt: 1]. endReplacement < newSize ifTrue:[ newSequenceableCollection replaceFrom: endReplacement + 1 to: newSize with: self startingAt: stop + 1]. ^newSequenceableCollection! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:00'! copyUpTo: anElement "Answer all elements up to but not including anObject. If there is no such object, answer a copy of the receiver." ^ self first: (self indexOf: anElement ifAbsent: [^ self copy]) - 1! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 16:02'! copyUpToLast: anElement "Answer a copy of the receiver from index 1 to the last occurrence of anElement, not including anElement." ^ self first: (self lastIndexOf: anElement ifAbsent: [^ self copy]) - 1! ! !SequenceableCollection methodsFor: 'copying'! copyWith: newElement "Answer a copy of the receiver that is 1 bigger than the receiver and has newElement at the last element." | newIC | newIC _ self species new: self size + 1. newIC replaceFrom: 1 to: self size with: self startingAt: 1. newIC at: newIC size put: newElement. ^newIC! ! !SequenceableCollection methodsFor: 'copying' stamp: 'ajh 9/27/2002 12:09'! copyWithFirst: newElement "Answer a copy of the receiver that is 1 bigger than the receiver with newElement as the first element." | newIC | newIC _ self species ofSize: self size + 1. newIC replaceFrom: 2 to: self size + 1 with: self startingAt: 1. newIC at: 1 put: newElement. ^ newIC! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 6/1/2000 15:38'! copyWithoutFirst "Deprecatd. Return a copy of the receiver which doesn't include the first element." ^ self allButFirst! ! !SequenceableCollection methodsFor: 'copying' stamp: 'rhi 12/6/2001 14:04'! copyWithoutIndex: index "Return a copy containing all elements except the index-th." | copy | copy := self species ofSize: self size - 1. copy replaceFrom: 1 to: index-1 with: self startingAt: 1. copy replaceFrom: index to: copy size with: self startingAt: index+1. ^ copy! ! !SequenceableCollection methodsFor: 'copying' stamp: 'fcs 1/20/2002 16:03'! forceTo: length paddingStartWith: elem "Force the length of the collection to length, padding the beginning of the result if necessary with elem. Note that this makes a copy." | newCollection padLen | newCollection _ self species new: length. padLen _ length - self size max: 0. newCollection from: 1 to: padLen put: elem. newCollection replaceFrom: padLen + 1 to: ((padLen + self size) min: length) with: self startingAt: 1. ^ newCollection! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 4/22/2000 18:01'! forceTo: length paddingWith: elem "Force the length of the collection to length, padding if necessary with elem. Note that this makes a copy." | newCollection copyLen | newCollection _ self species new: length. copyLen _ self size min: length. newCollection replaceFrom: 1 to: copyLen with: self startingAt: 1. newCollection from: copyLen + 1 to: length put: elem. ^ newCollection! ! !SequenceableCollection methodsFor: 'copying'! shallowCopy ^self copyFrom: 1 to: self size! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 5/12/2000 12:36'! shuffled ^ self shuffledBy: Collection randomForPicking "Examples: ($A to: $Z) shuffled "! ! !SequenceableCollection methodsFor: 'copying' stamp: 'djp 10/23/1999 22:12'! shuffledBy: aRandom | copy | copy _ self shallowCopy. copy size to: 1 by: -1 do: [:i | copy swap: i with: ((1 to: i) atRandom: aRandom)]. ^ copy! ! !SequenceableCollection methodsFor: 'copying' stamp: 'sma 4/28/2000 18:34'! sortBy: aBlock "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)." ^ (self asSortedCollection: aBlock) asOrderedCollection! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ajh 8/6/2002 15:03'! allButFirstDo: block 2 to: self size do: [:index | block value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ajh 8/6/2002 15:01'! allButLastDo: block 1 to: self size - 1 do: [:index | block value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'tk 7/30/97 12:41'! asDigitsToPower: anInteger do: aBlock "Repeatedly value aBlock with a single Array. Adjust the collection so that aBlock is presented all (self size raisedTo: anInteger) possible combinations of the receiver's elements taken as digits of an anInteger long number." "(0 to: 1) asDigitsToPower: 4 do: [:each | Transcript cr; show: each printString]" | aCollection | aCollection _ Array new: anInteger. self asDigitsAt: 1 in: aCollection do: aBlock! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:46'! collect: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect the resulting values into a collection like the receiver. Answer the new collection." | newCollection | newCollection _ self species new: self size. 1 to: self size do: [:index | newCollection at: index put: (aBlock value: (self at: index))]. ^ newCollection! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 6/1/2000 11:47'! collect: aBlock from: firstIndex to: lastIndex "Refer to the comment in Collection|collect:." | size result j | size _ lastIndex - firstIndex + 1. result _ self species new: size. j _ firstIndex. 1 to: size do: [:i | result at: i put: (aBlock value: (self at: j)). j _ j + 1]. ^ result! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 7/13/97 09:44'! collectWithIndex: elementAndIndexBlock "Use the new version with consistent naming" ^ self withIndexCollect: elementAndIndexBlock! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'tk 7/30/97 12:52'! combinations: kk atATimeDo: aBlock "Take the items in the receiver, kk at a time, and evaluate the block for each combination. Hand in an array of elements of self as the block argument. Each combination only occurs once, and order of the elements does not matter. There are (self size take: kk) combinations." " 'abcde' combinations: 3 atATimeDo: [:each | Transcript cr; show: each printString]" | aCollection | aCollection _ Array new: kk. self combinationsAt: 1 in: aCollection after: 0 do: aBlock! ! !SequenceableCollection methodsFor: 'enumerating'! do: aBlock "Refer to the comment in Collection|do:." 1 to: self size do: [:index | aBlock value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:56'! do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." 1 to: self size do: [:index | index = 1 ifFalse: [separatorBlock value]. elementBlock value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ar 5/1/1999 05:01'! do: aBlock without: anItem "Enumerate all elements in the receiver. Execute aBlock for those elements that are not equal to the given item" "Refer to the comment in Collection|do:." 1 to: self size do: [:index | anItem = (self at: index) ifFalse:[aBlock value: (self at: index)]]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 7/13/97 09:43'! doWithIndex: elementAndIndexBlock "Use the new version with consistent naming" ^ self withIndexDo: elementAndIndexBlock! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ar 6/3/2000 15:53'! findBinary: aBlock "Search for an element in the receiver using binary search. The argument aBlock is a one-element block returning 0 - if the element is the one searched for <0 - if the search should continue in the first half >0 - if the search should continue in the second half If no matching element is found, raise an error. Examples: #(1 3 5 7 11 15 23) findBinary:[:arg| 11 - arg] " ^self findBinary: aBlock ifNone: [self errorNotFound: aBlock]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ar 6/3/2000 15:52'! findBinary: aBlock ifNone: exceptionBlock "Search for an element in the receiver using binary search. The argument aBlock is a one-element block returning 0 - if the element is the one searched for <0 - if the search should continue in the first half >0 - if the search should continue in the second half If no matching element is found, evaluate exceptionBlock." | index low high test item | low _ 1. high _ self size. [index _ high + low // 2. low > high] whileFalse:[ test _ aBlock value: (item _ self at: index). test = 0 ifTrue:[^item] ifFalse:[test > 0 ifTrue: [low _ index + 1] ifFalse: [high _ index - 1]]]. ^exceptionBlock value! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ar 6/3/2000 15:54'! findBinaryIndex: aBlock "Search for an element in the receiver using binary search. The argument aBlock is a one-element block returning 0 - if the element is the one searched for <0 - if the search should continue in the first half >0 - if the search should continue in the second half If no matching element is found, raise an error. Examples: #(1 3 5 7 11 15 23) findBinaryIndex:[:arg| 11 - arg] " ^self findBinaryIndex: aBlock ifNone: [self errorNotFound: aBlock]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ar 6/3/2000 15:54'! findBinaryIndex: aBlock ifNone: exceptionBlock "Search for an element in the receiver using binary search. The argument aBlock is a one-element block returning 0 - if the element is the one searched for <0 - if the search should continue in the first half >0 - if the search should continue in the second half If no matching element is found, evaluate exceptionBlock." | index low high test | low _ 1. high _ self size. [index _ high + low // 2. low > high] whileFalse:[ test _ aBlock value: (self at: index). test = 0 ifTrue:[^index] ifFalse:[test > 0 ifTrue: [low _ index + 1] ifFalse: [high _ index - 1]]]. ^exceptionBlock value! ! !SequenceableCollection methodsFor: 'enumerating'! findFirst: aBlock "Return the index of my first element for which aBlock evaluates as true." | index | index _ 0. [(index _ index + 1) <= self size] whileTrue: [(aBlock value: (self at: index)) ifTrue: [^index]]. ^ 0! ! !SequenceableCollection methodsFor: 'enumerating'! findLast: aBlock "Return the index of my last element for which aBlock evaluates as true." | index | index _ self size + 1. [(index _ index - 1) >= 1] whileTrue: [(aBlock value: (self at: index)) ifTrue: [^index]]. ^ 0! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 18:11'! from: start to: stop do: aBlock "Evaluate aBlock for all elements between start and stop (inclusive)." start to: stop do: [:index | aBlock value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 5/12/2000 18:13'! keysAndValuesDo: aBlock "Enumerate the receiver with all the keys (aka indices) and values." 1 to: self size do: [:index | aBlock value: index value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 11/12/1998 15:01'! pairsCollect: aBlock "Evaluate aBlock with my elements taken two at a time, and return an Array with the results" ^ (1 to: self size // 2) collect: [:index | aBlock value: (self at: 2 * index - 1) value: (self at: 2 * index)] " #(1 'fred' 2 'charlie' 3 'elmer') pairsCollect: [:a :b | b, ' is number ', a printString] "! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 11/12/1998 15:01'! pairsDo: aBlock "Evaluate aBlock with my elements taken two at a time. If there's an odd number of items, ignore the last one. Allows use of a flattened array for things that naturally group into pairs. See also pairsCollect:" 1 to: self size // 2 do: [:index | aBlock value: (self at: 2 * index - 1) value: (self at: 2 * index)] " #(1 'fred' 2 'charlie' 3 'elmer') pairsDo: [:a :b | Transcript cr; show: b, ' is number ', a printString] "! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ward 7/28/97 09:41'! permutationsDo: aBlock "Repeatly value aBlock with a single copy of the receiver. Reorder the copy so that aBlock is presented all (self size factorial) possible permutations." "(1 to: 4) permutationsDo: [:each | Transcript cr; show: each printString]" self shallowCopy permutationsStartingAt: 1 do: aBlock! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'tk 12/27/2000 09:53'! polynomialEval: thisX | sum valToPower | "Treat myself as the coeficients of a polynomial in X. Evaluate it with thisX. First element is the constant and last is the coeficient for the highest power." " #(1 2 3) polynomialEval: 2 " "is 3*X^2 + 2*X + 1 with X = 2" sum _ self first. valToPower _ thisX. 2 to: self size do: [:ind | sum _ sum + ((self at: ind) * valToPower). valToPower _ valToPower * thisX]. ^ sum! ! !SequenceableCollection methodsFor: 'enumerating'! reverseDo: aBlock "Evaluate aBlock with each of the receiver's elements as the argument, starting with the last element and taking each in sequence up to the first. For SequenceableCollections, this is the reverse of the enumeration for do:." self size to: 1 by: -1 do: [:index | aBlock value: (self at: index)]! ! !SequenceableCollection methodsFor: 'enumerating'! reverseWith: aSequenceableCollection do: aBlock "Evaluate aBlock with each of the receiver's elements, in reverse order, along with the corresponding element, also in reverse order, from aSequencableCollection. " self size ~= aSequenceableCollection size ifTrue: [^ self errorNoMatch]. self size to: 1 by: -1 do: [:index | aBlock value: (self at: index) value: (aSequenceableCollection at: index)]! ! !SequenceableCollection methodsFor: 'enumerating'! select: aBlock "Refer to the comment in Collection|select:." | aStream | aStream _ WriteStream on: (self species new: self size). 1 to: self size do: [:index | (aBlock value: (self at: index)) ifTrue: [aStream nextPut: (self at: index)]]. ^ aStream contents! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'sma 6/1/2000 16:00'! upTo: anObject "Deprecated. Use copyUpTo:" ^ self copyUpTo: anObject! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 8/31/1999 13:13'! with: otherCollection collect: twoArgBlock "Collect and return the result of evaluating twoArgBlock with corresponding elements from this collection and otherCollection." | result | otherCollection size = self size ifFalse: [self error: 'otherCollection must be the same size']. result _ self species new: self size. 1 to: self size do: [:index | result at: index put: (twoArgBlock value: (self at: index) value: (otherCollection at: index))]. ^ result! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 8/3/1999 15:26'! with: otherCollection do: twoArgBlock "Evaluate twoArgBlock with corresponding elements from this collection and otherCollection." otherCollection size = self size ifFalse: [self error: 'otherCollection must be the same size']. 1 to: self size do: [:index | twoArgBlock value: (self at: index) value: (otherCollection at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 5/17/1998 13:34'! withIndexCollect: elementAndIndexBlock "Just like with:collect: except that the iteration index supplies the second argument to the block." | result | result _ self species new: self size. 1 to: self size do: [:index | result at: index put: (elementAndIndexBlock value: (self at: index) value: index)]. ^ result! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'di 7/13/97 09:35'! withIndexDo: elementAndIndexBlock "Just like with:do: except that the iteration index supplies the second argument to the block." 1 to: self size do: [:index | elementAndIndexBlock value: (self at: index) value: index]! ! !SequenceableCollection methodsFor: 'private' stamp: 'tk 7/30/97 12:42'! asDigitsAt: anInteger in: aCollection do: aBlock "(0 to: 1) asDigitsToPower: 4 do: [:each | Transcript cr; show: each printString]" self do: [:each | aCollection at: anInteger put: each. anInteger = aCollection size ifTrue: [aBlock value: aCollection] ifFalse: [self asDigitsAt: anInteger + 1 in: aCollection do: aBlock]].! ! !SequenceableCollection methodsFor: 'private' stamp: 'sma 5/12/2000 13:57'! checkedAt: index index > self size ifTrue: [self error: 'not enough elements']. ^ self at: index! ! !SequenceableCollection methodsFor: 'private' stamp: 'tk 7/30/97 12:42'! combinationsAt: jj in: aCollection after: nn do: aBlock "Choose k of N items and put in aCollection. jj-1 already chosen. Indexes of items are in numerical order, to avoid the same combo being used twice. In this slot, we are allowed to use items in self indexed by nn+1 to self size. nn is the index used for position jj-1." "(1 to: 6) combinationsSize: 3 do: [:each | Transcript cr; show: each printString]" nn+1 to: self size do: [:index | aCollection at: jj put: (self at: index). jj = aCollection size ifTrue: [aBlock value: aCollection] ifFalse: [self combinationsAt: jj + 1 in: aCollection after: index do: aBlock]].! ! !SequenceableCollection methodsFor: 'private' stamp: 'tk 1/7/98 10:57'! copyReplaceAll: oldSubstring with: newSubstring asTokens: ifTokens "Answer a copy of the receiver in which all occurrences of oldSubstring have been replaced by newSubstring. ifTokens (valid for Strings only) specifies that the characters surrounding the recplacement must not be alphanumeric. Bruce Simth, must be incremented by 1 and not newSubstring if ifTokens is true. See example below. " | aString startSearch currentIndex endIndex | (ifTokens and: [(self isKindOf: String) not]) ifTrue: [(self isKindOf: Text) ifFalse: [ self error: 'Token replacement only valid for Strings']]. aString _ self. startSearch _ 1. [(currentIndex _ aString indexOfSubCollection: oldSubstring startingAt: startSearch) > 0] whileTrue: [endIndex _ currentIndex + oldSubstring size - 1. (ifTokens not or: [(currentIndex = 1 or: [(aString at: currentIndex-1) isAlphaNumeric not]) and: [endIndex = aString size or: [(aString at: endIndex+1) isAlphaNumeric not]]]) ifTrue: [aString _ aString copyReplaceFrom: currentIndex to: endIndex with: newSubstring. startSearch _ currentIndex + newSubstring size] ifFalse: [ ifTokens ifTrue: [startSearch _ currentIndex + 1] ifFalse: [startSearch _ currentIndex + newSubstring size]]]. ^ aString "Test case: 'test te string' copyReplaceAll: 'te' with: 'longone' asTokens: true " ! ! !SequenceableCollection methodsFor: 'private' stamp: 'sma 5/12/2000 18:06'! errorFirstObject: anObject self error: 'specified object is first object'! ! !SequenceableCollection methodsFor: 'private' stamp: 'sma 5/12/2000 18:03'! errorLastObject: anObject self error: 'specified object is last object'! ! !SequenceableCollection methodsFor: 'private'! errorOutOfBounds self error: 'indices are out of bounds'! ! !SequenceableCollection methodsFor: 'private' stamp: 'ward 7/28/97 09:38'! permutationsStartingAt: anInteger do: aBlock "#(1 2 3 4) permutationsDo: [:each | Transcript cr; show: each printString]" anInteger > self size ifTrue: [^self]. anInteger = self size ifTrue: [^aBlock value: self]. anInteger to: self size do: [:i | self swap: anInteger with: i. self permutationsStartingAt: anInteger + 1 do: aBlock. self swap: anInteger with: i]! ! !SequenceableCollection methodsFor: 'removing'! remove: oldObject ifAbsent: anExceptionBlock "SequencableCollections cannot implement removing." self shouldNotImplement! ! !SequenceableCollection methodsFor: 'testing' stamp: 'bp 2/23/2004 21:47'! beginsWith: aSequenceableCollection (aSequenceableCollection isEmpty or: [self size < aSequenceableCollection size]) ifTrue: [^false]. aSequenceableCollection withIndexDo: [:each :index | (self at: index) ~= each ifTrue: [^false]]. ^true! ! !SequenceableCollection methodsFor: 'testing' stamp: 'bp 2/23/2004 21:48'! endsWith: aSequenceableCollection | start | (aSequenceableCollection isEmpty or: [self size < aSequenceableCollection size]) ifTrue: [^false]. start _ self size - aSequenceableCollection size. aSequenceableCollection withIndexDo: [:each :index | (self at: start + index) ~= each ifTrue: [^false]]. ^true! ! !SequenceableCollection methodsFor: 'testing' stamp: 'sma 5/12/2000 14:08'! includes: anObject "Answer whether anObject is one of the receiver's elements." ^ (self indexOf: anObject) ~= 0! ! !SequenceableCollection methodsFor: '*packageinfo-base' stamp: 'ab 9/17/2002 01:02'! do: aBlock displayingProgress: aString aString displayProgressAt: Sensor cursorPoint from: 0 to: self size during: [:bar | self withIndexDo: [:each :i | bar value: i. aBlock value: each]]! ! !SequenceableCollection methodsFor: '*connectors-enumerating' stamp: 'nk 12/30/2003 15:39'! groupsOf: n atATimeCollect: aBlock "Evaluate aBlock with my elements taken n at a time. Ignore any leftovers at the end. Allows use of a flattened array for things that naturally group into groups of n. If aBlock has a single argument, pass it an array of n items, otherwise, pass the items as separate arguments. See also pairsDo:" | passArray args | passArray := aBlock numArgs = 1. ^(n to: self size by: n) collect: [:index | args := (self copyFrom: index - n + 1 to: index) asArray. passArray ifTrue: [aBlock value: args] ifFalse: [aBlock valueWithArguments: args]]! ! !SequenceableCollection methodsFor: '*connectors-enumerating' stamp: 'nk 12/30/2003 15:37'! groupsOf: n atATimeDo: aBlock "Evaluate aBlock with my elements taken n at a time. Ignore any leftovers at the end. Allows use of a flattened array for things that naturally group into groups of n. If aBlock has a single argument, pass it an array of n items, otherwise, pass the items as separate arguments. See also pairsDo:" | passArray args | passArray := (aBlock numArgs = 1). n to: self size by: n do: [:index | args := (self copyFrom: index - n + 1 to: index) asArray. passArray ifTrue: [ aBlock value: args ] ifFalse: [ aBlock valueWithArguments: args ]].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SequenceableCollection class instanceVariableNames: ''! !SequenceableCollection class methodsFor: 'stream creation'! streamContents: blockWithArg | stream | stream _ WriteStream on: (self new: 100). blockWithArg value: stream. ^stream contents! ! !SequenceableCollection class methodsFor: 'stream creation' stamp: 'di 6/20/97 09:07'! streamContents: blockWithArg limitedTo: sizeLimit | stream | stream _ LimitedWriteStream on: (self new: (100 min: sizeLimit)). stream setLimit: sizeLimit limitBlock: [^ stream contents]. blockWithArg value: stream. ^ stream contents " String streamContents: [:s | 1000 timesRepeat: [s nextPutAll: 'Junk']] limitedTo: 25 'JunkJunkJunkJunkJunkJunkJ' "! ! Collection subclass: #Set instanceVariableNames: 'tally array' classVariableNames: '' poolDictionaries: '' category: 'Collections-Unordered'! !Set commentStamp: '<historical>' prior: 0! I represent a set of objects without duplicates. I can hold anything that responds to #hash and #=, except for nil. My instances will automatically grow, if necessary, Note that I rely on #=, not #==. If you want a set using #==, use IdentitySet. Instance structure: array An array whose non-nil elements are the elements of the set, and whose nil elements are empty slots. There is always at least one nil. In fact I try to keep my "load" at 75% or less so that hashing will work well. tally The number of elements in the set. The array size is always greater than this. The core operation is #findElementOrNil:, which either finds the position where an object is stored in array, if it is present, or finds a suitable position holding nil, if its argument is not present in array,! !Set methodsFor: 'accessing' stamp: 'ar 4/11/2001 23:01'! atRandom: aGenerator "Answer a random element of the receiver. Uses aGenerator which should be kept by the user in a variable and used 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." | ind | self emptyCheck. ind _ aGenerator nextInt: array size. ind to: array size do:[:i| (array at: i) == nil ifFalse:[^array at: i]]. 1 to: ind do:[:i| (array at: i) == nil ifFalse:[^array at: i]]. self errorEmptyCollection.! ! !Set methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:40'! capacity "Answer the current capacity of the receiver." ^ array size! ! !Set methodsFor: 'accessing' stamp: 'SqR 8/23/2000 13:51'! like: anObject "Answer an object in the receiver that is equal to anObject, nil if no such object is found. Relies heavily on hash properties" | index | ^(index _ self scanFor: anObject) = 0 ifFalse: [array at: index]! ! !Set methodsFor: 'accessing'! size ^ tally! ! !Set methodsFor: 'accessing' stamp: 'sma 5/12/2000 14:34'! someElement "Deprecated. Use anyOne." ^ self anyOne! ! !Set methodsFor: 'adding' stamp: 'sma 5/12/2000 17:28'! add: newObject "Include newObject as one of the receiver's elements, but only if not already present. Answer newObject." | index | newObject ifNil: [self error: 'Sets cannot meaningfully contain nil as an element']. index _ self findElementOrNil: newObject. (array at: index) ifNil: [self atNewIndex: index put: newObject]. ^ newObject! ! !Set methodsFor: 'adding' stamp: 'sma 5/12/2000 17:29'! add: newObject withOccurrences: anInteger ^ self add: newObject! ! !Set methodsFor: 'converting' stamp: 'ar 11/20/1998 16:34'! asSet ^self! ! !Set methodsFor: 'copying' stamp: 'sma 5/12/2000 14:54'! copy ^ self shallowCopy withArray: array shallowCopy! ! !Set methodsFor: 'enumerating' stamp: 'sma 5/12/2000 11:49'! collect: aBlock "Evaluate aBlock with each of the receiver's elements as the argument. Collect the resulting values into a collection like the receiver. Answer the new collection." | newSet | newSet _ Set new: self size. array do: [:each | each ifNotNil: [newSet add: (aBlock value: each)]]. ^ newSet! ! !Set methodsFor: 'enumerating' stamp: 'sma 5/12/2000 14:36'! do: aBlock tally = 0 ifTrue: [^ self]. 1 to: array size do: [:index | | each | (each _ array at: index) ifNotNil: [aBlock value: each]]! ! !Set methodsFor: 'enumerating'! doWithIndex: aBlock2 "Support Set enumeration with a counter, even though not ordered" | index | index _ 0. self do: [:item | aBlock2 value: item value: (index _ index+1)]! ! !Set methodsFor: 'enumerating' stamp: 'jcg 6/7/2003 02:01'! union: aCollection "Answer the set theoretic union of the receiver and aCollection, using the receiver's notion of equality and not side effecting the receiver at all." ^ self copy addAll: aCollection; yourself ! ! !Set methodsFor: 'objects from disk' stamp: 'tk 4/8/1999 13:05'! comeFullyUpOnReload: smartRefStream "Symbols have new hashes in this image." self rehash. "^ self" ! ! !Set methodsFor: 'private'! array ^ array! ! !Set methodsFor: 'private'! atNewIndex: index put: anObject array at: index put: anObject. tally _ tally + 1. self fullCheck! ! !Set methodsFor: 'private' stamp: 'SqR 8/23/2000 14:39'! findElementOrNil: anObject "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." | index | index _ self scanFor: anObject. index > 0 ifTrue: [^index]. "Bad scene. Neither have we found a matching element nor even an empty slot. No hashed set is ever supposed to get completely full." self error: 'There is no free space in this set!!'.! ! !Set methodsFor: 'private' stamp: 'SqR 8/23/2000 14:28'! fixCollisionsFrom: index "The element at index has been removed and replaced by nil. This method moves forward from there, relocating any entries that had been placed below due to collisions with this one" | length oldIndex newIndex element | oldIndex _ index. length _ array size. [oldIndex = length ifTrue: [oldIndex _ 1] ifFalse: [oldIndex _ oldIndex + 1]. (element _ self keyAt: oldIndex) == nil] whileFalse: [newIndex _ self findElementOrNil: element. oldIndex = newIndex ifFalse: [self swap: oldIndex with: newIndex]]! ! !Set methodsFor: 'private' stamp: 'di 11/4/97 20:11'! fullCheck "Keep array at least 1/4 free for decent hash behavior" array size - tally < (array size // 4 max: 1) ifTrue: [self grow]! ! !Set methodsFor: 'private'! grow "Grow the elements array and reinsert the old elements" | oldElements | oldElements _ array. array _ Array new: array size + self growSize. tally _ 0. oldElements do: [:each | each == nil ifFalse: [self noCheckAdd: each]]! ! !Set methodsFor: 'private'! growSize ^ array size max: 2! ! !Set methodsFor: 'private'! init: n "Initialize array to an array size of n" array _ Array new: n. tally _ 0! ! !Set methodsFor: 'private'! keyAt: index "May be overridden by subclasses so that fixCollisions will work" ^ array at: index! ! !Set methodsFor: 'private'! noCheckAdd: anObject array at: (self findElementOrNil: anObject) put: anObject. tally _ tally + 1! ! !Set methodsFor: 'private'! rehash | newSelf | newSelf _ self species new: self size. self do: [:each | newSelf noCheckAdd: each]. array _ newSelf array! ! !Set methodsFor: 'private'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element = anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element = anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !Set methodsFor: 'private'! swap: oneIndex with: otherIndex "May be overridden by subclasses so that fixCollisions will work" array swap: oneIndex with: otherIndex ! ! !Set methodsFor: 'private'! withArray: anArray "private -- for use only in copy" array _ anArray! ! !Set methodsFor: 'removing' stamp: 'sma 5/12/2000 14:45'! copyWithout: oldElement "Answer a copy of the receiver that does not contain any elements equal to oldElement." ^ self copy remove: oldElement ifAbsent: []; yourself! ! !Set methodsFor: 'removing'! remove: oldObject ifAbsent: aBlock | index | index _ self findElementOrNil: oldObject. (array at: index) == nil ifTrue: [ ^ aBlock value ]. array at: index put: nil. tally _ tally - 1. self fixCollisionsFrom: index. ^ oldObject! ! !Set methodsFor: 'testing' stamp: 'tk 11/8/2001 15:35'! = aSet self == aSet ifTrue: [^ true]. "stop recursion" (aSet isKindOf: Set) ifFalse: [^ false]. self size = aSet size ifFalse: [^ false]. self do: [:each | (aSet includes: each) ifFalse: [^ false]]. ^ true! ! !Set methodsFor: 'testing'! includes: anObject ^ (array at: (self findElementOrNil: anObject)) ~~ nil! ! !Set methodsFor: 'testing' stamp: 'sma 5/12/2000 14:46'! occurrencesOf: anObject ^ (self includes: anObject) ifTrue: [1] ifFalse: [0]! ! !Set methodsFor: 'explorer' stamp: 'hg 9/7/2001 11:51'! hasContentsInExplorer ^self isEmpty not! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Set class instanceVariableNames: ''! !Set class methodsFor: 'instance creation'! new ^ self new: 4! ! !Set class methodsFor: 'instance creation'! new: nElements "Create a Set large enough to hold nElements without growing" ^ super new init: (self sizeFor: nElements)! ! !Set class methodsFor: 'instance creation'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." | newCollection | newCollection _ self new: aCollection size. newCollection addAll: aCollection. ^ newCollection " Set newFrom: {1. 2. 3} {1. 2. 3} as: Set "! ! !Set class methodsFor: 'instance creation'! sizeFor: nElements "Large enough size to hold nElements with some slop (see fullCheck)" nElements <= 0 ifTrue: [^ 1]. ^ nElements+1*4//3! ! Object subclass: #SharedPool instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Pools'! !SharedPool commentStamp: '<historical>' prior: 0! A shared pool represents a set of bindings which are accessible to all classes which import the pool in its 'pool dictionaries'. SharedPool is NOT a dictionary but rather a name space. Bindings are represented by 'class variables' - as long as we have no better way to represent them at least.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SharedPool class instanceVariableNames: ''! !SharedPool class methodsFor: 'name lookup' stamp: 'ar 5/18/2003 17:46'! bindingOf: varName "Answer the binding of some variable resolved in the scope of the receiver" | aSymbol binding | aSymbol := varName asSymbol. "First look in classVar dictionary." binding := self classPool bindingOf: aSymbol. binding ifNotNil:[^binding]. "Next look in shared pools." self sharedPools do:[:pool | binding := pool bindingOf: aSymbol. binding ifNotNil:[^binding]. ]. "subclassing and environment are not preserved" ^nil! ! !SharedPool class methodsFor: 'name lookup' stamp: 'ar 5/18/2003 20:33'! bindingsDo: aBlock ^self classPool bindingsDo: aBlock! ! !SharedPool class methodsFor: 'name lookup' stamp: 'ar 5/18/2003 18:14'! classBindingOf: varName "For initialization messages grant the regular scope" ^super bindingOf: varName! ! !SharedPool class methodsFor: 'name lookup' stamp: 'tpr 5/29/2003 18:12'! includesKey: aName "does this pool include aName" ^(self bindingOf: aName) notNil! ! Object subclass: #SharedQueue instanceVariableNames: 'contentsArray readPosition writePosition accessProtect readSynch' classVariableNames: '' poolDictionaries: '' category: 'Collections-Sequenceable'! !SharedQueue commentStamp: '<historical>' prior: 0! 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.! !SharedQueue methodsFor: 'accessing' stamp: 'NS 6/18/2002 11:04'! flush "Throw out all pending contents" accessProtect critical: [ readPosition _ 1. writePosition _ 1. "Reset the read synchronization semaphore" readSynch initSignals].! ! !SharedQueue methodsFor: 'accessing' stamp: 'NS 6/18/2002 11:15'! flushAllSuchThat: aBlock "Remove from the queue all objects that satisfy aBlock." | value newReadPos | accessProtect critical: [ newReadPos _ writePosition. writePosition-1 to: readPosition by: -1 do: [:i | value _ contentsArray at: i. contentsArray at: i put: nil. (aBlock value: value) ifTrue: [ "We take an element out of the queue, and therefore, we need to decrement the readSynch signals" readSynch wait. ] ifFalse: [ newReadPos _ newReadPos - 1. contentsArray at: newReadPos put: value]]. readPosition _ newReadPos]. ^value ! ! !SharedQueue methodsFor: 'accessing'! next "Answer the object that was sent through the receiver first and has not yet been received by anyone. If no object has been sent, suspend the requesting process until one is." | value | readSynch wait. accessProtect critical: [readPosition = writePosition ifTrue: [self error: 'Error in SharedQueue synchronization'. value _ nil] ifFalse: [value _ contentsArray at: readPosition. contentsArray at: readPosition put: nil. readPosition _ readPosition + 1]]. ^value! ! !SharedQueue methodsFor: 'accessing' stamp: 'di 10/1/2001 20:58'! nextOrNilSuchThat: aBlock "Answer the next object that satisfies aBlock, skipping any intermediate objects. If no object has been sent, answer <nil> and leave me intact. NOTA BENE: aBlock MUST NOT contain a non-local return (^)." | value readPos | accessProtect critical: [ value _ nil. readPos _ readPosition. [readPos < writePosition and: [value isNil]] whileTrue: [ value _ contentsArray at: readPos. readPos _ readPos + 1. (aBlock value: value) ifTrue: [ readPosition to: readPos - 1 do: [ :j | contentsArray at: j put: nil. ]. readPosition _ readPos. ] ifFalse: [ value _ nil. ]. ]. readPosition >= writePosition ifTrue: [readSynch initSignals]. ]. ^value "=== q _ SharedQueue new. 1 to: 10 do: [ :i | q nextPut: i]. c _ OrderedCollection new. [ v _ q nextOrNilSuchThat: [ :e | e odd]. v notNil ] whileTrue: [ c add: {v. q size} ]. {c. q} explore ==="! ! !SharedQueue methodsFor: 'accessing'! nextPut: value "Send value through the receiver. If a Process has been suspended waiting to receive a value through the receiver, allow it to proceed." accessProtect critical: [writePosition > contentsArray size ifTrue: [self makeRoomAtEnd]. contentsArray at: writePosition put: value. writePosition _ writePosition + 1]. readSynch signal. ^value! ! !SharedQueue methodsFor: 'accessing'! peek "Answer the object that was sent through the receiver first and has not yet been received by anyone but do not remove it from the receiver. If no object has been sent, suspend the requesting process until one is." | value | accessProtect critical: [readPosition >= writePosition ifTrue: [readPosition _ 1. writePosition _ 1. value _ nil] ifFalse: [value _ contentsArray at: readPosition]]. ^value! ! !SharedQueue methodsFor: 'accessing'! size "Answer the number of objects that have been sent through the receiver and not yet received by anyone." ^writePosition - readPosition! ! !SharedQueue methodsFor: 'testing'! isEmpty "Answer whether any objects have been sent through the receiver and not yet received by anyone." ^readPosition = writePosition! ! !SharedQueue methodsFor: 'private'! init: size contentsArray _ Array new: size. readPosition _ 1. writePosition _ 1. accessProtect _ Semaphore forMutualExclusion. readSynch _ Semaphore new! ! !SharedQueue methodsFor: 'private' stamp: 'sma 4/22/2000 18:04'! makeRoomAtEnd | contentsSize | readPosition = 1 ifTrue: [contentsArray _ contentsArray , (Array new: 10)] ifFalse: [contentsSize _ writePosition - readPosition. "BLT direction ok for this. Lots faster!!!!!!!!!!!! SqR!!!! 4/10/2000 10:47" contentsArray replaceFrom: 1 to: contentsSize with: contentsArray startingAt: readPosition. readPosition _ 1. writePosition _ contentsSize + 1]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SharedQueue class instanceVariableNames: ''! !SharedQueue class methodsFor: 'instance creation'! new "Answer a new instance of SharedQueue that has 10 elements." ^self new: 10! ! !SharedQueue class methodsFor: 'instance creation'! new: anInteger ^super new init: anInteger! ! Model subclass: #SimpleServiceEntry instanceVariableNames: 'provider label selector useLineAfter stateSelector description argumentGetter buttonLabel' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !SimpleServiceEntry commentStamp: '<historical>' prior: 0! I represent a service provider : the service provider label : to be display in a menu selector : to do the service useLineAfter stateSelector : a secondary selector (to be able to query state of the provider for example) description : a description for balloon for example argumentGetter : a selector to get additional arguments with (if selector requres them) buttonLabel : a short label The entire client interface (provided by FileList and other users of the registry) is this (browse #getArgumentsFrom: and the senders of #argumentGetter:): fullName (returns a String with the full filename) dirAndFileName (returns {directory. fileName}) readOnlyStream (returns an open read-only stream) ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'RAA 2/2/2002 08:14'! argumentGetter: aBlock argumentGetter _ aBlock! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sw 2/15/2002 17:53'! buttonLabel "Answer the label to be emblazoned on a button representing the service in a file list, for example" ^ buttonLabel ifNil: [label]! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'dgd 9/1/2003 12:16'! buttonLabel: aString "Set the receiver's buttonLabel, to be used on a button in a tool-pane; this is split out so that a more abbreviated wording can be deployed if desired" buttonLabel := aString translated! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:03'! description "may be used for balloon or other" ^ description ! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:03'! description: aString "may be used for balloon or other" description := aString ! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:10'! extraSelector "normally should not be used directly" ^stateSelector! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:11'! extraSelector: aSymbol stateSelector := aSymbol! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'hg 8/3/2000 13:06'! label ^label! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:38'! provider ^ provider! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'dgd 9/1/2003 12:12'! provider: anObject label: aString selector: aSymbol "basic initialization message" provider := anObject. label := aString translated. selector := aSymbol. stateSelector := #none. description := ''! ! !SimpleServiceEntry methodsFor: 'accessing' stamp: 'sd 1/31/2002 21:09'! selector "normally should not be used directly" ^selector! ! !SimpleServiceEntry methodsFor: 'performing service' stamp: 'RAA 2/2/2002 08:31'! getArgumentsFrom: aProvider argumentGetter ifNil: [^aProvider fullName]. ^argumentGetter value: aProvider! ! !SimpleServiceEntry methodsFor: 'performing service' stamp: 'nk 2/15/2004 16:15'! performServiceFor: anObject "carry out the service I provide" ^selector numArgs = 0 ifTrue: [provider perform: selector] ifFalse: [provider perform: selector with: (self getArgumentsFrom: anObject) ]! ! !SimpleServiceEntry methodsFor: 'performing service' stamp: 'dgd 9/1/2003 12:13'! provider: anObject label: aString selector: aSymbol description: anotherString "basic initialization message" self provider: anObject label: aString selector: aSymbol. stateSelector := #none. description := anotherString translated! ! !SimpleServiceEntry methodsFor: 'performing service' stamp: 'hg 8/1/2000 19:49'! requestSelector "send me this message to ask me to perform my service" ^#performServiceFor: ! ! !SimpleServiceEntry methodsFor: 'services menu' stamp: 'nk 2/15/2004 16:16'! addServiceFor: served toMenu: aMenu aMenu add: self label target: self selector: self requestSelector argument: served. self useLineAfter ifTrue: [ aMenu addLine ].! ! !SimpleServiceEntry methodsFor: 'services menu' stamp: 'hg 8/1/2000 19:53'! useLineAfter ^useLineAfter == true! ! !SimpleServiceEntry methodsFor: 'services menu' stamp: 'hg 8/1/2000 19:54'! useLineAfter: aBoolean useLineAfter _ aBoolean ! ! !SimpleServiceEntry methodsFor: 'extra' stamp: 'nk 6/8/2004 16:42'! performExtraFor: anObject "carry out the extra service I provide" "the stateSelector can be used to ask state of the provider to be reflected in button or other" ^stateSelector numArgs = 0 ifTrue: [provider perform: stateSelector] ifFalse: [provider perform: stateSelector with: (self getArgumentsFrom: anObject) ] ! ! !SimpleServiceEntry methodsFor: 'extra' stamp: 'sd 1/31/2002 21:08'! requestExtraSelector "send me this message to ask me to perform secondary service" ^#performExtraFor: ! ! !SimpleServiceEntry methodsFor: 'printing' stamp: 'nk 10/14/2003 10:04'! printOn: aStream aStream nextPutAll: self class name; nextPutAll: ': ('. self provider notNil ifTrue: [aStream nextPutAll: provider printString]. aStream nextPutAll: ' --- '. self selector notNil ifTrue: [aStream nextPutAll: selector asString]. aStream nextPut: $) ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SimpleServiceEntry class instanceVariableNames: ''! !SimpleServiceEntry class methodsFor: 'instance creation' stamp: 'hg 8/1/2000 18:57'! provider: anObject label: aString selector: aSymbol ^self new provider: anObject label: aString selector: aSymbol! ! !SimpleServiceEntry class methodsFor: 'instance creation' stamp: 'sd 1/31/2002 22:05'! provider: anObject label: aString selector: aSymbol description: anotherString ^self new provider: anObject label: aString selector: aSymbol description: anotherString! ! !SimpleServiceEntry class methodsFor: 'instance creation' stamp: 'sw 2/17/2002 02:48'! provider: anObject label: aString selector: aSymbol description: anotherString buttonLabel: aLabel "Answer a new service object with the given initializations. This variant allows a custom button label to be provided, in order to preserve precious horizontal real-estate in the button pane, while still allowing more descriptive wordings in the popup menu" ^ self new provider: anObject label: aString selector: aSymbol description: anotherString; buttonLabel: aLabel; yourself! ! Integer subclass: #SmallInteger instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !SmallInteger commentStamp: '<historical>' prior: 0! My instances are 31-bit numbers, stored in twos complement form. The allowable range is approximately +- 1 billion (see SmallInteger minVal, maxVal).! !SmallInteger methodsFor: 'arithmetic' stamp: 'di 2/1/1999 21:29'! * aNumber "Primitive. Multiply the receiver by the argument and answer with the result if it is a SmallInteger. Fail if the argument or the result is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 9> ^ super * aNumber! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'di 2/1/1999 21:31'! + aNumber "Primitive. Add the receiver to the argument and answer with the result if it is a SmallInteger. Fail if the argument or the result is not a SmallInteger Essential No Lookup. See Object documentation whatIsAPrimitive." <primitive: 1> ^ super + aNumber! ! !SmallInteger methodsFor: 'arithmetic'! - aNumber "Primitive. Subtract the argument from the receiver and answer with the result if it is a SmallInteger. Fail if the argument or the result is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 2> ^super - aNumber! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'hh 10/3/2000 11:47'! / aNumber "Primitive. This primitive (for /) divides the receiver by the argument and returns the result if the division is exact. Fail if the result is not a whole integer. Fail if the argument is 0 or is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 10> aNumber isZero ifTrue: [^(ZeroDivide dividend: self) signal]. (aNumber isMemberOf: SmallInteger) ifTrue: [^(Fraction numerator: self denominator: aNumber) reduced] ifFalse: [^super / aNumber]! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'tk 11/30/2001 11:55'! // aNumber "Primitive. Divide the receiver by the argument and answer with the result. Round the result down towards negative infinity to make it a whole integer. Fail if the argument is 0 or is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive. " <primitive: 12> ^ super // aNumber "Do with quo: if primitive fails"! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'tk 11/30/2001 11:53'! \\ aNumber "Primitive. Take the receiver modulo the argument. The result is the remainder rounded towards negative infinity, of the receiver divided by the argument Fail if the argument is 0 or is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 11> ^ super \\ aNumber "will use // to compute it if primitive fails"! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'LC 4/22/1998 14:21'! gcd: anInteger "See SmallInteger (Integer) | gcd:" | n m | n _ self. m _ anInteger. [n = 0] whileFalse: [n _ m \\ (m _ n)]. ^ m abs! ! !SmallInteger methodsFor: 'arithmetic' stamp: 'sr 5/28/2000 04:41'! quo: aNumber "Primitive. Divide the receiver by the argument and answer with the result. Round the result down towards zero to make it a whole integer. Fail if the argument is 0 or is not a SmallInteger. Optional. See Object documentation whatIsAPrimitive." <primitive: 13> aNumber = 0 ifTrue: [^ (ZeroDivide dividend: self) signal]. (aNumber isMemberOf: SmallInteger) ifFalse: [^ super quo: aNumber]. (aNumber == -1 and: [self == self class minVal]) ifTrue: ["result is aLargeInteger" ^ self negated]. self primitiveFailed! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'wb 4/28/1998 12:17'! bitAnd: arg "Primitive. Answer an Integer whose bits are the logical OR of the receiver's bits and those of the argument, arg. Numbers are interpreted as having 2's-complement representation. Essential. See Object documentation whatIsAPrimitive." <primitive: 14> self >= 0 ifTrue: [^ arg bitAnd: self]. ^ (self bitInvert bitOr: arg bitInvert) bitInvert! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'di 4/30/1998 10:33'! bitOr: arg "Primitive. Answer an Integer whose bits are the logical OR of the receiver's bits and those of the argument, arg. Numbers are interpreted as having 2's-complement representation. Essential. See Object documentation whatIsAPrimitive." <primitive: 15> self >= 0 ifTrue: [^ arg bitOr: self]. ^ arg < 0 ifTrue: [(self bitInvert bitAnd: arg bitInvert) bitInvert] ifFalse: [(self bitInvert bitClear: arg) bitInvert]! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'wb 4/28/1998 12:17'! bitShift: arg "Primitive. Answer an Integer whose value is the receiver's value shifted left by the number of bits indicated by the argument. Negative arguments shift right. The receiver is interpreted as having 2's-complement representation. Essential. See Object documentation whatIsAPrimitive." <primitive: 17> self >= 0 ifTrue: [^ super bitShift: arg]. ^ arg >= 0 ifTrue: [(self negated bitShift: arg) negated] ifFalse: [(self bitInvert bitShift: arg) bitInvert]! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'wb 4/28/1998 12:17'! bitXor: arg "Primitive. Answer an Integer whose bits are the logical XOR of the receiver's bits and those of the argument, arg. Numbers are interpreted as having 2's-complement representation. Essential. See Object documentation whatIsAPrimitive." <primitive: 16> self >= 0 ifTrue: [^ arg bitXor: self]. ^ arg < 0 ifTrue: [self bitInvert bitXor: arg bitInvert] ifFalse: [(self bitInvert bitXor: arg) bitInvert]! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'SqR 8/3/2000 13:29'! hashMultiply | low | low _ self bitAnd: 16383. ^(16r260D * low + ((16r260D * (self bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:07'! highBit "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. Raise an error if the receiver is negative, since negative integers are defined to have an infinite number of leading 1's in 2's-complement arithmetic. Use >>highBitOfMagnitude if you want to get the highest bit of the magnitude." self < 0 ifTrue: [^ self error: 'highBit is not defined for negative integers']. ^ self highBitOfPositiveReceiver! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'sr 6/8/2000 02:08'! highBitOfMagnitude "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. This method is used for negative SmallIntegers as well, since Squeak's LargeIntegers are sign/magnitude." ^ self abs highBitOfPositiveReceiver! ! !SmallInteger methodsFor: 'bit manipulation' stamp: 'jm 2/19/98 12:11'! lowBit " Answer the index of the low order one bit. 2r00101000 lowBit (Answers: 4) 2r-00101000 lowBit (Answers: 4) First we skip bits in groups of 4, then single bits. While not optimal, this is a good tradeoff; long integer #lowBit always invokes us with bytes." | n result | n := self. n = 0 ifTrue: [ ^ 0 ]. result := 1. [ (n bitAnd: 16rF) = 0 ] whileTrue: [ result := result + 4. n := n bitShift: -4 ]. [ (n bitAnd: 1) = 0 ] whileTrue: [ result := result + 1. n := n bitShift: -1 ]. ^ result! ! !SmallInteger methodsFor: 'testing'! even ^(self bitAnd: 1) = 0! ! !SmallInteger methodsFor: 'testing'! odd ^(self bitAnd: 1) = 1! ! !SmallInteger methodsFor: 'comparing'! < aNumber "Primitive. Compare the receiver with the argument and answer with true if the receiver is less than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 3> ^super < aNumber! ! !SmallInteger methodsFor: 'comparing'! <= aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is less than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive. " <primitive: 5> ^super <= aNumber! ! !SmallInteger methodsFor: 'comparing'! = aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive. " <primitive: 7> ^super = aNumber! ! !SmallInteger methodsFor: 'comparing'! > aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 4> ^super > aNumber! ! !SmallInteger methodsFor: 'comparing'! >= aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 6> ^super >= aNumber! ! !SmallInteger methodsFor: 'comparing'! hash ^self! ! !SmallInteger methodsFor: 'comparing'! identityHash ^self! ! !SmallInteger methodsFor: 'comparing' stamp: 'di 9/27/97 20:32'! identityHashMappedBy: map ^ self! ! !SmallInteger methodsFor: 'comparing'! ~= aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is not equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 8> ^super ~= aNumber! ! !SmallInteger methodsFor: 'copying' stamp: 'tk 6/26/1998 11:34'! clone ! ! !SmallInteger methodsFor: 'copying'! deepCopy! ! !SmallInteger methodsFor: 'copying'! shallowCopy! ! !SmallInteger methodsFor: 'copying' stamp: 'tk 8/19/1998 16:04'! veryDeepCopyWith: deepCopier "Return self. I can't be copied. Do not record me."! ! !SmallInteger methodsFor: 'converting'! asFloat "Primitive. Answer a Float that represents the value of the receiver. Essential. See Object documentation whatIsAPrimitive." <primitive: 40> self primitiveFailed! ! !SmallInteger methodsFor: 'printing' stamp: 'gk 11/26/2003 10:27'! printOn: aStream base: base "Refer to the comment in Integer|printOn:base:." "SmallInteger maxVal printStringBase: 2" | x i digits letters | self < 0 ifTrue: [ aStream nextPut: $-. ^ self negated printOn: aStream base: base]. digits _ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'. base = 10 ifFalse: [aStream print: base; nextPut: $r]. letters _ String new: 32. x _ self. i _ 33. [x >= base] whileTrue: [ letters at: (i _ i - 1) put: (digits at: (x \\ base) + 1). x _ x // base]. letters at: (i _ i - 1) put: (digits at: x + 1). aStream nextPutAll: (letters copyFrom: i to: letters size)! ! !SmallInteger methodsFor: 'printing' stamp: 'RAA 8/24/2001 13:59'! threeDigitName | units answer | self = 0 ifTrue: [^'']. units _ #('one' 'two' 'three' 'four' 'five' 'six' 'seven' 'eight' 'nine' 'ten' 'eleven' 'twelve' 'thirteen' 'fourteen' 'fifteen' 'sixteen' 'seventeen' 'eighteen' 'nineteen'). self > 99 ifTrue: [ answer _ (units at: self // 100),' hundred'. (self \\ 100) = 0 ifFalse: [ answer _ answer,' ',(self \\ 100) threeDigitName ]. ^answer ]. self < 20 ifTrue: [ ^units at: self ]. answer _ #('twenty' 'thirty' 'forty' 'fifty' 'sixty' 'seventy' 'eighty' 'ninety') at: self // 10 - 1. (self \\ 10) = 0 ifFalse: [ answer _ answer,'-',(units at: self \\ 10) ]. ^answer! ! !SmallInteger methodsFor: 'printing' stamp: 'sw 10/26/2000 09:01'! uniqueNameForReference "Answer a nice name by which the receiver can be referred to by other objects. For SmallIntegers, we can actually just use the receiver's own printString, though this is pretty strange in some ways." ^ self asString! ! !SmallInteger methodsFor: 'system primitives'! asOop "Answer an object pointer as an integer, return negative number for SmallInteger" ^ self! ! !SmallInteger methodsFor: 'system primitives' stamp: 'tk 3/24/1999 20:28'! digitAt: n "Answer the value of an indexable field in the receiver. LargePositiveInteger uses bytes of base two number, and each is a 'digit' base 256. Fail if the argument (the index) is not an Integer or is out of bounds." n>4 ifTrue: [^ 0]. self < 0 ifTrue: [self = SmallInteger minVal ifTrue: ["Can't negate minVal -- treat specially" ^ #(0 0 0 64) at: n]. ^ ((0-self) bitShift: (1-n)*8) bitAnd: 16rFF] ifFalse: [^ (self bitShift: (1-n)*8) bitAnd: 16rFF]! ! !SmallInteger methodsFor: 'system primitives' stamp: 'md 6/5/2003 10:42'! digitAt: n put: value "Fails. The digits of a small integer can not be modified." self error: 'You can''t store in a SmallInteger'! ! !SmallInteger methodsFor: 'system primitives'! digitLength "Answer the number of indexable fields in the receiver. This value is the same as the largest legal subscript. Included so that a SmallInteger can behave like a LargePositiveInteger or LargeNegativeInteger." (self < 16r100 and: [self > -16r100]) ifTrue: [^ 1]. (self < 16r10000 and: [self > -16r10000]) ifTrue: [^ 2]. (self < 16r1000000 and: [self > -16r1000000]) ifTrue: [^ 3]. ^ 4! ! !SmallInteger methodsFor: 'system primitives'! instVarAt: i "Small integer has to be specially handled." i = 1 ifTrue: [^self]. self error: 'argument too big for small integer instVarAt:'! ! !SmallInteger methodsFor: 'system primitives' stamp: 'tk 5/14/1999 20:54'! nextInstance "SmallIntegers can't be enumerated this way. There are a finite number of them from from (SmallInteger minVal) to (SmallInteger maxVal), but you'll have to enumerate them yourself with: (SmallInteger minVal) to: (SmallInteger maxVal) do: [:integer | <your code here>]. " self shouldNotImplement ! ! !SmallInteger methodsFor: 'system primitives' stamp: 'je 10/22/2002 12:10'! nextObject "SmallIntegers are immediate objects, and, as such, do not have successors in object memory." self shouldNotImplement ! ! !SmallInteger methodsFor: 'private'! fromString: str radix: radix | maxdigit c val | maxdigit _ radix + (radix > 10 ifTrue: [55 - 1] ifFalse: [48 - 1]). val _ 0. 1 to: str size do: [:i | c _ str at: i. (c < 48 ifFalse: [c > maxdigit]) ifTrue: [^false]. val _ val * radix + (c <= 57 ifTrue: [c - 48] ifFalse: [c < 65 ifTrue: [^false]. c - 55])]. ^val! ! !SmallInteger methodsFor: 'private' stamp: 'sr 6/8/2000 01:14'! highBitOfPositiveReceiver | shifted bitNo | "Answer the index of the high order bit of the receiver, or zero if the receiver is zero. Receiver has to be positive!!" shifted _ self. bitNo _ 0. [shifted < 16] whileFalse: [shifted _ shifted bitShift: -4. bitNo _ bitNo + 4]. [shifted = 0] whileFalse: [shifted _ shifted bitShift: -1. bitNo _ bitNo + 1]. ^ bitNo! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SmallInteger class instanceVariableNames: ''! !SmallInteger class methodsFor: 'instance creation' stamp: 'tk 4/20/1999 14:17'! basicNew self error: 'SmallIntegers can only be created by performing arithmetic'! ! !SmallInteger class methodsFor: 'instance creation' stamp: 'tk 4/20/1999 14:18'! new self basicNew "generates an error"! ! !SmallInteger class methodsFor: 'constants'! maxVal "Answer the maximum value for a SmallInteger." ^ 16r3FFFFFFF! ! !SmallInteger class methodsFor: 'constants'! minVal "Answer the minimum value for a SmallInteger." ^ -16r40000000! ! !SmallInteger class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:04'! ccg: cg generateCoerceToOopFrom: aNode on: aStream cg generateCoerceToSmallIntegerObjectFrom: aNode on: aStream! ! !SmallInteger class methodsFor: 'plugin generation' stamp: 'acg 10/5/1999 06:11'! ccg: cg generateCoerceToValueFrom: aNode on: aStream cg generateCoerceToSmallIntegerValueFrom: aNode on: aStream! ! !SmallInteger class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 17:09'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asIntegerValueFrom: anInteger! ! !SmallInteger class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 11:20'! ccgCanConvertFrom: anObject ^anObject class == self! ! Object subclass: #SmalltalkImage instanceVariableNames: '' classVariableNames: 'LastImageName LastQuitLogPosition LastStats SourceFileVersionString StartupStamp' poolDictionaries: '' category: 'System-Support'! !SmalltalkImage commentStamp: 'sd 7/2/2003 21:50' prior: 0! I represent the SmalltalkImage and partly the VM. Using my current instance you can - get the value of some VM parameters, system arguments, vm profiling, endianess status, external objects,.... - save the image, manage sources As you will notice browsing my code I'm a fat class having still too much responsibility. But this is life. sd-2 July 2003 PS: if someone wants to split me go ahead.! !SmalltalkImage methodsFor: 'endian' stamp: 'sd 7/3/2003 22:05'! endianness | bytes word blt | "What endian-ness is the current hardware? The String '1234' will be stored into a machine word. On BigEndian machines (the Mac), $1 will be the high byte if the word. On LittleEndian machines (the PC), $4 will be the high byte." "SmalltalkImage current endianness" bytes _ ByteArray withAll: #(0 0 0 0). "(1 2 3 4) or (4 3 2 1)" word _ WordArray with: 16r01020304. blt _ (BitBlt toForm: (Form new hackBits: bytes)) sourceForm: (Form new hackBits: word). blt combinationRule: Form over. "store" blt sourceY: 0; destY: 0; height: 1; width: 4. blt sourceX: 0; destX: 0. blt copyBits. "paste the word into the bytes" bytes first = 1 ifTrue: [^ #big]. bytes first = 4 ifTrue: [^ #little]. self error: 'Ted is confused'.! ! !SmalltalkImage methodsFor: 'endian' stamp: 'sd 6/27/2003 23:25'! isBigEndian ^self endianness == #big! ! !SmalltalkImage methodsFor: 'endian' stamp: 'sd 6/27/2003 23:25'! isLittleEndian ^self endianness == #little! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 11/16/2003 11:58'! changeImageNameTo: aString self imageName: aString. LastImageName := self imageName! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 11/16/2003 11:58'! changesName "Answer the local name for the changes file corresponding to the image file name." "Smalltalk changesName" | imName | imName := FileDirectory baseNameFor: (FileDirectory localNameFor: self imageName). ^ imName, FileDirectory dot, 'changes'! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'tpr 12/15/2003 12:09'! fullNameForChangesNamed: aName | newName | newName := FileDirectory baseNameFor: (FileDirectory default fullNameFor: aName). ^newName , FileDirectory dot, FileDirectory changeSuffix.! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'tpr 12/15/2003 12:10'! fullNameForImageNamed: aName | newName | newName := FileDirectory baseNameFor: (FileDirectory default fullNameFor: aName). ^newName , FileDirectory dot, FileDirectory imageSuffix.! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 9/24/2003 12:51'! imageName "Answer the full path name for the current image." "SmalltalkImage current imageName" <primitive: 121> self primitiveFailed! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 10/11/2003 12:05'! imageName: newName "Set the the full path name for the current image. All further snapshots will use this." <primitive: 121> ^ self primitiveFailed! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 9/24/2003 12:43'! sourceFileVersionString ^ SourceFileVersionString! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'ssa 9/3/2008 14:28'! sourcesName "Answer the full path to the version-stable source code" ^ SourceFileVersionString , FileDirectory dot , 'sources'! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'sd 9/24/2003 12:46'! vmPath "Answer the path for the directory containing the Smalltalk virtual machine. Return the empty string if this primitive is not implemented." "SmalltalkImage current vmPath" <primitive: 142> ^ ''! ! !SmalltalkImage methodsFor: 'preferences' stamp: 'sd 6/28/2003 17:33'! setPlatformPreferences "Set some platform specific preferences on system startup" | platform specs | Preferences automaticPlatformSettings ifFalse:[^self]. platform _ self platformName. specs _ #( (soundStopWhenDone false) (soundQuickStart false) ). platform = 'Win32' ifTrue:[ specs _ #( (soundStopWhenDone true) (soundQuickStart false) )]. platform = 'Mac OS' ifTrue:[ specs _ #( (soundStopWhenDone false) (soundQuickStart true) )]. specs do:[:tuple| Preferences setPreference: tuple first toValue: (tuple last == #true). ]. ! ! !SmalltalkImage methodsFor: 'quit' stamp: 'sd 6/28/2003 17:32'! quitPrimitive "Primitive. Exit to another operating system on the host machine, if one exists. All state changes in the object space since the last snapshot are lost. Essential. See Object documentation whatIsAPrimitive." <primitive: 113> self primitiveFailed! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'tpr 12/15/2003 12:18'! getFileNameFromUser | newName | newName := FillInTheBlank request: 'New File Name?' translated initialAnswer: (FileDirectory localNameFor: self imageName). newName isEmpty ifTrue: [^nil]. ((FileDirectory default fileOrDirectoryExists: (self fullNameForImageNamed: newName)) or: [FileDirectory default fileOrDirectoryExists: (self fullNameForChangesNamed: newName)]) ifTrue: [ (self confirm: ('{1} already exists. Overwrite?' translated format: {newName})) ifFalse: [^nil]]. ^newName ! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 14:08'! readDocumentFile "No longer used. Everything is now done in ProjectLauncher." "I do not understand the above comment because this method is still called by other methods in the class SystemDictionary so I moved it here- sd - 16 Nov 03" StartupStamp _ '----STARTUP----', Time dateAndTimeNow printString, ' as ', self imageName. ! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 14:20'! shutDown ^ self closeSourceFiles! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 14:12'! snapshot: save andQuit: quit ^self snapshot: save andQuit: quit embedded: false! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'ssa 9/3/2008 11:13'! snapshot: save andQuit: quit embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil:[ msg _ String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ]]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position ]. self logChange: msg. Transcript cr; show: msg ]. Smalltalk processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. Smalltalk setGCParameters. resuming == true ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 13:58'! snapshotEmbeddedPrimitive <primitive: 247> ^nil "indicates error writing embedded image file"! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 13:59'! snapshotPrimitive "Primitive. Write the current state of the object memory on a file in the same format as the Smalltalk-80 release. The file can later be resumed, returning you to this exact state. Return normally after writing the file. Essential. See Object documentation whatIsAPrimitive." <primitive: 97> ^nil "indicates error writing image file"! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'NS 1/16/2004 15:34'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile _ SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp _ nil. self forceChangesToDisk.! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'sd 11/16/2003 13:12'! closeSourceFiles "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" 1 to: 2 do: [:i | ((SourceFiles at: i) isKindOf: FileStream) ifTrue: [(SourceFiles at: i) close. SourceFiles at: i put: nil]]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'NS 1/27/2004 15:55'! event: anEvent "Hook for SystemChangeNotifier" (anEvent isRemoved and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [ anEvent item acceptsLoggingOfCompilation ifTrue: [self logChange: 'Smalltalk removeClassNamed: #' , anEvent item name]. ]. anEvent isDoIt ifTrue: [self logChange: anEvent item]. (anEvent isRemoved and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [ anEvent itemClass acceptsLoggingOfCompilation ifTrue: [self logChange: anEvent itemClass name , ' removeSelector: #' , anEvent itemSelector]].! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'ssa 9/3/2008 11:25'! forceChangesToDisk "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." | changesFile | changesFile _ SourceFiles at: 2. (changesFile isKindOf: FileStream) ifTrue: [ changesFile flush. true ifTrue:[ changesFile close. changesFile open: changesFile name forWrite: true]. changesFile setToEnd. ]. ! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'sd 11/16/2003 14:02'! lastQuitLogPosition ^ LastQuitLogPosition! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'sd 11/16/2003 14:03'! lastQuitLogPosition: aNumber "should be only use to ensure the transition from SystemDictionary to SmalltalkImage, then be removed" LastQuitLogPosition := aNumber! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'NS 1/16/2004 15:32'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aStringOrText isText ifTrue: [aString _ aStringOrText string] ifFalse: [aString _ aStringOrText]. (aString isMemberOf: String) ifFalse: [self error: 'can''t log this change']. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile _ SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk.! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'sd 11/16/2003 12:00'! openSourceFiles self imageName = LastImageName ifFalse: ["Reset the author initials to blank when the image gets moved" LastImageName _ self imageName. Utilities setAuthorInitials: '']. FileDirectory openSources: self sourcesName andChanges: self changesName forImage: LastImageName. StandardSourceFileArray install! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'tpr 12/15/2003 12:21'! saveAs "Put up the 'saveAs' prompt, obtain a name, and save the image under that new name." | newName | newName _ self getFileNameFromUser. newName isNil ifTrue: [^ self]. (SourceFiles at: 2) ifNotNil: [self closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (self fullNameForChangesNamed: newName)]. self saveImageInFileNamed: (self fullNameForImageNamed: newName)! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'tpr 12/15/2003 16:01'! saveChangesInFileNamed: aString | fullChangesName | fullChangesName _ (FileDirectory default fullNameFor: aString). (FileDirectory default directoryNamed:(FileDirectory dirPathFor: fullChangesName )) assureExistence. FileDirectory default copyFileWithoutOverwriteConfirmationNamed: SmalltalkImage current changesName toFileNamed: fullChangesName. Smalltalk setMacFileInfoOn: fullChangesName.! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'tpr 12/15/2003 15:58'! saveImageInFileNamed: aString | fullImageName | fullImageName _ (FileDirectory default fullNameFor: aString). (FileDirectory default directoryNamed:(FileDirectory dirPathFor: fullImageName )) assureExistence. self changeImageNameTo: fullImageName; closeSourceFiles; openSourceFiles; "so SNAPSHOT appears in new changes file" saveImageSegments; snapshot: true andQuit: false! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'sd 11/16/2003 13:29'! saveImageSegments | haveSegs oldImageSegDir newImageSegDir | haveSegs _ false. Smalltalk at: #ImageSegment ifPresent: [:theClass | (haveSegs _ theClass instanceCount ~= 0) ifTrue: [ oldImageSegDir _ theClass segmentDirectory]]. haveSegs ifTrue: [ Smalltalk at: #ImageSegment ifPresent: [:theClass | newImageSegDir _ theClass segmentDirectory. "create the folder" oldImageSegDir fileNames do: [:theName | "copy all segment files" | imageSegmentName | imageSegmentName _ oldImageSegDir pathName, FileDirectory slash, theName. newImageSegDir copyFileWithoutOverwriteConfirmationNamed: imageSegmentName toFileNamed: theName]]]. ! ! !SmalltalkImage methodsFor: 'system attribute' stamp: 'md 10/26/2003 13:08'! getSystemAttribute: attributeID "Optional. Answer the string for the system attribute with the given integer ID. Answer nil if the given attribute is not defined on this platform. On platforms that support invoking programs from command lines (e.g., Unix), this mechanism can be used to pass command line arguments to programs written in Squeak. By convention, the first command line argument that is not a VM configuration option is considered a 'document' to be filed in. Such a document can add methods and classes, can contain a serialized object, can include code to be executed, or any combination of these. Currently defined attributes include: -1000...-1 - command line arguments that specify VM options 0 - the full path name for currently executing VM (or, on some platforms, just the path name of the VM's directory) 1 - full path name of this image 2 - a Squeak document to open, if any 3...1000 - command line arguments for Squeak programs 1001 - this platform's operating system 1002 - operating system version 1003 - this platform's processor type 1004 - vm version" <primitive: 149> ^ nil! ! !SmalltalkImage methodsFor: 'system attribute' stamp: 'sd 6/27/2003 23:38'! platformName "Return the name of the platform we're running on" ^self getSystemAttribute: 1001! ! !SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:47'! getVMParameters "Answer an Array containing the current values of the VM's internal parameter/metric registers. Each value is stored in the array at the index corresponding to its VM register. (See #vmParameterAt: and #vmParameterAt:put:.)" "SmalltalkImage current getVMParameters" <primitive: 254> self primitiveFailed! ! !SmalltalkImage methodsFor: 'vm parameters' stamp: 'sd 6/27/2003 23:27'! vmParameterAt: parameterIndex put: newValue "parameterIndex is a positive integer corresponding to one of the VM's internal parameter/metric registers. Store newValue (a positive integer) into that register and answer with the previous value that was stored there. Fail if newValue is out of range, if parameterIndex has no corresponding register, or if the corresponding register is read-only." <primitive: 254> self primitiveFailed! ! !SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 7/2/2003 21:45'! textMarkerForShortReport ^ 'Since last view '! ! !SmalltalkImage methodsFor: 'vm statistics' stamp: 'sd 9/30/2003 13:53'! vmStatisticsReportString "StringHolderView open: (StringHolder new contents: SmalltalkImage current vmStatisticsReportString) label: 'VM Statistics'" | params oldSpaceEnd youngSpaceEnd memoryEnd fullGCs fullGCTime incrGCs incrGCTime tenureCount mcMisses mcHits icHits upTime sendCount tms tmSize upTime2 fullGCs2 fullGCTime2 incrGCs2 incrGCTime2 tenureCount2 str | params _ self getVMParameters. oldSpaceEnd _ params at: 1. youngSpaceEnd _ params at: 2. memoryEnd _ params at: 3. fullGCs _ params at: 7. fullGCTime _ params at: 8. incrGCs _ params at: 9. incrGCTime _ params at: 10. tenureCount _ params at: 11. mcMisses _ params at: 15. mcHits _ params at: 16. icHits _ params at: 17. upTime _ Time millisecondClockValue. sendCount _ mcMisses + mcHits + icHits. tms _ TranslatedMethod allSubInstances. tmSize _ tms inject: 0 into: [:sum :tm | sum + (tm size * 4)]. str _ WriteStream on: (String new: 1000). str nextPutAll: 'uptime '; print: (upTime / 1000 / 60 // 60); nextPut: $h; print: (upTime / 1000 / 60 \\ 60) asInteger; nextPut: $m; print: (upTime / 1000 \\ 60) asInteger; nextPut: $s; cr. str nextPutAll: 'memory '; nextPutAll: memoryEnd asStringWithCommas; nextPutAll: ' bytes'; cr. str nextPutAll: ' old '; nextPutAll: oldSpaceEnd asStringWithCommas; nextPutAll: ' bytes ('; print: ((oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: ' young '; nextPutAll: (youngSpaceEnd - oldSpaceEnd) asStringWithCommas; nextPutAll: ' bytes ('; print: ((youngSpaceEnd - oldSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: ' used '; nextPutAll: youngSpaceEnd asStringWithCommas; nextPutAll: ' bytes ('; print: ((youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: ' free '; nextPutAll: (memoryEnd - youngSpaceEnd) asStringWithCommas; nextPutAll: ' bytes ('; print: ((memoryEnd - youngSpaceEnd / memoryEnd * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: 'GCs '; nextPutAll: (fullGCs + incrGCs) asStringWithCommas. fullGCs + incrGCs > 0 ifTrue: [ str nextPutAll: ' ('; print: ((upTime / (fullGCs + incrGCs)) roundTo: 1); nextPutAll: 'ms between GCs)' ]. str cr. str nextPutAll: ' full '; print: fullGCs; nextPutAll: ' totalling '; nextPutAll: fullGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((fullGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime)'. fullGCs = 0 ifFalse: [str nextPutAll: ', avg '; print: ((fullGCTime / fullGCs) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' incr '; print: incrGCs; nextPutAll: ' totalling '; nextPutAll: incrGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((incrGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime), avg '; print: ((incrGCTime / incrGCs) roundTo: 1.0); nextPutAll: 'ms'; cr. str nextPutAll: ' tenures '; nextPutAll: tenureCount asStringWithCommas. tenureCount = 0 ifFalse: [str nextPutAll: ' (avg '; print: (incrGCs / tenureCount) asInteger; nextPutAll: ' GCs/tenure)']. str cr. LastStats ifNil: [LastStats _ Array new: 6] ifNotNil: [ upTime2 _ upTime - (LastStats at: 1). fullGCs2 _ fullGCs - (LastStats at: 2). fullGCTime2 _ fullGCTime - (LastStats at: 3). incrGCs2 _ incrGCs - (LastStats at: 4). incrGCTime2 _ incrGCTime - (LastStats at: 5). tenureCount2 _ tenureCount - (LastStats at: 6). str nextPutAll: self textMarkerForShortReport ; nextPutAll: (fullGCs2 + incrGCs2) asStringWithCommas. fullGCs2 + incrGCs2 > 0 ifTrue: [ str nextPutAll: ' ('; print: ((upTime2 / (fullGCs2 + incrGCs2)) roundTo: 1); nextPutAll: 'ms between GCs)'. ]. str cr. str nextPutAll: ' uptime '; print: ((upTime2 / 1000.0) roundTo: 0.1); nextPutAll: 's'; cr. str nextPutAll: ' full '; print: fullGCs2; nextPutAll: ' totalling '; nextPutAll: fullGCTime2 asStringWithCommas; nextPutAll: 'ms ('; print: ((fullGCTime2 / upTime2 * 100) roundTo: 1.0); nextPutAll: '% uptime)'. fullGCs2 = 0 ifFalse: [str nextPutAll: ', avg '; print: ((fullGCTime2 / fullGCs2) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' incr '; print: incrGCs2; nextPutAll: ' totalling '; nextPutAll: incrGCTime2 asStringWithCommas; nextPutAll: 'ms ('; print: ((incrGCTime2 / upTime2 * 100) roundTo: 1.0); nextPutAll: '% uptime), avg '. incrGCs2 > 0 ifTrue: [ str print: ((incrGCTime2 / incrGCs2) roundTo: 1.0); nextPutAll: 'ms' ]. str cr. str nextPutAll: ' tenures '; nextPutAll: tenureCount2 asStringWithCommas. tenureCount2 = 0 ifFalse: [str nextPutAll: ' (avg '; print: (incrGCs2 / tenureCount2) asInteger; nextPutAll: ' GCs/tenure)']. str cr. ]. LastStats at: 1 put: upTime. LastStats at: 2 put: fullGCs. LastStats at: 3 put: fullGCTime. LastStats at: 4 put: incrGCs. LastStats at: 5 put: incrGCTime. LastStats at: 6 put: tenureCount. sendCount > 0 ifTrue: [ str nextPutAll: 'sends '; nextPutAll: sendCount asStringWithCommas; cr. str nextPutAll: ' full '; nextPutAll: mcMisses asStringWithCommas; nextPutAll: ' ('; print: ((mcMisses / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: ' m-cache '; nextPutAll: mcHits asStringWithCommas; nextPutAll: ' ('; print: ((mcHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr. str nextPutAll: ' i-cache '; nextPutAll: icHits asStringWithCommas; nextPutAll: ' ('; print: ((icHits / sendCount * 100) roundTo: 0.1); nextPutAll: '%)'; cr]. icHits > 0 ifTrue: [ str nextPutAll: 'methods '; nextPutAll: tms size asStringWithCommas; nextPutAll: ' translated'; cr. str nextPutAll: ' size '; nextPutAll: tmSize asStringWithCommas; nextPutAll: ' bytes, avg '; print: ((tmSize / tms size) roundTo: 0.1); nextPutAll: ' bytes/method'; cr. str nextPutAll: ' memory '; print: ((tmSize / youngSpaceEnd * 100) roundTo: 0.1); nextPutAll: '% of used, '; print: ((tmSize / memoryEnd * 100) roundTo: 0.1); nextPutAll: '% of available'; cr]. ^ str contents ! ! !SmalltalkImage methodsFor: 'private source file' stamp: 'sd 9/24/2003 12:42'! sourceFileVersionString: aString SourceFileVersionString := aString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SmalltalkImage class instanceVariableNames: 'current'! !SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 14:28'! current "Note that this could be implemented differently to avoid the test" current isNil ifTrue: [current := self basicNew]. ^ current! ! !SmalltalkImage class methodsFor: 'instance creation' stamp: 'sd 9/30/2003 13:39'! new self error: 'Use current'.! ! !SmalltalkImage class methodsFor: 'class initialization' stamp: 'NS 1/16/2004 16:12'! startUp SystemChangeNotifier uniqueInstance notify: self current ofAllSystemChangesUsing: #event:.! ! OrderedCollection subclass: #SortedCollection instanceVariableNames: 'sortBlock' classVariableNames: '' poolDictionaries: '' category: 'Collections-Sequenceable'! !SortedCollection commentStamp: '<historical>' prior: 0! I represent a collection of objects ordered by some property of the objects themselves. The ordering is specified in a BlockContext.! !SortedCollection methodsFor: 'accessing' stamp: 'sma 4/28/2000 17:47'! at: anInteger put: anObject self shouldNotImplement! ! !SortedCollection methodsFor: 'accessing' stamp: 'tk 3/28/1999 22:55'! median "Return the middle element, or as close as we can get." ^ self at: self size + 1 // 2! ! !SortedCollection methodsFor: 'accessing'! sortBlock "Answer the blockContext which is the criterion for sorting elements of the receiver." ^sortBlock! ! !SortedCollection methodsFor: 'accessing' stamp: 'stp 12/05/1999 07:09'! sortBlock: aBlock "Make the argument, aBlock, be the criterion for ordering elements of the receiver." aBlock ifNotNil: [sortBlock := aBlock fixTemps] ifNil: [sortBlock := aBlock]. "The sortBlock must copy its home context, so as to avoid circularities!!" "Therefore sortBlocks with side effects may not work right" self size > 0 ifTrue: [self reSort]! ! !SortedCollection methodsFor: 'adding' stamp: 'go 4/27/2000 13:19'! add: newObject ^ super insert: newObject before: (self indexForInserting: newObject)! ! !SortedCollection methodsFor: 'adding' stamp: 'sma 4/28/2000 18:35'! addAll: aCollection aCollection size > (self size // 3) ifTrue: [aCollection do: [:each | self addLast: each]. self reSort] ifFalse: [aCollection do: [:each | self add: each]]. ^ aCollection! ! !SortedCollection methodsFor: 'adding' stamp: 'go 4/26/2000 17:26'! addFirst: newObject self shouldNotImplement! ! !SortedCollection methodsFor: 'adding' stamp: 'MPH 10/23/2000 13:31'! copyEmpty "Answer a copy of the receiver without any of the receiver's elements." ^self species sortBlock: sortBlock! ! !SortedCollection methodsFor: 'comparing'! = aSortedCollection "Answer true if my and aSortedCollection's species are the same, and if our blocks are the same, and if our elements are the same." self species = aSortedCollection species ifFalse: [^ false]. sortBlock = aSortedCollection sortBlock ifTrue: [^ super = aSortedCollection] ifFalse: [^ false]! ! !SortedCollection methodsFor: 'copying'! copy | newCollection | newCollection _ self species sortBlock: sortBlock. newCollection addAll: self. ^newCollection! ! !SortedCollection methodsFor: 'enumerating' stamp: 'sma 2/5/2000 15:22'! collect: aBlock "Evaluate aBlock with each of my elements as the argument. Collect the resulting values into an OrderedCollection. Answer the new collection. Override the superclass in order to produce an OrderedCollection instead of a SortedCollection." | newCollection | newCollection _ OrderedCollection new: self size. self do: [:each | newCollection addLast: (aBlock value: each)]. ^ newCollection! ! !SortedCollection methodsFor: 'private' stamp: 'stp 04/23/1999 05:36'! indexForInserting: newObject | index low high | low _ firstIndex. high _ lastIndex. sortBlock isNil ifTrue: [[index _ high + low // 2. low > high] whileFalse: [((array at: index) <= newObject) ifTrue: [low _ index + 1] ifFalse: [high _ index - 1]]] ifFalse: [[index _ high + low // 2. low > high] whileFalse: [(sortBlock value: (array at: index) value: newObject) ifTrue: [low _ index + 1] ifFalse: [high _ index - 1]]]. ^low! ! !SortedCollection methodsFor: 'private' stamp: 'go 4/26/2000 17:17'! insert: anObject before: spot self shouldNotImplement! ! !SortedCollection methodsFor: 'private' stamp: 'sma 4/28/2000 17:46'! reSort self sort: firstIndex to: lastIndex! ! !SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 19:30'! should: a precede: b ^sortBlock ifNil: [a <= b] ifNotNil: [sortBlock value: a value: b] ! ! !SortedCollection methodsFor: 'private' stamp: 'hg 12/17/2001 20:22'! sort: i to: j "Sort elements i through j of self to be nondescending according to sortBlock." | di dij dj tt ij k l n | "The prefix d means the data at that index." (n _ j + 1 - i) <= 1 ifTrue: [^self]. "Nothing to sort." "Sort di,dj." di _ array at: i. dj _ array at: j. (self should: di precede: dj) ifFalse: [array swap: i with: j. tt _ di. di _ dj. dj _ tt]. n > 2 ifTrue: "More than two elements." [ij _ (i + j) // 2. "ij is the midpoint of i and j." dij _ array at: ij. "Sort di,dij,dj. Make dij be their median." (self should: di precede: dij) ifTrue: [(self should: dij precede: dj) ifFalse: [array swap: j with: ij. dij _ dj]] ifFalse: [array swap: i with: ij. dij _ di]. n > 3 ifTrue: "More than three elements." ["Find k>i and l<j such that dk,dij,dl are in reverse order. Swap k and l. Repeat this procedure until k and l pass each other." k _ i. l _ j. [[l _ l - 1. k <= l and: [self should: dij precede: (array at: l)]] whileTrue. "i.e. while dl succeeds dij" [k _ k + 1. k <= l and: [self should: (array at: k) precede: dij]] whileTrue. "i.e. while dij succeeds dk" k <= l] whileTrue: [array swap: k with: l]. "Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk through dj. Sort those two segments." self sort: i to: l. self sort: k to: j]]! ! !SortedCollection methodsFor: 'topological sort' stamp: 'hg 1/2/2002 13:34'! sortTopologically "Plenty of room for increased efficiency in this one." | remaining result pick | remaining _ self asOrderedCollection. result _ OrderedCollection new. [remaining isEmpty] whileFalse: [ pick _ remaining select: [:item | remaining allSatisfy: [:anotherItem | item == anotherItem or: [self should: item precede: anotherItem]]]. pick isEmpty ifTrue: [self error: 'bad topological ordering']. result addAll: pick. remaining removeAll: pick]. ^self copySameFrom: result! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SortedCollection class instanceVariableNames: ''! !SortedCollection class methodsFor: 'instance creation' stamp: 'stp 04/23/1999 05:34'! new: anInteger "The default sorting function is a <= comparison on elements." ^(super new: anInteger) "sortBlock: [:x :y | x <= y]" "nil sortBlock OK"! ! !SortedCollection class methodsFor: 'instance creation'! sortBlock: aBlock "Answer an instance of me such that its elements are sorted according to the criterion specified in aBlock." ^(super new: 10) sortBlock: aBlock! ! AppRegistry subclass: #SoundService instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Applications'! !SoundService commentStamp: 'gk 2/24/2004 23:14' prior: 0! This is the AppRegistry class for the sound system. A sound system offers a small protocol for playing sounds and making beeps and works like a facade towards the rest of Squeak. A sound system is registered in this registry and can be accessed by "SoundService default". This way we decouple the sound system from the rest of Squeak and make it pluggable. It also is a perfect spot to check for the Preference class>>soundsEnabled.! SequenceableCollection subclass: #SourceFileArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !SourceFileArray commentStamp: '<historical>' prior: 0! This class is an abstract superclass for source code access mechanisms. It defines the messages that need to be understood by those subclasses that store and retrieve source chunks on files, over the network or in databases. The first concrete subclass, StandardSourceFileArray, supports access to the traditional sources and changes files. Other subclasses might implement multiple source files for different applications, or access to a network source server.! ]style[(254 23 184)f1,f1LStandardSourceFileArray Comment;,f1! !SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:42'! at: index self subclassResponsibility! ! !SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'! at: index put: aFileStream self subclassResponsibility! ! !SourceFileArray methodsFor: 'accessing' stamp: 'ar 5/17/2000 18:28'! collect: aBlock | copy | copy _ self species new: self size. 1 to: self size do:[:i| copy at: i put: (aBlock value: (self at: i))]. ^copy! ! !SourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/26/2000 21:43'! size self subclassResponsibility! ! !SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'! fileIndexFromSourcePointer: anInteger "Return the index of a source file corresponding to the given source pointer." self subclassResponsibility! ! !SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:00'! filePositionFromSourcePointer: anInteger "Return the position within a source file for the given source pointer." self subclassResponsibility! ! !SourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 22:01'! sourcePointerFromFileIndex: index andPosition: position "Return a sourcePointer encoding the given file index and position" self subclassResponsibility! ! Path subclass: #Spline instanceVariableNames: 'coefficients' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Spline commentStamp: '<historical>' prior: 0! I represent a collection of Points through which a cubic spline curve is fitted.! !Spline methodsFor: 'displaying'! computeCurve "Compute an array for the coefficients." | length extras | length _ self size. extras _ 0. coefficients _ Array new: 8. 1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)]. 1 to: 5 by: 4 do: [:k | 1 to: length do: [:i | (coefficients at: k) at: i put: (k = 1 ifTrue: [(self at: i) x asFloat] ifFalse: [(self at: i) y asFloat])]. 1 to: extras do: [:i | (coefficients at: k) at: length + i put: ((coefficients at: k) at: i + 1)]. self derivs: (coefficients at: k) first: (coefficients at: k + 1) second: (coefficients at: k + 2) third: (coefficients at: k + 3)]. extras > 0 ifTrue: [1 to: 8 do: [:i | coefficients at: i put: ((coefficients at: i) copyFrom: 2 to: length + 1)]]! ! !Spline methodsFor: 'displaying'! displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm "Display the receiver, a spline curve, approximated by straight line segments." | n line t x y x1 x2 x3 y1 y2 y3 | collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point']. line _ Line new. line form: self form. line beginPoint: (x _ (coefficients at: 1) at: 1) rounded @ (y _ (coefficients at: 5) at: 1) rounded. 1 to: (coefficients at: 1) size - 1 do: [:i | "taylor series coefficients" x1 _ (coefficients at: 2) at: i. y1 _ (coefficients at: 6) at: i. x2 _ ((coefficients at: 3) at: i) / 2.0. y2 _ ((coefficients at: 7) at: i) / 2.0. x3 _ ((coefficients at: 4) at: i) / 6.0. y3 _ ((coefficients at: 8) at: i) / 6.0. "guess n" n _ 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3) at: i + 1) abs + ((coefficients at: 7) at: i + 1) abs / 100.0) rounded. 1 to: n - 1 do: [:j | t _ j asFloat / n. line endPoint: (x3 * t + x2 * t + x1 * t + x) rounded @ (y3 * t + y2 * t + y1 * t + y) rounded. line displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm. line beginPoint: line endPoint]. line beginPoint: (x _ (coefficients at: 1) at: i + 1) rounded @ (y _ (coefficients at: 5) at: i + 1) rounded. line displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm]! ! !Spline methodsFor: 'displaying'! displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm "Get the scaled and translated path of newKnots." | newKnots newSpline | newKnots _ aTransformation applyTo: self. newSpline _ Spline new. newKnots do: [:knot | newSpline add: knot]. newSpline form: self form. newSpline displayOn: aDisplayMedium at: 0 @ 0 clippingBox: clipRect rule: anInteger fillColor: aForm! ! !Spline methodsFor: 'private'! derivs: a first: point1 second: point2 third: point3 "Compute the first, second and third derivitives (in coefficients) from the Points in this Path (coefficients at: 1 and coefficients at: 5)." | l v anArray | l _ a size. l < 2 ifTrue: [^self]. l > 2 ifTrue: [v _ Array new: l. v at: 1 put: 4.0. anArray _ Array new: l. anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))). 2 to: l - 2 do: [:i | v at: i put: (4.0 - (1.0 / (v at: (i - 1)))). anArray at: i put: (6.0 * ((a at: i) - ((a at: (i + 1)) * 2.0) + (a at: (i + 2))) - ((anArray at: (i - 1)) / (v at: (i - 1))))]. point2 at: (l - 1) put: ((anArray at: (l - 2)) / (v at: (l - 2))). l - 2 to: 2 by: 0-1 do: [:i | point2 at: i put: ((anArray at: (i - 1)) - (point2 at: (i + 1)) / (v at: (i - 1)))]]. point2 at: 1 put: (point2 at: l put: 0.0). 1 to: l - 1 do: [:i | point1 at: i put: ((a at: (i + 1)) - (a at: i) - ((point2 at: i) * 2.0 + (point2 at: (i + 1)) / 6.0)). point3 at: i put: ((point2 at: (i + 1)) - (point2 at: i))]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Spline class instanceVariableNames: ''! !Spline class methodsFor: 'examples' stamp: '6/8/97 13:55 di'! example "Designate points on the Path by clicking the red button. Terminate by pressing any other button. A curve will be displayed, through the selected points, using a long black form." | splineCurve aForm flag| aForm _ Form extent: 2@2. aForm fillBlack. splineCurve _ Spline new. splineCurve form: aForm. flag _ true. [flag] whileTrue: [Sensor waitButton. Sensor redButtonPressed ifTrue: [splineCurve add: Sensor waitButton. Sensor waitNoButton. aForm displayOn: Display at: splineCurve last] ifFalse: [flag_false]]. splineCurve computeCurve. splineCurve isEmpty ifFalse: [splineCurve displayOn: Display. Sensor waitNoButton]. "Spline example"! ! SelectionMenu subclass: #StandardFileMenu instanceVariableNames: 'canTypeFileName pattern' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !StandardFileMenu commentStamp: '<historical>' prior: 0! I represent a SelectionMenu which operates like a modal dialog for selecting files, somewhat similar to the StandardFile dialogs in MacOS and Java Swing. Try for example, the following: StandardFileMenu oldFile inspect StandardFileMenu oldFileStream inspect StandardFileMenu newFile inspect StandardFileMenu newFileStream inspect! !StandardFileMenu methodsFor: 'menu building' stamp: 'di 5/12/2000 10:31'! directoryNamesString: aDirectory "Answer a string concatenating the directory name strings in aDirectory, each string followed by a '[...]' indicator, and followed by a cr." ^ String streamContents: [:s | aDirectory directoryNames do: [:dn | s nextPutAll: dn withBlanksTrimmed , ' [...]'; cr]] ! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'tk 2/14/2000 14:58'! fileNamesString: aDirectory "Answer a string concatenating the file name strings in aDirectory, each string followed by a cr." ^String streamContents: [:s | aDirectory fileNames do: [:fn | (pattern match: fn) ifTrue: [ s nextPutAll: fn withBlanksTrimmed; cr]]]! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'tk 2/14/2000 14:25'! makeFileMenuFor: aDirectory "Initialize an instance of me to operate on aDirectory" | theMenu | pattern ifNil: [pattern _ '*']. Cursor wait showWhile: [self labels: (self menuLabelsString: aDirectory) font: (MenuStyle fontAt: 1) lines: (self menuLinesArray: aDirectory). theMenu _ self selections: (self menuSelectionsArray: aDirectory)]. ^theMenu! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:57'! menuLabelsString: aDirectory "Answer a menu labels object corresponding to aDirectory" ^ String streamContents: [:s | canTypeFileName ifTrue: [s nextPutAll: 'Enter File Name...'; cr]. s nextPutAll: (self pathPartsString: aDirectory). s nextPutAll: (self directoryNamesString: aDirectory). s nextPutAll: (self fileNamesString: aDirectory). s skip: -1]! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'tpr 11/28/2003 15:12'! menuLinesArray: aDirectory "Answer a menu lines object corresponding to aDirectory" | typeCount nameCnt dirDepth| typeCount _ canTypeFileName ifTrue: [1] ifFalse: [0]. nameCnt _ aDirectory directoryNames size. dirDepth _ aDirectory pathParts size. ^Array streamContents: [:s | canTypeFileName ifTrue: [s nextPut: 1]. s nextPut: dirDepth + typeCount + 1. s nextPut: dirDepth + nameCnt + typeCount + 1]! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'di 5/12/2000 11:01'! menuSelectionsArray: aDirectory "Answer a menu selections object corresponding to aDirectory. The object is an array corresponding to each item, each element itself constituting a two-element array, the first element of which contains a selector to operate on and the second element of which contains the parameters for that selector." |dirSize| dirSize _ aDirectory pathParts size. ^Array streamContents: [:s | canTypeFileName ifTrue: [s nextPut: (StandardFileMenuResult directory: aDirectory name: nil)]. s nextPut: (StandardFileMenuResult directory: (FileDirectory root) name: ''). aDirectory pathParts doWithIndex: [:d :i | s nextPut: (StandardFileMenuResult directory: (self advance: dirSize - i containingDirectoriesFrom: aDirectory) name: '')]. aDirectory directoryNames do: [:dn | s nextPut: (StandardFileMenuResult directory: (FileDirectory on: (aDirectory fullNameFor: dn)) name: '')]. aDirectory fileNames do: [:fn | (pattern match: fn) ifTrue: [ s nextPut: (StandardFileMenuResult directory: aDirectory name: fn)]]]! ! !StandardFileMenu methodsFor: 'menu building' stamp: 'acg 4/15/1999 21:03'! pathPartsString: aDirectory "Answer a string concatenating the path parts strings in aDirectory, each string followed by a cr." ^String streamContents: [:s | s nextPutAll: '[]'; cr. aDirectory pathParts asArray doWithIndex: [:part :i | s next: i put: $ . s nextPutAll: part withBlanksTrimmed; cr]]! ! !StandardFileMenu methodsFor: 'basic control sequences' stamp: 'acg 4/15/1999 21:52'! confirmExistingFiles: aResult |choice| (aResult directory fileExists: aResult name) ifFalse: [^aResult]. choice _ (PopUpMenu labels: 'overwrite that file choose another name cancel') startUpWithCaption: aResult name, ' already exists.'. choice = 1 ifTrue: [ aResult directory deleteFileNamed: aResult name ifAbsent: [^self startUpWithCaption: 'Can''t delete ', aResult name, ' Select another file']. ^aResult]. choice = 2 ifTrue: [^self startUpWithCaption: 'Select Another File']. ^nil ! ! !StandardFileMenu methodsFor: 'basic control sequences' stamp: 'dgd 9/21/2003 13:17'! getTypedFileName: aResult | name | name _ FillInTheBlank request: 'Enter a new file name' initialAnswer: ''. name = '' ifTrue: [^self startUpWithCaption: 'Select a File:' translated]. name _ aResult directory fullNameFor: name. ^ StandardFileMenuResult directory: (FileDirectory forFileName: name) name: (FileDirectory localNameFor: name) ! ! !StandardFileMenu methodsFor: 'basic control sequences' stamp: 'acg 9/28/1999 23:34'! startUpWithCaption: aString at: location |result| result _ super startUpWithCaption: aString at: location. result ifNil: [^nil]. result isDirectory ifTrue: [self makeFileMenuFor: result directory. self computeForm. ^self startUpWithCaption: aString at: location]. result isCommand ifTrue: [result _ self getTypedFileName: result. result ifNil: [^nil]]. canTypeFileName ifTrue: [^self confirmExistingFiles: result]. ^result ! ! !StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 00:32'! advance: anInteger containingDirectoriesFrom: aDirectory | theDirectory | theDirectory _ aDirectory. 1 to: anInteger do: [:i | theDirectory _ theDirectory containingDirectory]. ^theDirectory! ! !StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 20:50'! computeLabelParagraph "Answer a Paragraph containing this menu's labels, one per line and centered." ^ Paragraph withText: labelString asText style: (MenuStyle leftFlush)! ! !StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'! newFileFrom: aDirectory canTypeFileName _ true. ^self makeFileMenuFor: aDirectory! ! !StandardFileMenu methodsFor: 'private' stamp: 'rww 9/23/2001 09:54'! newFileFrom: aDirectory withPattern: aPattern canTypeFileName _ true. pattern _ aPattern. ^self makeFileMenuFor: aDirectory! ! !StandardFileMenu methodsFor: 'private' stamp: 'acg 4/15/1999 22:03'! oldFileFrom: aDirectory canTypeFileName _ false. ^self makeFileMenuFor: aDirectory! ! !StandardFileMenu methodsFor: 'private'! oldFileFrom: aDirectory withPattern: aPattern canTypeFileName _ false. pattern _ aPattern. ^self makeFileMenuFor: aDirectory! ! !StandardFileMenu methodsFor: 'private' stamp: 'tk 2/14/2000 14:24'! pattern: patString " * for all files, or '*.cs' for changeSets, etc. Just like fileLists" pattern _ patString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardFileMenu class instanceVariableNames: ''! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:14'! newFileMenu: aDirectory Smalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory]. ^ super new newFileFrom: aDirectory! ! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'rww 9/23/2001 09:56'! newFileMenu: aDirectory withPattern: aPattern Smalltalk isMorphic ifFalse: [^ PluggableFileList newFileMenu: aDirectory]. ^ super new newFileFrom: aDirectory withPattern: aPattern! ! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'sma 4/30/2000 10:15'! oldFileMenu: aDirectory Smalltalk isMorphic ifFalse: [^ PluggableFileList oldFileMenu: aDirectory]. ^ super new oldFileFrom: aDirectory! ! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'RAA 5/25/2000 09:30'! oldFileMenu: aDirectory withPattern: aPattern Smalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory]. ^super new oldFileFrom: aDirectory withPattern: aPattern! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'! newFile ^self newFileFrom: (FileDirectory default)! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'! newFileFrom: aDirectory ^(self newFileMenu: aDirectory) startUpWithCaption: 'Select a File:' translated! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:18'! newFileStream ^self newFileStreamFrom: (FileDirectory default)! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'! newFileStreamFrom: aDirectory | sfmResult fileStream | sfmResult _ self newFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory newFileNamed: sfmResult name. [fileStream isNil] whileTrue: [sfmResult _ self newFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory newFileNamed: sfmResult name]. ^fileStream ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:28'! oldFile ^self oldFileFrom: (FileDirectory default)! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'dgd 9/21/2003 13:17'! oldFileFrom: aDirectory ^(self oldFileMenu: aDirectory) startUpWithCaption: 'Select a File:' translated! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'acg 4/15/1999 22:17'! oldFileStream ^self oldFileStreamFrom: (FileDirectory default) ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'tk 2/14/2000 14:27'! oldFileStreamFrom: aDirectory | sfmResult fileStream | sfmResult _ self oldFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name. [fileStream isNil] whileTrue: [sfmResult _ self oldFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name]. ^fileStream ! ! Object subclass: #StandardFileMenuResult instanceVariableNames: 'directory name' classVariableNames: '' poolDictionaries: '' category: 'Tools-FileList'! !StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'! directory ^directory! ! !StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'! directory: aDirectory ^directory _ aDirectory! ! !StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'! name ^name! ! !StandardFileMenuResult methodsFor: 'accessing' stamp: 'acg 4/15/1999 08:43'! name: aString ^name _ aString! ! !StandardFileMenuResult methodsFor: 'accessing' stamp: 'sw 6/9/1999 11:50'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' with directory: '. directory printOn: aStream. aStream nextPutAll: ' name: '. name printOn: aStream "StandardFileMenu oldFile"! ! !StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 09:05'! isCommand ^name isNil! ! !StandardFileMenuResult methodsFor: 'testing' stamp: 'acg 4/15/1999 20:57'! isDirectory ^name = ''! ! !StandardFileMenuResult methodsFor: 'private' stamp: 'acg 4/15/1999 08:42'! directory: aDirectory name: aString directory _ aDirectory. name _ aString. ^self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardFileMenuResult class instanceVariableNames: ''! !StandardFileMenuResult class methodsFor: 'instance creation' stamp: 'acg 4/15/1999 08:42'! directory: aDirectory name: aString ^super new directory: aDirectory name: aString! ! FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1' classVariableNames: 'Registry' poolDictionaries: '' category: 'System-Files'! !StandardFileStream commentStamp: '<historical>' prior: 0! 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! !StandardFileStream methodsFor: 'open/close' stamp: 'ar 10/7/1998 14:43'! close "Close this file." fileID ifNotNil: [ self primClose: fileID. self unregister. fileID _ nil]. ! ! !StandardFileStream methodsFor: 'open/close' stamp: 'jm 2/6/2002 08:33'! closed "Answer true if this file is closed." ^ fileID isNil or: [(self primSizeNoError: fileID) isNil] ! ! !StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 16:20'! ensureOpen "Make sure that this file really is open." self closed ifTrue: [^ self reopen]. (self primSizeNoError: fileID) ifNotNil: [^ self]. self reopen. ! ! !StandardFileStream methodsFor: 'open/close'! open "For compatibility with a few existing things. 2/14/96 sw" ^ self reopen! ! !StandardFileStream methodsFor: 'open/close' stamp: 'ar 12/12/2001 15:58'! open: fileName forWrite: writeMode "Open the file with the given name. If writeMode is true, allow writing, otherwise open the file in read-only mode." "Changed to do a GC and retry before failing ar 3/21/98 17:25" fileID _ StandardFileStream retryWithGC:[self primOpen: fileName writable: writeMode] until:[:id| id notNil] forFileNamed: fileName. fileID ifNil: [^ nil]. "allows sender to detect failure" self register. name _ fileName. rwmode _ writeMode. buffer1 _ String new: 1. ! ! !StandardFileStream methodsFor: 'open/close'! openReadOnly "Open the receiver as a read-only file. 1/31/96 sw" ^ self open: name forWrite: false! ! !StandardFileStream methodsFor: 'open/close' stamp: 'jm 9/21/1998 13:58'! reopen "Close and reopen this file. The file position is reset to zero." "Details: Files that were open when a snapshot occurs are no longer valid when the snapshot is resumed. This operation re-opens the file if that has happened." fileID ifNotNil: [self primCloseNoError: fileID]. self open: name forWrite: rwmode. ! ! !StandardFileStream methodsFor: 'properties-setting'! ascii "opposite of binary" buffer1 _ String new: 1! ! !StandardFileStream methodsFor: 'properties-setting'! binary buffer1 _ ByteArray new: 1! ! !StandardFileStream methodsFor: 'properties-setting'! isBinary ^ buffer1 class == ByteArray! ! !StandardFileStream methodsFor: 'properties-setting' stamp: 'tk 11/4/1998 19:17'! isReadOnly ^ rwmode not ! ! !StandardFileStream methodsFor: 'properties-setting' stamp: 'jm 9/21/1998 13:56'! readOnly "Make this file read-only." rwmode _ false. ! ! !StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:16'! directory "Return the directory containing this file." ^ FileDirectory forFileName: self fullName ! ! !StandardFileStream methodsFor: 'access'! file "Answer the object representing the receiver's file. Need for compatibility with some calls -- check senders. 2/14/96 sw" ^ self! ! !StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'! fullName "Answer this file's full path name." ^ name ! ! !StandardFileStream methodsFor: 'access'! isDirectory "Answer whether the receiver represents a directory. For the post-transition case, uncertain what to do. 2/14/96 sw" ^ false! ! !StandardFileStream methodsFor: 'access' stamp: 'ar 11/24/1998 14:00'! localName ^ name ifNotNil: [(name findTokens: FileDirectory pathNameDelimiter asString) last]! ! !StandardFileStream methodsFor: 'access' stamp: 'jm 9/21/1998 14:19'! name "Answer this file's full path name." ^ name ! ! !StandardFileStream methodsFor: 'access' stamp: 'di 6/27/97 12:18'! peekFor: item "Answer false and do not advance if the next element is not equal to item, or if this stream is at the end. If the next element is equal to item, then advance over it and return true" | next | "self atEnd ifTrue: [^ false]. -- SFStream will give nil" (next _ self next) == nil ifTrue: [^ false]. item = next ifTrue: [^ true]. self skip: -1. ^ false! ! !StandardFileStream methodsFor: 'access'! printOn: aStream "Put a printed version of the receiver onto aStream. 1/31/96 sw" aStream nextPutAll: self class name; nextPutAll: ': '; print: name! ! !StandardFileStream methodsFor: 'access' stamp: 'ar 6/16/2002 18:58'! reset self ensureOpen. self position: 0.! ! !StandardFileStream methodsFor: 'access'! size "Answer the size of the file in characters. 2/12/96 sw" ^ self primSize: fileID! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'sw 2/12/96'! atEnd "Answer whether the receiver is at its end. " ^ self primAtEnd: fileID! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'mir 2/25/2000 12:37'! basicNext "Answer the next byte from this file, or nil if at the end of the file." | count | count _ self primRead: fileID into: buffer1 startingAt: 1 count: 1. count = 1 ifTrue: [^ buffer1 at: 1] ifFalse: [^ nil]. ! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ls 8/23/2003 16:44'! findString: string "Fast version of #upToAll: to find a String in a file starting from the beginning. Returns the position and also sets the position there. If string is not found 0 is returned and position is unchanged." | pos buffer count oldPos sz | oldPos _ self position. self reset. sz _ self size. pos _ 0. buffer _ String new: 2000. [ buffer := self nextInto: buffer. (count _ buffer findString: string) > 0 ifTrue: ["Found the string part way into buffer" self position: pos. self next: count - 1. ^self position ]. pos _ ((pos + 2000 - string size) min: sz). self position: pos. pos = sz] whileFalse. "Never found it, and hit end of file" self position: oldPos. ^0! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 2/6/2001 17:59'! flush "Flush pending changes" ^self primFlush: fileID! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'mir 2/25/2000 12:37'! next "Answer the next byte from this file, or nil if at the end of the file." ^ self basicNext! ! !StandardFileStream methodsFor: 'read, write, position'! next: n "Return a string with the next n characters of the filestream in it. 1/31/96 sw" ^ self nextInto: (buffer1 class new: n)! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 12/23/1999 15:02'! next: n into: aString startingAt: startIndex "Read n bytes into the given string. Return aString or a partial copy if less than n elements have been read." | count | count _ self primRead: fileID into: aString startingAt: startIndex count: n. count = n ifTrue:[^aString] ifFalse:[^aString copyFrom: 1 to: startIndex+count-1]! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'jm 9/21/1998 13:55'! nextPut: char "Write the given character to this file." rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. buffer1 at: 1 put: char. self primWrite: fileID from: buffer1 startingAt: 1 count: 1. ^ char ! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:43'! nextPutAll: aString "Write all the characters of the given string to this file." rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. self primWrite: fileID from: aString startingAt: 1 count: aString basicSize. ^ aString ! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'tk 2/5/2000 21:58'! nextWordsInto: aBitmap "Note: The file primitives automatically adjust for word based objects." self next: aBitmap basicSize into: aBitmap startingAt: 1. aBitmap restoreEndianness. ^ aBitmap! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'mir 2/25/2000 12:37'! peek "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil. " | next | self atEnd ifTrue: [^ nil]. next _ self basicNext. self position: self position - 1. ^ next! ! !StandardFileStream methodsFor: 'read, write, position'! position "Return the receiver's current file position. 2/12/96 sw" ^ self primGetPosition: fileID! ! !StandardFileStream methodsFor: 'read, write, position'! position: pos "Set the receiver's position as indicated. 2/12/96 sw" ^ self primSetPosition: fileID to: pos! ! !StandardFileStream methodsFor: 'read, write, position'! readOnlyCopy ^ StandardFileStream readOnlyFileNamed: self name! ! !StandardFileStream methodsFor: 'read, write, position'! setToEnd "Set the position of the receiver to the end of file. 1/31/96 sw" self position: self size! ! !StandardFileStream methodsFor: 'read, write, position'! skip: n "Set the character position to n characters from the current position. Error if not enough characters left in the file. 1/31/96 sw" self position: self position + n! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'di 7/14/97 23:15'! upTo: delim "Fast version to speed up nextChunk" | pos buffer count | pos _ self position. buffer _ self next: 2000. (count _ buffer indexOf: delim) > 0 ifTrue: ["Found the delimiter part way into buffer" self position: pos + count. ^ buffer copyFrom: 1 to: count - 1]. self atEnd ifTrue: ["Never found it, and hit end of file" ^ buffer]. "Never found it, but there's more..." ^ buffer , (self upTo: delim)! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ar 12/22/1999 15:40'! upToEnd "Answer a subcollection from the current access position through the last element of the receiver." | newStream buffer | buffer _ buffer1 species new: 1000. newStream _ WriteStream on: (buffer1 species new: 100). [self atEnd] whileFalse: [newStream nextPutAll: (self nextInto: buffer)]. ^ newStream contents! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primAtEnd: id "Answer true if the file position is at the end of the file." <primitive: 'primitiveFileAtEnd' module: 'FilePlugin'> self primitiveFailed ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primClose: id "Close this file." <primitive: 'primitiveFileClose' module: 'FilePlugin'> self primitiveFailed ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primCloseNoError: id "Close this file. Don't raise an error if the primitive fails." <primitive: 'primitiveFileClose' module: 'FilePlugin'> ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/6/2001 17:58'! primFlush: id "Flush pending changes to the disk" | p | <primitive: 'primitiveFileFlush' module: 'FilePlugin'> "In some OS's seeking to 0 and back will do a flush" p _ self position. self position: 0; position: p! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primGetPosition: id "Get this files current position." <primitive: 'primitiveFileGetPosition' module: 'FilePlugin'> self primitiveFailed ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primOpen: fileName writable: writableFlag "Open a file of the given name, and return the file ID obtained. If writableFlag is true, then if there is none with this name, then create one else prepare to overwrite the existing from the beginning otherwise if the file exists, open it read-only else return nil" <primitive: 'primitiveFileOpen' module: 'FilePlugin'> ^ nil ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primRead: id into: byteArray startingAt: startIndex count: count "Read up to count bytes of data from this file into the given string or byte array starting at the given index. Answer the number of bytes actually read." <primitive: 'primitiveFileRead' module: 'FilePlugin'> self closed ifTrue: [^ self error: 'File is closed']. self error: 'File read failed'. ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primSetPosition: id to: anInteger "Set this file to the given position." <primitive: 'primitiveFileSetPosition' module: 'FilePlugin'> self primitiveFailed ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primSize: id "Answer the size of this file." <primitive: 'primitiveFileSize' module: 'FilePlugin'> self primitiveFailed ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primSizeNoError: id "Answer the size of this file. Answer nil if the primitive fails; this indicates that the file handle has become stale." <primitive: 'primitiveFileSize' module: 'FilePlugin'> ^ nil ! ! !StandardFileStream methodsFor: 'primitives' stamp: 'ar 2/2/2001 15:09'! primWrite: id from: stringOrByteArray startingAt: startIndex count: count "Write count bytes onto this file from the given string or byte array starting at the given index. Answer the number of bytes written." <primitive: 'primitiveFileWrite' module: 'FilePlugin'> self closed ifTrue: [^ self error: 'File is closed']. self error: 'File write failed'. ! ! !StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'! register ^self class register: self! ! !StandardFileStream methodsFor: 'registry' stamp: 'ar 3/21/98 17:23'! unregister ^self class unregister: self! ! !StandardFileStream methodsFor: 'finalization' stamp: 'ar 3/21/98 18:16'! actAsExecutor super actAsExecutor. name := nil.! ! !StandardFileStream methodsFor: 'finalization' stamp: 'ar 10/7/1998 15:44'! finalize self primCloseNoError: fileID.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardFileStream class instanceVariableNames: ''! !StandardFileStream class methodsFor: 'file creation' stamp: 'TPR 8/13/1999 21:22'! fileNamed: fileName "Open a file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close." ^ self new open: (self fullName: fileName) forWrite: true ! ! !StandardFileStream class methodsFor: 'file creation' stamp: 'tpr 10/21/2001 11:11'! forceNewFileNamed: fileName "Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, delete it without asking before creating the new file." | dir localName fullName f | fullName _ self fullName: fileName. (self isAFileNamed: fullName) ifFalse: [f _ self new open: fullName forWrite: true. ^ f isNil ifTrue: ["Failed to open the file" (FileDoesNotExistException fileName: fullName) signal] ifFalse: [f]]. dir _ FileDirectory forFileName: fullName. localName _ FileDirectory localNameFor: fullName. dir deleteFileNamed: localName ifAbsent: [(CannotDeleteFileException new messageText: 'Could not delete the old version of file ' , fullName) signal]. f _ self new open: fullName forWrite: true. ^ f isNil ifTrue: ["Failed to open the file" (FileDoesNotExistException fileName: fullName) signal] ifFalse: [f]! ! !StandardFileStream class methodsFor: 'file creation' stamp: 'mpw 9/18/1999 00:05'! isAFileNamed: fileName "Answer true if a file of the given name exists." | f | f _ self new open: fileName forWrite: false. f ifNil: [^ false]. f close. ^ true ! ! !StandardFileStream class methodsFor: 'file creation' stamp: 'LC 10/24/2001 21:43'! newFileNamed: fileName "Create a new file with the given name, and answer a stream opened for writing on that file. If the file already exists, ask the user what to do." | fullName | fullName _ self fullName: fileName. ^(self isAFileNamed: fullName) ifTrue: ["file already exists:" (FileExistsException fileName: fullName fileClass: self) signal] ifFalse: [self new open: fullName forWrite: true] ! ! !StandardFileStream class methodsFor: 'file creation' stamp: 'mir 7/25/2000 16:39'! oldFileNamed: fileName "Open an existing file with the given name for reading and writing. If the name has no directory part, then the file will be created in the default directory. If the file already exists, its prior contents may be modified or replaced, but the file will not be truncated on close." | fullName | fullName _ self fullName: fileName. ^(self isAFileNamed: fullName) ifTrue: [self new open: fullName forWrite: true] ifFalse: ["File does not exist..." (FileDoesNotExistException fileName: fullName) signal]! ! !StandardFileStream class methodsFor: 'file creation' stamp: 'mdr 12/5/2000 19:51'! readOnlyFileNamed: fileName "Open an existing file with the given name for reading." | fullName f | fullName _ self fullName: fileName. f _ self new open: fullName forWrite: false. ^ f isNil ifFalse: [f] ifTrue: ["File does not exist..." ((FileDoesNotExistException fileName: fullName) readOnly: true) signal]. "StandardFileStream readOnlyFileNamed: 'kjsd.txt' "! ! !StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'! register: anObject WeakArray isFinalizationSupported ifFalse:[^anObject]. self registry add: anObject! ! !StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 14:41'! registry WeakArray isFinalizationSupported ifFalse:[^nil]. ^Registry isNil ifTrue:[Registry := WeakRegistry new] ifFalse:[Registry].! ! !StandardFileStream class methodsFor: 'registry' stamp: 'ar 12/12/2001 15:55'! retryWithGC: execBlock until: testBlock forFileNamed: fullName "Re-implemented to only force GC if a file with the given name exists" | blockValue foundIt | blockValue := execBlock value. (testBlock value: blockValue) ifTrue:[^blockValue]. "See if we have a file with the given name" foundIt _ Registry keys "hold on strongly for now" anySatisfy:[:file| file name sameAs: fullName]. foundIt ifFalse:[^blockValue]. Smalltalk garbageCollectMost. blockValue := execBlock value. (testBlock value: blockValue) ifTrue:[^blockValue]. Smalltalk garbageCollect. ^execBlock value.! ! !StandardFileStream class methodsFor: 'registry' stamp: 'ar 10/7/1998 15:23'! unregister: anObject WeakArray isFinalizationSupported ifFalse:[^anObject]. self registry remove: anObject ifAbsent:[]! ! !StandardFileStream class methodsFor: 'error handling' stamp: 'mir 2/28/2000 16:06'! fileDoesNotExistUserHandling: fullFileName | selection newName | selection _ (PopUpMenu labels: 'create a new file choose another name cancel') startUpWithCaption: (FileDirectory localNameFor: fullFileName) , ' does not exist.'. selection = 1 ifTrue: [^ self new open: fullFileName forWrite: true]. selection = 2 ifTrue: [ newName _ FillInTheBlank request: 'Enter a new file name' initialAnswer: fullFileName. ^ self oldFileNamed: (self fullName: newName)]. self halt! ! !StandardFileStream class methodsFor: 'error handling' stamp: 'mir 2/28/2000 15:24'! fileExistsUserHandling: fullFileName | dir localName choice newName newFullFileName | dir _ FileDirectory forFileName: fullFileName. localName _ FileDirectory localNameFor: fullFileName. choice _ (PopUpMenu labels: 'overwrite that file\choose another name\cancel' withCRs) startUpWithCaption: localName, ' already exists.'. choice = 1 ifTrue: [ dir deleteFileNamed: localName ifAbsent: [self error: 'Could not delete the old version of that file']. ^ self new open: fullFileName forWrite: true]. choice = 2 ifTrue: [ newName _ FillInTheBlank request: 'Enter a new file name' initialAnswer: fullFileName. newFullFileName _ self fullName: newName. ^ self newFileNamed: newFullFileName]. self error: 'Please close this to abort file opening'! ! !StandardFileStream class methodsFor: 'error handling' stamp: 'tpr 10/18/2001 19:08'! readOnlyFileDoesNotExistUserHandling: fullFileName | dir files choices selection newName fileName | dir _ FileDirectory forFileName: fullFileName. files _ dir fileNames. fileName _ FileDirectory localNameFor: fullFileName. choices _ fileName correctAgainst: files. choices add: 'Choose another name'. choices add: 'Cancel'. selection _ (PopUpMenu labelArray: choices lines: (Array with: 5) ) startUpWithCaption: (FileDirectory localNameFor: fullFileName), ' does not exist.'. selection = choices size ifTrue:["cancel" ^ nil "should we raise another exception here?"]. selection < (choices size - 1) ifTrue: [ newName _ (dir pathName , FileDirectory slash , (choices at: selection))]. selection = (choices size - 1) ifTrue: [ newName _ FillInTheBlank request: 'Enter a new file name' initialAnswer: fileName]. newName = '' ifFalse: [^ self readOnlyFileNamed: (self fullName: newName)]. ^ self error: 'Could not open a file'! ! SourceFileArray subclass: #StandardSourceFileArray instanceVariableNames: 'files' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !StandardSourceFileArray commentStamp: '<historical>' prior: 0! This class implements the source file management behavior of traditional Squeak, with a sources file and a changes file. File positions are mapped such that those files can be up to 32MBytes in size. Structure: files Array -- storing the actual source files ! !StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'hmm 4/25/2000 21:20'! initialize files _ Array new: 2. files at: 1 put: (SourceFiles at: 1). files at: 2 put: (SourceFiles at: 2)! ! !StandardSourceFileArray methodsFor: 'initialize-release' stamp: 'ar 5/17/2000 18:28'! initialize: nFiles files _ Array new: nFiles! ! !StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'! at: index ^files at: index! ! !StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'! at: index put: aFile files at: index put: aFile! ! !StandardSourceFileArray methodsFor: 'accessing' stamp: 'hmm 4/25/2000 21:20'! size ^files size! ! !StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 21:44'! fileIndexFromSourcePointer: anInteger "Return the index of the source file which contains the source chunk addressed by anInteger" "This implements the recent 32M source file algorithm" | hi | hi _ anInteger // 16r1000000. ^hi < 3 ifTrue: [hi] ifFalse: [hi - 2]! ! !StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 21:44'! filePositionFromSourcePointer: anInteger "Return the position of the source chunk addressed by anInteger" "This implements the recent 32M source file algorithm" | hi lo | hi _ anInteger // 16r1000000. lo _ anInteger \\ 16r1000000. ^hi < 3 ifTrue: [lo] ifFalse: [lo + 16r1000000]! ! !StandardSourceFileArray methodsFor: 'sourcePointer conversion' stamp: 'hmm 4/25/2000 21:48'! sourcePointerFromFileIndex: index andPosition: position | hi lo | "Return a source pointer according to the new 32M algorithm" ((index between: 1 and: 2) and: [position between: 0 and: 16r1FFFFFF]) ifFalse: [self error: 'invalid source code pointer']. hi _ index. lo _ position. lo >= 16r1000000 ifTrue: [ hi _ hi+2. lo _ lo - 16r1000000]. ^hi * 16r1000000 + lo! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardSourceFileArray class instanceVariableNames: ''! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'hmm 4/25/2000 21:19'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" SourceFiles _ self new initialize! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'ar 5/17/2000 18:27'! new: nFiles ^self new initialize: nFiles.! ! MouseMenuController subclass: #StandardSystemController instanceVariableNames: 'status' classVariableNames: 'HBorderCursor ScheduledBlueButtonMenu ScheduledBlueButtonMessages VBorderCursor' poolDictionaries: '' category: 'ST80-Support'! !StandardSystemController commentStamp: '<historical>' prior: 0! 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.! !StandardSystemController methodsFor: 'initialize-release' stamp: 'sma 3/11/2000 11:48'! initialize super initialize. status _ #inactive! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 12:01'! blueButtonActivity ScheduledBlueButtonMenu ifNil: [^ super controlActivity]. ScheduledBlueButtonMenu invokeOn: self! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/11/2000 15:20'! controlActivity self checkForReframe. ^ super controlActivity! ! !StandardSystemController methodsFor: 'control defaults'! isControlActive status == #active ifFalse: [^ false]. sensor anyButtonPressed ifFalse: [^ true]. self viewHasCursor ifTrue: [^ true] ifFalse: [ScheduledControllers noteNewTop. ^ false]! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'sma 3/15/2000 22:19'! redButtonActivity "If cursor is in label of a window when red button is pushed, check for closeBox or growBox, else drag the window frame or edit the label." | box p | p _ sensor cursorPoint. self labelHasCursor ifFalse: [super redButtonActivity. ^ self]. ((box _ view closeBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [self close. ^ self]. ^ self]. ((box _ view growBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [Sensor controlKeyPressed ifTrue: [^ self expand; fullScreen]. ^ view isCollapsed ifTrue: [self expand] ifFalse: [self collapse]]. ^ self]. (((box _ view labelTextRegion expandBy: 1) containsPoint: p) and: [Preferences clickOnLabelToEdit or: [sensor leftShiftDown]]) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [^ self label]. ^ self]. self move! ! !StandardSystemController methodsFor: 'basic control sequence' stamp: 'sw 10/20/1999 09:52'! controlInitialize view displayEmphasized. view uncacheBits. "Release cached bitmap while active" model windowActiveOnFirstClick ifFalse: [sensor waitNoButton]. status _ #active. view isCollapsed ifFalse: [model modelWakeUpIn: view]! ! !StandardSystemController methodsFor: 'basic control sequence' stamp: 'di 5/11/1999 22:05'! controlTerminate status == #closed ifTrue: [view ~~ nil ifTrue: [view release]. ScheduledControllers unschedule: self. ^self]. view deEmphasize; cacheBits. view isCollapsed ifFalse: [model modelSleep].! ! !StandardSystemController methodsFor: 'menu messages'! chooseColor "Allow the user to specify a new background color for the receiver's window. 5/6/96 sw. 7/31/96 sw: use Color fromUser" view backgroundColor: Color fromUser; uncacheBits; display! ! !StandardSystemController methodsFor: 'menu messages'! close "The receiver's view should be removed from the screen and from the collection of scheduled views." model okToChange ifFalse: [^self]. status _ #closed. view erase! ! !StandardSystemController methodsFor: 'menu messages'! collapse "Get the receiver's view to change to a collapsed view on the screen." view collapseToPoint: view chooseCollapsePoint! ! !StandardSystemController methodsFor: 'menu messages'! expand "The receiver's view was collapsed; open it again and ask the user to designate its rectangular area." view expand; emphasize! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'jm 4/28/1998 06:57'! label | newLabel | newLabel _ FillInTheBlank request: 'Edit the label, then type RETURN' initialAnswer: view label. newLabel isEmpty ifFalse: [view relabel: newLabel]. ! ! !StandardSystemController methodsFor: 'menu messages'! move "Ask the user to designate a new origin position for the receiver's view. 6/10/96 sw: tell the view that it has moved" | oldBox | oldBox _ view windowBox. view uncacheBits. view align: view windowBox topLeft with: view chooseMoveRectangle topLeft. view displayEmphasized. view moved. "In case its model wishes to take note." (oldBox areasOutside: view windowBox) do: [:rect | ScheduledControllers restore: rect]! ! !StandardSystemController methodsFor: 'menu messages'! reframe ^ view reframeTo: view getFrame! ! !StandardSystemController methodsFor: 'menu messages'! toggleTwoTone (view isMemberOf: StandardSystemView) ifTrue: [^ view become: (view as: ColorSystemView)]. (view isMemberOf: ColorSystemView) ifTrue: [^ view become: (view as: StandardSystemView)]. ! ! !StandardSystemController methodsFor: 'menu messages'! under "Deactive the receiver's scheduled view and pass control to any view that might be positioned directly underneath it and the cursor." status _ #inactive! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'sw 9/30/97 22:04'! closeAndUnschedule "Erase the receiver's view and remove it from the collection of scheduled views." status _ #closed. view erase. view release. ScheduledControllers unschedule: self; searchForActiveController ! ! !StandardSystemController methodsFor: 'scheduling'! closeAndUnscheduleNoErase "Remove the scheduled view from the collection of scheduled views. Set its status to closed but do not erase." status _ #closed. view release. ScheduledControllers unschedule: self! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'jm 3/18/98 19:21'! closeAndUnscheduleNoTerminate "Erase the receiver's view and remove it from the collection of scheduled views, but do not terminate the current process." status _ #closed. view erase. view release. ScheduledControllers unschedule: self. ! ! !StandardSystemController methodsFor: 'scheduling'! open "Create an area on the screen in which the receiver's scheduled view can be displayed. Make it the active view." view resizeInitially. status _ #open. ScheduledControllers scheduleActive: self! ! !StandardSystemController methodsFor: 'scheduling'! openDisplayAt: aPoint "Create an area with origin aPoint in which the receiver's scheduled view can be displayed. Make it the active view." view align: view viewport center with: aPoint. view translateBy: (view displayBox amountToTranslateWithin: Display boundingBox). status _ #open. ScheduledControllers scheduleActive: self! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'jm 10/22/97 08:16'! openNoTerminate "Create an area in which the receiver's scheduled view can be displayed. Make it the active view. Do not terminate the currently active process." view resizeInitially. status _ #open. ScheduledControllers scheduleActiveNoTerminate: self! ! !StandardSystemController methodsFor: 'scheduling'! openNoTerminateDisplayAt: aPoint "Create an area with origin aPoint in which the receiver's scheduled view can be displayed. Make it the active view. Do not terminate the currently active process." view resizeMinimumCenteredAt: aPoint. status _ #open. ScheduledControllers scheduleActiveNoTerminate: self! ! !StandardSystemController methodsFor: 'scheduling'! status: aSymbol status _ aSymbol! ! !StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:45'! adjustPaneBorders | side sub newRect outerFrame | outerFrame _ view displayBox. side _ #none. VBorderCursor showWhile: [ [sub _ view subviewWithLongestSide: [:s | side _ s] near: sensor cursorPoint. self cursorOnBorder and: [(side = #left) | (side = #right)]] whileTrue: [ self interActivityPause. sensor redButtonPressed ifTrue: [side = #left ifTrue: [newRect _ sub stretchFrame: [:f | (f withLeft: sensor cursorPoint x) intersect: outerFrame] startingWith: sub displayBox]. side = #right ifTrue: [newRect _ sub stretchFrame: [:f | (f withRight: sensor cursorPoint x) intersect: outerFrame] startingWith: sub displayBox]. view reframePanesAdjoining: sub along: side to: newRect]]]. HBorderCursor showWhile: [ [sub _ view subviewWithLongestSide: [:s | side _ s] near: sensor cursorPoint. self cursorOnBorder and: [(side = #top) | (side = #bottom)]] whileTrue: [ self interActivityPause. sensor redButtonPressed ifTrue: [side = #top ifTrue: [newRect _ sub stretchFrame: [:f | (f withTop: sensor cursorPoint y) intersect: outerFrame] startingWith: sub displayBox]. side = #bottom ifTrue: [newRect _ sub stretchFrame: [:f | (f withBottom: sensor cursorPoint y) intersect: outerFrame] startingWith: sub displayBox]. view reframePanesAdjoining: sub along: side to: newRect]]]! ! !StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:22'! adjustWindowBorders | side noClickYet | noClickYet _ true. VBorderCursor showWhile: [ [side _ view displayBox sideNearestTo: sensor cursorPoint. self cursorOnBorder and: [(side = #left) | (side = #right) and: [noClickYet or: [sensor redButtonPressed]]]] whileTrue: [sensor redButtonPressed ifTrue: [noClickYet _ false. side = #left ifTrue: [view newFrame: [:f | f withLeft: sensor cursorPoint x]]. side = #right ifTrue: [view newFrame: [:f | f withRight: sensor cursorPoint x]]]. self interActivityPause]]. HBorderCursor showWhile: [ [side _ view displayBox sideNearestTo: sensor cursorPoint. self cursorOnBorder and: [(side = #top) | (side = #bottom) and: [noClickYet or: [sensor redButtonPressed]]]] whileTrue: [sensor redButtonPressed ifTrue: [noClickYet _ false. side = #top ifTrue: [view newFrame: [:f | f withTop: sensor cursorPoint y]]. side = #bottom ifTrue: [view newFrame: [:f | f withBottom: sensor cursorPoint y]]]. self interActivityPause]]! ! !StandardSystemController methodsFor: 'borders' stamp: 'ls 7/11/1998 07:38'! adjustWindowCorners | box cornerBox p clicked f2 | box _ view windowBox. clicked _ false. #(topLeft topRight bottomRight bottomLeft) do: [:readCorner | cornerBox _ ((box insetBy: 2) perform: readCorner) - (10@10) extent: 20@20. (cornerBox containsPoint: sensor cursorPoint) ifTrue: ["Display reverse: cornerBox." (Cursor perform: readCorner) showWhile: [[(cornerBox containsPoint: (p _ sensor cursorPoint)) and: [(clicked _ sensor anyButtonPressed) not]] whileTrue: [ self interActivityPause ]. "Display reverse: cornerBox." clicked ifTrue: [view newFrame: [:f | p _ sensor cursorPoint. readCorner = #topLeft ifTrue: [f2 _ p corner: f bottomRight]. readCorner = #bottomLeft ifTrue: [f2 _ (f withBottom: p y) withLeft: p x]. readCorner = #bottomRight ifTrue: [f2 _ f topLeft corner: p]. readCorner = #topRight ifTrue: [f2 _ (f withTop: p y) withRight: p x]. f2]]]]]. ^ clicked! ! !StandardSystemController methodsFor: 'borders' stamp: 'di 11/16/2001 22:30'! checkForReframe | cp | view isCollapsed ifTrue: [^ self]. cp _ sensor cursorPoint. ((view closeBoxFrame expandBy: 2) containsPoint: cp) | ((view growBoxFrame expandBy: 2) containsPoint: cp) ifTrue: [^ self]. "Dont let reframe interfere with close/grow" self adjustWindowCorners. self cursorOnBorder ifFalse: [^ self]. ((view insetDisplayBox insetBy: 2@2) containsPoint: cp) ifFalse: [^ self adjustWindowBorders]. view subViews size <= 1 ifTrue: [^ self]. (view subviewWithLongestSide: [:s | ] near: cp) == nil ifFalse: [^ self adjustPaneBorders].! ! !StandardSystemController methodsFor: 'borders'! cursorOnBorder | cp i box | view isCollapsed ifTrue: [^ false]. cp _ sensor cursorPoint. ((view labelDisplayBox insetBy: (0@2 corner: 0@-2)) containsPoint: cp) ifTrue: [^ false]. (i _ view subViews findFirst: [:v | v displayBox containsPoint: cp]) = 0 ifTrue: [box _ view windowBox] ifFalse: [box _ (view subViews at: i) insetDisplayBox]. ^ ((box insetBy: 3) containsPoint: cp) not and: [(box expandBy: 4) containsPoint: cp]! ! !StandardSystemController methodsFor: 'borders'! fullScreen "Make the receiver's window occupy jes' about the full screen. 6/10/96 sw" view fullScreen! ! !StandardSystemController methodsFor: 'cursor'! labelHasCursor "Answer true if the cursor is within the window's label" ^view labelContainsPoint: sensor cursorPoint! ! !StandardSystemController methodsFor: 'pluggable menus' stamp: 'sma 3/11/2000 15:12'! getPluggableYellowButtonMenu: shiftKeyState ^ nil! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardSystemController class instanceVariableNames: ''! !StandardSystemController class methodsFor: 'class initialization' stamp: 'sma 3/11/2000 11:57'! initialize "StandardSystemController initialize" ScheduledBlueButtonMenu _ SelectionMenu labels: 'edit label choose color... two-tone/full color move frame full screen collapse close' lines: #(3 7) selections: #(label chooseColor toggleTwoTone move reframe fullScreen collapse close). VBorderCursor _ Cursor extent: 16@16 fromArray: #( 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010010000100000 2r1010110000110000 2r1011111111111000 2r1010110000110000 2r1010010000100000 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010000000000000 2r1010000000000000) offset: 0@0. HBorderCursor _ Cursor extent: 16@16 fromArray: #( 2r1111111111111111 2r0000000000000000 2r1111111111111111 2r0000000100000000 2r0000001110000000 2r0000011111000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000000100000000 2r0000011111000000 2r0000001110000000 2r0000000100000000 2r0000000000000000 2r0000000000000000 2r0000000000000000) offset: 0@0.! ! View subclass: #StandardSystemView instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes' classVariableNames: 'CacheBits LabelStyle' poolDictionaries: '' category: 'ST80-Support'! !StandardSystemView commentStamp: '<historical>' prior: 0! 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.! !StandardSystemView methodsFor: 'initialize-release' stamp: 'sw 10/29/1999 12:58'! initialize "Refer to the comment in View|initialize." super initialize. labelFrame _ Quadrangle new. labelFrame region: (Rectangle origin: 0 @ 0 extent: 50 @ self labelHeight). labelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2. self label: nil. isLabelComplemented _ false. minimumSize _ 50 @ 50. maximumSize _ Display extent. collapsedViewport _ nil. expandedViewport _ nil. bitsValid _ false. updatablePanes _ #()! ! !StandardSystemView methodsFor: 'initialize-release'! model: aModel "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" super model: aModel. self setDefaultBackgroundColor! ! !StandardSystemView methodsFor: 'initialize-release' stamp: 'jm 8/20/1998 18:29'! release model windowIsClosing. self isCollapsed ifTrue: [savedSubViews do: [:v | v release]]. super release. ! ! !StandardSystemView methodsFor: 'testing'! containsPoint: aPoint "Refer to the comment in View|containsPoint:." ^(super containsPoint: aPoint) | (self labelContainsPoint: aPoint)! ! !StandardSystemView methodsFor: 'testing'! isCollapsed "Answer whether the receiver is collapsed (true) or expanded (false)." ^savedSubViews ~~ nil! ! !StandardSystemView methodsFor: 'testing'! labelContainsPoint: aPoint "Answer TRUE if aPoint is in the label box." ^self labelDisplayBox containsPoint: aPoint! ! !StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:30'! closeBoxFrame ^ Rectangle origin: (self labelDisplayBox leftCenter + (10@-5)) extent: (11@11)! ! !StandardSystemView methodsFor: 'label access' stamp: 'di 6/16/97 12:29'! growBoxFrame ^ Rectangle origin: (self labelDisplayBox rightCenter + (-22@-5)) extent: (11@11)! ! !StandardSystemView methodsFor: 'label access'! label "Answer the string that appears in the receiver's label." labelText isNil ifTrue: [^ 'Untitled' copy] ifFalse: [^ labelText asString]! ! !StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:44'! label: aString "Set aString to be the receiver's label." labelText _ Paragraph withText: (Text string: ((aString == nil or: [aString isEmpty]) ifTrue: ['Untitled' copy] ifFalse: [aString]) attributes: (Array with: TextEmphasis bold)) style: LabelStyle. insetDisplayBox == nil ifTrue: [^ self]. "wait for further initialization" self setLabelRegion! ! !StandardSystemView methodsFor: 'label access'! labelColor "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" ^ self backgroundColor! ! !StandardSystemView methodsFor: 'label access'! labelDisplayBox "Answer the rectangle that borders the visible parts of the receiver's label on the display screen." ^ labelFrame region align: labelFrame topLeft with: self windowOrigin! ! !StandardSystemView methodsFor: 'label access'! labelFrame ^labelFrame! ! !StandardSystemView methodsFor: 'label access' stamp: 'sw 12/9/1999 17:47'! labelHeight ^ ((LabelStyle fontAt: 1) height + 4) max: 20! ! !StandardSystemView methodsFor: 'label access'! labelOffset ^ 0 @ (self labelHeight-2)! ! !StandardSystemView methodsFor: 'label access' stamp: 'sr 3/26/2000 04:26'! labelText ^labelText! ! !StandardSystemView methodsFor: 'label access'! labelTextRegion labelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0]. ^ (labelText boundingBox align: labelText boundingBox center with: self labelDisplayBox center) intersect: (self labelDisplayBox insetBy: 35@0)! ! !StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 14:20'! noLabel "A label of zero height indicates no label" labelFrame height > 0 ifTrue: [labelFrame region: (labelFrame bottomLeft + (0@1) extent: labelFrame width@0). labelFrame borderWidth: 0. self uncacheBits]! ! !StandardSystemView methodsFor: 'label access' stamp: 'di 6/10/1998 13:18'! relabel: aString "A new string for the label. Window is assumed to be active. Window will redisplay only if label bar has to grow." | oldRegion oldWidth | (model windowReqNewLabel: aString) ifFalse: [^ self]. oldRegion _ self labelTextRegion. oldWidth _ self insetDisplayBox width. self label: aString. Display fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0) fillColor: self labelColor. self insetDisplayBox width = oldWidth ifTrue: [self displayLabelText; emphasizeLabel] ifFalse: [self uncacheBits; displayEmphasized]. ! ! !StandardSystemView methodsFor: 'label access' stamp: 'sw 1/19/2001 20:13'! setLabel: aLabel "For compatibility with morphic" self relabel: aLabel! ! !StandardSystemView methodsFor: 'label access' stamp: 'di 10/3/97 13:35'! setLabelRegion "Always follows view width" labelFrame region: (0 @ 0 extent: self displayBox width @ self labelHeight). labelFrame borderWidth: 2! ! !StandardSystemView methodsFor: 'label access' stamp: 'sumim 2/8/2002 14:36'! setLabelTo: aString "Force aString to be the new label of the receiver, bypassing any logic about whether it is acceptable and about propagating information about the change." | oldRegion oldWidth | self label: aString. self controller isControlActive ifFalse: [^ self]. oldRegion _ self labelTextRegion. oldWidth _ self insetDisplayBox width. Display fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0) fillColor: self labelColor. self insetDisplayBox width = oldWidth ifTrue: [self displayLabelText; emphasizeLabel] ifFalse: [self uncacheBits; displayEmphasized]! ! !StandardSystemView methodsFor: 'size'! maximumSize "Answer a point representing the maximum width and height of the receiver." ^maximumSize! ! !StandardSystemView methodsFor: 'size'! maximumSize: aPoint "Set the argument, aPoint, to be the maximum width and height of the receiver." maximumSize _ aPoint! ! !StandardSystemView methodsFor: 'size'! minimumSize "Answer a point representing the minimum width and height of the receiver." ^minimumSize! ! !StandardSystemView methodsFor: 'size'! minimumSize: aPoint "Set the argument, aPoint, to be the minimum width and height of the receiver." minimumSize _ aPoint! ! !StandardSystemView methodsFor: 'framing' stamp: 'sr 3/26/2000 03:47'! chooseCollapsePoint "Answer the point at which to place the collapsed window." | pt labelForm beenDown offset | labelForm _ Form fromDisplay: self labelDisplayBox. self uncacheBits. self erase. beenDown _ Sensor anyButtonPressed. self isCollapsed ifTrue: [offset _ self labelDisplayBox topLeft - self growBoxFrame topLeft. labelForm follow: [pt _ (Sensor cursorPoint + offset max: 0@0) truncateTo: 8] while: [Sensor anyButtonPressed ifTrue: [beenDown _ true] ifFalse: [beenDown not]]. ^ pt]. ^ (RealEstateAgent assignCollapseFrameFor: self) origin. ! ! !StandardSystemView methodsFor: 'framing'! chooseFrame "Answer a new frame, depending on whether the view is currently collapsed or not." | labelForm f | self isCollapsed & expandedViewport notNil ifTrue: [labelForm _ bitsValid ifTrue: [windowBits] ifFalse: [Form fromDisplay: self labelDisplayBox]. bitsValid _ false. self erase. labelForm slideFrom: self labelDisplayBox origin to: expandedViewport origin-self labelOffset nSteps: 10. ^ expandedViewport] ifFalse: [f _ self getFrame. bitsValid _ false. self erase. ^ f topLeft + self labelOffset extent: f extent]! ! !StandardSystemView methodsFor: 'framing'! chooseMoveRectangle "Ask the user to designate a new window rectangle." | offset p | offset _ Sensor anyButtonPressed "Offset if draggin, eg, label" ifTrue: [self windowBox topLeft - Sensor cursorPoint] ifFalse: [0@0]. self isCollapsed ifTrue: [^ self labelDisplayBox newRectFrom: [:f | p _ Sensor cursorPoint + offset. p _ (p max: 0@0) truncateTo: 8. p extent: f extent]] ifFalse: [^ self windowBox newRectFrom: [:f | p _ Sensor cursorPoint + offset. self constrainFrame: (p extent: f extent)]]! ! !StandardSystemView methodsFor: 'framing' stamp: 'BG 10/29/2003 09:46'! collapse "If the receiver is not already collapsed, change its view to be that of its label only." self isCollapsed ifFalse: [model modelSleep. (subViews ~~ nil and: [subViews size = 1 ]) ifTrue: [subViews first deEmphasizeView]. expandedViewport _ self viewport. savedSubViews _ subViews. self resetSubViews. labelText isNil ifTrue: [self label: nil. bitsValid _ false.]. self window: (self inverseDisplayTransform: ((self labelDisplayBox topLeft extent: (labelText extent x + 70) @ self labelHeight) intersect: self labelDisplayBox))]! ! !StandardSystemView methodsFor: 'framing'! collapseToPoint: collapsePoint self collapse. self align: self displayBox topLeft with: collapsePoint. collapsedViewport _ self viewport. self displayEmphasized! ! !StandardSystemView methodsFor: 'framing'! collapsedFrame "Answer the rectangle occupied by this window when collapsed." ^ collapsedViewport "NOTE may be nil"! ! !StandardSystemView methodsFor: 'framing' stamp: 'sw 10/20/1999 09:46'! expand "If the receiver is collapsed, change its view to be that of all of its subviews, not its label alone." | newFrame | self isCollapsed ifTrue: [newFrame _ self chooseFrame expandBy: borderWidth. collapsedViewport _ self viewport. subViews _ savedSubViews. labelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2. savedSubViews _ nil. self setWindow: nil. self resizeTo: newFrame. self displayDeEmphasized. model modelWakeUpIn: self]! ! !StandardSystemView methodsFor: 'framing'! expandedFrame "Answer the rectangle occupied by this window when expanded." ^ expandedViewport "NOTE may be nil"! ! !StandardSystemView methodsFor: 'framing' stamp: 'sw 8/15/97 17:18'! fullScreen "Expand the receiver to fill the screen. Let the model decide how big is full -- allows for flop-out scrollbar on left if desired" self isCollapsed ifFalse: [self reframeTo: model fullScreenSize]! ! !StandardSystemView methodsFor: 'framing'! getFrame "Ask the user to designate a rectangular area in which the receiver should be displayed." | minFrame | minFrame _ Cursor origin showWhile: [(Sensor cursorPoint extent: self minimumSize) newRectFrom: [:f | Sensor cursorPoint extent: self minimumSize]]. self maximumSize <= self minimumSize ifTrue: [^ minFrame]. ^ Cursor corner showWhile: [minFrame newRectFrom: [:f | self constrainFrame: (f origin corner: Sensor cursorPoint)]]! ! !StandardSystemView methodsFor: 'framing' stamp: 'sw 1/22/96'! initialExtent "Answer the desired extent for the receiver when it is first opened on the screen. " ^ model initialExtent min: maximumSize max: minimumSize! ! !StandardSystemView methodsFor: 'framing' stamp: 'RAA 6/14/2000 17:27'! initialFrame "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" ^ RealEstateAgent initialFrameFor: self world: nil! ! !StandardSystemView methodsFor: 'framing'! moved "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" ! ! !StandardSystemView methodsFor: 'framing'! newFrame: frameChangeBlock self reframeTo: (self windowBox newRectFrom: [:f | self constrainFrame: (frameChangeBlock value: f)])! ! !StandardSystemView methodsFor: 'framing' stamp: 'di 10/22/1998 16:15'! reframePanesAdjoining: subView along: side to: aDisplayBox | newBox delta newRect minDim theMin | newRect _ aDisplayBox. theMin _ 16. "First check that this won't make any pane smaller than theMin screen dots" minDim _ ((subViews select: [:sub | sub displayBox bordersOn: subView displayBox along: side]) collect: [:sub | sub displayBox adjustTo: newRect along: side]) inject: 999 into: [:was :rect | (was min: rect width) min: rect height]. "If so, amend newRect as required" minDim < theMin ifTrue: [delta _ minDim - theMin. newRect _ newRect withSide: side setTo: ((newRect perform: side) > (subView displayBox perform: side) ifTrue: [(newRect perform: side) + delta] ifFalse: [(newRect perform: side) - delta])]. "Now adjust all adjoining panes for real" subViews do: [:sub | (sub displayBox bordersOn: subView displayBox along: side) ifTrue: [newBox _ sub displayBox adjustTo: newRect along: side. sub window: sub window viewport: (sub transform: (sub inverseDisplayTransform: newBox)) rounded]]. "And adjust the growing pane itself" subView window: subView window viewport: (subView transform: (subView inverseDisplayTransform: newRect)) rounded. "Finally force a recomposition of the whole window" viewport _ nil. self resizeTo: self viewport. self uncacheBits; displayEmphasized! ! !StandardSystemView methodsFor: 'framing' stamp: 'BG 12/4/2003 13:14'! reframeTo: newFrame "Reframe the receiver to the given screen rectangle. Repaint difference after the change. " | oldBox newBox portRect | self uncacheBits. oldBox _ self windowBox. portRect _ newFrame topLeft + self labelOffset corner: newFrame corner. self setWindow: nil. self resizeTo: portRect. self setLabelRegion. newBox _ self windowBox. (oldBox areasOutside: newBox) do: [:rect | ScheduledControllers restore: rect]. self displayEmphasized! ! !StandardSystemView methodsFor: 'framing'! resize "Determine the rectangular area for the receiver, adjusted to the minimum and maximum sizes." | f | f _ self getFrame. self resizeTo: (f topLeft + self labelOffset extent: f extent) ! ! !StandardSystemView methodsFor: 'framing'! resizeInitially "Determine the rectangular area for the receiver, adjusted to the minimum and maximum sizes." self resizeTo: self initialFrame ! ! !StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:12'! resizeMinimumCenteredAt: aPoint "Determine the rectangular area for the receiver, adjusted so that it is centered a position, aPoint." | aRectangle | aRectangle _ 0 @ 0 extent: self minimumSize. aRectangle _ aRectangle align: aRectangle center with: aPoint. self resizeTo: aRectangle! ! !StandardSystemView methodsFor: 'framing' stamp: 'di 4/6/98 15:29'! resizeTo: aRectangle "Resize this view to aRectangle" "First get scaling right inside borders" self window: (self window insetBy: borderWidth) viewport: (aRectangle insetBy: borderWidth). "Then ensure window maps to aRectangle" window _ transformation applyInverseTo: aRectangle! ! !StandardSystemView methodsFor: 'framing'! standardWindowOffset ^ Preferences standardWindowOffset! ! !StandardSystemView methodsFor: 'framing'! windowBox ^ self displayBox merge: self labelDisplayBox! ! !StandardSystemView methodsFor: 'framing' stamp: 'di 10/3/97 14:19'! windowOrigin ^ (self isCollapsed or: [labelFrame height = 0 "no label"]) ifTrue: [self displayBox topLeft] ifFalse: [self displayBox topLeft - self labelOffset]! ! !StandardSystemView methodsFor: 'controller access'! defaultControllerClass "Refer to the comment in View|defaultControllerClass." ^StandardSystemController! ! !StandardSystemView methodsFor: 'displaying'! cacheBits | oldLabelState | CacheBits ifFalse: [^ self uncacheBits]. (oldLabelState _ isLabelComplemented) ifTrue: [ self deEmphasize ]. self cacheBitsAsIs. (isLabelComplemented _ oldLabelState) ifTrue: [ self emphasize ]. ! ! !StandardSystemView methodsFor: 'displaying'! cacheBitsAsIs CacheBits ifFalse: [^ self uncacheBits]. windowBits _ (self cacheBitsAsTwoTone and: [Display depth > 1]) ifTrue: [ColorForm twoToneFromDisplay: self windowBox using: windowBits backgroundColor: self backgroundColor] ifFalse: [Form fromDisplay: self windowBox using: windowBits]. bitsValid _ true. ! ! !StandardSystemView methodsFor: 'displaying'! cacheBitsAsTwoTone ^ true! ! !StandardSystemView methodsFor: 'displaying'! deEmphasizeForDebugger "Carefully de-emphasis this window because a debugger is being opened. Care must be taken to avoid invoking potentially buggy window display code that could cause a recursive chain of errors eventually resulting in a virtual machine crash. In particular, do not de-emphasize the subviews." self deEmphasizeView. "de-emphasize this top-level view" self uncacheBits. Smalltalk garbageCollectMost > 1000000 ifTrue: [ "if there is enough space, cache current window screen bits" self cacheBitsAsIs]. ! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: false. self displayLabelText.! ! !StandardSystemView methodsFor: 'displaying'! display isLabelComplemented ifTrue: [self displayEmphasized] ifFalse: [self displayDeEmphasized]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'hmm 7/21/1999 07:37'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." (bitsValid and: [controller ~~ ScheduledControllers activeController]) ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [Display deferUpdates: true. super display. Display deferUpdates: false; forceToScreen: self windowBox. CacheBits ifTrue: [self cacheBitsAsIs]] ! ! !StandardSystemView methodsFor: 'displaying'! displayEmphasized "Display with label highlighted to indicate that it is active." self displayDeEmphasized; emphasize. isLabelComplemented _ true! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 5/15/1998 21:55'! displayLabelBackground: emphasized "Clear or emphasize the inner region of the label" | r1 r2 r3 c3 c2 c1 | emphasized ifFalse: ["Just clear the label if not emphasized" ^ Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor]. r1 _ self labelDisplayBox insetBy: 2. r2 _ r1 insetBy: 0@2. r3 _ r2 insetBy: 0@3. c3 _ self labelColor. c2 _ c3 dansDarker. c1 _ c2 dansDarker. Display fill: r1 fillColor: c1. Display fill: r2 fillColor: c2. Display fill: r3 fillColor: c3. " Here is the Mac racing stripe code stripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth) with: (Form black pixelWordForDepth: Display depth). self windowOrigin y even ifTrue: [stripes swap: 1 with: 2]. Display fill: (self labelDisplayBox insetBy: 3) fillColor: stripes. "! ! !StandardSystemView methodsFor: 'displaying'! displayLabelBoxes "closeBox, growBox." | aRect smallRect backColor | aRect _ self closeBoxFrame. backColor _ self labelColor. Display fill: (aRect insetBy: -2) fillColor: backColor. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. aRect _ self growBoxFrame. smallRect _ aRect origin extent: 7@7. Display fill: (aRect insetBy: -2) fillColor: backColor. aRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. Display fillBlack: smallRect. Display fill: (smallRect insetBy: 1) fillColor: backColor! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 9/10/1998 09:43'! displayLabelText "The label goes in the center of the window" | labelRect | labelText foregroundColor: self foregroundColor backgroundColor: self labelColor. labelRect _ self labelTextRegion. Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor. labelText displayOn: Display at: labelRect topLeft clippingBox: labelRect rule: labelText rule fillColor: labelText fillColor. labelText destinationForm: nil! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 8/29/97 18:57'! displayOn: aPort bitsValid ifFalse: [^ Display clippingTo: aPort clipRect do: [super display]]. windowBits displayOnPort: aPort at: self windowOrigin! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ar 5/14/2001 23:40'! displayRacingStripes "Display Racing Stripes in the label" | labelDisplayBox stripes top bottom left box right | labelDisplayBox _ self labelDisplayBox. top _ labelDisplayBox top + 3. bottom _ labelDisplayBox bottom - 3. stripes _ Bitmap with: (Display pixelWordFor: self labelColor) with: (Display pixelWordFor: Color black). top even ifFalse: [stripes swap: 1 with: 2]. left _ labelDisplayBox left + 3. box _ self closeBoxFrame. right _ box left - 2. Display fill: (Rectangle left: left right: right top: top bottom: bottom) fillColor: stripes. left _ box right + 2. box _ self labelTextRegion. right _ box left - 3. Display fill: (Rectangle left: left right: right top: top bottom: bottom) fillColor: stripes. left _ box right + 2. box _ self growBoxFrame. right _ box left - 2. Display fill: (Rectangle left: left right: right top: top bottom: bottom) fillColor: stripes. left _ box right + 2. right _ labelDisplayBox right - 3. Display fill: (Rectangle left: left right: right top: top bottom: bottom) fillColor: stripes. ! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:14'! displayView "Refer to the comment in View|displayView. " labelFrame height = 0 ifTrue: [^ self]. "no label" self displayBox width = labelFrame width ifFalse: ["recompute label width when window changes size" self setLabelRegion]. (labelFrame align: labelFrame topLeft with: self windowOrigin) insideColor: self labelColor; displayOn: Display. self displayLabelText! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 10/3/97 13:18'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: true. self displayLabelBoxes. self displayLabelText.! ! !StandardSystemView methodsFor: 'displaying' stamp: 'di 8/30/97 11:07'! erase "Clear the display box of the receiver to be gray, as the screen background." | oldValid | CacheBits ifTrue: [oldValid _ bitsValid. bitsValid _ false. ScheduledControllers restore: self windowBox without: self. bitsValid _ oldValid] ifFalse: [ScheduledControllers restore: self windowBox without: self]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'RAA 6/14/2000 17:27'! makeMeVisible | newLoc portRect | ((Display boundingBox insetBy: (0@0 corner: self labelHeight asPoint)) containsPoint: self displayBox topLeft) ifTrue: [^ self "OK -- my top left is visible"]. "window not on screen (probably due to reframe) -- move it now" newLoc _ self isCollapsed ifTrue: [RealEstateAgent assignCollapsePointFor: self] ifFalse: [(RealEstateAgent initialFrameFor: self world: nil) topLeft]. portRect _ newLoc + self labelOffset extent: self windowBox extent - self labelOffset. self resizeTo: portRect. self setLabelRegion. ! ! !StandardSystemView methodsFor: 'displaying'! uncacheBits windowBits _ nil. bitsValid _ false.! ! !StandardSystemView methodsFor: 'displaying'! windowBits ^ windowBits! ! !StandardSystemView methodsFor: 'deEmphasizing'! deEmphasizeView "Refer to the comment in View|deEmphasizeView." isLabelComplemented ifTrue: [self deEmphasizeLabel. isLabelComplemented _ false]! ! !StandardSystemView methodsFor: 'deEmphasizing'! emphasizeView "Refer to the comment in View|emphasizeView." self emphasizeLabel! ! !StandardSystemView methodsFor: 'clipping box access'! clippingBox "Answer the rectangular area in which the receiver can show its label." ^self isTopView ifTrue: [self labelDisplayBox] ifFalse: [super insetDisplayBox]! ! !StandardSystemView methodsFor: 'clipping box access' stamp: 'BG 12/5/2003 11:13'! constrainFrame: aRectangle "Constrain aRectangle, to the minimum and maximum size for this window" | adjustmentForLabel | adjustmentForLabel := 0 @ (labelFrame height - labelFrame borderWidth). ^ aRectangle origin extent: ((aRectangle extent max: minimumSize + adjustmentForLabel) min: maximumSize + adjustmentForLabel).! ! !StandardSystemView methodsFor: 'private'! setTransformation: aTransformation "Override to support label size changes " super setTransformation: aTransformation. self label: self label! ! !StandardSystemView methodsFor: 'private' stamp: 'di 10/21/1998 16:12'! subviewWithLongestSide: sideBlock near: aPoint | theSub theSide theLen box | theLen _ 0. subViews do: [:sub | box _ sub insetDisplayBox. box forPoint: aPoint closestSideDistLen: [:side :dist :len | (dist <= 5 and: [len > theLen]) ifTrue: [theSub _ sub. theSide _ side. theLen _ len]]]. sideBlock value: theSide. ^ theSub! ! !StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 12:57'! setUpdatablePanesFrom: getSelectors | aList aPane | "Set my updatablePanes inst var to the list of panes which are list panes with the given get-list selectors. Order is important here!! Note that the method is robust in the face of panes not found, but a warning is printed in the transcript in each such case" aList _ OrderedCollection new. getSelectors do: [:sel | aPane _ self subViewSatisfying: [:pane | (pane isKindOf: PluggableListView) and: [pane getListSelector == sel]]. aPane ifNotNil: [aList add: aPane] ifNil: [Transcript cr; show: 'Warning: view ', sel, ' not found.']]. updatablePanes _ aList asArray! ! !StandardSystemView methodsFor: 'updating' stamp: 'sw 10/29/1999 21:20'! updatablePanes "Answer the list of panes, in order, which might be sent the #verifyContents message upon window activation or expansion." ^ updatablePanes ifNil: [updatablePanes _ #()]! ! !StandardSystemView methodsFor: 'updating' stamp: 'sw 1/11/2000 15:30'! update: aSymbol aSymbol = #relabel ifTrue: [^ self setLabelTo: model labelString]. ^ super update: aSymbol! ! !StandardSystemView methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:49'! convertToCurrentVersion: varDict refStream: smartRefStrm updatablePanes ifNil: [updatablePanes _ #()]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StandardSystemView class instanceVariableNames: ''! !StandardSystemView class methodsFor: 'class initialization'! cachingBits ^ CacheBits! ! !StandardSystemView class methodsFor: 'class initialization'! doCacheBits "StandardSystemView doCacheBits - Enable fast window repaint feature" CacheBits _ true. ScheduledControllers unCacheWindows. ScheduledControllers restore! ! !StandardSystemView class methodsFor: 'class initialization'! dontCacheBits "StandardSystemView dontCacheBits - Disable fast window repaint feature. Return true iff bits were cached, ie if space was been recovered" CacheBits ifFalse: [^ false]. CacheBits _ false. ScheduledControllers unCacheWindows. ^ true! ! !StandardSystemView class methodsFor: 'class initialization' stamp: 'sw 12/6/1999 23:42'! initialize "StandardSystemView initialize" self doCacheBits. self setLabelStyle! ! !StandardSystemView class methodsFor: 'class initialization' stamp: 'nk 7/11/2004 21:11'! setLabelStyle | aFont | "StandardSystemView setLabelStyle" aFont _ Preferences windowTitleFont. LabelStyle _ TextStyle fontArray: { aFont }. LabelStyle gridForFont: 1 withLead: 0! ! !StandardSystemView class methodsFor: 'instance creation' stamp: 'ssa 8/15/2008 17:42'! model: aModel label: aString minimumSize: aPoint ^self new model: aModel; label: aString; minimumSize: aPoint; yourself! ! ChangeSetCategory subclass: #StaticChangeSetCategory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !StaticChangeSetCategory commentStamp: '<historical>' prior: 0! StaticChangeSetCategory is a user-defined change-set category that has in it only those change sets specifically placed there.! !StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:10'! acceptsManualAdditions "Answer whether the user is allowed manually to manipulate the contents of the change-set-category." ^ true! ! !StaticChangeSetCategory methodsFor: 'queries' stamp: 'sw 4/11/2001 16:00'! includesChangeSet: aChangeSet "Answer whether the receiver includes aChangeSet in its retrieval list" ^ elementDictionary includesKey: aChangeSet name! ! !StaticChangeSetCategory methodsFor: 'add' stamp: 'sw 4/11/2001 15:58'! addChangeSet: aChangeSet "Add the change set manually" self elementAt: aChangeSet name put: aChangeSet! ! !StaticChangeSetCategory methodsFor: 'updating' stamp: 'sw 4/11/2001 16:36'! reconstituteList "Reformulate the list. Here, since we have a manually-maintained list, at this juncture we only make sure change-set-names are still up to date, and we purge moribund elements" | survivors | survivors _ elementDictionary select: [:aChangeSet | aChangeSet isMoribund not]. self clear. (survivors asSortedCollection: [:a :b | a name <= b name]) reverseDo: [:aChangeSet | self addChangeSet: aChangeSet]! ! Form subclass: #StaticForm instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Display Objects'! !StaticForm commentStamp: '<historical>' prior: 0! An optimization for Nebraska - a StaticForm does not change once created so it may be cached on the remote end.! !StaticForm methodsFor: 'as yet unclassified' stamp: 'RAA 8/14/2000 09:59'! isStatic ^true! ! Object subclass: #Stopwatch instanceVariableNames: 'timespans state' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Chronology'! !Stopwatch commentStamp: '<historical>' prior: 0! A Stopwatch maintains a collection of timespans.! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:12'! activate self isSuspended ifTrue: [self timespans add: (Timespan starting: DateAndTime now duration: Duration zero). self state: #active] ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:45'! duration | ts last | self isSuspended ifTrue: [ (ts _ self timespans) isEmpty ifTrue: [ ts _ { Timespan starting: DateAndTime now duration: Duration zero } ] ] ifFalse: [ last _ self timespans last. ts _ self timespans allButLast add: (last duration: (DateAndTime now - last start); yourself); yourself ]. ^ (ts collect: [ :t | t duration ]) sum ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:21'! end ^ self timespans last next ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'! isActive ^ self state = #active ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:48'! isSuspended ^ self state = #suspended ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 13:25'! printOn: aStream super printOn: aStream. aStream nextPut: $(; nextPutAll: self state; nextPut: $:; print: self duration; nextPut: $). ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 11:54'! reset self suspend. timespans _ nil. ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:18'! start ^ self timespans first start ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:47'! state ^ state ifNil: [ state _ #suspended ] ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:46'! state: aSymbol state _ aSymbol ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 23:13'! suspend | ts | self isActive ifTrue: [ ts _ self timespans last. ts duration: (DateAndTime now - ts start). self state: #suspended] ! ! !Stopwatch methodsFor: 'squeak protocol' stamp: 'brp 9/24/2003 22:44'! timespans ^ timespans ifNil: [ timespans _ OrderedCollection new ] ! ! Object subclass: #Stream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !Stream commentStamp: '<historical>' prior: 0! I am an abstract class that represents an accessor for a sequence of objects. This sequence is referred to as my "contents".! !Stream methodsFor: 'accessing' stamp: 'nk 2/24/2001 17:31'! binary! ! !Stream methodsFor: 'accessing'! contents "Answer all of the contents of the receiver." self subclassResponsibility! ! !Stream methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:07'! flush "Do nothing by default"! ! !Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:38'! localName ^'a stream'! ! !Stream methodsFor: 'accessing'! next "Answer the next object accessible by the receiver." self subclassResponsibility! ! !Stream methodsFor: 'accessing'! next: anInteger "Answer the next anInteger number of objects accessible by the receiver." | aCollection | aCollection _ OrderedCollection new. anInteger timesRepeat: [aCollection addLast: self next]. ^aCollection! ! !Stream methodsFor: 'accessing'! next: anInteger put: anObject "Make anObject be the next anInteger number of objects accessible by the receiver. Answer anObject." anInteger timesRepeat: [self nextPut: anObject]. ^anObject! ! !Stream methodsFor: 'accessing'! nextMatchAll: aColl "Answer true if next N objects are the ones in aColl, else false. Advance stream of true, leave as was if false." | save | save _ self position. aColl do: [:each | (self next) = each ifFalse: [ self position: save. ^ false] ]. ^ true! ! !Stream methodsFor: 'accessing'! nextMatchFor: anObject "Gobble the next object and answer whether it is equal to the argument, anObject." ^anObject = self next! ! !Stream methodsFor: 'accessing'! nextPut: anObject "Insert the argument, anObject, as the next object accessible by the receiver. Answer anObject." self subclassResponsibility! ! !Stream methodsFor: 'accessing'! nextPutAll: aCollection "Append the elements of aCollection to the sequence of objects accessible by the receiver. Answer aCollection." aCollection do: [:v | self nextPut: v]. ^aCollection! ! !Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:40'! openReadOnly ^self! ! !Stream methodsFor: 'accessing' stamp: 'ajh 7/31/2001 20:34'! printOn: stream super printOn: stream. stream space. self contents printOn: stream. ! ! !Stream methodsFor: 'accessing' stamp: 'nk 4/29/2004 10:41'! readOnly ^self! ! !Stream methodsFor: 'accessing' stamp: 'ls 9/12/1998 20:55'! upToEnd "answer the remaining elements in the string" | elements | elements _ OrderedCollection new. [ self atEnd ] whileFalse: [ elements add: self next ]. ^elements! ! !Stream methodsFor: 'testing'! atEnd "Answer whether the receiver can access any more objects." self subclassResponsibility! ! !Stream methodsFor: 'testing'! closed ^true! ! !Stream methodsFor: 'testing' stamp: 'ar 12/23/1999 15:43'! isStream "Return true if the receiver responds to the stream protocol" ^true! ! !Stream methodsFor: 'testing' stamp: 'ar 5/17/2001 19:07'! nextWordsPutAll: aCollection "Write the argument a word-like object in big endian format on the receiver. May be used to write other than plain word-like objects (such as ColorArray)." aCollection class isPointers | aCollection class isWords not ifTrue: [^self error: aCollection class name,' is not word-like']. 1 to: aCollection basicSize do:[:i| self nextNumber: 4 put: (aCollection basicAt: i). ]. ^aCollection! ! !Stream methodsFor: 'enumerating'! do: aBlock "Evaluate aBlock for each of the objects accessible by receiver." [self atEnd] whileFalse: [aBlock value: self next]! ! !Stream methodsFor: 'printing' stamp: 'sma 6/1/2000 09:56'! print: anObject "Have anObject print itself on the receiver." anObject printOn: self! ! !Stream methodsFor: 'printing' stamp: 'djp 7/21/1998 17:13'! printHtml: anObject anObject printHtmlOn: self! ! !Stream methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 00:48'! write:encodedObject ^encodedObject putOn:self. ! ! !Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:52'! dialect ^#ST80 "in case a regular stream is used to print parse nodes"! ! !Stream methodsFor: 'alternate syntax' stamp: 'RAA 6/20/2000 12:54'! withStyleFor: elementType do: aBlock ^aBlock value "in case a regular stream is used to print parse nodes" ">> (Compiler new compile: 'blah ^self' in: String notifying: nil ifFail: []) printString <<"! ! !Stream methodsFor: 'as yet unclassified' stamp: 'RAA 9/11/2000 19:12'! sleep "an FTP-based stream might close the connection here"! ! !Stream methodsFor: 'file open/close' stamp: 'mir 8/10/1999 12:04'! close! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Stream class instanceVariableNames: ''! !Stream class methodsFor: 'instance creation'! new self error: 'Streams are created with on: and with:'! ! AbstractFont subclass: #StrikeFont instanceVariableNames: 'characterToGlyphMap xTable glyphs name type minAscii maxAscii maxWidth strikeLength ascent descent xOffset raster subscript superscript emphasis derivativeFonts pointSize' classVariableNames: 'DefaultStringScanner' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !StrikeFont commentStamp: 'dew 1/1/2004 20:58' prior: 0! 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 glyphs. Characters are mapped to glyphs by using the characterToGyphMap. Subclasses can have non-trivial mapping rules as well as different representations for glyphs sizes (e.g., not using an xTable). If so, these classes should return nil when queried for xTable and/or the characterToGlyphMap. This will cause the CharacterScanner primitive to fail and query the font for the width of a character (so that a more programatical approach can be implemented). For display, fonts need to implement two messages: #installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor This method installs the receiver (a font) on the given DisplayContext (which may be an instance of BitBlt or Canvas (or any of it's subclasses). The font should take the appropriate action to initialize the display context so that further display operations can be optimized. #displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta This method is called for each subsequent run of characters in aString which is to be displayed with the (previously installed) settings. -------------------------------- The "AccuFont" StrikeFonts by Doug Easterbrook were added to the Squeak image for the 3.7 release. The following acknowledgement must remain in the image (in this class comment) as long as the Accufonts are in the image: >Doug Easterbrook >Arts Management Systems Ltd. >mailto:doug@artsman.com >http://www.artsman.com >Phone (403) 215-5701 Fax (403) 215-5704 ! !StrikeFont methodsFor: 'accessing'! ascent "Answer the receiver's maximum extent of characters above the baseline." ^ascent! ! !StrikeFont methodsFor: 'accessing' stamp: 'di 9/1/2000 17:17'! baseKern "Return the base kern value to be used for all characters." (emphasis noMask: 2) ifTrue: [^ 0]. ^ ((self height-1-self ascent+4)//4 max: 0) "See makeItalicGlyphs" + (((self ascent-5+4)//4 max: 0)) ! ! !StrikeFont methodsFor: 'accessing' stamp: 'ar 5/23/2000 12:52'! characterToGlyphMap ^characterToGlyphMap ifNil:[characterToGlyphMap _ self createCharacterToGlyphMap].! ! !StrikeFont methodsFor: 'accessing'! descent "Answer the receiver's maximum extent of characters below the baseline." ^descent! ! !StrikeFont methodsFor: 'accessing' stamp: 'di 9/2/2000 13:06'! descentKern "Return the kern delta for descenders." (emphasis noMask: 2) ifTrue: [^ 0]. ^ (self height-1-self ascent+4)//4 max: 0 "See makeItalicGlyphs" ! ! !StrikeFont methodsFor: 'accessing'! familyName ^self name withoutTrailingDigits. ! ! !StrikeFont methodsFor: 'accessing' stamp: 'tk 6/26/1998 16:45'! familySizeFace "Answer an array with familyName, a String, pointSize, an Integer, and faceCode, an Integer." ^Array with: name with: self height with: emphasis "(1 to: 12) collect: [:x | (TextStyle default fontAt: x) familySizeFace]"! ! !StrikeFont methodsFor: 'accessing' stamp: 'ar 9/21/2000 11:53'! fontNameWithPointSize ^self name withoutTrailingDigits, ' ', self pointSize printString! ! !StrikeFont methodsFor: 'accessing'! glyphs "Answer a Form containing the bits representing the characters of the receiver." ^glyphs! ! !StrikeFont methodsFor: 'accessing'! height "Answer the height of the receiver, total of maximum extents of characters above and below the baseline." ^self ascent + self descent! ! !StrikeFont methodsFor: 'accessing'! lineGrid ^ ascent + descent! ! !StrikeFont methodsFor: 'accessing'! maxAscii "Answer the integer that is the last Ascii character value of the receiver." ^maxAscii! ! !StrikeFont methodsFor: 'accessing'! maxWidth "Answer the integer that is the width of the receiver's widest character." ^maxWidth! ! !StrikeFont methodsFor: 'accessing'! minAscii "Answer the integer that is the first Ascii character value of the receiver." ^minAscii! ! !StrikeFont methodsFor: 'accessing' stamp: 'ls 3/27/2000 19:54'! name "Answer the receiver's name." ^name ifNil: ['(unnamed)']! ! !StrikeFont methodsFor: 'accessing'! name: aString "Set the receiver's name." name _ aString! ! !StrikeFont methodsFor: 'accessing' stamp: 'sw 1/18/2000 20:54'! pointSize ^ pointSize! ! !StrikeFont methodsFor: 'accessing' stamp: 'nk 6/17/2003 14:26'! textStyle ^ TextStyle actualTextStyles detect: [:aStyle | aStyle fontArray includes: self] ifNone: [nil]! ! !StrikeFont methodsFor: 'accessing' stamp: 'ar 12/31/2001 01:15'! widthOf: aCharacter "Answer the width of the argument as a character in the receiver." | ascii | ascii _ aCharacter asciiValue. (ascii >= minAscii and:[ascii <= maxAscii]) ifFalse: [ascii _ maxAscii + 1]. ^ (xTable at: ascii + 2) - (xTable at: ascii + 1) ! ! !StrikeFont methodsFor: 'accessing'! xTable "Answer an Array of the left x-coordinate of characters in glyphs." ^xTable! ! !StrikeFont methodsFor: 'displaying' stamp: 'ar 5/28/2000 12:11'! characters: anInterval in: sourceString displayAt: aPoint clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm "Simple, slow, primitive method for displaying a line of characters. No wrap-around is provided." | ascii destPoint bb leftX rightX sourceRect | destPoint _ aPoint. bb _ BitBlt current toForm: Display. anInterval do: [:i | ascii _ (sourceString at: i) asciiValue. (ascii < minAscii or: [ascii > maxAscii]) ifTrue: [ascii _ maxAscii]. leftX _ xTable at: ascii + 1. rightX _ xTable at: ascii + 2. sourceRect _ leftX@0 extent: (rightX-leftX) @ self height. bb copyFrom: sourceRect in: glyphs to: destPoint. destPoint _ destPoint + ((rightX-leftX)@0)]. ^ destPoint! ! !StrikeFont methodsFor: 'displaying'! displayLine: aString at: aPoint "Display the characters in aString, starting at position aPoint." self characters: (1 to: aString size) in: aString displayAt: aPoint clippedBy: Display boundingBox rule: Form over fillColor: nil! ! !StrikeFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 15:09'! displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta "Draw the given string from startIndex to stopIndex at aPoint on the (already prepared) BitBlt." aBitBlt displayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: self kern: kernDelta.! ! !StrikeFont methodsFor: 'displaying' stamp: 'ar 5/19/2000 15:08'! installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor ^aDisplayContext installStrikeFont: self foregroundColor: foregroundColor backgroundColor: backgroundColor! ! !StrikeFont methodsFor: 'displaying' stamp: 'ar 12/31/2001 00:55'! widthOfString: aString from: firstIndex to: lastIndex "Measure the length of the given string between start and stop index" DefaultStringScanner ifNil:[DefaultStringScanner _ CharacterScanner new initializeStringMeasurer]. ^DefaultStringScanner measureString: aString inFont: self from: firstIndex to: lastIndex ! ! !StrikeFont methodsFor: 'emphasis' stamp: 'ar 5/28/2000 12:11'! bonk: glyphForm with: bonkForm "Bonking means to run through the glyphs clearing out black pixels between characters to prevent them from straying into an adjacent character as a result of, eg, bolding or italicizing" "Uses the bonkForm to erase at every character boundary in glyphs." | bb offset | offset _ bonkForm offset x. bb _ BitBlt current toForm: glyphForm. bb sourceForm: bonkForm; sourceRect: bonkForm boundingBox; combinationRule: Form erase; destY: 0. 1 to: xTable size-1 do: [:i | bb destX: (xTable at: i) + offset; copyBits]. ! ! !StrikeFont methodsFor: 'emphasis'! emphasis: code "Set the integer code for synthetic bold, itallic, underline, and strike-out, where bold=1, italic=2, underlined=4, and struck out=8." emphasis _ code! ! !StrikeFont methodsFor: 'emphasis' stamp: 'di 9/3/2000 13:22'! emphasized: code "Answer a copy of the receiver with emphasis set to include code." | derivative addedEmphasis base safeCode | code = 0 ifTrue: [^ self]. (derivativeFonts == nil or: [derivativeFonts size = 0]) ifTrue: [^ self]. derivative _ derivativeFonts at: (safeCode _ code min: derivativeFonts size). derivative == nil ifFalse: [^ derivative]. "Already have this style" "Dont have it -- derive from another with one with less emphasis" addedEmphasis _ 1 bitShift: safeCode highBit - 1. base _ self emphasized: safeCode - addedEmphasis. "Order is Bold, Ital, Under, Narrow" addedEmphasis = 1 ifTrue: "Compute synthetic bold version of the font" [derivative _ (base copy ensureCleanBold name: base name , 'B') makeBoldGlyphs]. addedEmphasis = 2 ifTrue: "Compute synthetic italic version of the font" [ derivative _ (base copy name: base name , 'I') makeItalicGlyphs]. addedEmphasis = 4 ifTrue: "Compute underlined version of the font" [derivative _ (base copy name: base name , 'U') makeUnderlinedGlyphs]. addedEmphasis = 8 ifTrue: "Compute narrow version of the font" [derivative _ (base copy name: base name , 'N') makeCondensedGlyphs]. addedEmphasis = 16 ifTrue: "Compute struck-out version of the font" [derivative _ (base copy name: base name , 'X') makeStruckOutGlyphs]. derivative emphasis: safeCode. derivativeFonts at: safeCode put: derivative. ^ derivative! ! !StrikeFont methodsFor: 'emphasis'! makeBoldGlyphs "Make a bold set of glyphs with same widths by ORing 1 bit to the right (requires at least 1 pixel of intercharacter space)" | g bonkForm | g _ glyphs deepCopy. bonkForm _ (Form extent: 1@16) fillBlack offset: -1@0. self bonk: g with: bonkForm. g copyBits: g boundingBox from: g at: (1@0) clippingBox: g boundingBox rule: Form under fillColor: nil. glyphs _ g! ! !StrikeFont methodsFor: 'emphasis' stamp: 'di 10/31/97 13:18'! makeCondensedGlyphs "Make a condensed set of glyphs with same widths. NOTE: this has been superceded by kerning -- should not get called" | g newXTable x x1 w | g _ glyphs deepCopy. newXTable _ Array new: xTable size. newXTable at: 1 put: (x _ xTable at: 1). 1 to: xTable size-1 do: [:i | x1 _ xTable at: i. w _ (xTable at: i+1) - x1. w > 1 ifTrue: [w _ w-1]. "Shrink every character wider than 1" g copy: (x@0 extent: w@g height) from: x1@0 in: glyphs rule: Form over. newXTable at: i+1 put: (x _ x + w)]. xTable _ newXTable. glyphs _ g " (TextStyle default fontAt: 1) copy makeCondensedGlyphs displayLine: 'The quick brown fox jumps over the lazy dog' at: Sensor cursorPoint "! ! !StrikeFont methodsFor: 'emphasis' stamp: 'BG 10/6/2002 13:20'! makeItalicGlyphs "Make an italic set of glyphs with same widths by skewing left and right. In the process, characters would overlap, so we widen them all first. " | extraWidth newGlyphs newXTable x newX w extraOnLeft | extraOnLeft _ (self height-1-self ascent+4)//4 max: 0. extraWidth _ ((self ascent-5+4)//4 max: 0) + extraOnLeft. newGlyphs _ Form extent: (glyphs width + (maxAscii + 1 - minAscii*extraWidth)) @ glyphs height. newXTable _ xTable copy. "Copy glyphs into newGlyphs with room on left and right for overlap." minAscii to: maxAscii+1 do: [:ascii | x _ xTable at: ascii+1. w _ (xTable at: ascii+2) - x. newX _ newXTable at: ascii+1. newGlyphs copy: ((newX + extraOnLeft) @ 0 extent: w @ glyphs height) from: x @ 0 in: glyphs rule: Form over. newXTable at: ascii+2 put: newX + w + extraWidth]. glyphs _ newGlyphs. xTable _ newXTable. "Slide the bitmaps left and right for synthetic italic effect." 4 to: self ascent-1 by: 4 do: [:y | "Slide ascenders right..." glyphs copy: (1@0 extent: glyphs width @ (self ascent - y)) from: 0@0 in: glyphs rule: Form over]. self ascent to: self height-1 by: 4 do: [:y | "Slide descenders left..." glyphs copy: (0@y extent: glyphs width @ glyphs height) from: 1@y in: glyphs rule: Form over]. ! ! !StrikeFont methodsFor: 'emphasis'! makeStruckOutGlyphs "Make a struck-out set of glyphs with same widths" | g | g _ glyphs deepCopy. g fillBlack: (0 @ (self ascent - (self ascent//3)) extent: g width @ 1). glyphs _ g ! ! !StrikeFont methodsFor: 'emphasis'! makeUnderlinedGlyphs "Make an underlined set of glyphs with same widths" | g | g _ glyphs deepCopy. g fillBlack: (0 @ (self ascent+1) extent: g width @ 1). glyphs _ g ! ! !StrikeFont methodsFor: 'emphasis' stamp: 'nk 3/15/2004 18:46'! releaseCachedState self reset.! ! !StrikeFont methodsFor: 'emphasis' stamp: 'sma 12/30/1999 15:02'! reset "Reset the cache of derivative emphasized fonts" | style font | derivativeFonts _ Array new: 32. #('B' 'I' 'BI') doWithIndex: [:tag :index | (style _ TextStyle named: self familyName) ifNotNil: [(font _ style fontArray detect: [:each | each name = (self name , tag)] ifNone: [nil]) ifNotNil: [derivativeFonts at: index put: font]]]! ! !StrikeFont methodsFor: 'file in/out' stamp: 'sma 6/1/2000 09:32'! printOn: aStream super printOn: aStream. aStream nextPut: $(; nextPutAll: self name; space; print: self height; nextPut: $)! ! !StrikeFont methodsFor: 'file in/out' stamp: 'sma 12/30/1999 14:20'! readFromStrike2: fileName "StrikeFont new readFromStrike2: 'Palatino14.sf2'" "Build an instance from the strike font stored in strike2 format. fileName is of the form: <family name><pointSize>.sf2" | file | ('*.sf2' match: fileName) ifFalse: [self halt. "likely incompatible"]. name _ fileName copyUpTo: $. . "Drop filename extension" file _ FileStream readOnlyFileNamed: fileName. file binary. [self readFromStrike2Stream: file] ensure: [file close]! ! !StrikeFont methodsFor: 'file in/out' stamp: 'ar 5/23/2000 12:53'! readFromStrike2Stream: file "Build an instance from the supplied binary stream on data in strike2 format" type _ file nextInt32. type = 2 ifFalse: [file close. self error: 'not strike2 format']. minAscii _ file nextInt32. maxAscii _ file nextInt32. maxWidth _ file nextInt32. ascent _ file nextInt32. descent _ file nextInt32. pointSize _ file nextInt32. superscript _ ascent - descent // 3. subscript _ descent - ascent // 3. emphasis _ file nextInt32. xTable _ (Array new: maxAscii + 3) atAllPut: 0. (minAscii + 1 to: maxAscii + 3) do: [:index | xTable at: index put: file nextInt32]. glyphs _ Form new readFrom: file. "Set up space character" ((xTable at: (Space asciiValue + 2)) = 0 or: [(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))]) ifTrue: [(Space asciiValue + 2) to: xTable size do: [:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]]. characterToGlyphMap _ nil.! ! !StrikeFont methodsFor: 'character shapes' stamp: 'di 3/27/2000 14:25'! characterFormAt: character "Answer a Form copied out of the glyphs for the argument, character." | ascii leftX rightX | ascii _ character asciiValue. (ascii between: minAscii and: maxAscii) ifFalse: [ascii _ maxAscii + 1]. leftX _ xTable at: ascii + 1. rightX _ xTable at: ascii + 2. ^ glyphs copy: (leftX @ 0 corner: rightX @ self height)! ! !StrikeFont methodsFor: 'character shapes' stamp: 'di 8/30/2000 10:00'! characterFormAt: character put: characterForm "Copy characterForm over the glyph for the argument, character." | ascii leftX rightX widthDif newGlyphs | ascii _ character asciiValue. ascii < minAscii ifTrue: [^ self error: 'Cant store characters below min ascii']. ascii > maxAscii ifTrue: [(self confirm: 'This font does not accomodate ascii values higher than ' , maxAscii printString , '. Do you wish to extend it permanently to handle values up to ' , ascii printString) ifTrue: [self extendMaxAsciiTo: ascii] ifFalse: [^ self error: 'No change made']]. leftX _ xTable at: ascii + 1. rightX _ xTable at: ascii + 2. widthDif _ characterForm width - (rightX - leftX). widthDif ~= 0 ifTrue: ["Make new glyphs with more or less space for this char" newGlyphs _ Form extent: (glyphs width + widthDif) @ glyphs height. newGlyphs copy: (0@0 corner: leftX@glyphs height) from: 0@0 in: glyphs rule: Form over. newGlyphs copy: ((rightX+widthDif)@0 corner: newGlyphs width@glyphs height) from: rightX@0 in: glyphs rule: Form over. glyphs _ newGlyphs. "adjust further entries on xTable" xTable _ xTable copy. ascii+2 to: xTable size do: [:i | xTable at: i put: (xTable at: i) + widthDif]]. glyphs copy: (leftX @ 0 extent: characterForm extent) from: 0@0 in: characterForm rule: Form over " | f | f _ TextStyle defaultFont. f characterFormAt: $ put: (Form extent: (f widthOf: $ )+10@f height) "! ! !StrikeFont methodsFor: 'character shapes' stamp: 'di 8/30/2000 10:15'! ensureCleanBold "This ensures that all character glyphs have at least one pixel of white space on the right so as not to cause artifacts in neighboring characters in bold or italic." | wider glyph | emphasis = 0 ifFalse: [^ self]. minAscii to: maxAscii do: [:i | glyph _ self characterFormAt: (Character value: i). (glyph copy: (glyph boundingBox topRight - (1@0) corner: glyph boundingBox bottomRight)) isAllWhite ifFalse: [wider _ Form extent: (glyph width + 1)@glyph height. glyph displayOn: wider. self characterFormAt: (Character value: i) put: wider]]. " StrikeFont allInstancesDo: [:f | f ensureCleanBold]. (StrikeFont familyName: 'NewYork' size: 21) ensureCleanBold. StrikeFont shutDown. 'Flush synthetic fonts'. " ! ! !StrikeFont methodsFor: 'character shapes' stamp: 'ar 5/23/2000 12:48'! extendMaxAsciiTo: newMax "Extend the range of this font so that it can display glyphs up to newMax." (newMax+3) <= xTable size ifTrue: [^ self]. "No need to extend." xTable size = (maxAscii+3) ifFalse: [^ self error: 'This font is not well-formed.']. "Insert a bunch of zero-width characters..." xTable _ (xTable copyFrom: 1 to: maxAscii+2) , ((maxAscii+1 to: newMax) collect: [:i | xTable at: maxAscii+2]) , { xTable at: maxAscii+3 }. maxAscii _ newMax. self fillZeroWidthSlots. characterToGlyphMap _ nil.! ! !StrikeFont methodsFor: 'character shapes' stamp: 'di 3/27/2000 16:10'! fillZeroWidthSlots | nullGlyph | "Note: this is slow because it copies the font once for every replacement." nullGlyph _ (Form extent: 1@glyphs height) fillGray. "Now fill the empty slots with narrow box characters." minAscii to: maxAscii do: [:i | (self widthOf: (Character value: i)) = 0 ifTrue: [self characterFormAt: (Character value: i) put: nullGlyph]]. ! ! !StrikeFont methodsFor: 'copying' stamp: 'tk 8/19/1998 16:15'! veryDeepCopyWith: deepCopier "Return self. I am shared. Do not record me."! ! !StrikeFont methodsFor: 'private' stamp: 'ar 5/18/2000 18:13'! createCharacterToGlyphMap "Private. Create the character to glyph mapping for a font that didn't have any before. This is basically equivalent to what the former setStopCondition did, only based on indexes." | map | map _ Array new: 256. 0 to: minAscii - 1 do:[:i| map at: i + 1 put: maxAscii + 1]. minAscii to: maxAscii do:[:i| map at: i + 1 put: i]. maxAscii + 1 to: 255 do:[:i| map at: i + 1 put: maxAscii + 1]. ^map! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StrikeFont class instanceVariableNames: ''! !StrikeFont class methodsFor: 'examples'! example "Displays a line of text on the display screen at the location of the cursor. Example depends on the strike font file, 'TimesRoman10.strike'. existing." (StrikeFont new readFromStrike2: 'NewYork12.sf2') displayLine: 'A line of 12-pt text in New York style' at: Sensor cursorPoint "StrikeFont example."! ! !StrikeFont class methodsFor: 'examples' stamp: 'nop 2/11/2001 13:35'! readStrikeFont2Family: familyName "StrikeFont readStrikeFont2Family: 'Lucida'" "This utility reads all available .sf2 StrikeFont files for a given family from the current directory. It returns an Array, sorted by size, suitable for handing to TextStyle newFontArray: ." "For this utility to work as is, the .sf2 files must be named 'familyNN.sf2'." | fileNames strikeFonts fontArray | fileNames _ FileDirectory default fileNamesMatching: familyName , '##.sf2'. strikeFonts _ fileNames collect: [:fname | StrikeFont new readFromStrike2: fname]. strikeFonts do: [ :font | font reset ]. strikeFonts _ strikeFonts asSortedCollection: [:a :b | a height < b height]. fontArray _ strikeFonts asArray. ^ fontArray "TextConstants at: #Lucida put: (TextStyle fontArray: (StrikeFont readStrikeFont2Family: 'Lucida'))."! ! !StrikeFont class methodsFor: 'derivative font caching' stamp: 'tk 6/24/1999 11:45'! shutDown "StrikeFont shutDown" "Deallocate synthetically derived copies of base fonts to save space" self allSubInstancesDo: [:sf | sf reset]! ! !StrikeFont class methodsFor: 'accessing' stamp: 'nk 6/17/2003 15:15'! actualFamilyNames "Answer a sorted list of actual family names, without the Default aliases" ^(self familyNames copyWithoutAll: #(DefaultTextStyle DefaultFixedTextStyle)) asOrderedCollection! ! !StrikeFont class methodsFor: 'accessing' stamp: 'sma 12/30/1999 13:53'! familyName: aName size: aSize "Answer a font (or the default font if the name is unknown) in the specified size." ^ ((TextStyle named: aName asSymbol) ifNil: [TextStyle default]) fontOfSize: aSize! ! !StrikeFont class methodsFor: 'accessing' stamp: 'sma 12/30/1999 13:48'! familyNames ^ (TextConstants select: [:each | each isKindOf: TextStyle]) keys asSortedCollection! ! ArrayedCollection variableByteSubclass: #String instanceVariableNames: '' classVariableNames: 'AsciiOrder CSLineEnders CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder HtmlEntities LowercasingTable Tokenish UppercasingTable' poolDictionaries: '' category: 'Collections-Text'! !String commentStamp: '<historical>' prior: 0! A String is an indexed collection of Characters, compactly encoded as 8-bit bytes. String support a vast array of useful methods, which can best be learned by browsing and trying out examples as you find them in the code. Here are a few useful methods to look at... String match: String contractTo: String also inherits many useful methods from its hierarchy, such as SequenceableCollection , SequenceableCollection copyReplaceAll:with:! ]style[(269 13 2 18 72 24 2 43)f1,f1LString match:;,f1,f1LString contractTo:;,f1,f1LSequenceableCollection ,;,f1,f1LSequenceableCollection copyReplaceAll:with:;! !String methodsFor: 'accessing'! at: index "Primitive. Answer the Character stored in the field of the receiver indexed by the argument. Fail if the index argument is not an Integer or is out of bounds. Essential. See Object documentation whatIsAPrimitive." <primitive: 63> ^Character value: (super at: index)! ! !String methodsFor: 'accessing' stamp: 'wod 6/16/1998 15:24'! at: index put: aCharacter "Primitive. Store the Character in the field of the receiver indicated by the index. Fail if the index is not an Integer or is out of bounds, or if the argument is not a Character. Essential. See Object documentation whatIsAPrimitive." <primitive: 64> (aCharacter isKindOf: Character) ifTrue: [ index isInteger ifTrue: [self errorSubscriptBounds: index] ifFalse: [self errorNonIntegerIndex]] ifFalse: [self error: 'Strings only store Characters']! ! !String methodsFor: 'accessing' stamp: 'ar 12/27/1999 13:44'! byteAt: index <primitive: 60> ^(self at: index) asciiValue! ! !String methodsFor: 'accessing' stamp: 'ar 12/27/1999 13:44'! byteAt: index put: value <primitive: 61> self at: index put: value asCharacter. ^value! ! !String methodsFor: 'accessing' stamp: 'ar 3/3/2001 16:17'! byteSize ^self size! ! !String methodsFor: 'accessing' stamp: 'sw 12/6/2001 16:08'! do: aBlock toFieldNumber: aNumber "Considering the receiver as a holder of tab-delimited fields, evaluate aBlock on behalf of a field in this string" | start end index | start _ 1. index _ 1. [start <= self size] whileTrue: [end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1]. end _ end - 1. aNumber = index ifTrue: [aBlock value: (self copyFrom: start to: end). ^ self]. index _ index + 1. start _ end + 2] " 1 to: 6 do: [:aNumber | 'fred charlie elmo wimpy friml' do: [:aField | Transcript cr; show: aField] toFieldNumber: aNumber] "! ! !String methodsFor: 'accessing'! endsWithDigit "Answer whether the receiver's final character represents a digit. 3/11/96 sw" ^ self size > 0 and: [self last isDigit]! ! !String methodsFor: 'accessing' stamp: 'tk 12/26/97 11:09'! findAnySubStr: delimiters startingAt: start "Answer the index of the character within the receiver, starting at start, that begins a substring matching one of the delimiters. delimiters is an Array of Strings (Characters are permitted also). If the receiver does not contain any of the delimiters, answer size + 1." | min ind | min _ self size + 1. delimiters do: [:delim | "May be a char, a string of length 1, or a substring" delim class == Character ifTrue: [ind _ self indexOfSubCollection: (String with: delim) startingAt: start ifAbsent: [min]] ifFalse: [ind _ self indexOfSubCollection: delim startingAt: start ifAbsent: [min]]. min _ min min: ind]. ^ min! ! !String methodsFor: 'accessing' stamp: 'dew 11/15/2000 15:02'! findBetweenSubStrs: delimiters "Answer the collection of String tokens that result from parsing self. Tokens are separated by 'delimiters', which can be a collection of Strings, or a collection of Characters. Several delimiters in a row are considered as just one separation." | tokens keyStart keyStop | tokens _ OrderedCollection new. keyStop _ 1. [keyStop <= self size] whileTrue: [keyStart _ self skipAnySubStr: delimiters startingAt: keyStop. keyStop _ self findAnySubStr: delimiters startingAt: keyStart. keyStart < keyStop ifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]]. ^tokens! ! !String methodsFor: 'accessing' stamp: 'ls 3/19/2000 16:43'! findCloseParenthesisFor: startIndex "assume (self at: startIndex) is $(. Find the matching $), allowing parentheses to nest." " '(1+(2-3))-3.14159' findCloseParenthesisFor: 1 " " '(1+(2-3))-3.14159' findCloseParenthesisFor: 4 " | pos nestLevel | pos := startIndex+1. nestLevel := 1. [ pos <= self size ] whileTrue: [ (self at: pos) = $( ifTrue: [ nestLevel := nestLevel + 1 ]. (self at: pos) = $) ifTrue: [ nestLevel := nestLevel - 1 ]. nestLevel = 0 ifTrue: [ ^pos ]. pos := pos + 1. ]. ^self size + 1! ! !String methodsFor: 'accessing'! findDelimiters: delimiters startingAt: start "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." start to: self size do: [:i | delimiters do: [:delim | delim = (self at: i) ifTrue: [^ i]]]. ^ self size + 1! ! !String methodsFor: 'accessing' stamp: 'ar 4/11/1999 22:15'! findString: subString "Answer the index of subString within the receiver, starting at start. If the receiver does not contain subString, answer 0." ^self findString: subString startingAt: 1.! ! !String methodsFor: 'accessing' stamp: 'di 11/15/1998 16:43'! findString: subString startingAt: start "Answer the index of subString within the receiver, starting at start. If the receiver does not contain subString, answer 0." ^ self findSubstring: subString in: self startingAt: start matchTable: CaseSensitiveOrder! ! !String methodsFor: 'accessing' stamp: 'di 11/15/1998 16:45'! findString: key startingAt: start caseSensitive: caseSensitive "Answer the index in this String at which the substring key first occurs, at or beyond start. The match can be case-sensitive or not. If no match is found, zero will be returned." caseSensitive ifTrue: [^ self findSubstring: key in: self startingAt: start matchTable: CaseSensitiveOrder] ifFalse: [^ self findSubstring: key in: self startingAt: start matchTable: CaseInsensitiveOrder]! ! !String methodsFor: 'accessing' stamp: 'tk 8/10/2000 09:14'! findTokens: delimiters "Answer the collection of tokens that result from parsing self. Return strings between the delimiters. Any character in the Collection delimiters marks a border. Several delimiters in a row are considered as just one separation. Also, allow delimiters to be a single character." | tokens keyStart keyStop separators | tokens _ OrderedCollection new. separators _ delimiters class == Character ifTrue: [Array with: delimiters] ifFalse: [delimiters]. keyStop _ 1. [keyStop <= self size] whileTrue: [keyStart _ self skipDelimiters: separators startingAt: keyStop. keyStop _ self findDelimiters: separators startingAt: keyStart. keyStart < keyStop ifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]]. ^tokens! ! !String methodsFor: 'accessing' stamp: 'tk 12/26/97 09:50'! findTokens: delimiters includes: subString "Divide self into pieces using delimiters. Return the piece that includes subString anywhere in it. Is case sensitive (say asLowercase to everything beforehand to make insensitive)." ^ (self findTokens: delimiters) detect: [:str | (str includesSubString: subString)] ifNone: [nil]! ! !String methodsFor: 'accessing' stamp: 'tk 6/19/97 10:05'! findTokens: delimiters keep: keepers "Answer the collection of tokens that result from parsing self. The tokens are seperated by delimiters, any of a string of characters. If a delimiter is also in keepers, make a token for it. (Very useful for carriage return. A sole return ends a line, but is also saved as a token so you can see where the line breaks were.)" | tokens keyStart keyStop | tokens _ OrderedCollection new. keyStop _ 1. [keyStop <= self size] whileTrue: [keyStart _ self skipDelimiters: delimiters startingAt: keyStop. keyStop to: keyStart-1 do: [:ii | (keepers includes: (self at: ii)) ifTrue: [ tokens add: (self copyFrom: ii to: ii)]]. "Make this keeper be a token" keyStop _ self findDelimiters: delimiters startingAt: keyStart. keyStart < keyStop ifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]]. ^tokens! ! !String methodsFor: 'accessing' stamp: 'tk 6/2/2001 12:12'! findWordStart: key startingAt: start | ind | "HyperCard style searching. Answer the index in self of the substring key, when that key is preceeded by a separator character. Must occur at or beyond start. The match is case-insensitive. If no match is found, zero will be returned." ind _ start. [ind _ self findSubstring: key in: self startingAt: ind matchTable: CaseInsensitiveOrder. ind = 0 ifTrue: [^ 0]. "not found" ind = 1 ifTrue: [^ 1]. "First char is the start of a word" (self at: ind-1) isSeparator] whileFalse: [ind _ ind + 1]. ^ ind "is a word start"! ! !String methodsFor: 'accessing' stamp: 'sw 8/12/97 12:37'! includesSubString: subString ^ (self findString: subString startingAt: 1) > 0! ! !String methodsFor: 'accessing' stamp: 'di 11/15/1998 16:53'! includesSubstring: aString caseSensitive: caseSensitive ^ (self findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0! ! !String methodsFor: 'accessing' stamp: 'di 9/1/1999 18:28'! indexOf: aCharacter (aCharacter class == Character) ifFalse: [^ 0]. ^ String indexOfAscii: aCharacter asciiValue inString: self startingAt: 1! ! !String methodsFor: 'accessing' stamp: 'di 9/1/1999 18:28'! indexOf: aCharacter startingAt: start (aCharacter class == Character) ifFalse: [^ 0]. ^ String indexOfAscii: aCharacter asciiValue inString: self startingAt: start! ! !String methodsFor: 'accessing' stamp: 'di 9/1/1999 18:28'! indexOf: aCharacter startingAt: start ifAbsent: aBlock | ans | (aCharacter class == Character) ifFalse: [ ^ aBlock value ]. ans _ String indexOfAscii: aCharacter asciiValue inString: self startingAt: start. ans = 0 ifTrue: [ ^ aBlock value ] ifFalse: [ ^ ans ]! ! !String methodsFor: 'accessing' stamp: 'ls 8/20/1998 05:20'! indexOfAnyOf: aCharacterSet "returns the index of the first character in the given set. Returns 0 if none are found" ^self indexOfAnyOf: aCharacterSet startingAt: 1! ! !String methodsFor: 'accessing' stamp: 'ls 8/20/1998 05:19'! indexOfAnyOf: aCharacterSet ifAbsent: aBlock "returns the index of the first character in the given set. Returns the evaluation of aBlock if none are found" ^self indexOfAnyOf: aCharacterSet startingAt: 1 ifAbsent: aBlock! ! !String methodsFor: 'accessing' stamp: 'ls 8/20/1998 05:19'! indexOfAnyOf: aCharacterSet startingAt: start "returns the index of the first character in the given set, starting from start. Returns 0 if none are found" ^self indexOfAnyOf: aCharacterSet startingAt: start ifAbsent: [ 0 ]! ! !String methodsFor: 'accessing' stamp: 'ls 8/18/1998 00:27'! indexOfAnyOf: aCharacterSet startingAt: start ifAbsent: aBlock "returns the index of the first character in the given set, starting from start" | ans | ans _ String findFirstInString: self inSet: aCharacterSet byteArrayMap startingAt: start. ans = 0 ifTrue: [ ^aBlock value ] ifFalse: [ ^ans ]! ! !String methodsFor: 'accessing' stamp: 'RAH 4/25/2000 19:49'! indexOfSubCollection: sub #Collectn. "Added 2000/04/08 For ANSI <sequenceReadableCollection> protocol." ^ self indexOfSubCollection: sub startingAt: 1 ifAbsent: [0]! ! !String methodsFor: 'accessing' stamp: 'di 11/15/1998 17:02'! indexOfSubCollection: sub startingAt: start ifAbsent: exceptionBlock | index | index _ self findSubstring: sub in: self startingAt: start matchTable: CaseSensitiveOrder. index = 0 ifTrue: [^ exceptionBlock value]. ^ index! ! !String methodsFor: 'accessing' stamp: 'nk 2/21/2001 21:26'! lastIndexOfPKSignature: aSignature "Answer the last index in me where aSignature (4 bytes long) occurs, or 0 if not found" | a b c d | a _ aSignature first. b _ aSignature second. c _ aSignature third. d _ aSignature fourth. (self size - 3) to: 1 by: -1 do: [ :i | (((self at: i) = a) and: [ ((self at: i + 1) = b) and: [ ((self at: i + 2) = c) and: [ ((self at: i + 3) = d) ]]]) ifTrue: [ ^i ] ]. ^0! ! !String methodsFor: 'accessing'! lineCorrespondingToIndex: anIndex "Answer a string containing the line at the given character position. 1/15/96 sw: Inefficient first stab at this" | cr aChar answer | cr _ Character cr. answer _ ''. 1 to: self size do: [:i | aChar _ self at: i. aChar == cr ifTrue: [i > anIndex ifTrue: [^ answer] ifFalse: [answer _ '']] ifFalse: [answer _ answer copyWith: aChar]]. ^ answer! ! !String methodsFor: 'accessing' stamp: 'md 11/14/2003 17:26'! lineCount "Answer the number of lines represented by the receiver, where every cr adds one line. 5/10/96 sw" | cr count | cr _ Character cr. count _ 1 min: self size. 1 to: self size do: [:i | (self at: i) == cr ifTrue: [count _ count + 1]]. ^ count " 'Fred the Bear' lineCount "! ! !String methodsFor: 'accessing'! lineNumber: anIndex "Answer a string containing the characters in the given line number. 5/10/96 sw" | crString pos finalPos | crString _ String with: Character cr. pos _ 0. 1 to: anIndex - 1 do: [:i | pos _ self findString: crString startingAt: pos + 1. pos == 0 ifTrue: [^ nil]]. finalPos _ self findString: crString startingAt: pos + 1. finalPos == 0 ifTrue: [finalPos _ self size + 1]. ^ self copyFrom: pos + 1 to: finalPos - 1 " 'Fred the Bear' lineNumber: 3 "! ! !String methodsFor: 'accessing' stamp: 'ls 9/10/1998 22:27'! linesDo: aBlock "execute aBlock with each line in this string. The terminating CR's are not included in what is passed to aBlock" | start end | start _ 1. [ start <= self size ] whileTrue: [ end _ self indexOf: Character cr startingAt: start ifAbsent: [ self size + 1 ]. end _ end - 1. aBlock value: (self copyFrom: start to: end). start _ end + 2. ].! ! !String methodsFor: 'accessing' stamp: 'BJP 6/12/2000 18:53'! skipAnySubStr: delimiters startingAt: start "Answer the index of the last character within the receiver, starting at start, that does NOT match one of the delimiters. delimiters is a Array of substrings (Characters also allowed). If the receiver is all delimiters, answer size + 1." | any this ind ii | ii _ start-1. [(ii _ ii + 1) <= self size] whileTrue: [ "look for char that does not match" any _ false. delimiters do: [:delim | delim class == Character ifTrue: [(self at: ii) == delim ifTrue: [any _ true]] ifFalse: ["a substring" delim size > (self size - ii + 1) ifFalse: "Here's where the one-off error was." [ind _ 0. this _ true. delim do: [:dd | dd == (self at: ii+ind) ifFalse: [this _ false]. ind _ ind + 1]. this ifTrue: [ii _ ii + delim size - 1. any _ true]] ifTrue: [any _ false] "if the delim is too big, it can't match"]]. any ifFalse: [^ ii]]. ^ self size + 1! ! !String methodsFor: 'accessing'! skipDelimiters: delimiters startingAt: start "Answer the index of the character within the receiver, starting at start, that does NOT match 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." start to: self size do: [:i | delimiters detect: [:delim | delim = (self at: i)] ifNone: [^ i]]. ^ self size + 1! ! !String methodsFor: 'accessing' stamp: 'sw 4/23/1998 10:53'! startsWithDigit "Answer whether the receiver's first character represents a digit" ^ self size > 0 and: [self first isDigit]! ! !String methodsFor: 'accessing' stamp: 'sw 12/6/2001 21:30'! tabDelimitedFieldsDo: aBlock "Considering the receiver as a holder of tab-delimited fields, evaluate execute aBlock with each field in this string. The separatilng tabs are not included in what is passed to aBlock" | start end | "No senders but was useful enough in earlier work that it's retained for the moment." start _ 1. [start <= self size] whileTrue: [end _ self indexOf: Character tab startingAt: start ifAbsent: [self size + 1]. end _ end - 1. aBlock value: (self copyFrom: start to: end). start _ end + 2] " 'fred charlie elmo 2' tabDelimitedFieldsDo: [:aField | Transcript cr; show: aField] "! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:16'! < aString "Answer whether the receiver sorts before aString. The collation order is simple ascii (with case differences)." ^ (self compare: self with: aString collated: AsciiOrder) = 1! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:17'! <= aString "Answer whether the receiver sorts before or equal to aString. The collation order is simple ascii (with case differences)." ^ (self compare: self with: aString collated: AsciiOrder) <= 2! ! !String methodsFor: 'comparing' stamp: 'tk 10/17/2001 14:06'! = aString "Answer whether the receiver sorts equally as aString. The collation order is simple ascii (with case differences)." aString species == String ifFalse: [ aString isText ifTrue: [^ self = aString string]. ^ false]. ^ (self compare: self with: aString collated: AsciiOrder) = 2! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:17'! > aString "Answer whether the receiver sorts after aString. The collation order is simple ascii (with case differences)." ^ (self compare: self with: aString collated: AsciiOrder) = 3! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:18'! >= aString "Answer whether the receiver sorts after or equal to aString. The collation order is simple ascii (with case differences)." ^ (self compare: self with: aString collated: AsciiOrder) >= 2! ! !String methodsFor: 'comparing'! alike: aString "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." | i j k minSize bonus | minSize _ (j _ self size) min: (k _ aString size). bonus _ (j - k) abs < 2 ifTrue: [ 1 ] ifFalse: [ 0 ]. i _ 1. [(i <= minSize) and: [((super at: i) bitAnd: 16rDF) = ((aString at: i) asciiValue bitAnd: 16rDF)]] whileTrue: [ i _ i + 1 ]. [(j > 0) and: [(k > 0) and: [((super at: j) bitAnd: 16rDF) = ((aString at: k) asciiValue bitAnd: 16rDF)]]] whileTrue: [ j _ j - 1. k _ k - 1. ]. ^ i - 1 + self size - j + bonus. ! ! !String methodsFor: 'comparing' stamp: 'di 11/15/1998 17:25'! beginsWith: prefix "Answer whether the receiver begins with the given prefix string. The comparison is case-sensitive." self size < prefix size ifTrue: [^ false]. ^ (self findSubstring: prefix in: self startingAt: 1 matchTable: CaseSensitiveOrder) = 1 ! ! !String methodsFor: 'comparing' stamp: 'sw 4/19/1999 12:11'! caseInsensitiveLessOrEqual: aString "Answer whether the receiver sorts before or equal to aString. The collation order is case insensitive." ^ (self compare: self with: aString collated: CaseInsensitiveOrder) <= 2! ! !String methodsFor: 'comparing' stamp: 'di 9/20/1998 14:33'! caseSensitiveLessOrEqual: aString "Answer whether the receiver sorts before or equal to aString. The collation order is case sensitive." ^ (self compare: self with: aString collated: CaseSensitiveOrder) <= 2! ! !String methodsFor: 'comparing' stamp: 'tk 9/5/2000 10:42'! charactersExactlyMatching: aString "Do a character-by-character comparison between the receiver and aString. Return the index of the final character that matched exactly." | count | count _ self size min: aString size. 1 to: count do: [:i | (self at: i) == (aString at: i) ifFalse: [ ^ i - 1]]. ^ count! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:41'! compare: aString "Answer a comparison code telling how the receiver sorts relative to aString: 1 - before 2 - equal 3 - after. The collation sequence is ascii with case differences ignored. To get the effect of a <= b, but ignoring case, use (a compare: b) <= 2." ^ self compare: self with: aString collated: CaseInsensitiveOrder! ! !String methodsFor: 'comparing' stamp: 'go 2/11/98 14:59'! crc16 "Compute a 16 bit cyclic redundancy check." | crc | crc := 0. self do: [:c | crc := (crc bitShift: -8) bitXor: ( #( 16r0000 16rC0C1 16rC181 16r0140 16rC301 16r03C0 16r0280 16rC241 16rC601 16r06C0 16r0780 16rC741 16r0500 16rC5C1 16rC481 16r0440 16rCC01 16r0CC0 16r0D80 16rCD41 16r0F00 16rCFC1 16rCE81 16r0E40 16r0A00 16rCAC1 16rCB81 16r0B40 16rC901 16r09C0 16r0880 16rC841 16rD801 16r18C0 16r1980 16rD941 16r1B00 16rDBC1 16rDA81 16r1A40 16r1E00 16rDEC1 16rDF81 16r1F40 16rDD01 16r1DC0 16r1C80 16rDC41 16r1400 16rD4C1 16rD581 16r1540 16rD701 16r17C0 16r1680 16rD641 16rD201 16r12C0 16r1380 16rD341 16r1100 16rD1C1 16rD081 16r1040 16rF001 16r30C0 16r3180 16rF141 16r3300 16rF3C1 16rF281 16r3240 16r3600 16rF6C1 16rF781 16r3740 16rF501 16r35C0 16r3480 16rF441 16r3C00 16rFCC1 16rFD81 16r3D40 16rFF01 16r3FC0 16r3E80 16rFE41 16rFA01 16r3AC0 16r3B80 16rFB41 16r3900 16rF9C1 16rF881 16r3840 16r2800 16rE8C1 16rE981 16r2940 16rEB01 16r2BC0 16r2A80 16rEA41 16rEE01 16r2EC0 16r2F80 16rEF41 16r2D00 16rEDC1 16rEC81 16r2C40 16rE401 16r24C0 16r2580 16rE541 16r2700 16rE7C1 16rE681 16r2640 16r2200 16rE2C1 16rE381 16r2340 16rE101 16r21C0 16r2080 16rE041 16rA001 16r60C0 16r6180 16rA141 16r6300 16rA3C1 16rA281 16r6240 16r6600 16rA6C1 16rA781 16r6740 16rA501 16r65C0 16r6480 16rA441 16r6C00 16rACC1 16rAD81 16r6D40 16rAF01 16r6FC0 16r6E80 16rAE41 16rAA01 16r6AC0 16r6B80 16rAB41 16r6900 16rA9C1 16rA881 16r6840 16r7800 16rB8C1 16rB981 16r7940 16rBB01 16r7BC0 16r7A80 16rBA41 16rBE01 16r7EC0 16r7F80 16rBF41 16r7D00 16rBDC1 16rBC81 16r7C40 16rB401 16r74C0 16r7580 16rB541 16r7700 16rB7C1 16rB681 16r7640 16r7200 16rB2C1 16rB381 16r7340 16rB101 16r71C0 16r7080 16rB041 16r5000 16r90C1 16r9181 16r5140 16r9301 16r53C0 16r5280 16r9241 16r9601 16r56C0 16r5780 16r9741 16r5500 16r95C1 16r9481 16r5440 16r9C01 16r5CC0 16r5D80 16r9D41 16r5F00 16r9FC1 16r9E81 16r5E40 16r5A00 16r9AC1 16r9B81 16r5B40 16r9901 16r59C0 16r5880 16r9841 16r8801 16r48C0 16r4980 16r8941 16r4B00 16r8BC1 16r8A81 16r4A40 16r4E00 16r8EC1 16r8F81 16r4F40 16r8D01 16r4DC0 16r4C80 16r8C41 16r4400 16r84C1 16r8581 16r4540 16r8701 16r47C0 16r4680 16r8641 16r8201 16r42C0 16r4380 16r8341 16r4100 16r81C1 16r8081 16r4040) at: ((crc bitXor: c asciiValue) bitAnd: 16rFF) + 1) ]. ^crc! ! !String methodsFor: 'comparing' stamp: 'di 11/15/1998 17:25'! endsWith: suffix "Answer whether the tail end of the receiver is the same as suffix. The comparison is case-sensitive." | extra | (extra _ self size - suffix size) < 0 ifTrue: [^ false]. ^ (self findSubstring: suffix in: self startingAt: extra + 1 matchTable: CaseSensitiveOrder) > 0 " 'Elvis' endsWith: 'vis' "! ! !String methodsFor: 'comparing' stamp: 'ar 11/19/1998 21:48'! endsWithAnyOf: aCollection aCollection do:[:suffix| (self endsWith: suffix) ifTrue:[^true]. ]. ^false! ! !String methodsFor: 'comparing' stamp: 'SqR 8/13/2002 10:52'! hash "#hash is implemented, because #= is implemented" ^ByteArray hashBytes: self startingWith: self species hash! ! !String methodsFor: 'comparing'! hashMappedBy: map "My hash is independent of my oop." ^self hash! ! !String methodsFor: 'comparing' stamp: 'tk 3/8/2001 16:49'! howManyMatch: string "Count the number of characters that match up in self and aString." | count shorterLength | count _ 0 . shorterLength _ ((self size ) min: (string size ) ) . (1 to: shorterLength do: [:index | (((self at: index ) = (string at: index ) ) ifTrue: [count _ (count + 1 ) . ] ). ] ). ^ count ! ! !String methodsFor: 'comparing' stamp: 'di 11/19/1998 13:37'! match: text "Answer whether text matches the pattern in this string. Matching ignores upper/lower case differences. Where this string contains #, text may contain any character. Where this string contains *, text may contain any sequence of characters." ^ self startingAt: 1 match: text startingAt: 1 " '*' match: 'zort' true '*baz' match: 'mobaz' true '*baz' match: 'mobazo' false '*baz*' match: 'mobazo' true '*baz*' match: 'mozo' false 'foo*' match: 'foozo' true 'foo*' match: 'bozo' false 'foo*baz' match: 'foo23baz' true 'foo*baz' match: 'foobaz' true 'foo*baz' match: 'foo23bazo' false 'foo' match: 'Foo' true 'foo*baz*zort' match: 'foobazort' false 'foo*baz*zort' match: 'foobazzort' false '*foo#zort' match: 'afoo3zortthenfoo3zort' true '*foo*zort' match: 'afoodezortorfoo3zort' true "! ! !String methodsFor: 'comparing' stamp: 'di 2/27/98 12:19'! sameAs: aString "Answer whether the receiver sorts equal to aString. The collation sequence is ascii with case differences ignored." ^ (self compare: self with: aString collated: CaseInsensitiveOrder) = 2! ! !String methodsFor: 'comparing' stamp: 'di 11/19/1998 13:28'! startingAt: keyStart match: text startingAt: textStart "Answer whether text matches the pattern in this string. Matching ignores upper/lower case differences. Where this string contains #, text may contain any character. Where this string contains *, text may contain any sequence of characters." | anyMatch matchStart matchEnd i matchStr j ii jj | i _ keyStart. j _ textStart. "Check for any #'s" [i > self size ifTrue: [^ j > text size "Empty key matches only empty string"]. (self at: i) = $#] whileTrue: ["# consumes one char of key and one char of text" j > text size ifTrue: [^ false "no more text"]. i _ i+1. j _ j+1]. "Then check for *" (self at: i) = $* ifTrue: [i = self size ifTrue: [^ true "Terminal * matches all"]. "* means next match string can occur anywhere" anyMatch _ true. matchStart _ i + 1] ifFalse: ["Otherwise match string must occur immediately" anyMatch _ false. matchStart _ i]. "Now determine the match string" matchEnd _ self size. (ii _ self indexOf: $* startingAt: matchStart) > 0 ifTrue: [ii = 1 ifTrue: [self error: '** not valid -- use * instead']. matchEnd _ ii-1]. (ii _ self indexOf: $# startingAt: matchStart) > 0 ifTrue: [ii = 1 ifTrue: [self error: '*# not valid -- use #* instead']. matchEnd _ matchEnd min: ii-1]. matchStr _ self copyFrom: matchStart to: matchEnd. "Now look for the match string" [jj _ text findString: matchStr startingAt: j caseSensitive: false. anyMatch ifTrue: [jj > 0] ifFalse: [jj = j]] whileTrue: ["Found matchStr at jj. See if the rest matches..." (self startingAt: matchEnd+1 match: text startingAt: jj + matchStr size) ifTrue: [^ true "the rest matches -- success"]. "The rest did not match." anyMatch ifFalse: [^ false]. "Preceded by * -- try for a later match" j _ j+1]. ^ false "Failed to find the match string"! ! !String methodsFor: 'copying'! copyReplaceTokens: oldSubstring with: newSubstring "Replace all occurrences of oldSubstring that are surrounded by non-alphanumeric characters" ^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: true "'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Snick'"! ! !String methodsFor: 'copying'! deepCopy "DeepCopy would otherwise mean make a copy of the character; since characters are unique, just return a shallowCopy." ^self shallowCopy! ! !String methodsFor: 'copying' stamp: 'di 2/15/98 22:54'! padded: leftOrRight to: length with: char leftOrRight = #left ifTrue: [^ (String new: (length - self size max: 0) withAll: char) , self]. leftOrRight = #right ifTrue: [^ self , (String new: (length - self size max: 0) withAll: char)].! ! !String methodsFor: 'converting' stamp: 'di 11/6/1998 13:47'! adaptToCollection: rcvr andSend: selector "If I am involved in arithmetic with a collection, convert me to a number." ^ rcvr perform: selector with: self asNumber! ! !String methodsFor: 'converting' stamp: 'di 11/9/1998 12:17'! adaptToNumber: rcvr andSend: selector "If I am involved in arithmetic with a number, convert me to a number." ^ rcvr perform: selector with: self asNumber! ! !String methodsFor: 'converting' stamp: 'di 11/6/1998 13:49'! adaptToPoint: rcvr andSend: selector "If I am involved in arithmetic with a point, convert me to a number." ^ rcvr perform: selector with: self asNumber! ! !String methodsFor: 'converting' stamp: 'di 11/6/1998 13:49'! adaptToString: rcvr andSend: selector "If I am involved in arithmetic with a string, convert us both to numbers, and return the printString of the result." ^ (rcvr asNumber perform: selector with: self asNumber) printString! ! !String methodsFor: 'converting' stamp: 'sw 9/1/2000 10:39'! asCharacter "Answer the receiver's first character, or '' if none. Idiosyncratic, provisional." ^ self size > 0 ifTrue: [self first] ifFalse: [$]! ! !String methodsFor: 'converting' stamp: 'brp 8/23/2003 23:58'! asDate "Many allowed forms, see Date>>#readFrom:" ^ Date fromString: self! ! !String methodsFor: 'converting' stamp: 'brp 7/27/2003 17:28'! asDateAndTime "Convert from UTC format" ^ DateAndTime fromString: self! ! !String methodsFor: 'converting'! asDisplayText "Answer a DisplayText whose text string is the receiver." ^DisplayText text: self asText! ! !String methodsFor: 'converting' stamp: 'brp 5/16/2003 11:59'! asDuration "convert from [nnnd]hh:mm:ss[.nanos] format. [] implies optional elements" ^ Duration fromString: self ! ! !String methodsFor: 'converting'! asFileName "Answer a String made up from the receiver that is an acceptable file name." ^FileDirectory checkName: self fixErrors: true! ! !String methodsFor: 'converting' stamp: 'acg 9/11/1999 15:43'! asFourCode |result| self size = 4 ifFalse: [^self error: 'must be exactly four characters']. result _ self inject: 0 into: [:val :each | 256 * val + each asciiValue]. (result bitAnd: 16r80000000) = 0 ifFalse: [self error: 'cannot resolve fourcode']. (result bitAnd: 16r40000000) = 0 ifFalse: [^result - 16r80000000]. ^result! ! !String methodsFor: 'converting' stamp: 'nk 2/21/2001 20:06'! asHex | stream | stream _ WriteStream on: (String new: self size * 2). self do: [ :ch | stream nextPutAll: ch hex ]. ^stream contents! ! !String methodsFor: 'converting' stamp: 'sma 3/11/2000 17:25'! asHtml "Do the basic character conversion for HTML. Leave all original return and tabs in place, so can conver back by simply removing bracked things. 4/4/96 tk" | temp | temp _ self copyReplaceAll: '&' with: '&'. HtmlEntities keysAndValuesDo: [:entity :char | char = $& ifFalse: [temp _ temp copyReplaceAll: char asString with: '&' , entity , ';']]. temp _ temp copyReplaceAll: ' ' with: ' <IMG SRC="tab.gif" ALT=" ">'. temp _ temp copyReplaceAll: ' ' with: ' <BR>'. ^ temp " 'A<&>B' asHtml "! ! !String methodsFor: 'converting' stamp: 'ls 9/5/1998 01:19'! asIRCLowercase "Answer a String made up from the receiver whose characters are all lowercase, where 'lowercase' is by IRC's definition" ^self collect: [ :c | c asIRCLowercase ]! ! !String methodsFor: 'converting' stamp: 'sw 9/5/2000 09:03'! asIdentifier: shouldBeCapitalized "Return a legal identifier, with first character in upper case if shouldBeCapitalized is true, else lower case. This will always return a legal identifier, even for an empty string" | aString firstChar firstLetterPosition | aString _ self select: [:el | el isAlphaNumeric]. firstLetterPosition _ aString findFirst: [:ch | ch isLetter]. aString _ firstLetterPosition == 0 ifFalse: [aString copyFrom: firstLetterPosition to: aString size] ifTrue: ['a', aString]. firstChar _ shouldBeCapitalized ifTrue: [aString first asUppercase] ifFalse: [aString first asLowercase]. ^ firstChar asString, (aString copyFrom: 2 to: aString size) " '234Fred987' asIdentifier: false '235Fred987' asIdentifier: true '' asIdentifier: true '()87234' asIdentifier: false '())z>=PPve889 U >' asIdentifier: false "! ! !String methodsFor: 'converting' stamp: 'sw 9/1/2000 10:40'! asInteger "Answer the Integer created by interpreting the receiver as the string representation of an integer. Answer nil if no digits, else find the first digit and then all consecutive digits after that" | startPosition tail endPosition | startPosition _ self findFirst: [:ch | ch isDigit]. startPosition == 0 ifTrue: [^ nil]. tail _ self copyFrom: startPosition to: self size. endPosition _ tail findFirst: [:ch | ch isDigit not]. endPosition == 0 ifTrue: [endPosition _ tail size + 1]. ^ Number readFromString: (tail copyFrom: 1 to: endPosition - 1) " '1796exportFixes-tkMX' asInteger '1848recentLogFile-sw' asInteger 'donald' asInteger 'abc234def567' asInteger "! ! !String methodsFor: 'converting' stamp: 'sw 5/3/1998 23:19'! asLegalSelector | toUse | toUse _ ''. self do: [:char | char isAlphaNumeric ifTrue: [toUse _ toUse copyWith: char]]. (self size == 0 or: [self first isLetter not]) ifTrue: [toUse _ 'v', toUse]. ^ toUse withFirstCharacterDownshifted "'234znak 43 ) 2' asLegalSelector"! ! !String methodsFor: 'converting' stamp: 'sma 6/12/2000 11:40'! asLowercase "Answer a String made up from the receiver whose characters are all lowercase." ^ self copy asString translateToLowercase! ! !String methodsFor: 'converting'! asNumber "Answer the Number created by interpreting the receiver as the string representation of a number." ^Number readFromString: self! ! !String methodsFor: 'converting'! asPacked "Convert to a longinteger that describes the string" ^ self inject: 0 into: [ :pack :next | pack _ pack * 256 + next asInteger ].! ! !String methodsFor: 'converting'! asParagraph "Answer a Paragraph whose text string is the receiver." ^Paragraph withText: self asText! ! !String methodsFor: 'converting' stamp: 'sw 8/3/2002 04:32'! asSignedInteger "Answer the Integer created by interpreting the receiver as the string representation of an integer, possibly with a leading minus sign. Answer nil if no digits, else find the first digit and then all consecutive digits after that" | startPosition tail endPosition | startPosition _ self findFirst: [:ch | ch isDigit or: [ch == $-]]. startPosition == 0 ifTrue: [^ nil]. tail _ self copyFrom: startPosition to: self size. endPosition _ tail findFirst: [:ch | ch isDigit not and: [ch ~~ $-]]. endPosition == 0 ifTrue: [endPosition _ tail size + 1]. ^ Number readFromString: (tail copyFrom: 1 to: endPosition - 1) " 'znak -58 to wit' asSignedInteger "! ! !String methodsFor: 'converting' stamp: 'ls 10/28/2003 12:24'! asSmalltalkComment "return this string, munged so that it can be treated as a comment in Smalltalk code. Quote marks are added to the beginning and end of the string, and whenever a solitary quote mark appears within the string, it is doubled" ^String streamContents: [ :str | | quoteCount first | str nextPut: $". quoteCount := 0. first := true. self do: [ :char | char = $" ifTrue: [ first ifFalse: [ str nextPut: char. quoteCount := quoteCount + 1 ] ] ifFalse: [ quoteCount odd ifTrue: [ "add a quote to even the number of quotes in a row" str nextPut: $" ]. quoteCount := 0. str nextPut: char ]. first := false ]. quoteCount odd ifTrue: [ "check at the end" str nextPut: $". ]. str nextPut: $". ]. ! ! !String methodsFor: 'converting' stamp: 'jm 5/14/1998 10:40'! asString "Answer this string." ^ self ! ! !String methodsFor: 'converting' stamp: 'RAA 5/28/2001 06:19'! asStringOrText "Answer this string." ^ self ! ! !String methodsFor: 'converting'! asSymbol "Answer the unique Symbol whose characters are the characters of the string." ^Symbol intern: self! ! !String methodsFor: 'converting'! asText "Answer a Text whose string is the receiver." ^Text fromString: self! ! !String methodsFor: 'converting' stamp: 'brp 8/24/2003 00:01'! asTime "Many allowed forms, see Time>>readFrom:" ^ Time fromString: self.! ! !String methodsFor: 'converting' stamp: 'brp 8/24/2003 00:02'! asTimeStamp "Convert from obsolete TimeStamp format" ^ TimeStamp fromString: self! ! !String methodsFor: 'converting' stamp: 'tk 4/13/2002 09:13'! asUnHtml "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." | in out char rest did | in _ ReadStream on: self. out _ WriteStream on: (String new: self size). [in atEnd] whileFalse: [in peek = $< ifTrue: [in unCommand] "Absorb <...><...>" ifFalse: [(char _ in next) = $& ifTrue: [rest _ in upTo: $;. did _ out position. rest = 'lt' ifTrue: [out nextPut: $<]. rest = 'gt' ifTrue: [out nextPut: $>]. rest = 'amp' ifTrue: [out nextPut: $&]. rest = 'deg' ifTrue: [out nextPut: $]. rest = 'quot' ifTrue: [out nextPut: $"]. did = out position ifTrue: [ self error: 'unknown encoded HTML char'. "Please add it to this method"]] ifFalse: [out nextPut: char]]. ]. ^ out contents! ! !String methodsFor: 'converting' stamp: 'SqR 6/13/2000 20:10'! asUppercase "Answer a String made up from the receiver whose characters are all uppercase." ^self copy asString translateToUppercase! ! !String methodsFor: 'converting' stamp: 'ls 7/15/1998 18:40'! asUrlRelativeTo: aUrl ^aUrl newFromRelativeText: self! ! !String methodsFor: 'converting' stamp: 'di 2/2/98 12:59'! askIfAddStyle: priorMethod req: requestor ^ self "we are a string with no text style"! ! !String methodsFor: 'converting' stamp: 'ls 9/10/1998 08:48'! capitalized "Return a copy with the first letter capitalized" | cap | self isEmpty ifTrue: [ ^self copy ]. cap _ self copy. cap at: 1 put: (cap at: 1) asUppercase. ^ cap! ! !String methodsFor: 'converting'! compressWithTable: tokens "Return a string with all substrings that occur in tokens replaced by a character with ascii code = 127 + token index. This will work best if tokens are sorted by size. Assumes this string contains no characters > 127, or that they are intentionally there and will not interfere with this process." | str null finalSize start result ri c ts | null _ Character value: 0. str _ self copyFrom: 1 to: self size. "Working string will get altered" finalSize _ str size. tokens doWithIndex: [:token :tIndex | start _ 1. [(start _ str findString: token startingAt: start) > 0] whileTrue: [ts _ token size. ((start + ts) <= str size and: [(str at: start + ts) = $ and: [tIndex*2 <= 128]]) ifTrue: [ts _ token size + 1. "include training blank" str at: start put: (Character value: tIndex*2 + 127)] ifFalse: [str at: start put: (Character value: tIndex + 127)]. str at: start put: (Character value: tIndex + 127). 1 to: ts-1 do: [:i | str at: start+i put: null]. finalSize _ finalSize - (ts - 1). start _ start + ts]]. result _ String new: finalSize. ri _ 0. 1 to: str size do: [:i | (c _ str at: i) = null ifFalse: [result at: (ri _ ri+1) put: c]]. ^ result! ! !String methodsFor: 'converting' stamp: 'di 1/16/98 16:33'! contractTo: smallSize "return myself or a copy shortened by ellipsis to smallSize" | leftSize | self size <= smallSize ifTrue: [^ self]. "short enough" smallSize < 5 ifTrue: [^ self copyFrom: 1 to: smallSize]. "First N characters" leftSize _ smallSize-2//2. ^ self copyReplaceFrom: leftSize+1 "First N/2 ... last N/2" to: self size - (smallSize - leftSize - 3) with: '...' " 'A clear but rather long-winded summary' contractTo: 18 "! ! !String methodsFor: 'converting'! correctAgainst: wordList "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:" | results | results _ self correctAgainst: wordList continuedFrom: nil. results _ self correctAgainst: nil continuedFrom: results. ^ results! ! !String methodsFor: 'converting' stamp: 'ar 5/1/1999 05:01'! correctAgainst: wordList continuedFrom: oldCollection "Like correctAgainst:. Use when you want to correct against several lists, give nil as the first oldCollection, and nil as the last wordList." ^ wordList isNil ifTrue: [ self correctAgainstEnumerator: nil continuedFrom: oldCollection ] ifFalse: [ self correctAgainstEnumerator: [ :action | wordList do: action without: nil] continuedFrom: oldCollection ]! ! !String methodsFor: 'converting'! correctAgainstDictionary: wordDict continuedFrom: oldCollection "Like correctAgainst:continuedFrom:. Use when you want to correct against a dictionary." ^ wordDict isNil ifTrue: [ self correctAgainstEnumerator: nil continuedFrom: oldCollection ] ifFalse: [ self correctAgainstEnumerator: [ :action | wordDict keysDo: action ] continuedFrom: oldCollection ]! ! !String methodsFor: 'converting' stamp: 'ls 8/12/1998 23:31'! encodeForHTTP "change dangerous characters to their %XX form, for use in HTTP transactions" | encodedStream | encodedStream _ WriteStream on: (String new). self do: [ :c | c isSafeForHTTP ifTrue: [ encodedStream nextPut: c ] ifFalse: [ encodedStream nextPut: $%. encodedStream nextPut: (c asciiValue // 16) asHexDigit. encodedStream nextPut: (c asciiValue \\ 16) asHexDigit. ] ]. ^encodedStream contents. ! ! !String methodsFor: 'converting' stamp: 'tk 12/12/2001 15:11'! findSelector "Dan's code for hunting down selectors with keyword parts; while this doesn't give a true parse, in most cases it does what we want, in where it doesn't, we're none the worse for it." | sel possibleParens level n | sel _ self withBlanksTrimmed. (sel includes: $:) ifTrue: [sel _ sel copyReplaceAll: ':' with: ': '. "for the style (aa max:bb) with no space" possibleParens _ sel findTokens: Character separators. sel _ String streamContents: [:s | level _ 0. possibleParens do: [:token | (level = 0 and: [token endsWith: ':']) ifTrue: [s nextPutAll: token] ifFalse: [(n _ token occurrencesOf: $( ) > 0 ifTrue: [level _ level + n]. (n _ token occurrencesOf: $[ ) > 0 ifTrue: [level _ level + n]. (n _ token occurrencesOf: $] ) > 0 ifTrue: [level _ level - n]. (n _ token occurrencesOf: $) ) > 0 ifTrue: [level _ level - n]]]]]. sel isEmpty ifTrue: [^ nil]. Symbol hasInterned: sel ifTrue: [:aSymbol | ^ aSymbol]. ^ nil! ! !String methodsFor: 'converting' stamp: 'sw 8/20/1999 10:23'! initialIntegerOrNil "Answer the integer represented by the leading digits of the receiver, or nil if the receiver does not begin with a digit" | firstNonDigit | (self size == 0 or: [self first isDigit not]) ifTrue: [^ nil]. firstNonDigit _ (self findFirst: [:m | m isDigit not]). firstNonDigit = 0 ifTrue: [firstNonDigit _ self size + 1]. ^ (self copyFrom: 1 to: (firstNonDigit - 1)) asNumber " '234Whoopie' initialIntegerOrNil 'wimpy' initialIntegerOrNil '234' initialIntegerOrNil '2N' initialIntegerOrNil '2' initialIntegerOrNil ' 89Ten ' initialIntegerOrNil '78 92' initialIntegerOrNil " ! ! !String methodsFor: 'converting' stamp: 'di 4/22/2000 16:05'! keywords "Answer an array of the keywords that compose the receiver." | kwd char keywords | keywords _ Array streamContents: [:kwds | kwd _ WriteStream on: (String new: 16). 1 to: self size do: [:i | kwd nextPut: (char _ self at: i). char = $: ifTrue: [kwds nextPut: kwd contents. kwd reset]]. kwd isEmpty ifFalse: [kwds nextPut: kwd contents]]. (keywords size >= 1 and: [(keywords at: 1) = ':']) ifTrue: ["Has an initial keyword, as in #:if:then:else:" keywords _ keywords allButFirst]. (keywords size >= 2 and: [(keywords at: keywords size - 1) = ':']) ifTrue: ["Has a final keyword, as in #nextPut::andCR" keywords _ keywords copyReplaceFrom: keywords size - 1 to: keywords size with: {':' , keywords last}]. ^ keywords! ! !String methodsFor: 'converting' stamp: 'sw 5/30/2000 14:58'! numericSuffix ^ self stemAndNumericSuffix last " 'abc98' numericSuffix '98abc' numericSuffix "! ! !String methodsFor: 'converting' stamp: 'dgd 9/6/2003 18:48'! onlyLetters "answer the receiver with only letters" ^ self select:[:each | each isLetter]! ! !String methodsFor: 'converting' stamp: 'sma 5/20/2000 17:17'! romanNumber | value v1 v2 | value _ v1 _ v2 _ 0. self reverseDo: [:each | v1 _ #(1 5 10 50 100 500 1000) at: ('IVXLCDM' indexOf: each). v1 >= v2 ifTrue: [value _ value + v1] ifFalse: [value _ value - v1]. v2 _ v1]. ^ value! ! !String methodsFor: 'converting'! sansPeriodSuffix "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. " | likely | likely _ self copyUpTo: $.. ^ likely size == 0 ifTrue: [self] ifFalse: [likely]! ! !String methodsFor: 'converting' stamp: 'di 9/24/1999 12:31'! splitInteger "Answer an array that is a splitting of self into a string and an integer. '43Sam' ==> #(43 'Sam'). 'Try90' ==> #('Try' 90) BUT NOTE: 'Sam' ==> #('Sam' 0), and '90' ==> #('' 90) ie, (<string> <integer>)." | pos | (pos _ self findFirst: [:d | d isDigit not]) == 0 ifTrue: [^ Array with: '' with: self asNumber]. self first isDigit ifTrue: [ ^ Array with: (self copyFrom: 1 to: pos - 1) asNumber with: (self copyFrom: pos to: self size)]. (pos _ self findFirst: [:d | d isDigit]) == 0 ifTrue: [^ Array with: self with: 0]. ^ Array with: (self copyFrom: 1 to: pos - 1) with: (self copyFrom: pos to: self size) asNumber! ! !String methodsFor: 'converting'! stemAndNumericSuffix "Parse the receiver into a string-valued stem and a numeric-valued suffix. 6/7/96 sw" | stem suffix position | stem _ self. suffix _ 0. position _ 1. [stem endsWithDigit and: [stem size > 1]] whileTrue: [suffix _ stem last digitValue * position + suffix. position _ position * 10. stem _ stem copyFrom: 1 to: stem size - 1]. ^ Array with: stem with: suffix "'Fred2305' stemAndNumericSuffix"! ! !String methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! subStrings "Answer an array of the substrings that compose the receiver." #Collectn. "Added 2000/04/08 For ANSI <readableString> protocol." ^ self substrings! ! !String methodsFor: 'converting' stamp: 'RAH 4/25/2000 19:49'! subStrings: separators "Answer an array containing the substrings in the receiver separated by the elements of separators." | char result sourceStream subString | #Collectn. "Changed 2000/04/08 For ANSI <readableString> protocol." (separators allSatisfy: [:element | element isKindOf: Character]) ifFalse: [^ self error: 'separators must be Characters.']. sourceStream := ReadStream on: self. result := OrderedCollection new. subString := String new. [sourceStream atEnd] whileFalse: [char := sourceStream next. (separators includes: char) ifTrue: [subString notEmpty ifTrue: [result add: subString copy. subString := String new]] ifFalse: [subString := subString , (String with: char)]]. subString notEmpty ifTrue: [result add: subString copy]. ^ result asArray! ! !String methodsFor: 'converting' stamp: 'ls 1/3/1999 13:36'! substrings "Answer an array of the substrings that compose the receiver." | result end beginning | result _ WriteStream on: (Array new: 10). end _ 0. "find one substring each time through this loop" [ "find the beginning of the next substring" beginning _ self indexOfAnyOf: CSNonSeparators startingAt: end+1 ifAbsent: [ nil ]. beginning ~~ nil ] whileTrue: [ "find the end" end _ self indexOfAnyOf: CSSeparators startingAt: beginning ifAbsent: [ self size + 1 ]. end _ end - 1. result nextPut: (self copyFrom: beginning to: end). ]. ^result contents! ! !String methodsFor: 'converting' stamp: 'sw 11/25/96'! surroundedBySingleQuotes "Answer the receiver with leading and trailing quotes. " ^ $' asString, self, $' asString! ! !String methodsFor: 'converting' stamp: 'ls 8/15/1998 10:31'! translateFrom: start to: stop table: table "translate the characters in the string by the given table, in place" String translate: self from: start to: stop table: table! ! !String methodsFor: 'converting' stamp: 'ls 8/18/1998 07:44'! translateToLowercase "Translate all characters to lowercase, in place" self translateWith: LowercasingTable! ! !String methodsFor: 'converting' stamp: 'SqR 6/13/2000 20:10'! translateToUppercase "Translate all characters to lowercase, in place" self translateWith: UppercasingTable! ! !String methodsFor: 'converting' stamp: 'ls 8/15/1998 08:30'! translateWith: table "translate the characters in the string by the given table, in place" ^self translateFrom: 1 to: self size table: table! ! !String methodsFor: 'converting'! truncateTo: smallSize "return myself or a copy shortened to smallSize. 1/18/96 sw" ^ self size <= smallSize ifTrue: [self] ifFalse: [self copyFrom: 1 to: smallSize]! ! !String methodsFor: 'converting' stamp: 'sw 9/2/1998 17:09'! truncateWithElipsisTo: maxLength "Return myself or a copy suitably shortened but with elipsis added" ^ self size <= maxLength ifTrue: [self] ifFalse: [(self copyFrom: 1 to: (maxLength - 3)), '...'] "'truncateWithElipsisTo:' truncateWithElipsisTo: 20"! ! !String methodsFor: 'converting' stamp: 'sw 10/26/2000 10:00'! unparenthetically "If the receiver starts with (..( and ends with matching )..), strip them" | curr | curr _ self. [((curr first == $() and: [curr last == $)])] whileTrue: [curr _ curr copyFrom: 2 to: (curr size - 1)]. ^ curr " '((fred the bear))' unparenthetically " ! ! !String methodsFor: 'converting' stamp: 'bolot 11/3/1999 17:35'! withBlanksCondensed "Return a copy of the receiver with leading/trailing blanks removed and consecutive white spaces condensed." | trimmed lastBlank | trimmed _ self withBlanksTrimmed. ^String streamContents: [:stream | lastBlank _ false. trimmed do: [:c | (c isSeparator and: [lastBlank]) ifFalse: [stream nextPut: c]. lastBlank _ c isSeparator]]. " ' abc d ' withBlanksCondensed" ! ! !String methodsFor: 'converting' stamp: 'jm 5/14/1998 10:26'! withBlanksTrimmed "Return a copy of the receiver from which leading and trailing blanks have been trimmed." | first | first _ self findFirst: [:c | c isSeparator not]. first = 0 ifTrue: [^ '']. "no non-separator character" ^ self copyFrom: first to: (self findLast: [:c | c isSeparator not]) " ' abc d ' withBlanksTrimmed" ! ! !String methodsFor: 'converting' stamp: 'sw 6/6/2002 18:24'! withFirstCharacterDownshifted "Answer an object like the receiver but with first character downshifted if necesary" "'MElViN' withFirstCharacterDownshifted" "#Will withFirstCharacterDownshifted" | answer | self isEmpty ifTrue: [^ self]. answer _ self isString ifTrue: ["don't change receiver" self copy] ifFalse: [self asString]. answer at: 1 put: (answer at: 1) asLowercase. ^ self isString ifTrue: [answer] ifFalse: [answer as: self class]! ! !String methodsFor: 'converting' stamp: 'tk 3/28/1999 22:44'! withNoLineLongerThan: aNumber "Answer a string with the same content as receiver, but rewrapped so that no line has more characters than the given number" | listOfLines currentLast currentStart resultString putativeLast putativeLine crPosition | aNumber isNumber not | (aNumber < 1) ifTrue: [self error: 'too narrow']. listOfLines _ OrderedCollection new. currentLast _ 0. [currentLast < self size] whileTrue: [currentStart _ currentLast + 1. putativeLast _ (currentStart + aNumber - 1) min: self size. putativeLine _ self copyFrom: currentStart to: putativeLast. (crPosition _ putativeLine indexOf: Character cr) > 0 ifTrue: [putativeLast _ currentStart + crPosition - 1. putativeLine _ self copyFrom: currentStart to: putativeLast]. currentLast _ putativeLast == self size ifTrue: [putativeLast] ifFalse: [currentStart + putativeLine lastSpacePosition - 1]. currentLast <= currentStart ifTrue: ["line has NO spaces; baleout!!" currentLast _ putativeLast]. listOfLines add: (self copyFrom: currentStart to: currentLast) withBlanksTrimmed]. listOfLines size > 0 ifFalse: [^ '']. resultString _ listOfLines first. 2 to: listOfLines size do: [:i | resultString _ resultString, String cr, (listOfLines at: i)]. ^ resultString "#(5 7 20) collect: [:i | 'Fred the bear went down to the brook to read his book in silence' withNoLineLongerThan: i]"! ! !String methodsFor: 'converting' stamp: 'ls 8/20/1998 10:43'! withSeparatorsCompacted "replace each sequences of whitespace by a single space character" | out pos textEnd | self isEmpty ifTrue: [ ^self ]. out _ WriteStream on: (String new: self size). pos _ 1. "current position in a scan through aString" "handle the case of initial separators" self first isSeparator ifTrue: [ out nextPut: Character space. pos _ self indexOfAnyOf: CSNonSeparators ifAbsent: [ self size + 1 ] ]. "central loop: handle a segment of text, followed possibly by a segment of whitespace" [ pos <= self size ] whileTrue: [ "handle a segment of text..." textEnd _ self indexOfAnyOf: CSSeparators startingAt: pos ifAbsent: [ self size + 1 ]. textEnd _ textEnd - 1. out nextPutAll: (self copyFrom: pos to: textEnd). pos _ textEnd + 1. pos <= self size ifTrue: [ pos _ self indexOfAnyOf: CSNonSeparators startingAt: pos ifAbsent: [ self size + 1 ]. out nextPut: Character space ] ]. ^out contents! ! !String methodsFor: 'converting' stamp: 'sw 1/8/1999 14:45'! withoutLeadingDigits "Answer the portion of the receiver that follows any leading series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string" | firstNonDigit | firstNonDigit _ (self findFirst: [:m | m isDigit not and: [m ~~ $ ]]). ^ firstNonDigit > 0 ifTrue: [self copyFrom: firstNonDigit to: self size] ifFalse: [''] " '234Whoopie' withoutLeadingDigits ' 4321 BlastOff!!' withoutLeadingDigits 'wimpy' withoutLeadingDigits ' 89Ten ' withoutLeadingDigits '78 92' withoutLeadingDigits " ! ! !String methodsFor: 'converting' stamp: 'bf 11/24/1998 19:58'! withoutTrailingBlanks "Return a copy of the receiver from which trailing blanks have been trimmed." | last | last _ self findLast: [:c | c isSeparator not]. last = 0 ifTrue: [^ '']. "no non-separator character" ^ self copyFrom: 1 to: last " ' abc d ' withoutTrailingBlanks" ! ! !String methodsFor: 'converting'! withoutTrailingDigits "Answer the portion of the receiver that precedes any trailing series of digits and blanks. If the receiver consists entirely of digits and blanks, return an empty string" | firstDigit | firstDigit _ (self findFirst: [:m | m isDigit or: [m == $ ]]). ^ firstDigit > 0 ifTrue: [self copyFrom: 1 to: firstDigit-1] ifFalse: [self] " 'Whoopie234' withoutTrailingDigits ' 4321 BlastOff!!' withoutLeadingDigits 'wimpy' withoutLeadingDigits ' 89Ten ' withoutLeadingDigits '78 92' withoutLeadingDigits " ! ! !String methodsFor: 'displaying' stamp: 'di 5/28/1998 13:25'! displayAt: aPoint "Display the receiver as a DisplayText at aPoint on the display screen." self displayOn: Display at: aPoint! ! !String methodsFor: 'displaying'! displayOn: aDisplayMedium "Display the receiver on the given DisplayMedium. 5/16/96 sw" self displayOn: aDisplayMedium at: 0 @ 0! ! !String methodsFor: 'displaying' stamp: 'sw 2/5/2002 20:33'! displayOn: aDisplayMedium at: aPoint "Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, using black-colored text." self displayOn: aDisplayMedium at: aPoint textColor: Color black! ! !String methodsFor: 'displaying' stamp: 'sw 2/5/2002 20:33'! displayOn: aDisplayMedium at: aPoint textColor: aColor "Show a representation of the receiver as a DisplayText at location aPoint on aDisplayMedium, rendering the text in the designated color" (self asDisplayText foregroundColor: (aColor ifNil: [Color black]) backgroundColor: Color white) displayOn: aDisplayMedium at: aPoint! ! !String methodsFor: 'displaying' stamp: 'RAA 5/15/2000 11:00'! displayProgressAt: aPoint from: minVal to: maxVal during: workBlock "Display this string as a caption over a progress bar while workBlock is evaluated. EXAMPLE (Select next 6 lines and Do It) 'Now here''s some Real Progress' displayProgressAt: Sensor cursorPoint from: 0 to: 10 during: [:bar | 1 to: 10 do: [:x | bar value: x. (Delay forMilliseconds: 500) wait]]. HOW IT WORKS (Try this in any other language :-) Since your code (the last 2 lines in the above example) is in a block, this method gets control to display its heading before, and clean up the screen after, its execution. The key, though, is that the block is supplied with an argument, named 'bar' in the example, which will update the bar image every it is sent the message value: x, where x is in the from:to: range. " ^ProgressInitiationException display: self at: aPoint from: minVal to: maxVal during: workBlock! ! !String methodsFor: 'printing' stamp: 'sw 9/27/2001 17:26'! basicType "Answer a symbol representing the inherent type of the receiver" "Number String Boolean player collection sound color etc" ^ #String! ! !String methodsFor: 'printing' stamp: 'MPW 1/1/1901 00:22'! encodeDoublingQuoteOn: aStream "Print inside string quotes, doubling inbedded quotes." | x | aStream print: $'. 1 to: self size do: [:i | aStream print: (x _ self at: i). x == $' ifTrue: [aStream print: x]]. aStream print: $'! ! !String methodsFor: 'printing'! isLiteral ^true! ! !String methodsFor: 'printing' stamp: 'sma 6/1/2000 09:48'! printOn: aStream "Print inside string quotes, doubling inbedded quotes." self storeOn: aStream! ! !String methodsFor: 'printing'! storeOn: aStream "Print inside string quotes, doubling inbedded quotes." | x | aStream nextPut: $'. 1 to: self size do: [:i | aStream nextPut: (x _ self at: i). x == $' ifTrue: [aStream nextPut: x]]. aStream nextPut: $'! ! !String methodsFor: 'printing'! stringRepresentation "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" ^ self ! ! !String methodsFor: 'private' stamp: 'di 12/1/2000 14:55'! correctAgainstEnumerator: wordBlock continuedFrom: oldCollection "The guts of correction, instead of a wordList, there is a block that should take another block and enumerate over some list with it." | choices scoreMin results score maxChoices | scoreMin _ self size // 2 min: 3. maxChoices _ 10. oldCollection isNil ifTrue: [ choices _ SortedCollection sortBlock: [ :x :y | x value > y value ] ] ifFalse: [ choices _ oldCollection ]. wordBlock isNil ifTrue: [ results _ OrderedCollection new. 1 to: (maxChoices min: choices size) do: [ :i | results add: (choices at: i) key ] ] ifFalse: [ wordBlock value: [ :word | (score _ self alike: word) >= scoreMin ifTrue: [ choices add: (Association key: word value: score). (choices size >= maxChoices) ifTrue: [ scoreMin _ (choices at: maxChoices) value] ] ]. results _ choices ]. ^ results! ! !String methodsFor: 'private' stamp: 'dgd 8/27/2003 19:42'! evaluateExpression: aString parameters: aCollection "private - evaluate the expression aString with aCollection as the parameters and answer the evaluation result as an string" | index | index := ('0' , aString) asNumber. index isZero ifTrue: [^ '[invalid subscript: {1}]' format: {aString}]. index > aCollection size ifTrue: [^ '[subscript is out of bounds: {1}]' format: {aString}]. ^ (aCollection at: index) asString! ! !String methodsFor: 'private' stamp: 'dgd 8/27/2003 19:41'! getEnclosedExpressionFrom: aStream "private - get the expression enclosed between '{' and '}' and remove all the characters from the stream" | result currentChar | result := String new writeStream. [aStream atEnd or: [(currentChar := aStream next) == $}]] whileFalse: [result nextPut: currentChar]. ^ result contents withBlanksTrimmed! ! !String methodsFor: 'private'! replaceFrom: start to: stop with: replacement startingAt: repStart "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." <primitive: 105> super replaceFrom: start to: stop with: replacement startingAt: repStart! ! !String methodsFor: 'private'! stringhash ^self hash! ! !String methodsFor: 'system primitives' stamp: 'ar 2/3/2001 16:12'! compare: string1 with: string2 collated: order "Return 1, 2 or 3, if string1 is <, =, or > string2, with the collating order of characters given by the order array." | len1 len2 c1 c2 | <primitive: 'primitiveCompareString' module: 'MiscPrimitivePlugin'> self var: #string1 declareC: 'unsigned char *string1'. self var: #string2 declareC: 'unsigned char *string2'. self var: #order declareC: 'unsigned char *order'. len1 _ string1 size. len2 _ string2 size. 1 to: (len1 min: len2) do: [:i | c1 _ order at: (string1 basicAt: i) + 1. c2 _ order at: (string2 basicAt: i) + 1. c1 = c2 ifFalse: [c1 < c2 ifTrue: [^ 1] ifFalse: [^ 3]]]. len1 = len2 ifTrue: [^ 2]. len1 < len2 ifTrue: [^ 1] ifFalse: [^ 3]. ! ! !String methodsFor: 'system primitives' stamp: 'ar 2/3/2001 16:13'! findSubstring: key in: body startingAt: start matchTable: matchTable "Answer the index in the string body at which the substring key first occurs, at or beyond start. The match is determined using matchTable, which can be used to effect, eg, case-insensitive matches. If no match is found, zero will be returned. The algorithm below is not optimum -- it is intended to be translated to C which will go so fast that it wont matter." | index | <primitive: 'primitiveFindSubstring' module: 'MiscPrimitivePlugin'> self var: #key declareC: 'unsigned char *key'. self var: #body declareC: 'unsigned char *body'. self var: #matchTable declareC: 'unsigned char *matchTable'. key size = 0 ifTrue: [^ 0]. start to: body size - key size + 1 do: [:startIndex | index _ 1. [(matchTable at: (body at: startIndex+index-1) asciiValue + 1) = (matchTable at: (key at: index) asciiValue + 1)] whileTrue: [index = key size ifTrue: [^ startIndex]. index _ index+1]]. ^ 0 " ' ' findSubstring: 'abc' in: 'abcdefabcd' startingAt: 1 matchTable: CaseSensitiveOrder 1 ' ' findSubstring: 'abc' in: 'abcdefabcd' startingAt: 2 matchTable: CaseSensitiveOrder 7 ' ' findSubstring: 'abc' in: 'abcdefabcd' startingAt: 8 matchTable: CaseSensitiveOrder 0 ' ' findSubstring: 'abc' in: 'abcdefABcd' startingAt: 2 matchTable: CaseSensitiveOrder 0 ' ' findSubstring: 'abc' in: 'abcdefABcd' startingAt: 2 matchTable: CaseInsensitiveOrder 7 "! ! !String methodsFor: 'system primitives' stamp: 'di 12/3/2000 09:34'! numArgs "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." | firstChar numColons excess start ix | self size = 0 ifTrue: [^ -1]. firstChar _ self at: 1. (firstChar isLetter or: [firstChar = $:]) ifTrue: ["Fast reject if any chars are non-alphanumeric" (self findSubstring: '~' in: self startingAt: 1 matchTable: Tokenish) > 0 ifTrue: [^ -1]. "Fast colon count" numColons _ 0. start _ 1. [(ix _ self findSubstring: ':' in: self startingAt: start matchTable: CaseSensitiveOrder) > 0] whileTrue: [numColons _ numColons + 1. start _ ix + 1]. numColons = 0 ifTrue: [^ 0]. firstChar = $: ifTrue: [excess _ 2 "Has an initial keyword, as #:if:then:else:"] ifFalse: [excess _ 0]. self last = $: ifTrue: [^ numColons - excess] ifFalse: [^ numColons - excess - 1 "Has a final keywords as #nextPut::andCR"]]. firstChar isSpecial ifTrue: [self size = 1 ifTrue: [^ 1]. 2 to: self size do: [:i | (self at: i) isSpecial ifFalse: [^ -1]]. ^ 1]. ^ -1.! ! !String methodsFor: 'Celeste'! withCRs "Return a copy of the receiver in which backslash (\) characters have been replaced with carriage returns." ^ self collect: [ :c | c = $\ ifTrue: [ Character cr ] ifFalse: [ c ]].! ! !String methodsFor: 'internet' stamp: 'sma 3/11/2000 20:40'! isoToSqueak ^ self collect: [:each | each isoToSqueak]! ! !String methodsFor: 'internet' stamp: 'JO 9/2/2002 11:54'! isoToUtf8 "Convert ISO 8559-1 to UTF-8" | s v | s _ WriteStream on: (String new: self size). self do: [:c | v _ c asciiValue. (v > 128) ifFalse: [s nextPut: c] ifTrue: [ s nextPut: (192+(v >> 6)) asCharacter. s nextPut: (128+(v bitAnd: 63)) asCharacter]]. ^s contents. ! ! !String methodsFor: 'internet' stamp: 'BG 10/29/2003 08:20'! replaceHtmlCharRefs | pos ampIndex scIndex special specialValue outString outPos newOutPos | outString _ String new: self size. outPos _ 0. pos _ 1. [ pos <= self size ] whileTrue: [ "read up to the next ampersand" ampIndex _ self indexOf: $& startingAt: pos ifAbsent: [0]. ampIndex = 0 ifTrue: [ pos = 1 ifTrue: [ ^self ] ifFalse: [ ampIndex _ self size+1 ] ]. newOutPos _ outPos + ampIndex - pos. outString replaceFrom: outPos + 1 to: newOutPos with: self startingAt: pos. outPos _ newOutPos. pos _ ampIndex. ampIndex <= self size ifTrue: [ "find the $;" scIndex _ self indexOf: $; startingAt: ampIndex ifAbsent: [ self size + 1 ]. special _ self copyFrom: ampIndex+1 to: scIndex-1. specialValue _ "HtmlEntity valueOfHtmlEntity: special" 16r32. specialValue ifNil: [ "not a recognized entity. wite it back" scIndex > self size ifTrue: [ scIndex _ self size ]. newOutPos _ outPos + scIndex - ampIndex + 1. outString replaceFrom: outPos+1 to: newOutPos with: self startingAt: ampIndex. outPos _ newOutPos.] ifNotNil: [ outPos _ outPos + 1. outString at: outPos put: specialValue isoToSqueak.]. pos _ scIndex + 1. ]. ]. ^outString copyFrom: 1 to: outPos! ! !String methodsFor: 'internet' stamp: 'bf 3/9/2000 16:46'! squeakToIso ^self collect: [:c | c squeakToIso ]! ! !String methodsFor: 'internet' stamp: 'RAA 2/6/2001 09:37'! unescapePercents "change each %XY substring to the character with ASCII value XY in hex. This is the opposite of #encodeForHTTP" | ans c asciiVal pos oldPos specialChars | ans _ WriteStream on: String new. oldPos _ 1. specialChars _ '+%' asCharacterSet. [pos _ self indexOfAnyOf: specialChars startingAt: oldPos. pos > 0] whileTrue: [ ans nextPutAll: (self copyFrom: oldPos to: pos - 1). c _ self at: pos. c = $+ ifTrue: [ans nextPut: $ ] ifFalse: [ (c = $% and: [pos + 2 <= self size]) ifTrue: [ asciiVal _ (self at: pos+1) asUppercase digitValue * 16 + (self at: pos+2) asUppercase digitValue. pos _ pos + 2. asciiVal > 255 ifTrue: [^self]. "not really an escaped string" ans nextPut: (Character value: asciiVal)] ifFalse: [ans nextPut: c]]. oldPos _ pos+1]. ans nextPutAll: (self copyFrom: oldPos to: self size). ^ ans contents! ! !String methodsFor: 'internet' stamp: 'JO 9/2/2002 11:59'! utf8ToIso "Only UTF-8 characters that maps to 8-bit ISO-8559-1 values are converted. Others raises an error" | s i c v c2 v2 | s _ WriteStream on: (String new: self size). i _ 1. [i <= self size] whileTrue: [ c _ self at: i. i_i+1. v _ c asciiValue. (v > 128) ifFalse: [ s nextPut: c ] ifTrue: [((v bitAnd: 252) == 192) ifFalse: [self error: 'illegal UTF-8 ISO character'] ifTrue: [ (i > self size) ifTrue: [ self error: 'illegal end-of-string, expected 2nd byte of UTF-8']. c2 _ self at: i. i_i+1. v2 _ c2 asciiValue. ((v2 bitAnd: 192) = 128) ifFalse: [self error: 'illegal 2nd UTF-8 char']. s nextPut: ((v2 bitAnd: 63) bitOr: ((v << 6) bitAnd: 192)) asCharacter]]]. ^s contents. ! ! !String methodsFor: 'internet' stamp: 'ls 7/27/1998 23:17'! withInternetLineEndings "change line endings from CR's to CRLF's. This is probably in prepration for sending a string over the Internet" | cr lf | cr _ Character cr. lf _ Character linefeed. ^self class streamContents: [ :stream | self do: [ :c | stream nextPut: c. c = cr ifTrue:[ stream nextPut: lf ]. ] ].! ! !String methodsFor: 'internet' stamp: 'ls 10/27/1998 00:52'! withSqueakLineEndings "assume the string is textual, and that CR, LF, and CRLF are all valid line endings. Replace each occurence with a single CR" | cr lf input c crlf inPos outPos outString lineEndPos newOutPos | cr _ Character cr. lf _ Character linefeed. crlf _ CharacterSet new. crlf add: cr; add: lf. inPos _ 1. outPos _ 1. outString _ String new: self size. [ lineEndPos _ self indexOfAnyOf: crlf startingAt: inPos ifAbsent: [0]. lineEndPos ~= 0 ] whileTrue: [ newOutPos _ outPos + (lineEndPos - inPos + 1). outString replaceFrom: outPos to: newOutPos - 2 with: self startingAt: inPos. outString at: newOutPos-1 put: cr. outPos _ newOutPos. ((self at: lineEndPos) = cr and: [ lineEndPos < self size and: [ (self at: lineEndPos+1) = lf ] ]) ifTrue: [ "CRLF ending" inPos _ lineEndPos + 2 ] ifFalse: [ "CR or LF ending" inPos _ lineEndPos + 1 ]. ]. "no more line endings. copy the rest" newOutPos _ outPos + (self size - inPos + 1). outString replaceFrom: outPos to: newOutPos-1 with: self startingAt: inPos. ^outString copyFrom: 1 to: newOutPos-1 ! ! !String methodsFor: 'internet' stamp: 'ls 7/1/1998 02:26'! withoutQuoting "remove the initial and final quote marks, if present" "'''h''' withoutQuoting" | quote | self size < 2 ifTrue: [ ^self ]. quote _ self first. (quote = $' or: [ quote = $" ]) ifTrue: [ ^self copyFrom: 2 to: self size - 1 ] ifFalse: [ ^self ].! ! !String methodsFor: 'testing' stamp: 'RAA 6/21/1999 11:28'! hasContentsInExplorer ^false! ! !String methodsFor: 'testing' stamp: 'djp 10/26/1999 21:25'! isAllDigits "whether the receiver is composed entirely of digits" self do: [:c | c isDigit ifFalse: [^ false]]. ^ true! ! !String methodsFor: 'testing' stamp: 'ls 7/4/1998 19:17'! isAllSeparators "whether the receiver is composed entirely of separators" self do: [ :c | c isSeparator ifFalse: [ ^false ] ]. ^true! ! !String methodsFor: 'testing' stamp: 'sma 6/15/2000 15:48'! isString ^ true! ! !String methodsFor: 'testing' stamp: 'sw 11/5/1998 17:41'! lastSpacePosition "Answer the character position of the final space or other separator character in the receiver, and 0 if none" self size to: 1 by: -1 do: [:i | ((self at: i) isSeparator) ifTrue: [^ i]]. ^ 0 " 'fred the bear' lastSpacePosition 'ziggie' lastSpacePosition 'elvis ' lastSpacePosition 'wimpy ' lastSpacePosition '' lastSpacePosition "! ! !String methodsFor: 'paragraph support' stamp: 'RAA 8/30/1998 15:20'! indentationIfBlank: aBlock "Answer the number of leading tabs in the receiver. If there are no visible characters, pass the number of tabs to aBlock and return its value." | reader leadingTabs lastSeparator cr tab ch | cr _ Character cr. tab _ Character tab. reader _ ReadStream on: self. leadingTabs _ 0. [reader atEnd not and: [(ch _ reader next) == tab]] whileTrue: [leadingTabs _ leadingTabs + 1]. lastSeparator _ leadingTabs + 1. [reader atEnd not and: [ch isSeparator and: [ch ~~ cr]]] whileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next]. lastSeparator = self size | (ch == cr) ifTrue: [^aBlock value: leadingTabs]. ^leadingTabs! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! * arg ^ arg adaptToString: self andSend: #*! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! + arg ^ arg adaptToString: self andSend: #+! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! - arg ^ arg adaptToString: self andSend: #-! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! / arg ^ arg adaptToString: self andSend: #/! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! // arg ^ arg adaptToString: self andSend: #//! ! !String methodsFor: 'arithmetic' stamp: 'di 11/6/1998 14:03'! \\ arg ^ arg adaptToString: self andSend: #\\! ! !String methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 01:17'! byteEncode:aStream ^aStream writeString:self.! ! !String methodsFor: 'filter streaming' stamp: 'MPW 1/1/1901 23:02'! putOn:aStream ^aStream nextPutAll:self. ! ! !String methodsFor: 'encoding' stamp: 'RAA 7/22/2000 08:52'! getInteger32: location | integer | <primitive: 'getInteger' module: 'IntegerPokerPlugin'> "^IntegerPokerPlugin doPrimitive: #getInteger" "the following is about 7x faster than interpreting the plugin if not compiled" integer := ((self byteAt: location) bitShift: 24) + ((self byteAt: location+1) bitShift: 16) + ((self byteAt: location+2) bitShift: 8) + (self byteAt: location+3). integer > 1073741824 ifTrue: [ ^1073741824 - integer ]. ^integer ! ! !String methodsFor: 'encoding' stamp: 'RAA 7/31/2000 16:06'! putInteger32: anInteger at: location | integer | <primitive: 'putInteger' module: 'IntegerPokerPlugin'> "IntegerPokerPlugin doPrimitive: #putInteger" "the following is close to 20x faster than the above if the primitive is not compiled" "PUTCOUNTER _ PUTCOUNTER + 1." integer _ anInteger. integer < 0 ifTrue: [integer := 1073741824 - integer. ]. self byteAt: location+3 put: (integer \\ 256). self byteAt: location+2 put: (integer bitShift: -8) \\ 256. self byteAt: location+1 put: (integer bitShift: -16) \\ 256. self byteAt: location put: (integer bitShift: -24) \\ 256. "Smalltalk at: #PUTCOUNTER put: 0"! ! !String methodsFor: 'user interface' stamp: 'ajh 9/25/2002 13:10'! asExplorerString ^ self printString! ! !String methodsFor: 'user interface' stamp: 'sw 8/10/2001 10:41'! openInWorkspaceWithTitle: aTitle "Open up a workspace with the receiver as its contents, with the given title" (Workspace new contents: self) openLabel: aTitle! ! !String methodsFor: 'Camp Smalltalk' stamp: 'jp 3/17/2003 10:04'! sunitAsSymbol ^self asSymbol! ! !String methodsFor: 'Camp Smalltalk' stamp: 'jp 3/17/2003 10:04'! sunitMatch: aString ^self match: aString! ! !String methodsFor: 'Camp Smalltalk' stamp: 'jp 3/17/2003 10:04'! sunitSubStrings ^self substrings! ! !String methodsFor: '*packageinfo-base' stamp: 'ab 5/31/2003 17:13'! escapeEntities ^ String streamContents: [:s | self do: [:c | s nextPutAll: c escapeEntities]] ! ! !String methodsFor: 'translating' stamp: 'BG 8/18/2004 15:12'! translated "answer the receiver translated to the default language" ^self! ! !String methodsFor: 'formatting' stamp: 'dgd 8/27/2003 19:49'! format: aCollection "format the receiver with aCollection simplest example: 'foo {1} bar' format: {Date today}. complete example: '\{ \} \\ foo {1} bar {2}' format: {12. 'string'}. " | result stream | result := String new writeStream. stream := self readStream. [stream atEnd] whileFalse: [| currentChar | currentChar := stream next. currentChar == ${ ifTrue: [| expression | expression := self getEnclosedExpressionFrom: stream. result nextPutAll: (self evaluateExpression: expression parameters: aCollection)] ifFalse: [ currentChar == $\ ifTrue: [stream atEnd ifFalse: [result nextPut: stream next]] ifFalse: [result nextPut: currentChar]]]. ^ result contents! ! !String methodsFor: '*versionnumber' stamp: 'svp 6/18/2002 16:12'! asVersion "Answer a VersionNumber" ^VersionNumber fromString: self! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! String class instanceVariableNames: ''! !String class methodsFor: 'instance creation' stamp: 'jm 5/6/1998 18:39'! cr "Answer a string containing a single carriage return character." ^ self with: Character cr ! ! !String class methodsFor: 'instance creation' stamp: 'ls 9/10/1998 22:29'! crlf "Answer a string containing a carriage return and a linefeed." ^ self with: Character cr with: Character lf ! ! !String class methodsFor: 'instance creation' stamp: 'ar 8/17/2001 18:19'! crlfcrlf ^self crlf , self crlf. ! ! !String class methodsFor: 'instance creation'! fromPacked: aLong "Convert from a longinteger to a String of length 4." | s | s _ self new: 4. s at: 1 put: (aLong digitAt: 4) asCharacter. s at: 2 put: (aLong digitAt: 3) asCharacter. s at: 3 put: (aLong digitAt: 2) asCharacter. s at: 4 put: (aLong digitAt: 1) asCharacter. ^s "String fromPacked: 'TEXT' asPacked" ! ! !String class methodsFor: 'instance creation' stamp: 'di 1/14/98 10:26'! fromString: aString "Answer an instance of me that is a copy of the argument, aString." ^ aString copyFrom: 1 to: aString size! ! !String class methodsFor: 'instance creation' stamp: 'ar 3/15/2001 22:47'! lf "Answer a string containing a single carriage return character." ^ self with: Character lf! ! !String class methodsFor: 'instance creation'! readFrom: inStream "Answer an instance of me that is determined by reading the stream, inStream. Embedded double quotes become the quote Character." | outStream char done | outStream _ WriteStream on: (String new: 16). "go to first quote" inStream skipTo: $'. done _ false. [done or: [inStream atEnd]] whileFalse: [char _ inStream next. char = $' ifTrue: [char _ inStream next. char = $' ifTrue: [outStream nextPut: char] ifFalse: [done _ true]] ifFalse: [outStream nextPut: char]]. ^outStream contents! ! !String class methodsFor: 'instance creation' stamp: 'sw 6/15/1999 22:59'! tab "Answer a string containing a single tab character." ^ self with: Character tab ! ! !String class methodsFor: 'instance creation' stamp: 'ar 12/17/2001 01:24'! value: anInteger ^self with: (Character value: anInteger)! ! !String class methodsFor: 'examples'! example "To see the string displayed at the cursor point, execute this expression and select a point by pressing a mouse button." 'this is some text' displayOn: Display at: Sensor waitButton! ! !String class methodsFor: 'initialization' stamp: 'di 12/3/2000 09:06'! initialize "String initialize" | order | AsciiOrder _ (0 to: 255) as: ByteArray. CaseInsensitiveOrder _ AsciiOrder copy. ($a to: $z) do: [:c | CaseInsensitiveOrder at: c asciiValue + 1 put: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)]. "Case-sensitive compare sorts space, digits, letters, all the rest..." CaseSensitiveOrder _ ByteArray new: 256 withAll: 255. order _ -1. ' 0123456789' do: "0..10" [:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)]. ($a to: $z) do: "11-64" [:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order _ order+1). CaseSensitiveOrder at: c asciiValue + 1 put: (order _ order+1)]. 1 to: CaseSensitiveOrder size do: [:i | (CaseSensitiveOrder at: i) = 255 ifTrue: [CaseSensitiveOrder at: i put: (order _ order+1)]]. order = 255 ifFalse: [self error: 'order problem']. "a table for translating to lower case" LowercasingTable _ String withAll: (Character allCharacters collect: [:c | c asLowercase]). "a table for translating to upper case" UppercasingTable _ String withAll: (Character allCharacters collect: [:c | c asUppercase]). "a table for testing tokenish (for fast numArgs)" Tokenish _ String withAll: (Character allCharacters collect: [:c | c tokenish ifTrue: [c] ifFalse: [$~]]). "CR and LF--characters that terminate a line" CSLineEnders _ CharacterSet empty. CSLineEnders add: Character cr. CSLineEnders add: Character lf. "separators and non-separators" CSSeparators _ CharacterSet separators. CSNonSeparators _ CSSeparators complement.! ! !String class methodsFor: 'initialization' stamp: 'CdG 1/8/2004 15:17'! initializeHtmlEntities "String initializeHtmlEntities" HtmlEntities _ (Dictionary new: 128) at: 'amp' put: $&; at: 'lt' put: $<; at: 'gt' put: $>; at: 'quot' put: $"; at: 'euro' put: Character euro; yourself. #('nbsp' 'iexcl' 'cent' 'pound' 'curren' 'yen' 'brvbar' 'sect' 'uml' 'copy' 'ordf' 'laquo' 'not' 'shy' 'reg' 'hibar' 'deg' 'plusmn' 'sup2' 'sup3' 'acute' 'micro' 'para' 'middot' 'cedil' 'sup1' 'ordm' 'raquo' 'frac14' 'frac12' 'frac34' 'iquest' 'Agrave' 'Aacute' 'Acirc' 'Atilde' 'Auml' 'Aring' 'AElig' 'Ccedil' 'Egrave' 'Eacute' 'Ecirc' 'Euml' 'Igrave' 'Iacute' 'Icirc' 'Iuml' 'ETH' 'Ntilde' 'Ograve' 'Oacute' 'Ocirc' 'Otilde' 'Ouml' 'times' 'Oslash' 'Ugrave' 'Uacute' 'Ucirc' 'Uuml' 'Yacute' 'THORN' 'szlig' 'agrave' 'aacute' 'acirc' 'atilde' 'auml' 'aring' 'aelig' 'ccedil' 'egrave' 'eacute' 'ecirc' 'euml' 'igrave' 'iacute' 'icirc' 'iuml' 'eth' 'ntilde' 'ograve' 'oacute' 'ocirc' 'otilde' 'ouml' 'divide' 'oslash' 'ugrave' 'uacute' 'ucirc' 'uuml' 'yacute' 'thorn' 'yuml' ) withIndexDo: [:each :index | "filter out base characters CdG 1/8/2004 15:17" | char | char _ (index + 159) asCharacter isoToSqueak. char >= (Character value: 128) ifTrue: [ HtmlEntities at: each put: char]]! ! !String class methodsFor: 'primitives' stamp: 'ar 2/3/2001 16:12'! findFirstInString: aString inSet: inclusionMap startingAt: start | i stringSize | <primitive: 'primitiveFindFirstInString' module: 'MiscPrimitivePlugin'> self var: #aString declareC: 'unsigned char *aString'. self var: #inclusionMap declareC: 'char *inclusionMap'. inclusionMap size ~= 256 ifTrue: [ ^0 ]. i _ start. stringSize _ aString size. [ i <= stringSize and: [ (inclusionMap at: (aString at: i) asciiValue+1) = 0 ] ] whileTrue: [ i _ i + 1 ]. i > stringSize ifTrue: [ ^0 ]. ^i! ! !String class methodsFor: 'primitives' stamp: 'ar 2/3/2001 16:13'! indexOfAscii: anInteger inString: aString startingAt: start | stringSize | <primitive: 'primitiveIndexOfAsciiInString' module: 'MiscPrimitivePlugin'> self var: #aCharacter declareC: 'int anInteger'. self var: #aString declareC: 'unsigned char *aString'. stringSize _ aString size. start to: stringSize do: [:pos | (aString at: pos) asciiValue = anInteger ifTrue: [^ pos]]. ^ 0 ! ! !String class methodsFor: 'primitives' stamp: 'ar 9/28/2001 04:35'! stringHash: aString initialHash: speciesHash | stringSize hash low | <primitive: 'primitiveStringHash' module: 'MiscPrimitivePlugin'> self var: #aHash declareC: 'int speciesHash'. self var: #aString declareC: 'unsigned char *aString'. stringSize _ aString size. hash _ speciesHash bitAnd: 16rFFFFFFF. 1 to: stringSize do: [:pos | hash _ hash + (aString at: pos) asciiValue. "Begin hashMultiply" low _ hash bitAnd: 16383. hash _ (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF. ]. ^ hash! ! !String class methodsFor: 'primitives' stamp: 'ar 2/3/2001 16:12'! translate: aString from: start to: stop table: table "translate the characters in the string by the given table, in place" <primitive: 'primitiveTranslateStringWithTable' module: 'MiscPrimitivePlugin'> self var: #table declareC: 'unsigned char *table'. self var: #aString declareC: 'unsigned char *aString'. start to: stop do: [ :i | aString at: i put: (table at: (aString at: i) asciiValue+1) ]! ! !String class methodsFor: 'plugin generation' stamp: 'acg 9/19/1999 00:21'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asCharPtrFrom: anInteger andThen: (cg ccgValBlock: 'isBytes')! ! !String class methodsFor: 'plugin generation' stamp: 'acg 9/18/1999 17:10'! ccgDeclareCForVar: aSymbolOrString ^'char *', aSymbolOrString! ! Model subclass: #StringHolder instanceVariableNames: 'contents' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !StringHolder commentStamp: '<historical>' prior: 0! I am a kind of Model that includes a piece of text. In some cases, the text can be edited, and in some the text is a method. Categories 'code pane menu' and 'message list menu' are messages that may be called by my menus when the text is a method, and when some pane is a list of methods. Other of my subclasses may ignore these two catagories altogether.! !StringHolder methodsFor: 'initialize-release'! defaultContents ^''! ! !StringHolder methodsFor: 'initialize-release' stamp: 'jm 3/24/98 17:56'! initialize "Initialize the state of the receiver with its default contents." contents _ self defaultContents. ! ! !StringHolder methodsFor: 'initialize-release' stamp: 'sw 12/22/1998 00:16'! openLabel: aString "Create a standard system view of the model, me, a StringHolder and open it. If in mvc, terminate the active controller so that the new window will immediately be activated." self openLabel: aString andTerminate: true! ! !StringHolder methodsFor: 'initialize-release' stamp: 'BG 10/28/2003 20:43'! openLabel: aString andTerminate: terminateBoolean "Create a standard system view of the model, me, a StringHolder and open it.; do not terminate the active process if in mvc" | topView codeView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. topView label: aString. topView minimumSize: 100 @ 50. codeView _ PluggableTextView on: self text: #contents accept: #acceptContents: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. codeView window: (0@0 extent: 200@200). topView addSubView: codeView. "self contents size > 0 ifTrue: [ codeView hasUnacceptedEdits: true]. Is it already saved or not??" terminateBoolean ifTrue: [topView controller open] ifFalse: [topView controller openNoTerminate]! ! !StringHolder methodsFor: 'accessing' stamp: 'di 5/19/1998 15:34'! acceptContents: aString "Set aString to be the contents of the receiver. Return true cuz happy" self contents: aString. ^ true! ! !StringHolder methodsFor: 'accessing'! contents "Answer the contents that the receiver is holding--presumably a string." ^contents! ! !StringHolder methodsFor: 'accessing' stamp: 'sw 1/12/1999 11:47'! contents: textOrString "Set textOrString to be the contents of the receiver." contents _ textOrString "asString"! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/3/98 22:50'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" ^ 1 to: 0 "null selection"! ! !StringHolder methodsFor: 'accessing' stamp: 'sw 12/9/2000 23:59'! noteAcceptanceOfCodeFor: aSelector "A method has possibly been submitted for the receiver with aSelector as its selector; If the receiver wishes to take soem action here is a chance for it to do so" ! ! !StringHolder methodsFor: 'accessing' stamp: 'sw 12/1/2000 11:04'! reformulateList "If the receiver has a way of reformulating its message list, here is a chance for it to do so"! ! !StringHolder methodsFor: 'accessing' stamp: 'sw 12/6/2000 17:48'! reformulateListNoting: newSelector "A method has possibly been submitted for the receiver with newSelector as its selector; If the receiver has a way of reformulating its message list, here is a chance for it to do so" ^ self reformulateList! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 14:59'! selectedClassName "I may know what class is currently selected" self selectedClass ifNotNil: [^ self selectedClass name]. ^ nil! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:01'! selectedClassOrMetaClass ^ self selectedClass "I don't know any better"! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/18/1998 15:22'! selectedMessageName ^ nil! ! !StringHolder methodsFor: 'accessing' stamp: 'di 11/23/1998 15:21'! textContents: aStringOrText "Set aStringOrText to be the contents of the receiver." contents _ aStringOrText! ! !StringHolder methodsFor: 'code pane menu' stamp: 'sw 11/8/1999 17:56'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane" | donorMenu | donorMenu _ shifted ifTrue: [ParagraphEditor shiftedYellowButtonMenu] ifFalse: [ParagraphEditor yellowButtonMenu]. ^ aMenu labels: donorMenu labelString lines: donorMenu lineArray selections: donorMenu selections! ! !StringHolder methodsFor: 'code pane menu' stamp: 'wod 5/29/1998 16:35'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !StringHolder methodsFor: 'code pane menu' stamp: 'tk 4/6/98 11:43'! showBytecodes "We don't know how to do this" ^ self changed: #flash! ! !StringHolder methodsFor: 'code pane menu' stamp: 'di 9/7/1999 11:27'! spawn: contentsString (Workspace new contents: contentsString) openLabel: 'Workspace' ! ! !StringHolder methodsFor: 'evaluation'! doItContext "Answer the context in which a text selection can be evaluated." ^nil! ! !StringHolder methodsFor: 'evaluation'! doItReceiver "Answer the object that should be informed of the result of evaluating a text selection." ^nil! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/15/2003 22:46'! browseAllMessages "Create and schedule a message set browser on all implementors of all the messages sent by the current method." | aClass aName method filteredList | (aName _ self selectedMessageName) ifNotNil: [ method _ (aClass _ self selectedClassOrMetaClass) compiledMethodAt: aName. filteredList _ method messages reject: [:each | #(new initialize = ) includes: each]. self systemNavigation browseAllImplementorsOfList: filteredList asSortedCollection title: 'All messages sent in ', aClass name, '.', aName] ! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/18/1998 16:11'! browseClass "Open an class browser on this class and method" self selectedClassOrMetaClass ifNotNil: [ Browser newOnClass: self selectedClassOrMetaClass selector: self selectedMessageName]! ! !StringHolder methodsFor: 'message list menu' stamp: 'tpr 12/17/2003 15:43'! browseClassRefs | cls | (cls _ self selectedClass) ifNotNil: [ self systemNavigation browseAllCallsOnClass: cls theNonMetaClass] ! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/15/2003 16:11'! browseClassVarRefs "1/17/96 sw: devolve responsibility to the class, so that the code that does the real work can be shared" | cls | cls _ self selectedClass. cls ifNotNil: [self systemNavigation browseClassVarRefs: cls]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/15/2003 16:11'! browseClassVariables "Browse the class variables of the selected class. 2/5/96 sw" | cls | cls _ self selectedClass. cls ifNotNil: [self systemNavigation browseClassVariables: cls] ! ! !StringHolder methodsFor: 'message list menu' stamp: 'RAA 5/28/2001 11:09'! browseFullProtocol "Open up a protocol-category browser on the value of the receiver's current selection. If in mvc, an old-style protocol browser is opened instead. Someone who still uses mvc might wish to make the protocol-category-browser work there too, thanks." | aClass | (Smalltalk isMorphic and: [Smalltalk includesKey: #Lexicon]) ifFalse: [^ self spawnFullProtocol]. (aClass _ self selectedClassOrMetaClass) ifNotNil: [(Smalltalk at: #Lexicon) new openOnClass: aClass inWorld: ActiveWorld showingSelector: self selectedMessageName]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 19:42'! browseInstVarDefs | cls | (cls _ self selectedClassOrMetaClass) ifNotNil: [self systemNavigation browseInstVarDefs: cls]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/15/2003 16:11'! browseInstVarRefs "1/26/96 sw: real work moved to class, so it can be shared" | cls | cls _ self selectedClassOrMetaClass. cls ifNotNil: [self systemNavigation browseInstVarRefs: cls]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 08:42'! browseLocalImplementors "Present a menu of all messages sent by the currently selected message. Open a message set browser of all implementors of the message chosen in or below the selected class. Do nothing if no message is chosen." self getSelectorAndSendQuery: #browseAllImplementorsOf:localTo: to: self systemNavigation with: { self selectedClass }! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 20:41'! browseLocalSendersOfMessages "Present a menu of the currently selected message, as well as all messages sent by it. Open a message set browser of all implementors of the message chosen in or below the selected class" self getSelectorAndSendQuery: #browseAllCallsOn:localTo: to: self systemNavigation with: { self selectedClass }! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 08:45'! browseMessages "Present a menu of all messages sent by the currently selected message. Open a message set browser of all implementors of the message chosen." self getSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/28/1998 09:28'! browseMethodFull "Create and schedule a full Browser and then select the current class and message." | myClass | (myClass _ self selectedClassOrMetaClass) ifNotNil: [Browser fullOnClass: myClass selector: self selectedMessageName]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 20:40'! browseSendersOfMessages "Present a menu of the currently selected message, as well as all messages sent by it. Open a message set browser of all senders of the selector chosen." self getSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/29/2003 20:20'! browseUnusedMethods | classes unsent messageList cls | (cls _ self selectedClass) ifNil: [^ self]. classes _ Array with: cls with: cls class. unsent _ Set new. classes do: [:c | unsent addAll: c selectors]. unsent _ self systemNavigation allUnSentMessagesIn: unsent. messageList _ OrderedCollection new. classes do: [:c | (c selectors select: [:s | unsent includes: s]) asSortedCollection do: [:sel | messageList add: c name , ' ' , sel]]. self systemNavigation browseMessageList: messageList name: 'Unsent Methods in ' , cls name! ! !StringHolder methodsFor: 'message list menu' stamp: 'nk 1/7/2004 10:20'! browseVersions "Create and schedule a Versions Browser, showing all versions of the currently selected message. Answer the browser or nil." | selector class | (selector _ self selectedMessageName) ifNil:[ self inform: 'Sorry, only actual methods have retrievable versions.'. ^nil ] ifNotNil: [(MessageSet isPseudoSelector: selector) ifTrue: ["Eliminates Definition and Hierarchy" ^ self classCommentIndicated ifTrue: [ ClassCommentVersionsBrowser browseCommentOf: self selectedClass. nil ]]. class _ self selectedClassOrMetaClass. ^VersionsBrowser browseVersionsOf: (class compiledMethodAt: selector) class: self selectedClass meta: class isMeta category: (class organization categoryOfElement: selector) selector: selector]! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/28/1998 19:14'! buildMessageBrowser "Create and schedule a message browser." self selectedMessageName ifNil: [^ self]. Browser openMessageBrowserForClass: self selectedClassOrMetaClass selector: self selectedMessageName editString: nil! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 1/16/2004 21:14'! classHierarchy "Create and schedule a class list browser on the receiver's hierarchy." self systemNavigation spawnHierarchyForClass: self selectedClassOrMetaClass "OK if nil" selector: self selectedMessageName ! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 5/8/2000 02:16'! classListKey: aChar from: view "Respond to a Command key. I am a model with a list of classes and a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection." aChar == $f ifTrue: [^ self findMethod]. aChar == $r ifTrue: [^ self recent]. aChar == $h ifTrue: [^ self spawnHierarchy]. aChar == $x ifTrue: [^ self removeClass]. ^ self messageListKey: aChar from: view! ! !StringHolder methodsFor: 'message list menu' stamp: 'ar 1/15/2001 18:39'! copyName "Copy the current selector to the clipboard" | selector | (selector _ self selectedMessageName) ifNotNil: [Clipboard clipboardText: selector asString asText]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 8/5/2002 16:53'! copySelector "Copy the selected selector to the clipboard" | selector | (selector _ self selectedMessageName) ifNotNil: [Clipboard clipboardText: selector asString]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 7/1/2001 08:24'! fileOutMessage "Put a description of the selected message on a file" self selectedMessageName ifNotNil: [Cursor write showWhile: [self selectedClassOrMetaClass fileOutMethod: self selectedMessageName]]! ! !StringHolder methodsFor: 'message list menu' stamp: 'di 5/6/1998 17:03'! findMethodInChangeSets "Find and open a changeSet containing the current method." | aName | (aName _ self selectedMessageName) ifNotNil: [ ChangeSorter browseChangeSetsWithClass: self selectedClassOrMetaClass selector: aName]! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/21/1998 09:23'! inspectInstances "Inspect all instances of the selected class." | myClass | (myClass _ self selectedClassOrMetaClass) ifNotNil: [myClass theNonMetaClass inspectAllInstances]. ! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/21/1998 09:00'! inspectSubInstances "Inspect all instances of the selected class and all its subclasses" | aClass | (aClass _ self selectedClassOrMetaClass) ifNotNil: [ aClass theNonMetaClass inspectSubInstances]. ! ! !StringHolder methodsFor: 'message list menu' stamp: 'nb 6/17/2003 12:25'! makeIsolatedCodePane | msgName | (msgName _ self selectedMessageName) ifNil: [^ Beeper beep]. MethodHolder makeIsolatedCodePaneForClass: self selectedClassOrMetaClass selector: msgName! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 08:45'! messageListKey: aChar from: view "Respond to a Command key. I am a model with a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection." | sel class | aChar == $D ifTrue: [^ self toggleDiffing]. sel _ self selectedMessageName. aChar == $m ifTrue: "These next two put up a type in if no message selected" [^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllImplementorsOf: to: self systemNavigation]. aChar == $n ifTrue: [^ self useSelector: sel orGetSelectorAndSendQuery: #browseAllCallsOn: to: self systemNavigation]. "The following require a class selection" (class _ self selectedClassOrMetaClass) ifNil: [^ self arrowKey: aChar from: view]. aChar == $b ifTrue: [^ Browser fullOnClass: class selector: sel]. aChar == $N ifTrue: [^ self browseClassRefs]. aChar == $i ifTrue: [^ self methodHierarchy]. aChar == $h ifTrue: [^ self classHierarchy]. aChar == $p ifTrue: [^ self browseFullProtocol]. "The following require a method selection" sel ifNotNil: [aChar == $o ifTrue: [^ self fileOutMessage]. aChar == $c ifTrue: [^ self copySelector]. aChar == $v ifTrue: [^ self browseVersions]. aChar == $O ifTrue: [^ self openSingleMessageBrowser]. aChar == $x ifTrue: [^ self removeMessage]]. ^ self arrowKey: aChar from: view! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 12/28/2000 11:49'! messageListSelectorTitle | selector aString aStamp aSize | (selector _ self selectedMessageName) ifNil: [aSize _ self messageList size. ^ (aSize == 0 ifTrue: ['no'] ifFalse: [aSize printString]), ' message', (aSize == 1 ifTrue: [''] ifFalse: ['s'])] ifNotNil: [Preferences timeStampsInMenuTitles ifFalse: [^ nil]. aString _ selector truncateWithElipsisTo: 28. ^ (aStamp _ self timeStamp) size > 0 ifTrue: [aString, String cr, aStamp] ifFalse: [aString]]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 1/16/2004 21:10'! methodHierarchy "Create and schedule a method browser on the hierarchy of implementors." self systemNavigation methodHierarchyBrowserForClass: self selectedClassOrMetaClass selector: self selectedMessageName ! ! !StringHolder methodsFor: 'message list menu' stamp: 'BG 10/29/2003 09:40'! offerMenuFrom: menuRetriever shifted: aBoolean "Pop up, in morphic or mvc as the case may be, a menu whose target is the receiver and whose contents are provided by sending the menuRetriever to the receiver. The menuRetriever takes two arguments: a menu, and a boolean representing the shift state." | aMenu | Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu _ CustomMenu new. self perform: menuRetriever with: aMenu with: aBoolean. aMenu invokeOn: self]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/16/2003 08:52'! openSingleMessageBrowser | msgName mr | "Create and schedule a message list browser populated only by the currently selected message" (msgName _ self selectedMessageName) ifNil: [^ self]. mr _ MethodReference new setStandardClass: self selectedClassOrMetaClass methodSymbol: msgName. self systemNavigation browseMessageList: (Array with: mr) name: mr asStringOrText autoSelect: nil! ! !StringHolder methodsFor: 'message list menu' stamp: 'RAA 12/10/1999 09:36'! packageListKey: aChar from: view "Respond to a Command key in the package pane in the PackageBrowser" aChar == $f ifTrue: [^ self findClass]. ^ self classListKey: aChar from: view ! ! !StringHolder methodsFor: 'message list menu' stamp: 'tk 4/28/1998 18:16'! printOutMessage "Write a file with the text of the selected message, for printing by a web browser" self selectedMessageName ifNotNil: [ self selectedClassOrMetaClass fileOutMethod: self selectedMessageName asHtml: true]! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 5/23/2003 14:42'! removeFromCurrentChanges "Tell the changes mgr to forget that the current msg was changed." ChangeSet current removeSelectorChanges: self selectedMessageName class: self selectedClassOrMetaClass. self changed: #annotation! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 1/28/1999 12:34'! revertAndForget "Revert to the previous version of the current method, and tell the changes mgr to forget that it was ever changed. Danger!! Use only if you really know what you're doing!!" self okToChange ifFalse: [^ self]. self revertToPreviousVersion. self removeFromCurrentChanges. self contentsChanged ! ! !StringHolder methodsFor: 'message list menu' stamp: 'nb 6/17/2003 12:25'! revertToPreviousVersion "Revert to the previous version of the current method" | aClass aSelector changeRecords | self okToChange ifFalse: [^ self]. aClass _ self selectedClassOrMetaClass. aClass ifNil: [^ self changed: #flash]. aSelector _ self selectedMessageName. changeRecords _ aClass changeRecordsAt: aSelector. (changeRecords == nil or: [changeRecords size <= 1]) ifTrue: [self changed: #flash. ^ Beeper beep]. changeRecords second fileIn. self contentsChanged ! ! !StringHolder methodsFor: 'message list menu' stamp: 'sd 4/15/2003 16:11'! selectMessageAndEvaluate: aBlock "Allow the user to choose one selector, chosen from the currently selected message's selector, as well as those of all messages sent by it, and evaluate aBlock on behalf of chosen selector. If there is only one possible choice, simply make it; if there are multiple choices, put up a menu, and evaluate aBlock on behalf of the the chosen selector, doing nothing if the user declines to choose any" | selector method messages | (selector _ self selectedMessageName) ifNil: [^ self]. method _ (self selectedClassOrMetaClass ifNil: [^ self]) compiledMethodAt: selector ifAbsent: []. (method isNil or: [(messages _ method messages) size == 0]) ifTrue: [^ aBlock value: selector]. (messages size == 1 and: [messages includes: selector]) ifTrue: [^ aBlock value: selector]. "If only one item, there is no choice" self systemNavigation showMenuOf: messages withFirstItem: selector ifChosenDo: [:sel | aBlock value: sel]! ! !StringHolder methodsFor: 'message list menu' stamp: 'nk 11/15/2002 12:23'! systemCatListKey: aChar from: view "Respond to a Command key. I am a model with a code pane, and I also have a listView that has a list of methods. The view knows how to get the list and selection." aChar == $f ifTrue: [^ self findClass]. aChar == $x ifTrue: [^ self removeSystemCategory]. ^ self classListKey: aChar from: view! ! !StringHolder methodsFor: 'message list menu' stamp: 'sw 12/6/2000 21:01'! timeStamp "Answer the time stamp for the chosen class and method, if any, else an empty string" | selector aMethod | (selector _ self selectedMessageName) ifNotNil: [self selectedClassOrMetaClass ifNil: [^ String new] ifNotNil: [aMethod _ self selectedClassOrMetaClass compiledMethodAt: selector ifAbsent: [nil]. aMethod ifNotNil: [^ Utilities timeStampForMethod: aMethod]]]. ^ String new! ! !StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 21:25'! wantsAnnotationPane "Answer whether the receiver, seen in some browser window, would like to have the so-called annotationpane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary." ^ Preferences annotationPanes! ! !StringHolder methodsFor: 'optional panes' stamp: 'sw 1/24/2001 18:57'! wantsOptionalButtons "Answer whether the receiver, seen in some browser window, would like to have the so-called optional button pane included. By default, various browsers defer to the global preference 'optionalButtons' -- but individual subclasses can insist to the contrary." ^ Preferences optionalButtons! ! !StringHolder methodsFor: 'user edits' stamp: 'di 4/21/1998 11:30'! clearUserEditFlag "Clear the hasUnacceptedEdits flag in all my dependent views." self changed: #clearUserEdits! ! !StringHolder methodsFor: 'user edits' stamp: 'tk 4/13/1998 23:07'! okToChange self canDiscardEdits ifTrue: [^ true]. self changed: #wantToChange. "Solicit cancel from view" ^ self canDiscardEdits ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StringHolder class instanceVariableNames: ''! !StringHolder class methodsFor: 'class initialization'! initialize "The class variables were initialized once, and subsequently filled with information. Re-executing this method is therefore dangerous." "workSpace _ StringHolder new" "StringHolder initialize"! ! !StringHolder class methodsFor: 'instance creation' stamp: 'tk 5/4/1998 17:32'! open (Smalltalk at: #Workspace) new openLabel: 'Workspace' "Not to be confused with our own class var 'Workspace'"! ! !StringHolder class methodsFor: 'instance creation' stamp: 'tk 5/4/1998 16:41'! openLabel: aString self new openLabel: aString! ! ParagraphEditor subclass: #StringHolderController instanceVariableNames: '' classVariableNames: 'CodeYellowButtonMenu CodeYellowButtonMessages' poolDictionaries: '' category: 'ST80-Support'! !StringHolderController commentStamp: '<historical>' prior: 0! 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. doIt evaluate the text selection as an expression printIt same as doIt but insert a description of the result after the selection accept store the contents of the StringHolder into the model cancel store the contents of the model into the StringHolder! !StringHolderController methodsFor: 'accessing' stamp: 'di 6/21/2001 10:32'! changeText: aText "The paragraph to be edited is changed to aText." paragraph text: aText. self resetState. self selectInvisiblyFrom: paragraph text size + 1 to: paragraph text size. self selectAndScroll. self deselect! ! !StringHolderController methodsFor: 'accessing'! model: aModel super model: aModel. view displayContents == nil ifFalse: [self changeParagraph: view displayContents]! ! !StringHolderController methodsFor: 'edit flag' stamp: 'di 10/9/1998 15:41'! hasUnacceptedEdits: aBoolean ^ view hasUnacceptedEdits: aBoolean! ! !StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:09'! userHasEdited "Note that the user has edited my text." view hasUnacceptedEdits: true ! ! !StringHolderController methodsFor: 'edit flag' stamp: 'tk 4/13/1998 23:08'! userHasNotEdited "Note that my text is free of user edits." model clearUserEditFlag ! ! !StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:53'! accept "Refer to the comment in ParagraphEditor|accept." super accept. model contents: paragraph string. self userHasNotEdited. ! ! !StringHolderController methodsFor: 'menu messages' stamp: 'jm 3/18/98 20:54'! cancel "Refer to the comment in ParagraphEditor|cancel." super cancel. self userHasNotEdited. ! ! !StringHolderController methodsFor: 'menu messages' stamp: 'tk 4/13/1998 23:14'! performMenuMessage: aSelector "Intercept #again so the model does not get locked by keying the search text." | hadEdits | hadEdits _ view canDiscardEdits not. super performMenuMessage: aSelector. (hadEdits not and: [aSelector == #again and: [(UndoMessage sends: #undoAgain:andReselect:typedKey:) and: [UndoMessage arguments at: 3]]]) ifTrue: [self userHasNotEdited]. ! ! !StringHolderController methodsFor: 'compiler access'! bindingOf: aString ^model bindingOf: aString! ! !StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:43'! closeTypeIn "Note edit if something actually was typed." beginTypeInBlock ~~ nil ifTrue: [self userHasEdited]. super closeTypeIn. ! ! !StringHolderController methodsFor: 'private' stamp: 'jm 3/18/98 20:45'! zapSelectionWith: aText "Note edit except during typeIn, which notes edits at close." super zapSelectionWith: aText. beginTypeInBlock == nil ifTrue: [self userHasEdited]. ! ! View subclass: #StringHolderView instanceVariableNames: 'displayContents hasUnacceptedEdits askBeforeDiscardingEdits' classVariableNames: '' poolDictionaries: '' category: 'ST80-Support'! !StringHolderView commentStamp: '<historical>' prior: 0! 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.! !StringHolderView methodsFor: 'initialize-release' stamp: 'jm 3/24/98 14:39'! initialize "Refer to the comment in View|initialize." super initialize. displayContents _ '' asParagraph. hasUnacceptedEdits _ false. askBeforeDiscardingEdits _ true. ! ! !StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 14:38'! askBeforeDiscardingEdits: aBoolean "Set the flag that determines whether the user should be asked before discarding unaccepted edits." askBeforeDiscardingEdits _ aBoolean. ! ! !StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 22:58'! canDiscardEdits "Return true if this view either has no text changes or does not care." ^ (hasUnacceptedEdits & askBeforeDiscardingEdits) not ! ! !StringHolderView methodsFor: 'updating' stamp: 'jm 3/24/98 17:49'! hasUnacceptedEdits "Return true if this view has unaccepted edits." ^ hasUnacceptedEdits ! ! !StringHolderView methodsFor: 'updating' stamp: 'tk 4/13/1998 17:17'! hasUnacceptedEdits: aBoolean "Set the hasUnacceptedEdits flag to the given value." hasUnacceptedEdits _ aBoolean. ! ! !StringHolderView methodsFor: 'updating' stamp: 'dgd 9/21/2003 17:42'! promptForCancel "Ask if it is OK to cancel changes to text" | okToCancel stripes | self topView isCollapsed ifTrue: [(self confirm: 'Changes have not been saved. Is it OK to cancel those changes?' translated) ifTrue: [model clearUserEditFlag]. ^ self]. stripes _ (Form extent: 16@16 fromStipple: 16r36C9) bits. Display border: self insetDisplayBox width: 4 rule: Form reverse fillColor: stripes. okToCancel _ self confirm: 'Changes have not been saved. Is it OK to cancel those changes?' translated. Display border: self insetDisplayBox width: 4 rule: Form reverse fillColor: stripes. okToCancel ifTrue: [self updateDisplayContents. model clearUserEditFlag]. ! ! !StringHolderView methodsFor: 'updating' stamp: 'di 4/21/1998 11:30'! update: aSymbol "Refer to the comment in View|update:." aSymbol == #wantToChange ifTrue: [^ self promptForCancel]. aSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false]. aSymbol == #flash ifTrue: [^ controller flash]. self updateDisplayContents! ! !StringHolderView methodsFor: 'updating'! updateDisplayContents "Make the text that is displayed be the contents of the receiver's model." self editString: model contents. self displayView! ! !StringHolderView methodsFor: 'controller access'! defaultController "Refer to the comment in View|defaultController." ^self defaultControllerClass newParagraph: displayContents! ! !StringHolderView methodsFor: 'controller access'! defaultControllerClass "Refer to the comment in View|defaultControllerClass." ^StringHolderController! ! !StringHolderView methodsFor: 'controller access'! displayContents ^displayContents! ! !StringHolderView methodsFor: 'displaying'! display "Refer to the comment in View.display." (self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle]) ifTrue: "Recompose the text if the window changed" [self positionDisplayContents. (self controller isKindOf: ParagraphEditor) ifTrue: [controller recomputeSelection]]. super display! ! !StringHolderView methodsFor: 'displaying' stamp: 'hmm 6/18/2000 19:24'! displayView "Refer to the comment in View|displayView." Display deferUpdatesIn: self displayBox while: [ self clearInside. (self controller isKindOf: ParagraphEditor) ifTrue: [controller display] ifFalse: [displayContents display]]! ! !StringHolderView methodsFor: 'displaying'! lock "Refer to the comment in view|lock. Must do at least what display would do to lock the view." (self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle]) ifTrue: "Recompose the text if the window changed" [self positionDisplayContents. (self controller isKindOf: ParagraphEditor) ifTrue: [controller recomputeSelection]]. super lock! ! !StringHolderView methodsFor: 'displaying'! positionDisplayContents "Presumably the text being displayed changed so that the wrapping box and clipping box should be reset." displayContents wrappingBox: (self insetDisplayBox insetBy: 6 @ 0) clippingBox: self insetDisplayBox! ! !StringHolderView methodsFor: 'model access'! editString: aString "The paragraph to be displayed is created from the characters in aString." displayContents _ Paragraph withText: aString asText style: TextStyle default copy compositionRectangle: (self insetDisplayBox insetBy: 6 @ 0) clippingRectangle: self insetDisplayBox foreColor: self foregroundColor backColor: self backgroundColor. (self controller isKindOf: ParagraphEditor) ifTrue: [controller changeParagraph: displayContents]! ! !StringHolderView methodsFor: 'model access' stamp: 'sma 5/28/2000 23:25'! getMenu: shiftKeyState ^ nil! ! !StringHolderView methodsFor: 'model access'! model: aLockedModel "Refer to the comment in View|model:." super model: aLockedModel. self editString: model contents! ! !StringHolderView methodsFor: 'deEmphasizing'! deEmphasizeView "Refer to the comment in View|deEmphasizeView." (self controller isKindOf: ParagraphEditor) ifTrue: [controller deselect]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! StringHolderView class instanceVariableNames: ''! !StringHolderView class methodsFor: 'instance creation'! container "Answer an instance of me with a new instance of StringHolder as the model." ^self container: StringHolder new! ! !StringHolderView class methodsFor: 'instance creation'! container: aContainer "Answer an instance of me whose model is aContainer. Give it a 2-dot border." | aCodeView | aCodeView _ self new model: aContainer. aCodeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2. ^aCodeView! ! !StringHolderView class methodsFor: 'instance creation'! open "Create a standard system view of a workspace on the screen." self open: Workspace new label: 'Workspace'! ! !StringHolderView class methodsFor: 'instance creation'! open: aStringHolder "Create a standard system view of the argument, aStringHolder, as viewed by an instance of me. The view has label 'StringHolder'." self open: aStringHolder label: 'StringHolder'! ! !StringHolderView class methodsFor: 'instance creation' stamp: 'BG 10/28/2003 20:43'! open: aStringHolder label: labelString "NOTE this should be in the model class, and all senders so redirected, in order that the view class can be discarded in a morphic world." "Create a standard system view of the model, aStringHolder, as viewed by an instance of me. The label of the view is aString." | aStringHolderView topView | aStringHolderView _ self container: aStringHolder. topView _ StandardSystemView new. topView model: aStringHolderView model. topView addSubView: aStringHolderView. topView label: labelString. topView minimumSize: 100 @ 50. topView controller open! ! Model subclass: #Switch instanceVariableNames: 'on onAction offAction' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'! !Switch commentStamp: '<historical>' prior: 0! 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. 1/24/96 sw: made this a subclass of Model, for faster dependents handling! !Switch methodsFor: 'state'! clear "Set the state of the receiver to 'off'. If the state of the receiver was previously 'on', then 'self change' is sent. The receiver's off action is NOT executed." self isOn ifTrue: [on _ false. self changed]! ! !Switch methodsFor: 'state'! isOff "Answer whether the receiver is set off or not." ^on not! ! !Switch methodsFor: 'state'! isOn "Answer whether the receiver is set on or not." ^on! ! !Switch methodsFor: 'state'! set "Set the state of the receiver to 'on'. If the state of the receiver was previously 'off', then 'self change' is sent. The receiver's on action is NOT executed." self isOff ifTrue: [on _ true. self changed]! ! !Switch methodsFor: 'state'! switch "Change the state of the receiver from 'on' to 'off' or from 'off' to 'on' (see Switch|turnOn, Switch|turnOff)." self isOn ifTrue: [self turnOff] ifFalse: [self turnOn]! ! !Switch methodsFor: 'state'! turnOff "Set the state of the receiver to 'off'. If the state of the receiver was previously 'on', then 'self change' is sent and the receiver's off action is executed." self isOn ifTrue: [on _ false. self changed. self doAction: offAction]! ! !Switch methodsFor: 'state'! turnOn "Set the state of the receiver to 'on'. If the state of the receiver was previously 'off', then 'self change' is sent and the receiver's on action is executed." self isOff ifTrue: [on _ true. self changed. self doAction: onAction]! ! !Switch methodsFor: 'action'! doAction: anAction "Execute anAction if it is non-nil." anAction == nil ifFalse: [anAction value]! ! !Switch methodsFor: 'action'! offAction: anAction "Set the off action of the receiver to anAction." offAction _ anAction fixTemps! ! !Switch methodsFor: 'action'! onAction: anAction "Set the on action of the receiver to anAction." onAction _ anAction fixTemps! ! !Switch methodsFor: 'private'! initializeOff on _ false. onAction _ nil. offAction _ nil! ! !Switch methodsFor: 'private'! initializeOn on _ true. onAction _ nil. offAction _ nil! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Switch class instanceVariableNames: ''! !Switch class methodsFor: 'instance creation'! new "Answer an instance of me such that the on and off actions are set to nil ('no action'), and the state is set to 'off'." ^self newOff! ! !Switch class methodsFor: 'instance creation'! newOff "Answer an instance of me such that the on and off actions are set to nil ('no action'), and the state is set to 'off'." ^super new initializeOff! ! !Switch class methodsFor: 'instance creation'! newOn "Answer an instance of me such that the on and off actions are set to nil ('no action'), and the state is set to 'on'." ^super new initializeOn! ! String variableByteSubclass: #Symbol instanceVariableNames: '' classVariableNames: 'NewSymbols OneCharacterSymbols SymbolTable' poolDictionaries: '' category: 'Collections-Text'! !Symbol commentStamp: '<historical>' prior: 0! I represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol.! !Symbol methodsFor: 'accessing'! at: anInteger put: anObject "You cannot modify the receiver." self errorNoModification! ! !Symbol methodsFor: 'accessing' stamp: 'sma 2/5/2000 12:32'! precedence "Answer the receiver's precedence, assuming it is a valid Smalltalk message selector or 0 otherwise. The numbers are 1 for unary, 2 for binary and 3 for keyword selectors." self size = 0 ifTrue: [^ 0]. self first isLetter ifFalse: [^ 2]. self last = $: ifTrue: [^ 3]. ^ 1! ! !Symbol methodsFor: 'accessing'! replaceFrom: start to: stop with: replacement startingAt: repStart self errorNoModification! ! !Symbol methodsFor: 'comparing' stamp: 'di 4/11/2000 16:18'! = another "Use == between two symbols..." self == another ifTrue: [^ true]. "Was == " another class == Symbol ifTrue: [^ false]. "Was not == " "Otherwise use string =..." ^ super = another! ! !Symbol methodsFor: 'comparing' stamp: 'pm 9/23/97 09:36'! hashMappedBy: map "Answer what my hash would be if oops changed according to map." ^map newHashFor: self! ! !Symbol methodsFor: 'copying' stamp: 'tk 6/26/1998 11:35'! clone "Answer with the receiver, because Symbols are unique."! ! !Symbol methodsFor: 'copying'! copy "Answer with the receiver, because Symbols are unique."! ! !Symbol methodsFor: 'copying'! shallowCopy "Answer with the receiver, because Symbols are unique."! ! !Symbol methodsFor: 'copying' stamp: 'tk 8/19/1998 16:05'! veryDeepCopyWith: deepCopier "Return self. I am immutable in the Morphic world. Do not record me."! ! !Symbol methodsFor: 'converting'! asString "Refer to the comment in String|asString." | newString | newString _ String new: self size. 1 to: self size do: [:index | newString at: index put: (self at: index)]. ^newString! ! !Symbol methodsFor: 'converting'! asSymbol "Refer to the comment in String|asSymbol."! ! !Symbol methodsFor: 'converting' stamp: 'sw 1/28/98 18:18'! capitalized ^ self asString capitalized asSymbol! ! !Symbol methodsFor: 'printing' stamp: 'sw 8/19/1999 11:30'! isOrientedFill "Needs to be implemented here because symbols can occupy 'color' slots of morphs." ^ false! ! !Symbol methodsFor: 'printing' stamp: 'di 4/25/2000 12:32'! storeOn: aStream aStream nextPut: $#. (Scanner isLiteralSymbol: self) ifTrue: [aStream nextPutAll: self] ifFalse: [super storeOn: aStream]! ! !Symbol methodsFor: 'system primitives' stamp: 'di 1/2/1999 17:00'! flushCache "Tell the interpreter to remove all entries with this symbol as a selector from its method lookup cache, if it has one. This primitive must be called whenever a method is defined or removed. NOTE: Only one of the two selective flush methods needs to be used. Squeak 2.3 and later uses 116 (See CompiledMethod flushCache)." <primitive: 119> ! ! !Symbol methodsFor: 'private'! errorNoModification self error: 'symbols can not be modified.'! ! !Symbol methodsFor: 'private'! species ^String! ! !Symbol methodsFor: 'private'! string: aString 1 to: aString size do: [:j | super at: j put: (aString at: j)]. ^self ! ! !Symbol methodsFor: 'private'! stringhash ^super hash! ! !Symbol methodsFor: 'filter streaming' stamp: 'mpw 1/1/1901 00:20'! byteEncode:aStream ^aStream writeSymbol:self. ! ! !Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:32'! isInfix "Answer whether the receiver is an infix message selector." ^ self precedence == 2! ! !Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'! isKeyword "Answer whether the receiver is a message keyword." ^ self precedence == 3! ! !Symbol methodsFor: 'testing' stamp: 'di 4/25/2000 12:32'! isLiteral "Answer whether the receiver is a valid Smalltalk literal." ^ true! ! !Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:13'! isPvtSelector "Answer whether the receiver is a private message selector, that is, begins with 'pvt' followed by an uppercase letter, e.g. pvtStringhash." ^ (self beginsWith: 'pvt') and: [self size >= 4 and: [(self at: 4) isUppercase]]! ! !Symbol methodsFor: 'testing' stamp: 'md 4/30/2003 15:31'! isSymbol ^ true ! ! !Symbol methodsFor: 'testing' stamp: 'sma 2/5/2000 12:34'! isUnary "Answer whether the receiver is an unary message selector." ^ self precedence == 1! ! !Symbol methodsFor: 'user interface' stamp: 'sma 11/12/2000 11:46'! asExplorerString ^ self printString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Symbol class instanceVariableNames: ''! !Symbol class methodsFor: 'access' stamp: 'RAA 5/29/2001 14:34'! selectorsContaining: aString "Answer a list of selectors that contain aString within them. Case-insensitive. Does return symbols that begin with a capital letter." | size selectorList ascii | selectorList _ OrderedCollection new. (size _ aString size) = 0 ifTrue: [^selectorList]. aString size = 1 ifTrue: [ ascii _ aString first asciiValue. ascii < 128 ifTrue: [selectorList add: (OneCharacterSymbols at: ascii+1)] ]. aString first isLetter ifFalse: [ aString size == 2 ifTrue: [Symbol hasInterned: aString ifTrue: [:s | selectorList add: s]]. ^selectorList ]. selectorList _ selectorList copyFrom: 2 to: selectorList size. self allSymbolTablesDo: [:each | each size >= size ifTrue: [(each findSubstring: aString in: each startingAt: 1 matchTable: CaseInsensitiveOrder) > 0 ifTrue: [selectorList add: each]]]. ^selectorList reject: [:each | "reject non-selectors, but keep ones that begin with an uppercase" each numArgs < 0 and: [each asString withFirstCharacterDownshifted numArgs < 0]]. "Symbol selectorsContaining: 'scon'"! ! !Symbol class methodsFor: 'access' stamp: 'RAA 5/29/2001 14:35'! thatStarts: leadingCharacters skipping: skipSym "Answer a selector symbol that starts with leadingCharacters. Symbols beginning with a lower-case letter handled directly here. Ignore case after first char. If skipSym is not nil, it is a previous answer; start searching after it. If no symbols are found, answer nil. Used by Alt-q (Command-q) routines" | size firstMatch key | size _ leadingCharacters size. size = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]]. firstMatch _ leadingCharacters at: 1. size > 1 ifTrue: [key _ leadingCharacters copyFrom: 2 to: size]. self allSymbolTablesDo: [:each | each size >= size ifTrue: [ ((each at: 1) == firstMatch and: [key == nil or: [(each findString: key startingAt: 2 caseSensitive: false) = 2]]) ifTrue: [^each] ] ] after: skipSym. ^nil "Symbol thatStarts: 'sf' skipping: nil" "Symbol thatStarts: 'sf' skipping: #sfpGetFile:with:with:with:with:with:with:with:with:" "Symbol thatStarts: 'candidate' skipping: nil" ! ! !Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 08:21'! allSymbolTablesDo: aBlock NewSymbols do: aBlock. SymbolTable do: aBlock.! ! !Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 14:35'! allSymbolTablesDo: aBlock after: aSymbol NewSymbols do: aBlock after: aSymbol. SymbolTable do: aBlock after: aSymbol.! ! !Symbol class methodsFor: 'class initialization' stamp: 'RAA 12/17/2000 18:05'! compactSymbolTable "Reduce the size of the symbol table so that it holds all existing symbols + 25% (changed from 1000 since sets like to have 25% free and the extra space would grow back in a hurry)" | oldSize | Smalltalk garbageCollect. oldSize _ SymbolTable array size. SymbolTable growTo: SymbolTable size * 4 // 3 + 100. ^oldSize printString,' ',(oldSize - SymbolTable array size) printString, ' slot(s) reclaimed'! ! !Symbol class methodsFor: 'class initialization' stamp: 'RAA 5/29/2001 09:04'! initialize "Symbol initialize" Symbol rehash. OneCharacterSymbols _ nil. OneCharacterSymbols _ (1 to: 256) collect: [ :i | (i - 1) asCharacter asSymbol]. Smalltalk addToShutDownList: self. ! ! !Symbol class methodsFor: 'instance creation' stamp: 'RAA 5/29/2001 08:10'! intern: aStringOrSymbol ^(self lookup: aStringOrSymbol) ifNil: [ NewSymbols add: ((aStringOrSymbol isKindOf: Symbol) ifTrue: [aStringOrSymbol] ifFalse: [(self new: aStringOrSymbol size) string: aStringOrSymbol]) ]! ! !Symbol class methodsFor: 'instance creation' stamp: 'raa 5/26/2001 09:54'! internCharacter: aCharacter OneCharacterSymbols ifNil: [^self intern: aCharacter asString]. ^OneCharacterSymbols at: aCharacter asciiValue + 1 ! ! !Symbol class methodsFor: 'instance creation' stamp: 'RAA 5/29/2001 08:09'! lookup: aStringOrSymbol ^(SymbolTable like: aStringOrSymbol) ifNil: [ NewSymbols like: aStringOrSymbol ]! ! !Symbol class methodsFor: 'instance creation'! newFrom: aCollection "Answer an instance of me containing the same elements as aCollection." ^ (aCollection as: String) asSymbol " Symbol newFrom: {$P. $e. $n} {$P. $e. $n} as: Symbol "! ! !Symbol class methodsFor: 'instance creation' stamp: 'di 10/11/1999 00:02'! readFrom: strm "Symbol readFromString: '#abc'" strm peek = $# ifFalse: [self error: 'Symbols must be introduced by #']. ^ (Scanner new scan: strm) advance "Just do what the code scanner does"! ! !Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 08:23'! hasInterned: aString ifTrue: symBlock "Answer with false if aString hasnt been interned (into a Symbol), otherwise supply the symbol to symBlock and return true." | symbol | ^(symbol _ self lookup: aString) ifNil: [false] ifNotNil: [symBlock value: symbol. true] ! ! !Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 14:33'! possibleSelectorsFor: misspelled "Answer an ordered collection of possible corrections for the misspelled selector in order of likelyhood" | numArgs candidates lookupString best binary short long first ss | lookupString _ misspelled asLowercase. "correct uppercase selectors to lowercase" numArgs _ lookupString numArgs. (numArgs < 0 or: [lookupString size < 2]) ifTrue: [^ OrderedCollection new: 0]. first _ lookupString first. short _ lookupString size - (lookupString size // 4 max: 3) max: 2. long _ lookupString size + (lookupString size // 4 max: 3). "First assemble candidates for detailed scoring" candidates _ OrderedCollection new. self allSymbolTablesDo: [:s | (((ss _ s size) >= short "not too short" and: [ss <= long "not too long" or: [(s at: 1) = first]]) "well, any length OK if starts w/same letter" and: [s numArgs = numArgs]) "and numArgs is the same" ifTrue: [candidates add: s]]. "Then further prune these by correctAgainst:" best _ lookupString correctAgainst: candidates. ((misspelled last ~~ $:) and: [misspelled size > 1]) ifTrue: [ binary _ misspelled, ':'. "try for missing colon" Symbol hasInterned: binary ifTrue: [:him | best addFirst: him]]. ^ best! ! !Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 08:01'! rehash "Symbol rehash" "Rebuild the hash table, reclaiming unreferenced Symbols." SymbolTable _ WeakSet withAll: self allInstances. NewSymbols _ WeakSet new.! ! !Symbol class methodsFor: 'private' stamp: 'RAA 5/29/2001 09:04'! shutDown: aboutToQuit SymbolTable addAll: NewSymbols. NewSymbols _ WeakSet new.! ! StringHolder subclass: #SyntaxError instanceVariableNames: 'class selector category debugger doitFlag' classVariableNames: '' poolDictionaries: '' category: 'Tools-Debugger'! !SyntaxError commentStamp: '<historical>' prior: 0! I represent syntax error report for syntax errors encountered when filing in class descriptions from a non-interactive source such as an external file. As a StringHolder, the string to be viewed is the method code or expression containing the error. The user may fix the error and accept the method to continue the fileIn. ! !SyntaxError methodsFor: 'initialization' stamp: 'jm 5/3/1998 14:36'! category: aSymbol "Record the message category of method being compiled. This is used when the user corrects the error and accepts." category _ aSymbol. ! ! !SyntaxError methodsFor: 'initialization' stamp: 'tk 5/6/1999 13:28'! setClass: aClass code: aString debugger: aDebugger doitFlag: flag | types printables badChar | class _ aClass. debugger _ aDebugger. selector _ aClass parserClass new parseSelector: aString. types _ Scanner classPool at: #TypeTable. "dictionary" printables _ '!!@#$%&*-_=+<>{}?/\,`~`' asSet. badChar _ aString detect: [:aChar | (types at: aChar asciiValue) == #xBinary and: [ (printables includes: aChar) not]] ifNone: [nil]. contents _ badChar ifNil: [aString] ifNotNil: ['<<<This string contains a character (ascii value ', badChar asciiValue printString, ') that is not normally used in code>>> ', aString]. category ifNil: [category _ aClass organization categoryOfElement: selector]. category ifNil: [category _ ClassOrganizer default]. doitFlag _ flag! ! !SyntaxError methodsFor: 'message list' stamp: 'tk 4/19/1999 08:08'! list "Answer an array of one element made up of the class name, message category, and message selector in which the syntax error was found. This is the single item in the message list of a view/browser on the receiver." selector ifNil: [^ Array with: (class name, ' ', category, ' ', '<none>')]. ^ Array with: (class name, ' ', category, ' ', selector) ! ! !SyntaxError methodsFor: 'message list' stamp: 'jm 5/3/1998 13:48'! listIndex "There is always exactly one element in my list and it is always selected." ^ 1 ! ! !SyntaxError methodsFor: 'menu' stamp: 'RAA 12/1/2000 14:24'! debug "Show the stack of the process leading to this syntax editor, typically showing the stack of the compiler as called from fileIn." debugger openFullNoSuspendLabel: 'Stack of the Syntax Error'. Smalltalk isMorphic ifFalse: [Processor terminateActive]. ! ! !SyntaxError methodsFor: 'menu' stamp: 'jm 5/3/1998 14:22'! listMenu: aMenu ^ aMenu labels: 'proceed debug calling process browse full' lines: #() selections: #(proceed debug browseMethodFull) ! ! !SyntaxError methodsFor: 'menu' stamp: 'di 5/5/1998 00:06'! proceed "The user has has edited and presumably fixed the syntax error and the filein can now proceed." debugger proceed: self topView. ! ! !SyntaxError methodsFor: 'other' stamp: 'di 10/9/1998 16:36'! contents: aString notifying: aController "Compile the code in aString and notify aController of any errors. If there are no errors, then automatically proceed." doitFlag ifTrue: [Compiler new evaluate: aString in: nil to: nil notifying: aController ifFail: [^ false]] ifFalse: [(class compile: aString classified: category notifying: aController) ifNil: [^ false]]. aController hasUnacceptedEdits: false. self proceed! ! !SyntaxError methodsFor: 'other' stamp: 'di 10/9/1998 16:51'! notify: error at: location in: source "Open a syntax error view, inserting the given error message into the given source at the given location. This message is sent to the 'requestor' when the parser or compiler finds a syntax error." | aClass aString | aClass _ thisContext sender receiver encoder classEncoding. aString _ source contents copyReplaceFrom: location to: location - 1 with: error. self setClass: aClass code: aString debugger: (Debugger context: thisContext) doitFlag: false. self class open: self. ! ! !SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:15'! selectedClass "Answer the class in which the syntax error occurred." ^ class ! ! !SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:33'! selectedClassOrMetaClass "Answer the class of the method being compiled." ^ class ! ! !SyntaxError methodsFor: 'text menu support' stamp: 'jm 5/3/1998 14:17'! selectedMessageName "Answer the selector of the method being compiled." ^ selector ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SyntaxError class instanceVariableNames: ''! !SyntaxError class methodsFor: 'instance creation' stamp: 'di 5/6/1998 20:58'! buildMVCViewOn: aSyntaxError "Answer an MVC view on the given SyntaxError." | topView aListView aCodeView | topView _ StandardSystemView new model: aSyntaxError; label: 'Syntax Error'; minimumSize: 380@220. aListView _ PluggableListView on: aSyntaxError list: #list selected: #listIndex changeSelected: nil menu: #listMenu:. aListView window: (0@0 extent: 380@20). topView addSubView: aListView. aCodeView _ PluggableTextView on: aSyntaxError text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. aCodeView window: (0@0 extent: 380@200). topView addSubView: aCodeView below: aListView. ^ topView ! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'BG 10/29/2003 08:05'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | <primitive: 19> "Simulation guard" topView _ self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor activeProcess suspend. ! ! Notification subclass: #SyntaxErrorNotification instanceVariableNames: 'inClass code doitFlag debugger' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Extensions'! !SyntaxErrorNotification methodsFor: 'accessing' stamp: 'LC 1/6/2002 13:50'! messageText ^ super messageText ifNil: [messageText _ self syntaxError contents]! ! !SyntaxErrorNotification methodsFor: 'accessing' stamp: 'LC 1/6/2002 13:44'! setClass: aClass code: codeString debugger: aDebugger doitFlag: aBoolean inClass _ aClass. code _ codeString. debugger _ aDebugger. doitFlag _ aBoolean ! ! !SyntaxErrorNotification methodsFor: 'accessing' stamp: 'LC 1/6/2002 13:45'! syntaxError ^ SyntaxError new setClass: inClass code: code debugger: debugger doitFlag: doitFlag! ! !SyntaxErrorNotification methodsFor: 'exceptionDescription' stamp: 'LC 1/6/2002 13:47'! defaultAction | s | s _ self syntaxError. ^ s class open: s ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SyntaxErrorNotification class instanceVariableNames: ''! !SyntaxErrorNotification class methodsFor: 'exceptionInstantiator' stamp: 'LC 1/6/2002 13:52'! inClass: aClass withCode: codeString doitFlag: doitFlag ^ (self new setClass: aClass code: codeString debugger: (Debugger context: thisContext) doitFlag: doitFlag) signal! ! Object subclass: #SystemChangeNotifier instanceVariableNames: 'eventSource silenceLevel' classVariableNames: 'UniqueInstance' poolDictionaries: '' category: 'System-Change Notification'! !SystemChangeNotifier methodsFor: 'initialize' stamp: 'NS 1/26/2004 20:41'! initialize eventSource := SystemEventManager new. silenceLevel _ 0.! ! !SystemChangeNotifier methodsFor: 'private' stamp: 'rw 7/10/2003 15:15'! notify: anObject ofEvents: eventsCollection using: oneArgumentSelector "Notifies an object of any events in the eventsCollection. Send it back a message #oneArgumentSelector, with as argument the particular system event instance." eventsCollection do: [:eachEvent | eventSource when: eachEvent send: oneArgumentSelector to: anObject]! ! !SystemChangeNotifier methodsFor: 'private' stamp: 'NS 1/26/2004 20:41'! trigger: event self isBroadcasting ifTrue: [event trigger: eventSource] " | caughtExceptions | caughtExceptions := OrderedCollection new. self isBroadcasting ifTrue: [ [(eventSource actionForEvent: event eventSelector) valueWithArguments: (Array with: event)] on: Exception do: [:exc | caughtExceptions add: exc]]. caughtExceptions do: [:exc | exc resignalAs: exc class new]"! ! !SystemChangeNotifier methodsFor: 'private-event lists' stamp: 'rw 7/29/2003 15:14'! allSystemEvents ^AbstractEvent systemEvents! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:12'! class: aClass recategorizedFrom: oldCategory to: newCategory self trigger: (RecategorizedEvent class: aClass category: newCategory oldCategory: oldCategory)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'rw 7/29/2003 15:11'! classAdded: aClass inCategory: aCategoryName self trigger: (AddedEvent class: aClass category: aCategoryName)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/26/2004 09:37'! classCommented: aClass "A class with the given name was commented in the system." self trigger: (CommentedEvent class: aClass)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/20/2004 19:37'! classDefinitionChangedFrom: oldClass to: newClass self trigger: (ModifiedClassDefinitionEvent classDefinitionChangedFrom: oldClass to: newClass)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/16/2004 15:10'! classRemoved: aClass fromCategory: aCategoryName self trigger: (RemovedEvent class: aClass category: aCategoryName)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:19'! classRenamed: aClass from: oldClassName to: newClassName inCategory: aCategoryName self trigger: (RenamedEvent class: aClass category: aCategoryName oldName: oldClassName newName: newClassName)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 12:48'! classReorganized: aClass self trigger: (ReorganizedEvent class: aClass)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/19/2004 09:47'! evaluated: expression context: aContext self trigger: (DoItEvent expression: expression context: aContext)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'! methodAdded: aMethod selector: aSymbol inClass: aClass requestor: requestor "A method with the given selector was added to aClass, but not put in a protocol." self trigger: (AddedEvent method: aMethod selector: aSymbol class: aClass requestor: requestor)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:24'! methodAdded: aMethod selector: aSymbol inProtocol: aCategoryName class: aClass requestor: requestor "A method with the given selector was added to aClass in protocol aCategoryName." self trigger: (AddedEvent method: aMethod selector: aSymbol protocol: aCategoryName class: aClass requestor: requestor)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/27/2004 11:41'! methodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor self trigger: (ModifiedEvent methodChangedFrom: oldMethod to: newMethod selector: aSymbol inClass: aClass requestor: requestor)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 1/28/2004 11:11'! methodRemoved: aMethod selector: aSymbol inProtocol: protocol class: aClass "A method with the given selector was removed from the class." self trigger: (RemovedEvent method: aMethod selector: aSymbol protocol: protocol class: aClass)! ! !SystemChangeNotifier methodsFor: 'system triggers' stamp: 'NS 4/7/2004 13:35'! selector: selector recategorizedFrom: oldCategory to: newCategory inClass: aClass self trigger: (RecategorizedEvent method: (aClass compiledMethodAt: selector ifAbsent: [nil]) protocol: newCategory class: aClass oldProtocol: oldCategory)! ! !SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/28/2004 11:29'! doSilently: aBlock "Perform the block, and ensure that no system notification are broadcasted while doing so." | result | silenceLevel := silenceLevel + 1. [result := aBlock value] ensure: [silenceLevel > 0 ifTrue: [silenceLevel := silenceLevel - 1]]. ^ result.! ! !SystemChangeNotifier methodsFor: 'public' stamp: 'NS 1/26/2004 20:41'! isBroadcasting ^ silenceLevel = 0! ! !SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/29/2003 17:01'! noMoreNotificationsFor: anObject "Stop sending system notifications to an object." eventSource removeActionsWithReceiver: anObject! ! !SystemChangeNotifier methodsFor: 'public' stamp: 'rw 7/10/2003 12:00'! notify: anObject ofAllSystemChangesUsing: oneArgumentSelector "Notifies an object of any system changes." self notify: anObject ofEvents: self allSystemEvents using: oneArgumentSelector! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SystemChangeNotifier class instanceVariableNames: ''! !SystemChangeNotifier class methodsFor: 'instance creation' stamp: 'rw 6/28/2003 09:41'! new ^self error: self instanceCreationErrorString! ! !SystemChangeNotifier class methodsFor: 'private' stamp: 'NS 1/27/2004 16:23'! createInstance ^self basicNew initialize! ! !SystemChangeNotifier class methodsFor: 'private' stamp: 'rw 6/28/2003 09:41'! instanceCreationErrorString ^'This is a singleton implementation, so you are not allowed to create instances yourself. Use #uniqueInstance to access the instance.'! ! !SystemChangeNotifier class methodsFor: 'public' stamp: 'NS 1/27/2004 16:23'! uniqueInstance UniqueInstance ifNil: [UniqueInstance := self createInstance]. ^UniqueInstance! ! !SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'! categoryKind ^ AbstractEvent categoryKind! ! !SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'! classKind ^ AbstractEvent classKind! ! !SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'! expressionKind ^ AbstractEvent expressionKind! ! !SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:31'! methodKind ^ AbstractEvent methodKind! ! !SystemChangeNotifier class methodsFor: 'item kinds' stamp: 'NS 1/21/2004 09:32'! protocolKind ^ AbstractEvent protocolKind! ! IdentityDictionary subclass: #SystemDictionary instanceVariableNames: 'cachedClassNames' classVariableNames: 'LastImageName LastQuitLogPosition LowSpaceProcess LowSpaceSemaphore MemoryHogs ShutDownList SpecialSelectors StartUpList StartupStamp VersionString' poolDictionaries: '' category: 'System-Support'! !SystemDictionary commentStamp: '<historical>' prior: 0! I represent a special dictionary that supports protocol for asking questions about the structure of the system. Other than class names, I contain (print this)... Smalltalk keys select: [:k | ((Smalltalk at: k) isKindOf: Class) not] thenCollect: [:k | k -> (Smalltalk at: k) class] ! !SystemDictionary methodsFor: 'accessing' stamp: 'ar 7/11/1999 21:56'! organization "Return the organizer for the receiver" ^SystemOrganization! ! !SystemDictionary methodsFor: 'class names' stamp: 'di 3/26/2000 09:06'! classNamed: className "className is either a class name or a class name followed by ' class'. Answer the class or metaclass it names" | meta baseName baseClass | (className endsWith: ' class') ifTrue: [meta _ true. baseName _ className copyFrom: 1 to: className size - 6] ifFalse: [meta _ false. baseName _ className]. baseClass _ Smalltalk at: baseName asSymbol ifAbsent: [^ nil]. meta ifTrue: [^ baseClass class] ifFalse: [^ baseClass]! ! !SystemDictionary methodsFor: 'class names' stamp: 'di 11/16/1999 12:44'! classNames "Answer a SortedCollection of all class names." | names | cachedClassNames == nil ifTrue: [names _ OrderedCollection new: self size. self do: [:cl | (cl isInMemory and: [(cl isKindOf: Class) and: [(cl name beginsWith: 'AnObsolete') not]]) ifTrue: [names add: cl name]]. cachedClassNames _ names asSortedCollection]. ^ cachedClassNames! ! !SystemDictionary methodsFor: 'class names' stamp: 'di 2/16/2000 10:28'! flushClassNameCache "Smalltalk flushClassNameCache" "Forse recomputation of the cached list of class names." cachedClassNames _ nil! ! !SystemDictionary methodsFor: 'class names' stamp: 'NS 1/27/2004 12:08'! forgetClass: aClass logged: aBool "Delete the class, aClass, from the system. Note that this doesn't do everything required to dispose of a class - to do that use Class>>removeFromSystem." aBool ifTrue: [SystemChangeNotifier uniqueInstance classRemoved: aClass fromCategory: aClass category]. SystemOrganization removeElement: aClass name. self removeFromStartUpList: aClass. self removeFromShutDownList: aClass. self removeKey: aClass name ifAbsent: []. self flushClassNameCache! ! !SystemDictionary methodsFor: 'class names' stamp: 'sw 9/5/97 18:30'! removeClassNamed: aName "Invoked from fileouts: if there is currently a class in the system named aName, then remove it. If anything untoward happens, report it in the Transcript. " | oldClass | (oldClass _ self at: aName asSymbol ifAbsent: [nil]) == nil ifTrue: [Transcript cr; show: 'Removal of class named ', aName, ' ignored because ', aName, ' does not exist.'. ^ self]. oldClass removeFromSystem! ! !SystemDictionary methodsFor: 'class names' stamp: 'rr 3/11/2004 15:18'! renameClass: aClass as: newName "Rename the class, aClass, to have the title newName." | oldref i oldName category | oldName := aClass name. category := aClass category. SystemOrganization classify: newName under: aClass category. SystemOrganization removeElement: aClass name. oldref _ self associationAt: aClass name. self removeKey: aClass name. oldref key: newName. self add: oldref. "Old association preserves old refs" (Array with: StartUpList with: ShutDownList) do: [:list | i _ list indexOf: aClass name ifAbsent: [0]. i > 0 ifTrue: [list at: i put: newName]]. self flushClassNameCache. SystemChangeNotifier uniqueInstance classRenamed: aClass from: oldName to: newName inCategory: category! ! !SystemDictionary methodsFor: 'class names' stamp: 'sw 10/28/96'! renameClassNamed: oldName as: newName "Invoked from fileouts: if there is currently a class in the system named oldName, then rename it to newName. If anything untoward happens, report it in the Transcript. " | oldClass | (oldClass _ self at: oldName asSymbol ifAbsent: [nil]) == nil ifTrue: [Transcript cr; show: 'Class-rename for ', oldName, ' ignored because ', oldName, ' does not exist.'. ^ self]. oldClass rename: newName! ! !SystemDictionary methodsFor: 'dictionary access'! at: aKey put: anObject "Override from Dictionary to check Undeclared and fix up references to undeclared variables." | index element | (self includesKey: aKey) ifFalse: [self declare: aKey from: Undeclared. self flushClassNameCache]. super at: aKey put: anObject. ^ anObject! ! !SystemDictionary methodsFor: 'dictionary access' stamp: 'di 12/21/1999 12:00'! atOrAbove: key ifAbsent: absentBlock "Compatibility with environment protocol." ^ self at: key ifAbsent: absentBlock! ! !SystemDictionary methodsFor: 'dictionary access' stamp: 'di 12/6/1999 13:43'! atOrBelow: key ifAbsent: absentBlock "Compatibility with environment protocol." ^ self at: key ifAbsent: absentBlock! ! !SystemDictionary methodsFor: 'dictionary access' stamp: 'di 12/6/1999 20:36'! environmentForCategory: catName "Default response for non-partitioned systems" ^ Smalltalk! ! !SystemDictionary methodsFor: 'dictionary access' stamp: 'di 12/21/1999 12:00'! includesKeyOrAbove: key "Compatibility with environment protocol." self atOrAbove: key ifAbsent: [^ false]. ^ true! ! !SystemDictionary methodsFor: 'dictionary access' stamp: 'di 12/19/1999 21:17'! scopeFor: varName from: lower envtAndPathIfFound: envtAndPathBlock "Null compatibility with partitioning into environments." (self includesKey: varName) ifTrue: [^ envtAndPathBlock value: self value: String new] ifFalse: [^ nil]! ! !SystemDictionary methodsFor: 'housekeeping' stamp: 'BG 4/23/2004 14:38'! condenseChanges "Move all the changes onto a compacted sources file." "Smalltalk condenseChanges" | f oldChanges classCount | f _ FileStream fileNamed: 'ST80.temp'. f header; timeStamp. 'Condensing Changes File...' displayProgressAt: Sensor cursorPoint from: 0 to: Smalltalk classNames size during: [:bar | classCount _ 0. Smalltalk allClassesDo: [:class | bar value: (classCount _ classCount + 1). class moveChangesTo: f. class putClassCommentToCondensedChangesFile: f. class class moveChangesTo: f]]. SmalltalkImage current lastQuitLogPosition: f position. f trailer; close. oldChanges _ SourceFiles at: 2. oldChanges close. FileDirectory default deleteFileNamed: oldChanges name , '.old'; rename: oldChanges name toBe: oldChanges name , '.old'; rename: f name toBe: oldChanges name. self setMacFileInfoOn: oldChanges name. SourceFiles at: 2 put: (StandardFileStream oldFileNamed: oldChanges name)! ! !SystemDictionary methodsFor: 'housekeeping' stamp: 'BG 2/17/2005 23:30'! condenseSources "Move all the changes onto a compacted sources file." "Smalltalk condenseSources" | f classCount dir newVersionString | Utilities fixUpProblemsWithAllCategory. "The above removes any concrete, spurious '-- all --' categories, which mess up the process." dir := FileDirectory default. newVersionString := FillInTheBlank request: 'Please designate the version for the new source code file...' initialAnswer: SmalltalkImage current sourceFileVersionString. newVersionString ifNil: [^ self]. newVersionString = SmalltalkImage current sourceFileVersionString ifTrue: [^ self error: 'The new source file must not be the same as the old.']. SmalltalkImage current sourceFileVersionString: newVersionString. "Write all sources with fileIndex 1" f := FileStream newFileNamed: SmalltalkImage current sourcesName. f header; timeStamp. 'Condensing Sources File...' displayProgressAt: Sensor cursorPoint from: 0 to: self classNames size during: [:bar | classCount := 0. self allClassesDo: [:class | bar value: (classCount := classCount + 1). class fileOutOn: f moveSource: true toFile: 1]]. f trailer; close. "Make a new empty changes file" SmalltalkImage current closeSourceFiles. dir rename: SmalltalkImage current changesName toBe: SmalltalkImage current changesName , '.old'. (FileStream newFileNamed: SmalltalkImage current changesName) header; timeStamp; close. SmalltalkImage current lastQuitLogPosition: 0. self setMacFileInfoOn: SmalltalkImage current changesName. self setMacFileInfoOn: SmalltalkImage current sourcesName. SmalltalkImage current openSourceFiles. self inform: 'Source files have been rewritten!! Check that all is well, and then save/quit.'! ! !SystemDictionary methodsFor: 'housekeeping' stamp: 'sd 4/17/2003 20:59'! forgetDoIts "Smalltalk forgetDoIts" "get rid of old DoIt methods" self systemNavigation allBehaviorsDo: [:cl | cl forgetDoIts] ! ! !SystemDictionary methodsFor: 'housekeeping' stamp: 'jm 5/22/1998 11:37'! obsoleteClasses "Smalltalk obsoleteClasses inspect" "NOTE: Also try inspecting comments below" | obs c | obs _ OrderedCollection new. Smalltalk garbageCollect. Metaclass allInstancesDo: [:m | c _ m soleInstance. (c ~~ nil and: ['AnOb*' match: c name asString]) ifTrue: [obs add: c]]. ^ obs asArray "Likely in a ClassDict or Pool... (Association allInstances select: [:a | (a value isKindOf: Class) and: ['AnOb*' match: a value name]]) asArray " "Obsolete class refs or super pointer in last lit of a method... | n l found | Smalltalk browseAllSelect: [:m | found _ false. 1 to: m numLiterals do: [:i | (((l _ m literalAt: i) isMemberOf: Association) and: [(l value isKindOf: Behavior) and: ['AnOb*' match: l value name]]) ifTrue: [found _ true]]. found] "! ! !SystemDictionary methodsFor: 'housekeeping' stamp: 'di 3/1/2001 01:09'! reclaimDependents "No-opped due to weak dictionary in use" Smalltalk garbageCollect! ! !SystemDictionary methodsFor: 'image, changes name' stamp: 'nk 11/12/2003 10:28'! imageName "Answer the full path name for the current image." "Smalltalk imageName" ^ self deprecated: 'Use SmalltalkImage current imageName' block: [SmalltalkImage current imageName]! ! !SystemDictionary methodsFor: 'image, changes name' stamp: 'nk 11/12/2003 10:29'! imageName: newName "Set the the full path name for the current image. All further snapshots will use this." ^ self deprecated: 'Use SmalltalkImage current imageName' block: [ SmalltalkImage current imageName ]! ! !SystemDictionary methodsFor: 'image, changes name' stamp: 'BG 12/5/2003 19:30'! sourcesName "Answer the full path to the version-stable source code" self deprecatedExplanation: 'Use SmalltalkImage current sourcesName'. " ^ SourceFileVersionString , FileDirectory dot , 'sources' "! ! !SystemDictionary methodsFor: 'image, changes name' stamp: 'nk 11/12/2003 10:35'! vmPath "Answer the path for the directory containing the Smalltalk virtual machine. Return the empty string if this primitive is not implemented." "Smalltalk vmPath" ^ self deprecated: 'Use SmalltalkImage current vmPath' block: [SmalltalkImage current vmPath]! ! !SystemDictionary methodsFor: 'memory space'! bytesLeft "Answer the number of bytes of space available. Does a full garbage collection." ^ self garbageCollect ! ! !SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 17:55'! bytesLeft: aBool "Return the amount of available space. If aBool is true, include possibly available swap space. If aBool is false, include possibly available physical memory. For a report on the largest free block currently availabe within Squeak memory but not counting extra memory use #primBytesLeft." <primitive: 112> ^self primBytesLeft! ! !SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/25/2001 18:00'! bytesLeftString "Return a string describing the amount of memory available" | availInternal availPhysical availTotal | self garbageCollect. availInternal _ self primBytesLeft. availPhysical _ self bytesLeft: false. availTotal _ self bytesLeft: true. (availTotal > (availInternal + 10000)) "compensate for mini allocations inbetween" ifFalse:[^availInternal asStringWithCommas, ' bytes available']. ^String streamContents:[:s| s nextPutAll: availInternal asStringWithCommas, ' bytes (internal) '; cr. s nextPutAll: availPhysical asStringWithCommas, ' bytes (physical) '; cr. s nextPutAll: availTotal asStringWithCommas, ' bytes (total) '].! ! !SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:36'! garbageCollect "Primitive. Reclaims all garbage and answers the number of bytes of available space." Object flushDependents. Object flushEvents. ^self primitiveGarbageCollect! ! !SystemDictionary methodsFor: 'memory space'! garbageCollectMost "Primitive. Reclaims recently created garbage (which is usually most of it) fairly quickly and answers the number of bytes of available space." <primitive: 131> ^ self primBytesLeft! ! !SystemDictionary methodsFor: 'memory space'! installLowSpaceWatcher "Start a process to watch for low-space conditions." "Smalltalk installLowSpaceWatcher" self primSignalAtBytesLeft: 0. "disable low-space interrupts" LowSpaceProcess == nil ifFalse: [LowSpaceProcess terminate]. LowSpaceProcess _ [self lowSpaceWatcher] newProcess. LowSpaceProcess priority: Processor lowIOPriority. LowSpaceProcess resume. ! ! !SystemDictionary methodsFor: 'memory space' stamp: 'di 8/18/2000 16:49'! lowSpaceThreshold "Return the low space threshold. When the amount of free memory (after garbage collection) falls below this limit, the system is in serious danger of completely exhausting memory and crashing. This limit should be made high enough to allow the user open a debugger to diagnose a problem or to save the image." thisContext isPseudoContext ifTrue: [^ 400000 "Enough for JIT compiler"] ifFalse: [^ 200000 "Enough for interpreter"]! ! !SystemDictionary methodsFor: 'memory space' stamp: 'BG 10/30/2003 20:41'! lowSpaceWatcher "Wait until the low space semaphore is signalled, then take appropriate actions." | free | self garbageCollectMost <= self lowSpaceThreshold ifTrue: [ self garbageCollect <= self lowSpaceThreshold ifTrue: [ "free space must be above threshold before starting low space watcher" ^ self beep]]. LowSpaceSemaphore _ Semaphore new. self primLowSpaceSemaphore: LowSpaceSemaphore. self primSignalAtBytesLeft: self lowSpaceThreshold. "enable low space interrupts" LowSpaceSemaphore wait. "wait for a low space condition..." self primSignalAtBytesLeft: 0. "disable low space interrupts" self primLowSpaceSemaphore: nil. LowSpaceProcess _ nil. "Note: user now unprotected until the low space watcher is re-installed" self memoryHogs isEmpty ifFalse: [ free := self bytesLeft. self memoryHogs do: [ :hog | hog freeSomeSpace ]. self bytesLeft > free ifTrue: [ ^ self installLowSpaceWatcher ]]. Smalltalk isMorphic ifTrue: [] ifFalse: [ScheduledControllers interruptName: 'Space is low']! ! !SystemDictionary methodsFor: 'memory space' stamp: 'nk 10/28/2000 20:37'! lowSpaceWatcherProcess ^LowSpaceProcess! ! !SystemDictionary methodsFor: 'memory space' stamp: 'sma 4/22/2000 19:03'! memoryHogs "Answer the list of objects to notify with #freeSomeSpace if memory gets full." ^ MemoryHogs ifNil: [MemoryHogs _ OrderedCollection new]! ! !SystemDictionary methodsFor: 'memory space'! okayToProceedEvenIfSpaceIsLow "Return true if either there is enough memory to do so safely or if the user gives permission after being given fair warning." self garbageCollectMost > self lowSpaceThreshold ifTrue: [^ true]. "quick" self garbageCollect > self lowSpaceThreshold ifTrue: [^ true]. "work harder" ^ self confirm: 'WARNING: There is not enough space to start the low space watcher. If you proceed, you will not be warned again, and the system may run out of memory and crash. If you do proceed, you can start the low space notifier when more space becomes available simply by opening and then closing a debugger (e.g., by hitting Cmd-period.) Do you want to proceed?' ! ! !SystemDictionary methodsFor: 'memory space'! primBytesLeft "Primitive. Answer the number of bytes available for new object data. Not accurate unless preceded by Smalltalk garbageCollectMost (for reasonable accuracy), or Smalltalk garbageCollect (for real accuracy). See Object documentation whatIsAPrimitive." <primitive: 112> ^ 0! ! !SystemDictionary methodsFor: 'memory space'! primLowSpaceSemaphore: aSemaphore "Primitive. Register the given Semaphore to be signalled when the number of free bytes drops below some threshold. Disable low-space interrupts if the argument is nil." <primitive: 124> self primitiveFailed! ! !SystemDictionary methodsFor: 'memory space'! primSignalAtBytesLeft: numBytes "Tell the interpreter the low-space threshold in bytes. When the free space falls below this threshold, the interpreter will signal the low-space semaphore, if one has been registered. Disable low-space interrupts if the argument is zero. Fail if numBytes is not an Integer." <primitive: 125> self primitiveFailed! ! !SystemDictionary methodsFor: 'memory space' stamp: 'ar 2/11/2001 02:16'! primitiveGarbageCollect "Primitive. Reclaims all garbage and answers the number of bytes of available space." <primitive: 130> ^ self primBytesLeft! ! !SystemDictionary methodsFor: 'memory space'! signalLowSpace "Signal the low-space semaphore to alert the user that space is running low." LowSpaceSemaphore signal.! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'nk 11/12/2003 10:19'! getSystemAttribute: attributeID "Optional. Answer the string for the system attribute with the given integer ID. Answer nil if the given attribute is not defined on this platform. On platforms that support invoking programs from command lines (e.g., Unix), this mechanism can be used to pass command line arguments to programs written in Squeak. By convention, the first command line argument that is not a VM configuration option is considered a 'document' to be filed in. Such a document can add methods and classes, can contain a serialized object, can include code to be executed, or any combination of these. Currently defined attributes include: -1000...-1 - command line arguments that specify VM options 0 - the full path name for currently executing VM (or, on some platforms, just the path name of the VM's directory) 1 - full path name of this image 2 - a Squeak document to open, if any 3...1000 - command line arguments for Squeak programs 1001 - this platform's operating system 1002 - operating system version 1003 - this platform's processor type 1004 - vm version" ^self deprecated: 'Use SmalltalkImage current getSystemAttribute: attributeID ' block: [SmalltalkImage current getSystemAttribute: attributeID ] ! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'nk 11/12/2003 10:27'! getVMParameters "Smalltalk getVMParameters" "Answer an Array containing the current values of the VM's internal parameter/metric registers. Each value is stored in the array at the index corresponding to its VM register. (See #vmParameterAt: and #vmParameterAt:put:.)" ^self deprecated: 'Use SmalltalkImage current getVMParameters' block: [SmalltalkImage current getVMParameters] . ! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'BG 10/30/2003 20:40'! handleUserInterrupt Preferences cmdDotEnabled ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] fork]]! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'tk 10/16/2001 19:24'! logError: errMsg inContext: aContext to: aFilename "Log the error message and a stack trace to the given file." | ff | FileDirectory default deleteFileNamed: aFilename ifAbsent: []. (ff _ FileStream fileNamed: aFilename) ifNil: [^ self "avoid recursive errors"]. ff nextPutAll: errMsg; cr. aContext errorReportOn: ff. ff close.! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'md 12/12/2003 17:02'! platformName "Return the name of the platform we're running on" self deprecated: 'Use SmalltalkImage current platformName'. ^self getSystemAttribute: 1001! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'MPH 10/24/2000 14:27'! setMacFileInfoOn: aString "On Mac, set the file type and creator (noop on other platforms)" FileDirectory default setMacFileNamed: aString type: 'STch' creator: 'FAST'.! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'nk 11/12/2003 10:35'! vmParameterAt: parameterIndex put: newValue "parameterIndex is a positive integer corresponding to one of the VM's internal parameter/metric registers. Store newValue (a positive integer) into that register and answer with the previous value that was stored there. Fail if newValue is out of range, if parameterIndex has no corresponding register, or if the corresponding register is read-only." ^ self deprecated: 'Use SmalltalkImage current vmParameterAt: parameterIndex put: newValue' block: [SmalltalkImage current vmParameterAt: parameterIndex put: newValue] ! ! !SystemDictionary methodsFor: 'printing' stamp: 'sma 6/1/2000 09:53'! printElementsOn: aStream aStream nextPutAll:'(lots of globals)'! ! !SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:15'! allClasses "Return all the class defines in the Smalltalk SystemDictionary" "Smalltalk allClasses" ^ self classNames collect: [:name | self at: name]! ! !SystemDictionary methodsFor: 'retrieving' stamp: 'sd 4/17/2003 21:18'! allClassesDo: aBlock "Evaluate the argument, aBlock, for each class in the system." (self classNames collect: [:name | self at: name]) do: aBlock! ! !SystemDictionary methodsFor: 'retrieving' stamp: 'BG 11/1/2003 14:06'! allSentMessagesWithout: classesAndMessagesPair "Answer the set of selectors which are sent somewhere in the system, computed in the absence of the supplied classes and messages." | sent absentClasses absentSelectors literals hasMenuFromArray | sent _ IdentitySet new: CompiledMethod instanceCount. absentClasses _ classesAndMessagesPair first. absentSelectors _ classesAndMessagesPair second. Cursor execute showWhile: [self classNames do: [:cName | ((absentClasses includes: cName) ifTrue: [{}] ifFalse: [{(self at: cName). (self at: cName) class}]) do: [:cl | (absentSelectors isEmpty ifTrue: [cl selectors] ifFalse: [cl selectors copyWithoutAll: absentSelectors]) do: [:sel | "Include all sels, but not if sent by self" literals := (cl compiledMethodAt: sel) literals. hasMenuFromArray := (literals includes: #addList:) | (literals includes: #fromArray:) . literals do: [:m | (m isMemberOf: Symbol) ifTrue: "might be sent" [m == sel ifFalse: [sent add: m]]. (m isMemberOf: Array) ifTrue: "might be performed" [m do: [:x | (x isMemberOf: Symbol) ifTrue: [x == sel ifFalse: [sent add: x]]. (hasMenuFromArray and: [x isMemberOf: Array]) ifTrue: [x do: [:y | (y isMemberOf: Symbol) ifTrue: [y == sel ifFalse: [sent add: y]].]] ] ]. ]]]]. "The following may be sent without being in any literal frame" 1 to: self specialSelectorSize do: [:index | sent add: (self specialSelectorAt: index)]]. Smalltalk presumedSentMessages do: [:sel | sent add: sel]. ^ sent! ! !SystemDictionary methodsFor: 'retrieving' stamp: 'tk 9/26/1999 14:54'! pointersTo: anObject except: objectsToExclude "Find all occurrences in the system of pointers to the argument anObject. Remove objects in the exclusion list from the results." | results anObj | Smalltalk garbageCollect. "big collection shouldn't grow, so it's contents array is always the same" results _ OrderedCollection new: 1000. "allObjectsDo: is expanded inline to keep spurious method and block contexts out of the results" anObj _ self someObject. [0 == anObj] whileFalse: [ anObj isInMemory ifTrue: [ (anObj pointsTo: anObject) ifTrue: [ "exclude the results collector and contexts in call chain" ((anObj ~~ results collector) and: [(anObj ~~ objectsToExclude) and: [(anObj ~~ thisContext) and: [(anObj ~~ thisContext sender) and: [anObj ~~ thisContext sender sender]]]]) ifTrue: [ results add: anObj ]. ]]. anObj _ anObj nextObject. ]. objectsToExclude do: [ :obj | results removeAllSuchThat: [ :el | el == obj]]. ^ results asArray ! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'di 1/7/2004 15:39'! abandonSources "Smalltalk abandonSources" "Replaces every method by a copy with the 4-byte source pointer replaced by a string of all arg and temp names, followed by its length. These names can then be used to inform the decompiler. See stats below" "wod 11/3/1998: zap the organization before rather than after condensing changes." | oldCodeString argsAndTemps oldMethods newMethods m bTotal bCount | (self confirm: 'This method will preserve most temp names (up to about 400 characters) while allowing the sources file to be discarded. -- CAUTION -- If you have backed up your system and are prepared to face the consequences of abandoning source code files, choose Yes. If you have any doubts, you may choose No to back out with no harm done.') == true ifFalse: [^ self inform: 'Okay - no harm done']. Smalltalk forgetDoIts. oldMethods _ OrderedCollection new: CompiledMethod instanceCount. newMethods _ OrderedCollection new: CompiledMethod instanceCount. bTotal _ 0. bCount _ 0. self systemNavigation allBehaviorsDo: [: b | bTotal _ bTotal + 1]. 'Saving temp names for better decompilation...' displayProgressAt: Sensor cursorPoint from: 0 to: bTotal during: [:bar | self systemNavigation allBehaviorsDo: "for test: (Array with: Arc with: Arc class) do: " [:cl | bar value: (bCount _ bCount + 1). cl selectors do: [:selector | m _ cl compiledMethodAt: selector. m fileIndex > 0 ifTrue: [oldCodeString _ cl sourceCodeAt: selector. argsAndTemps _ (cl compilerClass new parse: oldCodeString in: cl notifying: nil) tempNames. oldMethods addLast: m. newMethods addLast: (m copyWithTempNames: argsAndTemps)]]]]. oldMethods asArray elementsExchangeIdentityWith: newMethods asArray. self systemNavigation allBehaviorsDo: [:b | b zapOrganization]. Smalltalk condenseChanges. Preferences disable: #warnIfNoSourcesFile. " In a system with 7780 methods, we got 83k of temp names, or around 100k with spaces between. The order of letter frequency was eatrnoislcmdgpSub, with about 60k falling in the first 11. This suggests that we could encode in 4 bits, with 0-11 beng most common chars, and 12-15 contributing 2 bits to the next nibble for 6 bits, enough to cover all alphaNumeric with upper and lower case. If we get 3/4 in 4 bits and 1/4 in 8, then we get 5 bits per char, or about 38% savings (=38k in this case). Summary: about 13 bytes of temp names per method, or 8 with simple compression, plus 1 for the size. This would be 5 bytes more than the current 4-byte trailer. "! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 10/8/2008 13:14'! majorShrinkClassesToLeave | manual categoryNames classNames classNameSets | manual := #(True False ReadOnlyVariableBinding SystemOrganizer ClassOrganizer View Switch Button EndOfStream ValueHolder EventSensorConstants ChronologyConstants InstructionPrinter Color Form ColorForm DisplayMedium DisplayObject Rectangle Point Pen OrderedCollection Array SortedCollection Dictionary Association SequenceableCollection Collection String Text DisplayText ArrayedCollection Object GIFReadWriter ImageReadWriter "Benchmark BinaryChoice " ChangeSet ChangeSorter DualChangeSorter ChangeList Inspector BasicInspector CompiledMethodInspector DictionaryInspector OrderedCollectionInspector). categoryNames := "(SystemOrganization categoriesMatching:'RVM-*'), " (SystemOrganization categoriesMatching:'PluggableGauges*'), (SystemOrganization categoriesMatching:'Tools-FileList'), (SystemOrganization categoriesMatching:'Tools-Browser'), (SystemOrganization categoriesMatching:'Kernel-ST80 Remnants'), (SystemOrganization categoriesMatching:'ST80-Framework'), (SystemOrganization categoriesMatching:'ST80-Support'), (SystemOrganization categoriesMatching:'ST80-Pluggable Views'), (SystemOrganization categoriesMatching:'ST80-Views'), (SystemOrganization categoriesMatching:'ST80-Editors'), (SystemOrganization categoriesMatching:'Tools-Process Browser'). classNameSets := categoryNames collect:[:each| SystemOrganization listAtCategoryNamed: each]. classNames := OrderedCollection new. classNameSets do:[:set| set do:[:n| classNames add: n]]. ^(manual, classNames) asSet asOrderedCollection! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 9/3/2008 12:00'! majorShrinkClassesToZap ^#(BDFFontReader InstanceBrowser Lexicon TarArchiveMember CRLookupResult " PluggableDictionary PluggableSet " MimeConverter QuotedPrintableMimeConverter RFC2047MimeConverter AbstractLauncher AutoStart AcornFileDirectory " AssertionFailure " CachedHTTPRequest CachingCodeLoader CodeLoader CanvasEncoder EToyVectorVocabulary EToyVocabulary FileList2 FontCache FTPConnectionException FullVocabulary HTTPClient HTTPLoader HTTPRequest HtmlFileStream "MacFileDirectory" "MacHFSPlusFileDirectory" PluginHTTPRequest SUnitNameResolver ScreenedVocabulary ScriptNameType SoundType StringType SymbolListType TestCase TestFailure TestResource TestResult TestRunner TestSuite TestCaseDebugger TestViaMethodCall TextSqkPageLink TextSqkProjectLink TextURL UnknownType Verifier VerifierOfProperty Vocabulary BooleanType ButtonPhaseType ColorType DataType GraphicType MenuType NumberType PlayerType)! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'BG 11/26/2003 19:09'! postMajorShrink | oldDicts newDicts | SystemOrganization removeEmptyCategories. Smalltalk allClassesDo: [:c | c compactOrganization]. Smalltalk garbageCollect. 'Rehashing method dictionaries . . .' displayProgressAt: Sensor cursorPoint from: 0 to: MethodDictionary instanceCount during: [:bar | oldDicts _ MethodDictionary allInstances. newDicts _ Array new: oldDicts size. oldDicts withIndexDo: [:d :index | bar value: index. newDicts at: index put: d rehashWithoutBecome. ]. oldDicts elementsExchangeIdentityWith: newDicts. ]. oldDicts _ newDicts _ nil. Project rebuildAllProjects. ChangeSet current initialize. "seems to take more than one try to gc all the weak refs in SymbolTable" 3 timesRepeat: [ Smalltalk garbageCollect. Symbol compactSymbolTable. ]. ! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 9/3/2008 13:42'! presumedSentMessages | sent | "Smalltalk presumedSentMessages" "The following should be preserved for doIts, etc" sent _ IdentitySet new. #( "menu messages from Debugger>>contextStackMenu: aMenu shifted: shifted" fullStack restart proceed doStep stepIntoBlock send where peelToFirst browseSendersOfMessages browseMessages methodHierarchy browseVersions browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables browseClassRefs browseMethodFull fileOutMessage shiftedYellowButtonActivity "menu messages from Preferences>>presentMvcFontConfigurationMenu" chooseSystemFont chooseListFont chooseMenuFont chooseWindowTitleFont chooseCodeFont restoreDefaultFonts "others" rehashWithoutBecome compactSymbolTable rebuildAllProjects browseAllSelect: printSpaceAnalysis lastRemoval scrollBarValue: scrollBarMenuButtonPressed: withSelectionFrom: to: removeClassNamed: instVarNamed:put: breakDependents maximumSize: redButtonMenu:redButtonMessages: dragon: hilberts: mandala: web test3 factorial tinyBenchmarks benchFib newDepth: restoreAfter: forgetDoIts zapAllMethods obsoleteClasses removeAllUnSentMessages abandonSources removeUnreferencedKeys reclaimDependents zapOrganization condenseChanges browseObsoleteReferences renameClassNamed:as: " this method is used in change sets " subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: variableByteSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: " subclass creation: " variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: variableWordSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: weakSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: methodsFor:stamp: methodsFor:stamp:prior: instanceVariableNames: startTimerInterruptWatcher unusedClasses widthOfString: widthOfString:from:to: clipHeight clipHeight: clipWidth clipWidth: clipX clipX: clipY clipY: newDay:monthIndex:year: abandon pixelForValueAt:put: magnifyBy: replaceColor:withColor: dotOfSize: "DisplayScreen> " fullBoundingBox originFromUser: " finalization " toFinalizeSend:to:with: " StrikeFont> " maxAscii minAscii maxWidth firstIndent: restIndent: rightIndent: newFontArray: fontArray: readStrikeFont2Family: familySizeFace writeAsStrike2Named: " Paragraph " compositionRectangle: " Form: these methods are meeded for gif creation " colorReduced colorsUsed " protocol from Pen class: " inkBrush simplePressurePen testMouseTracking testTabletTracking " two methods that are hidden from the method tracer " method: preamble: inspectElement inspectSelection inspectBasic fileOutAllChangeSets fillAggregateChangeSet " convenience methods in True and False: " and:and: and:and:and: and:and:and:and: or:or: or:or:or: or:or:or:or: " mics " pairsDo: font: notEmpty " ExternalEvent class: " registerClient: ) do: [:sel | sent add: sel]. "The following may be sent by perform: in dispatchOnChar..." (ParagraphEditor classPool at: #CmdActions) asSet do: [:sel | sent add: sel]. (ParagraphEditor classPool at: #ShiftCmdActions) asSet do: [:sel | sent add: sel]. Smalltalk majorShrinkClassesToLeave do: [:symbol | sent addAll: (Smalltalk at: symbol) selectors; addAll: (Smalltalk at: symbol) class selectors.]. ^ sent! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'BG 11/26/2003 14:35'! removeAllUnSentMessages "Smalltalk removeAllUnSentMessages" "[Smalltalk unusedClasses do: [:c | (Smalltalk at: c) removeFromSystem]. Smalltalk removeAllUnSentMessages > 0] whileTrue." "Remove all implementations of unsent messages." | sels n | sels _ SystemNavigation default allUnSentMessages. "The following should be preserved for doIts, etc" #( rehashWithoutBecome compactSymbolTable rebuildAllProjects "needed even after #majorShrink is pulled" browseAllSelect: printSpaceAnalysis lastRemoval scrollBarValue: scrollBarMenuButtonPressed: withSelectionFrom: to: removeClassNamed: dragon: hilberts: mandala: web test3 factorial tinyBenchmarks benchFib newDepth: restoreAfter: forgetDoIts zapAllMethods obsoleteClasses removeAllUnSentMessages condenseChanges condenseSources abandonSources removeUnreferencedKeys postMajorShrink offerShiftedClassListMenu offerUnshiftedClassListMenu font1 font2 font3 font4 reclaimDependents zapOrganization condenseChanges browseObsoleteReferences subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: methodsFor:stamp: methodsFor:stamp:prior: instanceVariableNames: startTimerInterruptWatcher unusedClasses) do: [:sel | sels remove: sel ifAbsent: []]. "The following may be sent by perform: in dispatchOnChar..." (ParagraphEditor classPool at: #CmdActions) asSet do: [:sel | sels remove: sel ifAbsent: []]. (ParagraphEditor classPool at: #ShiftCmdActions) asSet do: [:sel | sels remove: sel ifAbsent: []]. sels size = 0 ifTrue: [^ 0]. n _ 0. self systemNavigation allBehaviorsDo: [:x | n _ n+1]. 'Removing ', sels size printString , ' messages . . .' displayProgressAt: Sensor cursorPoint from: 0 to: n during: [:bar | n _ 0. self systemNavigation allBehaviorsDo: [:class | bar value: (n _ n+1). sels do: [:sel | class removeSelectorSimply: sel]]]. ^ sels size! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'sma 6/18/2000 11:34'! removeSelector: descriptor "Safely remove a selector from a class (or metaclass). If the class or the method doesn't exist anymore, never mind and answer nil. This method should be used instead of 'Class removeSelector: #method' to omit global class references." | class sel | class _ Smalltalk at: descriptor first ifAbsent: [^ nil]. (descriptor size > 2 and: [descriptor second == #class]) ifTrue: [class _ class class. sel _ descriptor third] ifFalse: [sel _ descriptor second]. ^ class removeSelector: sel! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'sd 4/29/2003 19:06'! unusedClasses "Enumerates all classes in the system and returns a list of those that are apparently unused. A class is considered in use if it (a) has subclasses or (b) is referred to by some method or (c) has its name in use as a literal. " "Smalltalk unusedClasses asSortedCollection" ^ self systemNavigation allUnusedClassesWithout: {{}. {}}! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/19/1999 22:36'! add: aClass toList: startUpOrShutDownList after: predecessor "Add the name of aClass to the startUp or shutDown list. Add it after the name of predecessor, or at the end if predecessor is nil." | name earlierName | name _ aClass name. (self at: name ifAbsent: [nil]) == aClass ifFalse: [self error: name , ' cannot be found in Smalltalk dictionary.']. predecessor == nil ifTrue: ["No-op if alredy in the list." (startUpOrShutDownList includes: name) ifFalse: [startUpOrShutDownList == StartUpList ifTrue: ["Add to end of startUp list" startUpOrShutDownList addLast: name] ifFalse: ["Add to front of shutDown list" startUpOrShutDownList addFirst: name]]] ifFalse: ["Add after predecessor, moving it if already there." earlierName _ predecessor name. (self at: earlierName) == predecessor ifFalse: [self error: earlierName , ' cannot be found in Smalltalk dictionary.']. (startUpOrShutDownList includes: earlierName) ifFalse: [self error: earlierName , ' cannot be found in the list.']. startUpOrShutDownList remove: name ifAbsent:[]. startUpOrShutDownList add: name after: earlierName]! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:38'! addToShutDownList: aClass "This will add a ref to this class at the BEGINNING of the shutDown list." self addToShutDownList: aClass after: nil! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'! addToShutDownList: aClass after: predecessor self add: aClass toList: ShutDownList after: predecessor! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/4/1999 15:37'! addToStartUpList: aClass "This will add a ref to this class at the END of the startUp list." self addToStartUpList: aClass after: nil! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:04'! addToStartUpList: aClass after: predecessor self add: aClass toList: StartUpList after: predecessor! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'RAA 6/14/2000 17:21'! isMorphic "Answer true if the user interface is running in Morphic rathern than MVC. By convention the gloabl variable World is set to nil when MVC is running. ScheduledControllers could be set to nil when Morphic is running, but this symmetry is not yet in effect." ^ World ~~ nil "or: [RequestCurrentWorldNotification signal notNil]"! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'! processShutDownList: quitting "Send #shutDown to each class that needs to wrap up before a snapshot." self send: #shutDown: toClassesNamedIn: ShutDownList with: quitting. ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 11/16/1999 20:12'! processStartUpList: resuming "Send #startUp to each class that needs to run initialization after a snapshot." self send: #startUp: toClassesNamedIn: StartUpList with: resuming. ! ! !SystemDictionary methodsFor: 'snapshot and quit'! quitPrimitive "Primitive. Exit to another operating system on the host machine, if one exists. All state changes in the object space since the last snapshot are lost. Essential. See Object documentation whatIsAPrimitive." <primitive: 113> self primitiveFailed! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'! removeFromShutDownList: aClass ShutDownList remove: aClass name ifAbsent: []! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 2/3/1999 22:22'! removeFromStartUpList: aClass StartUpList remove: aClass name ifAbsent: []! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'di 3/7/2001 01:26'! send: startUpOrShutDown toClassesNamedIn: startUpOrShutDownList with: argument "Send the message #startUp: or #shutDown: to each class named in the list. The argument indicates if the system is about to quit (for #shutDown:) or if the image is resuming (for #startUp:). If any name cannot be found, then remove it from the list." | removals class | removals _ OrderedCollection new. startUpOrShutDownList do: [:name | class _ self at: name ifAbsent: [nil]. class == nil ifTrue: [removals add: name] ifFalse: [class isInMemory ifTrue: [class perform: startUpOrShutDown with: argument]]]. "Remove any obsolete entries, but after the iteration" startUpOrShutDownList removeAll: removals! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 9/30/2003 13:47'! setGCParameters "Adjust the VM's default GC parameters to avoid premature tenuring." SmalltalkImage current vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations" SmalltalkImage current vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC" ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'md 12/12/2003 17:03'! setPlatformPreferences "Set some platform specific preferences on system startup" self deprecated: 'Use SmalltalkImage current setPlatformPreferences'. ! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'sd 11/16/2003 13:14'! shutDown ^ SmalltalkImage current closeSourceFiles! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'BG 10/29/2003 09:55'! snapshot: save andQuit: quit embedded: embeddedFlag "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. The latter part of this method runs when resuming a previously saved image. The resume logic checks for a document file to process when starting up." | resuming msg sourceLink | Object flushDependents. Object flushEvents. save & (SourceFiles at: 2) notNil ifTrue: [msg _ (quit ifTrue: ['----QUIT----'] ifFalse: ['----SNAPSHOT----']) , Date dateAndTimeNow printString, ' ', (FileDirectory default localNameFor: self imageName). sourceLink _ ' priorSource: ' , LastQuitLogPosition printString. self assureStartupStampLogged. LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position. self logChange: msg , sourceLink. Transcript cr; show: msg]. self processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [self clearExternalObjects]. self processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'JMM 11/21/2000 21:02'! snapshotEmbeddedPrimitive <primitive: 247> ^nil "indicates error writing embedded image file"! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'ar 7/22/2000 14:34'! snapshotPrimitive "Primitive. Write the current state of the object memory on a file in the same format as the Smalltalk-80 release. The file can later be resumed, returning you to this exact state. Return normally after writing the file. Essential. See Object documentation whatIsAPrimitive." <primitive: 97> ^nil "indicates error writing image file"! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'sw 2/15/1999 16:18'! aboutThisSystem "Identify software version" ^ self inform: self systemInformationString! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'NS 1/16/2004 15:37'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." self deprecated: 'Use SmalltalkImage current assureStartupStampLogged'. SmalltalkImage current assureStartupStampLogged. " StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile _ SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp _ nil. self forceChangesToDisk."! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 5/23/2003 14:42'! currentChangeSetString "Smalltalk currentChangeSetString" ^ 'Current Change Set: ', ChangeSet current name! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'di 9/10/1999 15:52'! currentProjectDo: aBlock "So that code can work after removal of Projects" Smalltalk at: #Project ifPresent: [:projClass | aBlock value: projClass current].! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'mir 5/1/2001 18:20'! datedVersion "Answer the version of this release." ^SystemVersion current datedVersion! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'tk 1/24/2000 23:01'! endianness | bytes word blt | "What endian-ness is the current hardware? The String '1234' will be stored into a machine word. On BigEndian machines (the Mac), $1 will be the high byte if the word. On LittleEndian machines (the PC), $4 will be the high byte." "Smalltalk endianness" bytes _ ByteArray withAll: #(0 0 0 0). "(1 2 3 4) or (4 3 2 1)" word _ WordArray with: 16r01020304. blt _ (BitBlt toForm: (Form new hackBits: bytes)) sourceForm: (Form new hackBits: word). blt combinationRule: Form over. "store" blt sourceY: 0; destY: 0; height: 1; width: 4. blt sourceX: 0; destX: 0. blt copyBits. "paste the word into the bytes" bytes first = 1 ifTrue: [^ #big]. bytes first = 4 ifTrue: [^ #little]. self error: 'Ted is confused'.! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'ssa 9/3/2008 11:25'! forceChangesToDisk "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." | changesFile | changesFile _ SourceFiles at: 2. (changesFile isKindOf: FileStream) ifTrue: [ changesFile flush. true ifTrue:[ changesFile close. changesFile open: changesFile name forWrite: true]. changesFile setToEnd. ]. ! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'md 12/12/2003 17:02'! isBigEndian self deprecated: 'Use SmalltalkImage current isBigEndian'. ^self endianness == #big! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'md 12/12/2003 17:02'! isLittleEndian self deprecated: 'Use SmalltalkImage current isLittleEndian'. ^self endianness == #little! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'mir 5/1/2001 18:02'! lastUpdateString "Smalltalk lastUpdateString" ^'latest update: #', SystemVersion current highestUpdate printString! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'NS 1/16/2004 15:38'! logChange: aStringOrText "Write the argument, aString, onto the changes file." self deprecated: 'Use SmalltalkImage current logChange:'. SmalltalkImage current logChange: aStringOrText. " | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aStringOrText isText ifTrue: [aString _ aStringOrText string] ifFalse: [aString _ aStringOrText]. (aString isMemberOf: String) ifFalse: [self error: 'can''t log this change']. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. (changesFile _ SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. self forceChangesToDisk. "! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'sd 7/2/2003 22:11'! systemInformationString "Identify software version" ^ SystemVersion current version, String cr, self lastUpdateString, String cr, self currentChangeSetString " (eToySystem _ self at: #EToySystem ifAbsent: [nil]) ifNotNil: [aString _ aString, ' Squeak-Central version: ', eToySystem version, ' of ', eToySystem versionDate]."! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'mir 5/1/2001 18:19'! timeStamp: aStream "Writes system version and current time on stream aStream." | dateTime | dateTime _ Time dateAndTimeNow. aStream nextPutAll: 'From ', Smalltalk datedVersion, ' [', Smalltalk lastUpdateString, '] on ', (dateTime at: 1) printString, ' at ', (dateTime at: 2) printString! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'md 12/12/2003 17:03'! version "Answer the version of this release." self deprecated: 'Use SystemVersion current version'. ^SystemVersion current version! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'sw 2/3/2000 15:58'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes _ SourceFiles at: 2. changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'sw 2/3/2000 16:17'! writeRecentToFile | numChars aDirectory aFileName | "Smalltalk writeRecentToFile" aDirectory _ FileDirectory default. aFileName _ Utilities keyLike: 'squeak-recent.01' withTrailing: '.log' satisfying: [:aKey | (aDirectory includesKey: aKey) not]. numChars _ ChangeList getRecentLocatorWithPrompt: 'copy logged source as far back as...'. numChars ifNotNil: [Smalltalk writeRecentCharacters: numChars toFileNamed: aFileName]! ! !SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 20:36'! clearExternalObjects "Clear the array of objects that have been registered for use in non-Smalltalk code." "Smalltalk clearExternalObjects" ExternalSemaphoreTable clearExternalObjects ! ! !SystemDictionary methodsFor: 'special objects'! compactClassesArray "Smalltalk compactClassesArray" "Return the array of 31 classes whose instances may be represented compactly" ^ Smalltalk specialObjectsArray at: 29! ! !SystemDictionary methodsFor: 'special objects'! hasSpecialSelector: aLiteral ifTrueSetByte: aBlock 1 to: self specialSelectorSize do: [:index | (self specialSelectorAt: index) == aLiteral ifTrue: [aBlock value: index + 16rAF. ^true]]. ^false! ! !SystemDictionary methodsFor: 'special objects' stamp: 'tpr 7/25/2003 12:30'! recreateSpecialObjectsArray "Smalltalk recreateSpecialObjectsArray" "The Special Objects Array is an array of object pointers used by the Squeak virtual machine. Its contents are critical and unchecked, so don't even think of playing here unless you know what you are doing." | newArray | newArray _ Array new: 50. "Nil false and true get used throughout the interpreter" newArray at: 1 put: nil. newArray at: 2 put: false. newArray at: 3 put: true. "This association holds the active process (a ProcessScheduler)" newArray at: 4 put: (Smalltalk associationAt: #Processor). "Numerous classes below used for type checking and instantiation" newArray at: 5 put: Bitmap. newArray at: 6 put: SmallInteger. newArray at: 7 put: String. newArray at: 8 put: Array. newArray at: 9 put: Smalltalk. newArray at: 10 put: Float. newArray at: 11 put: MethodContext. newArray at: 12 put: BlockContext. newArray at: 13 put: Point. newArray at: 14 put: LargePositiveInteger. newArray at: 15 put: Display. newArray at: 16 put: Message. newArray at: 17 put: CompiledMethod. newArray at: 18 put: (self specialObjectsArray at: 18) "(low space Semaphore)". newArray at: 19 put: Semaphore. newArray at: 20 put: Character. newArray at: 21 put: #doesNotUnderstand:. newArray at: 22 put: #cannotReturn:. newArray at: 23 put: nil. "*unused*" "An array of the 32 selectors that are compiled as special bytecodes, paired alternately with the number of arguments each takes." newArray at: 24 put: #(+ 1 - 1 < 1 > 1 <= 1 >= 1 = 1 ~= 1 * 1 / 1 \\ 1 @ 1 bitShift: 1 // 1 bitAnd: 1 bitOr: 1 at: 1 at:put: 2 size 0 next 0 nextPut: 1 atEnd 0 == 1 class 0 blockCopy: 1 value 0 value: 1 do: 1 new 0 new: 1 x 0 y 0 ). "An array of the 255 Characters in ascii order." newArray at: 25 put: ((0 to: 255) collect: [:ascii | Character value: ascii]). newArray at: 26 put: #mustBeBoolean. newArray at: 27 put: ByteArray. newArray at: 28 put: Process. "An array of up to 31 classes whose instances will have compact headers" newArray at: 29 put: self compactClassesArray. newArray at: 30 put: (self specialObjectsArray at: 30) "(delay Semaphore)". newArray at: 31 put: (self specialObjectsArray at: 31) "(user interrupt Semaphore)". "Prototype instances that can be copied for fast initialization" newArray at: 32 put: (Float new: 2). newArray at: 33 put: (LargePositiveInteger new: 4). newArray at: 34 put: Point new. newArray at: 35 put: #cannotInterpret:. "Note: This must be fixed once we start using context prototypes" newArray at: 36 put: (self specialObjectsArray at: 36). "(MethodContext new: CompiledMethod fullFrameSize)." newArray at: 37 put: nil. newArray at: 38 put: (self specialObjectsArray at: 38). "(BlockContext new: CompiledMethod fullFrameSize)." newArray at: 39 put: Array new. "array of objects referred to by external code" newArray at: 40 put: PseudoContext. newArray at: 41 put: TranslatedMethod. "finalization Semaphore" newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil:[Semaphore new]). newArray at: 43 put: LargeNegativeInteger. "External objects for callout. Note: Written so that one can actually completely remove the FFI." newArray at: 44 put: (Smalltalk at: #ExternalAddress ifAbsent:[nil]). newArray at: 45 put: (Smalltalk at: #ExternalStructure ifAbsent:[nil]). newArray at: 46 put: (Smalltalk at: #ExternalData ifAbsent:[nil]). newArray at: 47 put: (Smalltalk at: #ExternalFunction ifAbsent:[nil]). newArray at: 48 put: (Smalltalk at: #ExternalLibrary ifAbsent:[nil]). newArray at: 49 put: #aboutToReturn:through:. newArray at: 50 put: #run:with:in:. "Now replace the interpreter's reference in one atomic operation" self specialObjectsArray become: newArray! ! !SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 20:39'! registerExternalObject: anObject "Register the given object in the external objects array and return its index. If it is already there, just return its index." ^ExternalSemaphoreTable registerExternalObject: anObject! ! !SystemDictionary methodsFor: 'special objects'! specialNargsAt: anInteger "Answer the number of arguments for the special selector at: anInteger." ^ (self specialObjectsArray at: 24) at: anInteger * 2! ! !SystemDictionary methodsFor: 'special objects'! specialObjectsArray "Smalltalk specialObjectsArray at: 1" <primitive: 129> ^ self primitiveFailed! ! !SystemDictionary methodsFor: 'special objects'! specialSelectorAt: anInteger "Answer the special message selector from the interleaved specialSelectors array." ^ (self specialObjectsArray at: 24) at: anInteger * 2 - 1! ! !SystemDictionary methodsFor: 'special objects'! specialSelectorSize "Answer the number of special selectors in the system." ^ (self specialObjectsArray at: 24) size // 2! ! !SystemDictionary methodsFor: 'special objects' stamp: 'JMM 6/6/2000 20:40'! unregisterExternalObject: anObject "Unregister the given object in the external objects array. Do nothing if it isn't registered." ExternalSemaphoreTable unregisterExternalObject: anObject! ! !SystemDictionary methodsFor: 'copying' stamp: 'sw 11/21/2001 15:08'! assureUniClass "Assure that the receiver has a uniclass. Or rather, in this case, stop short of fulfilling such a request" self error: 'We do not want uniclasses descending from here' ! ! !SystemDictionary methodsFor: 'copying' stamp: 'tk 10/20/2000 11:35'! veryDeepCopyWith: deepCopier "Return self. I can't be copied. Do not record me."! ! !SystemDictionary methodsFor: 'deprecated' stamp: 'md 12/12/2003 17:03'! swapBytesIn: aNonPointerThing from: start to: stop "Perform a bigEndian/littleEndian byte reversal of my words. We only intend this for non-pointer arrays. Do nothing if I contain pointers." | hack blt | self deprecated: 'Use Bitmap class>>swapBytesIn: aNonPointerThing from: start to: stop instead'. "The implementation is a hack, but fast for large ranges" hack _ Form new hackBits: aNonPointerThing. blt _ (BitBlt toForm: hack) sourceForm: hack. blt combinationRule: Form reverse. "XOR" blt sourceY: start-1; destY: start-1; height: stop-start+1; width: 1. blt sourceX: 0; destX: 3; copyBits. "Exchange bytes 0 and 3" blt sourceX: 3; destX: 0; copyBits. blt sourceX: 0; destX: 3; copyBits. blt sourceX: 1; destX: 2; copyBits. "Exchange bytes 1 and 2" blt sourceX: 2; destX: 1; copyBits. blt sourceX: 1; destX: 2; copyBits. ! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:23'! changeImageNameTo: aString self deprecated: 'Use SmalltalkImage current changeImageNameTo: aString'. SmalltalkImage current imageName: aString. LastImageName _ SmalltalkImage current imageName! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:26'! changesName "Answer the local name for the changes file corresponding to the image file name." "Smalltalk changesName" | imName | self deprecated: 'Use SmalltalkImage current changesName'. imName _ FileDirectory baseNameFor: (FileDirectory localNameFor: SmalltalkImage current imageName). ^ imName, FileDirectory dot, 'changes' ! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:26'! closeSourceFiles "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" self deprecated: 'Use SmalltalkImage current closeSourceFiles'. 1 to: 2 do: [:i | ((SourceFiles at: i) isKindOf: FileStream) ifTrue: [(SourceFiles at: i) close. SourceFiles at: i put: nil]]! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'tpr 12/15/2003 12:09'! fullNameForChangesNamed: aName | newName | self deprecated: 'Use SmalltalkImage current fullNameForChangesNamed: aName'. newName _ FileDirectory baseNameFor: (FileDirectory default fullNameFor: aName). ^newName , FileDirectory dot, FileDirectory changeSuffix.! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'tpr 12/15/2003 12:10'! fullNameForImageNamed: aName | newName | self deprecated: 'Use SmalltalkImage current fullNameForImageNamed: aName'. newName _ FileDirectory baseNameFor: (FileDirectory default fullNameFor: aName). ^newName , FileDirectory dot, FileDirectory imageSuffix.! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'tpr 12/15/2003 12:19'! getFileNameFromUser | newName | self deprecated: 'Use SmalltalkImage current getFileNameFromUser'. newName _ FillInTheBlank request: 'New File Name?' translated initialAnswer: (FileDirectory localNameFor: SmalltalkImage current imageName). newName = '' ifTrue: [^nil]. ((FileDirectory default fileOrDirectoryExists: (SmalltalkImage current fullNameForImageNamed: newName)) or: [FileDirectory default fileOrDirectoryExists: (SmalltalkImage current fullNameForChangesNamed: newName)]) ifTrue: [ (self confirm: ('{1} already exists. Overwrite?' translated format: {newName})) ifFalse: [^nil]]. ^newName ! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! lastQuitLogPosition self deprecated: 'Use SmalltalkImage current lastQuitLogPosition'. ^ LastQuitLogPosition! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! openSourceFiles self deprecated: 'Use SmalltalkImage current lastQuitLogPosition'. SmalltalkImage current imageName = LastImageName ifFalse: ["Reset the author initials to blank when the image gets moved" LastImageName _ SmalltalkImage current imageName. Utilities setAuthorInitials: '']. FileDirectory openSources: SmalltalkImage current sourcesName andChanges: SmalltalkImage current changesName forImage: LastImageName. StandardSourceFileArray install! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! readDocumentFile "No longer used. Everything is now done in ProjectLauncher." self deprecated: 'Use SmalltalkImage current readDocumentFile'. StartupStamp _ '----STARTUP----', Time dateAndTimeNow printString, ' as ', SmalltalkImage current imageName. ! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'tpr 12/15/2003 12:21'! saveAs "Put up the 'saveAs' prompt, obtain a name, and save the image under that new name." | newName | self deprecated: 'Use SmalltalkImage current saveAs'. newName _ SmalltalkImage current getFileNameFromUser. newName isNil ifTrue: [^ self]. (SourceFiles at: 2) ifNotNil: [SmalltalkImage current closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (SmalltalkImage current fullNameForChangesNamed: newName)]. SmalltalkImage current saveImageInFileNamed: (SmalltalkImage current fullNameForImageNamed: newName)! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! saveChangesInFileNamed: aString self deprecated: 'Use SmalltalkImage current saveChangesInFileNamed: aString'. FileDirectory default copyFileWithoutOverwriteConfirmationNamed: SmalltalkImage current changesName toFileNamed: aString. self setMacFileInfoOn: aString.! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! saveImageInFileNamed: aString self deprecated: 'Use SmalltalkImage current saveImageInFileNamed: aString'. SmalltalkImage current changeImageNameTo: (FileDirectory default fullNameFor: aString). SmalltalkImage current closeSourceFiles. SmalltalkImage current openSourceFiles. "so SNAPSHOT appears in new changes file" SmalltalkImage current saveImageSegments. SmalltalkImage current snapshot: true andQuit: false.! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! saveImageSegments | haveSegs oldImageSegDir newImageSegDir | self deprecated: 'Use SmalltalkImage current saveImageSegments'. haveSegs _ false. Smalltalk at: #ImageSegment ifPresent: [:theClass | (haveSegs _ theClass instanceCount ~= 0) ifTrue: [ oldImageSegDir _ theClass segmentDirectory]]. haveSegs ifTrue: [ Smalltalk at: #ImageSegment ifPresent: [:theClass | newImageSegDir _ theClass segmentDirectory. "create the folder" oldImageSegDir fileNames do: [:theName | "copy all segment files" | imageSegmentName | imageSegmentName _ oldImageSegDir pathName, FileDirectory slash, theName. newImageSegDir copyFileWithoutOverwriteConfirmationNamed: imageSegmentName toFileNamed: theName]]]. ! ! !SystemDictionary methodsFor: 'toDeprecate' stamp: 'sd 11/16/2003 14:27'! snapshot: save andQuit: quit self deprecated: 'Use SmalltalkImage current snapshot: save andQuit: quit'. ^self snapshot: save andQuit: quit embedded: false! ! !SystemDictionary methodsFor: 'browsing' stamp: 'BG 10/30/2003 21:12'! browseMethodsWhoseNamesContain: aString "Launch a tool which shows all methods whose names contain the given string; case-insensitive. 1/16/1996 sw, at the dawn of Squeak: this was the classic implementation that provided the underpinning for the 'method names containing it' (cmd-shift-W) feature that has always been in Squeak -- the feature that later inspired the MethodFinder (aka SelectorBrowser). sw 7/27/2001: Switched to showing a MessageNames tool rather than a message-list browser, if in Morphic." | aList | aList _ Symbol selectorsContaining: aString. aList size > 0 ifTrue: [self browseAllImplementorsOfList: aList asSortedCollection title: 'Methods whose names contain ''', aString, ''''] ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SystemDictionary class instanceVariableNames: ''! !SystemDictionary class methodsFor: 'initialization' stamp: 'BG 8/18/2004 15:09'! initialize "SystemDictionary initialize" | oldList | oldList _ StartUpList. StartUpList _ OrderedCollection new. "These get processed from the top down..." #( DisplayScreen Cursor InputSensor ProcessorScheduler "Starts low space watcher and bkground." Delay FileDirectory "Enables file stack dump and opens sources." "ShortIntegerArray" ShortRunArray CrLfFileStream ) do:[:clsName| Smalltalk at: clsName ifPresent:[:cls| Smalltalk addToStartUpList: cls]. ]. oldList ifNotNil: [oldList do: [:className | Smalltalk at: className ifPresent: [:theClass | Smalltalk addToStartUpList: theClass]]]. #( ImageSegment ControlManager ) do:[:clsName| Smalltalk at: clsName ifPresent:[:cls| Smalltalk addToStartUpList: cls]. ]. oldList _ ShutDownList. ShutDownList _ OrderedCollection new. "These get processed from the bottom up..." #( DisplayScreen Form ControlManager StrikeFont Color FileDirectory Delay HttpUrl Password PWS MailDB ImageSegment ) do:[:clsName| Smalltalk at: clsName ifPresent:[:cls| Smalltalk addToShutDownList: cls]. ]. oldList ifNotNil: [oldList reverseDo: [:className | Smalltalk at: className ifPresent: [:theClass | Smalltalk addToShutDownList: theClass]]]. ! ! EventManager subclass: #SystemEventManager instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !SystemEventManager methodsFor: 'events-accessing' stamp: 'rw 7/20/2003 17:02'! actionSequenceForEvent: anEventSelector ^(self actionMap at: anEventSelector asSymbol ifAbsent: [^WeakActionSequenceTrappingErrors new]) asActionSequenceTrappingErrors! ! Object subclass: #SystemNavigation instanceVariableNames: 'browserClass hierarchyBrowserClass' classVariableNames: 'Default' poolDictionaries: '' category: 'System-Support'! !SystemNavigation commentStamp: 'sd 4/15/2003 22:30' prior: 0! I support the navigation of the system. I act as a facade but as I could require some state or different way of navigating the system all my behavior are on the instance side! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 08:53'! browseAllAccessesTo: instVarName from: aClass "Create and schedule a Message Set browser for all the receiver's methods or any methods of a subclass/superclass that refer to the instance variable name." "self new browseAllAccessesTo: 'contents' from: Collection." | coll | coll _ OrderedCollection new. Cursor wait showWhile: [ aClass withAllSubAndSuperclassesDo: [:class | (class whichSelectorsAccess: instVarName) do: [:sel | sel == #DoIt ifFalse: [ coll add: ( MethodReference new setStandardClass: class methodSymbol: sel ) ] ] ]. ]. ^ self browseMessageList: coll name: 'Accesses to ' , instVarName autoSelect: instVarName! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/29/2003 12:23'! browseAllCallsOn: aLiteral "Create and schedule a message browser on each method that refers to aLiteral. For example, SystemNavigation new browseAllCallsOn: #open:label:." (aLiteral isKindOf: LookupKey) ifTrue: [^ self browseMessageList: (self allCallsOn: aLiteral) asSortedCollection name: 'Users of ' , aLiteral key autoSelect: aLiteral key]. self browseMessageList: (self allCallsOn: aLiteral) asSortedCollection name: 'Senders of ' , aLiteral autoSelect: aLiteral keywords first! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 11:44'! browseAllCallsOn: aLiteral localTo: aClass "Create and schedule a message browser on each method in or below the given class that refers to aLiteral. For example, Smalltalk browseAllCallsOn: #open:label:." aClass ifNil: [ ^self inform: 'no selected class' ]. (aLiteral isKindOf: LookupKey) ifTrue: [self browseMessageList: (aClass allLocalCallsOn: aLiteral) asSortedCollection name: 'Users of ' , aLiteral key, ' local to ', aClass name autoSelect: aLiteral key] ifFalse: [self browseMessageList: (aClass allLocalCallsOn: aLiteral) asSortedCollection name: 'Senders of ' , aLiteral, ' local to ', aClass name autoSelect: aLiteral keywords first]! ! !SystemNavigation methodsFor: 'browse' stamp: 'tpr 12/17/2003 16:01'! browseAllCallsOnClass: aClass "Create and schedule a message browser on each method that refers to aClass. For example, SystemNavigation new browseAllCallsOnClass: Object." self browseMessageList: aClass allCallsOn asSortedCollection name: 'Users of class ' , aClass theNonMetaClass name autoSelect: aClass theNonMetaClass name! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/19/2003 12:15'! browseAllImplementorsOf: selector "Create and schedule a message browser on each method that implements the message whose selector is the argument, selector. For example, Smalltalk browseAllImplementorsOf: #at:put:." ^ self browseMessageList: (self allImplementorsOf: selector) name: 'Implementors of ' , selector! ! !SystemNavigation methodsFor: 'browse' stamp: 'nk 6/26/2003 22:31'! browseAllImplementorsOf: selector localTo: aClass "Create and schedule a message browser on each method in or below the given class that implements the message whose selector is the argument, selector. For example, SystemNavigation new browseAllImplementorsOf: #at:put: localTo: Dictionary." aClass ifNil: [ ^self inform: 'no class selected' ]. ^self browseMessageList: (self allImplementorsOf: selector localTo: aClass) name: 'Implementors of ' , selector, ' local to ', aClass name! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/19/2003 12:15'! browseAllImplementorsOfList: selectorList title: aTitle "Create and schedule a message browser on each method that implements the message whose selector is in the argument selectorList. For example, self new browseAllImplementorsOf: #(at:put: size). 1/16/96 sw: this variant adds the title argument. 1/24/96 sw: use a SortedCollection 2/1/96 sw: show normal cursor" | implementorLists flattenedList | implementorLists _ selectorList collect: [:each | self allImplementorsOf: each]. flattenedList _ SortedCollection new. implementorLists do: [:each | flattenedList addAll: each]. Cursor normal show. ^ self browseMessageList: flattenedList name: aTitle! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 11:39'! browseAllObjectReferencesTo: anObject except: objectsToExclude ifNone: aBlock "Bring up a list inspector on the objects that point to anObject. If there are none, then evaluate aBlock on anObject. " | aList shortName | aList _ Smalltalk pointersTo: anObject except: objectsToExclude. aList size > 0 ifFalse: [^ aBlock value: anObject]. shortName _ (anObject name ifNil: [anObject printString]) contractTo: 20. OrderedCollectionInspector openOn: aList withEvalPane: false withLabel: 'Objects pointing to ', shortName.! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/29/2003 20:43'! browseAllSelect: aBlock "Create and schedule a message browser on each method that, when used as the block argument to aBlock gives a true result. For example, SystemNavigation new browseAllSelect: [:method | method numLiterals > 10]." ^ self browseMessageList: (self allMethodsSelect: aBlock) name: 'selected messages'! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/29/2003 20:44'! browseAllSelect: aBlock name: aName autoSelect: autoSelectString "Create and schedule a message browser on each method that, when used as the block argument to aBlock gives a true result. Do not return an #DoIt traces." "self new browseAllSelect: [:method | method numLiterals > 10] name: 'Methods with more than 10 literals' autoSelect: 'isDigit'" ^ self browseMessageList: (self allMethodsNoDoitsSelect: aBlock) name: aName autoSelect: autoSelectString! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 08:53'! browseAllStoresInto: instVarName from: aClass "Create and schedule a Message Set browser for all the receiver's methods or any methods of a subclass/superclass that refer to the instance variable name." "self new browseAllStoresInto: 'contents' from: Collection." | coll | coll _ OrderedCollection new. Cursor wait showWhile: [ aClass withAllSubAndSuperclassesDo: [:class | (class whichSelectorsStoreInto: instVarName) do: [:sel | sel == #DoIt ifFalse: [ coll add: ( MethodReference new setStandardClass: class methodSymbol: sel ) ] ] ]. ]. ^ self browseMessageList: coll name: 'Stores into ' , instVarName autoSelect: instVarName! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 08:53'! browseClassCommentsWithString: aString "Smalltalk browseClassCommentsWithString: 'my instances' " "Launch a message list browser on all class comments containing aString as a substring." | caseSensitive suffix list | suffix _ (caseSensitive _ Sensor shiftPressed) ifTrue: [' (case-sensitive)'] ifFalse: [' (use shift for case-sensitive)']. list _ Set new. Cursor wait showWhile: [ Smalltalk allClassesDo: [:class | (class organization classComment asString findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ list add: ( MethodReference new setStandardClass: class methodSymbol: #Comment ) ] ] ]. ^ self browseMessageList: list asSortedCollection name: 'Class comments containing ' , aString printString , suffix autoSelect: aString! ! !SystemNavigation methodsFor: 'browse' stamp: 'md 10/22/2003 16:20'! browseClassVarRefs: aClass "Put up a menu offering all class variable names; if the user chooses one, open up a message-list browser on all methods that refer to the selected class variable" | lines labelStream vars allVars index owningClasses | lines _ OrderedCollection new. allVars _ OrderedCollection new. owningClasses _ OrderedCollection new. labelStream _ WriteStream on: (String new: 200). aClass withAllSuperclasses reverseDo: [:class | vars _ class classVarNames asSortedCollection. vars do: [:var | labelStream nextPutAll: var; cr. allVars add: var. owningClasses add: class]. vars isEmpty ifFalse: [lines add: allVars size]]. labelStream contents isEmpty ifTrue: [^Beeper beep]. "handle nil superclass better" labelStream skip: -1 "cut last CR". index _ (PopUpMenu labels: labelStream contents lines: lines) startUp. index = 0 ifTrue: [^ self]. self browseAllCallsOn: ((owningClasses at: index) classPool associationAt: (allVars at: index))! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 3/28/2003 18:49'! browseClassVariables: aClass aClass classPool inspectWithLabel: 'Class Variables in ' , aClass name! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 22:24'! browseClassesWithNamesContaining: aString caseSensitive: caseSensitive "Smalltalk browseClassesWithNamesContaining: 'eMorph' caseSensitive: true " "Launch a class-list list browser on all classes whose names containg aString as a substring." | suffix aList | suffix _ caseSensitive ifTrue: [' (case-sensitive)'] ifFalse: [' (use shift for case-sensitive)']. aList _ OrderedCollection new. Cursor wait showWhile: [Smalltalk allClassesDo: [:class | (class name includesSubstring: aString caseSensitive: caseSensitive) ifTrue: [aList add: class name]]]. aList size > 0 ifTrue: [ClassListBrowser new initForClassesNamed: aList asSet asSortedArray title: 'Classes whose names contain ' , aString , suffix]! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 16:08'! browseInstVarDefs: aClass "Copied from browseInstVarRefs. Should be consolidated some day. 7/29/96 di 7/30/96 sw: did the consolidation" "Change to use SystemNavigation 27 March 2003 sd" aClass chooseInstVarThenDo: [:aVar | self browseAllStoresInto: aVar from: aClass]! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 16:08'! browseInstVarRefs: aClass "1/16/96 sw: moved here from Browser so that it could be used from a variety of places. 7/30/96 sw: call chooseInstVarThenDo: to get the inst var choice" aClass chooseInstVarThenDo: [:aVar | self browseAllAccessesTo: aVar from: aClass]! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 09:18'! browseMessageList: messageList name: label "Create and schedule a MessageSet browser on messageList." ^ self browseMessageList: messageList name: label autoSelect: nil! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 08:48'! browseMessageList: messageList name: labelString autoSelect: autoSelectString | title aSize | "Create and schedule a MessageSet browser on the message list." messageList size = 0 ifTrue: [^ (PopUpMenu labels: ' OK ') startUpWithCaption: 'There are no ' , labelString]. title _ (aSize _ messageList size) > 1 ifFalse: [labelString] ifTrue: [ labelString, ' [', aSize printString, ']']. MessageSet openMessageList: messageList name: title autoSelect: autoSelectString! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 22:46'! browseMethodsWhoseNamesContain: aString "Launch a tool which shows all methods whose names contain the given string; case-insensitive. 1/16/1996 sw, at the dawn of Squeak: this was the classic implementation that provided the underpinning for the 'method names containing it' (cmd-shift-W) feature that has always been in Squeak -- the feature that later inspired the MethodFinder (aka SelectorBrowser). sw 7/27/2001: Switched to showing a MessageNames tool rather than a message-list browser, if in Morphic." | aList | Smalltalk isMorphic ifFalse: [aList _ Symbol selectorsContaining: aString. aList size > 0 ifTrue: [self browseAllImplementorsOfList: aList asSortedCollection title: 'Methods whose names contain ''', aString, '''']] ifTrue: [(MessageNames methodBrowserSearchingFor: aString) openInWorld] ! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/20/2003 14:11'! browseMethodsWithSourceString: aString "SystemNavigation new browseMethodsWithSourceString: 'SourceString'" "Launch a browser on all methods whose source code contains aString as a substring." | caseSensitive suffix | suffix _ (caseSensitive _ Sensor shiftPressed) ifTrue: [' (case-sensitive)'] ifFalse: [' (use shift for case-sensitive)']. ^ self browseMessageList: (self allMethodsWithSourceString: aString matchCase: caseSensitive) name: 'Methods containing ' , aString printString , suffix autoSelect: aString! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 22:28'! browseMethodsWithString: aString "Launch a browser on all methods that contain string literals with aString as a substring. The search is case-insensitive, unless the shift key is pressed, in which case the search is case-sensitive." 'string for testing'. ^ self browseMethodsWithString: aString matchCase: Sensor shiftPressed "SystemNavigation new browseMethodsWithString: 'Testing' matchCase: false" "SystemNavigation new browseMethodsWithString: 'Testing' matchCase: true"! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/16/2003 07:51'! browseMethodsWithString: aString matchCase: caseSensitive "Launch a browser on all methods that contain string literals with aString as a substring. Make the search case-sensitive or insensitive as dictated by the caseSensitive boolean parameter" self browseAllSelect: [:method | method hasLiteralSuchThat: [:lit | lit class == String and: [lit includesSubstring: aString caseSensitive: caseSensitive]]] name: 'Methods with string ', aString printString, (caseSensitive ifTrue: [' (case-sensitive)'] ifFalse: [' (case-insensitive)']) autoSelect: aString. ! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 4/15/2003 20:32'! browseObsoleteReferences "self new browseObsoleteReferences" | references | references _ OrderedCollection new. (LookupKey allSubInstances select: [:x | ((x value isKindOf: Behavior) and: ['AnOb*' match: x value name]) or: ['AnOb*' match: x value class name]]) do: [:x | references addAll: (self allCallsOn: x)]. self browseMessageList: references name: 'References to Obsolete Classes'! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 1/16/2004 21:09'! methodHierarchyBrowserForClass: aClass selector: sel "Create and schedule a message set browser on all implementors of the currently selected message selector. Do nothing if no message is selected." "SystemNavigation default methodHierarchyBrowserForClass: ParagraphEditor selector: #isControlActive" | list tab stab aClassNonMeta isMeta theClassOrMeta | aClass ifNil: [^ self]. sel ifNil: [^ self]. aClassNonMeta _ aClass theNonMetaClass. isMeta _ aClassNonMeta ~~ aClass. list _ OrderedCollection new. tab _ ''. aClass allSuperclasses reverseDo: [:cl | (cl includesSelector: sel) ifTrue: [list addLast: tab , cl name, ' ', sel]. tab _ tab , ' ']. aClassNonMeta allSubclassesWithLevelDo: [:cl :level | theClassOrMeta _ isMeta ifTrue: [cl class] ifFalse: [cl]. (theClassOrMeta includesSelector: sel) ifTrue: [stab _ ''. 1 to: level do: [:i | stab _ stab , ' ']. list addLast: tab , stab , theClassOrMeta name, ' ', sel]] startingLevel: 0. self browseMessageList: list name: 'Inheritance of ' , sel ! ! !SystemNavigation methodsFor: 'browse' stamp: 'sd 1/16/2004 21:13'! spawnHierarchyForClass: aClass selector: aSelector "Create and schedule a new class hierarchy browser on the requested class/selector." "SystemNavigation default spawnHierarchyForClass: SmallInteger selector: #hash" | newBrowser | (aClass == nil) ifTrue: [^ self]. (newBrowser _ Browser new) setClass: aClass selector: aSelector. newBrowser spawnHierarchy. ! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/17/2003 19:22'! allBehaviorsDo: aBlock "Evaluate the argument, aBlock, for each kind of Behavior in the system (that is, Object and its subclasses). ar 7/15/1999: The code below will not enumerate any obsolete or anonymous behaviors for which the following should be executed: Smalltalk allObjectsDo:[:obj| obj isBehavior ifTrue:[aBlock value: obj]]. but what follows is way faster than enumerating all objects." aBlock value: ProtoObject. ProtoObject allSubclassesDoGently: aBlock. "don't bring in ImageSegments" "Classes outside the ProtoObject hierarchy" Class subclassesDo: [:aClass | (aClass == ProtoObject class or: [aClass isInMemory not or: [aClass isMeta not]]) ifFalse: ["Enumerate the non-meta class and its subclasses" aBlock value: aClass soleInstance. aClass soleInstance allSubclassesDoGently: aBlock]].! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 11:48'! allCallsOn: aLiteral "Answer a Collection of all the methods that call on aLiteral even deeply embedded in literal array." "self new browseAllCallsOn: #open:label:." | aCollection special thorough aList byte | aCollection _ OrderedCollection new. special _ Smalltalk hasSpecialSelector: aLiteral ifTrueSetByte: [:b | byte _ b]. thorough _ (aLiteral isMemberOf: Symbol) and: ["Possibly search for symbols imbedded in literal arrays" Preferences thoroughSenders]. Cursor wait showWhile: [self allBehaviorsDo: [:class | aList _ thorough ifTrue: [class thoroughWhichSelectorsReferTo: aLiteral special: special byte: byte] ifFalse: [class whichSelectorsReferTo: aLiteral special: special byte: byte]. aList do: [:sel | sel == #DoIt ifFalse: [aCollection add: (MethodReference new setStandardClass: class methodSymbol: sel)]]]]. ^ aCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 3/28/2003 17:44'! allCallsOn: aSymbol from: aClass "Answer a SortedCollection of all the methods that call on aSymbol." | aSortedCollection special byte | aSortedCollection _ SortedCollection new. special _ aClass environment hasSpecialSelector: aSymbol ifTrueSetByte: [:b | byte _ b ]. aClass withAllSubclassesDo: [ :class | (class whichSelectorsReferTo: aSymbol special: special byte: byte) do: [:sel | sel == #DoIt ifFalse: [ aSortedCollection add: ( MethodReference new setStandardClass: class methodSymbol: sel ) ] ] ]. ^aSortedCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/17/2003 21:31'! allClasses "currently returns all the classes defined in Smalltalk but could be customized for dealing with environments and in such a case would return on really all the classes" ^ Smalltalk allClasses ! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/17/2003 21:31'! allClassesDo: aBlock "currently returns all the classes defined in Smalltalk but could be customized for dealing with environments and in such a case would work on really all the classes" ^ Smalltalk allClassesDo: aBlock ! ! !SystemNavigation methodsFor: 'query' stamp: 'nb 5/6/2003 16:57'! allClassesImplementing: aSelector "Answer an Array of all classes that implement the message aSelector." | aCollection | aCollection _ ReadWriteStream on: Array new. self allBehaviorsDo: [:class | (class includesSelector: aSelector) ifTrue: [aCollection nextPut: class]]. ^ aCollection contents! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 18:55'! allGlobalRefsWithout: classesAndMessagesPair "Answer a set of symbols that may be refs to Global names. In some sense we should only need the associations, but this will also catch, eg, HTML tag types. This method computes its result in the absence of specified classes and messages." "may be a problem if namespaces are introduced as for the moment only Smalltalk is queried. sd 29/4/03" | globalRefs absentClasses absentSelectors | globalRefs _ IdentitySet new: CompiledMethod instanceCount. absentClasses _ classesAndMessagesPair first. absentSelectors _ classesAndMessagesPair second. self flag: #shouldBeRewrittenUsingSmalltalkAllClassesDo:. "sd 29/04/03" Cursor execute showWhile: [Smalltalk classNames do: [:cName | ((absentClasses includes: cName) ifTrue: [{}] ifFalse: [{Smalltalk at: cName. (Smalltalk at: cName) class}]) do: [:cl | (absentSelectors isEmpty ifTrue: [cl selectors] ifFalse: [cl selectors copyWithoutAll: absentSelectors]) do: [:sel | "Include all capitalized symbols for good measure" (cl compiledMethodAt: sel) literals do: [:m | ((m isMemberOf: Symbol) and: [m size > 0 and: [m first isUppercase]]) ifTrue: [globalRefs add: m]. (m isMemberOf: Array) ifTrue: [m do: [:x | ((x isMemberOf: Symbol) and: [x size > 0 and: [x first isUppercase]]) ifTrue: [globalRefs add: x]]]. m isVariableBinding ifTrue: [m key ifNotNil: [globalRefs add: m key]]]]]]]. ^ globalRefs! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 18:55'! allImplementedMessagesWithout: classesAndMessagesPair "Answer a Set of all the messages that are implemented in the system, computed in the absence of the supplied classes and messages. Note this reports messages that are in the absent selectors set." | messages absentClasses | messages _ IdentitySet new: CompiledMethod instanceCount. absentClasses _ classesAndMessagesPair first. self flag: #shouldBeRewrittenUsingSmalltalkAllClassesDo:. "sd 29/04/03" Cursor execute showWhile: [Smalltalk classNames do: [:cName | ((absentClasses includes: cName) ifTrue: [{}] ifFalse: [{Smalltalk at: cName. (Smalltalk at: cName) class}]) do: [:cl | messages addAll: cl selectors]]]. ^ messages! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/23/2003 22:31'! allImplementorsOf: aSelector "Answer a SortedCollection of all the methods that implement the message aSelector." | aCollection | aCollection _ SortedCollection new. Cursor wait showWhile: [self allBehaviorsDo: [:class | (class includesSelector: aSelector) ifTrue: [aCollection add: (MethodReference new setStandardClass: class methodSymbol: aSelector)]]]. ^ aCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/20/2003 14:14'! allImplementorsOf: aSelector localTo: aClass "Answer a SortedCollection of all the methods that implement the message aSelector in, above, or below the given class." | aSet cls | aSet _ Set new. cls _ aClass theNonMetaClass. Cursor wait showWhile: [ cls withAllSuperAndSubclassesDoGently: [:class | (class includesSelector: aSelector) ifTrue: [aSet add: class name, ' ', aSelector]]. cls class withAllSuperAndSubclassesDoGently: [:class | (class includesSelector: aSelector) ifTrue: [aSet add: class name, ' ', aSelector]] ]. ^aSet asSortedCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 20:42'! allMethodsNoDoitsSelect: aBlock "Like allSelect:, but strip out Doits" | aCollection | aCollection _ SortedCollection new. Cursor execute showWhile: [self allBehaviorsDo: [:class | class selectorsDo: [:sel | (sel ~~ #DoIt and: [aBlock value: (class compiledMethodAt: sel)]) ifTrue: [aCollection add: (MethodReference new setStandardClass: class methodSymbol: sel)]]]]. ^ aCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 20:41'! allMethodsSelect: aBlock "Answer a SortedCollection of each method that, when used as the block argument to aBlock, gives a true result." | aCollection | aCollection _ SortedCollection new. Cursor execute showWhile: [self allBehaviorsDo: [:class | class selectorsDo: [:sel | (aBlock value: (class compiledMethodAt: sel)) ifTrue: [aCollection add: (MethodReference new setStandardClass: class methodSymbol: sel)]]]]. ^ aCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/20/2003 14:11'! allMethodsWithSourceString: aString matchCase: caseSensitive "Answer a SortedCollection of all the methods that contain, in source code, aString as a substring. Search the class comments also" | list classCount adder | list _ Set new. adder _ [ :mrClass :mrSel | list add: ( MethodReference new setStandardClass: mrClass methodSymbol: mrSel)]. 'Searching all source code...' displayProgressAt: Sensor cursorPoint from: 0 to: Smalltalk classNames size during: [:bar | classCount _ 0. Smalltalk allClassesDo: [:class | bar value: (classCount _ classCount + 1). (Array with: class with: class class) do: [:cl | cl selectorsDo: [:sel | ((cl sourceCodeAt: sel) findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ sel == #DoIt ifFalse: [adder value: cl value: sel]]]. (cl organization classComment asString findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ adder value: cl value: #Comment]. ]]]. ^ list asSortedCollection! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 5/5/2003 09:18'! allSelectorsWithAnyImplementorsIn: selectorList "Answer the subset of the given list which represent method selectors which have at least one implementor in the system." | good | good _ OrderedCollection new. self allBehaviorsDo: [:class | selectorList do: [:aSelector | (class includesSelector: aSelector) ifTrue: [good add: aSelector]]]. ^ good asSet asSortedArray" SystemNavigation new selectorsWithAnyImplementorsIn: #( contents contents: nuts) "! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 20:12'! allSentMessages "Answer the set of selectors which are sent somewhere in the system." ^ self allSentMessagesWithout: {{}. {}}! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 19:10'! allSentMessagesWithout: classesAndMessagesPair "Answer the set of selectors which are sent somewhere in the system, computed in the absence of the supplied classes and messages." | sent absentClasses absentSelectors | sent _ IdentitySet new: CompiledMethod instanceCount. absentClasses _ classesAndMessagesPair first. absentSelectors _ classesAndMessagesPair second. self flag: #shouldBeRewrittenUsingSmalltalkAllClassesDo:. "sd 29/04/03" Cursor execute showWhile: [Smalltalk classNames do: [:cName | ((absentClasses includes: cName) ifTrue: [{}] ifFalse: [{Smalltalk at: cName. (Smalltalk at: cName) class}]) do: [:cl | (absentSelectors isEmpty ifTrue: [cl selectors] ifFalse: [cl selectors copyWithoutAll: absentSelectors]) do: [:sel | "Include all sels, but not if sent by self" (cl compiledMethodAt: sel) literals do: [:m | (m isMemberOf: Symbol) ifTrue: ["might be sent" m == sel ifFalse: [sent add: m]]. (m isMemberOf: Array) ifTrue: ["might be performed" m do: [:x | (x isMemberOf: Symbol) ifTrue: [x == sel ifFalse: [sent add: x]]]]]]]]. "The following may be sent without being in any literal frame" 1 to: Smalltalk specialSelectorSize do: [:index | sent add: (Smalltalk specialSelectorAt: index)]]. Smalltalk presumedSentMessages do: [:sel | sent add: sel]. ^ sent! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 20:12'! allUnSentMessages "SystemNavigation new allUnSentMessages" "Answer the set of selectors that are implemented by some object in the system but not sent by any." ^ self allUnSentMessagesWithout: {{}. {}}! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 20:13'! allUnSentMessagesIn: selectorSet "Answer the subset of selectorSet which are not sent anywhere in the system. " ^ selectorSet copyWithoutAll: self allSentMessages! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 19:19'! allUnSentMessagesWithout: classesAndMessagesPair "Answer the set of selectors that are implemented but not sent, computed in the absence of the supplied classes and messages." ^ (self allImplementedMessagesWithout: classesAndMessagesPair) copyWithoutAll: (self allSentMessagesWithout: classesAndMessagesPair)! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 13:07'! allUnreferencedClassVariablesOf: aClass "Answer a list of the names of all the receiver's unreferenced class vars, including those defined in superclasses" | aList | aList _ OrderedCollection new. aClass withAllSuperclasses reverseDo: [:aSuperClass | aSuperClass classVarNames do: [:var | (self allCallsOn: (aSuperClass classPool associationAt: var)) isEmpty ifTrue: [aList add: var]]]. ^ aList! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/29/2003 19:06'! allUnusedClassesWithout: classesAndMessagesPair "Enumerates all classes in the system and returns a list of those that are apparently unused. A class is considered in use if it (a) has subclasses or (b) is referred to by some method or (c) has its name in use as a literal." "SystemNavigation new unusedClasses" | unused cl | unused _ Smalltalk classNames asIdentitySet copyWithoutAll: (self allGlobalRefsWithout: classesAndMessagesPair). ^ unused reject: [:cName | cl _ Smalltalk at: cName. cl subclasses isEmpty not or: [cl inheritsFrom: FileDirectory]]! ! !SystemNavigation methodsFor: 'query' stamp: 'sd 4/20/2003 14:27'! numberOfImplementorsOf: aSelector "Answer a count of the implementors of the given selector found in the system" "self new numberOfImplementorsOf: #contents. self new numberOfImplementorsOf: #nobodyImplementsThis. self new numberOfimplementorsOf: #numberOfImplementorsOf:." | aCount | aCount _ 0. self allBehaviorsDo: [:class | (class includesSelector: aSelector) ifTrue: [aCount _ aCount + 1]]. ^ aCount! ! !SystemNavigation methodsFor: 'ui' stamp: 'sd 4/29/2003 11:59'! confirmRemovalOf: aSelector on: aClass "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." | count aMenu answer caption allCalls | allCalls _ self allCallsOn: aSelector. (count _ allCalls size) == 0 ifTrue: [^ 1]. "no senders -- let the removal happen without warning" count == 1 ifTrue: [(allCalls first actualClass == aClass and: [allCalls first methodSymbol == aSelector]) ifTrue: [^ 1]]. "only sender is itself" aMenu _ PopUpMenu labels: 'Remove it Remove, then browse senders Don''t remove, but show me those senders Forget it -- do nothing -- sorry I asked'. caption _ 'This message has ' , count printString , ' sender'. count > 1 ifTrue: [caption _ caption copyWith: $s]. answer _ aMenu startUpWithCaption: caption. answer == 3 ifTrue: [self browseMessageList: allCalls name: 'Senders of ' , aSelector autoSelect: aSelector keywords first]. answer == 0 ifTrue: [answer _ 3]. "If user didn't answer, treat it as cancel" ^ answer min: 3! ! !SystemNavigation methodsFor: 'ui' stamp: 'sd 4/15/2003 15:34'! showMenuOf: selectorCollection withFirstItem: firstItem ifChosenDo: choiceBlock "Show a sorted menu of the given selectors, preceded by firstItem, and all abbreviated to 40 characters. Evaluate choiceBlock if a message is chosen." ^ self showMenuOf: selectorCollection withFirstItem: firstItem ifChosenDo: choiceBlock withCaption: nil! ! !SystemNavigation methodsFor: 'ui' stamp: 'sd 4/15/2003 15:35'! showMenuOf: selectorCollection withFirstItem: firstItem ifChosenDo: choiceBlock withCaption: aCaption "Show a sorted menu of the given selectors, preceded by firstItem, and all abbreviated to 40 characters. Use aCaption as the menu title, if it is not nil. Evaluate choiceBlock if a message is chosen." | index menuLabels sortedList aMenu | sortedList _ selectorCollection asSortedCollection. menuLabels _ String streamContents: [:strm | strm nextPutAll: (firstItem contractTo: 40). sortedList do: [:sel | strm cr; nextPutAll: (sel contractTo: 40)]]. aMenu _ PopUpMenu labels: menuLabels lines: #(1). index _ aCaption ifNotNil: [aMenu startUpWithCaption: aCaption] ifNil: [aMenu startUp]. index = 1 ifTrue: [choiceBlock value: firstItem]. index > 1 ifTrue: [choiceBlock value: (sortedList at: index - 1)]! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:47'! browseClass: aBehavior | targetClass | self browserClass ifNil: [self error: 'No browser installed:']. targetClass := aBehavior isMeta ifTrue: [aBehavior theNonMetaClass] ifFalse: [aBehavior ]. self browserClass newOnClass: targetClass! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:51'! browseHierarchy: aBehavior | targetClass | self hierarchyBrowserClass ifNil: [self error: 'No hierarchy browser installed:']. targetClass := aBehavior isMeta ifTrue: [aBehavior theNonMetaClass] ifFalse: [aBehavior ]. self hierarchyBrowserClass newFor: targetClass! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:46'! browserClass browserClass ifNil: [browserClass := self defaultBrowserClass]. ^browserClass! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:50'! defaultBrowserClass ^self class environment at: #Browser ifAbsent:[]! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:49'! defaultHierarchyBrowserClass ^self class environment at: #HierarchyBrowser ifAbsent:[]! ! !SystemNavigation methodsFor: '*tools-browser' stamp: 'mu 3/11/2004 15:50'! hierarchyBrowserClass hierarchyBrowserClass ifNil: [hierarchyBrowserClass := self defaultHierarchyBrowserClass]. ^hierarchyBrowserClass! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SystemNavigation class instanceVariableNames: ''! !SystemNavigation class methodsFor: 'as yet unclassified' stamp: 'dvf 8/23/2003 12:25'! default Default isNil ifTrue: [Default _ self new]. ^Default! ! Categorizer subclass: #SystemOrganizer instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Support'! !SystemOrganizer commentStamp: '<historical>' prior: 0! 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.! !SystemOrganizer methodsFor: 'fileIn/Out' stamp: 'di 8/16/2000 10:03'! fileOut "SystemOrganization fileOut" (FileStream newFileNamed: (FileDirectory default nextNameFor: 'SystemOrganization' extension: 'st')) nextPutAll: 'SystemOrganization changeFromCategorySpecs: #('; cr; print: SystemOrganization; "ends with a cr" nextPutAll: ')!!'; cr; close.! ! !SystemOrganizer methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 19:01'! fileOutCategory: category "Store on the file named category (a string) concatenated with '.st' all the classes associated with the category." ^ self fileOutCategory: category asHtml: false! ! !SystemOrganizer methodsFor: 'fileIn/Out' stamp: 'jf 2/7/2004 17:24'! fileOutCategory: category asHtml: useHtml "FileOut all the classes in the named system category." | fileStream | fileStream _ useHtml ifTrue: [(FileStream newFileNamed: category asFileName, '.html') asHtml] ifFalse: [FileStream newFileNamed: category asFileName , '.st']. self fileOutCategory: category on: fileStream initializing: true. fileStream close! ! !SystemOrganizer methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:28'! fileOutCategory: category on: aFileStream "Store on the file associated with aFileStream, all the classes associated with the category and any requested shared pools." ^self fileOutCategory: category on: aFileStream initializing: true! ! !SystemOrganizer methodsFor: 'fileIn/Out' stamp: 'ar 12/22/1999 17:28'! fileOutCategory: category on: aFileStream initializing: aBool "Store on the file associated with aFileStream, all the classes associated with the category and any requested shared pools." | first poolSet tempClass classes | classes _ (self superclassOrder: category). poolSet _ Set new. classes do: [:class | class sharedPools do: [:eachPool | poolSet add: eachPool]]. poolSet size > 0 ifTrue: [tempClass _ Class new. tempClass shouldFileOutPools ifTrue: [poolSet _ poolSet select: [:aPool | tempClass shouldFileOutPool: (Smalltalk keyAtIdentityValue: aPool)]. poolSet do: [:aPool | tempClass fileOutPool: aPool onFileStream: aFileStream]]]. first _ true. classes do: [:class | first ifTrue: [first _ false] ifFalse: [aFileStream cr; nextPut: Character newPage; cr]. class fileOutOn: aFileStream moveSource: false toFile: 0 initializing: false]. aBool ifTrue:[classes do:[:cls| cls fileOutInitializerOn: aFileStream]].! ! !SystemOrganizer methodsFor: 'fileIn/Out'! superclassOrder: category "Answer an OrderedCollection containing references to the classes in the category whose name is the argument, category (a string). The classes are ordered with superclasses first so they can be filed in." | list | list _ (self listAtCategoryNamed: category asSymbol) collect: [:title | Smalltalk at: title]. ^ChangeSet superclassOrder: list! ! !SystemOrganizer methodsFor: 'remove' stamp: 'di 3/3/2001 16:07'! categoriesMatching: matchString "Return all matching categories" ^ self categories select: [:c | matchString match: c]! ! !SystemOrganizer methodsFor: 'remove' stamp: 'di 3/3/2001 16:08'! removeCategoriesMatching: matchString "Remove all matching categories with their classes" (self categoriesMatching: matchString) do: [:c | self removeSystemCategory: c]! ! !SystemOrganizer methodsFor: 'remove' stamp: 'jm 5/20/1998 19:38'! removeMissingClasses "Remove any class names that are no longer in the Smalltalk dictionary. Used for cleaning up after garbage collecting user-generated classes." "SystemOrganization removeMissingClasses" elementArray copy do: [:el | (Smalltalk includesKey: el) ifFalse: [self removeElement: el]]. ! ! !SystemOrganizer methodsFor: 'remove' stamp: 'jf 8/1/2003 09:02'! removeSystemCategory: category "remove all the classes associated with the category" (self superclassOrder: category) reverseDo: [:class | class removeFromSystem]. self removeCategory: category. ! ! !SystemOrganizer methodsFor: 'private' stamp: 'rw 7/31/2003 17:23'! ifClassOrganizerDo: aBlock "Do nothing, since this is not a class organizer"! ! Object subclass: #SystemVersion instanceVariableNames: 'version date highestUpdate updates' classVariableNames: 'Current' poolDictionaries: '' category: 'System-Support'! !SystemVersion methodsFor: 'accessing'! date ^date! ! !SystemVersion methodsFor: 'accessing' stamp: 'mir 5/1/2001 18:19'! datedVersion "Answer the version of this release." ^ self version asString , ' of ' , self date printString! ! !SystemVersion methodsFor: 'accessing' stamp: 'mir 3/29/2001 18:03'! highestUpdate | sortedUpdates | highestUpdate ifNil: [ sortedUpdates _ self updates asSortedCollection. highestUpdate _ (sortedUpdates isEmpty ifTrue: [0] ifFalse: [sortedUpdates last])]. ^highestUpdate! ! !SystemVersion methodsFor: 'accessing'! unregisterUpdate: update self updates remove: update ifAbsent: []! ! !SystemVersion methodsFor: 'accessing'! updates ^updates! ! !SystemVersion methodsFor: 'accessing'! version ^version! ! !SystemVersion methodsFor: 'initialize'! initialize version _ 'No version set'. date _ Date today. updates _ Set new. ! ! !SystemVersion methodsFor: 'printing' stamp: 'mir 5/1/2001 18:20'! printOn: stream stream nextPutAll: self datedVersion; nextPutAll: ' update ' , self highestUpdate printString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! SystemVersion class instanceVariableNames: ''! !SystemVersion class methodsFor: 'accessing'! current Current ifNil: [Current _ SystemVersion new]. ^Current! ! VariableNode subclass: #TempVariableNode instanceVariableNames: 'isAnArg hasRefs hasDefs scope' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !TempVariableNode commentStamp: '<historical>' prior: 0! I am a parse tree leaf representing a temporary variable! !TempVariableNode methodsFor: 'initialize-release'! isArg: aBoolean isAnArg _ aBoolean. isAnArg ifTrue: [hasDefs _ true]! ! !TempVariableNode methodsFor: 'initialize-release'! name: varName index: i type: type scope: level "Only used for initting temporary variables" name _ varName. self key: varName index: i type: type. isAnArg _ hasDefs _ hasRefs _ false. scope _ level! ! !TempVariableNode methodsFor: 'initialize-release'! nowHasDef hasDefs _ true! ! !TempVariableNode methodsFor: 'initialize-release'! nowHasRef hasRefs _ true! ! !TempVariableNode methodsFor: 'initialize-release'! scope: level "Note scope of temporary variables. Currently only the following distinctions are made: 0 outer level: args and user-declared temps 1 block args and doLimiT temps -1 a block temp that is no longer active -2 a block temp that held limit of to:do:" scope _ level! ! !TempVariableNode methodsFor: 'testing'! assignmentCheck: encoder at: location isAnArg ifTrue: [^ location] ifFalse: [^ -1]! ! !TempVariableNode methodsFor: 'testing'! isTemp ^ true! ! !TempVariableNode methodsFor: 'testing'! isUndefTemp ^ hasDefs not! ! !TempVariableNode methodsFor: 'testing'! isUnusedTemp ^ hasRefs not! ! !TempVariableNode methodsFor: 'testing'! scope ^ scope! ! !TempVariableNode methodsFor: 'printing' stamp: 'di 4/5/2000 15:11'! printOn: aStream indent: level aStream withStyleFor: #temporaryVariable do: [aStream nextPutAll: name]! ! ArrayedCollection subclass: #Text instanceVariableNames: 'string runs' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Collections-Text'! !Text commentStamp: '<historical>' prior: 0! I represent a character 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. A Text associates a set of TextAttributes with each character in its character string. These attributes may be font numbers, emphases such as bold or italic, or hyperling actions. Font numbers are interpreted relative to whatever textStyle appears, along with the text, in a Paragraph. Since most characters have the same attributes as their neighbors, the attributes are stored in a RunArray for efficiency. Each of my instances has string a String runs a RunArray! ]style[(148 9 97 13 237 9 163 6 10 8)f1,f1LTextStyle Comment;,f1,f1LTextAttribute Hierarchy;,f1,f1LParagraph Comment;,f1,f1LString Comment;,f1,f1LRunArray Comment;! !Text methodsFor: 'accessing' stamp: 'tk 9/4/2000 16:04'! append: stringOrText self replaceFrom: string size + 1 to: string size with: stringOrText! ! !Text methodsFor: 'accessing'! at: index ^string at: index! ! !Text methodsFor: 'accessing'! at: index put: character ^string at: index put: character! ! !Text methodsFor: 'accessing' stamp: 'gm 2/15/2003 14:59'! embeddedMorphs "return the list of morphs embedded in me" | morphs | morphs := IdentitySet new. runs withStartStopAndValueDo: [:start :stop :attribs | attribs do: [:attrib | attrib anchoredMorph ifNotNil: [morphs add: attrib anchoredMorph]]]. ^morphs select: [:m | m isMorph]! ! !Text methodsFor: 'accessing' stamp: 'gm 2/15/2003 14:59'! embeddedMorphsFrom: start to: stop "return the list of morphs embedded in me" | morphs | morphs := IdentitySet new. runs runsFrom: start to: stop do: [:attribs | attribs do: [:attr | attr anchoredMorph ifNotNil: [morphs add: attr anchoredMorph]]]. ^morphs select: [:m | m isMorph]! ! !Text methodsFor: 'accessing'! findString: aString startingAt: start "Answer the index of subString within the receiver, starting at index start. If the receiver does not contain subString, answer 0." ^string findString: aString asString startingAt: start! ! !Text methodsFor: 'accessing' stamp: 'di 11/23/1998 11:53'! findString: aString startingAt: start caseSensitive: caseSensitive "Answer the index of subString within the receiver, starting at index start. If the receiver does not contain subString, answer 0." ^string findString: aString asString startingAt: start caseSensitive: caseSensitive! ! !Text methodsFor: 'accessing' stamp: 'tk 9/6/2000 12:33'! lineCount ^ string lineCount! ! !Text methodsFor: 'accessing' stamp: 'ar 12/27/2001 00:03'! prepend: stringOrText self replaceFrom: 1 to: 0 with: stringOrText! ! !Text methodsFor: 'accessing' stamp: 'BG 6/8/2003 16:18'! rangeOf: attribute startingAt: index "Answer an interval that gives the range of attribute at index position index. An empty interval with start value index is returned when the attribute is not present at position index. " ^string size = 0 ifTrue: [index to: index - 1] ifFalse: [runs rangeOf: attribute startingAt: index]! ! !Text methodsFor: 'accessing' stamp: 'md 12/12/2003 17:03'! rangeOf: attribute startingAt: index forStyle: aTextStyle "aTextStyle is not really needed, it is kept for compatibility with an earlier method version " self deprecated: 'Use Text>>rangeOf:startingAt: instead.'. ^self rangeOf: attribute startingAt: index! ! !Text methodsFor: 'accessing' stamp: 'tk 12/30/97 07:17'! replaceFrom: start to: stop with: aText | txt | txt _ aText asText. "might be a string" string _ string copyReplaceFrom: start to: stop with: txt string. runs _ runs copyReplaceFrom: start to: stop with: txt runs! ! !Text methodsFor: 'accessing'! size ^string size! ! !Text methodsFor: 'accessing'! string "Answer the string representation of the receiver." ^string! ! !Text methodsFor: 'comparing' stamp: 'tk 10/19/2001 17:48'! = other "Am I equal to the other Text or String? ***** Warning ***** Two Texts are considered equal if they have the same characters in them. They might have completely different emphasis, fonts, sizes, text actions, or embedded morphs. If you need to find out if one is a true copy of the other, you must do (text1 = text2 and: [text1 runs = text2 runs])." other isText ifTrue: ["This is designed to run fast even for megabytes" ^ string == other string or: [string = other string]]. other isString ifTrue: [^ string == other or: [string = other]]. ^ false! ! !Text methodsFor: 'comparing' stamp: 'tk 10/17/2001 14:12'! hash "#hash is implemented, because #= is implemented. We are now equal to a string with the same characters. Hash must reflect that." ^ string hash! ! !Text methodsFor: 'comparing' stamp: 'tk 9/6/2000 11:59'! howManyMatch: aString ^ self string howManyMatch: aString! ! !Text methodsFor: 'comparing'! isText ^ true! ! !Text methodsFor: 'copying'! copy ^ self class new setString: string copy setRuns: runs copy ! ! !Text methodsFor: 'copying'! copyFrom: start to: stop "Answer a copied subrange of the receiver." | realStart realStop | stop > self size ifTrue: [realStop _ self size] "handle selection at end of string" ifFalse: [realStop _ stop]. start < 1 ifTrue: [realStart _ 1] "handle selection before start of string" ifFalse: [realStart _ start]. ^Text string: (string copyFrom: realStart to: realStop) runs: (runs copyFrom: realStart to: realStop)! ! !Text methodsFor: 'copying'! copyReplaceFrom: start to: stop with: aText ^self shallowCopy replaceFrom: start to: stop with: aText! ! !Text methodsFor: 'copying' stamp: 'tk 1/7/98 10:58'! copyReplaceTokens: oldSubstring with: newSubstring "Replace all occurrences of oldSubstring that are surrounded by non-alphanumeric characters" ^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: true "'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Snick'"! ! !Text methodsFor: 'copying' stamp: 'di 11/9/97 17:13'! deepCopy ^ self copy "Both string and runs are assumed to be read-only"! ! !Text methodsFor: 'converting'! asDisplayText "Answer a DisplayText whose text is the receiver." ^DisplayText text: self! ! !Text methodsFor: 'converting'! asNumber "Answer the number created by interpreting the receiver as the textual representation of a number." ^string asNumber! ! !Text methodsFor: 'converting'! asParagraph "Answer a Paragraph whose text is the receiver." ^Paragraph withText: self! ! !Text methodsFor: 'converting'! asString "Answer a String representation of the textual receiver." ^string! ! !Text methodsFor: 'converting' stamp: 'RAA 5/28/2001 06:19'! asStringOrText "Answer the receiver itself." ^self! ! !Text methodsFor: 'converting'! asText "Answer the receiver itself." ^self! ! !Text methodsFor: 'converting' stamp: 'ls 7/14/1998 03:20'! asUrlRelativeTo: aUrl ^self asString asUrlRelativeTo: aUrl! ! !Text methodsFor: 'converting' stamp: 'bf 3/9/2000 18:25'! isoToSqueak ^ self class new setString: string isoToSqueak setRuns: runs copy! ! !Text methodsFor: 'converting' stamp: 'ar 12/17/2001 00:38'! removeAttributesThat: removalBlock replaceAttributesThat: replaceBlock by: convertBlock "Enumerate all attributes in the receiver. Remove those passing removalBlock and replace those passing replaceBlock after converting it through convertBlock" | added removed new | "Deliberately optimized for the no-op default." added _ removed _ nil. runs withStartStopAndValueDo: [ :start :stop :attribs | attribs do: [ :attrib | (removalBlock value: attrib) ifTrue:[ removed ifNil:[removed _ WriteStream on: #()]. removed nextPut: {start. stop. attrib}. ] ifFalse:[ (replaceBlock value: attrib) ifTrue:[ removed ifNil:[removed _ WriteStream on: #()]. removed nextPut: {start. stop. attrib}. new _ convertBlock value: attrib. added ifNil:[added _ WriteStream on: #()]. added nextPut: {start. stop. new}. ]. ]. ]. ]. (added == nil and:[removed == nil]) ifTrue:[^self]. "otherwise do the real work" removed ifNotNil:[removed contents do:[:spec| self removeAttribute: spec last from: spec first to: spec second]]. added ifNotNil:[added contents do:[:spec| self addAttribute: spec last from: spec first to: spec second]].! ! !Text methodsFor: 'converting' stamp: 'dvf 10/1/2003 02:58'! replaceFrom: start to: stop with: replacement startingAt: repStart "This destructively replaces elements from start to stop in the receiver starting at index, repStart, in replacementCollection. Do it to both the string and the runs." | rep newRepRuns | rep _ replacement asText. "might be a string" string replaceFrom: start to: stop with: rep string startingAt: repStart. newRepRuns _ rep runs copyFrom: repStart to: repStart + stop - start. runs _ runs copyReplaceFrom: start to: stop with: newRepRuns! ! !Text methodsFor: 'converting' stamp: 'BG 6/8/2003 16:38'! reversed "Answer a copy of the receiver with element order reversed." ^ self class string: string reversed runs: runs reversed. " It is assumed that self size = runs size holds. "! ! !Text methodsFor: 'converting' stamp: 'bf 3/9/2000 18:25'! squeakToIso ^ self class new setString: string squeakToIso setRuns: runs copy! ! !Text methodsFor: 'converting' stamp: 'nk 9/16/2003 16:46'! withSqueakLineEndings "Answer a copy of myself in which all sequences of <CR><LF> or <LF> have been changed to <CR>" | newText | (string includes: Character lf) ifFalse: [ ^self copy ]. newText _ self copyReplaceAll: String crlf with: String cr asTokens: false. (newText asString includes: Character lf) ifFalse: [ ^newText ]. ^newText copyReplaceAll: String lf with: String cr asTokens: false.! ! !Text methodsFor: 'emphasis'! addAttribute: att ^ self addAttribute: att from: 1 to: self size! ! !Text methodsFor: 'emphasis'! addAttribute: att from: start to: stop "Set the attribute for characters in the interval start to stop." runs _ runs copyReplaceFrom: start to: stop with: ((runs copyFrom: start to: stop) mapValues: [:attributes | Text addAttribute: att toArray: attributes]) ! ! !Text methodsFor: 'emphasis' stamp: 'ar 12/17/2001 23:48'! alignmentAt: characterIndex ifAbsent: aBlock | attributes emph | self size = 0 ifTrue: [^aBlock value]. emph _ nil. attributes _ runs at: characterIndex. attributes do:[:att | (att isKindOf: TextAlignment) ifTrue:[emph _ att]]. ^ emph ifNil: aBlock ifNotNil:[emph alignment]! ! !Text methodsFor: 'emphasis'! allBold "Force this whole text to be bold." string size = 0 ifTrue: [^self]. self makeBoldFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'sw 12/7/1999 12:30'! attributesAt: characterIndex "Answer the code for characters in the run beginning at characterIndex." "NB: no senders any more (supplanted by #attributesAt:forStyle: but retained for the moment in order not to break user code that may exist somewhere that still calls this" | attributes | self size = 0 ifTrue: [^ Array with: (TextFontChange new fontNumber: 1)]. "null text tolerates access" attributes _ runs at: characterIndex. ^ attributes! ! !Text methodsFor: 'emphasis' stamp: 'ar 12/17/2001 01:17'! attributesAt: characterIndex do: aBlock "Answer the code for characters in the run beginning at characterIndex." "NB: no senders any more (supplanted by #attributesAt:forStyle: but retained for the moment in order not to break user code that may exist somewhere that still calls this" self size = 0 ifTrue:[^self]. (runs at: characterIndex) do: aBlock! ! !Text methodsFor: 'emphasis' stamp: 'sw 12/7/1999 11:32'! attributesAt: characterIndex forStyle: aTextStyle "Answer the code for characters in the run beginning at characterIndex." | attributes | self size = 0 ifTrue: [^ Array with: (TextFontChange new fontNumber: aTextStyle defaultFontIndex)]. "null text tolerates access" attributes _ runs at: characterIndex. ^ attributes! ! !Text methodsFor: 'emphasis' stamp: 'di 4/1/1999 15:17'! emphasisAt: characterIndex "Answer the fontfor characters in the run beginning at characterIndex." | attributes emph | self size = 0 ifTrue: [^ 0]. "null text tolerates access" emph _ 0. attributes _ runs at: characterIndex. attributes do: [:att | emph _ emph bitOr: att emphasisCode]. ^ emph ! ! !Text methodsFor: 'emphasis' stamp: 'di 11/10/97 13:36'! find: attribute "Return the first interval over which this attribute applies" | begin end | begin _ 0. runs withStartStopAndValueDo: [:start :stop :attributes | (attributes includes: attribute) ifTrue: [begin = 0 ifTrue: [begin _ start]. end _ stop] ifFalse: [begin > 0 ifTrue: [^ begin to: end]]]. begin > 0 ifTrue: [^ begin to: end]. ^ nil! ! !Text methodsFor: 'emphasis' stamp: 'sw 12/7/1999 10:58'! fontAt: characterIndex withStyle: aTextStyle "Answer the fontfor characters in the run beginning at characterIndex." | attributes font | self size = 0 ifTrue: [^ aTextStyle defaultFont]. "null text tolerates access" attributes _ runs at: characterIndex. font _ aTextStyle defaultFont. "default" attributes do: [:att | att forFontInStyle: aTextStyle do: [:f | font _ f]]. ^ font! ! !Text methodsFor: 'emphasis'! fontNumberAt: characterIndex "Answer the fontNumber for characters in the run beginning at characterIndex." | attributes fontNumber | self size = 0 ifTrue: [^1]. "null text tolerates access" attributes _ runs at: characterIndex. fontNumber _ 1. attributes do: [:att | (att isMemberOf: TextFontChange) ifTrue: [fontNumber _ att fontNumber]]. ^ fontNumber ! ! !Text methodsFor: 'emphasis'! makeBoldFrom: start to: stop ^ self addAttribute: TextEmphasis bold from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ar 6/28/2003 00:06'! makeSelectorBold "For formatting Smalltalk source code, set the emphasis of that portion of the receiver's string that parses as a message selector to be bold." | parser i | string size = 0 ifTrue: [^ self]. i _ 0. [(string at: (i _ i + 1)) isSeparator] whileTrue. (string at: i) = $[ ifTrue: [^ self]. "block, no selector" (parser _ Compiler parserClass new) parseSelector: string. self makeBoldFrom: 1 to: (parser endOfLastToken min: string size)! ! !Text methodsFor: 'emphasis' stamp: 'sma 2/5/2000 12:03'! makeSelectorBoldIn: aClass "For formatting Smalltalk source code, set the emphasis of that portion of the receiver's string that parses as a message selector to be bold." | parser | string size = 0 ifTrue: [^self]. (parser _ aClass parserClass new) parseSelector: string. self makeBoldFrom: 1 to: (parser endOfLastToken min: string size)! ! !Text methodsFor: 'emphasis'! removeAttribute: att from: start to: stop "Remove the attribute over the interval start to stop." runs _ runs copyReplaceFrom: start to: stop with: ((runs copyFrom: start to: stop) mapValues: [:attributes | attributes copyWithout: att]) ! ! !Text methodsFor: 'emphasis'! runLengthFor: characterIndex "Answer the count of characters remaining in run beginning with characterIndex." ^runs runLengthAt: characterIndex! ! !Text methodsFor: 'printing' stamp: 'sma 6/1/2000 09:49'! printOn: aStream self printNameOn: aStream. aStream nextPutAll: ' for '; print: string! ! !Text methodsFor: 'printing'! storeOn: aStream aStream nextPutAll: '(Text string: '; store: string; nextPutAll: ' runs: '; store: runs; nextPut: $)! ! !Text methodsFor: 'private'! runs ^runs! ! !Text methodsFor: 'private'! setString: aString setRuns: anArray string _ aString. runs _ anArray! ! !Text methodsFor: 'private' stamp: 'tk 12/16/97 14:14'! setString: aString setRunsChecking: aRunArray "Check runs and do the best you can to make them fit..." string _ aString. "check the runs" aRunArray ifNil: [^ aString asText]. (aRunArray isKindOf: RunArray) ifFalse: [^ aString asText]. aRunArray runs size = aRunArray values size ifFalse: [^ aString asText]. (aRunArray values includes: #()) ifTrue: [^ aString asText]. "not allowed?" aRunArray size = aString size ifFalse: [^ aString asText]. runs _ aRunArray.! ! !Text methodsFor: 'attributes' stamp: 'tk 2/27/2001 08:20'! askIfAddStyle: priorMethod req: requestor "Ask the user if we have a complex style (i.e. bold) for the first time" | tell answ old | (Preferences browseWithPrettyPrint and: [Preferences colorWhenPrettyPrinting]) ifTrue: [self couldDeriveFromPrettyPrinting ifTrue: [^ self asString]]. self runs coalesce. self unembellished ifTrue: [^ self asString]. priorMethod ifNotNil: [old _ priorMethod getSourceFromFile]. (old == nil or: [old unembellished]) ifTrue: [tell _ 'This method contains style for the first time (e.g. bold or colored text). Do you really want to save the style info?'. answ _ (PopUpMenu labels: 'Save method with style Save method simply') startUpWithCaption: tell. answ = 2 ifTrue: [^ self asString]]! ! !Text methodsFor: 'attributes' stamp: 'tk 11/1/2001 14:37'! basicType "Answer a symbol representing the inherent type I hold" "Number String Boolean player collection sound color etc" ^ #Text! ! !Text methodsFor: 'attributes' stamp: 'sw 11/16/1999 22:33'! couldDeriveFromPrettyPrinting "Return true if the receiver has any TextAttributes that are functional rather than simply appearance-related" runs values do: [:emphArray | emphArray do: [:emph | emph couldDeriveFromPrettyPrinting ifFalse: [^ false]]]. ^ true! ! !Text methodsFor: 'attributes' stamp: 'sw 12/7/1999 12:31'! unembellished "Return true if the only emphases are the default font and bold" | font1 bold | font1 _ TextFontChange defaultFontChange. bold _ TextEmphasis bold. Preferences ignoreStyleIfOnlyBold ifFalse: ["Ignore font1 only or font1-bold followed by font1-plain" ^ (runs values = (Array with: (Array with: font1))) or: [runs values = (Array with: (Array with: font1 with: bold) with: (Array with: font1))]]. "If preference is set, then ignore any combo of font1 and bold" runs withStartStopAndValueDo: [:start :stop :emphArray | emphArray do: [:emph | (font1 = emph or: [bold = emph]) ifFalse: [^ false]]]. ^ true! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Text class instanceVariableNames: ''! !Text class methodsFor: 'class initialization' stamp: 'sw 5/23/2001 14:11'! initTextConstants "Initialize constants shared by classes associated with text display, e.g., Space, Tab, Cr, Bs, ESC." "1/24/96 sw: in exasperation and confusion, changed cmd-g mapping from 231 to 232 to see if I could gain any relief?!!" | letter varAndValue tempArray width | "CtrlA..CtrlZ, Ctrla..Ctrlz" letter _ $A. #( 212 230 228 196 194 226 241 243 214 229 200 217 246 245 216 202 210 239 211 240 197 198 209 215 242 231 1 166 228 132 130 12 232 179 150 165 136 153 182 14 15 138 17 18 19 11 21 134 145 151 178 167 ) do: [:kbd | TextConstants at: ('Ctrl', letter asSymbol) asSymbol put: kbd asCharacter. letter _ letter == $Z ifTrue: [$a] ifFalse: [(letter asciiValue + 1) asCharacter]]. varAndValue _ #( Space 32 Tab 9 CR 13 Enter 3 BS 8 BS2 158 ESC 160 Clear 173 ). varAndValue size odd ifTrue: [self error: 'unpaired text constant']. (2 to: varAndValue size by: 2) do: [:i | TextConstants at: (varAndValue at: i - 1) put: (varAndValue at: i) asCharacter]. varAndValue _ #( CtrlDigits (159 144 143 128 127 129 131 180 149 135) CtrlOpenBrackets (201 7 218 249 219 15) "lparen gottn by ctrl-_ = 201; should be 213 but can't type that on Mac" "location of non-character stop conditions" EndOfRun 257 CrossedX 258 "values for alignment" LeftFlush 0 RightFlush 1 Centered 2 Justified 3 "subscripts for a marginTabsArray tuple" LeftMarginTab 1 RightMarginTab 2 "font faces" Basal 0 Bold 1 Italic 2 "in case font doesn't have a width for space character" "some plausible numbers-- are they the right ones?" DefaultSpace 4 DefaultTab 24 DefaultLineGrid 16 DefaultBaseline 12 DefaultFontFamilySize 3 "basal, bold, italic" ). varAndValue size odd ifTrue: [self error: 'unpaired text constant']. (2 to: varAndValue size by: 2) do: [:i | TextConstants at: (varAndValue at: i - 1) put: (varAndValue at: i)]. TextConstants at: #DefaultRule put: Form over. TextConstants at: #DefaultMask put: Color black. width _ Display width max: 720. tempArray _ Array new: width // DefaultTab. 1 to: tempArray size do: [:i | tempArray at: i put: DefaultTab * i]. TextConstants at: #DefaultTabsArray put: tempArray. tempArray _ Array new: (width // DefaultTab) // 2. 1 to: tempArray size do: [:i | tempArray at: i put: (Array with: (DefaultTab*i) with: (DefaultTab*i))]. TextConstants at: #DefaultMarginTabsArray put: tempArray. "Text initTextConstants "! ! !Text class methodsFor: 'class initialization'! initialize "Text initialize" "Initialize constants shared by classes associated with text display." TextConstants at: #CaretForm put: (Form extent: 16@5 fromArray: #(2r001100e26 2r001100e26 2r011110e26 2r111111e26 2r110011e26) offset: -3@0). self initTextConstants! ! !Text class methodsFor: 'instance creation' stamp: 'sw 12/6/1999 14:14'! fromString: aString "Answer an instance of me whose characters are those of the argument, aString." ^ self string: aString attribute: (TextFontChange fontNumber: TextStyle default defaultFontIndex)! ! !Text class methodsFor: 'instance creation' stamp: 'jm 4/28/1998 06:54'! fromUser "Answer an instance of me obtained by requesting the user to type a string." "Text fromUser" ^ self fromString: (FillInTheBlank request: 'Enter text followed by carriage return') ! ! !Text class methodsFor: 'instance creation'! new: stringSize ^self fromString: (String new: stringSize)! ! !Text class methodsFor: 'instance creation'! streamContents: blockWithArg | stream | stream _ TextStream on: (self new: 400). blockWithArg value: stream. ^ stream contents! ! !Text class methodsFor: 'instance creation'! string: aString attribute: att "Answer an instance of me whose characters are aString. att is a TextAttribute." ^self string: aString attributes: (Array with: att)! ! !Text class methodsFor: 'instance creation'! string: aString attributes: atts "Answer an instance of me whose characters are those of aString. atts is an array of TextAttributes." ^self string: aString runs: (RunArray new: aString size withAll: atts)! ! !Text class methodsFor: 'instance creation'! string: aString emphasis: emphasis "This is an old method that is mainly used by old applications" emphasis isNumber ifTrue: [self halt: 'Numeric emphasis is not supported in Squeak'. "But if you proceed, we will do our best to give you what you want..." ^ self string: aString runs: (RunArray new: aString size withAll: (Array with: (TextFontChange new fontNumber: emphasis)))]. ^ self string: aString attributes: emphasis! ! !Text class methodsFor: 'private' stamp: 'di 10/31/97 11:22'! addAttribute: att toArray: others "Add a new text attribute to an existing set" "NOTE: The use of reset and set in this code is a specific hack for merging TextKerns." att reset. ^ Array streamContents: [:strm | others do: [:other | (att dominates: other) ifFalse: [strm nextPut: other]]. att set ifTrue: [strm nextPut: att]]! ! !Text class methodsFor: 'private'! string: aString runs: anArray ^self basicNew setString: aString setRuns: anArray! ! TextAttribute subclass: #TextAction instanceVariableNames: '' classVariableNames: 'Purple' poolDictionaries: '' category: 'Collections-Text'! !TextAction methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 16:44'! analyze: aString "Analyze the selected text to find both the parameter to store and the text to emphesize (may be different from original selection). Does not return self!!. May be of the form: 3+4 <3+4> Click Here<3+4> <3+4>Click Here " "Obtain the showing text and the instructions" | b1 b2 trim param show | b1 _ aString indexOf: $<. b2 _ aString indexOf: $>. (b1 < b2) & (b1 > 0) ifFalse: ["only one part" param _ self validate: aString. ^ Array with: param with: (param size = 0 ifTrue: [nil] ifFalse: [param])]. "Two parts" trim _ aString withBlanksTrimmed. (trim at: 1) == $< ifTrue: [(trim last) == $> ifTrue: ["only instructions" param _ self validate: (aString copyFrom: b1+1 to: b2-1). show _ param size = 0 ifTrue: [nil] ifFalse: [param]] ifFalse: ["at the front" param _ self validate: (aString copyFrom: b1+1 to: b2-1). show _ param size = 0 ifTrue: [nil] ifFalse: [aString copyFrom: b2+1 to: aString size]]] ifFalse: [(trim last) == $> ifTrue: ["at the end" param _ self validate: (aString copyFrom: b1+1 to: b2-1). show _ param size = 0 ifTrue: [nil] ifFalse: [aString copyFrom: 1 to: b1-1]] ifFalse: ["Illegal -- <> has text on both sides" show _ nil]]. ^ Array with: param with: show ! ! !TextAction methodsFor: 'as yet unclassified' stamp: 'sw 11/9/1999 17:21'! couldDeriveFromPrettyPrinting ^ false! ! !TextAction methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:11'! dominatedByCmd0 "Cmd-0 should turn off active text" ^ true! ! !TextAction methodsFor: 'as yet unclassified' stamp: 'di 1/14/98 09:30'! emphasizeScanner: scanner "Set the emphasis for text display" scanner textColor: Purple! ! !TextAction methodsFor: 'as yet unclassified' stamp: 'DSM 3/30/1999 13:15'! info ^ 'no hidden info'! ! !TextAction methodsFor: 'as yet unclassified'! mayActOnClick ^ true! ! !TextAction methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 16:48'! validate: aString "any format is OK with me" ^ aString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextAction class instanceVariableNames: ''! !TextAction class methodsFor: 'as yet unclassified' stamp: 'di 1/14/98 09:30'! initialize "TextAction initialize" Purple _ Color r: 0.4 g: 0 b: 1.0! ! TextAttribute subclass: #TextAlignment instanceVariableNames: 'alignment' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/15/2001 23:33'! = other ^ (other class == self class) and: [other alignment = alignment]! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/15/2001 23:33'! alignment ^alignment! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/15/2001 23:33'! alignment: aNumber alignment _ aNumber.! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/16/2001 00:20'! dominates: other "There can be only one..." ^self class == other class! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/15/2001 23:34'! emphasizeScanner: scanner "Set the emphasist for text scanning" scanner setAlignment: alignment.! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 9/9/2003 22:03'! hash "#hash is re-implemented because #= is re-implemented" ^ alignment hash! ! !TextAlignment methodsFor: 'as yet unclassified' stamp: 'ar 12/16/2001 01:55'! writeScanOn: strm strm nextPut: $a. alignment printOn: strm.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextAlignment class instanceVariableNames: ''! !TextAlignment class methodsFor: 'instance creation' stamp: 'ar 12/15/2001 23:36'! centered ^self new alignment: 2! ! !TextAlignment class methodsFor: 'instance creation' stamp: 'ar 12/15/2001 23:36'! justified ^self new alignment: 3! ! !TextAlignment class methodsFor: 'instance creation' stamp: 'ar 12/15/2001 23:35'! leftFlush ^self new alignment: 0! ! !TextAlignment class methodsFor: 'instance creation' stamp: 'ar 12/15/2001 23:35'! rightFlush ^self new alignment: 1! ! Object subclass: #TextAttribute instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextAttribute commentStamp: 'tk 7/22/2002 18:33' prior: 0! Tells a piece of text to be a certain way. Select text, press Command-6, choose a attribute. If selected text is of the form Hi There<Smalltalk beep> the part in angle brackets is saved for action, and the Hi There appears in the paragraph. If selection has no angle brackets, use the whole thing as both the text and the action. TextDoIt -- eval as a Smalltalk expression (the part in angle brackets) TextLink -- Show a method, class comment, class hierarchy, or class defintion. <Point extent:>, <Point Comment>, <Point Hierarchy>, or <Point Defintion> are what you type. TextURL -- Show the web page. <www.disney.com> These attributes of text need to be stored on the disk in a regular file-out. It is done in this form: Hi There in the text, and a Run containing dSmalltalk beep;; Click here to see the extent: in the text, and a Run containing method LPoint extent:; See RunArray class scanFrom: where decoding is done. ! ]style[(903 24 25)f1,f1LRunArray class scanFrom:;,f1! !TextAttribute methodsFor: 'as yet unclassified'! actOnClickFor: model "Subclasses may override to provide, eg, hot-spot actions" ^ false! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'ar 9/22/2001 16:00'! actOnClickFor: model in: aParagraph ^self actOnClickFor: model! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'ar 9/22/2001 16:08'! actOnClickFor: model in: aParagraph at: clickPoint ^self actOnClickFor: model in: aParagraph! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'ar 9/22/2001 16:22'! actOnClickFor: model in: aParagraph at: clickPoint editor: editor ^self actOnClickFor: model in: aParagraph at: clickPoint! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'ar 12/16/2001 23:18'! anchoredMorph "If one hides here, return it" ^nil! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'sw 11/9/1999 17:25'! couldDeriveFromPrettyPrinting "Answer whether the receiver is a kind of attribute that could have been generated by doing polychrome pretty-printing of a method without functional text attributes." ^ true! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:09'! dominatedByCmd0 "Subclasses may override if cmd-0 should turn them off" ^ false! ! !TextAttribute methodsFor: 'as yet unclassified'! dominates: another "Subclasses may override condense multiple attributes" ^ false! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'di 4/1/1999 15:16'! emphasisCode "Subclasses may override to add bold, italic, etc" ^ 0! ! !TextAttribute methodsFor: 'as yet unclassified'! emphasizeScanner: scanner "Subclasses may override to set, eg, font, color, etc"! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'di 11/9/97 17:46'! forFontInStyle: aTextStyle do: aBlock "No action is the default. Overridden by font specs"! ! !TextAttribute methodsFor: 'as yet unclassified'! mayActOnClick "Subclasses may override to provide, eg, hot-spot actions" ^ false! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'di 11/10/97 14:05'! mayBeExtended "A quality that may be overridden by subclasses, such as TextAnchors, that really only apply to a single character" ^ true! ! !TextAttribute methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:03'! reset "Allow subclasses to prepare themselves for merging attributes"! ! !TextAttribute methodsFor: 'as yet unclassified'! set "Respond true to include this attribute (as opposed to, eg, a bold emphasizer that is clearing the property" ^ true! ! TextAttribute subclass: #TextColor instanceVariableNames: 'color' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextColor commentStamp: '<historical>' prior: 0! A TextColor encodes a text color change applicable over a given range of text.! !TextColor methodsFor: 'accessing'! color ^ color! ! !TextColor methodsFor: 'accessing'! color: aColor color _ aColor! ! !TextColor methodsFor: 'comparing' stamp: 'di 10/31/97 11:19'! = other ^ (other class == self class) and: [other color = color]! ! !TextColor methodsFor: 'comparing' stamp: 'sma 3/24/2000 10:51'! hash ^ color hash! ! !TextColor methodsFor: 'printing' stamp: 'sma 3/24/2000 10:51'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' code: '; print: color! ! !TextColor methodsFor: 'scanning' stamp: 'di 10/31/97 11:20'! dominates: other ^ other class == self class! ! !TextColor methodsFor: 'scanning'! emphasizeScanner: scanner "Set the emphasis for text display" scanner textColor: color! ! !TextColor methodsFor: 'scanning' stamp: 'tk 12/16/97 09:47'! writeScanOn: strm "Two formats. c125000255 or cblue;" | nn str | strm nextPut: $c. (nn _ color name) ifNotNil: [ (self class respondsTo: nn) ifTrue: [ ^ strm nextPutAll: nn; nextPut: $;]]. (Array with: color red with: color green with: color blue) do: [:float | str _ '000', (float * 255) asInteger printString. strm nextPutAll: (str copyFrom: str size-2 to: str size)]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextColor class instanceVariableNames: ''! !TextColor class methodsFor: 'constants'! black ^ self new color: Color black! ! !TextColor class methodsFor: 'constants'! blue ^ self new color: Color blue! ! !TextColor class methodsFor: 'constants'! cyan ^ self new color: Color cyan! ! !TextColor class methodsFor: 'constants' stamp: 'ajh 9/10/2002 02:26'! gray ^ self new color: Color gray! ! !TextColor class methodsFor: 'constants'! green ^ self new color: Color green! ! !TextColor class methodsFor: 'constants'! magenta ^ self new color: Color magenta! ! !TextColor class methodsFor: 'constants'! red ^ self new color: Color red! ! !TextColor class methodsFor: 'constants' stamp: 'sma 3/24/2000 10:50'! white ^ self new color: Color white! ! !TextColor class methodsFor: 'constants'! yellow ^ self new color: Color yellow! ! !TextColor class methodsFor: 'instance creation'! color: aColor ^ self new color: aColor! ! !TextColor class methodsFor: 'instance creation' stamp: 'sma 3/24/2000 10:49'! scanFrom: strm "read a color in the funny format used by Text styles on files. c125000255 or cblue;" | r g b | strm peek isDigit ifTrue: [r _ (strm next: 3) asNumber. g _ (strm next: 3) asNumber. b _ (strm next: 3) asNumber. ^ self color: (Color r: r g: g b: b range: 255)]. "A name of a color" ^ self color: (Color perform: (strm upTo: $;) asSymbol)! ! Object subclass: #TextDiffBuilder instanceVariableNames: 'realSrc realDst srcMap dstMap srcLines dstLines srcPos dstPos added removed shifted runs matches multipleMatches patchSequence' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !TextDiffBuilder methodsFor: 'printing' stamp: 'nk 4/24/2004 08:48'! printPatchSequence: seq on: aStream seq do: [:assoc | aStream withAttributes: (self attributesOf: assoc key) do: [aStream nextPutAll: assoc value; cr]]! ! !TextDiffBuilder methodsFor: 'initialize' stamp: 'nk 10/29/2000 12:15'! destString: aString realDst _ self split: aString asString. dstLines _ OrderedCollection new. dstMap _ OrderedCollection new. realDst doWithIndex: [:line :realIndex | dstLines add: (self formatLine: line). dstMap add: realIndex]. dstPos _ PluggableDictionary new: dstLines size. dstPos hashBlock: self stringHashBlock. dstLines doWithIndex: [:line :index | (dstPos includesKey: line) ifTrue: [(dstPos at: line) add: index. multipleMatches _ true] ifFalse: [dstPos at: line put: (OrderedCollection with: index)]]! ! !TextDiffBuilder methodsFor: 'initialize' stamp: 'nk 1/7/2004 09:24'! formatLine: aString ^aString copyWithout: Character lf! ! !TextDiffBuilder methodsFor: 'initialize'! from: sourceString to: destString self sourceString: sourceString. self destString: destString.! ! !TextDiffBuilder methodsFor: 'initialize' stamp: 'nk 10/29/2000 12:15'! sourceString: aString realSrc _ self split: aString asString. srcLines _ OrderedCollection new. srcMap _ OrderedCollection new. realSrc doWithIndex: [:line :realIndex | srcLines add: (self formatLine: line). srcMap add: realIndex]. srcPos _ PluggableDictionary new: srcLines size. srcPos hashBlock: self stringHashBlock. srcLines doWithIndex: [:line :index | (srcPos includesKey: line) ifTrue: [(srcPos at: line) add: index. multipleMatches _ true] ifFalse: [srcPos at: line put: (OrderedCollection with: index)]]! ! !TextDiffBuilder methodsFor: 'initialize'! split: aString ^self split: aString by: self splitCharacter! ! !TextDiffBuilder methodsFor: 'testing'! hasMultipleMatches ^multipleMatches == true! ! !TextDiffBuilder methodsFor: 'creating patches'! buildDisplayPatch ^Text streamContents:[:stream| self printPatchSequence: self buildPatchSequence on: stream. ]! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'RAA 5/2/2001 23:35'! buildPatchSequence "@@ TODO: Das funktioniert noch nicht fr n-m matches" matches := TwoLevelDictionary new. self buildReferenceMap. runs := self processDiagonals. self validateRuns: runs. "There may be things which have just been moved around. Find those." shifted := self detectShiftedRuns. self processShiftedRuns. "Now generate a patch sequence" patchSequence := self generatePatchSequence. ^patchSequence! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'ar 11/20/1998 16:57'! buildReferenceMap dstLines doWithIndex:[:line :index| (srcPos at: line ifAbsent:[#()]) do:[:index2| matches at: index@index2 put: line] ]. srcLines doWithIndex:[:line :index| (dstPos at: line ifAbsent:[#()]) do:[:index2| matches at: index2@index put: line] ]. ! ! !TextDiffBuilder methodsFor: 'creating patches'! collectRunFrom: todo startingWith: startIndex into: run | next start | start := startIndex. self remove: start from: todo. run add: (matches at: start). "Search downwards" next := start. [next := next + (1@1). todo includes: next] whileTrue:[ run addLast: (matches at: next). self remove: next from: todo]. "Search upwards" next := start. [next := next - (1@1). todo includes: next] whileTrue:[ run addFirst: (matches at: next). self remove: next from: todo. start := next. "To use the first index" ]. ^start! ! !TextDiffBuilder methodsFor: 'creating patches'! detectShiftedRuns | sortedRuns lastY run shiftedRuns | runs size < 2 ifTrue: [^ nil]. shiftedRuns _ OrderedCollection new. sortedRuns _ SortedCollection sortBlock: [:a1 :a2 | a1 key x < a2 key x]. runs associationsDo: [:assoc | sortedRuns add: assoc]. lastY _ sortedRuns first key y. 2 to: sortedRuns size do:[:i | run _ sortedRuns at: i. run key y > lastY ifTrue: [lastY _ run key y] ifFalse: [shiftedRuns add: run]]. ^ shiftedRuns! ! !TextDiffBuilder methodsFor: 'creating patches'! generatePatchSequence | ps | ps := OrderedCollection new: srcLines size. srcLines size timesRepeat:[ps add: nil]. self incorporateMatchesInto: ps. self incorporateRemovalsInto: ps. self incorporateAddsInto: ps. ^ps! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'di 3/15/1999 14:01'! incorporateAddsInto: aPatchSequence "Incorporate adds" | lastMatch lastIndex index | added ifNil:[^self]. added := added sortBy:[:a1 :a2| a1 key < a2 key]. lastMatch := 1. lastIndex := 0. 1 to: added size do:[:i| index := (added at: i) key. [index > lastMatch] whileTrue:[ [lastIndex := lastIndex + 1. (aPatchSequence at: lastIndex) key == #match] whileFalse. lastMatch := lastMatch + 1. ]. aPatchSequence add: #insert->(added at: i) value afterIndex: lastIndex. lastIndex := lastIndex + 1. lastMatch := lastMatch + 1. ].! ! !TextDiffBuilder methodsFor: 'creating patches'! incorporateMatchesInto: aPatchSequence "Incorporate matches" | index | runs associationsDo:[:assoc| index := assoc key y. assoc value do:[:line| self assert:[(aPatchSequence at: index) isNil]. aPatchSequence at: index put: (#match -> line). index := index + 1. ]. ]. ! ! !TextDiffBuilder methodsFor: 'creating patches'! incorporateRemovalsInto: aPatchSequence "Incorporate removals" | index | removed ifNil:[^self]. removed do:[:assoc| index := assoc key. self assert:[(aPatchSequence at: index) isNil]. aPatchSequence at: index put: #remove -> assoc value. ]. ! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'RAA 5/2/2001 23:41'! processDiagonals ^self processDiagonalsFrom: matches twoLevelKeys ! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'RAA 5/2/2001 23:17'! processDiagonalsFrom: todoList | runList start run todo | todo := todoList copy. runList := PluggableDictionary new. runList hashBlock: self pointHashBlock. runList equalBlock: self pointEqualBlock. [todo isEmpty] whileFalse:[ start := todo detect:[:any| true]. run := OrderedCollection new. start := self collectRunFrom: todo startingWith: start into: run. runList at: start put: run. ]. "If we have multiple matches we might have chosen a bad sequence. There we redo the whole thing recursively" self hasMultipleMatches ifFalse:[^runList]. runList size < 2 ifTrue:[^runList]. run := nil. start := 0. runList associationsDo:[:assoc| (run isNil or:[assoc value size > run size]) ifTrue:[ run := assoc value. start := assoc key]]. "Now found the longest run" run := OrderedCollection new. start := self collectRunFrom: todoList startingWith: start into: run. "Find the diagonals in the remaining set" runList := self processDiagonalsFrom: todoList. runList at: start put: run. ^runList! ! !TextDiffBuilder methodsFor: 'creating patches'! processShiftedRuns | key | shifted isNil ifTrue:[^self]. shifted do:[:assoc| key := assoc key. assoc value doWithIndex:[:line :idx| removed add: (key y + idx - 1) -> line. added add: (key x + idx - 1) -> line]. runs removeKey: assoc key. ]. ! ! !TextDiffBuilder methodsFor: 'creating patches' stamp: 'ar 11/20/1998 17:26'! validateRuns: runList | srcPosCopy dstPosCopy lines srcIndex dstIndex | srcPosCopy _ srcPos copy. srcPosCopy associationsDo:[:assoc| assoc value: assoc value asSet]. dstPosCopy _ dstPos copy. dstPosCopy associationsDo:[:assoc| assoc value: assoc value asSet]. runList associationsDo:[:assoc| srcIndex := assoc key y. dstIndex := assoc key x. lines := assoc value. lines do:[:string| (srcPosCopy at: string) remove: srcIndex. (dstPosCopy at: string) remove: dstIndex. srcIndex := srcIndex + 1. dstIndex := dstIndex + 1. ]. ]. removed := OrderedCollection new. srcPosCopy associationsDo:[:assoc| assoc value do:[:index| removed add: (index -> assoc key)]. ]. removed := removed sortBy:[:a1 :a2| a1 key < a2 key]. added := OrderedCollection new. dstPosCopy associationsDo:[:assoc| assoc value do:[:index| added add: (index -> assoc key)]. ]. added := added sortBy:[:a1 :a2| a1 key < a2 key]. ! ! !TextDiffBuilder methodsFor: 'private' stamp: 'nk 4/24/2004 08:48'! attributesOf: type "Private. Answer the TextAttributes that are used to display text of the given type." ^type caseOf: { [#insert] -> [ {TextColor red} ]. [#remove] -> [ {TextEmphasis struckOut. TextColor blue}]. } otherwise: [ {TextEmphasis normal} ]. ! ! !TextDiffBuilder methodsFor: 'private' stamp: 'RAA 5/2/2001 22:56'! pointEqualBlock ^[ :a :b | a x = b x and: [a y = b y]] fixTemps! ! !TextDiffBuilder methodsFor: 'private' stamp: 'ar 11/20/1998 16:35'! pointHashBlock ^[:pt| (pt x bitShift: 12) + pt y] fixTemps! ! !TextDiffBuilder methodsFor: 'private' stamp: 'RAA 5/2/2001 23:28'! remove: pointKey from: aSet self hasMultipleMatches ifFalse:[^aSet remove: pointKey]. aSet removeAllXAndY: pointKey. ! ! !TextDiffBuilder methodsFor: 'private' stamp: 'ar 11/20/1998 17:26'! split: aString by: splitChar | lines index nextIndex | lines := OrderedCollection new. index _ 1. [index <= aString size] whileTrue:[ nextIndex _ aString indexOf: splitChar startingAt: index ifAbsent:[aString size+1]. lines add: (aString copyFrom: index to: nextIndex-1). index _ nextIndex+1]. ^lines! ! !TextDiffBuilder methodsFor: 'private'! splitCharacter ^Character cr! ! !TextDiffBuilder methodsFor: 'private' stamp: 'ar 11/24/1998 13:41'! stringHashBlock "Return a block for use in string hashing" | stringSize | ^[:string| stringSize _ string size. stringSize = 0 ifTrue:[0] ifFalse:[ stringSize < 3 ifTrue:[(string at: 1) asInteger + ((string at: string size) asInteger bitShift: 8)] ifFalse:[ (string at: 1) asInteger + ((string at: stringSize // 3 + 1) asInteger bitShift: 4) + ((string at: stringSize // 2 + 1) asInteger bitShift: 8) + ((string at: stringSize * 2 // 3 + 1) asInteger bitShift: 12) + ((string at: stringSize) asInteger bitShift: 16)]]] fixTemps! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextDiffBuilder class instanceVariableNames: ''! !TextDiffBuilder class methodsFor: 'instance creation'! buildDisplayPatchFrom: srcString to: dstString ^(self from: srcString to: dstString) buildDisplayPatch! ! !TextDiffBuilder class methodsFor: 'instance creation' stamp: 'sw 5/19/2001 10:52'! buildDisplayPatchFrom: srcString to: dstString inClass: srcClass prettyDiffs: prettyBoolean "Build a display patch for mapping via diffs from srcString to dstString in the given class. If prettyBoolean is true, do the diffing for pretty-printed forms" ^ ((srcClass notNil and: [prettyBoolean]) ifTrue: [PrettyTextDiffBuilder from: srcString to: dstString inClass: srcClass] ifFalse: [self from: srcString to: dstString]) buildDisplayPatch! ! !TextDiffBuilder class methodsFor: 'instance creation'! from: srcString to: dstString ^self new from: srcString to: dstString! ! TextAction subclass: #TextDoIt instanceVariableNames: 'evalString' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextDoIt methodsFor: 'as yet unclassified' stamp: 'tk 12/5/97 17:01'! actOnClickFor: anObject "Note: evalString gets evaluated IN THE CONTEXT OF anObject -- meaning that self and all instVars are accessible" Compiler evaluate: evalString for: anObject logged: false. ^ true ! ! !TextDoIt methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 16:46'! analyze: aString | list | list _ super analyze: aString. evalString _ list at: 1. ^ list at: 2! ! !TextDoIt methodsFor: 'as yet unclassified' stamp: 'tk 12/5/97 17:01'! evalString: str evalString _ str ! ! !TextDoIt methodsFor: 'as yet unclassified' stamp: 'tk 12/30/97 10:33'! info ^ evalString! ! !TextDoIt methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 13:46'! writeScanOn: strm strm nextPut: $d; nextPutAll: evalString; nextPutAll: ';;'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextDoIt class instanceVariableNames: ''! !TextDoIt class methodsFor: 'as yet unclassified' stamp: 'tk 12/6/97 20:28'! evalString: str ^ self new evalString: str! ! !TextDoIt class methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 09:06'! scanFrom: strm "read a doit in the funny format used by Text styles on files. d10 factorial;; end with two semicolons" | pos end doit | pos _ strm position. [strm skipTo: $;. strm peek == $;] whileFalse. end _ strm position - 1. strm position: pos. doit _ strm next: end-pos. strm skip: 2. ";;" ^ self evalString: doit! ! TextAttribute subclass: #TextEmphasis instanceVariableNames: 'emphasisCode setMode' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextEmphasis commentStamp: '<historical>' prior: 0! A TextEmphasis, encodes a characteristic applicable to all fonts. The encoding is as follows: 1 bold 2 itallic 4 underlined 8 narrow 16 struck out! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:15'! = other ^ (other class == self class) and: [other emphasisCode = emphasisCode]! ! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:11'! dominatedByCmd0 "Cmd-0 should turn off emphasis" ^ true! ! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:13'! dominates: other (emphasisCode = 0 and: [other dominatedByCmd0]) ifTrue: [^ true]. ^ (other class == self class) and: [emphasisCode = other emphasisCode]! ! !TextEmphasis methodsFor: 'as yet unclassified'! emphasisCode ^ emphasisCode! ! !TextEmphasis methodsFor: 'as yet unclassified'! emphasisCode: int emphasisCode _ int. setMode _ true! ! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'di 10/29/97 11:57'! emphasizeScanner: scanner "Set the emphasist for text scanning" scanner addEmphasis: emphasisCode! ! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'ar 9/9/2003 22:03'! hash "#hash is re-implemented because #= is re-implemented" ^emphasisCode hash ! ! !TextEmphasis methodsFor: 'as yet unclassified'! printOn: strm super printOn: strm. strm nextPutAll: ' code: '; print: emphasisCode! ! !TextEmphasis methodsFor: 'as yet unclassified'! set ^ setMode and: [emphasisCode ~= 0]! ! !TextEmphasis methodsFor: 'as yet unclassified'! turnOff setMode _ false! ! !TextEmphasis methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 09:28'! writeScanOn: strm emphasisCode = 1 ifTrue: [strm nextPut: $b]. emphasisCode = 2 ifTrue: [strm nextPut: $i]. emphasisCode = 0 ifTrue: [strm nextPut: $n]. emphasisCode = 16 ifTrue: [strm nextPut: $=]. emphasisCode = 4 ifTrue: [strm nextPut: $u].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextEmphasis class instanceVariableNames: ''! !TextEmphasis class methodsFor: 'as yet unclassified'! bold ^ self new emphasisCode: 1! ! !TextEmphasis class methodsFor: 'as yet unclassified'! italic ^ self new emphasisCode: 2! ! !TextEmphasis class methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:05'! narrow ^ TextKern kern: -1! ! !TextEmphasis class methodsFor: 'as yet unclassified'! normal ^ self new emphasisCode: 0! ! !TextEmphasis class methodsFor: 'as yet unclassified'! struckOut ^ self new emphasisCode: 16! ! !TextEmphasis class methodsFor: 'as yet unclassified'! underlined ^ self new emphasisCode: 4! ! TextAttribute subclass: #TextFontChange instanceVariableNames: 'fontNumber' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextFontChange commentStamp: '<historical>' prior: 0! A TextFontChange encodes a font change applicable over a given range of text. The font number is interpreted relative to the textStyle governing display of this text.! !TextFontChange methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:15'! = other ^ (other class == self class) and: [other fontNumber = fontNumber]! ! !TextFontChange methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:20'! dominates: other ^ other class == self class! ! !TextFontChange methodsFor: 'as yet unclassified'! emphasizeScanner: scanner "Set the font for text display" scanner setFont: fontNumber! ! !TextFontChange methodsFor: 'as yet unclassified'! fontNumber ^ fontNumber! ! !TextFontChange methodsFor: 'as yet unclassified'! fontNumber: int fontNumber _ int! ! !TextFontChange methodsFor: 'as yet unclassified' stamp: 'di 11/9/97 17:46'! forFontInStyle: aTextStyle do: aBlock aBlock value: (aTextStyle fontAt: fontNumber)! ! !TextFontChange methodsFor: 'as yet unclassified' stamp: 'ar 9/9/2003 22:03'! hash "#hash is re-implemented because #= is re-implemented" ^fontNumber hash! ! !TextFontChange methodsFor: 'as yet unclassified'! printOn: strm super printOn: strm. strm nextPutAll: ' font: '; print: fontNumber! ! !TextFontChange methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 09:22'! writeScanOn: strm strm nextPut: $f. fontNumber printOn: strm.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextFontChange class instanceVariableNames: ''! !TextFontChange class methodsFor: 'as yet unclassified' stamp: 'sw 12/6/1999 17:52'! defaultFontChange "Answer a TextFontChange that represents the default font" ^ self new fontNumber: TextStyle default defaultFontIndex! ! !TextFontChange class methodsFor: 'as yet unclassified'! font1 ^ self new fontNumber: 1! ! !TextFontChange class methodsFor: 'as yet unclassified'! font2 ^ self new fontNumber: 2! ! !TextFontChange class methodsFor: 'as yet unclassified'! font3 ^ self new fontNumber: 3! ! !TextFontChange class methodsFor: 'as yet unclassified'! font4 ^ self new fontNumber: 4! ! !TextFontChange class methodsFor: 'as yet unclassified'! fontNumber: n ^ self new fontNumber: n! ! TextFontChange subclass: #TextFontReference instanceVariableNames: 'font' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextFontReference commentStamp: '<historical>' prior: 0! A TextFontReference encodes a font change applicable over a given range of text. The font reference is absolute: unlike a TextFontChange, it is independent of the textStyle governing display of this text.! !TextFontReference methodsFor: 'as yet unclassified' stamp: 'sw 11/9/1999 17:22'! couldDeriveFromPrettyPrinting ^ false! ! !TextFontReference methodsFor: 'as yet unclassified'! emphasizeScanner: scanner "Set the actual font for text display" scanner setActualFont: font! ! !TextFontReference methodsFor: 'as yet unclassified' stamp: 'di 5/10/1999 23:47'! font ^ font! ! !TextFontReference methodsFor: 'as yet unclassified' stamp: 'di 11/9/97 17:47'! forFontInStyle: aTextStyle do: aBlock aBlock value: font! ! !TextFontReference methodsFor: 'as yet unclassified'! toFont: aFont font _ aFont! ! !TextFontReference methodsFor: 'as yet unclassified' stamp: 'tk 7/22/2002 18:39'! writeScanOn: strm strm nextPut: $F. strm nextPutAll: font familyName; nextPut: $#. font height printOn: strm.! ! !TextFontReference methodsFor: 'comparing' stamp: 'mas 5/7/1999 06:20'! = other ^ (other class == self class) and: [other font == font]! ! !TextFontReference methodsFor: 'comparing' stamp: 'ar 9/9/2003 22:03'! hash "#hash is re-implemented because #= is re-implemented" ^font hash! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextFontReference class instanceVariableNames: ''! !TextFontReference class methodsFor: 'as yet unclassified'! toFont: aFont ^ self new toFont: aFont! ! TextAttribute subclass: #TextIndent instanceVariableNames: 'amount' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextIndent commentStamp: '<historical>' prior: 0! create a hanging indent. ! !TextIndent methodsFor: 'access' stamp: 'ls 6/22/1998 17:51'! amount: anInteger "change the number of tabs to indent by" amount _ anInteger! ! !TextIndent methodsFor: 'printing' stamp: 'ls 6/22/1998 18:03'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' amount: '. amount printOn: aStream! ! !TextIndent methodsFor: 'setting indentation' stamp: 'ls 6/22/1998 18:56'! emphasizeScanner: scanner scanner indentationLevel: amount! ! !TextIndent methodsFor: 'condensing' stamp: 'ls 6/22/1998 19:27'! dominates: anAttribute ^(self class == anAttribute class)! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextIndent class instanceVariableNames: ''! !TextIndent class methodsFor: 'instance creation' stamp: 'ls 6/27/1998 15:55'! amount: amount "create a TextIndent which will indent by the given amount. Currently this is a number of tabs, but may change in the futur" ^super new amount: amount! ! !TextIndent class methodsFor: 'example' stamp: 'ls 6/24/1998 18:06'! example "TextIndent example" | text pg | "create an example text with some indentation" text _ 'abcdao euoaeuo aeuo aeuoaeu o aeuoeauefgh bcd efghi' asText. text addAttribute: (TextColor red) from: 3 to: 8. text addAttribute: (TextIndent amount: 1) from: 1 to: 2. text addAttribute: (TextIndent amount: 2) from: 20 to: 35. "stick it in a paragraph and display it" pg _ text asParagraph. pg compositionRectangle: (0@0 extent: 100@200). pg textStyle alignment: 2. pg displayAt: 0@0. ! ! TextAttribute subclass: #TextKern instanceVariableNames: 'kern active' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextKern commentStamp: '<historical>' prior: 0! A TextKern encodes a kerning change applicable over a given range of text. Positive values of kern spread letters out, negative kern will cause them to overlap more. Note that kerns other than 0 will display somewhat slower, as kerning is not yet supported in the text scanning primitive. ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:15'! = other ^ (other class == self class) and: [other kern = kern]! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'sw 11/9/1999 17:21'! couldDeriveFromPrettyPrinting ^ false! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 13:10'! dominatedByCmd0 "Cmd-0 should turn off kerning" ^ true! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:10'! dominates: other "NOTE: The use of active in this code is specific to its use in the method Text class addAttribute: att toArray: others" (active and: [other class == self class and: [other kern + kern = 0]]) ifTrue: [active _ false. ^ true]. "can only dominate once" ^ false! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/29/97 11:50'! emphasizeScanner: scanner "Augment (or diminish) the kerning offset for text display" scanner addKern: kern! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'ar 9/9/2003 22:03'! hash "#hash is re-implemented because #= is re-implemented" ^kern hash! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:12'! kern ^ kern! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'tk 12/30/97 09:59'! kern: kernValue kern _ kernValue. self reset.! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:04'! reset active _ true! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'di 10/31/97 11:11'! set ^ active! ! !TextKern methodsFor: 'as yet unclassified' stamp: 'tk 9/21/1999 15:57'! writeScanOn: strm kern > 0 ifTrue: [ 1 to: kern do: [:kk | strm nextPut: $+]]. kern < 0 ifTrue: [ 1 to: 0-kern do: [:kk | strm nextPut: $-]].! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextKern class instanceVariableNames: ''! !TextKern class methodsFor: 'as yet unclassified' stamp: 'di 10/29/97 11:49'! kern: kernValue ^ self new kern: kernValue! ! Interval subclass: #TextLineInterval instanceVariableNames: 'internalSpaces paddingWidth lineHeight baseline' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !TextLineInterval commentStamp: '<historical>' prior: 0! My instances specify the starting and stopping points in a String of a composed line. The step is always 1.! !TextLineInterval methodsFor: 'accessing'! baseline ^ baseline! ! !TextLineInterval methodsFor: 'accessing'! internalSpaces "Answer the number of spaces in the line." ^internalSpaces! ! !TextLineInterval methodsFor: 'accessing'! internalSpaces: spacesInteger "Set the number of spaces in the line to be spacesInteger." internalSpaces _ spacesInteger! ! !TextLineInterval methodsFor: 'accessing'! lineHeight ^ lineHeight! ! !TextLineInterval methodsFor: 'accessing'! paddingWidth "Answer the amount of space to be added to the font." ^paddingWidth! ! !TextLineInterval methodsFor: 'accessing'! paddingWidth: padWidthInteger "Set the amount of space to be added to the font to be padWidthInteger." paddingWidth _ padWidthInteger! ! !TextLineInterval methodsFor: 'accessing'! stop: stopInteger "Set the stopping point in the string of the line to be stopInteger." stop _ stopInteger! ! !TextLineInterval methodsFor: 'comparing'! = line self species = line species ifTrue: [^((start = line first and: [stop = line last]) and: [internalSpaces = line internalSpaces]) and: [paddingWidth = line paddingWidth]] ifFalse: [^false]! ! !TextLineInterval methodsFor: 'scanning'! justifiedPadFor: spaceIndex "Compute the width of pad for a given space in a line of justified text." | pad | internalSpaces = 0 ifTrue: [^0]. pad _ paddingWidth // internalSpaces. spaceIndex <= (paddingWidth \\ internalSpaces) ifTrue: [^pad + 1] ifFalse: [^pad]! ! !TextLineInterval methodsFor: 'scanning'! justifiedTabDeltaFor: spaceIndex "Compute the delta for a tab in a line of justified text, so tab falls somewhere plausible when line is justified." | pad extraPad | internalSpaces = 0 ifTrue: [^0]. pad _ paddingWidth // internalSpaces. extraPad _ paddingWidth \\ internalSpaces. spaceIndex <= extraPad ifTrue: [^spaceIndex * (pad + 1)] ifFalse: [^extraPad * (pad + 1) + (spaceIndex - extraPad * pad)]! ! !TextLineInterval methodsFor: 'updating'! slide: delta "Change the starting and stopping points of the line by delta." start _ start + delta. stop _ stop + delta! ! !TextLineInterval methodsFor: 'private'! internalSpaces: spacesInteger paddingWidth: padWidthInteger internalSpaces _ spacesInteger. paddingWidth _ padWidthInteger! ! !TextLineInterval methodsFor: 'private'! lineHeight: height baseline: ascent lineHeight _ height. baseline _ ascent! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextLineInterval class instanceVariableNames: ''! !TextLineInterval class methodsFor: 'instance creation'! start: startInteger stop: stopInteger internalSpaces: spacesInteger paddingWidth: padWidthInteger "Answer an instance of me with the arguments as the start, stop points, number of spaces in the line, and width of the padding." | newSelf | newSelf _ super from: startInteger to: stopInteger by: 1. ^newSelf internalSpaces: spacesInteger paddingWidth: padWidthInteger! ! TextAction subclass: #TextLink instanceVariableNames: 'classAndMethod' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 5/1/2001 18:17'! actOnClickFor: aMessageSet "Add to the end of the list. 'aClass selector', 'aClass Comment', 'aClass Definition', 'aClass Hierarchy' are the formats allowed." aMessageSet addItem: classAndMethod. ^ true! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 16:49'! analyze: aString | list | list _ super analyze: aString. classAndMethod _ list at: 1. ^ list at: 2! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'LC 10/8/2001 10:53'! analyze: aString with: nonMethod "Initalize this attribute holder with a piece text the user typed into a paragraph. Returns the text to emphesize (may be different from selection) Does not return self!!. nonMethod is what to show when clicked, i.e. the last part of specifier (Comment, Definition, or Hierarchy). May be of the form: Point <Point> Click Here<Point> <Point>Click Here " "Obtain the showing text and the instructions" | b1 b2 trim | b1 _ aString indexOf: $<. b2 _ aString indexOf: $>. (b1 < b2) & (b1 > 0) ifFalse: ["only one part" classAndMethod _ self validate: aString, ' ', nonMethod. ^ classAndMethod ifNotNil: [aString]]. "Two parts" trim _ aString withBlanksTrimmed. (trim at: 1) == $< ifTrue: [(trim last) == $> ifTrue: ["only instructions" classAndMethod _ self validate: (aString copyFrom: b1+1 to: b2-1), ' ', nonMethod. ^ classAndMethod ifNotNil: [classAndMethod]] ifFalse: ["at the front" classAndMethod _ self validate: (aString copyFrom: b1+1 to: b2-1), ' ', nonMethod. ^ classAndMethod ifNotNil: [aString copyFrom: b2+1 to: aString size]]] ifFalse: [(trim last) == $> ifTrue: ["at the end" classAndMethod _ self validate: (aString copyFrom: b1+1 to: b2-1), ' ', nonMethod. ^ classAndMethod ifNotNil: [aString copyFrom: 1 to: b1-1]] ifFalse: ["Illegal -- <> has text on both sides" ^ nil]] ! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 12/5/97 17:09'! classAndMethod: aString classAndMethod _ aString! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 12/30/97 10:33'! info ^ classAndMethod! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 5/7/2001 09:30'! validate: specString "Can this string be decoded to be Class space Method (or Comment, Definition, Hierarchy)? If so, return it in valid format, else nil" | list first mid last | list _ specString findTokens: ' .|'. last _ list last. last first isUppercase ifTrue: [ (#('Comment' 'Definition' 'Hierarchy') includes: last) ifFalse: [^ nil]. "Check for 'Rectangle Comment Comment' and remove last one" (list at: list size - 1) = last ifTrue: [list _ list allButLast]]. list size > 3 ifTrue: [^ nil]. list size < 2 ifTrue: [^ nil]. Symbol hasInterned: list first ifTrue: [:sym | first _ sym]. first ifNil: [^ nil]. Smalltalk at: first ifAbsent: [^ nil]. mid _ list size = 3 ifTrue: [(list at: 2) = 'class' ifTrue: ['class '] ifFalse: [^ nil]] ifFalse: ['']. "OK if method name is not interned -- may not be defined yet" ^ first, ' ', mid, last! ! !TextLink methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 13:44'! writeScanOn: strm strm nextPut: $L; nextPutAll: classAndMethod; nextPut: $;! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextLink class instanceVariableNames: ''! !TextLink class methodsFor: 'as yet unclassified' stamp: 'tk 12/16/97 08:53'! scanFrom: strm "read a link in the funny format used by Text styles on files. LPoint +;LPoint Comment;" ^ self new classAndMethod: (strm upTo: $;)! ! TextDoIt subclass: #TextPrintIt instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Text'! !TextPrintIt methodsFor: 'as yet unclassified' stamp: 'dvf 10/1/2003 13:27'! actOnClickFor: anObject in: aParagraph at: clickPoint editor: editor "Note: evalString gets evaluated IN THE CONTEXT OF anObject -- meaning that self and all instVars are accessible" | result range index | result _ Compiler evaluate: evalString for: anObject logged: false. result _ ' ', result printString,' '. "figure out where the attribute ends in aParagraph" index _ (aParagraph characterBlockAtPoint: clickPoint) stringIndex. range _ aParagraph text rangeOf: self startingAt: index. editor selectFrom: range last+1 to: range last. editor zapSelectionWith: result. editor selectFrom: range last to: range last + result size. ^ true ! ! !TextPrintIt methodsFor: 'as yet unclassified' stamp: 'ar 9/22/2001 16:28'! writeScanOn: strm strm nextPut: $P; nextPutAll: evalString; nextPutAll: ';;'! ! Object subclass: #TextPrinter instanceVariableNames: 'form para paperSize landscape resolution depth offset columns docTitle noHeader noFooter' classVariableNames: 'DefaultPaperSize DefaultTextPrinter' poolDictionaries: '' category: 'Graphics-Text'! !TextPrinter methodsFor: 'initialize' stamp: 'ar 4/30/98 19:26'! defaultPaperSize "Return the default paper size (inches) for printing" ^self class defaultPaperSize! ! !TextPrinter methodsFor: 'initialize' stamp: 'nk 4/2/2004 11:32'! defaultResolution "Return the default resolution (DPI) for printing" ^TextStyle pixelsPerInch asPoint! ! !TextPrinter methodsFor: 'initialize' stamp: 'ar 4/30/98 19:39'! initialize self paperSize: self defaultPaperSize. self resolution: self defaultResolution. self blackAndWhite. self landscape: false. self offsetRect: (1.0@1.0 corner: 1.0@1.0). self columns: 1. self noHeader: false. self noFooter: false. self documentTitle: 'Squeak Document (from ', Date today printString,')'.! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:42'! blackAndWhite "Set the reproduction quality to black and white" depth := 1.! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:50'! columns ^columns! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:50'! columns: aNumber columns := aNumber asInteger max: 1.! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 20:14'! documentTitle ^docTitle! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 20:14'! documentTitle: aString docTitle := aString! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:42'! landscape ^landscape! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:42'! landscape: aBoolean landscape := aBoolean! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:23'! noFooter ^noFooter! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:22'! noFooter: aBoolean "Turn off footer printing" noFooter := aBoolean.! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:22'! noHeader ^noHeader! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:22'! noHeader: aBoolean "Turn off header printing" noHeader := aBoolean.! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:27'! offsetRect ^offset! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 19:27'! offsetRect: aRectangle "Set the offset rectangle" offset := aRectangle! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:42'! paperSize ^paperSize! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:42'! paperSize: aPoint paperSize := aPoint! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:43'! resolution ^resolution! ! !TextPrinter methodsFor: 'accessing' stamp: 'ar 4/30/98 18:43'! resolution: aPoint resolution := aPoint! ! !TextPrinter methodsFor: 'printing' stamp: 'ar 4/30/98 20:41'! flushPage "The current page has been set up. Send it to the printer." form primPrintHScale: self resolution x vScale: self resolution y landscape: self landscape. "Uncomment the following for testing" "form displayOn: Display. (Delay forSeconds: 5) wait." ! ! !TextPrinter methodsFor: 'printing' stamp: 'ar 4/30/98 19:19'! printParagraph | pageNum nextIndex | para destinationForm: form. pageNum := 1. nextIndex := 1. [form fillColor: Color white. self printHeader: pageNum. self printFooter: pageNum. nextIndex := self formatPage: pageNum startingWith: nextIndex. self flushPage. nextIndex isNil] whileFalse:[pageNum := pageNum + 1].! ! !TextPrinter methodsFor: 'printing' stamp: 'ar 4/30/98 18:55'! printText: aText "Print aText" form isNil ifTrue:[ form := Form extent: self pixelSize depth: depth. ]. para := Paragraph withText: aText asText. Cursor wait showWhile:[ self printParagraph. ].! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:25'! columnRect: n "Return a rectangle describing the n-th column" | area left right | area := self textArea. left := area left + ((n-1) * self columnWidth). left := left + ((n-1) * self columnSkip). right := left + self columnWidth. ^(self in2pix: left @ area top) corner: (self in2pix: right @ area bottom)! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:20'! columnSkip "Return the separating space between two columns in inches" ^0.2! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:21'! columnWidth ^(self textWidth - ((self columns-1) * self columnSkip)) / self columns! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:29'! formatColumn: columnNum startingWith: anIndex "Format a new column starting at the given string index. Return the string index indicating the start of the next column or nil if no more columns need printing." | colRect blk | colRect := self columnRect: columnNum. anIndex > 1 ifTrue:[para text: (para text copyFrom: anIndex to: para text size)]. para compositionRectangle: colRect. para clippingRectangle: colRect. para composeAll. para displayOn: form. para visibleRectangle corner y <= colRect extent y ifTrue:[^nil]. "More columns -- find the character block of the last line and adjust clip rect" blk := para characterBlockAtPoint: para visibleRectangle bottomLeft. para clearVisibleRectangle. "Make sure that the background is clean" para clippingRectangle: (colRect topLeft corner: colRect right@blk top). para displayOn: form. ^blk stringIndex.! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:29'! formatPage: pageNum startingWith: anIndex "Format a new page starting at the given string index. Return the string index indicating the start of the next page or nil if no more pages need printing." | nextIndex | nextIndex := anIndex. 1 to: self columns do:[:i| nextIndex := self formatColumn: i startingWith: nextIndex. nextIndex isNil ifTrue:[^nil]. ]. ^nextIndex! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:58'! textArea ^(self offsetRect origin + (0.0@self headerHeight)) corner: (self realPaperSize - self offsetRect corner - (0.0@self footerHeight))! ! !TextPrinter methodsFor: 'formatting' stamp: 'ar 4/30/98 19:23'! textWidth ^self textArea extent x! ! !TextPrinter methodsFor: 'header' stamp: 'ar 4/30/98 19:23'! headerHeight "Return the (additional) height of the header in inches." self noHeader ifTrue:[^0.0]. ^(self pix2in: 0@TextStyle default lineGrid) y * 2! ! !TextPrinter methodsFor: 'header' stamp: 'ar 4/30/98 20:11'! headerParagraph "Return a paragraph for the footer" | hPara rect | hPara := Paragraph new. hPara destinationForm: form. rect := (self in2pix: self textArea topLeft - (0.0@self headerHeight)) corner: (self in2pix: self textArea topRight). hPara clippingRectangle: rect. hPara compositionRectangle: rect. ^hPara! ! !TextPrinter methodsFor: 'header' stamp: 'ar 4/30/98 19:23'! printHeader: pageNumber "Print the header for the given page number" | fPara | self noHeader ifTrue:[^self]. fPara := self headerParagraph. fPara centered. fPara text: self documentTitle asText. fPara displayOn: form.! ! !TextPrinter methodsFor: 'footer' stamp: 'ar 4/30/98 19:23'! footerHeight "Return the (additional) height of the footer in inches." self noFooter ifTrue:[^0.0]. ^(self pix2in: 0@TextStyle default lineGrid) y * 2! ! !TextPrinter methodsFor: 'footer' stamp: 'ar 4/30/98 20:11'! footerParagraph "Return a paragraph for the footer" | fPara rect | fPara := Paragraph new. fPara destinationForm: form. rect := (self in2pix: self textArea bottomLeft) corner: (self in2pix: self textArea bottomRight + (0.0@self footerHeight)). fPara clippingRectangle: rect. fPara compositionRectangle: rect. ^fPara! ! !TextPrinter methodsFor: 'footer' stamp: 'ar 4/30/98 19:24'! printFooter: pageNumber "Print the footer for the given page number" | fPara | self noFooter ifTrue:[^self]. fPara := self footerParagraph. fPara centered. fPara text: ('Page ', pageNumber printString) asText. fPara displayOn: form.! ! !TextPrinter methodsFor: 'other' stamp: 'ar 4/30/98 18:38'! in2pix: aPoint "Convert aPoint from inches to actual pixels" ^(aPoint * self resolution) rounded! ! !TextPrinter methodsFor: 'other' stamp: 'ar 4/30/98 18:38'! mm2in: aPoint "Convert aPoint from millimeters to inches" ^aPoint / 25.4! ! !TextPrinter methodsFor: 'other' stamp: 'ar 4/30/98 18:39'! pix2in: aPoint "Convert aPoint from a pixel value to inches" ^aPoint / self resolution! ! !TextPrinter methodsFor: 'private' stamp: 'ar 4/30/98 19:40'! pixelSize "Return the size of the page in pixels" ^self in2pix: (self realPaperSize)! ! !TextPrinter methodsFor: 'private' stamp: 'ar 4/30/98 19:39'! realPaperSize ^self landscape ifTrue:[self paperSize y @ self paperSize x] ifFalse:[self paperSize]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextPrinter class instanceVariableNames: ''! !TextPrinter class methodsFor: 'class initialization' stamp: 'ar 4/30/98 18:30'! initialize "TextPrinter initialize" self defaultPaperSize: self paperSizeA4.! ! !TextPrinter class methodsFor: 'accessing' stamp: 'ar 4/30/98 18:31'! defaultPaperSize ^DefaultPaperSize! ! !TextPrinter class methodsFor: 'accessing' stamp: 'ar 4/30/98 18:31'! defaultPaperSize: aPoint DefaultPaperSize := aPoint! ! !TextPrinter class methodsFor: 'accessing' stamp: 'dew 3/7/2000 20:39'! defaultTextPrinter "This is the global default TextPrinter instance." DefaultTextPrinter isNil ifTrue: [DefaultTextPrinter _ self new]. ^DefaultTextPrinter! ! !TextPrinter class methodsFor: 'paper sizes' stamp: 'ar 4/30/98 18:30'! mm2in: aPoint "Convert aPoint from millimeters to inches" ^aPoint / 25.4! ! !TextPrinter class methodsFor: 'paper sizes' stamp: 'ar 4/30/98 18:27'! paperSizeA4 ^self mm2in: 210@297! ! WriteStream subclass: #TextStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !TextStream methodsFor: 'as yet unclassified' stamp: 'dvf 10/1/2003 02:51'! nextPutAll: aCollection "Optimized access to get around Text at:Put: overhead" | n | n _ aCollection size. position + n > writeLimit ifTrue: [self growTo: position + n + 10]. collection replaceFrom: position+1 to: position + n with: aCollection startingAt: 1. position _ position + n! ! !TextStream methodsFor: 'as yet unclassified' stamp: 'djp 11/6/1999 20:30'! withAttributes: attributes do: streamBlock | pos1 val | pos1 _ self position. val _ streamBlock value. attributes do: [:attribute | collection addAttribute: attribute from: pos1 + 1 to: self position]. ^ val! ! Object subclass: #TextStyle instanceVariableNames: 'fontArray fontFamilySize lineGrid baseline alignment firstIndent restIndent rightIndent tabsArray marginTabsArray leading defaultFontIndex' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'Graphics-Text'! !TextStyle commentStamp: '<historical>' prior: 0! A TextStyle comprises the formatting information for composing and displaying a unit (usually a paragraph) of text. Typically one makes a copy of a master TextStyle (such as TextStyle default), and then that copy may get altered in the process of editing. Bad things can happen if you do not copy first. Each of my instances consists of... fontArray An array of StrikeFonts or other fonts fontFamilySize unused lineGrid An integer; default line spacing for paragraphs baseline An integer; default baseline (dist from line top to bottom of an 'a') alignment An integer; text alignment, see TextStyle alignment: firstIndent An integer; indent of first line in pixels restIndent An integer; indent of remaining lines in pixels rightIndent An integer; indent of right margin rel to section tabsArray An array of integers giving tab offsets in pixels marginTabsArray An array of margin tabs leading An integer giving default vertical line separation For a concrete example, look at TextStyle default copy inspect! ]style[(367 10 226 20 381 30)f1,f1LStrikeFont Comment;,f1,f1LTextStyle alignment:;,f1,f1dTextStyle default copy inspect;;! !TextStyle methodsFor: 'accessing'! alignment "Answer the code for the current setting of the alignment." ^alignment! ! !TextStyle methodsFor: 'accessing' stamp: 'ar 9/21/2000 15:17'! alignment: anInteger "Set the current setting of the alignment to be anInteger: 0=left flush, 1=right flush, 2=centered, 3=justified." alignment _ anInteger \\ (Justified + 1)! ! !TextStyle methodsFor: 'accessing'! baseline "Answer the distance from the top of the line to the bottom of most of the characters (by convention, bottom of the letter 'A')." ^baseline! ! !TextStyle methodsFor: 'accessing'! baseline: anInteger "Set the distance from the top of the line to the bottom of most of the characters." baseline _ anInteger! ! !TextStyle methodsFor: 'accessing'! centered alignment _ 2! ! !TextStyle methodsFor: 'accessing' stamp: 'sw 12/6/1999 12:31'! defaultFont ^ fontArray at: self defaultFontIndex! ! !TextStyle methodsFor: 'accessing'! firstIndent "Answer the horizontal indenting of the first line of a paragraph in the style of the receiver." ^firstIndent! ! !TextStyle methodsFor: 'accessing'! firstIndent: anInteger "Set the horizontal indenting of the first line of a paragraph in the style of the receiver to be the argument, anInteger." firstIndent _ anInteger! ! !TextStyle methodsFor: 'accessing'! fontNamed: fontName "TextStyle default fontNamed: 'TimesRoman10'" ^ fontArray detect: [:x | x name sameAs: fontName]! ! !TextStyle methodsFor: 'accessing'! fontNames "TextStyle default fontNames" ^ fontArray collect: [:x | x name]! ! !TextStyle methodsFor: 'accessing' stamp: 'ar 9/21/2000 11:53'! fontNamesWithPointSizes ^ fontArray collect: [:x | x fontNameWithPointSize] "TextStyle default fontNamesWithPointSizes"! ! !TextStyle methodsFor: 'accessing' stamp: 'nk 6/25/2003 12:54'! isTTCStyle ^ fontArray first isTTCFont. ! ! !TextStyle methodsFor: 'accessing'! justified alignment _ 3! ! !TextStyle methodsFor: 'accessing'! leading "Leading (from typographers historical use of extra lead (type metal)) is the extra spacing above and beyond that needed just to accomodate the various font heights in the set." ^ leading! ! !TextStyle methodsFor: 'accessing'! leading: yDelta leading _ yDelta! ! !TextStyle methodsFor: 'accessing'! leftFlush alignment _ 0! ! !TextStyle methodsFor: 'accessing'! lineGrid "Answer the relative space between lines of a paragraph in the style of the receiver." ^lineGrid! ! !TextStyle methodsFor: 'accessing'! lineGrid: anInteger "Set the relative space between lines of a paragraph in the style of the receiver to be the argument, anInteger." lineGrid _ anInteger! ! !TextStyle methodsFor: 'accessing' stamp: 'sma 12/30/1999 13:57'! printOn: aStream super printOn: aStream. aStream space; nextPutAll: self defaultFont name! ! !TextStyle methodsFor: 'accessing'! restIndent "Answer the indent for all but the first line of a paragraph in the style of the receiver." ^restIndent! ! !TextStyle methodsFor: 'accessing'! restIndent: anInteger "Set the indent for all but the first line of a paragraph in the style of the receiver to be the argument, anInteger." restIndent _ anInteger! ! !TextStyle methodsFor: 'accessing'! rightFlush alignment _ 1! ! !TextStyle methodsFor: 'accessing'! rightIndent "Answer the right margin indent for the lines of a paragraph in the style of the receiver." ^rightIndent! ! !TextStyle methodsFor: 'accessing'! rightIndent: anInteger "Answer the right margin indent for the lines of a paragraph in the style of the receiver to be the argument, anInteger." rightIndent _ anInteger! ! !TextStyle methodsFor: 'tabs and margins'! leftMarginTabAt: marginIndex "Set the 'nesting' level of left margin indents of the paragraph in the style of the receiver to be the argument, marginIndex." (marginIndex > 0 and: [marginIndex < marginTabsArray size]) ifTrue: [^(marginTabsArray at: marginIndex) at: 1] ifFalse: [^0] "The marginTabsArray is an Array of tuples. The Array is indexed according to the marginIndex, the 'nesting' level of the requestor." ! ! !TextStyle methodsFor: 'tabs and margins'! nextTabXFrom: anX leftMargin: leftMargin rightMargin: rightMargin "Tab stops are distances from the left margin. Set the distance into the argument, anX, normalized for the paragraph's left margin." | normalizedX tabX | normalizedX _ anX - leftMargin. 1 to: tabsArray size do: [:i | (tabX _ tabsArray at: i) > normalizedX ifTrue: [^leftMargin + tabX min: rightMargin]]. ^rightMargin! ! !TextStyle methodsFor: 'tabs and margins'! rightMarginTabAt: marginIndex "Set the 'nesting' level of right margin indents of the paragraph in the style of the receiver to be marginIndex." (marginIndex > 0 and: [marginIndex < marginTabsArray size]) ifTrue: [^(marginTabsArray at: marginIndex) at: 2] ifFalse: [^0] "The marginTabsArray is an Array of tuples. The Array is indexed according to the marginIndex, the 'nesting' level of the requestor." ! ! !TextStyle methodsFor: 'tabs and margins'! tabWidth "Answer the width of a tab." ^DefaultTab! ! !TextStyle methodsFor: 'fonts and font indexes' stamp: 'sw 12/8/1999 18:02'! consistOnlyOf: aFont fontArray _ Array with: aFont. defaultFontIndex _ 1! ! !TextStyle methodsFor: 'fonts and font indexes' stamp: 'sw 12/6/1999 13:54'! fontIndexOf: aFont ^ fontArray indexOf: aFont ifAbsent: [nil]! ! !TextStyle methodsFor: 'fonts and font indexes' stamp: 'di 10/11/97 09:23'! fontIndexOfSize: desiredHeight "Returns an index in fontArray of the font with height <= desiredHeight" "Leading is not inluded in the comparison" | bestMatch bestIndex d | bestMatch _ 9999. bestIndex _ 1. 1 to: fontArray size do: [:i | d _ desiredHeight - (fontArray at: i) height. d = 0 ifTrue: [^ i]. (d > 0 and: [d < bestMatch]) ifTrue: [bestIndex _ i. bestMatch _ d]]. ^ bestIndex! ! !TextStyle methodsFor: 'fonts and font indexes' stamp: 'di 10/11/97 09:33'! fontOfSize: aHeight "See fontIndexOfSize. Returns the actual font. Leading not considered." ^ fontArray at: (self fontIndexOfSize: aHeight)! ! !TextStyle methodsFor: 'private'! fontArray "Only for writing out fonts, etc. 8/16/96 tk" ^ fontArray! ! !TextStyle methodsFor: 'private' stamp: 'di 3/20/1999 22:31'! fontAt: index "This is private because no object outside TextStyle should depend on the representation of the font family in fontArray." ^ fontArray atPin: index! ! !TextStyle methodsFor: 'private'! gridForFont: fontIndex withLead: leadInteger "Force whole style to suit one of its fonts. Assumes only one font referred to by runs." | font | font _ self fontAt: fontIndex. self lineGrid: font height + leadInteger. self baseline: font ascent. self leading: leadInteger! ! !TextStyle methodsFor: 'private' stamp: 'tk 8/20/96'! newFontArray: anArray "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. , Make size depend on first font." fontArray _ anArray. lineGrid _ (fontArray at: 1) height + leading. "For whole family" baseline _ (fontArray at: 1) ascent + leading. alignment _ 0. firstIndent _ 0. restIndent _ 0. rightIndent _ 0. tabsArray _ DefaultTabsArray. marginTabsArray _ DefaultMarginTabsArray " TextStyle allInstancesDo: [:ts | ts newFontArray: TextStyle default fontArray]. "! ! !TextStyle methodsFor: 'Disk I/O' stamp: 'di 11/19/1999 20:12'! veryDeepCopyWith: deepCopier "All inst vars are meant to be shared" self == #veryDeepCopyWith:. "to satisfy checkVariables" ^ deepCopier references at: self ifAbsent: [ deepCopier references at: self put: self clone]. "remember"! ! !TextStyle methodsFor: 'default font' stamp: 'sw 12/6/1999 12:30'! defaultFontIndex ^ defaultFontIndex ifNil: [defaultFontIndex _ 1]! ! !TextStyle methodsFor: 'default font' stamp: 'sw 12/6/1999 13:50'! defaultFontIndex: anIndex defaultFontIndex _ anIndex! ! !TextStyle methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:18'! = other self species == other species ifFalse: [^ false]. 1 to: self class instSize do: [:i | (self instVarAt: i) == (other instVarAt: i) ifFalse: [^ false]]. ^ true! ! !TextStyle methodsFor: 'comparing' stamp: 'ar 9/9/2003 22:04'! hash "#hash is re-implemented because #= is re-implemented" ^fontArray hash ! ! !TextStyle methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:18'! species ^TextStyle! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TextStyle class instanceVariableNames: ''! !TextStyle class methodsFor: 'TextConstants access' stamp: 'nk 7/3/2003 19:12'! actualTextStyles | aDict | "TextStyle actualTextStyles" "Answer dictionary whose keys are the names of styles in the system and whose values are the actual styles" aDict _ TextConstants select: [:thang | thang isKindOf: self ]. aDict removeKey: #DefaultTextStyle. aDict removeKey: #DefaultFixedTextStyle. ^ aDict! ! !TextStyle class methodsFor: 'TextConstants access' stamp: 'nk 7/3/2003 19:06'! fontArrayForStyle: aName "Answer the fonts in the style named aName, or an empty Array if no such named style." "TextStyle fontArrayForStyle: #Atlanta" "TextStyle fontPointSizesFor: 'NewYork'" ^ ((self named: aName) ifNil: [ ^#() ]) fontArray ! ! !TextStyle class methodsFor: 'TextConstants access' stamp: 'nk 7/3/2003 18:56'! fontPointSizesFor: aName "Answer the point sizes for all the fonts in the given text style" "TextStyle fontPointSizesFor: 'Arial'" "TextStyle fontPointSizesFor: 'NewYork'" ^ (self fontArrayForStyle: aName) collect: [:f | f pointSize] ! ! !TextStyle class methodsFor: 'TextConstants access' stamp: 'nk 7/3/2003 19:00'! knownTextStyles "Answer the names of the known text styles, sorted in alphabetical order" "TextStyle knownTextStyles" ^ (TextConstants select: [:thang | thang isKindOf: TextStyle]) keys asSortedArray ! ! !TextStyle class methodsFor: 'class initialization' stamp: 'nk 3/25/2004 17:51'! initialize self initializeStyleDecoder.! ! !TextStyle class methodsFor: 'class initialization' stamp: 'nk 3/25/2004 17:53'! initializeStyleDecoder TextConstants at: #StyleDecoder put: nil. self styleDecoder.! ! !TextStyle class methodsFor: 'class initialization' stamp: 'nk 3/25/2004 17:57'! styleDecoder TextConstants at: #StyleDecoder ifPresent: [ :dict | dict ifNotNil: [ ^dict ]]. ^TextConstants at: #StyleDecoder put: ( Dictionary new at: 'Regular' put: 0; at: 'Roman' put: 0; at: 'Medium' put: 0; at: 'Light' put: 0; at: 'Normal' put: 0; at: 'Plain' put: 0; at: 'Book' put: 0; at: 'Demi' put: 0; at: 'Demibold' put: 0; at: 'Semibold' put: 0; at: 'SemiBold' put: 0; at: 'ExtraBold' put: 1; at: 'SuperBold' put: 1; at: 'B' put: 1; at: 'I' put: 2; at: 'U' put: 4; at: 'X' put: 16; at: 'N' put: 8; at: 'Bold' put: 1; at: 'Italic' put: 2; at: 'Oblique' put: 2; at: 'Narrow' put: 8; at: 'Condensed' put: 8; at: 'Underlined' put: 4; yourself )! ! !TextStyle class methodsFor: 'constants'! default "Answer the system default text style." ^DefaultTextStyle! ! !TextStyle class methodsFor: 'constants' stamp: 'sw 12/6/1999 12:32'! defaultFont "Answer the default system font" ^ DefaultTextStyle defaultFont! ! !TextStyle class methodsFor: 'constants' stamp: 'nk 7/3/2003 19:11'! named: familyName "Answer the TextStyle with the given name, or nil." "TextStyle named: 'NewYork'" | textStyle | textStyle _ TextConstants at: familyName ifAbsent: [ ^nil ]. (textStyle isKindOf: self) ifFalse: [ ^nil ]. ^textStyle! ! !TextStyle class methodsFor: 'instance creation'! fontArray: anArray "Answer an instance of me with fonts those in the argument, anArray." ^self new newFontArray: anArray! ! !TextStyle class methodsFor: 'instance creation'! new ^ super new leading: 2! ! !TextStyle class methodsFor: 'user interface' stamp: 'dgd 10/8/2003 18:38'! fontSizeSummary "Open a text window with a simple summary of the available sizes in each of the fonts in the system." "TextStyle fontSizeSummary" | aString aList | aList _ self knownTextStyles. aString _ String streamContents: [:aStream | aList do: [:aStyleName | aStream nextPutAll: aStyleName, ' ', (self fontPointSizesFor: aStyleName) asArray storeString. aStream cr]]. (StringHolder new contents: aString) openLabel: 'Font styles and sizes' translated! ! !TextStyle class methodsFor: 'user interface' stamp: 'nk 7/3/2003 19:01'! mvcPromptForFont: aPrompt andSendTo: aTarget withSelector: aSelector "MVC Only!! prompt for a font and if one is provided, send it to aTarget using a message with selector aSelector." | aMenu aChoice aStyle namesAndSizes aFont | "TextStyle mvcPromptForFont: 'Choose system font style' andSendTo: TextStyle withSelector: #setSystemFontTo:" aMenu _ CustomMenu new. self actualTextStyles keys do: [:styleName | aMenu add: styleName action: styleName]. aChoice _ aMenu startUpWithCaption: aPrompt. aChoice ifNil: [^ self]. aMenu _ CustomMenu new. aStyle _ self named: aChoice. (namesAndSizes _ aStyle fontNamesWithPointSizes) do: [:aString | aMenu add: aString action: aString]. aChoice _ aMenu startUpWithCaption: nil. aChoice ifNil: [^ self]. aFont _ aStyle fontAt: (namesAndSizes indexOf: aChoice). aTarget perform: aSelector with: aFont! ! !TextStyle class methodsFor: 'utilities' stamp: 'nk 4/2/2004 11:26'! pixelsPerInch "Answer the nominal resolution of the screen." ^TextConstants at: #pixelsPerInch ifAbsentPut: [ 96.0 ].! ! !TextStyle class methodsFor: 'utilities' stamp: 'nk 4/2/2004 11:22'! pointsToPixels: points ^points * self pixelsPerInch / 72.0! ! Magnitude subclass: #Time instanceVariableNames: 'seconds nanos' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !Time commentStamp: '<historical>' prior: 0! This represents a period of time.! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 15:54'! < aTime ^ self asDuration < aTime asDuration! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:11'! = aTime ^ [ self ticks = aTime ticks ] on: MessageNotUnderstood do: [false]! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:32'! duration ^ Duration zero ! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:11'! hash ^ self ticks hash ! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:10'! hour ^ self hour24 ! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:17'! hour24 ^ self asDuration hours ! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 22:08'! minute ^ self asDuration minutes! ! !Time methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 19:19'! second ^ self asDuration seconds! ! !Time methodsFor: 'deprecated' stamp: 'brp 8/23/2003 19:03'! hours: anInteger self deprecated: 'Deprecated'; hours: anInteger minutes: 0 seconds: 0. ! ! !Time methodsFor: 'deprecated' stamp: 'brp` 8/24/2003 19:27'! hours: hourInteger minutes: minInteger seconds: secInteger self deprecated: 'Deprecated'; setSeconds: (hourInteger * SecondsInHour) + (minInteger * SecondsInMinute) + secInteger. ! ! !Time methodsFor: 'deprecated' stamp: 'brp` 8/24/2003 19:28'! setSeconds: secondCount self deprecated: 'Deprecated'. self ticks: { 0. secondCount. 0 } ! ! !Time methodsFor: 'printing' stamp: 'BP 3/30/2001 15:25'! hhmm24 "Return a string of the form 1123 (for 11:23 am), 2154 (for 9:54 pm), of exactly 4 digits" ^(String streamContents: [ :aStream | self print24: true showSeconds: false on: aStream ]) copyWithout: $:! ! !Time methodsFor: 'printing' stamp: 'BP 3/30/2001 15:25'! print24 "Return as 8-digit string 'hh:mm:ss', with leading zeros if needed" ^String streamContents: [ :aStream | self print24: true on: aStream ] ! ! !Time methodsFor: 'printing' stamp: 'BP 3/30/2001 15:25'! print24: hr24 on: aStream "Format is 'hh:mm:ss' or 'h:mm:ss am' " self print24: hr24 showSeconds: true on: aStream ! ! !Time methodsFor: 'printing' stamp: 'brp 2/16/2004 09:10'! print24: hr24 showSeconds: showSeconds on: aStream "Format is 'hh:mm:ss' or 'h:mm:ss am' or, if showSeconds is false, 'hh:mm' or 'h:mm am'" | h m s | h _ self hour. m _ self minute. s _ self second. hr24 ifTrue: [ h < 10 ifTrue: [ aStream nextPutAll: '0' ]. h printOn: aStream ] ifFalse: [ h > 12 ifTrue: [h - 12 printOn: aStream] ifFalse: [h < 1 ifTrue: [ 12 printOn: aStream ] ifFalse: [ h printOn: aStream ]]]. aStream nextPutAll: (m < 10 ifTrue: [':0'] ifFalse: [':']). m printOn: aStream. showSeconds ifTrue: [ aStream nextPutAll: (s < 10 ifTrue: [':0'] ifFalse: [':']). s asInteger printOn: aStream ]. hr24 ifFalse: [ aStream nextPutAll: (h < 12 ifTrue: [' am'] ifFalse: [' pm']) ]. ! ! !Time methodsFor: 'printing' stamp: 'brp 8/23/2003 19:14'! printOn: aStream self print24: false showSeconds: (self seconds ~= 0) on: aStream! ! !Time methodsFor: 'printing' stamp: 'BP 3/30/2001 15:25'! storeOn: aStream aStream print: self printString; nextPutAll: ' asTime'! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 19:02'! addTime: timeAmount "Answer a Time that is timeInterval after the receiver. timeInterval is an instance of Date or Time." ^ self class seconds: self asSeconds + timeAmount asSeconds! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 15:55'! asSeconds "Answer the number of seconds since midnight of the receiver." ^ seconds! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:29'! hours ^ self hour! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 19:24'! intervalString "Treat the time as a difference. Give it in hours and minutes with two digits of accuracy." | d | d _ self asDuration. ^ String streamContents: [ :s | d hours > 0 ifTrue: [s print: d hours; nextPutAll: ' hours']. d minutes > 0 ifTrue: [s space; print: d minutes; nextPutAll: ' minutes']. d seconds > 0 ifTrue: [s space; print: d seconds; nextPutAll: ' seconds'] ]. ! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 22:07'! minutes ^ self asDuration minutes! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 18:18'! seconds ^ self second! ! !Time methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 19:03'! subtractTime: timeAmount "Answer a Time that is timeInterval before the receiver. timeInterval is an instance of Date or Time." ^ self class seconds: self asSeconds - timeAmount asSeconds! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 23:58'! asDate ^ Date today! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:26'! asDateAndTime ^ DateAndTime today + self! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:01'! asDuration "Answer the duration since midnight" ^ Duration seconds: seconds nanoSeconds: nanos ! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:29'! asMonth ^ self asDateAndTime asMonth! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:29'! asNanoSeconds "Answer the number of nanoseconds since midnight" ^ self asDuration asNanoSeconds ! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:08'! asTime ^ self! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:27'! asTimeStamp ^ self asDateAndTime asTimeStamp! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:43'! asYear ^ self asDateAndTime asYear! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:33'! nanoSecond ^ nanos ! ! !Time methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:35'! to: anEnd "Answer a Timespan. anEnd must respond to #asDateAndTime" ^ self asDateAndTime to: anEnd! ! !Time methodsFor: 'private' stamp: 'brp 8/23/2003 22:38'! ticks "Answer an Array: { seconds. nanoSeconds }" ^ Array with: 0 with: seconds with: nanos.! ! !Time methodsFor: 'private' stamp: 'brp 8/23/2003 20:44'! ticks: anArray "ticks is an Array: { days. seconds. nanoSeconds }" seconds _ anArray second. nanos _ anArray third.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Time class instanceVariableNames: ''! !Time class methodsFor: 'general inquiries' stamp: 'nk 3/8/2004 12:05'! millisecondClockValue "Answer the number of milliseconds since the millisecond clock was last reset or rolled over. Answer 0 if the primitive fails." <primitive: 135> ^ 0! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 23:59'! dateAndTimeFromSeconds: secondCount ^ Array with: (Date fromSeconds: secondCount) with: (Time fromSeconds: secondCount \\ 86400) ! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 19:50'! dateAndTimeNow "Answer a two-element Array of (Date today, Time now)." ^ self dateAndTimeFromSeconds: self totalSeconds! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:11'! fromSeconds: secondCount "Answer an instance of me that is secondCount number of seconds since midnight." ^ self seconds: secondCount ! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:11'! millisecondsToRun: timedBlock "Answer the number of milliseconds timedBlock takes to return its value." | initialMilliseconds | initialMilliseconds _ self millisecondClockValue. timedBlock value. ^ self millisecondClockValue - initialMilliseconds! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 20:01'! new "Answer a Time representing midnight" ^ self midnight! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 22:01'! primSecondsClock "Answer the number of seconds since 00:00 on the morning of January 1, 1901 (a 32-bit unsigned number). Essential. See Object documentation whatIsAPrimitive. " <primitive: 137> self primitiveFailed! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 8/23/2003 20:07'! readFrom: aStream "Read a Time from the stream in the form: <hour>:<minute>:<second> <am/pm> <minute>, <second> or <am/pm> may be omitted. e.g. 1:59:30 pm; 8AM; 15:30" | hour minute second ampm | hour _ Integer readFrom: aStream. minute _ 0. second _ 0. (aStream peekFor: $:) ifTrue: [ minute _ Integer readFrom: aStream. (aStream peekFor: $:) ifTrue: [ second _ Integer readFrom: aStream ]]. aStream skipSeparators. (aStream atEnd not and: [aStream peek isLetter]) ifTrue: [ampm _ aStream next asLowercase. (ampm = $p and: [hour < 12]) ifTrue: [hour _ hour + 12]. (ampm = $a and: [hour = 12]) ifTrue: [hour _ 0]. (aStream peekFor: $m) ifFalse: [aStream peekFor: $M ]]. ^ self hour: hour minute: minute second: second "Time readFrom: (ReadStream on: '2:23:09 pm')" ! ! !Time class methodsFor: 'smalltalk-80' stamp: 'brp 7/27/2003 16:12'! totalSeconds "Answer the total seconds since the Squeck epoch: 1 January 1901." ^ self primSecondsClock! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 19:46'! current ^ self now! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 22:34'! fromString: aString ^ self readFrom: aString readStream ! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:05'! hour: hour minute: minute second: second "Answer a Time" ^ self hour: hour minute: minute second: second nanoSecond: 0! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp` 8/24/2003 19:26'! hour: hour minute: minute second: second nanoSecond: nanoCount "Answer a Time - only second precision for now" ^ self seconds: (hour * SecondsInHour) + (minute * SecondsInMinute) + second nanoSeconds: nanoCount! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:01'! midnight ^ self seconds: 0 ! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:47'! seconds: seconds "Answer a Time from midnight" ^ self seconds: seconds nanoSeconds: 0! ! !Time class methodsFor: 'squeak protocol' stamp: 'brp 8/23/2003 20:46'! seconds: seconds nanoSeconds: nanoCount "Answer a Time from midnight" ^ self basicNew ticks: (Duration seconds: seconds nanoSeconds: nanoCount) ticks; yourself ! ! !Time class methodsFor: 'ansi protocol' stamp: 'brp 8/23/2003 18:56'! now "Answer a Time representing the time right now - this is a 24 hour clock." ^ self seconds: self totalSeconds \\ 86400. ! ! MessageSet subclass: #TimeProfileBrowser instanceVariableNames: 'selectedClass selectedSelector block tally' classVariableNames: 'TextMenu' poolDictionaries: '' category: 'Tools-Debugger'! !TimeProfileBrowser commentStamp: '<historical>' prior: 0! A TimeProfileBrowser is a browser visualizing the runtime profile of an executed Smalltalk block. It is useful for finding performance bottlenecks in code. When optimizing code it can be hard to know what methods actually constitute the bulk of the execution time. Is it a few methods that take very long time to execute or is it perhaps a single method that gets executed a thousand times? The block is first spied on using a MessageTally instance (which has even more funtionality than used by the TimeProfileBrowser) which samples the block during it's execution and collects the amount of time approximately spent in the methods executed. Then the methods are shown in the browser with their relative execution time in percent. Example: TimeProfileBrowser onBlock: [20 timesRepeat: [Transcript show: 100 factorial printString]] ! !TimeProfileBrowser methodsFor: 'accessing' stamp: 'stp 05/08/1999 11:37'! selectedClass "Answer the receiver's 'selectedClass'." ^selectedClass! ! !TimeProfileBrowser methodsFor: 'accessing' stamp: 'stp 05/08/1999 11:37'! selectedClass: anObject "Set the receiver's instance variable 'selectedClass' to be anObject." selectedClass := anObject! ! !TimeProfileBrowser methodsFor: 'accessing' stamp: 'stp 05/08/1999 11:37'! selectedSelector "Answer the receiver's 'selectedSelector'." ^selectedSelector! ! !TimeProfileBrowser methodsFor: 'accessing' stamp: 'stp 05/08/1999 11:37'! selectedSelector: anObject "Set the receiver's instance variable 'selectedSelector' to be anObject." selectedSelector := anObject! ! !TimeProfileBrowser methodsFor: 'accessing' stamp: 'stp 05/08/1999 11:37'! tally "Answer the receiver's 'tally'." ^tally! ! !TimeProfileBrowser methodsFor: 'private' stamp: 'dvf 7/5/2000 18:48'! initializeMessageList: anArray messageList _ anArray. messageListIndex _ 0. contents _ ''! ! !TimeProfileBrowser methodsFor: 'private' stamp: 'nk 3/8/2004 13:22'! messageListKey: aChar from: view "Respond to a Command key. Cmd-D means re-run block." aChar == $d ifTrue: [^Cursor execute showWhile: [ block value ]]. ^super messageListKey: aChar from: view! ! !TimeProfileBrowser methodsFor: 'private' stamp: 'stp 05/08/1999 15:27'! messageListMenu: aMenu shifted: shifted "Add a menu to the inherited one." | menu | menu := super messageListMenu: aMenu shifted: shifted. " menu addItem: (0)." ^menu! ! !TimeProfileBrowser methodsFor: 'private' stamp: 'rhi 5/17/2004 10:17'! setClassAndSelectorIn: csBlock "Decode strings of the form <selectorName> (<className> [class]) " | string strm class sel parens | self flag: #mref. "fix for faster references to methods" [string _ self selection asString. string first == $* ifTrue: [^contents := nil]. "Ignore lines starting with *" parens := string includes: $(. "Does it have open-paren?" strm := ReadStream on: string. parens ifTrue: [strm skipTo: $(. "easy case" class := strm upTo: $). strm next: 2. sel := strm upToEnd] ifFalse: [strm position: (string findString: ' class>>'). strm position > 0 ifFalse: [strm position: (string findLast: [ :ch | ch == $ ])] ifTrue: [ | subString | "find the next to last space character" subString := strm contents copyFrom: 1 to: (string findLast: [ :ch | ch == $ ]) - 1. strm position: (subString findLast: [ :ch | ch == $ ])]. "ifFalse: [strm position: (string findLast: [ :ch | ch == $ ])." class := strm upTo: $>. strm next. sel := strm upToEnd]. ^ MessageSet parse: (class, ' ', sel) toClassAndSelector: csBlock] on: Error do: [:ex | ^ contents _ nil]! ! !TimeProfileBrowser methodsFor: 'message list' stamp: 'nk 2/20/2001 10:38'! selectedMessage "Answer the source method for the currently selected message." | source | self setClassAndSelectorIn: [:class :selector | source _ class sourceMethodAt: selector ifAbsent: [^ 'Missing']. Preferences browseWithPrettyPrint ifTrue: [source _ class compilerClass new format: source in: class notifying: nil decorated: false]. self selectedClass: class. self selectedSelector: selector. ^ source asText makeSelectorBoldIn: class]. ^''! ! DateAndTime subclass: #TimeStamp instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Chronology'! !TimeStamp commentStamp: '<historical>' prior: 0! This represents a duration of 0 length that marks a particular point in time.! !TimeStamp methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:13'! asTimeStamp "Answer the receiver as an instance of TimeStamp." ^ self! ! !TimeStamp methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:14'! date "Answer the date of the receiver." ^ self asDate! ! !TimeStamp methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:17'! printOn: aStream "Print receiver's date and time on aStream." aStream nextPutAll: self date printString; space; nextPutAll: self time printString.! ! !TimeStamp methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:17'! storeOn: aStream aStream print: self printString; nextPutAll: ' asTimeStamp'! ! !TimeStamp methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:15'! time "Answer the time of the receiver." ^ self asTime! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TimeStamp class instanceVariableNames: ''! !TimeStamp class methodsFor: '*monticello-instance creation' stamp: 'cbc 2/4/2004 21:30'! fromString: aString "Answer a new instance for the value given by aString. TimeStamp fromString: '1-10-2000 11:55:00 am'. " ^self readFrom: (ReadStream on: aString).! ! !TimeStamp class methodsFor: '*monticello-instance creation' stamp: 'cbc 2/4/2004 21:17'! readFrom: stream | date time | stream skipSeparators. date _ Date readFrom: stream. stream peek = $, ifTrue: [stream next]. stream skipSeparators. time _ Time readFrom: stream. ^self date: date time: time! ! !TimeStamp class methodsFor: 'squeak protocol' stamp: 'brp 3/12/2004 15:49'! current ^ self now ! ! !TimeStamp class methodsFor: 'ansi protocol' stamp: 'brp 3/12/2004 15:52'! now | ts ticks | ts _ super now. ticks _ ts ticks. ticks at: 3 put: 0. ts ticks: ticks offset: ts offset. ^ ts! ! Object subclass: #TimeZone instanceVariableNames: 'offset abbreviation name' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !TimeZone commentStamp: 'brp 9/4/2003 06:32' prior: 0! TimeZone is a simple class to colect the information identifying a UTC time zone. offset - Duration - the time zone's offset from UTC abbreviation - String - the abbreviated name for the time zone. name - String - the name of the time zone. TimeZone class >> #timeZones returns an array of the known time zones TimeZone class >> #default returns the default time zone (Grenwich Mean Time)! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:28'! abbreviation ^ abbreviation ! ! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:28'! abbreviation: aString abbreviation _ aString ! ! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:29'! name ^ name ! ! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:28'! name: aString name _ aString ! ! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:28'! offset ^ offset! ! !TimeZone methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:28'! offset: aDuration offset _ aDuration! ! !TimeZone methodsFor: 'private' stamp: 'brp 9/4/2003 06:37'! printOn: aStream super printOn: aStream. aStream nextPut: $(; nextPutAll: self abbreviation; nextPut: $).! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TimeZone class instanceVariableNames: ''! !TimeZone class methodsFor: 'accessing' stamp: 'brp 9/4/2003 06:38'! default "Answer the default time zone - GMT" ^ self timeZones detect: [ :tz | tz offset = Duration zero ] ! ! !TimeZone class methodsFor: 'accessing' stamp: 'nk 3/30/2004 10:21'! timeZones ^ { self offset: 0 hours name: 'Universal Time' abbreviation: 'UTC'. self offset: 0 hours name: 'Greenwich Mean Time' abbreviation: 'GMT'. self offset: 0 hours name: 'British Summer Time' abbreviation: 'BST'. self offset: 2 hours name: 'South African Standard Time' abbreviation: 'SAST'. self offset: -8 hours name: 'Pacific Standard Time' abbreviation: 'PST'. self offset: -7 hours name: 'Pacific Daylight Time' abbreviation: 'PDT'. } ! ! !TimeZone class methodsFor: 'instance creation' stamp: 'brp 9/4/2003 06:33'! offset: aDuration name: aName abbreviation: anAbbreviation ^ self new offset: aDuration; name: aName; abbreviation: anAbbreviation; yourself! ! Magnitude subclass: #Timespan instanceVariableNames: 'start duration' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Chronology'! !Timespan commentStamp: 'brp 5/13/2003 08:07' prior: 0! I represent a duration starting on a specific DateAndTime. ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 9/15/2003 14:05'! + operand "operand conforms to protocol Duration" ^ self class starting: (self start + operand) duration: self duration ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 9/15/2003 14:07'! - operand "operand conforms to protocol DateAndTime or protocol Duration" ^ (operand respondsTo: #asDateAndTime) ifTrue: [ self start - operand ] ifFalse: [ self + (operand negated) ]. ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:43'! < comparand ^ self start < comparand ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:43'! = comparand ^ (self start = comparand start) and: [self duration = comparand duration] ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 7/27/2003 17:49'! dayOfMonth "Answer the day of the month represented by the receiver." ^ start dayOfMonth! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 8/6/2003 18:42'! dayOfWeek "Answer the day of the week represented by the receiver." ^ start dayOfWeek! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 8/6/2003 18:42'! dayOfWeekName "Answer the day of the week represented by the receiver." ^ start dayOfWeekName! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 8/24/2003 11:50'! dayOfYear "Answer the day of the year represented by the receiver." ^ start dayOfYear! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:44'! hash ^ start hash + duration hash ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:44'! isLeapYear ^ start isLeapYear ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:44'! month ^ start month ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:44'! monthName ^ start monthName ! ! !Timespan methodsFor: 'ansi protocol' stamp: 'brp 5/13/2003 08:44'! year ^ start year ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:44'! asDate ^ start asDate ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:44'! asDateAndTime ^ start ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/30/2003 00:10'! asDuration ^ self duration! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:45'! asMonth ^ start asMonth ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:45'! asTime ^ start asTime! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:25'! asTimeStamp ^ start asTimeStamp! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:45'! asYear ^ start asYear! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:45'! duration "Answer the Duration of this timespan" ^ duration ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:45'! end ^ self next start - DateAndTime clockPrecision ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 1/7/2004 16:05'! includes: aDateAndTime ^ (aDateAndTime isKindOf: Timespan) ifTrue: [ (self includes: aDateAndTime start) and: [ self includes: aDateAndTime end ] ] ifFalse: [ aDateAndTime asDateAndTime between: start and: self end ] ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:54'! includesAllOf: aCollection "Answer whether all the elements of aCollection are in the receiver." aCollection do: [:elem | (self includes: elem) ifFalse: [^ false]]. ^ true ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 1/7/2004 15:59'! includesAnyOf: aCollection "Answer whether any element of aCollection is included in the receiver" aCollection do: [ :elem | (self includes: elem) ifTrue: [^ true]]. ^false ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 17:47'! intersection: aTimespan "Return the Timespan both have in common, or nil" | aBegin anEnd | aBegin _ self start max: aTimespan start. anEnd _ self end min: aTimespan end. anEnd < aBegin ifTrue: [^nil]. ^ self class starting: aBegin ending: anEnd. ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:47'! julianDayNumber ^ start julianDayNumber ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 9/25/2003 09:17'! printOn: aStream super printOn: aStream. aStream nextPut: $(; print: start; nextPut: $D; print: duration; nextPut: $). ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:48'! start "Answer the start DateAndTime of this timespan" ^ start ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:48'! start: aDateAndTime "Store the start DateAndTime of this timespan" start _ aDateAndTime asDateAndTime ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:49'! to: anEnd "Answer an Timespan. anEnd must be aDateAndTime or a Timespan" ^ Timespan starting: (self start) ending: (anEnd asDateAndTime). ! ! !Timespan methodsFor: 'squeak protocol' stamp: 'brp 1/9/2004 16:46'! union: aTimespan "Return the Timespan spanned by both" | aBegin anEnd | aBegin _ self start min: aTimespan start. anEnd _ self end max: aTimespan end. ^ Timespan starting: aBegin ending: (anEnd + DateAndTime clockPrecision). ! ! !Timespan methodsFor: 'enumerating' stamp: 'brp 5/13/2003 08:49'! datesDo: aBlock self do: aBlock with: start asDate. ! ! !Timespan methodsFor: 'private' stamp: 'brp 5/13/2003 08:58'! do: aBlock with: aFirstElement self do: aBlock with: aFirstElement when: [ :t | true ]. ! ! !Timespan methodsFor: 'private' stamp: 'brp 5/13/2003 08:59'! do: aBlock with: aFirstElement when: aConditionBlock | element end | element _ aFirstElement. end _ self end. [ element start <= end ] whileTrue: [(aConditionBlock value: element) ifTrue: [ aBlock value: element ]. element _ element next. ]! ! !Timespan methodsFor: 'private' stamp: 'brp 5/13/2003 08:59'! duration: aDuration "Set the Duration of this timespan" duration _ aDuration ! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 14:09'! day "Answer the day of the year represented by the receiver." ^ self dayOfYear! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 08:45'! daysInMonth ^ start daysInMonth ! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 08:45'! daysInYear "Answer the number of days in the month represented by the receiver." ^ start daysInYear ! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 17:50'! daysLeftInYear ^ start daysLeftInYear! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 17:55'! firstDayOfMonth ^ start firstDayOfMonth! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 08:47'! monthIndex ^ self month ! ! !Timespan methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 08:47'! next ^ self class starting: (start + duration) duration: duration ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Timespan class instanceVariableNames: ''! !Timespan class methodsFor: 'squeak protocol' stamp: 'brp 5/21/2003 08:35'! current ^ self starting: DateAndTime now ! ! !Timespan class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 18:49'! new "Answer a Timespan starting on the Squeak epoch: 1 January 1901" ^ self starting: DateAndTime new ! ! !Timespan class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 08:42'! starting: aDateAndTime ^ self starting: aDateAndTime duration: Duration zero ! ! !Timespan class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 18:48'! starting: aDateAndTime duration: aDuration ^ self basicNew start: aDateAndTime asDateAndTime; duration: aDuration; yourself.! ! !Timespan class methodsFor: 'squeak protocol' stamp: 'brp 7/27/2003 16:16'! starting: startDateAndTime ending: endDateAndTime ^ self starting: startDateAndTime duration: (endDateAndTime asDateAndTime - startDateAndTime). ! ! WriteStream subclass: #TranscriptStream instanceVariableNames: '' classVariableNames: 'AccessSema' poolDictionaries: '' category: 'Collections-Streams'! !TranscriptStream commentStamp: '<historical>' prior: 0! This class is a much simpler implementation of Transcript protocol that supports multiple views and very simple conversion to morphic. Because it inherits from Stream, it is automatically compatible with code that is designe to write to streams.! !TranscriptStream methodsFor: 'initialization' stamp: 'BG 10/29/2003 08:05'! open | openCount | openCount _ 0. self dependents do: [:d | ((d isKindOf: PluggableTextView) ) ifTrue: [openCount _ openCount + 1]]. openCount = 0 ifTrue: [self openLabel: 'Transcript'] ifFalse: [self openLabel: 'Transcript #' , (openCount+1) printString]! ! !TranscriptStream methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:13'! openLabel: aString "Open a window on this transcriptStream" | topView codeView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. topView label: aString. topView minimumSize: 100 @ 50. codeView _ PluggableTextView on: self text: nil accept: nil readSelection: nil menu: #codePaneMenu:shifted:. codeView window: (0@0 extent: 200@200). topView addSubView: codeView. topView controller open! ! !TranscriptStream methodsFor: 'access' stamp: 'di 3/16/1999 21:38'! characterLimit "Tell the views how much to retain on screen" ^ 20000! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'sma 3/15/2000 21:28'! bs self position > 0 ifTrue: [^ self skip: -1]. self changed: #bs! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'di 5/8/1998 12:35'! clear "Clear all characters and redisplay the view" self changed: #clearText. self reset! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'mir 1/11/2000 11:41'! endEntry "Display all the characters since the last endEntry, and reset the stream" self semaphore critical:[ self changed: #appendEntry. self reset. ].! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'sma 4/22/2000 16:58'! flush self endEntry! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'di 5/8/1998 12:35'! pastEndPut: anObject "If the stream reaches its limit, just output the contents and reset." self endEntry. ^ self nextPut: anObject! ! !TranscriptStream methodsFor: 'stream extensions' stamp: 'sma 2/26/2000 19:31'! show: anObject "TextCollector compatibility" self nextPutAll: anObject asString; endEntry! ! !TranscriptStream methodsFor: 'model protocol' stamp: 'di 5/27/1998 16:44'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items" ^ StringHolder basicNew codePaneMenu: aMenu shifted: shifted ! ! !TranscriptStream methodsFor: 'model protocol' stamp: 'di 5/29/1998 17:13'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !TranscriptStream methodsFor: 'model protocol' stamp: 'di 5/3/1999 22:49'! release self dependents do: [:view | (view isMorph and: [view isInWorld not]) ifTrue: [self removeDependent: view]]! ! !TranscriptStream methodsFor: 'model protocol' stamp: 'sw 3/2/2001 10:18'! step "Objects that may be models of SystemWindows need to respond to this, albeit vacuously"! ! !TranscriptStream methodsFor: 'private' stamp: 'mir 1/11/2000 11:41'! semaphore ^AccessSema ifNil:[AccessSema _ Semaphore forMutualExclusion]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TranscriptStream class instanceVariableNames: ''! !TranscriptStream class methodsFor: 'as yet unclassified' stamp: 'di 5/8/1998 13:51'! new ^ self on: (String new: 1000) " INSTALLING: TextCollector allInstances do: [:t | t breakDependents. t become: TranscriptStream new]. TESTING: (Execute this text in a workspace) Do this first... tt _ TranscriptStream new. tt openLabel: 'Transcript test 1'. Then this will open a second view -- ooooh... tt openLabel: 'Transcript test 2'. And finally make them do something... tt clear. [Sensor anyButtonPressed] whileFalse: [1 to: 20 do: [:i | tt print: (2 raisedTo: i-1); cr; endEntry]]. "! ! !TranscriptStream class methodsFor: 'as yet unclassified' stamp: 'di 5/8/1998 12:44'! newTranscript: aTextCollector "Store aTextCollector as the value of the system global Transcript." Smalltalk at: #Transcript put: aTextCollector! ! !TranscriptStream class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:05'! initialize self registerInFlapsRegistry. ! ! !TranscriptStream class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:06'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(TranscriptStream openMorphicTranscript 'Transcript' 'A Transcript is a window usable for logging and debugging; browse references to #Transcript for examples of how to write to it.') forFlapNamed: 'Tools'] ! ! !TranscriptStream class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:41'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! ReadWriteStream subclass: #Transcripter instanceVariableNames: 'frame para' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !Transcripter commentStamp: '<historical>' prior: 0! Transcripter is a dog-simple scrolling stream with display. It is intended to operate with no support from MVC or color in a minimal, or headless version of Squeak. No attention has been paid to appearance or performance.! !Transcripter methodsFor: 'initialization' stamp: 'di 8/14/97 12:44'! initInFrame: rect frame _ rect insetBy: 2. "Leave room for border" para _ Paragraph withText: self contents asText style: TextStyle default compositionRectangle: ((frame insetBy: 4) withHeight: 9999) clippingRectangle: frame foreColor: self black backColor: self white! ! !Transcripter methodsFor: 'accessing' stamp: 'di 8/14/97 12:41'! clear Display fill: (frame insetBy: -2) fillColor: self black; fill: frame fillColor: self white. self on: (String new: 100); endEntry! ! !Transcripter methodsFor: 'accessing' stamp: 'di 8/14/97 12:44'! endEntry | c d cb | c _ self contents. Display extent ~= DisplayScreen actualScreenSize ifTrue: ["Handle case of user resizing physical window" DisplayScreen startUp. frame _ frame intersect: Display boundingBox. ^ self clear; show: c]. para setWithText: c asText style: TextStyle default compositionRectangle: ((frame insetBy: 4) withHeight: 9999) clippingRectangle: frame foreColor: self black backColor: self white. d _ para compositionRectangle bottom - frame bottom. d > 0 ifTrue: ["Scroll up to keep all contents visible" cb _ para characterBlockAtPoint: para compositionRectangle topLeft + (0@(d+para lineGrid)). self on: (c copyFrom: cb stringIndex to: c size). readLimit_ position_ collection size. ^ self endEntry]. para display! ! !Transcripter methodsFor: 'accessing' stamp: 'sma 2/26/2000 19:35'! show: anObject self nextPutAll: anObject asString; endEntry! ! !Transcripter methodsFor: 'command line' stamp: 'di 8/12/97 22:11'! confirm: queryString | choice | [true] whileTrue: [choice _ self request: queryString , ' Please type yes or no followed by return'. choice first asUppercase = $Y ifTrue: [^ true]. choice first asUppercase = $N ifTrue: [^ false]]! ! !Transcripter methodsFor: 'command line' stamp: 'di 11/3/2000 18:52'! readEvalPrint | line okToRevert | okToRevert _ true. [#('quit' 'exit' 'done' ) includes: (line _ self request: '>')] whileFalse: [line = 'revert' ifTrue: [okToRevert ifTrue: [Utilities revertLastMethodSubmission. self cr; show: 'reverted: ' , Utilities mostRecentlySubmittedMessage. okToRevert _ false] ifFalse: [self cr; show: 'Only one level of revert currently supported']] ifFalse: [self cr; show: ([Compiler evaluate: line] ifError: [:err :ex | err])]]! ! !Transcripter methodsFor: 'command line' stamp: 'sma 2/26/2000 19:39'! request: prompt | startPos char contents | self cr; show: prompt. startPos _ position. [[Sensor keyboardPressed] whileFalse. (char _ Sensor keyboard) = Character cr] whileFalse: [char = Character backspace ifTrue: [readLimit _ position _ (position - 1 max: startPos)] ifFalse: [self nextPut: char]. self endEntry]. contents _ self contents. ^ contents copyFrom: startPos + 1 to: contents size! ! !Transcripter methodsFor: 'private' stamp: 'di 8/14/97 12:12'! black Display depth = 1 ifTrue: [^ Bitmap with: 16rFFFFFFFF "Works without color support"]. ^ Color black! ! !Transcripter methodsFor: 'private' stamp: 'di 8/14/97 12:12'! white Display depth = 1 ifTrue: [^ Bitmap with: 0 "Works without color support"]. ^ Color white! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Transcripter class instanceVariableNames: ''! !Transcripter class methodsFor: 'instance creation' stamp: 'di 8/14/97 12:09'! newInFrame: frame " (Transcripter newInFrame: (0@0 extent: 100@200)) nextPutAll: 'Hello there'; endEntry; cr; print: 355.0/113; endEntry; readEvalPrint. " | transcript | transcript _ self on: (String new: 100). transcript initInFrame: frame. ^ transcript clear! ! !Transcripter class methodsFor: 'utilities' stamp: 'di 11/3/2000 18:47'! emergencyEvaluator (Transcripter newInFrame: (0@0 corner: 320@200)) show: 'Type ''revert'' to revert your last method change. Type ''exit'' to exit the emergency evaluator.'; readEvalPrint! ! ArrayedCollection variableSubclass: #TranslatedMethod instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! TranslatedMethod class instanceVariableNames: ''! !TranslatedMethod class methodsFor: 'class initialization' stamp: 'ikp 1/10/98 02:34'! initialize self becomeCompact. Smalltalk recreateSpecialObjectsArray. Smalltalk specialObjectsArray size = 41 ifFalse: [self error: 'Please check size of special objects array!!']! ! Color subclass: #TranslucentColor instanceVariableNames: 'alpha' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !TranslucentColor commentStamp: '<historical>' prior: 0! 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. An alpha of zero is transparent, and 1.0 is opaque.! !TranslucentColor methodsFor: 'accessing'! alpha "Return my alpha value, a number between 0.0 and 1.0 where 0.0 is completely transparent and 1.0 is completely opaque." ^ alpha asFloat / 255.0 ! ! !TranslucentColor methodsFor: 'equality'! hash ^ rgb bitXor: alpha ! ! !TranslucentColor methodsFor: 'printing' stamp: 'mir 7/21/1999 11:43'! storeArrayValuesOn: aStream self isTransparent ifTrue: [ ^ aStream space]. super storeArrayValuesOn: aStream. aStream space. (self alpha roundTo: 0.001) storeOn: aStream. ! ! !TranslucentColor methodsFor: 'printing' stamp: 'di 9/27/2000 13:33'! storeOn: aStream self isTransparent ifTrue: [^ aStream nextPutAll: '(Color transparent)']. super storeOn: aStream. aStream skip: -1; "get rid of trailing )" nextPutAll: ' alpha: '; print: (self alpha roundTo: 0.001); nextPutAll: ')'. ! ! !TranslucentColor methodsFor: 'conversions' stamp: 'di 1/15/1999 11:44'! alpha: alphaValue alphaValue = 1.0 ifTrue: [^ Color basicNew setPrivateRed: self privateRed green: self privateGreen blue: self privateBlue]. ^ super alpha: alphaValue! ! !TranslucentColor methodsFor: 'conversions' stamp: 'sw 10/27/1999 10:51'! asNontranslucentColor ^ self alpha: 1.0! ! !TranslucentColor methodsFor: 'conversions' stamp: 'di 3/25/2000 17:56'! balancedPatternForDepth: depth "Return an appropriate bit pattern or stipple. This will almost never be meaningful for tranlucentColors, except for the degenerate case of tranparency." alpha = 0 ifTrue: [^ Bitmap with: 0]. ^ super balancedPatternForDepth: depth! ! !TranslucentColor methodsFor: 'conversions' stamp: 'di 1/14/1999 20:05'! bitPatternForDepth: depth "Return an appropriate bit pattern or stipple. This will almost never be meaningful for tranlucentColors, except for the degenerate case of tranparency." alpha = 0 ifTrue: [^ Bitmap with: 0]. ^ super bitPatternForDepth: depth! ! !TranslucentColor methodsFor: 'conversions' stamp: 'ar 5/27/2001 16:30'! pixelValueForDepth: d "Return the pixel value for this color at the given depth. Translucency only works in RGB; this color will appear either opaque or transparent at all other depths." | basicPixelWord | alpha = 0 ifTrue: [^ 0]. basicPixelWord _ super pixelValueForDepth: d. d < 32 ifTrue: [^ basicPixelWord] ifFalse: [^ (basicPixelWord bitAnd: 16rFFFFFF) bitOr: (alpha bitShift: 24)]. ! ! !TranslucentColor methodsFor: 'conversions' stamp: 'di 1/6/1999 16:14'! pixelWordForDepth: depth "Return the pixel value for this color at the given depth. Translucency only works in RGB; this color will appear either opaque or transparent at all other depths." | basicPixelWord | alpha = 0 ifTrue: [^ 0]. basicPixelWord _ super pixelWordForDepth: depth. depth < 32 ifTrue: [^ basicPixelWord] ifFalse: [^ (basicPixelWord bitAnd: 16rFFFFFF) bitOr: (alpha bitShift: 24)]. ! ! !TranslucentColor methodsFor: 'conversions' stamp: 'ar 1/14/1999 15:30'! scaledPixelValue32 "Return the alpha scaled pixel value for depth 32" | pv32 a b g r | pv32 _ super scaledPixelValue32. a _ (self alpha * 255.0) rounded. b _ (pv32 bitAnd: 255) * a // 256. g _ ((pv32 bitShift: -8) bitAnd: 255) * a // 256. r _ ((pv32 bitShift: -16) bitAnd: 255) * a // 256. ^b + (g bitShift: 8) + (r bitShift: 16) + (a bitShift: 24)! ! !TranslucentColor methodsFor: 'private'! privateAlpha "Return my raw alpha value, an integer in the range 0..255. Used for fast equality testing." ^ alpha ! ! !TranslucentColor methodsFor: 'private'! setRgb: rgbValue alpha: alphaValue "Set the state of this translucent color. Alpha is represented internally by an integer in the range 0..255." rgb == nil ifFalse: [self attemptToMutateError]. rgb _ rgbValue. alpha _ (255.0 * alphaValue) asInteger min: 255 max: 0. ! ! !TranslucentColor methodsFor: 'queries' stamp: 'ar 4/20/2001 04:33'! isOpaque ^alpha = 255! ! !TranslucentColor methodsFor: 'queries' stamp: 'di 12/30/1998 14:33'! isTranslucent ^ alpha < 255! ! !TranslucentColor methodsFor: 'queries' stamp: 'di 1/3/1999 12:22'! isTranslucentColor "This means: self isTranslucent, but isTransparent not" ^ alpha > 0! ! !TranslucentColor methodsFor: 'queries' stamp: 'di 12/30/1998 14:33'! isTransparent ^ alpha = 0! ! !TranslucentColor methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:50'! convertToCurrentVersion: varDict refStream: smartRefStrm "1/13/1999 -- old versions did not have alpha??" varDict at: 'alpha' ifAbsent: [^ Color transparent]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! Boolean subclass: #True instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !True commentStamp: '<historical>' prior: 0! True defines the behavior of its single instance, true -- logical assertion. Notice how the truth-value checks become direct message sends, without the need for explicit testing. Be aware however that most of these methods are not sent as real messages in normal use. Most are inline coded by the compiler as test and jump bytecodes - avoiding the overhead of the full message sends. So simply redefining these methods here will have no effect.! !True methodsFor: 'logical operations'! & alternativeObject "Evaluating conjunction -- answer alternativeObject since receiver is true." ^alternativeObject! ! !True methodsFor: 'logical operations'! not "Negation--answer false since the receiver is true." ^false! ! !True methodsFor: 'logical operations'! | aBoolean "Evaluating disjunction (OR) -- answer true since the receiver is true." ^self! ! !True methodsFor: 'controlling'! and: alternativeBlock "Nonevaluating conjunction -- answer the value of alternativeBlock since the receiver is true." ^alternativeBlock value! ! !True methodsFor: 'controlling'! ifFalse: alternativeBlock "Since the condition is true, the value is the true alternative, which is nil. Execution does not actually reach here because the expression is compiled in-line." ^nil! ! !True methodsFor: 'controlling'! ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock "Answer the value of trueAlternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^trueAlternativeBlock value! ! !True methodsFor: 'controlling'! ifTrue: alternativeBlock "Answer the value of alternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^alternativeBlock value! ! !True methodsFor: 'controlling'! ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock "Answer with the value of trueAlternativeBlock. Execution does not actually reach here because the expression is compiled in-line." ^trueAlternativeBlock value! ! !True methodsFor: 'controlling'! or: alternativeBlock "Nonevaluating disjunction -- answer true since the receiver is true." ^self! ! !True methodsFor: 'printing'! printOn: aStream aStream nextPutAll: 'true'! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! True class instanceVariableNames: ''! !True class methodsFor: 'as yet unclassified' stamp: 'sw 5/8/2000 11:09'! initializedInstance ^ true! ! Object subclass: #TwoLevelDictionary instanceVariableNames: 'firstLevel' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !TwoLevelDictionary commentStamp: '<historical>' prior: 0! A simple dictionary for the use of the TextDiffBuilder. Keys are presumed to be Points and a significant speed advantage is gained by using a dictionary of dictionaries. The first is keyed by the x-values and the second by the y-values. Only the minimum necessary protocol is implemented.! !TwoLevelDictionary methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:42'! at: aPoint ^(firstLevel at: aPoint x ifAbsent: [^nil]) at: aPoint y ifAbsent: [^nil] ! ! !TwoLevelDictionary methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:37'! at: aPoint put: anObject (firstLevel at: aPoint x ifAbsentPut: [Dictionary new]) at: aPoint y put: anObject ! ! !TwoLevelDictionary methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:38'! initialize firstLevel _ Dictionary new.! ! !TwoLevelDictionary methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:40'! keysDo: aBlock firstLevel keysAndValuesDo: [ :x :v | v keysDo: [ :y | aBlock value: x@y] ].! ! !TwoLevelDictionary methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:40'! twoLevelKeys | twoLevelSet | twoLevelSet _ TwoLevelSet new. self keysDo: [ :each | twoLevelSet add: each]. ^twoLevelSet ! ! Object subclass: #TwoLevelSet instanceVariableNames: 'firstLevel' classVariableNames: '' poolDictionaries: '' category: 'Tools-File Contents Browser'! !TwoLevelSet commentStamp: '<historical>' prior: 0! A simple set for the use of the TextDiffBuilder. Elements are presumed to be Points and a significant speed advantage is gained by using a dictionary of sets. The first is keyed by the x-values and the second contains the y-values. Only the minimum necessary protocol is implemented.! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:18'! add: aPoint (firstLevel at: aPoint x ifAbsentPut: [Set new]) add: aPoint y ! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:18'! copy | answer | answer _ self class new initialize. self do: [ :each | answer add: each ]. ^answer! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/3/2001 09:26'! detect: aBlock firstLevel keysAndValuesDo: [ :x :v | v do: [ :y | (aBlock value: x@y) ifTrue: [^x@y]] ]. ^nil! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:15'! do: aBlock firstLevel keysAndValuesDo: [ :x :v | v do: [ :y | aBlock value: x@y] ].! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:19'! includes: aPoint ^(firstLevel at: aPoint x ifAbsent: [^false]) includes: aPoint y! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:11'! initialize firstLevel _ Dictionary new.! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:13'! isEmpty ^firstLevel isEmpty! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:22'! remove: aPoint | lev2 | lev2 _ firstLevel at: aPoint x ifAbsent: [^self]. lev2 remove: aPoint y ifAbsent: []. lev2 isEmpty ifTrue: [firstLevel removeKey: aPoint x]. ! ! !TwoLevelSet methodsFor: 'as yet unclassified' stamp: 'RAA 5/2/2001 23:28'! removeAllXAndY: aPoint | deletes | deletes _ OrderedCollection new. firstLevel removeKey: aPoint x ifAbsent: []. firstLevel keysAndValuesDo: [ :x :lev2 | lev2 remove: aPoint y ifAbsent: []. lev2 isEmpty ifTrue: [deletes add: x]. ]. deletes do: [ :each | firstLevel removeKey: each ifAbsent: []].! ! Object subclass: #UndefinedObject instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !UndefinedObject commentStamp: '<historical>' prior: 0! 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.! !UndefinedObject methodsFor: 'copying' stamp: 'tk 6/26/1998 11:35'! clone "Only one instance of UndefinedObject should ever be made, so answer with self."! ! !UndefinedObject methodsFor: 'copying'! deepCopy "Only one instance of UndefinedObject should ever be made, so answer with self."! ! !UndefinedObject methodsFor: 'copying'! shallowCopy "Only one instance of UndefinedObject should ever be made, so answer with self."! ! !UndefinedObject methodsFor: 'copying' stamp: 'tk 8/20/1998 16:07'! veryDeepCopyWith: deepCopier "Return self. I can't be copied. Do not record me."! ! !UndefinedObject methodsFor: 'printing'! printOn: aStream "Refer to the comment in Object|printOn:." aStream nextPutAll: 'nil'! ! !UndefinedObject methodsFor: 'printing'! storeOn: aStream "Refer to the comment in Object|storeOn:." aStream nextPutAll: 'nil'! ! !UndefinedObject methodsFor: 'testing' stamp: 'sw 1/12/98 18:09'! haltIfNil self halt! ! !UndefinedObject methodsFor: 'testing'! ifNil: aBlock "A convenient test, in conjunction with Object ifNil:" ^ aBlock value! ! !UndefinedObject methodsFor: 'testing'! ifNil: nilBlock ifNotNil: ifNotNilBlock "Evaluate the block for nil because I'm == nil" ^ nilBlock value! ! !UndefinedObject methodsFor: 'testing'! ifNotNil: aBlock "A convenient test, in conjunction with Object ifNotNil:" ^ self! ! !UndefinedObject methodsFor: 'testing'! ifNotNil: ifNotNilBlock ifNil: nilBlock "If I got here, I am nil, so evaluate the block nilBlock" ^ nilBlock value! ! !UndefinedObject methodsFor: 'testing' stamp: 'di 11/8/2000 21:22'! ifNotNilDo: aBlock "Override to do nothing." ^ self ! ! !UndefinedObject methodsFor: 'testing' stamp: 'sw 4/7/1999 17:44'! isEmptyOrNil "Answer whether the receiver contains any elements, or is nil. Useful in numerous situations where one wishes the same reaction to an empty collection or to nil" ^ true! ! !UndefinedObject methodsFor: 'testing' stamp: 'sma 6/6/2000 22:53'! isLiteral ^ true! ! !UndefinedObject methodsFor: 'testing'! isNil "Refer to the comment in Object|isNil." ^true! ! !UndefinedObject methodsFor: 'testing'! notNil "Refer to the comment in Object|notNil." ^false! ! !UndefinedObject methodsFor: 'dependents access'! addDependent: ignored "Refer to the comment in Object|dependents." self error: 'Nil should not have dependents'! ! !UndefinedObject methodsFor: 'dependents access'! release "Nil release is a no-op"! ! !UndefinedObject methodsFor: 'dependents access'! suspend "Kills off processes that didn't terminate properly" "Display reverse; reverse." "<-- So we can catch the suspend bug" Processor terminateActive! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ar 7/15/1999 16:49'! addSubclass: aClass "Ignored -- necessary to support disjoint class hierarchies"! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'sd 3/28/2003 15:16'! environment "Necessary to support disjoint class hierarchies." ^self class environment! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ajh 1/27/2003 17:48'! literalScannedAs: scannedLiteral notifying: requestor ^ scannedLiteral! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ikp 9/26/97 14:45'! removeSubclass: aClass "Ignored -- necessary to support disjoint class hierarchies"! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ls 10/9/2001 00:11'! subclass: nameOfClass instanceVariableNames: instVarNames classVariableNames: classVarNames poolDictionaries: poolDictnames category: category "Calling this method is now considered an accident. If you really want to create a class with a nil superclass, then create the class and then set the superclass using #superclass:" Transcript show: ('Attempt to create ', nameOfClass, ' as a subclass of nil. Possibly a class is being loaded before its superclass.'); cr. ^ProtoObject subclass: nameOfClass instanceVariableNames: instVarNames classVariableNames: classVarNames poolDictionaries: poolDictnames category: category ! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ar 8/29/1999 12:49'! subclassDefinerClass "For disjunct class hierarchies -- how should subclasses of nil be evaluated" ^Compiler! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ar 7/15/1999 16:55'! subclasses "Return all the subclasses of nil" | classList | classList _ WriteStream on: Array new. self subclassesDo:[:class| classList nextPut: class]. ^classList contents! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ar 7/15/1999 15:44'! subclassesDo: aBlock "Evaluate aBlock with all subclasses of nil." ^Class subclassesDo:[:cl| cl isMeta ifTrue:[aBlock value: cl soleInstance]].! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'tk 8/18/1999 17:46'! subclassesDoGently: aBlock "Evaluate aBlock with all subclasses of nil. Others are not direct subclasses of Class." ^ Class subclassesDoGently: [:cl | cl isMeta ifTrue: [aBlock value: cl soleInstance]].! ! !UndefinedObject methodsFor: 'class hierarchy' stamp: 'ar 7/13/1999 06:08'! typeOfClass "Necessary to support disjoint class hierarchies." ^#normal! ! !UndefinedObject methodsFor: 'bottom context' stamp: 'ajh 2/1/2003 01:31'! handleSignal: exception "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." ^ exception resumeUnchecked: exception defaultAction! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! UndefinedObject class instanceVariableNames: ''! !UndefinedObject class methodsFor: 'instance creation' stamp: 'sw 5/5/2000 09:32'! initializedInstance ^ nil! ! !UndefinedObject class methodsFor: 'instance creation'! new self error: 'You may not create any more undefined objects--use nil'! ! Exception subclass: #UnhandledError instanceVariableNames: 'exception' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !UnhandledError methodsFor: 'priv handling' stamp: 'ajh 9/5/2002 15:11'! defaultAction "The current computation is terminated. The cause of the error should be logged or reported to the user. If the program is operating in an interactive debugging environment the computation should be suspended and the debugger activated." self isDevelopmentEnvironmentPresent ifTrue: [self devDefaultAction] ifFalse: [self runtimeDefaultAction]. ! ! !UnhandledError methodsFor: 'priv handling' stamp: 'ajh 1/24/2003 19:21'! devDefaultAction Processor activeProcess debug: exception signalerContext title: exception description! ! !UnhandledError methodsFor: 'priv handling' stamp: 'ajh 9/4/2002 19:16'! isDevelopmentEnvironmentPresent ^ Smalltalk includesKey: #Debugger! ! !UnhandledError methodsFor: 'priv handling' stamp: 'ajh 2/1/2003 00:56'! isResumable ^ false! ! !UnhandledError methodsFor: 'priv handling' stamp: 'sd 11/16/2003 14:18'! runtimeDefaultAction "Dump the stack trace to a log file, then exit the program (image)." | file | file := FileStream newFileNamed: ('error', Utilities dateTimeSuffix, FileDirectory dot, 'log') asFileName. Smalltalk timeStamp: file. (thisContext sender stackOfSize: 20) do: [:ctx | file cr. ctx printOn: file]. file close. SmalltalkImage current snapshot: false andQuit: true! ! !UnhandledError methodsFor: 'as yet unclassified' stamp: 'ajh 9/4/2002 19:15'! exception ^ exception! ! !UnhandledError methodsFor: 'as yet unclassified' stamp: 'ajh 9/4/2002 19:15'! exception: anError exception _ anError! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! UnhandledError class instanceVariableNames: ''! !UnhandledError class methodsFor: 'as yet unclassified' stamp: 'ajh 9/4/2002 19:17'! signalForException: anError ^ self new exception: anError; signal! ! FileDirectory subclass: #UnixFileDirectory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Files'! !UnixFileDirectory commentStamp: '<historical>' prior: 0! I represent a Unix FileDirectory. ! !UnixFileDirectory methodsFor: 'file names' stamp: 'bf 3/22/2000 18:24'! fullPathFor: path "Return the fully-qualified path name for the given file." path isEmpty ifTrue: [^ pathName]. path first = $/ ifTrue: [^ path]. ^ pathName = '/' "Only root dir ends with a slash" ifTrue: ['/' , path] ifFalse: [pathName , '/' , path]! ! !UnixFileDirectory methodsFor: 'private' stamp: 'jm 12/4/97 23:43'! setPathName: pathString "Unix path names start with a leading delimiter character." (pathString isEmpty or: [pathString first ~= self pathNameDelimiter]) ifTrue: [pathName _ self pathNameDelimiter asString, pathString] ifFalse: [pathName _ pathString]. ! ! !UnixFileDirectory methodsFor: 'testing' stamp: 'sr 5/8/2000 12:58'! directoryExists: filenameOrPath "Handles the special case of testing for the root dir: there isn't a possibility to express the root dir as full pathname like '/foo'." ^ filenameOrPath = '/' or: [super directoryExists: filenameOrPath]! ! !UnixFileDirectory methodsFor: 'testing' stamp: 'sr 5/8/2000 13:03'! fileOrDirectoryExists: filenameOrPath "Handles the special case of testing for the root dir: there isn't a possibility to express the root dir as full pathname like '/foo'." ^ filenameOrPath = '/' or: [super fileOrDirectoryExists: filenameOrPath]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! UnixFileDirectory class instanceVariableNames: ''! !UnixFileDirectory class methodsFor: 'platform specific' stamp: 'yo 2/4/1999 06:40'! maxFileNameLength ^ 255! ! !UnixFileDirectory class methodsFor: 'platform specific' stamp: 'jm 9/17/97 15:48'! pathNameDelimiter ^ $/ ! ! Object subclass: #Utilities instanceVariableNames: '' classVariableNames: 'AuthorInitials AuthorName CommonRequestStrings LastStats RecentSubmissions ScrapsBook UpdateDownloader UpdateUrlLists' poolDictionaries: '' category: 'System-Support'! !Utilities commentStamp: '<historical>' prior: 0! 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! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Utilities class instanceVariableNames: ''! !Utilities class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:11'! initialize "Initialize the class variables. 5/16/96 sw" self initializeCommonRequestStrings. RecentSubmissions _ OrderedCollection new. self registerInFlapsRegistry. ! ! !Utilities class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:12'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(Utilities recentSubmissionsWindow 'Recent' 'A message browser that tracks the most recently-submitted methods') forFlapNamed: 'Tools'.]! ! !Utilities class methodsFor: 'class initialization' stamp: 'NS 1/26/2004 09:52'! startUp SystemChangeNotifier uniqueInstance notify: self ofAllSystemChangesUsing: #event:.! ! !Utilities class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:42'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !Utilities class methodsFor: 'common requests' stamp: 'tk 5/4/1998 17:35'! editCommonRequestStrings "Let the user edit the common request strings. 2/1/96 sw" CommonRequestStrings openLabel: 'Common Request Strings'! ! !Utilities class methodsFor: 'common requests' stamp: 'sd 1/19/2004 20:58'! evaluate: aString in: aContext to: aReceiver "evaluate aString in the given context, and return the result. 2/2/96 sw" self deprecated: 'Use Compiler>>evaluate: aString in: aContext to: aReceiver'. ^ Compiler new evaluate: aString in: aContext to: aReceiver! ! !Utilities class methodsFor: 'common requests' stamp: 'sw 2/5/2002 13:17'! initializeCommonRequestStrings "Initialize the common request strings, a directly-editable list of expressions that can be evaluated from the 'do...' menu." CommonRequestStrings _ StringHolder new contents: 'Utilities emergencyCollapse. Utilities closeAllDebuggers. - Sensor keyboard. ParagraphEditor abandonChangeText. Cursor normal show. - CommandHistory resetAllHistory. Project allInstancesDo: [:p | p displayDepth: 16]. ScriptingSystem inspectFormDictionary. Form fromUser bitEdit. Display border: (0@0 extent: 640@480) width: 2. - Undeclared inspect. Undeclared removeUnreferencedKeys; inspect. Transcript clear. Utilities grabScreenAndSaveOnDisk. FrameRateMorph new openInHand. - Utilities reconstructTextWindowsFromFileNamed: ''TW''. Utilities storeTextWindowContentsToFileNamed: ''TW''. ChangeSorter removeEmptyUnnamedChangeSets. ChangeSorter reorderChangeSets. - ActiveWorld installVectorVocabulary. ActiveWorld abandonVocabularyPreference. Smalltalk saveAsNewVersion' "Utilities initializeCommonRequestStrings"! ! !Utilities class methodsFor: 'common requests' stamp: 'BG 10/29/2003 08:38'! offerCommonRequests "Offer up the common-requests menu. If the user chooses one, then evaluate it, and -- provided the value is a number or string -- show it in the Transcript." "Utilities offerCommonRequests" | reply result aMenu index normalItemCount strings | (CommonRequestStrings == nil or: [CommonRequestStrings isKindOf: Array]) ifTrue: [self initializeCommonRequestStrings]. strings _ CommonRequestStrings contents. normalItemCount _ strings asString lineCount. aMenu _ PopUpMenu labels: (strings asString, ' edit this menu') lines: (Array with: normalItemCount). index _ aMenu startUp. index == 0 ifTrue: [^ self]. reply _ aMenu labelString lineNumber: index. reply size == 0 ifTrue: [^ self]. index > normalItemCount ifTrue: [^ self editCommonRequestStrings]. result _ self evaluate: reply in: nil to: nil. (result isKindOf: Number) | (result isKindOf: String) ifTrue: [Transcript cr; nextPutAll: result printString]! ! !Utilities class methodsFor: 'debugging' stamp: 'sw 4/29/2001 23:42'! doesNotUnderstand: aMessage "A temporary expedient for revectoring various messages formerly sent to Utilities that now are instead implemented by Flaps; this is only for the benefit of pre-existing buttons and menu items that were set up to call the old interface" | aSelector | aSelector _ aMessage selector. (#(addLocalFlap explainFlaps addMenuFlap addPaintingFlap addStackToolsFlap addGlobalFlap offerGlobalFlapsMenu toggleWhetherToUseGlobalFlaps ) includes: aSelector) ifTrue: [^ self inform: 'Sorry, this is an obsolete menu. Please dismiss it and get a fresh one. Thank you']. ^ super doesNotUnderstand: aMessage! ! !Utilities class methodsFor: 'fetching updates' stamp: 'RAA 12/17/2000 16:19'! zapUpdateDownloader UpdateDownloader ifNotNil: [UpdateDownloader terminate]. UpdateDownloader _ nil.! ! !Utilities class methodsFor: 'deprecated' stamp: 'sd 1/16/2004 21:37'! fileOutChangeSetsNamed: nameList "File out the list of change sets whose names are provided" self deprecated: 'Use ChangeSorter fileOutChangeSetsNamed: nameList'. ChangeSorter fileOutChangeSetsNamed: nameList! ! !Utilities class methodsFor: 'deprecated' stamp: 'sd 1/16/2004 21:31'! fileOutChanges "File out the current change set to a file whose name is a function of the current date and time." self deprecated: 'Use ChangeSet current verboseFileOut'. ChangeSet current verboseFileOut! ! !Utilities class methodsFor: 'deprecated' stamp: 'sd 1/16/2004 21:09'! methodHierarchyBrowserForClass: aClass selector: sel "Create and schedule a message set browser on all implementors of the currently selected message selector. Do nothing if no message is selected." self deprecated: 'Use SystemNavigation default methodHierarchyBrowserForClass: aClass selector: sel'. SystemNavigation default methodHierarchyBrowserForClass: aClass selector: sel! ! !Utilities class methodsFor: 'deprecated' stamp: 'sd 1/16/2004 21:14'! spawnHierarchyForClass: aClass selector: aSelector "Utilities spawnHierarchyForClass: SmallInteger selector: #hash" self deprecated: 'SystemNavigation default spawnHierarchyForClass: aClass selector: aSelector'. SystemNavigation default spawnHierarchyForClass: aClass selector: aSelector! ! !Utilities class methodsFor: 'graphical support' stamp: 'md 12/12/2003 17:03'! grabScreenAndSaveOnDisk "Utilities grabScreenAndSaveOnDisk" | form fileName | self deprecated: 'Use GIFReaderWriter grabScreenAndSaveOnDisk'. form _ Form fromUser. form bits size = 0 ifTrue: [^ Beeper beep]. fileName _ FileDirectory default nextNameFor: 'Squeak' extension: 'gif'. Utilities informUser: 'Writing ' , fileName during: [GIFReadWriter putForm: form onFileNamed: fileName].! ! !Utilities class methodsFor: 'identification' stamp: 'dhhi 11/6/97 16:48'! authorInitials "Answer the initials to be used to identify the current code author. " [AuthorInitials isEmpty] whileTrue: [self setAuthorInitials]. ^ AuthorInitials! ! !Utilities class methodsFor: 'identification' stamp: 'sw 7/6/1998 11:49'! authorInitialsPerSe "Answer the currently-prevailing author initials, such as they, empty or not" ^ AuthorInitials! ! !Utilities class methodsFor: 'identification' stamp: 'fc 3/11/2004 12:22'! authorName AuthorName ifEmpty: [self setAuthorName]. ^ AuthorName! ! !Utilities class methodsFor: 'identification' stamp: 'tk 4/10/98 06:25'! changeStamp "Answer a string to be pasted into source code to mark who changed it and when." ^ self authorInitials , ' ' , Date today mmddyyyy, ' ', ((String streamContents: [:s | Time now print24: true on: s]) copyFrom: 1 to: 5)! ! !Utilities class methodsFor: 'identification' stamp: 'sw 1/29/2001 09:28'! changeStampPerSe "Answer a string to be pasted into source code to mark who changed it and when." ^ (self authorInitialsPerSe ifNil: ['']) , ' ' , Date today mmddyyyy, ' ', ((String streamContents: [:s | Time now print24: true on: s]) copyFrom: 1 to: 5)! ! !Utilities class methodsFor: 'identification' stamp: 'sw 11/13/1999 22:45'! dateTimeSuffix "Answer a string which indicates the date and time, intended for use in building fileout filenames, etc." "Utilities dateTimeSuffix" ^ Preferences twentyFourHourFileStamps ifFalse: [self monthDayTimeStringFrom: Time primSecondsClock] ifTrue: [self monthDayTime24StringFrom: Time primSecondsClock]! ! !Utilities class methodsFor: 'identification' stamp: 'di 6/13/97 13:52'! fixStamp: changeStamp | parts | parts _ changeStamp findTokens: ' '. (parts size > 0 and: [parts last first isLetter]) ifTrue: ["Put initials first in all time stamps..." ^ String streamContents: [:s | s nextPutAll: parts last. parts allButLast do: [:p | s space; nextPutAll: p]]]. ^ changeStamp! ! !Utilities class methodsFor: 'identification' stamp: 'sw 11/13/1999 23:03'! monthDayTime24StringFrom: aSecondCount | aDate aTime | "From the date/time represented by aSecondCount, produce a string which indicates the date and time in the compact form ddMMMhhmm where dd is a two-digit day-of-month, MMM is the alpha month abbreviation and hhmm is the time on a 24-hr clock. Utilities monthDayTime24StringFrom: Time primSecondsClock " aDate _ Date fromSeconds: aSecondCount. aTime _ Time fromSeconds: aSecondCount \\ 86400. ^ (aDate dayOfMonth asTwoCharacterString), (aDate monthName copyFrom: 1 to: 3), (aTime hhmm24)! ! !Utilities class methodsFor: 'identification' stamp: 'sw 11/13/1999 23:03'! monthDayTimeStringFrom: aSecondCount | aDate aTime | "From the date/time represented by aSecondCount, produce a string which indicates the date and time in the form: ddMMMhhmmPP where: dd is a two-digit day-of-month, MMM is the alpha month abbreviation, hhmm is the time, PP is either am or pm Utilities monthDayTimeStringFrom: Time primSecondsClock " aDate _ Date fromSeconds: aSecondCount. aTime _ Time fromSeconds: aSecondCount \\ 86400. ^ (aDate dayOfMonth asTwoCharacterString), (aDate monthName copyFrom: 1 to: 3), ((aTime hours \\ 12) asTwoCharacterString), (aTime minutes asTwoCharacterString), (aTime hours > 12 ifTrue: ['pm'] ifFalse: ['am'])! ! !Utilities class methodsFor: 'identification' stamp: 'gm 5/15/2004 02:59'! setAuthorInitials "Put up a dialog allowing the user to specify the author's initials. " self setAuthorInitials: (FillInTheBlank request: 'Please type your initials: ' initialAnswer: AuthorInitials)! ! !Utilities class methodsFor: 'identification' stamp: 'fc 3/11/2004 12:13'! setAuthorInitials: aString AuthorInitials _ aString. "Case of being reset due to, eg, copy of image." aString isEmpty ifTrue: [AuthorName _ '']! ! !Utilities class methodsFor: 'identification' stamp: 'sma 6/1/2000 12:08'! setAuthorName AuthorName _ FillInTheBlank request: 'Please type your name:' initialAnswer: 'Your Name'! ! !Utilities class methodsFor: 'miscellaneous'! awaitMouseUpIn: box repeating: doBlock ifSucceed: succBlock "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 6/10/96 sw: call new method that adds extra feature" ^ self awaitMouseUpIn: box whileMouseDownDo: doBlock whileMouseDownInsideDo: [] ifSucceed: succBlock! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'JMM 3/31/2000 20:41'! awaitMouseUpIn: box whileMouseDownDo: doBlock1 whileMouseDownInsideDo: doBlock2 ifSucceed: succBlock "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 3/31/00 JMM added logic to stop multiple redraws" | p inside lightForm darkForm isLight | p _ Sensor cursorPoint. inside _ box insetBy: 1. isLight _ true. lightForm _ Form fromDisplay: inside. darkForm _ lightForm deepCopy reverse. [Sensor anyButtonPressed] whileTrue: [doBlock1 value. (box containsPoint: (p _ Sensor cursorPoint)) ifTrue: [doBlock2 value. isLight ifTrue: [isLight _ false. darkForm displayAt: inside origin]] ifFalse: [isLight ifFalse: [isLight _ true. lightForm displayAt: inside origin]]]. (box containsPoint: p) ifTrue: [lightForm displayAt: inside origin. ^ succBlock value] ! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'sma 4/30/2000 10:17'! emergencyCollapse Smalltalk isMorphic ifTrue: [^ self]. ScheduledControllers screenController emergencyCollapse! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'sd 4/17/2003 21:04'! fixUpProblemsWithAllCategory "Moves all methods that are in formally classified a category named '-- all --' into the default 'as yet unclassified' category" "Utilities fixUpProblemsWithAllCategory" | org aCategory methodCount classCount any | self flag: #ShouldBeMovedInClassOrganization. methodCount _ 0. classCount _ 0. self systemNavigation allBehaviorsDo: [:aClass | org _ aClass organization. (org categories includes: #'-- all --') ifTrue: [any _ false. aClass selectorsDo: [:aSelector | aCategory _ org categoryOfElement: aSelector. aCategory = #'-- all --' ifTrue: [org classify: aSelector under: ClassOrganizer default suppressIfDefault: false. Transcript cr; show: aClass name, ' >> ', aSelector. methodCount _ methodCount + 1. any _ true]]. any ifTrue: [classCount _ classCount + 1]. org removeEmptyCategories]]. Transcript cr; show: methodCount printString, ' methods in ', classCount printString, ' classes moved from "-- all --" to "as yet unclassified"' ! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'nk 2/15/2004 09:36'! garbageCollectAndReport "Do a garbage collection, and report results to the user." | cc reportString | reportString _ String streamContents: [:aStream | aStream nextPutAll: Smalltalk bytesLeftString. Smalltalk at: #Command ifPresent: [:cmdClass | (cc _ cmdClass instanceCount) > 0 ifTrue: [aStream cr; nextPutAll: ('(note: there are ', cc printString, ' undo record(s) present in your system; purging them may free up more space.)')]]]. self inform: reportString ! ! !Utilities class methodsFor: 'miscellaneous'! keyLike: aString satisfying: aBlock "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" | stemAndSuffix suffix stem newKey | (aBlock value: aString) ifTrue: [^ aString]. stemAndSuffix _ aString stemAndNumericSuffix. suffix _ stemAndSuffix last + 1. stem _ stemAndSuffix first. [aBlock value: (newKey _ stem, suffix printString)] whileFalse: [suffix _ suffix + 1]. ^ newKey ! ! !Utilities class methodsFor: 'miscellaneous'! keyLike: aString withTrailing: trailerString satisfying: aBlock "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" | stemAndSuffix suffix stem composite | composite _ aString, trailerString. (aBlock value: composite) ifTrue: [^ composite]. stemAndSuffix _ aString stemAndNumericSuffix. suffix _ stemAndSuffix last + 1. stem _ stemAndSuffix first. [aBlock value: (composite _ stem, suffix printString, trailerString)] whileFalse: [suffix _ suffix + 1]. ^ composite ! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'BG 10/29/2003 08:13'! lookUpDefinition | aWord aDefinition | (aWord _ FillInTheBlank request: 'Enter a word:') isEmpty ifTrue: [^ self]. " (aDefinition _ WordNet definitionsFor: aWord) ifNil: [^ self]. " aDefinition := ''. (StringHolder new contents: aDefinition) openLabel: aWord "Utilities lookUpDefinition"! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'md 11/14/2003 18:02'! methodDiffFor: aString class: aClass selector: aSelector prettyDiffs: prettyDiffBoolean "Return a string comprising a source-code diff between an existing method and the source-code in aString. DO prettyDiff if prettyDiffBoolean is true." ^ (aClass notNil and: [aClass includesSelector: aSelector]) ifTrue: [TextDiffBuilder buildDisplayPatchFrom: (aClass sourceCodeAt: aSelector) to: aString inClass: aClass prettyDiffs: prettyDiffBoolean] ifFalse: [aString copy]! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'jm 5/3/1998 20:12'! openScratchWorkspaceLabeled: labelString contents: initialContents "Open a scratch text view with the given label on the given string. A scratch text view won't warn you about unsaved changes when you close it." "Utilities openScratchWorkspaceLabeled: 'Scratch' contents: 'Hello. world!!'" | model topView stringView | model _ StringHolder new contents: initialContents. topView _ StandardSystemView new. topView model: model; label: labelString; minimumSize: 180@120. topView borderWidth: 1. stringView _ PluggableTextView on: model text: #contents accept: nil readSelection: #contentsSelection menu: #codePaneMenu:shifted:. stringView askBeforeDiscardingEdits: false; window: (0@0 extent: 180@120). topView addSubView: stringView. topView controller open. ! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'RAA 5/28/2001 10:02'! setClassAndSelectorFrom: messageIDString in: csBlock "Decode strings of the form <className> [class] <selectorName>. If <className> does not exist as a class, use nil for the class in the block" | aStream aClass maybeClass sel | (messageIDString isKindOf: MethodReference) ifTrue: [ ^messageIDString setClassAndSelectorIn: csBlock ]. aStream _ ReadStream on: messageIDString. aClass _ Smalltalk at: (aStream upTo: $ ) asSymbol ifAbsent: [nil]. maybeClass _ aStream upTo: $ . sel _ aStream upTo: $ . ((maybeClass = 'class') & (sel size ~= 0)) ifTrue: [aClass ifNil: [csBlock value: nil value: sel asSymbol] ifNotNil: [csBlock value: aClass class value: sel asSymbol]] ifFalse: [csBlock value: aClass value: maybeClass asSymbol] " Utilities setClassAndSelectorFrom: 'Utilities class oppositeModeTo:' in: [:aClass :aSelector | Transcript cr; show: 'Class = ', aClass name printString, ' selector = ', aSelector printString]. Utilities setClassAndSelectorFrom: 'MessageSet setClassAndSelectorIn:' in: [:aClass :aSelector | Transcript cr; show: 'Class = ', aClass name printString, ' selector = ', aSelector printString]. " ! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'sw 7/29/2002 02:23'! timeStampForMethod: method "Answer the authoring time-stamp for the given method, retrieved from the sources or changes file. Answer the empty string if no time stamp is available." "Utilities timeStampForMethod: (Utilities class compiledMethodAt: #timeStampForMethod:)" ^ method timeStamp! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 7/29/2002 02:18'! assureMostRecentSubmissionExists "Make certain that the most recent submission exists" [RecentSubmissions size > 0 and: [RecentSubmissions last isValid not]] whileTrue: [RecentSubmissions removeLast].! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 11/5/2001 01:16'! browseRecentSubmissions "Open up a browser on the most recent methods submitted in the image. 5/96 sw." "Utilities browseRecentSubmissions" | recentMessages | self recentMethodSubmissions size == 0 ifTrue: [^ self inform: 'There are no recent submissions']. recentMessages _ RecentSubmissions copy reversed. RecentMessageSet openMessageList: recentMessages name: 'Recent submissions -- youngest first ' autoSelect: nil! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'NS 4/12/2004 22:47'! event: anEvent "Hook for SystemChangeNotifier" (anEvent isCommented and: [anEvent itemKind = SystemChangeNotifier classKind]) ifTrue: [self noteMethodSubmission: #Comment forClass: anEvent item]. ((anEvent isAdded or: [anEvent isModified]) and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue: [anEvent itemRequestor ifNotNil: [self noteMethodSubmission: anEvent itemSelector forClass: anEvent itemClass]]. ((anEvent isAdded or: [anEvent isModified]) and: [anEvent itemKind = SystemChangeNotifier methodKind]) ifTrue:[ InMidstOfFileinNotification signal ifFalse: [Utilities changed: #recentMethodSubmissions]. ].! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 7/29/2002 02:12'! mostRecentlySubmittedMessage "Answer a string indicating the most recently submitted method that is still extant" self flag: #mref. "fix for faster references to methods" self assureMostRecentSubmissionExists. ^ RecentSubmissions last asStringOrText asString! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'RAA 5/28/2001 10:53'! noteMethodSubmission: selectorName forClass: class | submission | self flag: #mref. "fix for faster references to methods" self recentMethodSubmissions. "ensure it is valid" class wantsChangeSetLogging ifFalse: [^ self]. self purgeRecentSubmissionsOfMissingMethods. submission _ class name asString, ' ', selectorName. RecentSubmissions removeAllSuchThat: [ :each | each asStringOrText = submission ]. RecentSubmissions size >= self numberOfRecentSubmissionsToStore ifTrue: [ RecentSubmissions removeFirst ]. RecentSubmissions addLast: ( MethodReference new setClass: class methodSymbol: selectorName stringVersion: submission ) ! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 7/28/2002 23:20'! numberOfRecentSubmissionsToStore "Answer how many methods back the 'recent method submissions' history should store" ^ Preferences parameterAt: #numberOfRecentSubmissionsToStore ifAbsentPut: [30]! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 7/28/2002 23:52'! numberOfRecentSubmissionsToStore: aNumber "Set the number of Recent Submissions to store" Preferences setParameter: #numberOfRecentSubmissionsToStore to: aNumber! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 9/26/2002 19:16'! purgeFromRecentSubmissions: aMethodReference "Purge any reference found in RecentSubmissions to the method supplied" RecentSubmissions _ RecentSubmissions select: [:aSubmission | Utilities setClassAndSelectorFrom: aSubmission in: [:aClass :aSelector | (aClass ~~ aMethodReference actualClass) or: [aSelector ~~ aMethodReference methodSymbol]]]! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'sw 11/5/2001 12:04'! purgeRecentSubmissionsOfMissingMethods "Utilities purgeRecentSubmissionsOfMissingMethods" | keep | self flag: #mref. "fix for faster references to methods" RecentSubmissions _ RecentSubmissions select: [:aSubmission | Utilities setClassAndSelectorFrom: aSubmission in: [:aClass :aSelector | keep _ (aClass == nil) not and: [aClass isInMemory and: [aSelector == #Comment or: [(aClass compiledMethodAt: aSelector ifAbsent: [nil]) notNil]]]]. keep]! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'RAA 5/28/2001 07:39'! recentMethodSubmissions "Answer the list of recent method submissions, in order. 5/16/96 sw" self flag: #mref. "fix for faster references to methods" RecentSubmissions == nil ifTrue: [RecentSubmissions _ OrderedCollection new]. ^ RecentSubmissions! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'BG 11/1/2003 18:33'! recentSubmissionsWindow "Answer a SystemWindow holding recent submissions" | recentMessages messageSet | recentMessages _ RecentSubmissions copy reversed. messageSet _ RecentMessageSet messageList: recentMessages. messageSet autoSelectString: nil. " ^ (messageSet inMorphicWindowLabeled: 'Recent submissions -- youngest first') applyModelExtent " "Utilities recentSubmissionsWindow openInHand" ! ! !Utilities class methodsFor: 'recent method submissions' stamp: 'nb 6/17/2003 12:25'! revertLastMethodSubmission | changeRecords lastSubmission theClass theSelector | "If the most recent method submission was a method change, revert that change, and if it was a submission of a brand-new method, remove that method." RecentSubmissions isEmptyOrNil ifTrue: [^ Beeper beep]. lastSubmission _ RecentSubmissions last. theClass _ lastSubmission actualClass ifNil: [^ Beeper beep]. theSelector _ lastSubmission methodSymbol. changeRecords _ theClass changeRecordsAt: theSelector. changeRecords isEmptyOrNil ifTrue: [^ Beeper beep]. changeRecords size == 1 ifTrue: ["method has no prior version, so reverting in this case means removing" theClass removeSelector: theSelector] ifFalse: [changeRecords second fileIn]. "Utilities revertLastMethodSubmission"! ! !Utilities class methodsFor: 'summer97 additions' stamp: 'sw 1/9/2001 05:34'! classFromPattern: pattern withCaption: aCaption "If there is a class whose name exactly given by pattern, return it. If there is only one class in the system whose name matches pattern, return it. Otherwise, put up a menu offering the names of all classes that match pattern, and return the class chosen, else nil if nothing chosen. This method ignores tab, space, & cr characters in the pattern" | toMatch potentialClassNames classNames exactMatch index | (toMatch _ pattern copyWithoutAll: {Character space. Character cr. Character tab}) isEmpty ifTrue: [^ nil]. Symbol hasInterned: toMatch ifTrue: [:patternSymbol | Smalltalk at: patternSymbol ifPresent: [:maybeClass | (maybeClass isKindOf: Class) ifTrue: [^ maybeClass]]]. toMatch _ (toMatch copyWithout: $.) asLowercase. potentialClassNames _ Smalltalk classNames asOrderedCollection. classNames _ pattern last = $. ifTrue: [potentialClassNames select: [:nm | nm asLowercase = toMatch]] ifFalse: [potentialClassNames select: [:n | n includesSubstring: toMatch caseSensitive: false]]. classNames isEmpty ifTrue: [^ nil]. exactMatch _ classNames detect: [:each | each asLowercase = toMatch] ifNone: [nil]. index _ classNames size = 1 ifTrue: [1] ifFalse: [exactMatch ifNil: [(PopUpMenu labelArray: classNames lines: #()) startUpWithCaption: aCaption] ifNotNil: [classNames addFirst: exactMatch. (PopUpMenu labelArray: classNames lines: #(1)) startUpWithCaption: aCaption]]. index = 0 ifTrue: [^ nil]. ^ Smalltalk at: (classNames at: index) asSymbol " Utilities classFromPattern: 'CharRecog' Utilities classFromPattern: 'rRecog' Utilities classFromPattern: 'znak' Utilities classFromPattern: 'orph' " ! ! !Utilities class methodsFor: 'summer97 additions' stamp: 'sw 4/30/1998 12:20'! inviolateInstanceVariableNames "Answer a list of instance variable names not to be used. (Place holder for real list)" ^ #('thisContext' 'self')! ! !Utilities class methodsFor: 'summer97 additions' stamp: 'sw 4/30/1998 12:20'! isLegalInstVarName: aString "Answer whether aString is a legal instance variable name." ^ ((Scanner isLiteralSymbol: aString) and: [(aString includes: $:) not]) and: [(self inviolateInstanceVariableNames includes: aString) not]! ! !Utilities class methodsFor: 'summer97 additions' stamp: 'sw 10/6/2000 22:47'! wellFormedInstanceVariableNameFrom: aString "Answer a legal instance variable name, derived from aString" | cleansedString | cleansedString _ aString select: [:ch | ch isDigit or: [ch isLetter]]. (cleansedString size == 0 or: [cleansedString first isDigit]) ifTrue: [cleansedString _ 'a', cleansedString] ifFalse: [cleansedString _ cleansedString withFirstCharacterDownshifted]. [self isLegalInstVarName: cleansedString] whileFalse: [cleansedString _ cleansedString, 'x']. ^ cleansedString "Utilities wellFormedInstanceVariableNameFrom: '234 xx\ Uml /ler42342380-4'"! ! !Utilities class methodsFor: 'support windows' stamp: 'dgd 9/21/2003 15:12'! commandKeyMappings ^ (self class firstCommentAt: #commandKeyMappings) translated "Lower-case command keys (use with Cmd key on Mac and Alt key on other platforms) a Select all b Browse it (selection is a class name or cursor is over a class-list or message-list) c Copy selection d Do it (selection is a valid expression) e Exchange selection with prior selection f Find g Find again h Set selection as search string for find again i Inspect it (selection is a valid expression, or selection is over an inspect-ilst) j Again once (do the last text-related operation again) k Set font l Cancel m Implementors of it (selection is a message selector or cursor is over a class-list or message-list) n Senders of it (selection is a message selector or cursor is over a class-list or message-list) o Spawn current method p Print it (selection is a valid expression) q Query symbol (toggle all possible completion for a given prefix) r Recognizer s Save (i.e. accept) t Finds a Transcript (when cursor is over the desktop) u Toggle alignment v Paste w Delete preceding word (over text); Close-window (over morphic desktop) x Cut selection y Swap characters z Undo Note: for Do it, Senders of it, etc., a null selection will be expanded to a word or to the current line in an attempt to do what you want. Also note that Senders/Implementors of it will find the outermost keyword selector in a large selection, as when you have selected a bracketed expression or an entire line. Finally note that the same cmd-m and cmd-n (and cmd-v for versions) work in the message pane of most browsers. Upper-case command keys (use with Shift-Cmd, or Ctrl on Mac or Shift-Alt on other platforms; sometimes Ctrl works too) A Advance argument B Browse it in this same browser (in System browsers only) C Compare argument to clipboard D Duplicate E Method strings containing it F Insert 'ifFalse:' G fileIn from it (a file name) H cursor TopHome: I Inspect via Object Explorer J Again many (apply the previous text command repeatedly until the end of the text) K Set style L Outdent (move selection one tab-stop left) M Select current type-in N References to it (selection is a class name, or cursor is over a class-list or message-list) O Open single-message browser (in message lists) P Make project link R Indent (move selection one tab-stap right) S Search T Insert 'ifTrue:' U Convert linefeeds to carriage returns in selection V Paste author's initials W Selectors containing it (in text); show-world-menu (when issued with cursor over desktop) X Force selection to lowercase Y Force selection to uppercase Z Capitalize all words in selection Other special keys Backspace Backward delete character Del Forward delete character Shift-Bksp Backward delete word Shift-Del Forward delete word Esc Pop up the Desktop Menu \ Send top window to back Cursor keys left, right, up, down Move cursor left, right, up or down Ctrl-left Move cursor left one word Ctrl-right Move cursor right one word Home Move cursor to begin of line or begin of text End Move cursor to end of line or end of text PgUp, Ctrl-up Move cursor up one page PgDown, Ctrl-Dn Move cursor down one page Note all these keys can be used together with Shift to define or enlarge the selection. You cannot however shrink that selection again, as in some other systems. Other Cmd-key combinations (not available on all platforms) Return Insert return followed by as many tabs as the previous line (with a further adjustment for additional brackets in that line) Space Select the current word as with double clicking Enclose the selection in a kind of bracket. Each is a toggle. (not available on all platforms) Ctrl-( Enclose within ( and ), or remove enclosing ( and ) Ctrl-[ Enclose within [ and ], or remove enclosing [ and ] Crtl-{ Enclose within { and }, or remove enclosing { and } Ctrl-< Enclose within < and >, or remove enclosing < and > Ctrl-' Enclose within ' and ', or remove enclosing ' and ' Ctrl-"" Enclose within "" and "", or remove enclosing "" and "" Note also that you can double-click just inside any of the above delimiters, or at the beginning or end of a line, to select the text enclosed. Text Emphasis (not available on all platforms) Cmd-1 10 point font Cmd-2 12 point font Cmd-3 18 point font Cmd-4 24 point font Cmd-5 36 point font Cmd-6 color, action-on-click, link to class comment, link to method, url Brings up a menu. To remove these properties, select more than the active part and then use command-0. Cmd-7 bold Cmd-8 italic Cmd-9 narrow (same as negative kern) Cmd-0 plain text (resets all emphasis) Cmd-- underlined (toggles it) Cmd-= struck out (toggles it) Shift-Cmd-- (aka _) negative kern (letters 1 pixel closer) Shift-Cmd-+ positive kern (letters 1 pixel larger spread) "! ! !Utilities class methodsFor: 'support windows' stamp: 'dgd 9/21/2003 15:12'! openCommandKeyHelp "Open a window giving command key help." "Utilities openCommandKeyHelp" (StringHolder new contents: self commandKeyMappings) openLabel: 'Command Key Actions' translated ! ! !Utilities class methodsFor: 'support windows' stamp: 'di 9/23/1998 02:02'! openStandardWorkspace "Open up a throwaway workspace with useful expressions in it. 1/22/96 sw" "Utilities openStandardWorkspace" (StringHolder new contents: self standardWorkspaceContents) openLabel: 'Useful Expressions ', Date today printString! ! !Utilities class methodsFor: 'support windows' stamp: 'sw 1/19/2000 13:59'! standardWorkspaceContents ^ self class firstCommentAt: #standardWorkspaceContents "Smalltalk recover: 10000. ChangeList browseRecentLog. ChangeList browseRecent: 2000. Preferences editAnnotations. Utilities reinstateDefaultFlaps. Preferences resetCategoryInfo (FileStream oldFileNamed: 'Lives of the Wolves') edit. (FileStream oldFileNamed: 'tuesdayFixes.cs') fileIn ChangeList browseFile: 'myChanges.st' TextStyle default fontAt: 7 put: (StrikeFont new readMacFontHex: 'Cairo 18') StandardSystemView browseAllAccessesTo: 'maximumSize'. StandardSystemView doCacheBits ""restore fast windows mode in mvc"" Symbol selectorsContaining: 'rsCon'. Smalltalk browseMethodsWhoseNamesContain: 'screen'. Browser newOnClass: Utilities. Browser fullOnClass: SystemDictionary. FormView allInstances inspect. StandardSystemView someInstance inspect. Utilities storeTextWindowContentsToFileNamed: 'TextWindows' Utilities reconstructTextWindowsFromFileNamed: 'TextWindows' ScriptingSystem resetStandardPartsBin. ScheduledControllers screenController openMorphicConstructionWorld. ScheduledControllers screenController openMorphicWorld. SystemOrganization categoryOfElement: #Controller. ParagraphEditor organization categoryOfElement: #changeEmphasis. Cursor wait showWhile: [Sensor waitButton]. Smalltalk bytesLeft asStringWithCommas. Symbol instanceCount. Time millisecondsToRun: [Smalltalk allCallsOn: #asOop] MessageTally spyOn: [Smalltalk allCallsOn: #asOop]. " "Utilities openStandardWorkspace"! ! !Utilities class methodsFor: 'user interface' stamp: 'BG 11/11/2003 10:12'! informUser: aString during: aBlock "Display a message above (or below if insufficient room) the cursor during execution of the given block." "Utilities informUser: 'Just a sec!!' during: [(Delay forSeconds: 1) wait]" (SelectionMenu labels: '') displayAt: Sensor cursorPoint withCaption: aString during: [aBlock value]! ! !Utilities class methodsFor: 'user interface' stamp: 'ssa 9/3/2008 11:13'! informUserDuring: aBlock "Display a message above (or below if insufficient room) the cursor during execution of the given block." "Utilities informUserDuring:[:bar| #(one two three) do:[:info| bar value: info. (Delay forSeconds: 1) wait]]" aBlock value:[:string| Transcript cr; show: string]! ! !Utilities class methodsFor: 'vm statistics' stamp: 'nk 2/15/2004 09:35'! vmStatisticsReportString "StringHolderView open: (StringHolder new contents: Utilities vmStatisticsReportString) label: 'VM Statistics'" self deprecated: 'Use SmalltalkImage current vmStatisticsReportString'. ^SmalltalkImage current vmStatisticsReportString! ! Model subclass: #ValueHolder instanceVariableNames: 'contents' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !ValueHolder methodsFor: 'as yet unclassified' stamp: 'ls 8/5/1998 07:49'! contents ^contents! ! !ValueHolder methodsFor: 'as yet unclassified' stamp: 'sw 1/28/1999 12:35'! contents: newContents contents _ newContents. self contentsChanged! ! ObjectWithDocumentation subclass: #Variable instanceVariableNames: 'defaultValue floatPrecision variableName variableType' classVariableNames: '' poolDictionaries: '' category: 'Protocols-Kernel'! !Variable methodsFor: 'name' stamp: 'sw 5/3/2001 00:04'! printOn: aStream "Print the receiver on the stream" super printOn: aStream. aStream nextPutAll: ' named ', (self variableName ifNil: ['<unnamed>']), ' type = ', variableType printString! ! !Variable methodsFor: 'name' stamp: 'sw 12/11/2000 14:07'! variableName "Answer the variable name of the receiver" ^ variableName! ! !Variable methodsFor: 'type' stamp: 'sw 12/11/2000 14:06'! variableType "Anser the variable type of the receiver" ^ variableType! ! !Variable methodsFor: 'value' stamp: 'sw 12/11/2000 14:06'! defaultValue "Answer the default value to be supplied to the receiver" ^ defaultValue! ! LeafNode subclass: #VariableNode instanceVariableNames: 'name' classVariableNames: '' poolDictionaries: '' category: 'System-Compiler'! !VariableNode commentStamp: '<historical>' prior: 0! 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.! !VariableNode methodsFor: 'initialize-release'! asStorableNode: encoder ^ self! ! !VariableNode methodsFor: 'initialize-release' stamp: 'tk 9/28/2001 11:33'! name: string "Change name" name _ string. ! ! !VariableNode methodsFor: 'initialize-release'! name: varName index: i type: type "Only used for initting instVar refs" name _ varName. self key: varName index: i type: type! ! !VariableNode methodsFor: 'initialize-release'! name: string key: object code: byte "Only used for initting std variables, nil, true, false, self, etc." name _ string. key _ object. code _ byte! ! !VariableNode methodsFor: 'initialize-release'! name: varName key: objRef index: i type: type "Only used for initting global (litInd) variables" name _ varName. self key: objRef index: i type: type! ! !VariableNode methodsFor: 'testing'! assignmentCheck: encoder at: location (encoder cantStoreInto: name) ifTrue: [^ location] ifFalse: [^ -1] ! ! !VariableNode methodsFor: 'testing'! canBeSpecialArgument "Can I be an argument of (e.g.) ifTrue:?" ^code < LdNil! ! !VariableNode methodsFor: 'testing' stamp: 'ar 8/14/2001 23:00'! index "This code attempts to reconstruct the index from its encoding in code." code < 0 ifTrue:[^nil]. code > 256 ifTrue:[^code \\ 256]. ^code - self type! ! !VariableNode methodsFor: 'testing' stamp: 'tk 1/30/2001 14:04'! isSelfPseudoVariable "Answer if this ParseNode represents the 'self' pseudo-variable." ^ (key = 'self') | (name = '{{self}}')! ! !VariableNode methodsFor: 'testing'! isVariableReference ^true! ! !VariableNode methodsFor: 'testing' stamp: 'di 2/3/1999 09:41'! type "This code attempts to reconstruct the type from its encoding in code. This allows one to test, for instance, (aNode type = LdInstType)." | type | code < 0 ifTrue: [^ code negated]. code < 256 ifFalse: [^ code // 256]. type _ CodeBases findFirst: [:one | code < one]. type = 0 ifTrue: [^ 5] ifFalse: [^ type - 1]! ! !VariableNode methodsFor: 'code generation'! emitForReturn: stack on: strm (code >= LdSelf and: [code <= LdNil]) ifTrue: ["short returns" strm nextPut: EndMethod - 4 + (code - LdSelf). stack push: 1 "doesnt seem right"] ifFalse: [super emitForReturn: stack on: strm]! ! !VariableNode methodsFor: 'code generation'! emitForValue: stack on: strm code < 256 ifTrue: [strm nextPut: (code = LdSuper ifTrue: [LdSelf] ifFalse: [code]). stack push: 1] ifFalse: [self emitLong: LoadLong on: strm. stack push: 1]! ! !VariableNode methodsFor: 'code generation' stamp: 'ar 8/14/2001 23:14'! emitLoad: stack on: strm "Do nothing"! ! !VariableNode methodsFor: 'code generation'! emitStore: stack on: strm self emitLong: Store on: strm! ! !VariableNode methodsFor: 'code generation'! emitStorePop: stack on: strm (code between: 0 and: 7) ifTrue: [strm nextPut: ShortStoP + code "short stopop inst"] ifFalse: [(code between: 16 and: 23) ifTrue: [strm nextPut: ShortStoP + 8 + code - 16 "short stopop temp"] ifFalse: [(code >= 256 and: [code \\ 256 > 63 and: [code // 256 = 4]]) ifTrue: [self emitLong: Store on: strm. strm nextPut: Pop] ifFalse: [self emitLong: StorePop on: strm]]]. stack pop: 1! ! !VariableNode methodsFor: 'code generation' stamp: 'di 2/6/2000 10:52'! fieldOffset "Return temp or instVar offset for this variable" code < 256 ifTrue: [^ code \\ 16] ifFalse: [^ code \\ 256]! ! !VariableNode methodsFor: 'code generation'! sizeForReturn: encoder (code >= LdSelf and: [code <= LdNil]) ifTrue: ["short returns" ^1]. ^super sizeForReturn: encoder! ! !VariableNode methodsFor: 'code generation'! sizeForStore: encoder self reserve: encoder. code < 256 ifTrue: [^ 2]. (code \\ 256) <= 63 ifTrue: [^ 2]. ^ 3! ! !VariableNode methodsFor: 'code generation'! sizeForStorePop: encoder self reserve: encoder. (code < 24 and: [code noMask: 8]) ifTrue: [^ 1]. code < 256 ifTrue: [^ 2]. code \\ 256 <= 63 ifTrue: [^ 2]. "extended StorePop" code // 256 = 1 ifTrue: [^ 3]. "dbl extended StorePopInst" code // 256 = 4 ifTrue: [^ 4]. "dbl extended StoreLitVar , Pop" self halt. "Shouldn't get here"! ! !VariableNode methodsFor: 'printing' stamp: 'di 4/5/2000 15:11'! printOn: aStream indent: level aStream withStyleFor: #variable do: [aStream nextPutAll: name]. ! ! !VariableNode methodsFor: 'accessing' stamp: 'tk 1/30/2001 13:45'! name ^ name! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! VariableNode class instanceVariableNames: ''! !VariableNode class methodsFor: 'class initialization'! initialize "VariableNode initialize. Decompiler initialize" | encoder | encoder _ Encoder new. StdVariables _ Dictionary new: 16. encoder fillDict: StdVariables with: VariableNode mapping: #('self' 'thisContext' 'super' 'nil' 'false' 'true' ) to: (Array with: LdSelf with: LdThisContext with: LdSuper) , (Array with: LdNil with: LdFalse with: LdTrue). StdSelectors _ Dictionary new: 64. encoder fillDict: StdSelectors with: SelectorNode mapping: ((1 to: Smalltalk specialSelectorSize) collect: [:i | Smalltalk specialSelectorAt: i]) to: (SendPlus to: SendPlus + 31). StdLiterals _ LiteralDictionary new: 16. encoder fillDict: StdLiterals with: LiteralNode mapping: #(-1 0 1 2 ) to: (LdMinus1 to: LdMinus1 + 3). encoder initScopeAndLiteralTables. NodeNil _ encoder encodeVariable: 'nil'. NodeTrue _ encoder encodeVariable: 'true'. NodeFalse _ encoder encodeVariable: 'false'. NodeSelf _ encoder encodeVariable: 'self'. NodeThisContext _ encoder encodeVariable: 'thisContext'. NodeSuper _ encoder encodeVariable: 'super'! ! Magnitude subclass: #VersionNumber instanceVariableNames: 'numbers' classVariableNames: '' poolDictionaries: '' category: 'VersionNumber'! !VersionNumber commentStamp: '<historical>' prior: 0! I am a version number. My representation allows me to handle an entire tree of versions. Once created, an instance should not change (note: VersionNumbers could be canonicalized like Symbols, but are not currently). I am a magnitude so that you can see if one version preceeds another (only if the two versions are in the same branch). '2.1' asVersion < '2.2.1' asVersion "true" '2.3' asVersion < '2.2.1' asVersion "error different branches" '2.3' asVersion inSameBranchAs: '2.2.1' asVersion "false, why the previous one failed." '2.1' asVersion = '2.1' asVersion "true, obviously" To get the next version number in the same branch: '2.3.4' asVersion next "2.3.5" To get the next version number, starting a new branch: '2.3.4' asVersion branchNext "2.3.4.1" To get the common base version of any two version numbers (useful for merging): '2.3.8' asVersion commonBase: '2.3.4.1' asVersion "2.3.4"! !VersionNumber methodsFor: 'comparing' stamp: 'svp 6/18/2002 15:05'! < another "Answer whether the receiver is less than the argument." | tmp | (self inSameBranchAs: another) ifFalse: [^self error: 'Receiver and argument in different branches']. tmp := another numbers. (tmp size = numbers size) ifTrue: [1 to: numbers size do: [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. ^false]. ^numbers size < tmp size ! ! !VersionNumber methodsFor: 'comparing' stamp: 'svp 6/18/2002 15:10'! = aVersion ^numbers = aVersion numbers! ! !VersionNumber methodsFor: 'comparing' stamp: 'svp 6/18/2002 12:23'! hash ^numbers hash! ! !VersionNumber methodsFor: 'accessing' stamp: 'svp 6/18/2002 12:14'! next | tmp | tmp := numbers copy. tmp at: numbers size put: (numbers last + 1). ^self class fromCollection: tmp! ! !VersionNumber methodsFor: 'accessing' stamp: 'svp 6/18/2002 14:51'! numbers "Answer a copy (to discourage people from directly changing a version number). VersionNumbers should never change, instead, instantiate a new instance." ^numbers copy! ! !VersionNumber methodsFor: 'testing' stamp: 'svp 6/18/2002 14:57'! inSameBranchAs: aVersion | less more | (aVersion numbers size <= numbers size) ifTrue: [less := aVersion numbers. more := numbers] ifFalse: [less := numbers. more := aVersion numbers]. 1 to: (less size - 1) do: [ :in | ((less at: in) = (more at: in)) ifFalse: [^false]]. ^less size = more size or: [(less at: less size) <= (more at: less size)] ! ! !VersionNumber methodsFor: 'initialization' stamp: 'svp 6/18/2002 15:08'! initializeNumbers: aCollection aCollection do: [ :ea | ea <= 0 ifTrue: [^self error: 'VersionNumbers cannot contain zero or negative numbers']]. numbers := aCollection asArray! ! !VersionNumber methodsFor: 'printing' stamp: 'svp 6/18/2002 12:27'! printOn: strm self storeOn: strm! ! !VersionNumber methodsFor: 'printing' stamp: 'svp 6/18/2002 17:24'! storeOn: strm strm nextPut: $'. self versionStringOn: strm. strm nextPutAll: ''' asVersion'.! ! !VersionNumber methodsFor: '*smbase-override' stamp: 'svp 6/18/2002 17:23'! versionStringOn: strm | first | first := true. numbers do: [ :ea | first ifFalse: [strm nextPut: $.]. first := false. ea printOn: strm] ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! VersionNumber class instanceVariableNames: ''! !VersionNumber class methodsFor: 'as yet unclassified' stamp: 'svp 6/18/2002 16:34'! first ^self fromCollection: #(1)! ! !VersionNumber class methodsFor: 'as yet unclassified' stamp: 'svp 6/18/2002 12:21'! fromCollection: aCollection ^self new initializeNumbers: aCollection; yourself! ! !VersionNumber class methodsFor: 'as yet unclassified' stamp: 'svp 6/18/2002 12:20'! fromString: aString ^self fromCollection: ((aString findTokens: '.') collect: [:ea | ea asNumber ]) ! ! ChangeList subclass: #VersionsBrowser instanceVariableNames: 'classOfMethod selectorOfMethod addedChangeRecord' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! !VersionsBrowser commentStamp: 'nk 11/25/2003 10:04' prior: 0! VersionsBrowser shows all the versions of a particular method, and lets you compare them, revert to selected versions, and so on.! !VersionsBrowser methodsFor: 'init & update' stamp: 'nk 1/7/2004 10:10'! addedChangeRecord ^addedChangeRecord! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'nk 1/7/2004 10:23'! addedChangeRecord: aChangeRecord addedChangeRecord _ aChangeRecord. self reformulateList.! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'sw 5/6/2000 01:16'! changeListButtonSpecs ^#( ('compare to current' compareToCurrentVersion 'opens a separate window which shows the text differences between the selected version and the current version') ('revert' fileInSelections 'reverts the method to the version selected') ('remove from changes' removeMethodFromChanges 'remove this method from the current change set') ('help' offerVersionsHelp 'further explanation about use of Versions browsers') )! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'sw 11/28/1999 22:50'! reformulateList | aMethod | "Some uncertainty about how to deal with lost methods here" aMethod _ classOfMethod compiledMethodAt: selectorOfMethod ifAbsent: [^ self]. self scanVersionsOf: aMethod class: classOfMethod theNonMetaClass meta: classOfMethod isMeta category: (classOfMethod whichCategoryIncludesSelector: selectorOfMethod) selector: selectorOfMethod. self changed: #list. "for benefit of mvc" listIndex _ 1. self changed: #listIndex. self contentsChanged ! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'nk 1/7/2004 10:29'! scanVersionsOf: method class: class meta: meta category: category selector: selector | position prevPos prevFileIndex preamble tokens sourceFilesCopy stamp | selectorOfMethod _ selector. currentCompiledMethod _ method. classOfMethod _ meta ifTrue: [class class] ifFalse: [class]. changeList _ OrderedCollection new. list _ OrderedCollection new. self addedChangeRecord ifNotNilDo: [ :change | self addItem: change text: ('{1} (in {2})' translated format: { change stamp. change fileName }) ]. listIndex _ 0. position _ method filePosition. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. method fileIndex == 0 ifTrue: [^ nil]. file _ sourceFilesCopy at: method fileIndex. [position notNil & file notNil] whileTrue: [file position: (0 max: position-150). "Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. "Preamble is likely a linked method preamble, if we're in a changes file (not the sources file). Try to parse it for prior source position and file index" prevPos _ nil. stamp _ ''. (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble] ifFalse: [tokens _ Array new "ie cant be back ref"]. ((tokens size between: 7 and: 8) and: [(tokens at: tokens size-5) = #methodsFor:]) ifTrue: [(tokens at: tokens size-3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos] ifFalse: ["Old format gives no stamp; prior pointer in two parts" prevPos _ tokens at: tokens size-2. prevFileIndex _ tokens last]. (prevPos = 0 or: [prevFileIndex = 0]) ifTrue: [prevPos _ nil]]. ((tokens size between: 5 and: 6) and: [(tokens at: tokens size-3) = #methodsFor:]) ifTrue: [(tokens at: tokens size-1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size]]. self addItem: (ChangeRecord new file: file position: position type: #method class: class name category: category meta: meta stamp: stamp) text: stamp , ' ' , class name , (meta ifTrue: [' class '] ifFalse: [' ']) , selector. position _ prevPos. prevPos notNil ifTrue: [file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'di 11/28/2000 01:25'! updateListsAndCodeIn: aWindow | aMethod | aMethod _ classOfMethod compiledMethodAt: selectorOfMethod ifAbsent: [^ false]. aMethod == currentCompiledMethod ifFalse: ["Do not attempt to formulate if there is no source pointer. It probably means it has been recompiled, but the source hasn't been written (as during a display of the 'save text simply?' confirmation)." aMethod last ~= 0 ifTrue: [self reformulateList]]. ^ true ! ! !VersionsBrowser methodsFor: 'menu' stamp: 'sw 2/27/2001 08:46'! changeListKey: aChar from: view "Respond to a Command key in the list pane. of the versions browser" ^ self messageListKey: aChar from: view! ! !VersionsBrowser methodsFor: 'menu' stamp: 'sw 10/12/1999 17:51'! fileInSelections super fileInSelections. self reformulateList! ! !VersionsBrowser methodsFor: 'menu' stamp: 'BG 10/28/2003 20:49'! versionsMenu: aMenu "Fill aMenu with menu items appropriate to the receiver" ^ aMenu addList: #( ('compare to current' compareToCurrentVersion 'compare selected version to the current version') ('revert to selected version' fileInSelections 'resubmit the selected version, so that it becomes the current version') ('remove from changes' removeMethodFromChanges 'remove this method from the current change set, if present') ('edit current method (O)' openSingleMessageBrowser 'open a single-message browser on the current version of this method') ('find original change set' findOriginalChangeSet 'locate the changeset which originally contained this version') - ('toggle diffing (D)' toggleDiffing 'toggle whether or not diffs should be shown here') ('update list' reformulateList 'reformulate the list of versions, in case it somehow got out of synch with reality') - ('senders (n)' browseSenders 'browse all senders of this selector') ('implementors (m)' browseImplementors 'browse all implementors of this selector') - ('help...' offerVersionsHelp 'provide an explanation of the use of this tool')) ! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 2/27/2001 08:17'! addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream "Add an annotation detailing the prior versions count. Specially handled here for the case of a selector no longer in the system, whose prior versions are seen in a versions browser -- in this case, the inherited version of this method will not work." (aClass includesSelector: aSelector) ifTrue: [^ super addPriorVersionsCountForSelector: aSelector ofClass: aClass to: aStream]. aStream nextPutAll: ((changeList size > 0 ifTrue: [changeList size == 1 ifTrue: ['Deleted - one prior version'] ifFalse: ['Deleted - ', changeList size printString, ' prior versions']] ifFalse: ['surprisingly, no prior versions']), self annotationSeparator)! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 8/17/2002 21:57'! classCommentIndicated "Answer whether the receiver is pointed at a class comment" ^ false! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 1/25/2001 07:03'! selectedClass "Answer the class currently selected in the browser. In the case of a VersionsBrowser, the class and selector are always the same, regardless of which version is selected and indeed whether or not any entry is selected in the list pane" ^ classOfMethod theNonMetaClass! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 1/25/2001 06:26'! selectedClassOrMetaClass "Answer the class or metaclass currently selected in the browser. In the case of a VersionsBrowser, the class and selector are always the same, regardless of which version is selected and indeed whether or not any entry is selected in the list pane" ^ classOfMethod! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 1/25/2001 06:10'! selectedMessageName "Answer the message name currently selected in the browser. In the case of a VersionsBrowser, the class and selector are always the same, regardless of which version is selected and indeed whether or not any entry is selected in the list pane" ^ selectorOfMethod! ! !VersionsBrowser methodsFor: 'misc' stamp: 'sw 10/19/1999 15:04'! showsVersions ^ true! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! VersionsBrowser class instanceVariableNames: ''! !VersionsBrowser class methodsFor: 'as yet unclassified' stamp: 'di 1/11/2000 12:45'! browseVersionsOf: method class: class meta: meta category: msgCategory selector: selector ^ self browseVersionsOf: method class: class meta: meta category: msgCategory selector: selector lostMethodPointer: nil! ! !VersionsBrowser class methodsFor: 'as yet unclassified' stamp: 'nk 1/7/2004 10:19'! browseVersionsOf: method class: class meta: meta category: msgCategory selector: selector lostMethodPointer: sourcePointer | changeList browser | Cursor read showWhile: [changeList _ (browser _ self new) scanVersionsOf: method class: class meta: meta category: msgCategory selector: selector]. changeList ifNil: [ self inform: 'No versions available'. ^nil ]. sourcePointer ifNotNil: [changeList setLostMethodPointer: sourcePointer]. self open: changeList name: 'Recent versions of ' , selector multiSelect: false. ^browser! ! !VersionsBrowser class methodsFor: 'as yet unclassified' stamp: 'sw 10/21/1999 17:21'! timeStampFor: aSelector class: aClass reverseOrdinal: anInteger "Answer the time stamp corresponding to some version of the given method, nil if none. The reverseOrdinal parameter is interpreted as: 1 = current version; 2 = last-but-one version, etc." | method aChangeList | method _ aClass compiledMethodAt: aSelector ifAbsent: [^ nil]. aChangeList _ self new scanVersionsOf: method class: aClass meta: aClass isMeta category: nil selector: aSelector. ^ aChangeList ifNil: [nil] ifNotNil: [aChangeList list size >= anInteger ifTrue: [(aChangeList changeList at: anInteger) stamp] ifFalse: [nil]]! ! !VersionsBrowser class methodsFor: 'as yet unclassified' stamp: 'sw 10/19/1999 15:01'! versionCountForSelector: aSelector class: aClass "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. Answer zero if no logged version can be obtained." | method aChangeList | method _ aClass compiledMethodAt: aSelector ifAbsent: [^ 0]. aChangeList _ self new scanVersionsOf: method class: aClass meta: aClass isMeta category: nil selector: aSelector. ^ aChangeList ifNil: [0] ifNotNil: [aChangeList list size]! ! Object subclass: #View instanceVariableNames: 'model controller superView subViews transformation viewport window displayTransformation insetDisplayBox borderWidth borderColor insideColor boundingBox' classVariableNames: '' poolDictionaries: '' category: 'ST80-Framework'! !View commentStamp: '<historical>' prior: 0! 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: 1. Adding subViews to a View. 2. Positioning subViews within a View. 3. Deleting subViews from a View. 4. Transforming a View. 5. Displaying a View. 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. 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.! !View methodsFor: 'initialize-release'! initialize "Initialize the state of the receiver. Subclasses should include 'super initialize' when redefining this message to insure proper initialization." self resetSubViews. transformation _ WindowingTransformation identity. self borderWidth: 0! ! !View methodsFor: 'initialize-release'! release "Remove the receiver from its model's list of dependents (if the model exists), and release all of its subViews. It is used to break possible cycles in the receiver and should be sent when the receiver is no longer needed. Subclasses should include 'super release.' when redefining release." model removeDependent: self. model _ nil. controller release. controller _ nil. subViews ~~ nil ifTrue: [subViews do: [:aView | aView release]]. subViews _ nil. superView _ nil! ! !View methodsFor: 'initialize-release'! setDefaultBackgroundColor "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" | colorToUse | colorToUse _ Preferences uniformWindowColors ifTrue: [Object new defaultBackgroundColor] ifFalse: [model defaultBackgroundColor]. self backgroundColor: colorToUse! ! !View methodsFor: 'testing' stamp: 'tk 4/13/1998 22:58'! canDiscardEdits "Return true if this pane is not dirty." ^ true ! ! !View methodsFor: 'testing'! containsPoint: aPoint "Answer whether aPoint is within the receiver's display box. It is sent to a View's subViews by View|subViewAt: in order to determine which subView contains the cursor point (so that, for example, control can be pass down to that subView's controller)." ^ self insetDisplayBox containsPoint: aPoint! ! !View methodsFor: 'testing' stamp: 'jm 3/17/98 13:35'! hasUnacceptedEdits "Return true if this view has unaccepted edits." ^ false ! ! !View methodsFor: 'testing'! isObscured | topController displayRect | (topController _ self topView controller) == ScheduledControllers activeController ifTrue: [^false]. displayRect _ self insetDisplayBox. ScheduledControllers scheduledControllers do: [:ctrlr | ctrlr == topController ifTrue: [^false]. (displayRect intersects: ctrlr view insetDisplayBox) ifTrue: [^true]]. self error: 'not in ScheduledControllers'. ^false! ! !View methodsFor: 'model access'! model "Answer the receiver's model." ^model! ! !View methodsFor: 'model access'! model: aModel "Set the receiver's model to aModel. The model of the receiver's controller is also set to aModel." self model: aModel controller: controller! ! !View methodsFor: 'superView access'! isTopView "Answer whether the receiver is a top view, that is, if it has no superView." ^superView == nil! ! !View methodsFor: 'superView access'! superView "Answer the superView of the receiver." ^superView! ! !View methodsFor: 'superView access'! topView "Answer the root of the tree of Views in which the receiver is a node. The root of the tree is found by going up the superView path until reaching a View whose superView is nil." superView == nil ifTrue: [^self] ifFalse: [^superView topView]! ! !View methodsFor: 'subView access'! firstSubView "Answer the first subView in the receiver's list of subViews if it is not empty, else nil." subViews isEmpty ifTrue: [^nil] ifFalse: [^subViews first]! ! !View methodsFor: 'subView access'! lastSubView "Answer the last subView in the receiver's list of subViews if it is not empty, else nil." subViews isEmpty ifTrue: [^nil] ifFalse: [^subViews last]! ! !View methodsFor: 'subView access'! resetSubViews "Set the list of subviews to an empty collection." subViews _ OrderedCollection new! ! !View methodsFor: 'subView access'! subViewContaining: aPoint "Answer the first subView that contains aPoint within its window and answer nil, otherwise. It is typically sent from a Controller in order to determine where to pass control (usually to the Controller of the View returned by View|subViewContaining:)." subViews reverseDo: [:aSubView | (aSubView displayBox containsPoint: aPoint) ifTrue: [^aSubView]]. ^nil! ! !View methodsFor: 'subView access'! subViewSatisfying: aBlock "Return the first subview that satisfies aBlock, or nil if none does. 1/31/96 sw" ^ subViews detect: [:aView | aBlock value: aView] ifNone: [nil]! ! !View methodsFor: 'subView access'! subViews "Answer the receiver's collection of subViews." ^subViews! ! !View methodsFor: 'subView access'! textEditorView "Return the first view in the receiver whose controller is a ParagraphEdior, or nil if none. 1/31/96 sw" (controller isKindOf: ParagraphEditor) ifTrue: [^ self]. ^ self subViewSatisfying: [:v | v textEditorView ~~ nil]! ! !View methodsFor: 'controller access'! controller "If the receiver's controller is nil (the default case), answer an initialized instance of the receiver's default controller. If the receiver does not allow a controller, answer the symbol #NoControllerAllowed." controller == nil ifTrue: [self controller: self defaultController]. ^controller! ! !View methodsFor: 'controller access'! controller: aController "Set the receiver's controller to aController. #NoControllerAllowed can be specified to indicate that the receiver will not have a controller. The model of aController is set to the receiver's model." self model: model controller: aController! ! !View methodsFor: 'controller access'! defaultController "Answer an initialized instance of the receiver's default controller. Subclasses should redefine this message only if the default controller instances need to be initialized in a nonstandard way." ^self defaultControllerClass new! ! !View methodsFor: 'controller access'! defaultControllerClass "Answer the class of the default controller for the receiver. Subclasses should redefine View|defaultControllerClass if the class of the default controller is not Controller." ^Controller! ! !View methodsFor: 'controller access'! model: aModel controller: aController "Set the receiver's model to aModel, add the receiver to aModel's list of dependents, and set the receiver's controller to aController. Subsequent changes to aModel (see Model|change) will result in View|update: messages being sent to the receiver. #NoControllerAllowed for the value of aController indicates that no default controller is available; nil for the value of aController indicates that the default controller is to be used when needed. If aController is neither #NoControllerAllowed nor nil, its view is set to the receiver and its model is set to aModel." model ~~ nil & (model ~~ aModel) ifTrue: [model removeDependent: self]. aModel ~~ nil & (aModel ~~ model) ifTrue: [aModel addDependent: self]. model _ aModel. aController ~~ nil ifTrue: [aController view: self. aController model: aModel]. controller _ aController! ! !View methodsFor: 'basic control sequence'! subViewWantingControl "Answer the first subView that has a controller that now wants control." subViews reverseDo: [:aSubView | aSubView controller isControlWanted ifTrue: [^aSubView]]. ^nil! ! !View methodsFor: 'window access'! defaultWindow "Build the minimum Rectangle that encloses all the windows of the receiver's subViews. The answer is a Rectangle obtained by expanding this minimal Rectangle by the borderWidth of the receiver. If the receiver has no subViews, then a Rectangle enclosing the entire display screen is answered. It is used internally by View methods if no window has been specified for the View. Specialized subclasses of View should redefine View|defaultWindow to handle the default case for instances that have no subViews." | aRectangle | subViews isEmpty ifTrue: [^DisplayScreen boundingBox]. aRectangle _ self firstSubView viewport. subViews do: [:aView | aRectangle _ aRectangle merge: aView viewport]. ^aRectangle expandBy: borderWidth! ! !View methodsFor: 'window access'! insetWindow "Answer a Rectangle that is obtained by insetting the receiver's window rectangle by the border width." ^self getWindow insetBy: borderWidth! ! !View methodsFor: 'window access'! window "Answer a copy of the receiver's window." ^self getWindow copy! ! !View methodsFor: 'window access'! window: aWindow "Set the receiver's window to a copy of aWindow." self setWindow: aWindow copy! ! !View methodsFor: 'viewport access'! viewport "Answer a copy of the receiver's viewport." ^self getViewport copy! ! !View methodsFor: 'display box access'! apparentDisplayBox ^self insetDisplayBox expandBy: 2 @ 2! ! !View methodsFor: 'display box access'! boundingBox "Answer the bounding box which for the default case is the rectangular area surrounding the bounding boxes of all the subViews." boundingBox ~~ nil ifTrue: [^boundingBox] ifFalse: [^self computeBoundingBox]! ! !View methodsFor: 'display box access'! computeBoundingBox "Answer the minimum Rectangle that encloses the bounding boxes of the receiver's subViews. If the receiver has no subViews, then the bounding box is the receiver's window. Subclasses should redefine View|boundingBox if a more suitable default for the case of no subViews is available." | aRectangle | subViews isEmpty ifTrue: [^self getWindow]. aRectangle _ self firstSubView transform: self firstSubView boundingBox. subViews do: [:aView | aRectangle _ aRectangle merge: (aView transform: aView boundingBox).]. ^aRectangle expandBy: borderWidth! ! !View methodsFor: 'display box access'! displayBox "Answer the receiver's inset display box (see View|insetDisplayBox) expanded by the borderWidth. The display box represents the region of the display screen in which the receiver (including the border) is displayed. If the receiver is totally clipped by the display screen and its superView, the resulting Rectangle will be invalid." ^self insetDisplayBox expandBy: borderWidth! ! !View methodsFor: 'display box access' stamp: 'acg 2/23/2000 00:08'! insetDisplayBox "Answer the receiver's inset display box. The inset display box is the intersection of the receiver's window, tranformed to display coordinates, and the inset display box of the superView, inset by the border width. The inset display box represents the region of the display screen in which the inside of the receiver (all except the border) is displayed. If the receiver is totally clipped by the display screen and its superView, the resulting Rectangle will be invalid." insetDisplayBox ifNil: [insetDisplayBox _ self computeInsetDisplayBox]. ^insetDisplayBox! ! !View methodsFor: 'lock access'! isLocked "Answer whether the receiver is locked. A View is 'locked' if its display transformation and inset display box are defined. If these are undefined, the View is 'unlocked'. The display transformation and inset display box become undefined when the transformation of the View (or the transformation of a View in its superView chain) is changed, or when the superView of the View is changed, or any other change to the View that affects the display screen coordinates of the View. The locking and unlocking of a View is handled automatically by the internal methods of the View, but can also be done explicitly if desired (see View|lock, and View|unlock)." displayTransformation == nil | (insetDisplayBox == nil) ifTrue: [^false] ifFalse: [^true]! ! !View methodsFor: 'lock access'! isUnlocked "Answer whether the receiver is unlocked. See comment in View|isLocked." ^displayTransformation == nil & (insetDisplayBox == nil)! ! !View methodsFor: 'lock access'! lock "'Lock' the receiver and all of its subViews (see View|isLocked). This has the effect of computing and storing the display transformation (see View|displayTransformation) and inset display box (see View|insetDisplayBox) of the receiver and all its subViews. The locking and unlocking of a View is handled automatically by the internal methods of the View, but can also be done explicitly if desired." self isLocked ifTrue: [^self]. displayTransformation _ self computeDisplayTransformation. insetDisplayBox _ self computeInsetDisplayBox. subViews do: [:aSubView | aSubView lock]! ! !View methodsFor: 'lock access'! unlock "Unlock the receiver and all of its subViews (see View|isUnlocked). This has the effect of forcing the display transformation (see View|displayTransformation) and inset display box (see View|insetDisplayBox) of the receiver and all its subViews to be recomputed the next time they are referenced. The locking and unlocking of a View is handled automatically by the internal methods of the View, but can also be done explicitly if desired." self isUnlocked ifTrue: [^self]. displayTransformation _ nil. insetDisplayBox _ nil. subViews do: [:aSubView | aSubView unlock]! ! !View methodsFor: 'subView inserting'! addSubView: aView "Remove aView from the tree of Views it is in (if any) and adds it to the rear of the list of subViews of the receiver. Set the superView of aView to be the receiver. It is typically used to build up a hierarchy of Views (a structured picture). An error notification is generated if aView is the same as the receiver or its superView, and so on." self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']! ! !View methodsFor: 'subView inserting'! addSubView: aSubView above: lowerView "Adds aView (see View|addSubView:) so that it lies above topView." self addSubView: aSubView align: aSubView viewport bottomLeft with: lowerView viewport topLeft! ! !View methodsFor: 'subView inserting'! addSubView: aSubView align: aPoint1 with: aPoint2 "Add aView to the receiver's list of subViews (see View|addSubView:) and translate aView so that aPoint1 coincides with aPoint2. It is typically used to build up a hierarchy of Views (a structured picture). Normally, aPoint1 is a point on aView's viewport (e.g. aView viewport topLeft), and aPoint2 is either an arbitrary point in the receiver's coordinate system or a point on the receiver's window (e.g., self window topRight)." self addSubView: aSubView. aSubView align: aPoint1 with: aPoint2! ! !View methodsFor: 'subView inserting'! addSubView: aSubView below: lowerView "Add the argument, aSubView, (see View|addSubView:) so that it lies below the view, topView." self addSubView: aSubView align: aSubView viewport topLeft with: lowerView viewport bottomLeft! ! !View methodsFor: 'subView inserting'! addSubView: aView ifCyclic: exceptionBlock "Remove aView from the tree of Views it is in (if any) and add it to the rear of the list of subViews of the receiver. Set the superView of aView to be the receiver. It is typically used to build up a hierarchy of Views (a structured picture). An error notification is generated if aView is the same as the receiver or its superView, and so on." (self isCyclic: aView) ifTrue: [exceptionBlock value] ifFalse: [aView removeFromSuperView. subViews addLast: aView. aView superView: self]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 8/15/2008 17:31'! addSubView: aView in: aRelativeRectangle borderWidth: width "ssa - added for compatibility." "Make 'aView' into a subview. Use 'aRelativeRectangle' and the super view's window to compute (1) a viewport within the superview for 'aView' and (2) the window extent for 'aView'. Note: defining the windowing transformation and deriving the viewport is logically equivalent but does not seem to be easily done" | subViewPort myWindow myExtent myOrigin | self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']. aView borderWidth: width. myWindow _ self window. myExtent _ myWindow extent. myOrigin _ myWindow origin. subViewPort _ myExtent * aRelativeRectangle origin + myOrigin corner: myExtent * aRelativeRectangle corner + myOrigin. aView window: aView window viewport: subViewPort ! ! !View methodsFor: 'subView inserting'! addSubView: aSubView toLeftOf: rightView "Adds aView (see addSubView:) so that it lies to the right of rightView." self addSubView: aSubView align: aSubView viewport topRight with: rightView viewport topLeft! ! !View methodsFor: 'subView inserting'! addSubView: aSubView toRightOf: leftView "Add the argument, aSubView, (see View|addSubView:) so that it lies to the right of the view, leftView." self addSubView: aSubView align: aSubView viewport topLeft with: leftView viewport topRight! ! !View methodsFor: 'subView inserting'! addSubView: aView viewport: aViewport "Add aView to the receiver's list of subViews (see View|addSubView:) and applies to aView a scale and translation computed from its window and aViewport (such that its window fills aViewport)." self addSubView: aView. aView window: aView window viewport: aViewport! ! !View methodsFor: 'subView inserting'! addSubView: aView window: aWindow viewport: aViewport "Add aView to the receiver's list of subViews (see View|addSubView:) and applies to aView a scale and translation computed from aWindow and aViewport (such that aWindow fills aViewport)." self addSubView: aView. aView window: aWindow viewport: aViewport! ! !View methodsFor: 'subView removing'! releaseSubView: aView "Delete aView from the receiver's list of subViews and send it the message 'release' (so that it can break up cycles with subViews, etc.)." self removeSubView: aView. aView release! ! !View methodsFor: 'subView removing'! releaseSubViews "Release (see View|releaseSubView:) all subViews in the receiver's list of subViews." subViews do: [:aView | aView release]. self resetSubViews! ! !View methodsFor: 'subView removing'! removeFromSuperView "Delete the receiver from its superView's collection of subViews." superView ~= nil ifTrue: [superView removeSubView: self]! ! !View methodsFor: 'subView removing'! removeSubView: aView "Delete aView from the receiver's list of subViews. If the list of subViews does not contain aView, create an error notification." subViews remove: aView. aView superView: nil. aView unlock! ! !View methodsFor: 'subView removing'! removeSubViews "Delete all the receiver's subViews." subViews do: [:aView | aView superView: nil. aView unlock]. self resetSubViews! ! !View methodsFor: 'displaying'! clippingTo: rect do: aBlock superView clippingTo: rect do: aBlock! ! !View methodsFor: 'displaying' stamp: 'hmm 6/27/2000 07:07'! display "Display the receiver's border, display the receiver, then display the subViews of the receiver. Can be sent to the top View of a structured picture in order to display the entire structure, or to any particular View in the structure in order to display that View and its subViews. It is typically sent in response to an update request to a View." Display deferUpdatesIn: self displayBox while: [ self displayBorder. self displayView. self displaySubViews]! ! !View methodsFor: 'displaying'! displayBorder "Display the receiver's border (using the receiver's borderColor)." borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [Display border: self displayBox widthRectangle: borderWidth rule: Form over fillColor: self foregroundColor. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: self backgroundColor]]! ! !View methodsFor: 'displaying'! displayClippingTo: rect | bigRect | bigRect _ rect insetBy: -1. self clippingTo: bigRect do: [Display clippingTo: bigRect do: [self display]] ! ! !View methodsFor: 'displaying'! displayDeEmphasized self display; deEmphasize! ! !View methodsFor: 'displaying'! displaySubViews "Display all the subViews of the receiver." subViews do: [:aSubView | aSubView display]! ! !View methodsFor: 'displaying'! displayView "Subclasses should redefine View|displayView in order to display particular objects associated with the View such as labels, lines, and boxes." ^self! ! !View methodsFor: 'displaying'! displayViewDeEmphasized self displayView; deEmphasizeView! ! !View methodsFor: 'displaying'! inspectFirstSubView subViews notNil ifTrue: [subViews size > 0 ifTrue: [(subViews at: 1) inspect]]! ! !View methodsFor: 'displaying'! inspectModel model notNil ifTrue: [^ model inspect] ifFalse: [self flash]! ! !View methodsFor: 'displaying'! inspectView ^self inspect! ! !View methodsFor: 'displaying'! maximumSize "Answer the maximum size of the receiver." ^ 10000 @ 10000 ! ! !View methodsFor: 'displaying'! minimumSize "Answer the minimum size of the receiver." ^ 10 @ 10 ! ! !View methodsFor: 'deEmphasizing'! deEmphasize "Modify the emphasis (highlighting, special tabs) of the receiver. This includes objects such as labels, lines, and boxes. Typically used so that the receiver is not presented as active. Do this for the receiver and then for each of the receiver's subViews." self deEmphasizeView. self deEmphasizeSubViews! ! !View methodsFor: 'deEmphasizing'! deEmphasizeForDebugger "Overridden by StandardSystemView. This default behavior does nothing." ! ! !View methodsFor: 'deEmphasizing'! deEmphasizeSubViews "Send the deEmphasize message to each of the receiver's subviews." subViews do: [:aSubView | aSubView deEmphasize]! ! !View methodsFor: 'deEmphasizing'! deEmphasizeView "Subclasses should redefine View|deEmphasizeView in order to modify the emphasis (highlighting, special tabs) of particular objects associated with the View such as labels, lines, and boxes." ^self! ! !View methodsFor: 'deEmphasizing'! emphasize "Modify the emphasis (highlighting, special tabs) of the receiver. This includes objects such as labels, lines, and boxes. Typically used so that the receiver is presented as active. Do this for the receiver and then for each of the receiver's subViews." self emphasizeView. self emphasizeSubViews! ! !View methodsFor: 'deEmphasizing'! emphasizeSubViews "Send the emphasize message to each of the receiver's subviews." subViews do: [:aSubView | aSubView emphasize]! ! !View methodsFor: 'deEmphasizing'! emphasizeView "Subclasses should redefine View|emphasizeView in order to modify the emphasis (highlighting, special tabs) of particular objects associated with the View such as labels, lines, and boxes." ^self! ! !View methodsFor: 'display transformation'! displayTransform: anObject "Apply the display transformation of the receiver to anObject (see View|displayTransformation) and answer the resulting scaled, translated object. It is normally applied to Rectangles, Points, and other objects with coordinates defined in the View's local coordinate system in order to get a corresponding object in display coordinates." ^(self displayTransformation applyTo: anObject) rounded! ! !View methodsFor: 'display transformation'! displayTransformation "Answer a WindowingTransformation that is the result of composing all local transformations in the receiver's superView chain with the receiver's own local transformation. The resulting transformation transforms objects in the receiver's coordinate system into objects in the display screen coordinate system." displayTransformation == nil ifTrue: [displayTransformation _ self computeDisplayTransformation]. ^displayTransformation! ! !View methodsFor: 'display transformation'! inverseDisplayTransform: aPoint "Answer a Point that is obtained from the argument, aPoint, by applying to it the inverse of the receiver's display transformation. It is typically used by the Controller of the receiver in order to convert a point in display coordinates, such as the cursor point, to the local coordinate system of the receiver." ^self displayTransformation applyInverseTo: aPoint! ! !View methodsFor: 'transforming'! align: aPoint1 with: aPoint2 "Add a translation of (aPoint2 - aPoint1) to the receiver's local transformation. The point in the receiver's coordinate system that previously was transformed to aPoint1 in the superView's coordinate system will now be transformed to aPoint2 in the superView's coordinate system. Other points will be translated by the same amount. It is normally used when adding subViews to their superView in order to line up the Viewport of one subView with that of another subView (see View|addSubView:align:with:). aPoint1 and aPoint2 are usually points on the viewports that are to be aligned. For example, 'subView2 align: subView2 viewport topLeft with: subView1 viewport topRight' would be used to place the viewport of subView2 next to the viewport of subView1 with the topLeft and topRight corners, respectively, coinciding. It is also possible to align the viewport of a subView with the window of the superView, e.g., 'subView align: subView viewport center with: superView window center'. View|align:with: assumes that the view has been properly scaled, if necessary, to match its superView (see View|scaleBy:). Typically, the coordinate systems of the receiver and its superView will differ only by a translation offset so that no scaling is necessary." self setTransformation: (transformation align: aPoint1 with: aPoint2)! ! !View methodsFor: 'transforming'! scale: aScale translation: aTranslation "The x component of aScale (a Point) specifies the scale (translation) in the x direction; the y component specifies the scale (translation) in the y direction. aScale can optionally be an instance of Integer or Float in order to specify uniform scaling in both directions. Create a new local transformation for the receiver with a scale factor of aScale and a translation offset of aTranslation. When the transformation is applied (see View|transform:), the scale is applied first, followed by the translation. It is typically used when building a superView from its subViews in order to line up the viewports of the subViews in the desired way. If no scaling is required between subView and superView, then View|align:with: is often more convenient to use." self setTransformation: (WindowingTransformation scale: aScale translation: aTranslation)! ! !View methodsFor: 'transforming'! scaleBy: aScale "The x component of aScale (a Point) specifies the scale in the x direction; the y component specifies the scale in the y direction. aScale can, optionally, be an instance of Integer or Float in order to specify uniform scaling in both directions. Scales the View by aScale. The scale is concatenated with the current transformation of the receiver and is applied when View|transform is sent. This happens automatically in the process of displaying the receiver, for example." self setTransformation: (transformation scaleBy: aScale)! ! !View methodsFor: 'transforming'! transform: anObject "Apply the local transformation of the receiver to anObject and answer the resulting transformation. It is used to get the superView coordinates of an object. For example, the viewport is equal to the window transformed." ^transformation applyTo: anObject! ! !View methodsFor: 'transforming'! transformation "Answer a copy of the receiver's local transformation." ^transformation copy! ! !View methodsFor: 'transforming'! transformation: aTransformation "Set the receiver's local transformation to a copy of aTransformation, unlock the receiver (see View|unlock) and set the viewport to undefined (this forces it to be recomputed when needed)." self setTransformation: aTransformation copy! ! !View methodsFor: 'transforming'! translateBy: aPoint "Translate the receiver by aPoint. The translation is concatenated with the current transformation of the receiver and is applied when View|transform is sent. This happens automatically in the process of displaying the receiver." self setTransformation: (transformation translateBy: aPoint)! ! !View methodsFor: 'transforming'! window: aWindow viewport: aViewport "Set the receiver's window to aWindow, set its viewport to aViewport, and create a new local transformation for the receiver based on aWindow and aViewport. The receiver is scaled and translated so that aWindow, when transformed, coincides with aViewport. It is used to position a subView's window within some specific region of its superView's area. For example, 'subView window: aRectangle1 viewport: aRectangle2' sets subView's window to aRectangle1, its viewport to aRectangle2, and its local transformation to one that transforms aRectangle1 to aRectange2." self window: aWindow. self setTransformation: (WindowingTransformation window: aWindow viewport: aViewport). self getViewport! ! !View methodsFor: 'bordering' stamp: 'sw 11/2/1998 15:34'! backgroundColor Display depth <= 2 ifTrue: [^ Color white]. insideColor ifNotNil: [^ Color colorFrom: insideColor]. ^ superView == nil ifFalse: [superView backgroundColor] ifTrue: [Color white]! ! !View methodsFor: 'bordering' stamp: 'tk 10/21/97 12:31'! backgroundColor: aColor Display depth = 1 ifTrue: [(aColor ~= nil and: [aColor isTransparent not]) ifTrue: ["Avoid stipple due to attempts to match non-whites" ^ insideColor _ Color white]]. insideColor _ aColor! ! !View methodsFor: 'bordering'! borderWidth "Answer either 0, indicating no border, or a Rectangle whose left value is the width in display coordinates of the receiver's left border. Right, top, and bottom widths are analogous. The border width is initially 0. A View with a border width of 0 will not have any border displayed." ^borderWidth! ! !View methodsFor: 'bordering'! borderWidth: anInteger "Set the four border widths of the receiver to anInteger." self borderWidthLeft: anInteger right: anInteger top: anInteger bottom: anInteger! ! !View methodsFor: 'bordering'! borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4 "Set the border widths of the receiver. These arguments represent the left, right, top, and bottom border widths." borderWidth _ Rectangle left: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4. self unlock! ! !View methodsFor: 'bordering' stamp: 'sw 11/2/1998 15:35'! foregroundColor borderColor ifNotNil: [^ Color colorFrom: borderColor]. ^ superView == nil ifFalse: [superView foregroundColor] ifTrue: [Color black]! ! !View methodsFor: 'bordering'! foregroundColor: aColor borderColor _ aColor! ! !View methodsFor: 'bordering'! insideColor: aColor ^ self backgroundColor: aColor! ! !View methodsFor: 'scrolling'! scrollBy: aPoint "The x component of aPoint specifies the amount of scrolling in the x direction; the y component specifies the amount of scrolling in the y direction. The amounts are specified in the receiver's local coordinate system. Scroll the receiver up or down, left or right. The window of the receiver is kept stationary and the subViews and other objects in the receiver are translated relative to it. Scrolling doesn't change the insetDisplayBox or the viewport since the change in the transformation is canceled by the change in the window. In other words, all display objects in the view, except the window, are translated by the scrolling operation. Note: subclasses may override to return false if no scrolling takes place." | aRectangle | aRectangle _ insetDisplayBox. transformation _ transformation scrollBy: aPoint. window _ self getWindow translateBy: aPoint x negated @ aPoint y negated. self unlock. insetDisplayBox _ aRectangle. ^ true! ! !View methodsFor: 'clearing'! clear "Use the border color to paint the display box (including the border, see View|displayBox) of the receiver." borderColor ~= nil ifTrue: [self clear: Color black]! ! !View methodsFor: 'clearing'! clear: aColor "Use aColor to paint the display box (including the border, see View|displayBox) of the receiver." aColor ~= nil ifTrue: [Display fill: self displayBox fillColor: aColor]! ! !View methodsFor: 'clearing'! clearInside "Use the inside color to paint the inset display box (excluding the border, see View|insetDisplayBox) of the receiver." self clearInside: self backgroundColor! ! !View methodsFor: 'clearing'! clearInside: aColor "Use aColor to paint the inset display box (excluding the border, see View|insetDisplayBox) of the receiver." aColor ~~ nil ifTrue: [Display fill: self insetDisplayBox fillColor: aColor]! ! !View methodsFor: 'indicating'! flash "Cause the inset display box (the display box excluding the border, see View|insetDisplayBox) of the receiver to complement twice in succession." Display flash: self insetDisplayBox! ! !View methodsFor: 'indicating'! highlight "Cause the inset display box (the display box excluding the border, see View|insetDisplayBox) of the receiver to complement." Display reverse: self insetDisplayBox! ! !View methodsFor: 'updating'! update "Normally sent by the receiver's model in order to notify the receiver of a change in the model's state. Subclasses implement this message to do particular update actions. A typical action that might be required is to redisplay the receiver." self update: self! ! !View methodsFor: 'updating'! update: aParameter "Normally sent by the receiver's model in order to notify the receiver of a change in the model's state. Subclasses implement this message to do particular update actions. A typical action that might be required is to redisplay the receiver." ^self! ! !View methodsFor: 'private'! computeDisplayTransformation "Answer a WindowingTransformation that transforms the coordinate system of the View into that of the display screen. The transformation is computed by composing the View's transformation with all transformations along its superView chain. It is sent by View|displayTransformation when the View is unlocked (see View|unlock)." self isTopView ifTrue: [^transformation] ifFalse: [^superView displayTransformation compose: transformation]! ! !View methodsFor: 'private'! computeInsetDisplayBox "Compute the View's inset display box by intersecting the superView's inset display box with the View's window transformed to display coordinates and then inseting the result by the border width. It is sent by View|insetDisplayBox if the inset display box is nil. The insetDisplayBox points are truncated to prevent sending floating point numbers to QuickDraw which will die." self isTopView ifTrue: [^((self displayTransform: self getWindow) insetBy: borderWidth) truncated] ifFalse: [^(superView insetDisplayBox intersect: (self displayTransform: self getWindow)) truncated insetBy: borderWidth]! ! !View methodsFor: 'private'! getController "Answer the View's controller if one exists. nil indicates that the default controller is to be used." ^controller! ! !View methodsFor: 'private'! getViewport "Answer the Rectangle representing the View's viewport (in the coordinate system of the superclass). If no viewport has been specified, the View's window transformed into the superView's coordinate system is saved and returned. It should be used by methods of View and subclasses (instead of directly referring to the viewport) unless it is known that a viewport actually exists. It should not be used outside of View or subclasses because the viewport is not sharable." viewport == nil ifTrue: [viewport _ (self transform: self getWindow) truncated]. ^viewport! ! !View methodsFor: 'private'! getWindow "Answer the Rectangle that represents the window of this View. If no window has been specified, a default window (see View|defaultWindow) is created, saved, and returned. Should be used by methods of View and subclasses to access the View window instead of directly accessing the field unless it is known that a window actually exists. It is not to be used outside of View (or subclasses) because the window is not sharable. View|window should be used for outside access to the window." window == nil ifTrue: [self setWindow: self defaultWindow]. ^window! ! !View methodsFor: 'private'! isCyclic: aView "Answer true if aView is the same as this View or its superView, false otherwise." self == aView ifTrue: [^true]. self isTopView ifTrue: [^false]. ^superView isCyclic: aView! ! !View methodsFor: 'private'! setTransformation: aTransformation "Set the View's local transformation to aTransformation, unlock the View (see View|unlock), and set the viewport to undefined (this forces it to be recomputed when needed). Should be used instead of setting the transformation directly." transformation _ aTransformation. self unlock. viewport _ nil! ! !View methodsFor: 'private'! setWindow: aWindow "Set the View's window to aWindow and unlock the View (see View|unlock). View|setWindow should be used by methods of View and subclasses to set the View window (rather than directly setting the instance variable) to insure that the View is unlocked." window _ aWindow. viewport _ nil. self unlock! ! !View methodsFor: 'private'! superView: aView "Set the View's superView to aView and unlock the View (see View|unlock). It is sent by View|addSubView: in order to properly set all the links." superView _ aView. self unlock! ! !View methodsFor: 'miscellaneous'! clipRect ^ superView clipRect! ! !View methodsFor: 'miscellaneous'! clipRect: r superView clipRect: r! ! !View methodsFor: 'miscellaneous'! gridSpacing ^ superView gridSpacing! ! !View methodsFor: 'miscellaneous'! nestedViewport "The viewport size used to control scaling of nested user views." ^ (0@0 extent: self viewport extent) insetBy: 16 @ 16! ! !View methodsFor: 'miscellaneous'! printViewSpecOn: strm nested: level "Print window and viewport specs of this and all nested views." strm crtab: level; nextPutAll: self class name. strm crtab: level; nextPutAll: 'window: '; print: self window. strm crtab: level; nextPutAll: 'viewport: '; print: self viewport. strm crtab: level; nextPutAll: 'displayBox: '; print: self displayBox. strm crtab: level; nextPutAll: 'border: '; print: self borderWidth. subViews do: [:v | v printViewSpecOn: strm nested: level+1]! ! !View methodsFor: 'miscellaneous' stamp: 'JMM 10/21/2003 18:12'! stretchFrame: newFrameBlock startingWith: startFrame "Track the outline of a newFrame as long as mouse drags it. Maintain max and min constraints throughout the drag" | frame newFrame click delay | delay _ Delay forMilliseconds: 10. frame _ startFrame origin extent: ((startFrame extent min: self maximumSize) max: self minimumSize). Display border: frame width: 2 rule: Form reverse fillColor: Color gray. click _ false. [click and: [Sensor noButtonPressed]] whileFalse: [delay wait. click _ click | Sensor anyButtonPressed. newFrame _ newFrameBlock value: frame. newFrame _ newFrame topLeft extent: ((newFrame extent min: self maximumSize) max: self minimumSize). newFrame = frame ifFalse: [Display border: frame width: 2 rule: Form reverse fillColor: Color gray. Display border: newFrame width: 2 rule: Form reverse fillColor: Color gray. frame _ newFrame]]. Display border: frame width: 2 rule: Form reverse fillColor: Color gray. ^ frame! ! !View methodsFor: 'morphic compatibility' stamp: 'mdr 1/24/2000 17:27'! setBalloonText: aString "Unfortunately we just ignore this help text because we are not morphic" ! ! Notification subclass: #Warning instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !Warning commentStamp: '<historical>' prior: 0! A Warning is a Notification which by default should be brought to the attention of the user.! !Warning methodsFor: 'exceptionDescription' stamp: 'brp 5/9/2003 12:54'! defaultAction "The user should be notified of the occurrence of an exceptional occurrence and given an option of continuing or aborting the computation. The description of the occurrence should include any text specified as the argument of the #signal: message." Debugger openContext: thisContext label: 'Warning' contents: self messageText, '\\Select Proceed to continue, or close this window to cancel the operation.' withCRs. self resume! ! BitBlt subclass: #WarpBlt instanceVariableNames: 'p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z cellSize sourceRGBmap' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !WarpBlt commentStamp: '<historical>' prior: 0! 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. 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. 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.! !WarpBlt methodsFor: 'setup' stamp: 'jm 4/11/1999 12:00'! cellSize: s cellSize _ s. cellSize = 1 ifTrue: [^ self]. colorMap _ Color colorMapIfNeededFrom: 32 to: destForm depth. ! ! !WarpBlt methodsFor: 'smoothing' stamp: 'di 6/24/97 00:09'! mixPix: pix sourceMap: sourceMap destMap: destMap "Average the pixels in array pix to produce a destination pixel. First average the RGB values either from the pixels directly, or as supplied in the sourceMap. Then return either the resulting RGB value directly, or use it to index the destination color map." | r g b rgb nPix bitsPerColor d | nPix _ pix size. r _ 0. g _ 0. b _ 0. 1 to: nPix do: [:i | "Sum R, G, B values for each pixel" rgb _ sourceForm depth <= 8 ifTrue: [sourceMap at: (pix at: i) + 1] ifFalse: [sourceForm depth = 32 ifTrue: [pix at: i] ifFalse: [self rgbMap: (pix at: i) from: 5 to: 8]]. r _ r + ((rgb bitShift: -16) bitAnd: 16rFF). g _ g + ((rgb bitShift: -8) bitAnd: 16rFF). b _ b + ((rgb bitShift: 0) bitAnd: 16rFF)]. destMap == nil ifTrue: [bitsPerColor _ 3. "just in case eg depth <= 8 and no map" destForm depth = 16 ifTrue: [bitsPerColor _ 5]. destForm depth = 32 ifTrue: [bitsPerColor _ 8]] ifFalse: [destMap size = 512 ifTrue: [bitsPerColor _ 3]. destMap size = 4096 ifTrue: [bitsPerColor _ 4]. destMap size = 32768 ifTrue: [bitsPerColor _ 5]]. d _ bitsPerColor - 8. rgb _ ((r // nPix bitShift: d) bitShift: bitsPerColor*2) + ((g // nPix bitShift: d) bitShift: bitsPerColor) + ((b // nPix bitShift: d) bitShift: 0). destMap == nil ifTrue: [^ rgb] ifFalse: [^ destMap at: rgb+1]! ! !WarpBlt methodsFor: 'smoothing' stamp: 'di 6/24/97 00:08'! rgbMap: sourcePixel from: nBitsIn to: nBitsOut "NOTE: This code is copied verbatim from BitBltSimulation so that it may be removed from the system" "Convert the given pixel value with nBitsIn bits for each color component to a pixel value with nBitsOut bits for each color component. Typical values for nBitsIn/nBitsOut are 3, 5, or 8." | mask d srcPix destPix | self inline: true. (d _ nBitsOut - nBitsIn) > 0 ifTrue: ["Expand to more bits by zero-fill" mask _ (1 << nBitsIn) - 1. "Transfer mask" srcPix _ sourcePixel << d. mask _ mask << d. destPix _ srcPix bitAnd: mask. mask _ mask << nBitsOut. srcPix _ srcPix << d. ^ destPix + (srcPix bitAnd: mask) + (srcPix << d bitAnd: mask << nBitsOut)] ifFalse: ["Compress to fewer bits by truncation" d = 0 ifTrue: [^ sourcePixel]. "no compression" sourcePixel = 0 ifTrue: [^ sourcePixel]. "always map 0 (transparent) to 0" d _ nBitsIn - nBitsOut. mask _ (1 << nBitsOut) - 1. "Transfer mask" srcPix _ sourcePixel >> d. destPix _ srcPix bitAnd: mask. mask _ mask << nBitsOut. srcPix _ srcPix >> d. destPix _ destPix + (srcPix bitAnd: mask) + (srcPix >> d bitAnd: mask << nBitsOut). destPix = 0 ifTrue: [^ 1]. "Dont fall into transparent by truncation" ^ destPix]! ! !WarpBlt methodsFor: 'primitives'! copyQuad: pts toRect: destRect self sourceQuad: pts destRect: destRect. self warpBits! ! !WarpBlt methodsFor: 'primitives'! deltaFrom: x1 to: x2 nSteps: n "Utility routine for computing Warp increments. x1 is starting pixel, x2 is ending pixel; assumes n >= 1" | fixedPtOne | fixedPtOne _ 16384. "1.0 in fixed-pt representation" x2 > x1 ifTrue: [^ x2 - x1 + fixedPtOne // (n+1) + 1] ifFalse: [x2 = x1 ifTrue: [^ 0]. ^ 0 - (x1 - x2 + fixedPtOne // (n+1) + 1)]! ! !WarpBlt methodsFor: 'primitives' stamp: 'jm 5/2/1999 07:09'! sourceForm: srcForm destRect: dstRectangle "Set up a WarpBlt from the entire source Form to the given destination rectangle." | w h | sourceForm _ srcForm. sourceX _ sourceY _ 0. destX _ dstRectangle left. destY _ dstRectangle top. width _ dstRectangle width. height _ dstRectangle height. w _ 16384 * (srcForm width - 1). h _ 16384 * (srcForm height - 1). p1x _ 0. p2x _ 0. p3x _ w. p4x _ w. p1y _ 0. p2y _ h. p3y _ h. p4y _ 0. p1z _ p2z _ p3z _ p4z _ 16384. "z-warp ignored for now" ! ! !WarpBlt methodsFor: 'primitives'! sourceQuad: pts destRect: aRectangle | fixedPt1 | sourceX _ sourceY _ 0. self destRect: aRectangle. fixedPt1 _ (pts at: 1) x isInteger ifTrue: [16384] ifFalse: [16384.0]. p1x _ (pts at: 1) x * fixedPt1. p2x _ (pts at: 2) x * fixedPt1. p3x _ (pts at: 3) x * fixedPt1. p4x _ (pts at: 4) x * fixedPt1. p1y _ (pts at: 1) y * fixedPt1. p2y _ (pts at: 2) y * fixedPt1. p3y _ (pts at: 3) y * fixedPt1. p4y _ (pts at: 4) y * fixedPt1. p1z _ p2z _ p3z _ p4z _ 16384. "z-warp ignored for now" ! ! !WarpBlt methodsFor: 'primitives'! startFrom: x1 to: x2 offset: sumOfDeltas "Utility routine for computing Warp increments." x2 >= x1 ifTrue: [^ x1] ifFalse: [^ x2 - sumOfDeltas]! ! !WarpBlt methodsFor: 'primitives' stamp: 'jm 4/11/1999 13:45'! warpBits "Move those pixels!!" self warpBitsSmoothing: cellSize sourceMap: (sourceForm colormapIfNeededForDepth: 32). ! ! !WarpBlt methodsFor: 'primitives' stamp: 'nk 4/17/2004 19:50'! warpBitsSmoothing: n sourceMap: sourceMap | deltaP12 deltaP43 pA pB deltaPAB sp fixedPtOne picker poker pix nSteps | <primitive: 'primitiveWarpBits' module: 'BitBltPlugin'> "Check for compressed source, destination or halftone forms" ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self warpBitsSmoothing: n sourceMap: sourceMap]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self warpBitsSmoothing: n sourceMap: sourceMap]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self warpBitsSmoothing: n sourceMap: sourceMap]. (width < 1) | (height < 1) ifTrue: [^ self]. fixedPtOne _ 16384. "1.0 in fixed-pt representation" n > 1 ifTrue: [(destForm depth < 16 and: [colorMap == nil]) ifTrue: ["color map is required to smooth non-RGB dest" ^ self primitiveFail]. pix _ Array new: n*n]. nSteps _ height-1 max: 1. deltaP12 _ (self deltaFrom: p1x to: p2x nSteps: nSteps) @ (self deltaFrom: p1y to: p2y nSteps: nSteps). pA _ (self startFrom: p1x to: p2x offset: nSteps*deltaP12 x) @ (self startFrom: p1y to: p2y offset: nSteps*deltaP12 y). deltaP43 _ (self deltaFrom: p4x to: p3x nSteps: nSteps) @ (self deltaFrom: p4y to: p3y nSteps: nSteps). pB _ (self startFrom: p4x to: p3x offset: nSteps*deltaP43 x) @ (self startFrom: p4y to: p3y offset: nSteps*deltaP43 y). picker _ BitBlt current bitPeekerFromForm: sourceForm. poker _ BitBlt current bitPokerToForm: destForm. poker clipRect: self clipRect. nSteps _ width-1 max: 1. destY to: destY+height-1 do: [:y | deltaPAB _ (self deltaFrom: pA x to: pB x nSteps: nSteps) @ (self deltaFrom: pA y to: pB y nSteps: nSteps). sp _ (self startFrom: pA x to: pB x offset: nSteps*deltaPAB x) @ (self startFrom: pA y to: pB y offset: nSteps*deltaPAB x). destX to: destX+width-1 do: [:x | n = 1 ifTrue: [poker pixelAt: x@y put: (picker pixelAt: sp // fixedPtOne asPoint)] ifFalse: [0 to: n-1 do: [:dx | 0 to: n-1 do: [:dy | pix at: dx*n+dy+1 put: (picker pixelAt: sp + (deltaPAB*dx//n) + (deltaP12*dy//n) // fixedPtOne asPoint)]]. poker pixelAt: x@y put: (self mixPix: pix sourceMap: sourceMap destMap: colorMap)]. sp _ sp + deltaPAB]. pA _ pA + deltaP12. pB _ pB + deltaP43]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WarpBlt class instanceVariableNames: ''! !WarpBlt class methodsFor: 'initialization'! toForm: destinationForm "Default cell size is 1 (no pixel smoothing)" ^ (super toForm: destinationForm) cellSize: 1! ! !WarpBlt class methodsFor: 'examples'! test3 "Display restoreAfter: [WarpBlt test3]" "The Squeak Release Mandala - 9/23/96 di" "Move the mouse near the center of the square. Up and down affects shrink/grow Left and right affect rotation angle" | warp pts p0 p box map d t | box _ 100@100 extent: 300@300. Display border: (box expandBy: 2) width: 2. "Make a color map that steps through the color space" map _ (Display depth > 8 ifTrue: ["RGB is a bit messy..." d _ Display depth = 16 ifTrue: [5] ifFalse: [8]. (1 to: 512) collect: [:i | t _ i bitAnd: 511. ((t bitAnd: 16r7) bitShift: d-3) + ((t bitAnd: 16r38) bitShift: d-3*2) + ((t bitAnd: 16r1C0) bitShift: d-3*3)]] ifFalse: ["otherwise simple" 1 to: (1 bitShift: Display depth)]) as: Bitmap. warp _ (WarpBlt toForm: Display) clipRect: box; sourceForm: Display; colorMap: map; combinationRule: Form over. p0 _ box center. [Sensor anyButtonPressed] whileFalse: [p _ Sensor cursorPoint. pts _ (box insetBy: p y - p0 y) innerCorners collect: [:pt | pt rotateBy: p x - p0 x / 50.0 about: p0]. warp copyQuad: pts toRect: box]! ! !WarpBlt class methodsFor: 'instance creation' stamp: 'ar 5/28/2000 12:00'! current "Return the class currently to be used for WarpBlt" ^Display defaultWarpBltClass! ! Array variableSubclass: #WeakActionSequence instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !WeakActionSequence methodsFor: 'converting' stamp: 'rw 4/27/2002 07:44'! asActionSequence ^self! ! !WeakActionSequence methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'! asActionSequenceTrappingErrors ^WeakActionSequenceTrappingErrors withAll: self! ! !WeakActionSequence methodsFor: 'converting' stamp: 'nk 7/21/2003 15:16'! asMinimalRepresentation | valid | valid := self select: [:e | e isValid ]. valid size = 0 ifTrue: [^nil]. valid size = 1 ifTrue: [^valid first]. ^valid! ! !WeakActionSequence methodsFor: 'evaluating' stamp: 'nk 7/21/2003 15:17'! value "Answer the result of evaluating the elements of the receiver. Actually, return just the last result." | answer | self do: [:each | each isValid ifTrue: [answer := each value]]. ^answer! ! !WeakActionSequence methodsFor: 'evaluating' stamp: 'nk 7/21/2003 15:17'! valueWithArguments: anArray "Return the last result" | answer | self do: [:each | each isValid ifTrue: [answer := each valueWithArguments: anArray]]. ^answer! ! !WeakActionSequence methodsFor: 'printing' stamp: 'rw 4/27/2002 07:46'! printOn: aStream self size < 2 ifTrue: [^super printOn: aStream]. aStream nextPutAll: '#('. self do: [:each | each printOn: aStream] separatedBy: [aStream cr]. aStream nextPut: $)! ! WeakActionSequence variableSubclass: #WeakActionSequenceTrappingErrors instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Change Notification'! !WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'rw 8/6/2003 12:09'! value "Do the same as my parent, but make sure that all actions that do not give errors are evaluated before resignaling the ones that gave errors (giving the chance to clients to handle them)." ^self valueStartingFrom: 1! ! !WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'rw 8/6/2003 12:12'! valueStartingFrom: startIndex "Do the same as my parent, but make sure that all actions that do not give errors are evaluated before resignaling the ones that gave errors (giving the chance to clients to handle them)." "Note: I currently trap Halt,Exception so that I am sure to get a Halt event in case of a Halt. This is being fixed in the exception system - when the fix is done it will be enough to capture only Exception." | each answer | startIndex to: self size do: [:index | each := self at: index. each isReceiverOrAnyArgumentGarbage ifFalse: [ [answer _ each value] on: Halt, Exception do: [:exc | self valueStartingFrom: index + 1. exc pass]]]. ^ answer! ! !WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'rw 8/6/2003 12:07'! valueWithArguments: anArray "Do the same as my parent, but make sure that all actions that do not give errors are evaluated before resignaling the ones that gave errors (giving the chance to clients to handle them)." ^self valueWithArguments: anArray startingFrom: 1! ! !WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'rw 8/6/2003 12:11'! valueWithArguments: anArray startingFrom: startIndex "Do the same as my parent, but make sure that all actions that do not give errors are evaluated before resignaling the ones that gave errors (giving the chance to clients to handle them)." "Note: I currently trap Halt,Exception so that I am sure to get a Halt event in case of a Halt. This is being fixed in the exception system - when the fix is done it will be enough to capture only Exception." | each answer | startIndex to: self size do: [:index | each := self at: index. each isReceiverOrAnyArgumentGarbage ifFalse: [ [answer _ each valueWithArguments: anArray] on: Halt, Exception do: [:exc | self valueWithArguments: anArray startingFrom: index + 1. exc pass]]]. ^ answer! ! !WeakActionSequenceTrappingErrors methodsFor: 'converting' stamp: 'rw 7/20/2003 16:03'! asActionSequenceTrappingErrors ^self! ! Array weakSubclass: #WeakArray instanceVariableNames: '' classVariableNames: 'FinalizationDependents FinalizationLock FinalizationProcess FinalizationSemaphore IsFinalizationSupported' poolDictionaries: '' category: 'Collections-Weak'! !WeakArray commentStamp: '<historical>' prior: 0! WeakArray is an array which holds only weakly on its elements. This means whenever an object is only referenced by instances of WeakArray it will be garbage collected.! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WeakArray class instanceVariableNames: ''! !WeakArray class methodsFor: 'accessing' stamp: 'ar 10/8/1998 11:17'! addWeakDependent: anObject | finished index weakDependent | self isFinalizationSupported ifFalse:[^self]. FinalizationLock critical:[ finished := false. index := 0. [index := index + 1. finished not and:[index <= FinalizationDependents size]] whileTrue:[ weakDependent := FinalizationDependents at: index. weakDependent isNil ifTrue:[ FinalizationDependents at: index put: anObject. finished := true. ]. ]. finished ifFalse:[ "Grow linearly" FinalizationDependents := FinalizationDependents, (WeakArray new: 10). FinalizationDependents at: index put: anObject. ]. ] ifError:[:msg :rcvr| rcvr error: msg].! ! !WeakArray class methodsFor: 'accessing' stamp: 'ar 10/7/1998 15:30'! isFinalizationSupported "Check if this VM supports the finalization mechanism" | tempObject | IsFinalizationSupported ifNotNil:[^IsFinalizationSupported]. tempObject _ WeakArray new: 1. "Check if the class format 4 is correctly understood by the VM. If the weak class support is not installed then the VM will report any weak class as containing 32bit words - not pointers" (tempObject at: 1) = nil ifFalse:[^IsFinalizationSupported _false]. "Check if objects are correctly freed" self pvtCreateTemporaryObjectIn: tempObject. Smalltalk garbageCollect. ^IsFinalizationSupported _ (tempObject at: 1) == nil! ! !WeakArray class methodsFor: 'accessing' stamp: 'nk 10/28/2000 20:26'! runningFinalizationProcess "Answer the FinalizationProcess I am running, if any" ^FinalizationProcess! ! !WeakArray class methodsFor: 'class initialization' stamp: 'nk 6/21/2004 10:22'! initialize "WeakArray initialize" "Do we need to initialize specialObjectsArray?" Smalltalk specialObjectsArray size < 42 ifTrue:[Smalltalk recreateSpecialObjectsArray]. Smalltalk addToStartUpList: self. self restartFinalizationProcess.! ! !WeakArray class methodsFor: 'system startup' stamp: 'nk 6/21/2004 09:22'! startUp: resuming resuming ifFalse: [ ^self ]. self restartFinalizationProcess.! ! !WeakArray class methodsFor: 'private' stamp: 'di 5/21/2001 21:49'! finalizationProcess [true] whileTrue: [FinalizationSemaphore wait. FinalizationLock critical: [FinalizationDependents do: [:weakDependent | weakDependent ifNotNil: [weakDependent finalizeValues. "***Following statement is required to keep weakDependent from holding onto its value as garbage.***" weakDependent _ nil]]] ifError: [:msg :rcvr | rcvr error: msg]. ]. ! ! !WeakArray class methodsFor: 'private' stamp: 'ar 10/7/1998 15:24'! pvtCreateTemporaryObjectIn: tempObject "We have to create the temporary object in a separate stack frame" tempObject at: 1 put: Object new! ! !WeakArray class methodsFor: 'private' stamp: 'nk 6/21/2004 10:22'! restartFinalizationProcess "kill any old process, just in case" FinalizationProcess ifNotNil: [FinalizationProcess terminate. FinalizationProcess := nil]. "Check if Finalization is supported by this VM" IsFinalizationSupported := nil. self isFinalizationSupported ifFalse: [^ self]. FinalizationSemaphore := Smalltalk specialObjectsArray at: 42. FinalizationDependents ifNil: [FinalizationDependents := WeakArray new: 10]. FinalizationLock := Semaphore forMutualExclusion. FinalizationProcess := [self finalizationProcess] forkAt: Processor userInterruptPriority! ! WeakKeyDictionary subclass: #WeakIdentityKeyDictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Weak'! !WeakIdentityKeyDictionary commentStamp: '<historical>' prior: 0! This class represents an identity dictionary with weak keys.! !WeakIdentityKeyDictionary methodsFor: 'private' stamp: 'ar 7/1/2003 15:15'! scanFor: anObject "ar 10/21/2000: The method has been copied to this location to indicate that whenever #scanFor: changes #scanForNil: must be changed in the receiver as well." "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish hash | finish _ array size. finish > 4096 ifTrue: [hash _ anObject identityHash * (finish // 4096)] ifFalse: [hash _ anObject identityHash]. start _ (hash \\ array size) + 1. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element key == anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element key == anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !WeakIdentityKeyDictionary methodsFor: 'private' stamp: 'ar 7/1/2003 15:15'! scanForNil: anObject "Private. Scan the key array for the first slot containing nil (indicating an empty slot). Answer the index of that slot." | start finish hash | finish _ array size. finish > 4096 ifTrue: [hash _ anObject identityHash * (finish // 4096)] ifFalse: [hash _ anObject identityHash]. start _ (hash \\ array size) + 1. "Search from (hash mod size) to the end." start to: finish do: [:index | (array at: index) == nil ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | (array at: index) == nil ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! Association subclass: #WeakKeyAssociation instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Support'! !WeakKeyAssociation commentStamp: '<historical>' prior: 0! I am an association holding only weakly on my key.! !WeakKeyAssociation methodsFor: 'comparing' stamp: 'ar 3/21/98 15:45'! < aLookupKey "Refer to the comment in Magnitude|<." ^self key < aLookupKey key! ! !WeakKeyAssociation methodsFor: 'comparing' stamp: 'ar 3/21/98 15:46'! = aLookupKey self species = aLookupKey species ifTrue: [^self key = aLookupKey key] ifFalse: [^false]! ! !WeakKeyAssociation methodsFor: 'comparing' stamp: 'ar 3/21/98 15:46'! hash "Hash is reimplemented because = is implemented." ^self key hash! ! !WeakKeyAssociation methodsFor: 'comparing' stamp: 'ar 3/21/98 15:46'! hashMappedBy: map "Answer what my hash would be if oops changed according to map." ^self key hashMappedBy: map! ! !WeakKeyAssociation methodsFor: 'comparing' stamp: 'ar 3/21/98 15:47'! identityHashMappedBy: map "Answer what my hash would be if oops changed according to map." ^ self key identityHashMappedBy: map! ! !WeakKeyAssociation methodsFor: 'printing' stamp: 'ar 3/21/98 15:53'! printOn: aStream self key printOn: aStream. aStream nextPutAll: '->'. self value printOn: aStream! ! !WeakKeyAssociation methodsFor: 'printing' stamp: 'ar 3/21/98 15:53'! storeOn: aStream aStream nextPut: $(; nextPutAll: self class name; nextPutAll:' key: '. self key storeOn: aStream. aStream nextPutAll: ' value: '. self value storeOn: aStream. aStream nextPut: $)! ! !WeakKeyAssociation methodsFor: 'accessing' stamp: 'ar 3/21/98 15:54'! key ^key isNil ifTrue:[nil] ifFalse:[key at: 1]! ! !WeakKeyAssociation methodsFor: 'accessing' stamp: 'ar 3/21/98 15:45'! key: aKey key := WeakArray with: aKey! ! !WeakKeyAssociation methodsFor: 'accessing' stamp: 'raok 11/29/2002 14:49'! key: aKey value: anObject key := WeakArray with: aKey. value := anObject.! ! Dictionary subclass: #WeakKeyDictionary instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Weak'! !WeakKeyDictionary commentStamp: '<historical>' prior: 0! I am a dictionary holding only weakly on my keys. This is a bit dangerous since at any time my keys can go away. Clients are responsible to register my instances by WeakArray such that the appropriate actions can be taken upon loss of any keys. See WeakRegistry for an example of use. ! !WeakKeyDictionary methodsFor: 'finalization' stamp: 'ar 10/21/2000 20:00'! finalizeValues "remove all nil keys and rehash the receiver afterwards" | assoc | 1 to: array size do:[:i| assoc _ array at: i. (assoc notNil and:[assoc key == nil]) ifTrue:[array at: i put: nil]. ]. self rehash.! ! !WeakKeyDictionary methodsFor: 'finalization' stamp: 'ar 10/21/2000 20:01'! finalizeValues: finiObjects "Remove all associations with key == nil and value is in finiObjects. This method is folded with #rehash for efficiency." | oldArray assoc newIndex | oldArray _ array. array _ Array new: oldArray size. tally _ 0. 1 to: array size do:[:i| assoc _ oldArray at: i. assoc ifNotNil:[ (assoc key == nil and:[finiObjects includes: assoc value]) ifFalse:[ newIndex _ self scanForNil: assoc key. self atNewIndex: newIndex put: assoc]. ]. ].! ! !WeakKeyDictionary methodsFor: 'accessing' stamp: 'ar 3/21/98 16:02'! at: key put: anObject "Set the value at key to be anObject. If key is not found, create a new entry for key and set is value to anObject. Answer anObject." | index element | key isNil ifTrue:[^anObject]. index _ self findElementOrNil: key. element _ array at: index. element == nil ifTrue: [self atNewIndex: index put: (WeakKeyAssociation key: key value: anObject)] ifFalse: [element value: anObject]. ^ anObject! ! !WeakKeyDictionary methodsFor: 'accessing' stamp: 'ar 2/11/2001 02:21'! keysDo: aBlock "Evaluate aBlock for each of the receiver's keys." self associationsDo: [:association | association key ifNotNil:[aBlock value: association key]].! ! !WeakKeyDictionary methodsFor: 'private' stamp: 'ar 10/21/2000 19:58'! fixCollisionsFrom: oldIndex "The element at index has been removed and replaced by nil." self rehash. "Do it the hard way - we may have any number of nil keys and #rehash deals with them"! ! !WeakKeyDictionary methodsFor: 'private' stamp: 'ar 10/21/2000 19:56'! rehash "Rehash the receiver. Reimplemented to allow for multiple nil keys" | oldArray assoc newIndex | oldArray _ array. array _ Array new: oldArray size. tally _ 0. 1 to: array size do:[:i| assoc _ oldArray at: i. assoc ifNotNil:[ newIndex _ self scanForNil: assoc key. self atNewIndex: newIndex put: assoc. ]. ].! ! !WeakKeyDictionary methodsFor: 'private' stamp: 'ar 10/21/2000 19:46'! scanFor: anObject "ar 10/21/2000: The method has been copied to this location to indicate that whenever #scanFor: changes #scanForNil: must be changed in the receiver as well." "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == nil or: [element key = anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [element key = anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !WeakKeyDictionary methodsFor: 'private' stamp: 'ar 10/21/2000 19:46'! scanForNil: anObject "Private. Scan the key array for the first slot containing nil (indicating an empty slot). Answer the index of that slot." | start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | (array at: index) == nil ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | (array at: index) == nil ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !WeakKeyDictionary methodsFor: 'adding' stamp: 'ar 3/21/98 16:00'! add: anAssociation self at: anAssociation key put: anAssociation value. ^ anAssociation! ! Object weakSubclass: #WeakMessageSend instanceVariableNames: 'selector shouldBeNil arguments' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Objects'! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 09:54'! arguments ^arguments ifNil: [ Array new ] ! ! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 09:38'! arguments: anArray arguments _ WeakArray withAll: anArray. "no reason this should be a WeakArray" shouldBeNil _ Array withAll: (anArray collect: [ :ea | ea isNil ]). ! ! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 07:54'! receiver ^self at: 1 ! ! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 07:54'! receiver: anObject self at: 1 put: anObject ! ! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 07:54'! selector ^selector ! ! !WeakMessageSend methodsFor: 'accessing' stamp: 'nk 4/25/2002 07:55'! selector: aSymbol selector _ aSymbol ! ! !WeakMessageSend methodsFor: 'comparing' stamp: 'nk 4/25/2002 08:05'! = anObject "Compare equal to equivalent MessageSend" ^ anObject isMessageSend and: [self receiver == anObject receiver and: [selector == anObject selector and: [(Array withAll: arguments) = (Array withAll: anObject arguments)]]] ! ! !WeakMessageSend methodsFor: 'comparing' stamp: 'nk 4/25/2002 09:31'! hash "work like MessageSend>>hash" ^self receiver hash bitXor: selector hash ! ! !WeakMessageSend methodsFor: 'converting' stamp: 'rww 10/20/2002 19:56'! asMinimalRepresentation self isReceiverOrAnyArgumentGarbage ifTrue: [^nil] ifFalse:[^self].! ! !WeakMessageSend methodsFor: 'evaluating' stamp: 'nk 12/8/2002 12:15'! value ^ arguments isNil ifTrue: [self ensureReceiver ifTrue: [self receiver perform: selector] ifFalse: []] ifFalse: [self ensureReceiverAndArguments ifTrue: [self receiver perform: selector withArguments: (Array withAll: arguments)] ifFalse: []]! ! !WeakMessageSend methodsFor: 'evaluating' stamp: 'nk 12/8/2002 12:15'! valueWithArguments: anArray self ensureReceiverAndArguments ifFalse: [ ^nil ]. ^ self receiver perform: selector withArguments: (self collectArguments: anArray)! ! !WeakMessageSend methodsFor: 'printing' stamp: 'nk 4/25/2002 09:36'! printOn: aStream aStream nextPutAll: self class name; nextPut: $(. selector printOn: aStream. aStream nextPutAll: ' -> '. self receiver printOn: aStream. aStream nextPut: $) ! ! !WeakMessageSend methodsFor: 'testing' stamp: 'nk 4/25/2002 08:04'! isMessageSend ^true ! ! !WeakMessageSend methodsFor: 'testing' stamp: 'nk 8/24/2003 01:12'! isValid ^self isReceiverOrAnyArgumentGarbage not ! ! !WeakMessageSend methodsFor: 'private' stamp: 'nk 4/25/2002 09:49'! collectArguments: anArgArray "Private" | staticArgs | staticArgs := self arguments. ^(anArgArray size = staticArgs size) ifTrue: [anArgArray] ifFalse: [(staticArgs isEmpty ifTrue: [ staticArgs := Array new: selector numArgs] ifFalse: [staticArgs copy] ) replaceFrom: 1 to: (anArgArray size min: staticArgs size) with: anArgArray startingAt: 1] ! ! !WeakMessageSend methodsFor: 'private' stamp: 'nk 12/8/2002 12:13'! ensureReceiver "Return true if my receiver hasn't gone away" ^self receiver notNil ! ! !WeakMessageSend methodsFor: 'private' stamp: 'nk 12/8/2002 12:13'! ensureReceiverAndArguments "Return true if my receiver hasn't gone away" self receiver ifNil: [ ^false ]. "Make sure that my arguments haven't gone away" arguments ifNotNil: [ arguments with: shouldBeNil do: [ :arg :flag | arg ifNil: [ flag ifFalse: [ ^false ]] ] ]. ^true ! ! !WeakMessageSend methodsFor: 'private' stamp: 'rw 4/27/2002 07:33'! isAnyArgumentGarbage "Make sure that my arguments haven't gone away" arguments ifNotNil: [ arguments with: shouldBeNil do: [ :arg :flag | (flag not and: [arg isNil]) ifTrue: [^true] ] ]. ^false ! ! !WeakMessageSend methodsFor: 'private' stamp: 'rw 4/27/2002 07:31'! isReceiverGarbage "Make sure that my receiver hasn't gone away" ^self receiver isNil ! ! !WeakMessageSend methodsFor: 'private' stamp: 'rw 4/27/2002 07:34'! isReceiverOrAnyArgumentGarbage "Make sure that my receiver hasn't gone away" ^self isReceiverGarbage or: [self isAnyArgumentGarbage] ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WeakMessageSend class instanceVariableNames: ''! !WeakMessageSend class methodsFor: 'instance creation' stamp: 'nk 4/25/2002 10:00'! new ^self new: 1 ! ! !WeakMessageSend class methodsFor: 'instance creation' stamp: 'nk 4/25/2002 09:37'! receiver: anObject selector: aSymbol ^ self receiver: anObject selector: aSymbol arguments: #() ! ! !WeakMessageSend class methodsFor: 'instance creation' stamp: 'nk 4/25/2002 09:37'! receiver: anObject selector: aSymbol argument: aParameter ^ self receiver: anObject selector: aSymbol arguments: (Array with: aParameter) ! ! !WeakMessageSend class methodsFor: 'instance creation' stamp: 'nk 4/25/2002 09:37'! receiver: anObject selector: aSymbol arguments: anArray ^ self new receiver: anObject; selector: aSymbol; arguments: anArray ! ! Collection subclass: #WeakRegistry instanceVariableNames: 'valueDictionary accessLock' classVariableNames: 'Default' poolDictionaries: '' category: 'Collections-Weak'! !WeakRegistry commentStamp: '<historical>' prior: 0! I am a registry for objects needing finalization. When an object is added the object as well as its executor is stored. When the object is garbage collected, the executor can take the appropriate action for any resources associated with the object. See also: Object executor Object actAsExecutor Object finalize ! !WeakRegistry methodsFor: 'finalization' stamp: 'ar 10/22/2000 20:24'! finalizeValues "Some of our elements may have gone away. Look for those and activate the associated executors." | finiObjects | finiObjects := nil. "First collect the objects." self protected:[ valueDictionary associationsDo:[:assoc| assoc key isNil ifTrue:[ finiObjects isNil ifTrue:[finiObjects := OrderedCollection with: assoc value] ifFalse:[finiObjects add: assoc value]] ]. finiObjects isNil ifFalse:[valueDictionary finalizeValues: finiObjects asArray]. ]. "Then do the finalization" finiObjects isNil ifTrue:[^self]. finiObjects do:[:each| each finalize]. ! ! !WeakRegistry methodsFor: 'adding' stamp: 'ar 3/21/98 16:33'! add: anObject "Add anObject to the receiver. Store the object as well as the associated executor." | executor | executor := anObject executor. self protected:[ valueDictionary at: anObject put: executor. ]. ^anObject! ! !WeakRegistry methodsFor: 'adding' stamp: 'ar 5/19/2003 20:08'! add: anObject executor: anExecutor "Add anObject to the receiver. Store the object as well as the associated executor." self protected:[ valueDictionary at: anObject put: anExecutor. ]. ^anObject! ! !WeakRegistry methodsFor: 'accessing' stamp: 'ar 12/12/2001 16:00'! keys ^self protected:[ Array streamContents:[:s| valueDictionary keysDo:[:key| s nextPut: key]]].! ! !WeakRegistry methodsFor: 'accessing' stamp: 'sma 5/12/2000 11:40'! size ^ self protected: [valueDictionary size]! ! !WeakRegistry methodsFor: 'accessing' stamp: 'ar 3/20/98 19:31'! species ^Set! ! !WeakRegistry methodsFor: 'initialize' stamp: 'ar 3/21/98 16:08'! initialize: n valueDictionary := WeakKeyDictionary new: n. accessLock := Semaphore forMutualExclusion.! ! !WeakRegistry methodsFor: 'private' stamp: 'ar 10/8/1998 11:18'! protected: aBlock "Execute aBlock protected by the accessLock" ^accessLock isNil ifTrue:[aBlock value] ifFalse:[accessLock critical: aBlock ifError:[:msg :rcvr| rcvr error: msg]]! ! !WeakRegistry methodsFor: 'enumerating' stamp: 'ar 3/21/98 18:36'! do: aBlock ^self protected:[ valueDictionary keysDo: aBlock. ]. ! ! !WeakRegistry methodsFor: 'removing' stamp: 'ar 3/21/98 21:12'! remove: oldObject ifAbsent: exceptionBlock "Remove oldObject as one of the receiver's elements." | removedObject | oldObject isNil ifTrue:[^oldObject]. self protected:[ removedObject := valueDictionary removeKey: oldObject ifAbsent:[nil]. ]. ^removedObject isNil ifTrue:[exceptionBlock value] ifFalse:[removedObject]. ! ! !WeakRegistry methodsFor: 'printing' stamp: 'tk 12/5/2001 09:42'! printElementsOn: aStream aStream nextPut: $(. accessLock ifNil: [self do: [:element | aStream print: element; space]] ifNotNil: [aStream nextPutAll: '<this WeakRegistry is locked>; space']. self isEmpty ifFalse: [aStream skip: -1]. aStream nextPut: $)! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WeakRegistry class instanceVariableNames: ''! !WeakRegistry class methodsFor: 'instance creation' stamp: 'ar 3/21/98 15:32'! new ^self new: 5! ! !WeakRegistry class methodsFor: 'instance creation' stamp: 'ar 3/21/98 15:33'! new: n | registry | registry := super new initialize: n. WeakArray addWeakDependent: registry. ^registry! ! !WeakRegistry class methodsFor: 'accessing' stamp: 'ar 5/19/2003 20:10'! default ^Default ifNil:[Default := self new]! ! Set subclass: #WeakSet instanceVariableNames: 'flag' classVariableNames: '' poolDictionaries: '' category: 'Collections-Weak'! !WeakSet methodsFor: 'public' stamp: 'SqR 8/30/2000 13:15'! add: newObject "Include newObject as one of the receiver's elements, but only if not already present. Answer newObject" | index | newObject ifNil: [self error: 'Sets cannot meaningfully contain nil as an element']. index _ self findElementOrNil: newObject. ((array at: index) == flag or: [(array at: index) isNil]) ifTrue: [self atNewIndex: index put: newObject]. ^newObject! ! !WeakSet methodsFor: 'public' stamp: 'nk 3/11/2002 20:35'! collect: aBlock | each newSet | newSet _ self species new: self size. tally = 0 ifTrue: [^newSet ]. 1 to: array size do: [:index | ((each _ array at: index) == nil or: [each == flag]) ifFalse: [newSet add: (aBlock value: each)] ]. ^newSet! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/23/2000 15:46'! do: aBlock | each | tally = 0 ifTrue: [^self]. 1 to: array size do: [:index | ((each _ array at: index) == nil or: [each == flag]) ifFalse: [aBlock value: each] ]! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/30/2000 13:13'! do: aBlock after: anElement | each startIndex | tally = 0 ifTrue: [^self]. startIndex _ anElement ifNil: [1] ifNotNil: [self findElementOrNil: anElement]. startIndex + 1 to: array size do: [:index | ((each _ array at: index) == nil or: [each == flag]) ifFalse: [aBlock value: each] ]! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/30/2000 13:15'! includes: anObject ^(array at: (self findElementOrNil: anObject)) ~~ flag! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/23/2000 16:02'! like: anObject "Answer an object in the receiver that is equal to anObject, nil if no such object is found. Relies heavily on hash properties" | index element | ^(index _ self scanFor: anObject) = 0 ifFalse: [(element _ array at: index) == flag ifFalse: [element]]! ! !WeakSet methodsFor: 'public' stamp: 'di 2/3/2001 16:46'! printElementsOn: aStream | oldPos | aStream nextPut: $(. oldPos _ aStream position. self do: [:element | aStream print: element; space]. aStream position > oldPos ifTrue: [aStream skip: -1 "remove the extra space"]. aStream nextPut: $)! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/23/2000 15:08'! remove: oldObject ifAbsent: aBlock | index | index _ self findElementOrNil: oldObject. (array at: index) == flag ifTrue: [ ^ aBlock value ]. array at: index put: flag. tally _ tally - 1. self fixCollisionsFrom: index. ^oldObject! ! !WeakSet methodsFor: 'public' stamp: 'SqR 8/23/2000 15:12'! size "Careful!! Answer the maximum amount of elements in the receiver, not the exact amount" ^tally! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 14:30'! fixCollisionsFrom: index "The element at index has been removed and replaced by nil. This method moves forward from there, relocating any entries that had been placed below due to collisions with this one" | length oldIndex newIndex element | oldIndex _ index. length _ array size. [oldIndex = length ifTrue: [oldIndex _ 1] ifFalse: [oldIndex _ oldIndex + 1]. (element _ self keyAt: oldIndex) == flag] whileFalse: [newIndex _ self findElementOrNil: element. oldIndex = newIndex ifFalse: [self swap: oldIndex with: newIndex]]! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 15:43'! grow "Grow the elements array and reinsert the old elements" self growTo: array size + self growSize! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 15:43'! growTo: anInteger "Grow the elements array and reinsert the old elements" | oldElements | oldElements _ array. array _ WeakArray new: anInteger. array atAllPut: flag. tally _ 0. oldElements do: [:each | (each == flag or: [each == nil]) ifFalse: [self noCheckAdd: each]]! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 14:38'! init: n "Initialize array to an array size of n" flag _ Object new. array _ WeakArray new: n. array atAllPut: flag. tally _ 0! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 15:43'! rehash self growTo: array size! ! !WeakSet methodsFor: 'private' stamp: 'SqR 8/23/2000 14:35'! scanFor: anObject "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements" | element start finish | start _ (anObject hash \\ array size) + 1. finish _ array size. "Search from (hash mod size) to the end." start to: finish do: [:index | ((element _ array at: index) == flag or: [element = anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == flag or: [element = anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! Timespan subclass: #Week instanceVariableNames: '' classVariableNames: 'StartDay' poolDictionaries: 'ChronologyConstants' category: 'Kernel-Chronology'! !Week commentStamp: 'brp 5/13/2003 09:48' prior: 0! I represent a week.! !Week methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:37'! printOn: aStream aStream nextPutAll: 'a Week starting: '. self start printOn: aStream. ! ! !Week methodsFor: 'deprecated' stamp: 'brp 8/5/2003 22:17'! do: aBlock self deprecated: 'Use #datesDo:'. self datesDo: aBlock! ! !Week methodsFor: 'deprecated' stamp: 'brp 8/6/2003 18:39'! index self deprecated: 'obsolete'. ^ self indexInMonth: self asMonth ! ! !Week methodsFor: 'deprecated' stamp: 'brp 8/6/2003 18:42'! indexInMonth: aMonth "1=first week, 2=second week, etc." self deprecated: 'obsolete'. ^ (Date dayOfWeek: aMonth dayOfWeekName) + self dayOfMonth - 2 // 7 + 1 ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Week class instanceVariableNames: ''! !Week class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:34'! indexOfDay: aSymbol ^ DayNames indexOf: aSymbol ! ! !Week class methodsFor: 'squeak protocol' stamp: 'brp` 8/24/2003 19:38'! startDay ^ StartDay ifNil: [ StartDay _ DayNames first ]! ! !Week class methodsFor: 'squeak protocol' stamp: 'jf 4/23/2004 14:51'! starting: aDateAndTime duration: aDuration "Override - the duration is always one week. Week will start from the Week class>>startDay" | midnight delta adjusted | midnight _ aDateAndTime asDateAndTime midnight. delta _ ((midnight dayOfWeek + 7 - (DayNames indexOf: self startDay)) rem: 7) abs. adjusted _ midnight - (Duration days: delta hours: 0 minutes: 0 seconds: 0). ^ super starting: adjusted duration: (Duration weeks: 1).! ! !Week class methodsFor: 'smalltalk-80' stamp: 'brp 5/13/2003 09:34'! nameOfDay: anIndex ^ DayNames at: anIndex ! ! Object subclass: #WindowingTransformation instanceVariableNames: 'scale translation' classVariableNames: '' poolDictionaries: '' category: 'ST80-Framework'! !WindowingTransformation commentStamp: '<historical>' prior: 0! 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.! !WindowingTransformation methodsFor: 'scrolling'! scrollBy: aPoint "Answer a WindowingTransformation with the same scale as the receiver and with a translation of the current translation plus aPoint scaled by the current scale. It is used when the translation is known in source coordinates, rather than scaled source coordinates (see WindowingTransformation|translateBy:). An example is that of scrolling objects with respect to a stationary window in the source coordinate system. If no scaling is in effect (scale = nil), then WindowingTransformation|translateBy: and WindowingTransformation|scrollBy: are equivalent." | newTranslation | scale == nil ifTrue: [newTranslation _ aPoint] ifFalse: [newTranslation _ scale * aPoint]. ^self translateBy: newTranslation! ! !WindowingTransformation methodsFor: 'transforming'! align: point1 with: point2 "Answer a WindowingTransformation with the same scale as the receiver and with a translation of (aPoint2 - aPoint1). It is normally used when the source and destination coordinate systems are scaled the same (that is, there is no scaling between them), and is then a convenient way of specifying a translation, given two points that are intended to coincide." ^self translateBy: point2 - point1! ! !WindowingTransformation methodsFor: 'transforming'! noScale "Answer true if the identity scale is in effect; answer false, otherwise." ^scale == nil! ! !WindowingTransformation methodsFor: 'transforming'! scale "Answer a copy of the point that represents the current scale of the receiver." scale == nil ifTrue: [^1.0 @ 1.0] ifFalse: [^scale copy]! ! !WindowingTransformation methodsFor: 'transforming'! scaleBy: aScale "Answer a WindowingTransformation with the scale and translation of the receiver both scaled by aScale." | checkedScale newScale newTranslation | aScale == nil ifTrue: [newScale _ scale. newTranslation _ translation] ifFalse: [checkedScale _ self checkScale: aScale. scale == nil ifTrue: [newScale _ checkedScale] ifFalse: [newScale _ scale * checkedScale]. newTranslation _ checkedScale * translation]. ^WindowingTransformation scale: newScale translation: newTranslation! ! !WindowingTransformation methodsFor: 'transforming'! translateBy: aPoint "Answer a WindowingTransformation with the same scale as the receiver and with a translation of the current translation plus aPoint. It is used when the translation is known in scaled source coordinates, rather than source coordinates (see WindowingTransformation|scrollBy:). If no scaling is in effect (scale = nil), then WindowingTransformation|translateBy: and WindowingTransformation|scrollBy: are equivalent." ^WindowingTransformation scale: scale translation: translation + aPoint! ! !WindowingTransformation methodsFor: 'transforming'! translation "Answer a copy of the receiver's translation." ^translation copy! ! !WindowingTransformation methodsFor: 'applying transform'! applyInverseTo: anObject "Apply the inverse of the receiver to anObject and answer the result. Used to map some object in destination coordinates to one in source coordinates." | transformedObject | transformedObject _ anObject translateBy: translation x negated @ translation y negated. scale == nil ifFalse: [transformedObject _ transformedObject scaleBy: 1.0 / scale x @ (1.0 / scale y)]. ^transformedObject! ! !WindowingTransformation methodsFor: 'applying transform'! applyTo: anObject "Apply the receiver to anObject and answer the result. Used to map some object in source coordinates to one in destination coordinates." | transformedObject | scale == nil ifTrue: [transformedObject _ anObject] ifFalse: [transformedObject _ anObject scaleBy: scale]. transformedObject _ transformedObject translateBy: translation. ^transformedObject! ! !WindowingTransformation methodsFor: 'applying transform'! compose: aTransformation "Answer a WindowingTransformation that is the composition of the receiver and aTransformation. The effect of applying the resulting WindowingTransformation to an object is the same as that of first applying aTransformation to the object and then applying the receiver to its result." | aTransformationScale newScale newTranslation | aTransformationScale _ aTransformation scale. scale == nil ifTrue: [aTransformation noScale ifTrue: [newScale _ nil] ifFalse: [newScale _ aTransformationScale]. newTranslation _ translation + aTransformation translation] ifFalse: [aTransformation noScale ifTrue: [newScale _ scale] ifFalse: [newScale _ scale * aTransformationScale]. newTranslation _ translation + (scale * aTransformation translation)]. ^WindowingTransformation scale: newScale translation: newTranslation! ! !WindowingTransformation methodsFor: 'printing'! printOn: aStream "Refer to the comment in Object|printOn:." aStream nextPutAll: self class name, ' scale: '; print: scale; nextPutAll: ' translation: '; print: translation! ! !WindowingTransformation methodsFor: 'private'! checkScale: aScale "Convert aScale to the internal format of a floating-point Point." | checkedScale | checkedScale _ aScale asPoint. ^checkedScale x asFloat @ checkedScale y asFloat! ! !WindowingTransformation methodsFor: 'private'! setScale: aScale translation: aTranslation "Sets the scale to aScale and the translation to aTranslation." scale _ aScale. translation _ aTranslation! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WindowingTransformation class instanceVariableNames: ''! !WindowingTransformation class methodsFor: 'instance creation'! identity "Answer an instance of me with no scaling (nil) and no translation (0@0)." ^self new setScale: nil translation: 0 @ 0! ! !WindowingTransformation class methodsFor: 'instance creation'! scale: aScale translation: aTranslation "Answer an instance of me with a scale factor of aScale and a translation offset of aTranslation. When the transformation is applied (see WindowingTransformation|apply:), the scale is applied first, followed by the translation." ^self new setScale: aScale translation: aTranslation! ! !WindowingTransformation class methodsFor: 'instance creation'! window: aWindow viewport: aViewport "Answer an instance of me with a scale and translation based on aWindow and aViewport. The scale and translation are computed such that aWindow, when transformed, coincides with aViewport." | scale translation | aViewport width = aWindow width & (aViewport height = aWindow height) ifTrue: [scale _ nil] ifFalse: [scale _ aViewport width asFloat / aWindow width asFloat @ (aViewport height asFloat / aWindow height asFloat)]. scale == nil ifTrue: [translation _ aViewport left - aWindow left @ (aViewport top - aWindow top)] ifFalse: [translation _ aViewport left - (scale x * aWindow left) @ (aViewport top - (scale y * aWindow top))]. ^self new setScale: scale translation: translation! ! ArrayedCollection variableWordSubclass: #WordArray instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Collections-Arrayed'! !WordArray commentStamp: '<historical>' prior: 0! WordArrays store 32-bit unsigned Integer values. ! !WordArray methodsFor: 'converting' stamp: 'ar 9/14/1998 23:46'! asWordArray ^self! ! !WordArray methodsFor: 'accessing' stamp: 'sma 4/22/2000 17:47'! atAllPut: value "Fill the receiver with the given value" <primitive: 145> super atAllPut: value! ! !WordArray methodsFor: 'accessing' stamp: 'ar 3/3/2001 16:18'! byteSize ^self size * 4! ! !WordArray methodsFor: 'accessing' stamp: 'tk 3/13/2000 14:46'! bytesPerElement "Number of bytes in each item. This multiplied by (self size)*8 gives the number of bits stored." ^ 4! ! !WordArray methodsFor: 'accessing' stamp: 'ar 11/2/1998 12:19'! defaultElement "Return the default element of the receiver" ^0! ! !WordArray methodsFor: 'private' stamp: 'ar 2/15/1999 00:51'! replaceFrom: start to: stop with: replacement startingAt: repStart <primitive: 105> ^super replaceFrom: start to: stop with: replacement startingAt: repStart ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WordArray class instanceVariableNames: ''! !WordArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:19'! ccg: cg emitLoadFor: aString from: anInteger on: aStream cg emitLoad: aString asIntPtrFrom: anInteger on: aStream! ! !WordArray class methodsFor: 'plugin generation' stamp: 'acg 9/20/1999 13:16'! ccg: cg prolog: aBlock expr: aString index: anInteger ^cg ccgLoad: aBlock expr: aString asUnsignedPtrFrom: anInteger andThen: (cg ccgValBlock: 'isWords')! ! !WordArray class methodsFor: 'plugin generation' stamp: 'acg 9/17/1999 01:19'! ccgDeclareCForVar: aSymbolOrString ^'unsigned *', aSymbolOrString! ! StringHolder subclass: #Workspace instanceVariableNames: 'bindings acceptDroppedMorphs' classVariableNames: '' poolDictionaries: '' category: 'Kernel-ST80 Remnants'! !Workspace commentStamp: 'ls 10/14/2003 12:13' prior: 0! A Workspace is a text area plus a lot of support for executable code. It is a great place to execute top-level commands to compute something useful, and it is a great place to develop bits of a program before those bits get put into class methods. To open a new workspace, execute: Workspace open A workspace can have its own variables, called "workspace variables", to hold intermediate results. For example, if you type into a workspace "x := 5" and do-it, then later you could type in "y := x * 2" and y would become 10. Additionally, in Morphic, a workspace can gain access to morphs that are on the screen. If acceptDroppedMorphss is turned on, then whenever a morph is dropped on the workspace, a variable will be created which references that morph. This functionality is toggled with the window-wide menu of a workspace. The instance variables of this class are: bindings - holds the workspace variables for this workspace acceptDroppedMorphss - whether dropped morphs should create new variables! ]style[(286 14 722)f1,f1dWorkspace open;;,f1! !Workspace methodsFor: 'binding'! bindingOf: aString bindings isNil ifTrue: [bindings _ Dictionary new]. (bindings includesKey: aString) ifFalse: [bindings at: aString put: nil]. ^bindings associationAt: aString! ! !Workspace methodsFor: 'accessing' stamp: 'jsp 3/23/1999 12:19'! setBindings: aDictionary "Sets the Workspace to use the specified dictionary as its namespace" bindings _ aDictionary. ! ! !Workspace methodsFor: 'as yet unclassified' stamp: 'BG 11/1/2003 22:13'! saveContentsInFile "A bit of a hack to pass along this message to the controller or morph. (Possibly this Workspace menu item could be deleted, since it's now in the text menu.)" | textView | textView _ self dependents detect: [:dep | dep isKindOf: PluggableTextView] ifNone: [nil]. textView notNil ifTrue: [^ textView controller saveContentsInFile]. ! ! !Workspace methodsFor: 'initialize-release' stamp: 'sma 11/11/2000 16:33'! initialize super initialize. acceptDroppedMorphs _ false! ! !Workspace methodsFor: 'object fileIn' stamp: 'RAA 12/20/2000 17:50'! convertToCurrentVersion: varDict refStream: smartRefStrm acceptDroppedMorphs ifNil: [acceptDroppedMorphs _ false]. ^super convertToCurrentVersion: varDict refStream: smartRefStrm. ! ! !Workspace methodsFor: 'menu commands' stamp: 'ssa 9/3/2008 10:48'! addModelItemsToWindowMenu: aMenu "Add model-related items to the supplied window menu" aMenu addLine. aMenu add: 'save contents to file...' target: self action: #saveContentsInFile. aMenu addLine. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Workspace class instanceVariableNames: ''! !Workspace class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:13'! initialize self registerInFlapsRegistry. ! ! !Workspace class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:14'! registerInFlapsRegistry "Register the receiver in the system's flaps registry" self environment at: #Flaps ifPresent: [:cl | cl registerQuad: #(Workspace prototypicalToolWindow 'Workspace' 'A Workspace is a simple window for editing text. You can later save the contents to a file if you desire.') forFlapNamed: 'Tools'.]! ! !Workspace class methodsFor: 'class initialization' stamp: 'asm 4/11/2003 12:42'! unload "Unload the receiver from global registries" self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! PositionableStream subclass: #WriteStream instanceVariableNames: 'writeLimit' classVariableNames: '' poolDictionaries: '' category: 'Collections-Streams'! !WriteStream commentStamp: '<historical>' prior: 0! I represent an accessor for a sequence of objects that can only store objects in the sequence.! !WriteStream methodsFor: 'accessing'! contents readLimit _ readLimit max: position. ^collection copyFrom: 1 to: position! ! !WriteStream methodsFor: 'accessing'! next self shouldNotImplement! ! !WriteStream methodsFor: 'accessing' stamp: 'di 3/8/1999 09:02'! nextPut: anObject "Primitive. Insert the argument at the next position in the Stream represented by the receiver. Fail if the collection of this stream is not an Array or a String. Fail if the stream is positioned at its end, or if the position is out of bounds in the collection. Fail if the argument is not of the right type for the collection. Optional. See Object documentation whatIsAPrimitive." <primitive: 66> position >= writeLimit ifTrue: [^ self pastEndPut: anObject] ifFalse: [position _ position + 1. ^collection at: position put: anObject]! ! !WriteStream methodsFor: 'accessing' stamp: 'BG 5/24/2003 20:41'! nextPutAll: aCollection | newEnd | collection class == aCollection class ifFalse: [^ super nextPutAll: aCollection ]. newEnd _ position + aCollection size. newEnd > writeLimit ifTrue: [self growTo: newEnd + 10]. collection replaceFrom: position+1 to: newEnd with: aCollection startingAt: 1. position _ newEnd.! ! !WriteStream methodsFor: 'accessing'! size ^readLimit _ readLimit max: position! ! !WriteStream methodsFor: 'positioning'! position: anInteger "Refer to the comment in PositionableStream|position:." readLimit _ readLimit max: position. super position: anInteger! ! !WriteStream methodsFor: 'positioning'! reset "Refer to the comment in PositionableStream|reset." readLimit _ readLimit max: position. position _ 0! ! !WriteStream methodsFor: 'positioning' stamp: 'ar 11/12/1998 21:27'! resetToStart readLimit _ position _ 0.! ! !WriteStream methodsFor: 'positioning' stamp: 'ajh 5/25/2001 20:19'! setToEnd "Refer to the comment in PositionableStream|setToEnd." readLimit _ readLimit max: position. super setToEnd.! ! !WriteStream methodsFor: 'character writing'! cr "Append a return character to the receiver." self nextPut: Character cr! ! !WriteStream methodsFor: 'character writing'! crtab "Append a return character, followed by a single tab character, to the receiver." self nextPut: Character cr. self nextPut: Character tab! ! !WriteStream methodsFor: 'character writing'! crtab: anInteger "Append a return character, followed by anInteger tab characters, to the receiver." self nextPut: Character cr. anInteger timesRepeat: [self nextPut: Character tab]! ! !WriteStream methodsFor: 'character writing' stamp: 'di 6/7/2000 22:43'! nextPutKeyword: keyword withArg: argValue "Emit a keyword/value pair in the alternate syntax" self nextPutAll: (keyword copyWithout: $:); nextPut: $(; store: argValue; nextPut: $)! ! !WriteStream methodsFor: 'character writing'! space "Append a space character to the receiver." self nextPut: Character space! ! !WriteStream methodsFor: 'character writing'! tab "Append a tab character to the receiver." self nextPut: Character tab! ! !WriteStream methodsFor: 'character writing' stamp: 'JF 7/31/2003 13:00'! tab: anInteger "Append anInteger tab characters to the receiver." anInteger timesRepeat: [self tab]! ! !WriteStream methodsFor: 'fileIn/Out'! nextChunkPut: aString "Append the argument, aString, to the receiver, doubling embedded terminators." | i remainder terminator | terminator _ $!!. remainder _ aString. [(i _ remainder indexOf: terminator) = 0] whileFalse: [self nextPutAll: (remainder copyFrom: 1 to: i). self nextPut: terminator. "double imbedded terminators" remainder _ remainder copyFrom: i+1 to: remainder size]. self nextPutAll: remainder; nextPut: terminator! ! !WriteStream methodsFor: 'fileIn/Out' stamp: 'di 2/2/98 13:03'! nextChunkPutWithStyle: aStringOrText "Append the argument, aText, to the receiver, doubling embedded terminators. Put out one chunk for the string and one for the style runs. Mark the style with ]style[." aStringOrText class == String ifTrue: [^ self nextChunkPut: aStringOrText]. aStringOrText runs coalesce. aStringOrText unembellished ifTrue: [^ self nextChunkPut: aStringOrText asString]. self nextChunkPut: aStringOrText asString. self cr; nextPutAll: ']style['. self nextChunkPut: (String streamContents: [:strm | aStringOrText runs writeScanOn: strm]). ! ! !WriteStream methodsFor: 'fileIn/Out' stamp: 'dew 9/24/2001 23:45'! timeStamp "Append the current time to the receiver as a String." self nextChunkPut: "double string quotes and !!s" (String streamContents: [:s | Smalltalk timeStamp: s]) printString. self cr! ! !WriteStream methodsFor: 'printing'! store: anObject "Have anObject print on the receiver for purposes of rereading." anObject storeOn: self! ! !WriteStream methodsFor: 'private' stamp: 'di 11/18/1999 22:55'! braceArray "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." ^ collection! ! !WriteStream methodsFor: 'private' stamp: 'di 11/18/1999 22:50'! braceArray: anArray "This method is used in compilation of brace constructs. It MUST NOT be deleted or altered." collection _ anArray. position _ 0. readLimit _ 0. writeLimit _ anArray size.! ! !WriteStream methodsFor: 'private' stamp: 'BG 5/24/2003 22:49'! growTo: anInteger " anInteger is the required minimal new size of the collection " | oldSize grownCollection newSize | oldSize _ collection size. newSize := anInteger + (oldSize // 4 max: 20). grownCollection _ collection class new: newSize. collection _ grownCollection replaceFrom: 1 to: oldSize with: collection startingAt: 1. writeLimit _ collection size. ! ! !WriteStream methodsFor: 'private'! on: aCollection super on: aCollection. readLimit _ 0. writeLimit _ aCollection size! ! !WriteStream methodsFor: 'private'! on: aCollection from: firstIndex to: lastIndex | len | collection _ aCollection. readLimit _ writeLimit _ lastIndex > (len _ collection size) ifTrue: [len] ifFalse: [lastIndex]. position _ firstIndex <= 1 ifTrue: [0] ifFalse: [firstIndex - 1]! ! !WriteStream methodsFor: 'private' stamp: 'gh 5/15/2002 09:55'! pastEndPut: anObject "Grow the collection by creating a new bigger collection and then copy over the contents from the old one. We grow by doubling the size but the growth is kept between 20 and 1000000. Finally we put <anObject> at the current write position." | oldSize grownCollection | oldSize _ collection size. grownCollection _ collection class new: oldSize + ((oldSize max: 20) min: 1000000). collection _ grownCollection replaceFrom: 1 to: oldSize with: collection startingAt: 1. writeLimit _ collection size. collection at: (position _ position + 1) put: anObject! ! !WriteStream methodsFor: 'private'! with: aCollection super on: aCollection. position _ readLimit _ writeLimit _ aCollection size! ! !WriteStream methodsFor: 'private' stamp: 'djp 11/6/1999 23:15'! withAttributes: attributes do: strmBlock "No-op here is overriden in TextStream for font emphasis" ^ strmBlock value! ! !WriteStream methodsFor: 'file open/close' stamp: 'mir 8/10/1999 11:56'! flush! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! WriteStream class instanceVariableNames: ''! !WriteStream class methodsFor: 'instance creation'! on: aCollection from: firstIndex to: lastIndex "Answer an instance of me on a copy of the argument, aCollection, determined by the indices firstIndex and lastIndex. Position the instance at the beginning of the collection." ^self basicNew on: aCollection from: firstIndex to: lastIndex! ! !WriteStream class methodsFor: 'instance creation'! with: aCollection "Answer an instance of me on the argument, aCollection, positioned to store objects at the end of aCollection." ^self basicNew with: aCollection! ! !WriteStream class methodsFor: 'instance creation'! with: aCollection from: firstIndex to: lastIndex "Answer an instance of me on the subcollection of the argument, aCollection, determined by the indices firstIndex and lastIndex. Position the instance to store at the end of the subcollection." ^self basicNew with: (aCollection copyFrom: firstIndex to: lastIndex)! ! Timespan subclass: #Year instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Chronology'! !Year commentStamp: '<historical>' prior: 0! I represent a year. ! !Year methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:01'! asYear ^ self ! ! !Year methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:01'! daysInMonth self shouldNotImplement ! ! !Year methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:01'! daysInYear ^ self duration days.! ! !Year methodsFor: 'squeak protocol' stamp: 'brp 5/21/2003 08:38'! printOn: aStream aStream nextPutAll: 'a Year ('. self start year printOn: aStream. aStream nextPutAll: ')'. ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Year class instanceVariableNames: ''! !Year class methodsFor: 'squeak protocol' stamp: 'brp 9/11/2003 14:05'! current ^ self year: (DateAndTime now year) ! ! !Year class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:00'! isLeapYear: aYearInteger | adjustedYear | adjustedYear _ aYearInteger > 0 ifTrue: [aYearInteger] ifFalse: [(aYearInteger + 1) negated]. "There was no year 0" ^ ((adjustedYear \\ 4 ~= 0) or: [(adjustedYear \\ 100 = 0) and: [adjustedYear \\ 400 ~= 0]]) not.! ! !Year class methodsFor: 'squeak protocol' stamp: 'brp 7/1/2003 13:53'! starting: aDateAndTime duration: aDuration "Override - start from midnight" | midnight | midnight _ aDateAndTime asDateAndTime midnight. ^ super starting: midnight duration: (Duration days: (self daysInYear: midnight year)).! ! !Year class methodsFor: 'squeak protocol' stamp: 'brp 5/13/2003 09:00'! year: aYear ^ self starting: (DateAndTime year: aYear month: 1 day: 1).! ! !Year class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:52'! daysInYear: yearInteger ^ 365 + ((self isLeapYear: yearInteger) ifTrue: [1] ifFalse: [0]). ! ! !Year class methodsFor: 'smalltalk-80' stamp: 'brp 7/1/2003 13:55'! leapYear: yearInteger ^ (self isLeapYear: yearInteger) ifTrue: [1] ifFalse: [0]! ! ArithmeticError subclass: #ZeroDivide instanceVariableNames: 'dividend' classVariableNames: '' poolDictionaries: '' category: 'System-Exceptions Kernel'! !ZeroDivide commentStamp: '<historical>' prior: 0! ZeroDivide may be signaled when a mathematical division by 0 is attempted.! !ZeroDivide methodsFor: 'exceptionDescription' stamp: 'pnm 8/16/2000 15:05'! isResumable "Determine whether an exception is resumable." ^true! ! !ZeroDivide methodsFor: 'exceptionBuilder' stamp: 'pnm 8/16/2000 15:05'! dividend: argument "Specify the number that was being divided by zero." dividend := argument! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ZeroDivide class instanceVariableNames: ''! !ZeroDivide class methodsFor: 'exceptionInstantiator' stamp: 'bf 9/27/1999 17:26'! dividend: argument ^self new dividend: argument; yourself! ! ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/config.h ================================================ /* config.h. Generated by configure. */ /* config.h.in -- template for config.h -*- C -*- * * Copyright (C) 1996-2005 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. */ /* Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // /* Author: Ian.Piumarta@squeakland.org * * Last edited: 2005-03-28 22:47:17 by piumarta on emilia.local */ #ifndef __sq_config_h #define __sq_config_h /* explicit image width */ #define HAVE_INTERP_H 1 /* package options */ #define USE_X11 1 /* #undef USE_X11_GLX */ #define USE_QUARTZ 1 #define USE_QUARTZ_CGL 1 /* #undef USE_RFB */ /* libraries */ /* #undef HAVE_LIBX11 */ #define HAVE_LIBXEXT 1 /* #undef HAVE_LIBDL */ #define HAVE_DYLD 1 /* #undef HAVE_LIBFFI */ /* #undef HAVE_ICONV */ /* #undef USE_AUDIO_NONE */ /* #undef USE_AUDIO_SUN */ /* #undef USE_AUDIO_NAS */ /* #undef USE_AUDIO_OSS */ /* #undef USE_AUDIO_MACOSX */ /* #undef OSS_DEVICE */ /* header files */ #define HAVE_UNISTD_H 1 /* #undef NEED_GETHOSTNAME_P */ #define HAVE_DIRENT_H 1 /* #undef HAVE_SYS_NDIR_H */ /* #undef HAVE_SYS_DIR_H */ /* #undef HAVE_NDIR_H */ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 #undef HAVE_DLFCN_H #else #define HAVE_DLFCN_H 1 #endif #define HAVE_ICONV_H 1 #define HAVE_SYS_TIME_H 1 #define TIME_WITH_SYS_TIME 1 #define HAVE_SYS_FILIO_H 1 /* #undef HAVE_SYS_AUDIOIO_H */ /* #undef HAVE_SUN_AUDIOIO_H */ /* #undef HAVE_PTY_H */ #define HAVE_UTIL_H 1 /* #undef HAVE_LIBUTIL_H */ /* #undef HAVE_STROPTS_H */ /* #undef HAVE_GL_GL_H */ #define HAVE_OPENGL_GL_H 1 /* #undef NEED_SUNOS_H */ /* system calls/library functions */ #define AT_EXIT atexit #define HAVE_TZSET 1 #define HAVE_OPENPTY 1 /* #undef HAVE_UNIX98_PTYS */ #define HAVE_SNPRINTF 1 /* #undef HAVE___SNPRINTF */ #define HAVE_MMAP 1 #define HAVE_DYLD 1 #define HAVE_LANGINFO_CODESET 1 #define HAVE_ALLOCA 1 #define HAVE_ALLOCA_H 1 #define HAVE_UNSETENV 1 /* widths of primitive types */ #define SIZEOF_INT 4 #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 8 #ifdef __x86_64__ #define SIZEOF_VOID_P 8 #else #define SIZEOF_VOID_P 4 #endif /* structures */ #define HAVE_TM_GMTOFF 1 #define HAVE_TIMEZONE 1 /* typedefs */ /* #undef size_t */ #define squeakInt64 long long /* architecture */ #define OS_TYPE "unix" /* #undef VM_HOST_VENDOR */ #define VM_HOST_OS "darwin8.5.0" #if defined(__BIG_ENDIAN__) #define WORDS_BIGENDIAN 1 #define VMENDIANNESS 1 #define VMBIGENDIAN 1 #define VM_HOST "powerpc-apple-darwin8.5.0" #define VM_HOST_CPU "powerpc" #else #undef WORDS_BIGENDIAN #define VMENDIANNESS 0 #define VMBIGENDIAN 0 #define VM_HOST "intel-apple-darwin8.5.0" #define VM_HOST_CPU "intel" #if COGVM #else #define DOUBLE_WORD_ORDER 1 #endif #define LSB_FIRST 1 #endif #define HAVE_LIBDL 1 /* #undef DOUBLE_WORD_ALIGNMENT */ /* #undef DOUBLE_WORD_ORDER */ /* damage containment */ #define DARWIN 1 #ifdef NEED_SUNOS_H # include "sunos.h" #endif /* other configured variables */ #define SQ_VERSION "3.8g-6548" #define VM_VERSION "3.8a-2" #define VM_LIBDIR "/usr/local/lib/squeak/3.8a-2" #define VM_MODULE_PREFIX "" /* #undef VM_DLSYM_PREFIX */ #define VM_X11DIR "/usr/X11R6/lib" /* avoid dependencies on glibc2.3 */ /* #undef HAVE_FEATURES_H */ #if defined(HAVE_FEATURES_H) # include "glibc.h" #endif #endif /* __sq_config_h */ ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/iPhone.changes ================================================ 'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 14 August 2011 at 7:19:23 pm'! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:22'! genericMenu: aMenu aMenu add: 'no menu yet' target: self selector: #yourself. ^aMenu! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:44'! getCurrentSelection ^currentSelection! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:46'! noteNewSelection: x currentSelection _ x. self changed: #getCurrentSelection. currentSelection ifNil: [^self]. currentSelection sendSettingMessageTo: self. ! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:53'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !AbstractHierarchicalList methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:47'! update: aSymbol aSymbol == #hierarchicalList ifTrue: [ ^self changed: #getList ]. super update: aSymbol! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection "Answer the value of currentSelection" currentSelection isNil ifTrue:[self currentSelection: nil]. ^ currentSelection! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection: anObject "Set the value of currentSelection" currentSelection _ anObject! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser "Answer the value of myBrowser" myBrowser isNil ifTrue:[self myBrowser: nil]. ^ myBrowser! ! !AbstractHierarchicalList methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser: anObject "Set the value of myBrowser" myBrowser _ anObject! ! !AbstractHierarchicalList commentStamp: '<historical>' prior: 0! Contributed by Bob Arning as part of the ObjectExplorer package. ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'bf 2/25/2005 11:11'! allImages | body colorTable | stream class == ReadWriteStream ifFalse: [ stream binary. self on: (ReadWriteStream with: (stream contentsOfEntireFile))]. localColorTable _ nil. forms _ OrderedCollection new. delays _ OrderedCollection new. comments _ OrderedCollection new. self readHeader. [(body _ self readBody) == nil] whileFalse: [colorTable _ localColorTable ifNil: [colorPalette]. transparentIndex ifNotNil: [transparentIndex + 1 > colorTable size ifTrue: [colorTable _ colorTable forceTo: transparentIndex + 1 paddingWith: Color white]. colorTable at: transparentIndex + 1 put: Color transparent]. body colors: colorTable. forms add: body. delays add: delay]. ^ forms! ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'mir 11/19/2003 14:16'! delays ^ delays! ! !AnimatedGIFReadWriter methodsFor: 'accessing' stamp: 'mir 11/19/2003 14:16'! forms ^ forms! ! !AnimatedGIFReadWriter methodsFor: 'private' stamp: 'mir 11/19/2003 12:25'! comment: aString comments add: aString! ! !AnimatedGIFReadWriter methodsFor: 'private-decoding' stamp: 'mir 11/19/2003 12:21'! readBitData | form | form := super readBitData. form offset: offset. ^form! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'mir 11/18/2003 17:00'! formsFromFileNamed: fileName | stream | stream _ FileStream readOnlyFileNamed: fileName. ^ self formsFromStream: stream! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'mir 11/18/2003 17:00'! formsFromStream: stream | reader | reader _ self new on: stream reset. Cursor read showWhile: [reader allImages. reader close]. ^reader! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 6/12/2004 13:12'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('gif')! ! !AnimatedGIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! wantsToHandleGIFs ^true! ! !ArchiveReader methodsFor: 'reading'! close stream close! ! !ArchiveReader methodsFor: 'reading'! next | anInteger | startPosition _ position. anInteger _ self read: Integer. ^anInteger = 0 ifTrue: [objectMap at: (self read: Integer)] ifFalse: [(classMap at: anInteger) dearchive: (classVersions at: anInteger) from: self]! ! !ArchiveReader methodsFor: 'reading'! read: aClass "Ask aClass to read one of its objects from stream. aClass is typically Integer, Float, Symbol, etc. Assume the object was put on the stream using ArchiveWriter>store:" | anObject | anObject _ aClass readFrom: stream. stream skipSeparators. position _ position + 1. ^anObject! ! !ArchiveReader methodsFor: 'testing'! isCopier "For compatibility with CopyReader (in case an object cares what type of Reader its using)." ^false! ! !ArchiveReader methodsFor: 'private' stamp: 'ssa 10/25/2008 21:29'! dearchive: version from: aStream "This is used before a class is read in for the first time... version is ignored here. This method has this name only to avoid another case statement (see #next). A better name for this method would be #dearchiveClassFrom:" | aClass anInteger | classMap add: (aClass _ Smalltalk at: (aStream read: Symbol)). classVersions add: (anInteger _ aStream read: Integer). ^aClass dearchive: anInteger from: aStream! ! !ArchiveReader methodsFor: 'private'! setStream: aStream stream _ aStream. objectMap _ IdentityDictionary new: 400. classMap _ OrderedCollection new: 30. classMap add: self. classVersions _ OrderedCollection with: 0. position _ 0! ! !ArchiveReader methodsFor: 'private'! storeObject: anObject objectMap at: startPosition put: anObject! ! !ArchiveReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 08:08'! dearchive: aString "ArchiveReader dearchive: 'archive.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream next. aStream close. ^anObject! ! !ArchiveReader class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 20:52'! fastStreamOn: aFilename "Answer a stream which is appropriate for getting the data from aFilename as fast as possible. The default version ignores lineEndConventions. This is tightly coupled with ArchiveWriter>fastStreamOn:" ^(FileStream oldFileNamed: aFilename) openReadOnly; yourself! ! !ArchiveReader class methodsFor: 'instance creation'! on: aStream ^self new setStream: aStream! ! !ArchiveWriter methodsFor: 'writing'! canCopy: anObject "For archiving, I write out everything" ^true! ! !ArchiveWriter methodsFor: 'writing'! close stream close! ! !ArchiveWriter methodsFor: 'writing'! nextPut: anObject | anInteger | anInteger _ objectMap at: anObject ifAbsent: [^anObject archiveOn: self]. self store: 0; store: anInteger! ! !ArchiveWriter methodsFor: 'writing'! store: anObject "Put anObject on the Stream, converting it to an ascii String. anObject will typically be a Symbol, Number, etc. This takes advantage of the storeOn:/readFrom: facility already in Smalltalk which works well for Basic Classes." "kwa -- 12 October 1989, replaced #space with: nextPut: Space (a TextConstant) for efficiency." stream store: anObject; nextPut: Space. position _ position + 1! ! !ArchiveWriter methodsFor: 'private' stamp: 'ssa 10/26/2008 20:44'! setStream: aWriteStream stream _ aWriteStream. classMap _ IdentityDictionary new: 30. classMap at: self put: 1. objectMap _ IdentityDictionary new: 400. position _ 0! ! !ArchiveWriter methodsFor: 'private'! storeClass: aClass self store: (classMap at: aClass ifAbsent: [self store: 1; store: aClass name; store: aClass archiveVersion. ^classMap at: aClass put: classMap size + 1])! ! !ArchiveWriter methodsFor: 'private'! storeObject: anObject objectMap at: anObject put: "stream" position! ! !ArchiveWriter methodsFor: 'testing'! isCopier "For compatibility with CopyWriter (in case an object cares what type of Writer its using)." ^false! ! !ArchiveWriter class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 21:17'! archive: anObject to: aString "ArchiveWriter archive: Array new to: 'archive.test'" "ArchiveWriter archive: 1 to: 'archive.test'" "ArchiveWriter archive: #(1 2 3) to: 'archive.test'" "ArchiveWriter archive: (Array with: #aSymbol with: 'aSymbol') to: 'archive.test'" | stream | stream _ self fastStreamOn: aString. (self on: stream) nextPut: anObject; close.! ! !ArchiveWriter class methodsFor: 'instance creation' stamp: 'ssa 10/25/2008 20:34'! fastStreamOn: aFilename "Answer a stream which is appropriate for getting the data to aFilename as fast as possible. The default version ignores lineEndConventions. This is tightly coupled with ArchiveReader>fastStreamOn:" ^FileStream newFileNamed: aFilename! ! !ArchiveWriter class methodsFor: 'instance creation'! on: aWriteStream ^self new setStream: aWriteStream! ! !Array methodsFor: 'converting' stamp: 'ssa 10/26/2008 15:00'! asRunArray "Answer a RunArray of me" ^RunArray newFrom: self! ! !Array methodsFor: 'testing' stamp: 'ssa 5/12/2010 19:26'! isArray "Return true if the receiver is an Array" ^true! ! !ArrayWithNilDetector methodsFor: 'accessing' stamp: 'ssa 11/24/2009 20:01'! at: j put: obj obj ifNil:[self halt:'trying to add nil']. ^super at: j put: obj! ! !ArrayWithNilDetector methodsFor: 'accessing' stamp: 'ssa 11/24/2009 20:39'! species (self includes: nil) ifTrue:[self halt:'I found a nil!!!!']. ^super species! ! !ArrayWithNilDetector class methodsFor: 'instance creation' stamp: 'ssa 11/24/2009 20:37'! new: someSize someSize > 0 ifTrue:[self halt:'trying to create a an array with nil elements']. ^super new: someSize! ! !ArrayedCollection methodsFor: 'sorting' stamp: 'sma 5/12/2000 14:25'! mergeSortFrom: startIndex to: stopIndex by: aBlock "Sort the given range of indices using the mergesort algorithm. Mergesort is a worst-case O(N log N) sorting algorithm that usually does only half as many comparisons as heapsort or quicksort." "Details: recursively split the range to be sorted into two halves, mergesort each half, then merge the two halves together. An extra copy of the data is used as temporary storage and successive merge phases copy data back and forth between the receiver and this copy. The recursion is set up so that the final merge is performed into the receiver, resulting in the receiver being completely sorted." self size <= 1 ifTrue: [^ self]. "nothing to do" startIndex = stopIndex ifTrue: [^ self]. self assert: [startIndex >= 1 and: [startIndex < stopIndex]]. "bad start index" self assert: [stopIndex <= self size]. "bad stop index" self mergeSortFrom: startIndex to: stopIndex src: self clone dst: self by: aBlock! ! !ArrayedCollection methodsFor: '*Sly' stamp: 'dmu 9/17/2010 11:04'! parallelCollect: aBlock "#(1 2 3 4 5) parallelCollect:[:e| e * 2]" | results task barrier interlock result | "true ifTrue: [^ self collect: aBlock.]." "for debugging" self ifEmpty: [^ self]. (Sly3 serializeForDebugging or: [self size = 1]) ifTrue: [^ self collect: aBlock]. results _ self species new: self size. barrier _ RVMBarrier new signalsNeededToPass: self size. interlock _ Semaphore forMutualExclusion. 1 to: self size do: [:i| task _ [ result _ [aBlock copy fixTemps value: (self at: i)] ifCurtailed: [barrier signal]. interlock critical: [results at: i put: result]. barrier signal ] asSlyMemberProcess. task resume ]. barrier wait. ^results! ! !Association methodsFor: 'outlining' stamp: 'ssa 9/10/2009 16:01'! outlineString ^self key asString,' ',self value printString! ! !BGBinaryTrees methodsFor: 'benchmarking' stamp: 'StefanMarr 5/15/2011 12:25'! binarytrees: n to: output | minDepth maxDepth stretchDepth check longLivedTree iterations | minDepth := 4. maxDepth := minDepth + 2 max: n. stretchDepth := maxDepth + 1. check := (BGTreeNode bottomUpTree: 0 depth: stretchDepth) itemCheck. output nextPutAll: 'stretch tree of depth '; print: stretchDepth; tab; nextPutAll: ' check: '; print: check; cr. longLivedTree := BGTreeNode bottomUpTree: 0 depth: maxDepth. minDepth to: maxDepth by: 2 do: [:depth| iterations := 1 bitShift: maxDepth - depth + minDepth. check := 0. 1 to: iterations do: [:i| check := check + (BGTreeNode bottomUpTree: i depth: depth) itemCheck. check := check + (BGTreeNode bottomUpTree: -1*i depth: depth) itemCheck ]. output print: (2*iterations); tab; nextPutAll: ' trees of depth '; print: depth; tab; nextPutAll: ' check: '; print: check; cr ]. check := longLivedTree itemCheck. output nextPutAll: 'long lived tree of depth '; print: maxDepth; tab; nextPutAll: ' check: '; print: check; cr. ^ check.! ! !BGBinaryTrees commentStamp: 'StefanMarr 1/16/2011 17:29' prior: 0! This is an adaptation of a benchmark for testing GC. A whole tree is allocated before any nodes are GC'd. The binary-trees benchmark is a simplistic adaptation of Hans Boehm's GCBench, which in turn was adapted from a benchmark by John Ellis and Pete Kovac.! !BGBinaryTrees class methodsFor: 'defaults' stamp: 'StefanMarr 5/15/2011 23:25'! defaultProblemSize ^ 9! ! !BGBody methodsFor: 'nbody'! addMomentumTo: anArray anArray at: 1 put: (anArray at: 1) + (vx * mass). anArray at: 2 put: (anArray at: 2) + (vy * mass). anArray at: 3 put: (anArray at: 3) + (vz * mass). ^anArray! ! !BGBody methodsFor: 'nbody'! and: aBody velocityAfter: dt | dx dy dz distance mag | dx := x - aBody x. dy := y - aBody y. dz := z - aBody z. distance := ((dx*dx) + (dy*dy) + (dz*dz)) sqrt. mag := dt / (distance * distance * distance). self decreaseVelocity: dx y: dy z: dz m: aBody mass * mag. aBody increaseVelocity: dx y: dy z: dz m: mass * mag! ! !BGBody methodsFor: 'nbody'! decreaseVelocity: dx y: dy z: dz m: m vx := vx - (dx * m). vy := vy - (dy * m). vz := vz - (dz * m)! ! !BGBody methodsFor: 'nbody'! increaseVelocity: dx y: dy z: dz m: m vx := vx + (dx * m). vy := vy + (dy * m). vz := vz + (dz * m)! ! !BGBody methodsFor: 'nbody'! kineticEnergy ^0.5d0 * mass * ((vx * vx) + (vy * vy) + (vz * vz))! ! !BGBody methodsFor: 'nbody'! offsetMomentum: anArray | m | m := self class solarMass. vx := (anArray at: 1) negated / m. vy := (anArray at: 2) negated / m. vz := (anArray at: 3) negated / m! ! !BGBody methodsFor: 'nbody'! positionAfter: dt x := x + (dt * vx). y := y + (dt * vy). z := z + (dt * vz)! ! !BGBody methodsFor: 'nbody'! potentialEnergy: aBody | dx dy dz distance | dx := x - aBody x. dy := y - aBody y. dz := z - aBody z. distance := ((dx*dx) + (dy*dy) + (dz*dz)) sqrt. ^mass * aBody mass / distance! ! !BGBody methodsFor: 'accessing'! mass ^mass! ! !BGBody methodsFor: 'accessing'! x ^x! ! !BGBody methodsFor: 'accessing'! x: d1 y: d2 z: d3 vx: d4 vy: d5 vz: d6 mass: d7 x := d1. y := d2. z := d3. vx := d4. vy := d5. vz := d6. mass := d7! ! !BGBody methodsFor: 'accessing'! y ^y! ! !BGBody methodsFor: 'accessing'! z ^z! ! !BGBody class methodsFor: 'constants'! daysPerYear ^365.24d0! ! !BGBody class methodsFor: 'constants'! jupiter ^self new x: 4.84143144246472090d0 y: -1.16032004402742839d0 z: -1.03622044471123109d-1 vx: 1.66007664274403694d-3 * self daysPerYear vy: 7.69901118419740425d-3 * self daysPerYear vz: -6.90460016972063023d-5 * self daysPerYear mass: 9.54791938424326609d-4 * self solarMass! ! !BGBody class methodsFor: 'constants'! neptune ^self new x: 1.53796971148509165d1 y: -2.59193146099879641d1 z: 1.79258772950371181d-1 vx: 2.68067772490389322d-3 * self daysPerYear vy: 1.62824170038242295d-3 * self daysPerYear vz: -9.51592254519715870d-5 * self daysPerYear mass: 5.15138902046611451d-5 * self solarMass! ! !BGBody class methodsFor: 'constants'! pi ^3.141592653589793d0! ! !BGBody class methodsFor: 'constants'! saturn ^self new x: 8.34336671824457987d0 y: 4.12479856412430479d0 z: -4.03523417114321381d-1 vx: -2.76742510726862411d-3 * self daysPerYear vy: 4.99852801234917238d-3 * self daysPerYear vz: 2.30417297573763929d-5 * self daysPerYear mass: 2.85885980666130812d-4 * self solarMass! ! !BGBody class methodsFor: 'constants'! solarMass ^4.0d0 * self pi * self pi! ! !BGBody class methodsFor: 'constants'! sun ^self new x: 0.0d0 y: 0.0d0 z: 0.0d0 vx: 0.0d0 vy: 0.0d0 vz: 0.0d0 mass: self solarMass! ! !BGBody class methodsFor: 'constants'! uranus ^self new x: 1.28943695621391310d1 y: -1.51111514016986312d1 z: -2.23307578892655734d-1 vx: 2.96460137564761618d-3 * self daysPerYear vy: 2.37847173959480950d-3 * self daysPerYear vz: -2.96589568540237556d-5 * self daysPerYear mass: 4.36624404335156298d-5 * self solarMass! ! !BGChameleon methodsFor: 'accessing'! color ^color! ! !BGChameleon methodsFor: 'accessing'! meetings ^meetings! ! !BGChameleon methodsFor: 'accessing'! wait semaphore wait! ! !BGChameleon methodsFor: 'changing colours'! color: c color := c! ! !BGChameleon methodsFor: 'changing colours'! fade color := #faded. waitingForPair signal. semaphore signal! ! !BGChameleon methodsFor: 'changing colours'! met: other | newColor | meetings := meetings + 1. color == #red ifTrue: [ newColor := other == #yellow ifTrue: [ #blue ] ifFalse: [ #yellow ] ]. color == #yellow ifTrue: [ newColor := other == #red ifTrue: [ #blue ] ifFalse: [ #red ] ]. color == #blue ifTrue: [ newColor := other == #red ifTrue: [ #yellow ] ifFalse: [ #red ] ]. color := newColor. waitingForPair signal! ! !BGChameleon methodsFor: 'running'! fork: meetingPlace ^[ self run: meetingPlace ] fork! ! !BGChameleon methodsFor: 'running'! run: meetingPlace [ color == #faded ] whileFalse: [ meetingPlace reachedBy: self. waitingForPair wait ]! ! !BGChameleon methodsFor: 'initialize-release'! initialize meetings := 0. waitingForPair := Semaphore new. semaphore := Semaphore new! ! !BGChameleon class methodsFor: 'instance creation'! color: c ^self new initialize; color: c! ! !BGChameleons class methodsFor: 'benchmark scripts' stamp: 'StefanMarr 1/16/2011 12:12'! chameneos " reports back the number of meetings " | out | ^ self chameneos: 1000000! ! !BGChameleons class methodsFor: 'benchmarking' stamp: 'StefanMarr 5/15/2011 12:17'! chameneos: n | c1 c2 c3 c4 mp | c1 := BGChameleon color: #blue. c2 := BGChameleon color: #red. c3 := BGChameleon color: #yellow. c4 := BGChameleon color: #blue. mp := BGMeetingPlace forMeetings: n. c1 fork: mp. c2 fork: mp. c3 fork: mp. c4 fork: mp. c1 wait. c2 wait. c3 wait. c4 wait. ^c1 meetings + c2 meetings + c3 meetings + c4 meetings! ! !BGChameleons class methodsFor: 'defaults' stamp: 'StefanMarr 5/15/2011 23:31'! defaultProblemSize ^ 10000! ! !BGChameneosColour methodsFor: 'accessing'! color ^color! ! !BGChameneosColour methodsFor: 'accessing'! color: aColor color := aColor! ! !BGChameneosColour methodsFor: 'as yet unclassified'! complementaryColourFor: aChameneosColour "determine the complementary colour defined as..." self == aChameneosColour ifTrue: [^self]. self isBlue ifTrue: [aChameneosColour isRed ifTrue: [^self class yellow] ifFalse: [^self class red]]. self isRed ifTrue: [aChameneosColour isBlue ifTrue: [^self class yellow] ifFalse: [^self class blue]]. aChameneosColour isBlue ifTrue: [^self class red] ifFalse: [^self class blue]! ! !BGChameneosColour methodsFor: 'testing'! hasSameColorAs: aChameneos ^self color == aChameneos color! ! !BGChameneosColour methodsFor: 'testing'! isBlue ^self == self class blue! ! !BGChameneosColour methodsFor: 'testing'! isRed ^self == self class red! ! !BGChameneosColour methodsFor: 'testing'! isYellow ^self == self class yellow! ! !BGChameneosColour methodsFor: 'printing'! printOn: aStream aStream nextPutAll: self color! ! !BGChameneosColour class methodsFor: 'accessing'! blue ^Blue! ! !BGChameneosColour class methodsFor: 'accessing'! blue: anObject Blue := anObject! ! !BGChameneosColour class methodsFor: 'accessing'! red ^Red! ! !BGChameneosColour class methodsFor: 'accessing'! red: anObject Red := anObject! ! !BGChameneosColour class methodsFor: 'accessing'! yellow ^Yellow! ! !BGChameneosColour class methodsFor: 'accessing'! yellow: anObject Yellow := anObject! ! !BGChameneosColour class methodsFor: 'initialize-release'! createBlue "comment stating purpose of message" ^super new color: #blue! ! !BGChameneosColour class methodsFor: 'initialize-release'! createRed "comment stating purpose of message" ^super new color: #red! ! !BGChameneosColour class methodsFor: 'initialize-release'! createYellow "comment stating purpose of message" ^super new color: #yellow! ! !BGChameneosColour class methodsFor: 'initialize-release'! initialize "self initialize" Red := self createRed. Blue := self createBlue. Yellow := self createYellow! ! !BGChameneosColour class methodsFor: 'printing' stamp: 'StefanMarr 1/16/2011 14:13'! generateReportOfColoursOn: readOut | colours | colours := Array with: Blue with: Red with: Yellow. colours do: [:aColour | colours do: [:anotherColour | aColour printOn: readOut. readOut nextPutAll: ' + '. anotherColour printOn: readOut. readOut nextPutAll: ' -> '. (aColour complementaryColourFor: anotherColour) printOn: readOut. readOut cr]]. ^readOut! ! !BGChameneosRedux class methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 23:34'! defaultProblemSize ^ 6000! ! !BGChameneosRedux class methodsFor: 'benchmarking-scripts' stamp: 'StefanMarr 5/15/2011 12:27'! chameneosredux2 "ChameneosRedux chameneosredux2" | report | report := TextStream with: String new. BGMall runBenchMark: 600 on: report. ^report contents! ! !BGCreature methodsFor: 'accessing'! colour ^colour! ! !BGCreature methodsFor: 'accessing'! colour: anObject colour := anObject! ! !BGCreature methodsFor: 'accessing'! creaturesMet ^creaturesMet! ! !BGCreature methodsFor: 'accessing'! creaturesMet: anObject creaturesMet := anObject! ! !BGCreature methodsFor: 'accessing'! name ^creatureName! ! !BGCreature methodsFor: 'accessing'! name: anObject creatureName := anObject! ! !BGCreature methodsFor: 'accessing'! selfMet ^selfMet! ! !BGCreature methodsFor: 'accessing'! selfMet: anObject ^selfMet := anObject! ! !BGCreature methodsFor: 'initialize-release'! initialize selfMet := 0. creaturesMet := 0! ! !BGCreature methodsFor: 'controlling'! visitMall: mall [| partner | partner := mall visitWith: self. partner ifNotNil: [colour := colour complementaryColourFor: partner colour. self == partner ifTrue: [selfMet := selfMet + 1]. creaturesMet := creaturesMet + 1]. partner isNil] whileFalse! ! !BGCreature class methodsFor: 'initialize-release' stamp: 'StefanMarr 5/15/2011 12:28'! withName: aName colour: aColour ^(BGCreature new initialize) name: aName; colour: aColour! ! !BGFannkuchRedux class methodsFor: 'defaults' stamp: 'StefanMarr 5/15/2011 23:35'! defaultProblemSize ^ 4! ! !BGFannkuchRedux class methodsFor: 'benchmarking' stamp: 'StefanMarr 5/15/2011 12:19'! fannkuchRedux: n to: output ^(BGPermGeneratorRedux new: n) maxPfannkuchenTo: output! ! !BGFannkuchRedux class methodsFor: 'benchmark scripts' stamp: 'StefanMarr 5/16/2011 14:45'! fannkuchredux | n f | n := 4. f := self fannkuchRedux: n to: (TextStream with: String new). ScriptConsole println: 'Pfannkuchen(', n printString, ') = ', f asString. ^''! ! !BGFasta class methodsFor: 'benchmark scripts' stamp: 'StefanMarr 5/15/2011 23:20'! defaultProblemSize ^ 1000! ! !BGFasta class methodsFor: 'benchmark scripts' stamp: 'StefanMarr 1/16/2011 18:56'! fasta " self fasta" | out | out := TextStream with: String new. self fasta: 1000 to: out. ^out contents! ! !BGFasta class methodsFor: 'benchmarking' stamp: 'StefanMarr 5/15/2011 12:24'! fasta: n to: out | r lineLength | lineLength := 60. self writeFasta: 'ONE Homo sapiens alu' from: ( BGRepeatStream to: n*2 on:'GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG', 'GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA', 'CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT', 'ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA', 'GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG', 'AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC', 'AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA' ) to: out lineLength: lineLength. r := BGRandomNumber to: 1. "Shared random sequence" self writeFasta: 'TWO IUB ambiguity codes' from: (( BGRandomStream to: n*3 on: #( #($a 0.27d0) #($c 0.12d0) #($g 0.12d0) #($t 0.27d0) #($B 0.02d0) #($D 0.02d0) #($H 0.02d0) #($K 0.02d0) #($M 0.02d0) #($N 0.02d0) #($R 0.02d0) #($S 0.02d0) #($V 0.02d0) #($W 0.02d0) #($Y 0.02d0))) random: r; yourself) to: out lineLength: lineLength. self writeFasta: 'THREE Homo sapiens frequency' from: (( BGRandomStream to: n*5 on: #( #($a 0.3029549426680d0) #($c 0.1979883004921d0) #($g 0.1975473066391d0) #($t 0.3015094502008d0))) random: r; yourself) to: out lineLength: lineLength. out flush. ! ! !BGFasta class methodsFor: 'benchmarking' stamp: 'StefanMarr 6/14/2010 17:10'! writeFasta: aString from: inStream to: outStream lineLength: lineLength | i | outStream nextPut: $>; nextPutAll: aString; cr. i := 0. [inStream atEnd] whileFalse: [i == lineLength ifTrue: [outStream cr. i := 0]. outStream nextPut: inStream next. i := i + 1]. outStream cr! ! !BGMall methodsFor: 'controlling'! close open := false! ! !BGMall methodsFor: 'controlling'! visitWith: aChameneos | pair partner | pair := self obtainPair. pair me: aChameneos. queue nextPut: pair. pair wait. partner := pair partner. self releasePair: pair. ^partner! ! !BGMall methodsFor: 'initialize-release' stamp: 'StefanMarr 5/15/2011 12:27'! initialize guard := Semaphore forMutualExclusion. queue := SharedQueue new. cache := OrderedCollection new. 1 to: 10 do: [:x | cache add: BGPair new]! ! !BGMall methodsFor: 'initialize-release'! run open := true. process ifNil: [process := [self processVisitors] newProcess. process priority: Processor userBackgroundPriority -1 ]. process resume! ! !BGMall methodsFor: 'accessing'! maxRendezvous: max maxRendezvous := max! ! !BGMall methodsFor: 'private'! obtainPair ^cache removeFirst! ! !BGMall methodsFor: 'private'! processVisitors [open] whileTrue: [1 to: maxRendezvous do: [:x | | first second | first := queue next. second := queue next. self setPartnersOn: first and: second. first signal. second signal]. [queue isEmpty] whileFalse: [queue next signal]]. process terminate. process := nil! ! !BGMall methodsFor: 'private'! releasePair: pair pair release. cache addFirst: pair! ! !BGMall methodsFor: 'private'! setPartnersOn: first and: second first partner: second me. second partner: first me. ! ! !BGMall methodsFor: 'private'! shutdown [queue isEmpty] whileFalse: [queue next signal]. process terminate. process := nil! ! !BGMall class methodsFor: 'initialize-release'! createAllowing: maxRendezvous "Private" ^self basicNew initialize maxRendezvous: maxRendezvous! ! !BGMall class methodsFor: 'initialize-release' stamp: 'StefanMarr 5/15/2011 12:29'! createCreaturesWith: aCollectionOfColours "Private" | aName | aName := 0. ^aCollectionOfColours collect: [:aColour | aName := aName + 1. BGCreature withName: aName colour: aColour]! ! !BGMall class methodsFor: 'initialize-release'! initialize "self initialize" Units := #('zero' 'one' 'two' 'three' 'four' 'five' 'six' 'seven' 'eight' 'nine')! ! !BGMall class methodsFor: 'initialize-release'! new ^self shouldNotImplement! ! !BGMall class methodsFor: 'initialize-release'! openMallWith: aCollectionOfColours forNumberOfMeets: aNumber | mall creatures guard | mall := self createAllowing: aNumber. mall run. creatures := self createCreaturesWith: aCollectionOfColours. guard := Semaphore new. self openMall: mall forCreatures: creatures usingGuard: guard. self waitForClosingOfMall: mall withCreatures: creatures usingGuard: guard. ^creatures! ! !BGMall class methodsFor: 'printing' stamp: 'StefanMarr 1/16/2011 14:42'! generateReportFor: creatures printOn: stream | sum | sum := creatures inject: 0 into: [:accum :each | accum + each creaturesMet]. creatures do: [:aCreature | aCreature creaturesMet printOn: stream. stream space; nextPutAll: (self units at: aCreature selfMet + 1); cr]. stream space. sum printString do: [:el | stream nextPutAll: (self units at: el digitValue + 1)] separatedBy: [stream space]. lastSum := sum. ^stream! ! !BGMall class methodsFor: 'printing'! generateReportForColours: colours printOn: stream stream space. colours do: [:colour | colour printOn: stream] separatedBy: [stream space]. ^stream! ! !BGMall class methodsFor: 'private'! openMall: aMall forCreatures: creatures usingGuard: sema | processes | processes := creatures collect: [:aCreature | [aCreature visitMall: aMall. sema signal] newProcess]. processes do: [:proc | proc priority: Processor userBackgroundPriority. proc resume]! ! !BGMall class methodsFor: 'private'! waitForClosingOfMall: aMall withCreatures: creatures usingGuard: guard creatures size timesRepeat: [guard wait]. aMall close! ! !BGMall class methodsFor: 'public' stamp: 'StefanMarr 5/15/2011 12:28'! runBenchMark: number on: anOutputStream "self runBenchMark: 60000 on: Transcript." | firstTestColours secondTestColours blue red yellow creatures | blue := BGChameneosColour blue. red := BGChameneosColour red. yellow := BGChameneosColour yellow. firstTestColours := Array with: blue with: red with: yellow. secondTestColours := (OrderedCollection new) add: blue; add: red; add: yellow; add: red; add: yellow; add: blue; add: red; add: yellow; add: red; add: blue; yourself. (BGChameneosColour generateReportOfColoursOn: anOutputStream) cr. (self generateReportForColours: firstTestColours printOn: anOutputStream) cr. creatures := BGMall openMallWith: firstTestColours forNumberOfMeets: number. (self generateReportFor: creatures printOn: anOutputStream) cr; cr. (self generateReportForColours: secondTestColours printOn: anOutputStream) cr. creatures := BGMall openMallWith: secondTestColours forNumberOfMeets: number. (self generateReportFor: creatures printOn: anOutputStream) cr; cr. ^ lastSum! ! !BGMall class methodsFor: 'accessing'! units ^Units! ! !BGMeetingPlace methodsFor: 'initialize-release'! initialize mutex := Semaphore forMutualExclusion. total := 0! ! !BGMeetingPlace methodsFor: 'running'! max: maxMeetings max := maxMeetings! ! !BGMeetingPlace methodsFor: 'running'! organizeMeetingWith: second total >= max ifTrue: [ first fade. second fade ] ifFalse: [ first met: second color. second met: first color ]. total := total + 1! ! !BGMeetingPlace methodsFor: 'running'! reachedBy: chameleon mutex critical: [ first isNil ifTrue: [ first := chameleon ] ifFalse: [ self organizeMeetingWith: chameleon. first := nil ] ]! ! !BGMeetingPlace class methodsFor: 'instance creation'! forMeetings: maxMeetings ^super new initialize; max: maxMeetings; yourself! ! !BGNBody class methodsFor: 'defaults' stamp: 'StefanMarr 5/15/2011 23:36'! defaultProblemSize ^ 1000! ! !BGNBody class methodsFor: 'benchmark scripts' stamp: 'sm 6/1/2011 14:09'! nbody: times "self nbody: 1000" | bodies | self flag: 'Move the output that is currently in un-executed blocks into some reporter functionality'. bodies := BGNBodySystem new initialize. [ ScriptConsole print: bodies energy. ]. times timesRepeat: [bodies after: 0.01d0]. [ ScriptConsole print: bodies energy. ]. ^ bodies energy! ! !BGNBodySystem methodsFor: 'nbody'! after: dt 1 to: bodies size do: [:i| i+1 to: bodies size do: [:j| (bodies at: i) and: (bodies at: j) velocityAfter: dt]. ]. bodies do: [:each| each positionAfter: dt]! ! !BGNBodySystem methodsFor: 'nbody'! energy | e | e := 0.0d0. 1 to: bodies size do: [:i| e := e + (bodies at: i) kineticEnergy. i+1 to: bodies size do: [:j| e := e - ((bodies at: i) potentialEnergy: (bodies at: j))]. ]. ^e! ! !BGNBodySystem methodsFor: 'initialize-release' stamp: 'StefanMarr 5/15/2011 12:13'! initialize bodies := OrderedCollection new add: BGBody sun; add: BGBody jupiter; add: BGBody saturn; add: BGBody uranus; add: BGBody neptune; yourself. bodies first offsetMomentum: (bodies inject: (Array with: 0.0d0 with: 0.0d0 with: 0.0d0) into: [:m :each | each addMomentumTo: m])! ! !BGPair methodsFor: 'initialize-release'! initialize "Initialize a newly created instance. This method must answer the receiver." partner := nil. me := nil. sema := Semaphore new. ^self! ! !BGPair methodsFor: 'initialize-release'! release partner:=nil.! ! !BGPair methodsFor: 'initialize-release'! signal sema signal! ! !BGPair methodsFor: 'initialize-release'! wait sema wait! ! !BGPair methodsFor: 'accessing'! me ^me! ! !BGPair methodsFor: 'accessing'! me: anObject me := anObject! ! !BGPair methodsFor: 'accessing'! partner ^partner! ! !BGPair methodsFor: 'accessing'! partner: anObject partner := anObject! ! !BGPair class methodsFor: 'instance creation'! new "Answer a newly created and initialized instance." ^super new initialize.! ! !BGPair class methodsFor: 'instance creation'! with: me "Answer a newly created and initialized instance." self halt. ^super new initialize me: me! ! !BGPermGeneratorRedux methodsFor: 'accessing'! atEnd ^atEnd! ! !BGPermGeneratorRedux methodsFor: 'accessing'! next | result | result := perm copy. self makeNext. ^result! ! !BGPermGeneratorRedux methodsFor: 'initialize-release' stamp: 'StefanMarr 1/16/2011 22:01'! initialize: size perm := (1 to: size) asArray. timesRotated := Array new: size withAll: 0. atEnd := false.! ! !BGPermGeneratorRedux methodsFor: 'initialize-release'! makeNext | temp remainder | "* Generate the next permutation. *" 2 to: perm size do: [ :r | "* Rotate the first r items to the left. *" temp := perm at: 1. 1 to: r - 1 do: [ :i | perm at: i put: (perm at: i + 1) ]. perm at: r put: temp. remainder := timesRotated at: r put: ((timesRotated at: r) + 1) \\ r. remainder = 0 ifFalse: [ ^self ]. "* After r rotations, the first r items are in their original positions. Go on rotating the first r+1 items. *" ]. "* We are past the final permutation. *" atEnd := true! ! !BGPermGeneratorRedux methodsFor: 'benchmarks' stamp: 'StefanMarr 6/15/2010 13:31'! maxPfannkuchenTo: output | max permutation checksum permCount flipsCount | max := 0. permCount := 0. checksum := 0. [self atEnd] whileFalse: [permutation := self next. permCount := permCount + 1. (permCount = 1048576) ifTrue: [permCount := 0]. flipsCount := self pfannkuchen: permutation. checksum := permCount odd ifTrue: [checksum+flipsCount] ifFalse: [checksum-flipsCount]. max := max max: flipsCount]. output print: checksum; cr. ^max! ! !BGPermGeneratorRedux methodsFor: 'benchmarks' stamp: 'StefanMarr 6/15/2010 13:30'! pfannkuchen: anArray | first complement a b k | k := 0. [ (first := anArray at: 1) == 1 ] whileFalse: [ k := k + 1. complement := first + 1. 1 to: first // 2 do: [ :i | a := anArray at: i. b := anArray at: complement - i. anArray at: i put: b. anArray at: complement - i put: a. ] ]. ^k! ! !BGPermGeneratorRedux class methodsFor: 'instance creation'! new: size ^self new initialize: size; yourself! ! !BGRandomNumber methodsFor: 'accessing'! next seed := (seed * Multiplier + Increment) \\ Modulus. ^(seed * scale) / FModulus! ! !BGRandomNumber methodsFor: 'private'! to: anInteger seed := 42. scale := anInteger! ! !BGRandomNumber class methodsFor: 'class initialization'! initialize FModulus := 139968.0d0. Increment := 29573. Modulus := 139968. Multiplier := 3877.! ! !BGRandomNumber class methodsFor: 'initialize-release'! to: anInteger ^self basicNew to: anInteger! ! !BGRandomStream methodsFor: 'accessing'! next | r | r := random next. repeatPtr := repeatPtr + 1. 1 to: percentages size do: [:i| (r < (percentages at: i)) ifTrue: [^collection at: i]]! ! !BGRandomStream methodsFor: 'accessing'! random: aRandomNumber "* Share the random number generator so we can get the expected results. *" random := aRandomNumber! ! !BGRandomStream methodsFor: 'initialize-release' stamp: 'StefanMarr 5/15/2011 12:19'! on: aCollection | size cp | repeatPtr := 0. random := BGRandomNumber to: 1.0d0. size := aCollection size. percentages := Array new: size. collection := Array new: size. cp := 0.0d0. 1 to: size do: [:i| collection at: i put: (aCollection at: i) first. percentages at: i put: (cp := cp + (aCollection at: i) last). ]! ! !BGRepeatStream methodsFor: 'testing'! atEnd ^repeatPtr >= repeatLimit! ! !BGRepeatStream methodsFor: 'accessing'! next position >= readLimit ifTrue: [ self position: 0 ]. repeatPtr := repeatPtr + 1. ^collection at: (position := position + 1)! ! !BGRepeatStream methodsFor: 'initialize-release'! to: anInteger repeatPtr := 0. repeatLimit := anInteger! ! !BGRepeatStream class methodsFor: 'instance creation'! to: anInteger on: aCollection ^(super on: aCollection) to: anInteger! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 14:06'! testBinaryTrees | bench output expected | bench := BGBinaryTrees new. output := (TextStream with: String new). self assert: -1 equals: (bench binarytrees: 10 to: output). expected := 'stretch tree of depth 11 check: -1 2048 trees of depth 4 check: -2048 512 trees of depth 6 check: -512 128 trees of depth 8 check: -128 32 trees of depth 10 check: -32 long lived tree of depth 10 check: -1 '. self assert: expected equals: output contents.! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 14:08'! testBinaryTreesResult | bench output | bench := BGBinaryTrees new. output := (TextStream with: String new). self assert: -1 equals: (bench binarytrees: 9 to: output). output := (TextStream with: String new). self assert: -1 equals: (bench binarytrees: 8 to: output). output := (TextStream with: String new). self assert: -1 equals: (bench binarytrees: 7 to: output). ! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 18:03'! testChameleons self assert: (BGChameleons chameneos: 100) equals: 200. self assert: (BGChameleons chameneos: 10000) equals: 20000. self assert: (BGChameleons chameneos: 1000000) equals: 2000000.! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 18:03'! testChameneosRedux | report result | report := TextStream with: String new. result := BGMall runBenchMark: 600 on: report. self assert: result equals: 1200. report := TextStream with: String new. result := BGMall runBenchMark: 555 on: report. self assert: result equals: (555 * 2). report := TextStream with: String new. result := BGMall runBenchMark: 121 on: report. self assert: result equals: (121 * 2). ! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 12:15'! testFannkuchReduxResult | f | f := BGFannkuchRedux fannkuchRedux: 7 to: (TextStream with: String new). self assert: f equals: 16! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 18:07'! testFasta | result | self flag: 'TODO: add proper verification'. self shouldnt: [result := BGFasta fasta] raise: Error. self assert: (result size > 0). self assert: (result isKindOf: String). ! ! !BGTests methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/15/2011 18:04'! testNBody self assert: (((BGNBody nbody: 1000) asString) beginsWith: '-0.169087605')! ! !BGTreeNode methodsFor: 'accessing'! itemCheck ^left isNil ifTrue: [item] ifFalse: [item + (left itemCheck - right itemCheck)]! ! !BGTreeNode methodsFor: 'initialize-release'! left: leftChild right: rightChild item: anItem left := leftChild. right := rightChild. item := anItem! ! !BGTreeNode class methodsFor: 'instance creation'! bottomUpTree: anItem depth: anInteger ^(anInteger > 0) ifTrue: [ self left: (self bottomUpTree: 2*anItem - 1 depth: anInteger - 1) right: (self bottomUpTree: 2*anItem depth: anInteger - 1) item: anItem ] ifFalse: [self left: nil right: nil item: anItem]! ! !BGTreeNode class methodsFor: 'instance creation'! left: leftChild right: rightChild item: anItem ^(super new) left: leftChild right: rightChild item: anItem! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 6/16/2002 15:36'! nextImage | colors | stream binary. self readHeader. biBitCount = 24 ifTrue:[^self read24BmpFile]. "read the color map" colors := self readColorMap. ^self readIndexedBmpFile: colors! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:48'! read24BmpFile "Read 24-bit pixel data from the given a BMP stream." | form formBits pixelLine bitsIndex bitBlt | form _ Form extent: biWidth@biHeight depth: 32. pixelLine := ByteArray new: (((24 * biWidth) + 31) // 32) * 4. bitsIndex := form height - 1 * biWidth + 1. formBits := form bits. 1 to: biHeight do: [:i | pixelLine := stream nextInto: pixelLine. self read24BmpLine: pixelLine into: formBits startingAt: bitsIndex width: biWidth. bitsIndex := bitsIndex - biWidth. ]. bitBlt := BitBlt toForm: form. bitBlt combinationRule: 7 "bitOr:with:". bitBlt halftoneForm: (Bitmap with: 16rFF000000). bitBlt copyBits. ^ form ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:47'! read24BmpLine: pixelLine into: formBits startingAt: formBitsIndex width: width | pixIndex rgb bitsIndex | pixIndex _ 0. "pre-increment" bitsIndex := formBitsIndex-1. "pre-increment" 1 to: width do: [:j | rgb := (pixelLine at: (pixIndex := pixIndex+1)) + ((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 8) + ((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 16). formBits at: (bitsIndex := bitsIndex+1) put: rgb. ]. ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/24/2005 20:57'! readColorMap "Read colorCount BMP color map entries from the given binary stream. Answer an array of Colors." | colorCount colors maxLevel b g r ccStream | colorCount _ (bfOffBits - 54) // 4. "Note: some programs (e.g. Photoshop 4.0) apparently do not set colorCount; assume that any data between the end of the header and the start of the pixel data is the color map" biBitCount >= 16 ifTrue:[^nil]. colorCount = 0 ifTrue: [ "this BMP file does not have a color map" "default monochrome color map" biBitCount = 1 ifTrue: [^ Array with: Color white with: Color black]. "default gray-scale color map" maxLevel _ (2 raisedTo: biBitCount) - 1. ^ (0 to: maxLevel) collect: [:level | Color gray: (level asFloat / maxLevel)]]. ccStream := ReadStream on: (stream next: colorCount*4). colors _ Array new: colorCount. 1 to: colorCount do: [:i | b _ ccStream next. g _ ccStream next. r _ ccStream next. ccStream next. "skip reserved" colors at: i put: (Color r: r g: g b: b range: 255)]. ^ colors ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 6/16/2002 15:20'! readHeader | reserved | bfType _ stream nextLittleEndianNumber: 2. bfSize _ stream nextLittleEndianNumber: 4. reserved _ stream nextLittleEndianNumber: 4. bfOffBits _ stream nextLittleEndianNumber: 4. biSize _ stream nextLittleEndianNumber: 4. biWidth _ stream nextLittleEndianNumber: 4. biHeight _ stream nextLittleEndianNumber: 4. biPlanes _ stream nextLittleEndianNumber: 2. biBitCount _ stream nextLittleEndianNumber: 2. biCompression _ stream nextLittleEndianNumber: 4. biSizeImage _ stream nextLittleEndianNumber: 4. biXPelsPerMeter _ stream nextLittleEndianNumber: 4. biYPelsPerMeter _ stream nextLittleEndianNumber: 4. biClrUsed _ stream nextLittleEndianNumber: 4. biClrImportant _ stream nextLittleEndianNumber: 4. ! ! !BMPReadWriter methodsFor: 'reading' stamp: 'ar 10/25/2005 13:45'! readIndexedBmpFile: colors "Read uncompressed pixel data of depth d from the given BMP stream, where d is 1, 4, 8, or 16" | form bytesPerRow pixelData pixelLine startIndex map bitBlt mask | colors ifNil:[form _ Form extent: biWidth@biHeight depth: biBitCount] ifNotNil:[form _ ColorForm extent: biWidth@biHeight depth: biBitCount. form colors: colors]. bytesPerRow _ (((biBitCount* biWidth) + 31) // 32) * 4. pixelData _ ByteArray new: bytesPerRow * biHeight. biHeight to: 1 by: -1 do: [:y | pixelLine _ stream next: bytesPerRow. startIndex _ ((y - 1) * bytesPerRow) + 1. pixelData replaceFrom: startIndex to: startIndex + bytesPerRow - 1 with: pixelLine startingAt: 1]. form bits copyFromByteArray: pixelData. biBitCount = 16 ifTrue:[ map := ColorMap shifts: #(8 -8 0 0) masks: #(16rFF 16rFF00 0 0). mask := 16r80008000. ]. biBitCount = 32 ifTrue:[ map := ColorMap shifts: #(24 8 -8 -24) masks: #(16rFF 16rFF00 16rFF0000 16rFF000000). mask := 16rFF000000. ]. map ifNotNil:[ bitBlt := BitBlt toForm: form. bitBlt sourceForm: form. bitBlt colorMap: map. bitBlt combinationRule: Form over. bitBlt copyBits. ]. mask ifNotNil:[ bitBlt := BitBlt toForm: form. bitBlt combinationRule: 7 "bitOr:with:". bitBlt halftoneForm: (Bitmap with: mask). bitBlt copyBits. ]. ^ form ! ! !BMPReadWriter methodsFor: 'testing' stamp: 'ar 6/16/2002 15:27'! understandsImageFormat stream size < 54 ifTrue:[^false]. "min size = BITMAPFILEHEADER+BITMAPINFOHEADER" self readHeader. bfType = 19778 "BM" ifFalse:[^false]. biSize = 40 ifFalse:[^false]. biPlanes = 1 ifFalse:[^false]. bfSize <= stream size ifFalse:[^false]. biCompression = 0 ifFalse:[^false]. ^true! ! !BMPReadWriter methodsFor: 'writing' stamp: 'yo 2/18/2004 17:57'! nextPutImage: aForm | bhSize rowBytes rgb data colorValues depth image ppw scanLineLen | depth := aForm depth. [#(1 4 8 32) includes: depth] whileFalse:[depth := depth + 1 asLargerPowerOfTwo]. image := aForm asFormOfDepth: depth. image unhibernate. bhSize _ 14. "# bytes in file header" biSize _ 40. "info header size in bytes" biWidth := image width. biHeight := image height. biClrUsed _ depth = 32 ifTrue: [0] ifFalse:[1 << depth]. "No. color table entries" bfOffBits _ biSize + bhSize + (4*biClrUsed). rowBytes _ ((depth min: 24) * biWidth + 31 // 32) * 4. biSizeImage _ biHeight * rowBytes. "Write the file header" stream position: 0. stream nextLittleEndianNumber: 2 put: 19778. "bfType = BM" stream nextLittleEndianNumber: 4 put: bfOffBits + biSizeImage. "Entire file size in bytes" stream nextLittleEndianNumber: 4 put: 0. "bfReserved" stream nextLittleEndianNumber: 4 put: bfOffBits. "Offset of bitmap data from start of hdr (and file)" "Write the bitmap info header" stream position: bhSize. stream nextLittleEndianNumber: 4 put: biSize. "info header size in bytes" stream nextLittleEndianNumber: 4 put: image width. "biWidth" stream nextLittleEndianNumber: 4 put: image height. "biHeight" stream nextLittleEndianNumber: 2 put: 1. "biPlanes" stream nextLittleEndianNumber: 2 put: (depth min: 24). "biBitCount" stream nextLittleEndianNumber: 4 put: 0. "biCompression" stream nextLittleEndianNumber: 4 put: biSizeImage. "size of image section in bytes" stream nextLittleEndianNumber: 4 put: 2800. "biXPelsPerMeter" stream nextLittleEndianNumber: 4 put: 2800. "biYPelsPerMeter" stream nextLittleEndianNumber: 4 put: biClrUsed. stream nextLittleEndianNumber: 4 put: 0. "biClrImportant" biClrUsed > 0 ifTrue: [ "write color map; this works for ColorForms, too" colorValues _ image colormapIfNeededForDepth: 32. 1 to: biClrUsed do: [:i | rgb _ colorValues at: i. 0 to: 24 by: 8 do: [:j | stream nextPut: (rgb >> j bitAnd: 16rFF)]]]. depth < 32 ifTrue: [ "depth = 1, 4 or 8." data _ image bits asByteArray. ppw _ 32 // depth. scanLineLen _ biWidth + ppw - 1 // ppw * 4. "# of bytes in line" 1 to: biHeight do: [:i | stream next: scanLineLen putAll: data startingAt: (biHeight-i)*scanLineLen+1. ]. ] ifFalse: [ 1 to: biHeight do:[:i | data _ (image copy: (0@(biHeight-i) extent: biWidth@1)) bits. 1 to: data size do: [:j | stream nextLittleEndianNumber: 3 put: (data at: j)]. 1 to: (data size*3)+3//4*4-(data size*3) do: [:j | stream nextPut: 0 "pad to 32-bits"] ]. ]. stream position = (bfOffBits + biSizeImage) ifFalse: [self error:'Write failure']. stream close.! ! !BMPReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('bmp')! ! !BMPReadWriter class methodsFor: 'testing' stamp: 'ar 6/16/2002 18:55'! displayAllFrom: fd "BMPReadWriter displayAllFrom: FileDirectory default" fd fileNames do:[:fName| (fName endsWith: '.bmp') ifTrue:[ [(Form fromBinaryStream: (fd readOnlyFileNamed: fName)) display. Display forceDisplayUpdate] on: Error do:[:nix|]. ]. ]. fd directoryNames do:[:fdName| self displayAllFrom: (fd directoryNamed: fdName) ].! ! !BMPReadWriter class methodsFor: 'testing' stamp: 'ar 6/16/2002 18:56'! readAllFrom: fd "MessageTally spyOn:[BMPReadWriter readAllFrom: FileDirectory default]" fd fileNames do:[:fName| (fName endsWith: '.bmp') ifTrue:[ [Form fromBinaryStream: (fd readOnlyFileNamed: fName)] on: Error do:[:nix]. ]. ]. fd directoryNames do:[:fdName| self readAllFrom: (fd directoryNamed: fdName) ].! ! !BadEqualer methodsFor: 'comparing' stamp: 'mjr 8/20/2003 18:56'! = other self class = other class ifFalse: [^ false]. ^ 100 atRandom < 30 ! ! !BadEqualer commentStamp: 'mjr 8/20/2003 13:28' prior: 0! I am an object that doesn't always report #= correctly. Used for testing the EqualityTester.! !BadHasher methodsFor: 'comparing' stamp: 'mjr 8/20/2003 18:56'! hash "answer with a different hash some of the time" 100 atRandom < 30 ifTrue: [^ 1]. ^ 2! ! !BadHasher commentStamp: 'mjr 8/20/2003 13:28' prior: 0! I am an object that doesn't always hash correctly. I am used for testing the HashTester.! !Behavior methodsFor: 'accessing' stamp: 'ssa 9/2/2009 17:59'! setInstanceFormat: sizeAndFlags "Set the format for the receiver (a Class)." format _ sizeAndFlags! ! !Behavior methodsFor: 'printing' stamp: 'ssa 10/25/2008 20:48'! archiveVersion "This is the daefault version number for an archived instance of any class. Version 1 was back when each class was responsible for its own archiving. Version 2 uses the default archiving behavior in object (see Object>archiveOn: and Object class>dearchive:from:)." ^1! ! !Behavior methodsFor: 'printing' stamp: 'ads 1/24/2011 13:02'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables. But, not useful for a class with a method dictionary." aStream nextPutAll: (RVMPrimitivesNeededForBootstrapping printPrefixFor: self). aStream nextPutAll: '<<too complex to show>>'; cr.! ! !Behavior methodsFor: 'compiling' stamp: 'ssa 9/3/2008 12:19'! compile: code notifying: requestor trailer: trailingBytes "Compile the argument, code, as source code in the context of the receiver and insEtall the result in the receiver's method dictionary. The second argument, requestor, is to be notified if an error occurs. The argument code is either a string or an object that converts to a string or a PositionableStream. This method also saves the source code." | methodAndNode | methodAndNode := self basicCompile: code "a Text" notifying: requestor trailer: trailingBytes ifFail: [^nil]. methodAndNode method putSource: code fromParseNode: methodAndNode node inFile: 2 withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr]. self addSelector: methodAndNode selector withMethod: methodAndNode method notifying: requestor. ^ methodAndNode selector! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'ssa 10/8/2008 15:47'! allSubclasses "Answer a Set of the receiver's and the receiver's descendent's subclasses. " | scan scanTop | scan _ OrderedCollection withAll: self subclasses. scanTop _ 1. [scanTop > scan size] whileFalse: [scan addAll: (scan at: scanTop) subclasses. scanTop _ scanTop + 1]. ^ scan "asSet"! ! !Behavior methodsFor: 'accessing class hierarchy' stamp: 'ssa 10/8/2008 16:02'! withAllSubclasses "Answer a Set of the receiver, the receiver's descendent's, and the receiver's descendent's subclasses." | subs | subs _ self allSubclasses. subs addFirst: self. ^subs! ! !Behavior methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:46'! subobjects ^self subclasses! ! !Benchmark methodsFor: 'load and popStore'! testLoadInstVar dummy _ 1. self test: [dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. dummy == dummy. nil] labeled: 'load an instance variable, 20 times' repeated: 10000 "Benchmark new testLoadInstVar"! ! !Benchmark methodsFor: 'load and popStore'! testLoadLiteralIndirect self test: [Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. Point == Point. nil] labeled: 'load literal indirect (overflow refct), 20 times' repeated: 10000 "Benchmark new testLoadLiteralIndirect"! ! !Benchmark methodsFor: 'load and popStore'! testLoadLiteralNRef self test: [3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. 3 == 3. nil] labeled: 'load nonRefcounted literal, 20 times' repeated: 10000 "Benchmark new testLoadLiteralNRef"! ! !Benchmark methodsFor: 'load and popStore'! testLoadQuickConstant self test: [1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. 1 == 1. nil] labeled: 'load 1, 40 times; send ==, 20 times' repeated: 10000 "Benchmark new testLoadQuickConstant"! ! !Benchmark methodsFor: 'load and popStore'! testLoadTempNRef | temp | temp _ 1. self test: [temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. nil] labeled: 'load 1 as a temp, 20 times' repeated: 10000 "Benchmark new testLoadTempNRef"! ! !Benchmark methodsFor: 'load and popStore'! testLoadTempRef | temp | temp _ 0@0. self test: [temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. temp == temp. nil] labeled: 'load 0@0, 20 times' repeated: 10000 "Benchmark new testLoadTempRef"! ! !Benchmark methodsFor: 'load and popStore'! testPopStoreInstVar self test: [dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. dummy _ 1. nil] labeled: 'store into an instance variable, 20 times' repeated: 10000 "Benchmark new testPopStoreInstVar"! ! !Benchmark methodsFor: 'load and popStore'! testPopStoreTemp | temp | self test: [temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. temp _ 1. nil] labeled: 'store into a temp, 20 times' repeated: 10000 "Benchmark new testPopStoreTemp"! ! !Benchmark methodsFor: 'arithmetic'! test16bitArith | twentyK | twentyK _ 20000. self test: [twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. twentyK+twentyK. nil] labeled: 'add 20000 + 20000, 10 times' repeated: 1000 "Benchmark new test16bitArith"! ! !Benchmark methodsFor: 'arithmetic'! test3div4 self test: [3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. 3//4. nil] labeled: 'divide 3 by 4, 10 times' repeated: 1000 "Benchmark new test3div4"! ! !Benchmark methodsFor: 'arithmetic'! test3lessThan4 self test: [3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. 3<4. nil] labeled: 'test 3 < 4, 10 times' repeated: 10000 "Benchmark new test3lessThan4"! ! !Benchmark methodsFor: 'arithmetic'! test3plus4 self test: [3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. 3+4. nil] labeled: 'add 3 + 4, 10 times' repeated: 10000 "Benchmark new test3plus4"! ! !Benchmark methodsFor: 'arithmetic'! test3times4 self test: [3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. 3*4. nil] labeled: 'multiply 3 * 4, 10 times' repeated: 10000 "Benchmark new test3times4"! ! !Benchmark methodsFor: 'arithmetic'! testLargeIntArith | eightyK | eightyK _ 80000. self test: [eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. eightyK+eightyK. nil] labeled: 'add 80000 + 80000, 10 times' repeated: 100 "Benchmark new testLargeIntArith"! ! !Benchmark methodsFor: 'control'! testActivationReturn self test: [self recur: 14] labeled: 'activate and return, 32K times' repeated: 1 "Benchmark new testActivationReturn"! ! !Benchmark methodsFor: 'control'! testShortBranch self test: [false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. false ifTrue: [1] ifFalse: [2]. nil] labeled: 'short branch on false, 10 times' repeated: 10000 "Benchmark new testShortBranch"! ! !Benchmark methodsFor: 'control'! testWhileLoop | temp | self test: [temp _ 10000. [temp > 0] whileTrue: [temp _ temp - 1]. nil] labeled: 'simple whileLoop, 10000 times through' repeated: 10 "Benchmark new testWhileLoop"! ! !Benchmark methodsFor: 'arrays and strings'! testArrayAt | array index | array _ #(1 2 3 4 5 6). index _ 4. self test: [array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. array at: index. nil] labeled: 'send #at: 20 times (to an array)' repeated: 1000 "Benchmark new testArrayAt"! ! !Benchmark methodsFor: 'arrays and strings'! testArrayAtPut | array index element | array _ #(1 2 3 4 5 6). index _ 4. element _ 17. self test: [array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. array at: index put: element. nil] labeled: 'send #at:put: 20 times (to an array)' repeated: 1000 "Benchmark new testArrayAtPut"! ! !Benchmark methodsFor: 'arrays and strings'! testSize | string | string _ 'abcde'. self test: [string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. string size. nil] labeled: 'send #size 20 times (to a string)' repeated: 1000 "Benchmark new testSize"! ! !Benchmark methodsFor: 'arrays and strings'! testStringAt | string index | string _ 'abcdefg'. index _ 4. self test: [string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. string at: index. nil] labeled: 'send #at: 20 times (to a string)' repeated: 1000 "Benchmark new testStringAt"! ! !Benchmark methodsFor: 'arrays and strings'! testStringAtPut | string index char | string _ 'abcdefg'. index _ 4. char _ $q. self test: [string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. string at: index put: char. nil] labeled: 'send #at:put: 20 times (to a string)' repeated: 1000 "Benchmark new testStringAtPut"! ! !Benchmark methodsFor: 'primitive byte codes'! testBlockCopy | tC | tC _ thisContext. self test: [tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. tC blockCopy: 0. nil] labeled: 'execute blockCopy: 0, 20 times' repeated: 1000 "Benchmark new testBlockCopy"! ! !Benchmark methodsFor: 'primitive byte codes'! testClass | pt | pt _ 0@0. self test: [pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. pt class. nil] labeled: 'send #class 20 times (to a point)' repeated: 1000 "Benchmark new testClass"! ! !Benchmark methodsFor: 'primitive byte codes'! testCreation self test: [Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. Point new. nil] labeled: 'create 20 uninitialized points' repeated: 1000 "Benchmark new testCreation"! ! !Benchmark methodsFor: 'primitive byte codes'! testEQ | temp | temp _ 1. self test: [temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp == temp. nil] labeled: 'send ==, 20 times' repeated: 10000 "Benchmark new testEQ"! ! !Benchmark methodsFor: 'primitive byte codes'! testLoadThisContext self test: [thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. thisContext == thisContext. nil] labeled: 'load thisContext, 20 times' repeated: 10000 "Benchmark new testLoadThisContext"! ! !Benchmark methodsFor: 'primitive byte codes'! testPointCreation self test: [3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. 3@4. nil] labeled: 'create 3@4, 10 times' repeated: 1000 "Benchmark new testPointCreation"! ! !Benchmark methodsFor: 'primitive byte codes'! testPointX | pt | pt _ 0@0. self test: [pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. pt x. nil] labeled: 'execute aPoint x, 10 times' repeated: 10000 "Benchmark new testPointX"! ! !Benchmark methodsFor: 'primitive byte codes'! testStreamNext | strm | strm _ ReadStream on: 'abcdefghijklmnopqrstuvwxyz'. self test: [strm position: 0. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. strm next. nil] labeled: 'execute ReadStream next, 20 times' repeated: 1000 "Benchmark new testStreamNext"! ! !Benchmark methodsFor: 'primitive byte codes'! testStreamNextPut | strm ch | strm _ ReadWriteStream on: 'abcdefghijklmnopqrstuvwxyz'. ch _ $q. self test: [strm position: 0. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. strm nextPut: ch. nil] labeled: 'execute ReadWriteStream nextPut:, 20 times' repeated: 1000 "Benchmark new testStreamNextPut"! ! !Benchmark methodsFor: 'primitive byte codes'! testValue | block | block _ [3+4]. self test: [block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. block value. nil] labeled: 'evaluate the block: (3+4), 20 times' repeated: 1000 "Benchmark new testValue"! ! !Benchmark methodsFor: 'primitive methods'! testAsFloat self test: [1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. 1 asFloat. nil] labeled: 'convert 1 to floating point, 20 times' repeated: 100 "Benchmark new testAsFloat"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:08'! testBasicAt | coll index | coll _ Array new: 16. index _ 5. self test: [coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. coll basicAt: index. nil] labeled: 'send #basicAt: 20 times (to an array)' repeated: 1000 "Benchmark new testBasicAt"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:09'! testBasicAtPut | coll index element | coll _ Array new: 16. index _ 5. element _ 17. self test: [coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. coll basicAt: index put: element. nil] labeled: 'send #basicAtPut: 20 times (to a set)' repeated: 1000 "Benchmark new testBasicAtPut"! ! !Benchmark methodsFor: 'primitive methods'! testBitBLT | bLTer | bLTer _ self sampleBitBLT. self test: [bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. bLTer copyBits. nil] labeled: 'call bitBLT 10 times' repeated: 10 "Benchmark new testBitBLT"! ! !Benchmark methodsFor: 'primitive methods'! testFloatingPointAddition | a b | a _ 3.1. b _ 4.1. self test: [a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. a+b. nil] labeled: 'add 3.1 plus 4.1, 20 times' repeated: 100 "Benchmark new testFloatingPointAddition"! ! !Benchmark methodsFor: 'primitive methods'! testPerform self test: [3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. 3 perform: #+ with: 4. nil] labeled: '3 perform: #+ with: 4, 20 times' repeated: 1000 "Benchmark new testPerform"! ! !Benchmark methodsFor: 'primitive methods'! testStringReplace | source sink size | source _ self longishString copy. sink _ source copy. size _ sink size. self test: [sink replaceFrom: 1 to: size with: source startingAt: 1. nil] labeled: 'replace characters in a string' repeated: 100 "Benchmark new testStringReplace"! ! !Benchmark methodsFor: 'primitive methods' stamp: 'ssa 8/19/2008 21:51'! testTextScanning | clipRect para range scanner stops | "clipRect _ Display boundingBox. para _ Paragraph withText: 'Hi there, folks' asText. range _ 1 to: para numberOfLines. scanner _ DisplayScanner new. scanner displayLines: range in: para clippedBy: clipRect. stops _ scanner instVarAt: 17." self test: ["scanner destX: 0. scanner scanCharactersFrom: 1 to: 16 in: 'Hi there, folks!!' rightX: 400 stopConditions: stops displaying: true"] labeled: 'DISABLED scan characters (primitive text display)' repeated: 100 "Benchmark new testTextScanning"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:54'! testAllCallsOn self test: [SystemNavigation default allCallsOn: #printStringBase:] labeled: 'find all calls on #printStringBase:' repeated: 3 "Benchmark new testAllCallsOn"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:51'! testAllImplementors self test: [SystemNavigation default allImplementorsOf: #next] labeled: 'find all implementors of #next' repeated: 10 "Benchmark new testAllImplementors"! ! !Benchmark methodsFor: 'macro operations'! testClassOrganizer | class | class _ Benchmark. self test: [class organization changeFromString: class organization printString] labeled: 'read and write class organization' repeated: 1 "Benchmark new testClassOrganizer"! ! !Benchmark methodsFor: 'macro operations' stamp: 'dmu 1/1/2009 04:42'! testCompiler self test: [Benchmark compileBenchmark: 'dummy: aBlock repeated: nTimes | i emptyBlock emptyTime blockTime | nTimes > 1000 ifTrue: [^self time: aBlock repeatedK: nTimes // 1000]. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [emptyBlock value]]. blockTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [aBlock value]]. ^blockTime - emptyTime' notifying: nil ] labeled: 'compile dummy method' repeated: 5. Benchmark removeSelector: #dummy:repeated: "Benchmark new testCompiler"! ! !Benchmark methodsFor: 'macro operations'! testDecompiler | class | class _ InputSensor. self test: [class selectors do: [:sel | (Decompiler new decompile: sel in: class method: (class compiledMethodAt: sel)) decompileString]] labeled: 'decompile class InputSensor' repeated: 1 "Benchmark new testDecompiler"! ! !Benchmark methodsFor: 'macro operations' stamp: 'ssa 11/17/2008 22:57'! testMandala self test: [Pen new mandala: 30 diameter: 400] labeled: 'testing Mandala' repeated: 2 "Benchmark new testMandala"! ! !Benchmark methodsFor: 'macro operations'! testPrintDefinition | class | class _ Compiler. self test: [class definition] labeled: 'print a class definition' repeated: 20 "Benchmark new testPrintDefinition"! ! !Benchmark methodsFor: 'macro operations'! testPrintHierarchy | class | class _ InstructionStream. self test: [class printHierarchy] labeled: 'print a class hierarchy' repeated: 10 "Benchmark new testPrintHierarchy"! ! !Benchmark methodsFor: 'macro operations'! testTextDisplay | para | para _ Paragraph withText: self textForDisplay. para displayAt: 200@200. self test: [para displayAt: 200@200] labeled: 'display text' repeated: 10 "Benchmark new testTextDisplay"! ! !Benchmark methodsFor: 'macro operations'! testTextEditing | aStringHolderView editor selectPoint | aStringHolderView _ self favoriteStringHolderView. editor _ aStringHolderView controller. selectPoint _ 0. self test: [editor selectAt: (selectPoint _ selectPoint + 5). editor replaceSelectionWith: 'Now!! ' asText] labeled: 'text replacement and redisplay' repeated: 20. aStringHolderView release "Benchmark new testTextEditing"! ! !Benchmark methodsFor: 'macro operations'! testTextFormatting | aString aView contents | aString _ self stringForDisplay. aView _ StringHolderView container: StringHolder new. aView window: Display boundingBox viewport: (100@100 extent: 200@200). self test: [aView editString: (aString asText makeSelectorBoldIn: Benchmark) asParagraph] labeled: 'format a bunch of text' repeated: 5. aView release "Benchmark new testTextFormatting"! ! !Benchmark methodsFor: 'testing'! test: aBlock labeled: label repeated: nTimes "This is the main message to a Benchmark. aBlock is repeated nTimes, and the results are reported." | time | time _ self time: aBlock repeated: nTimes. self report: label timedAt: time repeated: nTimes! ! !Benchmark methodsFor: 'testing' stamp: 'ssa 8/19/2008 21:56'! testList: selectorList "This message allows you to test a series of benchmarks and record all the results on a file or stream." fromList _ true. self setOutputParameters. selectorList do: [:selector | self perform: selector]. reporting ifTrue: [self closeOutput: reportStream]. fromList _ false. "Benchmark new testList: #(testLoadInstVar testLoadLiteralIndirect testLoadLiteralNRef testLoadQuickConstant testLoadTempNRef)"! ! !Benchmark methodsFor: 'testing' stamp: 'ssa 8/19/2008 21:56'! testList: selectorList toFile: aFileStream "This message allows you to test a series of benchmarks and record all the results on a file or stream." fromList _ true. self fileOutputParameters: aFileStream. selectorList do: [:selector | self perform: selector. verboseTranscript ifTrue: []]. reporting ifTrue: [self closeOutput: reportStream]. fromList _ false. "Benchmark new testList: #(testLoadInstVar testLoadLiteralIndirect testLoadLiteralNRef testLoadQuickConstant testLoadTempNRef) toFile: (FileStream fileNamed: 'Smalltalk.timing')"! ! !Benchmark methodsFor: 'testing'! time: aBlock repeated10K: tenKTimes | i emptyBlock emptyTime blockTime | tenKTimes > 10000 ifTrue: [^self error: 'one hundred million repetitions is my limit']. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [1 to: tenKTimes do: [:j | i _ 0. [(i _ i + 1) <= 10000] whileTrue: [emptyBlock value]]]. blockTime _ Time millisecondsToRun: [1 to: tenKTimes do: [:j | i _ 0. [(i _ i + 1) <= 10000] whileTrue: [aBlock value]]]. ^blockTime - emptyTime! ! !Benchmark methodsFor: 'testing'! time: aBlock repeated: nTimes "Answer how many milliseconds it takes to repeat aBlock nTimes, corrected for the time to repeat an empty block." | i emptyBlock emptyTime blockTime iBox | nTimes > 10000 ifTrue: [^self time: aBlock repeated10K: nTimes // 10000]. emptyBlock _ []. emptyTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [emptyBlock value]]. blockTime _ Time millisecondsToRun: [i _ 0. [(i _ i + 1) <= nTimes] whileTrue: [aBlock value]]. ^blockTime - emptyTime! ! !Benchmark methodsFor: 'output'! clearOutputs "This allows you to get rid of your old accumulated output streams." Outputs _ nil "Benchmark new clearOutputs"! ! !Benchmark methodsFor: 'output'! closeOutput: aStream self streamsRatherThanFiles ifTrue: [aStream reset] ifFalse: [aStream close]! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:12'! compareOldTimes: oldName toNewTimes: newName outputTo: outName "Compare two sets of benchmark ouput reports." | oldDict newDict labels compareStream oldTime newTime | oldDict _ Dictionary new. newDict _ Dictionary new. labels _ OrderedCollection new. self readOutput: (self outputNamed: oldName) intoDict: oldDict andCollection: nil. self readOutput: (self outputNamed: newName) intoDict: newDict andCollection: labels. compareStream _ self makeOutputNamed: outName. labels do: [:label | (oldDict includesKey: label) ifTrue: [compareStream nextPutAll: label; cr; tab; nextPutAll: 'old time: ', (oldTime _ oldDict at: label) printString; tab; nextPutAll: 'new time: ', (newTime _ newDict at: label) printString; tab. oldTime = 0 ifTrue:[compareStream nextPutAll:'percent change: ERROR oldTime=0';cr;cr] ifFalse:[compareStream nextPutAll: 'percent change: ', (newTime - oldTime * 100.0 / oldTime) printString; cr; cr]]]. self closeOutput: compareStream "Benchmark new compareOldTimes: 'test1.timing' toNewTimes: 'test2.timing' outputTo: 'compare1-2.timing'" "Benchmark new displayOutputNamed: 'compare1-2.timing'"! ! !Benchmark methodsFor: 'output'! displayOutputNamed: name "Create a window on the display to view the contents of the named output. Does not allow editing of the output file or stream." | output contents | output _ self outputNamed: name. contents _ self streamsRatherThanFiles ifTrue: [output contents] ifFalse: [output contentsOfEntireFile]. StringHolderView open: (StringHolder new contents: contents) label: name! ! !Benchmark methodsFor: 'output'! makeOutputNamed: name "Create a new output file or stream of the given name." self streamsRatherThanFiles ifTrue: [Outputs == nil ifTrue: [Outputs _ Dictionary new]. Outputs at: name put: (ReadWriteStream on: (String new: 1000))]. ^self outputNamed: name! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:06'! outputNamed: name "Answer with the output file or stream of the given name." self streamsRatherThanFiles ifTrue: [^Outputs at: name] ifFalse: [^FileStream fileNamed: name]! ! !Benchmark methodsFor: 'output'! readOutput: aStream intoDict: aDict andCollection: aColl "Parse the output file or stream, aStream, putting labels and times in aDict. If aColl is non-nil (but rather an ordered collection), also add the labels to it in order." | leftBracket rightBracket tab space label value | leftBracket _ $[. rightBracket _ $]. tab _ $ . space _ $ . aStream upTo: leftBracket. [aStream atEnd] whileFalse: [label _ aStream upTo: rightBracket. aColl notNil ifTrue: [aColl add: label]. aStream next: 2; upTo: tab. value _ Number readFrom: (ReadStream on: (aStream upTo: space)). aDict at: label put: value. aStream upTo: leftBracket]. self closeOutput: aStream! ! !Benchmark methodsFor: 'output'! report: label timedAt: time repeated: numberOfTimes "Do all the reporting, both in the Transcript and on the output file or stream." | reportString | reportString _ self reportStringFor: label timedAt: time repeated: numberOfTimes. verboseTranscript ifTrue: [Transcript show: reportString] ifFalse: [Transcript show: ' [', label, ']']. reporting ifTrue: [reportStream nextPutAll: reportString. fromList ifFalse: [self closeOutput: reportStream]]! ! !Benchmark methodsFor: 'output'! reportStringFor: label timedAt: time repeated: numberOfTimes "Generate the parsible string to represent the measurement of a benchmark." | nTimes unitTime seconds aStream| aStream _ WriteStream on: (String new: 200). nTimes _ numberOfTimes <= 1000 ifTrue: [numberOfTimes] ifFalse: [numberOfTimes // 1000 * 1000]. seconds _ time asFloat / 1000. aStream cr; nextPutAll: 'Testing: [' , label , ']'; cr. aStream tab; print: nTimes; nextPutAll: ' repetition(s) in'; cr; tab; print: seconds; nextPutAll: ' seconds'; cr. nTimes ~= 1 ifTrue: [unitTime _ (time * 1000) asFloat / nTimes. aStream tab; print: unitTime; nextPutAll: ' microseconds per repetition'; cr]. ^aStream contents! ! !Benchmark methodsFor: 'output' stamp: 'ssa 8/19/2008 22:05'! streamsRatherThanFiles "Should the named outputs be (internal Smalltalk-80) streams rather than disk files? They should if there is no file system. Feel free to change this method if you have a file system but want streams anyway." ^false! ! !Benchmark methodsFor: 'instance initialization'! defaultOutputParameters reporting _ false. verboseTranscript _ true. fromList _ false! ! !Benchmark methodsFor: 'instance initialization'! fileOutputParameters: aFileStream reporting _ true. reportStream _ aFileStream. verboseTranscript _ false! ! !Benchmark methodsFor: 'instance initialization' stamp: 'ssa 8/19/2008 22:24'! setOutputParameters | answer | BinaryChoice message: 'Would you like the transcript to just show labels, rather than full reports?' displayAt: Sensor mousePoint centered: true ifTrue: [verboseTranscript _ false] ifFalse: [verboseTranscript _ true]. BinaryChoice message: 'Should the full reports to be output (saved on a file or stream)?' displayAt: Sensor mousePoint centered: true ifTrue: [reporting _ true] ifFalse: [reporting _ false]. reporting ifTrue: [answer := FillInTheBlank request: 'Please supply desired output name' initialAnswer: '.timing' centerAt: Sensor mousePoint. answer isEmpty ifFalse:[reportStream _ self makeOutputNamed: answer] ifTrue:[reporting := false]]! ! !Benchmark methodsFor: 'private'! favoriteStringHolderView | aStringHolderView message | message _ self longishString. aStringHolderView _ StringHolderView container: (StringHolder new contents: message). aStringHolderView window: (0@0 extent: 300@200). aStringHolderView translateBy: 100@250. aStringHolderView display. ^aStringHolderView! ! !Benchmark methodsFor: 'private'! longishString ^ 'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.'! ! !Benchmark methodsFor: 'private'! recur: exp "Invokes a recursion involving ((2 raisedTo: exp+1) - 1) activations and returns." exp = 0 ifTrue: [^self]. self recur: exp - 1. ^self recur: exp - 1! ! !Benchmark methodsFor: 'private' stamp: 'ssa 8/19/2008 21:11'! sampleBitBLT ^BitBlt destForm: Display sourceForm: nil halftoneForm: Color black combinationRule: Form reverse destOrigin: 0@0 sourceOrigin: 0@0 extent: 400@400 clipRect: Display boundingBox! ! !Benchmark methodsFor: 'private'! stringForDisplay ^'testTextDisplay | clipRect para range scanner | clipRect _ Display boundingBox. para _ Paragraph withText: self textForDisplay. range _ 1 to: para numberOfLines. scanner _ DisplayScanner new. self test: [scanner displayLines: range in: para clippedBy: clipRect] labeled: ''displaying text'' repeated: 10 "Benchmark new testTextDisplay"'! ! !Benchmark methodsFor: 'private'! textForDisplay ^self stringForDisplay asText! ! !Benchmark commentStamp: 'ssa 8/19/2008 22:14' prior: 0! Benchmark testStandardToFile: (FileStream fileNamed: 'test1.timing'). Benchmark testStandardToFile: (FileStream fileNamed: 'test2.timing'). Benchmark new compareOldTimes: 'test1.timing' toNewTimes: 'test2.timing' outputTo: 'compare1-2.timing'. Benchmark new displayOutputNamed: 'compare1-2.timing' --------------original comment follows------------------------------- Class Benchmark contains facilities for timing the performance of your system and reporting the results. There are built-in methods for timing certain activities that occur frequently in using Smalltalk-80. There are also facilities for timing the execution of most byte codes. It is intended that comparison of timing information between implementations and over time will allow implementors to discover where their systems could stand improvement and to gauge the value of intended performance enhancements. The main interface to these facilities is through sending the messsage Benchmark new test: aBlock labeled: aLabel repeated: howManyTimes. This will cause howManyTimes executions of aBlock and report the results, using aLabel for ease of identification. The results can be reported in several different ways. The default is to print a fairly verbose report in the Transcript. But the reporting mode can be altered by sending the Benchmark which is going to perform a given test the message setOutputParameters. This gives you the option of directing the report to a file or an internal stream and also of shortening the feedback in the Transcript. The system automatically invites you to respecify the output parameters (e.g. naming a new output report file) whenever you test more than one thing at a time, using the message testList: (as in testStandardTests below). Try an example. To time your system's performance of simple addition, say Benchmark new test3plus4 or to time pushing an instance variable onto the stack, say Benchmark new testLoadInstVar. If you had wished to print the results on a file or internal stream, you could have said Benchmark new setOutputParameters testLoadInstVar. If you look at the code for these methods (e.g. testLoadInstVar), you will notice that it does a few things that you didn't want to time, such as sending the message ==, or popping things off the stack. This is to make the compiler happy or to keep the stack from overflowing. So you may want to subtract this stuff out. (Use systems of equations. Be clever!!) The message category "macro operations" contains methods for timing more involved activities such as compiling, decompiling, editing text, formatting text, etc. There is a message to class Benchmark which will invoke all the built-in benchmarks sequentially. Say Benchmark testStandardTests. There are also facilities for examining or automatically comparing the output files or streams generated by testing a bunch of benchmarks sequentially. See the "output" category. Be sure to read the comment to the streamsRatherThanFiles code. Have fun and share your results with a friend. ! !Benchmark class methodsFor: 'standard tests' stamp: 'ssa 8/19/2008 21:36'! setStandardTests "These are all the built-in benchmarks. Feel free to change if you add more or think some of these are useless. To just execute a few, use testList: directly." StandardTests _ #(testLoadInstVar testLoadTempNRef testLoadTempRef testLoadQuickConstant testLoadLiteralNRef testLoadLiteralIndirect testPopStoreInstVar testPopStoreTemp test3plus4 test3lessThan4 test3times4 test3div4 test16bitArith testLargeIntArith testActivationReturn testShortBranch testWhileLoop testArrayAt testArrayAtPut testStringAt testStringAtPut testSize testPointCreation testStreamNext testStreamNextPut testEQ testClass testBlockCopy testValue testCreation testPointX testLoadThisContext testBasicAt testBasicAtPut testPerform testStringReplace testAsFloat testFloatingPointAddition testBitBLT testTextScanning testClassOrganizer testPrintDefinition testPrintHierarchy testAllCallsOn testAllImplementors testCompiler testDecompiler testTextDisplay testTextFormatting testTextEditing )! ! !Benchmark class methodsFor: 'standard tests'! testStandardTests "This message allows you to test the default series of benchmarks and record all the results according to how you answer the interactive prompts." self setStandardTests. self new testList: StandardTests "Benchmark testStandardTests"! ! !Benchmark class methodsFor: 'standard tests'! testStandardToFile: aFileStream "This message allows you to test the default series of benchmarks and record all the results on the specified file or stream." self setStandardTests. self new testList: StandardTests toFile: aFileStream "Benchmark testStandardToFile: (FileStream fileNamed: 'Smalltalk.timing')"! ! !Benchmark class methodsFor: 'instance creation'! new ^super new defaultOutputParameters "Benchmark new inspect"! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:40'! compileBenchmark: text classified: cat notifying: requestor | stamp | stamp _ self acceptsLoggingOfCompilation ifTrue: [Utilities changeStamp] ifFalse: [nil]. ^ self compileBenchmark: text classified: cat withStamp: stamp notifying: requestor ! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:39'! compileBenchmark: text classified: cat withStamp: changeStamp notifying: requestor ^ self compile: text classified: cat withStamp: changeStamp notifying: requestor logSource: false! ! !Benchmark class methodsFor: 'compiler benchmark support' stamp: 'dmu 1/1/2009 04:41'! compileBenchmark: code notifying: requestor "Refer to the comment in Behavior|compile:notifying:." ^self compileBenchmark: code classified: ClassOrganizer default notifying: requestor! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 5/31/2011 15:27'! benchBinaryTrees | bench problemSize | bench := BGBinaryTrees new. problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGBinaryTrees defaultProblemSize ]. ^ bench binarytrees: problemSize to: (TextStream with: String new).! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 6/1/2011 14:01'! benchChameleons | result problemSize | problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGChameleons defaultProblemSize ]. result := BGChameleons chameneos: problemSize. "Result should be 2*numberOfProcesses (as far as I understand the benchmark)" self flag: 'TODO adapt once verification is supported'. result = (2 * problemSize) ifFalse: [ Error signal: (BGChameleons name, ' benchmark failed. Input: ', problemSize asString, ' Output: ', result asString). ].! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 6/1/2011 14:02'! benchChameneosRedux | result report problemSize | problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGChameneosRedux defaultProblemSize ]. report := TextStream with: String new. result := BGMall runBenchMark: problemSize on: report. "Result should be 2*problemSize" self flag: 'TODO: adapt once verification is supported'. result = (2 * problemSize) ifFalse: [ Error signal: self class name, ' benchmark failed. Input: ', runner processes asString, ' Output: ', result asString ].! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 6/1/2011 14:02'! benchFannkuchRedux | f problemSize | problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGFannkuchRedux defaultProblemSize ]. f := BGFannkuchRedux fannkuchRedux: problemSize to: (TextStream with: String new). " the output should only be done by some reporter" [ScriptConsole print: 'Pfannkuchen(', problemSize asString , ') = ', f asString.]. ^f! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 5/31/2011 15:28'! benchFasta | out problemSize | out := TextStream with: String new. problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGFasta defaultProblemSize ]. BGFasta fasta: problemSize to: out.! ! !BenchmarkGameSuite methodsFor: 'benchmarking' stamp: 'sm 5/31/2011 15:28'! benchNBody | problemSize | problemSize := self problemSize ifNotNil: [ self problemSize asInteger ] ifNil: [ BGNBody defaultProblemSize ]. BGNBody nbody: problemSize.! ! !BenchmarkGameSuite methodsFor: 'license' stamp: 'StefanMarr 5/15/2011 12:31'! license ^ 'Revised BSD license This is a specific instance of the Open Source Initiative (OSI) BSD license template http://www.opensource.org/licenses/bsd-license.php Copyright 2008-2010 Isaac Gouy All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of "The Computer Language Benchmarks Game" nor the name of "The Computer Language Shootout Benchmarks" nor the name "nanobench" nor the name "bencher" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'! ! !BinaryChoice class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 21:47'! message: aString displayAt: aPoint centered: aBoolean ifTrue: trueBlock ifFalse: falseBlock "Mimic the old BinaryChoice protocol. Canceling the menu by clicking outside executes false block" | answer | answer := PopUpMenu withCaption: aString chooseFrom: #( 'Yes' 'No'). answer = 1 ifTrue: trueBlock ifFalse: falseBlock! ! !BitBlt methodsFor: 'accessing' stamp: 'dmu 4/4/2009 00:24'! copyBitsOnMain "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " <primitive: 'primitiveCopyBits' module: 'BitBltPlugin'> "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'ssa 4/7/2009 13:44'! OLDcopyBits "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " <primitive: 'primitiveCopyBits' module: 'BitBltPlugin'> "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'copying' stamp: 'ads 1/24/2011 13:00'! copyBits RVMPrimitivesNeededForBootstrapping isRVM ifFalse:[^self OLDcopyBits]. destForm == Display ifTrue: [self copyBitsOnMain] ifFalse: [self copyBitsLocally]! ! !BitBlt methodsFor: 'copying' stamp: 'dmu 4/4/2009 00:20'! copyBitsLocally "Primitive. Perform the movement of bits from the source form to the destination form. Fail if any variables are not of the right type (Integer, Float, or Form) or if the combination rule is not implemented. In addition to the original 16 combination rules, this BitBlt supports 16 fail (to simulate paint) 17 fail (to simulate mask) 18 sourceWord + destinationWord 19 sourceWord - destinationWord 20 rgbAdd: sourceWord with: destinationWord 21 rgbSub: sourceWord with: destinationWord 22 rgbDiff: sourceWord with: destinationWord 23 tallyIntoMap: destinationWord 24 alphaBlend: sourceWord with: destinationWord 25 pixPaint: sourceWord with: destinationWord 26 pixMask: sourceWord with: destinationWord 27 rgbMax: sourceWord with: destinationWord 28 rgbMin: sourceWord with: destinationWord 29 rgbMin: sourceWord bitInvert32 with: destinationWord " <primitive: 'primitiveCopyBitsLocally'> "Check for compressed source, destination or halftone forms" (combinationRule >= 30 and: [combinationRule <= 31]) ifTrue: ["No alpha specified -- re-run with alpha = 1.0" ^ self copyBitsTranslucent: 255]. ((sourceForm isForm) and: [sourceForm unhibernate]) ifTrue: [^ self copyBits]. ((destForm isForm) and: [destForm unhibernate]) ifTrue: [^ self copyBits]. ((halftoneForm isForm) and: [halftoneForm unhibernate]) ifTrue: [^ self copyBits]. "Check for unimplmented rules" combinationRule = Form oldPaint ifTrue: [^ self paintBits]. combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits]. "Check if BitBlt doesn't support full color maps" (colorMap notNil and:[colorMap isColormap]) ifTrue:[ colorMap _ colorMap colors. ^self copyBits]. "Check if clipping gots us way out of range" self clipRange ifTrue:[^self copyBits]. self error: 'Bad BitBlt arg (Fraction?); proceed to convert.'. "Convert all numeric parameters to integers and try again." destX _ destX asInteger. destY _ destY asInteger. width _ width asInteger. height _ height asInteger. sourceX _ sourceX asInteger. sourceY _ sourceY asInteger. clipX _ clipX asInteger. clipY _ clipY asInteger. clipWidth _ clipWidth asInteger. clipHeight _ clipHeight asInteger. ^ self copyBitsAgain! ! !BitBlt methodsFor: 'line drawing' stamp: 'ads 1/24/2011 13:00'! drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint "Draw a line whose end points are startPoint and stopPoint. The line is formed by repeatedly calling copyBits at every point along the line. If drawFirstPoint is false, then omit the first point so as not to overstrike at line junctions." | offset point1 point2 forwards | "Always draw down, or at least left-to-right" forwards _ (startPoint y = stopPoint y and: [startPoint x < stopPoint x]) or: [startPoint y < stopPoint y]. forwards ifTrue: [point1 _ startPoint. point2 _ stopPoint] ifFalse: [point1 _ stopPoint. point2 _ startPoint]. sourceForm == nil ifTrue: [destX _ point1 x. destY _ point1 y] ifFalse: [width _ sourceForm width. height _ sourceForm height. offset _ sourceForm offset. destX _ (point1 x + offset x) rounded. destY _ (point1 y + offset y) rounded]. "Note that if not forwards, then the first point is the last and vice versa. We agree to always paint stopPoint, and to optionally paint startPoint." (drawFirstPoint or: [forwards == false "ie this is stopPoint"]) ifTrue: [self copyBits]. (destForm == Display or:[RVMPrimitivesNeededForBootstrapping isRVM not]) ifTrue: [ self drawLoopX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded] ifFalse: [self drawLoopLocallyX: (point2 x - point1 x) rounded Y: (point2 y - point1 y) rounded]. (drawFirstPoint or: [forwards "ie this is stopPoint"]) ifTrue: [self copyBits]. ! ! !BitBlt methodsFor: 'line drawing' stamp: 'dmu 4/3/2009 23:01'! drawLoopLocallyX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | | <primitive: 'primitiveDrawLoopLocally'> self primitiveFailed! ! !BitBlt methodsFor: 'line drawing' stamp: 'ads 1/24/2011 13:01'! drawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." ^(destForm == Display or:[RVMPrimitivesNeededForBootstrapping isRVM not]) ifTrue:[self globalDrawLoopX:xDelta Y: yDelta ] ifFalse:[self localDrawLoopX:xDelta Y: yDelta ]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:36'! globalDrawLoopX: xDelta Y: yDelta "Primitive. Implements the Bresenham plotting algorithm (IBM Systems Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and maintains a potential, P. When P's sign changes, it is time to move in the minor direction as well. This particular version does not write the first and last points, so that these can be called for as needed in client code. Optional. See Object documentation whatIsAPrimitive." | dx dy px py P | <primitive: 'primitiveDrawLoop' module: 'BitBltPlugin'> dx _ xDelta sign. dy _ yDelta sign. px _ yDelta abs. py _ xDelta abs. "self copyBits." py > px ifTrue: ["more horizontal" P _ py // 2. 1 to: py do: [:i | destX _ destX + dx. (P _ P - px) < 0 ifTrue: [destY _ destY + dy. P _ P + py]. i < py ifTrue: [self copyBits]]] ifFalse: ["more vertical" P _ px // 2. 1 to: px do: [:i | destY _ destY + dy. (P _ P - py) < 0 ifTrue: [destX _ destX + dx. P _ P + px]. i < px ifTrue: [self copyBits]]]! ! !BitBlt methodsFor: 'line drawing' stamp: 'ssa 4/3/2009 22:52'! localDrawLoopX: xDelta Y: yDelta "Primitive" <primitive: 'primitiveDrawLoopLocally'> ^self primitiveFailed! ! !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:08'! alphaBlendDemo "To run this demo, use... Display restoreAfter: [BitBlt alphaBlendDemo] Displays 10 alphas, then lets you paint. Option-Click to stop painting." "This code exhibits alpha blending in any display depth by performing the blend in an off-screen buffer with 32-bit pixels, and then copying the result back onto the screen with an appropriate color map. - tk 3/10/97" "This version uses a sliding buffer for painting that keeps pixels in 32 bits as long as they are in the buffer, so as not to lose info by converting down to display resolution and back up to 32 bits at each operation. - di 3/15/97" | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect | "compute color maps if needed" Display depth <= 8 ifTrue: [ mapDto32 _ Color cachedColormapFrom: Display depth to: 32. map32toD _ Color cachedColormapFrom: 32 to: Display depth]. "display 10 different alphas, across top of screen" buff _ Form extent: 500@50 depth: 32. dispToBuff _ BitBlt toForm: buff. dispToBuff colorMap: mapDto32. dispToBuff copyFrom: (50@10 extent: 500@50) in: Display to: 0@0. 1 to: 10 do: [:i | dispToBuff fill: (50*(i-1)@0 extent: 50@50) fillColor: (Color red alpha: i/10) rule: Form blend]. buffToDisplay _ BitBlt toForm: Display. buffToDisplay colorMap: map32toD. buffToDisplay copyFrom: buff boundingBox in: buff to: 50@10. "Create a brush with radially varying alpha" brush _ Form extent: 30@30 depth: 32. 1 to: 5 do: [:i | brush fillShape: (Form dotOfSize: brush width*(6-i)//5) fillColor: (Color red alpha: 0.02 * i - 0.01) at: brush extent // 2]. "Now paint with the brush using alpha blending." buffSize _ 100. buff _ Form extent: brush extent + buffSize depth: 32. "Travelling 32-bit buffer" dispToBuff _ BitBlt toForm: buff. "This is from Display to buff" dispToBuff colorMap: mapDto32. brushToBuff _ BitBlt toForm: buff. "This is from brush to buff" brushToBuff sourceForm: brush; sourceOrigin: 0@0. brushToBuff combinationRule: Form blend. buffToBuff _ BitBlt toForm: buff. "This is for slewing the buffer" [Sensor yellowButtonPressed] whileFalse: [prevP _ nil. buffRect _ Sensor cursorPoint - (buffSize // 2) extent: buff extent. dispToBuff copyFrom: buffRect in: Display to: 0@0. [Sensor redButtonPressed] whileTrue: ["Here is the painting loop" p _ Sensor cursorPoint - (brush extent // 2). (prevP == nil or: [prevP ~= p]) ifTrue: [prevP == nil ifTrue: [prevP _ p]. (p dist: prevP) > buffSize ifTrue: ["Stroke too long to fit in buffer -- clip to buffer, and next time through will do more of it" theta _ (p-prevP) theta. p _ ((theta cos@theta sin) * buffSize asFloat + prevP) truncated]. brushRect _ p extent: brush extent. (buffRect containsRect: brushRect) ifFalse: ["Brush is out of buffer region. Scroll the buffer, and fill vacated regions from the display" delta _ brushRect amountToTranslateWithin: buffRect. buffToBuff copyFrom: buff boundingBox in: buff to: delta. newBuffRect _ buffRect translateBy: delta negated. (newBuffRect areasOutside: buffRect) do: [:r | dispToBuff copyFrom: r in: Display to: r origin - newBuffRect origin]. buffRect _ newBuffRect]. "Interpolate from prevP to p..." brushToBuff drawFrom: prevP - buffRect origin to: p - buffRect origin withFirstPoint: false. "Update (only) the altered pixels of the destination" updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent. buffToDisplay copy: updateRect from: updateRect origin - buffRect origin in: buff. prevP _ p]]]! ! !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:09'! antiAliasDemo "To run this demo, use... Display restoreAfter: [BitBlt antiAliasDemo] Goes immediately into on-screen paint mode. Option-Click to stop painting." "This code exhibits alpha blending in any display depth by performing the blend in an off-screen buffer with 32-bit pixels, and then copying the result back onto the screen with an appropriate color map. - tk 3/10/97" "This version uses a sliding buffer for painting that keeps pixels in 32 bits as long as they are in the buffer, so as not to lose info by converting down to display resolution and back up to 32 bits at each operation. - di 3/15/97" "This version also uses WarpBlt to paint into twice as large a buffer, and then use smoothing when reducing back down to the display. In fact this same routine will now work for 3x3 soothing as well. Remove the statements 'buff displayAt: 0@0' to hide the buffer. - di 3/19/97" | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect scale p0 | "compute color maps if needed" Display depth <= 8 ifTrue: [ mapDto32 _ Color cachedColormapFrom: Display depth to: 32. map32toD _ Color cachedColormapFrom: 32 to: Display depth]. "Create a brush with radially varying alpha" brush _ Form extent: 3@3 depth: 32. brush fill: brush boundingBox fillColor: (Color red alpha: 0.05). brush fill: (1@1 extent: 1@1) fillColor: (Color red alpha: 0.2). scale _ 2. "Actual drawing happens at this magnification" "Scale brush up for painting in magnified buffer" brush _ brush magnify: brush boundingBox by: scale. "Now paint with the brush using alpha blending." buffSize _ 100. buff _ Form extent: (brush extent + buffSize) * scale depth: 32. "Travelling 32-bit buffer" dispToBuff _ (WarpBlt toForm: buff) "From Display to buff - magnify by 2" sourceForm: Display; colorMap: mapDto32; combinationRule: Form over. brushToBuff _ (BitBlt toForm: buff) "From brush to buff" sourceForm: brush; sourceOrigin: 0@0; combinationRule: Form blend. buffToDisplay _ (WarpBlt toForm: Display) "From buff to Display - shrink by 2" sourceForm: buff; colorMap: map32toD; cellSize: scale; "...and use smoothing" combinationRule: Form over. buffToBuff _ BitBlt toForm: buff. "This is for slewing the buffer" [Sensor yellowButtonPressed] whileFalse: [prevP _ nil. buffRect _ Sensor cursorPoint - (buff extent // scale // 2) extent: buff extent // scale. p0 _ (buff extent // 2) - (buffRect extent // 2). dispToBuff copyQuad: buffRect innerCorners toRect: buff boundingBox. buff displayAt: 0@0. "** remove to hide sliding buffer **" [Sensor redButtonPressed] whileTrue: ["Here is the painting loop" p _ Sensor cursorPoint - buffRect origin + p0. "p, prevP are rel to buff origin" (prevP == nil or: [prevP ~= p]) ifTrue: [prevP == nil ifTrue: [prevP _ p]. (p dist: prevP) > (buffSize-1) ifTrue: ["Stroke too long to fit in buffer -- clip to buffer, and next time through will do more of it" theta _ (p-prevP) theta. p _ ((theta cos@theta sin) * (buffSize-2) asFloat + prevP) truncated]. brushRect _ p extent: brush extent. ((buff boundingBox insetBy: scale) containsRect: brushRect) ifFalse: ["Brush is out of buffer region. Scroll the buffer, and fill vacated regions from the display" delta _ (brushRect amountToTranslateWithin: (buff boundingBox insetBy: scale)) // scale. buffToBuff copyFrom: buff boundingBox in: buff to: delta*scale. newBuffRect _ buffRect translateBy: delta negated. p _ p translateBy: delta*scale. prevP _ prevP translateBy: delta*scale. (newBuffRect areasOutside: buffRect) do: [:r | dispToBuff copyQuad: r innerCorners toRect: (r origin - newBuffRect origin*scale extent: r extent*scale)]. buffRect _ newBuffRect]. "Interpolate from prevP to p..." brushToBuff drawFrom: prevP to: p withFirstPoint: false. buff displayAt: 0@0. "** remove to hide sliding buffer **" "Update (only) the altered pixels of the destination" updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent. updateRect _ updateRect origin // scale * scale corner: updateRect corner + scale // scale * scale. buffToDisplay copyQuad: updateRect innerCorners toRect: (updateRect origin // scale + buffRect origin extent: updateRect extent // scale). prevP _ p]]]! ! !BitBlt class methodsFor: 'examples' stamp: 'ssa 10/27/2008 16:38'! exampleColorMap "BitBlt exampleColorMap" "This example shows what one can do with the fixed part of a color map. The color map, as setup below, rotates the bits of a pixel all the way around. Thus you'll get a (sometime strange looking ;-) animation of colors which will end up exactly the way it looked at the beginning. The example is given to make you understand that the masks and shifts can be used for a lot more than simply color converting pixels. In this example, for instance, we use only two of the four independent shifters." | cc bb | cc _ ColorMap masks: { 1 << (Display depth-1). "mask out high bit of color component" 1 << (Display depth-1) - 1. "mask all other bits" 0. 0} shifts: { 1 - Display depth. "shift right to bottom most position" 1. "shift all other pixels one bit left" 0. 0}. bb _ BitBlt toForm: Display. bb sourceForm: Display; combinationRule: 3; colorMap: cc. 1 to: Display depth do:[:i| bb copyBits. Display forceDisplayUpdate. Sensor waitButton;waitNoButton ]. ! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 4/24/2001 23:49'! benchDiffsFrom: before to: afterwards "Given two outputs of BitBlt>>benchmark show the relative improvements." | old new log oldLine newLine oldVal newVal improvement | log _ WriteStream on: String new. old _ ReadStream on: before. new _ ReadStream on: afterwards. [old atEnd or:[new atEnd]] whileFalse:[ oldLine _ old upTo: Character cr. newLine _ new upTo: Character cr. (oldLine includes: Character tab) ifTrue:[ oldLine _ ReadStream on: oldLine. newLine _ ReadStream on: newLine. Transcript cr; show: (oldLine upTo: Character tab); tab. log cr; nextPutAll: (newLine upTo: Character tab); tab. [oldLine skipSeparators. newLine skipSeparators. oldLine atEnd] whileFalse:[ oldVal _ Integer readFrom: oldLine. newVal _ Integer readFrom: newLine. improvement _ oldVal asFloat / newVal asFloat roundTo: 0.01. Transcript show: improvement printString; tab; tab. log print: improvement; tab; tab]. ] ifFalse:[ Transcript cr; show: oldLine. log cr; nextPutAll: oldLine. ]. ]. ^log contents! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 5/14/2001 23:31'! benchmark2 "BitBlt benchmark" "Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else. Attention: *this*may*take*a*while*" | bb source dest destRect log t | log _ WriteStream on: String new. destRect _ 0@0 extent: 600@600. "Form paint/Form over - the most common rules" #( 25 3 ) do:[:rule| Transcript cr; show:'---- Combination rule: ', rule printString,' ----'. log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'. #(1 2 4 8 16 32) do:[:destDepth| dest _ nil. dest _ Form extent: destRect extent depth: destDepth. Transcript cr. log cr. #(1 2 4 8 16 32) do:[:sourceDepth| Transcript cr; show: sourceDepth printString, ' => ', destDepth printString. log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString. source _ nil. bb _ nil. source _ Form extent: destRect extent depth: sourceDepth. (source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black. bb _ WarpBlt toForm: dest. bb sourceForm: source. bb sourceRect: source boundingBox. bb destRect: dest boundingBox. bb colorMap: (source colormapIfNeededFor: dest). bb combinationRule: rule. "Measure speed of copyBits" t _ Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. bb sourceForm: source destRect: source boundingBox. "Measure speed of 1x1 warpBits" bb cellSize: 1. t _ Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 2x2 warpBits" bb cellSize: 2. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 3x3 warpBits" bb cellSize: 3. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. ]. ]. ]. ^log contents! ! !BitBlt class methodsFor: 'benchmarks' stamp: 'ar 4/26/2001 21:04'! benchmark3 "BitBlt benchmark" "Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else. Attention: *this*may*take*a*while*" | bb source dest destRect log t | log _ WriteStream on: String new. destRect _ 0@0 extent: 600@600. "Form paint/Form over - the most common rules" #( 25 3 ) do:[:rule| Transcript cr; show:'---- Combination rule: ', rule printString,' ----'. log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'. #(1 2 4 8 16 32) do:[:destDepth| dest _ nil. dest _ Form extent: destRect extent depth: destDepth. Transcript cr. log cr. #(1 2 4 8 16 32) do:[:sourceDepth| Transcript cr; show: sourceDepth printString, ' => ', destDepth printString. log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString. source _ nil. bb _ nil. source _ Form extent: destRect extent depth: sourceDepth. (source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black. bb _ WarpBlt toForm: dest. bb sourceForm: source. bb sourceRect: source boundingBox. bb destRect: dest boundingBox. bb colorMap: (source colormapIfNeededFor: dest). bb combinationRule: rule. "Measure speed of copyBits" t _ Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. bb sourceForm: source destRect: source boundingBox. "Measure speed of 1x1 warpBits" bb cellSize: 1. t _ Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 2x2 warpBits" bb cellSize: 2. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. "Measure speed of 3x3 warpBits" bb cellSize: 3. t _ Time millisecondsToRun:[bb warpBits]. Transcript tab; show: t printString. log tab; nextPutAll: t printString. ]. ]. ]. ^log contents! ! !BlockContext methodsFor: '*Sly3' stamp: 'dmu 9/17/2010 10:58'! asSlyMemberProcess ^ self copy fixTemps newProcess beSlyMemberProcess! ! !BlockContext methodsFor: 'controlling' stamp: 'ssa 8/24/2009 16:18'! loopExit [self value: [^ self]] repeat! ! !BlockContext methodsFor: 'controlling' stamp: 'ssa 8/24/2009 16:43'! untilFalse: aBlock [self value. aBlock value ifFalse: [^ self]] repeat ! ! !BlockContext methodsFor: 'converting' stamp: 'ssa 9/7/2009 14:36'! asContext ^self! ! !BlockContext methodsFor: 'evaluating' stamp: 'dmu 8/17/2009 21:52'! value: arg1 value: arg2 value: arg3 value: arg4 value: arg5 "Primitive. Evaluate the block represented by the receiver. Fail if the block expects other than three arguments or if the block is already being executed. Optional. See Object documentation whatIsAPrimitive." <primitive: 81> ^self valueWithArguments: (Array with: arg1 with: arg2 with: arg3 with: arg4 with: arg5)! ! !BlockContext methodsFor: 'printing' stamp: 'ssa 11/27/2009 16:55'! asString | str | str _ (((self decompile ifNil: ['--source missing--']) printString replaceAll: Character cr with: Character space) replaceAll: Character tab with: Character space). ^str copyFrom: 2 to: str size - 1! ! !BlockContext methodsFor: 'printing' stamp: 'ads 1/24/2011 13:02'! printOn: aStream | blockString truncatedBlockString | aStream nextPutAll:(RVMPrimitivesNeededForBootstrapping printPrefixFor: self). home == nil ifTrue: [^aStream nextPutAll: 'a BlockContext with home=nil']. aStream nextPutAll: '[] in '. super printOn: aStream. aStream nextPutAll: ' '. blockString _ ((self decompile ifNil: ['--source missing--']) printString replaceAll: Character cr with: Character space) replaceAll: Character tab with: Character space. truncatedBlockString _ blockString truncateWithElipsisTo: 800. truncatedBlockString size < blockString size ifTrue: [truncatedBlockString _ truncatedBlockString, ']}']. aStream nextPutAll: truncatedBlockString. ! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:34'! forkWith: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resume! ! !BlockContext methodsFor: 'scheduling' stamp: 'dmu 4/7/2009 02:33'! newProcessWith: anObject "Answer a Process running the code in the receiver. The process is not scheduled." <primitive: 19> "Simulation guard" ^Process forContext: [self value: anObject. Processor terminateActive] priority: Processor activePriority! ! !BlockContext methodsFor: 'private' stamp: 'dmu 11/25/2008 00:18'! valueUnpreemptively "Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!" "Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! After you've done all that thinking, go right ahead and use it..." | activeProcess oldPriority result | activeProcess _ Processor thisProcess. oldPriority _ activeProcess priority. activeProcess priority: Processor highestPriority. result _ self ensure: [activeProcess priority: oldPriority]. "Yield after restoring priority to give the preempted processes a chance to run" Processor yield. ^result! ! !BlockContext methodsFor: '*RVM' stamp: 'ads 1/30/2011 15:22'! cyclesToRunMe | s delta correction result | s _ RVMOperations cycleCounter. self value. delta _ RVMOperations cycleCounter - s. ^ delta < 0 ifTrue: [ correction _ SmallInteger maxVal + 1. result _ delta. [result < 0] whileTrue: [result _ result + correction]. result ] ifFalse: [delta]! ! !BlockContext methodsFor: '*RVM' stamp: 'dmu 4/7/2009 02:38'! forkOn: aCore "Create and schedule a Process running the code in the receiver." ^ self newProcess resumeOn: aCore! ! !BlockContext methodsFor: '*RVM' stamp: 'ssa 4/8/2009 20:09'! forkOn: aCore with: anObject "Create and schedule a Process running the code in the receiver." ^ (self newProcessWith: anObject) resumeOn: aCore! ! !BlockContext methodsFor: '*RVM' stamp: 'ssa 4/8/2009 20:08'! forkOn: aCore with: anObject at: aPriority "Create and schedule a Process running the code in the receiver." | proc | proc _ self newProcessWith: anObject. proc priority: aPriority. ^proc resumeOn: aCore! ! !BlockNode methodsFor: 'accessing' stamp: 'dmu 1/21/2010 15:22'! returnSelfIfNoOther self returns ifFalse: [statements last == NodeSelf ifFalse: [ (statements isKindOf: Array) ifTrue: [statements _ statements asOrderedCollection]. statements add: NodeSelf ]. self returnLast]! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/29/2010 14:37'! add: anObject (self includes: anObject) ifFalse: [mutex critical: [super addLast: anObject]]! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! add: anObject after: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! add: anObject afterIndex: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! add: anObject before: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! add: anObject beforeIndex: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/16/2010 13:13'! addAll: aCollection "Add each element of aCollection not already included in the reciever, at the end. Use super's method to avoid needless nested blocking. Answer aCollection." mutex critical: [aCollection do: [ :each | (array includes: each) ifFalse: [super addLast: each]]]. ^aCollection! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! addAllFirst: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! addAllFirstUnlessAlreadyPresent: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/16/2010 13:04'! addAllLast: aCollection self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! addFirst: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/16/2010 13:07'! addLast: anObject self add: anObject! ! !BlockingSmallSet methodsFor: 'adding' stamp: 'max 9/15/2010 14:33'! at: anObject ifAbsentPut: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'accessing' stamp: 'max 9/15/2010 14:33'! at: anObject put: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'enumerating' stamp: 'max 9/16/2010 12:38'! collect: aBlock from: fromIndex to: toIndex self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'enumerating' stamp: 'max 9/15/2010 14:33'! with: anObject collect: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'enumerating' stamp: 'max 9/15/2010 14:33'! withIndexCollect: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'copying' stamp: 'max 9/15/2010 14:33'! copyFrom: anObject to: anObject2 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'copying' stamp: 'max 9/15/2010 14:33'! copyReplaceFrom: anObject to: anObject2 with: anObject3 self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'copying' stamp: 'max 9/15/2010 14:33'! copyWith: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'copying' stamp: 'max 9/15/2010 14:33'! reversed self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 15:15'! remove: anObject self remove: anObject ifAbsent: []! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 15:13'! remove: anObject ifAbsent: absentBlock mutex critical: [super remove: anObject ifAbsent: absentBlock]! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'dmu 9/23/2010 14:28'! removeAll mutex critical: [super setCollection: (Array new: array size)]! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/17/2010 13:31'! removeAll: aCollection "Remove each element of aCollection, using super's method to avoid needless nested blocking. Answer aCollection." mutex critical: [aCollection do: [ :each | super remove: each ifAbsent: []]]. ^aCollection! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/16/2010 12:24'! removeAllSuchThat: aBlock mutex critical: [ super removeAllSuchThat: aBlock ]! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 14:33'! removeAt: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 14:33'! removeFirst self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 14:33'! removeFirst: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 14:33'! removeLast self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'removing' stamp: 'max 9/15/2010 14:33'! removeLast: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'sorting' stamp: 'max 9/15/2010 14:33'! sort self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'sorting' stamp: 'max 9/15/2010 14:33'! sort: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'sorting' stamp: 'max 9/15/2010 14:33'! sorted: anObject self shouldNotImplement! ! !BlockingSmallSet methodsFor: 'initialize-release' stamp: 'max 9/29/2010 14:38'! initialize super initialize. mutex := Semaphore forMutualExclusion! ! !BlockingSmallSet commentStamp: 'max 9/17/2010 12:48' prior: 0! A BlockingSmallSet is an unindexed collection which behaves like a set, allowing no duplicate elements. It uses a semaphore to ensure that adding and removing operations are atomic and thus thread-safe. It wraps an OrderedCollection, which is simpler than Set's hash-based implementation and may be more efficient for small numbers of elements. BlockingSmallSets block on recieving any of (#add: #remove: #addAll: #removeAll:). They also respond to: #intersection:, #union:, and all the standard enumeration messages. However, care should be taken when using any #do:-based enumerator which may affect the state of the reciever: while each individual successive #add: or #remove: is atomic, the overall enumeration is not.! !BlockingSmallSet class methodsFor: 'as yet unclassified' stamp: 'max 9/15/2010 17:55'! new | bss | bss := super new. bss initialize. ^ bss! ! !Boolean methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfFalse ! ! !Boolean methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfTrue ! ! !Boolean methodsFor: 'testing' stamp: 'ssa 6/1/2010 16:46'! mustBeBoolean ^false! ! !Boolean methodsFor: 'testing' stamp: 'ssa 6/1/2010 16:47'! mustBeBooleanIn: aContext ^true! ! !Boolean methodsFor: '*Sly' stamp: 'ssa 5/27/2010 10:41'! isBoolean "Return true if the receiver is true or false. Note: Do not override in any class except Boolean." ^true! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! classOrganizer "Answer the value of classOrganizer" classOrganizer isNil ifTrue:[self classOrganizer: nil]. ^ classOrganizer! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! classOrganizer: anObject "Set the value of classOrganizer" classOrganizer _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:40'! lastClassSelected "Answer the value of lastClassSelected" lastClassSelected isNil ifTrue:[self lastClassSelected: self selectedClassOrMetaClass]. ^ lastClassSelected! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! lastClassSelected: anObject "Set the value of lastClassSelected" lastClassSelected _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! metaClassOrganizer "Answer the value of metaClassOrganizer" metaClassOrganizer isNil ifTrue:[self metaClassOrganizer: nil]. ^ metaClassOrganizer! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! metaClassOrganizer: anObject "Set the value of metaClassOrganizer" metaClassOrganizer _ anObject! ! !Browser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 09:01'! systemOrganizer "Answer the value of systemOrganizer" systemOrganizer isNil ifTrue:[self systemOrganizer: nil]. ^ systemOrganizer! ! !Browser methodsFor: 'class functions' stamp: 'ssa 8/27/2009 05:09'! createInstVarAccessors "Create getters and setters for all inst vars defined at the level of the current class selection, except do NOT clobber or override any selectors already understood by the instances of the selected class" | aClass newMessage setter | (aClass _ self selectedClassOrMetaClass) ifNotNil: [aClass instVarNames do: [:aName | (aClass canUnderstand: aName asSymbol) ifFalse: [newMessage _ aName, ' "Answer the value of ', aName, '" ',aName,' isNil ifTrue:[self ',aName,': nil]. ^ ', aName. aClass compile: newMessage classified: 'accessing' notifying: nil]. (aClass canUnderstand: (setter _ aName, ':') asSymbol) ifFalse: [newMessage _ setter, ' anObject "Set the value of ', aName, '" ', aName, ' _ anObject'. aClass compile: newMessage classified: 'accessing' notifying: nil]]]. self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged. self selectMessageCategoryNamed:'accessing'! ! !Browser methodsFor: 'class list' stamp: 'ssa 9/9/2009 09:03'! classListIndex: anInteger "Set anInteger to be the index of the current class selection." | className | classListIndex _ anInteger. self lastClassSelected: self selectedClassOrMetaClass. self setClassOrganizer. messageCategoryListIndex _ 0. messageListIndex _ 0. self classCommentIndicated ifTrue: [] ifFalse: [self editSelection: (anInteger = 0 ifTrue: [metaClassIndicated | (systemCategoryListIndex == 0) ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. contents _ nil. self selectedClass isNil ifFalse: [className _ self selectedClass name. (RecentClasses includes: className) ifTrue: [RecentClasses remove: className]. RecentClasses addFirst: className. RecentClasses size > 16 ifTrue: [RecentClasses removeLast]]. self changed: #classSelectionChanged. self changed: #classCommentText. self changed: #classListIndex. "update my selection" self changed: #messageCategoryList. self changed: #messageList. self changed: #relabel. self contentsChanged! ! !Browser methodsFor: 'initialize-release' stamp: 'ssa 9/10/2009 13:32'! setClass: aBehavior selector: aSymbol "Set the state of a new, uninitialized Browser." | isMeta aClass messageCatIndex | aBehavior ifNil: [^ self]. (aBehavior isKindOf: Metaclass) ifTrue: [ isMeta _ true. aClass _ aBehavior soleInstance] ifFalse: [ isMeta _ false. aClass _ aBehavior]. self selectCategoryForClass: aClass. self classListIndex: ( (SystemOrganization listAtCategoryNamed: self selectedSystemCategoryName) indexOf: aClass name). self metaClassIndicated: isMeta. aSymbol ifNil: [^ self]. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: (messageCatIndex > 0 ifTrue: [messageCatIndex + 1] ifFalse: [0]). messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ( (aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol).! ! !Browser methodsFor: 'message functions' stamp: 'ssa 9/9/2009 09:05'! defineMessage: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer true if compilation succeeds, false otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ self lastClassSelected "selectedClassOrMetaClass" compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ false]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ true! ! !Browser methodsFor: 'message functions' stamp: 'ssa 9/9/2009 09:06'! defineMessageFrom: aString notifying: aController "Compile the expressions in aString. Notify aController if a syntax error occurs. Install the compiled method in the selected class classified under the currently selected message category name. Answer the selector obtained if compilation succeeds, nil otherwise." | selectedMessageName selector category oldMessageList | selectedMessageName _ self selectedMessageName. oldMessageList _ self messageList. contents _ nil. selector _ (Parser new parseSelector: aString). (self metaClassIndicated and: [(self lastClassSelected "selectedClassOrMetaClass" includesSelector: selector) not and: [Metaclass isScarySelector: selector]]) ifTrue: ["A frist-time definition overlaps the protocol of Metaclasses" (self confirm: ((selector , ' is used in the existing class system. Overriding it could cause serious problems. Is this really what you want to do?') asText makeBoldFrom: 1 to: selector size)) ifFalse: [^nil]]. selector _ self lastClassSelected "selectedClassOrMetaClass" compile: aString classified: (category _ self selectedMessageCategoryName) notifying: aController. selector == nil ifTrue: [^ nil]. contents _ aString copy. selector ~~ selectedMessageName ifTrue: [category = ClassOrganizer nullCategory ifTrue: [self changed: #classSelectionChanged. self changed: #classList. self messageCategoryListIndex: 1]. self setClassOrganizer. "In case organization not cached" (oldMessageList includes: selector) ifFalse: [self changed: #messageList]. self messageListIndex: (self messageList indexOf: selector)]. ^ selector! ! !Browser methodsFor: 'metaclass' stamp: 'ssa 9/10/2009 08:45'! metaClassIndicated: trueOrFalse "Indicate whether browsing instance or class messages." metaClassIndicated _ trueOrFalse. self setClassOrganizer. systemCategoryListIndex > 0 ifTrue: [self editSelection: (classListIndex = 0 ifTrue: [metaClassIndicated ifTrue: [#none] ifFalse: [#newClass]] ifFalse: [#editClass])]. messageCategoryListIndex _ 0. messageListIndex _ 0. contents _ nil. self changed: #classSelectionChanged. self changed: #messageCategoryList. self changed: #messageList. self changed: #contents. self changed: #annotation. self decorateButtons. self lastClassSelected: self selectedClassOrMetaClass. ! ! !CPUWatcher methodsFor: 'process operations' stamp: 'dmu 11/25/2008 00:18'! debugProcess: aProcess | uiPriority oldPriority | uiPriority _ Processor thisProcess priority. aProcess priority >= uiPriority ifTrue: [ oldPriority _ ProcessBrowser setProcess: aProcess toPriority: uiPriority - 1 ]. ProcessBrowser debugProcess: aProcess.! ! !CPUWatcher class methodsFor: 'as yet unclassified' stamp: 'sm 2/24/2011 16:39'! startMonitoringPeriod: pd rate: rt threshold: th "CPUWatcher startMonitoring" CurrentCPUWatcher ifNotNil: [ ^CurrentCPUWatcher startMonitoring. ]. CurrentCPUWatcher _ (self new) monitorProcessPeriod: pd sampleRate: rt; threshold: th; name: 'CurrentCPUWatcher'; yourself. ^CurrentCPUWatcher ! ! !Categorizer methodsFor: '*transporter' stamp: 'ads 12/1/2010 11:49'! classifyAllFrom: srcCat under: dstCat self classifyAll: (self listAtCategoryNamed: srcCat) under: dstCat. self removeCategory: srcCat.! ! !Categorizer methodsFor: '*transporter' stamp: 'ads 12/8/2010 14:00'! removeCategoryIfEmpty: cat (self listAtCategoryNamed: cat) isEmpty ifTrue: [self removeCategory: cat].! ! !ChangeList methodsFor: 'scanning' stamp: 'ssa 1/5/2010 15:55'! scanRecords: someRecords changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. someRecords do:[:each| each type = #doIt ifTrue:[self addItem: each text: 'do it: ' , (each string contractTo: 50)]. each type = #preamble ifTrue:[self addItem: each text: 'preamble: ' , (each string contractTo: 50)]. each type = #classComment ifTrue:[self addItem: each text: 'class comment for ', each methodClassName]. each type = #method ifTrue:[self addItem: each text: 'method: ',each methodClassName,(each isMetaClassChange ifTrue: [' class '] ifFalse: [' ']),each methodSelector,' ', each stamp]]. listSelections _ Array new: list size withAll: false! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 12:19'! changeListMenu: aMenu "Fill aMenu up so that it comprises the primary changelist-browser menu" aMenu addList: #( ('fileIn selections' fileInSelections 'import the selected items into the image') ('fileOut selections... ' fileOutSelections 'create a new file containing the selected items') - ('compare to current' compareToCurrentVersion 'open a separate window which shows the text differences between the on-file version and the in-image version.' ) ('toggle diffing (D)' toggleDiffing 'start or stop showing diffs in the code pane.') - ('select conflicts with any changeset' selectAllConflicts 'select methods in the file which also occur in any change-set in the system') ('select conflicts with current changeset' selectConflicts 'select methods in the file which also occur in the current change-set') ('select conflicts with...' selectConflictsWith 'allows you to designate a file or change-set against which to check for code conflicts.') - ('select changes matching...' selectChangesMatching 'select changes in the file that match a user-supplied pattern') ('spawn changes matching...' spawnChangesMatching 'spawn changes in the file that match a user-supplied pattern into a new change list view') ('select changes such that...' selectSuchThat 'select changes in the file that evaluate to true to a user-supplied code fragment') ('spawn changes such that...' spawnSuchThat 'spawn changes in the file that evaluate to true to a user-supplied code fragment') - ('select unchanged methods' selectUnchangedMethods 'select methods in the file whose in-image versions are the same as their in-file counterparts' ) ('select new methods' selectNewMethods 'select methods in the file that do not current occur in the image') ('select methods for this class' selectMethodsForThisClass 'select all methods in the file that belong to the currently-selected class') - ('select all (a)' selectAll 'select all the items in the list') ('deselect all' deselectAll 'deselect all the items in the list') ('invert selections' invertSelections 'select every item that is not currently selected, and deselect every item that *is* currently selected') ('spawn selections' spawnSelections 'spawn all selected changes into a new change list view') - ('browse current versions of selections' browseCurrentVersionsOfSelections 'open a message-list browser showing the current (in-image) counterparts of the selected methods') ('destroy current methods of selections' destroyCurrentCodeOfSelections 'remove (*destroy*) the in-image counterparts of all selected methods') - ('remove doIts' removeDoIts 'remove all items that are doIts rather than methods') ('remove older versions' removeOlderMethodVersions 'remove all but the most recent versions of methods in the list') ('remove up-to-date versions' removeExistingMethodVersions 'remove all items whose code is the same as the counterpart in-image code') ('remove selected items' removeSelections 'remove the selected items from the change-list') ('remove unselected items' removeNonSelections 'remove all the items not currently selected from the change-list')). ^ aMenu ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:16'! selectChangesMatching "query the user for a pattern then select all changes matching that pattern" | pattern | pattern _ FillInTheBlank request: 'Enter a pattern to match to select changes: # = single character wildcard * = many character wildcard'. '' . pattern isEmpty ifTrue: [^ self ]. self selectSuchThat: [:aChangeRecord | aChangeRecord match: pattern]! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 15:07'! selectSuchThat "query the user for a selection criterio. By Lex Spoon. NB: the UI for invoking this from a changelist browser is currently commented out; to reenfranchise it, you'll need to mild editing to ChangeList method #changeListMenu:" | code block | code _ FillInTheBlank request: 'selection criteria for a change named aChangeRecord? For instance, aChangeRecord category = ''System-Network'' aChangeRecord type = "one of #(#method #doIt #classComment #preamble )" aChangeRecord text = ''whole change text'' aChangeRecord string includesSubString: ''change text substring'' aChangeRecord string includesSubString: ''change text substring'' ''*fooba#'' match: aChangeRecord string ''*fooba#'' match: aChangeRecord methodSelectorSafe ''*fooba#'' match: aChangeRecord methodSelectorSafe ' initialAnswer: 'aChangeRecord match:''*anything#anyChar'''. code isEmpty ifTrue: [^ self ]. block _ Compiler evaluate: '[:aChangeRecord | ', code, ']'. self selectSuchThat: block! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:46'! spawnChangesMatching "query the user for a pattern then select all changes matching that pattern" | pattern | pattern _ FillInTheBlank request: 'Enter a pattern to match to select changes: # = single character wildcard * = many character wildcard'. '' . pattern isEmpty ifTrue: [^ self ]. self spawnSuchThat: [:aChangeRecord | aChangeRecord match: pattern] titled:'Changes matching ',pattern! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:55'! spawnSelections "spawn a new changelist view for the selections" self class browseRecords: self selectedChanges titled:'Selected Changes'! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 15:07'! spawnSuchThat "query the user for a selection criterion block and then spawn" | code block | code _ FillInTheBlank request: 'selection criteria for a change named aChangeRecord? For instance, aChangeRecord category = ''System-Network'' aChangeRecord type = "one of #(#method #doIt #classComment #preamble )" aChangeRecord text = ''whole change text'' aChangeRecord string includesSubString: ''change text substring'' ''*foo*ba#'' match: aChangeRecord string ''*foo*ba#'' match: aChangeRecord methodSelectorSafe ''*foo*ba#'' match: aChangeRecord methodSelectorSafe ' initialAnswer: 'aChangeRecord match:''*anything#anyChar'''. code isEmpty ifTrue: [^ self ]. block _ Compiler evaluate: '[:aChangeRecord | ', code, ']'. self spawnSuchThat: block titled: 'Changes such that ''',code,'''' ! ! !ChangeList methodsFor: 'menu actions' stamp: 'ssa 1/5/2010 14:58'! spawnSuchThat: aBlock titled: aString "spawn changes passing aBlock" | changes | changes _ changeList select: [ :change | aBlock value: change ]. self class browseRecords: changes titled: aString! ! !ChangeList methodsFor: 'viewing access' stamp: 'ssa 1/1/1970 00:15'! togglePrimaryListIndex: newListIndex listIndex = newListIndex ifTrue: [listSelections at: listIndex put: false. listIndex := 0] ifFalse: [newListIndex ~= 0 ifTrue: [listSelections at: newListIndex put: true. listIndex := newListIndex]]. self changed: #listIndex. self contentsChanged! ! !ChangeList methodsFor: 'accessing' stamp: 'ssa 1/5/2010 13:56'! changeList: aCollection changeList _ aCollection! ! !ChangeList methodsFor: 'accessing' stamp: 'ssa 1/5/2010 14:56'! selectedChanges | sels | sels _ OrderedCollection new. listSelections with: changeList do: [:selected :item | selected ifTrue: [sels add: item]]. ^sels! ! !ChangeList class methodsFor: 'public access' stamp: 'ssa 1/5/2010 14:45'! browseRecords: someChangeRecords "Opens a changeList on a collection of change records" self browseRecords: someChangeRecords titled: 'Some changes'! ! !ChangeList class methodsFor: 'public access' stamp: 'ssa 1/5/2010 14:45'! browseRecords: someChangeRecords titled: aString "Opens a changeList on a collection of change records" | changeList | changeList _ self new scanRecords: someChangeRecords. self open: changeList name: aString multiSelect: true! ! !ChangeList class methodsFor: 'public access' stamp: 'dmu 9/7/2010 14:16'! getRecentLocatorWithPrompt: aPrompt "Prompt with a menu of how far back to go. Return nil if user backs out. Otherwise return the number of characters back from the end of the .changes file the user wishes to include" "ChangeList getRecentPosition" | end changesFile banners positions pos chunk i | changesFile _ (SourceFiles at: 2) readOnlyCopy. banners _ OrderedCollection new. positions _ OrderedCollection new. changesFile safelyDo: [ end _ changesFile size. pos _ SmalltalkImage current lastQuitLogPosition. [pos = 0 or: [banners size > 20]] whileFalse: [ changesFile position: pos. chunk _ changesFile nextChunk. i _ chunk indexOfSubCollection: 'priorSource: ' startingAt: 1. i > 0 ifTrue: [positions addLast: pos. banners addLast: (chunk copyFrom: 5 to: i-2). pos _ Number readFrom: (chunk copyFrom: i+13 to: chunk size)] ifFalse: [pos _ 0]]. changesFile close. pos _ (SelectionMenu labelList: banners selections: positions) startUpWithCaption: aPrompt. pos == nil ifTrue: [^ nil]. ^ end - pos ]! ! !ChangeList class methodsFor: 'instance creation' stamp: 'ssa 8/21/2009 15:32'! open: aChangeList name: aString multiSelect: multiSelect "Create a standard system view for the messageSet, whose label is aString. The listView may be either single or multiple selection type" | topView listHeight annoHeight optButtonHeight codeHeight aListView underPane annotationPane buttonsView aBrowserCodeView | listHeight _ 70. annoHeight _ 10. optButtonHeight _ aChangeList optionalButtonHeight. codeHeight _ 110. topView _ (StandardSystemView new) model: aChangeList; label: aString; minimumSize: 200 @ 120; borderWidth: 1. aListView _ (multiSelect ifTrue: [PluggableListViewOfMany on: aChangeList list: #list primarySelection: #listIndex changePrimarySelection: #togglePrimaryListIndex: listSelection: #listSelectionAt: changeListSelection: #listSelectionAt:put: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])] ifFalse: [PluggableListView on: aChangeList list: #list selected: #listIndex changeSelected: #toggleListIndex: menu: (aChangeList showsVersions ifTrue: [#versionsMenu:] ifFalse: [#changeListMenu:])]). aListView window: (0 @ 0 extent: 200 @ listHeight). topView addSubView: aListView . underPane _ aListView. aChangeList wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: aChangeList text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0 @ 0 extent: 200 @ 10). topView addSubView: annotationPane below: underPane. underPane _ annotationPane . codeHeight _ codeHeight - annoHeight]. aChangeList wantsOptionalButtons ifTrue: [buttonsView _ aChangeList optionalButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. codeHeight _ codeHeight - optButtonHeight]. aBrowserCodeView _ PluggableTextView on: aChangeList text: #contents accept: #contents: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. aBrowserCodeView scrollingView controller: ReadOnlyTextController new. aBrowserCodeView window: (0 @ 0 extent: 200 @ codeHeight). topView addSubView: aBrowserCodeView below: underPane. topView controller open.! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:49'! fileReaderServicesForFile: fullName suffix: suffix | services | services _ OrderedCollection new. (FileStream isSourceFileSuffix: suffix) | (suffix = '*') ifTrue: [ services add: self serviceBrowseChangeFile ]. (suffix = 'changes') | (suffix = '*') ifTrue: [ services add: self serviceBrowseDotChangesFile ]. ^services! ! !ChangeList class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:49'! services "Answer potential file services associated with this class" ^ { self serviceBrowseChangeFile. self serviceBrowseDotChangesFile. }! ! !ChangeRecord methodsFor: 'testing' stamp: 'ssa 1/5/2010 14:12'! match: aPatternString "Answer true is any of my text matches aPatternString" (aPatternString match: self string) ifTrue:[^true]. (aPatternString match: self methodClassNameSafe) ifTrue:[^true]. ^false! ! !ChangeRecord methodsFor: 'access' stamp: 'ssa 1/5/2010 14:04'! methodClassNameSafe ^class isNil ifTrue:['']ifFalse:[class]! ! !ChangeRecord methodsFor: 'access' stamp: 'ssa 1/5/2010 14:03'! methodSelectorSafe "Answer a string in any case" type == #method ifFalse: [^ '']. ^ Parser new parseSelector: self string! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! changeRecords "Answer the value of changeRecords" changeRecords isNil ifTrue:[self changeRecords: nil]. ^ changeRecords! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! changeRecords: anObject "Set the value of changeRecords" changeRecords _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 9/3/2008 11:02'! editPostscript "edit the receiver's postscript, in a separate window. " | deps found | self assurePostscriptExists. deps _ postscript dependents select: [:m | m isKindOf: StandardSystemView]. deps size > 0 ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [found _ deps detect: [:obj | (obj isKindOf: StandardSystemView) and: [ScheduledControllers scheduledControllers includes: obj controller]] ifNone: [nil]. found ifNotNil: [^ ScheduledControllers activateController: found controller]]. . self inform: 'Caution -- there', (deps size isOrAreStringWith: 'other window'), ' already open on this postscript elsewhere']. postscript openLabel: 'Postscript for ChangeSet named ', name! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! isolatedProject: anObject "Set the value of isolatedProject" isolatedProject _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! isolationSet "Answer the value of isolationSet" isolationSet isNil ifTrue:[self isolationSet: nil]. ^ isolationSet! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! postscript "Answer the value of postscript" postscript isNil ifTrue:[self postscript: nil]. ^ postscript! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! postscript: anObject "Set the value of postscript" postscript _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! preamble "Answer the value of preamble" preamble isNil ifTrue:[self preamble: nil]. ^ preamble! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! preamble: anObject "Set the value of preamble" preamble _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! revertable "Answer the value of revertable" revertable isNil ifTrue:[self revertable: nil]. ^ revertable! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! revertable: anObject "Set the value of revertable" revertable _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! structures: anObject "Set the value of structures" structures _ anObject! ! !ChangeSet methodsFor: 'accessing' stamp: 'ssa 1/5/2010 21:02'! superclasses: anObject "Set the value of superclasses" superclasses _ anObject! ! !ChangeSet methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:51'! checkForConversionMethods "See if any conversion methods are needed" | oldStruct newStruct tell choice list need sel renamed rec nn | Preferences conversionMethodsAtFileOut ifFalse: [^ self]. "Check preference" structures ifNil: [^ self]. list _ OrderedCollection new. renamed _ OrderedCollection new. self changedClasses do: [:class | need _ (self atClass: class includes: #new) not. need ifTrue: ["Renamed classes." (self atClass: class includes: #rename) ifTrue: [ rec _ changeRecords at: class name. rec priorName ifNotNil: [ (structures includesKey: rec priorName) ifTrue: [ renamed add: class. need _ false]]]]. need ifTrue: [need _ (self atClass: class includes: #change)]. need ifTrue: [oldStruct _ structures at: class name ifAbsent: [need _ false. #()]]. need ifTrue: [ newStruct _ (Array with: class classVersion), (class allInstVarNames). need _ (oldStruct ~= newStruct)]. need ifTrue: [sel _ #convertToCurrentVersion:refStream:. (#(add change) includes: (self atSelector: sel class: class)) ifFalse: [ list add: class]]. ]. list isEmpty & renamed isEmpty ifTrue: [^ self]. "Ask user if want to do this" tell _ 'If there might be instances of ', (list asArray, renamed asArray) printString, '\in a project (.pr file) on someone''s disk, \please ask to write a conversion method.\' withCRs, 'After you edit the conversion method, you''ll need to fileOut again.\' withCRs, 'The preference conversionMethodsAtFileOut in category "fileout" controls this feature.'. choice _ (PopUpMenu labels: 'Write a conversion method by editing a prototype These classes are not used in any object file. fileOut my changes now. I''m too busy. fileOut my changes now. Don''t ever ask again. fileOut my changes now.') startUpWithCaption: tell. choice = 4 ifTrue: [Preferences disable: #conversionMethodsAtFileOut]. choice = 2 ifTrue: ["Don't consider this class again in the changeSet" list do: [:cls | structures removeKey: cls name ifAbsent: []]. renamed do: [:cls | nn _ (changeRecords at: cls name) priorName. structures removeKey: nn ifAbsent: []]]. choice ~= 1 ifTrue: [^ self]. "exit if choice 2,3,4" self error:'No support for writing conversion methods in this stripped image'! ! !ChangeSet methodsFor: 'private' stamp: 'ssa 9/3/2008 10:28'! fileOutClassDefinition: class on: stream "Write out class definition for the given class on the given stream, if the class definition was added or changed." (self atClass: class includes: #rename) ifTrue: [stream nextChunkPut: 'Smalltalk renameClassNamed: #', (self oldNameFor: class), ' as: #', class name; cr]. (self atClass: class includes: #change) ifTrue: [ "fat definition only needed for changes" stream command: 'H3'; nextChunkPut: (self fatDefForClass: class); cr; command: '/H3'. ] ifFalse: [ (self atClass: class includes: #add) ifTrue: [ "use current definition for add" stream command: 'H3'; nextChunkPut: class definition; cr; command: '/H3'. ]. ]. (self atClass: class includes: #comment) ifTrue: [class theNonMetaClass organization putCommentOnFile: stream numbered: 0 moveSource: false forClass: class theNonMetaClass. stream cr]. ! ! !ChangeSet methodsFor: '*transporter' stamp: 'ads 1/26/2011 14:23'! changedPackages | changedPackages nonCategoryBasedPackages | nonCategoryBasedPackages := Transporter nonCategoryBasedPackages. changedPackages := Set new. self changedMessageList do: [:m | changedPackages add: (PackageInfo named: m topLevelPackageName). changedPackages addAll: (nonCategoryBasedPackages select: [:p | p includesMethod: m methodSymbol ofClass: m actualClass]). ]. self changedClasses do: [:c | (self changeRecords at: c name) hasTheClassItselfChanged ifTrue: [ changedPackages add: (PackageInfo named: c topLevelPackageName). changedPackages addAll: (nonCategoryBasedPackages select: [:p | p includesClass: c]). ]. ]. ^ changedPackages! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'sw 7/17/2002 11:37'! changeSetListKey: aChar from: view "Respond to a Command key. I am a model with a listView that has a list of changeSets." aChar == $b ifTrue: [^ self browseChangeSet]. aChar == $B ifTrue: [^ self openChangeSetBrowser]. aChar == $c ifTrue: [^ self copyAllToOther]. aChar == $D ifTrue: [^ self toggleDiffing]. aChar == $f ifTrue: [^ self findCngSet]. aChar == $m ifTrue: [^ self newCurrent]. aChar == $n ifTrue: [^ self newSet]. aChar == $o ifTrue: [^ self fileOut]. aChar == $p ifTrue: [^ self addPreamble]. aChar == $r ifTrue: [^ self rename]. aChar == $s ifTrue: [^ self chooseChangeSetCategory]. aChar == $x ifTrue: [^ self remove]. aChar == $- ifTrue: [^ self subtractOtherSide]. ^ self messageListKey: aChar from: view! ! !ChangeSorter methodsFor: 'changeSet menu' stamp: 'BG 10/29/2003 08:09'! changeSetMenu: aMenu shifted: isShifted "Set up aMenu to hold commands for the change-set-list pane. This could be for a single or double changeSorter" isShifted ifTrue: [^ self shiftedChangeSetMenu: aMenu]. Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu title: 'Change Set: ' , myChangeSet name]. aMenu add: 'make changes go to me (m)' action: #newCurrent. aMenu addLine. aMenu add: 'new change set... (n)' action: #newSet. aMenu add: 'find...(f)' action: #findCngSet. aMenu add: 'show category... (s)' action: #chooseChangeSetCategory. aMenu balloonTextForLastItem: 'Lets you choose which change sets should be listed in this change sorter'. aMenu add: 'select change set...' action: #chooseCngSet. aMenu addLine. aMenu add: 'rename change set (r)' action: #rename. aMenu add: 'file out (o)' action: #fileOut. " aMenu add: 'mail to list' action: #mailOut. " aMenu add: 'browse methods (b)' action: #browseChangeSet. aMenu add: 'browse change set (B)' action: #openChangeSetBrowser. aMenu addLine. parent ifNotNil: [aMenu add: 'copy all to other side (c)' action: #copyAllToOther. aMenu add: 'submerge into other side' action: #submergeIntoOtherSide. aMenu add: 'subtract other side (-)' action: #subtractOtherSide. aMenu addLine]. myChangeSet hasPreamble ifTrue: [aMenu add: 'edit preamble (p)' action: #addPreamble. aMenu add: 'remove preamble' action: #removePreamble] ifFalse: [aMenu add: 'add preamble (p)' action: #addPreamble]. myChangeSet hasPostscript ifTrue: [aMenu add: 'edit postscript...' action: #editPostscript. aMenu add: 'remove postscript' action: #removePostscript] ifFalse: [aMenu add: 'add postscript...' action: #editPostscript]. aMenu addLine. aMenu add: 'category functions...' action: #offerCategorySubmenu. aMenu balloonTextForLastItem: 'Various commands relating to change-set-categories'. aMenu addLine. aMenu add: 'destroy change set (x)' action: #remove. aMenu addLine. aMenu add: 'more...' action: #offerShiftedChangeSetMenu. ^ aMenu! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:28'! classListKey: aChar from: view "Respond to a Command key in the class-list pane." aChar == $x ifTrue: [^ self removeClass]. aChar == $d ifTrue: [^ self forgetClass]. aChar == $m ifTrue: [^ self moveClassToOther]. ^ self messageListKey: aChar from: view "picks up b,h,p"! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:24'! classListMenu: aMenu shifted: shifted "Fill aMenu with items appropriate for the class list" aMenu title: 'class list'. (parent notNil and: [shifted not]) ifTrue: [aMenu addList: #( "These two only apply to dual change sorters" ('copy class chgs to other side' copyClassToOther) ('move class chgs to other side (m)' moveClassToOther) ('copy chgs to other side from classes matching...' copyClassesToOtherMatching) ('move chgs to other side from classes matching...' moveClassesToOtherMatching) )]. aMenu addList: (shifted ifFalse: [#( - ('delete class from change set (d)' forgetClass) ('remove class from system (x)' removeClass) - ('browse full (b)' browseMethodFull) ('browse hierarchy (h)' spawnHierarchy) ('browse protocol (p)' browseFullProtocol) - ('printOut' printOutClass) ('fileOut' fileOutClass) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' browseClassVarRefs) ('class vars' browseClassVariables) ('class refs (N)' browseClassRefs) - ('more...' offerShiftedClassListMenu))] ifTrue: [#( - ('unsent methods' browseUnusedMethods) ('unreferenced inst vars' showUnreferencedInstVars) ('unreferenced class vars' showUnreferencedClassVars) - ('sample instance' makeSampleInstance) ('inspect instances' inspectInstances) ('inspect subinstances' inspectSubInstances) - ('more...' offerUnshiftedClassListMenu ))]). ^ aMenu! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:13'! copyClassesToOtherMatching "Adsk the user for a pattern. Copy matching changes from this changeset in the other changeSet" | otherSorter otherChangeSet pattern classNamesToCopy | self checkThatSidesDiffer: [^ self halt]. self okToChange ifFalse: [^ self halt]. otherSorter _ parent other: self. otherChangeSet _ otherSorter changeSet. pattern _ FillInTheBlank request: 'Enter a pattern to match to the class to copy changes: # = single character wildcard * = many character wildcard'. ''. pattern isEmpty ifTrue: [^ self ]. classNamesToCopy _ OrderedCollection new. self changeSet changedClassNames do: [:nm | (pattern match: nm) ifTrue:[classNamesToCopy add: nm]]. classNamesToCopy do:[:clsnm| otherChangeSet absorbClass: clsnm from: myChangeSet]. otherSorter showChangeSet: otherChangeSet.! ! !ChangeSorter methodsFor: 'class list' stamp: 'ssa 1/5/2010 21:22'! moveClassesToOtherMatching "Adsk the user for a pattern. Move matching changes from this changeset in the other changeSet" | otherSorter otherChangeSet pattern classNamesToCopy | self checkThatSidesDiffer: [^ self halt]. self okToChange ifFalse: [^ self halt]. otherSorter _ parent other: self. otherChangeSet _ otherSorter changeSet. pattern _ FillInTheBlank request: 'Enter a pattern to match to the class to copy changes: # = single character wildcard * = many character wildcard'. ''. pattern isEmpty ifTrue: [^ self ]. classNamesToCopy _ OrderedCollection new. self changeSet changedClassNames do: [:nm | (pattern match: nm) ifTrue:[classNamesToCopy add: nm]]. classNamesToCopy do:[:clsnm| otherChangeSet absorbClass: clsnm from: myChangeSet. myChangeSet removeClassChanges: clsnm]. currentClassName _ nil. currentSelector _ nil. self showChangeSet: myChangeSet. otherSorter showChangeSet: otherChangeSet.! ! !ChangeSorter class methodsFor: 'adding' stamp: 'sm 3/11/2011 11:29'! basicNewChangeSet: newName | newSet | newName ifNil: [^ nil]. (self changeSetNamed: newName) ifNotNil: [self inform: 'Sorry that name is already used: ', newName. ^ nil]. newSet _ ChangeSet basicNewNamed: newName. AllChangeSets add: newSet. ^ newSet! ! !ChangeSorter class methodsFor: 'fileIn/Out' stamp: 'ssa 9/3/2008 10:33'! fileIntoNewChangeSet: fullName "File in all of the contents of the currently selected file, if any, into a new change set." | fn ff | fullName ifNil: [^ Beeper beep]. ff _ FileStream readOnlyFileNamed: (fn _ fullName). ((FileDirectory extensionFor: fn) sameAs: 'html') ifTrue: [ff _ ff asHtml]. self newChangesFromStream: ff named: (FileDirectory localNameFor: fn)! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:17'! changedMethods "ChangedMethodFinder new changedMethods" | result | result _ OrderedCollection new. Smalltalk allClassesDo: [:cls| {cls. cls class.} do: [:clsHalf| clsHalf methodDict associationsDo: [:a | (self isMethodChanged: a value) ifTrue: [ result add: { cls category. cls name. clsHalf name. clsHalf organization categoryOfElement: a key. a key} ] ] ] ]. ^ result! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:19'! changedMethodsInStandardClasses "ChangedMethodFinder new changedMethodsInStandardClasses" | changedMethods standardClassNames result | changedMethods _ self changedMethods. standardClassNames _ self standardClassNames. result _ changedMethods select: [:e| standardClassNames includes: (e at: 2)]. ^ result! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 15:56'! isMethodChanged: aMethod ^ (SourceFiles at: 1) ~= aMethod sourceFileStream! ! !ChangedMethodFinder methodsFor: 'as yet unclassified' stamp: 'dmu 8/25/2010 16:17'! standardClassNames "ChangedMethodFinder new standardClassNames" | result | result _ Set new. Smalltalk allClassesDo: [:cls| {cls. cls class.} do: [:clsHalf| clsHalf methodDict associationsDo: [:a | (self isMethodChanged: a value) ifFalse: [result add: cls name] ] ] ]. ^ result! ! !Character methodsFor: 'testing' stamp: 'ssa 8/11/2009 12:37'! isCharacter ^true! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:29'! at: index index > 1 ifTrue:[^super at: index]. ^self! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:25'! doesNotUnderstand: aMessage "Hack DNU to make chars act like strings" ^self asString perform: aMessage selector withArguments: aMessage arguments! ! !Character methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:28'! size ^1! ! !Character methodsFor: '*packageinfo-base' stamp: 'ab 5/31/2003 17:15'! escapeEntities #($< '<' $> '>' $& '&') pairsDo: [:k :v | self = k ifTrue: [^ v]]. ^ String with: self! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowDown ^ self value: 31! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowLeft ^ self value: 28! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowRight ^ self value: 29! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! arrowUp ^ self value: 30! ! !Character class methodsFor: 'accessing untypeable characters'! backspace "Answer the Character representing a backspace." ^self value: 8! ! !Character class methodsFor: 'accessing untypeable characters'! cr "Answer the Character representing a carriage return." ^self value: 13! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! delete ^ self value: 127! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! end ^ self value: 4! ! !Character class methodsFor: 'accessing untypeable characters'! enter "Answer the Character representing enter." ^self value: 3! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ls 9/2/1999 08:06'! escape "Answer the ASCII ESC character" ^self value: 27! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'sma 3/15/2000 22:33'! euro "The Euro currency sign, that E with two dashes. The key code is a wild guess" ^ Character value: 219! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! home ^ self value: 1! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:19'! insert ^ self value: 5! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'ls 9/8/1998 22:15'! lf "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters'! linefeed "Answer the Character representing a linefeed." ^self value: 10! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'wiz 4/9/2006 20:30'! nbsp "non-breakable space. Latin1 encoding common usage." ^ Character value: 160! ! !Character class methodsFor: 'accessing untypeable characters'! newPage "Answer the Character representing a form feed." ^self value: 12! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:20'! pageDown ^ self value: 12! ! !Character class methodsFor: 'accessing untypeable characters' stamp: 'NS 7/11/2000 09:21'! pageUp ^ self value: 11! ! !Character class methodsFor: 'accessing untypeable characters'! space "Answer the Character representing a space." ^self value: 32! ! !Character class methodsFor: 'accessing untypeable characters'! tab "Answer the Character representing a tab." ^self value: 9! ! !CharacterScanner methodsFor: 'scanning' stamp: 'ssa 8/19/2008 21:22'! scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops displaying: foo ^ self scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: 0! ! !CharacterScanner methodsFor: 'accessing' stamp: 'ssa 8/19/2008 21:15'! destX: x destX := x! ! !CharacterSet methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:50'! addAll: aCollection aCollection do:[:char| self add: char]! ! !CharacterSet methodsFor: '*Ly' stamp: 'ssa 8/18/2009 12:52'! removeAll: aCollection aCollection do:[:char| self remove: char]! ! !Class methodsFor: '*transporter' stamp: 'ads 12/14/2010 10:27'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." ^self fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock initializing: true! ! !Class methodsFor: '*transporter' stamp: 'ads 12/14/2010 10:29'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock initializing: aBool "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." Transcript cr; show: name. super fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock. self class nonTrivial ifTrue: [aFileStream cr; nextPutAll: '"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!!'; cr; cr. self class fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock initializing: aBool]! ! !Class methodsFor: '*SUnit-initialize-release' stamp: 'sm 5/25/2011 00:57'! removeFromChanges "References to the receiver, a class, and its metaclass should no longer be included in the system ChangeSet. 7/18/96 sw: call removeClassAndMetaClassChanges:" ChangeSet current removeClassAndMetaClassChanges: self! ! !Class methodsFor: '*SUnit-initialize-release' stamp: 'sm 5/25/2011 00:59'! removeFromSystemUnlogged "Forget the receiver from the Smalltalk global dictionary. Any existing instances will refer to an obsolete version of the receiver. Do not log the removal either to the current change set nor to the system changes log" ^self removeFromSystem: false! ! !ClassAndMethodSaver methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 14:01'! save self createRoot. self saveAllClasses.! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:41'! createRoot self rootDirectory: ( self createDir: self rootName in: FileDirectory default mustBeNew: false )! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:04'! rootDirectory "Answer the value of rootDirectory" rootDirectory isNil ifTrue:[self rootDirectory: nil]. ^ rootDirectory! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:04'! rootDirectory: anObject "Set the value of rootDirectory" rootDirectory _ anObject! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:00'! rootName "Answer the value of rootName" rootName isNil ifTrue:[self rootName: 'root']. ^ rootName! ! !ClassAndMethodSaver methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:00'! rootName: anObject "Set the value of rootName" rootName _ anObject! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:35'! classCategoryDirFor: cat ^ self createDir: cat in: self rootDirectory mustBeNew: false! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:34'! createDir: leafName in: parentDir mustBeNew: mustBeNew | p d | p _ parentDir pathName, parentDir pathNameDelimiter, leafName. d _ FileDirectory on: p. (mustBeNew and: [d exists]) ifTrue: [self error: p, ' already exists']. d exists ifFalse: [d assureExistence]. ^ d ! ! !ClassAndMethodSaver methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:38'! createDirectoriesFor: cls | catDir | catDir _ self classCategoryDirFor: cls category. classDir _ self createDir: cls name in: catDir mustBeNew: false. baseDir _ self createDir: 'base' in: classDir mustBeNew: false. metaDir _ self createDir: 'meta' in: classDir mustBeNew: false.! ! !ClassAndMethodSaver methodsFor: 'saving methods' stamp: 'dmu 10/1/2010 22:58'! methodSourceFor: sel in: clsHalf | method | method _ clsHalf methodDict at: sel ifAbsent: [^ sel printString, 'CORRUPTED']. ^ (method getSourceFor: sel in: clsHalf) asString! ! !ClassAndMethodSaver methodsFor: 'saving methods' stamp: 'dmu 10/1/2010 22:59'! saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir | src fs selOrFoo | src _ self methodSourceFor: sel in: clsHalf. selOrFoo _ (sel isKindOf: String) ifTrue: [sel] ifFalse: [sel printString]. fs _ self fileStreamIn: catDir named: selOrFoo, '.txt'. fs nextPutAll: src. fs close ! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:46'! fileStreamIn: dir named: n | fs | fs _ FileStream fileNamed: dir pathName, dir pathNameDelimiter, n. ^ fs! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:01'! saveAllClasses Smalltalk allClassesDo: [:cls| self saveClass: cls]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 15:00'! saveCategory: cat of: clsHalf in: dir | selectors catDir | catDir _ self createDir: cat in: dir mustBeNew: false. selectors := (cat asString = ClassOrganizer allCategory) ifTrue: [ clsHalf organization allMethodSelectors ] ifFalse: [ clsHalf organization listAtCategoryNamed: cat ]. selectors do: [:sel| self saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:39'! saveClass: cls self createDirectoriesFor: cls. self saveClassHalf: cls in: baseDir. self saveClassHalf: cls class in: metaDir! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:52'! saveClassHalf: clsHalf in: dir self saveClassHalfDefinition: clsHalf in: dir. self saveClassHalfComment: clsHalf in: dir. self saveClassHalfCategories: clsHalf in: dir! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:53'! saveClassHalfCategories: clsHalf in: dir clsHalf organization categories do: [:cat | self saveCategory: cat of: clsHalf in: dir]! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 15:15'! saveClassHalfComment: clsHalf in: dir | fs | fs _ self fileStreamIn: dir named: 'comment.txt'. fs nextPutAll: clsHalf organization classComment asString. fs close.! ! !ClassAndMethodSaver methodsFor: 'saving classes' stamp: 'dmu 8/23/2010 14:48'! saveClassHalfDefinition: clsHalf in: dir | fs | fs _ self fileStreamIn: dir named: 'definition.txt'. fs nextPutAll: clsHalf definition. fs close.! ! !ClassAndMethodSaver commentStamp: 'dmu 8/23/2010 13:56' prior: 0! Save all class definitions and method definitions to a directory tree so I can use FileMerge! !ClassAndMethodSaver class methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 16:32'! save "ClassAndMethodSaver save" ^self saveIn: 'root'! ! !ClassAndMethodSaver class methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 13:59'! saveIn: rootName (self new rootName: rootName) save! ! !ClassChangeRecord methodsFor: '*transporter' stamp: 'ads 1/26/2011 14:08'! hasTheClassItselfChanged "Or have there only been method changes?" ^ self allChangeTypes isEmpty not! ! !ClassCommentVersionsBrowser methodsFor: 'basic function' stamp: 'dmu 9/7/2010 14:16'! scanVersionsOf: class "Scan for all past versions of the class comment of the given class" | oldCommentRemoteStr sourceFilesCopy position prevPos stamp preamble tokens prevFileIndex | classOfMethod _ class. oldCommentRemoteStr _ class organization commentRemoteStr. currentCompiledMethod _ oldCommentRemoteStr. selectorOfMethod _ #Comment. changeList _ OrderedCollection new. list _ OrderedCollection new. listIndex _ 0. oldCommentRemoteStr ifNil:[^ nil] ifNotNil: [oldCommentRemoteStr sourcePointer]. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. position _ oldCommentRemoteStr position. file _ sourceFilesCopy at: oldCommentRemoteStr sourceFileNumber. [position notNil & file notNil] whileTrue: [ file position: (0 max: position-150). " Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. prevPos _ nil. stamp _ ''. (preamble findString: 'commentStamp:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble. (tokens at: tokens size-3) = #commentStamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos]] ifFalse: ["The stamp get lost, maybe after a condenseChanges" stamp _ '<historical>']. self addItem: (ChangeRecord new file: file position: position type: #classComment class: class name category: nil meta: class stamp: stamp) text: stamp , ' ' , class name , ' class comment'. prevPos = 0 ifTrue:[prevPos _ nil]. position _ prevPos. prevPos notNil ifTrue:[file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !ClassDescription methodsFor: 'printing' stamp: 'dmu 9/6/2010 16:21'! instanceVariablesString "Answer a string of my instance variable names separated by spaces." ^String streamContents: [ :stream | (self instVarNames isKindOf: Number) ifTrue: [stream nextPutAll: 'EEK'] ifFalse: [ self instVarNames do: [ :each | stream nextPutAll: each ] separatedBy: [ stream space ] ]]! ! !ClassDescription methodsFor: 'accessing method dictionary' stamp: 'ssa 10/8/2008 19:00'! allMethodsInCategory: aName "Answer a list of all the method categories of the receiver and all its superclasses " | aColl | aColl _ OrderedCollection new. self withAllSuperclasses do: [:aClass | aColl addAll: (aName = ClassOrganizer allCategory ifTrue: [aClass organization allMethodSelectors] ifFalse: [aClass organization listAtCategoryNamed: aName])]. ^ aColl asSet asSortedArray! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:17'! classComment: aString stamp: aStamp "Store the comment, aString or Text or RemoteString, associated with the class we are organizing. Empty string gets stored only if had a non-empty one before." | ptr header file oldCommentRemoteStr | (aString isKindOf: RemoteString) ifTrue: [SystemChangeNotifier uniqueInstance classCommented: self. ^ self organization classComment: aString stamp: aStamp]. oldCommentRemoteStr _ self organization commentRemoteStr. (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ self organization classComment: nil]. "never had a class comment, no need to write empty string out" ptr _ oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer]. SourceFiles ifNotNil: [(file _ SourceFiles at: 2) ifNotNil: [ file safelyDo: [ file setToEnd; cr; nextPut: $!!. "directly" "Should be saying (file command: 'H3') for HTML, but ignoring it here" header _ String streamContents: [:strm | strm nextPutAll: self name; nextPutAll: ' commentStamp: '. aStamp storeOn: strm. strm nextPutAll: ' prior: '; nextPutAll: ptr printString]. file nextChunkPut: header]]]. self organization classComment: (RemoteString newString: aString onFileNumber: 2) stamp: aStamp. SystemChangeNotifier uniqueInstance classCommented: self. ! ! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'dmu 9/7/2010 14:22'! printMethodChunk: selector withPreamble: doPreamble on: outStream moveSource: moveSource toFile: fileIndex "Copy the source code for the method associated with selector onto the fileStream. If moveSource true, then also set the source code pointer of the method." | preamble method oldPos newPos sourceFile endPos | doPreamble ifTrue: [preamble _ self name , ' methodsFor: ' , (self organization categoryOfElement: selector) asString printString] ifFalse: [preamble _ '']. method _ self methodDict at: selector. ((method fileIndex = 0 or: [(SourceFiles at: method fileIndex) == nil]) or: [(oldPos _ method filePosition) = 0]) ifTrue: ["The source code is not accessible. We must decompile..." preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr]. outStream nextChunkPut: (self decompilerClass new decompile: selector in: self method: method) decompileString] ifFalse: [sourceFile _ SourceFiles at: method fileIndex. sourceFile safelyDo: [ sourceFile position: oldPos. preamble size > 0 ifTrue: "Copy the preamble" [outStream copyPreamble: preamble from: sourceFile]. "Copy the method chunk" newPos _ outStream position. outStream copyMethodChunkFrom: sourceFile. sourceFile skipSeparators. "[" "The following chunk may have ]style[" "]" sourceFile peek == "[" $] ifTrue: [ outStream cr; copyMethodChunkFrom: sourceFile]. moveSource ifTrue: "Set the new method source pointer" [endPos _ outStream position. method checkOKToAdd: endPos - newPos at: newPos. method setSourcePosition: newPos inFile: fileIndex]]]. preamble size > 0 ifTrue: [outStream nextChunkPut: ' ']. ^ outStream cr! ! !ClassDescription methodsFor: '*transporter' stamp: 'StefanMarr 3/12/2011 10:14'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock "File a description of the receiver on aFileStream. If the boolean argument, moveSource, is true, then set the trailing bytes to the position of aFileStream and to fileIndex in order to indicate where to find the source code." aFileStream nextChunkPut: self definition. self organization putCommentOnFile: aFileStream numbered: fileIndex moveSource: moveSource forClass: self. self organization categories do: [:heading | (catFilterBlock value: heading value: self) ifTrue: [ self fileOutCategory: heading on: aFileStream moveSource: moveSource toFile: fileIndex]]! ! !ClassDescription methodsFor: '*transporter' stamp: 'ads 12/5/2010 23:14'! methodNamed: aSymbol ^ MethodReference new setStandardClass: self methodSymbol: aSymbol! ! !ClassDescription methodsFor: '*transporter' stamp: 'ads 1/26/2011 13:35'! topLevelPackageName ^ self theNonMetaClass category asString copyUpTo: $-! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 14:21'! createdClassNames ^self createdClasses collect: [:class| class name]! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 13:59'! createdClasses ^createdClasses! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 14:01'! createdClasses: classes createdClasses := classes asIdentitySet ! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 16:37'! defaultCategory ^ (self packageName , '-', self defaultCategoryPostfix) asSymbol! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 16:23'! defaultCategoryPostfix ^ #Default! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'NouryBouraqadi 12/18/2010 18:46'! defaultSuperclass ^Object! ! !ClassFactoryForTestCase methodsFor: 'accessing' stamp: 'Noury 10/26/2008 16:20'! packageName ^#CategoryForTestToBeDeleted! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 16:26'! cleanUp | createdClassNames | createdClassNames := self createdClassNames. self deleteClasses. self deletePackage. self cleanUpChangeSetForClassNames: createdClassNames! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 14:20'! cleanUpChangeSetForClassNames: classeNames | changeSet | changeSet := ChangeSet current. classeNames do: [:name| changeSet removeClassChanges: name; removeClassChanges: name, ' class']. ! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 12:47'! delete: aClass aClass isObsolete ifTrue: [^self]. aClass removeFromChanges. aClass removeFromSystemUnlogged ! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 12:46'! deleteClasses self createdClasses do: [:class| self delete: class]! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 16:33'! deletePackage | categoriesMatchString | categoriesMatchString := self packageName, '-*'. SystemOrganization removeCategoriesMatching: categoriesMatchString! ! !ClassFactoryForTestCase methodsFor: 'cleaning' stamp: 'Noury 10/26/2008 14:01'! initialize super initialize. self createdClasses: IdentitySet new! ! !ClassFactoryForTestCase methodsFor: 'creating' stamp: 'NouryBouraqadi 12/18/2010 18:46'! newClass ^self newSubclassOf: self defaultSuperclass instanceVariableNames: '' classVariableNames: ''! ! !ClassFactoryForTestCase methodsFor: 'creating' stamp: 'NouryBouraqadi 12/18/2010 18:48'! newClassInCategory: category ^self newSubclassOf: self defaultSuperclass instanceVariableNames: '' classVariableNames: '' category: category! ! !ClassFactoryForTestCase methodsFor: 'creating' stamp: 'Noury 11/12/2009 17:53'! newName | postFix | postFix := (self createdClasses size + 1) printString. ^(#ClassForTestToBeDeleted, postFix) asSymbol! ! !ClassFactoryForTestCase methodsFor: 'creating' stamp: 'Noury 10/26/2008 16:25'! newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString ^self newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: self defaultCategoryPostfix! ! !ClassFactoryForTestCase methodsFor: 'creating' stamp: 'Noury 10/26/2008 16:36'! newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: category | newClass | newClass := aClass subclass: self newName instanceVariableNames: ivNamesString classVariableNames: classVarsString poolDictionaries: '' category: (self packageName, '-', category) asSymbol. self createdClasses add: newClass. ^newClass! ! !ClassFactoryForTestCase commentStamp: 'LaurentLaffont 4/15/2011 20:20' prior: 0! I'm useful when classes needs to be created during the execution of the test. This avoid polluting your unit tests with dummy and mock classes. A typical usage of it is: TestCase subclass: #YourTest instanceVariableNames: 'classFactory' YourTest>>setUp classFactory := ClassFactoryForTestCase new YourTest>>tearDown classFactory deleteClasses. YourTest>>testIsBehavior | cls | cls := classFactory newClass. self assert: cls isBehavior ! !ClassFactoryForTestCaseTest methodsFor: 'setUp-tearDown' stamp: 'Noury 10/26/2008 12:19'! setUp super setUp. factory := ClassFactoryForTestCase new! ! !ClassFactoryForTestCaseTest methodsFor: 'setUp-tearDown' stamp: 'Noury 10/26/2008 14:53'! tearDown super tearDown. factory cleanUp! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:43'! testClassCreationInDifferentCategories | firstThreeClasses lastTwoClasses | 3 timesRepeat: [ factory newSubclassOf: Object instanceVariableNames: '' classVariableNames: '' category: #One]. firstThreeClasses := factory createdClasses copy. 2 timesRepeat: [ factory newSubclassOf: Object instanceVariableNames: '' classVariableNames: '' category: #Two]. lastTwoClasses := factory createdClasses copyWithoutAll: firstThreeClasses. self assert: (firstThreeClasses allSatisfy: [:class| class category = (factory packageName, '-', #One) asSymbol]). self assert: (lastTwoClasses allSatisfy: [:class| class category = (factory packageName, '-', #Two) asSymbol]).! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:42'! testClassFastCreationInDifferentCategories | firstThreeClasses lastTwoClasses | 3 timesRepeat: [ factory newClassInCategory: #One]. firstThreeClasses := factory createdClasses copy. 2 timesRepeat: [ factory newClassInCategory: #Two]. lastTwoClasses := factory createdClasses copyWithoutAll: firstThreeClasses. self assert: (firstThreeClasses allSatisfy: [:class| class category = (factory packageName, '-', #One) asSymbol]). self assert: (lastTwoClasses allSatisfy: [:class| class category = (factory packageName, '-', #Two) asSymbol]).! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:44'! testDefaultCategoryCleanUp | createdClassNames allClasses | 3 timesRepeat: [ factory newClass]. createdClassNames := factory createdClassNames. factory cleanUp. self assert: (factory createdClasses allSatisfy: [:class| class isObsolete]). allClasses := SystemNavigation new allClasses. self assert: (factory createdClasses noneSatisfy: [:class| allClasses includes: class]). self deny: (SystemOrganization categories includes: factory defaultCategory). self deny: (ChangeSet current changedClassNames includesAnyOf: createdClassNames) ! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:38'! testMultipleClassCreation 5 timesRepeat: [ factory newClass]. self assert: (SystemNavigation new allClasses includesAllOf: factory createdClasses). self assert: factory createdClassNames asSet size = 5. self assert: (SystemOrganization listAtCategoryNamed: factory defaultCategory) asSet = factory createdClassNames asSet! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:47'! testPackageCleanUp | createdClassNames allClasses | 3 timesRepeat: [ factory newClassInCategory: #One]. 2 timesRepeat: [ factory newClassInCategory: #Two]. createdClassNames := factory createdClassNames. factory cleanUp. self assert: (factory createdClasses allSatisfy: [:class| class isObsolete]). allClasses := SystemNavigation new allClasses. self assert: (factory createdClasses noneSatisfy: [:class| allClasses includes: class]). self assert: (SystemOrganization categoriesMatching: factory packageName, '*') isEmpty. self deny: (ChangeSet current changedClassNames includesAnyOf: createdClassNames) ! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'nice 12/3/2009 23:47'! testSingleClassCreation |class elementsInCategoryForTest | class := factory newSubclassOf: Object instanceVariableNames: 'a b c' classVariableNames: 'X Y'. self assert: (SystemNavigation new allClasses includes: class). elementsInCategoryForTest := SystemOrganization listAtCategoryNamed: factory defaultCategory. self assert: elementsInCategoryForTest = {class name}. self assert: class instVarNames = #(a b c). self assert: class classPool keys asSet = #(X Y) asSet! ! !ClassFactoryForTestCaseTest methodsFor: 'testing' stamp: 'Noury 10/26/2008 16:37'! testSingleClassFastCreation |class elementsInCategoryForTest | class := factory newClass. self assert: (SystemNavigation new allClasses includes: class). elementsInCategoryForTest := SystemOrganization listAtCategoryNamed: factory defaultCategory. self assert: elementsInCategoryForTest = {class name}. self assert: class instVarNames isEmpty. self assert: class classPool isEmpty! ! !ClassFactoryForTestCaseTest class methodsFor: 'history' stamp: 'simon.denier 11/22/2008 22:13'! lastStoredRun ^ ((Dictionary new) add: (#passed->((Set new) add: #testDefaultCategoryCleanUp; add: #testPackageCleanUp; add: #testSingleClassCreation; add: #testClassCreationInDifferentCategories; add: #testClassFastCreationInDifferentCategories; add: #testMultipleClassCreation; add: #testSingleClassFastCreation; yourself)); add: (#timeStamp->'22 November 2008 10:11:35 pm'); add: (#failures->((Set new))); add: (#errors->((Set new))); yourself)! ! !ClassFactoryWithOrganization methodsFor: 'accessing' stamp: 'LucFabresse 10/24/2010 20:31'! organization ^organization! ! !ClassFactoryWithOrganization methodsFor: 'accessing' stamp: 'LucFabresse 10/24/2010 20:31'! organization: aSystemOrganizer organization := aSystemOrganizer! ! !ClassFactoryWithOrganization methodsFor: 'cleaning' stamp: 'LucFabresse 10/24/2010 22:01'! deletePackage | categoriesMatchString | categoriesMatchString := self packageName, '-*'. self organization removeCategoriesMatching: categoriesMatchString ; removeEmptyCategories ! ! !ClassFactoryWithOrganization methodsFor: 'creating' stamp: 'LucFabresse 10/29/2010 08:04'! newClassNamed: aString subclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString ^self newClassNamed: aString subclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: (self packageName, '-', self defaultCategoryPostfix) asSymbol.! ! !ClassFactoryWithOrganization methodsFor: 'creating' stamp: 'LucFabresse 10/29/2010 08:03'! newClassNamed: aString subclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: category | newClass | newClass := (ClassBuilder new) name: aString inEnvironment: self organization environment subclassOf: aClass type: aClass typeOfClass instanceVariableNames: ivNamesString classVariableNames: classVarsString poolDictionaries: '' category: category asSymbol. self createdClasses add: newClass. ^newClass! ! !ClassFactoryWithOrganization methodsFor: 'creating' stamp: 'LucFabresse 10/24/2010 21:41'! newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString ^self newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: (self packageName, '-', self defaultCategoryPostfix) asSymbol.! ! !ClassFactoryWithOrganization methodsFor: 'creating' stamp: 'LucFabresse 10/24/2010 21:35'! newSubclassOf: aClass instanceVariableNames: ivNamesString classVariableNames: classVarsString category: category | newClass | newClass := (ClassBuilder new) name: self newName inEnvironment: self organization environment subclassOf: aClass type: aClass typeOfClass instanceVariableNames: ivNamesString classVariableNames: classVarsString poolDictionaries: '' category: category asSymbol. self createdClasses add: newClass. ^newClass! ! !ClassFactoryWithOrganization commentStamp: 'LaurentLaffont 5/4/2011 21:25' prior: 0! I'm a class to create classes with a category. I'm only used by Tests. I am similar to ClassFactoryForTestCase (i.e., I can be used in place of a ClassFactoryForTestCase), expect that classes may be created on a specific class category.! !ClassFactoryWithOrganization class methodsFor: 'instance creation' stamp: 'LucFabresse 10/24/2010 20:33'! newWithOrganization: aSystemOrganizer ^self new organization: aSystemOrganizer; yourself! ! !ClassFactoryWithOrganizationTest methodsFor: 'accessing' stamp: 'LucFabresse 10/24/2010 19:57'! testedEnvironment ^self testedOrganization environment! ! !ClassFactoryWithOrganizationTest methodsFor: 'accessing' stamp: 'LucFabresse 10/24/2010 20:31'! testedOrganization ^factory organization! ! !ClassFactoryWithOrganizationTest methodsFor: 'setUp-tearDown' stamp: 'LucFabresse 12/19/2010 12:42'! setUp | environment | super setUp. environment := SystemDictionary withOrganizer: SystemOrganizer new. factory := ClassFactoryWithOrganization newWithOrganization: environment organization. ! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:48'! assertEnvironmentOf: aBehavior self assert: aBehavior environment = self testedEnvironment! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'sm 5/25/2011 01:15'! expectedFailures ^ self class allTestSelectors! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/29/2010 09:09'! testClassCreationInDifferentCategories | firstThreeClasses lastTwoClasses | 3 timesRepeat: [ factory newSubclassOf: Object instanceVariableNames: '' classVariableNames: '' category: #One]. firstThreeClasses := factory createdClasses copy. 2 timesRepeat: [ factory newSubclassOf: Object instanceVariableNames: '' classVariableNames: '' category: #Two]. lastTwoClasses := factory createdClasses copyWithoutAll: firstThreeClasses. self assert: (firstThreeClasses allSatisfy: [:class| class category = #One]). self assert: (lastTwoClasses allSatisfy: [:class| class category = #Two]). factory createdClasses do: [ :aClass | self assertEnvironmentOf: aClass ]! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/29/2010 09:14'! testClassFastCreationInDifferentCategories | firstThreeClasses lastTwoClasses | 3 timesRepeat: [ factory newClassInCategory: #One]. firstThreeClasses := factory createdClasses copy. 2 timesRepeat: [ factory newClassInCategory: #Two]. lastTwoClasses := factory createdClasses copyWithoutAll: firstThreeClasses. self assert: (firstThreeClasses allSatisfy: [:class| class category = #One]). self assert: (lastTwoClasses allSatisfy: [:class| class category = #Two]). factory createdClasses do: [ :aClass | self assertEnvironmentOf: aClass ]! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:41'! testDefaultCategoryCleanUp | createdClassNames allClasses | 3 timesRepeat: [ factory newClass]. createdClassNames := factory createdClassNames. factory cleanUp. self assert: (factory createdClasses allSatisfy: [:class| class isObsolete]). allClasses := self testedEnvironment allClasses. self assert: (factory createdClasses noneSatisfy: [:class| allClasses includes: class]). self deny: (self testedOrganization categories includes: factory defaultCategory). self deny: (ChangeSet current changedClassNames includesAnyOf: createdClassNames) ! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:50'! testMultipleClassCreation 5 timesRepeat: [ factory newClass]. self assert: (self testedEnvironment allClasses includesAllOf: factory createdClasses). self assert: factory createdClassNames asSet size = 5. self assert: (self testedOrganization listAtCategoryNamed: factory defaultCategory) asSet = factory createdClassNames asSet. factory createdClasses do: [ :aClass | self assertEnvironmentOf: aClass ]! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:50'! testPackageCleanUp | createdClassNames allClasses | 3 timesRepeat: [ factory newClassInCategory: #One]. 2 timesRepeat: [ factory newClassInCategory: #Two]. createdClassNames := factory createdClassNames. factory cleanUp. self assert: (factory createdClasses allSatisfy: [:class| class isObsolete]). allClasses := self testedEnvironment allClasses. self assert: (factory createdClasses noneSatisfy: [:class| allClasses includes: class]). self assert: (self testedOrganization categoriesMatching: factory packageName, '*') isEmpty. self deny: (ChangeSet current changedClassNames includesAnyOf: createdClassNames). ! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:51'! testSingleClassCreation |class elementsInCategoryForTest | class := factory newSubclassOf: Object instanceVariableNames: 'a b c' classVariableNames: 'X Y'. self assert: (self testedEnvironment allClasses includes: class). factory createdClasses do: [ :aClass | self assertEnvironmentOf: aClass ]. elementsInCategoryForTest := self testedOrganization listAtCategoryNamed: factory defaultCategory. self assert: elementsInCategoryForTest = {class name}. self assert: class instVarNames = #(a b c). self assert: class classPool keys asSet = #(X Y) asSet! ! !ClassFactoryWithOrganizationTest methodsFor: 'testing' stamp: 'LucFabresse 10/24/2010 19:51'! testSingleClassFastCreation |class elementsInCategoryForTest | class := factory newClass. self assert: (self testedEnvironment allClasses includes: class). elementsInCategoryForTest := self testedOrganization listAtCategoryNamed: factory defaultCategory. factory createdClasses do: [ :aClass | self assertEnvironmentOf: aClass ]. self assert: elementsInCategoryForTest = {class name}. self assert: class instVarNames isEmpty. self assert: class classPool isEmpty! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! centralClass "Answer the value of centralClass" centralClass isNil ifTrue:[self centralClass: nil]. ^ centralClass! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! centralClass: anObject "Set the value of centralClass" centralClass _ anObject! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 11:52'! getCentralItem ^Array with: (ClassHierarchyExplorerWrapper with: self centralClass name: self centralClass name model: self) ! ! !ClassHierarchyExplorer methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:22'! getList | classList prev | classList _ OrderedCollection new. self centralClass allSuperclasses reverseDo: [:aClass | classList add: aClass]. classList add: self centralClass. self centralClass subclassesDo: [:aClass| classList add: aClass]. prev _nil. ^(classList collect:[:cls| prev _ ClassHierarchyExplorerWrapper with: cls name: cls name model: self parent: prev]) asArray! ! !ClassHierarchyExplorer methodsFor: 'user interface' stamp: 'ssa 3/1/2010 12:01'! explorerFor: anObject withLabel: label | topView listView | self centralClass: anObject. topView := StandardSystemView new label: label; model: self; yourself. topView addSubView:(listView := ExplorerListView on: self list: #list selected: #getCurrentSelection changeSelected: #noteNewSelection: menu: #genericMenu: keystroke: #explorerKey:from:) in: (0 @ 0 corner: 1 @ 1) borderWidth:1. listView autoDeselect: false. ^ topView! ! !ClassHierarchyExplorerWrapper methodsFor: 'testing' stamp: 'ssa 3/1/2010 12:06'! hasContents ^self item subclasses notEmpty ! ! !ClassHierarchyExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:07'! asString ^self itemName! ! !ClassHierarchyExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:04'! contents ^ self item subclasses collect: [:ea| self class with: ea name: ea name model: item parent: self]! ! !ClassHierarchyExplorerWrapper methodsFor: 'printing' stamp: 'ssa 3/1/2010 12:19'! printOn: aStream aStream nextPutAll:self class name,' on: ',self item printString! ! !ClassTestCase methodsFor: 'coverage' stamp: 'brp 7/27/2003 12:39'! classToBeTested self subclassResponsibility! ! !ClassTestCase methodsFor: 'coverage' stamp: 'brp 7/26/2003 16:35'! selectorsNotTested ^ self selectorsToBeTested difference: self selectorsTested. ! ! !ClassTestCase methodsFor: 'coverage'! selectorsTested | literals | literals := Set new. self class selectorsAndMethodsDo: [ :s :m | (s beginsWith: 'test') ifTrue: [ literals addAll: (m messages)] ]. ^ literals asArray sort! ! !ClassTestCase methodsFor: 'coverage' stamp: 'brp 7/26/2003 17:22'! selectorsToBeIgnored ^ #(#DoIt #DoItIn:)! ! !ClassTestCase methodsFor: 'coverage' stamp: 'brp 7/27/2003 12:40'! selectorsToBeTested ^ ( { self classToBeTested. self classToBeTested class } gather: [:c | c selectors]) difference: self selectorsToBeIgnored! ! !ClassTestCase methodsFor: 'tests'! testClassComment self should: [self targetClass organization hasComment].! ! !ClassTestCase methodsFor: 'tests' stamp: 'brp 12/14/2003 15:51'! testCoverage | untested | self class mustTestCoverage ifTrue: [ untested := self selectorsNotTested. self assert: untested isEmpty description: untested size asString, ' selectors are not covered' ]! ! !ClassTestCase methodsFor: 'tests' stamp: 'md 3/25/2003 23:07'! testNew self shouldnt: [self targetClass new] raise: Error.! ! !ClassTestCase methodsFor: 'tests' stamp: 'md 3/26/2003 17:24'! testUnCategorizedMethods | categories slips | categories := self categoriesForClass: self targetClass. slips := categories select: [:each | each = #'as yet unclassified']. self should: [slips isEmpty]. ! ! !ClassTestCase methodsFor: 'private' stamp: 'md 1/28/2004 11:32'! categoriesForClass: aClass ^ aClass organization allMethodSelectors collect: [:each | aClass organization categoryOfElement: each]. ! ! !ClassTestCase methodsFor: 'private' stamp: 'lr 3/14/2010 21:13'! targetClass [ ^ self classToBeTested ] on: Error do: [ | className | className := self class name asText copyFrom: 0 to: self class name size - 4. ^ Smalltalk globals at: className asString asSymbol ]! ! !ClassTestCase commentStamp: 'brp 7/26/2003 16:57' prior: 0! This class is intended for unit tests of individual classes and their metaclasses. It provides methods to determine the coverage of the unit tests. Subclasses are expected to re-implement #classesToBeTested and #selectorsToBeIgnored. They should also implement to confirm that all methods have been tested. #testCoverage super testCoverage. ! !ClassTestCase class methodsFor: 'testing' stamp: 'md 2/22/2006 14:21'! isAbstract "Override to true if a TestCase subclass is Abstract and should not have TestCase instances built from it" ^self name = #ClassTestCase ! ! !ClassTestCase class methodsFor: 'testing' stamp: 'brp 12/14/2003 15:50'! mustTestCoverage ^ false! ! !CodeHolder methodsFor: 'what to show' stamp: 'ssa 9/3/2008 11:02'! addContentsTogglesTo: aMenu "Add updating menu toggles governing contents to aMenu." self contentsSymbolQuints do: [:aQuint | aQuint == #- ifTrue: [aMenu addLine] ifFalse: [Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu add: (('<yes>*' match: (self perform: aQuint third)) ifTrue: ['*'] ifFalse: ['']), aQuint fourth target: self selector: #contentsSymbol: argumentList: { aQuint first } ]]]! ! !CodeHolder methodsFor: 'what to show' stamp: 'ssa 9/3/2008 10:29'! offerWhatToShowMenu "Offer a menu governing what to show" | aMenu | Smalltalk isMorphic ifTrue: [] ifFalse: [aMenu := CustomMenu new. self addContentsTogglesTo: aMenu. aMenu title: 'What to show' translated. aMenu invokeOn: self. self changed: #contents ]! ! !CodeHolder methodsFor: 'tiles' stamp: 'ssa 9/3/2008 11:03'! addModelItemsToWindowMenu: aMenu "Add model-related item to the window menu" super addModelItemsToWindowMenu: aMenu. ! ! !Collection methodsFor: 'accessing' stamp: 'ssa 3/12/2010 17:57'! atRandom "Answer a random element of the receiver. 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." ^ self atRandom: self class randomForPicking "Examples: #('one' 'or' 'the' 'other') atRandom (1 to: 10) atRandom 'Just pick one of these letters at random' atRandom #(3 7 4 9 21) asSet atRandom (just to show it also works for Sets) "! ! !Collection methodsFor: 'converting'! asString: aBlock withDelimiter: aDelimiter "kwa -- 30 November 1988, Answer a string with each of the objects in the receiver (converted to strings by aBlock) separated by aDelimiter." "KSC Extension" | aStream | self isEmpty ifTrue: [^'']. aStream _ WriteStream on: (String new: 64). self do: [:each | aStream nextPutAll: (aBlock value: each). aStream nextPutAll: aDelimiter]. aStream skip: aDelimiter size negated. ^aStream contents "#(13 2 3) asString: [:each | (each * 2) printString] withDelimiter: ', '"! ! !Collection methodsFor: 'converting'! asStringWithDelimiter: aDelimiter "kwa -- 13 May 1988, Answer a string of from the objects in the receiver separated by aDelimiter." "KSC Extension" | aStream | self isEmpty ifTrue: [^'']. aStream _ WriteStream on: (String new: 64). self do: [:each | (each isKindOf: String) ifTrue: [aStream nextPutAll: each asString] ifFalse: [each printOn: aStream]. aStream nextPutAll: aDelimiter]. aStream skip: aDelimiter size negated. ^aStream contents "#(a b 2 3) asStringWithDelimiter: ', '"! ! !Collection methodsFor: 'converting'! asText: aBlock withDelimiter: aDelimiter "kwa -- 30 November 1988, Answer a text with each of the objects in the receiver (converted to texts by aBlock) separated by aDelimiter." "KSC Extension" | aDelimiterText first text | self isEmpty ifTrue: [^'' asText]. aDelimiterText _ aDelimiter asText. first _ true. self do: [:each | first ifTrue: [text _ (aBlock value: each) asText. first _ false] ifFalse: [text _ text, aDelimiterText, (aBlock value: each) asText]]. ^text "(#(13 2 3) asText: [:each | (each * 2) printString asText allBold] withDelimiter: ', ') asDisplayText displayAt: Sensor cursorPoint"! ! !Collection methodsFor: 'enumerating'! collect: aBlock if: aQualifyingBlock "kwa -- 1 February 1989, Evaluate aQualifyingBlock with each of the values of the receiver as the argument. If the result is true, collect the resulting values of aBlock (using the same value as the argument) into a collection that is like the receiver. Answer the new collection." "KSC Extension" | newCollection | newCollection _ self species new. self do: [:each | (aQualifyingBlock value: each) ifTrue: [newCollection add: (aBlock value: each)]]. ^newCollection! ! !Collection methodsFor: '*Sly3' stamp: 'dmu 9/16/2010 23:41'! asEnsembleOfElements ^ Sly3Ensemble withMembersFrom: self! ! !Collection methodsFor: '*Sly' stamp: 'ssa 7/7/2010 19:50'! deactivateEnsembleSendsDuring: aBlock "disable messaging dispatching to members and just send it to myself during aBlock" 0 primitiveSetExtraPreheaderWord: self. aBlock value. self primitiveSetExtraPreheaderWord: self. ! ! !Collection methodsFor: '*Sly' stamp: 'dmu 9/17/2010 11:04'! parallelCollect: aBlock "#(1 2 3 4 5) asOrderedCollection parallelCollect:[:e| e * 2]" | results task barrier result interlock | "true ifTrue: [^ self collect: aBlock.]." "for debugging" self ifEmpty: [^ self]. (Sly3 serializeForDebugging or: [self size = 1]) ifTrue: [^ self collect: aBlock]. results _ self species new. barrier _ RVMBarrier new signalsNeededToPass: self size. interlock _ Semaphore forMutualExclusion. self do:[:each| task _ [ result _ ([aBlock copy fixTemps value: each] ifCurtailed: [barrier signal. "Tasks do:[:eachTask| eachTask terminate]. Tasks _ OrderedCollection new." "self error: 'Yipes!! An ensemble is NLRing back.'." ] ). interlock critical: [results add: result]. barrier signal] asSlyMemberProcess. task resume]. barrier wait. ^results! ! !Collection methodsFor: '*Sly' stamp: 'dmu 9/1/2010 15:17'! product | r | r _ 1. self do: [:e| r _ r * e]. ^ r! ! !Collection methodsFor: '*Sly' stamp: 'dmu 9/8/2010 21:58'! sentToEnsemble: aMessage | r | r _ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage members: self). ^ r! ! !Collection methodsFor: 'removing' stamp: 'ssa 9/9/2009 12:16'! removeAll: aCollection ifAbsent:aBlock "Remove each element of aCollection from the receiver. If successful for each, answer aCollection. Otherwise create an error notification. ArrayedCollections cannot respond to this message." aCollection do: [:each | self remove: each ifAbsent: aBlock]. ^ aCollection! ! !Collection methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:47'! subobjects ^self! ! !Collection methodsFor: '*RVM-converting' stamp: 'dmu 9/16/2010 23:43'! doInParallel: aBlock self parallelCollect: aBlock! ! !Collection methodsFor: '*packageinfo-base' stamp: 'ab 9/30/2002 19:26'! gather: aBlock ^ Array streamContents: [:stream | self do: [:ea | stream nextPutAll: (aBlock value: ea)]]! ! !Color class methodsFor: 'other' stamp: 'ssa 9/13/2008 16:04'! colorChart ^ColorChart! ! !Color class methodsFor: 'other' stamp: 'ssa 9/13/2008 16:04'! colorChart: aChart ColorChart _ aChart! ! !Color class methodsFor: 'color from user' stamp: 'ssa 9/13/2008 15:52'! fromUser "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette." "Note: Since the color chart is cached, you may need to do 'ColorChart _ nil' after changing the oldColorPaletteForDepth:extent: method." "Color fromUser" | d startPt save tr oldColor c here s | d _ Display depth. ((ColorChart == nil) or: [ColorChart depth ~= Display depth]) ifTrue: [ColorChart _ self oldColorPaletteForDepth: d extent: (2 * 144)@80]. startPt _ Sensor cursorPoint "y < Display center y ifTrue: [startPt _ 0@(Display boundingBox bottom - ColorChart height)] ifFalse: [startPt _ 0@0]". save _ Form fromDisplay: (startPt extent: ColorChart extent). ColorChart displayAt: startPt. tr _ ColorChart extent - (50@19) corner: ColorChart extent. tr _ tr translateBy: startPt. oldColor _ nil. [Sensor anyButtonPressed] whileFalse: [ c _ Display colorAt: (here _ Sensor cursorPoint). (tr containsPoint: here) ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c] ifTrue: [ c _ Color transparent. Display fill: (0@61+startPt extent: 20@19) fillColor: Color white]. c = oldColor ifFalse: [ Display fillWhite: (20@61 + startPt extent: 135@19). c isTransparent ifTrue: [s _ 'transparent'] ifFalse: [s _ c shortPrintString. s _ s copyFrom: 7 to: s size - 1]. s displayAt: 20@61 + startPt. oldColor _ c]]. save displayAt: startPt. Sensor waitNoButton. ^ c ! ! !ColorForm methodsFor: 'private' stamp: 'ssa 11/26/2009 22:44'! setExtent: extent depth: bitsPerPixel "Create a virtual bit map with the given extent and bitsPerPixel." | bpp | bpp _ bitsPerPixel. bpp > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits, proceed for 8 bits'. bpp _ 8]. super setExtent: extent depth: bpp. ! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/27/2000 20:08'! mappingToARGB: srcBitMasks "Return a ColorMap mapping from srcBitMasks into canonical ARGB space" ^self mappingFrom: srcBitMasks to: #(16rFF0000 16rFF00 16rFF 16rFF000000)! ! !ColorMap class methodsFor: 'instance creation' stamp: 'ar 5/4/2001 15:59'! masks: maskArray shifts: shiftArray ^self shifts: shiftArray masks: maskArray colors: nil.! ! !CompiledMethod methodsFor: 'printing' stamp: 'ads 1/24/2011 13:02'! longPrintOn: aStream indent: tabs "List of all the byte codes in a method with a short description of each" aStream nextPutAll: (RVMPrimitivesNeededForBootstrapping printPrefixFor: self). self isQuick ifTrue: [self isReturnSpecial ifTrue: [^ aStream tab: tabs; nextPutAll: 'Quick return ' , (#('self' 'true' 'false' 'nil' '-1' '0' '1' '2') at: self primitive - 255)]. ^ aStream nextPutAll: 'Quick return field ' , self returnField printString , ' (0-based)']. self primitive = 0 ifFalse: [ aStream tab: tabs. self printPrimitiveOn: aStream. ]. (InstructionPrinter on: self) indent: tabs; printInstructionsOn: aStream. ! ! !CompiledMethod methodsFor: 'printing' stamp: 'ssa 10/3/2008 18:13'! symbolic "Answer a String that contains a list of all the byte codes in a method with a short description of each." | aStream | aStream _ WriteStream on: (String new: 1000). self longPrintOn: aStream. ^aStream contents! ! !CompiledMethod methodsFor: 'printing' stamp: 'dmu 9/7/2010 14:23'! timeStamp "Answer the authoring time-stamp for the given method, retrieved from the sources or changes file. Answer the empty string if no time stamp is available." "(CompiledMethod compiledMethodAt: #timeStamp) timeStamp" | position file preamble stamp tokens tokenCount | self fileIndex == 0 ifTrue: [^ String new]. "no source pointer for this method" position _ self filePosition. file _ SourceFiles at: self fileIndex. file ifNil: [^ String new]. "sources file not available" "file does not exist happens in secure mode" file _ [file readOnlyCopy] on: FileDoesNotExistException do:[:ex| nil]. file ifNil: [^ String new]. file position: (0 max: position - 150). "Skip back to before the preamble" [file position < (position - 1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. stamp _ String new. tokens _ (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [Scanner new scanTokens: preamble] ifFalse: [Array new "ie cant be back ref"]. (((tokenCount _ tokens size) between: 7 and: 8) and: [(tokens at: tokenCount - 5) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount - 2]]. ((tokenCount between: 5 and: 6) and: [(tokens at: tokenCount - 3) = #methodsFor:]) ifTrue: [(tokens at: tokenCount - 1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokenCount]]. file close. ^ stamp ! ! !CompiledMethod methodsFor: 'source code management' stamp: 'dmu 9/7/2010 14:23'! putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock "Store the source code for the receiver on an external file. If no sources are available, i.e., SourceFile is nil, then store temp names for decompilation at the end of the method. If the fileIndex is 1, print on *.sources; if it is 2, print on *.changes, in each case, storing a 4-byte source code pointer at the method end." | file remoteString st80str | (SourceFiles == nil or: [(file _ SourceFiles at: fileIndex) == nil]) ifTrue: [^ self become: ( (self class methodDictionary includesKey: #copyWithTempsFromMethodNode:) ifTrue: [self copyWithTempsFromMethodNode: methodNode] ifFalse: [self copyWithTempNames: methodNode tempNames] )]. SmalltalkImage current assureStartupStampLogged. file safelyDo: [ file setToEnd. preambleBlock value: file. "Write the preamble" (DialectMethodNode notNil and: [methodNode isKindOf: DialectMethodNode]) ifTrue: ["This source was parsed from an alternate syntax. We must convert to ST80 before logging it." st80str _ (DialectStream dialect: #ST80 contents: [:strm | methodNode printOn: strm]) asString. remoteString _ RemoteString newString: st80str onFileNumber: fileIndex toFile: file] ifFalse: [remoteString _ RemoteString newString: sourceStr onFileNumber: fileIndex toFile: file]. file nextChunkPut: ' '. InMidstOfFileinNotification signal ifFalse: [file flush]. self checkOKToAdd: sourceStr size at: remoteString position. self setSourcePosition: remoteString position inFile: fileIndex ]! ! !CompositePackageInfo methodsFor: 'accessing' stamp: 'ads 12/10/2010 12:03'! name ^ name! ! !CompositePackageInfo methodsFor: 'accessing' stamp: 'ads 12/10/2010 12:02'! name: aString name := aString.! ! !CompositePackageInfo methodsFor: 'accessing' stamp: 'ads 12/10/2010 12:03'! packageNames: aCollection "Just a shortcut for setting my packages." self packages: (aCollection collect: [:n | PackageInfo named: n]).! ! !CompositePackageInfo methodsFor: 'accessing' stamp: 'ads 12/2/2010 14:46'! packages ^ packages! ! !CompositePackageInfo methodsFor: 'accessing' stamp: 'ads 12/2/2010 14:45'! packages: aCollection packages := aCollection.! ! !CompositePackageInfo methodsFor: 'classes' stamp: 'ads 12/2/2010 14:44'! classes ^ packages ifNil: [Smalltalk allClasses] ifNotNil: [packages gather: [:p | p classes]]! ! !CompositePackageInfo methodsFor: 'classes' stamp: 'ads 12/5/2010 22:59'! systemCategories ^ packages ifNil: [SystemOrganization categories] ifNotNil: [packages gather: [:p | p systemCategories]]! ! !CompositePackageInfo methodsFor: 'extension methods' stamp: 'ads 12/3/2010 11:20'! extensionCategoriesForClass: cls ^ packages ifNil: [{}] ifNotNil: [packages gather: [:p | p extensionCategoriesForClass: cls]]! ! !CompositePackageInfo methodsFor: 'extension methods' stamp: 'ads 1/13/2011 13:31'! extensionClasses ^ packages ifNil: [{}] ifNotNil: [((packages gather: [:p | p extensionClasses]) asSet asSortedCollection: [:a :b | a name < b name]) asArray]! ! !CompositePackageInfo methodsFor: 'extension methods' stamp: 'ads 12/2/2010 14:44'! extensionMethods ^ packages ifNil: [{}] ifNotNil: [packages gather: [:p | p extensionMethods]]! ! !CompositePackageInfo methodsFor: 'extension methods' stamp: 'ads 12/6/2010 01:02'! isYourClassExtension: categoryName ^ packages ifNil: [false] ifNotNil: [packages anySatisfy: [:p | p isYourClassExtension: categoryName]]! ! !CompositePackageInfo methodsFor: 'testing' stamp: 'ads 12/14/2010 10:16'! includesClass: aClass ^ self includesSystemCategory: aClass theNonMetaClass category! ! !CompositePackageInfo methodsFor: 'testing' stamp: 'ads 12/14/2010 10:15'! includesMethod: aSymbol ofClass: aClass aClass ifNil: [^ false]. ^ self includesMethodCategory: ((aClass organization categoryOfElement: aSymbol) ifNil: [' ']) ofClass: aClass! ! !CompositePackageInfo methodsFor: 'testing' stamp: 'ads 12/14/2010 10:15'! includesMethodCategory: categoryName ofClass: aClass ^ (self isYourClassExtension: categoryName) or: [(self includesClass: aClass) and: [(self isForeignClassExtension: categoryName) not]]! ! !CompositePackageInfo methodsFor: 'testing' stamp: 'ads 12/14/2010 10:17'! includesSystemCategory: categoryName ^ packages ifNil: [true] ifNotNil: [packages anySatisfy: [:p | p includesSystemCategory: categoryName]]! ! !CompositePackageInfo methodsFor: 'testing' stamp: 'ads 12/14/2010 10:18'! isForeignClassExtension: categoryName ^ categoryName first = $* and: [(self isYourClassExtension: categoryName) not]! ! !CompositePackageInfo methodsFor: 'comparing' stamp: 'ads 1/26/2011 13:05'! = other ^ self species = other species and: [self name = other name and: [self packages = other packages]]! ! !CompositePackageInfo methodsFor: 'comparing' stamp: 'ads 1/26/2011 13:06'! hash ^ self name hash bitXor: self packages hash! ! !CompositePackageInfo methodsFor: 'reverting' stamp: 'ads 1/26/2011 16:16'! revertToVersionBeforeTeam: team self extensionMethods do: [:m | team revertToOldVersionOrRemove: m]. self classes do: [:cls | cls removeFromSystem]. self systemCategories do: [:cat | SystemOrganization removeCategoryIfEmpty: cat]. ! ! !CompositePackageInfo methodsFor: 'composing' stamp: 'ads 12/5/2010 23:38'! , p ^ self class new packages: {self. p}; yourself! ! !CompositePackageInfo methodsFor: 'composing' stamp: 'ads 1/26/2011 14:15'! includesPackage: p ^ self = p or: [self packages anySatisfy: [:myPackage | myPackage includesPackage: p]]! ! !CompositePackageInfo commentStamp: 'ads 12/14/2010 09:16' prior: 0! Contains multiple packages (see the PackageInfo class). To specify that you want a CompositePackageInfo containing all classes in the entire image, leave the collection of packages as nil. Doesn't support the entire PackageInfo protocol yet; just the stuff we needed to save code out to text files.! !CompositePackageInfo class methodsFor: 'as yet unclassified' stamp: 'ads 12/10/2010 11:58'! forEntireImage ^ self new name: 'EntireImage'; yourself ! ! !CompositePackageInfo class methodsFor: 'as yet unclassified' stamp: 'ads 12/10/2010 11:58'! forRVMBootstrapping ^ self new name: 'RVMBootstrapping'; packageNames: {'RVMBootstrap'. 'SlyBootstrap'. 'Sly3Bootstrap'}; yourself ! ! !ConfigurationOfBenchmarking methodsFor: 'baselines' stamp: 'StefanMarr 7/8/2011 22:34'! baseline01: spec "<version: '0.1-baseline'>" spec for: #'common' do: [ spec blessing: #'baseline'. spec repository: 'http://www.squeaksource.com/SMark'. self class subPackages do: [:pkg | spec package: pkg ]. ]. spec for: #pharo do: [ spec project: 'OSProcess' with: [ spec className: 'ConfigurationOfOSProcess'; file: 'ConfigurationOfOSProcess'; repository: 'http://www.squeaksource.com/MetacelloRepository' ] ]! ! !ConfigurationOfBenchmarking methodsFor: 'symbolic versions' stamp: 'StefanMarr 7/8/2011 22:34'! development: spec "<symbolicVersion: #'development'>" spec for: #'common' version: '0.1'. ! ! !ConfigurationOfBenchmarking methodsFor: 'accessing' stamp: 'StefanMarr 5/14/2011 12:19'! project ^ project ifNil: [ | constructor | "Bootstrap Metacello if it is not already loaded" (self class baseConfigurationClassIfAbsent: []) ensureMetacello. "Construct Metacello project" constructor := (Smalltalk at: #MetacelloVersionConstructor) on: self. project := constructor project. project loadType: #linear. "change to #atomic if desired" project ]! ! !ConfigurationOfBenchmarking methodsFor: 'versions' stamp: 'StefanMarr 7/8/2011 22:34'! version01: spec "<version: '0.1' imports: #('0.1-baseline' )>" spec for: #'common' do: [ spec blessing: #'development'. spec description: ''. spec author: 'StefanMarr'. spec timestamp: '5/14/2011 12:19'. ].! ! !ConfigurationOfBenchmarking class methodsFor: 'development support' stamp: 'StefanMarr 7/8/2011 22:34'! DevelopmentSupport "See the methods in the 'development support' category on the class-side of MetacelloBaseConfiguration. Decide what development support methods you would like to use and copy them the the class-side of your configuration." "<apiDocumentation>" ! ! !ConfigurationOfBenchmarking class methodsFor: 'development support' stamp: 'StefanMarr 7/8/2011 22:35'! validate "Check the configuration for Errors, Critical Warnings, and Warnings (see class comment for MetacelloMCVersionValidator for more information). Errors identify specification issues that will result in unexpected behaviour when you load the configuration. Critical Warnings identify specification issues that may result in unexpected behavior when you load the configuration. Warnings identify specification issues that are technically correct, but are worth take a look at." "self validate" "<apiDocumentation>" self ensureMetacello. ^ ((Smalltalk at: #MetacelloToolBox) validateConfiguration: self debug: #() recurse: false) explore! ! !ConfigurationOfBenchmarking class methodsFor: 'private' stamp: 'StefanMarr 5/14/2011 12:19'! baseConfigurationClassIfAbsent: aBlock ^Smalltalk at: #MetacelloBaseConfiguration ifAbsent: [ self ensureMetacelloBaseConfiguration. Smalltalk at: #MetacelloBaseConfiguration ifAbsent: aBlock ]. ! ! !ConfigurationOfBenchmarking class methodsFor: 'private' stamp: 'StefanMarr 5/14/2011 12:19'! ensureMetacello (self baseConfigurationClassIfAbsent: []) ensureMetacello! ! !ConfigurationOfBenchmarking class methodsFor: 'private' stamp: 'StefanMarr 5/14/2011 12:19'! ensureMetacelloBaseConfiguration Smalltalk at: #MetacelloBaseConfiguration ifAbsent: [ | repository version | repository := MCHttpRepository location: 'http://seaside.gemstone.com/ss/metacello' user: '' password: ''. repository versionReaderForFileNamed: 'Metacello-Base-DaleHenrichs.2.mcz' do: [ :reader | version := reader version. version load. version workingCopy repositoryGroup addRepository: repository ] ]! ! !ConfigurationOfBenchmarking class methodsFor: 'metacello tool support' stamp: 'StefanMarr 5/14/2011 12:19'! isMetacelloConfig "Answer true and the Metacello tools will operate on you" ^true! ! !ConfigurationOfBenchmarking class methodsFor: 'loading' stamp: 'StefanMarr 7/8/2011 22:35'! load "Load the #stable version defined for this platform. The #stable version is the version that is recommended to be used on this platform." "self load" "<apiDocumentation>" ^(self project version: #stable) load! ! !ConfigurationOfBenchmarking class methodsFor: 'loading' stamp: 'StefanMarr 7/8/2011 22:35'! loadBleedingEdge "Load the latest versions of the mcz files defined for this project. It is not likely that the #bleedingEdge has been tested." "self loadBleedingEdge" "<apiDocumentation>" ^(self project version: #bleedingEdge) load! ! !ConfigurationOfBenchmarking class methodsFor: 'loading' stamp: 'StefanMarr 7/8/2011 22:35'! loadDevelopment "Load the #development version defined for this platform. The #development version will change over time and is not expected to be stable." "self loadDevelopment" "<apiDocumentation>" ^(self project version: #development) load! ! !ConfigurationOfBenchmarking class methodsFor: 'transporter' stamp: 'StefanMarr 5/25/2011 11:49'! saveWithTransporter "Will save the package in file-out format using the Transporter infrastructure" self transporters ifNotNilDo: [:transporters | transporters do: [:t | t saveNoPopup ]].! ! !ConfigurationOfBenchmarking class methodsFor: 'transporter' stamp: 'StefanMarr 7/8/2011 22:27'! subPackages "Specifies the names of all logical subpackages of the Benchmarking package." "TODO: have a versioning for this, to better comply with the Metacello approach." ^ { 'SMark'. 'NPB'. 'CL-Benchmarks-Game'. }! ! !ConfigurationOfBenchmarking class methodsFor: 'transporter' stamp: 'sm 7/8/2011 22:39'! transporters "Returns the transporters that define how to file out the different packages for versioning with Git." Smalltalk at: #Transporter ifPresent: [ :tpCls | | package packages | package := CompositePackageInfo new. package name: 'Benchmarking'. packages := { PackageInfo named: 'ConfigurationOfBenchmarking' }. packages := packages, (self subPackages collect: [:pkg | PackageInfo named: pkg ]). package packages: packages. ^ {Transporter forPackage: package}. ]. ^ nil.! ! !ConfigurationOfBenchmarking class methodsFor: 'transporter' stamp: 'StefanMarr 5/25/2011 11:48'! transportersForFileOutMenu ^ self transporters! ! !ConfigurationOfBenchmarking class methodsFor: 'accessing' stamp: 'StefanMarr 5/14/2011 12:19'! project ^self new project! ! !ContextPart methodsFor: 'debugger access' stamp: 'ads 1/24/2011 13:02'! tempsAndValues "Return a string of the temporary variabls and their current values" | aStream | aStream _ WriteStream on: (String new: 100). self tempNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab. aStream nextPutAll:(RVMPrimitivesNeededForBootstrapping printPrefixFor:(self tempAt: index)). (self tempAt: index) printOn: aStream. aStream cr]. ^aStream contents! ! !ContextPart methodsFor: 'system simulation' stamp: 'ssa 9/7/2009 14:34'! runSimulated: aBlock contextAtEachStep: block2 "Simulate the execution of the argument, aBlock, until it ends. aBlock MUST NOT contain an '^'. Evaluate block2 with the current context prior to each instruction executed. Answer the simulated value of aBlock." | current | (aBlock isBlock and: [aBlock hasMethodReturn]) ifTrue: [self error: 'simulation of blocks with ^ can run loose']. current _ aBlock asContext. current privSender: self. [current == self] whileFalse: [block2 value: current. current _ current step]. ^ self pop! ! !ContextPart methodsFor: 'private-exceptions' stamp: 'ssa 1/21/2010 16:20'! unwindTo: aContext | ctx unwindBlock | ctx := self. [(ctx _ ctx findNextUnwindContextUpTo: aContext) isNil] whileFalse: [ unwindBlock := ctx tempAt: 1. unwindBlock == nil ifFalse: [ ctx tempAt: 1 put: nil. unwindBlock value] ]. ! ! !ContextPart methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:42'! errorReportOn: foo! ! !ContextPart methodsFor: '*RVMBootstrap' stamp: 'dmu 9/22/2010 22:18'! contextStackIn: aProcess "Answer an Array of the contexts on the receiver's sender chain." ^self stackOfSize: 100000 in: aProcess! ! !ContextPart methodsFor: '*RVMBootstrap' stamp: 'dmu 9/22/2010 22:38'! senderOrSlyInvokerAndProcessIn: aProcess "Answer the context that sent the message that created the receiver." "Follow up the process parent chain to the invoking ensemble process." ^sender ifNotNil: [sender->aProcess] ifNil: [ aProcess parent ifNil: [nil] ifNotNil: [aProcess parent suspendedContext->aProcess parent]]! ! !ContextPart methodsFor: '*RVMBootstrap' stamp: 'dmu 9/22/2010 22:29'! senderOrSlyInvokerIn: aProcess "Answer the context that sent the message that created the receiver." "Follow up the process parent chain to the invoking ensemble process." ^sender ifNotNil: [sender] ifNil: [self halt. aProcess parent ifNil: [nil] ifNotNil: [aProcess parent suspendedContext]]! ! !ContextPart methodsFor: '*RVMBootstrap' stamp: 'dmu 9/22/2010 22:38'! stackOfSize: limit in: aProcess "Answer an OrderedCollection of the top 'limit' contexts on the receiver's sender chain." | a stack cachedStackTop newLimit p assoc | stack _ OrderedCollection new. stack addLast: (a _ self). p _ aProcess. "Ugh!! I ought to clean this up. -- dmu" [ (assoc _ a senderOrSlyInvokerAndProcessIn: p) ~~ nil and: [stack size < limit]] whileTrue: [ a _ assoc key. p _ assoc value. a hideFromDebugger ifFalse: [stack addLast: a]. a cachesStack ifTrue: [cachedStackTop := a cachedStackTop]]. ^cachedStackTop == nil ifTrue: [stack] ifFalse: [newLimit := limit - stack size. newLimit > 0 ifTrue: [stack addAllLast: (cachedStackTop stackOfSize: newLimit); yourself] ifFalse: [stack]]! ! !ControlManager methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:14'! activeControllerNoTerminate: aController andProcess: aProcess "Set aController to be the currently active controller and aProcess to be the the process that handles controller scheduling activities in the system. This message differs from activeController:andProcess: in that it does not send controlTerminate to the currently active controller." self inActiveControllerProcess ifTrue: [aController~~nil ifTrue: [(scheduledControllers includes: aController) ifTrue: [self promote: aController] ifFalse: [self error: 'Old controller not scheduled']]. activeController _ aController. activeController == nil ifFalse: [activeController controlInitialize]. activeControllerProcess _ aProcess. activeControllerProcess resume] ifFalse: ['New active controller process must be set from old one, resetting...' print. self reset. ] ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! inActiveControllerProcess "Answer whether the active scheduling process is the actual active process in the system." ^activeControllerProcess == Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/2/2010 14:12'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | suspendingList newActiveController | (suspendingList _ activeControllerProcess suspendingList) == nil ifTrue: [activeControllerProcess == Processor thisProcess ifTrue: [activeControllerProcess suspend]] ifFalse: [suspendingList remove: activeControllerProcess ifAbsent:[]. activeControllerProcess offList]. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController _ (Debugger openInterrupt: labelString onProcess: activeControllerProcess) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'ssa 3/25/2010 16:17'! reset "ssa - reset the window controller process" | newProcess | newProcess := [ScheduledControllers resetActiveController. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process" "Processor terminateActive"! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:19'! resetActiveController "When saving a morphic project whose parent is mvc, we need to set this up first" activeController _ nil. activeControllerProcess _ Processor thisProcess. ! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! scheduleActiveNoTerminate: aController "Make aController be the active controller. Presumably the process that requested the new active controller wants to keep control to do more activites before the new controller can take control. Therefore, do not terminate the currently active process." self schedulePassive: aController. self scheduled: aController from: Processor thisProcess! ! !ControlManager methodsFor: 'scheduling' stamp: 'dmu 11/25/2008 00:20'! searchForActiveController "Find a scheduled controller that wants control and give control to it. If none wants control, then see if the System Menu has been requested." | aController | activeController _ nil. activeControllerProcess _ Processor thisProcess. self activeController: self nextActiveController. Processor terminateActive! ! !ControlManager methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:48'! restore "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." scheduledControllers first view uncacheBits. "assure refresh" self unschedule: screenController; scheduleOnBottom: screenController. screenController view window: Display boundingBox; displayDeEmphasized. self scheduledWindowControllers reverseDo: [:aController | aController view resetDisplayInterlock; displayDeEmphasized]. ! ! !ControlManager methodsFor: 'displaying' stamp: 'ssa 8/26/2008 08:55'! restore: aRectangle below: index without: aView "Restore all windows visible in aRectangle, but without aView" | view | view := (scheduledControllers at: index) view. view == aView ifTrue: [index >= scheduledControllers size ifTrue: [^ self]. ^ self restore: aRectangle below: index+1 without: aView]. view isNil ifTrue:[^self]. view displayOn: ((BitBlt current toForm: Display) clipRect: aRectangle). index >= scheduledControllers size ifTrue: [^ self]. (aRectangle areasOutside: view windowBox) do: [:rect | self restore: rect below: index + 1 without: aView]! ! !Controller methodsFor: 'initialize-release'! initialize "Initialize the state of the receiver. Subclasses should include 'super initialize' when redefining this message to insure proper initialization." sensor _ InputSensor default! ! !Controller methodsFor: 'basic control sequence' stamp: 'sm 2/24/2011 18:49'! controlLoop "Sent by Controller|startUp as part of the standard control sequence. Controller|controlLoop sends the message Controller|isControlActive to test for loop termination. As long as true is returned, the loop continues. When false is returned, the loop ends. Each time through the loop, the message Controller|controlActivity is sent." | oldName | oldName := Processor thisProcess name. " as long as the process is executing the control loop it will be named according to its class " Processor thisProcess name: self class name, '(Controller)>>controlLoop'. [self isControlActive] whileTrue: ["self killExtraUIProcesses." self interActivityPause. self controlActivity. Processor yield]. " restore old name " Processor thisProcess name: oldName. self lastProcessRunningMe: nil! ! !Controller methodsFor: 'basic control sequence' stamp: 'ads 1/24/2011 13:01'! interActivityPause "if we are looping quickly, insert a short delay. Thus if we are just doing UI stuff, we won't take up much CPU" | currentTime wait | [RVMPrimitivesNeededForBootstrapping isRVM ifTrue: [Processor yield. ^ self].]. MinActivityLapse ifNotNil: [ lastActivityTime ifNotNil: [ currentTime _ Time millisecondClockValue. wait _ lastActivityTime + MinActivityLapse - currentTime. wait > 0 ifTrue: [ wait <= MinActivityLapse "big waits happen after a snapshot" ifTrue: [DisplayScreen checkForNewScreenSize. "(Delay forMilliseconds: wait) wait "]. ]. ]. ]. lastActivityTime _ Time millisecondClockValue.! ! !Controller methodsFor: '*Ly' stamp: 'dmu 3/29/2010 00:21'! killExtraUIProcesses | p lp | p _ Processor thisProcess. lp _ self lastProcessRunningMe. p == lp ifTrue: [self killCounter: 0. ^ self]. lp isRunning ifTrue: [ self killCounter < 5 ifTrue: [ self killCounter: self killCounter + 1. ^ self. ]. self killCounter: 0. Transcript cr;show:'Controller>>killExtraUIProcesses working, killing process hash=',p identityHash printString. p terminate ] "1 foo" "2 timesRepeat:[[self halt]fork]"! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:18'! lastActivityTime "Answer the value of lastActivityTime" lastActivityTime isNil ifTrue:[self lastActivityTime: nil]. ^ lastActivityTime! ! !Controller methodsFor: 'accessing' stamp: 'ssa 3/2/2010 17:18'! lastActivityTime: anObject "Set the value of lastActivityTime" lastActivityTime _ anObject! ! !Controller methodsFor: '*RVMBootstrap' stamp: 'dmu 3/26/2010 14:59'! killCounter "Answer the value of killCounter" killCounter isNil ifTrue:[self killCounter: 0]. ^ killCounter! ! !Controller methodsFor: '*RVMBootstrap' stamp: 'dmu 3/26/2010 14:59'! killCounter: anObject "Set the value of killCounter" killCounter _ anObject! ! !Controller methodsFor: '*RVMBootstrap' stamp: 'ssa 3/2/2010 17:28'! lastProcessRunningMe "Answer the value of lastProcessRunningMe" lastProcessRunningMe isNil ifTrue:[self lastProcessRunningMe: Processor thisProcess]. ^ lastProcessRunningMe! ! !Controller methodsFor: '*RVMBootstrap' stamp: 'ssa 3/2/2010 17:18'! lastProcessRunningMe: anObject "Set the value of lastProcessRunningMe" lastProcessRunningMe _ anObject! ! !Controller class methodsFor: 'initialization' stamp: 'ssa 8/15/2008 09:40'! initialize "Controller initialize" self MinActivityLapse: 50.! ! !CopyReader methodsFor: 'reading'! read: aClass "Ignore aClass and grab the object directly from the stream. aClass is typically Integer, Float, Symbol, etc. Assume the object was put on the stream using CopyWriter>store: (look there for more info)." | anObject | anObject _ stream next. position _ position + 1. ^anObject! ! !CopyReader methodsFor: 'testing'! isCopier ^true! ! !CopyWriter methodsFor: 'testing'! isCopier ^true! ! !CopyWriter methodsFor: 'writing'! canCopy: anObject "Answer true only if anObject is in the copySet (or if there is no copySet). This can be used by objects which are connected to objects which are not to be copied." ^copySet == nil ifTrue:[true] ifFalse:[copySet includes: anObject]! ! !CopyWriter methodsFor: 'writing'! copySet: aCollection "Set the set of objects that should be copied." copySet _ aCollection! ! !CopyWriter methodsFor: 'writing'! store: anObject "Put anObject directly on the Stream... don't convert it to an ascii String since it's not going to a file. anObject will typically be a Symbol, Number, etc." stream nextPut: anObject. position _ position + 1! ! !CopyWriter class methodsFor: 'instance creation'! copy: anObject | aStream | aStream _ ReadWriteStream on: (Array new: 100). (self on: aStream) nextPut: anObject. aStream reset. ^(CopyReader on: aStream) next! ! !Cursor class methodsFor: 'class initialization' stamp: 'ssa 1/1/1970 00:31'! initialize "Create all the standard cursors..." self initOrigin. self initRightArrow. self initLeftArrow. self initMenu. self initCorner. self initRead. self initWrite. self initWait. BlankCursor _ Cursor new. self initXeq. self initSquare. self initNormalWithMask. self initCrossHair. self initMarker. self initUp. self initDown. self initMove. self initBottomLeft. self initBottomRight. self initAction. self initResizeLeft. self initResizeTop. self initResizeTopLeft. self initResizeTopRight. self initTopLeft. self initTopRight. self makeCursorsWithMask. "Cursor initialize" ! ! !Cursor class methodsFor: '*RVM' stamp: 'ssa 9/19/2008 12:03'! action "Answer the instance of me that indicates a mouse action is available" ^ActionCursor! ! !Cursor class methodsFor: '*RVM' stamp: 'ssa 1/1/1970 00:21'! initAction "Cursor initAction" ActionCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000000000000000 2r0000000100000000 2r0010000100001000 2r0001000100010000 2r0000100100100000 2r0000010001000000 2r0000000000000000 2r1111100100111110 2r0000000000000000 2r0000100001000000 2r0001000100100000 2r0010000100010000 2r0100000100001000 2r0000000100000000 2r0000000000000000 2r0) offset: -7 @ -7). ! ! !Cursor class methodsFor: '*RVM' stamp: 'ssa 9/19/2008 11:39'! initLeftArrow LeftArrowCursor _ (Cursor extent: 16@16 fromArray: #( 2r0000100000000000 2r0011100000000000 2r1111111110000000 2r0011100000000000 2r0000100000000000 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0 2r0) offset: -8@0). "Cursor initLeftArrow"! ! !Cursor class methodsFor: '*RVM' stamp: 'ssa 9/19/2008 11:24'! leftArrow "Answer the instance of me that is the shape of an arrow pointing to the left." ^LeftArrowCursor! ! !CustomMenu methodsFor: 'invocation' stamp: 'ssa 12/17/2009 10:10'! invokeOn: targetObject orSendTo: anObject "Pop up this menu and return the result of sending to the target object the selector corresponding to the menu item selected by the user. Return nil if no item is selected. If the chosen selector has arguments, obtain appropriately. If the recipient does not respond to the resulting message, send it to the alternate object provided" | aSelector anIndex recipient | ^ (aSelector _ self startUp) ifNotNil: [anIndex _ self selection. recipient _ (self targets isEmpty or: [anIndex > self targets size]) ifTrue: [targetObject] ifFalse: [self targets at: anIndex]. aSelector numArgs == 0 ifTrue: [recipient perform: aSelector orSendTo: anObject] ifFalse: [recipient perform: aSelector withArguments: (self arguments at: 1)]]! ! !CustomMenu methodsFor: 'invocation' stamp: 'ssa 1/1/1970 00:42'! startUp: initialSelection withCaption: caption at: aPoint "Build and invoke this menu with the given initial selection and caption. Answer the selection associated with the menu item chosen by the user or nil if none is chosen." self build. (initialSelection notNil) ifTrue: [self preSelect: initialSelection]. ^ super startUpWithCaption: caption at: aPoint! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! arguments arguments isNil ifTrue:[arguments := OrderedCollection new]. ^arguments! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! selections selections isNil ifTrue:[selections := OrderedCollection new]. ^selections! ! !CustomMenu methodsFor: 'accessing' stamp: 'ssa 6/20/2008 14:29'! targets targets isNil ifTrue:[targets := OrderedCollection new]. ^targets! ! !Debugger methodsFor: '*Ly' stamp: 'smu 3/4/2010 10:26'! setContextStackIndexFromLyIndex: anIndex | ctx n | ctx _ contextStackTop. n _ 1. [ ctx _ ctx firstContextContainingLyActivation. ctx ifNil: [ Transcript show: 'setContextStackIndexFromLyIndex: missing activation'; cr. ^ self ]. n >= anIndex ifTrue: [ self fullStack. self toggleContextStackIndex: (self contextStack indexOf: ctx). ^ self ]. n _ n + 1. ctx _ ctx sender. ] repeat! ! !Debugger methodsFor: '*Ly' stamp: 'ssa 3/3/2010 20:25'! setContextStackIndexFromOtherIndex: anIndex otherTopContext: ctx self setContextStackIndexFromLyIndex: anIndex! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 23:00'! buildMVCDebuggerViewLabel: aString minSize: aPoint "Build an MVC debugger view around the receiver, and return the StandardSystemView thus created." | topView stackListView stackCodeView rcvrVarView rcvrValView ctxtVarView ctxtValView deltaY underPane annotationPane buttonsView oldContextStackIndex | oldContextStackIndex _ contextStackIndex. self expandStack. "Sets contextStackIndex to zero." contextStackIndex _ oldContextStackIndex. self contextVariablesInspector object: self selectedContext. self receiverInspector object: self receiver. topView _ StandardSystemView new model: self. topView borderWidth: 1. stackListView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #toggleContextStackIndex: menu: #contextStackMenu:shifted: keystroke: #contextStackKey:from:. self installListFontInto: stackListView. stackListView menuTitleSelector: #messageListSelectorTitle. stackListView window: (0 @ 0 extent: 150 @ 50). topView addSubView: stackListView. deltaY _ 0. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 150@self optionalAnnotationHeight). topView addSubView: annotationPane below: stackListView. deltaY _ deltaY + self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [underPane _ stackListView]. self wantsOptionalButtons ifTrue: [buttonsView _ self buildMVCOptionalButtonsButtonsView. buttonsView borderWidth: 1. topView addSubView: buttonsView below: underPane. underPane _ buttonsView. deltaY _ deltaY + self optionalButtonHeight]. stackCodeView _ self codeView. stackCodeView window: (0 @ 0 extent: 150 @ (75 - deltaY)). topView addSubView: stackCodeView below: underPane. rcvrVarView _ PluggableListView on: self receiverInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. self installListFontInto: rcvrVarView. rcvrVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: rcvrVarView below: stackCodeView. rcvrValView _ PluggableTextView on: self receiverInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. rcvrValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: rcvrValView toRightOf: rcvrVarView. ctxtVarView _ PluggableListView on: self contextVariablesInspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. self installListFontInto: ctxtVarView. ctxtVarView window: (0 @ 0 extent: 25 @ (50 - deltaY)). topView addSubView: ctxtVarView toRightOf: rcvrValView. ctxtValView _ PluggableTextView on: self contextVariablesInspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. ctxtValView window: (0 @ 0 extent: 50 @ (50 - deltaY)). topView addSubView: ctxtValView toRightOf: ctxtVarView. topView label: aString. topView minimumSize: aPoint. ^ topView ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 22:55'! buildMVCNotifierViewLabel: aString message: messageString minSize: aPoint | topView notifyView buttonView x y bHeight | self expandStack. topView _ StandardSystemView new model: self. topView borderWidth: 1. buttonView _ self buildMVCNotifierButtonView. topView addSubView: buttonView. notifyView _ PluggableListView on: self list: #contextStackList selected: #contextStackIndex changeSelected: #debugAt: menu: nil keystroke: nil. self installListFontInto: notifyView. x _ 350 max: (aPoint x). y _ ((4 * 15) + 16) max: (aPoint y - 16 - self optionalButtonHeight). bHeight _ self optionalButtonHeight. y _ y - bHeight. notifyView window: (0@0 extent: x@y). topView addSubView: notifyView below: buttonView; label: aString; minimumSize: aPoint. ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 21:35'! codeView "Answer the code editing view for me" ^PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:! ! !Debugger methodsFor: 'initialize' stamp: 'dmu 3/10/2010 18:15'! customButtonSpecs "Answer an array of elements of the form wording, selector, help-message, that characterize the custom button row of a debugger." | list | list _ #(('Proceed' proceed 'close the debugger and proceed.') ('Restart' restart 'reset this context to its start.') ('Into' send 'step Into message sends') ('Over' doStep 'step Over message sends') ('Through' stepIntoBlock 'step into a block') ('Full Stack' fullStack 'show full stack') ('Where' where 'select current pc range') ('Meta' halt 'go meta & debug the debugger')). list _ list, self otherButtonSpecs. Preferences restartAlsoProceeds ifTrue: [list _ list collect: [:each | each second == #restart ifTrue: [each copy at: 3 put: 'proceed from the beginning of this context.'; yourself] ifFalse: [each]]]. ^ list! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/9/2009 17:35'! debugAt: anInteger self toggleContextStackIndex: anInteger. ^ self debug.! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/10/2009 15:56'! openFullNoSuspendLabel: aString "Create and schedule a full debugger with the given label. Do not terminate the current active process." | topView oldContextStackIndex | Smalltalk isMorphic ifTrue: [ oldContextStackIndex := contextStackIndex. self expandStack. "Sets contextStackIndex to zero." ToolBuilder open: self label: aString. self toggleContextStackIndex: oldContextStackIndex. ^ self ]. topView _ self buildMVCDebuggerViewLabel: aString minSize: 300@200. topView controller openNoTerminate. ^ topView ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/15/2009 14:11'! openNotifierContents: msgString label: label "Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired." "NOTE: When this method returns, a new process has been scheduled to run the windows, and thus this notifier, but the previous active porcess has not been suspended. The sender will do this." | msg topView p | Sensor flushKeyboard. savedCursor _ Sensor currentCursor. Sensor currentCursor: Cursor normal. (label beginsWith: 'Space is low') ifTrue: [msg _ self lowSpaceChoices, (msgString ifNil: [''])] ifFalse: [msg _ msgString]. isolationHead ifNotNil: ["We have already revoked the isolation layer -- now jump to the parent project." msg _ self isolationRecoveryAdvice, msgString. failedProject _ Project current. isolationHead parent enterForEmergencyRecovery]. Smalltalk isMorphic ifTrue: [ builder := ToolBuilder default. spec := self buildNotifierWith: builder label: label message: msg. self expandStack. builder open: spec. errorWasInUIProcess := Project spawnNewProcessIfThisIsUI: interruptedProcess. ^ self ]. Display fullScreen. topView _ self buildMVCNotifierViewLabel: label , Time dateAndTimeNow printString message: thisContext sender sender shortStack minSize:600@((14 * 20) + 16 + self optionalButtonHeight). ScheduledControllers activeController ifNil: [p _ Display boundingBox center] ifNotNil: [p _ ScheduledControllers activeController view displayBox center]. topView controller openNoTerminateDisplayAt: (p adhereTo:(Display boundingBox insetBy: topView minimumSize)). ^ topView! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 9/3/2008 15:34'! optionalButtonPairs "Actually, return triples. In mvc (until someone deals with this) only the custom debugger-specific buttons are shown, but in morphic, the standard code-tool buttons are provided in addition to the custom buttons" ^ Smalltalk isMorphic ifFalse: [self customButtonSpecs] ifTrue: []! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 7/7/2010 10:48'! otherButtonSpecs | r | r _ OrderedCollection new. (Smalltalk includesKey:#Ly) ifTrue:[ contextStackTop hasLyActivation ifTrue:[r add: #('Debug in Ly' debugInLy 'launch a Ly execution debugger on this stack')]]. ^ r asArray! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 20:55'! release self windowIsClosing. super release. ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 3/3/2010 20:58'! terminateInterruptedProcessIfSoleOwner | otherOwners | otherOwners _ Smalltalk pointersTo: interruptedProcess except:{self}. otherOwners detect:[:each| each isKindOf: Debugger] ifNone:[ Transcript show: 'Debugger>>terminateInterruptedProcessIfSoleOwner: ', interruptedProcess identityHash printString; cr. interruptedProcess terminate]. ! ! !Debugger methodsFor: 'initialize' stamp: 'ssa 4/20/2010 11:05'! windowIsClosing "My window is being closed; clean up. Restart the low space watcher." interruptedProcess == nil ifTrue: [^ self]. interruptedProcess terminate. "self terminateInterruptedProcessIfSoleOwner." interruptedProcess _ nil. interruptedController _ nil. contextStack _ nil. contextStackTop _ nil. receiverInspector _ nil. contextVariablesInspector _ nil. Smalltalk installLowSpaceWatcher. "restart low space handler" ! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStack "Answer the value of contextStack" contextStack isNil ifTrue:[self contextStack: nil]. ^ contextStack! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStack: anObject "Set the value of contextStack" contextStack _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackIndex: anObject "Set the value of contextStackIndex" contextStackIndex _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackList: anObject "Set the value of contextStackList" contextStackList _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackTop "Answer the value of contextStackTop" contextStackTop isNil ifTrue:[self contextStackTop: nil]. ^ contextStackTop! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextStackTop: anObject "Set the value of contextStackTop" contextStackTop _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:24'! contextVariablesInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context." contextVariablesInspector isNil ifTrue:[self contextVariablesInspector: self defaultContextVariablesInspector]. ^contextVariablesInspector! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! contextVariablesInspector: anObject "Set the value of contextVariablesInspector" contextVariablesInspector _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:22'! defaultContextVariablesInspector ^ContextVariablesInspector inspect: nil! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:15'! defaultReceiverInspector ^Inspector inspect: nil! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! errorWasInUIProcess "Answer the value of errorWasInUIProcess" errorWasInUIProcess isNil ifTrue:[self errorWasInUIProcess: nil]. ^ errorWasInUIProcess! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! errorWasInUIProcess: anObject "Set the value of errorWasInUIProcess" errorWasInUIProcess _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! externalInterrupt "Answer the value of externalInterrupt" externalInterrupt isNil ifTrue:[self externalInterrupt: nil]. ^ externalInterrupt! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! failedProject "Answer the value of failedProject" failedProject isNil ifTrue:[self failedProject: nil]. ^ failedProject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! failedProject: anObject "Set the value of failedProject" failedProject _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedController "Answer the value of interruptedController" interruptedController isNil ifTrue:[self interruptedController: nil]. ^ interruptedController! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedController: anObject "Set the value of interruptedController" interruptedController _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedProcess "Answer the value of interruptedProcess" interruptedProcess isNil ifTrue:[self interruptedProcess: nil]. ^ interruptedProcess! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! interruptedProcess: anObject "Set the value of interruptedProcess" interruptedProcess _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! isolationHead "Answer the value of isolationHead" isolationHead isNil ifTrue:[self isolationHead: nil]. ^ isolationHead! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! isolationHead: anObject "Set the value of isolationHead" isolationHead _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! proceedValue "Answer the value of proceedValue" proceedValue isNil ifTrue:[self proceedValue: nil]. ^ proceedValue! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 3/3/2010 22:15'! receiverInspector "Answer the instance of Inspector that is providing a view of the variables of the selected context's receiver." receiverInspector isNil ifTrue:[self receiverInspector: self defaultReceiverInspector]. ^receiverInspector! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! receiverInspector: anObject "Set the value of receiverInspector" receiverInspector _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! savedCursor "Answer the value of savedCursor" savedCursor isNil ifTrue:[self savedCursor: nil]. ^ savedCursor! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! savedCursor: anObject "Set the value of savedCursor" savedCursor _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:16'! selectingPC "Answer the value of selectingPC" selectingPC isNil ifTrue:[self selectingPC: false]. ^ selectingPC! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! selectingPC: anObject "Set the value of selectingPC" selectingPC _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! sourceMap "Answer the value of sourceMap" sourceMap isNil ifTrue:[self sourceMap: nil]. ^ sourceMap! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! sourceMap: anObject "Set the value of sourceMap" sourceMap _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! tempNames "Answer the value of tempNames" tempNames isNil ifTrue:[self tempNames: nil]. ^ tempNames! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! tempNames: anObject "Set the value of tempNames" tempNames _ anObject! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! theMethodNode "Answer the value of theMethodNode" theMethodNode isNil ifTrue:[self theMethodNode: nil]. ^ theMethodNode! ! !Debugger methodsFor: 'accessing' stamp: 'ssa 9/15/2009 10:15'! theMethodNode: anObject "Set the value of theMethodNode" theMethodNode _ anObject! ! !Debugger methodsFor: 'notifier menu' stamp: 'ssa 3/2/2010 18:08'! debug "Open a full DebuggerView." | topView | Smalltalk isMorphic ifTrue: [ "hack for Squeak4.1 image -- dmu" topView := self topView. topView model: nil. "so close won't release me." self breakDependents. ToolBuilder default close: topView. ^ self openFullNoSuspendLabel: topView label]. topView _ self topView. topView isNil ifTrue:[topView _ self buildMVCDebuggerViewLabel: self labelString minSize: 200@200]. topView model: nil. "so close won't release me." topView controller controlTerminate. topView deEmphasize; erase. "a few hacks to get the scroll selection artifacts out when we got here by clicking in the list" topView subViewWantingControl ifNotNil: [ topView subViewWantingControl controller controlTerminate ]. topView controller status: #closed. self openFullNoSuspendLabel: topView label. topView controller closeAndUnscheduleNoErase. Transcript show: 'in debug: ', Processor thisProcess identityHash printString; cr. Processor terminateActive. ! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/10/2010 09:17'! contextStackIndex "Answer the index of the selected context." contextStackIndex isNil ifTrue:[self contextStackIndex: 0]. ^contextStackIndex! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/3/2010 22:23'! expandStack "A Notifier is being turned into a full debugger. Show a substantial amount of stack in the context pane." self newStack: (contextStackTop stackOfSize: 20). contextStackIndex _ 0. receiverInspector _ self defaultReceiverInspector. contextVariablesInspector _ self defaultContextVariablesInspector. proceedValue _ nil! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'dmu 9/22/2010 22:17'! fullyExpandStack "Expand the stack to include all of it, rather than the first four or five contexts." self okToChange ifFalse: [^ self]. self newStack: ( contextStackTop contextStackIn: interruptedProcess). self changed: #contextStackList! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 3/2/2010 16:17'! labelForContext: ctxt ^ctxt printString! ! !Debugger methodsFor: 'context stack (message list)' stamp: 'ssa 9/15/2009 10:14'! toggleContextStackIndex: anInteger "If anInteger is the same as the index of the selected context, deselect it. Otherwise, the context whose index is anInteger becomes the selected context." self contextStackIndex: (contextStackIndex = anInteger ifTrue: [0] ifFalse: [anInteger]) oldContextWas: ((contextStackIndex = 0 or:[contextStackIndex isNil]) ifTrue: [nil] ifFalse: [contextStack at: contextStackIndex])! ! !Debugger methodsFor: 'context stack menu' stamp: 'ssa 9/3/2008 11:23'! contextStackMenu: aMenu shifted: shifted "Set up the menu appropriately for the context-stack-list, either shifted or unshifted as per the parameter provided" ^ shifted ifFalse: [self selectedContext selector = #doesNotUnderstand: ifTrue: [aMenu add: 'implement in...' subMenu: (self populateImplementInMenu: (Smalltalk isMorphic ifTrue: [] ifFalse: [CustomMenu new])) target: nil selector: nil argumentList: #(nil)]. aMenu labels: 'fullStack (f) restart (r) proceed (p) step (t) step through (T) send (e) where (w) peel to first like this senders of... (n) implementors of... (m) inheritance (i) versions (v) inst var refs... inst var defs... class var refs... class variables class refs (N) browse full (b) file out more...' lines: #(8 12 14 17 20) selections: #(fullStack restart proceed doStep stepIntoBlock send where peelToFirst browseSendersOfMessages browseMessages methodHierarchy browseVersions browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables browseClassRefs browseMethodFull fileOutMessage shiftedYellowButtonActivity)] ifTrue: [aMenu labels: 'browse class hierarchy browse class browse method (O) implementors of sent messages change sets with this method inspect instances inspect subinstances revert to previous version remove from current change set revert & remove from changes more...' lines: #(5 7 10) selections: #(classHierarchy browseClass openSingleMessageBrowser browseAllMessages findMethodInChangeSets inspectInstances inspectSubInstances revertToPreviousVersion removeFromCurrentChanges revertAndForget unshiftedYellowButtonActivity)] ! ! !Debugger methodsFor: 'code pane' stamp: 'ssa 9/15/2009 10:16'! pcRange "Answer the indices in the source code for the method corresponding to the selected context's program counter value." | i pc end | (self selectingPC and: [contextStackIndex ~= 0]) ifFalse: [^1 to: 0]. sourceMap ifNil: [theMethodNode isNil ifTrue:[^1 to: 0]. sourceMap _ theMethodNode sourceMap. tempNames _ theMethodNode tempNames. self selectedContext method cacheTempNames: tempNames]. (sourceMap size = 0 or: [ self selectedContext isDead ]) ifTrue: [^1 to: 0]. Smalltalk at: #RBProgramNode ifPresent:[:nodeClass| (theMethodNode isKindOf: nodeClass) ifTrue: [ pc _ contextStackIndex = 1 ifTrue: [self selectedContext pc] ifFalse: [self selectedContext previousPc]. i _ sourceMap findLast:[:pcRange | pcRange key <= pc]. i = 0 ifTrue:[^ 1 to: 0]. ^ (sourceMap at: i) value ]. ]. pc_ self selectedContext pc - (("externalInterrupt" true and: [contextStackIndex=1]) ifTrue: [1] ifFalse: [2]). i _ sourceMap indexForInserting: (Association key: pc value: nil). i < 1 ifTrue: [^1 to: 0]. i > sourceMap size ifTrue: [end _ sourceMap inject: 0 into: [:prev :this | prev max: this value last]. ^ end+1 to: end]. ^(sourceMap at: i) value! ! !Debugger methodsFor: 'dependents access' stamp: 'ssa 3/3/2010 22:18'! step "Update the inspectors." self receiverInspector ifNotNil: [self receiverInspector step]. self contextVariablesInspector ifNotNil: [self contextVariablesInspector step]. ! ! !Debugger methodsFor: 'dependents access' stamp: 'ssa 3/3/2010 22:19'! updateInspectors "Update the inspectors on the receiver's variables." self receiverInspector == nil ifFalse: [self receiverInspector update]. self contextVariablesInspector == nil ifFalse: [self contextVariablesInspector update]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/3/2010 21:46'! contextStackIndex: anInteger oldContextWas: oldContext "Change the context stack index to anInteger, perhaps in response to user selection." | newMethod | contextStackIndex := anInteger. anInteger = 0 ifTrue: [currentCompiledMethod := theMethodNode := tempNames := sourceMap := contents := nil. self changed: #contextStackIndex. self decorateButtons. self contentsChanged. contextVariablesInspector object: nil. self updateInspectorToObject: self receiver. ^ self]. (newMethod := oldContext == nil or: [oldContext method ~~ (currentCompiledMethod := self selectedContext method)]) ifTrue: [tempNames := sourceMap := nil. theMethodNode := Preferences browseWithPrettyPrint ifTrue: [ self selectedContext methodNodeFormattedAndDecorated: Preferences colorWhenPrettyPrinting ] ifFalse: [ self selectedContext methodNode ]. contents := self selectedMessage. self contentsChanged. self pcRange "will compute tempNamesunless noFrills"]. self changed: #contextStackIndex. self decorateButtons. tempNames == nil ifTrue: [tempNames := self selectedClassOrMetaClass parserClass new parseArgsAndTemps: contents notifying: nil]. contextVariablesInspector object: self selectedContext. self updateInspectorToObject: self receiver. newMethod ifFalse: [self changed: #contentsSelection]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/2/2010 16:16'! newStack: stack | oldStack diff | contextStackTop _ stack first. oldStack _ contextStack. contextStack _ stack. (oldStack == nil or: [oldStack last ~~ stack last]) ifTrue: [contextStackList _ contextStack collect: [:ctx | self labelForContext: ctx ]. ^ self]. "May be able to re-use some of previous list" diff _ stack size - oldStack size. contextStackList _ diff <= 0 ifTrue: [contextStackList copyFrom: 1-diff to: oldStack size] ifFalse: [diff > 1 ifTrue: [contextStack collect: [:ctx | self labelForContext: ctx ]] ifFalse: [(Array with: (self labelForContext:stack first)) , contextStackList]]! ! !Debugger methodsFor: 'private' stamp: 'ssa 9/15/2009 14:25'! process: aProcess controller: aController context: aContext isolationHead: projectOrNil super initialize. Smalltalk at: #MessageTally ifPresentAndInMemory: [:c | c new close]. contents _ nil. interruptedProcess _ aProcess. interruptedController _ aController. contextStackTop _ aContext. self newStack: (contextStackTop stackOfSize: 1). contextStackIndex _ 1. externalInterrupt _ false. selectingPC _ true. isolationHead _ projectOrNil. ! ! !Debugger methodsFor: 'private' stamp: 'dmu 3/10/2010 17:52'! resetContext: aContext "Used when a new context becomes top-of-stack, for instance when the method of the selected context is re-compiled, or the simulator steps or returns to a new method. There is room for much optimization here, first to save recomputing the whole stack list (and text), and secondly to avoid recomposing all that text (by editing the paragraph instead of recreating it)." | oldContext | oldContext _ self selectedContext. contextStackTop _ aContext. self newStack: (contextStackTop ifNil: [^ self release] ifNotNil: [contextStackTop contextStack]). self changed: #contextStackList. self contextStackIndex: 1 oldContextWas: oldContext. self changed: #content.! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/25/2010 16:02'! resumeProcess: aTopView | c | aTopView erase. savedCursor ifNotNil: [Sensor currentCursor: savedCursor]. isolationHead ifNotNil: [failedProject enterForEmergencyRecovery. isolationHead invoke. isolationHead _ nil]. (interruptedProcess isNil or:[interruptedProcess isTerminated]) ifFalse: [ c _ interruptedController ifNil:[ScheduledControllers scheduledControllers last] ifNotNil:[interruptedController]. ScheduledControllers activeControllerNoTerminate: c andProcess: interruptedProcess]. "if old process was terminated, just terminate current one" interruptedProcess _ nil. "Before delete, so release doesn't terminate it" aTopView controller closeAndUnscheduleNoErase. Smalltalk installLowSpaceWatcher. "restart low space handler" errorWasInUIProcess == false ifFalse: [Processor terminateActive]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/10/2010 09:17'! selectedContext self contextStackIndex = 0 ifTrue: [^self contextStackTop] ifFalse: [^self contextStack at: contextStackIndex]! ! !Debugger methodsFor: 'private' stamp: 'ssa 3/3/2010 21:48'! updateInspectorToObject: obj self receiverInspector object: obj! ! !Debugger methodsFor: '*RVMBootstrap' stamp: 'ssa 3/3/2010 22:53'! installListFontInto: aListView "do nothing by default"! ! !Debugger class methodsFor: 'class initialization' stamp: 'sm 5/25/2011 20:27'! openContext: aContext label: aString contents: contentsStringOrNil | isolationHead | "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." <primitive: 19> "Simulation guard" "When we are running headless, we just print the stuff and quit." RVMOperations isHeadless ifTrue: [ Smalltalk logError: aString inContext: aContext onConsoleAndQuitWithSaving: false. ]. ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue: [Smalltalk logError: aString inContext: aContext to: 'SqueakDebug.log']. ErrorRecursion ifTrue: [ErrorRecursion _ false. "(isolationHead _ CurrentProjectRefactoring currentIsolationHead) ifNil: [self primitiveError: aString] ifNotNil: [isolationHead revoke]"]. ErrorRecursion _ true. self informExistingDebugger: aContext label: aString. (Debugger context: aContext isolationHead: nil) openNotifierContents: contentsStringOrNil label: aString. ErrorRecursion _ false. Processor thisProcess suspend. ! ! !Debugger class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:20'! context: aContext isolationHead: isolationHead "Answer an instance of me for debugging the active process starting with the given context." ^ self new process: Processor thisProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: aContext isolationHead: isolationHead ! ! !Debugger class methodsFor: 'opening' stamp: 'dmu 9/17/2010 12:00'! openInterrupt: aString onProcess: interruptedProcess "Open a notifier in response to an interrupt. An interrupt occurs when the user types the interrupt key (cmd-. on Macs, ctrl-c or alt-. on other systems) or when the low-space watcher detects that memory is low." | debugger | <primitive: 19> "Simulation guard" debugger _ self new. interruptedProcess suspend. debugger process: interruptedProcess controller: ((Smalltalk isMorphic not and: [ScheduledControllers activeControllerProcess == interruptedProcess]) ifTrue: [ScheduledControllers activeController]) context: interruptedProcess suspendedContextWaitingIfNecessary. debugger externalInterrupt: true. Preferences logDebuggerStackToFile ifTrue: [(aString includesSubString: 'Space') & (aString includesSubString: 'low') ifTrue: [ Smalltalk logError: aString inContext: debugger interruptedContext to:'LowSpaceDebug.log']]. ^ debugger openNotifierContents: nil label: aString ! ! !Debugger class methodsFor: 'opening' stamp: 'sm 5/25/2011 20:35'! openNoForkSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool selectingOtherIndex: anIndex "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." | controller | "When we are running headless, we just print the stuff and quit." RVMOperations isHeadless ifTrue: [ Smalltalk logError: (title, 'Contents: ', contentsStringOrNil asString) inContext: context onConsoleAndQuitWithSaving: false. ]. controller _ ScheduledControllers activeControllerProcess == process ifTrue: [ScheduledControllers activeController]. [ [ | debugger | debugger _ self new process: process controller: controller context: context. bool ifTrue: [debugger openFullNoSuspendLabel: title] ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]. debugger setContextStackIndexFromOtherIndex: anIndex otherTopContext: context. Preferences logDebuggerStackToFile ifTrue: [ Smalltalk logError: title inContext: context to: 'SqueakDebug.log']. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"]. ] on: Error do: [:ex | self primitiveError: 'Orginal error: ', title asString, '. Debugger error: ', ([ex description] on: Error do: ['a ', ex class printString]), ':' ] ] value! ! !Debugger class methodsFor: 'opening' stamp: 'sm 5/25/2011 20:35'! openNoSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger." | controller | "When we are running headless, we just print the stuff and quit." RVMOperations isHeadless ifTrue: [ Smalltalk logError: (title, 'Contents: ', contentsStringOrNil asString) inContext: context onConsoleAndQuitWithSaving: false. ]. Smalltalk isMorphic ifTrue: [] ifFalse: [controller _ ScheduledControllers activeControllerProcess == process ifTrue: [ScheduledControllers activeController]]. [ [ | debugger | debugger _ self new process: process controller: controller context: context. bool ifTrue: [debugger openFullNoSuspendLabel: title] ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]. Preferences logDebuggerStackToFile ifTrue: [ Smalltalk logError: title inContext: context to: 'SqueakDebug.log']. Smalltalk isMorphic ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"]. ] on: Error do: [:ex | self primitiveError: 'Orginal error: ', title asString, '. Debugger error: ', ([ex description] on: Error do: ['a ', ex class printString]), ':' ] ] fork! ! !Debugger class methodsFor: 'opening' stamp: 'dmu 3/25/2010 10:23'! openOn: process context: context label: title contents: contentsStringOrNil fullView: bool self openNoSuspendOn: process context: context label: title contents: contentsStringOrNil fullView: bool. process suspend. ! ! !Delay methodsFor: '*RVM' stamp: 'dmu 2/6/2011 21:25'! spinWait | t | t _ Time millisecondClockValue + delayDuration. [t > Time millisecondClockValue] whileTrue: [Processor yield]! ! !Delay class methodsFor: 'snapshotting' stamp: 'dmu 5/25/2010 11:02'! startUp "Restart active delay, if any, when resuming a snapshot." self restoreResumptionTimes. ActiveDelay == nil ifFalse: [ActiveDelay activate]. AccessProtect _ Semaphore forMutualExclusion ! ! !Delay class methodsFor: 'timer process' stamp: 'sm 2/24/2011 16:38'! startTimerInterruptWatcher "Reset the class variables that keep track of active Delays and re-start the timer interrupt watcher process. Any currently scheduled delays are forgotten." "Delay startTimerInterruptWatcher" | p | self primSignal: nil atMilliseconds: 0. TimingSemaphore == nil ifFalse: [TimingSemaphore terminateProcess]. TimingSemaphore _ Semaphore new. AccessProtect _ Semaphore forMutualExclusion. SuspendedDelays _ SortedCollection sortBlock: [:d1 :d2 | d1 resumptionTime <= d2 resumptionTime]. ActiveDelay _ nil. p _ [self timerInterruptWatcher] newProcess. p priority: Processor timingPriority. p name: 'TimerInterruptWatcher'. p resume. ! ! !Dictionary methodsFor: 'outlining' stamp: 'ssa 9/10/2009 14:30'! subobjects ^self associations asOrderedCollection! ! !Dictionary methodsFor: '*RVM-Archiving'! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self size. self associationsDo: [:each | aStream nextPut: each]! ! !Dictionary methodsFor: '*Ly-Explorer' stamp: 'hg 10/3/2001 20:47'! explorerContents | contents | contents := OrderedCollection new. self keysSortedSafely do: [:key | contents add: (ObjectExplorerWrapper with: (self at: key) name: (key printString contractTo: 32) model: self)]. ^contents ! ! !DictionaryInspector methodsFor: 'menu' stamp: 'ssa 1/6/2010 20:24'! dictionaryMenu: aMenu "Set up the key-list menu for a dictionary inspector" aMenu title: 'Dictionary key'. ^ aMenu addList: #( ('inspect' inspectSelection) ('explore' exploreSelection) ('copy name' copyName) ('references' selectionReferences) ('objects pointing to this value' objectReferencesToSelection) ('senders of this key' sendersOfSelectedKey) - ('refresh view' calculateKeyArray) - ('add key' addEntry) ('rename key' renameEntry) ('remove' removeSelection) - ('basic inspect' inspectBasic))! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:50'! border: aRectangle width: borderWidth fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: Form over fillColor: aHalfTone clippingBox: clipRect! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:50'! border: aRectangle width: borderWidth rule: combinationRule fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of the border of each side is borderWidth. Uses aHalfTone for drawing the border." self border: aRectangle widthRectangle: (Rectangle left: borderWidth right: borderWidth top: borderWidth bottom: borderWidth) rule: combinationRule fillColor: aHalfTone clippingBox: clipRect! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 11/30/2009 13:42'! border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone clippingBox: clipRect "Paint a border whose rectangular area is defined by aRectangle. The width of each edge of the border is determined by the four coordinates of insets. Uses aHalfTone and combinationRule for drawing the border." (aRectangle areasOutside: (aRectangle insetBy: insets)) do: [:edgeStrip | self fill: edgeStrip rule: combinationRule fillColor: aHalfTone clippingBox: clipRect]! ! !DisplayMedium methodsFor: 'bordering' stamp: 'ssa 12/18/2009 06:38'! outlined self border: self boundingBox width: 1! ! !DisplayObject methodsFor: 'displaying-generic' stamp: 'ssa 9/4/2009 10:47'! displayOn: aDisplayMedium at: aDisplayPoint "Display the receiver located at aDisplayPoint with default settings for rule and halftone." self displayOn: aDisplayMedium at: aDisplayPoint clippingBox: aDisplayMedium boundingBox rule: Form paint fillColor: nil! ! !DisplayObject methodsFor: 'displaying-generic' stamp: 'ssa 12/17/2009 16:54'! followCursor "Just show the Form following the mouse. 6/21/96 tk" Cursor blank showWhile: [self follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]. Sensor waitNoButton ! ! !DisplayScreen methodsFor: 'displaying' stamp: 'ssa 8/23/2009 15:06'! outline: rectBlock do: effectBlock while: durationBlock width: borderWidth halftone: halftone "Display an evolving rectangle dynamically. rectBlock supplies a rectangle, durationBlock supplies true, then false to terminate. effectBlock is executed at each iteration." | oldRect edges rect | oldRect _ rectBlock value rounded. edges _ oldRect areasOutside: (oldRect insetBy: borderWidth). edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. [durationBlock value] whileTrue: [rect _ rectBlock value rounded. rect = oldRect ifFalse: [edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. effectBlock value. edges _ rect areasOutside: (rect insetBy: borderWidth). edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. oldRect _ rect]]. edges do: [:edge | self fill: edge rule: Form reverse fillColor: halftone]. ^ oldRect! ! !DisplayScreen methodsFor: 'displaying' stamp: 'ssa 8/23/2009 15:05'! outline: rectBlock while: durationBlock width: borderWidth halftone: halftone "Display an evolving rectangle dynamically. rectBlock supplies a rectangle, durationBlock supplies true, then false to terminate." ^self outline: rectBlock do: [] while: durationBlock width: borderWidth halftone: halftone! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 10:14'! boundingBox clippingBox == nil ifTrue: [self clippingBox: super boundingBox]. ^ clippingBox copy! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 09:59'! clippingTo: aRect do: aBlock "Display clippingTo: Rectangle fromUser do: [ScheduledControllers restore: Display fullBoundingBox]" | saveClip | saveClip _ clippingBox. self clippingBox: aRect. aBlock value. self clippingBox: saveClip! ! !DisplayScreen methodsFor: 'other' stamp: 'ssa 8/24/2009 09:59'! fullScreen "Display fullScreen" ScreenSave notNil ifTrue: [Display _ ScreenSave]. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'private' stamp: 'ssa 8/24/2009 10:00'! copyFrom: aForm "Take on all state of aForm, with complete sharing" super copyFrom: aForm. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'private' stamp: 'ssa 8/24/2009 10:00'! setExtent: aPoint depth: bitsPerPixel "DisplayScreen startUp" "This method is critical. If the setExtent fails, there will be no proper display on which to show the error condition..." "ar 5/1/1999: ... and that is exactly why we check for the available display depths first." "RAA 27 Nov 99 - if depth and extent are the same and acceptable, why go through this. also - record when we change so worlds can tell if it is time to repaint" (depth == bitsPerPixel and: [aPoint = self extent and: [self supportsDisplayDepth: bitsPerPixel]]) ifFalse: [ bits _ nil. "Free up old bitmap in case space is low" DisplayChangeSignature _ (DisplayChangeSignature ifNil: [0]) + 1. (self supportsDisplayDepth: bitsPerPixel) ifTrue:[super setExtent: aPoint depth: bitsPerPixel] ifFalse:["Search for a suitable depth" super setExtent: aPoint depth: self findAnyDisplayDepth]. ]. self clippingBox: super boundingBox! ! !DisplayScreen methodsFor: 'accessing' stamp: 'ssa 8/24/2009 10:10'! clippingBox: aRect clippingBox _ aRect ! ! !DisplayScreen methodsFor: '*RVM' stamp: 'dmu 1/25/2010 11:25'! drawDot5At: point1 "Display drawDot5At: 100@100" Dot5 ifNil: [Dot5 _ Form dotOfSize:5]. Dot5 displayAt: point1! ! !DisplayScreen methodsFor: '*RVM' stamp: 'aau 1/13/2011 19:54'! drawDot5At: point1 color: c |ColorDot5| "Display drawDot5At: 100@100 color: Color red" ColorDot5 _ ColorForm dotOfSize:5 color: c. ColorDot5 displayAt: point1! ! !DisplayScreen methodsFor: '*RVM' stamp: 'dmu 3/23/2010 00:02'! drawLineFrom: point1 to: point2 color: aColor "Display drawLineFrom: Point fromUser to: Point fromUser color: Color fromUser" "Display drawLineFrom: 0@0 to: 200@200 color: Color black" "Display drawLineFrom: 0@0 to: 200@200 color: Color white" Dot1 ifNil: [Dot1 _ Form dotOfSize:1]. self drawLine: Dot1 from: point1 to: point2 clippingBox: self boundingBox rule: Form paint fillColor: aColor ! ! !DisplayScreen methodsFor: '*RVM' stamp: 'dmu 1/25/2010 11:27'! eraseDot5At: point1 "Display eraseDot5At: 100@100" Blank5 ifNil: [Blank5 _ (Form dotOfSize:5) fillWhite]. Blank5 displayAt: point1! ! !DisplayScreen methodsFor: '*RVM' stamp: 'dmu 3/23/2010 00:03'! eraseLineFrom: point1 to: point2 color: aColor "Display eraseLineFrom: Point fromUser to: Point fromUser color: Color fromUser" "Display eraseLineFrom: 0@0 to: 200@200 color: Color black" "Display eraseLineFrom: 0@0 to: 200@200 color: Color white" Dot1 ifNil: [Dot1 _ Form dotOfSize:1]. self drawLine: Dot1 from: point1 to: point2 clippingBox: self boundingBox rule: Form erase fillColor: aColor ! ! !DisplayText methodsFor: 'accessing' stamp: 'ssa 8/27/2009 11:17'! numberOfLines "Answer the number of lines of text in the receiver." ^self text lineCount! ! !DisplayText methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:34'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text is identical to that of the receiver." | para | para _ Paragraph withText: text style: aTextStyle. para foregroundColor: foreColor backgroundColor: backColor. backColor isTransparent ifTrue: [para rule: Form paint]. ^ para! ! !DisplayText methodsFor: 'testing' stamp: 'ssa 1/20/2010 11:00'! isEmpty ^self text isEmpty! ! !DisplayTextView class methodsFor: 'examples' stamp: 'ssa 9/4/1998 17:29'! example2 "Create a standarad system view with two parts, one editable, the other not." "Modified to support Windoze - ssa" | topView aDisplayTextView | topView _ StandardSystemView new. topView label: 'Text Editor'. aDisplayTextView _ MSWScrollBarView on: (self new model: 'test string label' asDisplayText). aDisplayTextView scrollingView controller: NoController new. aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidthLeft: 2 right: 0 top: 2 bottom: 2. topView addSubView: aDisplayTextView. aDisplayTextView _ MSWScrollBarView on: (self new model: 'test string' asDisplayText). aDisplayTextView window: (0 @ 0 extent: 100 @ 100). aDisplayTextView borderWidth: 2. topView addSubView: aDisplayTextView align: aDisplayTextView viewport topLeft with: topView lastSubView viewport topRight. topView controller open "DisplayTextView example2"! ! !DisplayTextView class methodsFor: 'examples'! open: textOrString label: aLabel "Create a system view with a paragraph editor in it. 6/2/96 sw" "VIVA LA JUNTA!! Modified to use MSWScrollBarViews - ssa 12/11/97 12:00" | topView aDisplayTextView | aDisplayTextView _ MSWScrollBarView on: (DisplayTextView new model: textOrString asDisplayText). aDisplayTextView borderWidth: 2. topView _ StandardSystemView new. topView label: aLabel. topView addSubView: aDisplayTextView. topView controller open "DisplayTextView open: 'Great green gobs' label: 'Gopher Guts'"! ! !DualChangeSorter methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:07'! open | topView | leftCngSorter _ ChangeSorter new myChangeSet: ChangeSet current. leftCngSorter parent: self. rightCngSorter _ ChangeSorter new myChangeSet: ChangeSorter secondaryChangeSet. rightCngSorter parent: self. topView _ (StandardSystemView new) model: self; borderWidth: 1. topView label: leftCngSorter label. topView minimumSize: 300 @ 200. leftCngSorter openView: topView offsetBy: 0@0. rightCngSorter openView: topView offsetBy: 360@0. topView controller open. ! ! !EnsembleNode methodsFor: 'printing' stamp: 'ssa 4/19/2010 20:44'! printOn: aStream indent: level aStream nextPut: $%;nextPut: ${. 1 to: elements size do: [:i | (elements at: i) printOn: aStream indent: level. i < elements size ifTrue: [aStream nextPutAll: '. ']]. aStream nextPut: $}! ! !EnsembleNode methodsFor: 'code generation' stamp: 'ssa 4/19/2010 22:35'! emitForValue: stack on: aStream ^ emitNode emitForValue: stack on: aStream! ! !EnsembleNode methodsFor: 'code generation' stamp: 'dmu 9/16/2010 23:44'! sizeForValue: encoder emitNode _ "Long form: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray;asEnsembleOfElements" CascadeNode new receiver: (MessageNode new receiver: (encoder encodeVariable: #Array) selector: #braceStream: arguments: (Array with: (encoder encodeLiteral: elements size)) precedence: 3 from: encoder) messages: (((elements collect: [:elt | MessageNode new receiver: nil selector: #nextPut: arguments: (Array with: elt) precedence: 3 from: encoder]) copyWith: (MessageNode new receiver: nil selector: #braceArray arguments: (Array new) precedence: 1 from: encoder))copyWith: (MessageNode new receiver: nil selector: #asEnsembleOfElements arguments: (Array new) precedence: 1 from: encoder)). ^ emitNode sizeForValue: encoder! ! !EqualityTester methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 18:56'! resultFor: runs "Test that equality is the same over runs and answer the result" 1 to: runs do: [:i | self prototype = self prototype ifFalse: [^ false]]. ^ true! ! !EqualityTester commentStamp: 'mjr 8/20/2003 13:04' prior: 0! I provide a simple way to test the equality properties of any object.! !Error methodsFor: '*SUnit'! sunitAnnounce: aTestCase toResult: aTestResult aTestResult addError: aTestCase. self sunitExitWith: false.! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 7/23/2000 14:37'! eventQueue "Return the current event queue" ^eventQueue! ! !EventSensor methodsFor: 'accessing' stamp: 'nk 4/12/2004 19:36'! eventTicklerProcess "Answer my event tickler process, if any" ^EventTicklerProcess! ! !EventSensor methodsFor: 'accessing' stamp: 'ssa 12/17/2009 13:19'! flushAllButDandDEvents | newQueue oldQueue | newQueue _ SharedQueue new. self eventQueue ifNil: [eventQueue := newQueue. ^self]. oldQueue _ self eventQueue. [oldQueue size > 0] whileTrue: [| item type | item _ oldQueue next. type _ item at: 1. type = EventTypeDragDropFiles ifTrue: [ newQueue nextPut: item]]. eventQueue := newQueue. ! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/7/2001 17:13'! flushEvents eventQueue ifNotNil:[eventQueue flush].! ! !EventSensor methodsFor: 'accessing' stamp: 'ssa 12/17/2009 12:30'! nextEvent "Return the next event from the receiver." eventQueue == nil ifTrue:[^self nextEventSynthesized] ifFalse:[^self nextEventFromQueue] ! ! !EventSensor methodsFor: 'accessing' stamp: 'JMM 11/7/2005 14:38'! peekButtons self wait2ms. self fetchMoreEvents. ^mouseButtons! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/6/2004 14:51'! peekEvent "Look ahead at the next event." eventQueue ifNil:[^nil]. self fetchMoreEvents. ^eventQueue peek! ! !EventSensor methodsFor: 'accessing' stamp: 'tpr 1/5/2005 17:34'! peekKeyboardEvent "Return the next keyboard char event from the receiver or nil if none available" ^eventQueue nextOrNilSuchThat: [:buf | buf first = EventTypeKeyboard and: [(buf fourth) = EventKeyChar]]! ! !EventSensor methodsFor: 'accessing' stamp: 'ar 2/8/2001 21:45'! peekMousePt ^mousePosition! ! !EventSensor methodsFor: 'accessing' stamp: 'JMM 11/7/2005 14:38'! peekPosition self wait2ms. self fetchMoreEvents. ^mousePosition! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 19:21'! initialize "Initialize the receiver" mouseButtons := 0. mousePosition := 0 @ 0. keyboardBuffer := SharedQueue new. self setInterruptKey: (interruptKey ifNil: [$. asciiValue bitOr: 16r0800 ]). "cmd-." interruptSemaphore := (Smalltalk specialObjectsArray at: 31) ifNil: [Semaphore new]. self flushAllButDandDEvents. inputSemaphore := Semaphore new. hasInputSemaphore := false.! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 4/12/2004 20:13'! shutDown super shutDown. EventTicklerProcess ifNotNil: [ EventTicklerProcess terminate. EventTicklerProcess _ nil. ]. inputSemaphore ifNotNil:[Smalltalk unregisterExternalObject: inputSemaphore]. ! ! !EventSensor methodsFor: 'initialize' stamp: 'nk 6/21/2004 10:42'! startUp "Run the I/O process" self initialize. self primSetInputSemaphore: (Smalltalk registerExternalObject: inputSemaphore). super startUp. self installEventTickler. Smalltalk isMorphic ifTrue:[self flushAllButDandDEvents]. "Attempt to discover whether the input semaphore is actually being signaled." hasInputSemaphore := false. inputSemaphore initSignals. ! ! !EventSensor methodsFor: 'mouse' stamp: 'ar 5/18/2003 18:27'! createMouseEvent "create and return a new mouse event from the current mouse position; this is useful for restarting normal event queue processing after manual polling" | buttons modifiers pos mapped eventBuffer | eventBuffer _ Array new: 8. buttons _ self primMouseButtons. pos _ self primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. eventBuffer at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ eventBuffer! ! !EventSensor methodsFor: 'private' stamp: 'nk 4/12/2004 20:16'! eventTickler "Poll infrequently to make sure that the UI process is not been stuck. If it has been stuck, then spin the event loop so that I can detect the interrupt key." | delay | delay := Delay forMilliseconds: self class eventPollPeriod. self lastEventPoll. "ensure not nil." [| delta | [ delay wait. delta := Time millisecondClockValue - lastEventPoll. (delta < 0 or: [delta > self class eventPollPeriod]) ifTrue: ["force check on rollover" self fetchMoreEvents]] on: Error do: [:ex | ]. true ] whileTrue.! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/17/2009 14:18'! flushNonKbdEvents eventQueue ifNil: [^ self]. [^self]value. "don't flush so we don't lose events" eventQueue flushAllSuchThat: [:buf | (self isKbdEvent: buf) not] ! ! !EventSensor methodsFor: 'private' stamp: 'sm 2/24/2011 16:42'! installEventTickler "Initialize the interrupt watcher process. Terminate the old process if any." "Sensor installEventTickler" EventTicklerProcess ifNotNil: [EventTicklerProcess terminate]. EventTicklerProcess _ [self eventTickler] forkAt: Processor lowIOPriority. EventTicklerProcess name: 'EventTicklerProcess'. ! ! !EventSensor methodsFor: 'private' stamp: 'di 10/1/2001 20:51'! isKbdEvent: buf ^ (buf at: 1) = EventTypeKeyboard and: [(buf at: 4) = EventKeyChar]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/18/2004 13:21'! lastEventPoll "Answer the last clock value at which fetchMoreEvents was called." ^lastEventPoll ifNil: [ lastEventPoll _ Time millisecondClockValue ]! ! !EventSensor methodsFor: 'private' stamp: 'ar 2/6/2004 14:42'! nextEventFromQueue "Return the next event from the receiver." eventQueue isEmpty ifTrue:[self fetchMoreEvents]. eventQueue isEmpty ifTrue:[^nil] ifFalse:[^eventQueue next]! ! !EventSensor methodsFor: 'private' stamp: 'nk 3/17/2004 07:09'! nextEventSynthesized "Return a synthesized event. This method is called if an event driven client wants to receive events but the primary user interface is not event-driven (e.g., the receiver does not have an event queue but only updates its state). This can, for instance, happen if a Morphic World is run in an MVC window. To simplify the clients work this method will always return all available keyboard events first, and then (repeatedly) the mouse events. Since mouse events come last, the client can assume that after one mouse event has been received there are no more to come. Note that it is impossible for EventSensor to determine if a mouse event has been issued before so the client must be aware of the possible problem of getting repeatedly the same mouse events. See HandMorph>>processEvents for an example on how to deal with this." | kbd array buttons pos modifiers mapped | "First check for keyboard" array _ Array new: 8. kbd _ self primKbdNext. kbd ifNotNil: ["simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^ array]. "Then check for mouse" pos _ self primMousePt. buttons _ mouseButtons. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ^ array ! ! !EventSensor methodsFor: 'private' stamp: 'ar 7/23/2000 00:34'! primInterruptSemaphore: aSemaphore "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." interruptSemaphore _ aSemaphore. "backward compatibility: use the old primitive which is obsolete now" super primInterruptSemaphore: aSemaphore! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primKbdNext "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | evtBuf | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse:[^ keyboardBuffer next]. eventQueue ifNotNil: [evtBuf _ eventQueue nextOrNilSuchThat: [:buf | self isKbdEvent: buf]. self flushNonKbdEvents]. ^ evtBuf ifNotNil: [evtBuf at: 3] ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primKbdPeek "Allows for use of old Sensor protocol to get at the keyboard, as when running kbdTest or the InterpreterSimulator in Morphic" | char | self fetchMoreEvents. keyboardBuffer isEmpty ifFalse: [^ keyboardBuffer peek]. char _ nil. eventQueue ifNotNil: [eventQueue nextOrNilSuchThat: "NOTE: must not return out of this block, so loop to end" [:buf | (self isKbdEvent: buf) ifTrue: [char ifNil: [char _ buf at: 3]]. false "NOTE: block value must be false so Queue won't advance"]]. ^ char ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMouseButtons self fetchMoreEvents. self flushNonKbdEvents. ^ mouseButtons ! ! !EventSensor methodsFor: 'private' stamp: 'ssa 12/16/2009 13:26'! primMousePt self fetchMoreEvents. self flushNonKbdEvents. ^ mousePosition ! ! !EventSensor methodsFor: 'private' stamp: 'ls 10/23/2000 14:14'! primSetInterruptKey: anInteger "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>." interruptKey _ anInteger. "backward compatibility: use the old primitive which is obsolete now" super primSetInterruptKey: anInteger! ! !EventSensor methodsFor: 'private' stamp: 'JMM 11/7/2005 14:37'! wait2ms (Delay forMilliseconds: 2) wait.! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 13:21'! fetchMoreEvents "Fetch more events from the VM" | eventBuffer type | "Reset input semaphore so clients can wait for the next events after this one." inputSemaphore isSignaled ifTrue: [ hasInputSemaphore _ true. inputSemaphore initSignals ]. "Remember the last time that I checked for events." lastEventPoll := Time millisecondClockValue. eventBuffer := Array new: 8. [self primGetNextEvent: eventBuffer. type := eventBuffer at: 1. type = EventTypeNone] whileFalse: [self processEvent: eventBuffer ]. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:12'! mapButtons: buttons modifiers: modifiers "Map the buttons to yellow or blue based on the given modifiers. If only the red button is pressed, then map Ctrl-RedButton -> BlueButton. Cmd-RedButton -> YellowButton. " (buttons = RedButtonBit) ifFalse:[^buttons]. (modifiers allMask: CtrlKeyBit) ifTrue:[^BlueButtonBit]. (modifiers allMask: CommandKeyBit) ifTrue:[^YellowButtonBit]. ^buttons! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 13:30'! primGetNextEvent: array "Store the next OS event available into the provided array. Essential. If the VM is not event driven the ST code will fall back to the old-style mechanism and use the state based primitives instead." | kbd buttons modifiers pos mapped | <primitive: 94> "Simulate the events" array at: 1 put: EventTypeNone. "assume no more events" "First check for keyboard" kbd _ super primKbdNext. kbd = nil ifFalse:[ "simulate keyboard event" array at: 1 put: EventTypeKeyboard. "evt type" array at: 2 put: Time millisecondClockValue. "time stamp" array at: 3 put: (kbd bitAnd: 255). "char code" array at: 4 put: EventKeyChar. "key press/release" array at: 5 put: (kbd bitShift: -8). "modifier keys" ^self]. "Then check for mouse" buttons _ super primMouseButtons. pos _ super primMousePt. modifiers _ buttons bitShift: -3. buttons _ buttons bitAnd: 7. mapped _ self mapButtons: buttons modifiers: modifiers. (pos = mousePosition and:[(mapped bitOr: (modifiers bitShift: 3)) = mouseButtons]) ifTrue:[^self]. array at: 1 put: EventTypeMouse; at: 2 put: Time millisecondClockValue; at: 3 put: pos x; at: 4 put: pos y; at: 5 put: mapped; at: 6 put: modifiers. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 7/30/2000 18:16'! primSetInputSemaphore: semaIndex "Set the input semaphore the VM should use for asynchronously signaling the availability of events. Primitive. Optional." <primitive: 93> ^nil! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 12:46'! processEvent: evt "Process a single event. This method is run at high priority." | type | type := evt at: 1. "Tackle mouse events first" type = EventTypeMouse ifTrue: [evt at: 5 put: (ButtonDecodeTable at: (evt at: 5) + 1). self queueEvent: evt. self processMouseEvent: evt . ^self]. "Store the event in the queue if there's any" type = EventTypeKeyboard ifTrue: [ "Check if the event is a user interrupt" ((evt at: 4) = 0 and: [((evt at: 3) bitOr: (((evt at: 5) bitAnd: 8) bitShift: 8)) = interruptKey]) ifTrue: ["interrupt key is meta - not reported as event" ^ interruptSemaphore signal]. "Else swap ctrl/alt keys if neeeded.wi" KeyDecodeTable at: {evt at: 3. evt at: 5} ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]. self queueEvent: evt. self processKeyboardEvent: evt . ^self ]. "Handle all events other than Keyborad or Mouse." self queueEvent: evt. ! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/16/2009 13:12'! processKeyboardEvent: evt "process a keyboard event, updating InputSensor state" | charCode pressCode | "Never update keyboardBuffer if we have an eventQueue active" mouseButtons _ (mouseButtons bitAnd: 7) bitOr: ((evt at: 5) bitShift: 3). eventQueue ifNotNil:[^self]. charCode _ evt at: 3. charCode = nil ifTrue:[^self]. "extra characters not handled in MVC" pressCode _ evt at: 4. pressCode = EventKeyChar ifFalse:[^self]. "key down/up not handled in MVC" "mix in modifiers" charCode _ charCode bitOr: ((evt at: 5) bitShift: 8). keyboardBuffer nextPut: charCode .! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ar 8/16/2000 22:07'! processMouseEvent: evt "process a mouse event, updating InputSensor state" | modifiers buttons mapped | mousePosition _ (evt at: 3) @ (evt at: 4). buttons _ evt at: 5. modifiers _ evt at: 6. mapped _ self mapButtons: buttons modifiers: modifiers. mouseButtons _ mapped bitOr: (modifiers bitShift: 3).! ! !EventSensor methodsFor: 'private-I/O' stamp: 'ssa 12/17/2009 14:17'! queueEvent: evt "Queue the given event in the event queue (if any). Note that the event buffer must be copied since it will be reused later on." eventQueue ifNil:[^self]. eventQueue nextPut: evt clone.! ! !EventSensor commentStamp: 'nk 4/13/2004 11:18' prior: 0! EventSensor is a replacement for InputSensor based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design. For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events. On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM. Instance variables: mouseButtons <Integer> - mouse button state as replacement for primMouseButtons mousePosition <Point> - mouse position as replacement for primMousePt keyboardBuffer <SharedQueue> - keyboard input buffer interruptKey <Integer> - currently defined interrupt key interruptSemaphore <Semaphore> - the semaphore signaled when the interruptKey is detected eventQueue <SharedQueue> - an optional event queue for event driven applications inputSemaphore <Semaphore>- the semaphore signaled by the VM if asynchronous event notification is supported lastEventPoll <Integer> - the last millisecondClockValue at which we called fetchMoreEvents hasInputSemaphore <Boolean> - true if my inputSemaphore has actually been signaled at least once. Class variables: EventPollPeriod <Integer> - the number of milliseconds to wait between polling for more events in the userInterruptHandler. EventTicklerProcess <Process> - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds). Event format: The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported. Currently, the following events are defined: Null event ============= The Null event is returned when the ST side asks for more events but no more events are available. Structure: [1] - event type 0 [2-8] - unused Mouse event structure ========================== Mouse events are generated when mouse input is detected. Structure: [1] - event type 1 [2] - time stamp [3] - mouse x position [4] - mouse y position [5] - button state; bitfield with the following entries: 1 - yellow (e.g., right) button 2 - blue (e.g., middle) button 4 - red (e.g., left) button [all other bits are currently undefined] [6] - modifier keys; bitfield with the following entries: 1 - shift key 2 - ctrl key 4 - (Mac specific) option key 8 - Cmd/Alt key [all other bits are currently undefined] [7] - reserved. [8] - reserved. Keyboard events ==================== Keyboard events are generated when keyboard input is detected. [1] - event type 2 [2] - time stamp [3] - character code For now the character code is in Mac Roman encoding. [4] - press state; integer with the following meaning 0 - character 1 - key press (down) 2 - key release (up) [5] - modifier keys (same as in mouse events) [6] - reserved. [7] - reserved. [8] - reserved. ! !EventSensor class methodsFor: 'class initialization' stamp: 'nk 4/12/2004 18:55'! eventPollPeriod ^EventPollPeriod ifNil: [ EventPollPeriod _ 500 ].! ! !EventSensor class methodsFor: 'class initialization' stamp: 'nk 4/12/2004 18:55'! eventPollPeriod: msec "Set the number of milliseconds between checking for events to msec." EventPollPeriod _ msec max: 10.! ! !EventSensor class methodsFor: 'class initialization' stamp: 'ar 7/23/2000 15:06'! install "EventSensor install" "Install an EventSensor in place of the current Sensor." | newSensor | Sensor shutDown. newSensor _ self new. newSensor startUp. "Note: We must use #become: here to replace all references to the old sensor with the new one, since Sensor is referenced from all the existing controllers." Sensor becomeForward: newSensor. "done"! ! !ExampleSetTest methodsFor: 'running' stamp: 'BaseSystem 8/30/2009 09:40'! setUp empty := Set new. full := Set with: 5 with: #abc! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testAdd empty add: 5. self assert: (empty includes: 5)! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testGrow empty addAll: (1 to: 100). self assert: empty size = 100! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testIllegal self should: [empty at: 5] raise: TestResult error. self should: [empty at: 5 put: #abc] raise: TestResult error! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testIncludes self assert: (full includes: 5). self assert: (full includes: #abc)! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testOccurrences self assert: (empty occurrencesOf: 0) = 0. self assert: (full occurrencesOf: 5) = 1. full add: 5. self assert: (full occurrencesOf: 5) = 1! ! !ExampleSetTest methodsFor: 'testing' stamp: 'BaseSystem 8/30/2009 09:40'! testRemove full remove: 5. self assert: (full includes: #abc). self deny: (full includes: 5)! ! !Exception methodsFor: '*SUnit' stamp: 'jp 3/17/2003 10:03'! sunitExitWith: aValue self return: aValue! ! !ExplorerListView methodsFor: 'accessing' stamp: 'ssa 3/9/2010 16:15'! indentFor: anItem | aStream lev | (anItem isKindOf: String) ifTrue:[^'']. aStream _ WriteStream on:''. (lev _ self levelOf: anItem) . lev timesRepeat:[aStream nextPutAll:' ']. ^aStream contents,' '! ! !ExplorerListView methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:33'! levelOf: anItem ^anItem depth! ! !ExplorerListView methodsFor: 'displaying' stamp: 'ssa 2/8/2010 16:17'! displayTwisties | box twisty to firstIndex | firstIndex _ self firstShown. firstIndex to: ((self list numberOfLines -2)min:(firstIndex + self numSelectionsInView )) do:[:index| (self objects at: index) hasContents ifTrue:[ box _ self indentBoxFor: index. twisty _(self objects at: index) isOpen ifTrue:[self openedTwistyIcon]ifFalse:[self closedTwistyIcon]. twisty displayOn: Display at: (to_box topRight- (twisty width@0)) clippingBox: (box intersect: self clippingBox) rule: Form paint fillColor: nil. self twistyTargets at:(to extent: twisty extent) put: index]].! ! !ExplorerListView methodsFor: 'displaying' stamp: 'ssa 6/17/2010 16:32'! labelForItem: anItem "Subclasses may want to override" ^(self indentFor: anItem),' ',anItem asString ! ! !FailingTestResourceTestCase methodsFor: 'utility' stamp: 'BaseSystem 8/30/2009 09:40'! clearOuterResourceStateDuring: aBlock "Make the resource impossible to make available, then ensure that every test raises a failure but not an error (which its setUp would do if it reached it and the resource were nil)." ^super clearOuterResourceStateDuring: [SimpleTestResource preventAvailabilityDuring: [self should: aBlock raise: TestResult failure]]! ! !False methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:53'! haltIfFalse self halt ! ! !False class methodsFor: 'instance creation'! dearchiveFrom: aStream aStream storeObject: false. ^false! ! !Field methodsFor: 'accessing' stamp: 'dmu 9/23/2010 14:25'! add: aParticle particles add: aParticle. simulation running ifTrue: [aParticle go]! ! !Field methodsFor: 'accessing'! area ^ area! ! !Field methodsFor: 'accessing'! extent ^ area extent! ! !Field methodsFor: 'accessing'! neighborE ^ neighborE! ! !Field methodsFor: 'accessing'! neighborN ^ neighborN! ! !Field methodsFor: 'accessing'! neighborNE ^ neighborNE! ! !Field methodsFor: 'accessing'! neighborNW ^ neighborNW! ! !Field methodsFor: 'accessing'! neighborS ^ neighborS! ! !Field methodsFor: 'accessing'! neighborSE ^ neighborSE! ! !Field methodsFor: 'accessing'! neighborSW ^ neighborSW! ! !Field methodsFor: 'accessing'! neighborW ^ neighborW! ! !Field methodsFor: 'accessing'! origin ^ self area origin! ! !Field methodsFor: 'accessing'! particles ^ particles! ! !Field methodsFor: 'accessing' stamp: 'dmu 10/6/2010 14:10'! remove: aParticle particles members remove: aParticle ifAbsent: []! ! !Field methodsFor: 'accessing'! simulation ^ simulation! ! !Field methodsFor: 'motion'! go particles do: [:t1 | t1 go]! ! !Field methodsFor: 'motion' stamp: 'max 9/29/2010 12:59'! hand: aParticle to: neighborField neighborField isNil ifTrue: [aParticle bounce. ^ self]. (neighborField = self) ifFalse: [aParticle moveTo: neighborField]. ^ self! ! !Field methodsFor: 'motion' stamp: 'max 9/17/2010 23:58'! localFieldsUnderParticleAt: aLocation size: particleSize | pX pY bounds | pX _ aLocation x. pY _ aLocation y. bounds _ area insetBy: (particleSize // 2). (pX < bounds left) ifTrue: [(pY < bounds top) ifTrue: [^ {neighborNW . neighborN . neighborW . self}]. (pY >= bounds bottom) ifTrue: [^ {neighborSW . neighborS . neighborW . self}]. ^ {neighborW . self}]. (pX >= bounds right) ifTrue: [(pY < bounds top) ifTrue: [^ {neighborNE . neighborN. neighborE . self}]. (pY >= bounds bottom) ifTrue: [^ {neighborSE . neighborS. neighborE . self}]. ^ {neighborE . self}]. (pY < bounds top) ifTrue: [^ {neighborN . self}]. (pY >= bounds bottom) ifTrue: [^ {neighborS . self}]. ^ {self}! ! !Field methodsFor: 'motion' stamp: 'max 9/29/2010 12:48'! particle: aParticle ofSize: itsSize movedTo: aLocation | fields | fields := self localFieldsUnderParticleAt: aLocation size: itsSize. self hand: aParticle to: (fields first). fields do: [:fld | fld ifNotNil: [fld particles do: [:p | p particle: aParticle ofSize: itsSize movedTo: aLocation]]] ! ! !Field methodsFor: 'motion' stamp: 'max 9/16/2010 16:30'! step particles do: [:each | each step]! ! !Field methodsFor: 'motion' stamp: 'max 9/16/2010 16:30'! stop particles do: [:each | each stop]! ! !Field methodsFor: 'displaying'! defaultLabelForInspector | t1 | t1 := WriteStream with: ''. self printOn: t1. ^ t1 contents! ! !Field methodsFor: 'displaying' stamp: 'max 9/16/2010 16:31'! displayOn: aDisplaySurface particles do: [:each | each displayOn: aDisplaySurface]! ! !Field methodsFor: 'displaying' stamp: 'max 9/16/2010 16:32'! printOn: aStream super printOn: aStream. aStream nextPut: $(. self origin printOn: aStream. aStream nextPut: $)! ! !Field methodsFor: 'private'! setArea: t1 area := t1! ! !Field methodsFor: 'private'! setNeighborE: t1 neighborE := t1! ! !Field methodsFor: 'private'! setNeighborN: t1 neighborN := t1! ! !Field methodsFor: 'private'! setNeighborNE: t1 neighborNE := t1! ! !Field methodsFor: 'private'! setNeighborNW: t1 neighborNW := t1! ! !Field methodsFor: 'private'! setNeighborS: t1 neighborS := t1! ! !Field methodsFor: 'private'! setNeighborSE: t1 neighborSE := t1! ! !Field methodsFor: 'private'! setNeighborSW: t1 neighborSW := t1! ! !Field methodsFor: 'private'! setNeighborW: t1 neighborW := t1! ! !Field methodsFor: 'private'! setSimulation: t1 simulation := t1! ! !Field methodsFor: 'initialize-release' stamp: 'max 9/17/2010 10:38'! initialize particles := BlockingSmallSet new! ! !Field class methodsFor: 'instance creation' stamp: 'dmu 9/23/2010 14:07'! null ^ NullField new! ! !Field class methodsFor: 'instance creation'! origin: t1 extent: t2 ^ self new setArea: (t1 extent: t2)! ! !FileDirectory methodsFor: '*transporter' stamp: 'ads 12/13/2010 15:32'! deleteLocalFiles "Took this method from Squeak 3.7; not sure why it wasn't already here. -- Adam" "Delete the local files in this directory." self fileNames do:[:fn| self deleteFileNamed: fn ifAbsent: [(CannotDeleteFileException new messageText: 'Could not delete the old version of file ' , (self fullNameFor: fn)) signal]] ! ! !FileDirectory methodsFor: '*transporter' stamp: 'ads 12/13/2010 15:32'! recursiveDelete "Took this method from Squeak 3.7; not sure why it wasn't already here. -- Adam" "Delete the this directory, recursing down its tree." self directoryNames do: [:dn | (self directoryNamed: dn) recursiveDelete]. self deleteLocalFiles. "should really be some exception handling for directory deletion, but no support for it yet" self containingDirectory deleteDirectory: self localName! ! !FileDirectory class methodsFor: 'name utilities' stamp: 'ssa 9/3/2008 11:25'! startUp "Establish the platform-specific FileDirectory subclass. Do any platform-specific startup." self setDefaultDirectoryClass. self setDefaultDirectory: (self dirPathFor: SmalltalkImage current imageName). Preferences startInUntrustedDirectory ifTrue:[ DefaultDirectory assureExistence]. SmalltalkImage current openSourceFiles. ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 8/28/2009 19:44'! fileContentsMenu: aMenu shifted: shifted "Construct aMenu to have items appropriate for the file browser's code pane, given the shift state provided" | shiftMenu services maybeLine extraLines | shifted ifTrue: [shiftMenu _ ParagraphEditor shiftedYellowButtonMenu. ^ aMenu labels: shiftMenu labelString lines: shiftMenu lineArray selections: shiftMenu selections]. fileName ifNotNil: [services _ OrderedCollection new. (#(briefHex briefFile needToGetBriefHex needToGetBrief) includes: brevityState) ifTrue: [services add: self serviceGet]. (#(fullHex briefHex needToGetFullHex needToGetBriefHex) includes: brevityState) ifFalse: [services add: self serviceGetHex]. maybeLine _ services size. (#('st' 'cs') includes: self suffixOfSelectedFile) ifTrue: [services addAll: (self servicesFromSelectorSpecs: #(fileIntoNewChangeSet: fileIn: browseChangesFile: browseFile:))]. (#('gif' 'jpg' 'bmp') includes: self suffixOfSelectedFile) ifTrue: [services halt addAll: (self servicesFromSelectorSpecs: #(importGraphic))]. extraLines _ OrderedCollection new. maybeLine > 0 ifTrue: [extraLines add: maybeLine]. services size > maybeLine ifTrue: [extraLines add: services size]. aMenu addServices: services for: self fullName extraLines: extraLines]. aMenu addList: { {'find...(f)' translated. #find}. {'find again (g)' translated. #findAgain}. {'set search string (h)' translated. #setSearchString}. #-. {'do again (j)' translated. #again}. {'undo (z)' translated. #undo}. #-. {'copy (c)' translated. #copySelection}. {'cut (x)' translated. #cut}. {'paste (v)' translated. #paste}. {'paste...' translated. #pasteRecent}. #-. {'do it (d)' translated. #doIt}. {'print it (p)' translated. #printIt}. {'inspect it (i)' translated. #inspectIt}. {'fileIn selection (G)' translated. #fileItIn}. #-. {'accept (s)' translated. #accept}. {'cancel (l)' translated. #cancel}. #-. {'more...' translated. #shiftedYellowButtonActivity}}. ^ aMenu ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 8/28/2009 19:14'! fileSelectedMenu: aMenu | firstItems secondItems thirdItems n1 n2 n3 services | firstItems _ self itemsForFile: self fullName. secondItems _ self itemsForAnyFile. thirdItems _ self itemsForNoFile. n1 _ firstItems size. n2 _ n1 + secondItems size. n3 _ n2 + thirdItems size. services _ firstItems, secondItems, thirdItems, self serviceAllFileOptions. services do: [ :svc | svc addDependent: self ]. ^ aMenu addServices2: services for: self extraLines: (Array with: n1 with: n2 with: n3) ! ! !FileList methodsFor: 'file list menu' stamp: 'ssa 9/3/2008 11:18'! fullFileListMenu: aMenu shifted: aBoolean "Fill the menu with all possible items for the file list pane, regardless of selection." | services servicesPlus extraLines linePointer | aMenu title: 'all possible file operations'. servicesPlus := self servicesFromSelectorSpecs: #( fromFileName: openFromFile: - openOn: fileIntoNewChangeSet: fileIn: browseChangesFile: browseRecentLogOnPath: - viewContents: saveContents: openOn: - removeLineFeeds: ). extraLines _ OrderedCollection new. linePointer _ 1. services _ OrderedCollection new. servicesPlus doWithIndex: [:svc :ind | svc == #- ifTrue: [extraLines add: linePointer - 1] ifFalse: [services add: svc. linePointer _ linePointer + 1]]. aMenu addServices: services for: self fullName extraLines: extraLines! ! !FileList methodsFor: 'file list menu' stamp: 'BG 11/2/2003 21:04'! myServicesForFile: fullName suffix: suffix ^(FileStream isSourceFileSuffix: suffix) ifTrue: [ #() ] ifFalse: [ #() ]! ! !FileList class methodsFor: 'instance creation' stamp: 'ssa 8/22/2009 14:57'! open "Open a view of an instance of me on the default directory." "Added scrollingView to support Windoze - ssa" "FileList open" | dir aFileList topView volListView templateView fileListView fileContentsView | World ifNotNil: [^ self openAsMorph]. dir _ FileDirectory default. aFileList _ self new directory: dir. topView _ StandardSystemView new. topView model: aFileList; label: dir pathName; minimumSize: 200@200. topView borderWidth: 1. volListView _ PluggableListView on: aFileList list: #volumeList selected: #volumeListIndex changeSelected: #volumeListIndex: menu: #volumeMenu:. volListView autoDeselect: false. volListView window: (0@0 extent: 80@45). topView addSubView: volListView. templateView _ PluggableTextView on: aFileList text: #pattern accept: #pattern:. templateView scrollingView askBeforeDiscardingEdits: false. templateView window: (0@0 extent: 80@15). topView addSubView: templateView below: volListView. fileListView _ PluggableListView on: aFileList list: #fileList selected: #fileListIndex changeSelected: #fileListIndex: menu: #fileListMenu:. fileListView window: (0@0 extent: 120@60). topView addSubView: fileListView toRightOf: volListView. "fileListView scrollingView controller terminateDuringSelect: true. " "Pane to left may change under scrollbar" fileContentsView _ PluggableTextView on: aFileList text: #contents accept: #put: readSelection: #contentsSelection menu: #fileContentsMenu:shifted:. fileContentsView window: (0@0 extent: 200@140). topView addSubView: fileContentsView below: templateView. topView controller open. ! ! !FileStream class methodsFor: 'concrete classes' stamp: 'ads 1/12/2011 16:27'! concreteStream "Who should we really direct class queries to? " ^ CrLfFileStream "may change this to StandardFileStream"! ! !FileStream class methodsFor: 'file reader services' stamp: 'ssa 9/3/2008 10:33'! fileIn: fullName "File in the entire contents of the file specified by the name provided" | fn ff | fullName ifNil: [^ Beeper beep]. ff _ self readOnlyFileNamed: (fn _ fullName). ((FileDirectory extensionFor: fn) sameAs: 'html') ifTrue: [ff _ ff asHtml]. ff fileIn! ! !Float methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:24'! absPrintOn: aStream base: base digitCount: digitCount "Print me in the given base, using digitCount significant figures." "Float pi absPrintOn: Transcript base: 10 digitCount: 4. Transcript cr;flush" | fuzz x exp q fBase scale logScale xi | self isInf ifTrue: [^ aStream nextPutAll: 'Inf']. fBase _ base asFloat. "x is myself normalized to [1.0, fBase), exp is my exponent" exp _ self < 1.0 ifTrue: [self reciprocalFloorLog: fBase] ifFalse: [self floorLog: fBase]. scale _ 1.0. logScale _ 0. [(x _ fBase raisedTo: (exp + logScale)) = 0] whileTrue: [scale _ scale * fBase. logScale _ logScale + 1]. x _ self * scale / x. fuzz _ fBase raisedTo: 1 - digitCount. "round the last digit to be printed" x _ 0.5 * fuzz + x. x >= fBase ifTrue: ["check if rounding has unnormalized x" x _ x / fBase. exp _ exp + 1]. (exp < 6 and: [exp > -4]) ifTrue: ["decimal notation" q _ 0. exp < 0 ifTrue: [1 to: 1 - exp do: [:i | aStream nextPut: ('0.0000' at: i)]]] ifFalse: ["scientific notation" q _ exp. exp _ 0]. [x >= fuzz] whileTrue: ["use fuzz to track significance" xi _ x asInteger. aStream nextPut: (Character digitValue: xi). x _ x - xi asFloat * fBase. fuzz _ fuzz * fBase. exp _ exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. [exp >= -1] whileTrue: [aStream nextPut: $0. exp _ exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. q ~= 0 ifTrue: [aStream nextPut: $e. q printOn: aStream]! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:23'! bottomCenter ^self width//2@self height ! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! bottomLeft ^0@self height! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! bottomRight ^self extent! ! !Form methodsFor: 'accessing' stamp: 'ssa 8/25/2009 13:22'! displayBox ^Rectangle origin: self offset extent: width @ height! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:22'! leftCenter ^0@(self height//2)! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:22'! rightCenter ^self width @ (self height//2)! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:23'! topCenter ^self width//2@0 ! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! topLeft ^0@0! ! !Form methodsFor: 'accessing' stamp: 'ssa 11/27/2009 00:21'! topRight ^self width@0! ! !Form methodsFor: 'converting' stamp: 'ssa 8/28/2009 16:18'! asOpaqueForm ^OpaqueForm figure: self shape: self! ! !Form methodsFor: 'converting' stamp: 'ssa 8/28/2009 11:32'! wrapAround: aPoint "Answer a new form which contains the image of the receiver, but translated by deltaPoint, with wrap-around. Used for realigning halftone masks. Assumes the receiver is 32x32 with zero offset." "[Sensor anyButtonPressed] whileFalse: [((Cursor normal wrapAround: Sensor cursorPoint) magnifyBy: 8) displayAt: 100@100]" | newForm delta | newForm _ Form extent: (width@height) depth: 1.. delta _ (aPoint x\\32)@(aPoint y\\32). delta = (0@0) ifTrue: [^self]. self displayOn: newForm at: delta-(32@32) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta-(32@0) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta-(0@32) clippingBox: newForm boundingBox rule: Form paint fillColor: nil. self displayOn: newForm at: delta clippingBox: newForm boundingBox rule: Form paint fillColor: nil. ^newForm! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 09:59'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm aDisplayMedium copyBits: self boundingBox from: self at: aDisplayPoint + self offset clippingBox: clipRectangle rule: rule fillColor: aForm map: (self colormapIfNeededFor: aDisplayMedium). ! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 15:45'! displayTranslucentOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle ((aDisplayMedium isKindOf:Form) ifTrue:[aDisplayMedium]ifFalse:[aDisplayMedium displayMedium]) paintBits: self at: aDisplayPoint + self offset clippingBox: clipRectangle translucent: 0.3! ! !Form methodsFor: 'displaying' stamp: 'ssa 9/4/2009 15:32'! paintBits: sourceForm at: destOrigin clippingBox: aRect translucent: factor "Make up a BitBlt table and copy the bits with the given colorMap." (BitBlt current destForm: self sourceForm: sourceForm halftoneForm: nil combinationRule: 31 destOrigin: destOrigin sourceOrigin: 0@0 extent: sourceForm extent clipRect: aRect) copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255) " | f f2 f3 | f _ Form fromUser. f replaceColor: (Color r: 0.8 g: 1.0 b: 0.599) withColor: Color transparent. f2 _ Form fromDisplay: (0@0 extent: f extent). f3 _ f2 deepCopy. 0.0 to: 1.0 by: 1.0/32 do: [:t | f3 _ f2 deepCopy. f3 paintBits: f at: 0@0 translucent: t. f3 displayAt: 0@0. (Delay forMilliseconds: 100) wait]. "! ! !Form methodsFor: 'filling' stamp: 'ssa 11/30/2009 13:30'! fill: aRectangle rule: anInteger fillColor: aForm clippingBox: clipRect "Replace a rectangular area of the receiver with the pattern described by aForm according to the rule anInteger." "Display fill: (300@300 extent: 300@100) rule: Form paint fillColor: Color red. Display fill: (300@300 extent: 300@100) rule: Form paint fillColor: Color green clippingBox: (300@300 extent: 150@100)" | bb | bb _ BitBlt current toForm: self. bb clipRect: clipRect. bb copy: aRectangle from: 0@0 in: nil fillColor: aForm rule: anInteger! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 12/17/2009 16:16'! erase self eraseInside: self boundingBox! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 12/17/2009 16:26'! eraseInside: aRect "Erase a transparent rectangular 'hole' in me" " | form| form _ Form extent:100@100 depth: Display depth. form fillColor: Color blue. form eraseInside: (20@20 extent:60@60). form followCursor" | eraser | eraser _ Form extent: self extent depth:1. eraser fill: aRect fillColor: Color black. self eraseShape: eraser! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 4/10/2009 23:42'! nextLifeGeneration "Compute next generation by computing neighbor counts. These are tallied in nbr1, nbr2, nbr4." | all delta nbr1 nbr2 nbr4 carry2 carry4 | all _ 0@0 extent: self extent. nbr1 _ Form extent: self extent. nbr2 _ Form extent: self extent. nbr4 _ Form extent: self extent. carry2 _ Form extent: self extent. carry4 _ Form extent: self extent. nbr1 fillWhite. nbr2 fillWhite. nbr4 fillWhite. 1 to: 8 do: "Three-bit add for each shift of self" [:i | delta _ (i+4\\9//3 - 1)@(i+4\\3 - 1). "8 neighbor deltas" carry2 copy: all from: nbr1 to: 0@0 rule: Form over. carry2 copy: all from: self to: delta rule: Form and. "carry 2" nbr1 copy: all from: self to: delta rule: Form reverse. "sum 1" "(reverse is xor)" carry4 copy: all from: nbr2 to: 0@0 rule: Form over. carry4 copy: all from: carry2 to: 0@0 rule: Form and. "carry 4" nbr2 copy: all from: carry2 to: 0@0 rule: Form reverse. "sum 2" nbr4 copy: all from: carry4 to: 0@0 rule: Form reverse]. "sum 4" "Next gen = ((2s AND self) OR (2s AND 1s)) AND (NOT 4s)" self copy: all from: nbr2 to: 0@0 rule: Form and. nbr1 copy: all from: nbr2 to: 0@0 rule: Form and. self copy: all from: nbr1 to: 0@0 rule: Form under. self copy: all from: nbr4 to: 0@0 rule: Form erase. self borderWidth: 1 fillColor: Color white. "trim edges"! ! !Form methodsFor: 'image manipulation' stamp: 'ssa 4/10/2009 23:39'! nextLifeGenerationBlueBook "|f| f_Form fromUser. 100 timesRepeat:[f nextLifeGeneration display]" | nbr1 nbr2 nbr4 carry2 carry4 all delta | nbr1 := Form extent: self extent. nbr2 := Form extent: self extent. nbr4 := Form extent: self extent. carry2 := Form extent: self extent. carry4 := Form extent: self extent. all := self boundingBox. 1 to: 8 do: [:i | "delta is the offset of the eight neighboring cells" delta := (#(-1 0 1 1 1 0 1 -1 ) at: i) @ (#(1 -1 -1 0 1 1 1 0 ) at: i). carry2 copy: all from: 0 @ 0 in: nbr1 rule: 3. carry2 copy: all from: delta in: self rule: 1. "AND for carry into 2" nbr1 copy: all from: delta in: self rule: 6. "XOR for sum 1" carry4 copy: all from: 0 @ 0 in: nbr2 rule: 3. carry4 copy: all from: 0 @ 0 in: carry2 rule: 1. "AND for carry into 4" nbr2 copy: all from: 0 @ 0 in: carry2 rule: 6. "XOR for sum 2" nbr4 copy: all from: 0 @ 0 in: carry4 rule: 6]. "XOR for sum 4 (ignore carry into 8)" self copy: all from: 0 @ 0 in: nbr2 rule: 1. nbr1 copy: all from: 0 @ 0 in: nbr2 rule: 1. self copy: all from: 0 @ 0 in: nbr1 rule: 7. self copy: all from: 0 @ 0 in: nbr4 rule: 4 "compute next generation"! ! !Form methodsFor: 'scaling, rotation' stamp: 'ssa 8/31/2009 13:43'! rotateBy: deg smoothing: cellSize "Rotate the receiver by the indicated number of degrees." "rot is the destination form, big enough for any angle." | side rot warp r1 pts p center dim | side _ 1 + ((width*width) + (height*height)) asFloat sqrt asInteger. (#(0 90 180 270 360) includes: deg abs) ifTrue:[dim _ self extent]ifFalse:[dim _ side@side]. rot _ Form extent: dim depth: self depth. center _ rot extent // 2. "Now compute the sin and cos constants for the rotation angle." warp _ (WarpBlt current toForm: rot) sourceForm: self; colorMap: (self colormapIfNeededFor: rot); cellSize: cellSize; "installs a new colormap if cellSize > 1" combinationRule: Form over. r1 _ rot boundingBox align: center with: self boundingBox center. pts _ r1 innerCorners collect: [:pt | p _ pt - r1 center. (r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @ (r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))]. warp copyQuad: pts toRect: rot boundingBox. ^ rot " | a f | f _ Form fromDisplay: (0@0 extent: 200@200). a _ 0. [Sensor anyButtonPressed] whileFalse: [((Form fromDisplay: (Sensor cursorPoint extent: 130@66)) rotateBy: (a _ a+5) smoothing: 2) display]. f display "! ! !Form methodsFor: 'scaling, rotation' stamp: 'ssa 11/30/2009 12:57'! scaledToSize: newExtent | scale | newExtent = self extent ifTrue: [^self]. scale _ (newExtent x / self width) @ (newExtent y / self height). ^self magnify: self boundingBox by: scale smoothing: 2. ! ! !Form methodsFor: '*RVM-Archiving'! archiveOn: anArchiver "Always use #storeOn: and #readFrom:" " anArchiver isCopier ifFalse: [^super archiveOn: anArchiver]." anArchiver storeObject: self; storeClass: self class; store: self.! ! !Form class methodsFor: 'instance creation' stamp: 'ssa 11/17/2008 13:50'! dotOfSize: diameter color: aColor "Create a form which contains a round colored dot with transparent background." | radius form bb rect centerX centerY centerYBias centerXBias radiusSquared xOverY maxy dx | radius _ diameter//2. form _ self extent: diameter@diameter depth: Display depth. form offset: (0@0) - (radius@radius). bb _ (BitBlt current toForm: form) sourceX: 0; sourceY: 0; combinationRule: Form over; fillColor: aColor. rect _ form boundingBox. centerX _ rect center x. centerY _ rect center y. centerYBias _ rect height odd ifTrue: [0] ifFalse: [1]. centerXBias _ rect width odd ifTrue: [0] ifFalse: [1]. radiusSquared _ (rect height asFloat / 2.0) squared - 0.01. xOverY _ rect width asFloat / rect height asFloat. maxy _ rect height - 1 // 2. "First do the inner fill, and collect x values" 0 to: maxy do: [:dy | dx _ ((radiusSquared - (dy * dy) asFloat) sqrt * xOverY) truncated. bb destX: centerX - centerXBias - dx destY: centerY - centerYBias - dy width: dx + dx + centerXBias + 1 height: 1; copyBits. bb destY: centerY + dy; copyBits]. form mapColor: Color white to: Color transparent. ^ form " Time millisecondsToRun: [1 to: 30 do: [:i | (Form dotOfSize: i color: Color random) displayAt: (i*30)@(i*30)]] "! ! !Form class methodsFor: 'instance creation' stamp: 'ssa 8/28/2009 19:30'! fromBinaryStream: aBinaryStream "Read a Form or ColorForm from given file, using the first byte of the file to guess its format. Currently handles: GIF, uncompressed BMP, and both old and new DisplayObject writeOn: formats, JPEG, and PCX. Return nil if the file could not be read or was of an unrecognized format." | firstByte | aBinaryStream binary. firstByte _ aBinaryStream next. firstByte = 1 ifTrue: [ "old Squeakform format" ^ self new readFromOldFormat: aBinaryStream]. firstByte = 2 ifTrue: [ "new Squeak form format" ^ self new readFrom: aBinaryStream]. "Try for JPG, GIF, or PCX..." "Note: The following call closes the stream." ^ ImageReadWriter formFromStream: aBinaryStream ! ! !Form class methodsFor: '*RVM-Archiving'! archiveVersion "universal 2.3, 2.4 format." ^3! ! !Form class methodsFor: '*RVM-Archiving'! dearchive2From: anArchiver "If the archiver is a copier, just get a deepCopy directly from it." | anObject | anArchiver isCopier ifFalse: [^super dearchiveFrom: anArchiver]. anObject _ (anArchiver read: self) deepCopy. anArchiver storeObject: anObject. ^anObject! ! !Form class methodsFor: '*RVM-Archiving'! dearchive: versionNumber from: aStream "Override this method when implementing new archive versions for a class." ^versionNumber == self archiveVersion ifTrue: [self dearchiveFrom: aStream] ifFalse: [versionNumber == 2 ifTrue: [self dearchive2From: aStream] ifFalse: [self error: 'Can''t dearchive this version.']]! ! !Form class methodsFor: '*RVM-Archiving'! dearchiveFrom: anArchiver "Always use store: and read:." | anObject | anObject _ anArchiver read: self. anArchiver isCopier ifTrue: [anObject _ anObject deepCopy]. anArchiver storeObject: anObject. ^anObject! ! !FormView methodsFor: 'controller access' stamp: 'ssa 10/8/2008 13:14'! defaultControllerClass ^ NoController! ! !FormView methodsFor: 'displaying' stamp: 'ssa 11/26/2009 22:52'! displayView "Refer to the comment in View|displayView." | oldOffset | super displayView. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: insideColor]. oldOffset _ model offset. model offset: "borderWidth origin" 0@0. model displayOn: Display at: self insetDisplayBox origin clippingBox: self insetDisplayBox rule: Form paint fillColor: nil. model offset: oldOffset! ! !FormView methodsFor: 'private' stamp: 'ssa 11/26/2009 22:42'! defaultRule "The default display rule is 3=over or storing." ^Form paint! ! !FormView class methodsFor: 'examples' stamp: 'ssa 11/26/2009 22:47'! open: aForm named: aString "FormView open: ((ColorForm fromUser) borderWidth: 1) named: 'Squeak' " "Open a window whose model is aForm and whose label is aString." | topView aView | topView _ StandardSystemView new. topView model: aForm. topView label: aString. topView minimumSize: aForm extent+2"; maximumSize: aForm extent + 2". aView _ FormView new. aView model: aForm. "aView window: (aForm boundingBox expandBy: 2)." aView borderWidthLeft: 1 right: 1 top: 2 bottom: 1. topView addSubView: aView. topView controller open! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:43'! delay: aNumberOrNil "Set delay for next image in hundredth (1/100) of seconds" delay := aNumberOrNil! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'bf 5/29/2003 01:39'! loopCount: aNumber "Set looping. This must be done before any image is written!!" loopCount := aNumber! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'sd 1/30/2004 15:18'! nextImage "Read in the next GIF image from the stream. Read it all into memory first for speed." | f thisImageColorTable | stream class == ReadWriteStream ifFalse: [ stream binary. self on: (ReadWriteStream with: (stream contentsOfEntireFile))]. localColorTable _ nil. self readHeader. f _ self readBody. self close. f == nil ifTrue: [^ self error: 'corrupt GIF file']. thisImageColorTable _ localColorTable ifNil: [colorPalette]. transparentIndex ifNotNil: [ transparentIndex + 1 > thisImageColorTable size ifTrue: [ thisImageColorTable _ thisImageColorTable forceTo: transparentIndex + 1 paddingWith: Color white ]. thisImageColorTable at: transparentIndex + 1 put: Color transparent ]. f colors: thisImageColorTable. ^ f ! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'ar 10/24/2005 22:52'! nextPutImage: aForm | reduced tempForm | aForm unhibernate. aForm depth > 8 ifTrue:[ reduced := aForm colorReduced. "minimize depth" reduced depth > 8 ifTrue: [ "Not enough color space; do it the hard way." reduced := reduced asFormOfDepth: 8]. ] ifFalse:[reduced := aForm]. reduced depth < 8 ifTrue: [ "writeBitData: expects depth of 8" tempForm := reduced class extent: reduced extent depth: 8. (reduced isColorForm) ifTrue:[ tempForm copyBits: reduced boundingBox from: reduced at: 0@0 clippingBox: reduced boundingBox rule: Form over fillColor: nil map: nil. tempForm colors: reduced colors. ] ifFalse: [reduced displayOn: tempForm]. reduced := tempForm. ]. (reduced isColorForm) ifTrue:[ (reduced colorsUsed includes: Color transparent) ifTrue: [ transparentIndex := (reduced colors indexOf: Color transparent) - 1. ] ] ifFalse: [transparentIndex := nil]. width := reduced width. height := reduced height. bitsPerPixel := reduced depth. colorPalette := reduced colormapIfNeededForDepth: 32. interlace := false. self writeHeader. self writeBitData: reduced bits. ! ! !GIFReadWriter methodsFor: 'accessing' stamp: '6/18/97 13:18 '! setStream: aStream "Feed it in from an existing source" stream _ aStream! ! !GIFReadWriter methodsFor: 'accessing' stamp: 'di 9/15/1998 09:53'! understandsImageFormat ^('abc' collect: [:x | stream next asCharacter]) = 'GIF'! ! !GIFReadWriter methodsFor: 'private-encoding'! flushCode self flushBits! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'tk 9/14/97 16:25'! readPixelFrom: bits "Since bits is a Bitmap with 32 bit values, watch out for the padding at the end of each row. But, GIF format already wants padding to 32 bit boundary!! OK as is. tk 9/14/97" | pixel | ypos >= height ifTrue: [^nil]. pixel _ bits byteAt: (ypos * rowByteSize + xpos + 1). self updatePixelPosition. ^pixel! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:21'! writeBitData: bits "using modified Lempel-Ziv Welch algorithm." | maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel index disp nomatch | pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ width * 8 + 31 // 32 * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ WriteStream on: (ByteArray new: 256). maxBits _ 12. maxMaxCode _ 1 bitShift: maxBits. tSize _ 5003. prefixTable _ Array new: tSize. suffixTable _ Array new: tSize. initCodeSize _ bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. self nextPut: initCodeSize. self setParameters: initCodeSize. tShift _ 0. fCode _ tSize. [fCode < 65536] whileTrue: [tShift _ tShift + 1. fCode _ fCode * 2]. tShift _ 8 - tShift. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self writeCodeAndCheckCodeSize: clearCode. ent _ self readPixelFrom: bits. [(pixel _ self readPixelFrom: bits) == nil] whileFalse: [ fCode _ (pixel bitShift: maxBits) + ent. index _ ((pixel bitShift: tShift) bitXor: ent) + 1. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index] ifFalse: [nomatch _ true. (suffixTable at: index) >= 0 ifTrue: [disp _ tSize - index + 1. index = 1 ifTrue: [disp _ 1]. "probe" [(index _ index - disp) < 1 ifTrue: [index _ index + tSize]. (suffixTable at: index) = fCode ifTrue: [ent _ prefixTable at: index. nomatch _ false. "continue whileFalse:"]. nomatch and: [(suffixTable at: index) > 0]] whileTrue: ["probe"]]. "nomatch" nomatch ifTrue: [self writeCodeAndCheckCodeSize: ent. ent _ pixel. freeCode < maxMaxCode ifTrue: [prefixTable at: index put: freeCode. suffixTable at: index put: fCode. freeCode _ freeCode + 1] ifFalse: [self writeCodeAndCheckCodeSize: clearCode. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self setParameters: initCodeSize]]]]. prefixTable _ suffixTable _ nil. self writeCodeAndCheckCodeSize: ent. self writeCodeAndCheckCodeSize: eoiCode. self flushCode. self nextPut: 0. "zero-length packet" ! ! !GIFReadWriter methodsFor: 'private-encoding'! writeCode: aCode self nextBitsPut: aCode! ! !GIFReadWriter methodsFor: 'private-encoding'! writeCodeAndCheckCodeSize: aCode self writeCode: aCode. self checkCodeSize! ! !GIFReadWriter methodsFor: 'private-encoding' stamp: 'bf 5/29/2003 01:38'! writeHeader | byte | stream position = 0 ifTrue: [ "For first image only" self nextPutAll: 'GIF89a' asByteArray. self writeWord: width. "Screen Width" self writeWord: height. "Screen Height" byte _ 16r80. "has color map" byte _ byte bitOr: ((bitsPerPixel - 1) bitShift: 5). "color resolution" byte _ byte bitOr: bitsPerPixel - 1. "bits per pixel" self nextPut: byte. self nextPut: 0. "background color." self nextPut: 0. "reserved" colorPalette do: [:pixelValue | self nextPut: ((pixelValue bitShift: -16) bitAnd: 255); nextPut: ((pixelValue bitShift: -8) bitAnd: 255); nextPut: (pixelValue bitAnd: 255)]. loopCount notNil ifTrue: [ "Write a Netscape loop chunk" self nextPut: Extension. self nextPutAll: #(255 11 78 69 84 83 67 65 80 69 50 46 48 3 1) asByteArray. self writeWord: loopCount. self nextPut: 0]]. delay notNil | transparentIndex notNil ifTrue: [ self nextPut: Extension; nextPutAll: #(16rF9 4) asByteArray; nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [9]); writeWord: (delay isNil ifTrue: [0] ifFalse: [delay]); nextPut: (transparentIndex isNil ifTrue: [0] ifFalse: [transparentIndex]); nextPut: 0]. self nextPut: ImageSeparator. self writeWord: 0. "Image Left" self writeWord: 0. "Image Top" self writeWord: width. "Image Width" self writeWord: height. "Image Height" byte _ interlace ifTrue: [16r40] ifFalse: [0]. self nextPut: byte. ! ! !GIFReadWriter methodsFor: 'private-encoding'! writeWord: aWord self nextPut: (aWord bitAnd: 255). self nextPut: ((aWord bitShift: -8) bitAnd: 255). ^aWord! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'mir 11/19/2003 12:19'! readBitData "using modified Lempel-Ziv Welch algorithm." | outCodes outCount bitMask initCodeSize code curCode oldCode inCode finChar i bytes f c packedBits hasLocalColor localColorSize maxOutCodes | maxOutCodes _ 4096. offset := self readWord@self readWord. "Image Left@Image Top" width _ self readWord. height _ self readWord. "--- Local Color Table Flag 1 Bit Interlace Flag 1 Bit Sort Flag 1 Bit Reserved 2 Bits Size of Local Color Table 3 Bits ----" packedBits _ self next. interlace _ (packedBits bitAnd: 16r40) ~= 0. hasLocalColor _ (packedBits bitAnd: 16r80) ~= 0. localColorSize _ 1 bitShift: ((packedBits bitAnd: 16r7) + 1). hasLocalColor ifTrue: [localColorTable _ self readColorTable: localColorSize]. pass _ 0. xpos _ 0. ypos _ 0. rowByteSize _ ((width + 3) // 4) * 4. remainBitCount _ 0. bufByte _ 0. bufStream _ ReadStream on: ByteArray new. outCodes _ ByteArray new: maxOutCodes + 1. outCount _ 0. bitMask _ (1 bitShift: bitsPerPixel) - 1. prefixTable _ Array new: 4096. suffixTable _ Array new: 4096. initCodeSize _ self next. self setParameters: initCodeSize. bitsPerPixel > 8 ifTrue: [^self error: 'never heard of a GIF that deep']. bytes _ ByteArray new: rowByteSize * height. [(code _ self readCode) = eoiCode] whileFalse: [code = clearCode ifTrue: [self setParameters: initCodeSize. curCode _ oldCode _ code _ self readCode. finChar _ curCode bitAnd: bitMask. "Horrible hack to avoid running off the end of the bitmap. Seems to cure problem reading some gifs!!? tk 6/24/97 20:16" xpos = 0 ifTrue: [ ypos < height ifTrue: [ bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]] ifFalse: [bytes at: (ypos * rowByteSize) + xpos + 1 put: finChar]. self updatePixelPosition] ifFalse: [curCode _ inCode _ code. curCode >= freeCode ifTrue: [curCode _ oldCode. outCodes at: (outCount _ outCount + 1) put: finChar]. [curCode > bitMask] whileTrue: [outCount > maxOutCodes ifTrue: [^self error: 'corrupt GIF file (OutCount)']. outCodes at: (outCount _ outCount + 1) put: (suffixTable at: curCode + 1). curCode _ prefixTable at: curCode + 1]. finChar _ curCode bitAnd: bitMask. outCodes at: (outCount _ outCount + 1) put: finChar. i _ outCount. [i > 0] whileTrue: ["self writePixel: (outCodes at: i) to: bits" bytes at: (ypos * rowByteSize) + xpos + 1 put: (outCodes at: i). self updatePixelPosition. i _ i - 1]. outCount _ 0. prefixTable at: freeCode + 1 put: oldCode. suffixTable at: freeCode + 1 put: finChar. oldCode _ inCode. freeCode _ freeCode + 1. self checkCodeSize]]. prefixTable _ suffixTable _ nil. f _ ColorForm extent: width@height depth: 8. f bits copyFromByteArray: bytes. "Squeak can handle depths 1, 2, 4, and 8" bitsPerPixel > 4 ifTrue: [^ f]. "reduce depth to save space" c _ ColorForm extent: width@height depth: (bitsPerPixel = 3 ifTrue: [4] ifFalse: [bitsPerPixel]). f displayOn: c. ^ c ! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'KLC 1/25/2004 14:04'! readBody "Read the GIF blocks. Modified to return a form. " | form extype block blocksize packedFields delay1 | form _ nil. [stream atEnd] whileFalse: [ block _ self next. block = Terminator ifTrue: [^ form]. block = ImageSeparator ifTrue: [ form isNil ifTrue: [form _ self readBitData] ifFalse: [self skipBitData]. ] ifFalse: [ block = Extension ifFalse: [^ form "^ self error: 'Unknown block type'"]. "Extension block" extype _ self next. "extension type" extype = 16rF9 ifTrue: [ "graphics control" self next = 4 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. "==== Reserved 3 Bits Disposal Method 3 Bits User Input Flag 1 Bit Transparent Color Flag 1 Bit ===" packedFields _ self next. delay1 := self next. "delay time 1" delay := (self next*256 + delay1) *10. "delay time 2" transparentIndex _ self next. (packedFields bitAnd: 1) = 0 ifTrue: [transparentIndex _ nil]. self next = 0 ifFalse: [^ form "^ self error: 'corrupt GIF file'"]. ] ifFalse: [ "Skip blocks" [(blocksize _ self next) > 0] whileTrue: [ "Read the block and ignore it and eat the block terminator" self next: blocksize]]]]! ! !GIFReadWriter methodsFor: 'private-decoding'! readCode ^self nextBits! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:48'! readColorTable: numberOfEntries | array r g b | array _ Array new: numberOfEntries. 1 to: array size do: [ :i | r _ self next. g _ self next. b _ self next. array at: i put: (Color r: r g: g b: b range: 255) ]. ^array! ! !GIFReadWriter methodsFor: 'private-decoding' stamp: 'RAA 4/25/2001 08:49'! readHeader | is89 byte hasColorMap | (self hasMagicNumber: 'GIF87a' asByteArray) ifTrue: [is89 _ false] ifFalse: [(self hasMagicNumber: 'GIF89a' asByteArray) ifTrue: [is89 _ true] ifFalse: [^ self error: 'This does not appear to be a GIF file']]. self readWord. "skip Screen Width" self readWord. "skip Screen Height" byte _ self next. hasColorMap _ (byte bitAnd: 16r80) ~= 0. bitsPerPixel _ (byte bitAnd: 7) + 1. byte _ self next. "skip background color." self next ~= 0 ifTrue: [is89 ifFalse: [^self error: 'corrupt GIF file (screen descriptor)']]. hasColorMap ifTrue: [colorPalette _ self readColorTable: (1 bitShift: bitsPerPixel)] ifFalse: ["Transcript cr; show: 'GIF file does not have a color map.'." colorPalette _ nil "Palette monochromeDefault"].! ! !GIFReadWriter methodsFor: 'private-decoding'! readWord ^self next + (self next bitShift: 8)! ! !GIFReadWriter methodsFor: 'private-decoding'! skipBitData | misc blocksize | self readWord. "skip Image Left" self readWord. "skip Image Top" self readWord. "width" self readWord. "height" misc _ self next. (misc bitAnd: 16r80) = 0 ifFalse: [ "skip colormap" 1 to: (1 bitShift: (misc bitAnd: 7) + 1) do: [:i | self next; next; next]]. self next. "minimum code size" [(blocksize _ self next) > 0] whileTrue: [self next: blocksize]! ! !GIFReadWriter methodsFor: 'private-bits access'! flushBits remainBitCount = 0 ifFalse: [self nextBytePut: bufByte. remainBitCount _ 0]. self flushBuffer! ! !GIFReadWriter methodsFor: 'private-bits access'! nextBits | integer readBitCount shiftCount byte | integer _ 0. remainBitCount = 0 ifTrue: [readBitCount _ 8. shiftCount _ 0] ifFalse: [readBitCount _ remainBitCount. shiftCount _ remainBitCount - 8]. [readBitCount < codeSize] whileTrue: [byte _ self nextByte. byte == nil ifTrue: [^eoiCode]. integer _ integer + (byte bitShift: shiftCount). shiftCount _ shiftCount + 8. readBitCount _ readBitCount + 8]. (remainBitCount _ readBitCount - codeSize) = 0 ifTrue: [byte _ self nextByte] ifFalse: [byte _ self peekByte]. byte == nil ifTrue: [^eoiCode]. ^(integer + (byte bitShift: shiftCount)) bitAnd: maxCode! ! !GIFReadWriter methodsFor: 'private-bits access'! nextBitsPut: anInteger | integer writeBitCount shiftCount | shiftCount _ 0. remainBitCount = 0 ifTrue: [writeBitCount _ 8. integer _ anInteger] ifFalse: [writeBitCount _ remainBitCount. integer _ bufByte + (anInteger bitShift: 8 - remainBitCount)]. [writeBitCount < codeSize] whileTrue: [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255). shiftCount _ shiftCount - 8. writeBitCount _ writeBitCount + 8]. (remainBitCount _ writeBitCount - codeSize) = 0 ifTrue: [self nextBytePut: (integer bitShift: shiftCount)] ifFalse: [bufByte _ integer bitShift: shiftCount]. ^anInteger! ! !GIFReadWriter methodsFor: 'private-packing'! fillBuffer | packSize | packSize _ self next. bufStream _ ReadStream on: (self next: packSize)! ! !GIFReadWriter methodsFor: 'private-packing'! flushBuffer bufStream isEmpty ifTrue: [^self]. self nextPut: bufStream size. self nextPutAll: bufStream contents. bufStream _ WriteStream on: (ByteArray new: 256)! ! !GIFReadWriter methodsFor: 'private-packing'! nextByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream next! ! !GIFReadWriter methodsFor: 'private-packing'! nextBytePut: aByte bufStream nextPut: aByte. bufStream size >= 254 ifTrue: [self flushBuffer]! ! !GIFReadWriter methodsFor: 'private-packing'! peekByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream peek! ! !GIFReadWriter methodsFor: 'private'! checkCodeSize (freeCode > maxCode and: [codeSize < 12]) ifTrue: [codeSize _ codeSize + 1. maxCode _ (1 bitShift: codeSize) - 1]! ! !GIFReadWriter methodsFor: 'private'! setParameters: initCodeSize clearCode _ 1 bitShift: initCodeSize. eoiCode _ clearCode + 1. freeCode _ clearCode + 2. codeSize _ initCodeSize + 1. maxCode _ (1 bitShift: codeSize) - 1! ! !GIFReadWriter methodsFor: 'private'! updatePixelPosition (xpos _ xpos + 1) >= width ifFalse: [^self]. xpos _ 0. interlace ifFalse: [ypos _ ypos + 1. ^self]. pass = 0 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 4]. ^self]. pass = 1 ifTrue: [(ypos _ ypos + 8) >= height ifTrue: [pass _ pass + 1. ypos _ 2]. ^self]. pass = 2 ifTrue: [(ypos _ ypos + 4) >= height ifTrue: [pass _ pass + 1. ypos _ 1]. ^self]. pass = 3 ifTrue: [ypos _ ypos + 2. ^self]. ^self error: 'can''t happen'! ! !GIFReadWriter methodsFor: 'stream access' stamp: 'bf 5/29/2003 01:23'! close "Write terminator" self nextPut: Terminator. ^super close! ! !GIFReadWriter commentStamp: '<historical>' prior: 0! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. Used with permission. Modified for use in Squeak.! !GIFReadWriter class methodsFor: 'class initialization'! initialize "GIFReadWriter initialize" ImageSeparator _ $, asInteger. Extension _ $!! asInteger. Terminator _ $; asInteger. ! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'bf 5/29/2003 01:56'! exampleAnim "GIFReadWriter exampleAnim" | writer extent center | writer := GIFReadWriter on: (FileStream newFileNamed: 'anim.gif'). writer loopCount: 20. "Repeat 20 times" writer delay: 10. "Wait 10/100 seconds" extent := 42@42. center := extent / 2. Cursor write showWhile: [ [2 to: center x - 1 by: 2 do: [:r | "Make a fancy anim without using Canvas - inefficient as hell" | image | image := ColorForm extent: extent depth: 8. 0.0 to: 359.0 do: [:theta | image colorAt: (center + (Point r: r degrees: theta)) rounded put: Color red]. writer nextPutImage: image] ] ensure: [writer close]].! ! !GIFReadWriter class methodsFor: 'examples' stamp: 'nk 7/30/2004 21:40'! grabScreenAndSaveOnDisk "GIFReaderWriter grabScreenAndSaveOnDisk" | form fileName | form := Form fromUser. form bits size = 0 ifTrue: [^Beeper beep]. fileName := FileDirectory default nextNameFor: 'Squeak' extension: 'gif'. Utilities informUser: 'Writing ' , fileName during: [GIFReadWriter putForm: form onFileNamed: fileName]! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" self allSubclasses detect: [:cls | cls wantsToHandleGIFs ] ifNone: ["if none of my subclasses wants , then i''ll have to do" ^ #('gif' )]. ^ #( )! ! !GIFReadWriter class methodsFor: 'image reading/writing' stamp: 'asm 12/11/2003 21:29'! wantsToHandleGIFs ^ false! ! !HashAndEqualsTestCase methodsFor: 'running' stamp: 'stephaneducasse 2/3/2006 22:39'! setUp "subclasses will add their prototypes into this collection" prototypes := OrderedCollection new ! ! !HashAndEqualsTestCase methodsFor: 'testing' stamp: 'mjr 8/20/2003 18:56'! testEquality "Check that TextFontChanges report equality correctly" prototypes do: [:p | self should: [(EqualityTester with: p) result]] ! ! !HashAndEqualsTestCase methodsFor: 'testing' stamp: 'al 6/12/2008 21:58'! testHash "test that TextFontChanges hash correctly" prototypes do: [:p | self should: [(HashTester with: p) result]] ! ! !HashAndEqualsTestCase commentStamp: 'mjr 8/20/2003 17:37' prior: 0! I am a simple TestCase that tests for correct operation of #hash and #=. Subclasses of me need to fill my prototypes with suitable objects to be tested.! !HashTester methodsFor: 'as yet unclassified'! resultFor: runs "Test that the hash is the same over runs and answer the result" | hash | hash := self prototype hash. 1 to: runs do: [:i | hash = self prototype hash ifFalse: [^ false]]. ^ true ! ! !HashTester commentStamp: 'mjr 8/20/2003 12:48' prior: 0! I provide a simple way to test the hash properties of any object. I am given an object that should be tested and I treat it like a prototype. I take a copy of it when I am given it so that it can't change whilst I am holding on to it. I can then test that multiple copies of this object all hash to the same value.! !HashTesterTest methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 18:56'! testBasicBehaviour self should: [(HashTester with: 1) resultFor: 100]. self should: [(HashTester with: 'fred') resultFor: 100]. self shouldnt: [(HashTester with: BadHasher new) resultFor: 100] ! ! !HashTesterTest commentStamp: 'mjr 8/20/2003 12:48' prior: 0! I am a simple test case to check that HashTester works correctly! !HeadlessSave class methodsFor: 'script entry' stamp: 'sm 2/13/2011 19:35'! run: arguments | proc | proc := [ | basicName newName | RVMOperations print: 'Do wait, let system run non-busy, and then save and quit'. (Delay forSeconds: 10) wait. RVMOperations print: 'Do headless save now.'. basicName := SmalltalkImage current imageName withoutLast: '.image' size. newName := basicName, '-headless.image'. SmalltalkImage current saveAs: newName. SmalltalkImage current snapshot: false andQuit: true. ] newProcess. proc priority: Processor userBackgroundPriority. proc resume. ! ! !HelloWorld commentStamp: 'StefanMarr 5/14/2011 16:42' prior: 0! Simple example for how to use ScriptStarter. HelloWorld prints all arguments given to #run:.! !HelloWorld class methodsFor: 'script entry'! run: arguments ScriptConsole print: 'Hello World!!'. arguments do: [:elem | ScriptConsole print: elem]. SmalltalkImage current snapshot: false andQuit: true! ! !HierarchyBrowser methodsFor: 'initialization' stamp: 'ssa 9/10/2009 13:34'! setClass: aBehavior selector: aSymbol "Set the state of a new, uninitialized Browser." | isMeta aClass messageCatIndex | aBehavior ifNil: [^ self]. (aBehavior isKindOf: Metaclass) ifTrue: [ isMeta _ true. aClass _ aBehavior soleInstance] ifFalse: [ isMeta _ false. aClass _ aBehavior]. self selectCategoryForClass: aClass. self selectClass: aClass. self metaClassIndicated: isMeta. aSymbol ifNil: [^ self]. messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol. self messageCategoryListIndex: (messageCatIndex > 0 ifTrue: [messageCatIndex + 1] ifFalse: [0]). messageCatIndex = 0 ifTrue: [^ self]. self messageListIndex: ( (aBehavior organization listAtCategoryNumber: messageCatIndex) indexOf: aSymbol).! ! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'ssa 3/1/2010 13:54'! newFor: aClass "Open a new HierarchyBrowser on the given class" self newFor: aClass labeled: nil "HierarchyBrowser newFor: Boolean"! ! !HierarchyBrowser class methodsFor: 'as yet unclassified' stamp: 'ssa 3/1/2010 13:54'! newFor: aClass labeled: aLabel "Open a new HierarchyBrowser on the given class, using aLabel as the window title." | newBrowser | newBrowser _ self new initHierarchyForClass: aClass. Browser openBrowserView: (newBrowser openSystemCatEditString: nil) label: (aLabel isNil ifTrue:[newBrowser labelString]ifFalse:[aLabel]) "HierarchyBrowser newFor: Boolean labeled: 'Testing'"! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:29'! childrenOf: anObject ^anObject subobjects! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection "Answer the value of currentSelection" currentSelection isNil ifTrue:[self currentSelection: nil]. ^ currentSelection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! currentSelection: anObject "Set the value of currentSelection" currentSelection _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 3/1/2010 14:12'! getClassList | prev classes | classes _ OrderedCollection new. centralClass allSuperclasses reverseDo: [:aClass | classes add: aClass]. classes add: centralClass. centralClass subclassesDo: [:aClass| classes add: aClass]. prev _nil. ^(classes collect:[:cls| prev _ ClassHierarchyExplorerWrapper with: cls name: cls name model: self parent: prev]) asArray! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:02'! initializeList self list do:[:each| self levels at: each put:0]! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levelOf: anItem ^self levels at: anItem ifAbsent:[0]! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levels "Answer the value of levels" levels isNil ifTrue:[self levels: Dictionary new]. ^ levels! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:00'! levels: anObject "Set the value of levels" levels _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:39'! list "Answer the value of list" list isNil ifTrue:[self list: (OrderedCollection with:self subject )]. ^ list! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:36'! list: anObject "Set the value of list" list _ anObject asOrderedCollection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser "Answer the value of myBrowser" myBrowser isNil ifTrue:[self myBrowser: nil]. ^ myBrowser! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:44'! myBrowser: anObject "Set the value of myBrowser" myBrowser _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems "Answer the value of openItems" openItems isNil ifTrue:[self openItems: Set new]. ^ openItems! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems: anObject "Set the value of openItems" openItems _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 13:28'! progenyOf: anObject | all | all _ (self childrenOf: anObject)copy. all isEmpty ifTrue:[^all]. all copy do:[:each| all addAll: (self progenyOf: each)]. ^all ! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:18'! selection "Answer the value of selection" selection isNil ifTrue:[self selection: nil]. ^ selection! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/9/2009 17:15'! selection: anObject "Set the value of selection" selection _ anObject . ! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 7/7/2010 12:40'! subject "Answer the value of subject" subject isNil ifTrue:[self subject: Object]. ^ subject! ! !HierarchyOutlineBrowser methodsFor: 'accessing' stamp: 'ssa 9/10/2009 08:25'! subject: anObject "Set the value of subject" subject _ anObject! ! !HierarchyOutlineBrowser methodsFor: 'user interfacing' stamp: 'ssa 3/1/2010 14:23'! openSystemCatEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers. The top list view is of the currently selected system class category--a single item list." | systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView y annotationPane underPane optionalButtonsView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" systemCategoryListView _ PluggableListView on: self list: #systemCategorySingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #systemCatSingletonMenu: keystroke: #systemCatSingletonKey:from:. systemCategoryListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: systemCategoryListView. classListView _ LyPluggableOutlineView on: self list: #getClassList selected: #currentSelection changeSelected: #currentSelection: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 67 @ 62). topView addSubView: classListView below: systemCategoryListView. messageCategoryListView _ PluggableListView on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. messageCategoryListView controller terminateDuringSelect: true. messageCategoryListView window: (0 @ 0 extent: 66 @ 70). topView addSubView: messageCategoryListView toRightOf: classListView. switchView _ self buildInstanceClassSwitchView. switchView window: switchView window viewport: (classListView viewport bottomLeft corner: messageCategoryListView viewport bottomLeft). switchView borderWidth: 1. topView addSubView: switchView below: classListView. messageListView _ PluggableListView on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageListView menuTitleSelector: #messageListSelectorTitle. messageListView window: (0 @ 0 extent: 67 @ 70). topView addSubView: messageListView toRightOf: messageCategoryListView. self wantsAnnotationPane ifTrue: [annotationPane _ PluggableTextView on: self text: #annotation accept: nil readSelection: nil menu: nil. annotationPane window: (0@0 extent: 200@self optionalAnnotationHeight). topView addSubView: annotationPane below: switchView. y _ 110 - 12 - self optionalAnnotationHeight. underPane _ annotationPane] ifFalse: [y _ 110 - 12. underPane _ switchView]. self wantsOptionalButtons ifTrue: [optionalButtonsView _ self buildOptionalButtonsView. optionalButtonsView borderWidth: 1. topView addSubView: optionalButtonsView below: underPane. underPane _ optionalButtonsView. y _ y - self optionalButtonHeight]. browserCodeView _ PluggableTextView on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. browserCodeView window: (0@0 extent: 200@y). topView addSubView: browserCodeView below: underPane. aString ifNotNil: [browserCodeView editString: aString. browserCodeView hasUnacceptedEdits: true]. topView setUpdatablePanesFrom: #(getClassList messageCategoryList messageList). ^ topView! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:42'! inspectSelection self selection inspect! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:47'! menu: aMenu aMenu add: 'inspect' action: #inspectSelection. aMenu add: 'outline' action: #outlineSelection. ^ aMenu! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:43'! outlineSelection self selection outline! ! !HierarchyOutlineBrowser methodsFor: 'menu support' stamp: 'RAA 4/7/1999 16:53'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." (self respondsTo: selector) ifTrue: [^ self perform: selector] ifFalse: [^ otherTarget perform: selector]! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 13:02'! hasChildren: anObject ^(self childrenOf: anObject) notEmpty ! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 14:07'! hideChildrenOfSelection | kids | self openItems remove: self selection. kids _ self progenyOf: self selection. kids do:[:each| self levels removeKey: each ifAbsent:[]. self openItems remove: each ifAbsent:[]]. self list removeAll: kids ifAbsent:[] ! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 11:42'! isOpen: anItem ^self openItems includes: anItem! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 12:10'! showChildrenOfSelection | kids nextLevel | self openItems add: self selection. nextLevel _ (self levelOf: self selection) + 1. kids _ self childrenOf: self selection. kids isEmpty ifTrue:[^self error:'should never try to show children of an childless object']. kids do:[:each| self levels at: each put: nextLevel]. self list addAll: kids after: self selection! ! !HierarchyOutlineBrowser methodsFor: 'opening/closing' stamp: 'ssa 9/10/2009 07:30'! toggleSelection self selection isNil ifTrue:[^self]. (self isOpen: self selection) ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !HierarchyOutlineBrowser methodsFor: 'arrow keys' stamp: 'ssa 9/9/2009 14:47'! arrowKey: aChar from: view "Process the up and down arrows in a list pane. Note that the listView tells us what index variable, how to get the list, and how to move the index. Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | (#(1 4 11 12 30 31) includes: (keyEvent _ aChar asciiValue)) ifFalse: [ ^ self]. oldSelection := view getCurrentSelectionIndex. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view numSelectionsInView. "get this exactly??" keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [self okToChange ifTrue: [view changeModelSelection: nextSelection. "view controller moveMarker"]] ! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 15:22'! genericMenu: aMenu aMenu add: 'no menu yet' target: self selector: #yourself. ^aMenu! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:44'! getCurrentSelection ^currentSelection! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:46'! noteNewSelection: x currentSelection _ x. self changed: #getCurrentSelection. currentSelection ifNil: [^self]. currentSelection sendSettingMessageTo: self. ! ! !HierarchyOutlineBrowser methodsFor: 'as yet unclassified' stamp: 'RAA 4/7/1999 16:47'! update: aSymbol aSymbol == #hierarchicalList ifTrue: [ ^self changed: #getList ]. super update: aSymbol! ! !HierarchyOutlineBrowser commentStamp: '<historical>' prior: 0! Contributed by Bob Arning as part of the ObjectExplorer package. ! !ImageReadWriter methodsFor: 'accessing'! nextImage "Dencoding an image on stream and answer the image." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'accessing'! nextPutImage: anImage "Encoding anImage on stream." ^self subclassResponsibility! ! !ImageReadWriter methodsFor: 'stream access'! atEnd ^stream atEnd! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'sd 1/30/2004 15:18'! close stream close! ! !ImageReadWriter methodsFor: 'stream access'! contents ^stream contents! ! !ImageReadWriter methodsFor: 'stream access'! cr ^stream nextPut: Character cr asInteger! ! !ImageReadWriter methodsFor: 'stream access'! lf "PPM and PBM are used LF as CR." ^stream nextPut: Character lf asInteger! ! !ImageReadWriter methodsFor: 'stream access'! next ^stream next! ! !ImageReadWriter methodsFor: 'stream access'! next: size ^stream next: size! ! !ImageReadWriter methodsFor: 'stream access'! nextLong "Read a 32-bit quantity from the input stream." ^(stream next bitShift: 24) + (stream next bitShift: 16) + (stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access'! nextLongPut: a32BitW "Write out a 32-bit integer as 32 bits." stream nextPut: ((a32BitW bitShift: -24) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -16) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a32BitW bitAnd: 16rFF). ^a32BitW! ! !ImageReadWriter methodsFor: 'stream access'! nextPut: aByte ^stream nextPut: aByte! ! !ImageReadWriter methodsFor: 'stream access'! nextPutAll: aByteArray ^stream nextPutAll: aByteArray! ! !ImageReadWriter methodsFor: 'stream access'! nextWord "Read a 16-bit quantity from the input stream." ^(stream next bitShift: 8) + stream next! ! !ImageReadWriter methodsFor: 'stream access'! nextWordPut: a16BitW "Write out a 16-bit integer as 16 bits." stream nextPut: ((a16BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a16BitW bitAnd: 16rFF). ^a16BitW! ! !ImageReadWriter methodsFor: 'stream access' stamp: 'tao 10/23/97 18:00'! peekFor: aValue ^stream peekFor: aValue! ! !ImageReadWriter methodsFor: 'stream access'! position ^stream position! ! !ImageReadWriter methodsFor: 'stream access'! position: anInteger ^stream position: anInteger! ! !ImageReadWriter methodsFor: 'stream access'! size ^stream size! ! !ImageReadWriter methodsFor: 'stream access'! skip: anInteger ^stream skip: anInteger! ! !ImageReadWriter methodsFor: 'stream access'! space ^stream nextPut: Character space asInteger! ! !ImageReadWriter methodsFor: 'stream access'! tab ^stream nextPut: Character tab asInteger! ! !ImageReadWriter methodsFor: 'private'! changePadOfBits: bits width: width height: height depth: depth from: oldPad to: newPad "Change padding size of bits." | srcRowByteSize dstRowByteSize newBits srcRowBase rowEndOffset | (#(8 16 32) includes: oldPad) ifFalse: [^self error: 'Invalid pad: ', oldPad printString]. (#(8 16 32) includes: newPad) ifFalse: [^self error: 'Invalid pad: ', newPad printString]. srcRowByteSize _ width * depth + oldPad - 1 // oldPad * (oldPad / 8). srcRowByteSize * height = bits size ifFalse: [^self error: 'Incorrect bitmap array size.']. dstRowByteSize _ width * depth + newPad - 1 // newPad * (newPad / 8). newBits _ ByteArray new: dstRowByteSize * height. srcRowBase _ 1. rowEndOffset _ dstRowByteSize - 1. 1 to: newBits size by: dstRowByteSize do: [:dstRowBase | newBits replaceFrom: dstRowBase to: dstRowBase + rowEndOffset with: bits startingAt: srcRowBase. srcRowBase _ srcRowBase + srcRowByteSize]. ^newBits! ! !ImageReadWriter methodsFor: 'private'! hasMagicNumber: aByteArray | position | position _ stream position. ((stream size - position) >= aByteArray size and: [(stream next: aByteArray size) = aByteArray]) ifTrue: [^true]. stream position: position. ^false! ! !ImageReadWriter methodsFor: 'private' stamp: 'sd 1/30/2004 15:18'! on: aStream (stream _ aStream) reset. stream binary. "Note that 'reset' makes a file be text. Must do this after."! ! !ImageReadWriter methodsFor: 'private'! unpackBits: bits depthTo8From: depth with: width height: height pad: pad "Unpack bits of depth 1, 2, or 4 image to it of depth 8 image." | bitMask pixelInByte bitsWidth upBitsWidth stopWidth trailingSize upBits bitIndex upBitIndex val | (#(1 2 4) includes: depth) ifFalse: [^self error: 'depth must be 1, 2, or 4']. (#(8 16 32) includes: pad) ifFalse: [^self error: 'pad must be 8, 16, or 32']. bitMask _ (1 bitShift: depth) - 1. pixelInByte _ 8 / depth. bitsWidth _ width * depth + pad - 1 // pad * (pad / 8). upBitsWidth _ width * 8 + pad - 1 // pad * (pad / 8). stopWidth _ width * depth + 7 // 8. trailingSize _ width - (stopWidth - 1 * pixelInByte). upBits _ ByteArray new: upBitsWidth * height. 1 to: height do: [:i | bitIndex _ i - 1 * bitsWidth. upBitIndex _ i - 1 * upBitsWidth. 1 to: stopWidth - 1 do: [:j | val _ bits at: (bitIndex _ bitIndex + 1). upBitIndex _ upBitIndex + pixelInByte. 1 to: pixelInByte do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. val _ (bits at: (bitIndex _ bitIndex + 1)) bitShift: depth negated * (pixelInByte - trailingSize). upBitIndex _ upBitIndex + trailingSize. 1 to: trailingSize do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val _ val bitShift: depth negated]]. ^ upBits ! ! !ImageReadWriter methodsFor: 'testing' stamp: 'tao 10/27/97 09:26'! understandsImageFormat "Test to see if the image stream format is understood by this decoder. This should be implemented in each subclass of ImageReadWriter so that a proper decoder can be selected without ImageReadWriter having to know about all possible image file types." ^ false! ! !ImageReadWriter commentStamp: '<historical>' prior: 0! Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved. I am an abstract class to provide for encoding and/or decoding an image on a stream. Instance Variables: stream <ReadStream | WriteStream> stream for image storages Class Variables: ImageNotStoredSignal <Signal> image not stored error signal MagicNumberErrorSignal <Signal> magic number error signal Subclasses must implement the following messages: accessing nextImage nextPutImage: testing canUnderstand (added tao 10/26/97)! !ImageReadWriter class methodsFor: 'instance creation'! on: aStream "Answer an instance of the receiver for encoding and/or decoding images on the given." ^ self new on: aStream ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:59'! allTypicalFileExtensions "Answer a collection of file extensions (lowercase) which files that my subclasses can read might commonly have" "ImageReadWriter allTypicalFileExtensions" | extensions | extensions _ Set new. self allSubclassesDo: [ :cls | extensions addAll: cls typicalFileExtensions ]. ^extensions! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ls 9/15/1998 19:08'! formFromFileNamed: fileName "Answer a ColorForm stored on the file with the given name." | stream | stream _ FileStream readOnlyFileNamed: fileName. ^self formFromStream: stream! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'tk 5/7/1998 17:35'! formFromServerFile: fileName "Answer a ColorForm stored on the file with the given name. Meant to be called from during the getting of updates from the server. That assures that (Utilities serverUrls) returns the right group of servers." | form urls doc | urls _ Utilities serverUrls collect: [:url | url, fileName]. " fileName starts with: 'updates/' " urls do: [:aURL | (fileName findTokens: '.') last asLowercase = 'gif' ifTrue: [ form _ HTTPSocket httpGif: aURL. form = (ColorForm extent: 20@20 depth: 8) ifTrue: [self inform: 'The file ',aURL,' is ill formed.']. ^ form]. (fileName findTokens: '.') last asLowercase = 'bmp' ifTrue: [ doc _ HTTPSocket httpGet: aURL accept: 'image/bmp'. form _ Form fromBMPFile: doc. doc close. form ifNil: [self inform: 'The file ',aURL,' is ill formed.'. ^ Form new] ifNotNil: [^ form]]. self inform: 'File ', fileName, 'does not end with .gif or .bmp']. self inform: 'That file not found on any server we know'.! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'sd 1/30/2004 15:18'! formFromStream: aBinaryStream "Answer a ColorForm stored on the given stream. closes the stream" | reader readerClass form | readerClass _ self withAllSubclasses detect: [:subclass | subclass understandsImageFormat: aBinaryStream] ifNone: [ aBinaryStream close. ^self error: 'image format not recognized']. reader _ readerClass new on: aBinaryStream reset. Cursor read showWhile: [ form _ reader nextImage. reader close]. ^ form ! ! !ImageReadWriter class methodsFor: 'image reading/writing'! putForm: aForm onFileNamed: fileName "Store the given form on a file of the given name." | writer | writer _ self on: (FileStream newFileNamed: fileName) binary. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'tk 9/13/97 16:13'! putForm: aForm onStream: aWriteStream "Store the given form on a file of the given name." | writer | writer _ self on: aWriteStream. Cursor write showWhile: [writer nextPutImage: aForm]. writer close. ! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:55'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#()! ! !ImageReadWriter class methodsFor: 'image reading/writing' stamp: 'ar 3/1/2006 22:59'! understandsImageFormat: aStream ^[(self new on: aStream) understandsImageFormat] on: Error do:[:ex| ex return: false]! ! !InfiniteForm methodsFor: 'accessing' stamp: 'ssa 8/28/2009 11:40'! depth ^patternForm depth! ! !InfiniteForm methodsFor: 'as yet unclassified' stamp: 'ssa 8/28/2009 11:39'! hasNonStandardPalette ^patternForm hasNonStandardPalette! ! !InputSensor methodsFor: 'mouse' stamp: 'ssa 10/27/2008 20:37'! waitClick "Wait for the user to press any mouse button and release it, then answer with the current location of the cursor." | pt | pt _ self waitButton. self waitNoButton. ^pt! ! !InputSensor methodsFor: 'user interrupts' stamp: 'sm 2/24/2011 16:44'! installInterruptWatcher "Initialize the interrupt watcher process. Terminate the old process if any." "Sensor installInterruptWatcher" InterruptWatcherProcess ifNotNil: [InterruptWatcherProcess terminate]. InterruptSemaphore _ Semaphore new. InterruptWatcherProcess _ [self userInterruptWatcher] forkAt: Processor lowIOPriority. InterruptWatcherProcess name: 'InterruptWatcher'. self primInterruptSemaphore: InterruptSemaphore. ! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionIndex: anObject "Set the value of selectionIndex" selectionIndex _ anObject! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionUpdateTime "Answer the value of selectionUpdateTime" selectionUpdateTime isNil ifTrue:[self selectionUpdateTime: nil]. ^ selectionUpdateTime! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! selectionUpdateTime: anObject "Set the value of selectionUpdateTime" selectionUpdateTime _ anObject! ! !Inspector methodsFor: 'accessing' stamp: 'ssa 8/26/2009 10:43'! timeOfLastListUpdate: anObject "Set the value of timeOfLastListUpdate" timeOfLastListUpdate _ anObject! ! !Inspector methodsFor: 'selecting' stamp: 'tk 4/10/1998 17:57'! selection "The receiver has a list of variables of its inspected object. One of these is selected. Answer the value of the selected variable." | basicIndex | selectionIndex = 0 ifTrue: [^ '']. selectionIndex = 1 ifTrue: [^ object]. selectionIndex = 2 ifTrue: [^ object longPrintString]. (selectionIndex - 2) <= object class instSize ifTrue: [^ object instVarAt: selectionIndex - 2]. basicIndex _ selectionIndex - 2 - object class instSize. (object basicSize <= (self i1 + self i2) or: [basicIndex <= self i1]) ifTrue: [^ object basicAt: basicIndex] ifFalse: [^ object basicAt: object basicSize - (self i1 + self i2) + basicIndex]! ! !Inspector methodsFor: 'selecting' stamp: 'ads 1/24/2011 13:02'! selectionPrintString | text nm | selectionUpdateTime _ [text _ [(RVMPrimitivesNeededForBootstrapping printPrefixFor: self selection),(self selection printString)] on: Error do: [nm _ self selectionIndex < 3 ifTrue: ['self'] ifFalse: [self selectedSlotName]. text _ ('<error in printString: evaluate "' , nm , ' printString" to debug>') asText. text addAttribute: TextColor red from: 1 to: text size. text]] timeToRun. ^ text! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 1/6/2010 20:21'! exploreSelection "Open an explorer on the receiver's model's currently selected object." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ^ self selection explore! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 7/7/2010 13:04'! fieldListMenu: aMenu "Arm the supplied menu with items for the field-list of the receiver" aMenu addList: #( ('inspect (i)' inspectSelection) ('explore (e)' exploreSelection) ('locate' locateSelection)). self addCollectionItemsTo: aMenu. aMenu addList: #( - ('method refs to this inst var' referencesToSelection) ('methods storing into this inst var' defsOfSelection) ('objects pointing to this value' objectReferencesToSelection) ('chase pointers' chasePointers) - ('browse full (b)' browseMethodFull) ('browse class' browseClass) ('browse hierarchy' classHierarchy) ('browse protocol (p)' browseFullProtocol) - ('inst var refs...' browseInstVarRefs) ('inst var defs...' browseInstVarDefs) ('class var refs...' classVarRefs) ('class variables' browseClassVariables) ('class refs (N)' browseClassRefs) - ('copy name (c)' copyName) ('basic inspect' inspectBasic)). ^ aMenu " - ('alias for this value' aliasForValue) ('watcher for this slot' watcherForSlot)" ! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 7/7/2010 13:04'! inspectorKey: aChar from: view "Respond to a Command key issued while the cursor is over my field list" aChar == $i ifTrue: [^ self selection inspect]. aChar == $e ifTrue: [^ self selection explore]. aChar == $b ifTrue: [^ self browseMethodFull]. aChar == $h ifTrue: [^ self classHierarchy]. aChar == $c ifTrue: [^ self copyName]. aChar == $p ifTrue: [^ self browseFullProtocol]. aChar == $N ifTrue: [^ self browseClassRefs]. "aChar == $t ifTrue: [^ self tearOffTile]." aChar == $v ifTrue: [^ self viewerForValue]. ^ self arrowKey: aChar from: view! ! !Inspector methodsFor: 'menu commands' stamp: 'ssa 11/16/2008 01:53'! locateSelection "Open a locator on the receiver's model's currently selected object." self selectionIndex = 0 ifTrue: [^ self changed: #flash]. ^ self selection locate! ! !Inspector class methodsFor: 'instance creation' stamp: 'ssa 8/26/2009 11:23'! newFrom: anInspector "Use anInspector's contents for that of a new instance of me" | in | in _ self new. in contents: anInspector contents. in myDependents: anInspector myDependents. in dependents do:[:each| (each respondsTo:#model:) ifTrue:[each model: in]]. in selectionIndex: anInspector selectionIndex. in timeOfLastListUpdate: anInspector timeOfLastListUpdate. in selectionUpdateTime: anInspector selectionUpdateTime. in object: anInspector object. ^in! ! !Inspector class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:43'! openOn: anObject withEvalPane: withEval withLabel: label valueViewClass: valueViewClass | topView inspector listView valueView evalView v | inspector _ self inspect: anObject. topView _ StandardSystemView new model: inspector. topView borderWidth: 1. listView _ PluggableListView on: inspector list: #fieldList selected: #selectionIndex changeSelected: #toggleIndex: menu: #fieldListMenu: keystroke: #inspectorKey:from:. (inspector isMemberOf: DictionaryInspector) ifTrue: [listView menu: #dictionaryMenu:]. listView window: (0 @ 0 extent: 40 @ 40). topView addSubView: listView. valueView _ valueViewClass new. "PluggableTextView or PluggableFormView" (valueView respondsTo: #getText) ifTrue: [ valueView on: inspector text: #contents accept: #accept: readSelection: #contentsSelection menu: #codePaneMenu:shifted:]. (valueViewClass inheritsFrom: FormView) ifTrue: [ valueView model: inspector]. v_ "MSWScrollBarView on:" valueView. v window: (0 @ 0 extent: 75 @ 40). topView addSubView: v toRightOf: listView. withEval ifTrue: [evalView _ PluggableTextView new on: inspector text: #trash accept: #trash: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. evalView window: (0 @ 0 extent: 115 @ 20). evalView askBeforeDiscardingEdits: false. topView addSubView: evalView below: listView]. topView label: label. topView minimumSize: 180 @ 120. topView setUpdatablePanesFrom: #(fieldList). topView controller open! ! !InstructionStream methodsFor: 'scanning' stamp: 'ssa 5/11/2010 16:14'! skipBackBeforeJump "Assuming that the receiver is positioned jast after a jump, skip back one or two bytes, depending on the size of the previous jump instruction." | strm short | strm _ InstructionStream on: self method. (strm scanFor: [:byte | ((short _ byte between: 152 and: 159) or: [byte between: 168 and: 175]) and: [strm pc = (short ifTrue: [pc-1] ifFalse: [pc-2])]]) ifFalse: [self error: 'Where''s the jump??'. self jump: 0]. self jump: (short ifTrue: [-1] ifFalse: [-2]). ! ! !Integer methodsFor: 'truncation and round off' stamp: 'ssa 11/27/2009 16:44'! atRandom "Answer a random integer from 1 to self. This implementation uses a shared generator. Heavy users should their own implementation or use Interval>atRandom: directly." self = 0 ifTrue: [ ^0 ]. self < 0 ifTrue: [ ^self negated atRandom negated ]. ^self atRandom: Collection randomForPicking ! ! !Integer methodsFor: 'printing' stamp: 'ar 7/18/2001 22:09'! asStringWithCommasSigned "123456789 asStringWithCommasSigned" "-123456789 asStringWithCommasSigned" | digits | digits _ self abs printString. ^ String streamContents: [:strm | self sign = -1 ifTrue: [strm nextPut: $-] ifFalse:[strm nextPut: $+]. 1 to: digits size do: [:i | strm nextPut: (digits at: i). (i < digits size and: [(i - digits size) \\ 3 = 0]) ifTrue: [strm nextPut: $,]]]! ! !Integer methodsFor: 'printing' stamp: 'ssa 8/26/2009 12:23'! printeth "1 printeth '1st'" "2 printeth '2nd'" "3 printeth '3rd'" "4 printeth '4th'" "5 printeth '5th'" "1234 printeth '1234th'" "121 printeth '121st'" | str suffix | str _ self printString. suffix _ (#('st' 'nd' 'rd' 'th')at: ((str last asNumber max:1) min:4)). ^str,suffix! ! !Integer methodsFor: 'explorer' stamp: 'ssa 7/7/2010 21:07'! hasContentsInExplorer ^false! ! !Integer methodsFor: '*RVM-benchmarks' stamp: 'dmu 1/1/1970 00:40'! tinyRVMBenchmarks "Report the results of running the two tiny Squeak benchmarks. ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results" "0 tinyBenchmarks" "On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec" "On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec" | t1 t2 r n1 n2 s1 s2 totalYields | n1 _ 1. s1 _ RVMMulticoreSample capture. [t1 _ Time millisecondsToRun: [n1 benchmark]. t1 < 1000] whileTrue:[n1 _ n1 * 2]. "Note: #benchmark's runtime is about O(n)" n2 _ 28. [t2 _ Time millisecondsToRun: [r _ n2 benchFib]. t2 < 1000] whileTrue:[n2 _ n2 + 1]. "Note: #benchFib's runtime is about O(k^n), where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...." s2 _ RVMMulticoreSample capture. totalYields _ s2 totalYields. ^ ((n1 * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', ((r * 1000) // t2) printString, ' sends/sec; ', totalYields printString, ' total yields; ', (t1 + t2) printString, ' total ms'! ! !Integer methodsFor: '*Ly-Explorer' stamp: 'laza 3/17/2005 13:37'! explorerContents ^{ 'hexadecimal' -> 16. 'octal' -> 8. 'binary' -> 2 } collect: [:each | ObjectExplorerWrapper with: each key translated name: (self printStringBase: each value) model: self]! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:21'! acTableIndex ^acTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:20'! acTableIndex: anInteger acTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:21'! dcTableIndex ^dcTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:20'! dcTableIndex: anInteger dcTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! heightInBlocks ^heightInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:10'! heightInBlocks: anInteger heightInBlocks _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:09'! id ^id! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:09'! id: anObject id _ anObject! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'ar 3/4/2001 01:19'! mcuWidth: mw mcuHeight: mh dctSize: ds mcuWidth _ mw. mcuHeight _ mh. dctSize _ ds. hSampleFactor _ mcuWidth // widthInBlocks. vSampleFactor _ mcuHeight // heightInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:15'! priorDCValue: aNumber priorDCValue _ aNumber! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:43'! qTableIndex ^qTableIndex! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! qTableIndex: anInteger qTableIndex _ anInteger! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:18'! totalMcuBlocks ^ heightInBlocks * widthInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:16'! updateDCValue: aNumber priorDCValue _ priorDCValue + aNumber. ^priorDCValue! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:11'! widthInBlocks ^widthInBlocks! ! !JPEGColorComponent methodsFor: 'accessing' stamp: 'tao 10/23/97 12:10'! widthInBlocks: anInteger widthInBlocks _ anInteger! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'tao 10/23/97 12:24'! initializeSampleStreamBlocks: aCollection mcuBlocks _ aCollection. self resetSampleStream! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'ar 3/4/2001 22:16'! nextSample | dx dy blockIndex sampleIndex sample | dx _ currentX // hSampleFactor. dy _ currentY // vSampleFactor. blockIndex _ dy // dctSize * widthInBlocks + (dx // dctSize) + 1. sampleIndex _ dy \\ dctSize * dctSize + (dx \\ dctSize) + 1. sample _ (mcuBlocks at: blockIndex) at: sampleIndex. currentX _ currentX + 1. currentX < (mcuWidth * dctSize) ifFalse: [currentX _ 0. currentY _ currentY + 1]. ^ sample! ! !JPEGColorComponent methodsFor: 'sample streaming' stamp: 'tao 10/23/97 12:24'! resetSampleStream currentX _ 0. currentY _ 0! ! !JPEGColorComponent commentStamp: '<historical>' prior: 0! I represent a single component of color in JPEG YCbCr color space. I can accept a list of blocks in my component from the current MCU, then stream the samples from this block for use in color conversion. I also store the running DC sample value for my component, used by the Huffman decoder. The following layout is fixed for the JPEG primitives to work: currentX <SmallInteger> currentY <SmallInteger> hSampleFactor <SmallInteger> vSampleFactor <SmallInteger> mcuBlocks <Array of: <IntegerArray of: DCTSize2 * Integer>> widthInBlocks <SmallInteger> heightInBlocks <SmallInteger> dctSize <SmallInteger> mcuWidth <SmallInteger> mcuHeight <SmallInteger> priorDCValue <SmallInteger> ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/20/97 14:27'! bits: anObject bits _ anObject! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:31'! lookaheadBits ^lookaheadBits! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:38'! lookaheadSymbol ^lookaheadSymbol! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/21/97 23:59'! maxcode ^maxcode! ! !JPEGHuffmanTable methodsFor: 'accessing' stamp: 'tao 10/20/97 14:27'! values: anObject values _ anObject! ! !JPEGHuffmanTable methodsFor: 'computation' stamp: 'tao 10/24/97 12:28'! makeDerivedTables | huffSize huffCode code si index lookbits | mincode _ Array new: 16. maxcode _ Array new: 17. valptr _ Array new: 17. huffSize _ OrderedCollection new. 1 to: 16 do: [:l | 1 to: (bits at: l) do: [:i | huffSize add: l]]. huffSize add: 0. code _ 0. huffCode _ Array new: huffSize size. si _ huffSize at: 1. index _ 1. [(huffSize at: index) ~= 0] whileTrue: [[(huffSize at: index) = si] whileTrue: [huffCode at: index put: code. index _ index + 1. code _ code + 1]. code _ code << 1. si _ si + 1]. index _ 1. 1 to: 16 do: [:l | (bits at: l) ~= 0 ifTrue: [valptr at: l put: index. mincode at: l put: (huffCode at: index). index _ index + (bits at: l). maxcode at: l put: (huffCode at: index-1)] ifFalse: [maxcode at: l put: -1]]. maxcode at: 17 put: 16rFFFFF. lookaheadBits _ (Array new: 1 << Lookahead) atAllPut: 0. lookaheadSymbol _ Array new: 1 << Lookahead. index _ 1. 1 to: Lookahead do: [:l | 1 to: (bits at: l) do: [:i | lookbits _ (huffCode at: index) << (Lookahead - l) + 1. (1 << (Lookahead - l) to: 1 by: -1) do: [:ctr | lookaheadBits at: lookbits put: l. lookaheadSymbol at: lookbits put: (values at: index). lookbits _ lookbits + 1]. index _ index + 1]]! ! !JPEGHuffmanTable methodsFor: 'computation' stamp: 'tao 10/21/97 22:44'! valueForCode: code length: length ^ values at: ((valptr at: length) + code - (mincode at: length))! ! !JPEGHuffmanTable commentStamp: '<historical>' prior: 0! I represent the table of values used to decode Huffman entropy-encoded bitstreams. From the JFIF file header entropy values, I build a derived table of codes and values for faster decoding.! !JPEGHuffmanTable class methodsFor: 'constants' stamp: 'tao 10/21/97 22:15'! lookahead ^ Lookahead! ! !JPEGHuffmanTable class methodsFor: 'initialization' stamp: 'tao 10/21/97 11:06'! initialize Lookahead _ 8. BitBufferSize _ 16! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 20:42'! fillBuffer | byte | [bitsInBuffer <= 16] whileTrue:[ byte _ self next. (byte = 16rFF and: [(self peekFor: 16r00) not]) ifTrue: [self position: self position - 1. ^0]. bitBuffer _ (bitBuffer bitShift: 8) bitOr: byte. bitsInBuffer _ bitsInBuffer + 8]. ^ bitsInBuffer! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 18:43'! getBits: requestedBits | value | requestedBits > bitsInBuffer ifTrue:[ self fillBuffer. requestedBits > bitsInBuffer ifTrue:[ self error: 'not enough bits available to decode']]. value _ bitBuffer bitShift: (requestedBits - bitsInBuffer). bitBuffer _ bitBuffer bitAnd: (1 bitShift: (bitsInBuffer - requestedBits)) -1. bitsInBuffer _ bitsInBuffer - requestedBits. ^ value! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/6/2001 12:34'! nextByte ^self next asInteger! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/6/2001 12:35'! nextBytes: n ^(self next: n) asByteArray! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 17:40'! reset super reset. self resetBitBuffer! ! !JPEGReadStream methodsFor: 'accessing' stamp: 'ar 3/4/2001 18:44'! resetBitBuffer bitBuffer _ 0. bitsInBuffer _ 0. ! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 21:06'! buildLookupTable: values counts: counts | min max | min _ max _ nil. 1 to: counts size do:[:i| (counts at: i) = 0 ifFalse:[ min ifNil:[min _ i-1]. max _ i]]. ^self createHuffmanTables: values counts: {0},counts from: min+1 to: max.! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:46'! createHuffmanTables: values counts: counts from: minBits to: maxBits "Create the actual tables" | table tableStart tableSize tableEnd valueIndex tableStack numValues deltaBits maxEntries lastTable lastTableStart tableIndex lastTableIndex | table _ WordArray new: ((4 bitShift: minBits) max: 16). "Create the first entry - this is a dummy. It gives us information about how many bits to fetch initially." table at: 1 put: (minBits bitShift: 24) + 2. "First actual table starts at index 2" "Create the first table from scratch." tableStart _ 2. "See above" tableSize _ 1 bitShift: minBits. tableEnd _ tableStart + tableSize. "Store the terminal symbols" valueIndex _ (counts at: minBits+1). tableIndex _ 0. 1 to: valueIndex do:[:i| table at: tableStart + tableIndex put: (values at: i). tableIndex _ tableIndex + 1]. "Fill up remaining entries with invalid entries" tableStack _ OrderedCollection new: 10. "Should be more than enough" tableStack addLast: (Array with: minBits "Number of bits (e.g., depth) for this table" with: tableStart "Start of table" with: tableIndex "Next index in table" with: minBits "Number of delta bits encoded in table" with: tableSize - valueIndex "Entries remaining in table"). "Go to next value index" valueIndex _ valueIndex + 1. "Walk over remaining bit lengths and create new subtables" minBits+1 to: maxBits do:[:bits| numValues _ counts at: bits+1. [numValues > 0] whileTrue:["Create a new subtable" lastTable _ tableStack last. lastTableStart _ lastTable at: 2. lastTableIndex _ lastTable at: 3. deltaBits _ bits - (lastTable at: 1). "Make up a table of deltaBits size" tableSize _ 1 bitShift: deltaBits. tableStart _ tableEnd. tableEnd _ tableEnd + tableSize. [tableEnd > table size ] whileTrue:[table _ self growHuffmanTable: table]. "Connect to last table" self assert:[(table at: lastTableStart + lastTableIndex) = 0]."Entry must be unused" table at: lastTableStart + lastTableIndex put: (deltaBits bitShift: 24) + tableStart. lastTable at: 3 put: lastTableIndex+1. lastTable at: 5 put: (lastTable at: 5) - 1. self assert:[(lastTable at: 5) >= 0]. "Don't exceed tableSize" "Store terminal values" maxEntries _ numValues min: tableSize. tableIndex _ 0. 1 to: maxEntries do:[:i| table at: tableStart + tableIndex put: (values at: valueIndex). valueIndex _ valueIndex + 1. numValues _ numValues - 1. tableIndex _ tableIndex+1]. "Check if we have filled up the current table completely" maxEntries = tableSize ifTrue:[ "Table has been filled. Back up to the last table with space left." [tableStack isEmpty not and:[(tableStack last at: 5) = 0]] whileTrue:[tableStack removeLast]. ] ifFalse:[ "Table not yet filled. Put it back on the stack." tableStack addLast: (Array with: bits "Nr. of bits in this table" with: tableStart "Start of table" with: tableIndex "Index in table" with: deltaBits "delta bits of table" with: tableSize - maxEntries "Unused entries in table"). ]. ]. ]. ^table copyFrom: 1 to: tableEnd-1! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:44'! decodeValueFrom: table "Decode the next value in the receiver using the given huffman table." | bits bitsNeeded tableIndex value | bitsNeeded _ (table at: 1) bitShift: -24. "Initial bits needed" tableIndex _ 2. "First real table" [bits _ self getBits: bitsNeeded. "Get bits" value _ table at: (tableIndex + bits). "Lookup entry in table" (value bitAnd: 16r3F000000) = 0] "Check if it is a non-leaf node" whileFalse:["Fetch sub table" tableIndex _ value bitAnd: 16rFFFF. "Table offset in low 16 bit" bitsNeeded _ (value bitShift: -24) bitAnd: 255. "Additional bits in high 8 bit" bitsNeeded > MaxBits ifTrue:[^self error:'Invalid huffman table entry']]. ^value! ! !JPEGReadStream methodsFor: 'huffman trees' stamp: 'ar 3/4/2001 18:21'! growHuffmanTable: table | newTable | newTable _ table species new: table size * 2. newTable replaceFrom: 1 to: table size with: table startingAt: 1. ^newTable! ! !JPEGReadStream commentStamp: '<historical>' prior: 0! Encapsulates huffman encoded access to JPEG data. The following layout is fixed for the JPEG primitives to work: collection <ByteArray | String> position <SmallInteger> readLimit <SmallInteger> bitBuffer <SmallInteger> bitsInBuffer <SmallInteger>! !JPEGReadStream class methodsFor: 'class initialization' stamp: 'ar 3/4/2001 18:32'! initialize "JPEGReadStream initialize" MaxBits _ 16.! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 13:46'! hACTable hACTable ifNil: [hACTable _ Array new: HuffmanTableSize]. ^ hACTable! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 13:46'! hDCTable hDCTable ifNil: [hDCTable _ Array new: HuffmanTableSize]. ^ hDCTable! ! !JPEGReadWriter methodsFor: 'accessing' stamp: 'tao 10/19/97 08:46'! qTable qTable ifNil: [qTable _ Array new: QuantizationTableSize]. ^ qTable! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:18'! colorConvertFloatYCbCrMCU | ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits | ySampleStream _ currentComponents at: 1. cbSampleStream _ currentComponents at: 2. crSampleStream _ currentComponents at: 3. ySampleStream resetSampleStream. cbSampleStream resetSampleStream. crSampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ ySampleStream nextSample. cb _ cbSampleStream nextSample - FloatSampleOffset. cr _ crSampleStream nextSample - FloatSampleOffset. red _ self sampleFloatRangeLimit: (y + (1.40200 * cr)). green _ self sampleFloatRangeLimit: (y - (0.34414 * cb) - (0.71414 * cr)). blue _ self sampleFloatRangeLimit: (y + (1.77200 * cb)). bits at: i put: 16rFF000000 + (red << 16) + (green << 8) + blue]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:17'! colorConvertGrayscaleMCU | ySampleStream y bits | ySampleStream _ currentComponents at: 1. ySampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ (ySampleStream nextSample) + (residuals at: 2). y > MaxSample ifTrue: [y _ MaxSample]. residuals at: 2 put: (y bitAnd: ditherMask). y _ y bitAnd: MaxSample - ditherMask. y < 1 ifTrue: [y _ 1]. bits at: i put: 16rFF000000 + (y<<16) + (y<<8) + y]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:18'! colorConvertIntYCbCrMCU | ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits | ySampleStream _ currentComponents at: 1. cbSampleStream _ currentComponents at: 2. crSampleStream _ currentComponents at: 3. ySampleStream resetSampleStream. cbSampleStream resetSampleStream. crSampleStream resetSampleStream. bits _ mcuImageBuffer bits. 1 to: bits size do: [:i | y _ ySampleStream nextSample. cb _ cbSampleStream nextSample - SampleOffset. cr _ crSampleStream nextSample - SampleOffset. red _ y + ((FIXn1n40200 * cr) // 65536) + (residuals at: 1). red > MaxSample ifTrue: [red _ MaxSample] ifFalse: [red < 0 ifTrue: [red _ 0]]. residuals at: 1 put: (red bitAnd: ditherMask). red _ red bitAnd: MaxSample - ditherMask. red < 1 ifTrue: [red _ 1]. green _ y - ((FIXn0n34414 * cb) // 65536) - ((FIXn0n71414 * cr) // 65536) + (residuals at: 2). green > MaxSample ifTrue: [green _ MaxSample] ifFalse: [green < 0 ifTrue: [green _ 0]]. residuals at: 2 put: (green bitAnd: ditherMask). green _ green bitAnd: MaxSample - ditherMask. green < 1 ifTrue: [green _ 1]. blue _ y + ((FIXn1n77200 * cb) // 65536) + (residuals at: 3). blue > MaxSample ifTrue: [blue _ MaxSample] ifFalse: [blue < 0 ifTrue: [blue _ 0]]. residuals at: 3 put: (blue bitAnd: ditherMask). blue _ blue bitAnd: MaxSample - ditherMask. blue < 1 ifTrue: [blue _ 1]. bits at: i put: 16rFF000000 + (red bitShift: 16) + (green bitShift: 8) + blue]. ! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/7/2001 01:02'! colorConvertMCU ^ currentComponents size = 3 ifTrue: [self useFloatingPoint ifTrue: [self colorConvertFloatYCbCrMCU] ifFalse: [self primColorConvertYCbCrMCU: currentComponents bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.]] ifFalse: [self primColorConvertGrayscaleMCU]! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 22:19'! primColorConvertGrayscaleMCU self primColorConvertGrayscaleMCU: (currentComponents at: 1) bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/15/2001 18:11'! primColorConvertGrayscaleMCU: componentArray bits: bits residuals: residualArray ditherMask: mask <primitive: 'primitiveColorConvertGrayscaleMCU' module: 'JPEGReaderPlugin'> "JPEGReaderPlugin doPrimitive: #primitiveColorConvertGrayscaleMCU." ^self colorConvertGrayscaleMCU! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 21:36'! primColorConvertIntYCbCrMCU self primColorConvertYCbCrMCU: currentComponents bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/4/2001 21:36'! primColorConvertYCbCrMCU: componentArray bits: bits residuals: residualArray ditherMask: mask <primitive: 'primitiveColorConvertMCU' module: 'JPEGReaderPlugin'> ^self colorConvertIntYCbCrMCU! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'tao 10/26/97 15:43'! sampleFloatRangeLimit: aNumber ^ (aNumber rounded max: 0) min: MaxSample! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'di 9/15/1998 14:30'! sampleRangeLimit: aNumber aNumber < 0 ifTrue: [^ 0]. aNumber > MaxSample ifTrue: [^ MaxSample]. ^ aNumber! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 15:16'! dctFloatRangeLimit: value ^ (value / 8.0) + FloatSampleOffset.! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 16:34'! idctBlockFloat: anArray component: aColorComponent | t0 t1 t2 t3 t4 t5 t6 t7 t10 t11 t12 t13 z5 z10 z11 z12 z13 qt ws | qt _ self qTable at: (aColorComponent qTableIndex). ws _ Array new: DCTSize2. "Pass 1: process columns from input, store into work array" 1 to: DCTSize do: [:i | t0 _ (anArray at: i) * (qt at: i). t1 _ (anArray at: (DCTSize*2 + i)) * (qt at: (DCTSize*2 + i)). t2 _ (anArray at: (DCTSize*4 + i)) * (qt at: (DCTSize*4 + i)). t3 _ (anArray at: (DCTSize*6 + i)) * (qt at: (DCTSize*6 + i)). t10 _ t0 + t2. t11 _ t0 - t2. t13 _ t1 + t3. t12 _ (t1 - t3) * DCTK1 - t13. t0 _ t10 + t13. t3 _ t10 - t13. t1 _ t11 + t12. t2 _ t11 - t12. t4 _ (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)). t5 _ (anArray at: (DCTSize*3 + i)) * (qt at: (DCTSize*3 + i)). t6 _ (anArray at: (DCTSize*5 + i)) * (qt at: (DCTSize*5 + i)). t7 _ (anArray at: (DCTSize*7 + i)) * (qt at: (DCTSize*7 + i)). z13 _ t6 + t5. z10 _ t6 - t5. z11 _ t4 + t7. z12 _ t4 - t7. t7 _ z11 + z13. t11 _ (z11 - z13) * DCTK1. z5 _ (z10 + z12) * DCTK2. t10 _ DCTK3 * z12 - z5. t12 _ DCTK4 * z10 + z5. t6 _ t12 - t7. t5 _ t11 - t6. t4 _ t10 + t5. ws at: i put: t0 + t7. ws at: (DCTSize*7 + i) put: t0 - t7. ws at: (DCTSize + i) put: t1 + t6. ws at: (DCTSize*6 + i) put: t1 - t6. ws at: (DCTSize*2 + i) put: t2 + t5. ws at: (DCTSize*5 + i) put: t2 - t5. ws at: (DCTSize*4 + i) put: t3 + t4. ws at: (DCTSize*3 + i) put: t3 - t4]. "Pass 2: process rows from the workspace" (0 to: DCTSize2-DCTSize by: DCTSize) do: [:i | t10 _ (ws at: (i+1)) + (ws at: (i+5)). t11 _ (ws at: (i+1)) - (ws at: (i+5)). t13 _ (ws at: (i+3)) + (ws at: (i+7)). t12 _ ((ws at: (i+3)) - (ws at: (i+7))) * DCTK1 - t13. t0 _ t10 + t13. t3 _ t10 - t13. t1 _ t11 + t12. t2 _ t11 - t12. z13 _ (ws at: (i+6)) + (ws at: (i+4)). z10 _ (ws at: (i+6)) - (ws at: (i+4)). z11 _ (ws at: (i+2)) + (ws at: (i+8)). z12 _ (ws at: (i+2)) - (ws at: (i+8)). t7 _ z11 + z13. t11 _ (z11 - z13) * DCTK1. z5 _ (z10 + z12) * DCTK2. t10 _ DCTK3 * z12 - z5. t12 _ DCTK4 * z10 + z5. t6 _ t12 - t7. t5 _ t11 - t6. t4 _ t10 + t5. "final output stage: scale down by a factor of 8 and range-limit" anArray at: (i+1) put: (self dctFloatRangeLimit: (t0 + t7)). anArray at: (i+8) put: (self dctFloatRangeLimit: (t0 - t7)). anArray at: (i+2) put: (self dctFloatRangeLimit: (t1 + t6)). anArray at: (i+7) put: (self dctFloatRangeLimit: (t1 - t6)). anArray at: (i+3) put: (self dctFloatRangeLimit: (t2 + t5)). anArray at: (i+6) put: (self dctFloatRangeLimit: (t2 - t5)). anArray at: (i+5) put: (self dctFloatRangeLimit: (t3 + t4)). anArray at: (i+4) put: (self dctFloatRangeLimit: (t3 - t4))] ! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:35'! idctBlockInt: anArray component: aColorComponent ^self idctBlockInt: anArray qt: (self qTable at: aColorComponent qTableIndex)! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:34'! idctBlockInt: anArray qt: qt | ws anACTerm dcval z1 z2 z3 z4 z5 t0 t1 t2 t3 t10 t11 t12 t13 shift | ws _ Array new: DCTSize2. "Pass 1: process columns from anArray, store into work array" shift _ 1 bitShift: ConstBits - Pass1Bits. 1 to: DCTSize do: [:i | anACTerm _ nil. 1 to: DCTSize-1 do:[:row| anACTerm ifNil:[ (anArray at: row * DCTSize + i) = 0 ifFalse:[anACTerm _ row]]]. anACTerm == nil ifTrue: [dcval _ (anArray at: i) * (qt at: 1) bitShift: Pass1Bits. 0 to: DCTSize-1 do: [:j | ws at: (j * DCTSize + i) put: dcval]] ifFalse: [z2 _ (anArray at: (DCTSize * 2 + i)) * (qt at: (DCTSize * 2 + i)). z3 _ (anArray at: (DCTSize * 6 + i)) * (qt at: (DCTSize * 6 + i)). z1 _ (z2 + z3) * FIXn0n541196100. t2 _ z1 + (z3 * FIXn1n847759065 negated). t3 _ z1 + (z2 * FIXn0n765366865). z2 _ (anArray at: i) * (qt at: i). z3 _ (anArray at: (DCTSize * 4 + i)) * (qt at: (DCTSize * 4 + i)). t0 _ (z2 + z3) bitShift: ConstBits. t1 _ (z2 - z3) bitShift: ConstBits. t10 _ t0 + t3. t13 _ t0 - t3. t11 _ t1 + t2. t12 _ t1 - t2. t0 _ (anArray at: (DCTSize * 7 + i)) * (qt at: (DCTSize * 7 + i)). t1 _ (anArray at: (DCTSize * 5 + i)) * (qt at: (DCTSize * 5 + i)). t2 _ (anArray at: (DCTSize * 3 + i)) * (qt at: (DCTSize * 3 + i)). t3 _ (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)). z1 _ t0 + t3. z2 _ t1 + t2. z3 _ t0 + t2. z4 _ t1 + t3. z5 _ (z3 + z4) * FIXn1n175875602. t0 _ t0 * FIXn0n298631336. t1 _ t1 * FIXn2n053119869. t2 _ t2 * FIXn3n072711026. t3 _ t3 * FIXn1n501321110. z1 _ z1 * FIXn0n899976223 negated. z2 _ z2 * FIXn2n562915447 negated. z3 _ z3 * FIXn1n961570560 negated. z4 _ z4 * FIXn0n390180644 negated. z3 _ z3 + z5. z4 _ z4 + z5. t0 _ t0 + z1 + z3. t1 _ t1 +z2 +z4. t2 _ t2 + z2 + z3. t3 _ t3 + z1 + z4. ws at: i put: (t10 + t3) >> (ConstBits - Pass1Bits). ws at: (DCTSize * 7 + i) put: (t10 - t3) // shift. ws at: (DCTSize * 1 + i) put: (t11 + t2) // shift. ws at: (DCTSize * 6 + i) put: (t11 - t2) // shift. ws at: (DCTSize * 2 + i) put: (t12 + t1) // shift. ws at: (DCTSize * 5 + i) put: (t12 - t1) // shift. ws at: (DCTSize * 3 + i) put: (t13 + t0) // shift. ws at: (DCTSize * 4 + i) put: (t13 - t0) // shift]]. "Pass 2: process rows from work array, store back into anArray" shift _ 1 bitShift: ConstBits + Pass1Bits + 3. 0 to: DCTSize2-DCTSize by: DCTSize do: [:i | z2 _ ws at: i + 3. z3 _ ws at: i + 7. z1 _ (z2 + z3) * FIXn0n541196100. t2 _ z1 + (z3 * FIXn1n847759065 negated). t3 _ z1 + (z2 * FIXn0n765366865). t0 _ (ws at: (i + 1)) + (ws at: (i + 5)) bitShift: ConstBits. t1 _ (ws at: (i + 1)) - (ws at: (i + 5)) bitShift: ConstBits. t10 _ t0 + t3. t13 _ t0 - t3. t11 _ t1 + t2. t12 _ t1 -t2. t0 _ ws at: (i + 8). t1 _ ws at: (i + 6). t2 _ ws at: (i + 4). t3 _ ws at: (i + 2). z1 _ t0 + t3. z2 _ t1 + t2. z3 _ t0 + t2. z4 _ t1 + t3. z5 _ (z3 + z4) * FIXn1n175875602. t0 _ t0 * FIXn0n298631336. t1 _ t1 * FIXn2n053119869. t2 _ t2 * FIXn3n072711026. t3 _ t3 * FIXn1n501321110. z1 _ z1 * FIXn0n899976223 negated. z2 _ z2 * FIXn2n562915447 negated. z3 _ z3 * FIXn1n961570560 negated. z4 _ z4 * FIXn0n390180644 negated. z3 _ z3 + z5. z4 _ z4 + z5. t0 _ t0 + z1 + z3. t1 _ t1 + z2 + z4. t2 _ t2 + z2 + z3. t3 _ t3 + z1 + z4. anArray at: (i + 1) put: (self sampleRangeLimit: (t10 + t3) // shift + SampleOffset). anArray at: (i + 8) put: (self sampleRangeLimit: (t10 - t3) // shift + SampleOffset). anArray at: (i + 2) put: (self sampleRangeLimit: (t11 + t2) // shift + SampleOffset). anArray at: (i + 7) put: (self sampleRangeLimit: (t11 - t2) // shift + SampleOffset). anArray at: (i + 3) put: (self sampleRangeLimit: (t12 + t1) // shift + SampleOffset). anArray at: (i + 6) put: (self sampleRangeLimit: (t12 - t1) // shift + SampleOffset). anArray at: (i + 4) put: (self sampleRangeLimit: (t13 + t0) // shift + SampleOffset). anArray at: (i + 5) put: (self sampleRangeLimit: (t13 - t0) // shift + SampleOffset)]. ! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/7/2001 00:58'! idctMCU | comp fp ci | fp _ self useFloatingPoint. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. fp ifTrue:[ self idctBlockFloat: (mcuSampleBuffer at: i) component: comp. ] ifFalse:[ self primIdctInt: (mcuSampleBuffer at: i) qt: (qTable at: comp qTableIndex)]].! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:37'! primIdctBlockInt: anArray component: aColorComponent ^self primIdctInt: anArray qt: (self qTable at: aColorComponent qTableIndex)! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/4/2001 21:35'! primIdctInt: anArray qt: qt <primitive: 'primitiveIdctInt' module: 'JPEGReaderPlugin'> ^self idctBlockInt: anArray qt: qt! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'tao 10/26/97 16:16'! scaleQuantizationTable: table | index | index _ 1. 1 to: DCTSize do: [:row | 1 to: DCTSize do: [:col | table at: index put: ((table at: index) * (QTableScaleFactor at: row) * (QTableScaleFactor at: col)) rounded. index _ index + 1]]. ^ table ! ! !JPEGReadWriter methodsFor: 'error handling' stamp: 'tao 10/19/97 12:25'! notSupported: aString self error: aString , ' is not currently supported'! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 20:55'! decodeBlockInto: anArray component: aColorComponent dcTable: huffmanDC acTable: huffmanAC | byte i zeroCount | byte _ stream decodeValueFrom: huffmanDC. byte ~= 0 ifTrue: [byte _ self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte]. byte _ aColorComponent updateDCValue: byte. anArray atAllPut: 0. anArray at: 1 put: byte. i _ 2. [i <= DCTSize2] whileTrue: [byte _ stream decodeValueFrom: huffmanAC. zeroCount _ byte >> 4. byte _ byte bitAnd: 16r0F. byte ~= 0 ifTrue: [i _ i + zeroCount. byte _ self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte. anArray at: (JPEGNaturalOrder at: i) put: byte] ifFalse: [zeroCount = 15 ifTrue: [i _ i + zeroCount] ifFalse: [^ self]]. i _ i + 1] ! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/7/2001 01:00'! decodeMCU | comp ci | (restartInterval ~= 0 and: [restartsToGo = 0]) ifTrue: [self processRestart]. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. self primDecodeBlockInto: (mcuSampleBuffer at: i) component: comp dcTable: (hDCTable at: comp dcTableIndex) acTable: (hACTable at: comp acTableIndex) stream: stream. ]. restartsToGo _ restartsToGo - 1.! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 17:27'! getBits: requestedBits ^stream getBits: requestedBits! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 21:32'! primDecodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable stream: jpegStream <primitive: 'primitiveDecodeMCU' module: 'JPEGReaderPlugin'> ^self decodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 17:40'! processRestart stream resetBitBuffer. self parseNextMarker. currentComponents do: [:c | c priorDCValue: 0]. restartsToGo _ restartInterval.! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/4/2001 01:17'! scaleAndSignExtend: aNumber inFieldWidth: w aNumber < (1 bitShift: (w - 1)) ifTrue: [^aNumber - (1 bitShift: w) + 1] ifFalse: [^aNumber]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/4/2001 18:38'! initialSOSSetup mcuWidth _ (components detectMax: [:c | c widthInBlocks]) widthInBlocks. mcuHeight _ (components detectMax: [:c | c heightInBlocks]) heightInBlocks. components do:[:c | c mcuWidth: mcuWidth mcuHeight: mcuHeight dctSize: DCTSize]. stream resetBitBuffer.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'mir 6/13/2001 13:06'! okToIgnoreMarker: aMarker ^ (((16rE0 to: 16rEF) includes: aMarker) "unhandled APPn markers" or: [aMarker = 16rDC or: [aMarker = 16rFE]]) "DNL or COM markers" or: [aMarker = 16r99] "Whatever that is"! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/6/2001 22:28'! parseAPPn | length buffer thumbnailLength markerStart | markerStart _ self position. length _ self nextWord. buffer _ self next: 4. (buffer asString = 'JFIF') ifFalse: [ "Skip APPs that we're not interested in" stream next: length-6. ^self]. self next. majorVersion _ self next. minorVersion _ self next. densityUnit _ self next. xDensity _ self nextWord. yDensity _ self nextWord. thumbnailLength _ self next * self next * 3. length _ length - (self position - markerStart). length = thumbnailLength ifFalse: [self error: 'APP0 thumbnail length is incorrect.']. self next: length! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/20/97 13:36'! parseDecoderRestartInterval | length | length _ self nextWord. length = 4 ifFalse: [self error: 'DRI length incorrect']. restartInterval _ self nextWord.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'mir 6/12/2001 11:28'! parseFirstMarker | marker | self next = 16rFF ifFalse: [self error: 'JFIF marker expected']. marker _ self next. marker = 16rD9 ifTrue: [^self "halt: 'EOI encountered.'"]. marker = 16rD8 ifFalse: [self error: 'SOI marker expected']. self parseStartOfInput. ! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/4/2001 18:36'! parseHuffmanTable | length markerStart index bits count huffVal isACTable hTable | markerStart _ self position. length _ self nextWord. [self position - markerStart >= length] whileFalse: [index _ self next. isACTable _ (index bitAnd: 16r10) ~= 0. index _ (index bitAnd: 16r0F) + 1. index > HuffmanTableSize ifTrue: [self error: 'image has more than ', HuffmanTableSize printString, ' quantization tables']. bits _ self next: 16. count _ bits sum. (count > 256 or: [(count > (length - (self position - markerStart)))]) ifTrue: [self error: 'Huffman Table count is incorrect']. huffVal _ self next: count. hTable _ stream buildLookupTable: huffVal counts: bits. isACTable ifTrue: [self hACTable at: index put: hTable] ifFalse: [self hDCTable at: index put: hTable]].! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/24/97 17:32'! parseNOP "don't need to do anything, here"! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'BG 3/16/2005 08:24'! parseNextMarker "Parse the next marker of the stream" | byte discardedBytes | discardedBytes _ 0. [(byte _ self next) = 16rFF] whileFalse: [discardedBytes _ discardedBytes + 1]. [[(byte _ self next) = 16rFF] whileTrue. byte = 16r00] whileTrue: [discardedBytes _ discardedBytes + 2]. discardedBytes > 0 ifTrue: [self "notifyWithLabel: 'warning: extraneous data discarded'"]. self perform: (JFIFMarkerParser at: byte ifAbsent: [(self okToIgnoreMarker: byte) ifTrue: [#skipMarker] ifFalse: [self error: 'marker ', byte printStringHex , ' cannot be handled']])! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/3/2001 22:19'! parseQuantizationTable | length markerStart n prec value table | markerStart _ self position. length _ self nextWord. [self position - markerStart >= length] whileFalse: [value _ self next. n _ (value bitAnd: 16r0F) + 1. prec _ (value >> 4) > 0. n > QuantizationTableSize ifTrue: [self error: 'image has more than ', QuantizationTableSize printString, ' quantization tables']. table _ IntegerArray new: DCTSize2. 1 to: DCTSize2 do: [:i | value _ (prec ifTrue: [self nextWord] ifFalse: [self next]). table at: (JPEGNaturalOrder at: i) put: value]. self useFloatingPoint ifTrue: [self scaleQuantizationTable: table]. self qTable at: n put: table]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/24/97 17:07'! parseStartOfFile | length markerStart value n | markerStart _ self position. length _ self nextWord. dataPrecision _ self next. dataPrecision = 8 ifFalse: [self error: 'cannot handle ', dataPrecision printString, '-bit components']. height _ self nextWord. width _ self nextWord. n _ self next. (height = 0) | (width = 0) | (n = 0) ifTrue: [self error: 'empty image']. (length - (self position - markerStart)) ~= (n * 3) ifTrue: [self error: 'component length is incorrect']. components _ Array new: n. 1 to: components size do: [:i | components at: i put: (JPEGColorComponent new id: self next; "heightInBlocks: (((value _ self next) >> 4) bitAnd: 16r0F); widthInBlocks: (value bitAnd: 16r0F);" widthInBlocks: (((value _ self next) >> 4) bitAnd: 16r0F); heightInBlocks: (value bitAnd: 16r0F); qTableIndex: self next + 1)]! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/22/97 17:38'! parseStartOfInput restartInterval _ 0. densityUnit _ 0. xDensity _ 1. yDensity _ 1 ! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/26/97 21:53'! parseStartOfScan | length n id value dcNum acNum comp | length _ self nextWord. n _ self next. (length ~= (n*2 + 6)) | (n < 1) ifTrue: [self error: 'SOS length is incorrect']. currentComponents _ Array new: n. 1 to: n do: [:i | id _ self next. value _ self next. dcNum _ (value >> 4) bitAnd: 16r0F. acNum _ value bitAnd: 16r0F. comp _ components detect: [:c | c id = id]. comp dcTableIndex: dcNum+1; acTableIndex: acNum+1. currentComponents at: i put: comp]. ss _ self next. se _ self next. value _ self next. ah _ (value >> 4) bitAnd: 16r0F. al _ value bitAnd: 16r0F. self initialSOSSetup. self perScanSetup. sosSeen _ true! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/7/2001 01:01'! perScanSetup mcusPerRow _ (width / (mcuWidth * DCTSize)) ceiling. mcuRowsInScan _ (height / (mcuHeight * DCTSize)) ceiling. (currentComponents size = 3 or: [currentComponents size = 1]) ifFalse: [self error: 'JPEG color space not recognized']. mcuMembership _ OrderedCollection new. currentComponents withIndexDo: [:c :i | c priorDCValue: 0. mcuMembership addAll: ((1 to: c totalMcuBlocks) collect: [:b | i])]. mcuMembership _ mcuMembership asArray. mcuSampleBuffer _ (1 to: mcuMembership size) collect: [:i | IntegerArray new: DCTSize2]. currentComponents withIndexDo: [:c :i | c initializeSampleStreamBlocks: ((1 to: mcuMembership size) select: [:j | i = (mcuMembership at: j)] thenCollect: [:j | mcuSampleBuffer at: j])]. mcuImageBuffer _ Form extent: (mcuWidth @ mcuHeight) * DCTSize depth: 32. restartsToGo _ restartInterval.! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'tao 10/22/97 16:27'! skipMarker | length markerStart | markerStart _ self position. length _ self nextWord. self next: length - (self position - markerStart) ! ! !JPEGReadWriter methodsFor: 'preferences' stamp: 'tao 10/26/97 22:09'! useFloatingPoint ^ false! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/7/2001 00:18'! decompressionTest "Test decompression; don't generate actual image" | xStep yStep x y | MessageTally spyOn:[ ditherMask _ DitherMasks at: 32. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. x _ x + xStep]. y _ y + yStep]. ].! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'tao 9/18/1998 08:53'! nextImage ^ self nextImageDitheredToDepth: Display depth ! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 10/28/2001 16:25'! nextImageDitheredToDepth: depth | form xStep yStep x y bb | ditherMask _ DitherMasks at: depth ifAbsent: [self error: 'can only dither to display depths']. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. form _ Form extent: (width @ height) depth: depth. bb _ BitBlt current toForm: form. bb sourceForm: mcuImageBuffer. bb colorMap: (mcuImageBuffer colormapIfNeededFor: form). bb sourceRect: mcuImageBuffer boundingBox. bb combinationRule: Form over. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. bb destX: x; destY: y; copyBits. x _ x + xStep]. y _ y + yStep]. ^ form! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/4/2001 17:26'! setStream: aStream "Feed it in from an existing source" stream _ JPEGReadStream on: aStream upToEnd.! ! !JPEGReadWriter methodsFor: 'testing' stamp: 'ar 3/4/2001 00:50'! understandsImageFormat "Answer true if the image stream format is understood by this decoder." self next = 16rFF ifFalse: [^ false]. self next = 16rD8 ifFalse: [^ false]. ^ true ! ! !JPEGReadWriter methodsFor: 'private' stamp: 'ar 3/4/2001 17:34'! on: aStream super on: aStream. stream _ JPEGReadStream on: stream upToEnd.! ! !JPEGReadWriter commentStamp: '<historical>' prior: 0! I am a subclass of ImageReadWriter that understands JFIF file streams, and can decode JPEG images. This code is based upon the Independent Joint Photographic Experts Group (IJPEG) software, originally written in C by Tom Lane, Philip Gladstone, Luis Ortiz, Jim Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. ! !JPEGReadWriter class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('jpg' 'jpeg')! ! !JPEGReadWriter class methodsFor: 'image reading/writing' stamp: 'ar 6/16/2002 18:54'! understandsImageFormat: aStream (JPEGReadWriter2 understandsImageFormat: aStream) ifTrue:[^false]. aStream reset. aStream next = 16rFF ifFalse: [^ false]. aStream next = 16rD8 ifFalse: [^ false]. ^true! ! !JPEGReadWriter class methodsFor: 'initialization' stamp: 'ar 3/3/2001 23:07'! initialize "JPEGReadWriter initialize" "general constants" DCTSize _ 8. MaxSample _ (2 raisedToInteger: DCTSize) - 1. SampleOffset _ MaxSample // 2. FloatSampleOffset _ SampleOffset asFloat. DCTSize2 _ DCTSize squared. QuantizationTableSize _ 4. HuffmanTableSize _ 4. "floating-point Inverse Discrete Cosine Transform (IDCT) constants" ConstBits _ 13. Pass1Bits _ 2. DCTK1 _ 2 sqrt. DCTK2 _ 1.847759065. DCTK3 _ 1.082392200. DCTK4 _ -2.613125930. Pass1Div _ 1 bitShift: ConstBits - Pass1Bits. Pass2Div _ 1 bitShift: ConstBits + Pass1Bits + 3. "fixed-point Inverse Discrete Cosine Transform (IDCT) constants" FIXn0n298631336 _ 2446. FIXn0n390180644 _ 3196. FIXn0n541196100 _ 4433. FIXn0n765366865 _ 6270. FIXn0n899976223 _ 7373. FIXn1n175875602 _ 9633. FIXn1n501321110 _ 12299. FIXn1n847759065 _ 15137. FIXn1n961570560 _ 16069. FIXn2n053119869 _ 16819. FIXn2n562915447 _ 20995. FIXn3n072711026 _ 25172. "fixed-point color conversion constants" FIXn0n34414 _ 22554. FIXn0n71414 _ 46802. FIXn1n40200 _ 91881. FIXn1n77200 _ 116130. "reordering table from JPEG zig-zag order" JPEGNaturalOrder _ #( 1 2 9 17 10 3 4 11 18 25 33 26 19 12 5 6 13 20 27 34 41 49 42 35 28 21 14 7 8 15 22 29 36 43 50 57 58 51 44 37 30 23 16 24 31 38 45 52 59 60 53 46 39 32 40 47 54 61 62 55 48 56 63 64). "scale factors for the values in the Quantization Tables" QTableScaleFactor _ (0 to: DCTSize-1) collect: [:k | k = 0 ifTrue: [1.0] ifFalse: [(k * Float pi / 16) cos * 2 sqrt]]. "dithering masks" (DitherMasks _ Dictionary new) add: 0 -> 0; add: 1 -> 127; add: 2 -> 63; add: 4 -> 63; add: 8 -> 31; add: 16 -> 7; add: 32 -> 0. "dictionary of marker parsers" (JFIFMarkerParser _ Dictionary new) add: (16r01 -> #parseNOP); add: (16rC0 -> #parseStartOfFile); add: (16rC4 -> #parseHuffmanTable); addAll: ((16rD0 to: 16rD7) collect: [:m | Association key: m value: #parseNOP]); add: (16rD8 -> #parseStartOfInput); add: (16rD9 -> #parseEndOfInput); add: (16rDA -> #parseStartOfScan); add: (16rDB -> #parseQuantizationTable); add: (16rDD -> #parseDecoderRestartInterval); add: (16rE0 -> #parseAPPn); add: (16rE1 -> #parseAPPn)! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:34'! primImageHeight: aJPEGCompressStruct <primitive: 'primImageHeight' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primImageWidth: aJPEGCompressStruct <primitive: 'primImageWidth' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGCompressStructSize <primitive: 'primJPEGCompressStructSize' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGDecompressStructSize <primitive: 'primJPEGDecompressStructSize' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGErrorMgr2StructSize <primitive: 'primJPEGErrorMgr2StructSize' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'ar 11/27/2001 00:39'! primJPEGPluginIsPresent <primitive: 'primJPEGPluginIsPresent' module: 'JPEGReadWriter2Plugin'> ^false! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGReadHeader: aJPEGDecompressStruct fromByteArray: source errorMgr: aJPEGErrorMgr2Struct <primitive: 'primJPEGReadHeaderfromByteArrayerrorMgr' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jmv 12/7/2001 13:45'! primJPEGReadImage: aJPEGDecompressStruct fromByteArray: source onForm: form doDithering: ditherFlag errorMgr: aJPEGErrorMgr2Struct <primitive: 'primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'primitives' stamp: 'jm 11/20/2001 10:35'! primJPEGWriteImage: aJPEGCompressStruct onByteArray: destination form: form quality: quality progressiveJPEG: progressiveFlag errorMgr: aJPEGErrorMgr2Struct <primitive: 'primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr' module: 'JPEGReadWriter2Plugin'> self primitiveFailed ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'JMM 1/11/2005 14:56'! compress: aForm quality: quality "Encode the given Form and answer the compressed ByteArray. Quality goes from 0 (low) to 100 (high), where -1 means default." | sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount | aForm unhibernate. "odd width images of depth 16 give problems; avoid them." sourceForm _ (aForm depth = 32) | (aForm width even & (aForm depth = 16)) ifTrue: [aForm] ifFalse: [aForm asFormOfDepth: 32]. jpegCompressStruct _ ByteArray new: self primJPEGCompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. buffer _ ByteArray new: sourceForm width * sourceForm height + 1024. byteCount _ self primJPEGWriteImage: jpegCompressStruct onByteArray: buffer form: sourceForm quality: quality progressiveJPEG: false errorMgr: jpegErrorMgr2Struct. byteCount = 0 ifTrue: [self error: 'buffer too small for compressed data']. ^ buffer copyFrom: 1 to: byteCount ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:01'! imageExtent: aByteArray "Answer the extent of the compressed image encoded in the given ByteArray." | jpegDecompressStruct jpegErrorMgr2Struct w h | jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ^ w @ h ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:23'! nextImage "Decode and answer a Form from my stream." ^ self nextImageSuggestedDepth: Display depth ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'sd 1/30/2004 15:19'! nextImageSuggestedDepth: depth "Decode and answer a Form of the given depth from my stream. Close the stream if it is a file stream. Possible depths are 16-bit and 32-bit." | bytes width height form jpegDecompressStruct jpegErrorMgr2Struct depthToUse | bytes _ stream upToEnd. stream close. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: bytes errorMgr: jpegErrorMgr2Struct. width _ self primImageWidth: jpegDecompressStruct. height _ self primImageHeight: jpegDecompressStruct. "Odd width images of depth 16 gave problems. Avoid them (or check carefully!!)" depthToUse _ ((depth = 32) | width odd) ifTrue: [32] ifFalse: [16]. form _ Form extent: width@height depth: depthToUse. (width = 0 or: [height = 0]) ifTrue: [^ form]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: bytes onForm: form doDithering: true errorMgr: jpegErrorMgr2Struct. ^ form ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jm 11/20/2001 10:21'! nextPutImage: aForm "Encode the given Form on my stream with default quality." ^ self nextPutImage: aForm quality: -1 progressiveJPEG: false ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'JMM 1/11/2005 14:45'! nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag "Encode the given Form on my stream with the given settings. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG." | sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount | aForm unhibernate. "odd width images of depth 16 give problems; avoid them." sourceForm _ (aForm depth = 32) | (aForm width even & (aForm depth = 16)) ifTrue: [aForm] ifFalse: [aForm asFormOfDepth: 32]. jpegCompressStruct _ ByteArray new: self primJPEGCompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. buffer _ ByteArray new: sourceForm width * sourceForm height + 1024. byteCount _ self primJPEGWriteImage: jpegCompressStruct onByteArray: buffer form: sourceForm quality: quality progressiveJPEG: progressiveFlag errorMgr: jpegErrorMgr2Struct. byteCount = 0 ifTrue: [self error: 'buffer too small for compressed data']. stream next: byteCount putAll: buffer startingAt: 1. self close. ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jmv 12/7/2001 13:49'! uncompress: aByteArray into: aForm "Uncompress an image from the given ByteArray into the given Form. Fails if the given Form has the wrong dimensions or depth. If aForm has depth 16, do ordered dithering." | jpegDecompressStruct jpegErrorMgr2Struct w h | aForm unhibernate. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ((aForm width = w) & (aForm height = h)) ifFalse: [ ^ self error: 'form dimensions do not match']. "odd width images of depth 16 give problems; avoid them" w odd ifTrue: [ aForm depth = 32 ifFalse: [^ self error: 'must use depth 32 with odd width']] ifFalse: [ ((aForm depth = 16) | (aForm depth = 32)) ifFalse: [^ self error: 'must use depth 16 or 32']]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: aByteArray onForm: aForm doDithering: true errorMgr: jpegErrorMgr2Struct. ! ! !JPEGReadWriter2 methodsFor: 'public access' stamp: 'jmv 12/7/2001 13:48'! uncompress: aByteArray into: aForm doDithering: ditherFlag "Uncompress an image from the given ByteArray into the given Form. Fails if the given Form has the wrong dimensions or depth. If aForm has depth 16 and ditherFlag = true, do ordered dithering." | jpegDecompressStruct jpegErrorMgr2Struct w h | aForm unhibernate. jpegDecompressStruct _ ByteArray new: self primJPEGDecompressStructSize. jpegErrorMgr2Struct _ ByteArray new: self primJPEGErrorMgr2StructSize. self primJPEGReadHeader: jpegDecompressStruct fromByteArray: aByteArray errorMgr: jpegErrorMgr2Struct. w _ self primImageWidth: jpegDecompressStruct. h _ self primImageHeight: jpegDecompressStruct. ((aForm width = w) & (aForm height = h)) ifFalse: [ ^ self error: 'form dimensions do not match']. "odd width images of depth 16 give problems; avoid them" w odd ifTrue: [ aForm depth = 32 ifFalse: [^ self error: 'must use depth 32 with odd width']] ifFalse: [ ((aForm depth = 16) | (aForm depth = 32)) ifFalse: [^ self error: 'must use depth 16 or 32']]. self primJPEGReadImage: jpegDecompressStruct fromByteArray: aByteArray onForm: aForm doDithering: ditherFlag errorMgr: jpegErrorMgr2Struct. ! ! !JPEGReadWriter2 methodsFor: 'testing' stamp: 'ar 11/27/2001 00:40'! isPluginPresent ^self primJPEGPluginIsPresent! ! !JPEGReadWriter2 methodsFor: 'testing' stamp: 'ar 11/27/2001 00:39'! understandsImageFormat "Answer true if the image stream format is understood by this decoder." self isPluginPresent ifFalse:[^false]. "cannot read it otherwise" self next = 16rFF ifFalse: [^ false]. self next = 16rD8 ifFalse: [^ false]. ^ true ! ! !JPEGReadWriter2 commentStamp: '<historical>' prior: 0! I provide fast JPEG compression and decompression. I require the VM pluginJPEGReadWriter2Plugin, which is typically stored in same directory as the Squeak virtual machine. JPEGReadWriter2Plugin is based on LIBJPEG library. This sentence applies to the plugin: "This software is based in part on the work of the Independent JPEG Group". The LIBJPEG license allows it to be used free for any purpose so long as its origin and copyright are acknowledged. You can read more about LIBJPEG and get the complete source code at www.ijg.org. ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'ar 6/16/2002 18:54'! primJPEGPluginIsPresent <primitive: 'primJPEGPluginIsPresent' module: 'JPEGReadWriter2Plugin'> ^false! ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'jm 12/22/2001 11:55'! putForm: aForm quality: quality progressiveJPEG: progressiveFlag onFileNamed: fileName "Store the given Form as a JPEG file of the given name, overwriting any existing file of that name. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG." | writer | FileDirectory deleteFilePath: fileName. writer _ self on: (FileStream newFileNamed: fileName) binary. Cursor write showWhile: [ writer nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag]. writer close. ! ! !JPEGReadWriter2 class methodsFor: 'image reading/writing' stamp: 'nk 7/16/2003 17:56'! typicalFileExtensions "Answer a collection of file extensions (lowercase) which files that I can read might commonly have" ^#('jpg' 'jpeg')! ! !LargePositiveInteger methodsFor: 'printing' stamp: 'ssa 9/11/2009 16:52'! printOn: aStream "hack to fix strange LPI bug" ^(self - 1 + 1)printOn: aStream base: 10! ! !LinkedList methodsFor: 'converting' stamp: 'ssa 1/26/2010 16:24'! asOrderedCollection ^(self collect:[:link| link])asOrderedCollection! ! !LinkedList methodsFor: 'explorer' stamp: 'ssa 1/26/2010 16:32'! hasContentsInExplorer ^self isEmpty not! ! !ListController methodsFor: 'menu messages' stamp: 'ssa 9/15/2009 16:53'! processKeyboard "Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | sensor keyboardPressed ifFalse: [^ self]. keyEvent := sensor keyboard asciiValue. (keyEvent = $l asciiValue and:[Sensor commandKeyPressed])ifTrue:[self view topView adjustWidths]. oldSelection := view selection. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view clippingBox height // view list lineGrid. keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [model okToChange ifTrue: [self changeModelSelection: nextSelection. self moveMarker]] ! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 12:15'! hasEquivalentIn: aCollection aCollection detect: [ :each | each withoutListWrapper = item withoutListWrapper ] ifNone: [^false]. ^true! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 4/4/1999 17:58'! sendSettingMessageTo: aModel aModel perform: (self settingSelector ifNil: [^self]) with: self withoutListWrapper ! ! !ListItemWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 21:31'! settingSelector ^nil! ! !ListItemWrapper methodsFor: 'converting' stamp: 'RAA 3/30/1999 18:17'! asString ^item asString! ! !ListItemWrapper methodsFor: 'converting' stamp: 'RAA 3/31/1999 12:13'! withoutListWrapper ^item withoutListWrapper! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/31/1999 16:32'! contents ^Array new! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 4/1/1999 20:09'! hasContents ^self contents isEmpty not! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 8/3/1999 09:40'! highlightingColor ^Color red! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:22'! icon "Answer a form to be used as icon" ^ nil! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! item "Answer the value of item" item isNil ifTrue:[self item: nil]. ^ item! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! item: anObject "Set the value of item" item _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! model "Answer the value of model" model isNil ifTrue:[self model: nil]. ^ model! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'ssa 11/24/2009 19:07'! model: anObject "Set the value of model" model _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 4/2/1999 15:14'! preferredColor ^nil! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/30/1999 18:27'! setItem: anObject item _ anObject! ! !ListItemWrapper methodsFor: 'accessing' stamp: 'RAA 3/31/1999 16:44'! setItem: anObject model: aModel item _ anObject. model _ aModel.! ! !ListItemWrapper commentStamp: '<historical>' prior: 0! Contributed by Bob Arning as part of the ObjectExplorer package. ! !ListItemWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 3/30/1999 18:28'! with: anObject ^self new setItem: anObject! ! !ListItemWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 3/31/1999 16:44'! with: anObject model: aModel ^self new setItem: anObject model: aModel! ! !ListView methodsFor: 'displaying'! scrollSelectionIntoView "Selection is assumed to be on and clipped out of view. Uses controller scrollView to keep selection right" | delta | (delta _ self insetDisplayBox bottom - self selectionBox bottom) < 0 ifTrue: [^ self controller scrollView: delta - (list lineGrid-1)]. "up" (delta _ self insetDisplayBox top - self selectionBox top) > 0 ifTrue: [^ self controller scrollView: delta + 1] "down"! ! !ListView methodsFor: 'clipping box access' stamp: 'ssa 9/11/2009 18:25'! clippingBox "Answer the rectangle in which the model can be displayed--this is the insetDisplayBox inset by the height of a line for an item." ^self insetDisplayBox insetBy: (Rectangle left: 0 right: 0 top: 0 bottom: 0 "self insetDisplayBox height \\ list lineGrid")! ! !ListView methodsFor: 'selecting' stamp: 'ssa 9/11/2009 18:25'! findSelection: aPoint "Determine which selection is displayed in an area containing the point, aPoint. Answer the selection if one contains the point, answer nil otherwise." | trialSelection | (self clippingBox containsPoint: aPoint) ifFalse: [^nil]. trialSelection _ aPoint y - list compositionRectangle top // list lineGrid + 1. topDelimiter == nil ifFalse: [trialSelection _ trialSelection - 1]. (trialSelection < 1) | (trialSelection > self maximumSelection) ifTrue: [^ nil] ifFalse: [^ trialSelection]! ! !ListView methodsFor: 'updating' stamp: 'ssa 1/22/2010 14:49'! update: aSymbol "Refer to the comment in View|update:." "Hacked to support MSWScrollBars - ssa 12/11/97 16:42" aSymbol == #list ifTrue: [self list: model list. self displayView] ifFalse:[ aSymbol == #listIndex ifTrue: [self moveSelectionBox: model listIndex]]. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! isEmpty "Answer the value of isEmpty" isEmpty isNil ifTrue:[self isEmpty: nil]. ^ isEmpty! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! isEmpty: anObject "Set the value of isEmpty" isEmpty _ anObject! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! textStyle "Answer the value of textStyle" textStyle isNil ifTrue:[self textStyle: nil]. ^ textStyle! ! !ListView methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:43'! textStyle: anObject "Set the value of textStyle" textStyle _ anObject! ! !ListView methodsFor: '*Interface-MSWLook'! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" | para lineIndex | para _ self list. lineIndex _ para lineIndexOfTop: para visibleRectangle top. lineIndex = 1 ifTrue:[^0.0]. ^lineIndex / para numberOfLines asFloat ! ! !ListView methodsFor: '*Interface-MSWLook'! scrollBy: anInteger "Scroll up by this amount adjusted by lineSpacing and list limits" "Hacked to support MSWScrollBarView - ssa 12/10/97 16:26" | maximumAmount minimumAmount amount | maximumAmount _ 0 max: list clippingRectangle top - list compositionRectangle top. minimumAmount _ 0 min: list clippingRectangle bottom - list compositionRectangle bottom. amount _ (anInteger min: maximumAmount) max: minimumAmount. amount ~= 0 ifTrue: [list scrollBy: amount negated. (self superView isKindOf: MSWScrollBarView) "______HERE IS THE HACK" ifTrue:[self superView updateElevator]. ^ true] ifFalse: [^ false] "Return false if no scrolling took place"! ! !ListView methodsFor: '*Interface-MSWLook' stamp: 'ssa 9/9/2009 15:24'! totalContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self list compositionRectangle height / self unitContentHeight! ! !ListView methodsFor: '*Interface-MSWLook'! unitContentHeight "Answer the unit height of my contents. ssa 12/5/97 15:16" ^ self list lineGrid asFloat! ! !ListView methodsFor: '*Interface-MSWLook'! visibleContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self list clippingRectangle height / self unitContentHeight! ! !LongTestCase commentStamp: 'DamirLaurent 5/2/2011 22:17' prior: 0! I'm a TestCase which takes time to run. I can be disabled using #doNotRunLongTestCases and enabled again using #runLongTestCases. Tests that are long should be subclasses of myself. I also provide a setting for the SettingsBrowser! !LongTestCase class methodsFor: 'accessing' stamp: 'StephaneDucasse 10/18/2010 14:02'! allTestSelectors self shouldRun ifTrue: [ ^super testSelectors]. ^#().! ! !LongTestCase class methodsFor: 'accessing' stamp: 'StephaneDucasse 10/18/2010 12:21'! doNotRunLongTestCases "Tells the system that long tests should not be run" self shouldRun: false! ! !LongTestCase class methodsFor: 'accessing' stamp: 'StephaneDucasse 10/18/2010 12:21'! runLongTestCases "Tell the system that long tests should be run" self shouldRun: true.! ! !LongTestCase class methodsFor: 'accessing' stamp: 'DamirLaurent 5/2/2011 21:33'! shouldRun "Return whether long tests should be run or not" RunLongTestCases ifNil: [self runLongTestCases]. ^ RunLongTestCases ! ! !LongTestCase class methodsFor: 'accessing' stamp: 'StephaneDucasse 10/18/2010 12:21'! shouldRun: aBoolean "Set whether long tests should be run or not" RunLongTestCases := aBoolean! ! !LongTestCase class methodsFor: 'initialization' stamp: 'DamirLaurent 5/2/2011 21:32'! initialize self runLongTestCases! ! !LongTestCase class methodsFor: 'instance creation' stamp: 'StephaneDucasse 10/18/2010 14:02'! buildSuite | suite | suite := self suiteClass new. self shouldRun ifTrue: [ self addToSuiteFromSelectors: suite]. ^suite! ! !LongTestCase class methodsFor: 'settings' stamp: 'DamirLaurent 5/2/2011 21:59'! runLongTestsSettingOn: aBuilder "<systemsettings>" (aBuilder setting: #shouldRun) target: self; parent: #pharoSystem; label: 'Run Long Tests' translated; description: 'Whether to run long SUnit TestCase. Tests which take long time to run should be subclasses of LongTestCase.' translated.! ! !LongTestCase class methodsFor: 'testing' stamp: 'md 2/22/2006 14:21'! isAbstract "Override to true if a TestCase subclass is Abstract and should not have TestCase instances built from it" ^self name = #LongTestCase ! ! !LongTestCaseTest methodsFor: 'setup'! setUp longTestCaseSettingValue := LongTestCase shouldRun! ! !LongTestCaseTest methodsFor: 'setup'! tearDown LongTestCase shouldRun: longTestCaseSettingValue! ! !LongTestCaseTest methodsFor: 'testing'! testLongTestCaseDoNotRun "self debug: #testLongTestCaseDoNotRun" "self run: #testLongTestCaseDoNotRun" LongTestCase doNotRunLongTestCases. LongTestCaseTestUnderTest markAsNotRun. self deny: LongTestCaseTestUnderTest hasRun. LongTestCaseTestUnderTest suite run. self deny: LongTestCaseTestUnderTest hasRun. ! ! !LongTestCaseTest methodsFor: 'testing' stamp: 'md 12/5/2004 21:28'! testLongTestCaseRun "self debug: #testLongTestCaseRun" "self run: #testLongTestCaseRun" LongTestCase runLongTestCases. LongTestCaseTestUnderTest markAsNotRun. self deny: LongTestCaseTestUnderTest hasRun. LongTestCaseTestUnderTest suite run. self assert: LongTestCaseTestUnderTest hasRun. LongTestCase doNotRunLongTestCases. ! ! !LongTestCaseTestUnderTest methodsFor: 'testing' stamp: 'md 11/14/2004 21:30'! testWhenRunMarkTestedToTrue RunStatus := true.! ! !LongTestCaseTestUnderTest class methodsFor: 'accessing' stamp: 'sd 9/25/2004 14:02'! hasRun ^ RunStatus! ! !LongTestCaseTestUnderTest class methodsFor: 'accessing' stamp: 'md 11/14/2004 21:37'! markAsNotRun ^ RunStatus := false! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 20:36'! fileReaderServicesForFile: fullName suffix: suffix ^(#('gif' 'jpg' 'jpeg' 'bmp')includes: suffix) ifTrue: [ self services] ifFalse: [#()]! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 3/9/2010 12:42'! importGraphic: fileName "self importGraphic:'/Users/samadams/Desktop/ssa working/lockClosed.gif'" | fname image selector | fname _ fileName sansPeriodSuffix. selector _ fname copyFrom: (fname lastIndexOf:$/)+ 1 to: fname size. image _ Form fromFileNamed: fileName. self installGraphic: image named: selector. ! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 11/26/2009 22:54'! installGraphic: aForm named: aString "add a new method to me named aString that regenerates aForm" | selector response code startString | startString _ aString select:[:c| c isLetter | c isDigit]. selector _ (self respondsTo: startString asSymbol) ifTrue:[[response _ FillInTheBlank request:'Selector #',startString,' already used.\Enter a new selector\to store this graphic under' withCRs initialAnswer: startString. response isEmpty ifTrue:[^self]. self respondsTo: response asSymbol] whileTrue. response] ifFalse:[startString]. code _ selector,' "Cursor blank showWhile:[self ',selector,' follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" "FormView open: self ',selector,' named: ''',selector,'''" ^',aForm storeString. self class compile: code classified:'graphics'! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 19:51'! serviceImportGraphic ^SimpleServiceEntry provider: self label: 'import graphic' selector: #importGraphic: description: 'import graphic to LyGraphicLibrary' buttonLabel: 'install'! ! !LyGraphicsLibrary class methodsFor: 'importing' stamp: 'ssa 8/28/2009 19:48'! services ^ Array with: self serviceImportGraphic ! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/5/2010 20:33'! selfTwistyClosed "Cursor blank showWhile:[self selfTwistyClosed follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 5@10 depth: 8 fromArray: #( 4278190080 0 4294901760 0 4294967040 0 4294967295 0 4294967295 4278190080 4294967295 4278190080 4294967295 0 4294967040 0 4294901760 0 4278190080 0) offset: 0@0) colorsFromArray: #(#( ) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/5/2010 20:33'! selfTwistyOpen "Cursor blank showWhile:[self selfTwistyOpen follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 10@10 depth: 8 fromArray: #( 0 4278190080 0 255 4294901760 0 65535 4294901760 0 16777215 4294967040 0 4294967295 4294967040 0 16777215 4294967295 0 255 4294967295 0 0 16777215 4278190080 0 255 4278190080 0 0 16711680) offset: 0@0) colorsFromArray: #(#( ) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'graphics' stamp: 'ssa 1/4/2010 16:22'! workWarningCone "Cursor blank showWhile:[self workWarningCone follow:[Sensor cursorPoint] while:[Sensor noButtonPressed]]" ^((ColorForm extent: 64@64 depth: 8 fromArray: #( 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4271808092 1549557758 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4266482012 1503549182 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4262222169 1128495870 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1360216899 1128487254 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 135742239 1128481560 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 136201027 524501875 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 140067651 1128481566 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124109 742605599 1128481624 1459551998 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 320806723 524501827 1442774782 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124039 236526106 522133279 1442774782 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278079746 269028884 336863007 2052521726 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278084614 33820180 437919519 2544107262 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278059008 21712149 2223281059 2170748670 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4272103936 1610637408 2164359520 23110654 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267704416 6291457 1616928864 1610711550 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261412960 16810336 1616928769 2170585598 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267713120 1610702944 23093344 2172739838 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2734710784 1616928864 1616904577 1610703011 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1610637313 1616904193 1619091585 2170585473 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 570458368 16810336 2170585440 1619067265 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 23093377 1619067232 1610702977 2172748198 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124116 177443713 2172748161 2172748161 2744355443 1459551998 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124109 135807833 1451853446 2256950614 1499225210 1912536830 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 656296259 1128481603 1130125660 1547918402 1912536830 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124071 675496771 1229144905 1128483139 1229538140 503250686 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278079752 356729667 1128483139 1128874825 1128483145 1938554622 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278085416 356731203 1128874825 1128483139 1229538121 2054094590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278061095 407061315 1128481603 1128874825 1128483139 1131347710 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4269886504 505356063 1128481603 1128481603 1126113091 1230222590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4267728903 1126111775 438247199 1126122271 522133315 2309198590 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261437536 2205032218 521805599 438247199 524506515 2743173630 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4261478400 1619104405 2223409430 1433306757 2510520705 2172739838 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2164285441 1610702977 1652654465 2172748161 2172752513 2172748195 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 1616904288 2170577025 1610711425 2172748161 2457960833 2173862273 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 6316128 1610702977 2170585473 2172748161 2172748178 2172748161 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124195 16777312 23093249 1619067265 1652646529 2173862273 2172748161 2784952062 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124128 6324481 1619100000 2172748161 2172748161 2172748161 2457960800 2751397630 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124132 1616928864 1619091585 2172748130 2172740242 2172752513 1619100033 2516516606 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124040 1684013408 2170552672 2164359553 2172748161 2172748161 1650483787 754908926 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278080551 1292416129 25264513 1619100033 2172748161 2173862290 2170683692 676855550 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124051 270422312 673012102 3028386177 1686208897 2173862290 2172756901 2536256029 946883070 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 671615244 507651880 742015836 1549183400 3030627491 2745414822 2996280648 1112087881 743721308 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278059779 134752019 1127876648 675891523 1229538121 1230784638 2120173897 1230981449 1229537353 493902409 1229586174 4278124286 4278124286 4278124286 4278124286 4278124286 4262200071 134875678 523380520 357122889 1128876355 1229539657 1229539657 1598638409 1229539423 1465152329 1128876542 4278124286 4278124286 4278124286 4278124286 4278124286 4268950279 134752286 1126705192 843663683 1229146441 1229146441 1229544521 1230981471 1229539657 1517383241 1230784841 1560215294 4278124286 4278124286 4278124286 4278124286 4266930691 134875706 1126639660 977486665 1229539651 1229539657 1548306780 1229545289 1600080223 1517383772 1229539679 1228938750 4278124286 4278124286 4278124286 4278124286 4278085939 134875667 1126639656 1212760905 1128876361 1229539657 1230784841 1598643273 1598644060 2117628255 1230784841 1598044211 4278124286 4278124286 4278124286 4278124286 4278124145 1846151692 405219111 1109346627 1128874825 1128876380 1229539679 1230784860 1229539679 1483823689 1548306780 1228943922 4278124286 4278124286 4278124286 4278124286 4278124286 2388069385 167912236 524492611 1128483139 1229146441 1229539657 1229539651 1128487260 2119671369 1229545289 1545418808 3221159678 4278124286 4278124286 4278124286 4278124286 4272786956 51387734 1549344579 524492611 1128481603 1128481603 1128481603 1130121632 1520322889 1230981468 1079676573 3388931838 4278124286 4278124286 4278124286 4278124286 4278095517 320020034 1549556825 1128481603 524501827 1128481603 1497586780 1549574304 1598638409 1598644128 2695732618 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 2685616926 1130143327 2656853081 1549556060 1499225180 1549753439 2694864713 1598638409 2694884768 2915041022 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2911781407 522142537 1553883040 2657067100 2690621600 2694881375 1599889225 1235263661 2695741950 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4273778012 522133315 1128874825 1230784860 1549551945 1128481628 1229545376 2912985276 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 1547902751 1128481603 1128874825 1128481567 1128483164 2695736749 2919169790 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 2908504863 522142531 1126122271 1128481603 1549574317 2913861374 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4272791625 1128472387 524501827 1128488096 2913840583 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278100128 1547913539 1229146460 2694884781 3170828030 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124205 2912985248 2694884781 2696740606 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4273778080 2694888702 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286 4278124286) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.878 0.815) #(0.972 0.815 0.627) #(0.972 0.784 0.564) #(0.972 0.784 0.47) #(0.972 0.753 0.595) #(0.972 0.753 0.501) #(0.972 0.721 0.564) #(0.972 0.721 0.501) #(0.972 0.721 0.313) #(0.972 0.69 0.439) #(0.972 0.69 0.282) #(0.972 0.658 0.408) #(0.972 0.658 0.376) #(0.972 0.658 0.156) #(0.972 0.627 0.376) #(0.972 0.627 0.345) #(0.972 0.627 0.313) #(0.972 0.627 0.125) #(0.972 0.595 0.282) #(0.972 0.595 0.094) #(0.972 0.564 0.313) #(0.972 0.564 0.219) #(0.972 0.533 0.188) #(0.972 0.533 0.125) #(0.972 0.533 0.063) #(0.972 0.533 0.031) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.219) #(0.972 0.47 0.063) #(0.972 0.47 0.031) #(0.94 0.94 0.972) #(0.94 0.94 0.94) #(0.94 0.909 0.878) #(0.94 0.753 0.627) #(0.94 0.721 0.533) #(0.94 0.69 0.501) #(0.94 0.69 0.47) #(0.94 0.658 0.501) #(0.94 0.658 0.439) #(0.94 0.627 0.47) #(0.94 0.627 0.439) #(0.94 0.627 0.408) #(0.94 0.595 0.408) #(0.94 0.595 0.376) #(0.94 0.595 0.345) #(0.94 0.564 0.376) #(0.94 0.564 0.345) #(0.94 0.564 0.282) #(0.94 0.533 0.345) #(0.94 0.533 0.25) #(0.94 0.501 0.313) #(0.94 0.501 0.282) #(0.94 0.501 0.219) #(0.94 0.501 0.188) #(0.94 0.47 0.25) #(0.94 0.47 0.188) #(0.94 0.47 0.156) #(0.94 0.47 0.0) #(0.94 0.439 0.188) #(0.94 0.439 0.094) #(0.94 0.439 0.063) #(0.94 0.439 0.0) #(0.94 0.408 0.156) #(0.94 0.408 0.125) #(0.94 0.408 0.063) #(0.94 0.408 0.031) #(0.94 0.408 0.0) #(0.94 0.376 0.094) #(0.94 0.376 0.031) #(0.94 0.376 0.0) #(0.94 0.345 0.063) #(0.94 0.313 0.031) #(0.94 0.313 0.0) #(0.909 0.784 0.627) #(0.909 0.721 0.564) #(0.909 0.658 0.47) #(0.909 0.658 0.408) #(0.909 0.627 0.47) #(0.909 0.627 0.439) #(0.909 0.595 0.408) #(0.909 0.595 0.376) #(0.909 0.564 0.282) #(0.909 0.533 0.345) #(0.909 0.501 0.188) #(0.909 0.47 0.156) #(0.909 0.408 0.188) #(0.909 0.408 0.063) #(0.909 0.408 0.0) #(0.909 0.376 0.156) #(0.909 0.376 0.063) #(0.909 0.345 0.031) #(0.909 0.345 0.0) #(0.909 0.313 0.031) #(0.909 0.282 0.0) #(0.878 0.878 0.909) #(0.878 0.878 0.878) #(0.878 0.847 0.847) #(0.878 0.847 0.815) #(0.878 0.815 0.753) #(0.878 0.784 0.721) #(0.878 0.721 0.595) #(0.878 0.658 0.501) #(0.878 0.627 0.501) #(0.878 0.595 0.47) #(0.878 0.533 0.376) #(0.878 0.533 0.313) #(0.878 0.533 0.219) #(0.878 0.501 0.313) #(0.878 0.501 0.282) #(0.878 0.501 0.25) #(0.878 0.47 0.313) #(0.878 0.47 0.282) #(0.878 0.47 0.25) #(0.878 0.47 0.219) #(0.878 0.47 0.188) #(0.878 0.439 0.25) #(0.878 0.439 0.219) #(0.878 0.439 0.188) #(0.878 0.439 0.156) #(0.878 0.439 0.125) #(0.878 0.439 0.094) #(0.878 0.408 0.156) #(0.878 0.408 0.125) #(0.878 0.376 0.125) #(0.878 0.345 0.094) #(0.878 0.313 0.0) #(0.878 0.282 0.0) #(0.847 0.847 0.847) #(0.847 0.815 0.815) #(0.847 0.69 0.627) #(0.847 0.627 0.408) #(0.847 0.595 0.408) #(0.847 0.564 0.345) #(0.847 0.564 0.313) #(0.847 0.501 0.345) #(0.847 0.501 0.25) #(0.847 0.439 0.282) #(0.847 0.439 0.219) #(0.847 0.408 0.156) #(0.847 0.408 0.125) #(0.847 0.345 0.063) #(0.847 0.313 0.063) #(0.815 0.815 0.847) #(0.815 0.815 0.815) #(0.815 0.784 0.753) #(0.815 0.69 0.595) #(0.815 0.69 0.564) #(0.815 0.658 0.564) #(0.815 0.595 0.439) #(0.815 0.533 0.408) #(0.815 0.533 0.345) #(0.815 0.501 0.313) #(0.815 0.439 0.25) #(0.815 0.408 0.219) #(0.815 0.376 0.156) #(0.815 0.345 0.125) #(0.815 0.345 0.0) #(0.815 0.313 0.0) #(0.815 0.282 0.031) #(0.815 0.282 0.0) #(0.815 0.25 0.0) #(0.784 0.784 0.753) #(0.784 0.753 0.784) #(0.784 0.721 0.69) #(0.784 0.69 0.627) #(0.784 0.658 0.595) #(0.784 0.627 0.533) #(0.784 0.501 0.345) #(0.784 0.313 0.094) #(0.784 0.313 0.0) #(0.784 0.282 0.063) #(0.784 0.282 0.031) #(0.784 0.25 0.0) #(0.753 0.753 0.753) #(0.753 0.69 0.658) #(0.753 0.658 0.564) #(0.753 0.595 0.501) #(0.753 0.25 0.0) #(0.721 0.721 0.721) #(0.721 0.69 0.69) #(0.721 0.595 0.564) #(0.721 0.595 0.533) #(0.721 0.408 0.156) #(0.69 0.313 0.125) #(0.69 0.25 0.031) #(0.69 0.25 0.0) #(0.69 0.219 0.0) #(0.658 0.345 0.188) #(0.658 0.313 0.125) #(0.658 0.282 0.094) #(0.658 0.25 0.063) #(0.658 0.219 0.0) #(0.627 0.313 0.156) #(0.627 0.25 0.063) #(0.627 0.219 0.031) #(0.595 0.376 0.282) #(0.595 0.25 0.063) #(0.595 0.188 0.0) #(0.564 0.533 0.533) #(0.564 0.219 0.063) #(0.564 0.188 0.0) #(0.533 0.533 0.533) #(0.533 0.501 0.501) #(0.533 0.156 0.0) #(0.47 0.439 0.439) #(0.47 0.408 0.345) #(0.47 0.345 0.313) #(0.47 0.282 0.188) #(0.47 0.219 0.031) #(0.47 0.188 0.031) #(0.47 0.156 0.0) #(0.439 0.408 0.376) #(0.439 0.219 0.125) #(0.439 0.188 0.094) #(0.439 0.156 0.063) #(0.439 0.156 0.031) #(0.439 0.125 0.0) #(0.408 0.188 0.063) #(0.408 0.156 0.031) #(0.408 0.125 0.0) #(0.376 0.345 0.313) #(0.376 0.313 0.282) #(0.376 0.125 0.0) #(0.345 0.345 0.345) #(0.345 0.282 0.282) #(0.313 0.313 0.313) #(0.313 0.313 0.282) #(0.313 0.094 0.0) #(0.282 0.094 0.0) #(0.25 0.25 0.25) #(0.25 0.125 0.031) #(0.25 0.063 0.0) #(0.219 0.219 0.219) #(0.219 0.188 0.188) #(0.219 0.156 0.125) #(0.219 0.125 0.063) #(0.219 0.125 0.0) #(0.219 0.094 0.031) #(0.219 0.063 0.0) #(0.188 0.188 0.188) #(0.188 0.063 0.0) #(0.156 0.156 0.156) #(0.156 0.031 0.0) #(0.125 0.063 0.031) #(0.125 0.031 0.0) #(0.094 0.094 0.094) #(0.094 0.063 0.063) #(0.094 0.031 0.0) #(0.063 0.031 0.031) #(0.063 0.0 0.0) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #( ) #(0.0 0.0 0.0) ))! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 12:30'! audition: selector "self audition: #rgbAddButton" "Audition a graphic, resizing it dynamically based on its screen x location, Answering the resized icon" | resized | Sensor waitNoButton. Cursor blank show. [Sensor noButtonPressed] whileTrue:[ resized _ self graphicNamed: selector resizedTo: Sensor cursorPoint. resized follow:[Sensor cursorPoint] while:[false]]. Cursor normal show. ^resized! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 13:14'! graphicNamed: selector resizedTo: anExtentPoint "(self graphicNamed: #rgbAddButton resizedTo: 16@16) followCursor" "(self graphicNamed: #rgbAddButton resizedTo: 400@400) followCursor" | base resized | base _ self perform: selector. resized _ base scaledToSize: anExtentPoint. resized offset: (base offset/ base extent) * resized offset rounded. ^resized! ! !LyGraphicsLibrary class methodsFor: 'transforming' stamp: 'ssa 8/31/2009 17:19'! graphicNamed: selector withWhitemappedTo: aColor "(self graphicNamed: #closedTwisty withWhitemappedTo: Color lightBlue) followCursor" "(self graphicNamed: #closedTwisty withWhitemappedTo: Color green) followCursor" | base | base _ self perform: selector. base mapColor: Color white to: aColor. ^base! ! !LyPluggableOutlineController methodsFor: 'selecting' stamp: 'ssa 9/9/2009 16:35'! redButtonActivity super redButtonActivity. self view twistyTargets keys detect:[:box| box containsPoint: Sensor cursorPoint] ifNone:[^self]. self model toggleSelection! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:58'! boxFor: index "Answer the rectangle in which the item is displayed." | offset | offset _ (index - 1 + (topDelimiter == nil ifTrue: [0] ifFalse: [1]))* list lineGrid. ^(self insetDisplayBox left @ (list compositionRectangle top +offset) extent: self insetDisplayBox width @ list lineGrid) insetBy: (Rectangle left: 1 right: 1 top: 1 bottom: 0)! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:52'! getChildrenSelector "Answer the value of getChildrenSelector" getChildrenSelector isNil ifTrue:[self getChildrenSelector: #subobjects]. ^ getChildrenSelector! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 10:51'! getChildrenSelector: anObject "Set the value of getChildrenSelector" getChildrenSelector _ anObject! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 3/1/2010 12:28'! indentBoxFor: index "Answer the rectangle which counds the whitespace in front of the item at this index" | itemBox indents | itemBox _ self boxFor: index. indents _ self indentFor:(self objects at: index). ^itemBox width: (Paragraph withText: indents asText style: self textStyle) boundingBox width.! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 14:42'! indentFor: anItem | aStream | aStream _ WriteStream on:''. (self levelOf: anItem) timesRepeat:[aStream tab]. ^aStream contents,' '! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/10/2009 16:00'! labelForItem: anItem "Subclasses may want to override" ^(self indentFor: anItem),anItem outlineString! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:59'! levelOf: anItem ^self model levelOf: anItem! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:25'! twistyTargets "Answer the value of twistyTargets" twistyTargets isNil ifTrue:[self twistyTargets: Dictionary new]. ^ twistyTargets! ! !LyPluggableOutlineView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:24'! twistyTargets: anObject "Set the value of twistyTargets" twistyTargets _ anObject! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 9/11/2009 17:06'! displayTwisties | box isOpen twisty to firstIndex | firstIndex _ self firstShown. firstIndex to: ((self list numberOfLines - 2)min:(firstIndex + self numSelectionsInView )) do:[:index| (self model hasChildren: (self objects at: index)) ifTrue:[ box _ self indentBoxFor: index. isOpen _ self model isOpen:(self objects at: index). twisty _ isOpen ifTrue:[self openedTwistyIcon]ifFalse:[self closedTwistyIcon]. twisty displayOn: Display at: (to_box topRight - (twisty width@0)) clippingBox: (box intersect: self clippingBox) rule: Form paint fillColor: nil. self twistyTargets at:(to extent: twisty extent) put: index]].! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 1/22/2010 14:03'! displayView self list foregroundColor: self foregroundColor backgroundColor: self backgroundColor. self list displayOn: Display at: self insetDisplayBox origin - (0@self scrollCache) clippingBox: self insetDisplayBox. (self insetDisplayBox copy areasOutside: (self insetDisplayBox origin extent: self list compositionRectangle extent )) do:[:box| Display fill: box fillColor: Color white]. self displayTwisties. ! ! !LyPluggableOutlineView methodsFor: 'displaying' stamp: 'ssa 11/25/2009 12:55'! positionList list wrappingBox: self wrappingBox clippingBox: self clippingBox! ! !LyPluggableOutlineView methodsFor: 'icons' stamp: 'ssa 9/9/2009 13:33'! closedTwistyIcon ^LyGraphicsLibrary selfTwistyClosed! ! !LyPluggableOutlineView methodsFor: 'icons' stamp: 'ssa 9/9/2009 13:33'! openedTwistyIcon ^LyGraphicsLibrary selfTwistyOpen! ! !LyPluggableOutlineView methodsFor: 'scrolling support' stamp: 'ssa 11/25/2009 12:36'! scrollBy: anInteger super scrollBy: anInteger . self displayTwisties. ^true! ! !LyPluggableOutlineView methodsFor: 'controller access' stamp: 'ssa 9/9/2009 16:34'! defaultControllerClass ^LyPluggableOutlineController! ! !LyPluggableOutlineView methodsFor: 'controller access' stamp: 'ssa 9/9/2009 16:28'! defaultCsntrollerClass ^LyPluggableOutlineController! ! !MSWLookTransporter methodsFor: 'initializing' stamp: 'sm 3/10/2011 12:25'! initialize self initializePackage. self initializePreambleAndPostscript. self initializeTeam.! ! !MSWLookTransporter methodsFor: 'initializing' stamp: 'sm 3/9/2011 16:48'! initializePackage self package: (PackageInfo named: 'Interface-MSWLook').! ! !MSWLookTransporter methodsFor: 'initializing' stamp: 'sm 3/11/2011 11:34'! initializePreambleAndPostscript self preambleBlock: [:file | PackageWhoseContentsMustBeTransportedInOrder new saveClassAndMethodModificationsInOrder: self trickyModificationsThatNeedToBeDoneInOrder on: file]; postscriptBlock: [:file | file nextPutAll: '"Just using some of the things of the MSWLook, not the actual systems view."'; cr. file nextPutAll: 'MSWSystemView unInstall.'; cr. ].! ! !MSWLookTransporter methodsFor: 'initializing' stamp: 'sm 3/9/2011 17:05'! initializeTeam self team: (ProjectTeam new initialsOfProjectMembers: {'dmu'. 'smu'. 'ssa'. 'ads'. 'sm'. 'piv'. 'max'}; "The Renaissance image is based on Squeak 3.7, which was put out in 2004; the Renaissance project started in 2007 or 2008. I don't understand why some of our methods are stamped 1970, though. -- Adam" timestampFilter: [:t | t year > 2005 or: [t year = 1970]]; yourself).! ! !MSWLookTransporter methodsFor: 'initializing' stamp: 'sm 5/31/2011 14:14'! trickyModificationsThatNeedToBeDoneInOrder "TODO: STEFAN find a better way to manage these changes, don't want to change method category, and this seems to be the only way for now to track those changes to core" ^ { { 'ScrollController'. 'controlInitialize' }. { 'ScrollController'. 'controlTerminate' }. { 'ScrollController'. 'controlActivity' }. { 'ScrollController'. 'isControlActive' }. { 'ScrollController'. 'moveMarker' }. { 'ScrollController'. 'moveMarkerTo:' }. { 'StandardSystemView class'. 'new' }. { 'StandardSystemController' }. { 'StandardSystemController'. 'adjustWindowCorners' }. { 'StandardSystemController'. 'checkForReframe' }. { 'StringHolderView' }. { 'StringHolderView'. 'updateDisplayContents' }. { 'StringHolderView class'. 'open:label:' }. { 'ParagraphEditor'. 'controlActivity' }. { 'ParagraphEditor'. 'scrollView:' }. { 'Preferences class'. 'enable:' }. { 'Character class'. 'arrowDown' }. { 'Character class'. 'arrowLeft' }. { 'Character class'. 'arrowRight' }. { 'Character class'. 'arrowUp' }. { 'Character class'. 'escape' }. { 'Character class'. 'nbsp' }. { 'Character class'. 'pageDown' }. { 'Character class'. 'pageUp' }. { 'PluggableTextView class'. 'on:text:accept:readSelection:menu:' }. { 'PluggableListView class'. 'on:list:selected:changeSelected:menu:keystroke:' }. { 'DisplayTextView class'. 'open:label:' }. { 'DisplayTextView class'. 'example2' }. { 'FileList class'. 'open' }. { 'ParagraphEditor'. 'updateMarker' }. { 'View'. 'unlock' }. }! ! !MSWScrollBarController methodsFor: 'delays' stamp: 'ssa 1/15/98 13:51'! defaultUnitScrollDelay "Answer the delay to use when unit scrolling, i.e., pressing the up or down button." ^Delay forMilliseconds: 50! ! !MSWScrollBarController methodsFor: 'delays' stamp: 'ssa 1/15/98 13:52'! wait self defaultUnitScrollDelay wait! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 8/22/2009 15:13'! elevatorBox "Compute this each time since the view content my change." | box originY extentY | box _ self view elevatorShaft. extentY _ self viewToScroll percentVisibleContent * box height. originY _ (self viewToScroll percentPreceedingContent * box height) min: box height - extentY. ^(box origin x asInteger @ (box origin y + originY) asInteger max: box origin) extent: ((box extent x asInteger @ extentY asInteger) min: box extent max: 10@box width)! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 12/5/97 16:00'! scroller ^self viewToScroll controller! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 1/15/98 13:50'! unitScrollDelay "<^hOf Delay>" "ssa 1/15/98 13:50 - Answer the instance variable, unitScrollDelay" unitScrollDelay isNil ifTrue:[self unitScrollDelay: self defaultUnitScrollDelay]. ^unitScrollDelay! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 1/15/98 13:50'! unitScrollDelay: aDelay "<aDelay: hOf Delay, ^self>" "ssa 1/15/98 13:50 - Set unitScrollDelay to be aDelay." unitScrollDelay _ aDelay! ! !MSWScrollBarController methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:40'! viewToScroll ^self view subViews first! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:07'! pageDown "Scroll down by one page length." self scroller scrollView: self pageHeight negated. self view updateElevator! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:00'! pageHeight "Answer the height of a page for the scrolling view." ^self viewToScroll displayBox height! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 8/27/2009 07:11'! pageUp "Scroll up by one page length." self scroller scrollView: self pageHeight. self view updateElevator! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'stp 2/18/98 13:50'! reallyScrollAbsolute | height center offset | center _ self view elevatorBox center y. offset _ (center - Sensor cursorPoint y). height _ self view elevatorShaft height. (self viewToScroll percentPreceedingContent ~= 0.0 or: [self viewToScroll percentVisibleContent < 1.0]) ifTrue:[self scroller scrollView: ((offset / height) * (self scroller view totalContentHeight * self scroller view unitContentHeight)) asInteger. self view updateElevator]! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'stp 2/18/98 13:53'! scrollAbsolute | lastY thisY | [Sensor redButtonPressed] whileTrue: [thisY := Sensor cursorPoint y. lastY isNil ifTrue: [lastY := thisY. self reallyScrollAbsolute] ifFalse: [lastY = thisY ifFalse: [lastY := thisY. self reallyScrollAbsolute]]]! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 1/15/98 13:54'! unitDown "Scroll down by one content unit." self view displayDownButtonPressed. [Sensor redButtonPressed] whileTrue:[ self scroller scrollView: self unitHeight negated. self view updateElevator. self wait]. self view displayDownButton. ! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 12/5/97 16:00'! unitHeight "Answer the height of a content unit for the scrolling view." ^self viewToScroll unitContentHeight! ! !MSWScrollBarController methodsFor: 'scrolling' stamp: 'ssa 1/15/98 13:54'! unitUp "Scroll up by one content unit." self view displayUpButtonPressed. [Sensor redButtonPressed] whileTrue:[ self scroller scrollView: self unitHeight. self view updateElevator. self wait]. self view displayUpButton. ! ! !MSWScrollBarController methodsFor: 'control activity' stamp: 'ssa 1/8/98 16:28'! controlActivity "Refer to the comment in Controller|controlActivity." (Sensor redButtonPressed and:[self view scrollBarBox containsPoint: Sensor cursorPoint]) ifTrue: [^self redButtonActivity]. super controlActivity ! ! !MSWScrollBarController methodsFor: 'control activity' stamp: 'ssa 8/27/2009 04:44'! redButtonActivity | point | " self scroller view visibleContentHeight >= (self scroller view totalContentHeight + 2) ifTrue:[^self]." point _ Sensor cursorPoint. (self view upButtonBox containsPoint: point) ifTrue:[^self unitUp]. (self view downButtonBox containsPoint: point) ifTrue:[^self unitDown]. (self view elevatorBox containsPoint: point) ifTrue:[^self scrollAbsolute]. self view elevatorBox center y > point y ifTrue:[self wait. self pageUp] ifFalse:[self wait. self pageDown]. ! ! !MSWScrollBarController methodsFor: 'delegation' stamp: 'ssa 8/21/2009 12:55'! doesNotUnderstand: aMessage "Here it comes, the dreaded doesNotUnderstand: HACK ssa 1/23/98 14:55" ^self viewToScroll controller perform: aMessage selector withArguments: aMessage arguments! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 11/30/2009 17:33'! backgroundColor: aColor "Blow the caches" super backgroundColor: aColor. self elevatorCache:nil. self downButtonCache: nil. self upButtonCache: nil. ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 12:24'! downButtonBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, downButtonBox" downButtonBox isNil ifTrue:[self downButtonBox: self determineDownButtonBox]. ^downButtonBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! downButtonBox: aRectangle "<aRectangle: hOf Rectangle, ^self>" "ssa 12/5/97 11:15 - Set downButtonBox to be aRectangle." downButtonBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:46'! downButtonCache "<^hOf Form>" "ssa 12/11/97 11:43 - Answer the instance variable, downButtonCache" downButtonCache isNil ifTrue:[self downButtonCache: (Form extent:1@1)]. ^downButtonCache! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:43'! downButtonCache: aColorForm "<aColorForm: hOf ColorForm, ^self>" "ssa 12/11/97 11:43 - Set downButtonCache to be aColorForm." downButtonCache _ aColorForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 16:29'! elevatorBox "Answer the rectangle for the elevator." ^self controller elevatorBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 9/9/2009 16:45'! elevatorCache "<^hOf Form>" "ssa 12/10/97 16:32 - Answer the instance variable, elevatorCache" elevatorCache isNil ifTrue:[self elevatorCache: (Form extent:1@1)]. ^elevatorCache ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/10/97 16:32'! elevatorCache: aForm "<aForm: hOf Form, ^self>" "ssa 12/10/97 16:32 - Set elevatorCache to be aForm." elevatorCache _ aForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:18'! elevatorShaft "<^hOf Rectangle>" "ssa 12/5/97 14:18 - Answer the instance variable, elevatorShaft" elevatorShaft isNil ifTrue:[self elevatorShaft: self determineElevatorShaft]. ^elevatorShaft! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 14:18'! elevatorShaft: aRectangle "<aRectangle: hOf Rectangle, ^self>" "ssa 12/5/97 14:18 - Set elevatorShaft to be aRectangle." elevatorShaft _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 12:43'! getWindow "This is here to break a recursive loop caused by the indirection of my display transformation." self window isNil ifTrue:[self window: Display boundingBox]. ^self window! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 8/27/2009 04:51'! model: aModel model ~~ nil & (model ~~ aModel) ifTrue: [model removeDependent: self]. aModel ~~ nil & (aModel ~~ model) ifTrue: [aModel addDependent: self]. model _ aModel. ! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:28'! scrollBarBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, scrollBarBox" scrollBarBox isNil ifTrue:[self scrollBarBox: self determineScrollBarBox]. ^scrollBarBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! scrollBarBox: aRectangle "<aRectangle: hOf Rectangle, ^self>" "ssa 12/5/97 11:15 - Set scrollBarBox to be aRectangle." scrollBarBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/10/97 14:05'! scrollBarWidth "<^hOf Integer>" "ssa 12/5/97 11:27 - Answer the instance variable, scrollBarWidth" scrollBarWidth isNil ifTrue:[self scrollBarWidth: 12]. ^scrollBarWidth! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:27'! scrollBarWidth: anInteger "<anInteger: hOf Integer, ^self>" "ssa 12/5/97 11:27 - Set scrollBarWidth to be anInteger." scrollBarWidth _ anInteger! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 1/24/98 16:06'! scrollingView ^self subViews isEmpty ifTrue:[nil] ifFalse:[self subViews first]! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 13:59'! upButtonBox "<^hOf Rectangle>" "ssa 12/5/97 11:15 - Answer the instance variable, upButtonBox" upButtonBox isNil ifTrue:[self upButtonBox: self determineUpButtonBox]. ^upButtonBox! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/5/97 11:15'! upButtonBox: aRectangle "<aRectangle: hOf Rectangle, ^self>" "ssa 12/5/97 11:15 - Set upButtonBox to be aRectangle." upButtonBox _ aRectangle! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:46'! upButtonCache "<^hOf Form>" "ssa 12/11/97 11:43 - Answer the instance variable, upButtonCache" upButtonCache isNil ifTrue:[self upButtonCache: (Form extent:1@1)]. ^upButtonCache! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 11:43'! upButtonCache: aColorForm "<aColorForm: hOf ColorForm, ^self>" "ssa 12/11/97 11:43 - Set upButtonCache to be aColorForm." upButtonCache _ aColorForm! ! !MSWScrollBarView methodsFor: 'accessing' stamp: 'ssa 12/11/97 12:44'! window "This is here to break a recursive loop caused by the indirection of my display transformation." window isNil ifTrue:[self window: Display boundingBox]. ^window! ! !MSWScrollBarView methodsFor: 'bordering' stamp: 'ssa 1/24/98 16:05'! borderWidth: anything super borderWidth:1. ! ! !MSWScrollBarView methodsFor: 'control defaults' stamp: 'stp 02/18/98 0-11:'! defaultControllerClass ^MSWScrollBarController! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 1/23/98 14:56'! doesNotUnderstand: aMessage "Here it comes, the dreaded doesNotUnderstand: HACK ssa 1/23/98 14:55" ^self scrollingView perform: aMessage selector withArguments: aMessage arguments! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 3/24/2010 14:37'! update: aSymbol self topView ifNotNil:[self topView isCollapsed ifFalse:[self updateElevator]]. super update: aSymbol. "self subViews do:[:each| each update: aSymbol]"! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 1/21/2010 12:24'! update: aSymbol with: aValue self updateElevator. super update: aSymbol with: aValue. "self subViews do:[:each| each update: aSymbol with: aValue]"! ! !MSWScrollBarView methodsFor: 'delegation' stamp: 'ssa 8/27/2009 04:55'! updateListsAndCodeIn: aWindow self updateElevator. super updateListsAndCodeIn: aWindow. ^self subViews first updateListsAndCodeIn: aWindow! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 8/27/2009 09:29'! determineDownButtonBox "Answer the rectangle for the scroll bar down button." ^self scrollBarBox corner - self scrollBarBox width asPoint extent: (self scrollBarBox width)asPoint! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:38'! determineElevatorBox "Answer the rectangle for the scroll bar elevator." ^self scrollBarBox center - (self scrollBarWidth asPoint // 2) extent: self scrollBarWidth asPoint! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 14:19'! determineElevatorShaft "Answer the rectangle for the scroll bar down button." ^self upButtonBox bottomLeft corner: self downButtonBox topRight! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:47'! determineScrollBarBox "Answer the rectangle for the scroll bar region." ^(self realInsetDisplayBox areasOutside: self insetDisplayBox) first! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/5/97 12:52'! determineUpButtonBox "Answer the rectangle for the scroll bar up button." ^self scrollBarBox origin extent: self scrollBarBox width asPoint! ! !MSWScrollBarView methodsFor: 'display box access'! displayBox "tah -- (17 July 1989 6:37:46 pm ) -- Answer the real displayBox" ^self realInsetDisplayBox expandBy: borderWidth! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:10'! insetDisplayBox "Answer the inset displayBox reduced by the horizontal space for the scroll bar" ^WhereToLocateScrollBars = #left ifTrue:[self insetDisplayBoxLeft] ifFalse:[self insetDisplayBoxRight]! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:09'! insetDisplayBoxLeft "Answer the inset displayBox reduced by the horizontal space for the scroll bar" | box | box _ self realInsetDisplayBox. ^box origin extent: box width - (self borderWidth left + self scrollBarWidth) @ box height ! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 2/27/98 11:10'! insetDisplayBoxRight "Answer the inset displayBox reduced by the horizontal space for the scroll bar" "Changed to left-side scroll bars--stp." "MSWScrollBarView someInstance" | box | box _ self realInsetDisplayBox. ^((box left + self scrollBarWidth) @ box top) extent: (box width - (self borderWidth left + self scrollBarWidth) @ box height) ! ! !MSWScrollBarView methodsFor: 'display box access' stamp: 'ssa 12/15/97 14:50'! realInsetDisplayBox "tah -- (17 July 1989 6:05:48 pm ) -- answer the real inset displayBox " ^super insetDisplayBox! ! !MSWScrollBarView methodsFor: 'display transformation'! displayTransform: anObject "Apply the display transformation of the receiver to anObject (see View|displayTransformation) and answer the resulting scaled, translated object. It is normally applied to Rectangles, Points, and other objects with coordinates defined in the View's local coordinate system in order to get a corresponding object in display coordinates." ^(self realDisplayTransformation applyTo: anObject) rounded! ! !MSWScrollBarView methodsFor: 'display transformation' stamp: 'ssa 12/15/97 14:49'! displayTransformation "This is a hook for to get the real displayTransformation" ^self scrollBarWidth = 0 ifTrue: [self realDisplayTransformation] ifFalse: [WindowingTransformation window: self getWindow viewport: (self realInsetDisplayBox expandBy: self borderWidth)]! ! !MSWScrollBarView methodsFor: 'display transformation'! realDisplayTransformation "This is a hook for labeledView to get the real displayTransformation" ^super displayTransformation! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:44'! deEmphasizeView super deEmphasizeView ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 12/11/97 13:13'! displayDownButton | box | box _ self downButtonBox. self downButtonCache extent = box extent ifFalse:[self drawDownButton]. self downButtonCache displayOn: Display at: box origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 1/20/98 21:45'! displayDownButtonPressed | box cf bb | box _ self downButtonBox. Display fill: box fillColor: Color darkGray. Display fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 260046848 117440512 33554432 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: Display sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 2 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 17:02'! displayElevatorOn: aForm | box shaft | box _ self elevatorBox. shaft _ self elevatorShaft. self elevatorCache extent = box extent ifFalse:[self drawElevator]. self elevatorCache displayOn: aForm at: box origin - shaft origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:52'! displayElevatorShaftOn: aForm | box | box _ self elevatorShaft. aForm fill: (0@0 extent: box extent) fillColor: self backgroundColor darker darker ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 12/11/97 13:18'! displayUpButton | box | box _ self upButtonBox. self upButtonCache extent = box extent ifFalse:[self drawUpButton]. self upButtonCache displayOn: Display at: box origin! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 1/20/98 21:45'! displayUpButtonPressed | box cf bb | box _ self upButtonBox. Display fill: box fillColor: Color darkGray. Display fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 33554432 117440512 260046848 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: Display sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 2 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:58'! displayView self displayUpButton. self displayDownButton. self updateElevator ! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/27/2009 09:30'! drawDownButton | box pen cf bb form | form _ Form extent: self downButtonBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color black. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 260046848 117440512 33554432 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: form sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 1 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits. self downButtonCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/21/2009 13:03'! drawElevator | box pen form | form _ Form extent: self controller elevatorBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: self backgroundColor. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. self elevatorCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 8/21/2009 13:03'! drawUpButton | box pen cf bb form | form _ Form extent: self upButtonBox extent depth: Display depth. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: self backgroundColor. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color black. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color black. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: self backgroundColor. cf _ ColorForm mappingWhiteToTransparentFrom: (Form extent: 13 @ 13 depth: 1 fromArray: #(0 0 0 0 0 33554432 117440512 260046848 0 0 0 0 0 ) offset: 0 @ 0). bb _ BitBlt destForm: form sourceForm: cf fillColor: Color black combinationRule: Form paint destOrigin: box origin + 1 sourceOrigin: 0 @ 0 extent: cf extent clipRect: box truncated. bb copyBits. self upButtonCache: form! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 16:46'! emphasizeView self displayView. super emphasizeView! ! !MSWScrollBarView methodsFor: 'displaying' stamp: 'ssa 9/9/2009 15:18'! updateElevator | newForm | newForm _ Form fromDisplay: self elevatorShaft. self displayElevatorShaftOn: newForm. self displayElevatorOn: newForm. newForm displayOn: Display at: self elevatorShaft origin! ! !MSWScrollBarView methodsFor: 'lock access' stamp: 'ssa 12/5/97 16:10'! unlock "Flush the cache." self scrollBarBox: nil. self upButtonBox: nil. self downButtonBox: nil. self elevatorShaft: nil. super unlock! ! !MSWScrollBarView methodsFor: 'subview additions' stamp: 'ssa 1/15/98 15:50'! addSubView: aView in: aRelativeRectangle borderWidth: width "11/3/96 ssa - added for compatibility." "Make 'aView' into a subview. Use 'aRelativeRectangle' and the super view's window to compute (1) a viewport within the superview for 'aView' and (2) the window extent for 'aView'. Note: defining the windowing transformation and deriving the viewport is logically equivalent but does not seem to be easily done" | subViewPort myWindow myExtent myOrigin | self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']. aView borderWidth: width. myWindow _ self window. myExtent _ myWindow extent. myOrigin _ myWindow origin. subViewPort _ myExtent * aRelativeRectangle origin + myOrigin corner: myExtent * aRelativeRectangle corner + myOrigin. aView window: aView window viewport: subViewPort ! ! !MSWScrollBarView methodsFor: 'subview additions' stamp: 'ssa 8/27/2009 04:49'! on: aView "tah -- (17 July 1989 7:17:34 pm ) -- Add a subview to this view" self on: aView borderWidth: 0. self model: aView model! ! !MSWScrollBarView methodsFor: 'subview additions'! on: aView borderWidth: aBorderWidth "tah -- (17 July 1989 7:17:34 pm ) -- Add a subview to this view" self addSubView: aView in: (0@0 extent: (1@1)) borderWidth: aBorderWidth! ! !MSWScrollBarView methodsFor: 'testing' stamp: 'ssa 1/8/98 16:13'! containsPoint: aPoint "Overriden to access my real insetDsiplayBox" ^ self realInsetDisplayBox containsPoint: aPoint! ! !MSWScrollBarView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 15:07'! on: aScrollingView "<aScrollingView: {hOf ListView | hOf TextView | hOf StringHolderView | hOf ParagraphEditor | hOf CodeView | hOf PPSListView | hOf SelectionInListView}, ^iOf self>" "Answer an instance of me that encapsulates aScrollingView by providing Windows-style scroll bars" ^aScrollingView class == self class "prevent scrollbars on scrolbars" ifTrue:[aScrollingView error:'should never try to embed scrollbar views'] ifFalse:[self new on: aScrollingView]! ! !MSWScrollBarView class methodsFor: 'class initialization' stamp: 'ssa 1/5/2010 18:10'! initialize "Make an initial decision as to which side to locate the scrollbars. See preferences to change sides." self locateScrollBarsOnRightSide! ! !MSWScrollBarView class methodsFor: 'preferences' stamp: 'ssa 2/27/98 11:40'! locateScrollBarsOnLeftSide "Set the flag to locate the ScrollBars on the left hand side of the view." "MSWScrollBarView locateScrollBarsOnLeftSide" | openWindows | WhereToLocateScrollBars _ #left. self allInstances do:[:each| each unlock]. openWindows _ ScheduledControllers controllersSatisfying: [:each| (each view respondsTo:#isCollapsed) and:[each view isCollapsed not]]. openWindows reverseDo:[:each| each view uncacheBits display]. ScheduledControllers restore! ! !MSWScrollBarView class methodsFor: 'preferences' stamp: 'ssa 2/27/98 11:39'! locateScrollBarsOnRightSide "Set the flag to locate the ScrollBars on the right hand side of the view." "MSWScrollBarView locateScrollBarsOnRightSide" | openWindows | WhereToLocateScrollBars _ #right. self allInstances do:[:each| each unlock]. openWindows _ ScheduledControllers controllersSatisfying: [:each| (each view respondsTo:#isCollapsed) and:[each view isCollapsed not]]. openWindows reverseDo:[:each| each view uncacheBits display]. ScheduledControllers restore! ! !MSWSystemController methodsFor: 'accessing' stamp: 'ar 1/22/98 23:30'! lastSystemActivity ^lastSystemActivity ifNil:[lastSystemActivity _ 0]! ! !MSWSystemController methodsFor: 'accessing' stamp: 'ar 1/22/98 23:30'! lastSystemActivity: aNumber lastSystemActivity _ aNumber! ! !MSWSystemController methodsFor: 'basic control sequence' stamp: 'ssa 9/11/2009 16:36'! redButtonActivity | box p | p _ sensor cursorPoint. ((box _ view systemBoxFrame) containsPoint: p) ifTrue: [^self systemActivity]. ((box _ view shrinkBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [self collapse. ^ self]. ^ self]. ((box _ view growBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [view isCollapsed ifTrue:[self expand] ifFalse:[view isFullScreen ifTrue:[self restore] ifFalse:[self fullScreen]]. ^ self]. ^ self]. super redButtonActivity.! ! !MSWSystemController methodsFor: 'basic control sequence' stamp: 'ar 1/22/98 23:33'! systemActivity "The system menu button has been pressed" | time | time _ Time millisecondClockValue. (time- self lastSystemActivity) < self doubleClickTime ifTrue:[^self close]. self lastSystemActivity: time. ^self blueButtonActivity! ! !MSWSystemController methodsFor: 'menu messages' stamp: 'ar 1/22/98 22:41'! restore view restore! ! !MSWSystemController methodsFor: 'private' stamp: 'ar 1/22/98 23:32'! doubleClickTime "Return the maximum delay time for double clicks. This value is in milliseconds." ^500! ! !MSWSystemController methodsFor: 'borders' stamp: 'ssa 1/25/98 00:00'! adjustWindowCorners | box cornerBox p clicked f2 | box _ view windowBox. clicked _ false. #(topLeft topRight bottomRight bottomLeft) do: [:readCorner | cornerBox _ ((box insetBy: 2) perform: readCorner) - (4@4) extent: 8@8. (cornerBox containsPoint: sensor cursorPoint) ifTrue: ["Display reverse: cornerBox." (Cursor perform: readCorner) showWhile: [[(cornerBox containsPoint: (p _ sensor cursorPoint)) and: [(clicked _ sensor anyButtonPressed) not]] whileTrue. "Display reverse: cornerBox." clicked ifTrue: [view newFrame: [:f | p _ sensor cursorPoint. readCorner = #topLeft ifTrue: [f2 _ p corner: f bottomRight]. readCorner = #bottomLeft ifTrue: [f2 _ (f withBottom: p y) withLeft: p x]. readCorner = #bottomRight ifTrue: [f2 _ f topLeft corner: p]. readCorner = #topRight ifTrue: [f2 _ (f withTop: p y) withRight: p x]. f2]]]]]. ^ clicked! ! !MSWSystemController methodsFor: 'borders' stamp: 'ssa 1/24/98 23:47'! cursorOnBorder | cp i box | view isCollapsed ifTrue: [^ false]. cp _ sensor cursorPoint. ((view labelDisplayBox insetBy: 5@5) containsPoint: cp) ifTrue: [^ false]. (i _ view subViews findFirst: [:v | v displayBox containsPoint: cp]) = 0 ifTrue: [box _ view windowBox] ifFalse: [box _ (view subViews at: i) insetDisplayBox]. ^ ((box insetBy: 3) containsPoint: cp) not and: [(box expandBy: 4) containsPoint: cp]! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 3/24/2010 16:03'! closeBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (boxHeight negated-9@7)) extent: boxHeight+2@boxHeight "MSWSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:35'! growBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (2*boxHeight negated-12@7)) extent: boxHeight+2@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 2/6/98 14:24'! labelHeight ^self isCollapsed ifFalse:[18 + 6] ifTrue:[(LabelStyle fontAt: 2) height + 14]! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:56'! labelTextRegion labelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0]. ^ (labelText boundingBox align: labelText boundingBox leftCenter with: self labelDisplayBox leftCenter + (25@0)) intersect: (self labelDisplayBox origin corner: self labelDisplayBox corner - (55@0))! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:34'! shrinkBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11. ^ Rectangle origin: (self labelDisplayBox topRight + (3*boxHeight negated-15@7)) extent: boxHeight+2@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'label accessing' stamp: 'ssa 1/24/98 23:17'! systemBoxFrame | boxHeight | boxHeight _ self labelDisplayBox height - 11 . ^ Rectangle origin: (self labelDisplayBox origin + (7@7)) extent: boxHeight@boxHeight "NiceSystemView initializeCache"! ! !MSWSystemView methodsFor: 'framing' stamp: 'stp 02/18/98 0-15:'! collapse "If the receiver is not already collapsed, change its view to be that of its label only." self isCollapsed ifFalse: [expandedViewport _ self viewport. savedSubViews _ subViews. self resetSubViews. labelText isNil ifTrue: [self label: nil. bitsValid _ false.]. self window: (self inverseDisplayTransform: ((self labelDisplayBox topLeft extent: (labelText extent x + 80) @ self labelHeight) intersect: self labelDisplayBox))]! ! !MSWSystemView methodsFor: 'framing' stamp: 'ar 1/22/98 22:47'! fullScreen | portRect | portRect _ self viewport. growFrame _ portRect topLeft - self labelOffset corner: portRect corner. ^super fullScreen! ! !MSWSystemView methodsFor: 'framing' stamp: 'ar 1/22/98 22:49'! restore self reframeTo: ( growFrame isNil ifTrue:[self initialFrame] ifFalse:[growFrame])! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:27'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: false. self displayLabelTextDeEmphasized. self displayLabelBorder. self displayClosingGuardBoxIfNeeded. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:32'! displayClosingGuardBoxIfNeeded "display closing guard active, if true" | aRect | self controller preventClosing ifTrue:[ aRect _ self closeBoxFrame. self closingGuardIcon displayOn: Display at: aRect origin + (2@1) clippingBox: aRect rule: Form over fillColor: nil]. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:42'! displayDeEmphasizedOLD "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self displayBorder. super displayDeEmphasized. self deEmphasizeLabel! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:43'! displayEmphasizedOLD "Display with label highlighted to indicate that it is active." self displayBorder. super displayEmphasized. self emphasizeLabel ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelBackground: emphasized "Clear or emphasize the inner region of the label" emphasized ifTrue:[Display fill: self labelDisplayBox fillColor: self labelBackgroundColor] ifFalse:[Display fill: self labelDisplayBox fillColor:self labelBackgroundColor darker darker]. self displayLabelBoxes. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:25'! displayLabelBoxes CloseBoxForm ifNil:[CloseBoxForm _ self drawCloseBoxForm]. GrowBoxForm ifNil:[GrowBoxForm _ self drawGrowBoxForm]. ShrinkBoxForm ifNil:[ShrinkBoxForm _ self drawShrinkBoxForm]. SystemBoxForm ifNil:[SystemBoxForm _ self drawSystemBoxForm]. CloseBoxForm displayOn: Display at: self closeBoxFrame origin. GrowBoxForm displayOn: Display at: self growBoxFrame origin. self isCollapsed ifFalse:[ShrinkBoxForm displayOn: Display at: self shrinkBoxFrame origin]. SystemBoxForm displayOn: Display at: self systemBoxFrame origin. "display closing guard active, if true" self displayClosingGuardBoxIfNeeded. ! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelText "The label goes in the center of the window" | labelRect | labelText foregroundColor: Color black backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. "Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor." labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelTextDeEmphasized | labelRect | labelText foregroundColor: Color gray backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:41'! displayLabelTextEmphasized | labelRect | labelText foregroundColor: Color black backgroundColor: self labelBackgroundColor. labelRect _ self labelTextRegion. labelText displayOn: Display at: labelRect topLeft +(0@1) clippingBox: labelRect rule: Form under fillColor: labelText fillColor! ! !MSWSystemView methodsFor: 'displaying' stamp: 'stp 02/18/98 0-13:'! drawCloseBoxForm "Answer a thinner 'X' for the close box." "CloseBoxForm bitEdit" ^Form extent: 15@13 depth: 8 fromArray: #( 50529027 50529027 50529027 50529024 51252750 235802126 235802126 235801600 51249923 50529027 50529027 50531328 51249921 16974595 50528513 50531328 51249923 16843523 50397443 50531328 51249923 50397443 16843523 50531328 51249923 50528513 16974595 50531328 51249923 50397443 16843523 50531328 51249923 16843523 50397443 50531328 51249921 16974595 50528513 50531328 51249923 50529027 50529027 50531328 51249923 50529027 50529027 50531328 51121164 202116108 202116108 202116096) offset: 0@0! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ar 1/22/98 22:10'! drawGrowBoxForm | box pen form | form _ Form extent: self growBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. pen color: Color black. pen place: box topLeft + (3@3). pen goto: box bottomLeft + (3 @ -3). pen goto: box bottomRight + (-3 @ -3). pen goto: box topRight + (-3@3). pen defaultNib: 2. pen place: box topRight + (-4@3). pen goto: box topLeft + (3@3). ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ar 1/22/98 22:11'! drawShrinkBoxForm | box pen form | form _ Form extent: self growBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. pen color: Color black. pen defaultNib: 2. pen place: box bottomRight + (-4 @ -3). pen goto: box bottomLeft + (3 @ -3). ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 1/24/98 23:09'! drawSystemBoxForm | box pen form | form _ Form extent: self systemBoxFrame extent depth: 8. box _ form boundingBox. pen _ Pen new. pen destForm: form. pen color: Color gray. pen place: box bottomLeft. pen goto: box topLeft. pen goto: box topRight. pen color: Color veryLightGray. pen place: box bottomLeft + (1 @ 0). pen goto: box topLeft + 1. pen goto: box topRight + (0 @ 1). pen color: Color darkGray. pen place: box bottomLeft + (1 @ 1 negated). pen goto: box bottomRight - (1 @ 1). pen goto: box topRight + (1 negated @ 1). pen color: Color black. pen place: box bottomLeft. pen goto: box bottomRight. pen goto: box topRight. form fill: (box origin + (2 @ 2) corner: box corner - (1 @ 1)) fillColor: Color gray. ^form! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 1/24/98 22:49'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self displayLabelBackground: true. self displayLabelBoxes. self displayLabelTextEmphasized. self displayLabelBorder! ! !MSWSystemView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 15:44'! labelBackgroundColor ^Color veryLightGray lighter! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:30'! baseColor ^Color gray ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:34'! borderBox: box Display border: (box insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 0@0) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (box insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (box insetBy: 1@1) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker . Display border: (box insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 2@2) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor lighter. ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:39'! borderBoxNoBottom: box Display border: (box insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 0@0) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (box insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (box insetBy: 1@1) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor darker . Display border: (box insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (box insetBy: 2@2) widthRectangle: (0@0 corner: 1@0) rule: Form paint fillColor: self baseColor lighter. ! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 9/4/1998 16:52'! borderWidth: anInteger "Override to support standard borders"! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:33'! displayBorder "Display the receiver's border (using the receiver's borderColor)." | | self isCollapsed ifTrue:[^self]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBox: self displayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/24/2010 17:09'! displayBorderOLD "Display the receiver's border (using the receiver's borderColor)." | box | self isCollapsed ifTrue:[^self]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [box _ self displayBox. "left edge" Display fill: (box origin extent: 1@(box height - 1)) fillColor: Color gray. Display fill: (box origin +(1@1) extent: 1@(box height - 2)) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: 2@(box height-4)) fillColor: Color gray. Display fill: (box origin +(4@3) extent: 1@(box height-6)) fillColor: Color veryDarkGray. Display fill: (box origin +(5@4) extent: 1@(box height-8)) fillColor: Color black. "right edge" Display fill: (box topRight -(1@0)extent: 1@(box height - 1)) fillColor: Color black. Display fill: (box topRight +(-2@1) extent: 1@(box height - 2)) fillColor: Color veryDarkGray. Display fill: (box topRight +(-4@2) extent: 2@(box height-4)) fillColor: Color gray. Display fill: (box topRight +(-5@5) extent: 1@(box height-10)) fillColor: Color veryLightGray. Display fill: (box topRight +(-6@6) extent: 1@(box height-12)) fillColor: Color gray. "top edge" Display fill: (box origin extent: box width@1) fillColor: Color gray. Display fill: (box origin +(1@1) extent: (box width - 2)@1) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box origin +(4@4) extent: (box width-8)@1) fillColor: Color veryDarkGray. Display fill: (box origin +(5@5) extent: (box width-10)@1) fillColor: Color black. "bottom edge" Display fill: (box bottomLeft -(0@1) extent: box width @1) fillColor: Color black. Display fill: (box bottomLeft +(1 @ -2) extent: (box width - 2)@1) fillColor: Color veryDarkGray. Display fill: (box bottomLeft +(2 @ -4) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box bottomLeft +(4 @ -5) extent: (box width-7)@1) fillColor: Color veryLightGray. Display fill: (box bottomLeft +(5 @ -6) extent: (box width-9)@1) fillColor: Color gray. insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: self backgroundColor]]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:37'! displayCollaspedLabelBorder "Display the receiver's label border." | | borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBox: self labelDisplayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:39'! displayLabelBorder "Display the receiver's label border." | | self isCollapsed ifTrue:[^self displayCollaspedLabelBorder]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [self borderBoxNoBottom: self labelDisplayBox]! ! !MSWSystemView methodsFor: 'bordering' stamp: 'ssa 3/25/2010 14:32'! displayLabelBorderOLD "Display the receiver's label border." | box | self isCollapsed ifTrue:[^self displayCollaspedLabelBorder]. borderWidth = 0 ifTrue: [insideColor == nil ifFalse: [Display fill: self displayBox fillColor: self backgroundColor]] ifFalse: [box _ self labelDisplayBox. "left edge" Display fill: (box origin extent: 1@(box height)) fillColor: Color gray. Display fill: (box origin +(1@1) extent: 1@(box height)) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: 2@(box height)) fillColor: Color gray. Display fill: (box origin +(4@3) extent: 1@(box height)) fillColor: Color veryDarkGray. Display fill: (box origin +(5@4) extent: 1@(box height)) fillColor: Color black. "right edge" Display fill: (box topRight -(1@0)extent: 1@(box height)) fillColor: Color black. Display fill: (box topRight +(-2@1) extent: 1@(box height)) fillColor: Color veryDarkGray. Display fill: (box topRight +(-4@2) extent: 2@(box height)) fillColor: Color gray. Display fill: (box topRight +(-5@5) extent: 1@(box height)) fillColor: Color veryLightGray. Display fill: (box topRight +(-6@6) extent: 1@(box height)) fillColor: Color gray. "top edge" Display fill: (box origin extent: box width@1) fillColor: Color gray. Display fill: (box origin +(1@1) extent: (box width - 2)@1) fillColor: Color veryLightGray. Display fill: (box origin +(2@2) extent: (box width-4)@2) fillColor: Color gray. Display fill: (box origin +(4@4) extent: (box width-8)@1) fillColor: Color veryDarkGray. Display fill: (box origin +(5@5) extent: (box width-10)@1) fillColor: Color black]! ! !MSWSystemView methodsFor: 'testing' stamp: 'ar 1/22/98 22:07'! cacheBitsAsTwoTone ^false! ! !MSWSystemView methodsFor: 'testing' stamp: 'ar 1/22/98 22:37'! isFullScreen | frame | frame _ model fullScreenSize. ^(frame topLeft + self labelOffset corner: frame corner) = self viewport ! ! !MSWSystemView methodsFor: 'controller access' stamp: 'stp 02/18/98 0-11:'! defaultControllerClass ^MSWSystemController! ! !MSWSystemView methodsFor: 'initialize' stamp: 'ssa 3/25/2010 14:36'! initialize "change the default border to 3 to support stylish edges." super initialize. self borderWidthLeft: 3 right: 3 top: 0 bottom: 3! ! !MSWSystemView methodsFor: 'window access' stamp: 'ssa 8/24/2009 10:13'! defaultWindow "Build the minimum Rectangle that encloses all the windows of the receiver's subViews. The answer is a Rectangle obtained by expanding this minimal Rectangle by the borderWidth of the receiver. If the receiver has no subViews, then a Rectangle enclosing the entire display screen is answered. It is used internally by View methods if no window has been specified for the View. Specialized subclasses of View should redefine View|defaultWindow to handle the default case for instances that have no subViews." | aRectangle | subViews isEmpty ifTrue: [^DisplayScreen boundingBox copy]. aRectangle _ self firstSubView viewport. subViews do: [:aView | aRectangle _ aRectangle merge: aView viewport]. ^aRectangle! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssaq 2/27/98 11:17'! initialize "MSWSystemView initialize" self install! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 2/27/98 11:02'! initializeCache "MSWSystemView initializeCache" GrowBoxForm _ nil. ShrinkBoxForm _ nil. SystemBoxForm _ nil. CloseBoxForm _ nil.! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 3/24/2010 15:16'! install "MSWSystemView install" Preferences enable:#nicerSystemViews! ! !MSWSystemView class methodsFor: 'class initialization' stamp: 'ssa 3/24/2010 15:16'! unInstall "MSWSystemView unInstall" Preferences disable:#nicerSystemViews! ! !ManyFilesPerClass methodsFor: 'directories' stamp: 'ads 12/2/2010 15:12'! createDirectoriesFor: cls | catDir | catDir _ self classCategoryDirFor: cls category. classDir _ self createDir: cls name in: catDir mustBeNew: false. baseDir _ self createDir: 'base' in: classDir mustBeNew: false. metaDir _ self createDir: 'meta' in: classDir mustBeNew: false.! ! !ManyFilesPerClass methodsFor: 'loading' stamp: 'ads 12/10/2010 12:28'! saveScriptForLoadingPackageBackIn: p "Not implemented."! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/2/2010 15:20'! methodSourceFor: sel in: clsHalf | method | method _ clsHalf methodDict at: sel ifAbsent: [^ sel printString, 'CORRUPTED']. ^ (method getSourceFor: sel in: clsHalf) asString! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/14/2010 14:15'! saveAllExtensionMethodsForPackage: p p extensionMethods asArray do: [:m | | cls catDir | cls _ Smalltalk at: m classSymbol. self createDirectoriesFor: cls. catDir _ self createDir: m category in: (m classIsMeta ifTrue: [metaDir] ifFalse: [baseDir]) mustBeNew: false. self saveMethodNamed: m methodSymbol inCategory: m category of: m actualClass in: catDir. ] displayingProgress: 'Saving ', p name, ' extension methods'. ! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/2/2010 15:18'! saveCategory: cat of: clsHalf in: dir | selectors catDir | catDir _ self createDir: cat in: dir mustBeNew: false. selectors := (cat asString = ClassOrganizer allCategory) ifTrue: [ clsHalf organization allMethodSelectors ] ifFalse: [ clsHalf organization listAtCategoryNamed: cat ]. selectors do: [:sel| self saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir]! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/2/2010 15:14'! saveClass: cls forPackage: p self createDirectoriesFor: cls. self saveClassHalf: cls in: baseDir. self saveClassHalf: cls class in: metaDir! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/5/2010 12:06'! saveClassHalf: clsHalf in: dir self saveClassHalfDefinition: clsHalf in: dir. self saveClassHalfComment: clsHalf in: dir. self saveClassHalfCategories: clsHalf in: dir ! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/2/2010 15:17'! saveClassHalfCategories: clsHalf in: dir clsHalf organization categories do: [:cat | self saveCategory: cat of: clsHalf in: dir]! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/5/2010 12:10'! saveClassHalfComment: clsHalf in: dir | fs | fs _ dir fileNamed: 'comment.txt'. fs nextPutAll: clsHalf organization classComment asString. fs close.! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'ads 12/5/2010 12:10'! saveClassHalfDefinition: clsHalf in: dir | fs | fs _ dir fileNamed: 'definition.txt'. fs nextPutAll: clsHalf definition. fs close.! ! !ManyFilesPerClass methodsFor: 'saving' stamp: 'sm 5/2/2011 20:49'! saveMethodNamed: sel inCategory: cat of: clsHalf in: catDir | src fs selOrFoo | src := self methodSourceFor: sel in: clsHalf. selOrFoo := (sel isKindOf: String) ifTrue: [sel] ifFalse: [sel printString]. fs := catDir fileNamed: selOrFoo, '.txt'. fs nextPutAll: src. fs close ! ! !ManyTestResourceTestCase methodsFor: 'running' stamp: 'nfr 1/3/2010 18:07'! testTearDownOrder | myResourceSetUpOrder myResourceReverseTearDownOrder | myResourceReverseTearDownOrder := OrderedCollection new: 7. myResourceSetUpOrder := (OrderedCollection new: 7) add: SimpleTestResource; add: SimpleTestResourceA1; add: SimpleTestResourceA2; add: SimpleTestResourceA; add: SimpleTestResourceB1; add: SimpleTestResourceB; yourself. self assert: (myResourceSetUpOrder allSatisfy: [:each | each isAvailable]) description: 'At test start, not all my resources were set up'. self class resources do: [:each | each resetOrAddResourcesTo: myResourceReverseTearDownOrder]. self assert: myResourceReverseTearDownOrder = myResourceSetUpOrder description: 'Wrong order for tearDown'. self assert: (myResourceSetUpOrder allSatisfy: [:each | each isAvailable]) description: 'At test start, not all my resources were set up'! ! !ManyTestResourceTestCase methodsFor: 'utility' stamp: 'NiallRoss 7/18/2010 11:52'! clearOuterResourceStateDuring: aBlock "This self-testing test must clear the outer state of its resources before starting and after finishing, so that it can construct test cases and suites of itself and test them." self assert: SimpleTestResourceA1 isAlreadyAvailable description: 'The resource was not set up for the test'. SimpleTestResourceA reset. SimpleTestResourceB reset. SimpleTestResourceA1 reset. self deny: SimpleTestResourceA1 isAlreadyAvailable description: 'The resource was still set up before we began the run'. ^[super clearOuterResourceStateDuring: aBlock] ensure: [self deny: SimpleTestResourceA1 isAlreadyAvailable description: 'The resource was still set up after we finished the run'. self deny: SimpleTestResourceB1 isAlreadyAvailable description: 'The resource was still set up after we finished the run'. SimpleTestResourceA isAvailable. self assert: SimpleTestResourceA1 isAlreadyAvailable description: 'The resource was not set up again after the test'. SimpleTestResourceB isAvailable. self assert: SimpleTestResourceB1 isAlreadyAvailable description: 'The resource was not set up again after the test']! ! !ManyTestResourceTestCase class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:13'! resources ^super resources , (Array with: SimpleTestResourceA with: SimpleTestResourceB)! ! !ManyTestResourceTestCase class methodsFor: 'testing' stamp: ' 17/7/10 17:28'! shouldInheritSelectors ^true! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:37'! anyOne ^contents anyOne! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:37'! at: row at: column ^contents at: (self indexForRow: row andColumn: column)! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/28/2002 14:14'! at: r at: c ifInvalid: v "If r,c is a valid index for this matrix, answer the corresponding element. Otherwise, answer v." (r between: 1 and: nrows) ifFalse: [^v]. (c between: 1 and: ncols) ifFalse: [^v]. ^contents at: (r-1)*ncols + c ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/22/2002 12:37'! at: row at: column incrementBy: value "Array2D>>at:at:add: was the origin of this method, but in Smalltalk add: generally suggests adding an element to a collection, not doing a sum. This method, and SequenceableCollection>>at:incrementBy: that supports it, have been renamed to reveal their intention more clearly." ^contents at: (self indexForRow: row andColumn: column) incrementBy: value! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:40'! at: row at: column put: value ^contents at: (self indexForRow: row andColumn: column) put: value! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:42'! atAllPut: value contents atAllPut: value! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:43'! atRandom ^contents atRandom ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:43'! atRandom: aGenerator ^contents atRandom: aGenerator! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:44'! columnCount ^ncols! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:48'! identityIndexOf: anElement ^self identityIndexOf: anElement ifAbsent: [0@0] ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:48'! identityIndexOf: anElement ifAbsent: anExceptionBlock ^self rowAndColumnForIndex: (contents identityIndexOf: anElement ifAbsent: [^anExceptionBlock value]) ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/22/2002 13:13'! indexOf: anElement "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer 0@0. This kind of perverse result is provided by analogy with SequenceableCollection>>indexOf:. The order in which the receiver are searched is UNSPECIFIED except that it is the same as the order used by #indexOf:ifAbsent: and #readStream." ^self indexOf: anElement ifAbsent: [0@0] ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 11/22/2002 13:10'! indexOf: anElement ifAbsent: anExceptionBlock "If there are integers r, c such that (self at: r at: c) = anElement, answer some such r@c, otherwise answer the result of anExceptionBlock." ^self rowAndColumnForIndex: (contents indexOf: anElement ifAbsent: [^anExceptionBlock value]) ! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:49'! replaceAll: oldObject with: newObject contents replaceAll: oldObject with: newObject! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:44'! rowCount ^nrows! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:49'! size ^contents size! ! !Matrix methodsFor: 'accessing' stamp: 'raok 10/21/2002 22:52'! swap: r1 at: c1 with: r2 at: c2 contents swap: (self indexForRow: r1 andColumn: c1) with: (self indexForRow: r2 andColumn: c2)! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/22/2002 12:41'! atColumn: column |p| p := (self indexForRow: 1 andColumn: column)-ncols. ^(1 to: nrows) collect: [:row | contents at: (p := p+ncols)] ! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/28/2002 14:21'! atColumn: column put: aCollection |p| aCollection size = nrows ifFalse: [self error: 'wrong column size']. p := (self indexForRow: 1 andColumn: column)-ncols. aCollection do: [:each | contents at: (p := p+ncols) put: each]. ^aCollection ! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 10/21/2002 23:32'! atRow: row (row between: 1 and: nrows) ifFalse: [self error: '1st subscript out of range']. ^contents copyFrom: (row-1)*ncols+1 to: row*ncols! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/22/2002 12:42'! atRow: row put: aCollection |p| aCollection size = ncols ifFalse: [self error: 'wrong row size']. p := (self indexForRow: row andColumn: 1)-1. aCollection do: [:each | contents at: (p := p+1) put: each]. ^aCollection! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 10/23/2002 20:41'! diagonal "Answer (1 to: (nrows min: ncols)) collect: [:i | self at: i at: i]" |i| i := ncols negated. ^(1 to: (nrows min: ncols)) collect: [:j | contents at: (i := i + ncols + 1)]! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/28/2002 14:21'! swapColumn: anIndex withColumn: anotherIndex |a b| a := self indexForRow: 1 andColumn: anIndex. b := self indexForRow: 1 andColumn: anotherIndex. nrows timesRepeat: [ contents swap: a with: b. a := a + ncols. b := b + ncols]. ! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 11/28/2002 14:22'! swapRow: anIndex withRow: anotherIndex |a b| a := self indexForRow: anIndex andColumn: 1. b := self indexForRow: anotherIndex andColumn: 1. ncols timesRepeat: [ contents swap: a with: b. a := a + 1. b := b + 1]. ! ! !Matrix methodsFor: 'accessing rows/columns' stamp: 'raok 10/22/2002 00:13'! transposed self assert: [nrows = ncols]. ^self indicesCollect: [:row :column | self at: column at: row]! ! !Matrix methodsFor: 'adding' stamp: 'raok 10/21/2002 22:53'! add: newObject self shouldNotImplement! ! !Matrix methodsFor: 'arithmetic' stamp: 'raok 10/22/2002 20:01'! +* aCollection "Premultiply aCollection by self. aCollection should be an Array or Matrix. The name of this method is APL's +.x squished into Smalltalk syntax." ^aCollection preMultiplyByMatrix: self ! ! !Matrix methodsFor: 'arithmetic' stamp: 'raok 11/28/2002 14:22'! preMultiplyByArray: a "Answer a +* self where a is an Array." nrows = 1 ifFalse: [self error: 'dimensions do not conform']. ^Matrix rows: a size columns: ncols tabulate: [:row :col | (a at: row) * (contents at: col)] ! ! !Matrix methodsFor: 'arithmetic' stamp: 'nice 12/27/2009 03:10'! preMultiplyByMatrix: m "Answer m +* self where m is a Matrix." nrows = m columnCount ifFalse: [self error: 'dimensions do not conform']. ^Matrix rows: m rowCount columns: ncols tabulate: [:row :col | | s | s := 0. 1 to: nrows do: [:k | s := (m at: row at: k) * (self at: k at: col) + s]. s]! ! !Matrix methodsFor: 'comparing' stamp: 'raok 11/22/2002 12:58'! = aMatrix ^aMatrix class == self class and: [ aMatrix rowCount = nrows and: [ aMatrix columnCount = ncols and: [ aMatrix privateContents = contents]]]! ! !Matrix methodsFor: 'comparing' stamp: 'raok 11/22/2002 13:14'! hash "I'm really not sure what would be a good hash function here. The essential thing is that it must be compatible with #=, and this satisfies that requirement." ^contents hash! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:57'! asArray ^contents shallowCopy! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:57'! asBag ^contents asBag! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asByteArray ^contents asByteArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asCharacterSet ^contents asCharacterSet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asFloatArray ^contents asFloatArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asIdentitySet ^contents asIdentitySet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asIntegerArray ^contents asIntegerArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asOrderedCollection ^contents asOrderedCollection! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asSet ^contents asSet! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:58'! asSortedArray ^contents asSortedArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:59'! asSortedCollection ^contents asSortedCollection! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 22:59'! asSortedCollection: aBlock ^contents asSortedCollection: aBlock! ! !Matrix methodsFor: 'converting' stamp: 'raok 10/21/2002 23:00'! asWordArray ^contents asWordArray! ! !Matrix methodsFor: 'converting' stamp: 'raok 11/22/2002 13:02'! readStream "Answer a ReadStream that returns all the elements of the receiver in some UNSPECIFIED order." ^ReadStream on: contents! ! !Matrix methodsFor: 'copying' stamp: 'raok 11/22/2002 12:57'! , aMatrix "Answer a new matrix having the same number of rows as the receiver and aMatrix, its columns being the columns of the receiver followed by the columns of aMatrix." |newCont newCols anArray oldCols a b c| self assert: [nrows = aMatrix rowCount]. newCont := Array new: self size + aMatrix size. anArray := aMatrix privateContents. oldCols := aMatrix columnCount. newCols := ncols + oldCols. a := b := c := 1. 1 to: nrows do: [:r | newCont replaceFrom: a to: a+ncols-1 with: contents startingAt: b. newCont replaceFrom: a+ncols to: a+newCols-1 with: anArray startingAt: c. a := a + newCols. b := b + ncols. c := c + oldCols]. ^self class rows: nrows columns: newCols contents: newCont ! ! !Matrix methodsFor: 'copying' stamp: 'raok 11/22/2002 12:58'! ,, aMatrix "Answer a new matrix having the same number of columns as the receiver and aMatrix, its rows being the rows of the receiver followed by the rows of aMatrix." self assert: [ncols = aMatrix columnCount]. ^self class rows: nrows + aMatrix rowCount columns: ncols contents: contents , aMatrix privateContents ! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:07'! copy ^self class rows: nrows columns: ncols contents: contents copy! ! !Matrix methodsFor: 'copying' stamp: 'nice 10/5/2009 09:09'! postCopy super postCopy. contents := contents copy! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:07'! shallowCopy ^self class rows: nrows columns: ncols contents: contents shallowCopy! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:27'! shuffled ^self class rows: nrows columns: ncols contents: (contents shuffled)! ! !Matrix methodsFor: 'copying' stamp: 'raok 10/21/2002 23:27'! shuffledBy: aRandom ^self class rows: nrows columns: ncols contents: (contents shuffledBy: aRandom)! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:41'! collect: aBlock "Answer a new matrix with transformed elements; transformations should be independent." ^self class rows: nrows columns: ncols contents: (contents collect: aBlock)! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! difference: aCollection "Union is in because the result is always a Set. Difference and intersection are out because the result is like the receiver, and with irregular seleection that cannot be." self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:40'! do: aBlock "Pass elements to aBlock one at a time in row-major order." contents do: aBlock! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/23/2002 20:57'! indicesCollect: aBlock |r i| r := Array new: nrows * ncols. i := 0. 1 to: nrows do: [:row | 1 to: ncols do: [:column | r at: (i := i+1) put: (aBlock value: row value: column)]]. ^self class rows: nrows columns: ncols contents: r! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:49'! indicesDo: aBlock 1 to: nrows do: [:row | 1 to: ncols do: [:column | aBlock value: row value: column]].! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:51'! indicesInject: start into: aBlock |current| current := start. 1 to: nrows do: [:row | 1 to: ncols do: [:column | current := aBlock value: current value: row value: column]]. ^current! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! intersection: aCollection "Union is in because the result is always a Set. Difference and intersection are out because the result is like the receiver, and with irregular seleection that cannot be." self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! reject: aBlock self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:42'! select: aBlock self shouldNotImplement! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/22/2002 00:15'! with: aCollection collect: aBlock "aCollection must support #at:at: and be at least as large as the receiver." ^self withIndicesCollect: [:each :row :column | aBlock value: each value: (aCollection at: row at: column)] ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:53'! with: aCollection do: aBlock "aCollection must support #at:at: and be at least as large as the receiver." self withIndicesDo: [:each :row :column | aBlock value: each value: (aCollection at: row at: column)]. ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:55'! with: aCollection inject: startingValue into: aBlock "aCollection must support #at:at: and be at least as large as the receiver." ^self withIndicesInject: startingValue into: [:value :each :row :column | aBlock value: value value: each value: (aCollection at: row at: column)]! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:52'! withIndicesCollect: aBlock |i r| i := 0. r := contents shallowCopy. 1 to: nrows do: [:row | 1 to: ncols do: [:column | i := i+1. r at: i put: (aBlock value: (r at: i) value: row value: column)]]. ^self class rows: nrows columns: ncols contents: r ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:52'! withIndicesDo: aBlock |i| i := 0. 1 to: nrows do: [:row | 1 to: ncols do: [:column | aBlock value: (contents at: (i := i+1)) value: row value: column]]. ! ! !Matrix methodsFor: 'enumerating' stamp: 'raok 10/21/2002 23:52'! withIndicesInject: start into: aBlock |i current| i := 0. current := start. 1 to: nrows do: [:row | 1 to: ncols do: [:column | current := aBlock value: current value: (contents at: (i := i+1)) value: row value: column]]. ^current! ! !Matrix methodsFor: 'printing' stamp: 'raok 10/21/2002 23:22'! storeOn: aStream aStream nextPut: $(; nextPutAll: self class name; nextPutAll: ' rows: '; store: nrows; nextPutAll: ' columns: '; store: ncols; nextPutAll: ' contents: '; store: contents; nextPut: $)! ! !Matrix methodsFor: 'removing' stamp: 'raok 10/21/2002 22:54'! remove: anObject ifAbsent: anExceptionBlock self shouldNotImplement! ! !Matrix methodsFor: 'removing' stamp: 'klub 9/14/2009 16:34'! removeAll self shouldNotImplement! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! identityIncludes: anObject ^contents identityIncludes: anObject! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:23'! includes: anObject ^contents includes: anObject! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! includesAllOf: aCollection ^contents includesAllOf: aCollection! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:24'! includesAnyOf: aCollection ^contents includesAnyOf: aCollection! ! !Matrix methodsFor: 'testing' stamp: 'raok 11/22/2002 13:03'! isSequenceable "LIE so that arithmetic on matrices will work. What matters for arithmetic is not that there should be random indexing but that the structure should be stable and independent of the values of the elements. #isSequenceable is simply the wrong question to ask." ^true! ! !Matrix methodsFor: 'testing' stamp: 'raok 10/21/2002 23:25'! occurrencesOf: anObject ^contents occurrencesOf: anObject! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 22:40'! indexForRow: row andColumn: column (row between: 1 and: nrows) ifFalse: [self error: '1st subscript out of range']. (column between: 1 and: ncols) ifFalse: [self error: '2nd subscript out of range']. ^(row-1) * ncols + column! ! !Matrix methodsFor: 'private' stamp: 'raok 11/22/2002 12:56'! privateContents "Only used in #, #,, and #= so far. It used to be called #contents, but that clashes with Collection>>contents." ^contents! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 22:47'! rowAndColumnForIndex: index |t| t := index - 1. ^(t // ncols + 1)@(t \\ ncols + 1)! ! !Matrix methodsFor: 'private' stamp: 'raok 10/21/2002 23:05'! rows: rows columns: columns contents: anArray self assert: [rows isInteger and: [rows >= 0]]. self assert: [columns isInteger and: [columns >= 0]]. self assert: [rows * columns = anArray size]. nrows := rows. ncols := columns. contents := anArray. ^self! ! !Matrix methodsFor: 'accessing submatrices' stamp: 'raok 11/25/2002 13:09'! atRows: rs columns: cs "Answer a Matrix obtained by slicing the receiver. rs and cs should be sequenceable collections of positive integers." ^self class rows: rs size columns: cs size tabulate: [:r :c | self at: (rs at: r) at: (cs at: c)]! ! !Matrix methodsFor: 'accessing submatrices' stamp: 'raok 11/25/2002 12:30'! atRows: r1 to: r2 columns: c1 to: c2 "Answer a submatrix [r1..r2][c1..c2] of the receiver." |rd cd| rd := r1 - 1. cd := c1 - 1. ^self class rows: r2-rd columns: c2-cd tabulate: [:r :c| self at: r+rd at: c+cd] ! ! !Matrix methodsFor: 'accessing submatrices' stamp: 'raok 11/25/2002 13:05'! atRows: r1 to: r2 columns: c1 to: c2 ifInvalid: element "Answer a submatrix [r1..r2][c1..c2] of the receiver. Portions of the result outside the bounds of the original matrix are filled in with element." |rd cd| rd := r1 - 1. cd := c1 - 1. ^self class rows: r2-rd columns: c2-cd tabulate: [:r :c| self at: r+rd at: c+cd ifInvalid: element] ! ! !Matrix methodsFor: 'accessing submatrices' stamp: 'raok 11/25/2002 12:32'! atRows: r1 to: r2 columns: c1 to: c2 put: aMatrix "Set the [r1..r2][c1..c2] submatrix of the receiver from the [1..r2-r1+1][1..c2-c1+1] submatrix of aMatrix. As long as aMatrix responds to at:at: and accepts arguments in the range shown, we don't care if it is bigger or even if it is a Matrix at all." |rd cd| rd := r1 - 1. cd := c1 - 1. r1 to: r2 do: [:r | c1 to: c2 do: [:c | self at: r at: c put: (aMatrix at: r-rd at: c-cd)]]. ^aMatrix ! ! !Matrix commentStamp: '<historical>' prior: 0! I represent a two-dimensional array, rather like Array2D. There are three main differences between me and Array2D: (1) Array2D inherits from ArrayedCollection, but isn't one. A lot of things that should work do not work in consequence of this. (2) Array2D uses "at: column at: row" index order, which means that nothing you write using it is likely to work either. I use the almost universal "at: row at: column" order, so it is much easier to adapt code from other languages without going doolally. (3) Array2D lets you specify the class of the underlying collection, I don't. Structure: nrows : a non-negative integer saying how many rows there are. ncols : a non-negative integer saying how many columns there are. contents : an Array holding the elements in row-major order. That is, for a 2x3 array the contents are (11 12 13 21 22 23). Array2D uses column major order. You can specify the class of 'contents' when you create a new Array2D, but Matrix always gives you an Array. There is a reason for this. In strongly typed languages like Haskell and Clean, 'unboxed arrays' save you both space AND time. But in Squeak, while WordArray and FloatArray and so on do save space, it costs time to use them. A LOT of time. I've measured aFloatArray sum running nearly twice as slow as anArray sum. The reason is that whenever you fetch an element from an Array, that's all that happens, but when you fetch an element from aFloatArray, a whole new Float gets allocated to hold the value. This takes time and churns memory. So the paradox is that if you want fast numerical stuff, DON'T use unboxed arrays!! Another reason for always insisting on an Array is that letting it be something else would make things like #, and #,, rather more complicated. Always using Array is the simplest thing that could possibly work, and it works rather well. I was trying to patch Array2D to make more things work, but just couldn't get my head around the subscript order. That's why I made Matrix. Element-wise matrix arithmetic works; you can freely mix matrices and numbers but don't try to mix matrices and arrays (yet). Matrix multiplication, using the symbol +* (derived from APL's +.x), works between (Matrix or Array) +* (Matrix or Array). Don't try to use a number as an argument of +*. Matrix * Number and Number * Matrix work fine, so you don't need +* with numbers. Still to come: oodles of stuff. Gaussian elimination maybe, other stuff probably not. ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/23/2002 20:58'! column: aCollection "Should this be called #fromColumn:?" ^self rows: aCollection size columns: 1 contents: aCollection asArray shallowCopy! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 00:09'! diagonal: aCollection |r i| r := self zeros: aCollection size. i := 0. aCollection do: [:each | i := i+1. r at: i at: i put: each]. ^r! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/23/2002 20:59'! identity: n |r| r := self zeros: n. 1 to: n do: [:i | r at: i at: i put: 1]. ^r! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 00:06'! new: dim "Answer a dim*dim matrix. Is this an abuse of #new:? The argument is NOT a size." ^self rows: dim columns: dim! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 11/25/2002 12:51'! new: dim element: element "Answer a dim*dim matrix with all elements set to element. Is this an abuse of #new:? The argument is NOT a size." ^self rows: dim columns: dim element: element! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 19:54'! new: dim tabulate: aBlock "Answer a dim*dim matrix where it at: i at: j is aBlock value: i value: j." ^self rows: dim columns: dim tabulate: aBlock! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 11/28/2002 14:08'! ones: n ^self new: n element: 1 ! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/23/2002 20:59'! row: aCollection "Should this be called #fromRow:?" ^self rows: 1 columns: aCollection size contents: aCollection asArray shallowCopy! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 00:04'! rows: rows columns: columns ^self rows: rows columns: columns contents: (Array new: rows*columns)! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 11/28/2002 14:10'! rows: rows columns: columns element: element ^self rows: rows columns: columns contents: ((Array new: rows*columns) atAllPut: element; yourself)! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 10/22/2002 19:51'! rows: rows columns: columns tabulate: aBlock "Answer a new Matrix of the given dimensions where result at: i at: j is aBlock value: i value: j" |a i| a := Array new: rows*columns. i := 0. 1 to: rows do: [:row | 1 to: columns do: [:column | a at: (i := i+1) put: (aBlock value: row value: column)]]. ^self rows: rows columns: columns contents: a ! ! !Matrix class methodsFor: 'instance creation' stamp: 'raok 11/28/2002 14:09'! zeros: n ^self new: n element: 0! ! !Matrix class methodsFor: 'private' stamp: 'raok 10/21/2002 23:06'! rows: rows columns: columns contents: contents ^self new rows: rows columns: columns contents: contents! ! !Message methodsFor: 'private' stamp: 'ssa 5/27/2010 11:13'! arguments: anArray args _ anArray! ! !Message methodsFor: 'private' stamp: 'ssa 7/16/2010 19:03'! selector: aSymbol selector _ aSymbol. ! ! !Message methodsFor: 'sending' stamp: 'ssa 5/28/2010 17:06'! sentTo: receiver "answer the result of sending this message to receiver" lookupClass == nil ifTrue: [^ receiver perform: selector withArguments: args asArray] ifFalse: [^ receiver perform: selector withArguments: args asArray inSuperclass: lookupClass]! ! !MessageSet class methodsFor: 'instance creation' stamp: 'ssa 9/3/2008 11:07'! openMessageList: messageList name: labelString autoSelect: autoSelectString "Open a system view for a MessageSet on messageList. 1/24/96 sw: the there-are-no msg now supplied by my sender" | messageSet | messageSet _ self messageList: messageList. messageSet autoSelectString: autoSelectString. ScheduledControllers scheduleActive: (self open: messageSet name: labelString)! ! !MessageTally methodsFor: 'comparing'! < aMessageTally "Refer to the comment in Magnitude|<." ^tally > aMessageTally tally! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:05'! = aMessageTally self species == aMessageTally species ifFalse: [^ false]. ^ aMessageTally method == method! ! !MessageTally methodsFor: 'comparing'! > aMessageTally "Refer to the comment in Magnitude|>." ^tally < aMessageTally tally! ! !MessageTally methodsFor: 'comparing'! hash "Hash is reimplemented because = is implemented." ^method asOop! ! !MessageTally methodsFor: 'comparing'! isPrimitives "Detect pseudo node used to carry tally of local hits" ^ receivers == nil! ! !MessageTally methodsFor: 'comparing'! sonsOver: threshold | hereTally last sons | (receivers == nil or: [receivers size = 0]) ifTrue: [^#()]. hereTally _ tally. sons _ receivers select: "subtract subNode tallies for primitive hits here" [:son | hereTally _ hereTally - son tally. son tally > threshold]. hereTally > threshold ifTrue: [last _ MessageTally new class: class method: method. ^sons copyWith: (last primitives: hereTally)]. ^sons! ! !MessageTally methodsFor: 'comparing' stamp: 'tk 7/5/2001 22:04'! species ^MessageTally! ! !MessageTally methodsFor: 'initialize-release'! close (Timer isMemberOf: Process) ifTrue: [Timer terminate]. Timer _ ObservedProcess _ nil. class _ method _ tally _ receivers _ nil! ! !MessageTally methodsFor: 'initialize-release' stamp: 'nk 3/8/2004 12:29'! initialize maxClassNameSize _ self class defaultMaxClassNameSize. maxClassPlusSelectorSize _ self class defaultMaxClassPlusSelectorSize. maxTabs _ self class defaultMaxTabs.! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 9/17/2010 12:02'! spyEvery: millisecs on: aBlock "Create a spy and spy on the given block at the specified rate." | myDelay startTime time0 | (aBlock isMemberOf: BlockContext) ifFalse: [self error: 'spy needs a block here']. self class: aBlock receiver class method: aBlock method. "set up the probe" ObservedProcess _ Processor thisProcess. myDelay := Delay forMilliseconds: millisecs. time0 := Time millisecondClockValue. gcStats _ SmalltalkImage current getVMParameters. Timer := [[true] whileTrue: [startTime := Time millisecondClockValue. myDelay wait. ObservedProcess suspend. self tally: ObservedProcess suspendedContextWaitingIfNecessary "tally can be > 1 if ran a long primitive" by: (Time millisecondClockValue - startTime) // millisecs. ObservedProcess resume]. nil] newProcess. Timer priority: Processor userInterruptPriority. "activate the probe and evaluate the block" Timer resume. ^ aBlock ensure: ["Collect gc statistics" SmalltalkImage current getVMParameters keysAndValuesDo: [:idx :gcVal| gcStats at: idx put: (gcVal - (gcStats at: idx))]. "cancel the probe and return the value" Timer notNil ifTrue:[Timer terminate]. time := Time millisecondClockValue - time0]! ! !MessageTally methodsFor: 'initialize-release' stamp: 'dmu 9/17/2010 12:03'! spyEvery: millisecs onProcess: aProcess forMilliseconds: msecDuration "Create a spy and spy on the given process at the specified rate." | myDelay time0 endTime sem | (aProcess isKindOf: Process) ifFalse: [self error: 'spy needs a Process here']. self class: aProcess suspendedContextWaitingIfNecessary receiver class method: aProcess suspendedContext method. "set up the probe" ObservedProcess _ aProcess. myDelay _ Delay forMilliseconds: millisecs. time0 _ Time millisecondClockValue. endTime _ time0 + msecDuration. sem _ Semaphore new. gcStats _ SmalltalkImage current getVMParameters. Timer _ [[| startTime | startTime _ Time millisecondClockValue. myDelay wait. ObservedProcess suspend. self tally: ObservedProcess suspendedContextWaitingIfNecessary by: Time millisecondClockValue - startTime // millisecs. startTime < endTime. ObservedProcess resume] whileTrue. sem signal] forkAt: (ObservedProcess priority + 1 min: Processor highestPriority). "activate the probe and wait for it to finish" sem wait. "Collect gc statistics" SmalltalkImage current getVMParameters keysAndValuesDo: [:idx :gcVal| gcStats at: idx put: (gcVal - gcStats at: idx)]. time _ Time millisecondClockValue - time0! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/15/2000 21:49'! fullPrintOn: aStream tallyExact: isExact orThreshold: perCent | threshold | isExact ifFalse: [threshold _ (perCent asFloat / 100 * tally) rounded]. aStream nextPutAll: '**Tree**'; cr. self treePrintOn: aStream tabs: OrderedCollection new thisTab: '' total: tally totalTime: time tallyExact: isExact orThreshold: threshold. aStream nextPut: Character newPage; cr. aStream nextPutAll: '**Leaves**'; cr. self leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/22/2000 02:28'! leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold | dict | dict _ IdentityDictionary new: 100. self leavesInto: dict fromSender: nil. isExact ifTrue: [dict asSortedCollection do: [:node | node printOn: aStream total: tally totalTime: nil tallyExact: isExact. node printSenderCountsOn: aStream]] ifFalse: [(dict asOrderedCollection select: [:node | node tally > threshold]) asSortedCollection do: [:node | node printOn: aStream total: tally totalTime: time tallyExact: isExact]]! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:14'! printOn: aStream | aSelector className aClass | (class isNil or: [method isNil]) ifTrue: [^super printOn: aStream]. aSelector := class selectorAtMethod: method setClass: [:c | aClass := c]. className := aClass name contractTo: self maxClassNameSize. aStream nextPutAll: className; nextPutAll: ' >> '; nextPutAll: (aSelector contractTo: self maxClassPlusSelectorSize - className size)! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:15'! printOn: aStream total: total totalTime: totalTime tallyExact: isExact | aSelector className myTally aClass percentage | isExact ifTrue: [myTally := tally. receivers == nil ifFalse: [receivers do: [:r | myTally := myTally - r tally]]. aStream print: myTally; space] ifFalse: [percentage := tally asFloat / total * 100.0 roundTo: 0.1. aStream print: percentage; nextPutAll: '% {'; print: (percentage * totalTime / 100) rounded; nextPutAll: 'ms} ']. receivers == nil ifTrue: [aStream nextPutAll: 'primitives'; cr] ifFalse: [aSelector := class selectorAtMethod: method setClass: [:c | aClass := c]. className := aClass name contractTo: self maxClassNameSize. aStream nextPutAll: class name; nextPutAll: (aClass = class ifTrue: ['>>'] ifFalse: ['(' , aClass name , ')>>']); nextPutAll: (aSelector contractTo: self maxClassPlusSelectorSize - className size); cr]! ! !MessageTally methodsFor: 'printing' stamp: 'dew 3/22/2000 02:28'! printSenderCountsOn: aStream | mergedSenders mergedNode | mergedSenders _ IdentityDictionary new. senders do: [:node | mergedNode _ mergedSenders at: node method ifAbsent: [nil]. mergedNode == nil ifTrue: [mergedSenders at: node method put: node] ifFalse: [mergedNode bump: node tally]]. mergedSenders asSortedCollection do: [:node | 10 to: node tally printString size by: -1 do: [:i | aStream space]. node printOn: aStream total: tally totalTime: nil tallyExact: true]! ! !MessageTally methodsFor: 'printing' stamp: 'nk 3/8/2004 12:23'! treePrintOn: aStream tabs: tabs thisTab: myTab total: total totalTime: totalTime tallyExact: isExact orThreshold: threshold | sons sonTab | tabs do: [:tab | aStream nextPutAll: tab]. tabs size > 0 ifTrue: [self printOn: aStream total: total totalTime: totalTime tallyExact: isExact]. sons := isExact ifTrue: [receivers] ifFalse: [self sonsOver: threshold]. sons isEmpty ifFalse: [tabs addLast: myTab. sons := sons asSortedCollection. (1 to: sons size) do: [:i | sonTab := i < sons size ifTrue: [' |'] ifFalse: [' ']. (sons at: i) treePrintOn: aStream tabs: (tabs size < self maxTabs ifTrue: [tabs] ifFalse: [(tabs select: [:x | x = '[']) copyWith: '[']) thisTab: sonTab total: total totalTime: totalTime tallyExact: isExact orThreshold: threshold]. tabs removeLast]! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassNameSize ^maxClassNameSize! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxClassNameSize: aNumber maxClassNameSize := aNumber! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxClassPlusSelectorSize ^maxClassPlusSelectorSize! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxClassPlusSelectorSize: aNumber maxClassPlusSelectorSize := aNumber! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:29'! maxTabs ^maxTabs! ! !MessageTally methodsFor: 'printing format' stamp: 'nk 3/8/2004 12:30'! maxTabs: aNumber maxTabs := aNumber! ! !MessageTally methodsFor: 'reporting'! report: strm "Print a report, with cutoff percentage of each element of the tree (leaves, roots, tree)=2, on the stream, strm." self report: strm cutoff: 2! ! !MessageTally methodsFor: 'reporting' stamp: 'spfa 6/1/2004 19:23'! report: strm cutoff: threshold tally = 0 ifTrue: [strm nextPutAll: ' - no tallies obtained'] ifFalse: [strm nextPutAll: ' - '; print: tally; nextPutAll: ' tallies, ', time printString, ' msec.'; cr; cr. self fullPrintOn: strm tallyExact: false orThreshold: threshold]. time isZero ifFalse: [self reportGCStatsOn: strm].! ! !MessageTally methodsFor: 'reporting' stamp: 'ar 7/18/2001 22:12'! reportGCStatsOn: str | oldSpaceEnd youngSpaceEnd memoryEnd fullGCs fullGCTime incrGCs incrGCTime tenureCount upTime rootOverflows | upTime _ time. oldSpaceEnd _ gcStats at: 1. youngSpaceEnd _ gcStats at: 2. memoryEnd _ gcStats at: 3. fullGCs _ gcStats at: 7. fullGCTime _ gcStats at: 8. incrGCs _ gcStats at: 9. incrGCTime _ gcStats at: 10. tenureCount _ gcStats at: 11. rootOverflows _ gcStats at: 22. str cr. str nextPutAll: '**Memory**'; cr. str nextPutAll: ' old '; nextPutAll: oldSpaceEnd asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' young '; nextPutAll: (youngSpaceEnd - oldSpaceEnd) asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' used '; nextPutAll: youngSpaceEnd asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str nextPutAll: ' free '; nextPutAll: (memoryEnd - youngSpaceEnd) asStringWithCommasSigned; nextPutAll: ' bytes'; cr. str cr. str nextPutAll: '**GCs**'; cr. str nextPutAll: ' full '; print: fullGCs; nextPutAll: ' totalling '; nextPutAll: fullGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((fullGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime)'. fullGCs = 0 ifFalse: [str nextPutAll: ', avg '; print: ((fullGCTime / fullGCs) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' incr '; print: incrGCs; nextPutAll: ' totalling '; nextPutAll: incrGCTime asStringWithCommas; nextPutAll: 'ms ('; print: ((incrGCTime / upTime * 100) roundTo: 1.0); nextPutAll: '% uptime)'. incrGCs = 0 ifFalse: [str nextPutAll:', avg '; print: ((incrGCTime / incrGCs) roundTo: 1.0); nextPutAll: 'ms']. str cr. str nextPutAll: ' tenures '; nextPutAll: tenureCount asStringWithCommas. tenureCount = 0 ifFalse: [str nextPutAll: ' (avg '; print: (incrGCs / tenureCount) asInteger; nextPutAll: ' GCs/tenure)']. str cr. str nextPutAll: ' root table '; nextPutAll: rootOverflows asStringWithCommas; nextPutAll:' overflows'. str cr. ! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 12:06'! tally "Answer the receiver's number of tally." ^tally! ! !MessageTally methodsFor: 'reporting' stamp: 'stp 05/08/1999 11:47'! time "Answer the receiver's run time." ^time! ! !MessageTally methodsFor: 'private'! class: aClass method: aMethod class _ aClass. method _ aMethod. tally _ 0. receivers _ Array new: 0! ! !MessageTally methodsFor: 'private'! copyWithTally: hitCount ^ (MessageTally new class: class method: method) bump: hitCount! ! !MessageTally methodsFor: 'private'! method ^method! ! !MessageTally methodsFor: 'private'! primitives: anInteger tally _ anInteger. receivers _ nil! ! !MessageTally methodsFor: 'collecting leaves'! bump: hitCount tally _ tally + hitCount! ! !MessageTally methodsFor: 'collecting leaves'! bump: hitCount fromSender: senderTally "Add this hitCount to the total, and include a reference to the sender responsible for the increment" self bump: hitCount. senders == nil ifTrue: [senders _ OrderedCollection new]. senderTally == nil ifFalse: [senders add: (senderTally copyWithTally: hitCount)]! ! !MessageTally methodsFor: 'collecting leaves'! into: leafDict fromSender: senderTally | leafNode | leafNode _ leafDict at: method ifAbsent: [leafDict at: method put: (MessageTally new class: class method: method)]. leafNode bump: tally fromSender: senderTally! ! !MessageTally methodsFor: 'collecting leaves'! leavesInto: leafDict fromSender: senderTally | rcvrs | rcvrs _ self sonsOver: 0. rcvrs size = 0 ifTrue: [self into: leafDict fromSender: senderTally] ifFalse: [rcvrs do: [:node | node isPrimitives ifTrue: [node leavesInto: leafDict fromSender: senderTally] ifFalse: [node leavesInto: leafDict fromSender: self]]]! ! !MessageTally methodsFor: 'tallying'! bumpBy: count tally _ tally + count! ! !MessageTally methodsFor: 'tallying'! tally: context by: count "Explicitly tally the specified context and its stack." | root | context method == method ifTrue: [^self bumpBy: count]. (root _ context home sender) == nil ifTrue: [^ (self bumpBy: count) tallyPath: context by: count]. ^ (self tally: root by: count) tallyPath: context by: count! ! !MessageTally methodsFor: 'tallying'! tallyPath: context by: count | aMethod path | aMethod _ context method. receivers do: [:aMessageTally | aMessageTally method == aMethod ifTrue: [path _ aMessageTally]]. path == nil ifTrue: [path _ MessageTally new class: context receiver class method: aMethod. receivers _ receivers copyWith: path]. ^ path bumpBy: count! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassNameSize "Return the default maximum width of the class name alone" ^30! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:27'! defaultMaxClassPlusSelectorSize "Return the default maximum width of the class plus selector together (not counting the '>>')" ^60! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:26'! defaultMaxTabs "Return the default number of tabs after which leading white space is compressed" ^18! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:41'! defaultPollPeriod "Answer the number of milliseconds between interrupts for spyOn: and friends. This should be faster for faster machines." ^DefaultPollPeriod ifNil: [ DefaultPollPeriod _ 1 ]! ! !MessageTally class methodsFor: 'defaults' stamp: 'nk 3/8/2004 12:41'! defaultPollPeriod: numberOfMilliseconds "Set the default number of milliseconds between interrupts for spyOn: and friends. This should be faster for faster machines." DefaultPollPeriod := numberOfMilliseconds! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:34'! spyOn: aBlock "MessageTally spyOn: [100 timesRepeat: [3.14159 printString]]" | node result | node _ self new. result _ node spyEvery: self defaultPollPeriod on: aBlock. (StringHolder new contents: (String streamContents: [:s | node report: s; close])) openLabel: 'Spy Results'. ^ result! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:34'! spyOn: aBlock toFileNamed: fileName "Spy on the evaluation of aBlock. Write the data collected on a file named fileName." | file value node | node _ self new. value _ node spyEvery: self defaultPollPeriod on: aBlock. file _ FileStream newFileNamed: fileName. node report: file; close. file close. ^value! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:35'! spyOnProcess: aProcess forMilliseconds: msecDuration "| p | p _ [100000 timesRepeat: [3.14159 printString]] fork. (Delay forMilliseconds: 100) wait. MessageTally spyOnProcess: p forMilliseconds: 1000" | node | node _ self new. node spyEvery: self defaultPollPeriod onProcess: aProcess forMilliseconds: msecDuration. (StringHolder new contents: (String streamContents: [:s | node report: s; close])) openLabel: 'Spy Results'! ! !MessageTally class methodsFor: 'spying' stamp: 'nk 3/8/2004 10:35'! spyOnProcess: aProcess forMilliseconds: msecDuration toFileNamed: fileName "Spy on the evaluation of aProcess. Write the data collected on a file named fileName. Will overwrite fileName" | file node | node _ self new. node spyEvery: self defaultPollPeriod onProcess: aProcess forMilliseconds: msecDuration. file _ FileStream fileNamed: fileName. node report: file; close. file close! ! !MessageTally class methodsFor: 'spying'! tallySends: aBlock "MessageTally tallySends: [3.14159 printString]" ^ self tallySendsTo: nil inBlock: aBlock showTree: true! ! !MessageTally class methodsFor: 'spying' stamp: 'tk 5/4/1998 17:01'! tallySendsTo: receiver inBlock: aBlock showTree: treeOption "MessageTally tallySends: [3.14159 printString]" "This method uses the simulator to count the number of calls on each method invoked in evaluating aBlock. If receiver is not nil, then only sends to that receiver are tallied. Results are presented as leaves, sorted by frequency, preceded, optionally, by the whole tree." | prev tallies startTime totalTime | startTime _ Time millisecondClockValue. tallies _ MessageTally new class: aBlock receiver class method: aBlock method. prev _ aBlock. thisContext sender runSimulated: aBlock contextAtEachStep: [:current | current == prev ifFalse: ["call or return" prev sender == nil ifFalse: ["call only" (receiver == nil or: [current receiver == receiver]) ifTrue: [tallies tally: current by: 1]]. prev _ current]]. totalTime _ Time millisecondClockValue - startTime // 1000.0 roundTo: 0.01. (StringHolder new contents: (String streamContents: [:s | s nextPutAll: 'This simulation took ' , totalTime printString , ' seconds.'; cr. treeOption ifTrue: [tallies fullPrintOn: s tallyExact: true orThreshold: 0] ifFalse: [tallies leavesPrintOn: s tallyExact: true orThreshold: 0]. tallies close])) openLabel: 'Spy Results'! ! !MessageTally class methodsFor: 'spying'! time: aBlock ^ Time millisecondsToRun: aBlock! ! !Metaclass methodsFor: '*transporter' stamp: 'ads 12/14/2010 10:27'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock ^self fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock initializing: true! ! !Metaclass methodsFor: '*transporter' stamp: 'ads 12/14/2010 10:30'! fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock initializing: aBool super fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex filteringCategoriesBy: catFilterBlock. (aBool and:[moveSource not and: [self methodDict includesKey: #initialize]]) ifTrue: [aFileStream cr. aFileStream cr. aFileStream nextChunkPut: thisClass name , ' initialize'. aFileStream cr]! ! !MethodContext methodsFor: 'printing' stamp: 'ads 1/24/2011 13:02'! printOn: aStream | h | aStream nextPutAll: (RVMPrimitivesNeededForBootstrapping printPrefixFor: self). (self class methodDictionary includesKey: #outerContext) ifTrue: [ self outerContext ifNil: [super printOn: aStream] ifNotNil: [ aStream nextPutAll: '[] in '. self outerContext printOn: aStream] ] ifFalse: [ self isExecutingBlock ifFalse: [^ super printOn: aStream]. h _ self blockHome. h ifNil: [^ aStream nextPutAll: '[]']. aStream nextPutAll: '[] from '. h printOn: aStream ]! ! !MethodContext methodsFor: 'converting' stamp: 'ssa 9/7/2009 14:36'! asContext ^self! ! !MethodHolder methodsFor: 'menu' stamp: 'ssa 9/4/2008 15:23'! doItReceiver "If there is an instance associated with me, answer it, for true mapping of self. If not, then do what other code-bearing tools do, viz. give access to the class vars." ^ self selectedClass ifNil: [FakeClassPool new]! ! !MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'! category ^ self actualClass organization categoryOfElement: methodSymbol! ! !MethodReference methodsFor: '*packageinfo-base' stamp: 'ab 5/23/2003 22:58'! sourceCode ^ self actualClass sourceCodeAt: methodSymbol! ! !MethodReference methodsFor: '*transporter' stamp: 'ads 12/7/2010 17:04'! changeRecords "changeRecordsAt: seems broken; doesn't handle class-side methods properly. -- Adam ^ (self actualClass changeRecordsAt: self methodSymbol) ifNil: [{}]" | cls aList | cls _ self actualClass. aList _ VersionsBrowser new scanVersionsOf: (cls compiledMethodAt: self methodSymbol ifAbsent: [^ {}]) class: cls theNonMetaClass meta: cls isMeta category: (cls whichCategoryIncludesSelector: self methodSymbol) selector: self methodSymbol. ^ (aList ifNotNil: [aList changeList]) ifNil: [{}]! ! !MethodReference methodsFor: '*transporter' stamp: 'ads 12/1/2010 12:23'! removeFromSystem self actualClass removeSelector: self methodSymbol.! ! !MethodReference methodsFor: '*transporter' stamp: 'ads 2/2/2011 15:02'! topLevelPackageName | category | category := (self category notNil and: [self category beginsWith: '*']) ifTrue: [self category asString allButFirst capitalized] ifFalse: [self actualClass theNonMetaClass category asString]. ^ category copyUpTo: $-! ! !Model methodsFor: '*RVM-Archiving'! archiveOn: aStream "To be consistent with Object, don't file out the dependents (subclasses may wish to override or put back the dependencies back in some other manner -- see Figure>dearchiveFrom:)." | oldDependents | oldDependents _ dependents. dependents _ nil. super archiveOn: aStream. dependents _ oldDependents.! ! !Mutex methodsFor: 'mutual exclusion' stamp: 'dmu 6/14/2010 16:16'! critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess | activeProcess := Processor thisProcess. activeProcess == owner ifTrue:[^aBlock value]. ^semaphore critical:[ owner := activeProcess. aBlock ensure:[owner := nil]].! ! !Mutex methodsFor: 'initialize' stamp: 'das 11/3/2005 22:53'! initialize semaphore := Semaphore forMutualExclusion.! ! !Mutex class methodsFor: 'as yet unclassified' stamp: 'dmu 11/13/2010 16:19'! forMutualExclusion ^ self new! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 15:57'! do: aStep self critical: [ rankThreads do: [ :thread | thread startStep: aStep.]. rankThreads do: [ :ignored | self wait. ] ].! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 14:22'! fullVerify " To save copy and memory sorting can be done directly: " | key idx count | key := 1. idx := 1. 1 to: numKeys do: [ :i | [ (idx == (masterHist at: key)) and: [ ((key >= maxKey) or: [ idx >= numKeys ]) not ] ] whileTrue: [ key := key + 1 ]. keyArray at: idx put: key. idx := idx + 1. ]. " Confirm keys correctly sorted: count incorrectly sorted keys, if any " count := 0. 2 to: numKeys do: [ :i | ((keyArray at: (i - 1)) > (keyArray at: i)) ifTrue: [ count := count + 1]]. (count ~= 0) ifTrue: [ Error signal: 'Full_verify: number of keys out of sort: '. count asString ] ifFalse: [ PassedVerification := PassedVerification + 1]. ^ PassedVerification! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'StefanMarr 10/16/2009 00:23'! initKeys: aDouble | x k | k := maxKey / 4. 1 to: numKeys do: [ :i | (i == 32769) ifTrue: [ Transcript show: 'Seed at: ', (rng seed asString);cr.]. x := rng randlc: aDouble. x := x + (rng randlc: aDouble). x := x + (rng randlc: aDouble). x := x + (rng randlc: aDouble). keyArray at: i put: (x * k) asInteger. ].! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 14:23'! partialVerify: iteration | k offset | 1 to: NPBISBase testArraySize do: [ :i | k := partialVerifyVals at: i. offset := iteration. ( (0 <= k) and: [k <= (numKeys - 1)]) ifTrue: [ (benchmarkClass == #S) ifTrue: [ ((i - 1) <= 2) ifTrue: [ offset := iteration. ] ifFalse: [ offset := 0 - iteration.]. ]. ((masterHist at: k) ~= ((testRankArray at: i) + offset)) ifTrue: [ Error signal: 'Failed partial verification: iteration ', iteration asString, ', test key ', i asString ] ifFalse: [ NPBISBase passedVerification: (NPBISBase passedVerification + 1). ] ] ]! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 17:18'! rank: iteration keyArray at: (iteration + 1) put: iteration. keyArray at: (1 + iteration + (NPBISBase maxIterations)) put: (maxKey - iteration). 1 to: NPBISBase testArraySize do: [ :i | partialVerifyVals at: i put: (keyArray at: (1 + (testIndexArray at: i)) ) ]. " Clear the work array " 1 to: maxKey do: [ :i | masterHist at: i put: 0 ]. " In the section, the keys themselves are used as their own indexes to determine how many of each there are: their individual population " 1 to: numKeys do: [ :i | masterHist at: (1 + (keyArray at: i)) incrementBy: 1 ]. " Now they have individual key population " " Density to Distribution conversion " 1 to: (maxKey - 1) do: [ :i | masterHist at: (i + 1) incrementBy: (masterHist at: i). ]. self partialVerify: iteration.! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'StefanMarr 9/21/2009 23:31'! resetMasterHist 1 to: maxKey do: [ :i | masterHist at: i put: 0 ].! ! !NPBIS methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 14:24'! run | mainTimer tPhase1 tPhase2 tKeyInit tVerify executionVerified | ScriptConsole println: ' Size: ', totalKeys asString, ' Iterations: ', NPBISBase maxIterations asString. mainTimer := runner createTimer: 'precise-total'. tPhase1 := runner createTimer: 'phase1'. tPhase2 := runner createTimer: 'phase2'. tKeyInit := runner createTimer: 'keyInit'. tVerify := runner createTimer: 'verifyCompletely'. NPBISBase passedVerification: 0. serial ifTrue: [ tKeyInit start. self initKeys: NPBIS amult. tKeyInit stop. self rank: 1. ] ifFalse: [ self setupThreads. tKeyInit start. self do: #initKeys. tKeyInit stop. RankThread iteration: 1. self do: #step1. self resetMasterHist. self do: #step2. self partialVerify: 1]. NPBISBase passedVerification: 0. mainTimer start. 1 to: NPBIS maxIterations do: [:i | serial ifTrue: [ self rank: i. ] ifFalse: [ RankThread iteration: i. tPhase1 start. self do: #step1. tPhase1 stop. self resetMasterHist. tPhase2 start. self do: #step2. tPhase2 stop. self partialVerify: i] ]. mainTimer stop. tVerify start. self fullVerify. tVerify stop. executionVerified := ((NPBISBase passedVerification) == ((5 * NPBIS maxIterations) + 1)). executionVerified ifFalse: [ Error signal: 'Benchmark verification failed']. serial ifFalse: [ self do: #quit. ]. ^ executionVerified! ! !NPBIS methodsFor: 'license' stamp: 'StefanMarr 4/15/2011 17:04'! license ^'This code is based on the Java version of NPB3. Permission to use, copy, distribute and modify this software for any purpose with or without fee is hereby granted. We request, however, that all derived work reference the NAS Parallel Benchmarks 3.0. This software is provided "as is" without express or implied warranty. Information on NPB 3.0, including the Technical Report NAS-02-008 "Implementation of the NAS Parallel Benchmarks in Java", original specifications, source code, results and information on how to submit new results, is available at: http://www.nas.nasa.gov/Software/NPB/'! ! !NPBIS methodsFor: 'accessors' stamp: 'StefanMarr 9/23/2009 19:14'! keyArray ^keyArray ! ! !NPBIS methodsFor: 'accessors' stamp: 'StefanMarr 9/23/2009 19:15'! masterHist ^masterHist ! ! !NPBIS methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 23:00'! rng: val rng := val! ! !NPBIS methodsFor: 'accessors' stamp: 'StefanMarr 5/14/2011 01:00'! runner: aRunner runner := aRunner ! ! !NPBIS methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 22:59'! serial: val serial := val! ! !NPBIS commentStamp: 'StefanMarr 5/14/2011 01:04' prior: 0! NPBIS definines the general benchmark Integer Sort benchmark of the NAS Parallel Benchmarks. See NPBSuite>>benchIS for the actual benchmark implemented based on SMark. Instance Variables: bid <ProtoObject | PseudoContext> results <ProtoObject | PseudoContext> serial <Boolean> rng <NPBRandom> runner <SMarkRunner>! !NPBIS class methodsFor: 'constants' stamp: 'StefanMarr 9/21/2009 18:15'! amult ^1220703125.0! ! !NPBIS class methodsFor: 'constants' stamp: 'StefanMarr 5/14/2011 10:39'! defaultProblemSize ^ #S! ! !NPBIS class methodsFor: 'instance creation' stamp: 'StefanMarr 9/23/2009 19:12'! newOfSizeClass: aSymbol with: nThreads serial: aBool | o | o := super new. o initializeWithSizeClass: aSymbol andNumberOfThreads: nThreads. o serial: aBool. o rng: NPBRandom new. ^o ! ! !NPBISBase methodsFor: 'as yet unclassified' stamp: 'StefanMarr 11/7/2010 12:31'! checksum: intArray name: aString stop: aBool | check | check := intArray sum. 1 halt. "RVMOperations print: name, ' checksum is ', check asString." aBool ifTrue: [ 1 halt. self StopSystemHere]! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 4/15/2011 17:19'! initializeValues "initialize the object after construction" totalKeys := 1 << self totalKeysLog2. maxKey := 1 << maxKeyLog2. numKeys := totalKeys. sizeOfBuffers := totalKeys. keyArray := Array new: sizeOfBuffers. masterHist := Array new: maxKey. partialVerifyVals := Array new: NPBISBase testArraySize. masterHist doWithIndex: [ :val :i | masterHist at: i put: 0 ]! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:36'! master ^ master! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:37'! master: val master := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:30'! maxKey ^ maxKey! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:30'! maxKey: val maxKey := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:28'! maxKeyLog2 ^ maxKeyLog2 ! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:28'! maxKeyLog2: val maxKeyLog2 := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:21'! numBuckets ^ numBuckets! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:21'! numBuckets: val numBuckets := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:29'! numBucketsLog2 ^ numBucketsLog2 ! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:29'! numBucketsLog2: val numBucketsLog2 := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:21'! numKeys ^ numKeys! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:36'! numKeys: val numKeys := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:02'! numThreads ^ numThreads! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:02'! numThreads: val numThreads := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/23/2009 19:32'! partialVerifyVals ^partialVerifyVals ! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:37'! rankThreads ^rankThreads ! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 16:37'! rankThreads: val rankThreads := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:22'! sizeOfBuffers ^ sizeOfBuffers! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:22'! sizeOfBuffers: val sizeOfBuffers := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'SM 9/16/2009 22:50'! testIndexArray ^ testIndexArray! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 1/16/2011 20:47'! testIndexArray: val testIndexArray := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'SM 9/16/2009 22:51'! testRankArray ^ testRankArray! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 1/16/2011 20:46'! testRankArray: val testRankArray := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/17/2009 08:30'! totalKeys ^ totalKeys! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 9/21/2009 15:38'! totalKeys: val totalKeys := val! ! !NPBISBase methodsFor: 'accessors' stamp: 'SM 9/16/2009 22:54'! totalKeysLog2 ^totalKeysLog2! ! !NPBISBase methodsFor: 'accessors' stamp: 'StefanMarr 1/16/2011 20:46'! totalKeysLog2: val totalKeysLog2 := val! ! !NPBISBase methodsFor: 'license' stamp: 'StefanMarr 4/15/2011 17:04'! license ^'This code is based on the Java version of NPB3. Permission to use, copy, distribute and modify this software for any purpose with or without fee is hereby granted. We request, however, that all derived work reference the NAS Parallel Benchmarks 3.0. This software is provided "as is" without express or implied warranty. Information on NPB 3.0, including the Technical Report NAS-02-008 "Implementation of the NAS Parallel Benchmarks in Java", original specifications, source code, results and information on how to submit new results, is available at: http://www.nas.nasa.gov/Software/NPB/'! ! !NPBISBase methodsFor: 'initialization' stamp: 'StefanMarr 10/5/2009 18:14'! initialize mtxCritical := Semaphore forMutualExclusion. mtxNotify := Semaphore new.! ! !NPBISBase methodsFor: 'initialization' stamp: 'StefanMarr 5/14/2011 10:44'! initializeWithSizeClass: aSymbol andNumberOfThreads: numberOfThreads | consts | benchmarkClass := aSymbol asSymbol. consts := NPBISBase perform: benchmarkClass. consts keysAndValuesDo: [ :key :val | self perform: (key , ':') asSymbol with: val ]. numThreads := numberOfThreads. self initializeValues. ^ self! ! !NPBISBase methodsFor: 'initialization' stamp: 'sm 6/1/2011 15:52'! setupThreads "Initialize the threads/processes for the benchmark" | start end remainder offset rStart rEnd rRemainder rOffset rThread | start := 0. end := 0. remainder := totalKeys \\ numThreads. offset := 0. rStart := 0. rEnd := 0. rRemainder := maxKey \\ numThreads. rOffset := 0. rankThreads := Array new: numThreads. 1 to: numThreads do: [ :i | | zeroIdx | zeroIdx := i - 1. start := (zeroIdx * ((totalKeys / numThreads) asInteger)) + offset. end := ((zeroIdx * ((totalKeys / numThreads) asInteger))) + ((totalKeys / numThreads) asInteger) - 1 + offset. (remainder > 0) ifTrue: [ remainder := remainder - 1. offset := offset + 1. end := end + 1]. rStart := (zeroIdx * ((maxKey / numThreads) asInteger)) + rOffset. rEnd := ((zeroIdx * ((maxKey / numThreads) asInteger))) + ((maxKey / numThreads) asInteger) -1 + rOffset. (rRemainder > 0) ifTrue: [ rRemainder := rRemainder - 1. rOffset := rOffset + 1. rEnd := rEnd + 1]. rThread := RankThread newFor: self with: i start: (start + 1) end: (end + 1) rStart: (rStart + 1) rEnd: (rEnd + 1). rankThreads at: i put: rThread. rThread rankThreads: rankThreads. rThread start. ].! ! !NPBISBase methodsFor: 'synchronization' stamp: 'StefanMarr 10/5/2009 18:13'! critical: aBlock mtxCritical critical: aBlock! ! !NPBISBase methodsFor: 'synchronization' stamp: 'StefanMarr 10/5/2009 18:13'! notify mtxNotify signal ! ! !NPBISBase methodsFor: 'synchronization' stamp: 'StefanMarr 10/5/2009 18:12'! wait mtxNotify wait ! ! !NPBISBase commentStamp: 'StefanMarr 5/14/2011 01:03' prior: 0! NPBISBase definines the commonalities for the general benchmark and its actual worker-threads. See NPBSuite>>benchIS for the actual benchmark implemented based on SMark. Instance Variables: testIndexArray <Object> testRankArray <Object> masterHist <(SequenceableCollection of: Object)> keyArray <(Array of: (CharacterBlock | Magnitude | Point | String | UUID))> partialVerifyVals <Array> sizeClass <ProtoObject | PseudoContext> totalKeys <Collection | Duration | Number | Point> maxKey <Collection | Duration | Number | Point> numBuckets <ProtoObject | PseudoContext> numKeys <Collection | Color | DateAndTime | Duration | Number | OBMetaNode | Point | Timespan | TraitComposition | TraitDescription | TraitTransformation> sizeOfBuffers <ProtoObject | PseudoContext> timerOn <ProtoObject | PseudoContext> timer <ProtoObject | PseudoContext> totalKeysLog2 <ProtoObject | PseudoContext> maxKeyLog2 <ProtoObject | PseudoContext> numBucketsLog2 <ProtoObject | PseudoContext> numThreads <ProtoObject | PseudoContext> rankThreads <(SequenceableCollection of: RankThread)> master <NPBISBase> benchmarkClass <ProtoObject> mtxNotify <Semaphore> mtxCritical <Semaphore>! !NPBISBase class methodsFor: 'constants' stamp: 'SM 9/16/2009 22:28'! S ^ Dictionary newFrom: { #testIndexArray -> { 48427. 17148. 23627. 62548. 4431 }. #testRankArray -> { 0. 18. 346. 64917. 65463 }. #totalKeysLog2 -> 16. #maxKeyLog2 -> 11. #numBucketsLog2 -> 9 }! ! !NPBISBase class methodsFor: 'constants' stamp: 'SM 9/16/2009 22:16'! maxIterations ^ 10! ! !NPBISBase class methodsFor: 'constants' stamp: 'StefanMarr 1/16/2011 21:40'! passedVerification ^PassedVerification! ! !NPBISBase class methodsFor: 'constants' stamp: 'StefanMarr 1/16/2011 21:41'! passedVerification: val PassedVerification := val! ! !NPBISBase class methodsFor: 'constants' stamp: 'SM 9/16/2009 22:17'! testArraySize ^ 5! ! !NPBISBase class methodsFor: 'instance creation' stamp: 'StefanMarr 9/21/2009 18:28'! newOfSizeClass: aSymbol with: numberOfThreads | o | o := super new. o initializeWithSizeClass: aSymbol andNumberOfThreads: numberOfThreads. ^o! ! !NPBRandom methodsFor: 'as yet unclassified'! findSeedFor: aRank with: numOfThreads of: totalRanNumbers using: seed and: aGenMult | i t1 t2 an mq nq kk ik continueLoop | nq := (totalRanNumbers / numOfThreads) asInteger. mq := 0. [nq > 1] whileTrue: [ mq := mq + 1. nq := nq / 2. ]. t1 := aGenMult. 1 to: mq do: [ :ii | tran := t1. t2 := self randlc: t1. t1 := tran. ]. an := t1. kk := aRank. t1 := seed. t2 := an. i := 1. continueLoop := true. [(i <= 100) and: continueLoop] whileTrue: [ ik := (kk / 2) asInteger. ((2 * ik) ~= kk) ifTrue: [ tran := t1. self randlc: t2. t1 := tran.]. (ik == 0) ifTrue: [ continueLoop := false. ] ifFalse: [ tran := t2. self randlc: t2. t2 := tran. kk := ik. i := i + 1. ]. ]. ^ t1.! ! !NPBRandom methodsFor: 'as yet unclassified'! randlc: aDouble | t1 t2 t3 t4 a1 a2 x1 x2 z | " Break A into two parts such that A = 2**23 * A1 + A2. " t1 := r23 * aDouble. a1 := t1 asInteger. a2 := aDouble - (t23 * a1). " Break X into two parts such that X = 2^23 * X1 + X2, compute Z = A1 * X2 + A2 * X1 (mod 2^23), and then X = 2^23 * Z + A2 * X2 (mod 2^46). " t1 := r23 * tran. x1 := t1 asInteger. x2 := tran - (t23 * x1). t1 := (a1 * x2) + (a2 * x1). t2 := (r23 * t1) asInteger. z := t1 - (t23 * t2). t3 := (t23 * z) + (a2 * x2). t4 := (r46 * t3) asInteger. tran := t3 - (t46 * t4). ^ r46 * tran! ! !NPBRandom methodsFor: 'initialization'! initialize tran := NPBRandom seed. amult := NPBIS amult. KS := 0. r23 := 0.5 raisedTo: 23. r46 := r23 raisedTo: 2. t23 := 2 raisedTo: 23. t46 := t23 raisedTo: 2.! ! !NPBRandom methodsFor: 'license' stamp: 'StefanMarr 4/15/2011 17:04'! license ^'This code is based on the Java version of NPB3. Permission to use, copy, distribute and modify this software for any purpose with or without fee is hereby granted. We request, however, that all derived work reference the NAS Parallel Benchmarks 3.0. This software is provided "as is" without express or implied warranty. Information on NPB 3.0, including the Technical Report NAS-02-008 "Implementation of the NAS Parallel Benchmarks in Java", original specifications, source code, results and information on how to submit new results, is available at: http://www.nas.nasa.gov/Software/NPB/'! ! !NPBRandom methodsFor: 'accessing'! seed ^ tran! ! !NPBRandom methodsFor: 'private - accessing'! seed: aSeed tran := aSeed! ! !NPBRandom class methodsFor: 'as yet unclassified'! d2m46 ^ 0.5 raisedTo: 46! ! !NPBRandom class methodsFor: 'as yet unclassified'! i246m1 ^ (2 raisedTo: 46) - 1! ! !NPBRandom class methodsFor: 'as yet unclassified'! seed ^314159265.0! ! !NPBSuite methodsFor: 'benchmarking' stamp: 'StefanMarr 5/14/2011 01:00'! benchIS "Run the IS benchmark" bench run.! ! !NPBSuite methodsFor: 'benchmarking' stamp: 'StefanMarr 5/14/2011 10:43'! setUpBenchIS "Prepare IS benchmark" | sizeClass threadCnt | sizeClass := runner problemSize. sizeClass ifNil: [ sizeClass := NPBIS defaultProblemSize. ]. threadCnt := runner processes. bench := NPBIS newOfSizeClass: sizeClass with: threadCnt serial: (threadCnt == 0). bench runner: runner.! ! !NPBTest methodsFor: 'tests'! testIS | verified runner suite | runner := SMarkRunner new. suite := NPBSuite new. suite runner: runner. runner suite: suite. runner iterations: 1. runner processes: 4. runner problemSize: #S. self shouldnt: [ runner execute. "TODO: update as soon as the SMark framework supports verification" verified := false. ] raise: Error. self assert: verified.! ! !NPBTest methodsFor: 'tests'! testKeyArrayContent | o keyArray | o := NPBIS newOfSizeClass: #S with: 0 serial: true. o initKeys: NPBIS amult. keyArray := o keyArray. self assert: (keyArray at: 65536) equals: 962. self assert: (keyArray at: 65535) equals: 677. self assert: (keyArray at: 30001) equals: 557. self assert: (keyArray at: 1) equals: 1585. self assert: (keyArray at: 2) equals: 825. self assert: (keyArray at: 12) equals: 1140. ! ! !NPBTest methodsFor: 'running' stamp: 'StefanMarr 5/22/2011 10:23'! setUp "Necessary for Squeak 4.2 compatibility, since method anotations are not supported in the base image." (self respondsTo: #timeout:) ifTrue: [ self timeout: 300. ].! ! !Number methodsFor: 'arithmetic' stamp: 'ssa 11/27/2009 16:14'! inverted ^1/self! ! !Number methodsFor: 'mathematical functions' stamp: 'ssa 8/27/2009 14:58'! pi ^Float pi * self! ! !Number methodsFor: 'truncation and round off' stamp: 'ssa 8/30/2009 04:04'! atRandom ^self asFloat * (Collection atRandom: self class randomForPicking copy)! ! !Number methodsFor: 'converting' stamp: 'ssa 11/15/2008 08:57'! asPointWithinRectangleWithExtent: extent "Answer a point showing what coordinate I would have if wrapped into a rectangle of this extent. Clip out of bounds answer to 0@0 if undershot or extent if overShot. Only really useful for integers" | x y newX newY | x _ extent x. y _ extent y. self > (x*y) ifTrue:[^extent]. self < 1 ifTrue:[^0@0]. newX _ self \\ x = 0 ifTrue:[x]ifFalse:[self \\ x]. newY _ self - 1 // x + 1. ^newX@newY "{0 asPointWithinRectangleWithExtent:2@2. 1 asPointWithinRectangleWithExtent:2@2. 2 asPointWithinRectangleWithExtent:2@2. 3 asPointWithinRectangleWithExtent:2@2. 4 asPointWithinRectangleWithExtent:2@2. 5 asPointWithinRectangleWithExtent:2@2.} #(0@0 1@1 2@1 1@2 2@2 2@2)" "{0 asPointWithinRectangleWithExtent:3@3. 1 asPointWithinRectangleWithExtent:3@3. 2 asPointWithinRectangleWithExtent:3@3. 3 asPointWithinRectangleWithExtent:3@3. 4 asPointWithinRectangleWithExtent:3@3. 5 asPointWithinRectangleWithExtent:3@3. 6 asPointWithinRectangleWithExtent:3@3. 7 asPointWithinRectangleWithExtent:3@3. 8 asPointWithinRectangleWithExtent:3@3. 9 asPointWithinRectangleWithExtent:3@3. 10 asPointWithinRectangleWithExtent:3@3.} #(0@0 1@1 2@1 3@1 1@2 2@2 3@2 1@3 2@3 3@3 3@3)"! ! !Number methodsFor: 'converting'! theta: angle "Answer a new Point whose r value is the receiver and whose theta value is the argument." "KSC Extension" ^(angle cos * self) @ (angle sin * self)! ! !Number methodsFor: 'intervals' stamp: 'ssa 9/7/2009 21:42'! zeno "100 zeno" "-100 zeno" "Answer a collection of numbers representing Zeno's paradox steps between myself and zero" | steps distanceRemaining | steps _ OrderedCollection new. distanceRemaining _ self abs. [distanceRemaining > 1] whileTrue:[steps add: distanceRemaining * self sign. distanceRemaining _ distanceRemaining / 2.0]. ^steps asArray! ! !Number methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:39'! floatPrecisionForDecimalPlaces: places "Answer the floatPrecision that corresponds to the given number of decimal places" ^ #(1 0.1 0.01 0.001 0.0001 0.00001 0.000001 0.0000001 0.00000001 0.000000001) at: (places + 1) " (0 to: 6) collect: [:i | Number floatPrecisionForDecimalPlaces: i] "! ! !Number methodsFor: 'printing' stamp: 'ssa 1/1/1970 00:48'! printShowingDecimalPlaces: placesDesired "Print the receiver showing precisely the given number of places desired . If the placesDesired provided is positive, a decimal point and that many digits after the decimal point will always be shown. If the placesDesired is zero, a whole number will be shown, without a decimal point. This method could probably be greatly optimized -- improvements welcomed." | aString | placesDesired <= 0 ifTrue: [^ self rounded printString]. aString _ ((self asFloat roundTo: (self floatPrecisionForDecimalPlaces: placesDesired)) asString), ((String new: placesDesired) atAllPut: $0). ^ aString copyFrom: 1 to: ((aString indexOf: $.) + placesDesired) " 0.23 printShowingDecimalPlaces: 2 23.5698 printShowingDecimalPlaces: 2 -234.567 printShowingDecimalPlaces: 5 23.4567 printShowingDecimalPlaces: 0 "! ! !Number methodsFor: 'printing' stamp: 'ssa 10/7/2008 18:20'! printShowingMax3Digits "Print the receiver showing precisely the 3 digits, using K M B T for thousand, million, etc." "|num| num _ 0.00001234567890. 20 timesRepeat:[num printShowingMax3Digits print. num _ num *10]." | s abs value | value _ self isFraction ifTrue:[self asFloat]ifFalse:[self]. s _ value printString select:[:char| '0123456789' includes: char]. s size <=3 ifTrue:[^value printString]. abs _ value abs asFloat. abs < 0.01 ifTrue:[^((value * 1000) printShowingDecimalPlaces: 2),'m']. abs < 0.1 ifTrue:[^((value * 1000) printShowingDecimalPlaces: 1),'m']. abs < 10 ifTrue:[^value printShowingDecimalPlaces: 2]. abs < 100 ifTrue:[^value printShowingDecimalPlaces: 1]. abs < 1000 ifTrue:[^value asInteger printString]. abs < 10000 ifTrue:[^((value /1000) printShowingDecimalPlaces: 2),'K']. abs < 100000 ifTrue:[^((value /1000) printShowingDecimalPlaces: 1),'K']. abs < 1000000 ifTrue:[^((value /1000) asInteger printString),'K']. abs < 10000000 ifTrue:[^((value /1000000) printShowingDecimalPlaces: 2),'M']. abs < 100000000 ifTrue:[^((value /1000000) printShowingDecimalPlaces: 1),'M']. abs < 1000000000 ifTrue:[^(value /1000000) asInteger printString,'M']. abs < 10000000000 ifTrue:[^((value /1000000000) printShowingDecimalPlaces: 2),'B']. abs < 100000000000 ifTrue:[^((value /1000000000) printShowingDecimalPlaces: 1),'B']. abs < 1000000000000 ifTrue:[^((value /1000000000) asInteger printString),'B']. abs < 10000000000000 ifTrue:[^((value /1000000000000) printShowingDecimalPlaces: 2),'T']. abs < 100000000000000 ifTrue:[^((value /1000000000000) printShowingDecimalPlaces: 1),'T']. abs < 1000000000000000 ifTrue:[^((value /1000000000000) asInteger printString),'T']. abs < 10000000000000000 ifTrue:[^((value /1000000000000000) printShowingDecimalPlaces: 2),'Q']. abs < 100000000000000000 ifTrue:[^((value /1000000000000000) printShowingDecimalPlaces: 1),'Q']. abs < 1000000000000000000 ifTrue:[^((value /1000000000000000) asInteger printString),'Q']. ^'too big' ! ! !Number methodsFor: '*RVM-Archiving'! archiveOn: aStream aStream storeClass: self class; store: self! ! !Number class methodsFor: '*RVM-Archiving'! dearchiveFrom: aStream ^aStream read: self! ! !Object methodsFor: '*Javascript' stamp: 'aw 8/29/2007 14:27'! ~== anObject ^ (self == anObject) not! ! !Object methodsFor: '*RVM-ensembles' stamp: 'ssa 4/21/2009 20:29'! forMeRun: aBlock ^ aBlock value! ! !Object methodsFor: '*RVM-ensembles' stamp: 'ads 1/30/2011 15:20'! printConsole RVMOperations isRVM ifTrue: [RVMOperations print: self printString] ifFalse: [Transcript showInConsole ifFalse: [Transcript show: self printString; cr]]! ! !Object methodsFor: '*Sly' stamp: 'dmu 9/19/2010 22:45'! comma: x ^self , x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:43'! divideBy: x ^ self / x! ! !Object methodsFor: '*Sly' stamp: 'dmu 8/27/2010 13:26'! doubleEquals: anObject "a keyword verion of == for use with selector modifiers in Sly" ^self == anObject! ! !Object methodsFor: '*Sly' stamp: 'dmu 8/27/2010 13:27'! equals: anObject "a keyword verion of = for use with SlySelectorModifiers" ^self = anObject! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:42'! minus: x ^ self - x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:42'! plus: x ^ self + x! ! !Object methodsFor: '*Sly' stamp: 'dmu 3/25/2010 23:43'! times: x ^ self * x! ! !Object methodsFor: '*Sly2' stamp: 'ssa 6/17/2010 16:32'! ENSasExplorerString ^ self asExplorerString! ! !Object methodsFor: '*Sly2' stamp: 'ssa 6/17/2010 16:26'! ENSasString ^self asString! ! !Object methodsFor: '*Sly2' stamp: 'ssa 7/16/2010 19:19'! ENSisEnsemble "SlyEnsemble overrides to true" ^false! ! !Object methodsFor: '*Sly2' stamp: 'ssa 6/17/2010 13:35'! ENSprintOn: aStream "Print a textual representation of myself on aStream" ^ self printOn: aStream! ! !Object methodsFor: '*Sly2' stamp: 'ssa 6/17/2010 15:01'! ENSprintString ^self printString! ! !Object methodsFor: '*Sly2' stamp: 'ssa 7/16/2010 19:14'! ENSsize ^self size! ! !Object methodsFor: '*Sly2' stamp: 'ssa 6/17/2010 13:34'! ENSstoreOn: aStream "Store a textual representation of myself on aStream" ^ self storeOn: aStream! ! !Object methodsFor: '*Sly2' stamp: 'ssa 7/7/2010 13:56'! sentToEnsemble: aMessage ^self perform: aMessage selector withArguments: aMessage arguments! ! !Object methodsFor: '*Sly3' stamp: 'dmu 9/16/2010 23:45'! asSingletonEnsemble ^Sly3Ensemble withSoleMember: self! ! !Object methodsFor: '*Sly3' stamp: 'dmu 9/1/2010 23:22'! collectionLY ^ nil! ! !Object methodsFor: '*Sly3' stamp: 'ads 1/30/2011 15:20'! doesNotUnderstand: aMessage "Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector)." "Testing: (3 activeProcess)" | newSelector rps | rps _ {Sly3Adverb reflectiveAdverb stringWithUppercaseSuffix. Sly3ModWholly stringWithUppercaseSuffix}. rps do: [:rp | (aMessage selector beginsWith: rp) ifTrue: [ newSelector _ aMessage selector copyFrom: rp size + 1 to: aMessage selector size. newSelector size = 0 ifTrue: [^ self]. ^ self perform: newSelector asSymbol withArguments: aMessage arguments ] ]. (RVMOperations isMulticoreCoordinate: aMessage selector) ifTrue:[RVMOperations teleport: self to: aMessage selector. ^self]. (Preferences autoAccessors and: [self tryToDefineVariableAccess: aMessage]) ifTrue: [^ aMessage sentTo: self]. ^ MessageNotUnderstood new message: aMessage; receiver: self; signal! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitAddDependent: anObject self addDependent: anObject! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitChanged: anAspect self changed: anAspect! ! !Object methodsFor: '*sunit-preload' stamp: 'jp 3/17/2003 09:58'! sunitRemoveDependent: anObject self removeDependent: anObject! ! !Object methodsFor: 'converting'! asDisplayObject "kwa -- 7 July 1989, answer some DisplayObject which represents the receiver. The default is DisplayString. Subclasses may wish to override. kwa -- 5 December 1989, changed from DisplayText to DisplayString for efficiency." "ssa - 27 February 1990, at kwa's suggestion, changed asDisplayString back to asDisplayText to work around a bug in glyph scanning" "KSC Extension" ^self asDisplayText! ! !Object methodsFor: 'converting'! DisplayText "Convert the receiver into a DisplayText." "KSC Extension." ^self asText asDisplayText! ! !Object methodsFor: 'converting' stamp: 'ssa 11/13/2008 10:34'! asObjectCoordinate "Answer an RVMObjectCoordinate with my manycore coordinate details" ^RVMObjectCoordinate for: self! ! !Object methodsFor: 'converting'! asText "kwa -- 7 July 1989, answer some Text which represents the receiver. The default is to use asString asText. This is so any object can can be treated as a Text (whether it is or not). Subclasses may wish to override (but shouldn't have to) to take advantage of emphasis et al." "KSC Extension" ^self asString asText! ! !Object methodsFor: 'converting' stamp: 'ssa 12/16/2009 13:22'! printDirectlyToDisplay "For debugging: write the receiver's printString directly to the display at (0, 100); senders of this are detected by the check-for-slips mechanism." self asString displayAt: 0@0 "StringMorph someInstance printDirectlyToDisplay"! ! !Object methodsFor: 'debugging' stamp: 'ssa 1/21/2010 12:08'! display "Display my printString on the screen to avoid the transcript" self printString asParagraph display! ! !Object methodsFor: 'debugging' stamp: 'ssa 2/26/2009 01:59'! locate "Open a object coordinate view on my location in the manycore world" "Array locate" RVMObjectCoordinateView openOn: self asObjectCoordinate! ! !Object methodsFor: 'debugging' stamp: 'ssa 8/8/2008 17:25'! print Transcript cr;show: self printString! ! !Object methodsFor: 'inspecting' stamp: 'ssa 1/6/2010 20:19'! inspect "Create and schedule an Inspector in which the user can examine the receiver's variables." self inspectorClass openOn: self withEvalPane: true! ! !Object methodsFor: 'macpal' stamp: 'ssa 9/8/2009 10:22'! allInstanceVariableValues "Answer a collection whose elements are the values of those instance variables of the receiver" | c | c _ OrderedCollection new. 1 to: self class instSize do: [:i | c add: (self instVarAt: i)]. ^ c! ! !Object methodsFor: 'macpal' stamp: 'ssa 9/8/2009 10:51'! allInstanceVariableValuesPlusIndexed "Answer a collection whose elements are the values of those instance variables of the receiver. Also include the indexed variables if any" | c | c _ OrderedCollection new. 1 to: self class instSize do: [:i | c add: (self instVarAt: i)]. self class isVariable ifFalse:[^c]. 1 to: self size do:[:index| c add: (self basicAt: index)]. ^ c! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/11/2009 16:40'! explore ObjectExplorer new openExplorerFor: self! ! !Object methodsFor: 'outlining' stamp: 'ssa 3/9/2010 16:17'! hasContents ^false! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/10/2009 16:00'! outlineString ^self printString! ! !Object methodsFor: 'outlining' stamp: 'ssa 9/10/2009 13:36'! subobjects "Answer an appropriate collection of my sub objects for an outliner view" ^self class allInstVarNames with: self allInstanceVariableValues collect:[:key :value| key -> value]! ! !Object methodsFor: 'printing' stamp: 'ssa 10/25/2008 20:45'! archiveVersion "Subclasses should override when they implement a different archive version" ^1! ! !Object methodsFor: 'printing'! sicArchiveOn: aStream "This is the generic archiver for objects. This can be used if you want to bypass superclass or other reasons for overriding archiveOn:" aStream storeObject: self; storeClass: self class. self class isVariable ifTrue: [aStream store: self basicSize. 1 to: self basicSize do: [:i | aStream nextPut: (self basicAt: i)].]. 1 to: self class instSize do: [:i | aStream nextPut: (self instVarAt: i)].! ! !Object methodsFor: 'printing' stamp: 'ads 1/24/2011 13:03'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables." self class allInstVarNames doWithIndex: [:title :index | aStream nextPutAll: title; nextPut: $:; space; tab; nextPutAll: (RVMPrimitivesNeededForBootstrapping printPrefixFor: (self instVarAt: index)); print:(self instVarAt: index); cr]! ! !Object methodsFor: 'printing' stamp: 'ssa 9/4/2009 22:29'! printStringUpTo: limit "Answer a String whose characters are a description of the receiver. If you want to print without a character limit, use fullPrintString." | limitedString | limitedString _ String streamContents: [:s | self printOn: s] limitedTo: limit. limitedString size < limit ifTrue: [^ limitedString]. ^ limitedString, '...'! ! !Object methodsFor: 'testing' stamp: 'ssa 9/8/2009 10:48'! hasInstanceVariables ^self allInstanceVariableValuesPlusIndexed size > 0! ! !Object methodsFor: 'testing' stamp: 'ssa 5/12/2010 19:26'! isArray "Return true if the receiver is an Array" ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 5/27/2010 10:40'! isBoolean "Return true if the receiver is true or false. Note: Do not override in any class except Boolean." ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 8/11/2009 12:37'! isCharacter ^false! ! !Object methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:00'! isEnsemble "Sly3Ensemble overrides to true" ^false! ! !Object methodsFor: 'testing' stamp: 'ssa 8/31/2009 14:14'! isObject ^true! ! !Object methodsFor: 'updating' stamp: 'ssa 5/12/2010 10:29'! changed: anAspect with: anObject from: aSource "Receiver changed. The change is denoted by the argument anAspect. Usually the argument is a Symbol that is part of the dependent's change protocol. Inform all of the dependents. Also pass anObject for additional information." self dependents do: [:aDependent | aDependent update: anAspect with: anObject from: aSource]! ! !Object methodsFor: 'updating' stamp: 'ssa 5/12/2010 10:29'! update: anAspect with: anObject from: aSource "Receive a change notice from an object of whom the receiver is a dependent. The default behavior is to call update:, which by default does nothing; a subclass might want to change itself in some way." ^ self update: anAspect with: anObject! ! !Object methodsFor: 'user interface' stamp: 'ssa 6/17/2010 16:15'! asExplorerString ^ self printString! ! !Object methodsFor: 'user interface' stamp: 'ssa 11/30/2009 17:49'! defaultBackgroundColor "Answer the color to be used as the base window color for a window whose model is an object of the receiver's class" (Smalltalk includesKey: #WINDOWCOLORSELECTOR) ifFalse:[Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| Preferences windowColorFor: obj class name]]. ^((Smalltalk at: #WINDOWCOLORSELECTOR) value: self) ! ! !Object methodsFor: 'private' stamp: 'yo 6/29/2004 11:37'! errorNotIndexable "Create an error notification that the receiver is not indexable." self error: ('Instances of {1} are not indexable' translated format: {self class name})! ! !Object methodsFor: 'private'! errorSubscriptBounds: index "Create an error notification that an improper integer was used as an index." self error: 'subscript is out of bounds: ' , index printString! ! !Object methodsFor: '*SlyBootstrap' stamp: 'dmu 3/18/2010 15:47'! primitiveGetExtraPreheaderWord: anObject "ignores receiver, queries argument" <primitive: 'primitiveGetExtraPreheaderWord' module: 'RVMPlugin'> self primitiveFailed! ! !Object methodsFor: '*SlyBootstrap' stamp: 'dmu 3/18/2010 14:52'! primitiveSetExtraPreheaderWord: w "sets word IN w to SELF" <primitive: 'primitiveSetExtraPreheaderWord' module: 'RVMPlugin'> self primitiveFailed! ! !Object methodsFor: '*SlyBootstrap' stamp: 'dmu 3/16/2010 19:11'! primitiveSetExtraWordSelector: aSelector <primitive: 'primitiveSetExtraWordSelector' module: 'RVMPlugin'> self primitiveFailed! ! !Object methodsFor: '*RVM-Archiving'! archiveOn: aStream "This is the generic archiver for objects. If an object does anything special, this method will need to be subclassed along with the complementary method - dearchiveFrom:" aStream storeObject: self; storeClass: self class. self class isVariable ifTrue: [aStream store: self basicSize. 1 to: self basicSize do: [:i | aStream nextPut: (self basicAt: i)].]. 1 to: self class instSize do: [:i | aStream nextPut: (self instVarAt: i)].! ! !Object methodsFor: '*RVM-Archiving'! dearchiveFrom: aStream "This is the generic de-archiver for objects. If an object does anything special, this method will need to be subclassed along with the complementary method - archiveOn:" self class isVariable ifTrue: [1 to: self basicSize do: [:i | self basicAt: i put: aStream next]]. 1 to: self class instSize do: [:j | self instVarAt: j put: aStream next]! ! !Object methodsFor: '*RVM-Archiving'! sicArchiveOn: aStream "This is the generic archiver for objects. This can be used if you want to bypass superclass or other reasons for overriding archiveOn:" aStream storeObject: self; storeClass: self class. self class isVariable ifTrue: [aStream store: self basicSize. 1 to: self basicSize do: [:i | aStream nextPut: (self basicAt: i)].]. 1 to: self class instSize do: [:i | aStream nextPut: (self instVarAt: i)].! ! !Object class methodsFor: '*RVM-Archiving'! dearchive: versionNumber from: aStream "Override this method when implementing new archive versions for a class." ^versionNumber == self archiveVersion ifTrue: [self dearchiveFrom: aStream] ifFalse: [self error: 'Can''t dearchive this version.']! ! !Object class methodsFor: '*RVM-Archiving'! dearchiveFrom: aStream | anObject | self isVariable ifTrue:[anObject _ self basicNew: (aStream read: Integer)] ifFalse:[anObject _ self dearchiveNewFrom: aStream]. aStream storeObject: anObject. anObject dearchiveFrom: aStream. ^anObject! ! !Object class methodsFor: '*RVM-Archiving'! dearchiveNewFrom: aStream ^self basicNew! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 16:15'! hide: anItem "recursively hide this and all progeny" anItem isOpen ifTrue:[(self listedChildrenOf: anItem) do:[:each| self hide: each]]. self levels removeKey: anItem ifAbsent:[]. self list remove: anItem ifAbsent:[self halt]. anItem isOpen: false. ! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 2/26/2010 13:47'! hideChildrenOfSelection (self listedChildrenOf: self currentSelection ) do:[:each| self hide: each]. self currentSelection isOpen: false. ! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 16:14'! listedChildrenOf: aWrapper ^self list select:[:item| item parent == aWrapper]! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 2/26/2010 13:45'! showChildrenOfSelection | kids | self currentSelection hasContents ifFalse:[^self]. kids _ self currentSelection contents. self list addAll: kids after: self currentSelection. self currentSelection isOpen: true.! ! !ObjectExplorer methodsFor: 'opening/closing' stamp: 'ssa 9/11/2009 15:44'! toggleSelection self currentSelection isNil ifTrue:[^self]. self currentSelection isOpen ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:11'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" ^ 1 to: 0 "null selection"! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:40'! defaultRootLabel ^'unlabeled object'! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:15'! doItContext "Answer the context in which a text selection can be evaluated." ^nil! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'RAA 9/23/1999 13:19'! doItReceiver "Answer the object that should be informed of the result of evaluating a text selection." currentSelection ifNil: [^rootObject]. ^currentSelection withoutListWrapper ! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 6/17/2010 16:25'! getList ^OrderedCollection with: (ObjectExplorerWrapper with: rootObject name: 'root' model: self parent: nil) ! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! inspector "Answer the value of inspector" inspector isNil ifTrue:[self inspector: nil]. ^ inspector! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! inspector: anObject "Set the value of inspector" inspector _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'hg 9/7/2001 12:12'! label ^ rootObject printStringLimitedTo: 32! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:51'! list "Answer the value of list" list isNil ifTrue:[self list: self getList]. ^ list! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! monitorList: anObject "Set the value of monitorList" monitorList _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 12/17/2009 10:02'! monitorProcess "Answer the value of monitorProcess" monitorProcess isNil ifTrue:[self monitorProcess: nil]. ^ monitorProcess! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 12/17/2009 10:02'! monitorProcess: anObject "Set the value of monitorProcess" monitorProcess _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:43'! object ^currentSelection ifNotNilDo: [ :cs | cs withoutListWrapper ]! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 10:02'! parentObject currentSelection ifNil: [ ^nil ]. currentSelection parent ifNil: [ ^rootObject ]. ^currentSelection parent withoutListWrapper! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:40'! rootLabel "Answer the value of rootLabel" rootLabel isNil ifTrue:[self rootLabel: self defaultRootLabel]. ^ rootLabel! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/8/2010 14:39'! rootLabel: anObject "Set the value of rootLabel" rootLabel _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! rootObject "Answer the value of rootObject" rootObject isNil ifTrue:[self rootObject: nil]. ^ rootObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:35'! rootObject: anObject "Set the value of rootObject" rootObject _ anObject! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'nk 7/24/2003 09:47'! selector ^currentSelection ifNotNilDo: [ :cs | cs selector ]! ! !ObjectExplorer methodsFor: 'accessing' stamp: 'ssa 2/9/2010 04:26'! wrapperFor: anObject ^self list detect:[:wrapper| wrapper item == anObject]ifNone:[^nil]! ! !ObjectExplorer methodsFor: 'error handling' stamp: 'nk 7/24/2003 09:29'! doesNotUnderstand: aMessage inspector ifNotNil: [ (inspector respondsTo: aMessage selector) ifTrue: [ ^inspector perform: aMessage selector withArguments: aMessage arguments ]]. ^super doesNotUnderstand: aMessage! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! chasePointers "Open a PointerFinder on the selected item" | path sel savedRoot saved | path := OrderedCollection new. sel := currentSelection. [ sel isNil ] whileFalse: [ path addFirst: sel asString. sel := sel parent ]. path addFirst: #openPath. path := path asArray. savedRoot := rootObject. saved := self object. [ rootObject := nil. self changed: #getList. (Smalltalk includesKey: #PointerFinder) ifTrue: [PointerFinder on: saved] ifFalse: [self objectReferencesToSelection ]] ensure: [ rootObject := savedRoot. self changed: #getList. self changed: path. ]! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:22'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items" ^ StringHolder basicNew codePaneMenu: aMenu shifted: shifted ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! defsOfSelection "Open a browser on all defining references to the selected instance variable, if that's what's currently selected." | aClass sel | (aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash]. sel := self selector. self systemNavigation browseAllStoresInto: sel from: aClass! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'! exploreSelection "Open an ObjectExplorer on the current selection" self object explore! ! !ObjectExplorer methodsFor: 'menus' stamp: 'ssa 1/6/2010 20:35'! explorerKey: aChar from: view "Similar to #genericMenu:..." | insideObject parentObject | currentSelection ifNotNil: [ insideObject := self object. parentObject := self parentObject. inspector ifNil: [inspector := Inspector new]. inspector inspect: parentObject; object: insideObject. aChar == $i ifTrue: [^ self inspectSelection]. aChar == $e ifTrue: [^ self exploreSelection]. aChar == $b ifTrue: [^ inspector browseMethodFull]. aChar == $h ifTrue: [^ inspector classHierarchy]. aChar == $c ifTrue: [^ inspector copyName]. aChar == $p ifTrue: [^ inspector browseFullProtocol]. aChar == $N ifTrue: [^ inspector browseClassRefs]. aChar == $t ifTrue: [^ inspector tearOffTile]. aChar == $v ifTrue: [^ inspector viewerForValue]]. ^ self arrowKey: aChar from: view! ! !ObjectExplorer methodsFor: 'menus' stamp: 'ssa 12/17/2009 10:13'! genericMenu: aMenu "Borrow a menu from my inspector" | insideObject menu parentObject | currentSelection ifNil: [menu := aMenu. menu add: '*nothing selected*' target: self selector: #yourself argument:nil] ifNotNil: [insideObject := self object. parentObject := self parentObject. inspector ifNil: [inspector := Inspector new]. inspector inspect: parentObject; object: insideObject. aMenu selections do:[:each| aMenu targets add: inspector]. inspector fieldListMenu: aMenu. aMenu selections do:[:each| aMenu targets add: inspector]. aMenu selections do: [:i | (#(#inspectSelection #exploreSelection #referencesToSelection #defsOfSelection #objectReferencesToSelection #chasePointers ) includes: i ) ifTrue: [aMenu targets at:(aMenu selections indexOf:i) put:self]]. aMenu addLine; add: 'monitor changes' target: self selector: #monitor: argument: currentSelection]. monitorList isEmptyOrNil ifFalse: [aMenu addLine; add: 'stop monitoring all' target: self selector: #stopMonitoring argument:nil]. ^ aMenu! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:26'! inspectSelection "Open an Inspector on the current selection" self object inspect! ! !ObjectExplorer methodsFor: 'menus' stamp: 'nk 7/24/2003 10:00'! objectReferencesToSelection "Open a browser on all references to the selected instance variable, if that's what currently selected. " self systemNavigation browseAllObjectReferencesTo: self object except: (Array with: self parentObject with: currentSelection with: inspector) ifNone: [:obj | self changed: #flash]. ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'sd 11/20/2005 21:27'! referencesToSelection "Open a browser on all references to the selected instance variable, if that's what's currently selected." | aClass sel | (aClass := self parentObject class) isVariable ifTrue: [^ self changed: #flash]. sel := self selector. self systemNavigation browseAllAccessesTo: sel from: aClass! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:19'! selectedClass "Answer the class of the receiver's current selection" ^self doItReceiver class ! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'! trash "What goes in the bottom pane" ^ ''! ! !ObjectExplorer methodsFor: 'menus' stamp: 'RAA 9/23/1999 13:10'! trash: newText "Don't save it" ^ true! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:24'! monitor: anObjectExplorerWrapper "Start stepping and watching the given wrapper for changes." anObjectExplorerWrapper ifNil: [ ^self ]. self monitorList at: anObjectExplorerWrapper put: anObjectExplorerWrapper asString. self monitorProcess isNil ifFalse:[self monitorProcess terminate]. self monitorProcess: [[self monitorList notEmpty]whileTrue:[(Delay forMilliseconds:200)wait. self step]] newProcess. [self monitorProcess resume] fork! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'sd 11/20/2005 21:27'! monitorList ^monitorList ifNil: [ monitorList := WeakIdentityKeyDictionary new ].! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:06'! release self stopMonitoring. super release.! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'nk 7/12/2003 17:55'! shouldGetStepsFrom: aWorld ^self monitorList notEmpty! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:20'! step "If there's anything in my monitor list, see if the strings have changed." | string changes | changes := false. self monitorList keysAndValuesDo: [ :k :v | k ifNotNil: [ k refresh. (string := k asString) ~= v ifTrue: [ self monitorList at: k put: string. changes := true ]. ] ]. changes ifTrue: [ | sel | sel := currentSelection. self changed: #list. self noteNewSelection: sel. ]. ! ! !ObjectExplorer methodsFor: 'monitoring' stamp: 'ssa 12/17/2009 10:06'! stopMonitoring monitorList := nil. self monitorProcess ifNotNil:[self monitorProcess terminate]! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/10/2009 16:51'! explorerFor: anObject ^self explorerFor: anObject withLabel:'Object Explorer'! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 3/24/2010 15:05'! explorerFor: anObject withLabel: label | topView listView ptv | rootObject := anObject. topView := StandardSystemView new label: 'Exploring ',anObject class name,' ',label; model: self; yourself. topView addSubView:(listView := ExplorerListView on: self list: #list selected: #getCurrentSelection changeSelected: #noteNewSelection: menu: #genericMenu: keystroke: #explorerKey:from:) in: (0 @ 0 corner: 1 @ 0.8) borderWidth:1. ptv _ PluggableTextView on: self text: #trash accept: #trash: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. ptv askBeforeDiscardingEdits: false. topView addSubView: ptv in: (0 @ 0.8 corner: 1 @ 1) borderWidth:1. listView autoDeselect: false. ^ topView! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'RAA 6/2/2000 16:23'! initialExtent ^300@500! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/10/2009 16:42'! openBrowser: aClass Browser newOnClass: aClass selector: nil! ! !ObjectExplorer methodsFor: 'user interface' stamp: 'ssa 9/11/2009 14:37'! openExplorerFor: anObject " ObjectExplorer new openExplorerFor: Smalltalk " (self explorerFor: anObject) controller open. ^ self ! ! !ObjectExplorer commentStamp: '<historical>' prior: 0! ObjectExplorer provides a hierarchical alternative to #inspect. Simply evaluate an expression like: World explore and enjoy.! !ObjectExplorer class methodsFor: 'instance creation' stamp: 'ssa 2/8/2010 14:44'! openExplorerFor: anObject labeled: newRootLabel withLabel: label | exp view | exp _ self new rootLabel: newRootLabel. view _ exp explorerFor: anObject withLabel: label . view controller open! ! !ObjectExplorer class methodsFor: 'instance creation' stamp: 'ssa 2/8/2010 14:33'! openExplorerFor: anObject withLabel: label | exp | exp _ self new explorerFor: anObject withLabel: label . exp controller open! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! parent ^parent! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! parent: anObject parent _ anObject! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:49'! selector parent ifNil: [ ^nil ]. ^(parent withoutListWrapper class allInstVarNames includes: itemName) ifTrue: [ itemName asSymbol ]! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:49'! setItem: anObject name: aString model: aModel item _ anObject. model _ aModel. itemName _ aString.! ! !ObjectExplorerWrapper methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:14'! setItem: anObject name: aString model: aModel parent: itemParent parent _ itemParent. self setItem: anObject name: aString model: aModel! ! !ObjectExplorerWrapper methodsFor: 'converting' stamp: 'ssa 7/7/2010 11:08'! asString | explorerString string | explorerString _ [item asExplorerString] on: Error do: ['<error: ', item class name, ' in asExplorerString: evaluate "' , itemName , ' asExplorerString" to debug>']. string _ (itemName ifNotNil: [itemName , ': '] ifNil: ['']) , explorerString. (string includes: Character cr) ifTrue: [^ string withSeparatorsCompacted]. ^ string! ! !ObjectExplorerWrapper methodsFor: 'converting' stamp: 'nk 7/24/2003 10:16'! itemName ^itemName! ! !ObjectExplorerWrapper methodsFor: 'monitoring' stamp: 'nk 7/12/2003 18:28'! refresh "hack to refresh item given an object and a string that is either an index or an instance variable name." [ | index | (model class allInstVarNames includes: itemName) ifTrue: [ item _ model instVarNamed: itemName ] ifFalse: [ index _ itemName asNumber. (index between: 1 and: model basicSize) ifTrue: [ item _ model basicAt: index]] ] on: Error do: [ :ex | item _ nil ]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 16:17'! contents (item respondsTo: #explorerContents) ifTrue: [^item explorerContents collect:[:e| e parent: self]]. "For all others, show named vars first, then indexed vars" ^(item class allInstVarNames asOrderedCollection withIndexCollect: [:each :index | self class with: (item instVarAt: index) name: each model: item parent: self]) , ((1 to: item basicSize) collect: [:index | self class with: (item basicAt: index) name: index printString model: item parent: self])! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 15:09'! depth ^self parent isNil ifTrue:[0]ifFalse:[self parent depth + 1]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'RAA 6/21/1999 11:27'! hasContents ^item hasContentsInExplorer ! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'dgd 9/26/2004 18:34'! icon "Answer a form to be used as icon" ^ Preferences visualExplorer ifTrue: [item iconOrThumbnailOfSize: 16] ifFalse: [nil]! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! isOpen "Answer the value of isOpen" isOpen isNil ifTrue:[self isOpen: false]. ^ isOpen! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! isOpen: anObject "Set the value of isOpen" isOpen _ anObject! ! !ObjectExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 14:45'! itemName: anObject "Set the value of itemName" itemName _ anObject! ! !ObjectExplorerWrapper commentStamp: '<historical>' prior: 0! Contributed by Bob Arning as part of the ObjectExplorer package. ! !ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'RAA 6/21/1999 10:50'! with: anObject name: aString model: aModel ^self new setItem: anObject name: aString model: aModel! ! !ObjectExplorerWrapper class methodsFor: 'as yet unclassified' stamp: 'nk 7/24/2003 09:16'! with: anObject name: aString model: aModel parent: aParent ^self new setItem: anObject name: aString model: aModel parent: aParent ! ! !OneFilePerClass methodsFor: 'loading' stamp: 'ads 12/3/2010 12:32'! filePathForClass: aClass | classCatDirName | classCatDirName := self validNameForDir: aClass category in: self rootDirectory. ^ classCatDirName, self rootDirectory pathNameDelimiter asString, (self fileNameForClass: aClass)! ! !OneFilePerClass methodsFor: 'loading' stamp: 'sm 4/21/2011 23:08'! saveScriptForLoadingPackageBackIn: p | file dirName | file := self rootDirectory newFileNamed: self rootName, '.st'. (file respondsTo: #lineEndConvention:) ifTrue: [ file lineEndConvention: #lf. ]. preambleBlock ifNotNil: [ preambleBlock value: file ]. file nextPutAll: '{'; cr. (self classesInOrderForLoading: p) do: [:class | file nextPutAll: String tab, (self filePathForClass: class) printString, '.'; cr. ]. dirName := (transporter baseDirectory = FileDirectory default ifTrue: [''] ifFalse: [transporter baseDirectory localName, FileDirectory pathNameDelimiter]), self rootName. file nextPutAll: '} do: [:fileName | ((FileDirectory default directoryNamed: ', dirName printString, ') readOnlyFileNamed: fileName) fileIn].'; cr. postscriptBlock ifNotNil: [ postscriptBlock value: file ]. file close.! ! !OneFilePerClass methodsFor: 'saving' stamp: 'ads 12/3/2010 13:34'! fileNameForClass: cls ^ cls theNonMetaClass name, FileDirectory dot, 'st'! ! !OneFilePerClass methodsFor: 'saving' stamp: 'sm 4/21/2011 23:10'! newFileForClass: cls do: blk | catDir fileName f | catDir := self classCategoryDirFor: cls theNonMetaClass category. fileName := self fileNameForClass: cls. (catDir fileExists: fileName) ifTrue: [ f := catDir fileNamed: fileName. f setToEnd. ] ifFalse: [ f := catDir newFileNamed: fileName. ]. (f respondsTo: #lineEndConvention:) ifTrue: [ f lineEndConvention: #lf. ]. blk value: f. f close.! ! !OneFilePerClass methodsFor: 'saving' stamp: 'ads 12/14/2010 14:16'! saveAllExtensionMethodsForPackage: p p extensionClasses asArray do: [:cls | self newFileForClass: cls do: [:f | (p extensionCategoriesForClass: cls) do: [:cat | cls fileOutCategory: cat on: f moveSource: false toFile: 0. ]. ]. ] displayingProgress: 'Saving ', p name, ' extension methods'.! ! !OneFilePerClass methodsFor: 'saving' stamp: 'ads 12/14/2010 10:33'! saveClass: class forPackage: p self newFileForClass: class do: [:f | class fileOutOn: f moveSource: false toFile: 0 filteringCategoriesBy: [:cat :classOrMetaclass | p includesMethodCategory: cat ofClass: classOrMetaclass]. ].! ! !OpaqueForm methodsFor: 'private' stamp: 'ssa 8/21/2009 20:42'! colormapIfNeededFor: df ^self colorForm colormapIfNeededFor: df! ! !OpaqueForm methodsFor: 'private' stamp: 'ssa 8/22/2009 13:50'! setFigure: figureForm shape: shapeForm "Initialize the instance variables." | figure shape | figure _ figureForm. shape _ ColorForm mappingWhiteToTransparentFrom:( shapeForm asFormOfDepth: 8). figure displayOn: shape at: 0@0 clippingBox: figure boundingBox rule: Form paint fillColor: nil. self colorForm: shape! ! !OpaqueForm methodsFor: 'display box access' stamp: 'ssa 8/21/2009 20:28'! computeBoundingBox "Answer the minimum enclosing rectangle around the image." ^self colorForm boundingBox! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:44'! colorForm "Answer the value of colorForm" self! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:44'! colorForm: anObject "Set the value of colorForm" self become: anObject! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! figure "Answer the visible image of the receiver." ^ self colorForm! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! offset "Answer the offset for displaying the image." ^ self figure offset! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:31'! shape "Answer the form that indicates what part of the background should get occluded in displaying the receiver." ^ self colorForm! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:34'! valueAt: aPoint "Answer the bit of the form image at position aPoint. The value is either 0, 1 or 2 where 0 is white, 1 is black, 2 is transparent." (self colorForm isTransparentAt: aPoint) ifTrue:[^2]. ^(self colorAt: aPoint) isBlack ifTrue:[1]ifFalse:[0]! ! !OpaqueForm methodsFor: 'accessing' stamp: 'ssa 8/21/2009 20:37'! valueAt: aPoint put: value "Store a bit of the form image at position aPoint. The value is either 0, 1 or 2 where 0 is white, 1 is black, 2 is transparent." (1 - (value//2)) = 2 ifTrue:[self colorForm colorAt: aPoint put: Color transparent] ifFalse:[value\\2 = 0 ifTrue:[self colorForm colorAt: aPoint put: Color white] ifFalse:[self colorForm colorAt: aPoint put: Color black]]! ! !OpaqueForm methodsFor: 'displaying' stamp: 'ssa 9/2/2009 09:30'! displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aColor "Display the receiver on the display medium aDisplayMedium positioned at aDisplayPoint within the rectangle clipRectangle and with the rule, ruleInteger, and mask, aForm. " self colorForm displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aColor! ! !OpaqueForm methodsFor: 'displaying' stamp: 'ssa 8/21/2009 20:39'! displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aColor "See comment in Form." self colorForm displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: Form under fillColor: aColor! ! !OpaqueForm methodsFor: 'printing' stamp: 'ssa 8/21/2009 20:40'! storeOn: aStream "Append to the argument aStream a sequence of characters that is an expression whose evaluation creates an object similar to the receiver. The general format for OpaqueForm is OpaqueForm figure: ( figure ) shape: ( shape )." aStream nextPutAll: '(OpaqueForm colorForm: ('. self colorForm storeOn: aStream. aStream nextPutAll: '))'! ! !OpaqueForm methodsFor: 'editing'! bitEdit "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." BitEditor openOnForm: self "OpaqueForm makeStar bitEdit."! ! !OpaqueForm commentStamp: '<historical>' prior: 0! OpaqueForms include a shape as well as a figure form. The shape indicates what part of the background should get occluded in displaying, so that patterns other than black in the figure form will still appear opaque. Instance Variables: figure <Form> the actual image shape <Form> the mask for displaying! !OpaqueForm class methodsFor: 'examples' stamp: 'ssa 8/21/2009 20:41'! makeStar "Answer a new OpaqueForm in the shape of a five-pointed star filled with black." "OpaqueForm makeStar." "OpaqueForm makeStar bitEdit" | figure shape pen formRect | formRect_ 0@0 extent: 50@50. pen _ Pen new. pen defaultNib: 2. Display fill: formRect fillColor: Color white. pen north; place: formRect center; spiral: 45 angle: 144. shape _ Form fromDisplay: formRect. pen fillColor: Color white; north; place: formRect center; spiral: 30 angle: 144. figure _ Form fromDisplay: formRect. ^ OpaqueForm figure: figure shape: shape! ! !OpaqueForm class methodsFor: 'examples'! starCursor "Make the cursor track a five-pointed star." "OpaqueForm starCursor" Cursor blank showWhile: [self makeStar follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]! ! !OpaqueForm class methodsFor: 'instance creation'! figure: figureForm shape: shapeForm "Answer a new instance of the receiver whose figure and shape forms are defined by the arguments." ^ self new setFigure: figureForm shape: shapeForm! ! !OpaqueForm class methodsFor: 'instance creation'! shape: aSolidForm "Answer a new instance of the receiver that is black where aSolidForm is black and transparent where aSolidForm is white." ^ self new setFigure: aSolidForm shape: aSolidForm! ! !OrderedCollection methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:44'! inspectorClass ^ OrderedCollectionInspector! ! !OrderedCollection methodsFor: 'adding' stamp: 'ssa 9/9/2009 11:48'! addAll: aCollection after: anObject "Add each element of aCollection at my end. Answer aCollection." | after | after _ anObject. aCollection do:[:each| self add: each after: after. after _ each]. ^aCollection! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:54'! add: newObject newObject ifNil:[self halt:'trying to add nil']. ^super add: newObject! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:56'! addAll: aCollection "Add each element of aCollection at my end. Answer aCollection." (aCollection includes: nil) ifTrue:[self halt:'trying to add nil']. ^ super addAll: aCollection! ! !OrderedCollectionWithNilDetector methodsFor: 'adding' stamp: 'ssa 11/24/2009 19:57'! insert: anObject before: spot anObject ifNil:[self halt:'trying to add nil']. ^super insert: anObject before: spot! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:38'! dependenciesOfPackageNamed: pkgNameAsString | deps classes | classes := self referencesInPackageNamed: pkgNameAsString. deps := Dictionary new. classes do: [:aClass | | pkg | pkg := PackageOrganizer default packageOfClass: aClass ifNone: []. pkg ifNil: [Transcript cr; show: 'WARNING: No package for ' , pkg] ifNotNil: [(deps at: pkg packageName ifAbsentPut: [OrderedCollection new]) add: aClass]]. deps removeKey: pkgNameAsString ifAbsent: []. ^ deps! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:47'! referencesInClass: aClass | classes | classes := IdentitySet new. aClass isTrait ifFalse: [ classes add: aClass superclass ]. "The following line is wrong because methods may be defined in a different package" "aClass methods do: [ :cm | classes addAll: (self referencesInCompiledMethod: cm) ]." ^ classes! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:32'! referencesInCompiledMethod: aCompiledMethod | classes | classes := IdentitySet new. 1 to: aCompiledMethod numLiterals do: [:i | | lit | ((lit := aCompiledMethod literalAt: i) isVariableBinding and: [ lit value isBehavior ]) ifTrue: [classes add: lit value ]]. ^ classes! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:43'! referencesInPackage: aPackageInfo | classes | classes := IdentitySet new. aPackageInfo classes do: [ :cls | classes addAll: (self referencesInClass: cls) ]. aPackageInfo methods do: [ :mr | classes addAll: (self referencesInCompiledMethod: mr compiledMethod )]. ^ classes! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:33'! referencesInPackageNamed: pkgNameAsString | pi | pi := PackageOrganizer default packageNamed: pkgNameAsString ifAbsent: [^ self]. ^ self referencesInPackage: pi! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'StephaneDucasse 9/9/2010 14:50'! testPackage: pkgName dependsExactlyOn: pkgList "Ensure that the package with the given name depends only on the packages in pkgList. NOTE: If you use this for fixing dependencies, classDeps includes the classes and users from the package(s) not declared as dependents. Basically, you need to fix all the references in classDeps to make the test pass." | classDeps pi pkgDeps | classDeps := IdentityDictionary new. pi := PackageOrganizer default packageNamed: pkgName ifAbsent:[^self]. "unloaded" pi classes do: [ :pkgClass | (classDeps at: (pkgClass superclass ifNil: [ProtoObject]) ifAbsentPut:[OrderedCollection new]) add: pkgClass name, ' superclass'.]. pi methods do: [ :mref | | cm | cm := mref compiledMethod. 1 to: cm numLiterals do: [ :i | | lit | ((lit := cm literalAt: i) isVariableBinding and:[lit value isBehavior]) ifTrue:[(classDeps at: lit value ifAbsentPut:[OrderedCollection new]) add: cm methodClass asString, '>>', cm selector]]]. pkgDeps := Dictionary new. classDeps keys do: [ :aClass | | pkg | pkg := PackageOrganizer default packageOfClass: aClass ifNone:[nil]. pkg ifNil: [ Transcript cr; show: 'WARNING: No package for ', aClass. (classDeps removeKey: aClass) do:[:each| Transcript crtab; show: each]] ifNotNil: [(pkgDeps at: pkg name ifAbsentPut:[OrderedCollection new]) add: aClass]]. (pkgDeps removeKey: pkgName ifAbsent: [#()]) do: [ :aClass | classDeps removeKey: aClass ifAbsent: []]. pkgList do: [ :pkg | self assert: (pkgDeps includesKey: pkg) description: pkgName, ' no longer depends on ', pkg. (pkgDeps removeKey: pkg ifAbsent: [#()]) do: [ :aClass | classDeps removeKey: aClass ifAbsent:[]]]. classDeps keysAndValuesDo: [ :class :deps | Transcript cr; show: class name, ' dependencies:'. deps do: [ :each | Transcript crtab; show: each]]. self assert: pkgDeps isEmpty description: pkgName, ' now depends on ', pkgDeps. ! ! !PackageDependencyTest methodsFor: 'test utility' stamp: 'Alexandre Bergel 5/22/2010 15:36'! testPackage: pkgName dependsOnlyOn: pkgList "Ensure that the package with the given name depends only on the packages in pkgList" | classes pi deps | deps := self dependenciesOfPackageNamed: pkgName. pkgList do: [:pkg | self assert: (deps includesKey: pkg). deps removeKey: pkg]. self assert: deps isEmpty! ! !PackageInfo methodsFor: 'testing' stamp: 'avi 3/9/2004 15:53'! category: categoryName matches: prefix ^ categoryName notNil and: [categoryName = prefix or: [categoryName beginsWith: prefix, '-']]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:18'! coreCategoriesForClass: aClass ^ aClass organization categories select: [:cat | (self isForeignClassExtension: cat) not]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'! coreMethodsForClass: aClass ^ (aClass selectors difference: ((self foreignExtensionMethodsForClass: aClass) collect: [:r | r methodSymbol])) asArray collect: [:sel | self referenceForMethod: sel ofClass: aClass]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:20'! extensionCategoriesForClass: aClass ^ aClass organization categories select: [:cat | self isYourClassExtension: cat]! ! !PackageInfo methodsFor: 'testing' stamp: 'avi 4/6/2004 15:16'! extensionMethodsForClass: aClass ^ (self extensionCategoriesForClass: aClass) gather: [:cat | ((aClass organization listAtCategoryNamed: cat) ifNil: [#()]) collect: [:sel | self referenceForMethod: sel ofClass: aClass]]! ! !PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'! extensionMethodsFromClasses: classes ^classes gather: [:class | self extensionMethodsForClass: class]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:22'! foreignExtensionCategoriesForClass: aClass ^ aClass organization categories select: [:cat | self isForeignClassExtension: cat]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'! foreignExtensionMethodsForClass: aClass ^ (self foreignExtensionCategoriesForClass: aClass) gather: [:cat | (aClass organization listAtCategoryNamed: cat) collect: [:sel | self referenceForMethod: sel ofClass: aClass]]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'! includesClass: aClass ^ self includesSystemCategory: aClass theNonMetaClass category! ! !PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:08'! includesClassNamed: aClassName ^ self includesSystemCategory: ((SystemOrganization categoryOfElement: aClassName) ifNil: [^false])! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 12/5/2002 00:16'! includesMethod: aSymbol ofClass: aClass aClass ifNil: [^ false]. ^ self includesMethodCategory: ((aClass organization categoryOfElement: aSymbol) ifNil: [' ']) ofClass: aClass! ! !PackageInfo methodsFor: 'testing' stamp: 'dvf 9/17/2002 00:18'! includesMethodCategory: categoryName ofClass: aClass ^ (self isYourClassExtension: categoryName) or: [(self includesClass: aClass) and: [(self isForeignClassExtension: categoryName) not]]! ! !PackageInfo methodsFor: 'testing' stamp: 'dvf 7/23/2003 14:06'! includesMethodCategory: categoryName ofClassNamed: aClass ^ (self isYourClassExtension: categoryName) or: [(self includesClassNamed: aClass) and: [(self isForeignClassExtension: categoryName) not]]! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/14/2002 18:06'! includesMethodReference: aMethodRef ^ self includesMethod: aMethodRef methodSymbol ofClass: aMethodRef actualClass! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'! includesSystemCategory: categoryName ^ self category: categoryName matches: self systemCategoryPrefix! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:23'! isForeignClassExtension: categoryName ^ categoryName first = $* and: [(self isYourClassExtension: categoryName) not]! ! !PackageInfo methodsFor: 'testing' stamp: 'avi 11/10/2003 15:42'! isOverrideMethod: aMethodReference ^ aMethodReference category endsWith: '-override'! ! !PackageInfo methodsFor: 'testing' stamp: 'avi 3/10/2004 12:37'! isYourClassExtension: categoryName ^ categoryName notNil and: [self category: categoryName asLowercase matches: self methodCategoryPrefix]! ! !PackageInfo methodsFor: 'testing' stamp: 'dvf 10/18/2002 23:22'! outsideClasses ^ProtoObject withAllSubclasses difference: self classesAndMetaClasses! ! !PackageInfo methodsFor: 'testing' stamp: 'ab 11/13/2002 01:25'! referenceForMethod: aSymbol ofClass: aClass ^ MethodReference new setStandardClass: aClass methodSymbol: aSymbol! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 10/17/2002 00:05'! categoryName |category| category _ self class category. ^ (category endsWith: '-Info') ifTrue: [category copyUpToLast: $-] ifFalse: [category]! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 10/16/2002 21:22'! externalName ^ self packageName! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 6/10/2003 17:21'! methodCategoryPrefix ^ methodCategoryPrefix ifNil: [methodCategoryPrefix _ '*', self packageName asLowercase]! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 10/16/2002 16:57'! packageName ^ packageName ifNil: [packageName _ self categoryName]! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 10/16/2002 16:56'! packageName: aString packageName _ aString! ! !PackageInfo methodsFor: 'naming' stamp: 'ab 10/28/2002 10:38'! systemCategoryPrefix ^ self packageName! ! !PackageInfo methodsFor: 'listing' stamp: 'ac 5/14/2003 16:23'! classes ^(self systemCategories gather: [:cat | (SystemOrganization listAtCategoryNamed: cat) collect: [:className | Smalltalk at: className]]) sortBy: [:a :b | a className <= b className]! ! !PackageInfo methodsFor: 'listing' stamp: 'dvf 9/17/2002 00:56'! classesAndMetaClasses | baseClasses | baseClasses := self classes. ^baseClasses , (baseClasses collect: [:c | c class])! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 11/13/2002 01:23'! coreMethods ^ self classesAndMetaClasses gather: [:class | self coreMethodsForClass: class]! ! !PackageInfo methodsFor: 'listing' stamp: 'cwp 3/17/2004 21:32'! extensionClasses ^ self externalClasses reject: [:class | (self extensionCategoriesForClass: class) isEmpty]! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 6/10/2003 17:12'! extensionMethods ^ self externalClasses gather: [:class | self extensionMethodsForClass: class]! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 12/3/2002 14:38'! foreignClasses | s | s _ IdentitySet new. self foreignSystemCategories do: [:c | (SystemOrganization listAtCategoryNamed: c) do: [:cl | | cls | cls _ Smalltalk at: cl. s add: cls; add: cls class]]. ^ s! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 12/3/2002 14:34'! foreignSystemCategories ^ SystemOrganization categories reject: [:cat | self includesSystemCategory: cat] ! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 7/6/2003 21:49'! methods ^ (self extensionMethods, self coreMethods) select: [:method | method isValid and: [(#(DoIt DoItIn:) includes: method methodSymbol) not]]! ! !PackageInfo methodsFor: 'listing' stamp: 'avi 11/10/2003 15:35'! overrideMethods ^ self extensionMethods select: [:ea | self isOvverideMethod: ea]! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 11/14/2002 18:39'! selectors ^ self methods collect: [:ea | ea methodSymbol]! ! !PackageInfo methodsFor: 'listing' stamp: 'ab 11/11/2002 21:51'! systemCategories ^ SystemOrganization categories select: [:cat | self includesSystemCategory: cat]! ! !PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:16'! externalCallers ^ self externalRefsSelect: [:literal | literal isKindOf: Symbol] thenCollect: [:l | l].! ! !PackageInfo methodsFor: 'dependencies' stamp: 'ab 6/10/2003 17:18'! externalClasses | myClasses | myClasses _ self classesAndMetaClasses. ^ Array streamContents: [:s | ProtoObject withAllSubclassesDo: [:class | (myClasses includes: class) ifFalse: [s nextPut: class]]]! ! !PackageInfo methodsFor: 'dependencies' stamp: 'avi 2/29/2004 13:38'! externalRefsSelect: selBlock thenCollect: colBlock | pkgMethods dependents refs extMethods otherClasses otherMethods classNames | classNames _ self classes collect: [:c | c name]. extMethods _ self extensionMethods collect: [:mr | mr methodSymbol]. otherClasses _ self externalClasses difference: self externalSubclasses. otherMethods _ otherClasses gather: [:c | c selectors]. pkgMethods _ self methods asSet collect: [:mr | mr methodSymbol]. pkgMethods removeAllFoundIn: otherMethods. dependents _ Set new. otherClasses do: [:c | c selectorsAndMethodsDo: [:sel :compiled | (extMethods includes: sel) ifFalse: [refs _ compiled literals select: selBlock thenCollect: colBlock. refs do: [:ea | ((classNames includes: ea) or: [pkgMethods includes: ea]) ifTrue: [dependents add: (self referenceForMethod: sel ofClass: c) -> ea]]]]]. ^ dependents! ! !PackageInfo methodsFor: 'dependencies' stamp: 'cwp 11/13/2002 00:24'! externalSubclasses | pkgClasses subClasses | pkgClasses _ self classes. subClasses _ Set new. pkgClasses do: [:c | subClasses addAll: (c allSubclasses)]. ^ subClasses difference: pkgClasses ! ! !PackageInfo methodsFor: 'dependencies' stamp: 'ab 11/18/2002 01:15'! externalUsers ^ self externalRefsSelect: [:literal | literal isVariableBinding] thenCollect: [:l | l key]! ! !PackageInfo methodsFor: 'modifying' stamp: 'avi 10/13/2003 15:40'! addCoreMethod: aMethodReference | category | category _ self baseCategoryOfMethod: aMethodReference. aMethodReference actualClass organization classify: aMethodReference methodSymbol under: category suppressIfDefault: false! ! !PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:17'! addExtensionMethod: aMethodReference | category | category _ self baseCategoryOfMethod: aMethodReference. aMethodReference actualClass organization classify: aMethodReference methodSymbol under: self methodCategoryPrefix, '-', category! ! !PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:16'! addMethod: aMethodReference (self includesClass: aMethodReference class) ifTrue: [self addCoreMethod: aMethodReference] ifFalse: [self addExtensionMethod: aMethodReference]! ! !PackageInfo methodsFor: 'modifying' stamp: 'avi 10/13/2003 15:39'! baseCategoryOfMethod: aMethodReference | oldCat oldPrefix tokens | oldCat _ aMethodReference category. ({ 'as yet unclassified'. 'all' } includes: oldCat) ifTrue: [ oldCat _ '' ]. tokens _ oldCat findTokens: '*-' keep: '*'. "Strip off any old prefixes" ((tokens at: 1 ifAbsent: [ '' ]) = '*') ifTrue: [ [ ((tokens at: 1 ifAbsent: [ '' ]) = '*') ] whileTrue: [ tokens removeFirst ]. oldPrefix _ tokens removeFirst asLowercase. [ (tokens at: 1 ifAbsent: [ '' ]) asLowercase = oldPrefix ] whileTrue: [ tokens removeFirst ]. ]. tokens isEmpty ifTrue: [^ 'as yet unclassified']. ^ String streamContents: [ :s | tokens do: [ :tok | s nextPutAll: tok ] separatedBy: [ s nextPut: $- ]]! ! !PackageInfo methodsFor: 'modifying' stamp: 'avi 10/11/2003 15:14'! removeMethod: aMethodReference! ! !PackageInfo methodsFor: 'removing' stamp: 'ads 1/30/2011 10:40'! removeFromSystem | extensionCategoriesByClass classes systemCategories | "Get the collections of classes and methods before actually doing the removal, so that removing the PackageInfo package will work." extensionCategoriesByClass := Dictionary new. self extensionClasses do: [:cls | extensionCategoriesByClass at: cls put: (self extensionCategoriesForClass: cls)]. classes := self classes. systemCategories := self systemCategories. extensionCategoriesByClass keysAndValuesDo: [:cls :cats | cats do: [:cat | cls removeCategory: cat]]. classes do: [:cls | cls removeFromSystem]. systemCategories do: [:cat | (SystemOrganization listAtCategoryNamed: cat) isEmpty ifTrue: [SystemOrganization removeCategory: cat]]. ! ! !PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 00:09'! = other ^ other species = self species and: [other packageName = self packageName]! ! !PackageInfo methodsFor: 'comparing' stamp: 'avi 10/11/2003 14:20'! hash ^ packageName hash! ! !PackageInfo methodsFor: '*transporter' stamp: 'ads 12/5/2010 23:40'! , p ^ CompositePackageInfo new packages: {self. p}; yourself! ! !PackageInfo methodsFor: '*transporter' stamp: 'ads 1/26/2011 14:13'! includesPackage: p ^ self = p! ! !PackageInfo methodsFor: '*transporter' stamp: 'ads 12/10/2010 12:05'! name ^ self packageName! ! !PackageInfo methodsFor: '*transporter' stamp: 'ads 1/26/2011 13:38'! printOn: aStream aStream nextPutAll: self packageName.! ! !PackageInfo methodsFor: '*transporter' stamp: 'ads 1/26/2011 16:15'! revertToVersionBeforeTeam: team self extensionMethods do: [:m | team revertToOldVersionOrRemove: m]. self classes do: [:cls | cls removeFromSystem]. self systemCategories do: [:cat | SystemOrganization removeCategoryIfEmpty: cat]. ! ! !PackageInfo commentStamp: '<historical>' prior: 0! Subclass this class to create new Packages.! !PackageInfo class methodsFor: 'packages access' stamp: 'avi 11/12/2003 23:00'! named: aString ^ self new packageName: aString! ! !PackageInfo class methodsFor: 'class initialization' stamp: 'avi 2/18/2004 00:46'! initialize self allSubclassesDo: [:ea | ea new register]! ! !PackageInfo class methodsFor: 'compatibility' stamp: 'avi 3/9/2004 16:28'! default ^ self allPackages detect: [:ea | ea class = self] ifNone: [self new register]! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'accessing' stamp: 'ads 1/24/2011 17:31'! classesToBeRedefined | classNames | classNames := Set new. self trickyModificationsThatNeedToBeDoneInOrder do: [:a | a size = 1 ifTrue: [classNames add: a first]. ]. ^ classNames collect: [:className | Smalltalk at: className asSymbol]! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'accessing' stamp: 'ads 1/24/2011 15:24'! extensionClasses | classes | classes := Set new. self extensionMethods do: [:m | classes add: m actualClass]. ^ classes! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'accessing' stamp: 'ads 1/24/2011 17:32'! extensionMethods | result | result := Set new. self trickyModificationsThatNeedToBeDoneInOrder do: [:a | a size = 2 ifTrue: [result add: ((Smalltalk classNamed: a first) methodNamed: a second)]. ]. ^ result! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'accessing' stamp: 'ads 1/24/2011 14:11'! name ^ self class name! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'accessing' stamp: 'sm 3/11/2011 23:13'! trickyModificationsThatNeedToBeDoneInOrder: someDefinitions trickyModificationsThatNeedToBeDoneInOrder := someDefinitions! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'comparing' stamp: 'ads 1/26/2011 13:36'! = other ^ self species = other species! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'comparing' stamp: 'ads 1/26/2011 13:36'! hash ^ self species hash! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'composing' stamp: 'ads 1/24/2011 15:11'! , p ^ CompositePackageInfo new packages: {self. p}; yourself! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'composing' stamp: 'ads 1/26/2011 14:11'! includesPackage: p ^ self = p! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'testing' stamp: 'ads 1/24/2011 17:31'! includesClass: aClass ^ self classesToBeRedefined includes: aClass theNonMetaClass! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'testing' stamp: 'ads 1/24/2011 17:32'! includesMethod: aSymbol ofClass: aClass aClass ifNil: [^ false]. ^ self extensionMethods includes: (aClass methodNamed: aSymbol)! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'saving' stamp: 'ads 2/2/2011 15:46'! saveClassAndMethodModificationsInOrder: classAndMethodSpecs on: aFileStream classAndMethodSpecs do: [:spec | | class | class := Smalltalk classNamed: (spec at: 1). spec size > 1 ifTrue: [ | selector | selector := (spec at: 2) asSymbol. class methodDict at: selector ifAbsent: [self error: 'Could not find method named ', selector printString, ' in class ', class name]. class printMethodChunk: selector withPreamble: true on: aFileStream moveSource: false toFile: 0. ] ifFalse: [ aFileStream nextChunkPut: class definition; cr. ]. ] displayingProgress: 'Saving tricky stuff that needs to happen in order'. ! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'saving' stamp: 'sm 3/11/2011 20:39'! saveTrickyModificationsToFile: aFileStream self saveClassAndMethodModificationsInOrder: self trickyModificationsThatNeedToBeDoneInOrder on: aFileStream.! ! !PackageWhoseContentsMustBeTransportedInOrder methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 23:13'! trickyModificationsThatNeedToBeDoneInOrder ^ trickyModificationsThatNeedToBeDoneInOrder.! ! !Paragraph methodsFor: 'accessing' stamp: 'dmu 4/1/2009 20:01'! destFormSema: s destFormSema _ s! ! !Paragraph methodsFor: 'converting' stamp: 'ssa 9/4/2009 10:44'! asForm "Answer a Form made up of the bits that represent the receiver's displayable text." | theForm oldBackColor oldForeColor | textStyle isTTCStyle ifTrue: [ theForm _ (Form extent: compositionRectangle extent depth: Display depth) offset: offset. ] ifFalse: [ theForm _ (ColorForm extent: compositionRectangle extent) offset: offset; colors: (Array with: (backColor == nil ifTrue: [Color transparent] ifFalse: [backColor]) with: (foreColor == nil ifTrue: [Color black] ifFalse: [foreColor])). ]. oldBackColor _ backColor. oldForeColor _ foreColor. backColor _ Color white. foreColor _ Color black. self displayOn: theForm at: 0@0 clippingBox: theForm boundingBox rule: Form over fillColor: nil. backColor _ oldBackColor. foreColor _ oldForeColor. ^ theForm "Example: | p | p _ 'Abc' asParagraph. p foregroundColor: Color red backgroundColor: Color black. p asForm displayOn: Display at: 30@30 rule: Form over" ! ! !Paragraph methodsFor: 'private' stamp: 'dmu 4/1/2009 19:38'! compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint compositionRectangle _ compositionRect copy. text _ aText. textStyle _ aTextStyle. rule _ DefaultRule. mask _ nil. "was DefaultMask " marginTabsLevel _ 0. destFormSema _ Semaphore forMutualExclusion. self destinationForm: Display. offset _ aPoint. ^self composeAll! ! !Paragraph methodsFor: 'private' stamp: 'ssa 4/7/2009 12:39'! displayOn: aDisplayMedium lines: lineInterval | saveDestinationForm | destFormSema isNil ifTrue:[self destFormSema: Semaphore forMutualExclusion]. destFormSema critical: [ saveDestinationForm _ destinationForm. self destinationForm: aDisplayMedium. self displayLines: lineInterval. destinationForm _ saveDestinationForm ]! ! !ParagraphEditor methodsFor: 'controlling'! controlActivity "Hacked to supprt MSWScrollBarView - ssa 12/10/97 17:07" self scrollBarContainsCursor ifTrue: [(self view superView isKindOf: MSWScrollBarView) ifFalse:[self scroll]] ifFalse: [self processKeyboard. self processMouseButtons]! ! !ParagraphEditor methodsFor: 'scrolling'! scrollView: anInteger "Paragraph scrolling uses opposite polarity" "Adjusted to keep text from scrolling off the view - ssa 1/15/98 15:22. The - 30 below is the hack to allow for some empty space to show at the bottom." | maximumAmount minimumAmount amount | maximumAmount _ paragraph clippingRectangle top - paragraph compositionRectangle top max: 0. minimumAmount _ paragraph clippingRectangle bottom - paragraph compositionRectangle bottom - 30 min: 0. amount _ (anInteger min: maximumAmount) max: minimumAmount. ^ self scrollBy: amount negated! ! !ParagraphEditor methodsFor: 'scrolling'! updateMarker "Hacked to catch this scrolling 'event'. ssa 12/5/97 16:22" "A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph." self moveMarkerTo: self computeMarkerRegion. "A hack to notify the MSWScrollBarController" (self view superView isKindOf: MSWScrollBarView) ifTrue:[self view superView updateElevator]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 9/15/2009 16:53'! adjustWidths self view topView adjustWidths! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 3/1/2010 11:41'! browseIt "Launch a browser for the current selection, if appropriate" | aSymbol anEntry brow | Preferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt]. self lineSelectAndEmptyCheck: [^ self]. (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash]. self terminateAndInitializeAround: [aSymbol first isUppercase ifTrue: [anEntry _ (Smalltalk at: aSymbol ifAbsent: [ self systemNavigation browseAllImplementorsOf: aSymbol. ^ nil]). anEntry isNil ifTrue: [^ view flash]. (anEntry isKindOf: Class) ifFalse: [anEntry _ anEntry class]. [^ self browseClassFromIt]value. "<<<<<<<<<<<<<<<<<< ssa added" brow _ Preferences browseToolClass new. brow setClass: anEntry selector: nil. brow class openBrowserView: (brow openEditString: nil) label: 'System Browser'] ifFalse: [ self systemNavigation browseAllImplementorsOf: aSymbol]]! ! !ParagraphEditor methodsFor: 'menu messages' stamp: 'ssa 1/21/2010 16:27'! methodSourceContainingIt "Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source). " self lineSelectAndEmptyCheck: [^ self]. self systemNavigation browseMethodsWithSourceString: self selection string! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ssa 1/6/2010 20:32'! exploreIt: characterStream "Inspect the selection -- invoked via cmd-i. If there is no current selection, use the current line." sensor keyboard. "flush character" self terminateAndInitializeAround: [self exploreIt]. ^ true! ! !ParagraphEditor methodsFor: 'editing keys' stamp: 'ssa 6/1/2010 16:55'! printIt: characterStream "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 2/29/96 sw: don't call selectLine now, since it's called by doIt" sensor keyboard. "flush character" self terminateAndInitializeAround: [self printIt]. ^ true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'ssa 1/20/2010 11:06'! cursorDown: characterStream "Private - Move cursor from position in current line to same position in next line. If next line too short, put at end. If shift key down, select." self closeTypeIn: characterStream. paragraph isEmpty ifTrue:[Sensor flushKeyboard. ^true]. self moveCursor:[:position | self sameColumn: position newLine:[:line | line + 1] forward: true] forward: true specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'nonediting/nontyping keys' stamp: 'ssa 1/20/2010 11:05'! cursorUp: characterStream "Private - Move cursor from position in current line to same position in prior line. If prior line too short, put at end" self closeTypeIn: characterStream. paragraph isEmpty ifTrue:[Sensor flushKeyboard. ^true]. self moveCursor: [:position | self sameColumn: position newLine:[:line | line - 1] forward: false] forward: false specialBlock:[:dummy | dummy]. ^true! ! !ParagraphEditor methodsFor: 'private' stamp: 'ssa 1/20/2010 10:55'! sameColumn: start newLine: lineBlock forward: isForward "Private - Compute the index in my text with the line number derived from lineBlock," " a one argument block accepting the old line number. The position inside the line will be preserved as good as possible" "The boolean isForward is used in the border case to determine if we should move to the beginning or the end of the line." | wordStyle column currentLine offsetAtTargetLine targetEOL lines numberOfLines currentLineNumber targetLineNumber | wordStyle _ Preferences wordStyleCursorMovement. wordStyle ifTrue: [ lines _ paragraph lines. numberOfLines := paragraph numberOfLines. currentLineNumber _ paragraph lineIndexOfCharacterIndex: start. currentLine _ lines at: (currentLineNumber max: 1)] ifFalse: [ lines _ self lines. numberOfLines := lines size. currentLine _ lines detect:[:lineInterval | lineInterval last >= start] ifNone:[lines last]. currentLineNumber _ currentLine second]. column _ start - currentLine first. targetLineNumber _ ((lineBlock value: currentLineNumber) max: 1) min: numberOfLines. offsetAtTargetLine _ (lines at: targetLineNumber) first. targetEOL _ (lines at: targetLineNumber) last + (targetLineNumber == numberOfLines ifTrue:[1]ifFalse:[0]). targetLineNumber == currentLineNumber "No movement or movement failed. Move to beginning or end of line." ifTrue:[^isForward ifTrue:[targetEOL] ifFalse:[offsetAtTargetLine]]. ^offsetAtTargetLine + column min: targetEOL.! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 8/31/2009 10:30'! compileSelectionFor: anObject in: evalContext | methodNode method | methodNode _ [Compiler new compileNoPattern: self selection in: anObject class context: evalContext notifying: self ifFail: [^nil]] on: OutOfScopeNotification do: [:ex | ex resume: true]. method _ methodNode generate: #(0 0 0 0). ^method copyWithTempNames: methodNode tempNames! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'dmu 9/17/2010 12:00'! debug: aCompiledMethod receiver: anObject in: evalContext | selector guineaPig debugger context | selector _ evalContext isNil ifTrue: [#DoIt] ifFalse: [#DoItIn:]. anObject class addSelectorSilently: selector withMethod: aCompiledMethod. guineaPig _ evalContext isNil ifTrue: [[anObject DoIt] newProcess] ifFalse: [[anObject DoItIn: evalContext] newProcess]. context _ guineaPig suspendedContextWaitingIfNecessary. debugger _ Debugger new process: guineaPig controller: ((Smalltalk isMorphic not and: [ScheduledControllers inActiveControllerProcess]) ifTrue: [ScheduledControllers activeController] ifFalse: [nil]) context: context isolationHead: nil. debugger openFullNoSuspendLabel: 'Debug it'. [debugger interruptedContext method == aCompiledMethod] whileFalse: [debugger send]. anObject class basicRemoveSelector: selector! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! debugIt | method receiver context | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model debug: self selection asString notifying:self]. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. receiver _ model doItReceiver. context _ model doItContext] ifFalse: [receiver _ context _ nil]. self lineSelectAndEmptyCheck: [^self]. method _ self compileSelectionFor: receiver in: context. method notNil ifTrue: [self debug: method receiver: receiver in: context]. FakeClassPool adopt: nil! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! evaluate: someCode "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | someCode isEmpty ifTrue:[^ '']. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[model evaluate: someCode notifying:self] ifFalse:[ rcvr class evaluatorClass new evaluate: someCode readStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true]. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! evaluateSelection "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | self lineSelectAndEmptyCheck: [^ '']. (model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[model evaluate: self selection asString notifying:self] ifFalse:[ rcvr class evaluatorClass new evaluate: self selectionAsStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true]. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! exploreIt | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model exploreIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [result explore]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:32'! inspectIt "1/13/96 sw: minor fixup" | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model inspectIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [result inspect]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! installAsTest | | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model installAsTest: self selection asString notifying:self]. self halt:'not implemented for Squeak Workspaces yet'! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! parseIt ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model parseAndExplore: self selection asString notifying:self]. ! ! !ParagraphEditor methodsFor: 'do-its' stamp: 'ssa 7/7/2010 12:33'! printIt "Treat the current text selection as an expression; evaluate it. Insert the description of the result of evaluation after the selection and then make this description the new text selection." | result | ((Smalltalk includesKey: #Ly) and:[model isKindOf: (Smalltalk at: #LyWorkspace)]) ifTrue:[^model printIt: self selection asString notifying:self]. result _ self evaluateSelection. ((result isKindOf: FakeClassPool) or: [result == #failedDoit]) ifTrue: [view flash] ifFalse: [self afterSelectionInsertAndSelect: result printString]! ! !ParagraphEditor methodsFor: '*RVM-UI-Generic' stamp: 'ssa 9/8/2009 19:09'! buttonIt "launch a button to evaluate the selection" | topView someCode extent | someCode _ self selection. extent _ (someCode asText asDisplayText extent + (30@20)) max: 80@30. topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: extent . topView maximumSize: extent. topView addSubView: (RVMButtonView label: someCode action:[self evaluate: someCode]). topView controller open! ! !ParagraphEditor methodsFor: '*RVM-UI-Generic' stamp: 'ssa 9/8/2009 18:28'! buttonIt: characterStream "Called when user hits cmd-B. make a button of the selection" sensor keyboard. self buttonIt. ^ true! ! !ParagraphEditor class methodsFor: 'keyboard shortcut tables' stamp: 'ssa 1/29/2010 12:18'! initializeCmdKeyShortcuts "Initialize the (unshifted) command-key (or alt-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "ParagraphEditor initialize" | cmdMap cmds | cmdMap := Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: 1 + 1 put: #cursorHome:. "home key" cmdMap at: 4 + 1 put: #cursorEnd:. "end key" cmdMap at: 8 + 1 put: #backspace:. "ctrl-H or delete key" cmdMap at: 11 + 1 put: #cursorPageUp:. "page up key" cmdMap at: 12 + 1 put: #cursorPageDown:. "page down key" cmdMap at: 13 + 1 put: #crWithIndent:. "cmd-Return" cmdMap at: 27 + 1 put: #offerMenuFromEsc:. "escape key" cmdMap at: 28 + 1 put: #cursorLeft:. "left arrow key" cmdMap at: 29 + 1 put: #cursorRight:. "right arrow key" cmdMap at: 30 + 1 put: #cursorUp:. "up arrow key" cmdMap at: 31 + 1 put: #cursorDown:. "down arrow key" cmdMap at: 32 + 1 put: #selectWord:. "space bar key" cmdMap at: 127 + 1 put: #forwardDelete:. "del key" '0123456789-=' do: [:char | cmdMap at: char asciiValue + 1 put: #changeEmphasis:]. '([{''"<' do: [:char | cmdMap at: char asciiValue + 1 put: #enclose:]. cmdMap at: $, asciiValue + 1 put: #shiftEnclose:. cmds := #($a #selectAll: $b #browseIt: $c #copySelection: $d #doIt: $e #exploreIt: $f #find: $g #findAgain: $h #setSearchString: $i #inspectIt: $j #doAgainOnce: $k #offerFontMenu: $l #cancel: $m #implementorsOfIt: $n #sendersOfIt: $o #spawnIt: $p #printIt: $q #querySymbol: $r #revert: $s #save: $S saveAs:: $t #tempCommand: $u #align: $v #paste: $w #backWord: $x #cut: $y #swapChars: $z #undo:). 1 to: cmds size by: 2 do: [:i | cmdMap at: (cmds at: i) asciiValue + 1 put: (cmds at: i + 1)]. CmdActions := cmdMap! ! !ParagraphEditor class methodsFor: '*RVM-UI-Generic' stamp: 'ssa 2/9/2010 05:26'! initializeShiftCmdKeyShortcuts "Initialize the shift-command-key (or control-key) shortcut table." "NOTE: if you don't know what your keyboard generates, use Sensor kbdTest" "wod 11/3/1998: Fix setting of cmdMap for shifted keys to actually use the capitalized versions of the letters. TPR 2/18/99: add the plain ascii values back in for those VMs that don't return the shifted values." | cmdMap cmds | "shift-command and control shortcuts" cmdMap _ Array new: 256 withAll: #noop:. "use temp in case of a crash" cmdMap at: ( 1 + 1) put: #cursorHome:. "home key" cmdMap at: ( 4 + 1) put: #cursorEnd:. "end key" cmdMap at: ( 8 + 1) put: #forwardDelete:. "ctrl-H or delete key" cmdMap at: (11 + 1) put: #cursorPageUp:. "page up key" cmdMap at: (12 + 1) put: #cursorPageDown:. "page down key" cmdMap at: (13 + 1) put: #crWithIndent:. "ctrl-Return" cmdMap at: (27 + 1) put: #offerMenuFromEsc:. "escape key" cmdMap at: (28 + 1) put: #cursorLeft:. "left arrow key" cmdMap at: (29 + 1) put: #cursorRight:. "right arrow key" cmdMap at: (30 + 1) put: #cursorUp:. "up arrow key" cmdMap at: (31 + 1) put: #cursorDown:. "down arrow key" cmdMap at: (32 + 1) put: #selectWord:. "space bar key" cmdMap at: (45 + 1) put: #changeEmphasis:. "cmd-sh-minus" cmdMap at: (61 + 1) put: #changeEmphasis:. "cmd-sh-plus" cmdMap at: (127 + 1) put: #forwardDelete:. "del key" "Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $(" '9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ]. "({< and double-quote" "Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command." "NB: sw 12/9/2001 commented out the idiosyncratic line just below, which was grabbing shift-esc in the text editor and hence which argued with the wish to have shift-esc be a universal gesture for escaping the local context and calling up the desktop menu." "cmdMap at: (27 + 1) put: #shiftEnclose:." "ctrl-[" "'""''(' do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose:]." cmds _ #( $a argAdvance: $b buttonIt: $c compareToClipboard: $d duplicate: $e methodStringsContainingIt: $f displayIfFalse: $g fileItIn: $h cursorTopHome: $i exploreIt: $j doAgainMany: $k changeStyle: $l outdent: $m selectCurrentTypeIn: $n referencesToIt: $p makeProjectLink: $r indent: $s search: $t displayIfTrue: $u changeLfToCr: $v pasteInitials: $w methodNamesContainingIt: $x makeLowercase: $y makeUppercase: $z makeCapitalized: ). 1 to: cmds size by: 2 do: [ :i | cmdMap at: ((cmds at: i) asciiValue + 1) put: (cmds at: i + 1). "plain keys" cmdMap at: ((cmds at: i) asciiValue - 32 + 1) put: (cmds at: i + 1). "shifted keys" cmdMap at: ((cmds at: i) asciiValue - 96 + 1) put: (cmds at: i + 1). "ctrl keys" ]. ShiftCmdActions _ cmdMap! ! !ParagraphEditor class methodsFor: '*RVM-UI-Generic' stamp: 'ssa 2/9/2010 05:23'! initializeTextEditorMenus "Initialize the yellow button pop-up menu and corresponding messages." "ParagraphEditor initializeTextEditorMenus" TextEditorYellowButtonMenu _ SelectionMenu labels: 'find...(f) find again (g) set search string (h) do again (j) undo (z) copy (c) cut (x) paste (v) paste... do it (d) print it (p) inspect it (i) explore it (e) debug it button it (B) accept (s) cancel (l) show bytecodes more...' lines: #(3 5 9 15 17 19) selections: #(find findAgain setSearchString again undo copySelection cut paste pasteRecent doIt printIt inspectIt exploreIt debugIt buttonIt accept cancel showBytecodes shiftedTextPaneMenuRequest).! ! !ParallelRandomBug class methodsFor: 'as yet unclassified' stamp: 'dmu 9/9/2010 00:13'! test | numWorkers | numWorkers _ 2. 1 to: numWorkers do: [ :w | [ | tr | tr := Random new. 10000 timesRepeat: [ (tr next) < 0.0 ifTrue: [self error: 'neg']. ]. ] fork ]. ! ! !ParallelRandomBug class methodsFor: 'as yet unclassified' stamp: 'dmu 9/9/2010 00:28'! test2 | numWorkers randoms | numWorkers _ 2. randoms _ ( Array new: 2) collect: [:x|Random new]. 1 to: numWorkers do: [ :w | [ 10000 timesRepeat: [ ((randoms at: w) next) < 0.0 ifTrue: [self error: 'neg']. ]. ] copy fixTemps fork ]. ! ! !Parser methodsFor: '*Sly-expression types' stamp: 'dmu 9/16/2010 23:49'! ensembleExpression " %{ elements } => MessageNode(BraceNode asEnsembleOfElements)." | elements locations loc more | elements _ OrderedCollection new. locations _ OrderedCollection new. self advance. "swallow the %" self advance. more _ hereType ~~ #rightBrace. [more] whileTrue: [loc _ hereMark + requestorOffset. self expression ifTrue: [elements addLast: parseNode. locations addLast: loc] ifFalse: [^self expected: 'Variable or expression']. (self match: #period) ifTrue: [more _ hereType ~~ #rightBrace] ifFalse: [more _ false]]. parseNode _ BraceNode new elements: elements sourceLocations: locations. (self match: #rightBrace) ifFalse: [^self expected: 'Period or right brace']. parseNode _ MessageNode new receiver: parseNode selector: #asEnsembleOfElements arguments: #() precedence: 1 "unary" from: encoder sourceRange: (self startOfNextToken to: self endOfLastToken). ^true! ! !Parser methodsFor: '*Sly-expression types' stamp: 'dmu 8/30/2010 09:42'! expression "Modified for Sly ensemble literals" (hereType == #word and: [tokenType == #leftArrow]) ifTrue: [^ self assignment: self variable]. hereType == #percent ifTrue: [self ensembleExpression] ifFalse:[ hereType == #leftBrace ifTrue: [self braceExpression] ifFalse: [self primaryExpression ifFalse: [^ false]]]. (self messagePart: 3 repeat: true) ifTrue: [hereType == #semicolon ifTrue: [self cascade]]. ^ true! ! !Parser methodsFor: '*Sly-expression types' stamp: 'ads 1/30/2011 15:21'! messagePart: level repeat: repeat "Changed to support RVM multicore coordinates and Sly selectors" | start receiver selector args precedence words keywordStart | [receiver _ parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start _ self startOfNextToken. selector _ WriteStream on: (String new: 32). args _ OrderedCollection new. words _ OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart _ self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. (Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ ((RVMOperations ifNil: [false] ifNotNil: [RVMOperations isMulticoreCoordinate: selector contents]) or:[Sly3AbstractModifier isSlySelector: selector contents]) ifTrue:[selector contents asSymbol] ifFalse:[self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]]. precedence _ 3] ifFalse: [((hereType == #binary or: [hereType == #verticalBar]) and: [level >= 2]) ifTrue: [start _ self startOfNextToken. selector _ self advance asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args _ Array with: parseNode. precedence _ 2] ifFalse: [hereType == #word ifTrue: [start _ self startOfNextToken. selector _ self advance. args _ #(). words _ OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). (Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym]) ifFalse: [ selector _ ((RVMOperations isMulticoreCoordinate: selector contents) or:[Sly3AbstractModifier isSlySelector: selector contents]) ifTrue:[selector contents asSymbol] ifFalse:[self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]]. precedence _ 1] ifFalse: [^args notNil]]]. parseNode _ MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! ! !Parser methodsFor: '*Sly-expression types' stamp: 'dmu 8/30/2010 09:49'! primaryExpression "Added Sly ensembleExpression type" hereType == #word ifTrue: [parseNode _ self variable. (parseNode isUndefTemp and: [self interactive]) ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #percent ifTrue: [self ensembleExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal]]) ifTrue: [parseNode _ encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number]) ifTrue: [self advance. parseNode _ encoder encodeLiteral: self advance negated. ^true]. ^false! ! !Particle methodsFor: 'displaying'! displayOn: t1 self form displayOn: t1 at: location rule: Form paint! ! !Particle methodsFor: 'displaying' stamp: 'max 9/17/2010 11:40'! form | fill | (formChanged or: [form isNil]) ifTrue: [form := (Form dotOfSize: size) as8BitColorForm. fill := (Form dotOfSize: size - 2) as8BitColorForm mapColor: Color black to: color. fill mapColor: Color white to: Color transparent. fill displayOn: form at: (size // 2) asPoint rule: Form paint. form mapColor: Color white to: Color transparent. formChanged := false]. ^ form! ! !Particle methodsFor: 'accessing'! area ^ Rectangle center: location extent: size asPoint! ! !Particle methodsFor: 'accessing'! color ^ color! ! !Particle methodsFor: 'accessing'! location ^ location! ! !Particle methodsFor: 'accessing'! size ^ size! ! !Particle methodsFor: 'accessing'! velocity ^ velocity! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/18/2010 00:19'! bounce | bounds | bounds := homeField area. ((location x < bounds left) or: [location x >= bounds right]) ifTrue: [velocity := velocity x negated @ velocity y]. ((location y < bounds top) or: [location y >= bounds bottom]) ifTrue: [velocity := velocity x @ velocity y negated]. location := location adhereTo: bounds. ! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/17/2010 19:18'! collideWith: anotherParticle "Two axis collision sort" anotherParticle color red > color red ifTrue: [velocity := velocity x abs negated @ velocity y] ifFalse: [velocity := velocity x abs @ velocity y]. anotherParticle color blue > color blue ifTrue: [velocity := velocity x @ velocity y abs negated] ifFalse: [velocity := velocity x @ velocity y abs]! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/17/2010 11:30'! go running := true. [[running] whileTrue: [self step. Processor yield]] fork! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/29/2010 12:54'! moveTo: anotherField anotherField add: self. "old" homeField remove: self. homeField := anotherField.! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/16/2010 17:17'! particle: aParticle ofSize: itsSize movedTo: aLocation "...but if it's not touching me, don't do anything about it." ((location dist: aLocation) <= (size + itsSize // 2) and: [aParticle ~= self]) ifTrue: [self collideWith: aParticle. aParticle collideWith: self]! ! !Particle methodsFor: 'motion and interaction' stamp: 'max 9/22/2010 14:18'! step location := location + velocity. homeField particle: self ofSize: size movedTo: location! ! !Particle methodsFor: 'motion and interaction'! stop running := false! ! !Particle methodsFor: 'printing'! printOn: t1 super printOn: t1. t1 nextPut: $(. self location printOn: t1. t1 nextPut: $)! ! !Particle methodsFor: 'initialize-release' stamp: 'max 9/17/2010 11:38'! initialize running := false. formChanged := true. ! ! !Particle methodsFor: 'private'! setColor: t1 size: t2 location: t3 velocity: t4 color := t1. size := t2. location := t3. velocity := t4! ! !Particle methodsFor: 'private' stamp: 'max 9/29/2010 14:00'! setHomeField: aField (aField isNil) ifFalse: [(homeField == aField) ifFalse: [homeField := aField]]! ! !Particle class methodsFor: 'as yet unclassified' stamp: 'max 9/16/2010 17:37'! c: aColor s: aSize l: aPoint v: aPointOffset | p | p := self new. p setColor: aColor size: aSize location: aPoint velocity: aPointOffset. ^ p! ! !ParticleSim methodsFor: 'private' stamp: 'max 9/16/2010 17:03'! makeBlankForm | newForm xMax yMax pen | xMax := extent x - 1. yMax := extent y - 1. newForm := (Form extent: extent depth: 8) fillWhite. pen := (Form extent: 1@1 depth: 8) fillColor: Color veryLightGray. "Draw horizontal grid lines" 0 to: xMax by: (xMax / fields rowCount) do: [:x | newForm drawLine: pen from: x@0 to: x@yMax clippingBox: (0@0 corner: extent) rule: Form paint fillColor: newForm]. "... and vertical" 0 to: yMax by: (yMax / fields columnCount) do: [:y | newForm drawLine: pen from: 0@y to: xMax@y clippingBox: (0@0 corner: extent) rule: Form paint fillColor: newForm]. blankForm := newForm! ! !ParticleSim methodsFor: 'private' stamp: 'max 9/29/2010 12:45'! setExtent: aPointOffset fields: xAndY "This is an initialization message which must be sent to all new ParticleSim objects." | fieldExtent | running := false. extent := aPointOffset. fieldExtent := aPointOffset // xAndY. form := Form extent: aPointOffset depth: 8. fields := Matrix rows: xAndY x columns: xAndY y. fields indicesDo: [:x :y | fields at: x at: y put: (Field origin: x@y - (1@1) * fieldExtent extent: fieldExtent)]. fields indicesDo: [:x :y | (fields at: x at: y) setNeighborN: (fields at: x at: y - 1 ifInvalid: nil); setNeighborNE: (fields at: x + 1 at: y - 1 ifInvalid: nil); setNeighborNW: (fields at: x - 1 at: y - 1 ifInvalid: nil); setNeighborS: (fields at: x at: y + 1 ifInvalid: nil); setNeighborSE: (fields at: x + 1 at: y + 1 ifInvalid: nil); setNeighborSW: (fields at: x - 1 at: y + 1 ifInvalid: nil); setNeighborE: (fields at: x + 1 at: y ifInvalid: nil); setNeighborW: (fields at: x - 1 at: y ifInvalid: nil); setSimulation: self]. self makeBlankForm! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/18/2010 18:03'! add: aParticle | loc destinationField | loc := aParticle location. destinationField := fields detect: [:fld | fld area containsPoint: loc]. aParticle setHomeField: destinationField. destinationField add: aParticle ! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/18/2010 18:03'! addRandom: nParticles nParticles timesRepeat: [self add: (Particle c: Color random s: (10 to: 30) atRandom l: (0 to: extent x - 1) atRandom @ (0 to: extent y - 1) atRandom v: (1 to: 10) atRandom @ (1 to: 10) atRandom)]! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/18/2010 18:04'! clear fields do: [:fld | fld particles removeAll]! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/17/2010 12:50'! go running := true. "[[running] whileTrue: [self refresh. (Delay forMilliseconds: 50) wait]] fork." fields do: [:fld | fld go]! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/16/2010 16:49'! openMVCWindow | topView | canvas := FormView new model: form. topView := StandardSystemView new label: 'Particle Simulator'; borderWidth: 2; minimumSize: extent; maximumSize: extent; model: self; addSubView: canvas. topView controller open! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/16/2010 16:49'! refresh blankForm displayOn: form. fields do: [:fld | fld displayOn: form]. canvas displayView! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/18/2010 00:28'! step fields do: [:fld | fld step]. self refresh! ! !ParticleSim methodsFor: 'user interface' stamp: 'max 9/16/2010 16:50'! stop fields do: [:fld | fld stop]. running := false! ! !ParticleSim methodsFor: 'accessing'! blankForm ^ blankForm! ! !ParticleSim methodsFor: 'accessing'! fields ^ fields! ! !ParticleSim methodsFor: 'accessing'! form ^ form! ! !ParticleSim methodsFor: 'accessing'! running ^ running! ! !ParticleSim class methodsFor: 'instance creation'! demo | t1 | t1 := self new setExtent: 500 @ 300 fields: 5 @ 3. t1 addRandom: 10. ^ t1! ! !ParticleSim class methodsFor: 'instance creation'! extent: t1 ^ self extent: t1 fields: 2 @ 2! ! !ParticleSim class methodsFor: 'instance creation' stamp: 'max 9/16/2010 16:51'! extent: aPointOffset fields: xAndY ^ self new setExtent: aPointOffset fields: xAndY! ! !Pen methodsFor: 'accessing'! destForm: aForm "2/14/97 ssa added for compatibility." self flag:#compatibility. destForm _ aForm ! ! !Pen methodsFor: 'operations' stamp: 'ssa 11/29/2009 03:27'! turnToward: aPoint "Aim the receiver at apoint" self north; turn: (self penAngleFrom: self location to: aPoint)! ! !Pen methodsFor: 'geometric designs' stamp: 'ssa 2/16/2009 11:50'! mandala: npoints diameter: d "Display restoreAfter: [Pen new mandala: 30 diameter: 400]" "On a circle of diameter d, place npoints number of points. Draw all possible connecting lines between the circumferential points." | l points | "Display fillWhite." l _ 3.14 * d / npoints. self home; up; turn: -90; go: d // 2; turn: 90; go: 0 - l / 2; down. points _ Array new: npoints. 1 to: npoints do: [:i | points at: i put: location rounded. self go: l; turn: 360.0 / npoints]. npoints // 2 to: 1 by: -1 do: [:i | self color: i. 1 to: npoints do: [:j | self place: (points at: j). self goto: (points at: j + i - 1 \\ npoints + 1)]] ! ! !Pen methodsFor: 'private' stamp: 'ssa 2/6/2009 10:49'! direction: aFloat direction _ aFloat. ! ! !Pen methodsFor: 'functions' stamp: 'ssa 11/29/2009 03:24'! penAngleFrom:firstPoint to: lastPoint | offset x y deg | "return the angle of the vector in Pen degrees (0 = north)" offset _ lastPoint - firstPoint. x _ offset x . y _ offset y. x = 0 ifTrue:[ x _ 0.0001]. deg _ (y / x) arcTan radiansToDegrees. x positive & y positive ifTrue:[ deg _ 90 + deg]. x positive & y negative ifTrue:[ deg _ 90 + deg]. x negative & y positive ifTrue:[ deg _ 270 + deg]. x negative & y negative ifTrue:[ deg _ 270 + deg]. ^deg! ! !PluggableButtonView methodsFor: 'accessing' stamp: 'ssa 8/23/2009 13:42'! label: aStringOrDisplayObject "Label this button with the given String or DisplayObject." ((aStringOrDisplayObject isKindOf: Paragraph) or: [aStringOrDisplayObject isForm]) ifTrue: [label _ aStringOrDisplayObject] ifFalse: [label _ aStringOrDisplayObject asParagraph]. self centerLabel. ! ! !PluggableButtonView methodsFor: 'displaying' stamp: 'acg 2/23/2000 00:18'! displayView "Displays this switch and its label, if any." self clearInside. label ifNotNil: [ (label isKindOf: Paragraph) ifTrue: [ label foregroundColor: self foregroundColor backgroundColor: self backgroundColor]. label displayOn: Display at: label boundingBox topLeft clippingBox: self insetDisplayBox]. complemented _ false.! ! !PluggableButtonView methodsFor: 'other' stamp: 'ssa 8/22/2009 15:54'! performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed." (argumentsSelector isKindOf: BlockContext) ifTrue:[^argumentsSelector value]. argumentsSelector ifNil: [actionSelector ifNotNil: [model perform: actionSelector]] ifNotNil: [model perform: actionSelector withArguments: (Array with: (argumentsProvider perform: argumentsSelector))]! ! !PluggableButtonView methodsFor: 'other' stamp: 'ssa 8/23/2009 13:47'! update: aParameter aParameter == getLabelSelector ifTrue: [ getLabelSelector ifNotNil: [ self label: (model perform: getLabelSelector halt ). self displayView]]. self getModelState ifTrue: [self displayComplemented] ifFalse: [self displayNormal]. ! ! !PluggableFileList methodsFor: 'StandardFileMenu' stamp: 'ssa 4/19/2010 20:06'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: Sensor cursorPoint! ! !PluggableFileList class methodsFor: 'StandardFileMenu' stamp: 'ssa 10/18/2008 23:10'! oldFileMenu: aDirectory withPattern: aPattern "For compatibility with StandardFileMenu for now, answer a StandardFileMenuResult" ^(self getFilePathNameDialog) resultBlock: self sfmResultBlock; directory: aDirectory; pattern: aPattern; yourself! ! !PluggableListController methodsFor: 'private' stamp: 'di 5/25/1998 10:20'! changeModelSelection: anInteger "Let the view handle this." terminateDuringSelect ifTrue: [self controlTerminate]. view changeModelSelection: anInteger. terminateDuringSelect ifTrue: [self controlInitialize].! ! !PluggableListControllerOfMany methodsFor: 'control defaults' stamp: 'ssa 1/1/1970 00:05'! redButtonActivity | selection firstHit turningOn lastSelection pt scrollFlag | model okToChange ifFalse: [^ self]. "Don't change selection if model refuses to unlock" firstHit _ true. scrollFlag _ false. lastSelection _ 0. [sensor redButtonPressed] whileTrue: [ selection _ view findSelection: (pt _ sensor cursorPoint). selection == nil ifTrue: "Maybe out of box - check for auto-scroll" [pt y < view insetDisplayBox top ifTrue: [self scrollView: view list lineGrid. scrollFlag _ true. selection _ view firstShown]. pt y > view insetDisplayBox bottom ifTrue: [self scrollView: view list lineGrid negated. scrollFlag _ true. selection _ view lastShown]]. (selection == nil or: [selection = lastSelection]) ifFalse: [firstHit ifTrue: [firstHit _ false. turningOn _ (view listSelectionAt: selection) not]. view selection: selection. (view listSelectionAt: selection) == turningOn ifFalse: [view displaySelectionBox. view listSelectionAt: selection put: turningOn]. lastSelection _ selection]]. selection notNil ifTrue: ["Normal protocol delivers change, so unchange first (ugh)" "view listSelectionAt: selection put: (view listSelectionAt: selection) not". self changeModelSelection: selection]. scrollFlag ifTrue: [self moveMarker]! ! !PluggableListView methodsFor: 'model access' stamp: 'ssa 9/2/2009 20:11'! getList "Answer the list to be displayed." | lst | getListSelector == nil ifTrue: [^ #()]. lst _ model perform: getListSelector. lst == nil ifTrue: [^ #()]. ^ lst ! ! !PluggableListView methodsFor: 'updating' stamp: 'ssa 11/25/2009 14:42'! update: aSymbol "Refer to the comment in View|update:." "Hacked to support Windoze - ssa" aSymbol == getListSelector ifTrue: [self list: self getList. self displayView. self displaySelectionBox]. aSymbol == getSelectionSelector ifTrue: [self moveSelectionBox: self getCurrentSelectionIndex]. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:45'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: nil keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:45'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." ^ self on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: #arrowKey:from: "default" ! ! !PluggableListView class methodsFor: 'instance creation' stamp: 'ssa 9/4/1998 16:00'! on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel "Create a 'pluggable' list view on the given model parameterized by the given message selectors. See aboutPluggability comment." "Added Windoze wrapper - ssa" ^ MSWScrollBarView on: (self new on: anObject list: getListSel selected: getSelectionSel changeSelected: setSelectionSel menu: getMenuSel keystroke: keyActionSel) ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 11/25/2009 12:50'! changeModelSelection: anInteger "Change the model's selected item to be the one at the given index." | item | setSelectionSelector ifNotNil: [ item _ (anInteger = 0 ifTrue: [nil] ifFalse: [self objects at: anInteger]). model perform: setSelectionSelector with: item]. ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:40'! getCurrentSelectionIndex "Answer the index of the current selection." | item | getSelectionSelector == nil ifTrue: [^ 0]. item _ model perform: getSelectionSelector. ^ self objects indexOf: item ifAbsent:[0] ! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/29/2010 13:47'! labelForItem: anItem "Subclasses may want to override" ^anItem isString ifTrue:[anItem]ifFalse:[anItem printString]! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 6/17/2010 16:40'! list: arrayOfObjects "Set the receivers items to be the given list of objects printStrings." "Note: the instance variable 'objects' holds the original list. The instance variable 'list' is a paragraph constructed from this list." | oldOffset | self scrollCache: (list isNil ifFalse:[list scrollDelta]ifTrue:[0]). self objects: arrayOfObjects. isEmpty _ arrayOfObjects isEmpty. oldOffset _ list isNil ifTrue:[0@0]ifFalse:[list offset]. "add top and bottom delimiters" list _ ListParagraph withArray: (Array streamContents: [:s | s nextPut: topDelimiter. self objects do: [:item | item == nil ifFalse: [s nextPut: (self labelForItem: item)]]. s nextPut: bottomDelimiter]) style: self assuredTextStyle. list offset: oldOffset. selection _ self getCurrentSelectionIndex. self positionList.! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:31'! objects "Answer the value of objects" objects isNil ifTrue:[self objects: OrderedCollection new]. ^ objects! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:29'! objects: anObject "Set the value of objects" objects _ anObject! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/22/2010 14:02'! scrollCache "Answer the value of scrollCache" scrollCache isNil ifTrue:[self scrollCache: 0]. ^ scrollCache! ! !PluggableListViewByObject methodsFor: 'accessing' stamp: 'ssa 1/22/2010 14:02'! scrollCache: anObject "Set the value of scrollCache" scrollCache _ anObject! ! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:46'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel ^ self on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: #arrowKey:from: "default"! ! !PluggableListViewOfMany class methodsFor: 'instance creation' stamp: 'ssa 8/21/2009 15:22'! on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel ^MSWScrollBarView on: ( self new on: anObject list: listSel primarySelection: getSelectionSel changePrimarySelection: setSelectionSel listSelection: getListSel changeListSelection: setListSel menu: getMenuSel keystroke: keyActionSel)! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:42'! inspectSelection self selection inspect! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:47'! menu: aMenu aMenu add: 'inspect' action: #inspectSelection. aMenu add: 'outline' action: #outlineSelection. ^ aMenu! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:43'! outlineSelection self selection outline! ! !PluggableOutline methodsFor: 'menu support' stamp: 'ssa 9/10/2009 14:55'! perform: selector orSendTo: otherTarget ^self perform: selector! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:29'! childrenOf: anObject ^anObject subobjects! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:02'! initializeList self list do:[:each| self levels at: each put:0]! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levelOf: anItem ^self levels at: anItem ifAbsent:[0]! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:01'! levels "Answer the value of levels" levels isNil ifTrue:[self levels: Dictionary new]. ^ levels! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 12:00'! levels: anObject "Set the value of levels" levels _ anObject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:39'! list "Answer the value of list" list isNil ifTrue:[self list: (OrderedCollection with:self subject )]. ^ list! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 13:36'! list: anObject "Set the value of list" list _ anObject asOrderedCollection! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems "Answer the value of openItems" openItems isNil ifTrue:[self openItems: Set new]. ^ openItems! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:42'! openItems: anObject "Set the value of openItems" openItems _ anObject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 13:28'! progenyOf: anObject | all | all _ (self childrenOf: anObject)copy. all isEmpty ifTrue:[^all]. all copy do:[:each| all addAll: (self progenyOf: each)]. ^all ! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 11:18'! selection "Answer the value of selection" selection isNil ifTrue:[self selection: nil]. ^ selection! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/9/2009 17:15'! selection: anObject "Set the value of selection" selection _ anObject . ! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 7/7/2010 12:40'! subject "Answer the value of subject" subject isNil ifTrue:[self subject: nil]. ^ subject! ! !PluggableOutline methodsFor: 'accessing' stamp: 'ssa 9/10/2009 08:25'! subject: anObject "Set the value of subject" subject _ anObject! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 13:02'! hasChildren: anObject ^(self childrenOf: anObject) notEmpty ! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 14:07'! hideChildrenOfSelection | kids | self openItems remove: self selection. kids _ self progenyOf: self selection. kids do:[:each| self levels removeKey: each ifAbsent:[]. self openItems remove: each ifAbsent:[]]. self list removeAll: kids ifAbsent:[] ! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 11:42'! isOpen: anItem ^self openItems includes: anItem! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/9/2009 12:10'! showChildrenOfSelection | kids nextLevel | self openItems add: self selection. nextLevel _ (self levelOf: self selection) + 1. kids _ self childrenOf: self selection. kids isEmpty ifTrue:[^self error:'should never try to show children of an childless object']. kids do:[:each| self levels at: each put: nextLevel]. self list addAll: kids after: self selection! ! !PluggableOutline methodsFor: 'opening/closing' stamp: 'ssa 9/10/2009 07:30'! toggleSelection self selection isNil ifTrue:[^self]. (self isOpen: self selection) ifTrue:[self hideChildrenOfSelection] ifFalse:[self showChildrenOfSelection]. self changed:#list! ! !PluggableOutline methodsFor: 'arrow keys' stamp: 'ssa 9/9/2009 14:47'! arrowKey: aChar from: view "Process the up and down arrows in a list pane. Note that the listView tells us what index variable, how to get the list, and how to move the index. Derived from a Martin Pammer submission, 02/98" | keyEvent oldSelection nextSelection max min howMany | (#(1 4 11 12 30 31) includes: (keyEvent _ aChar asciiValue)) ifFalse: [ ^ self]. oldSelection := view getCurrentSelectionIndex. nextSelection := oldSelection. max := view maximumSelection. min := view minimumSelection. howMany := view numSelectionsInView. "get this exactly??" keyEvent == 31 ifTrue: ["down-arrow; move down one, wrapping to top if needed" nextSelection := oldSelection + 1. nextSelection > max ifTrue: [nextSelection _ 1]]. keyEvent == 30 ifTrue: ["up arrow; move up one, wrapping to bottom if needed" nextSelection := oldSelection - 1. nextSelection < 1 ifTrue: [nextSelection _ max]]. keyEvent == 1 ifTrue: [nextSelection := 1]. "home" keyEvent == 4 ifTrue: [nextSelection := max]. "end" keyEvent == 11 ifTrue: [nextSelection := min max: (oldSelection - howMany)]. "page up" keyEvent == 12 ifTrue: [nextSelection := (oldSelection + howMany) min: max]. "page down" nextSelection = oldSelection ifFalse: [self okToChange ifTrue: [view changeModelSelection: nextSelection. "view controller moveMarker"]] ! ! !PluggableTextController methodsFor: 'accessing-selection' stamp: 'th 9/19/2002 18:35'! selectFrom: start to: stop scroll: scrollCommand "Deselect, then select the specified characters inclusive. Be sure the selection is in view." (start = self startIndex and: [stop + 1 = self stopIndex]) ifFalse: [view superView ifNotNil: [self deselect]. self selectInvisiblyFrom: start to: stop]. view superView ifNotNil: [self perform: scrollCommand]! ! !PluggableTextView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 14:35'! on: anObject text: getTextSel accept: setTextSel ^ self on: anObject text: getTextSel accept: setTextSel readSelection: nil menu: nil ! ! !PluggableTextView class methodsFor: 'instance creation' stamp: 'ssa 9/4/1998 16:04'! on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel "Added Windoze wrapper - ssa" ^ MSWScrollBarView on: (self new on: anObject text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel) ! ! !Point methodsFor: 'accessing' stamp: 'ssa 11/16/2008 13:12'! x: aNumber x _ aNumber! ! !Point methodsFor: 'accessing' stamp: 'ssa 11/16/2008 13:12'! y: aNumber y _ aNumber! ! !Point methodsFor: 'arithmetic' stamp: 'ssa 11/27/2009 16:15'! inverted ^1 asPoint / self! ! !Point methodsFor: 'comparing' stamp: 'ssa 9/3/2009 07:11'! maxed ^(x max: y) asPoint! ! !Point methodsFor: 'comparing' stamp: 'ssa 9/3/2009 07:11'! mined ^(x min: y) asPoint! ! !Point methodsFor: 'interpolating' stamp: 'ssa 9/7/2009 21:42'! zeno "(10@10) zeno #(10@10 5.0@5.0 2.5@2.5 1.25@1.25)" "(10@4) zeno #(10@4 5.0@2.0)" "(-10@4) zeno " | steps zx zy minSize | steps _ OrderedCollection new. zx _ x zeno. zy _ y zeno. minSize _ zx size min: zy size. 1 to: minSize do:[:index| steps add:(zx at: index)@(zy at: index)]. ^steps asArray! ! !Point methodsFor: 'point functions' stamp: 'ssa 11/16/2008 02:35'! atRandom ^x atRandom @ y atRandom! ! !Point methodsFor: 'point functions' stamp: 'ssa 1/30/2009 10:04'! mandist: aPoint "Answer the Manhattan distance between aPoint and the receiver." ^(x-aPoint x) abs + (y - aPoint y) abs! ! !Point methodsFor: 'point functions' stamp: 'dmu 4/1/2009 20:49'! manhattanDist: aPoint "Answer the distance between aPoint and the receiver." | p | p _ aPoint - self. ^ p x abs + p y abs! ! !Point methodsFor: 'polar coordinates'! complexProduct: aPoint ^((x * aPoint x) - (y * aPoint y)) @ ((x * aPoint y) + (y * aPoint x))! ! !Point methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:26'! moveBy: aPoint "Alter the receiver by moving it by a Point." x _ x + aPoint x. y _ y + aPoint y.! ! !Point methodsFor: 'transforming' stamp: 'ssa 2/8/2009 20:57'! wrapAround: aRectangle "If the receiver lies outside aRectangle, return the nearest point on the other side of the rectangle, otherwise return self." | newX newY | newX _ x. newY _ y. (aRectangle containsPoint: self) ifTrue: [^ self]. x >= aRectangle right ifTrue:[newX _ aRectangle left]. x <= aRectangle left ifTrue:[newX _ aRectangle right]. y >= aRectangle bottom ifTrue:[newY _ aRectangle top]. y <= aRectangle top ifTrue:[newY _ aRectangle bottom]. ^newX@newY! ! !Point methodsFor: 'truncation and round off' stamp: 'ssa 8/25/2009 14:08'! ceiling "Answer a new Point that is the receiver's x and y ceiling." ^x ceiling @ y ceiling! ! !Point methodsFor: 'truncation and round off' stamp: 'ssa 8/25/2009 14:07'! floor "Answer a new Point that is the receiver's x and y floor." ^x floor @ y floor! ! !Point methodsFor: '*Ly' stamp: 'dmu 1/25/2010 14:02'! minus: arg "Answer a Point that is the difference of the receiver and arg." arg isPoint ifTrue: [^ (x - arg x) @ (y - arg y)]. ^ arg adaptToPoint: self andSend: #-! ! !Point methodsFor: '*Ly' stamp: 'dmu 3/16/2010 23:16'! perturb: n | r | r _ Random new. ^ self + ( r next @r next * n - (n / 2.0) )! ! !PointerExplorer methodsFor: 'accessing' stamp: 'ab 8/22/2003 18:51'! getList ^Array with: (PointerExplorerWrapper with: rootObject name: rootObject identityHash asString model: self) ! ! !PointerExplorer commentStamp: 'avi 8/21/2004 20:01' prior: 0! A variant on the ObjectExlorer that works "backwards": like the ObjectExplorer, it shows a tree of objects, but expanding a node won't show the objects which that node references, but rather the objects that reference that node. Its main use is to track down memory leaks: if you want to know why a particular object is still alive, open a PointerExplorer on it and drill down until you find the root object that's referencing it. For example, find all the references to the symbol #zot with: PointerExplorer new openExplorerFor: #zot For the "name" of the object, the PointerExplorer shows each object's identityHash, to allow the user to identify when two similar objects are identical and notice cycles.! !PointerExplorerWrapper methodsFor: 'accessing' stamp: 'ssa 9/11/2009 16:23'! contents | objects | objects := Utilities pointersTo: item except: (Array with: self with: model). ^(objects reject: [:ea | ea class = self class]) collect: [:ea| self class with: ea name: ea identityHash asString model: item parent: self]! ! !PointerExplorerWrapper methodsFor: 'testing' stamp: 'ab 8/22/2003 18:39'! hasContents ^true! ! !PointerExplorerWrapper commentStamp: 'avi 8/21/2004 19:58' prior: 0! A subclass of ObjectExplorerWrapper for use with PointerExplorer. #contents is overridden to work backwards: it returns wrappers for the objects pointing to item rather than for the objects that item points to.! !PointerFinder methodsFor: 'morphic ui' stamp: 'ssa 3/9/2010 16:29'! menu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane" ^SelectionMenu labels: 'inpsect search again' lines: #() selections: #(inspectObject searchAgain).! ! !PointerFinder methodsFor: 'morphic ui' stamp: 'ssa 3/9/2010 16:37'! open | topView listView | topView := StandardSystemView new label: 'Pointer FInder'; model: self; yourself. topView addSubView:(listView := PluggableListView on: self list: #pointerList selected: #pointerListIndex changeSelected: #pointerListIndex: menu: #menu:shifted: keystroke: #arrowKey:from:) in:(0@0 extent: 1@1) borderWidth:1. listView backgroundColor: Color lightMagenta. topView controller open! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 9/24/2004 20:49'! pointersTo: anObject "Find all occurrences in the system of pointers to the argument anObject." "(PointerFinder pointersTo: Browser) inspect." ^ self pointersTo: anObject except: #() ! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 11/20/2005 21:28'! pointersTo: anObject except: objectsToExclude "Find all occurrences in the system of pointers to the argument anObject. Remove objects in the exclusion list from the results." | results anObj | Smalltalk garbageCollect. "big collection shouldn't grow, so it's contents array is always the same" results := OrderedCollection new: 1000. "allObjectsDo: is expanded inline to keep spurious method and block contexts out of the results" anObj := self someObject. [0 == anObj] whileFalse: [ anObj isInMemory ifTrue: [ (anObj pointsTo: anObject) ifTrue: [ "exclude the results collector and contexts in call chain" ((anObj ~~ results collector) and: [(anObj ~~ objectsToExclude) and: [(anObj ~~ thisContext) and: [(anObj ~~ thisContext sender) and: [anObj ~~ thisContext sender sender]]]]) ifTrue: [ results add: anObj ]. ]]. anObj := anObj nextObject. ]. objectsToExclude do: [ :obj | results removeAllSuchThat: [ :el | el == obj]]. ^ results asArray ! ! !PointerFinder class methodsFor: 'utilities' stamp: 'sd 9/24/2004 20:48'! pointersToItem: index of: anArray "Find all occurrences in the system of pointers to the given element of the given array. This is useful for tracing up a pointer chain from an inspector on the results of a previous call of pointersTo:. To find out who points to the second element of the results, one would evaluate: PointerFinder pointersToItem: 2 of: self in the inspector." ^ self pointersTo: (anArray at: index) except: (Array with: anArray)! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ssa 4/19/2010 20:04'! startUpWithCaption: captionOrNil "Display the menu, slightly offset from the cursor, so that a slight tweak is required to confirm any action." ^ self startUpWithCaption: captionOrNil at: Sensor cursorPoint! ! !PopUpMenu methodsFor: 'basic control sequence' stamp: 'ssa 4/19/2010 20:12'! startUpWithCaption: captionOrNil at: location allowKeyboard: aBoolean "Display the menu, with caption if supplied. Wait for the mouse button to go down, then track the selection as long as the button is pressed. When the button is released, Answer the index of the current selection, or zero if the mouse is not released over any menu item. Location specifies the desired topLeft of the menu body rectangle. The final argument indicates whether the menu should seize the keyboard focus in order to allow the user to navigate it via the keyboard." | maxHeight | "self terminateRedundantUIProcessIfAny." maxHeight _ Display height*3//4. self frameHeight > maxHeight ifTrue: [^ self startUpSegmented: maxHeight withCaption: captionOrNil at: location allowKeyboard: aBoolean]. frame ifNil: [self computeForm]. Cursor normal showWhile: [self displayAt: location withCaption: captionOrNil during: [self controlActivity]]. ^ selection! ! !PopUpMenu methodsFor: '*RVM' stamp: 'ssa 3/1/2010 13:43'! lastStartupTime ^ LastStartupTime ifNil: [LastStartupTime _ 0] ifNotNil: [LastStartupTime] ! ! !PopUpMenu methodsFor: '*RVM' stamp: 'ssa 3/1/2010 13:43'! lastStartupTime: t LastStartupTime _ t ! ! !PopUpMenu methodsFor: '*RVM' stamp: 'ads 1/30/2011 15:20'! terminateRedundantUIProcessIfAny "kill a redundant UI process if there is one; judge by pop-up time" "[self halt] fork" |now delta | now _ Time millisecondClockValue. delta _ now - self lastStartupTime. (delta <= (RVMOperations isRVM ifTrue:[100]ifFalse:[^10]) and: [delta > 0]) ifTrue: [" self lastStartupProcess" Transcript resetSemaphore show: 'terminateRedundantUIProcessIfAny zap!!'; cr. Processor thisProcess terminate ]. self lastStartupTime: now! ! !PositionableStream methodsFor: 'fileIn/Out' stamp: 'StefanMarr 7/14/2011 17:11'! copyPreamble: preamble from: aStream "Look for a changeStamp for this method by peeking backward. Write a method preamble, with that stamp if found." | terminator methodPos p last75 stamp i | terminator _ $!!. "Look back to find stamp in old preamble, such as... Polygon methodsFor: 'private' stamp: 'di 6/25/97 21:42' prior: 34957598!! " methodPos _ aStream position. aStream position: (p _ 0 max: methodPos-75). last75 _ aStream next: methodPos - p. stamp _ String new. (i _ last75 findString: 'stamp:' startingAt: 1) > 0 ifTrue: [stamp _ (last75 copyFrom: i+8 to: last75 size) copyUpTo: $']. "Write the new preamble, with old stamp if any." self cr; nextPut: terminator. self nextChunkPut: (String streamContents: [:strm | strm nextPutAll: preamble. stamp size > 0 ifTrue: [strm nextPutAll: ' stamp: '; print: stamp]]). self cr! ! !PositionableStream methodsFor: 'printing' stamp: 'ssa 8/19/2009 20:08'! printOn: aStream aStream nextPutAll:'@',self position printString,' in '. ^super printOn: aStream! ! !PositionableStream methodsFor: '*packageinfo-base' stamp: 'nk 6/17/2003 07:45'! untilEnd: aBlock displayingProgress: aString aString displayProgressAt: Sensor cursorPoint from: 0 to: self size during: [:bar | [self atEnd] whileFalse: [bar value: self position. aBlock value]].! ! !Preferences class methodsFor: 'get/set' stamp: 'ssa 3/24/2010 15:18'! enable: aSymbol "Shorthand access to enabling a preference of the given name. If there is none in the image, conjure one up" | aPreference | aPreference _ self preferenceAt: aSymbol ifAbsent: [self addPreference: aSymbol category: 'unclassified' default: false balloonHelp: 'this preference was added idiosyncratically and has no help message.'. self preferenceAt: aSymbol]. aPreference preferenceValue: true! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! errorHandler "Answer the value of errorHandler" errorHandler isNil ifTrue:[self errorHandler: nil]. ^ errorHandler! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! errorHandler: anObject "Set the value of errorHandler" errorHandler _ anObject! ! !Process methodsFor: 'accessing' stamp: 'ssa 2/17/2009 22:34'! isActiveProcess ^ suspendedContext isNil and:[myList notNil]! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList "Answer the value of myList" myList isNil ifTrue:[self myList: nil]. ^ myList! ! !Process methodsFor: 'accessing' stamp: 'dmu 3/8/2010 20:26'! myList: anObject "Set the value of myList" myList _ anObject! ! !Process methodsFor: 'changing process state' stamp: 'ads 2/2/2011 14:51'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). ASSUMES self is the active process. Essential. See Object documentation whatIsAPrimitive." "Debugging code below causes terminated running processes to seem not terminated. -- dmu 3/2/10" "(myList isNil and: [RVMOperations isRVM]) ifTrue:[self halt]." <primitive: 88> self primitiveFailed! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:44'! resume "Allow the process that the receiver represents to continue. Put the receiver in line to become the activeProcess. Check for a nil suspendedContext, which indicates a previously terminated Process that would cause a vm crash if the resume attempt were permitted" self children do: [:c| c resume]. suspendedContext ifNil: [^ self primitiveFailed]. ^ self primitiveResume! ! !Process methodsFor: 'changing process state' stamp: 'dmu 1/29/2011 21:18'! suspend "Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes." | aCopyOfMyListWhichIsSafeFromRaces | self children do: [:c| c suspend]. self isActiveProcess ifTrue: [ self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ aCopyOfMyListWhichIsSafeFromRaces _ myList. aCopyOfMyListWhichIsSafeFromRaces ifNotNil: [ aCopyOfMyListWhichIsSafeFromRaces remove: self ifAbsent: []. myList _ nil]. ] ! ! !Process methodsFor: 'changing process state' stamp: 'dmu 3/24/2010 15:45'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock | self children do: [:c| c terminate]. self == Processor thisProcess ifTrue: [ ctxt _ thisContext. [ ctxt _ ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ unwindBlock _ ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self nilMyListUnlessRVM. self primitiveSuspend. ] ifFalse: [ self suspend. myList ifNotNil: [ myList remove: self ifAbsent: []. myList _ nil]. suspendedContext ifNotNil: [ ctxt _ self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! activateReturn: aContext value: value "Activate 'aContext return: value', so execution will return to aContext's sender" self suspend. ^ suspendedContext _ suspendedContext activateReturn: aContext value: value! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:01'! complete: aContext "Run self until aContext is popped or an unhandled error is raised. Return self's new top context, unless an unhandled error was raised then return the signaler context (rather than open a debugger)." | ctxt pair error | self suspend. ctxt _ suspendedContext. suspendedContext _ nil. "disable this process while running its stack in active process below" pair _ ctxt runUntilErrorOrReturnFrom: aContext. suspendedContext _ pair first. error _ pair second. error ifNotNil: [^ error signalerContext]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 11/25/2008 00:21'! popTo: aContext "Pop self down to aContext by remote returning from aContext's callee. Unwind blocks will be executed on the way. This is done by pushing a new context on top which executes 'aContext callee return' then resuming self until aContext is reached. This way any errors raised in an unwind block will get handled by senders in self and not by senders in the activeProcess. If an unwind block raises an error that is not handled then the popping stops at the error and the signalling context is returned, othewise aContext is returned." | callee | (Processor isActive: self) ifTrue: [^ self error: 'The active process cannot pop contexts']. callee _ (self calleeOf: aContext) ifNil: [^ aContext]. "aContext is on top" ^ self return: callee value: callee receiver! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! return: aContext value: value "Pop thread down to aContext's sender. Execute any unwind blocks on the way. See #popTo: comment and #runUntilErrorOrReturnFrom: for more details." self suspend. suspendedContext == aContext ifTrue: [ ^ suspendedContext _ aContext return: value from: aContext]. self activateReturn: aContext value: value. ^ self complete: aContext. ! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:03'! step self suspend. ^ suspendedContext _ suspendedContext step! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:04'! stepToCallee "Step until top context changes" | ctxt | self suspend. ctxt _ suspendedContext. [ctxt == suspendedContext] whileTrue: [ suspendedContext _ suspendedContext step]. ^ suspendedContext! ! !Process methodsFor: 'changing suspended state' stamp: 'dmu 12/2/2008 14:05'! stepToSendOrReturn self suspend. ^ suspendedContext _ suspendedContext stepToSendOrReturn! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debug: context title: title full: bool "Open debugger on self with context shown on top" | topCtxt | topCtxt _ self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. (topCtxt hasContext: context) ifFalse: [^ self error: 'context not in process']. Transcript cr; show: 'Suspending siblings & progeny'. self class semaForSupensions critical:[ self siblings size print. self siblingsAndTheirDescendantsDo: [:proc| proc == Processor thisProcess ifFalse: [Transcript cr;show:'suspending proc ',proc identityHash printString. proc suspend]]. ]. Transcript cr; show: 'launching debugger'. Debugger openOn: self context: context label: title contents: nil fullView: bool. ! ! !Process methodsFor: 'debugging' stamp: 'dmu 9/17/2010 12:03'! debugWithTitle: title "Open debugger on self" | context | context _ self == Processor thisProcess ifTrue: [thisContext] ifFalse: [ self suspend. self suspendedContextWaitingIfNecessary]. self debug: context title: title full: true. ! ! !Process methodsFor: 'printing' stamp: 'ads 1/24/2011 13:03'! longPrintOn: stream | ctxt | stream nextPutAll: (RVMPrimitivesNeededForBootstrapping printPrefixFor: self). super printOn: stream. stream cr. ctxt _ self suspendedContext. [ctxt == nil] whileFalse: [ stream space. ctxt printOn: stream. stream cr. ctxt _ ctxt sender. ]. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:31'! pvtSignal: anException list: aList "Private. This method is used to signal an exception from another process...the receiver must be the active process. If the receiver was previously waiting on a Semaphore, then return the process to the waiting state after signaling the exception and if the Semaphore has not been signaled in the interim" "Since this method is not called in a normal way, we need to take care that it doesn't directly return to the caller (because I believe that could have the potential to push an unwanted object on the caller's stack)." | blocker | self == Processor thisProcess ifFalse: [^self]. self suspend. anException signal. blocker := Semaphore new. [self suspend. suspendedContext := suspendedContext swapSender: nil. aList class == Semaphore ifTrue: [aList isSignaled ifTrue: [aList wait. "Consume the signal that would have restarted the receiver" self resume] ifFalse: ["Add us back to the Semaphore's list (and remain blocked)" myList := aList. aList add: self]] ifFalse: [self resume]] fork. blocker wait. ! ! !Process methodsFor: 'signaling' stamp: 'ssa 2/17/2009 22:30'! signal: anException "Signal an exception in the receiver process...if the receiver is currently suspended, the exception will get signaled when the receiver is resumed. If the receiver is blocked on a Semaphore, it will be immediately re-awakened and the exception will be signaled; if the exception is resumed, then the receiver will return to a blocked state unless the blocking Semaphore has excess signals" "If we are the active process, go ahead and signal the exception" self == Processor thisProcess ifTrue: [^anException signal]. self suspend. "Add a new method context to the stack that will signal the exception" suspendedContext := MethodContext sender: suspendedContext receiver: self method: (self class methodDict at: #pvtSignal:list:) arguments: (Array with: anException with: myList). "If we are on a list to run, then suspend and restart the receiver (this lets the receiver run if it is currently blocked on a semaphore). If we are not on a list to be run (i.e. this process is suspended), then when the process is resumed, it will signal the exception" myList ifNotNil: [self suspend; resume].! ! !Process methodsFor: '*RVMBootstrap' stamp: 'dmu 5/9/2009 23:08'! isRunning Processor thisProcess == self ifTrue: [^ true]. self isActiveProcess ifTrue: [^ true]. myList ifNil: [^ false]. ^ myList class ~~ Semaphore! ! !Process methodsFor: '*RVMBootstrap' stamp: 'ssa 3/2/2010 18:23'! nilMyListUnlessRVM Processor areRunningProcessesInSchedulerLists ifFalse: [ "primitiveSuspend will use myList to remove from list and will nil it out" myList _ nil. ]! ! !Process methodsFor: '*RVMBootstrap' stamp: 'dmu 9/17/2010 11:59'! suspendedContextWaitingIfNecessary "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." [self suspendedContext isNil] whileTrue. ^ self suspendedContext! ! !Process methodsFor: '*Ly' stamp: 'dmu 9/3/2010 16:30'! lyDebuggingBlock "Answer the value of lyDebuggingBlock" lyDebuggingBlock isNil ifTrue:[self lyDebuggingBlock: nil]. ^ lyDebuggingBlock! ! !Process methodsFor: '*Ly' stamp: 'dmu 9/3/2010 16:30'! lyDebuggingBlock: anObject "Set the value of lyDebuggingBlock" lyDebuggingBlock _ anObject! ! !Process methodsFor: '*Ly' stamp: 'dmu 3/9/2010 14:59'! stopIfDebugging: whatIAmAboutToDo | | self lyDebuggingBlock ifNil: [^ self]. self lyDebuggingBlock value: whatIAmAboutToDo! ! !Process methodsFor: '*RVM' stamp: 'ssa 2/26/2009 02:57'! avoidCore: anIndex "Force this process to avoid this core (0-55)" self coreMask: (self coreMask bitClear: (1 bitShift: anIndex))! ! !Process methodsFor: '*RVM' stamp: 'ssa 2/26/2009 03:49'! avoidCores: aCollectionOfIndicies "Force this process to avoid these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitClear:mask)! ! !Process methodsFor: '*RVM' stamp: 'dmu 2/12/2009 23:15'! coreMask ^ coreMask! ! !Process methodsFor: '*RVM' stamp: 'dmu 2/12/2009 23:15'! coreMask: m coreMask _ m! ! !Process methodsFor: '*RVM' stamp: 'dmu 2/12/2009 23:14'! hostCore ^ hostCore! ! !Process methodsFor: '*RVM' stamp: 'dmu 3/8/2010 20:26'! hostCore: anObject "Set the value of hostCore" hostCore _ anObject! ! !Process methodsFor: '*RVM' stamp: 'dmu 4/7/2009 02:41'! resumeOn: aCore self useOnlyCore: aCore. self resume! ! !Process methodsFor: '*RVM' stamp: 'ssa 2/26/2009 02:59'! useAdditionalCore: anIndex "Force this process to only urn on this core (0-55)" self coreMask: (self coreMask bitOr:(1 bitShift: anIndex))! ! !Process methodsFor: '*RVM' stamp: 'ssa 2/26/2009 03:50'! useAdditionalCores: aCollectionOfIndicies "Allow this process to run on these additional cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: (self coreMask bitOr:mask)! ! !Process methodsFor: '*RVM' stamp: 'dmu 5/5/2009 01:32'! useOnlyCore: anIndex "Force this process to only run on this core (0-55)" self coreMask: (1 bitShift: anIndex)! ! !Process methodsFor: '*RVM' stamp: 'ssa 2/26/2009 03:02'! useOnlyCores: aCollectionOfIndicies "Force this process to only run on these cores (0-55)" | mask | mask _ 0. aCollectionOfIndicies do:[:index| mask _ mask bitOr: (1 bitShift: index)]. self coreMask: mask! ! !Process methodsFor: '*RVM' stamp: 'ads 1/30/2011 15:21'! useOnlyMainCore RVMOperations isRVM ifTrue: [self useOnlyCore: (RVMMonitor getSample; mainRank)]! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/24/2010 14:44'! addChild: aProcess self children add: aProcess. aProcess parent: self.! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 9/17/2010 11:12'! beSlyMemberProcess self priority: Processor userBackgroundPriority. Processor thisProcess addChild: self. ^ self! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/24/2010 14:42'! children "Answer the value of children" children isNil ifTrue:[self children: WeakSet new]. ^ children! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/24/2010 14:38'! children: anObject "Set the value of children" children _ anObject! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 23:56'! creatorEnsemble "Answer the value of creatorEnsemble" creatorEnsemble isNil ifTrue:[self creatorEnsemble: nil]. ^ creatorEnsemble! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 23:56'! creatorEnsemble: anObject "Set the value of creatorEnsemble" creatorEnsemble _ anObject! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 10:30'! descendantsDo: blk self children do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/26/2010 12:26'! myGeneration ^ self parent ifNil: [{self}] ifNotNil: [self parent children]! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 10:34'! myGenerationAndTheirDescendantsDo: blk self myGeneration do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/24/2010 14:38'! parent "Answer the value of parent" parent isNil ifTrue:[self parent: nil]. ^ parent! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/24/2010 14:38'! parent: anObject "Set the value of parent" parent _ anObject! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 10:34'! siblings ^ self myGeneration copyWithout: self! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 3/25/2010 10:32'! siblingsAndTheirDescendantsDo: blk self siblings do: [:p | blk value: p. p descendantsDo: blk]! ! !Process methodsFor: '*SlyBootstrap' stamp: 'dmu 9/17/2010 11:57'! synchronousSuspend "In RVM, can suspend some other running process, and so after sending suspend, suspendedContext may still be nil." "Send suspend and don't return till the process is really suspended" self suspend. [self suspendedContext isNil] whileTrue.! ! !Process class methodsFor: 'instance creation' stamp: 'dmu 3/24/2010 15:46'! forContext: aContext priority: anInteger "Answer an instance of me that has suspended aContext at priority anInteger." | newProcess | newProcess _ self new. newProcess suspendedContext: aContext. newProcess priority: anInteger. [newProcess coreMask:(1 bitShift: 27)]. ^newProcess! ! !Process class methodsFor: '*RVM' stamp: 'ssa 2/26/2009 02:45'! forContext: aContext priority: anInteger coreMask: anIntegerMask "Answer an instance of me that has suspended aContext at priority anInteger using this coreMask." | newProcess | newProcess _ self forContext: aContext priority: anInteger. newProcess coreMask:anIntegerMask. ^newProcess! ! !Process class methodsFor: '*RVMBootstrap' stamp: 'ssa 3/25/2010 15:11'! semaForSupensions SemaForSupensions isNil ifTrue:[SemaForSupensions _ Semaphore forMutualExclusion]. ^SemaForSupensions! ! !Process class methodsFor: 'testing-workaround-warning' stamp: 'sm 4/21/2011 23:43'! shouldNotBeRedefined ^ false! ! !ProcessBrowser methodsFor: 'stack list' stamp: 'dmu 11/25/2008 00:22'! updateStackList: depth | suspendedContext oldHighlight | selectedProcess ifNil: [^ self changeStackListTo: nil]. (stackList notNil and: [ stackListIndex > 0 ]) ifTrue: [oldHighlight _ stackList at: stackListIndex]. (Processor isActive: selectedProcess) ifTrue: [self changeStackListTo: (thisContext stackOfSize: depth)] ifFalse: [suspendedContext _ selectedProcess suspendedContext. suspendedContext ifNil: [self changeStackListTo: nil] ifNotNil: [self changeStackListTo: (suspendedContext stackOfSize: depth)]]. self stackListIndex: (stackList ifNil: [0] ifNotNil: [stackList indexOf: oldHighlight])! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'ssa 9/3/2008 11:08'! isUIProcess: aProcess ^aProcess == ScheduledControllers activeControllerProcess ! ! !ProcessBrowser class methodsFor: 'process control' stamp: 'ssa 6/11/2010 14:35'! nameAndRulesFor: aProcess "Answer a nickname and two flags: allow-stop, and allow-debug" ^ [aProcess caseOf: { [ProcessorScheduler emergencyProcess] -> [{'emergency evaluator ShftCtrl-A'. false. true}]. [] -> [{'no process'. false. false}]. [Smalltalk lowSpaceWatcherProcess] -> [{'the low space watcher'. false. false}]. [WeakArray runningFinalizationProcess] -> [{'the WeakArray finalization process'. false. false}]. [Processor thisProcess] -> [{'the UI process'. false. true}]. [Processor backgroundProcess] -> [{'the idle process'. false. false}]. [Sensor interruptWatcherProcess] -> [{'the user interrupt watcher'. false. false}]. [Sensor eventTicklerProcess] -> [{'the event tickler'. false. false}]. [Project uiProcess] -> [{'the inactive Morphic UI process'. false. false}]. [Smalltalk at: #SoundPlayer ifPresent: [:sp | sp playerProcess]] -> [{'the Sound Player'. false. false}]. [ScheduledControllers ifNotNil: [ScheduledControllers activeControllerProcess]] -> [{'the inactive MVC controller process'. false. true}]. [Smalltalk at: #CPUWatcher ifPresent: [:cw | cw currentWatcherProcess]] -> [{'the CPUWatcher'. false. false}]} otherwise: [(aProcess priority = Processor timingPriority and: [aProcess suspendedContext receiver == Delay]) ifTrue: [{'the timer interrupt watcher'. false. false}] ifFalse: [{aProcess suspendedContext asString. true. true}]]] ifError: [:err :rcvr | {aProcess suspendedContext asString. true. true}]! ! !ProcessorScheduler methodsFor: 'accessing' stamp: 'dmu 11/25/2008 00:23'! activePriority "Answer the priority level of the currently running Process." ^self thisProcess priority! ! !ProcessorScheduler methodsFor: 'process state change' stamp: 'dmu 11/25/2008 00:23'! terminateActive "Terminate the process that is currently running." self thisProcess terminate! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:37'! removeAllPossible "Terminate and remove all processes that you can. This should leave the standard set only" self terminatableProcesses print do:[:proc| proc terminate]! ! !ProcessorScheduler methodsFor: 'removing' stamp: 'ssa 6/11/2010 14:31'! terminatableProcesses "Answer all current processes that may be user terminated like in the ProcessBrowser" "self terminatableProcesses" | processList | Smalltalk garbageCollectMost. "lose defunct processes" processList _ Process allSubInstances reject: [:each | each isTerminated]. processList _ processList sortBy: [:a :b | a priority >= b priority]. processList _ WeakArray withAll: processList. ^processList select:[:proc| (ProcessBrowser nameAndRulesFor: proc) at: 2]! ! !ProcessorScheduler methodsFor: '*RVMBootstrap' stamp: 'ads 1/24/2011 13:01'! areRunningProcessesInSchedulerLists "Our RVM follows Pallas' MS system and keeps runnable processes in the scheduler lists even when running." ^RVMPrimitivesNeededForBootstrapping isRVM! ! !ProcessorScheduler methodsFor: '*RVMBootstrap' stamp: 'dmu 11/25/2008 00:26'! isActive: aProcess ^ aProcess suspendedContext == nil! ! !ProcessorScheduler methodsFor: '*RVMBootstrap' stamp: 'dmu 12/7/2008 20:43'! thisProcess <primitive: 'primitiveThisProcess' > "must not specify module in order to hit obsolete_named_primitive_table and thus be local" ^ self activeProcess! ! !ProcessorScheduler methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 12:18'! debugMemberProcesses self suspendMemberProcesses. self memberProcesses do: [:p| p debug]! ! !ProcessorScheduler methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 11:16'! memberProcesses ^Process allInstances select: [:proc | proc creatorEnsemble notNil]! ! !ProcessorScheduler methodsFor: '*Sly3Bootstrap' stamp: 'dmu 2/23/2011 18:05'! suspendMemberProcesses self memberProcesses do: [:p| p ~= self thisProcess ifTrue: [p suspend]]! ! !ProcessorScheduler methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 11:17'! terminateMemberProcesses self memberProcesses do: [:p| p terminate]! ! !ProcessorScheduler methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 11:02'! userBackgroundPriority ^ UserBackgroundPriority! ! !ProcessorScheduler methodsFor: '*RVM' stamp: 'ads 1/30/2011 15:21'! yieldIfFewerCoresThan: n RVMOperations coreCount < n ifTrue: [self yield]! ! !ProcessorScheduler class methodsFor: 'background process' stamp: 'sm 2/24/2011 16:42'! startUp "Install a background process of the lowest possible priority that is always runnable." "Details: The virtual machine requires that there is aways some runnable process that can be scheduled; this background process ensures that this is the case." Smalltalk installLowSpaceWatcher. BackgroundProcess == nil ifFalse: [BackgroundProcess terminate]. BackgroundProcess _ [self idleProcess] newProcess. [BackgroundProcess useOnlyCore: (RVMMonitor getSample; mainRank).]. BackgroundProcess priority: SystemRockBottomPriority. BackgroundProcess name: 'IdleProcess'. BackgroundProcess resume. self startEmergencyProcess ! ! !ProcessorScheduler class methodsFor: '*RVMBootstrap' stamp: 'ssa 6/11/2010 14:34'! emergencyProcess ^ EmergencyProcess! ! !ProcessorScheduler class methodsFor: '*RVMBootstrap' stamp: 'ads 1/24/2011 13:04'! startEmergencyProcess "Bring up an emergency evaluator if the user hits control-shift-a" "self startEmergencyProcess" "self startEmergencyProcess. RVMPrimitivesNeededForBootstrapping getEmergencySemaphore signal" | sema | sema _ Semaphore new. RVMPrimitivesNeededForBootstrapping setEmergencySemaphore: sema. EmergencyProcess ifNotNil: [EmergencyProcess terminate]. ^ EmergencyProcess _ [[sema wait. Transcripter emergencyEvaluator] repeat] forkAt: Processor userInterruptPriority! ! !Project methodsFor: 'initialization' stamp: 'ssa 1/22/2010 14:06'! backgroundColorForMvcProject ^ Color r: 1.0 g: 1.0 b: 0.65! ! !Project methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:08'! defaultBackgroundColor ^ self isMorphic ifTrue: [] ifFalse: [self backgroundColorForMvcProject]! ! !Project methodsFor: 'accessing' stamp: 'ssa 9/3/2008 11:21'! renameTo: newName | | newName = self name ifFalse: [ version _ nil. self changeSet name: newName. ].! ! !Project methodsFor: 'menu messages' stamp: 'ssa 9/3/2008 11:09'! enter: returningFlag revert: revertFlag saveForRevert: saveForRevert "Install my ChangeSet, Transcript, and scheduled views as current globals. If returningFlag is true, we will return to the project from whence the current project was entered; don't change its previousProject link in this case. If saveForRevert is true, save the ImageSegment of the project being left. If revertFlag is true, make stubs for the world of the project being left. If revertWithoutAsking is true in the project being left, then always revert." | showZoom old forceRevert response seg newProcess | self isCurrentProject ifTrue: [^ self]. "Check the guards" guards ifNotNil: [guards := guards reject: [:obj | obj isNil]. guards do: [:obj | obj okayToEnterProject ifFalse: [^ self]]]. CurrentProject world triggerEvent: #aboutToLeaveWorld. forceRevert := false. CurrentProject rawParameters ifNil: [revertFlag ifTrue: [^ self inform: 'nothing to revert to']] ifNotNil: [saveForRevert ifFalse: [forceRevert := CurrentProject projectParameters at: #revertWithoutAsking ifAbsent: [false]]]. forceRevert not & revertFlag ifTrue: [response := SelectionMenu confirm: 'Are you sure you want to destroy this Project\ and revert to an older version?\\(From the parent project, click on this project''s thumbnail.)' withCRs trueChoice: 'Revert to saved version' falseChoice: 'Cancel'. response ifFalse: [^ self]]. revertFlag | forceRevert ifTrue: [seg := CurrentProject projectParameters at: #revertToMe ifAbsent: [^ self inform: 'nothing to revert to']] ifFalse: [CurrentProject finalExitActions. CurrentProject makeThumbnail. returningFlag == #specialReturn ifTrue: [ProjectHistory forget: CurrentProject. "this guy is irrelevant" Project forget: CurrentProject] ifFalse: [ProjectHistory remember: CurrentProject]]. revertFlag | saveForRevert | forceRevert ifFalse: [(Preferences valueOfFlag: #projectsSentToDisk) ifTrue: [self storeToMakeRoom]]. CurrentProject abortResourceLoading. CurrentProject saveProjectPreferences. "Update the display depth and make a thumbnail of the current project" CurrentProject displayDepth: Display depth. old := CurrentProject. "for later" "Show the project transition. Note: The project zoom is run in the context of the old project, so that eventual errors can be handled accordingly" displayDepth == nil ifTrue: [displayDepth := Display depth]. self installNewDisplay: Display extent depth: displayDepth. (showZoom := self showZoom) ifTrue: [self displayZoom: CurrentProject parent ~~ self]. (world isMorph and: [world hasProperty: #letTheMusicPlay]) ifTrue: [world removeProperty: #letTheMusicPlay] ifFalse: [Smalltalk at: #ScorePlayer ifPresentAndInMemory: [:playerClass | playerClass allSubInstancesDo: [:player | player pause]]]. returningFlag == #specialReturn ifTrue: [old removeChangeSetIfPossible. "keep this stuff from accumulating" nextProject := nil] ifFalse: [returningFlag ifTrue: [nextProject := CurrentProject] ifFalse: [previousProject := CurrentProject]]. CurrentProject saveState. CurrentProject isolationHead == self isolationHead ifFalse: [self invokeFrom: CurrentProject]. CurrentProject := self. self installProjectPreferences. ChangeSet newChanges: changeSet. TranscriptStream newTranscript: transcript. Sensor flushKeyboard. ProjectHistory remember: CurrentProject. world isMorph ifTrue: [] ifFalse: [World := nil. "Signifies MVC" Smalltalk at: #ScheduledControllers put: world]. saveForRevert ifTrue: [Smalltalk garbageCollect. "let go of pointers" old storeSegment. "result _" old world isInMemory ifTrue: ['Can''t seem to write the project.'] ifFalse: [old projectParameters at: #revertToMe put: old world xxxSegment clone]. 'Project written.']. "original is for coming back in and continuing." revertFlag | forceRevert ifTrue: [seg clone revert]. "non-cloned one is for reverting again later" self removeParameter: #exportState. "Complete the enter: by launching a new process" world isMorph ifFalse: [newProcess := [ScheduledControllers resetActiveController. "in case of walkback in #restore" showZoom ifFalse: [ScheduledControllers restore]. ScheduledControllers searchForActiveController] fixTemps newProcess priority: Processor userSchedulingPriority. newProcess resume. "lose the current process and its referenced morphs" Processor terminateActive]! ! !Project methodsFor: 'menu messages' stamp: 'dmu 11/25/2008 00:23'! enterForEmergencyRecovery "This version of enter invokes an absolute minimum of mechanism. An unrecoverable error has been detected in an isolated project. It is assumed that the old changeSet has already been revoked. No new process gets spawned here. This will happen in the debugger." self isCurrentProject ifTrue: [^ self]. CurrentProject saveState. CurrentProject _ self. Display newDepthNoRestore: displayDepth. Smalltalk newChanges: changeSet. TranscriptStream newTranscript: transcript. world isMorph ifTrue: ["Entering a Morphic project" World _ world. world install. world triggerOpeningScripts] ifFalse: ["Entering an MVC project" World _ nil. Smalltalk at: #ScheduledControllers put: world. ScheduledControllers restore]. UIProcess _ Processor thisProcess. ! ! !Project methodsFor: 'release' stamp: 'ssa 9/3/2008 11:09'! okToChange "Answer whether the window in which the project is housed can be dismissed -- which is destructive. We never clobber a project without confirmation" | ok | self subProjects size >0 ifTrue: [self inform: 'The project ', self name printString, ' contains sub-projects. You must remove these explicitly before removing their parent.'. ^ false]. ok _ world isMorph not and: [world scheduledControllers size <= 1]. ok ifFalse: [self isMorphic ifTrue: []]. "view from elsewhere. just delete it." ok _ (self confirm: 'Really delete the project ', self name printString, ' and all its windows?'). ok ifFalse: [^ false]. self removeChangeSetIfPossible. "do this last since it will render project inaccessible to #allProjects and their ilk" ProjectHistory forget: self. Project deletingProject: self. ^ true ! ! !Project class methodsFor: 'utilities' stamp: 'ssa 9/3/2008 11:11'! addItem: item toMenu: menu selection: action project: aProject menu add: item action: action! ! !Project class methodsFor: 'utilities' stamp: 'dmu 11/25/2008 00:24'! spawnNewProcessAndTerminateOld: terminate self spawnNewProcess. terminate ifTrue: [Processor terminateActive] ifFalse: [Processor thisProcess suspend]! ! !ProjectTeam methodsFor: 'searching' stamp: 'ads 12/6/2010 14:26'! findMethodsWrittenByThisTeamButNotIncludedInPackage: p | result systemCats | "Convenient for finding methods that don't follow the PackageInfo category-naming scheme." result := OrderedCollection new. systemCats := p systemCategories. ((Smalltalk allClasses reject: [:cls | systemCats includes: cls category]) gather: [:cls| {cls. cls class}]) do: [:cls | cls organization allMethodSelectors do: [:sel | | mr crs | mr := MethodReference new setStandardClass: cls methodSymbol: sel. crs := mr changeRecords. crs isEmpty ifFalse: [ (self didProjectMemberCreateChangeRecord: crs first) ifTrue: [ (p isYourClassExtension: mr category) ifFalse: [ result add: mr. ]. ]. ]. ]. ]. ^ result ! ! !ProjectTeam methodsFor: 'timestamps' stamp: 'ads 12/13/2010 19:15'! timestampFilter ^ timestampFilter! ! !ProjectTeam methodsFor: 'timestamps' stamp: 'ads 12/13/2010 19:15'! timestampFilter: aBlock timestampFilter := aBlock.! ! !ProjectTeam methodsFor: 'members' stamp: 'ads 12/2/2010 14:59'! initialsOfNonProjectMembers "Just convenient for making sure I haven't left anybody off of the list." ^ (self packages gather: [:p | p extensionMethods gather: [:m | | v | v := self oldVersionOf: m. v ifNil: [{}] ifNotNil: [| tokens | tokens := v stamp findTokens: Character separators. tokens isEmpty ifTrue: [{}] ifFalse: [{tokens at: 1}]]]. ]) asSet asSortedCollection! ! !ProjectTeam methodsFor: 'members' stamp: 'ads 12/2/2010 14:59'! initialsOfProjectMembers ^ initialsOfProjectMembers! ! !ProjectTeam methodsFor: 'members' stamp: 'ads 12/2/2010 14:59'! initialsOfProjectMembers: aCollectionOfInitials initialsOfProjectMembers := aCollectionOfInitials.! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 12/7/2010 14:22'! aboutToModifyClass: cls "Called from the removal script to help debug problems." Transcript show: 'About to modify class: ', cls name; cr.! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 12/13/2010 19:22'! didProjectMemberCreateChangeRecord: cr | stamp | stamp := cr stamp ifNil: [^ false]. "Not really sure whether it's better to use the timestampFilter or initialsOfProjectMembers. For now let's try the timestampFilter, if present. -- Adam" ^ timestampFilter ifNil: [self initialsOfProjectMembers anySatisfy: [:initials | stamp beginsWith: initials]] ifNotNil: [timestampFilter value: cr timeStamp]! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 12/2/2010 15:33'! oldVersionOf: aMethodReference ^ aMethodReference changeRecords detect: [:cr | (self didProjectMemberCreateChangeRecord: cr) not] ifNone: [nil]! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 1/26/2011 16:16'! revertPackage: p p revertToVersionBeforeTeam: self.! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 12/5/2010 22:49'! revertToOldVersionOf: aMethodReference ifNone: noneBlk | v | v := self oldVersionOf: aMethodReference. ^ v ifNil: noneBlk ifNotNil: [v fileIn].! ! !ProjectTeam methodsFor: 'versions' stamp: 'ads 12/10/2010 10:13'! revertToOldVersionOrRemove: aMethodReference Transcript show: 'Reverting or removing ', aMethodReference printString; cr. ^ self revertToOldVersionOf: aMethodReference ifNone: [aMethodReference removeFromSystem]! ! !PrototypeTester methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 18:56'! prototype "Get a prototype" ^ prototype copy ! ! !PrototypeTester methodsFor: 'as yet unclassified'! prototype: aPrototype "Set my prototype" prototype := aPrototype copy ! ! !PrototypeTester methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 18:57'! result "Perform the test the default number of times" ^ self resultFor: self class defaultRuns ! ! !PrototypeTester commentStamp: 'mjr 8/20/2003 13:09' prior: 0! I am a simple holder of a prototype object and hand out copies when requested.! !PrototypeTester class methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 13:08'! defaultRuns "the default number of times to test" ^ 50! ! !PrototypeTester class methodsFor: 'as yet unclassified' stamp: 'mjr 8/20/2003 13:08'! with: aPrototype ^self new prototype:aPrototype! ! !Quadrangle methodsFor: 'bordering'! borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4 "Set the border width of the receiver to a Rectangle that represents the left, right, top, and bottom border widths." borderWidth _ anInteger1 @ anInteger3 corner: anInteger2 @ anInteger4! ! !RVMAbsScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:29'! drawOnCanvas | color | 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(self data at: index)) min: self numberOfColors max:1). self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0. ! ! !RVMAbsScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:41'! redrawOnCanvas | color | self canvas fillWhite. self resetScannerLocation. self previousData do:[:oldData| 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(oldData at: index)) min: self numberOfColors max:1). self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0]! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:23'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:26'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^scaler! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:23'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMAbsScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:49'! typeLabel ^'AbsScan: '! ! !RVMAbsScanningStripChartView methodsFor: 'scaling' stamp: 'ssa 10/28/2008 20:47'! rescale "Reset the scaler and pass the previous data thorugh it to find the min/max. Then redraw" self scaler resetScaling. self previousData do:[:dats| dats do:[:d| scaler scale: d]]. self scaler resetOutOfRangeDetector. self topView newFrame. self redrawOnCanvas! ! !RVMAbsScanningStripChartView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:19'! adjustScaler ^true! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! coreStats "Answer the value of coreStats" coreStats isNil ifTrue:[self coreStats: OrderedCollection new]. ^coreStats! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! coreStats: anObject "Set the value of coreStats" coreStats := anObject! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 16:52'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMAllCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:34'! initializeFastFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFastFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:05'! initializeFastestFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFastestFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/13/2008 17:25'! initializeFrom: data forMessageNames: messageNames "data is an array of arrays, each element comprising stats from a single core" self rawData: data. data do:[:each| self coreStats add: (RVMCPUCoreStats newFromData: each forMessageNames: messageNames)] ! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! allocationsSinceLastReadMostlys ^self coreStats collect:[:each| each allocationsSinceLastReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadWrites ^self coreStats collect:[:each| each allocationsSinceLastReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:52'! allocationsSinceLasts ^self coreStats collect:[:each| each allocationsSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:19'! bytecodeCounts "RVMMulticoreSample capture bytecodeCounts" "Answer the collection of bytecode counts during this sample" ^self coreStats collect:[:each| each bytecodesExecuted]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:37'! bytecodesPerMillisecond "RVMMulticoreSample capture bytecodesPerMillisecond" "Answer the collection of ratios of bytecodes executed per millisecond during this sample" ^self coreStats collect:[:each| each bytecodesPerMillisecond]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:24'! bytecodesPerSecond "RVMMulticoreSample capture bytecodesPerSecond" "Answer the collection of ratios of bytecodes executed per second during this sample" ^self coreStats collect:[:each| each bytecodesPerSecond]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! bytesLeftReadMostlys ^self coreStats collect:[:each| each bytesLeftReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadWrites ^self coreStats collect:[:each| each bytesLeftReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLefts ^self coreStats collect:[:each| each bytesLeft]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:38'! bytesUsedReadMostlys ^self coreStats collect:[:each| each bytesUsedReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:48'! bytesUsedReadWrites ^self coreStats collect:[:each| each bytesUsedReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 1/1/1970 00:07'! bytesUseds ^self coreStats collect:[:each| each bytesUsed]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:39'! compactionsSinceLastReadMostlys ^self coreStats collect:[:each| each compactionsSinceLastReadMostly]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLastReadWrites ^self coreStats collect:[:each| each compactionsSinceLastReadWrite]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLasts ^self coreStats collect:[:each| each compactionsSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:07'! contextChangeCounts "RVMMulticoreSample capture contextChangeCounts" "Answer the collection of contextChanges during this sample" ^self coreStats collect:[:each| each contextChangeCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:52'! cyclesRunWaitRatios "RVMMulticoreSample capture cyclesRunWaitRatios" "Answer the collection of ratios during this sample" ^self coreStats collect:[:each| each cyclesRunWaitRatio]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:48'! cyclesRunnings "RVMMulticoreSample capture cyclesRunnings" "Answer the collection of cyclesRunning counts during this sample" ^self coreStats collect:[:each| each cyclesRunning]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:41'! cyclesSinceLasts "RVMMulticoreSample capture cyclesSinceLasts" "Answer the collection of cyclesSinceLasts counts during this sample" ^self coreStats collect:[:each| each cyclesSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:48'! cyclesWaitings "RVMMulticoreSample capture cyclesWaitings" "Answer the collection of cyclesWaiting counts during this sample" ^self coreStats collect:[:each| each cyclesWaiting]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/5/2011 12:55'! gcMilliseconds ^ self coreStats collect: [:cs| cs gcMilliseconds]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! interruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each interruptCheckCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! millisecondsRunnings "RVMMulticoreSample capture millisecondsRunnings" "Answer the collection of millisecondsRunning counts during this sample" ^self coreStats collect:[:each| each millisecondsRunning]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:37'! millisecondsWaitings "RVMMulticoreSample capture millisecondsWaitings" "Answer the collection of millisecondsWaiting counts during this sample" ^self coreStats collect:[:each| each millisecondsWaiting]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:43'! msRunWaitRatios "RVMMulticoreSample capture msRunWaitRatios" "Answer the collection of ratios during this sample" ^self coreStats collect:[:each| each msRunWaitRatio]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:29'! msSinceLasts "RVMMulticoreSample capture msSinceLasts" "Answer the collection of msSinceLasts counts during this sample" ^self coreStats collect:[:each| each msSinceLast]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:03'! receiveTallySum | tallies sum s | tallies := self coreStats collect: [:each | each receiveTally]. sum := Array new: (tallies at: 1) rawData size. 1 to: sum size do: [:i | s := 0. 1 to: tallies size do: [:j | s := s + ((tallies at: j) rawData at: i)]. sum at: i put: s]. ^ sum! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:53'! sendTallySums "Answer an array with the sum of all my send tallies in order from all my coreStats" | sums stats | sums _ self coreStats first sendTallySums. 2 to: self coreStats size do:[:index| stats _ self coreStats at: index. sums _ sums + stats sendTallySums]. ^sums! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:27'! sendTallySumsDictionary "Answer a dictionary with the sums of all my send tallies from all my coreStats associated with their name" | dict keys values | dict _ Dictionary new. keys _ RVMCoreMessageTally tallyOrder. values _ self sendTallySums. keys with: values do:[:key :value| dict at: key put: value]. ^dict! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/26/2009 09:55'! sendTallySumsSorted "Answer a sorted collection with the sums of all my send tallies from all my coreStats associated with their name" ^self sendTallySumsDictionary associations asSortedCollection:[:a :b| a value > b value]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 17:06'! sendTallySumsSortedReport "Answer a string to be used as a report of the sorted send tally sums" | report | report _ 'Sorted Send Tallies for all cores',String crlf,'--------------------------',String crlf. self sendTallySumsSorted do:[:assoc| report _ report, assoc value printString,' ',assoc key,String crlf]. ^report! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:07'! unforcedInterruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each unforcedInterruptCheckCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:17'! yieldCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self coreStats collect:[:each| each yieldCount]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:16'! yieldFrequencies "RVMMulticoreSample capture yieldFrequencies" ^self coreStats collect:[:each| each yieldFrequency]! ! !RVMAllCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:37'! yieldsPerSecond "RVMMulticoreSample capture yieldsPerSecond" "Answer the collection of ratios of yields per second during this sample" ^self coreStats collect:[:each| each yieldsPerSecond]! ! !RVMAllCPUCoreStats methodsFor: 'DNU hacks' stamp: 'ssa 3/27/2009 17:26'! doesNotUnderstand: aMessage "Hack DNU to install measurement mesages for tally aspects" | code tallyAspect | (aMessage selector first: 5) = 'sumOf' ifTrue:[ tallyAspect _ aMessage selector last: aMessage selector - 5. tallyAspect at: 1 put: tallyAspect first asLowercase. (RVMMulticoreSample coreTallyAspects includes: tallyAspect) ifFalse:[^super doesNotUnderstand: aMessage]. code _ aMessage selector,' "Answer the sum for this tally aspect from all cores" ^self sendTallySumsDictionary at: #',tallyAspect. self class compile: code classified: 'tallying' notifying: nil. ^self perform: aMessage selector]. ^super doesNotUnderstand: aMessage! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:33'! newFastFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFastFrom: data forMessageNames: messageNames. ^stats! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:05'! newFastestFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFastestFrom: data forMessageNames: messageNames. ^stats! ! !RVMAllCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/13/2008 17:26'! newFrom: data forMessageNames: messageNames "Answer a new instance of me using this data, which is a collection of arrays of core stats" | stats | stats := self new. stats initializeFrom: data forMessageNames: messageNames. ^stats! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:25'! aspectFromUser | menu answer | menu := CustomMenu new. self view aspects do: [:aspect | menu add: aspect action: aspect]. answer := menu startUp: self view aspect withCaption: 'Select the aspect to monitor' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. self view aspect: answer. self view displayView. self view topView newFrame! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:55'! controlActivity Cursor menu show. super controlActivity! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:55'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMAspectLabelController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 16:19'! yellowButtonActivity self aspectFromUser. ! ! !RVMAspectLabelView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView | labelRect labelText labelForm | self uncache. labelText := self label asDisplayText. labelText foregroundColor: self foregroundColor backgroundColor: self backgroundColor. labelForm := labelText asParagraph asForm. labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self backgroundColor. labelForm displayOn: Display at: labelRect leftCenter - labelForm boundingBox leftCenter + (2@0) clippingBox: labelRect rule: Form paint fillColor: nil. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated." ! ! !RVMAspectLabelView methodsFor: 'updating' stamp: 'ssa 9/17/2008 14:17'! update: aSymbol aSymbol = self getAspectSelector ifTrue:[self displayView ]. super update: aSymbol! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:51'! aspect ^self getAspectSelector isSymbol ifTrue:[self model perform: self getAspectSelector] ifFalse:["assume a block" self getAspectSelector value]! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:14'! aspect: aSymbol self setAspectSelector isSymbol ifTrue:[self model perform: self setAspectSelector with: aSymbol] ifFalse:["assume a block" self setAspectSelector value: aSymbol]. ! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:15'! aspects ^self getAspectsSelector isSymbol ifTrue:[self model perform: self getAspectsSelector] ifFalse:["assume a block" self getAspectsSelector value]! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:06'! backgroundColor ^Color white! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:36'! foregroundColor ^Color black! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! getAspectSelector "Answer the value of getAspectSelector" getAspectSelector isNil ifTrue:[self getAspectSelector: #aspect]. ^ getAspectSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! getAspectSelector: anObject "Set the value of getAspectSelector" getAspectSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! getAspectsSelector "Answer the value of getAspectsSelector" getAspectsSelector isNil ifTrue:[self getAspectsSelector: #aspects]. ^ getAspectsSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! getAspectsSelector: anObject "Set the value of getAspectsSelector" getAspectsSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:18'! label ^self aspect! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:25'! lastAspect "Answer the value of lastAspect" lastAspect isNil ifTrue:[self lastAspect: #foo]. ^ lastAspect! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:25'! lastAspect: anObject "Set the value of lastAspect" lastAspect _ anObject! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:14'! setAspectSelector "Answer the value of setAspectSelector" setAspectSelector isNil ifTrue:[self setAspectSelector: #aspect:]. ^ setAspectSelector! ! !RVMAspectLabelView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 16:13'! setAspectSelector: anObject "Set the value of setAspectSelector" setAspectSelector _ anObject! ! !RVMAspectLabelView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 16:16'! defaultControllerClass ^RVMAspectLabelController! ! !RVMAspectLabelView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:27'! on: anObject "Answer a label view that will send #aspect to this object to find its label" | view | view := self new. view model: anObject. ^view! ! !RVMAspectLabelView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 14:04'! on: anObject getAllAspectsWith: getAspectsSelector getCurrentAspectWith: getAspectSelector setNewAspectWith: setAspectSelector "Answer an aspect view that can probe and change the aspect of its aspectee. Note 'selector' arguments can be symbols or blocks" | view | view := self new. view model: anObject. view getAspectsSelector: getAspectsSelector. view getAspectSelector: getAspectSelector. view setAspectSelector: setAspectSelector. ^view! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:31'! example "RVMAspectLabelView example" | topView view | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. view _ self on: view getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view model: view. topView addSubView: view. topView label: 'Aspect Button'. topView controller open! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:31'! exampleMany "RVMAspectLabelView exampleMany" | topView view1 view2 view3 | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@75. topView maximumSize: 200@100. view1 _ self on: view1 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view1 on: view1. view2 _ self on: view2 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view2 on: view2. view3 _ self on: view3 getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view3 on: view3. topView addSubView: view1. topView addSubView: view2 below: view1. topView addSubView: view3 below: view2. topView label: 'Aspect Button'. topView controller open! ! !RVMAspectLabelView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:32'! exampleWithColorButton "RVMAspectLabelView exampleWithColorButton" | topView view colorButton | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. view _ self on: view getAllAspectsWith: [{ #foo. #bar. #baz. #waz }] getCurrentAspectWith: #lastAspect setNewAspectWith: #lastAspect:. view model: view. colorButton _ RVMColorButtonView new. topView addSubView: view in: (0@0 extent: 5/6 @ 1) borderWidth:0. topView addSubView: colorButton in: (5/6@0 extent: 1/6@1) borderWidth:0. topView label: 'Aspect Button'. topView controller open! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:44'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #bytesUseds]. ^ aspect! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:03'! aspect: anObject "Set the value of aspect" aspect _ anObject. aspect notNil ifTrue:[self scaler: (RVMMonitor scalerFor:aspect)]! ! !RVMAspectTrace methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:17'! aspectLabel ^self aspect! ! !RVMAspectTrace methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:26'! addData "Assume a single valued data source" self add:(RVMMonitor lastSample perform: self aspect)! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:29'! allView ^self aspectColorMuteView! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:32'! aspectButton "Answer an aspect button connect to my aspect" ^RVMAspectLabelView on: self getAllAspectsWith: [RVMMulticoreSample systemAspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:46'! aspectColorMuteView "Answer a view showing my color and aspect" | view | view _ RVMView new. view model: self. view addSubView: self muteButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self colorButton in: ((1/10)@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((2/10)@0 extent: (8/10) @ 1) borderWidth:1. ^view! ! !RVMAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:37'! aspectColorView "Answer a view showing my color and aspect" | view | view _ RVMView new. view addSubView: self colorButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((1/10)@0 extent: (9/10) @ 1) borderWidth:1. ^view! ! !RVMAspectTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:35'! aspect: aSymbol size: anInteger color: aColor | trace | trace _ self new. trace scaler: RVMDataScaler new automatic; rawData: (RVMCircularCollection new: anInteger); color: aColor; aspect: aSymbol. ^trace! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:51'! exampleInstance "RVMAspectTrace exampleInstance" ^self aspect: #bytecodeCountsAverage size: 100 color: Color blue! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:46'! exampleView1 "RVMAspectTrace exampleView1" RVMStripChartView openOnTrace: self exampleInstance! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:31'! exampleView2 "RVMAspectTrace exampleView2" self exampleInstance aspectColorView demo! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:35'! exampleView3 "RVMAspectTrace exampleView3" self exampleInstance aspectButton demo! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:25'! exampleView4 "RVMAspectTrace exampleView4" | traces | traces _ OrderedCollection new. RVMMulticoreSample systemAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMAspectTrace class methodsFor: 'examples' stamp: 'dmu 9/17/2010 15:34'! exampleView8 "RVMAspectTrace exampleView8" | traces | traces _ OrderedCollection new. traces add:(self aspect: #numberOfRunningProcesses size: 100 color: Color random). RVMStripChartView openOnTraces: traces! ! !RVMAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:18'! monitorAllSystemAspects "RVMAspectTrace monitorAllSystemAspects" | traces colors | colors _ (Color wheel: RVMMulticoreSample systemAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. RVMMulticoreSample systemAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'All system aspects'! ! !RVMAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 00:07'! monitorAspects: someAspects "RVMAspectTrace monitorAspects: #(bytecodeCountsAverage bytecodesPerSecondAverage yieldCountsAverage)" | traces colors | colors _ (Color wheel: someAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. someAspects do:[:aspect| traces add:(self aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'Selected system aspects'! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:49'! initialize interlock _ Semaphore new. interlock signal. waitSema _ Semaphore new. signalsNeededToPass _ 0! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 19:14'! signal interlock critical: [ signalsNeededToPass _ signalsNeededToPass - 1. signalsNeededToPass < 0 ifTrue: [self error: 'oops']. signalsNeededToPass = 0 ifTrue: [waitSema signal] ]! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 14:23'! signalsNeededToPass: n signalsNeededToPass _ n! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:32'! wait waitSema wait! ! !RVMBarrier methodsFor: 'as yet unclassified' stamp: 'dmu 1/21/2010 18:24'! waitSema ^ waitSema! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 23:53'! moreModificationsByTheRenaissanceTeam1 ^ { { 'Debugger'. 'defaultReceiverInspector' }. { 'Debugger'. 'defaultContextVariablesInspector' }. { 'OpaqueForm' }. { 'PluggableListViewByObject' }. { 'TextBlockDoIt' }. { 'Behavior'. 'setInstanceFormat:' }. { 'Behavior'. 'subobjects' }. { 'Behavior'. 'withAllSubclasses' }. { 'BlockContext'. 'asString' }. { 'BlockContext'. 'untilFalse:' }. { 'Boolean'. 'haltIfTrue' }. { 'Boolean'. 'mustBeBoolean' }. { 'Boolean'. 'mustBeBooleanIn:' }. { 'Browser'. 'classListIndex:' }. { 'Browser'. 'createInstVarAccessors' }. { 'Browser'. 'defineMessage:notifying:' }. { 'Browser'. 'metaClassOrganizer:' }. { 'ChangeList'. 'selectChangesMatching' }. { 'ChangeList'. 'selectSuchThat' }. { 'ChangeList'. 'selectedChanges' }. { 'ChangeList'. 'spawnSelections' }. { 'ChangeList'. 'spawnSuchThat:titled:' }. { 'ChangeList'. 'togglePrimaryListIndex:' }. { 'ChangeSet'. 'postscript' }. { 'ChangeSet'. 'postscript:' }. { 'ChangeSet'. 'preamble' }. { 'ChangeSet'. 'preamble:' }. { 'ChangeSet'. 'revertable' }. { 'ChangeSet'. 'structures:' }. { 'ChangeSet'. 'superclasses:' }. { 'ChangeSorter'. 'moveClassesToOtherMatching' }. { 'CharacterScanner'. 'scanCharactersFrom:to:in:rightX:stopConditions:displaying:' }. { 'ClassCommentVersionsBrowser'. 'scanVersionsOf:' }. { 'ClassDescription'. 'allMethodsInCategory:' }. { 'ClassDescription'. 'instanceVariablesString' }. { 'CodeHolder'. 'addContentsTogglesTo:' }. { 'Collection'. 'atRandom' }. { 'Collection'. 'removeAll:ifAbsent:' }. { 'Collection'. 'subobjects' }. { 'ColorForm'. 'setExtent:depth:' }. { 'CompiledMethod'. 'symbolic' }. { 'CompiledMethod'. 'timeStamp' }. { 'ContextPart'. 'errorReportOn:' }. { 'ContextPart'. 'unwindTo:' }. { 'Controller'. 'lastActivityTime' }. { 'Controller'. 'lastActivityTime:' }. { 'CustomMenu'. 'arguments' }. { 'CustomMenu'. 'invokeOn:orSendTo:' }. { 'CustomMenu'. 'selections' }. { 'CustomMenu'. 'startUp:withCaption:at:' }. { 'CustomMenu'. 'targets' }. { 'Debugger'. 'buildMVCDebuggerViewLabel:minSize:' }. { 'Debugger'. 'codeView' }. { 'Debugger'. 'contextStack' }. { 'Debugger'. 'contextStack:' }. { 'Debugger'. 'contextStackIndex' }. { 'Debugger'. 'contextStackIndex:' }. { 'Debugger'. 'contextStackList:' }. { 'Debugger'. 'contextStackMenu:shifted:' }. { 'Debugger'. 'contextStackTop' }. { 'Debugger'. 'contextStackTop:' }. { 'Debugger'. 'customButtonSpecs' }. { 'Debugger'. 'debugAt:' }. { 'Debugger'. 'errorWasInUIProcess' }. { 'Debugger'. 'errorWasInUIProcess:' }. { 'Debugger'. 'expandStack' }. { 'Debugger'. 'interruptedController' }. { 'Debugger'. 'interruptedController:' }. { 'Debugger'. 'interruptedProcess' }. { 'Debugger'. 'interruptedProcess:' }. { 'Debugger'. 'isolationHead:' }. { 'Debugger'. 'labelForContext:' }. { 'Debugger'. 'openFullNoSuspendLabel:' }. { 'Debugger'. 'pcRange' }. { 'Debugger'. 'proceedValue' }. { 'Debugger'. 'process:controller:context:isolationHead:' }. { 'Debugger'. 'receiverInspector' }. { 'Debugger'. 'resetContext:' }. { 'Debugger'. 'resumeProcess:' }. { 'Debugger'. 'savedCursor' }. { 'Debugger'. 'savedCursor:' }. { 'Debugger'. 'selectedContext' }. { 'Debugger'. 'selectingPC' }. { 'Debugger'. 'selectingPC:' }. { 'Debugger'. 'sourceMap:' }. { 'Debugger'. 'tempNames' }. { 'Debugger'. 'terminateInterruptedProcessIfSoleOwner' }. { 'Debugger'. 'theMethodNode' }. { 'Debugger'. 'updateInspectorToObject:' }. { 'Debugger'. 'updateInspectors' }. { 'Dictionary'. 'subobjects' }. { 'DisplayMedium'. 'border:width:fillColor:clippingBox:' }. { 'DisplayMedium'. 'outlined' }. { 'DisplayObject'. 'displayOn:at:' }. { 'DisplayScreen'. 'clippingTo:do:' }. { 'DisplayScreen'. 'outline:while:width:halftone:' }. { 'DisplayScreen'. 'setExtent:depth:' }. { 'DisplayText'. 'asParagraphWithStyle:' }. { 'DisplayText'. 'isEmpty' }. { 'DisplayText'. 'numberOfLines' }. { 'EventSensor'. 'fetchMoreEvents' }. { 'EventSensor'. 'flushNonKbdEvents' }. { 'EventSensor'. 'nextEvent' }. { 'EventSensor'. 'primGetNextEvent:' }. { 'EventSensor'. 'primKbdNext' }. { 'EventSensor'. 'primMouseButtons' }. { 'EventSensor'. 'processEvent:' }. { 'EventSensor'. 'processKeyboardEvent:' }. { 'False'. 'haltIfFalse' }. { 'FileList'. 'fullFileListMenu:shifted:' }. { 'Form'. 'bottomLeft' }. { 'Form'. 'bottomRight' }. { 'Form'. 'displayTranslucentOn:at:clippingBox:' }. { 'Form'. 'eraseInside:' }. { 'Form'. 'fill:rule:fillColor:clippingBox:' }. { 'Form'. 'leftCenter' }. { 'Form'. 'paintBits:at:clippingBox:translucent:' }. { 'Form'. 'rightCenter' }. { 'Form'. 'rotateBy:smoothing:' }. { 'FormView'. 'defaultRule' }. { 'InfiniteForm'. 'hasNonStandardPalette' }. { 'InputSensor'. 'waitClick' }. { 'Inspector'. 'fieldListMenu:' }. { 'Inspector'. 'locateSelection' }. { 'Inspector'. 'selectionIndex:' }. { 'Inspector'. 'selectionUpdateTime' }. { 'Inspector'. 'selectionUpdateTime:' }. { 'InstructionStream'. 'skipBackBeforeJump' }. { 'LinkedList'. 'asOrderedCollection' }. { 'ListController'. 'processKeyboard' }. { 'ListView'. 'clippingBox' }. { 'ListView'. 'findSelection:' }. { 'ListView'. 'isEmpty' }. { 'ListView'. 'textStyle:' }. { 'ListView'. 'update:' }. { 'Matrix'. 'removeAll' }. { 'Message'. 'selector:' }. { 'MethodHolder'. 'doItReceiver' }. { 'Number'. 'asPointWithinRectangleWithExtent:' }. { 'Number'. 'atRandom' }. { 'Number'. 'floatPrecisionForDecimalPlaces:' }. { 'Number'. 'inverted' }. { 'Number'. 'pi' }. { 'Number'. 'printShowingMax3Digits' }. { 'Object'. 'allInstanceVariableValuesPlusIndexed' }. { 'Object'. 'asExplorerString' }. { 'Object'. 'asObjectCoordinate' }. { 'Object'. 'changed:with:from:' }. { 'Object'. 'hasInstanceVariables' }. { 'Object'. 'inspect' }. { 'Object'. 'isArray' }. { 'Object'. 'isBoolean' }. { 'Object'. 'isEnsemble' }. { 'Object'. 'locate' }. { 'Object'. 'outlineString' }. { 'Object'. 'printDirectlyToDisplay' }. { 'Object'. '~==' }. { 'OpaqueForm'. 'colormapIfNeededFor:' }. { 'OpaqueForm'. 'figure' }. { 'OpaqueForm'. 'offset' }. { 'OpaqueForm'. 'shape' }. { 'OpaqueForm'. 'valueAt:' }. { 'OrderedCollection'. 'addAll:after:' }. { 'OrderedCollection'. 'inspectorClass' }. { 'ParagraphEditor'. 'adjustWidths' }. { 'ParagraphEditor'. 'browseIt' }. { 'ParagraphEditor'. 'compileSelectionFor:in:' }. { 'ParagraphEditor'. 'cursorUp:' }. { 'ParagraphEditor'. 'evaluate:' }. { 'ParagraphEditor'. 'evaluateSelection' }. { 'ParagraphEditor'. 'exploreIt:' }. { 'ParagraphEditor'. 'inspectIt' }. { 'ParagraphEditor'. 'installAsTest' }. { 'ParagraphEditor'. 'printIt:' }. { 'Pen'. 'direction:' }. { 'Pen'. 'penAngleFrom:to:' }. { 'Pen'. 'turnToward:' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 22:23'! moreModificationsByTheRenaissanceTeam2 ^ { { 'PluggableButtonView'. 'label:' }. { 'PluggableButtonView'. 'performAction' }. { 'PluggableButtonView'. 'update:' }. { 'PluggableFileList'. 'startUpWithCaption:' }. { 'PluggableListControllerOfMany'. 'redButtonActivity' }. { 'PluggableListView'. 'update:' }. { 'PluggableListViewByObject'. 'labelForItem:' }. { 'PluggableListViewByObject'. 'list:' }. { 'PluggableListViewByObject'. 'objects:' }. { 'Point'. 'floor' }. { 'Point'. 'inverted' }. { 'Point'. 'manhattanDist:' }. { 'Point'. 'mined' }. { 'Point'. 'x:' }. { 'Point'. 'zeno' }. { 'PointerFinder'. 'menu:shifted:' }. { 'PointerFinder'. 'open' }. { 'PositionableStream'. 'printOn:' }. { 'Project'. 'enter:revert:saveForRevert:' }. { 'Rectangle'. 'asRandomPoint' }. { 'Rectangle'. 'displayOn:withBorderWidths:' }. { 'Rectangle'. 'displayWithBorderWidths:' }. { 'Rectangle'. 'height:' }. { 'Rectangle'. 'intersect:' }. { 'Rectangle'. 'moveBy:' }. { 'Rectangle'. 'newRectButtonPressedDo:' }. { 'Rectangle'. 'newRectFrom:' }. { 'Rectangle'. 'origin:' }. { 'Rectangle'. 'subDivideBy:' }. { 'Rectangle'. 'subDivideRoundedBy:' }. { 'Rectangle'. 'topRight:' }. { 'Rectangle'. 'width:' }. { 'ScreenController'. 'appearanceMenu' }. { 'ScreenController'. 'closeAllUnlockedWindows' }. { 'ScreenController'. 'closeTopWindow' }. { 'ScreenController'. 'controlActivity' }. { 'ScreenController'. 'exploreViewFromUser' }. { 'ScreenController'. 'isControlWanted' }. { 'ScreenController'. 'openMenu' }. { 'ScreenController'. 'openProcessBrowser' }. { 'ScreenController'. 'preventClosing' }. { 'ScreenController'. 'restoreDisplay' }. { 'ScreenController'. 'windowMenu' }. { 'SequenceableCollection'. 'asCircularCollection' }. { 'SequenceableCollection'. 'groupsOfNoMoreThan:atATimeDo:' }. { 'SequenceableCollection'. 'rotateBackward' }. { 'SequenceableCollection'. 'rotateForward' }. { 'SequenceableCollection'. 'with:with:do:' }. { 'SequenceableCollection'. 'with:with:withIndexDo:' }. { 'SequenceableCollection'. 'with:withIndexDo:' }. { 'SequenceableCollection'. 'without:collect:' }. { 'SequenceableCollection'. 'without:select:' }. { 'SmalltalkImage'. 'forceChangesToDisk' }. { 'StandardFileStream'. 'nextPut:' }. { 'StandardSystemController'. 'blueButtonActivity' }. { 'StandardSystemController'. 'blueButtonMenu' }. { 'StandardSystemController'. 'closeAndUnscheduleIfOkWithModelNoTerminate' }. { 'StandardSystemController'. 'closeForReal' }. { 'StandardSystemController'. 'preventClosing:' }. { 'StandardSystemController'. 'status' }. { 'StandardSystemView'. 'cacheBitsAsTwoTone' }. { 'StandardSystemView'. 'closingGuardIcon' }. { 'StandardSystemView'. 'displayLabelBackground:' }. { 'StandardSystemView'. 'displayView' }. { 'StandardSystemView'. 'initialFrame' }. { 'StandardSystemView'. 'setUpdatablePanesFrom:' }. { 'StrikeFont'. 'characterToGlyphMap:' }. { 'StrikeFont'. 'emphasis' }. { 'StrikeFont'. 'maxWidth:' }. { 'StrikeFont'. 'pointSize:' }. { 'StrikeFont'. 'raster:' }. { 'StrikeFont'. 'subscript:' }. { 'StrikeFont'. 'superscript:' }. { 'StrikeFont'. 'type' }. { 'StrikeFont'. 'xOffset:' }. { 'StrikeFont'. 'xTable:' }. { 'String'. 'asParagraphWithStyle:' }. { 'String'. 'withoutFirst:' }. { 'String'. 'withoutLast:' }. { 'StringHolderView'. 'displayContents:' }. { 'StringHolderView'. 'textStyle:' }. { 'SystemDictionary'. 'forceChangesToDisk' }. { 'SystemDictionary'. 'majorShrinkClassesToLeave' }. { 'SystemDictionary'. 'presumedSentMessages' }. { 'SystemDictionary'. 'recolorWindows' }. { 'Text'. 'asParagraphWithStyle:' }. { 'Text'. 'bold' }. { 'Text'. 'font:' }. { 'Text'. 'fontName:pointSize:' }. { 'Text'. 'italic' }. { 'Text'. 'makeUnderlineFrom:to:' }. { 'Text'. 'makeUnderlinedFrom:to:' }. { 'Text'. 'underline' }. { 'TextBlockDoIt'. 'actOnClickFor:' }. { 'TextBlockDoIt'. 'actionBlock' }. { 'True'. 'haltIfTrue' }. { 'View'. 'addSubView:below:' }. { 'View'. 'addSubView:toRightOf:' }. { 'View'. 'allSubViews' }. { 'View'. 'borderColor:' }. { 'View'. 'boundingBox:' }. { 'View'. 'displayTransformation:' }. { 'View'. 'isRVMView' }. { 'View'. 'moveLeft' }. { 'View'. 'moveRight' }. { 'View'. 'setDefaultBackgroundColor' }. { 'View'. 'shorter' }. { 'View'. 'stretchFrame:startingWith:' }. { 'View'. 'taller' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 23:07'! moreModificationsByTheRenaissanceTeam3 ^ { { 'Behavior'. 'allSubclasses' }. { 'Behavior'. 'archiveVersion' }. { 'Behavior'. 'compile:notifying:trailer:' }. { 'BlockContext'. 'asContext' }. { 'BlockContext'. 'loopExit' }. { 'BlockContext'. 'value:value:value:value:value:' }. { 'BlockNode'. 'returnSelfIfNoOther' }. { 'Boolean'. 'haltIfFalse' }. { 'Browser'. 'classOrganizer' }. { 'Browser'. 'classOrganizer:' }. { 'Browser'. 'defineMessageFrom:notifying:' }. { 'Browser'. 'lastClassSelected' }. { 'Browser'. 'lastClassSelected:' }. { 'Browser'. 'metaClassIndicated:' }. { 'Browser'. 'metaClassOrganizer' }. { 'Browser'. 'setClass:selector:' }. { 'Browser'. 'systemOrganizer' }. { 'ChangeList'. 'changeList:' }. { 'ChangeList'. 'changeListMenu:' }. { 'ChangeList'. 'scanRecords:' }. { 'ChangeList'. 'spawnChangesMatching' }. { 'ChangeList'. 'spawnSuchThat' }. { 'ChangeRecord'. 'match:' }. { 'ChangeRecord'. 'methodClassNameSafe' }. { 'ChangeRecord'. 'methodSelectorSafe' }. { 'ChangeSet'. 'changeRecords' }. { 'ChangeSet'. 'changeRecords:' }. { 'ChangeSet'. 'checkForConversionMethods' }. { 'ChangeSet'. 'editPostscript' }. { 'ChangeSet'. 'fileOutClassDefinition:on:' }. { 'ChangeSet'. 'isolatedProject:' }. { 'ChangeSet'. 'isolationSet' }. { 'ChangeSet'. 'revertable:' }. { 'ChangeSorter'. 'classListKey:from:' }. { 'ChangeSorter'. 'classListMenu:shifted:' }. { 'ChangeSorter'. 'copyClassesToOtherMatching' }. { 'Character'. 'isCharacter' }. { 'CharacterScanner'. 'destX:' }. { 'CodeHolder'. 'addModelItemsToWindowMenu:' }. { 'CodeHolder'. 'offerWhatToShowMenu' }. { 'ContextPart'. 'runSimulated:contextAtEachStep:' }. { 'ControlManager'. 'activeControllerNoTerminate:andProcess:' }. { 'ControlManager'. 'reset' }. { 'ControlManager'. 'restore:below:without:' }. { 'Controller'. 'initialize' }. { 'Debugger'. 'buildMVCNotifierViewLabel:message:minSize:' }. { 'Debugger'. 'contextStackIndex:oldContextWas:' }. { 'Debugger'. 'contextVariablesInspector' }. { 'Debugger'. 'contextVariablesInspector:' }. { 'Debugger'. 'externalInterrupt' }. { 'Debugger'. 'failedProject' }. { 'Debugger'. 'failedProject:' }. { 'Debugger'. 'installListFontInto:' }. { 'Debugger'. 'isolationHead' }. { 'Debugger'. 'newStack:' }. { 'Debugger'. 'openNotifierContents:label:' }. { 'Debugger'. 'optionalButtonPairs' }. { 'Debugger'. 'otherButtonSpecs' }. { 'Debugger'. 'receiverInspector:' }. { 'Debugger'. 'release' }. { 'Debugger'. 'sourceMap' }. { 'Debugger'. 'step' }. { 'Debugger'. 'tempNames:' }. { 'Debugger'. 'theMethodNode:' }. { 'Debugger'. 'toggleContextStackIndex:' }. { 'Debugger'. 'windowIsClosing' }. { 'DictionaryInspector'. 'dictionaryMenu:' }. { 'DisplayMedium'. 'border:width:rule:fillColor:clippingBox:' }. { 'DisplayMedium'. 'border:widthRectangle:rule:fillColor:clippingBox:' }. { 'DisplayObject'. 'followCursor' }. { 'DisplayScreen'. 'boundingBox' }. { 'DisplayScreen'. 'clippingBox:' }. { 'DisplayScreen'. 'copyFrom:' }. { 'DisplayScreen'. 'fullScreen' }. { 'DisplayScreen'. 'outline:do:while:width:halftone:' }. { 'DualChangeSorter'. 'open' }. { 'EventSensor'. 'flushAllButDandDEvents' }. { 'EventSensor'. 'primKbdPeek' }. { 'EventSensor'. 'primMousePt' }. { 'EventSensor'. 'queueEvent:' }. { 'FileList'. 'fileContentsMenu:shifted:' }. { 'FileList'. 'fileSelectedMenu:' }. { 'Float'. 'absPrintOn:base:digitCount:' }. { 'Form'. 'asOpaqueForm' }. { 'Form'. 'bottomCenter' }. { 'Form'. 'displayBox' }. { 'Form'. 'displayOn:at:clippingBox:rule:fillColor:' }. { 'Form'. 'erase' }. { 'Form'. 'nextLifeGeneration' }. { 'Form'. 'nextLifeGenerationBlueBook' }. { 'Form'. 'scaledToSize:' }. { 'Form'. 'topCenter' }. { 'Form'. 'topLeft' }. { 'Form'. 'topRight' }. { 'Form'. 'wrapAround:' }. { 'FormView'. 'defaultControllerClass' }. { 'FormView'. 'displayView' }. { 'HierarchyBrowser'. 'setClass:selector:' }. { 'InfiniteForm'. 'depth' }. { 'Inspector'. 'exploreSelection' }. { 'Inspector'. 'inspectorKey:from:' }. { 'Inspector'. 'timeOfLastListUpdate:' }. { 'LargePositiveInteger'. 'printOn:' }. { 'LinkedList'. 'hasContentsInExplorer' }. { 'ListView'. 'isEmpty:' }. { 'ListView'. 'textStyle' }. { 'ListView'. 'totalContentHeight' }. { 'Matrix'. 'postCopy' }. { 'Matrix'. 'preMultiplyByMatrix:' }. { 'Message'. 'arguments:' }. { 'Message'. 'sentTo:' }. { 'MethodContext'. 'asContext' }. { 'Number'. 'printShowingDecimalPlaces:' }. { 'Number'. 'zeno' }. { 'Object'. 'allInstanceVariableValues' }. { 'Object'. 'archiveVersion' }. { 'Object'. 'defaultBackgroundColor' }. { 'Object'. 'display' }. { 'Object'. 'explore' }. { 'Object'. 'hasContents' }. { 'Object'. 'isCharacter' }. { 'Object'. 'isObject' }. { 'Object'. 'print' }. { 'Object'. 'printStringUpTo:' }. { 'Object'. 'subobjects' }. { 'Object'. 'update:with:from:' }. { 'OpaqueForm'. 'colorForm' }. { 'OpaqueForm'. 'colorForm:' }. { 'OpaqueForm'. 'computeBoundingBox' }. { 'OpaqueForm'. 'displayOn:at:clippingBox:rule:fillColor:' }. { 'OpaqueForm'. 'displayOn:transformation:clippingBox:align:with:rule:fillColor:' }. { 'OpaqueForm'. 'setFigure:shape:' }. { 'OpaqueForm'. 'storeOn:' }. { 'OpaqueForm'. 'valueAt:put:' }. { 'PackageInfo'. 'removeFromSystem' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 22:47'! moreModificationsByTheRenaissanceTeam4 ^ { { 'Paragraph'. 'asForm' }. { 'ParagraphEditor'. 'cursorDown:' }. { 'ParagraphEditor'. 'debugIt' }. { 'ParagraphEditor'. 'exploreIt' }. { 'ParagraphEditor'. 'methodSourceContainingIt' }. { 'ParagraphEditor'. 'parseIt' }. { 'ParagraphEditor'. 'printIt' }. { 'ParagraphEditor'. 'sameColumn:newLine:forward:' }. { 'Pen'. 'mandala:diameter:' }. { 'PluggableListView'. 'getList' }. { 'PluggableListViewByObject'. 'changeModelSelection:' }. { 'PluggableListViewByObject'. 'getCurrentSelectionIndex' }. { 'PluggableListViewByObject'. 'objects' }. { 'PluggableListViewByObject'. 'scrollCache' }. { 'PluggableListViewByObject'. 'scrollCache:' }. { 'Point'. 'atRandom' }. { 'Point'. 'ceiling' }. { 'Point'. 'mandist:' }. { 'Point'. 'maxed' }. { 'Point'. 'moveBy:' }. { 'Point'. 'wrapAround:' }. { 'Point'. 'y:' }. { 'PopUpMenu'. 'startUpWithCaption:' }. { 'PopUpMenu'. 'startUpWithCaption:at:allowKeyboard:' }. { 'Project'. 'backgroundColorForMvcProject' }. { 'Project'. 'defaultBackgroundColor' }. { 'Project'. 'okToChange' }. { 'Project'. 'renameTo:' }. { 'RVMBootstrapPackage'. 'moreModificationsByTheRenaissanceTeam1' }. { 'RVMBootstrapPackage'. 'moreModificationsByTheRenaissanceTeam2' }. { 'RVMBootstrapPackage'. 'trickyModificationsManuallyCollected' }. { 'Rectangle'. 'corner:' }. { 'Rectangle'. 'display' }. { 'Rectangle'. 'extent:' }. { 'Rectangle'. 'fastMoveBy:' }. { 'Rectangle'. 'moveTo:' }. { 'Rectangle'. 'scaleByRect:' }. { 'Rectangle'. 'selfMerge:' }. { 'Rectangle'. 'size' }. { 'ScreenController'. 'recolorWindows' }. { 'SequenceableCollection'. 'is:after:' }. { 'SequenceableCollection'. 'shuffled' }. { 'SmalltalkImage'. 'saveAs:' }. { 'SmalltalkImage'. 'snapshot:andQuit:embedded:' }. { 'SmalltalkImage'. 'sourcesName' }. { 'StandardFileMenu'. 'oldFileFrom:withPattern:' }. { 'StandardSystemController'. 'close' }. { 'StandardSystemController'. 'closeAndUnscheduleIfOkWithModel' }. { 'StandardSystemController'. 'isClosed' }. { 'StandardSystemController'. 'preventClosing' }. { 'StandardSystemController'. 'redButtonActivity' }. { 'StandardSystemController'. 'togglePreventClosing' }. { 'StandardSystemView'. 'displayClosingGuardBoxIfNeeded' }. { 'StandardSystemView'. 'displayLabelBoxes' }. { 'StrikeFont'. 'ascent:' }. { 'StrikeFont'. 'derivativeFonts' }. { 'StrikeFont'. 'derivativeFonts:' }. { 'StrikeFont'. 'descent:' }. { 'StrikeFont'. 'glyphs:' }. { 'StrikeFont'. 'maxAscii:' }. { 'StrikeFont'. 'minAscii:' }. { 'StrikeFont'. 'raster' }. { 'StrikeFont'. 'strikeLength' }. { 'StrikeFont'. 'strikeLength:' }. { 'StrikeFont'. 'subscript' }. { 'StrikeFont'. 'superscript' }. { 'StrikeFont'. 'type:' }. { 'StrikeFont'. 'xOffset' }. { 'String'. 'asSmalltalkObject' }. { 'StringHolderView'. 'askBeforeDiscardingEdits' }. { 'StringHolderView'. 'changeTextStyle:' }. { 'StringHolderView'. 'defaultTextStyle' }. { 'StringHolderView'. 'editString:' }. { 'StringHolderView'. 'initialize' }. { 'StringHolderView'. 'textStyle' }. { 'Symbol'. 'asKeyword' }. { 'SystemDictionary'. 'majorShrinkClassesToZap' }. { 'SystemDictionary'. 'updateAllWindowColors' }. { 'Text'. 'emphasizeFrom:to:with:' }. { 'Text'. 'fontNumber:' }. { 'Text'. 'makeItalicFrom:to:' }. { 'Text'. 'underlined' }. { 'TextBlockDoIt'. 'actionBlock:' }. { 'TranscriptStream'. 'openLabel:' }. { 'VersionsBrowser'. 'scanVersionsOf:class:meta:category:selector:' }. { 'View'. 'addSubView:above:' }. { 'View'. 'addSubView:in:borderWidth:' }. { 'View'. 'addSubView:toLeftOf:' }. { 'View'. 'borderColor' }. { 'View'. 'demo' }. { 'View'. 'demoSized:' }. { 'View'. 'insetDisplayBox:' }. { 'View'. 'insideColor' }. { 'View'. 'moveBy:' }. { 'View'. 'moveDown' }. { 'View'. 'moveFrom:' }. { 'View'. 'moveUp' }. { 'View'. 'narrower' }. { 'View'. 'subViews:' }. { 'View'. 'subViewsSatisfying:' }. { 'View'. 'transformUsing:' }. { 'View'. 'viewport:' }. { 'View'. 'wider' }. { 'Workspace'. 'addModelItemsToWindowMenu:' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'StefanMarr 7/14/2011 17:13'! moreModificationsByTheRenaissanceTeam5 ^ { "Stefan: the next one is a fix for long Author names:" {'PositionableStream'. 'copyPreamble:from:'}. "Stefan: now other stuff, uncategorized" { 'ChangeList class'. 'browseRecords:' }. { 'ChangeList class'. 'browseRecords:titled:' }. { 'ChangeList class'. 'fileReaderServicesForFile:suffix:' }. { 'ChangeList class'. 'open:name:multiSelect:' }. { 'ChangeList class'. 'services' }. { 'ChangeSorter class'. 'fileIntoNewChangeSet:' }. { 'Color class'. 'colorChart' }. { 'Color class'. 'colorChart:' }. { 'Color class'. 'fromUser' }. { 'Controller class'. 'initialize' }. { 'Debugger class'. 'openNoForkSuspendOn:context:label:contents:fullView:selectingOtherIndex:' }. { 'Debugger class'. 'openNoSuspendOn:context:label:contents:fullView:' }. { 'Debugger class'. 'openOn:context:label:contents:fullView:' }. { 'Delay class'. 'startUp' }. { 'FileDirectory class'. 'startUp' }. { 'FileStream class'. 'concreteStream' }. { 'FileStream class'. 'fileIn:' }. { 'Form class'. 'dotOfSize:color:' }. { 'Form class'. 'fromBinaryStream:' }. { 'FormView class'. 'open:named:' }. { 'HierarchyBrowser class'. 'newFor:' }. { 'HierarchyBrowser class'. 'newFor:labeled:' }. { 'ImageReadWriter class'. 'understandsImageFormat:' }. { 'Inspector class'. 'newFrom:' }. { 'Inspector class'. 'openOn:withEvalPane:withLabel:valueViewClass:' }. { 'MessageSet class'. 'openMessageList:name:autoSelect:' }. { 'OpaqueForm class'. 'makeStar' }. { 'ParagraphEditor class'. 'initializeCmdKeyShortcuts' }. { 'PluggableFileList class'. 'oldFileMenu:withPattern:' }. { 'PluggableListView class'. 'on:list:selected:changeSelected:' }. { 'PluggableListView class'. 'on:list:selected:changeSelected:menu:' }. { 'PluggableListViewOfMany class'. 'on:list:primarySelection:changePrimarySelection:listSelection:changeListSelection:menu:' }. { 'PluggableListViewOfMany class'. 'on:list:primarySelection:changePrimarySelection:listSelection:changeListSelection:menu:keystroke:' }. { 'PluggableTextView class'. 'on:text:accept:' }. { 'ProcessBrowser class'. 'isUIProcess:' }. { 'Project class'. 'addItem:toMenu:selection:project:' }. { 'RealEstateAgent class'. 'assignCollapsePointFor:' }. { 'RealEstateAgent class'. 'maximumUsableArea' }. { 'RealEstateAgent class'. 'screenTopSetback' }. { 'RealEstateAgent class'. 'scrollBarSetback' }. { 'RunArray class'. 'scanFrom:' }. { 'SelectionMenu class'. 'labels:lines:selectors:' }. { 'StandardFileMenu class'. 'oldFileFrom:withPattern:' }. { 'StandardFileMenu class'. 'oldFileMenu:withPattern:' }. { 'StandardFileMenu class'. 'oldFileStreamFrom:withPattern:' }. { 'StandardFileMenu class'. 'oldFileStreamWithPattern:' }. { 'StandardFileMenu class'. 'oldFileWithPattern:' }. { 'StandardSystemView class'. 'model:label:minimumSize:' }. { 'Symbol class'. 'readFrom:' }. { 'TextStyle class'. 'mvcPromptForFont:' }. { 'TextStyle class'. 'mvcPromptForStyle:andSendTo:withSelector:' }. { 'Transcripter class'. 'emergencyEvaluator' }. { 'Utilities class'. 'exploreViewFromUser' }. { 'Utilities class'. 'informUserDuring:' }. { 'Utilities class'. 'pointersTo:except:' }. { 'RVMBootstrapPackage'. 'moreModificationsByTheRenaissanceTeam3' }. { 'RVMBootstrapPackage'. 'moreModificationsByTheRenaissanceTeam4' }. { 'RVMBootstrapPackage'. 'moreModificationsByTheRenaissanceTeam5' }. { 'OpaqueForm class'. 'figure:shape:' }. { 'OpaqueForm class'. 'shape:' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'ads 2/4/2011 12:24'! revertToVersionBeforeTeam: team "DO NOT RUN THIS METHOD ON MULTIPLE CORES!!!!!!!!!! Only on one core." "Also, notice that the stuff in this method is ALMOST exactly the same as the stuff in trickyModificationsThatNeedToBeDoneInOrder (but in reverse order, since we're removing). In the long run, we should be able to eliminate the duplication. But the current RVM image contains some weird stuff, like methods that existed in Squeak 3.7 and were changed by the Renaissance team but somehow the image doesn't contain a copy of the old version of the method. So for now, we have this big ugly method. -- Adam, Dec. 2010" team revertToOldVersionOrRemove: (ProcessorScheduler class methodNamed: #emergencyProcess). team revertToOldVersionOrRemove: (ProcessorScheduler class methodNamed: #startEmergencyProcess). team revertToOldVersionOrRemove: (ProcessorScheduler class methodNamed: #startUp). team revertToOldVersionOrRemove: (ProcessBrowser class methodNamed: #nameAndRulesFor:). team aboutToModifyClass: ProcessorScheduler. Object subclass: #ProcessorScheduler instanceVariableNames: 'quiescentProcessLists activeProcess' classVariableNames: 'BackgroundProcess HighIOPriority LowIOPriority SystemBackgroundPriority SystemRockBottomPriority TimingPriority UserBackgroundPriority UserInterruptPriority UserSchedulingPriority' poolDictionaries: '' category: 'Kernel-Processes'. team revertToOldVersionOrRemove: (Debugger methodNamed: #fullyExpandStack). team revertToOldVersionOrRemove: (Process methodNamed: #debug:title:full:). team revertToOldVersionOrRemove: (Process methodNamed: #resume). team revertToOldVersionOrRemove: (Process methodNamed: #suspend). team revertToOldVersionOrRemove: (Process methodNamed: #terminate). team revertToOldVersionOrRemove: (Process class methodNamed: #semaForSupensions). team revertToOldVersionOrRemove: (Process methodNamed: #children). team revertToOldVersionOrRemove: (Process methodNamed: #children:). team revertToOldVersionOrRemove: (Process methodNamed: #parent). team revertToOldVersionOrRemove: (Process methodNamed: #parent:). team revertToOldVersionOrRemove: (Process methodNamed: #creatorEnsemble). team revertToOldVersionOrRemove: (Process methodNamed: #creatorEnsemble:). team aboutToModifyClass: Process. Link subclass: #Process instanceVariableNames: 'suspendedContext priority myList errorHandler name' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Processes'. team revertToOldVersionOrRemove: (TranscriptStream class methodNamed: #showInConsole). team revertToOldVersionOrRemove: (TranscriptStream class methodNamed: #showInConsole:). team aboutToModifyClass: TranscriptStream. WriteStream subclass: #TranscriptStream instanceVariableNames: '' classVariableNames: 'AccessSema' poolDictionaries: '' category: 'Collections-Streams'. "Safe." team aboutToModifyClass: Collection. Object subclass: #Collection instanceVariableNames: '' classVariableNames: 'MutexForPicking RandomForPicking' poolDictionaries: '' category: 'Collections-Abstract'. "Safe. I don't even understand why they bothered or why the Squeak image had this variable." team aboutToModifyClass: AnimatedGIFReadWriter. GIFReadWriter subclass: #AnimatedGIFReadWriter instanceVariableNames: 'forms offsets delays comments' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Files'. "Safe. The methods that use the new cursors are already gone." team revertToOldVersionOrRemove: (Cursor class methodNamed: #initialize). team aboutToModifyClass: Cursor. Form subclass: #Cursor instanceVariableNames: '' classVariableNames: 'BlankCursor BottomLeftCursor BottomRightCursor CornerCursor CrossHairCursor CurrentCursor DownCursor MarkerCursor MenuCursor MoveCursor NormalCursor OriginCursor ReadCursor ResizeLeftCursor ResizeTopCursor ResizeTopLeftCursor ResizeTopRightCursor RightArrowCursor SquareCursor TopLeftCursor TopRightCursor UpCursor WaitCursor WebLinkCursor WriteCursor XeqCursor' poolDictionaries: '' category: 'Graphics-Display Objects'. "Safe. Only called by code that's part of the RVM packages." team aboutToModifyClass: DisplayScreen. Form subclass: #DisplayScreen instanceVariableNames: 'clippingBox extraRegions' classVariableNames: 'DeferringUpdates DisplayChangeSignature ScreenSave' poolDictionaries: '' category: 'Graphics-Display Objects'. team revertToOldVersionOrRemove: (Controller methodNamed: #controlLoop). team revertToOldVersionOrRemove: (Controller methodNamed: #killCounter). team revertToOldVersionOrRemove: (Controller methodNamed: #killCounter:). team revertToOldVersionOrRemove: (Controller methodNamed: #lastProcessRunningMe). team revertToOldVersionOrRemove: (Controller methodNamed: #lastProcessRunningMe:). team aboutToModifyClass: Controller. Object subclass: #Controller instanceVariableNames: 'model view sensor lastActivityTime' classVariableNames: 'MinActivityLapse' poolDictionaries: '' category: 'Kernel-ST80 Remnants'. team revertToOldVersionOrRemove: (Paragraph methodNamed: #displayOn:lines:). team revertToOldVersionOrRemove: (Paragraph methodNamed: #compositionRectangle:text:style:offset:). team revertToOldVersionOrRemove: (Paragraph methodNamed: #destFormSema:). team aboutToModifyClass: Paragraph. DisplayText subclass: #Paragraph instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine' classVariableNames: '' poolDictionaries: 'TextConstants' category: 'ST80-Support'. team revertToOldVersionOrRemove: (ControlManager methodNamed: #restore). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #deEmphasizeLabel). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #emphasizeLabel). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #displayEmphasized). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #displayDeEmphasized). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #critical:). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #resetDisplayInterlock). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #displayInterlock). team revertToOldVersionOrRemove: (StandardSystemView methodNamed: #displayInterlock:). team aboutToModifyClass: StandardSystemView. View subclass: #StandardSystemView instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid updatablePanes' classVariableNames: 'CacheBits LabelStyle' poolDictionaries: '' category: 'ST80-Support'. "Requires the removal of displayInterlock from StandardSystemView, see above." team aboutToModifyClass: Mutex. Mutex removeFromSystem. SystemOrganization removeCategoryIfEmpty: 'RVMBootstrap'. team revertToOldVersionOrRemove: (ChangeList class methodNamed: #getRecentLocatorWithPrompt:). team revertToOldVersionOrRemove: (ClassDescription methodNamed: #classComment:stamp:). team revertToOldVersionOrRemove: (ClassDescription methodNamed: #printMethodChunk:withPreamble:on:moveSource:toFile:). team revertToOldVersionOrRemove: (CompiledMethod methodNamed: #putSource:fromParseNode:inFile:withPreamble:). team revertToOldVersionOrRemove: (RemoteString methodNamed: #string:onFileNumber:). team revertToOldVersionOrRemove: (RemoteString methodNamed: #text). team revertToOldVersionOrRemove: (SmalltalkImage methodNamed: #assureStartupStampLogged). team revertToOldVersionOrRemove: (SmalltalkImage methodNamed: #logChange:). team revertToOldVersionOrRemove: (SystemDictionary methodNamed: #snapshot:andQuit:embedded:). team revertToOldVersionOrRemove: (SystemDictionary methodNamed: #writeRecentCharacters:toFileNamed:). team revertToOldVersionOrRemove: (StandardSourceFileArray class methodNamed: #install). team revertToOldVersionOrRemove: (StandardFileStream class methodNamed: #resetAllInterlocks). team revertToOldVersionOrRemove: (StandardFileStream methodNamed: #resetInterlock). team revertToOldVersionOrRemove: (StandardFileStream methodNamed: #safelyDo:). team revertToOldVersionOrRemove: (StandardFileStream methodNamed: #interlock). team revertToOldVersionOrRemove: (StandardFileStream methodNamed: #interlock:). team aboutToModifyClass: StandardFileStream. FileStream subclass: #StandardFileStream instanceVariableNames: 'name fileID buffer1' classVariableNames: 'Registry' poolDictionaries: '' category: 'System-Files'. "Safe. There are no users of the VersionString class variable." team aboutToModifyClass: SystemDictionary. IdentityDictionary subclass: #SystemDictionary instanceVariableNames: 'cachedClassNames' classVariableNames: 'LastImageName LastQuitLogPosition LowSpaceProcess LowSpaceSemaphore MemoryHogs ShutDownList SpecialSelectors StartUpList StartupStamp' poolDictionaries: '' category: 'System-Support'. "Safe. The methods using this are all in the RVM category." team aboutToModifyClass: PopUpMenu. Object subclass: #PopUpMenu instanceVariableNames: 'labelString font lineArray frame form marker selection' classVariableNames: 'CacheMenuForms MenuStyle' poolDictionaries: '' category: 'Tools-Menus'. "team revertToOldVersionOrRemove: (Debugger methodNamed: #installListFontInto:)." team revertToOldVersionOrRemove: (Process methodNamed: #nilMyListUnlessRVM). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #areRunningProcessesInSchedulerLists). team revertToOldVersionOrRemove: (ProcessBrowser methodNamed: #updateStackList:). team revertToOldVersionOrRemove: (Process methodNamed: #popTo:). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #isActive:). team revertToOldVersionOrRemove: (BlockContext methodNamed: #valueUnpreemptively). team revertToOldVersionOrRemove: (CPUWatcher methodNamed: #debugProcess:). team revertToOldVersionOrRemove: (ControlManager methodNamed: #inActiveControllerProcess). team revertToOldVersionOrRemove: (ControlManager methodNamed: #interruptName:). team revertToOldVersionOrRemove: (ControlManager methodNamed: #resetActiveController). team revertToOldVersionOrRemove: (ControlManager methodNamed: #scheduleActiveNoTerminate:). team revertToOldVersionOrRemove: (ControlManager methodNamed: #searchForActiveController). team revertToOldVersionOrRemove: (Debugger methodNamed: #debug). team revertToOldVersionOrRemove: (Debugger class methodNamed: #context:isolationHead:). team revertToOldVersionOrRemove: (Debugger class methodNamed: #openContext:label:contents:). team revertToOldVersionOrRemove: (Process methodNamed: #debugWithTitle:). team revertToOldVersionOrRemove: (Process methodNamed: #pvtSignal:list:). team revertToOldVersionOrRemove: (Process methodNamed: #signal:). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #activePriority). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #terminateActive). team revertToOldVersionOrRemove: (Project methodNamed: #enterForEmergencyRecovery). team revertToOldVersionOrRemove: (Project class methodNamed: #spawnNewProcessAndTerminateOld:). team revertToOldVersionOrRemove: (SyntaxError class methodNamed: #open:). team revertToOldVersionOrRemove: (SystemDictionary methodNamed: #handleUserInterrupt). team revertToOldVersionOrRemove: (UnhandledError methodNamed: #devDefaultAction). "aaa - There's no old version for spyEvery:on: in the current image. Blecch." team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #thisProcess). team revertToOldVersionOrRemove: (Process methodNamed: #isRunning). team revertToOldVersionOrRemove: (Process methodNamed: #synchronousSuspend). team revertToOldVersionOrRemove: (Debugger class methodNamed: #openInterrupt:onProcess:). team revertToOldVersionOrRemove: (MessageTally methodNamed: #spyEvery:onProcess:forMilliseconds:). team revertToOldVersionOrRemove: (ParagraphEditor methodNamed: #debug:receiver:in:). team revertToOldVersionOrRemove: (Process methodNamed: #suspendedContextWaitingIfNecessary). team revertToOldVersionOrRemove: (ContextPart methodNamed: #contextStackIn:). team revertToOldVersionOrRemove: (ContextPart methodNamed: #stackOfSize:in:). team revertToOldVersionOrRemove: (ContextPart methodNamed: #senderOrSlyInvokerAndProcessIn:). team revertToOldVersionOrRemove: (ContextPart methodNamed: #senderOrSlyInvokerIn:). team revertToOldVersionOrRemove: (Object methodNamed: #primitiveGetExtraPreheaderWord:). team revertToOldVersionOrRemove: (Object methodNamed: #primitiveSetExtraPreheaderWord:). team revertToOldVersionOrRemove: (Object methodNamed: #primitiveSetExtraWordSelector:). team revertToOldVersionOrRemove: (Process methodNamed: #beSlyMemberProcess). team revertToOldVersionOrRemove: (Process methodNamed: #addChild:). team revertToOldVersionOrRemove: (Process methodNamed: #myGenerationAndTheirDescendantsDo:). team revertToOldVersionOrRemove: (Process methodNamed: #siblingsAndTheirDescendantsDo:). team revertToOldVersionOrRemove: (Process methodNamed: #descendantsDo:). team revertToOldVersionOrRemove: (Process methodNamed: #myGeneration). team revertToOldVersionOrRemove: (Process methodNamed: #siblings). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #debugMemberProcesses). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #suspendMemberProcesses). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #terminateMemberProcesses). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #memberProcesses). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #userBackgroundPriority). team revertToOldVersionOrRemove: (TranscriptStream methodNamed: #toggleShowInConsole). team revertToOldVersionOrRemove: (TranscriptStream class methodNamed: #toggleShowInConsole). team revertToOldVersionOrRemove: (TranscriptStream methodNamed: #showInConsoleSwitch). team revertToOldVersionOrRemove: (TranscriptStream methodNamed: #showInConsole). team revertToOldVersionOrRemove: (TranscriptStream methodNamed: #showInConsole:). team revertToOldVersionOrRemove: (Object methodNamed: #longPrintOn:). team revertToOldVersionOrRemove: (Behavior methodNamed: #longPrintOn:). team revertToOldVersionOrRemove: (Process methodNamed: #longPrintOn:). team revertToOldVersionOrRemove: (MethodContext methodNamed: #printOn:). team revertToOldVersionOrRemove: (Inspector methodNamed: #selectionPrintString). team revertToOldVersionOrRemove: (Controller methodNamed: #interActivityPause). team revertToOldVersionOrRemove: (ContextPart methodNamed: #tempsAndValues). team revertToOldVersionOrRemove: (CompiledMethod methodNamed: #longPrintOn:indent:). team revertToOldVersionOrRemove: (BlockContext methodNamed: #printOn:). team revertToOldVersionOrRemove: (BitBlt methodNamed: #copyBits). team revertToOldVersionOrRemove: (BitBlt methodNamed: #drawFrom:to:withFirstPoint:). team revertToOldVersionOrRemove: (BitBlt methodNamed: #drawLoopX:Y:). team aboutToModifyClass: RVMPrimitivesNeededForBootstrapping. RVMPrimitivesNeededForBootstrapping removeFromSystem. SystemOrganization removeCategoryIfEmpty: 'RVMBootstrap'. team aboutToModifyClass: RVMObject. RVMObject removeFromSystem. SystemOrganization removeCategoryIfEmpty: 'RVMBootstrap'. team aboutToModifyClass: RenaissanceTransporter. RenaissanceTransporter removeFromSystem. SystemOrganization removeCategoryIfEmpty: 'RVMBootstrap'. team aboutToModifyClass: RVMBootstrapPackage. RVMBootstrapPackage removeFromSystem. SystemOrganization removeCategoryIfEmpty: 'RVMBootstrap'. team revertToOldVersionOrRemove: (Process methodNamed: #errorHandler). team revertToOldVersionOrRemove: (Process methodNamed: #errorHandler:). team revertToOldVersionOrRemove: (Process methodNamed: #myList). team revertToOldVersionOrRemove: (Process methodNamed: #myList:). team revertToOldVersionOrRemove: (Process methodNamed: #activateReturn:value:). team revertToOldVersionOrRemove: (Process methodNamed: #complete:). team revertToOldVersionOrRemove: (Process methodNamed: #isActiveProcess). team revertToOldVersionOrRemove: (Process methodNamed: #primitiveSuspend). team revertToOldVersionOrRemove: (Process methodNamed: #return:value:). team revertToOldVersionOrRemove: (Process methodNamed: #step). team revertToOldVersionOrRemove: (Process methodNamed: #stepToCallee). team revertToOldVersionOrRemove: (Process methodNamed: #stepToSendOrReturn). team revertToOldVersionOrRemove: (BlockContext methodNamed: #forkWith:). team revertToOldVersionOrRemove: (BlockContext methodNamed: #newProcessWith:). team revertToOldVersionOrRemove: (Process class methodNamed: #forContext:priority:). team revertToOldVersionOrRemove: (Transcripter methodNamed: #readEvalPrint). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #removeAllPossible). team revertToOldVersionOrRemove: (ProcessorScheduler methodNamed: #terminatableProcesses). team revertToOldVersionOrRemove: (BitBlt methodNamed: #OLDcopyBits). team revertToOldVersionOrRemove: (BitBlt methodNamed: #copyBitsLocally). team revertToOldVersionOrRemove: (BitBlt methodNamed: #copyBitsOnMain). team revertToOldVersionOrRemove: (BitBlt methodNamed: #drawLoopLocallyX:Y:). team revertToOldVersionOrRemove: (BitBlt methodNamed: #globalDrawLoopX:Y:). team revertToOldVersionOrRemove: (BitBlt methodNamed: #localDrawLoopX:Y:). ! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 5/25/2011 20:10'! trickyModificationsManuallyCollected ^ { { 'SystemDictionary'. 'logError:inContext:onConsoleAndQuitWithSaving:' }. { 'BitBlt'. 'localDrawLoopX:Y:' }. { 'BitBlt'. 'globalDrawLoopX:Y:' }. { 'BitBlt'. 'drawLoopLocallyX:Y:' }. { 'BitBlt'. 'copyBitsOnMain' }. { 'BitBlt'. 'copyBitsLocally' }. { 'BitBlt'. 'OLDcopyBits' }. { 'BitBlt class'. 'exampleColorMap' }. "Changes to Name Processes" "TODO: STEFAN find a better way to manage these changes, don't want to change method category" { 'WeakArray class'. 'restartFinalizationProcess' }. { 'SystemDictionary'. 'installLowSpaceWatcher' }. { 'InputSensor'. 'installInterruptWatcher' }. { 'EventSensor'. 'installEventTickler' }. { 'Delay class'. 'startTimerInterruptWatcher' }. { 'CPUWatcher class'. 'startMonitoringPeriod:rate:threshold:' }. "{ 'Controller'. 'controlLoop' }." "Was included already later" "STEFAN: other base system changes where I do not know how to handle it better." { 'Integer'. 'atRandom' }. { 'Integer'. 'hasContentsInExplorer' }. { 'Integer'. 'printeth' }. { 'Array'. 'asRunArray' }. { 'Array'. 'isArray' }. { 'Association'. 'outlineString' }. { 'ProcessorScheduler'. 'terminatableProcesses' }. { 'ProcessorScheduler'. 'removeAllPossible' }. { 'Transcripter'. 'readEvalPrint' }. { 'Process class'. 'forContext:priority:' }. { 'BlockContext'. 'newProcessWith:' }. { 'BlockContext'. 'forkWith:' }. { 'Process'. 'stepToSendOrReturn' }. { 'Process'. 'stepToCallee' }. { 'Process'. 'step' }. { 'Process'. 'return:value:' }. { 'Process'. 'primitiveSuspend' }. { 'Process'. 'isActiveProcess' }. { 'Process'. 'complete:' }. { 'Process'. 'activateReturn:value:' }. { 'Process'. 'myList:' }. { 'Process'. 'myList' }. { 'Process'. 'errorHandler:' }. { 'Process'. 'errorHandler' }. { 'RVMObject' }. { 'RVMPrimitivesNeededForBootstrapping' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'getCoreHolding:' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'getEmergencySemaphore' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'getReadWriteOf:' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'isRVM' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'primitivGetCoreHolding:' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'printPrefixFor:' }. { 'RVMPrimitivesNeededForBootstrapping class'. 'setEmergencySemaphore:' }. { 'BitBlt'. 'drawLoopX:Y:' }. { 'BitBlt'. 'drawFrom:to:withFirstPoint:' }. { 'BitBlt'. 'copyBits' }. { 'BlockContext'. 'printOn:' }. { 'CompiledMethod'. 'longPrintOn:indent:' }. { 'ContextPart'. 'tempsAndValues' }. { 'Controller'. 'interActivityPause' }. { 'Inspector'. 'selectionPrintString' }. { 'MethodContext'. 'printOn:' }. { 'Process'. 'longPrintOn:' }. { 'Behavior'. 'longPrintOn:' }. { 'Object'. 'longPrintOn:' }. { 'TranscriptStream'. 'showInConsole:' }. { 'TranscriptStream'. 'showInConsole' }. { 'TranscriptStream'. 'showInConsoleSwitch' }. { 'TranscriptStream class'. 'toggleShowInConsole' }. { 'TranscriptStream'. 'toggleShowInConsole' }. { 'ProcessorScheduler'. 'userBackgroundPriority' }. { 'ProcessorScheduler'. 'memberProcesses' }. { 'ProcessorScheduler'. 'terminateMemberProcesses' }. { 'ProcessorScheduler'. 'suspendMemberProcesses' }. { 'ProcessorScheduler'. 'debugMemberProcesses' }. { 'Process'. 'siblings' }. { 'Process'. 'myGeneration' }. { 'Process'. 'descendantsDo:' }. { 'Process'. 'siblingsAndTheirDescendantsDo:' }. { 'Process'. 'myGenerationAndTheirDescendantsDo:' }. { 'Process'. 'addChild:' }. { 'Process'. 'beSlyMemberProcess' }. { 'Object'. 'primitiveSetExtraWordSelector:' }. { 'Object'. 'primitiveSetExtraPreheaderWord:' }. { 'Object'. 'primitiveGetExtraPreheaderWord:' }. { 'ContextPart'. 'senderOrSlyInvokerIn:' }. { 'ContextPart'. 'senderOrSlyInvokerAndProcessIn:' }. { 'ContextPart'. 'stackOfSize:in:' }. { 'ContextPart'. 'contextStackIn:' }. { 'Process'. 'suspendedContextWaitingIfNecessary' }. { 'ParagraphEditor'. 'debug:receiver:in:' }. { 'MessageTally'. 'spyEvery:onProcess:forMilliseconds:' }. { 'Debugger class'. 'openInterrupt:onProcess:' }. { 'Process'. 'synchronousSuspend' }. { 'Process'. 'isRunning' }. { 'ProcessorScheduler'. 'thisProcess' }. { 'MessageTally'. 'spyEvery:on:' }. { 'UnhandledError'. 'devDefaultAction' }. { 'SystemDictionary'. 'handleUserInterrupt' }. { 'SyntaxError class'. 'open:' }. { 'Project class'. 'spawnNewProcessAndTerminateOld:' }. { 'Project'. 'enterForEmergencyRecovery' }. { 'ProcessorScheduler'. 'terminateActive' }. { 'ProcessorScheduler'. 'activePriority' }. { 'Process'. 'signal:' }. { 'Process'. 'pvtSignal:list:' }. { 'Process'. 'debugWithTitle:' }. { 'Debugger class'. 'openContext:label:contents:' }. { 'Debugger class'. 'context:isolationHead:' }. { 'Debugger'. 'debug' }. { 'ControlManager'. 'searchForActiveController' }. { 'ControlManager'. 'scheduleActiveNoTerminate:' }. { 'ControlManager'. 'resetActiveController' }. { 'ControlManager'. 'interruptName:' }. { 'ControlManager'. 'inActiveControllerProcess' }. { 'CPUWatcher'. 'debugProcess:' }. { 'BlockContext'. 'valueUnpreemptively' }. { 'ProcessorScheduler'. 'isActive:' }. { 'Process'. 'popTo:' }. { 'ProcessBrowser'. 'updateStackList:' }. { 'ProcessorScheduler'. 'areRunningProcessesInSchedulerLists' }. { 'Process'. 'nilMyListUnlessRVM' }. "{ 'Debugger'. 'installListFontInto:' }." { 'PopUpMenu' }. { 'SystemDictionary' }. { 'StandardFileStream' }. { 'StandardFileStream'. 'interlock:' }. { 'StandardFileStream'. 'interlock' }. { 'StandardFileStream'. 'safelyDo:' }. { 'StandardFileStream'. 'resetInterlock' }. { 'StandardFileStream class'. 'resetAllInterlocks' }. { 'StandardSourceFileArray class'. 'install' }. { 'SystemDictionary'. 'writeRecentCharacters:toFileNamed:' }. { 'SystemDictionary'. 'snapshot:andQuit:embedded:' }. { 'SmalltalkImage'. 'logChange:' }. { 'SmalltalkImage'. 'assureStartupStampLogged' }. { 'RemoteString'. 'text' }. { 'RemoteString'. 'string:onFileNumber:' }. { 'CompiledMethod'. 'putSource:fromParseNode:inFile:withPreamble:' }. { 'ClassDescription'. 'printMethodChunk:withPreamble:on:moveSource:toFile:' }. { 'ClassDescription'. 'classComment:stamp:' }. { 'ChangeList class'. 'getRecentLocatorWithPrompt:' }. { 'Mutex' }. { 'Mutex'. 'critical:' }. { 'Mutex'. 'initialize' }. { 'Mutex class'. 'forMutualExclusion' }. { 'StandardSystemView' }. { 'StandardSystemView'. 'displayInterlock:' }. { 'StandardSystemView'. 'displayInterlock' }. { 'StandardSystemView'. 'resetDisplayInterlock' }. { 'StandardSystemView'. 'critical:' }. { 'StandardSystemView'. 'displayDeEmphasized' }. { 'StandardSystemView'. 'displayEmphasized' }. { 'StandardSystemView'. 'emphasizeLabel' }. { 'StandardSystemView'. 'deEmphasizeLabel' }. { 'ControlManager'. 'restore' }. { 'Paragraph' }. { 'Paragraph'. 'destFormSema:' }. { 'Paragraph'. 'compositionRectangle:text:style:offset:' }. { 'Paragraph'. 'displayOn:lines:' }. { 'Controller' }. { 'Controller'. 'lastProcessRunningMe:' }. { 'Controller'. 'lastProcessRunningMe' }. { 'Controller'. 'killCounter:' }. { 'Controller'. 'killCounter' }. { 'Controller'. 'controlLoop' }. { 'DisplayScreen' }. { 'Cursor' }. { 'Cursor class'. 'initialize' }. { 'AnimatedGIFReadWriter' }. { 'Collection' }. { 'TranscriptStream' }. { 'TranscriptStream class'. 'showInConsole:' }. { 'TranscriptStream class'. 'showInConsole' }. { 'Process' }. { 'Process'. 'creatorEnsemble:' }. { 'Process'. 'creatorEnsemble' }. { 'Process'. 'parent:' }. { 'Process'. 'parent' }. { 'Process'. 'children:' }. { 'Process'. 'children' }. { 'Process class'. 'semaForSupensions' }. { 'Process'. 'terminate' }. { 'Process'. 'suspend' }. { 'Process'. 'resume' }. { 'Process'. 'debug:title:full:' }. { 'Debugger'. 'fullyExpandStack' }. { 'ProcessorScheduler' }. { 'ProcessBrowser class'. 'nameAndRulesFor:' }. { 'ProcessorScheduler class'. 'startUp' }. { 'ProcessorScheduler class'. 'startEmergencyProcess' }. { 'ProcessorScheduler class'. 'emergencyProcess' }. { 'RVMBootstrapPackage' }. { 'RVMBootstrapPackage'. 'trickyModificationsThatNeedToBeDoneInOrder' }. { 'RVMBootstrapPackage'. 'revertToVersionBeforeTeam:' }. { 'RenaissanceTransporter' }. { 'RenaissanceTransporter'. 'initialize' }. { 'RenaissanceTransporter'. 'initializePackage' }. { 'RenaissanceTransporter'. 'initializePreambleAndPostscript' }. { 'RenaissanceTransporter'. 'initializeTeam' }. { 'RenaissanceTransporter'. 'revert' }. { 'RenaissanceTransporter class'. 'transportersForFileOutMenu' }. }! ! !RVMBootstrapPackage methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 22:09'! trickyModificationsThatNeedToBeDoneInOrder | trickyStuff | trickyStuff := OrderedCollection new. trickyStuff addAll: self trickyModificationsManuallyCollected. trickyStuff addAll: self moreModificationsByTheRenaissanceTeam1. trickyStuff addAll: self moreModificationsByTheRenaissanceTeam2. trickyStuff addAll: self moreModificationsByTheRenaissanceTeam3. trickyStuff addAll: self moreModificationsByTheRenaissanceTeam4. trickyStuff addAll: self moreModificationsByTheRenaissanceTeam5. ^ trickyStuff.! ! !RVMButtonController methodsFor: 'basic control sequence' stamp: 'ssa 1/1/1970 01:12'! redButtonActivity | aborted lastAborted | self view displayPressed. lastAborted _ false. aborted _ true. [Sensor redButtonPressed] whileTrue:[ aborted _ (self view insetDisplayBox containsPoint: Sensor cursorPoint) not. aborted & lastAborted not ifTrue:[self view displayView. lastAborted _ true]. aborted not & lastAborted ifTrue:[self view displayPressed. lastAborted _ false]]. self view displayView. aborted ifFalse:[self view performAction]! ! !RVMButtonController methodsFor: 'controlling' stamp: 'ssa 10/3/2008 20:53'! controlInitialize self view style ~~ #raisedGray ifTrue:[Cursor action show]. super controlInitialize! ! !RVMButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:04'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:19'! displayAction "Let the controller indicate action available" self displayLabel. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 16:03'! displayLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: Color white. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 03:09'! displayLabelDark | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: self baseColorDark. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form erase fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:22'! displayOutline self displayLabel. Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: Color black.! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 03:02'! displayPressed self displayLabelDark. Display border: (self insetDisplayBox insetBy: 0@0) width:2 fillColor: self baseColor. Display border: (self insetDisplayBox insetBy: 2@2) width:2 fillColor: self baseColor darker. Display border: (self insetDisplayBox insetBy: 4@4) width:2 fillColor: self baseColor darker darker. Display border: (self insetDisplayBox insetBy: 6@6) width:2 fillColor: self baseColor darker darker darker. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 3/24/2010 17:07'! displayRaisedGray self displayRaisedWhiteLabel. self displayRaisedLabel. Display border: (self insetDisplayBox insetBy: 0@0) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor. Display border: (self insetDisplayBox insetBy: 0@0) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker darker. Display border: (self insetDisplayBox insetBy: 1@1) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (self insetDisplayBox insetBy: 1@1) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker darker. Display border: (self insetDisplayBox insetBy: 2@2) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter lighter. Display border: (self insetDisplayBox insetBy: 2@2) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor darker. Display border: (self insetDisplayBox insetBy: 3@3) widthRectangle: (1@1 corner: 0@0) rule: Form paint fillColor: self baseColor lighter. Display border: (self insetDisplayBox insetBy: 3@3) widthRectangle: (0@0 corner: 1@1) rule: Form paint fillColor: self baseColor . ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 2/22/2010 15:34'! displayRaisedLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. "Display fill: self insetDisplayBox fillColor: self baseColor." labelForm displayOn: Display at: labelRect center - labelForm boundingBox center - (0@3)clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 2/22/2010 15:37'! displayRaisedWhiteLabel | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: self baseColor lighter lighter backgroundColor: Color transparent. labelForm := labelText asParagraph asForm. labelForm width > self insetDisplayBox width ifTrue:[labelForm _ labelForm scaledToSize:self insetDisplayBox width@labelForm height]. labelForm height > self insetDisplayBox height ifTrue:[labelForm _ labelForm scaledToSize: labelForm width@self insetDisplayBox height]. labelRect := self insetDisplayBox. Display fill: self insetDisplayBox fillColor: self baseColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center - (0@3)+(1@1)clippingBox: labelRect rule: Form paint fillColor: nil. ! ! !RVMButtonView methodsFor: 'displaying' stamp: 'ssa 9/19/2008 12:15'! displayView self style == #raisedGray ifTrue:[self displayRaisedGray]. self style == #outline ifTrue:[self displayOutline]. self style == #action ifTrue:[self displayAction]. ! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! action "Answer the value of action, a block to execute when the button is released" action isNil ifTrue:[self action: [self inform:'no action defined yet']]. ^ action! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! action: anObject "Set the value of action" action _ anObject! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 02:47'! baseColor ^Color gray lighter lighter lighter! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:02'! baseColorDark ^Color gray ! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:42'! label "Answer the value of label" label isNil ifTrue:[self label: 'not labeled yet']. ^ label! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! label: anObject "Set the value of label" label _ anObject! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:14'! style "Answer the value of style. how I should display myself. Current options are #raisedGray, #outline, #action" style isNil ifTrue:[self style: #raisedGray]. ^ style! ! !RVMButtonView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 12:13'! style: anObject "Set the value of style" style _ anObject! ! !RVMButtonView methodsFor: 'actions' stamp: 'ssa 1/1/1970 00:10'! performAction self action copy value! ! !RVMButtonView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:25'! defaultControllerClass ^RVMButtonController! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:27'! example "RVMButtonView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'Flash' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 02:59'! exampleGC "RVMButtonView exampleGC" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'GC' action:[Smalltalk garbageCollect print]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:43'! exampleLong "RVMButtonView exampleLong" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:'Flash the display by reversing twice' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 01:43'! exampleTall "RVMButtonView exampleTall" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@25. topView maximumSize: 200@200. topView addSubView: (self label:' Flash the display by reversing twice' action:[Display reverse reverse]). topView label: 'RVMButtonView test'. topView controller open! ! !RVMButtonView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! label: aString action: aBlock | v | v _ self new. v label: aString. v action: aBlock. ^v ! ! !RVMButtonView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:21'! label: aString style: aSymbol action: aBlock | v | v _ self new. v label: aString. v style: aSymbol. v action: aBlock. ^v ! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! cyclesSinceLastQuery "Answer the value of cyclesSinceLastQuery" cyclesSinceLastQuery isNil ifTrue:[self cyclesSinceLastQuery: 0]. ^cyclesSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! cyclesSinceLastQuery: anObject "Set the value of cyclesSinceLastQuery" cyclesSinceLastQuery := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'dmu 1/5/2011 12:48'! gcMilliseconds ^ self memorySystemStats gcMilliseconds! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:22'! memorySystemStats "Answer the value of memorySystemStats" memorySystemStats isNil ifTrue:[self memorySystemStats: RVMMemorySystemStats new]. ^memorySystemStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! memorySystemStats: anObject "Set the value of memorySystemStats" memorySystemStats := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! messageNames "Answer the value of messageNames" messageNames isNil ifTrue:[self messageNames: nil]. ^messageNames! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! messageNames: anObject "Set the value of messageNames" messageNames := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:08'! millisecondsSinceLastQuery "Answer the value of millisecondsSinceLastQuery" millisecondsSinceLastQuery isNil ifTrue:[self millisecondsSinceLastQuery: 0]. ^millisecondsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! millisecondsSinceLastQuery: anObject "Set the value of millisecondsSinceLastQuery" millisecondsSinceLastQuery := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myRank "Answer the value of myRank" myRank isNil ifTrue:[self myRank: nil]. ^myRank! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myRank: anObject "Set the value of myRank" myRank := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myX "Answer the value of myX" myX isNil ifTrue:[self myX: nil]. ^myX! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myX: anObject "Set the value of myX" myX := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myY "Answer the value of myY" myY isNil ifTrue:[self myY: nil]. ^myY! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:58'! myY: anObject "Set the value of myY" myY := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:54'! objectTableStats "Answer the value of objectTableStats" objectTableStats isNil ifTrue:[self objectTableStats: RVMObjectTableStats new]. ^objectTableStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:54'! objectTableStats: anObject "Set the value of objectTableStats" objectTableStats := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:49'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:12'! receiveTally "Answer the value of receiveTally" receiveTally isNil ifTrue:[self receiveTally: nil]. ^receiveTally! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:12'! receiveTally: anObject "Set the value of receiveTally" receiveTally := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:20'! sendTallies "Answer the value of sendTallies" sendTallies isNil ifTrue:[self sendTallies: OrderedCollection new]. ^sendTallies! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! sendTallies: anObject "Set the value of sendTallies" sendTallies := anObject! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:11'! squeakInterpreterStats "Answer the value of squeakInterpreterStats" squeakInterpreterStats isNil ifTrue:[self squeakInterpreterStats: RVMSqueakInterpreterStats new]. ^squeakInterpreterStats! ! !RVMCPUCoreStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:07'! squeakInterpreterStats: anObject "Set the value of squeakInterpreterStats" squeakInterpreterStats := anObject! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:22'! initializeCoreStatsFrom: data | valueMap objectMap target | valueMap := { 'x' -> #myX:. 'y' -> #myY:. 'rank' -> #myRank:. }. objectMap := { 'sendTalliesByCore' -> #initializeSendTalliesFrom:. 'receiveTallies' -> #initializeReceiveTalliesFrom:. }. target := self. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'dmu 1/1/1970 01:09'! initializeFastCoreStatsFrom: data self myX: (data at: 2). self myY: (data at: 4). self myRank: (data at: 6). self initializeFastSendTalliesFrom: (data at: 8). self initializeFastReceiveTalliesFrom: (data at: 10). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:47'! initializeFastFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | self rawData: data. target := self. target millisecondsSinceLastQuery: (data at: 2). target cyclesSinceLastQuery: (data at: 4). target initializeFastCoreStatsFrom: (data at: 6). target initializeFastMemorySystemStatsFrom: (data at: 8). target initializeFastSqueakInterpreterStatsFrom: (data at: 10). target initializeFastObjectTableStatsFrom: (data at: 12). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:06'! initializeFastMemorySystemStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats. target gcCount: (data at: 2). target gcMilliseconds: (data at: 4). target gcCycles: (data at: 6). self initializeFastReadWriteHeapStatsFrom: (data at: 8). self initializeFastReadMostlyHeapStatsFrom: (data at: 10). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:53'! initializeFastObjectTableStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self objectTableStats. target allocatedEntryCount: (data at: 2). target entryCount: (data at: 4). target allocationsSinceLastQuery: (data at: 6). target entriesFreedSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeFastReadMostlyHeapStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats readMostlyHeapStats. target bytesUsed: (data at: 2). target bytesLeft: (data at: 4). target allocationsSinceLastQuery: (data at: 4). target compactionsSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeFastReadWriteHeapStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self memorySystemStats readWriteHeapStats. target bytesUsed: (data at: 2). target bytesLeft: (data at: 4). target allocationsSinceLastQuery: (data at: 4). target compactionsSinceLastQuery: (data at: 8). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:21'! initializeFastReceiveTalliesFrom: data "data looks like #(395 0 0 1041 1 520 0 0 0 121 0 1 0 1 0 1 28741 10 1 0) number of elements based on number of messages tallied" self receiveTally: (RVMCoreMessageTally fastForData: data)! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 3/25/2009 14:19'! initializeFastSendTalliesFrom: data "data USED TO looks like #('send_tallies' #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 'send_tallies' #(4 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 11 0 0 0) ... as many as we have cores being used) number of elements based on number of messages tallied" "NOW DATA LOOKS LIKE #(0 0 0 4290 0 0 0 0 0 4840 0 0 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 322 0 0)" "OLD CODE 2 to: data size by: 2 do:[:index| self sendTallies add: (RVMCoreMessageTally fastForData: (data at: index))]" "NEW CODE" self sendTallies add: (RVMCoreMessageTally fastForData: data )! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 9/9/2008 22:40'! initializeFastSqueakInterpreterStatsFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | target := self squeakInterpreterStats. target bytecodesExecuted: (data at: 2). target yieldCount: (data at: 4). " target millisecondsRunning: (data at: 6). target millisecondsWaiting: (data at: 8)." target cyclesRunning: (data at: 6). target cyclesWaiting: (data at: 8). target contextChangeCount: (data at: 10). target interruptCheckCount: (data at: 12). target unforcedInterruptCheckCount: (data at: 14) ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:07'! initializeFastestCoreStatsFrom: data "skip the tallies for speed" self myX: (data at: 2). self myY: (data at: 4). self myRank: (data at: 6). " self initializeFastSendTalliesFrom: (data at: 8). self initializeFastReceiveTalliesFrom: (data at: 10)." ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:48'! initializeFastestFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | target | self rawData: data. target := self. target millisecondsSinceLastQuery: (data at: 2). target cyclesSinceLastQuery: (data at: 4). target initializeFastestCoreStatsFrom: (data at: 6). target initializeFastMemorySystemStatsFrom: (data at: 8). target initializeFastSqueakInterpreterStatsFrom: (data at: 10). target initializeFastObjectTableStatsFrom: (data at: 12). ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:48'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap target | self rawData: data. valueMap := { 'millisecs' -> #millisecondsSinceLastQuery:. 'cycles' -> #cyclesSinceLastQuery:. }. objectMap := { 'coreStats' -> #initializeCoreStatsFrom:. 'memorySystemStats' -> #initializeMemorySystemStatsFrom:. 'interpreterStats' -> #initializeSqueakInterpreterStatsFrom:. 'objectTableStats' -> #initializeFastObjectTableStatsFrom:. }. target := self. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:04'! initializeMemorySystemStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | self rawData: data. valueMap := { 'gcCount' -> #gcCount:. 'gcMilliseconds' -> #gcMilliseconds:. 'gcCycles' -> #gcCycles:. 'readWriteHeapStats' -> #initializeReadWriteHeapStatsFrom:. 'readMostlyHeapStats' -> #initializeReadMostlyHeapStatsFrom:. }. target := self memorySystemStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 11/16/2008 15:50'! initializeObjectTableStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap target | valueMap := { 'allocatedEntryCount[rank]' -> #allocatedEntryCount:. 'entryCount[rank]' -> #entryCount:. 'allocationsSinceLastQuery[rank]' -> #allocationsSinceLastQuery:. 'entriesFreedSinceLastQuery[rank]' -> #entriesFreedSinceLastQuery:. }. objectMap := {}. target := self objectTableStats. self processMap: valueMap into: target forData: data. self processMap: objectMap into: target forData: data.! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeReadMostlyHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocationsSinceLastQuery' -> #allocationsSinceLastQuery:. 'compactionsSinceLastQuery' -> #compactionsSinceLastQuery:. }. target := self memorySystemStats readMostlyHeapStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:54'! initializeReadWriteHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocationsSinceLastQuery' -> #allocationsSinceLastQuery:. 'compactionsSinceLastQuery' -> #compactionsSinceLastQuery:. }. target := self memorySystemStats readWriteHeapStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/13/2008 18:21'! initializeReceiveTalliesFrom: data "data looks like #(395 0 0 1041 1 520 0 0 0 121 0 1 0 1 0 1 28741 10 1 0) number of elements based on number of messages tallied" self receiveTally: (RVMCoreMessageTally forMessageNames: self messageNames andData: data)! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 8/19/2008 11:31'! initializeSendTalliesFrom: data "data looks like #('send_tallies' #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 'send_tallies' #(4 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 11 0 0 0) ... as many as we have cores being used) number of elements based on number of messages tallied" | tally | data do:[:each| each = 'sendTallies' ifFalse:[ tally := RVMCoreMessageTally forMessageNames: self messageNames andData: each. self sendTallies add: tally]]! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'ssa 9/9/2008 22:24'! initializeSqueakInterpreterStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap target | self rawData: data. valueMap := { 'bytecodesExecuted' -> #bytecodesExecuted:. 'yieldCount' -> #yieldCount:. 'contextChangeCount' -> #contextChangeCount:. "'millisecondsRunning' -> #millisecondsRunning:." "'millisecondsWaiting' -> #millisecondsWaiting:." 'cyclesRunning' -> #cyclesRunning:. 'cyclesWaiting' -> #cyclesWaiting:. 'contextChangeCount' -> #contextChangeCount:. 'interruptCheckCount' -> #interruptCheckCount:. 'unforcedInterruptCheckCount' -> #unforcedInterruptCheckCount:. }. target := self squeakInterpreterStats. self processMap: valueMap into: target forData: data. ! ! !RVMCPUCoreStats methodsFor: 'initialize' stamp: 'dmu 8/15/2008 21:03'! processMap: map into: targetObject forData: data | index datum | map do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[ assoc key = 'receiveTallies' ifFalse:[self error:'Can''t find ',assoc key,' in sample data']]. datum := data at: index + 1. targetObject perform: assoc value with: datum]. ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:52'! allocationsSinceLast ^self allocationsSinceLastReadWrite + self allocationsSinceLastReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! allocationsSinceLastReadMostly ^self memorySystemStats readMostlyHeapStats allocationsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! allocationsSinceLastReadWrite ^self memorySystemStats readWriteHeapStats allocationsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:18'! bytecodesExecuted "Answer the count of bytecodes executed during this sample" ^self squeakInterpreterStats bytecodesExecuted! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:18'! bytecodesPerMillisecond "Answer the ratio of bytecodes executed per ms during this sample" ^(self squeakInterpreterStats bytecodesExectued / (1 max: self millisecondsSinceLastQuery) asFloat ) rounded! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:18'! bytecodesPerSecond "Answer the ratio of bytecodes executed per second during this sample" self millisecondsSinceLastQuery = 0 ifTrue:[^0]. ^(self squeakInterpreterStats bytecodesExecuted / (1 max: self millisecondsSinceLastQuery) asFloat * 1000) rounded! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeft ^self bytesLeftReadWrite + self bytesLeftReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeftReadMostly ^self memorySystemStats readMostlyHeapStats bytesLeft ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:49'! bytesLeftReadWrite ^self memorySystemStats readWriteHeapStats bytesLeft ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:45'! bytesUsed ^self bytesUsedReadWrite + self bytesUsedReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:44'! bytesUsedReadMostly ^self memorySystemStats readMostlyHeapStats bytesUsed ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 1/1/1970 00:54'! bytesUsedReadWrite ^self memorySystemStats readWriteHeapStats bytesUsed ! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:54'! compactionsSinceLast ^self compactionsSinceLastReadWrite + self compactionsSinceLastReadMostly! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:57'! compactionsSinceLastReadMostly ^self memorySystemStats readMostlyHeapStats compactionsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:56'! compactionsSinceLastReadWrite ^self memorySystemStats readWriteHeapStats compactionsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! contextChangeCount "Answer the count of yields during this sample" ^self squeakInterpreterStats contextChangeCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:53'! cyclesRunWaitRatio "Answer the ratio between my cyclesRunning and cyclesWaiting" ^self squeakInterpreterStats cyclesRunWaitRatio! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:46'! cyclesRunning "Answer the count of cycles spent running during this sample" ^self squeakInterpreterStats cyclesRunning! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:41'! cyclesSinceLast "Answer the count of cycles since last sample" ^self cyclesSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:46'! cyclesWaiting "Answer the count of cycles spect waiting during this sample" ^self squeakInterpreterStats cyclesWaiting! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! interruptCheckCount "Answer the count of yields during this sample" ^self squeakInterpreterStats interruptCheckCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:34'! millisecondsRunning "Answer the count of ms spent running during this sample" ^self squeakInterpreterStats millisecondsRunning! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:53'! millisecondsWaiting "Answer the count of ms spect waiting during this sample" ^self squeakInterpreterStats millisecondsWaiting! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:43'! msRunWaitRatio "Answer the ratio between my msRunning and msWaiting" ^self squeakInterpreterStats msRunWaitRatio! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:27'! msSinceLast "Answer the count of ms since last sample" ^self millisecondsSinceLastQuery! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 3/27/2009 16:55'! sendTallySums "Answer an array with the sum of all my send tallies in order" | sums tally | self sendTallies isEmpty ifTrue:[^#()]. sums _ self sendTallies first talliesInOrder. 2 to: self sendTallies size do:[:index| tally _ self sendTallies at: index. sums _ sums + tally talliesInOrder]. ^sums! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! unforcedInterruptCheckCount "Answer the count of yields during this sample" ^self squeakInterpreterStats unforcedInterruptCheckCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:16'! yieldCount "Answer the count of yields during this sample" ^self squeakInterpreterStats yieldCount! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:17'! yieldFrequency ^self squeakInterpreterStats yieldFrequency! ! !RVMCPUCoreStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:19'! yieldsPerSecond "Answer the ratio of yields per second during this sample" ^(self squeakInterpreterStats yieldCount / (1 max: self millisecondsSinceLastQuery) asFloat * 1000) rounded! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 10:57'! newFastFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFastFrom: data. ^stats! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:05'! newFastestFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFastestFrom: data. ^stats! ! !RVMCPUCoreStats class methodsFor: 'instance creation' stamp: 'ssa 8/13/2008 17:49'! newFromData: data forMessageNames: messageNames | stats | stats := self new. stats messageNames: messageNames. stats initializeFrom: data. ^stats! ! !RVMCanvasController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:16'! redButtonActivity "Move the offset of the view, effectively scrolling the canvas." | startPoint delta oldOffset | Cursor crossHair show. startPoint _ Sensor cursorPoint. oldOffset _ self view offset. [Sensor redButtonPressed] whileTrue:[delta _ Sensor cursorPoint - startPoint. self view offset: oldOffset + delta. self view displayView]. Cursor normal show ! ! !RVMCanvasController methodsFor: 'controlling' stamp: 'ssa 10/8/2008 19:05'! yellowButtonActivity ! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:10'! drawCanvas "This is the main drawing method. Subclasses will override to do their own drawing" self marker destForm: self canvas. self drawCross! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:10'! drawCross | box | box _ self canvas boundingBox. self drawLineFrom: box topLeft to: box bottomRight color: Color blue. self drawLineFrom: box topRight to: box bottomLeft color: Color red. ! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:22'! drawLineFrom: beginPoint to: endPoint color: aColor "Draw a line on the canvas in canvas coordinates" Marker color: aColor; place: beginPoint; goto: endPoint! ! !RVMCanvasView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:33'! eraseCanvas self canvas fillWhite! ! !RVMCanvasView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:29'! defaultControllerClass ^RVMCanvasController! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'dmiu 4/18/2011 13:32'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self extent - (0@2) depth: (8 min: Display depth)). self drawCanvas]. ^ canvas! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:25'! defaultOffset ^0@0! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! dirty "Answer the value of dirty" dirty isNil ifTrue:[self dirty: true]. ^ dirty! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! dirty: anObject "Set the value of dirty" dirty _ anObject! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:32'! extent "Answer the value of extent" extent isNil ifTrue:[self extent: self insetDisplayBox extent]. ^ extent! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:40'! extent: aPoint "Set the value of extent" extent _ aPoint ! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! marker ^self class marker! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:25'! offset "Answer the value of offset" offset isNil ifTrue:[self offset: self defaultOffset]. ^ offset! ! !RVMCanvasView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:31'! offset: aPoint "Set the value of offset" offset _ aPoint min: 0@0 max: self insetDisplayBox extent - self canvas extent! ! !RVMCanvasView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin + self offset clippingBox: self insetDisplayBox. ! ! !RVMCanvasView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:30'! newFrame "My frame has changed. Default is to do nothing special"! ! !RVMCanvasView class methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:20'! marker "Answer the default form to draw with, a 1 pixel black dot." Marker isNil ifTrue:[Marker _ Pen new. Marker defaultNib:1]. ^Marker! ! !RVMCanvasView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:13'! example "RVMCanvasView example" | topView | topView _ StandardSystemView new. topView label:'CanvasView test'. topView minimumSize: 200@200. topView borderWidth:2. topView addSubView: self new. topView controller open! ! !RVMCanvasView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:17'! example2 "RVMCanvasView example2" | topView view | topView _ RVMStandardSystemView new. topView label:'CanvasView test'. topView minimumSize: 200@50. topView borderWidth:2. view _ self new. view extent: 500@50. topView addSubView: view. topView controller open! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 11/15/2008 11:04'! clearView Display fill: self view insetDisplayBox fillColor: Color white! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 11/15/2008 11:04'! redButtonActivity | aborted lastAborted | self view displayPressed. lastAborted _ false. aborted _ true. [Sensor redButtonPressed] whileTrue:[ aborted _ (self view insetDisplayBox containsPoint: Sensor cursorPoint) not. aborted & lastAborted not ifTrue:[self clearView. self view displayView. lastAborted _ true]. aborted not & lastAborted ifTrue:[self clearView. self view displayPressed. lastAborted _ false]]. self clearView. self view displayView. aborted ifFalse:[self view performAction]! ! !RVMCheckBoxController methodsFor: 'basic control sequence' stamp: 'ssa 10/19/2008 00:09'! yellowButtonActivity ! ! !RVMCheckBoxController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:20'! controlActivity "Cursor action show." super controlActivity! ! !RVMCheckBoxController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 12:05'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 5/4/2010 15:36'! checkBoxForm "Answer the check(ed) box based on the current state " ^self checkBoxFormX! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 5/4/2010 15:36'! checkBoxFormNotCircle "Answer the check(ed) box based on the current state " ^self checked ifTrue:[self clearCircle]ifFalse:[self notSign]! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:05'! checkBoxFormOnOff "Answer the check(ed) box based on the current state " | msg msgText | msg _ self checked ifTrue:[ 'O N'] ifFalse:['O F F']. msgText _ msg asDisplayText. ^msgText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: msgText boundingBox extent). ! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:56'! checkBoxFormX "Answer the check(ed) box based on the current state " | box marker | box _ Form extent: self insetDisplayBox width asPoint depth: Display depth. "box border: box boundingBox width:2 fillColor: Color gray." self checked ifFalse:[^box]. "box fill: (box boundingBox insetBy: 2) fillColor: Color gray lighter lighter." marker _ Form extent:2@2 depth: Display depth. marker fillColor: Color gray. box drawLine: marker from: box boundingBox origin to: box boundingBox corner clippingBox: box boundingBox rule: Form over fillColor: nil. box drawLine: marker from: box boundingBox topRight - (2@0) to: box boundingBox bottomLeft - (2@0) clippingBox: box boundingBox rule: Form over fillColor: nil. ^box! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! checkedCircle ^Form extent: 10@10 depth: 1 fromArray: #( 1056964608 1635778560 3250585600 2185232384 2185232384 2487222272 2285895680 3368026112 1635778560 1056964608) offset: 0@0! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! clearCircle ^ Form extent: 10 @ 10 depth: 1 fromArray: #(1056964608 1635778560 3233808384 2151677952 2151677952 2151677952 2151677952 3233808384 1635778560 1056964608 ) offset: 0 @0! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 11/11/2008 22:42'! displayContents | checkBoxForm box | self okToDisplay ifFalse:[^self]. checkBoxForm _ self checkBoxForm. checkBoxForm _ checkBoxForm scaledToSize:(self insetDisplayBox extent min: checkBoxForm boundingBox extent). box _ checkBoxForm boundingBox. box _ box align: box center with: self insetDisplayBox center. Display fill: self insetDisplayBox fillColor: Color white. checkBoxForm displayOn: Display at: box origin ! ! !RVMCheckBoxOnlyView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:12'! notSign ^Form extent: 10@10 depth: 1 fromArray: #( 1056964608 1635778560 3250585600 2202009600 2252341248 2353004544 2554331136 4039114752 1635778560 1056964608) offset: 0@0! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 10/19/2008 00:43'! hear: aSpeaker "Some object I am listening to is speaking" self checked:nil. self displayView! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:44'! performAction "I've been clicked, switch state and act" self checked ifTrue:[self performUncheckAction]ifFalse:[self performCheckAction]. self checked: nil. self displayView! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:46'! performCheckAction self checkAction isSymbol ifTrue:[self model perform: self checkAction] ifFalse:[self checkAction value]! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 11/13/2008 10:46'! performUncheckAction self uncheckAction isSymbol ifTrue:[self model perform: self uncheckAction] ifFalse:[self uncheckAction value]! ! !RVMCheckBoxView methodsFor: 'updating' stamp: 'ssa 10/19/2008 00:56'! update: aSelector super update: aSelector. self checked: nil. self displayView! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 2/22/2010 15:39'! baseColor ^Color gray lighter lighter lighter! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:16'! checkAction "Answer the value of checkAction" checkAction isNil ifTrue:[self checkAction: [self inform:'box just checked']]. ^ checkAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! checkAction: anObject "Set the value of checkAction" checkAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:12'! checkBoxForm "Answer the value of checkBoxForm" ^self checkState ifTrue:[self checkedBoxForm]ifFalse:[self uncheckedBoxForm]! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:43'! checkState "Answer the value of checked the state of my checkbox" ^self checkStateAction isSymbol ifTrue:[self model perform: self checkStateAction] ifFalse:[self checkStateAction value]! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:19'! checkStateAction "Answer the value of checkStateAction" checkStateAction isNil ifTrue:[self checkStateAction: [false]]. ^ checkStateAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:18'! checkStateAction: anObject "Set the value of checkStateAction" checkStateAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:42'! checked "Answer the value of checked the state of my checkbox" checked isNil ifTrue:[self checked: self checkState]. ^ checked! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! checked: anObject "Set the value of checked" checked _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! checkedBoxForm "Answer the value of checkedBoxForm" checkedBoxForm isNil ifTrue:[self checkedBoxForm: self buildCheckedBoxForm]. ^ checkedBoxForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! checkedBoxForm: anObject "Set the value of checkedBoxForm" checkedBoxForm _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:17'! label "Answer the value of label" label isNil ifTrue:[self label: 'no label yet']. ^ label! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! label: anObject "Set the value of label" label _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:03'! labelForm "Answer the value of labelForm" labelForm isNil ifTrue:[self labelForm: self buildLabelForm]. ^ labelForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:03'! labelForm: anObject "Set the value of labelForm" labelForm _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:17'! uncheckAction "Answer the value of uncheckAction" uncheckAction isNil ifTrue:[self uncheckAction: [self inform:'box just UNchecked']]. ^ uncheckAction! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 03:15'! uncheckAction: anObject "Set the value of uncheckAction" uncheckAction _ anObject! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:10'! uncheckedBoxForm "Answer the value of uncheckedBoxForm" uncheckedBoxForm isNil ifTrue:[self uncheckedBoxForm: self buildUncheckedBoxForm]. ^ uncheckedBoxForm! ! !RVMCheckBoxView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 00:09'! uncheckedBoxForm: anObject "Set the value of uncheckedBoxForm" uncheckedBoxForm _ anObject! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:40'! buildCheckedBoxForm "Answer the check(ed) box " | box marker | box _ Form extent: 15@15 depth: Display depth . box fillColor: self baseColor lighter lighter. box border: box boundingBox width:1 fillColor: Color black. marker _ Form extent:2@2. marker fillColor: Color black. box drawLine: marker from: box boundingBox origin to: box boundingBox corner clippingBox: box boundingBox rule: Form over fillColor: nil. box drawLine: marker from: box boundingBox topRight - (2@0) to: box boundingBox bottomLeft - (2@0) clippingBox: box boundingBox rule: Form over fillColor: nil. ^box! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:01'! buildLabelForm "Answer the label form" | labelText | labelText := (' ',self label ) asDisplayText . labelText foregroundColor: Color black backgroundColor: Color transparent. ^labelText "asParagraph asForm" ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:40'! buildUncheckedBoxForm "Answer the uncheck(ed) box" | box | box _ Form extent: 15@15 depth: Display depth . box fillColor:self baseColor lighter lighter. box border: box boundingBox width:1 fillColor: Color black. ^box! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:34'! buildUnderLabelForm "Answer the under label form" | labelText | labelText := (' ',self label ) asDisplayText . labelText foregroundColor: self baseColor lighter lighter backgroundColor: Color transparent. ^labelText "asParagraph asForm" ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 2/23/2010 15:39'! displayContents | box theLabelForm theCheckBoxForm underLabelForm | theCheckBoxForm _ self checkBoxForm. theLabelForm _ self buildLabelForm. underLabelForm _ self buildUnderLabelForm. box _ 0@0 extent: theCheckBoxForm width + theLabelForm width @ (theCheckBoxForm height max: theLabelForm height). box _ box align: box leftCenter with: self insetDisplayBox leftCenter + (4@1). Display fill: self insetDisplayBox fillColor: self baseColor. theCheckBoxForm displayOn: Display at: box origin clippingBox: self insetDisplayBox rule: Form over fillColor:nil. underLabelForm displayOn: Display at: box origin + (theCheckBoxForm width @ -2)+(1@1) clippingBox: self insetDisplayBox rule: Form over fillColor:nil. theLabelForm displayOn: Display at: box origin + (theCheckBoxForm width @ -2) clippingBox: self insetDisplayBox rule: Form over fillColor:nil. ! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 04:10'! displayPressed self displayContents. Display border:( self insetDisplayBox insetBy: 2@2) width: 2 fillColor: Color gray! ! !RVMCheckBoxView methodsFor: 'displaying' stamp: 'ssa 11/15/2008 15:49'! displayView self okToDisplay ifFalse:[^self]. self uncache. self displayContents! ! !RVMCheckBoxView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 03:21'! defaultControllerClass ^RVMCheckBoxController! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 11/13/2008 10:05'! example "RVMCheckBoxView example" "Note we are using this class as a test model for this method. See examplePoint for a more normal usage" | topView | topView := RVMStandardSystemView new. self testState: true. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@200. topView addSubView: (self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]). topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 05:23'! examplePoint "RVMCheckBoxView examplePoint" | topView model | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@200. model _ 0@0. topView addSubView: (self on: model label: 'test' checkState: [model x = 1] whenChecked: [model x: 1] whenUnchecked: [model x:0]). topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 05:24'! exampleTwin "RVMCheckBoxView exampleTwin" "Note we are using this class as a test model for this method. See examplePoint for a more normal usage" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@50. topView maximumSize: 200@200. topView addSubView: (v _ self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]). topView addSubView: (self on: self label: 'test' checkState: [self testState] whenChecked: [self testState: true] whenUnchecked: [self testState: false]) below: v. topView label: 'RVMCheckBoxView test'. topView controller open! ! !RVMCheckBoxView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:22'! on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock ^self on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock monitor: false! ! !RVMCheckBoxView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:21'! on: aModel label: aString checkState: getterBlock whenChecked: checkedBlock whenUnchecked: uncheckedBlock monitor: updateFromRVMMonitor | v | v _ self new. v model: aModel. v label: aString. v checkStateAction: getterBlock. v checkAction: checkedBlock. v uncheckAction: uncheckedBlock. updateFromRVMMonitor ifTrue:[RVMMonitor inform: v]. ^v! ! !RVMCheckBoxView class methodsFor: 'testing' stamp: 'ssa 1/1/1970 04:22'! testState TestState isNil ifTrue:[TestState _ true]. ^TestState! ! !RVMCheckBoxView class methodsFor: 'testing' stamp: 'ssa 1/1/1970 04:25'! testState: aValue TestState _ aValue. self changed:#testState! ! !RVMCircularCollection methodsFor: 'add/remove elements' stamp: 'ssa 1/1/1970 00:03'! add: anObject "Add this object to my collection, increment the lastIndex, adjust if there is a rollover." self begin = 0 ifTrue:[ "I have no elements, add the first one" self begin:1. self end: 1] ifFalse:[ "I have elements, add one more and adjust if needed" self numberOfElements = self size ifTrue:["need to rollover the first element" self begin = self size "adjust begin and end" ifTrue:[self begin: 1. self end: self size] ifFalse:[self end: self begin. self begin: self begin + 1]] ifFalse:["no rollover needed" self end: (self end + 1 min: self size)]]. self array at: self end put: anObject. self incrementElements ! ! !RVMCircularCollection methodsFor: 'add/remove elements' stamp: 'ssa 1/1/1970 00:41'! removeAll self begin: 0. self end: 0. self array:nil. self numberOfElements:0! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:53'! array "Answer the value of array" array isNil ifTrue:[self array: (Array new: self size)]. ^ array! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:38'! array: anObject "Set the value of array" array _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! begin "Answer the value of begin" begin isNil ifTrue:[self begin: 0]. ^ begin! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! begin: anObject "Set the value of begin" begin _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:04'! decrementElements self numberOfElements: ((self numberOfElements - 1) max: 0)! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! end "Answer the value of end" end isNil ifTrue:[self end: 0]. ^ end! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! end: anObject "Set the value of end" end _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:12'! incrementElements self numberOfElements: ((self numberOfElements + 1) min: self size)! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:03'! numberOfElements "Answer the value of numberOfElements" numberOfElements isNil ifTrue:[self numberOfElements: 0]. ^ numberOfElements! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 01:02'! numberOfElements: anObject "Set the value of numberOfElements" numberOfElements _ anObject! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 10/18/2008 21:37'! realIndexFor: index "Answer the loop adjusted index value" | realIndex | index > self size ifTrue:[realIndex _ index \\ self size] ifFalse:[realIndex _ index]. realIndex _ realIndex - 1 + self begin. realIndex > self size ifTrue:[realIndex _ realIndex - self size]. ^realIndex ! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:52'! size "Answer the value of size" size isNil ifTrue:[self size: 10]. ^ size! ! !RVMCircularCollection methodsFor: 'private' stamp: 'ssa 1/1/1970 00:04'! size: aNumber "Set the value of size" | contents oldSize | size = aNumber ifTrue:[^self]. self isEmpty ifTrue:[size _ aNumber. self array:nil; numberOfElements:0] ifFalse:[contents _ self asOrderedCollection. oldSize _ contents size. size _ aNumber. self begin:0;end:0;numberOfElements:0. self array: (Array new: size). 1 to: (size min: oldSize) do:[:index| self add: (contents at: index)]]. ! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:14'! at: index ^self array at: (self realIndexFor: index)! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:15'! at: index put: anObject self array at: (self realIndexFor: index) put: anObject! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 22:00'! atRandom ^self at: self numberOfElements atRandom! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:27'! first ^self at:1! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:28'! last ^self at:self numberOfElements! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 21:29'! nextIndex "Answer the value of nextIndex" nextIndex isNil ifTrue:[self nextIndex: 1]. ^ nextIndex! ! !RVMCircularCollection methodsFor: 'accessing' stamp: 'ssa 10/18/2008 21:40'! nextIndex: anInteger "Set the value of nextIndex" anInteger > self size ifTrue:[^nextIndex _ 1]. nextIndex _ anInteger! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 1/1/1970 00:40'! asArray ^self asOrderedCollection asArray! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 10/28/2008 19:41'! asCircularCollection ^self! ! !RVMCircularCollection methodsFor: 'converting' stamp: 'ssa 1/1/1970 00:20'! asOrderedCollection | oc | oc _ OrderedCollection new. self do:[:each| oc add: each]. ^oc! ! !RVMCircularCollection methodsFor: 'enumerating' stamp: 'ssa 1/1/1970 00:18'! collect: aBlock "Iterate over my elements in order and answer the results" | results | results _ self class new: self size. self do:[:each| results add: (aBlock value: each)]. ^results! ! !RVMCircularCollection methodsFor: 'enumerating' stamp: 'ssa 1/1/1970 00:13'! do: aBlock "Iterate over my elements in order" 1 to: self numberOfElements do:[:index| aBlock value:(self at: index)]! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 5/28/2010 16:55'! atEnd "Acting like an infinite stream" ^false! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:55'! isEmpty ^self numberOfElements = 0! ! !RVMCircularCollection methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:55'! isFull ^self numberOfElements = self size! ! !RVMCircularCollection methodsFor: 'printing' stamp: 'ssa 10/3/2008 21:17'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' size:',self size printString,' numberOfElements:',self numberOfElements printString! ! !RVMCircularCollection methodsFor: 'stream emulation' stamp: 'ssa 10/18/2008 21:31'! next "Answer the next element in line, then advance the nextIndex" | item | self isEmpty ifTrue:[self error:'Empty Collection']. item _ self at: self nextIndex. self nextIndex: self nextIndex + 1. ^item! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:19'! new: anInteger | collection | collection _ self new. collection size: anInteger. ^collection! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:42'! new: anInteger withAll: aCollection | collection | collection _ self new: anInteger. aCollection do:[:each| collection add: each]. ^collection! ! !RVMCircularCollection class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:42'! withAll: aCollection ^self new: aCollection size withAll: aCollection! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:36'! testAdd "RVMCircularCollection testAdd" | cc bag | cc _ self new: 10. 5 timesRepeat:[cc add: 1]. bag _ cc asOrderedCollection asBag. bag size = 5 & ((bag occurrencesOf: 1) = 5 ) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:39'! testCollect "RVMCircularCollection testCollect" | cc results | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. results _ cc collect:[:each| each]. results asArray = #(16 17 18 19 20) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:38'! testDo "RVMCircularCollection testDo" | cc total | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. total _ 0. cc do:[:each| total _ total + each]. total = #(20 19 18 17 16) sum ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:54'! testResize "RVMCircularCollection testResize" | cc | cc _ self new: 5. 1 to: 20 do:[:each| cc add: each]. cc size: 2. cc asArray = #(16 17) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMCircularCollection class methodsFor: 'tests' stamp: 'ssa 1/1/1970 00:35'! testRollover "RVMCircularCollection testRollover" | cc | cc _ self new: 10. 1 to: 20 do:[:each| cc add: each]. cc asOrderedCollection asArray = #(11 12 13 14 15 16 17 18 19 20) ifTrue:['passed' print]ifFalse:['failed' print]! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:50'! colorFromUser "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette." | d startPt save tr oldColor c here s | d _ Display depth. ((Color colorChart == nil) or: [Color colorChart depth ~= Display depth]) ifTrue: [Color colorChart:(Color oldColorPaletteForDepth: d extent: (2 * 144)@80)]. startPt _ Sensor cursorPoint. save _ Form fromDisplay: (startPt extent: Color colorChart extent). Color colorChart displayAt: startPt. tr _ Color colorChart extent - (50@19) corner: Color colorChart extent. tr _ tr translateBy: startPt. oldColor _ nil. [Sensor anyButtonPressed] whileTrue: [ c _ Display colorAt: (here _ Sensor cursorPoint). (tr containsPoint: here) ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c] ifTrue: [ c _ Color transparent. Display fill: (0@61+startPt extent: 20@19) fillColor: Color white]. c = oldColor ifFalse: [ Display fillWhite: (20@61 + startPt extent: 135@19). c isTransparent ifTrue: [s _ 'transparent'] ifFalse: [s _ c shortPrintString. s _ s copyFrom: 7 to: s size - 1]. s displayAt: 20@61 + startPt. oldColor _ c]]. save displayAt: startPt. Sensor waitNoButton. ^ c ! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:56'! controlActivity Cursor menu show. super controlActivity! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:56'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMColorButtonController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 16:06'! yellowButtonActivity view color: self colorFromUser. view display! ! !RVMColorButtonView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 15:58'! defaultControllerClass ^RVMColorButtonController! ! !RVMColorButtonView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:31'! displayView self uncache. Display fill: self insetDisplayBox fillColor: self color. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self color negated."! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:29'! color "Answer the value of color" color isNil ifTrue:[color_(self colorSetter isSymbol ifTrue:[model perform: self colorGetter] ifFalse:[self colorGetter value])]. ^ color! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:05'! color: anObject "Set the value of color" color _ anObject. self colorSetter isSymbol ifTrue:[model perform: self colorSetter with: anObject] ifFalse:[self colorSetter value: anObject]! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:21'! colorGetter "Answer the value of colorGetter" colorGetter isNil ifTrue:[self colorGetter: #color]. ^ colorGetter! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:20'! colorGetter: anObject "Set the value of colorGetter" colorGetter _ anObject! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:21'! colorSetter "Answer the value of colorSetter" colorSetter isNil ifTrue:[self colorSetter: #color:]. ^ colorSetter! ! !RVMColorButtonView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:20'! colorSetter: anObject "Set the value of colorSetter" colorSetter _ anObject! ! !RVMColorButtonView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 22:03'! example "RVMColorButtonView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 50@50. topView maximumSize: 100@100. topView addSubView: self exampleInstance. topView label: 'ColorButton'. topView controller open! ! !RVMColorButtonView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:58'! exampleInstance ^self on: nil colorGetter:[Color random] colorSetter:[:color| color print]! ! !RVMColorButtonView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:57'! on: aModel colorGetter: getterSelector colorSetter: setterSelector | view | view _ self new. view model: aModel. view colorGetter: getterSelector. view colorSetter: setterSelector. ^view! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 20:13'! redButtonActivity self view usesScaler ifTrue:[ (self view adjustScaleBox containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]]! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 5/12/2010 10:19'! spawnScaleAdjuster | scaler maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height | scaler _ self view scaler. maxView _ RVMValueEditorView on: scaler valueGetter: [scaler max] valueSetter:[:v|scaler setMax:v. self view model redrawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: scaler valueGetter: [scaler min] valueSetter:[:v|scaler setMin:v. self view model redrawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[scaler resetScaling. self view model redrawOnCanvas; displayView]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[scaler setRangeToObserved. self view model redrawOnCanvas; displayView]. autoScaleCheckBox _ RVMCheckBoxView on: scaler label: 'Automatic Scaling' checkState: [scaler automaticScaling] whenChecked: [scaler automatic. self view model redrawOnCanvas; displayView] whenUnchecked: [scaler manual. self view model redrawOnCanvas; displayView] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: self view aspect. height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. topView controller open! ! !RVMColorScaleController methodsFor: 'controlling' stamp: 'ssa 5/4/2010 15:41'! yellowButtonActivity self spawnScaleAdjuster! ! !RVMColorScaleView methodsFor: 'controller access' stamp: 'ssa 11/4/2008 14:28'! defaultControllerClass ^RVMColorScaleController! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 14:26'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 14:25'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:42'! aspect ^self aspectSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/9/2008 11:42'! aspectLabel "Answer the value of aspectLabel" aspectLabel isNil ifTrue:[self aspectLabel: (Form extent: 1@1)]. ^ aspectLabel! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 19:13'! aspectLabel: anObject "Set the value of aspectLabel" aspectLabel _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:42'! aspectSource "Answer the value of aspectSource" aspectSource isNil ifTrue:[self aspectSource: [#bytesUseds]]. ^ aspectSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 07:41'! aspectSource: anObject "Set the value of aspectSource" aspectSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:26'! colors ^self colorsSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:25'! colorsSource "Answer the value of colorsSource" colorsSource isNil ifTrue:[self colorsSource: [Color hotColdShades: 25]]. ^ colorsSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:25'! colorsSource: anObject "Set the value of colorsSource" colorsSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! horizontal self orientation:#horizontal! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:27'! orientation "Answer the value of orientation" orientation isNil ifTrue:[self orientation: #vertical]. ^ orientation! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:30'! orientation: anObject "Set the value of orientation" orientation _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:20'! scaler ^self scalerSource value! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:19'! scalerSource "Answer the value of scalerSource" scalerSource isNil ifTrue:[self scalerSource: [RVMDataScaler exampleInstance]]. ^ scalerSource! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 06:19'! scalerSource: anObject "Set the value of scalerSource" scalerSource _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:11'! usesScaler "Answer the value of usesScaler" usesScaler isNil ifTrue:[self usesScaler: false]. ^ usesScaler! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:11'! usesScaler: anObject "Set the value of usesScaler" usesScaler _ anObject! ! !RVMColorScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! vertical self orientation:#vertical! ! !RVMColorScaleView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:55'! hear: something self drawFastCanvas. self displayView! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 13:44'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 14:14'! adjustScaleIconHorizontal ^((ColorForm extent: 31@16 depth: 8 fromArray: #( 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967040 4280755235 606282787 606282787 606282787 606282787 606282787 606282787 606600960 4280615169 16843009 16843009 16843009 16843009 16843009 16843009 19201792 4279173377 320014867 269488906 319427073 303237651 318837002 320014864 17760000 4280615169 4294967295 387186687 4294909697 251658239 4278852095 4294967050 19201792 4280615184 4294967295 4294967295 4294909713 251658239 4294967295 4294967050 19136256 4280615169 4294967295 4294967295 4294967295 4294967295 4294967295 4294967050 19201792 4280753933 4294967295 4294967295 4294967295 4294967295 4294967295 4294967072 522649344 4294967295 4294967295 4294967295 603979775 4294905615 4294967295 4294967295 4294967040 4294967295 4294967295 4280556050 251658239 4294911764 371261439 4294967295 4294967040 4294967295 4294967077 419496203 4294967295 4294967054 16847630 4294967295 4294967040 4294967295 4294909706 16843024 286331153 286331153 16843024 420478975 4294967040 4294967295 4294905368 268501267 202116108 202116120 16843028 505806847 4294967040 4294967295 4294967295 253100305 654311423 4294967043 17440767 4294967295 4294967040 4294967295 4294967295 4294910490 536870911 4294905623 505872383 4294967295 4294967040 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967040) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.0 0.0 0.0) #(1.0 1.0 1.0) #(0.5 0.5 0.5) #(1.0 0.0 0.0) #(0.0 1.0 0.0) #(0.0 0.0 1.0) #(0.0 1.0 1.0) #(1.0 1.0 0.0) #(1.0 0.0 1.0) #(0.125 0.125 0.125) #(0.25 0.25 0.25) #(0.375 0.375 0.375) #(0.625 0.625 0.625) #(0.75 0.75 0.75) #(0.875 0.875 0.875) #(0.031 0.031 0.031) #(0.063 0.063 0.063) #(0.094 0.094 0.094) #(0.156 0.156 0.156) #(0.188 0.188 0.188) #(0.219 0.219 0.219) #(0.282 0.282 0.282) #(0.313 0.313 0.313) #(0.344 0.344 0.344) #(0.407 0.407 0.407) #(0.438 0.438 0.438) #(0.469 0.469 0.469) #(0.531 0.531 0.531) #(0.562 0.562 0.562) #(0.593 0.593 0.593) #(0.656 0.656 0.656) #(0.687 0.687 0.687) #(0.718 0.718 0.718) #(0.781 0.781 0.781) #(0.812 0.812 0.812) #(0.844 0.844 0.844) #(0.906 0.906 0.906) #(0.937 0.937 0.937) #(0.969 0.969 0.969) #(0.0 0.0 0.0) #(0.0 0.199 0.0) #(0.0 0.4 0.0) #(0.0 0.599 0.0) #(0.0 0.8 0.0) #(0.0 1.0 0.0) #(0.0 0.0 0.199) #(0.0 0.199 0.199) #(0.0 0.4 0.199) #(0.0 0.599 0.199) #(0.0 0.8 0.199) #(0.0 1.0 0.199) #(0.0 0.0 0.4) #(0.0 0.199 0.4) #(0.0 0.4 0.4) #(0.0 0.599 0.4) #(0.0 0.8 0.4) #(0.0 1.0 0.4) #(0.0 0.0 0.599) #(0.0 0.199 0.599) #(0.0 0.4 0.599) #(0.0 0.599 0.599) #(0.0 0.8 0.599) #(0.0 1.0 0.599) #(0.0 0.0 0.8) #(0.0 0.199 0.8) #(0.0 0.4 0.8) #(0.0 0.599 0.8) #(0.0 0.8 0.8) #(0.0 1.0 0.8) #(0.0 0.0 1.0) #(0.0 0.199 1.0) #(0.0 0.4 1.0) #(0.0 0.599 1.0) #(0.0 0.8 1.0) #(0.0 1.0 1.0) #(0.199 0.0 0.0) #(0.199 0.199 0.0) #(0.199 0.4 0.0) #(0.199 0.599 0.0) #(0.199 0.8 0.0) #(0.199 1.0 0.0) #(0.199 0.0 0.199) #(0.199 0.199 0.199) #(0.199 0.4 0.199) #(0.199 0.599 0.199) #(0.199 0.8 0.199) #(0.199 1.0 0.199) #(0.199 0.0 0.4) #(0.199 0.199 0.4) #(0.199 0.4 0.4) #(0.199 0.599 0.4) #(0.199 0.8 0.4) #(0.199 1.0 0.4) #(0.199 0.0 0.599) #(0.199 0.199 0.599) #(0.199 0.4 0.599) #(0.199 0.599 0.599) #(0.199 0.8 0.599) #(0.199 1.0 0.599) #(0.199 0.0 0.8) #(0.199 0.199 0.8) #(0.199 0.4 0.8) #(0.199 0.599 0.8) #(0.199 0.8 0.8) #(0.199 1.0 0.8) #(0.199 0.0 1.0) #(0.199 0.199 1.0) #(0.199 0.4 1.0) #(0.199 0.599 1.0) #(0.199 0.8 1.0) #(0.199 1.0 1.0) #(0.4 0.0 0.0) #(0.4 0.199 0.0) #(0.4 0.4 0.0) #(0.4 0.599 0.0) #(0.4 0.8 0.0) #(0.4 1.0 0.0) #(0.4 0.0 0.199) #(0.4 0.199 0.199) #(0.4 0.4 0.199) #(0.4 0.599 0.199) #(0.4 0.8 0.199) #(0.4 1.0 0.199) #(0.4 0.0 0.4) #(0.4 0.199 0.4) #(0.4 0.4 0.4) #(0.4 0.599 0.4) #(0.4 0.8 0.4) #(0.4 1.0 0.4) #(0.4 0.0 0.599) #(0.4 0.199 0.599) #(0.4 0.4 0.599) #(0.4 0.599 0.599) #(0.4 0.8 0.599) #(0.4 1.0 0.599) #(0.4 0.0 0.8) #(0.4 0.199 0.8) #(0.4 0.4 0.8) #(0.4 0.599 0.8) #(0.4 0.8 0.8) #(0.4 1.0 0.8) #(0.4 0.0 1.0) #(0.4 0.199 1.0) #(0.4 0.4 1.0) #(0.4 0.599 1.0) #(0.4 0.8 1.0) #(0.4 1.0 1.0) #(0.599 0.0 0.0) #(0.599 0.199 0.0) #(0.599 0.4 0.0) #(0.599 0.599 0.0) #(0.599 0.8 0.0) #(0.599 1.0 0.0) #(0.599 0.0 0.199) #(0.599 0.199 0.199) #(0.599 0.4 0.199) #(0.599 0.599 0.199) #(0.599 0.8 0.199) #(0.599 1.0 0.199) #(0.599 0.0 0.4) #(0.599 0.199 0.4) #(0.599 0.4 0.4) #(0.599 0.599 0.4) #(0.599 0.8 0.4) #(0.599 1.0 0.4) #(0.599 0.0 0.599) #(0.599 0.199 0.599) #(0.599 0.4 0.599) #(0.599 0.599 0.599) #(0.599 0.8 0.599) #(0.599 1.0 0.599) #(0.599 0.0 0.8) #(0.599 0.199 0.8) #(0.599 0.4 0.8) #(0.599 0.599 0.8) #(0.599 0.8 0.8) #(0.599 1.0 0.8) #(0.599 0.0 1.0) #(0.599 0.199 1.0) #(0.599 0.4 1.0) #(0.599 0.599 1.0) #(0.599 0.8 1.0) #(0.599 1.0 1.0) #(0.8 0.0 0.0) #(0.8 0.199 0.0) #(0.8 0.4 0.0) #(0.8 0.599 0.0) #(0.8 0.8 0.0) #(0.8 1.0 0.0) #(0.8 0.0 0.199) #(0.8 0.199 0.199) #(0.8 0.4 0.199) #(0.8 0.599 0.199) #(0.8 0.8 0.199) #(0.8 1.0 0.199) #(0.8 0.0 0.4) #(0.8 0.199 0.4) #(0.8 0.4 0.4) #(0.8 0.599 0.4) #(0.8 0.8 0.4) #(0.8 1.0 0.4) #(0.8 0.0 0.599) #(0.8 0.199 0.599) #(0.8 0.4 0.599) #(0.8 0.599 0.599) #(0.8 0.8 0.599) #(0.8 1.0 0.599) #(0.8 0.0 0.8) #(0.8 0.199 0.8) #(0.8 0.4 0.8) #(0.8 0.599 0.8) #(0.8 0.8 0.8) #(0.8 1.0 0.8) #(0.8 0.0 1.0) #(0.8 0.199 1.0) #(0.8 0.4 1.0) #(0.8 0.599 1.0) #(0.8 0.8 1.0) #(0.8 1.0 1.0) #(1.0 0.0 0.0) #(1.0 0.199 0.0) #(1.0 0.4 0.0) #(1.0 0.599 0.0) #(1.0 0.8 0.0) #(1.0 1.0 0.0) #(1.0 0.0 0.199) #(1.0 0.199 0.199) #(1.0 0.4 0.199) #(1.0 0.599 0.199) #(1.0 0.8 0.199) #(1.0 1.0 0.199) #(1.0 0.0 0.4) #(1.0 0.199 0.4) #(1.0 0.4 0.4) #(1.0 0.599 0.4) #(1.0 0.8 0.4) #(1.0 1.0 0.4) #(1.0 0.0 0.599) #(1.0 0.199 0.599) #(1.0 0.4 0.599) #(1.0 0.599 0.599) #(1.0 0.8 0.599) #(1.0 1.0 0.599) #(1.0 0.0 0.8) #(1.0 0.199 0.8) #(1.0 0.4 0.8) #(1.0 0.599 0.8) #(1.0 0.8 0.8) #(1.0 1.0 0.8) #(1.0 0.0 1.0) #(1.0 0.199 1.0) #(1.0 0.4 1.0) #(1.0 0.599 1.0) #(1.0 0.8 1.0) #(1.0 1.0 1.0) ))! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:04'! drawCanvas self canvas fillWhite. self orientation = #vertical ifTrue:[self drawVertical] ifFalse:[self drawHorizontal]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 01:14'! drawColorBarHorizontalIn: aRectangle | w r | w _ aRectangle width / self colors size. r _ aRectangle origin extent: w@aRectangle height. self colors do: [:c | self canvas fill: r rounded fillColor: c. r _ r translateBy: w@0]. ! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:07'! drawColorBarVerticalIn: aRectangle | h r | h _ aRectangle height / self colors size. r _ aRectangle origin extent: aRectangle width@h. self colors do: [:c | self canvas fill: r rounded fillColor: c. r _ r translateBy: 0@h]. ! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:51'! drawFastCanvas self orientation = #vertical ifTrue:[self drawFastVertical] ifFalse:[self drawFastHorizontal]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawFastHorizontal "Display in horizontal style, text labels only for speed" | maxLabel minLabel midLabel box ticLength margin bigBox leftX midX adjustIcon loc | self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:self aspect asDisplayText. maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin+ (0@11) corner: bigBox corner. ticLength _ 4. margin _ 2. leftX _ box topLeft x + 2. midX _ box center x. self aspectLabel align: self aspectLabel boundingBox bottomCenter with: box bottomCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight + (-2@ticLength+margin). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox topCenter with: box topCenter + (0@ticLength+margin). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox topLeft with: box topLeft +(0@ticLength+margin). minLabel displayOn: self canvas. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIconHorizontal. adjustIcon displayOn: self canvas at: (loc _ ((leftX+midX//2)@(bigBox center y + 4)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawFastVertical "Display in vertical style, only the text labels for speed" | maxLabel minLabel midLabel box ticLength margin bigBox eraser1 eraser2 eraser3 eraser topY midY adjustIcon loc | eraser _ ' '. eraser1 _ eraser asDisplayText. eraser2 _ eraser asDisplayText. eraser3 _ eraser asDisplayText. eraser1 foregroundColor: Color white backgroundColor: Color white. eraser2 foregroundColor: Color white backgroundColor: Color white. eraser3 foregroundColor: Color white backgroundColor: Color white. self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:(self aspect asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0). maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin + (self aspectLabel width@0) extent: 40@bigBox height. ticLength _ 4. margin _ 2. topY _ box topRight y + 2 . midY _ box center y. self aspectLabel align: self aspectLabel boundingBox leftCenter with: bigBox leftCenter. self aspectLabel displayOn: self canvas. eraser1 align: eraser1 boundingBox topRight with: box topRight - (ticLength+margin+1@0). eraser1 displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. eraser2 align: eraser2 boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). eraser2 displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. eraser3 align: eraser3 boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). eraser3 displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIcon. adjustIcon displayOn: self canvas at: (loc _ (bigBox topCenter x @ (topY+midY//2)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawHorizontal "Display in horizontal style" | maxLabel minLabel midLabel box ticLength margin topY leftX rightX bigBox midX adjustIcon loc | self aspectLabel asParagraph asForm fillWhite displayOn: self canvas. self aspectLabel:self aspect asDisplayText. maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin+ (0@11) corner: bigBox corner. self drawColorBarHorizontalIn: (bigBox origin + (0@1) extent: bigBox width@10). ticLength _ 4. margin _ 2. self aspectLabel align: self aspectLabel boundingBox bottomCenter with: box bottomCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight + (-2@ticLength+margin). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox topCenter with: box topCenter + (0@ticLength+margin). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox topLeft with: box topLeft +(0@ticLength+margin). minLabel displayOn: self canvas. leftX _ box topLeft x + 2. midX _ box center x. rightX _ box topRight x - 2. topY _ box topRight y + margin. self canvas fill: (leftX@topY corner: rightX @(topY+1)) fillColor: Color black. self canvas fill: (leftX@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX+leftX//2@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (midX+rightX//2@topY extent: 1@ticLength) fillColor: Color black. self canvas fill: (rightX@topY extent: 1@ticLength) fillColor: Color black. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIconHorizontal. adjustIcon displayOn: self canvas at: (loc _ ((leftX+midX//2)@(bigBox center y + 4)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'drawing' stamp: 'ssa 11/4/2008 20:12'! drawVertical "Display in vertical style" | maxLabel minLabel midLabel box ticLength margin topY midY bottomY leftX rightX bigBox adjustIcon loc | self aspectLabel fillWhite displayOn: self canvas. self aspectLabel:(self aspect asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0). maxLabel _ self scaler max printShowingMax3Digits asDisplayText. minLabel _ self scaler min printShowingMax3Digits asDisplayText. midLabel _ (self scaler range / 2 + self scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: Color black backgroundColor: Color transparent. midLabel foregroundColor: Color black backgroundColor: Color transparent. minLabel foregroundColor: Color black backgroundColor: Color transparent. bigBox _ self canvas boundingBox. box _ bigBox origin + (aspectLabel width@0) extent: 40@bigBox height. self drawColorBarVerticalIn: (box topRight extent: 10@bigBox height). ticLength _ 4. margin _ 2. self aspectLabel align: self aspectLabel boundingBox leftCenter with: bigBox leftCenter. self aspectLabel displayOn: self canvas. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. topY _ box topRight y + 2 . midY _ box center y. bottomY _ box bottomRight y - 3. leftX _ box topRight x - ticLength - margin. rightX _ box corner x - margin. self canvas fill: (rightX - 1@topY corner: rightX@bottomY) fillColor: Color black. self canvas fill: (leftX@topY extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@(topY+midY//2) extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@midY extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@(midY+bottomY//2) extent: ticLength@1) fillColor: Color black. self canvas fill: (leftX@bottomY extent: ticLength@1) fillColor: Color black. self usesScaler ifTrue:[ adjustIcon _ self adjustScaleIcon. adjustIcon displayOn: self canvas at: (loc _( bigBox topCenter x @ (topY+midY//2)) - adjustIcon boundingBox center). self adjustScaleBox: (loc + self insetDisplayBox origin extent: adjustIcon extent)]! ! !RVMColorScaleView methodsFor: 'framing' stamp: 'ssa 1/1/1970 01:30'! newFrame self canvas: nil. self extent: self insetDisplayBox extent. self drawCanvas. self displayView! ! !RVMColorScaleView class methodsFor: 'instance creation' stamp: 'ssa 11/4/2008 20:16'! aspectSource: aspectBlock scalerSource: aBlock colorsSource: colorBlock orientation: aSymbol forView: aView adjustScaler: aBoolean "Answer a new view. Use these blocks to access the scaler and colors it will need to display. Orientation is #vertical or #horizontal" | v | v _ self new. v aspectSource: aspectBlock. v scalerSource: aBlock. v colorsSource: colorBlock. v orientation: aSymbol. v model: aView. v usesScaler: aBoolean. ^v! ! !RVMColorScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:02'! exampleHorizontal "RVMColorScaleView exampleHorizontal" self new horizontal demo! ! !RVMColorScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:03'! exampleVertical "RVMColorScaleView exampleVertical" self new vertical demo! ! !RVMColoredDataScaler methodsFor: 'privatizing' stamp: 'ssa 9/17/2008 13:01'! privatize "Install a copy of my current scaler so changes to it won't effect others." self scaler: self scaler deepCopy! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 12:56'! aspect ^self scaler aspect! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:22'! aspect: aSymbol "Swap in a new default scaler for this aspect if different from my current aspect." | defaultScaler | aSymbol == self aspect ifTrue:[^self]. "no need to change" defaultScaler _ RVMMonitor scalerFor: aSymbol. self scaler: defaultScaler "use the shared scaler until user asks for private copy". ! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:22'! color "Answer the value of color" color isNil ifTrue:[self color: Color blue]. ^ color! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:22'! color: anObject "Set the value of color" color _ anObject! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:23'! lastObserved ^self scaler lastObserved! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! max ^self scaler max! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! max: aValue ^self scaler max: aValue! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! min ^self scaler min! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 13:02'! min: aValue ^self scaler min: aValue! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:24'! scale: someData ^self scaler scale: someData! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:35'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: RVMDataScaler exampleInstance]. ^ scaler! ! !RVMColoredDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 22:35'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMColoredDataScaler methodsFor: 'user interface' stamp: 'ssa 9/17/2008 13:05'! open RVMColoredDataScalerView openOn: self. ! ! !RVMColoredDataScaler methodsFor: 'delegation' stamp: 'ssa 9/17/2008 13:03'! doesNotUnderstand: aMessage "See if my scaler understands it." Transcript cr;show:'delegating: ',aMessage printString. ^self scaler perform: aMessage selector withArguments: aMessage arguments! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:35'! aspect: aSymbol ^self aspect: aSymbol color: Color random! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/14/2008 20:58'! aspect: aSymbol color: aColor | scaler | scaler _ self new. scaler scaler: (RVMMonitor scalerFor: aSymbol). scaler color: aColor. ^scaler! ! !RVMColoredDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 22:37'! aspect: aSymbol min: minValue max: maxValue color: aColor | scaler | scaler _ self aspect: aSymbol min: minValue max: maxValue. scaler color: aColor. ^scaler! ! !RVMColoredDataScaler class methodsFor: 'examples' stamp: 'ssa 9/17/2008 14:03'! exampleInstance | cs | cs _ self new. cs scaler:RVMDataScaler exampleInstance. cs color: Color blue. ^cs! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:30'! aspectView "Answer a subview on my aspect, the symbol name for the aspect of the data sample I am scaling" ^RVMAspectLabelView on: self model getAllAspectsWith: [RVMMulticoreSample aspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:.! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 1/1/1970 01:02'! autoscaleHardenView "Answer a subview showing the autoscale/harden/privatize buttons" | view autoscaleButton hardenButton privatizeButton | view _ RVMView new. autoscaleButton _ RVMButtonView label:'A' style:#action action:[self model scaler setRangeToObserved]. hardenButton _ RVMButtonView label:'H' style:#action action:[self model scaler harden]. privatizeButton _ RVMButtonView label:'P' style:#action action:[self model privatize]. view addSubView: autoscaleButton. view addSubView: hardenButton below: autoscaleButton. view addSubView: privatizeButton below: hardenButton. ^view! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:59'! colorButton "Answer a subview that shows the color to use to display my data" ^RVMColorButtonView on: self model colorGetter:#color colorSetter: #color:! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 1/1/1970 01:16'! initializeSubViews "Add the subviews required to provide a UI for my model, a ColoredDataScaler." self addSubView: self aspectView in: (0@0 extent: 5/10 @ (1/2)) borderWidth:0. self addSubView: self valueView in: (0@(1/2 )extent: 5/10 @ (1/2)) borderWidth:0. self addSubView: self autoscaleHardenView in: (5/10@0 extent: 1/10@1) borderWidth:0. self addSubView: self minMaxView in: (6/10@0 extent: 4/10@1) borderWidth:1. ! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 14:00'! minMaxView "Answer a subview showing the min/max settings for the data sample I am scaling" ^RVMMinMaxView on: self model getMin: #min setMin: #min: getMax: #max setMax: #max:! ! !RVMColoredDataScalerView methodsFor: 'subView access' stamp: 'ssa 9/17/2008 13:56'! valueView "Answer a subview that will show the last observed value" ^RVMValueView on: self model valueGetterOnly:#lastObserved! ! !RVMColoredDataScalerView methodsFor: 'model access' stamp: 'ssa 9/17/2008 13:09'! model: aColoredDataScaler "Set my model and initialize my subviews" super model: aColoredDataScaler. self initializeSubViews! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:07'! on: aColoredDataScaler "Answer a new view on this scaler" | view | view _ self new. view model: aColoredDataScaler. ^view! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:37'! onAspect: aSymbol ^self on: (RVMColoredDataScaler aspect: aSymbol)! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:17'! openOn: aColoredDataScaler "RVMColoredDataScalerView openOn: RVMColoredDataScaler exampleInstance" "Open a new view on this scaler" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 200@40. topView maximumSize: 300@80. topView addSubView: (self on: aColoredDataScaler). topView label: 'Aspect Data Scaler'. topView controller open! ! !RVMColoredDataScalerView class methodsFor: 'instance creation' stamp: 'ssa 9/19/2008 12:35'! openOnAspect: aSymbol "RVMColoredDataScalerView openOnAspect:#bytesUsed" self openOn: (RVMColoredDataScaler aspect: aSymbol)! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:21'! aspectLabel ^'#',self coreIndex printString,' ',self aspect! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:27'! coreIndex "Answer the value of coreIndex" coreIndex isNil ifTrue:[self coreIndex: 1]. ^ coreIndex! ! !RVMCoreAspectTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:27'! coreIndex: anObject "Set the value of coreIndex" coreIndex _ anObject! ! !RVMCoreAspectTrace methodsFor: 'updating' stamp: 'ssa 11/17/2008 17:09'! addData "Assume a multi valued data source" self add:((RVMMonitor lastSample perform: self aspect) at: self coreIndex + 1)! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:46'! allView "Answer a view showing my color and aspect" | view | view _ RVMView new. view model: self. view addSubView: self muteButton in: (0@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self coreIndexButton in: (1/10@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self colorButton in: (2/10@0 extent: (1/10) @ 1) borderWidth:1. view addSubView: self aspectButton in: ((3/10)@0 extent: (7/10) @ 1) borderWidth:1. ^view! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:20'! aspectButton "Answer an aspect button connect to my aspect" ^RVMAspectLabelView on: self getAllAspectsWith: [RVMMulticoreSample coreAspects] getCurrentAspectWith: #aspect setNewAspectWith: #aspect:.! ! !RVMCoreAspectTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:34'! coreIndexButton "Answer an aspect button connect to my aspect" ^RVMCoreIndexView on: self getCoreIndex:#coreIndex setCoreIndex: #coreIndex: getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:14'! monitorAllCoreAspectsForCore: anInteger "RVMCoreAspectTrace monitorAllCoreAspectsForCore: 1" | traces colors | colors _ (Color wheel: RVMMulticoreSample coreAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. RVMMulticoreSample coreAspects do:[:aspect| traces add:(self coreIndex: anInteger aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'All core aspects for core #',anInteger printString! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 00:21'! monitorAllCoreAspectsForCoreFromUser "RVMCoreAspectTrace monitorAllCoreAspectsForCoreFromUser" self monitorAllCoreAspectsForCore: RVMMonitor coreIndexFromUser! ! !RVMCoreAspectTrace class methodsFor: 'common uses' stamp: 'ssa 1/1/1970 01:21'! monitorAspects: someAspects forCore: anInteger "RVMCoreAspectTrace monitorAspects: #(bytecodeCounts bytesUseds) forCore: 1" | traces colors | colors _ (Color wheel: someAspects size saturation: 1.0 brightness: 0.7) readStream. traces _ OrderedCollection new. someAspects do:[:aspect| traces add:(self coreIndex: anInteger aspect: aspect size: 100 color: colors next)]. RVMStripChartView openOnTraces: traces titled:'Selected aspects for core #',anInteger printString! ! !RVMCoreAspectTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:32'! coreIndex: anIndex aspect: aSymbol size: anInteger color: aColor | trace | trace _ self aspect: aSymbol size: anInteger color: aColor. trace coreIndex: anIndex. ^trace! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:44'! exampleInstance "RVMCoreAspectTrace exampleInstance" ^self coreIndex: 1 aspect: #bytesUseds size: 100 color: Color blue! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:16'! exampleView1 "RVMCoreAspectTrace exampleView1" RVMStripChartView openOnTrace: self exampleInstance! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:24'! exampleView2 "RVMCoreAspectTrace exampleView2" | traces | traces _ OrderedCollection new. traces add:(self coreIndex: 1 aspect: #bytecodeCounts size: 200 color: Color blue). traces add:(self coreIndex: 1 aspect: #bytesUseds size: 200 color: Color red). traces add:(self coreIndex: 1 aspect: #yieldCounts size: 200 color: Color green). RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:07'! exampleView3 "RVMCoreAspectTrace exampleView3" | traces | traces _ OrderedCollection new. 1 to: 4 do:[:core| traces add:(self coreIndex: core aspect: #bytecodeCounts size: 100 color: Color random). traces add:(self coreIndex: core aspect: #bytesUseds size: 100 color: Color random). traces add:(self coreIndex: core aspect: #yieldCounts size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:38'! exampleView4 "RVMCoreAspectTrace exampleView4" self exampleInstance aspectColorView demo! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:36'! exampleView5 "RVMCoreAspectTrace exampleView5" self exampleInstance allView demo! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:06'! exampleView6 "RVMCoreAspectTrace exampleView6" | traces | traces _ OrderedCollection new. 1 to: 10 do:[:core| traces add:(self coreIndex: core aspect: #bytecodeCounts size: 100 color: Color random). traces add:(self coreIndex: core aspect: #bytesUseds size: 100 color: Color random). traces add:(self coreIndex: core aspect: #yieldCounts size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMCoreAspectTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:09'! exampleView7 "RVMCoreAspectTrace exampleView7" | traces | traces _ OrderedCollection new. RVMMulticoreSample coreAspects do:[:aspect| traces add:(self coreIndex: 1 aspect: aspect size: 100 color: Color random)]. RVMStripChartView openOnTraces: traces! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:14'! controlActivity Cursor menu show. super controlActivity! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:14'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMCoreIndexController methodsFor: 'controlling' stamp: 'ssa 11/17/2008 17:10'! yellowButtonActivity | currentIndex maxIndex newIndex | currentIndex _ self view coreIndex. maxIndex _ self view availableIndicies. [newIndex _ FillInTheBlank request:'Enter a new core index between 0 and ',(maxIndex - 1)printString,':' initialAnswer: currentIndex printString. (newIndex isEmpty or:[(newIndex asNumber between: 0 and: maxIndex - 1) not])] whileTrue. newIndex asNumber = currentIndex ifTrue:[^self]. self view coreIndex: newIndex asNumber. self view displayView ! ! !RVMCoreIndexView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:36'! displayView | labelRect labelText labelForm | self okToDisplay ifFalse:[^self]. self uncache. labelText := self label asDisplayText. labelText foregroundColor: self foregroundColor backgroundColor: self backgroundColor. labelForm := labelText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: labelText boundingBox extent). labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self backgroundColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: nil. "Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated." ! ! !RVMCoreIndexView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:14'! defaultControllerClass ^RVMCoreIndexController! ! !RVMCoreIndexView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:24'! hear: something self displayView! ! !RVMCoreIndexView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:12'! update: aSymbol aSymbol = self getCoreIndex ifTrue:[self displayView ]. super update: aSymbol! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:18'! availableIndicies "Answer the number of indices available" ^self getAvailableIndicies isSymbol ifTrue:[self model perform: self getAvailableIndicies] ifFalse:["assume a block" self getAvailableIndicies value]! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! coreIndex ^self getCoreIndex isSymbol ifTrue:[self model perform: self getCoreIndex] ifFalse:["assume a block" self getCoreIndex value]! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! coreIndex: aValue self setCoreIndex isSymbol ifTrue:[self model perform: self setCoreIndex with: aValue] ifFalse:["assume a block" self setCoreIndex value: aValue]. ! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:18'! getAvailableIndicies "Answer the value of getAvailableIndicies" getAvailableIndicies isNil ifTrue:[self getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]]. ^ getAvailableIndicies! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:17'! getAvailableIndicies: anObject "Set the value of getAvailableIndicies" getAvailableIndicies _ anObject! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! getCoreIndex "Answer the value of getCoreIndex" getCoreIndex isNil ifTrue:[self getCoreIndex: #coreIndex]. ^ getCoreIndex! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! getCoreIndex: anObject "Set the value of getCoreIndex" getCoreIndex _ anObject! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:31'! label ^self coreIndex printString! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! setCoreIndex "Answer the value of setCoreIndex" setCoreIndex isNil ifTrue:[self setCoreIndex: #coreIndex:]. ^ setCoreIndex! ! !RVMCoreIndexView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! setCoreIndex: anObject "Set the value of setCoreIndex" setCoreIndex _ anObject! ! !RVMCoreIndexView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:30'! example "RVMCoreIndexView example" self exampleInstance demo! ! !RVMCoreIndexView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:30'! exampleInstance "RVMCoreIndexView exampleInstance" ^self on: RVMCoreAspectTrace exampleInstance getCoreIndex:#coreIndex setCoreIndex: #coreIndex: getAvailableIndicies: [RVMMonitor lastSample groupStats groupSize]! ! !RVMCoreIndexView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:28'! on: aModel getCoreIndex: getter setCoreIndex: setter getAvailableIndicies: maxIndexGetter | view | view _ self new. view model: aModel; getCoreIndex: getter; setCoreIndex: setter; getAvailableIndicies: maxIndexGetter. ^view! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryMessage "Answer the tally for this message." ^aboutToWriteReadMostlyMemoryMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryMessage: aValue "Answer the tally for this message." aboutToWriteReadMostlyMemoryMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryResponse "Answer the tally for this message." ^aboutToWriteReadMostlyMemoryResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! aboutToWriteReadMostlyMemoryResponse: aValue "Answer the tally for this message." aboutToWriteReadMostlyMemoryResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! addObjectFromSnapshotMessage "Answer the tally for this message." ^addObjectFromSnapshotMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! addObjectFromSnapshotMessage: aValue "Answer the tally for this message." addObjectFromSnapshotMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextJustTestingMessage "Answer the tally for this message." ^allocateOrRecycleContextJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextJustTestingMessage: aValue "Answer the tally for this message." allocateOrRecycleContextJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextMessage "Answer the tally for this message." ^allocateOrRecycleContextMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! allocateOrRecycleContextMessage: aValue "Answer the tally for this message." allocateOrRecycleContextMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterBoolMessage "Answer the tally for this message." ^broadcastInterpreterBoolMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterBoolMessage: aValue "Answer the tally for this message." broadcastInterpreterBoolMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterDoublewordMessage "Answer the tally for this message." ^broadcastInterpreterDoublewordMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterDoublewordMessage: aValue "Answer the tally for this message." broadcastInterpreterDoublewordMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterWordMessage "Answer the tally for this message." ^broadcastInterpreterWordMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! broadcastInterpreterWordMessage: aValue "Answer the tally for this message." broadcastInterpreterWordMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! determineTalliesInOrder "Answer an array of tallies in the order they appear in the sample" ^self tallyOrder collect:[:label| self perform: label]! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsHereMessage "Answer the tally for this message." ^doAllRootsHereMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsHereMessage: aValue "Answer the tally for this message." doAllRootsHereMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereMessage "Answer the tally for this message." ^doAllRootsThereMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereMessage: aValue "Answer the tally for this message." doAllRootsThereMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereResponse "Answer the tally for this message." ^doAllRootsThereResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! doAllRootsThereResponse: aValue "Answer the tally for this message." doAllRootsThereResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage "Answer the tally for this message." ^enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage: aValue "Answer the tally for this message." enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse "Answer the tally for this message." ^enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse: aValue "Answer the tally for this message." enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage "Answer the tally for this message." ^enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage: aValue "Answer the tally for this message." enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse "Answer the tally for this message." ^enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse: aValue "Answer the tally for this message." enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage "Answer the tally for this message." ^enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage: aValue "Answer the tally for this message." enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse "Answer the tally for this message." ^enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse: aValue "Answer the tally for this message." enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushByMethodMessage "Answer the tally for this message." ^flushByMethodMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushByMethodMessage: aValue "Answer the tally for this message." flushByMethodMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! flushFreeContextsMessage "Answer the tally for this message." ^flushFreeContextsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! flushFreeContextsMessage: aValue "Answer the tally for this message." flushFreeContextsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushInterpreterCachesMessage "Answer the tally for this message." ^flushInterpreterCachesMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushInterpreterCachesMessage: aValue "Answer the tally for this message." flushInterpreterCachesMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushMethodCacheMessage "Answer the tally for this message." ^flushMethodCacheMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushMethodCacheMessage: aValue "Answer the tally for this message." flushMethodCacheMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushSelectiveMessage "Answer the tally for this message." ^flushSelectiveMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! flushSelectiveMessage: aValue "Answer the tally for this message." flushSelectiveMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! hereIsARootResponse "Answer the tally for this message." ^hereIsARootResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! hereIsARootResponse: aValue "Answer the tally for this message." hereIsARootResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! initiateBarrierMessage "Answer the tally for this message." ^initiateBarrierMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! initiateBarrierMessage: aValue "Answer the tally for this message." initiateBarrierMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginMessage "Answer the tally for this message." ^loadFunctionFromPluginMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginMessage: aValue "Answer the tally for this message." loadFunctionFromPluginMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginResponse "Answer the tally for this message." ^loadFunctionFromPluginResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! loadFunctionFromPluginResponse: aValue "Answer the tally for this message." loadFunctionFromPluginResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! newValueForOopMessage "Answer the tally for this message." ^newValueForOopMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! newValueForOopMessage: aValue "Answer the tally for this message." newValueForOopMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! noMoreRootsResponse "Answer the tally for this message." ^noMoreRootsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! noMoreRootsResponse: aValue "Answer the tally for this message." noMoreRootsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! rawData "Answer the tally for this message." ^rawData! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! rawData: aValue "Answer the tally for this message." rawData _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! recycleContextIfPossibleMessage "Answer the tally for this message." ^recycleContextIfPossibleMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! recycleContextIfPossibleMessage: aValue "Answer the tally for this message." recycleContextIfPossibleMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! respondToBarrierMessage "Answer the tally for this message." ^respondToBarrierMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! respondToBarrierMessage: aValue "Answer the tally for this message." respondToBarrierMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! returnContextMessage "Answer the tally for this message." ^returnContextMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! returnContextMessage: aValue "Answer the tally for this message." returnContextMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveJustTestingMessage "Answer the tally for this message." ^runPrimitiveJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveJustTestingMessage: aValue "Answer the tally for this message." runPrimitiveJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveMessage "Answer the tally for this message." ^runPrimitiveMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveMessage: aValue "Answer the tally for this message." runPrimitiveMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveResponse "Answer the tally for this message." ^runPrimitiveResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! runPrimitiveResponse: aValue "Answer the tally for this message." runPrimitiveResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreMessage "Answer the tally for this message." ^sampleOneCoreMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreMessage: aValue "Answer the tally for this message." sampleOneCoreMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreResponse "Answer the tally for this message." ^sampleOneCoreResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! sampleOneCoreResponse: aValue "Answer the tally for this message." sampleOneCoreResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsMessage "Answer the tally for this message." ^scanCompactOrMakeFreeObjectsMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsMessage: aValue "Answer the tally for this message." scanCompactOrMakeFreeObjectsMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsResponse "Answer the tally for this message." ^scanCompactOrMakeFreeObjectsResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! scanCompactOrMakeFreeObjectsResponse: aValue "Answer the tally for this message." scanCompactOrMakeFreeObjectsResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! talliesInOrder "Answer an array of tallies in the order they appear in the sample" ^self talliesInOrderCache! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:05'! talliesInOrderCache "Answer the value of talliesInOrderCache" talliesInOrderCache isNil ifTrue:[self talliesInOrderCache: self determineTalliesInOrder]. ^ talliesInOrderCache! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:04'! talliesInOrderCache: anObject "Set the value of talliesInOrderCache" talliesInOrderCache _ anObject! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:16'! tallyOrder "Answer an array of tally names in the order they appear in the sample" "RVMMulticoreSample primitiveCapture at: 8" ^self class tallyOrder! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingMessage "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlJustTestingMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingMessage: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlJustTestingMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingResponse "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlJustTestingResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlJustTestingResponse: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlJustTestingResponse _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlMessage "Answer the tally for this message." ^updateEnoughInterpreterToTransferControlMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateEnoughInterpreterToTransferControlMessage: aValue "Answer the tally for this message." updateEnoughInterpreterToTransferControlMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateWholeInterpreterMessage "Answer the tally for this message." ^updateWholeInterpreterMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! updateWholeInterpreterMessage: aValue "Answer the tally for this message." updateWholeInterpreterMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! verifyInterpreterAndHeapMessage "Answer the tally for this message." ^verifyInterpreterAndHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! verifyInterpreterAndHeapMessage: aValue "Answer the tally for this message." verifyInterpreterAndHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! wroteReadMostlyMemoryMessage "Answer the tally for this message." ^wroteReadMostlyMemoryMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! wroteReadMostlyMemoryMessage: aValue "Answer the tally for this message." wroteReadMostlyMemoryMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapMessage "Answer the tally for this message." ^zapUnusedPortionOfHeapMessage! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapMessage: aValue "Answer the tally for this message." zapUnusedPortionOfHeapMessage _ aValue! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapResponse "Answer the tally for this message." ^zapUnusedPortionOfHeapResponse! ! !RVMCoreMessageTally methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:22'! zapUnusedPortionOfHeapResponse: aValue "Answer the tally for this message." zapUnusedPortionOfHeapResponse _ aValue! ! !RVMCoreMessageTally class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:00'! fastForData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. tally allocateOrRecycleContextMessage: (data at: 1). tally allocateOrRecycleContextJustTestingMessage: (data at: 2). tally recycleContextIfPossibleMessage: (data at: 3). tally flushInterpreterCachesMessage: (data at: 4). tally flushMethodCacheMessage: (data at: 5). tally flushByMethodMessage: (data at: 6). tally flushSelectiveMessage: (data at: 7). tally addObjectFromSnapshotMessage: (data at: 8). tally updateWholeInterpreterMessage: (data at: 9). tally updateEnoughInterpreterToTransferControlMessage: (data at: 10). tally updateEnoughInterpreterToTransferControlJustTestingMessage: (data at: 11). tally updateEnoughInterpreterToTransferControlJustTestingResponse: (data at: 12). tally zapUnusedPortionOfHeapMessage: (data at: 13). tally zapUnusedPortionOfHeapResponse: (data at: 14). tally verifyInterpreterAndHeapMessage: (data at: 15). tally doAllRootsThereMessage: (data at: 16). tally doAllRootsThereResponse: (data at: 17). tally doAllRootsHereMessage: (data at: 18). tally hereIsARootResponse: (data at: 19). tally newValueForOopMessage: (data at: 20). tally noMoreRootsResponse: (data at: 21). tally scanCompactOrMakeFreeObjectsMessage: (data at: 22). tally scanCompactOrMakeFreeObjectsResponse: (data at: 23). tally returnContextMessage: (data at: 24). tally runPrimitiveMessage: (data at: 25). tally runPrimitiveJustTestingMessage: (data at: 26). tally runPrimitiveResponse: (data at: 27). tally loadFunctionFromPluginMessage: (data at: 28). tally loadFunctionFromPluginResponse: (data at: 29). tally broadcastInterpreterDoublewordMessage: (data at: 30). tally broadcastInterpreterWordMessage: (data at: 31). tally broadcastInterpreterBoolMessage: (data at: 32). tally sampleOneCoreMessage: (data at: 33). tally sampleOneCoreResponse: (data at: 34). tally initiateBarrierMessage: (data at: 35). tally respondToBarrierMessage: (data at: 36). tally aboutToWriteReadMostlyMemoryMessage: (data at: 37). tally aboutToWriteReadMostlyMemoryResponse: (data at: 38). tally wroteReadMostlyMemoryMessage: (data at: 39). tally flushFreeContextsMessage: (data at: 40). tally enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage: (data at: 41). tally enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse: (data at: 42). tally enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage: (data at: 43). tally enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse: (data at: 44). tally enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage: (data at: 45). tally enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse: (data at: 46). ^tally! ! !RVMCoreMessageTally class methodsFor: 'instance creation' stamp: 'dmu 1/1/1970 00:02'! forMessageNames: aCollectionOfMessageNames andData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. 1 to: data size do:[:index| tally perform:((aCollectionOfMessageNames at: index),':') asSymbol with:(data at: index)]. ^tally! ! !RVMCoreMessageTally class methodsFor: 'code generation' stamp: 'ssa 3/26/2009 10:14'! adaptToNewTallyMessages "RVMCoreMessageTally adaptToNewTallyMessages" "Change this class to work with the new messages" "BE SURE TO UPDATE tallyOrder MESSAGE IF THE TALLY ORDER CHANGES" | messageNames code index | messageNames _ (RVMMulticoreSample primitiveCapture at: 8) asOrderedCollection. messageNames add: 'rawData'. RVMObject subclass: #RVMCoreMessageTally instanceVariableNames: messageNames asArray classVariableNames: '' poolDictionaries: '' category: 'RVM-Monitoring'. code _ 'fastForData: data "Answer a new instance of me initialized to tally these messages" | tally | tally := self new. tally rawData: data. '. index _ 0. messageNames remove: 'rawData'. messageNames do:[:messageName| index _ index + 1. code _ code, 'tally ',messageName,': (data at: ',index printString,'). ']. code _ code,'^tally'. RVMCoreMessageTally class compile: code classified:'instance creation' notifying:nil. RVMCoreMessageTally removeCategory: 'accessing'. messageNames do:[:selector| code _ selector,' "Answer the tally for this message." ^',selector. RVMCoreMessageTally compile: code classified:'accessing' notifying:nil. code _ selector,': aValue "Answer the tally for this message." ',selector,' _ aValue'. RVMCoreMessageTally compile: code classified:'accessing' notifying:nil]. ! ! !RVMCoreMessageTally class methodsFor: 'accessing' stamp: 'ssa 3/26/2009 10:15'! tallyOrder "Answer an array of tally names in the order they appear in the sample" "RVMMulticoreSample primitiveCapture at: 8" ^#(#allocateOrRecycleContextMessage #allocateOrRecycleContextJustTestingMessage #recycleContextIfPossibleMessage #flushInterpreterCachesMessage #flushMethodCacheMessage #flushByMethodMessage #flushSelectiveMessage #addObjectFromSnapshotMessage #updateWholeInterpreterMessage #updateEnoughInterpreterToTransferControlMessage #updateEnoughInterpreterToTransferControlJustTestingMessage #updateEnoughInterpreterToTransferControlJustTestingResponse #zapUnusedPortionOfHeapMessage #zapUnusedPortionOfHeapResponse #verifyInterpreterAndHeapMessage #doAllRootsThereMessage #doAllRootsThereResponse #doAllRootsHereMessage #hereIsARootResponse #newValueForOopMessage #noMoreRootsResponse #scanCompactOrMakeFreeObjectsMessage #scanCompactOrMakeFreeObjectsResponse #returnContextMessage #runPrimitiveMessage #runPrimitiveJustTestingMessage #runPrimitiveResponse #loadFunctionFromPluginMessage #loadFunctionFromPluginResponse #broadcastInterpreterDoublewordMessage #broadcastInterpreterWordMessage #broadcastInterpreterBoolMessage #sampleOneCoreMessage #sampleOneCoreResponse #initiateBarrierMessage #respondToBarrierMessage #aboutToWriteReadMostlyMemoryMessage #aboutToWriteReadMostlyMemoryResponse #wroteReadMostlyMemoryMessage #flushFreeContextsMessage #enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage #enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse #enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage #enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse #enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage #enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse) ! ! !RVMDataScaler methodsFor: 'private' stamp: 'ssa 11/4/2008 15:50'! setMax: aValue "No side effects" max _ aValue. self range:nil! ! !RVMDataScaler methodsFor: 'private' stamp: 'ssa 11/4/2008 15:50'! setMin: aValue "No side effects" min _ aValue. self range:nil! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 11/4/2008 15:08'! adjustMax "Adjust my max based on my observedMax" | newMax | self maxLocked ifTrue:[^self]. newMax _ self max max: self observedMax. self max = newMax ifTrue:[^self]. self outOfRangeDetected: true. self max: newMax! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 11/4/2008 15:09'! adjustMin "Adjust my min based on my observedMin" | newMin | self minLocked ifTrue:[^self]. newMin _ self min min: self observedMin. self min = newMin ifTrue:[^self]. self outOfRangeDetected: true. self min: newMin! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:40'! automatic "Set to automatic scaling mode. This mode expands the min/max over time to adapt to the data being observed. Send the message #resetScaling to flush historical min/max and rescale." self automaticScaling: true. self resetScaling! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:40'! manual "Turn off automatic scaling mode. Stops adapting min/max" self automaticScaling: false. ! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/6/2008 16:28'! resetObservations "Reset my memory of min/max observations and my min/max as well once the first data value is observed." self observedMin:nil. self observedMax: nil.! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 00:15'! resetOutOfRangeDetector "Reset my out of range detector" self outOfRangeDetected: false.! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/6/2008 16:29'! resetScaling "Reset my memory of min/max observations and my min/max as well once the first data value is observed." min _ nil. max _ nil. observedMin _ nil. observedMax _ nil. range _ nil! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 10/7/2008 17:35'! scale: someData "Answer a number between 0-100 representing the percentage location of this data between my min and max" self lastObserved: someData. self observedMin:(self observedMin min: someData). self observedMax:(self observedMax max: someData). someData <= self min ifTrue:[^0]. someData >= self max ifTrue:[^100]. ^someData - self min * 100.0 / self range ! ! !RVMDataScaler methodsFor: 'scaling data' stamp: 'ssa 1/1/1970 01:10'! setRangeToObserved "Set my min and max to what I have observed in my data scaling" min _ self observedMin. max _ self observedMax. self range: nil ! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:57'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #notDefinedYet]. ^ aspect! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:56'! aspect: anObject "Set the value of aspect" aspect _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:39'! automaticScaling "Answer the value of automaticScaling" automaticScaling isNil ifTrue:[self automaticScaling: false]. ^ automaticScaling! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:39'! automaticScaling: anObject "Set the value of automaticScaling" automaticScaling _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:33'! lastObserved "Answer the value of lastObserved" lastObserved isNil ifTrue:[self lastObserved: 0]. ^ lastObserved! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/14/2008 21:33'! lastObserved: anObject "Set the value of lastObserved" lastObserved _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:08'! max "Answer the value of max" max isNil ifTrue:[^1]. ^ max! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/19/2008 10:53'! max: aNumber "Set the value of max" max _ min isNil ifTrue:[aNumber] ifFalse:[aNumber max: self min]. self range:nil! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! maxLocked "Answer the value of maxLocked" maxLocked isNil ifTrue:[self maxLocked: false]. ^ maxLocked! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! maxLocked: anObject "Set the value of maxLocked" maxLocked _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:22'! min "Answer the value of min" self pinAtZero ifTrue:[^0]. min isNil ifTrue:[self min: 100000000]. ^ min! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/19/2008 10:53'! min: aNumber "Set the value of min" min _ max isNil ifTrue:[aNumber] ifFalse:[aNumber min: self max]. self range:nil! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! minLocked "Answer the value of minLocked" minLocked isNil ifTrue:[self minLocked: false]. ^ minLocked! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:20'! minLocked: anObject "Set the value of minLocked" minLocked _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:45'! observedMax "Answer the value of observedMax" observedMax isNil ifTrue:[self observedMax: -10000000000]. ^ observedMax! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:43'! observedMax: aNumber "Set the value of observedMax" observedMax _ aNumber. self automaticScaling ifTrue:[self adjustMax]! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 19:45'! observedMin "Answer the value of observedMin" observedMin isNil ifTrue:[self observedMin: 10000000000]. ^ observedMin! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:44'! observedMin: aNumber "Set the value of observedMin" observedMin _ aNumber. self automaticScaling ifTrue:[self adjustMin]! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:14'! outOfRangeDetected "Answer the value of outOfRangeDetected" outOfRangeDetected isNil ifTrue:[self outOfRangeDetected: false]. ^ outOfRangeDetected! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/2/2008 19:12'! outOfRangeDetected: anObject "Set the value of outOfRangeDetected" outOfRangeDetected _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:22'! pinAtZero "Answer the value of pinAtZero" pinAtZero isNil ifTrue:[self pinAtZero: false]. ^ pinAtZero! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:21'! pinAtZero: anObject "Set the value of pinAtZero" pinAtZero _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:50'! pinMinAtZero self pinAtZero: true! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:52'! range "Answer the value of range" range isNil ifTrue:[self range: (self max - self min)]. ^ range! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:52'! range: anObject "Set the value of range" range _ anObject! ! !RVMDataScaler methodsFor: 'accessing' stamp: 'ssa 10/6/2008 20:50'! unpinMinAtZero self pinAtZero: false! ! !RVMDataScaler methodsFor: 'data generation' stamp: 'ssa 9/13/2008 19:33'! atRandom "Answer a random data value in my range." ^ self range atRandom + self min! ! !RVMDataScaler methodsFor: 'autocoding' stamp: 'ssa 9/13/2008 20:13'! harden "Compile a method into RVMMonitor that will reproduce a scaler like me." RVMMonitor autocodeScalerMethodForScaler: self! ! !RVMDataScaler methodsFor: 'user interface' stamp: 'ssa 9/13/2008 22:38'! open | cs | cs _ RVMColoredDataScaler new. cs scaler: self. cs color: Color random. cs open! ! !RVMDataScaler methodsFor: 'printing' stamp: 'ssa 10/6/2008 16:19'! printOn: aStream super printOn: aStream. aStream nextPutAll: 'min:',self min printString,' max:',self max printString! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 17:59'! example1 "RVMDataScaler example1" | scaler | scaler _ self min: 5 max: 15. 1 to: 20 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:00'! example2 "RVMDataScaler example2" | scaler | scaler _ self min: 0.5 max: 1.5. 0.1 to: 2.0 by: 0.1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:02'! example3 "RVMDataScaler example3" | scaler | scaler _ self min: -5 max: -1. -7 to: 0 by: 1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 9/13/2008 18:02'! example4 "RVMDataScaler example4" | scaler | scaler _ self min: -5 max: 5. -7 to: 7 by: 1 do:[:value| Transcript cr;show: 'value: ',value printString,' => scaled: ',(scaler scale: value) printString]! ! !RVMDataScaler class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:48'! exampleInstance "RVMDataScaler exampleInstance" ^self aspect: #bytesUseds min: 0 max: 100000! ! !RVMDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 19:57'! aspect: aSymbol min: minValue max: maxValue "Answer a new data scaler with this range." | scaler | scaler _ self new. scaler aspect: aSymbol. scaler min: minValue. scaler max: maxValue. ^scaler! ! !RVMDataScaler class methodsFor: 'instance creation' stamp: 'ssa 9/13/2008 19:58'! min: minValue max: maxValue "Answer a new data scaler with this range." ^self aspect: nil min: minValue max: maxValue! ! !RVMDynamicScoper commentStamp: 'dmu 8/9/2011 11:41' prior: 0! I implement dynamic scoping; crucial for multithreaded apps, by added instance variables to Process on demand.! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/11/2011 21:53'! addAccessMessage: selectorToAdd sending: selectorToSend | methodText | (self class methodDictionary includesKey: selectorToAdd) ifTrue: [^ self]. methodText _ selectorToAdd, ' ^ Processor thisProcess ', selectorToSend. self class compileSilently: methodText classified: self createdMethodCategory! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 18:21'! addProcessAccessMethod: accessSelector | mungedAccessSelector mungedInstanceVariable methodText | mungedAccessSelector _ self munge: accessSelector. (Process methodDictionary includesKey: mungedAccessSelector) ifTrue: [^ self]. mungedInstanceVariable _ mungedAccessSelector. methodText _ mungedAccessSelector, ' "created by ', self className, '>addProcessAccessMethod:" ^', mungedInstanceVariable. Process compileSilently: methodText classified: self createdMethodCategory! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/11/2011 22:59'! addProcessAssignmentMethod: assignmentSelector | mungedAssignmentSelector mungedInstanceVariable methodText | mungedAssignmentSelector _ self munge: assignmentSelector. mungedInstanceVariable _ mungedAssignmentSelector copyFrom: 1 to: mungedAssignmentSelector size - 1. (Process methodDictionary includesKey: mungedAssignmentSelector) ifTrue: [^ self]. methodText _ mungedAssignmentSelector, ' x "created by ', self className, '>addProcessAssignmentMethod:" ', mungedInstanceVariable, ' := x'. Process compileSilently: methodText classified: self createdMethodCategory! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 15:24'! addProcessInstanceVariable: variableName | mungedName | mungedName _ self munge: variableName. (Process allInstVarNames includes: mungedName) ifTrue: [^ self]. Process addInstVarName: mungedName! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/11/2011 21:54'! addRegistrationMessage: selectorToAdd sending: selectorToSend | methodText | (self class methodDictionary includesKey: selectorToAdd) ifTrue: [^ self]. methodText _ selectorToAdd, ' x Processor thisProcess ', selectorToSend, ' x'. self class compileSilently: methodText classified: self createdMethodCategory! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 18:53'! computeAccessAndAssignmentSelectorsFrom: selector into: resultBlock | selectorWithoutPrefix assignmentSelector accessSelector | selectorWithoutPrefix _ self stripPrefixFrom: selector. self ensureSingleArgument: selectorWithoutPrefix. assignmentSelector _ selectorWithoutPrefix. accessSelector _ selectorWithoutPrefix copyFrom: 1 to: selectorWithoutPrefix size - 1. resultBlock value: accessSelector asSymbol value: assignmentSelector asSymbol! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/11/2011 21:52'! createAndRunRegistrationMessage: aMessage | assignmentSelector accessSelector | self computeAccessAndAssignmentSelectorsFrom: aMessage selector into: [:acc :agn | accessSelector _ acc. assignmentSelector _ agn]. self addProcessInstanceVariable: accessSelector. self addProcessAccessMethod: accessSelector. self addProcessAssignmentMethod: assignmentSelector. self addRegistrationMessage: aMessage selector sending: (self munge: assignmentSelector). self addAccessMessage: accessSelector sending: (self munge: accessSelector). ^ self perform: aMessage selector with: aMessage argument! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 18:38'! createdMethodCategory ^ '*created-by-', self className! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 14:55'! doesNotUnderstand: aMessage | selector | selector _ aMessage selector. (selector beginsWith: self prefix) ifFalse: [^ super doesNotUnderstand: aMessage]. ^ self createAndRunRegistrationMessage: aMessage! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 12:00'! ensureSingleArgument: aSelector (aSelector indexOf: $:) = aSelector size ifFalse: [self error: 'expecting a one-arg keyword']! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 18:37'! munge: identifierOrKeyword | asCreated | asCreated _ 'AsCreatedBy', self name. ^ ( identifierOrKeyword last = $: ifTrue: [ (identifierOrKeyword copyFrom: 1 to: identifierOrKeyword size - 1), asCreated, ':' ] ifFalse: [ identifierOrKeyword, asCreated ] ) asSymbol! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 12:05'! prefix ^'register'! ! !RVMDynamicScoper class methodsFor: 'as yet unclassified' stamp: 'dmu 8/9/2011 12:05'! stripPrefixFrom: dnuSelector ^ (dnuSelector copyFrom: self prefix size + 1 to: dnuSelector size) withFirstCharacterDownshifted! ! !RVMExperiment class methodsFor: 'as yet unclassified' stamp: 'dmu 1/1/1970 00:04'! do: aBlock | ms s | RVMMulticoreSample capture. ms := Time millisecondsToRun: aBlock. s := RVMMulticoreSample capture. Transcript cr; show: 'ms: '; show: ms; show: ' yields: '; show: s yieldCounts sum; show: ' bytecodes: '; show: s bytecodeCounts sum; show: ' total/unforced interruptCheckCounts: '; show: s interruptCheckCounts sum; show: '/'; show: s unforcedInterruptCheckCounts sum; cr; show: 'receive tallies: ', s receiveTallySum printString! ! !RVMExperiment class methodsFor: 'as yet unclassified' stamp: 'dmu 1/1/1970 00:14'! testCompiler self do: [Benchmark new testCompiler]! ! !RVMGlobalHeapStats methodsFor: 'testing' stamp: 'ssa 7/21/2008 10:09'! isGlobal ^true! ! !RVMGlobalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:09'! scope "Answer my scope" ^'Global'! ! !RVMGridLocationController methodsFor: 'controlling' stamp: 'ssa 11/16/2008 02:19'! redButtonActivity | point grid box coord cellSize | point _ Sensor cursorPoint. grid _ RVMMonitor extent. box _ self view insetDisplayBox. cellSize _ box extent // grid + 1. coord _ (point - box origin //(cellSize))+1. self view point: coord. view displayView. ! ! !RVMGridLocationController methodsFor: 'controlling' stamp: 'ssa 11/15/2008 16:11'! yellowButtonActivity ! ! !RVMGridLocationView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 01:29'! displayView | gridExtent point boxes box dot | self canvas extent > self insetDisplayBox extent ifTrue:[self canvas:nil; canvas]. self okToDisplay ifFalse:[^self]. point _ self point. self uncache. self canvas displayOn: Display at:self insetDisplayBox origin. gridExtent _ self gridExtent. dot _ Form extent:1@1. dot fillBlack. boxes _ self insetDisplayBox subDivideBy: gridExtent. 1 to: gridExtent x do:[:x| 1 to: gridExtent y do:[:y| point = (x@y) ifTrue:[box _ boxes at: y-1*gridExtent x+x. Display fill: (box origin - (0@1) extent:box extent)rounded fillColor: Color black]. (point = (0@0)) & ((x@y)=(1@1)) ifTrue:[box _ boxes at: y-1*gridExtent x+x.. Display fill: box rounded fillColor: Color red]. (point > (gridExtent)) & ((x@y)=(gridExtent)) ifTrue:[box _ boxes at: y-1*gridExtent x+x.. Display fill: box rounded fillColor: Color red]. ]]! ! !RVMGridLocationView methodsFor: 'displaying' stamp: 'ssa 11/15/2008 23:46'! drawGridOnCanvas | gridExtent boxes dot leftX rightX boxHeight boxWidth lineY lineX topY bottomY | self canvas fillWhite. gridExtent _ self gridExtent. dot _ Form extent:1@1. dot fillBlack. leftX _ self canvas boundingBox origin x. rightX _ self canvas boundingBox corner x. topY _ self canvas boundingBox origin y. bottomY _ self canvas boundingBox corner y. boxes _ self canvas boundingBox subDivideBy: gridExtent. boxHeight _ boxes first height. boxWidth _ boxes first width . lineY _ topY + boxHeight -2. lineX _ leftX + boxWidth . 1 to: gridExtent x do:[:x| x > (gridExtent x - 2) ifFalse:[ self canvas drawLine: dot from: (leftX@lineY) to: rightX@lineY clippingBox: self canvas boundingBox rule: Form paint fillColor: Color black. lineY _ lineY + boxHeight]. 1 to: gridExtent y do:[:y| y > (gridExtent y - 1) ifFalse:[ self canvas drawLine: dot from: lineX@topY to: lineX@bottomY clippingBox: self canvas boundingBox rule: Form paint fillColor: Color black. lineX _ lineX + boxWidth]. ]]! ! !RVMGridLocationView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:56'! hear: something self displayView! ! !RVMGridLocationView methodsFor: 'updating' stamp: 'ssa 11/16/2008 00:32'! newFrame self canvas: nil. self canvas! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 18:03'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (Form extent: self insetDisplayBox extent). self drawGridOnCanvas]. ^ canvas! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 18:02'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:31'! extentGetter "Answer the value of extentGetter" extentGetter isNil ifTrue:[self extentGetter: [8@7]]. ^ extentGetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! extentGetter: anObject "Set the value of extentGetter" extentGetter _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 13:05'! gridExtent ^self extentGetter isSymbol ifTrue:[self model perform: self extentGetter] ifFalse:[self extentGetter value]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:37'! point ^self pointGetter isSymbol ifTrue:[self model perform: self pointGetter] ifFalse:[self pointGetter value]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/16/2008 02:20'! point: aPoint self pointSetter isSymbol ifTrue:[self model perform: self pointSetter with: aPoint] ifFalse:[self pointSetter value: aPoint]! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:31'! pointGetter "Answer the value of pointGetter" pointGetter isNil ifTrue:[self pointGetter: [self extent atRandom]]. ^ pointGetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! pointGetter: anObject "Set the value of pointGetter" pointGetter _ anObject! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:32'! pointSetter "Answer the value of pointSetter" pointSetter isNil ifTrue:[self pointSetter: ["do nothing by default"]]. ^ pointSetter! ! !RVMGridLocationView methodsFor: 'accessing' stamp: 'ssa 11/13/2008 12:30'! pointSetter: anObject "Set the value of pointSetter" pointSetter _ anObject! ! !RVMGridLocationView methodsFor: 'controller access' stamp: 'ssa 11/15/2008 16:10'! defaultControllerClass ^RVMGridLocationController! ! !RVMGridLocationView class methodsFor: 'instance creation' stamp: 'ssa 11/13/2008 12:47'! on: aModel pointGetter: pointGetterBlockOrSelector pointSetter: pointSetterBlockOrSelector extentGetter: extentGetterBlockOrSelector | v | v _ self new. v model: aModel. v pointGetter: pointGetterBlockOrSelector. v pointSetter: pointSetterBlockOrSelector. v extentGetter: extentGetterBlockOrSelector. ^v ! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 11:36'! changeObjectsSourceSourceTo: aString Cursor wait showWhile:[ self view objectsSourceSource: aString. self view changed:#objectsSourceSource]! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 09:45'! redButtonActivity self view hear:nil! ! !RVMGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 11:33'! yellowButtonActivity | menu action choices | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:[self view inspect]. menu addLine. choices _ {'Object withAllSubclasses'. 'View withAllSubclasses'. 'Number allSubclasses'. #line. 'String allInstances'. 'Array allInstances'. 'Collection allSubInstances' }. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action:choice]]. action := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. (action isKindOf: BlockContext) ifTrue:[^action value]. action notNil ifTrue:[self changeObjectsSourceSourceTo: action]! ! !RVMGroupLocatorView methodsFor: 'framing' stamp: 'ssa 11/27/2008 09:33'! newFrame self boxes: nil. self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 14:42'! drawBackgroundCanvas | alt count lighter rowWidth | rowWidth _ RVMMonitor extent x . alt _ false. count _ 0. lighter _ Color black lighter lighter. self boxes do:[:r| self backgroundCanvas fill: r fillColor: (alt ifTrue:[Color black]ifFalse:[lighter]). "self backgroundCanvas border: r width: 1 fillColor: Color gray." alt _ alt not. count _ count + 1. rowWidth odd ifFalse:[count = rowWidth ifTrue:[alt _ alt not. count _ 0]]]. ! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 3/31/2009 18:06'! drawLocations | dot coreExtent amt index rect pt dotSize realRect label | coreExtent _ RVMMonitor extent. dotSize _(self boxes first width // ((self countsPerCore size // self boxes size)max:1))min:self boxes first width //2 max:1. dot _ Form dotOfSize: dotSize color: self color. 0 to: coreExtent x - 1 do:[:x| 0 to: coreExtent y - 1 do:[:y| amt _ self countsPerCore occurrencesOf: (index _ y*coreExtent x+x). rect _ (realRect _ self boxes at: index + 1) insetBy: dot offset abs. label _ amt printString asDisplayText . label foregroundColor: Color red backgroundColor: Color transparent. label displayOn: self canvas at: realRect origin - (0@3) clippingBox: realRect rule: Form paint fillColor: Color red. "amt timesRepeat:[pt _ rect asRandomPoint. dot displayOn: self canvas at: pt clippingBox: realRect rule: Form paint fillColor:nil]"]. ]! ! !RVMGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 09:19'! drawOnCanvas self backgroundCanvas displayOn: self canvas at: 0@0. self drawLocations! ! !RVMGroupLocatorView methodsFor: 'displaying' stamp: 'ssa 11/27/2008 09:24'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self drawOnCanvas. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. ! ! !RVMGroupLocatorView methodsFor: 'listening' stamp: 'ssa 11/27/2008 09:31'! hear: something "Update my display" self countsPerCore: nil. self drawOnCanvas. self displayView! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:35'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[self backgroundCanvas: (Form extent: self insetDisplayBox extent depth: Display depth). self drawBackgroundCanvas]. ^ backgroundCanvas! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:30'! boxes "Answer the value of boxes" boxes isNil ifTrue:[self boxes: ((self insetDisplayBox subDivideRoundedBy: RVMMonitor extent) collect:[:r| r translateBy: self insetDisplayBox origin negated])]. ^ boxes! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! boxes: anObject "Set the value of boxes" boxes _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:35'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (Form extent: self insetDisplayBox extent depth: Display depth)]. ^ canvas! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:08'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:27'! changeColorTo: aColor "Set the value of color" self color: aColor. self hear:nil! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:15'! color "Answer the value of color" color isNil ifTrue:[self color: Color red]. ^ color! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:15'! color: anObject "Set the value of color" color _ anObject! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ads 1/30/2011 15:20'! countsPerCore "Answer the value of countsPerCore" countsPerCore isNil ifTrue:[self countsPerCore: (self objects asOrderedCollection collect:[:obj| RVMOperations isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMOperations getCoreHolding:obj]]) asBag]. ^ countsPerCore! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:14'! countsPerCore: aBag "Set the value of countsPerCore, a Bag of coreIndicies with occurenceCounts showing how many of my objects reside in each core" countsPerCore _ aBag! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:16'! objects "Answer my colection of objects to locate." ^self objectsSource isSymbol ifTrue:[self model perform: self objectsSource] ifFalse:[self objectsSource value]! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:16'! objectsSource "Answer the value of objectsSource, a Block that returns a collection of objects to locate. Can also be a SYmbol, a message selector to send to my model" objectsSource isNil ifTrue:[self objectsSource: [String allInstances]]. ^ objectsSource! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 09:17'! objectsSource: aBlockOrSymbol "Set the value of objectsSource" objectsSource _ aBlockOrSymbol! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 10:34'! objectsSourceSource | code | self objectsSource isSymbol ifTrue:[^self objectsSource printString]. code _ self objectsSource decompile printString. (code beginsWith:'{[') &(code endsWith:']}') ifTrue:[code _ code copyFrom: 3 to: code size - 2]. ^code! ! !RVMGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 11:34'! objectsSourceSource: aText | value aString | aString _ aText asString. ( aString withBlanksTrimmed beginsWith:'#') ifTrue:[value _ Compiler new evaluate: aString in: nil to: nil notifying: nil ifFail: [^ false]. self model perform: value. "test to make sure it works before installing"] ifFalse:[value _ Compiler new evaluate: '[',aString,']' in: nil to: nil notifying: nil ifFail: [^ false]]. self objectsSource:value. self hear:nil. ^true "tell the editor its OK"! ! !RVMGroupLocatorView methodsFor: 'controller access' stamp: 'ssa 11/27/2008 09:57'! defaultControllerClass ^RVMGroupLocatorController! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 09:57'! on: aModel objectsSource: aBlockOrSelector "(RVMGroupLocatorView on: Smalltalk objectsSource:#values) demo" "(RVMGroupLocatorView on: nil objectsSource:[String allInstances]) demo" | v | v _ self new. v model: aModel. v objectsSource: aBlockOrSelector. ^v! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 14:10'! openOn: aModel objectsSource: aBlockOrSelector labeled: aString "RVMGroupLocatorView openOn: Smalltalk objectsSource:#allClasses labeled:'All Classes'" "RVMGroupLocatorView openOn: nil objectsSource:[Array allInstances] labeled: 'All Arrays'" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 150@150. topView maximumSize: 800@800. v := self on: aModel objectsSource: aBlockOrSelector. v borderWidth:1. topView addSubView: v viewport:(0@0 extent: 150@150). topView label: aString. topView controller open! ! !RVMGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 13:36'! openWithSourceEditorOn: aModel objectsSource: aBlockOrSelector "RVMGroupLocatorView openWithSourceEditorOn: Smalltalk objectsSource:#values" "RVMGroupLocatorView openWithSourceEditorOn: nil objectsSource:[Array allInstances]" | topView v ptv cbv | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 150@170. topView maximumSize: 400@425. v := self on: aModel objectsSource: aBlockOrSelector. v borderWidth:1. ptv _ PluggableTextView on: v text:#objectsSourceSource accept:#objectsSourceSource:. ptv borderWidth:1. cbv _ RVMColorButtonView on: v colorGetter:#color colorSetter:#changeColorTo:. cbv borderWidth:1. topView addSubView: v viewport:(0@0 extent: 150@150). topView addSubView: cbv viewport:(0@150 extent:20@20). topView addSubView: ptv viewport:(20@150 extent:130@20). topView label: 'Group Locator'. topView controller open! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! coreIndices "Answer a collection of points that give my core indicies as row@column" | points | points _ OrderedCollection new. 1 to: self height do:[:h| 1 to: self width do:[:w| h*w-1 + w > self groupSize ifTrue:[^points "handle odd last row case"]. points add: w@h]]. ^points! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'ssa 11/13/2008 09:41'! extent "Answer the dimensions of my tile grid" ^self width @ self height! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! groupSize ^ groupSize! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! groupSize: x groupSize _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! height ^ height! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! height: x height _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainRank ^ mainRank! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainRank: x mainRank _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainX ^ mainX! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainX: x mainX _ x! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:55'! mainY ^ mainY! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! mainY: y mainY _ y! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:56'! remaining ^ remaining! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:57'! remaining: r remaining _ r! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:00'! width ^ width! ! !RVMGroupStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:01'! width: x width _ x! ! !RVMGroupStats methodsFor: 'initialize-release' stamp: 'ssa 8/19/2008 10:56'! initializeFastFrom: data self mainX:(data at: 2). self mainY: (data at: 4). self mainRank: (data at: 6). self width: (data at: 8). self height: (data at: 10). self groupSize: (data at: 12). self remaining: (data at: 14). ! ! !RVMGroupStats methodsFor: 'initialize-release' stamp: 'dmu 8/15/2008 22:07'! initializeFrom: data 1 to: data size by: 2 do: [:i| self perform: ((data at: i), ':') asSymbol with: (data at: i + 1) ]! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:06'! allocationsSinceLastQuery "Answer the number of object allocations since the last query" allocationsSinceLastQuery isNil ifTrue:[^0]. ^allocationsSinceLastQuery! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:07'! allocationsSinceLastQuery: count "Set the number of object allocations since the last query" allocationsSinceLastQuery := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:04'! bytesLeft "Answer the number of bytes left in this heap" bytesLeft isNil ifTrue:[^0]. ^bytesLeft! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:05'! bytesLeft: count "Set the number of bytes left in this heap" bytesLeft := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 10/4/2008 08:38'! bytesUsed "Answer the number of bytes used in this heap" bytesUsed isNil ifTrue:[^0]. ^bytesUsed ! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:04'! bytesUsed: count "Set the number of bytes used in this heap" bytesUsed := count! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:06'! compactionsSinceLastQuery "Answer the number of object compactions since the last query" compactionsSinceLastQuery isNil ifTrue:[^0]. ^compactionsSinceLastQuery! ! !RVMHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:07'! compactionsSinceLastQuery: count "Set the number of object compactions since the last query" compactionsSinceLastQuery := count! ! !RVMHeapStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:27'! readWrite "Answer the value of readWrite" readWrite isNil ifTrue:[self readWrite: true]. ^ readWrite! ! !RVMHeapStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:27'! readWrite: anObject "Set the value of readWrite" readWrite _ anObject! ! !RVMHeapStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:27'! newReadMostly ^self new readWrite: false ! ! !RVMHeapStats class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:28'! newReadWrite ^self new readWrite: true! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ads 1/30/2011 23:31'! addCoreAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to monitor' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view addAspect: selectedAspect]]. self view drawOnCanvas. self view displayView ! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 10:26'! changeRescaleCounter | result | self view dontDisplayWhile:[ result _ FillInTheBlank request:'How many samples between rescaling?' initialAnswer: self view rescaleCounterDefault printString. result isNil ifFalse:[result _ result asNumber max:0. self view rescaleCounterDefault:result]]. self view displayView! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:52'! inspectView self view inspect! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 11/11/2008 17:37'! redButtonActivity ((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:55'! removeAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view aspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select aspect to remove:' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view removeAspect: selectedAspect]. ]. self view drawOnCanvas. self view displayView ! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:06'! rescale self view resetScaling. self view displayView! ! !RVMKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 09:06'! yellowButtonActivity | menu answer onlyOne maxed | onlyOne _ self view aspectCount = 1. maxed _ self view aspectCount = 4. self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:#inspectView. menu add:'Rescale' action:#rescale. menu add:'Change Rescale Counter' action:#changeRescaleCounter. onlyOne ifTrue:[menu add: 'Change aspect' action: #changeAspect. menu addLine]. maxed ifFalse:[ menu add: 'Add core aspect' action: #addCoreAspect]. onlyOne ifFalse:[menu addLine. menu add: 'Remove aspect' action: #removeAspect.]. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMKiviatController methodsFor: 'menu messages' stamp: 'ssa 10/7/2008 19:38'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'Core aspects' action: #core. menu add: 'Test aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. self view aspect = newAspect ifTrue:[^self]. self view aspect: newAspect]. self view resetScaling. self view drawOnCanvas. self view displayView! ! !RVMKiviatController methodsFor: 'menu messages' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height scalerIndex result | (self view scalers size = 1 or:[self view commonScale])ifFalse:[result _ (PopUpMenu labelArray:self view aspects) startUpWithCaption:'Adjust the scale of which aspect?'. result = 0 ifTrue:[^self]. scalerIndex _ result]ifTrue:[scalerIndex _ 1]. maxView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) max] valueSetter:[:v|(view scalerAt: scalerIndex) setMax:v. view drawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) min] valueSetter:[:v|(view scalerAt: scalerIndex) setMin:v. view drawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[(view scalerAt: scalerIndex) resetScaling. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[(view scalerAt: scalerIndex) setRangeToObserved. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: (view scalerAt: scalerIndex) label: 'Automatic Scaling' checkState: [(view scalerAt: scalerIndex) automaticScaling] whenChecked: [(view scalerAt: scalerIndex) automatic. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [(view scalerAt: scalerIndex) manual. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: (view aspects at: scalerIndex). height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. self scalerAdjusters add: topView. topView controller open! ! !RVMKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:32'! scalerAdjusters "Answer the value of scalerAdjusters" scalerAdjusters isNil ifTrue:[self scalerAdjusters: OrderedCollection new]. ^ scalerAdjusters! ! !RVMKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:31'! scalerAdjusters: anObject "Set the value of scalerAdjusters" scalerAdjusters _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ads 1/30/2011 23:31'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #test0to100]. ^ aspect! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:23'! aspect: anObject "Set the value of aspect" aspect _ anObject. self lastAverage: nil. self lastTotal: nil. self topView == self ifFalse:[self topView relabel: anObject asString]! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:22'! aspectCount ^1! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[ self backgroundCanvas:(ColorForm extent: self canvasExtent depth:8). self spokePens do:[:pen| pen destForm: backgroundCanvas]. self drawBackgroundCanvas.]. ^ backgroundCanvas! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:53'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject ! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:08'! blinker "Answer the value of blinker" blinker isNil ifTrue:[self blinker: true]. self blinker: blinker not. ^ blinker! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:08'! blinker: anObject "Set the value of blinker" blinker _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self canvasExtent depth:8)]. ^ canvas! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:11'! canvas: anObject "Set the value of canvas" canvas _ anObject. self webPen destForm: anObject. self spokePens:nil! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:00'! canvasExtent "Answer the extent of my canvas" ^self insetDisplayBox extent ! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:38'! center ^self canvas center! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:08'! centerMargin "the distance from center to the start of a spoke" ^20! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:13'! diameter "Answer the smallest square diameter for this view's box" ^self canvas height < self canvas width ifTrue:[self canvas height- (self labelRowCount * 10)] ifFalse:[self canvas width - 20]! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground "Answer the value of drawingBackground" drawingBackground isNil ifTrue:[self drawingBackground: false]. ^ drawingBackground! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground: anObject "Set the value of drawingBackground" drawingBackground _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:52'! firstDisplay "Answer the value of firstDisplay" firstDisplay isNil ifTrue:[self firstDisplay: false]. ^ firstDisplay! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 15:13'! firstDisplay: anObject "Set the value of firstDisplay" firstDisplay _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 01:18'! labelRowCount "How many rows of labels will I have?" ^2! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastAverage "Answer the value of lastAverage" lastAverage isNil ifTrue:[self lastAverage: 0]. ^ lastAverage! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastAverage: anObject "Set the value of lastAverage" lastAverage _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastTotal "Answer the value of lastTotal" lastTotal isNil ifTrue:[self lastTotal: 0]. ^ lastTotal! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 02:25'! lastTotal: anObject "Set the value of lastTotal" lastTotal _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! majorTicLength ^8! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:35'! majorTicSpacing ^self spokeLength / (self numberOfMajorTics - 1) asFloat! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicLength ^4! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicSpacing ^self majorTicSpacing /( self numberOfMinorTics + 1)! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:38'! numberOfMajorTics ^3! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! numberOfMinorTics ^1! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 13:56'! radius "Answer the smallest radius for this view's box" ^self diameter // 2! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: self rescaleCounterDefault]. ^ rescaleCounter! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 15:02'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault "Answer the value of rescaleCounterDefault" rescaleCounterDefault isNil ifTrue:[self rescaleCounterDefault: 10]. ^ rescaleCounterDefault! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault: anObject "Set the value of rescaleCounterDefault" rescaleCounterDefault _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: RVMDataScaler new automatic]. ^ scaler! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 22:07'! spokeColor "Answer the value of spokeColor" spokeColor isNil ifTrue:[self spokeColor: Color gray lighter lighter]. ^ spokeColor! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! spokeColor: anObject "Set the value of spokeColor" spokeColor _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:30'! spokeLength ^self radius - self centerMargin - 5! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! spokePens "Answer the value of spokePens" spokePens isNil ifTrue:[self spokePens: self initializeSpokePens]. ^ spokePens! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! spokePens: anObject "Set the value of spokePens" spokePens _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor "Answer the value of webColor" webColor isNil ifTrue:[self webColor: Color blue]. ^ webColor! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor: anObject "Set the value of webColor" webColor _ anObject! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:06'! webPen "Answer the value of webPen" webPen isNil ifTrue:[self webPen: Pen new. webPen color: self webColor. webPen defaultNib:2. webPen combinationRule: Form over. webPen destForm: self canvas]. ^ webPen! ! !RVMKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:29'! webPen: anObject "Set the value of webPen" webPen _ anObject! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:19'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:34'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. origin _ self backgroundCanvas boundingBox leftCenter - adjustIcon boundingBox leftCenter + (4@0). adjustIcon displayOn: self backgroundCanvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:18'! drawBackgroundCanvas self drawingBackground: true. self backgroundCanvas fillWhite. self drawSpokes. self drawAdjustScaleIcon. self drawingBackground: false ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:07'! drawCounterOnCanvas | counterLabel | self scaler automaticScaling ifFalse:[^self]. counterLabel _ ('rescale in: ',self rescaleCounter printString ) asDisplayText. counterLabel displayOn: self canvas at: self canvas boundingBox bottomRight -(counterLabel width@90). ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:29'! drawLabelsOnCanvas | minLabel maxLabel aspectLabel avgLabel totalLabel start | aspectLabel _ self aspect asString asDisplayText. aspectLabel foregroundColor: self webColor backgroundColor: Color transparent. aspectLabel displayOn: self canvas at: (2 @ -4). minLabel _ ('min: ',self scaler min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',self scaler max printShowingMax3Digits) asDisplayText. minLabel foregroundColor: self webColor backgroundColor: Color transparent. maxLabel foregroundColor: self webColor backgroundColor: Color transparent. minLabel displayOn: self canvas at: 0@((aspectLabel height //2)-2)clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: 0@(start _ maxLabel height) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. avgLabel _ ('avg: ',self lastAverage printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',self lastTotal printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: self webColor backgroundColor: Color transparent. totalLabel foregroundColor: self webColor backgroundColor: Color transparent. totalLabel displayOn: self canvas at: 0@(start _start +(totalLabel height - 6)) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: 0@( start + (maxLabel height - 6)) clippingBox: self canvas boundingBox rule: Form paint fillColor:nil. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMajorTicUsing: pen pen turn:90; go: self majorTicLength/2;turn:180;down;go:self majorTicLength;up; turn:180; go: self majorTicLength/2;turn:-90! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMinorTicUsing: pen pen turn:90; go: self minorTicLength/2;turn:180;down;go:self minorTicLength;up; turn:180; go: self minorTicLength/2;turn:-90! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/8/2008 19:16'! drawOnCanvas self drawingBackground ifTrue:[^self]. self backgroundCanvas displayOn: self canvas at: 0@0. self drawCounterOnCanvas. self drawWeb. self drawLabelsOnCanvas. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 11/17/2008 13:25'! drawSpokes | pen label labelOffsets labelOffset mainIndex oldColor | mainIndex _ RVMMonitor mainRank + 1. 1 to: self spokePens size do:[:index| pen _ self spokePens at: index. oldColor _ pen color. index = mainIndex ifTrue:[pen color: Color red]. pen destForm: self backgroundCanvas. pen place: self center. pen up; go: self centerMargin. pen down;go: self spokeLength;up. label _ (index - 1) printString asDisplayText asParagraph asForm. self diameter < 300 ifTrue:[label _ label scaledToSize: 11@11]. labelOffsets _ {0@label height negated. 0@0. label width negated@0. label extent negated}. labelOffset _ labelOffsets at: ((index - 1// (self spokePens size / 4) + 1) min:4). label displayOn: self backgroundCanvas at: pen location + labelOffset clippingBox: self backgroundCanvas boundingBox rule: Form paint fillColor: nil. self drawTicsUsing: pen. pen color: oldColor] ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 11:54'! drawTicsUsing: pen pen up;place: self center;go:self centerMargin. self drawMajorTicUsing: pen. self numberOfMajorTics - 1 timesRepeat:[ self numberOfMinorTics timesRepeat:[ pen go: self minorTicSpacing. self drawMinorTicUsing: pen]. pen go: self minorTicSpacing. self drawMajorTicUsing: pen]. ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 14:18'! drawWeb self drawingBackground ifTrue:[^self]. self placeSpokePens. self webPen color: self webColor. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up ! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:39'! placeSpokePens | data tot | data _ RVMMonitor lastSample perform: self aspect. tot _ 0. self spokePens size = data size ifFalse: [self resetAfterCoreCountChange]. data with: self spokePens do:[:datum :pen| tot _ tot + datum. pen up;place: self center;go:self centerMargin. pen go:(self spokeLength /100.0*(self scaler scale: datum))]. self lastTotal: tot. self lastAverage: tot / data size! ! !RVMKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:38'! resetAfterCoreCountChange self spokePens: nil. backgroundCanvas _ nil! ! !RVMKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 15:20'! firstFrame ! ! !RVMKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 19:20'! newFrame self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMKiviatView methodsFor: 'scaling' stamp: 'ssa 10/8/2008 18:52'! resetScaling self scaler resetScaling. ! ! !RVMKiviatView methodsFor: 'initialize-release' stamp: 'ssa 10/6/2008 16:42'! initializeSpokePens | pens numberOfSpokes spacing center pen | pens _ OrderedCollection new. numberOfSpokes _ RVMMonitor coreCount. spacing _ 360 / numberOfSpokes asFloat. center _ self insetDisplayBox center. numberOfSpokes timesRepeat:[ pen _ Pen new. pen defaultNib:1. pen combinationRule: Form over. pen color: self spokeColor. pen place: center. pen north. pen turn: pens size * spacing. pens add: pen]. ^pens! ! !RVMKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 21:41'! release "self controller scalerAdjusters do:[:each| each topView controller closeAndUnscheduleNoTerminate]. self controller scalerAdjusters: nil." super release! ! !RVMKiviatView methodsFor: 'displaying' stamp: 'ssa 11/12/2008 13:16'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self firstDisplay ifFalse:[self firstDisplay:true. self drawOnCanvas]. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. self blinker ifTrue:[(Form dotOfSize:5) displayOn: Display at: self insetDisplayBox center] ! ! !RVMKiviatView methodsFor: 'controller access' stamp: 'ssa 10/6/2008 13:35'! defaultControllerClass ^RVMKiviatController! ! !RVMKiviatView methodsFor: 'listening' stamp: 'dmu 2/6/2009 22:35'! hear: something "Update my traces and redisplay" self firstDisplay ifFalse:[^self]. self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self resetScaling.]. self drawingBackground ifTrue:[^self]. self drawOnCanvas. self displayView! ! !RVMKiviatView commentStamp: '<historical>' prior: 0! I'm a kiviat chart for displaying core aspect data! !RVMKiviatView class methodsFor: 'examples' stamp: 'ssa 10/6/2008 16:00'! example "RVMKiviatView example" self openOnAspect: #bytesUseds! ! !RVMKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 13:58'! openOnAspect: aSymbol "RVMKiviatView example" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@250. topView maximumSize: 600@500. v := self new. v borderWidth:1. v aspect: aSymbol. topView addSubView: v. topView label: v aspect. topView controller open! ! !RVMLabelView methodsFor: 'displaying' stamp: 'ssa 9/14/2008 20:45'! displayView | labelRect labelText labelForm | labelText := self label asDisplayText . labelText foregroundColor: self backgroundColor backgroundColor: self foregroundColor. labelForm := labelText asParagraph asForm scaledToSize:(self insetDisplayBox extent min: labelText boundingBox extent). labelRect := self insetDisplayBox. Display fill: labelRect fillColor: self foregroundColor. labelForm displayOn: Display at: labelRect center - labelForm boundingBox center clippingBox: labelRect rule: Form paint fillColor: labelText foregroundColor. ! ! !RVMLabelView methodsFor: 'accessing' stamp: 'ssa 8/26/2008 22:55'! label "Answer the value of label" label isNil ifTrue:[^'no label yet']. ^label! ! !RVMLabelView methodsFor: 'accessing' stamp: 'ssa 8/26/2008 22:54'! label: anObject "Set the value of label" label := anObject! ! !RVMLabelView class methodsFor: 'instance creation' stamp: 'ssa 8/26/2008 23:02'! label: aString | view | view := self new. view label: aString. ^view! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:31'! failedFetchRequestsSinceLastQuery "Answer how many fetch requests failed since the last query" failedFetchRequestsSinceLastQuery isNil ifTrue:[^0]. ^failedFetchRequestsSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:29'! failedFetchRequestsSinceLastQuery: count "Set how many fetch requests failed since the last query" failedFetchRequestsSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 11:09'! objectsFetchedSinceLastQuery "Answer how many objects were fetched into this local heap since the last query" objectsFetchedSinceLastQuery isNil ifTrue:[^0]. ^objectsFetchedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 11:09'! objectsFetchedSinceLastQuery: count "Set how many objects were fetched into this local heap since the last query" objectsFetchedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:32'! objectsFlushedSinceLastQuery "Answer how many objects were flushed since the last query" objectsFlushedSinceLastQuery isNil ifTrue:[^0]. ^objectsFlushedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:32'! objectsFlushedSinceLastQuery: count "Set how many objects were flushed since the last query" objectsFlushedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:26'! overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery "Answer how many 'cramden' requests were denied since the last query" overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery isNil ifTrue:[^0]. ^overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:27'! overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery: count "Set how many 'cramden' requests were denied since the last query" overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery := count! ! !RVMLocalHeapStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:11'! scope "Answer my scope" ^'Local'! ! !RVMLocalHeapStats methodsFor: 'testing' stamp: 'ssa 7/21/2008 10:11'! isLocal ^true! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCount "Answer the value of gcCount" gcCount isNil ifTrue:[self gcCount: nil]. ^gcCount! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCount: anObject "Set the value of gcCount" gcCount := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCycles "Answer the value of gcCycles" gcCycles isNil ifTrue:[self gcCycles: nil]. ^gcCycles! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcCycles: anObject "Set the value of gcCycles" gcCycles := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcMilliseconds "Answer the value of gcMilliseconds" gcMilliseconds isNil ifTrue:[self gcMilliseconds: nil]. ^gcMilliseconds! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:15'! gcMilliseconds: anObject "Set the value of gcMilliseconds" gcMilliseconds := anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:52'! readMostlyHeapStats "Answer the value of readMostlyHeapStats" readMostlyHeapStats isNil ifTrue:[self readMostlyHeapStats: RVMHeapStats newReadMostly]. ^ readMostlyHeapStats! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readMostlyHeapStats: anObject "Set the value of readMostlyHeapStats" readMostlyHeapStats _ anObject! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readWriteHeapStats "Answer the value of readWriteHeapStats" readWriteHeapStats isNil ifTrue:[self readWriteHeapStats: RVMHeapStats newReadWrite]. ^ readWriteHeapStats! ! !RVMMemorySystemStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! readWriteHeapStats: anObject "Set the value of readWriteHeapStats" readWriteHeapStats _ anObject! ! !RVMMinMaxView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 20:54'! example "RVMMinMaxView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@50. topView maximumSize: 200@100. topView addSubView: self exampleInstance. topView label: 'MinMax'. topView controller open! ! !RVMMinMaxView class methodsFor: 'examples' stamp: 'ssa 9/17/2008 13:56'! exampleInstance | scaler | scaler _ RVMDataScaler exampleInstance. ^self on: scaler getMin: [scaler min] setMin:[:v| scaler min: v] getMax: [scaler max] setMax: [:v| scaler max: v]. ! ! !RVMMinMaxView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:53'! on: aModel getMin: getMin setMin: setMin getMax: getMax setMax: setMax | view v | view _ self new. view addSubView: (v _ RVMValueView on: aModel valueGetter: getMin valueSetter: setMin label:'m'). view addSubView: (RVMValueView on: aModel valueGetter: getMax valueSetter: setMax label:'M') above: v. ^view! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:27'! closeRecordingFile "Close the recording file" self recordingFile flush;close. self recordingFile: nil! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:41'! isRecording ^self recordingMode ~= #off! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 15:32'! loadChunkedSamplesFromRecordingFile "Load the samples with the data on a file supplied by the user" | fs data chunk readChunkTime compileChunkTime | fs _ StandardFileMenu oldFileStreamWithPattern:'*.recording'. fs isNil ifTrue:[^self inform:'No file to load']. Cursor read showWhile:[ data _ OrderedCollection new. [fs atEnd] whileFalse:[Transcript cr;show:'reading data chunk #',(data size + 1) printString. readChunkTime _ Time millisecondsToRun:[chunk _ fs nextChunk]. Transcript cr;show:(readChunkTime //1000 )printString,' secs to read chunk'. compileChunkTime _ Time millisecondsToRun:[data add: (Compiler evaluate: chunk)]. Transcript cr;show: (compileChunkTime //1000) printString,' secs to compile chunk'. ]. fs close. self recordingMode = #file ifTrue:[self recordingMode: #loop]. self recordingMode = #loop ifTrue:[data _ data asCircularCollection]. self samples: data asCircularCollection]. self changed:#recordingMode ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 19:45'! loadSamplesFromRecordingFile "Load the samples with the data on a file supplied by the user" | fs data readChunkTime | fs _ StandardFileMenu oldFileStreamWithPattern:'*.recording'. fs isNil ifTrue:[^self inform:'No file to load']. Cursor read showWhile:[ data _ OrderedCollection new. [fs atEnd] whileFalse:[Transcript cr;show:'reading data chunk #',(data size + 1) printString. readChunkTime _ Time millisecondsToRun:[data add: (RVMSampleReader dearchiveRawDataFrom: fs)]. Transcript cr;show:(readChunkTime /1000.0)printString,' seconds to read'. ]. fs close. self recordingMode = #file ifTrue:[self recordingMode: #loop]. self recordingMode = #loop ifTrue:[data _ data asCircularCollection. self sampleLimit: data size]. self samples: data asCircularCollection]. self changed:#recordingMode ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:41'! openRecordingFile "Open the recording file" self recordingFile ensureOpen! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:37'! recordAllToFile: aCollection "Record each of these elements to the recording file in chunk format" aCollection do:[:each| self recordToFile: each]! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 15:33'! recordChunkToFile: anObject "Record the object on the recording file in chunk format" anObject printOn: self recordingFile. self recordingFile nextPut:$!!;cr;cr! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:45'! recordSample: someData "Record this sample data based on the recording mode" self recordingMode = #off ifTrue:[^self]. self recordingMode = #file ifTrue:[^self recordToFile: someData]. self samples add: someData! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/28/2008 19:27'! recordToFile: anObject "Record the object on the recording file in archiver format" RVMSampleWriter archiveRawData: anObject on:self recordingFile ! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:24'! recordingFile "Answer an appropriately named file for recording samples, open and ready." RecordingFile isNil ifTrue:[self recordingFile: self recordingFileFromUser]. ^RecordingFile! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:28'! recordingFile: aFile "Set an appropriately named file for recording samples, open and ready." RecordingFile isNil ifFalse:[RecordingFile close]. RecordingFile _ aFile! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:31'! recordingFileFromUser "Answer an appropriately named file for recording samples, open and ready." ^FileStream newFileNamed:'rvm-samples.recording'! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 23:19'! recordingMode "Recording modes are #off, #loop, #file, and #long" RecordingMode isNil ifTrue:[RecordingMode _ #loop]. ^RecordingMode! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/19/2008 00:52'! recordingMode: nextMode "Recording modes are #off, #loop, #file, and #long" | lastMode | lastMode _ RecordingMode. lastMode = nextMode ifTrue:[^self]. self switchFrom: lastMode to: nextMode. RecordingMode _ nextMode. self changed:#recordingMode! ! !RVMMonitor class methodsFor: 'recording' stamp: 'ssa 10/18/2008 22:21'! switchFrom: lastMode to: nextMode. "Switch recording modes. Recording modes are #off, #loop, #file, and #long" nextMode = #off ifTrue:[ lastMode = #loop ifTrue:["do nothing, leave collection in place"]. lastMode = #long ifTrue:["do nothing, leave collection in place"]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #loop ifTrue:[ lastMode = #off ifTrue:[self samples: (RVMCircularCollection new:self sampleLimit)]. lastMode = #long ifTrue:[self samples: (RVMCircularCollection withAll: self samples)]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #long ifTrue:[ lastMode = #off ifTrue:[self samples: OrderedCollection new]. lastMode = #loop ifTrue:[self samples: self samples asOrderedCollection]. lastMode = #file ifTrue:[self closeRecordingFile]]. nextMode = #file ifTrue:[self openRecordingFile; recordAllToFile: self samples]. ! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 1/1/1970 00:18'! coreCount ^self lastSample groupStats groupSize! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 11/27/2008 14:45'! extent ^self lastSample extent! ! !RVMMonitor class methodsFor: 'queries' stamp: 'ssa 11/17/2008 13:22'! mainRank ^self lastSample groupStats mainRank ! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/17/2008 17:11'! coreIndexFromUser "RVMMonitor coreIndexFromUser" "Answer a valid coreINdex from the user for my current configuration" | maxIndex newIndex | maxIndex _ self coreCount. [newIndex _ FillInTheBlank request:'Enter a core index between 0 and ',(maxIndex - 1) printString,':' initialAnswer: '1'. (newIndex isEmpty or:[(newIndex asNumber between: 0 and: maxIndex - 1) not])] whileTrue. ^newIndex asNumber! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ads 1/30/2011 15:21'! dashboard "RVMMonitor dashboard " | topView samplingCheck turboCheck gcButton benchButton subViewCount sampleButton clearSamplesButton forgetButton shuffle56Button shuffle4Button multistripButton systemAspectsButton coreAspectsButton inspectSampleButton testAspectCheck spiderButton bytesUsedsSpiderButton delayTimingCheck recordingOptionsButton allToReadMostlyButton printAllHeapsButton printExecutionTraceButton printStackButton gridButton stripButton scanButton outlierButton locateClassesButton locatorButton locators4Button heartbeat spread56Button runningProcessesButton | topView := RVMStandardSystemView new . topView borderWidth:1. samplingCheck _ RVMCheckBoxView on: self label: 'Sampling' checkState: [self sampling] whenChecked: [self startSampling] whenUnchecked: [self stopSampling] monitor: true. turboCheck _ RVMCheckBoxView on: self label: 'Turbo' checkState: [self turboSampling] whenChecked: [self turboOn] whenUnchecked: [self turboOff] monitor: true. testAspectCheck _ RVMCheckBoxView on: self label: 'Test Aspects' checkState: [self showTestAspects] whenChecked: [self showTestAspects:true] whenUnchecked: [self showTestAspects:false] monitor: true. delayTimingCheck _ RVMCheckBoxView on: self label: 'Short Delay' checkState: [self delayTiming = #short] whenChecked: [self useShortDelay] whenUnchecked: [self useNormalDelay] monitor: true. heartbeat _ RVMCheckBoxView on: self label: 'Heartbeat' checkState: [self showHeartbeat] whenChecked: [self startHeartbeat] whenUnchecked: [self stopHeartbeat] monitor: true. sampleButton _ RVMButtonView label:'Take Sample' action:[RVMMonitor getSample; informListeners]. inspectSampleButton _ RVMButtonView label:'Inspect Sample' action:[RVMMonitor lastSample inspect]. clearSamplesButton _ RVMButtonView label:'Clear Samples' action:[RVMMonitor clearSamples]. recordingOptionsButton _ RVMButtonView label:'Recording Options' action:[RVMMonitor recordingControls]. forgetButton _ RVMButtonView label:'Forget Listeners' action:[RVMMonitor forgetListeners]. gcButton _ RVMButtonView label:'GC' action:[Transcript cr show:'GC: ',Smalltalk garbageCollect printString]. spread56Button _ RVMButtonView label:'Spread 56' action:[RVMOperations spreadFrom: 0 to: 55 moveRWtoRM: true moveRMtoRW: false]. shuffle56Button _ RVMButtonView label:'Shuffle:56' action:[RVMOperations shuffle:56]. shuffle4Button _ RVMButtonView label:'Shuffle:4' action:[RVMOperations shuffle:4]. allToReadMostlyButton _ RVMButtonView label:'All->readMostly' action:[RVMOperations moveAllToReadMostlyHeaps]. printAllHeapsButton _ RVMButtonView label:'Print BytesUsed' action:[RVMOperations printAllHeapsBytesUsed]. printExecutionTraceButton _ RVMButtonView label:'Print Trace' action:[RVMOperations printExecutionTrace]. printStackButton _ RVMButtonView label:'Print Stack' action:[RVMOperations printStack]. gridButton _ self relAbsButtonLabeled:'Tile Grid...' relAction:[RVMTileGridView example] absAction:[RVMTileGridScalerView example]. stripButton _ self relAbsButtonLabeled:'Tile Strip...' relAction:[RVMTileStripChartView example] absAction:[RVMTileStripChartScalerView example]. scanButton _ self relAbsButtonLabeled:'Tile Scan...' relAction:[RVMScanningStripChartView example] absAction:[RVMAbsScanningStripChartView example]. multistripButton _ RVMButtonView label:'Multi Strip' action:[RVMCoreAspectTrace exampleView1]. systemAspectsButton _ RVMButtonView label:'System Aspects' action:[RVMAspectTrace monitorAllSystemAspects]. coreAspectsButton _ RVMButtonView label:'Core Aspects' action:[RVMCoreAspectTrace monitorAllCoreAspectsForCoreFromUser]. runningProcessesButton _ RVMButtonView label:'Running Processes' action:[RVMAspectTrace exampleView8]. spiderButton _ RVMButtonView label:'Kiviat' action:[RVMMultiKiviatView exampleBytecodesAndProcessesRunning]. bytesUsedsSpiderButton _ RVMButtonView label:'heap size Kiviat' action:[RVMMultiKiviatView exampleBytesUsedTrioCommonPinned]. outlierButton _ RVMButtonView label:'Outlier...' action:[RVMMonitor outlierFromUser]. locateClassesButton _ RVMButtonView label:'Class Locator' action:[RVMGroupLocatorView openOn: Smalltalk objectsSource:#allClasses labeled:'All Classes']. locatorButton _ RVMButtonView label:'Group Locator' action:[RVMGroupLocatorView openWithSourceEditorOn: nil objectsSource:[Array allInstances]]. locators4Button _ RVMButtonView label:'4 Group Locator' action:[RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Collection withAllSubclasses]. [Object withAllSubclasses]. [View allSubInstances]} colors: nil]. benchButton _ RVMButtonView label:'testCompiler' action:[Cursor wait showWhile:[RVMExperiment testCompiler]]. topView addSubView: samplingCheck. topView addSubView: turboCheck below: samplingCheck. topView addSubView: testAspectCheck below: turboCheck. topView addSubView: delayTimingCheck below: testAspectCheck. topView addSubView: heartbeat below: delayTimingCheck. topView addSubView: sampleButton below: heartbeat. topView addSubView: inspectSampleButton below: sampleButton. topView addSubView: clearSamplesButton below: inspectSampleButton. topView addSubView: recordingOptionsButton below: clearSamplesButton. topView addSubView: forgetButton below: recordingOptionsButton. topView addSubView: gcButton below: forgetButton. topView addSubView: spread56Button below: gcButton. topView addSubView: shuffle56Button below: spread56Button. topView addSubView: shuffle4Button below: shuffle56Button. topView addSubView: allToReadMostlyButton below: shuffle4Button. topView addSubView: printAllHeapsButton below: allToReadMostlyButton. topView addSubView: printExecutionTraceButton below: printAllHeapsButton. topView addSubView: printStackButton below: printExecutionTraceButton. topView addSubView: gridButton below: printStackButton. topView addSubView: stripButton below: gridButton. topView addSubView: scanButton below: stripButton. topView addSubView: multistripButton below: scanButton. topView addSubView: systemAspectsButton below: multistripButton. topView addSubView: coreAspectsButton below: systemAspectsButton. topView addSubView: runningProcessesButton below: coreAspectsButton. topView addSubView: spiderButton below: runningProcessesButton. topView addSubView: bytesUsedsSpiderButton below: spiderButton. topView addSubView: outlierButton below: bytesUsedsSpiderButton. topView addSubView: locateClassesButton below: outlierButton. topView addSubView: locatorButton below: locateClassesButton. topView addSubView: locators4Button below: locatorButton. topView addSubView: benchButton below: locators4Button. topView label: 'RVM'. RVMMonitor forgetAll: topView allSubViews. RVMMonitor forget: topView. subViewCount _ topView subViews size. topView minimumSize: 120@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/13/2008 02:10'! outlierFromUser | menu result selectors labels aspects sel cores | selectors _ #(coreAspectSubset coreAspectSubsetAllocationCompaction coreAspectSubsetBytecodes coreAspectSubsetBytes coreAspectSubsetRunWait coreAspectSubsetYields allCoreAspects). labels _ #('selected aspects' 'allocation/compaction' 'bytecodes' 'bytes' 'run/wait' 'yields' 'all for a single core'). menu _ PopUpMenu labelArray: labels. result _ menu startUpWithCaption:'Which set of aspects for the Outlier?'. result = 0 ifTrue: [^self]. aspects _ RVMMultiAspectKiviatView perform: (sel _ selectors at: result). cores _ sel = #allCoreAspects ifTrue:[Array with: self coreIndexFromUser]ifFalse:[(1 to: RVMMonitor coreCount) asOrderedCollection]. RVMMultiAspectKiviatView openOnAspects: aspects forCores: cores titled:'Outliers: ',(labels at: result)! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 5/12/2010 10:16'! recordingControls "RVMMonitor recordingControls " | topView offRadio loopRadio subViewCount longRadio fileRadio loadButton radios | topView := RVMStandardSystemView new . radios _ RVMView new. topView borderWidth:1. RVMRadioButtonView testState:#(true false false false false). offRadio _ RVMRadioButtonView on: self label: 'stop recording' checkState: [RVMMonitor recordingMode = #off] whenChecked: [RVMMonitor recordingMode: #off] whenUnchecked: [] monitor: true. loopRadio _ RVMRadioButtonView on: self label: 'record last ',RVMMonitor sampleLimit printString,' samples' checkState: [RVMMonitor recordingMode = #loop] whenChecked: [RVMMonitor recordingMode: #loop] whenUnchecked: [] monitor: true. longRadio _ RVMRadioButtonView on: self label: 'record all samples' checkState: [RVMMonitor recordingMode = #long] whenChecked: [RVMMonitor recordingMode: #long] whenUnchecked: [] monitor: true. fileRadio _ RVMRadioButtonView on: self label: 'record all samples to a file' checkState: [RVMMonitor recordingMode = #file] whenChecked: [RVMMonitor recordingMode: #file] whenUnchecked: [] monitor: true. loadButton _ RVMButtonView label:'Load samples from file' action:[RVMMonitor loadSamplesFromRecordingFile]. radios addSubView: offRadio. radios addSubView: loopRadio below: offRadio. radios addSubView: longRadio below: loopRadio. radios addSubView: fileRadio below: longRadio. topView addSubView: radios. topView addSubView: loadButton below: radios. RVMMonitor forgetAll: topView allSubViews. RVMMonitor forget: topView. topView label: 'Recording Options'. subViewCount _ radios subViews size + topView subViews size - 1. topView minimumSize: 200@(subViewCount*28). topView maximumSize: 200@topView minimumSize y. topView controller open! ! !RVMMonitor class methodsFor: 'user interface' stamp: 'ssa 11/15/2008 23:30'! relAbsButtonLabeled: aTitle relAction: relAction absAction: absAction | menu result | ^RVMButtonView label: aTitle action: [menu _ PopUpMenu labelArray:#('Relative Scaling' 'Absolute Scaling'). result _ menu startUpWithCaption:'Which color scaling to use?'. result = 1 ifTrue: [relAction copy value]. result = 2 ifTrue: [absAction copy value]] copy! ! !RVMMonitor class methodsFor: 'test aspects' stamp: 'ssa 10/3/2008 15:06'! showTestAspects ShowTestAspects isNil ifTrue:[ShowTestAspects _ false]. ^ShowTestAspects! ! !RVMMonitor class methodsFor: 'test aspects' stamp: 'ssa 10/3/2008 15:06'! showTestAspects: aBoolean ShowTestAspects _ aBoolean! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:12'! clearSamples "Clear my collection of samples" Samples := nil. LastSample := nil.! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:19'! delaySamplingDuring: aBlock self sampling ifTrue:[self stopSampling. aBlock value. self startSampling] ifFalse:[aBlock value]! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:25'! delayTiming DelayTiming isNil ifTrue:[DelayTiming _ #normal]. ^DelayTiming! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:25'! delayTiming: aSymbol "#normal or #short" DelayTiming _ aSymbol! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ads 1/30/2011 15:21'! getSample "Get the next sample" LastSample := self turboSampling ifTrue:[RVMMulticoreSample captureFastest]ifFalse:[RVMMulticoreSample next]. RVMOperations isRVM & self isRecording ifTrue:[ self recordSample: LastSample rawData]. ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 11/15/2008 23:42'! lastSample "Answer the last recorded sample" LastSample isNil ifTrue:[self getSample]. ^LastSample ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 20:23'! normalDelayTiming ^self delayTiming = #normal! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/21/2008 11:56'! sampleLimit SampleLimit isNil ifTrue:[SampleLimit := 2]. ^SampleLimit! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 8/22/2008 09:42'! sampleLimit: anInteger SampleLimit := anInteger. self clearSamples! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/18/2008 22:14'! samples "Answer my collection of samples" Samples isNil ifTrue:[self samples:(RVMCircularCollection new:self sampleLimit)]. ^Samples! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/18/2008 22:14'! samples: aCollection "Set my collection of samples" Samples _ aCollection! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:19'! sampling "Am I current sampling?" ^SamplingProcess notNil! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ads 2/2/2011 14:52'! startSampling "RVMMonitor startSampling" "Start the sampling process" | delay timeToRun delayTime lastTime| lastTime _ Time now asSeconds. SamplingProcess notNil ifTrue:[self stopSampling]. SamplingProcess := [[ Sensor leftShiftDown & Sensor controlKeyPressed] whileFalse: [ "RVMOperations print: (Time now asSeconds - lastTime) printString,' seconds since last sample'." timeToRun _ Time millisecondsToRun: [self getSample]. lastTime _ Time now asSeconds. "RVMOperations print:'sampling took ',(timeToRun/1000.0) printString,' seconds'." delayTime _ self normalDelayTiming ifTrue:[10*timeToRun]ifFalse:[100 min: 10*timeToRun]. delay := Delay forMilliseconds: delayTime. self informListeners. RVMMulticoreSample flush. "clear sample buffers from monitor activity" delay wait]] newProcess. SamplingProcess name: 'RVMMonitor sampling process'. SamplingProcess resume ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 9/4/2008 15:00'! stopSampling "RVMMonitor stopSampling" "Stop the sampling process" SamplingProcess isNil ifFalse:[SamplingProcess terminate]. SamplingProcess := nil! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboOff "Turn off turboSampling" TurboSampling := false! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboOn "Turn on turboSampling" TurboSampling := true! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 1/1/1970 00:16'! turboSampling "Answer my turboSampling flag" TurboSampling isNil ifTrue:[TurboSampling := true]. ^TurboSampling! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:22'! useNormalDelay self delaySamplingDuring:[self delayTiming: #normal]. ! ! !RVMMonitor class methodsFor: 'sampling' stamp: 'ssa 10/7/2008 21:22'! useShortDelay self delaySamplingDuring:[self delayTiming: #short].! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 1/1/1970 00:07'! forget: someone self listeners remove: someone ifAbsent:[]! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 10/28/2008 19:54'! forgetAll: someListeners someListeners do:[:each| self forget: each]! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 1/1/1970 00:07'! forgetListeners Listeners := nil! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 8/25/2008 05:02'! inform: someone self listeners add: someone! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 2/18/2009 17:42'! informListeners self listeners do:[:each| each hear: self] " | sema | sema _ Semaphore new. self listeners do:[:each| [each hear: self. sema signal] copy fixTemps fork]. self listeners do: [:each| sema wait]" ! ! !RVMMonitor class methodsFor: 'listeners' stamp: 'ssa 8/25/2008 04:59'! listeners "Answer the list of listeners to me" Listeners isNil ifTrue:[Listeners := OrderedCollection new]. ^Listeners! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:03'! autocodeScalerMethodFor: aSelector "Autocode and install a default scaler method for the aspect found in this selector." "Note this also adds a class variable of the form SCALERaspect" | aspect code var | aspect _ aSelector allButLast:'Scaler' size. var _ 'SCALER',aspect. self addClassVarName: var. code _ aSelector,' "Answer the default scaler for ',aspect,'." ',var,' isNil ifTrue:[',var,' _ RVMDataScaler aspect: #',aspect,' min: 0 max: 100]. ^',var. self class compile: code classified:'scalers' notifying:nil! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:03'! autocodeScalerMethodForScaler: aDataScaler "Autocode and install a default scaler method for the aspect found in this selector." "Note this also adds a class variable of the form SCALERaspect" | aspect code var | aspect _ aDataScaler aspect. var _ 'SCALER',aspect. (self classVarNames includes: var) ifFalse:[self addClassVarName: var]. code _ aspect,'Scaler "Answer the default scaler for ',aspect,'." ',var,' isNil ifTrue:[',var,' _ RVMDataScaler aspect:#',aspect,' min: ',aDataScaler min printString,' max: ',aDataScaler max printString,']. ^',var. self class compile: code classified:'scalers' notifying:nil! ! !RVMMonitor class methodsFor: 'autocoding' stamp: 'ssa 1/1/1970 00:49'! doesNotUnderstand: aMessage "autocode a method for aMessage if its one I recognize." (aMessage selector isUnary & (aMessage selector endsWith: 'Scaler')) ifTrue:[self halt:'this should not be used anymore'. self autocodeScalerMethodFor: aMessage selector. ^self perform: aMessage selector]. ^super doesNotUnderstand: aMessage! ! !RVMMonitor class methodsFor: 'data generation' stamp: 'ssa 9/13/2008 19:40'! dataFor: anAspect "Answer a generated data value for this aspect, based on the range of its scaler" ^(self scalerFor:anAspect) atRandom! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:44'! coloredScalerFor: aspect "Answer an appropriate colored scaler for this aspect." ^RVMColoredDataScaler aspect: aspect! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:44'! coloredScalersFor: aspects "Answer an appropriate colored scalers for this aspect." ^aspects collect:[:each| self coloredScalerFor: each]! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 1/1/1970 00:02'! scalerFor: aspect "Answer an appropriate scalers for this aspect." [^RVMDataScaler new automatic]value. ^self perform: (aspect,'Scaler') asSymbol! ! !RVMMonitor class methodsFor: 'scaling' stamp: 'ssa 9/13/2008 19:39'! scalersFor: aspects "Answer a collection of appropriate scalers for these aspects." ^aspects collect:[:aspect| self scalerFor: aspect]! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:02'! showHeartbeat ShowHeartbeat isNil ifTrue:[ShowHeartbeat _ false]. ^ShowHeartbeat! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:03'! showHeartbeat: aBoolean ShowHeartbeat _ aBoolean! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/3/2009 12:18'! startHeartbeat "RVMMonitor startHeartbeat" "RVMMonitor stopHeartbeat" | rect delay | self showHeartbeat: true. rect _ 0@0 extent: 4@4. delay _ Delay forSeconds: 1. [[self showHeartbeat] whileTrue:[Display reverse: rect. delay wait]] forkAt: Processor highestPriority. Processor yield ! ! !RVMMonitor class methodsFor: 'heartbeat' stamp: 'ssa 4/1/2009 16:09'! stopHeartbeat "RVMMonitor startHeartbeat" "RVMMonitor stopHeartbeat" self showHeartbeat: false.! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:42'! addCoreAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to monitor' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view addAspect: selectedAspect]]. self view drawOnCanvas. self view displayView ! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/20/2008 10:26'! changeRescaleCounter | result | self view dontDisplayWhile:[ result _ FillInTheBlank request:'How many samples between rescaling?' initialAnswer: self view rescaleCounterDefault printString. result isNil ifFalse:[result _ result asNumber max:0. self view rescaleCounterDefault:result]]. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:52'! inspectView self view inspect! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 11/27/2008 14:00'! redButtonActivity "((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]"! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 18:55'! removeAspect | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view aspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select aspect to remove:' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view removeAspect: selectedAspect]. ]. self view drawOnCanvas. self view displayView ! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 10/7/2008 19:06'! rescale self view resetScaling. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'control activity' stamp: 'ssa 11/12/2008 12:48'! yellowButtonActivity | menu answer | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:#inspectView. menu add:'Rescale' action:#rescale. menu add:'Change Rescale Counter' action:#changeRescaleCounter. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMMultiAspectKiviatController methodsFor: 'menu messages' stamp: 'ssa 10/7/2008 19:38'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'Core aspects' action: #core. menu add: 'Test aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. self view aspect = newAspect ifTrue:[^self]. self view aspect: newAspect]. self view resetScaling. self view drawOnCanvas. self view displayView! ! !RVMMultiAspectKiviatController methodsFor: 'menu messages' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height scalerIndex result | (self view scalers size = 1 or:[self view commonScale])ifFalse:[result _ (PopUpMenu labelArray:self view aspects) startUpWithCaption:'Adjust the scale of which aspect?'. result = 0 ifTrue:[^self]. scalerIndex _ result]ifTrue:[scalerIndex _ 1]. maxView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) max] valueSetter:[:v|(view scalerAt: scalerIndex) setMax:v. view drawOnCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: (view scalerAt: scalerIndex) valueGetter: [(view scalerAt: scalerIndex) min] valueSetter:[:v|(view scalerAt: scalerIndex) setMin:v. view drawOnCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[(view scalerAt: scalerIndex) resetScaling. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[(view scalerAt: scalerIndex) setRangeToObserved. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: (view scalerAt: scalerIndex) label: 'Automatic Scaling' checkState: [(view scalerAt: scalerIndex) automaticScaling] whenChecked: [(view scalerAt: scalerIndex) automatic. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [(view scalerAt: scalerIndex) manual. view drawOnCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: (view aspects at: scalerIndex). height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. self scalerAdjusters add: topView. topView controller open! ! !RVMMultiAspectKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:32'! scalerAdjusters "Answer the value of scalerAdjusters" scalerAdjusters isNil ifTrue:[self scalerAdjusters: OrderedCollection new]. ^ scalerAdjusters! ! !RVMMultiAspectKiviatController methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:31'! scalerAdjusters: anObject "Set the value of scalerAdjusters" scalerAdjusters _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 17:20'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:14'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: RVMMulticoreSample systemAspects]. ^ aspects! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:12'! aspects: anObject "Set the value of aspects" aspects _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! backgroundCanvas "Answer the value of backgroundCanvas" backgroundCanvas isNil ifTrue:[ self backgroundCanvas:(ColorForm extent: self canvasExtent depth:8). self spokePens do:[:pen| pen destForm: backgroundCanvas]. self drawBackgroundCanvas.]. ^ backgroundCanvas! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:53'! backgroundCanvas: anObject "Set the value of backgroundCanvas" backgroundCanvas _ anObject ! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:17'! blinker "Answer the value of blinker" blinker isNil ifTrue:[self blinker: true]. self blinker: blinker not. ^ blinker! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 13:18'! blinker: anObject "Set the value of blinker" blinker _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/10/2008 18:39'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent: self canvasExtent depth:8)]. ^ canvas! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:11'! canvas: anObject "Set the value of canvas" canvas _ anObject. self webPen destForm: anObject. self spokePens:nil! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:00'! canvasExtent "Answer the extent of my canvas" ^self insetDisplayBox extent ! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:38'! center ^self canvas center! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:08'! centerMargin "the distance from center to the start of a spoke" ^20! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:36'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: ((Color wheel: self coreIndicies size) "collect:[:each| each darker darker]") ]. ^ colors! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 09:38'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:34'! coreIndicies "Answer the value of coreIndicies" coreIndicies isNil ifTrue:[self coreIndicies: (1 to: RVMMonitor coreCount) asOrderedCollection]. ^ coreIndicies! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 09:50'! coreIndicies: anObject "Set the value of coreIndicies" coreIndicies _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:13'! diameter "Answer the smallest square diameter for this view's box" ^self canvas height < self canvas width ifTrue:[self canvas height- (self labelRowCount * 10)] ifFalse:[self canvas width - 20]! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground "Answer the value of drawingBackground" drawingBackground isNil ifTrue:[self drawingBackground: false]. ^ drawingBackground! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 14:17'! drawingBackground: anObject "Set the value of drawingBackground" drawingBackground _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 18:52'! firstDisplay "Answer the value of firstDisplay" firstDisplay isNil ifTrue:[self firstDisplay: false]. ^ firstDisplay! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/8/2008 15:13'! firstDisplay: anObject "Set the value of firstDisplay" firstDisplay _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:56'! indexIcons "Answer the value of indexIcons" indexIcons isNil ifTrue:[self indexIcons: self buildIndexIcons]. ^ indexIcons! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/12/2008 10:56'! indexIcons: anObject "Set the value of indexIcons" indexIcons _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 01:18'! labelRowCount "How many rows of labels will I have?" ^2! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! majorTicLength ^8! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:35'! majorTicSpacing ^self spokeLength / (self numberOfMajorTics - 1) asFloat! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicLength ^4! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:36'! minorTicSpacing ^self majorTicSpacing /( self numberOfMinorTics + 1)! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:38'! numberOfMajorTics ^3! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:37'! numberOfMinorTics ^1! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 13:56'! radius "Answer the smallest radius for this view's box" ^self diameter // 2! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: self rescaleCounterDefault]. ^ rescaleCounter! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 15:02'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault "Answer the value of rescaleCounterDefault" rescaleCounterDefault isNil ifTrue:[self rescaleCounterDefault: 10]. ^ rescaleCounterDefault! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/20/2008 10:25'! rescaleCounterDefault: anObject "Set the value of rescaleCounterDefault" rescaleCounterDefault _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:15'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: (self aspects collect:[:each| RVMDataScaler new automatic])]. ^ scalers! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 23:12'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 22:07'! spokeColor "Answer the value of spokeColor" spokeColor isNil ifTrue:[self spokeColor: Color gray lighter lighter]. ^ spokeColor! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! spokeColor: anObject "Set the value of spokeColor" spokeColor _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 14:30'! spokeLength ^self radius - self centerMargin - 5! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:25'! spokePens "Answer the value of spokePens" spokePens isNil ifTrue:[self spokePens: self initializeSpokePens]. ^ spokePens! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 11:22'! spokePens: anObject "Set the value of spokePens" spokePens _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor "Answer the value of webColor" webColor isNil ifTrue:[self webColor: Color blue]. ^ webColor! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:21'! webColor: anObject "Set the value of webColor" webColor _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:06'! webPen "Answer the value of webPen" webPen isNil ifTrue:[self webPen: Pen new. webPen color: self webColor. webPen defaultNib:2. webPen combinationRule: Form over. webPen destForm: self canvas]. ^ webPen! ! !RVMMultiAspectKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 13:29'! webPen: anObject "Set the value of webPen" webPen _ anObject! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:19'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:21'! buildIndexIcons | icon label | ^self coreIndicies collect:[:index| label _ index printString asDisplayText . label foregroundColor: Color black backgroundColor: Color transparent. icon _ self iconCircle. label align: label boundingBox center with: icon boundingBox center. label displayOn: icon at: 0 @ -2. icon offset: icon boundingBox center negated. icon]! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 17:34'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. origin _ self backgroundCanvas boundingBox leftCenter - adjustIcon boundingBox leftCenter + (4@0). adjustIcon displayOn: self backgroundCanvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:59'! drawBackgroundCanvas self drawingBackground: true. self backgroundCanvas fillWhite. self drawSpokes. "self drawAdjustScaleIcon." "self drawLabelsOnBackground." self drawingBackground: false. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:18'! drawCounterOnCanvas | counterLabel | counterLabel _ ('rescale in: ',self rescaleCounter printString ) asDisplayText. counterLabel displayOn: self canvas at: self canvas boundingBox bottomRight -(counterLabel width@90). ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 10:27'! drawLabelsOnBackground | labels count origin coreNameText | labels _ self coreIndicies isEmpty ifTrue:[Array with:'System Aspects']ifFalse:[self coreIndicies collect:[:each| 'Core #',each printString]]. count _ 1. origin _ 2 @ -4. labels do:[:coreName| coreNameText _ coreName asDisplayText. coreNameText foregroundColor: (self colors at: count) backgroundColor: Color transparent. coreNameText displayOn: self backgroundCanvas at: origin. origin _ origin + (0@coreNameText height). count = (labels size //2) ifTrue:[origin _ self canvas boundingBox topRight - (coreNameText width @0)]. count _ count + 1] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMajorTicUsing: pen pen turn:90; go: self majorTicLength/2;turn:180;down;go:self majorTicLength;up; turn:180; go: self majorTicLength/2;turn:-90! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 14:16'! drawMinorTicUsing: pen pen turn:90; go: self minorTicLength/2;turn:180;down;go:self minorTicLength;up; turn:180; go: self minorTicLength/2;turn:-90! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:43'! drawOnCanvas self drawingBackground ifTrue:[^self]. self backgroundCanvas displayOn: self canvas at: 0@0. "self drawCounterOnCanvas." self drawWeb. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 23:24'! drawSpokes | pen label labelOffsets labelOffset | 1 to: self spokePens size do:[:index| pen _ self spokePens at: index. pen destForm: self backgroundCanvas. pen place: self center. pen up; go: self centerMargin. pen down;go: self spokeLength;up. label _ (self aspects at: index) asString asDisplayText asParagraph asForm. "self diameter < 300 ifTrue:[label _ label scaledToSize: 11@11]." labelOffsets _ {0@label height negated. 0@0. label width negated@0. label extent negated}. labelOffset _ labelOffsets at: ((index - 1// (self spokePens size / 4) + 1) min:4). label displayOn: self backgroundCanvas at: pen location + labelOffset clippingBox: self backgroundCanvas boundingBox rule: Form paint fillColor: nil. self drawTicsUsing: pen] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 10/6/2008 11:54'! drawTicsUsing: pen pen up;place: self center;go:self centerMargin. self drawMajorTicUsing: pen. self numberOfMajorTics - 1 timesRepeat:[ self numberOfMinorTics timesRepeat:[ pen go: self minorTicSpacing. self drawMinorTicUsing: pen]. pen go: self minorTicSpacing. self drawMajorTicUsing: pen]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 13:06'! drawWeb self coreIndicies isEmpty ifTrue:[^self drawWebSystem]. self coreIndicies do:[:index| self placeSpokePensForCore: index. self webPen color: (self colors at: (self coreIndicies indexOf: index)). self webPen combinationRule: Form paint. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up]. self coreIndicies "shuffled" do:[:index| self placeIconsForCore: index] ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 10:07'! drawWebSystem self drawingBackground ifTrue:[^self]. self placeSpokePens. self webPen color: self webColor. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 11:12'! iconCircle | icon aForm aCircle | icon _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 1@1. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: icon. ^icon! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:46'! placeIconsForCore: anIndex | data scaledDatum offset aspectIndex | data _ anIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: anIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. offset _ self aspects size > 0 ifTrue:[0]ifFalse:[((anIndex) - 1)*8/5]. aspectIndex _ 1. data with: self spokePens do:[:datum :pen| pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalers at: aspectIndex) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset. aspectIndex _ aspectIndex + 1. (self indexIcons at: (self coreIndicies indexOf: anIndex)) displayOn: self canvas at: pen location]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 02:26'! placeSpokePens | data index | data _ self coreIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: self coreIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. index _ 0. data with: self spokePens do:[:datum :pen| index _ index + 1. pen up;place: self center;go:self centerMargin. pen go:(self spokeLength /100.0*((self scalers at: index) scale: datum))]. ! ! !RVMMultiAspectKiviatView methodsFor: 'drawing' stamp: 'ssa 11/12/2008 12:45'! placeSpokePensForCore: anIndex | data scaledDatum offset aspectIndex | data _ anIndex > 0 ifTrue:[self aspects collect:[:aspect| (RVMMonitor lastSample perform: aspect) at: anIndex]] ifFalse:[self aspects collect:[:aspect| RVMMonitor lastSample perform: aspect]]. offset _ self aspects size > 0 ifTrue:[0]ifFalse:[((anIndex) - 1)*8/5]. aspectIndex _ 1. data with: self spokePens do:[:datum :pen| pen color: (self colors at: (self coreIndicies indexOf: anIndex)). pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalers at: aspectIndex) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset. aspectIndex _ aspectIndex + 1]. ! ! !RVMMultiAspectKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 15:20'! firstFrame ! ! !RVMMultiAspectKiviatView methodsFor: 'framing' stamp: 'ssa 10/8/2008 19:20'! newFrame self canvas:nil. self backgroundCanvas:nil. self drawOnCanvas. Display fill: self insetDisplayBox fillColor: Color white. self displayView! ! !RVMMultiAspectKiviatView methodsFor: 'scaling' stamp: 'ssa 11/11/2008 23:06'! resetScaling self scalers do:[:each| each resetScaling]. ! ! !RVMMultiAspectKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 23:05'! initializeSpokePens | pens numberOfSpokes spacing center pen | pens _ OrderedCollection new. numberOfSpokes _ self aspects size. spacing _ 360 / numberOfSpokes asFloat. center _ self insetDisplayBox center. numberOfSpokes timesRepeat:[ pen _ Pen new. pen defaultNib:1. pen combinationRule: Form over. pen color: self spokeColor. pen place: center. pen north. pen turn: pens size * spacing. pens add: pen]. ^pens! ! !RVMMultiAspectKiviatView methodsFor: 'initialize-release' stamp: 'ssa 11/11/2008 21:41'! release "self controller scalerAdjusters do:[:each| each topView controller closeAndUnscheduleNoTerminate]. self controller scalerAdjusters: nil." super release! ! !RVMMultiAspectKiviatView methodsFor: 'displaying' stamp: 'ssa 11/12/2008 13:18'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self firstDisplay ifFalse:[self firstDisplay:true. self drawOnCanvas]. self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox center - self canvas center clippingBox: self insetDisplayBox. self blinker ifTrue:[(Form dotOfSize:5) displayOn: Display at: self insetDisplayBox center] ! ! !RVMMultiAspectKiviatView methodsFor: 'displaying' stamp: 'dmu 8/23/2010 17:38'! resetAfterCoreCountChange self spokePens: nil. backgroundCanvas _ nil! ! !RVMMultiAspectKiviatView methodsFor: 'controller access' stamp: 'ssa 10/6/2008 13:35'! defaultControllerClass ^RVMMultiAspectKiviatController! ! !RVMMultiAspectKiviatView methodsFor: 'listening' stamp: 'dmu 2/6/2009 22:35'! hear: something "Update my traces and redisplay" self firstDisplay ifFalse: [^self]. self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self resetScaling.]. self drawingBackground ifTrue:[^self]. self drawOnCanvas. self displayView! ! !RVMMultiAspectKiviatView commentStamp: '<historical>' prior: 0! I'm a kiviat chart for displaying core aspect data! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/13/2008 02:02'! allCoreAspects ^RVMMulticoreSample coreAspects! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:53'! coreAspectSubset "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubset forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers'" ^#( bytecodesPerSecond bytesUseds contextChangeCounts interruptCheckCounts unforcedInterruptCheckCounts yieldsPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetAllocationCompaction "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetAllocationCompaction forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Allocation/Compaction'" ^#(allocationsReadWrites allocationsReadMostlys allocationsTotal compactionsReadWrites compactionsReadMostlys compactionsTotal )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetBytecodes "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetBytecodes forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Bytecodes'" ^#( bytecodeCounts bytecodesPerCycles bytecodesPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:54'! coreAspectSubsetBytes "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetBytes forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Bytes'" ^#(bytesLeftReadWrites bytesLeftReadMostlys bytesLefts bytesUsedReadWrites bytesUsedReadMostlys bytesUseds )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:55'! coreAspectSubsetRunWait "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetRunWait forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: RunWait'" ^#(millisecondsRunnings millisecondsWaitings msRunWaitRatios msSinceLasts )! ! !RVMMultiAspectKiviatView class methodsFor: 'aspect subsets' stamp: 'ssa 11/12/2008 12:55'! coreAspectSubsetYields "RVMMultiAspectKiviatView openOnAspects: RVMMultiAspectKiviatView coreAspectSubsetYields forCores:(1 to: RVMMonitor coreCount) asOrderedCollection titled:'Outliers: Yields'" ^#(unforcedInterruptCheckCounts yieldCounts yieldFrequencies yieldsPerSecond )! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/11/2008 23:18'! example "RVMMultiAspectKiviatView example" self openOnAspects: RVMMulticoreSample systemAspects! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:26'! example10Cores "RVMMultiAspectKiviatView example10Cores" self openOnAspects: RVMMulticoreSample coreAspects forCores: #(1 2 3 4 5 6 7 8 9 10)! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:50'! example10CoresSubset1 "RVMMultiAspectKiviatView example10CoresSubset1" self openOnAspects: self coreAspectSubset forCores: #(1 2 3 4 5 6 7 8 9 10)! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:34'! example20Cores "RVMMultiAspectKiviatView example20Cores" self openOnAspects: RVMMulticoreSample coreAspects forCores: (1 to: 20) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 11:53'! exampleAllCores "RVMMultiAspectKiviatView exampleAllCores" self openOnAspects: RVMMulticoreSample coreAspects forCores:(1 to: RVMMonitor coreCount) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 11:53'! exampleAllCoresSubset1 "RVMMultiAspectKiviatView exampleAllCoresSubset1" self openOnAspects: self coreAspectSubset forCores:(1 to: RVMMonitor coreCount) asOrderedCollection! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 02:24'! exampleCore5 "RVMMultiAspectKiviatView exampleCore5" self openOnAspects: RVMMulticoreSample coreAspects forCore: 5! ! !RVMMultiAspectKiviatView class methodsFor: 'examples' stamp: 'ssa 11/12/2008 10:45'! exampleSubset1 "RVMMultiAspectKiviatView exampleSubset1" self openOnAspects: self coreAspectSubset! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/11/2008 23:17'! openOnAspect: aSymbol "RVMMultiAspectKiviatView example" self openOnAspects: (Array with: aSymbol)! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 11:44'! openOnAspects: someSymbols "RVMMultiAspectKiviatView example" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 600@250. topView maximumSize: 1000@800. v := self new. v borderWidth:1. v aspects: someSymbols. topView addSubView: v. topView label: 'MultiAspectKiviat'. topView controller open! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 10:15'! openOnAspects: someSymbols forCore: anIndex "RVMMultiAspectKiviatView exampleCore5" self openOnAspects: someSymbols forCores: (Array with: anIndex)! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 12:52'! openOnAspects: someSymbols forCores: indexArray "RVMMultiAspectKiviatView exampleAllCores" self openOnAspects: someSymbols forCores: indexArray titled: 'MultiAspectKiviat'! ! !RVMMultiAspectKiviatView class methodsFor: 'instance creation' stamp: 'ssa 11/12/2008 12:59'! openOnAspects: someSymbols forCores: indexArray titled: aString "RVMMultiAspectKiviatView exampleAllCores" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@150"(9*indexArray size max:250)". topView maximumSize: 1000@800. v := self new. v coreIndicies: indexArray. v borderWidth:1. v aspects: someSymbols. topView addSubView: v. topView label: aString. topView controller open! ! !RVMMultiAspectStripChartController methodsFor: 'menu messages' stamp: 'ssa 9/14/2008 21:49'! eraseStrip self view eraseStrip! ! !RVMMultiAspectStripChartController methodsFor: 'controlling' stamp: 'ssa 9/13/2008 17:44'! redButtonActivity self view displayView! ! !RVMMultiAspectStripChartController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 15:15'! yellowButtonActivity | menu answer | self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := CustomMenu new. menu add: 'erase strip' action: #eraseStrip:. answer := menu startUp: nil withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer]]]! ! !RVMMultiAspectStripChartView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 17:43'! defaultControllerClass ^RVMMultiAspectStripChartController! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:12'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: OrderedCollection new]. ^ aspects! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:41'! aspects: anObject "Set the value of aspects" aspects _ anObject.. self scalers:nil. self data: nil. ! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:12'! chart "Answer the value of chart" chart isNil ifTrue:[self chart: (Form fromDisplay: self insetDisplayBox) fillWhite]. ^ chart! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:11'! chart: anObject "Set the value of chart" chart _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/14/2008 20:55'! colors "Answer the value of colors" ^self scalers collect:[:each| each color]! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:36'! coreIndex "Answer the value of coreIndex" coreIndex isNil ifTrue:[self coreIndex: 1]. ^ coreIndex! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:36'! coreIndex: anObject "Set the value of coreIndex" coreIndex _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:25'! data "Answer the value of data" data isNil ifTrue:[self data: (Array new: self aspects size)]. ^ data! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:11'! data: anObject "Set the value of data" data _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:18'! dotSize "Answer the value of dotSize" dotSize isNil ifTrue:[self dotSize: 2]. ^ dotSize! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:14'! dotSize: anObject "Set the value of dotSize" dotSize _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:49'! getData | sample | sample _ self sampleSource value. 1 to: self aspects size do:[:index| self data at: index put: ((self scalers at: index) scale:((sample perform: (self aspects at: index)) at: self coreIndex))]! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:29'! sampleSource "Answer the value of sampleSource" sampleSource isNil ifTrue:[self sampleSource: [RVMMonitor lastSample]]. ^ sampleSource! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 17:27'! sampleSource: anObject "Set the value of sampleSource" sampleSource _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: (RVMMonitor coloredScalersFor: self aspects)]. ^ scalers! ! !RVMMultiAspectStripChartView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 18:04'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiAspectStripChartView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:33'! hear: something self displayView! ! !RVMMultiAspectStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | bottomLeft points sortedPoints box | self okToDisplay ifFalse:[^self]. self uncache. self getData. self chart displayOn: Display at: self insetDisplayBox origin + (self dotSize @ 0) clippingBox: self insetDisplayBox. bottomLeft := self insetDisplayBox bottomLeft. points := OrderedCollection new. 1 to: self aspects size do: [:index | points add: index @ (self data at: index)]. sortedPoints := points asSortedCollection: [:a :b | a y > b y]. sortedPoints do: [:each | box := bottomLeft - (0 @ (each y * self dotSize)) corner: bottomLeft + (self dotSize @ 0). Display fill: box fillColor: (self colors at: each x)]. self chart:(Form fromDisplay: self insetDisplayBox).! ! !RVMMultiAspectStripChartView methodsFor: 'displaying' stamp: 'ssa 9/14/2008 21:50'! eraseStrip Display fill: self insetDisplayBox fillColor: Color white. self chart: nil;chart! ! !RVMMultiAspectStripChartView methodsFor: 'auxiliary views' stamp: 'ssa 1/1/1970 00:29'! combinedScalerView "Answer a view holding all my appropriate scaler views" | v last current | v _ RVMView new. last _ nil. self scalers do:[:scaler| v addSubView: (current _ RVMColoredDataScalerView on: scaler) below: last. current borderWidth:1. last _ current]. ^v! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:29'! example "RVMMultiAspectStripChartView example" | topView chart scalers aspectCount | topView := RVMStandardSystemView new. topView borderWidth:1. chart _ self exampleInstance. aspectCount _ chart aspects size. topView minimumSize: 200@(aspectCount*40). topView maximumSize: 800@(2*aspectCount*40). scalers _ chart combinedScalerView. topView addSubView: scalers in:(0@0 extent: 1/3 @ 1)borderWidth:1. topView addSubView: chart in:(1/3@0 extent: 2/3 @ 1)borderWidth:1. topView label: 'Multi Aspect Strip'. topView controller open! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:28'! exampleInstance | view | view _ self new. view aspects: #( bytecodeCounts bytesUseds yieldCounts ). ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'examples' stamp: 'ssa 9/14/2008 20:30'! exampleMany "RVMMultiAspectStripChartView exampleMany" | topView view manyCount lastView | topView := RVMStandardSystemView new. topView borderWidth:1. manyCount _ 4. topView minimumSize: 100@(25*manyCount). topView maximumSize: 200@(50*manyCount). lastView _ nil. manyCount timesRepeat:[ view _ self exampleInstance. topView addSubView: view below: lastView. lastView _ view]. topView label: 'Aspect/Color'. topView controller open! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:10'! coreIndex: index "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: #(bytesUsed bytecodeCounts yieldCounts). view sampleSource: [RVMMonitor lastSample]. ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:08'! coreIndex: index aspects: aspects "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: aspects. view sampleSource: [RVMMonitor lastSample]. ^view! ! !RVMMultiAspectStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:08'! coreIndex: index aspects: aspects sampleSource: aBlock "Answer a stripchart for this core index watching these aspects from this source" | view | view _ self new. view coreIndex: index. view aspects: aspects. view sampleSource: aBlock. ^view! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:44'! changeSourceForGroupNumber: anIndex | menu action choices | menu := CustomMenu new. choices _ {'Object withAllSubclasses'. 'View withAllSubclasses'. 'Number allSubclasses'. #line. 'String allInstances'. 'Array allInstances'. 'Collection allSubInstances' }. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action:choice]]. action := menu startUp: nil withCaption: 'Select an expression to use for group #',(anIndex printString) at: Sensor cursorPoint. action notNil ifTrue:[self changeSourceSourcefromGroupNumber: anIndex to: action]! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:47'! changeSourceSourcefromGroupNumber: anIndex to: aString Cursor wait showWhile:[ self view sourceSourceForGroupNumber: anIndex put: aString. self view changed:#updateDisplay]! ! !RVMMultiGroupLocatorController methodsFor: 'controlling' stamp: 'ssa 11/27/2008 13:53'! yellowButtonActivity | menu action choices index | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add:'Inspect View' action:[self view inspect]. menu addLine. choices _ view sources collect:[:each| 'Change #',(index _ view sources indexOf: each) printString, ': ',(view sourceSourceForGroupNumber:index)]. choices do:[:choice| choice = #line ifTrue:[menu addLine] ifFalse:[menu add: choice action: (choices indexOf: choice)]]. action := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. (action isKindOf: BlockContext) ifTrue:[^action value]. action notNil ifTrue:[self changeSourceForGroupNumber: action]! ! !RVMMultiGroupLocatorView methodsFor: 'listening' stamp: 'ssa 11/27/2008 13:24'! hear: something "Update my display" self counts: nil. self drawOnCanvas. self displayView! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:55'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: (Color hotColdShades: (self sources size max:5))]. ^ colors! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:37'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:33'! counts "Answer the value of counts" counts isNil ifTrue:[self counts: (Array new:self sources size). 1 to: self sources size do:[:index| self countsPerCoreForGroupNumber: index]]. ^ counts! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:31'! counts: anObject "Set the value of counts" counts _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ads 1/30/2011 15:20'! countsPerCoreForGroupNumber: anIndex "Answer the value of countsPerCore" (self counts at: anIndex) isNil ifTrue:[self counts at: anIndex put: ((self objectsForGroupNumber: anIndex) asOrderedCollection collect:[:obj| RVMOperations isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMOperations getCoreHolding:obj]]) asBag]. ^ self counts at: anIndex! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:33'! objectsForGroupNumber: anIndex "Answer my colection of objects to locate." | source | source _ self sources at: anIndex. ^source isSymbol ifTrue:[self model perform: source] ifFalse:[source value]! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:19'! sourceSourceForGroupNumber: anIndex | code source | source _ self sources at: anIndex. source isSymbol ifTrue:[^source printString]. code _ source decompile printString. (code beginsWith:'{[') &(code endsWith:']}') ifTrue:[code _ code copyFrom: 3 to: code size - 2]. ^code! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 13:22'! sourceSourceForGroupNumber: anIndex put: aText | value aString | aString _ aText asString. ( aString withBlanksTrimmed beginsWith:'#') ifTrue:[value _ Compiler new evaluate: aString in: nil to: nil notifying: nil ifFail: [^ false]. self model perform: value. "test to make sure it works before installing"] ifFalse:[value _ Compiler new evaluate: '[',aString,']' in: nil to: nil notifying: nil ifFail: [^ false]]. self sources at: anIndex put: value. self hear:nil. ^true "tell the editor its OK"! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:42'! sources "Answer the value of sources" sources isNil ifTrue:[self sources: {[String allInstances]. [View withAllSubclasses]. [Number withAllSubclasses]}]. ^ sources! ! !RVMMultiGroupLocatorView methodsFor: 'accessing' stamp: 'ssa 11/27/2008 12:31'! sources: anObject "Set the value of sources" sources _ anObject! ! !RVMMultiGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 13:34'! drawLocations | indicies | indicies _ (self counts asSortedCollection:[:a :b| a size < b size]) collect:[:each| self counts indexOf: each]. indicies do:[:anIndex| self drawLocationsForGroupNumber: anIndex]! ! !RVMMultiGroupLocatorView methodsFor: 'drawing' stamp: 'ssa 11/27/2008 12:40'! drawLocationsForGroupNumber: anIndex | dot coreExtent amt index rect pt dotSize realRect | coreExtent _ RVMMonitor extent. dotSize _(self boxes first width // (((self countsPerCoreForGroupNumber:anIndex) size // self boxes size)max:1))min:self boxes first width //2 max:1. dot _ Form dotOfSize: dotSize color: (self colors at: anIndex). 0 to: coreExtent x - 1 do:[:x| 0 to: coreExtent y - 1 do:[:y| amt _ (self countsPerCoreForGroupNumber:anIndex) occurrencesOf: (index _ y*8+x). rect _ (realRect _ self boxes at: index + 1) insetBy: dot offset abs. amt timesRepeat:[pt _ rect asRandomPoint. dot displayOn: self canvas at: pt clippingBox: realRect rule: Form paint fillColor:nil]]. ]! ! !RVMMultiGroupLocatorView methodsFor: 'controller access' stamp: 'ssa 11/27/2008 13:40'! defaultControllerClass ^RVMMultiGroupLocatorController! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 12:58'! on: aModel sources: someBlocksOrSelectors ^self on: aModel sources: someBlocksOrSelectors colors: nil! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 12:55'! on: aModel sources: someBlocksOrSelectors colors: someColors "(RVMMultiGroupLocatorView on: Smalltalk sources: {#keys. #values. #classNames} colors: nil) demo" "(RVMultiGroupLocatorView on: nil sources: {[String allInstances]. [Array allInstances]} colors: {Color yellow. Color green}) demo" "(RVMMultiGroupLocatorView on: nil sources: {[String allInstances]. [Array allInstances]. [Object withAllSubclasses]. [Float allInstances]} colors: nil) demo" | v | v _ self new. v model: aModel. v sources: someBlocksOrSelectors. v colors: someColors. ^v! ! !RVMMultiGroupLocatorView class methodsFor: 'instance creation' stamp: 'ssa 11/27/2008 14:04'! openOn: aModel sources: someBlocksOrSelectors colors: someColors "RVMMultiGroupLocatorView openOn: Smalltalk sources: {#keys. #values. #classNames} colors: nil" "RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Array allInstances]} colors: {Color yellow. Color green}" "RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Array allInstances]. [Object withAllSubclasses]. [Float allInstances]} colors: nil" | topView v ptv cbv h | topView := RVMStandardSystemView new. topView borderWidth:1. v := self on: aModel sources: someBlocksOrSelectors colors: someColors. v borderWidth:1. topView minimumSize: 150@(150 + (v sources size * 20)). topView maximumSize: 800@900. topView addSubView: v viewport:(0@0 extent: 150@150). h _ 0. 1 to: v sources size do:[:groupIndex| ptv _ RVMPluggableTextView on: v text:[v sourceSourceForGroupNumber: groupIndex] fixTemps accept:[:arg| v sourceSourceForGroupNumber: groupIndex put: arg] fixTemps. ptv borderWidth:1. cbv _ RVMColorButtonView on: v colorGetter:[v colors at: groupIndex] fixTemps colorSetter:[:arg|v colors at: groupIndex put: arg. v displayView] fixTemps. cbv borderWidth:1. topView addSubView: cbv viewport:(0@(h+150) extent:20@20). topView addSubView: ptv viewport:(20@(h+150) extent:130@20). h _ h + 20]. topView label: 'Group Locator'. topView controller open! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:35'! addAspect: aSymbol | s | self aspects add: aSymbol. self scalers add:(s _ RVMDataScaler new automatic). self pinMinAtZero ifTrue:[s pinMinAtZero]. self lastTotals add: 0. self lastAverages add:0 ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:02'! aspect "Get the value of aspect" ^self aspects at:1! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:44'! aspect: anObject "Set the value of aspect" self aspects at:1 put: anObject. self lastAverages at: 1 put: 0. self lastTotals at: 1 put:0. self topView == self ifFalse:[self topView relabel: anObject asString]. self resetScaling. self drawOnCanvas! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 17:22'! aspectCount ^self aspects size! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:02'! aspects "Answer the value of aspects" aspects isNil ifTrue:[self aspects: #(bytesUseds bytesUsedReadWrites bytesUsedReadMostlys) asOrderedCollection]. ^ aspects ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:33'! aspects: anObject "Set the value of aspects" aspects _ anObject. aspects notNil ifTrue:[aspects _ aspects asOrderedCollection. aspects size > 4 ifTrue:[aspects _ aspects copyFrom: 1 to: 4]]. self lastAverages: nil. self lastTotals: nil! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:57'! colorForAspect: aSymbol ^self colors at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/21/2008 11:33'! colors "Answer the value of colors " colors isNil ifTrue:[self colors: {Color blue. Color red. Color green darker darker. Color orange darker }]. ^ colors! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:56'! colors: anObject "Set the value of colors" colors _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! commonScale "Answer the value of commonScale" commonScale isNil ifTrue:[self commonScale: false]. ^ commonScale! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:13'! commonScale: anObject "Set the value of commonScale" commonScale _ anObject.! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 20:02'! lastAverageForAspect: aSymbol ^self lastAverages at: (self aspects indexOf: aSymbol ifAbsent:[1])! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:19'! lastAverageForAspect: aSymbol put: aValue ^self lastAverages at: (self aspects indexOf: aSymbol) put: aValue! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:41'! lastAverages "Answer the value of lastAverages" lastAverages isNil ifTrue:[self lastAverages: (Array new: self aspects size withAll: 0)asOrderedCollection]. ^ lastAverages! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:14'! lastAverages: anObject "Set the value of lastAverages" lastAverages _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:15'! lastTotalForAspect: aSymbol ^self lastTotals at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:19'! lastTotalForAspect: aSymbol put: aValue ^self lastTotals at: (self aspects indexOf: aSymbol) put: aValue! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 18:41'! lastTotals "Answer the value of lastTotals" lastTotals isNil ifTrue:[self lastTotals: (Array new: self aspects size withAll: 0) asOrderedCollection]. ^ lastTotals! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 15:14'! lastTotals: anObject "Set the value of lastTotals" lastTotals _ anObject! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! pinMinAtZero "Answer the value of pinMinAtZero" pinMinAtZero isNil ifTrue:[self pinMinAtZero: false]. ^ pinMinAtZero! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:12'! pinMinAtZero: anObject "Set the value of pinMinAtZero" pinMinAtZero _ anObject. self scalers do:[:each| each pinMinAtZero]! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:15'! removeAspect: aSymbol | index | index _ self aspects indexOf: aSymbol. self aspects remove: aSymbol. self commonScale ifFalse:[self scalers remove:(self scalers at: index)]. self lastTotals remove:(self lastTotals at: index). self lastAverages remove:(self lastAverages at: index) ! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:04'! scaler "Get the default scaler" ^self scalers at:1! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 21:27'! scalerAt: anIndex "Get the default scaler" self commonScale ifTrue:[^self scalers first]. ^self scalers at: anIndex! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/7/2008 19:13'! scalerForAspect: aSymbol self commonScale ifTrue:[^self scalers first]. ^self scalers at: (self aspects indexOf: aSymbol)! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:59'! scalers "Answer the value of scalers" scalers isNil ifTrue:[self scalers: OrderedCollection new. self aspects do:[:a| scalers add: RVMDataScaler new automatic]]. ^ scalers! ! !RVMMultiKiviatView methodsFor: 'accessing' stamp: 'ssa 10/6/2008 17:56'! scalers: anObject "Set the value of scalers" scalers _ anObject! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:39'! drawBottomLeftLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height -3. aspectLabel displayOn: self canvas at: box bottomLeft - (0 @aspectLabel height). minLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y -( height*2) )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height*3)+3)) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height *4)+6)) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box bottomLeft x )@(box bottomLeft y - (height *5)+9)) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:36'! drawBottomRightLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height -3. aspectLabel displayOn: self canvas at: box bottomRight - (aspectLabel extent). minLabel displayOn: self canvas at: ((box bottomRight x - minLabel width)@(box bottomRight y -( height*2) )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box bottomRight x - maxLabel width)@(box bottomRight y - (height*3)+3)) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box bottomRight x - totalLabel width)@(box bottomRight y - (height *4)+6)) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box bottomRight x - avgLabel width)@(box bottomRight y - (height *5)+9)) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 14:56'! drawLabelsOnCanvas | quads | quads _ #(drawTopLeftLabelsOnCanvasForAspect: drawTopRightLabelsOnCanvasForAspect: drawBottomRightLabelsOnCanvasForAspect: drawBottomLeftLabelsOnCanvasForAspect:). 1 to: self aspects size do:[:index| self perform: (quads at: index) with: (self aspects at: index)]! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:13'! drawTopLeftLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height - 6. aspectLabel displayOn: self canvas at: (0 @ -4). minLabel displayOn: self canvas at: ((0)@(box topLeft y + height )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((0)@(box topLeft y + (height*2))) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((0)@(box topLeft y + (height *3))) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((0)@(box topLeft y + (height *4))) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 15:10'! drawTopRightLabelsOnCanvasForAspect: aSymbol | minLabel maxLabel aspectLabel avgLabel totalLabel aspectColor box height | box _ self canvas boundingBox. aspectColor _self colorForAspect:aSymbol. aspectLabel _ aSymbol asString asDisplayText. minLabel _ ('min: ',(self scalerForAspect: aSymbol) min printShowingMax3Digits) asDisplayText. maxLabel _ ('max: ',(self scalerForAspect: aSymbol) max printShowingMax3Digits) asDisplayText. avgLabel _ ('avg: ',(self lastAverageForAspect: aSymbol) printShowingMax3Digits) asDisplayText. totalLabel _ ('total: ',(self lastTotalForAspect: aSymbol) printShowingMax3Digits) asDisplayText. avgLabel foregroundColor: aspectColor backgroundColor: Color transparent. totalLabel foregroundColor: aspectColor backgroundColor: Color transparent. aspectLabel foregroundColor: aspectColor backgroundColor: Color transparent. minLabel foregroundColor: aspectColor backgroundColor: Color transparent. maxLabel foregroundColor: aspectColor backgroundColor: Color transparent. height _ aspectLabel height - 6. aspectLabel displayOn: self canvas at: box topRight - (aspectLabel width @4). minLabel displayOn: self canvas at: ((box topRight x - minLabel width)@(box topRight y + height )) clippingBox: box rule: Form paint fillColor:nil. maxLabel displayOn: self canvas at: ((box topRight x - maxLabel width)@(box topRight y + (height*2))) clippingBox: box rule: Form paint fillColor:nil. totalLabel displayOn: self canvas at: ((box topRight x - totalLabel width)@(box topRight y + (height *3))) clippingBox: box rule: Form paint fillColor:nil. avgLabel displayOn: self canvas at: ((box topRight x - avgLabel width)@(box topRight y + (height *4))) clippingBox: box rule: Form paint fillColor:nil. ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'ssa 10/7/2008 16:04'! drawWeb self aspects do:[:aSymbol| self placeSpokePensForAspect: aSymbol. self webPen color: (self colorForAspect: aSymbol). self webPen combinationRule: Form paint. self webPen up;place: self spokePens first location;down. self spokePens do:[:pen| self webPen goto: pen location]. self webPen goto: self spokePens first location;up] ! ! !RVMMultiKiviatView methodsFor: 'drawing' stamp: 'dmu 8/23/2010 17:37'! placeSpokePensForAspect: aSymbol | data scaledDatum tot offset | data _ RVMMonitor lastSample perform: aSymbol. offset _ ((self aspects indexOf: aSymbol) - 1)*4/5. tot _ 0. self spokePens size = data size ifFalse: [self resetAfterCoreCountChange]. data with: self spokePens do:[:datum :pen| tot _ tot + datum. pen up;place: self center;turn: offset negated;go:self centerMargin. scaledDatum _ (self scalerForAspect: aSymbol) scale: datum. pen go:(self spokeLength /100.0*(scaledDatum)). pen turn: offset]. self lastTotalForAspect: aSymbol put: tot. self lastAverageForAspect: aSymbol put: tot / data size! ! !RVMMultiKiviatView methodsFor: 'scaling' stamp: 'ssa 10/7/2008 19:48'! resetScaling | data tot | self scalers do:[:s| s resetScaling]. self aspects do:[:aSymbol| data _ RVMMonitor lastSample perform: aSymbol. tot _ 0. data do:[:datum | tot _ tot + datum. (self scalerForAspect: aSymbol) scale: datum]. self lastTotalForAspect: aSymbol put: tot. self lastAverageForAspect: aSymbol put: tot / data size]! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 15:38'! example "RVMMultiKiviatView example" self openOnAspects: #(bytesUsedReadMostlys bytesUsedReadWrites bytesUseds bytecodeCounts)! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 4/3/2009 17:51'! exampleBytecodesAndProcessesRunning "RVMMultiKiviatView exampleBytecodesAndProcessesRunning" self openOnAspects: #(bytecodeCounts runningProcessCountsPerCore ) pinAllScalesAtZero: false useCommonScale: false! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 16:01'! exampleBytesUsedTrioCommonPinned "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" self openOnAspects: #(bytesUsedReadWrites bytesUsedReadMostlys bytesUseds ) pinAllScalesAtZero: true useCommonScale: true! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 16:01'! exampleBytesUsedTrioPinned "RVMMultiKiviatView exampleBytesUsedTrioPinned" self openOnAspects: #(bytesUsedReadWrites bytesUsedReadMostlys bytesUseds ) pinAllScalesAtZero: true! ! !RVMMultiKiviatView class methodsFor: 'examples' stamp: 'ssa 10/7/2008 18:29'! exampleSingle "RVMMultiKiviatView exampleSingle" self openOnAspects: #(bytecodeCounts) pinAllScalesAtZero: false useCommonScale: false titled: 'bytecodeCounts' ! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 15:54'! openOnAspects: someAspects "RVMMultiKiviatView example" self openOnAspects: someAspects pinAllScalesAtZero: false! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 16:12'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean "RVMMultiKiviatView exampleBytesUsedTrioPinned" self openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: false! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 16:09'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" | | self openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale titled: 'Multiaspect Kiviat'! ! !RVMMultiKiviatView class methodsFor: 'instance creation' stamp: 'ssa 10/7/2008 19:24'! openOnAspects: someAspects pinAllScalesAtZero: aBoolean useCommonScale: commonScale titled: aString "RVMMultiKiviatView exampleBytesUsedTrioCommonPinned" | topView v label | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@250. topView maximumSize: 600@500. v := self new. v borderWidth:1. v aspects: someAspects. v commonScale: commonScale. v pinMinAtZero: aBoolean. topView addSubView: v. label _ aString,(aBoolean ifTrue:[' (pinned)']ifFalse:['']),(commonScale ifTrue:[' (uniscale)']ifFalse:['']). topView label: label. topView controller open! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 9/14/2008 20:50'! aspects "Answer a list of message selectors that will return arrays of numbers for my monitor" ^self class aspects! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:06'! coreIndices ^self groupStats coreIndices! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:33'! cpuCoreStats "Answer the value of cpuCoreStats" ^cpuCoreStats! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! cpuCoreStats: anObject "Set the value of cpuCoreStats" cpuCoreStats := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/13/2008 09:42'! extent "Answer the dimensions of my tile grid" ^self groupStats extent! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:03'! fence "Answer the value of fence" fence isNil ifTrue:[self fence: nil]. ^ fence! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 11/16/2008 15:03'! fence: anObject "Set the value of fence" fence _ anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 8/15/2008 22:13'! groupStats ^ groupStats! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 8/15/2008 22:14'! groupStats: x groupStats _ x! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 17:33'! messageNames "Answer the value of messageNames" ^messageNames! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! messageNames: anObject "Set the value of messageNames" messageNames := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! numberOfCores ^self groupStats isNil ifTrue:[56]ifFalse:[self groupStats groupSize]! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 7/16/2010 15:03'! processInstanceCount "Answer the value of processInstanceCount" processInstanceCount isNil ifTrue:[self processInstanceCount: Process instanceCount]. ^ processInstanceCount! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 7/16/2010 15:02'! processInstanceCount: anObject "Set the value of processInstanceCount" processInstanceCount _ anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 8/13/2008 15:11'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: nil]. ^rawData! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'ssa 10/18/2008 18:03'! rawData: anObject "Set the value of rawData" rawData := anObject! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:04'! runMask ^ runMask! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:05'! runMask: x runMask := x! ! !RVMMulticoreSample methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:20'! totalYields ^ self cpuCoreStats yieldCounts sum! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/13/2008 17:32'! initializeAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/19/2008 10:50'! initializeFastAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFastFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 7/16/2010 16:45'! initializeFastFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." self rawData: data. self runMask: (data at: 2). self messageNames: (data at: 4). self initializeFastGroupStatsFrom: (data at: 6). self initializeFastAllCPUCoreStatsFrom: (data at: 8). self fence: (data at: 10). self processInstanceCount: Process instanceCount ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 3/25/2009 14:11'! initializeFastGroupStatsFrom: data self groupStats: (RVMGroupStats new initializeFastFrom: data last)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 1/1/1970 00:04'! initializeFastestAllCPUCoreStatsFrom: data self cpuCoreStats: (RVMAllCPUCoreStats newFastestFrom: data forMessageNames: self messageNames)! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'dmu 5/21/2010 23:05'! initializeFastestFrom: data "This implementations assumes order dependency in the array for speed. Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." self rawData: data. self runMask: (data at: 2). self messageNames: (data at: 4). self initializeFastestGroupStatsFrom: ((data at: 6 ) at: 2). self initializeFastestAllCPUCoreStatsFrom: (data at: 8). self fence: (data at: 10). ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 3/25/2009 19:17'! initializeFastestGroupStatsFrom: data self groupStats: (RVMGroupStats new initializeFastFrom: data )! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 7/16/2010 16:46'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap | self rawData: data. valueMap := { }. objectMap := { 'runMask' -> #runMask:. 'messageNames' -> #messageNames:. 'allCPUCoreStats' -> #initializeAllCPUCoreStatsFrom:. 'groupStats' -> #initializeGroupStatsFrom:. 'fence' -> #fence:. }. self processMap: valueMap into: self forData: data. self processMap: objectMap into: self forData: data. self processInstanceCount: Process instanceCount ! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'dmu 8/15/2008 22:11'! initializeGroupStatsFrom: data groupStats _ RVMGroupStats new initializeFrom: data! ! !RVMMulticoreSample methodsFor: 'initialize' stamp: 'ssa 8/13/2008 15:47'! processMap: map into: targetObject forData: data | index datum | map do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. targetObject perform: assoc value with: datum]. ! ! !RVMMulticoreSample methodsFor: 'printing' stamp: 'ssa 8/15/2008 16:28'! printOn: aStream aStream nextPutAll: 'anRVMMulticoreStats('; cr;tab;nextPutAll: ' bytecodesPerCycle=';nextPutAll: self bytecodesPerCycle printString; cr;tab;nextPutAll: ' bytecodesPerCyclesAverage=';nextPutAll: self bytecodesPerCyclesAverage printString; cr;tab;nextPutAll: ' bytecodesPerMillisecond=';nextPutAll: self bytecodesPerMillisecond printString; cr;tab;nextPutAll: ' bytecodesPerMillisecondsAverage=';nextPutAll: self bytecodesPerMillisecondsAverage printString; cr;tab;nextPutAll: ' bytecodeCountsAvg=';nextPutAll: self bytecodeCountsAverage printString; cr;tab;nextPutAll: ' bytecodePerSecondAvg=';nextPutAll: self bytecodesPerSecondAverage printString; cr;tab;nextPutAll: ' cyclesRunningsAvg=';nextPutAll: self cyclesRunningsAverage printString; cr;tab;nextPutAll: ' cyclesWaitingsAvg=';nextPutAll: self cyclesWaitingsAverage printString; cr;tab;nextPutAll: ' cyclesRunWaitRatiosAvg=';nextPutAll: self cyclesRunWaitRatiosAverage printString; cr;tab;nextPutAll: ' msRunningsAvg=';nextPutAll: self msRunningsAverage printString; cr;tab;nextPutAll: ' msWaitingsAvg=';nextPutAll: self msWaitingsAverage printString; cr;tab;nextPutAll: ' msRunWaitRatiosAvg=';nextPutAll: self msRunWaitRatiosAverage printString; cr;tab;nextPutAll: ' yieldCountsAvg=';nextPutAll: self yieldCountsAverage printString; cr;tab;nextPutAll: ' yieldsPerSecondAvg=';nextPutAll: self yieldsPerSecondAverage printString; cr;tab;nextPutAll: ')';cr ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:58'! allocationsReadMostlys "RVMMulticoreSample capture allocationsReadMostlys" "Answer the collection of allocationsSinceLastReadMostlys" ^self cpuCoreStats allocationsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:58'! allocationsReadWrites "RVMMulticoreSample capture allocationsReadWrites" "Answer the collection of allocationsSinceLastReadWrites" ^self cpuCoreStats allocationsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadMostlys "RVMMulticoreSample capture allocationsSinceLastReadMostlys" "Answer the collection of allocationsSinceLastReadMostlys" ^self cpuCoreStats allocationsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:53'! allocationsSinceLastReadWrites "RVMMulticoreSample capture allocationsSinceLastReadWrites" "Answer the collection of allocationsSinceLastReadWrites" ^self cpuCoreStats allocationsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:00'! allocationsTotal "RVMMulticoreSample capture allocationsTotal" "Answer the collection of allocationsSinceLast" ^self cpuCoreStats allocationsSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:40'! bytecodeCounts "RVMMulticoreSample capture bytecodeCounts" "Answer the collection of bytecode counts during this sample" ^self cpuCoreStats bytecodeCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! bytecodeCountsAverage "RVMMulticoreSample capture bytecodeCountsAverage" "Answer the average of bytecode counts during this sample" ^self cpuCoreStats bytecodeCounts average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:19'! bytecodesPerCycle "RVMMulticoreSample capture bytecodesPerCycle" | avg | avg := self cyclesSinceLastsAverage. ^avg = 0 ifTrue:[0] ifFalse:[self bytecodeCounts sum / (1 max: self cyclesSinceLastsAverage) asFloat]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:05'! bytecodesPerCycles "RVMMulticoreSample capture bytecodesPerCycles" ^self bytecodeCounts with: self cyclesRunnings collect:[:bc :ms| ms = 0 ifTrue:[0] ifFalse:[bc/ms asFloat]]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:06'! bytecodesPerCyclesAverage "RVMMulticoreSample capture bytecodesPerCyclesAverage" ^self bytecodesPerCycles average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! bytecodesPerKCs ^ self bytecodesPerCycles collect: [:x| x * 1000]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:09'! bytecodesPerMCs ^ self bytecodesPerCycles collect: [:x| x * 1000000]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:20'! bytecodesPerMillisecond "RVMMulticoreSample capture bytecodesPerMillisecond" ^self bytecodeCounts sum / (1 max: self msSinceLastsAverage) asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:20'! bytecodesPerMilliseconds "RVMMulticoreSample capture bytecodesPerMilliseconds" ^self bytecodeCounts with: self msSinceLasts collect:[:bc :ms| bc/(1 max: ms) asFloat]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:35'! bytecodesPerMillisecondsAverage "RVMMulticoreSample capture bytecodesPerMillisecondsAverage" ^self bytecodesPerMilliseconds average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:25'! bytecodesPerSecond "RVMMulticoreSample capture bytecodesPerSecond" "Answer the collection of ratios of bytecodes executed per second during this sample" ^self cpuCoreStats bytecodesPerSecond! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! bytecodesPerSecondAverage "RVMMulticoreSample capture bytecodesPerSecondAverage" "Answer the average of ratios of bytecodes executed per second during this sample" ^self cpuCoreStats bytecodesPerSecond average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadMostlys "RVMMulticoreSample capture bytesLeftReadMostlys" "Answer the collection of bytesLeftReadMostlys" ^self cpuCoreStats bytesLeftReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLeftReadWrites "RVMMulticoreSample capture bytesLeftReadWrites" "Answer the collection of bytesLeftReadWrites" ^self cpuCoreStats bytesLeftReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:50'! bytesLefts "RVMMulticoreSample capture bytesLefts" "Answer the collection of bytesLeft" ^self cpuCoreStats bytesLefts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:48'! bytesUsedReadMostlys "RVMMulticoreSample capture bytesUsedReadMostlys" "Answer the collection of bytesUsedReadMostlys" ^self cpuCoreStats bytesUsedReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:47'! bytesUsedReadWrites "RVMMulticoreSample capture bytesUsedReadWrites" "Answer the collection of bytesUsedReadWrites" ^self cpuCoreStats bytesUsedReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:24'! bytesUseds "RVMMulticoreSample capture bytesUseds" "Answer the collection of bytesUsed" ^self cpuCoreStats bytesUseds! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:59'! compactionsReadMostlys "RVMMulticoreSample capture compactionsSinceLastReadMostlys" "Answer the collection of compactionsSinceLastReadMostlys" ^self cpuCoreStats compactionsSinceLastReadMostlys! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 07:59'! compactionsReadWrites "RVMMulticoreSample capture compactionsReadWrites" "Answer the collection of compactionsSinceLastReadWrites" ^self cpuCoreStats compactionsSinceLastReadWrites! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 10/4/2008 08:00'! compactionsTotal "RVMMulticoreSample capture compactionsTotal" "Answer the collection of compactionsSinceLast" ^self cpuCoreStats compactionsSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:06'! contextChangeCounts "RVMMulticoreSample capture contextChangeCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats contextChangeCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ads 1/30/2011 15:23'! coreProcessUtilization ^RVMOperations coreProcessUtilization asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:52'! cyclesRunWaitRatios "RVMMulticoreSample capture cyclesRunWaitRatios" "Answer the collection of ratios during this sample" ^self cpuCoreStats cyclesRunWaitRatios! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesRunWaitRatiosAverage "RVMMulticoreSample capture cyclesRunWaitRatiosAverage" "Answer the average of ratios during this sample" ^self cpuCoreStats cyclesRunWaitRatios average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:49'! cyclesRunnings "RVMMulticoreSample capture cyclesRunnings" "Answer the collection of cyclesRunning counts during this sample" ^self cpuCoreStats cyclesRunnings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesRunningsAverage "RVMMulticoreSample capture cyclesRunningsAverage" "Answer the average of cyclesRunning counts during this sample" ^self cpuCoreStats cyclesRunnings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:30'! cyclesSinceLasts "RVMMulticoreSample capture cyclesSinceLasts" "Answer the cyclesSinceLasts during this sample" ^self cpuCoreStats cyclesSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 16:08'! cyclesSinceLastsAverage "RVMMulticoreSample capture cyclesSinceLastsAverage" "Answer the average cyclesSinceLasts during this sample" ^self cpuCoreStats cyclesSinceLasts average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:49'! cyclesWaitings "RVMMulticoreSample capture cyclesWaitings" "Answer the collection of cyclesWaiting counts during this sample" ^self cpuCoreStats cyclesWaitings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:14'! cyclesWaitingsAverage "RVMMulticoreSample capture cyclesWaitingsAverage" "Answer the average of cyclesWaiting counts during this sample" ^self cpuCoreStats cyclesWaitings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/5/2011 12:55'! gcMilliseconds "RVMMulticoreSample capture gcMilliseconds" ^ self cpuCoreStats gcMilliseconds! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! interruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats interruptCheckCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 8/17/2008 11:01'! millisecondsRunnings "RVMMulticoreSample capture millisecondsRunnings" "Answer the collection of msRunning counts during this sample" ^self cpuCoreStats millisecondsRunnings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:41'! millisecondsWaitings "RVMMulticoreSample capture millisecondsWaitings" "Answer the collection of millisecondsWaitings counts during this sample" ^self cpuCoreStats millisecondsWaitings! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:44'! msRunWaitRatios "RVMMulticoreSample capture msRunWaitRatios" "Answer the collection of ratios during this sample" ^self cpuCoreStats msRunWaitRatios! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:15'! msRunWaitRatiosAverage "RVMMulticoreSample capture msRunWaitRatiosAverage" "Answer the average of ratios during this sample" ^self cpuCoreStats msRunWaitRatios average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:29'! msRunningsAverage "RVMMulticoreSample capture msRunningsAverage" "Answer the average of millisecondsRunning counts during this sample" ^self cpuCoreStats millisecondsRunnings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:30'! msSinceLasts "RVMMulticoreSample capture msSinceLasts" "Answer the collection of msSinceLasts during this sample" ^self cpuCoreStats msSinceLasts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/15/2008 15:30'! msSinceLastsAverage "RVMMulticoreSample capture msSinceLastsAverage" "Answer the average msSinceLasts during this sample" ^self cpuCoreStats msSinceLasts average! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:43'! msWaitingsAverage "RVMMulticoreSample capture msWaitingsAverage" "Answer the average of msWaiting counts during this sample" ^self cpuCoreStats millisecondsWaitings average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ads 1/30/2011 15:23'! numberOfRunningProcesses ^RVMOperations numberOfRunningProcesses ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 7/16/2010 15:21'! processCount ^self processInstanceCount! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ads 1/30/2011 15:22'! processCountsPerCore | bag counts | bag _ (Process allInstances asOrderedCollection collect:[:obj| RVMOperations isRVM ifFalse:[RVMMonitor coreCount atRandom - 1]ifTrue:[RVMOperations getCoreHolding:obj]]) asBag. counts _ Array new: RVMMonitor coreCount. 1 to: RVMMonitor coreCount do:[:coreIndex| counts at: coreIndex put: (bag occurrencesOf: coreIndex)]. ^counts ! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:20'! receiveTallySum ^ self cpuCoreStats receiveTallySum! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ads 1/30/2011 15:23'! runningProcessCountsPerCore ^RVMOperations runningProcessByCore collect:[:obj| obj isNil ifTrue:[0] ifFalse:[1]]! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 3/27/2009 17:04'! sendTallySumsSortedReport "Answer a string report of the sorted send tallies across all cores" ^self cpuCoreStats sendTallySumsSortedReport! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:08'! unforcedInterruptCheckCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats unforcedInterruptCheckCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:17'! yieldCounts "RVMMulticoreSample capture yieldCounts" "Answer the collection of yields during this sample" ^self cpuCoreStats yieldCounts! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:18'! yieldCountsAverage "RVMMulticoreSample capture yieldCountsAverage" "Answer the average of yields during this sample" ^self cpuCoreStats yieldCounts average asFloat! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'dmu 1/1/1970 00:16'! yieldFrequencies "RVMMulticoreSample capture yieldFrequencies" ^self cpuCoreStats yieldFrequencies! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 16:36'! yieldsPerSecond "RVMMulticoreSample capture yieldsPerSecond" "Answer the collection of ratios of yields per second during this sample" ^self cpuCoreStats yieldsPerSecond! ! !RVMMulticoreSample methodsFor: 'measuring' stamp: 'ssa 8/14/2008 17:15'! yieldsPerSecondAverage "RVMMulticoreSample capture yieldsPerSecondAverage" "Answer the average of ratios of yields per second during this sample" ^self cpuCoreStats yieldsPerSecond average asFloat! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random1 "RVMMulticoreSample new random1" "generated data for testing visualization" ^1 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random10 "RVMMulticoreSample new random10" "generated data for testing visualization" ^10 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:01'! random100 "RVMMulticoreSample new random100" "generated data for testing visualization" ^100 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - system' stamp: 'ssa 10/3/2008 15:00'! random1000 "RVMMulticoreSample new random1000" "generated data for testing visualization" ^1000 atRandom! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0001To1 "RVMMulticoreSample new test0001To1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0001. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1 "RVMMulticoreSample new test0to1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to10 "RVMMulticoreSample new test0to10" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 10.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:32'! test0to100 "RVMMulticoreSample new test0to100" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 100.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^(testData copyFrom: 1 to: self numberOfCores) ! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:27'! test0to1B "RVMMulticoreSample new test0to1B" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000000000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1K "RVMMulticoreSample new test0to1K" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! test0to1M "RVMMulticoreSample new test0to1M" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ 0.0. end _ 1000000.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 10/7/2008 17:28'! testNeg1To1 "RVMMulticoreSample new testNeg1To1" "generated data for testing visualization" | testData start end | testData _ OrderedCollection new. start _ -1.0. end _ 1.0. start to: end by: end - start / self numberOfCores do:[:value| testData add: value]. ^testData copyFrom: 1 to: self numberOfCores! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:07'! testRandom1 "RVMMulticoreSample new testRandom1" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 1 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom10 "RVMMulticoreSample new testRandom10" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 10 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom100 "RVMMulticoreSample new testRandom100" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 100 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:06'! testRandom1000 "RVMMulticoreSample new testRandom1000" "generated data for testing visualization" | testData | testData _ OrderedCollection new. self numberOfCores timesRepeat:[ testData add: 1000 atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandom100s "RVMMulticoreSample new testRandom100s" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 100. max _ 999. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandom1Ks "RVMMulticoreSample new testRandom1Ks" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000. max _ 1999. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:04'! testRandomBs "RVMMulticoreSample new testRandomBs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000000000. max _ 999000000000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:05'! testRandomKs "RVMMulticoreSample new testRandomKs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000. max _ 999000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'test measuring - core' stamp: 'ssa 1/1/1970 00:04'! testRandomMs "RVMMulticoreSample new testRandomMs" "generated data for testing visualization" | testData min max delta | testData _ OrderedCollection new. min _ 1000000. max _ 999000000. delta _ max - min. self numberOfCores timesRepeat:[ testData add: min + delta atRandom]. ^testData! ! !RVMMulticoreSample methodsFor: 'co vs inco' stamp: 'ads 2/2/2011 14:52'! coinBytes " RVMOperations moveAllToReadMostlyHeaps. RVMOperations printCoInBytesUsed. Smalltalk garbageCollect. RVMOperations printCoInBytesUsed. RVMMulticoreSample capture coinBytes" ^self cpuCoreStats coreStats collect: [:stat | (stat memorySystemStats readWriteHeapStats bytesUsed @ stat memorySystemStats readMostlyHeapStats bytesUsed)]! ! !RVMMulticoreSample methodsFor: 'co vs inco' stamp: 'dmu 10/5/2008 00:26'! coinBytesTotal "Smalltalk garbageCollect. RVMMulticoreSample capture coinBytes" | s | s := 0 @ 0. self cpuCoreStats coreStats do: [:stat | s := s + (stat memorySystemStats readWriteHeapStats bytesUsed @ stat memorySystemStats readMostlyHeapStats bytesUsed)]. ^ s! ! !RVMMulticoreSample methodsFor: 'archiving' stamp: 'ssa 10/26/2008 21:12'! archiveOn: aStream | rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: RVMMonitor lastSample on: rw. aStream storeObject: self; storeClass: self class; store: rw reset. ! ! !RVMMulticoreSample methodsFor: 'copying' stamp: 'ssa 10/26/2008 21:08'! deepCopy "Use the RVMSampleWriter/Reader" | rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: self on: rw. RVMSampleReader dearchiveSampleFrom: rw reset ! ! !RVMMulticoreSample commentStamp: 'ssa 8/19/2008 11:52' prior: 0! two ways to capture a sample: RVMMulticoreSample captureSlow - uses a flexible but slower approach to handle data pairs " captureFast - fast, order dependent version (6x faster) " capture - calls captureFast "performance test" results := OrderedCollection new. 100 timesRepeat:[results add: (Time millisecondsToRun:[1000 timesRepeat:[RVMMulticoreSample captureFast]])/1000.0]. results average captureFast = 0.13813 captureSlow = 0.80164 MessageTally spyOn:[1000 timesRepeat:[RVMMulticoreSample captureFast]] shows a 6x improvement over captureSlow! !RVMMulticoreSample class methodsFor: 'examples' stamp: 'ssa 8/13/2008 15:13'! example "RVMMulticoreSample example" self capture explore! ! !RVMMulticoreSample class methodsFor: 'examples' stamp: 'ssa 9/9/2008 19:50'! examplePrimitive "RVMMulticoreSample examplePrimitive" self primitiveCapture inspect! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:07'! archiveVersion ^2! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:10'! dearchive: versionNumber from: aStream versionNumber = self archiveVersion ifTrue:[^self dearchiveFrom: aStream]. self error:'Can''t handle this archive version'! ! !RVMMulticoreSample class methodsFor: 'archiving' stamp: 'ssa 10/26/2008 22:07'! dearchiveFrom: aStream | rwStream sample | rwStream _ aStream next. sample _ RVMSampleReader dearchiveSampleFrom: rwStream reset. aStream storeObject: sample. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:48'! capture "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample capture" ^self captureFast! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:34'! captureFast "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureFast" | data sample | data := self primitiveCapture. sample := self new. sample initializeFastFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:03'! captureFastest "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureFastest" | data sample | data := self primitiveCapture. sample := self new. sample initializeFastestFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 8/19/2008 11:48'! captureSlow "Capture a sample from the vm and answer a new instance of me holding those values" "RVMMulticoreSample captureSlow" | data sample | data := self primitiveCapture. sample := self new. sample initializeFrom: data. ^sample! ! !RVMMulticoreSample class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:26'! newFrom: rawData "Answer a new instance of me holding these values" "RVMMulticoreSample newFrom: self primitiveCapture" | sample | sample := self new. sample initializeFastFrom: rawData. ^sample! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'ssa 10/18/2008 21:42'! primitiveCapture "Grab some data from the VM and return it" <primitive: 'primitiveSampleRVM' module: 'RVMPlugin'> [^RVMMonitor samples next]value. self primitiveFailed! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'dmu 4/10/2009 17:39'! primitiveCapture: flags "Grab some data from the VM and return it" <primitive: 'primitiveSampleRVM' module: 'RVMPlugin'> self primitiveFailed! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'dmu 4/10/2009 17:39'! primitiveCaptureOneCore "self primitiveCaptureOneCore" ^ self primitiveCapture: RVMSampleFlags everything - RVMSampleFlags allCores! ! !RVMMulticoreSample class methodsFor: 'primitive access' stamp: 'ssa 11/12/2008 12:23'! primitiveFlush "Clear out the sample buffer in the vm by grabbing a sample" <primitive: 'primitiveSampleRVM' module: 'RVMPlugin'> ! ! !RVMMulticoreSample class methodsFor: 'sample access' stamp: 'ssa 11/12/2008 12:23'! flush self primitiveFlush! ! !RVMMulticoreSample class methodsFor: 'sample access' stamp: 'ssa 1/1/1970 00:32'! next ^self capture! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 22:54'! aspectFromUserUnder: aSymbol "Answer a selected aspect categorized under #system, #core, #testSystem, #testCore." | menu | menu := CustomMenu new. (self aspectsUnder: aSymbol) do: [:aspect | menu add: aspect action: aspect]. ^menu startUp:nil withCaption: 'Select the aspect to monitor'. ! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:10'! aspects "Answer a list of message selectors that will return arrays of numbers for my monitor" ^(RVMMulticoreSample allMethodsInCategory: #measuring), (RVMMonitor showTestAspects ifTrue:[self testAspects]ifFalse:[#()])! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 22:51'! aspectsUnder: aSymbol "Answer the aspects categorized under #system, #core, #testSystem, #testCore." aSymbol == #system ifTrue:[^self systemAspects]. aSymbol == #core ifTrue:[^self coreAspects]. aSymbol == #testSystem ifTrue:[^self testSystemAspects]. aSymbol == #testCore ifTrue:[^self testCoreAspects]. ^self aspects! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'dmu 4/2/2009 02:09'! coreAspects "Answer a list of message selectors that will return collections of core numbers for my monitor" ^#(#allocationsReadWrites #allocationsReadMostlys #allocationsTotal #bytecodeCounts #bytecodesPerCycles #bytecodesPerKCs #bytecodesPerMCs #bytecodesPerMilliseconds #bytecodesPerSecond #bytesLeftReadWrites #bytesLeftReadMostlys #bytesLefts #bytesUsedReadWrites #bytesUsedReadMostlys #bytesUseds #compactionsReadWrites #compactionsReadMostlys #compactionsTotal #contextChangeCounts #cyclesRunWaitRatios #cyclesRunnings #cyclesSinceLasts #cyclesWaitings #interruptCheckCounts #millisecondsRunnings #millisecondsWaitings #msRunWaitRatios #msSinceLasts #unforcedInterruptCheckCounts #yieldCounts #yieldFrequencies #yieldsPerSecond #processCountsPerCore #runningProcessCountsPerCore)! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 3/26/2009 10:18'! coreTallyAspects "Answer a list of message selectors that will return tallies from core message tallies" ^RVMCoreMessageTally tallyOrder! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 7/16/2010 15:21'! systemAspects "Answer a list of message selectors that will return single system numbers for my monitor" ^#(#numberOfRunningProcesses #processCount #coreProcessUtilization #bytecodeCountsAverage #bytecodesPerCycle #bytecodesPerCyclesAverage #bytecodesPerMillisecond #bytecodesPerMillisecondsAverage #bytecodesPerSecondAverage #cyclesRunWaitRatiosAverage #cyclesRunningsAverage #cyclesSinceLastsAverage #cyclesWaitingsAverage #msRunWaitRatiosAverage #msRunningsAverage #msSinceLastsAverage #msWaitingsAverage #yieldCountsAverage #yieldsPerSecondAverage )! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^self testCoreAspects, self testSystemAspects! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testCoreAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^RVMMulticoreSample allMethodsInCategory: 'test measuring - core' asSymbol! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/3/2008 15:14'! testSystemAspects "Answer a list of message selectors that will return arrays of test numbers for my monitor" ^RVMMulticoreSample allMethodsInCategory: 'test measuring - system' asSymbol! ! !RVMMulticoreSample class methodsFor: 'aspect access' stamp: 'ssa 10/6/2008 18:46'! updateSystemAndCoreAspectMethods "RVMMulticoreSample updateSystemAndCoreAspectMethods" "Determine the lists of single value system aspects and multivalue core aspects and update the access methods for them" | all singles groups code sample | all _ RVMMulticoreSample allMethodsInCategory: #measuring. singles _ OrderedCollection new. groups _ OrderedCollection new. sample _ RVMMulticoreSample capture. all do:[:msg| ((sample perform: msg) isKindOf:Number)ifTrue:[singles add: msg]ifFalse:[groups add: msg]]. groups remove:#receiveTallySum ifAbsent:[]. code _ 'coreAspects "Answer a list of message selectors that will return collections of core numbers for my monitor" ^', groups asArray storeString. self class compile: code classified:'aspect access' notifying:nil. code _ 'systemAspects "Answer a list of message selectors that will return single system numbers for my monitor" ^', singles asArray storeString. self class compile: code classified:'aspect access' notifying:nil. ! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ads 1/30/2011 15:23'! activity "Answer the value of activity, whether or not you want the baton passed on a message send" ^RVMOperations getPassTheBatonOf: self object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/16/2008 02:11'! coreCoordinate "Answer the value of coreCoordinate" ^(self coreIndex + 1 asPointWithinRectangleWithExtent: RVMMonitor extent) ! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ads 1/30/2011 15:23'! coreIndex "Answer the value of coreIndex" ^(RVMOperations getCoreHolding: self object)! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ads 1/30/2011 15:23'! mutability "Answer the value of mutability, whether you are readWrite (true) or readMostly (false)" ^RVMOperations getReadWriteOf: self object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:29'! object "Answer the value of object" object isNil ifTrue:[self object: nil]. ^ object! ! !RVMObjectCoordinate methodsFor: 'accessing' stamp: 'ssa 11/13/2008 10:29'! object: anObject "Set the value of object" object _ anObject! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ads 1/30/2011 15:23'! makeActive RVMOperations isRVM ifTrue:[ RVMOperations setCoordinatesOf: self object toCore: self coreIndex readWrite: self mutability]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ads 1/30/2011 15:23'! makePassive RVMOperations isRVM ifTrue:[ RVMOperations setCoordinatesOf: self object toCore: self coreIndex readWrite: self mutability ]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ads 1/30/2011 15:23'! makeReadMostly RVMOperations isRVM ifTrue:[ RVMOperations setCoordinatesOf: self object toCore: self coreIndex readWrite: false ]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ads 1/30/2011 15:23'! makeReadWrite RVMOperations isRVM ifTrue:[ RVMOperations setCoordinatesOf: self object toCore: self coreIndex readWrite: true]. self changed! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ssa 11/16/2008 02:23'! moveToCoordinate: aPoint self moveToCore: (aPoint y -1 * RVMMonitor extent x + aPoint x) -1 . self changed:#coreCoordinate! ! !RVMObjectCoordinate methodsFor: 'moving' stamp: 'ads 1/30/2011 15:23'! moveToCore: anIndex RVMOperations isRVM ifTrue:[ RVMOperations setCoordinatesOf: self object toCore: (anIndex max:0) readWrite: self mutability ]. self changed! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isActive ^self activity = true! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isPassive ^self activity = false! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:26'! isReadMostly ^self mutability = false! ! !RVMObjectCoordinate methodsFor: 'testing' stamp: 'ssa 11/13/2008 10:25'! isReadWrite ^self mutability = true! ! !RVMObjectCoordinate class methodsFor: 'instance creation' stamp: 'ssa 11/16/2008 01:27'! for: anObject "Answer the coordinate for this object" | coord | coord _ self new. coord object: anObject. ^coord! ! !RVMObjectCoordinateView methodsFor: 'listening' stamp: 'ssa 11/15/2008 23:43'! hear: something self displayView! ! !RVMObjectCoordinateView methodsFor: 'listening' stamp: 'ssa 11/15/2008 23:44'! update self displayView! ! !RVMObjectCoordinateView class methodsFor: 'instance creation' stamp: 'ssa 5/12/2010 10:15'! on: anRVMObjectCoordinate "RVMObjectCoordinateView openOn: nil asObjectCoordinate " | mutabilityView readWriteButton readMostlyButton activityView passButton holdButton coreIndexView coordView tileCoordView | mutabilityView _ RVMView new. readWriteButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'readWrite' checkState: #isReadWrite whenChecked: #makeReadWrite whenUnchecked: [] monitor: true. readMostlyButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'readMostly' checkState: #isReadMostly whenChecked: #makeReadMostly whenUnchecked: [] monitor: true. mutabilityView addSubView: readWriteButton in:(0@0 extent: 1@0.5) borderWidth:0. mutabilityView addSubView: readMostlyButton in:(0@0.5 extent: 1@0.5) borderWidth:0. activityView _ RVMView new.. passButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'pass baton' checkState: #isActive whenChecked: #makeActive whenUnchecked: [] monitor: true. holdButton _ RVMRadioButtonView on: anRVMObjectCoordinate label: 'keep baton' checkState: #isPassive whenChecked: #makePassive whenUnchecked: [] monitor: true. activityView addSubView: passButton in:(0@0 extent: 1@0.5) borderWidth:0. activityView addSubView: holdButton in:(0@0.5 extent: 1@0.5) borderWidth:0. tileCoordView _ RVMGridLocationView on: anRVMObjectCoordinate pointGetter: #coreCoordinate pointSetter: #moveToCoordinate: extentGetter: [RVMMonitor extent]. coreIndexView _ RVMCoreIndexView on: anRVMObjectCoordinate getCoreIndex:#coreIndex setCoreIndex: #moveToCore: getAvailableIndicies: [RVMMonitor coreCount]. coordView _ self new. coordView addSubView: mutabilityView in:(0@0 extent: 1/3@1) borderWidth:1. coordView addSubView: activityView in:((1/3)@0 extent: 1/3@1) borderWidth:1. coordView addSubView: tileCoordView in:((2/3)@0 extent: 1/6@1) borderWidth:1. coordView addSubView: coreIndexView in:((5/6)@0 extent: 1/6@1) borderWidth:1. ^coordView ! ! !RVMObjectCoordinateView class methodsFor: 'instance creation' stamp: 'ssa 11/15/2008 15:52'! openOn: anRVMObjectCoordinate "RVMObjectCoordinateView openOn: nil asObjectCoordinate" "Add me to a system view and open me on the desktop" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 300@50. topView addSubView: (self on: anRVMObjectCoordinate) . topView label: 'Locating: ',anRVMObjectCoordinate object printString. topView controller open! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:20'! allocatedEntryCount "Answer the number of allocated entries in this object table" allocatedEntryCount isNil ifTrue:[^0]. ^allocatedEntryCount! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:20'! allocatedEntryCount: count "Set the number of allocated entries in this object table" allocatedEntryCount := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:43'! allocationsSinceLastQuery "Answer the allocations made since the last query" allocationsSinceLastQuery isNil ifTrue:[^0]. ^allocationsSinceLastQuery! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:44'! allocationsSinceLastQuery: count "Set the allocations made since the last query" allocationsSinceLastQuery := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:45'! entriesFreedSinceLastQuery "Answer the allocations freed since the last query" entriesFreedSinceLastQuery isNil ifTrue:[^0]. ^entriesFreedSinceLastQuery! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'dmu 8/15/2008 21:46'! entriesFreedSinceLastQuery: count "Set the allocations freed since the last query" entriesFreedSinceLastQuery := count! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:19'! entryCount "Answer the number of entries in this object table" entryCount isNil ifTrue:[^0]. ^entryCount! ! !RVMObjectTableStats methodsFor: 'acessing' stamp: 'ssa 7/21/2008 10:19'! entryCount: count "Set the number of entries in this object table" entryCount := count! ! !RVMOperations commentStamp: 'ads 1/24/2011 13:43' prior: 0! This was the original parking lot for various VM testing methods! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:52'! allObjectsInHeap: rank isReadWrite: isC "RVMOperations allObjectsInHeap: 34 isReadWrite: true" <primitive: 'primitiveAllObjectsInHeap' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'RS 7/25/2011 17:18'! awakeInterpreters <primitive: 'primitiveAwakeOtherInterpreters' module: 'RVMPlugin'> ^false! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! coreCount "RVMOperations coreCount" <primitive: 'primitiveCoreCount' module: 'RVMPlugin'> ^ 1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! coreProcessUtilization "RVMOperations coreProcessUtilization" "How many processes are running on my cores versus how many core??" ^self numberOfRunningProcesses / RVMMonitor coreCount! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! cycleCounter "RVMOperations cycleCounter" <primitive: 'primitiveCycleCounter' module: 'RVMPlugin' > ^ -1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! enableMultithreading: aBool "RVMOperations enableMultithreading: true" <primitive:'primitiveEnableMultithreading' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:01'! extraRemoteContextAllocations: n <primitive: 'primitiveExtraRemoteContextAllocations' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:01'! extraYields: n <primitive: 'primitiveExtraYields' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! getCore "RVMOperations getCore" <primitive: 'primitiveGetCore' module: 'RVMPlugin' > ^ -1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! getCoreIAmRunningOn "RVMOperations getCoreIAmRunningOn" <primitive: 'primitiveGetCoreIAmRunningOn' module: 'RVMPlugin' > ^ -1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:05'! getCoreTrace <primitive: 'primitiveTraceCores' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:03'! getMutatedReplicatedObjectsTrace <primitive: 'primitiveTraceMutatedReplicatedObjects' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ssa 1/1/1970 00:11'! getPassTheBatonOf: anObject <primitive: 'primitiveGetPassTheBaton' module: 'RVMPlugin'> ^ true! ! !RVMOperations class methodsFor: 'primitives' stamp: 'sm 5/26/2011 14:22'! isHeadless <primitive: 'primitiveRunsHeadless' module: 'RVMPlugin'> "The default is set to false to avoid problems if the primitive is not their in normal mode. Made this choice since most smalltalkers are not console users anyway. Stefan 2011-05-25" ^ false ! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 4/3/2009 03:40'! move: anObject toCore: anInt <primitive: 'primitiveSetCoordinatesFor' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 4/3/2009 03:40'! move: anObject toCore: anInteger readWritely: readWriteBoolean passTheBaton: batonBoolean <primitive: 'primitiveSetCoordinatesFor' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! moveAllToReadMostlyHeaps "RVMOperations moveAllToReadMostlyHeaps" <primitive: 'primitiveMoveAllToReadMostlyHeaps' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ssa 7/16/2010 14:59'! numberOfProcessInstances ^Process instanceCount! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:56'! numberOfRunningProcesses ^self runningProcesses size! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! primitiveRunningProcessByCore "Answers an array of numberOfCores size with a nil or Process instance for each core. If a Process instance then that process was running on that core when invoked" "RVMOperations primitiveRunningProcessByCore" <primitive: 'primitiveRunningProcessByCore' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! print: aString "RVMOperations print: 'hello'" <primitive: 'primitivePrint' > "omit module just as in thisProcess method to hit obsolete_named-primitive_table and be local"! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! printAllHeapsBytesUsed "RVMOperations printAllHeapsBytesUsed" <primitive: 'primitivePrintReadWriteReadMostlyBytesUsed' module: 'RVMPlugin'> ! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! printExecutionTrace "RVMOperations printExecutionTrace" " [ [ [ RVMOperations printExecutionTrace ] value ] value ] value" <primitive: 'primitivePrintExecutionTrace' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 10/1/2010 19:59'! printObjectForVMDebugging: obj "self printObjectForVMDebugging: 3@4" <primitive: 'primitivePrintObjectForVMDebugging' module: 'RVMPlugin'>! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! printStack "RVMOperations printStack" <primitive: 'primitivePrintStack' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'sm 2/24/2011 15:51'! printVMStatistics <primitive: 'primitivePrintStats' module: 'RVMPlugin'>! ! !RVMOperations class methodsFor: 'primitives' stamp: 'sm 5/26/2011 11:10'! resetPerfCounters "RVMPrimitives resetPerfCounters" <primitive: 'primitiveResetPerfCounters' module: 'RVMPlugin'>! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:02'! runMask: aMask <primitive: 'primitiveRunMask' module: 'RVMPlugin'>! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! runOnAll "RVMOperations runOnAll" self runOnlyOn: -1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:03'! runOnOne: aBool self runMask: ( aBool ifTrue: [1] ifFalse: [0] )! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:53'! runOnlyOn: anInt "RVMOperations runOnlyOn: 0" <primitive:'primitiveRunOnlyOn' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:47'! runningProcessByCore "Answers an array of numberOfCores size with a nil or Process instance for each core. If a Process instance then that process was running on that core when invoked" ^self primitiveRunningProcessByCore! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ssa 4/1/2009 21:48'! runningProcesses "Answers an array of Process instances that were running when invoked" ^self runningProcessByCore select:[:each| each notNil]! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:54'! setCoordinatesOf: anObject toCore: anInt readWrite: aBool "RVMOperations setCoordinatesOf: 3@4 toCore: 17 readWrite: false " <primitive: 'primitiveSetCoordinatesFor' module: 'RVMPlugin'> self primitiveFailed ! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:54'! setCoordinatesOf: anObject toCore: anInt readWrite: aBool passTheBaton: anotherBool "RVMOperations setCoordinatesOf: 3@4 toCore: 17 readWrite: false passTheBaton: false" <primitive: 'primitiveSetCoordinatesFor' module: 'RVMPlugin'> self primitiveFailed ! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:00'! setCoreTraceSize: n <primitive: 'primitiveTraceCores' module: 'RVMPlugin'>! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:06'! setMutatedReplicatedObjectsTraceSize: n <primitive: 'primitiveTraceMutatedReplicatedObjects' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:40'! shuffle: numCores ^ self shuffleFrom: 0 to: numCores - 1! ! !RVMOperations class methodsFor: 'primitives' stamp: 'dmu 1/1/1970 00:39'! shuffleFrom: first to: last <primitive: 'primitiveShuffle' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:54'! shuffleFrom: first to: last moveRWtoRM: bool1 moveRMtoRW: bool2 "RVMOperations shuffleFrom: 1 to: 17 moveRWtoRM: false moveRMtoRW: true" <primitive: 'primitiveShuffle' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:54'! soleRunningCore "RVMOperations soleRunningCore" <primitive:'primitiveRunOnlyOn' module: 'RVMPlugin'> self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'ads 2/2/2011 14:54'! spreadFrom: first to: last moveRWtoRM: bool1 moveRMtoRW: bool2 "RVMOperations spreadFrom: 1 to: 17 moveRWtoRM: true moveRMtoRW: false" <primitive: 'primitiveSpread' module: 'RVMPlugin'> ^ self primitiveFailed! ! !RVMOperations class methodsFor: 'primitives' stamp: 'RS 7/25/2011 17:17'! suspendButMainInterpreter <primitive: 'primitiveSuspendOtherInterpreters' module: 'RVMPlugin'> ^false! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:52'! changingSuperclassTest "RVMOperations changingSuperclassTest" "Create a class, then change its superclass and verify" Transcript cr;show:'Starting changing superclass test......'. #(Foo Bar Baz)do:[:n| Smalltalk removeClassNamed: n]. Object subclass: #Foo instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. Object subclass: #Bar instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. (Smalltalk classNamed:#Foo) subclass: #Baz instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. Transcript cr;show:'Foo, Bar and Baz test classes created, Baz is subclass of Foo, ready to try to change superclass to Bar'. (Smalltalk classNamed:#Bar) subclass: #Baz instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. (Smalltalk classNamed:#Baz) superclass == (Smalltalk classNamed:#Bar) ifTrue:[Transcript cr;show:'Successful....test passed'] ifFalse:[Transcript cr;show:'Nope....test failed']. Transcript cr;show:'Cleaning up....'. #(Foo Bar Baz)do:[:n| Smalltalk removeClassNamed: n]. Transcript cr;show:'...End of changing superclass test'. ! ! !RVMOperations class methodsFor: 'testing' stamp: 'dmu 1/11/2011 12:32'! cyclesToRun: blk | x | x _ self cycleCounter. blk value. ^ self cycleCounter - x ! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:53'! delayTest "RVMOperations delayTest" | rect delay | rect _ 0@0 extent: 40@40. delay _ Delay forSeconds: 1. [Sensor leftShiftDown not] whileTrue:[Display reverse: rect. delay wait] ! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:53'! methodDeletionTest "RVMOperations methodDeletionTest" "Create a test class and add 32 methods to it, then try to add 33" | testClassName testClass | testClassName := #RVMTESTforMethodDeletion. (Smalltalk includesKey: testClassName) ifTrue:[(Smalltalk at: testClassName) removeFromSystem]. Object subclass: testClassName instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. testClass := Smalltalk at: testClassName. Transcript cr;cr;show:'Test class created: ',testClassName. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 5 methods'. 1 to: 5 do:[:count| testClass compile: 'testMethod',count printString]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Removing 5 methods'. 1 to: 5 do:[:count| testClass removeSelector: ('testMethod',count printString) asSymbol]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. testClass selectors notEmpty ifTrue:[Transcript cr;show:'Test Failed']ifFalse:[Transcript cr;show:'test passed']. Transcript cr;show:'Removing test class: ',testClassName. testClass removeFromSystem. Transcript cr;show:'test class removed.... test over'. ! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:53'! methodDictionaryGrowthTest "RVMOperations methodDictionaryGrowthTest" "Create a test class and add 32 methods to it, then try to add 33" | testClassName testClass | testClassName := #RVMTESTforMethodDictionaryGrowth. (Smalltalk includesKey: testClassName) ifTrue:[(Smalltalk at: testClassName) removeFromSystem]. Object subclass: testClassName instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'RVM-Testing'. testClass := Smalltalk at: testClassName. Transcript cr;cr;show:'Test class created: ',testClassName. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 32 methods'. 1 to: 32 do:[:count| testClass compile: 'testMethod',count printString]. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Adding 33rd method'. testClass compile: 'testMethod33'. Transcript cr;show:'Method dictionary size = ',testClass selectors size printString. Transcript cr;show:'Removing test class: ',testClassName. testClass removeFromSystem. Transcript cr;show:'test class removed.... test over'. ! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:53'! runParallelCompilerBenchmarks: n "RVMOperations runParallelCompilerBenchmarks: 4" n timesRepeat: [[Benchmark new testCompiler. Transcript show: 'done'; cr] copy fixTemps fork]! ! !RVMOperations class methodsFor: 'testing' stamp: 'ads 2/2/2011 14:53'! segmentationFaultTest "RVMOperations segmentationFaultTest" "Executing this code produces a segmenation fault" | all singles groups file | Transcript cr;show:'test starting... segmentation fault test... writing to segfaultLog.txt'. file _ FileStream newFileNamed:'segfaultLog.txt'. all _ #(bytecodeCounts bytecodeCountsAverage bytecodesPerCycle bytecodesPerCycles bytecodesPerCyclesAverage bytecodesPerKCs bytecodesPerMCs bytecodesPerMillisecond bytecodesPerMilliseconds bytecodesPerMillisecondsAverage bytecodesPerSecond bytecodesPerSecondAverage bytesUseds contextChangeCounts cyclesRunWaitRatios cyclesRunWaitRatiosAverage cyclesRunnings cyclesRunningsAverage cyclesSinceLasts cyclesSinceLastsAverage cyclesWaitings cyclesWaitingsAverage interruptCheckCounts millisecondsRunnings millisecondsWaitings msRunWaitRatios msRunWaitRatiosAverage msRunningsAverage msSinceLasts msSinceLastsAverage msWaitingsAverage receiveTallySum unforcedInterruptCheckCounts yieldCounts yieldCountsAverage yieldFrequencies yieldsPerSecond yieldsPerSecondAverage). singles _ OrderedCollection new. groups _ OrderedCollection new. all do:[:msg| file nextPutAll:'Attempting ',msg,' '. file flush. ((RVMMonitor lastSample perform: msg) isKindOf:Number)ifTrue:[singles add: msg]ifFalse:[groups add: msg]]. file close. Transcript cr;show:'test passed.... test over'. ! ! !RVMOperations class methodsFor: 'testing' stamp: 'dmu 5/4/2009 23:51'! testAtRandom "self testAtRandom" | r n t | r _ Random new. n _ 0. 100000 timesRepeat: [ t _ 396 atRandom: r. n _ n + 1. t isInteger ifFalse: [self error: 'not int']. t < 0 ifTrue: [self error: 'neg' ]. t > 400 ifTrue: [self error: 'too big']. ]! ! !RVMOperations class methodsFor: 'testing' stamp: 'dmu 5/5/2009 00:24'! testNextInt "self testAtRandom" | r n t | r _ Random new. n _ 0. 100000 timesRepeat: [ t _ r nextInt: 396. n _ n + 1. t isInteger ifFalse: [self error: 'not int']. t < 0 ifTrue: [self error: 'neg' ]. t > 400 ifTrue: [self error: 'too big']. ]! ! !RVMOperations class methodsFor: 'demos' stamp: 'ads 2/2/2011 14:52'! colorTrail "RVMOperations colorTrail" | rect boxes centers count colors pen x y coreIndex | rect _ Rectangle fromUser. boxes _ rect subDivideBy: 8@8. centers _ boxes collect:[:box| box center]. count _ 500. colors _ Color hotColdShades:count. pen _ Pen new. pen defaultNib:6. pen combinationRule: Form paint. pen place: (centers at:32). x _ y _ 4. pen down. 1 to:count do:[:index|pen color: (colors at: index). x _ (x + (3 atRandom - 2))min:8 max:1. y _ (y + (3 atRandom - 2))min:8 max:1. coreIndex _ y - 1 * 8 + x. pen goto: (centers at:(coreIndex))]! ! !RVMOperations class methodsFor: 'demos' stamp: 'ads 1/30/2011 15:21'! displayImageOnReadMostlyStripChart "RVMOperations displayImageOnReadMostlyStripChart" "Works on readMostlyHeap tile strip chart" | f text images height width pixelOn | f _ Form fromDisplay:(0@0 extent: 200@200).. text _ 'IBM' asDisplayText asParagraph asForm magnifyBy:2. "logo _ GIFReadWriter formFromFileNamed: 'ibm-logo-bw.gif'. logo replaceColor: Color white with: Color transparent. face _ GIFReadWriter formFromFileNamed: 'sam-photo-bw.gif'. face replaceColor: Color white with: Color transparent." images _ OrderedCollection new. "images add: logo. images add: face." images add: text. images do:[:image| height _ image boundingBox height. width _ image boundingBox width. 0 to: width -1 do:[:x| 0 to: height - 1 do:[:y| pixelOn _ (image colorAt: x@y) isTransparent. RVMOperations move: f copy toCore: y + 3 readWritely: pixelOn passTheBaton: true. ]. RVMOperations move: f toCore: 1 readWritely: true passTheBaton: true.. RVMMonitor getSample;informListeners. Smalltalk garbageCollect. ]] ! ! !RVMOperations class methodsFor: 'demos' stamp: 'ads 2/2/2011 14:54'! spockToursTheRenaissance "RVMOperations spockToursTheRenaissance" 'Spock' rwPass24 rmHold2 rmPass40 rwHold0 rwPass55 ! ! !RVMOperations class methodsFor: 'filing out ' stamp: 'ads 2/2/2011 14:53'! fileOutAllRVMCategories "RVMOperations fileOutAllRVMCategories" | cats classNames classes orderedClasses fileStream | cats := SystemOrganization categoriesMatching: 'RVM-*'. classNames := OrderedCollection new. cats do: [:cat | classNames addAll: (SystemOrganization listAtCategoryNamed: cat)]. classes := classNames collect: [:n | Smalltalk at: n]. orderedClasses := ChangeSet superclassOrder: classes. fileStream := FileStream fileNamed: 'all-RVM-categories ' , Time now print24 , ' ' , (Date today printFormat: #(2 1 3 $- 1 2 2 )) , '.st'. orderedClasses do: [:cls | cls fileOutOn: fileStream]. fileStream close! ! !RVMOperations class methodsFor: 'teleportation' stamp: 'ssa 11/4/2008 23:39'! isMulticoreCoordinate: stringOrSymbol "Answer true if my unary selector matched the special multicore object coordinate format. {rm,rw}{Pass,Hold}{coreIndex, 0-55}" | readWrite baton coreIndex aSymbol | aSymbol _ stringOrSymbol asSymbol. aSymbol isUnary ifFalse:[^false]. aSymbol size >= 7 ifFalse:[^false]. readWrite _ aSymbol first: 2. (#('rw' 'rm') includes: readWrite) ifFalse:[^false]. baton _ aSymbol copyFrom: 3 to: 6. (#('Pass' 'Hold') includes: baton) ifFalse:[^false]. coreIndex _ aSymbol allButFirst:6. (coreIndex isAllDigits and:[(coreIndex _ coreIndex asNumber) between: 0 and: 55]) ifFalse:[^false]. ^true ! ! !RVMOperations class methodsFor: 'teleportation' stamp: 'ssa 11/16/2008 01:00'! teleport: anObject to: aSymbol "move this object to this multicore object coordinate. aSymbol := {in,co}{Pass,Hold}{coreIndex, 1-56}" | readWrite baton coreIndex old new | (self isMulticoreCoordinate: aSymbol) ifFalse:[self error:'Teleport aborted; bad coordinates = ',aSymbol]. readWrite _ (aSymbol first: 2) = 'rw'. baton _ (aSymbol copyFrom: 3 to: 6) = 'Pass'. coreIndex _ (aSymbol allButFirst:6) asNumber - 1 max: 0. old _ self printPrefixFor: anObject. self move: anObject toCore: coreIndex readWritely: readWrite passTheBaton: baton. Sensor leftShiftDown ifTrue:[new _ self printPrefixFor: anObject. Transcript cr;show:'Zzzoingggg!! ',anObject printString,' vanished from ',old. Transcript cr;show:'Ggggniozzz!! ',anObject printString,' appeared at ',new]. ! ! !RVMOperations class methodsFor: 'testing for RVM' stamp: 'ads 2/2/2011 14:53'! positiveIfOnRVM "RVMOperations positiveIfOnRVM" <primitive: 'primitiveCoreCount' module: 'RVMPlugin'> ^ -1! ! !RVMOperations class methodsFor: 'debugging' stamp: 'sm 5/27/2011 13:27'! breakpoint <primitive: 'primitiveBreakpoint' module: 'RVMPlugin' >! ! !RVMOperations class methodsFor: 'debugging' stamp: 'ads 1/30/2011 15:21'! randomWalk "RVMOperations randomWalk" [ [Sensor leftShiftDown not] whileTrue: [ Delay forMilliseconds: 250. RVMOperations move: false toCore: ( 0 max: (55 min: ( self getCoreHolding: false) + 3 atRandom - 2)) ]. Transcript show: 'killed'; cr ] fork. ! ! !RVMPluggableTextView methodsFor: 'model access' stamp: 'ssa 11/27/2008 13:06'! getText "Answer the list to be displayed." | txt | getTextSelector == nil ifTrue: [^ Text new]. txt _ getTextSelector isSymbol ifTrue:[model perform: getTextSelector]ifFalse:[getTextSelector value]. txt == nil ifTrue: [^ Text new]. self hasUnacceptedEdits: false. "clean now" ^ txt! ! !RVMPluggableTextView methodsFor: 'model access' stamp: 'ssa 11/27/2008 13:08'! setText: textToAccept from: ctlr "Inform the model of text to be accepted, and return true if OK. Any errors should be reported to the controller, ctlr." setTextSelector == nil ifTrue: [^ true]. setTextSelector isSymbol ifTrue: [^ model perform: setTextSelector with: textToAccept] ifFalse: [^ setTextSelector value: textToAccept]! ! !RVMPluggableTextView methodsFor: 'updating' stamp: 'ssa 11/27/2008 13:47'! update: aSymbol "Refer to the comment in View|update:. Do nothing if the given symbol does not match any action. " aSymbol == #updateDisplay ifTrue: [^ self updateDisplayContents]. ^super update: aSymbol! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 1/24/2011 12:47'! getCoreHolding: anObject ^(self primitivGetCoreHolding: anObject)! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 1/24/2011 12:57'! getEmergencySemaphore "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" "self getEmergencySemaphore signal" <primitive: 'primitiveEmergencySemaphore' module: 'RVMPlugin'>! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 1/24/2011 12:55'! getReadWriteOf: anObject <primitive: 'primitiveGetMutability' module: 'RVMPlugin'> ^ true! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 2/2/2011 14:54'! isRVM "RVMPrimitivesNeededForBootstrapping isRVM" "Am I actually running on the Tilera64?" ^(self getCoreHolding: nil) ~= -1! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 1/24/2011 12:47'! primitivGetCoreHolding: anObject <primitive: 'primitiveGetCore' module: 'RVMPlugin'> ^ -1! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 2/2/2011 14:54'! printPrefixFor: anObject "RVMPrimitivesNeededForBootstrapping printPrefixFor: Array " "Answer a string to use as a prefix in Inspectors and Debuggers when printing an object" | index readWrite | (anObject isKindOf: SmallInteger) ifTrue:[^'']. (anObject isKindOf: Boolean) ifTrue:[^'']. (anObject isNil) ifTrue:[^'']. index _ (self getCoreHolding: anObject) printString. readWrite _ (self getReadWriteOf: anObject) ifTrue: ['rw'] ifFalse: ['rm']. ^'<',readWrite,index,'> '! ! !RVMPrimitivesNeededForBootstrapping class methodsFor: 'as yet unclassified' stamp: 'ads 1/24/2011 12:57'! setEmergencySemaphore: aSemaOrNil "When you hit shift-control-a, the VM will signal the emergency semaphore, if it has been set to a semaphore" <primitive: 'primitiveEmergencySemaphore' module: 'RVMPlugin'>! ! !RVMProcessSwarm methodsFor: 'creation' stamp: 'dmu 2/22/2009 07:14'! initialize: aBlock | p | processes _ OrderedCollection new. 0 to: 55 do: [:i | p _ aBlock copy fixTemps newProcess. p coreMask: (1 bitShift: i). p resume. ].! ! !RVMProcessSwarm methodsFor: 'creation' stamp: 'ssa 2/26/2009 04:36'! initialize: aBlock onCores: aCollectionOfIndicies | p | aCollectionOfIndicies size timesRepeat:[ p _ aBlock copy fixTemps newProcess. p useOnlyCores: aCollectionOfIndicies. p resume. ].! ! !RVMProcessSwarm commentStamp: 'ads 2/2/2011 14:56' prior: 0! RVMProcessSwarm newRunning: [1000 timesRepeat:[10 factorial]]. 56 timesRepeat:[1000 timesRepeat:[10 factorial]] (Time millisecondsToRun:[1000 timesRepeat:[10 factorial]])/1000.0 ====> 1.5ms per 10 factorial (Time millisecondsToRun:[1000 timesRepeat:[10 factorial]]) ====> 1587ms per job (Time millisecondsToRun:[10 timesRepeat:[56 timesRepeat:[1000 timesRepeat:[10 factorial]]]])/10.0 87902.1 85059.2 91263 proc _ [RVMOperations print: ((Time millisecondsToRun:[10 timesRepeat:[56 timesRepeat:[1000 timesRepeat:[10 factorial]]]])/10.0) printString] copy fixTemps newProcess. proc coreMask: (1 bitShift: 4). proc resume. Process allInstances collect:[:proc| proc coreMask] Process instanceCount Process allInstances do:[:proc| proc coreMask:(1 bitShift:27)] [:x | x _ 10. [x] value] value: 2 Array locate. coord _ Array asObjectCoordinate. delay _ Delay forMilliseconds: 500. 0 to: 55 do:[:coreIndex|delay wait. coord moveToCore: coreIndex] Benchmark new testCompiler Process allInstancesDo:[:each| each coreMask: nil]. RVMOperations runOnlyOn: 8. RVMOperations runOnAll count _ 0. [[true] whileTrue:[0 to: 55 do: [:i | Processor thisProcess coreMask: (1 bitShift: i). Processor yield. 10 factorial. RVMOperations print: '[',count printString,'] finished on core ',Processor thisProcess hostCore printString]. count _ count +1]]fork Process allInstances collect:[:e| e coreMask] RVMOperations moveAllToReadMostlyHeaps "RVMProcessSwarm newRunning: [3000 factorial] onCores:(1 to: 10)" "RVMProcessSwarm newRunning: [RVMOperations print: Processor thisProcess hostCore factorial printString] onCores:#(1 3 5 7)" "RVMProcessSwarm newRunning: [3000 factorial. RVMOperations print: Processor thisProcess hostCore printString,' done'] onCores:(1 to: 10),(40 to:50) "! !RVMProcessSwarm class methodsFor: 'instance creation' stamp: 'ads 2/2/2011 14:55'! newRunning: aBlock "RVMProcessSwarm newRunning: [3000 factorial]" "RVMProcessSwarm newRunning: [RVMOperations print: Processor thisProcess hostCore factorial printString]" super new initialize: aBlock! ! !RVMProcessSwarm class methodsFor: 'instance creation' stamp: 'ads 2/2/2011 14:56'! newRunning: aBlock onCores: aCollectionOfIndicies "RVMProcessSwarm newRunning: [3000 factorial] onCores:(1 to: 10)" "RVMProcessSwarm newRunning: [RVMOperations print: Processor thisProcess hostCore factorial printString] onCores:#(1 3 5 7)" "RVMProcessSwarm newRunning: [3000 factorial. RVMOperations print: Processor thisProcess hostCore printString,' done'] onCores:(1 to: 10),(40 to:50) " super new initialize: aBlock onCores: aCollectionOfIndicies! ! !RVMRadioButtonView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:19'! buildCheckedBoxForm "Answer the check(ed) circle " | box aForm aCircle dot | box _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 2@2. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: box. dot _ Form dotOfSize: 10. dot displayOn: box at: box boundingBox center clippingBox: box boundingBox rule: Form paint fillColor:nil. ^box! ! !RVMRadioButtonView methodsFor: 'displaying' stamp: 'ssa 11/16/2008 00:19'! buildUncheckedBoxForm "Answer the uncheck(ed) circle " | box aForm aCircle | box _ Form extent:18@18 depth: Display depth. aForm _ Form extent: 2@2. aForm fillBlack. aCircle _ Circle new. aCircle form: aForm. aCircle radius: 9. aCircle center: 8@8. aCircle displayOn: box. ^box! ! !RVMRadioButtonView methodsFor: 'action' stamp: 'ssa 11/16/2008 01:26'! performAction "I've been clicked, switch state and act" | others | self checked: true. self performCheckAction. others _ self superView subViewsSatisfying: [:each| each ~~ self and:[each class == self class]]. others do:[:each| each checked: false. each performUncheckAction. each displayView]. self displayView ! ! !RVMRadioButtonView class methodsFor: 'examples' stamp: 'ssa 10/18/2008 23:34'! example "RVMRadioButtonView example" super example! ! !RVMRadioButtonView class methodsFor: 'examples' stamp: 'ssa 5/12/2010 10:15'! exampleRecording "RVMRadioButtonView exampleRecording" | topView offRadio loopRadio subViewCount longRadio fileRadio | topView := RVMStandardSystemView new . topView borderWidth:1. RVMRadioButtonView testState:#(true false false false false). offRadio _ RVMRadioButtonView on: self label: 'off' checkState: [RVMMonitor recordingMode = #off] whenChecked: [RVMMonitor recordingMode: #off] whenUnchecked: [] monitor: true. loopRadio _ RVMRadioButtonView on: self label: 'record last ',RVMMonitor sampleLimit printString,' samples' checkState: [RVMMonitor recordingMode = #loop] whenChecked: [RVMMonitor recordingMode: #loop] whenUnchecked: [] monitor: true. longRadio _ RVMRadioButtonView on: self label: 'record all samples' checkState: [RVMMonitor recordingMode = #long] whenChecked: [RVMMonitor recordingMode: #long] whenUnchecked: [] monitor: true. fileRadio _ RVMRadioButtonView on: self label: 'record all samples to a file' checkState: [RVMMonitor recordingMode = #file] whenChecked: [RVMMonitor recordingMode: #file] whenUnchecked: [] monitor: true. topView addSubView: offRadio. topView addSubView: loopRadio below: offRadio. topView addSubView: longRadio below: loopRadio. topView addSubView: fileRadio below: longRadio. topView label: 'Recording Options'. subViewCount _ topView subViews size. topView minimumSize: 100@(subViewCount*28). topView maximumSize: 200@topView minimumSize y. topView controller open! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 11/13/2010 17:41'! finishedReading self isRunningWritingProcess ifTrue: [^ self]. readerCountInterlock critical: [ readerCount > 1 ifTrue: [readerCount _ readerCount - 1] ifFalse: [ readerCount = 1 ifFalse: [self error: 'oops'] ifTrue: [ readerCount _ 0. readVsWriteInterlock signal ]]. ]! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 11/13/2010 16:29'! finishedWriting writingProcess _ nil. readVsWriteInterlock signal! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 11/13/2010 16:28'! initialize readerCount _ 0. readerCountInterlock _ Semaphore forMutualExclusion. readVsWriteInterlock _ Semaphore forMutualExclusion. writingProcess _ nil! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 11/13/2010 16:33'! isRunningWritingProcess ^ Processor thisProcess == writingProcess! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 11/13/2010 17:42'! startingToRead self isRunningWritingProcess ifTrue: [^ self]. readerCountInterlock critical: [ readerCount > 0 ifTrue: [readerCount _ readerCount + 1] ifFalse: [ readerCount = 0 ifFalse: [self error: 'oops'] ifTrue: [ readVsWriteInterlock wait. readerCount _ 1. ]]. ]! ! !RVMReadersWriterLock methodsFor: 'private' stamp: 'dmu 6/13/2011 23:53'! startingToWrite writingProcess == Processor thisProcess ifTrue: [self error: 'recursive write']. readVsWriteInterlock wait. writingProcess _ Processor thisProcess! ! !RVMReadersWriterLock methodsFor: 'public' stamp: 'dmu 11/12/2010 17:31'! guardForReading: blockWhichReads self startingToRead. ^ blockWhichReads ensure: [self finishedReading]! ! !RVMReadersWriterLock methodsFor: 'public' stamp: 'dmu 11/12/2010 17:31'! guardForWriting: blockWhichWrites self startingToWrite. ^ blockWhichWrites ensure: [self finishedWriting]! ! !RVMReadersWriterLock commentStamp: 'dmu 11/12/2010 17:26' prior: 0! I provide synchronization for multiple readers or one writer. I am not very clever. readerCount: how many readers are currently reading readerCountInterlock: protects readerCount readVsWriteInterlock: ensures that reading & writing do not happen at the same time, also ensures only one writer at a time Usage: x _ RVMReadersWriterLock new. x guardForReading: [ "read the data" ]. x guardForWriting: [ "write the data" ].! !RVMReadersWriterLock class methodsFor: 'as yet unclassified' stamp: 'dmu 11/12/2010 18:08'! crudeTest | x g p | "RVMReadersWriterLock crudeTest" "Flashes dots in upper row when reading, flashes dots in lower row when writing." x _ RVMReadersWriterLock new. g _ 0@0. 1 to: 10 do: [:i| [ [g x = 0] whileTrue. p _ (100@100) + ( (5*i) @ 0). 100 timesRepeat: [ x guardForReading: [ (Delay forMilliseconds: 10) wait. Display drawDot5At: p. (Delay forMilliseconds: 10) wait. Display eraseDot5At: p. ] ] ] copy fixTemps fork. ]. 1 to: 4 do: [:i| [ [g x = 0] whileTrue. p _ (100@110) + ( (5*i) @ 0). 100 timesRepeat: [ x guardForWriting: [ (Delay forMilliseconds: 10) wait. Display drawDot5At: p. (Delay forMilliseconds: 10) wait. Display eraseDot5At: p. ] ] ] copy fixTemps fork. ]. g x: 1! ! !RVMSBinarySampleWriter commentStamp: 'ssa 10/26/2008 23:51' prior: 0! A test to see if a completely flattened binary stream write method would be faster than the archiver. Not so!! this takes 4-6 seconds and generates a 600K file for a 56 core sample Archiver takes 0.7 sec and generates a 40K file! !RVMSBinarySampleWriter class methodsFor: 'sample writing' stamp: 'ssa 10/26/2008 23:48'! writeSample: aSample on: aStream "RVMSBinarySampleWriter writeSample: RVMMonitor lastSample on: (FileStream newFileNamed:'binary-sample-writer.test')" "Write the minimum data in aSample to aStream in binary format" | data subData innerCoreStats allSendTallies tallies rcvTallies memoryStats readWriteHeap readMostlyHeap interpStats objTableStats | data _ aSample rawData. aStream binary; nextNumber: 8 put: (data at: 2); "runMask" nextPut: ((data at: 4)) ; "extraYields" nextPut: ((data at: 6)). "extraRemoteContextAllocations" "remember messageNames" subData _ data at: 10. "groupStats" aStream nextPut: ((subData at: 2)); "mainX" nextPut: ((subData at: 4)); "mainY" nextPut: ((subData at: 6)); "mainRank" nextPut: ((subData at: 8)); "width" nextPut: ((subData at: 10)); "height" nextPut: ((subData at: 12)); "groupSize" nextPut: ((subData at: 14)). "remaining" subData _ data at: 12. "allCPUCoreStats" subData do:[:each| aStream nextInt32Put: (each at: 2); "millisecs" nextInt32Put: (each at: 4). "cycles" innerCoreStats _ each at: 6. aStream nextPut: ((innerCoreStats at: 2)); "x" nextPut: ((innerCoreStats at: 4)); "y" nextPut: ((innerCoreStats at: 6)). "rank" allSendTallies _ innerCoreStats at: 8. "sendTalliesByCore" allSendTallies do:[:sndTally| tallies _ allSendTallies at: 2. tallies do:[:tally| aStream nextWordPut: tally]. "a single send tally" ]. rcvTallies _ innerCoreStats at: 10. rcvTallies do:[:tally| aStream nextWordPut: tally]. "a single recieve tally" memoryStats _ each at: 8. "memorySystemStats" aStream nextWordPut: (memoryStats at: 2); "gcCount" nextInt32Put: (memoryStats at: 4); "gcMilliseconds" nextInt32Put: (memoryStats at: 6). "gcCycles" readWriteHeap _ memoryStats at: 8. "readWriteHeapStats" aStream nextInt32Put: (readWriteHeap at: 2); "bytesUsed()" nextInt32Put: (readWriteHeap at: 4); "bytesLeft()" nextInt32Put: (readWriteHeap at: 6); "allocationsSinceLastQuery" nextInt32Put: (readWriteHeap at: 8). "compactionsSinceLastQuery" readMostlyHeap _ memoryStats at: 10. "readMostlyHeapStats" aStream nextInt32Put: (readMostlyHeap at: 2); "bytesUsed()" nextInt32Put: (readMostlyHeap at: 4); "bytesLeft()" nextInt32Put: (readMostlyHeap at: 6); "allocationsSinceLastQuery" nextInt32Put: (readMostlyHeap at: 8). "compactionsSinceLastQuery" interpStats _ each at: 10. "interpreterStats" aStream nextInt32Put: (interpStats at: 2); "bytecodesExecuted" nextInt32Put: (interpStats at: 4); "yieldCount" nextNumber: 6 put: (interpStats at: 6); "cyclesRunning" nextNumber: 6 put: (interpStats at: 8); "cyclesWaiting" nextInt32Put: (interpStats at: 10); "contextChangeCount" nextInt32Put: (interpStats at: 12); "interruptCheckCount" nextInt32Put: (interpStats at: 14); "unforcedInterruptCheckCount" nextInt32Put: (interpStats at: 16); "numberOfMovedMutatedReadMostlyObjects" nextNumber: 6 put: (interpStats at: 18). "cyclesMovingMutatedReadMostlyObjects" ]. objTableStats _ data at: 14. "objectTableStats" aStream nextInt32Put: (objTableStats at: 2); "allocatedEntryCount" nextInt32Put: (objTableStats at: 4); "entryCount" nextInt32Put: (objTableStats at: 6); "allocationsSinceLastQuery" nextInt32Put: (objTableStats at: 8). "entriesFreedSinceLastQuery" aStream nextPut: ((data at: 16)); "extraRunPrimitives" nextPut: ((data at: 18)); "extraDoublewordBroadcasts" nextPut: ((data at: 20)); "extraWordBroadcasts" nextPut: (((data at: 22) ifTrue:[1]ifFalse:[0])); "dontPassTheBatonDefault" nextPut: (((data at: 24) ifTrue:[1]ifFalse:[0])). "fence" ! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:38'! cyclesSinceLastSample "Answer the number of processor cycles since the last sample was taken" cyclesSinceLastSample isNil ifTrue:[^0]. ^cyclesSinceLastSample! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 10:05'! cyclesSinceLastSample: count "Set the number of processor cycles since the last sample was taken" cyclesSinceLastSample := count! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! globalHeapStats "Answer the global heap stats for this sample" globalHeapStats isNil ifTrue:[self globalHeapStats: RVMGlobalHeapStats new]. ^globalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:40'! globalHeapStats: anRVMGlobalHeapStats "Set the global heap stats for this sample" globalHeapStats := anRVMGlobalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! localHeapStats "Answer the local heap stats for this sample" localHeapStats isNil ifTrue:[self localHeapStats: RVMLocalHeapStats new]. ^localHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 10:13'! localHeapStats: anRVMLocalHeapStats "Set the local heap stats for this sample" localHeapStats := anRVMLocalHeapStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:38'! millisecondsSinceLastSample "Answer the time since the last sample was taken" millisecondsSinceLastSample isNil ifTrue:[^0]. ^millisecondsSinceLastSample! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 09:37'! millisecondsSinceLastSample: milliseconds "Set the time since the last sample was taken" millisecondsSinceLastSample := milliseconds! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:29'! objectTableStats "Answer the object stats for this sample" objectTableStats isNil ifTrue:[self objectTableStats: RVMObjectTableStats new]. ^objectTableStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:45'! objectTableStats: anRVMObjectTableStats "Set the object stats for this sample" objectTableStats := anRVMObjectTableStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:25'! rawData "Answer the raw data for this sample" ^rawData! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:25'! rawData: anArray "Set the raw data for this sample" rawData := anArray! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:30'! squeakInterpreterStats "Answer the squeak interpreter stats for this sample" squeakInterpreterStats isNil ifTrue:[self squeakInterpreterStats: RVMSqueakInterpreterStats new]. ^squeakInterpreterStats! ! !RVMSample methodsFor: 'accessing' stamp: 'ssa 7/21/2008 11:22'! squeakInterpreterStats: anRVMSqueakInterpreterStats "Set the squeak interpreter stats for this sample" squeakInterpreterStats := anRVMSqueakInterpreterStats! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:31'! initializeFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self rawData: data. valueMap := { 'millisecs' -> #millisecondsSinceLastSample:. 'cycles' -> #cyclesSinceLastSample:. }. objectMap := { 'The_Global_Object_Heap.get_stats()' -> #initializeGlobalHeapStatsFrom:. 'The_Local_Object_Heap.get_stats()' -> #initializeLocalHeapStatsFrom:. 'The_Object_Table.get_stats()' -> #initializeObjectTableStatsFrom:. 'The_Squeak_Interpreter.get_stats()' -> #initializeSqueakInterpreterStatsFrom:. }. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:11'! initializeGlobalHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self initializeHeapStatsFrom: data into: self globalHeapStats. valueMap := {}. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self globalHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self globalHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:11'! initializeHeapStatsFrom: data into: aHeapStats "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'bytesUsed()' -> #bytesUsed:. 'bytesLeft()' -> #bytesLeft:. 'allocations_since_last_query' -> #allocationsSinceLastQuery:. 'compactions_since_last_query' -> #compactionsSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. aHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. aHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:12'! initializeLocalHeapStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | self initializeHeapStatsFrom: data into: self localHeapStats. valueMap := { 'objects_fetched_into_local_heap_since_last_query' -> #objectsFetchedSinceLastQuery:. 'overly_large_fetch_or_allocation_requests_denied_since_last_query' -> #overlyLargeFetchOrAllocationRequestsDeniedSinceLastQuery:. 'fetch_requests_that_failed_since_last_query' -> #failedFetchRequestsSinceLastQuery:. 'objects_flushed_since_last_query' -> #objectsFlushedSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self localHeapStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self localHeapStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:16'! initializeObjectTableStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'how_many_entries_are_currently_allocated' -> #allocatedEntryCount:. 'how_many_entries_exist' -> #entryCount:. 'how_many_allocations_have_occured_since_last_query' -> #allocationsMadeSinceLastQuery:. 'how_many_have_been_freed_since_last_query' -> #allocationsFreedSinceLastQuery:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self objectTableStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self objectTableStats perform: assoc value with: datum]. ! ! !RVMSample methodsFor: 'initialize' stamp: 'ssa 7/21/2008 11:19'! initializeSqueakInterpreterStatsFrom: data "Set my variables based on the data array. The data array is organized as a series of name-value pairs, where the names are strings and the values are either numbers, strings, symbols or an array of name-value pairs. This implementations assumes no order dependency in the array except that values always follow their names. Subarrays will be passed to another method like me that will factor them into appropriate subobjects." | valueMap objectMap index datum | valueMap := { 'bcCount - bytecodes' -> #bytecodeCount:. }. objectMap := {}. valueMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self squeakInterpreterStats perform: assoc value with: datum]. objectMap do:[:assoc | index := data indexOf: assoc key. index = 0 ifTrue:[self error:'Can''t find ',assoc key,' in sample data']. datum := data at: index + 1. self squeakInterpreterStats perform: assoc value with: datum]. ! ! !RVMSample class methodsFor: 'primitive access' stamp: 'ssa 7/21/2008 10:38'! primitiveCapture "Grab some data from the VM and return it" <primitive: 'primitiveSampleRVM' module: 'RVMPlugin'> self primitiveFailed! ! !RVMSample class methodsFor: 'instance creation' stamp: 'ssa 7/21/2008 11:23'! capture "Capture a sample from the vm and answer a new instance of me holding those values" | data sample | data := self primitiveCapture. sample := self new. sample initializeFrom: data. ^sample! ! !RVMSample class methodsFor: 'example' stamp: 'ssa 7/21/2008 11:24'! example "RVMSample example" self capture explore! ! !RVMSample class methodsFor: 'example' stamp: 'ssa 8/13/2008 15:05'! examplePrimitive "RVMSample examplePrimitive" self primitiveCapture explore! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! allCoreStats ^ 1 bitShift: 4! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! allCores ^ 1 bitShift: 0! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! bufferedMessageStats ^ 1 bitShift: 17! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! bytecodes ^ 1 bitShift: 21! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:27'! coreCoords ^ 1 bitShift: 14! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:28'! cpuCoreStats ^ 1 bitShift: 3! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! cycleCounts ^ 1 bitShift: 23! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! cycles ^ 1 bitShift: 8! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:29'! dontPassTheBatonDefault ^ 1 bitShift: 5! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:30'! everything ^ SmallInteger maxVal! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:31'! fence ^ 1 bitShift: 6! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:31'! gcStats ^ 1 bitShift: 19! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! heapStats ^ 1 bitShift: 20! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interactionStats ^ 1 bitShift: 13! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interpreterLoopStats ^ 1 bitShift: 27! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interpreterStats ^ 1 bitShift: 11! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:32'! interruptChecks ^ 1 bitShift: 24! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! memorySystemStats ^ 1 bitShift: 10! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! messageNames ^ 1 bitShift: 2! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! messageStats ^ 1 bitShift: 9! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! millisecs ^ 1 bitShift: 7! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:33'! movedMutatedObjectStats ^ 1 bitShift: 25! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! mutexStats ^ 1 bitShift: 26 ! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! objectTableStats ^ 1 bitShift: 12! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! receiveCycles ^ 1 bitShift: 18! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! receiveTallies ^ 1 bitShift: 16! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:34'! runMask ^ 1 bitShift: 1! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:35'! sendTallies ^ 1 bitShift: 15! ! !RVMSampleFlags class methodsFor: 'flag values' stamp: 'dmu 4/10/2009 17:35'! yieldCount ^ 1 bitShift: 22! ! !RVMSampleReader methodsFor: 'common entries' stamp: 'ssa 11/16/2008 15:12'! messageNames "Normally at index 8 in sample raw data array" ^#('noMessage' 'allocateOrRecycleContextMessage' 'allocateOrRecycleContextJustTestingMessage' 'recycleContextIfPossibleMessage' 'flushInterpreterCachesMessage' 'flushMethodCacheMessage' 'flushByMethodMessage' 'flushSelectiveMessage' 'addObjectFromSnapshotMessage' 'addObjectFromSnapshotResponse' 'updateWholeInterpreterMessage' 'updateEnoughInterpreterToTransferControlMessage' 'updateEnoughInterpreterToTransferControlJustTestingMessage' 'updateEnoughInterpreterToTransferControlJustTestingResponse' 'zapUnusedPortionOfHeapMessage' 'zapUnusedPortionOfHeapResponse' 'verifyInterpreterAndHeapMessage' 'doAllRootsThereMessage' 'doAllRootsThereResponse' 'doAllRootsHereMessage' 'hereIsARootResponse' 'newValueForOopMessage' 'noMoreRootsResponse' 'scanCompactOrMakeFreeObjectsMessage' 'scanCompactOrMakeFreeObjectsResponse' 'returnContextMessage' 'runPrimitiveMessage' 'runPrimitiveJustTestingMessage' 'runPrimitiveResponse' 'loadFunctionFromPluginMessage' 'loadFunctionFromPluginResponse' 'broadcastInterpreterDoublewordMessage' 'broadcastInterpreterWordMessage' 'broadcastInterpreterBoolMessage' 'sampleOneCoreMessage' 'sampleOneCoreResponse' 'initiateBarrierMessage' 'respondToBarrierMessage' 'aboutToWriteRead_MostlyMemoryMessage' 'aboutToWriteRead_MostlyMemoryResponse' 'wroteRead_MostlyMemoryMessage' 'flushFreeContextsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse' 'preGCActionMessage' 'preGCActionResponse' 'postGCActionMessage' 'postGCActionResponse' 'startAnotherProcessMessage' 'startAnotherProcessResponse' 'initContextMessage' 'initContextResponse' 'requestSafepointMessage' 'requestSafepointResponse' 'relinquishSafepointMessage' 'relinquishSafepointResponse')! ! !RVMSampleReader methodsFor: 'common entries' stamp: 'ssa 11/16/2008 15:12'! version1messageNames "Normally at index 8 in sample raw data array" ^#('allocateOrRecycleContextMessage' 'allocateOrRecycleContextJustTestingMessage' 'recycleContextIfPossibleMessage' 'flushInterpreterCachesMessage' 'flushMethodCacheMessage' 'flushByMethodMessage' 'flushSelectiveMessage' 'addObjectFromSnapshotMessage' 'addObjectFromSnapshotResponse' 'updateWholeInterpreterMessage' 'updateEnoughInterpreterToTransferControlMessage' 'updateEnoughInterpreterToTransferControlJustTestingMessage' 'updateEnoughInterpreterToTransferControlJustTestingResponse' 'zapUnusedPortionOfHeapMessage' 'zapUnusedPortionOfHeapResponse' 'verifyInterpreterAndHeapMessage' 'doAllRootsThereMessage' 'doAllRootsThereResponse' 'doAllRootsHereMessage' 'hereIsARootResponse' 'newValueForOopMessage' 'noMoreRootsResponse' 'scanCompactOrMakeFreeObjectsMessage' 'scanCompactOrMakeFreeObjectsResponse' 'returnContextMessage' 'runPrimitiveMessage' 'runPrimitiveJustTestingMessage' 'runPrimitiveResponse' 'loadFunctionFromPluginMessage' 'loadFunctionFromPluginResponse' 'broadcastInterpreterDoublewordMessage' 'broadcastInterpreterWordMessage' 'broadcastInterpreterBoolMessage' 'sampleOneCoreMessage' 'sampleOneCoreResponse' 'initiateBarrierMessage' 'respondToBarrierMessage' 'aboutToWriteReadMostlyMemoryMessage' 'aboutToWriteReadMostlyMemoryResponse' 'wroteReadMostlyMemoryMessage' 'flushFreeContextsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsMessage' 'enforceCoherenceBeforeSenderStoresIntoAllHeapsResponse' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapMessage' 'enforceCoherenceAfterEachCoreHasStoredIntoItsOwnHeapResponse' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapMessage' 'enforceCoherenceBeforeEachCoreStoresIntoItsOwnHeapResponse')! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 16:03'! nextAllCPUCoreStats | rawData | rawData _ OrderedCollection new. 56 timesRepeat:[rawData add: self nextCoreStats]. ^rawData asArray! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:31'! nextCoreStats | rawData | rawData _ Array new: 12. rawData at:1 put: 'millisecs'. rawData at:2 put: self next. rawData at:3 put: 'cycles'. rawData at:4 put: self next. rawData at:5 put: 'coreStats'. rawData at:6 put: self nextInnerCoreStats. rawData at:7 put: 'memorySystemStats'. rawData at:8 put: self nextMemorySystemStats. rawData at:9 put: 'interpreterStats'. rawData at:10 put: self nextInterpreterStats. rawData at:11put: 'objectTableStats'. rawData at:12 put: self nextObjectTableStats. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 16:00'! nextGroupStats | rawData | rawData _ Array new: 14. rawData at:1 put: 'mainX'. rawData at:2 put: self next. rawData at:3 put: 'mainY'. rawData at:4 put: self next. rawData at:5 put: 'mainRank'. rawData at:6 put: self next. rawData at:7 put: 'width'. rawData at:8 put: self next. rawData at:9 put: 'height'. rawData at:10 put: self next. rawData at:11 put: 'groupSize'. rawData at:12 put: self next. rawData at:13 put: 'remaining'. rawData at:14 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 19:52'! nextInnerCoreStats | rawData | rawData _ Array new: 11. rawData at:1 put: 'x'. rawData at:2 put: self next. rawData at:3 put: 'y'. rawData at:4 put: self next. rawData at:5 put: 'rank'. rawData at:6 put: self next. rawData at:7 put: 'sendTalliesByCore'. rawData at:8 put: self nextSendTalliesByCore. rawData at:9 put: 'receiveTallies'. rawData at:10 put: self nextReceiveTallies. rawData at:11 put: #(). ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:24'! nextInterpreterStats | rawData | rawData _ Array new: 18. rawData at:1 put: 'bytecodesExecuted'. rawData at:2 put: self next. rawData at:3 put: 'yieldCount'. rawData at:4 put: self next. rawData at:5 put: 'cyclesRunning'. rawData at:6 put: self next. rawData at:7 put: 'cyclesWaiting'. rawData at:8 put: self next. rawData at:9 put: 'contextChangeCount'. rawData at:10 put: self next. rawData at:11 put: 'interruptCheckCount'. rawData at:12 put: self next. rawData at:13 put: 'unforcedInterruptCheckCount'. rawData at:14 put: self next. rawData at:15 put: 'numberOfMovedMutatedRead_MostlyObjects'. rawData at:16 put: self next. rawData at:17 put: 'cyclesMovingMutatedRead_MostlyObjects'. rawData at:18 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 20:10'! nextMemorySystemStats | rawData heap | rawData _ Array new: 10. rawData at:1 put: 'gcCount'. rawData at:2 put: self next. rawData at:3 put: 'gcMilliseconds'. rawData at:4 put: self next. rawData at:5 put: 'gcCycles'. rawData at:6 put: self next. rawData at:7 put: 'readWriteHeapStats'. heap _ Array new:8. heap at: 1 put:'bytesUsed()'. heap at: 2 put:self next. heap at: 3 put:'bytesLeft()'. heap at: 4 put:self next. heap at: 5 put:'allocationsSinceLastQuery'. heap at: 6 put:self next. heap at: 7 put:'compactionsSinceLastQuery'. heap at: 8 put: self next. rawData at:8 put: heap. rawData at:9 put: 'readMostlyHeapStats'. heap _ Array new:8. heap at: 1 put:'bytesUsed()'. heap at: 2 put:self next. heap at: 3 put:'bytesLeft()'. heap at: 4 put:self next. heap at: 5 put:'allocationsSinceLastQuery'. heap at: 6 put:self next. heap at: 7 put:'compactionsSinceLastQuery'. heap at: 8 put: self next. rawData at:10 put: heap. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:25'! nextObjectTableStats | rawData | rawData _ Array new: 8. rawData at:1 put: 'allocatedEntryCount[rank]'. rawData at:2 put: self next. rawData at:3 put: 'entryCount[rank]'. rawData at:4 put: self next. rawData at:5 put: 'allocationsSinceLastQuery[rank]'. rawData at:6 put: self next. rawData at:7 put: 'entriesFreedSinceLastQuery[rank]'. rawData at:8 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 20:00'! nextReceiveTallies ^ self next asArray! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 11/16/2008 15:15'! nextSample | rawData | rawData _ Array new: 22. rawData at:1 put: 'runMask'. rawData at:2 put: self next. rawData at:3 put: 'extraYields'. rawData at:4 put: self next. rawData at:5 put: 'extraRemoteContextAllocations'. rawData at:6 put: self next. rawData at:7 put: 'messageNames'. rawData at:8 put: self messageNames. self next. "consume #messageNames" rawData at:9 put: 'groupStats'. rawData at:10 put: self nextGroupStats. rawData at:11 put: 'allCPUCoreStats'. rawData at:12 put: self nextAllCPUCoreStats. rawData at:13 put: 'extraRunPrimitives'. rawData at:14 put: self next. rawData at:15 put: 'extraDoublewordBroadcasts'. rawData at:16 put: self next. rawData at:17 put: 'extraWordBroadcasts'. rawData at:18 put: self next. rawData at:19 put: 'dontPassTheBatonDefault'. rawData at:20 put: self next. rawData at:21 put: 'fence'. rawData at:22 put: self next. ^rawData! ! !RVMSampleReader methodsFor: 'reading' stamp: 'ssa 10/26/2008 19:58'! nextSendTalliesByCore | rawData | rawData _ Array new: 112. 1 to: 111 by: 2 do:[:index| rawData at: index put: 'sendTallies'. rawData at: index + 1 put: self next asArray]. ^rawData ! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 15:51'! dearchive: aString "RVMSampleReader dearchive: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:24'! dearchiveRawData: aString "RVMSampleReader dearchiveRawData: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:27'! dearchiveRawDataFrom: aStream "| rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: rw. RVMSampleReader dearchiveRawDataFrom: rw reset " | anObject aReader | aReader _ self on: aStream. anObject _ aReader nextSample. ^anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:27'! dearchiveSample: aString "RVMSampleReader dearchiveSample: 'sample-writer.test' " | aStream anObject | aStream _ self on: (self fastStreamOn: aString). anObject _ aStream nextSample. aStream close. ^RVMMulticoreSample newFrom:anObject! ! !RVMSampleReader class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:28'! dearchiveSampleFrom: aStream "| rw | rw _ ReadWriteStream on:''. RVMSampleWriter archiveSample: RVMMonitor lastSample on: rw. RVMSampleReader dearchiveSampleFrom: rw reset " | anObject aReader | aReader _ self on: aStream. anObject _ aReader nextSample. ^RVMMulticoreSample newFrom:anObject! ! !RVMSampleWriter methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:04'! rawData "Answer the value of rawData" ^ rawData! ! !RVMSampleWriter methodsFor: 'accessing' stamp: 'ssa 10/26/2008 15:04'! rawData: anObject "Set the value of rawData" rawData _ anObject! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:42'! archiveAllCPUCoreStats: data "Archive the rawData I have from the sample, minimizing space" | datum | data do:[:batch| 2 to: batch size by: 2 do:[:index| datum _ batch at: index. index = 6 ifTrue:[self archiveCoreStats: datum] ifFalse:[index = 8 ifTrue:[self archiveMemorySystemStats: datum] ifFalse:[(#(10 12) includes:index) ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:18'! archiveCoreStats: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self archiveSendTalliesByCore: datum] ifFalse:[index = 10 ifTrue:[self archiveRecieveTallies: datum] ifFalse:[self nextPut:datum]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:25'! archiveMemorySystemStats: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[index = 10 ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:25'! archiveNameValuePairArray: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. self nextPut: datum]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:20'! archiveRecieveTallies: data "Archive the rawData I have from the sample, minimizing space" self nextPut: data asRunArray ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 11/16/2008 15:31'! archiveSampleData "Archive the rawData I have from the sample, minimizing space" | data datum | data _ self rawData. 2 to: data size by: 2 do:[:index| datum _ data at: index. index = 8 ifTrue:[self nextPut: #messageNames] ifFalse:[index = 12 ifTrue:[self archiveAllCPUCoreStats: datum] ifFalse:[(index = 10) ifTrue:[self archiveNameValuePairArray: datum] ifFalse:[self nextPut:datum]]]]. ! ! !RVMSampleWriter methodsFor: 'archiving' stamp: 'ssa 10/26/2008 15:19'! archiveSendTalliesByCore: data "Archive the rawData I have from the sample, minimizing space" | datum | 2 to: data size by: 2 do:[:index| datum _ data at: index. self nextPut: datum asRunArray]. ! ! !RVMSampleWriter methodsFor: 'private' stamp: 'ssa 7/7/2010 13:13'! setStream: aWriteStream "Since I only store arrays of numbers, use plain Dictionarys" stream _ aWriteStream. classMap _ Dictionary new: 30. classMap at: self put: 1. objectMap _ Dictionary new: 400. position _ 0 ! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:23'! archive: rawData to: aString "use the other specific versions of me" self shouldNotImplement! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:26'! archiveRawData: rawData on: aStream "RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: (ReadWriteStream on:'')" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | writer | writer _ self on: aStream. writer rawData: rawData. writer archiveSampleData. ^aStream! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:22'! archiveRawData: rawData to: aString "RVMSampleWriter archiveRawData: (RVMMonitor samples first) to: 'sample-writer.test'" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | stream writer | stream _ self fastStreamOn: aString. writer _ self on: stream. writer rawData: rawData. writer archiveSampleData. writer close.! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/28/2008 19:26'! archiveSample: aMulticoreSample on: aStream "RVMSampleWriter archiveRawData: (RVMMonitor samples first) on: (ReadWriteStream on:'')" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | writer | writer _ self on: aStream. writer rawData: aMulticoreSample rawData. writer archiveSampleData. ^aStream! ! !RVMSampleWriter class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 20:23'! archiveSample: aMulticoreSample to: aString "RVMSampleWriter archiveRawData: (RVMMonitor samples first) to: 'sample-writer.test'" "rawData is expected to be the array of sample data obtained from the RVMMulticoreSample primitiveCapture primitive." | stream writer | stream _ self fastStreamOn: aString. writer _ self on: stream. writer rawData: aMulticoreSample rawData. writer archiveSampleData. writer close.! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 15:21'! drawOnCanvas | color colorIndex | 1 to: self count do: [:index | colorIndex := ((self data at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0. ! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:37'! eraseStrip self resetScannerLocation. super eraseStrip.! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:02'! nextScannerLocation "Answer the next location for the scanner" self scannerLocation: self scannerLocation + self boxSize. ^self scannerLocation! ! !RVMScanningStripChartView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:41'! redrawOnCanvas | color colorIndex | self canvas fillWhite. self resetScannerLocation. self previousData do:[:oldData| 1 to: self count do: [:index | colorIndex := ((oldData at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self scanner fill: (self boxes at: index) fillColor: color]. self scanner displayOn: self canvas at: self nextScannerLocation @ 0]! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 15:20'! box "Answer the value of box" box isNil ifTrue:[self box: (0@0 extent: self boxSize @ self scanner boundingBox height)]. ^box! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:37'! resetScannerLocation scannerLocation _ nil! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:27'! scanner "Answer the value of scanner" scanner isNil ifTrue:[self scanner: (ColorForm extent: self boxSize * 3 @self canvas height depth:8)]. ^ scanner! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:31'! scanner: anObject "Set the value of scanner" scanner _ anObject. scanner fillWhite. scanner border: scanner boundingBox width:1 fillColor:Color black. '< < < < < < < < < < < < < < < <' asParagraph asForm displayOn: scanner at: scanner boundingBox topCenter - (1@0). scanner border: scanner boundingBox width:1 ! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 15:24'! scannerLocation "Answer the value of scannerLocation" scannerLocation isNil ifTrue:[self scannerLocation: self boxSize negated]. ^ scannerLocation! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:15'! scannerLocation: anInteger "Set the value of scannerLocation" anInteger > self canvas boundingBox width ifTrue:[scannerLocation _ self boxSize negated] ifFalse:[scannerLocation _ anInteger]! ! !RVMScanningStripChartView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:49'! typeLabel ^'RelScan: '! ! !RVMSqueakInterpreterStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:21'! cyclesRunWaitRatio "Answer the ratio between my cyclesRunning and cyclesWaiting" ^self cyclesWaiting = 0 ifTrue:[0] ifFalse:[self cyclesRunning / (1 max: self cyclesWaiting) asFloat]! ! !RVMSqueakInterpreterStats methodsFor: 'measuring' stamp: 'dmu 9/17/2010 15:21'! msRunWaitRatio "Answer the ratio between my millisecondsRunning and millisecondsWaiting" ^self millisecondsWaiting = 0 ifTrue:[0] ifFalse:[self millisecondsRunning / (1 max: self millisecondsWaiting) asFloat]! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:27'! bytecodesExecuted "Answer the number of bytecodes processed since last query" bytecodesExecuted isNil ifTrue:[^0]. ^bytecodesExecuted! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:27'! bytecodesExecuted: count "Set the number of bytecodes processed since last query" bytecodesExecuted := count! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! contextChangeCount "Answer the value of contextChangeCount" contextChangeCount isNil ifTrue:[self contextChangeCount: 0]. ^contextChangeCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:10'! contextChangeCount: anObject "Set the value of contextChangeCount" contextChangeCount := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! cyclesRunning "Answer the value of cyclesRunning" cyclesRunning isNil ifTrue:[self cyclesRunning: 0]. ^cyclesRunning! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! cyclesRunning: anObject "Set the value of cyclesRunning" cyclesRunning := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! cyclesWaiting "Answer the value of cyclesWaiting" cyclesWaiting isNil ifTrue:[self cyclesWaiting: 0]. ^cyclesWaiting! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! cyclesWaiting: anObject "Set the value of cyclesWaiting" cyclesWaiting := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! interruptCheckCount ^ interruptCheckCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! interruptCheckCount: x interruptCheckCount := x! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! millisecondsRunning "Answer the value of millisecondsRunning" millisecondsRunning isNil ifTrue:[self millisecondsRunning: 0]. ^millisecondsRunning! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:24'! millisecondsRunning: anObject "Set the value of msRunning" millisecondsRunning := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:01'! millisecondsWaiting "Answer the value of msWaiting" millisecondsWaiting isNil ifTrue:[self millisecondsWaiting: 0]. ^millisecondsWaiting! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 8/15/2008 21:25'! millisecondsWaiting: anObject "Set the value of msWaiting" millisecondsWaiting := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:04'! unforcedInterruptCheckCount ^ unforcedInterruptCheckCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:03'! unforcedInterruptCheckCount: x unforcedInterruptCheckCount := x! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! yieldCount "Answer the value of yieldCount" yieldCount isNil ifTrue:[self yieldCount: 0]. ^yieldCount! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'ssa 8/13/2008 18:13'! yieldCount: anObject "Set the value of yieldCount" yieldCount := anObject! ! !RVMSqueakInterpreterStats methodsFor: 'accessing' stamp: 'dmu 9/17/2010 15:21'! yieldFrequency "Answer the value of yieldCount/contextChangeCount" ^self contextChangeCount = 0 ifTrue: [0] ifFalse: [(self yieldCount / (1 max: self contextChangeCount)) asFloat]! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 8/20/2008 19:15'! displayLabelText "The label goes in the center of the window" | labelRect | labelText foregroundColor: Color black backgroundColor: self labelColor. labelRect := self labelTextRegion. Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor. labelText displayOn: Display at: labelRect topLeft clippingBox: labelRect rule: labelText rule fillColor: labelText fillColor. labelText destinationForm: nil! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:02'! displayView self okToDisplay: true. super displayView! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! dontDisplayWhile: aBlock "Switch my okToDisplay flag off during this block" self okToDisplay: false. aBlock value. self okToDisplay: true. self displayView! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! erase self okToDisplay: false. ^super erase! ! !RVMStandardSystemView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 00:21'! okToDisplay: aBoolean self subViews do:[:v| v isRVMView ifTrue:[v okToDisplay: aBoolean]]. ! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:24'! constrainFrame: aRectangle "Constrain aRectangle, to the minimum and maximum size for this window" | adjustmentForLabel bWidth | bWidth _ labelFrame borderWidth. (bWidth isKindOf: Rectangle) ifTrue:[bWidth _ bWidth origin x]. adjustmentForLabel := 0 @ (labelFrame height - bWidth). ^ aRectangle origin extent: ((aRectangle extent max: minimumSize + adjustmentForLabel) min: maximumSize + adjustmentForLabel).! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:51'! initialExtent ^self minimumSize! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:25'! newFrame self subViews do:[:v| v isRVMView ifTrue:[v newFrame]]! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:15'! newFrame: frameChangeBlock super newFrame: frameChangeBlock. self subViews do:[:v| v isRVMView ifTrue:[v newFrame]]! ! !RVMStandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:14'! resizeInitially "Determine the rectangular area for the receiver, adjusted to the minimum and maximum sizes." self resizeTo: self initialFrame. self subViews do:[:v| v isRVMView ifTrue:[v firstFrame]] ! ! !RVMStandardSystemView methodsFor: 'accessing' stamp: 'ssa 10/4/2008 08:29'! subViews: aCollection. subViews _ aCollection! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:56'! eraseStrip self view traces do:[:trace| trace removeAllData]. self view canvas:nil. self view displayView! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 01:00'! inspectScaler self view traces first scaler inspect! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 12:59'! muteAll self view traces do:[:trace| trace mute]. self view topView allSubViews do:[:v|( v isKindOf: RVMCheckBoxOnlyView) ifTrue:[v update:#checked]]! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/20/2008 09:02'! spawnUnmuted | unmutes | unmutes _ self view traces select:[:trace| trace muted not]. self view okToDisplay: true. RVMStripChartView openOnTraces: unmutes deepCopy titled: 'Selected traces'! ! !RVMStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 12:59'! unmuteAll self view traces do:[:trace| trace unmute]. self view topView allSubViews do:[:v|( v isKindOf: RVMCheckBoxOnlyView) ifTrue:[v update:#checked]]! ! !RVMStripChartController methodsFor: 'controlling' stamp: 'ssa 10/20/2008 08:21'! yellowButtonActivity | menu answer | self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := CustomMenu new. "menu add: 'inspect scaler' action: #inspectScaler." menu add: 'mute all' action: #muteAll. menu add: 'unmute all' action: #unmuteAll. menu add: 'spawn unmuted' action: #spawnUnmuted. menu addLine. menu add: 'erase strip' action: #eraseStrip. answer := menu startUp: #eraseStrip withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer]]]! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:33'! addCoreTrace | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample coreAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a core aspect to trace' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view stripChart addCoreTraceForAspect: selectedAspect coreIndex: RVMMonitor coreIndexFromUser]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:36'! addSystemTrace | menu selectedAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. RVMMulticoreSample systemAspects do:[:aspect| menu add: aspect action: aspect]. selectedAspect := menu startUp: nil withCaption: 'Select a system aspect to trace' at: Sensor cursorPoint. selectedAspect notNil ifTrue:[ self view stripChart addSystemTraceForAspect: selectedAspect]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 10/3/2008 23:12'! changeAspect | menu answer newAspect | self view topView dontDisplayWhile:[ menu := CustomMenu new. menu add: 'System aspects' action: #system. menu add: 'Core aspects' action: #core. menu add: 'Test System Aspects' action: #testSystem. menu add: 'Test Core Aspects' action: #testCore. answer := menu startUp: nil withCaption: 'What kind of aspect would you like to monitor?' at: Sensor cursorPoint. answer isNil ifTrue:[^self]. newAspect _ RVMMulticoreSample aspectFromUserUnder: answer. newAspect isNil ifTrue:[^self]. newAspect = self view stripChart traces first aspect ifTrue:[^self]. self view stripChart removeAllTraces. (#(testCore core) includes: answer) ifTrue:[self view stripChart addCoreTraceForAspect: newAspect coreIndex: RVMMonitor coreIndexFromUser] ifFalse:[self view stripChart addSystemTraceForAspect: newAspect]. self view currentTrace: self view stripChart traces first]. self view hear: nil. self view stripChart newFrame.! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:31'! changeScaleAspect | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Show scale for this aspect:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view currentTrace: selectedTrace]]. self view hear: nil! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 11/11/2008 22:06'! redButtonActivity ((self view adjustScaleBox translateBy: self view insetDisplayBox origin) containsPoint: Sensor cursorPoint) ifTrue:[Sensor waitNoButton. self spawnScaleAdjuster]! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:08'! removeOtherTraces | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Remove all traces except:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view stripChart removeTraces: (self view stripChart traces copyWithout: selectedTrace). self view currentTrace: selectedTrace]]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:07'! removeTrace | menu selectedTrace | self view topView dontDisplayWhile:[ menu := CustomMenu new. self view stripChart traces do:[:trace| menu add: trace aspect action: trace]. selectedTrace := menu startUp: self view currentAspect withCaption: 'Select trace to remove:' at: Sensor cursorPoint. selectedTrace notNil ifTrue:[ self view stripChart removeTrace: selectedTrace. self view currentTrace = selectedTrace ifTrue:[self view currentTrace: nil]]. ]. self view stripChart rebuildAll. ! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:05'! scalerForThisAspect self view okToDisplay:true. RVMColoredDataScalerView openOnAspect: self view currentTrace aspect! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 5/12/2010 10:20'! spawnScaleAdjuster | maxView minView topView resetScaleButton setToObservedButton autoScaleCheckBox height | maxView _ RVMValueEditorView on: view currentTrace scaler valueGetter: [view currentTrace scaler max] valueSetter:[:v|view currentTrace scaler setMax:v. view drawCanvas; displayView] label:'max: '. maxView lockGetter:#maxLocked; lockSetter:#maxLocked:. minView _ RVMValueEditorView on: view currentTrace scaler valueGetter: [view currentTrace scaler min] valueSetter:[:v|view currentTrace scaler setMin:v. view drawCanvas; displayView] label:'min: '. minView lockGetter:#minLocked; lockSetter:#minLocked:. resetScaleButton _ RVMButtonView label:'Reset scale to default' action:[view currentTrace scaler resetScaling. view drawCanvas; displayView. minView hear:nil. maxView hear:nil]. setToObservedButton _ RVMButtonView label:'Set scale to observed values' action:[view currentTrace scaler setRangeToObserved. view drawCanvas; displayView. minView hear:nil. maxView hear:nil]. autoScaleCheckBox _ RVMCheckBoxView on: view currentTrace scaler label: 'Automatic Scaling' checkState: [view currentTrace scaler automaticScaling] whenChecked: [view currentTrace scaler automatic. view drawCanvas; displayView. minView hear:nil. maxView hear:nil] whenUnchecked: [view currentTrace scaler manual. view drawCanvas; displayView. minView hear:nil. maxView hear:nil] monitor: true. topView := RVMStandardSystemView new. topView borderWidth:1. topView addSubView: minView. topView addSubView: maxView below: minView. topView addSubView: resetScaleButton below: maxView. topView addSubView: setToObservedButton below: resetScaleButton. topView addSubView: autoScaleCheckBox below: setToObservedButton. RVMMonitor forgetAll:{resetScaleButton. setToObservedButton. autoScaleCheckBox}. topView label: view currentAspect. height _ topView subViews size * 26. topView minimumSize:200@height. topView maximumSize: 200@height. topView controller open! ! !RVMStripChartScaleController methodsFor: 'controlling' stamp: 'ssa 10/4/2008 08:19'! yellowButtonActivity | menu answer onlyOneTrace | onlyOneTrace _ self view stripChart traces size = 1. self view topView dontDisplayWhile:[ menu := CustomMenu new. onlyOneTrace ifTrue:[menu add: 'Change aspect' action: #changeAspect. menu addLine]. onlyOneTrace ifFalse:[menu add: 'Show other scale' action: #changeScaleAspect. menu addLine]. menu add: 'Add system aspect trace' action: #addSystemTrace. menu add: 'Add core aspect trace' action: #addCoreTrace. onlyOneTrace ifFalse:[menu addLine. menu add: 'Remove trace' action: #removeTrace. menu add: 'Remove other traces' action: #removeOtherTraces]. answer := menu startUp: nil withCaption: '' at: Sensor cursorPoint]. answer notNil ifTrue:[self perform: answer]! ! !RVMStripChartScaleController methodsFor: 'view resizing' stamp: 'ssa 1/1/1970 00:38'! adjustViewSizes self view topView unlock. self view topView display! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 22:02'! adjustScaleBox "Answer the value of adjustScaleBox" adjustScaleBox isNil ifTrue:[self adjustScaleBox: self insetDisplayBox]. ^ adjustScaleBox! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 22:02'! adjustScaleBox: anObject "Set the value of adjustScaleBox" adjustScaleBox _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! currentAspect "Answer the value of currentAspect" ^self currentTrace aspect! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 23:17'! currentAspectLabel "Answer a good label for this aspect" ^self currentTrace aspectLabel! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:12'! currentColor "Answer the value of currentColor" ^self currentTrace color! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:12'! currentTrace "Answer the value of currentTrace" currentTrace isNil ifTrue:[self currentTrace: self stripChart traces first]. ^ currentTrace! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! currentTrace: anObject "Set the value of currentTrace" currentTrace _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:10'! stripChart "Answer the value of stripChart" stripChart isNil ifTrue:[self stripChart: (RVMStripChartView trace:RVMCoreAspectTrace exampleInstance)]. ^ stripChart! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:03'! stripChart: anObject "Set the value of stripChart" stripChart _ anObject! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! uiHolder "Answer the value of uiHolder" uiHolder isNil ifTrue:[self uiHolder: nil]. ^ uiHolder! ! !RVMStripChartScaleView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! uiHolder: anObject "Set the value of uiHolder" uiHolder _ anObject! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 21:59'! adjustScaleIcon ^((ColorForm extent: 16@31 depth: 8 fromArray: #( 0 0 0 0 0 0 169614364 622594560 0 0 1694498815 4294913536 0 0 1845490943 4294915840 0 0 0 3506384384 0 0 0 3506386688 73 1677721600 0 3657379328 163 3642490880 0 3506386688 9716 4287692800 172 4110364160 46591 4294913536 208 4110366464 4259839 4294936576 0 3506384384 8973264 4106150400 0 3657381632 6558618 3942664503 0 3506384384 154 3942645760 0 3657381632 154 3942645760 25700 3808374272 154 3942645760 60415 4294915840 154 3942645760 18761 3808374272 154 3942645760 0 3506386688 2424986 3942648357 0 3657379328 11304867 3947480869 0 3506386688 7798783 4294948096 0 3506384384 1300991 4294925056 217 4294915840 25855 4291821568 145 3959369216 199 4098424832 0 3657381632 118 2432696320 0 3506384384 28 620756992 0 3506386688 0 0 0 3657379328 0 0 1541003737 4110366464 0 0 1694498815 4294913536 0 0 321795886 1227753984 0 0 0 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.94 0.94 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.847 0.847 0.847) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.815 0.815 0.815) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.784 0.784 0.784) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.753 0.753 0.753) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.721 0.721 0.721) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.69 0.69 0.69) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.658 0.658 0.658) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.627 0.627 0.627) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.595 0.595 0.595) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.501 0.501 0.501) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.439 0.439 0.439) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.408 0.408 0.408) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.376 0.376 0.376) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.345 0.345 0.345) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.313 0.313 0.313) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.282 0.282 0.282) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.25 0.25 0.25) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.188 0.188 0.188) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.156 0.156 0.156) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.125 0.125 0.125) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.094 0.094 0.094) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.063 0.063 0.063) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.031 0.031 0.031) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) #(0.0 0.0 0.0) ))! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 22:05'! drawAdjustScaleIcon | adjustIcon origin | . adjustIcon _ self adjustScaleIcon. adjustIcon _ adjustIcon scaledToSize: adjustIcon extent * 0.75. origin _ self canvas boundingBox center - adjustIcon boundingBox extent - (0@6). adjustIcon displayOn: self canvas at: origin. self adjustScaleBox:(origin extent: adjustIcon extent)! ! !RVMStripChartScaleView methodsFor: 'drawing' stamp: 'ssa 11/11/2008 22:03'! drawCanvas | scaler maxLabel minLabel midLabel box ticLength ticOffset topY midY bottomY leftX rightX margin aspectLabel | self eraseCanvas. scaler _ self currentTrace scaler. aspectLabel _ self currentAspectLabel asDisplayText asParagraph asForm rotateBy: #left centerAt: 0@0. maxLabel _ scaler max printShowingMax3Digits asDisplayText. minLabel _ scaler min printShowingMax3Digits asDisplayText. midLabel _ (scaler range / 2 + scaler min) printShowingMax3Digits asDisplayText. maxLabel foregroundColor: self currentColor backgroundColor: Color transparent. midLabel foregroundColor: self currentColor backgroundColor: Color transparent. minLabel foregroundColor: self currentColor backgroundColor: Color transparent. box _ self canvas boundingBox. ticLength _ 4. ticOffset _ maxLabel height // 2. margin _ 2. aspectLabel align: aspectLabel boundingBox leftCenter with: box leftCenter. aspectLabel displayOn: self canvas at: 0@0 clippingBox: box. maxLabel align: maxLabel boundingBox topRight with: box topRight - (ticLength+margin+1@0). maxLabel displayOn: self canvas. midLabel align: midLabel boundingBox rightCenter with: box rightCenter - (ticLength+margin+1@0). midLabel displayOn: self canvas. minLabel align: minLabel boundingBox bottomRight with: box bottomRight -(ticLength+margin+1@0). minLabel displayOn: self canvas. topY _ box topRight y . midY _ box center y. bottomY _ box bottomRight y - 2. leftX _ box topRight x - ticLength - margin. rightX _ box corner x - margin. self canvas fill: (rightX - 1@topY corner: rightX@bottomY) fillColor: self currentColor. self canvas fill: (leftX@topY extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@(topY+midY//2) extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@midY extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@(midY+bottomY//2) extent: ticLength@1) fillColor: self currentColor. self canvas fill: (leftX@bottomY extent: ticLength@1) fillColor: self currentColor. self drawAdjustScaleIcon! ! !RVMStripChartScaleView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:24'! newFrame self canvas: nil. self extent: self insetDisplayBox extent. self drawCanvas. self displayView! ! !RVMStripChartScaleView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:04'! defaultControllerClass ^RVMStripChartScaleController! ! !RVMStripChartScaleView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:05'! hear: something "Update my traces and redisplay" self drawCanvas. self displayView! ! !RVMStripChartScaleView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:22'! example "RVMStripChartScaleView example" self new demo! ! !RVMStripChartScaleView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:58'! stripChart: aStripChart uiHolder: aUIHolder | view | view _ self new. view stripChart: aStripChart. view uiHolder: aUIHolder. ^view! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 10/10/2008 19:23'! color "Answer the value of color" color isNil ifTrue:[self color: Color black]. ^ color! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:02'! color: anObject "Set the value of color" color _ anObject. color notNil ifTrue:[self pen color: color]! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! max "Answer my scaler max." ^self scaler max! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! max: aValue "Set my scaler max." self scaler max: aValue! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! min "Answer my scaler min." ^self scaler min! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! min: aValue "Set my scaler min." self scaler min: aValue! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:24'! muted "Answer the value of muted" muted isNil ifTrue:[self muted: false]. ^ muted! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:24'! muted: anObject "Set the value of muted" muted _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 10/10/2008 19:22'! pen "Answer the value of pen" | bic | pen isNil ifTrue:[bic _ Pen new. bic defaultNib:1. bic combinationRule: Form over. self pen: bic]. ^ pen! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:01'! pen: anObject "Set the value of pen" pen _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:07'! rawData "Answer the value of rawData" rawData isNil ifTrue:[self rawData: (RVMCircularCollection new:10)]. ^ rawData! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:51'! rawData: anObject "Set the value of rawData" rawData _ anObject. scaledData _ rawData collect:[:datum| self scaler scale: datum].! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:09'! scaledData "Answer the value of scaledData" scaledData isNil ifTrue:[self scaledData: self initialScaledData]. ^ scaledData! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scaledData: anObject "Set the value of scaledData" scaledData _ anObject! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:45'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: nil]. ^ scaler! ! !RVMStripChartTrace methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:04'! scaler: anObject "Set the value of scaler" scaler _ anObject. scaler notNil ifTrue:[self removeAllData]! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:53'! add: aValue "Add this value to the end of my data" self rawData add: aValue. self scaledData add: (self scaler scale: aValue)! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 01:25'! addData "do nothing, only works in subclasses"! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:25'! initialScaledData "Generate the scaled data by scaling the rawData" ^self rawData collect:[:datum| self scaler scale: datum]! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 00:41'! removeAllData self rawData removeAll. self scaledData removeAll! ! !RVMStripChartTrace methodsFor: 'add/remove data' stamp: 'ssa 1/1/1970 01:13'! resizeTo: anInteger (self rawData isKindOf: RVMCircularCollection) ifTrue:[ self rawData size: anInteger. self scaledData size: anInteger]! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:12'! drawLastOn: aColorForm "Draw the last line segment on this canvas using this pen." | yScale xSpacing x | self muted ifTrue:[^self]. self pen destForm: aColorForm. self scaledData numberOfElements = 1 ifTrue:[^self drawOn: aColorForm]. yScale _ aColorForm height / 100. xSpacing _ 2. x _ self scaledData numberOfElements - 1* xSpacing. self pen place: x@ (aColorForm height -((self scaledData at: self scaledData numberOfElements - 1) * yScale)). self pen goto: x+ xSpacing @ (aColorForm height -((self scaledData at: self scaledData numberOfElements) * yScale)). ! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:25'! drawOn: aColorForm | yScale xSpacing x first | self muted ifTrue:[^self]. self pen destForm: aColorForm. yScale _ aColorForm height / 100. xSpacing _ 2. x _ 0. first _ true. self scaledData do:[:datum| first ifTrue:[self pen place: x@ (aColorForm height -(datum * yScale)). first _ false]. self pen goto: x@ (aColorForm height -(datum * yScale)). x _ x + xSpacing. x < 0 ifTrue:[^self]]! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:28'! mute self muted: true.! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:11'! redrawOn: aColorForm self scaledData: nil. self drawOn: aColorForm! ! !RVMStripChartTrace methodsFor: 'drawing' stamp: 'ssa 1/1/1970 00:28'! unmute self muted: false.! ! !RVMStripChartTrace methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:04'! isEmpty ^self rawData isEmpty! ! !RVMStripChartTrace methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:04'! isFull ^self rawData isFull! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:21'! colorButton "Answer a color button connect to my color" ^RVMColorButtonView on: self colorGetter:#color colorSetter:#color:! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 1/1/1970 00:23'! minmaxButton "Answer a minmax button connect to my scaler's minmax" ^RVMMinMaxView on: self getMin: #min setMin: #min: getMax: #max setMax: #max:! ! !RVMStripChartTrace methodsFor: 'user interface' stamp: 'ssa 5/12/2010 10:13'! muteButton "Answer a color button connect to my color" | v | v _ RVMCheckBoxOnlyView on: self label: '' checkState: [self muted not] whenChecked: [self unmute] whenUnchecked: [self mute]. RVMMonitor inform: v. ^v! ! !RVMStripChartTrace methodsFor: 'scaling' stamp: 'ssa 10/6/2008 16:29'! rescale "Reset my scaler and recompute my scaledData" self scaler resetScaling. self scaledData:nil.! ! !RVMStripChartTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:50'! data: someData min: minValue max: maxValue color: aColor "Answer a new strip chart trace with this data and parameters. Note that the type of collection used for someData will also be used for scaled data. Use OrderedCollection for variable sized data, CircularCollection for fixed size." | trace | trace _ self new. trace scaler: (RVMDataScaler min: minValue max: maxValue); rawData: someData; color: aColor. ^trace! ! !RVMStripChartTrace class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:29'! size: anInteger min: minValue max: maxValue color: aColor "Answer a new strip chart trace with this size buffer and parameters" | trace | trace _ self new. trace scaler: (RVMDataScaler min: minValue max: maxValue); rawData: (RVMCircularCollection new: anInteger); color: aColor. ^trace! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 10/18/2008 23:18'! exampleCircularInstance "RVMStripChartTrace exampleCircularInstance" ^ self data: #(1 2 3 4 5 6 7 8 9) asCircularCollection min: 0 max: 10 color: Color blue! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:55'! exampleInstance "RVMStripChartTrace exampleInstance" ^ self data: #(1 2 3 4 5 6 5 4 3 2 1) min: 0 max: 10 color: Color blue! ! !RVMStripChartTrace class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:14'! randomInstance "RVMStripChartTrace randomInstance" | data | data _ OrderedCollection new. 100 timesRepeat:[data add: 10 atRandom]. ^ self data: data min: 0 max: 10 color: Color random! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/2/2008 19:21'! drawCanvas self eraseCanvas. self traces do:[:trace| trace drawOn: self canvas]! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/3/2008 23:13'! drawFastOnCanvas | box | self traces isEmpty ifTrue:[^self canvas fillWhite]. self traces first isFull ifTrue:[self canvas displayOn: self canvas at: -2@0]. box _ self canvas boundingBox. self canvas fillWhite: (box topRight - (2@0) extent: 2@ box height). self traces do:[:trace| trace drawLastOn: self canvas ]! ! !RVMStripChartView methodsFor: 'drawing' stamp: 'ssa 10/2/2008 19:21'! redrawCanvas self eraseCanvas. self traces do:[:trace| trace redrawOn: self canvas]! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:26'! defaultOffset ^self canvas width negated@ 0! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 16:09'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 15]. ^ rescaleCounter ! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 15:21'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! traces "Answer the value of traces" traces isNil ifTrue:[self traces: OrderedCollection new]. ^ traces! ! !RVMStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! traces: anObject "Set the value of traces" traces _ anObject! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/8/2008 18:34'! firstFrame "First time framed, set my canvas to match my view" self canvas: nil. self extent: self insetDisplayBox extent - (0@2). self traces do:[:trace| trace resizeTo: self extent x //2]. self drawCanvas. ! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/3/2008 23:23'! newFrame "My frame has changed. Reset my canvas to my new size and redraw" self canvas: nil. self extent: self insetDisplayBox extent - (0@2). self traces do:[:trace| trace resizeTo: self extent x //2]. self drawCanvas. self displayView! ! !RVMStripChartView methodsFor: 'framing' stamp: 'ssa 10/4/2008 08:28'! rebuildAll | view subGroups width scaleView scaleWidth topView extraRows | topView _ self topView. (topView allSubViews copyWithout: self) do:[:v| v release]. topView subViews: (OrderedCollection with: self). topView borderWidth:1. width _ 400. view _ self . scaleWidth _ 60. subGroups _ RVMTraceUIHolderView forStripChart: view. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. extraRows _ self traces size = 1 ifTrue:[0]ifFalse:[subGroups subViews size]. topView minimumSize: width@(100+(extraRows * 20)). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). extraRows > 0 ifTrue:[topView addSubView: subGroups viewport: (0@100 extent: width@(extraRows* 20))]. topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. subGroups borderWidth:0. topView reframeTo:(topView displayBox origin - (0@(topView labelHeight -2) ) extent: topView minimumSize + (0@topView labelHeight)). ScheduledControllers restore: topView windowBox. ! ! !RVMStripChartView methodsFor: 'listening' stamp: 'ssa 11/11/2008 22:38'! hear: something "Update my traces and redisplay" | outOfRangeTraces | self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self traces do:[:trace| trace scaler automaticScaling ifTrue:[trace rescale]]]. self traces do:[:trace| trace addData]. outOfRangeTraces _ self traces select:[:trace| trace scaler outOfRangeDetected] . outOfRangeTraces isEmpty ifTrue:[self drawFastOnCanvas. ^self displayView]. self redrawCanvas. outOfRangeTraces do:[:trace| trace scaler resetOutOfRangeDetector]. self displayView! ! !RVMStripChartView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:38'! defaultControllerClass ^RVMStripChartController! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/4/2008 08:18'! addCoreTraceForAspect: aSymbol coreIndex: anInteger | traceSize existingColors traceColor newTrace | traceSize _ self extent x //2. existingColors _ self traces collect:[:trace| trace color]. [traceColor _ Color random darker. self traces isEmpty or:[ (existingColors collect:[:color| color diff: traceColor]) asSortedCollection last < 0.7]] whileFalse. newTrace _ RVMCoreAspectTrace coreIndex: anInteger aspect: aSymbol size: traceSize color: traceColor. self traces add: newTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/3/2008 23:08'! addSystemTraceForAspect: aSymbol | traceSize existingColors traceColor newTrace | traceSize _ self extent x //2. existingColors _ self traces collect:[:trace| trace color]. [traceColor _ Color random darker. self traces isEmpty or:[(existingColors collect:[:color| color diff: traceColor]) asSortedCollection last < 0.7]] whileFalse. newTrace _ RVMAspectTrace aspect: aSymbol size: traceSize color: traceColor. self traces add: newTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 10/3/2008 22:59'! removeAllTraces self traces removeAll: self traces copy. ! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 1/1/1970 00:51'! removeTrace: aTrace self traces remove: aTrace. self newFrame! ! !RVMStripChartView methodsFor: 'add/remove traces' stamp: 'ssa 1/1/1970 00:51'! removeTraces: someTraces self traces removeAll: someTraces. self newFrame! ! !RVMStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView "Display my canvas at my offset. Subclasses should not override this method but should draw on the canvas instead" self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin + self offset - (0@2 ) clippingBox: self insetDisplayBox. ! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! openOnTrace: aTrace "RVMStripChartView openOnTrace: RVMAspectTrace exampleInstance" self openOnTrace: aTrace titled:'Multi-aspect Stripchart' ! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:30'! openOnTrace: aTrace titled: aString | topView view subGroups width scaleView scaleWidth | topView _ RVMStandardSystemView new. topView label: aString. topView borderWidth:1. width _ 400. view _ self traces: (OrderedCollection with: aTrace). scaleWidth _ 60. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. topView minimumSize: width@100. topView addSubView: view viewport: (scaleWidth@0 extent: width-scaleWidth@100). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. topView controller open! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:16'! openOnTraces: someTraces "RVMCoreAspectTrace exampleView3" self openOnTraces: someTraces titled: 'Multi-aspect Stripchart'! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 10/8/2008 19:09'! openOnTraces: someTraces titled: aString | topView view subGroups width scaleView scaleWidth | someTraces size = 1 ifTrue:[self openOnTrace: someTraces first titled: aString]. topView _ RVMStandardSystemView new. topView label: aString. topView borderWidth:1. someTraces size > 2 ifTrue:[width _ 400]ifFalse:[width _ someTraces size + 1 * 150 ]. view _ self traces: someTraces. scaleWidth _ 60. subGroups _ RVMTraceUIHolderView forStripChart: view. view extent: width - scaleWidth@100. scaleView _ RVMStripChartScaleView stripChart: view uiHolder:subGroups. topView minimumSize: width@(100+(subGroups subViews size + 1 * 20)). topView addSubView: view viewport: (scaleWidth@0 extent: width-scaleWidth@100). topView addSubView: scaleView viewport: (0@0 extent: scaleWidth@100). topView addSubView: subGroups viewport: (0@100 extent: width@(subGroups subViews size* 20)). topView backgroundColor: Color white. view borderWidthLeft: 0 right: 1 top: 1 bottom: 1. scaleView borderWidthLeft: 1 right: 0 top: 1 bottom: 1. subGroups borderWidth:0. topView controller open! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:10'! trace: aTrace ^self traces:(OrderedCollection with: aTrace)! ! !RVMStripChartView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 01:09'! traces: someTraces | view | view _ self new. view traces: someTraces. ^view! ! !RVMStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:09'! example "RVMStripChartView example" self openOnTrace: RVMCoreAspectTrace exampleInstance! ! !RVMTest methodsFor: 'logging' stamp: 'dmu 11/11/2009 18:06'! log: aString Transcript cr;show:'log: [',self name,'] ',aString. Transcript cr; cr. self runLog add: {Time dateAndTimeNow. aString}! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:19'! assertionBlock "Answer the value of assertionBlock" assertionBlock isNil ifTrue:[self assertionBlock: [:test :outcome| false]]. ^ assertionBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:46'! assertionBlock: anObject "Set the value of assertionBlock" assertionBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:47'! assertions "Answer the value of assertions" assertions isNil ifTrue:[self assertions: OrderedCollection new]. ^ assertions! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:47'! assertions: anObject "Set the value of assertions" assertions _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! environment "Answer the value of environment" environment isNil ifTrue:[self environment: nil]. ^ environment! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! environment: anObject "Set the value of environment" environment _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! lastResult "Answer the value of lastResult" lastResult isNil ifTrue:[self lastResult: nil]. ^ lastResult! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! lastResult: anObject "Set the value of lastResult" lastResult _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:05'! name "Answer the value of name" name isNil ifTrue:[self name: 'unnamed']. ^ name! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:05'! name: anObject "Set the value of name" name _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:39'! result ^self lastResult! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:31'! runLog "Answer the value of runLog" runLog isNil ifTrue:[self runLog: OrderedCollection new]. ^ runLog! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:31'! runLog: anObject "Set the value of runLog" runLog _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 08:58'! setUpBlock "Answer the value of setUpBlock" setUpBlock isNil ifTrue:[self setUpBlock: [:test| ]]. ^ setUpBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! setUpBlock: anObject "Set the value of setUpBlock" setUpBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 08:58'! tearDownBlock "Answer the value of tearDownBlock" tearDownBlock isNil ifTrue:[self tearDownBlock: [:test :env|]]. ^ tearDownBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:15'! tearDownBlock: anObject "Set the value of tearDownBlock" tearDownBlock _ anObject! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 06:19'! testBlock "Answer the value of testBlock" testBlock isNil ifTrue:[self testBlock: [:test :env| self log:'testing']]. ^ testBlock! ! !RVMTest methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:22'! testBlock: anObject "Set the value of testBlock" testBlock _ anObject! ! !RVMTest methodsFor: 'testing process' stamp: 'ssa 3/5/2010 17:37'! run self environment: (self setUpBlock value: self). self lastResult: self runTest. self tearDownBlock value: self value: self environment. ^self lastResult ! ! !RVMTest methodsFor: 'testing process' stamp: 'dmu 9/3/2010 11:49'! runTest | outcome result decision | outcome _ self testBlock value: self value: self environment. result _ RVMTestResult test: self result: outcome asserting: ((self assertionBlock value: self value: outcome) and:[self allAssertionsPassed]). self log: result gradeString. (result failed and:[self name ~= 'testFailure'])ifTrue:[decision _ self confirm:'Test [', self name,'] failed, continue?'. decision ifFalse:[self halt:'Test [', self name,'] failed, aborting other tests']]. ^result! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:00'! fullPrintOn: aStream aStream nextPutAll: 'Testing: ',self name. aStream cr; nextPutAll: 'result: '. self result printOn:aStream. aStream cr; nextPutAll: 'setUp: '. self setUpBlock printOn:aStream. aStream cr; nextPutAll: 'test: '. self testBlock printOn:aStream. aStream cr; nextPutAll: 'tearDown: '. self tearDownBlock printOn:aStream. aStream cr; nextPutAll: 'asserting: '. self assertionBlock printOn:aStream. aStream cr; nextPutAll: 'runLog: '. self runLog printOn:aStream. ! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:05'! gradeString ^self lastResult isNil ifTrue:['untested']ifFalse:[self lastResult gradeString]! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 06:59'! printOn: aStream aStream nextPutAll: self shortPrintString,'(',self gradeString,')'! ! !RVMTest methodsFor: 'printing' stamp: 'ssa 8/27/2009 06:04'! shortPrintString ^'Testing: ',self name! ! !RVMTest methodsFor: 'assertions' stamp: 'ssa 8/27/2009 06:51'! allAssertionsPassed self assertions detect:[:each| each = false] ifNone:[^true]. ^false! ! !RVMTest methodsFor: 'assertions' stamp: 'ssa 9/15/2009 16:34'! assert: aTrueResult self assert: aTrueResult ifFail: [self log: 'assertion failed']! ! !RVMTest methodsFor: 'assertions' stamp: 'dmu 12/16/2009 16:06'! assert: aTrueResult ifFail: failBlock (aTrueResult = true) | (aTrueResult = false) ifFalse:[self lyError:'assertion expressions result result in Booleans']. self assertions add: aTrueResult. aTrueResult ifFalse:[self class debugOnFail ifTrue:[self halt:self printString,' assertion failed']ifFalse:failBlock]. ! ! !RVMTest commentStamp: 'ssa 7/7/2010 14:09' prior: 0! See "examples" in my class! !RVMTest class methodsFor: 'settings' stamp: 'ssa 9/15/2009 16:28'! debugOnFail "If true, then a failing assertion or failBlock execution will open a Debugger" DebugOnFail isNil ifTrue:[DebugOnFail _ false]. ^DebugOnFail! ! !RVMTest class methodsFor: 'settings' stamp: 'ssa 9/15/2009 16:29'! debugOnFail: aBoolean "If true, then a failing assertion or failBlock execution will open a Debugger" DebugOnFail _ aBoolean! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runSetUp: setUpBlock test: testBlock asserting: assertionBlock | test | test _ self setUp: setUpBlock test: testBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:51'! runSetUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock | test | test _ self setUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runTest: testBlock asserting: assertionBlock | test | test _ self test: testBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'quick run' stamp: 'ssa 8/27/2009 05:52'! runTest: testBlock tearDown: tearDownBlock asserting: assertionBlock | test | test _ self test: testBlock tearDown: tearDownBlock asserting: assertionBlock. ^test run! ! !RVMTest class methodsFor: 'examples' stamp: 'ssa 7/7/2010 14:02'! fullExample "self fullExample run" "Use this example as a template for your tests in subclasses of LyTestSuite in the 'tests' message category" | theTest | theTest _ RVMTest setUp: [:test| test log:'setting up for test:',test name. "setUpBlocks return the test environment" #( 1 2 3 4 5 )] test:[:test :env| test log:'test:',test name,' starting...'. "testBlocks perform the test in the setup environment. The test object is available for assertions and logging" test assert: (env at: 2)=2. test assert:(env select:[:e| e odd]) = #(1 3 5) ifFail:[test log:'odd selections failed']. test log:'test:',test name,' complete'. "the last expression result is the outcome of the test" env size = 5] tearDown:[:test :env| test log:'tearing down test:',test name. "tearDownBlocks do any necessary cleanup that would not otherwise be garbage collected" test log:'tear down complete'] asserting:[:test :outcome| "assertionBlocks must result in True or False, and represent the pass/fail judgement of the test outcome" "if you use assert: or assert:ifFail: in these blocks their ANDed result will be ANDed to the result of this block for the final assertion" outcome = true "or use an expression that results in True or False"]. theTest name: 'fullExample'. ^theTest! ! !RVMTest class methodsFor: 'examples' stamp: 'ssa 7/7/2010 14:03'! simpleFullExample "self simpleFullExample run" | theTest | theTest _ RVMTest setUp: [:test| ] test:[:test :env| 123] tearDown:[:test :env| ] asserting:[:test :outcome| outcome = 123]. theTest name: 'simpleFullExample'. ^theTest! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:49'! setUp: setUpBlock test: testBlock asserting: assertionBlock ^self new setUpBlock: setUpBlock; testBlock: testBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:48'! setUp: setUpBlock test: testBlock tearDown: tearDownBlock asserting: assertionBlock ^self new setUpBlock: setUpBlock; testBlock: testBlock; tearDownBlock: tearDownBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:50'! test: testBlock asserting: assertionBlock ^self new testBlock: testBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:50'! test: testBlock tearDown: tearDownBlock asserting: assertionBlock ^self new testBlock: testBlock; tearDownBlock: tearDownBlock; assertionBlock: assertionBlock; yourself! ! !RVMTest class methodsFor: 'user interfacing' stamp: 'ssa 5/12/2010 10:19'! debugOnFailSwitch "self debugOnFailSwitch" | topView | topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: 130@30. topView maximumSize: 200@200. topView addSubView: (RVMCheckBoxView on: self label: 'LyTest debugOnFail' checkState: [self debugOnFail] whenChecked: [self debugOnFail: true] whenUnchecked: [self debugOnFail: false] monitor: true). topView controller open! ! !RVMTest class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! fullExampleTest "self fullExampleTest" | theTest | theTest _ RVMTest setUp: [:test| test log:'setting up for test:',test name. "setUpBlocks return the test environment" #( 1 2 3 4 5 )] test:[:test :env| test log:'test:',test name,' starting...'. "testBlocks perform the test in the setup environment. The test object is available for assertions and logging" test assert: (env at: 2)=2. test assert:(env select:[:e| e odd]) = #(1 3 5) ifFail:[test log:'odd selections failed']. test log:'test:',test name,' complete'. "the last expression result is the outcome of the test" env size = 5] tearDown:[:test :env| test log:'tearing down test:',test name. "tearDownBlocks do any necessary cleanup that would not otherwise be garbage collected" test log:'tear down complete'] asserting:[:test :outcome| "assertionBlocks must result in True or False, and represent the pass/fail judgement of the test outcome" test allAssertionsPassed . " use this when using assert: or assert:ifFail:" outcome = true "or use an expression that results in True or False"]. theTest name: 'fullExampleTest'. ^theTest! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:03'! assertion "Answer the value of assertion" assertion isNil ifTrue:[self assertion: nil]. ^ assertion! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:27'! assertion: anObject "Set the value of assertion" assertion _ anObject! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! result "Answer the value of result" result isNil ifTrue:[self result: nil]. ^ result! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! result: anObject "Set the value of result" result _ anObject! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! test "Answer the value of test" test isNil ifTrue:[self test: nil]. ^ test! ! !RVMTestResult methodsFor: 'accessing' stamp: 'ssa 8/27/2009 05:17'! test: anObject "Set the value of test" test _ anObject! ! !RVMTestResult methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:01'! gradeString ^self passed ifTrue:['passed']ifFalse:['failed']! ! !RVMTestResult methodsFor: 'printing' stamp: 'ssa 8/27/2009 07:01'! printOn: aStream aStream nextPutAll: self gradeString, ' ',self test shortPrintString! ! !RVMTestResult methodsFor: 'testing' stamp: 'ssa 8/27/2009 06:02'! failed ^self assertion not! ! !RVMTestResult methodsFor: 'testing' stamp: 'ssa 8/27/2009 06:02'! passed ^self assertion! ! !RVMTestResult class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:26'! test: aRVMTest result: anOutcome asserting: anAssertion ^self new test: aRVMTest; result: anOutcome; assertion: anAssertion; yourself! ! !RVMTestSuite methodsFor: 'acessing' stamp: 'ssa 8/27/2009 07:07'! results ^self tests collect:[:test| test result]! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/30/2009 03:50'! failureCount ^(self tests select:[:test| test result failed])size! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/30/2009 03:50'! failures ^(self tests select:[:test| test result failed])! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'ssa 8/27/2009 09:06'! reportResults | passers failures | passers _ OrderedCollection new. failures _ OrderedCollection new. self tests do:[:test| test result passed ifTrue:[passers add: test name asSymbol]ifFalse:[failures add: test name asSymbol]]. Transcript cr;show:'-------------------';cr; show: 'Results for TestSuite:'; show: 'Summary: ',passers size printString,' passed, ',failures size printString,' failed';cr. failures isEmpty ifFalse:[Transcript show:'Failed tests: ',failures asArray printString;cr; show:'"1 systemNavigation browseAllImplementorsOfList:', failures asArray printString,' title: ''Failed Tests'' "'] ! ! !RVMTestSuite methodsFor: 'testing process' stamp: 'dmu 9/3/2010 11:43'! run Transcript cr;show:'Starting run.....................'. self tests do:[:test| test run]. Transcript cr;show:'......................Ending run'. self reportResults! ! !RVMTestSuite methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:31'! tests "Answer the value of tests" tests isNil ifTrue:[self tests: OrderedCollection new]. ^ tests! ! !RVMTestSuite methodsFor: 'accessing' stamp: 'ssa 8/27/2009 07:31'! tests: anObject "Set the value of tests" tests _ anObject! ! !RVMTestSuite class methodsFor: 'instance creation' stamp: 'ssa 8/27/2009 05:35'! tests: someTests ^self new tests: someTests! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:31'! run "self run" "just run the tests in my own 'testing' message category" ^self tests run! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:45'! runAll "self runAll" "just run all tests in the 'testing' message category of myself and my subclasses" ^self testsWithSubTests run! ! !RVMTestSuite class methodsFor: 'running tests' stamp: 'ssa 8/27/2009 07:45'! runSubs "self runSubs" "just run all tests in the 'testing' message category of my subclasses" ^self subTests run! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 09:37'! subTests "Answer a test suite built by scanning methods in my subclasses 'tests' categories" | testSelectors tests | tests _ OrderedCollection new. self allSubclassesDo:[:cls| testSelectors _ cls class organization listAtCategoryNamed: 'tests'. tests addAll:(testSelectors collect:[:selector| cls perform: selector])]. ^self tests: tests! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 06:57'! tests "self tests" "Answer a test suite built by scanning methods in my 'tests' category" | testSelectors | testSelectors _ self class organization listAtCategoryNamed: 'tests'. ^self tests: (testSelectors collect:[:selector| self perform: selector])! ! !RVMTestSuite class methodsFor: 'suite creation' stamp: 'ssa 8/27/2009 08:29'! testsWithSubTests "Answer a test suite built by scanning methods in my own and my subclasses 'tests' categories" | testSelectors tests | tests _ OrderedCollection new. self withAllSubclassesDo:[:cls| testSelectors _ cls class organization listAtCategoryNamed: 'tests'. tests addAll:(testSelectors collect:[:selector| cls perform: selector])]. ^self tests: tests! ! !RVMTestSuite class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! testFailure "self testFailure run" "A test that will always fail to ensure the system is functioning at a minimum" | theTest | theTest _ RVMTest test:[:test :env| ] asserting:[:test :outcome| false]. theTest name: 'testFailure'. ^theTest! ! !RVMTestSuite class methodsFor: 'tests' stamp: 'ssa 7/7/2010 14:03'! testRVMTest ^RVMTest fullExampleTest! ! !RVMTestSuite class methodsFor: 'user interface' stamp: 'ssa 8/31/2009 10:50'! runAllButton "self runAllButton" | topView | topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: 130@30. topView maximumSize: 200@200. topView addSubView: (RVMButtonView label:'Run All Tests' action:[self runAll]). topView label: 'Tester'. topView controller open! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:22'! browseAspectsForCore: coreIndex self view okToDisplay:true. RVMCoreAspectTrace monitorAllCoreAspectsForCore: coreIndex! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:29'! browseThisAspectForAllCores: coreIndex self view okToDisplay:true. RVMTileStripChartView openOnAspect: self view aspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 16:24'! browseThisAspectForCore: coreIndex self view okToDisplay:true. RVMCoreAspectTrace monitorAspects: (Array with: self view aspect) forCore: coreIndex! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 10/4/2008 08:36'! changeAspect: coreIndex | menu answer | menu := CustomMenu new. self view sample aspects do: [:aspect | menu add: aspect action: aspect]. answer := menu startUp: self view aspect withCaption: 'Select the aspect to monitor'. self view topView okToDisplay:true. answer isNil ifTrue:[^self]. self view aspect: answer. self view topView allSubViews do:[:each| each hear: nil]. self view displayView! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:12'! doMessageTallyOfDisplayView self view topView okToDisplay:true. MessageTally spyOn:[100 timesRepeat:[view displayView]] ! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:12'! inspectDataValues: coreIndex self view topView okToDisplay:true. self view data inspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 02:00'! inspectView:coreIndex self view okToDisplay:true. self view inspect! ! !RVMTileGridController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 00:02'! scalerForThisAspect: coreIndex self view okToDisplay:true. RVMColoredDataScalerView openOnAspect: self view aspect! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 13:10'! coreIndexAt: aPoint | box | 1 to: self view tiles size do:[:index| box _ self view tiles at: index. ( box containsPoint: aPoint) ifTrue:[^index]]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:55'! redButtonActivity | delay | ["Color showColors: self view colors. " ^self ]value. Cursor move show. Sensor waitNoButton. Cursor normal show. self process isNil ifTrue: [ self view showProcessOn. self process: [[((self view displayBox containsPoint: Sensor cursorPoint) & Sensor redButtonPressed) or:[Sensor leftShiftDown & Sensor controlKeyPressed]] whileFalse: [ delay := Delay forMilliseconds: 1 * (Time millisecondsToRun: [self view displayView]). delay wait]]. self process fork] ifFalse: [self stopDisplayProcess]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'dmu 1/1/1970 00:08'! stopDisplayProcess self process terminate. self view showProcessOff. self view displayView. self process: nil! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:11'! yellowButtonActivity | menu answer coreIndex | coreIndex _ self coreIndexAt: Sensor cursorPoint. self view dontDisplayWhile:[ Sensor yellowButtonPressed ifTrue: [menu := self yellowButtonMenu. answer := menu startUp: nil withCaption: nil at: Sensor cursorPoint. answer notNil ifTrue:[ self perform: answer with: coreIndex]]]! ! !RVMTileGridController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 01:59'! yellowButtonMenu | menu coreIndex | coreIndex _ self coreIndexAt: Sensor cursorPoint. menu := CustomMenu new. menu add: 'change aspect' action: #changeAspect:. menu add: ' stripchart all aspects for core #',coreIndex printString action: #browseAspectsForCore:. menu add: 'stripchart this aspect for core #',coreIndex printString action: #browseThisAspectForCore:. menu add: 'stripchart this aspect for all cores' action: #browseThisAspectForAllCores:. menu add: 'adjust scale for this aspect' action: #scalerForThisAspect:. menu add: 'current data values' action: #inspectDataValues:. menu add: 'inspect view' action: #inspectView:. ^menu ! ! !RVMTileGridController methodsFor: 'accessing' stamp: 'ssa 8/15/2008 20:14'! process "Answer the value of process" process isNil ifTrue:[self process: nil]. ^process! ! !RVMTileGridController methodsFor: 'accessing' stamp: 'ssa 8/15/2008 20:14'! process: anObject "Set the value of process" process := anObject! ! !RVMTileGridController methodsFor: 'initialize-release' stamp: 'ssa 8/15/2008 20:21'! release self process notNil ifTrue:[self process terminate]. super release! ! !RVMTileGridScalerView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | color | self okToDisplay ifFalse: [^ self]. self uncache. self sample: nil. self scaler resetObservations. self canvas fillColor: self tileBorderColor. 1 to: self tiles size do: [:index | color := index > self data size ifTrue: [Color black] ifFalse: [self colors at: ((self scaler scale: (self data at: index))min: 100 max:1)]. self canvas fill: (((self tiles at: index) translateBy: self insetDisplayBox origin negated) insetBy: 1 @ 1) fillColor: color. self tiles size = 1 ifTrue: [(self data first printString asDisplayText alignedTo: #center) displayOn: self canvas at: self canvas boundingBox center]]. self canvas displayAt: self insetDisplayBox origin! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:07'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:02'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 30]. ^ rescaleCounter! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:03'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject ! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:46'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^ scaler! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 08:45'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMTileGridScalerView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:11'! typeLabel ^'Abs: '! ! !RVMTileGridScalerView methodsFor: 'listening' stamp: 'ssa 11/4/2008 15:37'! hear: someObject "self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self scaler resetScaling]. " self sample: nil. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileGridScalerView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:15'! example "RVMTileGridScalerView example" | topView v scaleWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. topView minimumSize: 200+scaleWidth@200. topView maximumSize: 460@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: 200@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: true) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileGridView methodsFor: 'autoscaling' stamp: 'ssa 10/1/2008 09:09'! autoscale "Adjust my scale so that it fits the data." self minValue: self data min. self maxValue: self data max. self scale:nil! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:34'! hear: someObject self sample: nil. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 10/3/2008 19:33'! newFrame self canvas: nil. self displayView! ! !RVMTileGridView methodsFor: 'updating' stamp: 'ssa 8/19/2008 18:25'! unlock super unlock. self tiles:nil ! ! !RVMTileGridView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:30'! defaultControllerClass ^RVMTileGridController! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:34'! aspect "Answer the value of aspect" aspect isNil ifTrue:[self aspect: #bytecodesPerSecond]. ^aspect! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:57'! aspect: anObject "Set the value of aspect" aspect := anObject. self topView == self ifFalse:[self topView relabel: self typeLabel,anObject]! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 14:27'! aspects ^self sample aspects! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:46'! canvas canvas isNil ifTrue:[self canvas: (Form fromDisplay: self insetDisplayBox) fillWhite]. ^canvas ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 9/24/2008 17:45'! canvas: aForm canvas _ aForm! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! colors "Answer the value of colors" colors isNil ifTrue:[self colors: self makeColors]. ^colors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! colors: anObject "Set the value of colors" colors := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 09:12'! data "Answer the value of data" data isNil ifTrue:[ (self sample respondsTo: self aspect) ifFalse: [^ Array new: 0]. self data: (self sample perform: self aspect)]. ^data! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:29'! data: anObject "Set the value of data" data := anObject. data ifNotNil:[(data isKindOf: Collection) ifFalse:[data _ Array with: data]]. data notNil ifTrue:[self autoscale]! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 12:44'! gridExtent "Answer the width and height of the grid of tiles that is appropriate for the layout of cores we have" | total | total _ self data size. total = 1 ifTrue:[^1@1]. total < 4 ifTrue:[^1@ total]. total = 4 ifTrue:[^2@ 2]. total < 16 ifTrue:[^4@ (total/4+0.5)rounded]. "otherwise assume a Tilera 8x8 grid" ^self sample groupStats width @ self sample groupStats height! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:23'! makeColors ^(Color hotColdShades: self numberOfColors) reversed! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:22'! maxValue "Answer the value of maxValue" maxValue isNil ifTrue:[self maxValue: 5000]. ^maxValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! maxValue: anObject "Set the value of maxValue" maxValue := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:22'! minValue "Answer the value of minValue" minValue isNil ifTrue:[self minValue: 0]. ^minValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 16:20'! minValue: anObject "Set the value of minValue" minValue := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'dmu 1/1/1970 00:26'! numberOfColors "Answer the value of numberOfColors" numberOfColors isNil ifTrue:[self numberOfColors: 100]. ^numberOfColors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 19:50'! numberOfColors: anObject "Set the value of numberOfColors" numberOfColors := anObject rounded. self colors:nil. self changed:#numberOfColors! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:25'! sample "Answer the value of sample" sample isNil ifTrue:[self sample: RVMMonitor lastSample]. ^sample! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:49'! sample: anObject "Set the value of sample" sample := anObject.. self data:nil. ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 10:04'! scale "Answer the value of scale" scale isNil ifTrue:[self scale: self maxValue / self numberOfColors asFloat]. ^scale ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:50'! scale: anObject "Set the value of scale" scale := anObject. scale = 0 ifTrue: [scale := 0.01]. self changed:#scale. ! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 10/1/2008 09:06'! scaler "Answer a scaler for me as needed" ^RVMDataScaler aspect: self aspect min: self minValue max: self maxValue! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/19/2008 18:09'! showProcessState "Answer the value of showProcessState" showProcessState isNil ifTrue:[self showProcessState: false]. ^showProcessState! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/19/2008 18:08'! showProcessState: anObject "Set the value of showProcessState" showProcessState := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:13'! tiles "Answer the value of tiles" tiles isNil ifTrue:[self tiles: (self insetDisplayBox subDivideRoundedBy: (self data size > 1 ifTrue:[self sample groupStats width @ self sample groupStats height]ifFalse:[1@1]))]. ^tiles! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 8/15/2008 11:56'! tiles: anObject "Set the value of tiles" tiles := anObject! ! !RVMTileGridView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:58'! typeLabel ^'Rel: '! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 15:47'! displayView | color colorIndex | self okToDisplay ifFalse:[^self]. self uncache. self sample: nil. self canvas fillColor: self tileBorderColor. 1 to: self tiles size do:[:index| color := index > self data size ifFalse:[ colorIndex _ (((self data at: index) / self scale)min: self numberOfColors max: 1) rounded. self colors at: colorIndex] ifTrue:[Color black]. self canvas fill: (((self tiles at: index) translateBy: self insetDisplayBox origin negated)insetBy:1@1) fillColor: color . self tiles size = 1 ifTrue:[(self data first printString asDisplayText alignedTo:#center)displayOn: self canvas at: self canvas boundingBox center]. ]. self canvas displayAt: self insetDisplayBox origin ! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:41'! redrawOnCanvas "do nothing"! ! !RVMTileGridView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:42'! tileBorderColor ^Color darkGray! ! !RVMTileGridView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:17'! example "RVMTileGridView example" | topView v scaleWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. topView minimumSize: 200+scaleWidth@200. topView maximumSize: 460@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: 200@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: false) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileGridView class methodsFor: 'instance creation' stamp: 'ssa 8/15/2008 16:36'! aspect: aMessageSelector numberOfColors: numColors minValue: minValue maxValue: maxValue "Answer a new view with these params" | view | view := self new. view aspect: aMessageSelector; numberOfColors: numColors; minValue: minValue; maxValue: maxValue. ^view! ! !RVMTileGridView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:19'! adjustScaler ^false! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 15:14'! eraseStrip: coreIndex self view eraseStrip! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 1/1/1970 01:40'! redraw: coreIndex self view okToDisplay: true. self view redrawOnCanvas. self view displayView! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/3/2008 21:43'! rescale: coreIndex self view okToDisplay: true. self view rescale. self view displayView! ! !RVMTileStripChartController methodsFor: 'menu messages' stamp: 'ssa 10/3/2008 21:27'! yellowButtonMenu | menu | menu _ super yellowButtonMenu. menu add: 'erase strip' action: #eraseStrip:. menu add: 'redraw' action: #redraw:. menu add: 'rescale' action: #rescale:. ^menu! ! !RVMTileStripChartController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 16:20'! coreIndexAt: aPoint | p | p _ aPoint y - self view insetDisplayBox origin y // self view boxSize. ^p max:1! ! !RVMTileStripChartScalerView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 21:02'! drawOnCanvas | color | self canvas displayOn: self canvas at: self boxSize negated @0. 1 to: self count do:[:index| color := self colors at: ((self scaler scale:(self data at: index)) min: self numberOfColors max:1). self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated )fillColor: color]. ! ! !RVMTileStripChartScalerView methodsFor: 'displaying' stamp: 'ssa 10/28/2008 20:51'! redrawOnCanvas | color x | [#redrawScaler print]. self canvas fillWhite. x _ 0. self previousData asOrderedCollection reversed do:[:oldData| 1 to: self count do: [:index | color := self colors at: ((self scaler scale:(oldData at: index)) min: self numberOfColors max:1). self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated - (x@0)) fillColor: color]. x _ x + self boxSize]! ! !RVMTileStripChartScalerView methodsFor: 'scaling' stamp: 'ssa 10/6/2008 16:30'! rescale "Reset the scaler and pass the previous data thorugh it to find the min/max. Then redraw" [#rescaling print]. self scaler resetScaling. self previousData do:[:dats| dats do:[:d| scaler scale: d]]. self scaler resetOutOfRangeDetector. self redrawOnCanvas! ! !RVMTileStripChartScalerView methodsFor: 'listening' stamp: 'ssa 11/4/2008 19:50'! hear: someObject self sample: nil. "self rescaleCounter: self rescaleCounter - 1. self rescaleCounter = 0 ifTrue:[self rescaleCounter:nil. self rescale]. self scaler outOfRangeDetected ifTrue:[[('out of range = ',self scaler lastObserved printString) print]. self rescale]." self drawOnCanvas. self topView isCollapsed ifFalse:[self displayView]. ! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:06'! aspect: aSymbol. self scaler: nil. super aspect: aSymbol! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 20:51'! rescaleCounter "Answer the value of rescaleCounter" rescaleCounter isNil ifTrue:[self rescaleCounter: 1]. ^ rescaleCounter! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 22:09'! rescaleCounter: anObject "Set the value of rescaleCounter" rescaleCounter _ anObject ! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:04'! scaler "Answer the value of scaler" scaler isNil ifTrue:[self scaler: (RVMMonitor scalerFor: self aspect)]. ^ scaler! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 21:03'! scaler: anObject "Set the value of scaler" scaler _ anObject! ! !RVMTileStripChartScalerView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:16'! typeLabel ^'Abs: '! ! !RVMTileStripChartScalerView class methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:20'! adjustScaler ^true! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView self okToDisplay ifFalse:[^self]. self uncache. self canvas displayOn: Display at: self insetDisplayBox origin clippingBox: self insetDisplayBox.! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 20:47'! drawOnCanvas | color colorIndex | [#draw print]. self canvas displayOn: self canvas at: self boxSize negated @ 0. 1 to: self count do: [:index | colorIndex := ((self data at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated) fillColor: color]! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 1/1/1970 01:38'! eraseStrip self previousData:nil. self canvas fillWhite. self displayView! ! !RVMTileStripChartView methodsFor: 'displaying' stamp: 'ssa 10/3/2008 20:27'! redrawOnCanvas | color colorIndex x | #redraw print. self canvas fillWhite. x _ 0. self previousData do:[:oldData| 1 to: self count do: [:index | colorIndex := ((oldData at: index) / self scale min: self numberOfColors max: 1) rounded. color := self colors at: colorIndex. self canvas fill: ((self boxes at: index) translateBy: self insetDisplayBox origin negated - (x@0)) fillColor: color]. x _ x + self boxSize]! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:37'! aspect: anObject "Set the value of aspect" super aspect: anObject. self eraseStrip! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 08:48'! box "Answer the value of box" box isNil ifTrue:[self box: (self insetDisplayBox topRight - (self boxSize @ 0) extent: self boxSize @ self insetDisplayBox height)]. ^box! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/22/2008 09:02'! box: anObject "Set the value of box" box := anObject. self boxes:nil. self boxSize: nil! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 5/4/2010 15:24'! boxSize "Answer the value of boxSize" boxSize isNil ifTrue:[self boxSize: ((self insetDisplayBox height // self count max:1)min:4)]. ^boxSize! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! boxSize: anObject "Set the value of boxSize" boxSize := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 4/20/2010 10:23'! boxes "Answer the value of boxes" boxes isNil ifTrue:[self boxes: (self box subDivideRoundedBy: 1@ self count)]. ^boxes! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! boxes: anObject "Set the value of boxes" boxes := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/9/2008 11:42'! chart "Answer the value of chart" chart isNil ifTrue:[self chart: (Form fromDisplay: self insetDisplayBox)]. ^chart! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:33'! chart: anObject "Set the value of chart" chart := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:32'! count "Answer the value of count" count isNil ifTrue:[self count: self data size]. ^count! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:30'! count: anObject "Set the value of count" count := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:36'! data: someData super data: someData. someData notNil ifTrue:[self previousData add: someData]! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:00'! previousData "Answer the value of previousData" previousData isNil ifTrue:[self previousData: (RVMCircularCollection new: self visibleSampleCount)]. ^previousData! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 16:28'! previousData: anObject "Set the value of previousData" previousData := anObject! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 10/3/2008 20:41'! scale: aValue "Set the value of scale" super scale: aValue. "aValue isNil ifFalse:[self redrawOnCanvas]"! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 8/20/2008 17:22'! unlock super unlock. self box:nil ! ! !RVMTileStripChartView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 01:06'! visibleSampleCount "How many samples (columns of boxes) can I currently display?" ^self chart boundingBox width // self boxSize! ! !RVMTileStripChartView methodsFor: 'updating' stamp: 'ssa 10/3/2008 20:34'! hear: someObject self sample: nil. self drawOnCanvas. self topView isCollapsed ifFalse:[self displayView]! ! !RVMTileStripChartView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:10'! newFrame super newFrame. self canvas:nil. self box: nil! ! !RVMTileStripChartView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:30'! defaultControllerClass ^RVMTileStripChartController! ! !RVMTileStripChartView methodsFor: 'scaling' stamp: 'ssa 10/3/2008 22:26'! rescale "do nothing"! ! !RVMTileStripChartView class methodsFor: 'examples' stamp: 'ssa 11/4/2008 20:18'! example "RVMTileStripChartView example" | topView v scaleWidth stripWidth | topView := RVMStandardSystemView new. topView borderWidth:1. scaleWidth _ 70. stripWidth _ 200. topView minimumSize: stripWidth+scaleWidth@200. topView maximumSize: 1000@400. topView addSubView: (v := self new) viewport: (scaleWidth@0 extent: stripWidth@200). topView addSubView: (RVMColorScaleView aspectSource: [v aspect] scalerSource: [v scaler] colorsSource: [v colors reverse] orientation: #vertical forView: v adjustScaler: self adjustScaler) viewport:(0@0 extent:scaleWidth@200). topView label: v typeLabel,v aspect. topView controller open! ! !RVMTileStripChartView class methodsFor: 'examples' stamp: 'ssa 1/1/1970 00:16'! example1 "RVMTileStripChartView example1" self openOnAspect: #bytesUseds! ! !RVMTileStripChartView class methodsFor: 'scheduling' stamp: 'ssa 1/1/1970 00:16'! openOnAspect: aSymbol "Open a new monitor on this aspect" | topView v | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 200@200. topView maximumSize: 600@400. topView insideColor: Color white. v := self new. v aspect: aSymbol. topView addSubView: v. topView label: v typeLabel,aSymbol. topView controller open! ! !RVMTraceUIHolderView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! stripChart "Answer the value of stripChart" ^ stripChart! ! !RVMTraceUIHolderView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! stripChart: anObject "Set the value of stripChart" stripChart _ anObject! ! !RVMTraceUIHolderView methodsFor: 'controller access' stamp: 'ssa 1/1/1970 00:39'! defaultControllerClass ^RVMTraceUIHolderController! ! !RVMTraceUIHolderView methodsFor: 'subView inserting' stamp: 'ssa 1/1/1970 00:19'! myControls "Add the button to use to modify the number of traces my stripchart uses" | addTraceButton removeTraceButton holder | addTraceButton _ RVMButtonView label:'+' action:[self addTrace]. removeTraceButton _ RVMButtonView label:'-' action:[self removeTrace]. holder _ RVMView new. holder addSubView: addTraceButton. holder addSubView: removeTraceButton toRightOf: addTraceButton. ^holder! ! !RVMTraceUIHolderView methodsFor: 'subView inserting' stamp: 'ssa 1/1/1970 00:15'! rebuildSubViews | allSubs lastGroup holder last | allSubs _ self stripChart traces collect:[:trace| trace allView]. lastGroup _ nil. allSubs groupsOfNoMoreThan: 3 atATimeDo:[:group| holder _ RVMView new. last _ nil. group do:[:v| holder addSubView: v toRightOf: last. last _ v]. self addSubView:holder below: lastGroup. lastGroup _ holder]. ! ! !RVMTraceUIHolderView class methodsFor: 'instance creation' stamp: 'ssa 1/1/1970 00:55'! forStripChart: aViewWithTraces | v | v _ self new. v stripChart: aViewWithTraces. v rebuildSubViews. ^v! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:51'! adjustCursor "Show the appropriate arrow cursor" (Sensor cursorPoint x - self view insetDisplayBox center x )> 0 ifTrue:[Cursor up show] ifFalse:[Cursor down show]. ! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:50'! controlActivity "Show the appropriate arrow cursor, then default to other controlActivity" self adjustCursor. super controlActivity! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:34'! controlTerminate Cursor normal show. super controlTerminate! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 9/19/2008 11:49'! redButtonActivity | point center delta sign delay | center _ self view insetDisplayBox center. delay _ Delay forMilliseconds: 100. [Sensor redButtonPressed] whileTrue: [self adjustCursor. point := Sensor cursorPoint. delta _ (point x - center x). sign _ delta < 0 ifTrue:[-1]ifFalse:[1]. delta _ delta abs max:1. delta >10 ifFalse:[delta _ 1]. self view changeValueBy: (delta * sign). delay wait]! ! !RVMValueController methodsFor: 'controlling' stamp: 'ssa 1/1/1970 00:15'! yellowButtonActivity | result | self view dontDisplayWhile:[ result _ FillInTheBlank request: 'Enter the new value' initialAnswer: self view value printString. result notNil ifTrue:[self view value: (Compiler evaluate: result). self view displayView] ]! ! !RVMValueEditorController methodsFor: 'controller access' stamp: 'ssa 10/29/2008 21:32'! defaultControllerClass ^RVMValueEditorController! ! !RVMValueEditorController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 20:47'! redButtonActivity | p wait delay | delay _ Delay forMilliseconds: 100. wait _ [Sensor leftShiftDown ifFalse:[Sensor waitNoButton] ifTrue:[delay wait]]. p _ Sensor cursorPoint - self view insetDisplayBox origin. (self view lockBox containsPoint: p) ifTrue:[self view locked: self view locked not. self view displayView. ^Sensor waitNoButton.]. (self view oneBox containsPoint: p) ifTrue:[self view performOperationWith: 1. ^wait value]. (self view tenBox containsPoint: p) ifTrue:[self view performOperationWith: 10. ^wait value]. (self view hundredBox containsPoint: p) ifTrue:[self view performOperationWith: 100. ^wait value]. (self view zeroBox containsPoint: p) ifTrue:[^self view resetValueToZero]. self view operations with: self view operationBoxes do:[:op :bx| (bx containsPoint: p) ifTrue:[self view operation: op. ^self view displayView]]! ! !RVMValueEditorController methodsFor: 'controlling' stamp: 'ssa 11/4/2008 19:35'! yellowButtonActivity | result | self view topView dontDisplayWhile:[ result _ FillInTheBlank request: 'Enter the new value' initialAnswer: self view value printString. result notNil ifTrue:[self view value: (Compiler evaluate: result). self view displayView] ]! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:27'! closedPadlock ^((ColorForm extent: 14@16 depth: 8 fromArray: #( 0 2511181205 2912223232 0 197 2097152000 7456089 0 51549 9817545 2908582317 0 7456000 2915368960 2915893445 1895825408 9276765 3445161984 13473173 2365587456 9276813 3439329280 13473173 2365587456 7712141 3036678400 12167597 1962934272 1701414249 2171169129 1770357121 2237988864 2634354961 286331153 286331153 228392960 2702252313 421075225 286857497 834732032 3625525537 555819297 555819321 1103167488 4011402533 623191333 623984969 905641984 4012455225 892942657 1094797621 1374617600 3693688117 892679497 893995345 1241186304 4012193065 1094795573 1363752273 1375404032 3504924904 3253266652 3705461980 3704619008) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.909) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.0 0.0 0.0) ))! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:03'! displayView self box. self okToDisplay ifFalse:[^self]. self uncache. ((self lastValue = self value and:[self lastOp = self operation])and:[self lastLocked = self locked])ifFalse:[ self drawOnCanvas]. self canvas displayAt: self insetDisplayBox origin ! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 11/4/2008 20:03'! drawOnCanvas | lock lt vt ot nt val | self box. self canvas fillWhite. lock _ self lockForm. self lastLocked: self locked. lock displayOn: self canvas at: self lockBox center - lock boundingBox center clippingBox: self lockBox. self lockBox displayOn: self canvas withBorderWidths:#(0 0 0 1). (lt _ (' ',label) asDisplayText) displayOn: self canvas at: self prefixBox leftCenter - (0@lt boundingBox leftCenter y) clippingBox: self prefixBox. self prefixBox displayOn: self canvas withBorderWidths:#(1 0 0 1). val _ self value. (vt _ val printShowingMax3Digits asDisplayText) displayOn: self canvas at: self valueBox leftCenter - vt boundingBox leftCenter clippingBox: self valueBox. self lastValue: val. self valueBox displayOn: self canvas withBorderWidths:#(0 0 0 1). self operationBoxes with: self operations do:[:bx :op| (ot _ op asString asDisplayText) displayOn: self canvas at: bx center - ot boundingBox center-(0@((#(/ + -) includes: op) ifTrue:[2]ifFalse:[1])) clippingBox: bx. bx displayOn: self canvas withBorderWidths:#(1 0 0 1). op = self operation ifTrue:[self lastOp: op. self canvas reverse: (bx insetBy:1)]. ]. self numberBoxes with: #(1 10 100 0) do:[:bx :num| (nt _ num printString asDisplayText) displayOn: self canvas at: bx center - nt boundingBox center clippingBox: bx. bx displayOn: self canvas withBorderWidths:#(1 0 0 1)]. ! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 21:25'! lockForm ^self locked ifTrue:[self closedPadlock] ifFalse:[self openPadlock]! ! !RVMValueEditorView methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:27'! openPadlock ^((ColorForm extent: 20@16 depth: 8 fromArray: #( 146 2861732522 2449473536 0 0 5614218 0 1841452288 0 0 12741888 3334915730 5882368 0 0 1839879626 2852126914 2852170349 0 0 2324859594 0 3396178570 0 0 2324859594 0 3396176522 0 0 1908838070 0 2995956337 0 0 0 24962 2122220133 1701143938 2122220129 0 39429 151850253 218959117 218958234 0 40461 353178901 353178901 353709502 0 54805 488447261 488447261 490028478 0 60957 556605729 556605733 1027944954 0 60961 824522037 825310525 1160859118 0 60965 825569585 1027423557 1162692090 0 60961 824524093 893732165 1162694126 0 52966 3873888954 3873888998 3873102542) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.972) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.972 0.376) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.25) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.219) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.94 0.188) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.156) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.878 0.125) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.815 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.784 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.094) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.721 0.063) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.69 0.031) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.063) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.658 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.627 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.595 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.564 0.031) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.533 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.501 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.972 0.47 0.0) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.94 0.94 0.972) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.94) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.909 0.909 0.909) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.878 0.878) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.69 0.501) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.345) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.878 0.658 0.313) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.847 0.878) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.721) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.847 0.784 0.69) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.815 0.847) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.815 0.627 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.282) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.784 0.595 0.25) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.753 0.784) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.753 0.721 0.721) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.784) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.721 0.753) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.501 0.156) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.721 0.47 0.125) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.69 0.753) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.69 0.658 0.658) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.721) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.658 0.658 0.69) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.501) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.533 0.47) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.408 0.125) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.627 0.345 0.063) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.595 0.595 0.69) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.564 0.564 0.658) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.533 0.595) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.408 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.376 0.313) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.313 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.533 0.282 0.094) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.533 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.501 0.595) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.313 0.125) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.501 0.25 0.063) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.282 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.094) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.25 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.47 0.219 0.063) #(0.0 0.0 0.0) ))! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:20'! box box isNil ifTrue:[self box: self canvas boundingBox]. box extent = self insetDisplayBox extent ifFalse:[self box: self canvas boundingBox]. ^box! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 10:43'! box: anObject "Set the value of box" box _ anObject. lockBox _ prefixBox _ valueBox _ operationBox _ oneBox _ tenBox _ hundredBox _ zeroBox _ nil.! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'dmiu 4/18/2011 13:34'! canvas "Answer the value of canvas" canvas isNil ifTrue:[self canvas: (ColorForm extent:198@26 depth: (8 min: Display depth)) fillWhite]. ^ canvas! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:12'! canvas: anObject "Set the value of canvas" canvas _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! hundredBox "Answer the value of hundredBox" hundredBox isNil ifTrue:[self hundredBox: (self zeroBox topLeft - (self hundredLabel boundingBox width@0) extent: ( self hundredLabel boundingBox width @ self box height))]. ^ hundredBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! hundredBox: anObject "Set the value of hundredBox" hundredBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:50'! hundredLabel ^' 100 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:02'! lastLocked "Answer the value of lastLocked" lastLocked isNil ifTrue:[self lastLocked: nil]. ^ lastLocked! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 20:02'! lastLocked: anObject "Set the value of lastLocked" lastLocked _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:57'! lastOp "Answer the value of lastOp" lastOp isNil ifTrue:[self lastOp: #none]. ^ lastOp! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:56'! lastOp: anObject "Set the value of lastOp" lastOp _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:52'! lastValue "Answer the value of lastValue" lastValue isNil ifTrue:[self lastValue: 0.0000000000000001]. ^ lastValue! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:51'! lastValue: anObject "Set the value of lastValue" lastValue _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 11/4/2008 19:43'! lockBox "Answer the value of lockBox" lockBox isNil ifTrue:[self lockBox: (self box origin extent: (24@self box height))]. ^ lockBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! lockBox: anObject "Set the value of lockBox" lockBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockGetter "Answer the value of lockGetter" lockGetter isNil ifTrue:[self lockGetter: nil]. ^ lockGetter! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockGetter: anObject "Set the value of lockGetter" lockGetter _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockSetter "Answer the value of lockSetter" lockSetter isNil ifTrue:[self lockSetter: nil]. ^ lockSetter! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:29'! lockSetter: anObject "Set the value of lockSetter" lockSetter _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 21:37'! locked | temp | temp _ self lockGetter isSymbol ifTrue:[self model perform: self lockGetter] ifFalse:[self lockGetter value]. ^temp! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 20:31'! locked: aBoolean "Set the value of locked" self lockSetter isSymbol ifTrue:[model perform: self lockSetter with: aBoolean] ifFalse:[self lockSetter value: aBoolean]! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/29/2008 07:49'! numberBoxes "Answer the number boxes" ^{self oneBox. self tenBox. self hundredBox. self zeroBox}! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:52'! numbersBox "Answer the rectangle encompassing all number boxes" ^((self zeroBox merge: self hundredBox)merge: self tenBox)merge:self oneBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! oneBox "Answer the value of oneBox" oneBox isNil ifTrue:[self oneBox: (self tenBox topLeft - (self oneLabel boundingBox width@0) extent: ( self oneLabel boundingBox width @ self box height))]. ^ oneBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! oneBox: anObject "Set the value of oneBox" oneBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! oneLabel ^' 1 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:42'! opBox "Answer the value of opBox, the rectangle sized for a single operation button" ^0@0 extent: (self box height //2) asPoint! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:39'! operation "Answer the value of operation, #+, #-, #*, or #/" operation isNil ifTrue:[self operation: #+]. ^ operation! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! operation: anObject "Set the value of operation" operation _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:41'! operationBox "Answer the value of operationBox" operationBox isNil ifTrue:[self operationBox: ((self numbersBox topLeft - (self opBox width * 2 @0)extent:self opBox extent * 2))]. ^ operationBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! operationBox: anObject "Set the value of operationBox" operationBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:45'! operationBoxes "Answer the boxes for + * - / boxes in + | * ----- - | / order" ^self operationBox subDivideBy: 2@2! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:47'! operations ^#(+ * - /)! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:37'! postLabelBox "Answer the rectangle encompassing all boxes to the left of the label" ^self operationBox merge: self numbersBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:35'! preLabelBox "Answer the rectangle encompassing all boxes to the right of the label" ^self lockBox merge: self prefixBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:53'! prefixBox "Answer the value of prefixBox" prefixBox isNil ifTrue:[self prefixBox: (self lockBox topRight extent: (self label asDisplayText boundingBox width @ self box height))]. ^ prefixBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:32'! prefixBox: anObject "Set the value of prefixBox" prefixBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:51'! tenBox "Answer the value of tenBox" tenBox isNil ifTrue:[self tenBox: (self hundredBox topLeft - (self tenLabel boundingBox width@0) extent: ( self tenLabel boundingBox width @ self box height))]. ^ tenBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! tenBox: anObject "Set the value of tenBox" tenBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:50'! tenLabel ^' 10 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:34'! valueBox "Answer the value of valueBox" valueBox isNil ifTrue:[self valueBox: (self preLabelBox topRight corner: self postLabelBox bottomLeft)]. ^ valueBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! valueBox: anObject "Set the value of valueBox" valueBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! zeroBox "Answer the value of zeroBox" zeroBox isNil ifTrue:[self zeroBox: (self box topRight - (self zeroLabel boundingBox width@0) extent: ( self zeroLabel boundingBox width @ self box height))]. ^ zeroBox! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:27'! zeroBox: anObject "Set the value of zeroBox" zeroBox _ anObject! ! !RVMValueEditorView methodsFor: 'accessing' stamp: 'ssa 10/28/2008 21:49'! zeroLabel ^' 0 ' asDisplayText! ! !RVMValueEditorView methodsFor: 'controller access' stamp: 'ssa 10/29/2008 21:35'! defaultControllerClass ^RVMValueEditorController! ! !RVMValueEditorView methodsFor: 'editing' stamp: 'ssa 10/29/2008 21:45'! performOperationWith: aNumber self value: (self value perform: self operation with: aNumber). self displayView! ! !RVMValueEditorView methodsFor: 'editing' stamp: 'ssa 10/29/2008 21:46'! resetValueToZero self value: 0. self displayView! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:06'! example "RVMValueEditorView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize:200@26. topView maximumSize: 200@26. topView addSubView: self exampleInstanceMin. topView label: 'Value Editor'. topView controller open! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 20:38'! exampleInstanceMax | view scaler | scaler _ RVMMonitor scalerFor: #bytesUseds. view _ self on: scaler valueGetter: [scaler max] valueSetter:[:v|scaler max:v] label:'max: '. view lockGetter:#maxLocked; lockSetter:#maxLocked:. ^view! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:06'! exampleInstanceMin | view scaler | scaler _ RVMMonitor scalerFor: #bytesUseds. view _ self on: scaler valueGetter: [scaler min] valueSetter:[:v|scaler min:v] label:'min: '. view lockGetter:#minLocked; lockSetter:#minLocked:. ^view! ! !RVMValueEditorView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 21:33'! exampleMinMax "RVMValueEditorView exampleMinMax" | topView v x | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize:200@54. topView maximumSize: 200@54. topView addSubView: (v_self exampleInstanceMin). topView addSubView: (x _ self exampleInstanceMax) below: v. topView label: 'Value Editor'. topView controller open! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/19/2008 11:00'! changeValueBy: delta self value: self value + delta. self displayView.! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 20:57'! label "Answer the value of label" label isNil ifTrue:[self label: '']. ^ label! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 20:57'! label: anObject "Set the value of label" label _ anObject! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:37'! value "Answer the value of value" | temp | temp _ self valueGetter isSymbol ifTrue:[self model perform: self valueGetter] ifFalse:[self valueGetter value]. ^temp isFraction ifTrue:[temp asFloat] ifFalse:[temp]! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/17/2008 14:28'! value: anObject "Set the value of value" self valueSetter isSymbol ifTrue:[model perform: self valueSetter with: anObject] ifFalse:[self valueSetter value: anObject]! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:37'! valueGetter "Answer the value of valueGetter" valueGetter isNil ifTrue:[self valueGetter: [100 atRandom]]. ^ valueGetter! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:36'! valueGetter: anObject "Set the value of valueGetter" valueGetter _ anObject! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:38'! valueSetter "Answer the value of valueSetter" valueSetter isNil ifTrue:[self valueSetter: [:v| v print]]. ^ valueSetter! ! !RVMValueView methodsFor: 'accessing' stamp: 'ssa 9/13/2008 21:36'! valueSetter: anObject "Set the value of valueSetter" valueSetter _ anObject! ! !RVMValueView methodsFor: 'displaying' stamp: 'ssa 10/21/2008 11:32'! displayView | label1 labelForm | self okToDisplay ifFalse:[^self]. self uncache. label1 _ ' ',self label,' ',self value printString. labelForm _ label1 asDisplayText. Display fill: self insetDisplayBox fillColor: Color white. labelForm displayOn: Display at: self insetDisplayBox leftCenter - labelForm boundingBox leftCenter clippingBox: self insetDisplayBox. "(self controller isKindOf: NoController) ifFalse:[ Display border: (self insetDisplayBox insetBy: 1)width: 1 fillColor: self backgroundColor negated.]" ! ! !RVMValueView methodsFor: 'controller access' stamp: 'ssa 9/13/2008 20:35'! defaultControllerClass ^RVMValueController! ! !RVMValueView methodsFor: 'listening' stamp: 'ssa 11/4/2008 19:37'! hear: something self displayView! ! !RVMValueView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 13:52'! on: aModel valueGetter: getterSymbolOrBlock valueSetter: setterSymbolOrBlock label: aString | view | view _ self new. view model: aModel. view valueGetter: getterSymbolOrBlock. view valueSetter: setterSymbolOrBlock. view label: aString. ^view! ! !RVMValueView class methodsFor: 'instance creation' stamp: 'ssa 9/17/2008 14:29'! on: aModel valueGetterOnly: getterSymbolOrBlock | view | view _ self new. view model: aModel. view controller: NoController new. view valueGetter: getterSymbolOrBlock. view valueSetter: [:v| ]. view label: ''. ^view! ! !RVMValueView class methodsFor: 'examples' stamp: 'ssa 9/13/2008 20:31'! example "RVMValueView example" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: 100@25. topView maximumSize: 200@50. topView addSubView: self exampleInstance. topView label: 'Value Editor'. topView controller open! ! !RVMValueView class methodsFor: 'examples' stamp: 'ssa 10/29/2008 07:51'! exampleInstance | view | view _ self on: nil valueGetter: [100 atRandom] valueSetter:[:v|v print] label:'min: '. ^view! ! !RVMView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:16'! dontDisplayWhile: aBlock "Switch my okToDisplay flag off during this block" self okToDisplay: false. aBlock value. self okToDisplay: true. self displayView! ! !RVMView methodsFor: 'updating' stamp: 'ssa 10/7/2008 21:55'! firstFrame "A signal from my topView that I have been reframed. Default is to do nothing but propagate the signal. Subclasses will override to react appropriately" self subViews do:[:each| each firstFrame]! ! !RVMView methodsFor: 'updating' stamp: 'ssa 1/1/1970 00:12'! newFrame "A signal from my topView that I have been reframed. Default is to do nothing but propagate the signal. Subclasses will override to react appropriately" self subViews do:[:each| each newFrame]! ! !RVMView methodsFor: 'updating' stamp: 'ssa 10/21/2008 11:31'! uncache (self topView isKindOf: StandardSystemView) ifTrue:[self topView uncacheBits]! ! !RVMView methodsFor: 'initialize-release' stamp: 'ssa 10/3/2008 23:24'! initialize super initialize. self backgroundColor: Color white. RVMMonitor inform: self! ! !RVMView methodsFor: 'initialize-release' stamp: 'ssa 1/1/1970 00:07'! release RVMMonitor forget: self. super release. ! ! !RVMView methodsFor: 'listening' stamp: 'ssa 1/1/1970 00:34'! hear: aSpeaker "Some object I am listening to is speaking" ! ! !RVMView methodsFor: 'demonstrating' stamp: 'ssa 11/15/2008 15:43'! demo "Add me to a system view and open me on the desktop" self demoSized: self minimumSize! ! !RVMView methodsFor: 'demonstrating' stamp: 'ssa 11/15/2008 15:42'! demoSized: anExtent "Add me to a system view and open me on the desktop" | topView | topView := RVMStandardSystemView new. topView borderWidth:1. topView minimumSize: anExtent. topView addSubView: self . topView label: self class name,' demo'. topView controller open! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 11/11/2008 18:24'! controller: aController super controller: aController. aController isNil ifTrue:[self okToDisplay: false]! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 11/15/2008 15:44'! minimumSize ^100@100! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:15'! okToDisplay "Answer the value of okToDisplay" okToDisplay isNil ifTrue:[self okToDisplay: false]. ^ okToDisplay ! ! !RVMView methodsFor: 'accessing' stamp: 'ssa 1/1/1970 00:05'! okToDisplay: aBoolean "Set the value of okToDisplay" okToDisplay _ aBoolean. self subViews do:[:v| v okToDisplay: aBoolean]! ! !RVMView methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:19'! isRVMView ^true! ! !Random methodsFor: 'private' stamp: 'sma 5/12/2000 12:28'! nextValue "This method generates random instances of Integer in the interval 0 to 16r7FFFFFFF. This method does NOT update the seed; repeated sends answer the same value. The algorithm is described in detail in 'Random Number Generators: Good Ones Are Hard to Find' by Stephen K. Park and Keith W. Miller (Comm. Asso. Comp. Mach., 31(10):1192--1201, 1988)." | lo hi aLoRHi answer | hi _ (seed quo: q) asFloat. lo _ seed - (hi * q). " = seed rem: q" aLoRHi _ (a * lo) - (r * hi). answer _ (aLoRHi > 0.0) ifTrue: [aLoRHi] ifFalse: [aLoRHi + m]. ^ answer! ! !RankThread methodsFor: 'accessing'! end: val end := val! ! !RankThread methodsFor: 'accessing'! id: val id := val! ! !RankThread methodsFor: 'accessing'! localHist ^localHist ! ! !RankThread methodsFor: 'accessing'! localHist: val localHist := val! ! !RankThread methodsFor: 'accessing'! rEnd ^rEnd! ! !RankThread methodsFor: 'accessing'! rEnd: val rEnd := val! ! !RankThread methodsFor: 'accessing'! rStart ^rStart! ! !RankThread methodsFor: 'accessing'! rStart: val rStart := val! ! !RankThread methodsFor: 'accessing'! start [self run] fork.! ! !RankThread methodsFor: 'accessing'! start: val start := val! ! !RankThread methodsFor: 'accessing'! state: val state := val! ! !RankThread methodsFor: 'as yet unclassified'! initKeys | rng mySeed a x k | a := NPBIS amult. rng := NPBRandom new. mySeed := rng findSeedFor: (id - 1) with: numThreads of: (4 * totalKeys * 1) using: (NPBRandom seed) and: a. rng seed: mySeed. k := (maxKey / 4) asInteger. ((start + numKeys) > (end + 1)) ifTrue: [self error: 'this here seems to be inconsistent'.]. start to: end do: [:i | x := rng randlc: a. x := x + (rng randlc: a). x := x + (rng randlc: a). x := x + (rng randlc: a). keyArray at: i put: (x * k) asInteger. ]! ! !RankThread methodsFor: 'as yet unclassified'! step1 "RVMTester print: 'do step 1 '." keyArray at: (Iteration + 1) put: Iteration. keyArray at: (1 + Iteration + (NPBISBase maxIterations)) put: (maxKey - Iteration). 1 to: NPBISBase testArraySize do: [ :i | partialVerifyVals at: i put: (keyArray at: (1 + (testIndexArray at: i)))]. 1 to: maxKey do: [ :i | localHist at: i put: 0]. start to: end do: [ :i | localHist at: (1 + (keyArray at: i)) incrementBy: 1]. 1 to: (maxKey - 1) do: [ :i | localHist at: (i + 1) incrementBy: (localHist at: i)]! ! !RankThread methodsFor: 'as yet unclassified'! step2 "RVMTester print: 'do step 2 '." rStart to: rEnd do: [ :i | 1 to: numThreads do: [ :j | masterHist at: i incrementBy: ((rankThreads at: j) localHist at: i)]]! ! !RankThread methodsFor: 'initialization'! initializeValues: anIS numThreads := anIS numThreads. maxKey := anIS maxKey. keyArray := anIS keyArray. testIndexArray := anIS testIndexArray. masterHist := anIS masterHist. partialVerifyVals := anIS partialVerifyVals. totalKeys := anIS totalKeys. numKeys := (anIS numKeys / anIS numThreads * 1) asInteger. ! ! !RankThread methodsFor: 'license' stamp: 'StefanMarr 4/15/2011 17:04'! license ^'This code is based on the Java version of NPB3. Permission to use, copy, distribute and modify this software for any purpose with or without fee is hereby granted. We request, however, that all derived work reference the NAS Parallel Benchmarks 3.0. This software is provided "as is" without express or implied warranty. Information on NPB 3.0, including the Technical Report NAS-02-008 "Implementation of the NAS Parallel Benchmarks in Java", original specifications, source code, results and information on how to submit new results, is available at: http://www.nas.nasa.gov/Software/NPB/'! ! !RankThread methodsFor: 'running'! run [true] whileTrue: [ "RVMOperations print: 'RankThread waiting id=.', id asString." self wait. self critical: [ "RVMOperations print: 'RankThread entered run critical Id=', id asString." (state == #quit) ifTrue: [ master notify. ^self ] ifFalse: [ self perform: state. master notify. ]. ] ]! ! !RankThread methodsFor: 'running' stamp: 'sm 6/1/2011 15:14'! startStep: aStep self critical: [ self state: aStep. self notify. ].! ! !RankThread class methodsFor: 'instance variables'! iteration ^ Iteration! ! !RankThread class methodsFor: 'instance variables'! iteration: val Iteration := val! ! !RankThread class methodsFor: 'benchmarking'! newFor: anIS with: id start: s1 end: e1 rStart: s2 rEnd: e2 "create new instance" | o | "RVMOperations print: ('new RankThread: ', id asString, ' ', s1 asString, ' ', e1 asString, ' ', s2 asString, ' ', e2 asString)." o := self new. o initializeValues: anIS. o master: anIS. o id: id. o start: s1. o end: e1. o rStart: s2. o rEnd: e2. o localHist: (Array new: o maxKey). o state: 0. ^o "setPriority(Thread.MAX_PRIORITY); setDaemon(true);"! ! !ReBenchHarness commentStamp: 'StefanMarr 5/16/2011 09:10' prior: 0! The ReBenchHarness is optimized for use from the command-line. It is especially meant to be used together with ReBench, a tool to execute and document benchmarks reproducibly. See: https://github.com/smarr/ReBench#readme! !ReBenchHarness class methodsFor: 'defaults'! defaultReporter ^ ReBenchReporter! ! !ReBenchHarness class methodsFor: 'defaults' stamp: 'sm 5/25/2011 17:06'! defaultRunner ^ SMarkWeakScalingRunner! ! !ReBenchHarness class methodsFor: 'helper'! parseArguments: arguments | parser | parser := ReBenchHarnessArgumentParser new. parser harness: self. ^ parser parse: arguments.! ! !ReBenchHarness class methodsFor: 'helper' stamp: 'sm 5/25/2011 17:20'! usageBenchmarkParameters: usage ^ usage, ' processes optional, number of processes/threads used by the benchmarks', String crlf, ' inner-iterations optional, number of iterations done by a single process', String crlf, ' problemSize optional, depending on benchmark for instance size of used data set', String crlf. ! ! !ReBenchHarness class methodsFor: 'helper' stamp: 'StefanMarr 7/25/2011 23:58'! usageHeader | usage | usage := 'SMark Benchmark Framework, version: ', self version, String crlf. usage := usage, String crlf. usage := usage, 'Usage: <vm+image> ', self name, ' <suiteOrBenchmark> [',self withoutWeakScalingOption ,']', ' [processes [inner-iterations [problemSize]]]', String crlf. usage := usage, String crlf. usage := usage, ' This harness is mostly used for weak-scalling benchmarks.', String crlf. usage := usage, ' Use the SMarkHarness for more general settings, it offers more options.', String crlf. usage := usage, String crlf. ^ usage! ! !ReBenchHarness class methodsFor: 'helper'! usageReporter: usage "Will rely on default, which is good for ReBench, so do not advertise option." ^ usage! ! !ReBenchHarness class methodsFor: 'helper'! usageRunner: usage "Will rely on default, which is good for ReBench, so do not advertise option." ^ usage! ! !ReBenchHarness class methodsFor: 'constant' stamp: 'StefanMarr 7/25/2011 23:56'! withoutWeakScalingOption ^ '--without-weak-scaling'! ! !ReBenchHarnessArgumentParser methodsFor: 'argument parsing' stamp: 'sm 5/25/2011 17:17'! determineBenchmarkParametersFromArguments i := i + 1. i <= numParams ifTrue: [ processes := (arguments at: i) asInteger. i := i + 1. i <= numParams ifTrue: [ iterations := (arguments at: i) asInteger. i := i + 1. i <= numParams ifTrue: [ problemSize := arguments at: i. ] ] ].! ! !ReBenchHarnessArgumentParser methodsFor: 'argument parsing'! determineReporter reporter := harness defaultReporter new.! ! !ReBenchHarnessArgumentParser methodsFor: 'argument parsing' stamp: 'StefanMarr 7/26/2011 00:10'! determineRunner (arguments includes: ReBenchHarness withoutWeakScalingOption) ifTrue: [ current = ReBenchHarness withoutWeakScalingOption ifTrue: [ current := arguments at: (i + 1). ]. arguments remove: ReBenchHarness withoutWeakScalingOption. runner := harness superclass defaultRunner new. ] ifFalse: [ runner := harness defaultRunner new. ].! ! !ReBenchHarnessArgumentParser methodsFor: 'helper' stamp: 'StefanMarr 7/26/2011 00:18'! instructRunner super instructRunner. runner iterations: runner class defaultNumberOfIterations. (runner respondsTo: #innerIterations:) ifTrue: [ runner innerIterations: iterations. ].! ! !ReBenchReporter methodsFor: 'as yet unclassified' stamp: 'StefanMarr 5/16/2011 15:23'! benchmarkHeader: aName ^ self! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 10:48'! assignCollapsePointFor: aSSView "Offer up a location along the left edge of the screen for a collapsed SSView. Make sure it doesn't overlap any other collapsed frames." | grid otherFrames y free topLeft viewBox | grid _ 24. "should be mult of 8, since manual move is gridded by 8" aSSView isMorph ifTrue: [otherFrames := (SystemWindow windowsIn: aSSView world satisfying: [:w | true]) collect: [:w | w collapsedFrame] thenSelect: [:rect | rect notNil]. viewBox := self reduceByFlaps: aSSView world viewBox] ifFalse: [otherFrames _ ScheduledControllers scheduledWindowControllers collect: [:aController | aController view collapsedFrame] thenSelect: [:rect | rect notNil]. viewBox _ Display boundingBox]. y _ viewBox top. [(y _ y + grid) <= (viewBox height - grid)] whileTrue: [topLeft _ viewBox left@y. free _ true. otherFrames do: [:w | free _ free & (topLeft ~= w topLeft)]. free ifTrue: [^ topLeft]]. "If all else fails..." ^ 0 @ 0! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:11'! maximumUsableArea | allowedArea | allowedArea _ Display usableArea. Smalltalk isMorphic ifTrue: [ allowedArea := allowedArea intersect: ActiveWorld visibleClearArea. ]. ^allowedArea ! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:12'! screenTopSetback Smalltalk isMorphic ifTrue: [^ 0] ifFalse: [^ 18]! ! !RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'ssa 9/3/2008 11:12'! scrollBarSetback Smalltalk isMorphic ifTrue: [^ 16 - 3] "width = 16; inset from border by 3" ifFalse: [^ 24]! ! !Rectangle methodsFor: 'accessing'! ottomLeft: aPoint "Set the position of the bottomLeft corner of the receiver." "KSC Extension" origin _ aPoint x @ self top. corner _ self right @ aPoint y! ! !Rectangle methodsFor: 'accessing'! ottomRight: bottomRightPoint "Set the position of the right corner of the bottom horizontal line of the receiver." corner _ bottomRightPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/22/2009 18:02'! corner: aPoint "Set the point at the bottom right corner of the receiver." corner _ aPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/23/2009 14:39'! extent: aPoint corner _ origin + aPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/22/2009 16:32'! height: heightInteger "Change the receiver's bottom y to make its height the argument heightInteger." corner y: origin y + heightInteger! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 9/2/2009 17:10'! origin: aPoint "Set the point at the top left corner of the receiver." origin _ aPoint! ! !Rectangle methodsFor: 'accessing'! topLeft: topLeftPoint "Set the point at the top left corner of the receiver's top horizontal line." origin _ topLeftPoint! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/25/2009 14:40'! topRight: aPoint "Set the position of the top right corner of the receiver." origin _ self left @ aPoint y. corner _ aPoint x @ self bottom! ! !Rectangle methodsFor: 'accessing' stamp: 'ssa 8/31/2009 16:30'! width: widthInteger "Change the receiver's right x to make its width the argument widthInteger." corner x: origin x + widthInteger! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 11/16/2008 02:34'! asRandomPoint "ssa - Answer a random point that lies within my borders" ^self origin + self extent atRandom ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/24/2009 09:39'! intersect: aRectangle "Answer a Rectangle that is the area in which the receiver overlaps with aRectangle. Optimized for speed; old code read: ^Rectangle origin: (origin max: aRectangle origin) corner: (corner min: aRectangle corner) " | aPoint left right top bottom | aPoint _ aRectangle origin copy. aPoint x > origin x ifTrue:[left _ aPoint x] ifFalse:[left _ origin x]. aPoint y > origin y ifTrue:[top _ aPoint y] ifFalse:[top _ origin y]. aPoint _ aRectangle corner copy. aPoint x < corner x ifTrue:[right _ aPoint x] ifFalse:[right _ corner x]. aPoint y < corner y ifTrue:[bottom _ aPoint y] ifFalse:[bottom _ corner y]. ^Rectangle origin: (left@top) corner: (right@bottom) ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/23/2009 17:07'! selfMerge: aRectangle "Alter the receiver so that it contains both self and the argument aRectangle. This is much faster than a merge: but must be used wisely since it modifies both the receiver and the points which make up its origin and corner." "KSC Extension" | hisOrigin hisCorner hisOriginX hisOriginY hisCornerX hisCornerY | hisOrigin _ aRectangle origin. hisCorner _ aRectangle corner. hisOriginX _ hisOrigin x. hisOriginY _ hisOrigin y. hisCornerX _ hisCorner x. hisCornerY _ hisCorner y. origin x > hisOriginX ifTrue: [origin x: hisOriginX]. origin y > hisOriginY ifTrue: [origin y: hisOriginY]. corner x < hisCornerX ifTrue: [corner x: hisCornerX]. corner y < hisCornerY ifTrue: [corner y: hisCornerY].! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 11:39'! subDivideBy: aPoint "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom). columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'rectangle functions' stamp: 'ssa 8/15/2008 12:24'! subDivideRoundedBy: aPoint "ssa - round the orign and extent points" "Answer a collection of rectangles which divide the receiver evenly into aPoint x columns and aPoint y rows. Answer the new rectangles left to right then down. Yes, this method could be much shorter, but I tried to minimize duplications of arithmetic for efficiency." "(0@0 corner: 100@100) subDivideBy: 4@2" | rows columns eachWidth eachHeight subRegions rowTop baseIndex myLeft rowBottom columnLeft columnRight | columns _ aPoint x. rows _ aPoint y. eachWidth _ self width / columns. eachHeight _ self height / rows. subRegions _ Array new: columns * rows. rowTop _ self top. baseIndex _ 0. myLeft _ self left. 1 to: rows do: [:rowNumber | rowBottom _ rowTop + eachHeight. columnLeft _ myLeft. columnRight _ columnLeft + eachWidth. 1 to: columns do: [:columnNumber | subRegions at: baseIndex + columnNumber put: (self species origin: columnLeft @ rowTop corner: columnRight @ rowBottom) rounded. columnLeft _ columnRight. columnRight _ columnRight + eachWidth]. rowTop _ rowBottom. rowBottom _ rowBottom + eachHeight. baseIndex _ baseIndex + columns]. ^subRegions ! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:24'! fastMoveBy: aPoint "Change the corner positions of the receiver so that its area translates by the amount defined by the argument, aPoint. This is much faster than a merge: but must be used wisely since it modifies both the receiver and the points which make up its origin and corner." origin moveBy: aPoint. corner moveBy: aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:09'! moveBy: aPoint "Change the corner positions of the receiver so that its area translates by the amount defined by the argument, aPoint." origin _ origin + aPoint. corner _ corner + aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/25/2009 14:09'! moveTo: aPoint "Change the corners of the receiver so that its top left position is aPoint." corner _ corner + aPoint - origin. origin _ aPoint! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 10/8/2008 17:52'! newRectButtonPressedDo: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous. Only tracks while mouse is down." | rect newRect buttonNow delay | delay _ Delay forMilliseconds: 10. buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow] whileTrue: ["delay wait." buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Smalltalk isMorphic ifTrue: []. Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 10/8/2008 17:49'! newRectFrom: newRectBlock "Track the outline of a new rectangle until mouse button changes. newFrameBlock produces each new rectangle from the previous" | rect newRect buttonStart buttonNow delay | delay _ Delay forMilliseconds: 10. buttonStart _ buttonNow _ Sensor anyButtonPressed. rect _ self. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. [buttonNow == buttonStart] whileTrue: ["delay wait." buttonNow _ Sensor anyButtonPressed. newRect _ newRectBlock value: rect. newRect = rect ifFalse: [Display border: rect width: 2 rule: Form reverse fillColor: Color gray. Display border: newRect width: 2 rule: Form reverse fillColor: Color gray. rect _ newRect]]. Display border: rect width: 2 rule: Form reverse fillColor: Color gray. " pay the price for reading the sensor directly ; get this party started " Sensor processEvent: Sensor createMouseEvent. ^ rect! ! !Rectangle methodsFor: 'transforming' stamp: 'ssa 8/27/2008 04:43'! scaleByRect: scale "Answer a Rectangle scaled by scale, a rectangle." ^Rectangle origin: origin * scale origin corner: corner * scale corner! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 10/29/2008 20:57'! display | quad | quad _ Quadrangle region: self borderWidth: 1 borderColor: Color black insideColor: nil. quad display! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 11/4/2008 19:15'! displayOn: aDisplayMedium withBorderWidths: anArray "Rectangle fromUser displayOn: Display withBorderWidths:#(16 8 4 1)" "anArray = #(left top right bottom ) integers" | quad | quad _ Quadrangle region: self borderWidth: ((anArray at:1)@(anArray at:2) corner: (anArray at:3)@(anArray at:4))borderColor: Color black insideColor: nil. quad displayOn: aDisplayMedium! ! !Rectangle methodsFor: 'displaying' stamp: 'ssa 11/4/2008 19:16'! displayWithBorderWidths: anArray "Rectangle fromUser displayWithBorderWidths:#(16 8 4 1)" "anArray = #(left top right bottom ) integers" self displayOn: Display withBorderWidths: anArray! ! !Rectangle methodsFor: 'sizing - Louvre' stamp: 'ssa 12/5/2009 08:28'! size ^self extent! ! !RemoteString methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:19'! text "Answer the receiver's string asText if remote files are enabled." | theFile theText | (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil]) ifTrue: [^ nil]. theFile _ SourceFiles at: sourceFileNumber. theFile safelyDo: [ theFile position: filePositionHi. theText _ theFile nextChunkText]. ^theText! ! !RemoteString methodsFor: 'private' stamp: 'dmu 9/7/2010 14:23'! string: aString onFileNumber: fileNumber "Store this as my string if source files exist." | theFile | (SourceFiles at: fileNumber) == nil ifFalse: [theFile _ SourceFiles at: fileNumber. theFile safelyDo: [ theFile setToEnd; cr. self string: aString onFileNumber: fileNumber toFile: theFile] ]! ! !RenaissanceTransporter methodsFor: 'initializing' stamp: 'sm 7/8/2011 23:17'! initialize self initializePackage; initializeTeam; initializePreambleAndPostscript. subTransporters := { MSWLookTransporter new. Transporter forPackage: (PackageInfo named: 'Ly'). SlyTransporter new. }! ! !RenaissanceTransporter methodsFor: 'initializing' stamp: 'sm 3/11/2011 12:11'! initializePackage self package: (CompositePackageInfo new name: 'Renaissance'; packages: { "RVMBootstrapPackage new." PackageInfo named: 'RVM'. PackageInfo named: 'DMU'. }; yourself). ! ! !RenaissanceTransporter methodsFor: 'initializing' stamp: 'ads 1/24/2011 14:52'! initializePreambleAndPostscript self preambleBlock: [:file | RVMBootstrapPackage new saveTrickyModificationsToFile: file]; postscriptBlock: [:file | file nextPutAll: '(ChangeSorter basicNewChangeSet: ''New changes'') ifNotNilDo: [:cs | ChangeSet newChanges: cs].'; cr].! ! !RenaissanceTransporter methodsFor: 'initializing' stamp: 'sm 3/7/2011 15:35'! initializeTeam self team: (ProjectTeam new initialsOfProjectMembers: {'dmu'. 'smu'. 'ssa'. 'ads'. 'sm'. 'piv'. 'max'}; "The Renaissance image is based on Squeak 3.7, which was put out in 2004; the Renaissance project started in 2007 or 2008. I don't understand why some of our methods are stamped 1970, though. -- Adam" timestampFilter: [:t | t year > 2005 or: [t year = 1970]]; yourself).! ! !RenaissanceTransporter methodsFor: 'removing' stamp: 'ads 1/26/2011 16:17'! revert super revert. self team revertPackage: RVMBootstrapPackage new.! ! !RenaissanceTransporter class methodsFor: 'transporter' stamp: 'ads 2/4/2011 11:47'! transportersForFileOutMenu ^ { self new }! ! !ResumableTestFailure methodsFor: 'camp smalltalk'! isResumable "Of course a ResumableTestFailure is resumable ;-)" ^true! ! !ResumableTestFailure methodsFor: 'camp smalltalk'! sunitExitWith: aValue self resume: aValue! ! !ResumableTestFailure commentStamp: '<historical>' prior: 0! A ResumableTestFailure triggers a TestFailure, but lets execution of the TestCase continue. this is useful when iterating through collections, and #assert: ing on each element. in combination with methods like testcase>>#assert:description:, this lets you run through a whole collection and note which tests pass. here''s an example: (1 to: 30) do: [ :each | self assert: each odd description: each printString, ' is even' resumable: true] for each element where #odd returns <false>, the element will be printed to the Transcript. ! !ResumableTestFailureTestCase methodsFor: 'Not categorized' stamp: 'BaseSystem 8/30/2009 09:40'! resumableTestFailureTest self assert: false description: 'You should see more than me' resumable: true; assert: false description: 'You should see more than me' resumable: true; assert: false description: 'You should see me last' resumable: false; assert: false description: 'You should not see me' resumable: true! ! !ResumableTestFailureTestCase methodsFor: 'logging' stamp: 'BaseSystem 8/30/2009 09:40'! logFailure: aString duplicateFailureLog add: aString. super logFailure: aString.! ! !ResumableTestFailureTestCase methodsFor: 'running' stamp: 'BaseSystem 8/30/2009 09:40'! setUp duplicateFailureLog := OrderedCollection with: 'In set up'.! ! !ResumableTestFailureTestCase methodsFor: 'running' stamp: 'BaseSystem 8/30/2009 09:40'! tearDown self deny: 'You should not see me' = duplicateFailureLog last description: 'We saw the ''You should not see me'' failure'. self deny: 'You should see more than me' = duplicateFailureLog last description: 'We did not see more than a ''You should see more than me'' failure'.! ! !ResumableTestFailureTestCase methodsFor: 'running' stamp: 'BaseSystem 8/30/2009 09:40'! testResumable | result suite | suite := TestSuite new. suite addTest: (self class selector: #errorTest). suite addTest: (self class selector: #regularTestFailureTest). suite addTest: (self class selector: #resumableTestFailureTest). suite addTest: (self class selector: #okTest). result := suite run. self assert: result failures size = 2; assert: result errors size = 1! ! !ResumableTestFailureTestCase methodsFor: 'test data' stamp: 'BaseSystem 8/30/2009 09:40'! errorTest 1 zork! ! !ResumableTestFailureTestCase methodsFor: 'test data' stamp: 'BaseSystem 8/30/2009 09:40'! failureTest self assert: false description: 'You should see me' resumable: true; assert: false description: 'You should see me too' resumable: true; assert: false description: 'You should see me last' resumable: false; assert: false description: 'You should not see me' resumable: true! ! !ResumableTestFailureTestCase methodsFor: 'test data' stamp: 'BaseSystem 8/30/2009 09:40'! okTest self assert: true! ! !ResumableTestFailureTestCase methodsFor: 'test data' stamp: 'BaseSystem 8/30/2009 09:40'! regularTestFailureTest self assert: false description: 'You should see me'! ! !ResumableTestFailureTestCase class methodsFor: 'history' stamp: 'simon.denier 11/22/2008 22:13'! lastStoredRun ^ ((Dictionary new) add: (#passed->((Set new) add: #testResumable; yourself)); add: (#timeStamp->'22 November 2008 10:11:35 pm'); add: (#failures->((Set new))); add: (#errors->((Set new))); yourself)! ! !RoarTinyBench methodsFor: 'benchmarking' stamp: 'StefanMarr 11/7/2010 03:31'! benchBytecode: iterations "Handy bytecode-heavy benchmark, was Integers>>benchmark" "(500000 // time to run) = approx bytecodes per second" "5000000 // (Time millisecondsToRun: [10 benchmark]) * 1000" "3059000 on a Mac 8100/100" | size flags prime k count | size := 8190. 1 to: iterations do: [:iter | count := 0. flags := (Array new: size) atAllPut: true. 1 to: size do: [:i | (flags at: i) ifTrue: [prime := i+1. k := i + prime. [k <= size] whileTrue: [flags at: k put: false. k := k + prime]. count := count + 1]]]. ^ count! ! !RoarTinyBench methodsFor: 'benchmarking' stamp: 'StefanMarr 11/7/2010 03:34'! benchFib: n "Handy send-heavy benchmark, was Integer>>benchFib" "(result // seconds to run) = approx calls per second" " | r t | t := Time millisecondsToRun: [r := 26 benchFib]. (r * 1000) // t" "138000 on a Mac 8100/100" ^ n < 2 ifTrue: [1] ifFalse: [(self benchFib: (n-1)) + (self benchFib: (n-2)) + 1] ! ! !RoarTinyBench methodsFor: 'benchmarking' stamp: 'StefanMarr 1/15/2011 22:53'! startBenchmarkAndWaitForCompletion RVMOperations print: (self tinyBenchmarksParallel)! ! !RoarTinyBench methodsFor: 'benchmarking' stamp: 'StefanMarr 11/7/2010 03:36'! tinyBenchmarks "Report the results of running the two tiny Squeak benchmarks. ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results" "0 tinyBenchmarks" "On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec" "On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec" | t1 t2 r n1 n2 | n1 := 1. [t1 := Time millisecondsToRun: [self benchBytecode: n1]. t1 < 1000] whileTrue: [n1 := n1 * 2]. "Note: #benchmark's runtime is about O(n)" n2 := 28. [t2 := Time millisecondsToRun: [r := self benchFib: n2]. t2 < 1000] whileTrue: [n2 := n2 + 1]. "Note: #benchFib's runtime is about O(n^2)." ^ ((n1 * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', ((r * 1000) // t2) printString, ' sends/sec'! ! !RoarTinyBench methodsFor: 'benchmarking' stamp: 'StefanMarr 1/15/2011 22:45'! tinyBenchmarksParallel "Report the results of running the two tiny Squeak benchmarks. ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results" "0 tinyBenchmarks" "On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec" "On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec" | t1 t2 r n1 n2 | "Determine a good problem size for the benchmark" n1 := 1. [t1 := Time millisecondsToRun: [self benchBytecode: n1]. t1 < 1000] whileTrue: [n1 := n1 * 2]. "Note: #benchmark's runtime is about O(n)" "now n1 is the value for which we do the measurement" t1 := Time millisecondsToRun: [self run: #benchBytecode: with: n1 times: numberOfProcesses]. "Determine a good problem size for the benchmark" n2 := 28. [t2 := Time millisecondsToRun: [r := self benchFib: n2]. t2 < 1000] whileTrue: [n2 := n2 + 1]. "Note: #benchFib's runtime is about O(k^n), where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...." "now we have our target n2 and r value. lets take the time for it" t2 := Time millisecondsToRun: [self run: #benchFib: with: n2 times: numberOfProcesses]. ^ ((n1 * numberOfProcesses * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', ((r * numberOfProcesses * 1000) // t2) printString, ' sends/sec' ! ! !RoarTinyBench methodsFor: 'private' stamp: 'StefanMarr 1/15/2011 22:49'! run: aSymbol with: argument times: nTimes | mtx sig n | mtx := Semaphore forMutualExclusion. sig := Semaphore new. n := nTimes. 1 to: nTimes do: [:i | [ aSymbol = #benchFib: ifTrue: [ self benchFib: argument.] ifFalse: [ aSymbol = #benchBytecode: ifTrue: [ self benchBytecode: argument] ifFalse: [ self perform: aSymbol with: argument.]]. mtx critical: [ n := n - 1. (n == 0) ifTrue: [sig signal]] ] fork ]. sig wait.! ! !RoarTinyBench class methodsFor: 'benchmarking' stamp: 'StefanMarr 11/7/2010 12:45'! tinyBenchmarks "RoarTinyBench tinyBenchmarks" RVMOperations print: (self new tinyBenchmarks)! ! !RoarTinyBench class methodsFor: 'benchmarking' stamp: 'StefanMarr 11/7/2010 12:45'! tinyBenchmarksParallel "RoarTinyBench tinyBenchmarksParallel" RVMOperations print: (self new numProcesses: 16; tinyBenchmarksParallel)! ! !RunArray methodsFor: '*RVM-Archiving-fileIn/Out'! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: runs size. 1 to: runs size do: [:x | aStream store: (runs at: x). aStream nextPut: (values at: x)]! ! !RunArray class methodsFor: 'instance creation' stamp: 'ssa 9/3/2008 11:15'! scanFrom: strm "Read the style section of a fileOut or sources file. nextChunk has already been done. We need to return a RunArray of TextAttributes of various kinds. These are written by the implementors of writeScanOn:" | rr vv aa this | (strm peekFor: $( ) ifFalse: [^ nil]. rr _ OrderedCollection new. [strm skipSeparators. strm peekFor: $)] whileFalse: [rr add: (Number readFrom: strm)]. vv _ OrderedCollection new. "Value array" aa _ OrderedCollection new. "Attributes list" [(this _ strm next) == nil] whileFalse: [ this == $, ifTrue: [vv add: aa asArray. aa _ OrderedCollection new]. this == $a ifTrue: [aa add: (TextAlignment new alignment: (Integer readFrom: strm))]. this == $f ifTrue: [aa add: (TextFontChange new fontNumber: (Integer readFrom: strm))]. this == $F ifTrue: [aa add: (TextFontReference new toFont: (StrikeFont familyName: (strm upTo: $#) size: (Integer readFrom: strm)))]. this == $b ifTrue: [aa add: (TextEmphasis bold)]. this == $i ifTrue: [aa add: (TextEmphasis italic)]. this == $u ifTrue: [aa add: (TextEmphasis underlined)]. this == $= ifTrue: [aa add: (TextEmphasis struckOut)]. this == $n ifTrue: [aa add: (TextEmphasis normal)]. this == $- ifTrue: [aa add: (TextKern kern: -1)]. this == $+ ifTrue: [aa add: (TextKern kern: 1)]. this == $c ifTrue: [aa add: (TextColor scanFrom: strm)]. "color" this == $L ifTrue: [aa add: (TextLink scanFrom: strm)]. "L not look like 1" " this == $R ifTrue: [aa add: (TextURL scanFrom: strm)]." "R capitalized so it can follow a number" " this == $q ifTrue: [aa add: (TextSqkPageLink scanFrom: strm)]. " " this == $p ifTrue: [aa add: (TextSqkProjectLink scanFrom: strm)]. " this == $P ifTrue: [aa add: (TextPrintIt scanFrom: strm)]. this == $d ifTrue: [aa add: (TextDoIt scanFrom: strm)]. "space, cr do nothing" ]. aa size > 0 ifTrue: [vv add: aa asArray]. ^ self runs: rr asArray values: vv asArray " RunArray scanFrom: (ReadStream on: '(14 50 312)f1,f1b,f1LInteger +;i') "! ! !RunArray class methodsFor: '*RVM-Archiving-instance creation'! archiveVersion ^3! ! !RunArray class methodsFor: '*RVM-Archiving-instance creation'! dearchive2From: aStream | anInteger runs values | anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: aStream next]. ^self runs: runs values: values! ! !RunArray class methodsFor: '*RVM-Archiving-instance creation'! dearchive: versionNumber from: aStream | anInteger runs values | versionNumber = 1 ifTrue: [anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: (aStream read: Integer)]. ^self runs: runs values: values]. versionNumber = 2 ifTrue: [^self dearchive2From: aStream]. versionNumber = self archiveVersion ifTrue: [^self dearchiveFrom: aStream]. self error: 'Can''t dearchive this version.'! ! !RunArray class methodsFor: '*RVM-Archiving-instance creation'! dearchiveFrom: aStream | anObject anInteger runs values | anObject _ self basicNew. aStream storeObject: anObject. anInteger _ aStream read: Integer. runs _ Array new: anInteger. values _ Array new: anInteger. 1 to: anInteger do: [:x | runs at: x put: (aStream read: Integer). values at: x put: aStream next]. ^anObject setRuns: runs setValues: values! ! !SMarkAutosizeRunner methodsFor: 'initialization' stamp: 'StefanMarr 3/19/2011 19:59'! initialize super initialize. targetTime := self class defaultTargetTime.! ! !SMarkAutosizeRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 3/20/2011 10:27'! performBenchmark: aSelector "First determine a useful number of inner loop iterations until the targetTime is reached." | execTime i | "make sure no timers are recorded for this" timers := nil. i := 1. execTime := Time millisecondsToRun: [ suite perform: aSelector. ]. [ execTime > targetTime ] whileFalse: [ i := i * 2. "Was thinking of doing something fancy here, but just go with this simple staight-forward solution" execTime := Time millisecondsToRun: [ 1 to: i do: [:ignored| suite perform: aSelector]]. ]. innerLoopIterations := i. "Then start executing the benchmark" ^ super performBenchmark: aSelector.! ! !SMarkAutosizeRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 3/20/2011 10:49'! runBaseBenchmark "baseBenchmark is not supported with autosizing. I do not see how that can be made possible since all different benchmarks will have different number of iterations, and the only way how a consistent baseline could be found would be to normalize the results, but well, incooprorating the baseline measurement with the statistical evaluation is harder than just substracting a one time value..., I am not going to do that here for the moment. Stefan 2011-03-20" (suite respondsTo: #baseBenchmark) ifFalse: [ ^ nil ]. "I decided to go here with a silent solution to avoid thinking about logging frameworks and Transcript to console convertion..." self recordResults: (self class defaultTimer new: 'total') for: #baseBenchmark ! ! !SMarkAutosizeRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 3/20/2011 10:31'! timedBenchmarkExecution: aSelector "Will do a timed execution of the benchmark and return the result timer" | timer | timers := Dictionary new. timer := self createTimer: 'total'. timer start. 1 to: innerLoopIterations do: [:ignored| suite perform: aSelector. ]. timer stop. self recordResults: timer for: aSelector. ^ timer! ! !SMarkAutosizeRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/19/2011 19:18'! targetTime "Target time in milliseconds" ^ targetTime! ! !SMarkAutosizeRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/19/2011 19:18'! targetTime: anIntInMilliseconds "Target time in milliseconds" targetTime := anIntInMilliseconds! ! !SMarkAutosizeRunner class methodsFor: 'defaults' stamp: 'StefanMarr 3/19/2011 19:17'! defaultTargetTime "300 milliseconds seems to be a reasonable target time for most problems. It is a compromise between the general measurment noise as well as timer accuracy and the absolute runtime of benchmarks" ^ 300! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! runnerClass ^ SMarkTestAutosizeRunner! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! testAutosizing "Ensure that the runtime is automatically sized up to a predefined value" | runner results big small runTime benchmarkSum | runner := self runnerClass new. "sanity check for target time" "Not checked since we reduced the targetTime for testing: self assert: self runnerClass defaultTargetTime equals: runner targetTime." self assert: (self runnerClass defaultTargetTime > 250). runner iterations: 3. runner suite: SMarkTestRunnerSuiteForAutosizing new. "Execute the benchmarks and take the overall time it takes" runTime := Time millisecondClockValue. results := runner execute. runTime := Time millisecondClockValue - runTime. "There should be three benchmarks" self assert: 3 equals: results size. self assert: (results includesKey: #baseBenchmark). big := results at: #Big. small := results at: #Small. self assert: (big respondsTo: #at:). self assert: 3 equals: big size. self assert: (runner targetTime <= (big at: 1) total). self assert: (runner targetTime <= (small at: 1) total). "Calculate the sum of all measurements" benchmarkSum := big inject: 0 into: [:sum :result| sum + result total]. benchmarkSum := small inject: benchmarkSum into: [:sum :result| sum + result total]. "And now make sure that we not try to find the problem size for every but only the first run" self assert: (benchmarkSum * 2) > runTime. ! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! testAutosizingBaseBenchmark "Ensure that baseBenchmarks are not delivering any data since I do not see how that could be done nicely" | runner results | runner := self runnerClass new. runner iterations: 3. runner suite: SMarkTestRunnerSuiteForAutosizing new. "Execute the benchmarks and take the overall time it takes" results := runner execute. "There should be two benchmarks" self assert: 3 equals: results size. self assert: 0 equals: ((results at: #baseBenchmark) at: 1) total. ! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! testBaseBenchmark "Different from base test: Ensure the base benchmark is NOT executed when available" | runner | runner := self runnerClass execute: SMarkTestSuiteWithBaseBenchmark new. self deny: runner baseBenchmarkExecuted ! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! testExecute "This test is slightly different from the one in the base class" | runner results performedBenchmarks | runner := self runnerClass new. runner suite: SMarkTestRunnerSuiteForPerfromBenchmark new. results := runner execute. performedBenchmarks := runner performedBenchmarks. self assert: 4 equals: performedBenchmarks size. "Different from base test" self deny: (performedBenchmarks includes: #baseBenchmark). "Different from base test" self assert: (results respondsTo: #at:). "But still we get a result" "Different from base test" self assert: (((results at: #baseBenchmark) at: 1) isKindOf: SMarkResult).! ! !SMarkAutosizeRunnerTest methodsFor: 'as yet unclassified'! testIterations | runner | "This test is different then the one in the base class, it is not direct, but just looks at the results" " simple scenario should default to 1 run for now " runner := self runnerClass execute: SMarkTestRunnerSuite new. self assert: 1 equals: (runner results at: #NotifyRunner) size. " but we can also be more fancy and set the number of iterations " runner := self runnerClass new. runner suite: SMarkTestRunnerSuite new. "first check again that the default is as expected" self assert: 1 equals: runner iterations. runner iterations: 10. self assert: runner iterations equals: 10. runner execute. self assert: 10 equals: (runner results at: #NotifyRunner) size.! ! !SMarkAutosizeRunnerTest class methodsFor: 'as yet unclassified'! shouldInheritSelectors ^ true! ! !SMarkCompiler methodsFor: 'benchmarking'! benchCompiler "was Benchmark>>testCompiler" SMarkCompilerTargetClass new compile: 'somethingDummy: aBlock repeated: nTimes | i emptyBlock emptyTime blockTime | nTimes > 1000 ifTrue: [^self time: aBlock repeatedK: nTimes // 1000]. emptyBlock := []. emptyTime := Time millisecondsToRun: [i := 0. [(i := i + 1) <= nTimes] whileTrue: [emptyBlock value]]. blockTime := Time millisecondsToRun: [i := 0. [(i := i + 1) <= nTimes] whileTrue: [aBlock value]]. ^blockTime - emptyTime'.! ! !SMarkCompiler class methodsFor: 'script entry'! defaultNumberOfIterations ^ 50! ! !SMarkCompiler class methodsFor: 'script entry'! defaultNumberOfProcesses ^ 8! ! !SMarkCompilerTargetClass methodsFor: 'compiling'! acceptsLoggingOfCompilation "Answer whether the receiver's method submisions and class defintions should be logged to the changes file and to the current change set." ^ false! ! !SMarkCompilerTargetClass methodsFor: 'accessing method dictionary'! addAndClassifySelector: selector withMethod: compiledMethod inProtocol: aCategory notifying: requestor | priorMethodOrNil oldProtocol newProtocol | priorMethodOrNil := self compiledMethodAt: selector ifAbsent: [nil]. self addSelectorSilently: selector withMethod: compiledMethod. oldProtocol := self organization categoryOfElement: selector. SystemChangeNotifier uniqueInstance doSilently: [self organization classify: selector under: aCategory]. newProtocol := self organization categoryOfElement: selector.! ! !SMarkCompilerTargetClass methodsFor: 'initialization' stamp: 'sm 1/17/2011 09:38'! initialize super initialize. self methodDictionary: MethodDictionary new.! ! !SMarkHarness commentStamp: 'StefanMarr 3/12/2011 21:12' prior: 0! A benchmark harness stears the execution and reporting of benchmarks. For that purpose, it will use a designated benchmark runner to do the execution and a benchmark reporter to output the results. The benchmark harness is also parameterized by the benchmark suites that are to be executed.! !SMarkHarness class methodsFor: 'defaults'! defaultOutputDestination ^ Smalltalk at: #ScriptConsole ifAbsent: [SMarkReporter defaultOutputDestination]! ! !SMarkHarness class methodsFor: 'defaults'! defaultReporter ^ SMarkReporter defaultReporter! ! !SMarkHarness class methodsFor: 'defaults'! defaultRunner ^ SMarkSuite defaultRunner! ! !SMarkHarness class methodsFor: 'benchmarking' stamp: 'sm 5/25/2011 17:41'! execute: runner andReport: reporter runner reportConfiguration: self defaultOutputDestination. runner execute. reporter runner: runner. reporter outputStream: self defaultOutputDestination. reporter report.! ! !SMarkHarness class methodsFor: 'benchmarking'! execute: aBenchmarkOrSuite using: aRunnerClass andReport: withAReporterClass | parsedBenchmarkOrSuite runner reporter | parsedBenchmarkOrSuite := self parseBenchmarkOrSuite: aBenchmarkOrSuite. runner := aRunnerClass new. reporter := withAReporterClass new. self instructRunner: runner with: parsedBenchmarkOrSuite. self execute: runner andReport: reporter. ! ! !SMarkHarness class methodsFor: 'helper'! parseArguments: arguments | parser | parser := SMarkHarnessArgumentParser new. ^ parser parse: arguments.! ! !SMarkHarness class methodsFor: 'helper'! shouldShowUsage: arguments arguments size < 2 ifTrue: [^ true ]. ^ arguments anySatisfy: [:elem | (elem = '--help') or: [elem = '-?'] ]. ! ! !SMarkHarness class methodsFor: 'helper'! usage | usage | "Example usage: SMarkHarness SMarkRunner SMarkReporter SMarkLoops.benchIntLoop 1 1 5" usage := self usageHeader. usage := usage, 'Arguments:', String crlf. usage := self usageRunner: usage. usage := self usageReporter: usage. usage := usage, ' suiteOrBenchmark required, either a SMarkSuite with benchmarks,', String crlf. usage := usage, ' or a benchmark denoted by Suite.benchName', String crlf. usage := self usageBenchmarkParameters: usage. ScriptConsole print: usage.! ! !SMarkHarness class methodsFor: 'helper'! usageBenchmarkParameters: usage ^ usage, ' iterations optional, number of times the benchmarks are repeated', String crlf, ' processes optional, number of processes/threads used by the benchmarks', String crlf, ' problemSize optional, depending on benchmark for instance number of', String crlf, ' inner iterations or size of used data set', String crlf. ! ! !SMarkHarness class methodsFor: 'helper'! usageHeader | usage | usage := 'SMark Benchmark Framework, version: ', self version, String crlf. usage := usage, String crlf. usage := usage, 'Usage: <vm+image> ', self name, ' [runner] [reporter] <suiteOrBenchmark>', String crlf. usage := usage, ' [iterations [processes [problemSize]]]', String crlf. usage := usage, String crlf. ^ usage! ! !SMarkHarness class methodsFor: 'helper'! usageReporter: usage ^ usage, ' reporter optional, a SMarkReporter class that processes', String crlf, ' and displays the results', String crlf. ! ! !SMarkHarness class methodsFor: 'helper'! usageRunner: usage ^ usage, ' runner optional, a SMarkRunner class that executes the benchmarks', String crlf.! ! !SMarkHarness class methodsFor: 'helper'! version (Smalltalk classNamed: #ConfigurationOfBenchmarking) ifNotNilDo: [:cfg | "Make sure Monticello is available, too" (Smalltalk classNamed: #MCHttpRepository) ifNotNil: [ ^ cfg project currentVersion versionNumber asString. ]. ]. (Smalltalk classNamed: #MCPackage) ifNotNilDo: [:mcp | | package | package := mcp named: 'SMark'. package hasWorkingCopy ifTrue: [ ^ package workingCopy ancestors first name. ]. ]. ^ ''.! ! !SMarkHarness class methodsFor: 'script entry'! run: arguments "Execcuted from the command line using something similar to ./vm my.image SMarkHarness SMarkRunner SMarkReporter SMarkLoops\>\>benchIntLoop 1 1 5 ./vm my.image SMarkHarness SMarkRunner SMarkReporter SMarkLoops.benchIntLoop 1 1 5" | runner reporter runnerAndReporter | (self shouldShowUsage: arguments) ifTrue: [ self usage. ^ self. ]. runnerAndReporter := self parseArguments: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self execute: runner andReport: reporter. ! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing' stamp: 'sm 5/25/2011 17:38'! determineBenchmarkParameters "Initialize with defaults, will be overwritten in case it is specified." iterations := runner class defaultNumberOfIterations. processes := runner class defaultNumberOfProcesses. problemSize:= suiteClass defaultProblemSize. self determineBenchmarkParametersFromArguments.! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing'! determineBenchmarkParametersFromArguments i := i + 1. i <= numParams ifTrue: [ iterations := (arguments at: i) asInteger. i := i + 1. i <= numParams ifTrue: [ processes := (arguments at: i) asInteger. i := i + 1. i <= numParams ifTrue: [ problemSize := arguments at: i. ] ] ].! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing'! determineReporter (currentObj isKindOf: SMarkReporter) ifFalse: [ reporter := harness defaultReporter new. ] ifTrue: [ reporter := currentObj. i := i + 1. i <= numParams ifTrue: [ current := arguments at: i. ] ].! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing'! determineRunner (currentObj isKindOf: SMarkRunner) ifFalse: [ runner := harness defaultRunner new. ] ifTrue: [ runner := currentObj. i := i + 1. i <= numParams ifTrue: [ current := arguments at: i. currentObj := (Smalltalk classNamed: current) ifNotNilDo: [:cls | cls new]. ] ].! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing' stamp: 'sm 5/25/2011 17:26'! determineSuiteOrBenchmark self parseBenchmarkOrSuite: current.! ! !SMarkHarnessArgumentParser methodsFor: 'argument parsing'! parseBenchmarkOrSuite: aBenchmarkOrSuite "Identify the benchmark suite or suite and benchmark method that should be executed. The string should be of the format 'Class>>benchName' or 'Class.benchName' for shell/bash compatibility. Accepts a string, class, or array. Returns, a class, or an array of a class and a symbol." | parsed | (aBenchmarkOrSuite isKindOf: Class) ifTrue: [ suiteClass := aBenchmarkOrSuite. ^ suiteClass ]. (aBenchmarkOrSuite isKindOf: Array) ifTrue: [ parsed := aBenchmarkOrSuite. ] ifFalse: [ parsed := aBenchmarkOrSuite findTokens: '>.'. ]. ((parsed size > 2) or: [parsed size < 1]) ifTrue: [ Error signal: 'The passed argument has to represent two elements. A class/classname and a method symbol' ]. suiteClass := parsed first. (suiteClass isKindOf: Class) ifFalse: [ suiteClass := Smalltalk at: (suiteClass asSymbol) ifAbsent: [Error signal: 'Class that was supposed to represent a benchmark suite was not found: ', suiteClass asString ]]. parsed size = 1 ifTrue: [^suiteClass]. specificBenchmark := parsed second asSymbol. ^ { suiteClass. specificBenchmark } ! ! !SMarkHarnessArgumentParser methodsFor: 'accessing'! harness: aHarness harness := aHarness! ! !SMarkHarnessArgumentParser methodsFor: 'parsing' stamp: 'sm 5/25/2011 17:27'! parse: argumentsArray arguments := argumentsArray. numParams := arguments size. i := 2. current := arguments at: i. currentObj := (Smalltalk classNamed: current) ifNotNilDo: [:cls | cls new]. self determineRunner. self determineReporter. self determineSuiteOrBenchmark. self determineBenchmarkParameters. self instructRunner. ^ {runner. reporter}! ! !SMarkHarnessArgumentParser methodsFor: 'helper' stamp: 'sm 5/25/2011 17:29'! instructRunner suite := suiteClass new. specificBenchmark ifNotNil: [ suite runOnly: specificBenchmark. ]. runner suite: suite. runner iterations: iterations. runner processes: processes. runner problemSize: problemSize.! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! setUp parser := SMarkHarnessArgumentParser new. parser harness: SMarkHarness.! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsOnlyBench | arguments runnerAndReporter runner reporter runOnly | arguments := {#ignored. 'SMarkTestSuite.benchA' }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner suite isKindOf: SMarkTestSuite). runOnly := runner suite selectedBenchmarks. self assert: 1 equals: runOnly size. self assert: (runOnly includes: #benchA). ! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsOnlySuite | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestSuite' }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. ! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsReporterSuiteIterations | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkSimpleStatisticsReporter'. 'SMarkTestSuite'. '13'. }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (reporter isKindOf: SMarkSimpleStatisticsReporter). self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations. ! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsRunnerReporterSuiteIterations | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestRunner'. 'SMarkSimpleStatisticsReporter'. 'SMarkTestSuite'. '13'. }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner isKindOf: SMarkTestRunner). self assert: (reporter isKindOf: SMarkSimpleStatisticsReporter). self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations.! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsRunnerSuiteIterations | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestRunner'. 'SMarkTestSuite'. '13'. }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner isKindOf: SMarkTestRunner). self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations.! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsSuiteAndIterations | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestSuite'. '13' }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations.! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsSuiteIterationsProcesses | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestSuite'. '13'. '91' }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations. self assert: 91 equals: runner processes. ! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseArgumentsSuiteIterationsProcessesProblemSize | arguments runnerAndReporter runner reporter | arguments := {#ignored. 'SMarkTestSuite'. '13'. '91'. 'SSS' }. runnerAndReporter := parser parse: arguments. runner := runnerAndReporter first. reporter := runnerAndReporter second. self assert: runner notNil. self assert: reporter notNil. self assert: (runner suite isKindOf: SMarkTestSuite). self assert: runner suite selectedBenchmarks isNil. self assert: 13 equals: runner iterations. self assert: 91 equals: runner processes. self assert: 'SSS' equals: runner problemSize. ! ! !SMarkHarnessArgumentParserTest methodsFor: 'as yet unclassified'! testParseBenchmarkOrSuite | example1 example2 example3 example4 example5 | example1 := 'String>>findTokens:'. example2 := 'SMarkTestSuite'. example3 := { SMarkTestSuite. #benchA }. example4 := SMarkTestSuite. example5 := 'String.findTokens:'. ". (dot) notation is required to avoid quoting in bash" self assert: { String. #findTokens: } equals: (parser parseBenchmarkOrSuite: example1). self assert: SMarkTestSuite equals: (parser parseBenchmarkOrSuite: example2). self assert: { SMarkTestSuite. #benchA } equals: (parser parseBenchmarkOrSuite: example3). self assert: SMarkTestSuite equals: (parser parseBenchmarkOrSuite: example4). self assert: { String. #findTokens: } equals: (parser parseBenchmarkOrSuite: example5). "What to do when the input is not a symbol, array, or class?" "What to do when the class does not exist" self should: [parser parseBenchmarkOrSuite: 'FooBarClassThatDoesNotExist'] raise: Error.! ! !SMarkHarnessClassTest methodsFor: 'tests'! testShouldShowUsage | example1 example2 example3 example4 | example1 := { #ignored. '--help' }. example2 := { #ignored. }. example3 := { #ignored. '-?'}. example4 := { #ignored. 1. 2. }. self assert: (SMarkHarness shouldShowUsage: example1). self assert: (SMarkHarness shouldShowUsage: example2). self assert: (SMarkHarness shouldShowUsage: example3). self deny: (SMarkHarness shouldShowUsage: example4). ! ! !SMarkLoops methodsFor: 'benchmarking'! benchFloatLoop | a | a := 1.23. [a < 50000] whileTrue: [ a := a + 0.6. a := a + 0.4. ].! ! !SMarkLoops methodsFor: 'benchmarking' stamp: 'StefanMarr 7/26/2011 11:46'! benchIntLoop | i | i := 25000. [i > 0] whileTrue: [ i := i - 1. ].! ! !SMarkReporter methodsFor: 'reporting'! benchmarkFooter: aName stream cr.! ! !SMarkReporter methodsFor: 'reporting'! benchmarkHeader: aName stream << 'Benchmark ' << (aName asString); cr.! ! !SMarkReporter methodsFor: 'reporting'! footer "No output at the moment" ^ self! ! !SMarkReporter methodsFor: 'reporting'! header | suiteName | suiteName := runner suite class name asString. stream << 'Report for: ' << suiteName; cr.! ! !SMarkReporter methodsFor: 'reporting'! reportAllRuns: aListOfResults of: benchmark aListOfResults do: [:result | result criteria keysAndValuesDo: [:benchName :timer | stream << benchName << ': ' << (timer totalTime asString, 'ms'); cr. ] ]! ! !SMarkReporter methodsFor: 'initialization'! initialize stream := self class defaultOutputDestination.! ! !SMarkReporter methodsFor: 'accessing'! outputStream: aStream stream := aStream ! ! !SMarkReporter methodsFor: 'accessing'! report self header. runner results keysAndValuesDo: [:key :value | self benchmarkHeader: key. self reportAllRuns: value of: key. self benchmarkFooter: key. ]. self footer. ^ self! ! !SMarkReporter methodsFor: 'accessing'! runner: aRunner runner := aRunner.! ! !SMarkReporter commentStamp: 'StefanMarr 3/20/2011 19:55' prior: 0! PBenchmarkReporter has not been documented yet. The class comment should describe the purpose of the class, its collaborations and its variables. Instance Variables: runner <PBenchmarkRunner> stream <NSDecoderDeflateStream | SocketStream | ThreadSafeTranscript | WriteStream> Example: f := TextStream on: String new. PBenchmarkSimpleStatisticsReporter reportFor: (PTestBenchmarkRunnerSuiteForAutosizing run: 10) on: f. f contents! !SMarkReporter class methodsFor: 'defaults'! defaultOutputDestination ^ ScriptConsole! ! !SMarkReporter class methodsFor: 'defaults'! defaultReporter ^ SMarkSimpleStatisticsReporter! ! !SMarkReporter class methodsFor: 'reporting'! reportFor: aRunner self reportFor: aRunner on: self defaultOutputDestination.! ! !SMarkReporter class methodsFor: 'reporting'! reportFor: aRunner on: aStream | reporter | reporter := self new. reporter runner: aRunner. reporter outputStream: aStream. reporter report. ^ reporter.! ! !SMarkReporterTest methodsFor: 'as yet unclassified'! setUp runner := SMarkTestRunnerSuiteForAutosizing run.! ! !SMarkReporterTest methodsFor: 'as yet unclassified'! testContentOfStream "Hm, how to test that robustly?" | reporter stream out | stream := TextStream on: String new. reporter := SMarkReporter reportFor: runner on: stream. out := stream contents. self assert: (out includesSubString: 'Small'). self assert: (out includesSubString: 'Big'). self assert: (out includesSubString: 'Small').! ! !SMarkReporterTest methodsFor: 'as yet unclassified'! testConvenienceReportOnRunner | stream out | stream := TextStream on: String new. "That should just work, cannot really check whether it is displayed anywhere." SMarkTestRunnerSuiteForAutosizing run report. "Check whether it reported as expected" SMarkTestRunnerSuiteForAutosizing run reportOn: stream. out := stream contents. self assert: (out includesSubString: 'Small'). self assert: (out includesSubString: 'Big'). self assert: (out includesSubString: 'Small').! ! !SMarkResult methodsFor: 'accessing'! benchmarkName ^ benchName! ! !SMarkResult methodsFor: 'accessing'! benchmarkName: aString benchName := aString! ! !SMarkResult methodsFor: 'accessing'! criteria ^ criteria! ! !SMarkResult methodsFor: 'accessing'! criteria: aCollectionOfTimers criteria := aCollectionOfTimers! ! !SMarkResult methodsFor: 'accessing'! suite ^ suite! ! !SMarkResult methodsFor: 'accessing'! suite: aBenchmarkSuite suite := aBenchmarkSuite! ! !SMarkResult methodsFor: 'accessing'! total ^ time! ! !SMarkResult methodsFor: 'accessing'! total: aTime time := aTime! ! !SMarkResult commentStamp: 'StefanMarr 3/18/2011 23:45' prior: 0! A benchmark result is characterized by: - the total execution time (#total is the least a benchmark results in) - the name of the benchmark that was executed - the suite object specifies the used input used for the benchmark - dictionary of additional the criteria and the related timings A benchmark can produced multiple resuts for different criteria. The standard criterion is #total.! !SMarkResultTest methodsFor: 'as yet unclassified'! setUp | runner | runner := SMarkTestRunner execute: SMarkTestRunnerSuite new. result := (runner results at: #DoNothing) at: 1.! ! !SMarkResultTest methodsFor: 'as yet unclassified'! testBenchmarkName self assert: (result benchmarkName isKindOf: String)! ! !SMarkResultTest methodsFor: 'as yet unclassified'! testCriteria self assert: (result criteria respondsTo: #at:). self assert: (result criteria size > 0).! ! !SMarkResultTest methodsFor: 'as yet unclassified'! testSuite self assert: result suite notNil! ! !SMarkResultTest methodsFor: 'as yet unclassified'! testTotal self assert: (result total isKindOf: Number)! ! !SMarkResultTest commentStamp: 'StefanMarr 3/18/2011 23:29' prior: 0! This test specifies the data stored in a result object. The result object does not actually provide behavior on its own.! !SMarkRunner methodsFor: 'helper' stamp: 'StefanMarr 3/20/2011 10:28'! createTimer: name "Create and register a new timer for the current benchmark" | timer | timer := self class defaultTimer new: name. timers ifNotNil: [ timers at: name put: timer. ]. ^ timer.! ! !SMarkRunner methodsFor: 'helper' stamp: 'StefanMarr 3/20/2011 21:01'! recordResults: timer for: aSelector | result name | name := suite benchmarkNameForSelector: aSelector. result := SMarkResult new. result total: timer totalTime. result benchmarkName: name. result suite: suite. result criteria: timers. (results at: name ifAbsentPut: OrderedCollection new) add: result.! ! !SMarkRunner methodsFor: 'execution' stamp: 'StefanMarr 3/13/2011 23:05'! execute suite run. self runBaseBenchmark. ^ results ! ! !SMarkRunner methodsFor: 'initialization' stamp: 'StefanMarr 5/14/2011 11:10'! initialize super initialize. numIterations := self class defaultNumberOfIterations. numProcesses := self class defaultNumberOfProcesses. results := Dictionary new.! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/21/2011 12:20'! iterations ^ numIterations! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/21/2011 12:20'! iterations: anInteger numIterations := anInteger! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 4/15/2011 16:08'! problemSize ^ problemSize! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 4/15/2011 16:09'! problemSize: aValue problemSize := aValue! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 5/14/2011 11:08'! processes "The standard runner does use only a single process, but in case a benchmark supports parallelism it can query for the intended degree of parallelism" ^ numProcesses! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 5/14/2011 11:08'! processes: anInt "The standard runner does use only a single process, but a benchmark can use that to do its own parallelism" numProcesses := anInt! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 4/15/2011 16:46'! report SMarkReporter defaultReporter reportFor: self. ! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/18/2011 19:41'! results ^ results! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 3/20/2011 18:45'! suite ^ suite! ! !SMarkRunner methodsFor: 'accessing' stamp: 'StefanMarr 4/15/2011 16:14'! suite: aBenchmarkSuite suite := aBenchmarkSuite. suite runner: self.! ! !SMarkRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 4/15/2011 11:50'! performBenchmark: aSelector currentBenchmark := aSelector. 1 to: numIterations do: [:i| "self timedBenchmarkExecution: aSelector." suite runBenchmark: aSelector. ]. currentBenchmark := nil. ^ results at: (suite benchmarkNameForSelector: aSelector)! ! !SMarkRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 3/18/2011 18:42'! runBaseBenchmark "In certain sitatuations it is one wants a baseline that is incooprated in all benchmark results to be substracted from the final values. #baseBenchmark can be used to charaterize such a baseline" (suite respondsTo: #baseBenchmark) ifFalse: [ ^ nil ]. ^ self performBenchmark: #baseBenchmark.! ! !SMarkRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 3/19/2011 22:08'! timedBenchmarkExecution: aSelector "Will do a timed execution of the benchmark and return the result timer" | timer | timers := Dictionary new. timer := self createTimer: 'total'. timer start. suite perform: aSelector. timer stop. self recordResults: timer for: aSelector. ^ timer! ! !SMarkRunner methodsFor: 'reporting' stamp: 'sm 5/25/2011 17:50'! reportConfiguration: aStream aStream << 'Runner Configuration:';cr. aStream << (' iterations: ', numIterations asString); cr. aStream << (' processes: ', numProcesses asString); cr. aStream << (' problem size: ', problemSize asString); cr. ! ! !SMarkRunner methodsFor: 'reporting' stamp: 'StefanMarr 4/15/2011 16:47'! reportOn: aStream SMarkReporter defaultReporter reportFor: self on: aStream ! ! !SMarkRunner class methodsFor: 'defaults' stamp: 'StefanMarr 3/21/2011 11:43'! defaultNumberOfIterations ^ 1! ! !SMarkRunner class methodsFor: 'defaults' stamp: 'StefanMarr 5/14/2011 11:09'! defaultNumberOfProcesses ^ 1! ! !SMarkRunner class methodsFor: 'defaults' stamp: 'StefanMarr 3/20/2011 20:56'! defaultTimer ^ SMarkTimer! ! !SMarkRunner class methodsFor: 'benchmarking' stamp: 'StefanMarr 3/20/2011 19:51'! execute: aSuite ^ self execute: aSuite with: 1.! ! !SMarkRunner class methodsFor: 'benchmarking' stamp: 'StefanMarr 3/20/2011 19:51'! execute: aSuite with: nIterations | runner | runner := self new. aSuite runner: runner. runner suite: aSuite. runner iterations: nIterations. runner execute. ^ runner! ! !SMarkRunner class methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 00:42'! execute: aSuite with: nIterations for: aProblemSize | runner | runner := self new. aSuite runner: runner. runner suite: aSuite. runner iterations: nIterations. runner problemSize: aProblemSize. runner execute. ^ runner! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! runnerClass ^ SMarkTestRunner! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testBaseBenchmark "Ensure the base benchmark is executed when available" | runner | runner := self runnerClass execute: SMarkTestSuiteWithBaseBenchmark new. self assert: runner baseBenchmarkExecuted ! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testBaseBenchmarkNone "Ensure that not having a base benchmark does not pose a problem" | runner | runner := self runnerClass execute: SMarkTestSuite new. self deny: runner baseBenchmarkExecuted ! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testBenchmarkWithMultipleCriteraTimers "Check whether the benchmark benchWithMultipleCriteria, really results in different unrelated timings" | runner result | runner := self runnerClass execute: SMarkTestSuite new. result := (runner results at: #WithMultipleCriteria) at: 1. self assert: (result isKindOf: SMarkResult). self assert: result benchmarkName equals: #WithMultipleCriteria. self assert: (result total >= 50). self assert: (result criteria notNil). self assert: (result criteria respondsTo: #at:). self assert: ((result criteria at: 't1') totalTime >= 10). self assert: ((result criteria at: 't2') totalTime >= 25). self assert: ((result criteria at: 't3') totalTime >= 50). ! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testClassExecute | runner | runner := self runnerClass execute: SMarkTestSuiteWithBaseBenchmark new. self assert: (runner isKindOf: self runnerClass).! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testExecute "Ensure all benchmarks are run, including the baseBenchmark and the results are returned" | runner results performedBenchmarks | runner := self runnerClass new. runner suite: SMarkTestRunnerSuiteForPerfromBenchmark new. results := runner execute. performedBenchmarks := runner performedBenchmarks. self assert: 5 equals: performedBenchmarks size. self assert: (performedBenchmarks includes: #baseBenchmark). self assert: (results respondsTo: #at:). self assert: (((results at: #baseBenchmark) at: 1) isKindOf: SMarkResult).! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testIterations | runner | " simple scenario should default to 1 run for now " runner := self runnerClass execute: SMarkTestRunnerSuite new. self assert: runner countWasExecuted equals: 1. " but we can also be more fancy and set the number of iterations " runner := self runnerClass new. runner suite: SMarkTestRunnerSuite new. "first check again that the default is as expected" self assert: runner iterations equals: 1. runner iterations: 10. self assert: 10 equals: runner iterations. runner execute. self assert: 10 equals: runner countWasExecuted.! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testPerformBenchmark "Ensure that performBenchmark executes all the defined #bench methods, but for instance not #Bench" | runner performedBenchmarks | runner := self runnerClass execute: SMarkTestRunnerSuiteForPerfromBenchmark new. performedBenchmarks := runner performedBenchmarks. self assert: (performedBenchmarks includes: #benchAfsdfsdfsdf). self assert: (performedBenchmarks includes: #benchBsdfasereSDSfsdfsdfs). self assert: (performedBenchmarks includes: #benchC). self assert: (performedBenchmarks includes: #benchZZ). self deny: (performedBenchmarks includes: #BenchShouldNotBeExecuted).! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testResultStructure | runner results resultA resultB suite | suite := SMarkTestSuite new. runner := self runnerClass execute: suite. results := runner results. "Don't care whether it is a dictionary, but at least it should present us something that maps benchmark names to result objects" self assert: (results respondsTo: #at:). resultA := (results at: #A) at: 1. resultB := (results at: #B) at: 1. self assert: (resultA isKindOf: SMarkResult). self assert: (resultB isKindOf: SMarkResult). self assert: (((results at: #C) at: 1) isKindOf: SMarkResult). "Make sure some properties of the result objects is ensured" self assert: resultA total > 0. self assert: #A equals: resultA benchmarkName. self assert: suite equals: resultA suite. self assert: 1 equals: resultA criteria size. self assert: resultB total > 0. self assert: #B equals: resultB benchmarkName. self assert: suite equals: resultB suite. self assert: 1 equals: resultB criteria size. "Testing for multi-criteria results somewhere else"! ! !SMarkRunnerTest methodsFor: 'as yet unclassified'! testTimer "Simple test whether a timer is created and it is from the expected class. This test is very basic, other tests like testBenchmarkWithMultipleCirteria* need to cover the rest" | runner timer | runner := self runnerClass new. timer := runner createTimer: #foo. self assert: timer name equals: #foo. self assert: (timer isKindOf: self runnerClass defaultTimer). ! ! !SMarkSimpleStatisticsReporter methodsFor: 'statistics' stamp: 'StefanMarr 3/20/2011 12:05'! confidenceVariance: times | numMeasurements | numMeasurements := times size. (numMeasurements >= 30) ifTrue: [ ^ (self gaussianConfidenceFactor) * (times stdev) / (numMeasurements asFloat sqrt)]. "use the students T distribution for small probe counts" ^ (self studentsTConfidenceFactorFor: numMeasurements) * (times stdev) / (numMeasurements asFloat sqrt)! ! !SMarkSimpleStatisticsReporter methodsFor: 'statistics' stamp: 'StefanMarr 3/20/2011 11:49'! gaussianConfidenceFactor "used for large probe counts >= 30" "1 ~ 68.27%" "1.644853626951 ~ 90%" "2 ~ 95.45%" ^ 1.644853626951! ! !SMarkSimpleStatisticsReporter methodsFor: 'statistics' stamp: 'StefanMarr 3/20/2011 11:46'! significantDigits: confidenceVariance confidenceVariance = 0 ifTrue: [ ^ 2]. confidenceVariance >= 10 ifTrue: [ ^ 0]. ^ 1 - (confidenceVariance log floor)! ! !SMarkSimpleStatisticsReporter methodsFor: 'statistics' stamp: 'StefanMarr 3/20/2011 12:03'! studentsTConfidenceFactorFor: aNumberOfMeasurements "used for small probe counts < 30" "the students T distribution sucks to calculate since the value depends on the probeCout" "these values are for a confidence interval of ~90%" | values | values := Array new: 30. values at: 1 put: 6.314. values at: 2 put: 2.920. values at: 3 put: 2.353. values at: 4 put: 2.132. values at: 5 put: 2.015. values at: 6 put: 1.943. values at: 7 put: 1.895. values at: 8 put: 1.860. values at: 9 put: 1.833. values at: 10 put: 1.812. values at: 11 put: 1.796. values at: 12 put: 1.782. values at: 13 put: 1.771. values at: 14 put: 1.761. values at: 15 put: 1.753. values at: 16 put: 1.746. values at: 17 put: 1.740. values at: 18 put: 1.734. values at: 19 put: 1.729. values at: 20 put: 1.725. values at: 21 put: 1.721. values at: 22 put: 1.717. values at: 23 put: 1.714. values at: 24 put: 1.711. values at: 25 put: 1.708. values at: 26 put: 1.706. values at: 27 put: 1.703. values at: 28 put: 1.701. values at: 29 put: 1.699. values at: 30 put: 1.697. ^ values at: aNumberOfMeasurements. ! ! !SMarkSimpleStatisticsReporter methodsFor: 'reporting' stamp: 'StefanMarr 5/16/2011 16:08'! reportAllRuns: aListOfResults of: benchmark | criteria | criteria := aListOfResults first criteria. criteria keysDo: [:criterion | | times | times := self resultsFor: criterion from: aListOfResults. self reportResult: times for: criterion of: benchmark. stream cr. ].! ! !SMarkSimpleStatisticsReporter methodsFor: 'reporting' stamp: 'StefanMarr 5/16/2011 15:54'! reportResult: anArrayOfResults for: aCriterion of: benchmark | convidenceVariance significantDigits quantum total stdev totalSignificantDigits outputLine | outputLine := benchmark, ' ', aCriterion, ': iterations=', anArrayOfResults size asString, ' runtime: '. anArrayOfResults size < 2 ifTrue: [ total := anArrayOfResults average printString. outputLine := outputLine, total, 'ms'. stream << outputLine. ^ self. ]. convidenceVariance := self confidenceVariance: anArrayOfResults. "only print significant " significantDigits := self significantDigits: convidenceVariance. quantum := (1/10 asFloat) raisedTo: significantDigits. "round to significantDigits" stdev := convidenceVariance roundTo: quantum. total := (anArrayOfResults average roundTo: quantum) printString. totalSignificantDigits := total size - (total indexOf: $.). outputLine := outputLine, total. "check if the last digit is 0 => padding" (totalSignificantDigits < significantDigits) ifTrue: [ (significantDigits - totalSignificantDigits) timesRepeat: [ outputLine := outputLine, '0']]. outputLine := outputLine, 'ms'. stream << outputLine. stream << ' +/-' << stdev.! ! !SMarkSimpleStatisticsReporter methodsFor: 'helper' stamp: 'StefanMarr 5/16/2011 16:02'! resultsFor: aCriterion from: aListOfResults ^aListOfResults collect: [:result | (result criteria at: aCriterion) totalTime] ! ! !SMarkSimpleStatisticsReporter methodsFor: 'helper' stamp: 'StefanMarr 3/20/2011 19:40'! totalResultsFor: aListOfResults ^aListOfResults collect: [:timer | timer total] ! ! !SMarkSlopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 15:08'! OLDERbenchStone "modified by nishis" "STEFAN: this version includes the original reporting, and is not used by SMark Only containted for historical purposes." | n nTests iters times speeds stones scale printA printB printC param count speed0 expln block time iter speed stone geoMean gm power | n := self problemSize. "Number of times each test block will be evaluated." n > SmallInteger maxVal ifTrue: [ self error: 'Count exceeded max small int.' ]. nTests := testParams size. nTests = testBlocks size ifFalse: [ self error: 'Inconsistent test count.' ]. iters := OrderedCollection new. times := OrderedCollection new. speeds := OrderedCollection new. stones := OrderedCollection new. scale := 1000. "So iterations can be reported as 1000s of iterations" "The following blocks are restricted to two args by ST/V-DOS." printA := [ :t1 :t2 | "[:iter1 :time1 |" output cr. output nextPutAll: (t1 / scale) rounded printString. output nextPutAll: ' '. output nextPutAll: t2 printString. output nextPutAll: ' ' ] copy fixTemps. printB := [ :t1 :t2 | "[:speed1 :slop1 |" output nextPutAll: (t1 / scale) rounded printString. output nextPutAll: ' '. output nextPutAll: t2 printString. output nextPutAll: ' ' ] copy fixTemps. printC := [ :t1 | ":expln1 |" output nextPutAll: t1 ] copy fixTemps. output nextPutAll: ' 1000s time 1000s of itera- sec- iterations slop- tions onds per sec stones explanation '. 1 to: nTests do: [ :i | param := testParams at: i. count := param at: 1. "repetitions of a test inside its block" speed0 := (param at: 2) * scale. "iters/sec for a one-slopstone machine" expln := param at: 3. block := (testBlocks at: i) copy fixTemps. time := Time millisecondsToRun: [ n timesRepeat: block ]. time := (time max: 1) / 1000.0. "time is now in seconds" iter := count * n. speed := iter / time. stone := speed / speed0. iters add: iter. times add: time. speeds add: speed. stones add: stone. printA value: iter value: time. printB value: speed value: stone. printC value: expln ]. geoMean := [ :t1 | "[:numbers |" gm := 1. power := 1 / nTests. "t2 as number" t1 do: [ :t2 | gm := gm * (t2 raisedTo: power) ]. gm ] copy fixTemps. output cr. printA value: (geoMean value: iters) value: (geoMean value: times). printB value: (geoMean value: speeds) value: (geoMean value: stones). printC value: 'geometric mean'. output cr; cr; nextPutAll: 'Benchmarks complete.'; cr! ! !SMarkSlopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 15:11'! benchStone "modified by nishis" | n nTests iters times speeds stones scale param count speed0 block time iter speed stone | n := self problemSize. "Number of times each test block will be evaluated." n > SmallInteger maxVal ifTrue: [ self error: 'Count exceeded max small int.' ]. nTests := testParams size. nTests = testBlocks size ifFalse: [ self error: 'Inconsistent test count.' ]. iters := OrderedCollection new. times := OrderedCollection new. speeds := OrderedCollection new. stones := OrderedCollection new. scale := 1000. "So iterations can be reported as 1000s of iterations" "The following blocks are restricted to two args by ST/V-DOS." 1 to: nTests do: [ :i | param := testParams at: i. count := param at: 1. "repetitions of a test inside its block" speed0 := (param at: 2) * scale. "iters/sec for a one-slopstone machine" block := (testBlocks at: i) copy fixTemps. time := Time millisecondsToRun: [ n timesRepeat: block ]. time := (time max: 1) / 1000.0. "time is now in seconds" iter := count * n. speed := iter / time. stone := speed / speed0. iters add: iter. times add: time. speeds add: speed. stones add: stone. ].! ! !SMarkSlopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 00:54'! problemSize | ps | ps := super problemSize. ps := ps asInteger. ps ifNil: [ ^ self defaultProblemSize]. ^ ps! ! !SMarkSlopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:33'! readme "INTRODUCTION Slopstone: Smalltalk Low level OPeration Stones Portable Low Level Benchmarks for ST80 and ST/V (using 16-bit SmallIntegers) Placed in public domain January 1993 (c) Bruce Samuelson Permission is given to place this in public Smalltalk archives Use monospaced fonts if possible to view the methods in this class. (1) Collect garbage if supported (2) do 'SlopstoneBenchmark new runBenchmark'. Results are printed in the Transcript window. Post results for your machines to comp.lang.smalltalk or mail them to bruce@ling.uta.edu or bruce@utafll.uta.edu. DISCUSSION This readme method would normally be in the class comment for ST80. ST/V-DOS doesn't support class comments. The benchmarks test strictly low level operations. They do not test higher level operations such as forming sets, sorting, or streaming, nor do they test applications. They also do not test user interface operations because of the non-portability of this area of Smalltalk and its sensitivity to the performance of the video subsystem. The tests are cpu bound. They do not access files and should not cause disk paging. The benchmarks use loop counts of 16000 because SmallIntegers cannot exceed 16383 for ST/V-DOS. 16-bit implementions would perform worse with large loop counts. The benchmarks are also suitable for testing 32-bit versions of Smalltalk. DEFINITION OF REFERENCE MACHINE (ONE SLOPSTONE) The following machine is the one on which I developed these benchmarks. By convention it is defined to operate at one slopstone. It's a mid range performer for current ParcPlace versions of Smalltalk. Hardware: Amax 486DX/33 (includes internal floating point processor and internal 8K cache), 256K external cache, 16MB RAM. Software: ParcPlace VisualWorks 1.0, Windows 3.1, DOS 5.0 (plain vanilla setup). COMPARISON TO XEROX DORADO For reference, the machine runs at 649% of a Dorado on ParcPlace benchmarks for ST80 4.1. Its fast video card helps on these PPS benchmarks. I didn't run them for VisualWorks 1.0. It would be somewhat slower because there are vastly more classes. EXAMPLE RESULTS FOR REFERENCE MACHINE 1000s time 1000s of itera- sec- iterations slop- tions onds per sec stones explanation 3808 0.577 6600 1.0 add integers 544 2.262 240 1.0 add floats 960 1.088 882 1.0 access strings 320 0.908 352 1.0 create objects 160 1.49 107 1.0 copy objects 480 1.129 425 1.0 perform selectors 896 1.237 724 1.0 evaluate blocks 640 1.151 555 1.0 geometric mean" ^ self! ! !SMarkSlopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 01:33'! setUp "Numbers in testParams represent the following: Column 1 number of internal repetitions for each test inside its block Column 2 thousands of iterations per second for a one-slopstone machine." output := TextStream with: String new. testParams := OrderedCollection new. testParams add: #(238 6600 'add integers'); add: #( 34 240 'add floats'); add: #( 60 882 'access strings'); add: #( 20 352 'create objects'); add: #( 10 107 'copy objects'); add: #( 30 425 'perform selectors'); add: #( 56 724 'evaluate blocks'). testBlocks := OrderedCollection new. "In the integer addition test, I originally had 340 internal repetitions. This caused the Digitalk compiler to blow up. The ParcPlace compiler compiled it ok but interestingly addition performed at slightly more than 50% of the performance with an internal count of 238. Perhaps something magical happens at 256." testBlocks add: [1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+ 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1]; add: [1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+ 1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0+1.0]; add: ['a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1. 'a' at: 1]; add: [Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new. Object new]; add: [Object new copy copy copy copy copy copy copy copy copy copy]; add: [0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself. 0 perform: #yourself]; add: [[] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value. [] value]! ! !SMarkSlopstone methodsFor: 'defaults'! defaultProblemSize ^ 1! ! !SMarkSlopstone commentStamp: 'nishis 2/21/98 06:26' prior: 0! modified for Squeak by nishis@urban.ne.jp I added one class methods. and modified execute method. block variables are renamed for Squeak. Thanx to Mr. Tim Olson, Mr. Kohler Markus, Mr. Tim Rowledge, Mr. John Maloney, Mr. Ian Piumarta. original comments NAME STones80 AUTHOR bruce@utafll.uta.edu (Bruce Samuelson) FUNCTION low and medium level benchmarks for ST80 and ST/V ST-VERSIONS pre R4.0, R4.0, R4.1, ST/V PREREQUISITES need floating point hardware or emulation CONFLICTS none DISTRIBUTION world VERSION 1.0 DATE April 16, 1993 SUMMARY The filein includes two classes: Slopstones (Smalltalk Low level OPeration Stones) and Smopstones (Smalltalk Medium level OPeration Stones). Each includes seven cpu intensive benchmarks. They work equally well with 16-bit and 32-bit implementations and are designed to be portable to all Smalltalk versions from ParcPlace and Digitalk. They are normalized to the author's 486/33 Windows 3.1 machine running ParcPlace VisualWorks 1.0. Results have been posted to the Usenet group comp.lang.smalltalk and form the basis of an article that is scheduled to be published in the June issue of The Smalltalk Report. The only difference between the ST80 (STones80) and ST/V (STonesV) filein is in the messages that define the classes in the first few lines of code. The ST80 messages specify the class category and message protocol, which are not used in ST/V. Bruce Samuelson ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 15:08'! OLDERbenchStone "modified by nishis" "STEFAN: this version includes the original reporting, and is not used by SMark Only containted for historical purposes." | n nTests times stones printA printC param time0 expln block time stone geoMean gm power | n := self problemSize. "Each test is repeated this many times. The smopstone times in the test parameters are normalized to a value of one. You may set it to a higher number if your machine is really blazing." output cr; cr; nextPutAll: 'Starting benchmarks with repetition count = ' , n printString , '.'. nTests := testParams size. nTests = testBlocks size ifFalse: [ self error: 'Inconsistent test count.' ]. times := OrderedCollection new. stones := OrderedCollection new. "The following blocks are restricted to two args by ST/V-DOS." printA := [ :time1 :smop1 | output cr. output nextPutAll: time1 printString. output nextPutAll: ' '. output nextPutAll: smop1 printString. output nextPutAll: ' ' ] copy fixTemps.. printC := [ :expln1 | output nextPutAll: expln1 ] copy fixTemps.. output nextPutAll: ' time in smop- seconds stones explanation '. 1 to: nTests do: [ :i | param := testParams at: i. time0 := param at: 1. "seconds for one-smopstone machine" expln := param at: 2. block := (testBlocks at: i) copy fixTemps. time := Time millisecondsToRun: [ n timesRepeat: block ]. time := (time max: 1) / 1000.0. "time is now in seconds" stone := n * time0 / time. times add: time. stones add: stone. printA value: time value: stone. printC value: expln ]. geoMean := [ :numbers | gm := 1. power := 1 / nTests. numbers do: [ :number | gm := gm * (number raisedTo: power) ]. gm ] copy fixTemps. output cr. printA value: (geoMean value: times) value: (geoMean value: stones). printC value: 'geometric mean'. IsSupportRecursiveBlock ifFalse: [ output nextPutAll: '*' ]. output cr; cr; nextPutAll: 'Benchmarks complete.'; cr. IsSupportRecursiveBlock ifFalse: [ output cr; nextPutAll: '*** Caution *** 2 test of this benchmark (marked at ''*'') is intended to test the efficiency of recursively calling a block, that it isn''t supported by this VM. So the result would be fairly pointless.'; cr ]! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/26/2011 11:45'! benchStone "modified by nishis" | n primes strings set | n := self problemSize. "Each test is repeated this many times. The smopstone times in the test parameters are normalized to a value of one. You may set it to a higher number if your machine is really blazing." 1 to: n do: [ :i | self fractonacci: 13/2. primes := self primesUpTo: 4000. self streamTestsOn: primes. strings := self stringsUpTo: 3000. set := self setFrom: strings. self sort: set. self sorcerersApprentice. ].! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:47'! fractonacci: n "Return something like the fibonacci function of n but using fractional numbers rather than whole ones. The reason for this variation is to run long enough to get a decent time measurement without exceeding 16383, the limit of small integers for ST/V-DOS. Choosing n = 13/2 takes enough time and computes to 13581. Fibonacci uses n-1 and n-2 instead of n-(1/2) and n-(1/3). However, I couldn't get it to run in the above constraints. This benchmark tests the efficiency of recursively calling a method that does a little fractional arithmetic internally." ^n > 1 ifTrue: [(self fractonacci: n - (1/2)) + (self fractonacci: n - (1/3))] ifFalse: [1]! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 01:27'! primesUpTo: n "modified by nishis" "Return the prime numbers between 2 and n. This method tests the efficiency of recursively calling a block that does some collection enumeration based on integer arithmetic." | nSqrt lowPrimes highPrimes genNext first nextPrime2 | n < 5 | (n > 16363) ifTrue: [self error: 'Prime limit(s) out of range.']. nSqrt := n sqrt rounded. lowPrimes := OrderedCollection with: 2. highPrimes := 5 to: n by: 2. IsSupportRecursiveBlock ifTrue: [genNext := [:nextPrime | lowPrimes add: nextPrime. highPrimes := highPrimes select: [:k | k \\ nextPrime ~= 0] copy fixTemps. (first := highPrimes first) <= nSqrt ifTrue: [genNext value: first]]. genNext value: 3.] ifFalse: [first := highPrimes first. nextPrime2 := 3. [first <= nSqrt] whileTrue: [lowPrimes add: nextPrime2. highPrimes := highPrimes select: [:k | k \\ nextPrime2 ~= 0]. (first := highPrimes first) <= nSqrt ifTrue: [nextPrime2 := first]]]. ^lowPrimes , highPrimes! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 00:54'! problemSize | ps | ps := super problemSize. ps := ps asInteger. ps ifNil: [ ^ self defaultProblemSize]. ^ ps! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:46'! readme "INTRODUCTION Smopstone: Smalltalk Medium level OPeration Stones Portable Medium level Benchmarks for ST80 and ST/V (using 16-bit SmallInts) Placed in public domain January 1993 (c) Bruce Samuelson Permission is given to place this in public Smalltalk archives Use monospaced fonts if possible to view the methods in this class. (1) Collect garbage if supported (2) do 'SmopstoneBenchmark new runBenchmark'. Results are printed in the Transcript window. Post results for your machines to comp.lang.smalltalk or mail them to bruce@ling.uta.edu or bruce@utafll.uta.edu. DISCUSSION This readme method would normally be in the class comment for ST80. ST/V-DOS doesn't support class comments. These benchmarks are a companion to the SlopstoneBenchmark class posted to comp.lang.smalltalk this month. Slopstones tested low level operations. Smopstones test medium level operations that exercise recursive block and method calls, collection building and enumeration, streaming, and sorting. The lower level operations contained in them exercise arithmetic (mostly integer, with some fractions and floats) string manipulation, and low level streaming. The benchmarks do not test applications. They also do not test user interface performance because of the non-portability of this area of Smalltalk and its sensitivity to the speed of the video subsystem. The tests are cpu bound. They do not access files and should not cause disk paging. The main weaknesses of the benchmarks are (1) they are not high enough level to test actual applications, and (2) they concentrate in too few areas of Smalltalk, omitting many of the diverse capabilities of its class library. My excuse is that one can only devote limited time writing public domain benchmarks. The tests avoid generating integers larger than 16383, the maximum SmallInteger in ST/V-DOS. 16-bit implementions would perform worse with larger integers. The benchmarks are also suitable for testing 32-bit versions of Smalltalk. They try to avoid other pitfalls that would skew the results such as the lack of an adequate hash function for a class. Someone warned of this in comp.lang.smalltalk (I forget who). DEFINITION OF REFERENCE MACHINE (ONE SMOPSTONE) The following machine is the one on which I developed these benchmarks. By convention it is defined to operate at one smopstone. It's a mid range performer for current ParcPlace versions of Smalltalk. Hardware: Amax 486DX/33 (includes internal floating point processor and internal 8K cache), 256K external cache, 16MB RAM. Software: ParcPlace VisualWorks 1.0, Windows 3.1, DOS 5.0 (plain vanilla setup). COMPARISON TO XEROX DORADO For reference, the machine runs at 649% of a Dorado on ParcPlace benchmarks for ST80 4.1. Its fast video card helps on these PPS benchmarks. I didn't run them for VisualWorks 1.0. It would be somewhat slower because there are vastly more classes. EXAMPLE RESULTS FOR REFERENCE MACHINE time in smop- seconds stones explanation 3.157 1.0 generating fractonaccis 1.123 1.0 generating primes 1.091 1.0 generating and parsing streams 3.091 1.0 generating strings 1.167 1.0 forming sets 5.139 1.0 sorting strings 5.601 1.0 sorcerer's apprentice 2.355 1.0 geometric mean" ^ self! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:46'! setFrom: collection "Form a set from collection and return it. This method tests the efficiency of building a fairly large set from strings. It indirectly tests the effectiveness of the string hash function. Strings are used often enough as dictionary keys that this may be worth including in the benchmark suite. ST/V-DOS has a primitive hash for strings, and ST80 has an elaborate one written in Smalltalk." ^collection asSet! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 01:41'! setUp "modified by nishis" "Numbers in testParams represent the approximate number of seconds it takes to run the tests for a one-smopstone machine. Numbers in testBlocks are parameters tuned for each test. Do not change them. The times for several tests depend on them non-linearly." | primes strings set | output := TextStream with: String new. testParams := OrderedCollection new. IsSupportRecursiveBlock ifTrue: [testParams add: #(3.157 'generating fractonaccis'); add: #(1.123 'generating primes'); add: #(1.091 'generating and parsing streams'); add: #(3.091 'generating strings'); add: #(1.167 'forming sets'); add: #(5.139 'sorting strings'); add: #(5.601 'sorcerer''s apprentice')] ifFalse: [testParams add: #(3.157 'generating fractonaccis'); add: #(1.123 'generating primes*'); add: #(1.091 'generating and parsing streams'); add: #(3.091 'generating strings'); add: #(1.167 'forming sets'); add: #(5.139 'sorting strings'); add: #(5.601 'sorcerer''s apprentice*')]. testBlocks := OrderedCollection new. primes := self primesUpTo: 9000. strings := self stringsUpTo: 8000. set := self setFrom: strings. testBlocks add: [self fractonacci: 13/2]; add: [self primesUpTo: 9000]; "7351 - 1" add: [self streamTestsOn: primes]; add: [self stringsUpTo: 8000]; add: [self setFrom: strings]; add: [self sort: set]; add: [self sorcerersApprentice]! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 01:42'! sorcerersApprentice "modified by nishis" " FORMATTED FOR MONOSPACED FONT Perform various operations on rectangles. This method tests the efficiency of recursively calling a block that includes lots of integer arithmetic, collection building, and collection enumeration. The method: (1) Creates a collection of pseudo random rectangles (2) Forms a new collection of all their intersections (3) Recursively continues until there are no more intersections (4) Returns a collection with the counts of rectangles in each generation. Because the intersections are forming progressively smaller rectangles (we exclude intersections of a rectangle with itself), the algorithm will eventually converge. Depending on the choice of numeric parameters, it may converge very quickly or very slowly. The parameters used below make it converge in a reasonable amount of time (a few seconds on a one-smopstone machine). It took some experimentation with different combinations to achieve this. The pseudo random number generator isn't very good, but it's adequate for this benchmark. I had intended the number '87' it uses to be a prime, but 87 = 29 * 3. The numbers may have been a bit more random otherwise. One could write an algorithm that would converge much more quickly and in a more predictable amount of time by sorting the intermediate rectangles in two dimensions and not bothering to test for intersections those rectangles that are contained in mutually exclusive regions. We have chosen algorithmic simplicity over performance optimization. We simply perform intersections of each rectangle with every possible partner in each generation. The time consumed is quadratic in the number of rectangles. The algorithm originally stored rectangles in sets to eliminate duplicates. Unfortunately, ST/V-DOS uses the hash function inherited from Object for Rectangle, which will allow duplicates to be stored. So we were forced to store rectangles in ordered collections and eliminate duplicates by brute force. The brutality was heightened because we could not use the test collection>>includes: to decide whether to add a rectangle to the ordered collections, since ST/V-DOS does not define equality (=) for rectangles either. The remaining warts in the code are not worth explaining. In an actual application, these shortcomings of ST/V-DOS would have been overcome by adding subclasses and methods rather than writing kludgy code." | m n firstGen intersection isIncluded counts r random a b c d e f g h generate nextGen | m := 80. n := 20 * m. firstGen := OrderedCollection new. counts := OrderedCollection new. r := 50. random := [r := r + 1 * 87 \\ n] copy fixTemps. 1 to: m do: [:i| a := random value. b := random value. c := random value. d := random value. e := a min: b. f := c min: d. g := a max: b. h := c max: d. firstGen add: (Rectangle origin: e @ f corner: g @ h)]. generate := [:lastGen | counts add: lastGen size. nextGen := OrderedCollection new. lastGen do: [:r1 | lastGen do: [:r2 | (r1 origin ~= r2 origin or: [r1 corner ~= r2 corner]) "In ST80 this test would have simply been r1 ~= r2" ifTrue: [(r1 intersects: r2) ifTrue: [intersection := r1 intersect: r2. isIncluded := false. "All these lines" nextGen do: "would have been" [:rec | "avoided if we" (rec origin = intersection origin and: "could have used" [rec corner = intersection corner]) "a set for" ifTrue: [isIncluded := true]]. "nextGen. See" isIncluded "explanation" ifFalse: "above." [nextGen size > 500 ifTrue: [self error: 'Converges too slowly.'] ifFalse: [nextGen add: intersection]]]]]]. nextGen size > 0 ifTrue: [generate value: nextGen]] copy fixTemps. IsSupportRecursiveBlock ifTrue: [generate value: firstGen] ifFalse: [^ self generate: firstGen counts: counts]. ^counts! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:39'! sort: collection "Form a sorted collection from collection and return it. This method tests the efficiency of sorting a fairly large collection of strings. It indirectly measures the efficiency of the sorting algorithm and of string comparison operations." ^collection asSortedCollection! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'StefanMarr 7/25/2011 01:29'! streamTestsOn: integers "modified by nishis" "Test steaming operations on the collection of integers. This method measures the efficiency of integer-to-float conversion, of printing numbers to a write stream, of parsing tokens in a read stream, and of converting the tokens from strings to numbers. The technique for converting tokens into floats is constrained by portability between ST80 and ST/V. To validate the logic, the original integers are compared with the final floats. There should be no roundoff errors." "The following line accounts for the different implementations of Float>>printString for some versions of Smalltalk. USA versions use the decimal character, while some European versions use the comma char. Thanks to Marten Feldtmann for pointing this out." | delim space s floats float string | WhichFloatPrintOn ifTrue: [delim := 1.0 printString at: 2] "$. for USA, $, for some Europe." ifFalse: [delim := $e]. "modified by nishis" space := Character value: 32. "Can't use Character space in ST/V-DOS" s := ReadWriteStream on: String new. integers do: [:i | WhichFloatPrintOn ifTrue: [i asFloat printOn: s] ifFalse: [i asFloat testPrintOn: s base: 10]. s space] copy fixTemps. "Now make sure the underlying string size is < 16383, a 16-bit small int." s contents size > (SmallInteger maxVal) ifTrue: [self error: 'String too big.']. s reset. floats := OrderedCollection new: integers size. [s atEnd] whileFalse: [float := 0.0. string := s upTo: delim. s upTo: space. "In the following, digitValue is portable between ST80 and ST/V-DOS. " string do: [:char | float := float * 10.0 + char digitValue]. floats add: float]. integers = floats ifFalse: [self error: 'Numbers do not compare.']! ! !SMarkSmopstone methodsFor: 'benchmarking' stamp: 'nishis 2/14/98 02:39'! stringsUpTo: n "Return a collection of strings representing the integers from 1 to n with their digits reversed. This method tests the efficiency of creating small streams, performing string operations, and building collections. It includes a gross kludge to coerce portability between ST80 and ST/V. They vary slightly in the selector used to reverse collections. Subsequent to freezing this code, someone pointed out that it could have been written more simply without using perform:. It could also have been simplified using select:. It was too late to change. The techniques are left as an exercise for the reader." | selector | (Array with: #reverse with: #reversed) do: [:symbol | (String canUnderstand: symbol) ifTrue: [selector := symbol]]. ^ (1 to: n) collect: [:m | m printString perform: selector]! ! !SMarkSmopstone methodsFor: 'defaults'! defaultProblemSize ^ 1! ! !SMarkSmopstone methodsFor: 'recursive method'! generate: lastGen counts: counts "added by nishis" "SmopstoneBenchmark new sorcerersApprentice." | intersection isIncluded nextGen | counts add: lastGen size. nextGen := OrderedCollection new. lastGen do: [:r1 | lastGen do: [:r2 | (r1 origin ~= r2 origin or: [r1 corner ~= r2 corner]) "In ST80 this test would have simply been r1 ~= r2" ifTrue: [(r1 intersects: r2) ifTrue: [intersection := r1 intersect: r2. isIncluded := false. "All these lines" nextGen do: "would have been" [:rec | "avoided if we" (rec origin = intersection origin and: "could have used" [rec corner = intersection corner]) "a set for" ifTrue: [isIncluded := true]]. "nextGen. See" isIncluded "explanation" ifFalse: "above." [nextGen size > 500 ifTrue: [self error: 'Converges too slowly.'] ifFalse: [nextGen add: intersection]]]]]]. nextGen size > 0 ifTrue: [self generate: nextGen counts: counts]. ^counts! ! !SMarkSmopstone commentStamp: 'nishis 2/21/98 06:26' prior: 0! modified for Squeak by nishis@urban.ne.jp see the comment of SlopstoneBenchmark class. I added all class methods and initialization>initilize method, modified: streamTestsOn: method. In some case use testPrintOn: s base: instead of printOn:, primesUpTo: method. From recursively calling a block to whileTrue: block. sorcerersApprentice method. From recursively calling a block to recursive method. execute and setup method. Thanx to Mr. Tim Olson, Mr. Kohler Markus, Mr. Tim Rowledge, Mr. John Maloney, Mr. Ian Piumarta. originak code by NAME STones80 AUTHOR bruce@utafll.uta.edu (Bruce Samuelson) FUNCTION low and medium level benchmarks for ST80 and ST/V ST-VERSIONS pre R4.0, R4.0, R4.1, ST/V PREREQUISITES need floating point hardware or emulation CONFLICTS none DISTRIBUTION world VERSION 1.0 DATE April 16, 1993 ! !SMarkSmopstone class methodsFor: 'class initialization'! initialize "added by nishis" "SmopstoneBenchmark initialize." | block | WhichFloatPrintOn := 7850 asFloat printString size = '7850.0' size. IsSupportRecursiveBlock := true. block := [:var | (var < 2) ifTrue: [block value: var + 1]]. [block value: 1] ifError: [ :msg :rec | IsSupportRecursiveBlock := false] ! ! !SMarkSuite methodsFor: 'helper'! benchmarkNameForSelector: selector "Extracts the actual name of the benchmark from the selector" (selector beginsWith: #bench) ifTrue: [ ^ selector copyFrom: 6 to: selector size]. ^ selector asSymbol ! ! !SMarkSuite methodsFor: 'helper'! shouldRunSelector: selector (selector includes: $:) ifTrue: [ ^ false ]. ^ selector beginsWith: #bench! ! !SMarkSuite methodsFor: 'running'! cleanUpInstanceVariables "Make sure all variables that are 'user variables' get cleaned" self class allInstVarNames do: [ :name | name = 'runner' ifFalse: [ self instVarNamed: name put: nil ] ]! ! !SMarkSuite methodsFor: 'running'! setUp "subclass responsibility to set up the necessary environment for a benchmark" ^ self! ! !SMarkSuite methodsFor: 'running'! tearDown "subclass responsibility to clean up the environment after a benchmark" ^ self! ! !SMarkSuite methodsFor: 'benchmarking'! performCustomSelector: aSelector with: aPrefix | customSelector | customSelector := (aPrefix, aSelector capitalized) asSymbol. (self respondsTo: customSelector) ifTrue: [ self perform: customSelector].! ! !SMarkSuite methodsFor: 'benchmarking'! problemSize ^ runner problemSize! ! !SMarkSuite methodsFor: 'benchmarking'! run "Executes all the benchmarks in the suite, coordinating with the runner when necessary" | potentialBenchmarkSelectors | selectedBenchmarks ifNotNil: [ potentialBenchmarkSelectors := selectedBenchmarks ] ifNil: [ potentialBenchmarkSelectors := self class allSelectors ]. potentialBenchmarkSelectors do: [ :selector | (self shouldRunSelector: selector) ifTrue: [ runner performBenchmark: selector ] ]. ! ! !SMarkSuite methodsFor: 'benchmarking'! runBenchmark: aSelector [self setUp. self performCustomSelector: aSelector with: #setUp. runner timedBenchmarkExecution: aSelector] ensure: [ self performCustomSelector: aSelector with: #tearDown. self tearDown. self cleanUpInstanceVariables]! ! !SMarkSuite methodsFor: 'benchmarking'! runOnly: aSymbol selectedBenchmarks := IdentitySet newFrom: { aSymbol }.! ! !SMarkSuite methodsFor: 'benchmarking'! selectedBenchmarks ^ selectedBenchmarks! ! !SMarkSuite methodsFor: 'accessing'! runner ^ runner! ! !SMarkSuite methodsFor: 'accessing'! runner: aRunner runner := aRunner.! ! !SMarkSuite commentStamp: 'StefanMarr 3/20/2011 20:57' prior: 0! A Benchmark Suite is a set of benchmarks and it knows what exactly needs to be executed. However, it does not really know how to execute it. It knows all the magic, that is, how to set up and tear down the environment for the benchmarks, but does not have the knowledge of how many iterations need to be done and how to evaluate any results that might be produced.! !SMarkSuite class methodsFor: 'defaults'! defaultProblemSize ^ nil! ! !SMarkSuite class methodsFor: 'defaults'! defaultRunner ^ SMarkRunner! ! !SMarkSuite class methodsFor: 'benchmarking'! isAbstractClass "This is a hack that is necessary in Squeak since it does not provide #isAbstractClass. Actually this class is supposed to be abstract, but well, inheritance..." ^ false! ! !SMarkSuite class methodsFor: 'benchmarking'! run ^ self defaultRunner execute: self new.! ! !SMarkSuite class methodsFor: 'benchmarking'! run: nIterations ^ self defaultRunner execute: self new with: nIterations.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testBenchmarkNameForSelector | suite | suite := SMarkSuite new. self assert: (suite benchmarkNameForSelector: #benchSomething) equals: #Something. self assert: (suite benchmarkNameForSelector: #benchsomeThingElse) equals: #someThingElse. self assert: (suite benchmarkNameForSelector: #nobenchSomeThing) equals: #nobenchSomeThing. self assert: (suite benchmarkNameForSelector: #BenchSomeThing) equals: #BenchSomeThing.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testClassRun | runner | runner := SMarkTestSuite run. self assert: (runner isKindOf: SMarkTestSuite defaultRunner). self deny: runner results isNil ! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testCleanUpInstanceVariables | suite | suite := SMarkTestSuite new. suite runner: #dummy. self assert: suite runner equals: #dummy. self assert: suite a equals: 1. self assert: suite c equals: #three. suite cleanUpInstanceVariables. self assert: suite runner equals: #dummy. self assert: suite a equals: nil. self assert: suite b equals: nil. self assert: suite c equals: nil. self assert: suite d equals: nil. ! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testCustomSetUp | suite runner | suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite. self assert: runner hasSetUpBenchB! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testCustomTearDown | suite runner | suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite. self assert: runner hasTearDownBenchC.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testRunOnly self assert: false description: 'not yet implemented'.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testSetUp | suite runner | suite := SMarkTestSuite new. self assert: suite a equals: 1. self assert: suite b equals: 2. self assert: suite c equals: #three. runner := SMarkTestRunner execute: suite. "Make sure they are reset after each run, well we test just whether they are reset after the final run" self assert: suite a equals: nil. self assert: suite b equals: nil. self assert: suite c equals: nil. self assert: suite d equals: nil. "Make sure setUp was called 4 times." self assert: 4 equals: runner setUpCount.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testSetupAndTeaddownCalledForEveryBenchForEveryIteration | suite runner | "Setup needs to be executed for every benchmark on every iteration. Test with iterations: 1" suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite with: 1. self assert: 4 equals: runner setUpCount. self assert: 4 equals: runner tearDownCount. "Setup needs to be executed for every benchmark on every iteration. Test with iterations: 4" suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite with: 4. self assert: (4 * 4) equals: runner setUpCount. self assert: (4 * 4) equals: runner tearDownCount. "Test with iterations: 10" suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite with: 10. self assert: (4 * 10) equals: runner setUpCount. self assert: (4 * 10) equals: runner tearDownCount.! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testShouldRunSelector | suite | suite := SMarkSuite new. self assert: (suite shouldRunSelector: #benchSomething). self assert: (suite shouldRunSelector: #benchsomeThingElse). self deny: (suite shouldRunSelector: #nobenchSomeThing). self deny: (suite shouldRunSelector: #BenchSomeThing).! ! !SMarkSuiteTest methodsFor: 'as yet unclassified'! testTearDown | suite runner | suite := SMarkTestSuite new. runner := SMarkTestRunner execute: suite. self assert: 4 equals: runner tearDownCount.! ! !SMarkTest methodsFor: 'tests'! testAllBenchmarksForReturningThemSelf "This is a regression test to ensure that the old behavior worked in the first place" | allSuites | allSuites := SMarkSuite subclasses. allSuites do: [:suite | suite isAbstractClass ifFalse: [ | runner results | Transcript show: (suite class name asString); cr. runner := suite run. results := runner results. self assert: (runner isKindOf: suite defaultRunner). self assert: 1 equals: runner iterations. self assert: (results size > 0). ]. ].! ! !SMarkTest methodsFor: 'tests'! testBasicRun | runner results benchResult result | runner := PBFloat run. results := runner results. result := (results at: #Add). self assert: (result isKindOf: Collection). self assert: result size equals: 1. benchResult := result at: 1. self assert: (benchResult isKindOf: SMarkResult). self assert: (benchResult total notNil). ! ! !SMarkTest methodsFor: 'running'! setUp "Necessary for Squeak 4.2 compatibility, since method anotations are not supported in the base image." (self respondsTo: #timeout:) ifTrue: [ self timeout: 300. ].! ! !SMarkTest commentStamp: 'StefanMarr 3/12/2011 21:57' prior: 0! A general test to ensure the overall framework works as expected.! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! baseBenchmarkExecuted ^ baseBenchmarkExecuted! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! countSetUpInvoke setUpCount := setUpCount + 1! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! countTearDownInvoke tearDownCount := tearDownCount + 1! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! countWasExecuted ^ notifyRunnerWasExecuted ! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! didPerform: aSymbol performedBenchmarks add: aSymbol.! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! didRunBaseBenchmark baseBenchmarkExecuted := true.! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! didSetUpBenchB didSetUpBenchB := true.! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! didTearDownBenchC didTearDownBenchC := true.! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 23:24'! initialize super initialize. setUpCount := 0. tearDownCount := 0. notifyRunnerWasExecuted := 0. baseBenchmarkExecuted := false. performedBenchmarks := Set new. "set the targetTime to something which is more reasonable for testing" targetTime := 50.! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! isNotifyRunnerWasExecutedSet ^ notifyRunnerWasExecuted! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! notifyRunnerWasExecuted notifyRunnerWasExecuted := notifyRunnerWasExecuted + 1! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! performedBenchmarks ^ performedBenchmarks! ! !SMarkTestAutosizeRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 11:01'! setUp notifyRunnerWasExecuted := false! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 18:35'! baseBenchmarkExecuted ^ baseBenchmarkExecuted! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 17:36'! countSetUpInvoke setUpCount := setUpCount + 1! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 17:39'! countTearDownInvoke tearDownCount := tearDownCount + 1! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:44'! countWasExecuted ^ notifyRunnerWasExecuted ! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:00'! didPerform: aSymbol performedBenchmarks add: aSymbol.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 17:56'! didRunBaseBenchmark baseBenchmarkExecuted := true.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 17:43'! didSetUpBenchB didSetUpBenchB := true.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 17:42'! didTearDownBenchC didTearDownBenchC := true.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 12:14'! hasSetUpBenchB ^ didSetUpBenchB.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 12:21'! hasTearDownBenchC ^ didTearDownBenchC! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:49'! initialize super initialize. setUpCount := 0. tearDownCount := 0. notifyRunnerWasExecuted := 0. baseBenchmarkExecuted := false. performedBenchmarks := OrderedCollection new.! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/15/2011 22:16'! isNotifyRunnerWasExecutedSet ^ notifyRunnerWasExecuted! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:44'! notifyRunnerWasExecuted notifyRunnerWasExecuted := notifyRunnerWasExecuted + 1! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:00'! performedBenchmarks ^ performedBenchmarks! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/15/2011 22:15'! setUp notifyRunnerWasExecuted := false! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 12:27'! setUpCount ^ setUpCount! ! !SMarkTestRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 12:39'! tearDownCount ^ tearDownCount! ! !SMarkTestRunnerSuite methodsFor: 'as yet unclassified'! benchDoNothing "Just a dummy that should be executed and result in some measured value" ^ self! ! !SMarkTestRunnerSuite methodsFor: 'as yet unclassified'! benchNotifyRunner runner notifyRunnerWasExecuted. ^ self! ! !SMarkTestRunnerSuite commentStamp: 'StefanMarr 3/13/2011 22:58' prior: 0! This is a benchmark suite used to test the benchmark runner! !SMarkTestRunnerSuite class methodsFor: 'as yet unclassified'! isAbstractClass "This is more like a hack, but we do not want to execute this as a benchmark" ^ true! ! !SMarkTestRunnerSuiteForAutosizing methodsFor: 'as yet unclassified'! baseBenchmark (Delay forMilliseconds: 5) wait.! ! !SMarkTestRunnerSuiteForAutosizing methodsFor: 'as yet unclassified'! benchBig (Delay forMilliseconds: 100) wait.! ! !SMarkTestRunnerSuiteForAutosizing methodsFor: 'as yet unclassified'! benchSmall (Delay forMilliseconds: 5) wait.! ! !SMarkTestRunnerSuiteForAutosizing class methodsFor: 'as yet unclassified'! defaultRunner ^ SMarkTestRunner! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! BenchShouldNotBeExecuted "This one should not be executed" (Delay forMilliseconds: 5) wait. runner didPerform: #BenchShouldNotBeExecuted.! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! baseBenchmark (Delay forMilliseconds: 5) wait. runner didPerform: #baseBenchmark.! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! benchAfsdfsdfsdf (Delay forMilliseconds: 5) wait. runner didPerform: #benchAfsdfsdfsdf.! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! benchBsdfasereSDSfsdfsdfs (Delay forMilliseconds: 5) wait. runner didPerform: #benchBsdfasereSDSfsdfsdfs.! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! benchC (Delay forMilliseconds: 5) wait. runner didPerform: #benchC.! ! !SMarkTestRunnerSuiteForPerfromBenchmark methodsFor: 'as yet unclassified'! benchZZ (Delay forMilliseconds: 5) wait. runner didPerform: #benchZZ.! ! !SMarkTestRunnerSuiteForPerfromBenchmark class methodsFor: 'as yet unclassified'! defaultRunner ^ SMarkTestRunner! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:15'! a ^a! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:15'! b ^b! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 00:35'! benchA a := #executed. (Delay forMilliseconds: 1) wait.! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 00:38'! benchB b := #executed. (Delay forMilliseconds: 1) wait.! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:37'! benchC c := #executed.! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/19/2011 01:04'! benchWithMultipleCriteria | t1 t2 t3 | t3 := runner createTimer: 't3'. t3 start. (Delay forMilliseconds: 25) wait. t2:= runner createTimer: 't2'. t2 start. (Delay forMilliseconds: 15) wait. t1 := runner createTimer: 't1'. t1 start. (Delay forMilliseconds: 10) wait. t3 stop. t2 stop. t1 stop. ! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:15'! c ^c! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:15'! d ^d! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 19:50'! initialize super initialize. "Filling in some test data" a := 1. b := 2. c := #three. d := '42'. ! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:39'! setUp runner countSetUpInvoke! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/13/2011 20:29'! setUpBenchB runner didSetUpBenchB! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/12/2011 22:39'! tearDown runner countTearDownInvoke! ! !SMarkTestSuite methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/13/2011 20:30'! tearDownBenchC runner didTearDownBenchC! ! !SMarkTestSuite commentStamp: 'StefanMarr 3/12/2011 22:13' prior: 0! This class is used for unit testing only.! !SMarkTestSuite class methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/20/2011 21:09'! defaultRunner ^ SMarkTestRunner! ! !SMarkTestSuite class methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/13/2011 20:57'! isAbstractClass "This is more like a hack, but we do not want to execute this as a benchmark" ^ true! ! !SMarkTestSuiteWithBaseBenchmark methodsFor: 'as yet unclassified' stamp: 'StefanMarr 3/18/2011 18:32'! baseBenchmark runner didRunBaseBenchmark.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:44'! baseBenchmarkExecuted ^ baseBenchmarkExecuted! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:41'! countSetUpInvoke setUpCount := setUpCount + 1! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:41'! countTearDownInvoke tearDownCount := tearDownCount + 1! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:41'! countWasExecuted ^ notifyRunnerWasExecuted ! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:41'! didPerform: aSymbol performedBenchmarks add: aSymbol.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! didRunBaseBenchmark baseBenchmarkExecuted := true.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! didSetUpBenchB didSetUpBenchB := true.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! didTearDownBenchC didTearDownBenchC := true.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! initialize super initialize. setUpCount := 0. tearDownCount := 0. notifyRunnerWasExecuted := 0. baseBenchmarkExecuted := false. performedBenchmarks := OrderedCollection new.! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 13:20'! isNotifyRunnerWasExecutedSet ^ notifyRunnerWasExecuted > 0! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! notifyRunnerWasExecuted notifyRunnerWasExecuted := notifyRunnerWasExecuted + 1! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:42'! performedBenchmarks ^ performedBenchmarks! ! !SMarkTestWeakScalingRunner methodsFor: 'as yet unclassified' stamp: 'StefanMarr 4/15/2011 10:43'! setUp notifyRunnerWasExecuted := false! ! !SMarkTimer methodsFor: 'timing' stamp: 'StefanMarr 3/20/2011 12:24'! currentMillis "hack to make it work under most Smalltalkses and Pinocchio" "STEFAN: had to take this out, since my images do not support pragmas <pPrimitive: #millisecondClock plugin: #'Chronology.Time' >" ^ Time millisecondClockValue! ! !SMarkTimer methodsFor: 'timing' stamp: 'StefanMarr 3/14/2011 08:54'! reset startTime := 0. elapsedTime := 0.! ! !SMarkTimer methodsFor: 'timing' stamp: 'StefanMarr 3/20/2011 12:24'! start startTime := self currentMillis.! ! !SMarkTimer methodsFor: 'timing' stamp: 'StefanMarr 3/20/2011 12:25'! stop | elapsedInThisPeriod current | current := self currentMillis. elapsedInThisPeriod := Time milliseconds: current since: startTime. elapsedTime := elapsedTime + elapsedInThisPeriod.! ! !SMarkTimer methodsFor: 'initialization' stamp: 'StefanMarr 3/14/2011 08:54'! initialize elapsedTime := 0! ! !SMarkTimer methodsFor: 'accessing' stamp: 'StefanMarr 3/14/2011 08:54'! name ^name! ! !SMarkTimer methodsFor: 'accessing' stamp: 'StefanMarr 3/14/2011 08:54'! name: aString name := aString ! ! !SMarkTimer methodsFor: 'accessing' stamp: 'StefanMarr 3/14/2011 08:54'! totalTime ^elapsedTime! ! !SMarkTimer class methodsFor: 'instance creation' stamp: 'StefanMarr 3/14/2011 08:54'! new: aName | timer | timer := super new. timer name: aName. ^timer! ! !SMarkTimerTest methodsFor: 'as yet unclassified'! testName | timer | timer := SMarkTimer new. self assert: timer name equals: nil. timer name: #foo. self assert: timer name equals: #foo.! ! !SMarkTimerTest methodsFor: 'as yet unclassified'! testReset | timer | timer := SMarkTimer new. timer start. (Delay forMilliseconds: 10) wait. timer stop. self assert: (timer totalTime >= 10). timer reset. self assert: timer totalTime equals: 0.! ! !SMarkTimerTest methodsFor: 'as yet unclassified'! testStartStop | timer | timer := SMarkTimer new. self assert: timer totalTime equals: 0. timer start. (Delay forMilliseconds: 10) wait. timer stop. self assert: (timer totalTime >= 10).! ! !SMarkTimerTest methodsFor: 'as yet unclassified'! testTotalTimeWithResume | timer | timer := SMarkTimer new. self assert: timer totalTime equals: 0. timer start. (Delay forMilliseconds: 10) wait. timer stop. self assert: (timer totalTime >= 10). timer start. (Delay forMilliseconds: 10) wait. timer stop. self assert: (timer totalTime >= 20). timer start. (Delay forMilliseconds: 10) wait. timer stop. self assert: (timer totalTime >= 30).! ! !SMarkTransporter commentStamp: 'sm 5/25/2011 14:09' prior: 0! SMarkTransporter is not actually a Transporter class, since there are currently no needs for customization. Thus, it is just a dummy class for future use, and to hold #transportersForFileOutMenu. ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'sm 5/30/2011 17:13'! execute: aSelector withProcesses: numberOfProcesses withTimer: timer "This case is meant for all cases. REM: this is also used for numProc==1 to be able to measure the process start overhead in all cases. It will start the processes and wait for their completion." | processes | processes := Array new: numberOfProcesses. runningProcessesMtx := Semaphore forMutualExclusion. completionSignal := Semaphore new. runningProcesses := numberOfProcesses. "First initialize the processes" 1 to: numberOfProcesses do: [ :procNum | | proc | proc := SMarkWeakScalingRunnerExecutor createFor: aSelector for: numInnerIterations with: self and: suite. proc priority: Processor highestPriority. proc name: (self class name, '-', procNum asString). processes at: procNum put: proc. "On: procNum" ]. "Now, execute the benchmark and do the timing now" timer start. 1 to: numberOfProcesses do: [ :procNum | (processes at: procNum) resume. ]. completionSignal wait. timer stop. ! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'sm 5/30/2011 16:17'! executorCompleted runningProcessesMtx critical: [ runningProcesses := runningProcesses - 1. (runningProcesses == 0) ifTrue: [ completionSignal signal. ] ]! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 4/15/2011 15:43'! innerIterations "The number of inner iterations the benchmark is executed inside a processes" ^ numInnerIterations! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 4/15/2011 15:43'! innerIterations: anInteger "The number of inner iterations the benchmark is executed inside a processes" numInnerIterations := anInteger! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 4/15/2011 10:54'! processes ^ numProcesses! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'StefanMarr 4/15/2011 10:53'! processes: anInteger numProcesses := anInteger! ! !SMarkWeakScalingRunner methodsFor: 'benchmarking' stamp: 'sm 5/25/2011 18:31'! timedBenchmarkExecution: aSelector "Will do a timed execution of the benchmark and return the result timer" | timer | timers := Dictionary new. timer := self createTimer: 'total'. self execute: aSelector withProcesses: numProcesses withTimer: timer. self recordResults: timer for: aSelector. ^ timer! ! !SMarkWeakScalingRunner methodsFor: 'initialization' stamp: 'StefanMarr 4/15/2011 15:43'! initialize super initialize. numProcesses := self class defaultNumberOfProcesses. numInnerIterations := self class defaultNumberOfInnerIterations. ! ! !SMarkWeakScalingRunner methodsFor: 'reporting' stamp: 'sm 5/25/2011 17:50'! reportConfiguration: aStream super reportConfiguration: aStream. aStream << ('inner iterations: ', numInnerIterations asString); cr.! ! !SMarkWeakScalingRunner class methodsFor: 'defaults' stamp: 'StefanMarr 4/15/2011 15:42'! defaultNumberOfInnerIterations "The number of iterations of the inner loop in which the benchmark is executed." ^ 1! ! !SMarkWeakScalingRunnerExecutor methodsFor: 'benchmarking' stamp: 'sm 5/30/2011 16:22'! run 1 to: numInnerIterations do: [:i | suite perform: benchmarkSelector.]. runner executorCompleted.! ! !SMarkWeakScalingRunnerExecutor methodsFor: 'accessing' stamp: 'sm 5/30/2011 16:20'! benchmarkSelector: aSelector benchmarkSelector := aSelector! ! !SMarkWeakScalingRunnerExecutor methodsFor: 'accessing' stamp: 'sm 5/30/2011 16:20'! innerIterations: anInt numInnerIterations := anInt! ! !SMarkWeakScalingRunnerExecutor methodsFor: 'accessing' stamp: 'sm 5/30/2011 16:21'! runner: aRunner runner := aRunner! ! !SMarkWeakScalingRunnerExecutor methodsFor: 'accessing' stamp: 'sm 5/30/2011 16:21'! suite: aSuite suite := aSuite! ! !SMarkWeakScalingRunnerExecutor class methodsFor: 'as yet unclassified' stamp: 'sm 5/30/2011 16:33'! createFor: aSelector for: numIterations with: aRunner and: aSuite | o | o := self new. o runner: aRunner. o suite: aSuite. o innerIterations: numIterations. o benchmarkSelector: aSelector. ^ ([ o run ] newProcess)! ! !SMarkWeakScalingRunnerTest methodsFor: 'as yet unclassified'! runnerClass ^ SMarkTestWeakScalingRunner! ! !SMarkWeakScalingRunnerTest methodsFor: 'as yet unclassified'! testInnerIterations "Test the semantics of the inner loop parameter" | runner results | "Setup" runner := self runnerClass new. runner iterations: 1. runner innerIterations: 1. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 10 equals: runner countWasExecuted. self assert: 1 equals: (results at: #NotifyRunner) size. runner := self runnerClass new. runner iterations: 2. runner innerIterations: 1. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 20 equals: runner countWasExecuted. self assert: 2 equals: (results at: #NotifyRunner) size. runner := self runnerClass new. runner iterations: 2. runner innerIterations: 4. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: (20 * 4) equals: runner countWasExecuted. self assert: 2 equals: (results at: #NotifyRunner) size. runner := self runnerClass new. runner iterations: 4. runner innerIterations: 7. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: (40 * 7) equals: runner countWasExecuted. self assert: 4 equals: (results at: #NotifyRunner) size.! ! !SMarkWeakScalingRunnerTest methodsFor: 'as yet unclassified'! testWeakScaling3Processes "test with small number of processes and varying number of iterations" | runner results | "Setup for 2 iteration, and 3 process" runner := self runnerClass new. runner iterations: 2. runner processes: 3. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 6 equals: runner countWasExecuted. self assert: 2 equals: (results at: #NotifyRunner) size.! ! !SMarkWeakScalingRunnerTest methodsFor: 'as yet unclassified'! testWeakScalingFewProcesses "test with small number of processes and varying number of iterations" | runner results | "Setup for 1 iteration, and 1 process" runner := self runnerClass new. runner iterations: 1. runner processes: 1. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 1 equals: runner countWasExecuted. ! ! !SMarkWeakScalingRunnerTest methodsFor: 'as yet unclassified'! testWeakScalingManyProcesses "test with large number of processes and varying number of iterations" | runner results | "Setup" runner := self runnerClass new. runner iterations: 1. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 10 equals: runner countWasExecuted. self assert: 1 equals: (results at: #NotifyRunner) size. runner := self runnerClass new. runner iterations: 2. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 20 equals: runner countWasExecuted. self assert: 2 equals: (results at: #NotifyRunner) size. runner := self runnerClass new. runner iterations: 4. runner processes: 10. runner suite: SMarkTestRunnerSuite new. results := runner execute. self assert: 40 equals: runner countWasExecuted. self assert: 4 equals: (results at: #NotifyRunner) size.! ! !SMarkWeakScalingRunnerTest class methodsFor: 'as yet unclassified'! shouldInheritSelectors ^ true! ! !SUnitAPIDocumentation class methodsFor: 'accessing' stamp: 'tbn 12/16/2010 22:39'! bookName ^'API Documentation'! ! !SUnitAPIDocumentation class methodsFor: 'accessing' stamp: 'tbn 12/16/2010 22:40'! packages ^#('SUnit-Core-Announcements' 'SUnit-Core-Extensions' 'SUnit-Core-Kernel' 'SUnit-Core-Kernel' 'SUnit-Core-Utilities' 'SUnit-Tests' 'SUnit-UI')! ! !SUnitAPIDocumentation class methodsFor: 'defaults' stamp: 'tbn 12/16/2010 22:39'! builder ^PackageAPIHelpBuilder! ! !SUnitExtensionsTest methodsFor: 'accessing' stamp: 'GuillermoPolito 9/1/2010 18:24'! stream ^stream ifNil: [stream := String new writeStream].! ! !SUnitExtensionsTest methodsFor: 'as yet unclassified' stamp: 'md 4/2/2006 14:02'! testExceptionWithMatchingString self should: [ Object obsolete ] raise: Error whoseDescriptionIncludes: 'NOT obsolete' description: 'tested obsoleting Object'! ! !SUnitExtensionsTest methodsFor: 'as yet unclassified' stamp: 'md 4/2/2006 14:02'! testExceptionWithoutMatchingString self should: [ Object obsolete ] raise: Error whoseDescriptionDoesNotInclude: 'Zero' description: 'tested obsoleting Object'! ! !SUnitExtensionsTest methodsFor: 'as yet unclassified' stamp: 'md 4/2/2006 14:02'! testNoExceptionWithMatchingString self shouldnt: [ Object obsolete ] raise: Error whoseDescriptionIncludes: 'Zero' description: 'tested obsoleting Object'! ! !SUnitExtensionsTest methodsFor: 'as yet unclassified' stamp: 'md 4/2/2006 14:02'! testNoExceptionWithNoMatchingString self shouldnt: [ Object obsolete ] raise: Error whoseDescriptionDoesNotInclude: 'NOT' description: 'tested obsoleting Object'! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! assertionFailedInRaiseWithExceptionDoTest self should: [ Error signal ] raise: Error withExceptionDo: [ :anException | self assert: false ]! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! differentExceptionInShouldRaiseWithExceptionDoTest [ self should: [ Error signal ] raise: Halt withExceptionDo: [ :anException | self assert: false description: 'should:raise:withExceptionDo: handled an exception that should not handle'] ] on: Error do: [ :anException | anException return: nil ]! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! errorInRaiseWithExceptionDoTest self should: [ Error signal ] raise: Error withExceptionDo: [ :anException | Error signal: 'A forced error' ]! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'EstebanLorenzano 11/11/2010 17:13'! invalidShouldNotTakeMoreThan self should: [(Delay forMilliseconds: 100) wait] notTakeMoreThan: 50 milliSeconds.! ! !SUnitExtensionsTest methodsFor: 'real tests'! invalidShouldNotTakeMoreThanMilliseconds self should: [(Delay forMilliseconds: 100) wait] notTakeMoreThanMilliseconds: 50! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! noExceptionInShouldRaiseWithExceptionDoTest self should: [ ] raise: Error withExceptionDo: [ :anException | Error signal: 'Should not get here' ]! ! !SUnitExtensionsTest methodsFor: 'real tests'! shouldFixTest self shouldFix: [ Error signal: 'any kind of error' ] ! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! shouldRaiseWithExceptionDoTest self should: [ Error signal: '1' ] raise: Error withExceptionDo: [ :anException | self assert: anException messageText = '1' ]! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'mx 3/20/2006 23:47'! shouldRaiseWithSignalDoTest self should: [ Error signal: '1' ] raise: Error withExceptionDo: [ :anException | self assert: anException messageText = '1' ]! ! !SUnitExtensionsTest methodsFor: 'real tests' stamp: 'md 8/2/2006 11:05'! validShouldNotTakeMoreThan self should: [(Delay forMilliseconds: 100) wait] notTakeMoreThan: 200 milliSeconds.! ! !SUnitExtensionsTest methodsFor: 'real tests'! validShouldNotTakeMoreThanMilliseconds self should: [(Delay forMilliseconds: 100) wait] notTakeMoreThanMilliseconds: 200! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 23:39'! testAssertionFailedInRaiseWithExceptionDo | testCase testResult | testCase := self class selector: #assertionFailedInRaiseWithExceptionDoTest. testResult := testCase run. self assert: (testResult failures includes: testCase). self assert: testResult failures size=1. self assert: testResult passed isEmpty. self assert: testResult errors isEmpty. ! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 21:15'! testAutoAssertFalse | booleanCondition | self assert: self isLogging. self should: [ self assert: 1 = 2 description: 'self assert: 1 = 2' ] raise: TestResult failure. booleanCondition := (self stream contents subStrings: {Character cr}) last = 'self assert: 1 = 2'. self assert: booleanCondition! ! !SUnitExtensionsTest methodsFor: 'test'! testAutoAssertTrue self assert: 1 = 1. self assert: true! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 21:16'! testAutoDenyFalse | booleanCondition | self assert: self isLogging. self should: [ self deny: 1 = 1 description: 'self deny: 1 = 1'.] raise: TestResult failure. booleanCondition := (self stream contents subStrings: {Character cr}) last = 'self deny: 1 = 1'. self assert: booleanCondition! ! !SUnitExtensionsTest methodsFor: 'test'! testAutoDenyTrue self deny: 1 = 2. self deny: false! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 23:40'! testDifferentExceptionInShouldRaiseWithExceptionDo | testCase testResult | testCase := self class selector: #differentExceptionInShouldRaiseWithExceptionDoTest. testResult := testCase run. self assert: (testResult passed includes: testCase). self assert: testResult errors isEmpty. self assert: testResult failures isEmpty. self assert: testResult passed size=1! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 23:40'! testErrorInRaiseWithExceptionDo | testCase testResult | testCase := self class selector: #errorInRaiseWithExceptionDoTest. testResult := testCase run. self assert: (testResult errors includes: testCase). self assert: testResult errors size=1. self assert: testResult failures isEmpty. self assert: testResult passed isEmpty. ! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'md 8/2/2006 11:06'! testInvalidShouldNotTakeMoreThan | testCase testResult | testCase := self class selector: #invalidShouldNotTakeMoreThan. testResult := testCase run. self assert: testResult passed isEmpty. self assert: testResult failures size = 1. self assert: (testResult failures includes: testCase). self assert: testResult errors isEmpty ! ! !SUnitExtensionsTest methodsFor: 'test'! testInvalidShouldNotTakeMoreThanMilliseconds | testCase testResult | testCase := self class selector: #invalidShouldNotTakeMoreThanMilliseconds. testResult := testCase run. self assert: testResult passed isEmpty. self assert: testResult failures size = 1. self assert: (testResult failures includes: testCase). self assert: testResult errors isEmpty ! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 23:40'! testNoExceptionInShouldRaiseWithExceptionDo | testCase testResult | testCase := self class selector: #noExceptionInShouldRaiseWithExceptionDoTest. testResult := testCase run. self assert: (testResult failures includes: testCase). self assert: testResult failures size=1. self assert: testResult passed isEmpty. self assert: testResult errors isEmpty. ! ! !SUnitExtensionsTest methodsFor: 'test'! testShouldFix | testCase testResult | testCase := self class selector: #shouldFixTest. testResult := testCase run. self assert: (testResult passed includes: testCase). self assert: testResult passed size=1. self assert: testResult failures isEmpty. self assert: testResult errors isEmpty. ! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'mx 3/20/2006 23:40'! testShouldRaiseWithExceptionDo | testCase testResult | testCase := self class selector: #shouldRaiseWithExceptionDoTest. testResult := testCase run. self assert: (testResult passed includes: testCase). self assert: testResult passed size=1. self assert: testResult failures isEmpty. self assert: testResult errors isEmpty. ! ! !SUnitExtensionsTest methodsFor: 'test' stamp: 'md 8/2/2006 11:06'! testValidShouldNotTakeMoreThan | testCase testResult | testCase := self class selector: #validShouldNotTakeMoreThan. testResult := testCase run. self assert: (testResult passed includes: testCase). self assert: testResult passed size = 1. self assert: testResult failures isEmpty. self assert: testResult errors isEmpty ! ! !SUnitExtensionsTest methodsFor: 'test'! testValidShouldNotTakeMoreThanMilliseconds | testCase testResult | testCase := self class selector: #validShouldNotTakeMoreThanMilliseconds. testResult := testCase run. self assert: (testResult passed includes: testCase). self assert: testResult passed size = 1. self assert: testResult failures isEmpty. self assert: testResult errors isEmpty ! ! !SUnitExtensionsTest methodsFor: 'test support'! failureLog ^self stream! ! !SUnitExtensionsTest methodsFor: 'testing'! isLogging ^true! ! !SUnitExtensionsTest class methodsFor: 'history' stamp: 'simon.denier 11/22/2008 22:13'! lastStoredRun ^ ((Dictionary new) add: (#passed->((Set new) add: #testNoExceptionWithMatchingString; add: #testNoExceptionWithNoMatchingString; add: #testExceptionWithMatchingString; add: #testExceptionWithoutMatchingString; add: #testValidShouldNotTakeMoreThan; add: #testInvalidShouldNotTakeMoreThanMilliseconds; add: #testDifferentExceptionInShouldRaiseWithExceptionDo; add: #testShouldRaiseWithExceptionDo; add: #testShouldFix; add: #testAssertionFailedInRaiseWithExceptionDo; add: #testAutoDenyFalse; add: #testAutoDenyTrue; add: #testAutoAssertFalse; add: #testAutoAssertTrue; add: #testValidShouldNotTakeMoreThanMilliseconds; add: #testErrorInRaiseWithExceptionDo; add: #testNoExceptionInShouldRaiseWithExceptionDo; add: #testInvalidShouldNotTakeMoreThan; yourself)); add: (#timeStamp->'22 November 2008 10:11:35 pm'); add: (#failures->((Set new))); add: (#errors->((Set new))); yourself)! ! !SUnitHelp commentStamp: 'tbn 12/16/2010 22:26' prior: 0! This is a custom help book for the SUnit framework. ! !SUnitHelp class methodsFor: 'accessing' stamp: 'tbn 12/16/2010 22:19'! bookName ^'SUnit framework'! ! !SUnitHelp class methodsFor: 'accessing' stamp: 'tbn 4/26/2011 15:37'! pages ^#(introduction running SUnitTutorial SUnitAPIDocumentation links)! ! !SUnitHelp class methodsFor: 'pages' stamp: 'tbn 12/16/2010 23:31'! introduction "This method was automatically generated. Edit it using:" "SUnitHelp edit: #introduction" ^HelpTopic title: 'Introduction' contents: 'SUnit is the mother of all unit testing frameworks, and serves as one of the cornerstones of test-driven development methodologies such as eXtreme Programming. The culture of testing has always been part of the philosophy of development in Smalltalk: You write a method, accept the code and test it by writing a small script in a workspace, in a comment or an example as a class method. But this approach does not allow to automatically repeat the testing or ensure that the code is working. SUnit is a framework you can use to describe and execute unit tests. Unit testing is a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application.!!' readStream nextChunkText! ! !SUnitHelp class methodsFor: 'pages' stamp: 'tbn 4/26/2011 15:37'! links "This method was automatically generated. Edit it using:" "SUnitHelp edit: #links" ^HelpTopic title: 'Links' contents: 'Visit the following sites to get more informations on SUnit - http://sunit.sourceforge.net/ - http://www.iam.unibe.ch/~ducasse/Programmez/OnTheWeb/Eng-Art8-SUnit-V1.pdf - http://en.wikipedia.org/wiki/SUnit!!' readStream nextChunkText! ! !SUnitHelp class methodsFor: 'pages' stamp: 'tbn 12/16/2010 23:31'! running "This method was automatically generated. Edit it using:" "SUnitHelp edit: #running" ^HelpTopic title: 'Running tests' contents: 'SUnit allows writing tests on Smalltalk source code and checking results. This is usually done in a tool called TestRunner which you can either open from the Pharo world menu or by evaluating: TestRunner open in a Smalltalk workspace. By writing tests and checking them with the test runner you can ensure the sustainability of your applications. !!' readStream nextChunkText! ! !SUnitTest methodsFor: 'accessing'! hasRun ^hasRun! ! !SUnitTest methodsFor: 'accessing'! hasSetup ^hasSetup! ! !SUnitTest methodsFor: 'running'! setUp hasSetup := true! ! !SUnitTest methodsFor: 'testing' stamp: 'md 2/22/2006 14:17'! errorShouldntRaise self shouldnt: [self someMessageThatIsntUnderstood] raise: Notification new ! ! !SUnitTest methodsFor: 'testing'! expectedFailures ^#(expectedFailureFails expectedFailurePasses)! ! !SUnitTest methodsFor: 'testing'! testAssert self assert: true. self deny: false! ! !SUnitTest methodsFor: 'testing'! testDefects | result suite error failure | suite := TestSuite new. suite addTest: (error := self class selector: #error). suite addTest: (failure := self class selector: #fail). result := suite run. self assert: result defects asArray = (Array with: error with: failure). self assertForTestResult: result runCount: 2 passed: 0 failed: 1 errors: 1! ! !SUnitTest methodsFor: 'testing'! testDialectLocalizedException self should: [TestResult signalFailureWith: 'Foo'] raise: TestResult failure. self should: [TestResult signalErrorWith: 'Foo'] raise: TestResult error.! ! !SUnitTest methodsFor: 'testing'! testError | case result | case := self class selector: #error. result := case run. self assertForTestResult: result runCount: 1 passed: 0 failed: 0 errors: 1. case := self class selector: #errorShouldntRaise. result := case run. self assertForTestResult: result runCount: 1 passed: 0 failed: 0 errors: 1! ! !SUnitTest methodsFor: 'testing'! testException self should: [self error: 'foo'] raise: TestResult error! ! !SUnitTest methodsFor: 'testing'! testExpectedFailure | case result | case := self class selector: #expectedFailureFails. self deny: case shouldPass. result := case run. self assertForTestResult: result runCount: 1 passed: 0 failed: 0 errors: 0 expectedFailures: 1.! ! !SUnitTest methodsFor: 'testing'! testExpectedFailureDetection self assert: self expectedFailures size = 2. self assert: (self expectedFailures includesAllOf: #(expectedFailureFails expectedFailurePasses))! ! !SUnitTest methodsFor: 'testing'! testExpectedFailurePass | case result | case := self class selector: #expectedFailurePasses. self deny: case shouldPass. result := case run. self assertForTestResult: result runCount: 1 passed: 0 failed: 1 errors: 0 expectedFailures: 0.! ! !SUnitTest methodsFor: 'testing'! testFail | case result | case := self class selector: #fail. result := case run. self assertForTestResult: result runCount: 1 passed: 0 failed: 1 errors: 0! ! !SUnitTest methodsFor: 'testing'! testFileOutResult | suite result fileout | suite := TestSuite new. suite addTest: (self class selector: #noop); addTest: (self class selector: #fail); addTest: (self class selector: #error). result := suite run. fileout := String streamContents: [:aStream| result fileOutOn: aStream]. self assert: fileout equals: '3 run, 1 passes, 0 expected failures, 1 failures, 1 errors, 0 unexpected passes Failures: SUnitTest>>#fail Errors: SUnitTest>>#error ' ! ! !SUnitTest methodsFor: 'testing'! testIsNotRerunOnDebug | case | case := self class selector: #testRanOnlyOnce. case run. case debug! ! !SUnitTest methodsFor: 'testing'! testRan | case | case := self class selector: #setRun. case resources do: [:each | each availableFor: case]. [case setUp. case performTest] ensure: [ self assert: case hasSetup. self assert: case hasRun. case tearDown. case cleanUpInstanceVariables]. self assert: case hasSetup isNil. self assert: case hasRun isNil.! ! !SUnitTest methodsFor: 'testing'! testRanOnlyOnce self assert: hasRanOnce ~= true. hasRanOnce := true! ! !SUnitTest methodsFor: 'testing'! testResult | case result | case := self class selector: #noop. result := case run. self assertForTestResult: result runCount: 1 passed: 1 failed: 0 errors: 0! ! !SUnitTest methodsFor: 'testing' stamp: 'md 2/22/2006 14:16'! testRunning (Delay forSeconds: 2) wait ! ! !SUnitTest methodsFor: 'testing' stamp: 'md 2/22/2006 14:19'! testSelectorWithArg: anObject "should not result in error"! ! !SUnitTest methodsFor: 'testing'! testShould self should: [true]; shouldnt: [false]! ! !SUnitTest methodsFor: 'testing'! testSuite | suite result | suite := TestSuite new. suite addTest: (self class selector: #noop); addTest: (self class selector: #fail); addTest: (self class selector: #error). result := suite run. self assertForTestResult: result runCount: 3 passed: 1 failed: 1 errors: 1! ! !SUnitTest methodsFor: 'testing' stamp: 'DF 3/17/2006 01:30'! testWithExceptionDo self should: [self error: 'foo'] raise: TestResult error withExceptionDo: [:exception | self assert: (exception description includesSubString: 'foo') ] ! ! !SUnitTest methodsFor: 'private'! assertForTestResult: aResult runCount: aRunCount passed: aPassedCount failed: aFailureCount errors: anErrorCount self assert: aResult runCount = aRunCount; assert: aResult passedCount = aPassedCount; assert: aResult failureCount = aFailureCount; assert: aResult errorCount = anErrorCount! ! !SUnitTest methodsFor: 'private'! assertForTestResult: aResult runCount: aRunCount passed: aPassedCount failed: aFailureCount errors: anErrorCount expectedFailures: anExpectedFailureCount self assert: aResult runCount = aRunCount; assert: aResult expectedPassCount = aPassedCount; assert: aResult failureCount = aFailureCount; assert: aResult errorCount = anErrorCount; assert: aResult expectedDefectCount = anExpectedFailureCount! ! !SUnitTest methodsFor: 'private'! error 3 zork! ! !SUnitTest methodsFor: 'private' stamp: 'NikoSchwarz 10/23/2010 14:34'! expectedFailureFails "<expectedFailure>" self assert: false.! ! !SUnitTest methodsFor: 'private' stamp: 'NikoSchwarz 10/23/2010 15:34'! expectedFailurePasses "<expectedFailure>" self assert: true.! ! !SUnitTest methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! fail self assert: false! ! !SUnitTest methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! noop! ! !SUnitTest methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! setRun hasRun := true! ! !SUnitTest commentStamp: '<historical>' prior: 0! This is both an example of writing tests and a self test for the SUnit. The tests here are pretty strange, since you want to make sure things blow up. You should not generally have to write tests this complicated in structure, although they will be far more complicated in terms of your own objects- more assertions, more complicated setup. Kent says: "Never forget, however, that if the tests are hard to write, something is probably wrong with the design".! !SUnitTest class methodsFor: 'history' stamp: 'AdrianLienhard 10/19/2009 10:49'! lastStoredRun ^ ((Dictionary new) add: (#passed->((Set new) add: #testWithExceptionDo; add: #testAssert; add: #testRanOnlyOnce; add: #testDialectLocalizedException; add: #testFail; add: #testDefects; add: #testIsNotRerunOnDebug; add: #testResult; add: #testRunning; add: #testError; add: #testException; add: #testShould; add: #testSuite; yourself)); add: (#timeStamp->'22 November 2008 10:11:35 pm'); add: (#failures->((Set new))); add: (#errors->((Set new))); yourself)! ! !SUnitTransporter commentStamp: 'sm 5/25/2011 00:01' prior: 0! SUnitTransporter is not actually a Transporter class, since there are currently no needs for customization. Thus, it is just a dummy class for future use, and to hold #transportersForFileOutMenu. ! !SUnitTransporter class methodsFor: 'transporter' stamp: 'sm 5/25/2011 00:02'! transportersForFileOutMenu ^ { Transporter forPackage: (PackageInfo named: 'SUnit') }! ! !SUnitTutorial commentStamp: 'tbn 12/16/2010 22:38' prior: 0! This is a custom help book providing a tutorial for the SUnit framework. ! !SUnitTutorial class methodsFor: 'accessing' stamp: 'tbn 12/16/2010 22:37'! bookName ^'Tutorial'! ! !SUnitTutorial class methodsFor: 'accessing' stamp: 'tbn 4/26/2011 15:56'! pages ^#(step1 step2 step3 step4 step5)! ! !SUnitTutorial class methodsFor: 'pages' stamp: 'tbn 12/16/2010 23:29'! step1 "This method was automatically generated. Edit it using:" "SUnitTutorial edit: #step1" ^HelpTopic title: 'Step 1 - Define a test class' contents: 'To define a series of tests in SUnit one typically creates a subclass of class TestCase. The idea is that the methods of this class will implement several tests, the instance variables represent the objects and / or the context in which these tests will be performed. In our example we want to write a test on a simple Person class (which is not yet in our image). If the unit under test is a single class one convention is to name the test like the class but followed with the postfix "Test". So to create a test for the Person class we subclass TestCase with a custom "PersonTest" class. TestCase subclass: #PersonTest instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: ''MyApp-Tests-Model'' Note that we havent created the class Person yet - so one idea of ExtremeProgramming (XP) is to write the test first as a way to describe a use case that your application has to cover. After that you write the code and the test will show you if the scenario is fullfilled. You dont have to follow this programming style and can also write tests to cover existing code. !!' readStream nextChunkText! ! !SUnitTutorial class methodsFor: 'pages' stamp: 'tbn 4/26/2011 15:42'! step2 "This method was automatically generated. Edit it using:" "SUnitTutorial edit: #step2" ^HelpTopic title: 'Step 2 - Define a first test method' contents: 'To define a test we create a new instance side method for our first test scenario. By convention any method (in a subclass of TestCase) whose selector starts with ''test'' is supposed to be a test and can be run using the TestRunner tool: testInstanceCreation |person| person := Person named: ''Beck''. person firstName: ''Kent''. self assert: person fullName = ''Kent Beck''. A good style is to put this method into the method category ''testing''. When you accept the code the system may ask you about the new class Person. It''s not yet defined - but you can easily create it using the following class definition: Object subclass: #Person instanceVariableNames: ''name firstName'' classVariableNames: '''' poolDictionaries: '''' category: ''MyApp-Core-Model''!!' readStream nextChunkText! ! !SUnitTutorial class methodsFor: 'pages' stamp: 'tbn 4/26/2011 15:55'! step3 "This method was automatically generated. Edit it using:" "SUnitTutorial edit: #step3" ^HelpTopic title: 'Step 3 - Running our first test method' contents: 'To run our test case method we can evaluate the following code snippet in a workspace: PersonTest run: #testInstanceCreation If you print the result then the following will appear: 1 run, 0 passes, 0 expected failures, 0 failures, 1 errors, 0 unexpected passes This tells us that one test has been run and one error occured while testing. Currently we dont have all messages implemented - so the test has to fail. If you want to debug the test to see whats happened you can evaluate: PersonTest debug: #testInstanceCreation !!' readStream nextChunkText! ! !SUnitTutorial class methodsFor: 'pages' stamp: 'tbn 4/26/2011 16:01'! step4 "This method was automatically generated. Edit it using:" "SUnitTutorial edit: #step4" ^HelpTopic title: 'Step 4 - Using the TestRunner' contents: 'Testing by evaluating an expression as we is not very convenient - so it is better to open the TestRunner - a user interface tool displaying all the tests in the system. You can start it either using the world menu or by evaluating TestRunner open in a workspace. Scroll down until you find the class category ''MyApp-Tests-Model'' and select the test by clicking on the class PersonTest. It is possible to select more than one test/category. Now click on "Run selected". If you run the test in the test runner it will be marked red since it contains errors. The test runner will also show you the result of the test run: 1 run, 0 passes, 0 expected failures, 0 failures, 1 errors, 0 unexpected passes If you click on the failed method in the lower right pane the debugger will open.!!' readStream nextChunkText! ! !SUnitTutorial class methodsFor: 'pages' stamp: 'tbn 4/26/2011 16:19'! step5 "This method was automatically generated. Edit it using:" "SUnitTutorial edit: #step5" ^HelpTopic title: 'Step 5 - Getting the test green' contents: 'To get our test green we have to implement the missing methods. First the debugger tells us that the Person class does not understand the message #named: We dont have to go back into a standard browser to implement it, we just select ''Create'' in the walkback window. The system now asks us where #named: should be defined in the inheritance hierarchy. We select the Person class and categorize the method in a new method category ''instance creation''. Finally we have a debugger open where we can implement the code like this: named: aString ^(self new) name: aString; yourself Note that after accepting the method in the debugger you can instantly step through it or hit ''Proceed'' to continue execution. The system tell us that there is no setter method #name:, so we implement it too on the instance side: name: aString name := aString Next the #firstName: message is missing: firstName: aString firstName := aString At any point in time we can control if the test is already green in the TestRunner. Finally when we implement the missing #fullName method by concatenating first name and surename: fullName ^firstName, '' '', name Now out test should be green.!!' readStream nextChunkText! ! !SUnitUnloader methodsFor: 'unloading'! unloadAll self unloadTestPackages. self unloadSUnit.! ! !SUnitUnloader methodsFor: 'unloading'! unloadSUnit Smalltalk globals at: #TestCase ifPresent: [ :class | SystemChangeNotifier uniqueInstance noMoreNotificationsFor: class ]. #(#SUnitGUI #SUnit) do: [ :each | (MCPackage named: each) unload ]. AppRegistry removeObsolete. ! ! !SUnitUnloader methodsFor: 'unloading'! unloadTestPackages #('Tests' 'CollectionsTests' 'CompilerTests' 'FreeTypeTests' 'Graphics-Tests' 'KernelTests' 'MorphicTests' 'MultilingualTests' 'NetworkTests' 'ToolsTest' 'Gofer-Tests' 'Announcements-Tests-Core' 'CompressionTests' 'HelpSystem-Tests' 'Multilingual-Tests' 'Regex-Tests-Core' 'HelpSystem-Tests' 'Balloon-Collections-Tests' 'StratifiedProxy-Tests' 'Finder-Tests' 'Zinc-Tests') do: [ :each | (MCPackage named: each) unload ]. ! ! !SUnitUnloader commentStamp: 'LaurentLaffont 4/15/2011 20:20' prior: 0! I am SUnitUnloader, a little tool to unload SUnit and a fixed set of Tests from the current image. Usage: SUnitUnloader new unloadAll Caveat: #unloadTestPackages uses a fixed and probably ill maintained list of what packages hold unit tests. ! !Scanner class methodsFor: '*Sly3' stamp: 'ssa 4/19/2010 20:31'! initialize | newTable | newTable _ Array new: 256 withAll: #xBinary. "default" newTable atAll: #(9 10 12 13 32 ) put: #xDelimiter. "tab lf ff cr space" newTable atAll: ($0 asciiValue to: $9 asciiValue) put: #xDigit. 1 to: 255 do: [:index | (Character value: index) isLetter ifTrue: [newTable at: index put: #xLetter]]. newTable at: 30 put: #doIt. newTable at: $" asciiValue put: #xDoubleQuote. newTable at: $# asciiValue put: #xLitQuote. newTable at: $% asciiValue put: #percent. newTable at: $$ asciiValue put: #xDollar. newTable at: $' asciiValue put: #xSingleQuote. newTable at: $: asciiValue put: #xColon. newTable at: $( asciiValue put: #leftParenthesis. newTable at: $) asciiValue put: #rightParenthesis. newTable at: $. asciiValue put: #period. newTable at: $; asciiValue put: #semicolon. newTable at: $[ asciiValue put: #leftBracket. newTable at: $] asciiValue put: #rightBracket. newTable at: ${ asciiValue put: #leftBrace. newTable at: $} asciiValue put: #rightBrace. newTable at: $^ asciiValue put: #upArrow. newTable at: $_ asciiValue put: #leftArrow. newTable at: $| asciiValue put: #verticalBar. TypeTable _ newTable "bon voyage!!" "Scanner initialize"! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/10/2010 10:26'! closeAllUnlockedWindows "ScreenController new closeAllUnlockedWindows" "Close any window that isn't locked." | toClose | toClose _ ScheduledControllers scheduledControllers select: [:c | c preventClosing not]. (SelectionMenu confirm:'Do you really want to close all unlocked windows?') ifFalse: [^ self]. toClose do: [:c | c closeAndUnscheduleIfOkWithModelNoTerminate]. self restoreDisplay. ! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/9/2010 15:26'! closeTopWindow | closeable | closeable _ ScheduledControllers scheduledControllers detect:[:controller| controller preventClosing not] ifNone:[^self]. closeable view flash. sensor commandKeyPressed ifTrue:[closeable closeAndUnscheduleIfOkWithModel]! ! !ScreenController methodsFor: 'fast window closing' stamp: 'ssa 3/9/2010 15:27'! preventClosing ^true! ! !ScreenController methodsFor: 'control defaults' stamp: 'ssa 3/3/2010 14:37'! controlActivity "Any button opens the screen's menu. If the shift key is down, do find window." sensor leftShiftDown ifTrue: [^ self findWindow]. sensor controlKeyPressed ifTrue: [^self closeTopWindow]. (self projectScreenMenu invokeOn: self) ifNil: [super controlActivity]! ! !ScreenController methodsFor: 'control defaults' stamp: 'ssa 3/3/2010 13:42'! isControlWanted ^ self viewHasCursor and: [sensor anyButtonPressed]! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 1/21/2010 12:17'! exploreViewFromUser "Explore the selected window" | controller | (controller _ ScheduledControllers windowFromUser) notNil ifTrue: [controller view explore]! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 9/4/2008 15:11'! openProcessBrowser "Create and schedule" ProcessBrowser open! ! !ScreenController methodsFor: 'menu messages' stamp: 'tk 5/4/1998 17:25'! openWorkspace "Create and schedule workspace." Workspace open! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 3/24/2010 16:34'! recolorWindows Smalltalk recolorWindows! ! !ScreenController methodsFor: 'menu messages' stamp: 'ssa 9/3/2008 11:12'! restoreDisplay "Clear the screen to gray and then redisplay all the scheduled views." Display extent = DisplayScreen actualScreenSize ifFalse: [DisplayScreen startUp. ScheduledControllers unCacheWindows]. ScheduledControllers restore! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/24/2010 16:33'! appearanceMenu "Answer the appearance menu to be put up as a screen submenu" ^ SelectionMenu labelList: #('system fonts...' 'full screen on' 'full screen off' 'recolor windows' 'set display depth...' 'set desktop color...' ) lines: #(1 3) selections: #( configureFonts fullScreenOn fullScreenOff recolorWindows setDisplayDepth setDesktopColor) " ScreenController new appearanceMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 9/4/2008 15:11'! openMenu ^ SelectionMenu labelList: #( 'browser' 'package browser' 'method finder' 'process browser' 'workspace' 'file list' 'file...' 'transcript' 'simple change sorter' 'dual change sorter' 'mvc project' ) lines: #(8 10 ) selections: #( openBrowser openPackageBrowser openSelectorBrowser openProcessBrowser openWorkspace openFileList openFile openTranscript openSimpleChangeSorter openChangeManager openProject ) " ScreenController new openMenu startUp "! ! !ScreenController methodsFor: 'nested menus' stamp: 'ssa 3/10/2010 10:01'! windowMenu "Answer a menu for windows-related items. " ^ SelectionMenu labelList: #( 'find window...' 'find changed browsers...' 'find changed windows...' 'collapse all windows' 'expand all windows' 'close unchanged windows' 'close unlocked windows' ) , (Array with: self bitCachingString with: self staggerPolicyString) lines: #(3 7) selections: #( findWindow chooseDirtyBrowser chooseDirtyWindow collapseAll expandAll closeUnchangedWindows closeAllUnlockedWindows fastWindows changeWindowPolicy ) " ScreenController new windowMenu startUp "! ! !ScreenController methodsFor: '*RVM' stamp: 'dmu 1/29/2011 16:31'! dashboardMenu | labels selections | labels _ #('RVM dashboard') asOrderedCollection. selections _ #(openRVMDashboard) asOrderedCollection. (Smalltalk includesKey: #Sly3) ifTrue:[ labels add: 'Sly dashboard'. selections add:#openSlyDashboard]. (Smalltalk includesKey: #Ly) ifTrue:[ labels add: 'Ly dashboard'. selections add:#openLyDashboard]. (Smalltalk includesKey: #Qube) ifTrue:[ labels add: 'Qube dashboard'. selections add:#openQubeDashboard]. ^ SelectionMenu labelList: labels lines: #() selections: selections " ScreenController new dashboardMenu startUp "! ! !ScreenController methodsFor: '*RVM' stamp: 'ssa 4/20/2010 09:50'! openRVMDashboard "Create and schedule a RVM dashboard." RVMMonitor dashboard! ! !ScreenController methodsFor: '*RVM' stamp: 'ssa 7/7/2010 11:20'! presentDashboardMenu self popUpMenuFor: #dashboardMenu! ! !ScreenController methodsFor: '*RVM' stamp: 'ads 1/12/2011 16:37'! projectScreenMenu "Answer the project screen menu." ^ SelectionMenu labelList: #( 'previous project' 'jump to project...' 'restore display' 'dashboards...' 'file out package...' 'open...' 'windows...' 'changes...' 'help...' 'appearance...' 'do...' 'save' 'save as...' 'save and quit' 'quit') lines: #(3 5 12) selections: #( returnToPreviousProject jumpToProject restoreDisplay presentDashboardMenu presentPackageMenu presentOpenMenu presentWindowMenu presentChangesMenu presentHelpMenu presentAppearanceMenu commonRequests snapshot saveAs snapshotAndQuit quit ) " ScreenController new projectScreenMenu startUp "! ! !ScreenController methodsFor: '*Sly' stamp: 'dmu 8/30/2010 10:44'! openSlyDashboard "Create and schedule a Sly dashboard." Sly3 dashboard! ! !ScreenController methodsFor: '*Sly' stamp: 'ssa 3/24/2010 14:13'! presentSlyMenu self popUpMenuFor: #slyMenu! ! !ScreenController methodsFor: '*Sly' stamp: 'ssa 3/24/2010 14:12'! slyMenu ^ SelectionMenu labelList: #( 'dashboard' ) lines: #() selections: #(openSlyDashboard) " ScreenController new slyMenu startUp "! ! !ScreenController methodsFor: '*Transporter' stamp: 'sm 3/11/2011 11:38'! presentPackageMenu | transportersByName packageNames selectedIndex | transportersByName := Transporter getAllTransporters. packageNames := transportersByName keys asSortedCollection. packageNames addLast: 'All'. packageNames := packageNames asArray. selectedIndex := (PopUpMenu labelArray: packageNames lines: {(packageNames size) - 1}) startUpWithCaption: 'Which package do you want to file out?'. selectedIndex = 0 ifFalse: [ selectedIndex = packageNames size ifTrue: [transportersByName valuesDo: [:transporter| transporter saveNoPopup]] ifFalse: [ | selectedPackageName selectedTransporter | selectedPackageName := packageNames at: selectedIndex. selectedTransporter := transportersByName at: selectedPackageName. selectedTransporter save. ]. ].! ! !ScriptConsole class methodsFor: 'as yet unclassified'! << aString self print: aString! ! !ScriptConsole class methodsFor: 'as yet unclassified'! cr self println: ''.! ! !ScriptConsole class methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 14:50'! detectAvailableMechanismForStdout "The RoarVM has its own primitive" | cls | cls := Smalltalk at: #RVMOperations ifAbsent: [nil]. IsRVM := (cls notNil and: [cls perform: #isRVM]). IsRVM ifTrue: [ PrintTarget := cls. ^ self. ] ifFalse: [ "Squeak 4.2 provides a stream at FileStream>>stdout" (FileStream respondsTo: #stdout) ifTrue: [ PrintTarget := FileStream stdout. ^ self. ]. ]. PrintTarget := nil. ^ nil! ! !ScriptConsole class methodsFor: 'as yet unclassified'! initialize OutputToTranscript := false. self detectAvailableMechanismForStdout.! ! !ScriptConsole class methodsFor: 'as yet unclassified'! outputToTranscript ^ OutputToTranscript! ! !ScriptConsole class methodsFor: 'as yet unclassified'! outputToTranscript: aBool OutputToTranscript := aBool! ! !ScriptConsole class methodsFor: 'as yet unclassified'! print: somethingAsString self print: somethingAsString withLineEnding: ''.! ! !ScriptConsole class methodsFor: 'as yet unclassified' stamp: 'sm 6/1/2011 14:47'! print: somethingAsString withLineEnding: lineEnd "Will output the somethingAsString to stdout using one of the available mechansims and to the transcript if requested" | output | output := somethingAsString asString. PrintTarget ifNotNil: [ IsRVM ifTrue: [ PrintTarget print: output. ] ifFalse: [ PrintTarget nextPutAll: (output, lineEnd) ]. ]. (OutputToTranscript or: [PrintTarget isNil]) ifTrue: [ Transcript show: output, lineEnd. ].! ! !ScriptConsole class methodsFor: 'as yet unclassified'! println: somethingAsString self print: somethingAsString withLineEnding: String crlf.! ! !ScriptStarter commentStamp: 'StefanMarr 5/14/2011 16:29' prior: 0! ScriptStarter provides a startUp method and registers itself on the startUpList to enable scripting using command-line arguments. The first argument on the command-line is used to identify a class on which #run: is invoked with the arguments as an array. #run: can be used similar to classic main(String[] args) methods in other languages. ! !ScriptStarter class methodsFor: 'system startup entry' stamp: 'sm 5/25/2011 12:41'! install "Will register ScriptStarter on the StartUpList to activate it on VM startup." | pref | Smalltalk addToStartUpList: ScriptStarter. "Disable the loading of documents on startup" pref := Smalltalk at: #Preferences ifAbsent: [nil]. pref ifNotNil: [ (pref respondsTo: #disable:) ifTrue: [ pref disable: #readDocumentAtStartup. ] ] ifNil: [ (Smalltalk globals at: #AbstractLauncer ifAbsent: [nil]) ifNotNilDo: [:launcher | launcher readDocumentAtStartup: false ] ].! ! !ScriptStarter class methodsFor: 'system startup entry' stamp: 'sm 5/30/2011 22:35'! startUp "startUp is invoked during startup. ScriptStarter has to be registered in the SystemDirectory's StartUpList See ScriptStarter>>install" | arguments scriptClassName | "Ok, only, and really only during startup" IsResuming ifFalse: [ Transcript show: 'ScriptStarter did not execute a given script, since it assumes to be executed after a snapshot and not during startup.'. ^ self. ]. "First make sure that stdout output can be used if available." ScriptConsole detectAvailableMechanismForStdout. arguments := self getSystemAttributes. arguments size > 0 ifTrue: [scriptClassName := arguments at: 1. self executeRunFor: scriptClassName with: arguments.]! ! !ScriptStarter class methodsFor: 'system startup entry' stamp: 'sm 5/30/2011 22:30'! startUp: resuming IsResuming := resuming. ^ super startUp: resuming.! ! !ScriptStarter class methodsFor: 'system startup entry'! uninstall "Will remove ScriptStarter from the StartUpList" Smalltalk removeFromStartUpList: ScriptStarter. self flag: 'TODO: restore original setting for readDocumentAtStartup, see >>install.'. Transcript show: 'You might need to restore the original setting for readDocumentAtStartup'.! ! !ScriptStarter class methodsFor: 'helper'! executeRunFor: scriptClassName with: arguments | scriptClass | scriptClass := Smalltalk classNamed: scriptClassName. scriptClass ifNotNil: [ scriptClass run: arguments. QuitVM ifTrue: [ Smalltalk snapshot: SafeBeforeQuit andQuit: true. ]. ].! ! !ScriptStarter class methodsFor: 'helper'! getSystemAttributes | arguments arg i | arguments := OrderedCollection new. i := 2. [[arg := SmalltalkImage current getSystemAttribute: i] value == nil] whileFalse: [arguments addLast: arg. i := i + 1]. ^ arguments! ! !ScriptStarter class methodsFor: 'transporter' stamp: 'sm 2/13/2011 19:09'! transportersForFileOutMenu ^ { Transporter forPackage: (PackageInfo named: 'Scripting') }! ! !ScriptStarter class methodsFor: 'initialization' stamp: 'sm 5/30/2011 22:33'! initialize "Automatically install ScriptStarter when the code is filed in." self install. QuitVM := true. SafeBeforeQuit := false. IsResuming := false.! ! !ScriptStarter class methodsFor: 'configuration'! quitVMAfterScriptExecution ^ QuitVM! ! !ScriptStarter class methodsFor: 'configuration'! quitVMAfterScriptExecution: aBool QuitVM := aBool! ! !ScriptStarter class methodsFor: 'configuration'! saveImageBeforeQuit ^ SafeBeforeQuit! ! !ScriptStarter class methodsFor: 'configuration'! saveImageBeforeQuit: aBool SafeBeforeQuit := aBool! ! !ScrollController methodsFor: 'basic control sequence' stamp: 'ssa 9/9/2009 17:06'! controlInitialize "Recompute scroll bars. Save underlying image unless it is already saved." "Hacked to disable flop-out scroll bars when inside an MSWScrollBarView - ssa 12/10/97 15:21" super controlInitialize. scrollBar region: (0 @ 0 extent: 24 @ view apparentDisplayBox height). scrollBar insideColor: view backgroundColor. marker region: self computeMarkerRegion. scrollBar _ scrollBar align: scrollBar topRight with: view apparentDisplayBox topLeft. marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2). savedArea isNil ifTrue: [savedArea _ Form fromDisplay: scrollBar]. (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[scrollBar displayOn: Display]. "Show a border around yellow-button (menu) region" " yellowBar _ Rectangle left: self yellowLine right: scrollBar right + 1 top: scrollBar top bottom: scrollBar bottom. Display border: yellowBar width: 1 mask: Form veryLightGray. " self moveMarker ! ! !ScrollController methodsFor: 'basic control sequence' stamp: 'ssa 9/9/2009 17:07'! controlTerminate super controlTerminate. savedArea notNil ifTrue: [ (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[savedArea displayOn: Display at: scrollBar topLeft]. savedArea _ nil].! ! !ScrollController methodsFor: 'control defaults'! controlActivity "Hacked to supprt MSWScrollBarView - ssa 12/10/97 17:07" (self view superView isKindOf: MSWScrollBarView) ifFalse:[ self scrollBarContainsCursor ifTrue: [self scroll] ifFalse: [super controlActivity]] ifTrue:[super controlActivity]! ! !ScrollController methodsFor: 'control defaults'! isControlActive "Viva la Junta!!" "HACKED to ignore scrollbar in the activity test if contained in a ScrollbarView - ssa 1/8/98 16:24" view isNil ifTrue: [^ false]. (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:["original code" ^(view insetDisplayBox merge: scrollBar inside) containsPoint: sensor cursorPoint] ifTrue:[^view insetDisplayBox containsPoint: sensor cursorPoint]! ! !ScrollController methodsFor: 'marker adjustment'! moveMarker "The view window has changed. Update the marker." "Hacked to suppress flop-out scrollbar updates when the view is encapsulated by an MSWScrollBarView - ssa 12/10/97 15:24" (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[self moveMarker: self markerDelta negated anchorMarker: nil]! ! !ScrollController methodsFor: 'marker adjustment'! moveMarkerTo: aRectangle "Same as markerRegion: aRectangle; moveMarker, except a no-op if the marker would not move." "Hacked to suppress flop-out scrollbar updates when the view is encapsulated by an MSWScrollBarView - ssa 12/10/97 15:24" (self view superView isKindOf: MSWScrollBarView) "_______HERE IS THE HACK" ifFalse:[ (aRectangle height = marker height and: [self viewDelta = 0]) ifFalse: [self markerRegion: aRectangle. self moveMarker]]! ! !SelectionMenu class methodsFor: 'instance creation' stamp: 'ssa 8/22/2009 16:21'! labels: labels lines: linesArray selectors: selectionsArray "ST80 Compatibility" ^ self labels: labels lines: linesArray selections: selectionsArray! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/18/2008 23:18'! asCircularCollection "Answer a circular version of myself" ^RVMCircularCollection withAll: self! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/27/2008 20:34'! rotateBackward "Answer a copy of the receiver with elements rotated toward the front." " 'frog' rotateBackward" | n result | n _ self size. result _ self species new: n. n = 0 ifTrue:[^result]. n = 1 ifTrue:[result at: 1 put: (self at: 1). ^result]. 1 to: n-1 do: [:i | result at: i put: (self at: i + 1)]. result at: n put: self first. ^ result ! ! !SequenceableCollection methodsFor: 'converting' stamp: 'ssa 10/27/2008 20:33'! rotateForward "Answer a copy of the receiver with elements rotated toward the end." " 'frog' rotateForward" | n result | n _ self size. result _ self species new: n. n = 0 ifTrue:[^result]. n = 1 ifTrue:[result at: 1 put: (self at: 1). ^result]. 2 to: n do: [:i | result at: i put: (self at: i - 1)]. result at: 1 put: self last. ^ result ! ! !SequenceableCollection methodsFor: 'copying' stamp: 'dmu 5/5/2009 01:05'! shuffled ^ self shuffledBy: Collection randomForPicking copy "Examples: ($A to: $Z) shuffled "! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 13:51'! with: secondCollection with: thirdCollection do: threeArgBlock "Evaluate threeArgBlock with corresponding elements from this collection, secondCollection and thirdCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. thirdCollection size = self size ifFalse: [self error: 'thirdCollection must be the same size']. 1 to: self size do: [:index | threeArgBlock value: (self at: index) value: (secondCollection at: index) value: (thirdCollection at: index)]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 14:01'! with: secondCollection with: thirdCollection withIndexDo: fourArgBlock "Evaluate fourArgBlock with corresponding elements from this collection, secondCollection and thirdCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. thirdCollection size = self size ifFalse: [self error: 'thirdCollection must be the same size']. 1 to: self size do: [:index | fourArgBlock value: (self at: index) value: (secondCollection at: index) value: (thirdCollection at: index) value: index]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 5/28/2010 15:34'! with: secondCollection withIndexDo: threeArgBlock "Evaluate threeArgBlock with corresponding elements from this collection and secondCollection." secondCollection size = self size ifFalse: [self error: 'secondCollection must be the same size']. 1 to: self size do: [:index | threeArgBlock value: (self at: index) value: (secondCollection at: index) value: index]! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 1/20/2009 14:08'! without: anObject collect: aBlock "Evaluate aBlock with each of the receiver's elements except anObject as the argument. Collect the resulting values into a collection like the receiver. Answer the new collection." | newCollection | newCollection _ self species new: self size - 1. 1 to: self size do: [:index | anObject = (self at: index) ifFalse:[newCollection add: (aBlock value: (self at: index))]]. ^ newCollection! ! !SequenceableCollection methodsFor: 'enumerating' stamp: 'ssa 1/20/2009 14:11'! without: anObject select: aBlock "Evaluate aBlock with each of the receiver's elements except anObject as the argument. Select the resulting values that pass into a collection like the receiver. Answer the new collection." | newCollection item | newCollection _ self species new: self size - 1. 1 to: self size do: [:index | item _ self at:index. (anObject ~= item and:[aBlock value: item]) ifTrue:[newCollection add: item]]. ^ newCollection! ! !SequenceableCollection methodsFor: 'testing' stamp: 'ssa 8/27/2009 12:44'! is: anObject after: anotherObject ^(self indexOf: anObject)<(self indexOf: anotherObject)! ! !SequenceableCollection methodsFor: '*connectors-enumerating' stamp: 'ssa 1/1/1970 00:18'! groupsOfNoMoreThan: n atATimeDo: aBlock "Evaluate aBlock with my elements taken n at a time. Handle leftovers at the end." | args remaining | n to: self size by: n do: [:index | args := (self copyFrom: index - n + 1 to: index) asArray. aBlock value: args]. (remaining _ self size \\ n) = 0 ifFalse:["handle leftovers" args := (self copyFrom: self size - remaining + 1 to: self size) asArray. aBlock value: args]! ! !SequenceableCollection methodsFor: '*packageinfo-base' stamp: 'ab 9/17/2002 01:02'! do: aBlock displayingProgress: aString aString displayProgressAt: Sensor cursorPoint from: 0 to: self size during: [:bar | self withIndexDo: [:each :i | bar value: i. aBlock value: each]]! ! !SequenceableCollection methodsFor: '*Ly-Explorer' stamp: 'hg 9/7/2001 12:01'! explorerContents ^self asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !Set methodsFor: '*RVM-Archiving'! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self size. self do: [:each | aStream nextPut: each]! ! !Set methodsFor: '*Ly-Explorer' stamp: 'hg 9/7/2001 11:51'! explorerContents ^self asOrderedCollection withIndexCollect: [:each :index | ObjectExplorerWrapper with: each name: index printString model: self]! ! !Set class methodsFor: '*RVM-Archiving'! dearchiveFrom: aStream | anObject anInteger | anInteger _ aStream read: Integer. anObject _ self new: (anInteger * 2 max: 2). aStream storeObject: anObject. anInteger timesRepeat: [anObject add: aStream next]. ^anObject! ! !SimpleTestResource methodsFor: 'accessing'! runningState ^runningState! ! !SimpleTestResource methodsFor: 'accessing'! runningState: aSymbol runningState := aSymbol! ! !SimpleTestResource methodsFor: 'running'! setRun hasRun := true! ! !SimpleTestResource methodsFor: 'running'! setUp self runningState: self startedStateSymbol. hasSetup := true! ! !SimpleTestResource methodsFor: 'running'! startedStateSymbol ^#started! ! !SimpleTestResource methodsFor: 'running'! stoppedStateSymbol ^#stopped! ! !SimpleTestResource methodsFor: 'running'! tearDown self runningState: self stoppedStateSymbol! ! !SimpleTestResource methodsFor: 'testing'! hasRun ^hasRun! ! !SimpleTestResource methodsFor: 'testing'! hasSetup ^hasSetup! ! !SimpleTestResource methodsFor: 'testing' stamp: ' 17/7/10 17:28'! isAvailable ^self class allowAvailability and: [self runningState == self startedStateSymbol]! ! !SimpleTestResource class methodsFor: 'accessing' stamp: ' 17/7/10 17:28'! allowAvailability ^preventAvailability isNil! ! !SimpleTestResource class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:13'! rawCurrentForTest ^current! ! !SimpleTestResource class methodsFor: 'utility' stamp: ' 17/7/10 17:28'! preventAvailabilityDuring: aBlock "Only setter of preventAvailability." preventAvailability := false. ^aBlock ensure: [preventAvailability := nil]! ! !SimpleTestResourceA class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:13'! resources ^Array with: SimpleTestResourceA1 with: SimpleTestResourceA2! ! !SimpleTestResourceB class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:13'! resources ^Array with: SimpleTestResourceA1 with: SimpleTestResourceB1! ! !SimpleTestResourceCircular class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:12'! resources ^preventAvailability isNil ifTrue: [super resources , (Array with: SimpleTestResourceA1)] ifFalse: [super resources , (Array with: SimpleTestResourceA1 with: SimpleTestResourceCircular1)]! ! !SimpleTestResourceCircular1 class methodsFor: 'accessing' stamp: 'nfr 1/3/2010 18:12'! resources "Circular prereq: C wants C1 which wants C." ^Array with: SimpleTestResourceCircular! ! !SimpleTestResourceTestCase methodsFor: 'not categorized'! testResourceInitRelease | result suite error failure | suite := TestSuite new. suite addTest: (error := self class selector: #error). suite addTest: (failure := self class selector: #fail). suite addTest: (self class selector: #dummy). result := suite run. self assert: resource hasSetup ! ! !SimpleTestResourceTestCase methodsFor: 'running' stamp: ' 17/7/10 17:28'! setUp "Ensure that we error, not just fail, if resource is nil so that #should:raise: checks cannot mistake such an error for what they are trapping." resource := SimpleTestResource rawCurrentForTest. self deny: resource isNil description: 'SimpleTestResource has no current value in test'. self assert: resource class == SimpleTestResource description: 'SimpleTestResource current is not an instance of itself'. self assert: resource hasSetup description: 'This test uses a resource but it was not set up'! ! !SimpleTestResourceTestCase methodsFor: 'running' stamp: 'nfr 1/3/2010 18:09'! testDebugTestWithResource "The debug will raise an error if the resource is not set up properly." self clearOuterResourceStateDuring: [(self class selector: #setRun) debug]! ! !SimpleTestResourceTestCase methodsFor: 'running' stamp: 'NiallRoss 7/18/2010 12:28'! testResourceCollection self assert: self class buildSuiteFromSelectors resources size = self resources size description: 'The suite should have the same number of resources as its test'. self class buildSuiteFromSelectors resources do: [:each | self assert: (self resources includes: each) description: each name , ': I have this resource but my suite does not'].! ! !SimpleTestResourceTestCase methodsFor: 'running' stamp: 'NiallRoss 7/18/2010 12:30'! testRunSuiteWithResource | suite | suite := TestSuite new. suite addTest: (SimpleTestResourceTestCase selector: #error). suite addTest: (SimpleTestResourceTestCase selector: #fail). suite addTest: (self class selector: #dummy). self clearOuterResourceStateDuring: [self assert: suite run printString = '3 run, 1 passes, 0 expected failures, 1 failures, 1 errors, 0 unexpected passes' description: 'A suite of tests needing SimpleTestResource did not run as expected'].! ! !SimpleTestResourceTestCase methodsFor: 'running' stamp: 'NiallRoss 7/18/2010 12:31'! testRunTestWithResource self clearOuterResourceStateDuring: [self assert: (self class selector: #dummy) run printString = '1 run, 1 passes, 0 expected failures, 0 failures, 0 errors, 0 unexpected passes' description: 'A dummy test that needed a resource did not pass']! ! !SimpleTestResourceTestCase methodsFor: 'utility' stamp: 'NiallRoss 7/18/2010 11:53'! clearOuterResourceStateDuring: aBlock "This self-testing test must clear the outer state of its resources before starting and after finishing, so that it can construct test cases and suites of itself and test them." self assert: SimpleTestResource isAlreadyAvailable description: 'The resource was not set up for the test'. SimpleTestResource reset. self deny: SimpleTestResource isAlreadyAvailable description: 'The resource was still set up before we began the run'. ^aBlock ensure: [self deny: SimpleTestResource isAlreadyAvailable description: 'The resource was still set up after we finished the run'. SimpleTestResource isAvailable. self assert: SimpleTestResource isAlreadyAvailable description: 'The resource was not set up again after the test']! ! !SimpleTestResourceTestCase methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! dummy self assert: resource hasSetup description: 'This test uses a resource but it was not set up'. self setRun. self assert: resource hasRun description: 'This test uses a resource but we could not interact with it'.! ! !SimpleTestResourceTestCase methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! error 'foo' odd! ! !SimpleTestResourceTestCase methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! fail self assert: false! ! !SimpleTestResourceTestCase methodsFor: 'private' stamp: 'BaseSystem 8/30/2009 09:40'! setRun resource setRun! ! !SimpleTestResourceTestCase class methodsFor: 'accessing' stamp: 'BaseSystem 8/30/2009 09:40'! resources ^Array with: SimpleTestResource! ! !SimpleTestResourceTestCase class methodsFor: 'history' stamp: 'AdrianLienhard 10/19/2009 10:49'! lastStoredRun ^ ((Dictionary new) add: (#passed->((Set new) add: #testResourceInitRelease; add: #testResourcesCollection; yourself)); add: (#timeStamp->'22 November 2008 10:11:35 pm'); add: (#failures->((Set new))); add: (#errors->((Set new))); yourself)! ! !Sly class methodsFor: 'testing' stamp: 'dmu 8/27/2010 13:38'! isSlySelector: aSelector "True if its has SlySelectorModifers" ^(aSelector beginsWith: SlySelectorModifier asAWhole) or:[(aSelector includesSubString: SlySelectorModifier adverbColon) or:[aSelector includesSubString: SlySelectorModifier gerundColon]]! ! !Sly class methodsFor: 'user interfacing' stamp: 'dmu 8/27/2010 14:15'! dashboard "Sly dashboard " | topView buttons lastView subViewCount | topView := RVMStandardSystemView new . topView borderWidth:1. buttons _ { Transcript showInConsoleSwitch. self keepFlyingSwitch. RVMButtonView label:'[ SlyBoids new run ] fork' action:[[ SlyBoids new run ] fork]. RVMButtonView label:'Restore normal cursor' action:[Cursor normal show]. RVMButtonView label:'process browser' action:[ProcessBrowser open]. RVMButtonView label: 'SlySyntaxTests runAll' action: [SlySyntaxTests runAll]. }. lastView _ nil. buttons do:[:view| topView addSubView: view below: lastView. lastView _ view]. topView label: 'Sly'. subViewCount _ topView subViews size. topView minimumSize: 165@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !Sly class methodsFor: 'user interfacing' stamp: 'dmu 8/30/2010 10:44'! keepFlyingSwitch "Sly3 keepFlyingSwitch demo" ^RVMCheckBoxView on: self label: 'Keep SlyBoids Flying' checkState: [Sly3 keepFlying] whenChecked: [Sly3 keepFlying:true] whenUnchecked: [Sly3 keepFlying:false].! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:29'! keepFlying KeepFlying isNil ifTrue:[KeepFlying _ true]. ^KeepFlying! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! keepFlying: aBoolean KeepFlying _ aBoolean! ! !Sly class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! toggleKeepFlying self keepFlying: self keepFlying not! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 10:58'! actualSelector "Answer the value of actualSelector" actualSelector isNil ifTrue:[self determineActualSelector]. ^ actualSelector! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:19'! actualSelector: anObject "Set the value of actualSelector" actualSelector _ anObject asSymbol. "(actualSelector = #readStream) ifTrue:[self halt:'FOUND IT!!']"! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:34'! argumentAdverbs "Answer the value of argumentAdverbs" argumentAdverbs isNil ifTrue:[self argumentAdverbs: "OrderedCollection new "(self arguments collect:[:e| nil])]. ^ argumentAdverbs! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! argumentAdverbs: anObject "Set the value of argumentAdverbs" argumentAdverbs _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:23'! argumentSources "Answer the value of argumentSources" argumentSources isNil ifTrue:[self argumentSources: Dictionary new]. ^ argumentSources! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:23'! argumentSources: anObject "Set the value of argumentSources" argumentSources _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 15:41'! arguments "Answer the value of arguments" arguments isNil ifTrue:[self arguments: self originalArguments]. ^ arguments! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:30'! arguments: anObject "Set the value of arguments" arguments _ anObject asOrderedCollection! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/14/2010 13:50'! executingSerially "Answer the value of executingSerially" executingSerially isNil ifTrue:[self executingSerially: false]. ^ executingSerially! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/14/2010 13:50'! executingSerially: anObject "Set the value of executingSerially" executingSerially _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! gerund "Answer the value of gerund, nil, a #symbol, or a block" gerund isNil ifTrue:[self gerund: nil]. ^ gerund! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! gerund: anObject "Set the value of gerund" gerund _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 6/1/2010 16:27'! hasGerund "Answer true if we have a gerund" ^self gerund notNil! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:28'! isAsAWhole "Answer the value of isAsAWhole" isAsAWhole isNil ifTrue:[self isAsAWhole: false]. ^ isAsAWhole! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:28'! isAsAWhole: anObject "Set the value of isAsAWhole" isAsAWhole _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! members "Answer the value of members" members isNil ifTrue:[self members: nil]. ^ members! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! members: anObject "Set the value of members" members _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 3/28/2010 23:04'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 15:55'! message: anObject "Set the value of message" message _ anObject. "force initialization" self arguments.! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! messageAdverb "Answer the value of messageAdverb" messageAdverb isNil ifTrue:[self messageAdverb: nil]. ^ messageAdverb! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:19'! messageAdverb: anObject "Set the value of messageAdverb" messageAdverb _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 16:08'! messageEnvelopes: anObject "Set the value of messageEnvelopes" messageEnvelopes _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:28'! originalArguments ^ self message arguments! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 4/20/2010 16:22'! originalSelector "Answer the value of originalSelector" originalSelector isNil ifTrue:[self originalSelector: self message selector]. ^ originalSelector! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 7/16/2010 18:48'! originalSelector: anObject "Set the value of originalSelector" "anObject = #selector ifTrue:[self halt]." "useful for debugging" Transcript cr;show:'Dispatching #',anObject. originalSelector _ anObject ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 19:32'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:36'! receiverSource "Answer the value of receiverSource" receiverSource isNil ifTrue:[self receiverSource: self determineReceiverSource]. ^ receiverSource! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:35'! receiverSource: anObject "Set the value of receiverSource" receiverSource _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:41'! receivers "Answer the value of receivers" receivers isNil ifTrue:[self receivers: self determineReceivers]. ^ receivers! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:41'! receivers: anObject "Set the value of receivers" receivers _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/11/2010 11:11'! return "Answer the value of return" self halt:'Special case...hould never access this way'. return isNil ifTrue:[self return: nil]. ^ return! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 16:54'! robinCount "Answer the value of robinCount" robinCount isNil ifTrue:[self robinCount: 0]. ^ robinCount! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 16:54'! robinCount: anObject "Set the value of robinCount" robinCount _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:29'! setAsAWhole self isAsAWhole: true! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 16:00'! theEnsemble "Answer the value of theEnsemble" ^ theEnsemble! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 16:00'! theEnsemble: anObject "Set the value of theEnsemble" theEnsemble _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 15:16'! usingRoundRobin "Answer the value of usingRoundRobin" usingRoundRobin isNil ifTrue:[self usingRoundRobin: self determineRoundRobin]. ^ usingRoundRobin! ! !Sly2EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/28/2010 14:47'! usingRoundRobin: anObject "Set the value of usingRoundRobin" usingRoundRobin _ anObject! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/28/2010 14:26'! applyAdverb: adverb toArgument: argument inEnvelope: envelope "Answer the final argument to send with the message being dispatched via this envelope. Common cases are #wholly (batch all args to each member with the message) #singly (distributed arguments one-to-one over members). Issue here with count mismatch. #roundly (distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs. #duplicatively (each member gets a copy of the arguments). Default case is #wholly" adverb isSymbol ifTrue:[^self perform: ('ARG',adverb,':inEnvelope:') asSymbol with: argument with: envelope]. adverb isBlock ifTrue:[^ adverb value: argument value: envelope]. self error:'adverbs can only be unarySelectors or Blocks at this point'! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/28/2010 17:04'! determineArgumentsForEachReceiver "Support for argument adverbs that allow arguments to be distributed/shared/paired/etc across members." | finalArg | self messageEnvelopes do:[:env| self arguments with: self argumentAdverbs withIndexDo:[:arg :adv :index| finalArg _ adv isNil ifTrue: [arg] ifFalse:["use adverb to determine and process the argument" self applyAdverb: adv toArgument: arg inEnvelope: env]. env message arguments at: index put: finalArg]] ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 7/16/2010 19:35'! determineRoundRobin "Do any of my argument adverbs imply a round-robin use of my receivers?" self argumentAdverbs isEmpty ifTrue:[^false]. self argumentAdverbs with: self arguments do:[:adv :arg| adv = #roundly ifTrue:[self robinCount: arg ENSsize. ^true]]. ^false! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/12/2010 19:51'! determineSelectorForEachReceiver "Support for message adverbs that allow members to modify the message selector being sent. Expect this case rarely. Implement later. Default case is to use the actualSelector" self messageEnvelopes do:[:each| each message selector: self actualSelector]! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying adverbs' stamp: 'ssa 5/12/2010 19:27'! receiversForAdverb: anAdverb "Answer the (sub)set of my members to send a message to based on this adverb" anAdverb isSymbol ifTrue:[^self perform: anAdverb]. anAdverb isArray ifTrue:[^self perform: anAdverb first withArguments: anAdverb allButFirst]. anAdverb isBlock ifTrue:[^anAdverb value: self members]. self error:'Expected a #symbol or aBlock for an adverb'! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 16:38'! anding:results "AND the elements in results and return the result. Assumes these elements understand &." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each & result]. ^result! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 7/7/2010 22:06'! applyGerundTo: results "use the gerund that was supplied by the sender to post-process the results of the message. ALL gerund processing starts here" self gerund isSymbol ifTrue:[^self perform: self gerund asKeyword with: results]. self gerund isBlock ifTrue:[^ gerund value: results]. self error:'gerunds can only be unarySelectors or Blocks at this point'! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:47'! averaging:results "Average the elements in results and return the result. Assumes these elements understand +." | sum | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. sum _ self totalling: results. ^sum / results size! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:35'! concatenating: results "Concatenate each element in results and return the result. Assumes these elements are collections of some kind." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ result , each]. ^result! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 16:39'! oring:results "OR the elements in results and return the result. Assumes these elements understand |." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each | result]. ^result! ! !Sly2EnsembleMessageDispatcher methodsFor: 'applying gerunds' stamp: 'ssa 5/11/2010 15:41'! totalling:results "Sum the elements in results and return the result. Assumes these elements understand +." | result | results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ 0. results do:[:each| result _ each + result]. ^result! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:27'! ARGReadMe "Argument adverbs set policies/strategies for how arguments participate in ensemble messages to the members. The ARG selector prefix is used to separate possible naming conflicts between message adverbs and argument adverbs. All argument adverbs found in a selector will get prefixed with ARG before being called. All argument adverb methods should begin with ARG and be of the form 'ARGadverbName: origArg inEnvelope: envelope'"! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:26'! ARGduplicatively: originalArgument inEnvelope: envelope "Each message uses a copy of the original argument" ^originalArgument copy! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:51'! ARGroundly: originalArgument inEnvelope: envelope "Each message uses one of the argument elements. Reuse receivers as needed in round-robin fashion. " ^self nextArgumentFromSource: originalArgument ifAtEnd:[^self] ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument adverbs' stamp: 'ssa 5/28/2010 14:11'! ARGwholly: originalArgument inEnvelope: envelope "Each message uses original argument" ^originalArgument! ! !Sly2EnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:46'! determineReceiverSource "Answer the stream(like) object that serves up my receivers" self usingRoundRobin ifTrue:[^RVMCircularCollection withAll: self receivers]. ^self receivers readStream! ! !Sly2EnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:42'! determineReceivers "identify the (sub)set of my members that will actually be sent a message. This can change based on message adverbs (completely, randomly, stochastically:aProbability, selectively:aBooleanBlock, aBlock etc) and argument adverbs (singly, aBlock, etc)" "only handle message adverbs for now, otherwise default to all members" ^self hasMessageAdverb ifTrue:[self receiversForAdverb: self messageAdverb] ifFalse:[self members asOrderedCollection]. ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'receiver sourcing' stamp: 'ssa 5/28/2010 14:35'! nextReceiver "Answer the next receiver from a stream set up over my receivers. This stream will be linear in normal cases and circular in #roundly(round-robin) cases" | source | source _ self receiverSource. source atEnd ifTrue:[self error:'not enough receivers!!']. ^source next! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument sourcing' stamp: 'ssa 5/28/2010 14:50'! nextArgumentFromSource: argument "Answer the next element from a stream set up over argument. NOTE: this implementation assumes that the argument source understands #readStream. May want to have an alternative version passing in a block to do the stream creation" ^self nextArgumentFromSource: argument ifAtEnd: [self error:'not enough argument elements for members']. ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'argument sourcing' stamp: 'ssa 7/16/2010 19:28'! nextArgumentFromSource: argument ifAtEnd: aBlock "Answer the next element from a stream set up over argument. NOTE: this implementation assumes that the argument source understands #readStream. May want to have an alternative version passing in a block to do the stream creation" | source | source _ self argumentSources at: argument ifAbsentPut:[argument ENSisEnsemble ifTrue:[argument ENSmembers readStream] ifFalse:[argument readStream]]. source atEnd ifTrue:[aBlock value]. ^source next! ! !Sly2EnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/27/2010 14:30'! dispatch | results | "NOTE: using non-local return to allow immediate exit from this method upon return determination" return _ [:result | ^ result]. "(self originalSelector endsWith:'equals:') ifTrue:[self halt]." self determineActualSelector. "gets selector to send to members and finds adverbs, gerunds and ENS" self isAsAWhole ifTrue:[self tryReflectiveMessages ]. self onlyHasGerund ifTrue:[self return: (self applyGerundTo: self members)]. results _ self sendMessageToMembersModeratedByAdverbs. self hasGerund ifTrue:[self return: (self applyGerundTo: results)]. self returnEnsembleContaining: results ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 3/29/2010 00:01'! return: r return value: r! ! !Sly2EnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/27/2010 16:04'! returnEnsembleContaining: membersOfResult "self return: ((self theEnsemble perform: #ensembleSpecies) with: membersOfResult)" self return: (SlyEnsemble with: membersOfResult) ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'reflection' stamp: 'dmu 8/27/2010 15:56'! OLDtryReflectiveMessages | reflectiveMessages r | self actualSelector = #members ifTrue:[self return: self members]. self actualSelector = #size ifTrue:[self return: self members size]. self actualSelector = #inspect ifTrue:[self return: self theEnsemble mirror inspect]. self actualSelector = #storeString ifTrue:[self return: self storeStringForMyEnsemble]. self actualSelector = #printString ifTrue:[self return: self storeStringForMyEnsemble]. self actualSelector = #printOn: ifTrue:[self return: (self originalArguments first nextPutAll: self storeStringForMyEnsemble)]. reflectiveMessages _ #( #isNil #isNotNil #isKindOf: #isInMemory #pointsTo: #nextObject #mustBeBooleanIn: #class #inspect #explore #hash #printString #printOn:). (reflectiveMessages includes: self actualSelector) ifTrue: [ 0 primitiveSetExtraPreheaderWord: self theEnsemble. r _ self theEnsemble perform: self actualSelector asSymbol withArguments: self originalArguments. self members primitiveSetExtraPreheaderWord: self theEnsemble. self return: r ].! ! !Sly2EnsembleMessageDispatcher methodsFor: 'reflection' stamp: 'dmu 8/27/2010 15:56'! tryReflectiveMessages "disable messaging dispatching to members and just send it to the ensemble object itself" | result | 0 primitiveSetExtraPreheaderWord: self message lookupClass "was theEnsemble". result _ self theEnsemble perform: self actualSelector asSymbol withArguments: self originalArguments. self theEnsemble members: self theEnsemble members. "force preheader update" self return: result! ! !Sly2EnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'ssa 6/17/2010 10:12'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! !Sly2EnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 5/28/2010 17:08'! determineEnvelopes "Determine the number of envelopes needed and create them. NOTE: #roundly argument adverb will impact this number" self usingRoundRobin ifFalse:[self receivers do:[:each| self messageEnvelopes add: (SlyMessageEnvelope receiver: each selector: self actualSelector arguments: self arguments asArray copy)]] ifTrue:[self robinCount timesRepeat:[ self messageEnvelopes add: (SlyMessageEnvelope receiver: self nextReceiver selector: self actualSelector arguments: self arguments asArray copy)]]! ! !Sly2EnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 7/8/2010 00:43'! sendMessageToMembersModeratedByAdverbs "default behavior when no adverbs found in message" self hasAdverbs ifFalse:[ self actualSelector = #members ifTrue:[self halt:'should never dispatch #members to members']. ^self members parallelCollect: [:elem| elem perform: self actualSelector withArguments: self arguments asArray]]. "now handle the general case for all possible adverbs" self determineEnvelopes. self determineSelectorForEachReceiver. self determineArgumentsForEachReceiver. self relocateReceiversIfNeeded. self relocateArgumentsIfNeeded. ^self sendMessages! ! !Sly2EnsembleMessageDispatcher methodsFor: 'member messaging' stamp: 'ssa 7/14/2010 13:49'! sendMessages "Deliver the message envelopes and collect results. This must eventually handle adverbs for timing and recurring messages, determining when the ensemble message is 'done'. etc. For now, do the simplest thing, a parallelCollect:" "check for serially flag and handle appropriately" ^self executingSerially ifTrue:[self messageEnvelopes collect:[:env| env deliver]] ifFalse:[self messageEnvelopes parallelCollect: [:env| env deliver]]! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/27/2010 14:36'! completely "A message level adverb indicating all members are to receive the message" ^self members! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:35'! exclusively: aBlock "A message level adverb indicating to exclude certain members from receiving the message" ^self rejectively: aBlock! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:36'! inclusively: aBlock "A message level adverb indicating to include certain members for receiving the message" ^self selectively: aBlock! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:37'! randomly "A message level adverb indicating one member at random to receive the message" ^self randomly: 1! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/27/2010 10:42'! randomly: n "A message level adverb indicating n members at random to receive the message" | remainders chosen picked | remainders _ self members asOrderedCollection. chosen _ OrderedCollection new. n timesRepeat:[ remainders isEmpty ifTrue:[^chosen]. chosen add: (picked _ remainders atRandom). remainders remove: picked]. ^chosen! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'dmu 8/27/2010 15:56'! reflectively "A message level adverb indicating the ensemble itself is to receive the message. This duplicates the ENS prefix protocol using message adverbs to make it possible for programmatic reflective messaging without hacking the selector. This approach has the effect of making the ensemble itself appear as the single member of an ensemble" ^self theEnsemble! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:35'! rejectively: aBlock "A message level adverb indicating to exclude certain members from receiving the message" ^self members reject: aBlock! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 5/12/2010 19:36'! selectively: aBlock "A message level adverb indicating to select certain members to receive the message" ^self members select: aBlock! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 7/14/2010 13:55'! serially "Execute this message serially to all my members. This is a hack since currently all message adverbs must return the members to make envelopes for" self executingSerially:true. ^self members! ! !Sly2EnsembleMessageDispatcher methodsFor: 'message adverbs' stamp: 'ssa 6/1/2010 16:38'! stochastically: aProbability "A message level adverb indicating some probalilty (0.0-1.0) for each members to receive the message" ^self members select:[:each| self randomNumberSource next <= aProbability]! ! !Sly2EnsembleMessageDispatcher methodsFor: 'relocating' stamp: 'ssa 5/27/2010 11:28'! relocateArgumentsIfNeeded "Supports argument adverbs that desire to be in special core locations relative to each other or to their receiving members. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'relocating' stamp: 'ssa 5/27/2010 11:28'! relocateReceiversIfNeeded "Supports message adverbs that desire to have member in special core locations relative to each other or to arguments. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 14:30'! determineActualKeywordSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig actual | orig _ self originalSelector. actual _ orig copy asString. (orig beginsWith: SlySelectorModifier asAWhole) ifTrue:[self setAsAWhole. actual _ actual withoutFirst: SlySelectorModifier asAWholeSize]. ((actual includesSubString: SlySelectorModifier adverbColon) or: [actual includesSubString: SlySelectorModifier gerundColon]) ifFalse:[^actual ] ifTrue:[self isAsAWhole ifTrue:[self error:'reflective ENS sends can''t have adverbs or gerunds']. "handle gerund case" (actual last: SlySelectorModifier gerundColonSize)= SlySelectorModifier gerundColon ifTrue:[self gerund: self arguments removeLast. actual _ actual withoutLast: SlySelectorModifier gerundColonSize. ]. "handle adverb cases" ^(actual includesSubString: SlySelectorModifier adverbColon) ifTrue:[self handleAdverbKeywordIn: actual] ifFalse:[actual]. ] "Cases: Normal Smalltalk support: + => + unary => unary keyword: => keyword: Adverb support: unaryLY: => unary LY:keyword: => keyword: LY:keyword:LY: => keyword: LY:keyword:LY:keyword:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword:LY: => keyword:keyword:keyword: LY:keyword:keyword:LY:keyword:LY: => keyword:keyword:keyword: etc., strip all LY:s Gerund (reducer) support: unaryING: => unary keyword:ING: => keyword: keyword:keyword:keyword:keyword:ING: => keyword:keyword:keyword:keyword: etc., strip all ING:s, though there should only be one per selector DotDot, reflective send support: ENSunary => unary ENSkeyword: => keyword: ENSkeywordLY: => error, smae with ING " ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'ssa 5/12/2010 15:51'! determineActualSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed" self actualSelector: self findActualSelector! ! !Sly2EnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 14:28'! determineActualUnarySelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig | orig _ self originalSelector. (orig beginsWith: SlySelectorModifier asAWhole) ifTrue:[self isAsAWhole: true. orig _ orig copyFrom: SlySelectorModifier asAWholeSize + 1 to: orig size]. ^orig. "Cases: Normal Smalltalk support: unary => unary Adverb support: unaryLY: => unary Gerund (reducer) support: unaryING: => unary DotDot, reflective send support: ENSunary => unary " ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'ssa 5/12/2010 15:45'! findActualSelector "Answer the selector to actually send to the members, with all the LY/ING/ENS stuff removed Cases follow at end of method" | orig | orig _ self originalSelector. orig isInfix ifTrue:[^orig]. "strategy extensions not supported on binary messages" orig isUnary ifTrue:[^self determineActualUnarySelector]. orig isKeyword ifTrue:[^self determineActualKeywordSelector]. self error:'Unknown selector type for ',orig. "Cases: Normal Smalltalk support: + => + unary => unary keyword: => keyword: Adverb support: unaryLY: => unary LY:keyword: => keyword: LY:keyword:LY: => keyword: LY:keyword:LY:keyword:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword: => keyword:keyword:keyword: LY:keyword:LY:keyword:LY:keyword:LY: => keyword:keyword:keyword: LY:keyword:keyword:LY:keyword:LY: => keyword:keyword:keyword: etc., strip all LY:s Gerund (reducer) support: unaryING: => unary keyword:ING: => keyword: keyword:keyword:keyword:keyword:ING: => keyword:keyword:keyword:keyword: etc., strip all ING:s, though there should only be one per selector DotDot, reflective send support: ENSunary => unary ENSkeyword: => keyword: ENSkeywordLY: => error, same with ING " ! ! !Sly2EnsembleMessageDispatcher methodsFor: 'selector deconstruction' stamp: 'dmu 8/27/2010 15:33'! handleAdverbKeywordIn: selector "Locate the *LY: keywords and extract adverb arguments, and set real arguments, Answer the selector stripped of LY:s " | keywords adverbOffset keyword argIndex strippedSelector realArgs lastWasAdverb | lastWasAdverb _ true. keywords _ selector subStrings: {$:}. adverbOffset _ 0. realArgs _ OrderedCollection new. strippedSelector _ ''. 1 to: keywords size do:[:index| keyword _ keywords at: index. (keyword endsWith: SlySelectorModifier adverb) ifTrue:["found an adverb keyword" index = 1 ifTrue:["its the message adverb" self messageAdverb: (self arguments first). adverbOffset _ 1. keyword = SlySelectorModifier adverb ifFalse:[" the unary case, e.g., oddLY " strippedSelector _ (keyword withoutLast: SlySelectorModifier adverbSize). keywords size > 1 ifTrue:[strippedSelector _ strippedSelector,':']] ifTrue:["the keyword case LY: adv foo: bar" "do nothing, let the first keyword drop"]] ifFalse:["its an argument adverb" lastWasAdverb _ true. argIndex _ index - adverbOffset. self argumentAdverbs at: argIndex put:(self arguments at: argIndex). "DO NOTHING HERE was: strippedSelector _ strippedSelector,(keyword withoutLast: SlySelectorModifier adverbSize),':'"]] ifFalse:["normal keyword found or ING found" (keyword endsWith: SlySelectorModifier gerund) ifFalse:[ lastWasAdverb ifFalse:[self argumentAdverbs add: nil]. lastWasAdverb _ false. realArgs add:(self arguments at: index). strippedSelector _ strippedSelector,keyword,':']]]. self arguments: realArgs. ^strippedSelector! ! !Sly2EnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:12'! hasAdverbs ^self hasMessageAdverb or:[self hasArgumentAdverbs]! ! !Sly2EnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:13'! hasArgumentAdverbs self argumentAdverbs detect:[:each| each notNil] ifNone:[^false]. ^true! ! !Sly2EnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/12/2010 11:13'! hasMessageAdverb ^self messageAdverb notNil! ! !Sly2EnsembleMessageDispatcher methodsFor: 'testing' stamp: 'ssa 5/11/2010 15:45'! onlyHasGerund "True is the selector is only #ING: " ^self originalSelector == #ING:! ! !Sly2EnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 8/27/2010 16:01'! dispatch: aMessage members: aCollection theEnsemble: anObject ^ self new theEnsemble: anObject; message: aMessage; members: aCollection; dispatch! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'dmu 9/23/2010 13:41'! dashboard "Sly3 dashboard " | topView buttons lastView subViewCount | topView := RVMStandardSystemView new . topView borderWidth:1. buttons _ { Transcript showInConsoleSwitch. self keepFlyingSwitch. self serializeForDebuggingSwitch. RVMButtonView label: 'Suspend member processes' action: [Processor suspendMemberProcesses]. RVMButtonView label: 'Terminate member processes' action: [Processor terminateMemberProcesses]. RVMButtonView label: 'Debug member processes' action: [Processor suspendMemberProcesses. ProcessBrowser open]. RVMButtonView label:'[ Sly3Boids new run ] fork' action:[[ Sly3Boids new run ] fork]. RVMButtonView label: '[Sly3aBoids new run ] fork' action: [[Sly3aBoids new run ] fork ]. RVMButtonView label:'Restore normal cursor' action:[Cursor normal show]. RVMButtonView label:'process browser' action:[ProcessBrowser open]. RVMButtonView label: 'Sly3SyntaxTests runAll' action: [Sly3SyntaxTests runAll]. }. lastView _ nil. buttons do:[:view| topView addSubView: view below: lastView. lastView _ view]. topView label: 'Sly3'. subViewCount _ topView subViews size. topView minimumSize: 165@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'ssa 3/25/2010 16:41'! keepFlyingSwitch "Sly3 keepFlyingSwitch demo" ^RVMCheckBoxView on: self label: 'Keep SlyBoids Flying' checkState: [Sly3 keepFlying] whenChecked: [Sly3 keepFlying:true] whenUnchecked: [Sly3 keepFlying:false].! ! !Sly3 class methodsFor: 'user interfacing' stamp: 'dmu 9/7/2010 17:25'! serializeForDebuggingSwitch "Sly3 serializeForDebuggingSwitch demo" ^RVMCheckBoxView on: self label: 'Serialize for debugging' checkState: [Sly3 serializeForDebugging] whenChecked: [Sly3 serializeForDebugging:true] whenUnchecked: [Sly3 serializeForDebugging:false].! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:29'! keepFlying KeepFlying isNil ifTrue:[KeepFlying _ true]. ^KeepFlying! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! keepFlying: aBoolean KeepFlying _ aBoolean! ! !Sly3 class methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:24'! serializeForDebugging ^ SerializeForDebugging ifNil: [SerializeForDebugging _ false] ifNotNil: [SerializeForDebugging]! ! !Sly3 class methodsFor: 'accessing' stamp: 'dmu 9/7/2010 17:25'! serializeForDebugging: aBool SerializeForDebugging _ aBool! ! !Sly3 class methodsFor: 'accessing' stamp: 'ssa 3/25/2010 16:32'! toggleKeepFlying self keepFlying: self keepFlying not! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:28'! dispatch ! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'dmu 8/29/2010 12:56'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self unprocessedMessage members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:24'! doneBlock "Answer the value of doneBlock" doneBlock isNil ifTrue:[self doneBlock: [:r | ^ r]]. ^ doneBlock! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:24'! doneBlock: anObject "Set the value of doneBlock" doneBlock _ anObject! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:56'! unprocessedMessage "Answer the value of unprocessedMessage" unprocessedMessage isNil ifTrue:[self unprocessedMessage: Sly3UnprocessedEnsembleMessage new]. ^ unprocessedMessage! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:55'! unprocessedMessage: anObject "Set the value of unprocessedMessage" unprocessedMessage _ anObject! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'created processed message' stamp: 'dmu 8/29/2010 18:32'! justReturn: anObject self doneBlock value: anObject! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'created processed message' stamp: 'dmu 9/1/2010 23:30'! sendToMembers: selector self doneBlock value: (Sly3MessageEnvelope receiver: self unprocessedMessage members selector: selector arguments: self unprocessedMessage arguments) deliver! ! !Sly3AbstractEnsembleMessageDispatcher methodsFor: 'as yet unclassified' stamp: 'dmu 8/29/2010 13:29'! setUnprocessedSelector: sel self unprocessedMessage selector: sel! ! !Sly3AbstractEnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:27'! dispatch: anUnprocessedMessage self dispatch: anUnprocessedMessage andDo: [:r | ^ r]. self error: 'unhandled'! ! !Sly3AbstractEnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:26'! dispatch: anUnprocessedMessage andDo: doneBlock ^ self new unprocessedMessage: anUnprocessedMessage; doneBlock: [:r | ^ doneBlock value: r]; dispatch! ! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:01'! isIndirect ^ true! ! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter "Answer the value of parameter" parameter isNil ifTrue:[self parameter: nil]. ^ parameter! ! !Sly3AbstractIndirectOperandDistributor methodsFor: 'accessing' stamp: 'dmu 9/4/2010 23:00'! parameter: anObject "Set the value of parameter" parameter _ anObject! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:33'! isAdverb ^ self class isAdverb! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isArgumentModifier ^ self class isArgumentModifier! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 9/3/2010 22:16'! isDirect ^ self isIndirect not! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isGerund ^ self class isGerund! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isMessageModifier ^ self class isMessageModifier! ! !Sly3AbstractModifier methodsFor: 'testing' stamp: 'dmu 9/11/2010 16:58'! isOperandDistributor ^ false! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:39'! allUppercaseSuffixes ^ self class allUppercaseSuffixes! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:35'! lowercaseSuffix ^ self class lowercaseSuffix! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:36'! stringWithLowercaseSuffix ^ self class stringWithLowercaseSuffix! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:41'! suffixSize ^ self class suffixSize! ! !Sly3AbstractModifier methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:37'! uppercaseSuffix ^ self class uppercaseSuffix! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:39'! allUppercaseSuffixes ^ {Sly3Adverb. Sly3Gerund} collect: [:x | x uppercaseSuffix]! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:52'! lowercaseSuffix ^ self uppercaseSuffix asLowercase! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:56'! membersSelector ^#members! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 9/3/2010 12:31'! modifySelector: sel ^ (self stringWithUppercaseSuffix, sel) asSymbol! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:36'! stringWithLowercaseSuffix "Sly3ModWholly stringWithLowercaseSuffix" ^ (self name copyFrom: 'Sly3Mod' size + 1 to: self name size) asLowercase! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:46'! stringWithUppercaseSuffix ^ self stringWithoutSuffix, self uppercaseSuffix! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:47'! stringWithoutSuffix | s ss | s _ self stringWithLowercaseSuffix. ss _ self suffixSize. ^ s copyFrom: 1 to: s size - ss! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:41'! suffixSize ^ self uppercaseSuffix size! ! !Sly3AbstractModifier class methodsFor: 'accessing' stamp: 'dmu 8/30/2010 18:37'! uppercaseSuffix ^self subclassResponsibility! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:33'! isAdverb ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isArgumentModifier ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isGerund ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:34'! isMessageModifier ^ false! ! !Sly3AbstractModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 19:00'! isSlySelector: aString " Sly3AbstractModifier isSlySelector: 'abdc' " ^ self allUppercaseSuffixes anySatisfy: [:s | aString includesSubString: s]! ! !Sly3AbstractModifier class methodsFor: 'instance creation' stamp: 'dmu 9/1/2010 10:59'! instantiateSpecificFromBaseName: baseName includingSuffix: suffix | specificClassName cls | specificClassName _ 'Sly3Mod', baseName capitalized, suffix asLowercase. cls _ Smalltalk at: specificClassName asSymbol ifAbsent: [self error: 'could not find modifier class: ', specificClassName]. ^ cls new! ! !Sly3Adverb methodsFor: 'testing' stamp: 'dmu 9/3/2010 18:15'! isIndirect ^ false! ! !Sly3Adverb class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:40'! isAdverb ^ true! ! !Sly3Adverb class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:38'! uppercaseSuffix ^ 'LY'! ! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 9/12/2010 22:08'! defaultArgumentOperandDistributor ^Sly3ModWholly! ! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 4/12/2011 12:30'! defaultReceiverOperandDistributor ^Sly3ModIndividually! ! !Sly3Adverb class methodsFor: 'nil' stamp: 'dmu 9/3/2010 14:33'! reflectiveAdverb ^Sly3ModPlainly! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:51'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: #()]. ^ flock! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! flock: anObject "Set the value of flock" flock _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:57'! lastDrawnPosition "Answer the value of lastDrawnPosition" lastDrawnPosition isNil ifTrue:[self lastDrawnPosition: self position]. ^ lastDrawnPosition! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:00'! lastDrawnPosition: anObject "Set the value of lastDrawnPosition" lastDrawnPosition _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/23/2010 00:05'! lastLastDrawnPosition "Answer the value of lastLastDrawnPosition" lastLastDrawnPosition isNil ifTrue:[self lastLastDrawnPosition: self lastDrawnPosition]. ^ lastLastDrawnPosition! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/22/2010 23:53'! lastLastDrawnPosition: anObject "Set the value of lastLastDrawnPosition" lastLastDrawnPosition _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:53'! neighbors "Answer the value of neighbors" neighbors isNil ifTrue:[self neighbors: #()]. ^ neighbors! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! neighbors: anObject "Set the value of neighbors" neighbors _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! position "Answer the value of position" position isNil ifTrue:[self position: 500@500]. ^ position! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! position: anObject "Set the value of position" position _ anObject! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! velocity "Answer the value of velocity" velocity isNil ifTrue:[self velocity: 0@0]. ^ velocity! ! !Sly3Boid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! velocity: anObject "Set the value of velocity" velocity _ anObject! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:00'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." ^ (self flock boids members collect: [:m| m position]) average! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:01'! computeNeighbors ^self flock boids members select:[:m| m isNear: self]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:07'! draw | p | self lastDrawnPosition = self position ifTrue: [^ self]. p _ self position. false ifTrue: [ Sly3Graphics drawWhiteCircle: self lastDrawnPosition. Sly3Graphics drawCircle: p. "Sly3Graphics drawFrom: self lastDrawnPosition to: p." ] ifFalse: [ Sly3Graphics drawFrom: self lastDrawnPosition to: p. Sly3Graphics eraseFrom: self lastLastDrawnPosition to: self lastDrawnPosition. ]. self lastLastDrawnPosition: self lastDrawnPosition. self lastDrawnPosition: p! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:22'! fly | centroid | [Sly3 keepFlying] whileTrue:[ centroid _ self computeCentroid. self moveToNewPosition: centroid. self flock maybeYield ]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:15'! go self fly! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:43'! isNear: aBoid ^ (self ~== aBoid) and: [(self position dist: aBoid position) <= 10]! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:04'! keepAwayFromNeighbors | sum | self neighbors ifEmpty: [^ 0@0]. sum _ 0. self neighbors do: [:m | sum _ sum + (self position - m position)]. ^ sum / self neighbors size asFloat! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:30'! limitPositionFrom: min to: max | r pos | pos _ self position. r _ ((pos max: min@min) min: max@max). r = pos ifTrue: [^ self]. pos x < min ifTrue: [r _ min + (min - pos x) @ pos y. self velocity: self velocity x negated @ self velocity y]. pos y < min ifTrue: [r _ pos x @ (min + (min - pos y)). self velocity: self velocity x @ self velocity y negated]. pos x > max ifTrue: [r _ max - (pos x - max) @ pos y. self velocity: self velocity x negated @ self velocity y ]. pos y > max ifTrue: [r _ pos x @ (max - (pos y - max)). self velocity: self velocity x @ self velocity y negated]. self position: r! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:36'! limitVelocityTo: n | ns v vs q | ns _ n * n * 2. v _ self velocity. vs _ v x squared + v y squared. vs <= ns ifTrue: [^ self]. q _ (ns / vs) sqrt. self velocity: v * q.! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 15:54'! matchVelocityWithNeighbors self neighbors size = 0 ifTrue: [^ 0@0]. ^ (self neighbors collect: [:m| m velocity]) average / 8.0! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:04'! moveToNewPosition: centroid | a b c | self neighbors: self computeNeighbors. a _ self moveTowardCentroidOfAllOthers: centroid. b _ self keepAwayFromNeighbors. c _ self matchVelocityWithNeighbors. self velocity: self velocity + a + b + c. self limitVelocityTo: 10. self position: self position + self velocity. self limitPositionFrom: 0 to: 1000! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:16'! moveTowardCentroidOfAllOthers: centroid | perceivedCentroid s | "collectionLYSize introduces overhead." s _ self flock boids collectionLYsize. s < 2 ifTrue: [^ 0@0]. perceivedCentroid _ (centroid * s - self position) / (s - 1). ^ (perceivedCentroid - self position) / 100.0! ! !Sly3Boid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:54'! perturb self position: (self position perturb: 100). self velocity: (self velocity perturb: 2).! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:52'! boidClass ^ Sly3Boid! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:29'! drawerClass ^ Sly3Drawer! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'ads 2/2/2011 14:55'! flockSize "RVMOperations coreCount - 6 max: 10". ^ 30! ! !Sly3Boids methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:58'! run "Transcript show: (Time millisecondsToRun: [Sly3Boids new run]); cr" "[ Sly3Boids new run ] fork" | c flock drawer flockAndDrawer n | c _ OrderedCollection new. n _ self flockSize. 1 to: n do: [:i| c add: self boidClass new perturb]. flock _ Sly3Flock boids: c asEnsembleOfElements. flock boids flock: flock. drawer _ self drawerClass flock: flock. flockAndDrawer _ %{flock. drawer}. "SlyGraphics clearScreen." flockAndDrawer go ! ! !Sly3Boids class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:30'! run ^ self new run! ! !Sly3Drawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: nil]. ^ flock! ! !Sly3Drawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock: anObject "Set the value of flock" flock _ anObject! ! !Sly3Drawer methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:28'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids members do: [:b| b draw]]! ! !Sly3Drawer class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:07'! flock: f ^ self new flock: f! ! !Sly3Ensemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 23:48'! select: aBlock ^ self members select: aBlock! ! !Sly3Ensemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:25'! totalWithIdentity: id ^ self plus: id adverb: #reductively! ! !Sly3Ensemble methodsFor: 'environment support' stamp: 'dmu 8/29/2010 12:53'! doesNotUnderstand: aMessage "Try to process this message as an ensemble dispatch message to help in the case of inlined primitive calls like perform:with:with:" ^ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage theEnsemble: self)! ! !Sly3Ensemble methodsFor: 'environment support' stamp: 'dmu 3/29/2010 01:04'! ensembleSpecies ^ Sly3Ensemble! ! !Sly3Ensemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:14'! explorerContents ^self members asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !Sly3Ensemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:15'! hasContentsInExplorer ^self members isEmpty not! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:05'! add: anObject members add: anObject! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'ssa 6/17/2010 10:29'! members "you should never trust that the members collection stays the same within the ensemble" ^members copy! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/19/2010 22:53'! members: aCollection "crude check:" self primitiveSetExtraWordSelector: #sentToEnsemble:. aCollection primitiveSetExtraPreheaderWord: self. members _ aCollection. ^ self! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:05'! remove: anObject members remove: anObject! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 9/23/2010 13:06'! remove: anObject ifAbsent: blk ^ members remove: anObject ifAbsent: blk! ! !Sly3Ensemble methodsFor: 'membership' stamp: 'dmu 8/30/2010 01:53'! size ^ members size! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 16:35'! asExplorerString ^self printString! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:50'! printOn: out "Add a string that should compile back into an ensemble like me" out nextPutAll:'%{'. self members do:[:mem| mem printOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ! ! !Sly3Ensemble methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:51'! storeOn: out "Write a string on aStream that should compile back into an ensemble like me" out nextPut:$%;nextPut:${. self members do:[:mem| mem storeOn: out. out nextPut:$.]. out nextPut:$}. ! ! !Sly3Ensemble methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:55'! ifEmpty: blk ^ self collecitonLYsize = 0 ifTrue: [blk value]! ! !Sly3Ensemble methodsFor: 'testing' stamp: 'dmu 9/3/2010 14:54'! isEnsemble "Sly3Ensemble overrides to true" ^true! ! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/7/2010 11:13'! deactivateEnsembleSendsFor: anEnsemble during: aBlock "disable messaging dispatching to members and just send it to the ensemble object itself during aBlock" | members r | members _ anEnsemble members. 0 primitiveSetExtraPreheaderWord: anEnsemble. r _ aBlock ensure: [members primitiveSetExtraPreheaderWord: anEnsemble. ]. ^ r ! ! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:37'! withMembersFrom: aCollection ^ self new members: aCollection! ! !Sly3Ensemble class methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:39'! withSoleMember: anObject ^ self withMembersFrom: {anObject}! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 19:04'! originalArguments ^ self unprocessedMessage arguments! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:49'! parsedMessage "Answer the value of parsedMessage" parsedMessage isNil ifTrue:[self parsedMessage: nil]. ^ parsedMessage! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/29/2010 18:49'! parsedMessage: anObject "Set the value of parsedMessage" parsedMessage _ anObject! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'ssa 5/12/2010 19:32'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !Sly3EnsembleMessageDispatcher methodsFor: 'accessing' stamp: 'dmu 8/27/2010 14:29'! setAsAWhole self isAsAWhole: true! ! !Sly3EnsembleMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 9/1/2010 23:18'! dispatch self parsedMessage: self parseMessage. self parsedMessage ifNil: [^ self]. ^ self doneBlock value: ( Sly3MessageEvaluator evaluate: self parsedMessage ) ! ! !Sly3EnsembleMessageDispatcher methodsFor: 'ensemble behavior' stamp: 'dmu 8/29/2010 19:00'! storeStringForMyEnsemble "Answer a string that should compile back into an ensemble like me" | out | out _ WriteStream on:''. out nextPutAll:'%{'. self unprocessedMessage members do:[:mem| mem storeOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ^out contents! ! !Sly3EnsembleMessageDispatcher methodsFor: 'parsing message' stamp: 'dmu 8/29/2010 21:54'! parseMessage ^ Sly3MessageParser parse: self unprocessedMessage ! ! !Sly3EnsembleMessageDispatcher class methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 12:27'! dispatch: anUnprocessedMessage andDo: doneBlock | newMessage | Sly3ReflectiveMessageDispatcher dispatch: anUnprocessedMessage andDo: [:r| ^ doneBlock value: r]. newMessage _ Sly3ReflectiveSelectorChanger modifyAsNeeded: anUnprocessedMessage. ^super dispatch: newMessage andDo: doneBlock! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! members "Answer the value of members" members isNil ifTrue:[self members: nil]. ^ members! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! members: anObject "Set the value of members" members _ anObject! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! theEnsemble "Answer the value of theEnsemble" theEnsemble isNil ifTrue:[self theEnsemble: nil]. ^ theEnsemble! ! !Sly3EnsembleMirror methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:25'! theEnsemble: anObject "Set the value of theEnsemble" theEnsemble _ anObject! ! !Sly3EnsembleMirror class methodsFor: 'as yet unclassified' stamp: 'dmu 9/5/2010 15:27'! forEnsemble: e members: m ^ self new theEnsemble: e; members: m; yourself! ! !Sly3EnsembleMirror class methodsFor: 'as yet unclassified' stamp: 'dmu 9/5/2010 15:27'! forObject: obj self new theEnsemble: obj; members: (obj wholLYisEnsemble ifTrue: [obj collectionLY] ifFalse: [obj]); yourself! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:39'! boids "Answer the value of boids" ^ boids! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:11'! boids: anObject "Set the value of boids" boids _ anObject! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone "Answer the value of isDone" isDone isNil ifTrue:[self isDone: false]. ^ isDone! ! !Sly3Flock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone: anObject "Set the value of isDone" isDone _ anObject! ! !Sly3Flock methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:13'! go self isDone: false. boids fly. self isDone: true! ! !Sly3Flock methodsFor: 'as yet unclassified' stamp: 'dmu 9/7/2010 17:32'! maybeYield | n | "[Processor yield. ^self]value." Sly3 serializeForDebugging ifTrue: [Processor yield. ^ self]. n _self boids collectionLYsize + 1 "1 for Drawer". Processor yieldIfFewerCoresThan: n! ! !Sly3Flock class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:11'! boids: b ^ self new boids: b! ! !Sly3Gerund methodsFor: 'testing' stamp: 'dmu 9/3/2010 22:16'! isIndirect ^ false! ! !Sly3Gerund methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 14:13'! reduceForEvaluator: ev self subclassResponsibility! ! !Sly3Gerund class methodsFor: 'testing' stamp: 'dmu 9/1/2010 23:44'! isGerund ^ true! ! !Sly3Gerund class methodsFor: 'testing' stamp: 'dmu 8/30/2010 18:38'! uppercaseSuffix ^ 'ING'! ! !Sly3Gerund class methodsFor: 'as yet unclassified' stamp: 'dmu 9/12/2010 21:24'! defaultGerund ^Sly3ModEnsembling! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! clearScreen Display fillWhite! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! drawCircle: pt Display drawDot5At: pt! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:03'! drawFrom: ptA to: ptB Display drawLineFrom: ptA to: ptB color: Color black! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:04'! drawWhiteCircle: pt Display eraseDot5At: pt! ! !Sly3Graphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/23/2010 00:02'! eraseFrom: ptA to: ptB Display eraseLineFrom: ptA to: ptB color: Color black! ! !Sly3MessageEnvelope methodsFor: 'delivering' stamp: 'dmu 9/21/2010 00:24'! deliver "send my message to my receiver and return the reply" | e | 1 to: deactivateEnsembleBehaviorFlags size do: [:i| (deactivateEnsembleBehaviorFlags at: i) ifTrue: [ e _ i = 1 ifTrue: [ receiver] ifFalse: [message arguments at: i - 1]. ^ Sly3Ensemble deactivateEnsembleSendsFor: e during: [(self copy at: i putDeactivateEnsembleBehaviorFlag: false) deliver] ] ]. self message arguments: self message arguments asArray. ^self message sentTo: self receiver! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 15:43'! at: rcvrArgIndex putDeactivateEnsembleBehaviorFlag: aBool deactivateEnsembleBehaviorFlags at: rcvrArgIndex put: aBool! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 15:35'! deactivateEnsembleBehaviorFlags: x deactivateEnsembleBehaviorFlags _ x! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:03'! message: anObject "Set the value of message" message _ anObject. ! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'dmu 9/3/2010 21:27'! receiver ^ receiver! ! !Sly3MessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3MessageEnvelope methodsFor: 'printing' stamp: 'dmu 9/3/2010 16:51'! printOn: aStream aStream nextPutAll:'MsgEnv|rcvr:',self receiver wholLYprintString,'|message: ',self message printString! ! !Sly3MessageEnvelope class methodsFor: 'instance creation' stamp: 'dmu 9/3/2010 15:35'! argumentCount: n ^self new message: (Message selector: #none arguments: (Array new: n)); deactivateEnsembleBehaviorFlags: ((Array new: n + 1) collect: [:x| false]); yourself! ! !Sly3MessageEnvelope class methodsFor: 'instance creation' stamp: 'ssa 5/27/2010 10:46'! receiver: anObject selector: aSymbol arguments: anArray ^self new receiver: anObject; message: (Message selector: aSymbol arguments: anArray); yourself! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:55'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:55'! message: anObject "Set the value of message" message _ anObject! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/22/2010 22:05'! putResultsIntoAnEnsemble ^ putResultsIntoAnEnsemble! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/4/2010 15:34'! result ^ result! ! !Sly3MessageEvaluator methodsFor: 'accessing' stamp: 'dmu 9/4/2010 15:33'! result: r result _ r! ! !Sly3MessageEvaluator methodsFor: 'post-processing' stamp: 'dmu 9/4/2010 15:34'! evaluateGerunds message gerunds reverseDo: [:g| g reduceForEvaluator: self]. ^ result! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 16:26'! buildOperandTuples | mems | operandTuples _ OrderedCollection new. operandTuples _ self operandTuplesForObject: message receiver membersOrNil: message members adverbs: message messageAdverbs operandTuplesSoFar: operandTuples. message arguments with: message argumentAdverbs do: [:arg :ads | mems _ arg collectionLY. operandTuples _ self operandTuplesForObject: arg membersOrNil: mems adverbs: ads operandTuplesSoFar: operandTuples]. ^ operandTuples! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:54'! calculatePutResultsIntoAnEnsemble ((message messageAdverbs select: [:mm| mm isOperandDistributor]) anySatisfy: [:m | m putResultsIntoAnEnsemble]) ifTrue: [^ true]. ^ message argumentAdverbs anySatisfy: [:aa| (aa select: [:mm| mm isOperandDistributor]) anySatisfy: [:m | m putResultsIntoAnEnsemble] ] ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'sm 2/19/2011 11:53'! evaluate | r | "message selector = #particle:ofSize:movedTo: ifTrue: [self halt]." putResultsIntoAnEnsemble _ false. operandTuples _ self buildOperandTuples. envelopes _ self makeEnvelopes. self stuffSelectors. self stuffReceivers. self stuffArguments. self relocateReceiversIfNeeded. self relocateArgumentsIfNeeded. self setDisableEnsembleBehaviorFlags. result _ self sendMessages. putResultsIntoAnEnsemble _ self calculatePutResultsIntoAnEnsemble. r _ self evaluateGerunds. ^ r ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 16:16'! operandTuplesForObject: operand membersOrNil: mems adverbs: ads operandTuplesSoFar: operandTuplesSoFar | ods operandTuplesIncludingThisOne | "Return the factor by which to multiply the number of envelopes for this operand." ods _ ads select: [:ad| ad isOperandDistributor]. operandTuplesIncludingThisOne _ ods last extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: mems. ods removeLast. ods reverseDo: [:operandDistributor | operandTuplesIncludingThisOne _ operandDistributor amendOperandTuples: operandTuplesIncludingThisOne ]. ^ operandTuplesIncludingThisOne! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 8/30/2010 01:27'! relocateArgumentsIfNeeded "Supports argument adverbs that desire to be in special core locations relative to each other or to their receiving members. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 8/30/2010 01:26'! relocateReceiversIfNeeded "Supports message adverbs that desire to have member in special core locations relative to each other or to arguments. Examples: #locally (same core) #globally (anywhere is fine) #closely (nearby cores) #distantly (on distant cores from each other. may need a parameter here for Manhattan distance apart) #evenly (spread over cores so each core has same number) #statically (don't relocate under any circumstances) Default case is #globally, i.e., no relocation. Others to be implemented later." ! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/21/2010 00:26'! sendMessages "Deliver the message envelopes and collect results. This must eventually handle adverbs for timing and recurring messages, determining when the ensemble message is 'done'. etc. For now, do the simplest thing, a parallelCollect:" | payloadBlock | payloadBlock _ [:env| Processor thisProcess creatorEnsemble: env receiver. env deliver]. "check for serially flag and handle appropriately" ^(message messageAdverbs anySatisfy: [:ad| ad isKindOf: Sly3ModSerially]) ifTrue:[ envelopes collect: payloadBlock] ifFalse:[ envelopes parallelCollect: payloadBlock]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:21'! stuffArguments envelopes with: operandTuples do: [:e :ot| 1 to: ot size -1 do: [:i| e message arguments at: i put: (ot at: i + 1)]]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/23/2010 15:18'! stuffReceivers envelopes with: operandTuples do: [:e :ot| e receiver: ot first]! ! !Sly3MessageEvaluator methodsFor: 'evaluating-modified' stamp: 'dmu 9/13/2010 00:13'! stuffSelectors "placeholder; could vary" envelopes do: [:e| e message setSelector: message selector]! ! !Sly3MessageEvaluator methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:17'! makeEnvelopes ^ (Array new: operandTuples size) collect: [:x|Sly3MessageEnvelope argumentCount: message arguments size]! ! !Sly3MessageEvaluator methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:35'! setDisableEnsembleBehaviorFlags | deactivateEnsembleBehaviorFlags | deactivateEnsembleBehaviorFlags _ ((OrderedCollection with: message messageAdverbs) addAll: message argumentAdverbs; yourself) collect: [:adverbs | adverbs anySatisfy: [:adverb| adverb isOperandDistributor and: [adverb shouldDisableEnsembleBehavior]]]. envelopes do: [:e|e deactivateEnsembleBehaviorFlags: deactivateEnsembleBehaviorFlags]! ! !Sly3MessageEvaluator class methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 21:55'! evaluate: message | r | r _ self new message: message; evaluate. ^ r! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 9/3/2010 19:44'! arguments ^ arguments! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:21'! parsedMessage "Answer the value of parsedMessage" parsedMessage isNil ifTrue:[self parsedMessage: nil]. ^ parsedMessage! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:21'! parsedMessage: anObject "Set the value of parsedMessage" parsedMessage _ anObject! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:22'! unparsedMessage "Answer the value of unparsedMessage" unparsedMessage isNil ifTrue:[self unparsedMessage: nil]. ^ unparsedMessage! ! !Sly3MessageParser methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:22'! unparsedMessage: anObject "Set the value of unparsedMessage" unparsedMessage _ anObject! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 21:17'! breakKeywordModifiersForArguments | s allOperandMods directsAndStrings argDirectMods argIndirectMods | s _ ReadStream on: foldedFlatStringsAndModifiers. allOperandMods _ OrderedCollection with: (self breakModifiersForReceiverIn: s). [s atEnd] whileFalse: [ directsAndStrings _ self nextOnesIn: s suchThat: [:x| (self isDirect: x) or: [self isNonKeywordString: x]]. argDirectMods _ directsAndStrings select: [:x | self isDirect: x]. (self isKeyword: s peek) ifFalse: [self error: 'expected keyword']. s next. argIndirectMods _ self nextOnesIn: s suchThat: [:x | self isIndirect: x]. allOperandMods addLast: argDirectMods, argIndirectMods. ]. ^ allOperandMods! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/16/2010 23:24'! breakModifiersForArguments | | arguments isEmpty ifTrue: [ ^ self breakUnaryModifiersForArguments]. unparsedSelector isInfix ifTrue: [ ^ OrderedCollection with: (OrderedCollection new) with: (OrderedCollection new) ]. ^ self breakKeywordModifiersForArguments! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 20:54'! breakModifiersForReceiverIn: s | rcvrDirectMods rcvrIndirectMods | rcvrDirectMods _ self nextOnesIn: s suchThat: [:x| self isDirect: x]. rcvrIndirectMods _ self nextOnesIn: s suchThat: [:x| self isIndirect: x]. ^ rcvrDirectMods, rcvrIndirectMods! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/12/2010 20:45'! breakUnaryModifiersForArguments ^ OrderedCollection with: (foldedFlatStringsAndModifiers select: [:x | x isKindOf: Sly3AbstractModifier])! ! !Sly3MessageParser methodsFor: 'assigning modifiers to arguments' stamp: 'dmu 9/13/2010 00:02'! foldInIndirectModifiers: blk | stringsAndMods args inStringsAndMods inArgs s | stringsAndMods _ OrderedCollection new. args _ OrderedCollection new. inStringsAndMods _ ReadStream on: flatKeywordsAndModifiers. inArgs _ ReadStream on: arguments. [inStringsAndMods atEnd] whileFalse: [ s _ inStringsAndMods next. (s isKindOf: String) ifTrue: [ stringsAndMods addLast: s. (s notEmpty and: [(s last = $:) or: [s first isLetter not]]) ifTrue: [args addLast: inArgs next]. ] ifFalse: [ s isIndirect ifTrue: [ s parameter: inArgs next. ]. stringsAndMods addLast: s. ] ]. blk value: stringsAndMods contents value: args asArray! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:18'! isDirect: x ^ (self isModifier: x) and: [x isDirect]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:18'! isIndirect: x ^ (self isModifier: x) and: [x isIndirect]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:17'! isKeyword: x ^ (self isString: x) and: [x last = $:]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:17'! isModifier: x ^ x isKindOf: Sly3AbstractModifier! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/13/2010 00:03'! isNonKeywordString: x ^ (self isString: x) and: [x isEmpty or: [x last ~= $:]]! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:16'! isString: x ^ x isKindOf: String! ! !Sly3MessageParser methodsFor: 'testing' stamp: 'dmu 9/12/2010 20:21'! nextOnesIn: aStream suchThat: testBlk | result | result _ OrderedCollection new. [ (aStream atEnd not and: [testBlk value: aStream peek]) ifFalse: [^ result]. result addLast: aStream next ] repeat! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/21/2010 00:23'! addDefaultModifiersTo: allMods | r rcvr ms defaultClass ods addDefault | r _ OrderedCollection new. rcvr _ true. allMods do: [:mods | ms _ mods copy. defaultClass _ rcvr ifTrue: [Sly3Adverb defaultReceiverOperandDistributor] ifFalse: [Sly3Adverb defaultArgumentOperandDistributor]. ods _ mods select: [:x|x isOperandDistributor]. addDefault _ ods isEmpty. addDefault ifTrue: [ms addFirst: defaultClass new]. (rcvr and: [mods noneSatisfy:[:x| x isGerund]]) ifTrue: [ms addFirst: Sly3Gerund defaultGerund new]. r addLast: ms. rcvr _ false. ]. ^ r! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/3/2010 19:44'! createParsedMessage. ^ Sly3ParsedMessage receiver: self unparsedMessage receiver members: self unparsedMessage members messageModifiers: messageModifiers selector: actualSelector arguments: self arguments argumentAdverbs: argumentModifiers ! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 9/3/2010 19:52'! gatherActualSelector | sel | sel _ ((foldedFlatStringsAndModifiers select: [:a| a isKindOf: String]) gather: [:a | a ]) as: Symbol. ^ sel ifEmpty: [#yourself] ifNotEmpty: [sel]! ! !Sly3MessageParser methodsFor: 'parsing' stamp: 'dmu 4/12/2011 14:13'! parse unparsedSelector _ self unparsedMessage selector. [unparsedSelector = #mustBeBoolean ifTrue: [self halt].]. arguments _ self unparsedMessage arguments. flatStringsAndModifiers _ self dissectSelectorIntoStringsAndModifiers: unparsedSelector. flatKeywordsAndModifiers _ self breakStringsIntoKeywords: flatStringsAndModifiers. self foldInIndirectModifiers: [:s :a | foldedFlatStringsAndModifiers _ s. arguments _ a]. actualSelector _ self gatherActualSelector. modifiersForRcvrAndArgs _ self breakModifiersForArguments. modifiersWithDefaults _ self addDefaultModifiersTo: modifiersForRcvrAndArgs. messageModifiers _ modifiersWithDefaults first. argumentModifiers _ modifiersWithDefaults copyWithoutFirst. parsedMessage _ self createParsedMessage.! ! !Sly3MessageParser methodsFor: 'dissecting selector' stamp: 'dmu 9/13/2010 00:09'! breakStringsIntoKeywords: inCol | in out x inin outout c | in _ ReadStream on: inCol. out _ WriteStream on: (Array new: inCol size * 2). [in atEnd] whileFalse: [ x _ in next. (x isKindOf: String) ifFalse: [ out nextPut: x] ifTrue: [ inin _ ReadStream on: x. outout _ WriteStream on: (String new: x size). [inin atEnd] whileFalse: [ c _ inin next. outout nextPut: c. c = $: ifTrue: [ out nextPut: (outout contents). outout _ WriteStream on: (String new: x size). ] ]. outout isEmpty ifFalse: [out nextPut: (outout contents)] ] ]. ^ out contents asOrderedCollection! ! !Sly3MessageParser methodsFor: 'dissecting selector' stamp: 'dmu 5/30/2011 12:11'! dissectSelectorIntoStringsAndModifiers: aString "break up a sequence of characters that are part of a selector" "returns a collection of Strings and Sly3AbstractModifier s" "Examples: snortLY -> adverb is snort selectorPart is empty snortLYfoo -> adverb is snort selectorPart is foo fooSnortLY -> selector part is foo, adverb is Snort" "Sly3MessageParser new breakIntoStringsAndModifiers: #serialLYRoundLYatRoundLY:atRoundLY:atRoundLY:atRoundLY:put:valueLY:" | lastStart i parts modifierString foundSuffix end nextWord c endWord charAfterSuffixIndex pastModifierIndex | parts _ OrderedCollection new. lastStart _ 1. i _ 1. [i <= aString size] whileTrue: [ foundSuffix _ nil. Sly3AbstractModifier allUppercaseSuffixes do: [:suffix| end _ i + suffix size - 1. (aString size >= end and: [ (aString copyFrom: i to: i + suffix size - 1) = suffix ]) ifTrue: [ foundSuffix ifNil: [foundSuffix _ suffix] ifNotNil: [self error: 'ambiguous'] ] ]. foundSuffix ifNotNil: [ charAfterSuffixIndex _ i + foundSuffix size. modifierString _ aString copyFrom: lastStart to: i - 1. parts addLast: (Sly3AbstractModifier instantiateSpecificFromBaseName: modifierString includingSuffix: foundSuffix). parts last isIndirect ifTrue: [ ((aString size >= charAfterSuffixIndex) and: [(aString at: charAfterSuffixIndex) = $:]) ifFalse: [self error: 'indirect modifier should have colon']. ]. pastModifierIndex _ charAfterSuffixIndex + (parts last isIndirect ifTrue: [1] ifFalse: [0]). lastStart _ i _ pastModifierIndex. ] ifNil: [ c _ aString at: i. (c isUppercase or: [c = $:]) ifTrue: [ endWord _ c = $: ifTrue: [i] ifFalse: [i - 1]. nextWord _ aString copyFrom: lastStart to: endWord. parts addLast: ( (parts notEmpty and: [(parts last isKindOf: String) and: [('X', parts last) last ~= $:]]) ifFalse: [nextWord] ifTrue: [parts removeLast, nextWord ]). lastStart _ endWord + 1 ]. i _ i + 1 ] ]. lastStart <= aString size ifTrue: [ nextWord _ aString copyFrom: lastStart to: aString size. parts addLast: ( (parts notEmpty and: [parts last isKindOf: String]) ifFalse: [nextWord] ifTrue: [parts removeLast, nextWord capitalized])]. ^ parts ! ! !Sly3MessageParser class methodsFor: 'as yet unclassified' stamp: 'dmu 8/29/2010 21:22'! parse: m ^self new unparsedMessage: m; parse; parsedMessage! ! !Sly3ModAnding methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each & result]. ev result: result! ! !Sly3ModAveraging methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:42'! reduceForEvaluator: ev | sum results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. sum _ results sum. ev result: sum / results size ! ! !Sly3ModCollectionly methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 00:46'! amendOperandTuples: operandTuplesIncludingThisOne | ens | ens _ (operandTuplesIncludingThisOne collect: [:ot| ot last]). ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ens; yourself]! ! !Sly3ModCollectionly methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ false! ! !Sly3ModCollectionly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:01'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [OrderedCollection with: (OrderedCollection with: mems)] ifNotEmpty: [ operandTuplesSoFar collect: [:tuple | tuple copy addLast: mems; yourself]]! ! !Sly3ModCollectionly commentStamp: 'dmu 9/3/2010 16:55' prior: 0! Use members collection of the ensemble! !Sly3ModConcatenating methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:33'! reduceForEvaluator: ev "Concatenate each element in results and return the result. Assumes these elements are collections of some kind." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ result , each]. ev result: result! ! !Sly3ModDuplicatively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:15'! amendOperandTuples: operandTuplesIncludingThisOne ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ot last copy; yourself]! ! !Sly3ModDuplicatively methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 14:46'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [operandMembers collect: [:m| OrderedCollection with: m copy]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. r _ OrderedCollection new. operandTuplesSoFar with: mems do: [:ot :m| r addLast: (ot copy addLast: m copy; yourself)]. r]! ! !Sly3ModDuplicatively commentStamp: 'dmu 9/1/2010 15:58' prior: 0! each member gets a copy of the arguments! !Sly3ModEnsembling methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:05'! reduceForEvaluator: ev | results | results _ ev result. ev result: ( ev putResultsIntoAnEnsemble ifTrue: [results asEnsembleOfElements] ifFalse: [results size = 1 ifTrue: [results first] ifFalse: [self error: 'no ensembles dismembered, but yet results have ', results size printString, ' elements']])! ! !Sly3ModGathering methodsFor: 'as yet unclassified' stamp: 'dmu 11/29/2010 19:37'! reduceForEvaluator: ev | results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. ev result: (results gather: [:x | x]) asEnsembleOfElements! ! !Sly3ModIndividually methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:10'! amendOperandTuples: operandTuplesIncludingThisOne operandTuplesIncludingThisOne size > 1 ifTrue: [^ self error: 'what?']. ^ operandTuplesIncludingThisOne first last members collect: [:m| operandTuplesIncludingThisOne first copy addLast: m; yourself ]! ! !Sly3ModIndividually methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:53'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [operandMembers collect: [:m| OrderedCollection with: m]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. operandTuplesSoFar with: mems collect: [:ot :m| ot copy addLast: m; yourself]. ]! ! !Sly3ModIndividually commentStamp: 'dmu 4/12/2011 12:32' prior: 0! Meaning: use my members in parallel. This is the default modifier for the receiver. For arguments, it creates a parallel thread for each member of the argument ensemble. The receiver arity must match this argument's arity.! !Sly3ModMaxing methodsFor: 'as yet unclassified' stamp: 'dmu 11/29/2010 18:53'! reduceForEvaluator: ev "Sum the elements in results and return the result. Assumes these elements understand +." | results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. ev result: results max! ! !Sly3ModMining methodsFor: 'as yet unclassified' stamp: 'dmu 11/29/2010 18:53'! reduceForEvaluator: ev "Sum the elements in results and return the result. Assumes these elements understand +." | results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. ev result: results min! ! !Sly3ModOring methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev "OR the elements in results and return the result. Assumes these elements understand |." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ results first. results allButFirst do:[:each| result _ each | result]. ev result: result! ! !Sly3ModPlainly methodsFor: 'testing' stamp: 'dmu 9/3/2010 15:41'! shouldDisableEnsembleBehavior ^ true! ! !Sly3ModPlainly commentStamp: 'dmu 9/3/2010 14:28' prior: 0! Disable all ensemble processing for the recursive duration of this send! !Sly3ModRandomly methodsFor: 'accessing' stamp: 'dmu 9/3/2010 18:12'! parameter "Answer the value of parameter" parameter isNil ifTrue:[self parameter: 1]. ^ parameter! ! !Sly3ModRandomly methodsFor: 'accessing' stamp: 'dmu 9/3/2010 19:46'! randomNumberSource RandomNumberSource isNil ifTrue:[RandomNumberSource _ Random new]. ^RandomNumberSource! ! !Sly3ModRandomly methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:16'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3ModRandomly methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 00:44'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [ (1 to: parameter) collect: [:m| OrderedCollection with: (mems atRandom: self randomNumberSource)] ] ifNotEmpty: [ r _ OrderedCollection new. parameter timesRepeat: [ r addAll: (operandTuplesSoFar collect: [:t| t copy addLast: (mems atRandom: self randomNumberSource); yourself]). ]. r ]! ! !Sly3ModRoundly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:14'! amendOperandTuples: operandTuplesIncludingThisOne | mems r | mems _ operandTuplesIncludingThisOne collect: [:tup | tup last]. r _ OrderedCollection new. operandTuplesIncludingThisOne do: [:ot| mems do: [:m| r add: (ot copy removeLast; addLast: m; yourself) ] ]. ^ r! ! !Sly3ModRoundly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:32'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [mems asOrderedCollection collect: [:m| OrderedCollection with: m]] ifNotEmpty: [ r _ OrderedCollection new. 1 to: operandMembers size do: [:i | r addAll: (operandTuplesSoFar collect: [:t| t copy addLast: (mems at: i); yourself]).. ]. r ]! ! !Sly3ModRoundly commentStamp: 'dmu 9/1/2010 15:58' prior: 0! distribute args over members round-robin fashion, repeating members as needed. Think of members here as a Resource Pool. This will require collaboration with any message adverbs.! !Sly3ModSelecting methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:59'! reduceForEvaluator: ev | results members r | results _ ev result. members _ ev message members. r _ OrderedCollection new. members with: results do: [:m :res | res ifTrue: [r add: m]]. ev result: r asEnsembleOfElements! ! !Sly3ModSelectively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 15:12'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3ModSelectively methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 16:03'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [self error: 'cannot be used for receiver'] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'sizes']. mems _ mems copy asOrderedCollection. operandTuplesSoFar select: [:ot | mems removeFirst] ]! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:51'! cachedEns self unimplemented: 'must get receiver and arg ens and construct a selected ensemble'. ^ cachedEns! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedEns: anObject "Set the value of cachedEns" cachedEns _ anObject! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedMod "Answer the value of cachedMod" cachedMod isNil ifTrue:[self cachedMod: nil]. ^ cachedMod! ! !Sly3ModSerially methodsFor: 'accessing' stamp: 'dmu 9/1/2010 15:49'! cachedMod: anObject "Set the value of cachedMod" cachedMod _ anObject! ! !Sly3ModStandardDeviationing methodsFor: 'as yet unclassified' stamp: 'dmu 11/29/2010 18:53'! reduceForEvaluator: ev "Sum the elements in results and return the result. Assumes these elements understand +." | results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. ev result: results standardDeviation! ! !Sly3ModTotalling methodsFor: 'as yet unclassified' stamp: 'dmu 9/4/2010 15:35'! reduceForEvaluator: ev "Sum the elements in results and return the result. Assumes these elements understand +." | result results | results _ ev result. results isEmpty ifTrue:[self error:'No members, how should we handle? proceed for nil'. ^nil]. result _ 0. results do:[:each| result _ each + result]. ev result: result! ! !Sly3ModValuely methodsFor: 'multiple adverb support' stamp: 'dmu 9/23/2010 15:16'! amendOperandTuples: operandTuplesIncludingThisOne self error: 'unimp'! ! !Sly3ModValuely methodsFor: 'multiple adverb support' stamp: 'dmu 9/24/2010 14:48'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers | r mems | mems _ operandMembers ifNil: [OrderedCollection with: operand] ifNotNil: [operandMembers]. ^ operandTuplesSoFar ifEmpty: [mems collect: [:m| OrderedCollection with: (parameter value: m)]] ifNotEmpty: [ operandTuplesSoFar size = mems size ifFalse: [self error: 'mismatch in number']. r _ OrderedCollection new. operandTuplesSoFar with: mems do: [:ot :m| r addLast: (ot copy addLast: (parameter value: m); yourself)]. r]! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/24/2010 00:47'! amendOperandTuples: operandTuplesIncludingThisOne | ens | ens _ (operandTuplesIncludingThisOne collect: [:ot| ot last]) asEnsembleOfElements. ^ operandTuplesIncludingThisOne collect: [:ot| ot copy removeLast; addLast: ens; yourself]! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/22/2010 22:00'! doNotDismember ^ true! ! !Sly3ModWholly methodsFor: 'as yet unclassified' stamp: 'dmu 9/23/2010 14:46'! extendOperandTuples: operandTuplesSoFar operand: operand membersOrNil: operandMembers ^ operandTuplesSoFar ifEmpty: [OrderedCollection with: (OrderedCollection with: operand)] ifNotEmpty: [ operandTuplesSoFar collect: [:tuple | tuple copy addLast: operand; yourself]]! ! !Sly3ModWholly methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ false! ! !Sly3ModWholly commentStamp: 'dmu 9/1/2010 15:57' prior: 0! batch all args to each member with the message! !Sly3OperandDistributor methodsFor: 'result handling' stamp: 'dmu 9/22/2010 22:03'! putResultsIntoAnEnsemble ^ true! ! !Sly3OperandDistributor methodsFor: 'testing' stamp: 'dmu 9/19/2010 20:52'! isOperandDistributor ^ true! ! !Sly3OperandDistributor methodsFor: 'testing' stamp: 'dmu 9/19/2010 20:59'! shouldDisableEnsembleBehavior ^ false! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! argumentAdverbs "Answer the value of argumentAdverbs" argumentAdverbs isNil ifTrue:[self argumentAdverbs: nil]. ^ argumentAdverbs! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/3/2010 20:29'! argumentAdverbs: collectionPerArgument "Set the value of argumentModifiers" (collectionPerArgument anySatisfy: [:x | x anySatisfy: [:a | a isAdverb not]]) ifTrue: [self error: 'only adverbs for arguments']. argumentAdverbs _ collectionPerArgument asArray! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! argumentMirrors "Answer the value of argumentMirrors" argumentMirrors isNil ifTrue:[self argumentMirrors: nil]. ^ argumentMirrors! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! argumentMirrors: anObject "Set the value of argumentMirrors" argumentMirrors _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:36'! arguments "Answer the value of arguments" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. arguments isNil ifTrue:[self arguments: nil]. ^ arguments! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! arguments: anObject "Set the value of arguments" arguments _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 16:34'! gerunds gerunds ifNil: [gerunds _ {}]. ^ gerunds! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! gerunds: anObject "Set the value of gerunds" gerunds _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:36'! members "Answer the value of members" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. members isNil ifTrue:[self members: nil]. ^ members! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! members: anObject "Set the value of members" members _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 16:46'! messageAdverbs ^ messageAdverbs ifNil: [messageAdverbs _ {}] ifNotNil: [messageAdverbs]! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/1/2010 23:05'! messageAdverbs: anObject "Set the value of messageAdverbs" messageAdverbs _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/12/2010 21:19'! messageModifiers: anObject "Set the value of messageModifiers" | | gerunds _ anObject select: [:x|x isGerund]. messageAdverbs _ anObject select: [:x| x isAdverb] ! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/19/2010 21:37'! receiver "Answer the value of receiver" false ifTrue: [SupportMultipleAdverbs. self error: 'should rm this inst var after mirror switch']. ^ receiver! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/6/2010 16:47'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! receiverMirror "Answer the value of receiverMirror" receiverMirror isNil ifTrue:[self receiverMirror: nil]. ^ receiverMirror! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 9/5/2010 15:32'! receiverMirror: anObject "Set the value of receiverMirror" receiverMirror _ anObject! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:08'! selector "Answer the value of selector" selector isNil ifTrue:[self selector: #noSelector]. ^ selector! ! !Sly3ParsedMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 21:08'! selector: anObject "Set the value of selector" selector _ anObject! ! !Sly3ParsedMessage methodsFor: 'testing' stamp: 'dmu 9/1/2010 16:09'! hasGerund ^ gerunds notEmpty ! ! !Sly3ParsedMessage methodsFor: 'printing' stamp: 'dmu 9/1/2010 11:15'! printOn: aStream super printOn: aStream. aStream nextPutAll: ': ', self selector! ! !Sly3ParsedMessage class methodsFor: 'as yet unclassified' stamp: 'dmu 9/19/2010 21:35'! receiver: ens members: mems messageModifiers: m selector: s arguments: args argumentAdverbs: argumentAdverbs | r | false ifFalse: [ ^ self new receiver: ens; members: mems; messageModifiers: m; selector: s; arguments: args; argumentAdverbs: argumentAdverbs; yourself ]. SupportMultipleAdverbs. "come back here later" r _ self new. r receiverMirror: (Sly3EnsembleMirror forEnsemble: ens members: mems). r messageModifiers: m. r selector: s. r argumentMirrors: (args collect: [:a| Sly3EnsembleMirror forObject: a]). r argumentAdverbs: argumentAdverbs. ^ r! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 8/29/2010 18:40'! dispatch self tryReflectiveMessageSend. ! ! !Sly3ReflectiveMessageDispatcher methodsFor: 'dispatching' stamp: 'dmu 9/8/2010 02:54'! tryReflectiveMessageSend | message selector | message _ self unprocessedMessage. selector _ message selector. selector = #members ifTrue: [self justReturn: message members]. ((selector = #isKindOf: and:[message arguments first = FakeClassPool]) or: [(selector = #== ) and:[message arguments first = #failedDoit] ] ) ifTrue:[self justReturn: false]. (#(hash halt error: halt: identityHash == isNil) includes: selector) ifTrue: [self justReturn: (message receiver class deactivateEnsembleSendsFor: message receiver during: [message receiver perform: message selector withArguments: message arguments])]. (selector = #isKindOf:) ifTrue: [self justReturn: (Sly3Ensemble includesBehavior: message arguments first)]! ! !Sly3ReflectiveSelectorChanger methodsFor: 'accessing' stamp: 'dmu 9/3/2010 12:17'! message: m message _ m! ! !Sly3ReflectiveSelectorChanger methodsFor: 'accessing' stamp: 'dmu 9/3/2010 17:49'! selector: x selector _ x! ! !Sly3ReflectiveSelectorChanger methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 17:46'! modifyMessageAsNeeded | newSelector | selector _ message selector. newSelector _ self modifySelectorAsNeeded. ^ selector = newSelector ifTrue: [message] ifFalse: [message copy selector: newSelector]! ! !Sly3ReflectiveSelectorChanger methodsFor: 'dispatching' stamp: 'dmu 9/3/2010 17:51'! modifySelectorAsNeeded (self isReflective or: [self isWholly or: [self isCollectionly]]) ifTrue: [^ selector]. ^ (self isEquals or: [self isToolMessage or: [self isToolProcess]]) ifTrue: [self modifiedSelector] ifFalse: [selector] ! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 17:52'! isCollectionly ^ selector beginsWith: Sly3ModCollectionly stringWithUppercaseSuffix! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/8/2010 21:09'! isEquals ^ selector = #= ifTrue:[self selector: #equals:. true] ifFalse: [false]! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 14:35'! isReflective ^ selector beginsWith: Sly3Adverb reflectiveAdverb stringWithUppercaseSuffix! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 12:12'! isToolMessage | toolMessages | toolMessages _ #(inspect explore printString asExplorerString hasContentsInExplorer explorerContents halt error: halt: isKindOf:). ^ toolMessages includes: selector! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 12:13'! isToolProcess | foundContext toolClasses | toolClasses _ { Inspector. Debugger. PluggableListController}. foundContext _ thisContext findContextSuchThat:[:ctxt| toolClasses includes: ctxt receiver class]. ^ foundContext notNil! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 17:52'! isWholly ^ selector beginsWith: Sly3ModWholly stringWithUppercaseSuffix! ! !Sly3ReflectiveSelectorChanger methodsFor: 'modifying reflective selectors' stamp: 'dmu 9/3/2010 14:34'! modifiedSelector ^ Sly3Adverb reflectiveAdverb modifySelector: selector! ! !Sly3ReflectiveSelectorChanger commentStamp: 'dmu 8/27/2010 14:38' prior: 0! No matter what Sly is, ST depends on some reflective messages. Handle them here. -- dmu Possible useful expressions for doIt or printIt. Structure: instVar1 type -- comment about the purpose of instVar1 instVar2 type -- comment about the purpose of instVar2 Any further useful comments about the general approach of this implementation.! !Sly3ReflectiveSelectorChanger class methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 12:25'! modifyAsNeeded: aMessage ^self new message: aMessage; modifyMessageAsNeeded! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/23/2010 13:11'! addTest "Sly3SyntaxTests addTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ {{1. 2}. {3. 4}. {5. 6}} asOrderedCollection asEnsembleOfElements. result _ ens wholLYadd: {7. 8}. test assert: result members asArray = {{1. 2}. {3. 4}. {5. 6}. {7. 8}}. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'addTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! adverbKeywordTest "Sly3SyntaxTests adverbKeywordTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens commaWholLY: {9. 10}. test assert: result members asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! adverbUnaryTest "self adverbUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 1. test assert: (result members size = 1) & (result members first isBoolean). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/22/2010 22:50'! argAdverbRoundlyTest "self argAdverbRoundlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{10. 20. 30}. result _ ens plusRoundLY: %(4. 5. 6. 7. 8. 9}. test assert: result members asArray = {14. 24. 34. 15. 25. 35. 16. 26. 36. 17. 27. 37. 18. 28. 38. 19. 29. 39. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbRoundlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! argAdverbWhollyTest "self argAdverbWhollyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens commaWholLY: {9. 10}. test assert: result members asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbWhollyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/17/2010 00:02'! binaryTest "Sly3SyntaxTests binaryTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens + 10. test assert: result members asArray = #(11 12 13). ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'binaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 5/30/2011 12:46'! doubleAdverbParsingTest "Sly3SyntaxTests doubleAdverbParsingTest run" "Sly3SyntaxTests runAll" | theTest result p | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| p _ 3@4. result _ %{ ( %{p} roundLYDuplicativeLYx: 10) members. p}. test assert: result members asArray = { {10@4}. 3@4}. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'doubleAdverbParsingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundAndingTest "self gerundAndingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens andINGodd. test assert: result = false. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundAndingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/17/2010 16:49'! gerundDoubleKeywordTest "self gerundDoubleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens concatenatINGat: 1 put: #(12 13). test assert: result = #( 12 13 12 13) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundDoubleKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyAveragingTest "self gerundOnlyAveragingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens averagING. test assert: result = 2. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyAveragingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyConcatenatingTest "self gerundOnlyConcatenatingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{'hello'. ' '. 'world'}. result _ ens concatenatING. test assert: result = 'hello world' ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyConcatenatingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyTest "self gerundOnlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallING. test assert: result = 6 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOnlyTotallingTest "self gerundOnlyTotallingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallING. test assert: result = 6 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTotallingTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundOringTest "self gerundOringTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens orINGodd. test assert: result = true ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOringTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundSingleKeywordTest "self gerundSingleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens totallINGplus: 1. test assert: result = 9 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundSingleKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! gerundUnaryTest "self gerundUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens andINGodd. test assert: result = false ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:50'! membersTest "Sly3SyntaxTests ensMembersTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens members. test assert: result = {{1. 2}. {3. 4}. {5. 6}} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensMembersTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvKeywordTest "self msgAdvKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens randomLY: 1 plus:1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvOnlyRandomlyTest "self msgAdvOnlyRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens randomLY: 1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvOnlyRandomlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvRandomly2Test "self msgAdvRandomly2Test run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 2. test assert: (result members size = 2) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomly2Test'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvRandomlyTest "self msgAdvRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddRandomLY: 1. test assert: (result members size = 1) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! msgAdvSeriallyTest "self msgAdvSeriallyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3. 4. 5. 6. 7. 8. 9}. result _ ens serialLY. test assert: (result members asArray = {1. 2. 3. 4. 5. 6. 7. 8. 9}) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSeriallyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! normalBinaryTest "self normalBinaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens +1. test assert: result members = {2. 3. 4} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalBinaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! normalKeywordTest "self normalKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1. test assert: result members = {2. 3. 4} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/22/2010 22:54'! normalUnaryTest "self normalUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens odd. test assert: result members = {true. false. true} ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalUnaryTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:59'! plainlyTest "Sly3SyntaxTests plainlyTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{}. result _ ens plainLYisEnsemble. test assert: result. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 00:37'! printStringTest "Sly3SyntaxTests printStringTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plainLYprintString. test assert: result = '%{1. 2. 3. }' ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'printStringTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/23/2010 13:12'! removeTest "Sly3SyntaxTests removeTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ {{1. 2}. {3. 4}. {5. 6}} asOrderedCollection asEnsembleOfElements. result _ ens wholLYremove: {3. 4}. test assert: result members asArray = {{1. 2}. {5. 6}. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'removeTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 00:41'! severalIndirectAdverbTests "self severalIndirectAdverbTests run" "self runAll" | theTest | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| %{1. 2. 3} randomLY: 2. %{1. 2. 3} oddRandomLY: 2. %{1. 3. 4} plus: %{4. 5} randomLY: 3. %{2. 4} randomLY: 3 plus: %{2. 6} randomLY: 4 . test assert: true. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'severalIndirectAdverbTests'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 4/12/2011 12:34'! singlyTest "Sly3SyntaxTests singlyTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plusIndividualLY: %{10. 20. 30 }. test assert: result members asArray = {11. 22. 33}. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'singlyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! sizeTest "Sly3SyntaxTests sizeTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens collectionLYsize. test assert: result = 3 ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'sizeTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/24/2010 14:51'! strategyMultipleAdverbTest "Sly3SyntaxTests strategyMultipleAdverbTest run" "Sly3SyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{3. 30}. {4. 40}. {5. 50}}. result _ ens serialLYatRoundLY: %{1. 2} put: %{1. 2. 3. 4. 5. 6} valueLY: [:x| x + 17]. test assert: result members asArray = {18. 19. 20. 21. 22. 23. }. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'strategyMultipleAdverbTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:50'! gerundPerformWithWithTest "CURRENTLY FAILS" "self gerundPerformWithWithTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens perform: #at:put: with: 1 with: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} perform: #at:put: with: 1 with 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundPerformWithWithTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:51'! msgAdvSelectivelyTest "self msgAdvSelectivelyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens serialLYselectiveLYvalueLY: [:mbr| mbr odd]. test assert: result members asArray = #(1 3) ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSelectivelyTest'. ^theTest! ! !Sly3SyntaxTests class methodsFor: 'tutorial' stamp: 'dmu 9/16/2010 23:51'! tutorialExamples %{1. 2. 3} isNil. "%{false. false. false}." %{1. 2. 3} totallING. "6" %{1. 2. 3} randomLY: 2. "%{1. 3}" %{1. 2. 3} oddRandomLY: 2. "%{true. false}" %{1. 3. 4} plus: %{4. 5} randomLY: 3. "%{5. 8. 8. 6. 7. 8. 6. 8. 8. }" %{2. 4} randomLY: 3 plus: %{2. 6} randomLY: 4. " %{10. 8. 8. 6. 10. 8. 10. 6. 4. 6. 10. 10. }" %{{1. 2}. {3. 4}. {5. 6}} commaWholLY: {9. 10}. "%{#(1 2 9 10). #(3 4 9 10). #(5 6 9 10). }" %{1. 2. 3} collectionLY. " #(1 2 3)" %{10. 20. 30} plusRoundLY: %{4. 5. 6.7. 8. 9} . " %{14. 24. 34. 15. 25. 35. 16.7. 26.7. 36.7. 18. 28. 38. 19. 29. 39. }"! ! !Sly3SyntaxTests class methodsFor: 'harness' stamp: 'dmu 9/3/2010 11:50'! runAll super runAll! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! arguments "Answer the value of arguments" arguments isNil ifTrue:[self arguments: #()]. ^ arguments! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! arguments: anObject "Set the value of arguments" arguments _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! members "Answer the value of members" members isNil ifTrue:[self members: #()]. ^ members! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! members: anObject "Set the value of members" members _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 9/16/2010 23:59'! receiver "Answer the value of receiver" "Send no messages; might be an ensemble" nil == receiver ifTrue:[self receiver: ( %{})]. ^ receiver! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/30/2010 19:35'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:46'! selector "Answer the value of selector" selector isNil ifTrue:[self selector: #noSelector]. ^ selector! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'accessing' stamp: 'dmu 8/29/2010 12:45'! selector: anObject "Set the value of selector" selector _ anObject! ! !Sly3UnprocessedEnsembleMessage methodsFor: 'printing' stamp: 'dmu 9/1/2010 10:35'! printOn: aStream super printOn: aStream. aStream nextPutAll: '(', self selector, ')'! ! !Sly3UnprocessedEnsembleMessage class methodsFor: 'instance creation' stamp: 'dmu 8/30/2010 19:37'! fromMessage: m members: members ^ self new receiver: m lookupClass "VM hack"; selector: m selector; arguments: m arguments; members: members; yourself! ! !Sly3UnprocessedEnsembleMessage class methodsFor: 'instance creation' stamp: 'dmu 8/30/2010 19:38'! fromMessage: m theEnsemble: e ^ self new receiver: e; selector: m selector; arguments: m arguments; members: e members; yourself! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/2/2010 23:59'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." ^ self flock boids averagINGserialLYposition! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 00:01'! computeNeighbors "should return ensemble" ^ self flock boids selectINGisNear: self! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/3/2010 15:56'! keepAwayFromNeighbors self neighbors collectionLYsize = 0 ifTrue: [^ 0@0]. ^ self position - self neighbors averagINGserialLYposition! ! !Sly3aBoid methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 03:02'! matchVelocityWithNeighbors self neighbors collectionLYsize = 0 ifTrue: [^ 0@0]. ^ self neighbors averagINGvelocity / 8.0! ! !Sly3aBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:27'! boidClass ^ Sly3aBoid! ! !Sly3aBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:30'! drawerClass ^ Sly3aDrawer! ! !Sly3aBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 03:03'! flockSize ^ 30! ! !Sly3aDrawer methodsFor: 'as yet unclassified' stamp: 'dmu 9/8/2010 02:28'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids serialLYdraw]! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:51'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: #()]. ^ flock! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! flock: anObject "Set the value of flock" flock _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:57'! lastDrawnPosition "Answer the value of lastDrawnPosition" lastDrawnPosition isNil ifTrue:[self lastDrawnPosition: self position]. ^ lastDrawnPosition! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:00'! lastDrawnPosition: anObject "Set the value of lastDrawnPosition" lastDrawnPosition _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/23/2010 00:05'! lastLastDrawnPosition "Answer the value of lastLastDrawnPosition" lastLastDrawnPosition isNil ifTrue:[self lastLastDrawnPosition: self lastDrawnPosition]. ^ lastLastDrawnPosition! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/22/2010 23:53'! lastLastDrawnPosition: anObject "Set the value of lastLastDrawnPosition" lastLastDrawnPosition _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:53'! neighbors "Answer the value of neighbors" neighbors isNil ifTrue:[self neighbors: #()]. ^ neighbors! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! neighbors: anObject "Set the value of neighbors" neighbors _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! position "Answer the value of position" position isNil ifTrue:[self position: 500@500]. ^ position! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! position: anObject "Set the value of position" position _ anObject! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:39'! velocity "Answer the value of velocity" velocity isNil ifTrue:[self velocity: 0@0]. ^ velocity! ! !SlyBoid methodsFor: 'accessing' stamp: 'dmu 3/16/2010 22:38'! velocity: anObject "Set the value of velocity" velocity _ anObject! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:42'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." "^500@500" "^ self flock boids positionING: #averaging" "^ self flock boids positionLY: #serially ING: #averaging" ^ (self flock boids members collect: [:m| m position]) average! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:43'! computeNeighbors "^self flock boids yourselfLY:{ #selectively:. [:b| b isNear: self]}" ^self flock boids members select:[:m| m isNear: self]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/22/2010 23:55'! draw | p | self lastDrawnPosition = self position ifTrue: [^ self]. p _ self position. false ifTrue: [ SlyGraphics drawWhiteCircle: self lastDrawnPosition. SlyGraphics drawCircle: p. "SlyGraphics drawFrom: self lastDrawnPosition to: p." ] ifFalse: [ SlyGraphics drawFrom: self lastDrawnPosition to: p. SlyGraphics eraseFrom: self lastLastDrawnPosition to: self lastDrawnPosition. ]. self lastLastDrawnPosition: self lastDrawnPosition. self lastDrawnPosition: p! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'ssa 3/25/2010 16:28'! fly | centroid | [Sly keepFlying] whileTrue:[ centroid _ self computeCentroid. self moveToNewPosition: centroid. self flock maybeYield ]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:15'! go self fly! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:43'! isNear: aBoid ^ (self ~== aBoid) and: [(self position dist: aBoid position) <= 10]! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/17/2010 00:10'! keepAwayFromNeighbors | sum | self neighbors ifEmpty: [^ 0@0]. sum _ 0. self neighbors do: [:m | sum _ sum + (self position - m position)]. ^ sum / self neighbors size asFloat! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:30'! limitPositionFrom: min to: max | r pos | pos _ self position. r _ ((pos max: min@min) min: max@max). r = pos ifTrue: [^ self]. pos x < min ifTrue: [r _ min + (min - pos x) @ pos y. self velocity: self velocity x negated @ self velocity y]. pos y < min ifTrue: [r _ pos x @ (min + (min - pos y)). self velocity: self velocity x @ self velocity y negated]. pos x > max ifTrue: [r _ max - (pos x - max) @ pos y. self velocity: self velocity x negated @ self velocity y ]. pos y > max ifTrue: [r _ pos x @ (max - (pos y - max)). self velocity: self velocity x @ self velocity y negated]. self position: r! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:36'! limitVelocityTo: n | ns v vs q | ns _ n * n * 2. v _ self velocity. vs _ v x squared + v y squared. vs <= ns ifTrue: [^ self]. q _ (ns / vs) sqrt. self velocity: v * q.! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:53'! matchVelocityWithNeighbors self neighbors ifEmpty: [^ 0@0]. ^ (self neighbors collect: [:m| m velocity]) average / 8.0! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/24/2010 15:04'! moveToNewPosition: centroid | a b c | self neighbors: self computeNeighbors. a _ self moveTowardCentroidOfAllOthers: centroid. b _ self keepAwayFromNeighbors. c _ self matchVelocityWithNeighbors. self velocity: self velocity + a + b + c. self limitVelocityTo: 10. self position: self position + self velocity. self limitPositionFrom: 0 to: 1000! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:43'! moveTowardCentroidOfAllOthers: centroid | perceivedCentroid s | s _ self flock boids members size. "was ENSsize" s < 2 ifTrue: [^ 0@0]. perceivedCentroid _ (centroid * s - self position) / (s - 1). ^ (perceivedCentroid - self position) / 100.0! ! !SlyBoid methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:54'! perturb self position: (self position perturb: 100). self velocity: (self velocity perturb: 2).! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:52'! boidClass ^ SlyBoid! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'ads 2/2/2011 14:55'! flockSize "RVMOperations coreCount - 6 max: 10". ^ 250! ! !SlyBoids methodsFor: 'as yet unclassified' stamp: 'dmu 9/16/2010 23:59'! run "Transcript show: (Time millisecondsToRun: [SlyBoids new run]); cr" "[ SlyBoids new run ] fork" | c flock drawer flockAndDrawer n | c _ OrderedCollection new. n _ self flockSize. 1 to: n do: [:i| c add: self boidClass new perturb]. flock _ SlyFlock boids: c asEnsembleOfElements. flock boids flock: flock. drawer _ SlyDrawer flock: flock. flockAndDrawer _ SlyEnsemble with: {flock. drawer}. "SlyGraphics clearScreen." flockAndDrawer go ! ! !SlyBoids class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 22:30'! run ^ self new run! ! !SlyDrawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock "Answer the value of flock" flock isNil ifTrue:[self flock: nil]. ^ flock! ! !SlyDrawer methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:06'! flock: anObject "Set the value of flock" flock _ anObject! ! !SlyDrawer methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:49'! go Processor thisProcess useOnlyMainCore. "for bitblt efficiency" [flock isDone] whileFalse: [flock boids members do: [:m | m draw. "self flock maybeYield"] ]! ! !SlyDrawer class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:07'! flock: f ^ self new flock: f! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 7/8/2010 00:50'! ENSsize ^members size! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 8/29/2010 12:53'! doesNotUnderstand: aMessage "Try to process this message as an ensemble dispatch message to help in the case of inlined primitive calls like perform:with:with:" ^ Sly3EnsembleMessageDispatcher dispatch: (Sly3UnprocessedEnsembleMessage fromMessage: aMessage theEnsemble: self)! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/29/2010 01:04'! ensembleSpecies ^ SlyEnsemble! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/26/2010 00:34'! ifEmpty: blk ^ self sizeAsAWhole = 0 ifTrue: [blk value]! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 6/11/2010 14:50'! isEnsemble "Object answers false" ^true! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 6/17/2010 10:29'! members "you should never trust that the members collection stays the same within the ensemble" ^members copy! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'ssa 7/7/2010 13:57'! members: aCollection self primitiveSetExtraWordSelector: #sentToEnsemble:. aCollection primitiveSetExtraPreheaderWord: self. members _ aCollection. ^ self! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 23:48'! select: aBlock ^ self members select: aBlock! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:13'! size ^ self members size! ! !SlyEnsemble methodsFor: 'as yet unclassified' stamp: 'dmu 3/25/2010 21:25'! totalWithIdentity: id ^ self plus: id adverb: #reductively! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 16:35'! asExplorerString ^self printString! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 13:48'! printOn: out "Add a string that should compile back into an ensemble like me" out nextPutAll:'%{'. self members do:[:mem| mem ENSprintOn: out. out nextPutAll:'. ']. out nextPutAll:'}'. ! ! !SlyEnsemble methodsFor: 'printing' stamp: 'ssa 6/17/2010 13:51'! storeOn: out "Write a string on aStream that should compile back into an ensemble like me" out nextPut:$%;nextPut:${. self members do:[:mem| mem ENSstoreOn: out. out nextPut:$.]. out nextPut:$}. ! ! !SlyEnsemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:14'! explorerContents ^self members asOrderedCollection withIndexCollect: [:value :index | ObjectExplorerWrapper with: value name: index printString model: self]! ! !SlyEnsemble methodsFor: 'exploring' stamp: 'ssa 6/15/2010 16:15'! hasContentsInExplorer ^self members isEmpty not! ! !SlyEnsemble methodsFor: 'disabling' stamp: 'ssa 7/7/2010 19:13'! deactivateEnsembleSendsDuring: aBlock "disable messaging dispatching to members and just send it to the ensemble object itself during aBlock" 0 primitiveSetExtraPreheaderWord: self. aBlock value. self members primitiveSetExtraPreheaderWord: self. ! ! !SlyEnsemble class methodsFor: 'as yet unclassified' stamp: 'dmu 3/28/2010 23:48'! with: aCollection ^ self new members: aCollection! ! !SlyField methodsFor: 'as yet unclassified' stamp: 'max 9/29/2010 13:55'! add: aParticle particles members add: aParticle. aParticle setHomeField: self. simulation running ifTrue: [aParticle go]! ! !SlyField methodsFor: 'as yet unclassified'! displayOn: t1 self shouldNotImplement! ! !SlyField methodsFor: 'as yet unclassified' stamp: 'max 9/29/2010 14:33'! initialize super initialize. particles := OrderedCollection new asEnsembleOfElements! ! !SlyField methodsFor: 'as yet unclassified'! particle: t1 ofSize: t2 movedTo: t3 | t4 | t4 := self localFieldsUnderParticleAt: t3 size: t2. self hand: t1 to: t4 first. ((t4 reject: [:t5 | t5 isNil]) collect: [:t5 | t5 particles]) asEnsembleOfElements particle: t1 ofSize: t2 movedTo: t3! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:39'! boids "Answer the value of boids" ^ boids! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:11'! boids: anObject "Set the value of boids" boids _ anObject! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone "Answer the value of isDone" isDone isNil ifTrue:[self isDone: false]. ^ isDone! ! !SlyFlock methodsFor: 'accessing' stamp: 'dmu 3/16/2010 23:12'! isDone: anObject "Set the value of isDone" isDone _ anObject! ! !SlyFlock methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:13'! go self isDone: false. boids fly. self isDone: true! ! !SlyFlock methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 17:09'! maybeYield | n | "[Processor yield. ^self]value." n _self boids ENSsize + 1 "1 for Drawer". Processor yieldIfFewerCoresThan: n! ! !SlyFlock class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:11'! boids: b ^ self new boids: b! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! clearScreen Display fillWhite! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:05'! drawCircle: pt Display drawDot5At: pt! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:03'! drawFrom: ptA to: ptB Display drawLineFrom: ptA to: ptB color: Color black! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/16/2010 23:04'! drawWhiteCircle: pt Display eraseDot5At: pt! ! !SlyGraphics class methodsFor: 'as yet unclassified' stamp: 'dmu 3/23/2010 00:02'! eraseFrom: ptA to: ptB Display eraseLineFrom: ptA to: ptB color: Color black! ! !SlyMessageEnvelope methodsFor: 'delivering' stamp: 'ssa 6/1/2010 16:31'! deliver "send my message to my receiver and return the reply" self message arguments: self message arguments asArray. ^self message sentTo: self receiver! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! message "Answer the value of message" message isNil ifTrue:[self message: nil]. ^ message! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 7/16/2010 19:03'! message: anObject "Set the value of message" message _ anObject. ! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver "Answer the value of receiver" receiver isNil ifTrue:[self receiver: nil]. ^ receiver! ! !SlyMessageEnvelope methodsFor: 'accessing' stamp: 'ssa 5/12/2010 15:24'! receiver: anObject "Set the value of receiver" receiver _ anObject! ! !SlyMessageEnvelope methodsFor: 'printing' stamp: 'ssa 5/28/2010 16:17'! printOn: aStream aStream nextPutAll:'MsgEnv|rcvr:',self receiver printString,'|message: ',self message printString! ! !SlyMessageEnvelope class methodsFor: 'instance creation' stamp: 'dmu 9/1/2010 15:32'! argumentCount: n ^self new message: (Message selector: #none arguments: (Array new: n)); yourself! ! !SlyMessageEnvelope class methodsFor: 'instance creation' stamp: 'ssa 5/27/2010 10:46'! receiver: anObject selector: aSymbol arguments: anArray ^self new receiver: anObject; message: (Message selector: aSymbol arguments: anArray); yourself! ! !SlyParticle methodsFor: 'as yet unclassified'! homeField ^ homeField! ! !SlyParticle methodsFor: 'as yet unclassified'! particle: t1 ofSize: t2 movedTo: t3 ((location dist: t3) <= (size + t2 // 2) and: [t1 ~= self]) ifTrue: [[self collideWith: t1] fork. [t1 collideWith: self] fork]! ! !SlyParticleSim methodsFor: 'as yet unclassified'! add: t1 particles members add: t1. super add: t1! ! !SlyParticleSim methodsFor: 'as yet unclassified'! addRandom: t1 t1 timesRepeat: [self add: (SlyParticle c: Color random s: (10 to: 30) atRandom l: (0 to: extent x - 1) atRandom @ (0 to: extent y - 1) atRandom v: (1 to: 10) atRandom @ (1 to: 10) atRandom)]! ! !SlyParticleSim methodsFor: 'as yet unclassified' stamp: 'max 9/29/2010 14:33'! clear particles := OrderedCollection new asEnsembleOfElements. super clear! ! !SlyParticleSim methodsFor: 'as yet unclassified'! go running := true. [[running] whileTrue: [self refresh. (Delay forMilliseconds: 50) wait]. nil] fork. particles go! ! !SlyParticleSim methodsFor: 'as yet unclassified'! particles ^ particles! ! !SlyParticleSim methodsFor: 'as yet unclassified'! refresh blankForm displayOn: form. particles displayOn: form. canvas displayView! ! !SlyParticleSim methodsFor: 'as yet unclassified' stamp: 'max 9/29/2010 14:31'! setExtent: t1 fields: t2 | t3 | particles := OrderedCollection new asEnsembleOfElements. running := false. extent := t1. t3 := t1 // t2. form := Form extent: t1 depth: 8. fields := Matrix rows: t2 x columns: t2 y. fields indicesDo: [:t4 :t5 | fields at: t4 at: t5 put: (SlyField origin: t4 @ t5 - (1 @ 1) * t3 extent: t3)]. fields indicesDo: [:t4 :t5 | (fields at: t4 at: t5) setNeighborN: (fields at: t4 at: t5 - 1 ifInvalid: nil); setNeighborNE: (fields at: t4 + 1 at: t5 - 1 ifInvalid: nil); setNeighborNW: (fields at: t4 - 1 at: t5 - 1 ifInvalid: nil); setNeighborS: (fields at: t4 at: t5 + 1 ifInvalid: nil); setNeighborSE: (fields at: t4 + 1 at: t5 + 1 ifInvalid: nil); setNeighborSW: (fields at: t4 - 1 at: t5 + 1 ifInvalid: nil); setNeighborE: (fields at: t4 + 1 at: t5 ifInvalid: nil); setNeighborW: (fields at: t4 - 1 at: t5 ifInvalid: nil); setSimulation: self]. self makeBlankForm! ! !SlyParticleSim methodsFor: 'as yet unclassified'! step particles step. self refresh! ! !SlyParticleSim methodsFor: 'as yet unclassified'! stop running := false. particles stop! ! !SlySamBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:42'! computeCentroid ["buttonize next two lines for a trigger setting button" "Click To Set Trigger" " ONEHALT _ true" ]. "ONEHALT ifTrue:[ONEHALT _ false. self halt]." "^500@500" "^ self flock boids positionING: #averaging" ^ self flock boids positionLY: #serially ING: #averaging "^ (self flock boids ENSmembers collect: [:m| m position]) average"! ! !SlySamBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:43'! computeNeighbors "^self flock boids yourselfLY:{ #selectively:. [:b| b isNear: self]}" ^self flock boids ING:[:members| members select:[:m| m isNear: self]]! ! !SlySamBoid methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:44'! moveTowardCentroidOfAllOthers: centroid | perceivedCentroid s | s _ self flock boids ENSsize. s < 2 ifTrue: [^ 0@0]. perceivedCentroid _ (centroid * s - self position) / (s - 1). ^ (perceivedCentroid - self position) / 100.0! ! !SlySamBoids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:52'! boidClass ^ SlySamBoid! ! !SlySamBoids methodsFor: 'as yet unclassified' stamp: 'dmu 8/23/2010 15:46'! flockSize ^ 10! ! !SlySelectorModifier class methodsFor: 'basic modifiers' stamp: 'dmu 8/27/2010 13:30'! adverb ^ 'LY'! ! !SlySelectorModifier class methodsFor: 'basic modifiers' stamp: 'dmu 8/27/2010 13:30'! asAWhole ^ 'ENS'! ! !SlySelectorModifier class methodsFor: 'extended modifiers' stamp: 'dmu 8/27/2010 13:35'! adverbColon ^ self adverb, ':'! ! !SlySelectorModifier class methodsFor: 'extended modifiers' stamp: 'dmu 8/27/2010 13:35'! gerundColon ^ self gerund, ':'! ! !SlySelectorModifier class methodsFor: 'sizes' stamp: 'dmu 8/27/2010 13:35'! adverbColonSize ^ self adverbColon size! ! !SlySelectorModifier class methodsFor: 'sizes' stamp: 'dmu 8/27/2010 13:44'! adverbSize ^ self adverb size! ! !SlySelectorModifier class methodsFor: 'sizes' stamp: 'dmu 8/27/2010 13:40'! asAWholeSize ^ self asAWhole size! ! !SlySelectorModifier class methodsFor: 'sizes' stamp: 'dmu 8/27/2010 14:17'! gerundColonSize ^ self gerundColon size! ! !SlySelectorModifier class methodsFor: 'commonly modified selectors' stamp: 'dmu 8/29/2010 18:36'! asAWholeify: selector (selector beginsWith: self asAWhole) ifTrue: [^ self]. ^ (self asAWhole, selector) asSymbol! ! !SlySelectorModifier class methodsFor: 'commonly modified selectors' stamp: 'dmu 8/27/2010 13:52'! sizeAsAWhole ^ self asAWholeify: #size! ! !SlySelectorModifier class methodsFor: 'accessing' stamp: 'dmu 8/27/2010 13:30'! gerund ^ 'ING'! ! !SlySelectorModifier class methodsFor: 'special selectors' stamp: 'dmu 8/27/2010 13:59'! equalsAsAWhole ^ ( self asAWhole, 'equals:' ) asSymbol! ! !SlySelectorModifier class methodsFor: 'special selectors' stamp: 'dmu 8/27/2010 13:56'! members ^ #members! ! !SlySelectorModifier class methodsFor: 'testing' stamp: 'dmu 8/30/2010 10:01'! isSlySelector: aSelector "True if its has SlySelectorModifers" ^ {self asAWhole. self adverb. self gerundColon} anySatisfy: [:ss | aSelector includesSubString: ss]! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! adverbKeywordTest "SlySyntaxTests adverbKeywordTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. self halt. result _ ens comma: {9. 10} LY:#wholly. test assert: result ENSmembers asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)) ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} comma: {9. 10} LY:#wholly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! adverbUnaryTest "self adverbUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#randomly. test assert: (result ENSmembers size = 1) & (result ENSmembers first isBoolean) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'adverbUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:51'! argAdverbRoundlyTest "self argAdverbRoundlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: #(4 5 6 7 8 9) LY:#roundly. test assert: result ENSmembers asArray = #(5 7 9 8 10 12) ifFail:[test log:' failed: %{1. 2. 3} plus: #(4 5 6 7 8 9) LY:#roundly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbRoundlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! argAdverbWhollyTest "self argAdverbWhollyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens comma: {9. 10} LY:#wholly. test assert: result ENSmembers asArray = #(#(1 2 9 10) #(3 4 9 10) #(5 6 9 10)) ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} comma: {9. 10} LY:#wholly ==> ', result ENSmembers asArray printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'argAdverbWhollyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensMembersTest "SlySyntaxTests ensMembersTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens ENSmembers. test assert: result = {{1. 2}. {3. 4}. {5. 6}} ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} ENSmembers ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensMembersTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensPrintStringTest "SlySyntaxTests ensPrintStringTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ENSprintString. test assert: result = '%{1. 2. 3. }' ifFail:[test log:' failed: %{1. 2. 3} ENSprintString ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensPrintStringTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! ensSizeTest "SlySyntaxTests ensSizeTest run" "SlySyntaxTests runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{{1. 2}. {3. 4}. {5. 6}}. result _ ens ENSsize. test assert: result = 3 ifFail:[test log:' failed: %{{1. 2}. {3. 4}. {5. 6}} ENSsize ==> ', result ENSmembers size printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'ensSizeTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundAndingTest "self gerundAndingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #anding. test assert: result = false ifFail:[test log:' failed: %{1. 2. 3} oddING: #anding ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundAndingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundDoubleKeywordTest "self gerundDoubleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens at: 1 put: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} at: 1 put: 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundDoubleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyAveragingTest "self gerundOnlyAveragingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #averaging. test assert: result = 2 ifFail:[test log:' failed: %{1. 2. 3} ING: #averaging ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyAveragingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyConcatenatingTest "self gerundOnlyConcatenatingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{'hello'. ' '. 'world'}. result _ ens ING: #concatenating. test assert: result = 'hello world' ifFail:[test log:' failed: %{''hello''. '' ''. ''world''} ING:#concatenating ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyConcatenatingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyTest "self gerundOnlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #totalling. test assert: result = 6 ifFail:[test log:' failed: %{1. 2. 3} ING: #totalling ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOnlyTotallingTest "self gerundOnlyTotallingTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens ING: #totalling. test assert: result = 6 ifFail:[test log:' failed: %{1. 2. 3} ING: #totalling ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOnlyTotallingTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundOringTest "self gerundOringTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #oring. test assert: result = true ifFail:[test log:' failed: %{1. 2. 3} oddING: #oring ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundOringTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundSingleKeywordTest "self gerundSingleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1 ING:#totalling. test assert: result = 9 ifFail:[test log:' failed: %{1. 2. 3} plus: 1 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundSingleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundTripleKeywordTest "self gerundTripleKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens changed:#foo with:#bar from:self ING:#concatenating. test assert: result = #( 1 2) ifFail:[test log:' failed: %{#(1). #(2)} changed:#foo with:#bar from:self ING:#concatenating ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundTripleKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! gerundUnaryTest "self gerundUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddING: #anding. test assert: result = false ifFail:[test log:' failed: %{1. 2. 3} oddING: #anding ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvKeywordTest "self msgAdvKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens LY:#randomly plus:1. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} LY:#randomly plus:1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvOnlyRandomlyTest "self msgAdvOnlyRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens yourselfLY:#randomly. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} LY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvOnlyRandomlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvRandomly2Test "self msgAdvRandomly2Test run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#(#randomly: 2). test assert: (result ENSmembers size = 2) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#(#randomly: 2) ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomly2Test'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:52'! msgAdvRandomlyTest "self msgAdvRandomlyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens oddLY:#randomly. test assert: (result ENSmembers size = 1) ifFail:[test log:' failed: %{1. 2. 3} oddLY:#randomly ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvRandomlyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! msgAdvSelectivelyTest "self msgAdvSelectivelyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens yourselfLY:{#selectively:. [:mbr| mbr odd]}. test assert: result ENSmembers asArray = #(1 3) ifFail:[test log:' failed: %{1. 2. 3} yourselfLy:{#selectively:. [:mbr| mbr odd]} ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSelectivelyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! msgAdvSeriallyTest "self msgAdvSeriallyTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3. 4. 5. 6. 7. 8. 9}. result _ ens yourselfLY:#serially. test assert: (result ENSmembers asArray = {1. 2. 3. 4. 5. 6. 7. 8. 9}) ifFail:[test log:' failed: %{1. 2. 3. 4. 5. 6. 7. 8. 9} yourselfLY:#serially ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'msgAdvSeriallyTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalBinaryTest "self normalBinaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens +1. test assert: result ENSmembers = {2. 3. 4} ifFail:[test log:' failed: %{1. 2. 3} + 1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalBinaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalKeywordTest "self normalKeywordTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens plus: 1. test assert: result ENSmembers = {2. 3. 4} ifFail:[test log:' failed: %{1. 2. 3} plus: 1 ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalKeywordTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'tests' stamp: 'dmu 9/16/2010 23:53'! normalUnaryTest "self normalUnaryTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{1. 2. 3}. result _ ens odd. test assert: result ENSmembers = {true. false. true} ifFail:[test log:' failed: %{1. 2. 3} odd ==> ', result ENSmembers printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'normalUnaryTest'. ^theTest! ! !SlySyntaxTests class methodsFor: 'isolated failures' stamp: 'dmu 9/16/2010 23:52'! gerundPerformWithWithTest "CURRENTLY FAILS" "self gerundPerformWithWithTest run" "self runAll" | theTest ens result | theTest _ RVMTest setUp: [:test| "no setup needed"] test:[:test :env| ens _ %{#(1). #(2)}. result _ ens perform: #at:put: with: 1 with: 4 ING:#totalling. test assert: result = 8 ifFail:[test log:' failed: %{#(1). #(2)} perform: #at:put: with: 1 with 4 ING:#totalling ==> ', result printString]. ] asserting:[:test :outcome| true "assertions will also be checked"]. theTest name: 'gerundPerformWithWithTest'. ^theTest! ! !SlyTransporter methodsFor: 'as yet unclassified' stamp: 'sm 4/22/2011 00:52'! extensionInOtherPackages ^ { { 'EnsembleNode' }. { 'EnsembleNode'. 'printOn:indent:' }. { 'EnsembleNode'. 'sizeForValue:' }. { 'EnsembleNode'. 'emitForValue:on:' }. { 'Scanner class'. 'initialize' }. }! ! !SlyTransporter methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 20:48'! fiddleWithClassLoadingOrder: classes | classesThatNeedToGoAtTheEnd | "Blecch. Need to make sure the Parser changes aren't loaded until after the classes needed to support those changes. And that the classes that depend on the Parser changes aren't loaded until after that. Maybe we want to split stuff up into separate packages? -- Adam, Dec. 2010" classesThatNeedToGoAtTheEnd := {Parser. Sly3UnprocessedEnsembleMessage. SlySyntaxTests. Sly3SyntaxTests. Sly3Boids. Sly3aBoids}. ^ (classes asOrderedCollection reject: [:class | classesThatNeedToGoAtTheEnd includes: class]) addAllLast: classesThatNeedToGoAtTheEnd; yourself! ! !SlyTransporter methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 23:15'! initialize self initializePackage. self initializePreambleAndPostscript.! ! !SlyTransporter methodsFor: 'as yet unclassified' stamp: 'sm 3/11/2011 21:24'! initializePackage self package: (CompositePackageInfo new name: 'Sly'; packages: { PackageInfo named: 'Sly'. PackageInfo named: 'Sly2'. PackageInfo named: 'Sly3'. }; yourself). ! ! !SlyTransporter methodsFor: 'as yet unclassified' stamp: 'sm 4/22/2011 01:03'! initializePreambleAndPostscript self preambleBlock: [:file | PackageWhoseContentsMustBeTransportedInOrder new trickyModificationsThatNeedToBeDoneInOrder: self extensionInOtherPackages; saveTrickyModificationsToFile: file. file cr. file nextChunkPut: '"Make sure the Scanner gets initialized" Scanner initialize.'; cr.]! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'ssa 9/3/2008 14:28'! sourcesName "Answer the full path to the version-stable source code" ^ SourceFileVersionString , FileDirectory dot , 'sources'! ! !SmalltalkImage methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:25'! snapshot: save andQuit: quit embedded: embeddedFlag "Mark the changes file and close all files as part of #processShutdownList. If save is true, save the current state of this Smalltalk in the image file. If quit is true, then exit to the outer OS shell. The latter part of this method runs when resuming a previously saved image. This resume logic checks for a document file to process when starting up." | resuming msg | "Save a copy of the image file before you save the new one" save ifTrue:[(FileDirectory default fileExists: SmalltalkImage current imageName ) ifTrue:[FileDirectory default rename: SmalltalkImage current imageName toBe: SmalltalkImage current imageName , '.prev',Time now hhmm24]]. Object flushDependents. Object flushEvents. (SourceFiles at: 2) ifNotNil:[ msg _ String streamContents: [ :s | s nextPutAll: '----'; nextPutAll: (save ifTrue: [ quit ifTrue: [ 'QUIT' ] ifFalse: [ 'SNAPSHOT' ] ] ifFalse: [quit ifTrue: [ 'QUIT/NOSAVE' ] ifFalse: [ 'NOP' ]]); nextPutAll: '----'; print: Date dateAndTimeNow; space; nextPutAll: (FileDirectory default localNameFor: self imageName); nextPutAll: ' priorSource: '; print: LastQuitLogPosition ]. self assureStartupStampLogged. save ifTrue: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position ]. self logChange: msg. Transcript cr; show: msg ]. Smalltalk processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. Smalltalk setGCParameters. resuming == true ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! assureStartupStampLogged "If there is a startup stamp not yet actually logged to disk, do it now." | changesFile | StartupStamp ifNil: [^ self]. (SourceFiles isNil or: [(changesFile _ SourceFiles at: 2) == nil]) ifTrue: [^ self]. changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: StartupStamp asString; cr. StartupStamp _ nil. self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'ssa 9/3/2008 11:25'! forceChangesToDisk "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." | changesFile | changesFile _ SourceFiles at: 2. (changesFile isKindOf: FileStream) ifTrue: [ changesFile flush. true ifTrue:[ changesFile close. changesFile open: changesFile name forWrite: true]. changesFile setToEnd. ]. ! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dmu 9/7/2010 14:25'! logChange: aStringOrText "Write the argument, aString, onto the changes file." | aString changesFile | (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^ self]. self assureStartupStampLogged. aStringOrText isText ifTrue: [aString _ aStringOrText string] ifFalse: [aString _ aStringOrText]. (aString isKindOf: String) ifFalse: [self error: 'can''t log this change']. (aString findFirst: [:char | char isSeparator not]) = 0 ifTrue: [^ self]. "null doits confuse replay" (changesFile _ SourceFiles at: 2). changesFile isReadOnly ifTrue:[^self]. changesFile safelyDo: [ changesFile setToEnd; cr; cr. changesFile nextChunkPut: aString. "If want style changes in DoIt, use nextChunkPutWithStyle:, and allow Texts to get here" self forceChangesToDisk. ]! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'ads 1/12/2011 16:40'! saveAs: newName "Save the image under the new name." (SourceFiles at: 2) ifNotNil: [self closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (self fullNameForChangesNamed: newName)]. self saveImageInFileNamed: (self fullNameForImageNamed: newName)! ! !StandardFileMenu methodsFor: 'private'! oldFileFrom: aDirectory withPattern: aPattern canTypeFileName _ false. pattern _ aPattern. ^self makeFileMenuFor: aDirectory! ! !StandardFileMenu class methodsFor: 'instance creation' stamp: 'ssa 10/18/2008 22:56'! oldFileMenu: aDirectory withPattern: aPattern Smalltalk isMorphic ifFalse: [^PluggableFileList oldFileMenu: aDirectory withPattern: aPattern]. ^super new oldFileFrom: aDirectory withPattern: aPattern! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:01'! oldFileFrom: aDirectory withPattern: aPattern ^(self oldFileMenu: aDirectory withPattern: aPattern) startUpWithCaption: 'Select a File:' translated! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:12'! oldFileStreamFrom: aDirectory withPattern: aPattern | sfmResult fileStream | sfmResult _ self oldFileFrom: aDirectory withPattern: aPattern. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name. [fileStream isNil] whileTrue: [sfmResult _ self oldFileFrom: aDirectory. sfmResult ifNil: [^nil]. fileStream _ sfmResult directory oldFileNamed: sfmResult name]. ^fileStream ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 23:12'! oldFileStreamWithPattern: aPattern ^self oldFileStreamFrom: (FileDirectory default) withPattern: aPattern ! ! !StandardFileMenu class methodsFor: 'standard file operations' stamp: 'ssa 10/18/2008 22:54'! oldFileWithPattern: aPattern ^self oldFileFrom: (FileDirectory default) withPattern: aPattern! ! !StandardFileStream methodsFor: 'read, write, position' stamp: 'ssa 10/26/2008 23:47'! nextPut: char "Write the given character to this file." rwmode ifFalse: [^ self error: 'Cannot write a read-only file']. buffer1 byteAt: 1 put: char. self primWrite: fileID from: buffer1 startingAt: 1 count: 1. ^ char ! ! !StandardFileStream methodsFor: '*RVMBootstrap' stamp: 'dmu 9/7/2010 14:07'! interlock interlock ifNil: [self interlock: Semaphore forMutualExclusion]. ^ interlock! ! !StandardFileStream methodsFor: '*RVMBootstrap' stamp: 'dmu 9/7/2010 14:07'! interlock: aSemaphore interlock _ aSemaphore! ! !StandardFileStream methodsFor: '*RVMBootstrap' stamp: 'dmu 9/7/2010 14:14'! resetInterlock self interlock signal. self interlock: nil! ! !StandardFileStream methodsFor: '*RVMBootstrap' stamp: 'dmu 9/7/2010 14:09'! safelyDo: aBlock ^ self interlock critical: aBlock! ! !StandardFileStream class methodsFor: '*RVMBootstrap' stamp: 'dmu 9/7/2010 14:14'! resetAllInterlocks "self resetAllInterlocks" self allSubInstancesDo: [:sfs| sfs resetInterlock]! ! !StandardSourceFileArray class methodsFor: 'initialize-release' stamp: 'dmu 9/7/2010 14:12'! install "Replace SourceFiles by an instance of me with the standard sources and changes files. This only works if SourceFiles is either an Array or an instance of this class" "StandardSourceFileArray install" StandardFileStream resetAllInterlocks. SourceFiles _ self new initialize! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:56'! preventClosing "Answer the value of preventClosing" preventClosing isNil ifTrue:[self preventClosing: false]. ^ preventClosing! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:25'! preventClosing: anObject "Set the value of preventClosing" preventClosing _ anObject! ! !StandardSystemController methodsFor: 'accessing' stamp: 'ssa 3/9/2010 12:25'! status "Answer the value of status" status isNil ifTrue:[self status: nil]. ^ status! ! !StandardSystemController methodsFor: 'borders'! adjustWindowCorners | box cornerBox p clicked f2 | box _ view windowBox. clicked _ false. #(topLeft topRight bottomRight bottomLeft) do: [:readCorner | cornerBox _ ((box insetBy: 2) perform: readCorner) - (10@10) extent: 20@20. (cornerBox containsPoint: sensor cursorPoint) ifTrue: ["Display reverse: cornerBox." (Cursor perform: readCorner) showWhile: [[(cornerBox containsPoint: (p _ sensor cursorPoint)) and: [(clicked _ sensor anyButtonPressed) not]] whileTrue. "Display reverse: cornerBox." clicked ifTrue: [view newFrame: [:f | p _ sensor cursorPoint. readCorner = #topLeft ifTrue: [f2 _ p corner: f bottomRight]. readCorner = #bottomLeft ifTrue: [f2 _ (f withBottom: p y) withLeft: p x]. readCorner = #bottomRight ifTrue: [f2 _ f topLeft corner: p]. readCorner = #topRight ifTrue: [f2 _ (f withTop: p y) withRight: p x]. f2]]]]]. ^ clicked! ! !StandardSystemController methodsFor: 'borders'! checkForReframe "2/18/97 ssa - added a leftshift hack to prevent over aggressive offerings of reframing help for subpanes." | cp | view isCollapsed ifTrue: [^ self]. cp _ sensor cursorPoint. ((view closeBoxFrame expandBy: 2) containsPoint: cp) | ((view growBoxFrame expandBy: 2) containsPoint: cp) ifTrue: [^ self]. "Dont let reframe interfere with close/grow" self adjustWindowCorners. self cursorOnBorder ifFalse: [^ self]. ((view insetDisplayBox insetBy: 2@2) containsPoint: cp) ifFalse: [^ self adjustWindowBorders]. Sensor leftShiftDown ifTrue:[ (view subviewWithLongestSide: [:s | ] near: cp) == nil ifFalse: [^ self adjustPaneBorders]].! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'ssa 3/9/2010 12:58'! blueButtonActivity self blueButtonMenu invokeOn: self! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'dmu 5/3/2009 12:12'! isClosed ^ status == #closed! ! !StandardSystemController methodsFor: 'control defaults' stamp: 'ssa 3/12/2010 09:50'! redButtonActivity "If cursor is in label of a window when red button is pushed, check for closeBox or growBox, else drag the window frame or edit the label." | box p | p _ sensor cursorPoint. self labelHasCursor ifFalse: [super redButtonActivity. ^ self]. ((box _ view closeBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [Sensor shiftPressed ifFalse:[self close. ^ self]ifTrue:[^self togglePreventClosing]]. ^ self]. ((box _ view growBoxFrame) containsPoint: p) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [Sensor controlKeyPressed ifTrue: [^ self expand; fullScreen]. ^ view isCollapsed ifTrue: [self expand] ifFalse: [self collapse]]. ^ self]. (((box _ view labelTextRegion expandBy: 1) containsPoint: p) and: [Preferences clickOnLabelToEdit or: [sensor leftShiftDown]]) ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [^ self label]. ^ self]. self move! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/24/2010 16:12'! close "The receiver's view should be removed from the screen and from the collection of scheduled views." self preventClosing ifTrue:[^self]. model okToChange ifFalse: [^self]. self closeForReal! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/12/2010 09:47'! closeForReal "The receiver's view should be removed from the screen and from the collection of scheduled views." status _ #closed. view erase! ! !StandardSystemController methodsFor: 'menu messages' stamp: 'ssa 3/9/2010 13:00'! togglePreventClosing self preventClosing: self preventClosing not. self view emphasizeLabel.! ! !StandardSystemController methodsFor: 'pluggable menus' stamp: 'ssa 3/12/2010 09:46'! blueButtonMenu ^SelectionMenu labels: 'edit label choose color... two-tone/full color move frame full screen collapse ', (self preventClosing ifTrue:['enable closing']ifFalse:['disable closing close']) lines: #(3 7) selections: #(label chooseColor toggleTwoTone move reframe fullScreen collapse togglePreventClosing close). ! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'ssa 3/3/2010 13:57'! closeAndUnscheduleIfOkWithModel "Erase the receiver's view and remove it from the collection of scheduled views. IF its ok with my model. This catches unsaved changes" model okToChange ifFalse: [^self]. self closeAndUnschedule! ! !StandardSystemController methodsFor: 'scheduling' stamp: 'ssa 3/10/2010 10:07'! closeAndUnscheduleIfOkWithModelNoTerminate "Erase the receiver's view and remove it from the collection of scheduled views. IF its ok with my model. This catches unsaved changes" model okToChange ifFalse: [^self]. self closeAndUnscheduleNoTerminate! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 8/24/2009 07:49'! cacheBitsAsTwoTone ^ false! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! deEmphasizeLabel "Un-Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: false. self displayClosingGuardBoxIfNeeded. self displayLabelText. ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayClosingGuardBoxIfNeeded "display closing guard active, if true" | aRect | self controller preventClosing ifTrue:[ aRect _ self closeBoxFrame. self closingGuardIcon displayOn: Display at: aRect origin clippingBox: aRect rule: Form over fillColor: nil]. ! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:30'! displayDeEmphasized "Display this view with emphasis off. If windowBits is not nil, then simply BLT if possible, but force full display for top window so color is preserved." self critical: [ (bitsValid and: [controller ~~ ScheduledControllers activeController]) ifTrue: [self lock. windowBits displayAt: self windowOrigin] ifFalse: [Display deferUpdates: true. super display. Display deferUpdates: false; forceToScreen: self windowBox. CacheBits ifTrue: [self cacheBitsAsIs]] ] ! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:31'! displayEmphasized "Display with label highlighted to indicate that it is active." self critical: [ self displayDeEmphasized; emphasize. isLabelComplemented _ true ]! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayLabelBackground: emphasized "Clear or emphasize the inner region of the label" | r1 r2 r3 c3 c2 c1 | emphasized ifFalse: ["Just clear the label if not emphasized" Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor. ^self displayClosingGuardBoxIfNeeded]. r1 _ self labelDisplayBox insetBy: 2. r2 _ r1 insetBy: 0@2. r3 _ r2 insetBy: 0@3. c3 _ self labelColor. c2 _ c3 dansDarker. c1 _ c2 dansDarker. Display fill: r1 fillColor: c1. Display fill: r2 fillColor: c2. Display fill: r3 fillColor: c3. " Here is the Mac racing stripe code stripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth) with: (Form black pixelWordForDepth: Display depth). self windowOrigin y even ifTrue: [stripes swap: 1 with: 2]. Display fill: (self labelDisplayBox insetBy: 3) fillColor: stripes. "! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 12:52'! displayLabelBoxes "closeBox,closingGuard box growBox." | aRect smallRect backColor | aRect _ self closeBoxFrame. backColor _ self labelColor. Display fill: (aRect insetBy: -2) fillColor: backColor. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. "display closing guard active, if true" self displayClosingGuardBoxIfNeeded. aRect _ self growBoxFrame. smallRect _ aRect origin extent: 7@7. Display fill: (aRect insetBy: -2) fillColor: backColor. aRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0. Display fillBlack: aRect. Display fill: (aRect insetBy: 1) fillColor: backColor. Display fillBlack: smallRect. Display fill: (smallRect insetBy: 1) fillColor: backColor! ! !StandardSystemView methodsFor: 'displaying' stamp: 'ssa 3/9/2010 15:41'! displayView "Refer to the comment in View|displayView. " labelFrame height = 0 ifTrue: [^ self]. "no label" self displayBox width = labelFrame width ifFalse: ["recompute label width when window changes size" self setLabelRegion]. (labelFrame align: labelFrame topLeft with: self windowOrigin) insideColor: self labelColor; displayOn: Display. self displayClosingGuardBoxIfNeeded. self displayLabelText! ! !StandardSystemView methodsFor: 'displaying' stamp: 'dmu 9/17/2010 12:42'! emphasizeLabel "Highlight the label." labelFrame height = 0 ifTrue: [^ self]. "no label" self critical: [ self displayLabelBackground: true. self displayLabelBoxes. self displayLabelText. ]! ! !StandardSystemView methodsFor: 'framing' stamp: 'ssa 1/1/1970 00:05'! initialFrame "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" | rect | rect _ Rectangle originFromUser: self initialExtent + (0@self labelHeight). ^rect origin + (0@ self labelHeight) extent: self initialExtent "RealEstateAgent initialFrameFor: self world: nil"! ! !StandardSystemView methodsFor: 'label access' stamp: 'ssa 3/9/2010 12:49'! closingGuardIcon ^(ColorForm extent: 11@11 depth: 1 fromArray: #( 0 520093696 1065353216 830472192 830472192 2143289344 2143289344 2143289344 2143289344 2143289344 0) offset: 0@0) colorsFromArray: #(#(1.0 1.0 1.0)#(0.0 0.0 0.0) )! ! !StandardSystemView methodsFor: 'label access'! labelColor "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" ^ self backgroundColor! ! !StandardSystemView methodsFor: 'updating' stamp: 'ssa 8/21/2009 12:58'! setUpdatablePanesFrom: getSelectors | aList aPane | "Set my updatablePanes inst var to the list of panes which are list panes with the given get-list selectors. Order is important here!! Note that the method is robust in the face of panes not found, but a warning is printed in the transcript in each such case" aList _ OrderedCollection new. getSelectors do: [:sel | aPane _ self subViewSatisfying: [:pane | ((pane isKindOf: PluggableListView) or:[pane isKindOf: MSWScrollBarView]) and: [pane getListSelector == sel]]. aPane ifNotNil: [aList add: aPane] ifNil: [Transcript cr; show: 'Warning: view ', sel, ' not found.']]. updatablePanes _ aList asArray! ! !StandardSystemView methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 12:37'! critical: aBlock ^self displayInterlock critical: aBlock! ! !StandardSystemView methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 12:37'! displayInterlock displayInterlock ifNil: [self displayInterlock: Mutex new]. ^ displayInterlock! ! !StandardSystemView methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 12:24'! displayInterlock: aSemaphore displayInterlock _ aSemaphore! ! !StandardSystemView methodsFor: '*Sly3Bootstrap' stamp: 'dmu 9/17/2010 12:47'! resetDisplayInterlock self displayInterlock: nil! ! !StandardSystemView class methodsFor: 'instance creation' stamp: 'ssa 8/15/2008 17:42'! model: aModel label: aString minimumSize: aPoint ^self new model: aModel; label: aString; minimumSize: aPoint; yourself! ! !StandardSystemView class methodsFor: 'instance creation' stamp: 'ssa 3/24/2010 15:17'! new "This is a rather dirty hack -- but we don't have a window builder yet. (ar 1/22/98 23:36)" ^Preferences nicerSystemViews ifTrue:[MSWSystemView basicNew initialize] ifFalse:[self basicNew initialize]! ! !StartupBench methodsFor: 'as yet unclassified' stamp: 'StefanMarr 1/16/2011 19:55'! runBench RVMOperations print: 'This Benchmark is not to be used with the harness, but requiries time measurment to be done outside of the VM. Use it directly, it works like the Harness and implements class>>#run:'. self notYetImplemented. ! ! !StartupBench class methodsFor: 'script entry' stamp: 'SM 9/13/2009 15:22'! run: args "Instantly quit the VM after Startup, this will measure only the time to initalize the image and start its execution. This includes the time spend on object distribution" SmalltalkImage current snapshot: false andQuit: true! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! ascent: anObject "Set the value of ascent" ascent _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! characterToGlyphMap: anObject "Set the value of characterToGlyphMap" characterToGlyphMap _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! derivativeFonts "Answer the value of derivativeFonts" derivativeFonts isNil ifTrue:[self derivativeFonts: nil]. ^ derivativeFonts! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! derivativeFonts: anObject "Set the value of derivativeFonts" derivativeFonts _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! descent: anObject "Set the value of descent" descent _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! emphasis "Answer the value of emphasis" emphasis isNil ifTrue:[self emphasis: nil]. ^ emphasis! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! glyphs: anObject "Set the value of glyphs" glyphs _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! maxAscii: anObject "Set the value of maxAscii" maxAscii _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! maxWidth: anObject "Set the value of maxWidth" maxWidth _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! minAscii: anObject "Set the value of minAscii" minAscii _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! pointSize: anObject "Set the value of pointSize" pointSize _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! raster "Answer the value of raster" raster isNil ifTrue:[self raster: nil]. ^ raster! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! raster: anObject "Set the value of raster" raster _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! strikeLength "Answer the value of strikeLength" strikeLength isNil ifTrue:[self strikeLength: nil]. ^ strikeLength! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! strikeLength: anObject "Set the value of strikeLength" strikeLength _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! subscript "Answer the value of subscript" subscript isNil ifTrue:[self subscript: nil]. ^ subscript! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! subscript: anObject "Set the value of subscript" subscript _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! superscript "Answer the value of superscript" superscript isNil ifTrue:[self superscript: nil]. ^ superscript! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! superscript: anObject "Set the value of superscript" superscript _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! type "Answer the value of type" type isNil ifTrue:[self type: nil]. ^ type! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! type: anObject "Set the value of type" type _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xOffset "Answer the value of xOffset" xOffset isNil ifTrue:[self xOffset: nil]. ^ xOffset! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xOffset: anObject "Set the value of xOffset" xOffset _ anObject! ! !StrikeFont methodsFor: 'accessing' stamp: 'ssa 2/15/2010 11:35'! xTable: anObject "Set the value of xTable" xTable _ anObject! ! !StrikeFont methodsFor: '*RVM-Archiving'! archiveOn: aStream "record this instance by its name. On dearchive, the name corresponding to this instance will be looked up." aStream storeObject: self; storeClass: self class; store: self name! ! !StrikeFont class methodsFor: '*RVM-Archiving'! archiveVersion "This version archives only the name of the strikeFont. On dearchive, the name will be looked up and the appropriate strike font existing in that image will be returned." ^3! ! !StrikeFont class methodsFor: '*RVM-Archiving'! dearchive: versionNumber from: aStream | aString sf | versionNumber = self archiveVersion ifFalse:[^super dearchiveFrom: aStream]. aString _ aStream read: String. sf _ self allInstances detect:[:inst| inst name = aString] ifNone:[self error:'missing strike font for this image']. aStream storeObject: sf. ^sf! ! !String methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:34'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text string is the receiver." ^Paragraph withText: self asText style: aTextStyle! ! !String methodsFor: 'converting' stamp: 'ssa 9/7/2009 09:29'! asSmalltalkObject ^Compiler evaluate: self! ! !String methodsFor: 'converting' stamp: 'ssa 7/7/2010 20:26'! withoutFirst: n "Answer a string without my first n characters." ^self size > n ifFalse:[''] ifTrue:[self copyFrom: n+1 to: self size]! ! !String methodsFor: 'converting' stamp: 'ssa 4/20/2010 15:52'! withoutLast: n "Answer a string without my last n characters." ^self size > n ifFalse:[''] ifTrue:[self copyFrom: 1 to: self size-n]! ! !String methodsFor: '*RVM-UI-Generic' stamp: 'ssa 1/21/2010 11:47'! buttonIt " 'Display reverse' buttonIt " "launch a button to evaluate this string" | topView someCode extent | someCode _ self. extent _ (someCode asText asDisplayText extent + (30@20)) max: 80@30. topView := RVMStandardSystemView new. topView noLabel. topView borderWidth:1. topView minimumSize: extent . topView maximumSize: extent. topView addSubView: (RVMButtonView label: someCode action:[Compiler evaluate: someCode]). topView controller open! ! !String methodsFor: '*packageinfo-base' stamp: 'nk 8/30/2004 09:02'! escapeEntities ^ self species streamContents: [:s | self do: [:c | s nextPutAll: c escapeEntities]] ! ! !String methodsFor: '*RVM-Archiving'! archiveOn: aStream aStream storeObject: self; storeClass: self class; store: self! ! !String class methodsFor: '*RVM-Archiving-instance creation'! dearchiveFrom: aStream | anObject | anObject _ aStream read: self. aStream storeObject: anObject. ^anObject! ! !StringHolder methodsFor: 'accessing' stamp: 'tk 4/3/98 22:50'! contentsSelection "Return the interval of text in the code pane to select when I set the pane's contents" ^ 1 to: 0 "null selection"! ! !StringHolderView methodsFor: 'initialize-release' stamp: 'ssa 1/20/2010 10:35'! initialize "Refer to the comment in View|initialize." super initialize. displayContents _ '' asParagraphWithStyle: self textStyle. hasUnacceptedEdits _ false. askBeforeDiscardingEdits _ true. ! ! !StringHolderView methodsFor: 'updating'! updateDisplayContents "Make the text that is displayed be the contents of the receiver's model." "VIVA LA JUNTA!!!! hack this to update the scroll bar when the contents changes - ssa 1/15/98 14:39" self editString: model contents. self displayView. (self superView isKindOf: MSWScrollBarView) ifTrue:[self superView updateElevator]! ! !StringHolderView methodsFor: 'model access' stamp: 'ssa 1/20/2010 10:43'! editString: aString "The paragraph to be displayed is created from the characters in aString." displayContents _ Paragraph withText: aString asText style: self textStyle copy compositionRectangle: (self insetDisplayBox insetBy: 6 @ 0) clippingRectangle: self insetDisplayBox foreColor: self foregroundColor backColor: self backgroundColor. (self controller isKindOf: ParagraphEditor) ifTrue: [controller changeParagraph: displayContents]! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! askBeforeDiscardingEdits "Answer the value of askBeforeDiscardingEdits" askBeforeDiscardingEdits isNil ifTrue:[self askBeforeDiscardingEdits: nil]. ^ askBeforeDiscardingEdits! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:48'! changeTextStyle: aTextStyle self textStyle: aTextStyle. self displayContents setWithText: self displayContents asText style: self textStyle ! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/27/2010 17:12'! defaultTextStyle ^TextStyle default ! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! displayContents: anObject "Set the value of displayContents" displayContents _ anObject! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:36'! textStyle "Answer the value of textStyle" textStyle isNil ifTrue:[self textStyle: self defaultTextStyle]. ^ textStyle! ! !StringHolderView methodsFor: 'accessing' stamp: 'ssa 1/20/2010 10:31'! textStyle: anObject "Set the value of textStyle" textStyle _ anObject! ! !StringHolderView methodsFor: '*Interface-MSWLook'! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" | para lineIndex | para _ self displayContents. lineIndex _ para lineIndexOfTop: para visibleRectangle top. lineIndex = 1 ifTrue:[^0.0]. ^lineIndex / para numberOfLines asFloat ! ! !StringHolderView methodsFor: '*Interface-MSWLook'! totalContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self displayContents compositionRectangle height / self unitContentHeight! ! !StringHolderView methodsFor: '*Interface-MSWLook'! unitContentHeight "Answer the unit height of my contents. ssa 12/5/97 15:16" ^ self displayContents lineGrid asFloat! ! !StringHolderView methodsFor: '*Interface-MSWLook'! visibleContentHeight "Answer the total height of my contents. ssa 12/5/97 15:16" ^ self displayContents clippingRectangle height / self unitContentHeight! ! !StringHolderView class methodsFor: 'instance creation'! open: aStringHolder label: aString "Create a standard system view of the model, aStringHolder, as viewed by an instance of me. The label of the view is aString." "VIVA LA JUNTA!! Modified to use MSWScrollBarViews - ssa 12/11/97 12:00" | aStringHolderView topView shv | aStringHolderView _ self container: aStringHolder. topView _ StandardSystemView new. topView model: aStringHolderView model. topView addSubView: (shv _ MSWScrollBarView on: aStringHolderView ). shv borderWidth: 2. topView label: aString. topView minimumSize: 100 @ 50. topView controller open! ! !Symbol methodsFor: 'converting' stamp: 'ssa 5/11/2010 15:14'! asKeyword ^self last == $: ifTrue:[self] ifFalse:[(self copyWith:$:) asSymbol]! ! !Symbol class methodsFor: 'instance creation' stamp: 'ssa 10/26/2008 08:08'! readFrom: aStream "Correctly read a Symbol from aStream." | string | aStream skipSeparators. ^(aStream peekFor: $#) ifTrue: [(aStream upTo: Character space) asSymbol] ifFalse: [string _ super readFrom: aStream. (aStream next: 9) = ' asSymbol' ifTrue: [string asSymbol] ifFalse: [self error: 'This ain''t no ', self class name]]! ! !SyntaxError class methodsFor: 'instance creation' stamp: 'dmu 11/25/2008 00:25'! open: aSyntaxError "Answer a standard system view whose model is an instance of me." | topView | <primitive: 19> "Simulation guard" topView _ self buildMVCViewOn: aSyntaxError. topView controller openNoTerminateDisplayAt: Display extent // 2. Cursor normal show. Processor thisProcess suspend. ! ! !SystemDictionary methodsFor: 'memory space' stamp: 'sm 2/24/2011 16:41'! installLowSpaceWatcher "Start a process to watch for low-space conditions." "Smalltalk installLowSpaceWatcher" self primSignalAtBytesLeft: 0. "disable low-space interrupts" LowSpaceProcess == nil ifFalse: [LowSpaceProcess terminate]. LowSpaceProcess _ [self lowSpaceWatcher] newProcess. LowSpaceProcess priority: Processor lowIOPriority. LowSpaceProcess name: 'LowSpaceWatcher'. LowSpaceProcess resume. ! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'dmu 9/17/2010 16:39'! handleUserInterrupt Preferences cmdDotEnabled ifTrue: [Smalltalk isMorphic ifTrue: [] ifFalse: [[ScheduledControllers interruptName: 'User Interrupt'] forkAt: Processor thisProcess priority + 1]]! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'sm 5/25/2011 20:59'! logError: errMsg inContext: aContext onConsoleAndQuitWithSaving: doSave "Log the error message and a stack trace to the given file." | stream cnt ctx | RVMOperations print: 'Error occured in Headless mode:'. RVMOperations print: errMsg. stream := TextStream on: ''. "aContext printOn: stream." ctx := aContext. cnt := 0. [ctx notNil and: [(cnt := cnt + 1) < 40]] whileTrue: [ctx printOn: stream. stream cr. ctx := ctx sender]. RVMOperations print: stream contents. self snapshot: doSave andQuit: true. ! ! !SystemDictionary methodsFor: '*Sly' stamp: 'dmu 8/23/2010 15:38'! allClassesDoInParallel: aBlock "Evaluate the argument, aBlock, for each class in the system." (self classNames collect: [:name | self at: name]) doInParallel: aBlock! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 10/8/2008 13:14'! majorShrinkClassesToLeave | manual categoryNames classNames classNameSets | manual := #(True False ReadOnlyVariableBinding SystemOrganizer ClassOrganizer View Switch Button EndOfStream ValueHolder EventSensorConstants ChronologyConstants InstructionPrinter Color Form ColorForm DisplayMedium DisplayObject Rectangle Point Pen OrderedCollection Array SortedCollection Dictionary Association SequenceableCollection Collection String Text DisplayText ArrayedCollection Object GIFReadWriter ImageReadWriter "Benchmark BinaryChoice " ChangeSet ChangeSorter DualChangeSorter ChangeList Inspector BasicInspector CompiledMethodInspector DictionaryInspector OrderedCollectionInspector). categoryNames := "(SystemOrganization categoriesMatching:'RVM-*'), " (SystemOrganization categoriesMatching:'PluggableGauges*'), (SystemOrganization categoriesMatching:'Tools-FileList'), (SystemOrganization categoriesMatching:'Tools-Browser'), (SystemOrganization categoriesMatching:'Kernel-ST80 Remnants'), (SystemOrganization categoriesMatching:'ST80-Framework'), (SystemOrganization categoriesMatching:'ST80-Support'), (SystemOrganization categoriesMatching:'ST80-Pluggable Views'), (SystemOrganization categoriesMatching:'ST80-Views'), (SystemOrganization categoriesMatching:'ST80-Editors'), (SystemOrganization categoriesMatching:'Tools-Process Browser'). classNameSets := categoryNames collect:[:each| SystemOrganization listAtCategoryNamed: each]. classNames := OrderedCollection new. classNameSets do:[:set| set do:[:n| classNames add: n]]. ^(manual, classNames) asSet asOrderedCollection! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 9/3/2008 12:00'! majorShrinkClassesToZap ^#(BDFFontReader InstanceBrowser Lexicon TarArchiveMember CRLookupResult " PluggableDictionary PluggableSet " MimeConverter QuotedPrintableMimeConverter RFC2047MimeConverter AbstractLauncher AutoStart AcornFileDirectory " AssertionFailure " CachedHTTPRequest CachingCodeLoader CodeLoader CanvasEncoder EToyVectorVocabulary EToyVocabulary FileList2 FontCache FTPConnectionException FullVocabulary HTTPClient HTTPLoader HTTPRequest HtmlFileStream "MacFileDirectory" "MacHFSPlusFileDirectory" PluginHTTPRequest SUnitNameResolver ScreenedVocabulary ScriptNameType SoundType StringType SymbolListType TestCase TestFailure TestResource TestResult TestRunner TestSuite TestCaseDebugger TestViaMethodCall TextSqkPageLink TextSqkProjectLink TextURL UnknownType Verifier VerifierOfProperty Vocabulary BooleanType ButtonPhaseType ColorType DataType GraphicType MenuType NumberType PlayerType)! ! !SystemDictionary methodsFor: 'shrinking' stamp: 'ssa 9/3/2008 13:42'! presumedSentMessages | sent | "Smalltalk presumedSentMessages" "The following should be preserved for doIts, etc" sent _ IdentitySet new. #( "menu messages from Debugger>>contextStackMenu: aMenu shifted: shifted" fullStack restart proceed doStep stepIntoBlock send where peelToFirst browseSendersOfMessages browseMessages methodHierarchy browseVersions browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables browseClassRefs browseMethodFull fileOutMessage shiftedYellowButtonActivity "menu messages from Preferences>>presentMvcFontConfigurationMenu" chooseSystemFont chooseListFont chooseMenuFont chooseWindowTitleFont chooseCodeFont restoreDefaultFonts "others" rehashWithoutBecome compactSymbolTable rebuildAllProjects browseAllSelect: printSpaceAnalysis lastRemoval scrollBarValue: scrollBarMenuButtonPressed: withSelectionFrom: to: removeClassNamed: instVarNamed:put: breakDependents maximumSize: redButtonMenu:redButtonMessages: dragon: hilberts: mandala: web test3 factorial tinyBenchmarks benchFib newDepth: restoreAfter: forgetDoIts zapAllMethods obsoleteClasses removeAllUnSentMessages abandonSources removeUnreferencedKeys reclaimDependents zapOrganization condenseChanges browseObsoleteReferences renameClassNamed:as: " this method is used in change sets " subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: variableByteSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: " subclass creation: " variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: variableWordSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: weakSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category: methodsFor:stamp: methodsFor:stamp:prior: instanceVariableNames: startTimerInterruptWatcher unusedClasses widthOfString: widthOfString:from:to: clipHeight clipHeight: clipWidth clipWidth: clipX clipX: clipY clipY: newDay:monthIndex:year: abandon pixelForValueAt:put: magnifyBy: replaceColor:withColor: dotOfSize: "DisplayScreen> " fullBoundingBox originFromUser: " finalization " toFinalizeSend:to:with: " StrikeFont> " maxAscii minAscii maxWidth firstIndent: restIndent: rightIndent: newFontArray: fontArray: readStrikeFont2Family: familySizeFace writeAsStrike2Named: " Paragraph " compositionRectangle: " Form: these methods are meeded for gif creation " colorReduced colorsUsed " protocol from Pen class: " inkBrush simplePressurePen testMouseTracking testTabletTracking " two methods that are hidden from the method tracer " method: preamble: inspectElement inspectSelection inspectBasic fileOutAllChangeSets fillAggregateChangeSet " convenience methods in True and False: " and:and: and:and:and: and:and:and:and: or:or: or:or:or: or:or:or:or: " mics " pairsDo: font: notEmpty " ExternalEvent class: " registerClient: ) do: [:sel | sent add: sel]. "The following may be sent by perform: in dispatchOnChar..." (ParagraphEditor classPool at: #CmdActions) asSet do: [:sel | sent add: sel]. (ParagraphEditor classPool at: #ShiftCmdActions) asSet do: [:sel | sent add: sel]. Smalltalk majorShrinkClassesToLeave do: [:symbol | sent addAll: (Smalltalk at: symbol) selectors; addAll: (Smalltalk at: symbol) class selectors.]. ^ sent! ! !SystemDictionary methodsFor: 'snapshot and quit' stamp: 'dmu 9/7/2010 14:26'! snapshot: save andQuit: quit embedded: embeddedFlag "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. The latter part of this method runs when resuming a previously saved image. The resume logic checks for a document file to process when starting up." | resuming msg sourceLink | Object flushDependents. Object flushEvents. save & (SourceFiles at: 2) notNil ifTrue: [msg _ (quit ifTrue: ['----QUIT----'] ifFalse: ['----SNAPSHOT----']) , Date dateAndTimeNow printString, ' ', (FileDirectory default localNameFor: self imageName). sourceLink _ ' priorSource: ' , LastQuitLogPosition printString. self assureStartupStampLogged. (SourceFiles at: 2) safelyDo: [ LastQuitLogPosition _ (SourceFiles at: 2) setToEnd; position. self logChange: msg , sourceLink. ]. Transcript cr; show: msg]. self processShutDownList: quit. Cursor write show. save ifTrue: [resuming _ embeddedFlag ifTrue: [self snapshotEmbeddedPrimitive] ifFalse: [self snapshotPrimitive]. "<-- PC frozen here on image file" resuming == false "guard against failure" ifTrue: ["Time to reclaim segment files is immediately after a save" Smalltalk at: #ImageSegment ifPresent: [:theClass | theClass reclaimObsoleteSegmentFiles]]] ifFalse: [resuming _ false]. quit & (resuming == false) ifTrue: [self quitPrimitive]. Cursor normal show. self setGCParameters. resuming == true ifTrue: [self clearExternalObjects]. self processStartUpList: resuming == true. resuming == true ifTrue:[ self setPlatformPreferences. self readDocumentFile]. "Now it's time to raise an error" resuming == nil ifTrue: [self error:'Failed to write image file (disk full?)']. ^ resuming! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'ssa 9/3/2008 11:25'! forceChangesToDisk "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." | changesFile | changesFile _ SourceFiles at: 2. (changesFile isKindOf: FileStream) ifTrue: [ changesFile flush. true ifTrue:[ changesFile close. changesFile open: changesFile name forWrite: true]. changesFile setToEnd. ]. ! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'dmu 9/7/2010 14:26'! writeRecentCharacters: nCharacters toFileNamed: aFilename "Schedule an editable text view on the last n characters of changes." | changes | changes _ SourceFiles at: 2. changes safelyDo: [ changes setToEnd; skip: nCharacters negated. (FileStream newFileNamed: aFilename) nextPutAll: (changes next: nCharacters); close; open; edit ]! ! !SystemDictionary methodsFor: 'window preferences' stamp: 'ssa 11/30/2009 17:48'! recolorWindows "Smalltalk recolorWindows" "Let the user define the color scheme for all my windows" | menu choice color | menu _ PopUpMenu labels:'one color for all windows\standard color palette' withCRs. choice _ menu startUp. choice = 0 ifTrue:[^self]. choice = 1 ifTrue:[color _ Color fromUser. Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| color]]. choice = 2 ifTrue:[ Smalltalk at: #WINDOWCOLORSELECTOR put:[:obj| Preferences windowColorFor: obj class name]]. self updateAllWindowColors! ! !SystemDictionary methodsFor: 'window preferences' stamp: 'ssa 11/30/2009 17:48'! updateAllWindowColors "Smalltalk updateAllWindowColors" Cursor wait showWhile:[ View allSubInstances do:[:v| v backgroundColor: v model defaultBackgroundColor]. ScheduledControllers unCacheWindows;restore]! ! !SystemNavigation methodsFor: '*Sly' stamp: 'dmu 8/23/2010 15:39'! parallelAllMethodsWithSourceString: aString matchCase: caseSensitive "Answer a SortedCollection of all the methods that contain, in source code, aString as a substring. Search the class comments also" "An experiment -- dmu" | list classCount adder sema | list _ Set new. sema _ Semaphore forMutualExclusion. adder _ [ :mrClass :mrSel | sema critical: [list add: ( MethodReference new setStandardClass: mrClass methodSymbol: mrSel)]]. 'Searching all source code...' displayProgressAt: Sensor cursorPoint from: 0 to: Smalltalk classNames size during: [:bar | classCount _ 0. Smalltalk allClassesDoInParallel: [:class | bar value: (classCount _ classCount + 1). (Array with: class with: class class) do: [:cl | cl selectorsDo: [:sel | ((cl sourceCodeAt: sel) findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ sel == #DoIt ifFalse: [adder copy fixTemps value: cl value: sel]]]. (cl organization classComment asString findString: aString startingAt: 1 caseSensitive: caseSensitive) > 0 ifTrue: [ adder copy fixTemps value: cl value: #Comment]. ]]]. ^ list asSortedCollection! ! !TestAsserter methodsFor: 'asserting'! assert: aBoolean aBoolean ifFalse: [self logFailure: 'Assertion failed'. TestResult failure signal: 'Assertion failed'].! ! !TestAsserter methodsFor: 'asserting'! assert: aBoolean description: aString aBoolean ifFalse: [self logFailure: aString. TestResult failure signal: aString].! ! !TestAsserter methodsFor: 'asserting'! assert: aBoolean description: aString resumable: resumableBoolean | exception | aBoolean ifFalse: [self logFailure: aString. exception := resumableBoolean ifTrue: [TestResult resumableFailure] ifFalse: [TestResult failure]. exception signal: aString].! ! !TestAsserter methodsFor: 'asserting'! deny: aBoolean self assert: aBoolean not.! ! !TestAsserter methodsFor: 'asserting'! deny: aBoolean description: aString self assert: aBoolean not description: aString.! ! !TestAsserter methodsFor: 'asserting'! deny: aBoolean description: aString resumable: resumableBoolean self assert: aBoolean not description: aString resumable: resumableBoolean.! ! !TestAsserter methodsFor: 'asserting'! should: aBlock raise: anExceptionalEvent self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent).! ! !TestAsserter methodsFor: 'asserting'! should: aBlock raise: anExceptionalEvent description: aString self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) description: aString.! ! !TestAsserter methodsFor: 'asserting'! shouldnt: aBlock raise: anExceptionalEvent self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) not.! ! !TestAsserter methodsFor: 'asserting'! shouldnt: aBlock raise: anExceptionalEvent description: aString self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) not description: aString.! ! !TestAsserter methodsFor: 'convenience' stamp: 'nfr 1/3/2010 18:38'! assert: anObject equals: anotherObject self assert: anObject = anotherObject description: anObject printString , ' is not equal to ' , anotherObject printString.! ! !TestAsserter methodsFor: 'logging'! logFailure: aString self class logFailure: aString.! ! !TestAsserter methodsFor: 'private'! executeShould: aBlock inScopeOf: anExceptionalEvent ^[aBlock value. false] on: anExceptionalEvent do: [:ex | ex sunitExitWith: true]! ! !TestAsserter commentStamp: '<historical>' prior: 0! I understand methods beginning #assert:... and #deny:... (and my class-side understands #assert:description:). I am the superclass of TestCase and TestResource and can also be the superclass of any test helper classes you create to factor out test behaviour. I exist so that test code can be refactored between my subclasses without difficulty. Send #assert:description: when you want to check for an expected value. For example, you might say self assert: socket isOpen description: 'We requested a socket but now it is not open'. to test whether or not a socket is open at a point in a test. Use description strings both to give more information about where a test failed in debugger notifiers and logs, and to document the intent of a test. Other methods include #assert:, #assert:description:resumable:, #deny:, #deny:description:, #deny:description:resumable:, #should:raise:, #should:raise:description:, #shouldnt:raise:, #shouldnt:raise:description:. All these methods are defined on the superclass, TestAsserter. (Any convenience assertion methods you create for general use should also be defined in my 'convenience' protocol.) Override my class-side #isLogging in subclasses to have failed assertion descriptions shown on the Transcript. To have them appear elsewhere, also override my class-side #failureLog. ! !TestAsserter class methodsFor: 'asserting'! assert: aBoolean description: aString "Minimal clone of the instance-side assert protocol so that class-side methods can use it." aBoolean ifFalse: [self logFailure: aString. TestResult failure signal: aString].! ! !TestAsserter class methodsFor: 'logging'! failureLog ^Transcript! ! !TestAsserter class methodsFor: 'logging'! isLogging "By default, we're not logging failures. Override in subclasses as desired." ^false! ! !TestAsserter class methodsFor: 'logging'! logFailure: aString self isLogging ifTrue: [self failureLog cr; nextPutAll: aString; flush].! ! !TestCase methodsFor: 'accessing'! resources "We give TestCase this instance-side method so that methods polymorphic with TestSuite can be code-identical. Having this instance-side method also helps when writing tests of resource behaviour. Except for such tests, it is rare to override this method and should not be done without thought. If there were a good reason why a single test case needed to share tests requiring different resources, it might be legitimate." ^self class resources! ! !TestCase methodsFor: 'accessing'! selector ^testSelector! ! !TestCase methodsFor: 'asserting'! assert: aBoolean aBoolean ifFalse: [self signalFailure: 'Assertion failed'] ! ! !TestCase methodsFor: 'asserting' stamp: 'md 8/2/2006 11:00'! assert: aBooleanOrBlock description: aString aBooleanOrBlock value ifFalse: [ self logFailure: aString. TestResult failure signal: aString] ! ! !TestCase methodsFor: 'asserting' stamp: 'md 8/2/2006 11:00'! assert: aBooleanOrBlock description: aString resumable: resumableBoolean | exception | aBooleanOrBlock value ifFalse: [self logFailure: aString. exception := resumableBoolean ifTrue: [TestResult resumableFailure] ifFalse: [TestResult failure]. exception signal: aString] ! ! !TestCase methodsFor: 'asserting' stamp: 'dc 4/2/2007 18:38'! assert: expected equals: actual ^ self assert: (expected = actual) description: (self comparingStringBetween: expected and: actual) ! ! !TestCase methodsFor: 'asserting'! deny: aBoolean self assert: aBoolean not ! ! !TestCase methodsFor: 'asserting' stamp: 'md 8/2/2006 11:00'! deny: aBooleanOrBlock description: aString self assert: aBooleanOrBlock value not description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'md 8/2/2006 11:00'! deny: aBooleanOrBlock description: aString resumable: resumableBoolean self assert: aBooleanOrBlock value not description: aString resumable: resumableBoolean ! ! !TestCase methodsFor: 'asserting'! should: aBlock raise: anExceptionalEvent ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) ! ! !TestCase methodsFor: 'asserting'! should: aBlock raise: anExceptionalEvent description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'nk 5/11/2003 10:32'! should: aBlock raise: anExceptionalEvent whoseDescriptionDoesNotInclude: subString description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionNotContaining: subString) description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'nk 5/11/2003 10:24'! should: aBlock raise: anExceptionalEvent whoseDescriptionIncludes: subString description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionContaining: subString) description: aString ! ! !TestCase methodsFor: 'asserting'! shouldnt: aBlock raise: anExceptionalEvent ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) not ! ! !TestCase methodsFor: 'asserting'! shouldnt: aBlock raise: anExceptionalEvent description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent) not description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'nk 5/11/2003 10:34'! shouldnt: aBlock raise: anExceptionalEvent whoseDescriptionDoesNotInclude: subString description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionNotContaining: subString) not description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'nk 5/11/2003 10:34'! shouldnt: aBlock raise: anExceptionalEvent whoseDescriptionIncludes: subString description: aString ^self assert: (self executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionContaining: subString) not description: aString ! ! !TestCase methodsFor: 'asserting' stamp: 'md 2/22/2006 14:26'! signalFailure: aString TestResult failure signal: aString! ! !TestCase methodsFor: 'dependencies'! addDependentToHierachy: anObject "an empty method. for Composite compability with TestSuite"! ! !TestCase methodsFor: 'dependencies'! removeDependentFromHierachy: anObject "an empty method. for Composite compability with TestSuite"! ! !TestCase methodsFor: 'deprecated'! should: aBlock self assert: aBlock value! ! !TestCase methodsFor: 'deprecated'! should: aBlock description: aString self assert: aBlock value description: aString! ! !TestCase methodsFor: 'deprecated'! shouldnt: aBlock self deny: aBlock value! ! !TestCase methodsFor: 'deprecated'! shouldnt: aBlock description: aString self deny: aBlock value description: aString! ! !TestCase methodsFor: 'events'! announce: anAnnouncementClass ^ self announce: anAnnouncementClass with: nil! ! !TestCase methodsFor: 'events' stamp: 'tbn 4/26/2011 09:58'! announce: anAnnouncementClass withResult: result | event | self shouldAnnounce ifFalse: [ ^ self ]. event := anAnnouncementClass asAnnouncement. event testCase: self. event testSelector: testSelector. event testResult: result. self announcer announce: event.! ! !TestCase methodsFor: 'events'! announcer ^ self class announcer! ! !TestCase methodsFor: 'events'! shouldAnnounce ^ self class shouldAnnounce! ! !TestCase methodsFor: 'extensions' stamp: 'mx 3/20/2006 23:32'! executeShould: aBlock inScopeOf: anException withExceptionDo: anotherBlock ^[aBlock value. false] on: anException do: [:exception | anotherBlock value: exception. exception return: true]! ! !TestCase methodsFor: 'extensions' stamp: 'mx 3/13/2006 23:21'! fail ^self assert: false! ! !TestCase methodsFor: 'extensions'! should: aBlock notTakeMoreThan: aDuration "Evaluate aBlock in a forked process and if it takes more than anInteger milliseconds to run we terminate the process and report a test failure. It'' important to use the active process for the test failure so that the failure reporting works correctly in the context of the exception handlers." | evaluated evaluationProcess result delay testProcess | evaluated := false. delay := Delay forDuration: aDuration. testProcess := Processor activeProcess. "Create a new process to evaluate aBlock" evaluationProcess := [ result := aBlock value. evaluated := true. delay unschedule. testProcess resume ] forkNamed: 'Process to evaluate should: notTakeMoreThanMilliseconds:'. "Wait the milliseconds they asked me to" delay wait. "After this point either aBlock was evaluated or not..." evaluated ifFalse: [ evaluationProcess terminate. self assert: false description: ('Block evaluation took more than the expected <1p>' expandMacrosWith: aDuration)]. ^result! ! !TestCase methodsFor: 'extensions' stamp: 'md 8/2/2006 11:08'! should: aBlock notTakeMoreThanMilliseconds: anInteger "For compatibility with other Smalltalks" self should: aBlock notTakeMoreThan: (Duration milliSeconds: anInteger).! ! !TestCase methodsFor: 'extensions' stamp: 'mx 3/20/2006 23:52'! should: aBlock raise: anException withExceptionDo: anotherBlock ^self assert: (self executeShould: aBlock inScopeOf: anException withExceptionDo: anotherBlock)! ! !TestCase methodsFor: 'extensions' stamp: 'mx 3/20/2006 21:29'! shouldFix: aBlock ^self should: aBlock raise: Exception! ! !TestCase methodsFor: 'printing'! printOn: aStream aStream nextPutAll: self class printString; nextPutAll: '>>#'; nextPutAll: testSelector! ! !TestCase methodsFor: 'running'! debug [(self class selector: testSelector) runCase] ensure: [TestResource resetResources: self resources]! ! !TestCase methodsFor: 'running' stamp: 'nfr 1/3/2010 18:04'! debugAsFailure | semaphore | semaphore := Semaphore new. [semaphore wait. TestResource resetResources: self resources] fork. (self class selector: testSelector) runCaseAsFailure: semaphore! ! !TestCase methodsFor: 'running' stamp: 'md 2/22/2006 14:17'! failureLog ^Transcript ! ! !TestCase methodsFor: 'running'! isLogging "By default, we're not logging failures. If you override this in a subclass, make sure that you override #failureLog" ^false ! ! !TestCase methodsFor: 'running'! logFailure: aString self isLogging ifTrue: [ self failureLog cr; nextPutAll: aString; flush] ! ! !TestCase methodsFor: 'running'! openDebuggerOnFailingTestMethod "SUnit has halted one step in front of the failing test method. Step over the 'self halt' and send into 'self perform: testSelector' to see the failure from the beginning" self halt; performTest! ! !TestCase methodsFor: 'running'! prepareToRunAgain "Used by the debugger when a test is restarted I'm not 'hidding'' possible exceptions because I think it is best to popup a new debugger if some one occurs and let the programmer decide what to do - Hernan" self tearDown; setUp! ! !TestCase methodsFor: 'running'! run | result | result := TestResult new. [self run: result] ensure: [TestResource resetResources: self resources]. ^result! ! !TestCase methodsFor: 'running'! run: aResult aResult runCase: self! ! !TestCase methodsFor: 'running'! runCase self resources do: [:each | each availableFor: self]. [self setUp. self performTest] ensure: [ self tearDown. self cleanUpInstanceVariables]! ! !TestCase methodsFor: 'running'! runCaseAsFailure: aSemaphore [self resources do: [:each | each availableFor: self]. [self setUp. self openDebuggerOnFailingTestMethod] ensure: [self tearDown]] ensure: [aSemaphore signal]! ! !TestCase methodsFor: 'running'! setUp! ! !TestCase methodsFor: 'running'! tearDown ! ! !TestCase methodsFor: 'testing'! expectedFailures "| pragmas | pragmas := Pragma allNamed: #expectedFailure from: self class to: Object. ^ pragmas collect: [:each | each method selector ]. this implementation is far too slow and block the execution of tests since just for printing a test it scans all the literal of the system. So I reverted the old way of declaring expectedFailures " ^ Array new! ! !TestCase methodsFor: 'testing' stamp: 'JF 7/30/2003 13:39'! shouldPass "Unless the selector is in the list we get from #expectedFailures, we expect it to pass" ^ (self expectedFailures includes: testSelector) not! ! !TestCase methodsFor: 'private'! cleanUpInstanceVariables self class allInstVarNames do: [ :name | name = 'testSelector' ifFalse: [ self instVarNamed: name put: nil ] ]! ! !TestCase methodsFor: 'private' stamp: 'dc 4/2/2007 18:46'! comparingStringBetween: expected and: actual ^ String streamContents: [:stream | stream nextPutAll: 'Expected '; nextPutAll: (expected printStringLimitedTo: 10); nextPutAll: ' but was '; nextPutAll: (actual printStringLimitedTo: 10); nextPutAll: '.' ]! ! !TestCase methodsFor: 'private' stamp: 'md 2/22/2006 14:27'! executeShould: aBlock inScopeOf: anExceptionalEvent ^[aBlock value. false] on: anExceptionalEvent do: [:ex | ex return: true] ! ! !TestCase methodsFor: 'private' stamp: 'md 2/22/2006 14:27'! executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionContaining: aString ^[aBlock value. false] on: anExceptionalEvent do: [:ex | ex return: (ex description includesSubString: aString) ] ! ! !TestCase methodsFor: 'private' stamp: 'md 2/22/2006 14:27'! executeShould: aBlock inScopeOf: anExceptionalEvent withDescriptionNotContaining: aString ^[aBlock value. false] on: anExceptionalEvent do: [:ex | ex return: (ex description includesSubString: aString) not ] ! ! !TestCase methodsFor: 'private'! performTest self perform: testSelector asSymbol! ! !TestCase methodsFor: 'private'! setTestSelector: aSymbol testSelector := aSymbol! ! !TestCase commentStamp: 'nfr 1/3/2010 17:56' prior: 0! A TestCase is an implementation of the Command pattern to run a test. TestCase instances are created with the class method #selector:, passing the symbol that names the method to be executed when the test case runs. Various UIs exist to run these instances and they can also be created and run programmatically. When you discover a new fixture, subclass TestCase and create a #test... method for the first test. As that method develops and more #test... methods are added, you will find yourself refactoring temps into instance variables for the objects in the fixture and overriding #setUp to initialize these variables. As required, override #tearDown to nil references, release objects and deallocate. See my superclass' comment for assertion and logging information.! !TestCase class methodsFor: 'accessing' stamp: ' 17/7/10 17:28'! allTestSelectors | answer pivotClass lookupRoot | answer := Set withAll: self testSelectors. self shouldInheritSelectors ifTrue: [pivotClass := self. lookupRoot := self lookupHierarchyRoot. [pivotClass == lookupRoot] whileFalse: [pivotClass := pivotClass superclass. answer addAll: pivotClass testSelectors]]. ^answer asSortedCollection asOrderedCollection! ! !TestCase class methodsFor: 'accessing' stamp: ' 17/7/10 17:28'! lookupHierarchyRoot ^TestCase! ! !TestCase class methodsFor: 'accessing'! resources ^#()! ! !TestCase class methodsFor: 'accessing' stamp: ' 17/7/10 17:28'! sunitVersion ^'4.0'! ! !TestCase class methodsFor: 'accessing'! testSelectors ^(self selectors select: [ :each | (each beginsWith: 'test') and: [each numArgs isZero]])! ! !TestCase class methodsFor: 'building suites' stamp: 'lr 3/14/2010 21:13'! addTestsFor: classNameString toSuite: suite | cls | cls := Smalltalk globals at: classNameString ifAbsent: [ ^ suite ]. ^ cls isAbstract ifTrue: [ cls allSubclasses do: [ :each | each isAbstract ifFalse: [ each addToSuiteFromSelectors: suite ] ]. suite ] ifFalse: [ cls addToSuiteFromSelectors: suite ]! ! !TestCase class methodsFor: 'building suites' stamp: 'nk 4/21/2002 10:51'! addToSuite: suite fromMethods: testMethods testMethods do: [ :selector | suite addTest: (self selector: selector) ]. ^suite! ! !TestCase class methodsFor: 'building suites' stamp: 'nk 4/21/2002 16:37'! addToSuiteFromSelectors: suite ^self addToSuite: suite fromMethods: (self shouldInheritSelectors ifTrue: [ self allTestSelectors ] ifFalse: [self testSelectors ])! ! !TestCase class methodsFor: 'building suites'! buildSuite | suite | ^self isAbstract ifTrue: [suite := self suiteClass named: self name asString. self allSubclasses do: [:each | each isAbstract ifFalse: [suite addTest: each buildSuiteFromSelectors]]. suite] ifFalse: [self buildSuiteFromSelectors]! ! !TestCase class methodsFor: 'building suites'! buildSuiteFromAllSelectors ^self buildSuiteFromMethods: self allTestSelectors ! ! !TestCase class methodsFor: 'building suites'! buildSuiteFromLocalSelectors ^self buildSuiteFromMethods: self testSelectors ! ! !TestCase class methodsFor: 'building suites'! buildSuiteFromMethods: testMethods ^testMethods inject: (self suiteClass named: self name asString) into: [:suite :selector | suite addTest: (self selector: selector); yourself]! ! !TestCase class methodsFor: 'building suites' stamp: ' 17/7/10 17:28'! buildSuiteFromSelectors ^self buildSuiteFromMethods: self allTestSelectors! ! !TestCase class methodsFor: 'building suites'! suiteClass ^TestSuite! ! !TestCase class methodsFor: 'coverage' stamp: 'lr 3/14/2010 21:13'! coverage "returns the coverage determined by a simple static analysis of test coverage made by the receiver on a class that is identified by the name of the receiver. We assume that SetTest test Set." | cls className | (self name endsWith: 'Test') ifFalse: [ self error: 'Please, use #coverageForClass: instead' ]. className := self name copyFrom: 1 to: self name size - 'Test' size. cls := Smalltalk globals at: className asSymbol ifAbsent: [ self error: 'Please, use #coverageForClass: instead' ]. "May happen with Transcript" cls isBehavior ifFalse: [ cls := cls class ]. ^ self coverageForClass: cls! ! !TestCase class methodsFor: 'coverage' stamp: 'ab 12/25/2008 17:20'! coverageAsString | cov className | cov := self coverage first asInteger. "coverage already checks that the name is ends with 'Test' and if the class tested exists" className := self name copyFrom: 1 to: (self name size - 'Test' size). ^ self name asString, ' covers ', cov asString, '% of ', className.! ! !TestCase class methodsFor: 'coverage' stamp: 'sd 1/28/2009 14:57'! coverageForClass: cls "returns the test coverage of all the methods included inherited ones" ^ self coverageForClass: cls until: ProtoObject! ! !TestCase class methodsFor: 'coverage' stamp: 'sd 1/28/2009 14:58'! coverageForClass: cls until: aRootClass "returns the test coverage of all the methods included inherited ones but stopping at aRootClass included" | definedMethods testedMethods untestedMethods | definedMethods := cls allSelectorsAboveUntil: aRootClass. definedMethods size = 0 ifTrue: [^ {0. Set new}]. testedMethods := self methodDictionary values inject: Set new into: [:sums :cm | sums union: cm messages]. testedMethods := testedMethods reject: [:sel | (definedMethods includes: sel) not]. untestedMethods := definedMethods select: [:selector | (testedMethods includes: selector) not]. ^ { (testedMethods size * 100 / definedMethods size) asFloat . untestedMethods} ! ! !TestCase class methodsFor: 'coverage' stamp: 'ab 12/25/2008 17:15'! coveragePercentage ^ self coverage first! ! !TestCase class methodsFor: 'coverage' stamp: 'lr 3/14/2010 21:13'! localCoverage "returns the coverage determined by a simple static analysis of test coverage made by the receiver on a class that is identified by the name of the receiver. We assume that SetTest test Set. The computation of the coverage takes only into account the methods defined locally in the tested class. See coverage for a more global coverage" | cls className | (self name endsWith: 'Test') ifFalse: [ self error: 'Please, use #localCoverageForClass: instead' ]. className := self name copyFrom: 1 to: self name size - 'Test' size. cls := Smalltalk globals at: className asSymbol ifAbsent: [ self error: 'Please, use #localCoverageForClass: instead' ]. cls isBehavior ifFalse: [ cls := cls class ]. ^ self localCoverageForClass: cls! ! !TestCase class methodsFor: 'coverage' stamp: 'sd 1/28/2009 15:04'! localCoverageAsString | cov className | cov := self localCoverage first asInteger. "coverage already checks that the name is ends with 'Test' and if the class tested exists" className := self name copyFrom: 1 to: (self name size - 'Test' size). ^ self name asString, ' covers ', cov asString, '% of ', className.! ! !TestCase class methodsFor: 'coverage' stamp: 'sd 1/28/2009 14:55'! localCoverageForClass: cls | definedMethods testedMethods untestedMethods | definedMethods := cls selectors. "It happens for IdentityBag / IdentityBagTest" definedMethods size = 0 ifTrue: [^ {0. Set new}]. testedMethods := self methodDictionary values inject: Set new into: [:sums :cm | sums union: cm messages]. "testedMethods contains all the methods send in test methods, which probably contains methods that have nothign to do with collection" testedMethods := testedMethods reject: [:sel | (definedMethods includes: sel) not]. untestedMethods := definedMethods select: [:selector | (testedMethods includes: selector) not]. ^ { (testedMethods size * 100 / definedMethods size) asFloat . untestedMethods} ! ! !TestCase class methodsFor: 'coverage' stamp: 'sd 1/28/2009 14:55'! localCoveragePercentage ^ self localCoverage first! ! !TestCase class methodsFor: 'events'! announcer ^ self announcers at: self ifAbsentPut: [ Announcer new ]! ! !TestCase class methodsFor: 'events'! announcers ^ Announcers ifNil: [ Announcers := Dictionary new ] ! ! !TestCase class methodsFor: 'events'! resetAnnouncer self announcers removeKey: self ifAbsent: []! ! !TestCase class methodsFor: 'events'! shouldAnnounce ^ self announcers includesKey: self! ! !TestCase class methodsFor: 'history'! generateLastStoredRunMethod self shouldGenerateLastStoredRunMethod ifTrue: [ self class compile: (self lastRunMethodNamed: #lastStoredRun) classified: 'history' ]! ! !TestCase class methodsFor: 'history'! history ^ history ifNil: [ history := self newTestDictionary ]! ! !TestCase class methodsFor: 'history'! history: aDictionary history := aDictionary! ! !TestCase class methodsFor: 'history'! lastRun ^ TestResult historyFor: self! ! !TestCase class methodsFor: 'history'! lastRunMethodNamed: aSelector ^ String streamContents: [:str | str nextPutAll: aSelector asString ;cr. str tab; nextPutAll: '^ ', (self lastRun) storeString] ! ! !TestCase class methodsFor: 'history'! lastStoredRun ^ ((Dictionary new) add: (#failures->#()); add: (#passed->#()); add: (#errors->#()); yourself)! ! !TestCase class methodsFor: 'history'! newTestDictionary ^ Dictionary new at: #timeStamp put: DateAndTime now; at: #passed put: Set new; at: #failures put: Set new; at: #errors put: Set new; yourself ! ! !TestCase class methodsFor: 'history'! resetHistory history := nil! ! !TestCase class methodsFor: 'history'! shouldGenerateLastStoredRunMethod | sameRun | (self class methodDictionary includesKey: #lastStoredRun) ifFalse: [^ true]. sameRun := #(#passed #failures #errors) inject: true into: [ :ok :set | ok and: [(self lastRun at: set) = (self lastStoredRun at: set) ]]. ^ sameRun not ! ! !TestCase class methodsFor: 'initialize - event'! initialize super initialize. (SystemChangeNotifier respondsTo: #notify:ofSystemChangesOfItem:using:) ifTrue: [ SystemChangeNotifier uniqueInstance notify: self ofSystemChangesOfItem: #method using: #methodChanged:. ]. "STEFAN: Not sure what the implication is of not having the notifications." ! ! !TestCase class methodsFor: 'initialize - event' stamp: 'al 2/9/2009 20:00'! methodChanged: anEvent "Remove the changed method from the known test results." | cls sel | anEvent item isCompiledMethod ifFalse: [ ^ self ]. cls := anEvent item methodClass. (cls inheritsFrom: TestCase) ifFalse: [^ self]. sel := anEvent item selector. (sel beginsWith: 'test') ifFalse: [^ self]. TestResult removeFromTestHistory: sel in: cls. ! ! !TestCase class methodsFor: 'instance creation'! debug: aSymbol ^(self selector: aSymbol) debug! ! !TestCase class methodsFor: 'instance creation'! run: aSymbol ^(self selector: aSymbol) run! ! !TestCase class methodsFor: 'instance creation'! selector: aSymbol ^self new setTestSelector: aSymbol! ! !TestCase class methodsFor: 'instance creation'! suite ^self buildSuite! ! !TestCase class methodsFor: 'testing'! hasMethodBeenRun: aSelector ^ ((self lastRun at: #errors), (self lastRun at: #failures), (self lastRun at: #passed)) includes: aSelector! ! !TestCase class methodsFor: 'testing' stamp: 'md 2/22/2006 14:21'! isAbstract "Override to true if a TestCase subclass is Abstract and should not have TestCase instances built from it" ^self name = #TestCase ! ! !TestCase class methodsFor: 'testing'! isUnitTest ^true! ! !TestCase class methodsFor: 'testing'! methodFailed: aSelector ^ (self lastRun at: #failures) includes: aSelector! ! !TestCase class methodsFor: 'testing'! methodPassed: aSelector ^ (self lastRun at: #passed) includes: aSelector! ! !TestCase class methodsFor: 'testing'! methodProgressed: aSelector ^ ((self storedMethodRaisedError: aSelector) or: [self storedMethodFailed: aSelector]) and: [self methodPassed: aSelector] ! ! !TestCase class methodsFor: 'testing'! methodRaisedError: aSelector ^ (self lastRun at: #errors) includes: aSelector! ! !TestCase class methodsFor: 'testing'! methodRegressed: aSelector ^ (self storedMethodPassed: aSelector) and: [(self methodFailed: aSelector) or: [self methodRaisedError: aSelector]]! ! !TestCase class methodsFor: 'testing' stamp: ' 17/7/10 17:28'! shouldInheritSelectors "I should inherit from an Abstract superclass but not from a concrete one by default, unless I have no testSelectors in which case I must be expecting to inherit them from my superclass. If a test case with selectors wants to inherit selectors from a concrete superclass, override this to true in that subclass." ^self ~~ self lookupHierarchyRoot and: [self superclass isAbstract or: [self testSelectors isEmpty]]! ! !TestCase class methodsFor: 'testing'! storedMethodFailed: aSelector ^ (self lastStoredRun at: #failures) includes: aSelector! ! !TestCase class methodsFor: 'testing'! storedMethodPassed: aSelector ^ (self lastStoredRun at: #passed) includes: aSelector! ! !TestCase class methodsFor: 'testing'! storedMethodRaisedError: aSelector ^ (self lastStoredRun at: #errors) includes: aSelector! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:56'! testCase "Returns the test case." ^testCase! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:56'! testCase: aTestCase "Sets the test case to the given test case." testCase := aTestCase! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:56'! testResult "Returns the test result." ^testResult! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:56'! testResult: aTestResult "Sets the test result to the given test result." testResult := aTestResult! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:56'! testSelector "Returns the test selector." ^testSelector! ! !TestCaseAnnouncement methodsFor: 'accessing' stamp: 'tbn 4/26/2011 09:57'! testSelector: aSymbol "Sets the test selector to the given symbol." testSelector := aSymbol! ! !TestCaseAnnouncement methodsFor: 'testing' stamp: 'tbn 4/26/2011 09:57'! hasErrors "Return true if the test result has errors." ^testResult hasErrors! ! !TestCaseAnnouncement methodsFor: 'testing' stamp: 'tbn 4/26/2011 09:57'! hasFailures "Return true if the test result has failures." ^testResult hasFailures! ! !TestCaseAnnouncement methodsFor: 'testing' stamp: 'tbn 4/26/2011 09:58'! hasPassed "Return true if the test has passed." ^testResult hasPassed! ! !TestCaseAnnouncement commentStamp: 'tbn 4/26/2011 09:54' prior: 0! This is a common superclass for announcements related to SUnit test cases. Instance Variables testCase: <TestCase> testResult: <TestResult> testSelector: <Symbol> testCase - The test case testResult - The result of the test case testSelector - The selector of the test method! !TestCaseEnded commentStamp: 'tbn 4/26/2011 09:55' prior: 0! This event is announced when testing a test case ends.! !TestCaseStarted commentStamp: 'tbn 4/26/2011 09:55' prior: 0! This event is announced when testing a test case starts.! !TestCaseTest methodsFor: 'events' stamp: 'jannik.laval 10/1/2010 14:15'! testAnnouncement | collection oldCollection suite unitTest | unitTest := ClassFactoryForTestCaseTest. collection := OrderedCollection new. unitTest resetAnnouncer. self deny: (unitTest shouldAnnounce). self deny: (unitTest new shouldAnnounce). unitTest announcer on: TestCaseAnnouncement do: [:ann | collection add: ann ]. self assert: (unitTest shouldAnnounce). self assert: (unitTest new shouldAnnounce). "We run SUnitTest" suite := unitTest buildSuite. suite run. self assert: (collection size = (suite tests size * 2)). self assert: (collection select: [:c | c isKindOf: TestCaseStarted]) size = (collection size / 2). self assert: (collection select: [:c | c isKindOf: TestCaseEnded]) size =( collection size / 2). self assert: (collection allSatisfy: #hasPassed). self deny: (collection anySatisfy: #hasFailures). oldCollection := collection copy. unitTest resetAnnouncer. unitTest debug: #testClassCreationInDifferentCategories. self assert: (collection = oldCollection)! ! !TestCaseTest methodsFor: 'testing' stamp: 'sm 5/25/2011 01:14'! expectedFailures ^ {#testAnnouncement }.! ! !TestCaseTest methodsFor: 'testing' stamp: 'JorgeRessia 3/16/2010 20:57'! testIsUnitTest self assert: TestCase isUnitTest! ! !TestConsoleRunner methodsFor: 'initialization' stamp: 'StefanMarr 7/14/2011 17:18'! initialize super initialize. stream := self class defaultOutputTarget! ! !TestConsoleRunner methodsFor: 'initialization'! initializeOn: aTestSuite suite := aTestSuite. suitePosition := suiteTime := suiteFailures := suiteErrors := 0! ! !TestConsoleRunner methodsFor: 'running' stamp: 'StefanMarr 7/14/2011 17:26'! run | execBlock | execBlock := [ [ self setUp. suiteTime := [ self runAll ] timeToRun ] ensure: [ self tearDown. self overviewReport. ] ]. (Smalltalk at: #Author ifAbsent: [ execBlock value. ^ self ]) uniqueInstance ifUnknownAuthorUse: 'TestConsoleRunner' during: execBlock.! ! !TestConsoleRunner methodsFor: 'running'! runAll suite tests do: [ :each | each run: self ]! ! !TestConsoleRunner methodsFor: 'running' stamp: 'StefanMarr 7/14/2011 17:27'! runCase: aTestCase | error runtime stack | runtime := [ [ aTestCase announce: TestCaseStarted withResult: self. aTestCase runCase. aTestCase announce: TestCaseEnded withResult: self. self addPass: aTestCase.] on: Halt , Error, TestFailure, self class failure, self class error do: [ :err | error := err. stack := self stackTraceString: err of: aTestCase. err sunitAnnounce: aTestCase toResult: self ] ] timeToRun. self beginTestCase: aTestCase time: runtime. (error isNil or: [ aTestCase expectedFailures includes: aTestCase selector ]) ifFalse: [ (error isKindOf: TestFailure) ifTrue: [ self writeError: error stack: stack ] ifFalse: [ self writeError: error stack: stack ] ]. self endTestCase! ! !TestConsoleRunner methodsFor: 'running'! setUp stream nextPutAll: 'TestSuite '; nextPutAll: suite name; nextPutAll: ':'; nextPut: Character lf. stream nextPutAll: 'Tests: '; print: suite tests size; nextPut: Character lf. "Initialize the test resources." suite resources do: [ :each | each isAvailable ifFalse: [ each signalInitializationError ] ]! ! !TestConsoleRunner methodsFor: 'running'! tearDown suite resources do: [ :each | each reset ]. stream nextPutAll: 'failures='; print: suiteFailures; tab; nextPutAll:'errors='; print: suiteErrors; tab; nextPutAll: 'time='; print: suiteTime / 1000.0; nextPut: Character lf. ! ! !TestConsoleRunner methodsFor: 'private'! beginTestCase: aTestCase time: time stream tab; nextPutAll: (aTestCase class category); nextPut: $.; nextPutAll: (aTestCase class name); nextPut: $.; nextPutAll: (aTestCase selector); tab; nextPutAll: 'time='; print: time / 1000.0; nextPut: Character lf! ! !TestConsoleRunner methodsFor: 'private'! endTestCase stream tab; nextPut: Character lf! ! !TestConsoleRunner methodsFor: 'private'! stackTraceString: err of: aTestCase ^ String streamContents: [ :str | | context | context := err signalerContext. [ context isNil or: [ context receiver == aTestCase and: [ context methodSelector == #runCase ] ] ] whileFalse: [ str print: context; nextPut: Character lf. context := context sender ] ] ! ! !TestConsoleRunner methodsFor: 'private'! writeError: error stack: stack suiteErrors := suiteErrors + 1. stream tab; tab; nextPutAll: 'Error type='; nextPutAll: (error class name); tab; nextPutAll: ' message='; nextPutAll: (error messageText ifNil: [ error description ]); nextPut: Character lf; nextPutAll: stack; nextPut: Character lf; nextPut: Character lf! ! !TestConsoleRunner methodsFor: 'private'! writeFailure: error stack: stack suiteFailures := suiteFailures + 1. stream tab; tab; nextPutAll: 'Failure type='; nextPutAll: (error class name); tab; nextPutAll: 'message='; nextPutAll: (error messageText ifNil: [ error description ]); nextPut: Character lf; nextPutAll: stack; nextPut: Character lf; nextPut: Character lf! ! !TestConsoleRunner methodsFor: 'reporting' stamp: 'StefanMarr 7/14/2011 17:17'! overviewReport | report results | results := self. report := stream. "Old code..." [report nextPutAll: SystemVersion current version; cr. report nextPutAll: 'Time: '; nextPutAll: DateAndTime now asString; cr; cr. report nextPutAll: 'Run: '; nextPutAll: results runCount asString; cr. report nextPutAll: 'Expected passes: '; nextPutAll: results expectedPassCount asString; cr. report nextPutAll: '------------------------------'; cr. report nextPutAll: 'Expected failures: '; nextPutAll: results expectedDefectCount asString; cr. results expectedDefects do: [:each | report tab; nextPutAll: each asString; cr ]. report nextPutAll: '------------------------------'; cr. report nextPutAll: 'Unexpected failures: '; nextPutAll: results unexpectedFailureCount asString; cr. results unexpectedFailures do: [:each | report tab; nextPutAll: each asString; cr ]. report nextPutAll: '------------------------------'; cr. report nextPutAll: 'Errors: '; nextPutAll: results unexpectedErrors size asString; cr. results unexpectedErrors do: [:each | report tab; nextPutAll: each asString; cr ]. report nextPutAll: '------------------------------'; cr. report nextPutAll: 'Unexpected passes: '; nextPutAll: results unexpectedPasses size asString; cr. report flush. results unexpectedPasses do: [:each | report tab; nextPutAll: each asString; cr ]. ] on: Error do: [:e | report cr; nextPutAll: 'INTERNAL ERROR'; cr. report nextPutAll: e asString; cr; cr. "thisContext stack copy withIndexDo: [:stck :i | [report nextPutAll: i asString; space; nextPutAll: stck asString; cr] ifError: []]." ]. report flush.! ! !TestConsoleRunner class methodsFor: 'running' stamp: 'sm 5/25/2011 16:05'! runAllTests self runClasses: Smalltalk allClasses named: 'All'.! ! !TestConsoleRunner class methodsFor: 'running'! runCategories: aCollectionOfStrings ^ aCollectionOfStrings do: [ :each | self runCategory: each ]! ! !TestConsoleRunner class methodsFor: 'running'! runCategory: aString ^ self runClasses: (Smalltalk organization classesInCategory: aString) named: aString! ! !TestConsoleRunner class methodsFor: 'running'! runClasses: aCollectionOfClasses named: aString | suite classes | suite := TestSuite named: aString. classes := (aCollectionOfClasses select: [ :each | (each includesBehavior: TestCase) and: [ each isAbstract not ] ]) asSortedCollection: [ :a :b | a name <= b name ]. classes isEmpty ifTrue: [ ^ self ]. classes do: [ :each | each addToSuiteFromSelectors: suite ]. ^ self runSuite: suite! ! !TestConsoleRunner class methodsFor: 'running'! runPackage: aString ^ self runClasses: (PackageInfo named: aString) classes named: aString! ! !TestConsoleRunner class methodsFor: 'running'! runPackages: aCollectionOfStrings ^ aCollectionOfStrings do: [ :each | self runPackage: each ]! ! !TestConsoleRunner class methodsFor: 'running'! runSuite: aTestSuite ^ self new initializeOn: aTestSuite; run! ! !TestConsoleRunner class methodsFor: 'defaults' stamp: 'sm 5/25/2011 14:20'! defaultOutputTarget ^ DefaultOutputTarget ifNil: [Transcript] ifNotNil: [DefaultOutputTarget]! ! !TestConsoleRunner class methodsFor: 'defaults' stamp: 'sm 5/25/2011 14:21'! defaultOutputTarget: someStreamishThing "The output target should understand some parts of the standard stream protocol. For details, see the actual usage. A Transcript is good, and most streams, too." DefaultOutputTarget := someStreamishThing! ! !TestCoverage methodsFor: 'actions' stamp: 'lr 3/30/2009 15:20'! install reference actualClass methodDictionary at: reference methodSymbol put: self! ! !TestCoverage methodsFor: 'actions' stamp: 'lr 3/30/2009 15:31'! uninstall reference actualClass methodDictionary at: reference methodSymbol put: method! ! !TestCoverage methodsFor: 'evaluation' stamp: 'lr 3/30/2009 15:32'! run: aSelector with: anArray in: aReceiver self mark; uninstall. ^ aReceiver withArgs: anArray executeMethod: method! ! !TestCoverage methodsFor: 'initialization' stamp: 'lr 3/30/2009 15:19'! initializeOn: aMethodReference hasRun := false. reference := aMethodReference. method := reference compiledMethod! ! !TestCoverage methodsFor: 'testing' stamp: 'lr 3/30/2009 15:09'! hasRun ^ hasRun! ! !TestCoverage methodsFor: 'private' stamp: 'lr 3/30/2009 20:26'! doesNotUnderstand: aMessage ^ method perform: aMessage selector withArguments: aMessage arguments! ! !TestCoverage methodsFor: 'private' stamp: 'lr 4/3/2011 10:59'! flushCache self reference methodSymbol flushCache! ! !TestCoverage methodsFor: 'private' stamp: 'lr 3/30/2009 15:21'! mark hasRun := true! ! !TestCoverage methodsFor: 'private' stamp: 'lr 3/30/2009 15:27'! reference ^ reference! ! !TestCoverage commentStamp: 'LaurentLaffont 4/15/2011 20:19' prior: 0! I wrap a method in order to detect whether it has been called or not. Then I can be used to calculate test coverage for SUnit.! !TestCoverage class methodsFor: 'instance creation' stamp: 'lr 3/30/2009 15:23'! on: aMethodReference ^ self new initializeOn: aMethodReference! ! !TestFailure methodsFor: 'Camp Smalltalk' stamp: ' 17/7/10 17:28'! sunitAnnounce: aTestCase toResult: aTestResult aTestResult addFailure: aTestCase. self sunitExitWith: false! ! !TestFailure methodsFor: 'camp smalltalk' stamp: 'ajh 1/24/2003 19:23'! defaultAction Processor activeProcess debug: self signalerContext title: self description! ! !TestFailure methodsFor: 'camp smalltalk' stamp: 'ajh 2/1/2003 00:58'! isResumable ^ false! ! !TestFailure commentStamp: '<historical>' prior: 0! The test framework distinguishes between failures and errors. A failure is an event whose possibiity is explicitly anticipated and checked for in an assertion, whereas an error is an unanticipated problem like a division by 0 or an index out of bounds. TestFailure is raised when the boolean parameter of an assert: ... or deny: ... call is the opposite of what the assertion claims.! !TestResource methodsFor: 'accessing'! description description isNil ifTrue: [^'']. ^description! ! !TestResource methodsFor: 'accessing'! description: aString description := aString! ! !TestResource methodsFor: 'accessing'! name name isNil ifTrue: [^self printString]. ^name! ! !TestResource methodsFor: 'accessing'! name: aString name := aString! ! !TestResource methodsFor: 'accessing'! resources ^self class resources! ! !TestResource methodsFor: 'initialize-release' stamp: ' 17/7/10 17:28'! initialize "This method used to call setUp but now does nothing; setUp is called by the framework at the appropriate point. Subclasses may override to set the object to its default state." ! ! !TestResource methodsFor: 'printing'! printOn: aStream aStream nextPutAll: self class printString! ! !TestResource methodsFor: 'running'! setUp "Does nothing. Subclasses should override this to initialize their resource"! ! !TestResource methodsFor: 'running'! tearDown "Does nothing. Subclasses should override this to tear down their resource"! ! !TestResource methodsFor: 'testing'! isAvailable "Override to provide information on the readiness of the resource. Put state-changing behaviour in setUp and keep this a state-preserving check as far as possible. Where setUp is guaranteed to provide a valid resource if it completes, there is no need to override this." ^true! ! !TestResource methodsFor: 'testing'! isUnavailable "override to provide information on the readiness of the resource" ^self isAvailable not ! ! !TestResource commentStamp: '<historical>' prior: 0! Normally a test will set up all the objects it needs and tear them down again after it has run. This self-containedness makes a test more robust. Use TestResources only for objects that are needed by several tests and that are too 'expensive' (in time or otherwise) to recreate and destroy for each test. A viable approach is to develop the code in MyTestCase's #setUp and #tearDown methods, then at some point refactor the code into the #setUp and #tearDown of a TestResource whose class is added to MyTestCase class>>resource method. TestResource uses the singleton pattern. A TestResource class will set up a single instance of itself when first requested and tear it down again at the end of TestSuite>>run (or TestCase>>run, >>debug and >>debugAsFailure). Normally, a TestResource, once setUp, remains active during the running of all remaining tests and is #reset after all tests have run. For an exception, see subclass CompetingResource in SUnitResourcePatterns. Users can choose to #reset a resource in the #tearDown of a test that alters it, sacrificing the performance gain of having a single #setUp of the resource for the certainty that other tests using it will not see the alterations. Generally however, this should be the exception: if you need to reset the resource for every test that uses it, its code should just be part of your test's #setUp and #tearDown code. To use, create a subclass of TestResource and override the following: - TestCase class>>resources, to return a collection including the TestResource class, for all test case classes that need it * a TestCase' resources are set up in the order returned and torn down in the reverse order - TestResource class>>resources, if the resource itself always needs some other resource to be present before it can set up * a TestResource's resource are set up before it and torn down after it, and are set up in the order returned and torn down in the reverse order - TestResource>>setUp and tearDown, to define initial and final behaviour (just like a test) - TestResource>>isAvailable, to return true if it is and false if it isn't (the framework calls this after setUp); ideally, this call should not change the resource' state - that should be done in setUp TestResource implements the singleton pattern in its class-side #isAvailable and #reset methods. Do not override these when creating specific resources; unless you are developing a whole new pattern of use, it will always be correct to override instance-side #setUp, #tearDown and #isAvailable, and dangerous to override class>>isAvailable, class>>isAlreadyAvailable and class>>reset. Generally, users do not code interactions with a test's resources during the running of a test. Code that reads a resource' values while leaving its state strictly alone is safe enough. A test must leave a resource in a clean state: always use #reset if a test must protect later-running tests from unsafe changes (and review whether in such a case a resource is the right thing to use in the first place). See my superclass' comment for assertion and logging information. ! !TestResource class methodsFor: 'accessing' stamp: ' 17/7/10 17:28'! current "This is a lazy accessor: the assert of self isAvailable does no work unless current isNil. However this method should normally be sent only to a resource that should already have been made available, e.g. in a test whose test case class has the resource class in its #resources, so should never be able to fail the assert. If the intent is indeed to access a possibly-unprepared or reset-in-earlier-test resource lazily, then preface the call of 'MyResource current' with 'MyResource availableFor: self'." self assert: self isAvailable description: 'Sent #current to unavailable resource ' , self name , '. Add it to test case'' class-side #resources (recommended) or send #availableFor: beforehand'. ^current! ! !TestResource class methodsFor: 'accessing'! current: aTestResource current := aTestResource ! ! !TestResource class methodsFor: 'accessing'! resources ^#()! ! !TestResource class methodsFor: 'instance creation' stamp: 'nfr 1/3/2010 18:01'! new "Use #current to get the valid current instance. Use of #new to get an instance (that should never be the current one) could be done in bizarre circumstances, so is not blocked, but will usually be inappropriate." ^super new initialize.! ! !TestResource class methodsFor: 'instance creation'! reset [self isAlreadyAvailable ifTrue: [current tearDown]] ensure: [current := nil]! ! !TestResource class methodsFor: 'running' stamp: ' 17/7/10 17:28'! availableFor: aTestAsserter aTestAsserter assert: self isAvailable description: 'Unavailable resource ' , self name , ' requested by ' , aTestAsserter printString! ! !TestResource class methodsFor: 'running' stamp: 'nfr 1/3/2010 18:01'! resetResources: topLevelResources "Reset all imperfectly-set-up resources while gathering the rest for ordered resetting." | availableResources | availableResources := OrderedCollection new: topLevelResources size. topLevelResources do: [:each | each resetOrAddResourcesTo: availableResources]. availableResources reverseDo: [:each | each reset]! ! !TestResource class methodsFor: 'testing' stamp: 'md 2/22/2006 14:21'! isAbstract "Override to true if a TestResource subclass is Abstract and should not have TestCase instances built from it" ^self name = #TestResource ! ! !TestResource class methodsFor: 'testing'! isAlreadyAvailable ^current class == self! ! !TestResource class methodsFor: 'testing'! isAvailable "This is (and must be) a lazy method. If my current has a value, an attempt to make me available has already been made: trust its result. If not, try to make me available." current isNil ifTrue: [self makeAvailable]. ^self isAlreadyAvailable! ! !TestResource class methodsFor: 'testing'! isUnavailable ^self isAvailable not ! ! !TestResource class methodsFor: 'private'! makeAvailable "This method must be the _only_ way to set a notNil value for the unique instance (current). First, obtain a candidate instance and set current to a notNil placeholder (any notNil object not an instance of me would do; this version uses false). Next, check any subordinate resources needed by this resource. Lastly, setUp the candidate and put it in current if it is available, ensuring that it is torn down otherwise." | candidate | current := nil. candidate := self new. self resources do: [:each | each availableFor: candidate]. [candidate setUp. candidate isAvailable ifTrue: [current := candidate]] ensure: [current == candidate ifFalse: [candidate tearDown]]! ! !TestResource class methodsFor: 'private' stamp: 'nfr 1/3/2010 18:00'! resetOrAddResourcesTo: aCollection "Add correctly set-up resources to the collection unless already there. Reset any imperfectly-set-up resources, so current isNil will return true if they are re-encountered via an indirectly self-prerequing resource; circular references cannot be set up so will never reply true to isAlreadyAvailable, but may have correctly-set-up prereqs to add and/or imperfectly-set-up ones to reset, so do not abort the loop first time round." current isNil ifTrue: [^self]. self isAlreadyAvailable ifFalse: [self reset. self resources do: [:each | each resetOrAddResourcesTo: aCollection]] ifTrue: [(aCollection includes: self) ifFalse: [self resources do: [:each | each resetOrAddResourcesTo: aCollection]. aCollection add: self]] "The cloned 'self resources do: ...' line in both blocks is, I think, the best way to write this method so that its logic is clear. The first loop resets this resource immediately, before traversing its resources; the second traverses before adding"! ! !TestResult methodsFor: 'accessing'! classesTested ^ (self tests collect: [ :testCase | testCase class ]) asSet! ! !TestResult methodsFor: 'accessing'! defects ^OrderedCollection new addAll: self errors; addAll: self failures; yourself! ! !TestResult methodsFor: 'accessing'! errorCount ^self errors size! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 13:54'! expectedDefectCount ^ self expectedDefects size! ! !TestResult methodsFor: 'accessing' stamp: 'md 11/25/2004 16:36'! expectedDefects ^ (errors, failures asOrderedCollection) select: [:each | each shouldPass not] ! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 13:54'! expectedPassCount ^ self expectedPasses size! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 16:14'! expectedPasses ^ passed select: [:each | each shouldPass] ! ! !TestResult methodsFor: 'accessing'! failureCount ^self failures size! ! !TestResult methodsFor: 'accessing'! passedCount ^self passed size! ! !TestResult methodsFor: 'accessing'! runCount ^self passedCount + self failureCount + self errorCount! ! !TestResult methodsFor: 'accessing'! tests ^(OrderedCollection new: self runCount) addAll: passed; addAll: failures; addAll: errors; yourself! ! !TestResult methodsFor: 'accessing'! timeStamp ^ timeStamp! ! !TestResult methodsFor: 'accessing'! timeStamp: anObject timeStamp := anObject! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 13:54'! unexpectedErrorCount ^ self unexpectedErrors size! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 16:14'! unexpectedErrors ^ errors select: [:each | each shouldPass] ! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 13:54'! unexpectedFailureCount ^ self unexpectedFailures size! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 16:14'! unexpectedFailures ^ failures select: [:each | each shouldPass] ! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 13:54'! unexpectedPassCount ^ self unexpectedPasses size! ! !TestResult methodsFor: 'accessing' stamp: 'JF 7/30/2003 16:14'! unexpectedPasses ^ passed select: [:each | each shouldPass not] ! ! !TestResult methodsFor: 'adding'! addError: aTestCase "We cannot use self errors as that incorporates test expectations and so does not return the stored collection." ^errors add: aTestCase! ! !TestResult methodsFor: 'adding'! addFailure: aTestCase "We cannot use self failures as that incorporates test expectations and so does not return the stored collection." ^failures add: aTestCase! ! !TestResult methodsFor: 'adding'! addPass: aTestCase "We cannot use self passed as that incorporates test expectations and so does not return the stored collection." ^passed add: aTestCase! ! !TestResult methodsFor: 'compatibility' stamp: 'JF 7/30/2003 16:09'! errors ^ self unexpectedErrors! ! !TestResult methodsFor: 'compatibility' stamp: 'md 11/25/2004 16:23'! failures ^ self unexpectedFailures, self unexpectedPasses ! ! !TestResult methodsFor: 'compatibility' stamp: 'JF 7/30/2003 16:08'! passed ^ self expectedPasses, self expectedDefects! ! !TestResult methodsFor: 'deprecated' stamp: 'nfr 1/3/2010 17:58'! correctCount "deprecated - use #passedCount" ^self passedCount! ! !TestResult methodsFor: 'diff'! diff: aTestResult "Return a collection that contains differences" | passed1Selectors failed1Selectors errors1Selectors passed2Selectors failed2Selectors errors2Selectors | passed1Selectors := self passed collect: [:testCase | testCase selector]. failed1Selectors := self failures collect: [:testCase | testCase selector]. errors1Selectors := self errors collect: [:testCase | testCase selector]. passed2Selectors := aTestResult passed collect: [:testCase | testCase selector]. failed2Selectors := aTestResult failures collect: [:testCase | testCase selector]. errors2Selectors := aTestResult errors collect: [:testCase | testCase selector]. ^ {passed1Selectors copyWithoutAll: passed2Selectors . failed1Selectors copyWithoutAll: failed2Selectors . errors1Selectors copyWithoutAll: errors2Selectors}! ! !TestResult methodsFor: 'filein/out'! fileOutOn: aFileStream "Write in aFileStream like: 3 run, 2 passes, 0 expected failures, 1 failures, 0 errors, 0 unexpected passes Failures: SHParserST80Test>>#testNumbers Errors:" | printer | printer := [:title :testCases | aFileStream cr; nextPutAll: title; cr. testCases do: [:aTestCase| aTestCase printOn: aFileStream. aFileStream cr]]. self printOn: aFileStream. printer value: 'Failures:' value: self failures. printer value: 'Errors:' value: self errors.! ! !TestResult methodsFor: 'history'! dispatchResultsIntoHistory self classesTested do: [ :testClass | self class historyAt: testClass put: (self selectResultsForTestCase: testClass) ]. ! ! !TestResult methodsFor: 'history'! selectResultsForTestCase: aTestCaseClass | passedSelectors errorsSelectors failuresSelectors | passedSelectors := self passed select: [:testCase | testCase class == aTestCaseClass ] thenCollect: [:testCase | testCase selector]. errorsSelectors := self errors select: [:testCase | testCase class == aTestCaseClass ] thenCollect: [:testCase | testCase selector]. failuresSelectors := self failures select: [:testCase | testCase class == aTestCaseClass ] thenCollect: [:testCase | testCase selector]. ^ self class newTestDictionary at: #passed put: passedSelectors asSet; at: #failures put: failuresSelectors asSet; at: #errors put: errorsSelectors asSet; yourself ! ! !TestResult methodsFor: 'history'! updateResultsInHistory #(#passed #failures #errors) do: [ :status | (self perform: status) do: [ :testCase | self class updateTestHistoryFor: testCase status: status ] ]! ! !TestResult methodsFor: 'initialization'! initialize super initialize. passed := OrderedCollection new. failures := Set new. errors := OrderedCollection new. timeStamp := DateAndTime now! ! !TestResult methodsFor: 'printing'! printOn: aStream aStream nextPutAll: self runCount printString; nextPutAll: ' run, '; nextPutAll: self expectedPassCount printString; nextPutAll: ' passes, '; nextPutAll: self expectedDefectCount printString; nextPutAll:' expected failures, '; nextPutAll: self unexpectedFailureCount printString; nextPutAll: ' failures, '; nextPutAll: self unexpectedErrorCount printString; nextPutAll:' errors, '; nextPutAll: self unexpectedPassCount printString; nextPutAll:' unexpected passes'.! ! !TestResult methodsFor: 'querying'! isErrorFor: class selector: selector ^ self errors anySatisfy: [:testCase | testCase class == class and: [testCase selector == selector]]! ! !TestResult methodsFor: 'querying'! isFailureFor: class selector: selector ^ self failures anySatisfy: [:testCase | testCase class == class and: [testCase selector == selector]]! ! !TestResult methodsFor: 'querying'! isPassedFor: class selector: selector ^ self passed anySatisfy: [:testCase | testCase class == class and: [testCase selector == selector]]! ! !TestResult methodsFor: 'running'! runCase: aTestCase [ aTestCase announce: TestCaseStarted withResult: self. aTestCase runCase. aTestCase announce: TestCaseEnded withResult: self. self addPass: aTestCase] on: self class failure , self class error do: [:ex | ex sunitAnnounce: aTestCase toResult: self]! ! !TestResult methodsFor: 'testing'! hasErrors ^self errors size > 0! ! !TestResult methodsFor: 'testing'! hasFailures ^self failures size > 0! ! !TestResult methodsFor: 'testing'! hasPassed ^self hasErrors not and: [self hasFailures not]! ! !TestResult methodsFor: 'testing'! isError: aTestCase ^self errors includes: aTestCase! ! !TestResult methodsFor: 'testing'! isFailure: aTestCase ^self failures includes: aTestCase! ! !TestResult methodsFor: 'testing'! isPassed: aTestCase ^self passed includes: aTestCase! ! !TestResult commentStamp: '<historical>' prior: 0! This implements the Collecting Parameter pattern for running a bunch of tests. It holds tests that have run, sorted into the result categories of passed, failures and errors. TestResult is an interesting object to subclass or substitute. #runCase: is the external protocol you need to reproduce. TestResult subclasses can handle multi-threaded tests (see SUnitXProcPatterns) and might record coverage information or send emails when the run completes. ! !TestResult class methodsFor: 'exceptions'! error ^self exError! ! !TestResult class methodsFor: 'exceptions' stamp: 'md 2/22/2006 14:17'! exError ^Error ! ! !TestResult class methodsFor: 'exceptions'! failure ^TestFailure! ! !TestResult class methodsFor: 'exceptions'! resumableFailure ^ResumableTestFailure! ! !TestResult class methodsFor: 'exceptions' stamp: 'md 2/22/2006 14:26'! signalErrorWith: aString self error signal: aString ! ! !TestResult class methodsFor: 'exceptions' stamp: 'md 2/22/2006 14:26'! signalFailureWith: aString self failure signal: aString ! ! !TestResult class methodsFor: 'history'! historyAt: aTestCaseClass "I will return the last test dictionary for aTestCaseClass. If none found, I will create a new empty one and link it in the history." ^ aTestCaseClass history ! ! !TestResult class methodsFor: 'history'! historyAt: aTestCaseClass put: aDictionary aTestCaseClass history: aDictionary "^ self history at: aTestCaseClass put: aDictionary "! ! !TestResult class methodsFor: 'history'! historyFor: aTestCaseClass "I return the last test dictionary for aTestCaseClass. If none found, I return an empty dictionary but will not link it to the class in the history." | history | history := aTestCaseClass history. history ifNil: [ ^ self newTestDictionary ]. ^ history " ^ self history at: aTestCaseClass ifAbsent: [ self newTestDictionary ]"! ! !TestResult class methodsFor: 'history'! newTestDictionary ^ Dictionary new at: #timeStamp put: DateAndTime now; at: #passed put: Set new; at: #failures put: Set new; at: #errors put: Set new; yourself ! ! !TestResult class methodsFor: 'history'! removeFromTestHistory: aSelector in: aTestCaseClass | lastRun | lastRun := self historyFor: aTestCaseClass. #(#passed #failures #errors) do: [ :set | (lastRun at: set) remove: aSelector ifAbsent: []]. ! ! !TestResult class methodsFor: 'history'! updateTestHistoryFor: aTestCase status: aSymbol | cls sel | cls := aTestCase class. sel := aTestCase selector. self removeFromTestHistory: sel in: cls. ((self historyAt: cls) at: aSymbol ) add: sel! ! !TestRunner methodsFor: 'accessing' stamp: 'lr 10/31/2005 15:31'! baseClass ^ TestCase! ! !TestRunner methodsFor: 'accessing' stamp: 'lr 11/3/2005 09:37'! suiteAll ^ TestSuite new in: [ :suite | classesSelected do: [ :each | each isAbstract ifFalse: [ each addToSuiteFromSelectors: suite ] ]. suite name: (self label: 'Test' forSuite: suite) ].! ! !TestRunner methodsFor: 'accessing' stamp: 'lr 10/27/2005 10:29'! suiteErrors ^ TestSuite new in: [ :suite | suite addTests: errorList; name: (self label: 'Error' forSuite: suite) ].! ! !TestRunner methodsFor: 'accessing' stamp: 'lr 10/27/2005 10:42'! suiteFailures ^ TestSuite new in: [ :suite | suite addTests: failedList; name: (self label: 'Failure' forSuite: suite) ].! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 10/31/2005 15:09'! categoryAt: anIndex ^ categoriesSelected includes: (categories at: anIndex ifAbsent: [ ^ false ]).! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 10/31/2005 15:51'! categoryAt: anInteger put: aBoolean categoriesSelected := categoriesSelected perform: (aBoolean ifTrue: [ #copyWith: ] ifFalse: [ #copyWithout: ]) with: (categories at: anInteger ifAbsent: [ ^ self ]). self changed: #categorySelected; updateClasses.! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 10/31/2005 15:10'! categoryList ^ categories! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 11/1/2005 19:25'! categoryMenu: aMenu ^ aMenu title: 'Categories'; add: 'Select all' action: #selectAllCategories; add: 'Select inversion' action: #selectInverseCategories; add: 'Select none' action: #selectNoCategories; addLine; add: 'Filter...' action: #filterCategories; addLine; add: 'Refresh' action: #updateCategories; yourself.! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 10/31/2005 15:11'! categorySelected ^ 0! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 10/31/2005 15:12'! categorySelected: anInteger self changed: #categorySelected.! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 7/4/2009 15:08'! filterCategories | pattern | pattern := UIManager default request: 'Pattern to select categories:' initialAnswer: '*'. pattern isNil ifTrue: [ ^ self ]. categoriesSelected := (categories select: [ :each | pattern match: each ]) asSet. self changed: #allSelections; changed: #categorySelected; updateClasses! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 7/4/2009 15:08'! selectAllCategories categoriesSelected := categories asSet. self changed: #allSelections; changed: #categorySelected; updateClasses! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 7/4/2009 15:08'! selectInverseCategories categoriesSelected := categories asSet removeAll: categoriesSelected; yourself. self changed: #allSelections; changed: #categorySelected; updateClasses! ! !TestRunner methodsFor: 'accessing-categories' stamp: 'lr 7/4/2009 15:08'! selectNoCategories categoriesSelected := Set new. self changed: #allSelections; changed: #categorySelected; updateClasses! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 1/20/2009 14:49'! browseClass (classes at: classIndex ifAbsent: [ ^ self ]) browse! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 10/8/2005 19:58'! classAt: anInteger ^ classesSelected includes: (classes at: anInteger ifAbsent: [ ^ false ]).! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 11/21/2005 13:19'! classAt: anInteger put: aBoolean classesSelected := classesSelected perform: (aBoolean ifTrue: [ #copyWith: ] ifFalse: [ #copyWithout: ]) with: (classes at: anInteger ifAbsent: [ ^ self ]). self changed: #classSelected; changed: #hasRunnable.! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'nice 1/5/2010 15:59'! classList | offset | classes isEmpty ifTrue: [ ^ classes ]. offset := classes first allSuperclasses size. ^ classes collect: [ :each | | ident | ident := String new: 2 * (0 max: each allSuperclasses size - offset) withAll: $ . each isAbstract ifFalse: [ ident , each name ] ifTrue: [ ident asText , each name asText addAttribute: TextEmphasis italic; yourself ] ].! ! !TestRunner methodsFor: 'accessing-classes'! classMenu: aMenu ^ aMenu title: 'Classes'; add: 'Browse' action: #browseClass; addLine; add: 'Select all' action: #selectAllClasses; add: 'Select unit tests' action: #selectAllUnitTests; add: 'Select subclasses' action: #selectSubclasses; add: 'Select inversion' action: #selectInverseClasses; add: 'Select none' action: #selectNoClasses; addLine; add: 'Filter...' action: #filterClasses; addLine; add: 'Refresh' action: #updateClasses; yourself.! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 1/20/2009 14:46'! classSelected ^ classIndex! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 1/20/2009 14:48'! classSelected: anInteger classIndex := anInteger. self changed: #classSelected! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'lr 7/4/2009 15:10'! filterClasses | pattern | pattern := UIManager default request: 'Pattern to select tests:' initialAnswer: '*'. pattern isNil ifTrue: [ ^ self ]. classesSelected := (classes select: [ :each | pattern match: each name ]) asSet. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'gvc 7/24/2007 12:01'! selectAllClasses "Fixed to update all selections now that the selection invalidation has been optimised." classesSelected := classes asSet. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-classes'! selectAllUnitTests classesSelected := classes asSet select: [ :eachClass | eachClass isUnitTest ]. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'gvc 7/24/2007 12:01'! selectInverseClasses "Fixed to update all selections now that the selection invalidation has been optimised." classesSelected := classes asSet removeAll: classesSelected; yourself. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'gvc 7/24/2007 11:59'! selectNoClasses "Fixed to update all selections now that the selection invalidation has been optimised." classesSelected := Set new. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-classes' stamp: 'gvc 7/24/2007 12:01'! selectSubclasses "Fixed to update all selections now that the selection invalidation has been optimised." | classesForPackages | classesForPackages := self findClassesForCategories: categoriesSelected. classesSelected := (classesSelected gather: [ :class | class withAllSubclasses select: [ :each | classesForPackages includes: each ] ]) asSet. self changed: #allSelections; changed: #classSelected; changed: #hasRunnable! ! !TestRunner methodsFor: 'accessing-menu'! errorMenu: aMenu "Add the browse item only if an item is selected" self statusMenu: aMenu. errorSelected ifNotNil: [aMenu add: 'Browse test' action: #browseSelectedErrorTest]. ^aMenu! ! !TestRunner methodsFor: 'accessing-menu'! failureMenu: aMenu "Add the browse item only if an item is selected" failedSelected ifNotNil: [aMenu add: 'Browse test' action: #browseSelectedFailedTest]. ^ aMenu! ! !TestRunner methodsFor: 'accessing-menu'! statusMenu: aMenu ^ aMenu add: 'History' action: #showHistoryMenu; add: 'Store result as progress reference' action: #storeResultIntoTestCases; add: 'Show progress' action: #showProgress; yourself! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/8/2005 22:37'! errorList ^ errorList collect: [ :each | each printString ].! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/6/2005 19:46'! errorSelected ^ errorList indexOf: errorSelected.! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/27/2005 10:37'! errorSelected: anInteger errorSelected := errorList at: anInteger ifAbsent: nil. self changed: #errorSelected. errorSelected ifNotNil: [ self debug: errorSelected ].! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/8/2005 22:37'! failedList ^ failedList collect: [ :each | each printString ].! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/6/2005 19:47'! failedSelected ^ failedList indexOf: failedSelected.! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/6/2005 20:14'! failedSelected: anInteger failedSelected := failedList at: anInteger ifAbsent: nil. self changed: #failedSelected. failedSelected ifNotNil: [ self debug: failedSelected ].! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/6/2005 15:47'! result ^ result! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/8/2005 22:47'! result: aResult result := aResult! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 3/16/2010 19:37'! statusColor result hasErrors ifTrue: [ ^ Color red ]. result hasFailures ifTrue: [ ^ Color yellow ]. ^ Color green! ! !TestRunner methodsFor: 'accessing-testing' stamp: 'lr 10/8/2005 22:45'! statusText ^ result printString.! ! !TestRunner methodsFor: 'accessing-ui' stamp: 'tbn 7/29/2010 21:17'! buttons ^ #(( 'Run Selected' #runAll 'Run all selected tests' #hasRunnable ) ( 'Run Profiled' #runProfiled 'Run tests and profile' #hasRunnable ) ( 'Run Coverage' #runCoverage 'Run test and check code coverage' #hasRunnable ) ( 'Run Failures' #runFailures 'Run all failures' #hasFailures ) ( 'Run Errors' #runErrors 'Run all errors' #hasErrors ) ( 'File out results' #fileOutResults 'File out test results' #hasFailuresOrErrors))! ! !TestRunner methodsFor: 'accessing-ui' stamp: 'lr 10/8/2005 18:39'! extent ^ 640 @ 480! ! !TestRunner methodsFor: 'accessing-ui' stamp: 'lr 1/20/2006 13:36'! label ^ 'Test Runner' ! ! !TestRunner methodsFor: 'actions' stamp: 'nice 10/20/2009 21:08'! addDeclaredPackagesUnderTestTo: packages classesSelected do: [ :class | (class class includesSelector: #packageNamesUnderTest) ifTrue: [ class packageNamesUnderTest do: [ :name | packages add: (PackageInfo named: name) ] ] ]! ! !TestRunner methodsFor: 'actions'! addMethodsUnderTestIn: packages to: methods packages do: [:package | package isNil ifFalse: [package methods do: [:method | ((#(#packageNamesUnderTest #classNamesNotUnderTest ) includes: method methodSymbol) or: [method compiledMethod isAbstract or: [method compiledMethod refersToLiteral: #ignoreForCoverage]]) ifFalse: [methods add: method]]]]! ! !TestRunner methodsFor: 'actions'! collectCoverageFor: methods | wrappers suite | wrappers := methods collect: [ :each | TestCoverage on: each ]. suite := self reset; suiteAll. [ wrappers do: [ :each | each install ]. [ self runSuite: suite ] ensure: [ wrappers do: [ :each | each uninstall ] ] ] valueUnpreemptively. wrappers := wrappers reject: [ :each | each hasRun ]. wrappers isEmpty ifTrue: [ UIManager default inform: 'Congratulations. Your tests cover all code under analysis.' ] ifFalse: [ MessageSet openMessageList: (wrappers collect: [ :each | each reference ]) name: 'Not Covered Code (' , (100 - (100 * wrappers size // methods size)) printString , '% Code Coverage)' ]. self saveResultInHistory! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/31/2005 17:42'! debug: aTestCase self debugSuite: (TestSuite new addTest: aTestCase; yourself).! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/31/2005 17:01'! debugSuite: aTestSuite self basicRunSuite: aTestSuite do: [ :each | each debug ].! ! !TestRunner methodsFor: 'actions' stamp: 'lr 3/14/2010 21:13'! excludeClassesNotUnderTestFrom: methods classesSelected do: [ :class | (class class includesSelector: #classNamesNotUnderTest) ifTrue: [ class classNamesNotUnderTest do: [ :className | | theClass | theClass := Smalltalk globals classNamed: className. theClass ifNotNil: [ theClass methods do: [ :each | methods remove: each methodReference ifAbsent: [ ] ]. theClass class methods do: [ :each | methods remove: each methodReference ifAbsent: [ ] ] ] ] ] ]! ! !TestRunner methodsFor: 'actions'! fileOutResults | fileName defaultFilename stream printer | "Save current test results into text file." "Generate a filename like 'tests_Pharo-1.1-11367-Beta_23_May_2010_9:19:20_am.txt' " defaultFilename := 'tests_', SystemVersion current version, '_', (result timeStamp asString copyReplaceAll: ' ' with: '_'), '.txt'. fileName := UIManager default request: 'Enter the file name' initialAnswer: defaultFilename. stream := CrLfFileStream newFileNamed: fileName. [result fileOutOn: stream] ensure: [stream close].! ! !TestRunner methodsFor: 'actions'! promptForPackages | packages | packages := (PackageOrganizer default packages reject: [:package | (package packageName beginsWith: 'Kernel') or: [(package packageName beginsWith: 'Collections') or: [(package packageName beginsWith: 'Exceptions') or: [(package packageName beginsWith: 'SUnit') or: [(package packageName beginsWith: 'System') or: [package packageName includesSubstring: 'Test' caseSensitive: false]]]]]]) sort: [:a :b | a packageName < b packageName]. packages := Array with: (UIManager default chooseFrom: (packages collect: [:package | package packageName]) values: packages title: 'Select Package'). ^ packages! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/8/2005 22:52'! reset self result: TestResult new; updateResults.! ! !TestRunner methodsFor: 'actions'! runAll self reset; runSuite: self suiteAll. self saveResultInHistory! ! !TestRunner methodsFor: 'actions'! runCoverage | packages methods | packages := Set new. self addDeclaredPackagesUnderTestTo: packages. packages isEmpty ifTrue: [ packages := self promptForPackages ]. methods := OrderedCollection new. self addMethodsUnderTestIn: packages to: methods. self excludeClassesNotUnderTestFrom: methods. methods isEmpty ifTrue: [ ^ UIManager default inform: 'No methods found for coverage analysis.' ]. self collectCoverageFor: methods ! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/8/2005 23:02'! runErrors self result instVarNamed: 'errors' put: OrderedCollection new. self runSuite: self suiteErrors.! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/27/2005 10:42'! runFailures self result instVarNamed: 'failures' put: Set new. self runSuite: self suiteFailures.! ! !TestRunner methodsFor: 'actions' stamp: 'lr 10/31/2005 17:13'! runProfiled MessageTally spyOn: [ self runAll ].! ! !TestRunner methodsFor: 'actions' stamp: 'lr 3/30/2009 14:50'! runSuite: aTestSuite self basicRunSuite: aTestSuite do: [ :each | self runTest: each ]. self updateResults ! ! !TestRunner methodsFor: 'actions' stamp: 'lr 11/3/2005 09:15'! runTest: aTestCase aTestCase run: result. self updateStatus: true.! ! !TestRunner methodsFor: 'browsing'! browseSelectedErrorTest errorSelected ifNil: [^self]. self browseSelectedTest: errorSelected! ! !TestRunner methodsFor: 'browsing'! browseSelectedFailedTest failedSelected ifNil: [^self]. self browseSelectedTest: failedSelected! ! !TestRunner methodsFor: 'browsing'! browseSelectedTest: aTest Browser fullOnClass: aTest class selector: aTest selector! ! !TestRunner methodsFor: 'building' stamp: 'tbn 7/29/2010 21:16'! buildButtonsWith: aBuilder ^ aBuilder pluggablePanelSpec new model: self; layout: #horizontal; children: (self buttons collect: [ :each | aBuilder pluggableButtonSpec new model: self; label: each first; action: each second; help: each third; enabled: (each at: 4); yourself ]); yourself.! ! !TestRunner methodsFor: 'building' stamp: 'lr 10/31/2005 15:12'! buildCategoriesWith: aBuilder ^ aBuilder pluggableMultiSelectionListSpec new model: self; list: #categoryList; menu: #categoryMenu:; getIndex: #categorySelected; setIndex: #categorySelected:; getSelectionList: #categoryAt:; setSelectionList: #categoryAt:put:; yourself.! ! !TestRunner methodsFor: 'building' stamp: 'lr 10/17/2005 09:13'! buildClassesWith: aBuilder ^ aBuilder pluggableMultiSelectionListSpec new model: self; list: #classList; menu: #classMenu:; getIndex: #classSelected; setIndex: #classSelected:; getSelectionList: #classAt:; setSelectionList: #classAt:put:; yourself.! ! !TestRunner methodsFor: 'building' stamp: 'lr 10/21/2008 18:04'! buildErrorListWith: aBuilder ^ aBuilder pluggableListSpec new model: self; name: 'Error List'; list: #errorList; menu: #errorMenu:; getIndex: #errorSelected; setIndex: #errorSelected:; yourself.! ! !TestRunner methodsFor: 'building' stamp: 'lr 10/21/2008 18:04'! buildFailureListWith: aBuilder ^ aBuilder pluggableListSpec new model: self; name: 'Failure List'; list: #failedList; menu: #failureMenu:; getIndex: #failedSelected; setIndex: #failedSelected:; yourself.! ! !TestRunner methodsFor: 'building' stamp: 'lr 10/21/2008 18:05'! buildStatusWith: aBuilder ^ aBuilder pluggableInputFieldSpec new model: self; menu: #statusMenu:; color: #statusColor; getText: #statusText; yourself.! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:45'! buildWith: aBuilder | window | window := aBuilder pluggableWindowSpec new model: self; label: self label; extent: self extent; children: (OrderedCollection new add: ((self buildCategoriesWith: aBuilder) frame: self categoriesFrame; yourself); add: ((self buildClassesWith: aBuilder) frame: self classesFrame; yourself); add: ((self buildStatusWith: aBuilder) frame: self statusFrame; yourself); add: ((self buildFailureListWith: aBuilder) frame: self failureListFrame; yourself); add: ((self buildErrorListWith: aBuilder) frame: self errorListFrame; yourself); add: ((self buildButtonsWith: aBuilder) frame: self buttonsFrame; yourself); yourself); yourself. ^ aBuilder build: window.! ! !TestRunner methodsFor: 'building'! buttonHeight ^ self theme buttonMinHeight + 25! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:45'! buttonsFrame ^LayoutFrame new leftFraction: 0 offset: 0; topFraction: 1 offset: self buttonHeight negated; rightFraction: 1 offset: 0; bottomFraction: 1 offset: 0! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:48'! categoriesFrame ^LayoutFrame new leftFraction: 0 offset: 0; topFraction: 0 offset: 0; rightFraction: 0.25 offset: 0; bottomFraction: 1 offset: self buttonHeight negated + 4! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:48'! classesFrame ^LayoutFrame new leftFraction: 0.25 offset: 0; topFraction: 0 offset: 0; rightFraction: 0.5 offset: 0; bottomFraction: 1 offset: self buttonHeight negated + 4! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:49'! errorListFrame ^LayoutFrame new leftFraction: 0.5 offset: 0; topFraction: 0.5 offset: 0; rightFraction: 1 offset: 0; bottomFraction: 1 offset: self buttonHeight negated + 4! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:43'! failureListFrame ^LayoutFrame new leftFraction: 0.5 offset: 0; topFraction: 0 offset: self statusHeight; rightFraction: 1 offset: 0; bottomFraction: 0.5 offset: 0! ! !TestRunner methodsFor: 'building' stamp: 'bp 11/22/2010 20:41'! statusFrame ^LayoutFrame new leftFraction: 0.5 offset: 0; topFraction: 0 offset: 0; rightFraction: 1 offset: 0; bottomFraction: 0 offset: self statusHeight! ! !TestRunner methodsFor: 'building'! statusHeight ^ self theme textFont height * 2 + 5! ! !TestRunner methodsFor: 'history saving'! hasProgress result classesTested do: [:cls | (cls class methodDictionary includesKey: #lastStoredRun) ifTrue: [^ true]]. ^ false! ! !TestRunner methodsFor: 'history saving'! hasResults ^ result notNil! ! !TestRunner methodsFor: 'history saving'! historyMenuList ^ {'** save current result **'}, (self previousRun collect: [:ts | ts printString])! ! !TestRunner methodsFor: 'history saving'! previousRun ^ previousRun ifNil: [ previousRun := OrderedCollection new ]! ! !TestRunner methodsFor: 'history saving'! saveResultInHistory result dispatchResultsIntoHistory! ! !TestRunner methodsFor: 'history saving'! showDiffWith: aTestResult | string diff | diff := result diff: aTestResult. string := String streamContents: [:str| str nextPutAll: '----------------'; cr. str nextPutAll: 'Diff between current result with: ', aTestResult asString; cr. str nextPutAll: 'New passed: '. diff first do: [:s| str nextPutAll: s printString, ' ']. str cr. str nextPutAll: 'New failures: '. diff second do: [:s| str nextPutAll: s printString, ' ']. str cr. str nextPutAll: 'New errors: '. diff third do: [:s| str nextPutAll: s printString, ' ']. str cr]. Workspace new contents: string; openLabel: 'SUnit Progress' ! ! !TestRunner methodsFor: 'history saving'! showHistoryMenu | selectionIndex selectedPreviousResult actionIndex | selectionIndex := UIManager default chooseFrom: self historyMenuList title: 'History:'. "We pressed outside the menu" selectionIndex isZero ifTrue: [ ^ self ]. "save current result is selected" selectionIndex = 1 ifTrue: [ self previousRun addFirst: result. ^ self ]. selectedPreviousResult := self previousRun at: (selectionIndex - 1). actionIndex := (UIManager default chooseFrom: #('delete' 'show diff') title: 'Action:'). actionIndex = 1 ifTrue: [ self previousRun remove: selectedPreviousResult. ^ self ]. actionIndex = 2 ifTrue: [ self showDiffWith: selectedPreviousResult]. ! ! !TestRunner methodsFor: 'history saving' stamp: 'nice 1/5/2010 15:59'! showProgress | testCaseClasses d string | testCaseClasses := (self suiteAll tests collect: [:testCase | testCase class]) asSet. "At the end of the algorithm, d will contains all the diff between what was saved and the current result" d := Dictionary new. d at: #passed put: OrderedCollection new. d at: #failures put: OrderedCollection new. d at: #errors put: OrderedCollection new. testCaseClasses do: [ :cls | | t | (cls class methodDict includesKey: #lastStoredRun) ifTrue: [t := cls lastStoredRun. (t at: #passed) do: [:s | (result isErrorFor: cls selector: s) ifTrue: [(d at: #errors) add: {cls . s}]. (result isFailureFor: cls selector: s) ifTrue: [(d at: #failures) add: {cls . s}] ]. (t at: #failures) do: [:s | (result isPassedFor: cls selector: s) ifTrue: [(d at: #passed) add: {cls . s}]. (result isErrorFor: cls selector: s) ifTrue: [(d at: #errors) add: {cls . s}]]. (t at: #errors) do: [:s | (result isPassedFor: cls selector: s) ifTrue: [(d at: #passed) add: {cls . s}]. (result isFailureFor: cls selector: s) ifTrue: [(d at: #failures) add: {cls . s}]]]]. string := String streamContents: [:str| str nextPutAll: '----------------'; cr. str nextPutAll: 'Diff between current result and saved result'; cr. str nextPutAll: 'New passed: '. (d at: #passed) do: [:s| str nextPutAll: s printString, ' ']. str cr. str nextPutAll: 'New failures: '. (d at: #failures) do: [:s| str nextPutAll: s printString, ' ']. str cr. str nextPutAll: 'New errors: '. (d at: #errors) do: [:s| str nextPutAll: s printString, ' ']. str cr]. Workspace new contents: string; openLabel: 'SUnit Progress' string. ! ! !TestRunner methodsFor: 'history saving'! storeResultIntoTestCases result classesTested do: [:testCaseCls | testCaseCls generateLastStoredRunMethod ] ! ! !TestRunner methodsFor: 'initialization' stamp: 'lr 3/22/2006 19:36'! initialize super initialize. failedList := errorList := Array new. SystemChangeNotifier uniqueInstance notify: self ofSystemChangesOfItem: #class change: #Added using: #update; notify: self ofSystemChangesOfItem: #category change: #Added using: #update; notify: self ofSystemChangesOfItem: #class change: #Removed using: #update; notify: self ofSystemChangesOfItem: #category change: #Removed using: #update; notify: self ofSystemChangesOfItem: #class change: #Renamed using: #update; notify: self ofSystemChangesOfItem: #category change: #Renamed using: #update; notify: self ofSystemChangesOfItem: #class change: #Recategorized using: #update; notify: self ofSystemChangesOfItem: #category change: #Recategorized using: #update. self update; reset! ! !TestRunner methodsFor: 'processing' stamp: 'lr 10/31/2005 17:43'! basicRunSuite: aTestSuite do: aBlock self basicSetUpSuite: aTestSuite. [ aTestSuite name isEmptyOrNil ifTrue: [ aTestSuite tests do: aBlock ] ifFalse: [ aTestSuite tests do: aBlock displayingProgress: aTestSuite name ] ] ensure: [ self basicTearDownSuite: aTestSuite ]. ! ! !TestRunner methodsFor: 'processing' stamp: 'lr 10/27/2005 10:04'! basicSetUpSuite: aTestSuite aTestSuite resources do: [ :each | each isAvailable ifFalse: [ each signalInitializationError ] ].! ! !TestRunner methodsFor: 'processing' stamp: 'lr 10/27/2005 10:04'! basicTearDownSuite: aTestSuite aTestSuite resources do: [ :each | each reset ].! ! !TestRunner methodsFor: 'testing' stamp: 'lr 11/21/2005 13:19'! hasErrors ^ result hasErrors.! ! !TestRunner methodsFor: 'testing' stamp: 'lr 11/21/2005 13:19'! hasFailures ^ result hasFailures.! ! !TestRunner methodsFor: 'testing'! hasFailuresOrErrors ^ result hasFailures | result hasErrors.! ! !TestRunner methodsFor: 'testing' stamp: 'lr 11/21/2005 13:19'! hasRunnable ^ classesSelected notEmpty.! ! !TestRunner methodsFor: 'theme'! theme "Answer the ui theme that provides controls." ^UITheme current! ! !TestRunner methodsFor: 'updating' stamp: 'lr 3/22/2006 19:35'! update self updateCategories; updateClasses! ! !TestRunner methodsFor: 'updating' stamp: 'lr 10/31/2005 15:45'! updateCategories categories := self findCategories. categoriesSelected := categoriesSelected isNil ifTrue: [ Set new ] ifFalse: [ categoriesSelected select: [ :each | categories includes: each ] ]. self changed: #categoryList; changed: #categorySelected.! ! !TestRunner methodsFor: 'updating' stamp: 'lr 1/20/2009 14:48'! updateClasses | classesForCategories | classesForCategories := self findClassesForCategories: categoriesSelected. classes := classesForCategories asArray sort: [ :a :b | self sortClass: a before: b ]. classIndex := 0. classesSelected := classesSelected isNil ifTrue: [ classesForCategories ] ifFalse: [ classesSelected select: [ :each | classesForCategories includes: each ] ]. self changed: #classList; changed: #classSelected; changed: #hasRunnable.! ! !TestRunner methodsFor: 'updating'! updateResults "<lint: #expect rule: #guardingClause>" "<lint: #expect rule: #longMethods>" self updateStatus: false. failedList size = result failures size ifFalse: [ failedList := result failures asArray sort: [ :a :b | a printString <= b printString ]. failedSelected := nil. self changed: #failedList; changed: #failedSelected; changed: #hasFailures; changed: #hasProgress; changed: #hasFailuresOrErrors ]. errorList size = result errors size ifFalse: [ errorList := result errors asArray sort: [ :a :b | a printString <= b printString ]. errorSelected := nil. self changed: #errorList; changed: #errorSelected; changed: #hasErrors; changed: #hasProgress; changed: #hasFailuresOrErrors ].! ! !TestRunner methodsFor: 'updating' stamp: 'lr 11/3/2005 09:28'! updateStatus: aBoolean "Update the status display, at most once a second if aBoolean is true." (aBoolean and: [ lastUpdate = Time totalSeconds ]) ifTrue: [ ^ self ]. self changed: #statusText; changed: #statusColor. lastUpdate := Time totalSeconds.! ! !TestRunner methodsFor: 'utilities'! findCategories | visible | visible := Set new. self baseClass withAllSubclassesDo: [ :each | each category ifNotNil: [ visible add: each category ] ]. ^ Array streamContents: [ :stream | Smalltalk organization categories do: [ :each | (visible includes: each) ifTrue: [ stream nextPut: each ] ] ].! ! !TestRunner methodsFor: 'utilities' stamp: 'lr 3/14/2010 21:13'! findClassesForCategories: aCollection | items | aCollection isEmpty ifTrue: [ ^ self baseClass withAllSubclasses asSet ]. items := aCollection gather: [ :category | ((Smalltalk organization listAtCategoryNamed: category) collect: [ :each | Smalltalk globals at: each ]) select: [ :each | each includesBehavior: self baseClass ] ]. ^ items asSet! ! !TestRunner methodsFor: 'utilities' stamp: 'lr 10/10/2005 08:43'! sortClass: aFirstClass before: aSecondClass | first second | first := aFirstClass withAllSuperclasses reversed. second := aSecondClass withAllSuperclasses reversed. 1 to: (first size min: second size) do: [ :index | (first at: index) == (second at: index) ifFalse: [ ^ (first at: index) name <= (second at: index) name ] ]. ^ second includes: aFirstClass.! ! !TestRunner methodsFor: 'private' stamp: 'lr 3/14/2010 21:13'! browserEnvironment ^ Smalltalk globals classNamed: #BrowserEnvironment! ! !TestRunner methodsFor: 'private' stamp: 'lr 10/27/2005 10:32'! label: aString forSuite: aTestSuite ^ String streamContents: [ :stream | stream nextPutAll: 'Running '; print: aTestSuite tests size; space; nextPutAll: aString. aTestSuite tests size > 1 ifTrue: [ stream nextPut: $s ] ]. ! ! !TestRunner methodsFor: 'private' stamp: 'lr 12/21/2005 10:39'! perform: selector orSendTo: otherTarget "<lint: #expect rule: #badMessage rational: 'this is a common morphic pattern'>" ^ (self respondsTo: selector) ifTrue: [ self perform: selector ] ifFalse: [ super perform: selector orSendTo: otherTarget ].! ! !TestRunner methodsFor: 'private' stamp: 'lr 3/22/2006 19:26'! windowIsClosing SystemChangeNotifier uniqueInstance noMoreNotificationsFor: self! ! !TestRunner commentStamp: '<historical>' prior: 0! "<lint: #ignore rule: #classNotReferenced rational: 'this view is only accessed from menus'> ! !TestRunner class methodsFor: 'initialization'! registerAsDefaultTestRunner TestRunnerBrowser default: self.! ! !TestRunner class methodsFor: 'instance-creation' stamp: 'KR 4/28/2006 21:07'! build ^ ToolBuilder build: self new.! ! !TestRunner class methodsFor: 'instance-creation' stamp: 'lr 10/8/2005 18:35'! open ^ ToolBuilder open: self new.! ! !TestRunner class methodsFor: 'window color'! patchworkUIThemeColor "Answer a default color for UI themes that make use of different colors for Browser, MessageList etc..." ^ Color brown whiter! ! !TestSuite methodsFor: 'accessing'! addTest: aTest self tests add: aTest! ! !TestSuite methodsFor: 'accessing'! addTests: aCollection aCollection do: [:eachTest | self addTest: eachTest]! ! !TestSuite methodsFor: 'accessing'! defaultResources ^self tests inject: OrderedCollection new into: [:coll :testCase | testCase resources do: [:each | (coll includes: each) ifFalse: [coll add: each]]. coll]! ! !TestSuite methodsFor: 'accessing'! name ^name! ! !TestSuite methodsFor: 'accessing'! name: aString name := aString! ! !TestSuite methodsFor: 'accessing'! resources resources isNil ifTrue: [resources := self defaultResources]. ^resources! ! !TestSuite methodsFor: 'accessing'! resources: someOrderedTestResourceClasses "The parameter should understand reverseDo: and should not contain duplicates." resources := someOrderedTestResourceClasses! ! !TestSuite methodsFor: 'accessing'! tests tests isNil ifTrue: [tests := OrderedCollection new]. ^tests! ! !TestSuite methodsFor: 'dependencies' stamp: 'md 2/22/2006 14:24'! addDependentToHierachy: anObject self addDependent: anObject. self tests do: [ :each | each addDependentToHierachy: anObject] ! ! !TestSuite methodsFor: 'dependencies' stamp: 'md 2/22/2006 14:24'! removeDependentFromHierachy: anObject self removeDependent: anObject. self tests do: [ :each | each removeDependentFromHierachy: anObject] ! ! !TestSuite methodsFor: 'running'! resourceClass ^TestResource! ! !TestSuite methodsFor: 'running'! resultClass ^ TestResult! ! !TestSuite methodsFor: 'running'! run | result | result := self resultClass new. [self run: result] ensure: [self resourceClass resetResources: self resources]. ^result! ! !TestSuite methodsFor: 'running'! run: aResult self tests do: [:each | self changed: each. each run: aResult]. ! ! !TestSuite commentStamp: '<historical>' prior: 0! This is a Composite of Tests, either TestCases or other TestSuites. The top-level protocol is #run. This creates aTestResult and sends self run: aTestResult. then ensures that any TestResources made available during the run are reset. These, and the dependencies protocol, are common between this and TestCase.! !TestSuite class methodsFor: 'instance creation'! named: aString ^self new name: aString; yourself! ! !Text methodsFor: 'converting' stamp: 'ssa 1/20/2010 10:35'! asParagraphWithStyle: aTextStyle "Answer a Paragraph whose text is the receiver." ^Paragraph withText: self style: aTextStyle! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:00'! bold "Force this whole text to be bold." string size = 0 ifTrue: [^self]. self makeBoldFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 8/22/2009 17:47'! emphasizeFrom: start to: stop with: emphasis "Set the emphasis for characters in the interval start-stop." runs _ runs copyReplaceFrom: start to: stop with: (RunArray new: stop - start + 1 withAll: emphasis)! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:01'! italic "Force this whole text to be italic." string size = 0 ifTrue: [^self]. self makeItalicFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:01'! makeItalicFrom: start to: stop ^ self addAttribute: TextEmphasis italic from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/27/2009 01:23'! makeUnderlineFrom: start to: stop ^ self addAttribute: TextEmphasis underline from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:03'! makeUnderlinedFrom: start to: stop ^ self addAttribute: TextEmphasis underlined from: start to: stop! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/27/2009 01:23'! underline "Force this whole text to be underline." string size = 0 ifTrue: [^self]. self makeUnderlineFrom: 1 to: string size! ! !Text methodsFor: 'emphasis' stamp: 'ssa 11/24/2009 19:03'! underlined "Force this whole text to be underlined." string size = 0 ifTrue: [^self]. self makeUnderlinedFrom: 1 to: string size! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 01:09'! font: aFont self addAttribute: (TextFontReference toFont: aFont)! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 01:28'! fontName: fname pointSize: ptsize " ('Hello World' asText fontName: #Accuny pointSize: 24) asParagraph display" | style sizes findex font availableSize | style _ TextStyle named:fname. sizes _ TextStyle fontPointSizesFor: fname. availableSize _ sizes detect:[:each| each >= ptsize] ifNone:[sizes last]. findex _ sizes indexOf: availableSize. font _ style fontAt:findex. self font: font "Accuat #(18 ) Accujen #(9 10 12 14 18 24 ) Accula #(12 24 ) Accumon #(9 10 12 ) Accuny #(9 10 12 14 18 24 ) Accusf #(18 ) Accushi #(12 ) Accuve #(12 14 ) Atlanta #(11 22 ) DefaultFixedTextStyle #(11 22 ) DefaultTextStyle #(9 10 12 14 18 24 )"! ! !Text methodsFor: 'attributes' stamp: 'ssa 11/27/2009 00:56'! fontNumber: anInteger self addAttribute: (TextFontChange fontNumber:anInteger)! ! !TextBlockDoIt methodsFor: 'accessing' stamp: 'ssa 9/15/2009 09:37'! actionBlock "Answer the value of actionBlock" actionBlock isNil ifTrue:[self actionBlock: [self notify:'default action block']]. ^ actionBlock! ! !TextBlockDoIt methodsFor: 'accessing' stamp: 'ssa 9/15/2009 09:36'! actionBlock: anObject "Set the value of actionBlock" actionBlock _ anObject! ! !TextBlockDoIt methodsFor: 'activating' stamp: 'ssa 9/15/2009 09:38'! actOnClickFor: anObject self actionBlock value. ^true! ! !TextStyle class methodsFor: 'user interface' stamp: 'ssa 9/4/2009 21:20'! mvcPromptForFont: aPrompt "MVC Only!! prompt for a font and if one is provided, send it to aTarget using a message with selector aSelector." | aMenu aChoice aStyle namesAndSizes | "TextStyle mvcPromptForFont: 'Choose system font style' " aMenu _ CustomMenu new. self actualTextStyles keys do: [:styleName | aMenu add: styleName action: styleName]. aChoice _ aMenu startUpWithCaption: aPrompt. aChoice ifNil: [^ self]. aMenu _ CustomMenu new. aStyle _ self named: aChoice. (namesAndSizes _ aStyle fontNamesWithPointSizes) do: [:aString | aMenu add: aString action: aString]. aChoice _ aMenu startUpWithCaption: nil. aChoice ifNil: [^ self]. ^aStyle fontAt: (namesAndSizes indexOf: aChoice). ! ! !TextStyle class methodsFor: 'user interface' stamp: 'ssa 9/4/2009 21:11'! mvcPromptForStyle: aPrompt andSendTo: aTarget withSelector: aSelector "MVC Only!! prompt for a font and if one is provided, send it to aTarget using a message with selector aSelector." | aMenu aChoice aStyle namesAndSizes aFont | "TextStyle mvcPromptForFont: 'Choose system font style' andSendTo: TextStyle withSelector: #setSystemFontTo:" aMenu _ CustomMenu new. self actualTextStyles keys do: [:styleName | aMenu add: styleName action: styleName]. aChoice _ aMenu startUpWithCaption: aPrompt. aChoice ifNil: [^ self]. aMenu _ CustomMenu new. aStyle _ self named: aChoice. (namesAndSizes _ aStyle fontNamesWithPointSizes) do: [:aString | aMenu add: aString action: aString]. aChoice _ aMenu startUpWithCaption: nil. aChoice ifNil: [^ self]. aTarget perform: aSelector with: aStyle! ! !Time class methodsFor: '*SMark-squeak protocol' stamp: 'sm 5/25/2011 14:26'! milliseconds: currentTime since: lastTime "Answer the elapsed time since last recorded in milliseconds. Compensate for rollover." | delta | delta := currentTime - lastTime. ^ delta < 0 ifTrue: [SmallInteger maxVal + delta] ifFalse: [delta] ! ! !TranscriptStream methodsFor: 'initialization' stamp: 'ssa 9/3/2008 11:13'! openLabel: aString "Open a window on this transcriptStream" | topView codeView | topView _ (StandardSystemView new) model: self. topView borderWidth: 1. topView label: aString. topView minimumSize: 100 @ 50. codeView _ PluggableTextView on: self text: nil accept: nil readSelection: nil menu: #codePaneMenu:shifted:. codeView window: (0@0 extent: 200@200). topView addSubView: codeView. topView controller open! ! !TranscriptStream methodsFor: '*Ly' stamp: 'ssa 7/16/2010 17:06'! nextPutAll: stuff self showInConsole ifTrue:[stuff printConsole]. super nextPutAll: stuff. ! ! !TranscriptStream methodsFor: '*Ly' stamp: 'dmu 3/22/2010 02:58'! resetSemaphore AccessSema signal! ! !TranscriptStream methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 14:03'! showInConsole ^self class showInConsole! ! !TranscriptStream methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 14:04'! showInConsole: aBoolean ^self class showInConsole: aBoolean! ! !TranscriptStream methodsFor: '*RVMBootstrap' stamp: 'ssa 7/5/2010 13:02'! showInConsoleSwitch "Transcript showInConsoleSwitch demo" ^RVMCheckBoxView on: nil label: 'Show Transcript in Console' checkState: [Transcript showInConsole] whenChecked: [Transcript showInConsole: true] whenUnchecked: [Transcript showInConsole: false].! ! !TranscriptStream methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 14:04'! toggleShowInConsole self class toggleShowInConsole! ! !TranscriptStream methodsFor: '*RVM' stamp: 'StefanMarr 7/14/2011 17:44'! nextPut: chr "Evil hack for some more platform independence...." chr = Character lf ifTrue: [ super nextPut: Character cr.] ifFalse: [super nextPut: chr ].! ! !TranscriptStream class methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 13:58'! showInConsole "A flag to support mirroring the transcript in the RVM console" ShowInConsole isNil ifTrue:[ShowInConsole _ false]. ^ShowInConsole! ! !TranscriptStream class methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 13:58'! showInConsole: aBoolean "A flag to support mirroring the transcript in the RVM console" ShowInConsole _ aBoolean! ! !TranscriptStream class methodsFor: '*RVMBootstrap' stamp: 'ssa 3/24/2010 13:59'! toggleShowInConsole self showInConsole: self showInConsole not! ! !Transcripter methodsFor: 'command line' stamp: 'ssa 7/7/2010 19:30'! readEvalPrint | line okToRevert | Sensor flushKeyboard. okToRevert _ true. [#('quit' 'exit' 'done' 'restart' 'refresh' 'revert') includes: (line _ self request: '>') ] whileFalse: [line = 'refresh' ifTrue:[ScheduledControllers restore halt] ifFalse:[line = 'restart' ifTrue:[ProcessorScheduler removeAllPossible] ifFalse:[line = 'revert' ifTrue: [okToRevert ifTrue: [Utilities revertLastMethodSubmission. self cr; show: 'reverted: ' , Utilities mostRecentlySubmittedMessage. okToRevert _ false] ifFalse: [self cr; show: 'Only one level of revert currently supported']] ifFalse: [self cr; show: ([Compiler evaluate: line] ifError: [:err :ex | err])]]]]! ! !Transcripter class methodsFor: 'utilities' stamp: 'ssa 6/11/2010 13:29'! emergencyEvaluator (Transcripter newInFrame: (0@0 corner: 320@200)) show: 'Type ''revert'' to revert your last method change. Type ''restart'' to restart the processor scheduler. Type ''refresh'' to refresh the display. Type ''exit'' to exit the emergency evaluator.'; readEvalPrint! ! !TransportFormat methodsFor: 'transporter' stamp: 'ads 12/23/2010 13:47'! transporter ^ transporter! ! !TransportFormat methodsFor: 'transporter' stamp: 'ads 12/23/2010 13:47'! transporter: t transporter := t.! ! !TransportFormat methodsFor: 'root directory' stamp: 'ads 1/6/2011 13:13'! createRoot self rootDirectory: ( self createDir: self rootName in: transporter baseDirectory mustBeNew: true )! ! !TransportFormat methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:04'! rootDirectory "Answer the value of rootDirectory" rootDirectory isNil ifTrue:[self rootDirectory: nil]. ^ rootDirectory! ! !TransportFormat methodsFor: 'root directory'! rootDirectory: anObject "Set the value of rootDirectory" rootDirectory := anObject! ! !TransportFormat methodsFor: 'root directory' stamp: 'dmu 8/23/2010 14:00'! rootName "Answer the value of rootName" rootName isNil ifTrue:[self rootName: 'root']. ^ rootName! ! !TransportFormat methodsFor: 'root directory'! rootName: anObject "Set the value of rootName" rootName := anObject! ! !TransportFormat methodsFor: 'directories' stamp: 'dmu 8/23/2010 14:35'! classCategoryDirFor: cat ^ self createDir: cat in: self rootDirectory mustBeNew: false! ! !TransportFormat methodsFor: 'directories'! createDir: leafName in: parentDir mustBeNew: mustBeNew | d validLeafName | validLeafName := self validNameForDir: leafName in: parentDir. leafName asString = validLeafName ifFalse: [Transcript show: 'Warning: renamed directory ', leafName asString, ' to ', validLeafName; cr]. d := parentDir directoryNamed: validLeafName. (mustBeNew and: [d exists]) ifTrue: [| oldDirName oldDir | oldDirName := validLeafName, '.old'. oldDir := parentDir directoryNamed: oldDirName. oldDir exists ifTrue: [oldDir recursiveDelete]. Transcript show: d fullName, ' already exists. Renaming it to ', oldDirName; cr. parentDir rename: validLeafName toBe: oldDirName. d exists ifTrue: [self error: 'Assertion failure; the directory should not exist anymore, we just tried to rename it.']. ]. d exists ifFalse: [d assureExistence]. ^ d ! ! !TransportFormat methodsFor: 'directories' stamp: 'ads 12/3/2010 12:04'! validNameForDir: leafName in: parentDir "MacOS doesn't like slashes in directory names. -- Adam" ^ leafName asString replaceAll: $/ with: $-! ! !TransportFormat methodsFor: 'saving' stamp: 'ads 1/6/2011 13:14'! savePackage: p self createRoot. self saveScriptForLoadingPackageBackIn: p. self saveAllClassesForPackage: p. self saveAllExtensionMethodsForPackage: p.! ! !TransportFormat methodsFor: 'saving methods' stamp: 'ads 12/10/2010 12:26'! saveAllExtensionMethodsForPackage: p self subclassResponsibility! ! !TransportFormat methodsFor: 'saving classes' stamp: 'ads 12/14/2010 14:14'! saveAllClassesForPackage: p p classes asArray do: [:cls | self saveClass: cls forPackage: p] displayingProgress: 'Saving ', p name, ' classes'. ! ! !TransportFormat methodsFor: 'saving classes' stamp: 'ads 12/2/2010 15:24'! saveClass: cls forPackage: p self subclassResponsibility! ! !TransportFormat methodsFor: 'loading'! classesInOrderForLoading: p | extensionClassNames extensionClasses coreClasses coreClassNames | "Gotta sort them to make sure superclassOrder: always puts them in canonical order." coreClassNames := (p classes collect: [:cls | cls theNonMetaClass name]) asSet asArray sort. extensionClassNames := (p extensionClasses collect: [:cls | cls theNonMetaClass name]) asSet asArray sort. coreClasses := coreClassNames collect: [:n | Smalltalk classNamed: n]. extensionClasses := extensionClassNames collect: [:n | Smalltalk classNamed: n]. ^ self transporter fiddleWithClassLoadingOrder: extensionClasses, (ChangeSet superclassOrder: coreClasses)! ! !TransportFormat methodsFor: 'loading' stamp: 'ads 12/10/2010 12:27'! saveScriptForLoadingPackageBackIn: p self subclassResponsibility! ! !TransportFormat methodsFor: 'preamble and postscript' stamp: 'ads 12/14/2010 12:15'! postscriptBlock ^ postscriptBlock! ! !TransportFormat methodsFor: 'preamble and postscript' stamp: 'ads 12/14/2010 12:15'! postscriptBlock: aBlock postscriptBlock := aBlock.! ! !TransportFormat methodsFor: 'preamble and postscript' stamp: 'ads 12/10/2010 12:39'! preambleBlock ^ preambleBlock! ! !TransportFormat methodsFor: 'preamble and postscript' stamp: 'ads 12/10/2010 12:39'! preambleBlock: aBlock preambleBlock := aBlock.! ! !Transporter methodsFor: 'accessing' stamp: 'ads 1/4/2011 15:56'! baseDirectory ^ baseDirectory ifNil: [FileDirectory default]! ! !Transporter methodsFor: 'accessing' stamp: 'ads 1/4/2011 15:56'! baseDirectory: aDirectory baseDirectory := aDirectory.! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/10/2010 11:54'! package ^ package! ! !Transporter methodsFor: 'accessing'! package: anObject package := anObject! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/14/2010 12:30'! postscriptBlock ^ postscriptBlock! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/14/2010 12:31'! postscriptBlock: aBlock postscriptBlock := aBlock.! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/14/2010 12:31'! preambleBlock ^ preambleBlock! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/14/2010 12:31'! preambleBlock: aBlock preambleBlock := aBlock.! ! !Transporter methodsFor: 'accessing' stamp: 'sm 7/8/2011 23:14'! subTransporters: anArrayOfTransporters subTransporters := anArrayOfTransporters! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/10/2010 11:54'! team ^ team! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/10/2010 11:54'! team: anObject team _ anObject! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/10/2010 12:08'! transportFormatClass ^ transportFormatClass ifNil: [OneFilePerClass]! ! !Transporter methodsFor: 'accessing' stamp: 'ads 12/10/2010 12:08'! transportFormatClass: anObject transportFormatClass _ anObject! ! !Transporter methodsFor: 'reverting' stamp: 'ads 12/10/2010 13:04'! revert self team revertPackage: self package.! ! !Transporter methodsFor: 'loading' stamp: 'ads 12/23/2010 13:50'! fiddleWithClassLoadingOrder: classes "Can be overridden by children who need special ordering." ^ classes! ! !Transporter methodsFor: 'saving' stamp: 'ads 12/23/2010 13:48'! createTransportFormat ^ self transportFormatClass new transporter: self; rootName: self package name; preambleBlock: self preambleBlock; postscriptBlock: self postscriptBlock; yourself! ! !Transporter methodsFor: 'saving' stamp: 'sm 7/8/2011 23:13'! save self willAllChangesInCurrentChangeSetBeSaved ifFalse: [ (PopUpMenu confirm: 'There are changes in the current changeset that will not be saved.' trueChoice: 'Save anyway!!' falseChoice: 'Cancel the save, show me what''s changed') ifFalse: [ ChangeSorter new showChangeSet: ChangeSet current; open. ^ self. ]. ]. self createTransportFormat savePackage: self package. self saveSubTransporters.! ! !Transporter methodsFor: 'saving' stamp: 'sm 7/8/2011 23:13'! saveNoPopup self willAllChangesInCurrentChangeSetBeSaved ifFalse: [ Transcript show: 'Not all changes in current ChangeSet will be saved'; cr. ]. self createTransportFormat savePackage: self package. self saveSubTransporters.! ! !Transporter methodsFor: 'saving' stamp: 'sm 7/8/2011 23:15'! saveSubTransporters subTransporters ifNotNil: [ subTransporters do: [:trsp | trsp saveNoPopup ]].! ! !Transporter methodsFor: 'changes' stamp: 'ads 1/26/2011 14:23'! willAllChangesInCurrentChangeSetBeSaved ^ ChangeSet current changedPackages allSatisfy: [:p | self package includesPackage: p]! ! !Transporter methodsFor: 'searching' stamp: 'ads 12/10/2010 12:12'! findMethodsWrittenByThisTeamButNotIncludedInPackage ^ self team findMethodsWrittenByThisTeamButNotIncludedInPackage: self package, (PackageInfo named: 'Transporter')! ! !Transporter class methodsFor: 'as yet unclassified' stamp: 'sm 3/10/2011 17:43'! findAllMethodChangedByTeamButNotTransported "Transporter findAllMethodChangedByTeamButNotTransported" "Find all changes in the system that were done by a team member but are not yet included in any of the Transporter packages/definitions" | transportersByName teams packages changedMethods systemCats tricky | transportersByName := self getAllTransporters. "next: get all teams and categories" teams := OrderedCollection new. systemCats := OrderedCollection new. packages := nil. transportersByName valuesDo: [:trns | trns team ifNotNil: [teams add: (trns team)]. systemCats addAll: trns package systemCategories. packages ifNil: [packages := trns package.] ifNotNil: [packages := packages, trns package.] ]. tricky := self constructTrickySet. changedMethods := Set new. ((Smalltalk allClasses reject: [:cls | systemCats includes: cls category]) gather: [:cls| {cls. cls class}]) do: [:cls | cls organization allMethodSelectors do: [:sel | | mr crs | mr := MethodReference new setStandardClass: cls methodSymbol: sel. crs := mr changeRecords. crs isEmpty ifFalse: [ teams do: [:team | (team didProjectMemberCreateChangeRecord: crs first) ifTrue: [ (packages isYourClassExtension: mr category) ifFalse: [ (tricky includes: (((cls name asString), '>>', sel asString) asSymbol)) ifFalse: [ changedMethods add: mr. ]. ]. ]. ]. ]. ]. ]. ^ changedMethods asArray! ! !Transporter class methodsFor: 'as yet unclassified' stamp: 'ads 1/26/2011 13:26'! nonCategoryBasedPackages "Not sure what would be the right way to do this. -- Adam, Jan. 2011" ^ PackageWhoseContentsMustBeTransportedInOrder allSubclasses collect: [:c | c new]! ! !Transporter class methodsFor: 'private' stamp: 'sm 3/10/2011 16:54'! classAndOrMethodAsUniqueSymbole: anArray anArray size = 1 ifTrue: [^ (anArray at: 1) asSymbol ] ifFalse: [^ ((anArray at: 1), '>>', (anArray at: 2)) asSymbol ].! ! !Transporter class methodsFor: 'private' stamp: 'sm 3/10/2011 17:31'! constructTrickySet "Transporter constructTrickySet" "Creates a set with symboles for all tricky elements" | result | result := Set new. self getAllTrickyDefinitions do: [:def | | uniqueSymbol | uniqueSymbol := self classAndOrMethodAsUniqueSymbole: def. (result includes: uniqueSymbol) ifTrue: [Transcript show: 'Multiple includes of ', uniqueSymbol asString.]. result add: uniqueSymbol. ]. ^ result! ! !Transporter class methodsFor: 'private' stamp: 'sm 3/10/2011 16:49'! constructTrickySet: transportersByName "Creates a set with symboles for all tricky elements" | result | result := Set new. transportersByName valuesDo: [:trans | trans trickyModificationsThatNeedToBeDoneInOrder do: [:trickyElem | result add: (self classAndOrMethodAsUniqueSymbole: trickyElem ) ]. ].! ! !Transporter class methodsFor: 'transporter' stamp: 'StefanMarr 7/14/2011 13:11'! fileOutPackage: aPackageName (Transporter forPackage: (PackageInfo named: aPackageName)) saveNoPopup.! ! !Transporter class methodsFor: 'transporter' stamp: 'ads 12/14/2010 12:26'! forEntireImage ^ self forPackage: CompositePackageInfo forEntireImage! ! !Transporter class methodsFor: 'transporter' stamp: 'ads 12/14/2010 12:25'! forPackage: p ^ self new package: p; yourself! ! !Transporter class methodsFor: 'transporter' stamp: 'sm 3/10/2011 15:34'! getAllTransporters "Identify all transporters based on #transportersForFileOutMenu" | transportersByName | transportersByName _ Dictionary new. Smalltalk allClassesDo: [:class | (class respondsTo: #transportersForFileOutMenu) ifTrue: [ class transportersForFileOutMenu do: [:transporter | transportersByName at: transporter package name put: transporter. ]. ]. ]. ^ transportersByName.! ! !Transporter class methodsFor: 'transporter' stamp: 'sm 4/22/2011 00:06'! getAllTrickyDefinitions "Transporter getAllTrickyDefinitions" "Identify all tricky definitions based on #trickyModificationsThatNeedToBeDoneInOrder" | tricky | tricky _ OrderedCollection new. Smalltalk allClassesDo: [:class | (class canUnderstand: #trickyModificationsThatNeedToBeDoneInOrder) ifTrue: [ | modifications | modifications := class new trickyModificationsThatNeedToBeDoneInOrder. modifications ifNotNil: [ tricky addAll: modifications. ]. ]. ]. ^ tricky.! ! !Transporter class methodsFor: 'transporter' stamp: 'sm 5/24/2011 23:27'! loadPackage: aPackageName "This is a convenience method to not require to remember how to file in stuff. It just uses the package name and the implemented convention to guess the file and load it." | stream chgSetName aNewChangeSet cls | stream := FileStream fileNamed: aPackageName, '/', aPackageName,'.st'. chgSetName := ChangeSet uniqueNameLike: stream localName sansPeriodSuffix. cls := (ChangeSet respondsTo: #newChangesFromStream:named:) ifTrue: [ChangeSet] ifFalse: [ChangeSorter]. aNewChangeSet := cls newChangesFromStream: stream named: chgSetName. aNewChangeSet ifNotNil: [ChangeSorter open model showChangeSet: aNewChangeSet]! ! !Transporter class methodsFor: 'transporter' stamp: 'ads 1/3/2011 17:41'! transportersForFileOutMenu ^ { Transporter forPackage: (PackageInfo named: 'Transporter') }! ! !True methodsFor: 'debugging' stamp: 'ssa 3/11/2010 11:54'! haltIfTrue self halt! ! !True class methodsFor: '*RVM-Archiving'! dearchiveFrom: aStream aStream storeObject: true. ^true! ! !UndefinedObject methodsFor: '*RVM-Archiving'! archiveOn: aStream aStream storeClass: self class! ! !UndefinedObject class methodsFor: 'instance creation'! dearchiveFrom: aStream ^nil! ! !UnhandledError methodsFor: 'priv handling' stamp: 'dmu 11/25/2008 00:25'! devDefaultAction Processor thisProcess debug: exception signalerContext title: exception description! ! !UpdateImage class methodsFor: 'script entry'! run: args "The loading needs to be done after everything in startup has been done. Otherwise the snaphost routine gets confused. Thus, we do that ourselfs." ScriptStarter quitVMAfterScriptExecution: false. self fileInAllRenaissanceCode. ScriptStarter quitVMAfterScriptExecution: false. ! ! !UpdateImage class methodsFor: 'fileIn script'! fileInAllRenaissanceCode "Create an up-to-date image" Transcript show: 'Save as updated.image.'; cr. SmalltalkImage current saveAs: 'updated-tmp.image'. Transcript show: 'File in code.'; cr. (FileStream readOnlyFileNamed: 'FileInAllRenaissanceCode.st') fileIn. Transcript show: 'Done filing in code. Now Save and Quit.'; cr. SmalltalkImage current saveAs: 'updated.image'. SmalltalkImage current closeSourceFiles. Smalltalk snapshot: true andQuit: true.! ! !Utilities class methodsFor: 'miscellaneous' stamp: 'ssa 1/21/2010 12:17'! exploreViewFromUser ScheduledControllers screenController exploreViewFromUser! ! !Utilities class methodsFor: 'user interface' stamp: 'ssa 9/3/2008 11:13'! informUserDuring: aBlock "Display a message above (or below if insufficient room) the cursor during execution of the given block." "Utilities informUserDuring:[:bar| #(one two three) do:[:info| bar value: info. (Delay forSeconds: 1) wait]]" aBlock value:[:string| Transcript cr; show: string]! ! !Utilities class methodsFor: 'finding pointers' stamp: 'ar 7/16/2005 19:56'! pointersTo: anObject "Find all occurrences in the system of pointers to the argument anObject." "(Utilities pointersTo: Browser) inspect." ^ self pointersTo: anObject except: #() ! ! !Utilities class methodsFor: 'finding pointers' stamp: 'dmu 3/23/2010 12:31'! pointersTo: anObject except: objectsToExclude "Find all occurrences in the system of pointers to the argument anObject. Remove objects in the exclusion list from the results. " | results anObj | Transcript cr; show: 'Calling garbageCollect from pointersTo:except:'. Smalltalk garbageCollect. "big collection shouldn't grow, so it's contents array is always the same" results := OrderedCollection new: 1000. "allObjectsDo: is expanded inline to keep spurious method and block contexts out of the results" anObj := self someObject. [0 == anObj] whileFalse: [ anObj isInMemory ifTrue: [ (anObj pointsTo: anObject) ifTrue: [ "exclude the results collector and contexts in call chain" (anObj ~~ results collector and: [anObj ~~ objectsToExclude and: [anObj ~~ thisContext and: [anObj ~~ thisContext sender and: [anObj ~~ thisContext sender sender]]]]) ifTrue: [results add: anObj]]]. anObj := anObj nextObject]. objectsToExclude do: [:obj | results removeAllSuchThat: [:el | el == obj]]. ^ results asArray! ! !Utilities class methodsFor: 'finding pointers' stamp: 'ar 7/16/2005 19:56'! pointersToItem: index of: anArray "Find all occurrences in the system of pointers to the given element of the given array. This is useful for tracing up a pointer chain from an inspector on the results of a previous call of pointersTo:. To find out who points to the second element of the results, one would evaluate: Utilities pointersToItem: 2 of: self in the inspector." ^ self pointersTo: (anArray at: index) except: (Array with: anArray)! ! !VersionsBrowser methodsFor: 'init & update' stamp: 'dmu 9/7/2010 14:26'! scanVersionsOf: method class: class meta: meta category: category selector: selector | position prevPos prevFileIndex preamble tokens sourceFilesCopy stamp | selectorOfMethod _ selector. currentCompiledMethod _ method. classOfMethod _ meta ifTrue: [class class] ifFalse: [class]. changeList _ OrderedCollection new. list _ OrderedCollection new. self addedChangeRecord ifNotNilDo: [ :change | self addItem: change text: ('{1} (in {2})' translated format: { change stamp. change fileName }) ]. listIndex _ 0. position _ method filePosition. sourceFilesCopy _ SourceFiles collect: [:x | x isNil ifTrue: [ nil ] ifFalse: [x readOnlyCopy]]. method fileIndex == 0 ifTrue: [^ nil]. file _ sourceFilesCopy at: method fileIndex. [position notNil & file notNil] whileTrue: [file position: (0 max: position-150). "Skip back to before the preamble" [file position < (position-1)] "then pick it up from the front" whileTrue: [preamble _ file nextChunk]. "Preamble is likely a linked method preamble, if we're in a changes file (not the sources file). Try to parse it for prior source position and file index" prevPos _ nil. stamp _ ''. (preamble findString: 'methodsFor:' startingAt: 1) > 0 ifTrue: [tokens _ Scanner new scanTokens: preamble] ifFalse: [tokens _ Array new "ie cant be back ref"]. ((tokens size between: 7 and: 8) and: [(tokens at: tokens size-5) = #methodsFor:]) ifTrue: [(tokens at: tokens size-3) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size-2. prevPos _ tokens last. prevFileIndex _ sourceFilesCopy fileIndexFromSourcePointer: prevPos. prevPos _ sourceFilesCopy filePositionFromSourcePointer: prevPos] ifFalse: ["Old format gives no stamp; prior pointer in two parts" prevPos _ tokens at: tokens size-2. prevFileIndex _ tokens last]. (prevPos = 0 or: [prevFileIndex = 0]) ifTrue: [prevPos _ nil]]. ((tokens size between: 5 and: 6) and: [(tokens at: tokens size-3) = #methodsFor:]) ifTrue: [(tokens at: tokens size-1) = #stamp: ifTrue: ["New format gives change stamp and unified prior pointer" stamp _ tokens at: tokens size]]. self addItem: (ChangeRecord new file: file position: position type: #method class: class name category: category meta: meta stamp: stamp) text: stamp , ' ' , class name , (meta ifTrue: [' class '] ifFalse: [' ']) , selector. position _ prevPos. prevPos notNil ifTrue: [file _ sourceFilesCopy at: prevFileIndex]]. sourceFilesCopy do: [:x | x notNil ifTrue: [x close]]. listSelections _ Array new: list size withAll: false! ! !View methodsFor: 'initialize-release' stamp: 'ssa 11/30/2009 17:50'! setDefaultBackgroundColor self backgroundColor: self model defaultBackgroundColor! ! !View methodsFor: 'testing' stamp: 'ssa 1/1/1970 00:19'! isRVMView ^false! ! !View methodsFor: 'subView access' stamp: 'ssa 1/1/1970 12:58'! allSubViews "Answer the receiver's collection of subViews and their subViews recursively." | all | all _ OrderedCollection new. all addAll: self subViews. self subViews do:[:sub| all addAll: sub allSubViews]. ^all! ! !View methodsFor: 'subView access' stamp: 'ssa 10/19/2008 00:00'! subViewsSatisfying: aBlock "Return the subviews that satisfy aBlock, or #() if none does. 1/31/96 sw" ^ subViews select: [:aView | aBlock value: aView]! ! !View methodsFor: 'lock access'! unlock "Unlock the receiver and all of its subViews (see View|isUnlocked). This has the effect of forcing the display transformation (see View|displayTransformation) and inset display box (see View|insetDisplayBox) of the receiver and all its subViews to be recomputed the next time they are referenced. The locking and unlocking of a View is handled automatically by the internal methods of the View, but can also be done explicitly if desired." "Added a guard clause to protect against empty subview collections. This is one reason why lazy initialization and consistent use of accessor methods is better than direct access. - ssa 2/27/98 11:26" self isUnlocked ifTrue: [^self]. displayTransformation _ nil. insetDisplayBox _ nil. subViews isNil ifFalse:[subViews do: [:aSubView | aSubView unlock]]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:54'! addSubView: aSubView above: lowerView "Adds aView (see View|addSubView:) so that it lies above topView." "ssa - added a hack to allow nil lowerView" lowerView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport bottomLeft with: lowerView viewport topLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:55'! addSubView: aSubView below: lowerView "Add the argument, aSubView, (see View|addSubView:) so that it lies below the view, topView." "ssa - added a hack to allow nil lowerView" lowerView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topLeft with: lowerView viewport bottomLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 8/15/2008 17:31'! addSubView: aView in: aRelativeRectangle borderWidth: width "ssa - added for compatibility." "Make 'aView' into a subview. Use 'aRelativeRectangle' and the super view's window to compute (1) a viewport within the superview for 'aView' and (2) the window extent for 'aView'. Note: defining the windowing transformation and deriving the viewport is logically equivalent but does not seem to be easily done" | subViewPort myWindow myExtent myOrigin | self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']. aView borderWidth: width. myWindow _ self window. myExtent _ myWindow extent. myOrigin _ myWindow origin. subViewPort _ myExtent * aRelativeRectangle origin + myOrigin corner: myExtent * aRelativeRectangle corner + myOrigin. aView window: aView window viewport: subViewPort ! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:55'! addSubView: aSubView toLeftOf: rightView "Adds aView (see addSubView:) so that it lies to the right of rightView." "ssa - added a hack to allow nil rightView" rightView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topRight with: rightView viewport topLeft]! ! !View methodsFor: 'subView inserting' stamp: 'ssa 9/13/2008 16:56'! addSubView: aSubView toRightOf: leftView "Add the argument, aSubView, (see View|addSubView:) so that it lies to the right of the view, leftView." "ssa - added a hack to allow nil leftView" leftView isNil ifTrue:[self addSubView: aSubView] ifFalse:[self addSubView: aSubView align: aSubView viewport topLeft with: leftView viewport topRight]! ! !View methodsFor: 'miscellaneous' stamp: 'ssa 10/8/2008 17:54'! stretchFrame: newFrameBlock startingWith: startFrame "Track the outline of a newFrame as long as mouse drags it. Maintain max and min constraints throughout the drag" | frame newFrame click delay | delay _ Delay forMilliseconds: 10. frame _ startFrame origin extent: ((startFrame extent min: self maximumSize) max: self minimumSize). Display border: frame width: 2 rule: Form reverse fillColor: Color gray. click _ false. [click and: [Sensor noButtonPressed]] whileFalse: ["delay wait." click _ click | Sensor anyButtonPressed. newFrame _ newFrameBlock value: frame. newFrame _ newFrame topLeft extent: ((newFrame extent min: self maximumSize) max: self minimumSize). newFrame = frame ifFalse: [Display border: frame width: 2 rule: Form reverse fillColor: Color gray. Display border: newFrame width: 2 rule: Form reverse fillColor: Color gray. frame _ newFrame]]. Display border: frame width: 2 rule: Form reverse fillColor: Color gray. ^ frame! ! !View methodsFor: 'demonstrating' stamp: 'ssa 11/27/2008 10:05'! demo "Add me to a system view and open me on the desktop" self demoSized: self minimumSize! ! !View methodsFor: 'demonstrating' stamp: 'ssa 11/27/2008 10:05'! demoSized: anExtent "Add me to a system view and open me on the desktop" | topView | topView := StandardSystemView new. topView borderWidth:1. topView minimumSize: anExtent. topView addSubView: self . topView label: self class name,' demo'. topView controller open! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! borderColor "Answer the value of borderColor" borderColor isNil ifTrue:[self borderColor: self foregroundColor]. ^ borderColor! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! borderColor: anObject "Set the value of borderColor" borderColor _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! boundingBox: anObject "Set the value of boundingBox" boundingBox _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! displayTransformation: anObject "Set the value of displayTransformation" displayTransformation _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! insetDisplayBox: anObject "Set the value of insetDisplayBox" insetDisplayBox _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! insideColor "Answer the value of insideColor" insideColor isNil ifTrue:[self insideColor: nil]. ^ insideColor! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! subViews: anObject "Set the value of subViews" subViews _ anObject! ! !View methodsFor: 'accessing' stamp: 'ssa 3/12/2010 10:12'! viewport: anObject "Set the value of viewport" viewport _ anObject! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:52'! moveBy: delta "Move me delta left in my superView" | scaledDelta | scaledDelta _ self viewport width / self insetDisplayBox width * delta. self transformUsing:[:ovp| ovp moveBy: scaledDelta]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveDown "Move me 10 pixels down in my superView" self moveBy:(0@10)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:50'! moveFrom: oldBox "Move me to ensure I refect my window/viewport" self uncacheBits. self displayEmphasized. self moved. "In case its model wishes to take note." (oldBox areasOutside: self windowBox) do: [:rect | ScheduledControllers restore: rect]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveLeft "Move me 10 pixels left in my superView" self moveBy:(-10@0)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveRight "Move me 10 pixels right in my superView" self moveBy:(10@0)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:54'! moveUp "Move me 10 pixels up in my superView" self moveBy:(0 @ -10)! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:55'! narrower "Make me 5% narrower in my superView" self transformUsing:[:ovp| ovp expandBy:(ovp width*0.05)negated@0]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:57'! shorter "Make me 5% shorter in my superView" self transformUsing:[:ovp| ovp expandBy:0@(ovp height*0.05)negated]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:57'! taller "Make me 5% taller in my superView" self transformUsing:[:ovp| ovp expandBy:0@(ovp height*0.05)]! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 17:43'! transformUsing: aBlock "self transformUsing: [:oldViewport | ...return new viewport... ] " "Change my viewport and update me on the display" | ovp nvp ow | ovp _ self viewport. ow _ self getWindow. nvp _ aBlock value:ovp. self window: self window viewport: nvp. self moveFrom: ow. self unlock.! ! !View methodsFor: '*Ly experiments' stamp: 'ssa 3/12/2010 16:55'! wider "Make me 5% wider in my superView" self transformUsing:[:ovp| ovp expandBy:(ovp width*0.05)@0]! ! !View methodsFor: '*Interface-MSWLook'! percentContentVisible "Answer the percent of my content that is visible. ssa 12/5/97 15:37" ^self visibleContentHeight / self totalContentHeight! ! !View methodsFor: '*Interface-MSWLook'! percentPrecedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" ^0.0! ! !View methodsFor: '*Interface-MSWLook'! percentPreceedingContent "Answer the percent of my content that not visible since it has been scrolled of the top of the screen. ssa 12/5/97 15:37" ^0.0! ! !View methodsFor: '*Interface-MSWLook'! percentVisibleContent "Answer the percent of my content that is visible. ssa 12/5/97 15:37" ^self totalContentHeight = 0 ifTrue:[0.0] ifFalse:[self visibleContentHeight / self totalContentHeight]! ! !View methodsFor: '*Interface-MSWLook'! totalContentHeight "Answer the height of my content, visible or not. ssa 12/5/97 15:04" ^100 / self unitContentHeight! ! !View methodsFor: '*Interface-MSWLook'! unitContentHeight "Answer the unit height of my content. ssa 12/5/97 15:04" ^10.0! ! !View methodsFor: '*Interface-MSWLook'! visibleContentHeight "Answer the height of my visible content. ssa 12/5/97 15:04" ^100 / self unitContentHeight! ! !WeakArray class methodsFor: 'private' stamp: 'sm 2/24/2011 16:41'! restartFinalizationProcess "kill any old process, just in case" FinalizationProcess ifNotNil: [FinalizationProcess terminate. FinalizationProcess := nil]. "Check if Finalization is supported by this VM" IsFinalizationSupported := nil. self isFinalizationSupported ifFalse: [^ self]. FinalizationSemaphore := Smalltalk specialObjectsArray at: 42. FinalizationDependents ifNil: [FinalizationDependents := WeakArray new: 10]. FinalizationLock := Semaphore forMutualExclusion. FinalizationProcess := [self finalizationProcess] forkAt: Processor userInterruptPriority. FinalizationProcess name: 'WeakArray Finalization'. ! ! !Workspace methodsFor: 'menu commands' stamp: 'ssa 9/3/2008 10:48'! addModelItemsToWindowMenu: aMenu "Add model-related items to the supplied window menu" aMenu addLine. aMenu add: 'save contents to file...' target: self action: #saveContentsInFile. aMenu addLine. ! ! !WriteStream methodsFor: '*SMark-printing' stamp: 'sm 5/25/2011 14:30'! << aCollection "we want a readable version of nextPutAll however it may be difficult to fully recreate nextPutAll: for all the different types of stream. Rather then simply send to nextPutAll: we handle the String (or ByteArray) argument as fast as possible - the rest we delegate to putOn: This means that we handle single characters and bytes whereas nextPutAll: is only for sequencable collections. . Note this may not work in every case that nextPutAll: does subject to extensive testing, but it should work in the important cases" | newEnd | collection class == aCollection class ifFalse: [ aCollection putOn: self. ^ self ]. newEnd := position + aCollection size. newEnd > writeLimit ifTrue: [self growTo: newEnd + 10]. collection replaceFrom: position+1 to: newEnd with: aCollection startingAt: 1. position := newEnd. ! ! ----STARTUP----#(14 August 2011 7:18:54 pm) as /Users/smarr/Projects/PhD/IBM/renaissance-image.git/awards-release.image! condenseChanges "Move all the changes onto a compacted sources file." "Smalltalk condenseChanges! ----QUIT----#(14 August 2011 7:19:37 pm) awards-release.image priorSource: 1985396! ----STARTUP----#(15 August 2011 2:33:57 pm) as /Users/smarr/Projects/PhD/IBM/github-master/vm/src/from_squeak/iOS/vm/iPhone/iPhone.image! ----QUIT----#(15 August 2011 2:34:20 pm) iPhone.image priorSource: 1985621! ----STARTUP----#(15 August 2011 2:34:28 pm) as /Users/smarr/Projects/PhD/IBM/github-master/vm/src/from_squeak/iOS/vm/iPhone/iPhone.image! ----QUIT----#(15 August 2011 2:34:50 pm) iPhone.image priorSource: 1985846! ----STARTUP----#(15 August 2011 2:42:33 pm) as /Users/smarr/Projects/PhD/IBM/github-master/vm/src/from_squeak/iOS/vm/iPhone/iPhone.image! "To activate the VM Monitors, enable Sampling in the RVM dashboard to the left" "Our canonical demo is a simulation of birds flying on the screen" [Sly3Boids new run] fork. "To stop them, deactivate Keep SlyBoids Flying in the dashboard to the left" "A brief introduction to Sly" "numbers and squaredNumbers are ensembles, denoted with the % sign. Sending a message to it will cause all members to evaluate the message" numbers := Sly3Ensemble withMembersFrom: {1. 2. 3. 4. 5}. squaredNumbers := numbers squared. "-> %{1. 4. 9. 16. 25. } " RVMOperations coreCount! !RVMMonitor class methodsFor: 'user interface' stamp: 'sm 8/15/2011 14:50' prior: 34661352! dashboard "RVMMonitor dashboard " | topView samplingCheck turboCheck gcButton benchButton subViewCount sampleButton clearSamplesButton forgetButton shuffle56Button shuffle4Button multistripButton systemAspectsButton coreAspectsButton inspectSampleButton testAspectCheck spiderButton bytesUsedsSpiderButton delayTimingCheck recordingOptionsButton allToReadMostlyButton printAllHeapsButton printExecutionTraceButton printStackButton gridButton stripButton scanButton outlierButton locateClassesButton locatorButton locators4Button heartbeat spread56Button runningProcessesButton | topView := RVMStandardSystemView new . topView borderWidth:1. samplingCheck _ RVMCheckBoxView on: self label: 'Sampling' checkState: [self sampling] whenChecked: [self startSampling] whenUnchecked: [self stopSampling] monitor: true. turboCheck _ RVMCheckBoxView on: self label: 'Turbo' checkState: [self turboSampling] whenChecked: [self turboOn] whenUnchecked: [self turboOff] monitor: true. testAspectCheck _ RVMCheckBoxView on: self label: 'Test Aspects' checkState: [self showTestAspects] whenChecked: [self showTestAspects:true] whenUnchecked: [self showTestAspects:false] monitor: true. delayTimingCheck _ RVMCheckBoxView on: self label: 'Short Delay' checkState: [self delayTiming = #short] whenChecked: [self useShortDelay] whenUnchecked: [self useNormalDelay] monitor: true. heartbeat _ RVMCheckBoxView on: self label: 'Heartbeat' checkState: [self showHeartbeat] whenChecked: [self startHeartbeat] whenUnchecked: [self stopHeartbeat] monitor: true. sampleButton _ RVMButtonView label:'Take Sample' action:[RVMMonitor getSample; informListeners]. inspectSampleButton _ RVMButtonView label:'Inspect Sample' action:[Transcript show: 'CoreCount: ', (RVMOperations coreCount) asString . RVMMonitor lastSample inspect]. clearSamplesButton _ RVMButtonView label:'Clear Samples' action:[RVMMonitor clearSamples]. recordingOptionsButton _ RVMButtonView label:'Recording Options' action:[RVMMonitor recordingControls]. forgetButton _ RVMButtonView label:'Forget Listeners' action:[RVMMonitor forgetListeners]. gcButton _ RVMButtonView label:'GC' action:[Transcript cr show:'GC: ',Smalltalk garbageCollect printString]. spread56Button _ RVMButtonView label:'Spread 56' action:[RVMOperations spreadFrom: 0 to: 55 moveRWtoRM: true moveRMtoRW: false]. shuffle56Button _ RVMButtonView label:'Shuffle:56' action:[RVMOperations shuffle:56]. shuffle4Button _ RVMButtonView label:'Shuffle:4' action:[RVMOperations shuffle:4]. allToReadMostlyButton _ RVMButtonView label:'All->readMostly' action:[RVMOperations moveAllToReadMostlyHeaps]. printAllHeapsButton _ RVMButtonView label:'Print BytesUsed' action:[RVMOperations printAllHeapsBytesUsed]. printExecutionTraceButton _ RVMButtonView label:'Print Trace' action:[RVMOperations printExecutionTrace]. printStackButton _ RVMButtonView label:'Print Stack' action:[RVMOperations printStack]. gridButton _ self relAbsButtonLabeled:'Tile Grid...' relAction:[RVMTileGridView example] absAction:[RVMTileGridScalerView example]. stripButton _ self relAbsButtonLabeled:'Tile Strip...' relAction:[RVMTileStripChartView example] absAction:[RVMTileStripChartScalerView example]. scanButton _ self relAbsButtonLabeled:'Tile Scan...' relAction:[RVMScanningStripChartView example] absAction:[RVMAbsScanningStripChartView example]. multistripButton _ RVMButtonView label:'Multi Strip' action:[RVMCoreAspectTrace exampleView1]. systemAspectsButton _ RVMButtonView label:'System Aspects' action:[RVMAspectTrace monitorAllSystemAspects]. coreAspectsButton _ RVMButtonView label:'Core Aspects' action:[RVMCoreAspectTrace monitorAllCoreAspectsForCoreFromUser]. runningProcessesButton _ RVMButtonView label:'Running Processes' action:[RVMAspectTrace exampleView8]. spiderButton _ RVMButtonView label:'Kiviat' action:[RVMMultiKiviatView exampleBytecodesAndProcessesRunning]. bytesUsedsSpiderButton _ RVMButtonView label:'heap size Kiviat' action:[RVMMultiKiviatView exampleBytesUsedTrioCommonPinned]. outlierButton _ RVMButtonView label:'Outlier...' action:[RVMMonitor outlierFromUser]. locateClassesButton _ RVMButtonView label:'Class Locator' action:[RVMGroupLocatorView openOn: Smalltalk objectsSource:#allClasses labeled:'All Classes']. locatorButton _ RVMButtonView label:'Group Locator' action:[RVMGroupLocatorView openWithSourceEditorOn: nil objectsSource:[Array allInstances]]. locators4Button _ RVMButtonView label:'4 Group Locator' action:[RVMMultiGroupLocatorView openOn: nil sources: {[String allInstances]. [Collection withAllSubclasses]. [Object withAllSubclasses]. [View allSubInstances]} colors: nil]. benchButton _ RVMButtonView label:'testCompiler' action:[Cursor wait showWhile:[RVMExperiment testCompiler]]. topView addSubView: samplingCheck. topView addSubView: turboCheck below: samplingCheck. topView addSubView: testAspectCheck below: turboCheck. topView addSubView: delayTimingCheck below: testAspectCheck. topView addSubView: heartbeat below: delayTimingCheck. topView addSubView: sampleButton below: heartbeat. topView addSubView: inspectSampleButton below: sampleButton. topView addSubView: clearSamplesButton below: inspectSampleButton. topView addSubView: recordingOptionsButton below: clearSamplesButton. topView addSubView: forgetButton below: recordingOptionsButton. topView addSubView: gcButton below: forgetButton. topView addSubView: spread56Button below: gcButton. topView addSubView: shuffle56Button below: spread56Button. topView addSubView: shuffle4Button below: shuffle56Button. topView addSubView: allToReadMostlyButton below: shuffle4Button. topView addSubView: printAllHeapsButton below: allToReadMostlyButton. topView addSubView: printExecutionTraceButton below: printAllHeapsButton. topView addSubView: printStackButton below: printExecutionTraceButton. topView addSubView: gridButton below: printStackButton. topView addSubView: stripButton below: gridButton. topView addSubView: scanButton below: stripButton. topView addSubView: multistripButton below: scanButton. topView addSubView: systemAspectsButton below: multistripButton. topView addSubView: coreAspectsButton below: systemAspectsButton. topView addSubView: runningProcessesButton below: coreAspectsButton. topView addSubView: spiderButton below: runningProcessesButton. topView addSubView: bytesUsedsSpiderButton below: spiderButton. topView addSubView: outlierButton below: bytesUsedsSpiderButton. topView addSubView: locateClassesButton below: outlierButton. topView addSubView: locatorButton below: locateClassesButton. topView addSubView: locators4Button below: locatorButton. topView addSubView: benchButton below: locators4Button. topView label: 'RVM'. RVMMonitor forgetAll: topView allSubViews. RVMMonitor forget: topView. subViewCount _ topView subViews size. topView minimumSize: 120@(subViewCount*27). topView maximumSize: topView minimumSize. topView controller open! ! ----QUIT----#(15 August 2011 2:50:42 pm) iPhone.image priorSource: 1986063! ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/macintoshextra.c ================================================ /* * macintoshextra.c * Squeak iPhone * * Created by John M McIntosh on 2/23/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ #include "macintoshextra.h" #include <sys/syslimits.h> int ioFormPrint(int bitsAddr, int width, int height, int depth, double hScale, double vScale, int landscapeFlag) { /* experimental: print a form with the given bitmap, width, height, and depth at the given horizontal and vertical scales in the given orientation However John Mcintosh has introduced a printjob class and plugin to replace this primitive */ #pragma unused( bitsAddr, width, height, depth, hScale, vScale, landscapeFlag) return true; } void *ioFindExternalFunctionIn(char *lookupName, void *moduleHandle) {return 0;} void *ioLoadModule(char *pluginName) {return 0;} sqInt ioFreeModule(void *moduleHandle){return 0;} sqInt ioGetButtonState() {return 0;} sqInt ioGetKeystroke() {return -1;} sqInt ioMousePoint() {return 0;} sqInt ioPeekKeystroke() {return 0;} sqInt ioSetCursor( sqInt cursorBitsIndex, sqInt offsetX, sqInt offsetY) {return 0;} sqInt ioSetCursorWithMask( sqInt cursorBitsIndex, sqInt cursorMaskIndex, sqInt offsetX, sqInt offsetY) {return 0;} sqInt ioSetCursorARGB(sqInt cursorBitsIndex, sqInt extentX, sqInt extentY, sqInt offsetX, sqInt offsetY); sqInt ioSetCursorARGB(sqInt cursorBitsIndex, sqInt extentX, sqInt extentY, sqInt offsetX, sqInt offsetY) {return 0;} /* Retrieve the next input event from the OS. */ sqInt ioSetDisplayMode( sqInt width, sqInt height, sqInt depth, sqInt fullscreenFlag) {return 0;} //int plugInTimeToReturn(void) { // return false; //} int clearProfile(void){return 0;} int dumpProfile(void){return 0;} int startProfiling(void){return 0;} int stopProfiling(void) {return 0;} int plugInNotifyUser(char *msg); int plugInNotifyUser(char *msg) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/macintoshextra.h ================================================ /* * hydramacintoshextra.h * SqueakHydraForCarbon * * Created by John M McIntosh on 2/23/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * */ #include "sq.h" ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/osExports.c ================================================ /* note: this file is only a backward compatible wrapper for the old-style "platform.exports" definitions. If your platform has migrated to the new exports style you may as well insert the exports right here */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include <stdio.h> /* duh ... this is ugly */ #define XFN(export) {"", #export, (void*)export}, #define XFN2(plugin, export) {#plugin, #export, (void*)plugin##_##export} void *os_exports[][3] = { {NULL, NULL, NULL} }; ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/ClipboardExtended/sqMacExtendedClipboard.h ================================================ /* * sqMacExtendedClipboard.h * SqueakClipboardExtendedxcodeproj * * Created by John Sterling Mcintosh on 4/21/06. * Copyright 2006-2010 Corporate Smalltalk Consulting ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" void sqPasteboardClear( void * inPasteboard ); sqInt sqPasteboardGetItemCount ( void *inPasteboard ); sqInt sqPasteboardCopyItemFlavorsitemNumber ( void *inPasteboard, sqInt formatNumber ); void * sqCreateClipboard( void ); void sqPasteboardPutItemFlavordatalengthformatTypeformatLength ( void *inPasteboard, char* inData, sqInt dataLength, char* format, sqInt formatLength); sqInt sqPasteboardCopyItemFlavorDataformatformatLength ( void* inPasteboard, char* format, sqInt formatLength); ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/ClipboardExtended/sqMacExtendedClipboard.m ================================================ /* * sqMacExtendedClipboard.m * SqueakClipboardExtendedxcodeproj * * Created by John Sterling Mcintosh on 4/21/06. * Copyright 2006-2010 Corporate Smalltalk Consulting ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ #include "sqMacExtendedClipboard.h" #import <UIKit/UIKit.h> extern struct VirtualMachine* interpreterProxy; void sqPasteboardClear(void *inPasteboard ) { NSArray *arrayOfTypes = [[NSArray alloc] init]; ((UIPasteboard *) inPasteboard).items = arrayOfTypes; [arrayOfTypes release]; } sqInt sqPasteboardGetItemCount (void *inPasteboard ) { return [((UIPasteboard *)inPasteboard).items count]; } sqInt sqPasteboardCopyItemFlavorsitemNumber ( void *inPasteboard, sqInt formatNumber ) { sqInt formatTypeLength; sqInt flavorCount; flavorCount = [[(UIPasteboard *)inPasteboard pasteboardTypes] count]; if (formatNumber > flavorCount) { return interpreterProxy->nilObject(); } NSString *formatType = [[(UIPasteboard *)inPasteboard pasteboardTypes] objectAtIndex: formatNumber-1]; const char *utf8data = [formatType UTF8String]; formatTypeLength = strlen(utf8data); sqInt outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), formatTypeLength); unsigned char* formatConverted = interpreterProxy->firstIndexableField(outData); memcpy(formatConverted,utf8data,formatTypeLength); return outData; } void * sqCreateClipboard( void ) { return (void*) [UIPasteboard generalPasteboard]; } void sqPasteboardPutItemFlavordatalengthformatTypeformatLength ( void *inPasteboard, char* inData, sqInt dataLength, char* format, sqInt formatLength) { NSString *formatType = [[NSString alloc] initWithBytes: format length: formatLength encoding: NSUTF8StringEncoding]; NSData* data = [[NSData alloc ] initWithBytes: inData length: dataLength]; [(UIPasteboard *)inPasteboard setData: data forPasteboardType: formatType]; [data release]; [formatType release]; } sqInt sqPasteboardCopyItemFlavorDataformatformatLength ( void *inPasteboard, char* format, sqInt formatLength) { NSString *formatType = [[NSString alloc] initWithBytes: format length: formatLength encoding: NSUTF8StringEncoding]; NSData *dataBuffer = [(UIPasteboard *)inPasteboard dataForPasteboardType: formatType]; if (dataBuffer == NULL) { [formatType release]; return interpreterProxy->nilObject(); } sqInt dataLength = [dataBuffer length]; sqInt outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), dataLength ); char *outDataPtr = (char *) interpreterProxy->firstIndexableField(outData); [dataBuffer getBytes: outDataPtr]; [formatType release]; return outData; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/HostWindowPlugin/sqMacHostWindow.c ================================================ /* * sqMacHostWindow.c * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * Copyright Corporate Smalltalk Consulting Ltd 2008. All rights reserved. * July 15th 2005 add logic to flush QD buffers for os-x 10.4 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic May 15th, 2008 IPhone */ /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "sqVirtualMachine.h" #include "sqMacHostWindow.h" #include <stdlib.h> extern struct VirtualMachine *interpreterProxy; sqInt RemoveWindowBlock(windowDescriptorBlock * thisWindow); sqInt createWindowWidthheightoriginXyattrlength(sqInt w,sqInt h,sqInt x,sqInt y, char * list, sqInt listLength) { return -1; } sqInt closeWindow(sqInt windowIndex) { return 1; } sqInt ioPositionOfWindow(wIndexType windowIndex) { if (windowHandleFromIndex(windowIndex) == NULL) return -1; return (0 << 16) | (0 & 0xFFFF); /* left is high 16 bits; top is low 16 bits */ } sqInt ioPositionOfWindowSetxy(wIndexType windowIndex, sqInt x, sqInt y) { return -1; } sqInt ioSizeOfWindow(wIndexType windowIndex) { sqInt w=0, h=0; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } int ioPositionOfNativeDisplay(unsigned long windowHandle) { sqInt w=0, h=0; return (w << 16) | (h & 0xFFFF); /* w is high 16 bits; h is low 16 bits */ } sqInt ioSizeOfWindowSetxy(wIndexType windowIndex, sqInt x, sqInt y) { return (0); /* w is high 16 bits; h is low 16 bits */ } sqInt ioSetTitleOfWindow(sqInt windowIndex, char * newTitle, sqInt sizeOfTitle) { return 1; } sqInt ioCloseAllWindows(void) { return 1; } /* addendum to sqPlatformSpecific.h */ /* multiple host windows stuff */ static windowDescriptorBlock *windowListRoot = NULL; /* end addendum to sqPlatformSpecific.h */ /* simple linked list management code */ /* window list management */ windowDescriptorBlock *windowBlockFromIndex(sqInt windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry; entry = entry->next; } return NULL; } windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry; entry = entry->next; } return NULL; } wHandleType windowHandleFromIndex(sqInt windowIndex) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->windowIndex == windowIndex) return entry->handle; entry = entry->next; } return NULL; } sqInt windowIndexFromHandle(wHandleType windowHandle) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry->handle == windowHandle) return entry->windowIndex; entry = entry->next; } return 0; } sqInt windowIndexFromBlock( windowDescriptorBlock * thisWindow) { windowDescriptorBlock *entry; entry = windowListRoot; while(entry) { if(entry == thisWindow) return entry->windowIndex; entry = entry->next; } return 0; } static sqInt nextIndex = 1; windowDescriptorBlock *AddWindowBlock(void) { /* create a new entry in the linkedlist of windows. * If the calloc fails, return NULL which will then go back to the * prim and fail it cleanly. * Initialize the block to a sensible state */ windowDescriptorBlock *thisWindow; thisWindow = (windowDescriptorBlock*) calloc(1, sizeof(windowDescriptorBlock)); if ( thisWindow == NULL) { return NULL; } thisWindow->next = windowListRoot; thisWindow->windowIndex = nextIndex++; thisWindow->handle = NULL; windowListRoot = thisWindow; return windowListRoot; } /* * RemoveWindowBlock: * Remove the given entry from the list of windows. * free it, if found. */ sqInt RemoveWindowBlock(windowDescriptorBlock * thisWindow) { windowDescriptorBlock *prevEntry; /* Unlink the entry from the module chain */ if(thisWindow == windowListRoot) { windowListRoot = thisWindow->next; } else { prevEntry = windowListRoot; while(prevEntry->next != thisWindow) { prevEntry = prevEntry->next; if (prevEntry == NULL) { return 0; } } prevEntry->next = thisWindow->next; } free(thisWindow); return 1; } sqInt getCurrentIndexInUse(void) { return nextIndex-1; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/HostWindowPlugin/sqMacHostWindow.h ================================================ /* * sqMacHostWindow.h * SqueakVMForCarbon * * Created by John M McIntosh on Tue Jul 20 2004. * 3.8.15b3 Feb 19th, 2007 JMM add cursor set logic Altered for IPhone */ /* Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "HostWindowPlugin.h" #ifdef BUILD_FOR_OSX #include <ApplicationServices/ApplicationServices.h> #else #include <CoreGraphics/CoreGraphics.h> #endif /* window handle type */ #define wHandleType void * #define wIndexType sqInt typedef struct windowDescriptorBlock { struct windowDescriptorBlock * next; wHandleType handle; wIndexType windowIndex; /* extra fields to support your platform needs */ void * context; CGRect updateArea; sqInt width; sqInt height; } windowDescriptorBlock; windowDescriptorBlock *windowBlockFromHandle(wHandleType windowHandle); sqInt windowIndexFromBlock( windowDescriptorBlock * thisWindow); sqInt windowIndexFromHandle(wHandleType windowHandle); wHandleType windowHandleFromIndex(wIndexType windowIndex); windowDescriptorBlock *AddWindowBlock(void); windowDescriptorBlock *windowBlockFromIndex(sqInt windowIndex); sqInt getCurrentIndexInUse(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/SqueakFFIPrims/dummyFFI.c ================================================ // // dummyFFI.m // SqueakNoOGLIPhone // // Created by John M McIntosh on 5/15/08. /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include <stdlib.h> #include "dummyFFI.h" #include "sqFFI.h" int ffiPushSignedByte(int value) { return 1; } int ffiPushUnsignedByte(int value) { return 1; } int ffiPushSignedShort(int value) { return 1; } int ffiPushUnsignedShort(int value) { return 1; } int ffiPushSignedInt(int value) { return 1; } int ffiPushUnsignedInt(int value) { return 1; } # define primitiveFail() 0 int ffiPushSignedLongLong(int low, int high) { return primitiveFail(); } int ffiPushUnsignedLongLong(int low, int high) { return primitiveFail(); } int ffiPushSignedChar(int value) { return 1; } int ffiPushUnsignedChar(int value) { return 1; } int ffiPushBool(int value) { return 1; } int ffiPushSingleFloat(double value) { return 1; } int ffiPushDoubleFloat(double value) { return 1; } /* ffiReturnFloatValue: Return the value from a previous ffi call with float return type. */ double ffiReturnFloatValue(void) { return 0; } /* ffiLongLongResultLow: Return the low 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultLow(void) { return 0; } /* ffiLongLongResultHigh: Return the high 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultHigh(void) { return 0; } /* ffiStoreStructure: Store the structure result of a previous ffi call into the given address*/ int ffiStoreStructure(int address, int structSize) { return 1; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return 0; } int ffiPushStringOfLength(int srcIndex, int length) { return 0; } int ffiAlloc(int byteSize) { return (int)malloc((unsigned) byteSize); } int ffiFree(int ptr) { if (ptr) free((void *)ptr); return 1; } int ffiInitialize(void) { return 1; } int ffiCallAddressOfWithStructReturn(int fn, int callType, int *structSpec, int specSize) { return 0; } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { return 0; } int ffiCanReturn(int *structSpec, int specSize) { return 0; } /* ffiCleanup: Cleanup after a foreign function call has completed. The generic support code only frees the temporarily allocated strings. */ int ffiCleanup(void) { return 0; } /* ffiSupportsCallingConvention: Return true if the support code supports the given calling convention */ int ffiSupportsCallingConvention(int callType) { return 0; } int ffiPushStructureOfLength(int pointer, int* structSpec, int structSize) { return 0; } int ffiPushPointer(int pointer) { return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/plugins/SqueakFFIPrims/dummyFFI.h ================================================ /* * dummyFFI.h * SqueakNoOGLIPhone * * Created by John M McIntosh on 10/24/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqConfig.h ================================================ /* sqConfig.h -- platform identification and configuration */ /* For Apple's OS X */ #define macintoshSqueak 1 # if defined(SQ_CONFIG_DONE) # error configuration conflict # endif # define SQ_CONFIG_DONE #if !defined(SQ_CONFIG_DONE) # error test for, and describe, your architecture here. #endif ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqDummyaio.c ================================================ /* * sqDummyaio.c * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/29/08. */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) * Copyright 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. * * Small parts of this code is * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ #include "sq.h" #include "sqDummyaio.h" int aioPoll(int microSeconds) { return 0; } void aioInit(void) { } /* sleep for microSeconds*/ int aioSleep(int microSeconds) { #if defined(HAVE_NANOSLEEP) if (microSeconds < (1000000/60)) /* < 1 timeslice? */ { int error; struct timespec rqtp= { 0, microSeconds * 1000 }; struct timespec rmtp; error = nanosleep(&rqtp, &rmtp); if (error == -1) { why := errno; } } #endif return 0; } ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqDummyaio.h ================================================ /* * sqDummyaio.h * SqueakNoOGLIPhone * * Created by John M McIntosh on 5/29/08. * */ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ int aioPoll(int microSeconds); void aioInit(void); int aioSleep(int microSeconds); ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqMacV2Memory.c ================================================ /**************************************************************************** * PROJECT: allocate memory from somewhere for the image * FILE: sqMacV2Memory.c * CONTENT: * * AUTHOR: John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: * * NOTES: *****************************************************************************/ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #include "sq.h" #include "sqMacV2Memory.h" #include <sys/mman.h> #include <errno.h> #include <sys/stat.h> #include <unistd.h> extern usqInt gMaxHeapSize; extern int gSqueakUseFileMappedMMAP; static usqInt gHeapSize; static void *startOfmmapForANONMemory,*startOfmmapForImageFile; static size_t fileRoundedUpToPageSize,freeSpaceRoundedUpToPageSize; #if defined(SQ_HOST64) && defined(SQ_IMAGE32) __attribute__ ((visibility("default"))) char * sqMemoryBase=0; #endif /* compute the desired memory allocation */ #if !STACKVM extern usqInt memory; #else usqInt memory; #endif usqInt sqGetAvailableMemory() { #if COGVM return gMaxHeapSize - 25*1024*1024; #else return gMaxHeapSize; #endif } static size_t pageSize; static size_t pageMask; usqInt sqAllocateMemoryMac(usqInt desiredHeapSize, sqInt minHeapSize, FILE * f,usqInt headersize) { void *possibleLocation,*startOfAnonymousMemory; off_t fileSize; struct stat sb; pageSize= getpagesize(); pageMask= ~(pageSize - 1); #define valign(x) ((x) & pageMask) #pragma unused(minHeapSize,desiredHeapSize) possibleLocation = (void*) (500*1024*1024); gHeapSize = gMaxHeapSize; if (desiredHeapSize > gHeapSize) return 0; if (gSqueakUseFileMappedMMAP) { /* Lets see about mmap the image file into a chunk of memory at the 500MB boundary rounding up to the page size Then we on the next page anonymously allocate the required free space for young space*/ /* Thanks to David Pennell for suggesting this */ fstat(fileno((FILE *)f), &sb); fileSize = sb.st_size; fileRoundedUpToPageSize = valign(fileSize+pageSize-1); startOfmmapForImageFile = mmap(possibleLocation, fileRoundedUpToPageSize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE,fileno((FILE *)f), (off_t)0); if (startOfmmapForImageFile != possibleLocation) { /* This isn't a failure case, let's continue and see what happens */ /* Before we would bail, but on 4GB macs with 27 apps running it might not allow 500MB boundary, so let it suggest one and live with it */ possibleLocation = startOfmmapForImageFile; } startOfAnonymousMemory = (void *) ((size_t) fileRoundedUpToPageSize + (size_t) possibleLocation); freeSpaceRoundedUpToPageSize = valign(gMaxHeapSize)-fileRoundedUpToPageSize+pageSize; startOfmmapForANONMemory = mmap(startOfAnonymousMemory, freeSpaceRoundedUpToPageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,0,(off_t)0); if (startOfmmapForANONMemory != startOfAnonymousMemory) { fprintf(stderr, "errno %d\n", errno); perror("startOfmmapForANONMemory failed"); exit(42); } #if defined(SQ_HOST64) && defined(SQ_IMAGE32) sqMemoryBase= (char*)startOfmmapForImageFile+headersize; return 0; #else return (usqInt) (char*)startOfmmapForImageFile+headersize; #endif } else { void * debug, *actually; debug = mmap( possibleLocation, gMaxHeapSize+pageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,-1,0); if(debug == MAP_FAILED) { fprintf(stderr, "errno %d\n", errno); perror("mmap failed"); exit(42); } actually = (char*) debug+pageSize-1; actually = (void*) (((size_t) actually) & pageMask); #if defined(SQ_HOST64) && defined(SQ_IMAGE32) sqMemoryBase= actually; return 0; #else return memory = (usqInt) actually; #endif } } sqInt sqGrowMemoryBy(sqInt memoryLimit, sqInt delta) { if ((usqInt) memoryLimit + (usqInt) delta - (usqInt) memory > gMaxHeapSize) return memoryLimit; gHeapSize += delta; return memoryLimit + delta; } sqInt sqShrinkMemoryBy(sqInt memoryLimit, sqInt delta) { return sqGrowMemoryBy(memoryLimit,0-delta); } sqInt sqMemoryExtraBytesLeft(sqInt includingSwap) { return gMaxHeapSize - gHeapSize; } void sqMacMemoryFree() { if (gSqueakUseFileMappedMMAP) { munmap(startOfmmapForImageFile,fileRoundedUpToPageSize); munmap(startOfmmapForANONMemory,freeSpaceRoundedUpToPageSize); } } #ifdef BUILD_FOR_OSX size_t sqImageFileReadEntireImage(void *ptr, size_t elementSize, size_t count, sqImageFile f) { if (gSqueakUseFileMappedMMAP) return count; return sqImageFileRead(ptr, elementSize, count, f); } #endif #if COGVM # define roundDownToPageBoundary(v) ((v)&pageMask) # define roundUpToPageBoundary(v) (((v)+pageSize-1)&pageMask) void sqMakeMemoryExecutableFromTo(unsigned long startAddr, unsigned long endAddr) { unsigned long firstPage = roundDownToPageBoundary(startAddr); if (mprotect((void *)firstPage, roundUpToPageBoundary(endAddr - firstPage), PROT_READ | PROT_WRITE | PROT_EXEC) < 0) perror("mprotect(x,y,PROT_READ | PROT_WRITE | PROT_EXEC)"); } void sqMakeMemoryNotExecutableFromTo(unsigned long startAddr, unsigned long endAddr) { unsigned long firstPage = roundDownToPageBoundary(startAddr); if (mprotect((void *)firstPage, roundUpToPageBoundary(endAddr - firstPage), PROT_READ | PROT_WRITE) < 0) perror("mprotect(x,y,PROT_READ | PROT_WRITE)"); } #endif /* COGVM */ ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqMacV2Memory.h ================================================ /**************************************************************************** * PROJECT: Squeak Headers * FILE: sqMacV2Memory.h * CONTENT: * * AUTHOR: John McIntosh. * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: * * NOTES: ****************************************************************************/ /* Some of this code was funded via a grant from the European Smalltalk User Group (ESUG) Copyright (c) 2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */// usqInt sqGetAvailableMemory(void); void sqMacMemoryFree(void); ================================================ FILE: vm/src/from_squeak/iOS/vm/iPhone/sqPlatformSpecific.h ================================================ /**************************************************************************** * PROJECT: Platform-specific prototypes and definitions for the iPhone * FILE: sqPlatformSpecific.h * CONTENT: * * AUTHOR: John McIntosh * ADDRESS: * EMAIL: johnmci@smalltalkconsulting.com * RCSID: How to use this file: This file is for general platform-specific macros and declarations. Function prototypes that are unlikely to introduce name conflicts on other platforms can be added directly. Macro re-definitions or conflicting function prototypes can be wrapped in a #ifdefs. Alternatively, a customized version of this file can be used on that platform. The goal is to keep all the other header files generic across platforms. To override a definition or macro from sq.h, you must first #undef it, then provide the new definition. Define plugin for Netscape Plugin building, needed for CodeWarrior */ /* Copyright (c) 2000-2008 Corporate Smalltalk Consulting Ltd. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by Corporate Smalltalk Consulting Ltd (http://www.smalltalkconsulting.com) and its contributors", in the same place and form as other third-party acknowledgments. Alternately, this acknowledgment may appear in the software itself, in the same form and location as other such third-party acknowledgments. */ // #ifdef macintoshSqueak //#define SQUEAK_BUILTIN_PLUGIN #define ENABLE_URL_FETCH /* replace the image file manipulation macros with functions */ #undef sqAllocateMemory //64bit function pointers undef #undef dispatchFunctionPointer #undef dispatchFunctionPointerOnin #undef squeakFileOffsetType #define squeakFileOffsetType off_t #include <unistd.h> #undef sqFTruncate #define sqFTruncate(f,o) ftruncate(fileno(f), o) #define ftell ftello #define fseek fseeko //int ftruncate(int, off_t); #undef sqFilenameFromStringOpen #undef sqFilenameFromString void sqFilenameFromStringOpen(char *buffer,sqInt fileIndex, long fileLength); void sqFilenameFromString(char *buffer,sqInt fileIndex, long fileLength); #undef allocateMemoryMinimumImageFileHeaderSize #undef sqImageFileReadEntireImage usqInt sqAllocateMemoryMac(usqInt desiredHeapSize,sqInt minHeapSize, FILE * f,usqInt headersize); #define allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, fileStream, headerSize) \ sqAllocateMemoryMac(heapSize, minimumMemory, fileStream, headerSize) #ifdef BUILD_FOR_OSX size_t sqImageFileReadEntireImage(void *ptr, size_t elementSize, size_t count, FILE * f); #define sqImageFileReadEntireImage(memoryAddress, elementSize, length, fileStream) \ sqImageFileReadEntireImage(memoryAddress, elementSize, length, fileStream) #else #define sqImageFileReadEntireImage(memoryAddress, elementSize, length, fileStream) length #endif #undef ioMSecs #define ioUtcWithOffset ioUtcWithOffset /* macro to return from interpret() loop in browser plugin VM */ #define ReturnFromInterpret() return 0 /* undef the memory routines for our logic */ #undef sqGrowMemoryBy #undef sqShrinkMemoryBy #undef sqMemoryExtraBytesLeft sqInt sqGrowMemoryBy(sqInt memoryLimit, sqInt delta); sqInt sqShrinkMemoryBy(sqInt memoryLimit, sqInt delta); sqInt sqMemoryExtraBytesLeft(sqInt includingSwap); #undef insufficientMemorySpecifiedError #undef insufficientMemoryAvailableError #undef unableToReadImageError int plugInNotifyUser(char *msg); #define insufficientMemorySpecifiedError() plugInNotifyUser("The amount of memory specified by the Setting Slider is not enough for the installed Squeak image file.") #define insufficientMemoryAvailableError() plugInNotifyUser("There is not enough memory to give Squeak the amount specified by the Setting Slider") #define unableToReadImageError() plugInNotifyUser("Read failed or premature end of image file") #undef browserPluginReturnIfNeeded int plugInTimeToReturn(void); #define browserPluginReturnIfNeeded() if (plugInTimeToReturn()) {ReturnFromInterpret();} sqInt ioSetCursorARGB(sqInt cursorBitsIndex, sqInt extentX, sqInt extentY, sqInt offsetX, sqInt offsetY); #if COGVM extern void sqMakeMemoryExecutableFromTo(unsigned long, unsigned long); extern void sqMakeMemoryNotExecutableFromTo(unsigned long, unsigned long); extern int isCFramePointerInUse(void); #endif /* Thread support for thread-safe signalSemaphoreWithIndex and/or the COGMTVM */ #if STACKVM # define sqLowLevelYield() sched_yield() # include <pthread.h> # define sqOSThread pthread_t /* these are used both in the STACKVM & the COGMTVM */ # define ioOSThreadsEqual(a,b) pthread_equal(a,b) # define ioCurrentOSThread() pthread_self() # if COGMTVM /* Please read the comment for CogThreadManager in the VMMaker package for * documentation of this API. */ typedef struct { pthread_cond_t cond; pthread_mutex_t mutex; int count; } sqOSSemaphore; # define ioDestroyOSSemaphore(ptr) 0 # if !ForCOGMTVMImplementation /* this is a read-only export */ extern const pthread_key_t tltiIndex; # endif # define ioGetThreadLocalThreadIndex() ((long)pthread_getspecific(tltiIndex)) # define ioSetThreadLocalThreadIndex(v) (pthread_setspecific(tltiIndex,(void*)(v))) # define ioOSThreadIsAlive(thread) (pthread_kill(thread,0) == 0) # define ioTransferTimeslice() sched_yield() # define ioMilliSleep(ms) usleep((ms) * 1000) # endif /* COGMTVM */ #endif /* STACKVM */ // From Joshua Gargus, for XCode 3.1 #ifdef __GNUC__ # undef EXPORT # define EXPORT(returnType) __attribute__((visibility("default"))) returnType //# define VM_LABEL(foo) asmXXX("\n.globl L" #foo "\nL" #foo ":") # define VM_LABEL(foo) #endif #if !defined(VM_LABEL) || COGVM # undef VM_LABEL # define VM_LABEL(foo) 0 #endif #endif /* macintoshSqueak */ ================================================ FILE: vm/src/from_squeak/iOS/vm/sqGnu.h ================================================ /* Definitions for "gnuified" interp.c * * Copyright (C) 1996 1997 1998 1999 2000 2001 Ian Piumarta and individual * authors/contributors listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. This notice may not be removed or altered in any source distribution. * * Using or modifying this file for use in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the base * of the distribution before proceeding with any such use. * * You are STRONGLY DISCOURAGED from distributing a modified version of * this file under its original name without permission. If you must * change it, rename it first. */ /* Author: Ian.Piumarta@inria.fr * * Last edited: Fri Aug 11 08:20:28 2000 by piumarta (Ian Piumarta) on emilia * April 17th, 2002, John M McIntosh use jumptable register logic for PPC * Feb 23rd, 2006, John M McIntosh watch usage of __Apple__ also Ian's changes for GCC i386 * December 10th 2008, Eliot Miranda, updated with FP_REG and use of GIV() for * the global struct. * * NOTES: * this file is #included IN PLACE OF sq.h */ #include "sq.h" #define CASE(N) case N: _##N: #if defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__) # define JUMP_TABLE_PTR ; register void **jumpTableP JP_REG; jumpTableP= &jumpTable[0] # define BREAK goto *jumpTableP[currentBytecode] #else # define JUMP_TABLE_PTR # define BREAK goto *jumpTable[currentBytecode] #endif #if defined(SQ_USE_GLOBAL_STRUCT) # define PRIM_DISPATCH goto *jumpTable[GIV(primitiveIndex)] #else # define PRIM_DISPATCH goto *jumpTable[primitiveIndex] #endif #define JUMP_TABLE \ static void *jumpTable[256]= { \ &&_0, &&_1, &&_2, &&_3, &&_4, &&_5, &&_6, &&_7, &&_8, &&_9, \ &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, \ &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, \ &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, \ &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, \ &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, \ &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, \ &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, \ &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, \ &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, \ &&_100, &&_101, &&_102, &&_103, &&_104, &&_105, &&_106, &&_107, &&_108, &&_109, \ &&_110, &&_111, &&_112, &&_113, &&_114, &&_115, &&_116, &&_117, &&_118, &&_119, \ &&_120, &&_121, &&_122, &&_123, &&_124, &&_125, &&_126, &&_127, &&_128, &&_129, \ &&_130, &&_131, &&_132, &&_133, &&_134, &&_135, &&_136, &&_137, &&_138, &&_139, \ &&_140, &&_141, &&_142, &&_143, &&_144, &&_145, &&_146, &&_147, &&_148, &&_149, \ &&_150, &&_151, &&_152, &&_153, &&_154, &&_155, &&_156, &&_157, &&_158, &&_159, \ &&_160, &&_161, &&_162, &&_163, &&_164, &&_165, &&_166, &&_167, &&_168, &&_169, \ &&_170, &&_171, &&_172, &&_173, &&_174, &&_175, &&_176, &&_177, &&_178, &&_179, \ &&_180, &&_181, &&_182, &&_183, &&_184, &&_185, &&_186, &&_187, &&_188, &&_189, \ &&_190, &&_191, &&_192, &&_193, &&_194, &&_195, &&_196, &&_197, &&_198, &&_199, \ &&_200, &&_201, &&_202, &&_203, &&_204, &&_205, &&_206, &&_207, &&_208, &&_209, \ &&_210, &&_211, &&_212, &&_213, &&_214, &&_215, &&_216, &&_217, &&_218, &&_219, \ &&_220, &&_221, &&_222, &&_223, &&_224, &&_225, &&_226, &&_227, &&_228, &&_229, \ &&_230, &&_231, &&_232, &&_233, &&_234, &&_235, &&_236, &&_237, &&_238, &&_239, \ &&_240, &&_241, &&_242, &&_243, &&_244, &&_245, &&_246, &&_247, &&_248, &&_249, \ &&_250, &&_251, &&_252, &&_253, &&_254, &&_255 \ } JUMP_TABLE_PTR #define PRIM_TABLE \ static void *jumpTable[700]= { \ &&_0, &&_1, &&_2, &&_3, &&_4, &&_5, &&_6, &&_7, &&_8, &&_9, \ &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, \ &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, \ &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, \ &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, \ &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, \ &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, \ &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, \ &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, \ &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, \ &&_100, &&_101, &&_102, &&_103, &&_104, &&_105, &&_106, &&_107, &&_108, &&_109, \ &&_110, &&_111, &&_112, &&_113, &&_114, &&_115, &&_116, &&_117, &&_118, &&_119, \ &&_120, &&_121, &&_122, &&_123, &&_124, &&_125, &&_126, &&_127, &&_128, &&_129, \ &&_130, &&_131, &&_132, &&_133, &&_134, &&_135, &&_136, &&_137, &&_138, &&_139, \ &&_140, &&_141, &&_142, &&_143, &&_144, &&_145, &&_146, &&_147, &&_148, &&_149, \ &&_150, &&_151, &&_152, &&_153, &&_154, &&_155, &&_156, &&_157, &&_158, &&_159, \ &&_160, &&_161, &&_162, &&_163, &&_164, &&_165, &&_166, &&_167, &&_168, &&_169, \ &&_170, &&_171, &&_172, &&_173, &&_174, &&_175, &&_176, &&_177, &&_178, &&_179, \ &&_180, &&_181, &&_182, &&_183, &&_184, &&_185, &&_186, &&_187, &&_188, &&_189, \ &&_190, &&_191, &&_192, &&_193, &&_194, &&_195, &&_196, &&_197, &&_198, &&_199, \ &&_200, &&_201, &&_202, &&_203, &&_204, &&_205, &&_206, &&_207, &&_208, &&_209, \ &&_210, &&_211, &&_212, &&_213, &&_214, &&_215, &&_216, &&_217, &&_218, &&_219, \ &&_220, &&_221, &&_222, &&_223, &&_224, &&_225, &&_226, &&_227, &&_228, &&_229, \ &&_230, &&_231, &&_232, &&_233, &&_234, &&_235, &&_236, &&_237, &&_238, &&_239, \ &&_240, &&_241, &&_242, &&_243, &&_244, &&_245, &&_246, &&_247, &&_248, &&_249, \ &&_250, &&_251, &&_252, &&_253, &&_254, &&_255, &&_256, &&_257, &&_258, &&_259, \ &&_260, &&_261, &&_262, &&_263, &&_264, &&_265, &&_266, &&_267, &&_268, &&_269, \ &&_270, &&_271, &&_272, &&_273, &&_274, &&_275, &&_276, &&_277, &&_278, &&_279, \ &&_280, &&_281, &&_282, &&_283, &&_284, &&_285, &&_286, &&_287, &&_288, &&_289, \ &&_290, &&_291, &&_292, &&_293, &&_294, &&_295, &&_296, &&_297, &&_298, &&_299, \ &&_300, &&_301, &&_302, &&_303, &&_304, &&_305, &&_306, &&_307, &&_308, &&_309, \ &&_310, &&_311, &&_312, &&_313, &&_314, &&_315, &&_316, &&_317, &&_318, &&_319, \ &&_320, &&_321, &&_322, &&_323, &&_324, &&_325, &&_326, &&_327, &&_328, &&_329, \ &&_330, &&_331, &&_332, &&_333, &&_334, &&_335, &&_336, &&_337, &&_338, &&_339, \ &&_340, &&_341, &&_342, &&_343, &&_344, &&_345, &&_346, &&_347, &&_348, &&_349, \ &&_350, &&_351, &&_352, &&_353, &&_354, &&_355, &&_356, &&_357, &&_358, &&_359, \ &&_360, &&_361, &&_362, &&_363, &&_364, &&_365, &&_366, &&_367, &&_368, &&_369, \ &&_370, &&_371, &&_372, &&_373, &&_374, &&_375, &&_376, &&_377, &&_378, &&_379, \ &&_380, &&_381, &&_382, &&_383, &&_384, &&_385, &&_386, &&_387, &&_388, &&_389, \ &&_390, &&_391, &&_392, &&_393, &&_394, &&_395, &&_396, &&_397, &&_398, &&_399, \ &&_400, &&_401, &&_402, &&_403, &&_404, &&_405, &&_406, &&_407, &&_408, &&_409, \ &&_410, &&_411, &&_412, &&_413, &&_414, &&_415, &&_416, &&_417, &&_418, &&_419, \ &&_420, &&_421, &&_422, &&_423, &&_424, &&_425, &&_426, &&_427, &&_428, &&_429, \ &&_430, &&_431, &&_432, &&_433, &&_434, &&_435, &&_436, &&_437, &&_438, &&_439, \ &&_440, &&_441, &&_442, &&_443, &&_444, &&_445, &&_446, &&_447, &&_448, &&_449, \ &&_450, &&_451, &&_452, &&_453, &&_454, &&_455, &&_456, &&_457, &&_458, &&_459, \ &&_460, &&_461, &&_462, &&_463, &&_464, &&_465, &&_466, &&_467, &&_468, &&_469, \ &&_470, &&_471, &&_472, &&_473, &&_474, &&_475, &&_476, &&_477, &&_478, &&_479, \ &&_480, &&_481, &&_482, &&_483, &&_484, &&_485, &&_486, &&_487, &&_488, &&_489, \ &&_490, &&_491, &&_492, &&_493, &&_494, &&_495, &&_496, &&_497, &&_498, &&_499, \ &&_500, &&_501, &&_502, &&_503, &&_504, &&_505, &&_506, &&_507, &&_508, &&_509, \ &&_510, &&_511, &&_512, &&_513, &&_514, &&_515, &&_516, &&_517, &&_518, &&_519, \ &&_520, &&_521, &&_522, &&_523, &&_524, &&_525, &&_526, &&_527, &&_528, &&_529, \ &&_530, &&_531, &&_532, &&_533, &&_534, &&_535, &&_536, &&_537, &&_538, &&_539, \ &&_540, &&_541, &&_542, &&_543, &&_544, &&_545, &&_546, &&_547, &&_548, &&_549, \ &&_550, &&_551, &&_552, &&_553, &&_554, &&_555, &&_556, &&_557, &&_558, &&_559, \ &&_560, &&_561, &&_562, &&_563, &&_564, &&_565, &&_566, &&_567, &&_568, &&_569, \ &&_570, &&_571, &&_572, &&_573, &&_574, &&_575, &&_576, &&_577, &&_578, &&_579, \ &&_580, &&_581, &&_582, &&_583, &&_584, &&_585, &&_586, &&_587, &&_588, &&_589, \ &&_590, &&_591, &&_592, &&_593, &&_594, &&_595, &&_596, &&_597, &&_598, &&_599, \ &&_600, &&_601, &&_602, &&_603, &&_604, &&_605, &&_606, &&_607, &&_608, &&_609, \ &&_610, &&_611, &&_612, &&_613, &&_614, &&_615, &&_616, &&_617, &&_618, &&_619, \ &&_620, &&_621, &&_622, &&_623, &&_624, &&_625, &&_626, &&_627, &&_628, &&_629, \ &&_630, &&_631, &&_632, &&_633, &&_634, &&_635, &&_636, &&_637, &&_638, &&_639, \ &&_640, &&_641, &&_642, &&_643, &&_644, &&_645, &&_646, &&_647, &&_648, &&_649, \ &&_650, &&_651, &&_652, &&_653, &&_654, &&_655, &&_656, &&_657, &&_658, &&_659, \ &&_660, &&_661, &&_662, &&_663, &&_664, &&_665, &&_666, &&_667, &&_668, &&_669, \ &&_670, &&_671, &&_672, &&_673, &&_674, &&_675, &&_676, &&_677, &&_678, &&_679, \ &&_680, &&_681, &&_682, &&_683, &&_684, &&_685, &&_686, &&_687, &&_688, &&_689, \ &&_690, &&_691, &&_692, &&_693, &&_694, &&_695, &&_696, &&_697, &&_698, &&_699, \ } /* IP_REG, SP_REG, CB_REG the machine registers in which to place localIP, localFP, localSP and currentBytecode. Wins big on register-deficient architectures -- especially Intel. */ #if defined(__mips__) # define IP_REG __asm__("$16") # define SP_REG __asm__("$17") # define CB_REG __asm__("$18") #endif #if defined(__sparc__) # define IP_REG __asm__("%l0") # define SP_REG __asm__("%l1") # define CB_REG __asm__("%l2") #endif #if defined(__alpha__) # define IP_REG __asm__("$9") # define SP_REG __asm__("$10") # define CB_REG __asm__("$11") #endif #if defined(__i386__) # define IP_REG __asm__("%esi") # define SP_REG __asm__("%edi") # if (__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) # define CB_REG __asm__("%ebx") # else # define CB_REG /* avoid undue register pressure */ # endif #endif #if defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__) # define GP_REG __asm__("24") # define JP_REG __asm__("25") # define IP_REG __asm__("26") # define SP_REG __asm__("27") # define CB_REG __asm__("28") #endif #if defined(__hppa__) # define IP_REG __asm__("%r18") # define SP_REG __asm__("%r17") # define CB_REG __asm__("%r16") #endif #if defined(__mc68000__) # define IP_REG __asm__("a5") # define SP_REG __asm__("a4") # define CB_REG __asm__("d7") #endif #if !defined(JP_REG) # define JP_REG #endif #ifndef IP_REG # define IP_REG #endif #if !defined(SP_REG) # define SP_REG #endif #if !defined(CB_REG) # define CB_REG #endif #if !defined(GP_REG) # define GP_REG #endif #if !defined(FOO_REG) # define FOO_REG /* nada */ #endif #if !defined(FP_REG) # define FP_REG /* nada */ #endif ================================================ FILE: vm/src/from_squeak/iOS/vm/src/plugins/LocalePlugin/LocalePlugin.c ================================================ /* Automatically generated from Squeak on #(17 November 2008 5:58:31 pm) by VMMaker 3.9.1-dtl */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "LocalePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt msg(char * s); #pragma export on EXPORT(sqInt) primitiveCountry(void); EXPORT(sqInt) primitiveCurrencyNotation(void); EXPORT(sqInt) primitiveCurrencySymbol(void); EXPORT(sqInt) primitiveDaylightSavings(void); EXPORT(sqInt) primitiveDecimalSymbol(void); EXPORT(sqInt) primitiveDigitGroupingSymbol(void); EXPORT(sqInt) primitiveLanguage(void); EXPORT(sqInt) primitiveLongDateFormat(void); EXPORT(sqInt) primitiveMeasurementMetric(void); EXPORT(sqInt) primitiveShortDateFormat(void); EXPORT(sqInt) primitiveTimeFormat(void); EXPORT(sqInt) primitiveTimezoneOffset(void); EXPORT(sqInt) primitiveVMOffsetToUTC(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "LocalePlugin 17 November 2008 (i)" #else "LocalePlugin 17 November 2008 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { return sqLocInitialize(); } static sqInt msg(char * s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* return a 3 char string describing the country in use. ISO 3166 is the relevant source here; see http://www.unicode.org/onlinedat/countries.html for details. Using the 3 character Alpha-3 codes */ EXPORT(sqInt) primitiveCountry(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 3); sqLocGetCountryInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying whether the currency symbol is pre or post fix. true -> pre */ EXPORT(sqInt) primitiveCurrencyNotation(void) { sqInt _return_value; _return_value = ((sqLocCurrencyNotation())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a string describing the currency symbol used Still need to find details on standard symbols - ISO 4217 is supposed to be it but cannot find on web */ EXPORT(sqInt) primitiveCurrencySymbol(void) { sqInt oop; sqInt length; length = sqLocCurrencySymbolSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetCurrencySymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying the DST setting. true -> active */ EXPORT(sqInt) primitiveDaylightSavings(void) { sqInt _return_value; _return_value = ((sqLocDaylightSavings())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a 1 char string describing the decimal symbol used - usually a . or a , */ EXPORT(sqInt) primitiveDecimalSymbol(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 1); sqLocGetDecimalSymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a 1 char string describing the digitGrouping symbol used - usually a . or a , between triples of digits */ EXPORT(sqInt) primitiveDigitGroupingSymbol(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 1); sqLocGetDigitGroupingSymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a 3 char string describing the language in use. ISO 639 is the relevant source here; see http://www.w3.org/WAI/ER/IG/ert/iso639.html for details */ EXPORT(sqInt) primitiveLanguage(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 3); sqLocGetLanguageInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a string describing the long date formatting. Format is made up of d day, m month, y year, double symbol is null padded, single not padded (m=6, mm=06) dddd weekday mmmm month name */ EXPORT(sqInt) primitiveLongDateFormat(void) { sqInt oop; sqInt length; length = sqLocLongDateFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetLongDateFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying whether the currency symbol is pre or post fix. true -> pre */ EXPORT(sqInt) primitiveMeasurementMetric(void) { sqInt _return_value; _return_value = ((sqLocMeasurementMetric())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a string describing the long date formatting. Format is made up of d day, m month, y year, double symbol is null padded, single not padded (m=6, mm=06) dddd weekday mmmm month name */ EXPORT(sqInt) primitiveShortDateFormat(void) { sqInt oop; sqInt length; length = sqLocShortDateFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetShortDateFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a string describing the time formatting. Format is made up of h hour (h 12, H 24), m minute, s seconds, x (am/pm String) double symbol is null padded, single not padded (h=6, hh=06) */ EXPORT(sqInt) primitiveTimeFormat(void) { sqInt oop; sqInt length; length = sqLocTimeFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetTimeFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return the number of minutes this VM's time value is offset from UTC */ EXPORT(sqInt) primitiveTimezoneOffset(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sqLocGetTimezoneOffset())); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return the number of minutes this VM's time value is offset from UTC */ EXPORT(sqInt) primitiveVMOffsetToUTC(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sqLocGetVMOffsetToUTC())); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* LocalePlugin_exports[][3] = { {"LocalePlugin", "primitiveDecimalSymbol", (void*)primitiveDecimalSymbol}, {"LocalePlugin", "primitiveMeasurementMetric", (void*)primitiveMeasurementMetric}, {"LocalePlugin", "primitiveDigitGroupingSymbol", (void*)primitiveDigitGroupingSymbol}, {"LocalePlugin", "primitiveCountry", (void*)primitiveCountry}, {"LocalePlugin", "primitiveVMOffsetToUTC", (void*)primitiveVMOffsetToUTC}, {"LocalePlugin", "primitiveCurrencyNotation", (void*)primitiveCurrencyNotation}, {"LocalePlugin", "initialiseModule", (void*)initialiseModule}, {"LocalePlugin", "primitiveCurrencySymbol", (void*)primitiveCurrencySymbol}, {"LocalePlugin", "primitiveTimezoneOffset", (void*)primitiveTimezoneOffset}, {"LocalePlugin", "primitiveLongDateFormat", (void*)primitiveLongDateFormat}, {"LocalePlugin", "primitiveDaylightSavings", (void*)primitiveDaylightSavings}, {"LocalePlugin", "primitiveLanguage", (void*)primitiveLanguage}, {"LocalePlugin", "getModuleName", (void*)getModuleName}, {"LocalePlugin", "primitiveShortDateFormat", (void*)primitiveShortDateFormat}, {"LocalePlugin", "primitiveTimeFormat", (void*)primitiveTimeFormat}, {"LocalePlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/iOS/vm/src/plugins.int ================================================ # Automatically generated makefile include for internal plugins INTERNAL_PLUGINS = ADPCMCodecPlugin B3DAcceleratorPlugin Squeak3D B2DPlugin BitBltPlugin BMPReadWriterPlugin ZipPlugin DropPlugin DSAPrims FFTPlugin FilePlugin FloatArrayPlugin GeniePlugin HostWindowPlugin InternetConfigPlugin JPEGReaderPlugin JPEGReadWriter2Plugin Klatt LargeIntegers Matrix2x3Plugin MIDIPlugin MiscPrimitivePlugin RePlugin SecurityPlugin SocketPlugin SoundCodecPrims SoundGenerationPlugin SoundPlugin StarSqueakPlugin SurfacePlugin UUIDPlugin ================================================ FILE: vm/src/from_squeak/iOS/vm/src/vm/interp.c ================================================ /* This file has been post-processed for GNU C */ /* Automatically generated from Squeak on 8 July 2010 12:32:36 pm by VMMaker 4.2.6 */ #define SQ_USE_GLOBAL_STRUCT 1 #include "sqGnu.h" #include <setjmp.h> #ifndef allocateMemoryMinimumImageFileHeaderSize /* Called by Interpreter>>allocateMemory:minimum:imageFile:headerSize: */ /* Default definition if not previously defined in config.h */ #define allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, fileStream, headerSize) \ sqAllocateMemory(minimumMemory, heapSize) #endif #ifndef sqImageFileReadEntireImage /* Called by Interpreter>>sqImage:read:size:length: */ /* Default definition if not previously defined in config.h */ #define sqImageFileReadEntireImage(memoryAddress, elementSize, length, fileStream) \ sqImageFileRead(memoryAddress, elementSize, length, fileStream) #endif #ifndef error /* error() function called from Interpreter */ /* Default definition if not previously defined in config.h */ #define error(str) defaultErrorProc(str) #endif #ifndef ioMicroSecondClock /* Called by Interpreter>>primitiveMicrosecondClock and GC methods */ /* Default definition if not previously defined in config.h */ #define ioMicroSecondClock ioMSecs #endif #ifndef ioUtcWithOffset /* Called by Interpreter>>primitiveUtcWithOffset */ /* Default definition if not previously defined in config.h */ #define ioUtcWithOffset(clock, offset) setMicroSecondsandOffset(clock, offset) #endif #include "sqMemoryAccess.h" sqInt printCallStack(void); void defaultErrorProc(char *s) { /* Print an error message and exit. */ static sqInt printingStack = false; printf("\n%s\n\n", s); if (!printingStack) { /* flag prevents recursive error when trying to print a broken stack */ printingStack = true; printCallStack(); } exit(-1); } /*** Constants ***/ #define ActiveProcessIndex 1 #define AtCacheFixedFields 4 #define AtCacheFmt 3 #define AtCacheMask 28 #define AtCacheOop 1 #define AtCacheSize 2 #define AtCacheTotalSize 64 #define AtPutBase 32 #define BlockArgumentCountIndex 3 #define Byte0Mask 255 #define Byte1Mask 65280 #define Byte1Shift 8 #define Byte1ShiftNegated -8 #define Byte2Mask 16711680 #define Byte3Mask 4278190080U #define Byte3Shift 24 #define Byte3ShiftNegated -24 #define Byte4Mask 1095216660480U #define Byte4Shift 32 #define Byte4ShiftNegated -32 #define Byte5Mask 280375465082880U #define Byte5Shift 40 #define Byte5ShiftNegated -40 #define Byte6Mask 71776119061217280U #define Byte7Mask 18374686479671623680U #define Byte7Shift 56 #define Byte7ShiftNegated -56 #define Bytes3to0Mask 4294967295U #define Bytes7to4Mask 18446744069414584320U #define CacheProbeMax 3 #define CallerIndex 0 #define CharacterTable 24 #define CharacterValueIndex 0 #define ClassAlien 52 #define ClassArray 7 #define ClassBitmap 4 #define ClassBlockClosure 36 #define ClassBlockContext 11 #define ClassByteArray 26 #define ClassCharacter 19 #define ClassExternalAddress 43 #define ClassExternalData 45 #define ClassExternalFunction 46 #define ClassExternalLibrary 47 #define ClassExternalStructure 44 #define ClassFloat 9 #define ClassInteger 5 #define ClassLargeNegativeInteger 42 #define ClassLargePositiveInteger 13 #define ClassMessage 15 #define ClassMethodContext 10 #define ClassPoint 12 #define ClassSemaphore 18 #define ClassString 6 #define ClassUnsafeAlien 54 #define ClassWeakFinalizer 55 #define ClosureFirstCopiedValueIndex 3 #define ClosureIndex 4 #define ClosureNumArgsIndex 2 #define ClosureOuterContextIndex 0 #define ClosureStartPCIndex 1 #define CompactClassMask 126976 #define CompactClasses 28 #define ConstMinusOne -1 #define ConstOne 3 #define ConstTwo 5 #define ConstZero 1 #define ContextFixedSizePlusHeader 7 #define CrossedX 258 #define CtxtTempFrameStart 6 #define DoAssertionChecks 0 #define DoBalanceChecks 0 #define Done 4 #define EndOfRun 257 #define ExcessSignalsIndex 2 #define ExternalObjectsArray 38 #define ExtraRootSize 2048 #define FalseObject 1 #define FirstLinkIndex 0 #define GCTopMarker 3 #define HashBits 536739840 #define HashBitsOffset 17 #define HeaderIndex 0 #define HeaderTypeClass 1 #define HeaderTypeFree 2 #define HeaderTypeGC 2 #define HeaderTypeShort 3 #define HeaderTypeSizeAndClass 0 #define HomeIndex 5 #define InitialIPIndex 4 #define InstanceSpecificationIndex 2 #define InstructionPointerIndex 1 #define InterpreterSourceVersion "4.2.6" #define InvokeCallbackSelector 53 #define LargeContextBit 262144 #define LastLinkIndex 1 #define LiteralStart 1 #define MaxExternalPrimitiveTableSize 4096 #define MaxJumpBuf 32 #define MaxPrimitiveIndex 575 #define MessageArgumentsIndex 1 #define MessageDictionaryIndex 1 #define MessageLookupClassIndex 2 #define MessageSelectorIndex 0 #define MethodArrayIndex 1 #define MethodCacheClass 2 #define MethodCacheEntries 512 #define MethodCacheEntrySize 8 #define MethodCacheMask 4088 #define MethodCacheMethod 3 #define MethodCacheNative 5 #define MethodCachePrim 4 #define MethodCachePrimFunction 6 #define MethodCacheSelector 1 #define MethodCacheSize 4096 #define MethodIndex 3 #define MillisecondClockMask 536870911 #define MyListIndex 3 #define NextLinkIndex 0 #define NilContext 1 #define NilObject 0 #define PrimitiveExternalCallIndex 117 #define PriorityIndex 2 #define ProcessListsIndex 0 #define ProcessSignalingLowSpace 22 #define ReceiverIndex 5 #define RootTableRedZone 2400 #define RootTableSize 2500 #define SchedulerAssociation 3 #define SelectorAboutToReturn 48 #define SelectorCannotInterpret 34 #define SelectorCannotReturn 21 #define SelectorDoesNotUnderstand 20 #define SelectorMustBeBoolean 25 #define SelectorRunWithIn 49 #define SelectorStart 2 #define SemaphoresToSignalSize 500 #define SenderIndex 0 #define SpecialSelectors 23 #define StackPointerIndex 2 #define StartField 1 #define StartObj 2 #define StreamArrayIndex 0 #define StreamIndexIndex 1 #define StreamReadLimitIndex 2 #define StreamWriteLimitIndex 3 #define SuperclassIndex 0 #define SuspendedContextIndex 1 #define TempFrameStart 6 #define TheDisplay 14 #define TheFinalizationSemaphore 41 #define TheInterruptSemaphore 30 #define TheLowSpaceSemaphore 17 #define TheTimerSemaphore 29 #define TrueObject 2 #define TypeMask 3 #define Upward 3 #define ValueIndex 1 #define XIndex 0 #define YIndex 1 /*** Function Prototypes ***/ sqInt accessibleObjectAfter(sqInt oop); sqInt activateNewClosureMethod(sqInt blockClosure); sqInt activateNewMethod(void); #pragma export on EXPORT(sqInt) addGCRoot(sqInt *varLoc); #pragma export off sqInt addNewMethodToCache(void); sqInt addToExternalPrimitiveTable(void *functionAddress); sqInt adjustAllOopsBy(sqInt bytesToShift); sqInt allYoungand(sqInt array1, sqInt array2); sqInt allocateChunk(sqInt byteSize); sqInt allocateOrRecycleContext(sqInt needsLarge); sqInt argumentCountOf(sqInt methodPointer); void * arrayValueOf(sqInt arrayOop); sqInt asciiOfCharacter(sqInt characterObj); sqInt balancedStackafterPrimitivewithArgs(sqInt delta, sqInt primIdx, sqInt nArgs); sqInt baseHeaderSize(void); sqInt beRootIfOld(sqInt oop); sqInt beRootWhileForwarding(sqInt oop); sqInt becomewith(sqInt array1, sqInt array2); sqInt becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag); sqInt biasToGrow(void); sqInt booleanValueOf(sqInt obj); sqInt byteSizeOf(sqInt oop); sqInt byteSwapByteObjectsFromto(sqInt startOop, sqInt stopAddr); sqInt byteSwapped(sqInt w); sqInt bytesPerWord(void); sqInt callExternalPrimitive(void * functionID); #pragma export on EXPORT(sqInt) callInterpreter(void); EXPORT(sqInt) callbackEnter(sqInt *callbackID); EXPORT(sqInt) callbackLeave(sqInt cbID); #pragma export off sqInt changeClassOfto(sqInt rcvr, sqInt argClass); sqInt characterForAscii(sqInt ascii); sqInt characterTable(void); sqInt checkForInterrupts(void); sqInt checkImageVersionFromstartingAt(sqImageFile f, squeakFileOffsetType imageOffset); sqInt checkedIntegerValueOf(sqInt intOop); sqInt checkedLongAt(sqInt byteAddress); sqInt classAlien(void); sqInt classArray(void); sqInt classBitmap(void); sqInt classByteArray(void); sqInt classCharacter(void); sqInt classExternalAddress(void); sqInt classExternalData(void); sqInt classExternalFunction(void); sqInt classExternalLibrary(void); sqInt classExternalStructure(void); sqInt classFloat(void); sqInt classLargeNegativeInteger(void); sqInt classLargePositiveInteger(void); sqInt classNameOfIs(sqInt aClass, char * className); sqInt classPoint(void); sqInt classSemaphore(void); sqInt classSmallInteger(void); sqInt classString(void); sqInt classUnsafeAlien(void); sqInt clone(sqInt oop); sqInt commonAt(sqInt stringy); sqInt commonAtPut(sqInt stringy); sqInt commonVariableatcacheIndex(sqInt rcvr, sqInt index, sqInt atIx); sqInt compare31or32Bitsequal(sqInt obj1, sqInt obj2); sqInt compilerCreateActualMessagestoringArgs(sqInt aMessage, sqInt argArray); sqInt compilerFlushCache(sqInt aCompiledMethod); sqInt compilerMapFromto(sqInt memStart, sqInt memEnd); sqInt compilerMark(void); sqInt compilerPostGC(void); sqInt compilerPostSnapshot(void); sqInt compilerPreGC(sqInt fullGCFlag); sqInt compilerPreSnapshot(void); sqInt compilerProcessChange(void); sqInt compilerProcessChangeto(sqInt oldProc, sqInt newProc); sqInt compilerTranslateMethod(void); sqInt containOnlyOopsand(sqInt array1, sqInt array2); sqInt contexthasSender(sqInt thisCntx, sqInt aContext); sqInt copyBits(void); sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt y); sqInt copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(sqInt oop, sqInt segmentWordArray, sqInt lastSeg, sqInt stopAddr, sqInt oopPtr, sqInt hdrPtr); sqInt createActualMessageTo(sqInt aClass); sqInt dispatchFunctionPointer(void * aFunctionPointer); sqInt dispatchFunctionPointerOnin(sqInt primIdx, void *primTable[]); sqInt displayBitsOfLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt displayObject(void); sqInt doPrimitiveDivby(sqInt rcvr, sqInt arg); sqInt doPrimitiveModby(sqInt rcvr, sqInt arg); sqInt dummyReferToProxy(void); #pragma export on EXPORT(sqInt) dumpImage(char * fileName); #pragma export off sqInt executeNewMethodFromCache(void); sqInt failed(void); sqInt falseObject(void); void * fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchClassOf(sqInt oop); sqInt fetchClassOfNonInt(sqInt oop); double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchLong32ofObject(sqInt fieldIndex, sqInt oop); sqInt fetchPointerofObject(sqInt fieldIndex, sqInt oop); sqInt fetchStackPointerOf(sqInt aContext); sqInt fetchWordLengthOf(sqInt objectPointer); sqInt finalizeReference(usqInt oop); sqInt findClassOfMethodforReceiver(sqInt meth, sqInt rcvr); sqInt findNewMethodInClass(sqInt class); sqInt findObsoleteNamedPrimitivelength(char * functionName, sqInt functionLength); sqInt findSelectorOfMethodforReceiver(sqInt meth, sqInt rcvr); sqInt firstAccessibleObject(void); char * firstFixedField(sqInt oop); char * firstIndexableField(sqInt oop); sqInt floatObjectOf(double aFloat); double floatValueOf(sqInt oop); sqInt flushExternalPrimitiveOf(sqInt methodPtr); sqInt flushExternalPrimitives(void); sqInt forceInterruptCheck(void); sqInt fullDisplayUpdate(void); sqInt fullGC(void); sqInt fwdTableInit(sqInt blkSize); sqInt fwdTableSize(sqInt blkSize); sqInt getCurrentBytecode(void); sqInt getFullScreenFlag(void); sqInt getInterruptCheckCounter(void); sqInt getInterruptKeycode(void); sqInt getInterruptPending(void); sqInt getLongFromFileswap(sqImageFile aFile, sqInt swapFlag); sqInt getNextWakeupTick(void); sqInt getSavedWindowSize(void); #pragma export on EXPORT(sqInt) getStackPointer(void); #pragma export off sqInt getThisSessionID(void); sqInt growObjectMemory(usqInt delta); sqInt headerOf(sqInt methodPointer); sqInt imageFormatBackwardCompatibilityVersion(void); sqInt imageFormatForwardCompatibilityVersion(void); sqInt imageSegmentVersion(void); sqInt incCompBody(void); sqInt incCompMakeFwd(void); sqInt incCompMove(sqInt bytesFreed); sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperclass); sqInt incrementalGC(void); sqInt initCompilerHooks(void); sqInt initializeImageFormatVersionIfNeeded(void); sqInt initializeInterpreter(sqInt bytesToShift); sqInt initializeMemoryFirstFree(usqInt firstFree); sqInt initializeObjectMemory(sqInt bytesToShift); sqInt installinAtCacheatstring(sqInt rcvr, sqInt * cache, sqInt atIx, sqInt stringy); sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size); sqInt instantiateContextsizeInBytes(sqInt classPointer, sqInt sizeInBytes); sqInt instantiateSmallClasssizeInBytes(sqInt classPointer, sqInt sizeInBytes); sqInt integerObjectOf(sqInt value); sqInt integerValueOf(sqInt objectPointer); #pragma export on EXPORT(sqInt) internalIsImmutable(sqInt oop); EXPORT(sqInt) internalIsMutable(sqInt oop); #pragma export off sqInt interpret(void); sqInt ioFilenamefromStringofLengthresolveAliases(char * aCharBuffer, char * aFilenameString, sqInt filenameLength, sqInt aBoolean); sqInt isKindOf(sqInt oop, char * className); sqInt isMemberOf(sqInt oop, char * className); sqInt isArray(sqInt oop); sqInt isBigEnder(void); sqInt isBytes(sqInt oop); sqInt isExcessiveAllocationRequestshift(sqInt size, sqInt bits); sqInt isFloatObject(sqInt oop); sqInt isHandlerMarked(sqInt aContext); sqInt isInMemory(sqInt address); sqInt isIndexable(sqInt oop); sqInt isIntegerObject(sqInt objectPointer); sqInt isIntegerValue(sqInt intValue); sqInt isPointers(sqInt oop); sqInt isWeak(sqInt oop); sqInt isWords(sqInt oop); sqInt isWordsOrBytes(sqInt oop); sqInt isWordsOrBytesNonInt(sqInt oop); sqInt lastPointerOf(sqInt oop); sqInt lengthOf(sqInt oop); sqInt literalofMethod(sqInt offset, sqInt methodPointer); sqInt literalCountOf(sqInt methodPointer); sqInt literalCountOfHeader(sqInt headerPointer); sqInt loadBitBltFrom(sqInt bb); sqInt loadInitialContext(void); sqInt lookupInMethodCacheSelclass(sqInt selector, sqInt class); sqInt lookupMethodInClass(sqInt class); sqInt lookupMethodInDictionary(sqInt dictionary); sqInt lookupMethodNoMNUEtcInClass(sqInt class); sqInt lowestFreeAfter(sqInt chunk); sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue); sqInt mapPointersInObjectsFromto(sqInt memStart, sqInt memEnd); sqInt markAndTrace(sqInt oop); sqInt markAndTraceInterpreterOops(void); sqInt markPhase(void); sqInt methodArgumentCount(void); sqInt methodPrimitiveIndex(void); #pragma export on EXPORT(sqInt) moduleUnloaded(char * aModuleName); #pragma export off sqInt nilObject(void); sqInt nonWeakFieldsOf(sqInt oop); sqInt noteAsRootheaderLoc(sqInt oop, sqInt headerLoc); sqInt nullCompilerHook(void); sqInt objectAfter(sqInt oop); sqInt obsoleteDontUseThisFetchWordofObject(sqInt fieldIndex, sqInt oop); sqInt okayFields(sqInt oop); sqInt okayOop(sqInt signedOop); sqInt oopisGreaterThan(sqInt anOop, sqInt otherOop); sqInt oopisGreaterThanOrEqualTo(sqInt anOop, sqInt otherOop); sqInt oopisLessThan(sqInt anOop, sqInt otherOop); sqInt oopHasAcceptableClass(sqInt signedOop); sqInt oopHasOkayClass(sqInt signedOop); sqInt pop(sqInt nItems); sqInt popthenPush(sqInt nItems, sqInt oop); double popFloat(void); sqInt popRemappableOop(void); sqInt popStack(void); sqInt positive32BitIntegerFor(sqInt integerValue); sqInt positive32BitValueOf(sqInt oop); sqInt positive64BitIntegerFor(sqLong integerValue); sqLong positive64BitValueOf(sqInt oop); sqInt possibleRootStoreIntovalue(sqInt oop, sqInt valueObj); sqInt postGCAction(void); sqInt prepareForwardingTableForBecomingwithtwoWay(sqInt array1, sqInt array2, sqInt twoWayFlag); sqInt primitiveAdd(void); sqInt primitiveArctan(void); sqInt primitiveArrayBecome(void); sqInt primitiveArrayBecomeOneWay(void); sqInt primitiveArrayBecomeOneWayCopyHash(void); sqInt primitiveAsFloat(void); sqInt primitiveAsOop(void); sqInt primitiveAt(void); sqInt primitiveAtEnd(void); sqInt primitiveAtPut(void); sqInt primitiveBeCursor(void); sqInt primitiveBeDisplay(void); sqInt primitiveBeep(void); sqInt primitiveBitAnd(void); sqInt primitiveBitOr(void); sqInt primitiveBitShift(void); sqInt primitiveBitXor(void); sqInt primitiveBlockCopy(void); sqInt primitiveBytesLeft(void); sqInt primitiveCalloutToFFI(void); sqInt primitiveChangeClass(void); #pragma export on EXPORT(sqInt) primitiveChangeClassWithClass(void); #pragma export off sqInt primitiveClass(void); sqInt primitiveClipboardText(void); sqInt primitiveClone(void); sqInt primitiveClosureCopyWithCopiedValues(void); sqInt primitiveClosureValue(void); sqInt primitiveClosureValueNoContextSwitch(void); sqInt primitiveClosureValueWithArgs(void); sqInt primitiveConstantFill(void); sqInt primitiveCopyObject(void); sqInt primitiveDeferDisplayUpdates(void); #pragma export on EXPORT(sqInt) primitiveDisablePowerManager(void); #pragma export off sqInt primitiveDiv(void); sqInt primitiveDivide(void); sqInt primitiveDoNamedPrimitiveWithArgs(void); sqInt primitiveDoPrimitiveWithArgs(void); sqInt primitiveEqual(void); sqInt primitiveEquivalent(void); sqInt primitiveExecuteMethod(void); sqInt primitiveExecuteMethodArgsArray(void); sqInt primitiveExitToDebugger(void); sqInt primitiveExp(void); sqInt primitiveExponent(void); sqInt primitiveExternalCall(void); sqInt primitiveFail(void); sqInt primitiveFailFor(sqInt reasonCode); sqInt primitiveFindHandlerContext(void); sqInt primitiveFindNextUnwindContext(void); sqInt primitiveFloatAdd(void); sqInt primitiveFloatAddtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatDivide(void); sqInt primitiveFloatDividebyArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatEqual(void); sqInt primitiveFloatEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterthanArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterOrEqual(void); sqInt primitiveFloatGreaterOrEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterThan(void); sqInt primitiveFloatLessthanArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatLessOrEqual(void); sqInt primitiveFloatLessOrEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatLessThan(void); sqInt primitiveFloatMultiply(void); sqInt primitiveFloatMultiplybyArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatNotEqual(void); sqInt primitiveFloatSubtract(void); sqInt primitiveFloatSubtractfromArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFlushCache(void); sqInt primitiveFlushCacheByMethod(void); sqInt primitiveFlushCacheSelective(void); sqInt primitiveFlushExternalPrimitives(void); sqInt primitiveForceDisplayUpdate(void); #pragma export on EXPORT(sqInt) primitiveForceTenure(void); #pragma export off sqInt primitiveFormPrint(void); sqInt primitiveFractionalPart(void); sqInt primitiveFullGC(void); sqInt primitiveGetAttribute(void); sqInt primitiveGetNextEvent(void); sqInt primitiveGreaterOrEqual(void); sqInt primitiveGreaterThan(void); #pragma export on EXPORT(sqInt) primitiveImageFormatVersion(void); #pragma export off sqInt primitiveImageName(void); sqInt primitiveIncrementalGC(void); sqInt primitiveIndexOf(sqInt methodPointer); sqInt primitiveIndexOfMethodHeader(sqInt methodHeader); sqInt primitiveInputSemaphore(void); sqInt primitiveInputWord(void); sqInt primitiveInstVarAt(void); sqInt primitiveInstVarAtPut(void); sqInt primitiveInstVarsPutFromStack(void); sqInt primitiveIntegerAt(void); sqInt primitiveIntegerAtPut(void); #pragma export on EXPORT(sqInt) primitiveInterpreterSourceVersion(void); #pragma export off sqInt primitiveInterruptSemaphore(void); sqInt primitiveInvokeObjectAsMethod(void); #pragma export on EXPORT(sqInt) primitiveIsRoot(void); EXPORT(sqInt) primitiveIsYoung(void); #pragma export off sqInt primitiveKbdNext(void); sqInt primitiveKbdPeek(void); sqInt primitiveLessOrEqual(void); sqInt primitiveLessThan(void); sqInt primitiveListBuiltinModule(void); sqInt primitiveListExternalModule(void); sqInt primitiveLoadImageSegment(void); sqInt primitiveLoadInstVar(void); sqInt primitiveLogN(void); sqInt primitiveLowSpaceSemaphore(void); sqInt primitiveMakePoint(void); sqInt primitiveMarkHandlerMethod(void); sqInt primitiveMarkUnwindMethod(void); sqInt primitiveMethod(void); #pragma export on EXPORT(sqInt) primitiveMicrosecondClock(void); #pragma export off sqInt primitiveMillisecondClock(void); sqInt primitiveMod(void); sqInt primitiveMouseButtons(void); sqInt primitiveMousePoint(void); sqInt primitiveMultiply(void); sqInt primitiveNew(void); sqInt primitiveNewMethod(void); sqInt primitiveNewWithArg(void); sqInt primitiveNext(void); sqInt primitiveNextInstance(void); sqInt primitiveNextObject(void); sqInt primitiveNextPut(void); sqInt primitiveNoop(void); sqInt primitiveNotEqual(void); sqInt primitiveObjectAt(void); sqInt primitiveObjectAtPut(void); sqInt primitiveObjectPointsTo(void); sqInt primitiveObsoleteIndexedPrimitive(void); sqInt primitivePerform(void); sqInt primitivePerformAt(sqInt lookupClass); sqInt primitivePerformInSuperclass(void); sqInt primitivePerformWithArgs(void); #pragma export on EXPORT(sqInt) primitivePlatformSourceVersion(void); #pragma export off sqInt primitivePushFalse(void); sqInt primitivePushMinusOne(void); sqInt primitivePushNil(void); sqInt primitivePushOne(void); sqInt primitivePushSelf(void); sqInt primitivePushTrue(void); sqInt primitivePushTwo(void); sqInt primitivePushZero(void); sqInt primitiveQuit(void); sqInt primitiveQuo(void); sqInt primitiveRelinquishProcessor(void); sqInt primitiveResponse(void); sqInt primitiveResume(void); #pragma export on EXPORT(sqInt) primitiveRootTable(void); EXPORT(sqInt) primitiveRootTableAt(void); #pragma export off sqInt primitiveScanCharacters(void); #pragma export on EXPORT(sqInt) primitiveScreenDepth(void); #pragma export off sqInt primitiveScreenSize(void); sqInt primitiveSecondsClock(void); sqInt primitiveSetDisplayMode(void); sqInt primitiveSetFullScreen(void); #pragma export on EXPORT(sqInt) primitiveSetGCBiasToGrow(void); EXPORT(sqInt) primitiveSetGCBiasToGrowGCLimit(void); EXPORT(sqInt) primitiveSetGCSemaphore(void); #pragma export off sqInt primitiveSetInterruptKey(void); sqInt primitiveShortAt(void); sqInt primitiveShortAtPut(void); sqInt primitiveShowDisplayRect(void); sqInt primitiveSignal(void); sqInt primitiveSignalAtBytesLeft(void); sqInt primitiveSignalAtMilliseconds(void); sqInt primitiveSine(void); sqInt primitiveSize(void); sqInt primitiveSnapshot(void); sqInt primitiveSnapshotEmbedded(void); sqInt primitiveSomeInstance(void); sqInt primitiveSomeObject(void); sqInt primitiveSpecialObjectsOop(void); sqInt primitiveSquareRoot(void); sqInt primitiveStoreImageSegment(void); sqInt primitiveStoreStackp(void); sqInt primitiveStringAt(void); sqInt primitiveStringAtPut(void); sqInt primitiveStringReplace(void); sqInt primitiveSubtract(void); sqInt primitiveSuspend(void); sqInt primitiveTerminateTo(void); sqInt primitiveTestDisplayDepth(void); sqInt primitiveTimesTwoPower(void); sqInt primitiveTruncated(void); sqInt primitiveUnloadModule(void); #pragma export on EXPORT(sqInt) primitiveUtcWithOffset(void); #pragma export off sqInt primitiveVMParameter(void); sqInt primitiveVMPath(void); #pragma export on EXPORT(sqInt) primitiveVMVersion(void); #pragma export off sqInt primitiveValue(void); sqInt primitiveValueUninterruptably(void); sqInt primitiveValueWithArgs(void); sqInt primitiveWait(void); sqInt primitiveYield(void); sqInt print(char * s); sqInt printAllStacks(void); sqInt printCallStack(void); sqInt printCallStackOf(sqInt aContext); sqInt printNameOfClasscount(sqInt classOop, sqInt cnt); sqInt printNum(sqInt n); sqInt printStringOf(sqInt oop); sqInt printUnbalancedStack(sqInt primIdx); sqInt push(sqInt object); sqInt pushBool(sqInt trueOrFalse); sqInt pushFloat(double f); sqInt pushInteger(sqInt integerValue); sqInt pushRemappableOop(sqInt oop); sqInt putLongtoFile(sqInt aWord, sqImageFile aFile); sqInt readImageFromFileHeapSizeStartingAt(sqImageFile f, usqInt desiredHeapSize, squeakFileOffsetType imageOffset); sqInt readableFormat(sqInt imageVersion); #pragma export on EXPORT(sqInt) reestablishContextPriorToCallback(sqInt callbackContext); #pragma export off sqInt remap(sqInt oop); sqInt removeFirstLinkOfList(sqInt aList); #pragma export on EXPORT(sqInt) removeGCRoot(sqInt *varLoc); #pragma export off sqInt restoreHeaderOf(sqInt oop); sqInt restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut); sqInt resume(sqInt aProcess); sqInt reverseDisplayFromto(sqInt startIndex, sqInt endIndex); sqInt rewriteMethodCacheSelclassprimIndex(sqInt selector, sqInt class, sqInt localPrimIndex); sqInt rewriteMethodCacheSelclassprimIndexprimFunction(sqInt selector, sqInt class, sqInt localPrimIndex, void * localPrimAddress); #pragma export on EXPORT(sqInt) sendInvokeCallbackStackRegistersJmpbuf(sqInt thunkPtr, sqInt stackPtr, sqInt regsPtr, sqInt jmpBufPtr); #pragma export off sqInt setCompilerInitialized(sqInt newFlag); sqInt setFullScreenFlag(sqInt value); sqInt setInterruptCheckCounter(sqInt value); sqInt setInterruptKeycode(sqInt value); sqInt setInterruptPending(sqInt value); sqInt setMicroSecondsandOffset(sqLong * microSeconds, int * utcOffset); sqInt setNextWakeupTick(sqInt value); sqInt setSavedWindowSize(sqInt value); sqInt showDisplayBitsLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt signalSemaphoreWithIndex(sqInt index); sqInt signed32BitIntegerFor(int integerValue); int signed32BitValueOf(sqInt oop); sqInt signed64BitIntegerFor(sqLong integerValue); sqLong signed64BitValueOf(sqInt oop); sqInt sizeBitsOf(sqInt oop); sqInt sizeOfSTArrayFromCPrimitive(void * cPtr); sqInt slotSizeOf(sqInt oop); sqInt snapshot(sqInt embedded); sqInt splObj(sqInt index); sqInt stObjectat(sqInt array, sqInt index); sqInt stObjectatput(sqInt array, sqInt index, sqInt value); sqInt stSizeOf(sqInt oop); double stackFloatValue(sqInt offset); sqInt stackIntegerValue(sqInt offset); sqInt stackObjectValue(sqInt offset); sqInt stackValue(sqInt offset); sqInt storeIntegerofObjectwithValue(sqInt fieldIndex, sqInt objectPointer, sqInt integerValue); sqInt storePointerofObjectwithValue(sqInt fieldIndex, sqInt oop, sqInt valuePointer); sqInt success(sqInt successValue); sqInt sufficientSpaceAfterGC(usqInt minFree); sqInt sufficientSpaceToAllocate(usqInt bytes); sqInt superclassOf(sqInt classPointer); sqInt sweepPhase(void); sqInt synchronousSignal(sqInt aSemaphore); sqInt transferTo(sqInt aProc); sqInt trueObject(void); sqInt updatePointersInRangeFromto(sqInt memStart, sqInt memEnd); sqInt updatePointersInRootObjectsFromto(sqInt memStart, sqInt memEnd); sqInt validateRoots(void); sqInt verifyCleanHeaders(void); sqInt vmEndianness(void); sqInt wakeHighestPriority(void); sqInt wordSwapped(sqInt w); sqInt writeImageFile(sqInt imageBytes); sqInt writeImageFileIO(sqInt imageBytes); /*** Variables ***/ struct foo { sqInt successFlag; sqInt specialObjectsOop; sqInt nilObj; sqInt argumentCount; sqInt trueObj; sqInt falseObj; sqInt interruptCheckCounter; sqInt remapBufferCount; sqInt nextPollTick; sqInt primitiveIndex; sqInt messageSelector; sqInt rootTableCount; sqInt allocationCount; sqInt compilerInitialized; sqInt receiver; sqInt lkupClass; sqInt allocationsBetweenGCs; sqInt lowSpaceThreshold; sqInt signalLowSpace; sqInt freeContexts; sqInt lastHash; sqInt reclaimableContextCount; sqInt pendingFinalizationSignals; sqInt freeLargeContexts; sqInt methodClass; sqInt newNativeMethod; sqInt jmpDepth; sqInt nextWakeupTick; sqInt extraRootCount; sqInt statMarkCount; sqInt interruptPending; sqInt semaphoresToSignalCountA; sqInt interruptKeycode; sqInt receiverClass; sqInt semaphoresUseBufferA; sqInt fullScreenFlag; sqInt statSweepCount; sqInt statMkFwdCount; sqInt statCompMoveCount; sqInt semaphoresToSignalCountB; sqInt statRootTableOverflows; sqInt tenuringThreshold; sqInt gcBiasToGrow; sqInt statFullGCs; sqInt statIncrGCs; sqInt statTenures; sqInt gcBiasToGrowGCLimit; sqInt forceTenureFlag; sqInt statShrinkMemory; sqInt savedWindowSize; sqInt statGrowMemory; sqInt deferDisplayUpdates; sqInt shrinkThreshold; sqInt statpendingFinalizationSignals; sqInt interruptChecksEveryNms; sqInt totalObjectCount; sqInt statSpecialMarkCount; sqInt statAllocationCount; sqInt statRootTableCount; sqInt weakRootCount; sqInt gcSemaphoreIndex; sqInt statSurvivorCount; sqInt lastTick; sqInt interruptCheckCounterFeedBackReset; sqInt jmpMax; sqInt globalSessionID; sqLong statIGCDeltaTime; sqLong statGCTime; sqInt remapBuffer[26]; sqInt headerTypeBytes[4]; usqInt gcBiasToGrowThreshold; sqLong statIncrGCMSecs; sqLong statFullGCMSecs; usqInt growHeadroom; usqInt fwdTableLast; sqInt processSignalingLowSpace; sqInt semaphoresToSignalB[501]; sqInt semaphoresToSignalA[501]; sqInt atCache[65]; usqInt method; usqInt theHomeContext; usqInt stackPointer; usqInt instructionPointer; void *primitiveFunctionPointer; usqInt newMethod; long methodCache[4097]; usqInt endOfMemory; sqInt* extraRoots[2049]; sqInt rootTable[2501]; usqInt freeBlock; sqInt weakRoots[2625]; usqInt compEnd; usqInt compStart; usqInt memoryLimit; usqInt activeContext; usqInt fwdTableNext; void *externalPrimitiveTable[4097]; sqInt suspendedCallbacks[33]; jmp_buf jmpBuf[33]; sqInt suspendedMethods[33]; usqInt youngStart; } fum; struct foo * foo = &fum; sqInt extraVMMemory; const char *interpreterVersion = "Squeak4.1 of 17 April 2010 [latest update: #9957]"; sqInt (*compilerHooks[16])(); char* obsoleteIndexedPrimitiveTable[][3] = { { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "BitBltPlugin", "primitiveCopyBits", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "BitBltPlugin", "primitiveDrawLoop", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "JoystickTabletPlugin", "primitiveReadJoystick", NULL }, { "BitBltPlugin", "primitiveWarpBits", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "FilePlugin", "primitiveFileAtEnd", NULL }, { "FilePlugin", "primitiveFileClose", NULL }, { "FilePlugin", "primitiveFileGetPosition", NULL }, { "FilePlugin", "primitiveFileOpen", NULL }, { "FilePlugin", "primitiveFileRead", NULL }, { "FilePlugin", "primitiveFileSetPosition", NULL }, { "FilePlugin", "primitiveFileDelete", NULL }, { "FilePlugin", "primitiveFileSize", NULL }, { "FilePlugin", "primitiveFileWrite", NULL }, { "FilePlugin", "primitiveFileRename", NULL }, { "FilePlugin", "primitiveDirectoryCreate", NULL }, { "FilePlugin", "primitiveDirectoryDelimitor", NULL }, { "FilePlugin", "primitiveDirectoryLookup", NULL }, { "FilePlugin", "primitiveDirectoryDelete", NULL }, { "FilePlugin", "primitiveDirectoryGetMacTypeAndCreator", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "FilePlugin", "primitiveDirectorySetMacTypeAndCreator", NULL }, { "SoundPlugin", "primitiveSoundStart", NULL }, { "SoundPlugin", "primitiveSoundStartWithSemaphore", NULL }, { "SoundPlugin", "primitiveSoundStop", NULL }, { "SoundPlugin", "primitiveSoundAvailableSpace", NULL }, { "SoundPlugin", "primitiveSoundPlaySamples", NULL }, { "SoundPlugin", "primitiveSoundPlaySilence", NULL }, { "SoundGenerationPlugin", "primitiveWaveTableSoundMix", NULL }, { "SoundGenerationPlugin", "primitiveFMSoundMix", NULL }, { "SoundGenerationPlugin", "primitivePluckedSoundMix", NULL }, { "SoundGenerationPlugin", "primitiveSampledSoundMix", NULL }, { "SoundGenerationPlugin", "primitiveMixFMSound", NULL }, { "SoundGenerationPlugin", "primitiveMixPluckedSound", NULL }, { "SoundGenerationPlugin", "primitiveOldSampledSoundMix", NULL }, { "SoundGenerationPlugin", "primitiveApplyReverb", NULL }, { "SoundGenerationPlugin", "primitiveMixLoopedSampledSound", NULL }, { "SoundGenerationPlugin", "primitiveMixSampledSound", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "SoundPlugin", "primitiveSoundInsertSamples", NULL }, { "SoundPlugin", "primitiveSoundStartRecording", NULL }, { "SoundPlugin", "primitiveSoundStopRecording", NULL }, { "SoundPlugin", "primitiveSoundGetRecordingSampleRate", NULL }, { "SoundPlugin", "primitiveSoundRecordSamples", NULL }, { "SoundPlugin", "primitiveSoundSetRecordLevel", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "SocketPlugin", "primitiveInitializeNetwork", NULL }, { "SocketPlugin", "primitiveResolverStartNameLookup", NULL }, { "SocketPlugin", "primitiveResolverNameLookupResult", NULL }, { "SocketPlugin", "primitiveResolverStartAddressLookup", NULL }, { "SocketPlugin", "primitiveResolverAddressLookupResult", NULL }, { "SocketPlugin", "primitiveResolverAbortLookup", NULL }, { "SocketPlugin", "primitiveResolverLocalAddress", NULL }, { "SocketPlugin", "primitiveResolverStatus", NULL }, { "SocketPlugin", "primitiveResolverError", NULL }, { "SocketPlugin", "primitiveSocketCreate", NULL }, { "SocketPlugin", "primitiveSocketDestroy", NULL }, { "SocketPlugin", "primitiveSocketConnectionStatus", NULL }, { "SocketPlugin", "primitiveSocketError", NULL }, { "SocketPlugin", "primitiveSocketLocalAddress", NULL }, { "SocketPlugin", "primitiveSocketLocalPort", NULL }, { "SocketPlugin", "primitiveSocketRemoteAddress", NULL }, { "SocketPlugin", "primitiveSocketRemotePort", NULL }, { "SocketPlugin", "primitiveSocketConnectToPort", NULL }, { "SocketPlugin", "primitiveSocketListenWithOrWithoutBacklog", NULL }, { "SocketPlugin", "primitiveSocketCloseConnection", NULL }, { "SocketPlugin", "primitiveSocketAbortConnection", NULL }, { "SocketPlugin", "primitiveSocketReceiveDataBufCount", NULL }, { "SocketPlugin", "primitiveSocketReceiveDataAvailable", NULL }, { "SocketPlugin", "primitiveSocketSendDataBufCount", NULL }, { "SocketPlugin", "primitiveSocketSendDone", NULL }, { "SocketPlugin", "primitiveSocketAccept", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "MiscPrimitivePlugin", "primitiveDecompressFromByteArray", NULL }, { "MiscPrimitivePlugin", "primitiveCompareString", NULL }, { "MiscPrimitivePlugin", "primitiveConvert8BitSigned", NULL }, { "MiscPrimitivePlugin", "primitiveCompressToByteArray", NULL }, { "SerialPlugin", "primitiveSerialPortOpen", NULL }, { "SerialPlugin", "primitiveSerialPortClose", NULL }, { "SerialPlugin", "primitiveSerialPortWrite", NULL }, { "SerialPlugin", "primitiveSerialPortRead", NULL }, { NULL, NULL, NULL }, { "MiscPrimitivePlugin", "primitiveTranslateStringWithTable", NULL }, { "MiscPrimitivePlugin", "primitiveFindFirstInString", NULL }, { "MiscPrimitivePlugin", "primitiveIndexOfAsciiInString", NULL }, { "MiscPrimitivePlugin", "primitiveFindSubstring", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "MIDIPlugin", "primitiveMIDIClosePort", NULL }, { "MIDIPlugin", "primitiveMIDIGetClock", NULL }, { "MIDIPlugin", "primitiveMIDIGetPortCount", NULL }, { "MIDIPlugin", "primitiveMIDIGetPortDirectionality", NULL }, { "MIDIPlugin", "primitiveMIDIGetPortName", NULL }, { "MIDIPlugin", "primitiveMIDIOpenPort", NULL }, { "MIDIPlugin", "primitiveMIDIParameterGetOrSet", NULL }, { "MIDIPlugin", "primitiveMIDIRead", NULL }, { "MIDIPlugin", "primitiveMIDIWrite", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "AsynchFilePlugin", "primitiveAsyncFileClose", NULL }, { "AsynchFilePlugin", "primitiveAsyncFileOpen", NULL }, { "AsynchFilePlugin", "primitiveAsyncFileReadResult", NULL }, { "AsynchFilePlugin", "primitiveAsyncFileReadStart", NULL }, { "AsynchFilePlugin", "primitiveAsyncFileWriteResult", NULL }, { "AsynchFilePlugin", "primitiveAsyncFileWriteStart", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { "JoystickTabletPlugin", "primitiveGetTabletParameters", NULL }, { "JoystickTabletPlugin", "primitiveReadTablet", NULL }, { "ADPCMCodecPlugin", "primitiveDecodeMono", NULL }, { "ADPCMCodecPlugin", "primitiveDecodeStereo", NULL }, { "ADPCMCodecPlugin", "primitiveEncodeMono", NULL }, { "ADPCMCodecPlugin", "primitiveEncodeStereo", NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL }, { NULL, NULL, NULL } }; sqInt imageFormatVersionNumber = 0; const char* obsoleteNamedPrimitiveTable[][3] = { { "gePrimitiveMergeFillFrom", "B2DPlugin", "primitiveMergeFillFrom" }, { "gePrimitiveSetClipRect", "B2DPlugin", "primitiveSetClipRect" }, { "gePrimitiveDoProfileStats", "B2DPlugin", "primitiveDoProfileStats" }, { "gePrimitiveAddCompressedShape", "B2DPlugin", "primitiveAddCompressedShape" }, { "gePrimitiveFinishedProcessing", "B2DPlugin", "primitiveFinishedProcessing" }, { "gePrimitiveGetBezierStats", "B2DPlugin", "primitiveGetBezierStats" }, { "gePrimitiveSetDepth", "B2DPlugin", "primitiveSetDepth" }, { "gePrimitiveAbortProcessing", "B2DPlugin", "primitiveAbortProcessing" }, { "gePrimitiveGetTimes", "B2DPlugin", "primitiveGetTimes" }, { "gePrimitiveNextActiveEdgeEntry", "B2DPlugin", "primitiveNextActiveEdgeEntry" }, { "gePrimitiveAddBezier", "B2DPlugin", "primitiveAddBezier" }, { "gePrimitiveRenderScanline", "B2DPlugin", "primitiveRenderScanline" }, { "gePrimitiveAddBezierShape", "B2DPlugin", "primitiveAddBezierShape" }, { "gePrimitiveAddLine", "B2DPlugin", "primitiveAddLine" }, { "gePrimitiveRenderImage", "B2DPlugin", "primitiveRenderImage" }, { "gePrimitiveGetAALevel", "B2DPlugin", "primitiveGetAALevel" }, { "gePrimitiveRegisterExternalEdge", "B2DPlugin", "primitiveRegisterExternalEdge" }, { "gePrimitiveInitializeBuffer", "B2DPlugin", "primitiveInitializeBuffer" }, { "gePrimitiveAddRect", "B2DPlugin", "primitiveAddRect" }, { "gePrimitiveInitializeProcessing", "B2DPlugin", "primitiveInitializeProcessing" }, { "gePrimitiveAddBitmapFill", "B2DPlugin", "primitiveAddBitmapFill" }, { "gePrimitiveGetClipRect", "B2DPlugin", "primitiveGetClipRect" }, { "gePrimitiveGetFailureReason", "B2DPlugin", "primitiveGetFailureReason" }, { "gePrimitiveNextGlobalEdgeEntry", "B2DPlugin", "primitiveNextGlobalEdgeEntry" }, { "gePrimitiveNextFillEntry", "B2DPlugin", "primitiveNextFillEntry" }, { "gePrimitiveSetColorTransform", "B2DPlugin", "primitiveSetColorTransform" }, { "gePrimitiveDisplaySpanBuffer", "B2DPlugin", "primitiveDisplaySpanBuffer" }, { "gePrimitiveGetOffset", "B2DPlugin", "primitiveGetOffset" }, { "gePrimitiveAddPolygon", "B2DPlugin", "primitiveAddPolygon" }, { "gePrimitiveNeedsFlush", "B2DPlugin", "primitiveNeedsFlush" }, { "gePrimitiveAddOval", "B2DPlugin", "primitiveAddOval" }, { "gePrimitiveSetAALevel", "B2DPlugin", "primitiveSetAALevel" }, { "gePrimitiveCopyBuffer", "B2DPlugin", "primitiveCopyBuffer" }, { "gePrimitiveAddActiveEdgeEntry", "B2DPlugin", "primitiveAddActiveEdgeEntry" }, { "gePrimitiveGetCounts", "B2DPlugin", "primitiveGetCounts" }, { "gePrimitiveSetOffset", "B2DPlugin", "primitiveSetOffset" }, { "gePrimitiveAddGradientFill", "B2DPlugin", "primitiveAddGradientFill" }, { "gePrimitiveChangedActiveEdgeEntry", "B2DPlugin", "primitiveChangedActiveEdgeEntry" }, { "gePrimitiveRegisterExternalFill", "B2DPlugin", "primitiveRegisterExternalFill" }, { "gePrimitiveGetDepth", "B2DPlugin", "primitiveGetDepth" }, { "gePrimitiveSetEdgeTransform", "B2DPlugin", "primitiveSetEdgeTransform" }, { "gePrimitiveNeedsFlushPut", "B2DPlugin", "primitiveNeedsFlushPut" }, { "primitiveFloatArrayAt", "FloatArrayPlugin", "primitiveAt" }, { "primitiveFloatArrayMulFloatArray", "FloatArrayPlugin", "primitiveMulFloatArray" }, { "primitiveFloatArrayAddScalar", "FloatArrayPlugin", "primitiveAddScalar" }, { "primitiveFloatArrayDivFloatArray", "FloatArrayPlugin", "primitiveDivFloatArray" }, { "primitiveFloatArrayDivScalar", "FloatArrayPlugin", "primitiveDivScalar" }, { "primitiveFloatArrayHash", "FloatArrayPlugin", "primitiveHashArray" }, { "primitiveFloatArrayAtPut", "FloatArrayPlugin", "primitiveAtPut" }, { "primitiveFloatArrayMulScalar", "FloatArrayPlugin", "primitiveMulScalar" }, { "primitiveFloatArrayAddFloatArray", "FloatArrayPlugin", "primitiveAddFloatArray" }, { "primitiveFloatArraySubScalar", "FloatArrayPlugin", "primitiveSubScalar" }, { "primitiveFloatArraySubFloatArray", "FloatArrayPlugin", "primitiveSubFloatArray" }, { "primitiveFloatArrayEqual", "FloatArrayPlugin", "primitiveEqual" }, { "primitiveFloatArrayDotProduct", "FloatArrayPlugin", "primitiveDotProduct" }, { "m23PrimitiveInvertRectInto", "Matrix2x3Plugin", "primitiveInvertRectInto" }, { "m23PrimitiveTransformPoint", "Matrix2x3Plugin", "primitiveTransformPoint" }, { "m23PrimitiveIsPureTranslation", "Matrix2x3Plugin", "primitiveIsPureTranslation" }, { "m23PrimitiveComposeMatrix", "Matrix2x3Plugin", "primitiveComposeMatrix" }, { "m23PrimitiveTransformRectInto", "Matrix2x3Plugin", "primitiveTransformRectInto" }, { "m23PrimitiveIsIdentity", "Matrix2x3Plugin", "primitiveIsIdentity" }, { "m23PrimitiveInvertPoint", "Matrix2x3Plugin", "primitiveInvertPoint" }, { "primitiveDeflateBlock", "ZipPlugin", "primitiveDeflateBlock" }, { "primitiveDeflateUpdateHashTable", "ZipPlugin", "primitiveDeflateUpdateHashTable" }, { "primitiveUpdateGZipCrc32", "ZipPlugin", "primitiveUpdateGZipCrc32" }, { "primitiveInflateDecompressBlock", "ZipPlugin", "primitiveInflateDecompressBlock" }, { "primitiveZipSendBlock", "ZipPlugin", "primitiveZipSendBlock" }, { "primitiveFFTTransformData", "FFTPlugin", "primitiveFFTTransformData" }, { "primitiveFFTScaleData", "FFTPlugin", "primitiveFFTScaleData" }, { "primitiveFFTPermuteData", "FFTPlugin", "primitiveFFTPermuteData" }, { NULL, NULL, NULL } }; struct VirtualMachine* interpreterProxy; void *primitiveTable[577] = { /* 0*/ (void *)primitiveFail, /* 1*/ (void *)primitiveAdd, /* 2*/ (void *)primitiveSubtract, /* 3*/ (void *)primitiveLessThan, /* 4*/ (void *)primitiveGreaterThan, /* 5*/ (void *)primitiveLessOrEqual, /* 6*/ (void *)primitiveGreaterOrEqual, /* 7*/ (void *)primitiveEqual, /* 8*/ (void *)primitiveNotEqual, /* 9*/ (void *)primitiveMultiply, /* 10*/ (void *)primitiveDivide, /* 11*/ (void *)primitiveMod, /* 12*/ (void *)primitiveDiv, /* 13*/ (void *)primitiveQuo, /* 14*/ (void *)primitiveBitAnd, /* 15*/ (void *)primitiveBitOr, /* 16*/ (void *)primitiveBitXor, /* 17*/ (void *)primitiveBitShift, /* 18*/ (void *)primitiveMakePoint, /* 19*/ (void *)primitiveFail, /* 20*/ (void *)primitiveFail, /* 21*/ (void *)primitiveFail, /* 22*/ (void *)primitiveFail, /* 23*/ (void *)primitiveFail, /* 24*/ (void *)primitiveFail, /* 25*/ (void *)primitiveFail, /* 26*/ (void *)primitiveFail, /* 27*/ (void *)primitiveFail, /* 28*/ (void *)primitiveFail, /* 29*/ (void *)primitiveFail, /* 30*/ (void *)primitiveFail, /* 31*/ (void *)primitiveFail, /* 32*/ (void *)primitiveFail, /* 33*/ (void *)primitiveFail, /* 34*/ (void *)primitiveFail, /* 35*/ (void *)primitiveFail, /* 36*/ (void *)primitiveFail, /* 37*/ (void *)primitiveFail, /* 38*/ (void *)primitiveFail, /* 39*/ (void *)primitiveFail, /* 40*/ (void *)primitiveAsFloat, /* 41*/ (void *)primitiveFloatAdd, /* 42*/ (void *)primitiveFloatSubtract, /* 43*/ (void *)primitiveFloatLessThan, /* 44*/ (void *)primitiveFloatGreaterThan, /* 45*/ (void *)primitiveFloatLessOrEqual, /* 46*/ (void *)primitiveFloatGreaterOrEqual, /* 47*/ (void *)primitiveFloatEqual, /* 48*/ (void *)primitiveFloatNotEqual, /* 49*/ (void *)primitiveFloatMultiply, /* 50*/ (void *)primitiveFloatDivide, /* 51*/ (void *)primitiveTruncated, /* 52*/ (void *)primitiveFractionalPart, /* 53*/ (void *)primitiveExponent, /* 54*/ (void *)primitiveTimesTwoPower, /* 55*/ (void *)primitiveSquareRoot, /* 56*/ (void *)primitiveSine, /* 57*/ (void *)primitiveArctan, /* 58*/ (void *)primitiveLogN, /* 59*/ (void *)primitiveExp, /* 60*/ (void *)primitiveAt, /* 61*/ (void *)primitiveAtPut, /* 62*/ (void *)primitiveSize, /* 63*/ (void *)primitiveStringAt, /* 64*/ (void *)primitiveStringAtPut, /* 65*/ (void *)primitiveNext, /* 66*/ (void *)primitiveNextPut, /* 67*/ (void *)primitiveAtEnd, /* 68*/ (void *)primitiveObjectAt, /* 69*/ (void *)primitiveObjectAtPut, /* 70*/ (void *)primitiveNew, /* 71*/ (void *)primitiveNewWithArg, /* 72*/ (void *)primitiveArrayBecomeOneWay, /* 73*/ (void *)primitiveInstVarAt, /* 74*/ (void *)primitiveInstVarAtPut, /* 75*/ (void *)primitiveAsOop, /* 76*/ (void *)primitiveStoreStackp, /* 77*/ (void *)primitiveSomeInstance, /* 78*/ (void *)primitiveNextInstance, /* 79*/ (void *)primitiveNewMethod, /* 80*/ (void *)primitiveBlockCopy, /* 81*/ (void *)primitiveValue, /* 82*/ (void *)primitiveValueWithArgs, /* 83*/ (void *)primitivePerform, /* 84*/ (void *)primitivePerformWithArgs, /* 85*/ (void *)primitiveSignal, /* 86*/ (void *)primitiveWait, /* 87*/ (void *)primitiveResume, /* 88*/ (void *)primitiveSuspend, /* 89*/ (void *)primitiveFlushCache, /* 90*/ (void *)primitiveMousePoint, /* 91*/ (void *)primitiveTestDisplayDepth, /* 92*/ (void *)primitiveSetDisplayMode, /* 93*/ (void *)primitiveInputSemaphore, /* 94*/ (void *)primitiveGetNextEvent, /* 95*/ (void *)primitiveInputWord, /* 96*/ (void *)primitiveObsoleteIndexedPrimitive, /* 97*/ (void *)primitiveSnapshot, /* 98*/ (void *)primitiveStoreImageSegment, /* 99*/ (void *)primitiveLoadImageSegment, /* 100*/ (void *)primitivePerformInSuperclass, /* 101*/ (void *)primitiveBeCursor, /* 102*/ (void *)primitiveBeDisplay, /* 103*/ (void *)primitiveScanCharacters, /* 104*/ (void *)primitiveObsoleteIndexedPrimitive, /* 105*/ (void *)primitiveStringReplace, /* 106*/ (void *)primitiveScreenSize, /* 107*/ (void *)primitiveMouseButtons, /* 108*/ (void *)primitiveKbdNext, /* 109*/ (void *)primitiveKbdPeek, /* 110*/ (void *)primitiveEquivalent, /* 111*/ (void *)primitiveClass, /* 112*/ (void *)primitiveBytesLeft, /* 113*/ (void *)primitiveQuit, /* 114*/ (void *)primitiveExitToDebugger, /* 115*/ (void *)primitiveChangeClass, /* 116*/ (void *)primitiveFlushCacheByMethod, /* 117*/ (void *)primitiveExternalCall, /* 118*/ (void *)primitiveDoPrimitiveWithArgs, /* 119*/ (void *)primitiveFlushCacheSelective, /* 120*/ (void *)primitiveCalloutToFFI, /* 121*/ (void *)primitiveImageName, /* 122*/ (void *)primitiveNoop, /* 123*/ (void *)primitiveValueUninterruptably, /* 124*/ (void *)primitiveLowSpaceSemaphore, /* 125*/ (void *)primitiveSignalAtBytesLeft, /* 126*/ (void *)primitiveDeferDisplayUpdates, /* 127*/ (void *)primitiveShowDisplayRect, /* 128*/ (void *)primitiveArrayBecome, /* 129*/ (void *)primitiveSpecialObjectsOop, /* 130*/ (void *)primitiveFullGC, /* 131*/ (void *)primitiveIncrementalGC, /* 132*/ (void *)primitiveObjectPointsTo, /* 133*/ (void *)primitiveSetInterruptKey, /* 134*/ (void *)primitiveInterruptSemaphore, /* 135*/ (void *)primitiveMillisecondClock, /* 136*/ (void *)primitiveSignalAtMilliseconds, /* 137*/ (void *)primitiveSecondsClock, /* 138*/ (void *)primitiveSomeObject, /* 139*/ (void *)primitiveNextObject, /* 140*/ (void *)primitiveBeep, /* 141*/ (void *)primitiveClipboardText, /* 142*/ (void *)primitiveVMPath, /* 143*/ (void *)primitiveShortAt, /* 144*/ (void *)primitiveShortAtPut, /* 145*/ (void *)primitiveConstantFill, /* 146*/ (void *)primitiveObsoleteIndexedPrimitive, /* 147*/ (void *)primitiveObsoleteIndexedPrimitive, /* 148*/ (void *)primitiveClone, /* 149*/ (void *)primitiveGetAttribute, /* 150*/ (void *)primitiveObsoleteIndexedPrimitive, /* 151*/ (void *)primitiveObsoleteIndexedPrimitive, /* 152*/ (void *)primitiveObsoleteIndexedPrimitive, /* 153*/ (void *)primitiveObsoleteIndexedPrimitive, /* 154*/ (void *)primitiveObsoleteIndexedPrimitive, /* 155*/ (void *)primitiveObsoleteIndexedPrimitive, /* 156*/ (void *)primitiveObsoleteIndexedPrimitive, /* 157*/ (void *)primitiveObsoleteIndexedPrimitive, /* 158*/ (void *)primitiveObsoleteIndexedPrimitive, /* 159*/ (void *)primitiveObsoleteIndexedPrimitive, /* 160*/ (void *)primitiveObsoleteIndexedPrimitive, /* 161*/ (void *)primitiveObsoleteIndexedPrimitive, /* 162*/ (void *)primitiveObsoleteIndexedPrimitive, /* 163*/ (void *)primitiveObsoleteIndexedPrimitive, /* 164*/ (void *)primitiveObsoleteIndexedPrimitive, /* 165*/ (void *)primitiveIntegerAt, /* 166*/ (void *)primitiveIntegerAtPut, /* 167*/ (void *)primitiveYield, /* 168*/ (void *)primitiveCopyObject, /* 169*/ (void *)primitiveObsoleteIndexedPrimitive, /* 170*/ (void *)primitiveObsoleteIndexedPrimitive, /* 171*/ (void *)primitiveObsoleteIndexedPrimitive, /* 172*/ (void *)primitiveObsoleteIndexedPrimitive, /* 173*/ (void *)primitiveObsoleteIndexedPrimitive, /* 174*/ (void *)primitiveObsoleteIndexedPrimitive, /* 175*/ (void *)primitiveObsoleteIndexedPrimitive, /* 176*/ (void *)primitiveObsoleteIndexedPrimitive, /* 177*/ (void *)primitiveObsoleteIndexedPrimitive, /* 178*/ (void *)primitiveObsoleteIndexedPrimitive, /* 179*/ (void *)primitiveObsoleteIndexedPrimitive, /* 180*/ (void *)primitiveObsoleteIndexedPrimitive, /* 181*/ (void *)primitiveObsoleteIndexedPrimitive, /* 182*/ (void *)primitiveObsoleteIndexedPrimitive, /* 183*/ (void *)primitiveObsoleteIndexedPrimitive, /* 184*/ (void *)primitiveObsoleteIndexedPrimitive, /* 185*/ (void *)primitiveObsoleteIndexedPrimitive, /* 186*/ (void *)primitiveFail, /* 187*/ (void *)primitiveFail, /* 188*/ (void *)primitiveExecuteMethodArgsArray, /* 189*/ (void *)primitiveExecuteMethod, /* 190*/ (void *)primitiveObsoleteIndexedPrimitive, /* 191*/ (void *)primitiveObsoleteIndexedPrimitive, /* 192*/ (void *)primitiveObsoleteIndexedPrimitive, /* 193*/ (void *)primitiveObsoleteIndexedPrimitive, /* 194*/ (void *)primitiveObsoleteIndexedPrimitive, /* 195*/ (void *)primitiveFindNextUnwindContext, /* 196*/ (void *)primitiveTerminateTo, /* 197*/ (void *)primitiveFindHandlerContext, /* 198*/ (void *)primitiveMarkUnwindMethod, /* 199*/ (void *)primitiveMarkHandlerMethod, /* 200*/ (void *)primitiveClosureCopyWithCopiedValues, /* 201*/ (void *)primitiveClosureValue, /* 202*/ (void *)primitiveClosureValue, /* 203*/ (void *)primitiveClosureValue, /* 204*/ (void *)primitiveClosureValue, /* 205*/ (void *)primitiveClosureValue, /* 206*/ (void *)primitiveClosureValueWithArgs, /* 207*/ (void *)primitiveFail, /* 208*/ (void *)primitiveFail, /* 209*/ (void *)primitiveFail, /* 210*/ (void *)primitiveAt, /* 211*/ (void *)primitiveAtPut, /* 212*/ (void *)primitiveSize, /* 213*/ (void *)primitiveFail, /* 214*/ (void *)primitiveFail, /* 215*/ (void *)primitiveFail, /* 216*/ (void *)primitiveFail, /* 217*/ (void *)primitiveFail, /* 218*/ (void *)primitiveDoNamedPrimitiveWithArgs, /* 219*/ (void *)primitiveFail, /* 220*/ (void *)primitiveFail, /* 221*/ (void *)primitiveClosureValueNoContextSwitch, /* 222*/ (void *)primitiveClosureValueNoContextSwitch, /* 223*/ (void *)primitiveFail, /* 224*/ (void *)primitiveFail, /* 225*/ (void *)primitiveFail, /* 226*/ (void *)primitiveFail, /* 227*/ (void *)primitiveFail, /* 228*/ (void *)primitiveFail, /* 229*/ (void *)primitiveFail, /* 230*/ (void *)primitiveRelinquishProcessor, /* 231*/ (void *)primitiveForceDisplayUpdate, /* 232*/ (void *)primitiveFormPrint, /* 233*/ (void *)primitiveSetFullScreen, /* 234*/ (void *)primitiveObsoleteIndexedPrimitive, /* 235*/ (void *)primitiveObsoleteIndexedPrimitive, /* 236*/ (void *)primitiveObsoleteIndexedPrimitive, /* 237*/ (void *)primitiveObsoleteIndexedPrimitive, /* 238*/ (void *)primitiveObsoleteIndexedPrimitive, /* 239*/ (void *)primitiveObsoleteIndexedPrimitive, /* 240*/ (void *)primitiveObsoleteIndexedPrimitive, /* 241*/ (void *)primitiveObsoleteIndexedPrimitive, /* 242*/ (void *)primitiveFail, /* 243*/ (void *)primitiveObsoleteIndexedPrimitive, /* 244*/ (void *)primitiveObsoleteIndexedPrimitive, /* 245*/ (void *)primitiveObsoleteIndexedPrimitive, /* 246*/ (void *)primitiveObsoleteIndexedPrimitive, /* 247*/ (void *)primitiveSnapshotEmbedded, /* 248*/ (void *)primitiveInvokeObjectAsMethod, /* 249*/ (void *)primitiveArrayBecomeOneWayCopyHash, /* 250*/ (void *)clearProfile, /* 251*/ (void *)dumpProfile, /* 252*/ (void *)startProfiling, /* 253*/ (void *)stopProfiling, /* 254*/ (void *)primitiveVMParameter, /* 255*/ (void *)primitiveInstVarsPutFromStack, /* 256*/ (void *)primitivePushSelf, /* 257*/ (void *)primitivePushTrue, /* 258*/ (void *)primitivePushFalse, /* 259*/ (void *)primitivePushNil, /* 260*/ (void *)primitivePushMinusOne, /* 261*/ (void *)primitivePushZero, /* 262*/ (void *)primitivePushOne, /* 263*/ (void *)primitivePushTwo, /* 264*/ (void *)primitiveLoadInstVar, /* 265*/ (void *)primitiveLoadInstVar, /* 266*/ (void *)primitiveLoadInstVar, /* 267*/ (void *)primitiveLoadInstVar, /* 268*/ (void *)primitiveLoadInstVar, /* 269*/ (void *)primitiveLoadInstVar, /* 270*/ (void *)primitiveLoadInstVar, /* 271*/ (void *)primitiveLoadInstVar, /* 272*/ (void *)primitiveLoadInstVar, /* 273*/ (void *)primitiveLoadInstVar, /* 274*/ (void *)primitiveLoadInstVar, /* 275*/ (void *)primitiveLoadInstVar, /* 276*/ (void *)primitiveLoadInstVar, /* 277*/ (void *)primitiveLoadInstVar, /* 278*/ (void *)primitiveLoadInstVar, /* 279*/ (void *)primitiveLoadInstVar, /* 280*/ (void *)primitiveLoadInstVar, /* 281*/ (void *)primitiveLoadInstVar, /* 282*/ (void *)primitiveLoadInstVar, /* 283*/ (void *)primitiveLoadInstVar, /* 284*/ (void *)primitiveLoadInstVar, /* 285*/ (void *)primitiveLoadInstVar, /* 286*/ (void *)primitiveLoadInstVar, /* 287*/ (void *)primitiveLoadInstVar, /* 288*/ (void *)primitiveLoadInstVar, /* 289*/ (void *)primitiveLoadInstVar, /* 290*/ (void *)primitiveLoadInstVar, /* 291*/ (void *)primitiveLoadInstVar, /* 292*/ (void *)primitiveLoadInstVar, /* 293*/ (void *)primitiveLoadInstVar, /* 294*/ (void *)primitiveLoadInstVar, /* 295*/ (void *)primitiveLoadInstVar, /* 296*/ (void *)primitiveLoadInstVar, /* 297*/ (void *)primitiveLoadInstVar, /* 298*/ (void *)primitiveLoadInstVar, /* 299*/ (void *)primitiveLoadInstVar, /* 300*/ (void *)primitiveLoadInstVar, /* 301*/ (void *)primitiveLoadInstVar, /* 302*/ (void *)primitiveLoadInstVar, /* 303*/ (void *)primitiveLoadInstVar, /* 304*/ (void *)primitiveLoadInstVar, /* 305*/ (void *)primitiveLoadInstVar, /* 306*/ (void *)primitiveLoadInstVar, /* 307*/ (void *)primitiveLoadInstVar, /* 308*/ (void *)primitiveLoadInstVar, /* 309*/ (void *)primitiveLoadInstVar, /* 310*/ (void *)primitiveLoadInstVar, /* 311*/ (void *)primitiveLoadInstVar, /* 312*/ (void *)primitiveLoadInstVar, /* 313*/ (void *)primitiveLoadInstVar, /* 314*/ (void *)primitiveLoadInstVar, /* 315*/ (void *)primitiveLoadInstVar, /* 316*/ (void *)primitiveLoadInstVar, /* 317*/ (void *)primitiveLoadInstVar, /* 318*/ (void *)primitiveLoadInstVar, /* 319*/ (void *)primitiveLoadInstVar, /* 320*/ (void *)primitiveLoadInstVar, /* 321*/ (void *)primitiveLoadInstVar, /* 322*/ (void *)primitiveLoadInstVar, /* 323*/ (void *)primitiveLoadInstVar, /* 324*/ (void *)primitiveLoadInstVar, /* 325*/ (void *)primitiveLoadInstVar, /* 326*/ (void *)primitiveLoadInstVar, /* 327*/ (void *)primitiveLoadInstVar, /* 328*/ (void *)primitiveLoadInstVar, /* 329*/ (void *)primitiveLoadInstVar, /* 330*/ (void *)primitiveLoadInstVar, /* 331*/ (void *)primitiveLoadInstVar, /* 332*/ (void *)primitiveLoadInstVar, /* 333*/ (void *)primitiveLoadInstVar, /* 334*/ (void *)primitiveLoadInstVar, /* 335*/ (void *)primitiveLoadInstVar, /* 336*/ (void *)primitiveLoadInstVar, /* 337*/ (void *)primitiveLoadInstVar, /* 338*/ (void *)primitiveLoadInstVar, /* 339*/ (void *)primitiveLoadInstVar, /* 340*/ (void *)primitiveLoadInstVar, /* 341*/ (void *)primitiveLoadInstVar, /* 342*/ (void *)primitiveLoadInstVar, /* 343*/ (void *)primitiveLoadInstVar, /* 344*/ (void *)primitiveLoadInstVar, /* 345*/ (void *)primitiveLoadInstVar, /* 346*/ (void *)primitiveLoadInstVar, /* 347*/ (void *)primitiveLoadInstVar, /* 348*/ (void *)primitiveLoadInstVar, /* 349*/ (void *)primitiveLoadInstVar, /* 350*/ (void *)primitiveLoadInstVar, /* 351*/ (void *)primitiveLoadInstVar, /* 352*/ (void *)primitiveLoadInstVar, /* 353*/ (void *)primitiveLoadInstVar, /* 354*/ (void *)primitiveLoadInstVar, /* 355*/ (void *)primitiveLoadInstVar, /* 356*/ (void *)primitiveLoadInstVar, /* 357*/ (void *)primitiveLoadInstVar, /* 358*/ (void *)primitiveLoadInstVar, /* 359*/ (void *)primitiveLoadInstVar, /* 360*/ (void *)primitiveLoadInstVar, /* 361*/ (void *)primitiveLoadInstVar, /* 362*/ (void *)primitiveLoadInstVar, /* 363*/ (void *)primitiveLoadInstVar, /* 364*/ (void *)primitiveLoadInstVar, /* 365*/ (void *)primitiveLoadInstVar, /* 366*/ (void *)primitiveLoadInstVar, /* 367*/ (void *)primitiveLoadInstVar, /* 368*/ (void *)primitiveLoadInstVar, /* 369*/ (void *)primitiveLoadInstVar, /* 370*/ (void *)primitiveLoadInstVar, /* 371*/ (void *)primitiveLoadInstVar, /* 372*/ (void *)primitiveLoadInstVar, /* 373*/ (void *)primitiveLoadInstVar, /* 374*/ (void *)primitiveLoadInstVar, /* 375*/ (void *)primitiveLoadInstVar, /* 376*/ (void *)primitiveLoadInstVar, /* 377*/ (void *)primitiveLoadInstVar, /* 378*/ (void *)primitiveLoadInstVar, /* 379*/ (void *)primitiveLoadInstVar, /* 380*/ (void *)primitiveLoadInstVar, /* 381*/ (void *)primitiveLoadInstVar, /* 382*/ (void *)primitiveLoadInstVar, /* 383*/ (void *)primitiveLoadInstVar, /* 384*/ (void *)primitiveLoadInstVar, /* 385*/ (void *)primitiveLoadInstVar, /* 386*/ (void *)primitiveLoadInstVar, /* 387*/ (void *)primitiveLoadInstVar, /* 388*/ (void *)primitiveLoadInstVar, /* 389*/ (void *)primitiveLoadInstVar, /* 390*/ (void *)primitiveLoadInstVar, /* 391*/ (void *)primitiveLoadInstVar, /* 392*/ (void *)primitiveLoadInstVar, /* 393*/ (void *)primitiveLoadInstVar, /* 394*/ (void *)primitiveLoadInstVar, /* 395*/ (void *)primitiveLoadInstVar, /* 396*/ (void *)primitiveLoadInstVar, /* 397*/ (void *)primitiveLoadInstVar, /* 398*/ (void *)primitiveLoadInstVar, /* 399*/ (void *)primitiveLoadInstVar, /* 400*/ (void *)primitiveLoadInstVar, /* 401*/ (void *)primitiveLoadInstVar, /* 402*/ (void *)primitiveLoadInstVar, /* 403*/ (void *)primitiveLoadInstVar, /* 404*/ (void *)primitiveLoadInstVar, /* 405*/ (void *)primitiveLoadInstVar, /* 406*/ (void *)primitiveLoadInstVar, /* 407*/ (void *)primitiveLoadInstVar, /* 408*/ (void *)primitiveLoadInstVar, /* 409*/ (void *)primitiveLoadInstVar, /* 410*/ (void *)primitiveLoadInstVar, /* 411*/ (void *)primitiveLoadInstVar, /* 412*/ (void *)primitiveLoadInstVar, /* 413*/ (void *)primitiveLoadInstVar, /* 414*/ (void *)primitiveLoadInstVar, /* 415*/ (void *)primitiveLoadInstVar, /* 416*/ (void *)primitiveLoadInstVar, /* 417*/ (void *)primitiveLoadInstVar, /* 418*/ (void *)primitiveLoadInstVar, /* 419*/ (void *)primitiveLoadInstVar, /* 420*/ (void *)primitiveLoadInstVar, /* 421*/ (void *)primitiveLoadInstVar, /* 422*/ (void *)primitiveLoadInstVar, /* 423*/ (void *)primitiveLoadInstVar, /* 424*/ (void *)primitiveLoadInstVar, /* 425*/ (void *)primitiveLoadInstVar, /* 426*/ (void *)primitiveLoadInstVar, /* 427*/ (void *)primitiveLoadInstVar, /* 428*/ (void *)primitiveLoadInstVar, /* 429*/ (void *)primitiveLoadInstVar, /* 430*/ (void *)primitiveLoadInstVar, /* 431*/ (void *)primitiveLoadInstVar, /* 432*/ (void *)primitiveLoadInstVar, /* 433*/ (void *)primitiveLoadInstVar, /* 434*/ (void *)primitiveLoadInstVar, /* 435*/ (void *)primitiveLoadInstVar, /* 436*/ (void *)primitiveLoadInstVar, /* 437*/ (void *)primitiveLoadInstVar, /* 438*/ (void *)primitiveLoadInstVar, /* 439*/ (void *)primitiveLoadInstVar, /* 440*/ (void *)primitiveLoadInstVar, /* 441*/ (void *)primitiveLoadInstVar, /* 442*/ (void *)primitiveLoadInstVar, /* 443*/ (void *)primitiveLoadInstVar, /* 444*/ (void *)primitiveLoadInstVar, /* 445*/ (void *)primitiveLoadInstVar, /* 446*/ (void *)primitiveLoadInstVar, /* 447*/ (void *)primitiveLoadInstVar, /* 448*/ (void *)primitiveLoadInstVar, /* 449*/ (void *)primitiveLoadInstVar, /* 450*/ (void *)primitiveLoadInstVar, /* 451*/ (void *)primitiveLoadInstVar, /* 452*/ (void *)primitiveLoadInstVar, /* 453*/ (void *)primitiveLoadInstVar, /* 454*/ (void *)primitiveLoadInstVar, /* 455*/ (void *)primitiveLoadInstVar, /* 456*/ (void *)primitiveLoadInstVar, /* 457*/ (void *)primitiveLoadInstVar, /* 458*/ (void *)primitiveLoadInstVar, /* 459*/ (void *)primitiveLoadInstVar, /* 460*/ (void *)primitiveLoadInstVar, /* 461*/ (void *)primitiveLoadInstVar, /* 462*/ (void *)primitiveLoadInstVar, /* 463*/ (void *)primitiveLoadInstVar, /* 464*/ (void *)primitiveLoadInstVar, /* 465*/ (void *)primitiveLoadInstVar, /* 466*/ (void *)primitiveLoadInstVar, /* 467*/ (void *)primitiveLoadInstVar, /* 468*/ (void *)primitiveLoadInstVar, /* 469*/ (void *)primitiveLoadInstVar, /* 470*/ (void *)primitiveLoadInstVar, /* 471*/ (void *)primitiveLoadInstVar, /* 472*/ (void *)primitiveLoadInstVar, /* 473*/ (void *)primitiveLoadInstVar, /* 474*/ (void *)primitiveLoadInstVar, /* 475*/ (void *)primitiveLoadInstVar, /* 476*/ (void *)primitiveLoadInstVar, /* 477*/ (void *)primitiveLoadInstVar, /* 478*/ (void *)primitiveLoadInstVar, /* 479*/ (void *)primitiveLoadInstVar, /* 480*/ (void *)primitiveLoadInstVar, /* 481*/ (void *)primitiveLoadInstVar, /* 482*/ (void *)primitiveLoadInstVar, /* 483*/ (void *)primitiveLoadInstVar, /* 484*/ (void *)primitiveLoadInstVar, /* 485*/ (void *)primitiveLoadInstVar, /* 486*/ (void *)primitiveLoadInstVar, /* 487*/ (void *)primitiveLoadInstVar, /* 488*/ (void *)primitiveLoadInstVar, /* 489*/ (void *)primitiveLoadInstVar, /* 490*/ (void *)primitiveLoadInstVar, /* 491*/ (void *)primitiveLoadInstVar, /* 492*/ (void *)primitiveLoadInstVar, /* 493*/ (void *)primitiveLoadInstVar, /* 494*/ (void *)primitiveLoadInstVar, /* 495*/ (void *)primitiveLoadInstVar, /* 496*/ (void *)primitiveLoadInstVar, /* 497*/ (void *)primitiveLoadInstVar, /* 498*/ (void *)primitiveLoadInstVar, /* 499*/ (void *)primitiveLoadInstVar, /* 500*/ (void *)primitiveLoadInstVar, /* 501*/ (void *)primitiveLoadInstVar, /* 502*/ (void *)primitiveLoadInstVar, /* 503*/ (void *)primitiveLoadInstVar, /* 504*/ (void *)primitiveLoadInstVar, /* 505*/ (void *)primitiveLoadInstVar, /* 506*/ (void *)primitiveLoadInstVar, /* 507*/ (void *)primitiveLoadInstVar, /* 508*/ (void *)primitiveLoadInstVar, /* 509*/ (void *)primitiveLoadInstVar, /* 510*/ (void *)primitiveLoadInstVar, /* 511*/ (void *)primitiveLoadInstVar, /* 512*/ (void *)primitiveLoadInstVar, /* 513*/ (void *)primitiveLoadInstVar, /* 514*/ (void *)primitiveLoadInstVar, /* 515*/ (void *)primitiveLoadInstVar, /* 516*/ (void *)primitiveLoadInstVar, /* 517*/ (void *)primitiveLoadInstVar, /* 518*/ (void *)primitiveLoadInstVar, /* 519*/ (void *)primitiveLoadInstVar, /* 520*/ (void *)primitiveFail, /* 521*/ (void *)primitiveObsoleteIndexedPrimitive, /* 522*/ (void *)primitiveObsoleteIndexedPrimitive, /* 523*/ (void *)primitiveObsoleteIndexedPrimitive, /* 524*/ (void *)primitiveObsoleteIndexedPrimitive, /* 525*/ (void *)primitiveObsoleteIndexedPrimitive, /* 526*/ (void *)primitiveObsoleteIndexedPrimitive, /* 527*/ (void *)primitiveObsoleteIndexedPrimitive, /* 528*/ (void *)primitiveObsoleteIndexedPrimitive, /* 529*/ (void *)primitiveObsoleteIndexedPrimitive, /* 530*/ (void *)primitiveFail, /* 531*/ (void *)primitiveFail, /* 532*/ (void *)primitiveFail, /* 533*/ (void *)primitiveFail, /* 534*/ (void *)primitiveFail, /* 535*/ (void *)primitiveFail, /* 536*/ (void *)primitiveFail, /* 537*/ (void *)primitiveFail, /* 538*/ (void *)primitiveFail, /* 539*/ (void *)primitiveFail, /* 540*/ (void *)primitiveObsoleteIndexedPrimitive, /* 541*/ (void *)primitiveObsoleteIndexedPrimitive, /* 542*/ (void *)primitiveObsoleteIndexedPrimitive, /* 543*/ (void *)primitiveObsoleteIndexedPrimitive, /* 544*/ (void *)primitiveObsoleteIndexedPrimitive, /* 545*/ (void *)primitiveObsoleteIndexedPrimitive, /* 546*/ (void *)primitiveFail, /* 547*/ (void *)primitiveFail, /* 548*/ (void *)primitiveObsoleteIndexedPrimitive, /* 549*/ (void *)primitiveObsoleteIndexedPrimitive, /* 550*/ (void *)primitiveObsoleteIndexedPrimitive, /* 551*/ (void *)primitiveObsoleteIndexedPrimitive, /* 552*/ (void *)primitiveObsoleteIndexedPrimitive, /* 553*/ (void *)primitiveObsoleteIndexedPrimitive, /* 554*/ (void *)primitiveFail, /* 555*/ (void *)primitiveFail, /* 556*/ (void *)primitiveFail, /* 557*/ (void *)primitiveFail, /* 558*/ (void *)primitiveFail, /* 559*/ (void *)primitiveFail, /* 560*/ (void *)primitiveFail, /* 561*/ (void *)primitiveFail, /* 562*/ (void *)primitiveFail, /* 563*/ (void *)primitiveFail, /* 564*/ (void *)primitiveFail, /* 565*/ (void *)primitiveFail, /* 566*/ (void *)primitiveFail, /* 567*/ (void *)primitiveFail, /* 568*/ (void *)primitiveFail, /* 569*/ (void *)primitiveFail, /* 570*/ (void *)primitiveFlushExternalPrimitives, /* 571*/ (void *)primitiveUnloadModule, /* 572*/ (void *)primitiveListBuiltinModule, /* 573*/ (void *)primitiveListExternalModule, /* 574*/ (void *)primitiveFail, /* 575*/ (void *)primitiveFail, 0 }; usqInt memory; void* showSurfaceFn; /* Return the accessible object following the given object or free chunk in the heap. Return nil when heap is exhausted. */ sqInt accessibleObjectAfter(sqInt oop) { register struct foo * foo = &fum; sqInt obj; sqInt sz; sqInt sz1; sqInt header; sqInt header1; /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz1 = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } obj = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { return obj; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(obj); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } return null; } /* Similar to activateNewMethod but for Closure and newMethod. */ sqInt activateNewClosureMethod(sqInt blockClosure) { register struct foo * foo = &fum; sqInt numCopied; sqInt where; sqInt i; sqInt theBlockClosure; sqInt closureMethod; sqInt newContext; sqInt methodHeader; sqInt outerContext; sqInt oop; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; if (DoAssertionChecks) { okayOop(blockClosure); } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (DoAssertionChecks) { okayOop(outerContext); } closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); methodHeader = longAt((closureMethod + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = blockClosure; /* All for one, and one for all! */ /* allocateOrRecycleContext: may cause a GC; restore blockClosure and refetch outerContext et al */ newContext = allocateOrRecycleContext(methodHeader & LargeContextBit); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; theBlockClosure = oop; outerContext = longAt((theBlockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); /* Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores. */ numCopied = (fetchWordLengthOf(theBlockClosure)) - ClosureFirstCopiedValueIndex; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), longAt((theBlockClosure + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)))); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), (((foo->argumentCount + numCopied) << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), theBlockClosure); longAtput(where + (ReceiverIndex << (SHIFT_FOR_WORD)), longAt((outerContext + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD)))); for (i = 1; i <= foo->argumentCount; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAt(foo->stackPointer - ((foo->argumentCount - i) * (BYTES_PER_WORD)))); } where = (newContext + (BASE_HEADER_SIZE)) + (((ReceiverIndex + 1) + foo->argumentCount) << (SHIFT_FOR_WORD)); for (i = 0; i <= (numCopied - 1); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), longAt((theBlockClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)))); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin fetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } sqInt activateNewMethod(void) { register struct foo * foo = &fum; sqInt tempCount; sqInt nilOop; sqInt where; sqInt initialIP; sqInt i; sqInt newContext; sqInt methodHeader; sqInt methodPointer; sqInt tmp; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; /* begin headerOf: */ methodPointer = foo->newMethod; methodHeader = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); newContext = allocateOrRecycleContext(methodHeader & LargeContextBit); initialIP = ((LiteralStart + ((((usqInt) methodHeader) >> 10) & 255)) * (BYTES_PER_WORD)) + 1; /* Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores. */ tempCount = (((usqInt) methodHeader) >> 19) & 63; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), ((tempCount << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), foo->newMethod); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), foo->nilObj); for (i = 0; i <= foo->argumentCount; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAt(foo->stackPointer - ((foo->argumentCount - i) * (BYTES_PER_WORD)))); } nilOop = foo->nilObj; for (i = ((foo->argumentCount + 1) + ReceiverIndex); i <= (tempCount + ReceiverIndex); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), nilOop); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); foo->reclaimableContextCount += 1; /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin fetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } /* Add the given variable location to the extra roots table */ EXPORT(sqInt) addGCRoot(sqInt *varLoc) { register struct foo * foo = &fum; if (foo->extraRootCount >= ExtraRootSize) { return 0; } foo->extraRoots[foo->extraRootCount += 1] = varLoc; return 1; } /* Add the given entry to the method cache. The policy is as follows: Look for an empty entry anywhere in the reprobe chain. If found, install the new entry there. If not found, then install the new entry at the first probe position and delete the entries in the rest of the reprobe chain. This has two useful purposes: If there is active contention over the first slot, the second or third will likely be free for reentry after ejection. Also, flushing is good when reprobe chains are getting full. */ sqInt addNewMethodToCache(void) { register struct foo * foo = &fum; sqInt hash; sqInt p; sqInt probe; foo->compilerInitialized && (compilerTranslateMethod()); /* drop low-order zeros from addresses */ hash = foo->messageSelector ^ foo->lkupClass; foo->primitiveFunctionPointer = primitiveTable[foo->primitiveIndex]; for (p = 0; p <= (CacheProbeMax - 1); p += 1) { probe = (((usqInt) hash) >> p) & MethodCacheMask; if ((foo->methodCache[probe + MethodCacheSelector]) == 0) { foo->methodCache[probe + MethodCacheSelector] = foo->messageSelector; foo->methodCache[probe + MethodCacheClass] = foo->lkupClass; foo->methodCache[probe + MethodCacheMethod] = foo->newMethod; foo->methodCache[probe + MethodCachePrim] = foo->primitiveIndex; foo->methodCache[probe + MethodCacheNative] = foo->newNativeMethod; foo->methodCache[probe + MethodCachePrimFunction] = (((long) foo->primitiveFunctionPointer)); return null; } } /* first probe */ probe = hash & MethodCacheMask; foo->methodCache[probe + MethodCacheSelector] = foo->messageSelector; foo->methodCache[probe + MethodCacheClass] = foo->lkupClass; foo->methodCache[probe + MethodCacheMethod] = foo->newMethod; foo->methodCache[probe + MethodCachePrim] = foo->primitiveIndex; foo->methodCache[probe + MethodCacheNative] = foo->newNativeMethod; foo->methodCache[probe + MethodCachePrimFunction] = (((long) foo->primitiveFunctionPointer)); for (p = 1; p <= (CacheProbeMax - 1); p += 1) { probe = (((usqInt) hash) >> p) & MethodCacheMask; foo->methodCache[probe + MethodCacheSelector] = 0; } } /* Add the given function address to the external primitive table and return the index where it's stored. This function doesn't need to be fast since it is only called when an external primitive has been looked up (which takes quite a bit of time itself). So there's nothing specifically complicated here. Note: Return index will be one-based (ST convention) */ sqInt addToExternalPrimitiveTable(void *functionAddress) { register struct foo * foo = &fum; sqInt i; for (i = 0; i <= (MaxExternalPrimitiveTableSize - 1); i += 1) { if ((foo->externalPrimitiveTable[i]) == 0) { foo->externalPrimitiveTable[i] = functionAddress; return i + 1; } } return 0; } /* Adjust all oop references by the given number of bytes. This is done just after reading in an image when the new base address of the object heap is different from the base address in the image. */ /* di 11/18/2000 - return number of objects found */ sqInt adjustAllOopsBy(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt oop; sqInt totalObjects; sqInt fieldAddr; sqInt classHeader; sqInt fieldOop; sqInt newClassOop; sqInt sz; sqInt header; if (bytesToShift == 0) { return 300000; } totalObjects = 0; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { totalObjects += 1; /* begin adjustFieldsAndClassOf:by: */ if (bytesToShift == 0) { goto l1; } fieldAddr = oop + (lastPointerOf(oop)); while ((((usqInt) fieldAddr)) > (((usqInt) oop))) { fieldOop = longAt(fieldAddr); if (!((fieldOop & 1))) { longAtput(fieldAddr, fieldOop + bytesToShift); } fieldAddr -= BYTES_PER_WORD; } if (((longAt(oop)) & TypeMask) != HeaderTypeShort) { classHeader = longAt(oop - (BYTES_PER_WORD)); newClassOop = (classHeader & (ALL_BUT_TYPE_MASK)) + bytesToShift; longAtput(oop - (BYTES_PER_WORD), newClassOop | (classHeader & TypeMask)); } l1: /* end adjustFieldsAndClassOf:by: */; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } return totalObjects; } /* Return true if all the oops in both arrays, and the arrays themselves, are in the young object space. */ sqInt allYoungand(sqInt array1, sqInt array2) { register struct foo * foo = &fum; sqInt fieldOffset; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; if ((((usqInt) array1)) < (((usqInt) foo->youngStart))) { return 0; } if ((((usqInt) array2)) < (((usqInt) foo->youngStart))) { return 0; } /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l2; } contextSize = (sp >> 1); l2: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { fieldOffset = 0; goto l4; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { if ((((usqInt) (longAt(array1 + fieldOffset)))) < (((usqInt) foo->youngStart))) { return 0; } if ((((usqInt) (longAt(array2 + fieldOffset)))) < (((usqInt) foo->youngStart))) { return 0; } fieldOffset -= BYTES_PER_WORD; } return 1; } /* Allocate a chunk of the given size. Sender must be sure that the requested size includes enough space for the header word(s). */ /* Details: To limit the time per incremental GC, do one every so many allocations. The number is settable via primitiveVMParameter to tune your memory system */ sqInt allocateChunk(sqInt byteSize) { register struct foo * foo = &fum; sqInt newFreeSize; sqInt enoughSpace; sqInt newChunk; usqInt minFree; sqInt sched; sqInt lastSavedProcess; sqInt currentProc; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + byteSize) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { /* signal that space is running low, but proceed with allocation if possible */ foo->signalLowSpace = 1; /* disable additional interrupts until lowSpaceThreshold is reset by image */ foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lastSavedProcess = longAt((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop3 = foo->specialObjectsOop; if ((((usqInt) oop3)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop3, currentProc); } longAtput((oop3 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), byteSize + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - byteSize; newChunk = foo->freeBlock; /* Assume: client will initialize object header of free chunk, so following is not needed: */ /* self setSizeOfFree: newChunk to: byteSize. */ foo->freeBlock += byteSize; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; return newChunk; } /* Return a recycled context or a newly allocated one if none is available for recycling. */ sqInt allocateOrRecycleContext(sqInt needsLarge) { register struct foo * foo = &fum; sqInt cntxt; sqInt valuePointer; if (needsLarge == 0) { if (foo->freeContexts != NilContext) { cntxt = foo->freeContexts; foo->freeContexts = longAt((cntxt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); return cntxt; } } else { if (foo->freeLargeContexts != NilContext) { cntxt = foo->freeLargeContexts; foo->freeLargeContexts = longAt((cntxt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); return cntxt; } } if (needsLarge == 0) { cntxt = instantiateContextsizeInBytes(fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop), SMALL_CONTEXT_SIZE); } else { cntxt = instantiateContextsizeInBytes(fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop), LARGE_CONTEXT_SIZE); } /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->nilObj; longAtput((cntxt + (BASE_HEADER_SIZE)) + (4 << (SHIFT_FOR_WORD)), valuePointer); return cntxt; } sqInt argumentCountOf(sqInt methodPointer) { return (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 25) & 15; } /* Return the address of first indexable field of resulting array object, or fail if the instance variable does not contain an indexable bytes or words object. */ /* Note: May be called by translated primitive code. */ void * arrayValueOf(sqInt arrayOop) { if ((!((arrayOop & 1))) && (((arrayOop & 1) == 0) && (isWordsOrBytesNonInt(arrayOop)))) { return pointerForOop(arrayOop + (BASE_HEADER_SIZE)); } /* begin primitiveFail */ foo->successFlag = 0; } /* Returns an integer object */ sqInt asciiOfCharacter(sqInt characterObj) { register struct foo * foo = &fum; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop; /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassCharacter << (SHIFT_FOR_WORD))); if ((characterObj & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(characterObj))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(characterObj - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { return longAt((characterObj + (BASE_HEADER_SIZE)) + (CharacterValueIndex << (SHIFT_FOR_WORD))); } else { return ConstZero; } } /* Return true if the stack is still balanced after executing primitive primIndex with nArgs args. Delta is 'stackPointer - activeContext' which is a relative measure for the stack pointer (so we don't have to relocate it during the primitive) */ sqInt balancedStackafterPrimitivewithArgs(sqInt delta, sqInt primIdx, sqInt nArgs) { register struct foo * foo = &fum; if ((primIdx >= 81) && (primIdx <= 88)) { return 1; } if (foo->successFlag) { return ((foo->stackPointer - foo->activeContext) + (nArgs * (BYTES_PER_WORD))) == delta; } return (foo->stackPointer - foo->activeContext) == delta; } /* Answer the size of an object memory header word in bytes. */ sqInt baseHeaderSize(void) { /* inline: */; return BASE_HEADER_SIZE; } /* If this object is old, mark it as a root (because a new object may be stored into it) */ sqInt beRootIfOld(sqInt oop) { register struct foo * foo = &fum; sqInt header; if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && (!((oop & 1)))) { /* begin noteAsRoot:headerLoc: */ header = longAt(oop); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } /* Record that the given oop in the old object area points to an object in the young area when oop may be forwarded. */ /* Warning: No young objects should be recorded as roots. Callers are responsible for ensuring this constraint is not violated. */ sqInt beRootWhileForwarding(sqInt oop) { register struct foo * foo = &fum; sqInt header; sqInt fwdBlock; sqInt header1; sqInt header2; header = longAt(oop); if ((header & (MARK_BIT)) != 0) { /* This oop is forwarded */ fwdBlock = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } /* begin noteAsRoot:headerLoc: */ header1 = longAt(fwdBlock + (BYTES_PER_WORD)); if ((header1 & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(fwdBlock + (BYTES_PER_WORD), header1 | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(fwdBlock + (BYTES_PER_WORD), header1 | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } else { /* begin noteAsRoot:headerLoc: */ header2 = longAt(oop); if ((header2 & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header2 | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header2 | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } sqInt becomewith(sqInt array1, sqInt array2) { return becomewithtwoWaycopyHash(array1, array2, 1, 1); } /* All references to each object in array1 are swapped with all references to the corresponding object in array2. That is, all pointers to one object are replaced with with pointers to the other. The arguments must be arrays of the same length. Returns true if the primitive succeeds. */ /* Implementation: Uses forwarding blocks to update references as done in compaction. */ sqInt becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag) { register struct foo * foo = &fum; sqInt hdr1; sqInt fieldOffset; sqInt oop1; sqInt hdr2; sqInt oop2; sqInt hdr11; sqInt oop11; sqInt hdr21; sqInt fwdBlock; sqInt oop21; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; if (!(((array1 & 1) == 0) && (((((usqInt) (longAt(array1))) >> 8) & 15) == 2))) { return 0; } if (!(((array2 & 1) == 0) && (((((usqInt) (longAt(array2))) >> 8) & 15) == 2))) { return 0; } if (!((lastPointerOf(array1)) == (lastPointerOf(array2)))) { return 0; } if (!(containOnlyOopsand(array1, array2))) { return 0; } if (!(prepareForwardingTableForBecomingwithtwoWay(array1, array2, twoWayFlag))) { return 0; } if (allYoungand(array1, array2)) { mapPointersInObjectsFromto(foo->youngStart, foo->endOfMemory); } else { mapPointersInObjectsFromto(memory, foo->endOfMemory); } if (twoWayFlag) { /* begin restoreHeadersAfterBecoming:with: */ /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l2; } contextSize = (sp >> 1); l2: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { fieldOffset = 0; goto l4; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { oop1 = longAt(array1 + fieldOffset); oop2 = longAt(array2 + fieldOffset); if (!(oop1 == oop2)) { restoreHeaderOf(oop1); restoreHeaderOf(oop2); hdr1 = longAt(oop1); hdr2 = longAt(oop2); longAtput(oop1, (hdr1 & (ALL_BUT_HASH_BITS)) | (hdr2 & HashBits)); longAtput(oop2, (hdr2 & (ALL_BUT_HASH_BITS)) | (hdr1 & HashBits)); } fieldOffset -= BYTES_PER_WORD; } } else { /* begin restoreHeadersAfterForwardBecome: */ fwdBlock = ((foo->endOfMemory + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); fwdBlock += (BYTES_PER_WORD) * 4; while ((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) { oop11 = longAt(fwdBlock + ((BYTES_PER_WORD) * 2)); oop21 = longAt(fwdBlock); restoreHeaderOf(oop11); if (copyHashFlag) { hdr11 = longAt(oop11); hdr21 = longAt(oop21); longAtput(oop21, (hdr21 & (ALL_BUT_HASH_BITS)) | (hdr11 & HashBits)); } fwdBlock += (BYTES_PER_WORD) * 4; } } initializeMemoryFirstFree(foo->freeBlock); /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; return 1; } sqInt biasToGrow(void) { register struct foo * foo = &fum; usqInt growSize; growSize = (((sqInt) (foo->growHeadroom * 3) >> 1)) - ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)); if (growSize > 0) { growObjectMemory(growSize); } } /* convert true and false (Smalltalk) to true or false(C) */ sqInt booleanValueOf(sqInt obj) { register struct foo * foo = &fum; if (obj == foo->trueObj) { return 1; } if (obj == foo->falseObj) { return 0; } foo->successFlag = 0; return null; } sqInt byteSizeOf(sqInt oop) { sqInt slots; sqInt header; sqInt sz; flag("Dan"); if ((oop & 1)) { return 0; } /* begin slotSizeOf: */ if ((oop & 1)) { slots = 0; goto l1; } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { slots = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { slots = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { slots = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; l1: /* end slotSizeOf: */; if (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8) { return slots; } else { return slots * 4; } } /* Byte-swap the words of all bytes objects in a range of the image, including Strings, ByteArrays, and CompiledMethods. This returns these objects to their original byte ordering after blindly byte-swapping the entire image. For compiled methods, byte-swap only their bytecodes part. */ sqInt byteSwapByteObjectsFromto(sqInt startOop, sqInt stopAddr) { register struct foo * foo = &fum; sqInt oop; sqInt fmt; sqInt methodHeader; sqInt wordAddr; sqInt stopAddr1; sqInt addr; sqInt stopAddr2; sqInt addr1; sqInt sz; sqInt header; oop = startOop; while ((((usqInt) oop)) < (((usqInt) stopAddr))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { fmt = (((usqInt) (longAt(oop))) >> 8) & 15; if (fmt >= 8) { /* oop contains bytes */ wordAddr = oop + (BASE_HEADER_SIZE); if (fmt >= 12) { /* compiled method; start after methodHeader and literals */ methodHeader = longAt(oop + (BASE_HEADER_SIZE)); wordAddr = (wordAddr + (BYTES_PER_WORD)) + (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)); } /* begin reverseBytesFrom:to: */ stopAddr1 = oop + (sizeBitsOf(oop)); flag("Dan"); addr = wordAddr; while ((((usqInt) addr)) < (((usqInt) stopAddr1))) { longAtput(addr, byteSwapped(longAt(addr))); addr += BYTES_PER_WORD; } } if ((fmt == 6) && ((BYTES_PER_WORD) == 8)) { /* Object contains 32-bit half-words packed into 64-bit machine words. */ wordAddr = oop + (BASE_HEADER_SIZE); /* begin reverseWordsFrom:to: */ stopAddr2 = oop + (sizeBitsOf(oop)); addr1 = wordAddr; while ((((usqInt) addr1)) < (((usqInt) stopAddr2))) { longAtput(addr1, wordSwapped(longAt(addr1))); addr1 += BYTES_PER_WORD; } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } } /* Answer the given integer with its bytes in the reverse order. */ sqInt byteSwapped(sqInt w) { # if (BYTES_PER_WORD == 4) // swap bytes in an object word return ((((((usqInt) w >> 24)) & Byte0Mask) + ((((usqInt) w >> 8)) & Byte1Mask)) + ((((usqInt) w << 8)) & Byte2Mask)) + ((((usqInt) w << 24)) & Byte3Mask); # else return ((((((((((usqInt) w >> 56)) & Byte0Mask) + ((((usqInt) w >> 40)) & Byte1Mask)) + ((((usqInt) w >> 24)) & Byte2Mask)) + ((((usqInt) w >> 8)) & Byte3Mask)) + ((((usqInt) w << 8)) & Byte4Mask)) + ((((usqInt) w << 24)) & Byte5Mask)) + ((((usqInt) w << 40)) & Byte6Mask)) + ((((usqInt) w << 56)) & Byte7Mask); # endif // BYTES_PER_WORD == 4 } /* Answer the size of an object memory word in bytes. */ sqInt bytesPerWord(void) { /* inline: */; return BYTES_PER_WORD; } /* Call the external plugin function identified. In the VM this is an address, see InterpreterSimulator for it's version. */ sqInt callExternalPrimitive(void * functionID) { dispatchFunctionPointer(functionID); } /* External call into the interpreter */ EXPORT(sqInt) callInterpreter(void) { interpret(); } /* Re-enter the interpreter for executing a callback */ EXPORT(sqInt) callbackEnter(sqInt *callbackID) { register struct foo * foo = &fum; sqInt activeProc; sqInt result; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; sqInt processLists; sqInt priority; sqInt processList; sqInt oop6; sqInt oop11; sqInt lastLink; sqInt oop21; if (foo->primitiveIndex == 0) { return 0; } if (foo->jmpDepth >= foo->jmpMax) { return 0; } /* Suspend the currently active process */ foo->jmpDepth += 1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop2 = longAt((oop4 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->suspendedCallbacks[foo->jmpDepth] = activeProc; foo->suspendedMethods[foo->jmpDepth] = foo->newMethod; transferTo(wakeHighestPriority()); /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; result = setjmp(foo->jmpBuf[foo->jmpDepth]); if (result == 0) { callbackID[0] = foo->jmpDepth; interpret(); } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop1 = longAt((oop3 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop1 + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin putToSleep: */ priority = ((longAt((activeProc + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop6 = longAt((oop11 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); processLists = longAt((oop6 + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); processList = longAt((processLists + (BASE_HEADER_SIZE)) + ((priority - 1) << (SHIFT_FOR_WORD))); /* begin addLastLink:toList: */ if ((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), activeProc); } else { lastLink = longAt((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink, activeProc); } longAtput((lastLink + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), activeProc); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), activeProc); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, processList); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), processList); activeProc = foo->suspendedCallbacks[foo->jmpDepth]; /* see comment above */ foo->newMethod = foo->suspendedMethods[foo->jmpDepth]; transferTo(activeProc); foo->jmpDepth -= 1; return 1; } /* Leave from a previous callback */ EXPORT(sqInt) callbackLeave(sqInt cbID) { register struct foo * foo = &fum; if (foo->primitiveIndex == 0) { return 0; } if (!(cbID == foo->jmpDepth)) { return 0; } if (cbID < 1) { return 0; } longjmp(foo->jmpBuf[foo->jmpDepth], 1); } /* Change the class of the receiver into the class specified by the argument given that the format of the receiver matches the format of the argument. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ /* Check what the format of the class says */ sqInt changeClassOfto(sqInt rcvr, sqInt argClass) { register struct foo * foo = &fum; sqInt argFormat; sqInt sizeHiBits; sqInt rcvrFormat; sqInt classHdr; sqInt byteSize; sqInt ccIndex; sqInt i; /* Low 2 bits are 0 */ /* Compute the size of instances of the class (used for fixed field classes only) */ classHdr = (longAt((argClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; sizeHiBits = ((usqInt) (classHdr & 393216)) >> 9; classHdr = classHdr & 131071; /* size in bytes -- low 2 bits are 0 */ /* Check the receiver's format against that of the class */ byteSize = (classHdr & (SIZE_MASK)) + sizeHiBits; argFormat = (((usqInt) classHdr) >> 8) & 15; rcvrFormat = (((usqInt) (longAt(rcvr))) >> 8) & 15; if (!(argFormat == rcvrFormat)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (argFormat < 2) { if (!((byteSize - (BASE_HEADER_SIZE)) == (byteSizeOf(rcvr)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } if (((longAt(rcvr)) & TypeMask) == HeaderTypeShort) { /* Compact classes. Check if the arg's class is compact and exchange ccIndex */ ccIndex = classHdr & CompactClassMask; if (ccIndex == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } longAtput(rcvr, ((longAt(rcvr)) & (~CompactClassMask)) | ccIndex); } else { longAtput(rcvr - (BASE_HEADER_SIZE), argClass | ((longAt(rcvr)) & TypeMask)); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, argClass); } } /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } for (i = 1; i <= AtCacheTotalSize; i += 1) { foo->atCache[i] = 0; } } /* Arg must lie in range 0-255! */ sqInt characterForAscii(sqInt ascii) { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); return longAt((oop + (BASE_HEADER_SIZE)) + (ascii << (SHIFT_FOR_WORD))); } sqInt characterTable(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); } /* Check for possible interrupts and handle one if necessary. */ sqInt checkForInterrupts(void) { register struct foo * foo = &fum; sqInt now; sqInt sema; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt i; sqInt xArray; sqInt xSize; sqInt index; sqInt sema1; sqInt oop4; now = (ioMSecs()) & MillisecondClockMask; if (!(foo->interruptCheckCounter < -100)) { if ((now - foo->lastTick) < foo->interruptChecksEveryNms) { /* don't play with the feedback if we forced a check. It only makes life difficult */ /* wrapping is not a concern, it'll get caught quickly enough. This clause is trying to keep a reasonable guess of how many times per interruptChecksEveryNms we are calling quickCheckForInterrupts. Not sure how effective it really is. */ foo->interruptCheckCounterFeedBackReset += 10; } else { if (foo->interruptCheckCounterFeedBackReset <= 1000) { foo->interruptCheckCounterFeedBackReset = 1000; } else { foo->interruptCheckCounterFeedBackReset -= 12; } } } foo->interruptCheckCounter = foo->interruptCheckCounterFeedBackReset; if (foo->signalLowSpace) { /* reset flag */ foo->signalLowSpace = 0; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; sema = longAt((oop + (BASE_HEADER_SIZE)) + (TheLowSpaceSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } if (now < foo->lastTick) { /* millisecond clock wrapped so correct the nextPollTick */ foo->nextPollTick = (foo->nextPollTick - MillisecondClockMask) - 1; } if (now >= foo->nextPollTick) { ioProcessEvents(); /* msecs to wait before next call to ioProcessEvents. Note that strictly speaking we might need to update 'now' at this point since ioProcessEvents could take a very long time on some platforms */ foo->nextPollTick = now + 200; } if (foo->interruptPending) { /* reset interrupt flag */ foo->interruptPending = 0; /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; sema = longAt((oop1 + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } if (foo->nextWakeupTick != 0) { if (now < foo->lastTick) { /* the clock has wrapped. Subtract the wrap interval from nextWakeupTick - this might just possibly result in 0. Since this is used as a flag value for 'no timer' we do the 0 check above */ foo->nextWakeupTick = (foo->nextWakeupTick - MillisecondClockMask) - 1; } if (now >= foo->nextWakeupTick) { /* set timer interrupt to 0 for 'no timer' */ foo->nextWakeupTick = 0; /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; sema = longAt((oop2 + (BASE_HEADER_SIZE)) + (TheTimerSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } } if (foo->pendingFinalizationSignals > 0) { /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; sema = longAt((oop3 + (BASE_HEADER_SIZE)) + (TheFinalizationSemaphore << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema); } foo->pendingFinalizationSignals = 0; } if ((foo->semaphoresToSignalCountA > 0) || (foo->semaphoresToSignalCountB > 0)) { /* begin signalExternalSemaphores */ foo->semaphoresUseBufferA = !foo->semaphoresUseBufferA; /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; xArray = longAt((oop4 + (BASE_HEADER_SIZE)) + (ExternalObjectsArray << (SHIFT_FOR_WORD))); xSize = stSizeOf(xArray); if (foo->semaphoresUseBufferA) { for (i = 1; i <= foo->semaphoresToSignalCountB; i += 1) { index = foo->semaphoresToSignalB[i]; if (index <= xSize) { sema1 = longAt((xArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema1)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema1); } } } foo->semaphoresToSignalCountB = 0; } else { for (i = 1; i <= foo->semaphoresToSignalCountA; i += 1) { index = foo->semaphoresToSignalA[i]; if (index <= xSize) { sema1 = longAt((xArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema1)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema1); } } } foo->semaphoresToSignalCountA = 0; } } foo->lastTick = now; } /* Read and verify the image file version number and return true if the the given image file needs to be byte-swapped. As a side effect, position the file stream just after the version number of the image header. This code prints a warning and does a hard-exit if it cannot find a valid version number. */ /* This code is based on C code by Ian Piumarta. */ sqInt checkImageVersionFromstartingAt(sqImageFile f, squeakFileOffsetType imageOffset) { sqInt version; sqInt firstVersion; sqImageFileSeek(f, imageOffset); version = firstVersion = getLongFromFileswap(f, 0); if ((version == imageFormatVersionNumber) || ((version == (imageFormatForwardCompatibilityVersion())) || (version == (imageFormatBackwardCompatibilityVersion())))) { return 0; } sqImageFileSeek(f, imageOffset); version = getLongFromFileswap(f, 1); if ((version == imageFormatVersionNumber) || ((version == (imageFormatForwardCompatibilityVersion())) || (version == (imageFormatBackwardCompatibilityVersion())))) { return 1; } if (imageOffset == 0) { sqImageFileSeek(f, 512); version = getLongFromFileswap(f, 0); if ((version == imageFormatVersionNumber) || ((version == (imageFormatForwardCompatibilityVersion())) || (version == (imageFormatBackwardCompatibilityVersion())))) { return 0; } sqImageFileSeek(f, 512); version = getLongFromFileswap(f, 1); if ((version == imageFormatVersionNumber) || ((version == (imageFormatForwardCompatibilityVersion())) || (version == (imageFormatBackwardCompatibilityVersion())))) { return 1; } } print("This interpreter (vers. "); printNum(imageFormatVersionNumber); print(") cannot read image file (vers. "); printNum(firstVersion); print(")."); /* begin cr */ printf("\n"); print("Press CR to quit..."); getchar(); ioExit(); } /* Note: May be called by translated primitive code. */ sqInt checkedIntegerValueOf(sqInt intOop) { if ((intOop & 1)) { return (intOop >> 1); } else { /* begin primitiveFail */ foo->successFlag = 0; return 0; } } /* Assumes zero-based array indexing. For testing in Smalltalk, this method should be overridden in a subclass. */ sqInt checkedLongAt(sqInt byteAddress) { register struct foo * foo = &fum; /* begin checkAddress: */ if ((((usqInt) byteAddress)) < (((usqInt) memory))) { error("bad address: negative"); } if ((((usqInt) byteAddress)) >= (((usqInt) foo->memoryLimit))) { error("bad address: past end of heap"); } /* begin checkAddress: */ if ((((usqInt) (byteAddress + 3))) < (((usqInt) memory))) { error("bad address: negative"); } if ((((usqInt) (byteAddress + 3))) >= (((usqInt) foo->memoryLimit))) { error("bad address: past end of heap"); } return longAt(byteAddress); } sqInt classAlien(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassAlien << (SHIFT_FOR_WORD))); } sqInt classArray(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassArray << (SHIFT_FOR_WORD))); } sqInt classBitmap(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassBitmap << (SHIFT_FOR_WORD))); } sqInt classByteArray(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassByteArray << (SHIFT_FOR_WORD))); } sqInt classCharacter(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassCharacter << (SHIFT_FOR_WORD))); } sqInt classExternalAddress(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalAddress << (SHIFT_FOR_WORD))); } sqInt classExternalData(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalData << (SHIFT_FOR_WORD))); } sqInt classExternalFunction(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalFunction << (SHIFT_FOR_WORD))); } sqInt classExternalLibrary(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalLibrary << (SHIFT_FOR_WORD))); } sqInt classExternalStructure(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalStructure << (SHIFT_FOR_WORD))); } sqInt classFloat(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); } sqInt classLargeNegativeInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD))); } sqInt classLargePositiveInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); } /* Check if aClass's name is className */ sqInt classNameOfIs(sqInt aClass, char * className) { sqInt length; sqInt name; sqInt i; char * srcName; if ((lengthOf(aClass)) <= 6) { return 0; } name = longAt((aClass + (BASE_HEADER_SIZE)) + (6 << (SHIFT_FOR_WORD))); if (!(((name & 1) == 0) && (((((usqInt) (longAt(name))) >> 8) & 15) >= 8))) { return 0; } length = stSizeOf(name); srcName = ((char *) (arrayValueOf(name))); for (i = 0; i <= (length - 1); i += 1) { if (!((srcName[i]) == (className[i]))) { return 0; } } return (className[length]) == 0; } sqInt classPoint(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); } sqInt classSemaphore(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassSemaphore << (SHIFT_FOR_WORD))); } sqInt classSmallInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } sqInt classString(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassString << (SHIFT_FOR_WORD))); } sqInt classUnsafeAlien(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassUnsafeAlien << (SHIFT_FOR_WORD))); } /* Return a shallow copy of the given object. May cause GC */ /* Assume: Oop is a real object, not a small integer. */ sqInt clone(sqInt oop) { register struct foo * foo = &fum; sqInt newOop; sqInt hash; usqInt fromIndex; sqInt header; sqInt remappedOop; sqInt extraHdrBytes; usqInt bytes; sqInt newChunk; usqInt lastFrom; sqInt toIndex; sqInt oop1; sqInt header1; sqInt newFreeSize; sqInt enoughSpace; sqInt newChunk1; usqInt minFree; sqInt sched; sqInt lastSavedProcess; sqInt currentProc; sqInt oop4; sqInt oop11; sqInt oop2; sqInt oop3; extraHdrBytes = foo->headerTypeBytes[(longAt(oop)) & TypeMask]; /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { bytes = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { bytes = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; /* allocate space for the copy, remapping oop in case of a GC */ bytes += extraHdrBytes; /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = oop; if (!(sufficientSpaceToAllocate(2500 + bytes))) { return 0; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + bytes) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l2; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l2; } l2: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop11 = foo->specialObjectsOop; lastSavedProcess = longAt((oop11 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop4 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop3 = foo->specialObjectsOop; if ((((usqInt) oop3)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop3, currentProc); } longAtput((oop3 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), bytes + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - bytes; newChunk1 = foo->freeBlock; foo->freeBlock += bytes; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newChunk = newChunk1; /* begin popRemappableOop */ oop1 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedOop = oop1; /* loop below uses pre-increment */ toIndex = newChunk - (BYTES_PER_WORD); fromIndex = (remappedOop - extraHdrBytes) - (BYTES_PER_WORD); lastFrom = fromIndex + bytes; while (fromIndex < lastFrom) { longAtput(toIndex += BYTES_PER_WORD, longAt(fromIndex += BYTES_PER_WORD)); } /* convert from chunk to oop */ /* fix base header: compute new hash and clear Mark and Root bits */ newOop = newChunk + extraHdrBytes; /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; /* use old ccIndex, format, size, and header-type fields */ header = (longAt(newOop)) & 131071; header = header | ((hash << 17) & 536739840); longAtput(newOop, header); return newOop; } /* This code is called if the receiver responds primitively to at:. If this is so, it will be installed in the atCache so that subsequent calls of at: or next may be handled immediately in bytecode primitive routines. */ sqInt commonAt(sqInt stringy) { register struct foo * foo = &fum; sqInt result; sqInt atIx; sqInt rcvr; sqInt index; sqInt sp; sqInt oop; sqInt sp1; sqInt oop1; /* Sets successFlag */ index = positive32BitValueOf(longAt(foo->stackPointer)); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (!(foo->successFlag && (!((rcvr & 1))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((foo->messageSelector == (fetchPointerofObject(16 * 2, fetchPointerofObject(SpecialSelectors, foo->specialObjectsOop)))) && (foo->lkupClass == (fetchClassOfNonInt(rcvr)))) { /* OK -- look in the at-cache */ /* Index into atCache = 4N, for N = 0 ... 7 */ atIx = rcvr & AtCacheMask; if (!((foo->atCache[atIx + AtCacheOop]) == rcvr)) { installinAtCacheatstring(rcvr, foo->atCache, atIx, stringy); } if (foo->successFlag) { result = commonVariableatcacheIndex(rcvr, index, atIx); } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp; return null; } } foo->successFlag = 1; result = stObjectat(rcvr, index); if (foo->successFlag) { if (stringy) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); result = longAt((oop + (BASE_HEADER_SIZE)) + (((result >> 1)) << (SHIFT_FOR_WORD))); } /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp1; return null; } } /* This code is called if the receiver responds primitively to at:Put:. If this is so, it will be installed in the atPutCache so that subsequent calls of at: or next may be handled immediately in bytecode primitive routines. */ sqInt commonAtPut(sqInt stringy) { register struct foo * foo = &fum; sqInt value; sqInt atIx; sqInt rcvr; sqInt index; sqInt sp; sqInt sp1; sqInt valToPut; sqInt fmt; sqInt fixedFields; sqInt stSize; value = longAt(foo->stackPointer); /* Sets successFlag */ index = positive32BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if (!(foo->successFlag && (!((rcvr & 1))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((foo->messageSelector == (fetchPointerofObject(17 * 2, fetchPointerofObject(SpecialSelectors, foo->specialObjectsOop)))) && (foo->lkupClass == (fetchClassOfNonInt(rcvr)))) { /* OK -- look in the at-cache */ /* Index into atPutCache */ atIx = (rcvr & AtCacheMask) + AtPutBase; if (!((foo->atCache[atIx + AtCacheOop]) == rcvr)) { installinAtCacheatstring(rcvr, foo->atCache, atIx, stringy); } if (foo->successFlag) { /* begin commonVariable:at:put:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, value); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); goto l1; } if (fmt < 8) { valToPut = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2), valToPut); } goto l1; } if (fmt >= 16) { valToPut = asciiOfCharacter(value); if (!(foo->successFlag)) { goto l1; } } else { valToPut = value; } if ((valToPut & 1)) { valToPut = (valToPut >> 1); if (!((valToPut >= 0) && (valToPut <= 255))) { /* begin primitiveFail */ foo->successFlag = 0; goto l1; } byteAtput((rcvr + (BASE_HEADER_SIZE)) + (index - 1), valToPut); goto l1; } } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end commonVariable:at:put:cacheIndex: */; } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp; return null; } } foo->successFlag = 1; if (stringy) { stObjectatput(rcvr, index, asciiOfCharacter(value)); } else { stObjectatput(rcvr, index, value); } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp1; return null; } } /* This code assumes the receiver has been identified at location atIx in the atCache. */ sqInt commonVariableatcacheIndex(sqInt rcvr, sqInt index, sqInt atIx) { register struct foo * foo = &fum; sqInt result; sqInt fmt; sqInt fixedFields; sqInt stSize; sqInt oop; sqInt oop1; stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; return longAt((rcvr + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD))); } if (fmt < 8) { /* Bitmap */ result = long32At((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2)); result = positive32BitIntegerFor(result); return result; } if (fmt >= 16) { /* begin characterForAscii: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); return longAt((oop + (BASE_HEADER_SIZE)) + ((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << (SHIFT_FOR_WORD))); } else { return (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << 1) | 1); } } /* begin primitiveFail */ foo->successFlag = 0; } /* May set success to false */ /* First compare two ST integers... */ sqInt compare31or32Bitsequal(sqInt obj1, sqInt obj2) { if (((obj1 & 1)) && ((obj2 & 1))) { return obj1 == obj2; } return (positive32BitValueOf(obj1)) == (positive32BitValueOf(obj2)); } sqInt compilerCreateActualMessagestoringArgs(sqInt aMessage, sqInt argArray) { return compilerHooks[14](aMessage, argArray); } sqInt compilerFlushCache(sqInt aCompiledMethod) { return compilerHooks[2](aCompiledMethod); } sqInt compilerMapFromto(sqInt memStart, sqInt memEnd) { return compilerHooks[4](memStart, memEnd); } sqInt compilerMark(void) { return compilerHooks[9](); } sqInt compilerPostGC(void) { return compilerHooks[5](); } sqInt compilerPostSnapshot(void) { return compilerHooks[8](); } sqInt compilerPreGC(sqInt fullGCFlag) { return compilerHooks[3](fullGCFlag); } sqInt compilerPreSnapshot(void) { return compilerHooks[7](); } sqInt compilerProcessChange(void) { return compilerHooks[6](); } sqInt compilerProcessChangeto(sqInt oldProc, sqInt newProc) { return compilerHooks[6](oldProc, newProc); } sqInt compilerTranslateMethod(void) { return compilerHooks[1](); } /* Return true if neither array contains a small integer. You can't become: integers! */ sqInt containOnlyOopsand(sqInt array1, sqInt array2) { sqInt fieldOffset; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l2; } contextSize = (sp >> 1); l2: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { fieldOffset = 0; goto l4; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { if (((longAt(array1 + fieldOffset)) & 1)) { return 0; } if (((longAt(array2 + fieldOffset)) & 1)) { return 0; } fieldOffset -= BYTES_PER_WORD; } return 1; } /* Does thisCntx have aContext in its sender chain? */ sqInt contexthasSender(sqInt thisCntx, sqInt aContext) { sqInt nilOop; sqInt s; if (thisCntx == aContext) { return 0; } nilOop = foo->nilObj; s = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); while (!(s == nilOop)) { if (s == aContext) { return 1; } s = longAt((s + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } return 0; } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=copyBits and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt copyBits(void) { void * fn; fn = ioLoadFunctionFrom("copyBits", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(void))fn)(); } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=copyBitsFrom:to:at: and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt y) { void * fn; fn = ioLoadFunctionFrom("copyBitsFromtoat", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(sqInt, sqInt, sqInt))fn)(x0, x1, y); } /* Copy this object into the segment beginning at lastSeg. Install a forwarding pointer, and save oop and header. Fail if out of space. Return the next segmentAddr if successful. */ /* Copy the object... */ sqInt copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(sqInt oop, sqInt segmentWordArray, sqInt lastSeg, sqInt stopAddr, sqInt oopPtr, sqInt hdrPtr) { register struct foo * foo = &fum; sqInt bodySize; sqInt extraSize; sqInt hdrAddr; sqInt in; sqInt lastIn; sqInt out; sqInt header; flag("Dan"); if (!(foo->successFlag)) { return lastSeg; } extraSize = foo->headerTypeBytes[(longAt(oop)) & TypeMask]; /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { bodySize = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { bodySize = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; if ((((usqInt) ((lastSeg + extraSize) + bodySize))) >= (((usqInt) stopAddr))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin transfer:from:to: */ flag("Dan"); in = (oop - extraSize) - (BYTES_PER_WORD); lastIn = in + (((extraSize + bodySize) / (BYTES_PER_WORD)) * (BYTES_PER_WORD)); out = (lastSeg + (BYTES_PER_WORD)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } hdrAddr = (lastSeg + (BYTES_PER_WORD)) + extraSize; longAtput(hdrAddr, (longAt(hdrAddr)) & ((ALL_BUT_ROOT_BIT) - (MARK_BIT))); /* begin forward:to:savingOopAt:andHeaderAt: */ longAtput(oopPtr, oop); longAtput(hdrPtr, longAt(oop)); longAtput(oop, (((lastSeg + (BYTES_PER_WORD)) + extraSize) - segmentWordArray) + HeaderTypeFree); return (lastSeg + extraSize) + bodySize; } /* Bundle up the selector, arguments and lookupClass into a Message object. In the process it pops the arguments off the stack, and pushes the message object. This can then be presented as the argument of e.g. #doesNotUnderstand:. ikp 11/20/1999 03:59 -- added hook for external runtime compilers. */ /* remap lookupClass in case GC happens during allocation */ sqInt createActualMessageTo(sqInt aClass) { register struct foo * foo = &fum; sqInt message; sqInt argumentArray; sqInt lookupClass; sqInt count; sqInt src; sqInt in; sqInt lastIn; sqInt out; sqInt sp; sqInt oop; sqInt oop1; sqInt valuePointer; /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = aClass; /* remap argumentArray in case GC happens during allocation */ argumentArray = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), foo->argumentCount); /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = argumentArray; message = instantiateClassindexableSize(fetchPointerofObject(ClassMessage, foo->specialObjectsOop), 0); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; argumentArray = oop; /* begin popRemappableOop */ oop1 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; lookupClass = oop1; beRootIfOld(argumentArray); if (foo->compilerInitialized) { compilerCreateActualMessagestoringArgs(message, argumentArray); } else { /* begin transfer:from:to: */ count = foo->argumentCount; src = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)); flag("Dan"); in = src - (BYTES_PER_WORD); lastIn = in + (count * (BYTES_PER_WORD)); out = (argumentArray + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)), message); foo->stackPointer = sp; } foo->argumentCount = 1; /* begin storePointer:ofObject:withValue: */ valuePointer = foo->messageSelector; if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, valuePointer); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageSelectorIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, argumentArray); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageArgumentsIndex << (SHIFT_FOR_WORD)), argumentArray); if ((lastPointerOf(message)) >= ((MessageLookupClassIndex * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE))) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, lookupClass); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageLookupClassIndex << (SHIFT_FOR_WORD)), lookupClass); } } sqInt dispatchFunctionPointer(void * aFunctionPointer) { ((void (*)(void))aFunctionPointer)(); } /* Call the primitive at index primIdx in the primitiveTable. */ sqInt dispatchFunctionPointerOnin(sqInt primIdx, void *primTable[]) { return dispatchFunctionPointer(primTable[primIdx]); } /* Repaint the portion of the Smalltalk screen bounded by the affected rectangle. Used to synchronize the screen after a Bitblt to the Smalltalk Display object. */ sqInt displayBitsOfLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b) { register struct foo * foo = &fum; sqInt displayObj; sqInt d; sqInt right; sqInt dispBits; sqInt bottom; sqInt h; sqInt top; sqInt left; sqInt surfaceHandle; sqInt w; sqInt dispBitsIndex; sqInt oop; sqInt successValue; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; displayObj = longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); if (!(aForm == displayObj)) { return null; } /* begin success: */ successValue = (((displayObj & 1) == 0) && (((((usqInt) (longAt(displayObj))) >> 8) & 15) <= 4)) && ((lengthOf(displayObj)) >= 4); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { dispBits = longAt((displayObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); w = fetchIntegerofObject(1, displayObj); h = fetchIntegerofObject(2, displayObj); d = fetchIntegerofObject(3, displayObj); } if (l < 0) { left = 0; } else { left = l; } if (r > w) { right = w; } else { right = r; } if (t < 0) { top = 0; } else { top = t; } if (b > h) { bottom = h; } else { bottom = b; } if (!((left <= right) && (top <= bottom))) { return null; } if (foo->successFlag) { if ((dispBits & 1)) { surfaceHandle = (dispBits >> 1); if (showSurfaceFn == 0) { showSurfaceFn = ioLoadFunctionFrom("ioShowSurface", "SurfacePlugin"); if (showSurfaceFn == 0) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } } ((sqInt (*)(sqInt, sqInt, sqInt, sqInt, sqInt))showSurfaceFn)(surfaceHandle, left, top, right-left, bottom-top); } else { /* index in memory byte array */ dispBitsIndex = dispBits + (BASE_HEADER_SIZE); ioShowDisplay(dispBitsIndex, w, h, d, left, right, top, bottom); } } } sqInt displayObject(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); } /* Rounds negative results towards negative infinity, rather than zero. */ sqInt doPrimitiveDivby(sqInt rcvr, sqInt arg) { register struct foo * foo = &fum; sqInt integerArg; sqInt result; sqInt integerRcvr; sqInt posRcvr; sqInt posArg; sqInt successValue; if (((rcvr & arg) & 1) != 0) { integerRcvr = (rcvr >> 1); integerArg = (arg >> 1); /* begin success: */ foo->successFlag = (integerArg != 0) && foo->successFlag; } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return 1; } if (integerRcvr > 0) { if (integerArg > 0) { result = integerRcvr / integerArg; } else { /* round negative result toward negative infinity */ posArg = 0 - integerArg; result = 0 - ((integerRcvr + (posArg - 1)) / posArg); } } else { posRcvr = 0 - integerRcvr; if (integerArg > 0) { /* round negative result toward negative infinity */ result = 0 - ((posRcvr + (integerArg - 1)) / integerArg); } else { posArg = 0 - integerArg; result = posRcvr / posArg; } } /* begin success: */ successValue = # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ; foo->successFlag = successValue && foo->successFlag; return result; } sqInt doPrimitiveModby(sqInt rcvr, sqInt arg) { register struct foo * foo = &fum; sqInt integerArg; sqInt integerResult; sqInt integerRcvr; sqInt successValue; if (((rcvr & arg) & 1) != 0) { integerRcvr = (rcvr >> 1); integerArg = (arg >> 1); /* begin success: */ foo->successFlag = (integerArg != 0) && foo->successFlag; } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return 1; } /* ensure that the result has the same sign as the integerArg */ integerResult = integerRcvr % integerArg; if (integerArg < 0) { if (integerResult > 0) { integerResult += integerArg; } } else { if (integerResult < 0) { integerResult += integerArg; } } /* begin success: */ successValue = # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ; foo->successFlag = successValue && foo->successFlag; return integerResult; } sqInt dummyReferToProxy(void) { interpreterProxy = interpreterProxy; } /* Dump the entire image out to the given file. Intended for debugging only. */ EXPORT(sqInt) dumpImage(char * fileName) { sqInt result; sqInt dataSize; sqImageFile f; f = sqImageFileOpen(fileName, "wb"); if (f == null) { return -1; } dataSize = foo->endOfMemory - memory; result = sqImageFileWrite(pointerForOop(memory), sizeof(unsigned char), dataSize, f); sqImageFileClose(f); return result; } /* execute a method found in the mCache - which means that primitiveIndex & primitiveFunctionPointer are already set. Any sender needs to have previously sent findMethodInClass: or equivalent */ sqInt executeNewMethodFromCache(void) { register struct foo * foo = &fum; sqInt delta; sqInt nArgs; if (foo->primitiveIndex > 0) { if (DoBalanceChecks) { /* check stack balance */ nArgs = foo->argumentCount; delta = foo->stackPointer - foo->activeContext; } foo->successFlag = 1; dispatchFunctionPointer(foo->primitiveFunctionPointer); if (DoBalanceChecks) { if (!(balancedStackafterPrimitivewithArgs(delta, foo->primitiveIndex, nArgs))) { printUnbalancedStack(foo->primitiveIndex); } } if (foo->successFlag) { return null; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } sqInt failed(void) { return !foo->successFlag; } sqInt falseObject(void) { return foo->falseObj; } /* Fetch the instance variable at the given index of the given object. Return the address of first indexable field of resulting array object, or fail if the instance variable does not contain an indexable bytes or words object. */ /* Note: May be called by translated primitive code. */ void * fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt arrayOop; arrayOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); /* begin arrayValueOf: */ if ((!((arrayOop & 1))) && (((arrayOop & 1) == 0) && (isWordsOrBytesNonInt(arrayOop)))) { return pointerForOop(arrayOop + (BASE_HEADER_SIZE)); } /* begin primitiveFail */ foo->successFlag = 0; return null; } sqInt fetchClassOf(sqInt oop) { register struct foo * foo = &fum; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; return longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { return (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } } sqInt fetchClassOfNonInt(sqInt oop) { sqInt ccIndex; sqInt oop1; sqInt oop2; ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { return (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } } /* Fetch the instance variable at the given index of the given object. Return the C double precision floating point value of that instance variable, or fail if it is not a Float. */ /* Note: May be called by translated primitive code. */ double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt floatOop; floatOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); return floatValueOf(floatOop); } /* Note: May be called by translated primitive code. */ sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt intOop; intOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((intOop & 1)) { return (intOop >> 1); } else { /* begin primitiveFail */ foo->successFlag = 0; return 0; } return null; } /* index by 32-bit units, and return a 32-bit value. Intended to replace fetchWord:ofObject: */ sqInt fetchLong32ofObject(sqInt fieldIndex, sqInt oop) { return long32At((oop + (BASE_HEADER_SIZE)) + (fieldIndex << 2)); } /* index by word size, and return a pointer as long as the word size */ sqInt fetchPointerofObject(sqInt fieldIndex, sqInt oop) { return longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); } /* Return the stackPointer of a Context or BlockContext. */ sqInt fetchStackPointerOf(sqInt aContext) { sqInt sp; sp = longAt((aContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { return 0; } return (sp >> 1); } /* NOTE: this gives size appropriate for fetchPointer: n, but not in general for, eg, fetchLong32, etc. */ sqInt fetchWordLengthOf(sqInt objectPointer) { sqInt sz; sqInt header; /* begin sizeBitsOf: */ header = longAt(objectPointer); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } /* During sweep phase we have encountered a weak reference. Check if its object has gone away (or is about to) and if so, signal a semaphore. */ /* Do *not* inline this in sweepPhase - it is quite an unlikely case to run into a weak reference */ sqInt finalizeReference(usqInt oop) { register struct foo * foo = &fum; sqInt chunk; sqInt lastField; sqInt nonWeakCnt; sqInt oopGone; sqInt firstField; usqInt weakOop; sqInt i; sqInt listOop; sqInt listItemOop; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; nonWeakCnt = nonWeakFieldsOf(oop); firstField = (BASE_HEADER_SIZE) + (nonWeakCnt << (SHIFT_FOR_WORD)); /* begin lastPointerOf: */ header = longAt(oop); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l2; } contextSize = (sp >> 1); l2: /* end fetchStackPointerOf: */; lastField = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(oop); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; lastField = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { lastField = 0; goto l4; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); lastField = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; for (i = firstField; i <= lastField; i += (BYTES_PER_WORD)) { /* ar 1/18/2005: Added oop < youngStart test to make sure we're not testing objects in non-GCable region. This could lead to a forward reference in old space with the oop pointed to not being marked and thus treated as free. */ weakOop = longAt(oop + i); if (!((weakOop == foo->nilObj) || (((weakOop & 1)) || (weakOop < foo->youngStart)))) { if (weakOop < oop) { /* Check if the object is being collected. If the weak reference points * backward: check if the weakOops chunk is free * forward: check if the weakOoop has been marked by GC */ chunk = weakOop - (foo->headerTypeBytes[(longAt(weakOop)) & TypeMask]); oopGone = ((longAt(chunk)) & TypeMask) == HeaderTypeFree; } else { oopGone = ((longAt(weakOop)) & (MARK_BIT)) == 0; } if (oopGone) { longAtput(oop + i, foo->nilObj); if (nonWeakCnt >= 2) { /* begin weakFinalizerCheck: */ listOop = longAt((oop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if ((fetchClassOf(listOop)) == (fetchPointerofObject(ClassWeakFinalizer, foo->specialObjectsOop))) { listItemOop = longAt((listOop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, listItemOop); } longAtput((oop + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), listItemOop); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) listOop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(listOop, oop); } longAtput((listOop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), oop); } } /* begin signalFinalization: */ /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; foo->pendingFinalizationSignals += 1; } } } } sqInt findClassOfMethodforReceiver(sqInt meth, sqInt rcvr) { register struct foo * foo = &fum; sqInt done; sqInt classDict; sqInt classDictSize; sqInt i; sqInt currClass; sqInt methodArray; sqInt sz; sqInt ccIndex; sqInt ccIndex1; sqInt oop; sqInt oop1; sqInt header; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; currClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop1 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; done = 0; while (!(done)) { classDict = longAt((currClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(classDict); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(classDict - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; classDictSize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray = longAt((classDict + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i = 0; while (i < (classDictSize - SelectorStart)) { if (meth == (longAt((methodArray + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))))) { return currClass; } i += 1; } currClass = longAt((currClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done = currClass == foo->nilObj; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; return longAt((oop2 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } ccIndex1 = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex1 == 0) { return (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop3 + (BASE_HEADER_SIZE)) + ((ccIndex1 - 1) << (SHIFT_FOR_WORD))); } return null; } /* Find the compiled method to be run when the current messageSelector is sent to the given class, setting the values of 'newMethod' and 'primitiveIndex'. */ sqInt findNewMethodInClass(sqInt class) { register struct foo * foo = &fum; sqInt ok; sqInt hash; sqInt probe; /* begin lookupInMethodCacheSel:class: */ hash = foo->messageSelector ^ class; probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } ok = 0; l1: /* end lookupInMethodCacheSel:class: */; if (!(ok)) { lookupMethodInClass(class); foo->lkupClass = class; addNewMethodToCache(); } } /* Search the obsolete named primitive table for the given function. Return the index if it's found, -1 otherwise. */ sqInt findObsoleteNamedPrimitivelength(char * functionName, sqInt functionLength) { sqInt chIndex; sqInt index; const char * entry; index = 0; while (1) { entry = obsoleteNamedPrimitiveTable[index][0]; if (entry == null) { return -1; } ; chIndex = 0; while (((entry[chIndex]) == (functionName[chIndex])) && (chIndex < functionLength)) { chIndex += 1; } if ((chIndex == functionLength) && ((entry[chIndex]) == 0)) { return index; } index += 1; } } sqInt findSelectorOfMethodforReceiver(sqInt meth, sqInt rcvr) { register struct foo * foo = &fum; sqInt done; sqInt classDict; sqInt classDictSize; sqInt i; sqInt currClass; sqInt methodArray; sqInt sz; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt header; sqInt oop2; /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; currClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; done = 0; while (!(done)) { classDict = longAt((currClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(classDict); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(classDict - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; classDictSize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray = longAt((classDict + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i = 0; while (i <= (classDictSize - SelectorStart)) { if (meth == (longAt((methodArray + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))))) { return longAt((classDict + (BASE_HEADER_SIZE)) + ((i + SelectorStart) << (SHIFT_FOR_WORD))); } i += 1; } currClass = longAt((currClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done = currClass == foo->nilObj; } return foo->nilObj; } /* Return the first accessible object in the heap. */ sqInt firstAccessibleObject(void) { register struct foo * foo = &fum; sqInt obj; sqInt sz; sqInt header; obj = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { return obj; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } error("heap is empty"); } char * firstFixedField(sqInt oop) { return pointerForOop(oop + (BASE_HEADER_SIZE)); } /* NOTE: copied in InterpreterSimulator, so please duplicate any changes */ char * firstIndexableField(sqInt oop) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(oop); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l3; } if (fmt < 2) { fixedFields = totalLength; goto l3; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l3: /* end fixedFieldsOf:format:length: */; if (fmt < 8) { if (fmt == 6) { return pointerForOop((oop + (BASE_HEADER_SIZE)) + (fixedFields << 2)); } return pointerForOop((oop + (BASE_HEADER_SIZE)) + (fixedFields << (SHIFT_FOR_WORD))); } else { return pointerForOop((oop + (BASE_HEADER_SIZE)) + fixedFields); } } sqInt floatObjectOf(double aFloat) { sqInt newFloatObj; flag("Dan"); newFloatObj = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassFloat, foo->specialObjectsOop), 8 + (BASE_HEADER_SIZE)); storeFloatAtfrom(newFloatObj + (BASE_HEADER_SIZE), aFloat); return newFloatObj; } /* Fetch the instance variable at the given index of the given object. Return the C double precision floating point value of that instance variable, or fail if it is not a Float. */ /* Note: May be called by translated primitive code. */ double floatValueOf(sqInt oop) { register struct foo * foo = &fum; double result; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; flag("Dan"); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { ; fetchFloatAtinto(oop + (BASE_HEADER_SIZE), result); } else { result = 0.0; } return result; } /* methodPtr is a CompiledMethod containing an external primitive. Flush the function address and session ID of the CM */ sqInt flushExternalPrimitiveOf(sqInt methodPtr) { sqInt lit; if (!((literalCountOfHeader(longAt((methodPtr + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) > 0)) { return null; } lit = longAt((methodPtr + (BASE_HEADER_SIZE)) + ((0 + LiteralStart) << (SHIFT_FOR_WORD))); if (!((((lit & 1) == 0) && (((((usqInt) (longAt(lit))) >> 8) & 15) == 2)) && ((lengthOf(lit)) == 4))) { return null; } longAtput((lit + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD)), ConstZero); longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ConstZero); } /* Flush the references to external functions from plugin primitives. This will force a reload of those primitives when accessed next. Note: We must flush the method cache here so that any failed primitives are looked up again. */ sqInt flushExternalPrimitives(void) { register struct foo * foo = &fum; sqInt oop; sqInt primIdx; sqInt primBits; sqInt sz; sqInt header; sqInt i; sqInt i1; sqInt i2; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { if (((((usqInt) (longAt(oop))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((oop + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; primIdx = (primBits & 511) + (((usqInt) primBits) >> 19); if (primIdx == PrimitiveExternalCallIndex) { flushExternalPrimitiveOf(oop); } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } for (i = 1; i <= AtCacheTotalSize; i += 1) { foo->atCache[i] = 0; } /* begin flushObsoleteIndexedPrimitives */ for (i1 = 1; i1 <= MaxPrimitiveIndex; i1 += 1) { (obsoleteIndexedPrimitiveTable[i1])[2] = null; } /* begin flushExternalPrimitiveTable */ for (i2 = 0; i2 <= (MaxExternalPrimitiveTableSize - 1); i2 += 1) { foo->externalPrimitiveTable[i2] = 0; } } /* force an interrupt check ASAP - setting interruptCheckCounter to a large -ve number is used as a flag to skip messing with the feedback mechanism and nextPollTick resetting makes sure that ioProcess gets called as near immediately as we can manage */ sqInt forceInterruptCheck(void) { register struct foo * foo = &fum; foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } /* Repaint the entire smalltalk screen, ignoring the affected rectangle. Used in some platform's code when the Smalltalk window is brought to the front or uncovered. */ sqInt fullDisplayUpdate(void) { sqInt displayObj; sqInt h; sqInt w; sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; displayObj = longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); if ((((displayObj & 1) == 0) && (((((usqInt) (longAt(displayObj))) >> 8) & 15) <= 4)) && ((lengthOf(displayObj)) >= 4)) { w = fetchIntegerofObject(1, displayObj); h = fetchIntegerofObject(2, displayObj); displayBitsOfLeftTopRightBottom(displayObj, 0, 0, w, h); ioForceDisplayUpdate(); } } /* Do a mark/sweep garbage collection of the entire object memory. Free inaccessible objects but do not move them. */ sqInt fullGC(void) { register struct foo * foo = &fum; sqLong startTime; sqInt oop; sqInt i; sqInt sz; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; if (DoAssertionChecks) { reverseDisplayFromto(0, 7); } /* begin preGCAction: */ if (foo->compilerInitialized) { compilerPreGC(1); } else { /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); } startTime = ioMicroSecondClock(); foo->statSweepCount = foo->statMarkCount = foo->statMkFwdCount = foo->statCompMoveCount = 0; /* begin clearRootsTable */ for (i = 1; i <= foo->rootTableCount; i += 1) { oop = foo->rootTable[i]; longAtput(oop, (longAt(oop)) & (ALL_BUT_ROOT_BIT)); foo->rootTable[i] = 0; } foo->rootTableCount = 0; /* process all of memory */ foo->youngStart = memory; markPhase(); foo->totalObjectCount = sweepPhase(); /* begin fullCompaction */ foo->compStart = lowestFreeAfter(memory); if (foo->compStart == foo->freeBlock) { initializeMemoryFirstFree(foo->freeBlock); goto l1; } if ((sz = fwdTableSize(8)) < foo->totalObjectCount) { growObjectMemory(((foo->totalObjectCount - sz) + 10000) * 8); } while (foo->compStart < foo->freeBlock) { foo->compStart = incCompBody(); } l1: /* end fullCompaction */; foo->allocationCount = 0; foo->statFullGCs += 1; foo->statGCTime = ioMicroSecondClock(); foo->statFullGCMSecs += foo->statGCTime - startTime; /* begin capturePendingFinalizationSignals */ foo->statpendingFinalizationSignals = foo->pendingFinalizationSignals; /* reset the young object boundary */ foo->youngStart = foo->freeBlock; postGCAction(); if (DoAssertionChecks) { reverseDisplayFromto(0, 7); } } /* Set the limits for a table of two- or three-word forwarding blocks above the last used oop. The pointer fwdTableNext moves up to fwdTableLast. Used for compaction of memory and become-ing objects. Returns the number of forwarding blocks available. */ sqInt fwdTableInit(sqInt blkSize) { register struct foo * foo = &fum; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); /* make a fake free chunk at endOfMemory for use as a sentinal in memory scans */ foo->endOfMemory = foo->freeBlock + (BASE_HEADER_SIZE); /* begin setSizeOfFree:to: */ longAtput(foo->endOfMemory, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->fwdTableNext = ((foo->endOfMemory + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); /* last forwarding table entry */ /* return the number of forwarding blocks available */ foo->fwdTableLast = foo->memoryLimit - blkSize; return (foo->fwdTableLast - foo->fwdTableNext) / blkSize; } /* Estimate the number of forwarding blocks available for compaction */ sqInt fwdTableSize(sqInt blkSize) { register struct foo * foo = &fum; sqInt fwdLast; sqInt eom; sqInt fwdFirst; /* use all memory free between freeBlock and memoryLimit for forwarding table */ /* Note: Forward blocks must be quadword aligned. */ eom = foo->freeBlock + (BASE_HEADER_SIZE); fwdFirst = ((eom + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); /* last forwarding table entry */ /* return the number of forwarding blocks available */ fwdLast = foo->memoryLimit - blkSize; return (fwdLast - fwdFirst) / blkSize; } /* currentBytecode will be private to the main dispatch loop in the generated code. This method allows the currentBytecode to be retrieved from global variables. */ sqInt getCurrentBytecode(void) { return byteAt(foo->instructionPointer); } sqInt getFullScreenFlag(void) { return foo->fullScreenFlag; } sqInt getInterruptCheckCounter(void) { return foo->interruptCheckCounter; } sqInt getInterruptKeycode(void) { return foo->interruptKeycode; } sqInt getInterruptPending(void) { return foo->interruptPending; } /* Answer the next word read from aFile, byte-swapped according to the swapFlag. */ sqInt getLongFromFileswap(sqImageFile aFile, sqInt swapFlag) { sqInt w; w = 0; sqImageFileRead(&w, sizeof(w), 1, aFile); if (swapFlag) { /* begin byteSwapped: */ # if (BYTES_PER_WORD == 4) // swap bytes in an object word return ((((((usqInt) w >> 24)) & Byte0Mask) + ((((usqInt) w >> 8)) & Byte1Mask)) + ((((usqInt) w << 8)) & Byte2Mask)) + ((((usqInt) w << 24)) & Byte3Mask); # else return ((((((((((usqInt) w >> 56)) & Byte0Mask) + ((((usqInt) w >> 40)) & Byte1Mask)) + ((((usqInt) w >> 24)) & Byte2Mask)) + ((((usqInt) w >> 8)) & Byte3Mask)) + ((((usqInt) w << 8)) & Byte4Mask)) + ((((usqInt) w << 24)) & Byte5Mask)) + ((((usqInt) w << 40)) & Byte6Mask)) + ((((usqInt) w << 56)) & Byte7Mask); # endif // BYTES_PER_WORD == 4 return null; } else { return w; } } sqInt getNextWakeupTick(void) { return foo->nextWakeupTick; } sqInt getSavedWindowSize(void) { return foo->savedWindowSize; } /* For Newsqueak FFI */ EXPORT(sqInt) getStackPointer(void) { return foo->stackPointer; } /* return the global session ID value */ sqInt getThisSessionID(void) { return foo->globalSessionID; } /* Attempt to grow the object memory by the given delta amount */ sqInt growObjectMemory(usqInt delta) { register struct foo * foo = &fum; usqInt limit; if (!(isExcessiveAllocationRequestshift(delta, 0))) { foo->statGrowMemory += 1; limit = sqGrowMemoryBy(foo->memoryLimit, delta); if (!(limit == foo->memoryLimit)) { /* remove a tad for safety */ foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } } } sqInt headerOf(sqInt methodPointer) { return longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); } /* This VM is backwards-compatible with the immediately preceeding pre-closure version, and will allow loading images (or image segments) of that version. */ sqInt imageFormatBackwardCompatibilityVersion(void) { if ((BYTES_PER_WORD) == 4) { return 6502; } else { return 68000; } } /* This VM is forwards-compatible with the immediately following closure version, and will write the new version number in snapshots if the closure creation bytecode is used. */ sqInt imageFormatForwardCompatibilityVersion(void) { if ((BYTES_PER_WORD) == 4) { return 6504; } else { return 68002; } } /* a more complex version that tells both the word reversal and the endianness of the machine it came from. Low half of word is 6502. Top byte is top byte of #doesNotUnderstand: on this machine. ($d on the Mac or $s on the PC) */ sqInt imageSegmentVersion(void) { sqInt wholeWord; /* first data word, 'does' */ wholeWord = longAt((fetchPointerofObject(SelectorDoesNotUnderstand, foo->specialObjectsOop)) + (BASE_HEADER_SIZE)); return imageFormatVersionNumber | (wholeWord & 4278190080U); } /* Move objects to consolidate free space into one big chunk. Return the newly created free chunk. */ sqInt incCompBody(void) { register struct foo * foo = &fum; sqInt bytesFreed; fwdTableInit((BYTES_PER_WORD) * 2); /* update pointers to point at new oops */ bytesFreed = incCompMakeFwd(); mapPointersInObjectsFromto(foo->youngStart, foo->endOfMemory); return incCompMove(bytesFreed); } /* Create and initialize forwarding blocks for all non-free objects following compStart. If the supply of forwarding blocks is exhausted, set compEnd to the first chunk above the area to be compacted; otherwise, set it to endOfMemory. Return the number of bytes to be freed. */ sqInt incCompMakeFwd(void) { register struct foo * foo = &fum; sqInt oop; sqInt newOop; sqInt fwdBlock; sqInt bytesFreed; sqInt originalHeader; sqInt originalHeaderType; sqInt sz; sqInt header; sqInt fwdBlock1; sqInt realHeader; sqInt sz1; sqInt header1; bytesFreed = 0; oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { foo->statMkFwdCount += 1; if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { bytesFreed += (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin fwdBlockGet: */ foo->fwdTableNext += (BYTES_PER_WORD) * 2; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l1; } else { fwdBlock = null; goto l1; } l1: /* end fwdBlockGet: */; if (fwdBlock == null) { /* stop; we have used all available forwarding blocks */ foo->compEnd = oop - (foo->headerTypeBytes[(longAt(oop)) & TypeMask]); return bytesFreed; } newOop = oop - bytesFreed; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader = longAt(oop); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType = originalHeader & TypeMask; longAtput(fwdBlock, newOop); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader); if (0) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop); } longAtput(oop, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType)); } /* begin objectAfterWhileForwarding: */ header = longAt(oop); if ((header & (MARK_BIT)) == 0) { /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } oop = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); goto l3; } fwdBlock1 = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } realHeader = longAt(fwdBlock1 + (BYTES_PER_WORD)); if ((realHeader & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = realHeader & (SIZE_MASK); } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); l3: /* end objectAfterWhileForwarding: */; } foo->compEnd = foo->endOfMemory; return bytesFreed; } /* Move all non-free objects between compStart and compEnd to their new locations, restoring their headers in the process. Create a new free block at the end of memory. Return the newly created free chunk. */ /* Note: The free block used by the allocator always must be the last free block in memory. It may take several compaction passes to make all free space bubble up to the end of memory. */ sqInt incCompMove(sqInt bytesFreed) { register struct foo * foo = &fum; usqInt w; usqInt lastWord; sqInt oop; sqInt target; sqInt newOop; sqInt sz; sqInt next; sqInt fwdBlock; sqInt header; sqInt bytesToMove; sqInt newFreeChunk; usqInt firstWord; sqInt header1; sqInt sz2; sqInt header2; sqInt fwdBlock1; sqInt realHeader; sqInt sz1; sqInt header11; newOop = null; oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->compEnd))) { foo->statCompMoveCount += 1; /* begin objectAfterWhileForwarding: */ header2 = longAt(oop); if ((header2 & (MARK_BIT)) == 0) { /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header11 = longAt(oop); if ((header11 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header11 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } next = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); goto l3; } fwdBlock1 = (header2 & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } realHeader = longAt(fwdBlock1 + (BYTES_PER_WORD)); if ((realHeader & TypeMask) == HeaderTypeSizeAndClass) { sz2 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz2 = realHeader & (SIZE_MASK); } next = (oop + sz2) + (foo->headerTypeBytes[(longAt(oop + sz2)) & TypeMask]); l3: /* end objectAfterWhileForwarding: */; if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { /* a moving object; unwind its forwarding block */ fwdBlock = ((longAt(oop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } newOop = longAt(fwdBlock); header = longAt(fwdBlock + (BYTES_PER_WORD)); longAtput(oop, header); /* move the oop (including any extra header words) */ bytesToMove = oop - newOop; /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; firstWord = oop - (foo->headerTypeBytes[(longAt(oop)) & TypeMask]); lastWord = (oop + sz) - (BASE_HEADER_SIZE); target = firstWord - bytesToMove; for (w = firstWord; w <= lastWord; w += (BYTES_PER_WORD)) { longAtput(target, longAt(w)); target += BYTES_PER_WORD; } } oop = next; } if (newOop == null) { /* no objects moved */ oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); if ((((longAt(oop)) & TypeMask) == HeaderTypeFree) && ((objectAfter(oop)) == (foo->compEnd + (foo->headerTypeBytes[(longAt(foo->compEnd)) & TypeMask])))) { newFreeChunk = oop; } else { newFreeChunk = foo->freeBlock; } } else { /* initialize the newly freed memory chunk */ /* newOop is the last object moved; free chunk starts right after it */ newFreeChunk = newOop + (sizeBitsOf(newOop)); /* begin setSizeOfFree:to: */ longAtput(newFreeChunk, (bytesFreed & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); } if (DoAssertionChecks) { if (!((objectAfter(newFreeChunk)) == (foo->compEnd + (foo->headerTypeBytes[(longAt(foo->compEnd)) & TypeMask])))) { error("problem creating free chunk after compaction"); } } if ((objectAfter(newFreeChunk)) == foo->endOfMemory) { initializeMemoryFirstFree(newFreeChunk); } else { initializeMemoryFirstFree(foo->freeBlock); } return newFreeChunk; } /* Return the equivalent of aClass includesBehavior: aSuperclass. Note: written for efficiency and better inlining (only 1 temp) */ sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperclass) { register struct foo * foo = &fum; sqInt theClass; if (((theClass = aClass) == aSuperclass) || (aSuperclass == foo->nilObj)) { return 1; } do { if ((theClass = longAt((theClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD)))) == aSuperclass) { return 1; } } while(theClass != foo->nilObj); return 0; } /* Do a mark/sweep garbage collection of just the young object area of object memory (i.e., objects above youngStart), using the root table to identify objects containing pointers to young objects from the old object area. */ sqInt incrementalGC(void) { register struct foo * foo = &fum; sqInt weDidGrow; sqLong startTime; sqInt survivorCount; sqInt i; sqInt growth; sqInt oop; sqInt i1; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; if (foo->rootTableCount >= RootTableSize) { /* root table overflow; cannot do an incremental GC (this should be very rare) */ foo->statRootTableOverflows += 1; return fullGC(); } if (DoAssertionChecks) { reverseDisplayFromto(8, 15); validateRoots(); /* begin validate */ } /* begin preGCAction: */ if (foo->compilerInitialized) { compilerPreGC(0); } else { /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); } startTime = ioMicroSecondClock(); foo->weakRootCount = 0; foo->statSweepCount = foo->statMarkCount = foo->statMkFwdCount = foo->statCompMoveCount = 0; markPhase(); for (i = 1; i <= foo->weakRootCount; i += 1) { finalizeReference(foo->weakRoots[i]); } survivorCount = sweepPhase(); /* begin incrementalCompaction */ if (foo->compStart == foo->freeBlock) { initializeMemoryFirstFree(foo->freeBlock); } else { incCompBody(); } foo->statAllocationCount = foo->allocationCount; foo->allocationCount = 0; foo->statIncrGCs += 1; foo->statGCTime = ioMicroSecondClock(); foo->statIGCDeltaTime = foo->statGCTime - startTime; foo->statIncrGCMSecs += foo->statIGCDeltaTime; /* begin capturePendingFinalizationSignals */ foo->statpendingFinalizationSignals = foo->pendingFinalizationSignals; /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; foo->statRootTableCount = foo->rootTableCount; foo->statSurvivorCount = survivorCount; weDidGrow = 0; if (((survivorCount > foo->tenuringThreshold) || (foo->rootTableCount >= RootTableRedZone)) || (foo->forceTenureFlag == 1)) { /* move up the young space boundary if * there are too many survivors: this limits the number of objects that must be processed on future incremental GC's * we're about to overflow the roots table this limits the number of full GCs that may be caused by root table overflows in the near future */ foo->forceTenureFlag = 0; foo->statTenures += 1; /* begin clearRootsTable */ for (i1 = 1; i1 <= foo->rootTableCount; i1 += 1) { oop = foo->rootTable[i1]; longAtput(oop, (longAt(oop)) & (ALL_BUT_ROOT_BIT)); foo->rootTable[i1] = 0; } foo->rootTableCount = 0; if ((foo->freeBlock < foo->growHeadroom) && (foo->gcBiasToGrow > 0)) { biasToGrow(); weDidGrow = 1; } foo->youngStart = foo->freeBlock; } postGCAction(); if (DoAssertionChecks) { validateRoots(); /* begin validate */ reverseDisplayFromto(8, 15); } if (weDidGrow) { /* begin biasToGrowCheckGCLimit */ growth = (foo->youngStart - memory) - foo->gcBiasToGrowThreshold; if (growth < 0) { foo->gcBiasToGrowThreshold = foo->youngStart - memory; } if (growth > foo->gcBiasToGrowGCLimit) { fullGC(); foo->gcBiasToGrowThreshold = foo->youngStart - memory; } } } /* Initialize hooks for the 'null compiler' */ sqInt initCompilerHooks(void) { compilerHooks[1]= nullCompilerHook; compilerHooks[2]= nullCompilerHook; compilerHooks[3]= nullCompilerHook; compilerHooks[4]= nullCompilerHook; compilerHooks[5]= nullCompilerHook; compilerHooks[6]= nullCompilerHook; compilerHooks[7]= nullCompilerHook; compilerHooks[8]= nullCompilerHook; compilerHooks[9]= nullCompilerHook; compilerHooks[10]= nullCompilerHook; compilerHooks[11]= nullCompilerHook; compilerHooks[12]= nullCompilerHook; compilerHooks[13]= nullCompilerHook; compilerHooks[14]= nullCompilerHook; foo->compilerInitialized = 0; } /* Set the imageFormatVersionNumber to a default value for this word size. Normally this will have been set at image load time, but set it to a reasonable default if this has not been done. */ sqInt initializeImageFormatVersionIfNeeded(void) { if (imageFormatVersionNumber == 0) { if ((BYTES_PER_WORD) == 8) { imageFormatVersionNumber = 68000; } else { imageFormatVersionNumber = 6502; } } } /* Initialize Interpreter state before starting execution of a new image. */ sqInt initializeInterpreter(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt i; sqInt proc; sqInt sched; sqInt oop; sqInt oop1; sqInt activeCntx; sqInt tmp; interpreterProxy = sqGetInterpreterProxy(); dummyReferToProxy(); initializeObjectMemory(bytesToShift); initCompilerHooks(); foo->activeContext = foo->nilObj; foo->theHomeContext = foo->nilObj; foo->method = foo->nilObj; foo->receiver = foo->nilObj; foo->messageSelector = foo->nilObj; foo->newMethod = foo->nilObj; foo->methodClass = foo->nilObj; foo->lkupClass = foo->nilObj; foo->receiverClass = foo->nilObj; foo->newNativeMethod = foo->nilObj; /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } for (i = 1; i <= AtCacheTotalSize; i += 1) { foo->atCache[i] = 0; } /* begin loadInitialContext */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); proc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->activeContext = longAt((proc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } /* begin fetchContextRegisters: */ activeCntx = foo->activeContext; tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = activeCntx; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (activeCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); foo->reclaimableContextCount = 0; /* begin initialCleanup */ if (((longAt(foo->activeContext)) & (ROOT_BIT)) == 0) { goto l1; } longAtput(foo->activeContext, (longAt(foo->activeContext)) & (ALL_BUT_ROOT_BIT)); flushExternalPrimitives(); l1: /* end initialCleanup */; foo->interruptCheckCounter = 0; foo->interruptCheckCounterFeedBackReset = 1000; foo->interruptChecksEveryNms = 1; foo->nextPollTick = 0; foo->nextWakeupTick = 0; foo->lastTick = 0; /* cmd-. as used for Mac but no other OS */ foo->interruptKeycode = 2094; foo->interruptPending = 0; foo->semaphoresUseBufferA = 1; foo->semaphoresToSignalCountA = 0; foo->semaphoresToSignalCountB = 0; foo->deferDisplayUpdates = 0; foo->pendingFinalizationSignals = 0; foo->globalSessionID = 0; while (foo->globalSessionID == 0) { foo->globalSessionID = time(NULL) + ioMSecs(); } foo->jmpDepth = 0; foo->jmpMax = MaxJumpBuf; } /* Initialize endOfMemory to the top of oop storage space, reserving some space for forwarding blocks, and create the freeBlock from which space is allocated. Also create a fake free chunk at endOfMemory to act as a sentinal for memory scans. */ /* Note: The amount of space reserved for forwarding blocks should be chosen to ensure that incremental compactions can usually be done in a single pass. However, there should be enough forwarding blocks so a full compaction can be done in a reasonable number of passes, say ten. (A full compaction requires N object-moving passes, where N = number of non-garbage objects / number of forwarding blocks). di 11/18/2000 Re totalObjectCount: Provide a margin of one byte per object to be used for forwarding pointers at GC time. Since fwd blocks are 8 bytes, this means an absolute worst case of 8 passes to compact memory. In most cases it will be adequate to do compaction in a single pass. */ sqInt initializeMemoryFirstFree(usqInt firstFree) { register struct foo * foo = &fum; usqInt fwdBlockBytes; fwdBlockBytes = foo->totalObjectCount & (((WORD_MASK) - (BYTES_PER_WORD)) + 1); if (!((((usqInt) (foo->memoryLimit - fwdBlockBytes))) >= (((usqInt) (firstFree + (BASE_HEADER_SIZE)))))) { /* reserve enough space for a minimal free block of BaseHeaderSize bytes */ fwdBlockBytes = foo->memoryLimit - (firstFree + (BASE_HEADER_SIZE)); } foo->endOfMemory = foo->memoryLimit - fwdBlockBytes; foo->freeBlock = firstFree; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, ((foo->endOfMemory - firstFree) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); /* begin setSizeOfFree:to: */ longAtput(foo->endOfMemory, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); if (DoAssertionChecks) { if (!((foo->freeBlock < foo->endOfMemory) && (foo->endOfMemory < foo->memoryLimit))) { error("error in free space computation"); } if (!((foo->endOfMemory + (foo->headerTypeBytes[(longAt(foo->endOfMemory)) & TypeMask])) == foo->endOfMemory)) { error("header format must have changed"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("free block not properly initialized"); } } } /* Initialize object memory variables at startup time. Assume endOfMemory is initially set (by the image-reading code) to the end of the last object in the image. Initialization redefines endOfMemory to be the end of the object allocation area based on the total available memory, but reserving some space for forwarding blocks. */ /* Assume: image reader initializes the following variables: memory endOfMemory memoryLimit specialObjectsOop lastHash */ /* di 11/18/2000 fix slow full GC */ sqInt initializeObjectMemory(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt oop; sqInt oop1; sqInt oop2; /* image may be at a different address; adjust oops for new location */ foo->youngStart = foo->endOfMemory; foo->totalObjectCount = adjustAllOopsBy(bytesToShift); initializeMemoryFirstFree(foo->endOfMemory); /* heavily used special objects */ foo->specialObjectsOop += bytesToShift; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->nilObj = longAt((oop + (BASE_HEADER_SIZE)) + (NilObject << (SHIFT_FOR_WORD))); /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->falseObj = longAt((oop1 + (BASE_HEADER_SIZE)) + (FalseObject << (SHIFT_FOR_WORD))); /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; foo->trueObj = longAt((oop2 + (BASE_HEADER_SIZE)) + (TrueObject << (SHIFT_FOR_WORD))); foo->rootTableCount = 0; foo->freeContexts = NilContext; foo->freeLargeContexts = NilContext; foo->allocationCount = 0; foo->lowSpaceThreshold = 0; foo->signalLowSpace = 0; foo->compStart = 0; foo->compEnd = 0; foo->fwdTableNext = 0; foo->fwdTableLast = 0; foo->remapBufferCount = 0; /* do incremental GC after this many allocations */ foo->allocationsBetweenGCs = 4000; /* tenure all suriving objects if count is over this threshold */ foo->tenuringThreshold = 2000; /* four megabyte of headroom when growing */ foo->growHeadroom = (4 * 1024) * 1024; /* eight megabyte of free space before shrinking */ /* garbage collection statistics */ foo->shrinkThreshold = (8 * 1024) * 1024; foo->statFullGCs = 0; foo->statFullGCMSecs = 0; foo->statIncrGCs = 0; foo->statIncrGCMSecs = 0; foo->statTenures = 0; foo->statRootTableOverflows = 0; foo->statGrowMemory = 0; foo->statShrinkMemory = 0; foo->forceTenureFlag = 0; foo->gcBiasToGrow = 0; foo->gcBiasToGrowGCLimit = 0; foo->extraRootCount = 0; } /* Install the oop of this object in the given cache (at or atPut), along with its size, format and fixedSize */ sqInt installinAtCacheatstring(sqInt rcvr, sqInt * cache, sqInt atIx, sqInt stringy) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; if ((fmt == 3) && ((((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l3; } if (fmt < 2) { fixedFields = totalLength; goto l3; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l3: /* end fixedFieldsOf:format:length: */; cache[atIx + AtCacheOop] = rcvr; if (stringy) { cache[atIx + AtCacheFmt] = (fmt + 16); } else { cache[atIx + AtCacheFmt] = fmt; } cache[atIx + AtCacheFixedFields] = fixedFields; cache[atIx + AtCacheSize] = (totalLength - fixedFields); } /* NOTE: This method supports the backward-compatible split instSize field of the class format word. The sizeHiBits will go away and other shifts change by 2 when the split fields get merged in an (incompatible) image change. */ sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size) { register struct foo * foo = &fum; sqInt header1; sqInt binc; sqInt byteSize; sqInt hash; sqInt bm1; sqInt classFormat; sqInt header2; sqInt sizeHiBits; sqInt hdrSize; sqInt cClass; sqInt fillWord; sqInt newObj; sqInt format; sqInt header3; usqInt end; sqInt remappedClassOop; usqInt i; sqInt newObj1; sqInt oop; sqInt newFreeSize; sqInt enoughSpace; sqInt newChunk; usqInt minFree; sqInt sched; sqInt lastSavedProcess; sqInt currentProc; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; if (DoAssertionChecks) { if (size < 0) { error("cannot have a negative indexable field count"); } } /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; /* Low 2 bits are 0 */ classFormat = (longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; header1 = (classFormat & 130816) | ((hash << HashBitsOffset) & HashBits); header2 = classPointer; header3 = 0; sizeHiBits = ((usqInt) (classFormat & 393216)) >> 9; /* compact class field from format word */ cClass = header1 & CompactClassMask; /* size in bytes -- low 2 bits are 0 */ /* Note this byteSize comes from the format word of the class which is pre-shifted to 4 bytes per field. Need another shift for 8 bytes per word... */ byteSize = (classFormat & ((SIZE_MASK) + (SIZE_4_BIT))) + sizeHiBits; byteSize = byteSize << ((SHIFT_FOR_WORD) - 2); format = (((usqInt) classFormat) >> 8) & 15; flag("sizeLowBits"); if (format < 8) { if (format == 6) { /* long32 bitmaps */ bm1 = (BYTES_PER_WORD) - 1; /* round up */ byteSize = ((byteSize + (size * 4)) + bm1) & (LONG_SIZE_MASK); /* odd bytes */ /* extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits) */ binc = bm1 - (((size * 4) + bm1) & bm1); header1 = header1 | (binc & 4); } else { /* Arrays and 64-bit bitmaps */ byteSize += size * (BYTES_PER_WORD); } } else { /* Strings and Methods */ bm1 = (BYTES_PER_WORD) - 1; /* round up */ byteSize = ((byteSize + size) + bm1) & (LONG_SIZE_MASK); /* odd bytes */ /* low bits of byte size go in format field */ binc = bm1 - ((size + bm1) & bm1); /* extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits) */ header1 = header1 | ((binc & 3) << 8); header1 = header1 | (binc & 4); } if (byteSize > 255) { /* requires size header word */ header3 = byteSize; header1 = header1; } else { header1 = header1 | byteSize; } if (header3 > 0) { /* requires full header */ hdrSize = 3; } else { if (cClass == 0) { hdrSize = 2; } else { hdrSize = 1; } } if (format <= 4) { /* if pointers, fill with nil oop */ fillWord = foo->nilObj; } else { fillWord = 0; } /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lastSavedProcess = longAt((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop4 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop3 = foo->specialObjectsOop; if ((((usqInt) oop3)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop3, currentProc); } longAtput((oop3 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += byteSize + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj1 = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj1, header3 | HeaderTypeSizeAndClass); longAtput(newObj1 + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj1 + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj1 += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj1, remappedClassOop | HeaderTypeClass); longAtput(newObj1 + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj1 += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj1, header1 | HeaderTypeShort); } if (1) { end = newObj1 + byteSize; i = newObj1 + (BYTES_PER_WORD); while (i < end) { longAtput(i, fillWord); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj1); oopHasOkayClass(newObj1); if (!((objectAfter(newObj1)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } newObj = newObj1; return newObj; } /* This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include four bytes for the base header word. */ sqInt instantiateContextsizeInBytes(sqInt classPointer, sqInt sizeInBytes) { register struct foo * foo = &fum; sqInt header1; sqInt hash; sqInt header2; sqInt hdrSize; sqInt extendedSize; usqInt end; sqInt remappedClassOop; usqInt i; sqInt newObj; sqInt oop; sqInt newFreeSize; sqInt enoughSpace; sqInt newChunk; usqInt minFree; sqInt sched; sqInt lastSavedProcess; sqInt currentProc; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; header1 = ((hash << HashBitsOffset) & HashBits) | ((longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1); header2 = classPointer; if ((header1 & CompactClassMask) > 0) { /* are contexts compact? */ hdrSize = 1; } else { hdrSize = 2; } if (sizeInBytes <= (SIZE_MASK)) { /* OR size into header1. Must not do this if size > SizeMask */ header1 += sizeInBytes - (header1 & (SIZE_MASK)); } else { /* Zero the size field of header1 if large */ hdrSize = 3; header1 -= header1 & (SIZE_MASK); } flag("Dan"); /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ extendedSize = LARGE_CONTEXT_SIZE; if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lastSavedProcess = longAt((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop4 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop3 = foo->specialObjectsOop; if ((((usqInt) oop3)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop3, currentProc); } longAtput((oop3 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj, extendedSize | HeaderTypeSizeAndClass); longAtput(newObj + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj, remappedClassOop | HeaderTypeClass); longAtput(newObj + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj, header1 | HeaderTypeShort); } if (0) { end = newObj + sizeInBytes; i = newObj + (BYTES_PER_WORD); while (i < end) { longAtput(i, 0); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj); oopHasOkayClass(newObj); if (!((objectAfter(newObj)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } return newObj; } /* This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include 4 or 8 bytes for the base header word. NOTE this code will only work for sizes that are an integral number of words (like not a 32-bit LargeInteger in a 64-bit system). May cause a GC. Note that the created small object IS NOT FILLED and must be completed before returning it to Squeak. Since this call is used in routines that do jsut that we are safe. Break this rule and die. */ sqInt instantiateSmallClasssizeInBytes(sqInt classPointer, sqInt sizeInBytes) { register struct foo * foo = &fum; sqInt header1; sqInt hash; sqInt header2; sqInt hdrSize; usqInt end; sqInt remappedClassOop; usqInt i; sqInt newObj; sqInt oop; sqInt newFreeSize; sqInt enoughSpace; sqInt newChunk; usqInt minFree; sqInt sched; sqInt lastSavedProcess; sqInt currentProc; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; if (!((sizeInBytes & ((BYTES_PER_WORD) - 1)) == 0)) { error("size must be integral number of words"); } /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; header1 = ((hash << HashBitsOffset) & HashBits) | ((longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1); header2 = classPointer; if ((header1 & CompactClassMask) > 0) { /* is this a compact class */ hdrSize = 1; } else { hdrSize = 2; } header1 += sizeInBytes - (header1 & ((SIZE_MASK) + (SIZE_4_BIT))); /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lastSavedProcess = longAt((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop4 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop3 = foo->specialObjectsOop; if ((((usqInt) oop3)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop3, currentProc); } longAtput((oop3 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj, 0 | HeaderTypeSizeAndClass); longAtput(newObj + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj, remappedClassOop | HeaderTypeClass); longAtput(newObj + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj, header1 | HeaderTypeShort); } if (0) { end = newObj + sizeInBytes; i = newObj + (BYTES_PER_WORD); while (i < end) { longAtput(i, 0); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj); oopHasOkayClass(newObj); if (!((objectAfter(newObj)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } return newObj; } sqInt integerObjectOf(sqInt value) { return (value << 1) + 1; } /* Translator produces 'objectPointer >> 1' */ sqInt integerValueOf(sqInt objectPointer) { if ((objectPointer & 2147483648U) != 0) { return ((((usqInt) (objectPointer & 2147483647U)) >> 1) - 1073741823) - 1; } else { return ((usqInt) objectPointer) >> 1; } } EXPORT(sqInt) internalIsImmutable(sqInt oop) { return 0; } EXPORT(sqInt) internalIsMutable(sqInt oop) { return 1; } /* This is the main interpreter loop. It normally loops forever, fetching and executing bytecodes. When running in the context of a browser plugin VM, however, it must return control to the browser periodically. This should done only when the state of the currently running Squeak thread is safely stored in the object heap. Since this is the case at the moment that a check for interrupts is performed, that is when we return to the browser if it is time to do so. Interrupt checks happen quite frequently. */ sqInt interpret(void) { #ifdef FOO_REG register struct foo * foo FOO_REG = &fum; #endif sqInt localReturnValue; sqInt localReturnContext; sqInt localHomeContext; char* localSP; char* localIP; sqInt currentBytecode; JUMP_TABLE; browserPluginInitialiseIfNeeded(); initializeImageFormatVersionIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); while (1) { switch (currentBytecode) { CASE(0) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 0 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(1) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 1 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(2) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 2 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(3) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 3 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(4) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 4 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(5) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 5 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(6) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 6 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(7) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 7 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(8) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 8 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(9) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 9 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(10) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 10 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(11) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 11 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(12) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 12 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(13) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 13 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(14) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 14 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(15) /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 15 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(16) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 16 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(17) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 17 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(18) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 18 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(19) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 19 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(20) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 20 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(21) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 21 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(22) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 22 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(23) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 23 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(24) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 24 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(25) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 25 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(26) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 26 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(27) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 27 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(28) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 28 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(29) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 29 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(30) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 30 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(31) /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 31 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(32) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 32 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(33) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 33 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(34) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 34 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(35) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 35 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(36) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 36 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(37) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 37 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(38) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 38 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(39) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 39 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(40) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 40 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(41) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 41 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(42) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 42 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(43) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 43 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(44) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 44 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(45) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 45 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(46) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 46 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(47) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 47 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(48) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 48 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(49) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 49 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(50) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 50 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(51) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 51 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(52) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 52 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(53) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 53 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(54) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 54 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(55) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 55 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(56) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 56 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(57) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 57 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(58) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 58 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(59) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 59 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(60) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 60 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(61) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 61 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(62) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 62 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(63) /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 63 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(64) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 64 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(65) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 65 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(66) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 66 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(67) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 67 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(68) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 68 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(69) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 69 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(70) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 70 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(71) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 71 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(72) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 72 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(73) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 73 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(74) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 74 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(75) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 75 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(76) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 76 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(77) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 77 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(78) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 78 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(79) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 79 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(80) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 80 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(81) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 81 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(82) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 82 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(83) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 83 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(84) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 84 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(85) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 85 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(86) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 86 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(87) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 87 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(88) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 88 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(89) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 89 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(90) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 90 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(91) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 91 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(92) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 92 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(93) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 93 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(94) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 94 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(95) /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 95 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(96) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 96 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(97) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 97 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(98) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 98 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(99) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 99 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(100) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 100 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(101) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 101 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(102) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 102 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(103) /* storeAndPopReceiverVariableBytecode */ { sqInt top; sqInt rcvr; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 103 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(104) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (104 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(105) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (105 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(106) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (106 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(107) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (107 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(108) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (108 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(109) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (109 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(110) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (110 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(111) /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (111 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(112) /* pushReceiverBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->receiver); } ; BREAK; CASE(113) /* pushConstantTrueBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } ; BREAK; CASE(114) /* pushConstantFalseBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } ; BREAK; CASE(115) /* pushConstantNilBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->nilObj); } ; BREAK; CASE(116) /* pushConstantMinusOneBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstMinusOne); } ; BREAK; CASE(117) /* pushConstantZeroBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstZero); } ; BREAK; CASE(118) /* pushConstantOneBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstOne); } ; BREAK; CASE(119) /* pushConstantTwoBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstTwo); } ; BREAK; CASE(120) /* returnReceiver */ { sqInt context; sqInt closureOrNil; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->receiver; /* goto commonReturn */ } ; commonReturn: /* commonReturn */ { sqInt localVal; sqInt nilOop; sqInt unwindMarked; sqInt thisCntx; sqInt contextOfCaller; sqInt localCntx; sqInt meth; sqInt header; sqInt pIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt primBits; sqInt header1; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; /* inline: */; nilOop = foo->nilObj; thisCntx = foo->activeContext; localCntx = localReturnContext; localVal = localReturnValue; if ((localCntx == nilOop) || ((longAt((localCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) == nilOop)) { /* begin internalCannotReturn: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + (SelectorCannotReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l42; } /* begin fetchPointer:ofObject: */ oop = foo->activeContext; thisCntx = longAt((oop + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); while (!(thisCntx == localCntx)) { if (thisCntx == nilOop) { /* begin internalCannotReturn: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; foo->messageSelector = longAt((oop2 + (BASE_HEADER_SIZE)) + (SelectorCannotReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l42; } /* begin isUnwindMarked: */ header = longAt(thisCntx); if (!(((((usqInt) header) >> 12) & 31) == 14)) { unwindMarked = 0; goto l43; } meth = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); unwindMarked = pIndex == 198; l43: /* end isUnwindMarked: */; if (unwindMarked) { /* begin internalAboutToReturn:through: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, thisCntx); /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; foo->messageSelector = longAt((oop3 + (BASE_HEADER_SIZE)) + (SelectorAboutToReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 2; goto normalSend; goto l42; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } thisCntx = foo->activeContext; while (!(thisCntx == localCntx)) { contextOfCaller = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); longAtput((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), nilOop); longAtput((thisCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), nilOop); if (foo->reclaimableContextCount > 0) { foo->reclaimableContextCount -= 1; /* begin recycleContextIfPossible: */ if ((((usqInt) thisCntx)) >= (((usqInt) foo->youngStart))) { header1 = longAt(thisCntx); if (((((usqInt) header1) >> 12) & 31) == 14) { if ((header1 & (SIZE_MASK)) == (SMALL_CONTEXT_SIZE)) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->freeContexts; longAtput((thisCntx + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer); foo->freeContexts = thisCntx; } if ((header1 & (SIZE_MASK)) == (LARGE_CONTEXT_SIZE)) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->freeLargeContexts; longAtput((thisCntx + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer1); foo->freeLargeContexts = thisCntx; } } } } thisCntx = contextOfCaller; } foo->activeContext = thisCntx; if ((((usqInt) thisCntx)) < (((usqInt) foo->youngStart))) { beRootIfOld(thisCntx); } /* begin internalFetchContextRegisters: */ tmp = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((thisCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = thisCntx; } localHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((thisCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localIP = pointerForOop(((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2); tmp = ((longAt((thisCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localSP = pointerForOop((thisCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD))); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); } ; l42: /* end case */; BREAK; CASE(121) /* returnTrue */ { sqInt context; sqInt closureOrNil; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->trueObj; goto commonReturn; } ; BREAK; CASE(122) /* returnFalse */ { sqInt context; sqInt closureOrNil; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->falseObj; goto commonReturn; } ; BREAK; CASE(123) /* returnNil */ { sqInt context; sqInt closureOrNil; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->nilObj; goto commonReturn; } ; BREAK; CASE(124) /* returnTopFromMethod */ { sqInt context; sqInt closureOrNil; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = longAtPointer(localSP); goto commonReturn; } ; BREAK; CASE(125) /* returnTopFromBlock */ { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->activeContext; localReturnContext = longAt((oop + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD))); localReturnValue = longAtPointer(localSP); goto commonReturn; } ; BREAK; CASE(126) CASE(127) /* unknownBytecode */ { error("Unknown bytecode"); } ; BREAK; CASE(128) /* extendedPushBytecode */ { sqInt variableIndex; sqInt descriptor; sqInt variableType; sqInt object; sqInt oop; sqInt object1; sqInt oop1; sqInt object2; sqInt methodPointer; sqInt object3; sqInt oop2; sqInt methodPointer1; descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin pushReceiverVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); goto l1; } if (variableType == 1) { /* begin pushTemporaryVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop1 = localHomeContext; object1 = longAt((oop1 + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object1); goto l1; } if (variableType == 2) { /* begin pushLiteralConstant: */ /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object2 = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object2); goto l1; } if (variableType == 3) { /* begin pushLiteralVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer1 = foo->method; oop2 = longAt((methodPointer1 + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); object3 = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object3); goto l1; } } ; l1: /* end case */; BREAK; CASE(129) /* extendedStoreBytecode */ { sqInt variableIndex; sqInt association; sqInt descriptor; sqInt variableType; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt valuePointer1; sqInt methodPointer; sqInt valuePointer2; descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin storePointer:ofObject:withValue: */ oop1 = foo->receiver; valuePointer1 = longAtPointer(localSP); if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer1); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD)), valuePointer1); goto l2; } if (variableType == 1) { /* begin storePointerUnchecked:ofObject:withValue: */ oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD)), valuePointer); goto l2; } if (variableType == 2) { error("illegal store"); } if (variableType == 3) { /* begin literal:ofMethod: */ methodPointer = foo->method; association = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAtPointer(localSP); if ((((usqInt) association)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(association, valuePointer2); } longAtput((association + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), valuePointer2); goto l2; } } ; l2: /* end case */; BREAK; CASE(130) /* extendedStoreAndPopBytecode */ { sqInt variableIndex; sqInt association; sqInt descriptor; sqInt variableType; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt valuePointer1; sqInt methodPointer; sqInt valuePointer2; /* begin extendedStoreBytecode */ descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin storePointer:ofObject:withValue: */ oop1 = foo->receiver; valuePointer1 = longAtPointer(localSP); if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer1); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD)), valuePointer1); goto l3; } if (variableType == 1) { /* begin storePointerUnchecked:ofObject:withValue: */ oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD)), valuePointer); goto l3; } if (variableType == 2) { error("illegal store"); } if (variableType == 3) { /* begin literal:ofMethod: */ methodPointer = foo->method; association = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAtPointer(localSP); if ((((usqInt) association)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(association, valuePointer2); } longAtput((association + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), valuePointer2); goto l3; } l3: /* end extendedStoreBytecode */; /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(131) /* singleExtendedSendBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 31) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 5; /* goto normalSend */ } ; normalSend: /* normalSend */ { sqInt rcvr; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; /* inline: */; rcvr = longAtPointer(localSP - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->lkupClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l44; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { foo->lkupClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l44; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); foo->lkupClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l44; } l44: /* end fetchClassOf: */; foo->receiverClass = foo->lkupClass; /* goto commonSend */ } ; commonSend: /* commonSend */ { sqInt ok; sqInt hash; sqInt probe; sqInt delta; sqInt localPrimIndex; sqInt nArgs; sqInt oop; sqInt oop1; sqInt tempCount; sqInt where; sqInt needsLarge; sqInt i; sqInt argCount2; sqInt newContext; sqInt methodHeader; sqInt methodPointer; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; /* begin internalFindNewMethod */ /* begin lookupInMethodCacheSel:class: */ hash = foo->messageSelector ^ foo->lkupClass; probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } ok = 0; l45: /* end lookupInMethodCacheSel:class: */; if (!(ok)) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; lookupMethodInClass(foo->lkupClass); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; addNewMethodToCache(); } /* begin internalExecuteNewMethod */ localPrimIndex = foo->primitiveIndex; if (localPrimIndex > 0) { if ((localPrimIndex > 255) && (localPrimIndex < 520)) { if (localPrimIndex >= 264) { /* begin internalPop:thenPush: */ /* begin fetchPointer:ofObject: */ oop1 = longAtPointer(localSP); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + ((localPrimIndex - 264) << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); goto l46; } else { if (localPrimIndex == 256) { goto l46; } if (localPrimIndex == 257) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->trueObj); goto l46; } if (localPrimIndex == 258) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->falseObj); goto l46; } if (localPrimIndex == 259) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->nilObj); goto l46; } /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), (((localPrimIndex - 261) << 1) | 1)); goto l46; } } else { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; if (DoBalanceChecks) { nArgs = foo->argumentCount; delta = foo->stackPointer - foo->activeContext; } foo->successFlag = 1; dispatchFunctionPointer(foo->primitiveFunctionPointer); if (DoBalanceChecks) { if (!(balancedStackafterPrimitivewithArgs(delta, localPrimIndex, nArgs))) { printUnbalancedStack(localPrimIndex); } } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { browserPluginReturnIfNeeded(); goto l46; } } } /* begin internalActivateNewMethod */ /* begin headerOf: */ methodPointer = foo->newMethod; methodHeader = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); needsLarge = methodHeader & LargeContextBit; if ((needsLarge == 0) && (foo->freeContexts != NilContext)) { newContext = foo->freeContexts; foo->freeContexts = longAt((newContext + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); } else { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; newContext = allocateOrRecycleContext(needsLarge); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } tempCount = (((usqInt) methodHeader) >> 19) & 63; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), (((((LiteralStart + ((((usqInt) methodHeader) >> 10) & 255)) * (BYTES_PER_WORD)) + 1) << 1) | 1)); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), ((tempCount << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), foo->newMethod); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), foo->nilObj); argCount2 = foo->argumentCount; for (i = 0; i <= argCount2; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAtPointer(localSP - ((argCount2 - i) * (BYTES_PER_WORD)))); } methodHeader = foo->nilObj; for (i = ((argCount2 + 1) + ReceiverIndex); i <= (tempCount + ReceiverIndex); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), methodHeader); } /* begin internalPop: */ localSP -= (argCount2 + 1) * (BYTES_PER_WORD); foo->reclaimableContextCount += 1; /* begin internalNewActiveContext: */ /* begin internalStoreContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = (((((oopForPointer(localIP)) + 2) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((oopForPointer(localSP)) - (activeCntx + (BASE_HEADER_SIZE)))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin internalFetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } localHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localIP = pointerForOop(((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localSP = pointerForOop((newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD))); /* begin internalQuickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; checkForInterrupts(); browserPluginReturnIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } l46: /* end internalExecuteNewMethod */; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; BREAK; CASE(132) /* doubleExtendedDoAnythingBytecode */ { sqInt top; sqInt opType; sqInt byte3; sqInt byte2; sqInt oop; sqInt oop1; sqInt oop2; sqInt methodPointer; sqInt methodPointer1; sqInt object; sqInt oop3; sqInt methodPointer2; sqInt object1; sqInt methodPointer3; sqInt object2; sqInt oop4; sqInt methodPointer4; byte2 = byteAtPointer(++localIP); byte3 = byteAtPointer(++localIP); opType = ((usqInt) byte2) >> 5; if (opType == 0) { /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = byte2 & 31; goto normalSend; goto l4; } if (opType == 1) { /* begin literal:ofMethod: */ methodPointer1 = foo->method; foo->messageSelector = longAt((methodPointer1 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = byte2 & 31; goto commonSupersend; goto l4; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (opType == 2) { /* begin pushReceiverVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop3 = foo->receiver; object = longAt((oop3 + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); goto l4; } if (opType == 3) { /* begin pushLiteralConstant: */ /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer3 = foo->method; object1 = longAt((methodPointer3 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object1); goto l4; } if (opType == 4) { /* begin pushLiteralVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer4 = foo->method; oop4 = longAt((methodPointer4 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); object2 = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object2); goto l4; } if (opType == 5) { top = longAtPointer(localSP); /* begin storePointer:ofObject:withValue: */ oop = foo->receiver; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, top); } longAtput((oop + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD)), top); goto l4; } if (opType == 6) { top = longAtPointer(localSP); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); /* begin storePointer:ofObject:withValue: */ oop1 = foo->receiver; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, top); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD)), top); goto l4; } if (opType == 7) { top = longAtPointer(localSP); /* begin storePointer:ofObject:withValue: */ /* begin literal:ofMethod: */ methodPointer2 = foo->method; oop2 = longAt((methodPointer2 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); if ((((usqInt) oop2)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop2, top); } longAtput((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), top); goto l4; } } ; l4: /* end case */; BREAK; CASE(133) /* singleExtendedSuperBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 31) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 5; /* goto commonSupersend */ } ; commonSupersend: /* superclassSend */ { sqInt rcvr; sqInt classPointer; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt methodPointer; sqInt oop3; sqInt offset; /* inline: */; /* begin superclassOf: */ /* begin methodClassOf: */ methodPointer = foo->method; /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ offset = (literalCountOfHeader(longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) - 1; oop3 = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); classPointer = longAt((oop3 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); foo->lkupClass = longAt((classPointer + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); rcvr = longAtPointer(localSP - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->receiverClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l47; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { foo->receiverClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l47; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); foo->receiverClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l47; } l47: /* end fetchClassOf: */; goto commonSend; } ; BREAK; CASE(134) /* secondExtendedSendBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 63) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 6; goto normalSend; } ; BREAK; CASE(135) /* popStackBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(136) /* duplicateTopBytecode */ { sqInt object; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ object = longAtPointer(localSP); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(137) /* pushActiveContextBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); foo->reclaimableContextCount = 0; /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); } ; BREAK; CASE(138) /* pushNewArrayBytecode */ { sqInt i; sqInt size; sqInt array; sqInt popValues; sqInt valuePointer; size = byteAtPointer(++localIP); popValues = size > 127; size = size & 127; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; array = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), size); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (popValues) { for (i = 0; i <= (size - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAtPointer(localSP - (((size - i) - 1) * (BYTES_PER_WORD))); longAtput((array + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); } /* begin internalPop: */ localSP -= size * (BYTES_PER_WORD); } /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, array); } ; BREAK; CASE(139) /* unknownBytecode */ { error("Unknown bytecode"); } ; BREAK; CASE(140) /* pushRemoteTempLongBytecode */ { sqInt tempVectorIndex; sqInt remoteTempIndex; sqInt tempVector; sqInt oop; sqInt object; remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin internalPush: */ object = longAt((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; BREAK; CASE(141) /* storeRemoteTempLongBytecode */ { sqInt tempVectorIndex; sqInt remoteTempIndex; sqInt tempVector; sqInt oop; sqInt valuePointer; remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storeRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer = longAtPointer(localSP); if ((((usqInt) tempVector)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(tempVector, valuePointer); } longAtput((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD)), valuePointer); } ; BREAK; CASE(142) /* storeAndPopRemoteTempLongBytecode */ { sqInt tempVectorIndex; sqInt remoteTempIndex; sqInt tempVector; sqInt oop; sqInt valuePointer; /* begin storeRemoteTempLongBytecode */ remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storeRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer = longAtPointer(localSP); if ((((usqInt) tempVector)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(tempVector, valuePointer); } longAtput((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; BREAK; CASE(143) /* pushClosureCopyCopiedValuesBytecode */ { sqInt numArgsNumCopied; sqInt numCopied; sqInt i; sqInt numArgs; sqInt newClosure; sqInt blockSize; sqInt valuePointer; sqInt initialIP; sqInt newClosure1; sqInt valuePointer1; if ((BYTES_PER_WORD) == 4) { imageFormatVersionNumber = 6504; } else { imageFormatVersionNumber = 68002; } numArgsNumCopied = byteAtPointer(++localIP); numArgs = numArgsNumCopied & 15; numCopied = ((usqInt) numArgsNumCopied >> 4); blockSize = (byteAtPointer(++localIP)) << 8; blockSize += byteAtPointer(++localIP); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin closureNumArgs:instructionPointer:numCopiedValues: */ initialIP = ((oopForPointer(localIP)) + 2) - (foo->method + (BASE_HEADER_SIZE)); newClosure1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop), ((BYTES_PER_WORD) * (ClosureFirstCopiedValueIndex + numCopied)) + (BASE_HEADER_SIZE)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)), ((numArgs << 1) | 1)); newClosure = newClosure1; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->activeContext; longAtput((newClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD)), valuePointer1); foo->reclaimableContextCount = 0; if (numCopied > 0) { for (i = 0; i <= (numCopied - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAtPointer(localSP - (((numCopied - i) - 1) * (BYTES_PER_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)), valuePointer); } /* begin internalPop: */ localSP -= numCopied * (BYTES_PER_WORD); } localIP += blockSize; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, newClosure); } ; BREAK; CASE(144) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (144 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(145) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (145 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(146) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (146 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(147) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (147 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(148) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (148 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(149) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (149 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(150) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (150 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(151) /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (151 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; BREAK; CASE(152) CASE(153) CASE(154) CASE(155) CASE(156) CASE(157) CASE(158) CASE(159) /* shortConditionalJump */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfFalseBy: */ offset = (currentBytecode & 7) + 1; boolean = longAtPointer(localSP); if (boolean == foo->falseObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->trueObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l5; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l5: /* end jumplfFalseBy: */; } ; BREAK; CASE(160) CASE(161) CASE(162) CASE(163) CASE(164) CASE(165) CASE(166) CASE(167) /* longUnconditionalJump */ { sqInt offset; offset = (((currentBytecode & 7) - 4) * 256) + (byteAtPointer(++localIP)); localIP += offset; if (offset < 0) { /* begin internalQuickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; checkForInterrupts(); browserPluginReturnIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; BREAK; CASE(168) CASE(169) CASE(170) CASE(171) /* longJumpIfTrue */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfTrueBy: */ offset = ((currentBytecode & 3) * 256) + (byteAtPointer(++localIP)); boolean = longAtPointer(localSP); if (boolean == foo->trueObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->falseObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l6; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l6: /* end jumplfTrueBy: */; } ; BREAK; CASE(172) CASE(173) CASE(174) CASE(175) /* longJumpIfFalse */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfFalseBy: */ offset = ((currentBytecode & 3) * 256) + (byteAtPointer(++localIP)); boolean = longAtPointer(localSP); if (boolean == foo->falseObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->trueObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l7; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l7: /* end jumplfFalseBy: */; } ; BREAK; CASE(176) /* bytecodePrimAdd */ { sqInt arg; sqInt result; sqInt rcvr; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { result = ((rcvr >> 1)) + ((arg >> 1)); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l8; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatAddtoArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l8; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((0 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l8: /* end case */; BREAK; CASE(177) /* bytecodePrimSubtract */ { sqInt arg; sqInt result; sqInt rcvr; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { result = ((rcvr >> 1)) - ((arg >> 1)); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l9; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatSubtractfromArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l9; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((1 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l9: /* end case */; BREAK; CASE(178) /* bytecodePrimLessThan */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr < arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr < arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr < arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l10; } foo->successFlag = 1; aBool = primitiveFloatLessthanArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l10; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((2 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l10: /* end case */; BREAK; CASE(179) /* bytecodePrimGreaterThan */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr > arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr > arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr > arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l11; } foo->successFlag = 1; aBool = primitiveFloatGreaterthanArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l11; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((3 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l11: /* end case */; BREAK; CASE(180) /* bytecodePrimLessOrEqual */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr <= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr <= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr <= arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l12; } foo->successFlag = 1; aBool = primitiveFloatLessOrEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l12; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((4 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l12: /* end case */; BREAK; CASE(181) /* bytecodePrimGreaterOrEqual */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr >= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr >= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr >= arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l13; } foo->successFlag = 1; aBool = primitiveFloatGreaterOrEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l13; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((5 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l13: /* end case */; BREAK; CASE(182) /* bytecodePrimEqual */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr == arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l14; } foo->successFlag = 1; aBool = primitiveFloatEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l14; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((6 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l14: /* end case */; BREAK; CASE(183) /* bytecodePrimNotEqual */ { sqInt arg; sqInt rcvr; sqInt aBool; sqInt oop; sqInt oop1; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr != arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr != arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr != arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l15; } foo->successFlag = 1; aBool = primitiveFloatEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (!aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (!aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (!aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l15; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((7 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l15: /* end case */; BREAK; CASE(184) /* bytecodePrimMultiply */ { sqInt arg; sqInt result; sqInt rcvr; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { rcvr = (rcvr >> 1); arg = (arg >> 1); result = rcvr * arg; if (((arg == 0) || ((result / arg) == rcvr)) && ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 )) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l16; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatMultiplybyArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l16; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((8 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l16: /* end case */; BREAK; CASE(185) /* bytecodePrimDivide */ { sqInt arg; sqInt result; sqInt rcvr; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { rcvr = (rcvr >> 1); arg = (arg >> 1); if ((arg != 0) && ((rcvr % arg) == 0)) { result = rcvr / arg; if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l17; } } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatDividebyArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l17; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((9 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l17: /* end case */; BREAK; CASE(186) /* bytecodePrimMod */ { sqInt mod; sqInt oop; sqInt oop1; foo->successFlag = 1; mod = doPrimitiveModby(longAtPointer(localSP - (1 * (BYTES_PER_WORD))), longAtPointer(localSP - (0 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((mod << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l18; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((10 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l18: /* end case */; BREAK; CASE(187) /* bytecodePrimMakePoint */ { sqInt oop; sqInt oop1; sqInt argument; sqInt pt; sqInt rcvr; sqInt pointResult; sqInt pointResult1; sqInt valuePointer; sqInt pointResult2; sqInt valuePointer1; sqInt valuePointer2; sqInt sp; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveMakePoint */ argument = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((rcvr & 1)) { if ((argument & 1)) { /* begin makePointwithxValue:yValue: */ pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((((argument >> 1)) << 1) | 1)); pt = pointResult; } else { /* begin makePointwithxValue:yValue: */ pointResult1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult1; /* begin storePointer:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer); } } else { if (!((fetchClassOf(rcvr)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; goto l20; } /* begin makePointwithxValue:yValue: */ pointResult2 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult2; /* begin storePointer:ofObject:withValue: */ valuePointer1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer1); } longAtput((pt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer1); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer2); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer2); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), pt); foo->stackPointer = sp; l20: /* end primitiveMakePoint */; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l19; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((11 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l19: /* end case */; BREAK; CASE(188) /* bytecodePrimBitShift */ { sqInt oop; sqInt oop1; sqInt integerArgument; sqInt shifted; sqInt integerReceiver; sqInt integerPointer; sqInt object; sqInt sp; sqInt top; sqInt top2; sqInt top1; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitShift */ /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l22; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l22; } l22: /* end checkedIntegerValueOf: */; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top1; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { if (integerArgument >= 0) { /* begin success: */ foo->successFlag = (integerArgument <= 31) && foo->successFlag; shifted = integerReceiver << integerArgument; /* begin success: */ foo->successFlag = ((((usqInt) shifted) >> integerArgument) == integerReceiver) && foo->successFlag; } else { /* begin success: */ foo->successFlag = (integerArgument >= -31) && foo->successFlag; shifted = ((integerArgument < 0) ? ((usqInt) integerReceiver >> -integerArgument) : ((usqInt) integerReceiver << integerArgument)); } } if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(shifted); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l21; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((12 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l21: /* end case */; BREAK; CASE(189) /* bytecodePrimDiv */ { sqInt quotient; sqInt oop; sqInt oop1; foo->successFlag = 1; quotient = doPrimitiveDivby(longAtPointer(localSP - (1 * (BYTES_PER_WORD))), longAtPointer(localSP - (0 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((quotient << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l23; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((13 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l23: /* end case */; BREAK; CASE(190) /* bytecodePrimBitAnd */ { sqInt integerArgument; sqInt integerReceiver; sqInt object; sqInt sp; sqInt oop; sqInt top; sqInt top1; sqInt top2; sqInt top11; sqInt oop1; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitAnd */ /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top11 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top11; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver & integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l24; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((14 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l24: /* end case */; BREAK; CASE(191) /* bytecodePrimBitOr */ { sqInt oop; sqInt integerArgument; sqInt integerReceiver; sqInt object; sqInt sp; sqInt top; sqInt top1; sqInt top2; sqInt top11; sqInt oop1; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitOr */ /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top11 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top11; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver | integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l25; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((15 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l25: /* end case */; BREAK; CASE(192) /* bytecodePrimAt */ { sqInt result; sqInt atIx; sqInt rcvr; sqInt index; sqInt oop; sqInt result1; sqInt fmt; sqInt fixedFields; sqInt stSize; sqInt oop1; sqInt oop2; sqInt oop11; index = longAtPointer(localSP); rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->successFlag = (!((rcvr & 1))) && ((index & 1)); if (foo->successFlag) { atIx = rcvr & AtCacheMask; if ((foo->atCache[atIx + AtCacheOop]) == rcvr) { /* begin commonVariableInternal:at:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) ((index >> 1)))) >= (((usqInt) 1))) && ((((usqInt) ((index >> 1)))) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; result = longAt((rcvr + (BASE_HEADER_SIZE)) + (((((index >> 1)) + fixedFields) - 1) << (SHIFT_FOR_WORD))); goto l27; } if (fmt < 8) { result1 = long32At((rcvr + (BASE_HEADER_SIZE)) + ((((index >> 1)) - 1) << 2)); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; result1 = positive32BitIntegerFor(result1); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; result = result1; goto l27; } if (fmt >= 16) { /* begin characterForAscii: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop11 = foo->specialObjectsOop; oop2 = longAt((oop11 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); result = longAt((oop2 + (BASE_HEADER_SIZE)) + ((byteAt((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1))) << (SHIFT_FOR_WORD))); goto l27; } else { result = (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1))) << 1) | 1); goto l27; } } /* begin primitiveFail */ foo->successFlag = 0; l27: /* end commonVariableInternal:at:cacheIndex: */; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), result); goto l26; } } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((16 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l26: /* end case */; BREAK; CASE(193) /* bytecodePrimAtPut */ { sqInt value; sqInt atIx; sqInt rcvr; sqInt index; sqInt oop; sqInt oop1; sqInt valToPut; sqInt fmt; sqInt fixedFields; sqInt stSize; value = longAtPointer(localSP); index = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); rcvr = longAtPointer(localSP - (2 * (BYTES_PER_WORD))); foo->successFlag = (!((rcvr & 1))) && ((index & 1)); if (foo->successFlag) { atIx = (rcvr & AtCacheMask) + AtPutBase; if ((foo->atCache[atIx + AtCacheOop]) == rcvr) { /* begin commonVariable:at:put:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) ((index >> 1)))) >= (((usqInt) 1))) && ((((usqInt) ((index >> 1)))) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, value); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (((((index >> 1)) + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); goto l29; } if (fmt < 8) { valToPut = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((((index >> 1)) - 1) << 2), valToPut); } goto l29; } if (fmt >= 16) { valToPut = asciiOfCharacter(value); if (!(foo->successFlag)) { goto l29; } } else { valToPut = value; } if ((valToPut & 1)) { valToPut = (valToPut >> 1); if (!((valToPut >= 0) && (valToPut <= 255))) { /* begin primitiveFail */ foo->successFlag = 0; goto l29; } byteAtput((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1), valToPut); goto l29; } } /* begin primitiveFail */ foo->successFlag = 0; l29: /* end commonVariable:at:put:cacheIndex: */; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (3 - 1) * (BYTES_PER_WORD), value); goto l28; } } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((17 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 2; goto normalSend; } ; l28: /* end case */; BREAK; CASE(194) /* bytecodePrimSize */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((18 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; BREAK; CASE(195) /* bytecodePrimNext */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((19 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; BREAK; CASE(196) /* bytecodePrimNextPut */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((20 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; BREAK; CASE(197) /* bytecodePrimAtEnd */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((21 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; BREAK; CASE(198) /* bytecodePrimEquivalent */ { sqInt arg; sqInt rcvr; sqInt bytecode; sqInt offset; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l30; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l30; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l30; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l30; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr == arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } l30: /* end booleanCheat: */; } ; BREAK; CASE(199) /* bytecodePrimClass */ { sqInt rcvr; sqInt oop; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; rcvr = longAtPointer(localSP); /* begin internalPop:thenPush: */ /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l31; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { oop = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l31; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l31; } l31: /* end fetchClassOf: */; longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; BREAK; CASE(200) /* bytecodePrimBlockCopy */ { sqInt hdr; sqInt rcvr; sqInt oop; sqInt successValue; sqInt oop1; sqInt methodContext; sqInt context; sqInt initialIP; sqInt newContext; sqInt contextSize; sqInt header; sqInt oop2; sqInt valuePointer; sqInt valuePointer1; sqInt sp; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->successFlag = 1; hdr = longAt(rcvr); /* begin success: */ successValue = (((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBlockCopy */ context = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (((longAt((context + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))) & 1)) { methodContext = longAt((context + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); } else { methodContext = context; } /* begin sizeBitsOf: */ header = longAt(methodContext); if ((header & TypeMask) == HeaderTypeSizeAndClass) { contextSize = (longAt(methodContext - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l33; } else { contextSize = header & (SIZE_MASK); goto l33; } l33: /* end sizeBitsOf: */; context = null; /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = methodContext; newContext = instantiateContextsizeInBytes(fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop), contextSize); /* begin popRemappableOop */ oop2 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; methodContext = oop2; initialIP = (((((foo->instructionPointer + 1) + 3) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((newContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD)), initialIP); longAtput((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ longAtput((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); longAtput((newContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD)), valuePointer); longAtput((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD)), methodContext); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->nilObj; longAtput((newContext + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), valuePointer1); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), newContext); foo->stackPointer = sp; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((24 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l32; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l32: /* end case */; BREAK; CASE(201) /* bytecodePrimValue */ { sqInt rcvrClass; sqInt maybeBlock; sqInt oop; sqInt oop1; sqInt ccIndex; sqInt oop11; sqInt oop2; maybeBlock = longAtPointer(localSP); foo->argumentCount = 0; foo->successFlag = 1; if ((maybeBlock & 1) == 0) { /* begin fetchClassOfNonInt: */ ccIndex = (((usqInt) (longAt(maybeBlock))) >> 12) & 31; if (ccIndex == 0) { rcvrClass = (longAt(maybeBlock - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l35; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop11 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); rcvrClass = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l35; } l35: /* end fetchClassOfNonInt: */; if (rcvrClass == (fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveClosureValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { if (rcvrClass == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { foo->successFlag = 0; } } } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((25 * 2) << (SHIFT_FOR_WORD))); goto normalSend; goto l34; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l34: /* end case */; BREAK; CASE(202) /* bytecodePrimValueWithArg */ { sqInt rcvrClass; sqInt maybeBlock; sqInt oop; sqInt oop1; sqInt ccIndex; sqInt oop11; sqInt oop2; maybeBlock = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->argumentCount = 1; foo->successFlag = 1; if ((maybeBlock & 1) == 0) { /* begin fetchClassOfNonInt: */ ccIndex = (((usqInt) (longAt(maybeBlock))) >> 12) & 31; if (ccIndex == 0) { rcvrClass = (longAt(maybeBlock - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l37; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop11 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); rcvrClass = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l37; } l37: /* end fetchClassOfNonInt: */; if (rcvrClass == (fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveClosureValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { if (rcvrClass == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { foo->successFlag = 0; } } } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((26 * 2) << (SHIFT_FOR_WORD))); goto normalSend; goto l36; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l36: /* end case */; BREAK; CASE(203) /* bytecodePrimDo */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((27 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; BREAK; CASE(204) /* bytecodePrimNew */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((28 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; BREAK; CASE(205) /* bytecodePrimNewWithArg */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((29 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; BREAK; CASE(206) /* bytecodePrimPointX */ { sqInt rcvr; sqInt oop; sqInt oop1; sqInt oop2; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop11; sqInt oop21; sqInt oop3; foo->successFlag = 1; rcvr = longAtPointer(localSP); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); if ((rcvr & 1)) { foo->successFlag = 0; goto l39; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l39: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin internalPop:thenPush: */ oop = longAt((rcvr + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l38; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + ((30 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; l38: /* end case */; BREAK; CASE(207) /* bytecodePrimPointY */ { sqInt rcvr; sqInt oop; sqInt oop1; sqInt oop2; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop11; sqInt oop21; sqInt oop3; foo->successFlag = 1; rcvr = longAtPointer(localSP); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); if ((rcvr & 1)) { foo->successFlag = 0; goto l41; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l41: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin internalPop:thenPush: */ oop = longAt((rcvr + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l40; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + ((31 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; l40: /* end case */; BREAK; CASE(208) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 208 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 208) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(209) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 209 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 209) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(210) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 210 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 210) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(211) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 211 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 211) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(212) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 212 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 212) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(213) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 213 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 213) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(214) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 214 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 214) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(215) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 215 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 215) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(216) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 216 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 216) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(217) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 217 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 217) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(218) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 218 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 218) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(219) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 219 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 219) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(220) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 220 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 220) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(221) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 221 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 221) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(222) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 222 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 222) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(223) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 223 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 223) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(224) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 224 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 224) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(225) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 225 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 225) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(226) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 226 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 226) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(227) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 227 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 227) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(228) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 228 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 228) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(229) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 229 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 229) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(230) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 230 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 230) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(231) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 231 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 231) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(232) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 232 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 232) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(233) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 233 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 233) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(234) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 234 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 234) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(235) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 235 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 235) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(236) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 236 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 236) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(237) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 237 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 237) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(238) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 238 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 238) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(239) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 239 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 239) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(240) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 240 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 240) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(241) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 241 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 241) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(242) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 242 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 242) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(243) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 243 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 243) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(244) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 244 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 244) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(245) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 245 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 245) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(246) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 246 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 246) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(247) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 247 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 247) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(248) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 248 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 248) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(249) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 249 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 249) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(250) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 250 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 250) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(251) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 251 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 251) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(252) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 252 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 252) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(253) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 253 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 253) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(254) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 254 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 254) >> 4) & 3) - 1; goto normalSend; } ; BREAK; CASE(255) /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 255 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 255) >> 4) & 3) - 1; goto normalSend; } ; BREAK; } } /* undo the pre-increment of IP before returning */ localIP -= 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; } /* the vm has to convert aFilenameString via any canonicalization and char-mapping and put the result in aCharBuffer. Note the resolveAliases flag - this is an awful artefact of OSX and Apples demented alias handling. When opening a file, the flag must be true, when closing or renaming it must be false. Sigh. */ sqInt ioFilenamefromStringofLengthresolveAliases(char * aCharBuffer, char * aFilenameString, sqInt filenameLength, sqInt aBoolean) { sqGetFilenameFromString(aCharBuffer, aFilenameString, filenameLength, aBoolean); } /* Support for external primitives. */ sqInt isKindOf(sqInt oop, char * className) { register struct foo * foo = &fum; sqInt oopClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oopClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { oopClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oopClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; while (!(oopClass == foo->nilObj)) { if (classNameOfIs(oopClass, className)) { return 1; } oopClass = longAt((oopClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } return 0; } /* Support for external primitives */ sqInt isMemberOf(sqInt oop, char * className) { register struct foo * foo = &fum; sqInt oopClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oopClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { oopClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oopClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; return classNameOfIs(oopClass, className); } /* Answer true if this is an indexable object with pointer elements, e.g., an array */ sqInt isArray(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 2); } /* Answer true (non-zero) if running on a big endian machine. */ sqInt isBigEnder(void) { char * cString; sqInt i; sqInt anInt; static sqInt endianness = -1; sqInt len; if (!(endianness == -1)) { return endianness; } len = sizeof(anInt); cString = (char *) &anInt; i = 0; while (i < len) { cString[i] = i; i += 1; } endianness = anInt & 255; return endianness; } /* Answer true if the argument contains indexable bytes. See comment in formatOf: */ /* Note: Includes CompiledMethods. */ sqInt isBytes(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8); } /* Answer true if size is greater than (((2 raisedTo: 31) - 1) >> bits). Used to limit size of allocation requests to 31 bit integer maximum to prevent arithmetic overflow in subsequent calculations. Always answers false in interpreter simulation. Assumes that sizeof(int) is 4 for all platforms. */ sqInt isExcessiveAllocationRequestshift(sqInt size, sqInt bits) { sqInt shiftCount; int int32; int32 = size; shiftCount = 0; if (int32 < 0) { return 1; } while (shiftCount < bits) { int32 = int32 << 1; if (int32 < 0) { return 1; } shiftCount += 1; } return 0; } sqInt isFloatObject(sqInt oop) { return (fetchClassOf(oop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)); } /* Is this a MethodContext whose meth has a primitive number of 199? */ /* NB: the use of a primitive number for marking the method is pretty grungy, but it is simple to use for a test sytem, not too expensive and we don't actually have the two spare method header bits we need. We can probably obtain them when the method format is changed. NB 2: actually, the jitter will probably implement the prim to actually mark the volatile frame by changing the return function pointer. */ sqInt isHandlerMarked(sqInt aContext) { sqInt meth; sqInt header; sqInt pIndex; sqInt primBits; header = longAt(aContext); if (!(((((usqInt) header) >> 12) & 31) == 14)) { return 0; } meth = longAt((aContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); return pIndex == 199; } /* Return true if the given address is in ST object memory */ sqInt isInMemory(sqInt address) { return ((((usqInt) address)) >= (((usqInt) memory))) && ((((usqInt) address)) < (((usqInt) foo->endOfMemory))); } sqInt isIndexable(sqInt oop) { return ((((usqInt) (longAt(oop))) >> 8) & 15) >= 2; } sqInt isIntegerObject(sqInt objectPointer) { return (objectPointer & 1) > 0; } /* Return true if the given value can be represented as a Smalltalk integer value. */ /* Use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits. Operands are coerced to machine integer size so the test will work with 64 bit images on 32 bit hosts. When running on a 32 bit host, the cast to int has little or no performance impact for either 32 bit or 64 bit images. On a 64 bit host, the shift and XOR test is replaced by an explicit range check, which provides the best performance for both 32 bit and 64 bit images. If the range of small integers is enlarged for 64 bit images, this method must be updated accordingly. */ sqInt isIntegerValue(sqInt intValue) { return # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) intValue)) ^ ((((int) intValue)) << 1)) >= 0) # else ((intValue >= -1073741824) && (intValue <= 1073741823)) # endif // SQ_HOST32 ; } /* Answer true if the argument has only fields that can hold oops. See comment in formatOf: */ sqInt isPointers(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) <= 4); } /* Answer true if the argument has only weak fields that can hold oops. See comment in formatOf: */ sqInt isWeak(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 4); } /* Answer true if the argument contains only indexable words (no oops). See comment in formatOf: */ sqInt isWords(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 6); } /* Answer true if the contains only indexable words or bytes (no oops). See comment in formatOf: */ /* Note: Excludes CompiledMethods. */ sqInt isWordsOrBytes(sqInt oop) { return ((oop & 1) == 0) && (isWordsOrBytesNonInt(oop)); } /* Answer true if the contains only indexable words or bytes (no oops). See comment in formatOf: */ /* Note: Excludes CompiledMethods. */ sqInt isWordsOrBytesNonInt(sqInt oop) { sqInt fmt; fmt = (((usqInt) (longAt(oop))) >> 8) & 15; return (fmt == 6) || ((fmt >= 8) && (fmt <= 11)); } /* Return the byte offset of the last pointer field of the given object. Works with CompiledMethods, as well as ordinary objects. Can be used even when the type bits are not correct. */ sqInt lastPointerOf(sqInt oop) { sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; header = longAt(oop); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l2; } contextSize = (sp >> 1); l2: /* end fetchStackPointerOf: */; return (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); } /* begin sizeBitsOfSafe: */ header1 = longAt(oop); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; return sz - (BASE_HEADER_SIZE); } if (fmt < 12) { return 0; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); return (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); } /* Return the number of indexable bytes or words in the given object. Assume the argument is not an integer. For a CompiledMethod, the size of the method header (in bytes) should be subtracted from the result. */ sqInt lengthOf(sqInt oop) { sqInt header; sqInt sz; header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } if (((((usqInt) header) >> 8) & 15) < 8) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; } else { return (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); } return null; } sqInt literalofMethod(sqInt offset, sqInt methodPointer) { return longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); } sqInt literalCountOf(sqInt methodPointer) { sqInt headerPointer; /* begin literalCountOfHeader: */ headerPointer = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); return (((usqInt) headerPointer) >> 10) & 255; } sqInt literalCountOfHeader(sqInt headerPointer) { return (((usqInt) headerPointer) >> 10) & 255; } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=loadBitBltFrom and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt loadBitBltFrom(sqInt bb) { void * fn; fn = ioLoadFunctionFrom("loadBitBltFrom", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(sqInt))fn)(bb); } sqInt loadInitialContext(void) { register struct foo * foo = &fum; sqInt proc; sqInt sched; sqInt oop; sqInt oop1; sqInt activeCntx; sqInt tmp; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); proc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->activeContext = longAt((proc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } /* begin fetchContextRegisters: */ activeCntx = foo->activeContext; tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = activeCntx; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (activeCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); foo->reclaimableContextCount = 0; } /* This method implements a simple method lookup cache. If an entry for the given selector and class is found in the cache, set the values of 'newMethod' and 'primitiveIndex' and return true. Otherwise, return false. */ /* About the re-probe scheme: The hash is the low bits of the XOR of two large addresses, minus their useless lowest two bits. If a probe doesn't get a hit, the hash is shifted right one bit to compute the next probe, introducing a new randomish bit. The cache is probed CacheProbeMax times before giving up. */ /* WARNING: Since the hash computation is based on the object addresses of the class and selector, we must rehash or flush when compacting storage. We've chosen to flush, since that also saves the trouble of updating the addresses of the objects in the cache. */ sqInt lookupInMethodCacheSelclass(sqInt selector, sqInt class) { register struct foo * foo = &fum; sqInt hash; sqInt probe; /* shift drops two low-order zeros from addresses */ hash = selector ^ class; /* first probe */ probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } /* second probe */ probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } return 0; } sqInt lookupMethodInClass(sqInt class) { register struct foo * foo = &fum; sqInt dictionary; sqInt currentClass; sqInt rclass; sqInt found; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt length; sqInt wrapAround; sqInt index; sqInt nextSelector; sqInt mask; sqInt methodArray; sqInt sz; sqInt methodPointer; sqInt primBits; sqInt header; currentClass = class; while (currentClass != foo->nilObj) { dictionary = longAt((currentClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); if (dictionary == foo->nilObj) { /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = currentClass; createActualMessageTo(class); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; currentClass = oop; /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + (SelectorCannotInterpret << (SHIFT_FOR_WORD))); return lookupMethodInClass(longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD)))); } /* begin lookupMethodInDictionary: */ /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(dictionary); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(dictionary - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); mask = (length - SelectorStart) - 1; if ((foo->messageSelector & 1)) { index = (mask & ((foo->messageSelector >> 1))) + SelectorStart; } else { index = (mask & ((((usqInt) (longAt(foo->messageSelector))) >> 17) & 4095)) + SelectorStart; } wrapAround = 0; while (1) { nextSelector = longAt((dictionary + (BASE_HEADER_SIZE)) + (index << (SHIFT_FOR_WORD))); if (nextSelector == foo->nilObj) { found = 0; goto l2; } if (nextSelector == foo->messageSelector) { methodArray = longAt((dictionary + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); foo->newMethod = longAt((methodArray + (BASE_HEADER_SIZE)) + ((index - SelectorStart) << (SHIFT_FOR_WORD))); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); if (foo->primitiveIndex > MaxPrimitiveIndex) { foo->primitiveIndex = 0; } } else { foo->primitiveIndex = 248; } found = 1; goto l2; } index += 1; if (index == length) { if (wrapAround) { found = 0; goto l2; } wrapAround = 1; index = SelectorStart; } } l2: /* end lookupMethodInDictionary: */; if (found) { return foo->methodClass = currentClass; } currentClass = longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } if (foo->messageSelector == (fetchPointerofObject(SelectorDoesNotUnderstand, foo->specialObjectsOop))) { error("Recursive not understood error encountered"); } /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = class; createActualMessageTo(class); /* begin popRemappableOop */ oop2 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; rclass = oop2; /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; foo->messageSelector = longAt((oop3 + (BASE_HEADER_SIZE)) + (SelectorDoesNotUnderstand << (SHIFT_FOR_WORD))); return lookupMethodInClass(rclass); } /* This method lookup tolerates integers as Dictionary keys to support execution of images in which Symbols have been compacted out */ sqInt lookupMethodInDictionary(sqInt dictionary) { register struct foo * foo = &fum; sqInt length; sqInt wrapAround; sqInt index; sqInt nextSelector; sqInt mask; sqInt methodArray; sqInt sz; sqInt methodPointer; sqInt primBits; sqInt header; /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(dictionary); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(dictionary - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); mask = (length - SelectorStart) - 1; if ((foo->messageSelector & 1)) { index = (mask & ((foo->messageSelector >> 1))) + SelectorStart; } else { index = (mask & ((((usqInt) (longAt(foo->messageSelector))) >> 17) & 4095)) + SelectorStart; } wrapAround = 0; while (1) { nextSelector = longAt((dictionary + (BASE_HEADER_SIZE)) + (index << (SHIFT_FOR_WORD))); if (nextSelector == foo->nilObj) { return 0; } if (nextSelector == foo->messageSelector) { methodArray = longAt((dictionary + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); /* Check if newMethod is a CompiledMethod. */ foo->newMethod = longAt((methodArray + (BASE_HEADER_SIZE)) + ((index - SelectorStart) << (SHIFT_FOR_WORD))); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); if (foo->primitiveIndex > MaxPrimitiveIndex) { /* If primitiveIndex is out of range, set to zero before putting in cache. This is equiv to primFail, and avoids the need to check on every send. */ foo->primitiveIndex = 0; } } else { /* indicate that this is no compiled method - use primitiveInvokeObjectAsMethod */ foo->primitiveIndex = 248; } return 1; } index += 1; if (index == length) { if (wrapAround) { return 0; } wrapAround = 1; index = SelectorStart; } } } /* Lookup. Answer false on failure father than performing MNU processing etc. */ sqInt lookupMethodNoMNUEtcInClass(sqInt class) { register struct foo * foo = &fum; sqInt dictionary; sqInt currentClass; currentClass = class; while (currentClass != foo->nilObj) { dictionary = longAt((currentClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); if ((dictionary != foo->nilObj) && (lookupMethodInDictionary(dictionary))) { foo->methodClass = currentClass; return 1; } currentClass = longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } return 0; } /* Return the first free block after the given chunk in memory. */ sqInt lowestFreeAfter(sqInt chunk) { register struct foo * foo = &fum; sqInt oopSize; sqInt oop; sqInt oopHeaderType; sqInt oopHeader; oop = chunk + (foo->headerTypeBytes[(longAt(chunk)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { oopHeader = longAt(oop); oopHeaderType = oopHeader & TypeMask; if (oopHeaderType == HeaderTypeFree) { return oop; } else { if (oopHeaderType == HeaderTypeSizeAndClass) { oopSize = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { oopSize = oopHeader & (SIZE_MASK); } } oop = (oop + oopSize) + (foo->headerTypeBytes[(longAt(oop + oopSize)) & TypeMask]); } error("expected to find at least one free object"); } /* make a Point xValue@yValue. We know both will be integers so no value nor root checking is needed */ sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue) { sqInt pointResult; pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((xValue << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((yValue << 1) | 1)); return pointResult; } /* Use the forwarding table to update the pointers of all non-free objects in the given range of memory. Also remap pointers in root objects which may contains pointers into the given memory range, and don't forget to flush the method cache based on the range */ sqInt mapPointersInObjectsFromto(sqInt memStart, sqInt memEnd) { register struct foo * foo = &fum; sqInt oop; sqInt i; sqInt oop1; sqInt i1; sqInt i2; sqInt probe; /* begin compilerMapHookFrom:to: */ if (foo->compilerInitialized) { compilerMapFromto(memStart, memEnd); } /* begin mapInterpreterOops */ foo->nilObj = remap(foo->nilObj); foo->falseObj = remap(foo->falseObj); foo->trueObj = remap(foo->trueObj); foo->specialObjectsOop = remap(foo->specialObjectsOop); if (!(foo->compilerInitialized)) { foo->stackPointer -= foo->activeContext; foo->activeContext = remap(foo->activeContext); foo->stackPointer += foo->activeContext; foo->theHomeContext = remap(foo->theHomeContext); } foo->instructionPointer -= foo->method; foo->method = remap(foo->method); foo->instructionPointer += foo->method; foo->receiver = remap(foo->receiver); foo->messageSelector = remap(foo->messageSelector); foo->newMethod = remap(foo->newMethod); foo->methodClass = remap(foo->methodClass); foo->lkupClass = remap(foo->lkupClass); foo->receiverClass = remap(foo->receiverClass); for (i1 = 1; i1 <= foo->remapBufferCount; i1 += 1) { oop1 = foo->remapBuffer[i1]; if (!((oop1 & 1))) { foo->remapBuffer[i1] = (remap(oop1)); } } for (i1 = 1; i1 <= foo->jmpDepth; i1 += 1) { oop1 = foo->suspendedCallbacks[i1]; if (!((oop1 & 1))) { foo->suspendedCallbacks[i1] = (remap(oop1)); } oop1 = foo->suspendedMethods[i1]; if (!((oop1 & 1))) { foo->suspendedMethods[i1] = (remap(oop1)); } } for (i = 1; i <= foo->extraRootCount; i += 1) { oop = (foo->extraRoots[i])[0]; if (!((oop & 1))) { (foo->extraRoots[i])[0] = (remap(oop)); } } /* begin flushMethodCacheFrom:to: */ probe = 0; for (i2 = 1; i2 <= MethodCacheEntries; i2 += 1) { if (!((foo->methodCache[probe + MethodCacheSelector]) == 0)) { if ((((((((usqInt) (foo->methodCache[probe + MethodCacheSelector]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheSelector]))) < (((usqInt) memEnd)))) || (((((usqInt) (foo->methodCache[probe + MethodCacheClass]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheClass]))) < (((usqInt) memEnd))))) || (((((usqInt) (foo->methodCache[probe + MethodCacheMethod]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheMethod]))) < (((usqInt) memEnd))))) || (((((usqInt) (foo->methodCache[probe + MethodCacheNative]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheNative]))) < (((usqInt) memEnd))))) { foo->methodCache[probe + MethodCacheSelector] = 0; } } probe += MethodCacheEntrySize; } for (i2 = 1; i2 <= AtCacheTotalSize; i2 += 1) { foo->atCache[i2] = 0; } updatePointersInRootObjectsFromto(memStart, memEnd); updatePointersInRangeFromto(memStart, memEnd); } /* Mark all objects reachable from the given one. Trace from the given object even if it is old. Do not trace if it is already marked. Mark it only if it is a young object. */ /* Tracer state variables: child object being examined field next field of child to examine parentField field where child was stored in its referencing object */ sqInt markAndTrace(sqInt oop) { register struct foo * foo = &fum; sqInt lastFieldOffset; sqInt action; sqInt header; sqInt statMarkCountLocal; sqInt typeBits; sqInt childType; sqInt lastFieldOffset1; sqInt oop1; sqInt header1; sqInt type; sqInt header2; sqInt sz; sqInt header3; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header11; sqInt type1; sqInt sp; sqInt sz1; sqInt header4; sqInt contextSize1; sqInt fmt1; sqInt methodHeader1; sqInt header12; sqInt type2; sqInt sp1; sqInt child; usqInt youngStartLocal; sqInt parentField; sqInt field; header = longAt(oop); if (!((header & (MARK_BIT)) == 0)) { return 0; } header = (header & (ALL_BUT_TYPE_MASK)) | HeaderTypeGC; if ((((usqInt) oop)) >= (((usqInt) foo->youngStart))) { header = header | (MARK_BIT); } longAtput(oop, header); parentField = GCTopMarker; child = oop; if (((((usqInt) (longAt(oop))) >> 8) & 15) == 4) { /* Set lastFieldOffset before the weak fields in the receiver */ /* And remember as weak root */ lastFieldOffset = (nonWeakFieldsOf(oop)) << (SHIFT_FOR_WORD); foo->weakRootCount += 1; foo->weakRoots[foo->weakRootCount] = oop; } else { /* begin lastPointerOf: */ header3 = longAt(oop); fmt = (((usqInt) header3) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header3) >> 12) & 31) == 13) || ((((((usqInt) header3) >> 12) & 31) == 14) || (((((usqInt) header3) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l8; } contextSize = (sp >> 1); l8: /* end fetchStackPointerOf: */; lastFieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l10; } /* begin sizeBitsOfSafe: */ header11 = longAt(oop); /* begin rightType: */ if ((header11 & (SIZE_MASK)) == 0) { type1 = HeaderTypeSizeAndClass; goto l9; } else { if ((header11 & CompactClassMask) == 0) { type1 = HeaderTypeClass; goto l9; } else { type1 = HeaderTypeShort; goto l9; } } l9: /* end rightType: */; if (type1 == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l7; } else { sz = header11 & (SIZE_MASK); goto l7; } l7: /* end sizeBitsOfSafe: */; lastFieldOffset = sz - (BASE_HEADER_SIZE); goto l10; } if (fmt < 12) { lastFieldOffset = 0; goto l10; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); lastFieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l10: /* end lastPointerOf: */; } field = oop + lastFieldOffset; action = StartField; youngStartLocal = foo->youngStart; /* run the tracer state machine until all objects reachable from oop are marked */ statMarkCountLocal = foo->statMarkCount; while (!(action == Done)) { statMarkCountLocal += 1; if (action == StartField) { /* begin startField */ child = longAt(field); typeBits = child & TypeMask; if ((typeBits & 1) == 1) { field -= BYTES_PER_WORD; action = StartField; goto l2; } if (typeBits == 0) { longAtput(field, parentField); parentField = field; action = StartObj; goto l2; } if (typeBits == 2) { if ((child & CompactClassMask) != 0) { child = child & (ALL_BUT_TYPE_MASK); /* begin rightType: */ if ((child & (SIZE_MASK)) == 0) { childType = HeaderTypeSizeAndClass; goto l1; } else { if ((child & CompactClassMask) == 0) { childType = HeaderTypeClass; goto l1; } else { childType = HeaderTypeShort; goto l1; } } l1: /* end rightType: */; longAtput(field, child | childType); action = Upward; goto l2; } else { child = longAt(field - (BYTES_PER_WORD)); child = child & (ALL_BUT_TYPE_MASK); longAtput(field - (BYTES_PER_WORD), parentField); parentField = (field - (BYTES_PER_WORD)) | 1; action = StartObj; goto l2; } } l2: /* end startField */; } if (action == StartObj) { /* begin startObj */ oop1 = child; if ((((usqInt) oop1)) < (((usqInt) youngStartLocal))) { field = oop1; action = Upward; goto l3; } header1 = longAt(oop1); if ((header1 & (MARK_BIT)) == 0) { if (((((usqInt) (longAt(oop1))) >> 8) & 15) == 4) { lastFieldOffset1 = (nonWeakFieldsOf(oop1)) << (SHIFT_FOR_WORD); } else { /* begin lastPointerOf: */ header4 = longAt(oop1); fmt1 = (((usqInt) header4) >> 8) & 15; if (fmt1 <= 4) { if ((fmt1 == 3) && ((((((usqInt) header4) >> 12) & 31) == 13) || ((((((usqInt) header4) >> 12) & 31) == 14) || (((((usqInt) header4) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp1 = longAt((oop1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp1 & 1))) { contextSize1 = 0; goto l12; } contextSize1 = (sp1 >> 1); l12: /* end fetchStackPointerOf: */; lastFieldOffset1 = (CtxtTempFrameStart + contextSize1) * (BYTES_PER_WORD); goto l14; } /* begin sizeBitsOfSafe: */ header12 = longAt(oop1); /* begin rightType: */ if ((header12 & (SIZE_MASK)) == 0) { type2 = HeaderTypeSizeAndClass; goto l13; } else { if ((header12 & CompactClassMask) == 0) { type2 = HeaderTypeClass; goto l13; } else { type2 = HeaderTypeShort; goto l13; } } l13: /* end rightType: */; if (type2 == HeaderTypeSizeAndClass) { sz1 = (longAt(oop1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l11; } else { sz1 = header12 & (SIZE_MASK); goto l11; } l11: /* end sizeBitsOfSafe: */; lastFieldOffset1 = sz1 - (BASE_HEADER_SIZE); goto l14; } if (fmt1 < 12) { lastFieldOffset1 = 0; goto l14; } methodHeader1 = longAt(oop1 + (BASE_HEADER_SIZE)); lastFieldOffset1 = (((((usqInt) methodHeader1) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l14: /* end lastPointerOf: */; } header1 = header1 & (ALL_BUT_TYPE_MASK); header1 = (header1 | (MARK_BIT)) | HeaderTypeGC; longAtput(oop1, header1); field = oop1 + lastFieldOffset1; action = StartField; goto l3; } else { field = oop1; action = Upward; goto l3; } l3: /* end startObj */; } if (action == Upward) { /* begin upward */ if ((parentField & 1) == 1) { if (parentField == GCTopMarker) { header2 = (longAt(field)) & (ALL_BUT_TYPE_MASK); /* begin rightType: */ if ((header2 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l4; } else { if ((header2 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l4; } else { type = HeaderTypeShort; goto l4; } } l4: /* end rightType: */; longAtput(field, header2 | type); action = Done; goto l6; } else { child = field; field = parentField - 1; parentField = longAt(field); header2 = longAt(field + (BYTES_PER_WORD)); /* begin rightType: */ if ((header2 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l5; } else { if ((header2 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l5; } else { type = HeaderTypeShort; goto l5; } } l5: /* end rightType: */; longAtput(field, child | type); field += BYTES_PER_WORD; header2 = header2 & (ALL_BUT_TYPE_MASK); longAtput(field, header2 | type); action = Upward; goto l6; } } else { child = field; field = parentField; parentField = longAt(field); longAtput(field, child); field -= BYTES_PER_WORD; action = StartField; goto l6; } l6: /* end upward */; } } foo->statMarkCount = statMarkCountLocal; } /* Mark and trace all oops in the interpreter's state. */ /* Assume: All traced variables contain valid oops. */ sqInt markAndTraceInterpreterOops(void) { register struct foo * foo = &fum; sqInt oop; sqInt i; /* begin compilerMarkHook */ if (foo->compilerInitialized) { compilerMark(); } markAndTrace(foo->specialObjectsOop); if (foo->compilerInitialized) { markAndTrace(foo->receiver); markAndTrace(foo->method); } else { markAndTrace(foo->activeContext); } markAndTrace(foo->messageSelector); markAndTrace(foo->newMethod); markAndTrace(foo->methodClass); markAndTrace(foo->lkupClass); markAndTrace(foo->receiverClass); for (i = 1; i <= foo->remapBufferCount; i += 1) { oop = foo->remapBuffer[i]; if (!((oop & 1))) { markAndTrace(oop); } } for (i = 1; i <= foo->jmpDepth; i += 1) { oop = foo->suspendedCallbacks[i]; if (!((oop & 1))) { markAndTrace(oop); } oop = foo->suspendedMethods[i]; if (!((oop & 1))) { markAndTrace(oop); } } } /* Mark phase of the mark and sweep garbage collector. Set the mark bits of all reachable objects. Free chunks are untouched by this process. */ /* Assume: All non-free objects are initially unmarked. Root objects were unmarked when they were made roots. (Make sure this stays true!!). */ sqInt markPhase(void) { register struct foo * foo = &fum; sqInt oop; sqInt i; foo->freeContexts = NilContext; /* trace the interpreter's objects, including the active stack and special objects array */ foo->freeLargeContexts = NilContext; markAndTraceInterpreterOops(); /* trace the roots */ foo->statSpecialMarkCount = foo->statMarkCount; for (i = 1; i <= foo->rootTableCount; i += 1) { oop = foo->rootTable[i]; markAndTrace(oop); } for (i = 1; i <= foo->extraRootCount; i += 1) { oop = (foo->extraRoots[i])[0]; if (!((oop & 1))) { markAndTrace(oop); } } } sqInt methodArgumentCount(void) { return foo->argumentCount; } sqInt methodPrimitiveIndex(void) { return foo->primitiveIndex; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char * aModuleName) { if ((strcmp(aModuleName, "SurfacePlugin")) == 0) { /* Surface plugin went away. Should never happen. But then, who knows */ showSurfaceFn = 0; } } /* For access from BitBlt module */ sqInt nilObject(void) { return foo->nilObj; } /* Return the number of non-weak fields in oop (i.e. the number of fixed fields). Note: The following is copied from fixedFieldsOf:format:length: since we do know the format of the oop (e.g. format = 4) and thus don't need the length. */ sqInt nonWeakFieldsOf(sqInt oop) { register struct foo * foo = &fum; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if (!(((((usqInt) (longAt(oop))) >> 8) & 15) == 4)) { error("Called fixedFieldsOfWeak: with a non-weak oop"); } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; return (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; } /* Record that the given oop in the old object area points to an object in the young area. HeaderLoc is usually = oop, but may be an addr in a forwarding block. */ sqInt noteAsRootheaderLoc(sqInt oop, sqInt headerLoc) { register struct foo * foo = &fum; sqInt header; header = longAt(headerLoc); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { /* record oop as root only if not already recorded */ /* record root if there is enough room in the roots table */ foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(headerLoc, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { /* we're getting in the red zone */ /* but there's still space to record it */ foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(headerLoc, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } /* This should never be called: either the compiler is uninitialised (in which case the hooks should never be reached) or the compiler initialisation should have replaced all the hook with their external implementations. */ sqInt nullCompilerHook(void) { error("uninitialised compiler hook called"); return 0; } /* Return the object or free chunk immediately following the given object or free chunk in memory. Return endOfMemory when enumeration is complete. */ sqInt objectAfter(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt header; if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } return (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } /* This message is deprecated but supported for a while via a tweak to sqVirtualMachine.[ch] Use fetchLong32, fetchLong64 or fetchPointer instead for new code */ sqInt obsoleteDontUseThisFetchWordofObject(sqInt fieldIndex, sqInt oop) { return long32At((oop + (BASE_HEADER_SIZE)) + (fieldIndex << 2)); } /* If this is a pointers object, check that its fields are all okay oops. */ sqInt okayFields(sqInt oop) { register struct foo * foo = &fum; sqInt i; sqInt c; sqInt fieldOop; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop == null) || (oop == 0)) { return 1; } if ((oop & 1)) { return 1; } okayOop(oop); oopHasOkayClass(oop); if (!(((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) <= 4))) { return 1; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; c = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { c = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); c = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; if ((c == (fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop))) || (c == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop)))) { i = (CtxtTempFrameStart + (fetchStackPointerOf(oop))) - 1; } else { i = (lengthOf(oop)) - 1; } while (i >= 0) { fieldOop = longAt((oop + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); if (!((fieldOop & 1))) { okayOop(fieldOop); oopHasOkayClass(fieldOop); } i -= 1; } } /* Verify that the given oop is legitimate. Check address, header, and size but not class. */ sqInt okayOop(sqInt signedOop) { register struct foo * foo = &fum; usqInt oop; sqInt unusedBit; sqInt sz; sqInt type; sqInt fmt; sqInt header; /* address and size checks */ oop = ((usqInt) signedOop); if ((oop & 1)) { return 1; } if (!(oop < foo->endOfMemory)) { error("oop is not a valid address"); } if (!((oop % (BYTES_PER_WORD)) == 0)) { error("oop is not a word-aligned address"); } /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; if (!((oop + sz) < foo->endOfMemory)) { error("oop size would make it extend beyond the end of memory"); } type = (longAt(oop)) & TypeMask; if (type == HeaderTypeFree) { error("oop is a free chunk, not an object"); } if (type == HeaderTypeShort) { if (((((usqInt) (longAt(oop))) >> 12) & 31) == 0) { error("cannot have zero compact class field in a short header"); } } if (type == HeaderTypeClass) { if (!((oop >= (BYTES_PER_WORD)) && (((longAt(oop - (BYTES_PER_WORD))) & TypeMask) == type))) { error("class header word has wrong type"); } } if (type == HeaderTypeSizeAndClass) { if (!((oop >= ((BYTES_PER_WORD) * 2)) && ((((longAt(oop - ((BYTES_PER_WORD) * 2))) & TypeMask) == type) && (((longAt(oop - (BYTES_PER_WORD))) & TypeMask) == type)))) { error("class header word has wrong type"); } } fmt = (((usqInt) (longAt(oop))) >> 8) & 15; if ((fmt == 5) || (fmt == 7)) { error("oop has an unknown format type"); } unusedBit = 536870912; if ((BYTES_PER_WORD) == 8) { unusedBit = unusedBit << 16; unusedBit = unusedBit << 16; } if (!(((longAt(oop)) & unusedBit) == 0)) { error("unused header bit 30 is set; should be zero"); } if ((((longAt(oop)) & (ROOT_BIT)) == 1) && (oop >= foo->youngStart)) { error("root bit is set in a young object"); } return 1; } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisGreaterThan(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) > (((usqInt) otherOop)); } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisGreaterThanOrEqualTo(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) >= (((usqInt) otherOop)); } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisLessThan(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) < (((usqInt) otherOop)); } /* Similar to oopHasOkayClass:, except that it only returns true or false. */ sqInt oopHasAcceptableClass(sqInt signedOop) { register struct foo * foo = &fum; usqInt oop; sqInt formatMask; usqInt oopClass; sqInt behaviorFormatBits; sqInt oopFormatBits; if ((signedOop & 1)) { return 1; } oop = ((usqInt) signedOop); if (!(oop < foo->endOfMemory)) { return 0; } if (!((oop % (BYTES_PER_WORD)) == 0)) { return 0; } if (!((oop + (sizeBitsOf(oop))) < foo->endOfMemory)) { return 0; } oopClass = ((usqInt) (fetchClassOf(oop))); if ((oopClass & 1)) { return 0; } if (!(oopClass < foo->endOfMemory)) { return 0; } if (!((oopClass % (BYTES_PER_WORD)) == 0)) { return 0; } if (!((oopClass + (sizeBitsOf(oopClass))) < foo->endOfMemory)) { return 0; } if (!((((oopClass & 1) == 0) && (((((usqInt) (longAt(oopClass))) >> 8) & 15) <= 4)) && ((lengthOf(oopClass)) >= 3))) { return 0; } if (((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8)) { /* ignore extra bytes size bits */ formatMask = 3072; } else { formatMask = 3840; } behaviorFormatBits = ((longAt((oopClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1) & formatMask; oopFormatBits = (longAt(oop)) & formatMask; if (!(behaviorFormatBits == oopFormatBits)) { return 0; } return 1; } /* Attempt to verify that the given oop has a reasonable behavior. The class must be a valid, non-integer oop and must not be nilObj. It must be a pointers object with three or more fields. Finally, the instance specification field of the behavior must match that of the instance. */ sqInt oopHasOkayClass(sqInt signedOop) { usqInt oop; sqInt formatMask; usqInt oopClass; sqInt behaviorFormatBits; sqInt oopFormatBits; oop = ((usqInt) signedOop); okayOop(oop); oopClass = ((usqInt) (fetchClassOf(oop))); if ((oopClass & 1)) { error("a SmallInteger is not a valid class or behavior"); } okayOop(oopClass); if (!((((oopClass & 1) == 0) && (((((usqInt) (longAt(oopClass))) >> 8) & 15) <= 4)) && ((lengthOf(oopClass)) >= 3))) { error("a class (behavior) must be a pointers object of size >= 3"); } if (((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8)) { /* ignore extra bytes size bits */ formatMask = 3072; } else { formatMask = 3840; } behaviorFormatBits = ((longAt((oopClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1) & formatMask; oopFormatBits = (longAt(oop)) & formatMask; if (!(behaviorFormatBits == oopFormatBits)) { error("object and its class (behavior) formats differ"); } return 1; } /* Note: May be called by translated primitive code. */ sqInt pop(sqInt nItems) { register struct foo * foo = &fum; foo->stackPointer -= nItems * (BYTES_PER_WORD); } sqInt popthenPush(sqInt nItems, sqInt oop) { register struct foo * foo = &fum; sqInt sp; longAtput(sp = foo->stackPointer - ((nItems - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* Note: May be called by translated primitive code. */ double popFloat(void) { register struct foo * foo = &fum; double result; sqInt top; sqInt top1; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); if ((top & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(top))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(top - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { ; fetchFloatAtinto(top + (BASE_HEADER_SIZE), result); } return result; } /* Pop and return the possibly remapped object from the remap buffer. */ sqInt popRemappableOop(void) { register struct foo * foo = &fum; sqInt oop; oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; return oop; } sqInt popStack(void) { register struct foo * foo = &fum; sqInt top; top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; return top; } /* Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:. */ sqInt positive32BitIntegerFor(sqInt integerValue) { register struct foo * foo = &fum; sqInt newLargeInteger; if (integerValue >= 0) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerValue)) ^ ((((int) integerValue)) << 1)) >= 0) # else ((integerValue >= -1073741824) && (integerValue <= 1073741823)) # endif // SQ_HOST32 ) { return ((integerValue << 1) | 1); } } if ((BYTES_PER_WORD) == 4) { /* Faster instantiateSmallClass: currently only works with integral word size. */ newLargeInteger = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), (BASE_HEADER_SIZE) + 4); } else { /* Cant use instantiateSmallClass: due to integral word requirement. */ newLargeInteger = instantiateClassindexableSize(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), 4); } byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 3, (((usqInt) integerValue) >> 24) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 2, (((usqInt) integerValue) >> 16) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 1, (((usqInt) integerValue) >> 8) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 0, integerValue & 255); return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a four-byte LargePositiveInteger. */ sqInt positive32BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt value; sqInt header; sqInt sz1; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { value = (oop >> 1); if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return value; } /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l2: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; if (!(sz == 4)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } if (foo->successFlag) { return (((byteAt((oop + (BASE_HEADER_SIZE)) + 0)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 1)) << 8)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 2)) << 16)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 3)) << 24); } } /* Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:. */ sqInt positive64BitIntegerFor(sqLong integerValue) { sqInt sz; sqInt highWord; sqInt i; sqInt value; sqInt newLargeInteger; if ((sizeof(integerValue)) == 4) { return positive32BitIntegerFor(integerValue); } /* shift is coerced to usqInt otherwise */ highWord = integerValue >> 32; if (highWord == 0) { return positive32BitIntegerFor(integerValue); } sz = 5; if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } newLargeInteger = instantiateClassindexableSize(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), sz); for (i = 0; i <= (sz - 1); i += 1) { value = (integerValue >> (i * 8)) & 255; byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + i, value); } return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargePositiveInteger. */ sqLong positive64BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt i; sqLong value; sqInt szsqLong; sqInt header; sqInt sz1; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { value = (oop >> 1); if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return value; } /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l2: /* end assertClassOf:is: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } szsqLong = sizeof(sqLong); /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; if (sz > szsqLong) { /* begin primitiveFail */ foo->successFlag = 0; return null; } value = 0; for (i = 0; i <= (sz - 1); i += 1) { value += (((sqLong) (byteAt((oop + (BASE_HEADER_SIZE)) + i)))) << (i * 8); } return value; } /* oop is an old object. If valueObj is young, mark the object as a root. */ sqInt possibleRootStoreIntovalue(sqInt oop, sqInt valueObj) { register struct foo * foo = &fum; sqInt header; if (((((usqInt) valueObj)) >= (((usqInt) foo->youngStart))) && (!((valueObj & 1)))) { /* begin noteAsRoot:headerLoc: */ header = longAt(oop); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } /* Mark the active and home contexts as roots if old. This allows the interpreter to use storePointerUnchecked to store into them. */ sqInt postGCAction(void) { register struct foo * foo = &fum; sqInt delta; sqInt limit; if (foo->compilerInitialized) { compilerPostGC(); } else { if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } if ((((usqInt) foo->theHomeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->theHomeContext); } } if (oopisGreaterThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), foo->shrinkThreshold)) { /* begin shrinkObjectMemory: */ delta = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - foo->growHeadroom; foo->statShrinkMemory += 1; limit = sqShrinkMemoryBy(foo->memoryLimit, delta); if (!(limit == foo->memoryLimit)) { foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } } /* begin signalSemaphoreWithIndex: */ if (foo->gcSemaphoreIndex <= 0) { goto l1; } if (foo->semaphoresUseBufferA) { if (foo->semaphoresToSignalCountA < SemaphoresToSignalSize) { foo->semaphoresToSignalCountA += 1; foo->semaphoresToSignalA[foo->semaphoresToSignalCountA] = foo->gcSemaphoreIndex; } } else { if (foo->semaphoresToSignalCountB < SemaphoresToSignalSize) { foo->semaphoresToSignalCountB += 1; foo->semaphoresToSignalB[foo->semaphoresToSignalCountB] = foo->gcSemaphoreIndex; } } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; l1: /* end signalSemaphoreWithIndex: */; } /* Ensure that there are enough forwarding blocks to accomodate this become, then prepare forwarding blocks for the pointer swap. Return true if successful. */ /* Details: Doing a GC might generate enough space for forwarding blocks if we're short. However, this is an uncommon enough case that it is better handled by primitive fail code at the Smalltalk level. */ /* Important note on multiple references to same object - since the preparation of fwdBlocks is NOT idempotent we get VM crashes if the same object is referenced more than once in such a way as to require multiple fwdBlocks. oop1 forwardBecome: oop1 is ok since only a single fwdBlock is needed. oop1 become: oop1 would fail because the second fwdBlock woudl not have the actual object header but rather the mutated ref to the first fwdBlock. Further problems can arise with an array1 or array2 that refer multiply to the same object. This would notbe expected input for programmer writen code but might arise from automatic usage such as in ImageSegment loading. To avoid the simple and rather common case of oop1 become*: oop1, we skip such pairs and simply avoid making fwdBlocks - it is redundant anyway */ sqInt prepareForwardingTableForBecomingwithtwoWay(sqInt array1, sqInt array2, sqInt twoWayFlag) { register struct foo * foo = &fum; sqInt fieldOffset; sqInt oop1; sqInt entriesAvailable; sqInt entriesNeeded; sqInt fwdBlock; sqInt oop2; sqInt fwdBlkSize; sqInt originalHeader; sqInt originalHeaderType; sqInt originalHeader1; sqInt originalHeaderType1; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp; /* need enough entries for all oops */ /* Note: Forward blocks must be quadword aligned - see fwdTableInit:. */ entriesNeeded = (lastPointerOf(array1)) / (BYTES_PER_WORD); if (twoWayFlag) { /* Double the number of blocks for two-way become */ entriesNeeded = entriesNeeded * 2; fwdBlkSize = (BYTES_PER_WORD) * 2; } else { /* One-way become needs backPointers in fwd blocks. */ fwdBlkSize = (BYTES_PER_WORD) * 4; } entriesAvailable = fwdTableInit(fwdBlkSize); if (entriesAvailable < entriesNeeded) { initializeMemoryFirstFree(foo->freeBlock); return 0; } /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l5; } contextSize = (sp >> 1); l5: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l6; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l4; } else { sz = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l6; } if (fmt < 12) { fieldOffset = 0; goto l6; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l6: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { oop1 = longAt(array1 + fieldOffset); /* if oop1 == oop2, no need to do any work for this pair. May still be other entries in the arrays though so keep looking */ oop2 = longAt(array2 + fieldOffset); if (!(oop1 == oop2)) { /* begin fwdBlockGet: */ foo->fwdTableNext += fwdBlkSize; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l2; } else { fwdBlock = null; goto l2; } l2: /* end fwdBlockGet: */; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader1 = longAt(oop1); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader1 & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType1 = originalHeader1 & TypeMask; longAtput(fwdBlock, oop2); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader1); if (!twoWayFlag) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop1); } longAtput(oop1, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType1)); if (twoWayFlag) { /* begin fwdBlockGet: */ foo->fwdTableNext += fwdBlkSize; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l1; } else { fwdBlock = null; goto l1; } l1: /* end fwdBlockGet: */; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader = longAt(oop2); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType = originalHeader & TypeMask; longAtput(fwdBlock, oop1); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader); if (!twoWayFlag) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop2); } longAtput(oop2, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType)); } } fieldOffset -= BYTES_PER_WORD; } return 1; } sqInt primitiveAdd(void) { register struct foo * foo = &fum; sqInt integerResult; sqInt sp; /* begin pop2AndPushIntegerIfOK: */ integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerResult << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } sqInt primitiveArctan(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(atan(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* We must flush the method cache here, to eliminate stale references to mutated classes and/or selectors. */ sqInt primitiveArrayBecome(void) { register struct foo * foo = &fum; sqInt arg; sqInt rcvr; sqInt successValue; arg = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 1, 1); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* We must flush the method cache here, to eliminate stale references to mutated classes and/or selectors. */ sqInt primitiveArrayBecomeOneWay(void) { register struct foo * foo = &fum; sqInt arg; sqInt rcvr; sqInt successValue; arg = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 0, 1); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Similar to primitiveArrayBecomeOneWay but accepts a third argument whether to copy the receiver's identity hash over the argument's identity hash. */ sqInt primitiveArrayBecomeOneWayCopyHash(void) { register struct foo * foo = &fum; sqInt arg; sqInt rcvr; sqInt copyHashFlag; sqInt successValue; /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { copyHashFlag = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { copyHashFlag = 0; goto l1; } foo->successFlag = 0; copyHashFlag = null; l1: /* end booleanValueOf: */; arg = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 0, copyHashFlag); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); } } sqInt primitiveAsFloat(void) { register struct foo * foo = &fum; sqInt arg; sqInt integerPointer; sqInt top; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { arg = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; arg = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { pushFloat(((double) arg)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } sqInt primitiveAsOop(void) { register struct foo * foo = &fum; sqInt thisReceiver; sqInt sp; thisReceiver = longAt(foo->stackPointer); /* begin success: */ foo->successFlag = (!((thisReceiver & 1))) && foo->successFlag; if (foo->successFlag) { /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((((((usqInt) (longAt(thisReceiver))) >> 17) & 4095) << 1) | 1)); foo->stackPointer = sp; } } sqInt primitiveAt(void) { commonAt(0); } sqInt primitiveAtEnd(void) { register struct foo * foo = &fum; sqInt stream; sqInt index; sqInt limit; sqInt sp; sqInt sp1; sqInt top; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; stream = top; foo->successFlag = (((stream & 1) == 0) && (((((usqInt) (longAt(stream))) >> 8) & 15) <= 4)) && ((lengthOf(stream)) >= (StreamReadLimitIndex + 1)); if (foo->successFlag) { index = fetchIntegerofObject(StreamIndexIndex, stream); limit = fetchIntegerofObject(StreamReadLimitIndex, stream); } if (foo->successFlag) { /* begin pushBool: */ if (index >= limit) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } sqInt primitiveAtPut(void) { commonAtPut(0); } /* Set the cursor to the given shape. The Mac only supports 16x16 pixel cursors. Cursor offsets are handled by Smalltalk. */ sqInt primitiveBeCursor(void) { register struct foo * foo = &fum; sqInt ourCursor; sqInt maskObj; sqInt offsetY; sqInt offsetX; sqInt offsetObj; sqInt cursorObj; sqInt i; sqInt extentY; sqInt maskBitsIndex; sqInt extentX; sqInt bitsObj; sqInt depth; sqInt cursorBitsIndex; sqInt successValue; sqInt successValue1; sqInt successValue2; sqInt successValue3; sqInt successValue4; sqInt successValue5; sqInt successValue6; sqInt successValue7; sqInt successValue8; sqInt successValue9; sqInt successValue10; sqInt successValue11; sqInt successValue12; flag("Dan"); if ((BYTES_PER_WORD) == 8) { /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); return null; } if (foo->argumentCount == 0) { cursorObj = longAt(foo->stackPointer); maskBitsIndex = null; } if (foo->argumentCount == 1) { cursorObj = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); maskObj = longAt(foo->stackPointer); } /* begin success: */ foo->successFlag = (foo->argumentCount < 2) && foo->successFlag; /* begin success: */ successValue11 = (((cursorObj & 1) == 0) && (((((usqInt) (longAt(cursorObj))) >> 8) & 15) <= 4)) && ((lengthOf(cursorObj)) >= 5); foo->successFlag = successValue11 && foo->successFlag; if (foo->successFlag) { bitsObj = longAt((cursorObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); extentX = fetchIntegerofObject(1, cursorObj); extentY = fetchIntegerofObject(2, cursorObj); depth = fetchIntegerofObject(3, cursorObj); offsetObj = longAt((cursorObj + (BASE_HEADER_SIZE)) + (4 << (SHIFT_FOR_WORD))); } /* begin success: */ successValue12 = (((offsetObj & 1) == 0) && (((((usqInt) (longAt(offsetObj))) >> 8) & 15) <= 4)) && ((lengthOf(offsetObj)) >= 2); foo->successFlag = successValue12 && foo->successFlag; if (foo->successFlag) { offsetX = fetchIntegerofObject(0, offsetObj); offsetY = fetchIntegerofObject(1, offsetObj); if ((foo->argumentCount == 0) && (depth == 32)) { /* begin success: */ successValue = (extentX > 0) && (extentY > 0); foo->successFlag = successValue && foo->successFlag; /* begin success: */ successValue1 = (offsetX >= (extentX * -1)) && (offsetX <= 0); foo->successFlag = successValue1 && foo->successFlag; /* begin success: */ successValue2 = (offsetY >= (extentY * -1)) && (offsetY <= 0); foo->successFlag = successValue2 && foo->successFlag; cursorBitsIndex = bitsObj + (BASE_HEADER_SIZE); /* begin success: */ successValue3 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == (extentX * extentY)); foo->successFlag = successValue3 && foo->successFlag; ; } else { /* begin success: */ successValue4 = (extentX == 16) && ((extentY == 16) && (depth == 1)); foo->successFlag = successValue4 && foo->successFlag; /* begin success: */ successValue5 = (offsetX >= -16) && (offsetX <= 0); foo->successFlag = successValue5 && foo->successFlag; /* begin success: */ successValue6 = (offsetY >= -16) && (offsetY <= 0); foo->successFlag = successValue6 && foo->successFlag; /* begin success: */ successValue7 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == 16); foo->successFlag = successValue7 && foo->successFlag; cursorBitsIndex = bitsObj + (BASE_HEADER_SIZE); ; } } if (foo->argumentCount == 1) { /* begin success: */ successValue10 = (((maskObj & 1) == 0) && (((((usqInt) (longAt(maskObj))) >> 8) & 15) <= 4)) && ((lengthOf(maskObj)) >= 5); foo->successFlag = successValue10 && foo->successFlag; if (foo->successFlag) { bitsObj = longAt((maskObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); extentX = fetchIntegerofObject(1, maskObj); extentY = fetchIntegerofObject(2, maskObj); depth = fetchIntegerofObject(3, maskObj); } if (foo->successFlag) { /* begin success: */ successValue8 = (extentX == 16) && ((extentY == 16) && (depth == 1)); foo->successFlag = successValue8 && foo->successFlag; /* begin success: */ successValue9 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == 16); foo->successFlag = successValue9 && foo->successFlag; maskBitsIndex = bitsObj + (BASE_HEADER_SIZE); } } if (foo->successFlag) { if (foo->argumentCount == 0) { if (depth == 32) { if (!(ioSetCursorARGB(cursorBitsIndex, extentX, extentY, offsetX, offsetY))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } } else { ioSetCursor(cursorBitsIndex, offsetX, offsetY); } } else { ioSetCursorWithMask(cursorBitsIndex, maskBitsIndex, offsetX, offsetY); } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } } /* Record the system Display object in the specialObjectsTable. */ sqInt primitiveBeDisplay(void) { register struct foo * foo = &fum; sqInt rcvr; sqInt oop; sqInt successValue; rcvr = longAt(foo->stackPointer); /* begin success: */ successValue = (((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4)) && ((lengthOf(rcvr)) >= 4); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, rcvr); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD)), rcvr); } } /* make the basic beep noise */ sqInt primitiveBeep(void) { ioBeep(); } sqInt primitiveBitAnd(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt object; sqInt sp; sqInt top; sqInt top1; sqInt top2; sqInt top11; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top11 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top11; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver & integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveBitOr(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt object; sqInt sp; sqInt top; sqInt top1; sqInt top2; sqInt top11; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top11 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top11; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver | integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveBitShift(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt shifted; sqInt integerReceiver; sqInt integerPointer; sqInt object; sqInt sp; sqInt top; sqInt top2; sqInt top1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top1; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { if (integerArgument >= 0) { /* begin success: */ foo->successFlag = (integerArgument <= 31) && foo->successFlag; shifted = integerReceiver << integerArgument; /* begin success: */ foo->successFlag = ((((usqInt) shifted) >> integerArgument) == integerReceiver) && foo->successFlag; } else { /* begin success: */ foo->successFlag = (integerArgument >= -31) && foo->successFlag; shifted = ((integerArgument < 0) ? ((usqInt) integerReceiver >> -integerArgument) : ((usqInt) integerReceiver << integerArgument)); } } if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(shifted); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveBitXor(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt object; sqInt sp; sqInt top; sqInt top1; sqInt top2; sqInt top11; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top11 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top2 = top11; integerReceiver = positive32BitValueOf(top2); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver ^ integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveBlockCopy(void) { register struct foo * foo = &fum; sqInt methodContext; sqInt context; sqInt initialIP; sqInt newContext; sqInt contextSize; sqInt header; sqInt oop; sqInt valuePointer; sqInt valuePointer1; sqInt sp; context = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (((longAt((context + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))) & 1)) { /* context is a block; get the context of its enclosing method */ methodContext = longAt((context + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); } else { methodContext = context; } /* begin sizeBitsOf: */ header = longAt(methodContext); if ((header & TypeMask) == HeaderTypeSizeAndClass) { contextSize = (longAt(methodContext - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { contextSize = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; /* context is no longer needed and is not preserved across allocation */ /* remap methodContext in case GC happens during allocation */ context = null; /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = methodContext; newContext = instantiateContextsizeInBytes(fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop), contextSize); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; methodContext = oop; /* Was instructionPointer + 3, but now it's greater by 1 due to preIncrement */ /* Assume: have just allocated a new context; it must be young. Thus, can use uncheck stores. See the comment in fetchContextRegisters. */ initialIP = (((((foo->instructionPointer + 1) + 3) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((newContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD)), initialIP); longAtput((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ longAtput((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); longAtput((newContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD)), valuePointer); longAtput((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD)), methodContext); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->nilObj; longAtput((newContext + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), valuePointer1); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), newContext); foo->stackPointer = sp; } /* Reports bytes available at this moment. For more meaningful results, calls to this primitive should be preceeded by a full or incremental garbage collection. */ sqInt primitiveBytesLeft(void) { register struct foo * foo = &fum; sqInt aBool; sqInt integerVal; sqInt sp; sqInt integerVal1; sqInt sp1; if (foo->argumentCount == 0) { /* begin pop:thenPushInteger: */ integerVal = (longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((integerVal << 1) | 1)); foo->stackPointer = sp; return null; } if (foo->argumentCount == 1) { /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { aBool = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { aBool = 0; goto l1; } foo->successFlag = 0; aBool = null; l1: /* end booleanValueOf: */; if (!(foo->successFlag)) { return null; } /* begin pop:thenPushInteger: */ integerVal1 = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(aBool)); longAtput(sp1 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerVal1 << 1) | 1)); foo->stackPointer = sp1; return null; } /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Perform a function call to a foreign function. Only invoked from method containing explicit external call spec. Due to this we use the pluggable prim mechanism explicitly here (the first literal of any FFI spec'ed method is an ExternalFunction and not an array as used in the pluggable primitive mechanism). */ sqInt primitiveCalloutToFFI(void) { static char *functionName = "primitiveCallout"; static char *moduleName = "SqueakFFIPrims"; static void *function = 0; if (function == 0) { function = ioLoadExternalFunctionOfLengthFromModuleOfLength(oopForPointer(functionName), 16, oopForPointer(moduleName), 14); if (function == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } return ((sqInt (*)(void))function)(); } /* Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ sqInt primitiveChangeClass(void) { register struct foo * foo = &fum; sqInt arg; sqInt argClass; sqInt rcvr; sqInt oop; sqInt oop1; sqInt ccIndex; sqInt oop2; sqInt oop3; sqInt oop4; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; arg = null; goto l1; } arg = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; /* begin fetchClassOf: */ if ((arg & 1)) { /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; argClass = longAt((oop2 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex = (((usqInt) (longAt(arg))) >> 12) & 31; if (ccIndex == 0) { argClass = (longAt(arg - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop3 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); argClass = longAt((oop3 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; changeClassOfto(rcvr, argClass); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } /* Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ EXPORT(sqInt) primitiveChangeClassWithClass(void) { register struct foo * foo = &fum; sqInt argClass; sqInt rcvr; sqInt oop; sqInt oop1; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; argClass = null; goto l1; } argClass = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; changeClassOfto(rcvr, argClass); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } sqInt primitiveClass(void) { register struct foo * foo = &fum; sqInt instance; sqInt oop; sqInt sp; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; instance = longAt(foo->stackPointer); /* begin pop:thenPush: */ /* begin fetchClassOf: */ if ((instance & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(instance))) >> 12) & 31; if (ccIndex == 0) { oop = (longAt(instance - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* When called with a single string argument, post the string to the clipboard. When called with zero arguments, return a string containing the current clipboard contents. */ sqInt primitiveClipboardText(void) { register struct foo * foo = &fum; sqInt sz; sqInt s; sqInt sp; if (foo->argumentCount == 1) { s = longAt(foo->stackPointer); if (!(((s & 1) == 0) && (((((usqInt) (longAt(s))) >> 8) & 15) >= 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (foo->successFlag) { sz = stSizeOf(s); clipboardWriteFromAt(sz, s + (BASE_HEADER_SIZE), 0); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } else { sz = clipboardSize(); if (!(sufficientSpaceToAllocate(sz))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); clipboardReadIntoAt(sz, s + (BASE_HEADER_SIZE), 0); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), s); foo->stackPointer = sp; } } /* Return a shallow copy of the receiver. */ sqInt primitiveClone(void) { register struct foo * foo = &fum; sqInt newCopy; sqInt sp; newCopy = clone(longAt(foo->stackPointer)); if (newCopy == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), newCopy); foo->stackPointer = sp; } sqInt primitiveClosureCopyWithCopiedValues(void) { register struct foo * foo = &fum; sqInt copiedValues; sqInt numCopiedValues; sqInt i; sqInt numArgs; sqInt newClosure; sqInt valuePointer; sqInt integerPointer; sqInt successValue; sqInt sz; sqInt valuePointer1; sqInt sp; sqInt header; sqInt initialIP; sqInt newClosure1; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { numArgs = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; numArgs = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; copiedValues = longAt(foo->stackPointer); /* begin success: */ successValue = (fetchClassOf(copiedValues)) == (fetchPointerofObject(ClassArray, foo->specialObjectsOop)); foo->successFlag = successValue && foo->successFlag; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(copiedValues); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(copiedValues - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; numCopiedValues = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin closureNumArgs:instructionPointer:numCopiedValues: */ initialIP = (foo->instructionPointer + 2) - (foo->method + (BASE_HEADER_SIZE)); newClosure1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop), ((BYTES_PER_WORD) * (ClosureFirstCopiedValueIndex + numCopiedValues)) + (BASE_HEADER_SIZE)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)), ((numArgs << 1) | 1)); newClosure = newClosure1; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD)), valuePointer1); if (numCopiedValues > 0) { /* Allocation may have done a GC and copiedValues may have moved. */ copiedValues = longAt(foo->stackPointer); for (i = 0; i <= (numCopiedValues - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt((copiedValues + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)), valuePointer); } } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), newClosure); foo->stackPointer = sp; } sqInt primitiveClosureValue(void) { register struct foo * foo = &fum; sqInt blockArgumentCount; sqInt closureMethod; sqInt blockClosure; sqInt outerContext; blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(foo->argumentCount == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } activateNewClosureMethod(blockClosure); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } /* An exact clone of primitiveClosureValue except that this version will not check for interrupts on stack overflow. */ sqInt primitiveClosureValueNoContextSwitch(void) { register struct foo * foo = &fum; sqInt blockArgumentCount; sqInt closureMethod; sqInt blockClosure; sqInt outerContext; blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(foo->argumentCount == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } activateNewClosureMethod(blockClosure); } sqInt primitiveClosureValueWithArgs(void) { register struct foo * foo = &fum; sqInt blockArgumentCount; sqInt cntxSize; sqInt closureMethod; sqInt arraySize; sqInt blockClosure; sqInt outerContext; sqInt argumentArray; sqInt index; sqInt object; sqInt sp; sqInt sz; sqInt objectPointer; sqInt sz1; sqInt top; sqInt header; sqInt header1; argumentArray = longAt(foo->stackPointer); if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin fetchWordLengthOf: */ objectPointer = foo->activeContext; /* begin sizeBitsOf: */ header1 = longAt(objectPointer); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; cntxSize = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); if (!(((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) < cntxSize)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(arraySize == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; index = 1; while (index <= arraySize) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } foo->argumentCount = arraySize; activateNewClosureMethod(blockClosure); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } /* Fill the receiver, which must be an indexable bytes or words objects, with the given integer value. */ sqInt primitiveConstantFill(void) { register struct foo * foo = &fum; usqInt end; usqInt i; sqInt fillValue; sqInt rcvr; sqInt rcvrIsBytes; sqInt successValue; sqInt successValue1; fillValue = positive32BitValueOf(longAt(foo->stackPointer)); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue1 = ((rcvr & 1) == 0) && (isWordsOrBytesNonInt(rcvr)); foo->successFlag = successValue1 && foo->successFlag; rcvrIsBytes = ((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) >= 8); if (rcvrIsBytes) { /* begin success: */ successValue = (fillValue >= 0) && (fillValue <= 255); foo->successFlag = successValue && foo->successFlag; } if (foo->successFlag) { end = rcvr + (sizeBitsOf(rcvr)); i = rcvr + (BASE_HEADER_SIZE); if (rcvrIsBytes) { while (i < end) { byteAtput(i, fillValue); i += 1; } } else { while (i < end) { long32Atput(i, fillValue); i += 4; } } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Primitive. Copy the state of the receiver from the argument. Fail if receiver and argument are of a different class. Fail if the receiver or argument are non-pointer objects. Fail if receiver and argument have different lengths (for indexable objects). */ sqInt primitiveCopyObject(void) { register struct foo * foo = &fum; sqInt arg; sqInt length; sqInt i; sqInt rcvr; sqInt valuePointer; sqInt oop; sqInt oop1; sqInt header; sqInt sz; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; arg = null; goto l1; } arg = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; if (!foo->successFlag) { return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!((fetchClassOf(rcvr)) == (fetchClassOf(arg)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l3; } if (((((usqInt) header) >> 8) & 15) < 8) { length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l3; } else { length = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l3; } l3: /* end lengthOf:baseHeader:format: */; if (!(length == (lengthOf(arg)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } for (i = 0; i <= (length - 1); i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = longAt((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, valuePointer); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } /* Set or clear the flag that controls whether modifications of the Display object are propagated to the underlying platform's screen. */ sqInt primitiveDeferDisplayUpdates(void) { register struct foo * foo = &fum; sqInt flag; flag = longAt(foo->stackPointer); if (flag == foo->trueObj) { foo->deferDisplayUpdates = 1; } else { if (flag == foo->falseObj) { foo->deferDisplayUpdates = 0; } else { /* begin primitiveFail */ foo->successFlag = 0; } } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Pass in a non-negative value to disable the architectures powermanager if any, zero to enable. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveDisablePowerManager(void) { register struct foo * foo = &fum; sqInt integer; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integer = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integer = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { ioDisablePowerManager(integer); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } sqInt primitiveDiv(void) { register struct foo * foo = &fum; sqInt quotient; sqInt sp; quotient = doPrimitiveDivby(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) quotient)) ^ ((((int) quotient)) << 1)) >= 0) # else ((quotient >= -1073741824) && (quotient <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((quotient << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } sqInt primitiveDivide(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt integerPointer; sqInt integerPointer1; sqInt sp; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerReceiver = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerArgument = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; if ((integerArgument != 0) && ((integerReceiver % integerArgument) == 0)) { /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (integerReceiver / integerArgument))) ^ ((((int) (integerReceiver / integerArgument))) << 1)) >= 0) # else (((integerReceiver / integerArgument) >= -1073741824) && ((integerReceiver / integerArgument) <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), (((integerReceiver / integerArgument) << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } else { /* begin primitiveFail */ foo->successFlag = 0; } } /* Simulate an primitiveExternalCall invocation (e.g. for the Debugger). Do not cache anything. e.g. ContextPart>>tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments */ sqInt primitiveDoNamedPrimitiveWithArgs(void) { register struct foo * foo = &fum; sqInt functionName; sqInt functionLength; sqInt methodArg; sqInt moduleName; sqInt arraySize; sqInt methodHeader; sqInt spec; sqInt moduleLength; sqInt argumentArray; sqInt index; void (*addr)(); sqInt successValue; sqInt header; sqInt object; sqInt sp; sqInt sp1; sqInt sz; sqInt successValue1; sqInt oop; sqInt successValue2; sqInt header1; sqInt oop1; sqInt sz1; sqInt header2; sqInt cntxSize; sqInt sz2; sqInt oop3; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop11; sqInt oop2; sqInt oop4; argumentArray = longAt(foo->stackPointer); if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header2 = longAt(argumentArray); if ((header2 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l3; } else { sz = header2 & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin success: */ /* begin roomToPushNArgs: */ if (((headerOf(foo->method)) & LargeContextBit) != 0) { cntxSize = ((LARGE_CONTEXT_SIZE) / (BYTES_PER_WORD)) - ReceiverIndex; } else { cntxSize = ((SMALL_CONTEXT_SIZE) / (BYTES_PER_WORD)) - ReceiverIndex; } successValue1 = ((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) <= cntxSize; foo->successFlag = successValue1 && foo->successFlag; /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; methodArg = null; goto l1; } methodArg = oop; l1: /* end stackObjectValue: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!(((((usqInt) (longAt(methodArg))) >> 8) & 15) >= 12)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } methodHeader = longAt((methodArg + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); if (!(((((usqInt) methodHeader) >> 10) & 255) > 2)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin assertClassOf:is: */ oop3 = spec = longAt((methodArg + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD))); /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; classOop = longAt((oop4 + (BASE_HEADER_SIZE)) + (ClassArray << (SHIFT_FOR_WORD))); if ((oop3 & 1)) { foo->successFlag = 0; goto l5; } ccIndex = (((usqInt) (longAt(oop3))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop3 - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop11 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l5: /* end assertClassOf:is: */; if (!(foo->successFlag && (((lengthOf(spec)) == 4) && ((primitiveIndexOfMethodHeader(methodHeader)) == 117)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!(((((usqInt) methodHeader) >> 25) & 15) == arraySize)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } moduleName = longAt((spec + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if (moduleName == foo->nilObj) { moduleLength = 0; } else { /* begin success: */ successValue = ((moduleName & 1) == 0) && (((((usqInt) (longAt(moduleName))) >> 8) & 15) >= 8); foo->successFlag = successValue && foo->successFlag; /* begin lengthOf: */ header = longAt(moduleName); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(moduleName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { moduleLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { moduleLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { moduleLength = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; ; } functionName = longAt((spec + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD))); /* begin success: */ successValue2 = ((functionName & 1) == 0) && (((((usqInt) (longAt(functionName))) >> 8) & 15) >= 8); foo->successFlag = successValue2 && foo->successFlag; /* begin lengthOf: */ header1 = longAt(functionName); /* begin lengthOf:baseHeader:format: */ if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz2 = (longAt(functionName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz2 = header1 & (SIZE_MASK); } sz2 -= header1 & (SIZE_4_BIT); if (((((usqInt) header1) >> 8) & 15) <= 4) { functionLength = ((usqInt) (sz2 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l4; } if (((((usqInt) header1) >> 8) & 15) < 8) { functionLength = ((usqInt) (sz2 - (BASE_HEADER_SIZE))) >> 2; goto l4; } else { functionLength = (sz2 - (BASE_HEADER_SIZE)) - (((((usqInt) header1) >> 8) & 15) & 3); goto l4; } l4: /* end lengthOf:baseHeader:format: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } addr = ioLoadExternalFunctionOfLengthFromModuleOfLength(functionName + (BASE_HEADER_SIZE), functionLength, moduleName + (BASE_HEADER_SIZE), moduleLength); if (addr == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); foo->argumentCount = arraySize; index = 1; while (index <= arraySize) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = argumentArray; foo->lkupClass = foo->nilObj; callExternalPrimitive(addr); /* begin popRemappableOop */ oop1 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; argumentArray = oop1; if (!(foo->successFlag)) { /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - ((arraySize - 1) * (BYTES_PER_WORD)), argumentArray); foo->stackPointer = sp1; foo->argumentCount = 3; } } sqInt primitiveDoPrimitiveWithArgs(void) { register struct foo * foo = &fum; sqInt cntxSize; sqInt primIdx; sqInt arraySize; sqInt argumentArray; sqInt index; sqInt object; sqInt sp; sqInt sp1; sqInt sp2; sqInt sz; sqInt objectPointer; sqInt sz1; sqInt successValue; sqInt integerPointer; sqInt oop; sqInt header; sqInt header1; argumentArray = longAt(foo->stackPointer); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin fetchWordLengthOf: */ objectPointer = foo->activeContext; /* begin sizeBitsOf: */ header1 = longAt(objectPointer); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l3; } else { sz1 = header1 & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOf: */; cntxSize = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin success: */ successValue = ((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) < cntxSize; foo->successFlag = successValue && foo->successFlag; if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { primIdx = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; primIdx = 0; goto l1; } primIdx = null; l1: /* end stackIntegerValue: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); foo->primitiveIndex = primIdx; foo->argumentCount = arraySize; index = 1; while (index <= foo->argumentCount) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = argumentArray; foo->lkupClass = foo->nilObj; primitiveResponse(); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; argumentArray = oop; if (!(foo->successFlag)) { /* begin pop: */ foo->stackPointer -= arraySize * (BYTES_PER_WORD); /* begin pushInteger: */ /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), ((primIdx << 1) | 1)); foo->stackPointer = sp1; /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), argumentArray); foo->stackPointer = sp2; foo->argumentCount = 2; } } sqInt primitiveEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt result; sqInt integerReceiver; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerArgument = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerReceiver = top1; /* begin compare31or32Bits:equal: */ if (((integerReceiver & 1)) && ((integerArgument & 1))) { result = integerReceiver == integerArgument; goto l1; } result = (positive32BitValueOf(integerReceiver)) == (positive32BitValueOf(integerArgument)); l1: /* end compare31or32Bits:equal: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (result) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* is the receiver the same object as the argument? */ sqInt primitiveEquivalent(void) { register struct foo * foo = &fum; sqInt thisObject; sqInt otherObject; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; otherObject = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisObject = top1; /* begin pushBool: */ if (thisObject == otherObject) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } /* receiver, args, then method are on top of stack. Execute method against receiver and args */ sqInt primitiveExecuteMethod(void) { register struct foo * foo = &fum; sqInt top; sqInt successValue; sqInt methodPointer; sqInt primBits; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; foo->newMethod = top; /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); /* begin success: */ successValue = (foo->argumentCount - 1) == (argumentCountOf(foo->newMethod)); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { foo->argumentCount -= 1; /* begin executeNewMethod */ if (foo->primitiveIndex > 0) { primitiveResponse(); if (foo->successFlag) { goto l1; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } l1: /* end executeNewMethod */; } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* receiver, argsArray, then method are on top of stack. Execute method against receiver and args */ sqInt primitiveExecuteMethodArgsArray(void) { register struct foo * foo = &fum; sqInt methodArgument; sqInt argCnt; sqInt argumentArray; sqInt top; sqInt top1; sqInt dst; sqInt in; sqInt lastIn; sqInt out; sqInt methodPointer; sqInt primBits; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; methodArgument = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; argumentArray = top1; if (!(((methodArgument & 1) == 0) && ((((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) && (((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))))) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); /* begin primitiveFail */ foo->successFlag = 0; return null; } argCnt = (((usqInt) (longAt((methodArgument + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 25) & 15; if (!(argCnt == (fetchWordLengthOf(argumentArray)))) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin transfer:from:to: */ dst = foo->stackPointer + (BYTES_PER_WORD); flag("Dan"); in = (argumentArray + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); lastIn = in + (argCnt * (BYTES_PER_WORD)); out = dst - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } /* begin unPop: */ foo->stackPointer += argCnt * (BYTES_PER_WORD); foo->newMethod = methodArgument; /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); foo->argumentCount = argCnt; /* begin executeNewMethod */ if (foo->primitiveIndex > 0) { primitiveResponse(); if (foo->successFlag) { goto l1; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } l1: /* end executeNewMethod */; foo->successFlag = 1; } sqInt primitiveExitToDebugger(void) { error("Exit to debugger at user request"); } /* Computes E raised to the receiver power. */ sqInt primitiveExp(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(exp(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Exponent part of this float. */ sqInt primitiveExponent(void) { register struct foo * foo = &fum; int pwr; double frac; double rcvr; sqInt sp; rcvr = popFloat(); if (foo->successFlag) { frac = frexp(rcvr, &pwr); /* begin pushInteger: */ /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), (((pwr - 1) << 1) | 1)); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Call an external primitive. The external primitive methods contain as first literal an array consisting of: * The module name (String | Symbol) * The function name (String | Symbol) * The session ID (SmallInteger) [OBSOLETE] * The function index (Integer) in the externalPrimitiveTable For fast failures the primitive index of any method where the external prim is not found is rewritten in the method cache with zero. This allows for ultra fast responses as long as the method stays in the cache. The fast failure response relies on lkupClass being properly set. This is done in #addToMethodCacheSel:class:method:primIndex: to compensate for execution of methods that are looked up in a superclass (such as in primitivePerformAt). With the latest modifications (e.g., actually flushing the function addresses from the VM), the session ID is obsolete. But for backward compatibility it is still kept around. Also, a failed lookup is reported specially. If a method has been looked up and not been found, the function address is stored as -1 (e.g., the SmallInteger -1 to distinguish from 16rFFFFFFFF which may be returned from the lookup). It is absolutely okay to remove the rewrite if we run into any problems later on. It has an approximate speed difference of 30% per failed primitive call which may be noticable but if, for any reasons, we run into problems (like with J3) we can always remove the rewrite. */ sqInt primitiveExternalCall(void) { register struct foo * foo = &fum; sqInt functionName; sqInt functionLength; sqInt moduleName; sqInt moduleLength; sqInt index; sqInt lit; void * addr; sqInt successValue; sqInt header; sqInt successValue1; sqInt methodPointer; sqInt successValue2; sqInt successValue3; sqInt header1; sqInt sz; sqInt sz1; /* begin success: */ successValue1 = (literalCountOf(foo->newMethod)) > 0; foo->successFlag = successValue1 && foo->successFlag; if (!(foo->successFlag)) { return null; } /* begin literal:ofMethod: */ methodPointer = foo->newMethod; lit = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((0 + LiteralStart) << (SHIFT_FOR_WORD))); /* begin success: */ successValue2 = (((lit & 1) == 0) && (((((usqInt) (longAt(lit))) >> 8) & 15) == 2)) && ((lengthOf(lit)) == 4); foo->successFlag = successValue2 && foo->successFlag; if (!(foo->successFlag)) { return null; } index = longAt((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((index & 1)) { index = (index >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (!(foo->successFlag)) { return null; } if (index < 0) { rewriteMethodCacheSelclassprimIndex(foo->messageSelector, foo->lkupClass, 0); /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if ((index > 0) && (index <= MaxExternalPrimitiveTableSize)) { addr = foo->externalPrimitiveTable[index - 1]; if (addr != 0) { rewriteMethodCacheSelclassprimIndexprimFunction(foo->messageSelector, foo->lkupClass, 1000 + index, addr); callExternalPrimitive(addr); return null; } /* begin primitiveFail */ foo->successFlag = 0; return null; } longAtput((lit + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD)), ConstZero); longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ConstZero); moduleName = longAt((lit + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if (moduleName == foo->nilObj) { moduleLength = 0; } else { /* begin success: */ successValue = ((moduleName & 1) == 0) && (((((usqInt) (longAt(moduleName))) >> 8) & 15) >= 8); foo->successFlag = successValue && foo->successFlag; /* begin lengthOf: */ header = longAt(moduleName); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(moduleName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { moduleLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { moduleLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { moduleLength = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; ; } functionName = longAt((lit + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD))); /* begin success: */ successValue3 = ((functionName & 1) == 0) && (((((usqInt) (longAt(functionName))) >> 8) & 15) >= 8); foo->successFlag = successValue3 && foo->successFlag; /* begin lengthOf: */ header1 = longAt(functionName); /* begin lengthOf:baseHeader:format: */ if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(functionName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header1 & (SIZE_MASK); } sz1 -= header1 & (SIZE_4_BIT); if (((((usqInt) header1) >> 8) & 15) <= 4) { functionLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l3; } if (((((usqInt) header1) >> 8) & 15) < 8) { functionLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l3; } else { functionLength = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header1) >> 8) & 15) & 3); goto l3; } l3: /* end lengthOf:baseHeader:format: */; if (!(foo->successFlag)) { return null; } /* Addr ~= 0 indicates we have a compat match later */ addr = 0; if (moduleLength == 0) { /* Search the obsolete named primitive table for a match */ /* The returned value is the index into the obsolete primitive table. If the index is found, use the 'C-style' version of the lookup. */ index = findObsoleteNamedPrimitivelength((pointerForOop(functionName)) + (BASE_HEADER_SIZE), functionLength); if (!(index < 0)) { addr = ioLoadFunctionFrom(((char*) ((obsoleteNamedPrimitiveTable[index])[2])), ((char*) ((obsoleteNamedPrimitiveTable[index])[1]))); } } if (addr == 0) { /* Only if no compat version was found */ addr = ioLoadExternalFunctionOfLengthFromModuleOfLength(functionName + (BASE_HEADER_SIZE), functionLength, moduleName + (BASE_HEADER_SIZE), moduleLength); } if (addr == 0) { index = -1; } else { /* add the function to the external primitive table */ index = addToExternalPrimitiveTable(addr); } /* begin success: */ foo->successFlag = (index >= 0) && foo->successFlag; longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ((index << 1) | 1)); if (foo->successFlag && (addr != 0)) { rewriteMethodCacheSelclassprimIndexprimFunction(foo->messageSelector, foo->lkupClass, 1000 + index, addr); callExternalPrimitive(addr); } else { rewriteMethodCacheSelclassprimIndex(foo->messageSelector, foo->lkupClass, 0); } } sqInt primitiveFail(void) { foo->successFlag = 0; } /* Set specific primitive failure. */ sqInt primitiveFailFor(sqInt reasonCode) { register struct foo * foo = &fum; sqInt primFailCode; primFailCode = reasonCode; /* begin primitiveFail */ foo->successFlag = 0; } /* Primitive. Search up the context stack for the next method context marked for exception handling starting at the receiver. Return nil if none found */ sqInt primitiveFindHandlerContext(void) { register struct foo * foo = &fum; sqInt nilOop; sqInt thisCntx; sqInt sp; sqInt top; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisCntx = top; nilOop = foo->nilObj; do { if (isHandlerMarked(thisCntx)) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), thisCntx); foo->stackPointer = sp; return null; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } while(!(thisCntx == nilOop)); /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp1; return null; } /* Primitive. Search up the context stack for the next method context marked for unwind handling from the receiver up to but not including the argument. Return nil if none found. */ sqInt primitiveFindNextUnwindContext(void) { register struct foo * foo = &fum; sqInt nilOop; sqInt unwindMarked; sqInt thisCntx; sqInt aContext; sqInt sp; sqInt meth; sqInt header; sqInt pIndex; sqInt top; sqInt oop; sqInt sp1; sqInt top1; sqInt primBits; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; aContext = top; /* begin fetchPointer:ofObject: */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; oop = top1; thisCntx = longAt((oop + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); nilOop = foo->nilObj; while (!((thisCntx == aContext) || (thisCntx == nilOop))) { /* begin isUnwindMarked: */ header = longAt(thisCntx); if (!(((((usqInt) header) >> 12) & 31) == 14)) { unwindMarked = 0; goto l1; } meth = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); unwindMarked = pIndex == 198; l1: /* end isUnwindMarked: */; if (unwindMarked) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), thisCntx); foo->stackPointer = sp; return null; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), nilOop); foo->stackPointer = sp1; return null; } sqInt primitiveFloatAdd(void) { register struct foo * foo = &fum; return primitiveFloatAddtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatAddtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr + arg); } } sqInt primitiveFloatDivide(void) { register struct foo * foo = &fum; return primitiveFloatDividebyArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatDividebyArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin success: */ foo->successFlag = (arg != 0.0) && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr / arg); } } } sqInt primitiveFloatEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr == arg; } } sqInt primitiveFloatGreaterthanArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr > arg; } } sqInt primitiveFloatGreaterOrEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatGreaterOrEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatGreaterOrEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr >= arg; } } sqInt primitiveFloatGreaterThan(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatGreaterthanArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatLessthanArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr < arg; } } sqInt primitiveFloatLessOrEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatLessOrEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatLessOrEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr <= arg; } } sqInt primitiveFloatLessThan(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatLessthanArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatMultiply(void) { register struct foo * foo = &fum; return primitiveFloatMultiplybyArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatMultiplybyArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr * arg); } } sqInt primitiveFloatNotEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (!aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatSubtract(void) { register struct foo * foo = &fum; return primitiveFloatSubtractfromArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatSubtractfromArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr - arg); } } /* Clear the method lookup cache. This must be done after every programming change. */ sqInt primitiveFlushCache(void) { register struct foo * foo = &fum; sqInt i; sqInt aCompiledMethod; /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } for (i = 1; i <= AtCacheTotalSize; i += 1) { foo->atCache[i] = 0; } /* begin compilerFlushCacheHook: */ aCompiledMethod = null; if (foo->compilerInitialized) { compilerFlushCache(aCompiledMethod); } } /* The receiver is a compiledMethod. Clear all entries in the method lookup cache that refer to this method, presumably because it has been redefined, overridden or removed. */ sqInt primitiveFlushCacheByMethod(void) { register struct foo * foo = &fum; sqInt oldMethod; sqInt i; sqInt probe; oldMethod = longAt(foo->stackPointer); probe = 0; for (i = 1; i <= MethodCacheEntries; i += 1) { if ((foo->methodCache[probe + MethodCacheMethod]) == oldMethod) { foo->methodCache[probe + MethodCacheSelector] = 0; } probe += MethodCacheEntrySize; } /* begin compilerFlushCacheHook: */ if (foo->compilerInitialized) { compilerFlushCache(oldMethod); } } /* The receiver is a message selector. Clear all entries in the method lookup cache with this selector, presumably because an associated method has been redefined. */ sqInt primitiveFlushCacheSelective(void) { register struct foo * foo = &fum; sqInt selector; sqInt i; sqInt probe; selector = longAt(foo->stackPointer); probe = 0; for (i = 1; i <= MethodCacheEntries; i += 1) { if ((foo->methodCache[probe + MethodCacheSelector]) == selector) { foo->methodCache[probe + MethodCacheSelector] = 0; } probe += MethodCacheEntrySize; } } /* Primitive. Flush all the existing external primitives in the image thus forcing a reload on next invokation. */ sqInt primitiveFlushExternalPrimitives(void) { return flushExternalPrimitives(); } /* On some platforms, this primitive forces enqueued display updates to be processed immediately. On others, it does nothing. */ sqInt primitiveForceDisplayUpdate(void) { ioForceDisplayUpdate(); } /* Set force tenure flag to true, this forces a tenure operation on the next incremental GC */ EXPORT(sqInt) primitiveForceTenure(void) { foo->forceTenureFlag = 1; } /* On platforms that support it, this primitive prints the receiver, assumed to be a Form, to the default printer. */ sqInt primitiveFormPrint(void) { register struct foo * foo = &fum; sqInt landscapeFlag; double vScale; sqInt bitsArraySize; sqInt wordsPerLine; sqInt h; sqInt pixelsPerWord; sqInt rcvr; sqInt depth; sqInt ok; sqInt bitsArray; double hScale; sqInt w; sqInt sz; sqInt header; sqInt fmt; /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { landscapeFlag = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { landscapeFlag = 0; goto l1; } foo->successFlag = 0; landscapeFlag = null; l1: /* end booleanValueOf: */; vScale = floatValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); hScale = floatValueOf(longAt(foo->stackPointer - (2 * (BYTES_PER_WORD)))); rcvr = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } if (foo->successFlag) { if (!((((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4)) && ((lengthOf(rcvr)) >= 4))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } } if (foo->successFlag) { bitsArray = longAt((rcvr + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); w = fetchIntegerofObject(1, rcvr); h = fetchIntegerofObject(2, rcvr); depth = fetchIntegerofObject(3, rcvr); if (!((w > 0) && (h > 0))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } pixelsPerWord = 32 / depth; wordsPerLine = (w + (pixelsPerWord - 1)) / pixelsPerWord; if ((!((rcvr & 1))) && (((bitsArray & 1) == 0) && (isWordsOrBytesNonInt(bitsArray)))) { /* begin byteLengthOf: */ header = longAt(bitsArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(bitsArray - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { sz = header & (SIZE_MASK); } fmt = (((usqInt) header) >> 8) & 15; if (fmt < 8) { bitsArraySize = sz - (BASE_HEADER_SIZE); goto l2; } else { bitsArraySize = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l2; } l2: /* end byteLengthOf: */; /* begin success: */ foo->successFlag = (bitsArraySize == ((wordsPerLine * h) * 4)) && foo->successFlag; } else { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } } if (foo->successFlag) { if ((BYTES_PER_WORD) == 8) { ok = ioFormPrint(bitsArray + 8, w, h, depth, hScale, vScale, landscapeFlag); } else { ok = ioFormPrint(bitsArray + 4, w, h, depth, hScale, vScale, landscapeFlag); } /* begin success: */ foo->successFlag = ok && foo->successFlag; } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 3 * (BYTES_PER_WORD); } } sqInt primitiveFractionalPart(void) { register struct foo * foo = &fum; double trunc; double frac; double rcvr; rcvr = popFloat(); if (foo->successFlag) { frac = modf(rcvr, &trunc); pushFloat(frac); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Do a full garbage collection and return the number of bytes available (including swap space if dynamic memory management is supported). */ sqInt primitiveFullGC(void) { register struct foo * foo = &fum; sqInt integerValue; sqInt sp; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); incrementalGC(); fullGC(); /* begin pushInteger: */ integerValue = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(1)); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ((integerValue << 1) | 1)); foo->stackPointer = sp; } /* Fetch the system attribute with the given integer ID. The result is a string, which will be empty if the attribute is not defined. */ sqInt primitiveGetAttribute(void) { register struct foo * foo = &fum; sqInt sz; sqInt s; sqInt attr; sqInt sp; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { attr = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; attr = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { sz = attributeSize(attr); } if (foo->successFlag) { s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); getAttributeIntoLength(attr, s + (BASE_HEADER_SIZE), sz); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), s); foo->stackPointer = sp; } } /* Primitive. Return the next input event from the VM event queue. */ sqInt primitiveGetNextEvent(void) { register struct foo * foo = &fum; sqInt arg; int evtBuf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; sqInt i; sqInt value; sqInt eventTypeIs; sqInt oop; ; arg = longAt(foo->stackPointer); if (!((((arg & 1) == 0) && (((((usqInt) (longAt(arg))) >> 8) & 15) == 2)) && ((slotSizeOf(arg)) == 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } ioGetNextEvent(((sqInputEvent*) evtBuf)); if (!(foo->successFlag)) { return null; } eventTypeIs = evtBuf[0]; /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (evtBuf[0]))) ^ ((((int) (evtBuf[0]))) << 1)) >= 0) # else (((evtBuf[0]) >= -1073741824) && ((evtBuf[0]) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), (((evtBuf[0]) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } if (eventTypeIs == 6) { for (i = 1; i <= 7; i += 1) { value = evtBuf[i]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) arg)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(arg, value); } longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), value); } } else { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) ((evtBuf[1]) & MillisecondClockMask))) ^ ((((int) ((evtBuf[1]) & MillisecondClockMask))) << 1)) >= 0) # else ((((evtBuf[1]) & MillisecondClockMask) >= -1073741824) && (((evtBuf[1]) & MillisecondClockMask) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), ((((evtBuf[1]) & MillisecondClockMask) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } for (i = 2; i <= 7; i += 1) { value = evtBuf[i]; if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), ((value << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } } else { /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = arg; value = positive32BitIntegerFor(value); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; arg = oop; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) arg)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(arg, value); } longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), value); } } } if (!(foo->successFlag)) { return null; } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } sqInt primitiveGreaterOrEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt integerPointer; sqInt integerPointer1; sqInt sp; sqInt sp1; sqInt top; sqInt top1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver >= integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveGreaterThan(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt integerPointer; sqInt integerPointer1; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver > integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Answer an integer identifying the type of image. The image version number may identify the format of the image (e.g. 32 or 64-bit word size) or specific requirements of the image (e.g. block closure support required). This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveImageFormatVersion(void) { register struct foo * foo = &fum; sqInt oop; sqInt sp; /* begin pop:thenPush: */ oop = positive32BitIntegerFor(imageFormatVersionNumber); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* When called with a single string argument, record the string as the current image file name. When called with zero arguments, return a string containing the current image file name. */ sqInt primitiveImageName(void) { register struct foo * foo = &fum; void * sCRIfn; sqInt sz; sqInt okToRename; sqInt s; sqInt sp; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop; if (foo->argumentCount == 1) { /* If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok */ sCRIfn = ioLoadFunctionFrom("secCanRenameImage", "SecurityPlugin"); if (sCRIfn != 0) { okToRename = ((sqInt (*)(void))sCRIfn)(); if (!(okToRename)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } s = longAt(foo->stackPointer); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassString << (SHIFT_FOR_WORD))); if ((s & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(s))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(s - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { sz = stSizeOf(s); imageNamePutLength(s + (BASE_HEADER_SIZE), sz); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } else { sz = imageNameSize(); s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); imageNameGetLength(s + (BASE_HEADER_SIZE), sz); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), s); foo->stackPointer = sp; } } /* Do a quick, incremental garbage collection and return the number of bytes immediately available. (Note: more space may be made available by doing a full garbage collection. */ sqInt primitiveIncrementalGC(void) { register struct foo * foo = &fum; sqInt integerValue; sqInt sp; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); incrementalGC(); /* begin pushInteger: */ integerValue = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(0)); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ((integerValue << 1) | 1)); foo->stackPointer = sp; } /* Note: We now have 10 bits of primitive index, but they are in two places for temporary backward compatibility. The time to unpack is negligible, since the reconstituted full index is stored in the method cache. */ sqInt primitiveIndexOf(sqInt methodPointer) { sqInt primBits; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; return (primBits & 511) + (((usqInt) primBits) >> 19); } /* Note: We now have 10 bits of primitive index, but they are in two places for temporary backward compatibility. The time to unpack is negligible, since the derived primitive function pointer is stored in the method cache. */ sqInt primitiveIndexOfMethodHeader(sqInt methodHeader) { sqInt primBits; primBits = ((usqInt) methodHeader) >> 1; return (primBits & 511) + ((((usqInt) primBits) >> 19) & 512); } /* Register the input semaphore. The argument is an index into the ExternalObjectsArray part of the specialObjectsArray and must have been allocated via 'Smalltalk registerExternalObject: the Semaphore' */ sqInt primitiveInputSemaphore(void) { register struct foo * foo = &fum; sqInt arg; arg = longAt(foo->stackPointer); if ((arg & 1)) { ioSetInputSemaphore((arg >> 1)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } } /* Return an integer indicating the reason for the most recent input interrupt. */ sqInt primitiveInputWord(void) { register struct foo * foo = &fum; sqInt sp; /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((0 << 1) | 1)); foo->stackPointer = sp; } sqInt primitiveInstVarAt(void) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt value; sqInt hdr; sqInt rcvr; sqInt index; sqInt sp; sqInt integerPointer; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l3; } l3: /* end checkedIntegerValueOf: */; rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (foo->successFlag) { hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l5; } if (fmt < 2) { fixedFields = totalLength; goto l5; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l4; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l4; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l4; } l4: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l5: /* end fixedFieldsOf:format:length: */; if (!((index >= 1) && (index <= fixedFields))) { foo->successFlag = 0; } } if (foo->successFlag) { /* begin subscript:with:format: */ if (fmt <= 4) { value = longAt((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); goto l1; } if (fmt < 8) { value = positive32BitIntegerFor(long32At((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2))); goto l1; } else { value = (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << 1) | 1); goto l1; } l1: /* end subscript:with:format: */; } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp; } } sqInt primitiveInstVarAtPut(void) { register struct foo * foo = &fum; sqInt newValue; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt rcvr; sqInt index; sqInt valueToStore; sqInt sp; sqInt integerPointer; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; newValue = longAt(foo->stackPointer); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if (foo->successFlag) { hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l4; } if (fmt < 2) { fixedFields = totalLength; goto l4; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l4: /* end fixedFieldsOf:format:length: */; if (!((index >= 1) && (index <= fixedFields))) { foo->successFlag = 0; } } if (foo->successFlag) { /* begin subscript:with:storing:format: */ if (fmt <= 4) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, newValue); } longAtput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD)), newValue); } else { if (fmt < 8) { valueToStore = positive32BitValueOf(newValue); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2), valueToStore); } } else { if (!((newValue & 1))) { foo->successFlag = 0; } valueToStore = (newValue >> 1); if (!((valueToStore >= 0) && (valueToStore <= 255))) { foo->successFlag = 0; } if (foo->successFlag) { byteAtput((rcvr + (BASE_HEADER_SIZE)) + (index - 1), valueToStore); } } } } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), newValue); foo->stackPointer = sp; } } /* Note: this primitive has been decommissioned. It is only here for short-term compatibility with an internal 2.3beta-d image that used this. It did not save much time and it complicated several things. Plus Jitter will do it right anyway. */ sqInt primitiveInstVarsPutFromStack(void) { register struct foo * foo = &fum; sqInt offsetBits; sqInt i; sqInt rcvr; sqInt valuePointer; /* Mark dirty so stores below can be unchecked */ rcvr = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { beRootIfOld(rcvr); } for (i = 0; i <= (foo->argumentCount - 1); i += 1) { if ((i & 3) == 0) { offsetBits = positive32BitValueOf(literalofMethod(((sqInt) i >> 2), foo->newMethod)); } /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (i * (BYTES_PER_WORD))); longAtput((rcvr + (BASE_HEADER_SIZE)) + ((offsetBits & 255) << (SHIFT_FOR_WORD)), valuePointer); offsetBits = ((usqInt) offsetBits) >> 8; } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } /* Return the 32bit signed integer contents of a words receiver */ sqInt primitiveIntegerAt(void) { register struct foo * foo = &fum; sqInt sz; sqInt value; int intValue; sqInt rcvr; sqInt index; sqInt addr; sqInt sp; sqInt object; sqInt sp1; sqInt integerPointer; sqInt header; sqInt successValue; sqInt sz1; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } index = null; l1: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) == 6))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; /* begin success: */ successValue = (index >= 1) && (index <= sz); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* for zero indexing */ addr = ((rcvr + (BASE_HEADER_SIZE)) - 4) + (index * 4); value = intAt(addr); /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pushInteger: */ /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ((value << 1) | 1)); foo->stackPointer = sp; } else { /* 32 bit int may have been stored in 32 or 64 bit sqInt */ intValue = value; /* begin push: */ object = signed32BitIntegerFor(intValue); longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp1; } } } /* Return the 32bit signed integer contents of a words receiver */ sqInt primitiveIntegerAtPut(void) { register struct foo * foo = &fum; sqInt sz; sqInt valueOop; sqInt value; sqInt rcvr; sqInt index; sqInt addr; sqInt sp; sqInt integerPointer; sqInt header; sqInt sz1; valueOop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } index = null; l1: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) == 6))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; if (!((index >= 1) && (index <= sz))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if ((valueOop & 1)) { value = (valueOop >> 1); } else { value = signed32BitValueOf(valueOop); } if (foo->successFlag) { /* for zero indexing */ addr = ((rcvr + (BASE_HEADER_SIZE)) - 4) + (index * 4); value = intAtput(addr, value); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), valueOop); foo->stackPointer = sp; } } /* Answer a string corresponding to the version of the interpreter source. This represents the version level of the Smalltalk source code (interpreter and various plugins) that is translated to C by a CCodeGenerator, as distinct from the external platform source code, typically written in C and managed separately for each platform. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveInterpreterSourceVersion(void) { register struct foo * foo = &fum; void * p; char * cString; sqInt versionString; sqInt len; sqInt sp; cString = InterpreterSourceVersion; len = strlen(cString); versionString = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), len); /* begin arrayValueOf: */ if ((!((versionString & 1))) && (((versionString & 1) == 0) && (isWordsOrBytesNonInt(versionString)))) { p = pointerForOop(versionString + (BASE_HEADER_SIZE)); goto l1; } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end arrayValueOf: */; strncpy(p, cString, len); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), versionString); foo->stackPointer = sp; } /* Register the user interrupt semaphore. If the argument is not a Semaphore, unregister the current interrupt semaphore. */ sqInt primitiveInterruptSemaphore(void) { register struct foo * foo = &fum; sqInt arg; sqInt top; sqInt oop; sqInt oop1; sqInt valuePointer; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; arg = top; if ((fetchClassOf(arg)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, arg); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD)), arg); } else { /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; valuePointer = foo->nilObj; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD)), valuePointer); } } /* Primitive. 'Invoke' an object like a function, sending the special message run: originalSelector with: arguments in: aReceiver. */ sqInt primitiveInvokeObjectAsMethod(void) { register struct foo * foo = &fum; sqInt newReceiver; sqInt runReceiver; sqInt runArgs; sqInt runSelector; sqInt lookupClass; sqInt sp; sqInt sp1; sqInt sp2; sqInt sp3; sqInt count; sqInt src; sqInt in; sqInt lastIn; sqInt out; sqInt oop; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; runArgs = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), foo->argumentCount); beRootIfOld(runArgs); /* begin transfer:from:to: */ count = foo->argumentCount; src = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)); flag("Dan"); in = src - (BYTES_PER_WORD); lastIn = in + (count * (BYTES_PER_WORD)); out = (runArgs + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } runSelector = foo->messageSelector; runReceiver = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); newReceiver = foo->newMethod; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorRunWithIn << (SHIFT_FOR_WORD))); foo->argumentCount = 3; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), newReceiver); foo->stackPointer = sp; /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), runSelector); foo->stackPointer = sp1; /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), runArgs); foo->stackPointer = sp2; /* begin push: */ longAtput(sp3 = foo->stackPointer + (BYTES_PER_WORD), runReceiver); foo->stackPointer = sp3; /* begin fetchClassOf: */ if ((newReceiver & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lookupClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(newReceiver))) >> 12) & 31; if (ccIndex == 0) { lookupClass = (longAt(newReceiver - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); lookupClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; findNewMethodInClass(lookupClass); executeNewMethodFromCache(); foo->successFlag = 1; } /* Primitive. Answer whether the argument to the primitive is a root for young space */ EXPORT(sqInt) primitiveIsRoot(void) { register struct foo * foo = &fum; sqInt oop; sqInt trueOrFalse; sqInt sp; sqInt sp1; sqInt oop1; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; oop = null; goto l1; } oop = oop1; l1: /* end stackObjectValue: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin pushBool: */ trueOrFalse = (longAt(oop)) & (ROOT_BIT); if (trueOrFalse) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* Primitive. Answer whether the argument to the primitive resides in young space. */ EXPORT(sqInt) primitiveIsYoung(void) { register struct foo * foo = &fum; sqInt oop; sqInt oop1; sqInt sp; sqInt sp1; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; oop = null; goto l1; } oop = oop1; l1: /* end stackObjectValue: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin pushBool: */ if ((((usqInt) oop)) >= (((usqInt) foo->youngStart))) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* Obsolete on virtually all platforms; old style input polling code. Return the next keycode and remove it from the input buffer. The low byte is the 8-bit ISO character. The next four bits are the Smalltalk modifier bits <cmd><option><ctrl><shift>. */ sqInt primitiveKbdNext(void) { register struct foo * foo = &fum; sqInt keystrokeWord; sqInt sp; sqInt sp1; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); keystrokeWord = ioGetKeystroke(); if (keystrokeWord >= 0) { /* begin pushInteger: */ /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), ((keystrokeWord << 1) | 1)); foo->stackPointer = sp1; } else { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; } } /* Obsolete on virtually all platforms; old style input polling code. Return the next keycode and without removing it from the input buffer. The low byte is the 8-bit ISO character. The next four bits are the Smalltalk modifier bits <cmd><option><ctrl><shift>. */ sqInt primitiveKbdPeek(void) { register struct foo * foo = &fum; sqInt keystrokeWord; sqInt sp; sqInt sp1; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); keystrokeWord = ioPeekKeystroke(); if (keystrokeWord >= 0) { /* begin pushInteger: */ /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), ((keystrokeWord << 1) | 1)); foo->stackPointer = sp1; } else { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; } } sqInt primitiveLessOrEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt integerPointer; sqInt integerPointer1; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver <= integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveLessThan(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt integerPointer; sqInt integerPointer1; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver < integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive. Return the n-th builtin module name. */ sqInt primitiveListBuiltinModule(void) { register struct foo * foo = &fum; sqInt length; sqInt i; char * moduleName; sqInt nameOop; sqInt index; sqInt sp; sqInt integerPointer; sqInt sp1; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (index <= 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } moduleName = ioListBuiltinModule(index); if (moduleName == null) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; return null; } length = strlen(moduleName); nameOop = instantiateClassindexableSize(splObj(ClassString), length); for (i = 0; i <= (length - 1); i += 1) { byteAtput((nameOop + (BASE_HEADER_SIZE)) + i, moduleName[i]); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), nameOop); foo->stackPointer = sp1; } /* Primitive. Return the n-th loaded external module name. */ sqInt primitiveListExternalModule(void) { register struct foo * foo = &fum; sqInt length; sqInt i; char * moduleName; sqInt nameOop; sqInt index; sqInt sp; sqInt integerPointer; sqInt sp1; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } index = null; l1: /* end stackIntegerValue: */; if (index <= 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } moduleName = ioListLoadedModule(index); if (moduleName == null) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; return null; } length = strlen(moduleName); nameOop = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), length); for (i = 0; i <= (length - 1); i += 1) { byteAtput((nameOop + (BASE_HEADER_SIZE)) + i, moduleName[i]); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), nameOop); foo->stackPointer = sp1; } /* This primitive is called from Squeak as... <imageSegment> loadSegmentFrom: aWordArray outPointers: anArray. */ /* This primitive will load a binary image segment created by primitiveStoreImageSegment. It expects the outPointer array to be of the proper size, and the wordArray to be well formed. It will return as its value the original array of roots, and the erstwhile segmentWordArray will have been truncated to a size of zero. If this primitive should fail, the segmentWordArray will, sadly, have been reduced to an unrecognizable and unusable jumble. But what more could you have done with it anyway? */ sqInt primitiveLoadImageSegment(void) { register struct foo * foo = &fum; sqInt mapOop; usqInt segOop; sqInt hdrTypeBits; usqInt lastPtr; sqInt segmentWordArray; sqInt doingClass; sqInt header; sqInt data; sqInt fieldOop; usqInt fieldPtr; usqInt lastOut; sqInt extraSize; usqInt outPtr; usqInt endSeg; sqInt outPointerArray; sqInt addr; sqInt addr1; sqInt sz; sqInt sz1; sqInt sp; sqInt header1; sqInt header2; if (DoAssertionChecks) { verifyCleanHeaders(); } outPointerArray = longAt(foo->stackPointer); lastOut = outPointerArray + (lastPointerOf(outPointerArray)); segmentWordArray = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* Essential type checks */ endSeg = (segmentWordArray + (sizeBitsOf(segmentWordArray))) - (BASE_HEADER_SIZE); if (!((((((usqInt) (longAt(outPointerArray))) >> 8) & 15) == 2) && (((((usqInt) (longAt(segmentWordArray))) >> 8) & 15) == 6))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } data = longAt(segmentWordArray + (BASE_HEADER_SIZE)); if (!(((data & 65535) == imageFormatVersionNumber) || (((data & 65535) == (imageFormatForwardCompatibilityVersion())) || ((data & 65535) == (imageFormatBackwardCompatibilityVersion()))))) { /* begin reverseBytesFrom:to: */ flag("Dan"); addr1 = segmentWordArray + (BASE_HEADER_SIZE); while ((((usqInt) addr1)) < (((usqInt) (endSeg + (BYTES_PER_WORD))))) { longAtput(addr1, byteSwapped(longAt(addr1))); addr1 += BYTES_PER_WORD; } data = longAt(segmentWordArray + (BASE_HEADER_SIZE)); if (!(((data & 65535) == imageFormatVersionNumber) || (((data & 65535) == (imageFormatForwardCompatibilityVersion())) || ((data & 65535) == (imageFormatBackwardCompatibilityVersion()))))) { /* begin reverseBytesFrom:to: */ flag("Dan"); addr = segmentWordArray + (BASE_HEADER_SIZE); while ((((usqInt) addr)) < (((usqInt) (endSeg + (BYTES_PER_WORD))))) { longAtput(addr, byteSwapped(longAt(addr))); addr += BYTES_PER_WORD; } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } } if (!((((usqInt) data) >> 16) == (((usqInt) (imageSegmentVersion())) >> 16))) { /* Reverse the byte-type objects once */ /* Oop of first embedded object */ segOop = ((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD)) + (foo->headerTypeBytes[(longAt((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD))) & TypeMask]); byteSwapByteObjectsFromto(segOop, endSeg + (BYTES_PER_WORD)); } segOop = ((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD)) + (foo->headerTypeBytes[(longAt((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD))) & TypeMask]); while (segOop <= endSeg) { if (((longAt(segOop)) & TypeMask) <= 1) { /* This object has a class field (type = 0 or 1) -- start with that. */ fieldPtr = segOop - (BYTES_PER_WORD); doingClass = 1; } else { /* No class field -- start with first data field */ fieldPtr = segOop + (BASE_HEADER_SIZE); doingClass = 0; } /* last field */ lastPtr = segOop + (lastPointerOf(segOop)); if (lastPtr > endSeg) { if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } while (!(fieldPtr > lastPtr)) { /* Examine each pointer field */ fieldOop = longAt(fieldPtr); if (doingClass) { hdrTypeBits = (longAt(fieldPtr)) & TypeMask; fieldOop -= hdrTypeBits; } if ((fieldOop & 1)) { /* Integer -- nothing to do */ fieldPtr += BYTES_PER_WORD; } else { if (!((fieldOop & 3) == 0)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((fieldOop & 2147483648U) == 0) { /* Internal pointer -- add segment offset */ mapOop = fieldOop + segmentWordArray; } else { /* External pointer -- look it up in outPointers */ outPtr = outPointerArray + (fieldOop & 2147483647U); if (outPtr > lastOut) { /* begin primitiveFail */ foo->successFlag = 0; return null; } mapOop = longAt(outPtr); } if (doingClass) { longAtput(fieldPtr, mapOop + hdrTypeBits); fieldPtr += 8; doingClass = 0; } else { longAtput(fieldPtr, mapOop); fieldPtr += BYTES_PER_WORD; } if (segOop < foo->youngStart) { possibleRootStoreIntovalue(segOop, mapOop); } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) segOop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(segOop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(segOop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(segOop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(segOop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } segOop = (segOop + sz) + (foo->headerTypeBytes[(longAt(segOop + sz)) & TypeMask]); } segOop = ((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD)) + (foo->headerTypeBytes[(longAt((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD))) & TypeMask]); while (segOop <= endSeg) { if (!(oopHasAcceptableClass(segOop))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* first field */ fieldPtr = segOop + (BASE_HEADER_SIZE); /* last field */ /* Go through all oops, remapping them... */ lastPtr = segOop + (lastPointerOf(segOop)); while (!(fieldPtr > lastPtr)) { /* Examine each pointer field */ fieldOop = longAt(fieldPtr); if (!(oopHasAcceptableClass(fieldOop))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } fieldPtr += BYTES_PER_WORD; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) segOop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(segOop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(segOop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header2 = longAt(segOop); if ((header2 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(segOop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header2 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } segOop = (segOop + sz1) + (foo->headerTypeBytes[(longAt(segOop + sz1)) & TypeMask]); } extraSize = foo->headerTypeBytes[(longAt(segmentWordArray)) & TypeMask]; hdrTypeBits = (longAt(segmentWordArray)) & TypeMask; if (extraSize == 8) { longAtput(segmentWordArray - extraSize, ((BASE_HEADER_SIZE) + (BYTES_PER_WORD)) + hdrTypeBits); } else { header = longAt(segmentWordArray); longAtput(segmentWordArray, ((header - (header & (SIZE_MASK))) + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD)); } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), ((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD)) + (foo->headerTypeBytes[(longAt((segmentWordArray + (BASE_HEADER_SIZE)) + (BYTES_PER_WORD))) & TypeMask])); foo->stackPointer = sp; } sqInt primitiveLoadInstVar(void) { register struct foo * foo = &fum; sqInt thisReceiver; sqInt top; sqInt object; sqInt sp; sqInt fieldIndex; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisReceiver = top; /* begin push: */ /* begin fetchPointer:ofObject: */ fieldIndex = foo->primitiveIndex - 264; object = longAt((thisReceiver + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } /* Natural log. */ sqInt primitiveLogN(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(log(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Register the low-space semaphore. If the argument is not a Semaphore, unregister the current low-space Semaphore. */ sqInt primitiveLowSpaceSemaphore(void) { register struct foo * foo = &fum; sqInt arg; sqInt top; sqInt oop; sqInt oop1; sqInt valuePointer; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; arg = top; if ((fetchClassOf(arg)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, arg); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheLowSpaceSemaphore << (SHIFT_FOR_WORD)), arg); } else { /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; valuePointer = foo->nilObj; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (TheLowSpaceSemaphore << (SHIFT_FOR_WORD)), valuePointer); } } sqInt primitiveMakePoint(void) { register struct foo * foo = &fum; sqInt argument; sqInt pt; sqInt rcvr; sqInt pointResult; sqInt pointResult1; sqInt valuePointer; sqInt pointResult2; sqInt valuePointer1; sqInt valuePointer2; sqInt sp; argument = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((rcvr & 1)) { if ((argument & 1)) { /* begin makePointwithxValue:yValue: */ pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((((argument >> 1)) << 1) | 1)); pt = pointResult; } else { /* begin makePointwithxValue:yValue: */ pointResult1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult1; /* begin storePointer:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer); } } else { if (!((fetchClassOf(rcvr)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } /* begin makePointwithxValue:yValue: */ pointResult2 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult2; /* begin storePointer:ofObject:withValue: */ valuePointer1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer1); } longAtput((pt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer1); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer2); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer2); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), pt); foo->stackPointer = sp; } /* Primitive. Mark the method for exception handling. The primitive must fail after marking the context so that the regular code is run. */ sqInt primitiveMarkHandlerMethod(void) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Primitive. Mark the method for exception unwinding. The primitive must fail after marking the context so that the regular code is run. */ sqInt primitiveMarkUnwindMethod(void) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Return the method an external primitive was defined in */ sqInt primitiveMethod(void) { return foo->newMethod; } /* This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveMicrosecondClock(void) { register struct foo * foo = &fum; sqInt oop; sqInt sp; /* begin pop:thenPush: */ oop = positive64BitIntegerFor(ioMicroSecondClock()); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* Return the value of the millisecond clock as an integer. Note that the millisecond clock wraps around periodically. On some platforms it can wrap daily. The range is limited to SmallInteger maxVal / 2 to allow delays of up to that length without overflowing a SmallInteger. */ sqInt primitiveMillisecondClock(void) { register struct foo * foo = &fum; sqInt oop; sqInt sp; /* begin pop:thenPush: */ oop = ((((ioMSecs()) & MillisecondClockMask) << 1) | 1); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } sqInt primitiveMod(void) { register struct foo * foo = &fum; sqInt mod; sqInt sp; mod = doPrimitiveModby(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) mod)) ^ ((((int) mod)) << 1)) >= 0) # else ((mod >= -1073741824) && (mod <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((mod << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } /* Obsolete on virtually all platforms; old style input polling code. Return the mouse button state. The low three bits encode the state of the <red><yellow><blue> mouse buttons. The next four bits encode the Smalltalk modifier bits <cmd><option><ctrl><shift>. */ sqInt primitiveMouseButtons(void) { register struct foo * foo = &fum; sqInt buttonWord; sqInt sp; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); buttonWord = ioGetButtonState(); /* begin pushInteger: */ /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ((buttonWord << 1) | 1)); foo->stackPointer = sp; } /* Obsolete on virtually all platforms; old style input polling code. Return a Point indicating current position of the mouse. Note that mouse coordinates may be negative if the mouse moves above or to the left of the top-left corner of the Smalltalk window. */ sqInt primitiveMousePoint(void) { register struct foo * foo = &fum; sqInt y; sqInt pointWord; sqInt x; sqInt object; sqInt sp; sqInt pointResult; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); pointWord = ioMousePoint(); /* begin signExtend16: */ if ((((((usqInt) pointWord) >> 16) & 65535) & 32768) == 0) { x = (((usqInt) pointWord) >> 16) & 65535; goto l1; } else { x = ((((usqInt) pointWord) >> 16) & 65535) - 65536; goto l1; } l1: /* end signExtend16: */; /* begin signExtend16: */ if (((pointWord & 65535) & 32768) == 0) { y = pointWord & 65535; goto l2; } else { y = (pointWord & 65535) - 65536; goto l2; } l2: /* end signExtend16: */; /* begin push: */ /* begin makePointwithxValue:yValue: */ pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((x << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((y << 1) | 1)); object = pointResult; longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } sqInt primitiveMultiply(void) { register struct foo * foo = &fum; sqInt integerArg; sqInt integerResult; sqInt integerRcvr; sqInt integerPointer; sqInt integerPointer1; sqInt sp; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerRcvr = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerRcvr = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerArg = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArg = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; if (foo->successFlag) { /* check for C overflow by seeing if computation is reversible */ integerResult = integerRcvr * integerArg; if ((integerArg == 0) || ((integerResult / integerArg) == integerRcvr)) { /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerResult << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } else { /* begin primitiveFail */ foo->successFlag = 0; } } } /* Allocate a new fixed-size instance. Fail if the allocation would leave less than lowSpaceThreshold bytes free. May cause a GC */ sqInt primitiveNew(void) { register struct foo * foo = &fum; sqInt spaceOkay; sqInt class; sqInt object; sqInt sp; sqInt format; usqInt minFree; usqInt minFree1; /* The following may cause GC! */ class = longAt(foo->stackPointer); /* begin sufficientSpaceToInstantiate:indexableSize: */ format = (((usqInt) ((longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1)) >> 8) & 15; if ((0 > 0) && (format < 2)) { spaceOkay = 0; goto l1; } if (format < 8) { if (isExcessiveAllocationRequestshift(0, SHIFT_FOR_WORD)) { spaceOkay = 0; goto l1; } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (2500 + (0 * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { spaceOkay = 1; goto l1; } else { spaceOkay = sufficientSpaceAfterGC(minFree); goto l1; } spaceOkay = null; goto l1; } else { if (isExcessiveAllocationRequestshift(0, 0)) { spaceOkay = 0; goto l1; } /* begin sufficientSpaceToAllocate: */ minFree1 = (foo->lowSpaceThreshold + (2500 + 0)) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree1)) { spaceOkay = 1; goto l1; } else { spaceOkay = sufficientSpaceAfterGC(minFree1); goto l1; } spaceOkay = null; goto l1; } l1: /* end sufficientSpaceToInstantiate:indexableSize: */; /* begin success: */ foo->successFlag = spaceOkay && foo->successFlag; if (foo->successFlag) { /* begin push: */ object = instantiateClassindexableSize(popStack(), 0); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } } sqInt primitiveNewMethod(void) { register struct foo * foo = &fum; sqInt bytecodeCount; sqInt header; sqInt i; sqInt literalCount; sqInt size; sqInt class; sqInt theMethod; sqInt valuePointer; sqInt top; sqInt integerPointer; sqInt top1; sqInt top2; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; header = top; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { bytecodeCount = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; bytecodeCount = 0; goto l1; } bytecodeCount = null; l1: /* end popInteger */; /* begin success: */ foo->successFlag = ((header & 1)) && foo->successFlag; if (!(foo->successFlag)) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); return null; } /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; class = top2; size = ((((((usqInt) header) >> 10) & 255) + 1) * (BYTES_PER_WORD)) + bytecodeCount; theMethod = instantiateClassindexableSize(class, size); longAtput((theMethod + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD)), header); literalCount = (((usqInt) header) >> 10) & 255; for (i = 1; i <= literalCount; i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = foo->nilObj; if ((((usqInt) theMethod)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(theMethod, valuePointer); } longAtput((theMethod + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); } /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), theMethod); foo->stackPointer = sp; } /* Allocate a new indexable instance. Fail if the allocation would leave less than lowSpaceThreshold bytes free. */ sqInt primitiveNewWithArg(void) { register struct foo * foo = &fum; sqInt spaceOkay; usqInt size; sqInt class; sqInt oop; sqInt sp; sqInt format; usqInt minFree; usqInt minFree1; size = positive32BitValueOf(longAt(foo->stackPointer)); class = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ foo->successFlag = (size >= 0) && foo->successFlag; if (foo->successFlag) { /* begin sufficientSpaceToInstantiate:indexableSize: */ format = (((usqInt) ((longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1)) >> 8) & 15; if ((size > 0) && (format < 2)) { spaceOkay = 0; goto l1; } if (format < 8) { if (isExcessiveAllocationRequestshift(size, SHIFT_FOR_WORD)) { spaceOkay = 0; goto l1; } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (2500 + (size * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { spaceOkay = 1; goto l1; } else { spaceOkay = sufficientSpaceAfterGC(minFree); goto l1; } spaceOkay = null; goto l1; } else { if (isExcessiveAllocationRequestshift(size, 0)) { spaceOkay = 0; goto l1; } /* begin sufficientSpaceToAllocate: */ minFree1 = (foo->lowSpaceThreshold + (2500 + size)) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree1)) { spaceOkay = 1; goto l1; } else { spaceOkay = sufficientSpaceAfterGC(minFree1); goto l1; } spaceOkay = null; goto l1; } l1: /* end sufficientSpaceToInstantiate:indexableSize: */; /* begin success: */ foo->successFlag = spaceOkay && foo->successFlag; class = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); } if (foo->successFlag) { /* begin pop:thenPush: */ oop = instantiateClassindexableSize(class, size); longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } } /* PrimitiveNext will succeed only if the stream's array is in the atCache. Otherwise failure will lead to proper message lookup of at: and subsequent installation in the cache if appropriate. */ sqInt primitiveNext(void) { register struct foo * foo = &fum; sqInt stream; sqInt result; sqInt atIx; sqInt array; sqInt index; sqInt limit; sqInt sp; stream = longAt(foo->stackPointer); if (!((((stream & 1) == 0) && (((((usqInt) (longAt(stream))) >> 8) & 15) <= 4)) && ((lengthOf(stream)) >= (StreamReadLimitIndex + 1)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } array = longAt((stream + (BASE_HEADER_SIZE)) + (StreamArrayIndex << (SHIFT_FOR_WORD))); index = fetchIntegerofObject(StreamIndexIndex, stream); limit = fetchIntegerofObject(StreamReadLimitIndex, stream); atIx = array & AtCacheMask; if (!((index < limit) && ((foo->atCache[atIx + AtCacheOop]) == array))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } index += 1; /* Above may cause GC, so can't use stream, array etc. below it */ result = commonVariableatcacheIndex(array, index, atIx); if (foo->successFlag) { stream = longAt(foo->stackPointer); /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) index)) ^ ((((int) index)) << 1)) >= 0) # else ((index >= -1073741824) && (index <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((stream + (BASE_HEADER_SIZE)) + (StreamIndexIndex << (SHIFT_FOR_WORD)), ((index << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp; return null; } } sqInt primitiveNextInstance(void) { register struct foo * foo = &fum; sqInt object; sqInt instance; sqInt sp; sqInt thisClass; sqInt classPointer; sqInt thisObj; sqInt ccIndex; sqInt ccIndex1; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; object = longAt(foo->stackPointer); /* begin instanceAfter: */ /* begin fetchClassOf: */ if ((object & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classPointer = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex1 = (((usqInt) (longAt(object))) >> 12) & 31; if (ccIndex1 == 0) { classPointer = (longAt(object - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop1 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); classPointer = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex1 - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; thisObj = accessibleObjectAfter(object); while (!(thisObj == null)) { /* begin fetchClassOf: */ if ((thisObj & 1)) { /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; thisClass = longAt((oop2 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(thisObj))) >> 12) & 31; if (ccIndex == 0) { thisClass = (longAt(thisObj - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); thisClass = longAt((oop3 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; if (thisClass == classPointer) { instance = thisObj; goto l1; } thisObj = accessibleObjectAfter(thisObj); } instance = foo->nilObj; l1: /* end instanceAfter: */; if (instance == foo->nilObj) { /* begin primitiveFail */ foo->successFlag = 0; } else { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), instance); foo->stackPointer = sp; } } /* Return the object following the receiver in the heap. Return the SmallInteger zero when there are no more objects. */ sqInt primitiveNextObject(void) { register struct foo * foo = &fum; sqInt object; sqInt instance; sqInt sp; sqInt sp1; object = longAt(foo->stackPointer); instance = accessibleObjectAfter(object); if (instance == null) { /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), ((0 << 1) | 1)); foo->stackPointer = sp; } else { /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), instance); foo->stackPointer = sp1; } } /* PrimitiveNextPut will succeed only if the stream's array is in the atPutCache. Otherwise failure will lead to proper message lookup of at:put: and subsequent installation in the cache if appropriate. */ sqInt primitiveNextPut(void) { register struct foo * foo = &fum; sqInt stream; sqInt value; sqInt atIx; sqInt array; sqInt index; sqInt limit; sqInt sp; sqInt valToPut; sqInt fmt; sqInt fixedFields; sqInt stSize; value = longAt(foo->stackPointer); stream = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (!((((stream & 1) == 0) && (((((usqInt) (longAt(stream))) >> 8) & 15) <= 4)) && ((lengthOf(stream)) >= (StreamReadLimitIndex + 1)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } array = longAt((stream + (BASE_HEADER_SIZE)) + (StreamArrayIndex << (SHIFT_FOR_WORD))); index = fetchIntegerofObject(StreamIndexIndex, stream); limit = fetchIntegerofObject(StreamWriteLimitIndex, stream); atIx = (array & AtCacheMask) + AtPutBase; if (!((index < limit) && ((foo->atCache[atIx + AtCacheOop]) == array))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } index += 1; /* begin commonVariable:at:put:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) array)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(array, value); } longAtput((array + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); goto l1; } if (fmt < 8) { valToPut = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((array + (BASE_HEADER_SIZE)) + ((index - 1) << 2), valToPut); } goto l1; } if (fmt >= 16) { valToPut = asciiOfCharacter(value); if (!(foo->successFlag)) { goto l1; } } else { valToPut = value; } if ((valToPut & 1)) { valToPut = (valToPut >> 1); if (!((valToPut >= 0) && (valToPut <= 255))) { /* begin primitiveFail */ foo->successFlag = 0; goto l1; } byteAtput((array + (BASE_HEADER_SIZE)) + (index - 1), valToPut); goto l1; } } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end commonVariable:at:put:cacheIndex: */; if (foo->successFlag) { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) index)) ^ ((((int) index)) << 1)) >= 0) # else ((index >= -1073741824) && (index <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((stream + (BASE_HEADER_SIZE)) + (StreamIndexIndex << (SHIFT_FOR_WORD)), ((index << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp; return null; } } /* A placeholder for primitives that haven't been implemented or are being withdrawn gradually. Just absorbs any arguments and returns the receiver. */ sqInt primitiveNoop(void) { register struct foo * foo = &fum; /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } sqInt primitiveNotEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt result; sqInt integerReceiver; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerArgument = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerReceiver = top1; result = !(compare31or32Bitsequal(integerReceiver, integerArgument)); /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (result) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Defined for CompiledMethods only */ sqInt primitiveObjectAt(void) { register struct foo * foo = &fum; sqInt thisReceiver; sqInt index; sqInt object; sqInt sp; sqInt integerPointer; sqInt top; sqInt top1; sqInt successValue; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } index = null; l1: /* end popInteger */; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisReceiver = top1; /* begin success: */ foo->successFlag = (index > 0) && foo->successFlag; /* begin success: */ successValue = index <= ((literalCountOfHeader(longAt((thisReceiver + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) + LiteralStart); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin push: */ object = longAt((thisReceiver + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Defined for CompiledMethods only */ sqInt primitiveObjectAtPut(void) { register struct foo * foo = &fum; sqInt newValue; sqInt thisReceiver; sqInt index; sqInt sp; sqInt top; sqInt integerPointer; sqInt top1; sqInt top2; sqInt successValue; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; newValue = top; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } index = null; l1: /* end popInteger */; /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisReceiver = top2; /* begin success: */ foo->successFlag = (index > 0) && foo->successFlag; /* begin success: */ successValue = index <= ((literalCountOfHeader(longAt((thisReceiver + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) + LiteralStart); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) thisReceiver)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(thisReceiver, newValue); } longAtput((thisReceiver + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD)), newValue); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), newValue); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 3 * (BYTES_PER_WORD); } } sqInt primitiveObjectPointsTo(void) { register struct foo * foo = &fum; sqInt thang; sqInt i; sqInt rcvr; sqInt lastField; sqInt top; sqInt top1; sqInt sp; sqInt sp1; sqInt sp2; sqInt sp11; sqInt sp3; sqInt sp12; sqInt sz; sqInt header; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt header1; sqInt type; sqInt sp4; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thang = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; rcvr = top1; if ((rcvr & 1)) { /* begin pushBool: */ if (0) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } return null; } /* begin lastPointerOf: */ header = longAt(rcvr); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp4 = longAt((rcvr + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp4 & 1))) { contextSize = 0; goto l2; } contextSize = (sp4 >> 1); l2: /* end fetchStackPointerOf: */; lastField = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(rcvr); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOfSafe: */; lastField = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { lastField = 0; goto l4; } methodHeader = longAt(rcvr + (BASE_HEADER_SIZE)); lastField = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; for (i = (BASE_HEADER_SIZE); i <= lastField; i += (BYTES_PER_WORD)) { if ((longAt(rcvr + i)) == thang) { /* begin pushBool: */ if (1) { /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp2; } else { /* begin push: */ longAtput(sp11 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp11; } return null; } } /* begin pushBool: */ if (0) { /* begin push: */ longAtput(sp3 = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp3; } else { /* begin push: */ longAtput(sp12 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp12; } } /* Primitive. Invoke an obsolete indexed primitive. */ sqInt primitiveObsoleteIndexedPrimitive(void) { register struct foo * foo = &fum; char * functionName; char * pluginName; void * functionAddress; functionAddress = ((void *) ((obsoleteIndexedPrimitiveTable[foo->primitiveIndex])[2])); if (!(functionAddress == null)) { return ((sqInt (*)(void))functionAddress)(); } pluginName = (obsoleteIndexedPrimitiveTable[foo->primitiveIndex])[0]; functionName = (obsoleteIndexedPrimitiveTable[foo->primitiveIndex])[1]; if ((pluginName == null) && (functionName == null)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } functionAddress = ioLoadFunctionFrom(functionName, pluginName); if (!(functionAddress == 0)) { (obsoleteIndexedPrimitiveTable[foo->primitiveIndex])[2] = (((char*) functionAddress)); return ((sqInt (*)(void))functionAddress)(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } sqInt primitivePerform(void) { register struct foo * foo = &fum; sqInt newReceiver; sqInt performMethod; sqInt i; sqInt performSelector; sqInt selectorIndex; sqInt lookupClass; sqInt successValue; sqInt fieldIndex; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt valuePointer1; sqInt count; sqInt fromOop; sqInt toOop; sqInt fromIndex; sqInt lastFrom; sqInt toIndex; sqInt ccIndex; sqInt oop11; sqInt oop2; sqInt oop3; sqInt fieldIndex1; sqInt oop4; performSelector = foo->messageSelector; performMethod = foo->newMethod; foo->messageSelector = longAt(foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD))); /* NOTE: the following lookup may fail and be converted to #doesNotUnderstand:, so we must adjust argumentCount and slide args now, so that would work. */ /* Slide arguments down over selector */ newReceiver = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); foo->argumentCount -= 1; selectorIndex = (((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - foo->argumentCount; /* begin transfer:fromIndex:ofObject:toIndex:ofObject: */ count = foo->argumentCount; fromOop = foo->activeContext; toOop = foo->activeContext; flag("Dan"); fromIndex = fromOop + ((selectorIndex + 1) * (BYTES_PER_WORD)); toIndex = toOop + (selectorIndex * (BYTES_PER_WORD)); lastFrom = fromIndex + (count * (BYTES_PER_WORD)); while ((((usqInt) fromIndex)) < (((usqInt) lastFrom))) { fromIndex += BYTES_PER_WORD; toIndex += BYTES_PER_WORD; longAtput(toIndex, longAt(fromIndex)); } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); /* begin fetchClassOf: */ if ((newReceiver & 1)) { /* begin fetchPointer:ofObject: */ oop11 = foo->specialObjectsOop; lookupClass = longAt((oop11 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(newReceiver))) >> 12) & 31; if (ccIndex == 0) { lookupClass = (longAt(newReceiver - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); lookupClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; findNewMethodInClass(lookupClass); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin success: */ successValue = (argumentCountOf(foo->newMethod)) == foo->argumentCount; foo->successFlag = successValue && foo->successFlag; } if (foo->successFlag) { executeNewMethodFromCache(); foo->successFlag = 1; } else { for (i = 1; i <= foo->argumentCount; i += 1) { /* begin storePointer:ofObject:withValue: */ fieldIndex = ((foo->argumentCount - i) + 1) + selectorIndex; oop = foo->activeContext; /* begin fetchPointer:ofObject: */ fieldIndex1 = (foo->argumentCount - i) + selectorIndex; oop4 = foo->activeContext; valuePointer = longAt((oop4 + (BASE_HEADER_SIZE)) + (fieldIndex1 << (SHIFT_FOR_WORD))); if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, valuePointer); } longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); } /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); /* begin storePointer:ofObject:withValue: */ oop1 = foo->activeContext; valuePointer1 = foo->messageSelector; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer1); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (selectorIndex << (SHIFT_FOR_WORD)), valuePointer1); foo->argumentCount += 1; foo->newMethod = performMethod; foo->messageSelector = performSelector; } } /* Common routine used by perform:withArgs: and perform:withArgs:inSuperclass: */ /* NOTE: The case of doesNotUnderstand: is not a failure to perform. The only failures are arg types and consistency of argumentCount. */ sqInt primitivePerformAt(sqInt lookupClass) { register struct foo * foo = &fum; sqInt performArgCount; sqInt cntxSize; sqInt performMethod; sqInt performSelector; sqInt arraySize; sqInt argumentArray; sqInt index; sqInt sz; sqInt objectPointer; sqInt sz1; sqInt successValue; sqInt object; sqInt sp; sqInt successValue1; sqInt sp1; sqInt sp2; sqInt top; sqInt top1; sqInt header; sqInt header1; argumentArray = longAt(foo->stackPointer); if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (foo->successFlag) { /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin fetchWordLengthOf: */ objectPointer = foo->activeContext; /* begin sizeBitsOf: */ header1 = longAt(objectPointer); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; cntxSize = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin success: */ successValue = ((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) < cntxSize; foo->successFlag = successValue && foo->successFlag; } if (!(foo->successFlag)) { return null; } performSelector = foo->messageSelector; performMethod = foo->newMethod; /* pop the arg array and the selector, then push the args out of the array, as if they were on the stack */ performArgCount = foo->argumentCount; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; foo->messageSelector = top1; index = 1; while (index <= arraySize) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } foo->argumentCount = arraySize; findNewMethodInClass(lookupClass); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin success: */ successValue1 = (argumentCountOf(foo->newMethod)) == foo->argumentCount; foo->successFlag = successValue1 && foo->successFlag; } if (foo->successFlag) { executeNewMethodFromCache(); foo->successFlag = 1; } else { /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->messageSelector); foo->stackPointer = sp1; /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), argumentArray); foo->stackPointer = sp2; foo->messageSelector = performSelector; foo->newMethod = performMethod; foo->argumentCount = performArgCount; } } sqInt primitivePerformInSuperclass(void) { register struct foo * foo = &fum; sqInt currentClass; sqInt rcvr; sqInt lookupClass; sqInt sp; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt top; sqInt oop; lookupClass = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; currentClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currentClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; oop2 = longAt((oop + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currentClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; while (currentClass != lookupClass) { currentClass = longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); if (currentClass == foo->nilObj) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; primitivePerformAt(lookupClass); if (!(foo->successFlag)) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), lookupClass); foo->stackPointer = sp; } } sqInt primitivePerformWithArgs(void) { register struct foo * foo = &fum; sqInt rcvr; sqInt lookupClass; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; rcvr = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; lookupClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { lookupClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); lookupClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; primitivePerformAt(lookupClass); } /* Answer a string corresponding to the version of the external platform source code, typically written in C and managed separately for each platform. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitivePlatformSourceVersion(void) { register struct foo * foo = &fum; void * p; sqInt versionString; sqInt len; sqInt sp; # ifdef PLATFORM_SOURCE_VERSION // version level of platform support code len = strlen(PLATFORM_SOURCE_VERSION); versionString = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), len); /* begin arrayValueOf: */ if ((!((versionString & 1))) && (((versionString & 1) == 0) && (isWordsOrBytesNonInt(versionString)))) { p = pointerForOop(versionString + (BASE_HEADER_SIZE)); goto l1; } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end arrayValueOf: */; strncpy(p, PLATFORM_SOURCE_VERSION, len); # else /* begin primitiveFail */ foo->successFlag = 0; return null; # endif // PLATFORM_SOURCE_VERSION /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), versionString); foo->stackPointer = sp; } sqInt primitivePushFalse(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp; } sqInt primitivePushMinusOne(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ConstMinusOne); foo->stackPointer = sp; } sqInt primitivePushNil(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; } sqInt primitivePushOne(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ConstOne); foo->stackPointer = sp; } /* no-op, really... thisReceiver := self popStack. self push: thisReceiver */ sqInt primitivePushSelf(void) { } sqInt primitivePushTrue(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } sqInt primitivePushTwo(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ConstTwo); foo->stackPointer = sp; } sqInt primitivePushZero(void) { register struct foo * foo = &fum; sqInt top; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ConstZero); foo->stackPointer = sp; } sqInt primitiveQuit(void) { ioExit(); } /* Rounds negative results towards zero. */ sqInt primitiveQuo(void) { register struct foo * foo = &fum; sqInt integerArg; sqInt integerResult; sqInt integerRcvr; sqInt integerPointer; sqInt integerPointer1; sqInt sp; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerRcvr = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerRcvr = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerArg = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArg = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin success: */ foo->successFlag = (integerArg != 0) && foo->successFlag; if (foo->successFlag) { if (integerRcvr > 0) { if (integerArg > 0) { integerResult = integerRcvr / integerArg; } else { integerResult = 0 - (integerRcvr / (0 - integerArg)); } } else { if (integerArg > 0) { integerResult = 0 - ((0 - integerRcvr) / integerArg); } else { integerResult = (0 - integerRcvr) / (0 - integerArg); } } } /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerResult << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } /* Relinquish the processor for up to the given number of microseconds. The exact behavior of this primitive is platform dependent. */ sqInt primitiveRelinquishProcessor(void) { register struct foo * foo = &fum; sqInt microSecs; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { microSecs = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; microSecs = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { ioRelinquishProcessorForMicroseconds(microSecs); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* NB: tpr removed the timer checks here and moved them to the primitiveExternalCall method. We make the possibly unwarranted assumption that numbered prims are quick and external prims are slow. */ sqInt primitiveResponse(void) { register struct foo * foo = &fum; sqInt delta; sqInt primIdx; sqInt nArgs; if (DoBalanceChecks) { /* check stack balance */ nArgs = foo->argumentCount; delta = foo->stackPointer - foo->activeContext; } primIdx = foo->primitiveIndex; /* self dispatchOn: primitiveIndex in: primitiveTable. */ foo->successFlag = 1; dispatchFunctionPointerOnin(primIdx, primitiveTable); if (DoBalanceChecks) { if (!(balancedStackafterPrimitivewithArgs(delta, primIdx, nArgs))) { printUnbalancedStack(primIdx); } } /* clear out primIndex so VM knows we're no longer in primitive */ foo->primitiveIndex = 0; return foo->successFlag; } /* put this process on the scheduler's lists thus allowing it to proceed next time there is a chance for processes of it's priority level */ sqInt primitiveResume(void) { register struct foo * foo = &fum; sqInt proc; /* rcvr */ /* self success: ((self fetchClassOf: proc) = (self splObj: ClassProcess)). */ proc = longAt(foo->stackPointer); if (foo->successFlag) { resume(proc); } } /* Primitive. Answer a copy (snapshot) element of the root table. The primitive can cause GC itself and if so the return value may be inaccurate - in this case one should guard the read operation by looking at the gc counter statistics. */ EXPORT(sqInt) primitiveRootTable(void) { register struct foo * foo = &fum; sqInt oop; sqInt sz; sqInt i; sqInt valuePointer; sqInt sp; sz = foo->rootTableCount; /* can cause GC */ oop = instantiateClassindexableSize(splObj(ClassArray), sz); if (sz > foo->rootTableCount) { sz = foo->rootTableCount; } for (i = 1; i <= sz; i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = foo->rootTable[i]; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, valuePointer); } longAtput((oop + (BASE_HEADER_SIZE)) + ((i - 1) << (SHIFT_FOR_WORD)), valuePointer); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), oop); foo->stackPointer = sp; } /* Primitive. Answer the nth element of the root table. This primitive avoids the creation of an extra array; it is intended for enumerations of the form: index := 1. [root := Smalltalk rootTableAt: index. root == nil] whileFalse:[index := index + 1]. */ EXPORT(sqInt) primitiveRootTableAt(void) { register struct foo * foo = &fum; sqInt index; sqInt successValue; sqInt sp; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin success: */ successValue = (index > 0) && (index <= foo->rootTableCount); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->rootTable[index]); foo->stackPointer = sp; } } /* The character scanner primitive. */ sqInt primitiveScanCharacters(void) { register struct foo * foo = &fum; sqInt ascii; sqInt stopReason; sqInt nextDestX; sqInt scanStartIndex; sqInt nilOop; sqInt scanMap; sqInt scanStopIndex; sqInt scanDestX; sqInt sourceX; sqInt scanLastIndex; sqInt kernDelta; sqInt rcvr; sqInt stops; sqInt maxGlyph; sqInt sourceX2; sqInt scanRightX; sqInt scanXTable; sqInt glyphIndex; sqInt sourceString; sqInt sp; sqInt object; sqInt sp1; sqInt integerPointer; sqInt oop; sqInt integerPointer1; sqInt oop1; sqInt integerPointer2; sqInt integerPointer3; sqInt oop2; sqInt object1; sqInt sp2; if (!(foo->argumentCount == 6)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { kernDelta = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; kernDelta = 0; goto l1; } kernDelta = null; l1: /* end stackIntegerValue: */; /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; stops = null; goto l2; } stops = oop; l2: /* end stackObjectValue: */; if (!(((stops & 1) == 0) && (((((usqInt) (longAt(stops))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!((slotSizeOf(stops)) >= 258)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { scanRightX = (integerPointer1 >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; scanRightX = 0; goto l3; } scanRightX = null; l3: /* end stackIntegerValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; sourceString = null; goto l4; } sourceString = oop1; l4: /* end stackObjectValue: */; if (!(((sourceString & 1) == 0) && (((((usqInt) (longAt(sourceString))) >> 8) & 15) >= 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer2 = longAt(foo->stackPointer - (4 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer2 & 1)) { scanStopIndex = (integerPointer2 >> 1); goto l5; } else { /* begin primitiveFail */ foo->successFlag = 0; scanStopIndex = 0; goto l5; } scanStopIndex = null; l5: /* end stackIntegerValue: */; /* begin stackIntegerValue: */ integerPointer3 = longAt(foo->stackPointer - (5 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer3 & 1)) { scanStartIndex = (integerPointer3 >> 1); goto l6; } else { /* begin primitiveFail */ foo->successFlag = 0; scanStartIndex = 0; goto l6; } scanStartIndex = null; l6: /* end stackIntegerValue: */; if (!((scanStartIndex > 0) && ((scanStopIndex > 0) && (scanStopIndex <= (byteSizeOf(sourceString)))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop2 = longAt(foo->stackPointer - (6 * (BYTES_PER_WORD))); if ((oop2 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l7; } rcvr = oop2; l7: /* end stackObjectValue: */; if (!((((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4)) && ((slotSizeOf(rcvr)) >= 4))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } scanDestX = fetchIntegerofObject(0, rcvr); scanLastIndex = fetchIntegerofObject(1, rcvr); scanXTable = longAt((rcvr + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD))); scanMap = longAt((rcvr + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD))); if (!((((scanXTable & 1) == 0) && (((((usqInt) (longAt(scanXTable))) >> 8) & 15) == 2)) && (((scanMap & 1) == 0) && (((((usqInt) (longAt(scanMap))) >> 8) & 15) == 2)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!((slotSizeOf(scanMap)) == 256)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!(foo->successFlag)) { return null; } /* Okay, here we go. We have eliminated nearly all failure conditions, to optimize the inner fetches. */ maxGlyph = (slotSizeOf(scanXTable)) - 2; scanLastIndex = scanStartIndex; nilOop = foo->nilObj; while (scanLastIndex <= scanStopIndex) { /* Known to be okay since scanStartIndex > 0 and scanStopIndex <= sourceString size */ /* Known to be okay since stops size >= 258 */ ascii = byteAt((sourceString + (BASE_HEADER_SIZE)) + (scanLastIndex - 1)); if (!((stopReason = longAt((stops + (BASE_HEADER_SIZE)) + (ascii << (SHIFT_FOR_WORD)))) == nilOop)) { if (!( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 )) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), ((scanDestX << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanLastIndex)) ^ ((((int) scanLastIndex)) << 1)) >= 0) # else ((scanLastIndex >= -1073741824) && (scanLastIndex <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), ((scanLastIndex << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin pop: */ foo->stackPointer -= 7 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), stopReason); foo->stackPointer = sp; return null; } /* fail if the glyphIndex is out of range */ glyphIndex = fetchIntegerofObject(ascii, scanMap); if ((!foo->successFlag) || ((glyphIndex < 0) || (glyphIndex > maxGlyph))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } sourceX = fetchIntegerofObject(glyphIndex, scanXTable); /* Above may fail if non-integer entries in scanXTable */ sourceX2 = fetchIntegerofObject(glyphIndex + 1, scanXTable); if (!foo->successFlag) { return null; } nextDestX = (scanDestX + sourceX2) - sourceX; if (nextDestX > scanRightX) { if (!( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 )) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), ((scanDestX << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanLastIndex)) ^ ((((int) scanLastIndex)) << 1)) >= 0) # else ((scanLastIndex >= -1073741824) && (scanLastIndex <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), ((scanLastIndex << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin pop: */ foo->stackPointer -= 7 * (BYTES_PER_WORD); /* begin push: */ object = longAt((stops + (BASE_HEADER_SIZE)) + ((CrossedX - 1) << (SHIFT_FOR_WORD))); longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp1; return null; } scanDestX = nextDestX + kernDelta; scanLastIndex += 1; } if (!( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 )) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanDestX)) ^ ((((int) scanDestX)) << 1)) >= 0) # else ((scanDestX >= -1073741824) && (scanDestX <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), ((scanDestX << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) scanStopIndex)) ^ ((((int) scanStopIndex)) << 1)) >= 0) # else ((scanStopIndex >= -1073741824) && (scanStopIndex <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((rcvr + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), ((scanStopIndex << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } /* begin pop: */ foo->stackPointer -= 7 * (BYTES_PER_WORD); /* begin push: */ object1 = longAt((stops + (BASE_HEADER_SIZE)) + ((EndOfRun - 1) << (SHIFT_FOR_WORD))); longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), object1); foo->stackPointer = sp2; return null; } /* Return a SmallInteger indicating the current depth of the OS screen. Negative values are used to imply LSB type pixel format an there is some support in the VM for handling either MSB or LSB */ EXPORT(sqInt) primitiveScreenDepth(void) { register struct foo * foo = &fum; sqInt depth; sqInt sp; depth = ioScreenDepth(); if (!foo->successFlag) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((depth << 1) | 1)); foo->stackPointer = sp; } /* Return a point indicating the current size of the Smalltalk window. Currently there is a limit of 65535 in each direction because the point is encoded into a single 32bit value in the image header. This might well become a problem one day */ sqInt primitiveScreenSize(void) { register struct foo * foo = &fum; sqInt pointWord; sqInt object; sqInt sp; sqInt pointResult; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); pointWord = ioScreenSize(); /* begin push: */ /* begin makePointwithxValue:yValue: */ pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((((usqInt) pointWord) >> 16) & 65535) << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), (((pointWord & 65535) << 1) | 1)); object = pointResult; longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } /* Return the number of seconds since January 1, 1901 as an integer. */ sqInt primitiveSecondsClock(void) { register struct foo * foo = &fum; sqInt oop; sqInt sp; /* begin pop:thenPush: */ oop = positive32BitIntegerFor(ioSeconds()); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* Set to OS to the requested display mode. See also DisplayScreen setDisplayDepth:extent:fullscreen: */ sqInt primitiveSetDisplayMode(void) { register struct foo * foo = &fum; sqInt okay; sqInt fsFlag; sqInt d; sqInt h; sqInt w; sqInt sp; sqInt sp1; sqInt integerPointer; sqInt integerPointer1; sqInt integerPointer2; /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { fsFlag = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { fsFlag = 0; goto l1; } foo->successFlag = 0; fsFlag = null; l1: /* end booleanValueOf: */; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { h = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; h = 0; goto l2; } h = null; l2: /* end stackIntegerValue: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { w = (integerPointer1 >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; w = 0; goto l3; } w = null; l3: /* end stackIntegerValue: */; /* begin stackIntegerValue: */ integerPointer2 = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer2 & 1)) { d = (integerPointer2 >> 1); goto l4; } else { /* begin primitiveFail */ foo->successFlag = 0; d = 0; goto l4; } d = null; l4: /* end stackIntegerValue: */; if (foo->successFlag) { okay = ioSetDisplayMode(w, h, d, fsFlag); } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 5 * (BYTES_PER_WORD); /* begin pushBool: */ if (okay) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* On platforms that support it, set full-screen mode to the value of the boolean argument. */ sqInt primitiveSetFullScreen(void) { register struct foo * foo = &fum; sqInt argOop; argOop = longAt(foo->stackPointer); if (argOop == foo->trueObj) { ioSetFullScreen(1); } else { if (argOop == foo->falseObj) { ioSetFullScreen(0); } else { /* begin primitiveFail */ foo->successFlag = 0; } } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Primitive. Indicate if the GC logic should have bias to grow */ EXPORT(sqInt) primitiveSetGCBiasToGrow(void) { register struct foo * foo = &fum; sqInt flag; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { flag = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; flag = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { foo->gcBiasToGrow = flag; /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } } /* Primitive. If the GC logic has bias to grow, set growth limit */ EXPORT(sqInt) primitiveSetGCBiasToGrowGCLimit(void) { register struct foo * foo = &fum; sqInt value; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { value = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; value = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { foo->gcBiasToGrowGCLimit = value; foo->gcBiasToGrowThreshold = foo->youngStart - (((int) memory)); /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } } /* Primitive. Indicate the semaphore to be signalled for upon garbage collection */ EXPORT(sqInt) primitiveSetGCSemaphore(void) { register struct foo * foo = &fum; sqInt index; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { foo->gcSemaphoreIndex = index; /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } } /* Set the user interrupt keycode. The keycode is an integer whose encoding is described in the comment for primitiveKbdNext. */ sqInt primitiveSetInterruptKey(void) { register struct foo * foo = &fum; sqInt keycode; sqInt integerPointer; sqInt top; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { keycode = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; keycode = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { foo->interruptKeycode = keycode; } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Treat the receiver, which can be indexible by either bytes or words, as an array of signed 16-bit values. Return the contents of the given index. Note that the index specifies the i-th 16-bit entry, not the i-th byte or word. */ sqInt primitiveShortAt(void) { register struct foo * foo = &fum; sqInt sz; sqInt value; sqInt rcvr; sqInt index; sqInt addr; sqInt sp; sqInt integerPointer; sqInt successValue; sqInt successValue1; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue = (!((rcvr & 1))) && (((rcvr & 1) == 0) && (isWordsOrBytesNonInt(rcvr))); foo->successFlag = successValue && foo->successFlag; if (!(foo->successFlag)) { return null; } /* number of 16-bit fields */ sz = ((sqInt) ((sizeBitsOf(rcvr)) - (BASE_HEADER_SIZE)) >> 1); /* begin success: */ successValue1 = (index >= 1) && (index <= sz); foo->successFlag = successValue1 && foo->successFlag; if (foo->successFlag) { addr = (rcvr + (BASE_HEADER_SIZE)) + (2 * (index - 1)); value = shortAt(addr); /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((value << 1) | 1)); foo->stackPointer = sp; } } /* Treat the receiver, which can be indexible by either bytes or words, as an array of signed 16-bit values. Set the contents of the given index to the given value. Note that the index specifies the i-th 16-bit entry, not the i-th byte or word. */ sqInt primitiveShortAtPut(void) { register struct foo * foo = &fum; sqInt sz; sqInt value; sqInt rcvr; sqInt index; sqInt addr; sqInt integerPointer; sqInt integerPointer1; sqInt successValue; sqInt successValue1; sqInt successValue2; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { value = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; value = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { index = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin success: */ successValue = (!((rcvr & 1))) && (((rcvr & 1) == 0) && (isWordsOrBytesNonInt(rcvr))); foo->successFlag = successValue && foo->successFlag; if (!(foo->successFlag)) { return null; } /* number of 16-bit fields */ sz = ((sqInt) ((sizeBitsOf(rcvr)) - (BASE_HEADER_SIZE)) >> 1); /* begin success: */ successValue1 = (index >= 1) && (index <= sz); foo->successFlag = successValue1 && foo->successFlag; /* begin success: */ successValue2 = (value >= -32768) && (value <= 32767); foo->successFlag = successValue2 && foo->successFlag; if (foo->successFlag) { addr = (rcvr + (BASE_HEADER_SIZE)) + (2 * (index - 1)); shortAtput(addr, value); /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); } } /* Force the given rectangular section of the Display to be copied to the screen. */ sqInt primitiveShowDisplayRect(void) { register struct foo * foo = &fum; sqInt right; sqInt bottom; sqInt top; sqInt left; sqInt integerPointer; sqInt integerPointer1; sqInt integerPointer2; sqInt integerPointer3; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { bottom = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; bottom = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { top = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; top = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer2 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer2 & 1)) { right = (integerPointer2 >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; right = 0; goto l3; } l3: /* end checkedIntegerValueOf: */; /* begin stackIntegerValue: */ integerPointer3 = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer3 & 1)) { left = (integerPointer3 >> 1); goto l4; } else { /* begin primitiveFail */ foo->successFlag = 0; left = 0; goto l4; } l4: /* end checkedIntegerValueOf: */; displayBitsOfLeftTopRightBottom(fetchPointerofObject(TheDisplay, foo->specialObjectsOop), left, top, right, bottom); if (foo->successFlag) { ioForceDisplayUpdate(); /* begin pop: */ foo->stackPointer -= 4 * (BYTES_PER_WORD); } } /* synchromously signal the semaphore. This may change the active process as a result */ sqInt primitiveSignal(void) { register struct foo * foo = &fum; sqInt sema; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop; /* rcvr */ sema = longAt(foo->stackPointer); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassSemaphore << (SHIFT_FOR_WORD))); if ((sema & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(sema))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(sema - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { synchronousSignal(sema); } } /* Set the low-water mark for free space. When the free space falls below this level, the new and new: primitives fail and system attempts to allocate space (e.g., to create a method context) cause the low-space semaphore (if one is registered) to be signalled. */ sqInt primitiveSignalAtBytesLeft(void) { register struct foo * foo = &fum; sqInt bytes; sqInt integerPointer; sqInt top; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { bytes = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; bytes = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { foo->lowSpaceThreshold = bytes; } else { foo->lowSpaceThreshold = 0; /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Cause the time semaphore, if one has been registered, to be signalled when the millisecond clock is greater than or equal to the given tick value. A tick value of zero turns off timer interrupts. */ sqInt primitiveSignalAtMilliseconds(void) { register struct foo * foo = &fum; sqInt tick; sqInt sema; sqInt integerPointer; sqInt top; sqInt top1; sqInt oop; sqInt oop1; sqInt valuePointer; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { tick = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; tick = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; sema = top1; if (foo->successFlag) { if ((fetchClassOf(sema)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, sema); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheTimerSemaphore << (SHIFT_FOR_WORD)), sema); foo->nextWakeupTick = tick; } else { /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; valuePointer = foo->nilObj; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (TheTimerSemaphore << (SHIFT_FOR_WORD)), valuePointer); foo->nextWakeupTick = 0; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveSine(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(sin(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } sqInt primitiveSize(void) { register struct foo * foo = &fum; sqInt sz; sqInt rcvr; sqInt oop; sqInt sp; rcvr = longAt(foo->stackPointer); if ((rcvr & 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (((((usqInt) (longAt(rcvr))) >> 8) & 15) < 2) { /* begin primitiveFail */ foo->successFlag = 0; return null; } sz = stSizeOf(rcvr); if (foo->successFlag) { /* begin pop:thenPush: */ oop = positive32BitIntegerFor(sz); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } } /* save a normal snapshot under the same name as it was loaded unless it has been renamed by the last primitiveImageName */ sqInt primitiveSnapshot(void) { return snapshot(0); } /* save an embedded snapshot */ sqInt primitiveSnapshotEmbedded(void) { return snapshot(1); } sqInt primitiveSomeInstance(void) { register struct foo * foo = &fum; sqInt class; sqInt instance; sqInt sp; sqInt thisClass; sqInt thisObj; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt obj; sqInt sz; sqInt header; class = longAt(foo->stackPointer); /* begin initialInstanceOf: */ /* begin firstAccessibleObject */ obj = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { thisObj = obj; goto l4; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l3; } else { sz = header & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } error("heap is empty"); l4: /* end firstAccessibleObject */; while (!(thisObj == null)) { /* begin fetchClassOf: */ if ((thisObj & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; thisClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(thisObj))) >> 12) & 31; if (ccIndex == 0) { thisClass = (longAt(thisObj - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); thisClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; if (thisClass == class) { instance = thisObj; goto l1; } thisObj = accessibleObjectAfter(thisObj); } instance = foo->nilObj; l1: /* end initialInstanceOf: */; if (instance == foo->nilObj) { /* begin primitiveFail */ foo->successFlag = 0; } else { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), instance); foo->stackPointer = sp; } } /* Return the first object in the heap. */ sqInt primitiveSomeObject(void) { register struct foo * foo = &fum; sqInt object; sqInt sp; sqInt obj; sqInt sz; sqInt header; /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin push: */ /* begin firstAccessibleObject */ obj = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { object = obj; goto l2; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } error("heap is empty"); l2: /* end firstAccessibleObject */; longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } /* Return the oop of the SpecialObjectsArray. */ sqInt primitiveSpecialObjectsOop(void) { register struct foo * foo = &fum; sqInt sp; /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), foo->specialObjectsOop); foo->stackPointer = sp; } sqInt primitiveSquareRoot(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); /* begin success: */ foo->successFlag = (rcvr >= 0.0) && foo->successFlag; if (foo->successFlag) { pushFloat(sqrt(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* This primitive is called from Squeak as... <imageSegment> storeSegmentFor: arrayOfRoots into: aWordArray outPointers: anArray. */ /* This primitive will store a binary image segment (in the same format as the Squeak image file) of the receiver and every object in its proper tree of subParts (ie, that is not refered to from anywhere else outside the tree). All pointers from within the tree to objects outside the tree will be copied into the array of outpointers. In their place in the image segment will be an oop equal to the offset in the outPointer array (the first would be 4). but with the high bit set. */ /* The primitive expects the array and wordArray to be more than adequately long. In this case it returns normally, and truncates the two arrays to exactly the right size. To simplify truncation, both incoming arrays are required to be 256 bytes or more long (ie with 3-word headers). If either array is too small, the primitive will fail, but in no other case. During operation of the primitive, it is necessary to convert from both internal and external oops to their mapped values. To make this fast, the headers of the original objects in question are replaced by the mapped values (and this is noted by adding the forbidden XX header type). Tables are kept of both kinds of oops, as well as of the original headers for restoration. To be specific, there are two similar two-part tables, the outpointer array, and one in the upper fifth of the segmentWordArray. Each grows oops from the bottom up, and preserved headers from halfway up. In case of either success or failure, the headers must be restored. In the event of primitive failure, the table of outpointers must also be nilled out (since the garbage in the high half will not have been discarded. */ sqInt primitiveStoreImageSegment(void) { register struct foo * foo = &fum; usqInt hdrBaseOut; sqInt mapOop; usqInt segOop; sqInt versionOffset; usqInt savedYoungStart; sqInt hdrTypeBits; usqInt lastPtr; sqInt segmentWordArray; usqInt lastIn; usqInt firstIn; sqInt doingClass; sqInt header; sqInt fieldOop; usqInt fieldPtr; usqInt lastOut; usqInt hdrBaseIn; sqInt extraSize; usqInt lastSeg; sqInt outPointerArray; usqInt endSeg; usqInt firstOut; sqInt arrayOfRoots; sqInt i; sqInt lastAddr; sqInt i1; sqInt lastAddr1; sqInt i2; sqInt lastAddr2; sqInt sz; sqInt i3; sqInt lastAddr3; sqInt in; sqInt lastIn1; sqInt out; sqInt in1; sqInt lastIn2; sqInt out1; sqInt header1; outPointerArray = longAt(foo->stackPointer); segmentWordArray = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* Essential type checks */ arrayOfRoots = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if (!((((((usqInt) (longAt(arrayOfRoots))) >> 8) & 15) == 2) && ((((((usqInt) (longAt(outPointerArray))) >> 8) & 15) == 2) && (((((usqInt) (longAt(segmentWordArray))) >> 8) & 15) == 6)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!((((longAt(outPointerArray)) & TypeMask) == HeaderTypeSizeAndClass) && (((longAt(segmentWordArray)) & TypeMask) == HeaderTypeSizeAndClass))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (DoAssertionChecks) { verifyCleanHeaders(); } firstOut = outPointerArray + (BASE_HEADER_SIZE); lastOut = firstOut - (BYTES_PER_WORD); /* top half */ hdrBaseOut = outPointerArray + (((lastPointerOf(outPointerArray)) / ((BYTES_PER_WORD) * 2)) * (BYTES_PER_WORD)); lastSeg = segmentWordArray; /* Write a version number for byte order and version check */ endSeg = (segmentWordArray + (sizeBitsOf(segmentWordArray))) - (BYTES_PER_WORD); versionOffset = BYTES_PER_WORD; lastSeg += versionOffset; if (lastSeg > endSeg) { /* begin primitiveFail */ foo->successFlag = 0; return null; } longAtput(lastSeg, imageSegmentVersion()); /* Take 1/8 of seg */ firstIn = endSeg - (((sizeBitsOf(segmentWordArray)) / ((BYTES_PER_WORD) * 8)) * (BYTES_PER_WORD)); lastIn = firstIn - (BYTES_PER_WORD); /* top half of that */ /* First mark the rootArray and all root objects. */ hdrBaseIn = firstIn + (((sizeBitsOf(segmentWordArray)) / ((BYTES_PER_WORD) * 16)) * (BYTES_PER_WORD)); longAtput(arrayOfRoots, (longAt(arrayOfRoots)) | (MARK_BIT)); lastPtr = arrayOfRoots + (lastPointerOf(arrayOfRoots)); fieldPtr = arrayOfRoots + (BASE_HEADER_SIZE); while (fieldPtr <= lastPtr) { fieldOop = longAt(fieldPtr); if (!((fieldOop & 1))) { longAtput(fieldOop, (longAt(fieldOop)) | (MARK_BIT)); } fieldPtr += BYTES_PER_WORD; } savedYoungStart = foo->youngStart; /* process all of memory */ /* clear the recycled context lists */ foo->youngStart = memory; foo->freeContexts = NilContext; foo->freeLargeContexts = NilContext; markAndTraceInterpreterOops(); /* Finally unmark the rootArray and all root objects. */ foo->youngStart = savedYoungStart; longAtput(arrayOfRoots, (longAt(arrayOfRoots)) & (ALL_BUT_MARK_BIT)); fieldPtr = arrayOfRoots + (BASE_HEADER_SIZE); while (fieldPtr <= lastPtr) { fieldOop = longAt(fieldPtr); if (!((fieldOop & 1))) { longAtput(fieldOop, (longAt(fieldOop)) & (ALL_BUT_MARK_BIT)); } fieldPtr += BYTES_PER_WORD; } lastIn += BYTES_PER_WORD; if (lastIn >= hdrBaseIn) { foo->successFlag = 0; } lastSeg = copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(arrayOfRoots, segmentWordArray, lastSeg, firstIn, lastIn, hdrBaseIn + (lastIn - firstIn)); if (!(foo->successFlag)) { lastIn -= BYTES_PER_WORD; restoreHeadersFromtofromandtofrom(firstIn, lastIn, hdrBaseIn, firstOut, lastOut, hdrBaseOut); /* begin primitiveFailAfterCleanup: */ lastAddr = outPointerArray + (lastPointerOf(outPointerArray)); i = outPointerArray + (BASE_HEADER_SIZE); while (i <= lastAddr) { longAtput(i, foo->nilObj); i += BYTES_PER_WORD; } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } segOop = ((segmentWordArray + versionOffset) + (BASE_HEADER_SIZE)) + (foo->headerTypeBytes[(longAt((segmentWordArray + versionOffset) + (BASE_HEADER_SIZE))) & TypeMask]); while (segOop <= lastSeg) { if (((longAt(segOop)) & TypeMask) <= 1) { /* This object has a class field (type=0 or 1) -- start with that. */ fieldPtr = segOop - (BYTES_PER_WORD); doingClass = 1; } else { /* No class field -- start with first data field */ fieldPtr = segOop + (BASE_HEADER_SIZE); doingClass = 0; } /* last field */ /* Go through all oops, remapping them... */ lastPtr = segOop + (lastPointerOf(segOop)); while (!(fieldPtr > lastPtr)) { /* Examine each pointer field */ fieldOop = longAt(fieldPtr); if (doingClass) { hdrTypeBits = fieldOop & TypeMask; fieldOop -= hdrTypeBits; } if ((fieldOop & 1)) { /* Just an integer -- nothing to do */ fieldPtr += BYTES_PER_WORD; } else { header = longAt(fieldOop); if ((header & TypeMask) == HeaderTypeFree) { /* Has already been forwarded -- this is the link */ mapOop = header & (ALL_BUT_TYPE_MASK); } else { if (((longAt(fieldOop)) & (MARK_BIT)) == 0) { /* Points to an unmarked obj -- an internal pointer. Copy the object into the segment, and forward its oop. */ lastIn += BYTES_PER_WORD; if (lastIn >= hdrBaseIn) { foo->successFlag = 0; } lastSeg = copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(fieldOop, segmentWordArray, lastSeg, firstIn, lastIn, hdrBaseIn + (lastIn - firstIn)); if (!(foo->successFlag)) { /* Out of space in segment */ lastIn -= BYTES_PER_WORD; restoreHeadersFromtofromandtofrom(firstIn, lastIn, hdrBaseIn, firstOut, lastOut, hdrBaseOut); /* begin primitiveFailAfterCleanup: */ lastAddr1 = outPointerArray + (lastPointerOf(outPointerArray)); i1 = outPointerArray + (BASE_HEADER_SIZE); while (i1 <= lastAddr1) { longAtput(i1, foo->nilObj); i1 += BYTES_PER_WORD; } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } mapOop = (longAt(fieldOop)) & (ALL_BUT_TYPE_MASK); } else { /* Points to a marked obj -- an external pointer. Map it as a tagged index in outPointers, and forward its oop. */ lastOut += BYTES_PER_WORD; if (lastOut >= hdrBaseOut) { /* Out of space in outPointerArray */ lastOut -= BYTES_PER_WORD; restoreHeadersFromtofromandtofrom(firstIn, lastIn, hdrBaseIn, firstOut, lastOut, hdrBaseOut); /* begin primitiveFailAfterCleanup: */ lastAddr2 = outPointerArray + (lastPointerOf(outPointerArray)); i2 = outPointerArray + (BASE_HEADER_SIZE); while (i2 <= lastAddr2) { longAtput(i2, foo->nilObj); i2 += BYTES_PER_WORD; } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } mapOop = (lastOut - outPointerArray) | 2147483648U; /* begin forward:to:savingOopAt:andHeaderAt: */ longAtput(lastOut, fieldOop); longAtput(hdrBaseOut + (lastOut - firstOut), longAt(fieldOop)); longAtput(fieldOop, mapOop + HeaderTypeFree); } } if (doingClass) { longAtput(fieldPtr, mapOop + hdrTypeBits); fieldPtr += (BYTES_PER_WORD) * 2; doingClass = 0; } else { longAtput(fieldPtr, mapOop); fieldPtr += BYTES_PER_WORD; } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) segOop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(segOop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(segOop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(segOop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(segOop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } segOop = (segOop + sz) + (foo->headerTypeBytes[(longAt(segOop + sz)) & TypeMask]); } restoreHeadersFromtofromandtofrom(firstIn, lastIn, hdrBaseIn, firstOut, lastOut, hdrBaseOut); if ((((outPointerArray + (lastPointerOf(outPointerArray))) - lastOut) < 12) || ((endSeg - lastSeg) < 12)) { /* begin primitiveFailAfterCleanup: */ lastAddr3 = outPointerArray + (lastPointerOf(outPointerArray)); i3 = outPointerArray + (BASE_HEADER_SIZE); while (i3 <= lastAddr3) { longAtput(i3, foo->nilObj); i3 += BYTES_PER_WORD; } if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin primitiveFail */ foo->successFlag = 0; return null; } extraSize = foo->headerTypeBytes[(longAt(segmentWordArray)) & TypeMask]; /* Copy the 3-word wordArray header to establish a free chunk. */ hdrTypeBits = (longAt(segmentWordArray)) & TypeMask; /* begin transfer:from:to: */ flag("Dan"); in = (segmentWordArray - extraSize) - (BYTES_PER_WORD); lastIn1 = in + (3 * (BYTES_PER_WORD)); out = (lastOut + (BYTES_PER_WORD)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn1))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } longAtput(lastOut + (BYTES_PER_WORD), (((outPointerArray + (lastPointerOf(outPointerArray))) - lastOut) - extraSize) + hdrTypeBits); longAtput(outPointerArray - extraSize, ((lastOut - firstOut) + ((BYTES_PER_WORD) * 2)) + hdrTypeBits); beRootIfOld(outPointerArray); /* begin transfer:from:to: */ flag("Dan"); in1 = (segmentWordArray - extraSize) - (BYTES_PER_WORD); lastIn2 = in1 + (3 * (BYTES_PER_WORD)); out1 = (lastSeg + (BYTES_PER_WORD)) - (BYTES_PER_WORD); while ((((usqInt) in1)) < (((usqInt) lastIn2))) { longAtput(out1 += BYTES_PER_WORD, longAt(in1 += BYTES_PER_WORD)); } longAtput(segmentWordArray - extraSize, ((lastSeg - segmentWordArray) + (BASE_HEADER_SIZE)) + hdrTypeBits); longAtput(lastSeg + (BYTES_PER_WORD), ((endSeg - lastSeg) - extraSize) + hdrTypeBits); if (DoAssertionChecks) { verifyCleanHeaders(); } /* begin pop: */ foo->stackPointer -= 3 * (BYTES_PER_WORD); } /* Atomic store into context stackPointer. Also ensures that any newly accessible cells are initialized to nil */ sqInt primitiveStoreStackp(void) { register struct foo * foo = &fum; sqInt stackp; sqInt i; sqInt newStackp; sqInt ctxt; sqInt integerPointer; sqInt successValue; sqInt valuePointer; sqInt otherOop; sqInt sp; ctxt = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { newStackp = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; newStackp = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin success: */ foo->successFlag = ((((usqInt) newStackp)) >= (((usqInt) 0))) && foo->successFlag; /* begin success: */ /* begin oop:isLessThanOrEqualTo: */ otherOop = (((LARGE_CONTEXT_SIZE) - (BASE_HEADER_SIZE)) / (BYTES_PER_WORD)) - CtxtTempFrameStart; successValue = (((usqInt) newStackp)) <= (((usqInt) otherOop)); foo->successFlag = successValue && foo->successFlag; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchStackPointerOf: */ sp = longAt((ctxt + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { stackp = 0; goto l2; } stackp = (sp >> 1); l2: /* end fetchStackPointerOf: */; if ((((usqInt) newStackp)) > (((usqInt) stackp))) { for (i = (stackp + 1); i <= newStackp; i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = foo->nilObj; if ((((usqInt) ctxt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(ctxt, valuePointer); } longAtput((ctxt + (BASE_HEADER_SIZE)) + (((i + CtxtTempFrameStart) - 1) << (SHIFT_FOR_WORD)), valuePointer); } } /* begin storeStackPointerValue:inContext: */ longAtput((ctxt + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((newStackp << 1) | 1)); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } sqInt primitiveStringAt(void) { commonAt(1); } sqInt primitiveStringAtPut(void) { commonAtPut(1); } /* <array> primReplaceFrom: start to: stop with: replacement startingAt: repStart <primitive: 105> */ sqInt primitiveStringReplace(void) { register struct foo * foo = &fum; sqInt stop; sqInt start; sqInt totalLength; sqInt srcIndex; sqInt i; sqInt arrayInstSize; sqInt replInstSize; sqInt hdr; sqInt replFmt; sqInt array; sqInt replStart; sqInt repl; sqInt arrayFmt; sqInt valuePointer; sqInt valueWord; sqInt integerPointer; sqInt integerPointer1; sqInt integerPointer2; sqInt sz; sqInt sz1; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; sqInt classFormat1; sqInt class1; sqInt ccIndex1; sqInt oop11; sqInt oop21; sqInt oop31; array = longAt(foo->stackPointer - (4 * (BYTES_PER_WORD))); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { start = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; start = 0; goto l1; } start = null; l1: /* end stackIntegerValue: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { stop = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; stop = 0; goto l2; } stop = null; l2: /* end stackIntegerValue: */; repl = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin stackIntegerValue: */ integerPointer2 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer2 & 1)) { replStart = (integerPointer2 >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; replStart = 0; goto l3; } replStart = null; l3: /* end stackIntegerValue: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((repl & 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } hdr = longAt(array); arrayFmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(array - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (arrayFmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l4; } if (arrayFmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l4; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (arrayFmt & 3); goto l4; } l4: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((arrayFmt > 4) || (arrayFmt == 2)) { arrayInstSize = 0; goto l7; } if (arrayFmt < 2) { arrayInstSize = totalLength; goto l7; } /* begin fetchClassOf: */ if ((array & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l6; } ccIndex = (((usqInt) (longAt(array))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(array - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l6; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l6; } l6: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; arrayInstSize = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l7: /* end fixedFieldsOf:format:length: */; if (!((start >= 1) && (((start - 1) <= stop) && ((stop + arrayInstSize) <= totalLength)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } hdr = longAt(repl); replFmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(repl - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = hdr & (SIZE_MASK); } sz1 -= hdr & (SIZE_4_BIT); if (replFmt <= 4) { totalLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l5; } if (replFmt < 8) { totalLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l5; } else { totalLength = (sz1 - (BASE_HEADER_SIZE)) - (replFmt & 3); goto l5; } l5: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((replFmt > 4) || (replFmt == 2)) { replInstSize = 0; goto l9; } if (replFmt < 2) { replInstSize = totalLength; goto l9; } /* begin fetchClassOf: */ if ((repl & 1)) { /* begin fetchPointer:ofObject: */ oop11 = foo->specialObjectsOop; class1 = longAt((oop11 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l8; } ccIndex1 = (((usqInt) (longAt(repl))) >> 12) & 31; if (ccIndex1 == 0) { class1 = (longAt(repl - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l8; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop31 = foo->specialObjectsOop; oop21 = longAt((oop31 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class1 = longAt((oop21 + (BASE_HEADER_SIZE)) + ((ccIndex1 - 1) << (SHIFT_FOR_WORD))); goto l8; } l8: /* end fetchClassOf: */; classFormat1 = (longAt((class1 + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; replInstSize = (((((usqInt) classFormat1) >> 11) & 192) + ((((usqInt) classFormat1) >> 2) & 63)) - 1; l9: /* end fixedFieldsOf:format:length: */; if (!((replStart >= 1) && ((((stop - start) + replStart) + replInstSize) <= totalLength))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (arrayFmt < 8) { if (!(arrayFmt == replFmt)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } else { if (!((arrayFmt & 12) == (replFmt & 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } /* - 1 for 0-based access */ srcIndex = (replStart + replInstSize) - 1; if (arrayFmt <= 4) { for (i = ((start + arrayInstSize) - 1); i <= ((stop + arrayInstSize) - 1); i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = longAt((repl + (BASE_HEADER_SIZE)) + (srcIndex << (SHIFT_FOR_WORD))); if ((((usqInt) array)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(array, valuePointer); } longAtput((array + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); srcIndex += 1; } } else { if (arrayFmt < 8) { for (i = ((start + arrayInstSize) - 1); i <= ((stop + arrayInstSize) - 1); i += 1) { /* begin storeLong32:ofObject:withValue: */ valueWord = long32At((repl + (BASE_HEADER_SIZE)) + (srcIndex << 2)); long32Atput((array + (BASE_HEADER_SIZE)) + (i << 2), valueWord); srcIndex += 1; } } else { for (i = ((start + arrayInstSize) - 1); i <= ((stop + arrayInstSize) - 1); i += 1) { byteAtput((array + (BASE_HEADER_SIZE)) + i, byteAt((repl + (BASE_HEADER_SIZE)) + srcIndex)); srcIndex += 1; } } } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } sqInt primitiveSubtract(void) { register struct foo * foo = &fum; sqInt integerResult; sqInt sp; /* begin pop2AndPushIntegerIfOK: */ integerResult = (stackIntegerValue(1)) - (stackIntegerValue(0)); if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerResult << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } sqInt primitiveSuspend(void) { register struct foo * foo = &fum; sqInt activeProc; sqInt sp; sqInt oop; sqInt oop1; sqInt oop2; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin success: */ foo->successFlag = ((longAt(foo->stackPointer)) == activeProc) && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp; transferTo(wakeHighestPriority()); } } /* Primitive. Terminate up the context stack from the receiver up to but not including the argument, if previousContext is on my Context stack. Make previousContext my sender. This prim has to shadow the code in ContextPart>terminateTo: to be correct */ sqInt primitiveTerminateTo(void) { register struct foo * foo = &fum; sqInt nilOop; sqInt thisCntx; sqInt aContext; sqInt nextCntx; sqInt currentCntx; sqInt top; sqInt top1; sqInt sp; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; aContext = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisCntx = top1; if (contexthasSender(thisCntx, aContext)) { nilOop = foo->nilObj; currentCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); while (!(currentCntx == aContext)) { nextCntx = longAt((currentCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) currentCntx)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(currentCntx, nilOop); } longAtput((currentCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), nilOop); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) currentCntx)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(currentCntx, nilOop); } longAtput((currentCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), nilOop); currentCntx = nextCntx; } } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) thisCntx)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(thisCntx, aContext); } longAtput((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), aContext); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), thisCntx); foo->stackPointer = sp; return null; } /* Return true if the host OS does support the given display depth. */ sqInt primitiveTestDisplayDepth(void) { register struct foo * foo = &fum; sqInt okay; sqInt bitsPerPixel; sqInt sp; sqInt sp1; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { bitsPerPixel = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; bitsPerPixel = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (foo->successFlag) { okay = ioHasDisplayDepth(bitsPerPixel); } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (okay) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveTimesTwoPower(void) { register struct foo * foo = &fum; sqInt arg; double rcvr; sqInt integerPointer; sqInt top; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { arg = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; arg = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; rcvr = popFloat(); if (foo->successFlag) { pushFloat(ldexp(rcvr, arg)); } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveTruncated(void) { register struct foo * foo = &fum; double trunc; double frac; double rcvr; sqInt successValue; sqInt sp; rcvr = popFloat(); if (foo->successFlag) { frac = modf(rcvr, &trunc); flag("Dan"); success((-1073741824.0 <= trunc) && (trunc <= 1073741823.0)); } if (foo->successFlag) { pushInteger((sqInt) trunc); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Primitive. Unload the module with the given name. */ /* Reloading of the module will happen *later* automatically, when a function from it is called. This is ensured by invalidating current sessionID. */ sqInt primitiveUnloadModule(void) { register struct foo * foo = &fum; sqInt moduleName; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } moduleName = longAt(foo->stackPointer); if ((moduleName & 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!(((moduleName & 1) == 0) && (((((usqInt) (longAt(moduleName))) >> 8) & 15) >= 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!(ioUnloadModuleOfLength(oopForPointer(firstIndexableField(moduleName)), byteSizeOf(moduleName)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } flushExternalPrimitives(); /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } /* Answer an array with UTC mocroseconds since the Posix epoch and tthe current seconds offset from GMT in the local time zone. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveUtcWithOffset(void) { register struct foo * foo = &fum; sqInt resultArray; sqLong clock; int offset; sqInt oop; sqInt sp; if ((ioUtcWithOffset(&clock, &offset)) == -1) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pushRemappableOop: */ oop = positive64BitIntegerFor(clock); foo->remapBuffer[foo->remapBufferCount += 1] = oop; resultArray = instantiateClassindexableSize(splObj(ClassArray), 2); stObjectatput(resultArray, 1, popRemappableOop()); stObjectatput(resultArray, 2, ((offset << 1) | 1)); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), resultArray); foo->stackPointer = sp; } /* Behaviour depends on argument count: 0 args: return an Array of VM parameter values; 1 arg: return the indicated VM parameter; 2 args: set the VM indicated parameter. VM parameters are numbered as follows: 1 end of old-space (0-based, read-only) 2 end of young-space (read-only) 3 end of memory (read-only) 4 allocationCount (read-only) 5 allocations between GCs (read-write) 6 survivor count tenuring threshold (read-write) 7 full GCs since startup (read-only) 8 total milliseconds in full GCs since startup (read-only) 9 incremental GCs since startup (read-only) 10 total milliseconds in incremental GCs since startup (read-only) 11 tenures of surving objects since startup (read-only) 12-20 specific to the translating VM 21 root table size (read-only) 22 root table overflows since startup (read-only) 23 bytes of extra memory to reserve for VM buffers, plugins, etc. 24 memory threshold above which shrinking object memory (rw) 25 memory headroom when growing object memory (rw) 26 interruptChecksEveryNms - force an ioProcessEvents every N milliseconds, in case the image is not calling getNextEvent often (rw) 27 number of times mark loop iterated for current IGC/FGC (read-only) includes ALL marking 28 number of times sweep loop iterated for current IGC/FGC (read-only) 29 number of times make forward loop iterated for current IGC/FGC (read-only) 30 number of times compact move loop iterated for current IGC/FGC (read-only) 31 number of grow memory requests (read-only) 32 number of shrink memory requests (read-only) 33 number of root table entries used for current IGC/FGC (read-only) 34 number of allocations done before current IGC/FGC (read-only) 35 number of survivor objects after current IGC/FGC (read-only) 36 millisecond clock when current IGC/FGC completed (read-only) 37 number of marked objects for Roots of the world, not including Root Table entries for current IGC/FGC (read-only) 38 milliseconds taken by current IGC (read-only) 39 Number of finalization signals for Weak Objects pending when current IGC/FGC completed (read-only) 40 BytesPerWord for this image Note: Thanks to Ian Piumarta for this primitive. */ sqInt primitiveVMParameter(void) { register struct foo * foo = &fum; sqInt statIncrGCMSecsObj; sqInt statFullGCMSecsObj; sqInt mem; sqInt arg; sqInt result; sqInt i; sqInt statGCTimeObj; sqInt statIGCDeltaTimeObj; sqLong resultLargePositiveInteger; sqInt paramsArraySize; sqInt index; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; sqInt oop6; sqInt oop7; sqInt oop8; sqInt sp; sqInt sp1; sqInt oop9; sqInt sp2; sqInt sp3; sqInt valuePointer; sqInt valuePointer1; sqInt valuePointer2; sqInt valuePointer3; sqInt valuePointer4; sqInt valuePointer5; sqInt valuePointer6; sqInt valuePointer7; sqInt valuePointer8; sqInt valuePointer9; sqInt valuePointer10; sqInt valuePointer11; sqInt valuePointer12; sqInt valuePointer13; sqInt valuePointer14; sqInt valuePointer15; sqInt valuePointer16; sqInt valuePointer17; sqInt valuePointer18; sqInt valuePointer19; sqInt valuePointer20; sqInt valuePointer21; sqInt valuePointer22; sqInt valuePointer23; sqInt valuePointer24; sqInt valuePointer25; mem = memory; paramsArraySize = 40; if (foo->argumentCount == 0) { result = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), paramsArraySize); /* begin pushRemappableOop: */ foo->remapBuffer[foo->remapBufferCount += 1] = result; /* begin pushRemappableOop: */ oop = positive64BitIntegerFor(foo->statFullGCMSecs); foo->remapBuffer[foo->remapBufferCount += 1] = oop; /* begin pushRemappableOop: */ oop1 = positive64BitIntegerFor(foo->statIncrGCMSecs); foo->remapBuffer[foo->remapBufferCount += 1] = oop1; /* begin pushRemappableOop: */ oop2 = positive64BitIntegerFor(foo->statGCTime); foo->remapBuffer[foo->remapBufferCount += 1] = oop2; /* begin pushRemappableOop: */ oop3 = positive64BitIntegerFor(foo->statIGCDeltaTime); foo->remapBuffer[foo->remapBufferCount += 1] = oop3; /* begin popRemappableOop */ oop4 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; statIGCDeltaTimeObj = oop4; /* begin popRemappableOop */ oop5 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; statGCTimeObj = oop5; /* begin popRemappableOop */ oop6 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; statIncrGCMSecsObj = oop6; /* begin popRemappableOop */ oop7 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; statFullGCMSecsObj = oop7; /* begin popRemappableOop */ oop8 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; result = oop8; for (i = 0; i <= (paramsArraySize - 1); i += 1) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, ConstZero); } longAtput((result + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), ConstZero); } /* begin storePointer:ofObject:withValue: */ valuePointer = (((foo->youngStart - mem) << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer); } longAtput((result + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointer:ofObject:withValue: */ valuePointer1 = (((foo->freeBlock - mem) << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer1); } longAtput((result + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer1); /* begin storePointer:ofObject:withValue: */ valuePointer2 = (((foo->endOfMemory - mem) << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer2); } longAtput((result + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD)), valuePointer2); /* begin storePointer:ofObject:withValue: */ valuePointer3 = ((foo->allocationCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer3); } longAtput((result + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), valuePointer3); /* begin storePointer:ofObject:withValue: */ valuePointer4 = ((foo->allocationsBetweenGCs << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer4); } longAtput((result + (BASE_HEADER_SIZE)) + (4 << (SHIFT_FOR_WORD)), valuePointer4); /* begin storePointer:ofObject:withValue: */ valuePointer5 = ((foo->tenuringThreshold << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer5); } longAtput((result + (BASE_HEADER_SIZE)) + (5 << (SHIFT_FOR_WORD)), valuePointer5); /* begin storePointer:ofObject:withValue: */ valuePointer6 = ((foo->statFullGCs << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer6); } longAtput((result + (BASE_HEADER_SIZE)) + (6 << (SHIFT_FOR_WORD)), valuePointer6); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, statFullGCMSecsObj); } longAtput((result + (BASE_HEADER_SIZE)) + (7 << (SHIFT_FOR_WORD)), statFullGCMSecsObj); /* begin storePointer:ofObject:withValue: */ valuePointer7 = ((foo->statIncrGCs << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer7); } longAtput((result + (BASE_HEADER_SIZE)) + (8 << (SHIFT_FOR_WORD)), valuePointer7); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, statIncrGCMSecsObj); } longAtput((result + (BASE_HEADER_SIZE)) + (9 << (SHIFT_FOR_WORD)), statIncrGCMSecsObj); /* begin storePointer:ofObject:withValue: */ valuePointer8 = ((foo->statTenures << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer8); } longAtput((result + (BASE_HEADER_SIZE)) + (10 << (SHIFT_FOR_WORD)), valuePointer8); /* begin storePointer:ofObject:withValue: */ valuePointer9 = ((foo->rootTableCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer9); } longAtput((result + (BASE_HEADER_SIZE)) + (20 << (SHIFT_FOR_WORD)), valuePointer9); /* begin storePointer:ofObject:withValue: */ valuePointer10 = ((foo->statRootTableOverflows << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer10); } longAtput((result + (BASE_HEADER_SIZE)) + (21 << (SHIFT_FOR_WORD)), valuePointer10); /* begin storePointer:ofObject:withValue: */ valuePointer11 = ((extraVMMemory << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer11); } longAtput((result + (BASE_HEADER_SIZE)) + (22 << (SHIFT_FOR_WORD)), valuePointer11); /* begin storePointer:ofObject:withValue: */ valuePointer12 = ((foo->shrinkThreshold << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer12); } longAtput((result + (BASE_HEADER_SIZE)) + (23 << (SHIFT_FOR_WORD)), valuePointer12); /* begin storePointer:ofObject:withValue: */ valuePointer13 = ((foo->growHeadroom << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer13); } longAtput((result + (BASE_HEADER_SIZE)) + (24 << (SHIFT_FOR_WORD)), valuePointer13); /* begin storePointer:ofObject:withValue: */ valuePointer14 = ((foo->interruptChecksEveryNms << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer14); } longAtput((result + (BASE_HEADER_SIZE)) + (25 << (SHIFT_FOR_WORD)), valuePointer14); /* begin storePointer:ofObject:withValue: */ valuePointer15 = ((foo->statMarkCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer15); } longAtput((result + (BASE_HEADER_SIZE)) + (26 << (SHIFT_FOR_WORD)), valuePointer15); /* begin storePointer:ofObject:withValue: */ valuePointer16 = ((foo->statSweepCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer16); } longAtput((result + (BASE_HEADER_SIZE)) + (27 << (SHIFT_FOR_WORD)), valuePointer16); /* begin storePointer:ofObject:withValue: */ valuePointer17 = ((foo->statMkFwdCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer17); } longAtput((result + (BASE_HEADER_SIZE)) + (28 << (SHIFT_FOR_WORD)), valuePointer17); /* begin storePointer:ofObject:withValue: */ valuePointer18 = ((foo->statCompMoveCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer18); } longAtput((result + (BASE_HEADER_SIZE)) + (29 << (SHIFT_FOR_WORD)), valuePointer18); /* begin storePointer:ofObject:withValue: */ valuePointer19 = ((foo->statGrowMemory << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer19); } longAtput((result + (BASE_HEADER_SIZE)) + (30 << (SHIFT_FOR_WORD)), valuePointer19); /* begin storePointer:ofObject:withValue: */ valuePointer20 = ((foo->statShrinkMemory << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer20); } longAtput((result + (BASE_HEADER_SIZE)) + (31 << (SHIFT_FOR_WORD)), valuePointer20); /* begin storePointer:ofObject:withValue: */ valuePointer21 = ((foo->statRootTableCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer21); } longAtput((result + (BASE_HEADER_SIZE)) + (32 << (SHIFT_FOR_WORD)), valuePointer21); /* begin storePointer:ofObject:withValue: */ valuePointer22 = ((foo->statAllocationCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer22); } longAtput((result + (BASE_HEADER_SIZE)) + (33 << (SHIFT_FOR_WORD)), valuePointer22); /* begin storePointer:ofObject:withValue: */ valuePointer23 = ((foo->statSurvivorCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer23); } longAtput((result + (BASE_HEADER_SIZE)) + (34 << (SHIFT_FOR_WORD)), valuePointer23); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, statGCTimeObj); } longAtput((result + (BASE_HEADER_SIZE)) + (35 << (SHIFT_FOR_WORD)), statGCTimeObj); /* begin storePointer:ofObject:withValue: */ valuePointer24 = ((foo->statSpecialMarkCount << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer24); } longAtput((result + (BASE_HEADER_SIZE)) + (36 << (SHIFT_FOR_WORD)), valuePointer24); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, statIGCDeltaTimeObj); } longAtput((result + (BASE_HEADER_SIZE)) + (37 << (SHIFT_FOR_WORD)), statIGCDeltaTimeObj); /* begin storePointer:ofObject:withValue: */ valuePointer25 = ((foo->statpendingFinalizationSignals << 1) | 1); if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, valuePointer25); } longAtput((result + (BASE_HEADER_SIZE)) + (38 << (SHIFT_FOR_WORD)), valuePointer25); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) result)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(result, (((BYTES_PER_WORD) << 1) | 1)); } longAtput((result + (BASE_HEADER_SIZE)) + (39 << (SHIFT_FOR_WORD)), (((BYTES_PER_WORD) << 1) | 1)); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp; return null; } arg = longAt(foo->stackPointer); if (!((arg & 1))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } arg = (arg >> 1); resultLargePositiveInteger = -1; if (foo->argumentCount == 1) { if ((arg < 1) || (arg > paramsArraySize)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (arg == 1) { result = foo->youngStart - mem; } if (arg == 2) { result = foo->freeBlock - mem; } if (arg == 3) { result = foo->endOfMemory - mem; } if (arg == 4) { result = foo->allocationCount; } if (arg == 5) { result = foo->allocationsBetweenGCs; } if (arg == 6) { result = foo->tenuringThreshold; } if (arg == 7) { result = foo->statFullGCs; } if (arg == 8) { resultLargePositiveInteger = foo->statFullGCMSecs; } if (arg == 9) { result = foo->statIncrGCs; } if (arg == 10) { resultLargePositiveInteger = foo->statIncrGCMSecs; } if (arg == 11) { result = foo->statTenures; } if ((arg >= 12) && (arg <= 20)) { result = 0; } if (arg == 21) { result = foo->rootTableCount; } if (arg == 22) { result = foo->statRootTableOverflows; } if (arg == 23) { result = extraVMMemory; } if (arg == 24) { result = foo->shrinkThreshold; } if (arg == 25) { result = foo->growHeadroom; } if (arg == 26) { result = foo->interruptChecksEveryNms; } if (arg == 27) { result = foo->statMarkCount; } if (arg == 28) { result = foo->statSweepCount; } if (arg == 29) { result = foo->statMkFwdCount; } if (arg == 30) { result = foo->statCompMoveCount; } if (arg == 31) { result = foo->statGrowMemory; } if (arg == 32) { result = foo->statShrinkMemory; } if (arg == 33) { result = foo->statRootTableCount; } if (arg == 34) { result = foo->statAllocationCount; } if (arg == 35) { result = foo->statSurvivorCount; } if (arg == 36) { resultLargePositiveInteger = foo->statGCTime; } if (arg == 37) { result = foo->statSpecialMarkCount; } if (arg == 38) { resultLargePositiveInteger = foo->statIGCDeltaTime; } if (arg == 39) { result = foo->statpendingFinalizationSignals; } if (arg == 40) { result = BYTES_PER_WORD; } if (resultLargePositiveInteger == -1) { /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((result << 1) | 1)); foo->stackPointer = sp1; } else { /* begin pop:thenPush: */ oop9 = positive64BitIntegerFor(resultLargePositiveInteger); longAtput(sp2 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oop9); foo->stackPointer = sp2; } return null; } if (!(foo->argumentCount == 2)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } index = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (!((index & 1))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } index = (index >> 1); if (index <= 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } foo->successFlag = 0; if (index == 5) { result = foo->allocationsBetweenGCs; foo->allocationsBetweenGCs = arg; foo->successFlag = 1; } if (index == 6) { result = foo->tenuringThreshold; foo->tenuringThreshold = arg; foo->successFlag = 1; } if (index == 23) { result = extraVMMemory; extraVMMemory = arg; foo->successFlag = 1; } if (index == 24) { result = foo->shrinkThreshold; if (arg > 0) { foo->shrinkThreshold = arg; foo->successFlag = 1; } } if (index == 25) { result = foo->growHeadroom; if (arg > 0) { foo->growHeadroom = arg; foo->successFlag = 1; } } if (index == 26) { if (arg > 1) { result = foo->interruptChecksEveryNms; foo->interruptChecksEveryNms = arg; foo->successFlag = 1; } } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp3 = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), ((result << 1) | 1)); foo->stackPointer = sp3; return null; } /* begin primitiveFail */ foo->successFlag = 0; } /* Return a string containing the path name of VM's directory. */ sqInt primitiveVMPath(void) { register struct foo * foo = &fum; sqInt sz; sqInt s; sqInt sp; sz = vmPathSize(); s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); vmPathGetLength(s + (BASE_HEADER_SIZE), sz); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), s); foo->stackPointer = sp; } /* Answer a string corresponding to the version of virtual machine. This represents the version level of the Smalltalk source code (interpreter and various plugins) that is translated to C by a CCodeGenerator, in addition to the external platform source code, typically written in C and managed separately for each platform. By convention, this is a string composed of the interpreter source version and the platform source version, e.g. '4.0.2-2172'. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveVMVersion(void) { register struct foo * foo = &fum; void * p; sqInt versionString; sqInt len; sqInt sp; # ifdef VM_VERSION // version level of interpreter plus platform support code len = strlen(VM_VERSION); versionString = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), len); /* begin arrayValueOf: */ if ((!((versionString & 1))) && (((versionString & 1) == 0) && (isWordsOrBytesNonInt(versionString)))) { p = pointerForOop(versionString + (BASE_HEADER_SIZE)); goto l1; } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end arrayValueOf: */; strncpy(p, VM_VERSION, len); # else /* begin primitiveFail */ foo->successFlag = 0; return null; # endif // VM_VERSION /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), versionString); foo->stackPointer = sp; } sqInt primitiveValue(void) { register struct foo * foo = &fum; sqInt blockContext; sqInt blockArgumentCount; sqInt initialIP; sqInt count; sqInt firstFrom; sqInt fromOop; sqInt fromIndex; sqInt lastFrom; sqInt toIndex; sqInt valuePointer; sqInt localArgCount; sqInt successValue; sqInt value; sqInt tmp; sqInt activeCntx; sqInt valuePointer2; sqInt valuePointer1; blockContext = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); /* begin argumentCountOfBlock: */ localArgCount = longAt((blockContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((localArgCount & 1)) { blockArgumentCount = (localArgCount >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; blockArgumentCount = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; /* begin success: */ successValue = (foo->argumentCount == blockArgumentCount) && ((longAt((blockContext + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD)))) == foo->nilObj); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin transfer:fromIndex:ofObject:toIndex:ofObject: */ count = foo->argumentCount; firstFrom = ((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - foo->argumentCount) + 1; fromOop = foo->activeContext; flag("Dan"); fromIndex = fromOop + (firstFrom * (BYTES_PER_WORD)); toIndex = blockContext + (TempFrameStart * (BYTES_PER_WORD)); lastFrom = fromIndex + (count * (BYTES_PER_WORD)); while ((((usqInt) fromIndex)) < (((usqInt) lastFrom))) { fromIndex += BYTES_PER_WORD; toIndex += BYTES_PER_WORD; longAtput(toIndex, longAt(fromIndex)); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); initialIP = longAt((blockContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD))); longAtput((blockContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ value = foo->argumentCount; longAtput((blockContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((value << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->activeContext; longAtput((blockContext + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer2 = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer2); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) blockContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(blockContext); } foo->activeContext = blockContext; /* begin fetchContextRegisters: */ tmp = longAt((blockContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((blockContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = blockContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((blockContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((blockContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (blockContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } } /* The only purpose of this primitive is to indicate that the new EH mechanisms are supported. */ sqInt primitiveValueUninterruptably(void) { return primitiveValue(); } sqInt primitiveValueWithArgs(void) { register struct foo * foo = &fum; sqInt arrayArgumentCount; sqInt blockContext; sqInt blockArgumentCount; sqInt initialIP; sqInt argumentArray; sqInt sz; sqInt successValue; sqInt fromIndex; sqInt lastFrom; sqInt toIndex; sqInt valuePointer; sqInt top; sqInt top1; sqInt localArgCount; sqInt header; sqInt tmp; sqInt activeCntx; sqInt valuePointer2; sqInt valuePointer1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; argumentArray = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; blockContext = top1; /* begin argumentCountOfBlock: */ localArgCount = longAt((blockContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((localArgCount & 1)) { blockArgumentCount = (localArgCount >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; blockArgumentCount = 0; goto l2; } l2: /* end checkedIntegerValueOf: */; if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); /* begin primitiveFail */ foo->successFlag = 0; return null; } if (foo->successFlag) { /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; arrayArgumentCount = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin success: */ successValue = (arrayArgumentCount == blockArgumentCount) && ((longAt((blockContext + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD)))) == foo->nilObj); foo->successFlag = successValue && foo->successFlag; } if (foo->successFlag) { /* begin transfer:fromIndex:ofObject:toIndex:ofObject: */ flag("Dan"); fromIndex = argumentArray + (0 * (BYTES_PER_WORD)); toIndex = blockContext + (TempFrameStart * (BYTES_PER_WORD)); lastFrom = fromIndex + (arrayArgumentCount * (BYTES_PER_WORD)); while ((((usqInt) fromIndex)) < (((usqInt) lastFrom))) { fromIndex += BYTES_PER_WORD; toIndex += BYTES_PER_WORD; longAtput(toIndex, longAt(fromIndex)); } initialIP = longAt((blockContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD))); longAtput((blockContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ longAtput((blockContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((arrayArgumentCount << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->activeContext; longAtput((blockContext + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer2 = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer2); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) blockContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(blockContext); } foo->activeContext = blockContext; /* begin fetchContextRegisters: */ tmp = longAt((blockContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((blockContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = blockContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((blockContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((blockContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (blockContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } sqInt primitiveWait(void) { register struct foo * foo = &fum; sqInt activeProc; sqInt excessSignals; sqInt sema; sqInt oop; sqInt oop1; sqInt lastLink; sqInt oop2; sqInt classOop; sqInt cl; sqInt ccIndex; sqInt oop11; sqInt oop21; sqInt oop3; /* rcvr */ sema = longAt(foo->stackPointer); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassSemaphore << (SHIFT_FOR_WORD))); if ((sema & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(sema))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(sema - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { excessSignals = fetchIntegerofObject(ExcessSignalsIndex, sema); if (excessSignals > 0) { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (excessSignals - 1))) ^ ((((int) (excessSignals - 1))) << 1)) >= 0) # else (((excessSignals - 1) >= -1073741824) && ((excessSignals - 1) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((sema + (BASE_HEADER_SIZE)) + (ExcessSignalsIndex << (SHIFT_FOR_WORD)), (((excessSignals - 1) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin addLastLink:toList: */ if ((longAt((sema + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) sema)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(sema, activeProc); } longAtput((sema + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), activeProc); } else { lastLink = longAt((sema + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink, activeProc); } longAtput((lastLink + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), activeProc); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) sema)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(sema, activeProc); } longAtput((sema + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), activeProc); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, sema); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), sema); transferTo(wakeHighestPriority()); } } } /* primitively do the equivalent of Process>yield */ sqInt primitiveYield(void) { register struct foo * foo = &fum; sqInt processLists; sqInt activeProc; sqInt priority; sqInt processList; sqInt oop; sqInt oop1; sqInt lastLink; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop2 = longAt((oop4 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); priority = ((longAt((activeProc + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop1 = longAt((oop3 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); processLists = longAt((oop1 + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); processList = longAt((processLists + (BASE_HEADER_SIZE)) + ((priority - 1) << (SHIFT_FOR_WORD))); if (!((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj)) { /* begin addLastLink:toList: */ if ((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), activeProc); } else { lastLink = longAt((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink, activeProc); } longAtput((lastLink + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), activeProc); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), activeProc); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, processList); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), processList); transferTo(wakeHighestPriority()); } } /* For testing in Smalltalk, this method should be overridden in a subclass. */ sqInt print(char * s) { printf("%s", s); } /* Print all the stacks of all running processes, including those that are currently suspended. */ sqInt printAllStacks(void) { register struct foo * foo = &fum; sqInt oop; sqInt proc; sqInt ctx; sqInt sz; sqInt header; sqInt oop1; sqInt oop2; sqInt oop3; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); proc = longAt((oop1 + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); printNameOfClasscount(fetchClassOf(proc), 5); /* begin cr */ printf("\n"); printCallStackOf(foo->activeContext); oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if ((fetchClassOf(oop)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { /* begin cr */ printf("\n"); proc = longAt((oop + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD))); while (!(proc == foo->nilObj)) { printNameOfClasscount(fetchClassOf(proc), 5); /* begin cr */ printf("\n"); ctx = longAt((proc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); if (!(ctx == foo->nilObj)) { printCallStackOf(ctx); } proc = longAt((proc + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD))); } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } } sqInt printCallStack(void) { return printCallStackOf(foo->activeContext); } sqInt printCallStackOf(sqInt aContext) { register struct foo * foo = &fum; sqInt methClass; sqInt methodSel; sqInt home; sqInt message; sqInt ctxt; sqInt meth; sqInt rcvr; sqInt done; sqInt classDict; sqInt classDictSize; sqInt i; sqInt currClass; sqInt methodArray; sqInt sz; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt header; sqInt oop2; sqInt meth1; sqInt rcvr1; sqInt done1; sqInt classDict1; sqInt classDictSize1; sqInt i1; sqInt currClass1; sqInt methodArray1; sqInt sz1; sqInt ccIndex2; sqInt ccIndex1; sqInt oop6; sqInt oop11; sqInt header1; sqInt oop21; sqInt oop3; sqInt oop4; sqInt oop5; ctxt = aContext; while (!(ctxt == foo->nilObj)) { if ((fetchClassOf(ctxt)) == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop))) { home = longAt((ctxt + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); } else { home = ctxt; } /* begin findClassOfMethod:forReceiver: */ meth1 = longAt((home + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); rcvr1 = longAt((home + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); /* begin fetchClassOf: */ if ((rcvr1 & 1)) { /* begin fetchPointer:ofObject: */ oop6 = foo->specialObjectsOop; currClass1 = longAt((oop6 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l4; } ccIndex2 = (((usqInt) (longAt(rcvr1))) >> 12) & 31; if (ccIndex2 == 0) { currClass1 = (longAt(rcvr1 - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l4; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop11 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass1 = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex2 - 1) << (SHIFT_FOR_WORD))); goto l4; } l4: /* end fetchClassOf: */; done1 = 0; while (!(done1)) { classDict1 = longAt((currClass1 + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header1 = longAt(classDict1); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(classDict1 - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l5; } else { sz1 = header1 & (SIZE_MASK); goto l5; } l5: /* end sizeBitsOf: */; classDictSize1 = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray1 = longAt((classDict1 + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i1 = 0; while (i1 < (classDictSize1 - SelectorStart)) { if (meth1 == (longAt((methodArray1 + (BASE_HEADER_SIZE)) + (i1 << (SHIFT_FOR_WORD))))) { methClass = currClass1; goto l6; } i1 += 1; } currClass1 = longAt((currClass1 + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done1 = currClass1 == foo->nilObj; } /* begin fetchClassOf: */ if ((rcvr1 & 1)) { /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; methClass = longAt((oop21 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l6; } ccIndex1 = (((usqInt) (longAt(rcvr1))) >> 12) & 31; if (ccIndex1 == 0) { methClass = (longAt(rcvr1 - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l6; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); methClass = longAt((oop3 + (BASE_HEADER_SIZE)) + ((ccIndex1 - 1) << (SHIFT_FOR_WORD))); goto l6; } methClass = null; l6: /* end findClassOfMethod:forReceiver: */; /* begin findSelectorOfMethod:forReceiver: */ meth = longAt((home + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); rcvr = longAt((home + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; currClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; done = 0; while (!(done)) { classDict = longAt((currClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(classDict); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(classDict - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; classDictSize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray = longAt((classDict + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i = 0; while (i <= (classDictSize - SelectorStart)) { if (meth == (longAt((methodArray + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))))) { methodSel = longAt((classDict + (BASE_HEADER_SIZE)) + ((i + SelectorStart) << (SHIFT_FOR_WORD))); goto l3; } i += 1; } currClass = longAt((currClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done = currClass == foo->nilObj; } methodSel = foo->nilObj; l3: /* end findSelectorOfMethod:forReceiver: */; printNum(ctxt); print(" "); if (!(ctxt == home)) { print("[] in "); } printNameOfClasscount(methClass, 5); print(">"); if (methodSel == foo->nilObj) { print("?"); } else { printStringOf(methodSel); } if (methodSel == (fetchPointerofObject(SelectorDoesNotUnderstand, foo->specialObjectsOop))) { /* print arg message selector */ message = longAt((home + (BASE_HEADER_SIZE)) + ((0 + TempFrameStart) << (SHIFT_FOR_WORD))); methodSel = longAt((message + (BASE_HEADER_SIZE)) + (MessageSelectorIndex << (SHIFT_FOR_WORD))); print(" "); printStringOf(methodSel); } /* begin cr */ printf("\n"); ctxt = longAt((ctxt + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } } /* Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object. */ sqInt printNameOfClasscount(sqInt classOop, sqInt cnt) { if (cnt <= 0) { return print("bad class"); } if ((sizeBitsOf(classOop)) == (7 * (BYTES_PER_WORD))) { printNameOfClasscount(longAt((classOop + (BASE_HEADER_SIZE)) + (5 << (SHIFT_FOR_WORD))), cnt - 1); print(" class"); } else { printStringOf(longAt((classOop + (BASE_HEADER_SIZE)) + (6 << (SHIFT_FOR_WORD)))); } } /* For testing in Smalltalk, this method should be overridden in a subclass. */ sqInt printNum(sqInt n) { printf("%ld", (long) n); } sqInt printStringOf(sqInt oop) { sqInt cnt; sqInt fmt; sqInt i; if ((oop & 1)) { return null; } fmt = (((usqInt) (longAt(oop))) >> 8) & 15; if (fmt < 8) { return null; } cnt = ((100 < (lengthOf(oop))) ? 100 : (lengthOf(oop))); i = 0; while (i < cnt) { /* begin printChar: */ putchar(byteAt((oop + (BASE_HEADER_SIZE)) + i)); i += 1; } } sqInt printUnbalancedStack(sqInt primIdx) { print("Stack unbalanced after "); if (foo->successFlag) { print("successful primitive "); } else { print("failed primitive "); } printNum(primIdx); /* begin cr */ printf("\n"); } sqInt push(sqInt object) { register struct foo * foo = &fum; sqInt sp; longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } sqInt pushBool(sqInt trueOrFalse) { register struct foo * foo = &fum; sqInt sp; sqInt sp1; if (trueOrFalse) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } sqInt pushFloat(double f) { register struct foo * foo = &fum; sqInt object; sqInt sp; /* begin push: */ object = floatObjectOf(f); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } sqInt pushInteger(sqInt integerValue) { register struct foo * foo = &fum; sqInt sp; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), ((integerValue << 1) | 1)); foo->stackPointer = sp; } /* Record the given object in a the remap buffer. Objects in this buffer are remapped when a compaction occurs. This facility is used by the interpreter to ensure that objects in temporary variables are properly remapped. */ sqInt pushRemappableOop(sqInt oop) { register struct foo * foo = &fum; foo->remapBuffer[foo->remapBufferCount += 1] = oop; } /* Append aWord to aFile in this platforms 'natural' byte order. (Bytes will be swapped, if necessary, when the image is read on a different platform.) Set successFlag to false if the write fails. */ sqInt putLongtoFile(sqInt aWord, sqImageFile aFile) { register struct foo * foo = &fum; sqInt objectsWritten; objectsWritten = sqImageFileWrite(&aWord, sizeof(aWord), 1, aFile); /* begin success: */ foo->successFlag = (objectsWritten == 1) && foo->successFlag; } /* Read an image from the given file stream, allocating the given amount of memory to its object heap. Fail if the image has an unknown format or requires more than the given amount of memory. */ /* Details: This method detects when the image was stored on a machine with the opposite byte ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header information to start 512 bytes into the file, since some file transfer programs for the Macintosh apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix area could also be used to store an exec command on Unix systems, allowing one to launch Smalltalk by invoking the image name as a command. */ /* This code is based on C code by Ian Piumarta and Smalltalk code by Tim Rowledge. Many thanks to both of you!! */ sqInt readImageFromFileHeapSizeStartingAt(sqImageFile f, usqInt desiredHeapSize, squeakFileOffsetType imageOffset) { register struct foo * foo = &fum; sqInt memStart; size_t bytesRead; sqInt headerSize; squeakFileOffsetType headerStart; sqInt swapBytes; size_t dataSize; sqInt heapSize; sqInt bytesToShift; sqInt oldBaseAddr; sqInt minimumMemory; char * memoryAddress; sqInt startAddr; sqInt stopAddr; sqInt addr; swapBytes = checkImageVersionFromstartingAt(f, imageOffset); /* record header start position */ headerStart = (sqImageFilePosition(f)) - (BYTES_PER_WORD); headerSize = getLongFromFileswap(f, swapBytes); dataSize = getLongFromFileswap(f, swapBytes); oldBaseAddr = getLongFromFileswap(f, swapBytes); foo->specialObjectsOop = getLongFromFileswap(f, swapBytes); foo->lastHash = getLongFromFileswap(f, swapBytes); foo->savedWindowSize = getLongFromFileswap(f, swapBytes); foo->fullScreenFlag = getLongFromFileswap(f, swapBytes); extraVMMemory = getLongFromFileswap(f, swapBytes); if (foo->lastHash == 0) { /* lastHash wasn't stored (e.g. by the cloner); use 999 as the seed */ foo->lastHash = 999; } heapSize = reserveExtraCHeapBytes(desiredHeapSize, extraVMMemory); /* need at least 100K of breathing room */ minimumMemory = dataSize + 100000; if (heapSize < minimumMemory) { insufficientMemorySpecifiedError(); } memory = allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, f, headerSize); if (memory == null) { insufficientMemoryAvailableError(); } memStart = memory; /* decrease memoryLimit a tad for safety */ foo->memoryLimit = (memStart + heapSize) - 24; /* position file after the header */ foo->endOfMemory = memStart + dataSize; sqImageFileSeek(f, headerStart + headerSize); /* begin sqImage:read:size:length: */ memoryAddress = pointerForOop(memory); bytesRead = sqImageFileReadEntireImage(memoryAddress, sizeof(unsigned char), dataSize, f); if (bytesRead != dataSize) { unableToReadImageError(); } foo->headerTypeBytes[0] = ((BYTES_PER_WORD) * 2); foo->headerTypeBytes[1] = (BYTES_PER_WORD); foo->headerTypeBytes[2] = 0; foo->headerTypeBytes[3] = 0; if (swapBytes) { /* begin reverseBytesInImage */ /* begin reverseBytesFrom:to: */ startAddr = memory; stopAddr = foo->endOfMemory; flag("Dan"); addr = startAddr; while ((((usqInt) addr)) < (((usqInt) stopAddr))) { longAtput(addr, byteSwapped(longAt(addr))); addr += BYTES_PER_WORD; } /* begin byteSwapByteObjects */ byteSwapByteObjectsFromto(memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]), foo->endOfMemory); } bytesToShift = memStart - oldBaseAddr; initializeInterpreter(bytesToShift); isBigEnder(); return dataSize; } /* Anwer true if images of the given format are readable by this interpreter. Allows a virtual machine to accept selected older image formats. In our case we can select a newer (closure) image format as well as the existing format. */ sqInt readableFormat(sqInt imageVersion) { return (imageVersion == imageFormatVersionNumber) || ((imageVersion == (imageFormatForwardCompatibilityVersion())) || (imageVersion == (imageFormatBackwardCompatibilityVersion()))); } /* callbackContext is an activation of invokeCallback:stack:registers:jmpbuf:. Its sender is the interpreter's state prior to the callback. Reestablish that state. */ EXPORT(sqInt) reestablishContextPriorToCallback(sqInt callbackContext) { register struct foo * foo = &fum; sqInt calloutContext; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; if ((fetchClassOf(callbackContext)) != (fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop))) { return 0; } calloutContext = longAt((callbackContext + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) calloutContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(calloutContext); } foo->activeContext = calloutContext; /* begin fetchContextRegisters: */ tmp = longAt((calloutContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((calloutContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = calloutContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((calloutContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((calloutContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (calloutContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); return 1; } /* Map the given oop to its new value during a compaction or become: operation. If it has no forwarding table entry, return the oop itself. */ sqInt remap(sqInt oop) { register struct foo * foo = &fum; sqInt fwdBlock; if (((oop & 1) == 0) && (((longAt(oop)) & (MARK_BIT)) != 0)) { /* get the new value for oop from its forwarding block */ fwdBlock = ((longAt(oop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } return longAt(fwdBlock); } return oop; } /* Remove the first process from the given linked list. */ sqInt removeFirstLinkOfList(sqInt aList) { register struct foo * foo = &fum; sqInt next; sqInt first; sqInt last; sqInt valuePointer; sqInt valuePointer1; sqInt valuePointer2; first = longAt((aList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD))); last = longAt((aList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); if (first == last) { /* begin storePointer:ofObject:withValue: */ valuePointer = foo->nilObj; if ((((usqInt) aList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(aList, valuePointer); } longAtput((aList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointer:ofObject:withValue: */ valuePointer1 = foo->nilObj; if ((((usqInt) aList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(aList, valuePointer1); } longAtput((aList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), valuePointer1); } else { next = longAt((first + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) aList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(aList, next); } longAtput((aList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), next); } /* begin storePointer:ofObject:withValue: */ valuePointer2 = foo->nilObj; if ((((usqInt) first)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(first, valuePointer2); } longAtput((first + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), valuePointer2); return first; } /* Remove the given variable location to the extra roots table */ EXPORT(sqInt) removeGCRoot(sqInt *varLoc) { register struct foo * foo = &fum; sqInt *root; sqInt i; for (i = 1; i <= foo->extraRootCount; i += 1) { root = foo->extraRoots[i]; if (root == varLoc) { foo->extraRoots[i] = (foo->extraRoots[foo->extraRootCount]); foo->extraRootCount -= 1; return 1; } } return 0; } /* Restore the original header of the given oop from its forwarding block. */ sqInt restoreHeaderOf(sqInt oop) { register struct foo * foo = &fum; sqInt fwdBlock; sqInt fwdHeader; fwdHeader = longAt(oop); fwdBlock = (fwdHeader & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { if ((fwdHeader & (MARK_BIT)) == 0) { error("attempting to restore the header of an object that has no forwarding block"); } /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } longAtput(oop, longAt(fwdBlock + (BYTES_PER_WORD))); } /* Restore headers smashed by forwarding links */ sqInt restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut) { register struct foo * foo = &fum; sqInt oop; sqInt header; sqInt tablePtr; sqInt sz; sqInt header1; tablePtr = firstIn; while ((((usqInt) tablePtr)) <= (((usqInt) lastIn))) { oop = longAt(tablePtr); header = longAt(hdrBaseIn + (tablePtr - firstIn)); longAtput(oop, header); tablePtr += BYTES_PER_WORD; } tablePtr = firstOut; while ((((usqInt) tablePtr)) <= (((usqInt) lastOut))) { oop = longAt(tablePtr); header = longAt(hdrBaseOut + (tablePtr - firstOut)); longAtput(oop, header); tablePtr += BYTES_PER_WORD; } oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { longAtput(oop, (longAt(oop)) & (ALL_BUT_MARK_BIT)); } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } } sqInt resume(sqInt aProcess) { register struct foo * foo = &fum; sqInt activeProc; sqInt activePriority; sqInt newPriority; sqInt oop; sqInt oop1; sqInt oop2; sqInt processLists; sqInt priority; sqInt processList; sqInt oop3; sqInt oop11; sqInt lastLink; sqInt oop21; sqInt processLists1; sqInt priority1; sqInt processList1; sqInt oop4; sqInt oop12; sqInt lastLink1; sqInt oop22; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); activePriority = ((longAt((activeProc + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); newPriority = ((longAt((aProcess + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); if (newPriority > activePriority) { /* begin putToSleep: */ priority = ((longAt((activeProc + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop3 = longAt((oop11 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); processLists = longAt((oop3 + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); processList = longAt((processLists + (BASE_HEADER_SIZE)) + ((priority - 1) << (SHIFT_FOR_WORD))); /* begin addLastLink:toList: */ if ((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), activeProc); } else { lastLink = longAt((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink, activeProc); } longAtput((lastLink + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), activeProc); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), activeProc); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, processList); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), processList); transferTo(aProcess); } else { /* begin putToSleep: */ priority1 = ((longAt((aProcess + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop22 = foo->specialObjectsOop; oop12 = longAt((oop22 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop4 = longAt((oop12 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); processLists1 = longAt((oop4 + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); processList1 = longAt((processLists1 + (BASE_HEADER_SIZE)) + ((priority1 - 1) << (SHIFT_FOR_WORD))); /* begin addLastLink:toList: */ if ((longAt((processList1 + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList1, aProcess); } longAtput((processList1 + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), aProcess); } else { lastLink1 = longAt((processList1 + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink1, aProcess); } longAtput((lastLink1 + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), aProcess); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList1, aProcess); } longAtput((processList1 + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), aProcess); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) aProcess)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(aProcess, processList1); } longAtput((aProcess + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), processList1); } } /* Reverse the given range of Display words (at different bit depths, this will reverse different numbers of pixels). Used to give feedback during VM activities such as garbage collection when debugging. It is assumed that the given word range falls entirely within the first line of the Display. */ sqInt reverseDisplayFromto(sqInt startIndex, sqInt endIndex) { register struct foo * foo = &fum; sqInt displayObj; sqInt ptr; sqInt reversed; sqInt dispBitsPtr; sqInt w; sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; displayObj = longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); if (!((((displayObj & 1) == 0) && (((((usqInt) (longAt(displayObj))) >> 8) & 15) <= 4)) && ((lengthOf(displayObj)) >= 4))) { return null; } w = fetchIntegerofObject(1, displayObj); dispBitsPtr = longAt((displayObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if ((dispBitsPtr & 1)) { return null; } dispBitsPtr += BASE_HEADER_SIZE; for (ptr = (dispBitsPtr + (startIndex * 4)); ptr <= (dispBitsPtr + (endIndex * 4)); ptr += 4) { reversed = (long32At(ptr)) ^ 4294967295U; longAtput(ptr, reversed); } foo->successFlag = 1; displayBitsOfLeftTopRightBottom(displayObj, 0, 0, w, 1); ioForceDisplayUpdate(); } /* Rewrite the cache entry with the given primitive index and matching function pointer */ sqInt rewriteMethodCacheSelclassprimIndex(sqInt selector, sqInt class, sqInt localPrimIndex) { void * primPtr; if (localPrimIndex == 0) { primPtr = 0; } else { primPtr = primitiveTable[localPrimIndex]; } rewriteMethodCacheSelclassprimIndexprimFunction(selector, class, localPrimIndex, primPtr); } /* Rewrite an existing entry in the method cache with a new primitive index & function address. Used by primExternalCall to make direct jumps to found external prims */ sqInt rewriteMethodCacheSelclassprimIndexprimFunction(sqInt selector, sqInt class, sqInt localPrimIndex, void * localPrimAddress) { register struct foo * foo = &fum; sqInt hash; sqInt p; sqInt probe; hash = selector ^ class; for (p = 0; p <= (CacheProbeMax - 1); p += 1) { probe = (((usqInt) hash) >> p) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->methodCache[probe + MethodCachePrim] = localPrimIndex; foo->methodCache[probe + MethodCachePrimFunction] = (((long) localPrimAddress)); return null; } } } /* Send the 4 argument callback message invokeCallback:stack:registers:jmpbuf: to Alien class with the supplied args. The arguments are raw C addresses and are converted to integer objects on the way. */ EXPORT(sqInt) sendInvokeCallbackStackRegistersJmpbuf(sqInt thunkPtr, sqInt stackPtr, sqInt regsPtr, sqInt jmpBufPtr) { register struct foo * foo = &fum; sqInt where; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; sqInt tempCount; sqInt where1; sqInt initialIP; sqInt needsLarge; sqInt i; sqInt newContext; sqInt methodHeader; sqInt activeCntx; sqInt tmp; sqInt activeCntx1; sqInt valuePointer; sqInt valuePointer1; sqInt methodPointer; sqInt oop6; sqInt ccIndex; sqInt oop11; sqInt oop21; /* begin pushRemappableOop: */ oop = positive32BitIntegerFor(jmpBufPtr); foo->remapBuffer[foo->remapBufferCount += 1] = oop; /* begin pushRemappableOop: */ oop1 = positive32BitIntegerFor(regsPtr); foo->remapBuffer[foo->remapBufferCount += 1] = oop1; /* begin pushRemappableOop: */ oop2 = positive32BitIntegerFor(stackPtr); foo->remapBuffer[foo->remapBufferCount += 1] = oop2; /* begin pushRemappableOop: */ oop3 = positive32BitIntegerFor(thunkPtr); foo->remapBuffer[foo->remapBufferCount += 1] = oop3; /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; foo->receiver = longAt((oop4 + (BASE_HEADER_SIZE)) + (ClassAlien << (SHIFT_FOR_WORD))); /* begin fetchClassOfNonInt: */ oop6 = foo->receiver; ccIndex = (((usqInt) (longAt(oop6))) >> 12) & 31; if (ccIndex == 0) { foo->lkupClass = (longAt(oop6 - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); foo->lkupClass = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOfNonInt: */; /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; foo->messageSelector = longAt((oop5 + (BASE_HEADER_SIZE)) + (InvokeCallbackSelector << (SHIFT_FOR_WORD))); if (!(lookupInMethodCacheSelclass(foo->messageSelector, foo->lkupClass))) { if (!(lookupMethodNoMNUEtcInClass(foo->lkupClass))) { return 0; } } if (foo->primitiveIndex != 0) { return 0; } /* begin storeContextRegisters: */ activeCntx1 = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx1 + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); /* begin internalJustActivateNewMethod */ /* begin headerOf: */ methodPointer = foo->newMethod; methodHeader = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); needsLarge = methodHeader & LargeContextBit; if ((needsLarge == 0) && (foo->freeContexts != NilContext)) { newContext = foo->freeContexts; foo->freeContexts = longAt((newContext + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); } else { newContext = allocateOrRecycleContext(needsLarge); } initialIP = ((LiteralStart + ((((usqInt) methodHeader) >> 10) & 255)) * (BYTES_PER_WORD)) + 1; tempCount = (((usqInt) methodHeader) >> 19) & 63; where1 = newContext + (BASE_HEADER_SIZE); longAtput(where1 + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where1 + (InstructionPointerIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput(where1 + (StackPointerIndex << (SHIFT_FOR_WORD)), ((tempCount << 1) | 1)); longAtput(where1 + (MethodIndex << (SHIFT_FOR_WORD)), foo->newMethod); longAtput(where1 + (ReceiverIndex << (SHIFT_FOR_WORD)), foo->receiver); needsLarge = foo->nilObj; for (i = (ReceiverIndex + 1); i <= (tempCount + ReceiverIndex); i += 1) { longAtput(where1 + (i << (SHIFT_FOR_WORD)), needsLarge); } foo->reclaimableContextCount += 1; foo->activeContext = newContext; where = (foo->activeContext + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD)); longAtput(where + (1 << (SHIFT_FOR_WORD)), popRemappableOop()); longAtput(where + (2 << (SHIFT_FOR_WORD)), popRemappableOop()); longAtput(where + (3 << (SHIFT_FOR_WORD)), popRemappableOop()); longAtput(where + (4 << (SHIFT_FOR_WORD)), popRemappableOop()); /* begin fetchContextRegisters: */ activeCntx = foo->activeContext; tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = activeCntx; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (activeCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); callInterpreter(); return 1; } sqInt setCompilerInitialized(sqInt newFlag) { register struct foo * foo = &fum; sqInt oldFlag; oldFlag = foo->compilerInitialized; foo->compilerInitialized = newFlag; return oldFlag; } sqInt setInterruptCheckCounter(sqInt value) { foo->interruptCheckCounter = value; } sqInt setInterruptKeycode(sqInt value) { foo->interruptKeycode = value; } sqInt setInterruptPending(sqInt value) { foo->interruptPending = value; } /* A default substitute for unimplemented ioUtcWithOffset external function. */ sqInt setMicroSecondsandOffset(sqLong * microSeconds, int * utcOffset) { flag("toRemove"); return -1; } sqInt setNextWakeupTick(sqInt value) { foo->nextWakeupTick = value; } sqInt setSavedWindowSize(sqInt value) { foo->savedWindowSize = value; } /* Repaint the portion of the Smalltalk screen bounded by the affected rectangle. Used to synchronize the screen after a Bitblt to the Smalltalk Display object. */ sqInt showDisplayBitsLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b) { if (foo->deferDisplayUpdates) { return null; } displayBitsOfLeftTopRightBottom(aForm, l, t, r, b); } /* Record the given semaphore index in the double buffer semaphores array to be signaled at the next convenient moment. Force a real interrupt check as soon as possible. */ sqInt signalSemaphoreWithIndex(sqInt index) { register struct foo * foo = &fum; if (index <= 0) { return null; } if (foo->semaphoresUseBufferA) { if (foo->semaphoresToSignalCountA < SemaphoresToSignalSize) { foo->semaphoresToSignalCountA += 1; foo->semaphoresToSignalA[foo->semaphoresToSignalCountA] = index; } } else { if (foo->semaphoresToSignalCountB < SemaphoresToSignalSize) { foo->semaphoresToSignalCountB += 1; foo->semaphoresToSignalB[foo->semaphoresToSignalCountB] = index; } } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } /* Return a full 32 bit integer object for the given integer value */ sqInt signed32BitIntegerFor(int integerValue) { register struct foo * foo = &fum; sqInt value; sqInt newLargeInteger; sqInt largeClass; sqInt oop; sqInt oop1; if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerValue)) ^ ((((int) integerValue)) << 1)) >= 0) # else ((integerValue >= -1073741824) && (integerValue <= 1073741823)) # endif // SQ_HOST32 ) { return ((integerValue << 1) | 1); } if (integerValue < 0) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; largeClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD))); value = 0 - integerValue; } else { /* begin splObj: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); value = integerValue; } newLargeInteger = instantiateClassindexableSize(largeClass, 4); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 3, (((usqInt) value) >> 24) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 2, (((usqInt) value) >> 16) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 1, (((usqInt) value) >> 8) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 0, value & 255); return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a four-byte LargeInteger. */ int signed32BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt sz; int value; sqInt negative; sqInt largeClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt header; sqInt oop3; sqInt sz1; if ((oop & 1)) { return (oop >> 1); } if ((lengthOf(oop)) > 4) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { largeClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); largeClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; if (largeClass == (splObj(ClassLargePositiveInteger))) { negative = 0; } else { if (largeClass == (fetchPointerofObject(ClassLargeNegativeInteger, foo->specialObjectsOop))) { negative = 1; } else { /* begin primitiveFail */ foo->successFlag = 0; return null; } } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; if (!(sz == 4)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Fail if value exceeds range of a 32-bit two's-complement signed integer. */ value = (((byteAt((oop + (BASE_HEADER_SIZE)) + 0)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 1)) << 8)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 2)) << 16)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 3)) << 24); if (negative) { value = 0 - value; if (value >= 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } else { if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } return value; } /* Return a Large Integer object for the given integer value */ sqInt signed64BitIntegerFor(sqLong integerValue) { register struct foo * foo = &fum; unsigned sqLong magnitude; sqInt sz; usqInt highWord; sqInt i; sqInt newLargeInteger; sqInt intValue; sqInt largeClass; sqInt oop; sqInt oop1; if (integerValue < 0) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; largeClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD))); magnitude = 0 - integerValue; } else { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); magnitude = integerValue; } if (magnitude <= 2147483647U) { return signed32BitIntegerFor(integerValue); } /* shift is coerced to usqInt otherwise */ highWord = magnitude >> 32; if (highWord == 0) { sz = 4; } else { sz = 5; if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } } newLargeInteger = instantiateClassindexableSize(largeClass, sz); for (i = 0; i <= (sz - 1); i += 1) { intValue = (magnitude >> (i * 8)) & 255; byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + i, intValue); } return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargeInteger. */ sqLong signed64BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt i; sqLong value; sqInt szsqLong; sqInt negative; sqInt largeClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt header; sqInt oop3; sqInt sz1; if ((oop & 1)) { return ((sqLong) ((oop >> 1))); } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; if (sz > 8) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { largeClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); largeClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; if (largeClass == (splObj(ClassLargePositiveInteger))) { negative = 0; } else { if (largeClass == (fetchPointerofObject(ClassLargeNegativeInteger, foo->specialObjectsOop))) { negative = 1; } else { /* begin primitiveFail */ foo->successFlag = 0; return null; } } szsqLong = sizeof(sqLong); if (sz > szsqLong) { /* begin primitiveFail */ foo->successFlag = 0; return null; } value = 0; for (i = 0; i <= (sz - 1); i += 1) { value += (((sqLong) (byteAt((oop + (BASE_HEADER_SIZE)) + i)))) << (i * 8); } if (negative) { value = 0 - value; if (value >= 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } else { if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } return value; } /* Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words. */ /* Note: byte indexable objects need to have low bits subtracted from this size. */ sqInt sizeBitsOf(sqInt oop) { sqInt header; header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { return (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { return header & (SIZE_MASK); } } /* Return the number of indexable fields of the given object. This method is to be called from an automatically generated C primitive. The argument is assumed to be a pointer to the first indexable field of a words or bytes object; the object header starts 4 bytes before that. */ /* Note: Only called by translated primitive code. */ sqInt sizeOfSTArrayFromCPrimitive(void * cPtr) { sqInt oop; sqInt header; sqInt sz; oop = (oopForPointer(((char *) cPtr))) - (BASE_HEADER_SIZE); if (!(((oop & 1) == 0) && (isWordsOrBytesNonInt(oop)))) { /* begin primitiveFail */ foo->successFlag = 0; return 0; } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } if (((((usqInt) header) >> 8) & 15) < 8) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; } else { return (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); } return null; } /* Returns the number of slots in the receiver. If the receiver is a byte object, return the number of bytes. Otherwise return the number of words. */ sqInt slotSizeOf(sqInt oop) { sqInt header; sqInt sz; if ((oop & 1)) { return 0; } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } if (((((usqInt) header) >> 8) & 15) < 8) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; } else { return (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); } return null; } /* update state of active context */ sqInt snapshot(sqInt embedded) { register struct foo * foo = &fum; sqInt activeProc; void * setMacType; sqInt dataSize; sqInt rcvr; sqInt top; sqInt sp; sqInt sp1; sqInt sp2; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt activeCntx; sqInt valuePointer2; sqInt valuePointer1; sqInt oop2; sqInt oop3; sqInt sz; sqInt header; sqInt fmt; sqInt i; sqInt header1; sqInt sz1; sqInt oop11; sqInt i1; sqInt header2; if (foo->compilerInitialized) { compilerPreSnapshot(); } else { /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer2 = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer2); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer = foo->activeContext; if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, valuePointer); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD)), valuePointer); incrementalGC(); fullGC(); /* begin snapshotCleanUp */ oop3 = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop3)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop3)) & TypeMask) == HeaderTypeFree)) { header = longAt(oop3); fmt = (((usqInt) header) >> 8) & 15; if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin sizeBitsOf: */ header1 = longAt(oop3); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop3 - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; for (i = ((lastPointerOf(oop3)) + (BYTES_PER_WORD)); i <= (sz - (BASE_HEADER_SIZE)); i += (BYTES_PER_WORD)) { longAtput(oop3 + i, foo->nilObj); } } if (fmt >= 12) { if ((primitiveIndexOf(oop3)) == PrimitiveExternalCallIndex) { flushExternalPrimitiveOf(oop3); } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop3)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop3)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop3)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header2 = longAt(oop3); if ((header2 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop3 - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header2 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } oop3 = (oop3 + sz1) + (foo->headerTypeBytes[(longAt(oop3 + sz1)) & TypeMask]); } /* begin clearRootsTable */ for (i1 = 1; i1 <= foo->rootTableCount; i1 += 1) { oop11 = foo->rootTable[i1]; longAtput(oop11, (longAt(oop11)) & (ALL_BUT_ROOT_BIT)); foo->rootTable[i1] = 0; } foo->rootTableCount = 0; /* Assume all objects are below the start of the free block */ dataSize = foo->freeBlock - memory; if (foo->successFlag) { /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; rcvr = top; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; writeImageFile(dataSize); if (!(embedded)) { /* set Mac file type and creator; this is a noop on other platforms */ setMacType = ioLoadFunctionFrom("setMacFileTypeAndCreator", "FilePlugin"); if (!(setMacType == 0)) { ((sqInt (*)(char *, char *, char *))setMacType)(imageName, "STim", "FAST"); } } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } beRootIfOld(foo->activeContext); if (foo->successFlag) { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } else { /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), rcvr); foo->stackPointer = sp2; } if (foo->compilerInitialized) { compilerPostSnapshot(); } } /* Return one of the objects in the SpecialObjectsArray */ sqInt splObj(sqInt index) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (index << (SHIFT_FOR_WORD))); } /* Return what ST would return for <obj> at: index. */ sqInt stObjectat(sqInt array, sqInt index) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt stSize; sqInt sp; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(array); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(array - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l4; } if (fmt < 2) { fixedFields = totalLength; goto l4; } /* begin fetchClassOf: */ if ((array & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex = (((usqInt) (longAt(array))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(array - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l4: /* end fixedFieldsOf:format:length: */; if ((fmt == 3) && ((((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { stSize = 0; goto l1; } stSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; } else { stSize = totalLength - fixedFields; } if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { /* begin subscript:with:format: */ if (fmt <= 4) { return longAt((array + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD))); } if (fmt < 8) { return positive32BitIntegerFor(long32At((array + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << 2))); } else { return (((byteAt((array + (BASE_HEADER_SIZE)) + ((index + fixedFields) - 1))) << 1) | 1); } return null; } else { foo->successFlag = 0; return 0; } } /* Do what ST would return for <obj> at: index put: value. */ sqInt stObjectatput(sqInt array, sqInt index, sqInt value) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt stSize; sqInt sp; sqInt valueToStore; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(array); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(array - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l4; } if (fmt < 2) { fixedFields = totalLength; goto l4; } /* begin fetchClassOf: */ if ((array & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex = (((usqInt) (longAt(array))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(array - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l4: /* end fixedFieldsOf:format:length: */; if ((fmt == 3) && ((((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { stSize = 0; goto l1; } stSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; } else { stSize = totalLength - fixedFields; } if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { /* begin subscript:with:storing:format: */ if (fmt <= 4) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) array)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(array, value); } longAtput((array + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); } else { if (fmt < 8) { valueToStore = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((array + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << 2), valueToStore); } } else { if (!((value & 1))) { foo->successFlag = 0; } valueToStore = (value >> 1); if (!((valueToStore >= 0) && (valueToStore <= 255))) { foo->successFlag = 0; } if (foo->successFlag) { byteAtput((array + (BASE_HEADER_SIZE)) + ((index + fixedFields) - 1), valueToStore); } } } } else { foo->successFlag = 0; } } /* Return the number of indexable fields in the given object. (i.e., what Smalltalk would return for <obj> size). */ /* Note: Assume oop is not a SmallInteger! */ sqInt stSizeOf(sqInt oop) { register struct foo * foo = &fum; sqInt totalLength; sqInt fmt; sqInt fixedFields; sqInt hdr; sqInt sp; sqInt sz; sqInt classFormat; sqInt class; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(oop); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l3; } if (fmt < 2) { fixedFields = totalLength; goto l3; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l3: /* end fixedFieldsOf:format:length: */; if ((fmt == 3) && ((((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { return 0; } return (sp >> 1); } else { return totalLength - fixedFields; } } /* Note: May be called by translated primitive code. */ double stackFloatValue(sqInt offset) { register struct foo * foo = &fum; double result; sqInt floatPointer; floatPointer = longAt(foo->stackPointer - (offset * (BYTES_PER_WORD))); if (!((fetchClassOf(floatPointer)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)))) { /* begin primitiveFail */ foo->successFlag = 0; return 0.0; } ; fetchFloatAtinto(floatPointer + (BASE_HEADER_SIZE), result); return result; } sqInt stackIntegerValue(sqInt offset) { register struct foo * foo = &fum; sqInt integerPointer; integerPointer = longAt(foo->stackPointer - (offset * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { return (integerPointer >> 1); } else { /* begin primitiveFail */ foo->successFlag = 0; return 0; } return null; } /* Ensures that the given object is a real object, not a SmallInteger. */ sqInt stackObjectValue(sqInt offset) { register struct foo * foo = &fum; sqInt oop; oop = longAt(foo->stackPointer - (offset * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return oop; } sqInt stackValue(sqInt offset) { return longAt(foo->stackPointer - (offset * (BYTES_PER_WORD))); } /* Note: May be called by translated primitive code. */ sqInt storeIntegerofObjectwithValue(sqInt fieldIndex, sqInt objectPointer, sqInt integerValue) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerValue)) ^ ((((int) integerValue)) << 1)) >= 0) # else ((integerValue >= -1073741824) && (integerValue <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), ((integerValue << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } } /* Note must check here for stores of young objects into old ones. */ sqInt storePointerofObjectwithValue(sqInt fieldIndex, sqInt oop, sqInt valuePointer) { if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, valuePointer); } return longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); } sqInt success(sqInt successValue) { register struct foo * foo = &fum; foo->successFlag = successValue && foo->successFlag; } /* Return true if there is enough free space after doing a garbage collection. If not, signal that space is low. */ sqInt sufficientSpaceAfterGC(usqInt minFree) { register struct foo * foo = &fum; usqInt minFreePlus; usqInt growSize; incrementalGC(); if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { if (foo->signalLowSpace) { return 0; } fullGC(); minFreePlus = minFree + 15000; if (minFreePlus < minFree) { return 0; } if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFreePlus)) { return 1; } growSize = (minFree - ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK))) + foo->growHeadroom; growObjectMemory(growSize); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFreePlus)) { return 1; } return 0; } return 1; } /* Return true if there is enough space to allocate the given number of bytes, perhaps after doing a garbage collection. Sender is responsible for ensuring that requested size does result in arithmetic overflow, see note below. */ sqInt sufficientSpaceToAllocate(usqInt bytes) { register struct foo * foo = &fum; usqInt minFree; /* check for low-space */ minFree = (foo->lowSpaceThreshold + bytes) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { return 1; } else { return sufficientSpaceAfterGC(minFree); } } sqInt superclassOf(sqInt classPointer) { return longAt((classPointer + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } /* Sweep memory from youngStart through the end of memory. Free all inaccessible objects and coalesce adjacent free chunks. Clear the mark bits of accessible objects. Compute the starting point for the first pass of incremental compaction (compStart). Return the number of surviving objects. */ /* Details: Each time a non-free object is encountered, decrement the number of available forward table entries. If all entries are spoken for (i.e., entriesAvailable reaches zero), set compStart to the last free chunk before that object or, if there is no free chunk before the given object, the first free chunk after it. Thus, at the end of the sweep phase, compStart through compEnd spans the highest collection of non-free objects that can be accomodated by the forwarding table. This information is used by the first pass of incremental compaction to ensure that space is initially freed at the end of memory. Note that there should always be at least one free chunk--the one at the end of the heap. */ sqInt sweepPhase(void) { register struct foo * foo = &fum; sqInt oopSize; usqInt oop; sqInt entriesAvailable; sqInt freeChunkSize; sqInt hdrBytes; sqInt oopHeaderType; sqInt firstFree; usqInt endOfMemoryLocal; sqInt freeChunk; sqInt oopHeader; sqInt survivors; entriesAvailable = fwdTableInit((BYTES_PER_WORD) * 2); survivors = 0; /* an invalid object pointer, note that 0 may refer to a meaningful slot */ freeChunk = -1; /* will be updated later */ firstFree = -1; endOfMemoryLocal = foo->endOfMemory; oop = foo->youngStart + (foo->headerTypeBytes[(longAt(foo->youngStart)) & TypeMask]); while (oop < endOfMemoryLocal) { /* get oop's header, header type, size, and header size */ foo->statSweepCount += 1; oopHeader = longAt(oop); oopHeaderType = oopHeader & TypeMask; hdrBytes = foo->headerTypeBytes[oopHeaderType]; if ((oopHeaderType & 1) == 1) { oopSize = oopHeader & (SIZE_MASK); } else { if (oopHeaderType == HeaderTypeSizeAndClass) { oopSize = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { /* free chunk */ oopSize = oopHeader & (LONG_SIZE_MASK); } } if ((oopHeader & (MARK_BIT)) == 0) { longAtput(oop - hdrBytes, HeaderTypeFree); if (freeChunk != -1) { /* enlarge current free chunk to include this oop */ freeChunkSize = (freeChunkSize + oopSize) + hdrBytes; } else { /* start a new free chunk */ /* chunk may start 4 or 8 bytes before oop */ freeChunk = oop - hdrBytes; /* adjust size for possible extra header bytes */ freeChunkSize = oopSize + (oop - freeChunk); if (firstFree == -1) { firstFree = freeChunk; } } } else { longAtput(oop, oopHeader & (ALL_BUT_MARK_BIT)); if (((((usqInt) (longAt(oop))) >> 8) & 15) == 4) { finalizeReference(oop); } if (entriesAvailable > 0) { entriesAvailable -= 1; } else { /* start compaction at the last free chunk before this object */ firstFree = freeChunk; } if (freeChunk != -1) { longAtput(freeChunk, (freeChunkSize & (LONG_SIZE_MASK)) | HeaderTypeFree); freeChunk = -1; } survivors += 1; } oop = (oop + oopSize) + (foo->headerTypeBytes[(longAt(oop + oopSize)) & TypeMask]); } if (freeChunk != -1) { longAtput(freeChunk, (freeChunkSize & (LONG_SIZE_MASK)) | HeaderTypeFree); } if (!(oop == foo->endOfMemory)) { error("sweep failed to find exact end of memory"); } if (firstFree == -1) { error("expected to find at least one free object"); } else { foo->compStart = firstFree; } return survivors; } /* Signal the given semaphore from within the interpreter. */ sqInt synchronousSignal(sqInt aSemaphore) { register struct foo * foo = &fum; sqInt excessSignals; if ((longAt((aSemaphore + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* no process is waiting on this semaphore */ excessSignals = fetchIntegerofObject(ExcessSignalsIndex, aSemaphore); /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (excessSignals + 1))) ^ ((((int) (excessSignals + 1))) << 1)) >= 0) # else (((excessSignals + 1) >= -1073741824) && ((excessSignals + 1) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((aSemaphore + (BASE_HEADER_SIZE)) + (ExcessSignalsIndex << (SHIFT_FOR_WORD)), (((excessSignals + 1) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } } else { resume(removeFirstLinkOfList(aSemaphore)); } } /* Record a process to be awoken on the next interpreter cycle. ikp 11/24/1999 06:07 -- added hook for external runtime compiler */ sqInt transferTo(sqInt aProc) { register struct foo * foo = &fum; sqInt sched; sqInt oldProc; sqInt newProc; sqInt oop; sqInt valuePointer; sqInt aContext; sqInt valuePointer1; sqInt oop1; sqInt activeCntx; sqInt valuePointer2; sqInt valuePointer11; sqInt tmp; newProc = aProc; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); oldProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) sched)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(sched, newProc); } longAtput((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD)), newProc); if (foo->compilerInitialized) { compilerProcessChangeto(oldProc, newProc); } else { /* begin storePointer:ofObject:withValue: */ valuePointer = foo->activeContext; if ((((usqInt) oldProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oldProc, valuePointer); } longAtput((oldProc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin newActiveContext: */ aContext = longAt((newProc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer2 = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer2); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer11 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer11); if ((((usqInt) aContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(aContext); } foo->activeContext = aContext; /* begin fetchContextRegisters: */ tmp = longAt((aContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((aContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = aContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((aContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((aContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (aContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); /* begin storePointer:ofObject:withValue: */ valuePointer1 = foo->nilObj; if ((((usqInt) newProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(newProc, valuePointer1); } longAtput((newProc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD)), valuePointer1); } foo->reclaimableContextCount = 0; } sqInt trueObject(void) { return foo->trueObj; } /* update pointers in the given memory range */ sqInt updatePointersInRangeFromto(sqInt memStart, sqInt memEnd) { register struct foo * foo = &fum; sqInt oop; sqInt newOop; sqInt fieldOffset; sqInt fwdBlock; sqInt fieldOop; sqInt size; sqInt header; sqInt fwdBlock1; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt sp; sqInt classHeader; sqInt newClassHeader; sqInt fwdBlock2; sqInt newClassOop; sqInt classOop; sqInt sz; sqInt header2; sqInt fwdBlock3; sqInt realHeader; sqInt sz1; sqInt header1; oop = memStart + (foo->headerTypeBytes[(longAt(memStart)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) memEnd))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { /* begin remapFieldsAndClassOf: */ /* begin lastPointerWhileForwarding: */ header = longAt(oop); if ((header & (MARK_BIT)) != 0) { fwdBlock1 = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } header = longAt(fwdBlock1 + (BYTES_PER_WORD)); } fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } if ((header & TypeMask) == HeaderTypeSizeAndClass) { size = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { size = header & (SIZE_MASK); } fieldOffset = size - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { fieldOffset = 0; goto l2; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerWhileForwarding: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { fieldOop = longAt(oop + fieldOffset); if (((fieldOop & 1) == 0) && (((longAt(fieldOop)) & (MARK_BIT)) != 0)) { fwdBlock = ((longAt(fieldOop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } newOop = longAt(fwdBlock); longAtput(oop + fieldOffset, newOop); if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && ((((usqInt) newOop)) >= (((usqInt) foo->youngStart)))) { beRootWhileForwarding(oop); } } fieldOffset -= BYTES_PER_WORD; } /* begin remapClassOf: */ if (((longAt(oop)) & TypeMask) == HeaderTypeShort) { goto l3; } classHeader = longAt(oop - (BYTES_PER_WORD)); classOop = classHeader & (ALL_BUT_TYPE_MASK); if (((classOop & 1) == 0) && (((longAt(classOop)) & (MARK_BIT)) != 0)) { fwdBlock2 = ((longAt(classOop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock2)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock2)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock2 & 3) == 0)))) { error("invalid fwd table entry"); } } newClassOop = longAt(fwdBlock2); newClassHeader = newClassOop | (classHeader & TypeMask); longAtput(oop - (BYTES_PER_WORD), newClassHeader); if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && ((((usqInt) newClassOop)) >= (((usqInt) foo->youngStart)))) { beRootWhileForwarding(oop); } } l3: /* end remapClassOf: */; } /* begin objectAfterWhileForwarding: */ header2 = longAt(oop); if ((header2 & (MARK_BIT)) == 0) { /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l4; } else { sz1 = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOf: */; } oop = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); goto l5; } fwdBlock3 = (header2 & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock3)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock3)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock3 & 3) == 0)))) { error("invalid fwd table entry"); } } realHeader = longAt(fwdBlock3 + (BYTES_PER_WORD)); if ((realHeader & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = realHeader & (SIZE_MASK); } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); l5: /* end objectAfterWhileForwarding: */; } } /* update pointers in root objects */ sqInt updatePointersInRootObjectsFromto(sqInt memStart, sqInt memEnd) { register struct foo * foo = &fum; sqInt oop; sqInt i; sqInt newOop; sqInt fieldOffset; sqInt fwdBlock; sqInt fieldOop; sqInt size; sqInt header; sqInt fwdBlock1; sqInt contextSize; sqInt fmt; sqInt methodHeader; sqInt sp; sqInt classHeader; sqInt newClassHeader; sqInt fwdBlock2; sqInt newClassOop; sqInt classOop; for (i = 1; i <= foo->rootTableCount; i += 1) { oop = foo->rootTable[i]; if (((((usqInt) oop)) < (((usqInt) memStart))) || ((((usqInt) oop)) >= (((usqInt) memEnd)))) { /* begin remapFieldsAndClassOf: */ /* begin lastPointerWhileForwarding: */ header = longAt(oop); if ((header & (MARK_BIT)) != 0) { fwdBlock1 = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } header = longAt(fwdBlock1 + (BYTES_PER_WORD)); } fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } if ((header & TypeMask) == HeaderTypeSizeAndClass) { size = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { size = header & (SIZE_MASK); } fieldOffset = size - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { fieldOffset = 0; goto l2; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerWhileForwarding: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { fieldOop = longAt(oop + fieldOffset); if (((fieldOop & 1) == 0) && (((longAt(fieldOop)) & (MARK_BIT)) != 0)) { fwdBlock = ((longAt(fieldOop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } newOop = longAt(fwdBlock); longAtput(oop + fieldOffset, newOop); if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && ((((usqInt) newOop)) >= (((usqInt) foo->youngStart)))) { beRootWhileForwarding(oop); } } fieldOffset -= BYTES_PER_WORD; } /* begin remapClassOf: */ if (((longAt(oop)) & TypeMask) == HeaderTypeShort) { goto l3; } classHeader = longAt(oop - (BYTES_PER_WORD)); classOop = classHeader & (ALL_BUT_TYPE_MASK); if (((classOop & 1) == 0) && (((longAt(classOop)) & (MARK_BIT)) != 0)) { fwdBlock2 = ((longAt(classOop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock2)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock2)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock2 & 3) == 0)))) { error("invalid fwd table entry"); } } newClassOop = longAt(fwdBlock2); newClassHeader = newClassOop | (classHeader & TypeMask); longAtput(oop - (BYTES_PER_WORD), newClassHeader); if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && ((((usqInt) newClassOop)) >= (((usqInt) foo->youngStart)))) { beRootWhileForwarding(oop); } } l3: /* end remapClassOf: */; } } } /* Verify that every old object that points to a new object has its root bit set, and appears in the rootTable. This method should not be called if the rootTable is full, because roots are no longer recorded, and incremental collections are not attempted. If DoAssertionChecks is true, this routine will halt on an unmarked root. Otherwise, this routine will merely return true in that case. */ sqInt validateRoots(void) { register struct foo * foo = &fum; usqInt fieldAddr; usqInt oop; sqInt header; usqInt fieldOop; sqInt badRoot; sqInt sz; sqInt header1; badRoot = 0; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while (oop < foo->youngStart) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { fieldAddr = oop + (lastPointerOf(oop)); while (fieldAddr > oop) { fieldOop = longAt(fieldAddr); if ((fieldOop >= foo->youngStart) && (!((fieldOop & 1)))) { /* fieldOop is a pointer to a young object */ header = longAt(oop); if ((header & (ROOT_BIT)) == 0) { if (DoAssertionChecks) { error("root bit not set"); } badRoot = 1; } else { null; } } fieldAddr -= BYTES_PER_WORD; } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } return badRoot; } sqInt verifyCleanHeaders(void) { register struct foo * foo = &fum; sqInt oop; sqInt sz; sqInt header; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { if (!((objectAfter(oop)) == foo->endOfMemory)) { error("Invalid obj with HeaderTypeBits = Free."); } } else { if (!(((longAt(oop)) & (MARK_BIT)) == 0)) { error("Invalid obj with MarkBit set."); } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } } /* return 0 for little endian, 1 for big endian */ sqInt vmEndianness(void) { if (isBigEnder()) { return 1; } else { return 0; } } /* Return the highest priority process that is ready to run. */ /* Note: It is a fatal VM error if there is no runnable process. */ sqInt wakeHighestPriority(void) { register struct foo * foo = &fum; sqInt p; sqInt schedLists; sqInt processList; sqInt oop; sqInt sz; sqInt oop1; sqInt header; sqInt oop2; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); schedLists = longAt((oop + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(schedLists); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(schedLists - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; p = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* index of last indexable field */ p -= 1; processList = longAt((schedLists + (BASE_HEADER_SIZE)) + (p << (SHIFT_FOR_WORD))); while ((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { p -= 1; if (p < 0) { error("scheduler could not find a runnable process"); } processList = longAt((schedLists + (BASE_HEADER_SIZE)) + (p << (SHIFT_FOR_WORD))); } return removeFirstLinkOfList(processList); } /* Return the given 64-bit integer with its halves in the reverse order. */ sqInt wordSwapped(sqInt w) { # if (BYTES_PER_WORD == 8) // swap 32-bit ends of a 64-bit object word return ((((usqInt) w >> 32)) & Bytes3to0Mask) + ((((usqInt) w << 32)) & Bytes7to4Mask); # else error("This cannot happen."); # endif // BYTES_PER_WORD == 8 } sqInt writeImageFile(sqInt imageBytes) { void * fn; writeImageFileIO(imageBytes); fn = ioLoadFunctionFrom("setMacFileTypeAndCreator", "FilePlugin"); if (!(fn == 0)) { ((sqInt (*)(char*, char*, char*))fn)(imageName, "STim", "FAST"); } } sqInt writeImageFileIO(sqInt imageBytes) { register struct foo * foo = &fum; sqInt headerSize; sqInt i; void * sCWIfn; squeakFileOffsetType headerStart; size_t bytesWritten; sqInt okToWrite; sqImageFile f; char * memoryAddress; sCWIfn = ioLoadFunctionFrom("secCanWriteImage", "SecurityPlugin"); if (sCWIfn != 0) { okToWrite = ((sqInt (*)(void))sCWIfn)(); if (!(okToWrite)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } headerStart = 0; /* header size in bytes; do not change! */ headerSize = 64; f = sqImageFileOpen(imageName, "wb"); if (f == null) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } headerStart = sqImageFileStartLocation(f,imageName,headerSize+imageBytes); /* Note: on Unix systems one could put an exec command here, padded to 512 bytes */; sqImageFileSeek(f, headerStart); putLongtoFile(imageFormatVersionNumber, f); putLongtoFile(headerSize, f); putLongtoFile(imageBytes, f); putLongtoFile(memory, f); putLongtoFile(foo->specialObjectsOop, f); putLongtoFile(foo->lastHash, f); putLongtoFile(ioScreenSize(), f); putLongtoFile(foo->fullScreenFlag, f); putLongtoFile(extraVMMemory, f); for (i = 1; i <= 7; i += 1) { putLongtoFile(0, f); } if (!(foo->successFlag)) { sqImageFileClose(f); return null; } sqImageFileSeek(f, headerStart + headerSize); /* begin sqImage:write:size:length: */ memoryAddress = pointerForOop(memory); bytesWritten = sqImageFileWrite(memoryAddress, sizeof(unsigned char), imageBytes, f); /* begin success: */ foo->successFlag = (bytesWritten == imageBytes) && foo->successFlag; sqImageFileClose(f); } void* vm_exports[][3] = { {"", "primitiveSetGCBiasToGrow", (void*)primitiveSetGCBiasToGrow}, {"", "internalIsMutable", (void*)internalIsMutable}, {"", "getStackPointer", (void*)getStackPointer}, {"", "primitiveImageFormatVersion", (void*)primitiveImageFormatVersion}, {"", "primitiveUtcWithOffset", (void*)primitiveUtcWithOffset}, {"", "sendInvokeCallbackStackRegistersJmpbuf", (void*)sendInvokeCallbackStackRegistersJmpbuf}, {"", "primitiveIsRoot", (void*)primitiveIsRoot}, {"", "primitiveMicrosecondClock", (void*)primitiveMicrosecondClock}, {"", "primitiveDisablePowerManager", (void*)primitiveDisablePowerManager}, {"", "primitiveIsYoung", (void*)primitiveIsYoung}, {"", "callbackEnter", (void*)callbackEnter}, {"", "primitiveChangeClassWithClass", (void*)primitiveChangeClassWithClass}, {"", "internalIsImmutable", (void*)internalIsImmutable}, {"", "callbackLeave", (void*)callbackLeave}, {"", "primitivePlatformSourceVersion", (void*)primitivePlatformSourceVersion}, {"", "moduleUnloaded", (void*)moduleUnloaded}, {"", "primitiveRootTableAt", (void*)primitiveRootTableAt}, {"", "primitiveSetGCBiasToGrowGCLimit", (void*)primitiveSetGCBiasToGrowGCLimit}, {"", "primitiveForceTenure", (void*)primitiveForceTenure}, {"", "primitiveVMVersion", (void*)primitiveVMVersion}, {"", "primitiveInterpreterSourceVersion", (void*)primitiveInterpreterSourceVersion}, {"", "primitiveScreenDepth", (void*)primitiveScreenDepth}, {"", "removeGCRoot", (void*)removeGCRoot}, {"", "primitiveRootTable", (void*)primitiveRootTable}, {"", "addGCRoot", (void*)addGCRoot}, {"", "dumpImage", (void*)dumpImage}, {"", "primitiveSetGCSemaphore", (void*)primitiveSetGCSemaphore}, {"", "callInterpreter", (void*)callInterpreter}, {"", "reestablishContextPriorToCallback", (void*)reestablishContextPriorToCallback}, {NULL, NULL, NULL} }; ================================================ FILE: vm/src/from_squeak/iOS/vm/src/vm/interp.h ================================================ /* Automatically generated from Squeak on 8 July 2010 12:32:31 pm by VMMaker 4.2.6 */ //#define VMMAKER_VERSION "4.2.6" /* * define SQ_VI_BYTES_PER_WORD 8 for a 64-bit word size VM * and default to SQ_VI_BYTES_PER_WORD 4 for a 32-bit word size VM */ #ifndef SQ_VI_BYTES_PER_WORD # define SQ_VI_BYTES_PER_WORD 4 #endif #define BYTES_PER_WORD SQ_VI_BYTES_PER_WORD // Is already defined for the RoarVM based on Object::BaseHeaderSize # ifndef ROAR_VM #define BASE_HEADER_SIZE sizeof(long int) # endif // !ROAR_VM /* #define BASE_HEADER_SIZE SQ_VI_BYTES_PER_WORD #if (BYTES_PER_WORD == 4) // 32-bit object memory # define WORD_MASK 0xffffffff # define SHIFT_FOR_WORD 2 # define SMALL_CONTEXT_SIZE 92 # define LARGE_CONTEXT_SIZE 252 # define SIZE_MASK 0xfc # define LONG_SIZE_MASK 0xfffffffc # define SIZE_4_BIT 0 # define MARK_BIT 0x80000000 # define ROOT_BIT 0x40000000 # define ALL_BUT_MARK_BIT 0x7fffffff # define ALL_BUT_ROOT_BIT 0xbfffffff # define ALL_BUT_TYPE_MASK 0xfffffffc # define ALL_BUT_MARK_BIT_AND_TYPE_MASK 0x7ffffffc # define ALL_BUT_HASH_BITS 0xe001ffff #else // 64-bit object memory # define WORD_MASK 0xffffffffffffffff # define SHIFT_FOR_WORD 3 # define SMALL_CONTEXT_SIZE 184 # define LARGE_CONTEXT_SIZE 504 # define SIZE_MASK 0xf8 # define LONG_SIZE_MASK 0xfffffffffffffff8 # define SIZE_4_BIT 4 # define MARK_BIT 0x8000000000000000 # define ROOT_BIT 0x4000000000000000 # define ALL_BUT_MARK_BIT 0x7fffffffffffffff # define ALL_BUT_ROOT_BIT 0xbfffffffffffffff # define ALL_BUT_TYPE_MASK 0xfffffffffffffffc # define ALL_BUT_MARK_BIT_AND_TYPE_MASK 0x7ffffffffffffffc # define ALL_BUT_HASH_BITS 0xffffffffe001ffff #endif // (BYTES_PER_WORD == 4) */ ================================================ FILE: vm/src/from_squeak/iOS/vm/src/vm/sqNamedPrims.h ================================================ /* Automatically generated from Squeak on #(15 May 2008 3:27:04 pm) by VMMaker 3.8b6 */ /* This is an automatically generated table of all builtin modules in the VM */ //extern sqExport vm_exports[]; extern sqExport os_exports[]; //extern sqExport ADPCMCodecPlugin_exports[]; extern sqExport Squeak3D_exports[]; extern sqExport B2DPlugin_exports[]; extern sqExport BitBltPlugin_exports[]; extern sqExport BMPReadWriterPlugin_exports[]; extern sqExport ZipPlugin_exports[]; extern sqExport DSAPrims_exports[]; # ifndef ROAR_VM extern sqExport SqueakFFIPrims_exports[]; # endif // !ROAR_VM extern sqExport FFTPlugin_exports[]; extern sqExport FilePlugin_exports[]; extern sqExport FloatArrayPlugin_exports[]; extern sqExport GeniePlugin_exports[]; extern sqExport HostWindowPlugin_exports[]; extern sqExport JPEGReaderPlugin_exports[]; extern sqExport JPEGReadWriter2Plugin_exports[]; extern sqExport Klatt_exports[]; extern sqExport LargeIntegers_exports[]; extern sqExport Matrix2x3Plugin_exports[]; extern sqExport MiscPrimitivePlugin_exports[]; extern sqExport ObjectiveCPlugin_exports[]; extern sqExport RePlugin_exports[]; extern sqExport SecurityPlugin_exports[]; extern sqExport SocketPlugin_exports[]; extern sqExport SoundCodecPrims_exports[]; extern sqExport SoundGenerationPlugin_exports[]; extern sqExport SoundPlugin_exports[]; extern sqExport StarSqueakPlugin_exports[]; extern sqExport SurfacePlugin_exports[]; extern sqExport UUIDPlugin_exports[]; extern sqExport RVMPlugin_exports[]; sqExport *pluginExports[] = { // vm_exports, os_exports, // ADPCMCodecPlugin_exports, Squeak3D_exports, B2DPlugin_exports, BitBltPlugin_exports, BMPReadWriterPlugin_exports, ZipPlugin_exports, DSAPrims_exports, # ifndef ROAR_VM SqueakFFIPrims_exports, # endif // !ROAR_VM FFTPlugin_exports, FilePlugin_exports, FloatArrayPlugin_exports, GeniePlugin_exports, HostWindowPlugin_exports, JPEGReaderPlugin_exports, JPEGReadWriter2Plugin_exports, Klatt_exports, LargeIntegers_exports, Matrix2x3Plugin_exports, MiscPrimitivePlugin_exports, ObjectiveCPlugin_exports, RePlugin_exports, SecurityPlugin_exports, #if !On_iOS SocketPlugin_exports, #endif SoundCodecPrims_exports, SoundGenerationPlugin_exports, SoundPlugin_exports, StarSqueakPlugin_exports, SurfacePlugin_exports, UUIDPlugin_exports, RVMPlugin_exports, // RoarVM NULL }; ================================================ FILE: vm/src/from_squeak/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from ADPCMCodecPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "ADPCMCodecPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Proxy Functions ***/ #define stackValue(i) (interpreterProxy->stackValue(i)) #define stackIntegerValue(i) (interpreterProxy->stackIntegerValue(i)) #define successFlag (!interpreterProxy->failed()) #define success(bool) (interpreterProxy->success(bool)) #define arrayValueOf(oop) (interpreterProxy->arrayValueOf(oop)) #define checkedIntegerValueOf(oop) (interpreterProxy->checkedIntegerValueOf(oop)) #define fetchArrayofObject(idx,oop) (interpreterProxy->fetchArrayofObject(idx,oop)) #define fetchFloatofObject(idx,oop) (interpreterProxy->fetchFloatofObject(idx,oop)) #define fetchIntegerofObject(idx,oop) (interpreterProxy->fetchIntegerofObject(idx,oop)) #define floatValueOf(oop) (interpreterProxy->floatValueOf(oop)) #define pop(n) (interpreterProxy->pop(n)) #define pushInteger(n) (interpreterProxy->pushInteger(n)) #define sizeOfSTArrayFromCPrimitive(cPtr) (interpreterProxy->sizeOfSTArrayFromCPrimitive(cPtr)) #define storeIntegerofObjectwithValue(idx,oop,value) (interpreterProxy->storeIntegerofObjectwithValue(idx,oop,value)) #define primitiveFail() interpreterProxy->primitiveFail() /* allows accessing Strings in both C and Smalltalk */ #define asciiValue(c) c /*** Constants ***/ /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "ADPCMCodecPlugin VMMaker-oscog.dtl.57 (i)" #else "ADPCMCodecPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveDecodeMono(void); EXPORT(sqInt) primitiveDecodeStereo(void); EXPORT(sqInt) primitiveEncodeMono(void); EXPORT(sqInt) primitiveEncodeStereo(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveDecodeMono(void) { sqInt bit; sqInt bitPosition; sqInt bitsPerSample; sqInt byteIndex; sqInt count; sqInt currentByte; sqInt delta; sqInt deltaSignMask; sqInt deltaValueHighBit; sqInt deltaValueMask; unsigned char *encodedBytes; sqInt frameSizeMask; sqInt i; sqInt index; short int *indexTable; sqInt predicted; sqInt predictedDelta; sqInt rcvr; sqInt remaining; sqInt remaining1; sqInt remaining2; sqInt result; sqInt result1; sqInt result2; sqInt sampleIndex; short int *samples; sqInt shift; sqInt shift1; sqInt shift2; sqInt step; short int *stepSizeTable; rcvr = stackValue(1); count = stackIntegerValue(0); predicted = fetchIntegerofObject(0, rcvr); index = fetchIntegerofObject(1, rcvr); deltaSignMask = fetchIntegerofObject(2, rcvr); deltaValueMask = fetchIntegerofObject(3, rcvr); deltaValueHighBit = fetchIntegerofObject(4, rcvr); frameSizeMask = fetchIntegerofObject(5, rcvr); currentByte = fetchIntegerofObject(6, rcvr); bitPosition = fetchIntegerofObject(7, rcvr); byteIndex = fetchIntegerofObject(8, rcvr); encodedBytes = fetchArrayofObject(9, rcvr); encodedBytes -= 1; samples = fetchArrayofObject(10, rcvr); samples -= 1; sampleIndex = fetchIntegerofObject(12, rcvr); bitsPerSample = fetchIntegerofObject(13, rcvr); stepSizeTable = fetchArrayofObject(14, rcvr); stepSizeTable -= 1; indexTable = fetchArrayofObject(15, rcvr); indexTable -= 1; if (!(successFlag)) { return null; } for (i = 1; i <= count; i += 1) { if ((i & frameSizeMask) == 1) { /* begin nextBits: */ result = 0; remaining = 16; while (1) { shift = remaining - bitPosition; result += ((shift < 0) ? ((usqInt) currentByte >> -shift) : ((usqInt) currentByte << shift)); if (shift > 0) { /* consumed currentByte buffer; fetch next byte */ remaining -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); predicted = result; goto l1; } } l1: /* end nextBits: */; if (predicted > 32767) { predicted -= 65536; } /* begin nextBits: */ result1 = 0; remaining1 = 6; while (1) { shift1 = remaining1 - bitPosition; result1 += ((shift1 < 0) ? ((usqInt) currentByte >> -shift1) : ((usqInt) currentByte << shift1)); if (shift1 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining1 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining1; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); index = result1; goto l2; } } l2: /* end nextBits: */; samples[(sampleIndex += 1)] = predicted; } else { /* begin nextBits: */ result2 = 0; remaining2 = bitsPerSample; while (1) { shift2 = remaining2 - bitPosition; result2 += ((shift2 < 0) ? ((usqInt) currentByte >> -shift2) : ((usqInt) currentByte << shift2)); if (shift2 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining2 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining2; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); delta = result2; goto l3; } } l3: /* end nextBits: */; step = stepSizeTable[index + 1]; predictedDelta = 0; bit = deltaValueHighBit; while (bit > 0) { if ((delta & bit) > 0) { predictedDelta += step; } step = ((usqInt) step >> 1); bit = ((usqInt) bit >> 1); } predictedDelta += step; if ((delta & deltaSignMask) > 0) { predicted -= predictedDelta; } else { predicted += predictedDelta; } if (predicted > 32767) { predicted = 32767; } else { if (predicted < -32768) { predicted = -32768; } } index += indexTable[(delta & deltaValueMask) + 1]; if (index < 0) { index = 0; } else { if (index > 88) { index = 88; } } samples[(sampleIndex += 1)] = predicted; } } if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(0, rcvr, predicted); storeIntegerofObjectwithValue(1, rcvr, index); storeIntegerofObjectwithValue(6, rcvr, currentByte); storeIntegerofObjectwithValue(7, rcvr, bitPosition); storeIntegerofObjectwithValue(8, rcvr, byteIndex); storeIntegerofObjectwithValue(12, rcvr, sampleIndex); pop(1); } EXPORT(sqInt) primitiveDecodeStereo(void) { sqInt bit; sqInt bitPosition; sqInt bitsPerSample; sqInt byteIndex; sqInt count; sqInt currentByte; sqInt deltaLeft; sqInt deltaRight; sqInt deltaSignMask; sqInt deltaValueHighBit; sqInt deltaValueMask; unsigned char *encodedBytes; sqInt frameSizeMask; sqInt i; short int *index; sqInt indexLeft; sqInt indexRight; short int *indexTable; short int *predicted; sqInt predictedDeltaLeft; sqInt predictedDeltaRight; sqInt predictedLeft; sqInt predictedRight; sqInt rcvr; sqInt remaining; sqInt remaining1; sqInt remaining2; sqInt remaining3; sqInt remaining4; sqInt remaining5; sqInt result; sqInt result1; sqInt result2; sqInt result3; sqInt result4; sqInt result5; short int *rightSamples; sqInt sampleIndex; short int *samples; sqInt shift; sqInt shift1; sqInt shift2; sqInt shift3; sqInt shift4; sqInt shift5; sqInt stepLeft; sqInt stepRight; short int *stepSizeTable; rcvr = stackValue(1); count = stackIntegerValue(0); predicted = fetchArrayofObject(0, rcvr); predicted -= 1; index = fetchArrayofObject(1, rcvr); index -= 1; deltaSignMask = fetchIntegerofObject(2, rcvr); deltaValueMask = fetchIntegerofObject(3, rcvr); deltaValueHighBit = fetchIntegerofObject(4, rcvr); frameSizeMask = fetchIntegerofObject(5, rcvr); currentByte = fetchIntegerofObject(6, rcvr); bitPosition = fetchIntegerofObject(7, rcvr); byteIndex = fetchIntegerofObject(8, rcvr); encodedBytes = fetchArrayofObject(9, rcvr); encodedBytes -= 1; samples = fetchArrayofObject(10, rcvr); samples -= 1; rightSamples = fetchArrayofObject(11, rcvr); rightSamples -= 1; sampleIndex = fetchIntegerofObject(12, rcvr); bitsPerSample = fetchIntegerofObject(13, rcvr); stepSizeTable = fetchArrayofObject(14, rcvr); stepSizeTable -= 1; indexTable = fetchArrayofObject(15, rcvr); indexTable -= 1; if (!(successFlag)) { return null; } /* make local copies of decoder state variables */ predictedLeft = predicted[1]; predictedRight = predicted[2]; indexLeft = index[1]; indexRight = index[2]; for (i = 1; i <= count; i += 1) { if ((i & frameSizeMask) == 1) { /* begin nextBits: */ result = 0; remaining = 16; while (1) { shift = remaining - bitPosition; result += ((shift < 0) ? ((usqInt) currentByte >> -shift) : ((usqInt) currentByte << shift)); if (shift > 0) { /* consumed currentByte buffer; fetch next byte */ remaining -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); predictedLeft = result; goto l1; } } l1: /* end nextBits: */; /* begin nextBits: */ result1 = 0; remaining1 = 6; while (1) { shift1 = remaining1 - bitPosition; result1 += ((shift1 < 0) ? ((usqInt) currentByte >> -shift1) : ((usqInt) currentByte << shift1)); if (shift1 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining1 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining1; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); indexLeft = result1; goto l2; } } l2: /* end nextBits: */; /* begin nextBits: */ result2 = 0; remaining2 = 16; while (1) { shift2 = remaining2 - bitPosition; result2 += ((shift2 < 0) ? ((usqInt) currentByte >> -shift2) : ((usqInt) currentByte << shift2)); if (shift2 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining2 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining2; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); predictedRight = result2; goto l3; } } l3: /* end nextBits: */; /* begin nextBits: */ result3 = 0; remaining3 = 6; while (1) { shift3 = remaining3 - bitPosition; result3 += ((shift3 < 0) ? ((usqInt) currentByte >> -shift3) : ((usqInt) currentByte << shift3)); if (shift3 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining3 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining3; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); indexRight = result3; goto l4; } } l4: /* end nextBits: */; if (predictedLeft > 32767) { predictedLeft -= 65536; } if (predictedRight > 32767) { predictedRight -= 65536; } samples[(sampleIndex += 1)] = predictedLeft; rightSamples[sampleIndex] = predictedRight; } else { /* begin nextBits: */ result4 = 0; remaining4 = bitsPerSample; while (1) { shift4 = remaining4 - bitPosition; result4 += ((shift4 < 0) ? ((usqInt) currentByte >> -shift4) : ((usqInt) currentByte << shift4)); if (shift4 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining4 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining4; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); deltaLeft = result4; goto l5; } } l5: /* end nextBits: */; /* begin nextBits: */ result5 = 0; remaining5 = bitsPerSample; while (1) { shift5 = remaining5 - bitPosition; result5 += ((shift5 < 0) ? ((usqInt) currentByte >> -shift5) : ((usqInt) currentByte << shift5)); if (shift5 > 0) { /* consumed currentByte buffer; fetch next byte */ remaining5 -= bitPosition; currentByte = encodedBytes[(byteIndex += 1)]; bitPosition = 8; } else { /* still some bits left in currentByte buffer */ /* mask out the consumed bits: */ bitPosition -= remaining5; currentByte = currentByte & ((((bitPosition - 8) < 0) ? ((usqInt) 255 >> -(bitPosition - 8)) : ((usqInt) 255 << (bitPosition - 8)))); deltaRight = result5; goto l6; } } l6: /* end nextBits: */; stepLeft = stepSizeTable[indexLeft + 1]; stepRight = stepSizeTable[indexRight + 1]; predictedDeltaLeft = predictedDeltaRight = 0; bit = deltaValueHighBit; while (bit > 0) { if ((deltaLeft & bit) > 0) { predictedDeltaLeft += stepLeft; } if ((deltaRight & bit) > 0) { predictedDeltaRight += stepRight; } stepLeft = ((usqInt) stepLeft >> 1); stepRight = ((usqInt) stepRight >> 1); bit = ((usqInt) bit >> 1); } predictedDeltaLeft += stepLeft; predictedDeltaRight += stepRight; if ((deltaLeft & deltaSignMask) > 0) { predictedLeft -= predictedDeltaLeft; } else { predictedLeft += predictedDeltaLeft; } if ((deltaRight & deltaSignMask) > 0) { predictedRight -= predictedDeltaRight; } else { predictedRight += predictedDeltaRight; } if (predictedLeft > 32767) { predictedLeft = 32767; } else { if (predictedLeft < -32768) { predictedLeft = -32768; } } if (predictedRight > 32767) { predictedRight = 32767; } else { if (predictedRight < -32768) { predictedRight = -32768; } } indexLeft += indexTable[(deltaLeft & deltaValueMask) + 1]; if (indexLeft < 0) { indexLeft = 0; } else { if (indexLeft > 88) { indexLeft = 88; } } indexRight += indexTable[(deltaRight & deltaValueMask) + 1]; if (indexRight < 0) { indexRight = 0; } else { if (indexRight > 88) { indexRight = 88; } } samples[(sampleIndex += 1)] = predictedLeft; rightSamples[sampleIndex] = predictedRight; } } predicted[1] = predictedLeft; predicted[2] = predictedRight; index[1] = indexLeft; index[2] = indexRight; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(6, rcvr, currentByte); storeIntegerofObjectwithValue(7, rcvr, bitPosition); storeIntegerofObjectwithValue(8, rcvr, byteIndex); storeIntegerofObjectwithValue(12, rcvr, sampleIndex); pop(1); } EXPORT(sqInt) primitiveEncodeMono(void) { sqInt bestIndex; sqInt bit; sqInt bitPosition; sqInt bitsAvailable; sqInt bitsAvailable1; sqInt bitsAvailable2; sqInt bitsPerSample; sqInt buf; sqInt buf1; sqInt buf2; sqInt bufBits; sqInt bufBits1; sqInt bufBits2; sqInt byteIndex; sqInt count; sqInt currentByte; sqInt delta; sqInt deltaSignMask; sqInt deltaValueHighBit; sqInt diff; sqInt diff1; unsigned char *encodedBytes; sqInt frameSizeMask; sqInt i; sqInt index; short int *indexTable; sqInt j; sqInt p; sqInt predicted; sqInt predictedDelta; sqInt rcvr; sqInt sampleIndex; short int *samples; sqInt shift; sqInt shift1; sqInt shift2; sqInt sign; sqInt step; short int *stepSizeTable; rcvr = stackValue(1); count = stackIntegerValue(0); predicted = fetchIntegerofObject(0, rcvr); index = fetchIntegerofObject(1, rcvr); deltaSignMask = fetchIntegerofObject(2, rcvr); deltaValueHighBit = fetchIntegerofObject(4, rcvr); frameSizeMask = fetchIntegerofObject(5, rcvr); currentByte = fetchIntegerofObject(6, rcvr); bitPosition = fetchIntegerofObject(7, rcvr); byteIndex = fetchIntegerofObject(8, rcvr); encodedBytes = fetchArrayofObject(9, rcvr); encodedBytes -= 1; samples = fetchArrayofObject(10, rcvr); samples -= 1; sampleIndex = fetchIntegerofObject(12, rcvr); bitsPerSample = fetchIntegerofObject(13, rcvr); stepSizeTable = fetchArrayofObject(14, rcvr); stepSizeTable -= 1; indexTable = fetchArrayofObject(15, rcvr); indexTable -= 1; if (!(successFlag)) { return null; } step = stepSizeTable[1]; for (i = 1; i <= count; i += 1) { if ((i & frameSizeMask) == 1) { predicted = samples[(sampleIndex += 1)]; if (((p = predicted)) < 0) { p += 65536; } /* begin nextBits:put: */ buf = p; bufBits = 16; while (1) { bitsAvailable = 8 - bitPosition; /* either left or right shift */ /* append high bits of buf to end of currentByte: */ shift = bitsAvailable - bufBits; currentByte += ((shift < 0) ? ((usqInt) buf >> -shift) : ((usqInt) buf << shift)); if (shift < 0) { encodedBytes[(byteIndex += 1)] = currentByte; bitPosition = 0; /* clear saved high bits of buf: */ currentByte = 0; buf = buf & (((((0 - shift) < 0) ? ((usqInt) 1 >> -(0 - shift)) : ((usqInt) 1 << (0 - shift)))) - 1); bufBits -= bitsAvailable; } else { /* still some bits available in currentByte buffer */ bitPosition += bufBits; goto l1; } } l1: /* end nextBits:put: */; if (i < count) { /* begin indexForDeltaFrom:to: */ diff1 = (samples[sampleIndex + 1]) - predicted; if (diff1 < 0) { diff1 = 0 - diff1; } bestIndex = 63; for (j = 1; j <= 62; j += 1) { if (bestIndex == 63) { if ((stepSizeTable[j]) >= diff1) { bestIndex = j; } } } index = bestIndex; } /* begin nextBits:put: */ buf1 = index; bufBits1 = 6; while (1) { bitsAvailable1 = 8 - bitPosition; /* either left or right shift */ /* append high bits of buf to end of currentByte: */ shift1 = bitsAvailable1 - bufBits1; currentByte += ((shift1 < 0) ? ((usqInt) buf1 >> -shift1) : ((usqInt) buf1 << shift1)); if (shift1 < 0) { encodedBytes[(byteIndex += 1)] = currentByte; bitPosition = 0; /* clear saved high bits of buf: */ currentByte = 0; buf1 = buf1 & (((((0 - shift1) < 0) ? ((usqInt) 1 >> -(0 - shift1)) : ((usqInt) 1 << (0 - shift1)))) - 1); bufBits1 -= bitsAvailable1; } else { /* still some bits available in currentByte buffer */ bitPosition += bufBits1; goto l2; } } l2: /* end nextBits:put: */; } else { /* compute sign and magnitude of difference from the predicted sample */ sign = 0; diff = (samples[(sampleIndex += 1)]) - predicted; if (diff < 0) { sign = deltaSignMask; diff = 0 - diff; } delta = 0; predictedDelta = 0; bit = deltaValueHighBit; while (bit > 0) { if (diff >= step) { delta += bit; predictedDelta += step; diff -= step; } step = ((usqInt) step >> 1); bit = ((usqInt) bit >> 1); } /* compute and clamp new prediction */ predictedDelta += step; if (sign > 0) { predicted -= predictedDelta; } else { predicted += predictedDelta; } if (predicted > 32767) { predicted = 32767; } else { if (predicted < -32768) { predicted = -32768; } } index += indexTable[delta + 1]; if (index < 0) { index = 0; } else { if (index > 88) { index = 88; } } /* output encoded, signed delta */ step = stepSizeTable[index + 1]; /* begin nextBits:put: */ buf2 = sign | delta; bufBits2 = bitsPerSample; while (1) { bitsAvailable2 = 8 - bitPosition; /* either left or right shift */ /* append high bits of buf to end of currentByte: */ shift2 = bitsAvailable2 - bufBits2; currentByte += ((shift2 < 0) ? ((usqInt) buf2 >> -shift2) : ((usqInt) buf2 << shift2)); if (shift2 < 0) { encodedBytes[(byteIndex += 1)] = currentByte; bitPosition = 0; /* clear saved high bits of buf: */ currentByte = 0; buf2 = buf2 & (((((0 - shift2) < 0) ? ((usqInt) 1 >> -(0 - shift2)) : ((usqInt) 1 << (0 - shift2)))) - 1); bufBits2 -= bitsAvailable2; } else { /* still some bits available in currentByte buffer */ bitPosition += bufBits2; goto l3; } } l3: /* end nextBits:put: */; } } if (bitPosition > 0) { encodedBytes[(byteIndex += 1)] = currentByte; } if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(0, rcvr, predicted); storeIntegerofObjectwithValue(1, rcvr, index); storeIntegerofObjectwithValue(6, rcvr, currentByte); storeIntegerofObjectwithValue(7, rcvr, bitPosition); storeIntegerofObjectwithValue(8, rcvr, byteIndex); storeIntegerofObjectwithValue(12, rcvr, sampleIndex); pop(1); } /* not yet implemented */ EXPORT(sqInt) primitiveEncodeStereo(void) { sqInt count; sqInt rcvr; rcvr = stackValue(1); count = stackIntegerValue(0); if (!(successFlag)) { return null; } success(0); if (!(successFlag)) { return null; } pop(1); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* ADPCMCodecPlugin_exports[][3] = { {"ADPCMCodecPlugin", "getModuleName", (void*)getModuleName}, {"ADPCMCodecPlugin", "primitiveDecodeMono", (void*)primitiveDecodeMono}, {"ADPCMCodecPlugin", "primitiveDecodeStereo", (void*)primitiveDecodeStereo}, {"ADPCMCodecPlugin", "primitiveEncodeMono", (void*)primitiveEncodeMono}, {"ADPCMCodecPlugin", "primitiveEncodeStereo", (void*)primitiveEncodeStereo}, {"ADPCMCodecPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/AsynchFilePlugin/AsynchFilePlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from AsynchFilePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "AsynchFilePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "AsynchFilePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static AsyncFile * asyncFileValueOf(sqInt oop); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); EXPORT(void) moduleUnloaded(char *aModuleName); static sqInt msg(char *s); EXPORT(sqInt) primitiveAsyncFileClose(void); EXPORT(sqInt) primitiveAsyncFileOpen(void); EXPORT(sqInt) primitiveAsyncFileReadResult(void); EXPORT(sqInt) primitiveAsyncFileReadStart(void); EXPORT(sqInt) primitiveAsyncFileWriteResult(void); EXPORT(sqInt) primitiveAsyncFileWriteStart(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "AsynchFilePlugin VMMaker-oscog.dtl.57 (i)" #else "AsynchFilePlugin VMMaker-oscog.dtl.57 (e)" #endif ; static void * sCOAFfn; /* Return a pointer to the first byte of the async file record within the given Smalltalk bytes object, or nil if oop is not an async file record. */ static AsyncFile * asyncFileValueOf(sqInt oop) { interpreterProxy->success((!((oop & 1))) && ((interpreterProxy->isBytes(oop)) && ((interpreterProxy->slotSizeOf(oop)) == (sizeof(AsyncFile))))); if (interpreterProxy->failed()) { return null; } return (AsyncFile *) (oop + 4); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* Initialise the module */ EXPORT(sqInt) initialiseModule(void) { sCOAFfn = interpreterProxy->ioLoadFunctionFrom("secCanOpenAsyncFileOfSizeWritable", "SecurityPlugin"); return asyncFileInit(); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(void) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SecurityPlugin")) == 0) { /* The security plugin just shut down. How odd. Zero the function pointer we have into it */ sCOAFfn = 0; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveAsyncFileClose(void) { AsyncFile *f; sqInt fh; fh = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } f = asyncFileValueOf(fh); asyncFileClose(f); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveAsyncFileOpen(void) { AsyncFile *f; char *fileName; sqInt fileNameSize; sqInt fOop; sqInt okToOpen; sqInt semaIndex; sqInt writeFlag; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); fileName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); writeFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); semaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ fileNameSize = interpreterProxy->slotSizeOf(((int) fileName) - 4); if (sCOAFfn != 0) { okToOpen = ((sqInt (*) (char *, sqInt, sqInt)) sCOAFfn)(fileName, fileNameSize, writeFlag); if (!(okToOpen)) { interpreterProxy->primitiveFail(); return null; } } fOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(AsyncFile)); f = asyncFileValueOf(fOop); if (!(interpreterProxy->failed())) { asyncFileOpen(f, (int)fileName, fileNameSize, writeFlag, semaIndex); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, fOop); return null; } EXPORT(sqInt) primitiveAsyncFileReadResult(void) { sqInt buffer; sqInt bufferPtr; sqInt bufferSize; sqInt count; AsyncFile *f; sqInt fhandle; sqInt num; sqInt r; sqInt start; sqInt startIndex; sqInt _return_value; fhandle = interpreterProxy->stackValue(3); buffer = interpreterProxy->stackValue(2); start = interpreterProxy->stackIntegerValue(1); num = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } f = asyncFileValueOf(fhandle); count = num; startIndex = start; /* in bytes or words */ bufferSize = interpreterProxy->slotSizeOf(buffer); if (interpreterProxy->isWords(buffer)) { /* covert word counts to byte counts */ count = count * 4; startIndex = ((startIndex - 1) * 4) + 1; bufferSize = bufferSize * 4; } interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= bufferSize)); /* adjust for zero-origin indexing */ bufferPtr = ((((int) (interpreterProxy->firstIndexableField(buffer)))) + startIndex) - 1; if (!(interpreterProxy->failed())) { r = asyncFileReadResult(f, bufferPtr, count); } _return_value = interpreterProxy->integerObjectOf(r); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveAsyncFileReadStart(void) { sqInt count; AsyncFile *f; sqInt fHandle; sqInt fPosition; fHandle = interpreterProxy->stackValue(2); fPosition = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } f = asyncFileValueOf(fHandle); asyncFileReadStart(f, fPosition, count); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveAsyncFileWriteResult(void) { AsyncFile *f; sqInt fHandle; sqInt r; sqInt _return_value; fHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } f = asyncFileValueOf(fHandle); r = asyncFileWriteResult(f); _return_value = interpreterProxy->integerObjectOf(r); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveAsyncFileWriteStart(void) { sqInt buffer; sqInt bufferPtr; sqInt bufferSize; sqInt count; AsyncFile *f; sqInt fHandle; sqInt fPosition; sqInt num; sqInt start; sqInt startIndex; fHandle = interpreterProxy->stackValue(4); fPosition = interpreterProxy->stackIntegerValue(3); buffer = interpreterProxy->stackValue(2); start = interpreterProxy->stackIntegerValue(1); num = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } f = asyncFileValueOf(fHandle); if (interpreterProxy->failed()) { return null; } count = num; startIndex = start; /* in bytes or words */ bufferSize = interpreterProxy->slotSizeOf(buffer); if (interpreterProxy->isWords(buffer)) { /* covert word counts to byte counts */ count = count * 4; startIndex = ((startIndex - 1) * 4) + 1; bufferSize = bufferSize * 4; } interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= bufferSize)); /* adjust for zero-origin indexing */ bufferPtr = ((((int) (interpreterProxy->firstIndexableField(buffer)))) + startIndex) - 1; if (!(interpreterProxy->failed())) { asyncFileWriteStart(f, fPosition, bufferPtr, count); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Initialise the module */ EXPORT(sqInt) shutdownModule(void) { return asyncFileShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* AsynchFilePlugin_exports[][3] = { {"AsynchFilePlugin", "getModuleName", (void*)getModuleName}, {"AsynchFilePlugin", "initialiseModule", (void*)initialiseModule}, {"AsynchFilePlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"AsynchFilePlugin", "primitiveAsyncFileClose", (void*)primitiveAsyncFileClose}, {"AsynchFilePlugin", "primitiveAsyncFileOpen", (void*)primitiveAsyncFileOpen}, {"AsynchFilePlugin", "primitiveAsyncFileReadResult", (void*)primitiveAsyncFileReadResult}, {"AsynchFilePlugin", "primitiveAsyncFileReadStart", (void*)primitiveAsyncFileReadStart}, {"AsynchFilePlugin", "primitiveAsyncFileWriteResult", (void*)primitiveAsyncFileWriteResult}, {"AsynchFilePlugin", "primitiveAsyncFileWriteStart", (void*)primitiveAsyncFileWriteStart}, {"AsynchFilePlugin", "setInterpreter", (void*)setInterpreter}, {"AsynchFilePlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/B2DPlugin/B2DPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from BalloonEnginePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "BalloonEnginePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ #define BEBalloonEngineSize 12 #define BEBitBltIndex 2 #define BEFormsIndex 3 #define BESpanIndex 1 #define BEWorkBufferIndex 0 #define ETBalloonEdgeDataSize 6 #define ETIndexIndex 0 #define ETLinesIndex 4 #define ETXValueIndex 1 #define ETYValueIndex 2 #define ETZValueIndex 3 #define FTBalloonFillDataSize 6 #define FTIndexIndex 0 #define FTMaxXIndex 2 #define FTMinXIndex 1 #define FTYValueIndex 3 #define GBBaseSize 16 #define GBBitmapDepth 12 #define GBBitmapHeight 11 #define GBBitmapRaster 14 #define GBBitmapSize 13 #define GBBitmapWidth 10 #define GBColormapOffset 18 #define GBColormapSize 15 #define GBEndX 14 #define GBEndY 15 #define GBFinalX 21 #define GBMBaseSize 18 #define GBTileFlag 16 #define GBUpdateData 10 #define GBUpdateDDX 4 #define GBUpdateDDY 5 #define GBUpdateDX 2 #define GBUpdateDY 3 #define GBUpdateX 0 #define GBUpdateY 1 #define GBViaX 12 #define GBViaY 13 #define GBWideEntry 18 #define GBWideExit 19 #define GBWideExtent 20 #define GBWideFill 16 #define GBWideSize 28 #define GBWideUpdateData 22 #define GBWideWidth 17 #define GEBaseEdgeSize 10 #define GEBaseFillSize 4 #define GEEdgeFillsInvalid 0x10000 #define GEFAlreadyFailed 100 #define GEFBadPoint 121 #define GEFBitBltLoadFailed 122 #define GEFClassMismatch 114 #define GEFEdgeDataTooSmall 112 #define GEFEngineIsInteger 101 #define GEFEngineIsWords 102 #define GEFEngineStopped 104 #define GEFEngineTooSmall 103 #define GEFEntityCheckFailed 120 #define GEFEntityLoadFailed 119 #define GEFFillDataTooSmall 113 #define GEFFormLoadFailed 123 #define GEFillIndexLeft 8 #define GEFillIndexRight 9 #define GEFSizeMismatch 115 #define GEFWorkBufferBadMagic 108 #define GEFWorkBufferIsInteger 105 #define GEFWorkBufferIsPointers 106 #define GEFWorkBufferStartWrong 110 #define GEFWorkBufferTooSmall 107 #define GEFWorkBufferWrongSize 109 #define GEFWorkTooBig 111 #define GEFWrongEdge 118 #define GEFWrongFill 117 #define GEFWrongState 116 #define GENumLines 7 #define GEObjectIndex 2 #define GEObjectLength 1 #define GEObjectType 0 #define GEPrimitiveBezier 6 #define GEPrimitiveClippedBitmapFill 0x400 #define GEPrimitiveEdge 2 #define GEPrimitiveEdgeMask 0xFF #define GEPrimitiveFill 0x100 #define GEPrimitiveFillMask 0xFF00 #define GEPrimitiveLine 4 #define GEPrimitiveLinearGradientFill 0x200 #define GEPrimitiveRadialGradientFill 0x300 #define GEPrimitiveTypeMask 0xFFFF #define GEPrimitiveWide 1 #define GEPrimitiveWideBezier 7 #define GEPrimitiveWideLine 5 #define GEPrimitiveWideMask 0xFE #define GErrorAETEntry 6 #define GErrorBadState 2 #define GErrorFillEntry 5 #define GErrorGETEntry 4 #define GErrorNeedFlush 3 #define GErrorNoMoreSpace 1 #define GEStateAddingFromGET 1 #define GEStateBlitBuffer 5 #define GEStateCompleted 8 #define GEStateScanningAET 3 #define GEStateUnlocked 0 #define GEStateUpdateEdges 6 #define GEStateWaitingChange 7 #define GEStateWaitingForEdge 2 #define GEStateWaitingForFill 4 #define GEXValue 4 #define GEYValue 5 #define GEZValue 6 #define GFDirectionX 6 #define GFDirectionY 7 #define GFNormalX 8 #define GFNormalY 9 #define GFOriginX 4 #define GFOriginY 5 #define GFRampLength 10 #define GFRampOffset 12 #define GGBaseSize 12 #define GLBaseSize 16 #define GLEndX 14 #define GLEndY 15 #define GLError 13 #define GLErrorAdjDown 15 #define GLErrorAdjUp 14 #define GLWideEntry 18 #define GLWideExit 19 #define GLWideExtent 20 #define GLWideFill 16 #define GLWideSize 21 #define GLWideWidth 17 #define GLXDirection 10 #define GLXIncrement 12 #define GLYDirection 11 #define GWAAColorMask 0x33 #define GWAAColorShift 50 #define GWAAHalfPixel 53 #define GWAALevel 48 #define GWAAScanMask 0x34 #define GWAAShift 49 #define GWAETStart 13 #define GWAETUsed 14 #define GWBezierHeightSubdivisions 109 #define GWBezierLineConversions 111 #define GWBezierMonotonSubdivisions 108 #define GWBezierOverflowSubdivisions 110 #define GWBufferTop 10 #define GWClearSpanBuffer 69 #define GWClipMaxX 43 #define GWClipMaxY 45 #define GWClipMinX 42 #define GWClipMinY 44 #define GWColorTransform 24 #define GWCountAddAETEntry 97 #define GWCountChangeAETEntry 107 #define GWCountDisplaySpan 103 #define GWCountFinishTest 93 #define GWCountInitializing 91 #define GWCountMergeFill 101 #define GWCountNextAETEntry 105 #define GWCountNextFillEntry 99 #define GWCountNextGETEntry 95 #define GWCurrentY 88 #define GWCurrentZ 113 #define GWDestOffsetX 46 #define GWDestOffsetY 47 #define GWEdgeTransform 18 #define GWFillMaxX 37 #define GWFillMaxY 39 #define GWFillMinX 36 #define GWFillMinY 38 #define GWFillOffsetX 40 #define GWFillOffsetY 41 #define GWGETStart 11 #define GWGETUsed 12 #define GWHasColorTransform 17 #define GWHasEdgeTransform 16 #define GWHeaderSize 128 #define GWLastExportedEdge 65 #define GWLastExportedFill 66 #define GWLastExportedLeftX 67 #define GWLastExportedRightX 68 #define GWMagicIndex 0 #define GWMagicNumber 1097753705 #define GWMinimalSize 256 #define GWNeedsFlush 63 #define GWObjStart 8 #define GWObjUsed 9 #define GWPoint1 80 #define GWPoint2 82 #define GWPoint3 84 #define GWPoint4 86 #define GWPointListFirst 70 #define GWSize 1 #define GWSpanEnd 34 #define GWSpanEndAA 35 #define GWSpanSize 33 #define GWSpanStart 32 #define GWState 2 #define GWStopReason 64 #define GWTimeAddAETEntry 96 #define GWTimeChangeAETEntry 106 #define GWTimeDisplaySpan 102 #define GWTimeFinishTest 92 #define GWTimeInitializing 90 #define GWTimeMergeFill 100 #define GWTimeNextAETEntry 104 #define GWTimeNextFillEntry 98 #define GWTimeNextGETEntry 94 #define PrimErrBadArgument 3 #define PrimErrBadNumArgs 5 /*** Function Prototypes ***/ static sqInt aaColorMaskGet(void); static sqInt aaColorMaskPut(sqInt value); static sqInt aaColorShiftGet(void); static sqInt aaColorShiftPut(sqInt value); static sqInt aaFirstPixelFromto(sqInt leftX, sqInt rightX); static sqInt aaHalfPixelGet(void); static sqInt aaHalfPixelPut(sqInt value); static sqInt aaLastPixelFromto(sqInt leftX, sqInt rightX); static sqInt aaLevelGet(void); static sqInt aaLevelPut(sqInt value); static sqInt aaScanMaskGet(void); static sqInt aaScanMaskPut(sqInt value); static sqInt aaShiftGet(void); static sqInt aaShiftPut(sqInt value); static sqInt absoluteSquared8Dot24(sqInt value); static sqInt accurateLengthOfwith(sqInt deltaX, sqInt deltaY); static sqInt addEdgeToGET(sqInt edge); static sqInt adjustAALevel(void); static sqInt adjustWideBezierLeftwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOffset, sqInt endX); static sqInt adjustWideBezierRightwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOffset, sqInt endX); static sqInt adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX); static sqInt aetStartGet(void); static sqInt aetStartPut(sqInt value); static sqInt aetUsedGet(void); static sqInt aetUsedPut(sqInt value); static sqInt allocateAETEntry(sqInt nSlots); static sqInt allocateBezier(void); static sqInt allocateBezierStackEntry(void); static sqInt allocateBitmapFillcolormap(sqInt cmSize, int *cmBits); static sqInt allocateGETEntry(sqInt nSlots); static sqInt allocateGradientFillrampWidthisRadial(int *ramp, sqInt rampWidth, sqInt isRadial); static sqInt allocateLine(void); static sqInt allocateObjEntry(sqInt nSlots); static sqInt allocateStackEntry(sqInt nSlots); static sqInt allocateStackFillEntry(void); static sqInt allocateWideBezier(void); static sqInt allocateWideLine(void); static sqInt areEdgeFillsValid(sqInt edge); static sqInt assureValuebetweenand(sqInt val1, sqInt val2, sqInt val3); static sqInt bezierEndXOf(sqInt bezier); static sqInt bezierEndXOfput(sqInt bezier, sqInt value); static sqInt bezierEndYOf(sqInt bezier); static sqInt bezierEndYOfput(sqInt bezier, sqInt value); static sqInt bezierFinalXOf(sqInt bezier); static sqInt bezierFinalXOfput(sqInt bezier, sqInt value); static int * bezierUpdateDataOf(sqInt bezier); static sqInt bezierViaXOf(sqInt bezier); static sqInt bezierViaXOfput(sqInt bezier, sqInt value); static sqInt bezierViaYOf(sqInt bezier); static sqInt bezierViaYOfput(sqInt bezier, sqInt value); static sqInt bitmapCmSizeOf(sqInt bmFill); static sqInt bitmapCmSizeOfput(sqInt bmFill, sqInt value); static sqInt bitmapDepthOf(sqInt bmFill); static sqInt bitmapDepthOfput(sqInt bmFill, sqInt value); static sqInt bitmapHeightOf(sqInt bmFill); static sqInt bitmapHeightOfput(sqInt bmFill, sqInt value); static sqInt bitmapRasterOf(sqInt bmFill); static sqInt bitmapRasterOfput(sqInt bmFill, sqInt value); static sqInt bitmapSizeOf(sqInt bmFill); static sqInt bitmapSizeOfput(sqInt bmFill, sqInt value); static sqInt bitmapTileFlagOf(sqInt bmFill); static sqInt bitmapTileFlagOfput(sqInt bmFill, sqInt value); static sqInt bitmapValuebitsatXy(sqInt bmFill, sqInt bits, sqInt xp, sqInt yp); static sqInt bitmapWidthOf(sqInt bmFill); static sqInt bitmapWidthOfput(sqInt bmFill, sqInt value); static sqInt bzEndX(sqInt index); static sqInt bzEndXput(sqInt index, sqInt value); static sqInt bzEndY(sqInt index); static sqInt bzEndYput(sqInt index, sqInt value); static sqInt bzStartX(sqInt index); static sqInt bzStartXput(sqInt index, sqInt value); static sqInt bzStartY(sqInt index); static sqInt bzStartYput(sqInt index, sqInt value); static sqInt bzViaX(sqInt index); static sqInt bzViaXput(sqInt index, sqInt value); static sqInt bzViaY(sqInt index); static sqInt bzViaYput(sqInt index, sqInt value); static sqInt checkCompressedFillIndexListmaxsegments(sqInt fillList, sqInt maxIndex, sqInt nSegs); static sqInt checkCompressedFills(sqInt indexList); static sqInt checkCompressedLineWidthssegments(sqInt lineWidthList, sqInt nSegments); static sqInt checkCompressedPointssegments(sqInt points, sqInt nSegments); static sqInt checkCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(sqInt points, sqInt nSegments, sqInt leftFills, sqInt rightFills, sqInt lineWidths, sqInt lineFills, sqInt fillIndexList); static sqInt checkedAddBezierToGET(sqInt bezier); static sqInt checkedAddEdgeToGET(sqInt edge); static sqInt checkedAddLineToGET(sqInt line); static double * circleCosTable(void); static double * circleSinTable(void); static sqInt clampValuemax(sqInt value, sqInt maxValue); static sqInt clearSpanBuffer(void); static sqInt clearSpanBufferGet(void); static sqInt clearSpanBufferPut(sqInt value); static sqInt clipMaxXGet(void); static sqInt clipMaxXPut(sqInt value); static sqInt clipMaxYGet(void); static sqInt clipMaxYPut(sqInt value); static sqInt clipMinXGet(void); static sqInt clipMinXPut(sqInt value); static sqInt clipMinYGet(void); static sqInt clipMinYPut(sqInt value); static int * colormapOf(sqInt bmFill); static float * colorTransform(void); static sqInt computeBezierSplitAtHalf(sqInt index); static sqInt computeBeziersplitAt(sqInt index, double param); static sqInt computeFinalWideBezierValueswidth(sqInt bezier, sqInt lineWidth); static sqInt computeSqrt(sqInt length2); static sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt yValue); static sqInt createGlobalEdgeTable(void); static sqInt currentYGet(void); static sqInt currentYPut(sqInt value); static sqInt currentZGet(void); static sqInt currentZPut(sqInt value); static sqInt destOffsetXGet(void); static sqInt destOffsetXPut(sqInt value); static sqInt destOffsetYGet(void); static sqInt destOffsetYPut(sqInt value); static sqInt displaySpanBufferAt(sqInt y); static sqInt drawWideEdgefrom(sqInt edge, sqInt leftX); static sqInt edgeFillsInvalidate(sqInt edge); static sqInt edgeFillsValidate(sqInt edge); static sqInt edgeLeftFillOf(sqInt edge); static sqInt edgeLeftFillOfput(sqInt edge, sqInt value); static sqInt edgeNumLinesOf(sqInt edge); static sqInt edgeNumLinesOfput(sqInt edge, sqInt value); static sqInt edgeRightFillOf(sqInt edge); static sqInt edgeRightFillOfput(sqInt edge, sqInt value); static float * edgeTransform(void); static sqInt edgeTypeOf(sqInt edge); static sqInt edgeXValueOf(sqInt edge); static sqInt edgeXValueOfput(sqInt edge, sqInt value); static sqInt edgeYValueOf(sqInt edge); static sqInt edgeYValueOfput(sqInt edge, sqInt value); static sqInt edgeZValueOf(sqInt edge); static sqInt edgeZValueOfput(sqInt edge, sqInt value); static sqInt errorWrongIndex(void); static sqInt estimatedLengthOfwith(sqInt deltaX, sqInt deltaY); static sqInt fillAllFromto(sqInt leftX, sqInt rightX); static sqInt fillBitmapSpan(void); static sqInt fillBitmapSpanAAfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue); static sqInt fillBitmapSpanfromto(int *bits, sqInt leftX, sqInt rightX); static sqInt fillBitmapSpanfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue); static sqInt fillColorSpanAAx0x1(sqInt pixelValue32, sqInt leftX, sqInt rightX); static sqInt fillColorSpanfromto(sqInt pixelValue32, sqInt leftX, sqInt rightX); static sqInt fillDirectionXOf(sqInt fill); static sqInt fillDirectionXOfput(sqInt fill, sqInt value); static sqInt fillDirectionYOf(sqInt fill); static sqInt fillDirectionYOfput(sqInt fill, sqInt value); static sqInt fillLinearGradient(void); static sqInt fillLinearGradientAArampdsdsXfromto(sqInt fill, int *ramp, sqInt deltaS, sqInt dsX, sqInt leftX, sqInt rightX); static sqInt fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue); static sqInt fillMaxXGet(void); static sqInt fillMaxXPut(sqInt value); static sqInt fillMaxYGet(void); static sqInt fillMaxYPut(sqInt value); static sqInt fillMinXGet(void); static sqInt fillMinXPut(sqInt value); static sqInt fillMinYGet(void); static sqInt fillMinYPut(sqInt value); static sqInt fillNormalXOf(sqInt fill); static sqInt fillNormalXOfput(sqInt fill, sqInt value); static sqInt fillNormalYOf(sqInt fill); static sqInt fillNormalYOfput(sqInt fill, sqInt value); static sqInt fillOffsetXGet(void); static sqInt fillOffsetXPut(sqInt value); static sqInt fillOffsetYGet(void); static sqInt fillOffsetYPut(sqInt value); static sqInt fillOriginXOf(sqInt fill); static sqInt fillOriginXOfput(sqInt fill, sqInt value); static sqInt fillOriginYOf(sqInt fill); static sqInt fillOriginYOfput(sqInt fill, sqInt value); static sqInt fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX); static sqInt fillRadialDecreasingrampdeltaSTdsXdtXfromto(sqInt fill, sqInt ramp, sqInt deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX); static sqInt fillRadialGradient(void); static sqInt fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue); static sqInt fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX); static sqInt fillRadialIncreasingrampdeltaSTdsXdtXfromto(sqInt fill, sqInt ramp, sqInt deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX); static sqInt fillSortsbefore(sqInt fillEntry1, sqInt fillEntry2); static sqInt fillSpanfromto(unsigned int fill, sqInt leftX, sqInt rightX); static sqInt fillTypeOf(sqInt fill); static sqInt findNextAETEdgeFrom(sqInt leftEdge); static sqInt findNextExternalEntryFromGET(void); static sqInt findNextExternalFillFromAET(void); static sqInt findNextExternalUpdateFromAET(void); static sqInt findStackFilldepth(sqInt fillIndex, sqInt depth); static sqInt finishedProcessing(void); static sqInt firstPointListGet(void); static sqInt firstPointListPut(sqInt value); static sqInt freeStackFillEntry(void); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt getSortsbefore(sqInt edge1, sqInt edge2); static sqInt getStartGet(void); static sqInt getStartPut(sqInt value); static sqInt getUsedGet(void); static sqInt getUsedPut(sqInt value); static sqInt gradientRampLengthOf(sqInt fill); static sqInt gradientRampLengthOfput(sqInt fill, sqInt value); static int * gradientRampOf(sqInt fill); static sqInt halt(void); static sqInt hasColorTransform(void); static sqInt hasColorTransformGet(void); static sqInt hasColorTransformPut(sqInt value); static sqInt hasEdgeTransform(void); static sqInt hasEdgeTransformGet(void); static sqInt hasEdgeTransformPut(sqInt value); static sqInt hideFilldepth(sqInt fillIndex, sqInt depth); static sqInt incrementPointby(int *point, sqInt delta); static sqInt incrementStatby(sqInt statIndex, sqInt value); static sqInt indexForInsertingIntoAET(sqInt edge); static sqInt initColorTransform(void); static sqInt initEdgeTransform(void); EXPORT(sqInt) initialiseModule(void); static sqInt initializeGETProcessing(void); static sqInt insertEdgeIntoAET(sqInt edge); static sqInt insertToAETbeforeIndex(sqInt edge, sqInt index); static sqInt isBezier(sqInt bezier); static sqInt isEdge(sqInt edge); static sqInt isFillColor(sqInt fill); static sqInt isFillOkay(sqInt fill); static sqInt isFill(sqInt fill); static sqInt isLine(sqInt line); static sqInt isObject(sqInt obj); static sqInt isRealFill(sqInt fill); static sqInt isStackEntry(sqInt entry); static sqInt isStackIndex(sqInt index); static sqInt isWideBezier(sqInt bezier); static sqInt isWideLine(sqInt line); static sqInt isWide(sqInt object); static sqInt lastExportedEdgeGet(void); static sqInt lastExportedEdgePut(sqInt value); static sqInt lastExportedFillGet(void); static sqInt lastExportedFillPut(sqInt value); static sqInt lastExportedLeftXGet(void); static sqInt lastExportedLeftXPut(sqInt value); static sqInt lastExportedRightXGet(void); static sqInt lastExportedRightXPut(sqInt value); static sqInt lineEndXOf(sqInt line); static sqInt lineEndXOfput(sqInt line, sqInt value); static sqInt lineEndYOf(sqInt line); static sqInt lineEndYOfput(sqInt line, sqInt value); static sqInt lineErrorAdjDownOf(sqInt line); static sqInt lineErrorAdjDownOfput(sqInt line, sqInt value); static sqInt lineErrorAdjUpOf(sqInt line); static sqInt lineErrorAdjUpOfput(sqInt line, sqInt value); static sqInt lineErrorOf(sqInt line); static sqInt lineErrorOfput(sqInt line, sqInt value); static sqInt lineXDirectionOf(sqInt line); static sqInt lineXDirectionOfput(sqInt line, sqInt value); static sqInt lineXIncrementOf(sqInt line); static sqInt lineXIncrementOfput(sqInt line, sqInt value); static sqInt lineYDirectionOf(sqInt line); static sqInt lineYDirectionOfput(sqInt line, sqInt value); static sqInt loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqInt wideFlag); static sqInt loadArrayPolygonnPointsfilllineWidthlineFill(sqInt points, sqInt nPoints, sqInt fillIndex, sqInt lineWidth, sqInt lineFill); static sqInt loadArrayShapenSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill); static sqInt loadArrayTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadBeziersegmentleftFillrightFilloffset(sqInt bezier, sqInt index, sqInt leftFillIndex, sqInt rightFillIndex, sqInt yOffset); static sqInt loadBitBltFrom(sqInt bbObj); static sqInt loadBitmapFillcolormaptilefromalongnormalxIndex(sqInt formOop, sqInt cmOop, sqInt tileFlag, int *point1, int *point2, int *point3, sqInt xIndex); static int * loadBitsFrom(sqInt bmFill); static sqInt loadColorTransformFrom(sqInt transformOop); static sqInt loadCompressedSegmentfromshortleftFillrightFilllineWidthlineColor(sqInt segmentIndex, sqInt points, sqInt pointsShort, sqInt leftFill, sqInt rightFill, sqInt lineWidth, sqInt lineFill); static sqInt loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList, sqInt pointsShort); static sqInt loadEdgeStateFrom(sqInt edgeOop); static sqInt loadEdgeTransformFrom(sqInt transformOop); static sqInt loadFillOrientationfromalongnormalwidthheight(sqInt fill, int *point1, int *point2, int *point3, sqInt fillWidth, sqInt fillHeight); static sqInt loadFormsFrom(sqInt arrayOop); static sqInt loadGradientFillfromalongnormalisRadial(sqInt rampOop, int *point1, int *point2, int *point3, sqInt isRadial); static sqInt loadLinefromtooffsetleftFillrightFill(sqInt line, int *point1, int *point2, sqInt yOffset, sqInt leftFill, sqInt rightFill); static sqInt loadOvalSegmentwhcxcy(sqInt seg, sqInt w, sqInt h, sqInt cx, sqInt cy); static sqInt loadOvallineFillleftFillrightFill(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill); static sqInt loadPointIntAtfrom(sqInt index, sqInt intArray); static short loadPointShortAtfrom(sqInt index, sqInt shortArray); static sqInt loadPointfrom(int *pointArray, sqInt pointOop); static sqInt loadPolygonnPointsfilllineWidthlineFillpointsShort(int *points, sqInt nPoints, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt isShort); static sqInt loadRectanglelineFillleftFillrightFill(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill); static sqInt loadRenderingState(void); static sqInt loadShapenSegmentsfilllineWidthlineFillpointsShort(int *points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt pointsShort); static sqInt loadSpanBufferFrom(sqInt spanOop); static sqInt loadTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadWideBezierlineFillleftFillrightFilln(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill, sqInt nSegments); static sqInt loadWideLinefromtolineFillleftFillrightFill(sqInt lineWidth, int *p1, int *p2, sqInt lineFill, sqInt leftFill, sqInt rightFill); static sqInt loadWordTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadWorkBufferFrom(sqInt wbOop); static sqInt magicNumberGet(void); static sqInt magicNumberPut(sqInt value); static sqInt makeRectFromPoints(void); static sqInt makeUnsignedFrom(sqInt someIntegerValue); EXPORT(sqInt) moduleUnloaded(char *aModuleName); static sqInt moveAETEntryFromedgex(sqInt index, sqInt edge, sqInt xValue); static sqInt msg(char *s); static sqInt needAvailableSpace(sqInt nSlots); static sqInt needsFlush(void); static sqInt needsFlushGet(void); static sqInt needsFlushPut(sqInt value); static sqInt objectHeaderOf(sqInt obj); static sqInt objectIndexOf(sqInt obj); static sqInt objectIndexOfput(sqInt obj, sqInt value); static sqInt objectLengthOf(sqInt obj); static sqInt objectLengthOfput(sqInt obj, sqInt value); static sqInt objectTypeOf(sqInt obj); static sqInt objectTypeOfput(sqInt obj, sqInt value); static sqInt objStartGet(void); static sqInt objStartPut(sqInt value); static sqInt objUsedGet(void); static sqInt objUsedPut(sqInt value); static sqInt objat(sqInt object, sqInt index); static sqInt objatput(sqInt object, sqInt index, sqInt value); static sqInt offsetFromWidth(sqInt lineWidth); static int * point1Get(void); static int * point2Get(void); static int * point3Get(void); static int * point4Get(void); static sqInt postDisplayAction(void); EXPORT(sqInt) primitiveAbortProcessing(void); EXPORT(sqInt) primitiveAddActiveEdgeEntry(void); EXPORT(sqInt) primitiveAddBezier(void); EXPORT(sqInt) primitiveAddBezierShape(void); EXPORT(sqInt) primitiveAddBitmapFill(void); EXPORT(sqInt) primitiveAddCompressedShape(void); EXPORT(sqInt) primitiveAddGradientFill(void); EXPORT(sqInt) primitiveAddLine(void); EXPORT(sqInt) primitiveAddOval(void); EXPORT(sqInt) primitiveAddPolygon(void); EXPORT(sqInt) primitiveAddRect(void); EXPORT(sqInt) primitiveChangedActiveEdgeEntry(void); EXPORT(sqInt) primitiveCopyBuffer(void); EXPORT(sqInt) primitiveDisplaySpanBuffer(void); EXPORT(sqInt) primitiveDoProfileStats(void); EXPORT(sqInt) primitiveFinishedProcessing(void); EXPORT(sqInt) primitiveGetAALevel(void); EXPORT(sqInt) primitiveGetBezierStats(void); EXPORT(sqInt) primitiveGetClipRect(void); EXPORT(sqInt) primitiveGetCounts(void); EXPORT(sqInt) primitiveGetDepth(void); EXPORT(sqInt) primitiveGetFailureReason(void); EXPORT(sqInt) primitiveGetOffset(void); EXPORT(sqInt) primitiveGetTimes(void); EXPORT(sqInt) primitiveInitializeBuffer(void); EXPORT(sqInt) primitiveInitializeProcessing(void); EXPORT(sqInt) primitiveMergeFillFrom(void); EXPORT(sqInt) primitiveNeedsFlush(void); EXPORT(sqInt) primitiveNeedsFlushPut(void); EXPORT(sqInt) primitiveNextActiveEdgeEntry(void); EXPORT(sqInt) primitiveNextFillEntry(void); EXPORT(sqInt) primitiveNextGlobalEdgeEntry(void); EXPORT(sqInt) primitiveRegisterExternalEdge(void); EXPORT(sqInt) primitiveRegisterExternalFill(void); EXPORT(sqInt) primitiveRenderImage(void); EXPORT(sqInt) primitiveRenderScanline(void); EXPORT(sqInt) primitiveSetAALevel(void); EXPORT(sqInt) primitiveSetBitBltPlugin(void); EXPORT(sqInt) primitiveSetClipRect(void); EXPORT(sqInt) primitiveSetColorTransform(void); EXPORT(sqInt) primitiveSetDepth(void); EXPORT(sqInt) primitiveSetEdgeTransform(void); EXPORT(sqInt) primitiveSetOffset(void); static sqInt proceedRenderingImage(void); static sqInt proceedRenderingScanline(void); static sqInt quickLoadEngineFrom(sqInt engineOop); static sqInt quickLoadEngineFromrequiredState(sqInt oop, sqInt requiredState); static sqInt quickLoadEngineFromrequiredStateor(sqInt oop, sqInt requiredState, sqInt alternativeState); static sqInt quickRemoveInvalidFillsAt(sqInt leftX); static sqInt quickSortGlobalEdgeTablefromto(int *array, sqInt i, sqInt j); static sqInt removeFirstAETEntry(void); static sqInt repeatValuemax(sqInt delta, sqInt maxValue); static sqInt resetGraphicsEngineStats(void); static sqInt resortFirstAETEntry(void); static sqInt returnWideBezierFill(void); static sqInt returnWideBezierWidth(void); static sqInt returnWideLineFill(void); static sqInt returnWideLineWidth(void); static int * rShiftTable(void); static sqInt setAALevel(sqInt level); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt shortRunLengthAtfrom(sqInt i, sqInt runArray); static sqInt shortRunValueAtfrom(sqInt i, sqInt runArray); static sqInt showFilldepthrightX(sqInt fillIndex, sqInt depth, sqInt rightX); static int * smallSqrtTable(void); static sqInt sortGlobalEdgeTable(void); static sqInt spanEndAAGet(void); static sqInt spanEndAAPut(sqInt value); static sqInt spanEndGet(void); static sqInt spanEndPut(sqInt value); static sqInt spanSizeGet(void); static sqInt spanSizePut(sqInt value); static sqInt spanStartGet(void); static sqInt spanStartPut(sqInt value); static sqInt squaredLengthOfwith(sqInt deltaX, sqInt deltaY); static sqInt stackFillDepth(sqInt index); static sqInt stackFillDepthput(sqInt index, sqInt value); static sqInt stackFillEntryLength(void); static sqInt stackFillRightX(sqInt index); static sqInt stackFillRightXput(sqInt index, sqInt value); static sqInt stackFillSize(void); static sqInt stackFillValue(sqInt index); static sqInt stackFillValueput(sqInt index, sqInt value); static sqInt stateGet(void); static sqInt statePut(sqInt value); static sqInt stepToFirstBezier(void); static sqInt stepToFirstBezierInat(sqInt bezier, sqInt yValue); static sqInt stepToFirstLine(void); static sqInt stepToFirstLineInat(sqInt line, sqInt yValue); static sqInt stepToFirstWideBezier(void); static sqInt stepToFirstWideBezierInat(sqInt bezier, sqInt yValue); static sqInt stepToFirstWideLine(void); static sqInt stepToFirstWideLineInat(sqInt line, sqInt yValue); static sqInt stepToNextBezier(void); static sqInt stepToNextBezierForwardat(sqInt updateData, sqInt yValue); static sqInt stepToNextBezierInat(sqInt bezier, sqInt yValue); static sqInt stepToNextLine(void); static sqInt stepToNextLineInat(sqInt line, sqInt yValue); static sqInt stepToNextWideBezier(void); static sqInt stepToNextWideBezierInat(sqInt bezier, sqInt yValue); static sqInt stepToNextWideLine(void); static sqInt stepToNextWideLineInat(sqInt line, sqInt yValue); static sqInt stopBecauseOf(sqInt stopReason); static sqInt stopReasonGet(void); static sqInt stopReasonPut(sqInt value); static sqInt storeEdgeStateFrominto(sqInt edge, sqInt edgeOop); static sqInt storeEngineStateInto(sqInt oop); static sqInt storeFillStateInto(sqInt fillOop); static sqInt storeRenderingState(void); static sqInt storeStopStateIntoEdgefill(sqInt edgeOop, sqInt fillOop); static sqInt subdivideBezierFrom(sqInt index); static sqInt subdivideBezier(sqInt index); static sqInt subdivideToBeMonotonInX(sqInt index); static sqInt subdivideToBeMonotonInY(sqInt index); static sqInt subdivideToBeMonotoninX(sqInt base, sqInt doTestX); static sqInt toggleFillsOf(sqInt edge); static sqInt toggleFilldepthrightX(sqInt fillIndex, sqInt depth, sqInt rightX); static sqInt toggleWideFillOf(sqInt edge); static sqInt topDepth(void); static sqInt topFill(void); static sqInt topFillDepth(void); static sqInt topFillDepthPut(sqInt value); static sqInt topFillRightX(void); static sqInt topFillRightXPut(sqInt value); static sqInt topFillValue(void); static sqInt topFillValuePut(sqInt value); static sqInt topRightX(void); static sqInt transformColor(sqInt fillIndex); static sqInt transformPoints(sqInt n); static sqInt transformPointXyinto(double xValue, double yValue, int *dstPoint); static sqInt transformPoint(int *point); static sqInt transformPointinto(sqInt srcPoint, sqInt dstPoint); static sqInt transformWidth(sqInt w); static sqInt uncheckedTransformColor(sqInt fillIndex); static sqInt wbSizeGet(void); static sqInt wbSizePut(sqInt value); static sqInt wbStackClear(void); static sqInt wbStackPop(sqInt nItems); static sqInt wbStackPush(sqInt nItems); static sqInt wbStackSize(void); static sqInt wbStackValue(sqInt index); static sqInt wbStackValueput(sqInt index, sqInt value); static sqInt wbTopGet(void); static sqInt wbTopPut(sqInt value); static sqInt wideBezierEntryOf(sqInt line); static sqInt wideBezierEntryOfput(sqInt line, sqInt value); static sqInt wideBezierExitOf(sqInt line); static sqInt wideBezierExitOfput(sqInt line, sqInt value); static sqInt wideBezierExtentOf(sqInt bezier); static sqInt wideBezierExtentOfput(sqInt bezier, sqInt value); static sqInt wideBezierFillOf(sqInt bezier); static sqInt wideBezierFillOfput(sqInt bezier, sqInt value); static int * wideBezierUpdateDataOf(sqInt bezier); static sqInt wideBezierWidthOf(sqInt line); static sqInt wideBezierWidthOfput(sqInt line, sqInt value); static sqInt wideLineEntryOf(sqInt line); static sqInt wideLineEntryOfput(sqInt line, sqInt value); static sqInt wideLineExitOf(sqInt line); static sqInt wideLineExitOfput(sqInt line, sqInt value); static sqInt wideLineExtentOf(sqInt line); static sqInt wideLineExtentOfput(sqInt line, sqInt value); static sqInt wideLineFillOf(sqInt line); static sqInt wideLineFillOfput(sqInt line, sqInt value); static sqInt wideLineWidthOf(sqInt line); static sqInt wideLineWidthOfput(sqInt line, sqInt value); static sqInt workBufferPut(sqInt wbOop); /*** Variables ***/ static int* aetBuffer; static char bbPluginName[256] = "BitBltPlugin"; static void * copyBitsFn; static sqInt dispatchedValue; static sqInt dispatchReturnValue; static int doProfileStats = 0; static sqInt engine; static sqInt engineStopped; static sqInt formArray; static sqInt geProfileTime; static int* getBuffer; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static void * loadBBFn; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "B2DPlugin VMMaker-oscog.dtl.57 (i)" #else "B2DPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static int* objBuffer; static sqInt objUsed; static unsigned int* spanBuffer; static int* workBuffer; static sqInt aaColorMaskGet(void) { return workBuffer[GWAAColorMask]; } static sqInt aaColorMaskPut(sqInt value) { return workBuffer[GWAAColorMask] = value; } static sqInt aaColorShiftGet(void) { return workBuffer[GWAAColorShift]; } static sqInt aaColorShiftPut(sqInt value) { return workBuffer[GWAAColorShift] = value; } /* Common function to compute the first full pixel for AA drawing */ static sqInt aaFirstPixelFromto(sqInt leftX, sqInt rightX) { sqInt firstPixel; firstPixel = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel > rightX) { return rightX; } else { return firstPixel; } } static sqInt aaHalfPixelGet(void) { return workBuffer[GWAAHalfPixel]; } static sqInt aaHalfPixelPut(sqInt value) { return workBuffer[GWAAHalfPixel] = value; } /* Common function to compute the last full pixel for AA drawing */ static sqInt aaLastPixelFromto(sqInt leftX, sqInt rightX) { return (rightX - 1) & (~((workBuffer[GWAALevel]) - 1)); } static sqInt aaLevelGet(void) { return workBuffer[GWAALevel]; } static sqInt aaLevelPut(sqInt value) { return workBuffer[GWAALevel] = value; } static sqInt aaScanMaskGet(void) { return workBuffer[GWAAScanMask]; } static sqInt aaScanMaskPut(sqInt value) { return workBuffer[GWAAScanMask] = value; } static sqInt aaShiftGet(void) { return workBuffer[GWAAShift]; } static sqInt aaShiftPut(sqInt value) { return workBuffer[GWAAShift] = value; } /* Compute the squared value of a 8.24 number with 0.0 <= value < 1.0, e.g., compute (value * value) bitShift: -24 */ static sqInt absoluteSquared8Dot24(sqInt value) { sqInt word1; sqInt word2; word1 = value & 65535; word2 = (((usqInt) value >> 16)) & 255; return ((usqInt) (((((usqInt) (((unsigned) (word1 * word1))) >> 16)) + ((word1 * word2) * 2)) + (((usqInt) (word2 * word2) << 16))) >> 8); } /* Return the accurate length of the vector described by deltaX and deltaY */ static sqInt accurateLengthOfwith(sqInt deltaX, sqInt deltaY) { sqInt length2; if (deltaX == 0) { if (deltaY < 0) { return 0 - deltaY; } else { return deltaY; } } if (deltaY == 0) { if (deltaX < 0) { return 0 - deltaX; } else { return deltaX; } } length2 = (deltaX * deltaX) + (deltaY * deltaY); /* begin computeSqrt: */ if (length2 < 32) { return (smallSqrtTable())[length2]; } else { return ((sqInt)((sqrt(((double) length2 ))) + 0.5)); } } static sqInt addEdgeToGET(sqInt edge) { if (!(allocateGETEntry(1))) { return 0; } getBuffer[workBuffer[GWGETUsed]] = edge; workBuffer[GWGETUsed] = ((workBuffer[GWGETUsed]) + 1); } /* NOTE: This method is (hopefully) obsolete due to unrolling the fill loops to deal with full pixels. */ /* Adjust the span buffers values by the appropriate color offset for anti-aliasing. We do this by replicating the top bits of each color in the lower bits. The idea is that we can scale each color value uniquely from 0 to 255 and thus fill the entire range of colors. */ static sqInt adjustAALevel(void) { sqInt adjustMask; sqInt adjustShift; sqInt pixelValue; sqInt x0; sqInt x1; adjustShift = 8 - (workBuffer[GWAAColorShift]); adjustMask = ~(workBuffer[GWAAColorMask]); x0 = ((usqInt) (workBuffer[GWSpanStart])) >> (workBuffer[GWAAShift]); x1 = ((usqInt) (workBuffer[GWSpanEnd])) >> (workBuffer[GWAAShift]); while (x0 < x1) { pixelValue = spanBuffer[x0]; spanBuffer[x0] = (pixelValue | ((((usqInt) pixelValue) >> adjustShift) & adjustMask)); x0 += 1; } } /* Adjust the wide bezier curve (dx < 0) to start/end at the right point */ static sqInt adjustWideBezierLeftwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOffset, sqInt endX) { sqInt lastX; sqInt lastY; (bezierUpdateDataOf(bezier))[GBUpdateX] = (((bezierUpdateDataOf(bezier))[GBUpdateX]) - (lineOffset * 256)); lastX = (wideBezierUpdateDataOf(bezier))[GBUpdateX]; (wideBezierUpdateDataOf(bezier))[GBUpdateX] = (lastX + ((lineWidth - lineOffset) * 256)); lastY = (wideBezierUpdateDataOf(bezier))[GBUpdateY]; (wideBezierUpdateDataOf(bezier))[GBUpdateY] = (lastY + (lineWidth * 256)); objBuffer[bezier + GBFinalX] = (endX - lineOffset); } /* Adjust the wide bezier curve (dx >= 0) to start/end at the right point */ static sqInt adjustWideBezierRightwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOffset, sqInt endX) { sqInt lastX; sqInt lastY; (bezierUpdateDataOf(bezier))[GBUpdateX] = (((bezierUpdateDataOf(bezier))[GBUpdateX]) + (lineOffset * 256)); lastX = (wideBezierUpdateDataOf(bezier))[GBUpdateX]; (wideBezierUpdateDataOf(bezier))[GBUpdateX] = (lastX - ((lineWidth - lineOffset) * 256)); /* Set lineWidth pixels down */ lastY = (wideBezierUpdateDataOf(bezier))[GBUpdateY]; (wideBezierUpdateDataOf(bezier))[GBUpdateY] = (lastY + (lineWidth * 256)); objBuffer[bezier + GBFinalX] = ((endX - lineOffset) + lineWidth); } /* Adjust the wide line after it has been stepped from lastX to nextX. Special adjustments of line width and start position are made here to simulate a rectangular brush */ static sqInt adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX) { sqInt baseWidth; sqInt deltaX; sqInt lineOffset; sqInt lineWidth; sqInt xDir; sqInt yEntry; sqInt yExit; /* Don't inline this */ /* Fetch the values the adjustment decisions are based on */ yEntry = objBuffer[line + GLWideEntry]; yExit = objBuffer[line + GLWideExit]; baseWidth = objBuffer[line + GLWideExtent]; lineOffset = ((sqInt) baseWidth >> 1); lineWidth = objBuffer[line + GLWideWidth]; xDir = objBuffer[line + GLXDirection]; /* Adjust the start of the line to fill an entire rectangle */ deltaX = nextX - lastX; if (yEntry < baseWidth) { if (xDir < 0) { /* effectively adding */ lineWidth -= deltaX; } else { lineWidth += deltaX; objBuffer[line + GEXValue] = lastX; } } if ((yExit + lineOffset) == 0) { if (xDir > 0) { lineWidth -= objBuffer[line + GLXIncrement]; } else { /* effectively subtracting */ lineWidth += objBuffer[line + GLXIncrement]; objBuffer[line + GEXValue] = lastX; } } if ((yExit + lineOffset) > 0) { if (xDir < 0) { /* effectively subtracting */ lineWidth += deltaX; objBuffer[line + GEXValue] = lastX; } else { lineWidth -= deltaX; } } objBuffer[line + GLWideWidth] = lineWidth; } static sqInt aetStartGet(void) { return workBuffer[GWAETStart]; } static sqInt aetStartPut(sqInt value) { return workBuffer[GWAETStart] = value; } static sqInt aetUsedGet(void) { return workBuffer[GWAETUsed]; } static sqInt aetUsedPut(sqInt value) { return workBuffer[GWAETUsed] = value; } /* Allocate n slots in the active edge table */ static sqInt allocateAETEntry(sqInt nSlots) { /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + nSlots) > (workBuffer[GWBufferTop])) { /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorNoMoreSpace; engineStopped = 1; return 0; } return 1; } static sqInt allocateBezier(void) { sqInt bezier; if (!(allocateObjEntry(GBBaseSize))) { return 0; } bezier = objUsed; objUsed = bezier + GBBaseSize; objBuffer[bezier + GEObjectType] = GEPrimitiveBezier; objBuffer[bezier + GEObjectIndex] = 0; objBuffer[bezier + GEObjectLength] = GBBaseSize; return bezier; } static sqInt allocateBezierStackEntry(void) { /* begin wbStackPush: */ if (!(needAvailableSpace(6))) { goto l1; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - 6); l1: /* end wbStackPush: */; return (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); } static sqInt allocateBitmapFillcolormap(sqInt cmSize, int *cmBits) { int *cm; sqInt fill; sqInt fillSize; sqInt i; fillSize = GBMBaseSize + cmSize; if (!(allocateObjEntry(fillSize))) { return 0; } fill = objUsed; objUsed = fill + fillSize; objBuffer[fill + GEObjectType] = GEPrimitiveClippedBitmapFill; objBuffer[fill + GEObjectIndex] = 0; objBuffer[fill + GEObjectLength] = fillSize; /* begin colormapOf: */ cm = (objBuffer + fill) + GBColormapOffset; if ((workBuffer[GWHasColorTransform]) != 0) { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (transformColor(cmBits[i])); } } else { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (cmBits[i]); } } objBuffer[fill + GBColormapSize] = cmSize; return fill; } /* Allocate n slots in the global edge table */ static sqInt allocateGETEntry(sqInt nSlots) { sqInt dstIndex; sqInt i; sqInt srcIndex; if (!(needAvailableSpace(nSlots))) { return 0; } if (!((workBuffer[GWAETUsed]) == 0)) { /* Then move the AET upwards */ srcIndex = workBuffer[GWAETUsed]; dstIndex = (workBuffer[GWAETUsed]) + nSlots; for (i = 1; i <= (workBuffer[GWAETUsed]); i += 1) { aetBuffer[(dstIndex -= 1)] = (aetBuffer[(srcIndex -= 1)]); } } aetBuffer += nSlots; return 1; } static sqInt allocateGradientFillrampWidthisRadial(int *ramp, sqInt rampWidth, sqInt isRadial) { sqInt fill; sqInt fillSize; sqInt i; int *rampPtr; fillSize = GGBaseSize + rampWidth; if (!(allocateObjEntry(fillSize))) { return 0; } fill = objUsed; objUsed = fill + fillSize; if (isRadial) { objBuffer[fill + GEObjectType] = GEPrimitiveRadialGradientFill; } else { objBuffer[fill + GEObjectType] = GEPrimitiveLinearGradientFill; } objBuffer[fill + GEObjectIndex] = 0; objBuffer[fill + GEObjectLength] = fillSize; /* begin gradientRampOf: */ rampPtr = (objBuffer + fill) + GFRampOffset; if ((workBuffer[GWHasColorTransform]) != 0) { for (i = 0; i <= (rampWidth - 1); i += 1) { rampPtr[i] = (transformColor(ramp[i])); } } else { for (i = 0; i <= (rampWidth - 1); i += 1) { rampPtr[i] = (ramp[i]); } } objBuffer[fill + GFRampLength] = rampWidth; return fill; } static sqInt allocateLine(void) { sqInt line; if (!(allocateObjEntry(GLBaseSize))) { return 0; } line = objUsed; objUsed = line + GLBaseSize; objBuffer[line + GEObjectType] = GEPrimitiveLine; objBuffer[line + GEObjectIndex] = 0; objBuffer[line + GEObjectLength] = GLBaseSize; return line; } /* Allocate n slots in the object buffer */ static sqInt allocateObjEntry(sqInt nSlots) { sqInt dstIndex; sqInt i; sqInt srcIndex; if (!(allocateGETEntry(nSlots))) { return 0; } if (!((workBuffer[GWGETUsed]) == 0)) { /* Then move the GET upwards */ srcIndex = workBuffer[GWGETUsed]; dstIndex = (workBuffer[GWGETUsed]) + nSlots; for (i = 1; i <= (workBuffer[GWGETUsed]); i += 1) { getBuffer[(dstIndex -= 1)] = (getBuffer[(srcIndex -= 1)]); } } getBuffer += nSlots; return 1; } /* AET and Stack allocation are symmetric */ static sqInt allocateStackEntry(sqInt nSlots) { /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + nSlots) > (workBuffer[GWBufferTop])) { /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorNoMoreSpace; engineStopped = 1; return 0; } return 1; } static sqInt allocateStackFillEntry(void) { /* begin wbStackPush: */ if (!(needAvailableSpace(3))) { return 0; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - 3); return 1; } static sqInt allocateWideBezier(void) { sqInt bezier; if (!(allocateObjEntry(GBWideSize))) { return 0; } bezier = objUsed; objUsed = bezier + GBWideSize; objBuffer[bezier + GEObjectType] = GEPrimitiveWideBezier; objBuffer[bezier + GEObjectIndex] = 0; objBuffer[bezier + GEObjectLength] = GBWideSize; return bezier; } static sqInt allocateWideLine(void) { sqInt line; if (!(allocateObjEntry(GLWideSize))) { return 0; } line = objUsed; objUsed = line + GLWideSize; objBuffer[line + GEObjectType] = GEPrimitiveWideLine; objBuffer[line + GEObjectIndex] = 0; objBuffer[line + GEObjectLength] = GLWideSize; return line; } static sqInt areEdgeFillsValid(sqInt edge) { return ((objBuffer[edge + GEObjectType]) & GEEdgeFillsInvalid) == 0; } /* Make sure that val1 is between val2 and val3. */ static sqInt assureValuebetweenand(sqInt val1, sqInt val2, sqInt val3) { if (val2 > val3) { if (val1 > val2) { return val2; } if (val1 < val3) { return val3; } } else { if (val1 < val2) { return val2; } if (val1 > val3) { return val3; } } return val1; } static sqInt bezierEndXOf(sqInt bezier) { return objBuffer[bezier + GBEndX]; } static sqInt bezierEndXOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBEndX] = value; } static sqInt bezierEndYOf(sqInt bezier) { return objBuffer[bezier + GBEndY]; } static sqInt bezierEndYOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBEndY] = value; } static sqInt bezierFinalXOf(sqInt bezier) { return objBuffer[bezier + GBFinalX]; } static sqInt bezierFinalXOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBFinalX] = value; } static int * bezierUpdateDataOf(sqInt bezier) { return (objBuffer + bezier) + GBUpdateData; } static sqInt bezierViaXOf(sqInt bezier) { return objBuffer[bezier + GBViaX]; } static sqInt bezierViaXOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBViaX] = value; } static sqInt bezierViaYOf(sqInt bezier) { return objBuffer[bezier + GBViaY]; } static sqInt bezierViaYOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBViaY] = value; } static sqInt bitmapCmSizeOf(sqInt bmFill) { return objBuffer[bmFill + GBColormapSize]; } static sqInt bitmapCmSizeOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBColormapSize] = value; } static sqInt bitmapDepthOf(sqInt bmFill) { return objBuffer[bmFill + GBBitmapDepth]; } static sqInt bitmapDepthOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBBitmapDepth] = value; } static sqInt bitmapHeightOf(sqInt bmFill) { return objBuffer[bmFill + GBBitmapHeight]; } static sqInt bitmapHeightOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBBitmapHeight] = value; } static sqInt bitmapRasterOf(sqInt bmFill) { return objBuffer[bmFill + GBBitmapRaster]; } static sqInt bitmapRasterOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBBitmapRaster] = value; } static sqInt bitmapSizeOf(sqInt bmFill) { return objBuffer[bmFill + GBBitmapSize]; } static sqInt bitmapSizeOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBBitmapSize] = value; } static sqInt bitmapTileFlagOf(sqInt bmFill) { return objBuffer[bmFill + GBTileFlag]; } static sqInt bitmapTileFlagOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBTileFlag] = value; } static sqInt bitmapValuebitsatXy(sqInt bmFill, sqInt bits, sqInt xp, sqInt yp) { sqInt a; sqInt b; sqInt bmDepth; sqInt bmRaster; sqInt cMask; sqInt g; sqInt r; sqInt rShift; sqInt someIntegerValue; sqInt value; bmDepth = objBuffer[bmFill + GBBitmapDepth]; bmRaster = objBuffer[bmFill + GBBitmapRaster]; if (bmDepth == 32) { value = (((int*) bits))[(bmRaster * yp) + xp]; if ((value != 0) && ((value & 4278190080UL) == 0)) { value = value | 4278190080UL; } return uncheckedTransformColor(value); } rShift = (rShiftTable())[bmDepth]; /* cMask - mask out the pixel from the word */ value = (((int*) bits))[(bmRaster * yp) + (((usqInt) xp) >> rShift)]; /* rShift - shift value to move the pixel in the word to the lowest bit position */ cMask = (1 << bmDepth) - 1; rShift = (32 - bmDepth) - ((xp & ((1 << rShift) - 1)) * bmDepth); value = (((usqInt) value) >> rShift) & cMask; if (bmDepth == 16) { if (!(value == 0)) { /* Must convert by expanding bits */ b = (value & 31) << 3; b += ((usqInt) b) >> 5; g = ((((usqInt) value) >> 5) & 31) << 3; g += ((usqInt) g) >> 5; r = ((((usqInt) value) >> 10) & 31) << 3; r += ((usqInt) r) >> 5; a = 255; value = ((b + (g << 8)) + (r << 16)) + (a << 24); } } else { if ((objBuffer[bmFill + GBColormapSize]) == 0) { /* Must convert by using color map */ value = 0; } else { /* begin makeUnsignedFrom: */ someIntegerValue = (colormapOf(bmFill))[value]; value = someIntegerValue; } } return uncheckedTransformColor(value); } static sqInt bitmapWidthOf(sqInt bmFill) { return objBuffer[bmFill + GBBitmapWidth]; } static sqInt bitmapWidthOfput(sqInt bmFill, sqInt value) { return objBuffer[bmFill + GBBitmapWidth] = value; } static sqInt bzEndX(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; } static sqInt bzEndXput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)] = value; } static sqInt bzEndY(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; } static sqInt bzEndYput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)] = value; } static sqInt bzStartX(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]; } static sqInt bzStartXput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)] = value; } static sqInt bzStartY(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; } static sqInt bzStartYput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)] = value; } static sqInt bzViaX(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]; } static sqInt bzViaXput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)] = value; } static sqInt bzViaY(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]; } static sqInt bzViaYput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)] = value; } /* Check the fill indexes in the run-length encoded fillList */ static sqInt checkCompressedFillIndexListmaxsegments(sqInt fillList, sqInt maxIndex, sqInt nSegs) { int *fillPtr; sqInt i; sqInt length; sqInt nFills; sqInt runLength; sqInt runValue; length = interpreterProxy->slotSizeOf(fillList); fillPtr = interpreterProxy->firstIndexableField(fillList); nFills = 0; for (i = 0; i <= (length - 1); i += 1) { runLength = ((usqInt) ((((int *) fillPtr))[i]) >> 16); runValue = ((((int *) fillPtr))[i]) & 65535; if (!((runValue >= 0) && (runValue <= maxIndex))) { return 0; } nFills += runLength; } return nFills == nSegs; } /* Check if the indexList (containing fill handles) is okay. */ static sqInt checkCompressedFills(sqInt indexList) { sqInt fillIndex; int *fillPtr; sqInt i; sqInt length; if (!(interpreterProxy->isWords(indexList))) { return 0; } length = interpreterProxy->slotSizeOf(indexList); fillPtr = interpreterProxy->firstIndexableField(indexList); for (i = 0; i <= (length - 1); i += 1) { /* Make sure the fill is okay */ fillIndex = fillPtr[i]; if (!(isFillOkay(fillIndex))) { return 0; } } return 1; } /* Check the run-length encoded lineWidthList matches nSegments */ static sqInt checkCompressedLineWidthssegments(sqInt lineWidthList, sqInt nSegments) { sqInt i; sqInt length; sqInt nItems; int *ptr; sqInt runLength; length = interpreterProxy->slotSizeOf(lineWidthList); ptr = interpreterProxy->firstIndexableField(lineWidthList); nItems = 0; for (i = 0; i <= (length - 1); i += 1) { runLength = ((usqInt) ((((int *) ptr))[i]) >> 16); nItems += runLength; } return nItems == nSegments; } /* Check if the given point array can be handled by the engine. */ static sqInt checkCompressedPointssegments(sqInt points, sqInt nSegments) { sqInt pSize; if (!(interpreterProxy->isWords(points))) { return 0; } /* The points must be either in PointArray format or ShortPointArray format. Also, we currently handle only quadratic segments (e.g., 3 points each) and thus either pSize = nSegments * 3, for ShortPointArrays or, pSize = nSegments * 6, for PointArrays */ pSize = interpreterProxy->slotSizeOf(points); if (!((pSize == (nSegments * 3)) || (pSize == (nSegments * 6)))) { return 0; } return 1; } /* Check if the given shape can be handled by the engine. Since there are a number of requirements this is an extra method. */ static sqInt checkCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(sqInt points, sqInt nSegments, sqInt leftFills, sqInt rightFills, sqInt lineWidths, sqInt lineFills, sqInt fillIndexList) { sqInt maxFillIndex; if (!(checkCompressedPointssegments(points, nSegments))) { return 0; } if (!(checkCompressedFills(fillIndexList))) { return 0; } maxFillIndex = interpreterProxy->slotSizeOf(fillIndexList); if (!(checkCompressedFillIndexListmaxsegments(leftFills, maxFillIndex, nSegments))) { return 0; } if (!(checkCompressedFillIndexListmaxsegments(rightFills, maxFillIndex, nSegments))) { return 0; } if (!(checkCompressedFillIndexListmaxsegments(lineFills, maxFillIndex, nSegments))) { return 0; } if (!(checkCompressedLineWidthssegments(lineWidths, nSegments))) { return 0; } return 1; } /* Add the bezier to the global edge table if it intersects the clipping region */ static sqInt checkedAddBezierToGET(sqInt bezier) { sqInt lineWidth; if ((((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth = objBuffer[bezier + GBWideExtent]; } else { lineWidth = 0; } if (((objBuffer[bezier + GBEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { return 0; } if ((((objBuffer[bezier + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[bezier + GBEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { return 0; } addEdgeToGET(bezier); } /* Add the edge to the global edge table. For known edge types, check if the edge intersects the visible region */ static sqInt checkedAddEdgeToGET(sqInt edge) { sqInt lineWidth; sqInt lineWidth1; if ((((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveLine) { /* begin checkedAddLineToGET: */ if ((((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth1 = objBuffer[edge + GLWideExtent]; } else { lineWidth1 = 0; } if (((objBuffer[edge + GLEndY]) + lineWidth1) < (workBuffer[GWFillMinY])) { return 0; } if ((((objBuffer[edge + GEXValue]) - lineWidth1) >= (workBuffer[GWFillMaxX])) && (((objBuffer[edge + GLEndX]) - lineWidth1) >= (workBuffer[GWFillMaxX]))) { return 0; } addEdgeToGET(edge); return null; } if ((((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveBezier) { /* begin checkedAddBezierToGET: */ if ((((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth = objBuffer[edge + GBWideExtent]; } else { lineWidth = 0; } if (((objBuffer[edge + GBEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { return 0; } if ((((objBuffer[edge + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[edge + GBEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { return 0; } addEdgeToGET(edge); return null; } addEdgeToGET(edge); } /* Add the line to the global edge table if it intersects the clipping region */ static sqInt checkedAddLineToGET(sqInt line) { sqInt lineWidth; if ((((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth = objBuffer[line + GLWideExtent]; } else { lineWidth = 0; } if (((objBuffer[line + GLEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { return 0; } if ((((objBuffer[line + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[line + GLEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { return 0; } addEdgeToGET(line); } static double * circleCosTable(void) { static double theTable[33] = {1.0, 0.98078528040323, 0.923879532511287, 0.831469612302545, 0.7071067811865475, 0.555570233019602, 0.38268343236509, 0.1950903220161286, 0.0, -0.1950903220161283, -0.3826834323650896, -0.555570233019602, -0.707106781186547, -0.831469612302545, -0.9238795325112865, -0.98078528040323, -1.0, -0.98078528040323, -0.923879532511287, -0.831469612302545, -0.707106781186548, -0.555570233019602, -0.3826834323650903, -0.1950903220161287, 0.0, 0.1950903220161282, 0.38268343236509, 0.555570233019602, 0.707106781186547, 0.831469612302545, 0.9238795325112865, 0.98078528040323, 1.0 }; return theTable; } static double * circleSinTable(void) { static double theTable[33] = {0.0, 0.1950903220161282, 0.3826834323650897, 0.555570233019602, 0.707106781186547, 0.831469612302545, 0.923879532511287, 0.98078528040323, 1.0, 0.98078528040323, 0.923879532511287, 0.831469612302545, 0.7071067811865475, 0.555570233019602, 0.38268343236509, 0.1950903220161286, 0.0, -0.1950903220161283, -0.3826834323650896, -0.555570233019602, -0.707106781186547, -0.831469612302545, -0.9238795325112865, -0.98078528040323, -1.0, -0.98078528040323, -0.923879532511287, -0.831469612302545, -0.707106781186548, -0.555570233019602, -0.3826834323650903, -0.1950903220161287, 0.0 }; return theTable; } static sqInt clampValuemax(sqInt value, sqInt maxValue) { if (value < 0) { return 0; } else { if (value >= maxValue) { return maxValue - 1; } else { return value; } } } /* Clear the current span buffer. The span buffer is only cleared in the area that has been used by the previous scan line. */ static sqInt clearSpanBuffer(void) { sqInt x0; sqInt x1; x0 = ((usqInt) (workBuffer[GWSpanStart])) >> (workBuffer[GWAAShift]); x1 = (((usqInt) (workBuffer[GWSpanEnd])) >> (workBuffer[GWAAShift])) + 1; if (x0 < 0) { x0 = 0; } if (x1 > (workBuffer[GWSpanSize])) { x1 = workBuffer[GWSpanSize]; } while (x0 < x1) { spanBuffer[x0] = 0; x0 += 1; } workBuffer[GWSpanStart] = (workBuffer[GWSpanSize]); workBuffer[GWSpanEnd] = 0; } static sqInt clearSpanBufferGet(void) { return workBuffer[GWClearSpanBuffer]; } static sqInt clearSpanBufferPut(sqInt value) { return workBuffer[GWClearSpanBuffer] = value; } static sqInt clipMaxXGet(void) { return workBuffer[GWClipMaxX]; } static sqInt clipMaxXPut(sqInt value) { return workBuffer[GWClipMaxX] = value; } static sqInt clipMaxYGet(void) { return workBuffer[GWClipMaxY]; } static sqInt clipMaxYPut(sqInt value) { return workBuffer[GWClipMaxY] = value; } static sqInt clipMinXGet(void) { return workBuffer[GWClipMinX]; } static sqInt clipMinXPut(sqInt value) { return workBuffer[GWClipMinX] = value; } static sqInt clipMinYGet(void) { return workBuffer[GWClipMinY]; } static sqInt clipMinYPut(sqInt value) { return workBuffer[GWClipMinY] = value; } static int * colormapOf(sqInt bmFill) { return (objBuffer + bmFill) + GBColormapOffset; } static float * colorTransform(void) { return ((float *) (workBuffer + GWColorTransform)); } /* Split the bezier curve at 0.5. */ static sqInt computeBezierSplitAtHalf(sqInt index) { sqInt endX; sqInt endY; sqInt leftViaX; sqInt leftViaY; sqInt newIndex; sqInt rightViaX; sqInt rightViaY; sqInt sharedX; sqInt sharedY; sqInt startX; sqInt startY; sqInt viaX; sqInt viaY; /* begin allocateBezierStackEntry */ /* begin wbStackPush: */ if (!(needAvailableSpace(6))) { goto l1; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - 6); l1: /* end wbStackPush: */; newIndex = (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); if (engineStopped) { return 0; } leftViaX = startX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]; leftViaY = startY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; rightViaX = viaX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]; rightViaY = viaY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]; endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; /* Compute intermediate points */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; leftViaX += ((sqInt) (viaX - startX) >> 1); leftViaY += ((sqInt) (viaY - startY) >> 1); sharedX = rightViaX += ((sqInt) (endX - viaX) >> 1); /* Compute new shared point */ sharedY = rightViaY += ((sqInt) (endY - viaY) >> 1); sharedX += ((sqInt) (leftViaX - rightViaX) >> 1); /* Store the first part back */ sharedY += ((sqInt) (leftViaY - rightViaY) >> 1); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)] = leftViaX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)] = leftViaY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)] = sharedX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)] = sharedY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 0)] = sharedX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 1)] = sharedY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 2)] = rightViaX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 3)] = rightViaY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 4)] = endX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 5)] = endY; return newIndex; } /* Split the bezier curve at the given parametric value. Note: Since this method is only invoked to make non-monoton beziers monoton we must check for the resulting y values to be *really* between the start and end value. */ static sqInt computeBeziersplitAt(sqInt index, double param) { sqInt endX; sqInt endY; sqInt leftViaX; sqInt leftViaY; sqInt newIndex; sqInt rightViaX; sqInt rightViaY; sqInt sharedX; sqInt sharedY; sqInt startX; sqInt startY; sqInt viaX; sqInt viaY; leftViaX = startX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]; leftViaY = startY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; rightViaX = viaX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]; rightViaY = viaY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]; endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; /* Compute intermediate points */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; sharedX = leftViaX += ((sqInt)((((double) (viaX - startX) )) * param)); sharedY = leftViaY += ((sqInt)((((double) (viaY - startY) )) * param)); rightViaX += ((sqInt)((((double) (endX - viaX) )) * param)); /* Compute new shared point */ rightViaY += ((sqInt)((((double) (endY - viaY) )) * param)); sharedX += ((sqInt)((((double) (rightViaX - leftViaX) )) * param)); /* Check the new via points */ sharedY += ((sqInt)((((double) (rightViaY - leftViaY) )) * param)); /* begin assureValue:between:and: */ if (startY > sharedY) { if (leftViaY > startY) { leftViaY = startY; goto l1; } if (leftViaY < sharedY) { leftViaY = sharedY; goto l1; } } else { if (leftViaY < startY) { leftViaY = startY; goto l1; } if (leftViaY > sharedY) { leftViaY = sharedY; goto l1; } } leftViaY = leftViaY; l1: /* end assureValue:between:and: */; /* begin assureValue:between:and: */ if (sharedY > endY) { if (rightViaY > sharedY) { rightViaY = sharedY; goto l2; } if (rightViaY < endY) { rightViaY = endY; goto l2; } } else { if (rightViaY < sharedY) { rightViaY = sharedY; goto l2; } if (rightViaY > endY) { rightViaY = endY; goto l2; } } rightViaY = rightViaY; l2: /* end assureValue:between:and: */; /* begin allocateBezierStackEntry */ /* begin wbStackPush: */ if (!(needAvailableSpace(6))) { goto l3; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - 6); l3: /* end wbStackPush: */; newIndex = (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); if (engineStopped) { return 0; } workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)] = leftViaX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)] = leftViaY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)] = sharedX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)] = sharedY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 0)] = sharedX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 1)] = sharedY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 2)] = rightViaX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 3)] = rightViaY; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 4)] = endX; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex) + 5)] = endY; return newIndex; } /* Get both values from the two boundaries of the given bezier and compute the actual position/width of the line */ static sqInt computeFinalWideBezierValueswidth(sqInt bezier, sqInt lineWidth) { sqInt leftX; sqInt rightX; sqInt temp; leftX = ((sqInt) ((bezierUpdateDataOf(bezier))[GBUpdateX]) >> 8); rightX = ((sqInt) ((wideBezierUpdateDataOf(bezier))[GBUpdateX]) >> 8); if (leftX > rightX) { temp = leftX; leftX = rightX; rightX = temp; } objBuffer[bezier + GEXValue] = leftX; if ((rightX - leftX) > lineWidth) { objBuffer[bezier + GBWideWidth] = (rightX - leftX); } else { objBuffer[bezier + GBWideWidth] = lineWidth; } } static sqInt computeSqrt(sqInt length2) { if (length2 < 32) { return (smallSqrtTable())[length2]; } else { return ((sqInt)((sqrt(((double) length2 ))) + 0.5)); } } static sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt yValue) { if (copyBitsFn == 0) { if (!(initialiseModule())) { return 0; } } return ((sqInt (*)(sqInt, sqInt, sqInt))copyBitsFn)(x0, x1, yValue); } /* Create the global edge table */ static sqInt createGlobalEdgeTable(void) { sqInt end; sqInt lineWidth; sqInt lineWidth1; sqInt object; object = 0; end = objUsed; while (object < end) { if (isEdge(object)) { if (!((objBuffer[object + GEYValue]) >= (workBuffer[GWFillMaxY]))) { /* begin checkedAddEdgeToGET: */ if ((((objBuffer[object + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveLine) { /* begin checkedAddLineToGET: */ if ((((objBuffer[object + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth1 = objBuffer[object + GLWideExtent]; } else { lineWidth1 = 0; } if (((objBuffer[object + GLEndY]) + lineWidth1) < (workBuffer[GWFillMinY])) { goto l1; } if ((((objBuffer[object + GEXValue]) - lineWidth1) >= (workBuffer[GWFillMaxX])) && (((objBuffer[object + GLEndX]) - lineWidth1) >= (workBuffer[GWFillMaxX]))) { goto l1; } addEdgeToGET(object); goto l1; } if ((((objBuffer[object + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveBezier) { /* begin checkedAddBezierToGET: */ if ((((objBuffer[object + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { lineWidth = objBuffer[object + GBWideExtent]; } else { lineWidth = 0; } if (((objBuffer[object + GBEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { goto l1; } if ((((objBuffer[object + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[object + GBEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { goto l1; } addEdgeToGET(object); goto l1; } addEdgeToGET(object); l1: /* end checkedAddEdgeToGET: */; } } object += objBuffer[object + GEObjectLength]; } } static sqInt currentYGet(void) { return workBuffer[GWCurrentY]; } static sqInt currentYPut(sqInt value) { return workBuffer[GWCurrentY] = value; } static sqInt currentZGet(void) { return workBuffer[GWCurrentZ]; } static sqInt currentZPut(sqInt value) { return workBuffer[GWCurrentZ] = value; } static sqInt destOffsetXGet(void) { return workBuffer[GWDestOffsetX]; } static sqInt destOffsetXPut(sqInt value) { return workBuffer[GWDestOffsetX] = value; } static sqInt destOffsetYGet(void) { return workBuffer[GWDestOffsetY]; } static sqInt destOffsetYPut(sqInt value) { return workBuffer[GWDestOffsetY] = value; } /* Display the span buffer at the current scan line. */ static sqInt displaySpanBufferAt(sqInt y) { sqInt targetX0; sqInt targetX1; sqInt targetY; /* self aaLevelGet > 1 ifTrue:[self adjustAALevel]. */ targetX0 = ((usqInt) (workBuffer[GWSpanStart])) >> (workBuffer[GWAAShift]); if (targetX0 < (workBuffer[GWClipMinX])) { targetX0 = workBuffer[GWClipMinX]; } targetX1 = ((usqInt) (((workBuffer[GWSpanEnd]) + (workBuffer[GWAALevel])) - 1)) >> (workBuffer[GWAAShift]); if (targetX1 > (workBuffer[GWClipMaxX])) { targetX1 = workBuffer[GWClipMaxX]; } targetY = ((usqInt) y) >> (workBuffer[GWAAShift]); if ((targetY < (workBuffer[GWClipMinY])) || ((targetY >= (workBuffer[GWClipMaxY])) || ((targetX1 < (workBuffer[GWClipMinX])) || (targetX0 >= (workBuffer[GWClipMaxX]))))) { return 0; } copyBitsFromtoat(targetX0, targetX1, targetY); } /* Draw the given edge starting from leftX with the edge's fill. Return the end value of the drawing operation. */ static sqInt drawWideEdgefrom(sqInt edge, sqInt leftX) { sqInt fill; sqInt lineWidth; sqInt rightX; sqInt type; /* Not for the moment */ type = ((usqInt) ((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask)) >> 1; dispatchedValue = edge; switch (type) { case 0: case 1: errorWrongIndex(); break; case 2: dispatchReturnValue = objBuffer[dispatchedValue + GLWideWidth]; break; case 3: dispatchReturnValue = objBuffer[dispatchedValue + GBWideWidth]; break; } lineWidth = dispatchReturnValue; switch (type) { case 0: case 1: errorWrongIndex(); break; case 2: dispatchReturnValue = objBuffer[dispatchedValue + GLWideFill]; break; case 3: dispatchReturnValue = objBuffer[dispatchedValue + GBWideFill]; break; } fill = dispatchReturnValue; if (fill == 0) { return leftX; } rightX = leftX + lineWidth; fillSpanfromto(fill, leftX, rightX); return rightX; } static sqInt edgeFillsInvalidate(sqInt edge) { return objBuffer[edge + GEObjectType] = (((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } static sqInt edgeFillsValidate(sqInt edge) { return objBuffer[edge + GEObjectType] = (((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } static sqInt edgeLeftFillOf(sqInt edge) { return objBuffer[edge + GEFillIndexLeft]; } static sqInt edgeLeftFillOfput(sqInt edge, sqInt value) { return objBuffer[edge + GEFillIndexLeft] = value; } static sqInt edgeNumLinesOf(sqInt edge) { return objBuffer[edge + GENumLines]; } static sqInt edgeNumLinesOfput(sqInt edge, sqInt value) { return objBuffer[edge + GENumLines] = value; } static sqInt edgeRightFillOf(sqInt edge) { return objBuffer[edge + GEFillIndexRight]; } static sqInt edgeRightFillOfput(sqInt edge, sqInt value) { return objBuffer[edge + GEFillIndexRight] = value; } static float * edgeTransform(void) { return ((float *) (workBuffer + GWEdgeTransform)); } /* Return the edge type (e.g., witout the wide edge flag) */ static sqInt edgeTypeOf(sqInt edge) { return ((usqInt) ((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask)) >> 1; } static sqInt edgeXValueOf(sqInt edge) { return objBuffer[edge + GEXValue]; } static sqInt edgeXValueOfput(sqInt edge, sqInt value) { return objBuffer[edge + GEXValue] = value; } static sqInt edgeYValueOf(sqInt edge) { return objBuffer[edge + GEYValue]; } static sqInt edgeYValueOfput(sqInt edge, sqInt value) { return objBuffer[edge + GEYValue] = value; } static sqInt edgeZValueOf(sqInt edge) { return objBuffer[edge + GEZValue]; } static sqInt edgeZValueOfput(sqInt edge, sqInt value) { return objBuffer[edge + GEZValue] = value; } /* Ignore dispatch errors when translating to C (since we have no entry point for #error in the VM proxy) */ static sqInt errorWrongIndex(void) { ; } /* Estimate the length of the vector described by deltaX and deltaY. This method may be extremely inaccurate - use it only if you know exactly that this doesn't matter. Otherwise use #accurateLengthOf:width: */ static sqInt estimatedLengthOfwith(sqInt deltaX, sqInt deltaY) { sqInt absDx; sqInt absDy; if (deltaX >= 0) { absDx = deltaX; } else { absDx = 0 - deltaX; } if (deltaY >= 0) { absDy = deltaY; } else { absDy = 0 - deltaY; } if (absDx > absDy) { return absDx + (((sqInt) absDy >> 1)); } else { return absDy + (((sqInt) absDx >> 1)); } } /* Fill the span buffer from leftX to rightX with the given fill. */ static sqInt fillAllFromto(sqInt leftX, sqInt rightX) { sqInt fill; sqInt someIntegerValue; sqInt someIntegerValue1; sqInt startX; sqInt stopX; /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { fill = 0; goto l4; } else { fill = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l4; } l4: /* end topFill */; startX = leftX; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX = 999999999; goto l5; } else { stopX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l5; } l5: /* end topRightX */; while (stopX < rightX) { /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue = 0; goto l2; } else { someIntegerValue = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l2; } l2: /* end topFill */; fill = someIntegerValue; if (!(fill == 0)) { if (fillSpanfromto(fill, startX, stopX)) { return 1; } } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } while ((topRightX()) <= stopX) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } } l1: /* end quickRemoveInvalidFillsAt: */; startX = stopX; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX = 999999999; goto l3; } else { stopX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l3; } l3: /* end topRightX */; } /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue1 = 0; goto l6; } else { someIntegerValue1 = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l6; } l6: /* end topFill */; fill = someIntegerValue1; if (!(fill == 0)) { return fillSpanfromto(fill, startX, rightX); } return 0; } static sqInt fillBitmapSpan(void) { return fillBitmapSpanfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); } static sqInt fillBitmapSpanAAfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) { sqInt a; sqInt a1; sqInt a2; sqInt aaLevel; sqInt b; sqInt b1; sqInt b2; sqInt baseShift; int *bits; sqInt bmDepth; sqInt bmDepth1; sqInt bmDepth2; sqInt bmHeight; sqInt bmRaster; sqInt bmRaster1; sqInt bmRaster2; sqInt bmWidth; sqInt cMask; sqInt cMask1; sqInt cMask2; sqInt cMask3; sqInt cShift; sqInt deltaX; sqInt deltaY; sqInt ds; sqInt dsX; sqInt dt; sqInt dtX; sqInt fillValue; sqInt firstPixel; sqInt firstPixel1; sqInt g; sqInt g1; sqInt g2; sqInt idx; sqInt lastPixel; sqInt newDelta; sqInt newDelta1; sqInt newDelta2; sqInt newDelta3; sqInt newDelta4; sqInt newDelta5; sqInt r; sqInt r1; sqInt r2; sqInt rShift; sqInt rShift1; sqInt rShift2; sqInt someIntegerValue; sqInt someIntegerValue1; sqInt someIntegerValue2; sqInt tileFlag; sqInt value; sqInt value1; sqInt value2; sqInt x; sqInt xp; sqInt yp; bits = loadBitsFrom(bmFill); if (bits == null) { return null; } bmWidth = objBuffer[bmFill + GBBitmapWidth]; bmHeight = objBuffer[bmFill + GBBitmapHeight]; tileFlag = (objBuffer[bmFill + GBTileFlag]) == 1; deltaX = leftX - (objBuffer[bmFill + GFOriginX]); deltaY = yValue - (objBuffer[bmFill + GFOriginY]); dsX = objBuffer[bmFill + GFDirectionX]; dtX = objBuffer[bmFill + GFNormalX]; ds = (deltaX * dsX) + (deltaY * (objBuffer[bmFill + GFDirectionY])); dt = (deltaX * dtX) + (deltaY * (objBuffer[bmFill + GFNormalY])); aaLevel = workBuffer[GWAALevel]; /* begin aaFirstPixelFrom:to: */ firstPixel1 = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel1 > rightX) { firstPixel = rightX; goto l10; } else { firstPixel = firstPixel1; goto l10; } l10: /* end aaFirstPixelFrom:to: */; lastPixel = (rightX - 1) & (~((workBuffer[GWAALevel]) - 1)); baseShift = workBuffer[GWAAShift]; cMask = workBuffer[GWAAColorMask]; cShift = workBuffer[GWAAColorShift]; x = leftX; while (x < firstPixel) { if (tileFlag) { /* begin repeatValue:max: */ newDelta = ds; while (newDelta < 0) { newDelta += bmWidth << 16; } while (newDelta >= (bmWidth << 16)) { newDelta -= bmWidth << 16; } ds = newDelta; /* begin repeatValue:max: */ newDelta1 = dt; while (newDelta1 < 0) { newDelta1 += bmHeight << 16; } while (newDelta1 >= (bmHeight << 16)) { newDelta1 -= bmHeight << 16; } dt = newDelta1; } xp = ((sqInt) ds >> 16); yp = ((sqInt) dt >> 16); if (!(tileFlag)) { /* begin clampValue:max: */ if (xp < 0) { xp = 0; goto l1; } else { if (xp >= bmWidth) { xp = bmWidth - 1; goto l1; } else { xp = xp; goto l1; } } l1: /* end clampValue:max: */; /* begin clampValue:max: */ if (yp < 0) { yp = 0; goto l2; } else { if (yp >= bmHeight) { yp = bmHeight - 1; goto l2; } else { yp = yp; goto l2; } } l2: /* end clampValue:max: */; } if ((xp >= 0) && ((yp >= 0) && ((xp < bmWidth) && (yp < bmHeight)))) { /* begin bitmapValue:bits:atX:y: */ bmDepth = objBuffer[bmFill + GBBitmapDepth]; bmRaster = objBuffer[bmFill + GBBitmapRaster]; if (bmDepth == 32) { value = (((int*) bits))[(bmRaster * yp) + xp]; if ((value != 0) && ((value & 4278190080UL) == 0)) { value = value | 4278190080UL; } fillValue = uncheckedTransformColor(value); goto l3; } rShift = (rShiftTable())[bmDepth]; /* cMask - mask out the pixel from the word */ value = (((int*) bits))[(bmRaster * yp) + (((usqInt) xp) >> rShift)]; /* rShift - shift value to move the pixel in the word to the lowest bit position */ cMask1 = (1 << bmDepth) - 1; rShift = (32 - bmDepth) - ((xp & ((1 << rShift) - 1)) * bmDepth); value = (((usqInt) value) >> rShift) & cMask1; if (bmDepth == 16) { if (!(value == 0)) { /* Must convert by expanding bits */ b = (value & 31) << 3; b += ((usqInt) b) >> 5; g = ((((usqInt) value) >> 5) & 31) << 3; g += ((usqInt) g) >> 5; r = ((((usqInt) value) >> 10) & 31) << 3; r += ((usqInt) r) >> 5; a = 255; value = ((b + (g << 8)) + (r << 16)) + (a << 24); } } else { if ((objBuffer[bmFill + GBColormapSize]) == 0) { /* Must convert by using color map */ value = 0; } else { /* begin makeUnsignedFrom: */ someIntegerValue = (colormapOf(bmFill))[value]; value = someIntegerValue; } } fillValue = uncheckedTransformColor(value); l3: /* end bitmapValue:bits:atX:y: */; fillValue = ((usqInt) (fillValue & cMask)) >> cShift; idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + fillValue); } ds += dsX; dt += dtX; x += 1; } cMask = (((usqInt) (workBuffer[GWAAColorMask])) >> (workBuffer[GWAAShift])) | 4042322160UL; cShift = workBuffer[GWAAShift]; while (x < lastPixel) { if (tileFlag) { /* begin repeatValue:max: */ newDelta2 = ds; while (newDelta2 < 0) { newDelta2 += bmWidth << 16; } while (newDelta2 >= (bmWidth << 16)) { newDelta2 -= bmWidth << 16; } ds = newDelta2; /* begin repeatValue:max: */ newDelta3 = dt; while (newDelta3 < 0) { newDelta3 += bmHeight << 16; } while (newDelta3 >= (bmHeight << 16)) { newDelta3 -= bmHeight << 16; } dt = newDelta3; } xp = ((sqInt) ds >> 16); yp = ((sqInt) dt >> 16); if (!(tileFlag)) { /* begin clampValue:max: */ if (xp < 0) { xp = 0; goto l4; } else { if (xp >= bmWidth) { xp = bmWidth - 1; goto l4; } else { xp = xp; goto l4; } } l4: /* end clampValue:max: */; /* begin clampValue:max: */ if (yp < 0) { yp = 0; goto l5; } else { if (yp >= bmHeight) { yp = bmHeight - 1; goto l5; } else { yp = yp; goto l5; } } l5: /* end clampValue:max: */; } if ((xp >= 0) && ((yp >= 0) && ((xp < bmWidth) && (yp < bmHeight)))) { /* begin bitmapValue:bits:atX:y: */ bmDepth1 = objBuffer[bmFill + GBBitmapDepth]; bmRaster1 = objBuffer[bmFill + GBBitmapRaster]; if (bmDepth1 == 32) { value1 = (((int*) bits))[(bmRaster1 * yp) + xp]; if ((value1 != 0) && ((value1 & 4278190080UL) == 0)) { value1 = value1 | 4278190080UL; } fillValue = uncheckedTransformColor(value1); goto l6; } rShift1 = (rShiftTable())[bmDepth1]; /* cMask - mask out the pixel from the word */ value1 = (((int*) bits))[(bmRaster1 * yp) + (((usqInt) xp) >> rShift1)]; /* rShift - shift value to move the pixel in the word to the lowest bit position */ cMask2 = (1 << bmDepth1) - 1; rShift1 = (32 - bmDepth1) - ((xp & ((1 << rShift1) - 1)) * bmDepth1); value1 = (((usqInt) value1) >> rShift1) & cMask2; if (bmDepth1 == 16) { if (!(value1 == 0)) { /* Must convert by expanding bits */ b1 = (value1 & 31) << 3; b1 += ((usqInt) b1) >> 5; g1 = ((((usqInt) value1) >> 5) & 31) << 3; g1 += ((usqInt) g1) >> 5; r1 = ((((usqInt) value1) >> 10) & 31) << 3; r1 += ((usqInt) r1) >> 5; a1 = 255; value1 = ((b1 + (g1 << 8)) + (r1 << 16)) + (a1 << 24); } } else { if ((objBuffer[bmFill + GBColormapSize]) == 0) { /* Must convert by using color map */ value1 = 0; } else { /* begin makeUnsignedFrom: */ someIntegerValue1 = (colormapOf(bmFill))[value1]; value1 = someIntegerValue1; } } fillValue = uncheckedTransformColor(value1); l6: /* end bitmapValue:bits:atX:y: */; fillValue = ((usqInt) (fillValue & cMask)) >> cShift; idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + fillValue); } ds += dsX << cShift; dt += dtX << cShift; x += aaLevel; } cMask = workBuffer[GWAAColorMask]; cShift = workBuffer[GWAAColorShift]; while (x < rightX) { if (tileFlag) { /* begin repeatValue:max: */ newDelta4 = ds; while (newDelta4 < 0) { newDelta4 += bmWidth << 16; } while (newDelta4 >= (bmWidth << 16)) { newDelta4 -= bmWidth << 16; } ds = newDelta4; /* begin repeatValue:max: */ newDelta5 = dt; while (newDelta5 < 0) { newDelta5 += bmHeight << 16; } while (newDelta5 >= (bmHeight << 16)) { newDelta5 -= bmHeight << 16; } dt = newDelta5; } xp = ((sqInt) ds >> 16); yp = ((sqInt) dt >> 16); if (!(tileFlag)) { /* begin clampValue:max: */ if (xp < 0) { xp = 0; goto l7; } else { if (xp >= bmWidth) { xp = bmWidth - 1; goto l7; } else { xp = xp; goto l7; } } l7: /* end clampValue:max: */; /* begin clampValue:max: */ if (yp < 0) { yp = 0; goto l8; } else { if (yp >= bmHeight) { yp = bmHeight - 1; goto l8; } else { yp = yp; goto l8; } } l8: /* end clampValue:max: */; } if ((xp >= 0) && ((yp >= 0) && ((xp < bmWidth) && (yp < bmHeight)))) { /* begin bitmapValue:bits:atX:y: */ bmDepth2 = objBuffer[bmFill + GBBitmapDepth]; bmRaster2 = objBuffer[bmFill + GBBitmapRaster]; if (bmDepth2 == 32) { value2 = (((int*) bits))[(bmRaster2 * yp) + xp]; if ((value2 != 0) && ((value2 & 4278190080UL) == 0)) { value2 = value2 | 4278190080UL; } fillValue = uncheckedTransformColor(value2); goto l9; } rShift2 = (rShiftTable())[bmDepth2]; /* cMask - mask out the pixel from the word */ value2 = (((int*) bits))[(bmRaster2 * yp) + (((usqInt) xp) >> rShift2)]; /* rShift - shift value to move the pixel in the word to the lowest bit position */ cMask3 = (1 << bmDepth2) - 1; rShift2 = (32 - bmDepth2) - ((xp & ((1 << rShift2) - 1)) * bmDepth2); value2 = (((usqInt) value2) >> rShift2) & cMask3; if (bmDepth2 == 16) { if (!(value2 == 0)) { /* Must convert by expanding bits */ b2 = (value2 & 31) << 3; b2 += ((usqInt) b2) >> 5; g2 = ((((usqInt) value2) >> 5) & 31) << 3; g2 += ((usqInt) g2) >> 5; r2 = ((((usqInt) value2) >> 10) & 31) << 3; r2 += ((usqInt) r2) >> 5; a2 = 255; value2 = ((b2 + (g2 << 8)) + (r2 << 16)) + (a2 << 24); } } else { if ((objBuffer[bmFill + GBColormapSize]) == 0) { /* Must convert by using color map */ value2 = 0; } else { /* begin makeUnsignedFrom: */ someIntegerValue2 = (colormapOf(bmFill))[value2]; value2 = someIntegerValue2; } } fillValue = uncheckedTransformColor(value2); l9: /* end bitmapValue:bits:atX:y: */; fillValue = ((usqInt) (fillValue & cMask)) >> cShift; idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + fillValue); } ds += dsX; dt += dtX; x += 1; } } /* Fill the span buffer between leftEdge and rightEdge using the given bits. Note: We always start from zero - this avoids using huge bitmap buffers if the bitmap is to be displayed at the very far right hand side and also gives us a chance of using certain bitmaps (e.g., those with depth 32) directly. */ static sqInt fillBitmapSpanfromto(int *bits, sqInt leftX, sqInt rightX) { sqInt baseShift; sqInt bitX; sqInt colorMask; sqInt colorShift; sqInt fillValue; sqInt x; sqInt x0; sqInt x1; x0 = leftX; x1 = rightX; /* Hack for pre-increment */ bitX = -1; if ((workBuffer[GWAALevel]) == 1) { while (x0 < x1) { fillValue = (((int *) bits))[(bitX += 1)]; spanBuffer[x0] = fillValue; x0 += 1; } } else { /* Generic version with anti-aliasing */ colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; baseShift = workBuffer[GWAAShift]; while (x0 < x1) { x = ((usqInt) x0) >> baseShift; fillValue = (((int *) bits))[(bitX += 1)]; fillValue = ((usqInt) (fillValue & colorMask)) >> colorShift; spanBuffer[x] = ((spanBuffer[x]) + fillValue); x0 += 1; } } if (x1 > (workBuffer[GWSpanEnd])) { workBuffer[GWSpanEnd] = x1; } if (x1 > (workBuffer[GWSpanEndAA])) { workBuffer[GWSpanEndAA] = x1; } } static sqInt fillBitmapSpanfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) { sqInt a; sqInt b; int *bits; sqInt bmDepth; sqInt bmHeight; sqInt bmRaster; sqInt bmWidth; sqInt cMask; sqInt deltaX; sqInt deltaY; sqInt ds; sqInt dsX; sqInt dt; sqInt dtX; sqInt fillValue; sqInt g; sqInt newDelta; sqInt newDelta1; sqInt r; sqInt rShift; sqInt someIntegerValue; sqInt tileFlag; sqInt value; sqInt x; sqInt x1; sqInt xp; sqInt yp; if (!((workBuffer[GWAALevel]) == 1)) { return fillBitmapSpanAAfromtoat(bmFill, leftX, rightX, yValue); } bits = loadBitsFrom(bmFill); if (bits == null) { return null; } bmWidth = objBuffer[bmFill + GBBitmapWidth]; bmHeight = objBuffer[bmFill + GBBitmapHeight]; tileFlag = (objBuffer[bmFill + GBTileFlag]) == 1; deltaX = leftX - (objBuffer[bmFill + GFOriginX]); deltaY = yValue - (objBuffer[bmFill + GFOriginY]); dsX = objBuffer[bmFill + GFDirectionX]; dtX = objBuffer[bmFill + GFNormalX]; ds = (deltaX * dsX) + (deltaY * (objBuffer[bmFill + GFDirectionY])); dt = (deltaX * dtX) + (deltaY * (objBuffer[bmFill + GFNormalY])); x = leftX; x1 = rightX; while (x < x1) { if (tileFlag) { /* begin repeatValue:max: */ newDelta = ds; while (newDelta < 0) { newDelta += bmWidth << 16; } while (newDelta >= (bmWidth << 16)) { newDelta -= bmWidth << 16; } ds = newDelta; /* begin repeatValue:max: */ newDelta1 = dt; while (newDelta1 < 0) { newDelta1 += bmHeight << 16; } while (newDelta1 >= (bmHeight << 16)) { newDelta1 -= bmHeight << 16; } dt = newDelta1; } xp = ((sqInt) ds >> 16); yp = ((sqInt) dt >> 16); if (!(tileFlag)) { /* begin clampValue:max: */ if (xp < 0) { xp = 0; goto l1; } else { if (xp >= bmWidth) { xp = bmWidth - 1; goto l1; } else { xp = xp; goto l1; } } l1: /* end clampValue:max: */; /* begin clampValue:max: */ if (yp < 0) { yp = 0; goto l2; } else { if (yp >= bmHeight) { yp = bmHeight - 1; goto l2; } else { yp = yp; goto l2; } } l2: /* end clampValue:max: */; } if ((xp >= 0) && ((yp >= 0) && ((xp < bmWidth) && (yp < bmHeight)))) { /* begin bitmapValue:bits:atX:y: */ bmDepth = objBuffer[bmFill + GBBitmapDepth]; bmRaster = objBuffer[bmFill + GBBitmapRaster]; if (bmDepth == 32) { value = (((int*) bits))[(bmRaster * yp) + xp]; if ((value != 0) && ((value & 4278190080UL) == 0)) { value = value | 4278190080UL; } fillValue = uncheckedTransformColor(value); goto l3; } rShift = (rShiftTable())[bmDepth]; /* cMask - mask out the pixel from the word */ value = (((int*) bits))[(bmRaster * yp) + (((usqInt) xp) >> rShift)]; /* rShift - shift value to move the pixel in the word to the lowest bit position */ cMask = (1 << bmDepth) - 1; rShift = (32 - bmDepth) - ((xp & ((1 << rShift) - 1)) * bmDepth); value = (((usqInt) value) >> rShift) & cMask; if (bmDepth == 16) { if (!(value == 0)) { /* Must convert by expanding bits */ b = (value & 31) << 3; b += ((usqInt) b) >> 5; g = ((((usqInt) value) >> 5) & 31) << 3; g += ((usqInt) g) >> 5; r = ((((usqInt) value) >> 10) & 31) << 3; r += ((usqInt) r) >> 5; a = 255; value = ((b + (g << 8)) + (r << 16)) + (a << 24); } } else { if ((objBuffer[bmFill + GBColormapSize]) == 0) { /* Must convert by using color map */ value = 0; } else { /* begin makeUnsignedFrom: */ someIntegerValue = (colormapOf(bmFill))[value]; value = someIntegerValue; } } fillValue = uncheckedTransformColor(value); l3: /* end bitmapValue:bits:atX:y: */; spanBuffer[x] = fillValue; } ds += dsX; dt += dtX; x += 1; } } /* This is the inner loop for solid color fills with anti-aliasing. This loop has been unrolled for speed and quality into three parts: a) copy all pixels that fall into the first full pixel. b) copy aaLevel pixels between the first and the last full pixel c) copy all pixels that fall in the last full pixel */ static sqInt fillColorSpanAAx0x1(sqInt pixelValue32, sqInt leftX, sqInt rightX) { sqInt aaLevel; sqInt baseShift; sqInt colorMask; sqInt firstPixel; sqInt firstPixel1; sqInt idx; sqInt lastPixel; sqInt pv32; sqInt x; /* begin aaFirstPixelFrom:to: */ firstPixel1 = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel1 > rightX) { firstPixel = rightX; goto l1; } else { firstPixel = firstPixel1; goto l1; } l1: /* end aaFirstPixelFrom:to: */; lastPixel = (rightX - 1) & (~((workBuffer[GWAALevel]) - 1)); aaLevel = workBuffer[GWAALevel]; baseShift = workBuffer[GWAAShift]; /* Part a: Deal with the first n sub-pixels */ x = leftX; if (x < firstPixel) { pv32 = ((usqInt) (pixelValue32 & (workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAColorShift]); while (x < firstPixel) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + pv32); x += 1; } } if (x < lastPixel) { colorMask = (((usqInt) (workBuffer[GWAAColorMask])) >> (workBuffer[GWAAShift])) | 4042322160UL; pv32 = ((usqInt) (pixelValue32 & colorMask)) >> (workBuffer[GWAAShift]); while (x < lastPixel) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + pv32); x += aaLevel; } } if (x < rightX) { pv32 = ((usqInt) (pixelValue32 & (workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAColorShift]); while (x < rightX) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + pv32); x += 1; } } } /* Fill the span buffer between leftEdge and rightEdge with the given pixel value. */ static sqInt fillColorSpanfromto(sqInt pixelValue32, sqInt leftX, sqInt rightX) { sqInt x0; sqInt x1; if (!((workBuffer[GWAALevel]) == 1)) { return fillColorSpanAAx0x1(pixelValue32, leftX, rightX); } x0 = leftX; /* Unroll the inner loop four times, since we're only storing data. */ x1 = rightX; while ((x0 + 4) < x1) { spanBuffer[x0] = pixelValue32; spanBuffer[x0 + 1] = pixelValue32; spanBuffer[x0 + 2] = pixelValue32; spanBuffer[x0 + 3] = pixelValue32; x0 += 4; } while (x0 < x1) { spanBuffer[x0] = pixelValue32; x0 += 1; } } static sqInt fillDirectionXOf(sqInt fill) { return objBuffer[fill + GFDirectionX]; } static sqInt fillDirectionXOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFDirectionX] = value; } static sqInt fillDirectionYOf(sqInt fill) { return objBuffer[fill + GFDirectionY]; } static sqInt fillDirectionYOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFDirectionY] = value; } static sqInt fillLinearGradient(void) { return fillLinearGradientfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); } /* This is the AA version of linear gradient filling. */ static sqInt fillLinearGradientAArampdsdsXfromto(sqInt fill, int *ramp, sqInt deltaS, sqInt dsX, sqInt leftX, sqInt rightX) { sqInt aaLevel; sqInt baseShift; sqInt colorMask; sqInt colorShift; sqInt ds; sqInt firstPixel; sqInt firstPixel1; sqInt idx; sqInt lastPixel; sqInt rampIndex; sqInt rampSize; sqInt rampValue; sqInt x; aaLevel = workBuffer[GWAALevel]; baseShift = workBuffer[GWAAShift]; rampSize = objBuffer[fill + GFRampLength]; ds = deltaS; x = leftX; rampIndex = ((sqInt) ds >> 16); /* begin aaFirstPixelFrom:to: */ firstPixel1 = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel1 > rightX) { firstPixel = rightX; goto l1; } else { firstPixel = firstPixel1; goto l1; } l1: /* end aaFirstPixelFrom:to: */; /* Deal with the first n sub-pixels */ lastPixel = (rightX - 1) & (~((workBuffer[GWAALevel]) - 1)); colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; while ((x < firstPixel) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; /* Copy as many pixels as possible */ rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < firstPixel) && ((((sqInt) ds >> 16)) == rampIndex)) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + rampValue); x += 1; ds += dsX; } rampIndex = ((sqInt) ds >> 16); } colorMask = (((usqInt) (workBuffer[GWAAColorMask])) >> (workBuffer[GWAAShift])) | 4042322160UL; colorShift = workBuffer[GWAAShift]; while ((x < lastPixel) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; /* Copy as many pixels as possible */ rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < lastPixel) && ((((sqInt) ds >> 16)) == rampIndex)) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + rampValue); x += aaLevel; ds += dsX << colorShift; } rampIndex = ((sqInt) ds >> 16); } colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; while ((x < rightX) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; /* Copy as many pixels as possible */ rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < rightX) && ((((sqInt) ds >> 16)) == rampIndex)) { idx = ((usqInt) x) >> baseShift; spanBuffer[idx] = ((spanBuffer[idx]) + rampValue); x += 1; ds += dsX; } rampIndex = ((sqInt) ds >> 16); } return x; } /* Draw a linear gradient fill. */ static sqInt fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) { sqInt ds; sqInt dsX; int *ramp; sqInt rampIndex; sqInt rampSize; sqInt x; sqInt x0; sqInt x01; sqInt x02; sqInt x1; sqInt x11; sqInt x12; /* begin gradientRampOf: */ ramp = (objBuffer + fill) + GFRampOffset; rampSize = objBuffer[fill + GFRampLength]; dsX = objBuffer[fill + GFDirectionX]; ds = ((leftX - (objBuffer[fill + GFOriginX])) * dsX) + ((yValue - (objBuffer[fill + GFOriginY])) * (objBuffer[fill + GFDirectionY])); x = x0 = leftX; /* Note: The inner loop has been divided into three parts for speed */ /* Part one: Fill everything outside the left boundary */ x1 = rightX; while (((((rampIndex = ((sqInt) ds >> 16))) < 0) || (rampIndex >= rampSize)) && (x < x1)) { x += 1; ds += dsX; } if (x > x0) { if (rampIndex < 0) { rampIndex = 0; } if (rampIndex >= rampSize) { rampIndex = rampSize - 1; } /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(ramp[rampIndex], x0, x); goto l1; } x01 = x0; /* Unroll the inner loop four times, since we're only storing data. */ x11 = x; while ((x01 + 4) < x11) { spanBuffer[x01] = (ramp[rampIndex]); spanBuffer[x01 + 1] = (ramp[rampIndex]); spanBuffer[x01 + 2] = (ramp[rampIndex]); spanBuffer[x01 + 3] = (ramp[rampIndex]); x01 += 4; } while (x01 < x11) { spanBuffer[x01] = (ramp[rampIndex]); x01 += 1; } l1: /* end fillColorSpan:from:to: */; } if ((workBuffer[GWAALevel]) == 1) { while (((((rampIndex = ((sqInt) ds >> 16))) < rampSize) && (rampIndex >= 0)) && (x < x1)) { spanBuffer[x] = (ramp[rampIndex]); x += 1; ds += dsX; } } else { x = fillLinearGradientAArampdsdsXfromto(fill, ramp, ds, dsX, x, rightX); } if (x < x1) { if (rampIndex < 0) { rampIndex = 0; } if (rampIndex >= rampSize) { rampIndex = rampSize - 1; } /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(ramp[rampIndex], x, x1); goto l2; } x02 = x; /* Unroll the inner loop four times, since we're only storing data. */ x12 = x1; while ((x02 + 4) < x12) { spanBuffer[x02] = (ramp[rampIndex]); spanBuffer[x02 + 1] = (ramp[rampIndex]); spanBuffer[x02 + 2] = (ramp[rampIndex]); spanBuffer[x02 + 3] = (ramp[rampIndex]); x02 += 4; } while (x02 < x12) { spanBuffer[x02] = (ramp[rampIndex]); x02 += 1; } l2: /* end fillColorSpan:from:to: */; } } static sqInt fillMaxXGet(void) { return workBuffer[GWFillMaxX]; } static sqInt fillMaxXPut(sqInt value) { return workBuffer[GWFillMaxX] = value; } static sqInt fillMaxYGet(void) { return workBuffer[GWFillMaxY]; } static sqInt fillMaxYPut(sqInt value) { return workBuffer[GWFillMaxY] = value; } static sqInt fillMinXGet(void) { return workBuffer[GWFillMinX]; } static sqInt fillMinXPut(sqInt value) { return workBuffer[GWFillMinX] = value; } static sqInt fillMinYGet(void) { return workBuffer[GWFillMinY]; } static sqInt fillMinYPut(sqInt value) { return workBuffer[GWFillMinY] = value; } static sqInt fillNormalXOf(sqInt fill) { return objBuffer[fill + GFNormalX]; } static sqInt fillNormalXOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFNormalX] = value; } static sqInt fillNormalYOf(sqInt fill) { return objBuffer[fill + GFNormalY]; } static sqInt fillNormalYOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFNormalY] = value; } static sqInt fillOffsetXGet(void) { return workBuffer[GWFillOffsetX]; } static sqInt fillOffsetXPut(sqInt value) { return workBuffer[GWFillOffsetX] = value; } static sqInt fillOffsetYGet(void) { return workBuffer[GWFillOffsetY]; } static sqInt fillOffsetYPut(sqInt value) { return workBuffer[GWFillOffsetY] = value; } static sqInt fillOriginXOf(sqInt fill) { return objBuffer[fill + GFOriginX]; } static sqInt fillOriginXOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFOriginX] = value; } static sqInt fillOriginYOf(sqInt fill) { return objBuffer[fill + GFOriginY]; } static sqInt fillOriginYOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFOriginY] = value; } /* Part 2a) Compute the decreasing part of the ramp */ static sqInt fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX) { sqInt aaLevel; sqInt baseShift; sqInt colorMask; sqInt colorShift; sqInt ds; sqInt dt; sqInt firstPixel; sqInt firstPixel1; sqInt index; sqInt lastPixel; sqInt length2; sqInt nextLength; sqInt rampIndex; sqInt rampValue; sqInt x; sqInt x1; ds = (((int*) deltaST))[0]; dt = (((int*) deltaST))[1]; aaLevel = workBuffer[GWAALevel]; baseShift = workBuffer[GWAAShift]; rampIndex = accurateLengthOfwith(((sqInt) ds >> 16), ((sqInt) dt >> 16)); length2 = (rampIndex - 1) * (rampIndex - 1); x = leftX; x1 = objBuffer[fill + GFOriginX]; if (x1 > rightX) { x1 = rightX; } /* begin aaFirstPixelFrom:to: */ firstPixel1 = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel1 > x1) { firstPixel = x1; goto l1; } else { firstPixel = firstPixel1; goto l1; } l1: /* end aaFirstPixelFrom:to: */; /* Deal with the first n sub-pixels */ lastPixel = (x1 - 1) & (~((workBuffer[GWAALevel]) - 1)); if (x < firstPixel) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while (x < firstPixel) { while ((x < firstPixel) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) >= length2)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += 1; ds += dsX; dt += dtX; } nextLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (nextLength < length2) { rampIndex -= 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; length2 = (rampIndex - 1) * (rampIndex - 1); } } } if (x < lastPixel) { colorMask = (((usqInt) (workBuffer[GWAAColorMask])) >> (workBuffer[GWAAShift])) | 4042322160UL; colorShift = workBuffer[GWAAShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while (x < lastPixel) { while ((x < lastPixel) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) >= length2)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += aaLevel; ds += dsX << colorShift; dt += dtX << colorShift; } nextLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (nextLength < length2) { rampIndex -= 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; length2 = (rampIndex - 1) * (rampIndex - 1); } } } if (x < x1) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while (x < x1) { while ((x < x1) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) >= length2)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += 1; ds += dsX; dt += dtX; } nextLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (nextLength < length2) { rampIndex -= 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; length2 = (rampIndex - 1) * (rampIndex - 1); } } } (((int *) deltaST))[0] = ds; (((int *) deltaST))[1] = dt; return x; } /* Part 2a) Compute the decreasing part of the ramp */ static sqInt fillRadialDecreasingrampdeltaSTdsXdtXfromto(sqInt fill, sqInt ramp, sqInt deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX) { sqInt ds; sqInt dt; sqInt length2; sqInt nextLength; sqInt rampIndex; sqInt rampValue; sqInt x; sqInt x1; ds = (((int*) deltaST))[0]; dt = (((int*) deltaST))[1]; rampIndex = accurateLengthOfwith(((sqInt) ds >> 16), ((sqInt) dt >> 16)); rampValue = (((int *) ramp))[rampIndex]; length2 = (rampIndex - 1) * (rampIndex - 1); x = leftX; x1 = rightX; if (x1 > (objBuffer[fill + GFOriginX])) { x1 = objBuffer[fill + GFOriginX]; } while (x < x1) { while ((x < x1) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) >= length2)) { spanBuffer[x] = rampValue; x += 1; ds += dsX; dt += dtX; } nextLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (nextLength < length2) { rampIndex -= 1; rampValue = (((int *) ramp))[rampIndex]; length2 = (rampIndex - 1) * (rampIndex - 1); } } (((int *) deltaST))[0] = ds; (((int *) deltaST))[1] = dt; return x; } static sqInt fillRadialGradient(void) { return fillRadialGradientfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); } /* Draw a radial gradient fill. */ static sqInt fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) { int *deltaST; sqInt deltaX; sqInt deltaY; sqInt ds; sqInt ds1; sqInt ds2; sqInt dsX; sqInt dt; sqInt dt1; sqInt dt2; sqInt dtX; sqInt lastLength; sqInt length2; sqInt length21; sqInt length22; sqInt nextLength; sqInt nextLength1; int *ramp; sqInt rampIndex; sqInt rampIndex1; sqInt rampSize; sqInt rampSize1; sqInt rampValue; sqInt rampValue1; sqInt x; sqInt x0; sqInt x01; sqInt x1; sqInt x11; sqInt x12; sqInt x13; sqInt x14; sqInt x2; sqInt x3; /* begin gradientRampOf: */ ramp = (objBuffer + fill) + GFRampOffset; rampSize = objBuffer[fill + GFRampLength]; deltaX = leftX - (objBuffer[fill + GFOriginX]); deltaY = yValue - (objBuffer[fill + GFOriginY]); dsX = objBuffer[fill + GFDirectionX]; dtX = objBuffer[fill + GFNormalX]; ds = (deltaX * dsX) + (deltaY * (objBuffer[fill + GFDirectionY])); dt = (deltaX * dtX) + (deltaY * (objBuffer[fill + GFNormalY])); x = leftX; /* Note: The inner loop has been divided into three parts for speed */ /* Part one: Fill everything outside the left boundary */ x1 = rightX; /* This is the upper bound */ length2 = (rampSize - 1) * (rampSize - 1); while (((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) >= length2) && (x < x1)) { x += 1; ds += dsX; dt += dtX; } if (x > leftX) { /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(ramp[rampSize - 1], leftX, x); goto l1; } x0 = leftX; /* Unroll the inner loop four times, since we're only storing data. */ x11 = x; while ((x0 + 4) < x11) { spanBuffer[x0] = (ramp[rampSize - 1]); spanBuffer[x0 + 1] = (ramp[rampSize - 1]); spanBuffer[x0 + 2] = (ramp[rampSize - 1]); spanBuffer[x0 + 3] = (ramp[rampSize - 1]); x0 += 4; } while (x0 < x11) { spanBuffer[x0] = (ramp[rampSize - 1]); x0 += 1; } l1: /* end fillColorSpan:from:to: */; } /* begin point1Get */ deltaST = ((int *) (workBuffer + GWPoint1)); deltaST[0] = ds; deltaST[1] = dt; if (x < (objBuffer[fill + GFOriginX])) { if ((workBuffer[GWAALevel]) == 1) { /* begin fillRadialDecreasing:ramp:deltaST:dsX:dtX:from:to: */ ds1 = (((int*) deltaST))[0]; dt1 = (((int*) deltaST))[1]; rampIndex = accurateLengthOfwith(((sqInt) ds1 >> 16), ((sqInt) dt1 >> 16)); rampValue = (((int *) ramp))[rampIndex]; length21 = (rampIndex - 1) * (rampIndex - 1); x2 = x; x12 = x1; if (x12 > (objBuffer[fill + GFOriginX])) { x12 = objBuffer[fill + GFOriginX]; } while (x2 < x12) { while ((x2 < x12) && ((((((sqInt) ds1 >> 16)) * (((sqInt) ds1 >> 16))) + ((((sqInt) dt1 >> 16)) * (((sqInt) dt1 >> 16)))) >= length21)) { spanBuffer[x2] = rampValue; x2 += 1; ds1 += dsX; dt1 += dtX; } nextLength = ((((sqInt) ds1 >> 16)) * (((sqInt) ds1 >> 16))) + ((((sqInt) dt1 >> 16)) * (((sqInt) dt1 >> 16))); while (nextLength < length21) { rampIndex -= 1; rampValue = (((int *) ramp))[rampIndex]; length21 = (rampIndex - 1) * (rampIndex - 1); } } (((int *) deltaST))[0] = ds1; (((int *) deltaST))[1] = dt1; x = x2; } else { x = fillRadialDecreasingAArampdeltaSTdsXdtXfromto(fill, ramp, deltaST, dsX, dtX, x, x1); } } if (x < x1) { if ((workBuffer[GWAALevel]) == 1) { /* begin fillRadialIncreasing:ramp:deltaST:dsX:dtX:from:to: */ ds2 = (((int*) deltaST))[0]; dt2 = (((int*) deltaST))[1]; rampIndex1 = accurateLengthOfwith(((sqInt) ds2 >> 16), ((sqInt) dt2 >> 16)); rampValue1 = (((int *) ramp))[rampIndex1]; rampSize1 = objBuffer[fill + GFRampLength]; /* This is the upper bound */ length22 = (rampSize1 - 1) * (rampSize1 - 1); nextLength1 = (rampIndex1 + 1) * (rampIndex1 + 1); lastLength = ((((sqInt) ds2 >> 16)) * (((sqInt) ds2 >> 16))) + ((((sqInt) dt2 >> 16)) * (((sqInt) dt2 >> 16))); x3 = x; x14 = x1; while ((x3 < x14) && (lastLength < length22)) { while ((x3 < x14) && ((((((sqInt) ds2 >> 16)) * (((sqInt) ds2 >> 16))) + ((((sqInt) dt2 >> 16)) * (((sqInt) dt2 >> 16)))) <= nextLength1)) { spanBuffer[x3] = rampValue1; x3 += 1; ds2 += dsX; dt2 += dtX; } lastLength = ((((sqInt) ds2 >> 16)) * (((sqInt) ds2 >> 16))) + ((((sqInt) dt2 >> 16)) * (((sqInt) dt2 >> 16))); while (lastLength > nextLength1) { rampIndex1 += 1; rampValue1 = (((int *) ramp))[rampIndex1]; nextLength1 = (rampIndex1 + 1) * (rampIndex1 + 1); } } (((int *) deltaST))[0] = ds2; (((int *) deltaST))[1] = dt2; x = x3; } else { x = fillRadialIncreasingAArampdeltaSTdsXdtXfromto(fill, ramp, deltaST, dsX, dtX, x, x1); } } if (x < rightX) { /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(ramp[rampSize - 1], x, rightX); goto l2; } x01 = x; /* Unroll the inner loop four times, since we're only storing data. */ x13 = rightX; while ((x01 + 4) < x13) { spanBuffer[x01] = (ramp[rampSize - 1]); spanBuffer[x01 + 1] = (ramp[rampSize - 1]); spanBuffer[x01 + 2] = (ramp[rampSize - 1]); spanBuffer[x01 + 3] = (ramp[rampSize - 1]); x01 += 4; } while (x01 < x13) { spanBuffer[x01] = (ramp[rampSize - 1]); x01 += 1; } l2: /* end fillColorSpan:from:to: */; } } /* Part 2b) Compute the increasing part of the ramp */ static sqInt fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX) { sqInt aaLevel; sqInt baseShift; sqInt colorMask; sqInt colorShift; sqInt ds; sqInt dt; sqInt firstPixel; sqInt firstPixel1; sqInt index; sqInt lastLength; sqInt lastPixel; sqInt length2; sqInt nextLength; sqInt rampIndex; sqInt rampSize; sqInt rampValue; sqInt x; ds = (((int*) deltaST))[0]; dt = (((int*) deltaST))[1]; aaLevel = workBuffer[GWAALevel]; baseShift = workBuffer[GWAAShift]; rampIndex = accurateLengthOfwith(((sqInt) ds >> 16), ((sqInt) dt >> 16)); rampSize = objBuffer[fill + GFRampLength]; /* This is the upper bound */ length2 = (rampSize - 1) * (rampSize - 1); nextLength = (rampIndex + 1) * (rampIndex + 1); lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); x = leftX; /* begin aaFirstPixelFrom:to: */ firstPixel1 = ((leftX + (workBuffer[GWAALevel])) - 1) & (~((workBuffer[GWAALevel]) - 1)); if (firstPixel1 > rightX) { firstPixel = rightX; goto l1; } else { firstPixel = firstPixel1; goto l1; } l1: /* end aaFirstPixelFrom:to: */; /* Deal with the first n subPixels */ lastPixel = (rightX - 1) & (~((workBuffer[GWAALevel]) - 1)); if ((x < firstPixel) && (lastLength < length2)) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < firstPixel) && (lastLength < length2)) { while ((x < firstPixel) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) <= nextLength)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += 1; ds += dsX; dt += dtX; } lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (lastLength > nextLength) { rampIndex += 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; nextLength = (rampIndex + 1) * (rampIndex + 1); } } } if ((x < lastPixel) && (lastLength < length2)) { colorMask = (((usqInt) (workBuffer[GWAAColorMask])) >> (workBuffer[GWAAShift])) | 4042322160UL; colorShift = workBuffer[GWAAShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < lastPixel) && (lastLength < length2)) { while ((x < lastPixel) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) <= nextLength)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += aaLevel; ds += dsX << colorShift; dt += dtX << colorShift; } lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (lastLength > nextLength) { rampIndex += 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; nextLength = (rampIndex + 1) * (rampIndex + 1); } } } if ((x < rightX) && (lastLength < length2)) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; while ((x < rightX) && (lastLength < length2)) { while ((x < rightX) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) <= nextLength)) { index = ((usqInt) x) >> baseShift; spanBuffer[index] = ((spanBuffer[index]) + rampValue); x += 1; ds += dsX; dt += dtX; } lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (lastLength > nextLength) { rampIndex += 1; rampValue = (((int *) ramp))[rampIndex]; rampValue = ((usqInt) (rampValue & colorMask)) >> colorShift; nextLength = (rampIndex + 1) * (rampIndex + 1); } } } (((int *) deltaST))[0] = ds; (((int *) deltaST))[1] = dt; return x; } /* Part 2b) Compute the increasing part of the ramp */ static sqInt fillRadialIncreasingrampdeltaSTdsXdtXfromto(sqInt fill, sqInt ramp, sqInt deltaST, sqInt dsX, sqInt dtX, sqInt leftX, sqInt rightX) { sqInt ds; sqInt dt; sqInt lastLength; sqInt length2; sqInt nextLength; sqInt rampIndex; sqInt rampSize; sqInt rampValue; sqInt x; sqInt x1; ds = (((int*) deltaST))[0]; dt = (((int*) deltaST))[1]; rampIndex = accurateLengthOfwith(((sqInt) ds >> 16), ((sqInt) dt >> 16)); rampValue = (((int *) ramp))[rampIndex]; rampSize = objBuffer[fill + GFRampLength]; /* This is the upper bound */ length2 = (rampSize - 1) * (rampSize - 1); nextLength = (rampIndex + 1) * (rampIndex + 1); lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); x = leftX; x1 = rightX; while ((x < x1) && (lastLength < length2)) { while ((x < x1) && ((((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16)))) <= nextLength)) { spanBuffer[x] = rampValue; x += 1; ds += dsX; dt += dtX; } lastLength = ((((sqInt) ds >> 16)) * (((sqInt) ds >> 16))) + ((((sqInt) dt >> 16)) * (((sqInt) dt >> 16))); while (lastLength > nextLength) { rampIndex += 1; rampValue = (((int *) ramp))[rampIndex]; nextLength = (rampIndex + 1) * (rampIndex + 1); } } (((int *) deltaST))[0] = ds; (((int *) deltaST))[1] = dt; return x; } /* Return true if fillEntry1 should be drawn before fillEntry2 */ static sqInt fillSortsbefore(sqInt fillEntry1, sqInt fillEntry2) { sqInt diff; /* First check the depth value */ diff = (workBuffer[(workBuffer[GWBufferTop]) + (fillEntry1 + 1)]) - (workBuffer[(workBuffer[GWBufferTop]) + (fillEntry2 + 1)]); if (!(diff == 0)) { return diff > 0; } return (((unsigned) (workBuffer[(workBuffer[GWBufferTop]) + fillEntry1]))) < (((unsigned) (workBuffer[(workBuffer[GWBufferTop]) + fillEntry2]))); } /* Fill the span buffer from leftX to rightX with the given fill. Clip before performing any operations. Return true if the fill must be handled by some Smalltalk code. */ static sqInt fillSpanfromto(unsigned int fill, sqInt leftX, sqInt rightX) { sqInt type; sqInt x0; sqInt x01; sqInt x1; sqInt x11; if (fill == 0) { return 0; } if (leftX < (workBuffer[GWSpanEndAA])) { x0 = workBuffer[GWSpanEndAA]; } else { x0 = leftX; } if (rightX > ((workBuffer[GWSpanSize]) << (workBuffer[GWAAShift]))) { x1 = (workBuffer[GWSpanSize]) << (workBuffer[GWAAShift]); } else { x1 = rightX; } if (x0 < (workBuffer[GWFillMinX])) { x0 = workBuffer[GWFillMinX]; } if (x1 > (workBuffer[GWFillMaxX])) { x1 = workBuffer[GWFillMaxX]; } if (x0 < (workBuffer[GWSpanStart])) { workBuffer[GWSpanStart] = x0; } if (x1 > (workBuffer[GWSpanEnd])) { workBuffer[GWSpanEnd] = x1; } if (x1 > (workBuffer[GWSpanEndAA])) { workBuffer[GWSpanEndAA] = x1; } if (x0 >= x1) { return 0; } if ((fill & 4278190080UL) != 0) { /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(fill, x0, x1); goto l1; } x01 = x0; /* Unroll the inner loop four times, since we're only storing data. */ x11 = x1; while ((x01 + 4) < x11) { spanBuffer[x01] = fill; spanBuffer[x01 + 1] = fill; spanBuffer[x01 + 2] = fill; spanBuffer[x01 + 3] = fill; x01 += 4; } while (x01 < x11) { spanBuffer[x01] = fill; x01 += 1; } l1: /* end fillColorSpan:from:to: */; } else { workBuffer[GWLastExportedFill] = fill; workBuffer[GWLastExportedLeftX] = x0; workBuffer[GWLastExportedRightX] = x1; type = ((usqInt) (((objBuffer[fill + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveFillMask)) >> 8; if (type <= 1) { return 1; } switch (type) { case 0: case 1: errorWrongIndex(); break; case 2: fillLinearGradientfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); break; case 3: fillRadialGradientfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); break; case 4: case 5: fillBitmapSpanfromtoat(workBuffer[GWLastExportedFill], workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX], workBuffer[GWCurrentY]); break; } } return 0; } static sqInt fillTypeOf(sqInt fill) { return ((usqInt) (((objBuffer[fill + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveFillMask)) >> 8; } static sqInt findNextAETEdgeFrom(sqInt leftEdge) { sqInt depth; sqInt rightEdge; depth = objBuffer[leftEdge + GEZValue]; while ((workBuffer[GWAETStart]) < (workBuffer[GWAETUsed])) { rightEdge = aetBuffer[workBuffer[GWAETStart]]; if ((objBuffer[rightEdge + GEZValue]) >= depth) { return rightEdge; } workBuffer[GWAETStart] = ((workBuffer[GWAETStart]) + 1); } return null; } /* Check the global edge table for any entries that cannot be handled by the engine itself. If there are any, return true. Otherwise, initialize the the edge and add it to the AET */ static sqInt findNextExternalEntryFromGET(void) { sqInt edge; sqInt type; sqInt yValue; /* As long as we have entries in the GET */ yValue = workBuffer[GWCurrentY]; while ((workBuffer[GWGETStart]) < (workBuffer[GWGETUsed])) { edge = getBuffer[workBuffer[GWGETStart]]; if ((objBuffer[edge + GEYValue]) > yValue) { return 0; } type = (objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask; if ((type & GEPrimitiveWideMask) == GEPrimitiveEdge) { return 1; } if (!(needAvailableSpace(1))) { return 0; } switch (type) { case 0: case 1: case 2: case 3: errorWrongIndex(); break; case 4: stepToFirstLineInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); break; case 5: stepToFirstWideLineInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); break; case 6: stepToFirstBezierInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); break; case 7: stepToFirstWideBezierInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); break; } insertEdgeIntoAET(edge); workBuffer[GWGETStart] = ((workBuffer[GWGETStart]) + 1); } return 0; } /* Scan the active edge table. If there is any fill that cannot be handled by the engine itself, return true. Otherwise handle the fills and return false. */ /* self currentYGet >= 680 ifTrue:[ self printAET. self halt. ]. */ static sqInt findNextExternalFillFromAET(void) { sqInt fill; sqInt fill1; sqInt leftEdge; sqInt leftX; sqInt rightEdge; sqInt rightX; sqInt someIntegerValue; sqInt someIntegerValue1; sqInt someIntegerValue11; sqInt someIntegerValue2; sqInt startX; sqInt startX1; sqInt stopX; sqInt stopX1; leftX = rightX = workBuffer[GWFillMaxX]; while ((workBuffer[GWAETStart]) < (workBuffer[GWAETUsed])) { /* TODO: We should check if leftX from last operation is greater than leftX from next edge. Currently, we rely here on spanEndAA from the span buffer fill. */ leftEdge = rightEdge = aetBuffer[workBuffer[GWAETStart]]; leftX = rightX = objBuffer[leftEdge + GEXValue]; if (leftX >= (workBuffer[GWFillMaxX])) { return 0; } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l3; } while ((topRightX()) <= leftX) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l3; } } l3: /* end quickRemoveInvalidFillsAt: */; if ((((objBuffer[leftEdge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { toggleWideFillOf(leftEdge); } if (((objBuffer[leftEdge + GEObjectType]) & GEEdgeFillsInvalid) == 0) { toggleFillsOf(leftEdge); if (engineStopped) { return 0; } } workBuffer[GWAETStart] = ((workBuffer[GWAETStart]) + 1); if ((workBuffer[GWAETStart]) < (workBuffer[GWAETUsed])) { rightEdge = aetBuffer[workBuffer[GWAETStart]]; rightX = objBuffer[rightEdge + GEXValue]; if (rightX >= (workBuffer[GWFillMinX])) { /* begin fillAllFrom:to: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { fill = 0; goto l8; } else { fill = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l8; } l8: /* end topFill */; startX = leftX; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX = 999999999; goto l9; } else { stopX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l9; } l9: /* end topRightX */; while (stopX < rightX) { /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue = 0; goto l6; } else { someIntegerValue = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l6; } l6: /* end topFill */; fill = someIntegerValue; if (!(fill == 0)) { if (fillSpanfromto(fill, startX, stopX)) { goto l2; } } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } while ((topRightX()) <= stopX) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } } l1: /* end quickRemoveInvalidFillsAt: */; startX = stopX; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX = 999999999; goto l7; } else { stopX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l7; } l7: /* end topRightX */; } /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue1 = 0; goto l10; } else { someIntegerValue1 = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l10; } l10: /* end topFill */; fill = someIntegerValue1; if (!(fill == 0)) { fillSpanfromto(fill, startX, rightX); goto l2; } l2: /* end fillAllFrom:to: */; } } } if (rightX < (workBuffer[GWFillMaxX])) { /* begin fillAllFrom:to: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { fill1 = 0; goto l13; } else { fill1 = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l13; } l13: /* end topFill */; startX1 = rightX; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX1 = 999999999; goto l14; } else { stopX1 = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l14; } l14: /* end topRightX */; while (stopX1 < (workBuffer[GWFillMaxX])) { /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue2 = 0; goto l11; } else { someIntegerValue2 = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l11; } l11: /* end topFill */; fill1 = someIntegerValue2; if (!(fill1 == 0)) { if (fillSpanfromto(fill1, startX1, stopX1)) { goto l5; } } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l4; } while ((topRightX()) <= stopX1) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l4; } } l4: /* end quickRemoveInvalidFillsAt: */; startX1 = stopX1; /* begin topRightX */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { stopX1 = 999999999; goto l12; } else { stopX1 = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; goto l12; } l12: /* end topRightX */; } /* begin makeUnsignedFrom: */ /* begin topFill */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { someIntegerValue11 = 0; goto l15; } else { someIntegerValue11 = workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; goto l15; } l15: /* end topFill */; fill1 = someIntegerValue11; if (!(fill1 == 0)) { fillSpanfromto(fill1, startX1, workBuffer[GWFillMaxX]); goto l5; } l5: /* end fillAllFrom:to: */; } return 0; } /* Check the active edge table for any entries that cannot be handled by the engine itself. If there are any, return true. Otherwise, step the the edge to the next y value. */ static sqInt findNextExternalUpdateFromAET(void) { sqInt count; sqInt edge; sqInt type; while ((workBuffer[GWAETStart]) < (workBuffer[GWAETUsed])) { edge = aetBuffer[workBuffer[GWAETStart]]; count = (objBuffer[edge + GENumLines]) - 1; if (count == 0) { removeFirstAETEntry(); } else { objBuffer[edge + GENumLines] = count; type = (objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask; if ((type & GEPrimitiveWideMask) == GEPrimitiveEdge) { return 1; } switch (type) { case 0: case 1: case 2: case 3: errorWrongIndex(); break; case 4: stepToNextLineInat(aetBuffer[workBuffer[GWAETStart]], workBuffer[GWCurrentY]); break; case 5: stepToNextWideLineInat(aetBuffer[workBuffer[GWAETStart]], workBuffer[GWCurrentY]); break; case 6: stepToNextBezierInat(aetBuffer[workBuffer[GWAETStart]], workBuffer[GWCurrentY]); break; case 7: stepToNextWideBezier(); break; } resortFirstAETEntry(); workBuffer[GWAETStart] = ((workBuffer[GWAETStart]) + 1); } } return 0; } static sqInt findStackFilldepth(sqInt fillIndex, sqInt depth) { sqInt index; index = 0; while ((index < ((workBuffer[GWSize]) - (workBuffer[GWBufferTop]))) && (((workBuffer[(workBuffer[GWBufferTop]) + index]) != fillIndex) || ((workBuffer[(workBuffer[GWBufferTop]) + (index + 1)]) != depth))) { index += 3; } if (index >= ((workBuffer[GWSize]) - (workBuffer[GWBufferTop]))) { return -1; } else { return index; } } /* Return true if processing is finished */ static sqInt finishedProcessing(void) { return (workBuffer[GWState]) == GEStateCompleted; } static sqInt firstPointListGet(void) { return workBuffer[GWPointListFirst]; } static sqInt firstPointListPut(sqInt value) { return workBuffer[GWPointListFirst] = value; } static sqInt freeStackFillEntry(void) { /* begin wbStackPop: */ workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) + 3); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } /* Return true if the edge at index i should sort before the edge at index j. */ static sqInt getSortsbefore(sqInt edge1, sqInt edge2) { sqInt diff; if (edge1 == edge2) { return 1; } diff = (objBuffer[edge1 + GEYValue]) - (objBuffer[edge2 + GEYValue]); if (!(diff == 0)) { return diff < 0; } diff = (objBuffer[edge1 + GEXValue]) - (objBuffer[edge2 + GEXValue]); return diff < 0; } static sqInt getStartGet(void) { return workBuffer[GWGETStart]; } static sqInt getStartPut(sqInt value) { return workBuffer[GWGETStart] = value; } static sqInt getUsedGet(void) { return workBuffer[GWGETUsed]; } static sqInt getUsedPut(sqInt value) { return workBuffer[GWGETUsed] = value; } static sqInt gradientRampLengthOf(sqInt fill) { return objBuffer[fill + GFRampLength]; } static sqInt gradientRampLengthOfput(sqInt fill, sqInt value) { return objBuffer[fill + GFRampLength] = value; } static int * gradientRampOf(sqInt fill) { return (objBuffer + fill) + GFRampOffset; } static sqInt halt(void) { ; return 0; } static sqInt hasColorTransform(void) { return (workBuffer[GWHasColorTransform]) != 0; } static sqInt hasColorTransformGet(void) { return workBuffer[GWHasColorTransform]; } static sqInt hasColorTransformPut(sqInt value) { return workBuffer[GWHasColorTransform] = value; } static sqInt hasEdgeTransform(void) { return (workBuffer[GWHasEdgeTransform]) != 0; } static sqInt hasEdgeTransformGet(void) { return workBuffer[GWHasEdgeTransform]; } static sqInt hasEdgeTransformPut(sqInt value) { return workBuffer[GWHasEdgeTransform] = value; } /* Make the fill style with the given index invisible */ static sqInt hideFilldepth(sqInt fillIndex, sqInt depth) { sqInt index; sqInt newDepth; sqInt newRightX; sqInt newTop; sqInt newTopIndex; index = findStackFilldepth(fillIndex, depth); if (index == -1) { return 0; } if (index == 0) { /* begin freeStackFillEntry */ /* begin wbStackPop: */ workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) + 3); return 1; } workBuffer[(workBuffer[GWBufferTop]) + index] = (workBuffer[(workBuffer[GWBufferTop]) + 0]); workBuffer[(workBuffer[GWBufferTop]) + (index + 1)] = (workBuffer[(workBuffer[GWBufferTop]) + (0 + 1)]); workBuffer[(workBuffer[GWBufferTop]) + (index + 2)] = (workBuffer[(workBuffer[GWBufferTop]) + (0 + 2)]); /* begin freeStackFillEntry */ /* begin wbStackPop: */ workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) + 3); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) <= 3) { return 1; } newTopIndex = 0; index = 3; while (index < ((workBuffer[GWSize]) - (workBuffer[GWBufferTop]))) { if (fillSortsbefore(index, newTopIndex)) { newTopIndex = index; } index += 3; } if ((newTopIndex + 3) == ((workBuffer[GWSize]) - (workBuffer[GWBufferTop]))) { return 1; } newTop = workBuffer[(workBuffer[GWBufferTop]) + newTopIndex]; workBuffer[(workBuffer[GWBufferTop]) + newTopIndex] = (workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]); workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)] = newTop; newDepth = workBuffer[(workBuffer[GWBufferTop]) + (newTopIndex + 1)]; workBuffer[(workBuffer[GWBufferTop]) + (newTopIndex + 1)] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)] = newDepth; newRightX = workBuffer[(workBuffer[GWBufferTop]) + (newTopIndex + 2)]; workBuffer[(workBuffer[GWBufferTop]) + (newTopIndex + 2)] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)] = newRightX; return 1; } static sqInt incrementPointby(int *point, sqInt delta) { point[0] = ((point[0]) + delta); point[1] = ((point[1]) + delta); } static sqInt incrementStatby(sqInt statIndex, sqInt value) { return workBuffer[statIndex] = ((workBuffer[statIndex]) + value); } /* Find insertion point for the given edge in the AET */ static sqInt indexForInsertingIntoAET(sqInt edge) { sqInt index; sqInt initialX; initialX = objBuffer[edge + GEXValue]; index = 0; while ((index < (workBuffer[GWAETUsed])) && ((objBuffer[(aetBuffer[index]) + GEXValue]) < initialX)) { index += 1; } while ((index < (workBuffer[GWAETUsed])) && (((objBuffer[(aetBuffer[index]) + GEXValue]) == initialX) && (getSortsbefore(aetBuffer[index], edge)))) { index += 1; } return index; } static sqInt initColorTransform(void) { float *transform; /* begin colorTransform */ transform = ((float *) (workBuffer + GWColorTransform)); transform[0] = (((float) 1.0)); transform[1] = (((float) 0.0)); transform[2] = (((float) 1.0)); transform[3] = (((float) 0.0)); transform[4] = (((float) 1.0)); transform[5] = (((float) 0.0)); transform[6] = (((float) 1.0)); transform[7] = (((float) 0.0)); workBuffer[GWHasColorTransform] = 0; } static sqInt initEdgeTransform(void) { float *transform; /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); transform[0] = (((float) 1.0)); transform[1] = (((float) 0.0)); transform[2] = (((float) 0.0)); transform[3] = (((float) 0.0)); transform[4] = (((float) 1.0)); transform[5] = (((float) 0.0)); workBuffer[GWHasEdgeTransform] = 0; } EXPORT(sqInt) initialiseModule(void) { loadBBFn = interpreterProxy->ioLoadFunctionFrom("loadBitBltFrom", bbPluginName); copyBitsFn = interpreterProxy->ioLoadFunctionFrom("copyBitsFromtoat", bbPluginName); return (loadBBFn != 0) && (copyBitsFn != 0); } /* Initialization stuff that needs to be done before any processing can take place. */ /* Make sure aaLevel is initialized */ static sqInt initializeGETProcessing(void) { setAALevel(workBuffer[GWAALevel]); if ((workBuffer[GWClipMinX]) < 0) { workBuffer[GWClipMinX] = 0; } if ((workBuffer[GWClipMaxX]) > (workBuffer[GWSpanSize])) { workBuffer[GWClipMaxX] = (workBuffer[GWSpanSize]); } workBuffer[GWFillMinX] = ((workBuffer[GWClipMinX]) << (workBuffer[GWAAShift])); workBuffer[GWFillMinY] = ((workBuffer[GWClipMinY]) << (workBuffer[GWAAShift])); workBuffer[GWFillMaxX] = ((workBuffer[GWClipMaxX]) << (workBuffer[GWAAShift])); workBuffer[GWFillMaxY] = ((workBuffer[GWClipMaxY]) << (workBuffer[GWAAShift])); workBuffer[GWGETUsed] = 0; workBuffer[GWAETUsed] = 0; getBuffer = objBuffer + objUsed; /* Create the global edge table */ aetBuffer = objBuffer + objUsed; createGlobalEdgeTable(); if (engineStopped) { return null; } if ((workBuffer[GWGETUsed]) == 0) { workBuffer[GWCurrentY] = (workBuffer[GWFillMaxY]); return 0; } /* begin sortGlobalEdgeTable */ quickSortGlobalEdgeTablefromto(getBuffer, 0, (workBuffer[GWGETUsed]) - 1); workBuffer[GWCurrentY] = (objBuffer[(getBuffer[0]) + GEYValue]); if ((workBuffer[GWCurrentY]) < (workBuffer[GWFillMinY])) { workBuffer[GWCurrentY] = (workBuffer[GWFillMinY]); } workBuffer[GWSpanStart] = 0; workBuffer[GWSpanEnd] = (((workBuffer[GWSpanSize]) << (workBuffer[GWAAShift])) - 1); clearSpanBuffer(); } /* Insert the edge with the given index from the global edge table into the active edge table. The edge has already been stepped to the initial yValue -- thus remainingLines and rasterX are both set. */ static sqInt insertEdgeIntoAET(sqInt edge) { sqInt index; if ((objBuffer[edge + GENumLines]) <= 0) { return null; } /* And insert edge */ index = indexForInsertingIntoAET(edge); insertToAETbeforeIndex(edge, index); } /* Insert the given edge into the AET. */ static sqInt insertToAETbeforeIndex(sqInt edge, sqInt index) { sqInt i; if (!(needAvailableSpace(1))) { return null; } i = (workBuffer[GWAETUsed]) - 1; while (!(i < index)) { aetBuffer[i + 1] = (aetBuffer[i]); i -= 1; } aetBuffer[index] = edge; workBuffer[GWAETUsed] = ((workBuffer[GWAETUsed]) + 1); } static sqInt isBezier(sqInt bezier) { return (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveBezier; } static sqInt isEdge(sqInt edge) { sqInt type; type = (objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask; if (type > GEPrimitiveEdgeMask) { return 0; } return (((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveEdgeMask) != 0; } static sqInt isFillColor(sqInt fill) { return (fill & 4278190080UL) != 0; } static sqInt isFillOkay(sqInt fill) { return (fill == 0) || (((fill & 4278190080UL) != 0) || (((fill >= 0) && (fill < objUsed)) && (((fill & 4278190080UL) != 0) || ((((objBuffer[fill + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveFillMask) != 0)))); } static sqInt isFill(sqInt fill) { return ((fill & 4278190080UL) != 0) || ((((objBuffer[fill + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveFillMask) != 0); } static sqInt isLine(sqInt line) { return (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveLine; } static sqInt isObject(sqInt obj) { return (obj >= 0) && (obj < objUsed); } static sqInt isRealFill(sqInt fill) { return (((objBuffer[fill + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveFillMask) != 0; } static sqInt isStackEntry(sqInt entry) { return (entry >= (workBuffer[GWBufferTop])) && (entry < (workBuffer[GWSize])); } static sqInt isStackIndex(sqInt index) { return (index >= 0) && (index < ((workBuffer[GWSize]) - (workBuffer[GWBufferTop]))); } static sqInt isWideBezier(sqInt bezier) { return ((((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveBezier) && ((((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0); } static sqInt isWideLine(sqInt line) { return ((((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWideMask) == GEPrimitiveLine) && ((((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0); } static sqInt isWide(sqInt object) { return (((objBuffer[object + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0; } static sqInt lastExportedEdgeGet(void) { return workBuffer[GWLastExportedEdge]; } static sqInt lastExportedEdgePut(sqInt value) { return workBuffer[GWLastExportedEdge] = value; } static sqInt lastExportedFillGet(void) { return workBuffer[GWLastExportedFill]; } static sqInt lastExportedFillPut(sqInt value) { return workBuffer[GWLastExportedFill] = value; } static sqInt lastExportedLeftXGet(void) { return workBuffer[GWLastExportedLeftX]; } static sqInt lastExportedLeftXPut(sqInt value) { return workBuffer[GWLastExportedLeftX] = value; } static sqInt lastExportedRightXGet(void) { return workBuffer[GWLastExportedRightX]; } static sqInt lastExportedRightXPut(sqInt value) { return workBuffer[GWLastExportedRightX] = value; } static sqInt lineEndXOf(sqInt line) { return objBuffer[line + GLEndX]; } static sqInt lineEndXOfput(sqInt line, sqInt value) { return objBuffer[line + GLEndX] = value; } static sqInt lineEndYOf(sqInt line) { return objBuffer[line + GLEndY]; } static sqInt lineEndYOfput(sqInt line, sqInt value) { return objBuffer[line + GLEndY] = value; } static sqInt lineErrorAdjDownOf(sqInt line) { return objBuffer[line + GLErrorAdjDown]; } static sqInt lineErrorAdjDownOfput(sqInt line, sqInt value) { return objBuffer[line + GLErrorAdjDown] = value; } static sqInt lineErrorAdjUpOf(sqInt line) { return objBuffer[line + GLErrorAdjUp]; } static sqInt lineErrorAdjUpOfput(sqInt line, sqInt value) { return objBuffer[line + GLErrorAdjUp] = value; } static sqInt lineErrorOf(sqInt line) { return objBuffer[line + GLError]; } static sqInt lineErrorOfput(sqInt line, sqInt value) { return objBuffer[line + GLError] = value; } static sqInt lineXDirectionOf(sqInt line) { return objBuffer[line + GLXDirection]; } static sqInt lineXDirectionOfput(sqInt line, sqInt value) { return objBuffer[line + GLXDirection] = value; } static sqInt lineXIncrementOf(sqInt line) { return objBuffer[line + GLXIncrement]; } static sqInt lineXIncrementOfput(sqInt line, sqInt value) { return objBuffer[line + GLXIncrement] = value; } static sqInt lineYDirectionOf(sqInt line) { return objBuffer[line + GLYDirection]; } static sqInt lineYDirectionOfput(sqInt line, sqInt value) { return objBuffer[line + GLYDirection] = value; } /* Load and subdivide the bezier curve from point1/point2/point3. If wideFlag is set then make sure the curve is monoton in X. */ static sqInt loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqInt wideFlag) { sqInt bz1; sqInt bz2; sqInt index; sqInt index1; sqInt index2; /* begin allocateBezierStackEntry */ /* begin wbStackPush: */ if (!(needAvailableSpace(6))) { goto l1; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - 6); l1: /* end wbStackPush: */; bz1 = (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); if (engineStopped) { return 0; } workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 0)] = (point1[0]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 1)] = (point1[1]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 2)] = (point2[0]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 3)] = (point2[1]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 4)] = (point3[0]); workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 5)] = (point3[1]); index2 = bz2 = subdivideToBeMonotoninX(bz1, wideFlag); for (index = bz1; index <= bz2; index += 6) { index1 = subdivideBezierFrom(index); if (index1 > index2) { index2 = index1; } if (engineStopped) { return 0; } } return index2 / 6; } static sqInt loadArrayPolygonnPointsfilllineWidthlineFill(sqInt points, sqInt nPoints, sqInt fillIndex, sqInt lineWidth, sqInt lineFill) { sqInt i; int *point; int *point1; int *point2; int *point3; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; loadPointfrom(point1Get(), interpreterProxy->fetchPointerofObject(0, points)); if (interpreterProxy->failed()) { return null; } x0 = (point1Get())[0]; y0 = (point1Get())[1]; for (i = 1; i <= (nPoints - 1); i += 1) { loadPointfrom(point1Get(), interpreterProxy->fetchPointerofObject(i, points)); if (interpreterProxy->failed()) { return null; } x1 = (point1Get())[0]; y1 = (point1Get())[1]; (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x2; (((int *) point1))[1] = y2; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x3; (((int *) point2))[1] = y3; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x4; (((int *) point3))[1] = y4; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, fillIndex, 0); if (engineStopped) { return null; } x0 = x1; y0 = y1; } } static sqInt loadArrayShapenSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill) { sqInt i; int *point; int *point1; int *point2; int *point3; sqInt pointOop; sqInt segs; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt x5; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; sqInt y5; for (i = 0; i <= (nSegments - 1); i += 1) { pointOop = interpreterProxy->fetchPointerofObject(i * 3, points); loadPointfrom(point1Get(), pointOop); pointOop = interpreterProxy->fetchPointerofObject((i * 3) + 1, points); loadPointfrom(point2Get(), pointOop); pointOop = interpreterProxy->fetchPointerofObject((i * 3) + 2, points); loadPointfrom(point3Get(), pointOop); if (interpreterProxy->failed()) { return null; } /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x3; (((int *) point1))[1] = y3; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x4; (((int *) point2))[1] = y4; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x5 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y5 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x5; (((int *) point3))[1] = y5; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } x0 = (point1Get())[0]; y0 = (point1Get())[1]; x1 = (point2Get())[0]; y1 = (point2Get())[1]; x2 = (point3Get())[0]; /* Check if we can use a line */ y2 = (point3Get())[1]; if (((x0 == y0) && (x1 == y1)) || ((x1 == x2) && (y1 == y2))) { loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point3Get(), lineFill, fillIndex, 0); } else { segs = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), (lineWidth != 0) && (lineFill != 0)); if (engineStopped) { return null; } loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); } if (engineStopped) { return null; } } } /* Load a transformation from the given array. */ static sqInt loadArrayTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) { sqInt i; sqInt value; for (i = 0; i <= (n - 1); i += 1) { value = interpreterProxy->fetchPointerofObject(i, transformOop); if (!(((value & 1)) || (interpreterProxy->isFloatObject(value)))) { return interpreterProxy->primitiveFail(); } if ((value & 1)) { destPtr[i] = (((float) (((double) ((value >> 1)) )))); } else { destPtr[i] = (((float) (interpreterProxy->floatValueOf(value)))); } } } /* Initialize the bezier segment stored on the stack */ static sqInt loadBeziersegmentleftFillrightFilloffset(sqInt bezier, sqInt index, sqInt leftFillIndex, sqInt rightFillIndex, sqInt yOffset) { if ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) >= (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)])) { objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]); objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); } else { objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]); objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); } objBuffer[bezier + GEZValue] = (workBuffer[GWCurrentZ]); objBuffer[bezier + GEFillIndexLeft] = leftFillIndex; objBuffer[bezier + GEFillIndexRight] = rightFillIndex; } static sqInt loadBitBltFrom(sqInt bbObj) { if (loadBBFn == 0) { if (!(initialiseModule())) { return 0; } } return ((sqInt (*)(sqInt))loadBBFn)(bbObj); } /* Load the bitmap fill. */ static sqInt loadBitmapFillcolormaptilefromalongnormalxIndex(sqInt formOop, sqInt cmOop, sqInt tileFlag, int *point1, int *point2, int *point3, sqInt xIndex) { sqInt bmBits; sqInt bmBitsSize; sqInt bmDepth; sqInt bmFill; sqInt bmHeight; sqInt bmRaster; sqInt bmWidth; int *cm; int *cmBits; sqInt cmSize; sqInt fill; sqInt fillSize; sqInt i; sqInt ppw; if (cmOop == (interpreterProxy->nilObject())) { cmSize = 0; cmBits = null; } else { if (!((interpreterProxy->fetchClassOf(cmOop)) == (interpreterProxy->classBitmap()))) { return interpreterProxy->primitiveFail(); } cmSize = interpreterProxy->slotSizeOf(cmOop); cmBits = interpreterProxy->firstIndexableField(cmOop); } if ((formOop & 1)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isPointers(formOop))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(formOop)) < 5) { return interpreterProxy->primitiveFail(); } bmBits = interpreterProxy->fetchPointerofObject(0, formOop); if (!((interpreterProxy->fetchClassOf(bmBits)) == (interpreterProxy->classBitmap()))) { return interpreterProxy->primitiveFail(); } bmBitsSize = interpreterProxy->slotSizeOf(bmBits); bmWidth = interpreterProxy->fetchIntegerofObject(1, formOop); bmHeight = interpreterProxy->fetchIntegerofObject(2, formOop); bmDepth = interpreterProxy->fetchIntegerofObject(3, formOop); if (interpreterProxy->failed()) { return null; } if (!((bmWidth >= 0) && (bmHeight >= 0))) { return interpreterProxy->primitiveFail(); } if (!((((((bmDepth == 32) || (bmDepth == 8)) || (bmDepth == 16)) || (bmDepth == 1)) || (bmDepth == 2)) || (bmDepth == 4))) { return interpreterProxy->primitiveFail(); } if (!((cmSize == 0) || (cmSize == (1 << bmDepth)))) { return interpreterProxy->primitiveFail(); } ppw = 32 / bmDepth; bmRaster = (bmWidth + (ppw - 1)) / ppw; if (!(bmBitsSize == (bmRaster * bmHeight))) { return interpreterProxy->primitiveFail(); } /* begin allocateBitmapFill:colormap: */ fillSize = GBMBaseSize + cmSize; if (!(allocateObjEntry(fillSize))) { bmFill = 0; goto l1; } fill = objUsed; objUsed = fill + fillSize; objBuffer[fill + GEObjectType] = GEPrimitiveClippedBitmapFill; objBuffer[fill + GEObjectIndex] = 0; objBuffer[fill + GEObjectLength] = fillSize; /* begin colormapOf: */ cm = (objBuffer + fill) + GBColormapOffset; if ((workBuffer[GWHasColorTransform]) != 0) { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (transformColor(cmBits[i])); } } else { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (cmBits[i]); } } objBuffer[fill + GBColormapSize] = cmSize; bmFill = fill; l1: /* end allocateBitmapFill:colormap: */; if (engineStopped) { return null; } objBuffer[bmFill + GBBitmapWidth] = bmWidth; objBuffer[bmFill + GBBitmapHeight] = bmHeight; objBuffer[bmFill + GBBitmapDepth] = bmDepth; objBuffer[bmFill + GBBitmapRaster] = bmRaster; objBuffer[bmFill + GBBitmapSize] = bmBitsSize; objBuffer[bmFill + GBTileFlag] = tileFlag; objBuffer[bmFill + GEObjectIndex] = xIndex; loadFillOrientationfromalongnormalwidthheight(bmFill, point1, point2, point3, bmWidth, bmHeight); return bmFill; } /* Note: Assumes that the contents of formArray has been checked before */ static int * loadBitsFrom(sqInt bmFill) { sqInt bitsLen; sqInt bitsOop; sqInt formOop; sqInt xIndex; xIndex = objBuffer[bmFill + GEObjectIndex]; if (xIndex > (interpreterProxy->slotSizeOf(formArray))) { return null; } formOop = interpreterProxy->fetchPointerofObject(xIndex, formArray); bitsOop = interpreterProxy->fetchPointerofObject(0, formOop); bitsLen = interpreterProxy->slotSizeOf(bitsOop); if (!(bitsLen == (objBuffer[bmFill + GBBitmapSize]))) { return null; } return interpreterProxy->firstIndexableField(bitsOop); } /* Load a 2x3 transformation matrix from the given oop. Return true if the matrix is not nil, false otherwise */ static sqInt loadColorTransformFrom(sqInt transformOop) { sqInt okay; float *transform; /* begin colorTransform */ transform = ((float *) (workBuffer + GWColorTransform)); workBuffer[GWHasColorTransform] = 0; okay = loadTransformFromintolength(transformOop, transform, 8); if (!(okay)) { return 0; } workBuffer[GWHasColorTransform] = 1; transform[1] = ((transform[1]) * (((float) 256.0))); transform[3] = ((transform[3]) * (((float) 256.0))); transform[5] = ((transform[5]) * (((float) 256.0))); transform[7] = ((transform[7]) * (((float) 256.0))); return okay; } /* Load the compressed segment identified by segment index */ static sqInt loadCompressedSegmentfromshortleftFillrightFilllineWidthlineColor(sqInt segmentIndex, sqInt points, sqInt pointsShort, sqInt leftFill, sqInt rightFill, sqInt lineWidth, sqInt lineFill) { sqInt index; int *point; int *point1; int *point2; int *point3; int *point4; int *point5; int *point6; int *point7; sqInt segs; float *transform; float *transform1; float *transform2; float *transform3; float *transform4; float *transform5; float *transform6; float *transform7; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt x5; sqInt x6; sqInt x7; sqInt x8; sqInt x9; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; sqInt y5; sqInt y6; sqInt y7; sqInt y8; sqInt y9; if ((leftFill == rightFill) && ((lineWidth == 0) || (lineFill == 0))) { return null; } /* 3 points with x/y each */ index = segmentIndex * 6; if (pointsShort) { /* begin loadPointShortAt:from: */ x0 = ((short) ((((short *) points))[index + 0])); /* begin loadPointShortAt:from: */ y0 = ((short) ((((short *) points))[index + 1])); /* begin loadPointShortAt:from: */ x1 = ((short) ((((short *) points))[index + 2])); /* begin loadPointShortAt:from: */ y1 = ((short) ((((short *) points))[index + 3])); /* begin loadPointShortAt:from: */ x2 = ((short) ((((short *) points))[index + 4])); /* begin loadPointShortAt:from: */ y2 = ((short) ((((short *) points))[index + 5])); } else { x0 = (((int *) points))[index + 0]; y0 = (((int *) points))[index + 1]; x1 = (((int *) points))[index + 2]; y1 = (((int *) points))[index + 3]; x2 = (((int *) points))[index + 4]; y2 = (((int *) points))[index + 5]; } if (((x0 == x1) && (y0 == y1)) || ((x1 == x2) && (y1 == y2))) { if ((x0 == x2) && (y0 == y2)) { return null; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x2; (point2Get())[1] = y2; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x3; (((int *) point1))[1] = y3; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x4; (((int *) point2))[1] = y4; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x5 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y5 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x5; (((int *) point3))[1] = y5; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } return loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, leftFill, rightFill); } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; (point3Get())[0] = x2; (point3Get())[1] = y2; /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point4 = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform4 = ((float *) (workBuffer + GWEdgeTransform)); x6 = ((sqInt)(((((transform4[0]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[1]) * (((double) ((((int *) point4))[1]) )))) + (transform4[2])) * (((double) (workBuffer[GWAALevel]) )))); y6 = ((sqInt)(((((transform4[3]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[4]) * (((double) ((((int *) point4))[1]) )))) + (transform4[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point4))[0] = x6; (((int *) point4))[1] = y6; } else { point4[0] = (((point4[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point4[1] = (((point4[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point5 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform5 = ((float *) (workBuffer + GWEdgeTransform)); x7 = ((sqInt)(((((transform5[0]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[1]) * (((double) ((((int *) point5))[1]) )))) + (transform5[2])) * (((double) (workBuffer[GWAALevel]) )))); y7 = ((sqInt)(((((transform5[3]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[4]) * (((double) ((((int *) point5))[1]) )))) + (transform5[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point5))[0] = x7; (((int *) point5))[1] = y7; } else { point5[0] = (((point5[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point5[1] = (((point5[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point6 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform6 = ((float *) (workBuffer + GWEdgeTransform)); x8 = ((sqInt)(((((transform6[0]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[1]) * (((double) ((((int *) point6))[1]) )))) + (transform6[2])) * (((double) (workBuffer[GWAALevel]) )))); y8 = ((sqInt)(((((transform6[3]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[4]) * (((double) ((((int *) point6))[1]) )))) + (transform6[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point6))[0] = x8; (((int *) point6))[1] = y8; } else { point6[0] = (((point6[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point6[1] = (((point6[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point7 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform7 = ((float *) (workBuffer + GWEdgeTransform)); x9 = ((sqInt)(((((transform7[0]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[1]) * (((double) ((((int *) point7))[1]) )))) + (transform7[2])) * (((double) (workBuffer[GWAALevel]) )))); y9 = ((sqInt)(((((transform7[3]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[4]) * (((double) ((((int *) point7))[1]) )))) + (transform7[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point7))[0] = x9; (((int *) point7))[1] = y9; } else { point7[0] = (((point7[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point7[1] = (((point7[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } segs = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), (lineWidth != 0) && (lineFill != 0)); if (engineStopped) { return null; } loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, leftFill, rightFill, segs); } /* Load a compressed shape into the engine. WARNING: THIS METHOD NEEDS THE FULL FRAME SIZE!!!! */ static sqInt loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList, sqInt pointsShort) { sqInt i; sqInt index; sqInt leftLength; sqInt leftRun; sqInt leftValue; sqInt lineFillLength; sqInt lineFillRun; sqInt lineFillValue; int *point; int *point1; int *point2; int *point3; int *point4; int *point5; int *point6; int *point7; sqInt rightLength; sqInt rightRun; sqInt rightValue; sqInt segs; float *transform; float *transform1; float *transform2; float *transform3; float *transform4; float *transform5; float *transform6; float *transform7; sqInt widthLength; sqInt widthRun; sqInt widthValue; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt x5; sqInt x6; sqInt x7; sqInt x8; sqInt x9; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; sqInt y5; sqInt y6; sqInt y7; sqInt y8; sqInt y9; if (nSegments == 0) { return 0; } leftRun = rightRun = widthRun = lineFillRun = -1; leftLength = rightLength = widthLength = lineFillLength = 1; leftValue = rightValue = widthValue = lineFillValue = 0; for (i = 1; i <= nSegments; i += 1) { if (((leftLength -= 1)) <= 0) { /* Decrement current run length and load new stuff */ leftRun += 1; leftLength = ((usqInt) ((((int *) leftFills))[leftRun]) >> 16); leftValue = ((((int *) leftFills))[leftRun]) & 65535; if (!(leftValue == 0)) { leftValue = fillIndexList[leftValue - 1]; leftValue = transformColor(leftValue); if (engineStopped) { return null; } } } if (((rightLength -= 1)) <= 0) { rightRun += 1; rightLength = ((usqInt) ((((int *) rightFills))[rightRun]) >> 16); rightValue = ((((int *) rightFills))[rightRun]) & 65535; if (!(rightValue == 0)) { rightValue = fillIndexList[rightValue - 1]; rightValue = transformColor(rightValue); } } if (((widthLength -= 1)) <= 0) { widthRun += 1; widthLength = ((usqInt) ((((int *) lineWidths))[widthRun]) >> 16); widthValue = ((((int *) lineWidths))[widthRun]) & 65535; if (!(widthValue == 0)) { widthValue = transformWidth(widthValue); } } if (((lineFillLength -= 1)) <= 0) { lineFillRun += 1; lineFillLength = ((usqInt) ((((int *) lineFills))[lineFillRun]) >> 16); lineFillValue = ((((int *) lineFills))[lineFillRun]) & 65535; if (!(lineFillValue == 0)) { lineFillValue = fillIndexList[lineFillValue - 1]; } } /* begin loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */ if ((leftValue == rightValue) && ((widthValue == 0) || (lineFillValue == 0))) { goto l1; } /* 3 points with x/y each */ index = (i - 1) * 6; if (pointsShort) { /* begin loadPointShortAt:from: */ x0 = ((short) ((((short *) points))[index + 0])); /* begin loadPointShortAt:from: */ y0 = ((short) ((((short *) points))[index + 1])); /* begin loadPointShortAt:from: */ x1 = ((short) ((((short *) points))[index + 2])); /* begin loadPointShortAt:from: */ y1 = ((short) ((((short *) points))[index + 3])); /* begin loadPointShortAt:from: */ x2 = ((short) ((((short *) points))[index + 4])); /* begin loadPointShortAt:from: */ y2 = ((short) ((((short *) points))[index + 5])); } else { x0 = (((int *) points))[index + 0]; y0 = (((int *) points))[index + 1]; x1 = (((int *) points))[index + 2]; y1 = (((int *) points))[index + 3]; x2 = (((int *) points))[index + 4]; y2 = (((int *) points))[index + 5]; } if (((x0 == x1) && (y0 == y1)) || ((x1 == x2) && (y1 == y2))) { if ((x0 == x2) && (y0 == y2)) { goto l1; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x2; (point2Get())[1] = y2; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x3; (((int *) point1))[1] = y3; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x4; (((int *) point2))[1] = y4; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x5 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y5 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x5; (((int *) point3))[1] = y5; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(widthValue, point1Get(), point2Get(), lineFillValue, leftValue, rightValue); goto l1; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; (point3Get())[0] = x2; (point3Get())[1] = y2; /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point4 = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform4 = ((float *) (workBuffer + GWEdgeTransform)); x6 = ((sqInt)(((((transform4[0]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[1]) * (((double) ((((int *) point4))[1]) )))) + (transform4[2])) * (((double) (workBuffer[GWAALevel]) )))); y6 = ((sqInt)(((((transform4[3]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[4]) * (((double) ((((int *) point4))[1]) )))) + (transform4[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point4))[0] = x6; (((int *) point4))[1] = y6; } else { point4[0] = (((point4[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point4[1] = (((point4[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point5 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform5 = ((float *) (workBuffer + GWEdgeTransform)); x7 = ((sqInt)(((((transform5[0]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[1]) * (((double) ((((int *) point5))[1]) )))) + (transform5[2])) * (((double) (workBuffer[GWAALevel]) )))); y7 = ((sqInt)(((((transform5[3]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[4]) * (((double) ((((int *) point5))[1]) )))) + (transform5[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point5))[0] = x7; (((int *) point5))[1] = y7; } else { point5[0] = (((point5[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point5[1] = (((point5[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point6 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform6 = ((float *) (workBuffer + GWEdgeTransform)); x8 = ((sqInt)(((((transform6[0]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[1]) * (((double) ((((int *) point6))[1]) )))) + (transform6[2])) * (((double) (workBuffer[GWAALevel]) )))); y8 = ((sqInt)(((((transform6[3]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[4]) * (((double) ((((int *) point6))[1]) )))) + (transform6[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point6))[0] = x8; (((int *) point6))[1] = y8; } else { point6[0] = (((point6[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point6[1] = (((point6[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point7 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform7 = ((float *) (workBuffer + GWEdgeTransform)); x9 = ((sqInt)(((((transform7[0]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[1]) * (((double) ((((int *) point7))[1]) )))) + (transform7[2])) * (((double) (workBuffer[GWAALevel]) )))); y9 = ((sqInt)(((((transform7[3]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[4]) * (((double) ((((int *) point7))[1]) )))) + (transform7[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point7))[0] = x9; (((int *) point7))[1] = y9; } else { point7[0] = (((point7[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point7[1] = (((point7[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } segs = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), (widthValue != 0) && (lineFillValue != 0)); if (engineStopped) { goto l1; } loadWideBezierlineFillleftFillrightFilln(widthValue, lineFillValue, leftValue, rightValue, segs); l1: /* end loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */; if (engineStopped) { return null; } } } static sqInt loadEdgeStateFrom(sqInt edgeOop) { sqInt edge; sqInt value; sqInt value1; sqInt value2; sqInt value3; edge = workBuffer[GWLastExportedEdge]; if ((interpreterProxy->slotSizeOf(edgeOop)) < ETBalloonEdgeDataSize) { return null; } /* begin edgeXValueOf:put: */ value = interpreterProxy->fetchIntegerofObject(ETXValueIndex, edgeOop); objBuffer[edge + GEXValue] = value; /* begin edgeYValueOf:put: */ value1 = interpreterProxy->fetchIntegerofObject(ETYValueIndex, edgeOop); objBuffer[edge + GEYValue] = value1; /* begin edgeZValueOf:put: */ value2 = interpreterProxy->fetchIntegerofObject(ETZValueIndex, edgeOop); objBuffer[edge + GEZValue] = value2; /* begin edgeNumLinesOf:put: */ value3 = interpreterProxy->fetchIntegerofObject(ETLinesIndex, edgeOop); objBuffer[edge + GENumLines] = value3; return edge; } /* Load a 2x3 transformation matrix from the given oop. Return true if the matrix is not nil, false otherwise */ static sqInt loadEdgeTransformFrom(sqInt transformOop) { sqInt okay; float *transform; workBuffer[GWHasEdgeTransform] = 0; /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); okay = loadTransformFromintolength(transformOop, transform, 6); if (interpreterProxy->failed()) { return null; } if (!(okay)) { return 0; } workBuffer[GWHasEdgeTransform] = 1; transform[2] = (((float) ((transform[2]) + (((double) (workBuffer[GWDestOffsetX]) ))))); transform[5] = (((float) ((transform[5]) + (((double) (workBuffer[GWDestOffsetY]) ))))); return 1; } /* Transform the points */ static sqInt loadFillOrientationfromalongnormalwidthheight(sqInt fill, int *point1, int *point2, int *point3, sqInt fillWidth, sqInt fillHeight) { sqInt dirX; sqInt dirY; sqInt dsLength2; sqInt dsX; sqInt dsY; sqInt dtLength2; sqInt dtX; sqInt dtY; sqInt nrmX; sqInt nrmY; float *transform; float *transform1; float *transform2; sqInt x; sqInt x1; sqInt x2; sqInt y; sqInt y1; sqInt y2; point2[0] = ((point2[0]) + (point1[0])); point2[1] = ((point2[1]) + (point1[1])); point3[0] = ((point3[0]) + (point1[0])); point3[1] = ((point3[1]) + (point1[1])); /* begin transformPoint: */ if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform[1]) * (((double) ((((int *) point1))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform[4]) * (((double) ((((int *) point1))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x; (((int *) point1))[1] = y; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } /* begin transformPoint: */ if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point2))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point2))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x1; (((int *) point2))[1] = y1; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } /* begin transformPoint: */ if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point3))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point3))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x2; (((int *) point3))[1] = y2; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } dirX = (point2[0]) - (point1[0]); dirY = (point2[1]) - (point1[1]); nrmX = (point3[0]) - (point1[0]); /* Compute the scale from direction/normal into ramp size */ nrmY = (point3[1]) - (point1[1]); dsLength2 = (dirX * dirX) + (dirY * dirY); if (dsLength2 > 0) { dsX = ((sqInt)((((((double) dirX )) * (((double) fillWidth ))) * 65536.0) / (((double) dsLength2 )))); dsY = ((sqInt)((((((double) dirY )) * (((double) fillWidth ))) * 65536.0) / (((double) dsLength2 )))); } else { dsX = 0; dsY = 0; } dtLength2 = (nrmX * nrmX) + (nrmY * nrmY); if (dtLength2 > 0) { dtX = ((sqInt)((((((double) nrmX )) * (((double) fillHeight ))) * 65536.0) / (((double) dtLength2 )))); dtY = ((sqInt)((((((double) nrmY )) * (((double) fillHeight ))) * 65536.0) / (((double) dtLength2 )))); } else { dtX = 0; dtY = 0; } objBuffer[fill + GFOriginX] = (point1[0]); objBuffer[fill + GFOriginY] = (point1[1]); objBuffer[fill + GFDirectionX] = dsX; objBuffer[fill + GFDirectionY] = dsY; objBuffer[fill + GFNormalX] = dtX; objBuffer[fill + GFNormalY] = dtY; } /* Check all the forms from arrayOop. */ static sqInt loadFormsFrom(sqInt arrayOop) { sqInt bmBits; sqInt bmBitsSize; sqInt bmDepth; sqInt bmHeight; sqInt bmRaster; sqInt bmWidth; sqInt formOop; sqInt i; sqInt ppw; if (!(interpreterProxy->isArray(arrayOop))) { return 0; } formArray = arrayOop; for (i = 0; i <= ((interpreterProxy->slotSizeOf(formArray)) - 1); i += 1) { formOop = interpreterProxy->fetchPointerofObject(i, formArray); if ((formOop & 1)) { return 0; } if (!(interpreterProxy->isPointers(formOop))) { return 0; } if ((interpreterProxy->slotSizeOf(formOop)) < 5) { return 0; } bmBits = interpreterProxy->fetchPointerofObject(0, formOop); if (!((interpreterProxy->fetchClassOf(bmBits)) == (interpreterProxy->classBitmap()))) { return 0; } bmBitsSize = interpreterProxy->slotSizeOf(bmBits); bmWidth = interpreterProxy->fetchIntegerofObject(1, formOop); bmHeight = interpreterProxy->fetchIntegerofObject(2, formOop); bmDepth = interpreterProxy->fetchIntegerofObject(3, formOop); if (interpreterProxy->failed()) { return 0; } if (!((bmWidth >= 0) && (bmHeight >= 0))) { return 0; } ppw = 32 / bmDepth; bmRaster = (bmWidth + (ppw - 1)) / ppw; if (!(bmBitsSize == (bmRaster * bmHeight))) { return 0; } } return 1; } /* Load the gradient fill as defined by the color ramp. */ static sqInt loadGradientFillfromalongnormalisRadial(sqInt rampOop, int *point1, int *point2, int *point3, sqInt isRadial) { sqInt fill; sqInt fill1; sqInt fillSize; sqInt i; int *ramp; int *rampPtr; sqInt rampWidth; if (!((interpreterProxy->fetchClassOf(rampOop)) == (interpreterProxy->classBitmap()))) { return interpreterProxy->primitiveFail(); } rampWidth = interpreterProxy->slotSizeOf(rampOop); /* begin allocateGradientFill:rampWidth:isRadial: */ ramp = interpreterProxy->firstIndexableField(rampOop); fillSize = GGBaseSize + rampWidth; if (!(allocateObjEntry(fillSize))) { fill = 0; goto l1; } fill1 = objUsed; objUsed = fill1 + fillSize; if (isRadial) { objBuffer[fill1 + GEObjectType] = GEPrimitiveRadialGradientFill; } else { objBuffer[fill1 + GEObjectType] = GEPrimitiveLinearGradientFill; } objBuffer[fill1 + GEObjectIndex] = 0; objBuffer[fill1 + GEObjectLength] = fillSize; /* begin gradientRampOf: */ rampPtr = (objBuffer + fill1) + GFRampOffset; if ((workBuffer[GWHasColorTransform]) != 0) { for (i = 0; i <= (rampWidth - 1); i += 1) { rampPtr[i] = (transformColor(ramp[i])); } } else { for (i = 0; i <= (rampWidth - 1); i += 1) { rampPtr[i] = (ramp[i]); } } objBuffer[fill1 + GFRampLength] = rampWidth; fill = fill1; l1: /* end allocateGradientFill:rampWidth:isRadial: */; if (engineStopped) { return null; } loadFillOrientationfromalongnormalwidthheight(fill, point1, point2, point3, rampWidth, rampWidth); return fill; } /* Load the line defined by point1 and point2. */ static sqInt loadLinefromtooffsetleftFillrightFill(sqInt line, int *point1, int *point2, sqInt yOffset, sqInt leftFill, sqInt rightFill) { int *p1; int *p2; sqInt yDir; if ((point1[1]) <= (point2[1])) { p1 = point1; p2 = point2; yDir = 1; } else { p1 = point2; p2 = point1; yDir = -1; } objBuffer[line + GEXValue] = (p1[0]); objBuffer[line + GEYValue] = ((p1[1]) - yOffset); objBuffer[line + GEZValue] = (workBuffer[GWCurrentZ]); objBuffer[line + GEFillIndexLeft] = leftFill; objBuffer[line + GEFillIndexRight] = rightFill; objBuffer[line + GLEndX] = (p2[0]); objBuffer[line + GLEndY] = ((p2[1]) - yOffset); objBuffer[line + GLYDirection] = yDir; } static sqInt loadOvalSegmentwhcxcy(sqInt seg, sqInt w, sqInt h, sqInt cx, sqInt cy) { sqInt x0; sqInt x1; sqInt x2; sqInt y0; sqInt y1; sqInt y2; /* Load start point of segment */ x0 = ((sqInt)((((circleCosTable())[(seg * 2) + 0]) * (((double) w ))) + cx)); y0 = ((sqInt)((((circleSinTable())[(seg * 2) + 0]) * (((double) h ))) + cy)); (point1Get())[0] = x0; (point1Get())[1] = y0; x2 = ((sqInt)((((circleCosTable())[(seg * 2) + 2]) * (((double) w ))) + cx)); y2 = ((sqInt)((((circleSinTable())[(seg * 2) + 2]) * (((double) h ))) + cy)); (point3Get())[0] = x2; (point3Get())[1] = y2; x1 = ((sqInt)((((circleCosTable())[(seg * 2) + 1]) * (((double) w ))) + cx)); /* NOTE: The intermediate point is the point ON the curve and not yet the control point (which is OFF the curve) */ y1 = ((sqInt)((((circleSinTable())[(seg * 2) + 1]) * (((double) h ))) + cy)); x1 = (x1 * 2) - (((sqInt) (x0 + x2) >> 1)); y1 = (y1 * 2) - (((sqInt) (y0 + y2) >> 1)); (point2Get())[0] = x1; (point2Get())[1] = y1; } /* Load a rectangular oval currently defined by point1/point2 */ static sqInt loadOvallineFillleftFillrightFill(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill) { sqInt cx; sqInt cy; sqInt h; sqInt i; sqInt nSegments; int *point; int *point1; int *point2; int *point3; float *transform; float *transform1; float *transform2; float *transform3; sqInt w; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; w = ((sqInt) (((point2Get())[0]) - ((point1Get())[0])) >> 1); h = ((sqInt) (((point2Get())[1]) - ((point1Get())[1])) >> 1); cx = ((sqInt) (((point2Get())[0]) + ((point1Get())[0])) >> 1); cy = ((sqInt) (((point2Get())[1]) + ((point1Get())[1])) >> 1); for (i = 0; i <= 15; i += 1) { loadOvalSegmentwhcxcy(i, w, h, cx, cy); /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } nSegments = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), (lineWidth != 0) && (lineFill != 0)); if (engineStopped) { return null; } loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, leftFill, rightFill, nSegments); if (engineStopped) { return null; } } } /* Load the int value from the given index in intArray */ static sqInt loadPointIntAtfrom(sqInt index, sqInt intArray) { return (((int *) intArray))[index]; } /* Load the short value from the given index in shortArray */ static short loadPointShortAtfrom(sqInt index, sqInt shortArray) { return (((short *) shortArray))[index]; } /* Load the contents of pointOop into pointArray */ static sqInt loadPointfrom(int *pointArray, sqInt pointOop) { sqInt value; if (!((interpreterProxy->fetchClassOf(pointOop)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } value = interpreterProxy->fetchPointerofObject(0, pointOop); if (!(((value & 1)) || (interpreterProxy->isFloatObject(value)))) { return interpreterProxy->primitiveFail(); } if ((value & 1)) { pointArray[0] = ((value >> 1)); } else { pointArray[0] = (((sqInt)(interpreterProxy->floatValueOf(value)))); } value = interpreterProxy->fetchPointerofObject(1, pointOop); if (!(((value & 1)) || (interpreterProxy->isFloatObject(value)))) { return interpreterProxy->primitiveFail(); } if ((value & 1)) { pointArray[1] = ((value >> 1)); } else { pointArray[1] = (((sqInt)(interpreterProxy->floatValueOf(value)))); } } static sqInt loadPolygonnPointsfilllineWidthlineFillpointsShort(int *points, sqInt nPoints, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt isShort) { sqInt i; int *point; int *point1; int *point2; int *point3; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; if (isShort) { /* begin loadPointShortAt:from: */ x0 = ((short) ((((short *) points))[0])); /* begin loadPointShortAt:from: */ y0 = ((short) ((((short *) points))[1])); } else { x0 = (((int *) points))[0]; y0 = (((int *) points))[1]; } for (i = 1; i <= (nPoints - 1); i += 1) { if (isShort) { /* begin loadPointShortAt:from: */ x1 = ((short) ((((short *) points))[i * 2])); /* begin loadPointShortAt:from: */ y1 = ((short) ((((short *) points))[(i * 2) + 1])); } else { x1 = (((int *) points))[i * 2]; y1 = (((int *) points))[(i * 2) + 1]; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x2; (((int *) point1))[1] = y2; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x3; (((int *) point2))[1] = y3; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x4; (((int *) point3))[1] = y4; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, fillIndex, 0); if (engineStopped) { return null; } x0 = x1; y0 = y1; } } /* Load a rectangle currently defined by point1-point4 */ static sqInt loadRectanglelineFillleftFillrightFill(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill) { loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, leftFill, rightFill); loadWideLinefromtolineFillleftFillrightFill(lineWidth, point2Get(), point3Get(), lineFill, leftFill, rightFill); loadWideLinefromtolineFillleftFillrightFill(lineWidth, point3Get(), point4Get(), lineFill, leftFill, rightFill); loadWideLinefromtolineFillleftFillrightFill(lineWidth, point4Get(), point1Get(), lineFill, leftFill, rightFill); } /* Load the entire state from the interpreter for the rendering primitives. Answer 0 on success or a non-zero failure code on failure. */ static sqInt loadRenderingState(void) { sqInt edgeOop; sqInt failCode; sqInt fillOop; sqInt state; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return PrimErrBadNumArgs; } if (((failCode = quickLoadEngineFrom(interpreterProxy->stackValue(2)))) != 0) { return failCode; } fillOop = interpreterProxy->stackObjectValue(0); edgeOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return PrimErrBadArgument; } if (!(((failCode = loadSpanBufferFrom(interpreterProxy->fetchPointerofObject(BESpanIndex, engine)))) == 0)) { return failCode; } if (!(loadBitBltFrom(interpreterProxy->fetchPointerofObject(BEBitBltIndex, engine)))) { return GEFBitBltLoadFailed; } if (!(loadFormsFrom(interpreterProxy->fetchPointerofObject(BEFormsIndex, engine)))) { return GEFFormLoadFailed; } if ((interpreterProxy->slotSizeOf(edgeOop)) < ETBalloonEdgeDataSize) { return GEFEdgeDataTooSmall; } if ((interpreterProxy->slotSizeOf(fillOop)) < FTBalloonFillDataSize) { return GEFFillDataTooSmall; } state = workBuffer[GWState]; if ((state == GEStateWaitingForEdge) || ((state == GEStateWaitingForFill) || (state == GEStateWaitingChange))) { return GEFWrongState; } return 0; } static sqInt loadShapenSegmentsfilllineWidthlineFillpointsShort(int *points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt pointsShort) { sqInt i; sqInt index; int *point; int *point1; int *point2; int *point3; int *point4; int *point5; int *point6; int *point7; sqInt segs; float *transform; float *transform1; float *transform2; float *transform3; float *transform4; float *transform5; float *transform6; float *transform7; sqInt x; sqInt x0; sqInt x1; sqInt x2; sqInt x3; sqInt x4; sqInt x5; sqInt x6; sqInt x7; sqInt x8; sqInt x9; sqInt y; sqInt y0; sqInt y1; sqInt y2; sqInt y3; sqInt y4; sqInt y5; sqInt y6; sqInt y7; sqInt y8; sqInt y9; for (i = 1; i <= nSegments; i += 1) { /* begin loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */ if ((fillIndex == 0) && ((lineWidth == 0) || (lineFill == 0))) { goto l1; } /* 3 points with x/y each */ index = (i - 1) * 6; if (pointsShort) { /* begin loadPointShortAt:from: */ x0 = ((short) ((((short *) points))[index + 0])); /* begin loadPointShortAt:from: */ y0 = ((short) ((((short *) points))[index + 1])); /* begin loadPointShortAt:from: */ x1 = ((short) ((((short *) points))[index + 2])); /* begin loadPointShortAt:from: */ y1 = ((short) ((((short *) points))[index + 3])); /* begin loadPointShortAt:from: */ x2 = ((short) ((((short *) points))[index + 4])); /* begin loadPointShortAt:from: */ y2 = ((short) ((((short *) points))[index + 5])); } else { x0 = (((int *) points))[index + 0]; y0 = (((int *) points))[index + 1]; x1 = (((int *) points))[index + 2]; y1 = (((int *) points))[index + 3]; x2 = (((int *) points))[index + 4]; y2 = (((int *) points))[index + 5]; } if (((x0 == x1) && (y0 == y1)) || ((x1 == x2) && (y1 == y2))) { if ((x0 == x2) && (y0 == y2)) { goto l1; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x2; (point2Get())[1] = y2; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x3; (((int *) point1))[1] = y3; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x4; (((int *) point2))[1] = y4; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x5 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y5 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x5; (((int *) point3))[1] = y5; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, fillIndex, 0); goto l1; } (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; (point3Get())[0] = x2; (point3Get())[1] = y2; /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point4 = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform4 = ((float *) (workBuffer + GWEdgeTransform)); x6 = ((sqInt)(((((transform4[0]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[1]) * (((double) ((((int *) point4))[1]) )))) + (transform4[2])) * (((double) (workBuffer[GWAALevel]) )))); y6 = ((sqInt)(((((transform4[3]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[4]) * (((double) ((((int *) point4))[1]) )))) + (transform4[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point4))[0] = x6; (((int *) point4))[1] = y6; } else { point4[0] = (((point4[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point4[1] = (((point4[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point5 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform5 = ((float *) (workBuffer + GWEdgeTransform)); x7 = ((sqInt)(((((transform5[0]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[1]) * (((double) ((((int *) point5))[1]) )))) + (transform5[2])) * (((double) (workBuffer[GWAALevel]) )))); y7 = ((sqInt)(((((transform5[3]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[4]) * (((double) ((((int *) point5))[1]) )))) + (transform5[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point5))[0] = x7; (((int *) point5))[1] = y7; } else { point5[0] = (((point5[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point5[1] = (((point5[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point6 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform6 = ((float *) (workBuffer + GWEdgeTransform)); x8 = ((sqInt)(((((transform6[0]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[1]) * (((double) ((((int *) point6))[1]) )))) + (transform6[2])) * (((double) (workBuffer[GWAALevel]) )))); y8 = ((sqInt)(((((transform6[3]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[4]) * (((double) ((((int *) point6))[1]) )))) + (transform6[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point6))[0] = x8; (((int *) point6))[1] = y8; } else { point6[0] = (((point6[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point6[1] = (((point6[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point7 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform7 = ((float *) (workBuffer + GWEdgeTransform)); x9 = ((sqInt)(((((transform7[0]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[1]) * (((double) ((((int *) point7))[1]) )))) + (transform7[2])) * (((double) (workBuffer[GWAALevel]) )))); y9 = ((sqInt)(((((transform7[3]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[4]) * (((double) ((((int *) point7))[1]) )))) + (transform7[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point7))[0] = x9; (((int *) point7))[1] = y9; } else { point7[0] = (((point7[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point7[1] = (((point7[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } segs = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), (lineWidth != 0) && (lineFill != 0)); if (engineStopped) { goto l1; } loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); l1: /* end loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */; if (engineStopped) { return null; } } } /* Load the span buffer from the given oop. Answer 0 on success or a non-zero failure code on failure. */ static sqInt loadSpanBufferFrom(sqInt spanOop) { sqInt value; if (!((interpreterProxy->fetchClassOf(spanOop)) == (interpreterProxy->classBitmap()))) { return GEFClassMismatch; } /* Leave last entry unused to avoid complications */ spanBuffer = interpreterProxy->firstIndexableField(spanOop); /* begin spanSizePut: */ value = (interpreterProxy->slotSizeOf(spanOop)) - 1; workBuffer[GWSpanSize] = value; return 0; } /* Load a transformation from transformOop into the float array defined by destPtr. The transformation is assumed to be either an array or a FloatArray of length n. */ static sqInt loadTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) { if (transformOop == (interpreterProxy->nilObject())) { return 0; } if ((transformOop & 1)) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(transformOop)) == n)) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->isWords(transformOop)) { loadWordTransformFromintolength(transformOop, destPtr, n); } else { loadArrayTransformFromintolength(transformOop, destPtr, n); } return 1; } /* Load the (possibly wide) bezier from the segments currently on the bezier stack. */ static sqInt loadWideBezierlineFillleftFillrightFilln(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill, sqInt nSegments) { sqInt bezier; sqInt bezier1; sqInt bezier2; sqInt index; sqInt offset; sqInt wide; if ((lineWidth == 0) || (lineFill == 0)) { wide = 0; offset = 0; } else { wide = 1; offset = ((sqInt) lineWidth >> 1); } index = nSegments * 6; while (index > 0) { if (wide) { /* begin allocateWideBezier */ if (!(allocateObjEntry(GBWideSize))) { bezier = 0; goto l1; } bezier1 = objUsed; objUsed = bezier1 + GBWideSize; objBuffer[bezier1 + GEObjectType] = GEPrimitiveWideBezier; objBuffer[bezier1 + GEObjectIndex] = 0; objBuffer[bezier1 + GEObjectLength] = GBWideSize; bezier = bezier1; l1: /* end allocateWideBezier */; } else { /* begin allocateBezier */ if (!(allocateObjEntry(GBBaseSize))) { bezier = 0; goto l2; } bezier2 = objUsed; objUsed = bezier2 + GBBaseSize; objBuffer[bezier2 + GEObjectType] = GEPrimitiveBezier; objBuffer[bezier2 + GEObjectIndex] = 0; objBuffer[bezier2 + GEObjectLength] = GBBaseSize; bezier = bezier2; l2: /* end allocateBezier */; } if (engineStopped) { return 0; } loadBeziersegmentleftFillrightFilloffset(bezier, index, leftFill, rightFill, offset); if (wide) { objBuffer[bezier + GBWideFill] = lineFill; objBuffer[bezier + GBWideWidth] = lineWidth; objBuffer[bezier + GBWideExtent] = lineWidth; } index -= 6; } /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); } /* Load a (possibly wide) line defined by the points p1 and p2 */ static sqInt loadWideLinefromtolineFillleftFillrightFill(sqInt lineWidth, int *p1, int *p2, sqInt lineFill, sqInt leftFill, sqInt rightFill) { sqInt line; sqInt line1; sqInt line2; sqInt offset; int *p11; int *p21; sqInt yDir; if ((lineWidth == 0) || (lineFill == 0)) { /* begin allocateLine */ if (!(allocateObjEntry(GLBaseSize))) { line = 0; goto l1; } line1 = objUsed; objUsed = line1 + GLBaseSize; objBuffer[line1 + GEObjectType] = GEPrimitiveLine; objBuffer[line1 + GEObjectIndex] = 0; objBuffer[line1 + GEObjectLength] = GLBaseSize; line = line1; l1: /* end allocateLine */; offset = 0; } else { /* begin allocateWideLine */ if (!(allocateObjEntry(GLWideSize))) { line = 0; goto l2; } line2 = objUsed; objUsed = line2 + GLWideSize; objBuffer[line2 + GEObjectType] = GEPrimitiveWideLine; objBuffer[line2 + GEObjectIndex] = 0; objBuffer[line2 + GEObjectLength] = GLWideSize; line = line2; l2: /* end allocateWideLine */; offset = ((sqInt) lineWidth >> 1); } if (engineStopped) { return 0; } /* begin loadLine:from:to:offset:leftFill:rightFill: */ if ((p1[1]) <= (p2[1])) { p11 = p1; p21 = p2; yDir = 1; } else { p11 = p2; p21 = p1; yDir = -1; } objBuffer[line + GEXValue] = (p11[0]); objBuffer[line + GEYValue] = ((p11[1]) - offset); objBuffer[line + GEZValue] = (workBuffer[GWCurrentZ]); objBuffer[line + GEFillIndexLeft] = leftFill; objBuffer[line + GEFillIndexRight] = rightFill; objBuffer[line + GLEndX] = (p21[0]); objBuffer[line + GLEndY] = ((p21[1]) - offset); objBuffer[line + GLYDirection] = yDir; if ((((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0) { objBuffer[line + GLWideFill] = lineFill; objBuffer[line + GLWideWidth] = lineWidth; objBuffer[line + GLWideExtent] = lineWidth; } } /* Load a float array transformation from the given oop */ static sqInt loadWordTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) { sqInt i; float *srcPtr; srcPtr = ((float *) (interpreterProxy->firstIndexableField(transformOop))); for (i = 0; i <= (n - 1); i += 1) { destPtr[i] = (srcPtr[i]); } } /* Load the working buffer from the given oop */ static sqInt loadWorkBufferFrom(sqInt wbOop) { if ((wbOop & 1)) { return GEFWorkBufferIsInteger; } if (!(interpreterProxy->isWords(wbOop))) { return GEFWorkBufferIsPointers; } if ((interpreterProxy->slotSizeOf(wbOop)) < GWMinimalSize) { return GEFWorkBufferTooSmall; } /* begin workBufferPut: */ workBuffer = interpreterProxy->firstIndexableField(wbOop); if (!((workBuffer[GWMagicIndex]) == GWMagicNumber)) { return GEFWorkBufferBadMagic; } if (!((workBuffer[GWSize]) == (interpreterProxy->slotSizeOf(wbOop)))) { return GEFWorkBufferWrongSize; } if (!((workBuffer[GWObjStart]) == GWHeaderSize)) { return GEFWorkBufferStartWrong; } objBuffer = workBuffer + (workBuffer[GWObjStart]); getBuffer = objBuffer + (workBuffer[GWObjUsed]); /* Make sure we don't exceed the work buffer */ aetBuffer = getBuffer + (workBuffer[GWGETUsed]); if ((((GWHeaderSize + (workBuffer[GWObjUsed])) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) > (workBuffer[GWSize])) { return GEFWorkTooBig; } return 0; } static sqInt magicNumberGet(void) { return workBuffer[GWMagicIndex]; } static sqInt magicNumberPut(sqInt value) { return workBuffer[GWMagicIndex] = value; } static sqInt makeRectFromPoints(void) { (point2Get())[0] = ((point3Get())[0]); (point2Get())[1] = ((point1Get())[1]); (point4Get())[0] = ((point1Get())[0]); (point4Get())[1] = ((point3Get())[1]); } static sqInt makeUnsignedFrom(sqInt someIntegerValue) { return someIntegerValue; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, bbPluginName)) == 0) { /* BitBlt just shut down. How nasty. */ loadBBFn = 0; copyBitsFn = 0; } } /* The entry at index is not in the right position of the AET. Move it to the left until the position is okay. */ static sqInt moveAETEntryFromedgex(sqInt index, sqInt edge, sqInt xValue) { sqInt newIndex; newIndex = index; while ((newIndex > 0) && ((objBuffer[(aetBuffer[newIndex - 1]) + GEXValue]) > xValue)) { aetBuffer[newIndex] = (aetBuffer[newIndex - 1]); newIndex -= 1; } aetBuffer[newIndex] = edge; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Check if we have n slots available */ static sqInt needAvailableSpace(sqInt nSlots) { if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + nSlots) > (workBuffer[GWBufferTop])) { /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorNoMoreSpace; engineStopped = 1; return 0; } return 1; } static sqInt needsFlush(void) { return (workBuffer[GWNeedsFlush]) != 0; } static sqInt needsFlushGet(void) { return workBuffer[GWNeedsFlush]; } static sqInt needsFlushPut(sqInt value) { return workBuffer[GWNeedsFlush] = value; } static sqInt objectHeaderOf(sqInt obj) { return objBuffer[obj + GEObjectType]; } static sqInt objectIndexOf(sqInt obj) { return objBuffer[obj + GEObjectIndex]; } static sqInt objectIndexOfput(sqInt obj, sqInt value) { return objBuffer[obj + GEObjectIndex] = value; } static sqInt objectLengthOf(sqInt obj) { return objBuffer[obj + GEObjectLength]; } static sqInt objectLengthOfput(sqInt obj, sqInt value) { return objBuffer[obj + GEObjectLength] = value; } static sqInt objectTypeOf(sqInt obj) { return (objBuffer[obj + GEObjectType]) & GEPrimitiveTypeMask; } static sqInt objectTypeOfput(sqInt obj, sqInt value) { return objBuffer[obj + GEObjectType] = value; } static sqInt objStartGet(void) { return workBuffer[GWObjStart]; } static sqInt objStartPut(sqInt value) { return workBuffer[GWObjStart] = value; } static sqInt objUsedGet(void) { return workBuffer[GWObjUsed]; } static sqInt objUsedPut(sqInt value) { return workBuffer[GWObjUsed] = value; } static sqInt objat(sqInt object, sqInt index) { return objBuffer[object + index]; } static sqInt objatput(sqInt object, sqInt index, sqInt value) { return objBuffer[object + index] = value; } /* Common function so that we don't compute that wrong in any place and can easily find all the places where we deal with one-pixel offsets. */ static sqInt offsetFromWidth(sqInt lineWidth) { return ((sqInt) lineWidth >> 1); } static int * point1Get(void) { return ((int *) (workBuffer + GWPoint1)); } static int * point2Get(void) { return ((int *) (workBuffer + GWPoint2)); } static int * point3Get(void) { return ((int *) (workBuffer + GWPoint3)); } static int * point4Get(void) { return ((int *) (workBuffer + GWPoint4)); } /* We have just blitted a scan line to the screen. Do whatever seems to be a good idea here. */ /* Note: In the future we may check the time needed for this scan line and interrupt processing to give the Smalltalk code a chance to run at a certain time. */ /* Check if there is any more work to do. */ static sqInt postDisplayAction(void) { if (((workBuffer[GWGETStart]) >= (workBuffer[GWGETUsed])) && ((workBuffer[GWAETUsed]) == 0)) { workBuffer[GWState] = GEStateCompleted; } if ((workBuffer[GWCurrentY]) >= (workBuffer[GWFillMaxY])) { workBuffer[GWState] = GEStateCompleted; } } EXPORT(sqInt) primitiveAbortProcessing(void) { sqInt failureCode; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } workBuffer[GWState] = GEStateCompleted; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; } /* Note: No need to load either bitBlt or spanBuffer */ EXPORT(sqInt) primitiveAddActiveEdgeEntry(void) { sqInt edge; sqInt edgeOop; sqInt failureCode; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateWaitingForEdge))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } edgeOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } edge = loadEdgeStateFrom(edgeOop); if (edge == null) { return interpreterProxy->primitiveFailFor(GEFEdgeDataTooSmall); } if (!(needAvailableSpace(1))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } if ((objBuffer[edge + GENumLines]) > 0) { insertEdgeIntoAET(edge); } if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } workBuffer[GWState] = GEStateAddingFromGET; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); if (doProfileStats) { workBuffer[GWCountAddAETEntry] = ((workBuffer[GWCountAddAETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeAddAETEntry] = ((workBuffer[GWTimeAddAETEntry]) + value); } } EXPORT(sqInt) primitiveAddBezier(void) { sqInt endOop; sqInt failureCode; sqInt leftFill; sqInt nSegments; int *point; int *point1; int *point2; int *point3; sqInt rightFill; sqInt startOop; float *transform; float *transform1; float *transform2; float *transform3; sqInt viaOop; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } rightFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); leftFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); viaOop = interpreterProxy->stackObjectValue(2); endOop = interpreterProxy->stackObjectValue(3); startOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!((isFillOkay(leftFill)) && (isFillOkay(rightFill)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } if ((leftFill == rightFill) && 0) { return interpreterProxy->pop(6); } loadPointfrom(point1Get(), startOop); loadPointfrom(point2Get(), viaOop); loadPointfrom(point3Get(), endOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } nSegments = loadAndSubdivideBezierFromviatoisWide(point1Get(), point2Get(), point3Get(), 0); /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + (nSegments * GBBaseSize)) > (workBuffer[GWBufferTop])) { /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorNoMoreSpace; engineStopped = 1; goto l1; } l1: /* end needAvailableSpace: */; if (!(engineStopped)) { leftFill = transformColor(leftFill); rightFill = transformColor(rightFill); } if (!(engineStopped)) { loadWideBezierlineFillleftFillrightFilln(0, 0, leftFill, rightFill, nSegments); } if (engineStopped) { /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(5); } EXPORT(sqInt) primitiveAddBezierShape(void) { sqInt failureCode; sqInt fillIndex; sqInt isArray; sqInt length; sqInt lineFill; sqInt lineWidth; sqInt nSegments; sqInt points; sqInt segSize; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } lineFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); lineWidth = interpreterProxy->stackIntegerValue(1); fillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(2)); nSegments = interpreterProxy->stackIntegerValue(3); points = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } length = interpreterProxy->slotSizeOf(points); if (interpreterProxy->isWords(points)) { /* Either PointArray or ShortPointArray */ isArray = 0; if (!((length == (nSegments * 3)) || (length == (nSegments * 6)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } } else { if (!(interpreterProxy->isArray(points))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(length == (nSegments * 3))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } isArray = 1; } if ((lineWidth == 0) || (lineFill == 0)) { segSize = GLBaseSize; } else { segSize = GLWideSize; } if (!(needAvailableSpace(segSize * nSegments))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } if (!((isFillOkay(lineFill)) && (isFillOkay(fillIndex)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } lineFill = transformColor(lineFill); fillIndex = transformColor(fillIndex); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (((lineFill == 0) || (lineWidth == 0)) && (fillIndex == 0)) { return interpreterProxy->pop(5); } if (!(lineWidth == 0)) { lineWidth = transformWidth(lineWidth); if (lineWidth < 1) { lineWidth = 1; } } if (isArray) { loadArrayShapenSegmentsfilllineWidthlineFill(points, nSegments, fillIndex, lineWidth, lineFill); } else { loadShapenSegmentsfilllineWidthlineFillpointsShort(interpreterProxy->firstIndexableField(points), nSegments, fillIndex, lineWidth, lineFill, (nSegments * 3) == length); } if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } workBuffer[GWNeedsFlush] = 1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(5); } EXPORT(sqInt) primitiveAddBitmapFill(void) { sqInt bmBits; sqInt bmBitsSize; sqInt bmDepth; sqInt bmFill; sqInt bmHeight; sqInt bmRaster; sqInt bmWidth; int *cm; int *cmBits; sqInt cmOop; sqInt cmSize; sqInt dirOop; sqInt failureCode; sqInt fill; sqInt fill1; sqInt fillSize; sqInt formOop; sqInt i; sqInt nrmOop; sqInt originOop; int *point1; int *point2; int *point3; sqInt ppw; sqInt tileFlag; sqInt tileFlag1; sqInt xIndex; if (!((interpreterProxy->methodArgumentCount()) == 7)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } xIndex = interpreterProxy->stackIntegerValue(0); if (xIndex <= 0) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } nrmOop = interpreterProxy->stackObjectValue(1); dirOop = interpreterProxy->stackObjectValue(2); originOop = interpreterProxy->stackObjectValue(3); tileFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(4)); cmOop = interpreterProxy->stackObjectValue(5); formOop = interpreterProxy->stackObjectValue(6); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(7), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } loadPointfrom(point1Get(), originOop); loadPointfrom(point2Get(), dirOop); loadPointfrom(point3Get(), nrmOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFBadPoint); } /* begin loadBitmapFill:colormap:tile:from:along:normal:xIndex: */ tileFlag1 = (tileFlag ? 1 : 0); /* begin point1Get */ point1 = ((int *) (workBuffer + GWPoint1)); /* begin point2Get */ point2 = ((int *) (workBuffer + GWPoint2)); /* begin point3Get */ point3 = ((int *) (workBuffer + GWPoint3)); if (cmOop == (interpreterProxy->nilObject())) { cmSize = 0; cmBits = null; } else { if (!((interpreterProxy->fetchClassOf(cmOop)) == (interpreterProxy->classBitmap()))) { fill = interpreterProxy->primitiveFail(); goto l1; } cmSize = interpreterProxy->slotSizeOf(cmOop); cmBits = interpreterProxy->firstIndexableField(cmOop); } if ((formOop & 1)) { fill = interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isPointers(formOop))) { fill = interpreterProxy->primitiveFail(); goto l1; } if ((interpreterProxy->slotSizeOf(formOop)) < 5) { fill = interpreterProxy->primitiveFail(); goto l1; } bmBits = interpreterProxy->fetchPointerofObject(0, formOop); if (!((interpreterProxy->fetchClassOf(bmBits)) == (interpreterProxy->classBitmap()))) { fill = interpreterProxy->primitiveFail(); goto l1; } bmBitsSize = interpreterProxy->slotSizeOf(bmBits); bmWidth = interpreterProxy->fetchIntegerofObject(1, formOop); bmHeight = interpreterProxy->fetchIntegerofObject(2, formOop); bmDepth = interpreterProxy->fetchIntegerofObject(3, formOop); if (interpreterProxy->failed()) { fill = null; goto l1; } if (!((bmWidth >= 0) && (bmHeight >= 0))) { fill = interpreterProxy->primitiveFail(); goto l1; } if (!((((((bmDepth == 32) || (bmDepth == 8)) || (bmDepth == 16)) || (bmDepth == 1)) || (bmDepth == 2)) || (bmDepth == 4))) { fill = interpreterProxy->primitiveFail(); goto l1; } if (!((cmSize == 0) || (cmSize == (1 << bmDepth)))) { fill = interpreterProxy->primitiveFail(); goto l1; } ppw = 32 / bmDepth; bmRaster = (bmWidth + (ppw - 1)) / ppw; if (!(bmBitsSize == (bmRaster * bmHeight))) { fill = interpreterProxy->primitiveFail(); goto l1; } /* begin allocateBitmapFill:colormap: */ fillSize = GBMBaseSize + cmSize; if (!(allocateObjEntry(fillSize))) { bmFill = 0; goto l2; } fill1 = objUsed; objUsed = fill1 + fillSize; objBuffer[fill1 + GEObjectType] = GEPrimitiveClippedBitmapFill; objBuffer[fill1 + GEObjectIndex] = 0; objBuffer[fill1 + GEObjectLength] = fillSize; /* begin colormapOf: */ cm = (objBuffer + fill1) + GBColormapOffset; if ((workBuffer[GWHasColorTransform]) != 0) { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (transformColor(cmBits[i])); } } else { for (i = 0; i <= (cmSize - 1); i += 1) { cm[i] = (cmBits[i]); } } objBuffer[fill1 + GBColormapSize] = cmSize; bmFill = fill1; l2: /* end allocateBitmapFill:colormap: */; if (engineStopped) { fill = null; goto l1; } objBuffer[bmFill + GBBitmapWidth] = bmWidth; objBuffer[bmFill + GBBitmapHeight] = bmHeight; objBuffer[bmFill + GBBitmapDepth] = bmDepth; objBuffer[bmFill + GBBitmapRaster] = bmRaster; objBuffer[bmFill + GBBitmapSize] = bmBitsSize; objBuffer[bmFill + GBTileFlag] = tileFlag1; objBuffer[bmFill + GEObjectIndex] = (xIndex - 1); loadFillOrientationfromalongnormalwidthheight(bmFill, point1, point2, point3, bmWidth, bmHeight); fill = bmFill; l1: /* end loadBitmapFill:colormap:tile:from:along:normal:xIndex: */; if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->popthenPush(8, interpreterProxy->positive32BitIntegerFor(fill)); } EXPORT(sqInt) primitiveAddCompressedShape(void) { sqInt failureCode; sqInt fillIndexList; sqInt leftFills; sqInt lineFills; sqInt lineWidths; sqInt nSegments; sqInt points; sqInt pointsShort; sqInt rightFills; if (!((interpreterProxy->methodArgumentCount()) == 7)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } fillIndexList = interpreterProxy->stackObjectValue(0); lineFills = interpreterProxy->stackObjectValue(1); lineWidths = interpreterProxy->stackObjectValue(2); rightFills = interpreterProxy->stackObjectValue(3); leftFills = interpreterProxy->stackObjectValue(4); nSegments = interpreterProxy->stackIntegerValue(5); points = interpreterProxy->stackObjectValue(6); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(7), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(checkCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(points, nSegments, leftFills, rightFills, lineWidths, lineFills, fillIndexList))) { return interpreterProxy->primitiveFailFor(GEFEntityCheckFailed); } if (!(needAvailableSpace((((GBBaseSize < GLBaseSize) ? GLBaseSize : GBBaseSize)) * nSegments))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } /* Then actually load the compressed shape */ pointsShort = (interpreterProxy->slotSizeOf(points)) == (nSegments * 3); loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(interpreterProxy->firstIndexableField(points), nSegments, interpreterProxy->firstIndexableField(leftFills), interpreterProxy->firstIndexableField(rightFills), interpreterProxy->firstIndexableField(lineWidths), interpreterProxy->firstIndexableField(lineFills), interpreterProxy->firstIndexableField(fillIndexList), pointsShort); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } workBuffer[GWNeedsFlush] = 1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(7); } EXPORT(sqInt) primitiveAddGradientFill(void) { sqInt dirOop; sqInt failureCode; sqInt fill; sqInt isRadial; sqInt nrmOop; sqInt originOop; sqInt rampOop; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } isRadial = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); nrmOop = interpreterProxy->stackValue(1); dirOop = interpreterProxy->stackValue(2); originOop = interpreterProxy->stackValue(3); rampOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } loadPointfrom(point1Get(), originOop); loadPointfrom(point2Get(), dirOop); loadPointfrom(point3Get(), nrmOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFBadPoint); } fill = loadGradientFillfromalongnormalisRadial(rampOop, point1Get(), point2Get(), point3Get(), isRadial); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->popthenPush(6, interpreterProxy->positive32BitIntegerFor(fill)); } EXPORT(sqInt) primitiveAddLine(void) { sqInt endOop; sqInt failureCode; sqInt leftFill; int *point; int *point1; int *point2; int *point3; sqInt rightFill; sqInt startOop; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } rightFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); leftFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); endOop = interpreterProxy->stackObjectValue(2); startOop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(4), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!((isFillOkay(leftFill)) && (isFillOkay(rightFill)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } loadPointfrom(point1Get(), startOop); loadPointfrom(point2Get(), endOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFBadPoint); } /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } leftFill = transformColor(leftFill); rightFill = transformColor(rightFill); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } loadWideLinefromtolineFillleftFillrightFill(0, point1Get(), point2Get(), 0, leftFill, rightFill); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(4); } EXPORT(sqInt) primitiveAddOval(void) { sqInt borderIndex; sqInt borderWidth; sqInt endOop; sqInt failureCode; sqInt fillIndex; sqInt startOop; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } borderIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); borderWidth = interpreterProxy->stackIntegerValue(1); fillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(2)); endOop = interpreterProxy->stackObjectValue(3); startOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!((isFillOkay(borderIndex)) && (isFillOkay(fillIndex)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } fillIndex = transformColor(fillIndex); borderIndex = transformColor(borderIndex); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if ((fillIndex == 0) && ((borderIndex == 0) || (borderWidth <= 0))) { return interpreterProxy->pop(5); } if (!(needAvailableSpace(16 * GBBaseSize))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } if ((borderWidth > 0) && (borderIndex != 0)) { borderWidth = transformWidth(borderWidth); } else { borderWidth = 0; } loadPointfrom(point1Get(), startOop); loadPointfrom(point2Get(), endOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFBadPoint); } loadOvallineFillleftFillrightFill(borderWidth, borderIndex, 0, fillIndex); if (engineStopped) { /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } workBuffer[GWNeedsFlush] = 1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(5); } EXPORT(sqInt) primitiveAddPolygon(void) { sqInt failureCode; sqInt fillIndex; sqInt i; sqInt i1; sqInt isArray; sqInt length; sqInt lineFill; sqInt lineWidth; sqInt nPoints; int *point; int *point1; int *point2; int *point3; int *point4; int *point5; int *point6; int *point7; sqInt points; int *points1; sqInt segSize; float *transform; float *transform1; float *transform2; float *transform3; float *transform4; float *transform5; float *transform6; float *transform7; sqInt x; sqInt x0; sqInt x01; sqInt x1; sqInt x11; sqInt x2; sqInt x3; sqInt x4; sqInt x5; sqInt x6; sqInt x7; sqInt x8; sqInt y; sqInt y0; sqInt y01; sqInt y1; sqInt y11; sqInt y2; sqInt y3; sqInt y4; sqInt y5; sqInt y6; sqInt y7; sqInt y8; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } lineFill = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); lineWidth = interpreterProxy->stackIntegerValue(1); fillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(2)); nPoints = interpreterProxy->stackIntegerValue(3); points = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } length = interpreterProxy->slotSizeOf(points); if (interpreterProxy->isWords(points)) { /* Either PointArray or ShortPointArray */ isArray = 0; if (!((length == nPoints) || ((nPoints * 2) == length))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } } else { if (!(interpreterProxy->isArray(points))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(length == nPoints)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } isArray = 1; } if ((lineWidth == 0) || (lineFill == 0)) { segSize = GLBaseSize; } else { segSize = GLWideSize; } if (!(needAvailableSpace(segSize * nPoints))) { return interpreterProxy->primitiveFail(); } if (!((isFillOkay(lineFill)) && (isFillOkay(fillIndex)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } lineFill = transformColor(lineFill); fillIndex = transformColor(fillIndex); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (((lineFill == 0) || (lineWidth == 0)) && (fillIndex == 0)) { return interpreterProxy->pop(6); } if (!(lineWidth == 0)) { lineWidth = transformWidth(lineWidth); } if (isArray) { /* begin loadArrayPolygon:nPoints:fill:lineWidth:lineFill: */ loadPointfrom(point1Get(), interpreterProxy->fetchPointerofObject(0, points)); if (interpreterProxy->failed()) { goto l1; } x0 = (point1Get())[0]; y0 = (point1Get())[1]; for (i = 1; i <= (nPoints - 1); i += 1) { loadPointfrom(point1Get(), interpreterProxy->fetchPointerofObject(i, points)); if (interpreterProxy->failed()) { goto l1; } x1 = (point1Get())[0]; y1 = (point1Get())[1]; (point1Get())[0] = x0; (point1Get())[1] = y0; (point2Get())[0] = x1; (point2Get())[1] = y1; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x2; (((int *) point1))[1] = y2; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x3; (((int *) point2))[1] = y3; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x4 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y4 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x4; (((int *) point3))[1] = y4; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, fillIndex, 0); if (engineStopped) { goto l1; } x0 = x1; y0 = y1; } l1: /* end loadArrayPolygon:nPoints:fill:lineWidth:lineFill: */; } else { /* begin loadPolygon:nPoints:fill:lineWidth:lineFill:pointsShort: */ points1 = interpreterProxy->firstIndexableField(points); if (nPoints == length) { /* begin loadPointShortAt:from: */ x01 = ((short) ((((short *) points1))[0])); /* begin loadPointShortAt:from: */ y01 = ((short) ((((short *) points1))[1])); } else { x01 = (((int *) points1))[0]; y01 = (((int *) points1))[1]; } for (i1 = 1; i1 <= (nPoints - 1); i1 += 1) { if (nPoints == length) { /* begin loadPointShortAt:from: */ x11 = ((short) ((((short *) points1))[i1 * 2])); /* begin loadPointShortAt:from: */ y11 = ((short) ((((short *) points1))[(i1 * 2) + 1])); } else { x11 = (((int *) points1))[i1 * 2]; y11 = (((int *) points1))[(i1 * 2) + 1]; } (point1Get())[0] = x01; (point1Get())[1] = y01; (point2Get())[0] = x11; (point2Get())[1] = y11; /* begin transformPoints: */ if (2 > 0) { /* begin transformPoint: */ /* begin point1Get */ point4 = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform4 = ((float *) (workBuffer + GWEdgeTransform)); x5 = ((sqInt)(((((transform4[0]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[1]) * (((double) ((((int *) point4))[1]) )))) + (transform4[2])) * (((double) (workBuffer[GWAALevel]) )))); y5 = ((sqInt)(((((transform4[3]) * (((double) ((((int *) point4))[0]) ))) + ((transform4[4]) * (((double) ((((int *) point4))[1]) )))) + (transform4[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point4))[0] = x5; (((int *) point4))[1] = y5; } else { point4[0] = (((point4[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point4[1] = (((point4[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 1) { /* begin transformPoint: */ /* begin point2Get */ point5 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform5 = ((float *) (workBuffer + GWEdgeTransform)); x6 = ((sqInt)(((((transform5[0]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[1]) * (((double) ((((int *) point5))[1]) )))) + (transform5[2])) * (((double) (workBuffer[GWAALevel]) )))); y6 = ((sqInt)(((((transform5[3]) * (((double) ((((int *) point5))[0]) ))) + ((transform5[4]) * (((double) ((((int *) point5))[1]) )))) + (transform5[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point5))[0] = x6; (((int *) point5))[1] = y6; } else { point5[0] = (((point5[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point5[1] = (((point5[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 2) { /* begin transformPoint: */ /* begin point3Get */ point6 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform6 = ((float *) (workBuffer + GWEdgeTransform)); x7 = ((sqInt)(((((transform6[0]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[1]) * (((double) ((((int *) point6))[1]) )))) + (transform6[2])) * (((double) (workBuffer[GWAALevel]) )))); y7 = ((sqInt)(((((transform6[3]) * (((double) ((((int *) point6))[0]) ))) + ((transform6[4]) * (((double) ((((int *) point6))[1]) )))) + (transform6[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point6))[0] = x7; (((int *) point6))[1] = y7; } else { point6[0] = (((point6[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point6[1] = (((point6[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (2 > 3) { /* begin transformPoint: */ /* begin point4Get */ point7 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform7 = ((float *) (workBuffer + GWEdgeTransform)); x8 = ((sqInt)(((((transform7[0]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[1]) * (((double) ((((int *) point7))[1]) )))) + (transform7[2])) * (((double) (workBuffer[GWAALevel]) )))); y8 = ((sqInt)(((((transform7[3]) * (((double) ((((int *) point7))[0]) ))) + ((transform7[4]) * (((double) ((((int *) point7))[1]) )))) + (transform7[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point7))[0] = x8; (((int *) point7))[1] = y8; } else { point7[0] = (((point7[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point7[1] = (((point7[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } loadWideLinefromtolineFillleftFillrightFill(lineWidth, point1Get(), point2Get(), lineFill, fillIndex, 0); if (engineStopped) { goto l2; } x01 = x11; y01 = y11; } l2: /* end loadPolygon:nPoints:fill:lineWidth:lineFill:pointsShort: */; } if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } workBuffer[GWNeedsFlush] = 1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(5); } EXPORT(sqInt) primitiveAddRect(void) { sqInt borderIndex; sqInt borderWidth; sqInt endOop; sqInt failureCode; sqInt fillIndex; int *point; int *point1; int *point2; int *point3; sqInt startOop; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } borderIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); borderWidth = interpreterProxy->stackIntegerValue(1); fillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(2)); endOop = interpreterProxy->stackObjectValue(3); startOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(5), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!((isFillOkay(borderIndex)) && (isFillOkay(fillIndex)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } borderIndex = transformColor(borderIndex); fillIndex = transformColor(fillIndex); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if ((fillIndex == 0) && ((borderIndex == 0) || (borderWidth == 0))) { return interpreterProxy->pop(5); } if (!(needAvailableSpace(4 * GLBaseSize))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } if ((borderWidth > 0) && (borderIndex != 0)) { borderWidth = transformWidth(borderWidth); } else { borderWidth = 0; } loadPointfrom(point1Get(), startOop); loadPointfrom(point3Get(), endOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFBadPoint); } (point2Get())[0] = ((point3Get())[0]); (point2Get())[1] = ((point1Get())[1]); (point4Get())[0] = ((point1Get())[0]); (point4Get())[1] = ((point3Get())[1]); /* begin transformPoints: */ if (4 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (4 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (4 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (4 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } /* begin loadRectangle:lineFill:leftFill:rightFill: */ loadWideLinefromtolineFillleftFillrightFill(borderWidth, point1Get(), point2Get(), borderIndex, 0, fillIndex); loadWideLinefromtolineFillleftFillrightFill(borderWidth, point2Get(), point3Get(), borderIndex, 0, fillIndex); loadWideLinefromtolineFillleftFillrightFill(borderWidth, point3Get(), point4Get(), borderIndex, 0, fillIndex); loadWideLinefromtolineFillleftFillrightFill(borderWidth, point4Get(), point1Get(), borderIndex, 0, fillIndex); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } workBuffer[GWNeedsFlush] = 1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(5); } /* Note: No need to load either bitBlt or spanBuffer */ EXPORT(sqInt) primitiveChangedActiveEdgeEntry(void) { sqInt edge; sqInt edgeOop; sqInt failureCode; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateWaitingChange))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } edgeOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } edge = loadEdgeStateFrom(edgeOop); if (edge == null) { return interpreterProxy->primitiveFailFor(GEFEdgeDataTooSmall); } if ((objBuffer[edge + GENumLines]) == 0) { removeFirstAETEntry(); } else { resortFirstAETEntry(); workBuffer[GWAETStart] = ((workBuffer[GWAETStart]) + 1); } workBuffer[GWState] = GEStateUpdateEdges; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); if (doProfileStats) { workBuffer[GWCountChangeAETEntry] = ((workBuffer[GWCountChangeAETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeChangeAETEntry] = ((workBuffer[GWTimeChangeAETEntry]) + value); } } EXPORT(sqInt) primitiveCopyBuffer(void) { sqInt buf1; sqInt buf2; sqInt diff; int * dst; sqInt failCode; sqInt i; int * src; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } buf2 = interpreterProxy->stackValue(0); /* Make sure the old buffer is properly initialized */ buf1 = interpreterProxy->stackValue(1); if (!(((failCode = loadWorkBufferFrom(buf1))) == 0)) { return interpreterProxy->primitiveFailFor(failCode); } if (!((interpreterProxy->fetchClassOf(buf1)) == (interpreterProxy->fetchClassOf(buf2)))) { return interpreterProxy->primitiveFailFor(GEFClassMismatch); } diff = (interpreterProxy->slotSizeOf(buf2)) - (interpreterProxy->slotSizeOf(buf1)); if (diff < 0) { return interpreterProxy->primitiveFailFor(GEFSizeMismatch); } src = workBuffer; dst = interpreterProxy->firstIndexableField(buf2); for (i = 0; i <= ((workBuffer[GWBufferTop]) - 1); i += 1) { dst[i] = (src[i]); } dst[GWBufferTop] = ((workBuffer[GWBufferTop]) + diff); dst[GWSize] = ((workBuffer[GWSize]) + diff); src += workBuffer[GWBufferTop]; dst = (dst + (workBuffer[GWBufferTop])) + diff; for (i = 0; i <= (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 1); i += 1) { dst[i] = (src[i]); } if (!(((failCode = loadWorkBufferFrom(buf2))) == 0)) { return interpreterProxy->primitiveFailFor(failCode); } interpreterProxy->pop(2); } /* Note: Must load bitBlt and spanBuffer */ EXPORT(sqInt) primitiveDisplaySpanBuffer(void) { sqInt failureCode; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(0), GEStateBlitBuffer))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(((failureCode = loadSpanBufferFrom(interpreterProxy->fetchPointerofObject(BESpanIndex, engine)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(loadBitBltFrom(interpreterProxy->fetchPointerofObject(BEBitBltIndex, engine)))) { return interpreterProxy->primitiveFailFor(GEFBitBltLoadFailed); } if (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == (workBuffer[GWAAScanMask])) { displaySpanBufferAt(workBuffer[GWCurrentY]); postDisplayAction(); } if (!((workBuffer[GWState]) == GEStateCompleted)) { workBuffer[GWAETStart] = 0; workBuffer[GWCurrentY] = ((workBuffer[GWCurrentY]) + 1); workBuffer[GWState] = GEStateUpdateEdges; } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; if (doProfileStats) { workBuffer[GWCountDisplaySpan] = ((workBuffer[GWCountDisplaySpan]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeDisplaySpan] = ((workBuffer[GWTimeDisplaySpan]) + value); } } /* Turn on/off profiling. Return the old value of the flag. */ EXPORT(sqInt) primitiveDoProfileStats(void) { sqInt newValue; sqInt oldValue; oldValue = doProfileStats; newValue = interpreterProxy->stackObjectValue(0); newValue = interpreterProxy->booleanValueOf(newValue); if (!(interpreterProxy->failed())) { doProfileStats = newValue; interpreterProxy->pop(2); interpreterProxy->pushBool(oldValue); } } EXPORT(sqInt) primitiveFinishedProcessing(void) { sqInt failureCode; sqInt finished; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } finished = (workBuffer[GWState]) == GEStateCompleted; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); interpreterProxy->pushBool(finished); if (doProfileStats) { workBuffer[GWCountFinishTest] = ((workBuffer[GWCountFinishTest]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeFinishTest] = ((workBuffer[GWTimeFinishTest]) + value); } } EXPORT(sqInt) primitiveGetAALevel(void) { sqInt failureCode; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } interpreterProxy->pop(1); interpreterProxy->pushInteger(workBuffer[GWAALevel]); } EXPORT(sqInt) primitiveGetBezierStats(void) { sqInt failureCode; sqInt statOop; int *stats; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(1)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } statOop = interpreterProxy->stackObjectValue(0); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->isWords(statOop)) && ((interpreterProxy->slotSizeOf(statOop)) >= 4)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } stats = interpreterProxy->firstIndexableField(statOop); stats[0] = ((stats[0]) + (workBuffer[GWBezierMonotonSubdivisions])); stats[1] = ((stats[1]) + (workBuffer[GWBezierHeightSubdivisions])); stats[2] = ((stats[2]) + (workBuffer[GWBezierOverflowSubdivisions])); stats[3] = ((stats[3]) + (workBuffer[GWBezierLineConversions])); interpreterProxy->pop(1); } EXPORT(sqInt) primitiveGetClipRect(void) { sqInt failureCode; sqInt pointOop; sqInt rectOop; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(1)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } rectOop = interpreterProxy->stackObjectValue(0); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->isPointers(rectOop)) && ((interpreterProxy->slotSizeOf(rectOop)) >= 2)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } interpreterProxy->pushRemappableOop(rectOop); pointOop = interpreterProxy->makePointwithxValueyValue(workBuffer[GWClipMinX], workBuffer[GWClipMinY]); interpreterProxy->storePointerofObjectwithValue(0, interpreterProxy->topRemappableOop(), pointOop); pointOop = interpreterProxy->makePointwithxValueyValue(workBuffer[GWClipMaxX], workBuffer[GWClipMaxY]); rectOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, rectOop, pointOop); interpreterProxy->popthenPush(2, rectOop); } EXPORT(sqInt) primitiveGetCounts(void) { sqInt failureCode; sqInt statOop; int *stats; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(1)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } statOop = interpreterProxy->stackObjectValue(0); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->isWords(statOop)) && ((interpreterProxy->slotSizeOf(statOop)) >= 9)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } stats = interpreterProxy->firstIndexableField(statOop); stats[0] = ((stats[0]) + (workBuffer[GWCountInitializing])); stats[1] = ((stats[1]) + (workBuffer[GWCountFinishTest])); stats[2] = ((stats[2]) + (workBuffer[GWCountNextGETEntry])); stats[3] = ((stats[3]) + (workBuffer[GWCountAddAETEntry])); stats[4] = ((stats[4]) + (workBuffer[GWCountNextFillEntry])); stats[5] = ((stats[5]) + (workBuffer[GWCountMergeFill])); stats[6] = ((stats[6]) + (workBuffer[GWCountDisplaySpan])); stats[7] = ((stats[7]) + (workBuffer[GWCountNextAETEntry])); stats[8] = ((stats[8]) + (workBuffer[GWCountChangeAETEntry])); interpreterProxy->pop(1); } EXPORT(sqInt) primitiveGetDepth(void) { sqInt failureCode; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } interpreterProxy->pop(1); interpreterProxy->pushInteger(workBuffer[GWCurrentZ]); } /* Return the reason why the last operation failed. */ EXPORT(sqInt) primitiveGetFailureReason(void) { sqInt failCode; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } /* Note -- don't call loadEngineFrom here because this will override the stopReason with Zero */ engine = interpreterProxy->stackValue(0); if ((engine & 1)) { return interpreterProxy->primitiveFailFor(GEFEngineIsInteger); } if (!(interpreterProxy->isPointers(engine))) { return interpreterProxy->primitiveFailFor(GEFEngineIsWords); } if ((interpreterProxy->slotSizeOf(engine)) < BEBalloonEngineSize) { return interpreterProxy->primitiveFailFor(GEFEngineTooSmall); } if (!(((failCode = loadWorkBufferFrom(interpreterProxy->fetchPointerofObject(BEWorkBufferIndex, engine)))) == 0)) { return interpreterProxy->primitiveFailFor(failCode); } interpreterProxy->pop(1); interpreterProxy->pushInteger(workBuffer[GWStopReason]); } EXPORT(sqInt) primitiveGetOffset(void) { sqInt failureCode; sqInt pointOop; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } pointOop = interpreterProxy->makePointwithxValueyValue(workBuffer[GWDestOffsetX], workBuffer[GWDestOffsetY]); interpreterProxy->popthenPush(1, pointOop); } EXPORT(sqInt) primitiveGetTimes(void) { sqInt failureCode; sqInt statOop; int *stats; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(1)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } statOop = interpreterProxy->stackObjectValue(0); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->isWords(statOop)) && ((interpreterProxy->slotSizeOf(statOop)) >= 9)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } stats = interpreterProxy->firstIndexableField(statOop); stats[0] = ((stats[0]) + (workBuffer[GWTimeInitializing])); stats[1] = ((stats[1]) + (workBuffer[GWTimeFinishTest])); stats[2] = ((stats[2]) + (workBuffer[GWTimeNextGETEntry])); stats[3] = ((stats[3]) + (workBuffer[GWTimeAddAETEntry])); stats[4] = ((stats[4]) + (workBuffer[GWTimeNextFillEntry])); stats[5] = ((stats[5]) + (workBuffer[GWTimeMergeFill])); stats[6] = ((stats[6]) + (workBuffer[GWTimeDisplaySpan])); stats[7] = ((stats[7]) + (workBuffer[GWTimeNextAETEntry])); stats[8] = ((stats[8]) + (workBuffer[GWTimeChangeAETEntry])); interpreterProxy->pop(1); } EXPORT(sqInt) primitiveInitializeBuffer(void) { sqInt size; sqInt wbOop; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } wbOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(wbOop))) { return interpreterProxy->primitiveFail(); } if (((size = interpreterProxy->slotSizeOf(wbOop))) < GWMinimalSize) { return interpreterProxy->primitiveFail(); } /* begin workBufferPut: */ workBuffer = interpreterProxy->firstIndexableField(wbOop); objBuffer = workBuffer + GWHeaderSize; workBuffer[GWMagicIndex] = GWMagicNumber; workBuffer[GWSize] = size; workBuffer[GWBufferTop] = size; workBuffer[GWState] = GEStateUnlocked; workBuffer[GWObjStart] = GWHeaderSize; workBuffer[GWObjUsed] = 4; objBuffer[0 + GEObjectType] = GEPrimitiveFill; objBuffer[0 + GEObjectLength] = 4; objBuffer[0 + GEObjectIndex] = 0; workBuffer[GWGETStart] = 0; workBuffer[GWGETUsed] = 0; workBuffer[GWAETStart] = 0; workBuffer[GWAETUsed] = 0; workBuffer[GWStopReason] = 0; workBuffer[GWNeedsFlush] = 0; workBuffer[GWClipMinX] = 0; workBuffer[GWClipMaxX] = 0; workBuffer[GWClipMinY] = 0; workBuffer[GWClipMaxY] = 0; workBuffer[GWCurrentZ] = 0; resetGraphicsEngineStats(); initEdgeTransform(); initColorTransform(); interpreterProxy->pop(2); interpreterProxy->push(wbOop); } /* Note: No need to load bitBlt but must load spanBuffer */ EXPORT(sqInt) primitiveInitializeProcessing(void) { sqInt failureCode; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(0), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(((failureCode = loadSpanBufferFrom(interpreterProxy->fetchPointerofObject(BESpanIndex, engine)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } initializeGETProcessing(); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } workBuffer[GWState] = GEStateAddingFromGET; if (!(interpreterProxy->failed())) { /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; } if (doProfileStats) { workBuffer[GWCountInitializing] = ((workBuffer[GWCountInitializing]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeInitializing] = ((workBuffer[GWTimeInitializing]) + value); } } /* Note: No need to load bitBlt but must load spanBuffer */ EXPORT(sqInt) primitiveMergeFillFrom(void) { sqInt bitsOop; sqInt failureCode; sqInt fillOop; sqInt value; sqInt value1; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(2), GEStateWaitingForFill))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(((failureCode = loadSpanBufferFrom(interpreterProxy->fetchPointerofObject(BESpanIndex, engine)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } fillOop = interpreterProxy->stackObjectValue(0); /* Check bitmap */ bitsOop = interpreterProxy->stackObjectValue(1); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->fetchClassOf(bitsOop)) == (interpreterProxy->classBitmap())))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if ((interpreterProxy->slotSizeOf(fillOop)) < FTBalloonFillDataSize) { return interpreterProxy->primitiveFailFor(GEFFillDataTooSmall); } value = interpreterProxy->fetchIntegerofObject(FTIndexIndex, fillOop); if (!((objBuffer[(workBuffer[GWLastExportedFill]) + GEObjectIndex]) == value)) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } value = interpreterProxy->fetchIntegerofObject(FTMinXIndex, fillOop); if (!((workBuffer[GWLastExportedLeftX]) == value)) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } value = interpreterProxy->fetchIntegerofObject(FTMaxXIndex, fillOop); if (!((workBuffer[GWLastExportedRightX]) == value)) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } if ((interpreterProxy->slotSizeOf(bitsOop)) < ((workBuffer[GWLastExportedRightX]) - (workBuffer[GWLastExportedLeftX]))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (interpreterProxy->failed()) { return null; } fillBitmapSpanfromto(interpreterProxy->firstIndexableField(bitsOop), workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX]); workBuffer[GWState] = GEStateScanningAET; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(2); if (doProfileStats) { workBuffer[GWCountMergeFill] = ((workBuffer[GWCountMergeFill]) + 1); /* begin incrementStat:by: */ value1 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeMergeFill] = ((workBuffer[GWTimeMergeFill]) + value1); } } EXPORT(sqInt) primitiveNeedsFlush(void) { sqInt failureCode; sqInt needFlush; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(0)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } needFlush = (workBuffer[GWNeedsFlush]) != 0; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); interpreterProxy->pushBool(needFlush); } EXPORT(sqInt) primitiveNeedsFlushPut(void) { sqInt failureCode; sqInt needFlush; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFrom(interpreterProxy->stackValue(1)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } needFlush = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (needFlush == 1) { workBuffer[GWNeedsFlush] = 1; } else { workBuffer[GWNeedsFlush] = 0; } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } /* Note: No need to load either bitBlt or spanBuffer */ EXPORT(sqInt) primitiveNextActiveEdgeEntry(void) { sqInt edge; sqInt edgeOop; sqInt failureCode; sqInt hasEdge; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredStateor(interpreterProxy->stackValue(1), GEStateUpdateEdges, GEStateCompleted))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } edgeOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } hasEdge = 0; if (!((workBuffer[GWState]) == GEStateCompleted)) { hasEdge = findNextExternalUpdateFromAET(); if (hasEdge) { edge = aetBuffer[workBuffer[GWAETStart]]; storeEdgeStateFrominto(edge, edgeOop); workBuffer[GWState] = GEStateWaitingChange; } else { workBuffer[GWState] = GEStateAddingFromGET; } } if (interpreterProxy->failed()) { return null; } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(2); interpreterProxy->pushBool(!hasEdge); if (doProfileStats) { workBuffer[GWCountNextAETEntry] = ((workBuffer[GWCountNextAETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextAETEntry] = ((workBuffer[GWTimeNextAETEntry]) + value); } } /* Note: No need to load bitBlt but must load spanBuffer */ EXPORT(sqInt) primitiveNextFillEntry(void) { sqInt failureCode; sqInt fillOop; sqInt hasFill; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateScanningAET))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(((failureCode = loadSpanBufferFrom(interpreterProxy->fetchPointerofObject(BESpanIndex, engine)))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } if (!(loadFormsFrom(interpreterProxy->fetchPointerofObject(BEFormsIndex, engine)))) { return interpreterProxy->primitiveFailFor(GEFFormLoadFailed); } if (!((workBuffer[GWClearSpanBuffer]) == 0)) { if (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == 0) { clearSpanBuffer(); } workBuffer[GWClearSpanBuffer] = 0; } fillOop = interpreterProxy->stackObjectValue(0); hasFill = findNextExternalFillFromAET(); if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (hasFill) { storeFillStateInto(fillOop); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } if (hasFill) { workBuffer[GWState] = GEStateWaitingForFill; } else { /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); workBuffer[GWSpanEndAA] = 0; workBuffer[GWState] = GEStateBlitBuffer; } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(2); interpreterProxy->pushBool(!hasFill); if (doProfileStats) { workBuffer[GWCountNextFillEntry] = ((workBuffer[GWCountNextFillEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextFillEntry] = ((workBuffer[GWTimeNextFillEntry]) + value); } } /* Note: No need to load either bitBlt or spanBuffer */ EXPORT(sqInt) primitiveNextGlobalEdgeEntry(void) { sqInt edge; sqInt edgeOop; sqInt failureCode; sqInt hasEdge; sqInt value; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateAddingFromGET))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } edgeOop = interpreterProxy->stackObjectValue(0); hasEdge = findNextExternalEntryFromGET(); if (hasEdge) { edge = getBuffer[workBuffer[GWGETStart]]; storeEdgeStateFrominto(edge, edgeOop); workBuffer[GWGETStart] = ((workBuffer[GWGETStart]) + 1); } if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFWrongEdge); } if (hasEdge) { workBuffer[GWState] = GEStateWaitingForEdge; } else { workBuffer[GWState] = GEStateScanningAET; workBuffer[GWClearSpanBuffer] = 1; workBuffer[GWAETStart] = 0; /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(2); interpreterProxy->pushBool(!hasEdge); if (doProfileStats) { workBuffer[GWCountNextGETEntry] = ((workBuffer[GWCountNextGETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextGETEntry] = ((workBuffer[GWTimeNextGETEntry]) + value); } } EXPORT(sqInt) primitiveRegisterExternalEdge(void) { sqInt edge; sqInt failureCode; sqInt index; sqInt initialX; sqInt initialY; sqInt initialZ; sqInt leftFillIndex; sqInt rightFillIndex; sqInt value; sqInt value1; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(6), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } rightFillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); leftFillIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); initialZ = interpreterProxy->stackIntegerValue(2); initialY = interpreterProxy->stackIntegerValue(3); initialX = interpreterProxy->stackIntegerValue(4); index = interpreterProxy->stackIntegerValue(5); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(allocateObjEntry(GEBaseEdgeSize))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } if (!((isFillOkay(leftFillIndex)) && (isFillOkay(rightFillIndex)))) { return interpreterProxy->primitiveFailFor(GEFWrongFill); } edge = objUsed; /* Install type and length */ objUsed = edge + GEBaseEdgeSize; objBuffer[edge + GEObjectType] = GEPrimitiveEdge; objBuffer[edge + GEObjectLength] = GEBaseEdgeSize; objBuffer[edge + GEObjectIndex] = index; objBuffer[edge + GEXValue] = initialX; objBuffer[edge + GEYValue] = initialY; objBuffer[edge + GEZValue] = initialZ; /* begin edgeLeftFillOf:put: */ value = transformColor(leftFillIndex); objBuffer[edge + GEFillIndexLeft] = value; /* begin edgeRightFillOf:put: */ value1 = transformColor(rightFillIndex); objBuffer[edge + GEFillIndexRight] = value1; if (engineStopped) { return interpreterProxy->primitiveFailFor(GEFEngineStopped); } if (!(interpreterProxy->failed())) { /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(6); } } EXPORT(sqInt) primitiveRegisterExternalFill(void) { sqInt failureCode; sqInt fill; sqInt index; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } index = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } fill = 0; while (fill == 0) { if (!(allocateObjEntry(GEBaseEdgeSize))) { return interpreterProxy->primitiveFailFor(GEFWorkTooBig); } fill = objUsed; /* Install type and length */ objUsed = fill + GEBaseFillSize; objBuffer[fill + GEObjectType] = GEPrimitiveFill; objBuffer[fill + GEObjectLength] = GEBaseFillSize; objBuffer[fill + GEObjectIndex] = index; } if (!(interpreterProxy->failed())) { /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(2); interpreterProxy->pushInteger(fill); } } /* Start/Proceed rendering the entire image */ EXPORT(sqInt) primitiveRenderImage(void) { sqInt failCode; if (!(((failCode = loadRenderingState())) == 0)) { return interpreterProxy->primitiveFailFor(failCode); } proceedRenderingScanline(); if (engineStopped) { return storeRenderingState(); } proceedRenderingImage(); storeRenderingState(); } /* Start rendering the entire image */ EXPORT(sqInt) primitiveRenderScanline(void) { sqInt failCode; if (!(((failCode = loadRenderingState())) == 0)) { return interpreterProxy->primitiveFailFor(failCode); } proceedRenderingScanline(); storeRenderingState(); } EXPORT(sqInt) primitiveSetAALevel(void) { sqInt failureCode; sqInt level; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } level = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } setAALevel(level); /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } /* Primitive. Set the BitBlt plugin to use. */ EXPORT(sqInt) primitiveSetBitBltPlugin(void) { sqInt i; sqInt length; sqInt needReload; sqInt pluginName; char *ptr; /* Must be string to work */ pluginName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(pluginName))) { return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(pluginName); if (length >= 256) { return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(pluginName); needReload = 0; for (i = 0; i <= (length - 1); i += 1) { if (!((bbPluginName[i]) == (ptr[i]))) { bbPluginName[i] = (ptr[i]); needReload = 1; } } if (!((bbPluginName[length]) == 0)) { bbPluginName[length] = 0; needReload = 1; } if (needReload) { if (!(initialiseModule())) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveSetClipRect(void) { sqInt failureCode; sqInt rectOop; sqInt value; sqInt value1; sqInt value2; sqInt value3; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } rectOop = interpreterProxy->stackObjectValue(0); if (!((!(interpreterProxy->failed())) && ((interpreterProxy->isPointers(rectOop)) && ((interpreterProxy->slotSizeOf(rectOop)) >= 2)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } loadPointfrom(point1Get(), interpreterProxy->fetchPointerofObject(0, rectOop)); loadPointfrom(point2Get(), interpreterProxy->fetchPointerofObject(1, rectOop)); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } /* begin clipMinXPut: */ value = (point1Get())[0]; workBuffer[GWClipMinX] = value; /* begin clipMinYPut: */ value1 = (point1Get())[1]; workBuffer[GWClipMinY] = value1; /* begin clipMaxXPut: */ value2 = (point2Get())[0]; workBuffer[GWClipMaxX] = value2; /* begin clipMaxYPut: */ value3 = (point2Get())[1]; workBuffer[GWClipMaxY] = value3; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } EXPORT(sqInt) primitiveSetColorTransform(void) { sqInt failureCode; sqInt okay; float *transform; sqInt transformOop; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } transformOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } /* begin loadColorTransformFrom: */ /* begin colorTransform */ transform = ((float *) (workBuffer + GWColorTransform)); workBuffer[GWHasColorTransform] = 0; okay = loadTransformFromintolength(transformOop, transform, 8); if (!(okay)) { goto l1; } workBuffer[GWHasColorTransform] = 1; transform[1] = ((transform[1]) * (((float) 256.0))); transform[3] = ((transform[3]) * (((float) 256.0))); transform[5] = ((transform[5]) * (((float) 256.0))); transform[7] = ((transform[7]) * (((float) 256.0))); l1: /* end loadColorTransformFrom: */; if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(GEFEntityLoadFailed); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } EXPORT(sqInt) primitiveSetDepth(void) { sqInt depth; sqInt failureCode; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } depth = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } workBuffer[GWCurrentZ] = depth; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } EXPORT(sqInt) primitiveSetEdgeTransform(void) { sqInt failureCode; sqInt transformOop; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } transformOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } loadEdgeTransformFrom(transformOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } EXPORT(sqInt) primitiveSetOffset(void) { sqInt failureCode; sqInt pointOop; sqInt value; sqInt value1; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); } if (!(((failureCode = quickLoadEngineFromrequiredState(interpreterProxy->stackValue(1), GEStateUnlocked))) == 0)) { return interpreterProxy->primitiveFailFor(failureCode); } pointOop = interpreterProxy->stackValue(0); if (!((interpreterProxy->fetchClassOf(pointOop)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } loadPointfrom(point1Get(), pointOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } /* begin destOffsetXPut: */ value = (point1Get())[0]; workBuffer[GWDestOffsetX] = value; /* begin destOffsetYPut: */ value1 = (point1Get())[1]; workBuffer[GWDestOffsetY] = value1; /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(1); } /* This is the main rendering entry */ static sqInt proceedRenderingImage(void) { sqInt external; sqInt value; sqInt value1; sqInt value2; sqInt value3; while (!((workBuffer[GWState]) == GEStateCompleted)) { if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } external = findNextExternalEntryFromGET(); if (doProfileStats) { workBuffer[GWCountNextGETEntry] = ((workBuffer[GWCountNextGETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextGETEntry] = ((workBuffer[GWTimeNextGETEntry]) + value); } if (engineStopped) { return workBuffer[GWState] = GEStateAddingFromGET; } if (external) { workBuffer[GWState] = GEStateWaitingForEdge; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorGETEntry; engineStopped = 1; return null; } workBuffer[GWAETStart] = 0; /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); workBuffer[GWClearSpanBuffer] = 1; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (((workBuffer[GWClearSpanBuffer]) != 0) && (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == 0)) { clearSpanBuffer(); } workBuffer[GWClearSpanBuffer] = 0; external = findNextExternalFillFromAET(); if (doProfileStats) { workBuffer[GWCountNextFillEntry] = ((workBuffer[GWCountNextFillEntry]) + 1); /* begin incrementStat:by: */ value1 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextFillEntry] = ((workBuffer[GWTimeNextFillEntry]) + value1); } if (engineStopped) { return workBuffer[GWState] = GEStateScanningAET; } if (external) { workBuffer[GWState] = GEStateWaitingForFill; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorFillEntry; engineStopped = 1; return null; } /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); workBuffer[GWSpanEndAA] = 0; if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == (workBuffer[GWAAScanMask])) { displaySpanBufferAt(workBuffer[GWCurrentY]); postDisplayAction(); } if (doProfileStats) { workBuffer[GWCountDisplaySpan] = ((workBuffer[GWCountDisplaySpan]) + 1); /* begin incrementStat:by: */ value2 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeDisplaySpan] = ((workBuffer[GWTimeDisplaySpan]) + value2); } if (engineStopped) { return workBuffer[GWState] = GEStateBlitBuffer; } if ((workBuffer[GWState]) == GEStateCompleted) { return 0; } workBuffer[GWAETStart] = 0; workBuffer[GWCurrentY] = ((workBuffer[GWCurrentY]) + 1); if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } external = findNextExternalUpdateFromAET(); if (doProfileStats) { workBuffer[GWCountNextAETEntry] = ((workBuffer[GWCountNextAETEntry]) + 1); /* begin incrementStat:by: */ value3 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextAETEntry] = ((workBuffer[GWTimeNextAETEntry]) + value3); } if (engineStopped) { return workBuffer[GWState] = GEStateUpdateEdges; } if (external) { workBuffer[GWState] = GEStateWaitingChange; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorAETEntry; engineStopped = 1; return null; } } } /* Proceed rendering the current scan line. This method may be called after some Smalltalk code has been executed inbetween. */ /* This is the main rendering entry */ static sqInt proceedRenderingScanline(void) { sqInt external; sqInt state; sqInt value; sqInt value1; sqInt value2; sqInt value3; state = workBuffer[GWState]; if (state == GEStateUnlocked) { initializeGETProcessing(); if (engineStopped) { return 0; } state = GEStateAddingFromGET; } if (state == GEStateAddingFromGET) { if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } external = findNextExternalEntryFromGET(); if (doProfileStats) { workBuffer[GWCountNextGETEntry] = ((workBuffer[GWCountNextGETEntry]) + 1); /* begin incrementStat:by: */ value = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextGETEntry] = ((workBuffer[GWTimeNextGETEntry]) + value); } if (engineStopped) { return workBuffer[GWState] = GEStateAddingFromGET; } if (external) { workBuffer[GWState] = GEStateWaitingForEdge; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorGETEntry; engineStopped = 1; return null; } workBuffer[GWAETStart] = 0; /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); workBuffer[GWClearSpanBuffer] = 1; state = GEStateScanningAET; } if (state == GEStateScanningAET) { if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (((workBuffer[GWClearSpanBuffer]) != 0) && (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == 0)) { clearSpanBuffer(); } workBuffer[GWClearSpanBuffer] = 0; external = findNextExternalFillFromAET(); if (doProfileStats) { workBuffer[GWCountNextFillEntry] = ((workBuffer[GWCountNextFillEntry]) + 1); /* begin incrementStat:by: */ value1 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextFillEntry] = ((workBuffer[GWTimeNextFillEntry]) + value1); } if (engineStopped) { return workBuffer[GWState] = GEStateScanningAET; } if (external) { workBuffer[GWState] = GEStateWaitingForFill; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorFillEntry; engineStopped = 1; return null; } state = GEStateBlitBuffer; /* begin wbStackClear */ workBuffer[GWBufferTop] = (workBuffer[GWSize]); workBuffer[GWSpanEndAA] = 0; } if (state == GEStateBlitBuffer) { if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } if (((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask])) == (workBuffer[GWAAScanMask])) { displaySpanBufferAt(workBuffer[GWCurrentY]); postDisplayAction(); } if (doProfileStats) { workBuffer[GWCountDisplaySpan] = ((workBuffer[GWCountDisplaySpan]) + 1); /* begin incrementStat:by: */ value2 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeDisplaySpan] = ((workBuffer[GWTimeDisplaySpan]) + value2); } if (engineStopped) { return workBuffer[GWState] = GEStateBlitBuffer; } if ((workBuffer[GWState]) == GEStateCompleted) { return 0; } state = GEStateUpdateEdges; workBuffer[GWAETStart] = 0; workBuffer[GWCurrentY] = ((workBuffer[GWCurrentY]) + 1); } if (state == GEStateUpdateEdges) { if (doProfileStats) { geProfileTime = interpreterProxy->ioMicroMSecs(); } external = findNextExternalUpdateFromAET(); if (doProfileStats) { workBuffer[GWCountNextAETEntry] = ((workBuffer[GWCountNextAETEntry]) + 1); /* begin incrementStat:by: */ value3 = (interpreterProxy->ioMicroMSecs()) - geProfileTime; workBuffer[GWTimeNextAETEntry] = ((workBuffer[GWTimeNextAETEntry]) + value3); } if (engineStopped) { return workBuffer[GWState] = GEStateUpdateEdges; } if (external) { workBuffer[GWState] = GEStateWaitingChange; /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorAETEntry; engineStopped = 1; return null; } workBuffer[GWState] = GEStateAddingFromGET; } } /* Load the minimal required state from the engineOop, e.g., just the work buffer. Answer 0 on success or non-zero a failure code on failure */ static sqInt quickLoadEngineFrom(sqInt engineOop) { sqInt failCode; if (interpreterProxy->failed()) { return GEFAlreadyFailed; } if ((engineOop & 1)) { return GEFEngineIsInteger; } if (!(interpreterProxy->isPointers(engineOop))) { return GEFEngineIsWords; } if ((interpreterProxy->slotSizeOf(engineOop)) < BEBalloonEngineSize) { return GEFEngineTooSmall; } engine = engineOop; if (!(((failCode = loadWorkBufferFrom(interpreterProxy->fetchPointerofObject(BEWorkBufferIndex, engineOop)))) == 0)) { return failCode; } workBuffer[GWStopReason] = 0; objUsed = workBuffer[GWObjUsed]; engineStopped = 0; return 0; } static sqInt quickLoadEngineFromrequiredState(sqInt oop, sqInt requiredState) { sqInt failureCode; if (!(((failureCode = quickLoadEngineFrom(oop))) == 0)) { return failureCode; } if ((workBuffer[GWState]) == requiredState) { return 0; } workBuffer[GWStopReason] = GErrorBadState; return GEFWrongState; } static sqInt quickLoadEngineFromrequiredStateor(sqInt oop, sqInt requiredState, sqInt alternativeState) { sqInt failureCode; if (!(((failureCode = quickLoadEngineFrom(oop))) == 0)) { return failureCode; } if ((workBuffer[GWState]) == requiredState) { return 0; } if ((workBuffer[GWState]) == alternativeState) { return 0; } workBuffer[GWStopReason] = GErrorBadState; return GEFWrongState; } /* Remove any top fills if they have become invalid. */ static sqInt quickRemoveInvalidFillsAt(sqInt leftX) { if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { return null; } while ((topRightX()) <= leftX) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { return null; } } } /* Sort elements i through j of self to be nondescending according to sortBlock. */ /* Note: The original loop has been heavily re-written for C translation */ static sqInt quickSortGlobalEdgeTablefromto(int *array, sqInt i, sqInt j) { sqInt again; sqInt before; sqInt di; sqInt dij; sqInt dj; sqInt ij; sqInt k; sqInt l; sqInt n; sqInt tmp; sqInt tt; if (((n = (j + 1) - i)) <= 1) { return 0; } di = array[i]; dj = array[j]; /* i.e., should di precede dj? */ before = getSortsbefore(di, dj); if (!(before)) { tmp = array[i]; array[i] = (array[j]); array[j] = tmp; tt = di; di = dj; dj = tt; } if (n <= 2) { return 0; } /* ij is the midpoint of i and j. */ ij = ((sqInt) (i + j) >> 1); /* Sort di,dij,dj. Make dij be their median. */ dij = array[ij]; /* i.e. should di precede dij? */ before = getSortsbefore(di, dij); if (before) { /* i.e., should dij precede dj? */ before = getSortsbefore(dij, dj); if (!(before)) { /* i.e., should dij precede dj? */ tmp = array[j]; array[j] = (array[ij]); array[ij] = tmp; dij = dj; } } else { /* i.e. di should come after dij */ tmp = array[i]; array[i] = (array[ij]); array[ij] = tmp; dij = di; } if (n <= 3) { return 0; } k = i; l = j; again = 1; while (again) { before = 1; while (before) { if (k <= ((l -= 1))) { tmp = array[l]; before = getSortsbefore(dij, tmp); } else { before = 0; } } before = 1; while (before) { if (((k += 1)) <= l) { tmp = array[k]; before = getSortsbefore(tmp, dij); } else { before = 0; } } again = k <= l; if (again) { tmp = array[k]; array[k] = (array[l]); array[l] = tmp; } } quickSortGlobalEdgeTablefromto(array, i, l); quickSortGlobalEdgeTablefromto(array, k, j); } static sqInt removeFirstAETEntry(void) { sqInt index; index = workBuffer[GWAETStart]; workBuffer[GWAETUsed] = ((workBuffer[GWAETUsed]) - 1); while (index < (workBuffer[GWAETUsed])) { aetBuffer[index] = (aetBuffer[index + 1]); index += 1; } } static sqInt repeatValuemax(sqInt delta, sqInt maxValue) { sqInt newDelta; newDelta = delta; while (newDelta < 0) { newDelta += maxValue; } while (newDelta >= maxValue) { newDelta -= maxValue; } return newDelta; } static sqInt resetGraphicsEngineStats(void) { workBuffer[GWTimeInitializing] = 0; workBuffer[GWTimeFinishTest] = 0; workBuffer[GWTimeNextGETEntry] = 0; workBuffer[GWTimeAddAETEntry] = 0; workBuffer[GWTimeNextFillEntry] = 0; workBuffer[GWTimeMergeFill] = 0; workBuffer[GWTimeDisplaySpan] = 0; workBuffer[GWTimeNextAETEntry] = 0; workBuffer[GWTimeChangeAETEntry] = 0; workBuffer[GWCountInitializing] = 0; workBuffer[GWCountFinishTest] = 0; workBuffer[GWCountNextGETEntry] = 0; workBuffer[GWCountAddAETEntry] = 0; workBuffer[GWCountNextFillEntry] = 0; workBuffer[GWCountMergeFill] = 0; workBuffer[GWCountDisplaySpan] = 0; workBuffer[GWCountNextAETEntry] = 0; workBuffer[GWCountChangeAETEntry] = 0; workBuffer[GWBezierMonotonSubdivisions] = 0; workBuffer[GWBezierHeightSubdivisions] = 0; workBuffer[GWBezierOverflowSubdivisions] = 0; workBuffer[GWBezierLineConversions] = 0; } static sqInt resortFirstAETEntry(void) { sqInt edge; sqInt leftEdge; sqInt xValue; if ((workBuffer[GWAETStart]) == 0) { return null; } edge = aetBuffer[workBuffer[GWAETStart]]; xValue = objBuffer[edge + GEXValue]; leftEdge = aetBuffer[(workBuffer[GWAETStart]) - 1]; if ((objBuffer[leftEdge + GEXValue]) <= xValue) { return null; } moveAETEntryFromedgex(workBuffer[GWAETStart], edge, xValue); } static sqInt returnWideBezierFill(void) { return dispatchReturnValue = objBuffer[dispatchedValue + GBWideFill]; } static sqInt returnWideBezierWidth(void) { return dispatchReturnValue = objBuffer[dispatchedValue + GBWideWidth]; } /* Return the fill of the (wide) line - this method is called from a case. */ static sqInt returnWideLineFill(void) { return dispatchReturnValue = objBuffer[dispatchedValue + GLWideFill]; } /* Return the width of the (wide) line - this method is called from a case. */ static sqInt returnWideLineWidth(void) { return dispatchReturnValue = objBuffer[dispatchedValue + GLWideWidth]; } static int * rShiftTable(void) { static int theTable[17] = {0, 5, 4, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1}; return theTable; } /* Set the anti-aliasing level. Three levels are supported: 1 - No antialiasing 2 - 2x2 unweighted anti-aliasing 4 - 4x4 unweighted anti-aliasing. */ static sqInt setAALevel(sqInt level) { sqInt aaLevel; if (level >= 4) { aaLevel = 4; } if ((level >= 2) && (level < 4)) { aaLevel = 2; } if (level < 2) { aaLevel = 1; } workBuffer[GWAALevel] = aaLevel; if (aaLevel == 1) { workBuffer[GWAAShift] = 0; workBuffer[GWAAColorMask] = 4294967295UL; workBuffer[GWAAScanMask] = 0; } if (aaLevel == 2) { workBuffer[GWAAShift] = 1; workBuffer[GWAAColorMask] = 4244438268UL; workBuffer[GWAAScanMask] = 1; } if (aaLevel == 4) { workBuffer[GWAAShift] = 2; workBuffer[GWAAColorMask] = 4042322160UL; workBuffer[GWAAScanMask] = 3; } workBuffer[GWAAColorShift] = ((workBuffer[GWAAShift]) * 2); workBuffer[GWAAHalfPixel] = (workBuffer[GWAAShift]); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Return the run-length value from the given ShortRunArray. */ static sqInt shortRunLengthAtfrom(sqInt i, sqInt runArray) { return ((usqInt) ((((int *) runArray))[i]) >> 16); } /* Return the run-length value from the given ShortRunArray. Note: We don't need any coercion to short/int here, since we deal basically only with unsigned values. */ static sqInt shortRunValueAtfrom(sqInt i, sqInt runArray) { return ((((int *) runArray))[i]) & 65535; } static sqInt showFilldepthrightX(sqInt fillIndex, sqInt depth, sqInt rightX) { if (!(wbStackPush(3))) { return null; } workBuffer[(workBuffer[GWBufferTop]) + 0] = fillIndex; workBuffer[(workBuffer[GWBufferTop]) + (0 + 1)] = depth; workBuffer[(workBuffer[GWBufferTop]) + (0 + 2)] = rightX; if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 3) { return null; } if (fillSortsbefore(0, ((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)) { workBuffer[(workBuffer[GWBufferTop]) + 0] = (workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]); workBuffer[(workBuffer[GWBufferTop]) + (0 + 1)] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)]); workBuffer[(workBuffer[GWBufferTop]) + (0 + 2)] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]); workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)] = fillIndex; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)] = depth; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)] = rightX; } } static int * smallSqrtTable(void) { static int theTable[32] = {0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6}; return theTable; } /* Sort the entire global edge table */ static sqInt sortGlobalEdgeTable(void) { quickSortGlobalEdgeTablefromto(getBuffer, 0, (workBuffer[GWGETUsed]) - 1); } static sqInt spanEndAAGet(void) { return workBuffer[GWSpanEndAA]; } static sqInt spanEndAAPut(sqInt value) { return workBuffer[GWSpanEndAA] = value; } static sqInt spanEndGet(void) { return workBuffer[GWSpanEnd]; } static sqInt spanEndPut(sqInt value) { return workBuffer[GWSpanEnd] = value; } static sqInt spanSizeGet(void) { return workBuffer[GWSpanSize]; } static sqInt spanSizePut(sqInt value) { return workBuffer[GWSpanSize] = value; } static sqInt spanStartGet(void) { return workBuffer[GWSpanStart]; } static sqInt spanStartPut(sqInt value) { return workBuffer[GWSpanStart] = value; } static sqInt squaredLengthOfwith(sqInt deltaX, sqInt deltaY) { return (deltaX * deltaX) + (deltaY * deltaY); } static sqInt stackFillDepth(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + (index + 1)]; } static sqInt stackFillDepthput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + (index + 1)] = value; } static sqInt stackFillEntryLength(void) { return 3; } static sqInt stackFillRightX(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + (index + 2)]; } static sqInt stackFillRightXput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + (index + 2)] = value; } static sqInt stackFillSize(void) { return (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); } static sqInt stackFillValue(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + index]; } static sqInt stackFillValueput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + index] = value; } static sqInt stateGet(void) { return workBuffer[GWState]; } static sqInt statePut(sqInt value) { return workBuffer[GWState] = value; } /* Initialize the current entry in the GET by stepping to the current scan line */ static sqInt stepToFirstBezier(void) { return stepToFirstBezierInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); } /* Initialize the bezier at yValue. TODO: Check if reducing maxSteps from 2*deltaY to deltaY brings a *significant* performance improvement. In theory this should make for double step performance but will cost in quality. Might be that the AA stuff will compensate for this - but I'm not really sure. */ static sqInt stepToFirstBezierInat(sqInt bezier, sqInt yValue) { sqInt deltaY; sqInt endX; sqInt endY; sqInt fwDDx; sqInt fwDDy; sqInt fwDx; sqInt fwDx1; sqInt fwDy; sqInt fwDy1; sqInt fwX1; sqInt fwX2; sqInt fwY1; sqInt fwY2; sqInt lastX; sqInt lastY; sqInt maxSteps; sqInt minY; sqInt scaledStepSize; sqInt squaredStepSize; sqInt startX; sqInt startY; int *updateData; sqInt updateData1; sqInt viaX; sqInt viaY; sqInt word1; sqInt word2; sqInt xValue; if ((!((((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0)) && (yValue >= (objBuffer[bezier + GBEndY]))) { return objBuffer[bezier + GENumLines] = 0; } startX = objBuffer[bezier + GEXValue]; startY = objBuffer[bezier + GEYValue]; viaX = objBuffer[bezier + GBViaX]; viaY = objBuffer[bezier + GBViaY]; endX = objBuffer[bezier + GBEndX]; endY = objBuffer[bezier + GBEndY]; /* Initialize integer forward differencing */ deltaY = endY - startY; fwX1 = (viaX - startX) * 2; fwX2 = (startX + endX) - (viaX * 2); fwY1 = (viaY - startY) * 2; fwY2 = (startY + endY) - (viaY * 2); maxSteps = deltaY * 2; if (maxSteps < 2) { maxSteps = 2; } scaledStepSize = 16777216 / maxSteps; /* begin absoluteSquared8Dot24: */ word1 = scaledStepSize & 65535; word2 = (((usqInt) scaledStepSize >> 16)) & 255; squaredStepSize = ((usqInt) (((((usqInt) (((unsigned) (word1 * word1))) >> 16)) + ((word1 * word2) * 2)) + (((usqInt) (word2 * word2) << 16))) >> 8); fwDx = fwX1 * scaledStepSize; fwDDx = (fwX2 * squaredStepSize) * 2; fwDx += ((sqInt) fwDDx >> 1); fwDy = fwY1 * scaledStepSize; fwDDy = (fwY2 * squaredStepSize) * 2; /* Store the values */ fwDy += ((sqInt) fwDDy >> 1); objBuffer[bezier + GENumLines] = deltaY; /* begin bezierUpdateDataOf: */ updateData = (objBuffer + bezier) + GBUpdateData; updateData[GBUpdateX] = (startX * 256); updateData[GBUpdateY] = (startY * 256); updateData[GBUpdateDX] = fwDx; updateData[GBUpdateDY] = fwDy; updateData[GBUpdateDDX] = fwDDx; updateData[GBUpdateDDY] = fwDDy; if (!(((startY = objBuffer[bezier + GEYValue])) == yValue)) { /* begin stepToNextBezierIn:at: */ /* begin stepToNextBezierForward:at: */ /* begin bezierUpdateDataOf: */ updateData1 = ((int *) ((objBuffer + bezier) + GBUpdateData)); lastX = (((int*) updateData1))[GBUpdateX]; lastY = (((int*) updateData1))[GBUpdateY]; fwDx1 = (((int*) updateData1))[GBUpdateDX]; fwDy1 = (((int*) updateData1))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY = yValue * 256; while ((minY > lastY) && (fwDy1 >= 0)) { lastX += ((sqInt) (fwDx1 + 32768) >> 16); lastY += ((sqInt) (fwDy1 + 32768) >> 16); fwDx1 += (((int*) updateData1))[GBUpdateDDX]; fwDy1 += (((int*) updateData1))[GBUpdateDDY]; } (((int*) updateData1))[GBUpdateX] = lastX; (((int*) updateData1))[GBUpdateY] = lastY; (((int*) updateData1))[GBUpdateDX] = fwDx1; (((int*) updateData1))[GBUpdateDY] = fwDy1; xValue = ((sqInt) lastX >> 8); objBuffer[bezier + GEXValue] = xValue; objBuffer[bezier + GENumLines] = (deltaY - (yValue - startY)); } } /* Initialize the current entry in the GET by stepping to the current scan line */ static sqInt stepToFirstLine(void) { return stepToFirstLineInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); } /* Initialize the line at yValue */ static sqInt stepToFirstLineInat(sqInt line, sqInt yValue) { sqInt deltaX; sqInt deltaY; sqInt err; sqInt error; sqInt errorAdjUp; sqInt i; sqInt startY; sqInt widthX; sqInt x; sqInt xDir; sqInt xInc; if ((!((((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) != 0)) && (yValue >= (objBuffer[line + GLEndY]))) { return objBuffer[line + GENumLines] = 0; } deltaX = (objBuffer[line + GLEndX]) - (objBuffer[line + GEXValue]); /* Check if edge goes left to right */ deltaY = (objBuffer[line + GLEndY]) - (objBuffer[line + GEYValue]); if (deltaX >= 0) { xDir = 1; widthX = deltaX; error = 0; } else { xDir = -1; widthX = 0 - deltaX; error = 1 - deltaY; } if (deltaY == 0) { /* No error for horizontal edges */ error = 0; /* Encodes width and direction */ xInc = deltaX; errorAdjUp = 0; } else { if (deltaY > widthX) { /* Check if edge is y-major */ /* Note: The '>' instead of '>=' could be important here... */ xInc = 0; errorAdjUp = widthX; } else { xInc = (widthX / deltaY) * xDir; errorAdjUp = widthX % deltaY; } } objBuffer[line + GENumLines] = deltaY; objBuffer[line + GLXDirection] = xDir; objBuffer[line + GLXIncrement] = xInc; objBuffer[line + GLError] = error; objBuffer[line + GLErrorAdjUp] = errorAdjUp; objBuffer[line + GLErrorAdjDown] = deltaY; if (!(((startY = objBuffer[line + GEYValue])) == yValue)) { for (i = startY; i <= (yValue - 1); i += 1) { /* begin stepToNextLineIn:at: */ x = (objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement]); err = (objBuffer[line + GLError]) + (objBuffer[line + GLErrorAdjUp]); if (err > 0) { x += objBuffer[line + GLXDirection]; err -= objBuffer[line + GLErrorAdjDown]; } objBuffer[line + GLError] = err; objBuffer[line + GEXValue] = x; } objBuffer[line + GENumLines] = (deltaY - (yValue - startY)); } } /* Initialize the current entry in the GET by stepping to the current scan line */ static sqInt stepToFirstWideBezier(void) { return stepToFirstWideBezierInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); } /* Initialize the bezier at yValue */ static sqInt stepToFirstWideBezierInat(sqInt bezier, sqInt yValue) { sqInt endX; sqInt i; sqInt lineOffset; sqInt lineWidth; sqInt nLines; sqInt startY; sqInt xDir; sqInt yEntry; sqInt yExit; /* Get some values */ lineWidth = objBuffer[bezier + GBWideExtent]; /* Compute the incremental values of the bezier */ lineOffset = ((sqInt) lineWidth >> 1); endX = objBuffer[bezier + GBEndX]; startY = objBuffer[bezier + GEYValue]; stepToFirstBezierInat(bezier, startY); /* Copy the incremental update data */ nLines = objBuffer[bezier + GENumLines]; for (i = 0; i <= 5; i += 1) { (wideBezierUpdateDataOf(bezier))[i] = ((bezierUpdateDataOf(bezier))[i]); } xDir = (bezierUpdateDataOf(bezier))[GBUpdateDX]; if (xDir == 0) { (bezierUpdateDataOf(bezier))[GBUpdateDDX]; } if (xDir >= 0) { xDir = 1; } else { xDir = -1; } if (xDir < 0) { adjustWideBezierLeftwidthoffsetendX(bezier, lineWidth, lineOffset, endX); } else { adjustWideBezierRightwidthoffsetendX(bezier, lineWidth, lineOffset, endX); } if (nLines == 0) { (bezierUpdateDataOf(bezier))[GBUpdateX] = ((objBuffer[bezier + GBFinalX]) * 256); } objBuffer[bezier + GENumLines] = (nLines + lineWidth); /* turned on at lineOffset */ yEntry = 0; /* turned off at zero */ yExit = (0 - nLines) - lineOffset; objBuffer[bezier + GBWideEntry] = yEntry; objBuffer[bezier + GBWideExit] = yExit; if ((yEntry >= lineOffset) && (yExit < 0)) { objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } else { objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } computeFinalWideBezierValueswidth(bezier, lineWidth); if (!(startY == yValue)) { for (i = startY; i <= (yValue - 1); i += 1) { stepToNextWideBezierInat(bezier, i); } objBuffer[bezier + GENumLines] = ((objBuffer[bezier + GENumLines]) - (yValue - startY)); } } /* Initialize the current entry in the GET by stepping to the current scan line */ static sqInt stepToFirstWideLine(void) { return stepToFirstWideLineInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); } /* Initialize the wide line at yValue. */ static sqInt stepToFirstWideLineInat(sqInt line, sqInt yValue) { sqInt err; sqInt i; sqInt lastX; sqInt lineOffset; sqInt lineOffset1; sqInt lineWidth; sqInt lineWidth1; sqInt nextX; sqInt nLines; sqInt startX; sqInt startY; sqInt x; sqInt xDir; sqInt yEntry; sqInt yEntry1; sqInt yExit; sqInt yExit1; /* Get some values */ lineWidth = objBuffer[line + GLWideExtent]; /* Compute the incremental values of the line */ lineOffset = ((sqInt) lineWidth >> 1); startX = objBuffer[line + GEXValue]; startY = objBuffer[line + GEYValue]; stepToFirstLineInat(line, startY); nLines = objBuffer[line + GENumLines]; /* Adjust the line to start at the correct X position */ xDir = objBuffer[line + GLXDirection]; objBuffer[line + GEXValue] = (startX - lineOffset); objBuffer[line + GENumLines] = (nLines + lineWidth); if (xDir > 0) { objBuffer[line + GLWideWidth] = ((objBuffer[line + GLXIncrement]) + lineWidth); } else { objBuffer[line + GLWideWidth] = (lineWidth - (objBuffer[line + GLXIncrement])); objBuffer[line + GEXValue] = ((objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement])); } /* turned on at lineOffset */ yEntry = 0; /* turned off at zero */ yExit = (0 - nLines) - lineOffset; objBuffer[line + GLWideEntry] = yEntry; objBuffer[line + GLWideExit] = yExit; if ((yEntry >= lineOffset) && (yExit < 0)) { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } else { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } if (!(startY == yValue)) { for (i = startY; i <= (yValue - 1); i += 1) { /* begin stepToNextWideLineIn:at: */ /* Adjust entry/exit values */ yEntry1 = (objBuffer[line + GLWideEntry]) + 1; yExit1 = (objBuffer[line + GLWideExit]) + 1; objBuffer[line + GLWideEntry] = yEntry1; objBuffer[line + GLWideExit] = yExit1; lineWidth1 = objBuffer[line + GLWideExtent]; lineOffset1 = ((sqInt) lineWidth1 >> 1); if (yEntry1 >= lineOffset1) { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } if (yExit1 >= 0) { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } lastX = objBuffer[line + GEXValue]; /* begin stepToNextLineIn:at: */ x = (objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement]); err = (objBuffer[line + GLError]) + (objBuffer[line + GLErrorAdjUp]); if (err > 0) { x += objBuffer[line + GLXDirection]; err -= objBuffer[line + GLErrorAdjDown]; } objBuffer[line + GLError] = err; objBuffer[line + GEXValue] = x; /* Check for special start/end adjustments */ nextX = objBuffer[line + GEXValue]; if ((yEntry1 <= lineWidth1) || ((yExit1 + lineOffset1) >= 0)) { adjustWideLineafterSteppingFromto(line, lastX, nextX); } } objBuffer[line + GENumLines] = ((objBuffer[line + GENumLines]) - (yValue - startY)); } } /* Process the current entry in the AET by stepping to the next scan line */ static sqInt stepToNextBezier(void) { sqInt fwDx; sqInt fwDy; sqInt lastX; sqInt lastY; sqInt minY; sqInt updateData; sqInt xValue; /* begin stepToNextBezierIn:at: */ /* begin stepToNextBezierForward:at: */ /* begin bezierUpdateDataOf: */ updateData = ((int *) ((objBuffer + (aetBuffer[workBuffer[GWAETStart]])) + GBUpdateData)); lastX = (((int*) updateData))[GBUpdateX]; lastY = (((int*) updateData))[GBUpdateY]; fwDx = (((int*) updateData))[GBUpdateDX]; fwDy = (((int*) updateData))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY = (workBuffer[GWCurrentY]) * 256; while ((minY > lastY) && (fwDy >= 0)) { lastX += ((sqInt) (fwDx + 32768) >> 16); lastY += ((sqInt) (fwDy + 32768) >> 16); fwDx += (((int*) updateData))[GBUpdateDDX]; fwDy += (((int*) updateData))[GBUpdateDDY]; } (((int*) updateData))[GBUpdateX] = lastX; (((int*) updateData))[GBUpdateY] = lastY; (((int*) updateData))[GBUpdateDX] = fwDx; (((int*) updateData))[GBUpdateDY] = fwDy; xValue = ((sqInt) lastX >> 8); objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue] = xValue; return null; } /* Incrementally step to the next scan line in the given bezier update data. Note: This method has been written so that inlining works, e.g., not declaring updateData as 'int*' but casting it on every use. */ static sqInt stepToNextBezierForwardat(sqInt updateData, sqInt yValue) { sqInt fwDx; sqInt fwDy; sqInt lastX; sqInt lastY; sqInt minY; lastX = (((int*) updateData))[GBUpdateX]; lastY = (((int*) updateData))[GBUpdateY]; fwDx = (((int*) updateData))[GBUpdateDX]; fwDy = (((int*) updateData))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY = yValue * 256; while ((minY > lastY) && (fwDy >= 0)) { lastX += ((sqInt) (fwDx + 32768) >> 16); lastY += ((sqInt) (fwDy + 32768) >> 16); fwDx += (((int*) updateData))[GBUpdateDDX]; fwDy += (((int*) updateData))[GBUpdateDDY]; } (((int*) updateData))[GBUpdateX] = lastX; (((int*) updateData))[GBUpdateY] = lastY; (((int*) updateData))[GBUpdateDX] = fwDx; (((int*) updateData))[GBUpdateDY] = fwDy; return ((sqInt) lastX >> 8); } /* Incrementally step to the next scan line in the given bezier */ static sqInt stepToNextBezierInat(sqInt bezier, sqInt yValue) { sqInt fwDx; sqInt fwDy; sqInt lastX; sqInt lastY; sqInt minY; sqInt updateData; sqInt xValue; /* begin stepToNextBezierForward:at: */ /* begin bezierUpdateDataOf: */ updateData = ((int *) ((objBuffer + bezier) + GBUpdateData)); lastX = (((int*) updateData))[GBUpdateX]; lastY = (((int*) updateData))[GBUpdateY]; fwDx = (((int*) updateData))[GBUpdateDX]; fwDy = (((int*) updateData))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY = yValue * 256; while ((minY > lastY) && (fwDy >= 0)) { lastX += ((sqInt) (fwDx + 32768) >> 16); lastY += ((sqInt) (fwDy + 32768) >> 16); fwDx += (((int*) updateData))[GBUpdateDDX]; fwDy += (((int*) updateData))[GBUpdateDDY]; } (((int*) updateData))[GBUpdateX] = lastX; (((int*) updateData))[GBUpdateY] = lastY; (((int*) updateData))[GBUpdateDX] = fwDx; (((int*) updateData))[GBUpdateDY] = fwDy; xValue = ((sqInt) lastX >> 8); objBuffer[bezier + GEXValue] = xValue; } /* Process the current entry in the AET by stepping to the next scan line */ static sqInt stepToNextLine(void) { sqInt err; sqInt x; /* begin stepToNextLineIn:at: */ x = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue]) + (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLXIncrement]); err = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLError]) + (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLErrorAdjUp]); if (err > 0) { x += objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLXDirection]; err -= objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLErrorAdjDown]; } objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLError] = err; objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue] = x; return null; } /* Incrementally step to the next scan line in the given line */ static sqInt stepToNextLineInat(sqInt line, sqInt yValue) { sqInt err; sqInt x; x = (objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement]); err = (objBuffer[line + GLError]) + (objBuffer[line + GLErrorAdjUp]); if (err > 0) { x += objBuffer[line + GLXDirection]; err -= objBuffer[line + GLErrorAdjDown]; } objBuffer[line + GLError] = err; objBuffer[line + GEXValue] = x; } /* Initialize the current entry in the GET by stepping to the current scan line */ static sqInt stepToNextWideBezier(void) { stepToNextWideBezierInat(aetBuffer[workBuffer[GWAETStart]], workBuffer[GWCurrentY]); } /* Incrementally step to the next scan line in the given wide bezier */ static sqInt stepToNextWideBezierInat(sqInt bezier, sqInt yValue) { sqInt fwDx; sqInt fwDx1; sqInt fwDy; sqInt fwDy1; sqInt lastX; sqInt lastX1; sqInt lastY; sqInt lastY1; sqInt lineOffset; sqInt lineWidth; sqInt minY; sqInt minY1; sqInt updateData; sqInt updateData1; sqInt yEntry; sqInt yExit; /* Don't inline this */ lineWidth = objBuffer[bezier + GBWideExtent]; lineOffset = ((sqInt) lineWidth >> 1); yEntry = (objBuffer[bezier + GBWideEntry]) + 1; yExit = (objBuffer[bezier + GBWideExit]) + 1; objBuffer[bezier + GBWideEntry] = yEntry; objBuffer[bezier + GBWideExit] = yExit; if (yEntry >= lineOffset) { objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } if (yExit >= 0) { objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } if ((yExit + lineOffset) < 0) { /* begin stepToNextBezierForward:at: */ /* begin bezierUpdateDataOf: */ updateData = ((int *) ((objBuffer + bezier) + GBUpdateData)); lastX = (((int*) updateData))[GBUpdateX]; lastY = (((int*) updateData))[GBUpdateY]; fwDx = (((int*) updateData))[GBUpdateDX]; fwDy = (((int*) updateData))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY = yValue * 256; while ((minY > lastY) && (fwDy >= 0)) { lastX += ((sqInt) (fwDx + 32768) >> 16); lastY += ((sqInt) (fwDy + 32768) >> 16); fwDx += (((int*) updateData))[GBUpdateDDX]; fwDy += (((int*) updateData))[GBUpdateDDY]; } (((int*) updateData))[GBUpdateX] = lastX; (((int*) updateData))[GBUpdateY] = lastY; (((int*) updateData))[GBUpdateDX] = fwDx; (((int*) updateData))[GBUpdateDY] = fwDy; ((sqInt) lastX >> 8); } else { (bezierUpdateDataOf(bezier))[GBUpdateX] = ((objBuffer[bezier + GBFinalX]) * 256); } /* begin stepToNextBezierForward:at: */ /* begin wideBezierUpdateDataOf: */ updateData1 = ((int *) ((objBuffer + bezier) + GBWideUpdateData)); lastX1 = (((int*) updateData1))[GBUpdateX]; lastY1 = (((int*) updateData1))[GBUpdateY]; fwDx1 = (((int*) updateData1))[GBUpdateDX]; fwDy1 = (((int*) updateData1))[GBUpdateDY]; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ minY1 = yValue * 256; while ((minY1 > lastY1) && (fwDy1 >= 0)) { lastX1 += ((sqInt) (fwDx1 + 32768) >> 16); lastY1 += ((sqInt) (fwDy1 + 32768) >> 16); fwDx1 += (((int*) updateData1))[GBUpdateDDX]; fwDy1 += (((int*) updateData1))[GBUpdateDDY]; } (((int*) updateData1))[GBUpdateX] = lastX1; (((int*) updateData1))[GBUpdateY] = lastY1; (((int*) updateData1))[GBUpdateDX] = fwDx1; (((int*) updateData1))[GBUpdateDY] = fwDy1; ((sqInt) lastX1 >> 8); computeFinalWideBezierValueswidth(bezier, lineWidth); } /* Process the current entry in the AET by stepping to the next scan line */ static sqInt stepToNextWideLine(void) { sqInt err; sqInt lastX; sqInt lineOffset; sqInt lineWidth; sqInt nextX; sqInt x; sqInt yEntry; sqInt yExit; /* begin stepToNextWideLineIn:at: */ /* Adjust entry/exit values */ yEntry = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLWideEntry]) + 1; yExit = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLWideExit]) + 1; objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLWideEntry] = yEntry; objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLWideExit] = yExit; lineWidth = objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLWideExtent]; lineOffset = ((sqInt) lineWidth >> 1); if (yEntry >= lineOffset) { objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEObjectType] = (((objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } if (yExit >= 0) { objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEObjectType] = (((objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } lastX = objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue]; /* begin stepToNextLineIn:at: */ x = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue]) + (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLXIncrement]); err = (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLError]) + (objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLErrorAdjUp]); if (err > 0) { x += objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLXDirection]; err -= objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLErrorAdjDown]; } objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GLError] = err; objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue] = x; /* Check for special start/end adjustments */ nextX = objBuffer[(aetBuffer[workBuffer[GWAETStart]]) + GEXValue]; if ((yEntry <= lineWidth) || ((yExit + lineOffset) >= 0)) { adjustWideLineafterSteppingFromto(aetBuffer[workBuffer[GWAETStart]], lastX, nextX); } return null; } /* Incrementally step to the next scan line in the given wide line */ static sqInt stepToNextWideLineInat(sqInt line, sqInt yValue) { sqInt err; sqInt lastX; sqInt lineOffset; sqInt lineWidth; sqInt nextX; sqInt x; sqInt yEntry; sqInt yExit; /* Adjust entry/exit values */ yEntry = (objBuffer[line + GLWideEntry]) + 1; yExit = (objBuffer[line + GLWideExit]) + 1; objBuffer[line + GLWideEntry] = yEntry; objBuffer[line + GLWideExit] = yExit; lineWidth = objBuffer[line + GLWideExtent]; lineOffset = ((sqInt) lineWidth >> 1); if (yEntry >= lineOffset) { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) & (~GEEdgeFillsInvalid)); } if (yExit >= 0) { objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } lastX = objBuffer[line + GEXValue]; /* begin stepToNextLineIn:at: */ x = (objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement]); err = (objBuffer[line + GLError]) + (objBuffer[line + GLErrorAdjUp]); if (err > 0) { x += objBuffer[line + GLXDirection]; err -= objBuffer[line + GLErrorAdjDown]; } objBuffer[line + GLError] = err; objBuffer[line + GEXValue] = x; /* Check for special start/end adjustments */ nextX = objBuffer[line + GEXValue]; if ((yEntry <= lineWidth) || ((yExit + lineOffset) >= 0)) { adjustWideLineafterSteppingFromto(line, lastX, nextX); } } static sqInt stopBecauseOf(sqInt stopReason) { workBuffer[GWStopReason] = stopReason; engineStopped = 1; } static sqInt stopReasonGet(void) { return workBuffer[GWStopReason]; } static sqInt stopReasonPut(sqInt value) { return workBuffer[GWStopReason] = value; } static sqInt storeEdgeStateFrominto(sqInt edge, sqInt edgeOop) { if ((interpreterProxy->slotSizeOf(edgeOop)) < ETBalloonEdgeDataSize) { return interpreterProxy->primitiveFail(); } interpreterProxy->storeIntegerofObjectwithValue(ETIndexIndex, edgeOop, objBuffer[edge + GEObjectIndex]); interpreterProxy->storeIntegerofObjectwithValue(ETXValueIndex, edgeOop, objBuffer[edge + GEXValue]); interpreterProxy->storeIntegerofObjectwithValue(ETYValueIndex, edgeOop, workBuffer[GWCurrentY]); interpreterProxy->storeIntegerofObjectwithValue(ETZValueIndex, edgeOop, objBuffer[edge + GEZValue]); interpreterProxy->storeIntegerofObjectwithValue(ETLinesIndex, edgeOop, objBuffer[edge + GENumLines]); workBuffer[GWLastExportedEdge] = edge; } static sqInt storeEngineStateInto(sqInt oop) { workBuffer[GWObjUsed] = objUsed; } static sqInt storeFillStateInto(sqInt fillOop) { sqInt fillIndex; sqInt leftX; sqInt rightX; fillIndex = workBuffer[GWLastExportedFill]; leftX = workBuffer[GWLastExportedLeftX]; rightX = workBuffer[GWLastExportedRightX]; if ((interpreterProxy->slotSizeOf(fillOop)) < FTBalloonFillDataSize) { return interpreterProxy->primitiveFail(); } interpreterProxy->storeIntegerofObjectwithValue(FTIndexIndex, fillOop, objBuffer[fillIndex + GEObjectIndex]); interpreterProxy->storeIntegerofObjectwithValue(FTMinXIndex, fillOop, leftX); interpreterProxy->storeIntegerofObjectwithValue(FTMaxXIndex, fillOop, rightX); interpreterProxy->storeIntegerofObjectwithValue(FTYValueIndex, fillOop, workBuffer[GWCurrentY]); } static sqInt storeRenderingState(void) { sqInt edge; sqInt edgeOop; sqInt fillOop; sqInt reason; if (interpreterProxy->failed()) { return null; } if (engineStopped) { /* begin storeStopStateIntoEdge:fill: */ edgeOop = interpreterProxy->stackObjectValue(1); fillOop = interpreterProxy->stackObjectValue(0); reason = workBuffer[GWStopReason]; if (reason == GErrorGETEntry) { edge = getBuffer[workBuffer[GWGETStart]]; storeEdgeStateFrominto(edge, edgeOop); workBuffer[GWGETStart] = ((workBuffer[GWGETStart]) + 1); } if (reason == GErrorFillEntry) { storeFillStateInto(fillOop); } if (reason == GErrorAETEntry) { edge = aetBuffer[workBuffer[GWAETStart]]; storeEdgeStateFrominto(edge, edgeOop); } } /* begin storeEngineStateInto: */ workBuffer[GWObjUsed] = objUsed; interpreterProxy->pop(3); interpreterProxy->pushInteger(workBuffer[GWStopReason]); } static sqInt storeStopStateIntoEdgefill(sqInt edgeOop, sqInt fillOop) { sqInt edge; sqInt reason; reason = workBuffer[GWStopReason]; if (reason == GErrorGETEntry) { edge = getBuffer[workBuffer[GWGETStart]]; storeEdgeStateFrominto(edge, edgeOop); workBuffer[GWGETStart] = ((workBuffer[GWGETStart]) + 1); } if (reason == GErrorFillEntry) { storeFillStateInto(fillOop); } if (reason == GErrorAETEntry) { edge = aetBuffer[workBuffer[GWAETStart]]; storeEdgeStateFrominto(edge, edgeOop); } } /* Recursively subdivide the curve on the bezier stack. */ static sqInt subdivideBezierFrom(sqInt index) { sqInt index1; sqInt index2; sqInt otherIndex; otherIndex = subdivideBezier(index); if (!(otherIndex == index)) { index1 = subdivideBezierFrom(index); if (engineStopped) { return 0; } index2 = subdivideBezierFrom(otherIndex); if (engineStopped) { return 0; } if (index1 >= index2) { return index1; } else { return index2; } } return index; } /* Subdivide the given bezier curve if necessary */ static sqInt subdivideBezier(sqInt index) { sqInt deltaX; sqInt deltaY; sqInt endX; sqInt endY; sqInt startX; sqInt startY; startY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; /* If the receiver is horizontal, don't do anything */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; if (endY == startY) { return index; } deltaY = endY - startY; if (deltaY < 0) { deltaY = 0 - deltaY; } if (deltaY > 255) { workBuffer[GWBezierHeightSubdivisions] = ((workBuffer[GWBezierHeightSubdivisions]) + 1); return computeBezierSplitAtHalf(index); } startX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]; endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; deltaX = endX - startX; if (deltaX < 0) { deltaX = 0 - deltaX; } if ((deltaY * 32) < deltaX) { workBuffer[GWBezierOverflowSubdivisions] = ((workBuffer[GWBezierOverflowSubdivisions]) + 1); return computeBezierSplitAtHalf(index); } return index; } /* Check if the given bezier curve is monoton in X. If not, subdivide it */ static sqInt subdivideToBeMonotonInX(sqInt index) { sqInt denom; sqInt dx1; sqInt dx2; sqInt endX; sqInt num; sqInt startX; sqInt viaX; startX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 0)]; viaX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]; endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; dx1 = viaX - startX; dx2 = endX - viaX; if ((dx1 * dx2) >= 0) { return index; } workBuffer[GWBezierMonotonSubdivisions] = ((workBuffer[GWBezierMonotonSubdivisions]) + 1); denom = dx2 - dx1; num = dx1; if (num < 0) { num = 0 - num; } if (denom < 0) { denom = 0 - denom; } return computeBeziersplitAt(index, (((double) num )) / (((double) denom ))); } /* Check if the given bezier curve is monoton in Y. If not, subdivide it */ static sqInt subdivideToBeMonotonInY(sqInt index) { sqInt denom; sqInt dy1; sqInt dy2; sqInt endY; sqInt num; sqInt startY; sqInt viaY; startY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; viaY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]; endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; dy1 = viaY - startY; dy2 = endY - viaY; if ((dy1 * dy2) >= 0) { return index; } workBuffer[GWBezierMonotonSubdivisions] = ((workBuffer[GWBezierMonotonSubdivisions]) + 1); denom = dy2 - dy1; num = dy1; if (num < 0) { num = 0 - num; } if (denom < 0) { denom = 0 - denom; } return computeBeziersplitAt(index, (((double) num )) / (((double) denom ))); } /* Check if the given bezier curve is monoton in Y, and, if desired in X. If not, subdivide it */ static sqInt subdivideToBeMonotoninX(sqInt base, sqInt doTestX) { sqInt base2; sqInt index1; sqInt index2; base2 = index1 = index2 = subdivideToBeMonotonInY(base); if (doTestX) { index1 = subdivideToBeMonotonInX(base); } if (index1 > index2) { index2 = index1; } if ((base != base2) && (doTestX)) { index1 = subdivideToBeMonotonInX(base2); } if (index1 > index2) { index2 = index1; } return index2; } static sqInt toggleFillsOf(sqInt edge) { sqInt depth; sqInt fillIndex; if (!(needAvailableSpace(3 * 2))) { return null; } depth = (objBuffer[edge + GEZValue]) << 1; fillIndex = objBuffer[edge + GEFillIndexLeft]; if (!(fillIndex == 0)) { toggleFilldepthrightX(fillIndex, depth, 999999999); } fillIndex = objBuffer[edge + GEFillIndexRight]; if (!(fillIndex == 0)) { toggleFilldepthrightX(fillIndex, depth, 999999999); } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } while ((topRightX()) <= (objBuffer[edge + GEXValue])) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } } l1: /* end quickRemoveInvalidFillsAt: */; } /* Make the fill style with the given index either visible or invisible */ static sqInt toggleFilldepthrightX(sqInt fillIndex, sqInt depth, sqInt rightX) { sqInt hidden; if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { if (wbStackPush(3)) { workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)] = fillIndex; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)] = depth; workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)] = rightX; } } else { hidden = hideFilldepth(fillIndex, depth); if (!(hidden)) { showFilldepthrightX(fillIndex, depth, rightX); } } } static sqInt toggleWideFillOf(sqInt edge) { sqInt depth; sqInt fill; sqInt index; sqInt lineWidth; sqInt rightX; sqInt type; type = ((usqInt) ((objBuffer[edge + GEObjectType]) & GEPrimitiveTypeMask)) >> 1; dispatchedValue = edge; switch (type) { case 0: case 1: errorWrongIndex(); break; case 2: dispatchReturnValue = objBuffer[dispatchedValue + GLWideWidth]; break; case 3: dispatchReturnValue = objBuffer[dispatchedValue + GBWideWidth]; break; } lineWidth = dispatchReturnValue; switch (type) { case 0: case 1: errorWrongIndex(); break; case 2: dispatchReturnValue = objBuffer[dispatchedValue + GLWideFill]; break; case 3: dispatchReturnValue = objBuffer[dispatchedValue + GBWideFill]; break; } fill = dispatchReturnValue; if (fill == 0) { return null; } if (!(needAvailableSpace(3))) { return null; } /* So lines sort before interior fills */ depth = ((objBuffer[edge + GEZValue]) << 1) + 1; rightX = (objBuffer[edge + GEXValue]) + lineWidth; index = findStackFilldepth(fill, depth); if (index == -1) { showFilldepthrightX(fill, depth, rightX); } else { if ((workBuffer[(workBuffer[GWBufferTop]) + (index + 2)]) < rightX) { workBuffer[(workBuffer[GWBufferTop]) + (index + 2)] = rightX; } } /* begin quickRemoveInvalidFillsAt: */ if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } while ((topRightX()) <= (objBuffer[edge + GEXValue])) { hideFilldepth(topFill(), topDepth()); if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { goto l1; } } l1: /* end quickRemoveInvalidFillsAt: */; } static sqInt topDepth(void) { if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { return -1; } else { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)]; } } static sqInt topFill(void) { if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { return 0; } else { return workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; } } static sqInt topFillDepth(void) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)]; } static sqInt topFillDepthPut(sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 1)] = value; } static sqInt topFillRightX(void) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; } static sqInt topFillRightXPut(sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)] = value; } static sqInt topFillValue(void) { return workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)]; } static sqInt topFillValuePut(sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3)] = value; } static sqInt topRightX(void) { if (((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) == 0) { return 999999999; } else { return workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 3) + 2)]; } } static sqInt transformColor(sqInt fillIndex) { sqInt a; double alphaScale; sqInt b; sqInt g; sqInt r; float *transform; if (!((fillIndex == 0) || ((fillIndex & 4278190080UL) != 0))) { return fillIndex; } b = fillIndex & 255; g = (((usqInt) fillIndex) >> 8) & 255; r = (((usqInt) fillIndex) >> 16) & 255; a = (((usqInt) fillIndex) >> 24) & 255; if ((workBuffer[GWHasColorTransform]) != 0) { /* begin colorTransform */ transform = ((float *) (workBuffer + GWColorTransform)); alphaScale = ((a * (transform[6])) + (transform[7])) / a; r = ((sqInt)(((r * (transform[0])) + (transform[1])) * alphaScale)); g = ((sqInt)(((g * (transform[2])) + (transform[3])) * alphaScale)); b = ((sqInt)(((b * (transform[4])) + (transform[5])) * alphaScale)); a = a * alphaScale; r = ((r < 0) ? 0 : r); r = ((r < 255) ? r : 255); g = ((g < 0) ? 0 : g); g = ((g < 255) ? g : 255); b = ((b < 0) ? 0 : b); b = ((b < 255) ? b : 255); a = ((a < 0) ? 0 : a); a = ((a < 255) ? a : 255); } if (a < 1) { return 0; } if ((a < 255) && ((workBuffer[GWNeedsFlush]) != 0)) { /* begin stopBecauseOf: */ workBuffer[GWStopReason] = GErrorNeedFlush; engineStopped = 1; } return ((b + (g << 8)) + (r << 16)) + (a << 24); } /* Transform n (n=1,2,3) points. If haveMatrix is true then the matrix contains the actual transformation. */ static sqInt transformPoints(sqInt n) { int *point; int *point1; int *point2; int *point3; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; if (n > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (n > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (n > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (n > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } } /* Transform srcPoint into dstPoint by using the currently loaded matrix */ /* Note: This should be rewritten so that inlining works (e.g., removing the declarations and adding argument coercions at the appropriate points) */ static sqInt transformPointXyinto(double xValue, double yValue, int *dstPoint) { float *transform; sqInt x; sqInt y; /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * xValue) + ((transform[1]) * yValue)) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * xValue) + ((transform[4]) * yValue)) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); dstPoint[0] = x; dstPoint[1] = y; } /* Transform the given point. If haveMatrix is true then use the current transformation. */ static sqInt transformPoint(int *point) { float *transform; sqInt x; sqInt y; if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } /* Transform srcPoint into dstPoint by using the currently loaded matrix */ /* Note: This method has been rewritten so that inlining works (e.g., removing the declarations and adding argument coercions at the appropriate points) */ static sqInt transformPointinto(sqInt srcPoint, sqInt dstPoint) { float *transform; sqInt x; sqInt y; /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) srcPoint))[0]) ))) + ((transform[1]) * (((double) ((((int *) srcPoint))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) srcPoint))[0]) ))) + ((transform[4]) * (((double) ((((int *) srcPoint))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) dstPoint))[0] = x; (((int *) dstPoint))[1] = y; } /* Transform the given width */ static sqInt transformWidth(sqInt w) { double deltaX; double deltaY; sqInt dstWidth; sqInt dstWidth2; int *point; int *point1; int *point2; int *point3; float *transform; float *transform1; float *transform2; float *transform3; sqInt x; sqInt x1; sqInt x2; sqInt x3; sqInt y; sqInt y1; sqInt y2; sqInt y3; if (w == 0) { return 0; } (point1Get())[0] = 0; (point1Get())[1] = 0; (point2Get())[0] = (w * 256); (point2Get())[1] = 0; (point3Get())[0] = 0; (point3Get())[1] = (w * 256); /* begin transformPoints: */ if (3 > 0) { /* begin transformPoint: */ /* begin point1Get */ point = ((int *) (workBuffer + GWPoint1)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform = ((float *) (workBuffer + GWEdgeTransform)); x = ((sqInt)(((((transform[0]) * (((double) ((((int *) point))[0]) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); y = ((sqInt)(((((transform[3]) * (((double) ((((int *) point))[0]) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point))[0] = x; (((int *) point))[1] = y; } else { point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 1) { /* begin transformPoint: */ /* begin point2Get */ point1 = ((int *) (workBuffer + GWPoint2)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform1 = ((float *) (workBuffer + GWEdgeTransform)); x1 = ((sqInt)(((((transform1[0]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[1]) * (((double) ((((int *) point1))[1]) )))) + (transform1[2])) * (((double) (workBuffer[GWAALevel]) )))); y1 = ((sqInt)(((((transform1[3]) * (((double) ((((int *) point1))[0]) ))) + ((transform1[4]) * (((double) ((((int *) point1))[1]) )))) + (transform1[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point1))[0] = x1; (((int *) point1))[1] = y1; } else { point1[0] = (((point1[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point1[1] = (((point1[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 2) { /* begin transformPoint: */ /* begin point3Get */ point2 = ((int *) (workBuffer + GWPoint3)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform2 = ((float *) (workBuffer + GWEdgeTransform)); x2 = ((sqInt)(((((transform2[0]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[1]) * (((double) ((((int *) point2))[1]) )))) + (transform2[2])) * (((double) (workBuffer[GWAALevel]) )))); y2 = ((sqInt)(((((transform2[3]) * (((double) ((((int *) point2))[0]) ))) + ((transform2[4]) * (((double) ((((int *) point2))[1]) )))) + (transform2[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point2))[0] = x2; (((int *) point2))[1] = y2; } else { point2[0] = (((point2[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point2[1] = (((point2[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } if (3 > 3) { /* begin transformPoint: */ /* begin point4Get */ point3 = ((int *) (workBuffer + GWPoint4)); if ((workBuffer[GWHasEdgeTransform]) != 0) { /* begin transformPoint:into: */ /* begin transformPointX:y:into: */ /* begin edgeTransform */ transform3 = ((float *) (workBuffer + GWEdgeTransform)); x3 = ((sqInt)(((((transform3[0]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[1]) * (((double) ((((int *) point3))[1]) )))) + (transform3[2])) * (((double) (workBuffer[GWAALevel]) )))); y3 = ((sqInt)(((((transform3[3]) * (((double) ((((int *) point3))[0]) ))) + ((transform3[4]) * (((double) ((((int *) point3))[1]) )))) + (transform3[5])) * (((double) (workBuffer[GWAALevel]) )))); (((int *) point3))[0] = x3; (((int *) point3))[1] = y3; } else { point3[0] = (((point3[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); point3[1] = (((point3[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } deltaX = ((double) (((point2Get())[0]) - ((point1Get())[0])) ); deltaY = ((double) (((point2Get())[1]) - ((point1Get())[1])) ); dstWidth = ((sqInt) ((((sqInt)(sqrt((deltaX * deltaX) + (deltaY * deltaY))))) + 128) >> 8); deltaX = ((double) (((point3Get())[0]) - ((point1Get())[0])) ); deltaY = ((double) (((point3Get())[1]) - ((point1Get())[1])) ); dstWidth2 = ((sqInt) ((((sqInt)(sqrt((deltaX * deltaX) + (deltaY * deltaY))))) + 128) >> 8); if (dstWidth2 < dstWidth) { dstWidth = dstWidth2; } if (dstWidth == 0) { return 1; } else { return dstWidth; } } static sqInt uncheckedTransformColor(sqInt fillIndex) { sqInt a; sqInt b; sqInt g; sqInt r; float *transform; if (!((workBuffer[GWHasColorTransform]) != 0)) { return fillIndex; } b = fillIndex & 255; g = (((usqInt) fillIndex) >> 8) & 255; r = (((usqInt) fillIndex) >> 16) & 255; a = (((usqInt) fillIndex) >> 24) & 255; /* begin colorTransform */ transform = ((float *) (workBuffer + GWColorTransform)); r = ((sqInt)((r * (transform[0])) + (transform[1]))); g = ((sqInt)((g * (transform[2])) + (transform[3]))); b = ((sqInt)((b * (transform[4])) + (transform[5]))); a = ((sqInt)((a * (transform[6])) + (transform[7]))); r = ((r < 0) ? 0 : r); r = ((r < 255) ? r : 255); g = ((g < 0) ? 0 : g); g = ((g < 255) ? g : 255); b = ((b < 0) ? 0 : b); b = ((b < 255) ? b : 255); a = ((a < 0) ? 0 : a); a = ((a < 255) ? a : 255); if (a < 16) { return 0; } return ((b + (g << 8)) + (r << 16)) + (a << 24); } static sqInt wbSizeGet(void) { return workBuffer[GWSize]; } static sqInt wbSizePut(sqInt value) { return workBuffer[GWSize] = value; } static sqInt wbStackClear(void) { workBuffer[GWBufferTop] = (workBuffer[GWSize]); } static sqInt wbStackPop(sqInt nItems) { workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) + nItems); } static sqInt wbStackPush(sqInt nItems) { if (!(needAvailableSpace(nItems))) { return 0; } workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) - nItems); return 1; } static sqInt wbStackSize(void) { return (workBuffer[GWSize]) - (workBuffer[GWBufferTop]); } static sqInt wbStackValue(sqInt index) { return workBuffer[(workBuffer[GWBufferTop]) + index]; } static sqInt wbStackValueput(sqInt index, sqInt value) { return workBuffer[(workBuffer[GWBufferTop]) + index] = value; } static sqInt wbTopGet(void) { return workBuffer[GWBufferTop]; } static sqInt wbTopPut(sqInt value) { return workBuffer[GWBufferTop] = value; } static sqInt wideBezierEntryOf(sqInt line) { return objBuffer[line + GBWideEntry]; } static sqInt wideBezierEntryOfput(sqInt line, sqInt value) { return objBuffer[line + GBWideEntry] = value; } static sqInt wideBezierExitOf(sqInt line) { return objBuffer[line + GBWideExit]; } static sqInt wideBezierExitOfput(sqInt line, sqInt value) { return objBuffer[line + GBWideExit] = value; } static sqInt wideBezierExtentOf(sqInt bezier) { return objBuffer[bezier + GBWideExtent]; } static sqInt wideBezierExtentOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBWideExtent] = value; } static sqInt wideBezierFillOf(sqInt bezier) { return objBuffer[bezier + GBWideFill]; } static sqInt wideBezierFillOfput(sqInt bezier, sqInt value) { return objBuffer[bezier + GBWideFill] = value; } static int * wideBezierUpdateDataOf(sqInt bezier) { return (objBuffer + bezier) + GBWideUpdateData; } static sqInt wideBezierWidthOf(sqInt line) { return objBuffer[line + GBWideWidth]; } static sqInt wideBezierWidthOfput(sqInt line, sqInt value) { return objBuffer[line + GBWideWidth] = value; } static sqInt wideLineEntryOf(sqInt line) { return objBuffer[line + GLWideEntry]; } static sqInt wideLineEntryOfput(sqInt line, sqInt value) { return objBuffer[line + GLWideEntry] = value; } static sqInt wideLineExitOf(sqInt line) { return objBuffer[line + GLWideExit]; } static sqInt wideLineExitOfput(sqInt line, sqInt value) { return objBuffer[line + GLWideExit] = value; } static sqInt wideLineExtentOf(sqInt line) { return objBuffer[line + GLWideExtent]; } static sqInt wideLineExtentOfput(sqInt line, sqInt value) { return objBuffer[line + GLWideExtent] = value; } static sqInt wideLineFillOf(sqInt line) { return objBuffer[line + GLWideFill]; } static sqInt wideLineFillOfput(sqInt line, sqInt value) { return objBuffer[line + GLWideFill] = value; } static sqInt wideLineWidthOf(sqInt line) { return objBuffer[line + GLWideWidth]; } static sqInt wideLineWidthOfput(sqInt line, sqInt value) { return objBuffer[line + GLWideWidth] = value; } static sqInt workBufferPut(sqInt wbOop) { workBuffer = interpreterProxy->firstIndexableField(wbOop); } #ifdef SQUEAK_BUILTIN_PLUGIN void* B2DPlugin_exports[][3] = { {"B2DPlugin", "getModuleName", (void*)getModuleName}, {"B2DPlugin", "initialiseModule", (void*)initialiseModule}, {"B2DPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"B2DPlugin", "primitiveAbortProcessing", (void*)primitiveAbortProcessing}, {"B2DPlugin", "primitiveAddActiveEdgeEntry", (void*)primitiveAddActiveEdgeEntry}, {"B2DPlugin", "primitiveAddBezier", (void*)primitiveAddBezier}, {"B2DPlugin", "primitiveAddBezierShape", (void*)primitiveAddBezierShape}, {"B2DPlugin", "primitiveAddBitmapFill", (void*)primitiveAddBitmapFill}, {"B2DPlugin", "primitiveAddCompressedShape", (void*)primitiveAddCompressedShape}, {"B2DPlugin", "primitiveAddGradientFill", (void*)primitiveAddGradientFill}, {"B2DPlugin", "primitiveAddLine", (void*)primitiveAddLine}, {"B2DPlugin", "primitiveAddOval", (void*)primitiveAddOval}, {"B2DPlugin", "primitiveAddPolygon", (void*)primitiveAddPolygon}, {"B2DPlugin", "primitiveAddRect", (void*)primitiveAddRect}, {"B2DPlugin", "primitiveChangedActiveEdgeEntry", (void*)primitiveChangedActiveEdgeEntry}, {"B2DPlugin", "primitiveCopyBuffer", (void*)primitiveCopyBuffer}, {"B2DPlugin", "primitiveDisplaySpanBuffer", (void*)primitiveDisplaySpanBuffer}, {"B2DPlugin", "primitiveDoProfileStats", (void*)primitiveDoProfileStats}, {"B2DPlugin", "primitiveFinishedProcessing", (void*)primitiveFinishedProcessing}, {"B2DPlugin", "primitiveGetAALevel", (void*)primitiveGetAALevel}, {"B2DPlugin", "primitiveGetBezierStats", (void*)primitiveGetBezierStats}, {"B2DPlugin", "primitiveGetClipRect", (void*)primitiveGetClipRect}, {"B2DPlugin", "primitiveGetCounts", (void*)primitiveGetCounts}, {"B2DPlugin", "primitiveGetDepth", (void*)primitiveGetDepth}, {"B2DPlugin", "primitiveGetFailureReason", (void*)primitiveGetFailureReason}, {"B2DPlugin", "primitiveGetOffset", (void*)primitiveGetOffset}, {"B2DPlugin", "primitiveGetTimes", (void*)primitiveGetTimes}, {"B2DPlugin", "primitiveInitializeBuffer", (void*)primitiveInitializeBuffer}, {"B2DPlugin", "primitiveInitializeProcessing", (void*)primitiveInitializeProcessing}, {"B2DPlugin", "primitiveMergeFillFrom", (void*)primitiveMergeFillFrom}, {"B2DPlugin", "primitiveNeedsFlush", (void*)primitiveNeedsFlush}, {"B2DPlugin", "primitiveNeedsFlushPut", (void*)primitiveNeedsFlushPut}, {"B2DPlugin", "primitiveNextActiveEdgeEntry", (void*)primitiveNextActiveEdgeEntry}, {"B2DPlugin", "primitiveNextFillEntry", (void*)primitiveNextFillEntry}, {"B2DPlugin", "primitiveNextGlobalEdgeEntry", (void*)primitiveNextGlobalEdgeEntry}, {"B2DPlugin", "primitiveRegisterExternalEdge", (void*)primitiveRegisterExternalEdge}, {"B2DPlugin", "primitiveRegisterExternalFill", (void*)primitiveRegisterExternalFill}, {"B2DPlugin", "primitiveRenderImage", (void*)primitiveRenderImage}, {"B2DPlugin", "primitiveRenderScanline", (void*)primitiveRenderScanline}, {"B2DPlugin", "primitiveSetAALevel", (void*)primitiveSetAALevel}, {"B2DPlugin", "primitiveSetBitBltPlugin", (void*)primitiveSetBitBltPlugin}, {"B2DPlugin", "primitiveSetClipRect", (void*)primitiveSetClipRect}, {"B2DPlugin", "primitiveSetColorTransform", (void*)primitiveSetColorTransform}, {"B2DPlugin", "primitiveSetDepth", (void*)primitiveSetDepth}, {"B2DPlugin", "primitiveSetEdgeTransform", (void*)primitiveSetEdgeTransform}, {"B2DPlugin", "primitiveSetOffset", (void*)primitiveSetOffset}, {"B2DPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from B3DAcceleratorPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "B3DAcceleratorPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "B3DAcceleratorPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt checkBoundsRangefacescount(sqInt vertices, unsigned int *facePtr, sqInt faceCount); static sqInt checkVertexData(sqInt vertices); static void* fetchLightSourceofObject(sqInt index, sqInt anArray); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt loadClientStateverticescolorsnormalstexCoords(sqInt handle, sqInt vertices, sqInt colors, sqInt normals, sqInt texCoords); static sqInt msg(char *s); EXPORT(sqInt) primitiveAllocateTexture(void); EXPORT(sqInt) primitiveClearDepthBuffer(void); EXPORT(sqInt) primitiveClearViewport(void); EXPORT(sqInt) primitiveCompositeTexture(void); EXPORT(sqInt) primitiveCreateRenderer(void); EXPORT(sqInt) primitiveCreateRendererFlags(void); EXPORT(sqInt) primitiveDestroyRenderer(void); EXPORT(sqInt) primitiveDestroyTexture(void); EXPORT(sqInt) primitiveDrawArrays(void); EXPORT(sqInt) primitiveDrawElements(void); EXPORT(sqInt) primitiveDrawRangeElements(void); EXPORT(sqInt) primitiveEnableDrawRangeChecks(void); EXPORT(sqInt) primitiveFinishRenderer(void); EXPORT(sqInt) primitiveFlushRenderer(void); EXPORT(sqInt) primitiveGetIntProperty(void); EXPORT(sqInt) primitiveGetRendererColorMasks(void); EXPORT(sqInt) primitiveGetRendererSurfaceDepth(void); EXPORT(sqInt) primitiveGetRendererSurfaceHandle(void); EXPORT(sqInt) primitiveGetRendererSurfaceHeight(void); EXPORT(sqInt) primitiveGetRendererSurfaceWidth(void); EXPORT(sqInt) primitiveIsOverlayRenderer(void); EXPORT(sqInt) primitiveRendererVersion(void); EXPORT(sqInt) primitiveRenderVertexBuffer(void); EXPORT(sqInt) primitiveSetBufferRect(void); EXPORT(sqInt) primitiveSetFog(void); EXPORT(sqInt) primitiveSetIntProperty(void); EXPORT(sqInt) primitiveSetLights(void); EXPORT(sqInt) primitiveSetMaterial(void); EXPORT(sqInt) primitiveSetTransform(void); EXPORT(sqInt) primitiveSetVerboseLevel(void); EXPORT(sqInt) primitiveSetViewport(void); EXPORT(sqInt) primitiveSwapRendererBuffers(void); EXPORT(sqInt) primitiveTextureByteSex(void); EXPORT(sqInt) primitiveTextureDepth(void); EXPORT(sqInt) primitiveTextureGetColorMasks(void); EXPORT(sqInt) primitiveTextureSurfaceHandle(void); EXPORT(sqInt) primitiveTextureUpload(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static sqInt stackLightArrayValue(sqInt stackIndex); static void * stackMaterialValue(sqInt stackIndex); static void* stackMatrix(sqInt index); static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex); static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems); static void* stackPrimitiveVertex(sqInt index); /*** Variables ***/ static sqInt doRangeChecks; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "B3DAcceleratorPlugin VMMaker-oscog.dtl.57 (i)" #else "B3DAcceleratorPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Verify the bounds condition on the entire faces array */ static sqInt checkBoundsRangefacescount(sqInt vertices, unsigned int *facePtr, sqInt faceCount) { sqInt i; sqInt vtxSize; vtxSize = (interpreterProxy->slotSizeOf(vertices)) / 3; for (i = 0; i <= (faceCount - 1); i += 1) { if ((facePtr[i]) > vtxSize) { return interpreterProxy->primitiveFail(); } } } /* Check the entire vertex data to ensure no nan/inf values */ static sqInt checkVertexData(sqInt vertices) { float f; sqInt i; float *vtxPtr; sqInt vtxSize; vtxSize = interpreterProxy->slotSizeOf(vertices); vtxPtr = interpreterProxy->firstIndexableField(vertices); for (i = 0; i <= (vtxSize - 1); i += 1) { f = vtxPtr[i]; if (isnan(f - f)) { return interpreterProxy->primitiveFail(); } } } /* Fetch the primitive light source from the given array. Note: No checks are done within here - that happened in stackLightArrayValue: */ static void* fetchLightSourceofObject(sqInt index, sqInt anArray) { sqInt lightOop; lightOop = interpreterProxy->fetchPointerofObject(index, anArray); return interpreterProxy->firstIndexableField(lightOop); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { doRangeChecks = 1; return b3dxInitialize(); } /* Common method to set up client state for some render ops */ static sqInt loadClientStateverticescolorsnormalstexCoords(sqInt handle, sqInt vertices, sqInt colors, sqInt normals, sqInt texCoords) { void *colorPtr; void *normalPtr; sqInt ok; sqInt sz; void *txPtr; void *vertexPtr; sqInt vtxSize; /* Verify vertex data */ colorPtr = normalPtr = txPtr = vertexPtr = null; if (!(interpreterProxy->isWords(vertices))) { return interpreterProxy->primitiveFail(); } /* Verify assumptions of color, normal, texCoords data */ vtxSize = (interpreterProxy->slotSizeOf(vertices)) / 3; if (!((colors == (interpreterProxy->nilObject())) || ((interpreterProxy->isWords(colors)) && ((interpreterProxy->slotSizeOf(colors)) == (vtxSize * 4))))) { return interpreterProxy->primitiveFail(); } if (!((normals == (interpreterProxy->nilObject())) || ((interpreterProxy->isWords(normals)) && ((interpreterProxy->slotSizeOf(normals)) == (vtxSize * 3))))) { return interpreterProxy->primitiveFail(); } if (!((texCoords == (interpreterProxy->nilObject())) || (interpreterProxy->isWords(texCoords)))) { return interpreterProxy->primitiveFail(); } if (!(colors == (interpreterProxy->nilObject()))) { colorPtr = interpreterProxy->firstIndexableField(colors); } if (!(normals == (interpreterProxy->nilObject()))) { normalPtr = interpreterProxy->firstIndexableField(normals); } if (!(texCoords == (interpreterProxy->nilObject()))) { sz = (interpreterProxy->slotSizeOf(texCoords)) / vtxSize; txPtr = interpreterProxy->firstIndexableField(texCoords); } vertexPtr = interpreterProxy->firstIndexableField(vertices); if (interpreterProxy->failed()) { return null; } ok = b3dLoadClientState(handle, vertexPtr, 3, colorPtr, 4, normalPtr, 3, txPtr, sz); if (!(ok)) { return interpreterProxy->primitiveFail(); } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveAllocateTexture(void) { sqInt d; sqInt h; sqInt renderer; sqInt result; sqInt w; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); d = interpreterProxy->stackIntegerValue(2); renderer = interpreterProxy->stackIntegerValue(3); if (interpreterProxy->failed()) { return null; } result = b3dxAllocateTexture(renderer, w, h, d); if (result == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(5); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveClearDepthBuffer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxClearDepthBuffer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveClearViewport(void) { sqInt handle; sqInt pv; sqInt result; sqInt rgba; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } pv = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); rgba = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); handle = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } result = b3dxClearViewport(handle, rgba, pv); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveCompositeTexture(void) { sqInt h; sqInt rendererHandle; sqInt result; sqInt texHandle; sqInt translucent; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 7)) { return interpreterProxy->primitiveFail(); } translucent = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); h = interpreterProxy->stackIntegerValue(1); w = interpreterProxy->stackIntegerValue(2); y = interpreterProxy->stackIntegerValue(3); x = interpreterProxy->stackIntegerValue(4); texHandle = interpreterProxy->stackIntegerValue(5); rendererHandle = interpreterProxy->stackIntegerValue(6); if (interpreterProxy->failed()) { return null; } result = b3dxCompositeTexture(rendererHandle, texHandle, x, y, w, h, translucent); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(7); } /* NOTE: This primitive is obsolete but should be supported for older images */ EXPORT(sqInt) primitiveCreateRenderer(void) { sqInt allowHardware; sqInt allowSoftware; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); allowHardware = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(4)); allowSoftware = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(5)); if (interpreterProxy->failed()) { return null; } result = b3dxCreateRenderer(allowSoftware, allowHardware, x, y, w, h); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(7); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveCreateRendererFlags(void) { sqInt flags; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); flags = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxCreateRendererFlags(x, y, w, h, flags); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(6); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveDestroyRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxDestroyRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDestroyTexture(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxDestroyTexture(renderer, handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } /* Primitive. Setup non-VBO client state and call drawRangeElements in one go to avoid garbage collection to move the buffers underneith. */ EXPORT(sqInt) primitiveDrawArrays(void) { sqInt colors; float f; sqInt handle; sqInt i; sqInt maxIdx; sqInt minIdx; sqInt mode; sqInt normals; sqInt ok; sqInt texCoords; sqInt vertices; float *vtxPtr; sqInt vtxSize; sqInt vtxSize1; if (!((interpreterProxy->methodArgumentCount()) == 8)) { return interpreterProxy->primitiveFail(); } maxIdx = interpreterProxy->stackIntegerValue(0); minIdx = interpreterProxy->stackIntegerValue(1); mode = interpreterProxy->stackIntegerValue(2); texCoords = interpreterProxy->stackValue(3); normals = interpreterProxy->stackValue(4); colors = interpreterProxy->stackValue(5); vertices = interpreterProxy->stackValue(6); handle = interpreterProxy->stackIntegerValue(7); loadClientStateverticescolorsnormalstexCoords(handle, vertices, colors, normals, texCoords); if (interpreterProxy->failed()) { return null; } if (doRangeChecks) { /* begin checkVertexData: */ vtxSize1 = interpreterProxy->slotSizeOf(vertices); vtxPtr = interpreterProxy->firstIndexableField(vertices); for (i = 0; i <= (vtxSize1 - 1); i += 1) { f = vtxPtr[i]; if (isnan(f - f)) { interpreterProxy->primitiveFail(); goto l1; } } l1: /* end checkVertexData: */; vtxSize = (interpreterProxy->slotSizeOf(vertices)) / 3; if ((minIdx < 0) || ((minIdx > maxIdx) || (maxIdx > vtxSize))) { return interpreterProxy->primitiveFail(); } } if (interpreterProxy->failed()) { return null; } ok = b3dDrawArrays(handle, mode, minIdx, maxIdx); if (!(ok)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } } /* Primitive. Setup non-VBO client state and call drawElements in one go to avoid garbage collection to move the buffers underneith. */ EXPORT(sqInt) primitiveDrawElements(void) { sqInt colors; float f; unsigned int *facePtr; sqInt faceSize; sqInt faces; sqInt handle; sqInt i; sqInt i1; sqInt mode; sqInt normals; sqInt ok; sqInt texCoords; sqInt vertices; float *vtxPtr; sqInt vtxSize; sqInt vtxSize1; if (!((interpreterProxy->methodArgumentCount()) == 7)) { return interpreterProxy->primitiveFail(); } faces = interpreterProxy->stackValue(0); if (!(interpreterProxy->isWords(faces))) { return interpreterProxy->primitiveFail(); } faceSize = interpreterProxy->slotSizeOf(faces); facePtr = interpreterProxy->firstIndexableField(faces); mode = interpreterProxy->stackIntegerValue(1); texCoords = interpreterProxy->stackValue(2); normals = interpreterProxy->stackValue(3); colors = interpreterProxy->stackValue(4); vertices = interpreterProxy->stackValue(5); handle = interpreterProxy->stackIntegerValue(6); loadClientStateverticescolorsnormalstexCoords(handle, vertices, colors, normals, texCoords); if (interpreterProxy->failed()) { return null; } if (doRangeChecks) { /* begin checkVertexData: */ vtxSize = interpreterProxy->slotSizeOf(vertices); vtxPtr = interpreterProxy->firstIndexableField(vertices); for (i = 0; i <= (vtxSize - 1); i += 1) { f = vtxPtr[i]; if (isnan(f - f)) { interpreterProxy->primitiveFail(); goto l1; } } l1: /* end checkVertexData: */; /* begin checkBoundsRange:faces:count: */ vtxSize1 = (interpreterProxy->slotSizeOf(vertices)) / 3; for (i1 = 0; i1 <= (faceSize - 1); i1 += 1) { if ((facePtr[i1]) > vtxSize1) { interpreterProxy->primitiveFail(); goto l2; } } l2: /* end checkBoundsRange:faces:count: */; } if (interpreterProxy->failed()) { return null; } ok = b3dDrawElements(handle, mode, faceSize, facePtr); if (!(ok)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } } /* Primitive. Setup non-VBO client state and call drawRangeElements in one go to avoid garbage collection to move the buffers underneith. */ EXPORT(sqInt) primitiveDrawRangeElements(void) { sqInt colors; float f; unsigned int *facePtr; sqInt faceSize; sqInt faces; sqInt handle; sqInt i; sqInt i1; sqInt maxIdx; sqInt minIdx; sqInt mode; sqInt normals; sqInt ok; sqInt texCoords; sqInt vertices; float *vtxPtr; sqInt vtxSize; sqInt vtxSize1; sqInt vtxSize2; if (!((interpreterProxy->methodArgumentCount()) == 9)) { return interpreterProxy->primitiveFail(); } faces = interpreterProxy->stackValue(0); if (!(interpreterProxy->isWords(faces))) { return interpreterProxy->primitiveFail(); } faceSize = interpreterProxy->slotSizeOf(faces); facePtr = interpreterProxy->firstIndexableField(faces); maxIdx = interpreterProxy->stackIntegerValue(1); minIdx = interpreterProxy->stackIntegerValue(2); mode = interpreterProxy->stackIntegerValue(3); texCoords = interpreterProxy->stackValue(4); normals = interpreterProxy->stackValue(5); colors = interpreterProxy->stackValue(6); vertices = interpreterProxy->stackValue(7); handle = interpreterProxy->stackIntegerValue(8); loadClientStateverticescolorsnormalstexCoords(handle, vertices, colors, normals, texCoords); if (interpreterProxy->failed()) { return null; } if (doRangeChecks) { /* begin checkVertexData: */ vtxSize1 = interpreterProxy->slotSizeOf(vertices); vtxPtr = interpreterProxy->firstIndexableField(vertices); for (i = 0; i <= (vtxSize1 - 1); i += 1) { f = vtxPtr[i]; if (isnan(f - f)) { interpreterProxy->primitiveFail(); goto l1; } } l1: /* end checkVertexData: */; /* begin checkBoundsRange:faces:count: */ vtxSize2 = (interpreterProxy->slotSizeOf(vertices)) / 3; for (i1 = 0; i1 <= (faceSize - 1); i1 += 1) { if ((facePtr[i1]) > vtxSize2) { interpreterProxy->primitiveFail(); goto l2; } } l2: /* end checkBoundsRange:faces:count: */; vtxSize = (interpreterProxy->slotSizeOf(vertices)) / 3; if ((minIdx < 0) || ((minIdx > maxIdx) || (maxIdx > vtxSize))) { return interpreterProxy->primitiveFail(); } } if (interpreterProxy->failed()) { return null; } ok = b3dDrawRangeElements(handle, mode, minIdx, maxIdx, faceSize, facePtr); if (!(ok)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } } /* Primitive. Enable/disable draw (range) checks */ EXPORT(sqInt) primitiveEnableDrawRangeChecks(void) { sqInt enabled; if ((interpreterProxy->methodArgumentCount()) == 0) { interpreterProxy->pop(1); return interpreterProxy->pushBool(doRangeChecks); } if ((interpreterProxy->methodArgumentCount()) == 1) { enabled = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } doRangeChecks = enabled; return interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFinishRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxFinishRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveFlushRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxFlushRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveGetIntProperty(void) { sqInt handle; sqInt prop; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } prop = interpreterProxy->stackIntegerValue(0); handle = interpreterProxy->stackIntegerValue(1); result = b3dxGetIntProperty(handle, prop); interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererColorMasks(void) { sqInt array; sqInt arrayOop; sqInt handle; sqInt i; int masks[4]; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } array = interpreterProxy->stackObjectValue(0); handle = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(array)) == 4)) { return interpreterProxy->primitiveFail(); } result = b3dxGetRendererColorMasks(handle, masks); if (!(result)) { return interpreterProxy->primitiveFail(); } arrayOop = array; for (i = 0; i <= 3; i += 1) { interpreterProxy->pushRemappableOop(arrayOop); result = interpreterProxy->positive32BitIntegerFor(masks[i]); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, result); } return interpreterProxy->pop(2); } EXPORT(sqInt) primitiveGetRendererSurfaceDepth(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceDepth(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceHandle(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceHandle(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceHeight(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceHeight(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceWidth(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceWidth(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveIsOverlayRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxIsOverlayRenderer(handle); interpreterProxy->pop(2); return interpreterProxy->pushBool(result); } EXPORT(sqInt) primitiveRendererVersion(void) { if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); return interpreterProxy->pushInteger(1); } EXPORT(sqInt) primitiveRenderVertexBuffer(void) { sqInt flags; sqInt handle; int *idxArray; sqInt idxCount; sqInt primType; sqInt result; sqInt texHandle; float *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 8)) { return interpreterProxy->primitiveFail(); } idxCount = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); texHandle = interpreterProxy->stackIntegerValue(4); flags = interpreterProxy->stackIntegerValue(5); primType = interpreterProxy->stackIntegerValue(6); handle = interpreterProxy->stackIntegerValue(7); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxCount, 1, vtxCount); if ((vtxArray == null) || ((idxArray == null) || ((primType < 1) || ((primType > 6) || (interpreterProxy->failed()))))) { return interpreterProxy->primitiveFail(); } result = b3dxRenderVertexBuffer(handle, primType, flags, texHandle, vtxArray, vtxCount, idxArray, idxCount); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(8); } /* Primitive. Set the buffer rectangle (e.g., the pixel area on screen) to use for this renderer. The viewport is positioned within the buffer rectangle. */ EXPORT(sqInt) primitiveSetBufferRect(void) { sqInt h; sqInt handle; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); handle = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxSetBufferRect(handle, x, y, w, h); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(5); } EXPORT(sqInt) primitiveSetFog(void) { double density; sqInt fogType; sqInt handle; sqInt result; sqInt rgba; double start; double stop; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } rgba = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); stop = interpreterProxy->floatValueOf(interpreterProxy->stackValue(1)); start = interpreterProxy->floatValueOf(interpreterProxy->stackValue(2)); density = interpreterProxy->floatValueOf(interpreterProxy->stackValue(3)); fogType = interpreterProxy->stackIntegerValue(4); handle = interpreterProxy->stackIntegerValue(5); if (interpreterProxy->failed()) { return null; } result = b3dxSetFog(handle, fogType, density, start, stop, rgba); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(6); } EXPORT(sqInt) primitiveSetIntProperty(void) { sqInt handle; sqInt prop; sqInt result; sqInt value; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } value = interpreterProxy->stackIntegerValue(0); prop = interpreterProxy->stackIntegerValue(1); handle = interpreterProxy->stackIntegerValue(2); result = b3dxSetIntProperty(handle, prop, value); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveSetLights(void) { sqInt handle; sqInt i; void*light; sqInt lightArray; sqInt lightCount; sqInt lightOop; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } lightArray = stackLightArrayValue(0); handle = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!(b3dxDisableLights(handle))) { return interpreterProxy->primitiveFail(); } if (lightArray == null) { return null; } /* For each enabled light source */ lightCount = interpreterProxy->slotSizeOf(lightArray); for (i = 0; i <= (lightCount - 1); i += 1) { /* begin fetchLightSource:ofObject: */ lightOop = interpreterProxy->fetchPointerofObject(i, lightArray); light = interpreterProxy->firstIndexableField(lightOop); if (!(b3dxLoadLight(handle, i, light))) { return interpreterProxy->primitiveFail(); } } return interpreterProxy->pop(2); } EXPORT(sqInt) primitiveSetMaterial(void) { sqInt handle; void*material; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } material = stackMaterialValue(0); handle = interpreterProxy->stackIntegerValue(1); if (!(b3dxLoadMaterial(handle, material))) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } /* Transform an entire vertex buffer using the supplied modelview and projection matrix. */ EXPORT(sqInt) primitiveSetTransform(void) { sqInt handle; float *modelViewMatrix; float *projectionMatrix; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } projectionMatrix = stackMatrix(0); modelViewMatrix = stackMatrix(1); handle = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } b3dxSetTransform(handle, modelViewMatrix, projectionMatrix); return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveSetVerboseLevel(void) { sqInt level; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } level = interpreterProxy->stackIntegerValue(0); result = b3dxSetVerboseLevel(level); interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveSetViewport(void) { sqInt h; sqInt handle; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); handle = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxSetViewport(handle, x, y, w, h); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(5); } EXPORT(sqInt) primitiveSwapRendererBuffers(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxSwapRendererBuffers(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveTextureByteSex(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxTextureByteSex(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushBool(result); } EXPORT(sqInt) primitiveTextureDepth(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxActualTextureDepth(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveTextureGetColorMasks(void) { sqInt array; sqInt arrayOop; sqInt handle; sqInt i; int masks[4]; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } array = interpreterProxy->stackObjectValue(0); handle = interpreterProxy->stackIntegerValue(1); renderer = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(array)) == 4)) { return interpreterProxy->primitiveFail(); } result = b3dxTextureColorMasks(renderer, handle, masks); if (!(result)) { return interpreterProxy->primitiveFail(); } arrayOop = array; for (i = 0; i <= 3; i += 1) { interpreterProxy->pushRemappableOop(arrayOop); result = interpreterProxy->positive32BitIntegerFor(masks[i]); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, result); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveTextureSurfaceHandle(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxTextureSurfaceHandle(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveTextureUpload(void) { sqInt bits; void*bitsPtr; sqInt d; sqInt form; sqInt h; sqInt handle; sqInt ppw; sqInt renderer; sqInt result; sqInt w; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } form = interpreterProxy->stackValue(0); if (!((interpreterProxy->isPointers(form)) && ((interpreterProxy->slotSizeOf(form)) >= 4))) { return interpreterProxy->primitiveFail(); } bits = interpreterProxy->fetchPointerofObject(0, form); w = interpreterProxy->fetchIntegerofObject(1, form); h = interpreterProxy->fetchIntegerofObject(2, form); d = interpreterProxy->fetchIntegerofObject(3, form); ppw = 32 / d; if (!(interpreterProxy->isWords(bits))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(bits)) == ((((w + ppw) - 1) / ppw) * h))) { return interpreterProxy->primitiveFail(); } bitsPtr = interpreterProxy->firstIndexableField(bits); handle = interpreterProxy->stackIntegerValue(1); renderer = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } result = b3dxUploadTexture(renderer, handle, w, h, d, bitsPtr); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return b3dxShutdown(); } /* Load an Array of B3DPrimitiveLights from the given stack index */ static sqInt stackLightArrayValue(sqInt stackIndex) { sqInt array; sqInt arraySize; sqInt i; sqInt oop; array = interpreterProxy->stackObjectValue(stackIndex); if (array == null) { return null; } if (array == (interpreterProxy->nilObject())) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(array); for (i = 0; i <= (arraySize - 1); i += 1) { oop = interpreterProxy->fetchPointerofObject(i, array); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 32))) { return interpreterProxy->primitiveFail(); } } return array; } /* Load a B3DMaterial from the given stack index */ static void * stackMaterialValue(sqInt stackIndex) { sqInt oop; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (oop == (interpreterProxy->nilObject())) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 17)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a 4x4 transformation matrix from the interpreter stack. Return a pointer to the matrix data if successful, nil otherwise. */ static void* stackMatrix(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive index array from the interpreter stack. If aBool is true then check that all the indexes are in the range (1,maxIndex). Return a pointer to the index data if successful, nil otherwise. */ static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex) { sqInt i; int *idxPtr; sqInt index; sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (!(interpreterProxy->isWords(oop))) { return null; } oopSize = interpreterProxy->slotSizeOf(oop); if (oopSize < nItems) { return null; } idxPtr = ((int *) (interpreterProxy->firstIndexableField(oop))); if (aBool) { for (i = 0; i <= (nItems - 1); i += 1) { index = idxPtr[i]; if ((index < 0) || (index > maxIndex)) { return null; } } } return idxPtr; } /* Load a primitive vertex array from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems) { sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if (interpreterProxy->isWords(oop)) { oopSize = interpreterProxy->slotSizeOf(oop); if (((oopSize >= nItems) * 16) && ((oopSize % 16) == 0)) { return interpreterProxy->firstIndexableField(oop); } } return null; } /* Load a primitive vertex from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertex(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } #ifdef SQUEAK_BUILTIN_PLUGIN void* B3DAcceleratorPlugin_exports[][3] = { {"B3DAcceleratorPlugin", "getModuleName", (void*)getModuleName}, {"B3DAcceleratorPlugin", "initialiseModule", (void*)initialiseModule}, {"B3DAcceleratorPlugin", "primitiveAllocateTexture", (void*)primitiveAllocateTexture}, {"B3DAcceleratorPlugin", "primitiveClearDepthBuffer", (void*)primitiveClearDepthBuffer}, {"B3DAcceleratorPlugin", "primitiveClearViewport", (void*)primitiveClearViewport}, {"B3DAcceleratorPlugin", "primitiveCompositeTexture", (void*)primitiveCompositeTexture}, {"B3DAcceleratorPlugin", "primitiveCreateRenderer", (void*)primitiveCreateRenderer}, {"B3DAcceleratorPlugin", "primitiveCreateRendererFlags", (void*)primitiveCreateRendererFlags}, {"B3DAcceleratorPlugin", "primitiveDestroyRenderer", (void*)primitiveDestroyRenderer}, {"B3DAcceleratorPlugin", "primitiveDestroyTexture", (void*)primitiveDestroyTexture}, {"B3DAcceleratorPlugin", "primitiveDrawArrays", (void*)primitiveDrawArrays}, {"B3DAcceleratorPlugin", "primitiveDrawElements", (void*)primitiveDrawElements}, {"B3DAcceleratorPlugin", "primitiveDrawRangeElements", (void*)primitiveDrawRangeElements}, {"B3DAcceleratorPlugin", "primitiveEnableDrawRangeChecks", (void*)primitiveEnableDrawRangeChecks}, {"B3DAcceleratorPlugin", "primitiveFinishRenderer", (void*)primitiveFinishRenderer}, {"B3DAcceleratorPlugin", "primitiveFlushRenderer", (void*)primitiveFlushRenderer}, {"B3DAcceleratorPlugin", "primitiveGetIntProperty", (void*)primitiveGetIntProperty}, {"B3DAcceleratorPlugin", "primitiveGetRendererColorMasks", (void*)primitiveGetRendererColorMasks}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceDepth", (void*)primitiveGetRendererSurfaceDepth}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceHandle", (void*)primitiveGetRendererSurfaceHandle}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceHeight", (void*)primitiveGetRendererSurfaceHeight}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceWidth", (void*)primitiveGetRendererSurfaceWidth}, {"B3DAcceleratorPlugin", "primitiveIsOverlayRenderer", (void*)primitiveIsOverlayRenderer}, {"B3DAcceleratorPlugin", "primitiveRendererVersion", (void*)primitiveRendererVersion}, {"B3DAcceleratorPlugin", "primitiveRenderVertexBuffer", (void*)primitiveRenderVertexBuffer}, {"B3DAcceleratorPlugin", "primitiveSetBufferRect", (void*)primitiveSetBufferRect}, {"B3DAcceleratorPlugin", "primitiveSetFog", (void*)primitiveSetFog}, {"B3DAcceleratorPlugin", "primitiveSetIntProperty", (void*)primitiveSetIntProperty}, {"B3DAcceleratorPlugin", "primitiveSetLights", (void*)primitiveSetLights}, {"B3DAcceleratorPlugin", "primitiveSetMaterial", (void*)primitiveSetMaterial}, {"B3DAcceleratorPlugin", "primitiveSetTransform", (void*)primitiveSetTransform}, {"B3DAcceleratorPlugin", "primitiveSetVerboseLevel", (void*)primitiveSetVerboseLevel}, {"B3DAcceleratorPlugin", "primitiveSetViewport", (void*)primitiveSetViewport}, {"B3DAcceleratorPlugin", "primitiveSwapRendererBuffers", (void*)primitiveSwapRendererBuffers}, {"B3DAcceleratorPlugin", "primitiveTextureByteSex", (void*)primitiveTextureByteSex}, {"B3DAcceleratorPlugin", "primitiveTextureDepth", (void*)primitiveTextureDepth}, {"B3DAcceleratorPlugin", "primitiveTextureGetColorMasks", (void*)primitiveTextureGetColorMasks}, {"B3DAcceleratorPlugin", "primitiveTextureSurfaceHandle", (void*)primitiveTextureSurfaceHandle}, {"B3DAcceleratorPlugin", "primitiveTextureUpload", (void*)primitiveTextureUpload}, {"B3DAcceleratorPlugin", "setInterpreter", (void*)setInterpreter}, {"B3DAcceleratorPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/BMPReadWriterPlugin/BMPReadWriterPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from BMPReadWriterPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "BMPReadWriterPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveRead24BmpLine(void); EXPORT(sqInt) primitiveWrite24BmpLine(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "BMPReadWriterPlugin VMMaker-oscog.dtl.57 (i)" #else "BMPReadWriterPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveRead24BmpLine(void) { unsigned int *formBits; sqInt formBitsIndex; sqInt formBitsOop; sqInt formBitsSize; unsigned char *pixelLine; sqInt pixelLineOop; sqInt pixelLineSize; sqInt width; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } width = interpreterProxy->stackIntegerValue(0); formBitsIndex = interpreterProxy->stackIntegerValue(1); formBitsOop = interpreterProxy->stackObjectValue(2); pixelLineOop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(formBitsOop))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(pixelLineOop))) { return interpreterProxy->primitiveFail(); } formBitsSize = interpreterProxy->slotSizeOf(formBitsOop); formBits = interpreterProxy->firstIndexableField(formBitsOop); pixelLineSize = interpreterProxy->slotSizeOf(pixelLineOop); pixelLine = interpreterProxy->firstIndexableField(pixelLineOop); if (!(((formBitsIndex + width) <= formBitsSize) && ((width * 3) <= pixelLineSize))) { return interpreterProxy->primitiveFail(); } formBits += formBitsIndex-1; while(width--) { unsigned int rgb; rgb = (*pixelLine++); rgb += (*pixelLine++) << 8; rgb += (*pixelLine++) << 16; if(rgb) rgb |= 0xFF000000; else rgb |= 0xFF000001; *formBits++ = rgb; } ; interpreterProxy->pop(4); } EXPORT(sqInt) primitiveWrite24BmpLine(void) { unsigned int *formBits; sqInt formBitsIndex; sqInt formBitsOop; sqInt formBitsSize; unsigned char *pixelLine; sqInt pixelLineOop; sqInt pixelLineSize; sqInt width; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } width = interpreterProxy->stackIntegerValue(0); formBitsIndex = interpreterProxy->stackIntegerValue(1); formBitsOop = interpreterProxy->stackObjectValue(2); pixelLineOop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(formBitsOop))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(pixelLineOop))) { return interpreterProxy->primitiveFail(); } formBitsSize = interpreterProxy->slotSizeOf(formBitsOop); formBits = interpreterProxy->firstIndexableField(formBitsOop); pixelLineSize = interpreterProxy->slotSizeOf(pixelLineOop); pixelLine = interpreterProxy->firstIndexableField(pixelLineOop); if (!(((formBitsIndex + width) <= formBitsSize) && ((width * 3) <= pixelLineSize))) { return interpreterProxy->primitiveFail(); } formBits += formBitsIndex-1; while(width--) { unsigned int rgb; rgb = *formBits++; (*pixelLine++) = (rgb ) & 0xFF; (*pixelLine++) = (rgb >> 8 ) & 0xFF; (*pixelLine++) = (rgb >> 16) & 0xFF; } ; interpreterProxy->pop(4); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* BMPReadWriterPlugin_exports[][3] = { {"BMPReadWriterPlugin", "getModuleName", (void*)getModuleName}, {"BMPReadWriterPlugin", "primitiveRead24BmpLine", (void*)primitiveRead24BmpLine}, {"BMPReadWriterPlugin", "primitiveWrite24BmpLine", (void*)primitiveWrite24BmpLine}, {"BMPReadWriterPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/BitBltPlugin/BitBltPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from BitBltSimulation VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "BitBltSimulation VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ #define AllOnes 0xFFFFFFFFUL #define AlphaIndex 3 #define BBClipHeightIndex 13 #define BBClipWidthIndex 12 #define BBClipXIndex 10 #define BBClipYIndex 11 #define BBColorMapIndex 14 #define BBDestFormIndex 0 #define BBDestXIndex 4 #define BBDestYIndex 5 #define BBHalftoneFormIndex 2 #define BBHeightIndex 7 #define BBRuleIndex 3 #define BBSourceFormIndex 1 #define BBSourceXIndex 8 #define BBSourceYIndex 9 #define BBWarpBase 15 #define BBWidthIndex 6 #define BinaryPoint 14 #define BlueIndex 2 #define ColorMapFixedPart 2 #define ColorMapIndexedPart 4 #define ColorMapNewStyle 8 #define ColorMapPresent 1 #define FixedPt1 0x4000 #define FormBitsIndex 0 #define FormDepthIndex 3 #define FormHeightIndex 2 #define FormWidthIndex 1 #define GreenIndex 1 #define OpTableSize 42 #define RedIndex 0 /*** Function Prototypes ***/ static sqInt addWordwith(sqInt sourceWord, sqInt destinationWord); static sqInt affectedBottom(void); static sqInt affectedLeft(void); static sqInt affectedRight(void); static sqInt affectedTop(void); static sqInt alphaBlendConstwith(sqInt sourceWord, sqInt destinationWord); static sqInt alphaBlendConstwithpaintMode(sqInt sourceWord, sqInt destinationWord, sqInt paintMode); static sqInt alphaBlendScaledwith(sqInt sourceWord, sqInt destinationWord); static sqInt alphaBlendwith(sqInt sourceWord, sqInt destinationWord); static sqInt alphaPaintConstwith(sqInt sourceWord, sqInt destinationWord); static sqInt alphaSourceBlendBits16(void); static sqInt alphaSourceBlendBits32(void); static sqInt alphaSourceBlendBits8(void); static sqInt bitAndInvertwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitAndwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertAndInvertwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertAndwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertDestinationwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertOrInvertwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertOrwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertSourcewith(sqInt sourceWord, sqInt destinationWord); static sqInt bitInvertXorwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitOrInvertwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitOrwith(sqInt sourceWord, sqInt destinationWord); static sqInt bitXorwith(sqInt sourceWord, sqInt destinationWord); static sqInt checkSourceOverlap(void); static sqInt clearWordwith(sqInt source, sqInt destination); static sqInt clipRange(void); EXPORT(sqInt) copyBits(void); EXPORT(sqInt) copyBitsFromtoat(sqInt startX, sqInt stopX, sqInt yValue); static sqInt copyBitsLockedAndClipped(void); static sqInt copyLoop(void); static sqInt copyLoopNoSource(void); static sqInt copyLoopPixMap(void); static unsigned int * default8To32Table(void); static sqInt deltaFromtonSteps(sqInt x1, sqInt x2, sqInt n); static sqInt destinationWordwith(sqInt sourceWord, sqInt destinationWord); static sqInt destMaskAndPointerInit(void); static sqInt dither32To16threshold(sqInt srcWord, sqInt ditherValue); static sqInt drawLoopXY(sqInt xDelta, sqInt yDelta); static sqInt dstLongAt(sqInt idx); static sqInt dstLongAtput(sqInt idx, sqInt value); static sqInt dstLongAtputmask(sqInt idx, sqInt srcValue, sqInt dstMask); static sqInt expensiveDither32To16threshold(sqInt srcWord, sqInt ditherValue); static sqInt fetchIntOrFloatofObject(sqInt fieldIndex, sqInt objectPointer); static sqInt fetchIntOrFloatofObjectifNil(sqInt fieldIndex, sqInt objectPointer, sqInt defaultValue); static sqInt fixAlphawith(sqInt sourceWord, sqInt destinationWord); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halftoneAt(sqInt idx); static sqInt halt(void); static sqInt ignoreSourceOrHalftone(sqInt formPointer); static sqInt initBBOpTable(void); static sqInt initDither8Lookup(void); EXPORT(sqInt) initialiseModule(void); static sqInt isIdentityMapwith(int *shifts, unsigned int *masks); static sqInt loadBitBltDestForm(void); EXPORT(sqInt) loadBitBltFrom(sqInt bbObj); static sqInt loadBitBltFromwarping(sqInt bbObj, sqInt aBool); static sqInt loadBitBltSourceForm(void); static sqInt loadColorMap(void); static void * loadColorMapShiftOrMaskFrom(sqInt mapOop); static sqInt loadHalftoneForm(void); static sqInt loadSurfacePlugin(void); static sqInt loadWarpBltFrom(sqInt bbObj); static sqInt lockSurfaces(void); static sqInt mapPixelflags(sqInt sourcePixel, sqInt mapperFlags); static sqInt mergewith(sqInt sourceWord, sqInt destinationWord); EXPORT(sqInt) moduleUnloaded(char *aModuleName); static sqInt msg(char *s); static sqInt OLDrgbDiffwith(sqInt sourceWord, sqInt destinationWord); static sqInt OLDtallyIntoMapwith(sqInt sourceWord, sqInt destinationWord); static sqInt partitionedAddtonBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts); static sqInt partitionedANDtonBitsnPartitions(sqInt word1, sqInt word2, sqInt nBits, sqInt nParts); static sqInt partitionedMaxwithnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts); static sqInt partitionedMinwithnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts); static sqInt partitionedMulwithnBitsnPartitions(sqInt word1, sqInt word2, sqInt nBits, sqInt nParts); static sqInt partitionedSubfromnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts); static sqInt performCopyLoop(void); static sqInt pickSourcePixelsflagssrcMaskdestMasksrcShiftIncdstShiftInc(sqInt nPixels, sqInt mapperFlags, sqInt srcMask, sqInt dstMask, sqInt srcShiftInc, sqInt dstShiftInc); static sqInt pickWarpPixelAtXy(sqInt xx, sqInt yy); static sqInt pixClearwith(sqInt sourceWord, sqInt destinationWord); static sqInt pixMaskwith(sqInt sourceWord, sqInt destinationWord); static sqInt pixPaintwith(sqInt sourceWord, sqInt destinationWord); static sqInt pixSwapwith(sqInt sourceWord, sqInt destWord); EXPORT(sqInt) primitiveCopyBits(void); EXPORT(sqInt) primitiveDisplayString(void); EXPORT(sqInt) primitiveDrawLoop(void); EXPORT(sqInt) primitiveWarpBits(void); static sqInt queryDestSurface(sqInt handle); static sqInt querySourceSurface(sqInt handle); static sqInt rgbAddwith(sqInt sourceWord, sqInt destinationWord); static sqInt rgbDiffwith(sqInt sourceWord, sqInt destinationWord); static sqInt rgbMap16To32(sqInt sourcePixel); static sqInt rgbMap32To32(sqInt sourcePixel); static sqInt rgbMapPixelflags(sqInt sourcePixel, sqInt mapperFlags); static sqInt rgbMapfromto(sqInt sourcePixel, sqInt nBitsIn, sqInt nBitsOut); static sqInt rgbMaxwith(sqInt sourceWord, sqInt destinationWord); static sqInt rgbMinInvertwith(sqInt wordToInvert, sqInt destinationWord); static sqInt rgbMinwith(sqInt sourceWord, sqInt destinationWord); static sqInt rgbMulwith(sqInt sourceWord, sqInt destinationWord); static sqInt rgbSubwith(sqInt sourceWord, sqInt destinationWord); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt setupColorMasks(void); static sqInt setupColorMasksFromto(sqInt srcBits, sqInt targetBits); static sqInt showDisplayBits(void); static sqInt sourceSkewAndPointerInit(void); static sqInt sourceWordwith(sqInt sourceWord, sqInt destinationWord); static sqInt srcLongAt(sqInt idx); static sqInt subWordwith(sqInt sourceWord, sqInt destinationWord); static sqInt tallyIntoMapwith(sqInt sourceWord, sqInt destinationWord); static sqInt tallyMapAt(sqInt idx); static sqInt tallyMapAtput(sqInt idx, sqInt value); static sqInt tryCopyingBitsQuickly(void); static sqInt unlockSurfaces(void); static sqInt warpBits(void); static sqInt warpLoop(void); static sqInt warpLoopSetup(void); static sqInt warpPickSmoothPixelsxDeltahyDeltahxDeltavyDeltavsourceMapsmoothingdstShiftInc(sqInt nPixels, sqInt xDeltah, sqInt yDeltah, sqInt xDeltav, sqInt yDeltav, sqInt sourceMap, sqInt n, sqInt dstShiftInc); static sqInt warpPickSourcePixelsxDeltahyDeltahxDeltavyDeltavdstShiftIncflags(sqInt nPixels, sqInt xDeltah, sqInt yDeltah, sqInt xDeltav, sqInt yDeltav, sqInt dstShiftInc, sqInt mapperFlags); /*** Variables ***/ static sqInt affectedB; static sqInt affectedL; static sqInt affectedR; static sqInt affectedT; static sqInt bbH; static sqInt bbW; static sqInt bitBltOop; static sqInt bitCount; static sqInt clipHeight; static sqInt clipWidth; static sqInt clipX; static sqInt clipY; static sqInt cmBitsPerColor; static sqInt cmFlags; static unsigned int * cmLookupTable; static sqInt cmMask; static unsigned int * cmMaskTable; static int * cmShiftTable; static sqInt combinationRule; static sqInt destBits; static sqInt destBitsOop_xxx_dmu; static sqInt destDelta; static sqInt destDepth; static sqInt destForm; static sqInt destHeight; static sqInt destIndex; static sqInt destMask; static sqInt destMSB; static sqInt destPitch; static sqInt destPPW; static sqInt destWidth; static sqInt destX; static sqInt destY; static unsigned char dither8Lookup[4096]; static const int ditherMatrix4x4[16] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 }; static const int ditherThresholds16[8] = { 0, 2, 4, 6, 8, 12, 14, 16 }; static const int ditherValues16[32] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; static sqInt dstBitShift; static sqInt dx; static sqInt dy; static sqInt halftoneBase; static sqInt halftoneForm; static sqInt halftoneHeight; static sqInt hasSurfaceLock; static sqInt hDir; static sqInt height; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static sqInt isWarping; static void * lockSurfaceFn; static sqInt mask1; static sqInt mask2; static int maskTable[33] = { 0, 1, 3, 0, 15, 31, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 }; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "BitBltPlugin VMMaker-oscog.dtl.57 (i)" #else "BitBltPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static sqInt noHalftone; static sqInt noSource; static sqInt nWords; static void *opTable[42]; static sqInt preload; static void * querySurfaceFn; static sqInt skew; static sqInt sourceAlpha; static sqInt sourceBits; static sqInt sourceBitsOop_xxx_dmu; static sqInt sourceDelta; static sqInt sourceDepth; static sqInt sourceForm; static sqInt sourceHeight; static sqInt sourceIndex; static sqInt sourceMSB; static sqInt sourcePitch; static sqInt sourcePPW; static sqInt sourceWidth; static sqInt sourceX; static sqInt sourceY; static sqInt srcBitShift; static sqInt sx; static sqInt sy; static void * unlockSurfaceFn; static sqInt vDir; static sqInt warpAlignMask; static sqInt warpAlignShift; static int warpBitShiftTable[32]; static sqInt warpSrcMask; static sqInt warpSrcShift; static sqInt width; static sqInt addWordwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord + destinationWord; } static sqInt affectedBottom(void) { return affectedB; } static sqInt affectedLeft(void) { return affectedL; } static sqInt affectedRight(void) { return affectedR; } static sqInt affectedTop(void) { return affectedT; } static sqInt alphaBlendConstwith(sqInt sourceWord, sqInt destinationWord) { return alphaBlendConstwithpaintMode(sourceWord, destinationWord, 0); } /* Blend sourceWord with destinationWord using a constant alpha. Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0. The blend produced is alpha*source + (1.0-alpha)*dest, with the computation being performed independently on each color component. This function could eventually blend into any depth destination, using the same color averaging and mapping as warpBlt. paintMode = true means do nothing if the source pixel value is zero. */ /* This first implementation works with dest depths of 16 and 32 bits only. Normal color mapping will allow sources of lower depths in this case, and results can be mapped directly by truncation, so no extra color maps are needed. To allow storing into any depth will require subsequent addition of two other colormaps, as is the case with WarpBlt. */ static sqInt alphaBlendConstwithpaintMode(sqInt sourceWord, sqInt destinationWord, sqInt paintMode) { sqInt bitsPerColor; sqInt blend; sqInt destPixVal; sqInt destShifted; sqInt i; sqInt j; sqInt maskShifted; sqInt pixBlend; sqInt pixMask; sqInt result; sqInt rgbMask; sqInt shift; sqInt sourcePixVal; sqInt sourceShifted; sqInt unAlpha; if (destDepth < 16) { return destinationWord; } unAlpha = 255 - sourceAlpha; pixMask = maskTable[destDepth]; if (destDepth == 16) { bitsPerColor = 5; } else { bitsPerColor = 8; } rgbMask = (1 << bitsPerColor) - 1; maskShifted = destMask; destShifted = destinationWord; sourceShifted = sourceWord; result = destinationWord; if (destPPW == 1) { if (!(paintMode && (sourceWord == 0))) { /* 32bpp blends include alpha */ /* painting a transparent pixel */ result = 0; for (i = 1; i <= 4; i += 1) { shift = (i - 1) * 8; blend = ((((((((usqInt) sourceWord) >> shift) & rgbMask) * sourceAlpha) + (((((usqInt) destinationWord) >> shift) & rgbMask) * unAlpha)) + 254) / 255) & rgbMask; result = result | (blend << shift); } } } else { for (j = 1; j <= destPPW; j += 1) { sourcePixVal = sourceShifted & pixMask; if (!(((maskShifted & pixMask) == 0) || (paintMode && (sourcePixVal == 0)))) { destPixVal = destShifted & pixMask; pixBlend = 0; for (i = 1; i <= 3; i += 1) { shift = (i - 1) * bitsPerColor; blend = ((((((((usqInt) sourcePixVal) >> shift) & rgbMask) * sourceAlpha) + (((((usqInt) destPixVal) >> shift) & rgbMask) * unAlpha)) + 254) / 255) & rgbMask; pixBlend = pixBlend | (blend << shift); } if (destDepth == 16) { result = (result & (~(pixMask << ((j - 1) * 16)))) | (pixBlend << ((j - 1) * 16)); } else { result = pixBlend; } } maskShifted = ((usqInt) maskShifted) >> destDepth; sourceShifted = ((usqInt) sourceShifted) >> destDepth; destShifted = ((usqInt) destShifted) >> destDepth; } } return result; } /* Blend sourceWord with destinationWord using the alpha value from sourceWord. Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0. In contrast to alphaBlend:with: the color produced is srcColor + (1-srcAlpha) * dstColor e.g., it is assumed that the source color is already scaled. */ static sqInt alphaBlendScaledwith(sqInt sourceWord, sqInt destinationWord) { sqInt a; sqInt b; sqInt dstMask; sqInt g; sqInt r; sqInt srcMask; sqInt unAlpha; /* Do NOT inline this into optimized loops */ /* High 8 bits of source pixel */ unAlpha = 255 - (((usqInt) sourceWord) >> 24); dstMask = destinationWord; srcMask = sourceWord; b = (((usqInt) ((dstMask & 255) * unAlpha)) >> 8) + (srcMask & 255); if (b > 255) { b = 255; } dstMask = ((usqInt) dstMask) >> 8; srcMask = ((usqInt) srcMask) >> 8; g = (((usqInt) ((dstMask & 255) * unAlpha)) >> 8) + (srcMask & 255); if (g > 255) { g = 255; } dstMask = ((usqInt) dstMask) >> 8; srcMask = ((usqInt) srcMask) >> 8; r = (((usqInt) ((dstMask & 255) * unAlpha)) >> 8) + (srcMask & 255); if (r > 255) { r = 255; } dstMask = ((usqInt) dstMask) >> 8; srcMask = ((usqInt) srcMask) >> 8; a = (((usqInt) ((dstMask & 255) * unAlpha)) >> 8) + (srcMask & 255); if (a > 255) { a = 255; } return (((((a << 8) + r) << 8) + g) << 8) + b; } /* Blend sourceWord with destinationWord, assuming both are 32-bit pixels. The source is assumed to have 255*alpha in the high 8 bits of each pixel, while the high 8 bits of the destinationWord will be ignored. The blend produced is alpha*source + (1-alpha)*dest, with the computation being performed independently on each color component. The high byte of the result will be 0. */ static sqInt alphaBlendwith(sqInt sourceWord, sqInt destinationWord) { sqInt alpha; sqInt blend; sqInt colorMask; sqInt result; sqInt shift; sqInt unAlpha; /* High 8 bits of source pixel */ alpha = ((usqInt) sourceWord) >> 24; if (alpha == 0) { return destinationWord; } if (alpha == 255) { return sourceWord; } unAlpha = 255 - alpha; colorMask = 255; /* red */ result = 0; shift = 0; blend = ((((((((usqInt) sourceWord) >> shift) & colorMask) * alpha) + (((((usqInt) destinationWord) >> shift) & colorMask) * unAlpha)) + 254) / 255) & colorMask; /* green */ result = result | (blend << shift); shift = 8; blend = ((((((((usqInt) sourceWord) >> shift) & colorMask) * alpha) + (((((usqInt) destinationWord) >> shift) & colorMask) * unAlpha)) + 254) / 255) & colorMask; /* blue */ result = result | (blend << shift); shift = 16; blend = ((((((((usqInt) sourceWord) >> shift) & colorMask) * alpha) + (((((usqInt) destinationWord) >> shift) & colorMask) * unAlpha)) + 254) / 255) & colorMask; /* alpha (pre-multiplied) */ result = result | (blend << shift); shift = 24; blend = ((((alpha * 255) + (((((usqInt) destinationWord) >> shift) & colorMask) * unAlpha)) + 254) / 255) & colorMask; result = result | (blend << shift); return result; } static sqInt alphaPaintConstwith(sqInt sourceWord, sqInt destinationWord) { if (sourceWord == 0) { return destinationWord; } return alphaBlendConstwithpaintMode(sourceWord, destinationWord, 1); } /* This version assumes combinationRule = 34 sourcePixSize = 32 destPixSize = 16 sourceForm ~= destForm. */ static sqInt alphaSourceBlendBits16(void) { sqInt addThreshold; sqInt addThreshold1; sqInt deltaX; sqInt deltaY; sqInt destWord; sqInt ditherBase; sqInt ditherIndex; sqInt ditherThreshold; sqInt dstIndex; sqInt dstMask; sqInt dstValue; sqInt dstValue1; sqInt dstY; sqInt sourceWord; sqInt srcAlpha; sqInt srcIndex; sqInt srcShift; sqInt srcY; /* This particular method should be optimized in itself */ /* So we can pre-decrement */ deltaY = bbH + 1; srcY = sy; dstY = dy; srcShift = (dx & 1) * 16; if (destMSB) { srcShift = 16 - srcShift; } /* This is the outer loop */ mask1 = 65535 << (16 - srcShift); while (((deltaY -= 1)) != 0) { srcIndex = (sourceBits + (srcY * sourcePitch)) + (sx * 4); dstIndex = (destBits + (dstY * destPitch)) + ((((sqInt) dx >> 1)) * 4); ditherBase = (dstY & 3) * 4; /* For pre-increment */ ditherIndex = (sx & 3) - 1; /* So we can pre-decrement */ deltaX = bbW + 1; dstMask = mask1; if (dstMask == 65535) { srcShift = 16; } else { srcShift = 0; } while (((deltaX -= 1)) != 0) { ditherThreshold = ditherMatrix4x4[ditherBase + ((ditherIndex = (ditherIndex + 1) & 3))]; sourceWord = long32AtPointer(srcIndex); srcAlpha = ((usqInt) sourceWord) >> 24; if (srcAlpha == 255) { /* begin dither32To16:threshold: */ /* You bet */ addThreshold = ((usqInt) ditherThreshold << 8); sourceWord = ((((usqInt) (dither8Lookup[addThreshold + ((((usqInt) sourceWord >> 16)) & 255)]) << 10)) + (((usqInt) (dither8Lookup[addThreshold + ((((usqInt) sourceWord >> 8)) & 255)]) << 5))) + (dither8Lookup[addThreshold + (sourceWord & 255)]); if (sourceWord == 0) { sourceWord = 1 << srcShift; } else { sourceWord = sourceWord << srcShift; } /* begin dstLongAt:put:mask: */ dstValue = long32AtPointer(dstIndex); dstValue = dstValue & dstMask; dstValue = dstValue | sourceWord; long32AtPointerput(dstIndex, dstValue); } else { if (!(srcAlpha == 0)) { /* srcAlpha ~= 255 */ /* 0 < srcAlpha < 255 */ /* If we have to mix colors then just copy a single word */ destWord = long32AtPointer(dstIndex); destWord = destWord & (~dstMask); /* Expand from 16 to 32 bit by adding zero bits */ destWord = ((usqInt) destWord) >> srcShift; /* Mix colors */ destWord = ((((usqInt) (destWord & 31744) << 9)) | (((usqInt) (destWord & 992) << 6))) | ((((usqInt) (destWord & 31) << 3)) | 4278190080UL); /* And dither */ sourceWord = alphaBlendScaledwith(sourceWord, destWord); /* begin dither32To16:threshold: */ /* You bet */ addThreshold1 = ((usqInt) ditherThreshold << 8); sourceWord = ((((usqInt) (dither8Lookup[addThreshold1 + ((((usqInt) sourceWord >> 16)) & 255)]) << 10)) + (((usqInt) (dither8Lookup[addThreshold1 + ((((usqInt) sourceWord >> 8)) & 255)]) << 5))) + (dither8Lookup[addThreshold1 + (sourceWord & 255)]); if (sourceWord == 0) { sourceWord = 1 << srcShift; } else { sourceWord = sourceWord << srcShift; } /* begin dstLongAt:put:mask: */ dstValue1 = long32AtPointer(dstIndex); dstValue1 = dstValue1 & dstMask; dstValue1 = dstValue1 | sourceWord; long32AtPointerput(dstIndex, dstValue1); } } srcIndex += 4; if (destMSB) { if (srcShift == 0) { dstIndex += 4; } } else { if (!(srcShift == 0)) { dstIndex += 4; } } /* Toggle between 0 and 16 */ srcShift = srcShift ^ 16; dstMask = ~dstMask; } srcY += 1; dstY += 1; } } /* This version assumes combinationRule = 34 sourcePixSize = destPixSize = 32 sourceForm ~= destForm. Note: The inner loop has been optimized for dealing with the special cases of srcAlpha = 0.0 and srcAlpha = 1.0 */ static sqInt alphaSourceBlendBits32(void) { sqInt deltaX; sqInt deltaY; sqInt destWord; sqInt dstIndex; sqInt dstY; sqInt sourceWord; sqInt srcAlpha; sqInt srcIndex; sqInt srcY; /* This particular method should be optimized in itself */ /* Give the compile a couple of hints */ /* The following should be declared as pointers so the compiler will notice that they're used for accessing memory locations (good to know on an Intel architecture) but then the increments would be different between ST code and C code so must hope the compiler notices what happens (MS Visual C does) */ /* So we can pre-decrement */ deltaY = bbH + 1; srcY = sy; /* This is the outer loop */ dstY = dy; while (((deltaY -= 1)) != 0) { srcIndex = (sourceBits + (srcY * sourcePitch)) + (sx * 4); dstIndex = (destBits + (dstY * destPitch)) + (dx * 4); /* So we can pre-decrement */ /* This is the inner loop */ deltaX = bbW + 1; while (((deltaX -= 1)) != 0) { sourceWord = long32AtPointer(srcIndex); srcAlpha = ((usqInt) sourceWord) >> 24; if (srcAlpha == 255) { long32AtPointerput(dstIndex, sourceWord); srcIndex += 4; /* Now copy as many words as possible with alpha = 255 */ dstIndex += 4; while ((((deltaX -= 1)) != 0) && ((((usqInt) ((sourceWord = long32AtPointer(srcIndex)))) >> 24) == 255)) { long32AtPointerput(dstIndex, sourceWord); srcIndex += 4; dstIndex += 4; } deltaX += 1; } else { if (srcAlpha == 0) { /* srcAlpha ~= 255 */ srcIndex += 4; /* Now skip as many words as possible, */ dstIndex += 4; while ((((deltaX -= 1)) != 0) && ((((usqInt) ((sourceWord = long32AtPointer(srcIndex)))) >> 24) == 0)) { srcIndex += 4; dstIndex += 4; } deltaX += 1; } else { /* 0 < srcAlpha < 255 */ /* If we have to mix colors then just copy a single word */ destWord = long32AtPointer(dstIndex); destWord = alphaBlendScaledwith(sourceWord, destWord); long32AtPointerput(dstIndex, destWord); srcIndex += 4; dstIndex += 4; } } } srcY += 1; dstY += 1; } } /* This version assumes combinationRule = 34 sourcePixSize = 32 destPixSize = 8 sourceForm ~= destForm. Note: This is not real blending since we don't have the source colors available. */ static sqInt alphaSourceBlendBits8(void) { sqInt adjust; sqInt deltaX; sqInt deltaY; sqInt destWord; sqInt dstIndex; sqInt dstMask; sqInt dstValue; sqInt dstY; sqInt mapperFlags; unsigned int *mappingTable; sqInt pv; sqInt sourceWord; sqInt srcAlpha; sqInt srcIndex; sqInt srcShift; sqInt srcY; sqInt val; mappingTable = default8To32Table(); mapperFlags = cmFlags & (~ColorMapNewStyle); /* So we can pre-decrement */ deltaY = bbH + 1; srcY = sy; dstY = dy; mask1 = (dx & 3) * 8; if (destMSB) { mask1 = 24 - mask1; } mask2 = AllOnes ^ (255 << mask1); if ((dx & 1) == 0) { adjust = 0; } else { adjust = 522133279; } if ((dy & 1) == 0) { adjust = adjust ^ 522133279; } while (((deltaY -= 1)) != 0) { adjust = adjust ^ 522133279; srcIndex = (sourceBits + (srcY * sourcePitch)) + (sx * 4); dstIndex = (destBits + (dstY * destPitch)) + ((((sqInt) dx >> 2)) * 4); /* So we can pre-decrement */ deltaX = bbW + 1; srcShift = mask1; /* This is the inner loop */ dstMask = mask2; while (((deltaX -= 1)) != 0) { sourceWord = ((long32AtPointer(srcIndex)) & (~adjust)) + adjust; srcAlpha = ((usqInt) sourceWord) >> 24; if (srcAlpha > 31) { if (srcAlpha < 224) { /* Everything below 31 is transparent */ /* Everything above 224 is opaque */ destWord = long32AtPointer(dstIndex); destWord = destWord & (~dstMask); destWord = ((usqInt) destWord) >> srcShift; destWord = mappingTable[destWord]; sourceWord = alphaBlendScaledwith(sourceWord, destWord); } /* begin mapPixel:flags: */ pv = sourceWord; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourceWord & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourceWord & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourceWord & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourceWord & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourceWord & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourceWord & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourceWord & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourceWord & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourceWord != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } sourceWord = pv; /* Store back */ sourceWord = sourceWord << srcShift; /* begin dstLongAt:put:mask: */ dstValue = long32AtPointer(dstIndex); dstValue = dstValue & dstMask; dstValue = dstValue | sourceWord; long32AtPointerput(dstIndex, dstValue); } srcIndex += 4; if (destMSB) { if (srcShift == 0) { dstIndex += 4; srcShift = 24; dstMask = 16777215; } else { srcShift -= 8; dstMask = (((usqInt) dstMask) >> 8) | 4278190080UL; } } else { if (srcShift == 32) { dstIndex += 4; srcShift = 0; dstMask = 4294967040UL; } else { srcShift += 8; dstMask = (dstMask << 8) | 255; } } adjust = adjust ^ 522133279; } srcY += 1; dstY += 1; } } static sqInt bitAndInvertwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord & (~destinationWord); } static sqInt bitAndwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord & destinationWord; } static sqInt bitInvertAndInvertwith(sqInt sourceWord, sqInt destinationWord) { return (~sourceWord) & (~destinationWord); } static sqInt bitInvertAndwith(sqInt sourceWord, sqInt destinationWord) { return (~sourceWord) & destinationWord; } static sqInt bitInvertDestinationwith(sqInt sourceWord, sqInt destinationWord) { return ~destinationWord; } static sqInt bitInvertOrInvertwith(sqInt sourceWord, sqInt destinationWord) { return (~sourceWord) | (~destinationWord); } static sqInt bitInvertOrwith(sqInt sourceWord, sqInt destinationWord) { return (~sourceWord) | destinationWord; } static sqInt bitInvertSourcewith(sqInt sourceWord, sqInt destinationWord) { return ~sourceWord; } static sqInt bitInvertXorwith(sqInt sourceWord, sqInt destinationWord) { return (~sourceWord) ^ destinationWord; } static sqInt bitOrInvertwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord | (~destinationWord); } static sqInt bitOrwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord | destinationWord; } static sqInt bitXorwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord ^ destinationWord; } /* check for possible overlap of source and destination */ /* ar 10/19/1999: This method requires surfaces to be locked. */ static sqInt checkSourceOverlap(void) { sqInt t; if ((sourceForm == destForm) && (dy >= sy)) { if (dy > sy) { /* have to start at bottom */ vDir = -1; sy = (sy + bbH) - 1; dy = (dy + bbH) - 1; } else { if ((dy == sy) && (dx > sx)) { /* y's are equal, but x's are backward */ hDir = -1; /* start at right */ sx = (sx + bbW) - 1; /* and fix up masks */ dx = (dx + bbW) - 1; if (nWords > 1) { t = mask1; mask1 = mask2; mask2 = t; } } } destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); } } static sqInt clearWordwith(sqInt source, sqInt destination) { return 0; } /* clip and adjust source origin and extent appropriately */ /* first in x */ static sqInt clipRange(void) { if (destX >= clipX) { sx = sourceX; dx = destX; bbW = width; } else { sx = sourceX + (clipX - destX); bbW = width - (clipX - destX); dx = clipX; } if ((dx + bbW) > (clipX + clipWidth)) { bbW -= (dx + bbW) - (clipX + clipWidth); } if (destY >= clipY) { sy = sourceY; dy = destY; bbH = height; } else { sy = (sourceY + clipY) - destY; bbH = height - (clipY - destY); dy = clipY; } if ((dy + bbH) > (clipY + clipHeight)) { bbH -= (dy + bbH) - (clipY + clipHeight); } if (noSource) { return null; } if (sx < 0) { dx -= sx; bbW += sx; sx = 0; } if ((sx + bbW) > sourceWidth) { bbW -= (sx + bbW) - sourceWidth; } if (sy < 0) { dy -= sy; bbH += sy; sy = 0; } if ((sy + bbH) > sourceHeight) { bbH -= (sy + bbH) - sourceHeight; } } /* This function is exported for the Balloon engine */ EXPORT(sqInt) copyBits(void) { sqInt done; sqInt dWid; sqInt dxLowBits; sqInt endBits; sqInt pixPerM1; sqInt pixPerM11; sqInt startBits; sqInt sxLowBits; sqInt t; clipRange(); if ((bbW <= 0) || (bbH <= 0)) { /* zero width or height; noop */ affectedL = affectedR = affectedT = affectedB = 0; return null; } if (!(lockSurfaces())) { return interpreterProxy->primitiveFail(); } /* begin copyBitsLockedAndClipped */ /* begin tryCopyingBitsQuickly */ if (noSource) { done = 0; goto l2; } if (!(combinationRule == 34)) { done = 0; goto l2; } if (!(sourceDepth == 32)) { done = 0; goto l2; } if (sourceForm == destForm) { done = 0; goto l2; } if (destDepth < 8) { done = 0; goto l2; } if ((destDepth == 8) && ((cmFlags & ColorMapPresent) == 0)) { done = 0; goto l2; } if (destDepth == 32) { alphaSourceBlendBits32(); } if (destDepth == 16) { alphaSourceBlendBits16(); } if (destDepth == 8) { alphaSourceBlendBits8(); } affectedL = dx; affectedR = dx + bbW; affectedT = dy; affectedB = dy + bbH; done = 1; l2: /* end tryCopyingBitsQuickly */; if (done) { goto l1; } if ((combinationRule == 30) || (combinationRule == 31)) { if ((interpreterProxy->methodArgumentCount()) == 1) { /* Check and fetch source alpha parameter for alpha blend */ sourceAlpha = interpreterProxy->stackIntegerValue(0); if (!((!(interpreterProxy->failed())) && ((sourceAlpha >= 0) && (sourceAlpha <= 255)))) { interpreterProxy->primitiveFail(); goto l1; } } else { interpreterProxy->primitiveFail(); goto l1; } } /* Choose and perform the actual copy loop. */ bitCount = 0; /* begin performCopyLoop */ /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); if (noSource) { copyLoopNoSource(); } else { /* begin checkSourceOverlap */ if ((sourceForm == destForm) && (dy >= sy)) { if (dy > sy) { /* have to start at bottom */ vDir = -1; sy = (sy + bbH) - 1; dy = (dy + bbH) - 1; } else { if ((dy == sy) && (dx > sx)) { /* y's are equal, but x's are backward */ hDir = -1; /* start at right */ sx = (sx + bbW) - 1; /* and fix up masks */ dx = (dx + bbW) - 1; if (nWords > 1) { t = mask1; mask1 = mask2; mask2 = t; } } } destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); } if ((sourceDepth != destDepth) || ((cmFlags != 0) || (sourceMSB != destMSB))) { copyLoopPixMap(); } else { /* begin sourceSkewAndPointerInit */ /* A mask, assuming power of two */ pixPerM11 = destPPW - 1; sxLowBits = sx & pixPerM11; /* check if need to preload buffer (i.e., two words of source needed for first word of destination) */ dxLowBits = dx & pixPerM11; if (hDir > 0) { /* n Bits stored in 1st word of dest */ dWid = ((bbW < (destPPW - dxLowBits)) ? bbW : (destPPW - dxLowBits)); preload = (sxLowBits + dWid) > pixPerM11; } else { dWid = ((bbW < (dxLowBits + 1)) ? bbW : (dxLowBits + 1)); preload = ((sxLowBits - dWid) + 1) < 0; } if (sourceMSB) { skew = (sxLowBits - dxLowBits) * destDepth; } else { skew = (dxLowBits - sxLowBits) * destDepth; } if (preload) { if (skew < 0) { skew += 32; } else { skew -= 32; } } /* calculate increments from end of 1 line to start of next */ sourceIndex = (sourceBits + (sy * sourcePitch)) + ((sx / (32 / sourceDepth)) * 4); sourceDelta = (sourcePitch * vDir) - (4 * (nWords * hDir)); if (preload) { /* Compensate for extra source word fetched */ sourceDelta -= 4 * hDir; } copyLoop(); } } if ((combinationRule == 22) || (combinationRule == 32)) { /* zero width and height; return the count */ affectedL = affectedR = affectedT = affectedB = 0; } if (hDir > 0) { affectedL = dx; affectedR = dx + bbW; } else { affectedL = (dx - bbW) + 1; affectedR = dx + 1; } if (vDir > 0) { affectedT = dy; affectedB = dy + bbH; } else { affectedT = (dy - bbH) + 1; affectedB = dy + 1; } l1: /* end copyBitsLockedAndClipped */; unlockSurfaces(); } /* Support for the balloon engine. */ EXPORT(sqInt) copyBitsFromtoat(sqInt startX, sqInt stopX, sqInt yValue) { destX = startX; destY = yValue; sourceX = startX; width = stopX - startX; copyBits(); /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); } /* Perform the actual copyBits operation. Assume: Surfaces have been locked and clipping was performed. */ static sqInt copyBitsLockedAndClipped(void) { sqInt done; sqInt dWid; sqInt dxLowBits; sqInt endBits; sqInt pixPerM1; sqInt pixPerM11; sqInt startBits; sqInt sxLowBits; sqInt t; /* begin tryCopyingBitsQuickly */ if (noSource) { done = 0; goto l1; } if (!(combinationRule == 34)) { done = 0; goto l1; } if (!(sourceDepth == 32)) { done = 0; goto l1; } if (sourceForm == destForm) { done = 0; goto l1; } if (destDepth < 8) { done = 0; goto l1; } if ((destDepth == 8) && ((cmFlags & ColorMapPresent) == 0)) { done = 0; goto l1; } if (destDepth == 32) { alphaSourceBlendBits32(); } if (destDepth == 16) { alphaSourceBlendBits16(); } if (destDepth == 8) { alphaSourceBlendBits8(); } affectedL = dx; affectedR = dx + bbW; affectedT = dy; affectedB = dy + bbH; done = 1; l1: /* end tryCopyingBitsQuickly */; if (done) { return null; } if ((combinationRule == 30) || (combinationRule == 31)) { if ((interpreterProxy->methodArgumentCount()) == 1) { /* Check and fetch source alpha parameter for alpha blend */ sourceAlpha = interpreterProxy->stackIntegerValue(0); if (!((!(interpreterProxy->failed())) && ((sourceAlpha >= 0) && (sourceAlpha <= 255)))) { return interpreterProxy->primitiveFail(); } } else { return interpreterProxy->primitiveFail(); } } /* Choose and perform the actual copy loop. */ bitCount = 0; /* begin performCopyLoop */ /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); if (noSource) { copyLoopNoSource(); } else { /* begin checkSourceOverlap */ if ((sourceForm == destForm) && (dy >= sy)) { if (dy > sy) { /* have to start at bottom */ vDir = -1; sy = (sy + bbH) - 1; dy = (dy + bbH) - 1; } else { if ((dy == sy) && (dx > sx)) { /* y's are equal, but x's are backward */ hDir = -1; /* start at right */ sx = (sx + bbW) - 1; /* and fix up masks */ dx = (dx + bbW) - 1; if (nWords > 1) { t = mask1; mask1 = mask2; mask2 = t; } } } destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); } if ((sourceDepth != destDepth) || ((cmFlags != 0) || (sourceMSB != destMSB))) { copyLoopPixMap(); } else { /* begin sourceSkewAndPointerInit */ /* A mask, assuming power of two */ pixPerM11 = destPPW - 1; sxLowBits = sx & pixPerM11; /* check if need to preload buffer (i.e., two words of source needed for first word of destination) */ dxLowBits = dx & pixPerM11; if (hDir > 0) { /* n Bits stored in 1st word of dest */ dWid = ((bbW < (destPPW - dxLowBits)) ? bbW : (destPPW - dxLowBits)); preload = (sxLowBits + dWid) > pixPerM11; } else { dWid = ((bbW < (dxLowBits + 1)) ? bbW : (dxLowBits + 1)); preload = ((sxLowBits - dWid) + 1) < 0; } if (sourceMSB) { skew = (sxLowBits - dxLowBits) * destDepth; } else { skew = (dxLowBits - sxLowBits) * destDepth; } if (preload) { if (skew < 0) { skew += 32; } else { skew -= 32; } } /* calculate increments from end of 1 line to start of next */ sourceIndex = (sourceBits + (sy * sourcePitch)) + ((sx / (32 / sourceDepth)) * 4); sourceDelta = (sourcePitch * vDir) - (4 * (nWords * hDir)); if (preload) { /* Compensate for extra source word fetched */ sourceDelta -= 4 * hDir; } copyLoop(); } } if ((combinationRule == 22) || (combinationRule == 32)) { /* zero width and height; return the count */ affectedL = affectedR = affectedT = affectedB = 0; } if (hDir > 0) { affectedL = dx; affectedR = dx + bbW; } else { affectedL = (dx - bbW) + 1; affectedR = dx + 1; } if (vDir > 0) { affectedT = dy; affectedB = dy + bbH; } else { affectedT = (dy - bbH) + 1; affectedB = dy + 1; } } /* This version of the inner loop assumes noSource = false. */ static sqInt copyLoop(void) { sqInt destWord; sqInt halftoneWord; sqInt hInc; sqInt i; sqInt (*mergeFnwith)(sqInt, sqInt); sqInt mergeWord; sqInt notSkewMask; sqInt prevWord; sqInt skewMask; sqInt skewWord; sqInt thisWord; sqInt unskew; sqInt word; sqInt y; mergeFnwith = ((sqInt (*)(sqInt, sqInt)) (opTable[combinationRule + 1])); mergeFnwith; /* Byte delta */ /* degenerate skew fixed for Sparc. 10/20/96 ikp */ hInc = hDir * 4; if (skew == -32) { skew = unskew = skewMask = 0; } else { if (skew < 0) { unskew = skew + 32; skewMask = AllOnes << (0 - skew); } else { if (skew == 0) { unskew = 0; skewMask = AllOnes; } else { unskew = skew - 32; skewMask = ((usqInt) AllOnes) >> skew; } } } notSkewMask = ~skewMask; if (noHalftone) { halftoneWord = AllOnes; halftoneHeight = 0; } else { halftoneWord = long32AtPointer(halftoneBase + ((0 % halftoneHeight) * 4)); } y = dy; for (i = 1; i <= bbH; i += 1) { if (halftoneHeight > 1) { /* here is the vertical loop */ /* Otherwise, its always the same */ halftoneWord = long32AtPointer(halftoneBase + ((y % halftoneHeight) * 4)); y += vDir; } if (preload) { /* load the 64-bit shifter */ prevWord = long32AtPointer(sourceIndex); sourceIndex += hInc; } else { prevWord = 0; } destMask = mask1; /* pick up next word */ thisWord = long32AtPointer(sourceIndex); sourceIndex += hInc; /* 32-bit rotate */ skewWord = (((unskew < 0) ? ((usqInt) (prevWord & notSkewMask) >> -unskew) : ((usqInt) (prevWord & notSkewMask) << unskew))) | (((skew < 0) ? ((usqInt) (thisWord & skewMask) >> -skew) : ((usqInt) (thisWord & skewMask) << skew))); prevWord = thisWord; destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(skewWord & halftoneWord, destWord); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); /* This central horizontal loop requires no store masking */ destIndex += hInc; destMask = AllOnes; if (combinationRule == 3) { if ((skew == 0) && (halftoneWord == AllOnes)) { if (hDir == -1) { for (word = 2; word <= (nWords - 1); word += 1) { /* Very special inner loop for STORE mode with no skew -- just move words */ /* Woeful patch: revert to older code for hDir = -1 */ thisWord = long32AtPointer(sourceIndex); sourceIndex += hInc; long32AtPointerput(destIndex, thisWord); destIndex += hInc; } } else { for (word = 2; word <= (nWords - 1); word += 1) { long32AtPointerput(destIndex, prevWord); destIndex += hInc; prevWord = long32AtPointer(sourceIndex); sourceIndex += hInc; } } } else { for (word = 2; word <= (nWords - 1); word += 1) { /* Special inner loop for STORE mode -- no need to call merge */ thisWord = long32AtPointer(sourceIndex); sourceIndex += hInc; /* 32-bit rotate */ skewWord = (((unskew < 0) ? ((usqInt) (prevWord & notSkewMask) >> -unskew) : ((usqInt) (prevWord & notSkewMask) << unskew))) | (((skew < 0) ? ((usqInt) (thisWord & skewMask) >> -skew) : ((usqInt) (thisWord & skewMask) << skew))); prevWord = thisWord; long32AtPointerput(destIndex, skewWord & halftoneWord); destIndex += hInc; } } } else { for (word = 2; word <= (nWords - 1); word += 1) { /* Normal inner loop does merge: */ /* pick up next word */ thisWord = long32AtPointer(sourceIndex); sourceIndex += hInc; /* 32-bit rotate */ skewWord = (((unskew < 0) ? ((usqInt) (prevWord & notSkewMask) >> -unskew) : ((usqInt) (prevWord & notSkewMask) << unskew))) | (((skew < 0) ? ((usqInt) (thisWord & skewMask) >> -skew) : ((usqInt) (thisWord & skewMask) << skew))); prevWord = thisWord; mergeWord = mergeFnwith(skewWord & halftoneWord, long32AtPointer(destIndex)); long32AtPointerput(destIndex, mergeWord); destIndex += hInc; } } if (nWords > 1) { destMask = mask2; /* pick up next word */ thisWord = long32AtPointer(sourceIndex); sourceIndex += hInc; /* 32-bit rotate */ skewWord = (((unskew < 0) ? ((usqInt) (prevWord & notSkewMask) >> -unskew) : ((usqInt) (prevWord & notSkewMask) << unskew))) | (((skew < 0) ? ((usqInt) (thisWord & skewMask) >> -skew) : ((usqInt) (thisWord & skewMask) << skew))); destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(skewWord & halftoneWord, destWord); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); destIndex += hInc; } sourceIndex += sourceDelta; destIndex += destDelta; } } /* Faster copyLoop when source not used. hDir and vDir are both positive, and perload and skew are unused */ static sqInt copyLoopNoSource(void) { sqInt destWord; sqInt halftoneWord; sqInt i; sqInt (*mergeFnwith)(sqInt, sqInt); sqInt mergeWord; sqInt word; mergeFnwith = ((sqInt (*)(sqInt, sqInt)) (opTable[combinationRule + 1])); mergeFnwith; for (i = 1; i <= bbH; i += 1) { if (noHalftone) { /* here is the vertical loop */ halftoneWord = AllOnes; } else { halftoneWord = long32AtPointer(halftoneBase + ((((dy + i) - 1) % halftoneHeight) * 4)); } destMask = mask1; destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(halftoneWord, destWord); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); /* This central horizontal loop requires no store masking */ destIndex += 4; destMask = AllOnes; if (combinationRule == 3) { /* Special inner loop for STORE */ destWord = halftoneWord; for (word = 2; word <= (nWords - 1); word += 1) { long32AtPointerput(destIndex, destWord); destIndex += 4; } } else { for (word = 2; word <= (nWords - 1); word += 1) { /* Normal inner loop does merge */ /* Normal inner loop does merge */ destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(halftoneWord, destWord); long32AtPointerput(destIndex, mergeWord); destIndex += 4; } } if (nWords > 1) { destMask = mask2; destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(halftoneWord, destWord); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); destIndex += 4; } destIndex += destDelta; } } /* This version of the inner loop maps source pixels to a destination form with different depth. Because it is already unweildy, the loop is not unrolled as in the other versions. Preload, skew and skewMask are all overlooked, since pickSourcePixels delivers its destination word already properly aligned. Note that pickSourcePixels could be copied in-line at the top of the horizontal loop, and some of its inits moved out of the loop. */ /* ar 12/7/1999: The loop has been rewritten to use only one pickSourcePixels call. The idea is that the call itself could be inlined. If we decide not to inline pickSourcePixels we could optimize the loop instead. */ static sqInt copyLoopPixMap(void) { sqInt destPix; sqInt destPixMask; sqInt destWord; sqInt destWord1; sqInt dstShift; sqInt dstShift1; sqInt dstShiftInc; sqInt dstShiftLeft; sqInt endBits; sqInt halftoneWord; sqInt i; sqInt idx; sqInt idx1; sqInt mapperFlags; sqInt (*mergeFnwith)(sqInt, sqInt); sqInt mergeWord; sqInt nPix; sqInt nPix1; sqInt nSourceIncs; sqInt pv; sqInt scrStartBits; sqInt skewWord; sqInt sourcePix; sqInt sourcePixMask; sqInt sourceWord; sqInt srcShift; sqInt srcShift1; sqInt srcShiftInc; sqInt startBits; sqInt val; sqInt words; mergeFnwith = ((sqInt (*)(sqInt, sqInt)) (opTable[combinationRule + 1])); mergeFnwith; sourcePPW = 32 / sourceDepth; sourcePixMask = maskTable[sourceDepth]; destPixMask = maskTable[destDepth]; mapperFlags = cmFlags & (~ColorMapNewStyle); sourceIndex = (sourceBits + (sy * sourcePitch)) + ((sx / sourcePPW) * 4); scrStartBits = sourcePPW - (sx & (sourcePPW - 1)); if (bbW < scrStartBits) { nSourceIncs = 0; } else { nSourceIncs = ((bbW - scrStartBits) / sourcePPW) + 1; } /* Note following two items were already calculated in destmask setup! */ sourceDelta = sourcePitch - (nSourceIncs * 4); startBits = destPPW - (dx & (destPPW - 1)); endBits = (((dx + bbW) - 1) & (destPPW - 1)) + 1; if (bbW < startBits) { startBits = bbW; } srcShift = (sx & (sourcePPW - 1)) * sourceDepth; dstShift = (dx & (destPPW - 1)) * destDepth; srcShiftInc = sourceDepth; dstShiftInc = destDepth; dstShiftLeft = 0; if (sourceMSB) { srcShift = (32 - sourceDepth) - srcShift; srcShiftInc = 0 - srcShiftInc; } if (destMSB) { dstShift = (32 - destDepth) - dstShift; dstShiftInc = 0 - dstShiftInc; dstShiftLeft = 32 - destDepth; } for (i = 1; i <= bbH; i += 1) { if (noHalftone) { /* here is the vertical loop */ /* *** is it possible at all that noHalftone == false? *** */ halftoneWord = AllOnes; } else { halftoneWord = long32AtPointer(halftoneBase + ((((dy + i) - 1) % halftoneHeight) * 4)); } srcBitShift = srcShift; dstBitShift = dstShift; destMask = mask1; /* Here is the horizontal loop... */ nPix = startBits; words = nWords; do { /* begin pickSourcePixels:flags:srcMask:destMask:srcShiftInc:dstShiftInc: */ /* oh please */ sourceWord = long32AtPointer(sourceIndex); destWord1 = 0; /* Hint: Keep in register */ srcShift1 = srcBitShift; /* Hint: Keep in register */ dstShift1 = dstBitShift; /* always > 0 so we can use do { } while(--nPix); */ nPix1 = nPix; if (mapperFlags == (ColorMapPresent | ColorMapIndexedPart)) { do { /* a little optimization for (pretty crucial) blits using indexed lookups only */ /* grab, colormap and mix in pixel */ sourcePix = (((usqInt) sourceWord) >> srcShift1) & sourcePixMask; destPix = cmLookupTable[sourcePix & cmMask]; /* adjust dest pix index */ destWord1 = destWord1 | ((destPix & destPixMask) << dstShift1); /* adjust source pix index */ dstShift1 += dstShiftInc; if (!((((srcShift1 += srcShiftInc)) & 4294967264UL) == 0)) { if (sourceMSB) { srcShift1 += 32; } else { srcShift1 -= 32; } /* begin srcLongAt: */ idx = sourceIndex += 4; sourceWord = long32AtPointer(idx); } } while(!(((nPix1 -= 1)) == 0)); } else { do { /* grab, colormap and mix in pixel */ sourcePix = (((usqInt) sourceWord) >> srcShift1) & sourcePixMask; /* begin mapPixel:flags: */ pv = sourcePix; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePix & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePix & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePix & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePix & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourcePix != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } destPix = pv; /* adjust dest pix index */ destWord1 = destWord1 | ((destPix & destPixMask) << dstShift1); /* adjust source pix index */ dstShift1 += dstShiftInc; if (!((((srcShift1 += srcShiftInc)) & 4294967264UL) == 0)) { if (sourceMSB) { srcShift1 += 32; } else { srcShift1 -= 32; } /* begin srcLongAt: */ idx1 = sourceIndex += 4; sourceWord = long32AtPointer(idx1); } } while(!(((nPix1 -= 1)) == 0)); } /* Store back */ srcBitShift = srcShift1; skewWord = destWord1; dstBitShift = dstShiftLeft; if (destMask == AllOnes) { /* avoid read-modify-write */ mergeWord = mergeFnwith(skewWord & halftoneWord, long32AtPointer(destIndex)); long32AtPointerput(destIndex, destMask & mergeWord); } else { /* General version using dest masking */ destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(skewWord & halftoneWord, destWord & destMask); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); } destIndex += 4; if (words == 2) { /* e.g., is the next word the last word? */ /* set mask for last word in this row */ destMask = mask2; nPix = endBits; } else { /* use fullword mask for inner loop */ destMask = AllOnes; nPix = destPPW; } } while(!(((words -= 1)) == 0)); sourceIndex += sourceDelta; destIndex += destDelta; } } /* Return the default translation table from 1..8 bit indexed colors to 32bit */ /* The table has been generated by the following statements */ /* | pvs hex | String streamContents:[:s| s nextPutAll:'static unsigned int theTable[256] = { '. pvs := (Color colorMapIfNeededFrom: 8 to: 32) asArray. 1 to: pvs size do:[:i| i > 1 ifTrue:[s nextPutAll:', ']. (i-1 \\ 8) = 0 ifTrue:[s cr]. s nextPutAll:'0x'. hex := (pvs at: i) printStringBase: 16. s nextPutAll: (hex copyFrom: 4 to: hex size). ]. s nextPutAll:'};'. ]. */ static unsigned int * default8To32Table(void) { static unsigned int theTable[256] = { 0x0, 0xFF000001, 0xFFFFFFFF, 0xFF808080, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFF00FFFF, 0xFFFFFF00, 0xFFFF00FF, 0xFF202020, 0xFF404040, 0xFF606060, 0xFF9F9F9F, 0xFFBFBFBF, 0xFFDFDFDF, 0xFF080808, 0xFF101010, 0xFF181818, 0xFF282828, 0xFF303030, 0xFF383838, 0xFF484848, 0xFF505050, 0xFF585858, 0xFF686868, 0xFF707070, 0xFF787878, 0xFF878787, 0xFF8F8F8F, 0xFF979797, 0xFFA7A7A7, 0xFFAFAFAF, 0xFFB7B7B7, 0xFFC7C7C7, 0xFFCFCFCF, 0xFFD7D7D7, 0xFFE7E7E7, 0xFFEFEFEF, 0xFFF7F7F7, 0xFF000001, 0xFF003300, 0xFF006600, 0xFF009900, 0xFF00CC00, 0xFF00FF00, 0xFF000033, 0xFF003333, 0xFF006633, 0xFF009933, 0xFF00CC33, 0xFF00FF33, 0xFF000066, 0xFF003366, 0xFF006666, 0xFF009966, 0xFF00CC66, 0xFF00FF66, 0xFF000099, 0xFF003399, 0xFF006699, 0xFF009999, 0xFF00CC99, 0xFF00FF99, 0xFF0000CC, 0xFF0033CC, 0xFF0066CC, 0xFF0099CC, 0xFF00CCCC, 0xFF00FFCC, 0xFF0000FF, 0xFF0033FF, 0xFF0066FF, 0xFF0099FF, 0xFF00CCFF, 0xFF00FFFF, 0xFF330000, 0xFF333300, 0xFF336600, 0xFF339900, 0xFF33CC00, 0xFF33FF00, 0xFF330033, 0xFF333333, 0xFF336633, 0xFF339933, 0xFF33CC33, 0xFF33FF33, 0xFF330066, 0xFF333366, 0xFF336666, 0xFF339966, 0xFF33CC66, 0xFF33FF66, 0xFF330099, 0xFF333399, 0xFF336699, 0xFF339999, 0xFF33CC99, 0xFF33FF99, 0xFF3300CC, 0xFF3333CC, 0xFF3366CC, 0xFF3399CC, 0xFF33CCCC, 0xFF33FFCC, 0xFF3300FF, 0xFF3333FF, 0xFF3366FF, 0xFF3399FF, 0xFF33CCFF, 0xFF33FFFF, 0xFF660000, 0xFF663300, 0xFF666600, 0xFF669900, 0xFF66CC00, 0xFF66FF00, 0xFF660033, 0xFF663333, 0xFF666633, 0xFF669933, 0xFF66CC33, 0xFF66FF33, 0xFF660066, 0xFF663366, 0xFF666666, 0xFF669966, 0xFF66CC66, 0xFF66FF66, 0xFF660099, 0xFF663399, 0xFF666699, 0xFF669999, 0xFF66CC99, 0xFF66FF99, 0xFF6600CC, 0xFF6633CC, 0xFF6666CC, 0xFF6699CC, 0xFF66CCCC, 0xFF66FFCC, 0xFF6600FF, 0xFF6633FF, 0xFF6666FF, 0xFF6699FF, 0xFF66CCFF, 0xFF66FFFF, 0xFF990000, 0xFF993300, 0xFF996600, 0xFF999900, 0xFF99CC00, 0xFF99FF00, 0xFF990033, 0xFF993333, 0xFF996633, 0xFF999933, 0xFF99CC33, 0xFF99FF33, 0xFF990066, 0xFF993366, 0xFF996666, 0xFF999966, 0xFF99CC66, 0xFF99FF66, 0xFF990099, 0xFF993399, 0xFF996699, 0xFF999999, 0xFF99CC99, 0xFF99FF99, 0xFF9900CC, 0xFF9933CC, 0xFF9966CC, 0xFF9999CC, 0xFF99CCCC, 0xFF99FFCC, 0xFF9900FF, 0xFF9933FF, 0xFF9966FF, 0xFF9999FF, 0xFF99CCFF, 0xFF99FFFF, 0xFFCC0000, 0xFFCC3300, 0xFFCC6600, 0xFFCC9900, 0xFFCCCC00, 0xFFCCFF00, 0xFFCC0033, 0xFFCC3333, 0xFFCC6633, 0xFFCC9933, 0xFFCCCC33, 0xFFCCFF33, 0xFFCC0066, 0xFFCC3366, 0xFFCC6666, 0xFFCC9966, 0xFFCCCC66, 0xFFCCFF66, 0xFFCC0099, 0xFFCC3399, 0xFFCC6699, 0xFFCC9999, 0xFFCCCC99, 0xFFCCFF99, 0xFFCC00CC, 0xFFCC33CC, 0xFFCC66CC, 0xFFCC99CC, 0xFFCCCCCC, 0xFFCCFFCC, 0xFFCC00FF, 0xFFCC33FF, 0xFFCC66FF, 0xFFCC99FF, 0xFFCCCCFF, 0xFFCCFFFF, 0xFFFF0000, 0xFFFF3300, 0xFFFF6600, 0xFFFF9900, 0xFFFFCC00, 0xFFFFFF00, 0xFFFF0033, 0xFFFF3333, 0xFFFF6633, 0xFFFF9933, 0xFFFFCC33, 0xFFFFFF33, 0xFFFF0066, 0xFFFF3366, 0xFFFF6666, 0xFFFF9966, 0xFFFFCC66, 0xFFFFFF66, 0xFFFF0099, 0xFFFF3399, 0xFFFF6699, 0xFFFF9999, 0xFFFFCC99, 0xFFFFFF99, 0xFFFF00CC, 0xFFFF33CC, 0xFFFF66CC, 0xFFFF99CC, 0xFFFFCCCC, 0xFFFFFFCC, 0xFFFF00FF, 0xFFFF33FF, 0xFFFF66FF, 0xFFFF99FF, 0xFFFFCCFF, 0xFFFFFFFF};; return theTable; } /* Utility routine for computing Warp increments. */ static sqInt deltaFromtonSteps(sqInt x1, sqInt x2, sqInt n) { if (x2 > x1) { return (((x2 - x1) + FixedPt1) / (n + 1)) + 1; } else { if (x2 == x1) { return 0; } return 0 - ((((x1 - x2) + FixedPt1) / (n + 1)) + 1); } } static sqInt destinationWordwith(sqInt sourceWord, sqInt destinationWord) { return destinationWord; } /* Compute masks for left and right destination words */ static sqInt destMaskAndPointerInit(void) { sqInt endBits; sqInt pixPerM1; sqInt startBits; /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); } /* Dither the given 32bit word to 16 bit. Ignore alpha. */ static sqInt dither32To16threshold(sqInt srcWord, sqInt ditherValue) { sqInt addThreshold; /* You bet */ addThreshold = ((usqInt) ditherValue << 8); return ((((usqInt) (dither8Lookup[addThreshold + ((((usqInt) srcWord >> 16)) & 255)]) << 10)) + (((usqInt) (dither8Lookup[addThreshold + ((((usqInt) srcWord >> 8)) & 255)]) << 5))) + (dither8Lookup[addThreshold + (srcWord & 255)]); } /* This is the primitive implementation of the line-drawing loop. See the comments in BitBlt>>drawLoopX:Y: */ static sqInt drawLoopXY(sqInt xDelta, sqInt yDelta) { sqInt affB; sqInt affL; sqInt affR; sqInt affT; sqInt dx1; sqInt dy1; sqInt i; sqInt P; sqInt px; sqInt py; if (xDelta > 0) { dx1 = 1; } else { if (xDelta == 0) { dx1 = 0; } else { dx1 = -1; } } if (yDelta > 0) { dy1 = 1; } else { if (yDelta == 0) { dy1 = 0; } else { dy1 = -1; } } px = abs(yDelta); py = abs(xDelta); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; if (py > px) { /* more horizontal */ P = ((sqInt) py >> 1); for (i = 1; i <= py; i += 1) { destX += dx1; if (((P -= px)) < 0) { destY += dy1; P += py; } if (i < py) { copyBits(); if (interpreterProxy->failed()) { return null; } if ((affectedL < affectedR) && (affectedT < affectedB)) { /* Affected rectangle grows along the line */ affL = ((affL < affectedL) ? affL : affectedL); affR = ((affR < affectedR) ? affectedR : affR); affT = ((affT < affectedT) ? affT : affectedT); affB = ((affB < affectedB) ? affectedB : affB); if (((affR - affL) * (affB - affT)) > 4000) { /* If affected rectangle gets large, update it in chunks */ affectedL = affL; affectedR = affR; affectedT = affT; affectedB = affB; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; } } } } } else { /* more vertical */ P = ((sqInt) px >> 1); for (i = 1; i <= px; i += 1) { destY += dy1; if (((P -= py)) < 0) { destX += dx1; P += px; } if (i < px) { copyBits(); if (interpreterProxy->failed()) { return null; } if ((affectedL < affectedR) && (affectedT < affectedB)) { /* Affected rectangle grows along the line */ affL = ((affL < affectedL) ? affL : affectedL); affR = ((affR < affectedR) ? affectedR : affR); affT = ((affT < affectedT) ? affT : affectedT); affB = ((affB < affectedB) ? affectedB : affB); if (((affR - affL) * (affB - affT)) > 4000) { /* If affected rectangle gets large, update it in chunks */ affectedL = affL; affectedR = affR; affectedT = affT; affectedB = affB; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; } } } } } affectedL = affL; affectedR = affR; affectedT = affT; /* store destX, Y back */ affectedB = affB; interpreterProxy->storeIntegerofObjectwithValue(BBDestXIndex, bitBltOop, destX); interpreterProxy->storeIntegerofObjectwithValue(BBDestYIndex, bitBltOop, destY); } static sqInt dstLongAt(sqInt idx) { return long32AtPointer(idx); } static sqInt dstLongAtput(sqInt idx, sqInt value) { return long32AtPointerput(idx, value); } /* Store the given value back into destination form, using dstMask to mask out the bits to be modified. This is an essiantial read-modify-write operation on the destination form. */ static sqInt dstLongAtputmask(sqInt idx, sqInt srcValue, sqInt dstMask) { sqInt dstValue; dstValue = long32AtPointer(idx); dstValue = dstValue & dstMask; dstValue = dstValue | srcValue; long32AtPointerput(idx, dstValue); } /* Dither the given 32bit word to 16 bit. Ignore alpha. */ static sqInt expensiveDither32To16threshold(sqInt srcWord, sqInt ditherValue) { sqInt out; sqInt pv; sqInt threshold; sqInt value; /* You bet */ pv = srcWord & 255; threshold = ditherThresholds16[pv & 7]; value = ditherValues16[((usqInt) pv >> 3)]; if (ditherValue < threshold) { out = value + 1; } else { out = value; } pv = (((usqInt) srcWord >> 8)) & 255; threshold = ditherThresholds16[pv & 7]; value = ditherValues16[((usqInt) pv >> 3)]; if (ditherValue < threshold) { out = out | (((usqInt) (value + 1) << 5)); } else { out = out | (((usqInt) value << 5)); } pv = (((usqInt) srcWord >> 16)) & 255; threshold = ditherThresholds16[pv & 7]; value = ditherValues16[((usqInt) pv >> 3)]; if (ditherValue < threshold) { out = out | (((usqInt) (value + 1) << 10)); } else { out = out | (((usqInt) value << 10)); } return out; } /* Return the integer value of the given field of the given object. If the field contains a Float, truncate it and return its integral part. Fail if the given field does not contain a small integer or Float, or if the truncated Float is out of the range of small integers. */ static sqInt fetchIntOrFloatofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt fieldOop; double floatValue; fieldOop = interpreterProxy->fetchPointerofObject(fieldIndex, objectPointer); // OK xxx_dmu if ((fieldOop & 1)) { return (fieldOop >> 1); } floatValue = interpreterProxy->floatValueOf(fieldOop); if (!((-2.147483648e9 <= floatValue) && (floatValue <= 2.147483647e9))) { interpreterProxy->primitiveFail(); return 0; } return ((sqInt)floatValue); } /* Return the integer value of the given field of the given object. If the field contains a Float, truncate it and return its integral part. Fail if the given field does not contain a small integer or Float, or if the truncated Float is out of the range of small integers. */ static sqInt fetchIntOrFloatofObjectifNil(sqInt fieldIndex, sqInt objectPointer, sqInt defaultValue) { sqInt fieldOop; double floatValue; fieldOop = interpreterProxy->fetchPointerofObject(fieldIndex, objectPointer); // OK xxx_dmu if ((fieldOop & 1)) { return (fieldOop >> 1); } if (fieldOop == (interpreterProxy->nilObject())) { return defaultValue; } floatValue = interpreterProxy->floatValueOf(fieldOop); if (!((-2.147483648e9 <= floatValue) && (floatValue <= 2.147483647e9))) { interpreterProxy->primitiveFail(); return 0; } return ((sqInt)floatValue); } /* For any non-zero pixel value in destinationWord with zero alpha channel take the alpha from sourceWord and fill it in. Intended for fixing alpha channels left at zero during 16->32 bpp conversions. */ static sqInt fixAlphawith(sqInt sourceWord, sqInt destinationWord) { if (!(destDepth == 32)) { return destinationWord; } if (destinationWord == 0) { return 0; } if (!((destinationWord & 4278190080UL) == 0)) { return destinationWord; } return destinationWord | (sourceWord & 4278190080UL); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } /* Return a value from the halftone pattern. */ static sqInt halftoneAt(sqInt idx) { return long32AtPointer(halftoneBase + ((idx % halftoneHeight) * 4)); } static sqInt halt(void) { ; return 0; } static sqInt ignoreSourceOrHalftone(sqInt formPointer) { if (formPointer == (interpreterProxy->nilObject())) { return 1; } if (combinationRule == 0) { return 1; } if (combinationRule == 5) { return 1; } if (combinationRule == 10) { return 1; } if (combinationRule == 15) { return 1; } return 0; } static sqInt initBBOpTable(void) { opTable[0+1] = (void *)clearWordwith; opTable[1+1] = (void *)bitAndwith; opTable[2+1] = (void *)bitAndInvertwith; opTable[3+1] = (void *)sourceWordwith; opTable[4+1] = (void *)bitInvertAndwith; opTable[5+1] = (void *)destinationWordwith; opTable[6+1] = (void *)bitXorwith; opTable[7+1] = (void *)bitOrwith; opTable[8+1] = (void *)bitInvertAndInvertwith; opTable[9+1] = (void *)bitInvertXorwith; opTable[10+1] = (void *)bitInvertDestinationwith; opTable[11+1] = (void *)bitOrInvertwith; opTable[12+1] = (void *)bitInvertSourcewith; opTable[13+1] = (void *)bitInvertOrwith; opTable[14+1] = (void *)bitInvertOrInvertwith; opTable[15+1] = (void *)destinationWordwith; opTable[16+1] = (void *)destinationWordwith; opTable[17+1] = (void *)destinationWordwith; opTable[18+1] = (void *)addWordwith; opTable[19+1] = (void *)subWordwith; opTable[20+1] = (void *)rgbAddwith; opTable[21+1] = (void *)rgbSubwith; opTable[22+1] = (void *)OLDrgbDiffwith; opTable[23+1] = (void *)OLDtallyIntoMapwith; opTable[24+1] = (void *)alphaBlendwith; opTable[25+1] = (void *)pixPaintwith; opTable[26+1] = (void *)pixMaskwith; opTable[27+1] = (void *)rgbMaxwith; opTable[28+1] = (void *)rgbMinwith; opTable[29+1] = (void *)rgbMinInvertwith; opTable[30+1] = (void *)alphaBlendConstwith; opTable[31+1] = (void *)alphaPaintConstwith; opTable[32+1] = (void *)rgbDiffwith; opTable[33+1] = (void *)tallyIntoMapwith; opTable[34+1] = (void *)alphaBlendScaledwith; opTable[35+1] = (void *)alphaBlendScaledwith; opTable[36+1] = (void *)alphaBlendScaledwith; opTable[37+1] = (void *)rgbMulwith; opTable[38+1] = (void *)pixSwapwith; opTable[39+1] = (void *)pixClearwith; opTable[40+1] = (void *)fixAlphawith; } static sqInt initDither8Lookup(void) { sqInt b; sqInt out; sqInt pv; sqInt t; sqInt threshold; sqInt value; sqInt value1; for (b = 0; b <= 255; b += 1) { for (t = 0; t <= 15; t += 1) { /* begin expensiveDither32To16:threshold: */ /* You bet */ pv = b & 255; threshold = ditherThresholds16[pv & 7]; value1 = ditherValues16[((usqInt) pv >> 3)]; if (t < threshold) { out = value1 + 1; } else { out = value1; } pv = (((usqInt) b >> 8)) & 255; threshold = ditherThresholds16[pv & 7]; value1 = ditherValues16[((usqInt) pv >> 3)]; if (t < threshold) { out = out | (((usqInt) (value1 + 1) << 5)); } else { out = out | (((usqInt) value1 << 5)); } pv = (((usqInt) b >> 16)) & 255; threshold = ditherThresholds16[pv & 7]; value1 = ditherValues16[((usqInt) pv >> 3)]; if (t < threshold) { out = out | (((usqInt) (value1 + 1) << 10)); } else { out = out | (((usqInt) value1 << 10)); } value = out; dither8Lookup[(t << 8) + b] = value; } } } EXPORT(sqInt) initialiseModule(void) { initBBOpTable(); initDither8Lookup(); return 1; } /* Return true if shiftTable/maskTable define an identity mapping. */ static sqInt isIdentityMapwith(int *shifts, unsigned int *masks) { if ((shifts == null) || (masks == null)) { return 1; } if (((shifts[RedIndex]) == 0) && (((shifts[GreenIndex]) == 0) && (((shifts[BlueIndex]) == 0) && (((shifts[AlphaIndex]) == 0) && (((masks[RedIndex]) == 16711680) && (((masks[GreenIndex]) == 65280) && (((masks[BlueIndex]) == 255) && ((masks[AlphaIndex]) == 4278190080UL)))))))) { return 1; } return 0; } /* Load the dest form for BitBlt. Return false if anything is wrong, true otherwise. */ static sqInt loadBitBltDestForm(void) { sqInt destBitsSize; destBitsOop_xxx_dmu = interpreterProxy->fetchPointerofObject(FormBitsIndex, destForm); // maybe xxx_dmu destWidth = interpreterProxy->fetchIntegerofObject(FormWidthIndex, destForm); destHeight = interpreterProxy->fetchIntegerofObject(FormHeightIndex, destForm); if (!((destWidth >= 0) && (destHeight >= 0))) { return 0; } destDepth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, destForm); destMSB = destDepth > 0; if (destDepth < 0) { destDepth = 0 - destDepth; } if ((destBitsOop_xxx_dmu & 1)) { if (!(queryDestSurface((destBitsOop_xxx_dmu >> 1)))) { return 0; } destPPW = 32 / destDepth; destBits = destPitch = 0; } else { destPPW = 32 / destDepth; destPitch = ((destWidth + (destPPW - 1)) / destPPW) * 4; destBitsSize = interpreterProxy->byteSizeOf(destBitsOop_xxx_dmu); if (!((interpreterProxy->isWordsOrBytes(destBitsOop_xxx_dmu)) && (destBitsSize == (destPitch * destHeight)))) { return 0; } // xxx_dmu destBits = oopForPointer(interpreterProxy->firstIndexableField(destBits)); destBits = (sqInt) interpreterProxy->firstIndexableField(destBitsOop_xxx_dmu); } return 1; } /* Load BitBlt from the oop. This function is exported for the Balloon engine. */ EXPORT(sqInt) loadBitBltFrom(sqInt bbObj) { return loadBitBltFromwarping(bbObj, 0); } /* Load context from BitBlt instance. Return false if anything is amiss */ /* NOTE this should all be changed to minX/maxX coordinates for simpler clipping -- once it works! */ static sqInt loadBitBltFromwarping(sqInt bbObj, sqInt aBool) { sqInt cmOop; sqInt cmSize; sqInt destBitsSize; sqInt fieldOop; sqInt fieldOop1; double floatValue; double floatValue1; sqInt halftoneBits; sqInt mapOop; sqInt mapOop1; sqInt ok; sqInt oldStyle; sqInt oop; sqInt sourceBitsSize; bitBltOop = bbObj; isWarping = aBool; combinationRule = interpreterProxy->fetchIntegerofObject(BBRuleIndex, bitBltOop); if ((interpreterProxy->failed()) || ((combinationRule < 0) || (combinationRule > (OpTableSize - 2)))) { return 0; } if ((combinationRule >= 16) && (combinationRule <= 17)) { return 0; } sourceForm = interpreterProxy->fetchPointerofObject(BBSourceFormIndex, bitBltOop); // maybe xxx_dmu /* begin ignoreSourceOrHalftone: */ if (sourceForm == (interpreterProxy->nilObject())) { noSource = 1; goto l1; } if (combinationRule == 0) { noSource = 1; goto l1; } if (combinationRule == 5) { noSource = 1; goto l1; } if (combinationRule == 10) { noSource = 1; goto l1; } if (combinationRule == 15) { noSource = 1; goto l1; } noSource = 0; l1: /* end ignoreSourceOrHalftone: */; halftoneForm = interpreterProxy->fetchPointerofObject(BBHalftoneFormIndex, bitBltOop); // maybe xxx_dmu /* begin ignoreSourceOrHalftone: */ if (halftoneForm == (interpreterProxy->nilObject())) { noHalftone = 1; goto l2; } if (combinationRule == 0) { noHalftone = 1; goto l2; } if (combinationRule == 5) { noHalftone = 1; goto l2; } if (combinationRule == 10) { noHalftone = 1; goto l2; } if (combinationRule == 15) { noHalftone = 1; goto l2; } noHalftone = 0; l2: /* end ignoreSourceOrHalftone: */; destForm = interpreterProxy->fetchPointerofObject(BBDestFormIndex, bbObj); // maybe xxx_dmu if (!((interpreterProxy->isPointers(destForm)) && ((interpreterProxy->slotSizeOf(destForm)) >= 4))) { return 0; } /* begin loadBitBltDestForm */ destBitsOop_xxx_dmu = interpreterProxy->fetchPointerofObject(FormBitsIndex, destForm); // maybe xxx_dmu destWidth = interpreterProxy->fetchIntegerofObject(FormWidthIndex, destForm); destHeight = interpreterProxy->fetchIntegerofObject(FormHeightIndex, destForm); if (!((destWidth >= 0) && (destHeight >= 0))) { ok = 0; goto l3; } destDepth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, destForm); destMSB = destDepth > 0; if (destDepth < 0) { destDepth = 0 - destDepth; } if ((destBitsOop_xxx_dmu & 1)) { if (!(queryDestSurface((destBitsOop_xxx_dmu >> 1)))) { ok = 0; goto l3; } destPPW = 32 / destDepth; destBits = destPitch = 0; } else { destPPW = 32 / destDepth; destPitch = ((destWidth + (destPPW - 1)) / destPPW) * 4; destBitsSize = interpreterProxy->byteSizeOf(destBitsOop_xxx_dmu); if (!((interpreterProxy->isWordsOrBytes(destBitsOop_xxx_dmu)) && (destBitsSize == (destPitch * destHeight)))) { ok = 0; goto l3; } // xxx_dmu destBits = oopForPointer(interpreterProxy->firstIndexableField(destBits)); destBits = (sqInt) interpreterProxy->firstIndexableField(destBitsOop_xxx_dmu); } ok = 1; l3: /* end loadBitBltDestForm */; if (!(ok)) { return 0; } destX = fetchIntOrFloatofObjectifNil(BBDestXIndex, bitBltOop, 0); destY = fetchIntOrFloatofObjectifNil(BBDestYIndex, bitBltOop, 0); width = fetchIntOrFloatofObjectifNil(BBWidthIndex, bitBltOop, destWidth); height = fetchIntOrFloatofObjectifNil(BBHeightIndex, bitBltOop, destHeight); if (interpreterProxy->failed()) { return 0; } if (noSource) { sourceX = sourceY = 0; } else { if (!((interpreterProxy->isPointers(sourceForm)) && ((interpreterProxy->slotSizeOf(sourceForm)) >= 4))) { return 0; } /* begin loadBitBltSourceForm */ sourceBitsOop_xxx_dmu = interpreterProxy->fetchPointerofObject(FormBitsIndex, sourceForm); // maybe xxx_dmu /* begin fetchIntOrFloat:ofObject: */ fieldOop = interpreterProxy->fetchPointerofObject(FormWidthIndex, sourceForm); if ((fieldOop & 1)) { sourceWidth = (fieldOop >> 1); goto l8; } floatValue = interpreterProxy->floatValueOf(fieldOop); if (!((-2.147483648e9 <= floatValue) && (floatValue <= 2.147483647e9))) { interpreterProxy->primitiveFail(); sourceWidth = 0; goto l8; } sourceWidth = ((sqInt)floatValue); l8: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop1 = interpreterProxy->fetchPointerofObject(FormHeightIndex, sourceForm); if ((fieldOop1 & 1)) { sourceHeight = (fieldOop1 >> 1); goto l9; } floatValue1 = interpreterProxy->floatValueOf(fieldOop1); if (!((-2.147483648e9 <= floatValue1) && (floatValue1 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); sourceHeight = 0; goto l9; } sourceHeight = ((sqInt)floatValue1); l9: /* end fetchIntOrFloat:ofObject: */; if (!((sourceWidth >= 0) && (sourceHeight >= 0))) { ok = 0; goto l10; } sourceDepth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, sourceForm); sourceMSB = sourceDepth > 0; if (sourceDepth < 0) { sourceDepth = 0 - sourceDepth; } if ((sourceBitsOop_xxx_dmu & 1)) { if (!(querySourceSurface((sourceBitsOop_xxx_dmu >> 1)))) { ok = 0; goto l10; } sourcePPW = 32 / sourceDepth; sourceBits = sourcePitch = 0; } else { sourcePPW = 32 / sourceDepth; sourcePitch = ((sourceWidth + (sourcePPW - 1)) / sourcePPW) * 4; sourceBitsSize = interpreterProxy->byteSizeOf(sourceBitsOop_xxx_dmu); if (!((interpreterProxy->isWordsOrBytes(sourceBitsOop_xxx_dmu)) && (sourceBitsSize == (sourcePitch * sourceHeight)))) { ok = 0; goto l10; } // xxx_dmu sourceBits = oopForPointer(interpreterProxy->firstIndexableField(sourceBits)); sourceBits = (sqInt)(interpreterProxy->firstIndexableField(sourceBitsOop_xxx_dmu)); } ok = 1; l10: /* end loadBitBltSourceForm */; if (!(ok)) { return 0; } /* begin loadColorMap */ cmFlags = cmMask = cmBitsPerColor = 0; cmShiftTable = null; cmMaskTable = null; cmLookupTable = null; cmOop = interpreterProxy->fetchPointerofObject(BBColorMapIndex, bitBltOop); // OK xxx_dmu if (cmOop == (interpreterProxy->nilObject())) { ok = 1; goto l4; } /* even if identity or somesuch - may be cleared later */ cmFlags = ColorMapPresent; oldStyle = 0; if (interpreterProxy->isWords(cmOop)) { /* This is an old-style color map (indexed only, with implicit RGBA conversion) */ cmSize = interpreterProxy->slotSizeOf(cmOop); cmLookupTable = interpreterProxy->firstIndexableField(cmOop); oldStyle = 1; ; } else { if (!((interpreterProxy->isPointers(cmOop)) && ((interpreterProxy->slotSizeOf(cmOop)) >= 3))) { ok = 0; goto l4; } /* begin loadColorMapShiftOrMaskFrom: */ mapOop = interpreterProxy->fetchPointerofObject(0, cmOop); // OK xxx_dmu if (mapOop == (interpreterProxy->nilObject())) { cmShiftTable = ((void *) null); goto l6; } if ((mapOop & 1)) { interpreterProxy->primitiveFail(); cmShiftTable = ((void *) null); goto l6; } if (!((interpreterProxy->isWords(mapOop)) && ((interpreterProxy->slotSizeOf(mapOop)) == 4))) { interpreterProxy->primitiveFail(); cmShiftTable = ((void *) null); goto l6; } cmShiftTable = ((void *) (interpreterProxy->firstIndexableField(mapOop))); l6: /* end loadColorMapShiftOrMaskFrom: */; /* begin loadColorMapShiftOrMaskFrom: */ mapOop1 = interpreterProxy->fetchPointerofObject(1, cmOop); // OK xxx_dmu if (mapOop1 == (interpreterProxy->nilObject())) { cmMaskTable = ((void *) null); goto l7; } if ((mapOop1 & 1)) { interpreterProxy->primitiveFail(); cmMaskTable = ((void *) null); goto l7; } if (!((interpreterProxy->isWords(mapOop1)) && ((interpreterProxy->slotSizeOf(mapOop1)) == 4))) { interpreterProxy->primitiveFail(); cmMaskTable = ((void *) null); goto l7; } cmMaskTable = ((void *) (interpreterProxy->firstIndexableField(mapOop1))); l7: /* end loadColorMapShiftOrMaskFrom: */; oop = interpreterProxy->fetchPointerofObject(2, cmOop); // maybe xxx_dmu if (oop == (interpreterProxy->nilObject())) { cmSize = 0; } else { if (!(interpreterProxy->isWords(oop))) { ok = 0; goto l4; } cmSize = interpreterProxy->slotSizeOf(oop); cmLookupTable = interpreterProxy->firstIndexableField(oop); } cmFlags = cmFlags | ColorMapNewStyle; ; } if (!((cmSize & (cmSize - 1)) == 0)) { ok = 0; goto l4; } cmMask = cmSize - 1; cmBitsPerColor = 0; if (cmSize == 512) { cmBitsPerColor = 3; } if (cmSize == 4096) { cmBitsPerColor = 4; } if (cmSize == 32768) { cmBitsPerColor = 5; } if (cmSize == 0) { cmLookupTable = null; cmMask = 0; } else { cmFlags = cmFlags | ColorMapIndexedPart; } if (oldStyle) { setupColorMasks(); } if (isIdentityMapwith(cmShiftTable, cmMaskTable)) { cmMaskTable = null; cmShiftTable = null; } else { cmFlags = cmFlags | ColorMapFixedPart; } ok = 1; l4: /* end loadColorMap */; if (!(ok)) { return 0; } if ((cmFlags & ColorMapNewStyle) == 0) { setupColorMasks(); } sourceX = fetchIntOrFloatofObjectifNil(BBSourceXIndex, bitBltOop, 0); sourceY = fetchIntOrFloatofObjectifNil(BBSourceYIndex, bitBltOop, 0); } /* begin loadHalftoneForm */ if (noHalftone) { halftoneBase = null; ok = 1; goto l5; } if ((interpreterProxy->isPointers(halftoneForm)) && ((interpreterProxy->slotSizeOf(halftoneForm)) >= 4)) { /* Old-style 32xN monochrome halftone Forms */ halftoneBits = interpreterProxy->fetchPointerofObject(FormBitsIndex, halftoneForm); halftoneHeight = interpreterProxy->fetchIntegerofObject(FormHeightIndex, halftoneForm); if (!(interpreterProxy->isWords(halftoneBits))) { noHalftone = 1; } } else { if (!((!(interpreterProxy->isPointers(halftoneForm))) && (interpreterProxy->isWords(halftoneForm)))) { ok = 0; goto l5; } halftoneBits = halftoneForm; halftoneHeight = interpreterProxy->slotSizeOf(halftoneBits); } // xxx_dmu halftoneBase = oopForPointer(interpreterProxy->firstIndexableField(halftoneBits)); halftoneBase = (sqInt)(interpreterProxy->firstIndexableField(halftoneBits)); ok = 1; l5: /* end loadHalftoneForm */; if (!(ok)) { return 0; } clipX = fetchIntOrFloatofObjectifNil(BBClipXIndex, bitBltOop, 0); clipY = fetchIntOrFloatofObjectifNil(BBClipYIndex, bitBltOop, 0); clipWidth = fetchIntOrFloatofObjectifNil(BBClipWidthIndex, bitBltOop, destWidth); clipHeight = fetchIntOrFloatofObjectifNil(BBClipHeightIndex, bitBltOop, destHeight); if (interpreterProxy->failed()) { return 0; } if (clipX < 0) { clipWidth += clipX; clipX = 0; } if (clipY < 0) { clipHeight += clipY; clipY = 0; } if ((clipX + clipWidth) > destWidth) { clipWidth = destWidth - clipX; } if ((clipY + clipHeight) > destHeight) { clipHeight = destHeight - clipY; } return 1; } /* Load the source form for BitBlt. Return false if anything is wrong, true otherwise. */ static sqInt loadBitBltSourceForm(void) { sqInt fieldOop; sqInt fieldOop1; double floatValue; double floatValue1; sqInt sourceBitsSize; sourceBitsOop_xxx_dmu = interpreterProxy->fetchPointerofObject(FormBitsIndex, sourceForm); // maybe xxx_dmu /* begin fetchIntOrFloat:ofObject: */ fieldOop = interpreterProxy->fetchPointerofObject(FormWidthIndex, sourceForm); if ((fieldOop & 1)) { sourceWidth = (fieldOop >> 1); goto l1; } floatValue = interpreterProxy->floatValueOf(fieldOop); if (!((-2.147483648e9 <= floatValue) && (floatValue <= 2.147483647e9))) { interpreterProxy->primitiveFail(); sourceWidth = 0; goto l1; } sourceWidth = ((sqInt)floatValue); l1: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop1 = interpreterProxy->fetchPointerofObject(FormHeightIndex, sourceForm); if ((fieldOop1 & 1)) { sourceHeight = (fieldOop1 >> 1); goto l2; } floatValue1 = interpreterProxy->floatValueOf(fieldOop1); if (!((-2.147483648e9 <= floatValue1) && (floatValue1 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); sourceHeight = 0; goto l2; } sourceHeight = ((sqInt)floatValue1); l2: /* end fetchIntOrFloat:ofObject: */; if (!((sourceWidth >= 0) && (sourceHeight >= 0))) { return 0; } sourceDepth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, sourceForm); sourceMSB = sourceDepth > 0; if (sourceDepth < 0) { sourceDepth = 0 - sourceDepth; } if ((sourceBitsOop_xxx_dmu & 1)) { if (!(querySourceSurface((sourceBitsOop_xxx_dmu >> 1)))) { return 0; } sourcePPW = 32 / sourceDepth; sourceBits = sourcePitch = 0; } else { sourcePPW = 32 / sourceDepth; sourcePitch = ((sourceWidth + (sourcePPW - 1)) / sourcePPW) * 4; sourceBitsSize = interpreterProxy->byteSizeOf(sourceBitsOop_xxx_dmu); if (!((interpreterProxy->isWordsOrBytes(sourceBitsOop_xxx_dmu)) && (sourceBitsSize == (sourcePitch * sourceHeight)))) { return 0; } // xxx_dmu sourceBits = oopForPointer(interpreterProxy->firstIndexableField(sourceBits)); sourceBits = (sqInt)(interpreterProxy->firstIndexableField(sourceBitsOop_xxx_dmu)); } return 1; } /* ColorMap, if not nil, must be longWords, and 2^N long, where N = sourceDepth for 1, 2, 4, 8 bits, or N = 9, 12, or 15 (3, 4, 5 bits per color) for 16 or 32 bits. */ static sqInt loadColorMap(void) { sqInt cmOop; sqInt cmSize; sqInt mapOop; sqInt mapOop1; sqInt oldStyle; sqInt oop; cmFlags = cmMask = cmBitsPerColor = 0; cmShiftTable = null; cmMaskTable = null; cmLookupTable = null; cmOop = interpreterProxy->fetchPointerofObject(BBColorMapIndex, bitBltOop); // OK xxx_dmu if (cmOop == (interpreterProxy->nilObject())) { return 1; } /* even if identity or somesuch - may be cleared later */ cmFlags = ColorMapPresent; oldStyle = 0; if (interpreterProxy->isWords(cmOop)) { /* This is an old-style color map (indexed only, with implicit RGBA conversion) */ cmSize = interpreterProxy->slotSizeOf(cmOop); cmLookupTable = interpreterProxy->firstIndexableField(cmOop); oldStyle = 1; ; } else { if (!((interpreterProxy->isPointers(cmOop)) && ((interpreterProxy->slotSizeOf(cmOop)) >= 3))) { return 0; } /* begin loadColorMapShiftOrMaskFrom: */ mapOop = interpreterProxy->fetchPointerofObject(0, cmOop); // OK xxx_dmu if (mapOop == (interpreterProxy->nilObject())) { cmShiftTable = ((void *) null); goto l1; } if ((mapOop & 1)) { interpreterProxy->primitiveFail(); cmShiftTable = ((void *) null); goto l1; } if (!((interpreterProxy->isWords(mapOop)) && ((interpreterProxy->slotSizeOf(mapOop)) == 4))) { interpreterProxy->primitiveFail(); cmShiftTable = ((void *) null); goto l1; } cmShiftTable = ((void *) (interpreterProxy->firstIndexableField(mapOop))); l1: /* end loadColorMapShiftOrMaskFrom: */; /* begin loadColorMapShiftOrMaskFrom: */ mapOop1 = interpreterProxy->fetchPointerofObject(1, cmOop); // maybe xxx_dmu if (mapOop1 == (interpreterProxy->nilObject())) { cmMaskTable = ((void *) null); goto l2; } if ((mapOop1 & 1)) { interpreterProxy->primitiveFail(); cmMaskTable = ((void *) null); goto l2; } if (!((interpreterProxy->isWords(mapOop1)) && ((interpreterProxy->slotSizeOf(mapOop1)) == 4))) { interpreterProxy->primitiveFail(); cmMaskTable = ((void *) null); goto l2; } cmMaskTable = ((void *) (interpreterProxy->firstIndexableField(mapOop1))); l2: /* end loadColorMapShiftOrMaskFrom: */; oop = interpreterProxy->fetchPointerofObject(2, cmOop); // OK xxx_dmu if (oop == (interpreterProxy->nilObject())) { cmSize = 0; } else { if (!(interpreterProxy->isWords(oop))) { return 0; } cmSize = interpreterProxy->slotSizeOf(oop); cmLookupTable = interpreterProxy->firstIndexableField(oop); } cmFlags = cmFlags | ColorMapNewStyle; ; } if (!((cmSize & (cmSize - 1)) == 0)) { return 0; } cmMask = cmSize - 1; cmBitsPerColor = 0; if (cmSize == 512) { cmBitsPerColor = 3; } if (cmSize == 4096) { cmBitsPerColor = 4; } if (cmSize == 32768) { cmBitsPerColor = 5; } if (cmSize == 0) { cmLookupTable = null; cmMask = 0; } else { cmFlags = cmFlags | ColorMapIndexedPart; } if (oldStyle) { setupColorMasks(); } if (isIdentityMapwith(cmShiftTable, cmMaskTable)) { cmMaskTable = null; cmShiftTable = null; } else { cmFlags = cmFlags | ColorMapFixedPart; } return 1; } static void * loadColorMapShiftOrMaskFrom(sqInt mapOop) { if (mapOop == (interpreterProxy->nilObject())) { return null; } if ((mapOop & 1)) { interpreterProxy->primitiveFail(); return null; } if (!((interpreterProxy->isWords(mapOop)) && ((interpreterProxy->slotSizeOf(mapOop)) == 4))) { interpreterProxy->primitiveFail(); return null; } return interpreterProxy->firstIndexableField(mapOop); } /* Load the halftone form */ static sqInt loadHalftoneForm(void) { sqInt halftoneBits; if (noHalftone) { halftoneBase = null; return 1; } if ((interpreterProxy->isPointers(halftoneForm)) && ((interpreterProxy->slotSizeOf(halftoneForm)) >= 4)) { /* Old-style 32xN monochrome halftone Forms */ halftoneBits = interpreterProxy->fetchPointerofObject(FormBitsIndex, halftoneForm); halftoneHeight = interpreterProxy->fetchIntegerofObject(FormHeightIndex, halftoneForm); if (!(interpreterProxy->isWords(halftoneBits))) { noHalftone = 1; } } else { if (!((!(interpreterProxy->isPointers(halftoneForm))) && (interpreterProxy->isWords(halftoneForm)))) { return 0; } halftoneBits = halftoneForm; halftoneHeight = interpreterProxy->slotSizeOf(halftoneBits); } // xxx_dmu halftoneBase = oopForPointer(interpreterProxy->firstIndexableField(halftoneBits)); halftoneBase = (sqInt)(interpreterProxy->firstIndexableField(halftoneBits)); return 1; } /* Load the surface support plugin */ static sqInt loadSurfacePlugin(void) { querySurfaceFn = interpreterProxy->ioLoadFunctionFrom("ioGetSurfaceFormat", "SurfacePlugin"); lockSurfaceFn = interpreterProxy->ioLoadFunctionFrom("ioLockSurface", "SurfacePlugin"); unlockSurfaceFn = interpreterProxy->ioLoadFunctionFrom("ioUnlockSurface", "SurfacePlugin"); return (querySurfaceFn != 0) && ((lockSurfaceFn != 0) && (unlockSurfaceFn != 0)); } static sqInt loadWarpBltFrom(sqInt bbObj) { return loadBitBltFromwarping(bbObj, 1); } /* Get a pointer to the bits of any OS surfaces. */ /* Notes: * For equal source/dest handles only one locking operation is performed. This is to prevent locking of overlapping areas which does not work with certain APIs (as an example, DirectDraw prevents locking of overlapping areas). A special case for non-overlapping but equal source/dest handle would be possible but we would have to transfer this information over to unlockSurfaces somehow (currently, only one unlock operation is performed for equal source and dest handles). Also, this would require a change in the notion of ioLockSurface() which is right now interpreted as a hint and not as a requirement to lock only the specific portion of the surface. * The arguments in ioLockSurface() provide the implementation with an explicit hint what area is affected. It can be very useful to know the max. affected area beforehand if getting the bits requires expensive copy operations (e.g., like a roundtrip to the X server or a glReadPixel op). However, the returned pointer *MUST* point to the virtual origin of the surface and not to the beginning of the rectangle. The promise made by BitBlt is to never access data outside the given rectangle (aligned to 4byte boundaries!) so it is okay to return a pointer to the virtual origin that is actually outside the valid memory area. * The area provided in ioLockSurface() is already clipped (e.g., it will always be inside the source and dest boundingBox) but it is not aligned to word boundaries yet. It is up to the support code to compute accurate alignment if necessary. * Warping always requires the entire source surface to be locked because there is no beforehand knowledge about what area will actually be traversed. */ static sqInt lockSurfaces(void) { sqInt b; sqInt destHandle; sqInt (*fn)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt); sqInt l; sqInt r; sqInt sourceHandle; sqInt t; hasSurfaceLock = 0; if (destBits == 0) { if (lockSurfaceFn == 0) { if (!(loadSurfacePlugin())) { return null; } } fn = ((sqInt (*)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt)) lockSurfaceFn); destHandle = interpreterProxy->fetchIntegerofObject(FormBitsIndex, destForm); if ((sourceBits == 0) && (!noSource)) { /* Handle the special case of equal source and dest handles */ sourceHandle = interpreterProxy->fetchIntegerofObject(FormBitsIndex, sourceForm); if (sourceHandle == destHandle) { if (isWarping) { /* Otherwise use overlapping area */ l = ((sx < dx) ? sx : dx); r = (((sx < dx) ? dx : sx)) + bbW; t = ((sy < dy) ? sy : dy); b = (((sy < sy) ? sy : sy)) + bbH; sourceBits = fn(sourceHandle, &sourcePitch, l, t, r-l, b-t); } else { sourceBits = fn(sourceHandle, &sourcePitch, 0,0, sourceWidth, sourceHeight); } destBits = sourceBits; destBitsOop_xxx_dmu = sourceBitsOop_xxx_dmu; destPitch = sourcePitch; hasSurfaceLock = 1; return destBits != 0; } } destBits = fn(destHandle, &destPitch, dx, dy, bbW, bbH); hasSurfaceLock = 1; } if ((sourceBits == 0) && (!noSource)) { /* Blitting *from* OS surface */ sourceHandle = interpreterProxy->fetchIntegerofObject(FormBitsIndex, sourceForm); if (lockSurfaceFn == 0) { if (!(loadSurfacePlugin())) { return null; } } /* Warping requiring the entire surface */ fn = ((sqInt (*)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt)) lockSurfaceFn); if (isWarping) { sourceBits = fn(sourceHandle, &sourcePitch, 0, 0, sourceWidth, sourceHeight); } else { sourceBits = fn(sourceHandle, &sourcePitch, sx, sy, bbW, bbH); } hasSurfaceLock = 1; } return (destBits != 0) && ((sourceBits != 0) || (noSource)); } /* Color map the given source pixel. */ static sqInt mapPixelflags(sqInt sourcePixel, sqInt mapperFlags) { sqInt pv; sqInt val; pv = sourcePixel; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePixel & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePixel & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePixel & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePixel & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourcePixel != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } return pv; } /* Sender warpLoop is too big to include this in-line */ static sqInt mergewith(sqInt sourceWord, sqInt destinationWord) { sqInt (*mergeFnwith)(sqInt, sqInt); mergeFnwith = ((sqInt (*)(sqInt, sqInt)) (opTable[combinationRule + 1])); mergeFnwith; return mergeFnwith(sourceWord, destinationWord); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SurfacePlugin")) == 0) { querySurfaceFn = lockSurfaceFn = unlockSurfaceFn = 0; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Subract the pixels in the source and destination, color by color, and return the sum of the absolute value of all the differences. For non-rgb, XOR the two and return the number of differing pixels. Note that the region is not clipped to bit boundaries, but only to the nearest (enclosing) word. This is because copyLoop does not do pre-merge masking. For accurate results, you must subtract the values obtained from the left and right fringes. */ static sqInt OLDrgbDiffwith(sqInt sourceWord, sqInt destinationWord) { sqInt diff; sqInt pixMask; if (destDepth < 16) { /* Just xor and count differing bits if not RGB */ diff = sourceWord ^ destinationWord; pixMask = maskTable[destDepth]; while (!(diff == 0)) { if ((diff & pixMask) != 0) { bitCount += 1; } diff = ((usqInt) diff) >> destDepth; } return destinationWord; } if (destDepth == 16) { diff = partitionedSubfromnBitsnPartitions(sourceWord, destinationWord, 5, 3); bitCount = ((bitCount + (diff & 31)) + ((((usqInt) diff) >> 5) & 31)) + ((((usqInt) diff) >> 10) & 31); diff = partitionedSubfromnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3); bitCount = ((bitCount + (diff & 31)) + ((((usqInt) diff) >> 5) & 31)) + ((((usqInt) diff) >> 10) & 31); } else { diff = partitionedSubfromnBitsnPartitions(sourceWord, destinationWord, 8, 3); bitCount = ((bitCount + (diff & 255)) + ((((usqInt) diff) >> 8) & 255)) + ((((usqInt) diff) >> 16) & 255); } return destinationWord; } /* Tally pixels into the color map. Note that the source should be specified = destination, in order for the proper color map checks to be performed at setup. Note that the region is not clipped to bit boundaries, but only to the nearest (enclosing) word. This is because copyLoop does not do pre-merge masking. For accurate results, you must subtract the values obtained from the left and right fringes. */ static sqInt OLDtallyIntoMapwith(sqInt sourceWord, sqInt destinationWord) { sqInt d; sqInt d1; sqInt d2; sqInt destPix; sqInt destPix1; sqInt destPix2; sqInt i; sqInt mapIndex; sqInt mask; sqInt mask3; sqInt mask4; sqInt pixMask; sqInt shiftWord; sqInt srcPix; sqInt srcPix1; sqInt srcPix2; if (!((cmFlags & (ColorMapPresent | ColorMapIndexedPart)) == (ColorMapPresent | ColorMapIndexedPart))) { return destinationWord; } if (destDepth < 16) { /* loop through all packed pixels. */ pixMask = (maskTable[destDepth]) & cmMask; shiftWord = destinationWord; for (i = 1; i <= destPPW; i += 1) { mapIndex = shiftWord & pixMask; cmLookupTable[mapIndex & cmMask] = ((cmLookupTable[mapIndex & cmMask]) + 1); shiftWord = ((usqInt) shiftWord) >> destDepth; } return destinationWord; } if (destDepth == 16) { /* begin rgbMap:from:to: */ if (((d = cmBitsPerColor - 5)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask = (1 << 5) - 1; srcPix = (destinationWord & 65535) << d; mask = mask << d; destPix = srcPix & mask; mask = mask << cmBitsPerColor; srcPix = srcPix << d; mapIndex = (destPix + (srcPix & mask)) + ((srcPix << d) & (mask << cmBitsPerColor)); goto l1; } else { if (d == 0) { if (5 == 5) { mapIndex = (destinationWord & 65535) & 32767; goto l1; } if (5 == 8) { mapIndex = (destinationWord & 65535) & 16777215; goto l1; } mapIndex = destinationWord & 65535; goto l1; } if ((destinationWord & 65535) == 0) { mapIndex = destinationWord & 65535; goto l1; } d = 5 - cmBitsPerColor; /* Transfer mask */ mask = (1 << cmBitsPerColor) - 1; srcPix = ((usqInt) (destinationWord & 65535)) >> d; destPix = srcPix & mask; mask = mask << cmBitsPerColor; srcPix = ((usqInt) srcPix) >> d; destPix = (destPix + (srcPix & mask)) + ((((usqInt) srcPix) >> d) & (mask << cmBitsPerColor)); if (destPix == 0) { mapIndex = 1; goto l1; } mapIndex = destPix; goto l1; } l1: /* end rgbMap:from:to: */; cmLookupTable[mapIndex & cmMask] = ((cmLookupTable[mapIndex & cmMask]) + 1); /* begin rgbMap:from:to: */ if (((d1 = cmBitsPerColor - 5)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask3 = (1 << 5) - 1; srcPix1 = (((usqInt) destinationWord) >> 16) << d1; mask3 = mask3 << d1; destPix1 = srcPix1 & mask3; mask3 = mask3 << cmBitsPerColor; srcPix1 = srcPix1 << d1; mapIndex = (destPix1 + (srcPix1 & mask3)) + ((srcPix1 << d1) & (mask3 << cmBitsPerColor)); goto l2; } else { if (d1 == 0) { if (5 == 5) { mapIndex = (((usqInt) destinationWord) >> 16) & 32767; goto l2; } if (5 == 8) { mapIndex = (((usqInt) destinationWord) >> 16) & 16777215; goto l2; } mapIndex = ((usqInt) destinationWord) >> 16; goto l2; } if ((((usqInt) destinationWord) >> 16) == 0) { mapIndex = ((usqInt) destinationWord) >> 16; goto l2; } d1 = 5 - cmBitsPerColor; /* Transfer mask */ mask3 = (1 << cmBitsPerColor) - 1; srcPix1 = ((usqInt) (((usqInt) destinationWord) >> 16)) >> d1; destPix1 = srcPix1 & mask3; mask3 = mask3 << cmBitsPerColor; srcPix1 = ((usqInt) srcPix1) >> d1; destPix1 = (destPix1 + (srcPix1 & mask3)) + ((((usqInt) srcPix1) >> d1) & (mask3 << cmBitsPerColor)); if (destPix1 == 0) { mapIndex = 1; goto l2; } mapIndex = destPix1; goto l2; } l2: /* end rgbMap:from:to: */; cmLookupTable[mapIndex & cmMask] = ((cmLookupTable[mapIndex & cmMask]) + 1); } else { /* begin rgbMap:from:to: */ if (((d2 = cmBitsPerColor - 8)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask4 = (1 << 8) - 1; srcPix2 = destinationWord << d2; mask4 = mask4 << d2; destPix2 = srcPix2 & mask4; mask4 = mask4 << cmBitsPerColor; srcPix2 = srcPix2 << d2; mapIndex = (destPix2 + (srcPix2 & mask4)) + ((srcPix2 << d2) & (mask4 << cmBitsPerColor)); goto l3; } else { if (d2 == 0) { if (8 == 5) { mapIndex = destinationWord & 32767; goto l3; } if (8 == 8) { mapIndex = destinationWord & 16777215; goto l3; } mapIndex = destinationWord; goto l3; } if (destinationWord == 0) { mapIndex = destinationWord; goto l3; } d2 = 8 - cmBitsPerColor; /* Transfer mask */ mask4 = (1 << cmBitsPerColor) - 1; srcPix2 = ((usqInt) destinationWord) >> d2; destPix2 = srcPix2 & mask4; mask4 = mask4 << cmBitsPerColor; srcPix2 = ((usqInt) srcPix2) >> d2; destPix2 = (destPix2 + (srcPix2 & mask4)) + ((((usqInt) srcPix2) >> d2) & (mask4 << cmBitsPerColor)); if (destPix2 == 0) { mapIndex = 1; goto l3; } mapIndex = destPix2; goto l3; } l3: /* end rgbMap:from:to: */; cmLookupTable[mapIndex & cmMask] = ((cmLookupTable[mapIndex & cmMask]) + 1); } return destinationWord; } /* Add word1 to word2 as nParts partitions of nBits each. This is useful for packed pixels, or packed colors */ /* In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints (this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of words as unsigned int in those cases where comparisions are done (jmv) */ static sqInt partitionedAddtonBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts) { sqInt i; unsigned int mask; unsigned int maskedWord1; unsigned int result; unsigned int sum; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= nParts; i += 1) { maskedWord1 = word1 & mask; sum = maskedWord1 + (word2 & mask); if ((sum <= mask) && (sum >= maskedWord1)) { /* This is needed because in C, integer arithmetic overflows silently! (jmv) */ result = result | sum; } else { result = result | mask; } /* slide left to next partition */ mask = mask << nBits; } return result; } /* AND word1 to word2 as nParts partitions of nBits each. Any field of word1 not all-ones is treated as all-zeroes. Used for erasing, eg, brush shapes prior to ORing in a color */ static sqInt partitionedANDtonBitsnPartitions(sqInt word1, sqInt word2, sqInt nBits, sqInt nParts) { sqInt i; sqInt mask; sqInt result; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= nParts; i += 1) { if ((word1 & mask) == mask) { result = result | (word2 & mask); } /* slide left to next partition */ mask = mask << nBits; } return result; } /* Max word1 to word2 as nParts partitions of nBits each */ /* In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints (this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of words as unsigned int in those cases where comparisions are done (jmv) */ static sqInt partitionedMaxwithnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts) { sqInt i; unsigned int mask; unsigned int result; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= nParts; i += 1) { result = result | ((((word2 & mask) < (word1 & mask)) ? (word1 & mask) : (word2 & mask))); /* slide left to next partition */ mask = mask << nBits; } return result; } /* Min word1 to word2 as nParts partitions of nBits each */ /* In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints (this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of words as unsigned int in those cases where comparisions are done (jmv) */ static sqInt partitionedMinwithnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts) { sqInt i; unsigned int mask; unsigned int result; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= nParts; i += 1) { result = result | ((((word2 & mask) < (word1 & mask)) ? (word2 & mask) : (word1 & mask))); /* slide left to next partition */ mask = mask << nBits; } return result; } /* Multiply word1 with word2 as nParts partitions of nBits each. This is useful for packed pixels, or packed colors. Bug in loop version when non-white background */ /* In C, integer multiplication might answer a wrong value if the unsigned values are declared as signed. This problem does not affect this method, because the most significant bit (i.e. the sign bit) will always be zero (jmv) */ static sqInt partitionedMulwithnBitsnPartitions(sqInt word1, sqInt word2, sqInt nBits, sqInt nParts) { sqInt dMask; sqInt product; sqInt result; sqInt sMask; /* partition mask starts at the right */ sMask = maskTable[nBits]; dMask = sMask << nBits; /* optimized first step */ result = ((usqInt) (((((word1 & sMask) + 1) * ((word2 & sMask) + 1)) - 1) & dMask)) >> nBits; if (nParts == 1) { return result; } product = (((((((usqInt) word1) >> nBits) & sMask) + 1) * (((((usqInt) word2) >> nBits) & sMask) + 1)) - 1) & dMask; result = result | product; if (nParts == 2) { return result; } product = (((((((usqInt) word1) >> (2 * nBits)) & sMask) + 1) * (((((usqInt) word2) >> (2 * nBits)) & sMask) + 1)) - 1) & dMask; result = result | (product << nBits); if (nParts == 3) { return result; } product = (((((((usqInt) word1) >> (3 * nBits)) & sMask) + 1) * (((((usqInt) word2) >> (3 * nBits)) & sMask) + 1)) - 1) & dMask; result = result | (product << (2 * nBits)); return result; } /* Subtract word1 from word2 as nParts partitions of nBits each. This is useful for packed pixels, or packed colors */ /* In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints (this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of words as unsigned int in those cases where comparisions are done (jmv) */ static sqInt partitionedSubfromnBitsnPartitions(unsigned int word1, unsigned int word2, sqInt nBits, sqInt nParts) { sqInt i; unsigned int mask; unsigned int p1; unsigned int p2; unsigned int result; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= nParts; i += 1) { p1 = word1 & mask; p2 = word2 & mask; if (p1 < p2) { /* result is really abs value of thedifference */ result = result | (p2 - p1); } else { result = result | (p1 - p2); } /* slide left to next partition */ mask = mask << nBits; } return result; } /* Based on the values provided during setup choose and perform the appropriate inner loop function. */ /* Should be inlined into caller for speed */ static sqInt performCopyLoop(void) { sqInt dWid; sqInt dxLowBits; sqInt endBits; sqInt pixPerM1; sqInt pixPerM11; sqInt startBits; sqInt sxLowBits; sqInt t; /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); if (noSource) { copyLoopNoSource(); } else { /* begin checkSourceOverlap */ if ((sourceForm == destForm) && (dy >= sy)) { if (dy > sy) { /* have to start at bottom */ vDir = -1; sy = (sy + bbH) - 1; dy = (dy + bbH) - 1; } else { if ((dy == sy) && (dx > sx)) { /* y's are equal, but x's are backward */ hDir = -1; /* start at right */ sx = (sx + bbW) - 1; /* and fix up masks */ dx = (dx + bbW) - 1; if (nWords > 1) { t = mask1; mask1 = mask2; mask2 = t; } } } destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); } if ((sourceDepth != destDepth) || ((cmFlags != 0) || (sourceMSB != destMSB))) { copyLoopPixMap(); } else { /* begin sourceSkewAndPointerInit */ /* A mask, assuming power of two */ pixPerM11 = destPPW - 1; sxLowBits = sx & pixPerM11; /* check if need to preload buffer (i.e., two words of source needed for first word of destination) */ dxLowBits = dx & pixPerM11; if (hDir > 0) { /* n Bits stored in 1st word of dest */ dWid = ((bbW < (destPPW - dxLowBits)) ? bbW : (destPPW - dxLowBits)); preload = (sxLowBits + dWid) > pixPerM11; } else { dWid = ((bbW < (dxLowBits + 1)) ? bbW : (dxLowBits + 1)); preload = ((sxLowBits - dWid) + 1) < 0; } if (sourceMSB) { skew = (sxLowBits - dxLowBits) * destDepth; } else { skew = (dxLowBits - sxLowBits) * destDepth; } if (preload) { if (skew < 0) { skew += 32; } else { skew -= 32; } } /* calculate increments from end of 1 line to start of next */ sourceIndex = (sourceBits + (sy * sourcePitch)) + ((sx / (32 / sourceDepth)) * 4); sourceDelta = (sourcePitch * vDir) - (4 * (nWords * hDir)); if (preload) { /* Compensate for extra source word fetched */ sourceDelta -= 4 * hDir; } copyLoop(); } } } /* Pick nPix pixels starting at srcBitIndex from the source, map by the color map, and justify them according to dstBitIndex in the resulting destWord. */ static sqInt pickSourcePixelsflagssrcMaskdestMasksrcShiftIncdstShiftInc(sqInt nPixels, sqInt mapperFlags, sqInt srcMask, sqInt dstMask, sqInt srcShiftInc, sqInt dstShiftInc) { sqInt destPix; sqInt destWord; sqInt dstShift; sqInt idx; sqInt idx1; sqInt nPix; sqInt pv; sqInt sourcePix; sqInt sourceWord; sqInt srcShift; sqInt val; /* oh please */ sourceWord = long32AtPointer(sourceIndex); destWord = 0; /* Hint: Keep in register */ srcShift = srcBitShift; /* Hint: Keep in register */ dstShift = dstBitShift; /* always > 0 so we can use do { } while(--nPix); */ nPix = nPixels; if (mapperFlags == (ColorMapPresent | ColorMapIndexedPart)) { do { /* a little optimization for (pretty crucial) blits using indexed lookups only */ /* grab, colormap and mix in pixel */ sourcePix = (((usqInt) sourceWord) >> srcShift) & srcMask; destPix = cmLookupTable[sourcePix & cmMask]; /* adjust dest pix index */ destWord = destWord | ((destPix & dstMask) << dstShift); /* adjust source pix index */ dstShift += dstShiftInc; if (!((((srcShift += srcShiftInc)) & 4294967264UL) == 0)) { if (sourceMSB) { srcShift += 32; } else { srcShift -= 32; } /* begin srcLongAt: */ idx = sourceIndex += 4; sourceWord = long32AtPointer(idx); } } while(!(((nPix -= 1)) == 0)); } else { do { /* grab, colormap and mix in pixel */ sourcePix = (((usqInt) sourceWord) >> srcShift) & srcMask; /* begin mapPixel:flags: */ pv = sourcePix; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePix & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePix & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePix & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePix & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourcePix != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } destPix = pv; /* adjust dest pix index */ destWord = destWord | ((destPix & dstMask) << dstShift); /* adjust source pix index */ dstShift += dstShiftInc; if (!((((srcShift += srcShiftInc)) & 4294967264UL) == 0)) { if (sourceMSB) { srcShift += 32; } else { srcShift -= 32; } /* begin srcLongAt: */ idx1 = sourceIndex += 4; sourceWord = long32AtPointer(idx1); } } while(!(((nPix -= 1)) == 0)); } /* Store back */ srcBitShift = srcShift; return destWord; } /* Pick a single pixel from the source for WarpBlt. Note: This method is crucial for WarpBlt speed w/o smoothing and still relatively important when smoothing is used. */ static sqInt pickWarpPixelAtXy(sqInt xx, sqInt yy) { sqInt sourcePix; sqInt sourceWord; sqInt srcIndex; sqInt x; sqInt y; if ((xx < 0) || ((yy < 0) || ((((x = ((usqInt) xx) >> BinaryPoint)) >= sourceWidth) || (((y = ((usqInt) yy) >> BinaryPoint)) >= sourceHeight)))) { return 0; } srcIndex = (sourceBits + (y * sourcePitch)) + ((((usqInt) x) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord = long32AtPointer(srcIndex); srcBitShift = warpBitShiftTable[x & warpAlignMask]; sourcePix = (((usqInt) sourceWord) >> srcBitShift) & warpSrcMask; return sourcePix; } /* Clear all pixels in destinationWord for which the pixels of sourceWord have the same values. Used to clear areas of some constant color to zero. */ static sqInt pixClearwith(sqInt sourceWord, sqInt destinationWord) { sqInt i; sqInt mask; sqInt nBits; sqInt pv; sqInt result; if (destDepth == 32) { if (sourceWord == destinationWord) { return 0; } else { return destinationWord; } } nBits = destDepth; /* partition mask starts at the right */ mask = maskTable[nBits]; result = 0; for (i = 1; i <= destPPW; i += 1) { pv = destinationWord & mask; if ((sourceWord & mask) == pv) { pv = 0; } result = result | pv; /* slide left to next partition */ mask = mask << nBits; } return result; } static sqInt pixMaskwith(sqInt sourceWord, sqInt destinationWord) { sqInt i; sqInt mask; sqInt result; /* begin partitionedAND:to:nBits:nPartitions: */ /* partition mask starts at the right */ mask = maskTable[destDepth]; result = 0; for (i = 1; i <= destPPW; i += 1) { if (((~sourceWord) & mask) == mask) { result = result | (destinationWord & mask); } /* slide left to next partition */ mask = mask << destDepth; } return result; } static sqInt pixPaintwith(sqInt sourceWord, sqInt destinationWord) { if (sourceWord == 0) { return destinationWord; } return sourceWord | (partitionedANDtonBitsnPartitions(~sourceWord, destinationWord, destDepth, destPPW)); } /* Swap the pixels in destWord */ static sqInt pixSwapwith(sqInt sourceWord, sqInt destWord) { sqInt highMask; sqInt i; sqInt lowMask; sqInt result; sqInt shift; if (destPPW == 1) { return destWord; } result = 0; /* mask low pixel */ lowMask = (1 << destDepth) - 1; /* mask high pixel */ highMask = lowMask << ((destPPW - 1) * destDepth); shift = 32 - destDepth; result = result | (((destWord & lowMask) << shift) | (((usqInt) (destWord & highMask)) >> shift)); if (destPPW <= 2) { return result; } for (i = 2; i <= (((sqInt) destPPW >> 1)); i += 1) { lowMask = lowMask << destDepth; highMask = ((usqInt) highMask) >> destDepth; shift -= destDepth * 2; result = result | (((destWord & lowMask) << shift) | (((usqInt) (destWord & highMask)) >> shift)); } return result; } /* Invoke the copyBits primitive. If the destination is the display, then copy it to the screen. */ EXPORT(sqInt) primitiveCopyBits(void) { sqInt rcvr; rcvr = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); if (!(loadBitBltFromwarping(rcvr, 0))) { return interpreterProxy->primitiveFail(); } copyBits(); if (interpreterProxy->failed()) { return null; } /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(interpreterProxy->methodArgumentCount()); if ((combinationRule == 22) || (combinationRule == 32)) { interpreterProxy->pop(1); return interpreterProxy->pushInteger(bitCount); } } EXPORT(sqInt) primitiveDisplayString(void) { sqInt ascii; sqInt bbObj; sqInt charIndex; sqInt endBits; sqInt glyphIndex; sqInt glyphMap; sqInt kernDelta; sqInt left; sqInt maxGlyph; sqInt pixPerM1; sqInt quickBlt; char *sourcePtr; sqInt sourceString; sqInt startBits; sqInt startIndex; sqInt stopIndex; sqInt xTable; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } kernDelta = interpreterProxy->stackIntegerValue(0); xTable = interpreterProxy->stackObjectValue(1); glyphMap = interpreterProxy->stackObjectValue(2); if (!(((interpreterProxy->fetchClassOf(xTable)) == (interpreterProxy->classArray())) && ((interpreterProxy->fetchClassOf(glyphMap)) == (interpreterProxy->classArray())))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(glyphMap)) == 256)) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } maxGlyph = (interpreterProxy->slotSizeOf(xTable)) - 2; stopIndex = interpreterProxy->stackIntegerValue(3); startIndex = interpreterProxy->stackIntegerValue(4); sourceString = interpreterProxy->stackObjectValue(5); if (!(interpreterProxy->isBytes(sourceString))) { return interpreterProxy->primitiveFail(); } if (!((startIndex > 0) && ((stopIndex > 0) && (stopIndex <= (interpreterProxy->byteSizeOf(sourceString)))))) { return interpreterProxy->primitiveFail(); } bbObj = interpreterProxy->stackObjectValue(6); if (!(loadBitBltFromwarping(bbObj, 0))) { return interpreterProxy->primitiveFail(); } if ((combinationRule == 30) || (combinationRule == 31)) { return interpreterProxy->primitiveFail(); } quickBlt = (destBits != 0) && ((sourceBits != 0) && ((noSource == 0) && ((sourceForm != destForm) && ((cmFlags != 0) || ((sourceMSB != destMSB) || (sourceDepth != destDepth)))))); left = destX; sourcePtr = interpreterProxy->firstIndexableField(sourceString); for (charIndex = startIndex; charIndex <= stopIndex; charIndex += 1) { ascii = byteAtPointer((sourcePtr + charIndex) - 1); glyphIndex = interpreterProxy->fetchIntegerofObject(ascii, glyphMap); if ((glyphIndex < 0) || (glyphIndex > maxGlyph)) { return interpreterProxy->primitiveFail(); } sourceX = interpreterProxy->fetchIntegerofObject(glyphIndex, xTable); width = (interpreterProxy->fetchIntegerofObject(glyphIndex + 1, xTable)) - sourceX; if (interpreterProxy->failed()) { return null; } clipRange(); if ((bbW > 0) && (bbH > 0)) { if (quickBlt) { /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); copyLoopPixMap(); affectedL = dx; affectedR = dx + bbW; affectedT = dy; affectedB = dy + bbH; } else { copyBits(); } } if (interpreterProxy->failed()) { return null; } destX = (destX + width) + kernDelta; } affectedL = left; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); interpreterProxy->pop(6); } /* Invoke the line drawing primitive. */ EXPORT(sqInt) primitiveDrawLoop(void) { sqInt affB; sqInt affL; sqInt affR; sqInt affT; sqInt dx1; sqInt dy1; sqInt i; sqInt P; sqInt px; sqInt py; sqInt rcvr; sqInt xDelta; sqInt yDelta; rcvr = interpreterProxy->stackValue(2); xDelta = interpreterProxy->stackIntegerValue(1); yDelta = interpreterProxy->stackIntegerValue(0); if (!(loadBitBltFromwarping(rcvr, 0))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { /* begin drawLoopX:Y: */ if (xDelta > 0) { dx1 = 1; } else { if (xDelta == 0) { dx1 = 0; } else { dx1 = -1; } } if (yDelta > 0) { dy1 = 1; } else { if (yDelta == 0) { dy1 = 0; } else { dy1 = -1; } } px = abs(yDelta); py = abs(xDelta); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; if (py > px) { /* more horizontal */ P = ((sqInt) py >> 1); for (i = 1; i <= py; i += 1) { destX += dx1; if (((P -= px)) < 0) { destY += dy1; P += py; } if (i < py) { copyBits(); if (interpreterProxy->failed()) { goto l1; } if ((affectedL < affectedR) && (affectedT < affectedB)) { /* Affected rectangle grows along the line */ affL = ((affL < affectedL) ? affL : affectedL); affR = ((affR < affectedR) ? affectedR : affR); affT = ((affT < affectedT) ? affT : affectedT); affB = ((affB < affectedB) ? affectedB : affB); if (((affR - affL) * (affB - affT)) > 4000) { /* If affected rectangle gets large, update it in chunks */ affectedL = affL; affectedR = affR; affectedT = affT; affectedB = affB; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; } } } } } else { /* more vertical */ P = ((sqInt) px >> 1); for (i = 1; i <= px; i += 1) { destY += dy1; if (((P -= py)) < 0) { destX += dx1; P += px; } if (i < px) { copyBits(); if (interpreterProxy->failed()) { goto l1; } if ((affectedL < affectedR) && (affectedT < affectedB)) { /* Affected rectangle grows along the line */ affL = ((affL < affectedL) ? affL : affectedL); affR = ((affR < affectedR) ? affectedR : affR); affT = ((affT < affectedT) ? affT : affectedT); affB = ((affB < affectedB) ? affectedB : affB); if (((affR - affL) * (affB - affT)) > 4000) { /* If affected rectangle gets large, update it in chunks */ affectedL = affL; affectedR = affR; affectedT = affT; affectedB = affB; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); /* init null rectangle */ affL = affT = 9999; affR = affB = -9999; } } } } } affectedL = affL; affectedR = affR; affectedT = affT; /* store destX, Y back */ affectedB = affB; interpreterProxy->storeIntegerofObjectwithValue(BBDestXIndex, bitBltOop, destX); interpreterProxy->storeIntegerofObjectwithValue(BBDestYIndex, bitBltOop, destY); l1: /* end drawLoopX:Y: */; /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } /* Invoke the warpBits primitive. If the destination is the display, then copy it to the screen. */ EXPORT(sqInt) primitiveWarpBits(void) { sqInt endBits; sqInt ns; sqInt pixPerM1; sqInt rcvr; sqInt startBits; rcvr = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); if (!(loadBitBltFromwarping(rcvr, 1))) { return interpreterProxy->primitiveFail(); } /* begin warpBits */ ns = noSource; noSource = 1; clipRange(); noSource = ns; if (noSource || ((bbW <= 0) || (bbH <= 0))) { /* zero width or height; noop */ affectedL = affectedR = affectedT = affectedB = 0; goto l1; } if (!(lockSurfaces())) { interpreterProxy->primitiveFail(); goto l1; } /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); warpLoop(); if (hDir > 0) { affectedL = dx; affectedR = dx + bbW; } else { affectedL = (dx - bbW) + 1; affectedR = dx + 1; } if (vDir > 0) { affectedT = dy; affectedB = dy + bbH; } else { affectedT = (dy - bbH) + 1; affectedB = dy + 1; } unlockSurfaces(); l1: /* end warpBits */; if (interpreterProxy->failed()) { return null; } /* begin showDisplayBits */ interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } /* Query the dimension of an OS surface. This method is provided so that in case the inst vars of the source form are broken, *actual* values of the OS surface can be obtained. This might, for instance, happen if the user resizes the main window. Note: Moved to a separate function for better inlining of the caller. */ static sqInt queryDestSurface(sqInt handle) { if (querySurfaceFn == 0) { if (!(loadSurfacePlugin())) { return 0; } } return ((sqInt (*) (sqInt, sqInt*, sqInt*, sqInt*, sqInt*))querySurfaceFn) (handle, &destWidth, &destHeight, &destDepth, &destMSB); } /* Query the dimension of an OS surface. This method is provided so that in case the inst vars of the source form are broken, *actual* values of the OS surface can be obtained. This might, for instance, happen if the user resizes the main window. Note: Moved to a separate function for better inlining of the caller. */ static sqInt querySourceSurface(sqInt handle) { if (querySurfaceFn == 0) { if (!(loadSurfacePlugin())) { return 0; } } return ((sqInt (*) (sqInt, sqInt*, sqInt*, sqInt*, sqInt*))querySurfaceFn) (handle, &sourceWidth, &sourceHeight, &sourceDepth, &sourceMSB); } static sqInt rgbAddwith(sqInt sourceWord, sqInt destinationWord) { if (destDepth < 16) { return partitionedAddtonBitsnPartitions(sourceWord, destinationWord, destDepth, destPPW); } if (destDepth == 16) { return (partitionedAddtonBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedAddtonBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { return partitionedAddtonBitsnPartitions(sourceWord, destinationWord, 8, 4); } } /* Subract the pixels in the source and destination, color by color, and return the sum of the absolute value of all the differences. For non-rgb, return the number of differing pixels. */ static sqInt rgbDiffwith(sqInt sourceWord, sqInt destinationWord) { sqInt bitsPerColor; sqInt destPixVal; sqInt destShifted; sqInt diff; sqInt i; sqInt maskShifted; sqInt pixMask; sqInt rgbMask; sqInt sourcePixVal; sqInt sourceShifted; pixMask = maskTable[destDepth]; if (destDepth == 16) { bitsPerColor = 5; rgbMask = 31; } else { bitsPerColor = 8; rgbMask = 255; } maskShifted = destMask; destShifted = destinationWord; sourceShifted = sourceWord; for (i = 1; i <= destPPW; i += 1) { if ((maskShifted & pixMask) > 0) { /* Only tally pixels within the destination rectangle */ destPixVal = destShifted & pixMask; sourcePixVal = sourceShifted & pixMask; if (destDepth < 16) { if (sourcePixVal == destPixVal) { diff = 0; } else { diff = 1; } } else { diff = partitionedSubfromnBitsnPartitions(sourcePixVal, destPixVal, bitsPerColor, 3); diff = ((diff & rgbMask) + ((((usqInt) diff) >> bitsPerColor) & rgbMask)) + ((((usqInt) (((usqInt) diff) >> bitsPerColor)) >> bitsPerColor) & rgbMask); } bitCount += diff; } maskShifted = ((usqInt) maskShifted) >> destDepth; sourceShifted = ((usqInt) sourceShifted) >> destDepth; destShifted = ((usqInt) destShifted) >> destDepth; } return destinationWord; } /* Convert the given 16bit pixel value to a 32bit RGBA value. Note: This method is intended to deal with different source formats. */ static sqInt rgbMap16To32(sqInt sourcePixel) { return (((sourcePixel & 31) << 3) | ((sourcePixel & 992) << 6)) | ((sourcePixel & 31744) << 9); } /* Convert the given 32bit pixel value to a 32bit RGBA value. Note: This method is intended to deal with different source formats. */ static sqInt rgbMap32To32(sqInt sourcePixel) { return sourcePixel; } /* Perform the RGBA conversion for the given source pixel */ static sqInt rgbMapPixelflags(sqInt sourcePixel, sqInt mapperFlags) { sqInt val; val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePixel & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePixel & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePixel & (cmMaskTable[2])) << (cmShiftTable[2])))); return val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePixel & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePixel & (cmMaskTable[3])) << (cmShiftTable[3])))); } /* Convert the given pixel value with nBitsIn bits for each color component to a pixel value with nBitsOut bits for each color component. Typical values for nBitsIn/nBitsOut are 3, 5, or 8. */ static sqInt rgbMapfromto(sqInt sourcePixel, sqInt nBitsIn, sqInt nBitsOut) { sqInt d; sqInt destPix; sqInt mask; sqInt srcPix; if (((d = nBitsOut - nBitsIn)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask = (1 << nBitsIn) - 1; srcPix = sourcePixel << d; mask = mask << d; destPix = srcPix & mask; mask = mask << nBitsOut; srcPix = srcPix << d; return (destPix + (srcPix & mask)) + ((srcPix << d) & (mask << nBitsOut)); } else { if (d == 0) { if (nBitsIn == 5) { return sourcePixel & 32767; } if (nBitsIn == 8) { return sourcePixel & 16777215; } return sourcePixel; } if (sourcePixel == 0) { return sourcePixel; } d = nBitsIn - nBitsOut; /* Transfer mask */ mask = (1 << nBitsOut) - 1; srcPix = ((usqInt) sourcePixel) >> d; destPix = srcPix & mask; mask = mask << nBitsOut; srcPix = ((usqInt) srcPix) >> d; destPix = (destPix + (srcPix & mask)) + ((((usqInt) srcPix) >> d) & (mask << nBitsOut)); if (destPix == 0) { return 1; } return destPix; } } static sqInt rgbMaxwith(sqInt sourceWord, sqInt destinationWord) { sqInt i; sqInt i1; unsigned int mask; unsigned int mask3; unsigned int result; unsigned int result1; if (destDepth < 16) { /* begin partitionedMax:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask = maskTable[destDepth]; result = 0; for (i = 1; i <= destPPW; i += 1) { result = result | ((((destinationWord & mask) < (sourceWord & mask)) ? (sourceWord & mask) : (destinationWord & mask))); /* slide left to next partition */ mask = mask << destDepth; } return result; } if (destDepth == 16) { return (partitionedMaxwithnBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedMaxwithnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { /* begin partitionedMax:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask3 = maskTable[8]; result1 = 0; for (i1 = 1; i1 <= 4; i1 += 1) { result1 = result1 | ((((destinationWord & mask3) < (sourceWord & mask3)) ? (sourceWord & mask3) : (destinationWord & mask3))); /* slide left to next partition */ mask3 = mask3 << 8; } return result1; } } static sqInt rgbMinInvertwith(sqInt wordToInvert, sqInt destinationWord) { sqInt i; sqInt i1; unsigned int mask; unsigned int mask3; unsigned int result; unsigned int result1; sqInt sourceWord; sourceWord = ~wordToInvert; if (destDepth < 16) { /* begin partitionedMin:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask = maskTable[destDepth]; result = 0; for (i = 1; i <= destPPW; i += 1) { result = result | ((((destinationWord & mask) < (sourceWord & mask)) ? (destinationWord & mask) : (sourceWord & mask))); /* slide left to next partition */ mask = mask << destDepth; } return result; } if (destDepth == 16) { return (partitionedMinwithnBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedMinwithnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { /* begin partitionedMin:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask3 = maskTable[8]; result1 = 0; for (i1 = 1; i1 <= 4; i1 += 1) { result1 = result1 | ((((destinationWord & mask3) < (sourceWord & mask3)) ? (destinationWord & mask3) : (sourceWord & mask3))); /* slide left to next partition */ mask3 = mask3 << 8; } return result1; } } static sqInt rgbMinwith(sqInt sourceWord, sqInt destinationWord) { sqInt i; sqInt i1; unsigned int mask; unsigned int mask3; unsigned int result; unsigned int result1; if (destDepth < 16) { /* begin partitionedMin:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask = maskTable[destDepth]; result = 0; for (i = 1; i <= destPPW; i += 1) { result = result | ((((destinationWord & mask) < (sourceWord & mask)) ? (destinationWord & mask) : (sourceWord & mask))); /* slide left to next partition */ mask = mask << destDepth; } return result; } if (destDepth == 16) { return (partitionedMinwithnBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedMinwithnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { /* begin partitionedMin:with:nBits:nPartitions: */ /* partition mask starts at the right */ mask3 = maskTable[8]; result1 = 0; for (i1 = 1; i1 <= 4; i1 += 1) { result1 = result1 | ((((destinationWord & mask3) < (sourceWord & mask3)) ? (destinationWord & mask3) : (sourceWord & mask3))); /* slide left to next partition */ mask3 = mask3 << 8; } return result1; } } static sqInt rgbMulwith(sqInt sourceWord, sqInt destinationWord) { if (destDepth < 16) { return partitionedMulwithnBitsnPartitions(sourceWord, destinationWord, destDepth, destPPW); } if (destDepth == 16) { return (partitionedMulwithnBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedMulwithnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { return partitionedMulwithnBitsnPartitions(sourceWord, destinationWord, 8, 4); } } static sqInt rgbSubwith(sqInt sourceWord, sqInt destinationWord) { if (destDepth < 16) { return partitionedSubfromnBitsnPartitions(sourceWord, destinationWord, destDepth, destPPW); } if (destDepth == 16) { return (partitionedSubfromnBitsnPartitions(sourceWord, destinationWord, 5, 3)) + ((partitionedSubfromnBitsnPartitions(((usqInt) sourceWord) >> 16, ((usqInt) destinationWord) >> 16, 5, 3)) << 16); } else { return partitionedSubfromnBitsnPartitions(sourceWord, destinationWord, 8, 4); } } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* WARNING: For WarpBlt w/ smoothing the source depth is wrong here! */ static sqInt setupColorMasks(void) { sqInt bits; sqInt targetBits; bits = targetBits = 0; if (sourceDepth <= 8) { return null; } if (sourceDepth == 16) { bits = 5; } if (sourceDepth == 32) { bits = 8; } if (cmBitsPerColor == 0) { if (destDepth <= 8) { return null; } if (destDepth == 16) { targetBits = 5; } if (destDepth == 32) { targetBits = 8; } } else { targetBits = cmBitsPerColor; } setupColorMasksFromto(bits, targetBits); } /* Setup color masks for converting an incoming RGB pixel value from srcBits to targetBits. */ static sqInt setupColorMasksFromto(sqInt srcBits, sqInt targetBits) { sqInt deltaBits; sqInt mask; static unsigned int masks[4] = {0, 0, 0, 0}; static int shifts[4] = {0, 0, 0, 0}; ; deltaBits = targetBits - srcBits; if (deltaBits == 0) { return 0; } if (deltaBits <= 0) { /* Mask for extracting a color part of the source */ mask = (1 << targetBits) - 1; masks[RedIndex] = (mask << ((srcBits * 2) - deltaBits)); masks[GreenIndex] = (mask << (srcBits - deltaBits)); masks[BlueIndex] = (mask << (0 - deltaBits)); masks[AlphaIndex] = 0; } else { /* Mask for extracting a color part of the source */ mask = (1 << srcBits) - 1; masks[RedIndex] = (mask << (srcBits * 2)); masks[GreenIndex] = (mask << srcBits); masks[BlueIndex] = mask; } shifts[RedIndex] = (deltaBits * 3); shifts[GreenIndex] = (deltaBits * 2); shifts[BlueIndex] = deltaBits; shifts[AlphaIndex] = 0; cmShiftTable = shifts; cmMaskTable = masks; cmFlags = cmFlags | (ColorMapPresent | ColorMapFixedPart); } static sqInt showDisplayBits(void) { interpreterProxy->showDisplayBitsLeftTopRightBottom(destForm, affectedL, affectedT, affectedR, affectedB); } /* This is only used when source and dest are same depth, ie, when the barrel-shift copy loop is used. */ static sqInt sourceSkewAndPointerInit(void) { sqInt dWid; sqInt dxLowBits; sqInt pixPerM1; sqInt sxLowBits; /* A mask, assuming power of two */ pixPerM1 = destPPW - 1; sxLowBits = sx & pixPerM1; /* check if need to preload buffer (i.e., two words of source needed for first word of destination) */ dxLowBits = dx & pixPerM1; if (hDir > 0) { /* n Bits stored in 1st word of dest */ dWid = ((bbW < (destPPW - dxLowBits)) ? bbW : (destPPW - dxLowBits)); preload = (sxLowBits + dWid) > pixPerM1; } else { dWid = ((bbW < (dxLowBits + 1)) ? bbW : (dxLowBits + 1)); preload = ((sxLowBits - dWid) + 1) < 0; } if (sourceMSB) { skew = (sxLowBits - dxLowBits) * destDepth; } else { skew = (dxLowBits - sxLowBits) * destDepth; } if (preload) { if (skew < 0) { skew += 32; } else { skew -= 32; } } /* calculate increments from end of 1 line to start of next */ sourceIndex = (sourceBits + (sy * sourcePitch)) + ((sx / (32 / sourceDepth)) * 4); sourceDelta = (sourcePitch * vDir) - (4 * (nWords * hDir)); if (preload) { /* Compensate for extra source word fetched */ sourceDelta -= 4 * hDir; } } static sqInt sourceWordwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord; } static sqInt srcLongAt(sqInt idx) { return long32AtPointer(idx); } static sqInt subWordwith(sqInt sourceWord, sqInt destinationWord) { return sourceWord - destinationWord; } /* Tally pixels into the color map. Those tallied are exactly those in the destination rectangle. Note that the source should be specified == destination, in order for the proper color map checks to be performed at setup. */ static sqInt tallyIntoMapwith(sqInt sourceWord, sqInt destinationWord) { sqInt d; sqInt d1; sqInt destPix; sqInt destPix1; sqInt destShifted; sqInt i; sqInt mapIndex; sqInt mask; sqInt mask3; sqInt maskShifted; sqInt pixMask; sqInt pixVal; sqInt srcPix; sqInt srcPix1; if (!((cmFlags & (ColorMapPresent | ColorMapIndexedPart)) == (ColorMapPresent | ColorMapIndexedPart))) { return destinationWord; } pixMask = maskTable[destDepth]; destShifted = destinationWord; maskShifted = destMask; for (i = 1; i <= destPPW; i += 1) { if (!((maskShifted & pixMask) == 0)) { /* Only tally pixels within the destination rectangle */ pixVal = destShifted & pixMask; if (destDepth < 16) { mapIndex = pixVal; } else { if (destDepth == 16) { /* begin rgbMap:from:to: */ if (((d = cmBitsPerColor - 5)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask = (1 << 5) - 1; srcPix = pixVal << d; mask = mask << d; destPix = srcPix & mask; mask = mask << cmBitsPerColor; srcPix = srcPix << d; mapIndex = (destPix + (srcPix & mask)) + ((srcPix << d) & (mask << cmBitsPerColor)); goto l1; } else { if (d == 0) { if (5 == 5) { mapIndex = pixVal & 32767; goto l1; } if (5 == 8) { mapIndex = pixVal & 16777215; goto l1; } mapIndex = pixVal; goto l1; } if (pixVal == 0) { mapIndex = pixVal; goto l1; } d = 5 - cmBitsPerColor; /* Transfer mask */ mask = (1 << cmBitsPerColor) - 1; srcPix = ((usqInt) pixVal) >> d; destPix = srcPix & mask; mask = mask << cmBitsPerColor; srcPix = ((usqInt) srcPix) >> d; destPix = (destPix + (srcPix & mask)) + ((((usqInt) srcPix) >> d) & (mask << cmBitsPerColor)); if (destPix == 0) { mapIndex = 1; goto l1; } mapIndex = destPix; goto l1; } l1: /* end rgbMap:from:to: */; } else { /* begin rgbMap:from:to: */ if (((d1 = cmBitsPerColor - 8)) > 0) { /* Expand to more bits by zero-fill */ /* Transfer mask */ mask3 = (1 << 8) - 1; srcPix1 = pixVal << d1; mask3 = mask3 << d1; destPix1 = srcPix1 & mask3; mask3 = mask3 << cmBitsPerColor; srcPix1 = srcPix1 << d1; mapIndex = (destPix1 + (srcPix1 & mask3)) + ((srcPix1 << d1) & (mask3 << cmBitsPerColor)); goto l2; } else { if (d1 == 0) { if (8 == 5) { mapIndex = pixVal & 32767; goto l2; } if (8 == 8) { mapIndex = pixVal & 16777215; goto l2; } mapIndex = pixVal; goto l2; } if (pixVal == 0) { mapIndex = pixVal; goto l2; } d1 = 8 - cmBitsPerColor; /* Transfer mask */ mask3 = (1 << cmBitsPerColor) - 1; srcPix1 = ((usqInt) pixVal) >> d1; destPix1 = srcPix1 & mask3; mask3 = mask3 << cmBitsPerColor; srcPix1 = ((usqInt) srcPix1) >> d1; destPix1 = (destPix1 + (srcPix1 & mask3)) + ((((usqInt) srcPix1) >> d1) & (mask3 << cmBitsPerColor)); if (destPix1 == 0) { mapIndex = 1; goto l2; } mapIndex = destPix1; goto l2; } l2: /* end rgbMap:from:to: */; } } cmLookupTable[mapIndex & cmMask] = ((cmLookupTable[mapIndex & cmMask]) + 1); } maskShifted = ((usqInt) maskShifted) >> destDepth; destShifted = ((usqInt) destShifted) >> destDepth; } return destinationWord; } /* Return the word at position idx from the colorMap */ static sqInt tallyMapAt(sqInt idx) { return cmLookupTable[idx & cmMask]; } /* Store the word at position idx in the colorMap */ static sqInt tallyMapAtput(sqInt idx, sqInt value) { return cmLookupTable[idx & cmMask] = value; } /* Shortcut for stuff that's being run from the balloon engine. Since we do this at each scan line we should avoid the expensive setup for source and destination. */ /* We need a source. */ static sqInt tryCopyingBitsQuickly(void) { if (noSource) { return 0; } if (!(combinationRule == 34)) { return 0; } if (!(sourceDepth == 32)) { return 0; } if (sourceForm == destForm) { return 0; } if (destDepth < 8) { return 0; } if ((destDepth == 8) && ((cmFlags & ColorMapPresent) == 0)) { return 0; } if (destDepth == 32) { alphaSourceBlendBits32(); } if (destDepth == 16) { alphaSourceBlendBits16(); } if (destDepth == 8) { alphaSourceBlendBits8(); } affectedL = dx; affectedR = dx + bbW; affectedT = dy; affectedB = dy + bbH; return 1; } /* Unlock the bits of any OS surfaces. */ /* See the comment in lockSurfaces. Similar rules apply. That is, the area provided in ioUnlockSurface can be used to determine the dirty region after drawing. If a source is unlocked, then the area will be (0,0,0,0) to indicate that no portion is dirty. */ static sqInt unlockSurfaces(void) { sqInt destHandle; sqInt destLocked; sqInt (*fn)(sqInt, sqInt, sqInt, sqInt, sqInt); sqInt sourceHandle; if (hasSurfaceLock) { if (unlockSurfaceFn == 0) { if (!(loadSurfacePlugin())) { return null; } } fn = ((sqInt (*)(sqInt, sqInt, sqInt, sqInt, sqInt)) unlockSurfaceFn); destLocked = 0; destHandle = interpreterProxy->fetchPointerofObject(FormBitsIndex, destForm); // maybe xxx_dmu if ((destHandle & 1)) { /* The destBits are always assumed to be dirty */ destHandle = (destHandle >> 1); fn(destHandle, affectedL, affectedT, affectedR-affectedL, affectedB-affectedT); destBits = destPitch = 0; destLocked = 1; } if (!(noSource)) { sourceHandle = interpreterProxy->fetchPointerofObject(FormBitsIndex, sourceForm); // maybe xxx_dmu if ((sourceHandle & 1)) { /* Only unlock sourceHandle if different from destHandle */ sourceHandle = (sourceHandle >> 1); if (!(destLocked && (sourceHandle == destHandle))) { fn(sourceHandle, 0, 0, 0, 0); } sourceBits = sourcePitch = 0; } } hasSurfaceLock = 0; } } static sqInt warpBits(void) { sqInt endBits; sqInt ns; sqInt pixPerM1; sqInt startBits; ns = noSource; noSource = 1; clipRange(); noSource = ns; if (noSource || ((bbW <= 0) || (bbH <= 0))) { /* zero width or height; noop */ affectedL = affectedR = affectedT = affectedB = 0; return null; } if (!(lockSurfaces())) { return interpreterProxy->primitiveFail(); } /* begin destMaskAndPointerInit */ /* A mask, assuming power of two */ /* how many pixels in first word */ pixPerM1 = destPPW - 1; startBits = destPPW - (dx & pixPerM1); if (destMSB) { mask1 = ((usqInt) AllOnes) >> (32 - (startBits * destDepth)); } else { mask1 = AllOnes << (32 - (startBits * destDepth)); } endBits = (((dx + bbW) - 1) & pixPerM1) + 1; if (destMSB) { mask2 = AllOnes << (32 - (endBits * destDepth)); } else { mask2 = ((usqInt) AllOnes) >> (32 - (endBits * destDepth)); } if (bbW < startBits) { mask1 = mask1 & mask2; mask2 = 0; nWords = 1; } else { nWords = (((bbW - startBits) + pixPerM1) / destPPW) + 1; } /* defaults for no overlap with source */ /* calculate byte addr and delta, based on first word of data */ /* Note pitch is bytes and nWords is longs, not bytes */ hDir = vDir = 1; destIndex = (destBits + (dy * destPitch)) + ((dx / destPPW) * 4); destDelta = (destPitch * vDir) - (4 * (nWords * hDir)); warpLoop(); if (hDir > 0) { affectedL = dx; affectedR = dx + bbW; } else { affectedL = (dx - bbW) + 1; affectedR = dx + 1; } if (vDir > 0) { affectedT = dy; affectedB = dy + bbH; } else { affectedT = (dy - bbH) + 1; affectedB = dy + 1; } unlockSurfaces(); } /* This version of the inner loop traverses an arbirary quadrilateral source, thus producing a general affine transformation. */ static sqInt warpLoop(void) { sqInt deltaP12x; sqInt deltaP12y; sqInt deltaP43x; sqInt deltaP43y; sqInt destPix; sqInt destWord; sqInt destWord1; sqInt dstMask; sqInt dstShiftInc; sqInt dstShiftLeft; sqInt endBits; sqInt fieldOop; sqInt fieldOop1; sqInt fieldOop2; sqInt fieldOop3; sqInt fieldOop4; sqInt fieldOop5; sqInt fieldOop6; sqInt fieldOop7; double floatValue; double floatValue1; double floatValue2; double floatValue3; double floatValue4; double floatValue5; double floatValue6; double floatValue7; sqInt halftoneWord; sqInt i; sqInt i1; sqInt mapperFlags; sqInt (*mergeFnwith)(sqInt, sqInt); sqInt mergeWord; sqInt nPix; sqInt nPix1; sqInt nSteps; sqInt pAx; sqInt pAy; sqInt pBx; sqInt pBy; sqInt pv; sqInt skewWord; sqInt smoothingCount; sqInt sourceMapOop; sqInt sourceMapIndex_xxx_dmu; sqInt sourcePix; sqInt sourcePix1; sqInt sourcePix2; sqInt sourceWord; sqInt sourceWord1; sqInt srcIndex; sqInt srcIndex1; sqInt startBits; sqInt val; sqInt words; sqInt words1; sqInt x; sqInt x1; sqInt xDelta; sqInt y; sqInt y1; sqInt yDelta; mergeFnwith = ((sqInt (*)(sqInt, sqInt)) (opTable[combinationRule + 1])); mergeFnwith; if (!((interpreterProxy->slotSizeOf(bitBltOop)) >= (BBWarpBase + 12))) { return interpreterProxy->primitiveFail(); } nSteps = height - 1; if (nSteps <= 0) { nSteps = 1; } /* begin fetchIntOrFloat:ofObject: */ fieldOop = interpreterProxy->fetchPointerofObject(BBWarpBase, bitBltOop); if ((fieldOop & 1)) { pAx = (fieldOop >> 1); goto l3; } floatValue = interpreterProxy->floatValueOf(fieldOop); if (!((-2.147483648e9 <= floatValue) && (floatValue <= 2.147483647e9))) { interpreterProxy->primitiveFail(); pAx = 0; goto l3; } pAx = ((sqInt)floatValue); l3: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop1 = interpreterProxy->fetchPointerofObject(BBWarpBase + 3, bitBltOop); if ((fieldOop1 & 1)) { words = (fieldOop1 >> 1); goto l4; } floatValue1 = interpreterProxy->floatValueOf(fieldOop1); if (!((-2.147483648e9 <= floatValue1) && (floatValue1 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); words = 0; goto l4; } words = ((sqInt)floatValue1); l4: /* end fetchIntOrFloat:ofObject: */; /* begin deltaFrom:to:nSteps: */ if (words > pAx) { deltaP12x = (((words - pAx) + FixedPt1) / (nSteps + 1)) + 1; goto l5; } else { if (words == pAx) { deltaP12x = 0; goto l5; } deltaP12x = 0 - ((((pAx - words) + FixedPt1) / (nSteps + 1)) + 1); goto l5; } l5: /* end deltaFrom:to:nSteps: */; if (deltaP12x < 0) { pAx = words - (nSteps * deltaP12x); } /* begin fetchIntOrFloat:ofObject: */ fieldOop2 = interpreterProxy->fetchPointerofObject(BBWarpBase + 1, bitBltOop); if ((fieldOop2 & 1)) { pAy = (fieldOop2 >> 1); goto l6; } floatValue2 = interpreterProxy->floatValueOf(fieldOop2); if (!((-2.147483648e9 <= floatValue2) && (floatValue2 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); pAy = 0; goto l6; } pAy = ((sqInt)floatValue2); l6: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop3 = interpreterProxy->fetchPointerofObject(BBWarpBase + 4, bitBltOop); if ((fieldOop3 & 1)) { words = (fieldOop3 >> 1); goto l7; } floatValue3 = interpreterProxy->floatValueOf(fieldOop3); if (!((-2.147483648e9 <= floatValue3) && (floatValue3 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); words = 0; goto l7; } words = ((sqInt)floatValue3); l7: /* end fetchIntOrFloat:ofObject: */; /* begin deltaFrom:to:nSteps: */ if (words > pAy) { deltaP12y = (((words - pAy) + FixedPt1) / (nSteps + 1)) + 1; goto l8; } else { if (words == pAy) { deltaP12y = 0; goto l8; } deltaP12y = 0 - ((((pAy - words) + FixedPt1) / (nSteps + 1)) + 1); goto l8; } l8: /* end deltaFrom:to:nSteps: */; if (deltaP12y < 0) { pAy = words - (nSteps * deltaP12y); } /* begin fetchIntOrFloat:ofObject: */ fieldOop4 = interpreterProxy->fetchPointerofObject(BBWarpBase + 9, bitBltOop); if ((fieldOop4 & 1)) { pBx = (fieldOop4 >> 1); goto l9; } floatValue4 = interpreterProxy->floatValueOf(fieldOop4); if (!((-2.147483648e9 <= floatValue4) && (floatValue4 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); pBx = 0; goto l9; } pBx = ((sqInt)floatValue4); l9: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop5 = interpreterProxy->fetchPointerofObject(BBWarpBase + 6, bitBltOop); if ((fieldOop5 & 1)) { words = (fieldOop5 >> 1); goto l10; } floatValue5 = interpreterProxy->floatValueOf(fieldOop5); if (!((-2.147483648e9 <= floatValue5) && (floatValue5 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); words = 0; goto l10; } words = ((sqInt)floatValue5); l10: /* end fetchIntOrFloat:ofObject: */; /* begin deltaFrom:to:nSteps: */ if (words > pBx) { deltaP43x = (((words - pBx) + FixedPt1) / (nSteps + 1)) + 1; goto l11; } else { if (words == pBx) { deltaP43x = 0; goto l11; } deltaP43x = 0 - ((((pBx - words) + FixedPt1) / (nSteps + 1)) + 1); goto l11; } l11: /* end deltaFrom:to:nSteps: */; if (deltaP43x < 0) { pBx = words - (nSteps * deltaP43x); } /* begin fetchIntOrFloat:ofObject: */ fieldOop6 = interpreterProxy->fetchPointerofObject(BBWarpBase + 10, bitBltOop); if ((fieldOop6 & 1)) { pBy = (fieldOop6 >> 1); goto l12; } floatValue6 = interpreterProxy->floatValueOf(fieldOop6); if (!((-2.147483648e9 <= floatValue6) && (floatValue6 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); pBy = 0; goto l12; } pBy = ((sqInt)floatValue6); l12: /* end fetchIntOrFloat:ofObject: */; /* begin fetchIntOrFloat:ofObject: */ fieldOop7 = interpreterProxy->fetchPointerofObject(BBWarpBase + 7, bitBltOop); if ((fieldOop7 & 1)) { words = (fieldOop7 >> 1); goto l13; } floatValue7 = interpreterProxy->floatValueOf(fieldOop7); if (!((-2.147483648e9 <= floatValue7) && (floatValue7 <= 2.147483647e9))) { interpreterProxy->primitiveFail(); words = 0; goto l13; } words = ((sqInt)floatValue7); l13: /* end fetchIntOrFloat:ofObject: */; /* begin deltaFrom:to:nSteps: */ if (words > pBy) { deltaP43y = (((words - pBy) + FixedPt1) / (nSteps + 1)) + 1; goto l14; } else { if (words == pBy) { deltaP43y = 0; goto l14; } deltaP43y = 0 - ((((pBy - words) + FixedPt1) / (nSteps + 1)) + 1); goto l14; } l14: /* end deltaFrom:to:nSteps: */; if (deltaP43y < 0) { pBy = words - (nSteps * deltaP43y); } if (interpreterProxy->failed()) { return 0; } if ((interpreterProxy->methodArgumentCount()) == 2) { smoothingCount = interpreterProxy->stackIntegerValue(1); sourceMapOop = interpreterProxy->stackValue(0); if (sourceMapOop == (interpreterProxy->nilObject())) { if (sourceDepth < 16) { return interpreterProxy->primitiveFail(); } } else { if ((interpreterProxy->slotSizeOf(sourceMapOop)) < (1 << sourceDepth)) { return interpreterProxy->primitiveFail(); } // xxx_dmu sourceMapOop = oopForPointer(interpreterProxy->firstIndexableField(sourceMapOop)); sourceMapIndex_xxx_dmu = (sqInt)(interpreterProxy->firstIndexableField(sourceMapOop)); } } else { smoothingCount = 1; sourceMapOop = interpreterProxy->nilObject(); sourceMapIndex_xxx_dmu = 0; } nSteps = width - 1; if (nSteps <= 0) { nSteps = 1; } startBits = destPPW - (dx & (destPPW - 1)); endBits = (((dx + bbW) - 1) & (destPPW - 1)) + 1; if (bbW < startBits) { startBits = bbW; } if (destY < clipY) { /* Advance increments if there was clipping in y */ pAx += (clipY - destY) * deltaP12x; pAy += (clipY - destY) * deltaP12y; pBx += (clipY - destY) * deltaP43x; pBy += (clipY - destY) * deltaP43y; } /* begin warpLoopSetup */ /* warpSrcShift = log2(sourceDepth) */ warpSrcShift = 0; /* recycle temp */ words1 = sourceDepth; while (!(words1 == 1)) { warpSrcShift += 1; words1 = ((usqInt) words1) >> 1; } /* warpAlignShift: Shift for aligning x position to word boundary */ warpSrcMask = maskTable[sourceDepth]; /* warpAlignMask: Mask for extracting the pixel position from an x position */ warpAlignShift = 5 - warpSrcShift; /* Setup the lookup table for source bit shifts */ /* warpBitShiftTable: given an sub-word x value what's the bit shift? */ warpAlignMask = (1 << warpAlignShift) - 1; for (i1 = 0; i1 <= warpAlignMask; i1 += 1) { if (sourceMSB) { warpBitShiftTable[i1] = (32 - ((i1 + 1) << warpSrcShift)); } else { warpBitShiftTable[i1] = (i1 << warpSrcShift); } } if ((smoothingCount > 1) && ((cmFlags & ColorMapNewStyle) == 0)) { if (cmLookupTable == null) { if (destDepth == 16) { setupColorMasksFromto(8, 5); } } else { setupColorMasksFromto(8, cmBitsPerColor); } } mapperFlags = cmFlags & (~ColorMapNewStyle); if (destMSB) { dstShiftInc = 0 - destDepth; dstShiftLeft = 32 - destDepth; } else { dstShiftInc = destDepth; dstShiftLeft = 0; } for (i = 1; i <= bbH; i += 1) { /* begin deltaFrom:to:nSteps: */ if (pBx > pAx) { xDelta = (((pBx - pAx) + FixedPt1) / (nSteps + 1)) + 1; goto l1; } else { if (pBx == pAx) { xDelta = 0; goto l1; } xDelta = 0 - ((((pAx - pBx) + FixedPt1) / (nSteps + 1)) + 1); goto l1; } l1: /* end deltaFrom:to:nSteps: */; if (xDelta >= 0) { sx = pAx; } else { sx = pBx - (nSteps * xDelta); } /* begin deltaFrom:to:nSteps: */ if (pBy > pAy) { yDelta = (((pBy - pAy) + FixedPt1) / (nSteps + 1)) + 1; goto l2; } else { if (pBy == pAy) { yDelta = 0; goto l2; } yDelta = 0 - ((((pAy - pBy) + FixedPt1) / (nSteps + 1)) + 1); goto l2; } l2: /* end deltaFrom:to:nSteps: */; if (yDelta >= 0) { sy = pAy; } else { sy = pBy - (nSteps * yDelta); } if (destMSB) { dstBitShift = 32 - (((dx & (destPPW - 1)) + 1) * destDepth); } else { dstBitShift = (dx & (destPPW - 1)) * destDepth; } if (destX < clipX) { /* Advance increments if there was clipping in x */ sx += (clipX - destX) * xDelta; sy += (clipX - destX) * yDelta; } if (noHalftone) { halftoneWord = AllOnes; } else { halftoneWord = long32AtPointer(halftoneBase + ((((dy + i) - 1) % halftoneHeight) * 4)); } destMask = mask1; /* Here is the inner loop... */ nPix = startBits; words = nWords; do { if (smoothingCount == 1) { /* begin warpPickSourcePixels:xDeltah:yDeltah:xDeltav:yDeltav:dstShiftInc:flags: */ /* Yepp - this should go into warpLoop */ dstMask = maskTable[destDepth]; destWord1 = 0; nPix1 = nPix; if (mapperFlags == (ColorMapPresent | ColorMapIndexedPart)) { do { /* begin pickWarpPixelAtX:y: */ if ((sx < 0) || ((sy < 0) || ((((x = ((usqInt) sx) >> BinaryPoint)) >= sourceWidth) || (((y = ((usqInt) sy) >> BinaryPoint)) >= sourceHeight)))) { sourcePix = 0; goto l15; } srcIndex = (sourceBits + (y * sourcePitch)) + ((((usqInt) x) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord = long32AtPointer(srcIndex); srcBitShift = warpBitShiftTable[x & warpAlignMask]; sourcePix1 = (((usqInt) sourceWord) >> srcBitShift) & warpSrcMask; sourcePix = sourcePix1; l15: /* end pickWarpPixelAtX:y: */; destPix = cmLookupTable[sourcePix & cmMask]; destWord1 = destWord1 | ((destPix & dstMask) << dstBitShift); dstBitShift += dstShiftInc; sx += xDelta; sy += yDelta; } while(!(((nPix1 -= 1)) == 0)); } else { do { /* begin pickWarpPixelAtX:y: */ if ((sx < 0) || ((sy < 0) || ((((x1 = ((usqInt) sx) >> BinaryPoint)) >= sourceWidth) || (((y1 = ((usqInt) sy) >> BinaryPoint)) >= sourceHeight)))) { sourcePix = 0; goto l16; } srcIndex1 = (sourceBits + (y1 * sourcePitch)) + ((((usqInt) x1) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord1 = long32AtPointer(srcIndex1); srcBitShift = warpBitShiftTable[x1 & warpAlignMask]; sourcePix2 = (((usqInt) sourceWord1) >> srcBitShift) & warpSrcMask; sourcePix = sourcePix2; l16: /* end pickWarpPixelAtX:y: */; /* begin mapPixel:flags: */ pv = sourcePix; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePix & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePix & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePix & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePix & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourcePix != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } destPix = pv; destWord1 = destWord1 | ((destPix & dstMask) << dstBitShift); dstBitShift += dstShiftInc; sx += xDelta; sy += yDelta; } while(!(((nPix1 -= 1)) == 0)); } skewWord = destWord1; } else { skewWord = warpPickSmoothPixelsxDeltahyDeltahxDeltavyDeltavsourceMapsmoothingdstShiftInc(nPix, xDelta, yDelta, deltaP12x, deltaP12y, sourceMapIndex_xxx_dmu, smoothingCount, dstShiftInc); } dstBitShift = dstShiftLeft; if (destMask == AllOnes) { /* avoid read-modify-write */ mergeWord = mergeFnwith(skewWord & halftoneWord, long32AtPointer(destIndex)); long32AtPointerput(destIndex, destMask & mergeWord); } else { /* General version using dest masking */ destWord = long32AtPointer(destIndex); mergeWord = mergeFnwith(skewWord & halftoneWord, destWord & destMask); destWord = (destMask & mergeWord) | (destWord & (~destMask)); long32AtPointerput(destIndex, destWord); } destIndex += 4; if (words == 2) { /* e.g., is the next word the last word? */ /* set mask for last word in this row */ destMask = mask2; nPix = endBits; } else { /* use fullword mask for inner loop */ destMask = AllOnes; nPix = destPPW; } } while(!(((words -= 1)) == 0)); pAx += deltaP12x; pAy += deltaP12y; pBx += deltaP43x; pBy += deltaP43y; destIndex += destDelta; } } /* Setup values for faster pixel fetching. */ static sqInt warpLoopSetup(void) { sqInt i; sqInt words; /* warpSrcShift = log2(sourceDepth) */ warpSrcShift = 0; /* recycle temp */ words = sourceDepth; while (!(words == 1)) { warpSrcShift += 1; words = ((usqInt) words) >> 1; } /* warpAlignShift: Shift for aligning x position to word boundary */ warpSrcMask = maskTable[sourceDepth]; /* warpAlignMask: Mask for extracting the pixel position from an x position */ warpAlignShift = 5 - warpSrcShift; /* Setup the lookup table for source bit shifts */ /* warpBitShiftTable: given an sub-word x value what's the bit shift? */ warpAlignMask = (1 << warpAlignShift) - 1; for (i = 0; i <= warpAlignMask; i += 1) { if (sourceMSB) { warpBitShiftTable[i] = (32 - ((i + 1) << warpSrcShift)); } else { warpBitShiftTable[i] = (i << warpSrcShift); } } } /* Pick n (sub-) pixels from the source form, mapped by sourceMap, average the RGB values, map by colorMap and return the new word. This version is only called from WarpBlt with smoothingCount > 1 */ static sqInt warpPickSmoothPixelsxDeltahyDeltahxDeltavyDeltavsourceMapsmoothingdstShiftInc(sqInt nPixels, sqInt xDeltah, sqInt yDeltah, sqInt xDeltav, sqInt yDeltav, sqInt sourceMap, sqInt n, sqInt dstShiftInc) { sqInt a; sqInt b; sqInt destWord; sqInt dstMask; sqInt g; sqInt i; sqInt j; sqInt k; sqInt nPix; sqInt pv; sqInt r; sqInt rgb; sqInt sourcePix; sqInt sourceWord; sqInt srcIndex; sqInt val; sqInt x; sqInt x1; sqInt xdh; sqInt xdv; sqInt xx; sqInt y; sqInt y1; sqInt ydh; sqInt ydv; sqInt yy; /* nope - too much stuff in here */ dstMask = maskTable[destDepth]; destWord = 0; if (n == 2) { /* Try avoiding divides for most common n (divide by 2 is generated as shift) */ xdh = ((sqInt) xDeltah >> 1); ydh = ((sqInt) yDeltah >> 1); xdv = ((sqInt) xDeltav >> 1); ydv = ((sqInt) yDeltav >> 1); } else { xdh = xDeltah / n; ydh = yDeltah / n; xdv = xDeltav / n; ydv = yDeltav / n; } i = nPixels; do { x = sx; y = sy; /* Pick and average n*n subpixels */ a = r = g = b = 0; /* actual number of pixels (not clipped and not transparent) */ nPix = 0; j = n; do { xx = x; yy = y; k = n; do { /* begin pickWarpPixelAtX:y: */ if ((xx < 0) || ((yy < 0) || ((((x1 = ((usqInt) xx) >> BinaryPoint)) >= sourceWidth) || (((y1 = ((usqInt) yy) >> BinaryPoint)) >= sourceHeight)))) { rgb = 0; goto l1; } srcIndex = (sourceBits + (y1 * sourcePitch)) + ((((usqInt) x1) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord = long32AtPointer(srcIndex); srcBitShift = warpBitShiftTable[x1 & warpAlignMask]; sourcePix = (((usqInt) sourceWord) >> srcBitShift) & warpSrcMask; rgb = sourcePix; l1: /* end pickWarpPixelAtX:y: */; if (!((combinationRule == 25) && (rgb == 0))) { /* If not clipped and not transparent, then tally rgb values */ nPix += 1; if (sourceDepth < 16) { rgb = long32AtPointer(sourceMap + (rgb << 2)); } else { if (sourceDepth == 16) { /* Already in RGB format */ rgb = (((rgb & 31) << 3) | ((rgb & 992) << 6)) | ((rgb & 31744) << 9); } else { rgb = rgb; } } b += rgb & 255; g += (((usqInt) rgb) >> 8) & 255; r += (((usqInt) rgb) >> 16) & 255; a += ((usqInt) rgb) >> 24; } xx += xdh; yy += ydh; } while(!(((k -= 1)) == 0)); x += xdv; y += ydv; } while(!(((j -= 1)) == 0)); if ((nPix == 0) || ((combinationRule == 25) && (nPix < (((sqInt) (n * n) >> 1))))) { /* All pixels were 0, or most were transparent */ rgb = 0; } else { if (nPix == 4) { /* normalize rgba sums */ /* Try to avoid divides for most common n */ r = ((usqInt) r) >> 2; g = ((usqInt) g) >> 2; b = ((usqInt) b) >> 2; a = ((usqInt) a) >> 2; } else { r = r / nPix; g = g / nPix; b = b / nPix; a = a / nPix; } /* map the pixel */ rgb = (((a << 24) + (r << 16)) + (g << 8)) + b; if (rgb == 0) { if ((((r + g) + b) + a) > 0) { /* only generate zero if pixel is really transparent */ rgb = 1; } } /* begin mapPixel:flags: */ pv = rgb; if ((cmFlags & ColorMapPresent) != 0) { if ((cmFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (rgb & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (rgb & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (rgb & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (rgb & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (rgb & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (rgb & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (rgb & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (rgb & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (rgb != 0)) { pv = 1; } } if ((cmFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } rgb = pv; } destWord = destWord | ((rgb & dstMask) << dstBitShift); dstBitShift += dstShiftInc; sx += xDeltah; sy += yDeltah; } while(!(((i -= 1)) == 0)); return destWord; } /* Pick n pixels from the source form, map by colorMap and return aligned by dstBitShift. This version is only called from WarpBlt with smoothingCount = 1 */ static sqInt warpPickSourcePixelsxDeltahyDeltahxDeltavyDeltavdstShiftIncflags(sqInt nPixels, sqInt xDeltah, sqInt yDeltah, sqInt xDeltav, sqInt yDeltav, sqInt dstShiftInc, sqInt mapperFlags) { sqInt destPix; sqInt destWord; sqInt dstMask; sqInt nPix; sqInt pv; sqInt sourcePix; sqInt sourcePix1; sqInt sourcePix2; sqInt sourceWord; sqInt sourceWord1; sqInt srcIndex; sqInt srcIndex1; sqInt val; sqInt x; sqInt x1; sqInt y; sqInt y1; /* Yepp - this should go into warpLoop */ dstMask = maskTable[destDepth]; destWord = 0; nPix = nPixels; if (mapperFlags == (ColorMapPresent | ColorMapIndexedPart)) { do { /* begin pickWarpPixelAtX:y: */ if ((sx < 0) || ((sy < 0) || ((((x = ((usqInt) sx) >> BinaryPoint)) >= sourceWidth) || (((y = ((usqInt) sy) >> BinaryPoint)) >= sourceHeight)))) { sourcePix = 0; goto l1; } srcIndex = (sourceBits + (y * sourcePitch)) + ((((usqInt) x) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord = long32AtPointer(srcIndex); srcBitShift = warpBitShiftTable[x & warpAlignMask]; sourcePix1 = (((usqInt) sourceWord) >> srcBitShift) & warpSrcMask; sourcePix = sourcePix1; l1: /* end pickWarpPixelAtX:y: */; destPix = cmLookupTable[sourcePix & cmMask]; destWord = destWord | ((destPix & dstMask) << dstBitShift); dstBitShift += dstShiftInc; sx += xDeltah; sy += yDeltah; } while(!(((nPix -= 1)) == 0)); } else { do { /* begin pickWarpPixelAtX:y: */ if ((sx < 0) || ((sy < 0) || ((((x1 = ((usqInt) sx) >> BinaryPoint)) >= sourceWidth) || (((y1 = ((usqInt) sy) >> BinaryPoint)) >= sourceHeight)))) { sourcePix = 0; goto l2; } srcIndex1 = (sourceBits + (y1 * sourcePitch)) + ((((usqInt) x1) >> warpAlignShift) * 4); /* Extract pixel from word */ sourceWord1 = long32AtPointer(srcIndex1); srcBitShift = warpBitShiftTable[x1 & warpAlignMask]; sourcePix2 = (((usqInt) sourceWord1) >> srcBitShift) & warpSrcMask; sourcePix = sourcePix2; l2: /* end pickWarpPixelAtX:y: */; /* begin mapPixel:flags: */ pv = sourcePix; if ((mapperFlags & ColorMapPresent) != 0) { if ((mapperFlags & ColorMapFixedPart) != 0) { /* begin rgbMapPixel:flags: */ val = (((cmShiftTable[0]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[0])) >> -(cmShiftTable[0])) : ((usqInt) (sourcePix & (cmMaskTable[0])) << (cmShiftTable[0]))); val = val | ((((cmShiftTable[1]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[1])) >> -(cmShiftTable[1])) : ((usqInt) (sourcePix & (cmMaskTable[1])) << (cmShiftTable[1])))); val = val | ((((cmShiftTable[2]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[2])) >> -(cmShiftTable[2])) : ((usqInt) (sourcePix & (cmMaskTable[2])) << (cmShiftTable[2])))); pv = val | ((((cmShiftTable[3]) < 0) ? ((usqInt) (sourcePix & (cmMaskTable[3])) >> -(cmShiftTable[3])) : ((usqInt) (sourcePix & (cmMaskTable[3])) << (cmShiftTable[3])))); if ((pv == 0) && (sourcePix != 0)) { pv = 1; } } if ((mapperFlags & ColorMapIndexedPart) != 0) { pv = cmLookupTable[pv & cmMask]; } } destPix = pv; destWord = destWord | ((destPix & dstMask) << dstBitShift); dstBitShift += dstShiftInc; sx += xDeltah; sy += yDeltah; } while(!(((nPix -= 1)) == 0)); } return destWord; } #ifdef SQUEAK_BUILTIN_PLUGIN void* BitBltPlugin_exports[][3] = { {"BitBltPlugin", "copyBits", (void*)copyBits}, {"BitBltPlugin", "copyBitsFromtoat", (void*)copyBitsFromtoat}, {"BitBltPlugin", "getModuleName", (void*)getModuleName}, {"BitBltPlugin", "initialiseModule", (void*)initialiseModule}, {"BitBltPlugin", "loadBitBltFrom", (void*)loadBitBltFrom}, {"BitBltPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"BitBltPlugin", "primitiveCopyBits", (void*)primitiveCopyBits}, {"BitBltPlugin", "primitiveDisplayString", (void*)primitiveDisplayString}, {"BitBltPlugin", "primitiveDrawLoop", (void*)primitiveDrawLoop}, {"BitBltPlugin", "primitiveWarpBits", (void*)primitiveWarpBits}, {"BitBltPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/CroquetPlugin/CroquetPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from CroquetPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "CroquetPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "CroquetPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveAdj3(void); EXPORT(sqInt) primitiveARC4Transform(void); EXPORT(sqInt) primitiveDet3(void); EXPORT(sqInt) primitiveGatherEntropy(void); EXPORT(sqInt) primitiveInplaceHouseHolderInvert(void); EXPORT(sqInt) primitiveInverseByAdjoint(void); EXPORT(sqInt) primitiveMD5Transform(void); EXPORT(sqInt) primitiveOrthoNormInverseMatrix(void); EXPORT(sqInt) primitiveTransformDirection(void); EXPORT(sqInt) primitiveTransformMatrixWithInto(void); EXPORT(sqInt) primitiveTransformVector3(void); EXPORT(sqInt) primitiveTransposeMatrix(void); EXPORT(sqInt) primitiveTriBoxIntersects(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void* stackMatrix(sqInt index); static void* stackVector3(sqInt index); static sqInt transformMatrixwithinto(float *src, float *arg, float *dst); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "CroquetPlugin VMMaker-oscog.dtl.57 (i)" #else "CroquetPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Computes the adjoint of the Matrix4x4 receiver, placing the results the the Matrix4x4 argument, */ EXPORT(sqInt) primitiveAdj3(void) { sqInt argc; const int c11 = 0; const int c12 = 1; const int c13 = 2; const int c21 = 4; const int c22 = 5; const int c23 = 6; const int c31 = 8; const int c32 = 9; const int c33 = 10; float *dst; sqInt dstOop; double m11; double m12; double m13; double m21; double m22; double m23; double m31; double m32; double m33; float *src; sqInt srcOop; ; argc = interpreterProxy->methodArgumentCount(); if (!(argc == 1)) { return interpreterProxy->primitiveFail(); } flag("stackArgv"); srcOop = interpreterProxy->stackObjectValue(argc); src = interpreterProxy->firstIndexableField(srcOop); dstOop = interpreterProxy->stackObjectValue(argc - 1); /* read in the source matrix 3x3, which contains the encoded rotation and scale factors */ dst = interpreterProxy->firstIndexableField(dstOop); m11 = src[c11]; m12 = src[c12]; m13 = src[c13]; m21 = src[c21]; m22 = src[c22]; m23 = src[c23]; m31 = src[c31]; m32 = src[c32]; /* do the actual work */ /* compute our cofactors and transpose. adj = transpose of cofactors */ m33 = src[c33]; dst[c11] = ((m22 * m33) - (m23 * m32)); dst[c21] = (0.0 - ((m21 * m33) - (m23 * m31))); dst[c31] = ((m21 * m32) - (m22 * m31)); dst[c12] = (0.0 - ((m12 * m33) - (m13 * m32))); dst[c22] = ((m11 * m33) - (m13 * m31)); dst[c32] = (0.0 - ((m11 * m32) - (m12 * m31))); dst[c13] = ((m12 * m23) - (m13 * m22)); dst[c23] = (0.0 - ((m11 * m23) - (m13 * m21))); dst[c33] = ((m11 * m22) - (m12 * m21)); interpreterProxy->pop(argc + 1); return interpreterProxy->push(dstOop); } /* Perform an ARC4 transform of input. Arguments: buffer <ByteArray> transformed data startIndex <Integer> start of transform stopIndex <Integer> end of transform m <ByteArray> key stream data x <Integer> key state value y <Integer> key state value Return value: x@y - updated key state value */ EXPORT(sqInt) primitiveARC4Transform(void) { sqInt a; sqInt b; unsigned char *buffer; sqInt bufOop; sqInt bufSize; sqInt i; unsigned char *m; sqInt mask; sqInt mOop; sqInt ptOop; sqInt startIndex; sqInt stopIndex; sqInt x; sqInt xOop; sqInt y; sqInt yOop; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } y = interpreterProxy->stackIntegerValue(0); x = interpreterProxy->stackIntegerValue(1); mOop = interpreterProxy->stackObjectValue(2); stopIndex = interpreterProxy->stackIntegerValue(3); startIndex = interpreterProxy->stackIntegerValue(4); bufOop = interpreterProxy->stackObjectValue(5); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isBytes(mOop)) && (interpreterProxy->isBytes(bufOop)))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->byteSizeOf(mOop)) == 256)) { return interpreterProxy->primitiveFail(); } bufSize = interpreterProxy->byteSizeOf(bufOop); if (!((startIndex > 0) && (startIndex <= bufSize))) { return interpreterProxy->primitiveFail(); } if (!((stopIndex >= startIndex) && (stopIndex <= bufSize))) { return interpreterProxy->primitiveFail(); } m = interpreterProxy->firstIndexableField(mOop); buffer = interpreterProxy->firstIndexableField(bufOop); for (i = (startIndex - 1); i <= (stopIndex - 1); i += 1) { x = (x + 1) & 255; a = m[x]; y = (y + a) & 255; b = m[y]; m[x] = b; m[y] = a; mask = m[(a + b) & 255]; buffer[i] = ((buffer[i]) ^ mask); } ptOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classPoint(), 0); interpreterProxy->pushRemappableOop(ptOop); xOop = interpreterProxy->positive32BitIntegerFor(x); interpreterProxy->pushRemappableOop(xOop); yOop = interpreterProxy->positive32BitIntegerFor(y); xOop = interpreterProxy->popRemappableOop(); ptOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, ptOop, xOop); interpreterProxy->storePointerofObjectwithValue(1, ptOop, yOop); interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); return interpreterProxy->push(ptOop); } /* Computes the determinant of the upper 3x3 of a Matrix4x4 */ EXPORT(sqInt) primitiveDet3(void) { sqInt argc; double det; double m11; double m12; double m13; double m21; double m22; double m23; double m31; double m32; double m33; float *src; sqInt srcOop; argc = interpreterProxy->methodArgumentCount(); if (!(argc == 0)) { return interpreterProxy->primitiveFail(); } flag("stackArgv"); srcOop = interpreterProxy->stackObjectValue(argc); src = interpreterProxy->firstIndexableField(srcOop); m11 = src[0]; m12 = src[1]; m13 = src[2]; m21 = src[4]; m22 = src[5]; m23 = src[6]; m31 = src[8]; m32 = src[9]; /* do the actual work */ m33 = src[10]; det = ((m11 * ((m22 * m33) - (m23 * m32))) + (m12 * ((m23 * m31) - (m21 * m33)))) + (m13 * ((m21 * m32) - (m22 * m31))); interpreterProxy->pop(argc + 1); return interpreterProxy->pushFloat(det); } /* Primitive. Gather good random entropy from a system source. */ EXPORT(sqInt) primitiveGatherEntropy(void) { sqInt bufOop; void *bufPtr; sqInt bufSize; sqInt okay; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } bufOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(bufOop))) { return interpreterProxy->primitiveFail(); } bufSize = interpreterProxy->byteSizeOf(bufOop); bufPtr = interpreterProxy->firstIndexableField(bufOop); okay = ioGatherEntropy(bufPtr, bufSize); if (!(okay)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); return interpreterProxy->pushBool(1); } /* Primitive. Perform an inplace house holder matrix inversion */ EXPORT(sqInt) primitiveInplaceHouseHolderInvert(void) { double beta; double d[4][4]; sqInt i; sqInt j; sqInt k; double m[4][4]; sqInt r; float *rcvr; double s; double sigma; double sum; double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; ; rcvr = stackMatrix(0); for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { (m[i])[j] = (rcvr[(i * 4) + j]); } } for (j = 0; j <= 3; j += 1) { sigma = 0.0; for (i = j; i <= 3; i += 1) { sigma += ((m[i])[j]) * ((m[i])[j]); } if (sigma < 1.0e-10) { return interpreterProxy->primitiveFail(); } if (((m[j])[j]) < 0.0) { s = sqrt(sigma); } else { s = 0.0 - (sqrt(sigma)); } for (r = 0; r <= 3; r += 1) { (d[j])[r] = s; } beta = 1.0 / ((s * ((m[j])[j])) - sigma); (m[j])[j] = (((m[j])[j]) - s); for (k = (j + 1); k <= 3; k += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((m[i])[j]) * ((m[i])[k]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (m[i])[k] = (((m[i])[k]) + (((m[i])[j]) * sum)); } } for (r = 0; r <= 3; r += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((x[i])[r]) * ((m[i])[j]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (x[i])[r] = (((x[i])[r]) + (sum * ((m[i])[j]))); } } } for (r = 0; r <= 3; r += 1) { for (i = 3; i >= 0; i += -1) { for (j = (i + 1); j <= 3; j += 1) { (x[i])[r] = (((x[i])[r]) - (((x[j])[r]) * ((m[i])[j]))); } (x[i])[r] = (((x[i])[r]) / ((d[i])[r])); } } for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { rcvr[(i * 4) + j] = (((float) ((x[i])[j]))); } } return null; } /* Computes the inverse of the Matrix4x4 receiver, using the 'classical adjoint' method, placing the results the the Matrix4x4 argument, */ EXPORT(sqInt) primitiveInverseByAdjoint(void) { sqInt argc; const int c11 = 0; const int c12 = 1; const int c13 = 2; const int c14 = 3; const int c21 = 4; const int c22 = 5; const int c23 = 6; const int c24 = 7; const int c31 = 8; const int c32 = 9; const int c33 = 10; const int c34 = 11; double det; float *dst; sqInt dstOop; double m11; double m12; double m13; double m21; double m22; double m23; double m31; double m32; double m33; float *src; sqInt srcOop; double x; double y; double z; ; argc = interpreterProxy->methodArgumentCount(); if (!(argc == 1)) { return interpreterProxy->primitiveFail(); } flag("stackArgv"); srcOop = interpreterProxy->stackObjectValue(argc); src = interpreterProxy->firstIndexableField(srcOop); dstOop = interpreterProxy->stackObjectValue(argc - 1); /* read in the source matrix 3x3, which contains the encoded rotation and scale factors */ dst = interpreterProxy->firstIndexableField(dstOop); m11 = src[c11]; m12 = src[c12]; m13 = src[c13]; m21 = src[c21]; m22 = src[c22]; m23 = src[c23]; m31 = src[c31]; m32 = src[c32]; /* read in the source translation vector */ m33 = src[c33]; x = src[c14]; y = src[c24]; /* do the actual work */ /* first, compute the determinant of the upper 3x3 of the source */ z = src[c34]; /* Compute the classical adjunct of the source, and divide by the source determinant storing in the destination. adjoint = transpose of cofactors, so we'll transpose as we store. */ det = ((m11 * ((m22 * m33) - (m23 * m32))) + (m12 * ((m23 * m31) - (m21 * m33)))) + (m13 * ((m21 * m32) - (m22 * m31))); /* let's make div by det a multiply */ det = 1 / det; dst[c11] = (((m22 * m33) - (m23 * m32)) * det); dst[c21] = ((0.0 - ((m21 * m33) - (m23 * m31))) * det); dst[c31] = (((m21 * m32) - (m22 * m31)) * det); dst[c12] = ((0.0 - ((m12 * m33) - (m13 * m32))) * det); dst[c22] = (((m11 * m33) - (m13 * m31)) * det); dst[c32] = ((0.0 - ((m11 * m32) - (m12 * m31))) * det); dst[c13] = (((m12 * m23) - (m13 * m22)) * det); dst[c23] = ((0.0 - ((m11 * m23) - (m13 * m21))) * det); dst[c33] = (((m11 * m22) - (m12 * m21)) * det); m11 = dst[c11]; m12 = dst[c12]; m13 = dst[c13]; m21 = dst[c21]; m22 = dst[c22]; m23 = dst[c23]; m31 = dst[c31]; m32 = dst[c32]; m33 = dst[c33]; dst[c14] = (0.0 - (((x * m11) + (y * m12)) + (z * m13))); dst[c24] = (0.0 - (((x * m21) + (y * m22)) + (z * m23))); dst[c34] = (0.0 - (((x * m31) + (y * m32)) + (z * m33))); interpreterProxy->pop(argc + 1); return interpreterProxy->push(dstOop); } /* Perform an MD5 transform of input */ EXPORT(sqInt) primitiveMD5Transform(void) { unsigned int *buffer; sqInt bufOop; unsigned int *hash; sqInt hashOop; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } hashOop = interpreterProxy->stackObjectValue(0); if (!((interpreterProxy->isWords(hashOop)) && ((interpreterProxy->slotSizeOf(hashOop)) == 4))) { return interpreterProxy->primitiveFail(); } hash = interpreterProxy->firstIndexableField(hashOop); bufOop = interpreterProxy->stackObjectValue(1); if (!((interpreterProxy->isWords(bufOop)) && ((interpreterProxy->slotSizeOf(bufOop)) == 16))) { return interpreterProxy->primitiveFail(); } buffer = interpreterProxy->firstIndexableField(bufOop); MD5Transform(hash, buffer); interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); return interpreterProxy->push(bufOop); } EXPORT(sqInt) primitiveOrthoNormInverseMatrix(void) { float *dst; sqInt dstOop; double rx; double ry; double rz; float *src; sqInt srcOop; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* Transpose upper 3x3 matrix */ /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[4] = (src[1]); dst[6] = (src[9]); dst[8] = (src[2]); dst[9] = (src[6]); x = src[3]; y = src[7]; z = src[11]; rx = ((x * (dst[0])) + (y * (dst[1]))) + (z * (dst[2])); ry = ((x * (dst[4])) + (y * (dst[5]))) + (z * (dst[6])); rz = ((x * (dst[8])) + (y * (dst[9]))) + (z * (dst[10])); dst[3] = (((float) (0.0 - rx))); dst[7] = (((float) (0.0 - ry))); dst[11] = (((float) (0.0 - rz))); interpreterProxy->pop(1); return interpreterProxy->push(dstOop); } EXPORT(sqInt) primitiveTransformDirection(void) { float *matrix; double rx; double ry; double rz; sqInt v3Oop; float *vertex; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); interpreterProxy->pop(2); return interpreterProxy->push(v3Oop); } /* Transform two matrices into the third */ EXPORT(sqInt) primitiveTransformMatrixWithInto(void) { double c1; double c2; double c3; double c4; sqInt i; float *m1; float *m11; float *m2; float *m21; float *m3; float *m31; m3 = stackMatrix(0); m2 = stackMatrix(1); m1 = stackMatrix(2); if (((m1 == null) || (m2 == null)) || (m3 == null)) { return interpreterProxy->primitiveFail(); } if (m2 == m3) { return interpreterProxy->primitiveFail(); } /* begin transformMatrix:with:into: */ m11 = ((float *) m1); m21 = ((float *) m2); m31 = ((float *) m3); for (i = 0; i <= 3; i += 1) { /* Compute next row */ c1 = ((((((double) (m11[0]) )) * (((double) (m21[0]) ))) + ((((double) (m11[1]) )) * (((double) (m21[4]) )))) + ((((double) (m11[2]) )) * (((double) (m21[8]) )))) + ((((double) (m11[3]) )) * (((double) (m21[12]) ))); c2 = ((((((double) (m11[0]) )) * (((double) (m21[1]) ))) + ((((double) (m11[1]) )) * (((double) (m21[5]) )))) + ((((double) (m11[2]) )) * (((double) (m21[9]) )))) + ((((double) (m11[3]) )) * (((double) (m21[13]) ))); c3 = ((((((double) (m11[0]) )) * (((double) (m21[2]) ))) + ((((double) (m11[1]) )) * (((double) (m21[6]) )))) + ((((double) (m11[2]) )) * (((double) (m21[10]) )))) + ((((double) (m11[3]) )) * (((double) (m21[14]) ))); /* Store result */ c4 = ((((((double) (m11[0]) )) * (((double) (m21[3]) ))) + ((((double) (m11[1]) )) * (((double) (m21[7]) )))) + ((((double) (m11[2]) )) * (((double) (m21[11]) )))) + ((((double) (m11[3]) )) * (((double) (m21[15]) ))); m31[0] = c1; m31[1] = c2; m31[2] = c3; m31[3] = c4; m11 += 4; m31 += 4; } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveTransformVector3(void) { float *matrix; double rw; double rx; double ry; double rz; sqInt v3Oop; float *vertex; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); if (rw == 1.0) { vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); } else { if (rw == 0.0) { rw = 0.0; } else { rw = 1.0 / rw; } vertex[0] = (((float) (rx * rw))); vertex[1] = (((float) (ry * rw))); vertex[2] = (((float) (rz * rw))); } interpreterProxy->pop(2); return interpreterProxy->push(v3Oop); } EXPORT(sqInt) primitiveTransposeMatrix(void) { float *dst; sqInt dstOop; float *src; sqInt srcOop; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[3] = (src[12]); dst[4] = (src[1]); dst[6] = (src[9]); dst[7] = (src[13]); dst[8] = (src[2]); dst[9] = (src[6]); dst[11] = (src[14]); dst[12] = (src[3]); dst[13] = (src[7]); dst[14] = (src[11]); interpreterProxy->pop(1); return interpreterProxy->push(dstOop); } /* Primitive. Answer whether an AABB intersects with a given triangle */ EXPORT(sqInt) primitiveTriBoxIntersects(void) { float *maxCorner; float *minCorner; sqInt result; float *v0; float *v1; float *v2; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } v2 = stackVector3(0); v1 = stackVector3(1); v0 = stackVector3(2); maxCorner = stackVector3(3); minCorner = stackVector3(4); result = triBoxOverlap(minCorner, maxCorner, v0, v1, v2); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(6); return interpreterProxy->pushBool(result); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Load a 4x4 transformation matrix from the interpreter stack. Return a pointer to the matrix data if successful, nil otherwise. */ static void* stackMatrix(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a Vector3 from the interpreter stack. Return a pointer to the float data if successful, nil otherwise. */ static void* stackVector3(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 3)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Transform src with arg into dst. It is allowed that src == dst but not arg == dst */ static sqInt transformMatrixwithinto(float *src, float *arg, float *dst) { double c1; double c2; double c3; double c4; sqInt i; float *m1; float *m2; float *m3; m1 = ((float *) src); m2 = ((float *) arg); m3 = ((float *) dst); for (i = 0; i <= 3; i += 1) { /* Compute next row */ c1 = ((((((double) (m1[0]) )) * (((double) (m2[0]) ))) + ((((double) (m1[1]) )) * (((double) (m2[4]) )))) + ((((double) (m1[2]) )) * (((double) (m2[8]) )))) + ((((double) (m1[3]) )) * (((double) (m2[12]) ))); c2 = ((((((double) (m1[0]) )) * (((double) (m2[1]) ))) + ((((double) (m1[1]) )) * (((double) (m2[5]) )))) + ((((double) (m1[2]) )) * (((double) (m2[9]) )))) + ((((double) (m1[3]) )) * (((double) (m2[13]) ))); c3 = ((((((double) (m1[0]) )) * (((double) (m2[2]) ))) + ((((double) (m1[1]) )) * (((double) (m2[6]) )))) + ((((double) (m1[2]) )) * (((double) (m2[10]) )))) + ((((double) (m1[3]) )) * (((double) (m2[14]) ))); /* Store result */ c4 = ((((((double) (m1[0]) )) * (((double) (m2[3]) ))) + ((((double) (m1[1]) )) * (((double) (m2[7]) )))) + ((((double) (m1[2]) )) * (((double) (m2[11]) )))) + ((((double) (m1[3]) )) * (((double) (m2[15]) ))); m3[0] = c1; m3[1] = c2; m3[2] = c3; m3[3] = c4; m1 += 4; m3 += 4; } return null; } #ifdef SQUEAK_BUILTIN_PLUGIN void* CroquetPlugin_exports[][3] = { {"CroquetPlugin", "getModuleName", (void*)getModuleName}, {"CroquetPlugin", "primitiveAdj3", (void*)primitiveAdj3}, {"CroquetPlugin", "primitiveARC4Transform", (void*)primitiveARC4Transform}, {"CroquetPlugin", "primitiveDet3", (void*)primitiveDet3}, {"CroquetPlugin", "primitiveGatherEntropy", (void*)primitiveGatherEntropy}, {"CroquetPlugin", "primitiveInplaceHouseHolderInvert", (void*)primitiveInplaceHouseHolderInvert}, {"CroquetPlugin", "primitiveInverseByAdjoint", (void*)primitiveInverseByAdjoint}, {"CroquetPlugin", "primitiveMD5Transform", (void*)primitiveMD5Transform}, {"CroquetPlugin", "primitiveOrthoNormInverseMatrix", (void*)primitiveOrthoNormInverseMatrix}, {"CroquetPlugin", "primitiveTransformDirection", (void*)primitiveTransformDirection}, {"CroquetPlugin", "primitiveTransformMatrixWithInto", (void*)primitiveTransformMatrixWithInto}, {"CroquetPlugin", "primitiveTransformVector3", (void*)primitiveTransformVector3}, {"CroquetPlugin", "primitiveTransposeMatrix", (void*)primitiveTransposeMatrix}, {"CroquetPlugin", "primitiveTriBoxIntersects", (void*)primitiveTriBoxIntersects}, {"CroquetPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/DSAPrims/DSAPrims.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from DSAPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "DSAPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt addBackDivisorDigitShift(sqInt digitShift); static sqInt bigDivideLoop(void); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt leftRotateby(unsigned int anInteger, sqInt bits); static sqInt msg(char *s); EXPORT(sqInt) primitiveBigDivide(void); EXPORT(sqInt) primitiveBigMultiply(void); EXPORT(sqInt) primitiveExpandBlock(void); EXPORT(sqInt) primitiveHashBlock(void); EXPORT(sqInt) primitiveHasSecureHashPrimitive(void); EXPORT(sqInt) primitiveHighestNonZeroDigitIndex(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt subtractDivisorMultipliedByDigitdigitShift(sqInt digit, sqInt digitShift); /*** Variables ***/ static sqInt divisorDigitCount; static unsigned char* dsaDivisor; static unsigned char* dsaQuotient; static unsigned char* dsaRemainder; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "DSAPrims VMMaker-oscog.dtl.57 (i)" #else "DSAPrims VMMaker-oscog.dtl.57 (e)" #endif ; static sqInt remainderDigitCount; /* Add back the divisor shifted left by the given number of digits. This is done only when the estimate of quotient digit was one larger than the correct value. */ static sqInt addBackDivisorDigitShift(sqInt digitShift) { sqInt carry; sqInt i; sqInt rIndex; sqInt sum; carry = 0; rIndex = digitShift + 1; for (i = 1; i <= divisorDigitCount; i += 1) { sum = ((dsaRemainder[rIndex]) + (dsaDivisor[i])) + carry; dsaRemainder[rIndex] = (sum & 255); carry = ((usqInt) sum >> 8); rIndex += 1; } sum = (dsaRemainder[rIndex]) + carry; dsaRemainder[rIndex] = (sum & 255); } /* This is the core of the divide algorithm. This loop steps through the digit positions of the quotient, each time estimating the right quotient digit, subtracting from the remainder the divisor times the quotient digit shifted left by the appropriate number of digits. When the loop terminates, all digits of the quotient have been filled in and the remainder contains a value less than the divisor. The tricky bit is estimating the next quotient digit. Knuth shows that the digit estimate computed here will never be less than it should be and cannot be more than one over what it should be. Furthermore, the case where the estimate is one too large is extremely rare. For example, in a typical test of 100000 random 60-bit division problems, the rare case only occured five times. See Knuth, volume 2 ('Semi-Numerical Algorithms') 2nd edition, pp. 257-260 */ /* extract the top two digits of the divisor */ static sqInt bigDivideLoop(void) { sqInt borrow; sqInt carry; sqInt d1; sqInt d2; sqInt digitShift; sqInt firstDigit; sqInt firstTwoDigits; sqInt i; sqInt i1; sqInt j; sqInt prod; sqInt q; sqInt qTooBig; sqInt resultDigit; sqInt rIndex; sqInt rIndex1; sqInt sum; sqInt thirdDigit; d1 = dsaDivisor[divisorDigitCount]; d2 = dsaDivisor[divisorDigitCount - 1]; for (j = remainderDigitCount; j >= (divisorDigitCount + 1); j += -1) { /* extract the top several digits of remainder. */ firstDigit = dsaRemainder[j]; firstTwoDigits = (((usqInt) firstDigit << 8)) + (dsaRemainder[j - 1]); /* estimate q, the next digit of the quotient */ thirdDigit = dsaRemainder[j - 2]; if (firstDigit == d1) { q = 255; } else { q = firstTwoDigits / d1; } if ((d2 * q) > ((((usqInt) (firstTwoDigits - (q * d1)) << 8)) + thirdDigit)) { q -= 1; if ((d2 * q) > ((((usqInt) (firstTwoDigits - (q * d1)) << 8)) + thirdDigit)) { q -= 1; } } digitShift = (j - divisorDigitCount) - 1; if (q > 0) { /* begin subtractDivisorMultipliedByDigit:digitShift: */ borrow = 0; rIndex1 = digitShift + 1; for (i1 = 1; i1 <= divisorDigitCount; i1 += 1) { prod = ((dsaDivisor[i1]) * q) + borrow; borrow = ((usqInt) prod >> 8); resultDigit = (dsaRemainder[rIndex1]) - (prod & 255); if (resultDigit < 0) { /* borrow from the next digit */ resultDigit += 256; borrow += 1; } dsaRemainder[rIndex1] = resultDigit; rIndex1 += 1; } if (borrow == 0) { qTooBig = 0; goto l1; } resultDigit = (dsaRemainder[rIndex1]) - borrow; if (resultDigit < 0) { dsaRemainder[rIndex1] = (resultDigit + 256); qTooBig = 1; goto l1; } else { dsaRemainder[rIndex1] = resultDigit; qTooBig = 0; goto l1; } l1: /* end subtractDivisorMultipliedByDigit:digitShift: */; if (qTooBig) { /* begin addBackDivisorDigitShift: */ carry = 0; rIndex = digitShift + 1; for (i = 1; i <= divisorDigitCount; i += 1) { sum = ((dsaRemainder[rIndex]) + (dsaDivisor[i])) + carry; dsaRemainder[rIndex] = (sum & 255); carry = ((usqInt) sum >> 8); rIndex += 1; } sum = (dsaRemainder[rIndex]) + carry; dsaRemainder[rIndex] = (sum & 255); q -= 1; } } dsaQuotient[digitShift + 1] = q; } } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* Rotate the given 32-bit integer left by the given number of bits and answer the result. */ static sqInt leftRotateby(unsigned int anInteger, sqInt bits) { return (anInteger << bits) | (((usqInt) anInteger) >> (32 - bits)); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Called with three LargePositiveInteger arguments, rem, div, quo. Divide div into rem and store the quotient into quo, leaving the remainder in rem. */ /* Assume: quo starts out filled with zeros. */ EXPORT(sqInt) primitiveBigDivide(void) { sqInt borrow; sqInt carry; sqInt d1; sqInt d2; sqInt digitShift; sqInt div; sqInt firstDigit; sqInt firstTwoDigits; sqInt i; sqInt i1; sqInt j; sqInt prod; sqInt q; sqInt qTooBig; sqInt quo; sqInt rem; sqInt resultDigit; sqInt rIndex; sqInt rIndex1; sqInt sum; sqInt thirdDigit; quo = interpreterProxy->stackObjectValue(0); div = interpreterProxy->stackObjectValue(1); rem = interpreterProxy->stackObjectValue(2); interpreterProxy->success((interpreterProxy->fetchClassOf(rem)) == (interpreterProxy->classLargePositiveInteger())); interpreterProxy->success((interpreterProxy->fetchClassOf(div)) == (interpreterProxy->classLargePositiveInteger())); interpreterProxy->success((interpreterProxy->fetchClassOf(quo)) == (interpreterProxy->classLargePositiveInteger())); if (interpreterProxy->failed()) { return null; } dsaRemainder = interpreterProxy->firstIndexableField(rem); dsaDivisor = interpreterProxy->firstIndexableField(div); dsaQuotient = interpreterProxy->firstIndexableField(quo); divisorDigitCount = interpreterProxy->stSizeOf(div); /* adjust pointers for base-1 indexing */ remainderDigitCount = interpreterProxy->stSizeOf(rem); dsaRemainder -= 1; dsaDivisor -= 1; dsaQuotient -= 1; /* begin bigDivideLoop */ d1 = dsaDivisor[divisorDigitCount]; d2 = dsaDivisor[divisorDigitCount - 1]; for (j = remainderDigitCount; j >= (divisorDigitCount + 1); j += -1) { /* extract the top several digits of remainder. */ firstDigit = dsaRemainder[j]; firstTwoDigits = (((usqInt) firstDigit << 8)) + (dsaRemainder[j - 1]); /* estimate q, the next digit of the quotient */ thirdDigit = dsaRemainder[j - 2]; if (firstDigit == d1) { q = 255; } else { q = firstTwoDigits / d1; } if ((d2 * q) > ((((usqInt) (firstTwoDigits - (q * d1)) << 8)) + thirdDigit)) { q -= 1; if ((d2 * q) > ((((usqInt) (firstTwoDigits - (q * d1)) << 8)) + thirdDigit)) { q -= 1; } } digitShift = (j - divisorDigitCount) - 1; if (q > 0) { /* begin subtractDivisorMultipliedByDigit:digitShift: */ borrow = 0; rIndex1 = digitShift + 1; for (i1 = 1; i1 <= divisorDigitCount; i1 += 1) { prod = ((dsaDivisor[i1]) * q) + borrow; borrow = ((usqInt) prod >> 8); resultDigit = (dsaRemainder[rIndex1]) - (prod & 255); if (resultDigit < 0) { /* borrow from the next digit */ resultDigit += 256; borrow += 1; } dsaRemainder[rIndex1] = resultDigit; rIndex1 += 1; } if (borrow == 0) { qTooBig = 0; goto l1; } resultDigit = (dsaRemainder[rIndex1]) - borrow; if (resultDigit < 0) { dsaRemainder[rIndex1] = (resultDigit + 256); qTooBig = 1; goto l1; } else { dsaRemainder[rIndex1] = resultDigit; qTooBig = 0; goto l1; } l1: /* end subtractDivisorMultipliedByDigit:digitShift: */; if (qTooBig) { /* begin addBackDivisorDigitShift: */ carry = 0; rIndex = digitShift + 1; for (i = 1; i <= divisorDigitCount; i += 1) { sum = ((dsaRemainder[rIndex]) + (dsaDivisor[i])) + carry; dsaRemainder[rIndex] = (sum & 255); carry = ((usqInt) sum >> 8); rIndex += 1; } sum = (dsaRemainder[rIndex]) + carry; dsaRemainder[rIndex] = (sum & 255); q -= 1; } } dsaQuotient[digitShift + 1] = q; } interpreterProxy->pop(3); } /* Multiple f1 by f2, placing the result into prod. f1, f2, and prod must be LargePositiveIntegers, and the length of prod must be the sum of the lengths of f1 and f2. */ /* Assume: prod starts out filled with zeros */ EXPORT(sqInt) primitiveBigMultiply(void) { sqInt carry; sqInt digit; sqInt f1; sqInt f1Len; unsigned char *f1Ptr; sqInt f2; sqInt f2Len; unsigned char *f2Ptr; sqInt i; sqInt j; sqInt k; sqInt prod; sqInt prodLen; unsigned char *prodPtr; sqInt sum; prod = interpreterProxy->stackObjectValue(0); f2 = interpreterProxy->stackObjectValue(1); f1 = interpreterProxy->stackObjectValue(2); interpreterProxy->success(interpreterProxy->isBytes(prod)); interpreterProxy->success(interpreterProxy->isBytes(f2)); interpreterProxy->success(interpreterProxy->isBytes(f1)); interpreterProxy->success((interpreterProxy->fetchClassOf(prod)) == (interpreterProxy->classLargePositiveInteger())); interpreterProxy->success((interpreterProxy->fetchClassOf(f2)) == (interpreterProxy->classLargePositiveInteger())); interpreterProxy->success((interpreterProxy->fetchClassOf(f1)) == (interpreterProxy->classLargePositiveInteger())); if (interpreterProxy->failed()) { return null; } prodLen = interpreterProxy->stSizeOf(prod); f1Len = interpreterProxy->stSizeOf(f1); f2Len = interpreterProxy->stSizeOf(f2); interpreterProxy->success(prodLen == (f1Len + f2Len)); if (interpreterProxy->failed()) { return null; } prodPtr = interpreterProxy->firstIndexableField(prod); f2Ptr = interpreterProxy->firstIndexableField(f2); f1Ptr = interpreterProxy->firstIndexableField(f1); for (i = 0; i <= (f1Len - 1); i += 1) { if (((digit = f1Ptr[i])) != 0) { carry = 0; /* Loop invariants: 0 <= carry <= 16rFF, k = i + j - 1 */ k = i; for (j = 0; j <= (f2Len - 1); j += 1) { sum = (((f2Ptr[j]) * digit) + (prodPtr[k])) + carry; carry = ((usqInt) sum >> 8); prodPtr[k] = (sum & 255); k += 1; } prodPtr[k] = carry; } } interpreterProxy->pop(3); } /* Expand a 64 byte ByteArray (the first argument) into and an Bitmap of 80 32-bit words (the second argument). When reading a 32-bit integer from the ByteArray, consider the first byte to contain the most significant bits of the word (i.e., use big-endian byte ordering). */ EXPORT(sqInt) primitiveExpandBlock(void) { sqInt buf; unsigned char *bytePtr; sqInt expanded; sqInt i; sqInt src; sqInt v; unsigned int *wordPtr; expanded = interpreterProxy->stackObjectValue(0); buf = interpreterProxy->stackObjectValue(1); interpreterProxy->success(interpreterProxy->isWords(expanded)); interpreterProxy->success(interpreterProxy->isBytes(buf)); if (interpreterProxy->failed()) { return null; } interpreterProxy->success((interpreterProxy->stSizeOf(expanded)) == 80); interpreterProxy->success((interpreterProxy->stSizeOf(buf)) == 64); if (interpreterProxy->failed()) { return null; } wordPtr = interpreterProxy->firstIndexableField(expanded); bytePtr = interpreterProxy->firstIndexableField(buf); src = 0; for (i = 0; i <= 15; i += 1) { v = ((((bytePtr[src]) << 24) + ((bytePtr[src + 1]) << 16)) + ((bytePtr[src + 2]) << 8)) + (bytePtr[src + 3]); wordPtr[i] = v; src += 4; } for (i = 16; i <= 79; i += 1) { v = (((wordPtr[i - 3]) ^ (wordPtr[i - 8])) ^ (wordPtr[i - 14])) ^ (wordPtr[i - 16]); v = (v << 1) | (((usqInt) v) >> (32 - 1)); wordPtr[i] = v; } interpreterProxy->pop(2); } /* Hash a Bitmap of 80 32-bit words (the first argument), using the given state (the second argument). */ EXPORT(sqInt) primitiveHashBlock(void) { sqInt a; sqInt b; sqInt buf; unsigned int *bufPtr; sqInt c; sqInt d; sqInt e; sqInt i; sqInt state; unsigned int *statePtr; sqInt tmp; state = interpreterProxy->stackObjectValue(0); buf = interpreterProxy->stackObjectValue(1); interpreterProxy->success(interpreterProxy->isWords(state)); interpreterProxy->success(interpreterProxy->isWords(buf)); if (interpreterProxy->failed()) { return null; } interpreterProxy->success((interpreterProxy->stSizeOf(state)) == 5); interpreterProxy->success((interpreterProxy->stSizeOf(buf)) == 80); if (interpreterProxy->failed()) { return null; } statePtr = interpreterProxy->firstIndexableField(state); bufPtr = interpreterProxy->firstIndexableField(buf); a = statePtr[0]; b = statePtr[1]; c = statePtr[2]; d = statePtr[3]; e = statePtr[4]; for (i = 0; i <= 19; i += 1) { tmp = (((1518500249 + ((b & c) | ((~b) & d))) + ((a << 5) | (((usqInt) a) >> (32 - 5)))) + e) + (bufPtr[i]); e = d; d = c; c = (b << 30) | (((usqInt) b) >> (32 - 30)); b = a; a = tmp; } for (i = 20; i <= 39; i += 1) { tmp = (((1859775393 + ((b ^ c) ^ d)) + ((a << 5) | (((usqInt) a) >> (32 - 5)))) + e) + (bufPtr[i]); e = d; d = c; c = (b << 30) | (((usqInt) b) >> (32 - 30)); b = a; a = tmp; } for (i = 40; i <= 59; i += 1) { tmp = (((2400959708UL + (((b & c) | (b & d)) | (c & d))) + ((a << 5) | (((usqInt) a) >> (32 - 5)))) + e) + (bufPtr[i]); e = d; d = c; c = (b << 30) | (((usqInt) b) >> (32 - 30)); b = a; a = tmp; } for (i = 60; i <= 79; i += 1) { tmp = (((3395469782UL + ((b ^ c) ^ d)) + ((a << 5) | (((usqInt) a) >> (32 - 5)))) + e) + (bufPtr[i]); e = d; d = c; c = (b << 30) | (((usqInt) b) >> (32 - 30)); b = a; a = tmp; } statePtr[0] = ((statePtr[0]) + a); statePtr[1] = ((statePtr[1]) + b); statePtr[2] = ((statePtr[2]) + c); statePtr[3] = ((statePtr[3]) + d); statePtr[4] = ((statePtr[4]) + e); interpreterProxy->pop(2); } /* Answer true if the secure hash primitive is implemented. */ EXPORT(sqInt) primitiveHasSecureHashPrimitive(void) { interpreterProxy->pop(1); interpreterProxy->pushBool(1); } /* Called with one LargePositiveInteger argument. Answer the index of the top-most non-zero digit. */ EXPORT(sqInt) primitiveHighestNonZeroDigitIndex(void) { sqInt arg; unsigned char *bigIntPtr; sqInt i; arg = interpreterProxy->stackObjectValue(0); interpreterProxy->success((interpreterProxy->fetchClassOf(arg)) == (interpreterProxy->classLargePositiveInteger())); if (interpreterProxy->failed()) { return null; } bigIntPtr = interpreterProxy->firstIndexableField(arg); i = interpreterProxy->stSizeOf(arg); while ((i > 0) && ((bigIntPtr[(i -= 1)]) == 0)) { } interpreterProxy->pop(1); interpreterProxy->pushInteger(i + 1); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Multiply the divisor by the given digit (an integer in the range 0..255), shift it left by the given number of digits, and subtract the result from the current remainder. Answer true if there is an excess borrow, indicating that digit was one too large. (This case is quite rare.) */ static sqInt subtractDivisorMultipliedByDigitdigitShift(sqInt digit, sqInt digitShift) { sqInt borrow; sqInt i; sqInt prod; sqInt resultDigit; sqInt rIndex; borrow = 0; rIndex = digitShift + 1; for (i = 1; i <= divisorDigitCount; i += 1) { prod = ((dsaDivisor[i]) * digit) + borrow; borrow = ((usqInt) prod >> 8); resultDigit = (dsaRemainder[rIndex]) - (prod & 255); if (resultDigit < 0) { /* borrow from the next digit */ resultDigit += 256; borrow += 1; } dsaRemainder[rIndex] = resultDigit; rIndex += 1; } if (borrow == 0) { return 0; } resultDigit = (dsaRemainder[rIndex]) - borrow; if (resultDigit < 0) { dsaRemainder[rIndex] = (resultDigit + 256); return 1; } else { dsaRemainder[rIndex] = resultDigit; return 0; } } #ifdef SQUEAK_BUILTIN_PLUGIN void* DSAPrims_exports[][3] = { {"DSAPrims", "getModuleName", (void*)getModuleName}, {"DSAPrims", "primitiveBigDivide", (void*)primitiveBigDivide}, {"DSAPrims", "primitiveBigMultiply", (void*)primitiveBigMultiply}, {"DSAPrims", "primitiveExpandBlock", (void*)primitiveExpandBlock}, {"DSAPrims", "primitiveHashBlock", (void*)primitiveHashBlock}, {"DSAPrims", "primitiveHasSecureHashPrimitive", (void*)primitiveHasSecureHashPrimitive}, {"DSAPrims", "primitiveHighestNonZeroDigitIndex", (void*)primitiveHighestNonZeroDigitIndex}, {"DSAPrims", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/DropPlugin/DropPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from DropPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "DropPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "DropPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveDropRequestFileHandle(void); EXPORT(sqInt) primitiveDropRequestFileName(void); EXPORT(sqInt) setFileAccessCallback(int address); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "DropPlugin VMMaker-oscog.dtl.57 (i)" #else "DropPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return dropInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Note: File handle creation needs to be handled by specific support code explicitly bypassing the plugin file sand box. */ EXPORT(sqInt) primitiveDropRequestFileHandle(void) { sqInt dropIndex; sqInt handleOop; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } dropIndex = interpreterProxy->stackIntegerValue(0); /* dropRequestFileHandle needs to return the actual oop returned */ handleOop = dropRequestFileHandle(dropIndex); if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); interpreterProxy->push(handleOop); } } /* Note: File handle creation needs to be handled by specific support code explicitly bypassing the plugin file sand box. */ EXPORT(sqInt) primitiveDropRequestFileName(void) { sqInt dropIndex; char *dropName; sqInt i; sqInt nameLength; sqInt nameOop; char *namePtr; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } dropIndex = interpreterProxy->stackIntegerValue(0); /* dropRequestFileName returns name or NULL on error */ dropName = dropRequestFileName(dropIndex); if (dropName == null) { return interpreterProxy->primitiveFail(); } nameLength = strlen(dropName); nameOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), nameLength); namePtr = interpreterProxy->firstIndexableField(nameOop); for (i = 0; i <= (nameLength - 1); i += 1) { namePtr[i] = (dropName[i]); } interpreterProxy->pop(2); interpreterProxy->push(nameOop); } EXPORT(sqInt) setFileAccessCallback(int address) { return sqSecFileAccessCallback((void *) address); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return dropShutdown(); } #ifdef SQUEAK_BUILTIN_PLUGIN void* DropPlugin_exports[][3] = { {"DropPlugin", "getModuleName", (void*)getModuleName}, {"DropPlugin", "initialiseModule", (void*)initialiseModule}, {"DropPlugin", "primitiveDropRequestFileHandle", (void*)primitiveDropRequestFileHandle}, {"DropPlugin", "primitiveDropRequestFileName", (void*)primitiveDropRequestFileName}, {"DropPlugin", "setFileAccessCallback", (void*)setFileAccessCallback}, {"DropPlugin", "setInterpreter", (void*)setInterpreter}, {"DropPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FFTPlugin/FFTPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from FFTPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "FFTPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static float * checkedFloatPtrOf(sqInt oop); static unsigned int * checkedWordPtrOf(sqInt oop); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt loadFFTFrom(sqInt fftOop); static sqInt msg(char *s); static sqInt permuteData(void); EXPORT(sqInt) primitiveFFTPermuteData(void); EXPORT(sqInt) primitiveFFTScaleData(void); EXPORT(sqInt) primitiveFFTTransformData(void); static sqInt scaleData(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt transformData(sqInt forward); static sqInt transformForward(sqInt forward); /*** Variables ***/ static sqInt fftSize; static float * imagData; static sqInt imagDataSize; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FFTPlugin VMMaker-oscog.dtl.57 (i)" #else "FFTPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static sqInt nu; static unsigned int * permTable; static sqInt permTableSize; static float * realData; static sqInt realDataSize; static float * sinTable; static sqInt sinTableSize; /* Return the first indexable word of oop which is assumed to be variableWordSubclass */ static float * checkedFloatPtrOf(sqInt oop) { interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { return 0; } return ((float *) (interpreterProxy->firstIndexableField(oop))); } /* Return the first indexable word of oop which is assumed to be variableWordSubclass */ static unsigned int * checkedWordPtrOf(sqInt oop) { interpreterProxy->success(interpreterProxy->isWords(oop)); return ((unsigned int *) (interpreterProxy->firstIndexableField(oop))); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt loadFFTFrom(sqInt fftOop) { sqInt oop; interpreterProxy->success((interpreterProxy->slotSizeOf(fftOop)) >= 6); if (interpreterProxy->failed()) { return 0; } nu = interpreterProxy->fetchIntegerofObject(0, fftOop); fftSize = interpreterProxy->fetchIntegerofObject(1, fftOop); oop = interpreterProxy->fetchPointerofObject(2, fftOop); sinTableSize = interpreterProxy->stSizeOf(oop); /* begin checkedFloatPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { sinTable = 0; goto l1; } sinTable = ((float *) (interpreterProxy->firstIndexableField(oop))); l1: /* end checkedFloatPtrOf: */; oop = interpreterProxy->fetchPointerofObject(3, fftOop); permTableSize = interpreterProxy->stSizeOf(oop); /* begin checkedWordPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(oop)); permTable = ((unsigned int *) (interpreterProxy->firstIndexableField(oop))); oop = interpreterProxy->fetchPointerofObject(4, fftOop); realDataSize = interpreterProxy->stSizeOf(oop); /* begin checkedFloatPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { realData = 0; goto l2; } realData = ((float *) (interpreterProxy->firstIndexableField(oop))); l2: /* end checkedFloatPtrOf: */; oop = interpreterProxy->fetchPointerofObject(5, fftOop); imagDataSize = interpreterProxy->stSizeOf(oop); /* begin checkedFloatPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { imagData = 0; goto l3; } imagData = ((float *) (interpreterProxy->firstIndexableField(oop))); l3: /* end checkedFloatPtrOf: */; interpreterProxy->success((((((1 << nu) == fftSize) && (((((sqInt) fftSize >> 2)) + 1) == sinTableSize)) && (fftSize == realDataSize)) && (fftSize == imagDataSize)) && (realDataSize == imagDataSize)); return (interpreterProxy->failed()) == 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } static sqInt permuteData(void) { sqInt a; sqInt b; sqInt end; sqInt i; float tmp; i = 0; end = permTableSize; while (i < end) { a = (permTable[i]) - 1; b = (permTable[i + 1]) - 1; if (!((a < realDataSize) && (b < realDataSize))) { return interpreterProxy->success(0); } tmp = realData[a]; realData[a] = (realData[b]); realData[b] = tmp; tmp = imagData[a]; imagData[a] = (imagData[b]); imagData[b] = tmp; i += 2; } } EXPORT(sqInt) primitiveFFTPermuteData(void) { sqInt rcvr; rcvr = interpreterProxy->stackObjectValue(0); if (!(loadFFTFrom(rcvr))) { return null; } permuteData(); if (interpreterProxy->failed()) { permuteData(); } } EXPORT(sqInt) primitiveFFTScaleData(void) { sqInt rcvr; rcvr = interpreterProxy->stackObjectValue(0); if (!(loadFFTFrom(rcvr))) { return null; } scaleData(); } EXPORT(sqInt) primitiveFFTTransformData(void) { sqInt fftScale; sqInt fftSize2; sqInt fftSize4; sqInt forward; sqInt i; sqInt ii; float imagT; float imagU; sqInt ip; sqInt j; sqInt lev; sqInt lev1; sqInt level; sqInt rcvr; float realT; float realU; sqInt theta; forward = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); rcvr = interpreterProxy->stackObjectValue(1); if (!(loadFFTFrom(rcvr))) { return null; } /* begin transformData: */ permuteData(); if (interpreterProxy->failed()) { permuteData(); goto l1; } /* begin transformForward: */ fftSize2 = ((sqInt) fftSize >> 1); fftSize4 = ((sqInt) fftSize >> 2); for (level = 1; level <= nu; level += 1) { lev = ((level < 0) ? ((usqInt) 1 >> -level) : ((usqInt) 1 << level)); lev1 = ((sqInt) lev >> 1); fftScale = fftSize / lev; for (j = 1; j <= lev1; j += 1) { /* pi * (j-1) / lev1 mapped onto 0..n/2 */ theta = (j - 1) * fftScale; if (theta < fftSize4) { /* Compute U, the complex multiplier for each level */ realU = sinTable[(sinTableSize - theta) - 1]; imagU = sinTable[theta]; } else { realU = 0.0 - (sinTable[theta - fftSize4]); imagU = sinTable[fftSize2 - theta]; } if (!(forward)) { imagU = 0.0 - imagU; } i = j; while (i <= fftSize) { ip = (i + lev1) - 1; ii = i - 1; realT = ((realData[ip]) * realU) - ((imagData[ip]) * imagU); imagT = ((realData[ip]) * imagU) + ((imagData[ip]) * realU); realData[ip] = ((realData[ii]) - realT); imagData[ip] = ((imagData[ii]) - imagT); realData[ii] = ((realData[ii]) + realT); imagData[ii] = ((imagData[ii]) + imagT); i += lev; } } } if (!(forward)) { scaleData(); } l1: /* end transformData: */; if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } /* Scale all elements by 1/n when doing inverse */ static sqInt scaleData(void) { sqInt i; float realN; if (fftSize <= 1) { return null; } realN = ((float) (1.0 / (((double) fftSize)))); for (i = 0; i <= (fftSize - 1); i += 1) { realData[i] = ((realData[i]) * realN); imagData[i] = ((imagData[i]) * realN); } } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt transformData(sqInt forward) { sqInt fftScale; sqInt fftSize2; sqInt fftSize4; sqInt i; sqInt ii; float imagT; float imagU; sqInt ip; sqInt j; sqInt lev; sqInt lev1; sqInt level; float realT; float realU; sqInt theta; permuteData(); if (interpreterProxy->failed()) { permuteData(); return null; } /* begin transformForward: */ fftSize2 = ((sqInt) fftSize >> 1); fftSize4 = ((sqInt) fftSize >> 2); for (level = 1; level <= nu; level += 1) { lev = ((level < 0) ? ((usqInt) 1 >> -level) : ((usqInt) 1 << level)); lev1 = ((sqInt) lev >> 1); fftScale = fftSize / lev; for (j = 1; j <= lev1; j += 1) { /* pi * (j-1) / lev1 mapped onto 0..n/2 */ theta = (j - 1) * fftScale; if (theta < fftSize4) { /* Compute U, the complex multiplier for each level */ realU = sinTable[(sinTableSize - theta) - 1]; imagU = sinTable[theta]; } else { realU = 0.0 - (sinTable[theta - fftSize4]); imagU = sinTable[fftSize2 - theta]; } if (!(forward)) { imagU = 0.0 - imagU; } i = j; while (i <= fftSize) { ip = (i + lev1) - 1; ii = i - 1; realT = ((realData[ip]) * realU) - ((imagData[ip]) * imagU); imagT = ((realData[ip]) * imagU) + ((imagData[ip]) * realU); realData[ip] = ((realData[ii]) - realT); imagData[ip] = ((imagData[ii]) - imagT); realData[ii] = ((realData[ii]) + realT); imagData[ii] = ((imagData[ii]) + imagT); i += lev; } } } if (!(forward)) { scaleData(); } } static sqInt transformForward(sqInt forward) { sqInt fftScale; sqInt fftSize2; sqInt fftSize4; sqInt i; sqInt ii; float imagT; float imagU; sqInt ip; sqInt j; sqInt lev; sqInt lev1; sqInt level; float realT; float realU; sqInt theta; fftSize2 = ((sqInt) fftSize >> 1); fftSize4 = ((sqInt) fftSize >> 2); for (level = 1; level <= nu; level += 1) { lev = ((level < 0) ? ((usqInt) 1 >> -level) : ((usqInt) 1 << level)); lev1 = ((sqInt) lev >> 1); fftScale = fftSize / lev; for (j = 1; j <= lev1; j += 1) { /* pi * (j-1) / lev1 mapped onto 0..n/2 */ theta = (j - 1) * fftScale; if (theta < fftSize4) { /* Compute U, the complex multiplier for each level */ realU = sinTable[(sinTableSize - theta) - 1]; imagU = sinTable[theta]; } else { realU = 0.0 - (sinTable[theta - fftSize4]); imagU = sinTable[fftSize2 - theta]; } if (!(forward)) { imagU = 0.0 - imagU; } i = j; while (i <= fftSize) { ip = (i + lev1) - 1; ii = i - 1; realT = ((realData[ip]) * realU) - ((imagData[ip]) * imagU); imagT = ((realData[ip]) * imagU) + ((imagData[ip]) * realU); realData[ip] = ((realData[ii]) - realT); imagData[ip] = ((imagData[ii]) - imagT); realData[ii] = ((realData[ii]) + realT); imagData[ii] = ((imagData[ii]) + imagT); i += lev; } } } } #ifdef SQUEAK_BUILTIN_PLUGIN void* FFTPlugin_exports[][3] = { {"FFTPlugin", "getModuleName", (void*)getModuleName}, {"FFTPlugin", "primitiveFFTPermuteData", (void*)primitiveFFTPermuteData}, {"FFTPlugin", "primitiveFFTScaleData", (void*)primitiveFFTScaleData}, {"FFTPlugin", "primitiveFFTTransformData", (void*)primitiveFFTTransformData}, {"FFTPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FT2Plugin/FT2Plugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:36 pm by VMMaker 4.4.7 */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include <ft2build.h> #include FT_TRUETYPE_TABLES_H #include FT_FREETYPE_H #include FT_OUTLINE_H #include "sqMemoryAccess.h" /*** Constants ***/ #define FT2GlyphSlotFaceIndex 0 #define FT2GlyphSlotInstSize 17 #define FT2OutlineContoursIndex 4 #define FT2OutlineContoursSizeIndex 0 #define FT2OutlineFlagsIndex 5 #define FT2OutlineInstSize 6 #define FT2OutlinePointsIndex 2 #define FT2OutlinePointsSizeIndex 1 #define FT2OutlineTagsIndex 3 #define FormBitsIndex 0 #define FormDepthIndex 3 #define FormHeightIndex 2 #define FormInstSize 5 #define FormWidthIndex 1 /*** Function Prototypes ***/ static char * fetchByteArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize); static short* fetchShortArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize); static long * fetchWordArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize); static sqInt ftAllocateHandleInReceiverForPointer(void *aPointer); static sqInt ftAllocateStringForPointer(const char *aPointer); static FT_Encoding ftEncodingValueFromString(sqInt string); static void * ftHandleValueFromReceiver(sqInt rcvrOop); static int ftInitBitmapfromForm(FT_Bitmap*bitmap, sqInt formOop); static int ftInitBitmapfromFormrenderMode(FT_Bitmap*bitmap, sqInt formOop, sqInt mode); static int ftParameterError(void); static sqInt ftStringFromEncodingValue(FT_Encoding encoding); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveCopyToExternalMemory(void); EXPORT(sqInt) primitiveDoneFace(void); EXPORT(sqInt) primitiveDoneFacePreserveFields(void); EXPORT(sqInt) primitiveEmboldenFaceGlyphSlotOutline(void); EXPORT(sqInt) primitiveErrorCode(void); EXPORT(sqInt) primitiveErrorString(void); EXPORT(sqInt) primitiveFreeExternalMemory(void); EXPORT(sqInt) primitiveGetFaceCharIndex(void); EXPORT(sqInt) primitiveGetFaceCharMap(void); EXPORT(sqInt) primitiveGetFaceCharMapsIntoArray(void); EXPORT(sqInt) primitiveGetFaceGlyphName(void); EXPORT(sqInt) primitiveGetKerningLeftRight(void); EXPORT(sqInt) primitiveGetPostscriptName(void); EXPORT(sqInt) primitiveGetSfntTableOS2(void); #pragma export off static sqInt primitiveGetTrackKerningPointSizedegree(sqInt pointSize, sqInt degree); #pragma export on EXPORT(sqInt) primitiveHasKerning(void); EXPORT(sqInt) primitiveLibraryHandle(void); EXPORT(sqInt) primitiveLoadCharacter(void); EXPORT(sqInt) primitiveLoadFaceBbox(void); EXPORT(sqInt) primitiveLoadFaceFields(void); EXPORT(sqInt) primitiveLoadGlyph(void); EXPORT(sqInt) primitiveLoadGlyphSlotFromFace(void); EXPORT(sqInt) primitiveLoadOutlineArraysFromFace(void); EXPORT(sqInt) primitiveLoadOutlineSizesFromFace(void); EXPORT(sqInt) primitiveModuleErrorCode(void); EXPORT(sqInt) primitiveNewFaceFromFileAndIndex(void); EXPORT(sqInt) primitiveNewMemoryFaceFromExternalMemoryAndIndex(void); EXPORT(sqInt) primitiveNumberOfOutlineCountours(void); EXPORT(sqInt) primitiveRenderGlyphIntoForm(void); EXPORT(sqInt) primitiveRenderGlyphIntoFormWithRenderMode(void); EXPORT(sqInt) primitiveResetErrorCode(void); EXPORT(sqInt) primitiveSetFaceCharMap(void); EXPORT(sqInt) primitiveSetPixelSizes(void); EXPORT(sqInt) primitiveSetTransform(void); EXPORT(sqInt) primitiveTransformFaceGlyphSlotOutline(void); EXPORT(sqInt) primitiveTranslateFaceGlyphSlotOutline(void); EXPORT(sqInt) primitiveVersion(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ static int errorCode; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static FT_Library library; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FT2Plugin 23 January 2011 (i)" #else "FT2Plugin 23 January 2011 (e)" #endif ; static char * fetchByteArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize) { sqInt array; array = interpreterProxy->fetchPointerofObject(fieldIndex, objectPointer); if ((interpreterProxy->isBytes(array)) && ((interpreterProxy->slotSizeOf(array)) == aSize)) { return interpreterProxy->arrayValueOf(array); } return null; } static short* fetchShortArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize) { sqInt array; array = interpreterProxy->fetchPointerofObject(fieldIndex, objectPointer); if ((interpreterProxy->isWords(array)) && ((interpreterProxy->slotSizeOf(array)) == (((sqInt) (aSize + 1) >> 1)))) { return interpreterProxy->arrayValueOf(array); } return null; } static long * fetchWordArrayofObjectassureSize(sqInt fieldIndex, sqInt objectPointer, sqInt aSize) { sqInt array; array = interpreterProxy->fetchPointerofObject(fieldIndex, objectPointer); if ((interpreterProxy->isWords(array)) && ((interpreterProxy->slotSizeOf(array)) == aSize)) { return interpreterProxy->arrayValueOf(array); } return null; } /* given aPointer (returned from a library call), set the receiver's (bottom of stack) first instance variable to a ByteArray containing the pointer's bytes */ static sqInt ftAllocateHandleInReceiverForPointer(void *aPointer) { sqInt returnedHandle; void **extraByteArrayPtr; if (aPointer) { /* Allocate a Smalltalk ByteArray -- lastAlloc contains the length */ /* Copy from the C bytecode buffer to the Smalltalk ByteArray */ returnedHandle = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(void **)); extraByteArrayPtr = interpreterProxy->arrayValueOf(returnedHandle); *extraByteArrayPtr = (void *)(aPointer); } else { returnedHandle = interpreterProxy->nilObject(); } interpreterProxy->storePointerofObjectwithValue(0, interpreterProxy->stackObjectValue(interpreterProxy->methodArgumentCount()), returnedHandle); ; return returnedHandle; } /* given NUL-terminated char* aPointer (returned from a library call), return the oop for a String containing the pointer's bytes */ static sqInt ftAllocateStringForPointer(const char *aPointer) { sqInt returnedHandle; char *extraByteArrayPtr; if (aPointer) { /* Allocate a Smalltalk ByteArray -- lastAlloc contains the length */ /* Copy from the C bytecode buffer to the Smalltalk ByteArray */ returnedHandle = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strlen(aPointer)); extraByteArrayPtr = interpreterProxy->arrayValueOf(returnedHandle); ; strncpy(extraByteArrayPtr, aPointer, strlen(aPointer)); } else { returnedHandle = interpreterProxy->nilObject(); } return returnedHandle; } /* Return a 32-bit word from the bytes held by string. */ static FT_Encoding ftEncodingValueFromString(sqInt string) { unsigned long retval; unsigned char*ptr; interpreterProxy->success((!((string & 1))) && ((interpreterProxy->isBytes(string)) && ((interpreterProxy->slotSizeOf(string)) == (sizeof(FT_Encoding))))); if (interpreterProxy->failed()) { return null; } retval = 0; /* ptr := self cCode: '(unsigned char *) (string + 4)'. */ ptr = interpreterProxy->arrayValueOf(string); ; retval = ((unsigned long)ptr[0]) << 24; retval += ((unsigned long)ptr[1]) << 16; retval += ((unsigned long)ptr[2]) << 8; retval += (unsigned long)ptr[3]; ; return (FT_Encoding)retval; } /* this is the opposite of #ftAllocateHandleIn:forPointer: . It takes rcvr's first instance variable, which should be a ByteArray the size of a void*, and returns its value as a C pointer. */ static void * ftHandleValueFromReceiver(sqInt rcvrOop) { sqInt oop; sqInt btw; oop = interpreterProxy->fetchPointerofObject(0, rcvrOop); interpreterProxy->success((interpreterProxy->isBytes(oop)) && ((interpreterProxy->slotSizeOf(oop)) == (sizeof(void *)))); if (interpreterProxy->failed()) { return null; } btw = BYTES_PER_WORD; return *(void**)(pointerForOop(oop + btw)); } /* Initialize the values in an FT_Bitmap from the given Form */ static int ftInitBitmapfromForm(FT_Bitmap*bitmap, sqInt formOop) { sqInt pixelMode; sqInt numGrays; sqInt width; sqInt depth; sqInt height; sqInt wordsPerRow; sqInt pitch; unsigned char*buffer; interpreterProxy->success(interpreterProxy->isPointers(formOop)); interpreterProxy->success((interpreterProxy->slotSizeOf(formOop)) >= FormInstSize); if (interpreterProxy->failed()) { return null; } width = interpreterProxy->fetchIntegerofObject(FormWidthIndex, formOop); height = interpreterProxy->fetchIntegerofObject(FormHeightIndex, formOop); depth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, formOop); buffer = ((void*) (interpreterProxy->fetchArrayofObject(FormBitsIndex, formOop))); if (interpreterProxy->failed()) { return null; } if (depth < 0) { depth = depth * -1; } if (depth == 1) { wordsPerRow = ((sqInt) (width + 31) >> 5); numGrays = 1; pixelMode = FT_PIXEL_MODE_MONO; } else { if (depth == 8) { wordsPerRow = ((sqInt) (width + 3) >> 2); numGrays = 256; pixelMode = FT_PIXEL_MODE_GRAY; } else { return interpreterProxy->primitiveFail(); } } #ifndef WORDS_BIGENDIAN depth = depth * -1; #endif ; interpreterProxy->storeIntegerofObjectwithValue(FormDepthIndex, formOop, depth); pitch = wordsPerRow * 4; bitmap->rows = height; bitmap->width = width; bitmap->pitch = pitch; bitmap->buffer = buffer; bitmap->num_grays = numGrays; bitmap->pixel_mode = pixelMode; return 1; } /* Initialize the values in an FT_Bitmap from the given Form */ /* pixelMode */ static int ftInitBitmapfromFormrenderMode(FT_Bitmap*bitmap, sqInt formOop, sqInt mode) { sqInt numGrays; sqInt width; sqInt depth; sqInt height; sqInt wordsPerRow; sqInt pitch; unsigned char*buffer; interpreterProxy->success(interpreterProxy->isPointers(formOop)); interpreterProxy->success((interpreterProxy->slotSizeOf(formOop)) >= FormInstSize); if (interpreterProxy->failed()) { return null; } width = interpreterProxy->fetchIntegerofObject(FormWidthIndex, formOop); height = interpreterProxy->fetchIntegerofObject(FormHeightIndex, formOop); depth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, formOop); buffer = ((void*) (interpreterProxy->fetchArrayofObject(FormBitsIndex, formOop))); if (interpreterProxy->failed()) { return null; } if (depth < 0) { depth = depth * -1; } if (depth == 1) { wordsPerRow = ((sqInt) (width + 31) >> 5); numGrays = 1; } else { if (depth == 8) { wordsPerRow = ((sqInt) (width + 3) >> 2); numGrays = 256; } else { return interpreterProxy->primitiveFail(); } } #ifndef WORDS_BIGENDIAN depth = depth * -1; #endif ; interpreterProxy->storeIntegerofObjectwithValue(FormDepthIndex, formOop, depth); pitch = wordsPerRow * 4; bitmap->rows = height; bitmap->width = width; bitmap->pitch = pitch; bitmap->buffer = buffer; bitmap->num_grays = numGrays; bitmap->pixel_mode = mode; return 1; } static int ftParameterError(void) { errorCode = 255; return interpreterProxy->primitiveFail(); } /* Return a newly allocated String from the given 32-bit word */ static sqInt ftStringFromEncodingValue(FT_Encoding encoding) { unsigned char*ptr; sqInt stringOop; stringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), sizeof(FT_Encoding)); ; if (interpreterProxy->failed()) { return null; } ptr = interpreterProxy->firstIndexableField(stringOop); ; ptr[0] = (encoding & 0xFF000000) >> 24; ptr[1] = (encoding & 0x00FF0000) >> 16; ptr[2] = (encoding & 0x0000FF00) >> 8; ptr[3] = (encoding & 0x000000FF); return stringOop; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { library = null; #ifdef macintoshSqueak fetchPreferences(); #endif ; errorCode = FT_Init_FreeType(&library); return errorCode == 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primitiveCopyToExternalMemory(void) { void *aPointer; sqInt rcvr; size_t byteSize; char *aByteArray; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aByteArray = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FreeTypeExternalMemory")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } ; errorCode = 0; byteSize = interpreterProxy->byteSizeOf((oopForPointer( aByteArray ) - BASE_HEADER_SIZE)); ; if (interpreterProxy->failed()) { return null; } aPointer = malloc(byteSize); memcpy(aPointer,aByteArray,byteSize); ftAllocateHandleInReceiverForPointer(aPointer); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* Call the library to release the given face record. Nil out the pointer fields */ EXPORT(sqInt) primitiveDoneFace(void) { sqInt rcvr; sqInt i; FT_Face face; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } ; /* nil out all the fields */ errorCode = FT_Done_Face(face); for (i = 0; i <= 23; i += 1) { interpreterProxy->storePointerofObjectwithValue(i, rcvr, interpreterProxy->nilObject()); } interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } /* Call the library to release the given face record. Nil out the handle field, but do not nil the other fields, as their values are needed even if the face cannot be re-opened in the future due to a missing font file etc. */ EXPORT(sqInt) primitiveDoneFacePreserveFields(void) { sqInt rcvr; FT_Face face; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } ; /* nil the handle field */ errorCode = FT_Done_Face(face); interpreterProxy->storePointerofObjectwithValue(0, rcvr, interpreterProxy->nilObject()); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } /* emboldens the outline in the face's glyphSlot by strength (expressed in 26.6 pixel format). The new outline will be at most 4 times `strength' pixels wider and higher. */ EXPORT(sqInt) primitiveEmboldenFaceGlyphSlotOutline(void) { sqInt rcvr; FT_Face face; sqInt strength; strength = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } errorCode = FT_Outline_Embolden( &face->glyph->outline, strength ); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* high byte is module error, low is generic error */ EXPORT(sqInt) primitiveErrorCode(void) { sqInt _return_value; _return_value = interpreterProxy->positive32BitIntegerFor((FT_ERROR_BASE(errorCode))); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveErrorString(void) { const char *str; const struct ftError *ftError; struct ftError { int errCode; const char* errMsg; }; #undef __FTERRORS_H__ #define FT_ERRORDEF( e, v, s ) { e, s }, #define FT_ERROR_START_LIST { #define FT_ERROR_END_LIST { 0xFF, "Bad Squeak Method Parameter" }, { 0, NULL } }; static const struct ftError ftErrors[] = #include FT_ERRORS_H ; ftError = ftErrors; ; while ((str = ftError->errMsg) && (FT_ERROR_BASE(errorCode) != ftError->errCode)) { ftError++; } ; if (!(str)) { interpreterProxy->success(0); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, ftAllocateStringForPointer(str)); if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } EXPORT(sqInt) primitiveFreeExternalMemory(void) { sqInt rcvr; void*memPointer; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FreeTypeExternalMemory")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } ; /* free the memory handle */ errorCode = 0; memPointer = ftHandleValueFromReceiver(rcvr); if (!(memPointer == null)) { free(memPointer); } if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } /* Return the Freetype glyph index of the given character code, in the current encoding. Return value of 0 means 'undefined character code'. */ EXPORT(sqInt) primitiveGetFaceCharIndex(void) { sqInt rcvr; sqInt result; FT_Face face; sqInt charIndex; sqInt _return_value; charIndex = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } result = FT_Get_Char_Index(face, charIndex); _return_value = interpreterProxy->positive32BitIntegerFor(result); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveGetFaceCharMap(void) { FT_Encoding encoding; sqInt rcvr; FT_CharMap charmap; sqInt stringOop; FT_Face face; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } charmap = face->charmap; if (!(charmap)) { return null; } interpreterProxy->pushRemappableOop(rcvr); encoding = charmap->encoding; stringOop = ftStringFromEncodingValue(encoding); rcvr = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(22, rcvr, stringOop); interpreterProxy->storeIntegerofObjectwithValue(23, rcvr, charmap->platform_id); interpreterProxy->storeIntegerofObjectwithValue(24, rcvr, charmap->encoding_id); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } EXPORT(sqInt) primitiveGetFaceCharMapsIntoArray(void) { FT_CharMap *charmap; int numCharmaps; sqInt i; sqInt stringOop; FT_Face face; sqInt arrayOop; sqInt rcvr; sqInt *array; interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(0))); array = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } numCharmaps = face->num_charmaps; arrayOop = oopForPointer(array) - BASE_HEADER_SIZE; interpreterProxy->success((interpreterProxy->slotSizeOf(arrayOop)) == numCharmaps); if (interpreterProxy->failed()) { return null; } charmap = face->charmaps; ; for (i = 0; i <= (numCharmaps - 1); i += 1) { interpreterProxy->pushRemappableOop(arrayOop); stringOop = ftStringFromEncodingValue((*charmap)->encoding); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, stringOop); charmap++; } if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* return a String */ EXPORT(sqInt) primitiveGetFaceGlyphName(void) { char buffer[100]; sqInt rcvr; sqInt string; FT_Face face; sqInt glyphIndex; glyphIndex = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } errorCode = FT_Get_Glyph_Name(face, glyphIndex, buffer, 100); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } string = ftAllocateStringForPointer(buffer); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(2, string); return null; } EXPORT(sqInt) primitiveGetKerningLeftRight(void) { sqInt kernMode; sqInt rcvr; FT_Vector result; sqInt pointOop; FT_Face face; sqInt leftGlyph; sqInt rightGlyph; leftGlyph = interpreterProxy->stackIntegerValue(1); rightGlyph = interpreterProxy->stackIntegerValue(0); result.x=3; result.y=4;; ; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } kernMode = FT_KERNING_UNSCALED; ; FT_Get_Kerning(face, leftGlyph, rightGlyph, kernMode, &result);; pointOop = interpreterProxy->makePointwithxValueyValue(result.x, result.y); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(3, pointOop); return null; } /* return a String */ EXPORT(sqInt) primitiveGetPostscriptName(void) { char*buffer; sqInt rcvr; sqInt string; FT_Face face; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } buffer = 0; face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } buffer = FT_Get_Postscript_Name(face); interpreterProxy->success(buffer != 0); if (interpreterProxy->failed()) { return null; } string = ftAllocateStringForPointer(buffer); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, string); return null; } /* return the bytes from the OS/2 table */ EXPORT(sqInt) primitiveGetSfntTableOS2(void) { char *buffer; sqInt rcvr; sqInt returnedHandle; char *extraByteArrayPtr; FT_Face face; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } buffer = 0; face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } buffer = FT_Get_Sfnt_Table(face,ft_sfnt_os2); if (buffer == 0) { _return_value = interpreterProxy->integerObjectOf(-1); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Copy from the C bytecode buffer to the Smalltalk ByteArray */ returnedHandle = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(TT_OS2)); extraByteArrayPtr = interpreterProxy->arrayValueOf(returnedHandle); ; memcpy(extraByteArrayPtr, buffer, sizeof(TT_OS2)); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, returnedHandle); return null; } /* disabled becaus of yet implemented */ static sqInt primitiveGetTrackKerningPointSizedegree(sqInt pointSize, sqInt degree) { return interpreterProxy->primitiveFail(); } EXPORT(sqInt) primitiveHasKerning(void) { sqInt rcvr; FT_Face face; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } _return_value = (((FT_HAS_KERNING( face )) << 1) | 1); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Fill in the handle in an FT2Library structure with a copy of our global pointer. */ EXPORT(sqInt) primitiveLibraryHandle(void) { sqInt rcvr; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Library")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; ftAllocateHandleInReceiverForPointer(library); if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } /* Load the glyph at the given index in the current charmap. The default map upon opening a font is the 'unic' or Unicode charmap, if any. */ EXPORT(sqInt) primitiveLoadCharacter(void) { sqInt rcvr; FT_Face face; sqInt index; sqInt flags; index = interpreterProxy->stackIntegerValue(1); flags = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } errorCode = FT_Load_Char(face, index, flags); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveLoadFaceBbox(void) { sqInt rcvr; sqInt pointOop; sqInt rectOop; FT_Face face; sqInt aRectangle; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Rectangle")); aRectangle = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } rectOop = aRectangle; if (!(interpreterProxy->isPointers(rectOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(rectOop)) < 2) { interpreterProxy->primitiveFail(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } ; if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) { interpreterProxy->success(0); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pushRemappableOop(rectOop); pointOop = interpreterProxy->makePointwithxValueyValue(face->bbox.xMin, face->bbox.yMin); rectOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, rectOop, pointOop); interpreterProxy->pushRemappableOop(rectOop); pointOop = interpreterProxy->makePointwithxValueyValue(face->bbox.xMax, face->bbox.yMax); rectOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, rectOop, pointOop); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* Fill in many of the receiver's (an FT2Face) fields (other than its handle) from the FT_Face record that it points to. */ EXPORT(sqInt) primitiveLoadFaceFields(void) { sqInt rcvr; sqInt strOop; FT_Face face; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } ; interpreterProxy->storeIntegerofObjectwithValue(1, rcvr, face->num_faces); interpreterProxy->storeIntegerofObjectwithValue(2, rcvr, face->face_index); interpreterProxy->storeIntegerofObjectwithValue(3, rcvr, face->face_flags); interpreterProxy->storeIntegerofObjectwithValue(4, rcvr, face->style_flags); interpreterProxy->storeIntegerofObjectwithValue(5, rcvr, face->num_glyphs); interpreterProxy->pushRemappableOop(rcvr); strOop = ftAllocateStringForPointer(face->family_name); rcvr = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(6, rcvr, strOop); interpreterProxy->pushRemappableOop(rcvr); strOop = ftAllocateStringForPointer(face->style_name); rcvr = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(7, rcvr, strOop); interpreterProxy->storeIntegerofObjectwithValue(8, rcvr, face->num_fixed_sizes); interpreterProxy->storeIntegerofObjectwithValue(10, rcvr, face->num_charmaps); if (face->face_flags & FT_FACE_FLAG_SCALABLE) { interpreterProxy->storeIntegerofObjectwithValue(13, rcvr, face->units_per_EM); interpreterProxy->storeIntegerofObjectwithValue(14, rcvr, face->ascender); interpreterProxy->storeIntegerofObjectwithValue(15, rcvr, face->descender); interpreterProxy->storeIntegerofObjectwithValue(16, rcvr, face->height); interpreterProxy->storeIntegerofObjectwithValue(17, rcvr, face->max_advance_width); interpreterProxy->storeIntegerofObjectwithValue(18, rcvr, face->max_advance_height); interpreterProxy->storeIntegerofObjectwithValue(19, rcvr, face->underline_position); interpreterProxy->storeIntegerofObjectwithValue(20, rcvr, face->underline_thickness); } if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } EXPORT(sqInt) primitiveLoadGlyph(void) { sqInt rcvr; FT_Face face; sqInt index; sqInt flags; index = interpreterProxy->stackIntegerValue(1); flags = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } errorCode = FT_Load_Glyph(face, index, flags); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } /* Assumes that primitiveLoadGlyph:flags: has been called earlier to set face->glyph. */ EXPORT(sqInt) primitiveLoadGlyphSlotFromFace(void) { sqInt rcvr; FT_GlyphSlot gs; sqInt gfOop; sqInt btw; FT_Face face; FT_Glyph_Format *gfPtr; sqInt aFace; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); aFace = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2GlyphSlot")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; if ((interpreterProxy->slotSizeOf(rcvr)) < 8) { interpreterProxy->primitiveFail(); return null; } face = ftHandleValueFromReceiver(aFace); if (face == null) { interpreterProxy->primitiveFail(); return null; } gs = face->glyph; if (!(gs)) { interpreterProxy->primitiveFail(); return null; } ; interpreterProxy->storePointerofObjectwithValue(0, rcvr, aFace); interpreterProxy->storeIntegerofObjectwithValue(1, rcvr, gs->linearHoriAdvance); interpreterProxy->storeIntegerofObjectwithValue(2, rcvr, gs->linearVertAdvance); interpreterProxy->storeIntegerofObjectwithValue(3, rcvr, gs->advance.x); interpreterProxy->storeIntegerofObjectwithValue(4, rcvr, gs->advance.y); interpreterProxy->pushRemappableOop(rcvr); gfOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(FT_Glyph_Format)); ; btw = BYTES_PER_WORD; gfPtr = (FT_Glyph_Format *) pointerForOop(gfOop + btw); ; if (interpreterProxy->failed()) { return null; } *gfPtr = gs->format; rcvr = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(5, rcvr, gfOop); interpreterProxy->storeIntegerofObjectwithValue(6, rcvr, gs->bitmap_left); interpreterProxy->storeIntegerofObjectwithValue(7, rcvr, gs->bitmap_top); interpreterProxy->storeIntegerofObjectwithValue(8, rcvr, gs->metrics.width); interpreterProxy->storeIntegerofObjectwithValue(9, rcvr, gs->metrics.height); interpreterProxy->storeIntegerofObjectwithValue(10, rcvr, gs->metrics.horiBearingX); interpreterProxy->storeIntegerofObjectwithValue(11, rcvr, gs->metrics.horiBearingY); interpreterProxy->storeIntegerofObjectwithValue(12, rcvr, gs->metrics.horiAdvance); interpreterProxy->storeIntegerofObjectwithValue(13, rcvr, gs->metrics.vertBearingX); interpreterProxy->storeIntegerofObjectwithValue(14, rcvr, gs->metrics.vertBearingY); interpreterProxy->storeIntegerofObjectwithValue(15, rcvr, gs->metrics.vertAdvance); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* Assumes that primitiveLoadGlyph:flags: has been called earlier to set face->glyph. */ EXPORT(sqInt) primitiveLoadOutlineArraysFromFace(void) { sqInt i; sqInt pointsSize; FT_GlyphSlot gs; FT_Face face; sqInt rcvr; char * tags; short* contours; sqInt contoursSize; long * points; sqInt aFace; sqInt array; sqInt array1; sqInt array2; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); aFace = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Outline")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; if ((interpreterProxy->slotSizeOf(rcvr)) < FT2OutlineInstSize) { interpreterProxy->primitiveFail(); return null; } face = ftHandleValueFromReceiver(aFace); if (face == null) { interpreterProxy->primitiveFail(); return null; } gs = face->glyph; if (!(gs)) { interpreterProxy->primitiveFail(); return null; } ; pointsSize = gs->outline.n_points; /* begin fetchWordArray:ofObject:assureSize: */ array = interpreterProxy->fetchPointerofObject(FT2OutlinePointsIndex, rcvr); if ((interpreterProxy->isWords(array)) && ((interpreterProxy->slotSizeOf(array)) == (pointsSize * 2))) { points = interpreterProxy->arrayValueOf(array); goto l1; } points = null; l1: /* end fetchWordArray:ofObject:assureSize: */; if (points == null) { interpreterProxy->primitiveFail(); return null; } /* begin fetchByteArray:ofObject:assureSize: */ array1 = interpreterProxy->fetchPointerofObject(FT2OutlineTagsIndex, rcvr); if ((interpreterProxy->isBytes(array1)) && ((interpreterProxy->slotSizeOf(array1)) == pointsSize)) { tags = interpreterProxy->arrayValueOf(array1); goto l2; } tags = null; l2: /* end fetchByteArray:ofObject:assureSize: */; if (tags == null) { interpreterProxy->primitiveFail(); return null; } for (i = 0; i <= (pointsSize - 1); i += 1) { points[2 * i] = (gs->outline.points[i].x); points[(2 * i) + 1] = (gs->outline.points[i].y); tags[i] = (gs->outline.tags[i]); } contoursSize = gs->outline.n_contours; /* begin fetchShortArray:ofObject:assureSize: */ array2 = interpreterProxy->fetchPointerofObject(FT2OutlineContoursIndex, rcvr); if ((interpreterProxy->isWords(array2)) && ((interpreterProxy->slotSizeOf(array2)) == (((sqInt) (contoursSize + 1) >> 1)))) { contours = interpreterProxy->arrayValueOf(array2); goto l3; } contours = null; l3: /* end fetchShortArray:ofObject:assureSize: */; for (i = 0; i <= (contoursSize - 1); i += 1) { contours[i] = (gs->outline.contours[i]); } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* Assumes that primitiveLoadGlyph:flags: has been called earlier to set face->glyph. */ EXPORT(sqInt) primitiveLoadOutlineSizesFromFace(void) { sqInt rcvr; FT_GlyphSlot gs; FT_Face face; sqInt aFace; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Face")); aFace = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Outline")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; if ((interpreterProxy->slotSizeOf(rcvr)) < FT2OutlineInstSize) { interpreterProxy->primitiveFail(); return null; } face = ftHandleValueFromReceiver(aFace); if (face == null) { interpreterProxy->primitiveFail(); return null; } gs = face->glyph; if (!(gs)) { interpreterProxy->primitiveFail(); return null; } ; interpreterProxy->storeIntegerofObjectwithValue(FT2OutlineContoursSizeIndex, rcvr, gs->outline.n_contours); interpreterProxy->storeIntegerofObjectwithValue(FT2OutlinePointsSizeIndex, rcvr, gs->outline.n_points); interpreterProxy->storeIntegerofObjectwithValue(FT2OutlineFlagsIndex, rcvr, gs->outline.flags); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* high byte is module error, low is generic error */ EXPORT(sqInt) primitiveModuleErrorCode(void) { sqInt _return_value; _return_value = interpreterProxy->positive32BitIntegerFor((FT_ERROR_MODULE(errorCode))); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Fill in the receiver's (a FT2Face object) fields from the address and fields of a newly opened FT_Face object. */ EXPORT(sqInt) primitiveNewFaceFromFileAndIndex(void) { char translatedFilePath[1024]; sqInt rcvr; size_t byteSize; FT_Face face; char *fontFilePath; sqInt anInteger; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); fontFilePath = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); anInteger = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } ; errorCode = 0; byteSize = interpreterProxy->byteSizeOf((oopForPointer( fontFilePath ) - BASE_HEADER_SIZE)); ; if (interpreterProxy->failed()) { return null; } if (byteSize > 1000) { interpreterProxy->success(0); return null; } interpreterProxy->ioFilenamefromStringofLengthresolveAliases(translatedFilePath, fontFilePath, byteSize, 1); errorCode = FT_New_Face(library, translatedFilePath, anInteger, &face); ; ; interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } ftAllocateHandleInReceiverForPointer(face); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } /* Fill in the receiver's (a FT2Face object) fields from the address and fields of a newly opened FT_Face object. */ EXPORT(sqInt) primitiveNewMemoryFaceFromExternalMemoryAndIndex(void) { sqInt rcvr; void *memPointer; FT_Face face; sqInt aFreeTypeExternalMemory; sqInt byteSize; sqInt anInteger; aFreeTypeExternalMemory = interpreterProxy->stackValue(2); byteSize = interpreterProxy->stackIntegerValue(1); anInteger = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(3), "FT2Face")); rcvr = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { ftParameterError(); return null; } ; errorCode = 0; memPointer = ftHandleValueFromReceiver(aFreeTypeExternalMemory); ; if (interpreterProxy->failed()) { return null; } errorCode = FT_New_Memory_Face(library, memPointer, byteSize, anInteger, &face); ; ; interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } ftAllocateHandleInReceiverForPointer(face); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(3); return null; } /* Assumes that primitiveLoadGlyph:flags: has been called earlier to set face->glyph. */ EXPORT(sqInt) primitiveNumberOfOutlineCountours(void) { sqInt rcvr; sqInt contoursSize; FT_GlyphSlot gs; sqInt aFace; FT_Face face; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2GlyphSlot")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; if ((interpreterProxy->slotSizeOf(rcvr)) < FT2GlyphSlotInstSize) { interpreterProxy->primitiveFail(); return null; } aFace = interpreterProxy->fetchPointerofObject(FT2GlyphSlotFaceIndex, rcvr); face = ftHandleValueFromReceiver(aFace); if (face == null) { interpreterProxy->primitiveFail(); return null; } gs = face->glyph; if (!(gs)) { interpreterProxy->primitiveFail(); return null; } ; contoursSize = gs->outline.n_contours; _return_value = ((contoursSize << 1) | 1); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Render this face into the given form */ EXPORT(sqInt) primitiveRenderGlyphIntoForm(void) { FT_Bitmap bitmap; sqInt faceOop; FT_Face face; sqInt formOop; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Form")); formOop = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); faceOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(faceOop); if (face == null) { interpreterProxy->primitiveFail(); return null; } ftInitBitmapfromForm(&bitmap, formOop); if (interpreterProxy->failed()) { return null; } errorCode = FT_Outline_Get_Bitmap(library, &face->glyph->outline, &bitmap); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } /* Render this face into the given form */ EXPORT(sqInt) primitiveRenderGlyphIntoFormWithRenderMode(void) { FT_Bitmap bitmap; sqInt faceOop; FT_Face face; sqInt formOop; sqInt mode; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Form")); formOop = interpreterProxy->stackValue(1); mode = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); faceOop = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(faceOop); if (face == null) { interpreterProxy->primitiveFail(); return null; } ftInitBitmapfromFormrenderMode(&bitmap, formOop, mode); if (interpreterProxy->failed()) { return null; } errorCode = FT_Outline_Get_Bitmap(library, &face->glyph->outline, &bitmap); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveResetErrorCode(void) { sqInt oldError; sqInt _return_value; oldError = errorCode; errorCode = 0; _return_value = interpreterProxy->positive32BitIntegerFor(oldError); if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveSetFaceCharMap(void) { FT_Encoding encoding; sqInt rcvr; FT_Face face; sqInt encodingString; encodingString = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } encoding = ftEncodingValueFromString(encodingString); if (interpreterProxy->failed()) { return null; } ; errorCode = FT_Select_Charmap(face, encoding); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSetPixelSizes(void) { sqInt rcvr; FT_Face face; sqInt x; sqInt y; x = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } errorCode = FT_Set_Pixel_Sizes(face, x, y); interpreterProxy->success(errorCode == 0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveSetTransform(void) { sqInt *matrixsqIntPtr; sqInt *deltasqIntPtr; FT_Face face; FT_Vector delta; FT_Matrix matrix; sqInt rcvr; sqInt matrixWordArray; sqInt deltaWordArray; matrixWordArray = interpreterProxy->stackValue(1); deltaWordArray = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "FT2Face")); rcvr = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } matrixsqIntPtr = interpreterProxy->arrayValueOf(matrixWordArray); deltasqIntPtr = interpreterProxy->arrayValueOf(deltaWordArray); delta.x = deltasqIntPtr[0]; delta.y = deltasqIntPtr[1];; matrix.xx = matrixsqIntPtr[0]; matrix.xy = matrixsqIntPtr[1]; matrix.yx = matrixsqIntPtr[2]; matrix.yy = matrixsqIntPtr[3]; ; if (!(interpreterProxy->failed())) { FT_Set_Transform( face, &matrix, &delta); } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveTransformFaceGlyphSlotOutline(void) { FT_Matrix matrix; sqInt rcvr; sqInt *matrixsqIntPtr; FT_Face face; sqInt matrixWordArray; matrixWordArray = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } matrixsqIntPtr = interpreterProxy->arrayValueOf(matrixWordArray); matrix.xx = matrixsqIntPtr[0]; matrix.xy = matrixsqIntPtr[1]; matrix.yx = matrixsqIntPtr[2]; matrix.yy = matrixsqIntPtr[3]; ; if (!(interpreterProxy->failed())) { FT_Outline_Transform( &face->glyph->outline, &matrix ); } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveTranslateFaceGlyphSlotOutline(void) { sqInt rcvr; FT_Vector delta; sqInt *deltasqIntPtr; FT_Face face; sqInt deltaWordArray; deltaWordArray = interpreterProxy->stackValue(0); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "FT2Face")); rcvr = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { ftParameterError(); return null; } face = ftHandleValueFromReceiver(rcvr); if (face == null) { interpreterProxy->primitiveFail(); return null; } deltasqIntPtr = interpreterProxy->arrayValueOf(deltaWordArray); delta.x = deltasqIntPtr[0]; delta.y = deltasqIntPtr[1];; if (!(interpreterProxy->failed())) { FT_Outline_Translate( &face->glyph->outline, delta.x, delta.y ); } if (interpreterProxy->failed()) { ftParameterError(); return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveVersion(void) { int aminor; int apatch; sqInt rcvr; int amajor; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "FT2Version")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { ftParameterError(); return null; } errorCode = 0; FT_Library_Version(library, &amajor, &aminor, &apatch); ; interpreterProxy->storeIntegerofObjectwithValue(0, rcvr, amajor); ; interpreterProxy->storeIntegerofObjectwithValue(1, rcvr, aminor); ; interpreterProxy->storeIntegerofObjectwithValue(2, rcvr, apatch); if (interpreterProxy->failed()) { ftParameterError(); return null; } return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { errorCode = FT_Done_FreeType(library); if (errorCode == 0) { library = null; } return errorCode == 0; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* FT2Plugin_exports[][3] = { {"FT2Plugin", "primitiveTransformFaceGlyphSlotOutline", (void*)primitiveTransformFaceGlyphSlotOutline}, {"FT2Plugin", "primitiveModuleErrorCode", (void*)primitiveModuleErrorCode}, {"FT2Plugin", "primitiveLoadFaceFields", (void*)primitiveLoadFaceFields}, {"FT2Plugin", "primitiveGetFaceGlyphName", (void*)primitiveGetFaceGlyphName}, {"FT2Plugin", "shutdownModule", (void*)shutdownModule}, {"FT2Plugin", "primitiveGetSfntTableOS2", (void*)primitiveGetSfntTableOS2}, {"FT2Plugin", "primitiveDoneFace", (void*)primitiveDoneFace}, {"FT2Plugin", "primitiveNewFaceFromFileAndIndex", (void*)primitiveNewFaceFromFileAndIndex}, {"FT2Plugin", "primitiveLibraryHandle", (void*)primitiveLibraryHandle}, {"FT2Plugin", "primitiveGetKerningLeftRight", (void*)primitiveGetKerningLeftRight}, {"FT2Plugin", "primitiveLoadOutlineArraysFromFace", (void*)primitiveLoadOutlineArraysFromFace}, {"FT2Plugin", "primitiveEmboldenFaceGlyphSlotOutline", (void*)primitiveEmboldenFaceGlyphSlotOutline}, {"FT2Plugin", "primitiveLoadGlyph", (void*)primitiveLoadGlyph}, {"FT2Plugin", "getModuleName", (void*)getModuleName}, {"FT2Plugin", "primitiveSetTransform", (void*)primitiveSetTransform}, {"FT2Plugin", "primitiveLoadGlyphSlotFromFace", (void*)primitiveLoadGlyphSlotFromFace}, {"FT2Plugin", "setInterpreter", (void*)setInterpreter}, {"FT2Plugin", "primitiveNumberOfOutlineCountours", (void*)primitiveNumberOfOutlineCountours}, {"FT2Plugin", "primitiveSetPixelSizes", (void*)primitiveSetPixelSizes}, {"FT2Plugin", "primitiveTranslateFaceGlyphSlotOutline", (void*)primitiveTranslateFaceGlyphSlotOutline}, {"FT2Plugin", "primitiveGetFaceCharMapsIntoArray", (void*)primitiveGetFaceCharMapsIntoArray}, {"FT2Plugin", "primitiveResetErrorCode", (void*)primitiveResetErrorCode}, {"FT2Plugin", "primitiveHasKerning", (void*)primitiveHasKerning}, {"FT2Plugin", "primitiveGetFaceCharIndex", (void*)primitiveGetFaceCharIndex}, {"FT2Plugin", "primitiveCopyToExternalMemory", (void*)primitiveCopyToExternalMemory}, {"FT2Plugin", "primitiveLoadFaceBbox", (void*)primitiveLoadFaceBbox}, {"FT2Plugin", "primitiveDoneFacePreserveFields", (void*)primitiveDoneFacePreserveFields}, {"FT2Plugin", "primitiveNewMemoryFaceFromExternalMemoryAndIndex", (void*)primitiveNewMemoryFaceFromExternalMemoryAndIndex}, {"FT2Plugin", "primitiveGetFaceCharMap", (void*)primitiveGetFaceCharMap}, {"FT2Plugin", "primitiveSetFaceCharMap", (void*)primitiveSetFaceCharMap}, {"FT2Plugin", "primitiveLoadOutlineSizesFromFace", (void*)primitiveLoadOutlineSizesFromFace}, {"FT2Plugin", "primitiveFreeExternalMemory", (void*)primitiveFreeExternalMemory}, {"FT2Plugin", "primitiveErrorCode", (void*)primitiveErrorCode}, {"FT2Plugin", "initialiseModule", (void*)initialiseModule}, {"FT2Plugin", "primitiveGetPostscriptName", (void*)primitiveGetPostscriptName}, {"FT2Plugin", "primitiveErrorString", (void*)primitiveErrorString}, {"FT2Plugin", "primitiveLoadCharacter", (void*)primitiveLoadCharacter}, {"FT2Plugin", "primitiveVersion", (void*)primitiveVersion}, {"FT2Plugin", "primitiveRenderGlyphIntoForm", (void*)primitiveRenderGlyphIntoForm}, {"FT2Plugin", "primitiveRenderGlyphIntoFormWithRenderMode", (void*)primitiveRenderGlyphIntoFormWithRenderMode}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FileCopyPlugin/FileCopyPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from FileCopyPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "FileCopyPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveFileCopyNamedTo(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FileCopyPlugin VMMaker-oscog.dtl.57 (i)" #else "FileCopyPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveFileCopyNamedTo(void) { char *dstName; sqInt dstSz; sqInt ok; char *srcName; sqInt srcSz; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); srcName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); dstName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } srcSz = interpreterProxy->slotSizeOf(((sqInt)(long)(srcName) - 4)); dstSz = interpreterProxy->slotSizeOf(((sqInt)(long)(dstName) - 4)); ok = sqCopyFilesizetosize(srcName, srcSz, dstName, dstSz); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* FileCopyPlugin_exports[][3] = { {"FileCopyPlugin", "getModuleName", (void*)getModuleName}, {"FileCopyPlugin", "primitiveFileCopyNamedTo", (void*)primitiveFileCopyNamedTo}, {"FileCopyPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FilePlugin/FilePlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from FilePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "FilePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "FilePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ #define DirBadPath 2 #define DirNoMoreEntries 1 #define PrimErrBadArgument 3 #define PrimErrBadIndex 4 #define PrimErrNoMemory 9 #define PrimErrObjectMayMove 14 #define PrimErrUnsupported 7 #define PrimNoErr 0 /*** Function Prototypes ***/ static sqInt asciiDirectoryDelimiter(void); EXPORT(sqInt) fileOpenNamesizewritesecure(char *nameIndex, sqInt nameSize, sqInt writeFlag, sqInt secureFlag); sqInt fileRecordSize(void); SQFile * fileValueOf(sqInt objectPointer); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); EXPORT(sqInt) getThisSession(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, sqInt entryNameSize, sqInt createDate, sqInt modifiedDate, sqInt dirFlag, squeakFileOffsetType fileSize); EXPORT(sqInt) moduleUnloaded(char *aModuleName); static sqInt msg(char *s); EXPORT(sqInt) primitiveDirectoryCreate(void); EXPORT(sqInt) primitiveDirectoryDelete(void); EXPORT(sqInt) primitiveDirectoryDelimitor(void); EXPORT(sqInt) primitiveDirectoryEntry(void); EXPORT(sqInt) primitiveDirectoryGetMacTypeAndCreator(void); EXPORT(sqInt) primitiveDirectoryLookup(void); EXPORT(sqInt) primitiveDirectorySetMacTypeAndCreator(void); EXPORT(sqInt) primitiveDisableFileAccess(void); EXPORT(sqInt) primitiveFileAtEnd(void); EXPORT(sqInt) primitiveFileClose(void); EXPORT(sqInt) primitiveFileDelete(void); EXPORT(sqInt) primitiveFileFlush(void); EXPORT(sqInt) primitiveFileGetPosition(void); EXPORT(sqInt) primitiveFileOpen(void); EXPORT(sqInt) primitiveFileRead(void); EXPORT(sqInt) primitiveFileRename(void); EXPORT(sqInt) primitiveFileSetPosition(void); EXPORT(sqInt) primitiveFileSize(void); EXPORT(sqInt) primitiveFileStdioHandles(void); EXPORT(sqInt) primitiveFileTruncate(void); EXPORT(sqInt) primitiveFileWrite(void); EXPORT(sqInt) primitiveHasFileAccess(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) setMacFileTypeAndCreator(char *fileName, char *typeString, char *creatorString); EXPORT(sqInt) shutdownModule(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FilePlugin VMMaker-oscog.dtl.57 (i)" #else "FilePlugin VMMaker-oscog.dtl.57 (e)" #endif ; static void * sCCPfn; static void * sCDFfn; static void * sCDPfn; static void * sCGFTfn; static void * sCLPfn; static void * sCOFfn; static void * sCRFfn; static void * sCSFTfn; static void * sDFAfn; static void * sHFAfn; static sqInt asciiDirectoryDelimiter(void) { return dir_Delimitor(); } /* Open the named file, possibly checking security. Answer the file oop. */ EXPORT(sqInt) fileOpenNamesizewritesecure(char *nameIndex, sqInt nameSize, sqInt writeFlag, sqInt secureFlag) { SQFile *file; sqInt fileOop; sqInt okToOpen; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); /* begin fileValueOf: */ if (!((interpreterProxy->isBytes(fileOop)) && ((interpreterProxy->byteSizeOf(fileOop)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(fileOop); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { if (secureFlag) { if (sCOFfn != 0) { okToOpen = ((sqInt (*) (char *, sqInt, sqInt)) sCOFfn)(nameIndex, nameSize, writeFlag); if (!(okToOpen)) { interpreterProxy->primitiveFail(); } } } } if (!(interpreterProxy->failed())) { sqFileOpen(file, nameIndex, nameSize, writeFlag); } return fileOop; } /* Return the size of a Smalltalk file record in bytes. */ sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the file record within the given Smalltalk object, or nil if objectPointer is not a file record. */ SQFile * fileValueOf(sqInt objectPointer) { if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); return null; } return interpreterProxy->firstIndexableField(objectPointer); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } /* Exported entry point for the VM. Only used by AsynchFilePlugin and needs to be reowrked now we have a VM global session Id capability */ EXPORT(sqInt) getThisSession(void) { return sqFileThisSession(); } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { sCCPfn = interpreterProxy->ioLoadFunctionFrom("secCanCreatePathOfSize", "SecurityPlugin"); sCDPfn = interpreterProxy->ioLoadFunctionFrom("secCanDeletePathOfSize", "SecurityPlugin"); sCGFTfn = interpreterProxy->ioLoadFunctionFrom("secCanGetFileTypeOfSize", "SecurityPlugin"); sCLPfn = interpreterProxy->ioLoadFunctionFrom("secCanListPathOfSize", "SecurityPlugin"); sCSFTfn = interpreterProxy->ioLoadFunctionFrom("secCanSetFileTypeOfSize", "SecurityPlugin"); sDFAfn = interpreterProxy->ioLoadFunctionFrom("secDisableFileAccess", "SecurityPlugin"); sCDFfn = interpreterProxy->ioLoadFunctionFrom("secCanDeleteFileOfSize", "SecurityPlugin"); sCOFfn = interpreterProxy->ioLoadFunctionFrom("secCanOpenFileOfSizeWritable", "SecurityPlugin"); sCRFfn = interpreterProxy->ioLoadFunctionFrom("secCanRenameFileOfSize", "SecurityPlugin"); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); return sqFileInit(); } static sqInt makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, sqInt entryNameSize, sqInt createDate, sqInt modifiedDate, sqInt dirFlag, squeakFileOffsetType fileSize) { sqInt createDateOop; sqInt fileSizeOop; sqInt i; sqInt modDateOop; sqInt nameString; sqInt results; char *stringPtr; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 5)); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), entryNameSize)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(createDate)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(modifiedDate)); interpreterProxy->pushRemappableOop(interpreterProxy->positive64BitIntegerFor(fileSize)); fileSizeOop = interpreterProxy->popRemappableOop(); modDateOop = interpreterProxy->popRemappableOop(); createDateOop = interpreterProxy->popRemappableOop(); nameString = interpreterProxy->popRemappableOop(); /* copy name into Smalltalk string */ results = interpreterProxy->popRemappableOop(); stringPtr = interpreterProxy->firstIndexableField(nameString); for (i = 0; i <= (entryNameSize - 1); i += 1) { stringPtr[i] = (entryName[i]); } interpreterProxy->storePointerofObjectwithValue(0, results, nameString); interpreterProxy->storePointerofObjectwithValue(1, results, createDateOop); interpreterProxy->storePointerofObjectwithValue(2, results, modDateOop); if (dirFlag) { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->trueObject()); } else { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->falseObject()); } interpreterProxy->storePointerofObjectwithValue(4, results, fileSizeOop); return results; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SecurityPlugin")) == 0) { sCCPfn = sCDPfn = sCGFTfn = sCLPfn = sCSFTfn = sDFAfn = sCDFfn = sCOFfn = sCRFfn = sHFAfn = 0; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveDirectoryCreate(void) { sqInt dirName; char *dirNameIndex; sqInt dirNameSize; sqInt okToCreate; dirName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(dirName))) { return interpreterProxy->primitiveFail(); } dirNameIndex = interpreterProxy->firstIndexableField(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ dirNameSize = interpreterProxy->byteSizeOf(dirName); if (sCCPfn != 0) { okToCreate = ((sqInt (*)(char *, sqInt))sCCPfn)(dirNameIndex, dirNameSize); if (!(okToCreate)) { return interpreterProxy->primitiveFail(); } } if (!(dir_Create(dirNameIndex, dirNameSize))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDirectoryDelete(void) { sqInt dirName; char *dirNameIndex; sqInt dirNameSize; sqInt okToDelete; dirName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(dirName))) { return interpreterProxy->primitiveFail(); } dirNameIndex = interpreterProxy->firstIndexableField(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ dirNameSize = interpreterProxy->byteSizeOf(dirName); if (sCDPfn != 0) { okToDelete = ((sqInt (*)(char *, sqInt))sCDPfn)(dirNameIndex, dirNameSize); if (!(okToDelete)) { return interpreterProxy->primitiveFail(); } } if (!(dir_Delete(dirNameIndex, dirNameSize))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDirectoryDelimitor(void) { sqInt ascii; ascii = asciiDirectoryDelimiter(); if (!((ascii >= 0) && (ascii <= 255))) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(1, interpreterProxy->fetchPointerofObject(ascii, interpreterProxy->characterTable())); } /* Two arguments - directory path, and simple file name; returns an array (see primitiveDirectoryLookup) describing the file or directory, or nil if it does not exist. Primitive fails if the outer path does not identify a readable directory. (This is a lookup-by-name variant of primitiveDirectoryLookup.) */ EXPORT(sqInt) primitiveDirectoryEntry(void) { sqInt createDate; sqInt dirFlag; char entryName[256]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt modifiedDate; sqInt okToList; sqInt pathName; char *pathNameIndex; sqInt pathNameSize; char *reqNameIndex; sqInt reqNameSize; sqInt requestedName; sqInt status; requestedName = interpreterProxy->stackValue(0); pathName = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(pathName))) { return interpreterProxy->primitiveFail(); } pathNameIndex = interpreterProxy->firstIndexableField(pathName); pathNameSize = interpreterProxy->byteSizeOf(pathName); reqNameIndex = interpreterProxy->firstIndexableField(requestedName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ reqNameSize = interpreterProxy->byteSizeOf(requestedName); if (sCLPfn != 0) { okToList = ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize); } else { okToList = 1; } if (okToList) { status = dir_EntryLookup(pathNameIndex, pathNameSize, reqNameIndex, reqNameSize, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize); } else { status = DirNoMoreEntries; } if (interpreterProxy->failed()) { return null; } if (status == DirNoMoreEntries) { interpreterProxy->popthenPush(3, interpreterProxy->nilObject()); return null; } if (status == DirBadPath) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(3, makeDirEntryNamesizecreateDatemodDateisDirfileSize(entryName, entryNameSize, createDate, modifiedDate, dirFlag, fileSize)); } EXPORT(sqInt) primitiveDirectoryGetMacTypeAndCreator(void) { sqInt creatorString; char *creatorStringIndex; sqInt fileName; char *fileNameIndex; sqInt fileNameSize; sqInt okToGet; sqInt typeString; char *typeStringIndex; creatorString = interpreterProxy->stackValue(0); typeString = interpreterProxy->stackValue(1); fileName = interpreterProxy->stackValue(2); if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(fileName))) { return interpreterProxy->primitiveFail(); } creatorStringIndex = interpreterProxy->firstIndexableField(creatorString); typeStringIndex = interpreterProxy->firstIndexableField(typeString); fileNameIndex = interpreterProxy->firstIndexableField(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ fileNameSize = interpreterProxy->byteSizeOf(fileName); if (sCGFTfn != 0) { okToGet = ((sqInt (*)(char *, sqInt))sCGFTfn)(fileNameIndex, fileNameSize); if (!(okToGet)) { return interpreterProxy->primitiveFail(); } } if (!(dir_GetMacFileTypeAndCreator(fileNameIndex, fileNameSize, typeStringIndex, creatorStringIndex))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); } EXPORT(sqInt) primitiveDirectoryLookup(void) { sqInt createDate; sqInt dirFlag; char entryName[256]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt index; sqInt modifiedDate; sqInt okToList; sqInt pathName; char *pathNameIndex; sqInt pathNameSize; sqInt status; index = interpreterProxy->stackIntegerValue(0); pathName = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(pathName))) { return interpreterProxy->primitiveFail(); } pathNameIndex = interpreterProxy->firstIndexableField(pathName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ pathNameSize = interpreterProxy->byteSizeOf(pathName); if (sCLPfn != 0) { okToList = ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize); } else { okToList = 1; } if (okToList) { status = dir_Lookup(pathNameIndex, pathNameSize, index, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize); } else { status = DirNoMoreEntries; } if (interpreterProxy->failed()) { return null; } if (status == DirNoMoreEntries) { interpreterProxy->popthenPush(3, interpreterProxy->nilObject()); return null; } if (status == DirBadPath) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(3, makeDirEntryNamesizecreateDatemodDateisDirfileSize(entryName, entryNameSize, createDate, modifiedDate, dirFlag, fileSize)); } EXPORT(sqInt) primitiveDirectorySetMacTypeAndCreator(void) { sqInt creatorString; char *creatorStringIndex; sqInt fileName; char *fileNameIndex; sqInt fileNameSize; sqInt okToSet; sqInt typeString; char *typeStringIndex; creatorString = interpreterProxy->stackValue(0); typeString = interpreterProxy->stackValue(1); fileName = interpreterProxy->stackValue(2); if (!((interpreterProxy->isBytes(creatorString)) && ((interpreterProxy->byteSizeOf(creatorString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isBytes(typeString)) && ((interpreterProxy->byteSizeOf(typeString)) == 4))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(fileName))) { return interpreterProxy->primitiveFail(); } creatorStringIndex = interpreterProxy->firstIndexableField(creatorString); typeStringIndex = interpreterProxy->firstIndexableField(typeString); fileNameIndex = interpreterProxy->firstIndexableField(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ fileNameSize = interpreterProxy->byteSizeOf(fileName); if (sCSFTfn != 0) { okToSet = ((sqInt (*)(char *, sqInt))sCSFTfn)(fileNameIndex, fileNameSize); if (!(okToSet)) { return interpreterProxy->primitiveFail(); } } if (!(dir_SetMacFileTypeAndCreator(fileNameIndex, fileNameSize,typeStringIndex, creatorStringIndex))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); } /* If the security plugin can be loaded, use it to turn off file access If not, assume it's ok */ EXPORT(sqInt) primitiveDisableFileAccess(void) { if (sDFAfn != 0) { ((sqInt (*)(void))sDFAfn)(); } } EXPORT(sqInt) primitiveFileAtEnd(void) { sqInt atEnd; SQFile *file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { atEnd = sqFileAtEnd(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); interpreterProxy->pushBool(atEnd); } } EXPORT(sqInt) primitiveFileClose(void) { SQFile *file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileClose(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileDelete(void) { char *nameIndex; sqInt namePointer; sqInt nameSize; sqInt okToDelete; namePointer = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(namePointer))) { return interpreterProxy->primitiveFail(); } nameIndex = interpreterProxy->firstIndexableField(namePointer); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ nameSize = interpreterProxy->byteSizeOf(namePointer); if (sCDFfn != 0) { okToDelete = ((sqInt (*)(char *, sqInt))sCDFfn)(nameIndex, nameSize); if (!(okToDelete)) { return interpreterProxy->primitiveFail(); } } sqFileDeleteNameSize(nameIndex, nameSize); if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileFlush(void) { SQFile *file; sqInt objectPointer; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileFlush(file); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(1); } } EXPORT(sqInt) primitiveFileGetPosition(void) { SQFile *file; sqInt objectPointer; squeakFileOffsetType position; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { position = sqFileGetPosition(file); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(2, interpreterProxy->positive64BitIntegerFor(position)); } } EXPORT(sqInt) primitiveFileOpen(void) { sqInt filePointer; char *nameIndex; sqInt namePointer; sqInt nameSize; sqInt writeFlag; writeFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); namePointer = interpreterProxy->stackValue(1); if (!(interpreterProxy->isBytes(namePointer))) { return interpreterProxy->primitiveFail(); } nameIndex = interpreterProxy->firstIndexableField(namePointer); nameSize = interpreterProxy->byteSizeOf(namePointer); filePointer = fileOpenNamesizewritesecure(nameIndex, nameSize, writeFlag, 1); if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(3, filePointer); } } EXPORT(sqInt) primitiveFileRead(void) { sqInt array; sqInt bytesRead; size_t count; size_t elementSize; SQFile *file; sqInt objectPointer; sqInt retryCount; size_t startIndex; retryCount = 0; count = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); startIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); while (1) { array = interpreterProxy->stackValue(2); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(3); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if ((interpreterProxy->failed()) || (!(interpreterProxy->isWordsOrBytes(array)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } elementSize = (interpreterProxy->isWords(array) ? 4 : 1); if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } bytesRead = sqFileReadIntoAt(file, count * elementSize, ((char *) (interpreterProxy->firstIndexableField(array))), (startIndex - 1) * elementSize); if (!(((interpreterProxy->primitiveFailureCode()) == PrimErrObjectMayMove) && (((retryCount += 1)) <= 2))) break; interpreterProxy->tenuringIncrementalGC(); interpreterProxy->primitiveFailFor(PrimNoErr); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(5, (((bytesRead / elementSize) << 1) | 1)); } } EXPORT(sqInt) primitiveFileRename(void) { char *newNameIndex; sqInt newNamePointer; sqInt newNameSize; sqInt okToRename; char *oldNameIndex; sqInt oldNamePointer; sqInt oldNameSize; newNamePointer = interpreterProxy->stackValue(0); oldNamePointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(newNamePointer)) && (interpreterProxy->isBytes(oldNamePointer)))) { return interpreterProxy->primitiveFail(); } newNameIndex = interpreterProxy->firstIndexableField(newNamePointer); newNameSize = interpreterProxy->byteSizeOf(newNamePointer); oldNameIndex = interpreterProxy->firstIndexableField(oldNamePointer); /* If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok */ oldNameSize = interpreterProxy->byteSizeOf(oldNamePointer); if (sCRFfn != 0) { okToRename = ((sqInt (*)(char *, sqInt))sCRFfn)(oldNameIndex, oldNameSize); if (!(okToRename)) { return interpreterProxy->primitiveFail(); } } sqFileRenameOldSizeNewSize(oldNameIndex, oldNameSize, newNameIndex, newNameSize); if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileSetPosition(void) { SQFile *file; squeakFileOffsetType newPosition; sqInt objectPointer; sqInt sz; if (!(((interpreterProxy->stackValue(0)) & 1))) { sz = sizeof(squeakFileOffsetType); if ((interpreterProxy->byteSizeOf(interpreterProxy->stackValue(0))) > sz) { return interpreterProxy->primitiveFail(); } } newPosition = interpreterProxy->positive64BitValueOf(interpreterProxy->stackValue(0)); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileSetPosition(file, newPosition); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileSize(void) { SQFile *file; sqInt objectPointer; squeakFileOffsetType size; /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(0); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { size = sqFileSize(file); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(2, interpreterProxy->positive64BitIntegerFor(size)); } } /* Answer an Array of file handles for standard in, standard out and standard error, with nil in entries that are unvailable, e.g. because the platform does not provide standard error, etc. Fail if there are no standard i/o facilities on the platform or if the security plugin denies access or if memory runs out. */ EXPORT(sqInt) primitiveFileStdioHandles(void) { SQFile fileRecords[3]; sqInt index; sqInt result; sqInt validMask; if (sHFAfn != 0) { if (!( ((sqInt (*)(void))sHFAfn)())) { return interpreterProxy->primitiveFailFor(PrimErrUnsupported); } } validMask = sqFileStdioHandlesInto((&fileRecords)); if (validMask == 0) { return interpreterProxy->primitiveFailFor(PrimErrUnsupported); } result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); if (result == null) { return interpreterProxy->primitiveFailFor(PrimErrNoMemory); } interpreterProxy->pushRemappableOop(result); for (index = 0; index <= 2; index += 1) { if ((validMask & (1 << index)) != 0) { result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); if (result == null) { interpreterProxy->popRemappableOop(); return interpreterProxy->primitiveFailFor(PrimErrNoMemory); } interpreterProxy->storePointerofObjectwithValue(index, interpreterProxy->topRemappableOop(), result); memcpy(interpreterProxy->firstIndexableField(result), (&(fileRecords[index])), fileRecordSize()); } } # if COGMTVM interpreterProxy->fullGC(); # endif /* COGMTVM */ result = interpreterProxy->popRemappableOop(); interpreterProxy->popthenPush(1, result); } /* ftruncate is not an ansi function so we have a macro to point to a suitable platform implementation */ EXPORT(sqInt) primitiveFileTruncate(void) { SQFile *file; sqInt objectPointer; sqInt sz; squeakFileOffsetType truncatePosition; if (!(((interpreterProxy->stackValue(0)) & 1))) { sz = sizeof(squeakFileOffsetType); if ((interpreterProxy->byteSizeOf(interpreterProxy->stackValue(0))) > sz) { return interpreterProxy->primitiveFail(); } } truncatePosition = interpreterProxy->positive64BitValueOf(interpreterProxy->stackValue(0)); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(1); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->failed())) { sqFileTruncate(file, truncatePosition); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(2); } } EXPORT(sqInt) primitiveFileWrite(void) { sqInt array; char *arrayIndex; size_t byteSize; sqInt bytesWritten; size_t count; SQFile *file; sqInt objectPointer; size_t startIndex; count = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); startIndex = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); array = interpreterProxy->stackValue(2); /* begin fileValueOf: */ objectPointer = interpreterProxy->stackValue(3); if (!((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize())))) { interpreterProxy->primitiveFail(); file = null; goto l1; } file = interpreterProxy->firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(interpreterProxy->isWordsOrBytes(array))) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } if (!((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { /* Note: adjust startIndex for zero-origin indexing */ arrayIndex = interpreterProxy->firstIndexableField(array); bytesWritten = sqFileWriteFromAt(file, count * byteSize, arrayIndex, (startIndex - 1) * byteSize); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(5, (((bytesWritten / byteSize) << 1) | 1)); } } EXPORT(sqInt) primitiveHasFileAccess(void) { sqInt hasAccess; if (sHFAfn != 0) { hasAccess = ((sqInt (*)(void))sHFAfn)(); } else { hasAccess = 1; } interpreterProxy->pop(1); interpreterProxy->pushBool(hasAccess); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Exported entry point for the VM. Needed for image saving only and no-op on anything but Macs. */ EXPORT(sqInt) setMacFileTypeAndCreator(char *fileName, char *typeString, char *creatorString) { return dir_SetMacFileTypeAndCreator(fileName, strlen(fileName), typeString, creatorString); } EXPORT(sqInt) shutdownModule(void) { return sqFileShutdown(); } #ifdef SQUEAK_BUILTIN_PLUGIN void* FilePlugin_exports[][3] = { {"FilePlugin", "fileOpenNamesizewritesecure", (void*)fileOpenNamesizewritesecure}, {"FilePlugin", "getModuleName", (void*)getModuleName}, {"FilePlugin", "getThisSession", (void*)getThisSession}, {"FilePlugin", "initialiseModule", (void*)initialiseModule}, {"FilePlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"FilePlugin", "primitiveDirectoryCreate", (void*)primitiveDirectoryCreate}, {"FilePlugin", "primitiveDirectoryDelete", (void*)primitiveDirectoryDelete}, {"FilePlugin", "primitiveDirectoryDelimitor", (void*)primitiveDirectoryDelimitor}, {"FilePlugin", "primitiveDirectoryEntry", (void*)primitiveDirectoryEntry}, {"FilePlugin", "primitiveDirectoryGetMacTypeAndCreator", (void*)primitiveDirectoryGetMacTypeAndCreator}, {"FilePlugin", "primitiveDirectoryLookup", (void*)primitiveDirectoryLookup}, {"FilePlugin", "primitiveDirectorySetMacTypeAndCreator", (void*)primitiveDirectorySetMacTypeAndCreator}, {"FilePlugin", "primitiveDisableFileAccess", (void*)primitiveDisableFileAccess}, {"FilePlugin", "primitiveFileAtEnd", (void*)primitiveFileAtEnd}, {"FilePlugin", "primitiveFileClose", (void*)primitiveFileClose}, {"FilePlugin", "primitiveFileDelete", (void*)primitiveFileDelete}, {"FilePlugin", "primitiveFileFlush", (void*)primitiveFileFlush}, {"FilePlugin", "primitiveFileGetPosition", (void*)primitiveFileGetPosition}, {"FilePlugin", "primitiveFileOpen", (void*)primitiveFileOpen}, {"FilePlugin", "primitiveFileRead", (void*)primitiveFileRead}, {"FilePlugin", "primitiveFileRename", (void*)primitiveFileRename}, {"FilePlugin", "primitiveFileSetPosition", (void*)primitiveFileSetPosition}, {"FilePlugin", "primitiveFileSize", (void*)primitiveFileSize}, {"FilePlugin", "primitiveFileStdioHandles", (void*)primitiveFileStdioHandles}, {"FilePlugin", "primitiveFileTruncate", (void*)primitiveFileTruncate}, {"FilePlugin", "primitiveFileWrite", (void*)primitiveFileWrite}, {"FilePlugin", "primitiveHasFileAccess", (void*)primitiveHasFileAccess}, {"FilePlugin", "setInterpreter", (void*)setInterpreter}, {"FilePlugin", "setMacFileTypeAndCreator", (void*)setMacFileTypeAndCreator}, {"FilePlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FloatArrayPlugin/FloatArrayPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from FloatArrayPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "FloatArrayPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveAddFloatArray(void); EXPORT(sqInt) primitiveAddScalar(void); EXPORT(sqInt) primitiveAt(void); EXPORT(sqInt) primitiveAtPut(void); EXPORT(sqInt) primitiveDivFloatArray(void); EXPORT(sqInt) primitiveDivScalar(void); EXPORT(sqInt) primitiveDotProduct(void); EXPORT(sqInt) primitiveEqual(void); EXPORT(sqInt) primitiveHashArray(void); EXPORT(sqInt) primitiveLength(void); EXPORT(sqInt) primitiveMulFloatArray(void); EXPORT(sqInt) primitiveMulScalar(void); EXPORT(sqInt) primitiveNormalize(void); EXPORT(sqInt) primitiveSubFloatArray(void); EXPORT(sqInt) primitiveSubScalar(void); EXPORT(sqInt) primitiveSum(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FloatArrayPlugin VMMaker-oscog.dtl.57 (i)" #else "FloatArrayPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Primitive. Add the receiver and the argument, both FloatArrays and store the result into the receiver. */ EXPORT(sqInt) primitiveAddFloatArray(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(arg); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvr))); if (interpreterProxy->failed()) { return null; } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) + (((double) (argPtr[i])))); } interpreterProxy->pop(1); } /* Primitive. Add the argument, a scalar value to the receiver, a FloatArray */ EXPORT(sqInt) primitiveAddScalar(void) { sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double value; value = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) + value); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveAt(void) { float *floatPtr; double floatValue; sqInt index; sqInt rcvr; index = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); interpreterProxy->success((index > 0) && (index <= (interpreterProxy->slotSizeOf(rcvr)))); if (interpreterProxy->failed()) { return null; } floatPtr = interpreterProxy->firstIndexableField(rcvr); floatValue = ((double) (floatPtr[index - 1]) ); interpreterProxy->pop(2); interpreterProxy->pushFloat(floatValue); } EXPORT(sqInt) primitiveAtPut(void) { float *floatPtr; double floatValue; sqInt index; sqInt rcvr; sqInt value; value = interpreterProxy->stackValue(0); if ((value & 1)) { floatValue = ((double) ((value >> 1)) ); } else { floatValue = interpreterProxy->floatValueOf(value); } index = interpreterProxy->stackIntegerValue(1); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); interpreterProxy->success((index > 0) && (index <= (interpreterProxy->slotSizeOf(rcvr)))); if (interpreterProxy->failed()) { return null; } floatPtr = interpreterProxy->firstIndexableField(rcvr); floatPtr[index - 1] = (((float) floatValue)); if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(3, value); } } /* Primitive. Add the receiver and the argument, both FloatArrays and store the result into the receiver. */ EXPORT(sqInt) primitiveDivFloatArray(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(arg); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvr))); if (interpreterProxy->failed()) { return null; } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); /* Check if any of the argument's values is zero */ argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); for (i = 0; i <= (length - 1); i += 1) { if ((intAtPointer(((char*) (argPtr + i)))) == 0) { return interpreterProxy->primitiveFail(); } } for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) / (((double) (argPtr[i])))); } interpreterProxy->pop(1); } /* Primitive. Add the argument, a scalar value to the receiver, a FloatArray */ EXPORT(sqInt) primitiveDivScalar(void) { sqInt i; double inverse; sqInt length; sqInt rcvr; float *rcvrPtr; double value; value = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (value == 0.0) { return interpreterProxy->primitiveFail(); } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); inverse = 1.0 / value; for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) * inverse); } interpreterProxy->pop(1); } /* Primitive. Compute the dot product of the receiver and the argument. The dot product is defined as the sum of the products of the individual elements. */ EXPORT(sqInt) primitiveDotProduct(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double result; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(arg); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvr))); if (interpreterProxy->failed()) { return null; } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); result = 0.0; for (i = 0; i <= (length - 1); i += 1) { result += (((double) (rcvrPtr[i]))) * (((double) (argPtr[i]))); } interpreterProxy->pop(2); interpreterProxy->pushFloat(result); } EXPORT(sqInt) primitiveEqual(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); length = interpreterProxy->stSizeOf(arg); if (!(length == (interpreterProxy->stSizeOf(rcvr)))) { return interpreterProxy->pushBool(0); } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); for (i = 0; i <= (length - 1); i += 1) { if (!((rcvrPtr[i]) == (argPtr[i]))) { return interpreterProxy->pushBool(0); } } return interpreterProxy->pushBool(1); } EXPORT(sqInt) primitiveHashArray(void) { sqInt i; sqInt length; sqInt rcvr; int *rcvrPtr; sqInt result; rcvr = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((int *) (interpreterProxy->firstIndexableField(rcvr))); result = 0; for (i = 0; i <= (length - 1); i += 1) { result += rcvrPtr[i]; } interpreterProxy->pop(1); return interpreterProxy->pushInteger(result & 536870911); } /* Primitive. Compute the length of the argument (sqrt of sum of component squares). */ EXPORT(sqInt) primitiveLength(void) { sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double result; rcvr = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); interpreterProxy->success(1); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); result = 0.0; for (i = 0; i <= (length - 1); i += 1) { result += (((double) (rcvrPtr[i]))) * (((double) (rcvrPtr[i]))); } result = sqrt(result); interpreterProxy->popthenPush(1, interpreterProxy->floatObjectOf(result)); } /* Primitive. Add the receiver and the argument, both FloatArrays and store the result into the receiver. */ EXPORT(sqInt) primitiveMulFloatArray(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(arg); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvr))); if (interpreterProxy->failed()) { return null; } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) * (((double) (argPtr[i])))); } interpreterProxy->pop(1); } /* Primitive. Add the argument, a scalar value to the receiver, a FloatArray */ EXPORT(sqInt) primitiveMulScalar(void) { sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double value; value = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) * value); } interpreterProxy->pop(1); } /* Primitive. Normalize the argument (A FloatArray) in place. */ EXPORT(sqInt) primitiveNormalize(void) { sqInt i; double len; sqInt length; sqInt rcvr; float *rcvrPtr; rcvr = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); interpreterProxy->success(1); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); len = 0.0; for (i = 0; i <= (length - 1); i += 1) { len += (((double) (rcvrPtr[i]))) * (((double) (rcvrPtr[i]))); } interpreterProxy->success(len > 0.0); if (interpreterProxy->failed()) { return null; } len = sqrt(len); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) / len); } } /* Primitive. Add the receiver and the argument, both FloatArrays and store the result into the receiver. */ EXPORT(sqInt) primitiveSubFloatArray(void) { sqInt arg; float *argPtr; sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; arg = interpreterProxy->stackObjectValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(arg)); interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(arg); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvr))); if (interpreterProxy->failed()) { return null; } rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); argPtr = ((float *) (interpreterProxy->firstIndexableField(arg))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) - (((double) (argPtr[i])))); } interpreterProxy->pop(1); } /* Primitive. Add the argument, a scalar value to the receiver, a FloatArray */ EXPORT(sqInt) primitiveSubScalar(void) { sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double value; value = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); for (i = 0; i <= (length - 1); i += 1) { rcvrPtr[i] = ((((double) (rcvrPtr[i]))) - value); } interpreterProxy->pop(1); } /* Primitive. Find the sum of each float in the receiver, a FloatArray, and stash the result into the argument Float. */ EXPORT(sqInt) primitiveSum(void) { sqInt i; sqInt length; sqInt rcvr; float *rcvrPtr; double sum; rcvr = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvr)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvr); rcvrPtr = ((float *) (interpreterProxy->firstIndexableField(rcvr))); sum = 0.0; for (i = 0; i <= (length - 1); i += 1) { sum += ((double) (rcvrPtr[i])); } interpreterProxy->popthenPush(1, interpreterProxy->floatObjectOf(sum)); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* FloatArrayPlugin_exports[][3] = { {"FloatArrayPlugin", "getModuleName", (void*)getModuleName}, {"FloatArrayPlugin", "primitiveAddFloatArray", (void*)primitiveAddFloatArray}, {"FloatArrayPlugin", "primitiveAddScalar", (void*)primitiveAddScalar}, {"FloatArrayPlugin", "primitiveAt", (void*)primitiveAt}, {"FloatArrayPlugin", "primitiveAtPut", (void*)primitiveAtPut}, {"FloatArrayPlugin", "primitiveDivFloatArray", (void*)primitiveDivFloatArray}, {"FloatArrayPlugin", "primitiveDivScalar", (void*)primitiveDivScalar}, {"FloatArrayPlugin", "primitiveDotProduct", (void*)primitiveDotProduct}, {"FloatArrayPlugin", "primitiveEqual", (void*)primitiveEqual}, {"FloatArrayPlugin", "primitiveHashArray", (void*)primitiveHashArray}, {"FloatArrayPlugin", "primitiveLength", (void*)primitiveLength}, {"FloatArrayPlugin", "primitiveMulFloatArray", (void*)primitiveMulFloatArray}, {"FloatArrayPlugin", "primitiveMulScalar", (void*)primitiveMulScalar}, {"FloatArrayPlugin", "primitiveNormalize", (void*)primitiveNormalize}, {"FloatArrayPlugin", "primitiveSubFloatArray", (void*)primitiveSubFloatArray}, {"FloatArrayPlugin", "primitiveSubScalar", (void*)primitiveSubScalar}, {"FloatArrayPlugin", "primitiveSum", (void*)primitiveSum}, {"FloatArrayPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/FloatMathPlugin/FloatMathPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from FloatMathPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "FloatMathPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "FloatMathPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveArcCos(void); EXPORT(sqInt) primitiveArcCosH(void); EXPORT(sqInt) primitiveArcSin(void); EXPORT(sqInt) primitiveArcSinH(void); EXPORT(sqInt) primitiveArcTan(void); EXPORT(sqInt) primitiveArcTan2(void); EXPORT(sqInt) primitiveArcTanH(void); EXPORT(sqInt) primitiveCos(void); EXPORT(sqInt) primitiveCosH(void); EXPORT(sqInt) primitiveExp(void); EXPORT(sqInt) primitiveFMod(void); EXPORT(sqInt) primitiveFractionalPart(void); EXPORT(sqInt) primitiveHypot(void); EXPORT(sqInt) primitiveLog10(void); EXPORT(sqInt) primitiveLogN(void); EXPORT(sqInt) primitiveRaisedToPower(void); EXPORT(sqInt) primitiveSin(void); EXPORT(sqInt) primitiveSinH(void); EXPORT(sqInt) primitiveSqrt(void); EXPORT(sqInt) primitiveTan(void); EXPORT(sqInt) primitiveTanH(void); EXPORT(sqInt) primitiveTimesTwoPower(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FloatMathPlugin VMMaker-oscog.dtl.57 (i)" #else "FloatMathPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Computes acos(receiver) */ EXPORT(sqInt) primitiveArcCos(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_acos(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes acosh(receiver) */ EXPORT(sqInt) primitiveArcCosH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_acosh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes asin(receiver) */ EXPORT(sqInt) primitiveArcSin(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_asin(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes asinh(receiver) */ EXPORT(sqInt) primitiveArcSinH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_asinh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes atan(receiver) */ EXPORT(sqInt) primitiveArcTan(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_atan(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes atan2(receiver, arg) */ EXPORT(sqInt) primitiveArcTan2(void) { double arg; double rcvr; double result; arg = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackFloatValue(1); if (interpreterProxy->failed()) { return null; } result = __ieee754_atan2(rcvr, arg); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes atanh(receiver) */ EXPORT(sqInt) primitiveArcTanH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_atanh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes cos(receiver) */ EXPORT(sqInt) primitiveCos(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_cos(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes cosh(receiver) */ EXPORT(sqInt) primitiveCosH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_cosh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes E raised to the receiver power. */ EXPORT(sqInt) primitiveExp(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_exp(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes receiver \\ arg */ EXPORT(sqInt) primitiveFMod(void) { double arg; double rcvr; double result; arg = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackFloatValue(1); if (interpreterProxy->failed()) { return null; } result = __ieee754_fmod(rcvr, arg); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes receiver \\ 1.0 */ EXPORT(sqInt) primitiveFractionalPart(void) { double rcvr; double result; double trunc; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_modf(rcvr, &trunc); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* hypot(x,y) returns sqrt(x^2+y^2) with error less than 1 ulps */ EXPORT(sqInt) primitiveHypot(void) { double arg; double rcvr; double result; arg = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackFloatValue(1); if (interpreterProxy->failed()) { return null; } result = __ieee754_hypot(rcvr, arg); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes log10(receiver) */ EXPORT(sqInt) primitiveLog10(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } if (rcvr < 0.0) { return interpreterProxy->primitiveFail(); } result = __ieee754_log10(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes log(receiver) */ EXPORT(sqInt) primitiveLogN(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } if (rcvr < 0.0) { return interpreterProxy->primitiveFail(); } result = __ieee754_log(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes receiver**arg */ EXPORT(sqInt) primitiveRaisedToPower(void) { double arg; double rcvr; double result; arg = interpreterProxy->stackFloatValue(0); rcvr = interpreterProxy->stackFloatValue(1); if (interpreterProxy->failed()) { return null; } result = __ieee754_pow(rcvr, arg); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes sin(receiver) */ EXPORT(sqInt) primitiveSin(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_sin(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes sinh(receiver) */ EXPORT(sqInt) primitiveSinH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_sinh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes sqrt(receiver) */ EXPORT(sqInt) primitiveSqrt(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } if (rcvr < 0.0) { return interpreterProxy->primitiveFail(); } result = __ieee754_sqrt(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes tan(receiver) */ EXPORT(sqInt) primitiveTan(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_tan(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes tanh(receiver) */ EXPORT(sqInt) primitiveTanH(void) { double rcvr; double result; rcvr = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } result = __ieee754_tanh(rcvr); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Computes E raised to the receiver power. */ EXPORT(sqInt) primitiveTimesTwoPower(void) { sqInt arg; double rcvr; double result; arg = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackFloatValue(1); if (interpreterProxy->failed()) { return null; } result = __ieee754_ldexp(rcvr, arg); if (isnan(result)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushFloat(result); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* FloatMathPlugin_exports[][3] = { {"FloatMathPlugin", "getModuleName", (void*)getModuleName}, {"FloatMathPlugin", "primitiveArcCos", (void*)primitiveArcCos}, {"FloatMathPlugin", "primitiveArcCosH", (void*)primitiveArcCosH}, {"FloatMathPlugin", "primitiveArcSin", (void*)primitiveArcSin}, {"FloatMathPlugin", "primitiveArcSinH", (void*)primitiveArcSinH}, {"FloatMathPlugin", "primitiveArcTan", (void*)primitiveArcTan}, {"FloatMathPlugin", "primitiveArcTan2", (void*)primitiveArcTan2}, {"FloatMathPlugin", "primitiveArcTanH", (void*)primitiveArcTanH}, {"FloatMathPlugin", "primitiveCos", (void*)primitiveCos}, {"FloatMathPlugin", "primitiveCosH", (void*)primitiveCosH}, {"FloatMathPlugin", "primitiveExp", (void*)primitiveExp}, {"FloatMathPlugin", "primitiveFMod", (void*)primitiveFMod}, {"FloatMathPlugin", "primitiveFractionalPart", (void*)primitiveFractionalPart}, {"FloatMathPlugin", "primitiveHypot", (void*)primitiveHypot}, {"FloatMathPlugin", "primitiveLog10", (void*)primitiveLog10}, {"FloatMathPlugin", "primitiveLogN", (void*)primitiveLogN}, {"FloatMathPlugin", "primitiveRaisedToPower", (void*)primitiveRaisedToPower}, {"FloatMathPlugin", "primitiveSin", (void*)primitiveSin}, {"FloatMathPlugin", "primitiveSinH", (void*)primitiveSinH}, {"FloatMathPlugin", "primitiveSqrt", (void*)primitiveSqrt}, {"FloatMathPlugin", "primitiveTan", (void*)primitiveTan}, {"FloatMathPlugin", "primitiveTanH", (void*)primitiveTanH}, {"FloatMathPlugin", "primitiveTimesTwoPower", (void*)primitiveTimesTwoPower}, {"FloatMathPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/GeniePlugin/GeniePlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from GeniePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "GeniePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt cSquaredDistanceFromto(int * aPoint, int * bPoint); static sqInt cSubstAngleFactorFromto(sqInt startDegreeNumber, sqInt endDegreeNumber); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt majorNO(void); static sqInt minorNO(void); static sqInt msg(char *s); EXPORT(sqInt) primSameClassAbsoluteStrokeDistanceMyPoints_otherPoints_myVectors_otherVectors_mySquaredLengths_otherSquaredLengths_myAngles_otherAngles_maxSizeAndReferenceFlag_rowBase_rowInsertRemove_rowInsertRemoveCount(void); EXPORT(sqInt) primVersionNO(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "GeniePlugin v2.0 22 April 2011 VMMaker-oscog.dtl.57 (i)" #else "GeniePlugin v2.0 22 April 2011 VMMaker-oscog.dtl.57 (e)" #endif ; /* arguments are pointer to ints paired as x,y coordinates of points */ static sqInt cSquaredDistanceFromto(int * aPoint, int * bPoint) { sqInt aPointX; sqInt aPointY; sqInt bPointX; sqInt bPointY; sqInt xDiff; sqInt yDiff; aPointX = aPoint[0]; aPointY = aPoint[1]; bPointX = bPoint[0]; bPointY = bPoint[1]; xDiff = bPointX - aPointX; yDiff = bPointY - aPointY; return (xDiff * xDiff) + (yDiff * yDiff); } static sqInt cSubstAngleFactorFromto(sqInt startDegreeNumber, sqInt endDegreeNumber) { sqInt absDiff; absDiff = abs(endDegreeNumber - startDegreeNumber); if (absDiff > 180) { absDiff = 360 - absDiff; } return ((usqInt) (absDiff * absDiff) >> 6); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt majorNO(void) { return 2; } static sqInt minorNO(void) { return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primSameClassAbsoluteStrokeDistanceMyPoints_otherPoints_myVectors_otherVectors_mySquaredLengths_otherSquaredLengths_myAngles_otherAngles_maxSizeAndReferenceFlag_rowBase_rowInsertRemove_rowInsertRemoveCount(void) { sqInt additionalMultiInsertRemoveCost; sqInt base; sqInt forReference; sqInt i; sqInt iM1; sqInt iM1T2; sqInt insert; sqInt insertBase; sqInt insertRemove; sqInt insertRemoveCount; sqInt j; sqInt jLimiT; sqInt jM1; sqInt jM1T2; sqInt maxDist; sqInt maxSize; sqInt maxSizeAndRefFlag; int * myAngles; sqInt myAnglesOop; int * myPoints; sqInt myPointsOop; int * mySquaredLengths; sqInt mySquaredLengthsOop; int * myVectors; sqInt myVectorsOop; sqInt myVectorsSize; int * otherAngles; sqInt otherAnglesOop; int * otherPoints; sqInt otherPointsOop; sqInt otherPointsSize; int * otherSquaredLengths; sqInt otherSquaredLengthsOop; sqInt otherSquaredLengthsSize; int * otherVectors; sqInt otherVectorsOop; sqInt otherVectorsSize; sqInt remove; sqInt removeBase; int * rowBase; sqInt rowBaseOop; sqInt rowBaseSize; int * rowInsertRemove; int * rowInsertRemoveCount; sqInt rowInsertRemoveCountOop; sqInt rowInsertRemoveOop; sqInt subst; sqInt substBase; sqInt _return_value; myPointsOop = interpreterProxy->stackValue(11); otherPointsOop = interpreterProxy->stackValue(10); myVectorsOop = interpreterProxy->stackValue(9); otherVectorsOop = interpreterProxy->stackValue(8); mySquaredLengthsOop = interpreterProxy->stackValue(7); otherSquaredLengthsOop = interpreterProxy->stackValue(6); myAnglesOop = interpreterProxy->stackValue(5); otherAnglesOop = interpreterProxy->stackValue(4); maxSizeAndRefFlag = interpreterProxy->stackIntegerValue(3); rowBaseOop = interpreterProxy->stackValue(2); rowInsertRemoveOop = interpreterProxy->stackValue(1); rowInsertRemoveCountOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { msg("failed 1"); return null; } interpreterProxy->success(((((((((((interpreterProxy->isWords(myPointsOop)) && (interpreterProxy->isWords(otherPointsOop))) && (interpreterProxy->isWords(myVectorsOop))) && (interpreterProxy->isWords(otherVectorsOop))) && (interpreterProxy->isWords(mySquaredLengthsOop))) && (interpreterProxy->isWords(otherSquaredLengthsOop))) && (interpreterProxy->isWords(myAnglesOop))) && (interpreterProxy->isWords(otherAnglesOop))) && (interpreterProxy->isWords(rowBaseOop))) && (interpreterProxy->isWords(rowInsertRemoveOop))) && (interpreterProxy->isWords(rowInsertRemoveCountOop))); if (interpreterProxy->failed()) { msg("failed 2"); return null; } interpreterProxy->success((interpreterProxy->isMemberOf(myPointsOop, "PointArray")) && (interpreterProxy->isMemberOf(otherPointsOop, "PointArray"))); if (interpreterProxy->failed()) { msg("failed 3"); return null; } myPoints = interpreterProxy->firstIndexableField(myPointsOop); otherPoints = interpreterProxy->firstIndexableField(otherPointsOop); myVectors = interpreterProxy->firstIndexableField(myVectorsOop); otherVectors = interpreterProxy->firstIndexableField(otherVectorsOop); mySquaredLengths = interpreterProxy->firstIndexableField(mySquaredLengthsOop); otherSquaredLengths = interpreterProxy->firstIndexableField(otherSquaredLengthsOop); myAngles = interpreterProxy->firstIndexableField(myAnglesOop); otherAngles = interpreterProxy->firstIndexableField(otherAnglesOop); rowBase = interpreterProxy->firstIndexableField(rowBaseOop); rowInsertRemove = interpreterProxy->firstIndexableField(rowInsertRemoveOop); /* Note: myPointsSize and mySquaredLengthsSize variables eliminated to reduce method temporary variable count for closure-enabled images */ /* PointArrays */ /* myPointsSize := (interpreterProxy stSizeOf: myPointsOop) bitShift: -1. */ rowInsertRemoveCount = interpreterProxy->firstIndexableField(rowInsertRemoveCountOop); otherPointsSize = ((usqInt) (interpreterProxy->stSizeOf(otherPointsOop)) >> 1); myVectorsSize = ((usqInt) (interpreterProxy->stSizeOf(myVectorsOop)) >> 1); /* IntegerArrays */ /* mySquaredLengthsSize := interpreterProxy stSizeOf: mySquaredLengthsOop. */ otherVectorsSize = ((usqInt) (interpreterProxy->stSizeOf(otherVectorsOop)) >> 1); otherSquaredLengthsSize = interpreterProxy->stSizeOf(otherSquaredLengthsOop); rowBaseSize = interpreterProxy->stSizeOf(rowBaseOop); interpreterProxy->success(((rowBaseSize == (interpreterProxy->stSizeOf(rowInsertRemoveOop))) && (rowBaseSize == (interpreterProxy->stSizeOf(rowInsertRemoveCountOop)))) && (rowBaseSize > otherVectorsSize)); if (interpreterProxy->failed()) { msg("failed 4"); return null; } interpreterProxy->success(((((((interpreterProxy->stSizeOf(mySquaredLengthsOop)) >= (myVectorsSize - 1)) && ((((usqInt) (interpreterProxy->stSizeOf(myPointsOop)) >> 1)) >= myVectorsSize)) && (otherSquaredLengthsSize >= (otherVectorsSize - 1))) && (otherPointsSize >= otherVectorsSize)) && ((interpreterProxy->stSizeOf(myAnglesOop)) >= (myVectorsSize - 1))) && ((interpreterProxy->stSizeOf(otherAnglesOop)) >= (otherVectorsSize - 1))); if (interpreterProxy->failed()) { msg("failed 5"); return null; } forReference = maxSizeAndRefFlag & 1; maxSize = ((usqInt) maxSizeAndRefFlag >> 1); maxDist = ((usqInt) 1 << 29); if (forReference) { additionalMultiInsertRemoveCost = 0; } else { additionalMultiInsertRemoveCost = ((usqInt) (maxSize * maxSize) >> 10); } rowBase[0] = 0; rowInsertRemove[0] = 0; rowInsertRemoveCount[0] = 2; insertRemove = 0 - additionalMultiInsertRemoveCost; jLimiT = otherVectorsSize; if (!((otherPointsSize >= (jLimiT - 1)) && (otherSquaredLengthsSize >= (jLimiT - 1)))) { interpreterProxy->primitiveFail(); return null; } for (j = 1; j <= jLimiT; j += 1) { jM1 = j - 1; insertRemove = (insertRemove + (((usqInt) ((otherSquaredLengths[jM1]) + (cSquaredDistanceFromto(otherPoints + (((usqInt) jM1 << 1)), myPoints))) >> 7))) + additionalMultiInsertRemoveCost; rowInsertRemove[j] = insertRemove; rowBase[j] = (insertRemove * j); rowInsertRemoveCount[j] = (j + 1); } insertRemove = (rowInsertRemove[0]) - additionalMultiInsertRemoveCost; for (i = 1; i <= myVectorsSize; i += 1) { iM1 = i - 1; iM1T2 = ((usqInt) iM1 << 1); substBase = rowBase[0]; insertRemove = (insertRemove + (((usqInt) ((mySquaredLengths[iM1]) + (cSquaredDistanceFromto(myPoints + iM1T2, otherPoints))) >> 7))) + additionalMultiInsertRemoveCost; rowInsertRemove[0] = insertRemove; rowBase[0] = (insertRemove * i); rowInsertRemoveCount[0] = (i + 1); jLimiT = otherVectorsSize; for (j = 1; j <= jLimiT; j += 1) { jM1 = j - 1; jM1T2 = ((usqInt) jM1 << 1); removeBase = rowBase[j]; insertBase = rowBase[jM1]; remove = ((usqInt) ((mySquaredLengths[iM1]) + (cSquaredDistanceFromto(myPoints + iM1T2, otherPoints + (((usqInt) j << 1))))) >> 7); if (((insertRemove = rowInsertRemove[j])) == 0) { removeBase += remove; } else { removeBase = (removeBase + insertRemove) + (remove * (rowInsertRemoveCount[j])); remove += insertRemove; } insert = ((usqInt) ((otherSquaredLengths[jM1]) + (cSquaredDistanceFromto(otherPoints + jM1T2, myPoints + (((usqInt) i << 1))))) >> 7); if (((insertRemove = rowInsertRemove[jM1])) == 0) { insertBase += insert; } else { insertBase = (insertBase + insertRemove) + (insert * (rowInsertRemoveCount[jM1])); insert += insertRemove; } if (forReference) { substBase = maxDist; } else { subst = ((usqInt) (((cSquaredDistanceFromto(otherVectors + jM1T2, myVectors + iM1T2)) + (cSquaredDistanceFromto(otherPoints + jM1T2, myPoints + iM1T2))) * (16 + (cSubstAngleFactorFromto(otherAngles[jM1], myAngles[iM1])))) >> 11); substBase += subst; } if ((substBase <= removeBase) && (substBase <= insertBase)) { base = substBase; insertRemove = 0; insertRemoveCount = 1; } else { if (removeBase <= insertBase) { base = removeBase; insertRemove = remove + additionalMultiInsertRemoveCost; insertRemoveCount = (rowInsertRemoveCount[j]) + 1; } else { base = insertBase; insertRemove = insert + additionalMultiInsertRemoveCost; insertRemoveCount = (rowInsertRemoveCount[jM1]) + 1; } } substBase = rowBase[j]; rowBase[j] = (((base < maxDist) ? base : maxDist)); rowInsertRemove[j] = (((insertRemove < maxDist) ? insertRemove : maxDist)); rowInsertRemoveCount[j] = insertRemoveCount; } insertRemove = rowInsertRemove[0]; } _return_value = interpreterProxy->integerObjectOf(base); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, _return_value); return null; } /* majorNO * 1000 + minorNO */ EXPORT(sqInt) primVersionNO(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf(((2 * 1000) + 0)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* GeniePlugin_exports[][3] = { {"GeniePlugin", "getModuleName", (void*)getModuleName}, {"GeniePlugin", "primSameClassAbsoluteStrokeDistanceMyPoints_otherPoints_myVectors_otherVectors_mySquaredLengths_otherSquaredLengths_myAngles_otherAngles_maxSizeAndReferenceFlag_rowBase_rowInsertRemove_rowInsertRemoveCount", (void*)primSameClassAbsoluteStrokeDistanceMyPoints_otherPoints_myVectors_otherVectors_mySquaredLengths_otherSquaredLengths_myAngles_otherAngles_maxSizeAndReferenceFlag_rowBase_rowInsertRemove_rowInsertRemoveCount}, {"GeniePlugin", "primVersionNO", (void*)primVersionNO}, {"GeniePlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/HostWindowPlugin/HostWindowPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from HostWindowPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "HostWindowPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "HostWindowPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveCloseHostWindow(void); EXPORT(sqInt) primitiveCreateHostWindow(void); EXPORT(sqInt) primitiveHostWindowPosition(void); EXPORT(sqInt) primitiveHostWindowPositionSet(void); EXPORT(sqInt) primitiveHostWindowSize(void); EXPORT(sqInt) primitiveHostWindowSizeSet(void); EXPORT(sqInt) primitiveHostWindowTitle(void); EXPORT(sqInt) primitiveShowHostWindowRect(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "HostWindowPlugin VMMaker-oscog.dtl.57 (i)" #else "HostWindowPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Close a host window. windowIndex is the SmallInt handle returned previously by primitiveCreateHostWindow. Fail if the index is invalid or the platform code fails */ EXPORT(sqInt) primitiveCloseHostWindow(void) { sqInt ok; sqInt windowIndex; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } ok = closeWindow(windowIndex); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Create a host window of width 'w' pixels, height 'h' with the origin of the user area at 'x@y' from the topleft corner of the screen. Return the SmallInt value of the internal index to the window description block - which is whatever the host platform code needs it to be. */ EXPORT(sqInt) primitiveCreateHostWindow(void) { sqInt h; char *list; sqInt listLength; sqInt w; sqInt windowIndex; sqInt x; sqInt y; sqInt _return_value; w = interpreterProxy->stackIntegerValue(4); h = interpreterProxy->stackIntegerValue(3); x = interpreterProxy->stackIntegerValue(2); y = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); list = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } listLength = interpreterProxy->slotSizeOf(((sqInt)(long)(list) - 4)); windowIndex = createWindowWidthheightoriginXyattrlength(w, h, x, y, list, listLength); if (windowIndex > 0) { _return_value = interpreterProxy->integerObjectOf(windowIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } else { interpreterProxy->primitiveFail(); return null; } } /* Return the origin position of the user area of the window in pixels from the topleft corner of the screen. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowPosition(void) { sqInt pos; sqInt windowIndex; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pos = ioPositionOfWindow(windowIndex); if (pos == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) pos) >> 16, pos & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } /* Set the origin position of the user area of the window in pixels from the topleft corner of the screen- return the position actually set by the OS/GUI/window manager. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowPositionSet(void) { sqInt pos; sqInt windowIndex; sqInt x; sqInt y; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pos = ioPositionOfWindowSetxy(windowIndex, x, y); if (pos == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) pos) >> 16, pos & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } } /* Return the size of the user area of the window in pixels. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowSize(void) { sqInt size; sqInt windowIndex; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } size = ioSizeOfWindow(windowIndex); if (size == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) size) >> 16, size & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } /* Set the size of the user area of the window in pixels - return what is actually set by the OS/GUI/window manager. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowSizeSet(void) { sqInt size; sqInt windowIndex; sqInt x; sqInt y; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } size = ioSizeOfWindowSetxy(windowIndex, x, y); if (size == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) size) >> 16, size & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } } /* Set the title bar label of the window. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowTitle(void) { sqInt id; sqInt res; sqInt titleLength; char *titleString; id = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); titleString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } titleLength = interpreterProxy->slotSizeOf(((sqInt)(long)(titleString) - 4)); res = ioSetTitleOfWindow(id, titleString, titleLength); if (res == -1) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Host window analogue of DisplayScreen> primShowRectLeft:right:top:bottom: (Interpreter>primitiveShowDisplayRect) which takes the window index, bitmap details and the rectangle bounds. Fail if the windowIndex is invalid or the platform routine returns false to indicate failure */ EXPORT(sqInt) primitiveShowHostWindowRect(void) { sqInt bottom; sqInt d; usqInt *dispBits; sqInt h; sqInt left; sqInt ok; sqInt right; sqInt top; sqInt w; sqInt windowIndex; windowIndex = interpreterProxy->stackIntegerValue(8); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(7))); dispBits = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(7)))); w = interpreterProxy->stackIntegerValue(6); h = interpreterProxy->stackIntegerValue(5); d = interpreterProxy->stackIntegerValue(4); left = interpreterProxy->stackIntegerValue(3); right = interpreterProxy->stackIntegerValue(2); top = interpreterProxy->stackIntegerValue(1); bottom = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } ok = ioShowDisplayOnWindow(dispBits, w, h, d, left, right, top, bottom, windowIndex); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(9); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* do any window related VM closing down work your platform requires. */ EXPORT(sqInt) shutdownModule(void) { return ioCloseAllWindows(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* HostWindowPlugin_exports[][3] = { {"HostWindowPlugin", "getModuleName", (void*)getModuleName}, {"HostWindowPlugin", "primitiveCloseHostWindow", (void*)primitiveCloseHostWindow}, {"HostWindowPlugin", "primitiveCreateHostWindow", (void*)primitiveCreateHostWindow}, {"HostWindowPlugin", "primitiveHostWindowPosition", (void*)primitiveHostWindowPosition}, {"HostWindowPlugin", "primitiveHostWindowPositionSet", (void*)primitiveHostWindowPositionSet}, {"HostWindowPlugin", "primitiveHostWindowSize", (void*)primitiveHostWindowSize}, {"HostWindowPlugin", "primitiveHostWindowSizeSet", (void*)primitiveHostWindowSizeSet}, {"HostWindowPlugin", "primitiveHostWindowTitle", (void*)primitiveHostWindowTitle}, {"HostWindowPlugin", "primitiveShowHostWindowRect", (void*)primitiveShowHostWindowRect}, {"HostWindowPlugin", "setInterpreter", (void*)setInterpreter}, {"HostWindowPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/IA32ABI/IA32ABI.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from IA32ABIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "IA32ABIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <setjmp.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "vmCallback.h" #include "ia32abi.h" #include "sqMemoryAccess.h" typedef struct { int type; int pad; union { long valword; struct { int low, high; } valleint64; struct { int high, low; } valbeint64; double valflt64; struct { void *addr; long size; } valstruct; } crvrvs; } VMCallbackReturnValue; /*** Constants ***/ #define BaseHeaderSize 4 #define BytesPerOop 4 #define PrimErrBadArgument 3 #define PrimErrBadIndex 4 #define PrimErrBadReceiver 2 #define PrimErrInappropriate 6 #define PrimErrNoCMemory 10 #define PrimErrNoMemory 9 #define PrimErrNotFound 11 #define PrimErrUnsupported 7 /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt indexlengthinRange(sqInt byteIndex, sqInt length, sqInt rcvr); EXPORT(sqInt) isAlien(sqInt anOop); static sqInt msg(char *s); EXPORT(sqInt) primAddressField(void); EXPORT(sqInt) primAddressFieldPut(void); EXPORT(sqInt) primAlienReplace(void); EXPORT(sqInt) primAllocateExecutablePage(void); EXPORT(sqInt) primBoxedFree(void); EXPORT(sqInt) primCallOutDoubleReturn(void); EXPORT(sqInt) primCallOutFloatReturn(void); EXPORT(sqInt) primCallOutIntegralReturn(void); EXPORT(sqInt) primCalloc(void); EXPORT(sqInt) primDoubleAt(void); EXPORT(sqInt) primDoubleAtPut(void); EXPORT(sqInt) primFloatAt(void); EXPORT(sqInt) primFloatAtPut(void); EXPORT(sqInt) primFree(void); EXPORT(sqInt) primInIOProcessEventsFlagAddress(void); EXPORT(sqInt) primInLibraryFindSymbol(void); EXPORT(sqInt) primLoadLibrary(void); EXPORT(sqInt) primMalloc(void); EXPORT(sqInt) primReturnAsFromContextThrough(void); EXPORT(sqInt) primReturnFromContextThrough(void); EXPORT(sqInt) primSignedByteAt(void); EXPORT(sqInt) primSignedByteAtPut(void); EXPORT(sqInt) primSignedLongAt(void); EXPORT(sqInt) primSignedLongAtPut(void); EXPORT(sqInt) primSignedLongLongAt(void); EXPORT(sqInt) primSignedLongLongAtPut(void); EXPORT(sqInt) primSignedShortAt(void); EXPORT(sqInt) primSignedShortAtPut(void); EXPORT(sqInt) primSizeField(void); EXPORT(sqInt) primSizeFieldPut(void); EXPORT(sqInt) primStrlenFromStartIndex(void); EXPORT(sqInt) primStrlenThroughPointerAtIndex(void); EXPORT(sqInt) primThunkEntryAddress(void); EXPORT(sqInt) primUnsignedByteAt(void); EXPORT(sqInt) primUnsignedByteAtPut(void); EXPORT(sqInt) primUnsignedLongAt(void); EXPORT(sqInt) primUnsignedLongAtPut(void); EXPORT(sqInt) primUnsignedLongLongAt(void); EXPORT(sqInt) primUnsignedLongLongAtPut(void); EXPORT(sqInt) primUnsignedShortAt(void); EXPORT(sqInt) primUnsignedShortAtPut(void); EXPORT(sqInt) primVarArgsCallOutDoubleReturn(void); EXPORT(sqInt) primVarArgsCallOutFloatReturn(void); EXPORT(sqInt) primVarArgsCallOutIntegralReturn(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt sizeField(sqInt rcvr); static sqInt startOfByteData(sqInt rcvr); static sqInt startOfData(sqInt rcvr); static sqInt startOfDatawithSize(sqInt rcvr, sqInt sizeField); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "IA32ABI VMMaker-oscog.dtl.57 (i)" #else "IA32ABI VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* Answer if the indices byteIndex to byteIndex + length - 1 are valid zero-relative indices into the rcvr. N.B. This code only works when translated because asUnisgnedInteger only works for non-negative values. Hence the override in IA32ABIPluginSimulator. */ static sqInt indexlengthinRange(sqInt byteIndex, sqInt length, sqInt rcvr) { sqInt dataSize; return (((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteIndex)) + length) <= (abs(dataSize))); } EXPORT(sqInt) isAlien(sqInt anOop) { return interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Answer the unsigned 32-bit integer comprising the address field (the second 32-bit field). */ /* <Alien> primAddressField ^<Integer> <primitive: 'primAddressField' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primAddressField(void) { sqInt rcvr; sqInt value; sqInt valueOop; rcvr = interpreterProxy->stackValue(0); value = longAt((rcvr + BaseHeaderSize) + BytesPerOop); valueOop = interpreterProxy->positive32BitIntegerFor(value); return interpreterProxy->popthenPush(1, valueOop); } /* Store an unsigned integer into the size field (the second 32 bit field; little endian). */ /* <Alien> addressFieldPut: value <Integer> ^<Integer> <primitive: 'primAddressFieldPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primAddressFieldPut(void) { sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); rcvr = interpreterProxy->stackValue(1); value = interpreterProxy->positive32BitValueOf(valueOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } longAtput((rcvr + BaseHeaderSize) + BytesPerOop, value); return interpreterProxy->popthenPush(2, valueOop); } /* Copy some number of bytes from some source object starting at the index into the receiver destination object from startIndex to stopIndex . The source and destination may be Aliens or byte-indexable objects. The primitive wll have either of the following signatures: <Alien | indexableByteSubclass | indexableWordSubclass> primReplaceFrom: start <Integer> to: stop <Integer> with: replacement <Alien | indexableByteSubclass | indexableWordSubclass | Integer> startingAt: repStart <Integer> ^<self> <primitive: 'primitiveAlienReplace' error: errorCode module: 'IA32ABI'> <Anywhere> primReplaceIn: dest <Alien | indexableByteSubclass | indexableWordSubclass> from: start <Integer> to: stop <Integer> with: replacement <Alien | indexableByteSubclass | indexableWordSubclass | Integer> startingAt: repStart <Integer> ^<self> <primitive: 'primitiveAlienReplace' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primAlienReplace(void) { sqInt array; sqInt count; sqInt dest; sqInt repl; sqInt replStart; sqInt src; sqInt start; sqInt stop; sqInt totalLength; array = interpreterProxy->stackValue(4); start = interpreterProxy->stackIntegerValue(3); stop = interpreterProxy->stackIntegerValue(2); repl = interpreterProxy->stackValue(1); replStart = interpreterProxy->stackIntegerValue(0); if ((interpreterProxy->failed()) || (!(interpreterProxy->isWordsOrBytes(array)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(array), interpreterProxy->classAlien())) { totalLength = longAt(array + BaseHeaderSize); dest = (((totalLength > 0 ? (array + BaseHeaderSize) + BytesPerOop : longAt((array + BaseHeaderSize) + BytesPerOop))) + start) - 1; if (totalLength == 0) { /* no bounds checks for zero-sized (pointer) Aliens */ totalLength = stop; } else { totalLength = abs(totalLength); } } else { totalLength = interpreterProxy->byteSizeOf(array); dest = ((array + BaseHeaderSize) + start) - 1; } if (!((start >= 1) && (((start - 1) <= stop) && (stop <= totalLength)))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } if ((repl & 1)) { if (((repl >> 1)) <= 0) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } src = (((repl >> 1)) + replStart) - 1; } else { if ((interpreterProxy->fetchClassOf(repl)) == (interpreterProxy->classLargePositiveInteger())) { src = ((interpreterProxy->positive32BitValueOf(repl)) + replStart) - 1; if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } } else { if (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(repl), interpreterProxy->classAlien())) { totalLength = longAt(repl + BaseHeaderSize); src = (((totalLength > 0 ? (repl + BaseHeaderSize) + BytesPerOop : longAt((repl + BaseHeaderSize) + BytesPerOop))) + replStart) - 1; if (totalLength == 0) { /* no bounds checks for zero-sized (pointer) Aliens */ totalLength = (stop - start) + replStart; } else { totalLength = abs(totalLength); } } else { if (!(interpreterProxy->isWordsOrBytes(repl))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } totalLength = interpreterProxy->byteSizeOf(repl); src = ((repl + BaseHeaderSize) + replStart) - 1; } if (!((replStart >= 1) && (((stop - start) + replStart) <= totalLength))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } } } count = (stop - start) + 1; memcpy((void *)dest,(void *)src,count); interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } /* Answer an Alien for an executable page; for thunks */ /* primAllocateExecutablePage ^<Alien> <primitive: 'primAllocateExecutablePage' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primAllocateExecutablePage(void) { sqInt alien; long byteSize; void *mem; long *ptr; mem = allocateExecutablePage(&byteSize); if (mem == 0) { return interpreterProxy->primitiveFailFor(PrimErrNoCMemory); } alien = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classAlien(), 8); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrNoMemory); } ptr = interpreterProxy->firstIndexableField(alien); ptr[0] = (0 - byteSize); ptr[1] = (((long) mem)); interpreterProxy->popthenPush(1, alien); } /* Free the memory referenced by the receiver, an Alien. */ /* proxy <Alien> primFree ^<Alien> <primitive: 'primBoxedFree' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primBoxedFree(void) { sqInt addr; sqInt *ptr; sqInt rcvr; long sizeField; rcvr = interpreterProxy->stackObjectValue(0); if (!(((interpreterProxy->byteSizeOf(rcvr)) >= 2) * BytesPerOop)) { return interpreterProxy->primitiveFailFor(PrimErrBadReceiver); } ptr = interpreterProxy->firstIndexableField(rcvr); sizeField = ptr[0]; /* Don't you dare to free Squeak's memory! */ addr = ptr[1]; if ((sizeField >= 0) || ((addr == 0) || (interpreterProxy->isInMemory(addr)))) { return interpreterProxy->primitiveFailFor(PrimErrInappropriate); } free((void *)addr); ptr[0] = 0; ptr[1] = 0; } /* Call a foreign function that answers a double-precision floating-point result in %f0 according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> with: firstArg <Alien | Integer> ... with: lastArg <Alien | Integer> ^<Alien> <primitive: 'primCallOutDoubleReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primCallOutDoubleReturn(void) { sqInt errCode; sqInt mac; sqInt result; mac = interpreterProxy->methodArgumentCount(); errCode = callIA32DoubleReturn(interpreterProxy->getStackPointer() - mac + 2, /* arg vec */ mac - 1 /* nargs */, mac /* funcOffset*/, mac - 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(mac - 1); interpreterProxy->popthenPush(mac + 1, result); } /* Call a foreign function that answers a single-precision floating-point result in %f0 according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> with: firstArg <Alien | Integer> ... with: lastArg <Alien | Integer> ^<Alien> <primitive: 'primCallOutFloatReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primCallOutFloatReturn(void) { sqInt errCode; sqInt mac; sqInt result; mac = interpreterProxy->methodArgumentCount(); errCode = callIA32FloatReturn(interpreterProxy->getStackPointer() - mac + 2, /* arg vec */ mac - 1 /* nargs */, mac /* funcOffset*/, mac - 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(mac - 1); interpreterProxy->popthenPush(mac + 1, result); } /* Call a foreign function that answers an integral result in %eax (and possibly %edx) according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> with: firstArg <Alien | Integer> ... with: lastArg <Alien | Integer> ^<Alien> <primitive: 'primCallOutIntegralReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primCallOutIntegralReturn(void) { sqInt errCode; sqInt mac; sqInt result; mac = interpreterProxy->methodArgumentCount(); errCode = callIA32IntegralReturn(interpreterProxy->getStackPointer() - mac + 2, /* arg vec */ mac - 1 /* nargs */, mac /* funcOffset*/, mac - 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(mac - 1); interpreterProxy->popthenPush(mac + 1, result); } /* calloc (malloc + zero-fill) arg bytes. */ /* primCalloc: byteSize <Integer> ^<Integer> <primitive: 'primCalloc' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primCalloc(void) { sqInt addr; long byteSize; byteSize = interpreterProxy->stackIntegerValue(0); if ((interpreterProxy->failed()) || (byteSize <= 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } addr = (sqInt)calloc(1,byteSize); if (addr == 0) { return interpreterProxy->primitiveFailFor(PrimErrNoCMemory); } interpreterProxy->popthenPush(2, interpreterProxy->positive32BitIntegerFor(addr)); } /* Answer the 64-bit double starting at the given byte offset (little endian). */ /* <Alien> doubleAt: index <Integer> ^<Float> <primitive: 'primDoubleAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primDoubleAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; double floatValue; sqInt rcvr; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; ((long *)(&floatValue))[0] = ((long *)addr)[0]; ((long *)(&floatValue))[1] = ((long *)addr)[1]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Store a double into 64 bits starting at the given byte offset (little endian). */ /* <Alien> doubleAt: index <Integer> put: value <Float | Integer> ^<Float | Integer> <primitive: 'primDoubleAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primDoubleAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; double floatValue; sqInt rcvr; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); if ((valueOop & 1)) { floatValue = ((double) ((valueOop >> 1))); } else { floatValue = ((double) (interpreterProxy->floatValueOf(valueOop))); } byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; ((int*)addr)[0] = ((int*)(&floatValue))[0]; ((int*)addr)[1] = ((int*)(&floatValue))[1]; interpreterProxy->popthenPush(3, valueOop); } /* Answer the 32-bit float starting at the given byte offset (little endian). */ /* <Alien> floatAt: index <Integer> ^<Float> <primitive: 'primFloatAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primFloatAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; float floatValue; sqInt rcvr; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; ((long *)(&floatValue))[0] = ((long *)addr)[0]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Store a float into 32 bits starting at the given byte offset (little endian). */ /* <Alien> floatAt: index <Integer> put: value <Float | Integer> ^<Float | Integer> <primitive: 'primFloatAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primFloatAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; float floatValue; sqInt rcvr; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); if ((valueOop & 1)) { floatValue = ((double) ((valueOop >> 1))); } else { floatValue = ((double) (interpreterProxy->floatValueOf(valueOop))); } byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; ((long *)addr)[0] = ((long *)(&floatValue))[0]; interpreterProxy->popthenPush(3, valueOop); } /* Free the memory referenced by the argument, an integer. */ /* <Anywhere> primFree: address <Integer> <primitive: 'primFree' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primFree(void) { sqInt addr; addr = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if ((addr == 0) || (interpreterProxy->isInMemory(addr))) { return interpreterProxy->primitiveFailFor(PrimErrInappropriate); } free((void *)addr); interpreterProxy->pop(1); } /* Answer the address of the int inIOProcessEvents flag. This can be used to disable invocation of ioProcessEvents and is for backward-compatibility. Please use the core VM primitiveEventProcessingControl in new code. */ EXPORT(sqInt) primInIOProcessEventsFlagAddress(void) { sqInt address; { extern int inIOProcessEvents; address = (sqInt)&inIOProcessEvents; } interpreterProxy->popthenPush(1, interpreterProxy->positive32BitIntegerFor(address)); } /* Attempt to find the address of a symbol in a loaded library. The primitive can have a signature either of the form: <Anywhere> primInLibrary: libraryHandle <Alien> findSymbol: symbolName <String> ^<Integer> <primitive: 'primInLibraryFindSymbol' error: errorCode module: 'IA32ABI'> or: libraryHandle <Alien> primFindSymbol: symbolName <String> ^<Integer> <primitive: 'primInLibraryFindSymbol' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primInLibraryFindSymbol(void) { sqInt address; sqInt functionName; sqInt libraryProxy; functionName = interpreterProxy->stackValue(0); libraryProxy = interpreterProxy->stackValue(1); if (!((interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(libraryProxy), interpreterProxy->classAlien())) && ((((interpreterProxy->byteSizeOf(libraryProxy)) >= 2) * BytesPerOop) && (interpreterProxy->isBytes(functionName))))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } address = interpreterProxy->ioLoadSymbolOfLengthFromModule(((sqInt) (interpreterProxy->firstIndexableField(functionName))), interpreterProxy->byteSizeOf(functionName), longAt((libraryProxy + BaseHeaderSize) + BytesPerOop)); if ((interpreterProxy->failed()) || (address == 0)) { return interpreterProxy->primitiveFailFor(PrimErrNotFound); } interpreterProxy->popthenPush((interpreterProxy->methodArgumentCount()) + 1, interpreterProxy->positive32BitIntegerFor(address)); } /* Attempt to load a library of the given name. The primitive will have a signature of the form: <Anywhere> primLoadLibrary: libraryName <String> ^<Integer> <primitive: 'primLoadLibrary' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primLoadLibrary(void) { sqInt libraryHandle; sqInt libraryName; libraryName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(libraryName))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } libraryHandle = interpreterProxy->ioLoadModuleOfLength(((sqInt) (interpreterProxy->firstIndexableField(libraryName))), interpreterProxy->byteSizeOf(libraryName)); if (libraryHandle == 0) { return interpreterProxy->primitiveFailFor(PrimErrNotFound); } interpreterProxy->popthenPush(2, interpreterProxy->positive32BitIntegerFor(libraryHandle)); } /* Malloc arg bytes. */ /* primMalloc: byteSize <Integer> <^Integer> <primitive: 'primMalloc' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primMalloc(void) { sqInt addr; long byteSize; byteSize = interpreterProxy->stackIntegerValue(0); if ((interpreterProxy->failed()) || (byteSize <= 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } addr = (sqInt)malloc(byteSize); if (addr == 0) { return interpreterProxy->primitiveFailFor(PrimErrNoCMemory); } interpreterProxy->popthenPush(2, interpreterProxy->positive32BitIntegerFor(addr)); } /* Return a result from a callback to the callback's callee. The primitive has a signature of the form: result <VMCallbackContext32/64> primReturnAs: returnTypeCode <Integer> FromContext: callbackContext <Context> <primitive: 'primReturnAsFromContextThrough' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primReturnAsFromContextThrough(void) { if (!(interpreterProxy->returnAsThroughCallbackContext(interpreterProxy->stackValue(1), ((VMCallbackContext *) (startOfData(interpreterProxy->stackValue(2)))), interpreterProxy->stackValue(0)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } } /* Return a result from a callback to the callback's callee. The primitive has a signature of the form: result <FFICallbackResult> primReturnFromContext: callbackContext <Context> through: jmpBuf <Integer> <primitive: 'primReturnFromContextThrough' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primReturnFromContextThrough(void) { VMCallbackContext *vmCallbackContext; VMCallbackReturnValue *vmCallbackReturnValue; vmCallbackReturnValue = ((VMCallbackReturnValue *) (startOfData(interpreterProxy->stackValue(2)))); vmCallbackContext = ((VMCallbackContext *) (interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)))); if ((interpreterProxy->failed()) || (vmCallbackContext == 0)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!(interpreterProxy->reestablishContextPriorToCallback(interpreterProxy->stackValue(1)))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } memcpy((&((vmCallbackContext->rvs))), (&((vmCallbackReturnValue->crvrvs))), sizeof((vmCallbackContext->rvs))); longjmp((vmCallbackContext->trampoline), ((vmCallbackReturnValue->type)) + 1); } /* Answer the signed 8-bit integer starting at the given byte offset (little endian). */ /* <Alien> unsignedByteAt: index <Integer> ^<Integer> <primitive: 'primSignedByteAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedByteAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; signed char value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 1) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = byteAt(addr); valueOop = interpreterProxy->signed32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store a signed integer into 8 bits starting at the given byte offset (little endian). */ /* <Alien> signedByteAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primSignedByteAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedByteAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->signed32BitValueOf(valueOop); if ((interpreterProxy->failed()) || ((value < -128) || (value > 127))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 1) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; byteAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Answer the signed 32-bit integer starting at the given byte offset (little endian). */ /* <Alien> signedLongAt: index <Integer> ^<Integer> <primitive: 'primSignedLongAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedLongAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = longAt(addr); valueOop = interpreterProxy->signed32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store a signed integer into 32 bits starting at the given byte offset (little endian). */ /* <Alien> signedLongAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primSignedLongAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedLongAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->signed32BitValueOf(valueOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; longAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Answer the signed 64-bit integer starting at the given byte offset (little endian). */ /* <Alien> signedLongLongAt: index <Integer> ^<Integer> <primitive: 'primSignedLongLongAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedLongLongAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; long long signedlonglongvalue; long long *signedlonglongvaluePtr; sqInt valueOop; signedlonglongvaluePtr = 0; ; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; signedlonglongvaluePtr = ((long long*) addr); signedlonglongvalue = *signedlonglongvaluePtr; valueOop = interpreterProxy->signed64BitIntegerFor(signedlonglongvalue); return interpreterProxy->popthenPush(2, valueOop); } /* Store a signed integer into 64 bits starting at the given byte offset (little endian). */ /* <Alien> signedLongLongAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primSignedLongLongAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedLongLongAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; long long signedlonglongvalue; long long *signedlonglongvaluePtr; sqInt valueOop; signedlonglongvaluePtr = 0; ; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); signedlonglongvalue = interpreterProxy->signed64BitValueOf(valueOop); ; if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; signedlonglongvaluePtr = ((long long*) addr); *signedlonglongvaluePtr = signedlonglongvalue; return interpreterProxy->popthenPush(3, valueOop); } /* Answer the signed 32-bit integer starting at the given byte offset (little endian). */ /* <Alien> signedShortAt: index <Integer> ^<Integer> <primitive: 'primSignedShortAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedShortAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; short value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 2) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = shortAt(addr); valueOop = interpreterProxy->signed32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store a signed integer into 16 bits starting at the given byte offset (little endian). */ /* <Alien> signedShortAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primSignedShortAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSignedShortAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->signed32BitValueOf(valueOop); if ((interpreterProxy->failed()) || ((value < -32768) || (value > 32767))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 2) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; shortAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Answer the signed 32-bit integer comprising the size field (the first 32-bit field). */ /* <Alien> primSizeField ^<Integer> <primitive: 'primSizeField' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSizeField(void) { sqInt rcvr; sqInt value; sqInt valueOop; rcvr = interpreterProxy->stackValue(0); value = longAt(rcvr + BaseHeaderSize); valueOop = interpreterProxy->signed32BitIntegerFor(value); return interpreterProxy->popthenPush(1, valueOop); } /* Store a signed integer into the size field (the first 32 bit field; little endian). */ /* <Alien> sizeFieldPut: value <Integer> ^<Integer> <primitive: 'primSizeFieldPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primSizeFieldPut(void) { sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); rcvr = interpreterProxy->stackValue(1); value = interpreterProxy->signed32BitValueOf(valueOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } longAtput(rcvr + BaseHeaderSize, value); return interpreterProxy->popthenPush(2, valueOop); } /* Answer the number of non-null bytes starting at index. If there isn't a null byte before the end of the object then the result will be the number of bytes from index to the end of the object, i.e. the result will be within the bounds of the object. */ /* <Alien> primStrlenFrom: index <Integer> ^<Integer> <primitive: 'primStrlenFromStartIndex' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primStrlenFromStartIndex(void) { sqInt byteOffset; sqInt dataSize; sqInt index; sqInt limit; char *ptr; sqInt rcvr; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 1) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } limit = longAt(rcvr + BaseHeaderSize); ptr = ((char *) (((limit > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset)); if (limit == 0) { index = strlen(ptr); } else { limit = abs(limit); index = 0; while ((index < limit) && ((ptr[index]) != 0)) { index += 1; } } return interpreterProxy->popthenPush(2, interpreterProxy->positive32BitIntegerFor(index)); } /* Answer the number of non-null bytes starting at the byte addressed by the 4-byte pointer at index. */ /* <Alien> strlenThroughPointerAt: index <Integer> ^<Integer> <primitive: 'primStrlenThroughPointerAtIndex' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primStrlenThroughPointerAtIndex(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; char *ptr; sqInt rcvr; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; ptr = ((char *) (longAt(addr))); return interpreterProxy->popthenPush(2, interpreterProxy->positive32BitIntegerFor(strlen(ptr))); } /* Answer the address of the entry-point for thunk callbacks: long thunkEntry(void *thunkp, long *stackp); This could be derived via loadModule: findSymbol: etc but that would preclude making the plugin internal. */ EXPORT(sqInt) primThunkEntryAddress(void) { sqInt address; address = (sqInt)thunkEntry; interpreterProxy->popthenPush(1, interpreterProxy->positive32BitIntegerFor(address)); } /* Answer the unsigned 8-bit integer starting at the given byte offset (little endian). */ /* <Alien> unsignedByteAt: index <Integer> ^<Integer> <primitive: 'primUnsignedByteAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedByteAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; unsigned char value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 1) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = byteAt(addr); valueOop = interpreterProxy->positive32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store an unsigned integer into 8 bits starting at the given byte offset (little endian). */ /* <Alien> unsignedByteAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primUnsignedByteAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedByteAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->positive32BitValueOf(valueOop); if ((interpreterProxy->failed()) || (value > 255)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 1) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; byteAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Answer the unsigned 32-bit integer starting at the given byte offset (little endian). */ /* <Alien> unsignedLongAt: index <Integer> ^<Integer> <primitive: 'primUnsignedLongAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedLongAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = longAt(addr); valueOop = interpreterProxy->positive32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store an unsigned integer into 32 bits starting at the given byte offset (little endian). */ /* <Alien> unsignedLongAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primUnsignedLongAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedLongAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->positive32BitValueOf(valueOop); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 4) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; longAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Answer the unsigned 64-bit integer starting at the given byte offset (little endian). */ /* <Alien>unsignedLongLongAt: index <Integer> ^<Integer> <primitive: 'primUnsignedLongLongAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedLongLongAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; unsigned long long unsignedlonglongvalue; unsigned long long *unsignedlonglongvaluePtr; sqInt valueOop; unsignedlonglongvaluePtr = 0; ; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; unsignedlonglongvaluePtr = ((unsigned long long*) addr); unsignedlonglongvalue = *unsignedlonglongvaluePtr; valueOop = interpreterProxy->positive64BitIntegerFor(unsignedlonglongvalue); return interpreterProxy->popthenPush(2, valueOop); } /* Store a signed integer into 64 bits starting at the given byte offset (little endian). */ /* <Alien> unsignedLongLongAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primUnSignedLongLongAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedLongLongAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; unsigned long long unsignedlonglongvalue; unsigned long long *unsignedlonglongvaluePtr; sqInt valueOop; unsignedlonglongvaluePtr = 0; ; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); unsignedlonglongvalue = interpreterProxy->positive64BitValueOf(valueOop); ; if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 8) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; unsignedlonglongvaluePtr = ((unsigned long long*) addr); *unsignedlonglongvaluePtr = unsignedlonglongvalue; return interpreterProxy->popthenPush(3, valueOop); } /* Answer the unsigned 16-bit integer starting at the given byte offset (little endian). */ /* <Alien> unsignedShortAt: index <Integer> ^<Integer> <primitive: 'primUnsignedShortAt' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedShortAt(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; unsigned short value; sqInt valueOop; byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(0)) - 1; rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 2) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; value = shortAt(addr); valueOop = interpreterProxy->positive32BitIntegerFor(value); return interpreterProxy->popthenPush(2, valueOop); } /* Store an unsigned integer into 16 bits starting at the given byte offset (little endian). */ /* <Alien> unsignedShortAt: index <Integer> put: value <Integer> ^<Integer> <primitive: 'primUnsignedShortAtPut' error: errorCode module: 'IA32ABI'> */ EXPORT(sqInt) primUnsignedShortAtPut(void) { sqInt addr; sqInt byteOffset; sqInt dataSize; sqInt rcvr; sqInt value; sqInt valueOop; valueOop = interpreterProxy->stackValue(0); byteOffset = (interpreterProxy->stackPositiveMachineIntegerValue(1)) - 1; rcvr = interpreterProxy->stackObjectValue(2); value = interpreterProxy->positive32BitValueOf(valueOop); if ((interpreterProxy->failed()) || (value > 65535)) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } if (!((((dataSize = longAt(rcvr + BaseHeaderSize))) == 0) || (((((usqInt)byteOffset)) + 2) <= (abs(dataSize))))) { return interpreterProxy->primitiveFailFor(PrimErrBadIndex); } addr = (((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop))) + byteOffset; shortAtput(addr, value); return interpreterProxy->popthenPush(3, valueOop); } /* Call a foreign function that answers a double-precision floating-point result in %f0 according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> withArguments: args <Array of: Alien | Integer> ^<Alien> <primitive: 'primVarArgsCallOutDoubleReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primVarArgsCallOutDoubleReturn(void) { sqInt array; sqInt errCode; sqInt result; array = interpreterProxy->stackValue(0); if (!(interpreterProxy->isArray(array))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } errCode = callIA32DoubleReturn(interpreterProxy->firstIndexableField(array), /* arg vec */ interpreterProxy->stSizeOf(array) /* nargs */, 2 /* funcOffset*/, 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(1); interpreterProxy->popthenPush(3, result); } /* Call a foreign function that answers a single-precision floating-point result in %f0 according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> withArguments: args <Array of: Alien | Integer> ^<Alien> <primitive: 'primVarArgsCallOutFloatReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primVarArgsCallOutFloatReturn(void) { sqInt array; sqInt errCode; sqInt result; array = interpreterProxy->stackValue(0); if (!(interpreterProxy->isArray(array))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } errCode = callIA32FloatReturn(interpreterProxy->firstIndexableField(array), /* arg vec */ interpreterProxy->stSizeOf(array) /* nargs */, 2 /* funcOffset*/, 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(1); interpreterProxy->popthenPush(3, result); } /* Call a foreign function that answers an integral result in %eax (and possibly %edx) according to IA32-ish ABI rules. The primitive will have a signature of the form functionAddress <Alien> primFFICallResult: result <Alien|Object> withArguments: args <Array of: Alien | Integer> ^<Alien> <primitive: 'primVarArgsCallOutIntegralReturn' error: errorCode module: 'IA32ABI'>. Answer result. If result is an Alien the value answered by the call will be assigned to result. */ EXPORT(sqInt) primVarArgsCallOutIntegralReturn(void) { sqInt array; sqInt errCode; sqInt result; array = interpreterProxy->stackValue(0); if (!(interpreterProxy->isArray(array))) { return interpreterProxy->primitiveFailFor(PrimErrBadArgument); } errCode = callIA32IntegralReturn(interpreterProxy->firstIndexableField(array), /* arg vec */ interpreterProxy->stSizeOf(array) /* nargs */, 2 /* funcOffset*/, 1 /* resultOffset */); if (errCode != 0) { return interpreterProxy->primitiveFailFor(errCode); } result = interpreterProxy->stackValue(1); interpreterProxy->popthenPush(3, result); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Answer the first field of rcvr which is assumed to be an Alien of at least 8 bytes */ static sqInt sizeField(sqInt rcvr) { return longAt(rcvr + BaseHeaderSize); } /* <byte indexable oop> ^<Integer> */ /* Answer the start of rcvr's data, given that it is not an alien. */ static sqInt startOfByteData(sqInt rcvr) { return rcvr + BaseHeaderSize; } /* <Alien oop> ^<Integer> */ /* Answer the start of rcvr's data. For direct aliens this is the address of the second field. For indirect and pointer aliens it is what the second field points to. */ static sqInt startOfData(sqInt rcvr) { return ((longAt(rcvr + BaseHeaderSize)) > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop)); } /* <Alien oop> */ /* <Integer> ^<Integer> */ /* Answer the start of rcvr's data. For direct aliens this is the address of the second field. For indirect and pointer aliens it is what the second field points to. */ static sqInt startOfDatawithSize(sqInt rcvr, sqInt sizeField) { return (sizeField > 0 ? (rcvr + BaseHeaderSize) + BytesPerOop : longAt((rcvr + BaseHeaderSize) + BytesPerOop)); } #ifdef SQUEAK_BUILTIN_PLUGIN void* IA32ABI_exports[][3] = { {"IA32ABI", "getModuleName", (void*)getModuleName}, {"IA32ABI", "isAlien", (void*)isAlien}, {"IA32ABI", "primAddressField", (void*)primAddressField}, {"IA32ABI", "primAddressFieldPut", (void*)primAddressFieldPut}, {"IA32ABI", "primAlienReplace", (void*)primAlienReplace}, {"IA32ABI", "primAllocateExecutablePage", (void*)primAllocateExecutablePage}, {"IA32ABI", "primBoxedFree", (void*)primBoxedFree}, {"IA32ABI", "primCallOutDoubleReturn", (void*)primCallOutDoubleReturn}, {"IA32ABI", "primCallOutFloatReturn", (void*)primCallOutFloatReturn}, {"IA32ABI", "primCallOutIntegralReturn", (void*)primCallOutIntegralReturn}, {"IA32ABI", "primCalloc", (void*)primCalloc}, {"IA32ABI", "primDoubleAt", (void*)primDoubleAt}, {"IA32ABI", "primDoubleAtPut", (void*)primDoubleAtPut}, {"IA32ABI", "primFloatAt", (void*)primFloatAt}, {"IA32ABI", "primFloatAtPut", (void*)primFloatAtPut}, {"IA32ABI", "primFree", (void*)primFree}, {"IA32ABI", "primInIOProcessEventsFlagAddress", (void*)primInIOProcessEventsFlagAddress}, {"IA32ABI", "primInLibraryFindSymbol", (void*)primInLibraryFindSymbol}, {"IA32ABI", "primLoadLibrary", (void*)primLoadLibrary}, {"IA32ABI", "primMalloc", (void*)primMalloc}, {"IA32ABI", "primReturnAsFromContextThrough", (void*)primReturnAsFromContextThrough}, {"IA32ABI", "primReturnFromContextThrough", (void*)primReturnFromContextThrough}, {"IA32ABI", "primSignedByteAt", (void*)primSignedByteAt}, {"IA32ABI", "primSignedByteAtPut", (void*)primSignedByteAtPut}, {"IA32ABI", "primSignedLongAt", (void*)primSignedLongAt}, {"IA32ABI", "primSignedLongAtPut", (void*)primSignedLongAtPut}, {"IA32ABI", "primSignedLongLongAt", (void*)primSignedLongLongAt}, {"IA32ABI", "primSignedLongLongAtPut", (void*)primSignedLongLongAtPut}, {"IA32ABI", "primSignedShortAt", (void*)primSignedShortAt}, {"IA32ABI", "primSignedShortAtPut", (void*)primSignedShortAtPut}, {"IA32ABI", "primSizeField", (void*)primSizeField}, {"IA32ABI", "primSizeFieldPut", (void*)primSizeFieldPut}, {"IA32ABI", "primStrlenFromStartIndex", (void*)primStrlenFromStartIndex}, {"IA32ABI", "primStrlenThroughPointerAtIndex", (void*)primStrlenThroughPointerAtIndex}, {"IA32ABI", "primThunkEntryAddress", (void*)primThunkEntryAddress}, {"IA32ABI", "primUnsignedByteAt", (void*)primUnsignedByteAt}, {"IA32ABI", "primUnsignedByteAtPut", (void*)primUnsignedByteAtPut}, {"IA32ABI", "primUnsignedLongAt", (void*)primUnsignedLongAt}, {"IA32ABI", "primUnsignedLongAtPut", (void*)primUnsignedLongAtPut}, {"IA32ABI", "primUnsignedLongLongAt", (void*)primUnsignedLongLongAt}, {"IA32ABI", "primUnsignedLongLongAtPut", (void*)primUnsignedLongLongAtPut}, {"IA32ABI", "primUnsignedShortAt", (void*)primUnsignedShortAt}, {"IA32ABI", "primUnsignedShortAtPut", (void*)primUnsignedShortAtPut}, {"IA32ABI", "primVarArgsCallOutDoubleReturn", (void*)primVarArgsCallOutDoubleReturn}, {"IA32ABI", "primVarArgsCallOutFloatReturn", (void*)primVarArgsCallOutFloatReturn}, {"IA32ABI", "primVarArgsCallOutIntegralReturn", (void*)primVarArgsCallOutIntegralReturn}, {"IA32ABI", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/JPEGReadWriter2Plugin/JPEGReadWriter2Plugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from JPEGReadWriter2Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "JPEGReadWriter2Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "JPEGReadWriter2Plugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primImageHeight(void); EXPORT(sqInt) primImageWidth(void); EXPORT(sqInt) primJPEGCompressStructSize(void); EXPORT(sqInt) primJPEGDecompressStructSize(void); EXPORT(sqInt) primJPEGErrorMgr2StructSize(void); EXPORT(sqInt) primJPEGPluginIsPresent(void); EXPORT(sqInt) primJPEGReadHeaderfromByteArrayerrorMgr(void); EXPORT(sqInt) primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr(void); EXPORT(sqInt) primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "JPEGReadWriter2Plugin VMMaker-oscog.dtl.57 (i)" #else "JPEGReadWriter2Plugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return 1; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primImageHeight(void) { char *aJPEGDecompressStruct; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct jpeg_decompress_struct))); if (interpreterProxy->failed()) return null; ; _return_value = interpreterProxy->integerObjectOf((((j_decompress_ptr)aJPEGDecompressStruct)->image_height)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primImageWidth(void) { char *aJPEGDecompressStruct; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct jpeg_decompress_struct))); if (interpreterProxy->failed()) return null; ; _return_value = interpreterProxy->integerObjectOf((((j_decompress_ptr)aJPEGDecompressStruct)->image_width)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primJPEGCompressStructSize(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sizeof(struct jpeg_compress_struct))); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primJPEGDecompressStructSize(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sizeof(struct jpeg_decompress_struct))); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primJPEGErrorMgr2StructSize(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sizeof(struct error_mgr2))); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primJPEGPluginIsPresent(void) { sqInt _return_value; _return_value = (1? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primJPEGReadHeaderfromByteArrayerrorMgr(void) { char *aJPEGDecompressStruct; char *aJPEGErrorMgr2Struct; j_decompress_ptr pcinfo; error_ptr2 pjerr; char *source; sqInt sourceSize; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); source = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } pcinfo = null; pjerr = null; sourceSize = null; pcinfo; pjerr; sourceSize; interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(2))) >= (sizeof(struct jpeg_decompress_struct))); interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2))); if (interpreterProxy->failed()) return null; ; sourceSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(1)); pcinfo = (j_decompress_ptr)aJPEGDecompressStruct; pjerr = (error_ptr2)aJPEGErrorMgr2Struct; if (sourceSize) { pcinfo->err = jpeg_std_error(&pjerr->pub); pjerr->pub.error_exit = error_exit; if (setjmp(pjerr->setjmp_buffer)) { jpeg_destroy_decompress(pcinfo); sourceSize = 0; } if (sourceSize) { jpeg_create_decompress(pcinfo); jpeg_mem_src(pcinfo, source, sourceSize); jpeg_read_header(pcinfo, TRUE); } } ; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr(void) { char *aJPEGDecompressStruct; char *aJPEGErrorMgr2Struct; sqInt b1; sqInt b2; sqInt bOff; sqInt bOff2; JSAMPARRAY buffer; sqInt di; sqInt ditherFlag; sqInt dmi; sqInt dmo; sqInt dmv1; sqInt dmv2; sqInt form; unsigned * formBits; sqInt formBitsAsInt; sqInt formBitsSize; sqInt formDepth; sqInt formHeight; sqInt formPitch; sqInt formPix; sqInt formWidth; sqInt g1; sqInt g2; sqInt gOff; sqInt gOff2; sqInt i; sqInt j; sqInt ok; j_decompress_ptr pcinfo; sqInt pixPerWord; error_ptr2 pjerr; sqInt r1; sqInt r2; sqInt rOff; sqInt rOff2; sqInt rowStride; char *source; sqInt sourceSize; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(4))); aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(4)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(3))); source = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Form")); form = interpreterProxy->stackValue(2); ditherFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } pcinfo = null; pjerr = null; buffer = null; rowStride = null; formDepth = null; formBits = null; i = null; j = null; formPix = null; ok = null; rOff = null; gOff = null; bOff = null; rOff2 = null; gOff2 = null; bOff2 = null; sourceSize = null; r1 = null; r2 = null; g1 = null; g2 = null; b1 = null; b2 = null; dmv1 = null; dmv2 = null; di = null; dmi = null; dmo = null; pcinfo; pjerr; buffer; rowStride; formBits; formDepth; i; j; formPix; ok; rOff; gOff; bOff; rOff2; gOff2; bOff2; sourceSize; r1; r2; g1; g2; b1; b2; dmv1; dmv2; di; dmi; dmo; formBits = ((unsigned *) (interpreterProxy->fetchPointerofObject(0, form))); formBitsAsInt = interpreterProxy->fetchPointerofObject(0, form); /* Various parameter checks */ formDepth = interpreterProxy->fetchIntegerofObject(3, form); interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(4))) >= (sizeof(struct jpeg_decompress_struct))); interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2))); if (interpreterProxy->failed()) return null; ; formWidth = ((j_decompress_ptr)aJPEGDecompressStruct)->image_width; formHeight = ((j_decompress_ptr)aJPEGDecompressStruct)->image_height; pixPerWord = 32 / formDepth; formPitch = ((formWidth + (pixPerWord - 1)) / pixPerWord) * 4; formBitsSize = interpreterProxy->byteSizeOf(formBitsAsInt); interpreterProxy->success((interpreterProxy->isWordsOrBytes(formBitsAsInt)) && (formBitsSize == (formPitch * formHeight))); if (interpreterProxy->failed()) { return null; } sourceSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(3)); if (sourceSize == 0) { interpreterProxy->success(false); return null; } pcinfo = (j_decompress_ptr)aJPEGDecompressStruct; pjerr = (error_ptr2)aJPEGErrorMgr2Struct; pcinfo->err = jpeg_std_error(&pjerr->pub); pjerr->pub.error_exit = error_exit; ok = 1; if (setjmp(pjerr->setjmp_buffer)) { jpeg_destroy_decompress(pcinfo); ok = 0; } if (ok) { ok = jpeg_mem_src_newLocationOfData(pcinfo, source, sourceSize); if (ok) { /* Dither Matrix taken from Form>>orderedDither32To16, but rewritten for this method. */ int ditherMatrix1[] = { 2, 0, 14, 12, 1, 3, 13, 15 }; int ditherMatrix2[] = { 10, 8, 6, 4, 9, 11, 5, 7 }; jpeg_start_decompress(pcinfo); rowStride = pcinfo->output_width * pcinfo->output_components; if (pcinfo->out_color_components == 3) { rOff = 0; gOff = 1; bOff = 2; rOff2 = 3; gOff2 = 4; bOff2 = 5; } else { rOff = 0; gOff = 0; bOff = 0; rOff2 = 1; gOff2 = 1; bOff2 = 1; } /* Make a one-row-high sample array that will go away when done with image */ buffer = (*(pcinfo->mem)->alloc_sarray) ((j_common_ptr) pcinfo, JPOOL_IMAGE, rowStride, 1); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library state variable cinfo.output_scanline as the * loop counter, so that we dont have to keep track ourselves. */ while (pcinfo->output_scanline < pcinfo->output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if thats more convenient. */ (void) jpeg_read_scanlines(pcinfo, buffer, 1); switch (formDepth) { case 32: for(i = 0, j = 1; i < rowStride; i +=(pcinfo->out_color_components), j++) { formPix = (255 << 24) | (buffer[0][i+rOff] << 16) | (buffer[0][i+gOff] << 8) | buffer[0][i+bOff]; if (formPix == 0) formPix = 1; formBits [ ((pcinfo->output_scanline - 1) * (pcinfo->image_width)) + j ] = formPix; } break; case 16: for(i = 0, j = 1; i < rowStride; i +=(pcinfo->out_color_components*2), j++) { r1 = buffer[0][i+rOff]; r2 = buffer[0][i+rOff2]; g1 = buffer[0][i+gOff]; g2 = buffer[0][i+gOff2]; b1 = buffer[0][i+bOff]; b2 = buffer[0][i+bOff2]; if (!ditherFlag) { r1 = r1 >> 3; r2 = r2 >> 3; g1 = g1 >> 3; g2 = g2 >> 3; b1 = b1 >> 3; b2 = b2 >> 3; } else { /* Do 4x4 ordered dithering. Taken from Form>>orderedDither32To16 */ dmv1 = ditherMatrix1[ ((pcinfo->output_scanline & 3 )<< 1) | (j&1) ]; dmv2 = ditherMatrix2[ ((pcinfo->output_scanline & 3 )<< 1) | (j&1) ]; di = (r1 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv1 < dmi) { r1 = dmo+1; } else { r1 = dmo; }; di = (g1 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv1 < dmi) { g1 = dmo+1; } else { g1 = dmo; }; di = (b1 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv1 < dmi) { b1 = dmo+1; } else { b1 = dmo; }; di = (r2 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv2 < dmi) { r2 = dmo+1; } else { r2 = dmo; }; di = (g2 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv2 < dmi) { g2 = dmo+1; } else { g2 = dmo; }; di = (b2 * 496) >> 8; dmi = di & 15; dmo = di >> 4; if(dmv2 < dmi) { b2 = dmo+1; } else { b2 = dmo; }; } formPix = (r1 << 10) | (g1 << 5) | b1; if (!formPix) formPix = 1; formPix = (formPix << 16) | (r2 << 10) | (g2 << 5) | b2; if (!(formPix & 65535)) formPix = formPix | 1; formBits [ ((pcinfo->output_scanline - 1) * (pcinfo->image_width)) / 2 + j ] = formPix; } break; } } jpeg_finish_decompress(pcinfo); } jpeg_destroy_decompress(pcinfo); } ; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); return null; } EXPORT(sqInt) primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr(void) { char *aJPEGCompressStruct; char *aJPEGErrorMgr2Struct; JSAMPARRAY buffer; char *destination; unsigned int destinationSize; sqInt form; unsigned * formBits; sqInt formBitsAsInt; sqInt formBitsSize; sqInt formDepth; sqInt formHeight; sqInt formPitch; sqInt formPix; sqInt formWidth; sqInt i; sqInt j; j_compress_ptr pcinfo; sqInt pixPerWord; error_ptr2 pjerr; sqInt progressiveFlag; sqInt quality; sqInt rowStride; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(5))); aJPEGCompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(5)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(4))); destination = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(4)))); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(3), "Form")); form = interpreterProxy->stackValue(3); quality = interpreterProxy->stackIntegerValue(2); progressiveFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } pcinfo = null; pjerr = null; buffer = null; rowStride = null; formBits = null; formWidth = null; formHeight = null; formDepth = null; i = null; j = null; formPix = null; destinationSize = null; pcinfo; pjerr; buffer; rowStride; formBits; formWidth; formHeight; formDepth; i; j; formPix; destinationSize; formBits = ((unsigned *) (interpreterProxy->fetchPointerofObject(0, form))); formBitsAsInt = interpreterProxy->fetchPointerofObject(0, form); formWidth = interpreterProxy->fetchIntegerofObject(1, form); formHeight = interpreterProxy->fetchIntegerofObject(2, form); /* Various parameter checks */ formDepth = interpreterProxy->fetchIntegerofObject(3, form); interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(5))) >= (sizeof(struct jpeg_compress_struct))); interpreterProxy->success ((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2))); if (interpreterProxy->failed()) return null; ; pixPerWord = 32 / formDepth; formPitch = ((formWidth + (pixPerWord - 1)) / pixPerWord) * 4; formBitsSize = interpreterProxy->byteSizeOf(formBitsAsInt); interpreterProxy->success((interpreterProxy->isWordsOrBytes(formBitsAsInt)) && (formBitsSize == (formPitch * formHeight))); if (interpreterProxy->failed()) { return null; } destinationSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(4)); pcinfo = (j_compress_ptr)aJPEGCompressStruct; pjerr = (error_ptr2)aJPEGErrorMgr2Struct; if (destinationSize) { pcinfo->err = jpeg_std_error(&pjerr->pub); pjerr->pub.error_exit = error_exit; if (setjmp(pjerr->setjmp_buffer)) { jpeg_destroy_compress(pcinfo); destinationSize = 0; } if (destinationSize) { jpeg_create_compress(pcinfo); jpeg_mem_dest(pcinfo, destination, &destinationSize); pcinfo->image_width = formWidth; pcinfo->image_height = formHeight; pcinfo->input_components = 3; pcinfo->in_color_space = JCS_RGB; jpeg_set_defaults(pcinfo); if (quality > 0) jpeg_set_quality (pcinfo, quality, 1); if (progressiveFlag) jpeg_simple_progression(pcinfo); jpeg_start_compress(pcinfo, TRUE); rowStride = formWidth * 3; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*(pcinfo->mem)->alloc_sarray) ((j_common_ptr) pcinfo, JPOOL_IMAGE, rowStride, 1); while (pcinfo->next_scanline < pcinfo->image_height) { switch (formDepth) { case 32: for(i = 0, j = 1; i < rowStride; i +=3, j++) { formPix = formBits [ ((pcinfo->next_scanline) * formWidth) + j ]; buffer[0][i] = (formPix >> 16) & 255; buffer[0][i+1] = (formPix >> 8) & 255; buffer[0][i+2] = formPix & 255; } break; case 16: for(i = 0, j = 1; i < rowStride; i +=6, j++) { formPix = formBits [ ((pcinfo->next_scanline) * formWidth) / 2 + j ]; buffer[0][i] = (formPix >> 23) & 248; buffer[0][i+1] = (formPix >> 18) & 248; buffer[0][i+2] = (formPix >> 13) & 248; buffer[0][i+3] = (formPix >> 7) & 248; buffer[0][i+4] = (formPix >> 2) & 248; buffer[0][i+5] = (formPix << 3) & 248; } break; } (void) jpeg_write_scanlines(pcinfo, buffer, 1); } jpeg_finish_compress(pcinfo); jpeg_destroy_compress(pcinfo); } } ; _return_value = interpreterProxy->integerObjectOf((destinationSize)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(7, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return 1; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* JPEGReadWriter2Plugin_exports[][3] = { {"JPEGReadWriter2Plugin", "getModuleName", (void*)getModuleName}, {"JPEGReadWriter2Plugin", "initialiseModule", (void*)initialiseModule}, {"JPEGReadWriter2Plugin", "primImageHeight", (void*)primImageHeight}, {"JPEGReadWriter2Plugin", "primImageWidth", (void*)primImageWidth}, {"JPEGReadWriter2Plugin", "primJPEGCompressStructSize", (void*)primJPEGCompressStructSize}, {"JPEGReadWriter2Plugin", "primJPEGDecompressStructSize", (void*)primJPEGDecompressStructSize}, {"JPEGReadWriter2Plugin", "primJPEGErrorMgr2StructSize", (void*)primJPEGErrorMgr2StructSize}, {"JPEGReadWriter2Plugin", "primJPEGPluginIsPresent", (void*)primJPEGPluginIsPresent}, {"JPEGReadWriter2Plugin", "primJPEGReadHeaderfromByteArrayerrorMgr", (void*)primJPEGReadHeaderfromByteArrayerrorMgr}, {"JPEGReadWriter2Plugin", "primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr", (void*)primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr}, {"JPEGReadWriter2Plugin", "primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr", (void*)primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr}, {"JPEGReadWriter2Plugin", "setInterpreter", (void*)setInterpreter}, {"JPEGReadWriter2Plugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/JPEGReaderPlugin/JPEGReaderPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from JPEGReaderPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "JPEGReaderPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ #define BlockWidthIndex 5 #define BlueIndex 2 #define ConstBits 13 #define CurrentXIndex 0 #define CurrentYIndex 1 #define DCTSize 8 #define DCTSize2 64 #define FIXn0n298631336 2446 #define FIXn0n34414 22554 #define FIXn0n390180644 0xC7C #define FIXn0n541196100 4433 #define FIXn0n71414 46802 #define FIXn0n765366865 6270 #define FIXn0n899976223 7373 #define FIXn1n175875602 9633 #define FIXn1n40200 91881 #define FIXn1n501321110 12299 #define FIXn1n77200 116130 #define FIXn1n847759065 15137 #define FIXn1n961570560 16069 #define FIXn2n053119869 16819 #define FIXn2n562915447 20995 #define FIXn3n072711026 25172 #define GreenIndex 1 #define HScaleIndex 2 #define MaxBits 16 #define MaxMCUBlocks 128 #define MaxSample 255 #define MCUBlockIndex 4 #define MCUWidthIndex 8 #define MinComponentSize 11 #define Pass1Bits 2 #define Pass1Div 0x800 #define Pass2Div 0x40000 #define PriorDCValueIndex 10 #define RedIndex 0 #define SampleOffset 127 #define VScaleIndex 3 /*** Function Prototypes ***/ static sqInt cbColorComponentFrom(sqInt oop); static sqInt colorComponentBlocksfrom(int **blocks, sqInt oop); static sqInt colorComponentfrom(int *aColorComponent, sqInt oop); static sqInt colorConvertGrayscaleMCU(void); static sqInt colorConvertMCU(void); static sqInt crColorComponentFrom(sqInt oop); static sqInt decodeBlockIntocomponent(int *anArray, int *aColorComponent); static sqInt fillBuffer(void); static sqInt getBits(sqInt requestedBits); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt idctBlockIntqt(int *anArray, int *qt); static sqInt jpegDecodeValueFromsize(int *table, sqInt tableSize); static sqInt loadJPEGStreamFrom(sqInt streamOop); static sqInt msg(char *s); static sqInt nextSampleCb(void); static sqInt nextSampleCr(void); static sqInt nextSampleFromblocks(int *aComponent, int **aBlockArray); static sqInt nextSampleY(void); EXPORT(sqInt) primitiveColorConvertGrayscaleMCU(void); EXPORT(sqInt) primitiveColorConvertMCU(void); EXPORT(sqInt) primitiveDecodeMCU(void); EXPORT(sqInt) primitiveIdctInt(void); static sqInt scaleAndSignExtendinFieldWidth(sqInt aNumber, sqInt w); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt stInit(void); static sqInt storeJPEGStreamOn(sqInt streamOop); static sqInt yColorComponentFrom(sqInt oop); /*** Variables ***/ static int *acTable; static sqInt acTableSize; static int *cbBlocks[128]; static int cbComponent[11]; static sqInt cbSampleStream; static int *crBlocks[128]; static int crComponent[11]; static sqInt crSampleStream; static int *dcTable; static sqInt dcTableSize; static sqInt ditherMask; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static int *jpegBits; static sqInt jpegBitsSize; static int jpegNaturalOrder[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; static sqInt jsBitBuffer; static sqInt jsBitCount; static unsigned char *jsCollection; static sqInt jsPosition; static sqInt jsReadLimit; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "JPEGReaderPlugin VMMaker-oscog.dtl.57 (i)" #else "JPEGReaderPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static int *residuals; static int *yBlocks[128]; static int yComponent[11]; static sqInt ySampleStream; static sqInt cbColorComponentFrom(sqInt oop) { return (colorComponentfrom(cbComponent, oop)) && (colorComponentBlocksfrom(cbBlocks, oop)); } static sqInt colorComponentBlocksfrom(int **blocks, sqInt oop) { sqInt arrayOop; sqInt blockOop; sqInt i; sqInt max; if ((oop & 1)) { return 0; } if (!(interpreterProxy->isPointers(oop))) { return 0; } if ((interpreterProxy->slotSizeOf(oop)) < MinComponentSize) { return 0; } arrayOop = interpreterProxy->fetchPointerofObject(MCUBlockIndex, oop); if ((arrayOop & 1)) { return 0; } if (!(interpreterProxy->isPointers(arrayOop))) { return 0; } max = interpreterProxy->slotSizeOf(arrayOop); if (max > MaxMCUBlocks) { return 0; } for (i = 0; i <= (max - 1); i += 1) { blockOop = interpreterProxy->fetchPointerofObject(i, arrayOop); if ((blockOop & 1)) { return 0; } if (!(interpreterProxy->isWords(blockOop))) { return 0; } if (!((interpreterProxy->slotSizeOf(blockOop)) == DCTSize2)) { return 0; } blocks[i] = (interpreterProxy->firstIndexableField(blockOop)); } return !(interpreterProxy->failed()); } static sqInt colorComponentfrom(int *aColorComponent, sqInt oop) { if ((oop & 1)) { return 0; } if (!(interpreterProxy->isPointers(oop))) { return 0; } if ((interpreterProxy->slotSizeOf(oop)) < MinComponentSize) { return 0; } aColorComponent[CurrentXIndex] = (interpreterProxy->fetchIntegerofObject(CurrentXIndex, oop)); aColorComponent[CurrentYIndex] = (interpreterProxy->fetchIntegerofObject(CurrentYIndex, oop)); aColorComponent[HScaleIndex] = (interpreterProxy->fetchIntegerofObject(HScaleIndex, oop)); aColorComponent[VScaleIndex] = (interpreterProxy->fetchIntegerofObject(VScaleIndex, oop)); aColorComponent[BlockWidthIndex] = (interpreterProxy->fetchIntegerofObject(BlockWidthIndex, oop)); aColorComponent[MCUWidthIndex] = (interpreterProxy->fetchIntegerofObject(MCUWidthIndex, oop)); aColorComponent[PriorDCValueIndex] = (interpreterProxy->fetchIntegerofObject(PriorDCValueIndex, oop)); return !(interpreterProxy->failed()); } static sqInt colorConvertGrayscaleMCU(void) { sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt i; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; sqInt y; yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = 0; for (i = 0; i <= (jpegBitsSize - 1); i += 1) { /* begin nextSampleY */ dx = curX = yComponent[CurrentXIndex]; dy = yComponent[CurrentYIndex]; sx = yComponent[HScaleIndex]; sy = yComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (yBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((yComponent[MCUWidthIndex]) * 8)) { yComponent[CurrentXIndex] = curX; } else { yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1); } y = sample; y += residuals[GreenIndex]; y = ((y < MaxSample) ? y : MaxSample); residuals[GreenIndex] = (y & ditherMask); y = y & (MaxSample - ditherMask); y = ((y < 1) ? 1 : y); jpegBits[i] = (((4278190080UL + (y << 16)) + (y << 8)) + y); } } static sqInt colorConvertMCU(void) { sqInt blockIndex; sqInt blockIndex1; sqInt blockIndex2; sqInt blue; sqInt cb; sqInt cr; sqInt curX; sqInt curX1; sqInt curX2; sqInt dx; sqInt dx1; sqInt dx2; sqInt dy; sqInt dy1; sqInt dy2; sqInt green; sqInt i; sqInt red; sqInt sample; sqInt sample1; sqInt sample2; sqInt sampleIndex; sqInt sampleIndex1; sqInt sampleIndex2; sqInt sx; sqInt sx1; sqInt sx2; sqInt sy; sqInt sy1; sqInt sy2; sqInt y; yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = 0; cbComponent[CurrentXIndex] = 0; cbComponent[CurrentYIndex] = 0; crComponent[CurrentXIndex] = 0; crComponent[CurrentYIndex] = 0; for (i = 0; i <= (jpegBitsSize - 1); i += 1) { /* begin nextSampleY */ dx = curX = yComponent[CurrentXIndex]; dy = yComponent[CurrentYIndex]; sx = yComponent[HScaleIndex]; sy = yComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (yBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((yComponent[MCUWidthIndex]) * 8)) { yComponent[CurrentXIndex] = curX; } else { yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1); } y = sample; /* begin nextSampleCb */ dx1 = curX1 = cbComponent[CurrentXIndex]; dy1 = cbComponent[CurrentYIndex]; sx1 = cbComponent[HScaleIndex]; sy1 = cbComponent[VScaleIndex]; if (!((sx1 == 0) && (sy1 == 0))) { dx1 = dx1 / sx1; dy1 = dy1 / sy1; } blockIndex1 = ((((usqInt) dy1 >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx1 >> 3)); sampleIndex1 = (((usqInt) (dy1 & 7) << 3)) + (dx1 & 7); sample1 = (cbBlocks[blockIndex1])[sampleIndex1]; curX1 += 1; if (curX1 < ((cbComponent[MCUWidthIndex]) * 8)) { cbComponent[CurrentXIndex] = curX1; } else { cbComponent[CurrentXIndex] = 0; cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1); } cb = sample1; cb -= SampleOffset; /* begin nextSampleCr */ dx2 = curX2 = crComponent[CurrentXIndex]; dy2 = crComponent[CurrentYIndex]; sx2 = crComponent[HScaleIndex]; sy2 = crComponent[VScaleIndex]; if (!((sx2 == 0) && (sy2 == 0))) { dx2 = dx2 / sx2; dy2 = dy2 / sy2; } blockIndex2 = ((((usqInt) dy2 >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx2 >> 3)); sampleIndex2 = (((usqInt) (dy2 & 7) << 3)) + (dx2 & 7); sample2 = (crBlocks[blockIndex2])[sampleIndex2]; curX2 += 1; if (curX2 < ((crComponent[MCUWidthIndex]) * 8)) { crComponent[CurrentXIndex] = curX2; } else { crComponent[CurrentXIndex] = 0; crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1); } cr = sample2; cr -= SampleOffset; red = (y + (((sqInt) (FIXn1n40200 * cr) >> 16))) + (residuals[RedIndex]); red = ((red < MaxSample) ? red : MaxSample); red = ((red < 0) ? 0 : red); residuals[RedIndex] = (red & ditherMask); red = red & (MaxSample - ditherMask); red = ((red < 1) ? 1 : red); green = ((y - (((sqInt) (FIXn0n34414 * cb) >> 16))) - (((sqInt) (FIXn0n71414 * cr) >> 16))) + (residuals[GreenIndex]); green = ((green < MaxSample) ? green : MaxSample); green = ((green < 0) ? 0 : green); residuals[GreenIndex] = (green & ditherMask); green = green & (MaxSample - ditherMask); green = ((green < 1) ? 1 : green); blue = (y + (((sqInt) (FIXn1n77200 * cb) >> 16))) + (residuals[BlueIndex]); blue = ((blue < MaxSample) ? blue : MaxSample); blue = ((blue < 0) ? 0 : blue); residuals[BlueIndex] = (blue & ditherMask); blue = blue & (MaxSample - ditherMask); blue = ((blue < 1) ? 1 : blue); jpegBits[i] = (((4278190080UL + (((usqInt) red << 16))) + (((usqInt) green << 8))) + blue); } } static sqInt crColorComponentFrom(sqInt oop) { return (colorComponentfrom(crComponent, oop)) && (colorComponentBlocksfrom(crBlocks, oop)); } static sqInt decodeBlockIntocomponent(int *anArray, int *aColorComponent) { sqInt bits; sqInt byte; sqInt i; sqInt index; sqInt zeroCount; byte = jpegDecodeValueFromsize(dcTable, dcTableSize); if (byte < 0) { return interpreterProxy->primitiveFail(); } if (byte != 0) { bits = getBits(byte); /* begin scaleAndSignExtend:inFieldWidth: */ if (bits < ((((byte - 1) < 0) ? ((usqInt) 1 >> -(byte - 1)) : ((usqInt) 1 << (byte - 1))))) { byte = (bits - (((byte < 0) ? ((usqInt) 1 >> -byte) : ((usqInt) 1 << byte)))) + 1; goto l1; } else { byte = bits; goto l1; } l1: /* end scaleAndSignExtend:inFieldWidth: */; } byte = aColorComponent[PriorDCValueIndex] = ((aColorComponent[PriorDCValueIndex]) + byte); anArray[0] = byte; for (i = 1; i <= (DCTSize2 - 1); i += 1) { anArray[i] = 0; } index = 1; while (index < DCTSize2) { byte = jpegDecodeValueFromsize(acTable, acTableSize); if (byte < 0) { return interpreterProxy->primitiveFail(); } zeroCount = ((usqInt) byte) >> 4; byte = byte & 15; if (byte != 0) { index += zeroCount; bits = getBits(byte); /* begin scaleAndSignExtend:inFieldWidth: */ if (bits < ((((byte - 1) < 0) ? ((usqInt) 1 >> -(byte - 1)) : ((usqInt) 1 << (byte - 1))))) { byte = (bits - (((byte < 0) ? ((usqInt) 1 >> -byte) : ((usqInt) 1 << byte)))) + 1; goto l2; } else { byte = bits; goto l2; } l2: /* end scaleAndSignExtend:inFieldWidth: */; if ((index < 0) || (index >= DCTSize2)) { return interpreterProxy->primitiveFail(); } anArray[jpegNaturalOrder[index]] = byte; } else { if (zeroCount == 15) { index += zeroCount; } else { return null; } } index += 1; } } static sqInt fillBuffer(void) { sqInt byte; while (jsBitCount <= 16) { if (!(jsPosition < jsReadLimit)) { return jsBitCount; } byte = jsCollection[jsPosition]; jsPosition += 1; if (byte == 255) { if (!((jsPosition < jsReadLimit) && ((jsCollection[jsPosition]) == 0))) { jsPosition -= 1; return jsBitCount; } jsPosition += 1; } jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte; jsBitCount += 8; } return jsBitCount; } static sqInt getBits(sqInt requestedBits) { sqInt byte; sqInt value; if (requestedBits > jsBitCount) { /* begin fillBuffer */ while (jsBitCount <= 16) { if (!(jsPosition < jsReadLimit)) { goto l1; } byte = jsCollection[jsPosition]; jsPosition += 1; if (byte == 255) { if (!((jsPosition < jsReadLimit) && ((jsCollection[jsPosition]) == 0))) { jsPosition -= 1; goto l1; } jsPosition += 1; } jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte; jsBitCount += 8; } l1: /* end fillBuffer */; if (requestedBits > jsBitCount) { return -1; } } value = (((requestedBits - jsBitCount) < 0) ? ((usqInt) jsBitBuffer >> -(requestedBits - jsBitCount)) : ((usqInt) jsBitBuffer << (requestedBits - jsBitCount))); jsBitBuffer = jsBitBuffer & (((((jsBitCount - requestedBits) < 0) ? ((usqInt) 1 >> -(jsBitCount - requestedBits)) : ((usqInt) 1 << (jsBitCount - requestedBits)))) - 1); jsBitCount -= requestedBits; return value; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt idctBlockIntqt(int *anArray, int *qt) { sqInt anACTerm; sqInt dcval; sqInt i; sqInt j; sqInt row; sqInt t0; sqInt t1; sqInt t10; sqInt t11; sqInt t12; sqInt t13; sqInt t2; sqInt t3; sqInt v; int ws[64]; sqInt z1; sqInt z2; sqInt z3; sqInt z4; sqInt z5; ; for (i = 0; i <= (DCTSize - 1); i += 1) { anACTerm = -1; for (row = 1; row <= (DCTSize - 1); row += 1) { if (anACTerm == -1) { if (!((anArray[(row * DCTSize) + i]) == 0)) { anACTerm = row; } } } if (anACTerm == -1) { dcval = ((usqInt) ((anArray[i]) * (qt[0])) << 2); for (j = 0; j <= (DCTSize - 1); j += 1) { ws[(j * DCTSize) + i] = dcval; } } else { z2 = (anArray[(DCTSize * 2) + i]) * (qt[(DCTSize * 2) + i]); z3 = (anArray[(DCTSize * 6) + i]) * (qt[(DCTSize * 6) + i]); z1 = (z2 + z3) * FIXn0n541196100; t2 = z1 + (z3 * (0 - FIXn1n847759065)); t3 = z1 + (z2 * FIXn0n765366865); z2 = (anArray[i]) * (qt[i]); z3 = (anArray[(DCTSize * 4) + i]) * (qt[(DCTSize * 4) + i]); t0 = ((usqInt) (z2 + z3) << 13); t1 = ((usqInt) (z2 - z3) << 13); t10 = t0 + t3; t13 = t0 - t3; t11 = t1 + t2; t12 = t1 - t2; t0 = (anArray[(DCTSize * 7) + i]) * (qt[(DCTSize * 7) + i]); t1 = (anArray[(DCTSize * 5) + i]) * (qt[(DCTSize * 5) + i]); t2 = (anArray[(DCTSize * 3) + i]) * (qt[(DCTSize * 3) + i]); t3 = (anArray[DCTSize + i]) * (qt[DCTSize + i]); z1 = t0 + t3; z2 = t1 + t2; z3 = t0 + t2; z4 = t1 + t3; z5 = (z3 + z4) * FIXn1n175875602; t0 = t0 * FIXn0n298631336; t1 = t1 * FIXn2n053119869; t2 = t2 * FIXn3n072711026; t3 = t3 * FIXn1n501321110; z1 = z1 * (0 - FIXn0n899976223); z2 = z2 * (0 - FIXn2n562915447); z3 = z3 * (0 - FIXn1n961570560); z4 = z4 * (0 - FIXn0n390180644); z3 += z5; z4 += z5; t0 = (t0 + z1) + z3; t1 = (t1 + z2) + z4; t2 = (t2 + z2) + z3; t3 = (t3 + z1) + z4; ws[i] = (((sqInt) (t10 + t3) >> 11)); ws[(DCTSize * 7) + i] = (((sqInt) (t10 - t3) >> 11)); ws[(DCTSize * 1) + i] = (((sqInt) (t11 + t2) >> 11)); ws[(DCTSize * 6) + i] = (((sqInt) (t11 - t2) >> 11)); ws[(DCTSize * 2) + i] = (((sqInt) (t12 + t1) >> 11)); ws[(DCTSize * 5) + i] = (((sqInt) (t12 - t1) >> 11)); ws[(DCTSize * 3) + i] = (((sqInt) (t13 + t0) >> 11)); ws[(DCTSize * 4) + i] = (((sqInt) (t13 - t0) >> 11)); } } for (i = 0; i <= (DCTSize2 - DCTSize); i += DCTSize) { z2 = ws[i + 2]; z3 = ws[i + 6]; z1 = (z2 + z3) * FIXn0n541196100; t2 = z1 + (z3 * (0 - FIXn1n847759065)); t3 = z1 + (z2 * FIXn0n765366865); t0 = ((usqInt) ((ws[i]) + (ws[i + 4])) << 13); t1 = ((usqInt) ((ws[i]) - (ws[i + 4])) << 13); t10 = t0 + t3; t13 = t0 - t3; t11 = t1 + t2; t12 = t1 - t2; t0 = ws[i + 7]; t1 = ws[i + 5]; t2 = ws[i + 3]; t3 = ws[i + 1]; z1 = t0 + t3; z2 = t1 + t2; z3 = t0 + t2; z4 = t1 + t3; z5 = (z3 + z4) * FIXn1n175875602; t0 = t0 * FIXn0n298631336; t1 = t1 * FIXn2n053119869; t2 = t2 * FIXn3n072711026; t3 = t3 * FIXn1n501321110; z1 = z1 * (0 - FIXn0n899976223); z2 = z2 * (0 - FIXn2n562915447); z3 = z3 * (0 - FIXn1n961570560); z4 = z4 * (0 - FIXn0n390180644); z3 += z5; z4 += z5; t0 = (t0 + z1) + z3; t1 = (t1 + z2) + z4; t2 = (t2 + z2) + z3; t3 = (t3 + z1) + z4; v = (((sqInt) (t10 + t3) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i] = v; v = (((sqInt) (t10 - t3) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 7] = v; v = (((sqInt) (t11 + t2) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 1] = v; v = (((sqInt) (t11 - t2) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 6] = v; v = (((sqInt) (t12 + t1) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 2] = v; v = (((sqInt) (t12 - t1) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 5] = v; v = (((sqInt) (t13 + t0) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 3] = v; v = (((sqInt) (t13 - t0) >> 18)) + SampleOffset; v = ((v < MaxSample) ? v : MaxSample); v = ((v < 0) ? 0 : v); anArray[i + 4] = v; } } /* Decode the next value in the receiver using the given huffman table. */ static sqInt jpegDecodeValueFromsize(int *table, sqInt tableSize) { sqInt bits; sqInt bitsNeeded; sqInt index; sqInt tableIndex; sqInt value; /* Initial bits needed */ bitsNeeded = ((usqInt) (table[0])) >> 24; if (bitsNeeded > MaxBits) { return -1; } /* First real table */ tableIndex = 2; while (1) { /* Get bits */ bits = getBits(bitsNeeded); if (bits < 0) { return -1; } index = (tableIndex + bits) - 1; if (index >= tableSize) { return -1; } /* Lookup entry in table */ value = table[index]; if ((value & 1056964608) == 0) { return value; } /* Table offset in low 16 bit */ tableIndex = value & 65535; /* Additional bits in high 8 bit */ bitsNeeded = (((usqInt) value) >> 24) & 255; if (bitsNeeded > MaxBits) { return -1; } } return -1; } static sqInt loadJPEGStreamFrom(sqInt streamOop) { sqInt oop; sqInt sz; if ((interpreterProxy->slotSizeOf(streamOop)) < 5) { return 0; } if (!(interpreterProxy->isPointers(streamOop))) { return 0; } oop = interpreterProxy->fetchPointerofObject(0, streamOop); if ((oop & 1)) { return 0; } if (!(interpreterProxy->isBytes(oop))) { return 0; } jsCollection = interpreterProxy->firstIndexableField(oop); sz = interpreterProxy->byteSizeOf(oop); jsPosition = interpreterProxy->fetchIntegerofObject(1, streamOop); jsReadLimit = interpreterProxy->fetchIntegerofObject(2, streamOop); jsBitBuffer = interpreterProxy->fetchIntegerofObject(3, streamOop); jsBitCount = interpreterProxy->fetchIntegerofObject(4, streamOop); if (interpreterProxy->failed()) { return 0; } if (sz < jsReadLimit) { return 0; } if ((jsPosition < 0) || (jsPosition >= jsReadLimit)) { return 0; } return 1; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } static sqInt nextSampleCb(void) { sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; dx = curX = cbComponent[CurrentXIndex]; dy = cbComponent[CurrentYIndex]; sx = cbComponent[HScaleIndex]; sy = cbComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (cbBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((cbComponent[MCUWidthIndex]) * 8)) { cbComponent[CurrentXIndex] = curX; } else { cbComponent[CurrentXIndex] = 0; cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1); } return sample; } static sqInt nextSampleCr(void) { sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; dx = curX = crComponent[CurrentXIndex]; dy = crComponent[CurrentYIndex]; sx = crComponent[HScaleIndex]; sy = crComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (crBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((crComponent[MCUWidthIndex]) * 8)) { crComponent[CurrentXIndex] = curX; } else { crComponent[CurrentXIndex] = 0; crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1); } return sample; } static sqInt nextSampleFromblocks(int *aComponent, int **aBlockArray) { sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; dx = curX = aComponent[CurrentXIndex]; dy = aComponent[CurrentYIndex]; sx = aComponent[HScaleIndex]; sy = aComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (aComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (aBlockArray[blockIndex])[sampleIndex]; curX += 1; if (curX < ((aComponent[MCUWidthIndex]) * 8)) { aComponent[CurrentXIndex] = curX; } else { aComponent[CurrentXIndex] = 0; aComponent[CurrentYIndex] = ((aComponent[CurrentYIndex]) + 1); } return sample; } static sqInt nextSampleY(void) { sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; dx = curX = yComponent[CurrentXIndex]; dy = yComponent[CurrentYIndex]; sx = yComponent[HScaleIndex]; sy = yComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (yBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((yComponent[MCUWidthIndex]) * 8)) { yComponent[CurrentXIndex] = curX; } else { yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1); } return sample; } /* Requires: JPEGColorComponent bits WordArray with: 3*Integer (residuals) ditherMask */ EXPORT(sqInt) primitiveColorConvertGrayscaleMCU(void) { sqInt arrayOop; sqInt blockIndex; sqInt curX; sqInt dx; sqInt dy; sqInt i; sqInt sample; sqInt sampleIndex; sqInt sx; sqInt sy; sqInt y; stInit(); if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } ditherMask = interpreterProxy->stackIntegerValue(0); arrayOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) { return interpreterProxy->primitiveFail(); } residuals = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(arrayOop))) { return interpreterProxy->primitiveFail(); } jpegBitsSize = interpreterProxy->slotSizeOf(arrayOop); jpegBits = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } if (!((colorComponentfrom(yComponent, arrayOop)) && (colorComponentBlocksfrom(yBlocks, arrayOop)))) { return interpreterProxy->primitiveFail(); } /* begin colorConvertGrayscaleMCU */ yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = 0; for (i = 0; i <= (jpegBitsSize - 1); i += 1) { /* begin nextSampleY */ dx = curX = yComponent[CurrentXIndex]; dy = yComponent[CurrentYIndex]; sx = yComponent[HScaleIndex]; sy = yComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (yBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((yComponent[MCUWidthIndex]) * 8)) { yComponent[CurrentXIndex] = curX; } else { yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1); } y = sample; y += residuals[GreenIndex]; y = ((y < MaxSample) ? y : MaxSample); residuals[GreenIndex] = (y & ditherMask); y = y & (MaxSample - ditherMask); y = ((y < 1) ? 1 : y); jpegBits[i] = (((4278190080UL + (y << 16)) + (y << 8)) + y); } interpreterProxy->pop(4); } /* Requires: Array with: 3*JPEGColorComponent bits WordArray with: 3*Integer (residuals) ditherMask */ EXPORT(sqInt) primitiveColorConvertMCU(void) { sqInt arrayOop; sqInt blockIndex; sqInt blockIndex1; sqInt blockIndex2; sqInt blue; sqInt cb; sqInt cr; sqInt curX; sqInt curX1; sqInt curX2; sqInt dx; sqInt dx1; sqInt dx2; sqInt dy; sqInt dy1; sqInt dy2; sqInt green; sqInt i; sqInt red; sqInt sample; sqInt sample1; sqInt sample2; sqInt sampleIndex; sqInt sampleIndex1; sqInt sampleIndex2; sqInt sx; sqInt sx1; sqInt sx2; sqInt sy; sqInt sy1; sqInt sy2; sqInt y; stInit(); if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } ditherMask = interpreterProxy->stackIntegerValue(0); arrayOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) { return interpreterProxy->primitiveFail(); } residuals = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(arrayOop))) { return interpreterProxy->primitiveFail(); } jpegBitsSize = interpreterProxy->slotSizeOf(arrayOop); jpegBits = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isPointers(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) { return interpreterProxy->primitiveFail(); } if (!(yColorComponentFrom(interpreterProxy->fetchPointerofObject(0, arrayOop)))) { return interpreterProxy->primitiveFail(); } if (!(cbColorComponentFrom(interpreterProxy->fetchPointerofObject(1, arrayOop)))) { return interpreterProxy->primitiveFail(); } if (!(crColorComponentFrom(interpreterProxy->fetchPointerofObject(2, arrayOop)))) { return interpreterProxy->primitiveFail(); } /* begin colorConvertMCU */ yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = 0; cbComponent[CurrentXIndex] = 0; cbComponent[CurrentYIndex] = 0; crComponent[CurrentXIndex] = 0; crComponent[CurrentYIndex] = 0; for (i = 0; i <= (jpegBitsSize - 1); i += 1) { /* begin nextSampleY */ dx = curX = yComponent[CurrentXIndex]; dy = yComponent[CurrentYIndex]; sx = yComponent[HScaleIndex]; sy = yComponent[VScaleIndex]; if (!((sx == 0) && (sy == 0))) { dx = dx / sx; dy = dy / sy; } blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3)); sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7); sample = (yBlocks[blockIndex])[sampleIndex]; curX += 1; if (curX < ((yComponent[MCUWidthIndex]) * 8)) { yComponent[CurrentXIndex] = curX; } else { yComponent[CurrentXIndex] = 0; yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1); } y = sample; /* begin nextSampleCb */ dx1 = curX1 = cbComponent[CurrentXIndex]; dy1 = cbComponent[CurrentYIndex]; sx1 = cbComponent[HScaleIndex]; sy1 = cbComponent[VScaleIndex]; if (!((sx1 == 0) && (sy1 == 0))) { dx1 = dx1 / sx1; dy1 = dy1 / sy1; } blockIndex1 = ((((usqInt) dy1 >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx1 >> 3)); sampleIndex1 = (((usqInt) (dy1 & 7) << 3)) + (dx1 & 7); sample1 = (cbBlocks[blockIndex1])[sampleIndex1]; curX1 += 1; if (curX1 < ((cbComponent[MCUWidthIndex]) * 8)) { cbComponent[CurrentXIndex] = curX1; } else { cbComponent[CurrentXIndex] = 0; cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1); } cb = sample1; cb -= SampleOffset; /* begin nextSampleCr */ dx2 = curX2 = crComponent[CurrentXIndex]; dy2 = crComponent[CurrentYIndex]; sx2 = crComponent[HScaleIndex]; sy2 = crComponent[VScaleIndex]; if (!((sx2 == 0) && (sy2 == 0))) { dx2 = dx2 / sx2; dy2 = dy2 / sy2; } blockIndex2 = ((((usqInt) dy2 >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx2 >> 3)); sampleIndex2 = (((usqInt) (dy2 & 7) << 3)) + (dx2 & 7); sample2 = (crBlocks[blockIndex2])[sampleIndex2]; curX2 += 1; if (curX2 < ((crComponent[MCUWidthIndex]) * 8)) { crComponent[CurrentXIndex] = curX2; } else { crComponent[CurrentXIndex] = 0; crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1); } cr = sample2; cr -= SampleOffset; red = (y + (((sqInt) (FIXn1n40200 * cr) >> 16))) + (residuals[RedIndex]); red = ((red < MaxSample) ? red : MaxSample); red = ((red < 0) ? 0 : red); residuals[RedIndex] = (red & ditherMask); red = red & (MaxSample - ditherMask); red = ((red < 1) ? 1 : red); green = ((y - (((sqInt) (FIXn0n34414 * cb) >> 16))) - (((sqInt) (FIXn0n71414 * cr) >> 16))) + (residuals[GreenIndex]); green = ((green < MaxSample) ? green : MaxSample); green = ((green < 0) ? 0 : green); residuals[GreenIndex] = (green & ditherMask); green = green & (MaxSample - ditherMask); green = ((green < 1) ? 1 : green); blue = (y + (((sqInt) (FIXn1n77200 * cb) >> 16))) + (residuals[BlueIndex]); blue = ((blue < MaxSample) ? blue : MaxSample); blue = ((blue < 0) ? 0 : blue); residuals[BlueIndex] = (blue & ditherMask); blue = blue & (MaxSample - ditherMask); blue = ((blue < 1) ? 1 : blue); jpegBits[i] = (((4278190080UL + (((usqInt) red << 16))) + (((usqInt) green << 8))) + blue); } interpreterProxy->pop(4); } /* In: anArray WordArray of: DCTSize2 aColorComponent JPEGColorComponent dcTable WordArray acTable WordArray stream JPEGStream */ EXPORT(sqInt) primitiveDecodeMCU(void) { int *anArray; sqInt arrayOop; sqInt bits; sqInt byte; sqInt i; sqInt index; sqInt oop; sqInt streamOop; sqInt zeroCount; ; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(loadJPEGStreamFrom(oop))) { return interpreterProxy->primitiveFail(); } arrayOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(arrayOop))) { return interpreterProxy->primitiveFail(); } acTableSize = interpreterProxy->slotSizeOf(arrayOop); acTable = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(arrayOop))) { return interpreterProxy->primitiveFail(); } dcTableSize = interpreterProxy->slotSizeOf(arrayOop); dcTable = interpreterProxy->firstIndexableField(arrayOop); oop = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } if (!(colorComponentfrom(yComponent, oop))) { return interpreterProxy->primitiveFail(); } arrayOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(arrayOop))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(arrayOop)) == DCTSize2)) { return interpreterProxy->primitiveFail(); } anArray = interpreterProxy->firstIndexableField(arrayOop); if (interpreterProxy->failed()) { return null; } /* begin decodeBlockInto:component: */ byte = jpegDecodeValueFromsize(dcTable, dcTableSize); if (byte < 0) { interpreterProxy->primitiveFail(); goto l1; } if (byte != 0) { bits = getBits(byte); /* begin scaleAndSignExtend:inFieldWidth: */ if (bits < ((((byte - 1) < 0) ? ((usqInt) 1 >> -(byte - 1)) : ((usqInt) 1 << (byte - 1))))) { byte = (bits - (((byte < 0) ? ((usqInt) 1 >> -byte) : ((usqInt) 1 << byte)))) + 1; goto l2; } else { byte = bits; goto l2; } l2: /* end scaleAndSignExtend:inFieldWidth: */; } byte = yComponent[PriorDCValueIndex] = ((yComponent[PriorDCValueIndex]) + byte); anArray[0] = byte; for (i = 1; i <= (DCTSize2 - 1); i += 1) { anArray[i] = 0; } index = 1; while (index < DCTSize2) { byte = jpegDecodeValueFromsize(acTable, acTableSize); if (byte < 0) { interpreterProxy->primitiveFail(); goto l1; } zeroCount = ((usqInt) byte) >> 4; byte = byte & 15; if (byte != 0) { index += zeroCount; bits = getBits(byte); /* begin scaleAndSignExtend:inFieldWidth: */ if (bits < ((((byte - 1) < 0) ? ((usqInt) 1 >> -(byte - 1)) : ((usqInt) 1 << (byte - 1))))) { byte = (bits - (((byte < 0) ? ((usqInt) 1 >> -byte) : ((usqInt) 1 << byte)))) + 1; goto l3; } else { byte = bits; goto l3; } l3: /* end scaleAndSignExtend:inFieldWidth: */; if ((index < 0) || (index >= DCTSize2)) { interpreterProxy->primitiveFail(); goto l1; } anArray[jpegNaturalOrder[index]] = byte; } else { if (zeroCount == 15) { index += zeroCount; } else { goto l1; } } index += 1; } l1: /* end decodeBlockInto:component: */; if (interpreterProxy->failed()) { return null; } /* begin storeJPEGStreamOn: */ streamOop = interpreterProxy->stackValue(0); interpreterProxy->storeIntegerofObjectwithValue(1, streamOop, jsPosition); interpreterProxy->storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer); interpreterProxy->storeIntegerofObjectwithValue(4, streamOop, jsBitCount); interpreterProxy->storeIntegerofObjectwithValue(PriorDCValueIndex, interpreterProxy->stackValue(3), yComponent[PriorDCValueIndex]); interpreterProxy->pop(5); } /* In: anArray: IntegerArray new: DCTSize2 qt: IntegerArray new: DCTSize2. */ EXPORT(sqInt) primitiveIdctInt(void) { int *anArray; sqInt arrayOop; int *qt; ; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } arrayOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == DCTSize2))) { return interpreterProxy->primitiveFail(); } qt = interpreterProxy->firstIndexableField(arrayOop); arrayOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == DCTSize2))) { return interpreterProxy->primitiveFail(); } anArray = interpreterProxy->firstIndexableField(arrayOop); idctBlockIntqt(anArray, qt); interpreterProxy->pop(2); } static sqInt scaleAndSignExtendinFieldWidth(sqInt aNumber, sqInt w) { if (aNumber < ((((w - 1) < 0) ? ((usqInt) 1 >> -(w - 1)) : ((usqInt) 1 << (w - 1))))) { return (aNumber - (((w < 0) ? ((usqInt) 1 >> -w) : ((usqInt) 1 << w)))) + 1; } else { return aNumber; } } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt stInit(void) { ; } static sqInt storeJPEGStreamOn(sqInt streamOop) { interpreterProxy->storeIntegerofObjectwithValue(1, streamOop, jsPosition); interpreterProxy->storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer); interpreterProxy->storeIntegerofObjectwithValue(4, streamOop, jsBitCount); } static sqInt yColorComponentFrom(sqInt oop) { return (colorComponentfrom(yComponent, oop)) && (colorComponentBlocksfrom(yBlocks, oop)); } #ifdef SQUEAK_BUILTIN_PLUGIN void* JPEGReaderPlugin_exports[][3] = { {"JPEGReaderPlugin", "getModuleName", (void*)getModuleName}, {"JPEGReaderPlugin", "primitiveColorConvertGrayscaleMCU", (void*)primitiveColorConvertGrayscaleMCU}, {"JPEGReaderPlugin", "primitiveColorConvertMCU", (void*)primitiveColorConvertMCU}, {"JPEGReaderPlugin", "primitiveDecodeMCU", (void*)primitiveDecodeMCU}, {"JPEGReaderPlugin", "primitiveIdctInt", (void*)primitiveIdctInt}, {"JPEGReaderPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/JoystickTabletPlugin/JoystickTabletPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from JoystickTabletPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "JoystickTabletPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "JoystickTabletPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveGetTabletParameters(void); EXPORT(sqInt) primitiveReadJoystick(void); EXPORT(sqInt) primitiveReadTablet(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "JoystickTabletPlugin VMMaker-oscog.dtl.57 (i)" #else "JoystickTabletPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return joystickInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Get information on the pen tablet attached to this machine. Fail if there is no tablet. If successful, the result is an array of integers; see the Smalltalk call on this primitive for its interpretation. */ EXPORT(sqInt) primitiveGetTabletParameters(void) { sqInt cursorIndex; sqInt result; int * resultPtr; sqInt resultSize; cursorIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } resultSize = tabletResultSize(); result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classBitmap(), resultSize); resultPtr = (int *) interpreterProxy->firstIndexableField(result); interpreterProxy->success(tabletGetParameters(cursorIndex, resultPtr)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, result); return null; } /* Read an input word from the joystick with the given index. */ EXPORT(sqInt) primitiveReadJoystick(void) { sqInt index; sqInt _return_value; index = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } _return_value = interpreterProxy->positive32BitIntegerFor((joystickRead(index))); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Get the current state of the cursor of the pen tablet specified by my argument. Fail if there is no tablet. If successful, the result is an array of integers; see the Smalltalk call on this primitive for its interpretation. */ EXPORT(sqInt) primitiveReadTablet(void) { sqInt cursorIndex; sqInt result; int * resultPtr; sqInt resultSize; cursorIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } resultSize = tabletResultSize(); result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classBitmap(), resultSize); resultPtr = (int *) interpreterProxy->firstIndexableField(result); interpreterProxy->success(tabletRead(cursorIndex, resultPtr)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, result); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return joystickShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* JoystickTabletPlugin_exports[][3] = { {"JoystickTabletPlugin", "getModuleName", (void*)getModuleName}, {"JoystickTabletPlugin", "initialiseModule", (void*)initialiseModule}, {"JoystickTabletPlugin", "primitiveGetTabletParameters", (void*)primitiveGetTabletParameters}, {"JoystickTabletPlugin", "primitiveReadJoystick", (void*)primitiveReadJoystick}, {"JoystickTabletPlugin", "primitiveReadTablet", (void*)primitiveReadTablet}, {"JoystickTabletPlugin", "setInterpreter", (void*)setInterpreter}, {"JoystickTabletPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/Klatt/Klatt.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from KlattSynthesizerPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "KlattSynthesizerPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ #define A1v 46 #define A2f 34 #define A2v 47 #define A3f 35 #define A3v 48 #define A4f 36 #define A4v 49 #define A5f 37 #define A6f 38 #define Anv 45 #define Aspiration 9 #define Atv 50 #define B1 13 #define B2 17 #define B2f 40 #define B3 19 #define B3f 41 #define B4 21 #define B4f 42 #define B5 23 #define B5f 43 #define B6 25 #define B6f 44 #define Bnp 27 #define Bnz 29 #define Btp 31 #define Btz 33 #define Bypass 39 #define Diplophonia 4 #define Epsilon 0.0001 #define F0 0 #define F1 12 #define F2 16 #define F3 18 #define F4 20 #define F5 22 #define F6 24 #define Flutter 1 #define Fnp 26 #define Fnz 28 #define Friction 10 #define Ftp 30 #define Ftz 32 #define Gain 51 #define Jitter 2 #define PI 3.141592653589793 #define R1c 12 #define R1vp 3 #define R2c 13 #define R2fp 7 #define R2vp 4 #define R3c 14 #define R3fp 8 #define R3vp 5 #define R4c 15 #define R4fp 9 #define R4vp 6 #define R5c 16 #define R5fp 10 #define R6c 17 #define R6fp 11 #define R7c 18 #define R8c 19 #define Ra 7 #define Rk 8 #define Rnpc 20 #define Rnpp 1 #define Rnz 21 #define Ro 6 #define Rout 24 #define Rtpc 22 #define Rtpp 2 #define Rtz 23 #define Shimmer 3 #define Turbulence 11 #define Voicing 5 /*** Function Prototypes ***/ static void addAmplitudeDiplophonia(void); static void addFlutter(void); static void addFrequencyDiplophonia(void); static void addJitter(void); static void addShimmer(void); static void antiResonatorfrequencybandwidth(sqInt index, float freq, float bw); static float antiResonatorvalue(sqInt index, double aFloat); static float cascadeBranch(float source); static float * checkedFloatPtrOf(sqInt oop); static short * checkedShortPtrOf(sqInt oop); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static float glottalSource(void); static sqInt halt(void); static float linearFromdB(double aNumber); static sqInt loadFrom(sqInt klattOop); static sqInt msg(char *s); static sqInt nextRandom(void); static void normalizeGlottalPulse(void); static float parallelFrictionBranch(float source); static float parallelVoicedBranch(float source); static void pitchSynchronousReset(void); EXPORT(sqInt) primitiveSynthesizeFrameIntoStartingAt(void); static float quphicosphisinphirphid(float u, float phi, float cosphi, float sinphi, float rphid); static float resonatorA(sqInt index); static void resonatorAput(sqInt index, float aFloat); static float resonatorB(sqInt index); static void resonatorBput(sqInt index, float aFloat); static float resonatorC(sqInt index); static void resonatorCput(sqInt index, float aFloat); static float resonatorP1(sqInt index); static void resonatorP1put(sqInt index, float aFloat); static float resonatorP2(sqInt index); static void resonatorP2put(sqInt index, float aFloat); static void resonatorfrequencybandwidth(sqInt index, float freq, float bw); static void resonatorfrequencybandwidthgain(sqInt index, float freq, float bw, float gain); static float resonatorvalue(sqInt index, float aFloat); static void rorark(float roNumber, float raNumber, float rkNumber); static sqInt saveTo(sqInt origKlattOop); static void setCurrentFrame(float *aKlattFrame); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void synthesizeFrameintostartingAt(float *aKlattFrame, short *buffer, sqInt startIndex); static void voicedPitchSynchronousReset(void); static float zeroQphicosphisinphirphid(float phi, float cosphi, float sinphi, float rphid); /*** Variables ***/ static float a1; static float a2; static float b1; static float c1; static sqInt cascade; static float * frame; static float glast; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Klatt VMMaker-oscog.dtl.57 (i)" #else "Klatt VMMaker-oscog.dtl.57 (e)" #endif ; static float nlast; static sqInt nmod; static sqInt nopen; static sqInt nper; static sqInt periodCount; static float pitch; static float * resonators; static sqInt samplesCount; static sqInt samplesPerFrame; static sqInt samplingRate; static sqInt seed; static sqInt t0; static float vlast; static float x1; static float x2; /* Add diplophonia (bicyclic voice). Change voicing amplitude. */ static void addAmplitudeDiplophonia(void) { if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } } /* Add F0 flutter, as specified in: 'Analysis, synthesis and perception of voice quality variations among female and male talkers' D.H. Klatt and L.C. Klatt JASA 87(2) February 1990. Flutter is added by applying a quasi-random element constructed from three slowly varying sine waves. */ static void addFlutter(void) { float asin; float bsin; float csin; double deltaF0; float timeCount; timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; } /* Add diplophonia (bicyclic voice). Change F0. */ static void addFrequencyDiplophonia(void) { if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } } /* Add jitter (random F0 perturbation). */ static void addJitter(void) { pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); } /* Add shimmer (random voicing amplitude perturbation). */ static void addShimmer(void) { /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } } /* Set up an anti-resonator */ static void antiResonatorfrequencybandwidth(sqInt index, float freq, float bw) { float a; double arg; float b; float c; float r; arg = ((0.0 - PI) / samplingRate) * bw; r = exp(arg); c = 0.0 - (r * r); arg = ((PI * 2.0) / samplingRate) * freq; b = (r * (cos(arg))) * 2.0; a = (1.0 - b) - c; a = 1.0 / a; b = (0.0 - b) * a; c = (0.0 - c) * a; /* begin resonatorA:put: */ resonators[(index * 5) - 5] = a; /* begin resonatorB:put: */ resonators[(index * 5) - 4] = b; /* begin resonatorC:put: */ resonators[(index * 5) - 3] = c; } static float antiResonatorvalue(sqInt index, double aFloat) { double answer; double p1; answer = (((resonatorA(index)) * aFloat) + ((resonatorB(index)) * ((p1 = resonatorP1(index))))) + ((resonatorC(index)) * (resonatorP2(index))); /* begin resonatorP2:put: */ resonators[(index * 5) - 1] = p1; /* begin resonatorP1:put: */ resonators[(index * 5) - 2] = aFloat; return answer; } /* Cascade vocal tract, excited by laryngeal sources. Nasal antiresonator, nasal resonator, tracheal antirresonator, tracheal resonator, then formants F8, F7, F6, F5, F4, F3, F2, F1. */ static float cascadeBranch(float source) { double answer; double answer1; float answer10; float answer11; float answer2; float answer3; float answer4; float answer5; float answer6; float answer7; float answer8; float answer9; float out; double p1; double p11; float p110; float p111; float p12; float p13; float p14; float p15; float p16; float p17; float p18; float p19; if (!(cascade > 0)) { return 0.0; } /* begin antiResonator:value: */ answer = (((resonatorA(Rnz)) * source) + ((resonatorB(Rnz)) * ((p1 = resonatorP1(Rnz))))) + ((resonatorC(Rnz)) * (resonatorP2(Rnz))); /* begin resonatorP2:put: */ resonators[(Rnz * 5) - 1] = p1; /* begin resonatorP1:put: */ resonators[(Rnz * 5) - 2] = source; out = answer; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer10 = (((resonatorA(Rnpc)) * out) + ((resonatorB(Rnpc)) * ((p110 = resonatorP1(Rnpc))))) + ((resonatorC(Rnpc)) * (resonatorP2(Rnpc))); /* begin resonatorP2:put: */ resonators[(Rnpc * 5) - 1] = p110; /* begin resonatorP1:put: */ resonators[(Rnpc * 5) - 2] = answer10; out = answer10; /* begin antiResonator:value: */ answer1 = (((resonatorA(Rtz)) * out) + ((resonatorB(Rtz)) * ((p11 = resonatorP1(Rtz))))) + ((resonatorC(Rtz)) * (resonatorP2(Rtz))); /* begin resonatorP2:put: */ resonators[(Rtz * 5) - 1] = p11; /* begin resonatorP1:put: */ resonators[(Rtz * 5) - 2] = out; out = answer1; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer11 = (((resonatorA(Rtpc)) * out) + ((resonatorB(Rtpc)) * ((p111 = resonatorP1(Rtpc))))) + ((resonatorC(Rtpc)) * (resonatorP2(Rtpc))); /* begin resonatorP2:put: */ resonators[(Rtpc * 5) - 1] = p111; /* begin resonatorP1:put: */ resonators[(Rtpc * 5) - 2] = answer11; out = answer11; if (cascade >= 8) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer2 = (((resonatorA(R8c)) * out) + ((resonatorB(R8c)) * ((p12 = resonatorP1(R8c))))) + ((resonatorC(R8c)) * (resonatorP2(R8c))); /* begin resonatorP2:put: */ resonators[(R8c * 5) - 1] = p12; /* begin resonatorP1:put: */ resonators[(R8c * 5) - 2] = answer2; out = answer2; } if (cascade >= 7) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer3 = (((resonatorA(R7c)) * out) + ((resonatorB(R7c)) * ((p13 = resonatorP1(R7c))))) + ((resonatorC(R7c)) * (resonatorP2(R7c))); /* begin resonatorP2:put: */ resonators[(R7c * 5) - 1] = p13; /* begin resonatorP1:put: */ resonators[(R7c * 5) - 2] = answer3; out = answer3; } if (cascade >= 6) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer4 = (((resonatorA(R6c)) * out) + ((resonatorB(R6c)) * ((p14 = resonatorP1(R6c))))) + ((resonatorC(R6c)) * (resonatorP2(R6c))); /* begin resonatorP2:put: */ resonators[(R6c * 5) - 1] = p14; /* begin resonatorP1:put: */ resonators[(R6c * 5) - 2] = answer4; out = answer4; } if (cascade >= 5) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer5 = (((resonatorA(R5c)) * out) + ((resonatorB(R5c)) * ((p15 = resonatorP1(R5c))))) + ((resonatorC(R5c)) * (resonatorP2(R5c))); /* begin resonatorP2:put: */ resonators[(R5c * 5) - 1] = p15; /* begin resonatorP1:put: */ resonators[(R5c * 5) - 2] = answer5; out = answer5; } if (cascade >= 4) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer6 = (((resonatorA(R4c)) * out) + ((resonatorB(R4c)) * ((p16 = resonatorP1(R4c))))) + ((resonatorC(R4c)) * (resonatorP2(R4c))); /* begin resonatorP2:put: */ resonators[(R4c * 5) - 1] = p16; /* begin resonatorP1:put: */ resonators[(R4c * 5) - 2] = answer6; out = answer6; } if (cascade >= 3) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer7 = (((resonatorA(R3c)) * out) + ((resonatorB(R3c)) * ((p17 = resonatorP1(R3c))))) + ((resonatorC(R3c)) * (resonatorP2(R3c))); /* begin resonatorP2:put: */ resonators[(R3c * 5) - 1] = p17; /* begin resonatorP1:put: */ resonators[(R3c * 5) - 2] = answer7; out = answer7; } if (cascade >= 2) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer8 = (((resonatorA(R2c)) * out) + ((resonatorB(R2c)) * ((p18 = resonatorP1(R2c))))) + ((resonatorC(R2c)) * (resonatorP2(R2c))); /* begin resonatorP2:put: */ resonators[(R2c * 5) - 1] = p18; /* begin resonatorP1:put: */ resonators[(R2c * 5) - 2] = answer8; out = answer8; } if (cascade >= 1) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer9 = (((resonatorA(R1c)) * out) + ((resonatorB(R1c)) * ((p19 = resonatorP1(R1c))))) + ((resonatorC(R1c)) * (resonatorP2(R1c))); /* begin resonatorP2:put: */ resonators[(R1c * 5) - 1] = p19; /* begin resonatorP1:put: */ resonators[(R1c * 5) - 2] = answer9; out = answer9; } return out; } /* Return the first indexable word of oop which is assumed to be variableWordSubclass */ static float * checkedFloatPtrOf(sqInt oop) { interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { return 0; } return ((float *) (interpreterProxy->firstIndexableField(oop))); } /* Return the first indexable word of oop which is assumed to be variableWordSubclass */ static short * checkedShortPtrOf(sqInt oop) { interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { return 0; } return ((short *) (interpreterProxy->firstIndexableField(oop))); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static float glottalSource(void) { float asin; float bsin; float cosphi; float csin; float d; double deltaF0; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float gamma; float gammapwr; sqInt ingore; float phi; float qa; float qb; float qc; float qzero; float r; float ra; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; sqInt te; float theta; float timeCount; float u; float ua; float ub; float uc; float x0; if (t0 == 0) { return 0; } if (nper < nopen) { x0 = (a1 * x1) + (a2 * x2); x2 = x1; x1 = x0; } else { x0 = (b1 * x1) - c1; x1 = x0; } if (nper >= t0) { nper = 0; /* begin pitchSynchronousReset */ if ((frame[F0]) > 0) { /* begin voicedPitchSynchronousReset */ /* Add flutter and jitter (F0 perturbations). */ pitch = frame[F0]; /* begin addFlutter */ timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; /* begin addJitter */ pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); /* begin addFrequencyDiplophonia */ if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } if (pitch < 0) { pitch = 0; } /* Duration of period before amplitude modulation. */ t0 = ((sqInt)(samplingRate / pitch)); nmod = t0; if ((frame[Voicing]) > 0) { nmod = ((sqInt) nmod >> 1); } /* Set the LF glottal pulse model parameters. */ nopen = ((sqInt)(t0 * (frame[Ro]))); /* begin ro:ra:rk: */ te = ((sqInt)(t0 * (frame[Ro]))); ro = (((double) te )) / (((double) t0 )); rk = frame[Rk]; ra = frame[Ra]; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } /* begin addShimmer */ /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } /* begin addAmplitudeDiplophonia */ if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } periodCount = (periodCount + 1) % 65535; } else { t0 = 1; nmod = t0; } } nper += 1; return x0; } static sqInt halt(void) { ; return 0; } static float linearFromdB(double aNumber) { return (pow(2.0,((aNumber - 87.0) / 6.0))) * 32.767; } static sqInt loadFrom(sqInt klattOop) { sqInt oop; interpreterProxy->success((interpreterProxy->slotSizeOf(klattOop)) == 22); if (interpreterProxy->failed()) { return 0; } oop = interpreterProxy->fetchPointerofObject(0, klattOop); /* begin checkedFloatPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { resonators = 0; goto l1; } resonators = ((float *) (interpreterProxy->firstIndexableField(oop))); l1: /* end checkedFloatPtrOf: */; pitch = interpreterProxy->fetchFloatofObject(2, klattOop); t0 = interpreterProxy->fetchIntegerofObject(3, klattOop); nper = interpreterProxy->fetchIntegerofObject(4, klattOop); nopen = interpreterProxy->fetchIntegerofObject(5, klattOop); nmod = interpreterProxy->fetchIntegerofObject(6, klattOop); a1 = interpreterProxy->fetchFloatofObject(7, klattOop); a2 = interpreterProxy->fetchFloatofObject(8, klattOop); x1 = interpreterProxy->fetchFloatofObject(9, klattOop); x2 = interpreterProxy->fetchFloatofObject(10, klattOop); b1 = interpreterProxy->fetchFloatofObject(11, klattOop); c1 = interpreterProxy->fetchFloatofObject(12, klattOop); glast = interpreterProxy->fetchFloatofObject(13, klattOop); vlast = interpreterProxy->fetchFloatofObject(14, klattOop); nlast = interpreterProxy->fetchFloatofObject(15, klattOop); periodCount = interpreterProxy->fetchIntegerofObject(16, klattOop); samplesCount = interpreterProxy->fetchIntegerofObject(17, klattOop); seed = interpreterProxy->fetchIntegerofObject(18, klattOop); cascade = interpreterProxy->fetchIntegerofObject(19, klattOop); samplesPerFrame = interpreterProxy->fetchIntegerofObject(20, klattOop); samplingRate = interpreterProxy->fetchIntegerofObject(21, klattOop); return (interpreterProxy->failed()) == 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Answer a random number between 0 and 65535. */ static sqInt nextRandom(void) { seed = ((seed * 1309) + 13849) & 65535; return seed; } static void normalizeGlottalPulse(void) { sqInt ingore; float s0; float s1; float s2; s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } } /* Friction-excited parallel vocal tract formants F6, F5, F4, F3, F2, outputs added with alternating sign. Sound source for other parallel resonators is friction plus first difference of voicing waveform. */ static float parallelFrictionBranch(float source) { return ((((resonatorvalue(R2fp, source)) - (resonatorvalue(R3fp, source))) + (resonatorvalue(R4fp, source))) - (resonatorvalue(R5fp, source))) + (resonatorvalue(R6fp, source)); } /* Voice-excited parallel vocal tract F1, F2, F3, F4, FNP and FTP. */ static float parallelVoicedBranch(float source) { return (((((resonatorvalue(R1vp, source)) + (resonatorvalue(R2vp, source))) + (resonatorvalue(R3vp, source))) + (resonatorvalue(R4vp, source))) + (resonatorvalue(Rnpp, source))) + (resonatorvalue(Rtpp, source)); } static void pitchSynchronousReset(void) { float asin; float bsin; float cosphi; float csin; float d; double deltaF0; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float gamma; float gammapwr; sqInt ingore; float phi; float qa; float qb; float qc; float qzero; float r; float ra; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; sqInt te; float theta; float timeCount; float u; float ua; float ub; float uc; if ((frame[F0]) > 0) { /* begin voicedPitchSynchronousReset */ /* Add flutter and jitter (F0 perturbations). */ pitch = frame[F0]; /* begin addFlutter */ timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; /* begin addJitter */ pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); /* begin addFrequencyDiplophonia */ if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } if (pitch < 0) { pitch = 0; } /* Duration of period before amplitude modulation. */ t0 = ((sqInt)(samplingRate / pitch)); nmod = t0; if ((frame[Voicing]) > 0) { nmod = ((sqInt) nmod >> 1); } /* Set the LF glottal pulse model parameters. */ nopen = ((sqInt)(t0 * (frame[Ro]))); /* begin ro:ra:rk: */ te = ((sqInt)(t0 * (frame[Ro]))); ro = (((double) te )) / (((double) t0 )); rk = frame[Rk]; ra = frame[Ra]; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } /* begin addShimmer */ /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } /* begin addAmplitudeDiplophonia */ if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } periodCount = (periodCount + 1) % 65535; } else { t0 = 1; nmod = t0; } } EXPORT(sqInt) primitiveSynthesizeFrameIntoStartingAt(void) { float aFloat; float aFloat1; float aFloat10; float aFloat11; float aFloat2; float aFloat3; float aFloat4; float aFloat5; float aFloat6; float aFloat7; float aFloat8; float aFloat9; float *aKlattFrame; float ampF1V; float ampF2F; float ampF2V; float ampF3F; float ampF3V; float ampF4F; float ampF4V; float ampF5F; float ampF6F; float ampFNV; float ampFTV; float ampGain; float answer; double answer1; float answer10; float answer11; double answer12; float answer2; float answer3; float answer4; float answer5; float answer6; float answer7; float answer8; float answer9; float asin; float aspiration; float aspirationNoise; float bsin; short *buffer; sqInt bufferOop; float bypass; float cosphi; float csin; float d; double deltaF0; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float friction; float frictionNoise; float gain; float gamma; float gammapwr; float glotout; sqInt index; sqInt ingore; float noise; sqInt oop; sqInt oop1; float out; float out1; float p1; double p11; float p110; float p111; double p112; float p12; float p13; float p14; float p15; float p16; float p17; float p18; float p19; float parGlotout; float parVoicing; float phi; float qa; float qb; float qc; float qzero; float r; float ra; sqInt rcvr; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; float source; sqInt startIndex; sqInt te; sqInt temp; float theta; float timeCount; sqInt top; float turbulence; float u; float ua; float ub; float uc; float voice; float voicing; float x0; /* begin checkedFloatPtrOf: */ oop = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { aKlattFrame = 0; goto l1; } aKlattFrame = ((float *) (interpreterProxy->firstIndexableField(oop))); l1: /* end checkedFloatPtrOf: */; /* begin checkedShortPtrOf: */ oop1 = bufferOop = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isWords(oop1)); if (interpreterProxy->failed()) { buffer = 0; goto l2; } buffer = ((short *) (interpreterProxy->firstIndexableField(oop1))); l2: /* end checkedShortPtrOf: */; startIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } rcvr = interpreterProxy->stackObjectValue(3); if (!(loadFrom(rcvr))) { return null; } interpreterProxy->success(((interpreterProxy->stSizeOf(bufferOop)) * 2) >= samplesPerFrame); if (interpreterProxy->failed()) { return null; } /* begin synthesizeFrame:into:startingAt: */ /* begin setCurrentFrame: */ /* Fudge factors... */ frame = aKlattFrame; /* -4.44 dB */ ampFNV = (linearFromdB(frame[Anv])) * 0.6; /* -4.44 dB */ ampFTV = (linearFromdB(frame[Atv])) * 0.6; /* -7.96 dB */ ampF1V = (linearFromdB(frame[A1v])) * 0.4; /* -16.5 dB */ ampF2V = (linearFromdB(frame[A2v])) * 0.15; /* -24.4 dB */ ampF3V = (linearFromdB(frame[A3v])) * 0.06; /* -28.0 dB */ ampF4V = (linearFromdB(frame[A4v])) * 0.04; /* -16.5 dB */ ampF2F = (linearFromdB(frame[A2f])) * 0.15; /* -24.4 dB */ ampF3F = (linearFromdB(frame[A3f])) * 0.06; /* -28.0 dB */ ampF4F = (linearFromdB(frame[A4f])) * 0.04; /* -33.2 dB */ ampF5F = (linearFromdB(frame[A5f])) * 0.022; /* -30.5 dB */ /* Set coefficients of variable cascade resonators */ ampF6F = (linearFromdB(frame[A6f])) * 0.03; if (cascade >= 8) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R8c, 7500, 600); } else { cascade = 6; } } if (cascade >= 7) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R7c, 6500, 500); } else { cascade = 6; } } if (cascade >= 6) { resonatorfrequencybandwidth(R6c, frame[F6], frame[B6]); } if (cascade >= 5) { resonatorfrequencybandwidth(R5c, frame[F5], frame[B5]); } resonatorfrequencybandwidth(R4c, frame[F4], frame[B4]); resonatorfrequencybandwidth(R3c, frame[F3], frame[B3]); resonatorfrequencybandwidth(R2c, frame[F2], frame[B2]); resonatorfrequencybandwidth(R1c, frame[F1], frame[B1]); resonatorfrequencybandwidth(Rnpc, frame[Fnp], frame[Bnp]); resonatorfrequencybandwidth(Rtpc, frame[Ftp], frame[Btp]); antiResonatorfrequencybandwidth(Rnz, frame[Fnz], frame[Bnz]); antiResonatorfrequencybandwidth(Rtz, frame[Ftz], frame[Btz]); /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rnpp, frame[Fnp], frame[Bnp]); /* begin resonatorA:put: */ aFloat = (resonatorA(Rnpp)) * ampFNV; resonators[(Rnpp * 5) - 5] = aFloat; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rtpp, frame[Ftp], frame[Btp]); /* begin resonatorA:put: */ aFloat1 = (resonatorA(Rtpp)) * ampFTV; resonators[(Rtpp * 5) - 5] = aFloat1; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R1vp, frame[F1], frame[B1]); /* begin resonatorA:put: */ aFloat2 = (resonatorA(R1vp)) * ampF1V; resonators[(R1vp * 5) - 5] = aFloat2; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2vp, frame[F2], frame[B2]); /* begin resonatorA:put: */ aFloat3 = (resonatorA(R2vp)) * ampF2V; resonators[(R2vp * 5) - 5] = aFloat3; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3vp, frame[F3], frame[B3]); /* begin resonatorA:put: */ aFloat4 = (resonatorA(R3vp)) * ampF3V; resonators[(R3vp * 5) - 5] = aFloat4; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4vp, frame[F4], frame[B4]); /* begin resonatorA:put: */ aFloat5 = (resonatorA(R4vp)) * ampF4V; resonators[(R4vp * 5) - 5] = aFloat5; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2fp, frame[F2], frame[B2f]); /* begin resonatorA:put: */ aFloat6 = (resonatorA(R2fp)) * ampF2F; resonators[(R2fp * 5) - 5] = aFloat6; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3fp, frame[F3], frame[B3f]); /* begin resonatorA:put: */ aFloat7 = (resonatorA(R3fp)) * ampF3F; resonators[(R3fp * 5) - 5] = aFloat7; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4fp, frame[F4], frame[B4f]); /* begin resonatorA:put: */ aFloat8 = (resonatorA(R4fp)) * ampF4F; resonators[(R4fp * 5) - 5] = aFloat8; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R5fp, frame[F5], frame[B5f]); /* begin resonatorA:put: */ aFloat9 = (resonatorA(R5fp)) * ampF5F; resonators[(R5fp * 5) - 5] = aFloat9; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R6fp, frame[F6], frame[B6f]); /* begin resonatorA:put: */ aFloat10 = (resonatorA(R6fp)) * ampF6F; resonators[(R6fp * 5) - 5] = aFloat10; if (pitch > 0) { /* begin linearFromdB: */ voicing = (pow(2.0,((((frame[Voicing]) - 7) - 87.0) / 6.0))) * 32.767; /* begin linearFromdB: */ parVoicing = (pow(2.0,(((frame[Voicing]) - 87.0) / 6.0))) * 32.767; turbulence = (linearFromdB(frame[Turbulence])) * 0.1; } else { voicing = parVoicing = turbulence = 0.0; } friction = (linearFromdB(frame[Friction])) * 0.25; aspiration = (linearFromdB(frame[Aspiration])) * 0.05; /* -26.0 dB */ /* Flod overall gain into output resonator (low-pass filter) */ bypass = (linearFromdB(frame[Bypass])) * 0.05; gain = (frame[Gain]) - 3; if (gain <= 0) { gain = 57; } /* begin linearFromdB: */ ampGain = (pow(2.0,((gain - 87.0) / 6.0))) * 32.767; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rout, 0, samplingRate); /* begin resonatorA:put: */ aFloat11 = (resonatorA(Rout)) * ampGain; resonators[(Rout * 5) - 5] = aFloat11; noise = nlast; index = startIndex; top = (samplesPerFrame + startIndex) - 1; while (index <= top) { /* Get low-passed random number for aspiration and friction noise */ /* radom number between -8196.0 and 8196.0 */ /* Tilt down noise spectrum by soft low-pass filter having a pole near the origin in the z-plane. */ noise = (((double) ((nextRandom()) - 32768) )) / 4.0; noise += 0.75 * nlast; /* Amplitude modulate noise (reduce noise amplitude during second half of glottal period) if voicing simultaneously present. */ nlast = noise; if (nper > nmod) { noise = noise * 0.5; } /* Compute voicing waveform. */ frictionNoise = friction * noise; /* begin glottalSource */ if (t0 == 0) { voice = 0; goto l3; } if (nper < nopen) { x0 = (a1 * x1) + (a2 * x2); x2 = x1; x1 = x0; } else { x0 = (b1 * x1) - c1; x1 = x0; } if (nper >= t0) { nper = 0; /* begin pitchSynchronousReset */ if ((frame[F0]) > 0) { /* begin voicedPitchSynchronousReset */ /* Add flutter and jitter (F0 perturbations). */ pitch = frame[F0]; /* begin addFlutter */ timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; /* begin addJitter */ pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); /* begin addFrequencyDiplophonia */ if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } if (pitch < 0) { pitch = 0; } /* Duration of period before amplitude modulation. */ t0 = ((sqInt)(samplingRate / pitch)); nmod = t0; if ((frame[Voicing]) > 0) { nmod = ((sqInt) nmod >> 1); } /* Set the LF glottal pulse model parameters. */ nopen = ((sqInt)(t0 * (frame[Ro]))); /* begin ro:ra:rk: */ te = ((sqInt)(t0 * (frame[Ro]))); ro = (((double) te )) / (((double) t0 )); rk = frame[Rk]; ra = frame[Ra]; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } /* begin addShimmer */ /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } /* begin addAmplitudeDiplophonia */ if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } periodCount = (periodCount + 1) % 65535; } else { t0 = 1; nmod = t0; } } nper += 1; voice = x0; l3: /* end glottalSource */; /* Add turbulence during glottal open phase. Use random rather than noise because noise is low-passed. */ vlast = voice; if (nper < nopen) { voice += (turbulence * (((double) ((nextRandom()) - 32768) ))) / 4.0; } glotout = voicing * voice; /* Compute aspiration amplitude and add to voicing source. */ parGlotout = parVoicing * voice; aspirationNoise = aspiration * noise; glotout += aspirationNoise; /* Cascade vocal tract, excited by laryngeal sources. Nasal antiresonator, nasal resonator, trachearl antirresonator, tracheal resonator, then formants F8, F7, F6, F5, F4, F3, F2, F1. */ parGlotout += aspirationNoise; /* begin cascadeBranch: */ if (!(cascade > 0)) { out = 0.0; goto l4; } /* begin antiResonator:value: */ answer12 = (((resonatorA(Rnz)) * glotout) + ((resonatorB(Rnz)) * ((p112 = resonatorP1(Rnz))))) + ((resonatorC(Rnz)) * (resonatorP2(Rnz))); /* begin resonatorP2:put: */ resonators[(Rnz * 5) - 1] = p112; /* begin resonatorP1:put: */ resonators[(Rnz * 5) - 2] = glotout; out1 = answer12; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer10 = (((resonatorA(Rnpc)) * out1) + ((resonatorB(Rnpc)) * ((p110 = resonatorP1(Rnpc))))) + ((resonatorC(Rnpc)) * (resonatorP2(Rnpc))); /* begin resonatorP2:put: */ resonators[(Rnpc * 5) - 1] = p110; /* begin resonatorP1:put: */ resonators[(Rnpc * 5) - 2] = answer10; out1 = answer10; /* begin antiResonator:value: */ answer1 = (((resonatorA(Rtz)) * out1) + ((resonatorB(Rtz)) * ((p11 = resonatorP1(Rtz))))) + ((resonatorC(Rtz)) * (resonatorP2(Rtz))); /* begin resonatorP2:put: */ resonators[(Rtz * 5) - 1] = p11; /* begin resonatorP1:put: */ resonators[(Rtz * 5) - 2] = out1; out1 = answer1; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer11 = (((resonatorA(Rtpc)) * out1) + ((resonatorB(Rtpc)) * ((p111 = resonatorP1(Rtpc))))) + ((resonatorC(Rtpc)) * (resonatorP2(Rtpc))); /* begin resonatorP2:put: */ resonators[(Rtpc * 5) - 1] = p111; /* begin resonatorP1:put: */ resonators[(Rtpc * 5) - 2] = answer11; out1 = answer11; if (cascade >= 8) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer2 = (((resonatorA(R8c)) * out1) + ((resonatorB(R8c)) * ((p12 = resonatorP1(R8c))))) + ((resonatorC(R8c)) * (resonatorP2(R8c))); /* begin resonatorP2:put: */ resonators[(R8c * 5) - 1] = p12; /* begin resonatorP1:put: */ resonators[(R8c * 5) - 2] = answer2; out1 = answer2; } if (cascade >= 7) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer3 = (((resonatorA(R7c)) * out1) + ((resonatorB(R7c)) * ((p13 = resonatorP1(R7c))))) + ((resonatorC(R7c)) * (resonatorP2(R7c))); /* begin resonatorP2:put: */ resonators[(R7c * 5) - 1] = p13; /* begin resonatorP1:put: */ resonators[(R7c * 5) - 2] = answer3; out1 = answer3; } if (cascade >= 6) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer4 = (((resonatorA(R6c)) * out1) + ((resonatorB(R6c)) * ((p14 = resonatorP1(R6c))))) + ((resonatorC(R6c)) * (resonatorP2(R6c))); /* begin resonatorP2:put: */ resonators[(R6c * 5) - 1] = p14; /* begin resonatorP1:put: */ resonators[(R6c * 5) - 2] = answer4; out1 = answer4; } if (cascade >= 5) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer5 = (((resonatorA(R5c)) * out1) + ((resonatorB(R5c)) * ((p15 = resonatorP1(R5c))))) + ((resonatorC(R5c)) * (resonatorP2(R5c))); /* begin resonatorP2:put: */ resonators[(R5c * 5) - 1] = p15; /* begin resonatorP1:put: */ resonators[(R5c * 5) - 2] = answer5; out1 = answer5; } if (cascade >= 4) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer6 = (((resonatorA(R4c)) * out1) + ((resonatorB(R4c)) * ((p16 = resonatorP1(R4c))))) + ((resonatorC(R4c)) * (resonatorP2(R4c))); /* begin resonatorP2:put: */ resonators[(R4c * 5) - 1] = p16; /* begin resonatorP1:put: */ resonators[(R4c * 5) - 2] = answer6; out1 = answer6; } if (cascade >= 3) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer7 = (((resonatorA(R3c)) * out1) + ((resonatorB(R3c)) * ((p17 = resonatorP1(R3c))))) + ((resonatorC(R3c)) * (resonatorP2(R3c))); /* begin resonatorP2:put: */ resonators[(R3c * 5) - 1] = p17; /* begin resonatorP1:put: */ resonators[(R3c * 5) - 2] = answer7; out1 = answer7; } if (cascade >= 2) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer8 = (((resonatorA(R2c)) * out1) + ((resonatorB(R2c)) * ((p18 = resonatorP1(R2c))))) + ((resonatorC(R2c)) * (resonatorP2(R2c))); /* begin resonatorP2:put: */ resonators[(R2c * 5) - 1] = p18; /* begin resonatorP1:put: */ resonators[(R2c * 5) - 2] = answer8; out1 = answer8; } if (cascade >= 1) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer9 = (((resonatorA(R1c)) * out1) + ((resonatorB(R1c)) * ((p19 = resonatorP1(R1c))))) + ((resonatorC(R1c)) * (resonatorP2(R1c))); /* begin resonatorP2:put: */ resonators[(R1c * 5) - 1] = p19; /* begin resonatorP1:put: */ resonators[(R1c * 5) - 2] = answer9; out1 = answer9; } out = out1; l4: /* end cascadeBranch: */; /* Source is voicing plus aspiration. */ source = parGlotout; /* Friction-excited parallel vocal tract formants F6, F5, F4, F3, F2, outputs added with alternating sign. Sound source for other parallel resonators is friction plus first difference of voicing waveform. */ out += parallelVoicedBranch(source); source = (frictionNoise + parGlotout) - glast; glast = parGlotout; /* Apply bypas and output low-pass filter */ out = (parallelFrictionBranch(source)) - out; out = (bypass * source) - out; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer = (((resonatorA(Rout)) * out) + ((resonatorB(Rout)) * ((p1 = resonatorP1(Rout))))) + ((resonatorC(Rout)) * (resonatorP2(Rout))); /* begin resonatorP2:put: */ resonators[(Rout * 5) - 1] = p1; /* begin resonatorP1:put: */ resonators[(Rout * 5) - 2] = answer; out = answer; temp = ((sqInt)(out * ampGain)); if (temp < -32768) { temp = -32768; } if (temp > 32767) { temp = 32767; } buffer[index - 1] = temp; index += 1; samplesCount += 1; } if (!(saveTo(rcvr))) { return null; } interpreterProxy->pop(3); } static float quphicosphisinphirphid(float u, float phi, float cosphi, float sinphi, float rphid) { float expuphi; expuphi = exp(u * phi); return (expuphi * ((((rphid * ((u * u) + 1.0)) + u) * sinphi) - cosphi)) + 1.0; } static float resonatorA(sqInt index) { return resonators[(index * 5) - 5]; } static void resonatorAput(sqInt index, float aFloat) { resonators[(index * 5) - 5] = aFloat; } static float resonatorB(sqInt index) { return resonators[(index * 5) - 4]; } static void resonatorBput(sqInt index, float aFloat) { resonators[(index * 5) - 4] = aFloat; } static float resonatorC(sqInt index) { return resonators[(index * 5) - 3]; } static void resonatorCput(sqInt index, float aFloat) { resonators[(index * 5) - 3] = aFloat; } static float resonatorP1(sqInt index) { return resonators[(index * 5) - 2]; } static void resonatorP1put(sqInt index, float aFloat) { resonators[(index * 5) - 2] = aFloat; } static float resonatorP2(sqInt index) { return resonators[(index * 5) - 1]; } static void resonatorP2put(sqInt index, float aFloat) { resonators[(index * 5) - 1] = aFloat; } /* Convert formant frequencies and bandwidth into resonator difference equation coefficients. */ static void resonatorfrequencybandwidth(sqInt index, float freq, float bw) { float a; double arg; float b; float c; float r; arg = ((0.0 - PI) / samplingRate) * bw; r = exp(arg); c = 0.0 - (r * r); arg = ((PI * 2.0) / samplingRate) * freq; b = (r * (cos(arg))) * 2.0; a = (1.0 - b) - c; /* begin resonatorA:put: */ resonators[(index * 5) - 5] = a; /* begin resonatorB:put: */ resonators[(index * 5) - 4] = b; /* begin resonatorC:put: */ resonators[(index * 5) - 3] = c; } /* Convert formant frequencies and bandwidth into resonator difference equation coefficients. */ static void resonatorfrequencybandwidthgain(sqInt index, float freq, float bw, float gain) { float aFloat; resonatorfrequencybandwidth(index, freq, bw); /* begin resonatorA:put: */ aFloat = (resonatorA(index)) * gain; resonators[(index * 5) - 5] = aFloat; } static float resonatorvalue(sqInt index, float aFloat) { float answer; float p1; /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer = (((resonatorA(index)) * aFloat) + ((resonatorB(index)) * ((p1 = resonatorP1(index))))) + ((resonatorC(index)) * (resonatorP2(index))); /* begin resonatorP2:put: */ resonators[(index * 5) - 1] = p1; /* begin resonatorP1:put: */ resonators[(index * 5) - 2] = answer; return answer; } static void rorark(float roNumber, float raNumber, float rkNumber) { float cosphi; float d; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float gamma; float gammapwr; sqInt ingore; float phi; float qa; float qb; float qc; float qzero; float r; float ra; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; sqInt te; float theta; float u; float ua; float ub; float uc; te = ((sqInt)(t0 * roNumber)); ro = (((double) te )) / (((double) t0 )); rk = rkNumber; ra = raNumber; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } } static sqInt saveTo(sqInt origKlattOop) { sqInt a1Oop; sqInt a2Oop; sqInt b1Oop; sqInt c1Oop; sqInt glastOop; sqInt klattOop; sqInt nlastOop; sqInt pitchOop; sqInt vlastOop; sqInt x1Oop; sqInt x2Oop; interpreterProxy->pushRemappableOop(origKlattOop); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(pitch)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(a1)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(a2)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(x1)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(x2)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(b1)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(c1)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(glast)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(vlast)); nlastOop = interpreterProxy->floatObjectOf(nlast); vlastOop = interpreterProxy->popRemappableOop(); glastOop = interpreterProxy->popRemappableOop(); c1Oop = interpreterProxy->popRemappableOop(); b1Oop = interpreterProxy->popRemappableOop(); x2Oop = interpreterProxy->popRemappableOop(); x1Oop = interpreterProxy->popRemappableOop(); a2Oop = interpreterProxy->popRemappableOop(); a1Oop = interpreterProxy->popRemappableOop(); pitchOop = interpreterProxy->popRemappableOop(); klattOop = interpreterProxy->popRemappableOop(); if (interpreterProxy->failed()) { return 0; } interpreterProxy->storePointerofObjectwithValue(2, klattOop, pitchOop); interpreterProxy->storeIntegerofObjectwithValue(3, klattOop, t0); interpreterProxy->storeIntegerofObjectwithValue(4, klattOop, nper); interpreterProxy->storeIntegerofObjectwithValue(5, klattOop, nopen); interpreterProxy->storeIntegerofObjectwithValue(6, klattOop, nmod); interpreterProxy->storePointerofObjectwithValue(7, klattOop, a1Oop); interpreterProxy->storePointerofObjectwithValue(8, klattOop, a2Oop); interpreterProxy->storePointerofObjectwithValue(9, klattOop, x1Oop); interpreterProxy->storePointerofObjectwithValue(10, klattOop, x2Oop); interpreterProxy->storePointerofObjectwithValue(11, klattOop, b1Oop); interpreterProxy->storePointerofObjectwithValue(12, klattOop, c1Oop); interpreterProxy->storePointerofObjectwithValue(13, klattOop, glastOop); interpreterProxy->storePointerofObjectwithValue(14, klattOop, vlastOop); interpreterProxy->storePointerofObjectwithValue(15, klattOop, nlastOop); interpreterProxy->storeIntegerofObjectwithValue(16, klattOop, periodCount); interpreterProxy->storeIntegerofObjectwithValue(17, klattOop, samplesCount); interpreterProxy->storeIntegerofObjectwithValue(18, klattOop, seed); return (interpreterProxy->failed()) == 0; } static void setCurrentFrame(float *aKlattFrame) { float aFloat; float aFloat1; float aFloat10; float aFloat2; float aFloat3; float aFloat4; float aFloat5; float aFloat6; float aFloat7; float aFloat8; float aFloat9; float ampF1V; float ampF2F; float ampF2V; float ampF3F; float ampF3V; float ampF4F; float ampF4V; float ampF5F; float ampF6F; float ampFNV; float ampFTV; /* Fudge factors... */ frame = aKlattFrame; /* -4.44 dB */ ampFNV = (linearFromdB(frame[Anv])) * 0.6; /* -4.44 dB */ ampFTV = (linearFromdB(frame[Atv])) * 0.6; /* -7.96 dB */ ampF1V = (linearFromdB(frame[A1v])) * 0.4; /* -16.5 dB */ ampF2V = (linearFromdB(frame[A2v])) * 0.15; /* -24.4 dB */ ampF3V = (linearFromdB(frame[A3v])) * 0.06; /* -28.0 dB */ ampF4V = (linearFromdB(frame[A4v])) * 0.04; /* -16.5 dB */ ampF2F = (linearFromdB(frame[A2f])) * 0.15; /* -24.4 dB */ ampF3F = (linearFromdB(frame[A3f])) * 0.06; /* -28.0 dB */ ampF4F = (linearFromdB(frame[A4f])) * 0.04; /* -33.2 dB */ ampF5F = (linearFromdB(frame[A5f])) * 0.022; /* -30.5 dB */ /* Set coefficients of variable cascade resonators */ ampF6F = (linearFromdB(frame[A6f])) * 0.03; if (cascade >= 8) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R8c, 7500, 600); } else { cascade = 6; } } if (cascade >= 7) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R7c, 6500, 500); } else { cascade = 6; } } if (cascade >= 6) { resonatorfrequencybandwidth(R6c, frame[F6], frame[B6]); } if (cascade >= 5) { resonatorfrequencybandwidth(R5c, frame[F5], frame[B5]); } resonatorfrequencybandwidth(R4c, frame[F4], frame[B4]); resonatorfrequencybandwidth(R3c, frame[F3], frame[B3]); resonatorfrequencybandwidth(R2c, frame[F2], frame[B2]); resonatorfrequencybandwidth(R1c, frame[F1], frame[B1]); resonatorfrequencybandwidth(Rnpc, frame[Fnp], frame[Bnp]); resonatorfrequencybandwidth(Rtpc, frame[Ftp], frame[Btp]); antiResonatorfrequencybandwidth(Rnz, frame[Fnz], frame[Bnz]); antiResonatorfrequencybandwidth(Rtz, frame[Ftz], frame[Btz]); /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rnpp, frame[Fnp], frame[Bnp]); /* begin resonatorA:put: */ aFloat = (resonatorA(Rnpp)) * ampFNV; resonators[(Rnpp * 5) - 5] = aFloat; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rtpp, frame[Ftp], frame[Btp]); /* begin resonatorA:put: */ aFloat1 = (resonatorA(Rtpp)) * ampFTV; resonators[(Rtpp * 5) - 5] = aFloat1; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R1vp, frame[F1], frame[B1]); /* begin resonatorA:put: */ aFloat2 = (resonatorA(R1vp)) * ampF1V; resonators[(R1vp * 5) - 5] = aFloat2; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2vp, frame[F2], frame[B2]); /* begin resonatorA:put: */ aFloat3 = (resonatorA(R2vp)) * ampF2V; resonators[(R2vp * 5) - 5] = aFloat3; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3vp, frame[F3], frame[B3]); /* begin resonatorA:put: */ aFloat4 = (resonatorA(R3vp)) * ampF3V; resonators[(R3vp * 5) - 5] = aFloat4; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4vp, frame[F4], frame[B4]); /* begin resonatorA:put: */ aFloat5 = (resonatorA(R4vp)) * ampF4V; resonators[(R4vp * 5) - 5] = aFloat5; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2fp, frame[F2], frame[B2f]); /* begin resonatorA:put: */ aFloat6 = (resonatorA(R2fp)) * ampF2F; resonators[(R2fp * 5) - 5] = aFloat6; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3fp, frame[F3], frame[B3f]); /* begin resonatorA:put: */ aFloat7 = (resonatorA(R3fp)) * ampF3F; resonators[(R3fp * 5) - 5] = aFloat7; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4fp, frame[F4], frame[B4f]); /* begin resonatorA:put: */ aFloat8 = (resonatorA(R4fp)) * ampF4F; resonators[(R4fp * 5) - 5] = aFloat8; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R5fp, frame[F5], frame[B5f]); /* begin resonatorA:put: */ aFloat9 = (resonatorA(R5fp)) * ampF5F; resonators[(R5fp * 5) - 5] = aFloat9; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R6fp, frame[F6], frame[B6f]); /* begin resonatorA:put: */ aFloat10 = (resonatorA(R6fp)) * ampF6F; resonators[(R6fp * 5) - 5] = aFloat10; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void synthesizeFrameintostartingAt(float *aKlattFrame, short *buffer, sqInt startIndex) { float aFloat; float aFloat1; float aFloat10; float aFloat11; float aFloat2; float aFloat3; float aFloat4; float aFloat5; float aFloat6; float aFloat7; float aFloat8; float aFloat9; float ampF1V; float ampF2F; float ampF2V; float ampF3F; float ampF3V; float ampF4F; float ampF4V; float ampF5F; float ampF6F; float ampFNV; float ampFTV; float ampGain; float answer; double answer1; float answer10; float answer11; double answer12; float answer2; float answer3; float answer4; float answer5; float answer6; float answer7; float answer8; float answer9; float asin; float aspiration; float aspirationNoise; float bsin; float bypass; float cosphi; float csin; float d; double deltaF0; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float friction; float frictionNoise; float gain; float gamma; float gammapwr; float glotout; sqInt index; sqInt ingore; float noise; float out; float out1; float p1; double p11; float p110; float p111; double p112; float p12; float p13; float p14; float p15; float p16; float p17; float p18; float p19; float parGlotout; float parVoicing; float phi; float qa; float qb; float qc; float qzero; float r; float ra; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; float source; sqInt te; sqInt temp; float theta; float timeCount; sqInt top; float turbulence; float u; float ua; float ub; float uc; float voice; float voicing; float x0; /* begin setCurrentFrame: */ /* Fudge factors... */ frame = aKlattFrame; /* -4.44 dB */ ampFNV = (linearFromdB(frame[Anv])) * 0.6; /* -4.44 dB */ ampFTV = (linearFromdB(frame[Atv])) * 0.6; /* -7.96 dB */ ampF1V = (linearFromdB(frame[A1v])) * 0.4; /* -16.5 dB */ ampF2V = (linearFromdB(frame[A2v])) * 0.15; /* -24.4 dB */ ampF3V = (linearFromdB(frame[A3v])) * 0.06; /* -28.0 dB */ ampF4V = (linearFromdB(frame[A4v])) * 0.04; /* -16.5 dB */ ampF2F = (linearFromdB(frame[A2f])) * 0.15; /* -24.4 dB */ ampF3F = (linearFromdB(frame[A3f])) * 0.06; /* -28.0 dB */ ampF4F = (linearFromdB(frame[A4f])) * 0.04; /* -33.2 dB */ ampF5F = (linearFromdB(frame[A5f])) * 0.022; /* -30.5 dB */ /* Set coefficients of variable cascade resonators */ ampF6F = (linearFromdB(frame[A6f])) * 0.03; if (cascade >= 8) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R8c, 7500, 600); } else { cascade = 6; } } if (cascade >= 7) { if (samplingRate >= 16000) { resonatorfrequencybandwidth(R7c, 6500, 500); } else { cascade = 6; } } if (cascade >= 6) { resonatorfrequencybandwidth(R6c, frame[F6], frame[B6]); } if (cascade >= 5) { resonatorfrequencybandwidth(R5c, frame[F5], frame[B5]); } resonatorfrequencybandwidth(R4c, frame[F4], frame[B4]); resonatorfrequencybandwidth(R3c, frame[F3], frame[B3]); resonatorfrequencybandwidth(R2c, frame[F2], frame[B2]); resonatorfrequencybandwidth(R1c, frame[F1], frame[B1]); resonatorfrequencybandwidth(Rnpc, frame[Fnp], frame[Bnp]); resonatorfrequencybandwidth(Rtpc, frame[Ftp], frame[Btp]); antiResonatorfrequencybandwidth(Rnz, frame[Fnz], frame[Bnz]); antiResonatorfrequencybandwidth(Rtz, frame[Ftz], frame[Btz]); /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rnpp, frame[Fnp], frame[Bnp]); /* begin resonatorA:put: */ aFloat = (resonatorA(Rnpp)) * ampFNV; resonators[(Rnpp * 5) - 5] = aFloat; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rtpp, frame[Ftp], frame[Btp]); /* begin resonatorA:put: */ aFloat1 = (resonatorA(Rtpp)) * ampFTV; resonators[(Rtpp * 5) - 5] = aFloat1; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R1vp, frame[F1], frame[B1]); /* begin resonatorA:put: */ aFloat2 = (resonatorA(R1vp)) * ampF1V; resonators[(R1vp * 5) - 5] = aFloat2; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2vp, frame[F2], frame[B2]); /* begin resonatorA:put: */ aFloat3 = (resonatorA(R2vp)) * ampF2V; resonators[(R2vp * 5) - 5] = aFloat3; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3vp, frame[F3], frame[B3]); /* begin resonatorA:put: */ aFloat4 = (resonatorA(R3vp)) * ampF3V; resonators[(R3vp * 5) - 5] = aFloat4; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4vp, frame[F4], frame[B4]); /* begin resonatorA:put: */ aFloat5 = (resonatorA(R4vp)) * ampF4V; resonators[(R4vp * 5) - 5] = aFloat5; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R2fp, frame[F2], frame[B2f]); /* begin resonatorA:put: */ aFloat6 = (resonatorA(R2fp)) * ampF2F; resonators[(R2fp * 5) - 5] = aFloat6; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R3fp, frame[F3], frame[B3f]); /* begin resonatorA:put: */ aFloat7 = (resonatorA(R3fp)) * ampF3F; resonators[(R3fp * 5) - 5] = aFloat7; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R4fp, frame[F4], frame[B4f]); /* begin resonatorA:put: */ aFloat8 = (resonatorA(R4fp)) * ampF4F; resonators[(R4fp * 5) - 5] = aFloat8; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R5fp, frame[F5], frame[B5f]); /* begin resonatorA:put: */ aFloat9 = (resonatorA(R5fp)) * ampF5F; resonators[(R5fp * 5) - 5] = aFloat9; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(R6fp, frame[F6], frame[B6f]); /* begin resonatorA:put: */ aFloat10 = (resonatorA(R6fp)) * ampF6F; resonators[(R6fp * 5) - 5] = aFloat10; if (pitch > 0) { /* begin linearFromdB: */ voicing = (pow(2.0,((((frame[Voicing]) - 7) - 87.0) / 6.0))) * 32.767; /* begin linearFromdB: */ parVoicing = (pow(2.0,(((frame[Voicing]) - 87.0) / 6.0))) * 32.767; turbulence = (linearFromdB(frame[Turbulence])) * 0.1; } else { voicing = parVoicing = turbulence = 0.0; } friction = (linearFromdB(frame[Friction])) * 0.25; aspiration = (linearFromdB(frame[Aspiration])) * 0.05; /* -26.0 dB */ /* Flod overall gain into output resonator (low-pass filter) */ bypass = (linearFromdB(frame[Bypass])) * 0.05; gain = (frame[Gain]) - 3; if (gain <= 0) { gain = 57; } /* begin linearFromdB: */ ampGain = (pow(2.0,((gain - 87.0) / 6.0))) * 32.767; /* begin resonator:frequency:bandwidth:gain: */ resonatorfrequencybandwidth(Rout, 0, samplingRate); /* begin resonatorA:put: */ aFloat11 = (resonatorA(Rout)) * ampGain; resonators[(Rout * 5) - 5] = aFloat11; noise = nlast; index = startIndex; top = (samplesPerFrame + startIndex) - 1; while (index <= top) { /* Get low-passed random number for aspiration and friction noise */ /* radom number between -8196.0 and 8196.0 */ /* Tilt down noise spectrum by soft low-pass filter having a pole near the origin in the z-plane. */ noise = (((double) ((nextRandom()) - 32768) )) / 4.0; noise += 0.75 * nlast; /* Amplitude modulate noise (reduce noise amplitude during second half of glottal period) if voicing simultaneously present. */ nlast = noise; if (nper > nmod) { noise = noise * 0.5; } /* Compute voicing waveform. */ frictionNoise = friction * noise; /* begin glottalSource */ if (t0 == 0) { voice = 0; goto l1; } if (nper < nopen) { x0 = (a1 * x1) + (a2 * x2); x2 = x1; x1 = x0; } else { x0 = (b1 * x1) - c1; x1 = x0; } if (nper >= t0) { nper = 0; /* begin pitchSynchronousReset */ if ((frame[F0]) > 0) { /* begin voicedPitchSynchronousReset */ /* Add flutter and jitter (F0 perturbations). */ pitch = frame[F0]; /* begin addFlutter */ timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; /* begin addJitter */ pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); /* begin addFrequencyDiplophonia */ if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } if (pitch < 0) { pitch = 0; } /* Duration of period before amplitude modulation. */ t0 = ((sqInt)(samplingRate / pitch)); nmod = t0; if ((frame[Voicing]) > 0) { nmod = ((sqInt) nmod >> 1); } /* Set the LF glottal pulse model parameters. */ nopen = ((sqInt)(t0 * (frame[Ro]))); /* begin ro:ra:rk: */ te = ((sqInt)(t0 * (frame[Ro]))); ro = (((double) te )) / (((double) t0 )); rk = frame[Rk]; ra = frame[Ra]; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } /* begin addShimmer */ /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } /* begin addAmplitudeDiplophonia */ if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } periodCount = (periodCount + 1) % 65535; } else { t0 = 1; nmod = t0; } } nper += 1; voice = x0; l1: /* end glottalSource */; /* Add turbulence during glottal open phase. Use random rather than noise because noise is low-passed. */ vlast = voice; if (nper < nopen) { voice += (turbulence * (((double) ((nextRandom()) - 32768) ))) / 4.0; } glotout = voicing * voice; /* Compute aspiration amplitude and add to voicing source. */ parGlotout = parVoicing * voice; aspirationNoise = aspiration * noise; glotout += aspirationNoise; /* Cascade vocal tract, excited by laryngeal sources. Nasal antiresonator, nasal resonator, trachearl antirresonator, tracheal resonator, then formants F8, F7, F6, F5, F4, F3, F2, F1. */ parGlotout += aspirationNoise; /* begin cascadeBranch: */ if (!(cascade > 0)) { out = 0.0; goto l2; } /* begin antiResonator:value: */ answer12 = (((resonatorA(Rnz)) * glotout) + ((resonatorB(Rnz)) * ((p112 = resonatorP1(Rnz))))) + ((resonatorC(Rnz)) * (resonatorP2(Rnz))); /* begin resonatorP2:put: */ resonators[(Rnz * 5) - 1] = p112; /* begin resonatorP1:put: */ resonators[(Rnz * 5) - 2] = glotout; out1 = answer12; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer10 = (((resonatorA(Rnpc)) * out1) + ((resonatorB(Rnpc)) * ((p110 = resonatorP1(Rnpc))))) + ((resonatorC(Rnpc)) * (resonatorP2(Rnpc))); /* begin resonatorP2:put: */ resonators[(Rnpc * 5) - 1] = p110; /* begin resonatorP1:put: */ resonators[(Rnpc * 5) - 2] = answer10; out1 = answer10; /* begin antiResonator:value: */ answer1 = (((resonatorA(Rtz)) * out1) + ((resonatorB(Rtz)) * ((p11 = resonatorP1(Rtz))))) + ((resonatorC(Rtz)) * (resonatorP2(Rtz))); /* begin resonatorP2:put: */ resonators[(Rtz * 5) - 1] = p11; /* begin resonatorP1:put: */ resonators[(Rtz * 5) - 2] = out1; out1 = answer1; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer11 = (((resonatorA(Rtpc)) * out1) + ((resonatorB(Rtpc)) * ((p111 = resonatorP1(Rtpc))))) + ((resonatorC(Rtpc)) * (resonatorP2(Rtpc))); /* begin resonatorP2:put: */ resonators[(Rtpc * 5) - 1] = p111; /* begin resonatorP1:put: */ resonators[(Rtpc * 5) - 2] = answer11; out1 = answer11; if (cascade >= 8) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer2 = (((resonatorA(R8c)) * out1) + ((resonatorB(R8c)) * ((p12 = resonatorP1(R8c))))) + ((resonatorC(R8c)) * (resonatorP2(R8c))); /* begin resonatorP2:put: */ resonators[(R8c * 5) - 1] = p12; /* begin resonatorP1:put: */ resonators[(R8c * 5) - 2] = answer2; out1 = answer2; } if (cascade >= 7) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer3 = (((resonatorA(R7c)) * out1) + ((resonatorB(R7c)) * ((p13 = resonatorP1(R7c))))) + ((resonatorC(R7c)) * (resonatorP2(R7c))); /* begin resonatorP2:put: */ resonators[(R7c * 5) - 1] = p13; /* begin resonatorP1:put: */ resonators[(R7c * 5) - 2] = answer3; out1 = answer3; } if (cascade >= 6) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer4 = (((resonatorA(R6c)) * out1) + ((resonatorB(R6c)) * ((p14 = resonatorP1(R6c))))) + ((resonatorC(R6c)) * (resonatorP2(R6c))); /* begin resonatorP2:put: */ resonators[(R6c * 5) - 1] = p14; /* begin resonatorP1:put: */ resonators[(R6c * 5) - 2] = answer4; out1 = answer4; } if (cascade >= 5) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer5 = (((resonatorA(R5c)) * out1) + ((resonatorB(R5c)) * ((p15 = resonatorP1(R5c))))) + ((resonatorC(R5c)) * (resonatorP2(R5c))); /* begin resonatorP2:put: */ resonators[(R5c * 5) - 1] = p15; /* begin resonatorP1:put: */ resonators[(R5c * 5) - 2] = answer5; out1 = answer5; } if (cascade >= 4) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer6 = (((resonatorA(R4c)) * out1) + ((resonatorB(R4c)) * ((p16 = resonatorP1(R4c))))) + ((resonatorC(R4c)) * (resonatorP2(R4c))); /* begin resonatorP2:put: */ resonators[(R4c * 5) - 1] = p16; /* begin resonatorP1:put: */ resonators[(R4c * 5) - 2] = answer6; out1 = answer6; } if (cascade >= 3) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer7 = (((resonatorA(R3c)) * out1) + ((resonatorB(R3c)) * ((p17 = resonatorP1(R3c))))) + ((resonatorC(R3c)) * (resonatorP2(R3c))); /* begin resonatorP2:put: */ resonators[(R3c * 5) - 1] = p17; /* begin resonatorP1:put: */ resonators[(R3c * 5) - 2] = answer7; out1 = answer7; } if (cascade >= 2) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer8 = (((resonatorA(R2c)) * out1) + ((resonatorB(R2c)) * ((p18 = resonatorP1(R2c))))) + ((resonatorC(R2c)) * (resonatorP2(R2c))); /* begin resonatorP2:put: */ resonators[(R2c * 5) - 1] = p18; /* begin resonatorP1:put: */ resonators[(R2c * 5) - 2] = answer8; out1 = answer8; } if (cascade >= 1) { /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer9 = (((resonatorA(R1c)) * out1) + ((resonatorB(R1c)) * ((p19 = resonatorP1(R1c))))) + ((resonatorC(R1c)) * (resonatorP2(R1c))); /* begin resonatorP2:put: */ resonators[(R1c * 5) - 1] = p19; /* begin resonatorP1:put: */ resonators[(R1c * 5) - 2] = answer9; out1 = answer9; } out = out1; l2: /* end cascadeBranch: */; /* Source is voicing plus aspiration. */ source = parGlotout; /* Friction-excited parallel vocal tract formants F6, F5, F4, F3, F2, outputs added with alternating sign. Sound source for other parallel resonators is friction plus first difference of voicing waveform. */ out += parallelVoicedBranch(source); source = (frictionNoise + parGlotout) - glast; glast = parGlotout; /* Apply bypas and output low-pass filter */ out = (parallelFrictionBranch(source)) - out; out = (bypass * source) - out; /* begin resonator:value: */ /* (p1 between: -100000 and: 100000) ifFalse: [self halt]. (answer between: -100000 and: 100000) ifFalse: [self halt]. */ answer = (((resonatorA(Rout)) * out) + ((resonatorB(Rout)) * ((p1 = resonatorP1(Rout))))) + ((resonatorC(Rout)) * (resonatorP2(Rout))); /* begin resonatorP2:put: */ resonators[(Rout * 5) - 1] = p1; /* begin resonatorP1:put: */ resonators[(Rout * 5) - 2] = answer; out = answer; temp = ((sqInt)(out * ampGain)); if (temp < -32768) { temp = -32768; } if (temp > 32767) { temp = 32767; } buffer[index - 1] = temp; index += 1; samplesCount += 1; } } /* Set the pitch. */ static void voicedPitchSynchronousReset(void) { float asin; float bsin; float cosphi; float csin; float d; double deltaF0; float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float gamma; float gammapwr; sqInt ingore; float phi; float qa; float qb; float qc; float qzero; float r; float ra; float rho; float rk; float ro; float rphid; float s0; float s1; float s2; float sinphi; sqInt te; float theta; float timeCount; float u; float ua; float ub; float uc; /* Add flutter and jitter (F0 perturbations). */ pitch = frame[F0]; /* begin addFlutter */ timeCount = (((float) samplesCount)) / (((float) samplingRate)); asin = sin(((2.0 * PI) * 12.7) * timeCount); bsin = sin(((2.0 * PI) * 7.1) * timeCount); csin = sin(((2.0 * PI) * 4.7) * timeCount); deltaF0 = ((((frame[Flutter]) * 2.0) * (frame[F0])) / 100.0) * ((asin + bsin) + csin); pitch += deltaF0; /* begin addJitter */ pitch += ((((nextRandom()) - 32767) * (frame[Jitter])) / 32768.0) * (frame[F0]); /* begin addFrequencyDiplophonia */ if ((periodCount % 2) == 0) { pitch += ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } else { pitch -= ((frame[Diplophonia]) * (frame[F0])) * (1.0 - (frame[Ro])); } if (pitch < 0) { pitch = 0; } /* Duration of period before amplitude modulation. */ t0 = ((sqInt)(samplingRate / pitch)); nmod = t0; if ((frame[Voicing]) > 0) { nmod = ((sqInt) nmod >> 1); } /* Set the LF glottal pulse model parameters. */ nopen = ((sqInt)(t0 * (frame[Ro]))); /* begin ro:ra:rk: */ te = ((sqInt)(t0 * (frame[Ro]))); ro = (((double) te )) / (((double) t0 )); rk = frame[Rk]; ra = frame[Ra]; if (ra <= 0.0) { d = 1.0; } else { r = (1.0 - ro) / ra; d = 1.0 - (r / ((exp(r)) - 1.0)); } phi = PI * (rk + 1.0); cosphi = cos(phi); sinphi = sin(phi); rphid = ((ra / ro) * phi) * d; /* begin zeroQphi:cosphi:sinphi:rphid: */ /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } u = (ub + ua) / 2.0; theta = phi / te; rho = exp(u * theta); a1 = (2.0 * (cos(theta))) * rho; a2 = 0.0 - (rho * rho); x2 = 0.0; x1 = rho * (sin(theta)); gamma = exp(-1.0 / (ra * t0)); gammapwr = pow(gamma,(t0 - te)); b1 = gamma; c1 = ((1.0 - gamma) * gammapwr) / (1.0 - gammapwr); /* begin normalizeGlottalPulse */ s0 = 0.0; s1 = x1; s2 = x2; for (ingore = 1; ingore <= nopen; ingore += 1) { s0 = (a1 * s1) + (a2 * s2); s2 = s1; s1 = s0; } if (!(s0 == 0.0)) { x1 = (x1 / s0) * 10000.0; } /* begin addShimmer */ /* x1 must be <= 0 */ x1 += ((((nextRandom()) - 32767) * (frame[Shimmer])) / 32768.0) * x1; if (x1 > 0) { x1 = 0; } /* begin addAmplitudeDiplophonia */ if (!((periodCount % 2) == 0)) { /* x1 must be <= 0 */ x1 = x1 * (1.0 - (frame[Diplophonia])); if (x1 > 0) { x1 = 0; } } } static float zeroQphicosphisinphirphid(float phi, float cosphi, float sinphi, float rphid) { float expuphi; float expuphi1; float expuphi2; float expuphi3; float expuphi4; float expuphi5; float qa; float qb; float qc; float qzero; float ua; float ub; float uc; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi5 = exp(0 * phi); qzero = (expuphi5 * ((((rphid * ((0 * 0) + 1.0)) + 0) * sinphi) - cosphi)) + 1.0; if (qzero > 0) { ua = 0; ub = 1; qa = qzero; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi1 = exp(ub * phi); qb = (expuphi1 * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; while (qb > 0) { ua = ub; qa = qb; ub = ub * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi = exp(ub * phi); qb = (expuphi * ((((rphid * ((ub * ub) + 1.0)) + ub) * sinphi) - cosphi)) + 1.0; } } else { ua = -1; ub = 0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi3 = exp(ua * phi); qa = (expuphi3 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; qb = qzero; while (qa < 0) { ub = ua; qb = qa; ua = ua * 2; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi2 = exp(ua * phi); qa = (expuphi2 * ((((rphid * ((ua * ua) + 1.0)) + ua) * sinphi) - cosphi)) + 1.0; } } while ((ub - ua) > Epsilon) { uc = (ub + ua) / 2.0; /* begin qu:phi:cosphi:sinphi:rphid: */ expuphi4 = exp(uc * phi); qc = (expuphi4 * ((((rphid * ((uc * uc) + 1.0)) + uc) * sinphi) - cosphi)) + 1.0; if (qc > 0) { ua = uc; qa = qc; } else { ub = uc; qb = qc; } } return (ub + ua) / 2.0; } #ifdef SQUEAK_BUILTIN_PLUGIN void* Klatt_exports[][3] = { {"Klatt", "getModuleName", (void*)getModuleName}, {"Klatt", "primitiveSynthesizeFrameIntoStartingAt", (void*)primitiveSynthesizeFrameIntoStartingAt}, {"Klatt", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/LargeIntegers/LargeIntegers.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from LargeIntegersPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "LargeIntegersPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt anyBitOfBytesfromto(sqInt aBytesOop, sqInt start, sqInt stopArg); static sqInt byteSizeOfBytes(sqInt bytesOop); static sqInt bytesOrIntgrowTo(sqInt oop, sqInt len); static sqInt bytesgrowTo(sqInt aBytesObject, sqInt newLen); static sqInt bytesLshift(sqInt aBytesOop, sqInt shiftCount); static sqInt bytesRshiftbyteslookfirst(sqInt aBytesOop, sqInt anInteger, sqInt b, sqInt a); static sqInt cByteOpshortlenlongleninto(sqInt opIndex, unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes); static int cBytesCopyFromtolen(unsigned char * pFrom, unsigned char * pTo, sqInt len); static sqInt cBytesHighBitlen(unsigned char * pByte, sqInt len); static int cBytesLshiftfromlentolen(sqInt shiftCount, unsigned char * pFrom, sqInt lenFrom, unsigned char * pTo, sqInt lenTo); static int cBytesReplacefromtowithstartingAt(unsigned char * pTo, sqInt start, sqInt stop, unsigned char * pFrom, sqInt repStart); static void cCopyIntValtoBytes(sqInt val, sqInt bytes); static void cCoreBytesRshiftCountnmfbytesfromlentolen(sqInt count, sqInt n, sqInt m, sqInt f, sqInt b, unsigned char * pFrom, sqInt fromLen, unsigned char * pTo, sqInt toLen); static void cCoreDigitDivDivlenremlenquolen(unsigned char * pDiv, sqInt divLen, unsigned char * pRem, sqInt remLen, unsigned char * pQuo, sqInt quoLen); static unsigned char cDigitAddlenwithleninto(unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes); static sqInt cDigitComparewithlen(unsigned char * pFirst, unsigned char * pSecond, sqInt len); static sqInt cDigitLengthOfCSI(sqInt csi); static unsigned char cDigitMultiplylenwithleninto(unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes); static sqInt cDigitOfCSIat(sqInt csi, sqInt ix); static void cDigitSublenwithleninto(unsigned char * pByteSmall, sqInt smallLen, unsigned char * pByteLarge, sqInt largeLen, unsigned char * pByteRes); static sqInt cHighBit(sqInt uint); static sqInt createLargeFromSmallInteger(sqInt anOop); static sqInt digitAddLargewith(sqInt firstInteger, sqInt secondInteger); static sqInt digitBitLogicwithopIndex(sqInt firstInteger, sqInt secondInteger, sqInt opIx); static sqInt digitCompareLargewith(sqInt firstInteger, sqInt secondInteger); static sqInt digitDivLargewithnegative(sqInt firstInteger, sqInt secondInteger, sqInt neg); static sqInt digitLength(sqInt oop); static sqInt digitMultiplyLargewithnegative(sqInt firstInteger, sqInt secondInteger, sqInt neg); static sqInt digitOfBytesat(sqInt aBytesOop, sqInt ix); static sqInt digitOfat(sqInt oop, sqInt ix); static sqInt digitSubLargewith(sqInt firstInteger, sqInt secondInteger); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt highBitOfBytes(sqInt aBytesOop); static void initialize(void); static sqInt isNormalized(sqInt anInteger); static sqInt msg(char *s); static sqInt negative(sqInt aLarge); static sqInt normalizeNegative(sqInt aLargeNegativeInteger); static sqInt normalizePositive(sqInt aLargePositiveInteger); static sqInt normalize(sqInt aLargeInteger); EXPORT(sqInt) primAnyBitFromTo(void); EXPORT(sqInt) primAsLargeInteger(void); EXPORT(sqInt) primCheckIfCModuleExists(void); EXPORT(sqInt) primDigitAdd(void); EXPORT(sqInt) primDigitAddWith(void); EXPORT(sqInt) primDigitBitAnd(void); EXPORT(sqInt) primDigitBitLogicWithOp(void); EXPORT(sqInt) primDigitBitOr(void); EXPORT(sqInt) primDigitBitShift(void); EXPORT(sqInt) primDigitBitShiftMagnitude(void); EXPORT(sqInt) primDigitBitXor(void); EXPORT(sqInt) primDigitCompare(void); EXPORT(sqInt) primDigitCompareWith(void); EXPORT(sqInt) primDigitDivNegative(void); EXPORT(sqInt) primDigitDivWithNegative(void); EXPORT(sqInt) primDigitMultiplyNegative(void); EXPORT(sqInt) primDigitMultiplyWithNegative(void); EXPORT(sqInt) primDigitSubtract(void); EXPORT(sqInt) primDigitSubtractWith(void); EXPORT(sqInt) primGetModuleName(void); EXPORT(sqInt) primNormalize(void); EXPORT(sqInt) primNormalizeNegative(void); EXPORT(sqInt) primNormalizePositive(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void sqAssert(sqInt aBool); static sqInt think(void); static sqInt unsafeByteOfat(sqInt bytesOop, sqInt ix); EXPORT(sqInt) _primDigitBitShift(void); /*** Variables ***/ static const int andOpIndex = 0; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "LargeIntegers v1.5 VMMaker-oscog.dtl.57 (i)" #else "LargeIntegers v1.5 VMMaker-oscog.dtl.57 (e)" #endif ; static const int orOpIndex = 1; static const int xorOpIndex = 2; /* Argument has to be aBytesOop! */ /* Tests for any magnitude bits in the interval from start to stopArg. */ static sqInt anyBitOfBytesfromto(sqInt aBytesOop, sqInt start, sqInt stopArg) { sqInt digit; sqInt firstByteIx; sqInt ix; sqInt lastByteIx; sqInt leftShift; sqInt magnitude; sqInt mask; unsigned char *pointer; sqInt rightShift; sqInt stop; /* missing DebugCode */; if ((start < 1) || (stopArg < 1)) { return interpreterProxy->primitiveFail(); } magnitude = aBytesOop; stop = ((stopArg < (cBytesHighBitlen(interpreterProxy->firstIndexableField(magnitude), interpreterProxy->slotSizeOf(magnitude)))) ? stopArg : (cBytesHighBitlen(interpreterProxy->firstIndexableField(magnitude), interpreterProxy->slotSizeOf(magnitude)))); if (start > stop) { return 0; } firstByteIx = (((sqInt) (start - 1) >> 3)) + 1; lastByteIx = (((sqInt) (stop - 1) >> 3)) + 1; rightShift = 0 - ((start - 1) % 8); leftShift = 7 - ((stop - 1) % 8); if (firstByteIx == lastByteIx) { mask = ((((0 - rightShift) < 0) ? ((usqInt) 255 >> -(0 - rightShift)) : ((usqInt) 255 << (0 - rightShift)))) & ((((0 - leftShift) < 0) ? ((usqInt) 255 >> -(0 - leftShift)) : ((usqInt) 255 << (0 - leftShift)))); /* begin digitOfBytes:at: */ if (firstByteIx > (interpreterProxy->slotSizeOf(magnitude))) { digit = 0; goto l1; } else { digit = ((pointer = interpreterProxy->firstIndexableField(magnitude)))[firstByteIx - 1]; goto l1; } l1: /* end digitOfBytes:at: */; return (digit & mask) != 0; } if ((((rightShift < 0) ? ((usqInt) (digitOfBytesat(magnitude, firstByteIx)) >> -rightShift) : ((usqInt) (digitOfBytesat(magnitude, firstByteIx)) << rightShift))) != 0) { return 1; } for (ix = (firstByteIx + 1); ix <= (lastByteIx - 1); ix += 1) { if ((digitOfBytesat(magnitude, ix)) != 0) { return 1; } } if (((((leftShift < 0) ? ((usqInt) (digitOfBytesat(magnitude, lastByteIx)) >> -leftShift) : ((usqInt) (digitOfBytesat(magnitude, lastByteIx)) << leftShift))) & 255) != 0) { return 1; } return 0; } /* Precondition: bytesOop is not anInteger and a bytes object. */ /* Function #byteSizeOf: is used by the interpreter, be careful with name clashes... */ static sqInt byteSizeOfBytes(sqInt bytesOop) { return interpreterProxy->slotSizeOf(bytesOop); } /* Attention: this method invalidates all oop's! Only newBytes is valid at return. */ static sqInt bytesOrIntgrowTo(sqInt oop, sqInt len) { sqInt class; sqInt ix; sqInt newBytes; unsigned char * pByte; sqInt val; if ((oop & 1)) { val = (oop >> 1); if (val < 0) { class = interpreterProxy->classLargeNegativeInteger(); } else { class = interpreterProxy->classLargePositiveInteger(); } newBytes = interpreterProxy->instantiateClassindexableSize(class, len); /* begin cCopyIntVal:toBytes: */ pByte = interpreterProxy->firstIndexableField(newBytes); for (ix = 1; ix <= (cDigitLengthOfCSI(val)); ix += 1) { pByte[ix - 1] = (cDigitOfCSIat(val, ix)); } } else { newBytes = bytesgrowTo(oop, len); } return newBytes; } /* Attention: this method invalidates all oop's! Only newBytes is valid at return. */ /* Does not normalize. */ static sqInt bytesgrowTo(sqInt aBytesObject, sqInt newLen) { sqInt copyLen; sqInt newBytes; sqInt oldLen; interpreterProxy->pushRemappableOop(aBytesObject); newBytes = interpreterProxy->instantiateClassindexableSize(interpreterProxy->fetchClassOf(aBytesObject), newLen); aBytesObject = interpreterProxy->popRemappableOop(); oldLen = interpreterProxy->slotSizeOf(aBytesObject); if (oldLen < newLen) { copyLen = oldLen; } else { copyLen = newLen; } cBytesCopyFromtolen(interpreterProxy->firstIndexableField(aBytesObject), interpreterProxy->firstIndexableField(newBytes), copyLen); return newBytes; } /* Attention: this method invalidates all oop's! Only newBytes is valid at return. */ /* Does not normalize. */ static sqInt bytesLshift(sqInt aBytesOop, sqInt shiftCount) { sqInt bitShift; sqInt byteShift; sqInt carry; sqInt digit; sqInt highBit; sqInt i; sqInt lastIx; sqInt limit; sqInt mask; sqInt newBytes; sqInt newLen; sqInt oldLen; unsigned char * pFrom; unsigned char * pTo; sqInt rShift; oldLen = interpreterProxy->slotSizeOf(aBytesOop); if (((highBit = cBytesHighBitlen(interpreterProxy->firstIndexableField(aBytesOop), oldLen))) == 0) { return interpreterProxy->integerObjectOf(0); } newLen = ((sqInt) ((highBit + shiftCount) + 7) >> 3); interpreterProxy->pushRemappableOop(aBytesOop); newBytes = interpreterProxy->instantiateClassindexableSize(interpreterProxy->fetchClassOf(aBytesOop), newLen); aBytesOop = interpreterProxy->popRemappableOop(); /* begin cBytesLshift:from:len:to:len: */ pFrom = interpreterProxy->firstIndexableField(aBytesOop); pTo = interpreterProxy->firstIndexableField(newBytes); byteShift = ((sqInt) shiftCount >> 3); bitShift = shiftCount % 8; if (bitShift == 0) { /* begin cBytesReplace:from:to:with:startingAt: */ cBytesCopyFromtolen(pFrom + 0, pTo + byteShift, ((newLen - 1) - byteShift) + 1); goto l1; } carry = 0; rShift = bitShift - 8; mask = (((0 - bitShift) < 0) ? ((usqInt) 255 >> -(0 - bitShift)) : ((usqInt) 255 << (0 - bitShift))); limit = byteShift - 1; for (i = 0; i <= limit; i += 1) { pTo[i] = 0; } limit = (newLen - byteShift) - 2; /* begin sqAssert: */ /* missing DebugCode */; l2: /* end sqAssert: */; for (i = 0; i <= limit; i += 1) { digit = pFrom[i]; pTo[i + byteShift] = ((((bitShift < 0) ? ((usqInt) (digit & mask) >> -bitShift) : ((usqInt) (digit & mask) << bitShift))) | carry); carry = ((rShift < 0) ? ((usqInt) digit >> -rShift) : ((usqInt) digit << rShift)); } lastIx = limit + 1; if (lastIx > (oldLen - 1)) { digit = 0; } else { digit = pFrom[lastIx]; } pTo[lastIx + byteShift] = ((((bitShift < 0) ? ((usqInt) (digit & mask) >> -bitShift) : ((usqInt) (digit & mask) << bitShift))) | carry); carry = ((rShift < 0) ? ((usqInt) digit >> -rShift) : ((usqInt) digit << rShift)); /* begin sqAssert: */ /* missing DebugCode */; l3: /* end sqAssert: */; l1: /* end cBytesLshift:from:len:to:len: */; return newBytes; } /* Attention: this method invalidates all oop's! Only newBytes is valid at return. */ /* Shift right 8*b+anInteger bits, 0<=n<8. Discard all digits beyond a, and all zeroes at or below a. */ /* Does not normalize. */ static sqInt bytesRshiftbyteslookfirst(sqInt aBytesOop, sqInt anInteger, sqInt b, sqInt a) { sqInt digit; sqInt digit1; sqInt f; sqInt i; sqInt j; sqInt m; sqInt n; sqInt newBytes; sqInt newLen; sqInt oldLen; unsigned char * pFrom; unsigned char *pointer; unsigned char *pointer1; unsigned char * pTo; sqInt x; sqInt x1; n = 0 - anInteger; x = 0; f = n + 8; i = a; m = (((0 - f) < 0) ? ((usqInt) 255 >> -(0 - f)) : ((usqInt) 255 << (0 - f))); /* begin digitOfBytes:at: */ if (i > (interpreterProxy->slotSizeOf(aBytesOop))) { digit = 0; goto l2; } else { digit = ((pointer1 = interpreterProxy->firstIndexableField(aBytesOop)))[i - 1]; goto l2; } l2: /* end digitOfBytes:at: */; while ((((((n < 0) ? ((usqInt) digit >> -n) : ((usqInt) digit << n))) | x) == 0) && (i != 1)) { /* Can't exceed 8 bits */ x = ((f < 0) ? ((usqInt) digit >> -f) : ((usqInt) digit << f)); i -= 1; /* begin digitOfBytes:at: */ if (i > (interpreterProxy->slotSizeOf(aBytesOop))) { digit = 0; goto l1; } else { digit = ((pointer = interpreterProxy->firstIndexableField(aBytesOop)))[i - 1]; goto l1; } l1: /* end digitOfBytes:at: */; } if (i <= b) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->fetchClassOf(aBytesOop), 0); } oldLen = interpreterProxy->slotSizeOf(aBytesOop); newLen = i - b; interpreterProxy->pushRemappableOop(aBytesOop); newBytes = interpreterProxy->instantiateClassindexableSize(interpreterProxy->fetchClassOf(aBytesOop), newLen); aBytesOop = interpreterProxy->popRemappableOop(); /* begin cCoreBytesRshiftCount:n:m:f:bytes:from:len:to:len: */ pFrom = interpreterProxy->firstIndexableField(aBytesOop); pTo = interpreterProxy->firstIndexableField(newBytes); /* begin sqAssert: */ /* missing DebugCode */; l3: /* end sqAssert: */; x1 = ((n < 0) ? ((usqInt) (pFrom[b]) >> -n) : ((usqInt) (pFrom[b]) << n)); /* begin sqAssert: */ /* missing DebugCode */; l4: /* end sqAssert: */; for (j = (b + 1); j <= (i - 1); j += 1) { digit1 = pFrom[j]; pTo[(j - b) - 1] = ((((f < 0) ? ((usqInt) (digit1 & m) >> -f) : ((usqInt) (digit1 & m) << f))) | x1); x1 = ((n < 0) ? ((usqInt) digit1 >> -n) : ((usqInt) digit1 << n)); } if (i == oldLen) { digit1 = 0; } else { digit1 = pFrom[i]; } pTo[(i - b) - 1] = ((((f < 0) ? ((usqInt) (digit1 & m) >> -f) : ((usqInt) (digit1 & m) << f))) | x1); return newBytes; } /* pByteRes len = longLen. */ static sqInt cByteOpshortlenlongleninto(sqInt opIndex, unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes) { sqInt i; sqInt limit; limit = shortLen - 1; if (opIndex == andOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) & (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = 0; } return 0; } if (opIndex == orOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) | (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = (pByteLong[i]); } return 0; } if (opIndex == xorOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) ^ (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = (pByteLong[i]); } return 0; } return interpreterProxy->primitiveFail(); } static int cBytesCopyFromtolen(unsigned char * pFrom, unsigned char * pTo, sqInt len) { sqInt i; sqInt limit; ; limit = len - 1; for (i = 0; i <= limit; i += 1) { pTo[i] = (pFrom[i]); } return 0; } /* Answer the index (in bits) of the high order bit of the receiver, or zero if the receiver is zero. This method is allowed (and needed) for LargeNegativeIntegers as well, since Squeak's LargeIntegers are sign/magnitude. */ static sqInt cBytesHighBitlen(unsigned char * pByte, sqInt len) { sqInt lastDigit; sqInt realLength; realLength = len; while (((lastDigit = pByte[realLength - 1])) == 0) { if (((realLength -= 1)) == 0) { return 0; } } return (cHighBit(lastDigit)) + (8 * (realLength - 1)); } /* C indexed! */ static int cBytesLshiftfromlentolen(sqInt shiftCount, unsigned char * pFrom, sqInt lenFrom, unsigned char * pTo, sqInt lenTo) { sqInt bitShift; sqInt byteShift; sqInt carry; sqInt digit; sqInt i; sqInt lastIx; sqInt limit; sqInt mask; sqInt rShift; byteShift = ((sqInt) shiftCount >> 3); bitShift = shiftCount % 8; if (bitShift == 0) { /* begin cBytesReplace:from:to:with:startingAt: */ return cBytesCopyFromtolen(pFrom + 0, pTo + byteShift, ((lenTo - 1) - byteShift) + 1); } carry = 0; rShift = bitShift - 8; mask = (((0 - bitShift) < 0) ? ((usqInt) 255 >> -(0 - bitShift)) : ((usqInt) 255 << (0 - bitShift))); limit = byteShift - 1; for (i = 0; i <= limit; i += 1) { pTo[i] = 0; } limit = (lenTo - byteShift) - 2; /* begin sqAssert: */ /* missing DebugCode */; l1: /* end sqAssert: */; for (i = 0; i <= limit; i += 1) { digit = pFrom[i]; pTo[i + byteShift] = ((((bitShift < 0) ? ((usqInt) (digit & mask) >> -bitShift) : ((usqInt) (digit & mask) << bitShift))) | carry); carry = ((rShift < 0) ? ((usqInt) digit >> -rShift) : ((usqInt) digit << rShift)); } lastIx = limit + 1; if (lastIx > (lenFrom - 1)) { digit = 0; } else { digit = pFrom[lastIx]; } pTo[lastIx + byteShift] = ((((bitShift < 0) ? ((usqInt) (digit & mask) >> -bitShift) : ((usqInt) (digit & mask) << bitShift))) | carry); carry = ((rShift < 0) ? ((usqInt) digit >> -rShift) : ((usqInt) digit << rShift)); /* begin sqAssert: */ /* missing DebugCode */; l2: /* end sqAssert: */; } /* C indexed! */ static int cBytesReplacefromtowithstartingAt(unsigned char * pTo, sqInt start, sqInt stop, unsigned char * pFrom, sqInt repStart) { return cBytesCopyFromtolen(pFrom + repStart, pTo + start, (stop - start) + 1); } static void cCopyIntValtoBytes(sqInt val, sqInt bytes) { sqInt ix; unsigned char * pByte; pByte = interpreterProxy->firstIndexableField(bytes); for (ix = 1; ix <= (cDigitLengthOfCSI(val)); ix += 1) { pByte[ix - 1] = (cDigitOfCSIat(val, ix)); } } static void cCoreBytesRshiftCountnmfbytesfromlentolen(sqInt count, sqInt n, sqInt m, sqInt f, sqInt b, unsigned char * pFrom, sqInt fromLen, unsigned char * pTo, sqInt toLen) { sqInt digit; sqInt j; sqInt x; /* begin sqAssert: */ /* missing DebugCode */; l1: /* end sqAssert: */; x = ((n < 0) ? ((usqInt) (pFrom[b]) >> -n) : ((usqInt) (pFrom[b]) << n)); /* begin sqAssert: */ /* missing DebugCode */; l2: /* end sqAssert: */; for (j = (b + 1); j <= (count - 1); j += 1) { digit = pFrom[j]; pTo[(j - b) - 1] = ((((f < 0) ? ((usqInt) (digit & m) >> -f) : ((usqInt) (digit & m) << f))) | x); x = ((n < 0) ? ((usqInt) digit >> -n) : ((usqInt) digit << n)); } if (count == fromLen) { digit = 0; } else { digit = pFrom[count]; } pTo[(count - b) - 1] = ((((f < 0) ? ((usqInt) (digit & m) >> -f) : ((usqInt) (digit & m) << f))) | x); } static void cCoreDigitDivDivlenremlenquolen(unsigned char * pDiv, sqInt divLen, unsigned char * pRem, sqInt remLen, unsigned char * pQuo, sqInt quoLen) { sqInt a; sqInt cond; sqInt dh; sqInt dl; sqInt dnh; sqInt hi; sqInt i; sqInt j; sqInt k; sqInt l; sqInt lo; sqInt mul; sqInt q; sqInt ql; sqInt r1r2; sqInt r3; sqInt t; /* Last actual byte of data (ST ix) */ dl = divLen - 1; ql = quoLen; dh = pDiv[dl - 1]; if (dl == 1) { dnh = 0; } else { dnh = pDiv[dl - 2]; } for (k = 1; k <= ql; k += 1) { /* maintain quo*arg+rem=self */ /* Estimate rem/div by dividing the leading two bytes of rem by dh. */ /* The estimate is q = qhi*16+qlo, where qhi and qlo are nibbles. */ /* Nibbles are kicked off! We use full 16 bits now, because we are in the year 2000 ;-) [sr] */ /* r1 := rem digitAt: j. */ j = (remLen + 1) - k; if ((pRem[j - 1]) == dh) { q = 255; } else { /* Compute q = (r1,r2)//dh, t = (r1,r2)\\dh. Note that r1,r2 are bytes, not nibbles. Be careful not to generate intermediate results exceeding 13 bits. */ /* r2 := (rem digitAt: j - 2). */ r1r2 = (((usqInt) (pRem[j - 1]) << 8)) + (pRem[j - 2]); t = r1r2 % dh; /* Next compute (hi,lo) := q*dnh */ q = r1r2 / dh; mul = q * dnh; hi = ((usqInt) mul >> 8); /* Correct overestimate of q. Max of 2 iterations through loop -- see Knuth vol. 2 */ lo = mul & 255; if (j < 3) { r3 = 0; } else { r3 = pRem[j - 3]; } while (1) { if ((t < hi) || ((t == hi) && (r3 < lo))) { /* i.e. (t,r3) < (hi,lo) */ q -= 1; lo -= dnh; if (lo < 0) { hi -= 1; lo += 256; } cond = hi >= dh; } else { cond = 0; } if (!(cond)) break; hi -= dh; } } l = j - dl; a = 0; for (i = 1; i <= divLen; i += 1) { hi = (pDiv[i - 1]) * (((usqInt) q >> 8)); /* pRem at: l - 1 put: lo - (lo // 256 * 256). */ /* sign-tolerant form of (lo bitAnd: 255) -> obsolete... */ lo = (a + (pRem[l - 1])) - ((pDiv[i - 1]) * (q & 255)); pRem[l - 1] = (lo & 255); a = (((sqInt) lo >> 8)) - hi; l += 1; } if (a < 0) { /* Add div back into rem, decrease q by 1 */ q -= 1; l = j - dl; a = 0; for (i = 1; i <= divLen; i += 1) { a = ((((usqInt) a >> 8)) + (pRem[l - 1])) + (pDiv[i - 1]); pRem[l - 1] = (a & 255); l += 1; } } pQuo[quoLen - k] = q; } } /* pByteRes len = longLen; returns over.. */ static unsigned char cDigitAddlenwithleninto(unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes) { sqInt accum; sqInt i; sqInt limit; accum = 0; limit = shortLen - 1; for (i = 0; i <= limit; i += 1) { accum = ((((usqInt) accum >> 8)) + (pByteShort[i])) + (pByteLong[i]); pByteRes[i] = (accum & 255); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { accum = (((usqInt) accum >> 8)) + (pByteLong[i]); pByteRes[i] = (accum & 255); } return ((usqInt) accum >> 8); } /* Precondition: pFirst len = pSecond len. */ static sqInt cDigitComparewithlen(unsigned char * pFirst, unsigned char * pSecond, sqInt len) { sqInt firstDigit; sqInt ix; sqInt secondDigit; ix = len - 1; while (ix >= 0) { if (((secondDigit = pSecond[ix])) != ((firstDigit = pFirst[ix]))) { if (secondDigit < firstDigit) { return 1; } else { return -1; } } ix -= 1; } return 0; } /* Answer the number of indexable fields of a CSmallInteger. This value is the same as the largest legal subscript. */ static sqInt cDigitLengthOfCSI(sqInt csi) { if ((csi < 256) && (csi > -256)) { return 1; } if ((csi < 65536) && (csi > -65536)) { return 2; } if ((csi < 16777216) && (csi > -16777216)) { return 3; } return 4; } static unsigned char cDigitMultiplylenwithleninto(unsigned char * pByteShort, sqInt shortLen, unsigned char * pByteLong, sqInt longLen, unsigned char * pByteRes) { sqInt ab; sqInt carry; sqInt digit; sqInt i; sqInt j; sqInt k; sqInt limitLong; sqInt limitShort; if ((shortLen == 1) && ((pByteShort[0]) == 0)) { return 0; } if ((longLen == 1) && ((pByteLong[0]) == 0)) { return 0; } limitShort = shortLen - 1; for (i = 0; i <= limitShort; i += 1) { if (((digit = pByteShort[i])) != 0) { k = i; /* Loop invariant: 0<=carry<=0377, k=i+j-1 (ST) */ /* -> Loop invariant: 0<=carry<=0377, k=i+j (C) (?) */ carry = 0; limitLong = longLen - 1; for (j = 0; j <= limitLong; j += 1) { ab = (((pByteLong[j]) * digit) + carry) + (pByteRes[k]); carry = ((usqInt) ab >> 8); pByteRes[k] = (ab & 255); k += 1; } pByteRes[k] = carry; } } return 0; } /* Answer the value of an indexable field in the receiver. LargePositiveInteger uses bytes of base two number, and each is a 'digit' base 256. */ /* ST indexed! */ static sqInt cDigitOfCSIat(sqInt csi, sqInt ix) { if (ix < 0) { interpreterProxy->primitiveFail(); } if (ix > 4) { return 0; } if (csi < 0) { ; return (((((1 - ix) * 8) < 0) ? ((usqInt) (0 - csi) >> -((1 - ix) * 8)) : ((usqInt) (0 - csi) << ((1 - ix) * 8)))) & 255; } else { return (((((1 - ix) * 8) < 0) ? ((usqInt) csi >> -((1 - ix) * 8)) : ((usqInt) csi << ((1 - ix) * 8)))) & 255; } } static void cDigitSublenwithleninto(unsigned char * pByteSmall, sqInt smallLen, unsigned char * pByteLarge, sqInt largeLen, unsigned char * pByteRes) { sqInt i; sqInt limit; sqInt z; /* Loop invariant is -1<=z<=1 */ z = 0; limit = smallLen - 1; for (i = 0; i <= limit; i += 1) { z = (z + (pByteLarge[i])) - (pByteSmall[i]); pByteRes[i] = (z - ((((sqInt) z >> 8)) * 256)); z = ((sqInt) z >> 8); } limit = largeLen - 1; for (i = smallLen; i <= limit; i += 1) { z += pByteLarge[i]; pByteRes[i] = (z - ((((sqInt) z >> 8)) * 256)); z = ((sqInt) z >> 8); } } /* Answer the index of the high order bit of the argument, or zero if the argument is zero. */ /* For 64 bit uints there could be added a 32-shift. */ static sqInt cHighBit(sqInt uint) { sqInt bitNo; unsigned int shifted; shifted = uint; bitNo = 0; if (!(shifted < (1 << 16))) { shifted = ((usqInt) shifted >> 16); bitNo += 16; } if (!(shifted < (1 << 8))) { shifted = ((usqInt) shifted >> 8); bitNo += 8; } if (!(shifted < (1 << 4))) { shifted = ((usqInt) shifted >> 4); bitNo += 4; } if (!(shifted < (1 << 2))) { shifted = ((usqInt) shifted >> 2); bitNo += 2; } if (!(shifted < (1 << 1))) { shifted = ((usqInt) shifted >> 1); bitNo += 1; } return bitNo + shifted; } /* anOop has to be a SmallInteger! */ static sqInt createLargeFromSmallInteger(sqInt anOop) { sqInt class; sqInt ix; unsigned char * pByte; sqInt res; sqInt size; sqInt val; val = (anOop >> 1); if (val < 0) { class = interpreterProxy->classLargeNegativeInteger(); } else { class = interpreterProxy->classLargePositiveInteger(); } /* begin cDigitLengthOfCSI: */ if ((val < 256) && (val > -256)) { size = 1; goto l1; } if ((val < 65536) && (val > -65536)) { size = 2; goto l1; } if ((val < 16777216) && (val > -16777216)) { size = 3; goto l1; } size = 4; l1: /* end cDigitLengthOfCSI: */; res = interpreterProxy->instantiateClassindexableSize(class, size); pByte = interpreterProxy->firstIndexableField(res); for (ix = 1; ix <= size; ix += 1) { pByte[ix - 1] = (cDigitOfCSIat(val, ix)); } return res; } /* Does not need to normalize! */ static sqInt digitAddLargewith(sqInt firstInteger, sqInt secondInteger) { sqInt accum; sqInt firstLen; sqInt i; sqInt limit; sqInt longInt; sqInt longLen; sqInt newSum; unsigned char over; unsigned char * pByteLong; unsigned char * pByteRes; unsigned char * pByteShort; sqInt resClass; sqInt secondLen; sqInt shortInt; sqInt shortLen; sqInt sum; firstLen = interpreterProxy->slotSizeOf(firstInteger); secondLen = interpreterProxy->slotSizeOf(secondInteger); resClass = interpreterProxy->fetchClassOf(firstInteger); if (firstLen <= secondLen) { shortInt = firstInteger; shortLen = firstLen; longInt = secondInteger; longLen = secondLen; } else { shortInt = secondInteger; shortLen = secondLen; longInt = firstInteger; longLen = firstLen; } interpreterProxy->pushRemappableOop(shortInt); interpreterProxy->pushRemappableOop(longInt); sum = interpreterProxy->instantiateClassindexableSize(resClass, longLen); longInt = interpreterProxy->popRemappableOop(); shortInt = interpreterProxy->popRemappableOop(); /* begin cDigitAdd:len:with:len:into: */ pByteShort = interpreterProxy->firstIndexableField(shortInt); pByteLong = interpreterProxy->firstIndexableField(longInt); pByteRes = interpreterProxy->firstIndexableField(sum); accum = 0; limit = shortLen - 1; for (i = 0; i <= limit; i += 1) { accum = ((((usqInt) accum >> 8)) + (pByteShort[i])) + (pByteLong[i]); pByteRes[i] = (accum & 255); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { accum = (((usqInt) accum >> 8)) + (pByteLong[i]); pByteRes[i] = (accum & 255); } over = ((usqInt) accum >> 8); if (over > 0) { interpreterProxy->pushRemappableOop(sum); /* sum := sum growby: 1. */ newSum = interpreterProxy->instantiateClassindexableSize(resClass, longLen + 1); sum = interpreterProxy->popRemappableOop(); cBytesCopyFromtolen(interpreterProxy->firstIndexableField(sum), interpreterProxy->firstIndexableField(newSum), longLen); /* C index! */ sum = newSum; (((unsigned char *) (interpreterProxy->firstIndexableField(sum))))[longLen] = over; } return sum; } /* Bit logic here is only implemented for positive integers or Zero; if rec or arg is negative, it fails. */ static sqInt digitBitLogicwithopIndex(sqInt firstInteger, sqInt secondInteger, sqInt opIx) { sqInt firstLarge; sqInt firstLen; sqInt i; sqInt limit; sqInt longLarge; sqInt longLen; unsigned char * pByteLong; unsigned char * pByteRes; unsigned char * pByteShort; sqInt result; sqInt secondLarge; sqInt secondLen; sqInt shortLarge; sqInt shortLen; if ((firstInteger & 1)) { if (((firstInteger >> 1)) < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pushRemappableOop(secondInteger); firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { if ((interpreterProxy->fetchClassOf(firstInteger)) == (interpreterProxy->classLargeNegativeInteger())) { return interpreterProxy->primitiveFail(); } firstLarge = firstInteger; } if ((secondInteger & 1)) { if (((secondInteger >> 1)) < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pushRemappableOop(firstLarge); secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { if ((interpreterProxy->fetchClassOf(secondInteger)) == (interpreterProxy->classLargeNegativeInteger())) { return interpreterProxy->primitiveFail(); } secondLarge = secondInteger; } firstLen = interpreterProxy->slotSizeOf(firstLarge); secondLen = interpreterProxy->slotSizeOf(secondLarge); if (firstLen < secondLen) { shortLen = firstLen; shortLarge = firstLarge; longLen = secondLen; longLarge = secondLarge; } else { shortLen = secondLen; shortLarge = secondLarge; longLen = firstLen; longLarge = firstLarge; } interpreterProxy->pushRemappableOop(shortLarge); interpreterProxy->pushRemappableOop(longLarge); result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classLargePositiveInteger(), longLen); longLarge = interpreterProxy->popRemappableOop(); shortLarge = interpreterProxy->popRemappableOop(); /* begin cByteOp:short:len:long:len:into: */ pByteShort = interpreterProxy->firstIndexableField(shortLarge); pByteLong = interpreterProxy->firstIndexableField(longLarge); pByteRes = interpreterProxy->firstIndexableField(result); limit = shortLen - 1; if (opIx == andOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) & (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = 0; } goto l1; } if (opIx == orOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) | (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = (pByteLong[i]); } goto l1; } if (opIx == xorOpIndex) { for (i = 0; i <= limit; i += 1) { pByteRes[i] = ((pByteShort[i]) ^ (pByteLong[i])); } limit = longLen - 1; for (i = shortLen; i <= limit; i += 1) { pByteRes[i] = (pByteLong[i]); } goto l1; } interpreterProxy->primitiveFail(); l1: /* end cByteOp:short:len:long:len:into: */; if (interpreterProxy->failed()) { return 0; } return normalizePositive(result); } /* Compare the magnitude of firstInteger with that of secondInteger. Return a code of 1, 0, -1 for firstInteger >, = , < secondInteger */ static sqInt digitCompareLargewith(sqInt firstInteger, sqInt secondInteger) { sqInt firstLen; sqInt secondLen; firstLen = interpreterProxy->slotSizeOf(firstInteger); secondLen = interpreterProxy->slotSizeOf(secondInteger); if (secondLen != firstLen) { if (secondLen > firstLen) { return interpreterProxy->integerObjectOf(-1); } else { return interpreterProxy->integerObjectOf(1); } } return interpreterProxy->integerObjectOf((cDigitComparewithlen(interpreterProxy->firstIndexableField(firstInteger), interpreterProxy->firstIndexableField(secondInteger), firstLen))); } /* Does not normalize. */ /* Division by zero has to be checked in caller. */ static sqInt digitDivLargewithnegative(sqInt firstInteger, sqInt secondInteger, sqInt neg) { sqInt a; sqInt cond; sqInt d; sqInt dh; sqInt div; sqInt divLen; sqInt dl; sqInt dnh; sqInt firstLen; sqInt hi; sqInt i; sqInt j; sqInt k; sqInt l; sqInt l1; sqInt lo; sqInt mul; unsigned char * pDiv; unsigned char *pointer; unsigned char * pQuo; unsigned char * pRem; sqInt q; sqInt ql; sqInt quo; sqInt quoLen; sqInt r1r2; sqInt r3; sqInt rem; sqInt remLen; sqInt result; sqInt resultClass; sqInt secondLen; sqInt t; firstLen = interpreterProxy->slotSizeOf(firstInteger); secondLen = interpreterProxy->slotSizeOf(secondInteger); if (neg) { resultClass = interpreterProxy->classLargeNegativeInteger(); } else { resultClass = interpreterProxy->classLargePositiveInteger(); } l = (firstLen - secondLen) + 1; if (l <= 0) { interpreterProxy->pushRemappableOop(firstInteger); result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); firstInteger = interpreterProxy->popRemappableOop(); interpreterProxy->stObjectatput(result,1,(interpreterProxy->integerObjectOf(0))); interpreterProxy->stObjectatput(result,2,firstInteger); return result; } d = 8 - (cHighBit(((pointer = interpreterProxy->firstIndexableField(secondInteger)))[secondLen - 1])); interpreterProxy->pushRemappableOop(firstInteger); div = bytesLshift(secondInteger, d); div = bytesOrIntgrowTo(div, (digitLength(div)) + 1); firstInteger = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(div); rem = bytesLshift(firstInteger, d); if ((digitLength(rem)) == firstLen) { rem = bytesOrIntgrowTo(rem, firstLen + 1); } div = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(div); interpreterProxy->pushRemappableOop(rem); quo = interpreterProxy->instantiateClassindexableSize(resultClass, l); rem = interpreterProxy->popRemappableOop(); div = interpreterProxy->popRemappableOop(); /* begin cCoreDigitDivDiv:len:rem:len:quo:len: */ pDiv = interpreterProxy->firstIndexableField(div); /* begin digitLength: */ if ((div & 1)) { /* begin cDigitLengthOfCSI: */ if ((((div >> 1)) < 256) && (((div >> 1)) > -256)) { divLen = 1; goto l1; } if ((((div >> 1)) < 65536) && (((div >> 1)) > -65536)) { divLen = 2; goto l1; } if ((((div >> 1)) < 16777216) && (((div >> 1)) > -16777216)) { divLen = 3; goto l1; } divLen = 4; goto l1; } else { divLen = interpreterProxy->slotSizeOf(div); goto l1; } l1: /* end digitLength: */; pRem = interpreterProxy->firstIndexableField(rem); /* begin digitLength: */ if ((rem & 1)) { /* begin cDigitLengthOfCSI: */ if ((((rem >> 1)) < 256) && (((rem >> 1)) > -256)) { remLen = 1; goto l2; } if ((((rem >> 1)) < 65536) && (((rem >> 1)) > -65536)) { remLen = 2; goto l2; } if ((((rem >> 1)) < 16777216) && (((rem >> 1)) > -16777216)) { remLen = 3; goto l2; } remLen = 4; goto l2; } else { remLen = interpreterProxy->slotSizeOf(rem); goto l2; } l2: /* end digitLength: */; pQuo = interpreterProxy->firstIndexableField(quo); /* begin digitLength: */ if ((quo & 1)) { /* begin cDigitLengthOfCSI: */ if ((((quo >> 1)) < 256) && (((quo >> 1)) > -256)) { quoLen = 1; goto l3; } if ((((quo >> 1)) < 65536) && (((quo >> 1)) > -65536)) { quoLen = 2; goto l3; } if ((((quo >> 1)) < 16777216) && (((quo >> 1)) > -16777216)) { quoLen = 3; goto l3; } quoLen = 4; goto l3; } else { quoLen = interpreterProxy->slotSizeOf(quo); goto l3; } l3: /* end digitLength: */; /* Last actual byte of data (ST ix) */ dl = divLen - 1; ql = quoLen; dh = pDiv[dl - 1]; if (dl == 1) { dnh = 0; } else { dnh = pDiv[dl - 2]; } for (k = 1; k <= ql; k += 1) { /* maintain quo*arg+rem=self */ /* Estimate rem/div by dividing the leading two bytes of rem by dh. */ /* The estimate is q = qhi*16+qlo, where qhi and qlo are nibbles. */ /* Nibbles are kicked off! We use full 16 bits now, because we are in the year 2000 ;-) [sr] */ /* r1 := rem digitAt: j. */ j = (remLen + 1) - k; if ((pRem[j - 1]) == dh) { q = 255; } else { /* Compute q = (r1,r2)//dh, t = (r1,r2)\\dh. Note that r1,r2 are bytes, not nibbles. Be careful not to generate intermediate results exceeding 13 bits. */ /* r2 := (rem digitAt: j - 2). */ r1r2 = (((usqInt) (pRem[j - 1]) << 8)) + (pRem[j - 2]); t = r1r2 % dh; /* Next compute (hi,lo) := q*dnh */ q = r1r2 / dh; mul = q * dnh; hi = ((usqInt) mul >> 8); /* Correct overestimate of q. Max of 2 iterations through loop -- see Knuth vol. 2 */ lo = mul & 255; if (j < 3) { r3 = 0; } else { r3 = pRem[j - 3]; } while (1) { if ((t < hi) || ((t == hi) && (r3 < lo))) { /* i.e. (t,r3) < (hi,lo) */ q -= 1; lo -= dnh; if (lo < 0) { hi -= 1; lo += 256; } cond = hi >= dh; } else { cond = 0; } if (!(cond)) break; hi -= dh; } } l1 = j - dl; a = 0; for (i = 1; i <= divLen; i += 1) { hi = (pDiv[i - 1]) * (((usqInt) q >> 8)); /* pRem at: l - 1 put: lo - (lo // 256 * 256). */ /* sign-tolerant form of (lo bitAnd: 255) -> obsolete... */ lo = (a + (pRem[l1 - 1])) - ((pDiv[i - 1]) * (q & 255)); pRem[l1 - 1] = (lo & 255); a = (((sqInt) lo >> 8)) - hi; l1 += 1; } if (a < 0) { /* Add div back into rem, decrease q by 1 */ q -= 1; l1 = j - dl; a = 0; for (i = 1; i <= divLen; i += 1) { a = ((((usqInt) a >> 8)) + (pRem[l1 - 1])) + (pDiv[i - 1]); pRem[l1 - 1] = (a & 255); l1 += 1; } } pQuo[quoLen - k] = q; } interpreterProxy->pushRemappableOop(quo); rem = bytesRshiftbyteslookfirst(rem, d, 0, (digitLength(div)) - 1); quo = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(quo); interpreterProxy->pushRemappableOop(rem); result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); rem = interpreterProxy->popRemappableOop(); quo = interpreterProxy->popRemappableOop(); interpreterProxy->stObjectatput(result,1,quo); interpreterProxy->stObjectatput(result,2,rem); return result; } static sqInt digitLength(sqInt oop) { if ((oop & 1)) { /* begin cDigitLengthOfCSI: */ if ((((oop >> 1)) < 256) && (((oop >> 1)) > -256)) { return 1; } if ((((oop >> 1)) < 65536) && (((oop >> 1)) > -65536)) { return 2; } if ((((oop >> 1)) < 16777216) && (((oop >> 1)) > -16777216)) { return 3; } return 4; } else { return interpreterProxy->slotSizeOf(oop); } } /* Normalizes. */ static sqInt digitMultiplyLargewithnegative(sqInt firstInteger, sqInt secondInteger, sqInt neg) { sqInt ab; sqInt carry; sqInt digit; sqInt firstLen; sqInt i; sqInt j; sqInt k; sqInt limitLong; sqInt limitShort; sqInt longInt; sqInt longLen; unsigned char * pByteLong; unsigned char * pByteRes; unsigned char * pByteShort; sqInt prod; sqInt resultClass; sqInt secondLen; sqInt shortInt; sqInt shortLen; firstLen = interpreterProxy->slotSizeOf(firstInteger); secondLen = interpreterProxy->slotSizeOf(secondInteger); if (firstLen <= secondLen) { shortInt = firstInteger; shortLen = firstLen; longInt = secondInteger; longLen = secondLen; } else { shortInt = secondInteger; shortLen = secondLen; longInt = firstInteger; longLen = firstLen; } if (neg) { resultClass = interpreterProxy->classLargeNegativeInteger(); } else { resultClass = interpreterProxy->classLargePositiveInteger(); } interpreterProxy->pushRemappableOop(shortInt); interpreterProxy->pushRemappableOop(longInt); prod = interpreterProxy->instantiateClassindexableSize(resultClass, longLen + shortLen); longInt = interpreterProxy->popRemappableOop(); shortInt = interpreterProxy->popRemappableOop(); /* begin cDigitMultiply:len:with:len:into: */ pByteShort = interpreterProxy->firstIndexableField(shortInt); pByteLong = interpreterProxy->firstIndexableField(longInt); pByteRes = interpreterProxy->firstIndexableField(prod); if ((shortLen == 1) && ((pByteShort[0]) == 0)) { goto l1; } if ((longLen == 1) && ((pByteLong[0]) == 0)) { goto l1; } limitShort = shortLen - 1; for (i = 0; i <= limitShort; i += 1) { if (((digit = pByteShort[i])) != 0) { k = i; /* Loop invariant: 0<=carry<=0377, k=i+j-1 (ST) */ /* -> Loop invariant: 0<=carry<=0377, k=i+j (C) (?) */ carry = 0; limitLong = longLen - 1; for (j = 0; j <= limitLong; j += 1) { ab = (((pByteLong[j]) * digit) + carry) + (pByteRes[k]); carry = ((usqInt) ab >> 8); pByteRes[k] = (ab & 255); k += 1; } pByteRes[k] = carry; } } l1: /* end cDigitMultiply:len:with:len:into: */; /* begin normalize: */ /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(prod)) == (interpreterProxy->classLargePositiveInteger())) { return normalizePositive(prod); } else { return normalizeNegative(prod); } } /* Argument has to be aLargeInteger! */ static sqInt digitOfBytesat(sqInt aBytesOop, sqInt ix) { unsigned char *pointer; if (ix > (interpreterProxy->slotSizeOf(aBytesOop))) { return 0; } else { return ((pointer = interpreterProxy->firstIndexableField(aBytesOop)))[ix - 1]; } } static sqInt digitOfat(sqInt oop, sqInt ix) { unsigned char *pointer; if ((oop & 1)) { return cDigitOfCSIat((oop >> 1), ix); } else { /* begin digitOfBytes:at: */ if (ix > (interpreterProxy->slotSizeOf(oop))) { return 0; } else { return ((pointer = interpreterProxy->firstIndexableField(oop)))[ix - 1]; } } } /* Normalizes. */ static sqInt digitSubLargewith(sqInt firstInteger, sqInt secondInteger) { sqInt firstLen; sqInt firstNeg; sqInt i; sqInt larger; sqInt largerLen; sqInt limit; sqInt neg; unsigned char * pByteLarge; unsigned char * pByteRes; unsigned char * pByteSmall; sqInt res; sqInt resLen; sqInt secondLen; sqInt smaller; sqInt smallerLen; sqInt z; firstNeg = (interpreterProxy->fetchClassOf(firstInteger)) == (interpreterProxy->classLargeNegativeInteger()); firstLen = interpreterProxy->slotSizeOf(firstInteger); secondLen = interpreterProxy->slotSizeOf(secondInteger); if (firstLen == secondLen) { while ((firstLen > 1) && ((digitOfBytesat(firstInteger, firstLen)) == (digitOfBytesat(secondInteger, firstLen)))) { firstLen -= 1; } secondLen = firstLen; } if ((firstLen < secondLen) || ((firstLen == secondLen) && ((digitOfBytesat(firstInteger, firstLen)) < (digitOfBytesat(secondInteger, firstLen))))) { larger = secondInteger; largerLen = secondLen; smaller = firstInteger; smallerLen = firstLen; neg = firstNeg == 0; } else { larger = firstInteger; largerLen = firstLen; smaller = secondInteger; smallerLen = secondLen; neg = firstNeg; } resLen = largerLen; interpreterProxy->pushRemappableOop(smaller); interpreterProxy->pushRemappableOop(larger); res = interpreterProxy->instantiateClassindexableSize((neg ? interpreterProxy->classLargeNegativeInteger() : interpreterProxy->classLargePositiveInteger()), resLen); larger = interpreterProxy->popRemappableOop(); smaller = interpreterProxy->popRemappableOop(); /* begin cDigitSub:len:with:len:into: */ pByteSmall = interpreterProxy->firstIndexableField(smaller); pByteLarge = interpreterProxy->firstIndexableField(larger); pByteRes = interpreterProxy->firstIndexableField(res); /* Loop invariant is -1<=z<=1 */ z = 0; limit = smallerLen - 1; for (i = 0; i <= limit; i += 1) { z = (z + (pByteLarge[i])) - (pByteSmall[i]); pByteRes[i] = (z - ((((sqInt) z >> 8)) * 256)); z = ((sqInt) z >> 8); } limit = largerLen - 1; for (i = smallerLen; i <= limit; i += 1) { z += pByteLarge[i]; pByteRes[i] = (z - ((((sqInt) z >> 8)) * 256)); z = ((sqInt) z >> 8); } return (neg ? normalizeNegative(res) : normalizePositive(res)); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt highBitOfBytes(sqInt aBytesOop) { sqInt lastDigit; sqInt len; unsigned char * pByte; sqInt realLength; /* begin cBytesHighBit:len: */ pByte = interpreterProxy->firstIndexableField(aBytesOop); len = interpreterProxy->slotSizeOf(aBytesOop); realLength = len; while (((lastDigit = pByte[realLength - 1])) == 0) { if (((realLength -= 1)) == 0) { return 0; } } return (cHighBit(lastDigit)) + (8 * (realLength - 1)); } /* Initializes ST constants; C's are set by class>>declareCVarsIn:. */ static void initialize(void) { "nothing to do here"; } static sqInt isNormalized(sqInt anInteger) { sqInt ix; sqInt len; sqInt maxVal; sqInt minVal; unsigned char *pointer; unsigned char *pointer1; unsigned char *pointer2; unsigned char *pointer3; sqInt sLen; if ((anInteger & 1)) { return 1; } /* begin digitLength: */ if ((anInteger & 1)) { /* begin cDigitLengthOfCSI: */ if ((((anInteger >> 1)) < 256) && (((anInteger >> 1)) > -256)) { len = 1; goto l1; } if ((((anInteger >> 1)) < 65536) && (((anInteger >> 1)) > -65536)) { len = 2; goto l1; } if ((((anInteger >> 1)) < 16777216) && (((anInteger >> 1)) > -16777216)) { len = 3; goto l1; } len = 4; goto l1; } else { len = interpreterProxy->slotSizeOf(anInteger); goto l1; } l1: /* end digitLength: */; if (len == 0) { return 0; } if ((((pointer = interpreterProxy->firstIndexableField(anInteger)))[len - 1]) == 0) { return 0; } /* maximal digitLength of aSmallInteger */ sLen = 4; if (len > sLen) { return 1; } if (len < sLen) { return 0; } if ((interpreterProxy->fetchClassOf(anInteger)) == (interpreterProxy->classLargePositiveInteger())) { /* SmallInteger maxVal */ /* all bytes of maxVal but the highest one are just FF's */ maxVal = 1073741823; return (((pointer1 = interpreterProxy->firstIndexableField(anInteger)))[sLen - 1]) > (cDigitOfCSIat(maxVal, sLen)); } else { /* SmallInteger minVal */ /* all bytes of minVal but the highest one are just 00's */ minVal = -1073741824; if ((((pointer2 = interpreterProxy->firstIndexableField(anInteger)))[sLen - 1]) < (cDigitOfCSIat(minVal, sLen))) { return 0; } else { for (ix = 1; ix <= sLen; ix += 1) { if (!((((pointer3 = interpreterProxy->firstIndexableField(anInteger)))[ix - 1]) == (cDigitOfCSIat(minVal, ix)))) { return 1; } } } } return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } static sqInt negative(sqInt aLarge) { return (interpreterProxy->fetchClassOf(aLarge)) == (interpreterProxy->classLargeNegativeInteger()); } /* Check for leading zeroes and return shortened copy if so. */ /* First establish len = significant length. */ static sqInt normalizeNegative(sqInt aLargeNegativeInteger) { sqInt i; sqInt len; sqInt minVal; sqInt oldLen; unsigned char *pointer; unsigned char *pointer1; sqInt sLen; sqInt val; len = oldLen = digitLength(aLargeNegativeInteger); while ((len != 0) && ((((pointer = interpreterProxy->firstIndexableField(aLargeNegativeInteger)))[len - 1]) == 0)) { len -= 1; } if (len == 0) { return interpreterProxy->integerObjectOf(0); } /* SmallInteger minVal digitLength */ sLen = 4; if (len <= sLen) { /* SmallInteger minVal */ minVal = -1073741824; if ((len < sLen) || ((digitOfBytesat(aLargeNegativeInteger, sLen)) < (cDigitOfCSIat(minVal, sLen)))) { /* If high digit less, then can be small */ val = 0; for (i = len; i >= 1; i += -1) { val = (val * 256) - (((pointer1 = interpreterProxy->firstIndexableField(aLargeNegativeInteger)))[i - 1]); } return interpreterProxy->integerObjectOf(val); } for (i = 1; i <= sLen; i += 1) { if (!((digitOfBytesat(aLargeNegativeInteger, i)) == (cDigitOfCSIat(minVal, i)))) { if (len < oldLen) { return bytesgrowTo(aLargeNegativeInteger, len); } else { return aLargeNegativeInteger; } } } return interpreterProxy->integerObjectOf(minVal); } if (len < oldLen) { return bytesgrowTo(aLargeNegativeInteger, len); } else { return aLargeNegativeInteger; } } /* Check for leading zeroes and return shortened copy if so. */ /* First establish len = significant length. */ static sqInt normalizePositive(sqInt aLargePositiveInteger) { sqInt i; sqInt len; sqInt oldLen; unsigned char *pointer; unsigned char *pointer1; sqInt sLen; sqInt val; len = oldLen = digitLength(aLargePositiveInteger); while ((len != 0) && ((((pointer = interpreterProxy->firstIndexableField(aLargePositiveInteger)))[len - 1]) == 0)) { len -= 1; } if (len == 0) { return interpreterProxy->integerObjectOf(0); } /* SmallInteger maxVal digitLength. */ sLen = 4; if ((len <= sLen) && ((digitOfBytesat(aLargePositiveInteger, sLen)) <= (cDigitOfCSIat(1073741823, sLen)))) { /* If so, return its SmallInt value */ val = 0; for (i = len; i >= 1; i += -1) { val = (val * 256) + (((pointer1 = interpreterProxy->firstIndexableField(aLargePositiveInteger)))[i - 1]); } return interpreterProxy->integerObjectOf(val); } if (len < oldLen) { return bytesgrowTo(aLargePositiveInteger, len); } else { return aLargePositiveInteger; } } /* Check for leading zeroes and return shortened copy if so. */ static sqInt normalize(sqInt aLargeInteger) { /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(aLargeInteger)) == (interpreterProxy->classLargePositiveInteger())) { return normalizePositive(aLargeInteger); } else { return normalizeNegative(aLargeInteger); } } EXPORT(sqInt) primAnyBitFromTo(void) { sqInt from; sqInt integer; sqInt large; sqInt to; sqInt _return_value; from = interpreterProxy->stackIntegerValue(1); to = interpreterProxy->stackIntegerValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); integer = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } if ((integer & 1)) { /* convert it to a not normalized LargeInteger */ large = createLargeFromSmallInteger(integer); } else { large = integer; } _return_value = ((anyBitOfBytesfromto(large, from, to))? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Converts a SmallInteger into a - non normalized! - LargeInteger; aLargeInteger will be returned unchanged. */ /* Do not check for forced fail, because we need this conversion to test the plugin in ST during forced fail, too. */ EXPORT(sqInt) primAsLargeInteger(void) { sqInt anInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); anInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((anInteger & 1)) { _return_value = createLargeFromSmallInteger(anInteger); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, anInteger); return null; } } /* If calling this primitive fails, then C module does not exist. Do not check for forced fail, because we want to know if module exists during forced fail, too. */ EXPORT(sqInt) primCheckIfCModuleExists(void) { sqInt _return_value; _return_value = (1? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primDigitAdd(void) { sqInt firstInteger; sqInt firstLarge; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitAddLargewith(firstLarge, secondLarge); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primDigitAddWith(void) { sqInt firstInteger; sqInt firstLarge; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitAddLargewith(firstLarge, secondLarge); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Bit logic here is only implemented for positive integers or Zero; if rec or arg is negative, it fails. */ EXPORT(sqInt) primDigitBitAnd(void) { sqInt firstInteger; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } _return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, andOpIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Bit logic here is only implemented for positive integers or Zero; if any arg is negative, it fails. */ EXPORT(sqInt) primDigitBitLogicWithOp(void) { sqInt firstInteger; sqInt opIndex; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); firstInteger = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); secondInteger = interpreterProxy->stackValue(1); opIndex = interpreterProxy->stackIntegerValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } _return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, opIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* Bit logic here is only implemented for positive integers or Zero; if rec or arg is negative, it fails. */ EXPORT(sqInt) primDigitBitOr(void) { sqInt firstInteger; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } _return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, orOpIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primDigitBitShift(void) { sqInt aLarge; sqInt aLargeInteger; sqInt anInteger; sqInt rShift; sqInt shiftCount; sqInt _return_value; shiftCount = interpreterProxy->stackIntegerValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); anInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if ((anInteger & 1)) { /* convert it to a not normalized LargeInteger */ aLarge = createLargeFromSmallInteger(anInteger); } else { aLarge = anInteger; } if (shiftCount >= 0) { _return_value = bytesLshift(aLarge, shiftCount); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { rShift = 0 - shiftCount; /* begin normalize: */ aLargeInteger = bytesRshiftbyteslookfirst(aLarge, rShift & 7, ((usqInt) rShift >> 3), interpreterProxy->slotSizeOf(aLarge)); /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(aLargeInteger)) == (interpreterProxy->classLargePositiveInteger())) { _return_value = normalizePositive(aLargeInteger); goto l1; } else { _return_value = normalizeNegative(aLargeInteger); goto l1; } l1: /* end normalize: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } EXPORT(sqInt) primDigitBitShiftMagnitude(void) { sqInt aLarge; sqInt aLargeInteger; sqInt anInteger; sqInt rShift; sqInt shiftCount; sqInt _return_value; shiftCount = interpreterProxy->stackIntegerValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); anInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if ((anInteger & 1)) { /* convert it to a not normalized LargeInteger */ aLarge = createLargeFromSmallInteger(anInteger); } else { aLarge = anInteger; } if (shiftCount >= 0) { _return_value = bytesLshift(aLarge, shiftCount); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { rShift = 0 - shiftCount; /* begin normalize: */ aLargeInteger = bytesRshiftbyteslookfirst(aLarge, rShift & 7, ((usqInt) rShift >> 3), interpreterProxy->slotSizeOf(aLarge)); /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(aLargeInteger)) == (interpreterProxy->classLargePositiveInteger())) { _return_value = normalizePositive(aLargeInteger); goto l1; } else { _return_value = normalizeNegative(aLargeInteger); goto l1; } l1: /* end normalize: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } /* Bit logic here is only implemented for positive integers or Zero; if rec or arg is negative, it fails. */ EXPORT(sqInt) primDigitBitXor(void) { sqInt firstInteger; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } _return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, xorOpIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primDigitCompare(void) { sqInt firstInteger; sqInt firstVal; sqInt secondInteger; sqInt secondVal; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { if ((secondInteger & 1)) { if (((firstVal = (firstInteger >> 1))) > ((secondVal = (secondInteger >> 1)))) { _return_value = interpreterProxy->integerObjectOf(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { if (firstVal < secondVal) { _return_value = interpreterProxy->integerObjectOf(-1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { _return_value = interpreterProxy->integerObjectOf(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } } else { _return_value = interpreterProxy->integerObjectOf(-1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } else { if ((secondInteger & 1)) { _return_value = interpreterProxy->integerObjectOf(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } else { _return_value = digitCompareLargewith(firstInteger, secondInteger); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } } EXPORT(sqInt) primDigitCompareWith(void) { sqInt firstInteger; sqInt firstVal; sqInt secondInteger; sqInt secondVal; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { if ((secondInteger & 1)) { if (((firstVal = (firstInteger >> 1))) > ((secondVal = (secondInteger >> 1)))) { _return_value = interpreterProxy->integerObjectOf(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { if (firstVal < secondVal) { _return_value = interpreterProxy->integerObjectOf(-1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { _return_value = interpreterProxy->integerObjectOf(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } } else { _return_value = interpreterProxy->integerObjectOf(-1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } else { if ((secondInteger & 1)) { _return_value = interpreterProxy->integerObjectOf(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { _return_value = digitCompareLargewith(firstInteger, secondInteger); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } } /* Answer the result of dividing firstInteger by secondInteger. Fail if parameters are not integers, not normalized or secondInteger is zero. */ EXPORT(sqInt) primDigitDivNegative(void) { sqInt firstAsLargeInteger; sqInt firstInteger; sqInt neg; sqInt secondAsLargeInteger; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); secondInteger = interpreterProxy->stackValue(1); neg = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); firstInteger = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } if (!(isNormalized(firstInteger))) { /* missing DebugCode */; interpreterProxy->primitiveFail(); return null; } if (!(isNormalized(secondInteger))) { /* missing DebugCode */; interpreterProxy->primitiveFail(); return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert to LargeInteger */ firstAsLargeInteger = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstAsLargeInteger = firstInteger; } if ((secondInteger & 1)) { if (((secondInteger >> 1)) == 0) { interpreterProxy->primitiveFail(); return null; } interpreterProxy->pushRemappableOop(firstAsLargeInteger); secondAsLargeInteger = createLargeFromSmallInteger(secondInteger); firstAsLargeInteger = interpreterProxy->popRemappableOop(); } else { secondAsLargeInteger = secondInteger; } _return_value = digitDivLargewithnegative(firstAsLargeInteger, secondAsLargeInteger, neg); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Answer the result of dividing firstInteger by secondInteger. Fail if parameters are not integers or secondInteger is zero. */ EXPORT(sqInt) primDigitDivWithNegative(void) { sqInt firstAsLargeInteger; sqInt firstInteger; sqInt neg; sqInt secondAsLargeInteger; sqInt secondInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); firstInteger = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); secondInteger = interpreterProxy->stackValue(1); neg = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert to LargeInteger */ firstAsLargeInteger = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstAsLargeInteger = firstInteger; } if ((secondInteger & 1)) { if (((secondInteger >> 1)) == 0) { interpreterProxy->primitiveFail(); return null; } interpreterProxy->pushRemappableOop(firstAsLargeInteger); secondAsLargeInteger = createLargeFromSmallInteger(secondInteger); firstAsLargeInteger = interpreterProxy->popRemappableOop(); } else { secondAsLargeInteger = secondInteger; } _return_value = digitDivLargewithnegative(firstAsLargeInteger, secondAsLargeInteger, neg); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primDigitMultiplyNegative(void) { sqInt firstInteger; sqInt firstLarge; sqInt neg; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); secondInteger = interpreterProxy->stackValue(1); neg = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); firstInteger = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitMultiplyLargewithnegative(firstLarge, secondLarge, neg); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primDigitMultiplyWithNegative(void) { sqInt firstInteger; sqInt firstLarge; sqInt neg; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Integer")); firstInteger = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); secondInteger = interpreterProxy->stackValue(1); neg = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitMultiplyLargewithnegative(firstLarge, secondLarge, neg); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primDigitSubtract(void) { sqInt firstInteger; sqInt firstLarge; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitSubLargewith(firstLarge, secondLarge); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primDigitSubtractWith(void) { sqInt firstInteger; sqInt firstLarge; sqInt secondInteger; sqInt secondLarge; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); firstInteger = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); secondInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((firstInteger & 1)) { interpreterProxy->pushRemappableOop(secondInteger); /* convert it to a not normalized LargeInteger */ firstLarge = createLargeFromSmallInteger(firstInteger); secondInteger = interpreterProxy->popRemappableOop(); } else { firstLarge = firstInteger; } if ((secondInteger & 1)) { interpreterProxy->pushRemappableOop(firstLarge); /* convert it to a not normalized LargeInteger */ secondLarge = createLargeFromSmallInteger(secondInteger); firstLarge = interpreterProxy->popRemappableOop(); } else { secondLarge = secondInteger; } _return_value = digitSubLargewith(firstLarge, secondLarge); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* If calling this primitive fails, then C module does not exist. */ EXPORT(sqInt) primGetModuleName(void) { sqInt i; sqInt strLen; sqInt strOop; char *strPtr; /* missing DebugCode */; strLen = strlen(getModuleName()); strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i = 0; i <= (strLen - 1); i += 1) { strPtr[i] = ((getModuleName())[i]); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, strOop); return null; } /* Parameter specification #(Integer) doesn't convert! */ EXPORT(sqInt) primNormalize(void) { sqInt anInteger; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Integer")); anInteger = interpreterProxy->stackValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((anInteger & 1)) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, anInteger); return null; } /* begin normalize: */ /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(anInteger)) == (interpreterProxy->classLargePositiveInteger())) { _return_value = normalizePositive(anInteger); goto l1; } else { _return_value = normalizeNegative(anInteger); goto l1; } l1: /* end normalize: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primNormalizeNegative(void) { sqInt rcvr; sqInt _return_value; /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "LargeNegativeInteger")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } _return_value = normalizeNegative(rcvr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primNormalizePositive(void) { sqInt rcvr; sqInt _return_value; /* missing DebugCode */; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "LargePositiveInteger")); rcvr = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } _return_value = normalizePositive(rcvr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } /* Flag for marking methods for later thinking. */ static sqInt think(void) { /* missing DebugCode */; return null; } /* Argument bytesOop must not be aSmallInteger! */ static sqInt unsafeByteOfat(sqInt bytesOop, sqInt ix) { unsigned char *pointer; return ((pointer = interpreterProxy->firstIndexableField(bytesOop)))[ix - 1]; } EXPORT(sqInt) _primDigitBitShift(void) { sqInt aLarge; sqInt aLargeInteger; sqInt anInteger; sqInt rShift; sqInt shiftCount; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Integer")); anInteger = interpreterProxy->stackValue(1); shiftCount = interpreterProxy->stackIntegerValue(0); /* missing DebugCode */; if (interpreterProxy->failed()) { return null; } if ((anInteger & 1)) { /* convert it to a not normalized LargeInteger */ aLarge = createLargeFromSmallInteger(anInteger); } else { aLarge = anInteger; } if (shiftCount >= 0) { _return_value = bytesLshift(aLarge, shiftCount); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { rShift = 0 - shiftCount; /* begin normalize: */ aLargeInteger = bytesRshiftbyteslookfirst(aLarge, rShift & 7, ((usqInt) rShift >> 3), interpreterProxy->slotSizeOf(aLarge)); /* missing DebugCode */; if ((interpreterProxy->fetchClassOf(aLargeInteger)) == (interpreterProxy->classLargePositiveInteger())) { _return_value = normalizePositive(aLargeInteger); goto l1; } else { _return_value = normalizeNegative(aLargeInteger); goto l1; } l1: /* end normalize: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } #ifdef SQUEAK_BUILTIN_PLUGIN void* LargeIntegers_exports[][3] = { {"LargeIntegers", "getModuleName", (void*)getModuleName}, {"LargeIntegers", "primAnyBitFromTo", (void*)primAnyBitFromTo}, {"LargeIntegers", "primAsLargeInteger", (void*)primAsLargeInteger}, {"LargeIntegers", "primCheckIfCModuleExists", (void*)primCheckIfCModuleExists}, {"LargeIntegers", "primDigitAdd", (void*)primDigitAdd}, {"LargeIntegers", "primDigitAddWith", (void*)primDigitAddWith}, {"LargeIntegers", "primDigitBitAnd", (void*)primDigitBitAnd}, {"LargeIntegers", "primDigitBitLogicWithOp", (void*)primDigitBitLogicWithOp}, {"LargeIntegers", "primDigitBitOr", (void*)primDigitBitOr}, {"LargeIntegers", "primDigitBitShift", (void*)primDigitBitShift}, {"LargeIntegers", "primDigitBitShiftMagnitude", (void*)primDigitBitShiftMagnitude}, {"LargeIntegers", "primDigitBitXor", (void*)primDigitBitXor}, {"LargeIntegers", "primDigitCompare", (void*)primDigitCompare}, {"LargeIntegers", "primDigitCompareWith", (void*)primDigitCompareWith}, {"LargeIntegers", "primDigitDivNegative", (void*)primDigitDivNegative}, {"LargeIntegers", "primDigitDivWithNegative", (void*)primDigitDivWithNegative}, {"LargeIntegers", "primDigitMultiplyNegative", (void*)primDigitMultiplyNegative}, {"LargeIntegers", "primDigitMultiplyWithNegative", (void*)primDigitMultiplyWithNegative}, {"LargeIntegers", "primDigitSubtract", (void*)primDigitSubtract}, {"LargeIntegers", "primDigitSubtractWith", (void*)primDigitSubtractWith}, {"LargeIntegers", "primGetModuleName", (void*)primGetModuleName}, {"LargeIntegers", "primNormalize", (void*)primNormalize}, {"LargeIntegers", "primNormalizeNegative", (void*)primNormalizeNegative}, {"LargeIntegers", "primNormalizePositive", (void*)primNormalizePositive}, {"LargeIntegers", "setInterpreter", (void*)setInterpreter}, {"LargeIntegers", "_primDigitBitShift", (void*)_primDigitBitShift}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/LocalePlugin/LocalePlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from LocalePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "LocalePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "LocalePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveCountry(void); EXPORT(sqInt) primitiveCurrencyNotation(void); EXPORT(sqInt) primitiveCurrencySymbol(void); EXPORT(sqInt) primitiveDaylightSavings(void); EXPORT(sqInt) primitiveDecimalSymbol(void); EXPORT(sqInt) primitiveDigitGroupingSymbol(void); EXPORT(sqInt) primitiveLanguage(void); EXPORT(sqInt) primitiveLongDateFormat(void); EXPORT(sqInt) primitiveMeasurementMetric(void); EXPORT(sqInt) primitiveShortDateFormat(void); EXPORT(sqInt) primitiveTimeFormat(void); EXPORT(sqInt) primitiveTimezoneOffset(void); EXPORT(sqInt) primitiveVMOffsetToUTC(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "LocalePlugin VMMaker-oscog.dtl.57 (i)" #else "LocalePlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return sqLocInitialize(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* return a 3 char string describing the country in use. ISO 3166 is the relevant source here; see http://www.unicode.org/onlinedat/countries.html for details. Using the 3 character Alpha-3 codes */ EXPORT(sqInt) primitiveCountry(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 3); sqLocGetCountryInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying whether the currency symbol is pre or post fix. true -> pre */ EXPORT(sqInt) primitiveCurrencyNotation(void) { sqInt _return_value; _return_value = ((sqLocCurrencyNotation())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a string describing the currency symbol used Still need to find details on standard symbols - ISO 4217 is supposed to be it but cannot find on web */ EXPORT(sqInt) primitiveCurrencySymbol(void) { sqInt length; sqInt oop; length = sqLocCurrencySymbolSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetCurrencySymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying the DST setting. true -> active */ EXPORT(sqInt) primitiveDaylightSavings(void) { sqInt _return_value; _return_value = ((sqLocDaylightSavings())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a 1 char string describing the decimal symbol used - usually a . or a , */ EXPORT(sqInt) primitiveDecimalSymbol(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 1); sqLocGetDecimalSymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a 1 char string describing the digitGrouping symbol used - usually a . or a , between triples of digits */ EXPORT(sqInt) primitiveDigitGroupingSymbol(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 1); sqLocGetDigitGroupingSymbolInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a 3 char string describing the language in use. ISO 639 is the relevant source here; see http://www.w3.org/WAI/ER/IG/ert/iso639.html for details */ EXPORT(sqInt) primitiveLanguage(void) { sqInt oop; oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), 3); sqLocGetLanguageInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a string describing the long date formatting. Format is made up of d day, m month, y year, double symbol is null padded, single not padded (m=6, mm=06) dddd weekday mmmm month nam */ EXPORT(sqInt) primitiveLongDateFormat(void) { sqInt length; sqInt oop; length = sqLocLongDateFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetLongDateFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a boolean specifying whether the currency symbol is pre or post fix. true -> pre */ EXPORT(sqInt) primitiveMeasurementMetric(void) { sqInt _return_value; _return_value = ((sqLocMeasurementMetric())? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return a string describing the long date formatting. Format is made up of d day, m month, y year, double symbol is null padded, single not padded (m=6, mm=06) dddd weekday mmmm month nam */ EXPORT(sqInt) primitiveShortDateFormat(void) { sqInt length; sqInt oop; length = sqLocShortDateFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetShortDateFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return a string describing the time formatting. Format is made up of h hour (h 12, H 24), m minute, s seconds, x (am/pm String) double symbol is null padded, single not padded (h=6, hh=06) */ EXPORT(sqInt) primitiveTimeFormat(void) { sqInt length; sqInt oop; length = sqLocTimeFormatSize(); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); sqLocGetTimeFormatInto(interpreterProxy->firstIndexableField(oop)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, oop); return null; } /* return the number of minutes this VM's time value is offset from UTC */ EXPORT(sqInt) primitiveTimezoneOffset(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sqLocGetTimezoneOffset())); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* return the number of minutes this VM's time value is offset from UTC */ EXPORT(sqInt) primitiveVMOffsetToUTC(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sqLocGetVMOffsetToUTC())); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* LocalePlugin_exports[][3] = { {"LocalePlugin", "getModuleName", (void*)getModuleName}, {"LocalePlugin", "initialiseModule", (void*)initialiseModule}, {"LocalePlugin", "primitiveCountry", (void*)primitiveCountry}, {"LocalePlugin", "primitiveCurrencyNotation", (void*)primitiveCurrencyNotation}, {"LocalePlugin", "primitiveCurrencySymbol", (void*)primitiveCurrencySymbol}, {"LocalePlugin", "primitiveDaylightSavings", (void*)primitiveDaylightSavings}, {"LocalePlugin", "primitiveDecimalSymbol", (void*)primitiveDecimalSymbol}, {"LocalePlugin", "primitiveDigitGroupingSymbol", (void*)primitiveDigitGroupingSymbol}, {"LocalePlugin", "primitiveLanguage", (void*)primitiveLanguage}, {"LocalePlugin", "primitiveLongDateFormat", (void*)primitiveLongDateFormat}, {"LocalePlugin", "primitiveMeasurementMetric", (void*)primitiveMeasurementMetric}, {"LocalePlugin", "primitiveShortDateFormat", (void*)primitiveShortDateFormat}, {"LocalePlugin", "primitiveTimeFormat", (void*)primitiveTimeFormat}, {"LocalePlugin", "primitiveTimezoneOffset", (void*)primitiveTimezoneOffset}, {"LocalePlugin", "primitiveVMOffsetToUTC", (void*)primitiveVMOffsetToUTC}, {"LocalePlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/MIDIPlugin/MIDIPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from MIDIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "MIDIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "MIDIPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveMIDIClosePort(void); EXPORT(sqInt) primitiveMIDIGetClock(void); EXPORT(sqInt) primitiveMIDIGetPortCount(void); EXPORT(sqInt) primitiveMIDIGetPortDirectionality(void); EXPORT(sqInt) primitiveMIDIGetPortName(void); EXPORT(sqInt) primitiveMIDIOpenPort(void); EXPORT(sqInt) primitiveMIDIParameterGet(void); EXPORT(sqInt) primitiveMIDIParameterGetOrSet(void); EXPORT(sqInt) primitiveMIDIParameterSet(void); EXPORT(sqInt) primitiveMIDIRead(void); EXPORT(sqInt) primitiveMIDIWrite(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "MIDIPlugin VMMaker-oscog.dtl.57 (i)" #else "MIDIPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return midiInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveMIDIClosePort(void) { sqInt portNum; portNum = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } sqMIDIClosePort(portNum); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Return the value of the MIDI clock as a SmallInteger. The range is limited to SmallInteger maxVal / 2 to allow scheduling MIDI events into the future without overflowing a SmallInteger. The sqMIDIGetClock function is assumed to wrap at or before 16r20000000. */ EXPORT(sqInt) primitiveMIDIGetClock(void) { sqInt clockValue; sqInt _return_value; clockValue = (sqMIDIGetClock()) & 536870911; _return_value = interpreterProxy->integerObjectOf(clockValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveMIDIGetPortCount(void) { sqInt n; sqInt _return_value; n = sqMIDIGetPortCount(); _return_value = interpreterProxy->integerObjectOf(n); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveMIDIGetPortDirectionality(void) { sqInt dir; sqInt portNum; sqInt _return_value; portNum = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } dir = sqMIDIGetPortDirectionality(portNum); _return_value = interpreterProxy->integerObjectOf(dir); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveMIDIGetPortName(void) { sqInt nameObj; char * namePtr; char portName[256]; sqInt portNum; sqInt sz; portNum = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } sz = sqMIDIGetPortName(portNum, (int) &portName, 255); nameObj = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), sz); if (interpreterProxy->failed()) { return null; } namePtr = ((char *) interpreterProxy->firstIndexableField(nameObj)); memcpy(namePtr, portName, sz); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, nameObj); return null; } EXPORT(sqInt) primitiveMIDIOpenPort(void) { sqInt clockRate; sqInt portNum; sqInt semaIndex; portNum = interpreterProxy->stackIntegerValue(2); semaIndex = interpreterProxy->stackIntegerValue(1); clockRate = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } sqMIDIOpenPort(portNum, semaIndex, clockRate); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* read parameter */ EXPORT(sqInt) primitiveMIDIParameterGet(void) { sqInt currentValue; sqInt whichParameter; sqInt _return_value; whichParameter = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } currentValue = sqMIDIParameterGet(whichParameter); _return_value = interpreterProxy->integerObjectOf(currentValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Backward compatibility */ EXPORT(sqInt) primitiveMIDIParameterGetOrSet(void) { if ((interpreterProxy->methodArgumentCount()) == 1) { return primitiveMIDIParameterGet(); } else { return primitiveMIDIParameterSet(); } } /* write parameter */ EXPORT(sqInt) primitiveMIDIParameterSet(void) { sqInt newValue; sqInt whichParameter; whichParameter = interpreterProxy->stackIntegerValue(1); newValue = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } sqMIDIParameterSet(whichParameter, newValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveMIDIRead(void) { char *array; sqInt arrayLength; sqInt bytesRead; sqInt portNum; sqInt _return_value; portNum = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } arrayLength = interpreterProxy->byteSizeOf(((sqInt)(long)(array) - 4)); bytesRead = sqMIDIPortReadInto(portNum, arrayLength, ((sqInt)array)); _return_value = interpreterProxy->integerObjectOf(bytesRead); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveMIDIWrite(void) { char *array; sqInt arrayLength; sqInt bytesWritten; sqInt portNum; sqInt time; sqInt _return_value; portNum = interpreterProxy->stackIntegerValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); time = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } arrayLength = interpreterProxy->byteSizeOf(((sqInt)(long)(array) - 4)); bytesWritten = sqMIDIPortWriteFromAt(portNum, arrayLength, ((sqInt)array), time); _return_value = interpreterProxy->integerObjectOf(bytesWritten); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return midiShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* MIDIPlugin_exports[][3] = { {"MIDIPlugin", "getModuleName", (void*)getModuleName}, {"MIDIPlugin", "initialiseModule", (void*)initialiseModule}, {"MIDIPlugin", "primitiveMIDIClosePort", (void*)primitiveMIDIClosePort}, {"MIDIPlugin", "primitiveMIDIGetClock", (void*)primitiveMIDIGetClock}, {"MIDIPlugin", "primitiveMIDIGetPortCount", (void*)primitiveMIDIGetPortCount}, {"MIDIPlugin", "primitiveMIDIGetPortDirectionality", (void*)primitiveMIDIGetPortDirectionality}, {"MIDIPlugin", "primitiveMIDIGetPortName", (void*)primitiveMIDIGetPortName}, {"MIDIPlugin", "primitiveMIDIOpenPort", (void*)primitiveMIDIOpenPort}, {"MIDIPlugin", "primitiveMIDIParameterGet", (void*)primitiveMIDIParameterGet}, {"MIDIPlugin", "primitiveMIDIParameterGetOrSet", (void*)primitiveMIDIParameterGetOrSet}, {"MIDIPlugin", "primitiveMIDIParameterSet", (void*)primitiveMIDIParameterSet}, {"MIDIPlugin", "primitiveMIDIRead", (void*)primitiveMIDIRead}, {"MIDIPlugin", "primitiveMIDIWrite", (void*)primitiveMIDIWrite}, {"MIDIPlugin", "setInterpreter", (void*)setInterpreter}, {"MIDIPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/Matrix2x3Plugin/Matrix2x3Plugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from Matrix2x3Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "Matrix2x3Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static float * loadArgumentMatrix(sqInt matrix); static sqInt loadArgumentPoint(sqInt point); static sqInt matrix2x3ComposeMatrixwithinto(const float *m1, const float *m2, float *m3); static sqInt matrix2x3InvertPoint(float *m); static sqInt matrix2x3TransformPoint(float *m); static sqInt msg(char *s); static sqInt okayIntValue(sqInt value); EXPORT(sqInt) primitiveComposeMatrix(void); EXPORT(sqInt) primitiveInvertPoint(void); EXPORT(sqInt) primitiveInvertRectInto(void); EXPORT(sqInt) primitiveIsIdentity(void); EXPORT(sqInt) primitiveIsPureTranslation(void); EXPORT(sqInt) primitiveTransformPoint(void); EXPORT(sqInt) primitiveTransformRectInto(void); static sqInt roundAndStoreResultPoint(sqInt nItemsToPop); static sqInt roundAndStoreResultRectx0y0x1y1(sqInt dstOop, double x0, double y0, double x1, double y1); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static double m23ArgX; static double m23ArgY; static double m23ResultX; static double m23ResultY; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Matrix2x3Plugin VMMaker-oscog.dtl.57 (i)" #else "Matrix2x3Plugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* Load the argument matrix */ static float * loadArgumentMatrix(sqInt matrix) { if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(matrix)) && ((interpreterProxy->slotSizeOf(matrix)) == 6))) { interpreterProxy->primitiveFail(); return null; } return ((float *) (interpreterProxy->firstIndexableField(matrix))); } /* Load the argument point into m23ArgX and m23ArgY */ static sqInt loadArgumentPoint(sqInt point) { sqInt isInt; sqInt oop; if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(point)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->fetchPointerofObject(0, point); isInt = (oop & 1); if (!(isInt || (interpreterProxy->isFloatObject(oop)))) { return interpreterProxy->primitiveFail(); } if (isInt) { m23ArgX = (oop >> 1); } else { m23ArgX = interpreterProxy->floatValueOf(oop); } oop = interpreterProxy->fetchPointerofObject(1, point); isInt = (oop & 1); if (!(isInt || (interpreterProxy->isFloatObject(oop)))) { return interpreterProxy->primitiveFail(); } if (isInt) { m23ArgY = (oop >> 1); } else { m23ArgY = interpreterProxy->floatValueOf(oop); } } /* Multiply matrix m1 with m2 and store the result into m3. */ static sqInt matrix2x3ComposeMatrixwithinto(const float *m1, const float *m2, float *m3) { double a11; double a12; double a13; double a21; double a22; double a23; a11 = ((m1[0]) * (m2[0])) + ((m1[1]) * (m2[3])); a12 = ((m1[0]) * (m2[1])) + ((m1[1]) * (m2[4])); a13 = (((m1[0]) * (m2[2])) + ((m1[1]) * (m2[5]))) + (m1[2]); a21 = ((m1[3]) * (m2[0])) + ((m1[4]) * (m2[3])); a22 = ((m1[3]) * (m2[1])) + ((m1[4]) * (m2[4])); a23 = (((m1[3]) * (m2[2])) + ((m1[4]) * (m2[5]))) + (m1[5]); m3[0] = (((float) a11)); m3[1] = (((float) a12)); m3[2] = (((float) a13)); m3[3] = (((float) a21)); m3[4] = (((float) a22)); m3[5] = (((float) a23)); } /* Invert the pre-loaded argument point by the given matrix */ static sqInt matrix2x3InvertPoint(float *m) { double det; double detX; double detY; double x; double y; x = m23ArgX - (m[2]); y = m23ArgY - (m[5]); det = ((m[0]) * (m[4])) - ((m[1]) * (m[3])); if (det == 0.0) { return interpreterProxy->primitiveFail(); } det = 1.0 / det; detX = (x * (m[4])) - ((m[1]) * y); detY = ((m[0]) * y) - (x * (m[3])); m23ResultX = detX * det; m23ResultY = detY * det; } /* Transform the pre-loaded argument point by the given matrix */ static sqInt matrix2x3TransformPoint(float *m) { m23ResultX = ((m23ArgX * (m[0])) + (m23ArgY * (m[1]))) + (m[2]); m23ResultY = ((m23ArgX * (m[3])) + (m23ArgY * (m[4]))) + (m[5]); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } static sqInt okayIntValue(sqInt value) { return (value >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))); } EXPORT(sqInt) primitiveComposeMatrix(void) { double a11; double a12; double a13; double a21; double a22; double a23; float *m1; float *m2; float *m3; sqInt matrix; sqInt matrix1; sqInt matrix2; sqInt result; ; /* begin loadArgumentMatrix: */ matrix = result = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { m3 = null; goto l1; } if (!((interpreterProxy->isWords(matrix)) && ((interpreterProxy->slotSizeOf(matrix)) == 6))) { interpreterProxy->primitiveFail(); m3 = null; goto l1; } m3 = ((float *) (interpreterProxy->firstIndexableField(matrix))); l1: /* end loadArgumentMatrix: */; /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { m2 = null; goto l2; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); m2 = null; goto l2; } m2 = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l2: /* end loadArgumentMatrix: */; /* begin loadArgumentMatrix: */ matrix2 = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { m1 = null; goto l3; } if (!((interpreterProxy->isWords(matrix2)) && ((interpreterProxy->slotSizeOf(matrix2)) == 6))) { interpreterProxy->primitiveFail(); m1 = null; goto l3; } m1 = ((float *) (interpreterProxy->firstIndexableField(matrix2))); l3: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } /* begin matrix2x3ComposeMatrix:with:into: */ a11 = ((m1[0]) * (m2[0])) + ((m1[1]) * (m2[3])); a12 = ((m1[0]) * (m2[1])) + ((m1[1]) * (m2[4])); a13 = (((m1[0]) * (m2[2])) + ((m1[1]) * (m2[5]))) + (m1[2]); a21 = ((m1[3]) * (m2[0])) + ((m1[4]) * (m2[3])); a22 = ((m1[3]) * (m2[1])) + ((m1[4]) * (m2[4])); a23 = (((m1[3]) * (m2[2])) + ((m1[4]) * (m2[5]))) + (m1[5]); m3[0] = (((float) a11)); m3[1] = (((float) a12)); m3[2] = (((float) a13)); m3[3] = (((float) a21)); m3[4] = (((float) a22)); m3[5] = (((float) a23)); interpreterProxy->popthenPush(3, result); } EXPORT(sqInt) primitiveInvertPoint(void) { float *matrix; sqInt matrix1; loadArgumentPoint(interpreterProxy->stackObjectValue(0)); /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } matrix2x3InvertPoint(matrix); if (!(interpreterProxy->failed())) { /* begin roundAndStoreResultPoint: */ m23ResultX += 0.5; m23ResultY += 0.5; if (!((m23ResultX >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { interpreterProxy->primitiveFail(); goto l2; } if (!((m23ResultY >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { interpreterProxy->primitiveFail(); goto l2; } interpreterProxy->popthenPush(2, interpreterProxy->makePointwithxValueyValue(((sqInt)m23ResultX), ((sqInt)m23ResultY))); l2: /* end roundAndStoreResultPoint: */; } } EXPORT(sqInt) primitiveInvertRectInto(void) { double cornerX; double cornerY; sqInt dstOop; float *matrix; sqInt matrix1; double maxX; double maxY; double minX; double minY; double originX; double originY; sqInt srcOop; dstOop = interpreterProxy->stackObjectValue(0); srcOop = interpreterProxy->stackObjectValue(1); /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(srcOop)) == (interpreterProxy->fetchClassOf(dstOop)))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isPointers(srcOop))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(srcOop)) == 2)) { return interpreterProxy->primitiveFail(); } loadArgumentPoint(interpreterProxy->fetchPointerofObject(0, srcOop)); if (interpreterProxy->failed()) { return null; } originX = m23ArgX; originY = m23ArgY; matrix2x3InvertPoint(matrix); minX = maxX = m23ResultX; /* Load bottom-right point */ minY = maxY = m23ResultY; loadArgumentPoint(interpreterProxy->fetchPointerofObject(1, srcOop)); if (interpreterProxy->failed()) { return null; } cornerX = m23ArgX; cornerY = m23ArgY; matrix2x3InvertPoint(matrix); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); /* Load top-right point */ maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); m23ArgX = cornerX; m23ArgY = originY; matrix2x3InvertPoint(matrix); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); /* Load bottom-left point */ maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); m23ArgX = originX; m23ArgY = cornerY; matrix2x3InvertPoint(matrix); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); if (!(interpreterProxy->failed())) { dstOop = roundAndStoreResultRectx0y0x1y1(dstOop, minX, minY, maxX, maxY); } if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(3, dstOop); } } EXPORT(sqInt) primitiveIsIdentity(void) { float *matrix; sqInt matrix1; /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); interpreterProxy->pushBool(((((((matrix[0]) == (((float) 1.0))) && ((matrix[1]) == (((float) 0.0)))) && ((matrix[2]) == (((float) 0.0)))) && ((matrix[3]) == (((float) 0.0)))) && ((matrix[4]) == (((float) 1.0)))) && ((matrix[5]) == (((float) 0.0)))); } EXPORT(sqInt) primitiveIsPureTranslation(void) { float *matrix; sqInt matrix1; /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); interpreterProxy->pushBool(((((matrix[0]) == (((float) 1.0))) && ((matrix[1]) == (((float) 0.0)))) && ((matrix[3]) == (((float) 0.0)))) && ((matrix[4]) == (((float) 1.0)))); } EXPORT(sqInt) primitiveTransformPoint(void) { float *matrix; sqInt matrix1; loadArgumentPoint(interpreterProxy->stackObjectValue(0)); /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } /* begin matrix2x3TransformPoint: */ m23ResultX = ((m23ArgX * (matrix[0])) + (m23ArgY * (matrix[1]))) + (matrix[2]); m23ResultY = ((m23ArgX * (matrix[3])) + (m23ArgY * (matrix[4]))) + (matrix[5]); /* begin roundAndStoreResultPoint: */ m23ResultX += 0.5; m23ResultY += 0.5; if (!((m23ResultX >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { interpreterProxy->primitiveFail(); goto l2; } if (!((m23ResultY >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { interpreterProxy->primitiveFail(); goto l2; } interpreterProxy->popthenPush(2, interpreterProxy->makePointwithxValueyValue(((sqInt)m23ResultX), ((sqInt)m23ResultY))); l2: /* end roundAndStoreResultPoint: */; } EXPORT(sqInt) primitiveTransformRectInto(void) { double cornerX; double cornerY; sqInt dstOop; float *matrix; sqInt matrix1; double maxX; double maxY; double minX; double minY; double originX; double originY; sqInt srcOop; dstOop = interpreterProxy->stackObjectValue(0); srcOop = interpreterProxy->stackObjectValue(1); /* begin loadArgumentMatrix: */ matrix1 = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { matrix = null; goto l1; } if (!((interpreterProxy->isWords(matrix1)) && ((interpreterProxy->slotSizeOf(matrix1)) == 6))) { interpreterProxy->primitiveFail(); matrix = null; goto l1; } matrix = ((float *) (interpreterProxy->firstIndexableField(matrix1))); l1: /* end loadArgumentMatrix: */; if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(srcOop)) == (interpreterProxy->fetchClassOf(dstOop)))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isPointers(srcOop))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(srcOop)) == 2)) { return interpreterProxy->primitiveFail(); } loadArgumentPoint(interpreterProxy->fetchPointerofObject(0, srcOop)); if (interpreterProxy->failed()) { return null; } originX = m23ArgX; originY = m23ArgY; /* begin matrix2x3TransformPoint: */ m23ResultX = ((m23ArgX * (matrix[0])) + (m23ArgY * (matrix[1]))) + (matrix[2]); m23ResultY = ((m23ArgX * (matrix[3])) + (m23ArgY * (matrix[4]))) + (matrix[5]); minX = maxX = m23ResultX; /* Load bottom-right point */ minY = maxY = m23ResultY; loadArgumentPoint(interpreterProxy->fetchPointerofObject(1, srcOop)); if (interpreterProxy->failed()) { return null; } cornerX = m23ArgX; cornerY = m23ArgY; /* begin matrix2x3TransformPoint: */ m23ResultX = ((m23ArgX * (matrix[0])) + (m23ArgY * (matrix[1]))) + (matrix[2]); m23ResultY = ((m23ArgX * (matrix[3])) + (m23ArgY * (matrix[4]))) + (matrix[5]); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); /* Load top-right point */ maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); m23ArgX = cornerX; m23ArgY = originY; /* begin matrix2x3TransformPoint: */ m23ResultX = ((m23ArgX * (matrix[0])) + (m23ArgY * (matrix[1]))) + (matrix[2]); m23ResultY = ((m23ArgX * (matrix[3])) + (m23ArgY * (matrix[4]))) + (matrix[5]); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); /* Load bottom-left point */ maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); m23ArgX = originX; m23ArgY = cornerY; /* begin matrix2x3TransformPoint: */ m23ResultX = ((m23ArgX * (matrix[0])) + (m23ArgY * (matrix[1]))) + (matrix[2]); m23ResultY = ((m23ArgX * (matrix[3])) + (m23ArgY * (matrix[4]))) + (matrix[5]); minX = ((minX < m23ResultX) ? minX : m23ResultX); maxX = ((maxX < m23ResultX) ? m23ResultX : maxX); minY = ((minY < m23ResultY) ? minY : m23ResultY); maxY = ((maxY < m23ResultY) ? m23ResultY : maxY); dstOop = roundAndStoreResultRectx0y0x1y1(dstOop, minX, minY, maxX, maxY); if (!(interpreterProxy->failed())) { interpreterProxy->popthenPush(3, dstOop); } } /* Store the result of a previous operation. Fail if we cannot represent the result as SmallInteger */ static sqInt roundAndStoreResultPoint(sqInt nItemsToPop) { m23ResultX += 0.5; m23ResultY += 0.5; if (!((m23ResultX >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } if (!((m23ResultY >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(nItemsToPop, interpreterProxy->makePointwithxValueyValue(((sqInt)m23ResultX), ((sqInt)m23ResultY))); } /* Check, round and store the result of a rectangle operation */ static sqInt roundAndStoreResultRectx0y0x1y1(sqInt dstOop, double x0, double y0, double x1, double y1) { sqInt cornerOop; double maxX; double maxY; double minX; double minY; sqInt originOop; sqInt rectOop; minX = x0 + 0.5; if (!((minX >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } maxX = x1 + 0.5; if (!((maxX >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } minY = y0 + 0.5; if (!((minY >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } maxY = y1 + 0.5; if (!((maxY >= (((double) -1073741824 ))) && (m23ResultX <= (((double) 1073741823 ))))) { return interpreterProxy->primitiveFail(); } interpreterProxy->pushRemappableOop(dstOop); originOop = interpreterProxy->makePointwithxValueyValue(((sqInt)minX), ((sqInt)minY)); interpreterProxy->pushRemappableOop(originOop); cornerOop = interpreterProxy->makePointwithxValueyValue(((sqInt)maxX), ((sqInt)maxY)); originOop = interpreterProxy->popRemappableOop(); rectOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, rectOop, originOop); interpreterProxy->storePointerofObjectwithValue(1, rectOop, cornerOop); return rectOop; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* Matrix2x3Plugin_exports[][3] = { {"Matrix2x3Plugin", "getModuleName", (void*)getModuleName}, {"Matrix2x3Plugin", "primitiveComposeMatrix", (void*)primitiveComposeMatrix}, {"Matrix2x3Plugin", "primitiveInvertPoint", (void*)primitiveInvertPoint}, {"Matrix2x3Plugin", "primitiveInvertRectInto", (void*)primitiveInvertRectInto}, {"Matrix2x3Plugin", "primitiveIsIdentity", (void*)primitiveIsIdentity}, {"Matrix2x3Plugin", "primitiveIsPureTranslation", (void*)primitiveIsPureTranslation}, {"Matrix2x3Plugin", "primitiveTransformPoint", (void*)primitiveTransformPoint}, {"Matrix2x3Plugin", "primitiveTransformRectInto", (void*)primitiveTransformRectInto}, {"Matrix2x3Plugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from MiscPrimitivePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "MiscPrimitivePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Proxy Functions ***/ #define stackValue(i) (interpreterProxy->stackValue(i)) #define stackIntegerValue(i) (interpreterProxy->stackIntegerValue(i)) #define successFlag (!interpreterProxy->failed()) #define success(bool) (interpreterProxy->success(bool)) #define arrayValueOf(oop) (interpreterProxy->arrayValueOf(oop)) #define checkedIntegerValueOf(oop) (interpreterProxy->checkedIntegerValueOf(oop)) #define fetchArrayofObject(idx,oop) (interpreterProxy->fetchArrayofObject(idx,oop)) #define fetchFloatofObject(idx,oop) (interpreterProxy->fetchFloatofObject(idx,oop)) #define fetchIntegerofObject(idx,oop) (interpreterProxy->fetchIntegerofObject(idx,oop)) #define floatValueOf(oop) (interpreterProxy->floatValueOf(oop)) #define pop(n) (interpreterProxy->pop(n)) #define pushInteger(n) (interpreterProxy->pushInteger(n)) #define sizeOfSTArrayFromCPrimitive(cPtr) (interpreterProxy->sizeOfSTArrayFromCPrimitive(cPtr)) #define storeIntegerofObjectwithValue(idx,oop,value) (interpreterProxy->storeIntegerofObjectwithValue(idx,oop,value)) #define primitiveFail() interpreterProxy->primitiveFail() /* allows accessing Strings in both C and Smalltalk */ #define asciiValue(c) c /*** Constants ***/ /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "MiscPrimitivePlugin VMMaker-oscog.dtl.57 (i)" #else "MiscPrimitivePlugin VMMaker-oscog.dtl.57 (e)" #endif ; /*** Function Prototypes ***/ static sqInt encodeBytesOfinat(sqInt anInt, unsigned char *ba, sqInt i); static sqInt encodeIntinat(sqInt anInt, unsigned char *ba, sqInt i); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveCompareString(void); EXPORT(sqInt) primitiveCompressToByteArray(void); EXPORT(sqInt) primitiveConvert8BitSigned(void); EXPORT(sqInt) primitiveDecompressFromByteArray(void); EXPORT(sqInt) primitiveFindFirstInString(void); EXPORT(sqInt) primitiveFindSubstring(void); EXPORT(sqInt) primitiveIndexOfAsciiInString(void); EXPORT(sqInt) primitiveStringHash(void); EXPORT(sqInt) primitiveTranslateStringWithTable(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /* Copy the integer anInt into byteArray ba at index i, and return the next index */ static sqInt encodeBytesOfinat(sqInt anInt, unsigned char *ba, sqInt i) { sqInt j; for (j = 0; j <= 3; j += 1) { ba[i + j] = ((((usqInt) anInt) >> ((3 - j) * 8)) & 255); } return i + 4; } /* Encode the integer anInt in byteArray ba at index i, and return the next index. The encoding is as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes */ static sqInt encodeIntinat(sqInt anInt, unsigned char *ba, sqInt i) { sqInt j; if (anInt <= 223) { ba[i] = anInt; return i + 1; } if (anInt <= 7935) { ba[i] = ((((sqInt) anInt >> 8)) + 224); ba[i + 1] = (anInt % 256); return i + 2; } ba[i] = 255; /* begin encodeBytesOf:in:at: */ for (j = 0; j <= 3; j += 1) { ba[(i + 1) + j] = ((((usqInt) anInt) >> ((3 - j) * 8)) & 255); } return (i + 1) + 4; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Return 1, 2 or 3, if string1 is <, =, or > string2, with the collating order of characters given by the order array. */ EXPORT(sqInt) primitiveCompareString(void) { sqInt c1; sqInt c2; sqInt i; sqInt len1; sqInt len2; unsigned char *order; sqInt rcvr; unsigned char *string1; unsigned char *string2; rcvr = stackValue(3); if (!(isBytes(stackValue(2)))) { return primitiveFail(); } string1 = arrayValueOf(stackValue(2)); string1 -= 1; if (!(isBytes(stackValue(1)))) { return primitiveFail(); } string2 = arrayValueOf(stackValue(1)); string2 -= 1; if (!(isBytes(stackValue(0)))) { return primitiveFail(); } order = arrayValueOf(stackValue(0)); order -= 1; if (!(successFlag)) { return null; } len1 = sizeOfSTArrayFromCPrimitive(string1 + 1); len2 = sizeOfSTArrayFromCPrimitive(string2 + 1); for (i = 1; i <= (((len1 < len2) ? len1 : len2)); i += 1) { c1 = order[(string1[i]) + 1]; c2 = order[(string2[i]) + 1]; if (!(c1 == c2)) { if (c1 < c2) { if (!(successFlag)) { return null; } pop(4); pushInteger(1); return null; } else { if (!(successFlag)) { return null; } pop(4); pushInteger(3); return null; } } } if (len1 == len2) { if (!(successFlag)) { return null; } pop(4); pushInteger(2); return null; } if (len1 < len2) { if (!(successFlag)) { return null; } pop(4); pushInteger(1); return null; } else { if (!(successFlag)) { return null; } pop(4); pushInteger(3); return null; } } /* Store a run-coded compression of the receiver into the byteArray ba, and return the last index stored into. ba is assumed to be large enough. The encoding is as follows... S {N D}*. S is the size of the original bitmap, followed by run-coded pairs. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes */ EXPORT(sqInt) primitiveCompressToByteArray(void) { unsigned char *ba; int *bm; sqInt eqBytes; sqInt i; sqInt j; sqInt j1; sqInt j2; sqInt j3; sqInt j4; sqInt j5; sqInt j6; sqInt j7; sqInt k; sqInt lowByte; sqInt m; sqInt rcvr; sqInt size; sqInt word; rcvr = stackValue(2); bm = arrayValueOf(stackValue(1)); bm -= 1; if (!(isBytes(stackValue(0)))) { return primitiveFail(); } ba = arrayValueOf(stackValue(0)); ba -= 1; if (!(successFlag)) { return null; } size = sizeOfSTArrayFromCPrimitive(bm + 1); /* begin encodeInt:in:at: */ if (size <= 223) { ba[1] = size; i = 1 + 1; goto l5; } if (size <= 7935) { ba[1] = ((((sqInt) size >> 8)) + 224); ba[1 + 1] = (size % 256); i = 1 + 2; goto l5; } ba[1] = 255; /* begin encodeBytesOf:in:at: */ for (j7 = 0; j7 <= 3; j7 += 1) { ba[(1 + 1) + j7] = ((((usqInt) size) >> ((3 - j7) * 8)) & 255); } i = (1 + 1) + 4; l5: /* end encodeInt:in:at: */; k = 1; while (k <= size) { word = bm[k]; lowByte = word & 255; eqBytes = (((((usqInt) word) >> 8) & 255) == lowByte) && ((((((usqInt) word) >> 16) & 255) == lowByte) && (((((usqInt) word) >> 24) & 255) == lowByte)); j = k; while ((j < size) && (word == (bm[j + 1]))) { j += 1; } if (j > k) { if (eqBytes) { /* begin encodeInt:in:at: */ if (((((j - k) + 1) * 4) + 1) <= 223) { ba[i] = ((((j - k) + 1) * 4) + 1); i += 1; goto l1; } if (((((j - k) + 1) * 4) + 1) <= 7935) { ba[i] = ((((sqInt) ((((j - k) + 1) * 4) + 1) >> 8)) + 224); ba[i + 1] = (((((j - k) + 1) * 4) + 1) % 256); i += 2; goto l1; } ba[i] = 255; /* begin encodeBytesOf:in:at: */ for (j3 = 0; j3 <= 3; j3 += 1) { ba[(i + 1) + j3] = ((((usqInt) ((((j - k) + 1) * 4) + 1)) >> ((3 - j3) * 8)) & 255); } i = (i + 1) + 4; l1: /* end encodeInt:in:at: */; ba[i] = lowByte; i += 1; } else { /* begin encodeInt:in:at: */ if (((((j - k) + 1) * 4) + 2) <= 223) { ba[i] = ((((j - k) + 1) * 4) + 2); i += 1; goto l2; } if (((((j - k) + 1) * 4) + 2) <= 7935) { ba[i] = ((((sqInt) ((((j - k) + 1) * 4) + 2) >> 8)) + 224); ba[i + 1] = (((((j - k) + 1) * 4) + 2) % 256); i += 2; goto l2; } ba[i] = 255; /* begin encodeBytesOf:in:at: */ for (j4 = 0; j4 <= 3; j4 += 1) { ba[(i + 1) + j4] = ((((usqInt) ((((j - k) + 1) * 4) + 2)) >> ((3 - j4) * 8)) & 255); } i = (i + 1) + 4; l2: /* end encodeInt:in:at: */; /* begin encodeBytesOf:in:at: */ for (j1 = 0; j1 <= 3; j1 += 1) { ba[i + j1] = ((((usqInt) word) >> ((3 - j1) * 8)) & 255); } i += 4; } k = j + 1; } else { if (eqBytes) { /* begin encodeInt:in:at: */ if (((1 * 4) + 1) <= 223) { ba[i] = ((1 * 4) + 1); i += 1; goto l3; } if (((1 * 4) + 1) <= 7935) { ba[i] = ((((sqInt) ((1 * 4) + 1) >> 8)) + 224); ba[i + 1] = (((1 * 4) + 1) % 256); i += 2; goto l3; } ba[i] = 255; /* begin encodeBytesOf:in:at: */ for (j5 = 0; j5 <= 3; j5 += 1) { ba[(i + 1) + j5] = ((((usqInt) ((1 * 4) + 1)) >> ((3 - j5) * 8)) & 255); } i = (i + 1) + 4; l3: /* end encodeInt:in:at: */; ba[i] = lowByte; i += 1; k += 1; } else { while ((j < size) && ((bm[j]) != (bm[j + 1]))) { j += 1; } if (j == size) { j += 1; } /* begin encodeInt:in:at: */ if ((((j - k) * 4) + 3) <= 223) { ba[i] = (((j - k) * 4) + 3); i += 1; goto l4; } if ((((j - k) * 4) + 3) <= 7935) { ba[i] = ((((sqInt) (((j - k) * 4) + 3) >> 8)) + 224); ba[i + 1] = ((((j - k) * 4) + 3) % 256); i += 2; goto l4; } ba[i] = 255; /* begin encodeBytesOf:in:at: */ for (j6 = 0; j6 <= 3; j6 += 1) { ba[(i + 1) + j6] = ((((usqInt) (((j - k) * 4) + 3)) >> ((3 - j6) * 8)) & 255); } i = (i + 1) + 4; l4: /* end encodeInt:in:at: */; for (m = k; m <= (j - 1); m += 1) { /* begin encodeBytesOf:in:at: */ for (j2 = 0; j2 <= 3; j2 += 1) { ba[i + j2] = ((((usqInt) (bm[m])) >> ((3 - j2) * 8)) & 255); } i += 4; } k = j; } } } if (!(successFlag)) { return null; } pop(3); pushInteger(i - 1); return null; } /* Copy the contents of the given array of signed 8-bit samples into the given array of 16-bit signed samples. */ EXPORT(sqInt) primitiveConvert8BitSigned(void) { unsigned char *aByteArray; unsigned short *aSoundBuffer; sqInt i; sqInt n; sqInt rcvr; sqInt s; rcvr = stackValue(2); if (!(isBytes(stackValue(1)))) { return primitiveFail(); } aByteArray = arrayValueOf(stackValue(1)); aByteArray -= 1; aSoundBuffer = arrayValueOf(stackValue(0)); aSoundBuffer -= 1; if (!(successFlag)) { return null; } n = sizeOfSTArrayFromCPrimitive(aByteArray + 1); for (i = 1; i <= n; i += 1) { s = aByteArray[i]; if (s > 127) { aSoundBuffer[i] = (((usqInt) (s - 256) << 8)); } else { aSoundBuffer[i] = (((usqInt) s << 8)); } } if (!(successFlag)) { return null; } pop(2); } /* Decompress the body of a byteArray encoded by compressToByteArray (qv)... The format is simply a sequence of run-coded pairs, {N D}*. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent (could be used to skip from one raster line to the next) 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows (see decodeIntFrom:)... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes */ /* NOTE: If fed with garbage, this routine could read past the end of ba, but it should fail before writing past the ned of bm. */ EXPORT(sqInt) primitiveDecompressFromByteArray(void) { sqInt anInt; unsigned char *ba; int *bm; sqInt code; sqInt data; sqInt end; sqInt i; sqInt index; sqInt j; sqInt k; sqInt m; sqInt n; sqInt pastEnd; sqInt rcvr; rcvr = stackValue(3); bm = arrayValueOf(stackValue(2)); bm -= 1; if (!(isBytes(stackValue(1)))) { return primitiveFail(); } ba = arrayValueOf(stackValue(1)); ba -= 1; index = stackIntegerValue(0); if (!(successFlag)) { return null; } /* byteArray read index */ i = index; end = sizeOfSTArrayFromCPrimitive(ba + 1); /* bitmap write index */ k = 1; pastEnd = (sizeOfSTArrayFromCPrimitive(bm + 1)) + 1; while (i <= end) { /* Decode next run start N */ anInt = ba[i]; i += 1; if (!(anInt <= 223)) { if (anInt <= 254) { anInt = ((anInt - 224) * 256) + (ba[i]); i += 1; } else { anInt = 0; for (j = 1; j <= 4; j += 1) { anInt = (((usqInt) anInt << 8)) + (ba[i]); i += 1; } } } n = ((usqInt) anInt) >> 2; if ((k + n) > pastEnd) { primitiveFail(); return null; } code = anInt & 3; if (code == 0) { null; } if (code == 1) { /* n consecutive words of 4 bytes = the following byte */ data = ba[i]; i += 1; data = data | (((usqInt) data << 8)); data = data | (((usqInt) data << 16)); for (j = 1; j <= n; j += 1) { bm[k] = data; k += 1; } } if (code == 2) { /* n consecutive words = 4 following bytes */ data = 0; for (j = 1; j <= 4; j += 1) { data = (((usqInt) data << 8)) | (ba[i]); i += 1; } for (j = 1; j <= n; j += 1) { bm[k] = data; k += 1; } } if (code == 3) { for (m = 1; m <= n; m += 1) { /* n consecutive words from the data... */ data = 0; for (j = 1; j <= 4; j += 1) { data = (((usqInt) data << 8)) | (ba[i]); i += 1; } bm[k] = data; k += 1; } } } if (!(successFlag)) { return null; } pop(3); } EXPORT(sqInt) primitiveFindFirstInString(void) { unsigned char *aString; sqInt i; char *inclusionMap; sqInt rcvr; sqInt start; sqInt stringSize; rcvr = stackValue(3); if (!(isBytes(stackValue(2)))) { return primitiveFail(); } aString = arrayValueOf(stackValue(2)); aString -= 1; if (!(isBytes(stackValue(1)))) { return primitiveFail(); } inclusionMap = arrayValueOf(stackValue(1)); inclusionMap -= 1; start = stackIntegerValue(0); if (!(successFlag)) { return null; } if ((sizeOfSTArrayFromCPrimitive(inclusionMap + 1)) != 256) { if (!(successFlag)) { return null; } pop(4); pushInteger(0); return null; } i = start; stringSize = sizeOfSTArrayFromCPrimitive(aString + 1); while ((i <= stringSize) && ((inclusionMap[(asciiValue(aString[i])) + 1]) == 0)) { i += 1; } if (i > stringSize) { if (!(successFlag)) { return null; } pop(4); pushInteger(0); return null; } if (!(successFlag)) { return null; } pop(4); pushInteger(i); return null; } /* Answer the index in the string body at which the substring key first occurs, at or beyond start. The match is determined using matchTable, which can be used to effect, eg, case-insensitive matches. If no match is found, zero will be returned. The algorithm below is not optimum -- it is intended to be translated to C which will go so fast that it wont matter. */ EXPORT(sqInt) primitiveFindSubstring(void) { unsigned char *body; sqInt index; unsigned char *key; unsigned char *matchTable; sqInt rcvr; sqInt start; sqInt startIndex; rcvr = stackValue(4); if (!(isBytes(stackValue(3)))) { return primitiveFail(); } key = arrayValueOf(stackValue(3)); key -= 1; if (!(isBytes(stackValue(2)))) { return primitiveFail(); } body = arrayValueOf(stackValue(2)); body -= 1; start = stackIntegerValue(1); if (!(isBytes(stackValue(0)))) { return primitiveFail(); } matchTable = arrayValueOf(stackValue(0)); matchTable -= 1; if (!(successFlag)) { return null; } if ((sizeOfSTArrayFromCPrimitive(key + 1)) == 0) { if (!(successFlag)) { return null; } pop(5); pushInteger(0); return null; } for (startIndex = start; startIndex <= (((sizeOfSTArrayFromCPrimitive(body + 1)) - (sizeOfSTArrayFromCPrimitive(key + 1))) + 1); startIndex += 1) { index = 1; while ((matchTable[(asciiValue(body[(startIndex + index) - 1])) + 1]) == (matchTable[(asciiValue(key[index])) + 1])) { if (index == (sizeOfSTArrayFromCPrimitive(key + 1))) { if (!(successFlag)) { return null; } pop(5); pushInteger(startIndex); return null; } index += 1; } } if (!(successFlag)) { return null; } pop(5); pushInteger(0); return null; } EXPORT(sqInt) primitiveIndexOfAsciiInString(void) { sqInt anInteger; unsigned char *aString; sqInt pos; sqInt rcvr; sqInt start; sqInt stringSize; rcvr = stackValue(3); anInteger = stackIntegerValue(2); if (!(isBytes(stackValue(1)))) { return primitiveFail(); } aString = arrayValueOf(stackValue(1)); aString -= 1; start = stackIntegerValue(0); if (!(successFlag)) { return null; } stringSize = sizeOfSTArrayFromCPrimitive(aString + 1); for (pos = start; pos <= stringSize; pos += 1) { if ((asciiValue(aString[pos])) == anInteger) { if (!(successFlag)) { return null; } pop(4); pushInteger(pos); return null; } } if (!(successFlag)) { return null; } pop(4); pushInteger(0); return null; } /* Answer the hash of a byte-indexed collection, using speciesHash as the initial value. See SmallInteger>>hashMultiply. The primitive should be renamed at a suitable point in the future */ EXPORT(sqInt) primitiveStringHash(void) { unsigned char *aByteArray; sqInt byteArraySize; sqInt hash; sqInt low; sqInt pos; sqInt rcvr; sqInt speciesHash; rcvr = stackValue(2); if (!(isBytes(stackValue(1)))) { return primitiveFail(); } aByteArray = arrayValueOf(stackValue(1)); aByteArray -= 1; speciesHash = stackIntegerValue(0); if (!(successFlag)) { return null; } byteArraySize = sizeOfSTArrayFromCPrimitive(aByteArray + 1); hash = speciesHash & 268435455; for (pos = 1; pos <= byteArraySize; pos += 1) { /* Begin hashMultiply */ hash += aByteArray[pos]; low = hash & 16383; hash = ((9741 * low) + ((((9741 * (((usqInt) hash >> 14))) + (101 * low)) & 16383) * 16384)) & 268435455; } if (!(successFlag)) { return null; } pop(3); pushInteger(hash); return null; } /* translate the characters in the string by the given table, in place */ EXPORT(sqInt) primitiveTranslateStringWithTable(void) { unsigned char *aString; sqInt i; sqInt rcvr; sqInt start; sqInt stop; unsigned char *table; rcvr = stackValue(4); if (!(isBytes(stackValue(3)))) { return primitiveFail(); } aString = arrayValueOf(stackValue(3)); aString -= 1; start = stackIntegerValue(2); stop = stackIntegerValue(1); if (!(isBytes(stackValue(0)))) { return primitiveFail(); } table = arrayValueOf(stackValue(0)); table -= 1; if (!(successFlag)) { return null; } for (i = start; i <= stop; i += 1) { aString[i] = (table[(asciiValue(aString[i])) + 1]); } if (!(successFlag)) { return null; } pop(4); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* MiscPrimitivePlugin_exports[][3] = { {"MiscPrimitivePlugin", "getModuleName", (void*)getModuleName}, {"MiscPrimitivePlugin", "primitiveCompareString", (void*)primitiveCompareString}, {"MiscPrimitivePlugin", "primitiveCompressToByteArray", (void*)primitiveCompressToByteArray}, {"MiscPrimitivePlugin", "primitiveConvert8BitSigned", (void*)primitiveConvert8BitSigned}, {"MiscPrimitivePlugin", "primitiveDecompressFromByteArray", (void*)primitiveDecompressFromByteArray}, {"MiscPrimitivePlugin", "primitiveFindFirstInString", (void*)primitiveFindFirstInString}, {"MiscPrimitivePlugin", "primitiveFindSubstring", (void*)primitiveFindSubstring}, {"MiscPrimitivePlugin", "primitiveIndexOfAsciiInString", (void*)primitiveIndexOfAsciiInString}, {"MiscPrimitivePlugin", "primitiveStringHash", (void*)primitiveStringHash}, {"MiscPrimitivePlugin", "primitiveTranslateStringWithTable", (void*)primitiveTranslateStringWithTable}, {"MiscPrimitivePlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/Mpeg3Plugin/Mpeg3Plugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from Mpeg3Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "Mpeg3Plugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "Mpeg3Plugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt checkFileEntry(mpeg3_t * aMpegFile); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt makeFileEntry(mpeg3_t * aMpegFile); static mpeg3_t * mpeg3tValueOf(sqInt mpeg3tHandle); static sqInt msg(char *s); EXPORT(sqInt) primitiveMPEG3AudioChannels(void); EXPORT(sqInt) primitiveMPEG3AudioSamples(void); EXPORT(sqInt) primitiveMPEG3CheckSig(void); EXPORT(sqInt) primitiveMPEG3Close(void); EXPORT(sqInt) primitiveMPEG3DropFrames(void); EXPORT(sqInt) primitiveMPEG3EndOfAudio(void); EXPORT(sqInt) primitiveMPEG3EndOfVideo(void); EXPORT(sqInt) primitiveMPEG3FrameRate(void); EXPORT(sqInt) primitiveMPEG3GenerateToc(void); EXPORT(sqInt) primitiveMPEG3GetFrame(void); EXPORT(sqInt) primitiveMPEG3GetSample(void); EXPORT(sqInt) primitiveMPEG3GetTime(void); EXPORT(sqInt) primitiveMPEG3HasAudio(void); EXPORT(sqInt) primitiveMPEG3HasVideo(void); EXPORT(sqInt) primitiveMPEG3Open(void); EXPORT(sqInt) primitiveMPEG3OpenABuffer(void); EXPORT(sqInt) primitiveMPEG3PreviousFrame(void); EXPORT(sqInt) primitiveMPEG3ReadAudio(void); EXPORT(sqInt) primitiveMPEG3ReadFrame(void); EXPORT(sqInt) primitiveMPEG3ReadFrameBufferOffset(void); EXPORT(sqInt) primitiveMPEG3ReReadAudio(void); EXPORT(sqInt) primitiveMPEG3SampleRate(void); EXPORT(sqInt) primitiveMPEG3SeekPercentage(void); EXPORT(sqInt) primitiveMPEG3SetCpus(void); EXPORT(sqInt) primitiveMPEG3SetFrame(void); EXPORT(sqInt) primitiveMPEG3SetMmx(void); EXPORT(sqInt) primitiveMPEG3SetSample(void); EXPORT(sqInt) primitiveMPEG3TellPercentage(void); EXPORT(sqInt) primitiveMPEG3TotalAStreams(void); EXPORT(sqInt) primitiveMPEG3TotalVStreams(void); EXPORT(sqInt) primitiveMPEG3VideoFrames(void); EXPORT(sqInt) primitiveMPEG3VideoHeight(void); EXPORT(sqInt) primitiveMPEG3VideoWidth(void); static sqInt removeFileEntry(mpeg3_t * aMpegFile); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static sqInt maximumNumberOfFilesToWatch; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Mpeg3Plugin VMMaker-oscog.dtl.57 (i)" #else "Mpeg3Plugin VMMaker-oscog.dtl.57 (e)" #endif ; static mpeg3_t *mpegFiles[1024+1]; static sqInt checkFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == aMpegFile) { return 1; } } return 0; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { sqInt i; maximumNumberOfFilesToWatch = 1024; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { mpegFiles[i] = 0; } return true; } static sqInt makeFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == 0) { mpegFiles[i] = aMpegFile; return 1; } } return 0; } /* Return a pointer to the first byte of of the mpeg3_t record within the given Smalltalk object, or nil if socketOop is not a mpeg3_t record. */ static mpeg3_t * mpeg3tValueOf(sqInt mpeg3tHandle) { sqInt check; mpeg3_t ** index; interpreterProxy->success((interpreterProxy->isBytes(mpeg3tHandle)) && ((interpreterProxy->byteSizeOf(mpeg3tHandle)) == 4)); if (interpreterProxy->failed()) { return null; } else { index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3tHandle))); check = checkFileEntry(*index); if (check == 0) { return null; } return *index; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* int mpeg3_audio_channels(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3AudioChannels(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber >= (mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_audio_channels(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* long mpeg3_audio_samples(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3AudioSamples(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_audio_samples(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_check_sig(char *path) */ EXPORT(sqInt) primitiveMPEG3CheckSig(void) { char *path; sqInt result; char storage[1024] ; sqInt sz; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } sz = interpreterProxy->byteSizeOf(((sqInt)(long)(path) - 4)); sqFilenameFromStringOpen(storage, path, sz); result = mpeg3_check_sig(storage); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_close(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3Close(void) { mpeg3_t * file; sqInt fileHandle; mpeg3_t ** index; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } removeFileEntry(file); mpeg3_close(file); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(fileHandle))); *index = 0; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream) */ EXPORT(sqInt) primitiveMPEG3DropFrames(void) { sqInt aFrameNumber; sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aFrameNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } result = mpeg3_drop_frames(file,aFrameNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* int mpeg3_end_of_audio(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3EndOfAudio(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_end_of_audio(file,aNumber); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_end_of_video(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3EndOfVideo(void) { sqInt aNumber; mpeg3_t *file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_end_of_video(file,aNumber); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* float mpeg3_frame_rate(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3FrameRate(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; double result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_frame_rate(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_generate_toc_for_Squeak(FILE *output, char *path, int timecode_search, int print_streams, char *buffer) */ EXPORT(sqInt) primitiveMPEG3GenerateToc(void) { char *aString; sqInt bufferSize; mpeg3_t * file; sqInt fileHandle; sqInt streams; sqInt timecode; fileHandle = interpreterProxy->stackValue(3); timecode = interpreterProxy->stackIntegerValue(2); streams = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } bufferSize = interpreterProxy->slotSizeOf(interpreterProxy->stackValue(0)); mpeg3_generate_toc_for_Squeak(file,timecode,streams,aString,bufferSize); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } /* long mpeg3_get_frame(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3GetFrame(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_get_frame(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_width(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3GetSample(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_get_sample(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* double mpeg3_get_time(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3GetTime(void) { mpeg3_t * file; sqInt fileHandle; double result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_get_time(file); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_has_audio(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3HasAudio(void) { mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_has_audio(file); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_has_video(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3HasVideo(void) { mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_has_video(file); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* mpeg3_t* mpeg3_open(char *path) */ EXPORT(sqInt) primitiveMPEG3Open(void) { mpeg3_t ** index; sqInt mpeg3Oop; char *path; char storage[1024]; sqInt sz; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } sz = interpreterProxy->byteSizeOf(((sqInt)(long)(path) - 4)); sqFilenameFromStringOpen(storage, path, sz); mpeg3Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), 4); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3Oop))); *index = mpeg3_open(storage,0); makeFileEntry(*index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, mpeg3Oop); return null; } EXPORT(sqInt) primitiveMPEG3OpenABuffer(void) { mpeg3_t ** index; sqInt mpeg3Oop; char *path; sqInt size; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); size = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } mpeg3Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), 4); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3Oop))); *index = mpeg3_open(path,size); makeFileEntry(*index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, mpeg3Oop); return null; } /* int mpeg3_previous_frame(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3PreviousFrame(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (aNumber < 0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_previous_frame(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_read_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) */ EXPORT(sqInt) primitiveMPEG3ReadAudio(void) { sqInt aChannelNumber; sqInt aNumber; sqInt *anArray; short * arrayBase; sqInt aSampleNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(4); interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(3))); anArray = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); aChannelNumber = interpreterProxy->stackIntegerValue(2); aSampleNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } arrayBase = ((short *) anArray); if (interpreterProxy->failed()) { return null; } result = mpeg3_read_audio(file,(float *) NULL,arrayBase,aChannelNumber,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } /* int mpeg3_read_frame(mpeg3_t *file, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model, int stream) */ EXPORT(sqInt) primitiveMPEG3ReadFrame(void) { usqInt *aBuffer; sqInt aByteNumber; sqInt aNumber; unsigned char *bufferBaseAddr; mpeg3_t * file; sqInt fileHandle; sqInt height; sqInt i; sqInt model; sqInt outHeight; unsigned char ** outputRowsPtr; sqInt outWidth; sqInt result; sqInt width; sqInt xNumber; sqInt yNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(10); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(9))); aBuffer = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(9)))); xNumber = interpreterProxy->stackIntegerValue(8); yNumber = interpreterProxy->stackIntegerValue(7); width = interpreterProxy->stackIntegerValue(6); height = interpreterProxy->stackIntegerValue(5); outWidth = interpreterProxy->stackIntegerValue(4); outHeight = interpreterProxy->stackIntegerValue(3); model = interpreterProxy->stackIntegerValue(2); aNumber = interpreterProxy->stackIntegerValue(1); aByteNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, 0); return null; } bufferBaseAddr = ((unsigned char *) aBuffer); outputRowsPtr = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * outHeight); for (i = 0; i <= (outHeight - 1); i += 1) { outputRowsPtr[i] = (bufferBaseAddr + (aByteNumber * i)); } result = mpeg3_read_frame(file,outputRowsPtr,xNumber,yNumber,width,height,outWidth,outHeight,model,aNumber); memoryFree(outputRowsPtr); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, _return_value); return null; } /* int mpeg3_read_frame(mpeg3_t *file, unsigned char **output_rows, int in_x, int in_y, int in_w, int in_h, int out_w, int out_h, int color_model, int stream) */ EXPORT(sqInt) primitiveMPEG3ReadFrameBufferOffset(void) { usqInt *aBuffer; sqInt aBufferOffset; sqInt aByteNumber; sqInt aNumber; unsigned char *bufferBaseAddr; mpeg3_t * file; sqInt fileHandle; sqInt height; sqInt i; sqInt model; sqInt outHeight; unsigned char ** outputRowsPtr; sqInt outWidth; sqInt result; sqInt width; sqInt xNumber; sqInt yNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(11); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(10))); aBuffer = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(10)))); aBufferOffset = interpreterProxy->stackIntegerValue(9); xNumber = interpreterProxy->stackIntegerValue(8); yNumber = interpreterProxy->stackIntegerValue(7); width = interpreterProxy->stackIntegerValue(6); height = interpreterProxy->stackIntegerValue(5); outWidth = interpreterProxy->stackIntegerValue(4); outHeight = interpreterProxy->stackIntegerValue(3); model = interpreterProxy->stackIntegerValue(2); aNumber = interpreterProxy->stackIntegerValue(1); aByteNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, 0); return null; } bufferBaseAddr = ((unsigned char *) aBuffer); outputRowsPtr = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * outHeight); for (i = 0; i <= (outHeight - 1); i += 1) { outputRowsPtr[i] = ((bufferBaseAddr + aBufferOffset) + (aByteNumber * i)); } result = mpeg3_read_frame(file,outputRowsPtr,xNumber,yNumber,width,height,outWidth,outHeight,model,aNumber); memoryFree(outputRowsPtr); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, _return_value); return null; } /* int mpeg3_reread_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) */ EXPORT(sqInt) primitiveMPEG3ReReadAudio(void) { sqInt aChannelNumber; sqInt aNumber; sqInt *anArray; short * arrayBase; sqInt aSampleNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(4); interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(3))); anArray = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); aChannelNumber = interpreterProxy->stackIntegerValue(2); aSampleNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } arrayBase = ((short *) anArray); if (interpreterProxy->failed()) { return null; } result = mpeg3_reread_audio(file,(float *) NULL,arrayBase,aChannelNumber,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } /* int mpeg3_sample_rate(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3SampleRate(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_sample_rate(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_seek_percentage(mpeg3_t *file, double percentage) */ EXPORT(sqInt) primitiveMPEG3SeekPercentage(void) { double aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (aNumber < 0.0) { interpreterProxy->success(0); return null; } if (aNumber > 1.0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } result = mpeg3_seek_percentage(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_set_cpus(mpeg3_t *file, int cpus) */ EXPORT(sqInt) primitiveMPEG3SetCpus(void) { sqInt cpus; mpeg3_t * file; sqInt fileHandle; fileHandle = interpreterProxy->stackValue(1); cpus = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (cpus < 0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } mpeg3_set_cpus(file,cpus); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* int mpeg3_set_frame(mpeg3_t *file, long frame, int stream) */ EXPORT(sqInt) primitiveMPEG3SetFrame(void) { double aFrameNumber; sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aFrameNumber = interpreterProxy->stackFloatValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } result = mpeg3_set_frame(file,(long) aFrameNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* int mpeg3_set_mmx(mpeg3_t *file, int use_mmx) */ EXPORT(sqInt) primitiveMPEG3SetMmx(void) { mpeg3_t * file; sqInt fileHandle; sqInt mmx; fileHandle = interpreterProxy->stackValue(1); mmx = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } mpeg3_set_mmx(file,mmx); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* int mpeg3_set_sample(mpeg3_t *file, long sample, int stream) */ EXPORT(sqInt) primitiveMPEG3SetSample(void) { sqInt aNumber; double aSampleNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aSampleNumber = interpreterProxy->stackFloatValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aSampleNumber < 0) { interpreterProxy->success(0); return null; } result = mpeg3_set_sample(file,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* double mpeg3_tell_percentage(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TellPercentage(void) { mpeg3_t * file; sqInt fileHandle; double result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_tell_percentage(file); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_total_astreams(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TotalAStreams(void) { mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, 0); return null; } result = mpeg3_total_astreams(file); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_total_vstreams(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TotalVStreams(void) { mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_total_vstreams(file); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* long mpeg3_video_frames(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3VideoFrames(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_frames(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_height(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3VideoHeight(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_height(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_width(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3VideoWidth(void) { sqInt aNumber; mpeg3_t * file; sqInt fileHandle; sqInt result; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_width(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } static sqInt removeFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == aMpegFile) { mpegFiles[i] = 0; return 1; } } return 0; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) != 0) { mpeg3_close(mpegFiles[i]); mpegFiles[i] = 0; } } return true; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* Mpeg3Plugin_exports[][3] = { {"Mpeg3Plugin", "getModuleName", (void*)getModuleName}, {"Mpeg3Plugin", "initialiseModule", (void*)initialiseModule}, {"Mpeg3Plugin", "primitiveMPEG3AudioChannels", (void*)primitiveMPEG3AudioChannels}, {"Mpeg3Plugin", "primitiveMPEG3AudioSamples", (void*)primitiveMPEG3AudioSamples}, {"Mpeg3Plugin", "primitiveMPEG3CheckSig", (void*)primitiveMPEG3CheckSig}, {"Mpeg3Plugin", "primitiveMPEG3Close", (void*)primitiveMPEG3Close}, {"Mpeg3Plugin", "primitiveMPEG3DropFrames", (void*)primitiveMPEG3DropFrames}, {"Mpeg3Plugin", "primitiveMPEG3EndOfAudio", (void*)primitiveMPEG3EndOfAudio}, {"Mpeg3Plugin", "primitiveMPEG3EndOfVideo", (void*)primitiveMPEG3EndOfVideo}, {"Mpeg3Plugin", "primitiveMPEG3FrameRate", (void*)primitiveMPEG3FrameRate}, {"Mpeg3Plugin", "primitiveMPEG3GenerateToc", (void*)primitiveMPEG3GenerateToc}, {"Mpeg3Plugin", "primitiveMPEG3GetFrame", (void*)primitiveMPEG3GetFrame}, {"Mpeg3Plugin", "primitiveMPEG3GetSample", (void*)primitiveMPEG3GetSample}, {"Mpeg3Plugin", "primitiveMPEG3GetTime", (void*)primitiveMPEG3GetTime}, {"Mpeg3Plugin", "primitiveMPEG3HasAudio", (void*)primitiveMPEG3HasAudio}, {"Mpeg3Plugin", "primitiveMPEG3HasVideo", (void*)primitiveMPEG3HasVideo}, {"Mpeg3Plugin", "primitiveMPEG3Open", (void*)primitiveMPEG3Open}, {"Mpeg3Plugin", "primitiveMPEG3OpenABuffer", (void*)primitiveMPEG3OpenABuffer}, {"Mpeg3Plugin", "primitiveMPEG3PreviousFrame", (void*)primitiveMPEG3PreviousFrame}, {"Mpeg3Plugin", "primitiveMPEG3ReadAudio", (void*)primitiveMPEG3ReadAudio}, {"Mpeg3Plugin", "primitiveMPEG3ReadFrame", (void*)primitiveMPEG3ReadFrame}, {"Mpeg3Plugin", "primitiveMPEG3ReadFrameBufferOffset", (void*)primitiveMPEG3ReadFrameBufferOffset}, {"Mpeg3Plugin", "primitiveMPEG3ReReadAudio", (void*)primitiveMPEG3ReReadAudio}, {"Mpeg3Plugin", "primitiveMPEG3SampleRate", (void*)primitiveMPEG3SampleRate}, {"Mpeg3Plugin", "primitiveMPEG3SeekPercentage", (void*)primitiveMPEG3SeekPercentage}, {"Mpeg3Plugin", "primitiveMPEG3SetCpus", (void*)primitiveMPEG3SetCpus}, {"Mpeg3Plugin", "primitiveMPEG3SetFrame", (void*)primitiveMPEG3SetFrame}, {"Mpeg3Plugin", "primitiveMPEG3SetMmx", (void*)primitiveMPEG3SetMmx}, {"Mpeg3Plugin", "primitiveMPEG3SetSample", (void*)primitiveMPEG3SetSample}, {"Mpeg3Plugin", "primitiveMPEG3TellPercentage", (void*)primitiveMPEG3TellPercentage}, {"Mpeg3Plugin", "primitiveMPEG3TotalAStreams", (void*)primitiveMPEG3TotalAStreams}, {"Mpeg3Plugin", "primitiveMPEG3TotalVStreams", (void*)primitiveMPEG3TotalVStreams}, {"Mpeg3Plugin", "primitiveMPEG3VideoFrames", (void*)primitiveMPEG3VideoFrames}, {"Mpeg3Plugin", "primitiveMPEG3VideoHeight", (void*)primitiveMPEG3VideoHeight}, {"Mpeg3Plugin", "primitiveMPEG3VideoWidth", (void*)primitiveMPEG3VideoWidth}, {"Mpeg3Plugin", "setInterpreter", (void*)setInterpreter}, {"Mpeg3Plugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/ObjectiveCPlugin/ObjectiveCPlugin.c ================================================ /* Automatically generated from Squeak on 8 July 2010 5:52:05 pm by VMMaker 4.2.6 */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <Foundation/Foundation.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType # include "squeak_adapters.h" /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt initialiseModule(void); static sqInt msg(char * s); #pragma export on EXPORT(sqInt) primitiveCallbackLeave(void); EXPORT(sqInt) primitiveGetAddressFromEntryPointString(void); EXPORT(sqInt) primitiveGetAutoReleasePool(void); EXPORT(sqInt) primitiveGetClass(void); EXPORT(sqInt) primitiveGetDescription(void); EXPORT(sqInt) primitiveGetMethodSignatureForSelector(void); EXPORT(sqInt) primitiveGetNSStringForString(void); EXPORT(sqInt) primitiveGetObjCClassForString(void); EXPORT(sqInt) primitiveGetSelectorForString(void); EXPORT(sqInt) primitiveGetSuperClass(void); EXPORT(sqInt) primitiveIsEqual(void); EXPORT(sqInt) primitiveMethodSignatureGetArgumentType(void); EXPORT(sqInt) primitiveMethodSignatureGetMethodReturnLength(void); EXPORT(sqInt) primitiveMethodSignatureGetNumberOfArguments(void); EXPORT(sqInt) primitiveMethodSignatureGetReturnType(void); EXPORT(sqInt) primitiveNSInvocationCalloc(void); EXPORT(sqInt) primitiveNSInvocationFree(void); EXPORT(sqInt) primitiveNSInvocationGetArgument(void); EXPORT(sqInt) primitiveNSInvocationGetCType(void); EXPORT(sqInt) primitiveNSInvocationGetCharPointerType(void); EXPORT(sqInt) primitiveNSInvocationGetClassType(void); EXPORT(sqInt) primitiveNSInvocationGetDoubleType(void); EXPORT(sqInt) primitiveNSInvocationGetFloatType(void); EXPORT(sqInt) primitiveNSInvocationGetIntType(void); EXPORT(sqInt) primitiveNSInvocationGetLongLongType(void); EXPORT(sqInt) primitiveNSInvocationGetLongType(void); EXPORT(sqInt) primitiveNSInvocationGetObjectType(void); EXPORT(sqInt) primitiveNSInvocationGetReturnValue(void); EXPORT(sqInt) primitiveNSInvocationGetSelectorType(void); EXPORT(sqInt) primitiveNSInvocationGetShortType(void); EXPORT(sqInt) primitiveNSInvocationGetStructureType(void); EXPORT(sqInt) primitiveNSInvocationMalloc(void); EXPORT(sqInt) primitiveNSInvocationSetCType(void); EXPORT(sqInt) primitiveNSInvocationSetDoubleType(void); EXPORT(sqInt) primitiveNSInvocationSetFloatType(void); EXPORT(sqInt) primitiveNSInvocationSetIntType(void); EXPORT(sqInt) primitiveNSInvocationSetLongLongType(void); EXPORT(sqInt) primitiveNSInvocationSetLongType(void); EXPORT(sqInt) primitiveNSInvocationSetPointerType(void); EXPORT(sqInt) primitiveNSInvocationSetRetained(void); EXPORT(sqInt) primitiveNSInvocationSetSelector(void); EXPORT(sqInt) primitiveNSInvocationSetShortType(void); EXPORT(sqInt) primitiveNSInvocationSetStringType(void); EXPORT(sqInt) primitiveNSInvocationSetStructureType(void); EXPORT(sqInt) primitiveNSInvocationSetVoidPointerType(void); EXPORT(sqInt) primitiveNSInvocationWithMethodSignature(void); EXPORT(sqInt) primitiveNSLog(void); EXPORT(sqInt) primitiveNSStringToUTF8(void); EXPORT(sqInt) primitivePerformSelector(void); EXPORT(sqInt) primitivePerformSelectorOnMainThreadWithWaitTilDone(void); EXPORT(sqInt) primitivePerformSelectorWith(void); EXPORT(sqInt) primitivePerformSelectorWithWith(void); EXPORT(sqInt) primitiveSELGetName(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static sqInt shutdownModule(void); static sqInt sqAssert(sqInt aBool); static sqInt stringFromCString(const char * aCString); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "ObjectiveCPlugin 8 July 2010 (i)" #else "ObjectiveCPlugin 8 July 2010 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } /* Initialise the module */ static sqInt initialiseModule(void) { return 1; } static sqInt msg(char * s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primitiveCallbackLeave(void) { sqInt aNumber; aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (aNumber == 0) { if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } //interpreterProxy->callbackLeave(aNumber); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveGetAddressFromEntryPointString(void) { sqInt entryPointNameLength; void * fn; char entryPointName[256]; char *aEntryPointName; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aEntryPointName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } entryPointNameLength = interpreterProxy->slotSizeOf((oopForPointer( aEntryPointName ) - BASE_HEADER_SIZE)); if (entryPointNameLength > 255) { _return_value = interpreterProxy->positive64BitIntegerFor(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } strlcpy(entryPointName, aEntryPointName, entryPointNameLength + 1); fn = dlsym(-2, entryPointName); _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) fn)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveGetAutoReleasePool(void) { NSAutoreleasePool * pool; sqInt _return_value; pool = null; NS_DURING; pool = [NSAutoreleasePool new]; NS_HANDLER pool = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) pool)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveGetClass(void) { id classOrInstanceObject; Class classObject; sqInt aClassOrInstanceOop; sqInt _return_value; aClassOrInstanceOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); classObject = null; if (interpreterProxy->failed()) { return null; } ; ; NS_DURING; classObject = [classOrInstanceObject class]; NS_HANDLER classObject = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) classObject)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveGetDescription(void) { sqInt utf8StringOop; id classOrInstanceObject; const char * utf8String; NSString* nsStringObject; sqInt aClassOrInstanceOop; aClassOrInstanceOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); utf8String = null; if (interpreterProxy->failed()) { return null; } ; NS_DURING; nsStringObject = [classOrInstanceObject description]; utf8String = [nsStringObject UTF8String]; NS_HANDLER utf8String = nil;; NS_ENDHANDLER; if (!(utf8String)) { interpreterProxy->success(0); return null; } utf8StringOop = stringFromCString(utf8String); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, utf8StringOop); return null; } EXPORT(sqInt) primitiveGetMethodSignatureForSelector(void) { SEL selectorObject; NSMethodSignature * messageSignatureObject; id classOrInstanceObject; sqInt aSelectorOop; sqInt aClassOrInstanceOop; sqInt _return_value; aSelectorOop = interpreterProxy->stackValue(1); aClassOrInstanceOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); messageSignatureObject = null; if (interpreterProxy->failed()) { return null; } ; ; NS_DURING; messageSignatureObject = [classOrInstanceObject methodSignatureForSelector: selectorObject]; NS_HANDLER messageSignatureObject = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) messageSignatureObject)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveGetNSStringForString(void) { NSString* aStringAsNSString; sqInt stringLength; NSUInteger encoding; char* aString; sqInt aStringOop; sqInt anEncoding; sqInt _return_value; aStringOop = interpreterProxy->stackValue(1); anEncoding = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } encoding = ((NSUInteger) (interpreterProxy->positive64BitValueOf(anEncoding))); aString = interpreterProxy->firstIndexableField(aStringOop); stringLength = interpreterProxy->byteSizeOf(aStringOop); ; aStringAsNSString = 0; NS_DURING; aStringAsNSString = [[NSString alloc] initWithBytes: aString length: stringLength encoding: encoding]; NS_HANDLER aStringAsNSString = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) aStringAsNSString)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveGetObjCClassForString(void) { NSString* classNameNSString; sqInt classNameLength; Class classObject; char *aClassName; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aClassName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } classNameLength = interpreterProxy->slotSizeOf((oopForPointer( aClassName ) - BASE_HEADER_SIZE)); ; classNameNSString = [[NSString alloc] initWithBytes: aClassName length: classNameLength encoding: NSUTF8StringEncoding]; NS_DURING; classObject = NSClassFromString(classNameNSString); NS_HANDLER classObject = nil;; NS_ENDHANDLER; [classNameNSString release]; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) classObject)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveGetSelectorForString(void) { SEL selectorObject; NSString * selectorNSString; sqInt selectorLength; char *aSelectorName; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aSelectorName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } selectorLength = interpreterProxy->slotSizeOf((oopForPointer( aSelectorName ) - BASE_HEADER_SIZE)); ; selectorNSString = [[NSString alloc] initWithBytes: aSelectorName length: selectorLength encoding: NSUTF8StringEncoding]; NS_DURING; selectorObject = NSSelectorFromString(selectorNSString); NS_HANDLER selectorObject = nil;; NS_ENDHANDLER; [selectorNSString release]; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) selectorObject)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveGetSuperClass(void) { id classOrInstanceObject; Class classObject; sqInt aClassOrInstanceOop; sqInt _return_value; aClassOrInstanceOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); classObject = null; if (interpreterProxy->failed()) { return null; } ; ; NS_DURING; classObject = [classOrInstanceObject superclass]; NS_HANDLER classObject = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) classObject)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveIsEqual(void) { BOOL result; id oop2; id oop1; sqInt anOop1; sqInt anOop2; sqInt _return_value; anOop1 = interpreterProxy->stackValue(1); anOop2 = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } oop1 = ((id) (interpreterProxy->positive64BitValueOf(anOop1))); oop2 = ((id) (interpreterProxy->positive64BitValueOf(anOop2))); if (interpreterProxy->failed()) { return null; } ; ; result = 0; NS_DURING; result = [oop1 isEqual: oop2]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = ((result == 1)) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveMethodSignatureGetArgumentType(void) { NSMethodSignature* nsMethodSignatureObject; const char * string; sqInt stringOop; sqInt aMethodSignatureOop; sqInt aIndexNumber; aMethodSignatureOop = interpreterProxy->stackValue(1); aIndexNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } nsMethodSignatureObject = ((NSMethodSignature *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); string = null; if (interpreterProxy->failed()) { return null; } ; NS_DURING; string = [nsMethodSignatureObject getArgumentTypeAtIndex: aIndexNumber]; NS_HANDLER string = nil;; NS_ENDHANDLER; if (!(string)) { interpreterProxy->success(0); return null; } stringOop = stringFromCString(string); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, stringOop); return null; } EXPORT(sqInt) primitiveMethodSignatureGetMethodReturnLength(void) { NSUInteger methodReturnLength; NSMethodSignature* nsMethodSignatureObject; sqInt aMethodSignatureOop; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsMethodSignatureObject = ((NSMethodSignature *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); methodReturnLength = 0; if (interpreterProxy->failed()) { return null; } ; NS_DURING; methodReturnLength = [nsMethodSignatureObject methodReturnLength]; NS_HANDLER methodReturnLength = 0xFFFFFFFF; NS_ENDHANDLER; if (methodReturnLength == 4294967295U) { interpreterProxy->success(0); return null; } _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) methodReturnLength)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveMethodSignatureGetNumberOfArguments(void) { NSMethodSignature* nsMethodSignatureObject; NSUInteger numberOfArguments; sqInt aMethodSignatureOop; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsMethodSignatureObject = ((NSMethodSignature *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); numberOfArguments = 9999999; if (interpreterProxy->failed()) { return null; } ; NS_DURING; numberOfArguments = [nsMethodSignatureObject numberOfArguments]; NS_HANDLER numberOfArguments = 9999999; NS_ENDHANDLER; if (numberOfArguments == 9999999) { interpreterProxy->success(0); return null; } _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) numberOfArguments)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveMethodSignatureGetReturnType(void) { NSMethodSignature* nsMethodSignatureObject; const char * string; sqInt stringOop; sqInt aMethodSignatureOop; aMethodSignatureOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsMethodSignatureObject = ((NSMethodSignature *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); string = null; if (interpreterProxy->failed()) { return null; } ; NS_DURING; string = [nsMethodSignatureObject methodReturnType]; NS_HANDLER string = nil;; NS_ENDHANDLER; if (!(string)) { interpreterProxy->success(0); return null; } stringOop = stringFromCString(string); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, stringOop); return null; } EXPORT(sqInt) primitiveNSInvocationCalloc(void) { void* pointer; sqInt size; sqInt _return_value; size = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pointer = calloc(size,1); _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) pointer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationFree(void) { void* pointerToFree; sqInt pointer; pointer = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } pointerToFree = ((void *) (interpreterProxy->positive64BitValueOf(pointer))); if (interpreterProxy->failed()) { return null; } free((void*)pointerToFree); ; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveNSInvocationGetArgument(void) { void * buffer; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt bufferOop; sqInt index; aMethodSignatureOop = interpreterProxy->stackValue(2); bufferOop = interpreterProxy->stackValue(1); index = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); buffer = ((void *) (interpreterProxy->positive64BitValueOf(bufferOop))); if (interpreterProxy->failed()) { return null; } ; ; NS_DURING; [nsInvocationInstance getArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveNSInvocationGetCType(void) { char * buffer; sqInt newCharacterOop; char targetOopData; sqInt bufferAddressOop; sqInt signedBoolean; bufferAddressOop = interpreterProxy->stackValue(1); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } buffer = ((char *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; newCharacterOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classCharacter(), 1); targetOopData = 0; ; if (signedBoolean) { targetOopData = *(char*) buffer; interpreterProxy->storeIntegerofObjectwithValue(0, newCharacterOop, ((sqInt) targetOopData)); } else { targetOopData = *(char*) buffer; interpreterProxy->storeIntegerofObjectwithValue(0, newCharacterOop, ((usqInt) targetOopData)); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, newCharacterOop); return null; } EXPORT(sqInt) primitiveNSInvocationGetCharPointerType(void) { char * buffer; char ** bufferPointer; sqInt stringOop; sqInt bufferAddressOop; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } bufferPointer = ((char **) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } buffer = *bufferPointer; stringOop = stringFromCString(buffer); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, stringOop); return null; } EXPORT(sqInt) primitiveNSInvocationGetClassType(void) { Class * buffer; Class data; sqInt bufferAddressOop; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((Class *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; data = *buffer; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationGetDoubleType(void) { double * buffer; double data; sqInt bufferAddressOop; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((double *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; data = *buffer; _return_value = interpreterProxy->floatObjectOf(data); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationGetFloatType(void) { float * buffer; float data; sqInt bufferAddressOop; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((float *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; data = *buffer; _return_value = interpreterProxy->floatObjectOf(data); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationGetIntType(void) { int * buffer; int data; unsigned int unsignedData; sqInt bufferAddressOop; sqInt signedBoolean; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(1); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } buffer = ((int *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; unsignedData = data = 0; if (signedBoolean) { data = *buffer; _return_value = interpreterProxy->signed32BitIntegerFor(((sqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { unsignedData = *(unsigned int *)buffer; _return_value = interpreterProxy->positive32BitIntegerFor(((usqInt) unsignedData)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } EXPORT(sqInt) primitiveNSInvocationGetLongLongType(void) { long long * buffer; long long data; unsigned long long unsignedData; sqInt bufferAddressOop; sqInt signedBoolean; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(1); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } buffer = ((long long *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; unsignedData = data = 0; if (signedBoolean) { data = *buffer; _return_value = interpreterProxy->signed64BitIntegerFor(((long long) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { unsignedData = * (unsigned long long*) buffer; _return_value = interpreterProxy->positive64BitIntegerFor(((unsigned long long) unsignedData)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } EXPORT(sqInt) primitiveNSInvocationGetLongType(void) { long * buffer; long data; unsigned long unsignedData; sqInt bufferAddressOop; sqInt signedBoolean; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(1); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } buffer = ((long *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; unsignedData = data = 0; if (signedBoolean) { data = *buffer; _return_value = interpreterProxy->signed64BitIntegerFor(((sqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { unsignedData = *(unsigned long *) buffer; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) unsignedData)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } EXPORT(sqInt) primitiveNSInvocationGetObjectType(void) { id * buffer; id data; sqInt bufferAddressOop; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((id *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; data = *buffer; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationGetReturnValue(void) { void * buffer; NSInvocation *nsInvoke; sqInt bufferAddressOop; sqInt aNSinvokeOops; bufferAddressOop = interpreterProxy->stackValue(1); aNSinvokeOops = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((void *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); nsInvoke = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aNSinvokeOops))); if (interpreterProxy->failed()) { return null; } ; NS_DURING; [nsInvoke getReturnValue: buffer]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveNSInvocationGetSelectorType(void) { SEL * buffer; SEL data; sqInt bufferAddressOop; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } buffer = ((SEL *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } ; data = *buffer; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationGetShortType(void) { short * buffer; short data; unsigned short unsignedData; sqInt bufferAddressOop; sqInt signedBoolean; sqInt _return_value; bufferAddressOop = interpreterProxy->stackValue(1); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } buffer = ((short *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); unsignedData = data = 0; if (interpreterProxy->failed()) { return null; } ; if (signedBoolean) { data = *buffer; _return_value = interpreterProxy->signed32BitIntegerFor(((sqInt) data)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } else { unsignedData = *(unsigned short *)buffer; _return_value = interpreterProxy->positive32BitIntegerFor(((usqInt) unsignedData)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } } EXPORT(sqInt) primitiveNSInvocationGetStructureType(void) { sqInt newByteArray; char ** bufferPointer; sqInt bufferAddressOop; sqInt length; bufferAddressOop = interpreterProxy->stackValue(1); length = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } bufferPointer = ((void *) (interpreterProxy->positive64BitValueOf(bufferAddressOop))); if (interpreterProxy->failed()) { return null; } newByteArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), length); memcpy(interpreterProxy->arrayValueOf(newByteArray), bufferPointer, length); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, newByteArray); return null; } EXPORT(sqInt) primitiveNSInvocationMalloc(void) { void* pointer; sqInt size; sqInt _return_value; size = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pointer = malloc(size); _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) pointer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetCType(void) { void * buffer; unsigned char aUnsignedValue; char aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt signedBoolean; sqInt index; sqInt newCharacterOop; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(3); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(2)); index = interpreterProxy->stackIntegerValue(1); newCharacterOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } aValue = interpreterProxy->fetchIntegerofObject(0, newCharacterOop); aUnsignedValue = interpreterProxy->fetchIntegerofObject(0, newCharacterOop); if (signedBoolean) { buffer = malloc(sizeof(char)); *(char*) buffer = (char) aValue; } else { buffer = malloc(sizeof(unsigned char)); *(unsigned char*)buffer = (unsigned char) aUnsignedValue; } ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetDoubleType(void) { void * buffer; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; double aValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); aValue = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(double)); *(double*) buffer = (double) aValue; ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetFloatType(void) { void * buffer; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; double aValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); aValue = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(float)); *(float*) buffer = (float) aValue; ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetIntType(void) { void * buffer; int aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt signedBoolean; sqInt index; sqInt intValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(3); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(2)); index = interpreterProxy->stackIntegerValue(1); intValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } if (signedBoolean) { aValue = ((int) (interpreterProxy->signed64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(int)); *(int*) buffer = (int) aValue; } else { aValue = ((unsigned int) (interpreterProxy->positive64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(unsigned int)); *(unsigned int*)buffer = (unsigned int) aValue; } ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetLongLongType(void) { void * buffer; long long aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt signedBoolean; sqInt index; sqInt intValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(3); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(2)); index = interpreterProxy->stackIntegerValue(1); intValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } if (signedBoolean) { aValue = ((long long) (interpreterProxy->signed64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(long long)); *(long long*) buffer = (long long) aValue; } else { aValue = ((unsigned long long) (interpreterProxy->positive64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(unsigned long long)); *(unsigned long long*)buffer = (unsigned long long) aValue; } ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetLongType(void) { void * buffer; long aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt signedBoolean; sqInt index; sqInt intValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(3); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(2)); index = interpreterProxy->stackIntegerValue(1); intValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } if (signedBoolean) { aValue = ((long) (interpreterProxy->signed64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(long)); *(long*) buffer = (long) aValue; } else { aValue = ((unsigned long) (interpreterProxy->positive64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(unsigned long)); *(unsigned long*)buffer = (unsigned long) aValue; } ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetPointerType(void) { void ** buffer; void * aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; sqInt pointerValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); pointerValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); aValue = ((char *) (interpreterProxy->positive64BitValueOf(pointerValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(void*)); *buffer = aValue; ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetRetained(void) { NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; aMethodSignatureOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } NS_DURING; [nsInvocationInstance retainArguments]; NS_HANDLER; interpreterProxy->success(0); NS_ENDHANDLER; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveNSInvocationSetSelector(void) { SEL selectorObject; id object1; NSInvocation *nsInvoke; sqInt aSelectorOop; sqInt object1Oops; sqInt aNSinvokeOops; aSelectorOop = interpreterProxy->stackValue(2); object1Oops = interpreterProxy->stackValue(1); aNSinvokeOops = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); object1 = ((id) (interpreterProxy->positive64BitValueOf(object1Oops))); nsInvoke = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aNSinvokeOops))); if (interpreterProxy->failed()) { return null; } NS_DURING; [nsInvoke setSelector: selectorObject]; [nsInvoke setTarget: object1]; NS_HANDLER; interpreterProxy->success(0); if (1) { if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } NS_ENDHANDLER; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveNSInvocationSetShortType(void) { void * buffer; short aValue; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt signedBoolean; sqInt index; sqInt intValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(3); signedBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(2)); index = interpreterProxy->stackIntegerValue(1); intValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } if (signedBoolean) { aValue = ((short) (interpreterProxy->signed64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(short)); *(short*) buffer = (short) aValue; } else { aValue = ((unsigned short) (interpreterProxy->positive64BitValueOf(intValue))); if (interpreterProxy->failed()) { return null; } buffer = malloc(sizeof(unsigned short)); *(unsigned short*)buffer = (unsigned short) aValue; } ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetStringType(void) { char * buffer; sqInt stringSize; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; char *aValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aValue = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } stringSize = interpreterProxy->slotSizeOf((oopForPointer( aValue ) - BASE_HEADER_SIZE)); buffer = malloc(stringSize + 1); memcpy(buffer,aValue,stringSize); buffer[stringSize] = 0x00; ; ; NS_DURING; [nsInvocationInstance setArgument: &buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetStructureType(void) { void * buffer; sqInt byteArraySize; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; char *aValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aValue = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } byteArraySize = interpreterProxy->slotSizeOf((oopForPointer( aValue ) - BASE_HEADER_SIZE)); buffer = malloc(byteArraySize); memcpy(buffer,aValue,byteArraySize); ; ; ; NS_DURING; [nsInvocationInstance setArgument: buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationSetVoidPointerType(void) { void * buffer; sqInt byteArraySize; NSInvocation* nsInvocationInstance; sqInt aMethodSignatureOop; sqInt index; char *aValue; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(2); index = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aValue = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } nsInvocationInstance = ((NSInvocation *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } byteArraySize = interpreterProxy->slotSizeOf((oopForPointer( aValue ) - BASE_HEADER_SIZE)); buffer = malloc(byteArraySize); memcpy(buffer,aValue,byteArraySize); ; ; ; NS_DURING; [nsInvocationInstance setArgument: &buffer atIndex: index]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) buffer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveNSInvocationWithMethodSignature(void) { NSInvocation* nsInvocationOops; NSMethodSignature * methodSignatureOop; sqInt aMethodSignatureOop; sqInt _return_value; aMethodSignatureOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } methodSignatureOop = ((NSMethodSignature *) (interpreterProxy->positive64BitValueOf(aMethodSignatureOop))); if (interpreterProxy->failed()) { return null; } nsInvocationOops = 0; NS_DURING; nsInvocationOops = [NSInvocation invocationWithMethodSignature: methodSignatureOop]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) nsInvocationOops)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveNSLog(void) { id oop1; sqInt aNSStringOOP; aNSStringOOP = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } oop1 = ((id) (interpreterProxy->positive64BitValueOf(aNSStringOOP))); if (interpreterProxy->failed()) { return null; } ; NSLog(oop1); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveNSStringToUTF8(void) { sqInt utf8StringOop; NSString* nsStringObject; const char * utf8String; sqInt aNSStringOop; aNSStringOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } nsStringObject = ((NSString *) (interpreterProxy->positive64BitValueOf(aNSStringOop))); if (interpreterProxy->failed()) { return null; } utf8String = null; ; NS_DURING; utf8String = [nsStringObject UTF8String]; NS_HANDLER utf8String = nil;; NS_ENDHANDLER; if (!(utf8String)) { interpreterProxy->success(0); return null; } utf8StringOop = stringFromCString(utf8String); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, utf8StringOop); return null; } /* - (id)performSelector:(SEL)aSelector */ EXPORT(sqInt) primitivePerformSelector(void) { SEL selectorObject; id classOrInstanceObject; id returnValue; sqInt aSelectorOop; sqInt aClassOrInstanceOop; sqInt _return_value; aSelectorOop = interpreterProxy->stackValue(1); aClassOrInstanceOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); if (interpreterProxy->failed()) { return null; } returnValue = null; ; ; NS_DURING; returnValue = [classOrInstanceObject performSelector: selectorObject]; NS_HANDLER returnValue = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) returnValue)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* - (id)performSelector:(SEL)aSelector */ EXPORT(sqInt) primitivePerformSelectorOnMainThreadWithWaitTilDone(void) { SEL selectorObject; id classOrInstanceObject; id object1; void *returnAddress; sqInt aSelectorOop; sqInt aClassOrInstanceOop; sqInt anObject1; sqInt aReturnValueAddress; sqInt doneFlag; aSelectorOop = interpreterProxy->stackValue(4); aClassOrInstanceOop = interpreterProxy->stackValue(3); anObject1 = interpreterProxy->stackValue(2); aReturnValueAddress = interpreterProxy->stackValue(1); doneFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); object1 = ((id) (interpreterProxy->positive64BitValueOf(anObject1))); returnAddress = ((void *) (interpreterProxy->positive64BitValueOf(aReturnValueAddress))); if (interpreterProxy->failed()) { return null; } ; ; ; ; NS_DURING; [classOrInstanceObject performSelectorOnMainThread: selectorObject withObject: object1 waitUntilDone: doneFlag ]; NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; NS_DURING; if (returnAddress != 0) { [classOrInstanceObject getReturnValue: returnAddress]; } NS_HANDLER; interpreterProxy->success(0); if (1) { return null; } NS_ENDHANDLER; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); return null; } /* - (id)performSelector:(SEL)aSelector */ EXPORT(sqInt) primitivePerformSelectorWith(void) { SEL selectorObject; id object1; id classOrInstanceObject; id returnValue; sqInt aSelectorOop; sqInt aClassOrInstanceOop; sqInt anObject1; sqInt _return_value; aSelectorOop = interpreterProxy->stackValue(2); aClassOrInstanceOop = interpreterProxy->stackValue(1); anObject1 = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); object1 = ((id) (interpreterProxy->positive64BitValueOf(anObject1))); if (interpreterProxy->failed()) { return null; } returnValue = null; ; ; ; NS_DURING; returnValue = [classOrInstanceObject performSelector: selectorObject withObject: object1]; NS_HANDLER returnValue = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) returnValue)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* - (id)performSelector:(SEL)aSelector */ EXPORT(sqInt) primitivePerformSelectorWithWith(void) { SEL selectorObject; id object1; id classOrInstanceObject; id returnValue; id object2; sqInt aSelectorOop; sqInt aClassOrInstanceOop; sqInt anObject1; sqInt anObject2; sqInt _return_value; aSelectorOop = interpreterProxy->stackValue(3); aClassOrInstanceOop = interpreterProxy->stackValue(2); anObject1 = interpreterProxy->stackValue(1); anObject2 = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } classOrInstanceObject = ((id) (interpreterProxy->positive64BitValueOf(aClassOrInstanceOop))); selectorObject = ((SEL) (interpreterProxy->positive64BitValueOf(aSelectorOop))); object1 = ((id) (interpreterProxy->positive64BitValueOf(anObject1))); object2 = ((id) (interpreterProxy->positive64BitValueOf(anObject2))); if (interpreterProxy->failed()) { return null; } returnValue = null; ; ; ; ; NS_DURING; returnValue = [classOrInstanceObject performSelector: selectorObject withObject: object1 withObject: object2 ]; NS_HANDLER returnValue = nil;; NS_ENDHANDLER; _return_value = interpreterProxy->positive64BitIntegerFor(((usqInt) returnValue)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveSELGetName(void) { SEL bufferPointer; sqInt stringOop; sqInt aSEL; aSEL = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } #define selgetName sel_getName ; bufferPointer = ((SEL) (interpreterProxy->positive64BitValueOf(aSEL))); if (interpreterProxy->failed()) { return null; } stringOop = stringFromCString(selgetName(bufferPointer)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, stringOop); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt shutdownModule(void) { return 1; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char * aCString) { sqInt len; sqInt newString; len = ((sqInt) (strlen(aCString))); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } #ifdef SQUEAK_BUILTIN_PLUGIN void* ObjectiveCPlugin_exports[][3] = { {"ObjectiveCPlugin", "primitiveNSInvocationSetSelector", (void*)primitiveNSInvocationSetSelector}, {"ObjectiveCPlugin", "primitiveNSInvocationGetDoubleType", (void*)primitiveNSInvocationGetDoubleType}, {"ObjectiveCPlugin", "primitiveGetAddressFromEntryPointString", (void*)primitiveGetAddressFromEntryPointString}, {"ObjectiveCPlugin", "primitiveGetObjCClassForString", (void*)primitiveGetObjCClassForString}, {"ObjectiveCPlugin", "primitiveNSInvocationSetRetained", (void*)primitiveNSInvocationSetRetained}, {"ObjectiveCPlugin", "primitiveNSInvocationGetLongType", (void*)primitiveNSInvocationGetLongType}, {"ObjectiveCPlugin", "primitiveNSInvocationGetCType", (void*)primitiveNSInvocationGetCType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetShortType", (void*)primitiveNSInvocationSetShortType}, {"ObjectiveCPlugin", "primitiveNSInvocationGetFloatType", (void*)primitiveNSInvocationGetFloatType}, {"ObjectiveCPlugin", "primitivePerformSelectorWithWith", (void*)primitivePerformSelectorWithWith}, {"ObjectiveCPlugin", "primitiveNSInvocationMalloc", (void*)primitiveNSInvocationMalloc}, {"ObjectiveCPlugin", "primitiveNSInvocationSetLongLongType", (void*)primitiveNSInvocationSetLongLongType}, {"ObjectiveCPlugin", "primitiveMethodSignatureGetMethodReturnLength", (void*)primitiveMethodSignatureGetMethodReturnLength}, {"ObjectiveCPlugin", "primitiveNSStringToUTF8", (void*)primitiveNSStringToUTF8}, {"ObjectiveCPlugin", "getModuleName", (void*)getModuleName}, {"ObjectiveCPlugin", "primitiveNSInvocationGetLongLongType", (void*)primitiveNSInvocationGetLongLongType}, {"ObjectiveCPlugin", "primitiveMethodSignatureGetReturnType", (void*)primitiveMethodSignatureGetReturnType}, {"ObjectiveCPlugin", "primitiveSELGetName", (void*)primitiveSELGetName}, {"ObjectiveCPlugin", "primitivePerformSelectorOnMainThreadWithWaitTilDone", (void*)primitivePerformSelectorOnMainThreadWithWaitTilDone}, {"ObjectiveCPlugin", "primitiveNSInvocationSetDoubleType", (void*)primitiveNSInvocationSetDoubleType}, {"ObjectiveCPlugin", "primitiveCallbackLeave", (void*)primitiveCallbackLeave}, {"ObjectiveCPlugin", "primitiveNSInvocationGetReturnValue", (void*)primitiveNSInvocationGetReturnValue}, {"ObjectiveCPlugin", "primitiveNSInvocationGetShortType", (void*)primitiveNSInvocationGetShortType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetStringType", (void*)primitiveNSInvocationSetStringType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetPointerType", (void*)primitiveNSInvocationSetPointerType}, {"ObjectiveCPlugin", "primitiveNSInvocationGetObjectType", (void*)primitiveNSInvocationGetObjectType}, {"ObjectiveCPlugin", "primitiveMethodSignatureGetArgumentType", (void*)primitiveMethodSignatureGetArgumentType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetStructureType", (void*)primitiveNSInvocationSetStructureType}, {"ObjectiveCPlugin", "primitiveNSInvocationGetArgument", (void*)primitiveNSInvocationGetArgument}, {"ObjectiveCPlugin", "primitiveGetSelectorForString", (void*)primitiveGetSelectorForString}, {"ObjectiveCPlugin", "primitiveNSInvocationSetIntType", (void*)primitiveNSInvocationSetIntType}, {"ObjectiveCPlugin", "primitiveGetNSStringForString", (void*)primitiveGetNSStringForString}, {"ObjectiveCPlugin", "primitiveNSInvocationGetClassType", (void*)primitiveNSInvocationGetClassType}, {"ObjectiveCPlugin", "primitiveNSInvocationCalloc", (void*)primitiveNSInvocationCalloc}, {"ObjectiveCPlugin", "primitivePerformSelectorWith", (void*)primitivePerformSelectorWith}, {"ObjectiveCPlugin", "primitiveIsEqual", (void*)primitiveIsEqual}, {"ObjectiveCPlugin", "primitiveNSInvocationGetIntType", (void*)primitiveNSInvocationGetIntType}, {"ObjectiveCPlugin", "primitiveGetMethodSignatureForSelector", (void*)primitiveGetMethodSignatureForSelector}, {"ObjectiveCPlugin", "primitiveGetClass", (void*)primitiveGetClass}, {"ObjectiveCPlugin", "primitiveNSInvocationSetLongType", (void*)primitiveNSInvocationSetLongType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetVoidPointerType", (void*)primitiveNSInvocationSetVoidPointerType}, {"ObjectiveCPlugin", "primitiveNSInvocationFree", (void*)primitiveNSInvocationFree}, {"ObjectiveCPlugin", "setInterpreter", (void*)setInterpreter}, {"ObjectiveCPlugin", "primitiveMethodSignatureGetNumberOfArguments", (void*)primitiveMethodSignatureGetNumberOfArguments}, {"ObjectiveCPlugin", "primitiveNSInvocationGetSelectorType", (void*)primitiveNSInvocationGetSelectorType}, {"ObjectiveCPlugin", "primitiveNSInvocationSetCType", (void*)primitiveNSInvocationSetCType}, {"ObjectiveCPlugin", "primitivePerformSelector", (void*)primitivePerformSelector}, {"ObjectiveCPlugin", "primitiveNSLog", (void*)primitiveNSLog}, {"ObjectiveCPlugin", "primitiveNSInvocationWithMethodSignature", (void*)primitiveNSInvocationWithMethodSignature}, {"ObjectiveCPlugin", "primitiveGetAutoReleasePool", (void*)primitiveGetAutoReleasePool}, {"ObjectiveCPlugin", "primitiveGetDescription", (void*)primitiveGetDescription}, {"ObjectiveCPlugin", "primitiveNSInvocationGetCharPointerType", (void*)primitiveNSInvocationGetCharPointerType}, {"ObjectiveCPlugin", "primitiveGetSuperClass", (void*)primitiveGetSuperClass}, {"ObjectiveCPlugin", "primitiveNSInvocationSetFloatType", (void*)primitiveNSInvocationSetFloatType}, {"ObjectiveCPlugin", "primitiveNSInvocationGetStructureType", (void*)primitiveNSInvocationGetStructureType}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/RePlugin/RePlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from RePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "RePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "rePlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt allocateByteArrayAndSetRcvrExtraPtrFrom(sqInt anExtraPtr); static sqInt allocateByteArrayAndSetRcvrPCREPtrFromPCRE(sqInt aPCREPtr); static sqInt allocateStringAndSetRcvrErrorStrFromCStr(const char *aCStrBuffer); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static void loadRcvrFromStackAt(sqInt stackInteger); static sqInt msg(char *s); EXPORT(void) primLastAlloc(void); EXPORT(void) primNetMemory(void); EXPORT(void) primNumAllocs(void); EXPORT(void) primNumFrees(void); EXPORT(void) primPCRECompile(void); EXPORT(void) primPCREExec(void); EXPORT(void) primPCREExecfromto(void); EXPORT(void) primPCRENumSubPatterns(void); static sqInt rcvrCompileFlags(void); static void rcvrErrorOffsetFrom(sqInt anInteger); static void rcvrErrorStrFrom(sqInt aString); static sqInt rcvrExtraPtr(void); static void rcvrExtraPtrFrom(sqInt aByteArrayOrNilObject); static sqInt rcvrMatchFlags(void); static int * rcvrMatchSpacePtr(void); static sqInt rcvrMatchSpaceSize(void); static char * rcvrPatternStrPtr(void); static void rcvrPCREBufferFrom(sqInt aByteArray); static sqInt rcvrPCREBufferPtr(void); static void rePluginFree(void * aPointer); static void * rePluginMalloc(size_t anInteger); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static void sqAssert(sqInt aBool); /*** Variables ***/ static sqInt compileFlags; static sqInt errorOffset; static sqInt errorStr; static const char * errorStrBuffer; static sqInt extraPtr; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static int lastAlloc = 0; static sqInt matchFlags; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "RePlugin VMMaker-oscog.dtl.57 (i)" #else "RePlugin VMMaker-oscog.dtl.57 (e)" #endif ; static int netMemory = 0; static int numAllocs = 0; static int numFrees = 0; static sqInt patternStr; static const char * patternStrPtr; static sqInt pcrePtr; static sqInt rcvr; static sqInt allocateByteArrayAndSetRcvrExtraPtrFrom(sqInt anExtraPtr) { void *extraByteArrayPtr; sqInt extraObject; if (anExtraPtr) { /* Allocate a Smalltalk ByteArray -- lastAlloc contains the length */ extraObject = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(real_pcre_extra)); /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(0); extraByteArrayPtr = interpreterProxy->arrayValueOf(extraObject); memcpy(extraByteArrayPtr, (void *) anExtraPtr, sizeof(real_pcre_extra)); } else { extraObject = interpreterProxy->nilObject(); } /* begin rcvrExtraPtrFrom: */ interpreterProxy->storePointerofObjectwithValue(3, rcvr, extraObject); ; return extraObject; } static sqInt allocateByteArrayAndSetRcvrPCREPtrFromPCRE(sqInt aPCREPtr) { void *patByteArrayPtr; sqInt patObject; /* Allocate a Smalltalk ByteArray -- lastAlloc contains the length */ patObject = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), lastAlloc); /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(0); patByteArrayPtr = interpreterProxy->arrayValueOf(patObject); memcpy(patByteArrayPtr, (void *) aPCREPtr, lastAlloc); /* begin rcvrPCREBufferFrom: */ interpreterProxy->storePointerofObjectwithValue(2, rcvr, patObject); ; return patObject; } static sqInt allocateStringAndSetRcvrErrorStrFromCStr(const char *aCStrBuffer) { sqInt errorStrObj; void *errorStrObjPtr; sqInt length; /* Allocate errorStrObj */ length = strlen(aCStrBuffer); errorStrObj = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(0); errorStrObjPtr = interpreterProxy->arrayValueOf(errorStrObj); memcpy(errorStrObjPtr,aCStrBuffer,length); ; ; /* begin rcvrErrorStrFrom: */ interpreterProxy->storePointerofObjectwithValue(4, rcvr, errorStrObj); return errorStrObj; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static void loadRcvrFromStackAt(sqInt stackInteger) { rcvr = interpreterProxy->stackObjectValue(stackInteger); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(void) primLastAlloc(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(lastAlloc); } EXPORT(void) primNetMemory(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(netMemory); } EXPORT(void) primNumAllocs(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(numAllocs); } EXPORT(void) primNumFrees(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(numFrees); } /* <rcvr primPCRECompile>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Compile the regular expression in patternStr, and if the compilation is successful, attempt to optimize the compiled expression. Store the results in <pcrePtr> and <extratr>, or fill errorStr with a meaningful errorString and errorOffset with an indicator where the error was found, applying compileFlags throughout. Answer nil with a clean compile (regardless of whether an optimization is possible, and answer with the string otherwise. */ EXPORT(void) primPCRECompile(void) { /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(0); /* begin rcvrPatternStrPtr */ patternStrPtr = ((char *) (((char *) (interpreterProxy->fetchArrayofObject(0, rcvr))))); compileFlags = interpreterProxy->fetchIntegerofObject(1, rcvr); if (interpreterProxy->failed()) { return; } pcrePtr = (int) pcre_compile(patternStrPtr, compileFlags, &errorStrBuffer, &errorOffset, NULL); if (pcrePtr) { allocateByteArrayAndSetRcvrPCREPtrFromPCRE(pcrePtr); extraPtr = (int) pcre_study((pcre *)pcrePtr, compileFlags, &errorStrBuffer); allocateByteArrayAndSetRcvrExtraPtrFrom(extraPtr); rePluginFree(((void *) pcrePtr)); if (extraPtr) { rePluginFree(((void *) extraPtr)); } if (interpreterProxy->failed()) { return; } interpreterProxy->popthenPush(1, interpreterProxy->nilObject()); } else { errorStr = allocateStringAndSetRcvrErrorStrFromCStr(errorStrBuffer); /* begin rcvrErrorOffsetFrom: */ interpreterProxy->storeIntegerofObjectwithValue(5, rcvr, errorOffset); if (interpreterProxy->failed()) { return; } interpreterProxy->popthenPush(1, errorStr); } } /* <rcvr primPCREExec: searchObject>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in <pcrePtr> and <extratr>, generated from calls to primPCRECompile), to smalltalk String searchObject using <matchOptions>. If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match. */ EXPORT(void) primPCREExec(void) { sqInt length; int *matchSpacePtr; sqInt matchSpaceSize; sqInt result; char *searchBuffer; sqInt searchObject; /* Load Parameters */ searchObject = interpreterProxy->stackObjectValue(0); searchBuffer = interpreterProxy->arrayValueOf(searchObject); length = interpreterProxy->byteSizeOf(searchObject); /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(1); pcrePtr = ((int) (interpreterProxy->fetchArrayofObject(2, rcvr))); extraPtr = rcvrExtraPtr(); matchFlags = interpreterProxy->fetchIntegerofObject(6, rcvr); /* begin rcvrMatchSpacePtr */ matchSpacePtr = ((int *) (interpreterProxy->fetchArrayofObject(7, rcvr))); matchSpaceSize = ((sqInt) (interpreterProxy->byteSizeOf(interpreterProxy->fetchPointerofObject(7, rcvr))) >> 2); if (interpreterProxy->failed()) { return; } result = pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); ; ; ; ; } /* <rcvr primPCREExec: searchObject> from: fromInteger to: toInteger>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Apply the regular expression (stored in <pcrePtr> and <extratr>, generated from calls to primPCRECompile), to smalltalk String searchObject using <matchOptions>, beginning at offset <fromInteger> and continuing until offset <toInteger>. If there is no match, answer nil. Otherwise answer a ByteArray of offsets representing the results of the match. */ EXPORT(void) primPCREExecfromto(void) { sqInt fromInteger; sqInt length; int *matchSpacePtr; sqInt matchSpaceSize; sqInt result; char *searchBuffer; sqInt searchObject; sqInt toInteger; /* Load Parameters */ toInteger = interpreterProxy->stackIntegerValue(0); fromInteger = interpreterProxy->stackIntegerValue(1); searchObject = interpreterProxy->stackObjectValue(2); searchBuffer = interpreterProxy->arrayValueOf(searchObject); length = interpreterProxy->byteSizeOf(searchObject); /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(3); interpreterProxy->success(1 <= fromInteger); interpreterProxy->success(toInteger <= length); /* Smalltalk offsets are 1-based */ fromInteger -= 1; interpreterProxy->success(fromInteger <= toInteger); length = toInteger - fromInteger; /* Load Instance Variables */ searchBuffer += fromInteger; pcrePtr = ((int) (interpreterProxy->fetchArrayofObject(2, rcvr))); extraPtr = rcvrExtraPtr(); matchFlags = interpreterProxy->fetchIntegerofObject(6, rcvr); /* begin rcvrMatchSpacePtr */ matchSpacePtr = ((int *) (interpreterProxy->fetchArrayofObject(7, rcvr))); matchSpaceSize = ((sqInt) (interpreterProxy->byteSizeOf(interpreterProxy->fetchPointerofObject(7, rcvr))) >> 2); if (interpreterProxy->failed()) { return; } result = pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); ; ; ; ; } /* <rcvr primPCRENumSubPatterns>, where rcvr is an object with instance variables: 'patternStr compileFlags pcrePtr extraPtr errorStr errorOffset matchFlags' Return the number of subpatterns captured by the compiled pattern. */ /* Load Parameters */ EXPORT(void) primPCRENumSubPatterns(void) { /* begin loadRcvrFromStackAt: */ rcvr = interpreterProxy->stackObjectValue(0); pcrePtr = ((int) (interpreterProxy->fetchArrayofObject(2, rcvr))); interpreterProxy->pop(1); interpreterProxy->pushInteger(pcre_info((pcre *)pcrePtr, NULL, NULL)); } static sqInt rcvrCompileFlags(void) { return interpreterProxy->fetchIntegerofObject(1, rcvr); } static void rcvrErrorOffsetFrom(sqInt anInteger) { interpreterProxy->storeIntegerofObjectwithValue(5, rcvr, anInteger); } static void rcvrErrorStrFrom(sqInt aString) { interpreterProxy->storePointerofObjectwithValue(4, rcvr, aString); } static sqInt rcvrExtraPtr(void) { sqInt extraObj; extraObj = interpreterProxy->fetchPointerofObject(3, rcvr); if (extraObj == (interpreterProxy->nilObject())) { return (int) NULL; } return ((int) (interpreterProxy->arrayValueOf(extraObj))); } static void rcvrExtraPtrFrom(sqInt aByteArrayOrNilObject) { interpreterProxy->storePointerofObjectwithValue(3, rcvr, aByteArrayOrNilObject); } static sqInt rcvrMatchFlags(void) { return interpreterProxy->fetchIntegerofObject(6, rcvr); } static int * rcvrMatchSpacePtr(void) { return ((int *) (interpreterProxy->fetchArrayofObject(7, rcvr))); } static sqInt rcvrMatchSpaceSize(void) { return ((sqInt) (interpreterProxy->byteSizeOf(interpreterProxy->fetchPointerofObject(7, rcvr))) >> 2); } static char * rcvrPatternStrPtr(void) { return ((char *) (interpreterProxy->fetchArrayofObject(0, rcvr))); } static void rcvrPCREBufferFrom(sqInt aByteArray) { interpreterProxy->storePointerofObjectwithValue(2, rcvr, aByteArray); } static sqInt rcvrPCREBufferPtr(void) { return ((int) (interpreterProxy->fetchArrayofObject(2, rcvr))); } /* Free a block of fixed memory allocated with rePluginMalloc. Instrumented version of C free() to facilitate leak analysis from Smalltalk. OS-specific variations on malloc/free, such as with MacOS, are handled by adding a C macro to the header file redefining malloc/free -- see the class comment */ static void rePluginFree(void * aPointer) { numFrees += 1; if (aPointer) { free(aPointer); } } /* Allocate a block of fixed memory using C calls to malloc(). Instrumented to facilitate leak analysis from Smalltalk. Set global lastAlloc to anInteger. OS-specific variations on malloc/free, such as with MacOS, are handled by adding a C macro to the header file redefining malloc/free -- see the class comment */ static void * rePluginMalloc(size_t anInteger) { void *aPointer; numAllocs += 1; if ((aPointer = malloc(anInteger))) { lastAlloc = anInteger; } return aPointer; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* RePlugin_exports[][3] = { {"RePlugin", "getModuleName", (void*)getModuleName}, {"RePlugin", "primLastAlloc", (void*)primLastAlloc}, {"RePlugin", "primNetMemory", (void*)primNetMemory}, {"RePlugin", "primNumAllocs", (void*)primNumAllocs}, {"RePlugin", "primNumFrees", (void*)primNumFrees}, {"RePlugin", "primPCRECompile", (void*)primPCRECompile}, {"RePlugin", "primPCREExec", (void*)primPCREExec}, {"RePlugin", "primPCREExecfromto", (void*)primPCREExecfromto}, {"RePlugin", "primPCRENumSubPatterns", (void*)primPCRENumSubPatterns}, {"RePlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SecurityPlugin/SecurityPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SecurityPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SecurityPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "SecurityPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveCanWriteImage(void); EXPORT(sqInt) primitiveDisableImageWrite(void); EXPORT(sqInt) primitiveGetSecureUserDirectory(void); EXPORT(sqInt) primitiveGetUntrustedUserDirectory(void); EXPORT(sqInt) secCanConnectToPort(sqInt addr, sqInt port); EXPORT(sqInt) secCanCreatePathOfSize(char *dirName, sqInt dirNameSize); EXPORT(sqInt) secCanCreateSocketOfType(sqInt netType, sqInt socketType); EXPORT(sqInt) secCanDeleteFileOfSize(char *fileName, sqInt fileNameSize); EXPORT(sqInt) secCanDeletePathOfSize(char *dirName, sqInt dirNameSize); EXPORT(sqInt) secCanGetFileTypeOfSize(char *fileName, sqInt fileNameSize); EXPORT(sqInt) secCanListPathOfSize(char *pathName, sqInt pathNameSize); EXPORT(sqInt) secCanOpenAsyncFileOfSizeWritable(char *fileName, sqInt fileNameSize, sqInt writeFlag); EXPORT(sqInt) secCanOpenFileOfSizeWritable(char *fileName, sqInt fileNameSize, sqInt writeFlag); EXPORT(sqInt) secCanRenameFileOfSize(char *fileName, sqInt fileNameSize); EXPORT(sqInt) secCanRenameImage(void); EXPORT(sqInt) secCanSetFileTypeOfSize(char *fileName, sqInt fileNameSize); EXPORT(sqInt) secCanWriteImage(void); EXPORT(sqInt) secCanListenOnPort(sqInt socket, sqInt port); EXPORT(sqInt) secDisableFileAccess(void); EXPORT(sqInt) secDisableSocketAccess(void); EXPORT(sqInt) secHasFileAccess(void); EXPORT(sqInt) secHasSocketAccess(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SecurityPlugin VMMaker-oscog.dtl.57 (i)" #else "SecurityPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return ioInitSecurity(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveCanWriteImage(void) { interpreterProxy->pop(1); interpreterProxy->pushBool(ioCanWriteImage()); } EXPORT(sqInt) primitiveDisableImageWrite(void) { ioDisableImageWrite(); } /* Primitive. Return the secure directory for the current user. */ EXPORT(sqInt) primitiveGetSecureUserDirectory(void) { sqInt dirLen; char *dirName; sqInt dirOop; char *dirPtr; sqInt i; dirName = ioGetSecureUserDirectory(); if ((dirName == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } dirLen = strlen(dirName); dirOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), dirLen); if (interpreterProxy->failed()) { return null; } dirPtr = interpreterProxy->firstIndexableField(dirOop); for (i = 0; i <= (dirLen - 1); i += 1) { dirPtr[i] = (dirName[i]); } interpreterProxy->popthenPush(1, dirOop); } /* Primitive. Return the untrusted user directory name. */ EXPORT(sqInt) primitiveGetUntrustedUserDirectory(void) { sqInt dirLen; char *dirName; sqInt dirOop; char *dirPtr; sqInt i; dirName = ioGetUntrustedUserDirectory(); if ((dirName == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } dirLen = strlen(dirName); dirOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), dirLen); if (interpreterProxy->failed()) { return null; } dirPtr = interpreterProxy->firstIndexableField(dirOop); for (i = 0; i <= (dirLen - 1); i += 1) { dirPtr[i] = (dirName[i]); } interpreterProxy->popthenPush(1, dirOop); } EXPORT(sqInt) secCanConnectToPort(sqInt addr, sqInt port) { return ioCanConnectToPort(addr, port); } EXPORT(sqInt) secCanCreatePathOfSize(char *dirName, sqInt dirNameSize) { return ioCanCreatePathOfSize(dirName, dirNameSize); } EXPORT(sqInt) secCanCreateSocketOfType(sqInt netType, sqInt socketType) { return ioCanCreateSocketOfType(netType, socketType); } EXPORT(sqInt) secCanDeleteFileOfSize(char *fileName, sqInt fileNameSize) { return ioCanDeleteFileOfSize(fileName, fileNameSize); } EXPORT(sqInt) secCanDeletePathOfSize(char *dirName, sqInt dirNameSize) { return ioCanDeletePathOfSize(dirName, dirNameSize); } EXPORT(sqInt) secCanGetFileTypeOfSize(char *fileName, sqInt fileNameSize) { return ioCanGetFileTypeOfSize(fileName, fileNameSize); } EXPORT(sqInt) secCanListPathOfSize(char *pathName, sqInt pathNameSize) { return ioCanListPathOfSize(pathName, pathNameSize); } EXPORT(sqInt) secCanOpenAsyncFileOfSizeWritable(char *fileName, sqInt fileNameSize, sqInt writeFlag) { return ioCanOpenAsyncFileOfSizeWritable(fileName, fileNameSize, writeFlag); } EXPORT(sqInt) secCanOpenFileOfSizeWritable(char *fileName, sqInt fileNameSize, sqInt writeFlag) { return ioCanOpenFileOfSizeWritable(fileName, fileNameSize, writeFlag); } EXPORT(sqInt) secCanRenameFileOfSize(char *fileName, sqInt fileNameSize) { return ioCanRenameFileOfSize(fileName, fileNameSize); } EXPORT(sqInt) secCanRenameImage(void) { return ioCanRenameImage(); } EXPORT(sqInt) secCanSetFileTypeOfSize(char *fileName, sqInt fileNameSize) { return ioCanSetFileTypeOfSize(fileName, fileNameSize); } EXPORT(sqInt) secCanWriteImage(void) { return ioCanWriteImage(); } EXPORT(sqInt) secCanListenOnPort(sqInt socket, sqInt port) { return ioCanListenOnPort(socket, port); } EXPORT(sqInt) secDisableFileAccess(void) { return ioDisableFileAccess(); } EXPORT(sqInt) secDisableSocketAccess(void) { return ioDisableSocketAccess(); } EXPORT(sqInt) secHasFileAccess(void) { return ioHasFileAccess(); } EXPORT(sqInt) secHasSocketAccess(void) { return ioHasSocketAccess(); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SecurityPlugin_exports[][3] = { {"SecurityPlugin", "getModuleName", (void*)getModuleName}, {"SecurityPlugin", "initialiseModule", (void*)initialiseModule}, {"SecurityPlugin", "primitiveCanWriteImage", (void*)primitiveCanWriteImage}, {"SecurityPlugin", "primitiveDisableImageWrite", (void*)primitiveDisableImageWrite}, {"SecurityPlugin", "primitiveGetSecureUserDirectory", (void*)primitiveGetSecureUserDirectory}, {"SecurityPlugin", "primitiveGetUntrustedUserDirectory", (void*)primitiveGetUntrustedUserDirectory}, {"SecurityPlugin", "secCanConnectToPort", (void*)secCanConnectToPort}, {"SecurityPlugin", "secCanCreatePathOfSize", (void*)secCanCreatePathOfSize}, {"SecurityPlugin", "secCanCreateSocketOfType", (void*)secCanCreateSocketOfType}, {"SecurityPlugin", "secCanDeleteFileOfSize", (void*)secCanDeleteFileOfSize}, {"SecurityPlugin", "secCanDeletePathOfSize", (void*)secCanDeletePathOfSize}, {"SecurityPlugin", "secCanGetFileTypeOfSize", (void*)secCanGetFileTypeOfSize}, {"SecurityPlugin", "secCanListenOnPort", (void*)secCanListenOnPort}, {"SecurityPlugin", "secCanListPathOfSize", (void*)secCanListPathOfSize}, {"SecurityPlugin", "secCanOpenAsyncFileOfSizeWritable", (void*)secCanOpenAsyncFileOfSizeWritable}, {"SecurityPlugin", "secCanOpenFileOfSizeWritable", (void*)secCanOpenFileOfSizeWritable}, {"SecurityPlugin", "secCanRenameFileOfSize", (void*)secCanRenameFileOfSize}, {"SecurityPlugin", "secCanRenameImage", (void*)secCanRenameImage}, {"SecurityPlugin", "secCanSetFileTypeOfSize", (void*)secCanSetFileTypeOfSize}, {"SecurityPlugin", "secCanWriteImage", (void*)secCanWriteImage}, {"SecurityPlugin", "secDisableFileAccess", (void*)secDisableFileAccess}, {"SecurityPlugin", "secDisableSocketAccess", (void*)secDisableSocketAccess}, {"SecurityPlugin", "secHasFileAccess", (void*)secHasFileAccess}, {"SecurityPlugin", "secHasSocketAccess", (void*)secHasSocketAccess}, {"SecurityPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SerialPlugin/SerialPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SerialPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SerialPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "SerialPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveSerialPortClose(void); EXPORT(sqInt) primitiveSerialPortOpen(void); EXPORT(sqInt) primitiveSerialPortRead(void); EXPORT(sqInt) primitiveSerialPortWrite(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SerialPlugin VMMaker-oscog.dtl.57 (i)" #else "SerialPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return serialPortInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveSerialPortClose(void) { sqInt portNum; portNum = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } serialPortClose(portNum); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSerialPortOpen(void) { sqInt baudRate; sqInt dataBits; sqInt inFlowControl; sqInt outFlowControl; sqInt parityType; sqInt portNum; sqInt stopBitsType; sqInt xOffChar; sqInt xOnChar; portNum = interpreterProxy->stackIntegerValue(8); baudRate = interpreterProxy->stackIntegerValue(7); stopBitsType = interpreterProxy->stackIntegerValue(6); parityType = interpreterProxy->stackIntegerValue(5); dataBits = interpreterProxy->stackIntegerValue(4); inFlowControl = interpreterProxy->stackIntegerValue(3); outFlowControl = interpreterProxy->stackIntegerValue(2); xOnChar = interpreterProxy->stackIntegerValue(1); xOffChar = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } serialPortOpen( portNum, baudRate, stopBitsType, parityType, dataBits, inFlowControl, outFlowControl, xOnChar, xOffChar); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(9); return null; } EXPORT(sqInt) primitiveSerialPortRead(void) { char *array; sqInt arrayPtr; sqInt bytesRead; sqInt count; sqInt portNum; sqInt startIndex; sqInt _return_value; portNum = interpreterProxy->stackIntegerValue(3); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->byteSizeOf(((sqInt)(long)(array) - 4))))); arrayPtr = ((((sqInt)array)) + startIndex) - 1; bytesRead = serialPortReadInto( portNum, count, arrayPtr); _return_value = interpreterProxy->integerObjectOf(bytesRead); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveSerialPortWrite(void) { char *array; sqInt arrayPtr; sqInt bytesWritten; sqInt count; sqInt portNum; sqInt startIndex; sqInt _return_value; portNum = interpreterProxy->stackIntegerValue(3); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); array = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= (interpreterProxy->byteSizeOf(((sqInt)(long)(array) - 4))))); if (!(interpreterProxy->failed())) { arrayPtr = ((((sqInt)array)) + startIndex) - 1; bytesWritten = serialPortWriteFrom(portNum, count, arrayPtr); } _return_value = interpreterProxy->integerObjectOf(bytesWritten); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return serialPortShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SerialPlugin_exports[][3] = { {"SerialPlugin", "getModuleName", (void*)getModuleName}, {"SerialPlugin", "initialiseModule", (void*)initialiseModule}, {"SerialPlugin", "primitiveSerialPortClose", (void*)primitiveSerialPortClose}, {"SerialPlugin", "primitiveSerialPortOpen", (void*)primitiveSerialPortOpen}, {"SerialPlugin", "primitiveSerialPortRead", (void*)primitiveSerialPortRead}, {"SerialPlugin", "primitiveSerialPortWrite", (void*)primitiveSerialPortWrite}, {"SerialPlugin", "setInterpreter", (void*)setInterpreter}, {"SerialPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SlangTestSupportPlugin/SlangTestSupportPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:46 pm by VMMaker 4.4.7 */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt declareExportFalseByMethod(void); static sqInt declareExportFalseByPragma(void); #pragma export on EXPORT(sqInt) declareExportTrueByMethod(void); EXPORT(sqInt) declareExportTrueByPragma(void); #pragma export off sqInt declareStaticFalseByMethod(void); sqInt declareStaticFalseByPragma(void); static sqInt declareStaticTrueByMethod(void); static sqInt declareStaticTrueByPragma(void); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt inlineByMethod(void); static sqInt inlineByPragma(void); static sqInt methodThatShouldBeInlinedByMethod(void); static sqInt methodThatShouldBeInlinedByPragma(void); static sqInt methodThatShouldNotBeInlinedByMethod(void); static sqInt methodThatShouldNotBeInlinedByPragma(void); static sqInt msg(char *s); static char * returnTypeByMethod(void); static char * returnTypeByPragma(void); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static sqInt varDefByMethod(void); static sqInt varDefByMethodAndPragma(void); static sqInt varDefByPragma(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SlangTestSupportPlugin 23 January 2011 (i)" #else "SlangTestSupportPlugin 23 January 2011 (e)" #endif ; /* SlangTestSupport asCString: #declareExportFalseByMethod */ static sqInt declareExportFalseByMethod(void) { } /* SlangTestSupport asCString: #declareExportFalseByPragma */ static sqInt declareExportFalseByPragma(void) { } /* SlangTestSupport asCString: #declareExportTrueByMethod */ EXPORT(sqInt) declareExportTrueByMethod(void) { } /* SlangTestSupport asCString: #declareExportTrueByPragma */ EXPORT(sqInt) declareExportTrueByPragma(void) { } /* SlangTestSupport asCString: #declareStaticFalseByMethod */ sqInt declareStaticFalseByMethod(void) { } /* SlangTestSupport asCString: #declareStaticFalseByPragma */ sqInt declareStaticFalseByPragma(void) { } /* SlangTestSupport asCString: #declareStaticTrueByMethod */ static sqInt declareStaticTrueByMethod(void) { } /* SlangTestSupport asCString: #declareStaticTrueByPragma */ static sqInt declareStaticTrueByPragma(void) { } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } /* SlangTestSupport asCString: #inlineByMethod */ /* SlangTestSupport asInlinedCString: #inlineByMethod */ static sqInt inlineByMethod(void) { sqInt bar; sqInt foo; foo = "foo"; bar = methodThatShouldNotBeInlinedByMethod(); } /* SlangTestSupport asCString: #inlineByPragma */ /* SlangTestSupport asInlinedCString: #inlineByPragma */ static sqInt inlineByPragma(void) { sqInt bar; sqInt foo; foo = "foo"; bar = methodThatShouldNotBeInlinedByPragma(); } static sqInt methodThatShouldBeInlinedByMethod(void) { return "foo"; } static sqInt methodThatShouldBeInlinedByPragma(void) { return "foo"; } static sqInt methodThatShouldNotBeInlinedByMethod(void) { return "bar"; } static sqInt methodThatShouldNotBeInlinedByPragma(void) { return "bar"; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* SlangTestSupport asCString: #returnTypeByMethod */ static char * returnTypeByMethod(void) { } /* SlangTestSupport asCString: #returnTypeByPragma */ static char * returnTypeByPragma(void) { } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* SlangTestSupport asCString: #varDefByMethod */ static sqInt varDefByMethod(void) { unsigned int * bar; char *foo; } /* SlangTestSupportPlugin asCString: #varDefByMethodAndPragma */ static sqInt varDefByMethodAndPragma(void) { unsigned int * bar; float baz; char *foo; double fum; } /* SlangTestSupport asCString: #varDefByPragma */ static sqInt varDefByPragma(void) { unsigned int * bar; char *foo; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SlangTestSupportPlugin_exports[][3] = { {"SlangTestSupportPlugin", "declareExportTrueByMethod", (void*)declareExportTrueByMethod}, {"SlangTestSupportPlugin", "setInterpreter", (void*)setInterpreter}, {"SlangTestSupportPlugin", "declareExportTrueByPragma", (void*)declareExportTrueByPragma}, {"SlangTestSupportPlugin", "getModuleName", (void*)getModuleName}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SocketPlugin/SocketPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SocketPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SocketPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "SocketPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt intToNetAddress(sqInt addr); EXPORT(void) moduleUnloaded(char *aModuleName); static sqInt msg(char *s); static sqInt netAddressToInt(unsigned char * ptrToByteArray); EXPORT(void) primitiveDisableSocketAccess(void); EXPORT(void) primitiveHasSocketAccess(void); EXPORT(sqInt) primitiveInitializeNetwork(void); EXPORT(sqInt) primitiveResolverAbortLookup(void); EXPORT(sqInt) primitiveResolverAddressLookupResult(void); EXPORT(sqInt) primitiveResolverError(void); EXPORT(sqInt) primitiveResolverLocalAddress(void); EXPORT(sqInt) primitiveResolverNameLookupResult(void); EXPORT(sqInt) primitiveResolverStartAddressLookup(void); EXPORT(sqInt) primitiveResolverStartNameLookup(void); EXPORT(sqInt) primitiveResolverStatus(void); EXPORT(sqInt) primitiveSocketAbortConnection(void); EXPORT(sqInt) primitiveSocketAccept(void); EXPORT(sqInt) primitiveSocketAccept3Semaphores(void); EXPORT(sqInt) primitiveSocketBindToPort(void); EXPORT(sqInt) primitiveSocketCloseConnection(void); EXPORT(sqInt) primitiveSocketConnectionStatus(void); EXPORT(sqInt) primitiveSocketConnectToPort(void); EXPORT(sqInt) primitiveSocketCreate(void); EXPORT(sqInt) primitiveSocketCreate3Semaphores(void); EXPORT(sqInt) primitiveSocketCreateRAW(void); EXPORT(sqInt) primitiveSocketDestroy(void); EXPORT(sqInt) primitiveSocketError(void); EXPORT(sqInt) primitiveSocketGetOptions(void); EXPORT(sqInt) primitiveSocketListenOnPort(void); EXPORT(sqInt) primitiveSocketListenOnPortBacklog(void); EXPORT(sqInt) primitiveSocketListenOnPortBacklogInterface(void); EXPORT(sqInt) primitiveSocketListenWithOrWithoutBacklog(void); EXPORT(sqInt) primitiveSocketLocalAddress(void); EXPORT(sqInt) primitiveSocketLocalPort(void); EXPORT(sqInt) primitiveSocketReceiveDataAvailable(void); EXPORT(sqInt) primitiveSocketReceiveDataBufCount(void); EXPORT(sqInt) primitiveSocketReceiveUDPDataBufCount(void); EXPORT(sqInt) primitiveSocketRemoteAddress(void); EXPORT(sqInt) primitiveSocketRemotePort(void); EXPORT(sqInt) primitiveSocketSendDataBufCount(void); EXPORT(sqInt) primitiveSocketSendDone(void); EXPORT(sqInt) primitiveSocketSendUDPDataBufCount(void); EXPORT(sqInt) primitiveSocketSetOptions(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static sqInt socketRecordSize(void); static SocketPtr socketValueOf(sqInt socketOop); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SocketPlugin VMMaker-oscog.dtl.57 (i)" #else "SocketPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static void * sCCLOPfn; static void * sCCSOTfn; static void * sCCTPfn; static void * sDSAfn; static void * sHSAfn; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { sDSAfn = interpreterProxy->ioLoadFunctionFrom("secDisableSocketAccess", "SecurityPlugin"); sHSAfn = interpreterProxy->ioLoadFunctionFrom("secHasSocketAccess", "SecurityPlugin"); sCCTPfn = interpreterProxy->ioLoadFunctionFrom("secCanConnectToPort", "SecurityPlugin"); sCCLOPfn = interpreterProxy->ioLoadFunctionFrom("secCanListenOnPort", "SecurityPlugin"); sCCSOTfn = interpreterProxy->ioLoadFunctionFrom("secCanCreateSocketOfType", "SecurityPlugin"); return socketInit(); } /* Convert the given 32-bit integer into an internet network address represented as a four-byte ByteArray. */ static sqInt intToNetAddress(sqInt addr) { char * naPtr; sqInt netAddressOop; netAddressOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), 4); naPtr = (char *) interpreterProxy->firstIndexableField(netAddressOop); naPtr[0] = (((char) ((((usqInt) addr) >> 24) & 255))); naPtr[1] = (((char) ((((usqInt) addr) >> 16) & 255))); naPtr[2] = (((char) ((((usqInt) addr) >> 8) & 255))); naPtr[3] = (((char) (addr & 255))); return netAddressOop; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(void) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SecurityPlugin")) == 0) { sDSAfn = sHSAfn = sCCTPfn = sCCLOPfn = sCCSOTfn = 0; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Convert the given internet network address (represented as a four-byte ByteArray) into a 32-bit integer. Fail if the given ptrToByteArray does not appear to point to a four-byte ByteArray. */ static sqInt netAddressToInt(unsigned char * ptrToByteArray) { sqInt sz; sz = interpreterProxy->byteSizeOf(((sqInt)(long)(ptrToByteArray) - 4)); if (!(sz == 4)) { return interpreterProxy->primitiveFail(); } return (((ptrToByteArray[3]) + ((ptrToByteArray[2]) << 8)) + ((ptrToByteArray[1]) << 16)) + ((ptrToByteArray[0]) << 24); } /* If the security plugin can be loaded, use it to turn off socket access If not, assume it's ok */ EXPORT(void) primitiveDisableSocketAccess(void) { if (sDSAfn != 0) { ((int (*) (void)) sDSAfn)(); } } EXPORT(void) primitiveHasSocketAccess(void) { sqInt hasAccess; hasAccess = (sHSAfn == 0) || ( ((int (*) (void)) sHSAfn)()); interpreterProxy->pop(1); interpreterProxy->pushBool(hasAccess); } EXPORT(sqInt) primitiveInitializeNetwork(void) { sqInt err; sqInt resolverSemaIndex; resolverSemaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } err = sqNetworkInit(resolverSemaIndex); interpreterProxy->success(err == 0); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveResolverAbortLookup(void) { sqResolverAbort(); if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitiveResolverAddressLookupResult(void) { sqInt s; sqInt sz; sz = sqResolverAddrLookupResultSize(); if (!(interpreterProxy->failed())) { s = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), sz); sqResolverAddrLookupResult((char *) interpreterProxy->firstIndexableField(s), sz); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, s); return null; } EXPORT(sqInt) primitiveResolverError(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf((sqResolverError())); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveResolverLocalAddress(void) { sqInt addr; sqInt _return_value; addr = sqResolverLocalAddress(); _return_value = intToNetAddress(addr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveResolverNameLookupResult(void) { sqInt addr; sqInt _return_value; addr = sqResolverNameLookupResult(); _return_value = intToNetAddress(addr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveResolverStartAddressLookup(void) { sqInt addr; char *address; sqInt sz; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); address = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } /* begin netAddressToInt: */ sz = interpreterProxy->byteSizeOf(((sqInt)(long)((((unsigned char *) address))) - 4)); if (!(sz == 4)) { addr = interpreterProxy->primitiveFail(); goto l1; } addr = ((((((unsigned char *) address))[3]) + (((((unsigned char *) address))[2]) << 8)) + (((((unsigned char *) address))[1]) << 16)) + (((((unsigned char *) address))[0]) << 24); l1: /* end netAddressToInt: */; if (!(interpreterProxy->failed())) { sqResolverStartAddrLookup(addr); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveResolverStartNameLookup(void) { char *name; sqInt sz; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->failed())) { sz = interpreterProxy->byteSizeOf(((sqInt)(long)(name) - 4)); sqResolverStartNameLookup(name, sz); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveResolverStatus(void) { sqInt status; sqInt _return_value; status = sqResolverStatus(); _return_value = interpreterProxy->integerObjectOf(status); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveSocketAbortConnection(void) { SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { sqSocketAbortConnection(s); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSocketAccept(void) { sqInt recvBufSize; SocketPtr s; sqInt semaIndex; sqInt sendBufSize; SocketPtr serverSocket; void *socketIndex; void *socketIndex1; sqInt socketOop; sqInt sockHandle; sockHandle = interpreterProxy->stackValue(3); recvBufSize = interpreterProxy->stackIntegerValue(2); sendBufSize = interpreterProxy->stackIntegerValue(1); semaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(sockHandle)) && ((interpreterProxy->byteSizeOf(sockHandle)) == (socketRecordSize()))); if (interpreterProxy->failed()) { serverSocket = null; goto l2; } socketIndex1 = ((SocketPtr) (interpreterProxy->firstIndexableField(sockHandle))); serverSocket = socketIndex1; l2: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { socketOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); s = socketIndex; l1: /* end socketValueOf: */; sqSocketAcceptFromRecvBytesSendBytesSemaID(s, serverSocket, recvBufSize, sendBufSize, semaIndex); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, socketOop); return null; } EXPORT(sqInt) primitiveSocketAccept3Semaphores(void) { sqInt aReadSema; sqInt aWriteSema; sqInt recvBufSize; SocketPtr s; sqInt semaIndex; sqInt sendBufSize; SocketPtr serverSocket; void *socketIndex; void *socketIndex1; sqInt socketOop; sqInt sockHandle; sockHandle = interpreterProxy->stackValue(5); recvBufSize = interpreterProxy->stackIntegerValue(4); sendBufSize = interpreterProxy->stackIntegerValue(3); semaIndex = interpreterProxy->stackIntegerValue(2); aReadSema = interpreterProxy->stackIntegerValue(1); aWriteSema = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(sockHandle)) && ((interpreterProxy->byteSizeOf(sockHandle)) == (socketRecordSize()))); if (interpreterProxy->failed()) { serverSocket = null; goto l2; } socketIndex1 = ((SocketPtr) (interpreterProxy->firstIndexableField(sockHandle))); serverSocket = socketIndex1; l2: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { socketOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); s = socketIndex; l1: /* end socketValueOf: */; sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(s, serverSocket, recvBufSize, sendBufSize, semaIndex, aReadSema, aWriteSema); } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(7, socketOop); return null; } EXPORT(sqInt) primitiveSocketBindToPort(void) { sqInt addr; char *address; sqInt port; SocketPtr s; sqInt socket; void *socketIndex; sqInt sz; socket = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); address = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); port = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin netAddressToInt: */ sz = interpreterProxy->byteSizeOf(((sqInt)(long)((((unsigned char *) address))) - 4)); if (!(sz == 4)) { addr = interpreterProxy->primitiveFail(); goto l1; } addr = ((((((unsigned char *) address))[3]) + (((((unsigned char *) address))[2]) << 8)) + (((((unsigned char *) address))[1]) << 16)) + (((((unsigned char *) address))[0]) << 24); l1: /* end netAddressToInt: */; /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l2; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l2: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { sqSocketBindToPort(s, addr, port); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveSocketCloseConnection(void) { SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { sqSocketCloseConnection(s); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSocketConnectionStatus(void) { SocketPtr s; sqInt socket; void *socketIndex; sqInt status; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { status = sqSocketConnectionStatus(s); } _return_value = interpreterProxy->integerObjectOf(status); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketConnectToPort(void) { sqInt addr; char *address; sqInt okToConnect; sqInt port; SocketPtr s; sqInt socket; void *socketIndex; sqInt sz; socket = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); address = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); port = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin netAddressToInt: */ sz = interpreterProxy->byteSizeOf(((sqInt)(long)((((unsigned char *) address))) - 4)); if (!(sz == 4)) { addr = interpreterProxy->primitiveFail(); goto l1; } addr = ((((((unsigned char *) address))[3]) + (((((unsigned char *) address))[2]) << 8)) + (((((unsigned char *) address))[1]) << 16)) + (((((unsigned char *) address))[0]) << 24); l1: /* end netAddressToInt: */; if (sCCTPfn != 0) { okToConnect = ((int (*) (int, int)) sCCTPfn)(addr, port); if (!(okToConnect)) { interpreterProxy->primitiveFail(); return null; } } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l2; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l2: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { sqSocketConnectToPort(s, addr, port); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveSocketCreate(void) { sqInt netType; sqInt okToCreate; sqInt recvBufSize; SocketPtr s; sqInt semaIndex; sqInt sendBufSize; void *socketIndex; sqInt socketOop; sqInt socketType; netType = interpreterProxy->stackIntegerValue(4); socketType = interpreterProxy->stackIntegerValue(3); recvBufSize = interpreterProxy->stackIntegerValue(2); sendBufSize = interpreterProxy->stackIntegerValue(1); semaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (sCCSOTfn != 0) { okToCreate = ((int (*) (int, int)) sCCSOTfn)(netType, socketType); if (!(okToCreate)) { interpreterProxy->primitiveFail(); return null; } } socketOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); s = socketIndex; l1: /* end socketValueOf: */; sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID(s, netType, socketType, recvBufSize, sendBufSize, semaIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, socketOop); return null; } EXPORT(sqInt) primitiveSocketCreate3Semaphores(void) { sqInt aReadSema; sqInt aWriteSema; sqInt netType; sqInt okToCreate; sqInt recvBufSize; SocketPtr s; sqInt semaIndex; sqInt sendBufSize; void *socketIndex; sqInt socketOop; sqInt socketType; netType = interpreterProxy->stackIntegerValue(6); socketType = interpreterProxy->stackIntegerValue(5); recvBufSize = interpreterProxy->stackIntegerValue(4); sendBufSize = interpreterProxy->stackIntegerValue(3); semaIndex = interpreterProxy->stackIntegerValue(2); aReadSema = interpreterProxy->stackIntegerValue(1); aWriteSema = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (sCCSOTfn != 0) { okToCreate = ((int (*) (int, int)) sCCSOTfn)(netType, socketType); if (!(okToCreate)) { interpreterProxy->primitiveFail(); return null; } } socketOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); s = socketIndex; l1: /* end socketValueOf: */; sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(s, netType, socketType, recvBufSize, sendBufSize, semaIndex, aReadSema, aWriteSema); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(8, socketOop); return null; } EXPORT(sqInt) primitiveSocketCreateRAW(void) { sqInt aReadSema; sqInt aWriteSema; sqInt netType; sqInt okToCreate; sqInt protoType; sqInt recvBufSize; SocketPtr s; sqInt semaIndex; sqInt sendBufSize; void *socketIndex; sqInt socketOop; netType = interpreterProxy->stackIntegerValue(6); protoType = interpreterProxy->stackIntegerValue(5); recvBufSize = interpreterProxy->stackIntegerValue(4); sendBufSize = interpreterProxy->stackIntegerValue(3); semaIndex = interpreterProxy->stackIntegerValue(2); aReadSema = interpreterProxy->stackIntegerValue(1); aWriteSema = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (sCCSOTfn != 0) { okToCreate = ((int (*) (int, int)) sCCSOTfn)(netType, protoType); if (!(okToCreate)) { interpreterProxy->primitiveFail(); return null; } } socketOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); s = socketIndex; l1: /* end socketValueOf: */; sqSocketCreateRawProtoTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(s, netType, protoType, recvBufSize, sendBufSize, semaIndex, aReadSema, aWriteSema); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(8, socketOop); return null; } EXPORT(sqInt) primitiveSocketDestroy(void) { SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { sqSocketDestroy(s); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSocketError(void) { sqInt err; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (!(interpreterProxy->failed())) { err = sqSocketError(s); } _return_value = interpreterProxy->integerObjectOf(err); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketGetOptions(void) { sqInt errorCode; sqInt optionName; sqInt optionNameSize; char *optionNameStart; sqInt results; sqInt returnedValue; SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(1); optionName = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isBytes(optionName)); optionNameStart = ((char *) (interpreterProxy->firstIndexableField(optionName))); optionNameSize = interpreterProxy->slotSizeOf(optionName); if (interpreterProxy->failed()) { return null; } returnedValue = 0; errorCode = sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(s, optionNameStart, optionNameSize, &returnedValue); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(returnedValue)); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(errorCode)); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); results = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, results, interpreterProxy->popRemappableOop()); interpreterProxy->storePointerofObjectwithValue(1, results, interpreterProxy->popRemappableOop()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, results); return null; } /* one part of the wierdass dual prim primitiveSocketListenOnPort which was warped by some demented evil person determined to twist the very nature of reality */ EXPORT(sqInt) primitiveSocketListenOnPort(void) { sqInt okToListen; sqInt port; SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(1); port = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (sCCLOPfn != 0) { okToListen = ((int (*) (SocketPtr, int)) sCCLOPfn)(s, port); if (!(okToListen)) { interpreterProxy->primitiveFail(); return null; } } sqSocketListenOnPort(s, port); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* second part of the wierdass dual prim primitiveSocketListenOnPort which was warped by some demented evil person determined to twist the very nature of reality */ EXPORT(sqInt) primitiveSocketListenOnPortBacklog(void) { sqInt backlog; sqInt okToListen; sqInt port; SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(2); port = interpreterProxy->stackIntegerValue(1); backlog = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; if (sCCLOPfn != 0) { okToListen = ((int (*) (SocketPtr, int)) sCCLOPfn)(s, port); if (!(okToListen)) { interpreterProxy->primitiveFail(); return null; } } sqSocketListenOnPortBacklogSize(s, port, backlog); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* Bind a socket to the given port and interface address with no more than backlog pending connections. The socket can be UDP, in which case the backlog should be specified as zero. */ EXPORT(sqInt) primitiveSocketListenOnPortBacklogInterface(void) { sqInt addr; sqInt backlog; char *ifAddr; sqInt okToListen; sqInt port; SocketPtr s; sqInt socket; void *socketIndex; sqInt sz; socket = interpreterProxy->stackValue(3); port = interpreterProxy->stackIntegerValue(2); backlog = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); ifAddr = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l2; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l2: /* end socketValueOf: */; if (sCCLOPfn != 0) { okToListen = ((int (*) (SocketPtr, int)) sCCLOPfn)(s, port); if (!(okToListen)) { interpreterProxy->primitiveFail(); return null; } } /* begin netAddressToInt: */ sz = interpreterProxy->byteSizeOf(((sqInt)(long)((((unsigned char *) ifAddr))) - 4)); if (!(sz == 4)) { addr = interpreterProxy->primitiveFail(); goto l1; } addr = ((((((unsigned char *) ifAddr))[3]) + (((((unsigned char *) ifAddr))[2]) << 8)) + (((((unsigned char *) ifAddr))[1]) << 16)) + (((((unsigned char *) ifAddr))[0]) << 24); l1: /* end netAddressToInt: */; sqSocketListenOnPortBacklogSizeInterface(s, port, backlog, addr); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } /* Backward compatibility */ EXPORT(sqInt) primitiveSocketListenWithOrWithoutBacklog(void) { if ((interpreterProxy->methodArgumentCount()) == 2) { return primitiveSocketListenOnPort(); } else { return primitiveSocketListenOnPortBacklog(); } } EXPORT(sqInt) primitiveSocketLocalAddress(void) { sqInt addr; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; addr = sqSocketLocalAddress(s); _return_value = intToNetAddress(addr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketLocalPort(void) { sqInt port; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; port = sqSocketLocalPort(s); _return_value = interpreterProxy->integerObjectOf(port); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketReceiveDataAvailable(void) { sqInt dataIsAvailable; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; dataIsAvailable = sqSocketReceiveDataAvailable(s); _return_value = (dataIsAvailable) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketReceiveDataBufCount(void) { sqInt array; char *arrayBase; char *bufStart; sqInt byteSize; sqInt bytesReceived; sqInt count; SocketPtr s; sqInt socket; void *socketIndex; sqInt startIndex; sqInt _return_value; socket = interpreterProxy->stackValue(3); array = interpreterProxy->stackValue(2); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isWordsOrBytes(array)); if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } interpreterProxy->success((startIndex >= 1) && ((count >= 0) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))); if (!(interpreterProxy->failed())) { /* Note: adjust bufStart for zero-origin indexing */ arrayBase = ((char *) (interpreterProxy->firstIndexableField(array))); bufStart = arrayBase + ((startIndex - 1) * byteSize); bytesReceived = sqSocketReceiveDataBufCount(s, bufStart, count * byteSize); } _return_value = interpreterProxy->integerObjectOf((bytesReceived / byteSize)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveSocketReceiveUDPDataBufCount(void) { sqInt address; sqInt array; char *arrayBase; char *bufStart; sqInt byteSize; sqInt bytesReceived; sqInt count; sqInt moreFlag; sqInt port; sqInt results; SocketPtr s; sqInt socket; void *socketIndex; sqInt startIndex; socket = interpreterProxy->stackValue(3); array = interpreterProxy->stackValue(2); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isWordsOrBytes(array)); if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } interpreterProxy->success((startIndex >= 1) && ((count >= 0) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))); if (!(interpreterProxy->failed())) { /* Note: adjust bufStart for zero-origin indexing */ arrayBase = ((char *) (interpreterProxy->firstIndexableField(array))); /* allocate storage for results, remapping newly allocated oops in case GC happens during allocation */ bufStart = arrayBase + ((startIndex - 1) * byteSize); address = 0; port = 0; moreFlag = 0; bytesReceived = sqSocketReceiveUDPDataBufCountaddressportmoreFlag(s, bufStart, count * byteSize, &address, &port, &moreFlag); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(port)); interpreterProxy->pushRemappableOop(intToNetAddress(address)); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf((bytesReceived / byteSize))); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); results = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, results, interpreterProxy->popRemappableOop()); interpreterProxy->storePointerofObjectwithValue(1, results, interpreterProxy->popRemappableOop()); interpreterProxy->storePointerofObjectwithValue(2, results, interpreterProxy->popRemappableOop()); if (moreFlag) { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->trueObject()); } else { interpreterProxy->storePointerofObjectwithValue(3, results, interpreterProxy->falseObject()); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, results); return null; } EXPORT(sqInt) primitiveSocketRemoteAddress(void) { sqInt addr; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; addr = sqSocketRemoteAddress(s); _return_value = intToNetAddress(addr); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketRemotePort(void) { sqInt port; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; port = sqSocketRemotePort(s); _return_value = interpreterProxy->integerObjectOf(port); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketSendDataBufCount(void) { sqInt array; char *arrayBase; char *bufStart; sqInt byteSize; sqInt bytesSent; sqInt count; SocketPtr s; sqInt socket; void *socketIndex; sqInt startIndex; sqInt _return_value; socket = interpreterProxy->stackValue(3); array = interpreterProxy->stackValue(2); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isWordsOrBytes(array)); if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } interpreterProxy->success((startIndex >= 1) && ((count >= 0) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))); if (!(interpreterProxy->failed())) { /* Note: adjust bufStart for zero-origin indexing */ arrayBase = ((char *) (interpreterProxy->firstIndexableField(array))); bufStart = arrayBase + ((startIndex - 1) * byteSize); bytesSent = sqSocketSendDataBufCount(s, bufStart, count * byteSize); } _return_value = interpreterProxy->integerObjectOf((bytesSent / byteSize)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveSocketSendDone(void) { sqInt done; SocketPtr s; sqInt socket; void *socketIndex; sqInt _return_value; socket = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; done = sqSocketSendDone(s); _return_value = (done) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSocketSendUDPDataBufCount(void) { sqInt address; sqInt array; char *arrayBase; char *bufStart; sqInt byteSize; sqInt bytesSent; sqInt count; char *hostAddress; sqInt portNumber; SocketPtr s; sqInt socket; void *socketIndex; sqInt startIndex; sqInt sz; sqInt _return_value; socket = interpreterProxy->stackValue(5); array = interpreterProxy->stackValue(4); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(3))); hostAddress = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); portNumber = interpreterProxy->stackIntegerValue(2); startIndex = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l2; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l2: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isWordsOrBytes(array)); if (interpreterProxy->isWords(array)) { byteSize = 4; } else { byteSize = 1; } interpreterProxy->success((startIndex >= 1) && ((count >= 0) && (((startIndex + count) - 1) <= (interpreterProxy->slotSizeOf(array))))); if (!(interpreterProxy->failed())) { /* Note: adjust bufStart for zero-origin indexing */ arrayBase = ((char *) (interpreterProxy->firstIndexableField(array))); bufStart = arrayBase + ((startIndex - 1) * byteSize); /* begin netAddressToInt: */ sz = interpreterProxy->byteSizeOf(((sqInt)(long)((((unsigned char *) hostAddress))) - 4)); if (!(sz == 4)) { address = interpreterProxy->primitiveFail(); goto l1; } address = ((((((unsigned char *) hostAddress))[3]) + (((((unsigned char *) hostAddress))[2]) << 8)) + (((((unsigned char *) hostAddress))[1]) << 16)) + (((((unsigned char *) hostAddress))[0]) << 24); l1: /* end netAddressToInt: */; bytesSent = sqSockettoHostportSendDataBufCount(s, address, portNumber, bufStart, count * byteSize); } _return_value = interpreterProxy->integerObjectOf((bytesSent / byteSize)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(7, _return_value); return null; } EXPORT(sqInt) primitiveSocketSetOptions(void) { sqInt errorCode; sqInt optionName; sqInt optionNameSize; char *optionNameStart; sqInt optionValue; sqInt optionValueSize; char *optionValueStart; sqInt results; sqInt returnedValue; SocketPtr s; sqInt socket; void *socketIndex; socket = interpreterProxy->stackValue(2); optionName = interpreterProxy->stackValue(1); optionValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* begin socketValueOf: */ interpreterProxy->success((interpreterProxy->isBytes(socket)) && ((interpreterProxy->byteSizeOf(socket)) == (socketRecordSize()))); if (interpreterProxy->failed()) { s = null; goto l1; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socket))); s = socketIndex; l1: /* end socketValueOf: */; interpreterProxy->success(interpreterProxy->isBytes(optionName)); optionNameStart = ((char *) (interpreterProxy->firstIndexableField(optionName))); optionNameSize = interpreterProxy->slotSizeOf(optionName); interpreterProxy->success(interpreterProxy->isBytes(optionValue)); optionValueStart = ((char *) (interpreterProxy->firstIndexableField(optionValue))); optionValueSize = interpreterProxy->slotSizeOf(optionValue); if (interpreterProxy->failed()) { return null; } returnedValue = 0; errorCode = sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(s, optionNameStart, optionNameSize, optionValueStart, optionValueSize, &returnedValue); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(returnedValue)); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(errorCode)); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); results = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, results, interpreterProxy->popRemappableOop()); interpreterProxy->storePointerofObjectwithValue(1, results, interpreterProxy->popRemappableOop()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, results); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return socketShutdown(); } /* Return the size of a Smalltalk socket record in bytes. */ static sqInt socketRecordSize(void) { return sizeof(SQSocket); } /* Return a pointer to the first byte of of the socket record within the given Smalltalk object, or nil if socketOop is not a socket record. */ static SocketPtr socketValueOf(sqInt socketOop) { void *socketIndex; interpreterProxy->success((interpreterProxy->isBytes(socketOop)) && ((interpreterProxy->byteSizeOf(socketOop)) == (socketRecordSize()))); if (interpreterProxy->failed()) { return null; } socketIndex = ((SocketPtr) (interpreterProxy->firstIndexableField(socketOop))); return socketIndex; } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SocketPlugin_exports[][3] = { {"SocketPlugin", "getModuleName", (void*)getModuleName}, {"SocketPlugin", "initialiseModule", (void*)initialiseModule}, {"SocketPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"SocketPlugin", "primitiveDisableSocketAccess", (void*)primitiveDisableSocketAccess}, {"SocketPlugin", "primitiveHasSocketAccess", (void*)primitiveHasSocketAccess}, {"SocketPlugin", "primitiveInitializeNetwork", (void*)primitiveInitializeNetwork}, {"SocketPlugin", "primitiveResolverAbortLookup", (void*)primitiveResolverAbortLookup}, {"SocketPlugin", "primitiveResolverAddressLookupResult", (void*)primitiveResolverAddressLookupResult}, {"SocketPlugin", "primitiveResolverError", (void*)primitiveResolverError}, {"SocketPlugin", "primitiveResolverLocalAddress", (void*)primitiveResolverLocalAddress}, {"SocketPlugin", "primitiveResolverNameLookupResult", (void*)primitiveResolverNameLookupResult}, {"SocketPlugin", "primitiveResolverStartAddressLookup", (void*)primitiveResolverStartAddressLookup}, {"SocketPlugin", "primitiveResolverStartNameLookup", (void*)primitiveResolverStartNameLookup}, {"SocketPlugin", "primitiveResolverStatus", (void*)primitiveResolverStatus}, {"SocketPlugin", "primitiveSocketAbortConnection", (void*)primitiveSocketAbortConnection}, {"SocketPlugin", "primitiveSocketAccept", (void*)primitiveSocketAccept}, {"SocketPlugin", "primitiveSocketAccept3Semaphores", (void*)primitiveSocketAccept3Semaphores}, {"SocketPlugin", "primitiveSocketBindToPort", (void*)primitiveSocketBindToPort}, {"SocketPlugin", "primitiveSocketCloseConnection", (void*)primitiveSocketCloseConnection}, {"SocketPlugin", "primitiveSocketConnectionStatus", (void*)primitiveSocketConnectionStatus}, {"SocketPlugin", "primitiveSocketConnectToPort", (void*)primitiveSocketConnectToPort}, {"SocketPlugin", "primitiveSocketCreate", (void*)primitiveSocketCreate}, {"SocketPlugin", "primitiveSocketCreate3Semaphores", (void*)primitiveSocketCreate3Semaphores}, {"SocketPlugin", "primitiveSocketCreateRAW", (void*)primitiveSocketCreateRAW}, {"SocketPlugin", "primitiveSocketDestroy", (void*)primitiveSocketDestroy}, {"SocketPlugin", "primitiveSocketError", (void*)primitiveSocketError}, {"SocketPlugin", "primitiveSocketGetOptions", (void*)primitiveSocketGetOptions}, {"SocketPlugin", "primitiveSocketListenOnPort", (void*)primitiveSocketListenOnPort}, {"SocketPlugin", "primitiveSocketListenOnPortBacklog", (void*)primitiveSocketListenOnPortBacklog}, {"SocketPlugin", "primitiveSocketListenOnPortBacklogInterface", (void*)primitiveSocketListenOnPortBacklogInterface}, {"SocketPlugin", "primitiveSocketListenWithOrWithoutBacklog", (void*)primitiveSocketListenWithOrWithoutBacklog}, {"SocketPlugin", "primitiveSocketLocalAddress", (void*)primitiveSocketLocalAddress}, {"SocketPlugin", "primitiveSocketLocalPort", (void*)primitiveSocketLocalPort}, {"SocketPlugin", "primitiveSocketReceiveDataAvailable", (void*)primitiveSocketReceiveDataAvailable}, {"SocketPlugin", "primitiveSocketReceiveDataBufCount", (void*)primitiveSocketReceiveDataBufCount}, {"SocketPlugin", "primitiveSocketReceiveUDPDataBufCount", (void*)primitiveSocketReceiveUDPDataBufCount}, {"SocketPlugin", "primitiveSocketRemoteAddress", (void*)primitiveSocketRemoteAddress}, {"SocketPlugin", "primitiveSocketRemotePort", (void*)primitiveSocketRemotePort}, {"SocketPlugin", "primitiveSocketSendDataBufCount", (void*)primitiveSocketSendDataBufCount}, {"SocketPlugin", "primitiveSocketSendDone", (void*)primitiveSocketSendDone}, {"SocketPlugin", "primitiveSocketSendUDPDataBufCount", (void*)primitiveSocketSendUDPDataBufCount}, {"SocketPlugin", "primitiveSocketSetOptions", (void*)primitiveSocketSetOptions}, {"SocketPlugin", "setInterpreter", (void*)setInterpreter}, {"SocketPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SoundCodecPrims/SoundCodecPrims.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SoundCodecPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SoundCodecPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "SoundCodecPrims.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveGSMDecode(void); EXPORT(sqInt) primitiveGSMEncode(void); EXPORT(sqInt) primitiveGSMNewState(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SoundCodecPrims VMMaker-oscog.dtl.57 (i)" #else "SoundCodecPrims VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveGSMDecode(void) { sqInt dst; sqInt dstDelta; sqInt dstIndex; sqInt dstSize; sqInt frameCount; sqInt result; sqInt src; sqInt srcDelta; sqInt srcIndex; sqInt srcSize; sqInt state; dstIndex = interpreterProxy->stackIntegerValue(0); dst = interpreterProxy->stackObjectValue(1); srcIndex = interpreterProxy->stackIntegerValue(2); src = interpreterProxy->stackObjectValue(3); frameCount = interpreterProxy->stackIntegerValue(4); state = interpreterProxy->stackObjectValue(5); interpreterProxy->success(interpreterProxy->isWords(dst)); interpreterProxy->success(interpreterProxy->isBytes(src)); interpreterProxy->success(interpreterProxy->isBytes(state)); if (interpreterProxy->failed()) { return null; } srcSize = interpreterProxy->slotSizeOf(src); dstSize = (interpreterProxy->slotSizeOf(dst)) * 2; gsmDecode(state + 4, frameCount, src, srcIndex, srcSize, dst, dstIndex, dstSize, &srcDelta, &dstDelta); if (interpreterProxy->failed()) { return null; } result = interpreterProxy->makePointwithxValueyValue(srcDelta, dstDelta); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(result); } EXPORT(sqInt) primitiveGSMEncode(void) { sqInt dst; sqInt dstDelta; sqInt dstIndex; sqInt dstSize; sqInt frameCount; sqInt result; sqInt src; sqInt srcDelta; sqInt srcIndex; sqInt srcSize; sqInt state; dstIndex = interpreterProxy->stackIntegerValue(0); dst = interpreterProxy->stackObjectValue(1); srcIndex = interpreterProxy->stackIntegerValue(2); src = interpreterProxy->stackObjectValue(3); frameCount = interpreterProxy->stackIntegerValue(4); state = interpreterProxy->stackObjectValue(5); interpreterProxy->success(interpreterProxy->isBytes(dst)); interpreterProxy->success(interpreterProxy->isWords(src)); interpreterProxy->success(interpreterProxy->isBytes(state)); if (interpreterProxy->failed()) { return null; } srcSize = (interpreterProxy->slotSizeOf(src)) * 2; dstSize = interpreterProxy->slotSizeOf(dst); gsmEncode(state + 4, frameCount, src, srcIndex, srcSize, dst, dstIndex, dstSize, &srcDelta, &dstDelta); if (interpreterProxy->failed()) { return null; } result = interpreterProxy->makePointwithxValueyValue(srcDelta, dstDelta); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(result); } EXPORT(sqInt) primitiveGSMNewState(void) { sqInt state; sqInt stateBytes; stateBytes = gsmStateBytes(); state = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), stateBytes); gsmInitState(state + 4); interpreterProxy->pop(1); interpreterProxy->push(state); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SoundCodecPrims_exports[][3] = { {"SoundCodecPrims", "getModuleName", (void*)getModuleName}, {"SoundCodecPrims", "primitiveGSMDecode", (void*)primitiveGSMDecode}, {"SoundCodecPrims", "primitiveGSMEncode", (void*)primitiveGSMEncode}, {"SoundCodecPrims", "primitiveGSMNewState", (void*)primitiveGSMNewState}, {"SoundCodecPrims", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SoundGenerationPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SoundGenerationPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Proxy Functions ***/ #define stackValue(i) (interpreterProxy->stackValue(i)) #define stackIntegerValue(i) (interpreterProxy->stackIntegerValue(i)) #define successFlag (!interpreterProxy->failed()) #define success(bool) (interpreterProxy->success(bool)) #define arrayValueOf(oop) (interpreterProxy->arrayValueOf(oop)) #define checkedIntegerValueOf(oop) (interpreterProxy->checkedIntegerValueOf(oop)) #define fetchArrayofObject(idx,oop) (interpreterProxy->fetchArrayofObject(idx,oop)) #define fetchFloatofObject(idx,oop) (interpreterProxy->fetchFloatofObject(idx,oop)) #define fetchIntegerofObject(idx,oop) (interpreterProxy->fetchIntegerofObject(idx,oop)) #define floatValueOf(oop) (interpreterProxy->floatValueOf(oop)) #define pop(n) (interpreterProxy->pop(n)) #define pushInteger(n) (interpreterProxy->pushInteger(n)) #define sizeOfSTArrayFromCPrimitive(cPtr) (interpreterProxy->sizeOfSTArrayFromCPrimitive(cPtr)) #define storeIntegerofObjectwithValue(idx,oop,value) (interpreterProxy->storeIntegerofObjectwithValue(idx,oop,value)) #define primitiveFail() interpreterProxy->primitiveFail() /* allows accessing Strings in both C and Smalltalk */ #define asciiValue(c) c /*** Constants ***/ #define IncrementFractionBits 16 #define LoopIndexFractionMask 0x1FF #define LoopIndexScaleFactor 0x200 #define ScaledIndexOverflow 0x20000000 #define ScaleFactor 0x8000 /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SoundGenerationPlugin VMMaker-oscog.dtl.57 (i)" #else "SoundGenerationPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveApplyReverb(void); EXPORT(sqInt) primitiveMixFMSound(void); EXPORT(sqInt) primitiveMixLoopedSampledSound(void); EXPORT(sqInt) primitiveMixPluckedSound(void); EXPORT(sqInt) primitiveMixSampledSound(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveApplyReverb(void) { short int *aSoundBuffer; sqInt bufferIndex; sqInt bufferSize; sqInt delayedLeft; sqInt delayedRight; sqInt i; sqInt j; short int *leftBuffer; sqInt n; sqInt out; sqInt rcvr; short int *rightBuffer; sqInt sliceIndex; sqInt startIndex; sqInt tapCount; int *tapDelays; sqInt tapGain; int *tapGains; sqInt tapIndex; rcvr = stackValue(3); aSoundBuffer = arrayValueOf(stackValue(2)); aSoundBuffer -= 1; startIndex = stackIntegerValue(1); n = stackIntegerValue(0); tapDelays = fetchArrayofObject(7, rcvr); tapDelays -= 1; tapGains = fetchArrayofObject(8, rcvr); tapGains -= 1; tapCount = fetchIntegerofObject(9, rcvr); bufferSize = fetchIntegerofObject(10, rcvr); bufferIndex = fetchIntegerofObject(11, rcvr); leftBuffer = fetchArrayofObject(12, rcvr); leftBuffer -= 1; rightBuffer = fetchArrayofObject(13, rcvr); rightBuffer -= 1; if (!(successFlag)) { return null; } for (sliceIndex = startIndex; sliceIndex <= ((startIndex + n) - 1); sliceIndex += 1) { delayedLeft = delayedRight = 0; for (tapIndex = 1; tapIndex <= tapCount; tapIndex += 1) { i = bufferIndex - (tapDelays[tapIndex]); if (i < 1) { i += bufferSize; } tapGain = tapGains[tapIndex]; delayedLeft += tapGain * (leftBuffer[i]); delayedRight += tapGain * (rightBuffer[i]); } j = (2 * sliceIndex) - 1; out = (aSoundBuffer[j]) + (((sqInt) delayedLeft >> 15)); if (out > 32767) { out = 32767; } if (out < -32767) { out = -32767; } aSoundBuffer[j] = out; leftBuffer[bufferIndex] = out; j += 1; out = (aSoundBuffer[j]) + (((sqInt) delayedRight >> 15)); if (out > 32767) { out = 32767; } if (out < -32767) { out = -32767; } aSoundBuffer[j] = out; rightBuffer[bufferIndex] = out; bufferIndex = (bufferIndex % bufferSize) + 1; } if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(11, rcvr, bufferIndex); pop(3); } /* Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy. */ /* (FMSound pitch: 440.0 dur: 1.0 loudness: 0.5) play */ EXPORT(sqInt) primitiveMixFMSound(void) { short int *aSoundBuffer; sqInt count; sqInt doingFM; sqInt i; sqInt lastIndex; sqInt leftVol; sqInt n; sqInt normalizedModulation; sqInt offset; sqInt rcvr; sqInt rightVol; sqInt s; sqInt sample; sqInt scaledIndex; sqInt scaledIndexIncr; sqInt scaledOffsetIndex; sqInt scaledOffsetIndexIncr; sqInt scaledVol; sqInt scaledVolIncr; sqInt scaledVolLimit; sqInt scaledWaveTableSize; sqInt sliceIndex; sqInt startIndex; short int *waveTable; rcvr = stackValue(5); n = stackIntegerValue(4); aSoundBuffer = arrayValueOf(stackValue(3)); aSoundBuffer -= 1; startIndex = stackIntegerValue(2); leftVol = stackIntegerValue(1); rightVol = stackIntegerValue(0); scaledVol = fetchIntegerofObject(3, rcvr); scaledVolIncr = fetchIntegerofObject(4, rcvr); scaledVolLimit = fetchIntegerofObject(5, rcvr); count = fetchIntegerofObject(7, rcvr); waveTable = fetchArrayofObject(8, rcvr); waveTable -= 1; scaledWaveTableSize = fetchIntegerofObject(9, rcvr); scaledIndex = fetchIntegerofObject(10, rcvr); scaledIndexIncr = fetchIntegerofObject(11, rcvr); normalizedModulation = fetchIntegerofObject(14, rcvr); scaledOffsetIndex = fetchIntegerofObject(15, rcvr); scaledOffsetIndexIncr = fetchIntegerofObject(16, rcvr); if (!(successFlag)) { return null; } doingFM = (normalizedModulation != 0) && (scaledOffsetIndexIncr != 0); lastIndex = (startIndex + n) - 1; for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) { sample = ((sqInt) (scaledVol * (waveTable[(((sqInt) scaledIndex >> 15)) + 1])) >> 15); if (doingFM) { offset = normalizedModulation * (waveTable[(((sqInt) scaledOffsetIndex >> 15)) + 1]); scaledOffsetIndex = (scaledOffsetIndex + scaledOffsetIndexIncr) % scaledWaveTableSize; if (scaledOffsetIndex < 0) { scaledOffsetIndex += scaledWaveTableSize; } scaledIndex = ((scaledIndex + scaledIndexIncr) + offset) % scaledWaveTableSize; if (scaledIndex < 0) { scaledIndex += scaledWaveTableSize; } } else { scaledIndex = (scaledIndex + scaledIndexIncr) % scaledWaveTableSize; } if (leftVol > 0) { i = (2 * sliceIndex) - 1; s = (aSoundBuffer[i]) + (((sqInt) (sample * leftVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (rightVol > 0) { i = 2 * sliceIndex; s = (aSoundBuffer[i]) + (((sqInt) (sample * rightVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (scaledVolIncr != 0) { scaledVol += scaledVolIncr; if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) { /* reached the limit; stop incrementing */ scaledVol = scaledVolLimit; scaledVolIncr = 0; } } } count -= n; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(10, rcvr, scaledIndex); storeIntegerofObjectwithValue(15, rcvr, scaledOffsetIndex); pop(5); } /* Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy. If a loop length is specified, then the index is looped back when the loopEnd index is reached until count drops below releaseCount. This allows a short sampled sound to be sustained indefinitely. */ /* (LoopedSampledSound pitch: 440.0 dur: 5.0 loudness: 0.5) play */ EXPORT(sqInt) primitiveMixLoopedSampledSound(void) { short int *aSoundBuffer; sqInt compositeLeftVol; sqInt compositeRightVol; sqInt count; sqInt i; sqInt isInStereo; sqInt lastIndex; sqInt lastSample; short int *leftSamples; sqInt leftVal; sqInt leftVol; sqInt loopEnd; sqInt m; sqInt n; sqInt nextSampleIndex; sqInt rcvr; sqInt releaseCount; short int *rightSamples; sqInt rightVal; sqInt rightVol; sqInt s; sqInt sampleIndex; sqInt scaledIndex; sqInt scaledIndexIncr; sqInt scaledLoopLength; sqInt scaledVol; sqInt scaledVolIncr; sqInt scaledVolLimit; sqInt sliceIndex; sqInt startIndex; rcvr = stackValue(5); n = stackIntegerValue(4); aSoundBuffer = arrayValueOf(stackValue(3)); aSoundBuffer -= 1; startIndex = stackIntegerValue(2); leftVol = stackIntegerValue(1); rightVol = stackIntegerValue(0); scaledVol = fetchIntegerofObject(3, rcvr); scaledVolIncr = fetchIntegerofObject(4, rcvr); scaledVolLimit = fetchIntegerofObject(5, rcvr); count = fetchIntegerofObject(7, rcvr); releaseCount = fetchIntegerofObject(8, rcvr); leftSamples = fetchArrayofObject(10, rcvr); leftSamples -= 1; rightSamples = fetchArrayofObject(11, rcvr); rightSamples -= 1; lastSample = fetchIntegerofObject(16, rcvr); loopEnd = fetchIntegerofObject(17, rcvr); scaledLoopLength = fetchIntegerofObject(18, rcvr); scaledIndex = fetchIntegerofObject(19, rcvr); scaledIndexIncr = fetchIntegerofObject(20, rcvr); if (!(successFlag)) { return null; } isInStereo = leftSamples != rightSamples; compositeLeftVol = ((sqInt) (leftVol * scaledVol) >> 15); compositeRightVol = ((sqInt) (rightVol * scaledVol) >> 15); i = (2 * startIndex) - 1; lastIndex = (startIndex + n) - 1; for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) { sampleIndex = ((sqInt) ((scaledIndex += scaledIndexIncr)) >> 9); if ((sampleIndex > loopEnd) && (count > releaseCount)) { /* loop back if not within releaseCount of the note end */ /* note: unlooped sounds will have loopEnd = lastSample */ sampleIndex = ((sqInt) ((scaledIndex -= scaledLoopLength)) >> 9); } if (((nextSampleIndex = sampleIndex + 1)) > lastSample) { if (sampleIndex > lastSample) { count = 0; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(19, rcvr, scaledIndex); pop(6); pushInteger(null); return null; } if (scaledLoopLength == 0) { nextSampleIndex = sampleIndex; } else { nextSampleIndex = (((sqInt) (scaledIndex - scaledLoopLength) >> 9)) + 1; } } m = scaledIndex & LoopIndexFractionMask; rightVal = leftVal = ((sqInt) (((leftSamples[sampleIndex]) * (LoopIndexScaleFactor - m)) + ((leftSamples[nextSampleIndex]) * m)) >> 9); if (isInStereo) { rightVal = ((sqInt) (((rightSamples[sampleIndex]) * (LoopIndexScaleFactor - m)) + ((rightSamples[nextSampleIndex]) * m)) >> 9); } if (leftVol > 0) { s = (aSoundBuffer[i]) + (((sqInt) (compositeLeftVol * leftVal) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } i += 1; if (rightVol > 0) { s = (aSoundBuffer[i]) + (((sqInt) (compositeRightVol * rightVal) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } i += 1; if (scaledVolIncr != 0) { /* update volume envelope if it is changing */ scaledVol += scaledVolIncr; if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) { /* reached the limit; stop incrementing */ scaledVol = scaledVolLimit; scaledVolIncr = 0; } compositeLeftVol = ((sqInt) (leftVol * scaledVol) >> 15); compositeRightVol = ((sqInt) (rightVol * scaledVol) >> 15); } } count -= n; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(19, rcvr, scaledIndex); pop(5); } /* 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. */ /* (PluckedSound pitch: 220.0 dur: 6.0 loudness: 0.8) play */ EXPORT(sqInt) primitiveMixPluckedSound(void) { short int *aSoundBuffer; sqInt average; sqInt count; sqInt i; sqInt lastIndex; sqInt leftVol; sqInt n; sqInt rcvr; sqInt rightVol; short int *ring; sqInt s; sqInt sample; sqInt scaledIndex; sqInt scaledIndexIncr; sqInt scaledIndexLimit; sqInt scaledNextIndex; sqInt scaledThisIndex; sqInt scaledVol; sqInt scaledVolIncr; sqInt scaledVolLimit; sqInt sliceIndex; sqInt startIndex; rcvr = stackValue(5); n = stackIntegerValue(4); aSoundBuffer = arrayValueOf(stackValue(3)); aSoundBuffer -= 1; startIndex = stackIntegerValue(2); leftVol = stackIntegerValue(1); rightVol = stackIntegerValue(0); scaledVol = fetchIntegerofObject(3, rcvr); scaledVolIncr = fetchIntegerofObject(4, rcvr); scaledVolLimit = fetchIntegerofObject(5, rcvr); count = fetchIntegerofObject(7, rcvr); ring = fetchArrayofObject(8, rcvr); ring -= 1; scaledIndex = fetchIntegerofObject(9, rcvr); scaledIndexIncr = fetchIntegerofObject(10, rcvr); scaledIndexLimit = fetchIntegerofObject(11, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; scaledThisIndex = scaledNextIndex = scaledIndex; for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) { scaledNextIndex = scaledThisIndex + scaledIndexIncr; if (scaledNextIndex >= scaledIndexLimit) { scaledNextIndex = ScaleFactor + (scaledNextIndex - scaledIndexLimit); } average = ((sqInt) ((ring[((sqInt) scaledThisIndex >> 15)]) + (ring[((sqInt) scaledNextIndex >> 15)])) >> 1); ring[((sqInt) scaledThisIndex >> 15)] = average; /* scale by volume */ sample = ((sqInt) (average * scaledVol) >> 15); scaledThisIndex = scaledNextIndex; if (leftVol > 0) { i = (2 * sliceIndex) - 1; s = (aSoundBuffer[i]) + (((sqInt) (sample * leftVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (rightVol > 0) { i = 2 * sliceIndex; s = (aSoundBuffer[i]) + (((sqInt) (sample * rightVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (scaledVolIncr != 0) { scaledVol += scaledVolIncr; if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) { /* reached the limit; stop incrementing */ scaledVol = scaledVolLimit; scaledVolIncr = 0; } } } scaledIndex = scaledNextIndex; count -= n; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(9, rcvr, scaledIndex); pop(5); } /* 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. */ EXPORT(sqInt) primitiveMixSampledSound(void) { short int *aSoundBuffer; sqInt count; sqInt i; sqInt indexHighBits; sqInt lastIndex; sqInt leftVol; sqInt n; sqInt outIndex; sqInt overflow; sqInt rcvr; sqInt rightVol; sqInt s; sqInt sample; sqInt sampleIndex; short int *samples; sqInt samplesSize; sqInt scaledIncrement; sqInt scaledIndex; sqInt scaledVol; sqInt scaledVolIncr; sqInt scaledVolLimit; sqInt startIndex; rcvr = stackValue(5); n = stackIntegerValue(4); aSoundBuffer = arrayValueOf(stackValue(3)); aSoundBuffer -= 1; startIndex = stackIntegerValue(2); leftVol = stackIntegerValue(1); rightVol = stackIntegerValue(0); scaledVol = fetchIntegerofObject(3, rcvr); scaledVolIncr = fetchIntegerofObject(4, rcvr); scaledVolLimit = fetchIntegerofObject(5, rcvr); count = fetchIntegerofObject(7, rcvr); samples = fetchArrayofObject(8, rcvr); samples -= 1; samplesSize = fetchIntegerofObject(10, rcvr); scaledIndex = fetchIntegerofObject(11, rcvr); indexHighBits = fetchIntegerofObject(12, rcvr); scaledIncrement = fetchIntegerofObject(13, rcvr); if (!(successFlag)) { return null; } lastIndex = (startIndex + n) - 1; /* index of next stereo output sample pair */ outIndex = startIndex; sampleIndex = indexHighBits + (((usqInt) scaledIndex) >> IncrementFractionBits); while ((sampleIndex <= samplesSize) && (outIndex <= lastIndex)) { sample = ((sqInt) ((samples[sampleIndex]) * scaledVol) >> 15); if (leftVol > 0) { i = (2 * outIndex) - 1; s = (aSoundBuffer[i]) + (((sqInt) (sample * leftVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (rightVol > 0) { i = 2 * outIndex; s = (aSoundBuffer[i]) + (((sqInt) (sample * rightVol) >> 15)); if (s > 32767) { s = 32767; } if (s < -32767) { s = -32767; } aSoundBuffer[i] = s; } if (scaledVolIncr != 0) { scaledVol += scaledVolIncr; if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) { /* reached the limit; stop incrementing */ scaledVol = scaledVolLimit; scaledVolIncr = 0; } } scaledIndex += scaledIncrement; if (scaledIndex >= ScaledIndexOverflow) { overflow = ((usqInt) scaledIndex) >> IncrementFractionBits; indexHighBits += overflow; scaledIndex -= overflow << IncrementFractionBits; } sampleIndex = indexHighBits + (((usqInt) scaledIndex) >> IncrementFractionBits); outIndex += 1; } count -= n; if (!(successFlag)) { return null; } storeIntegerofObjectwithValue(3, rcvr, scaledVol); storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr); storeIntegerofObjectwithValue(7, rcvr, count); storeIntegerofObjectwithValue(11, rcvr, scaledIndex); storeIntegerofObjectwithValue(12, rcvr, indexHighBits); pop(5); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SoundGenerationPlugin_exports[][3] = { {"SoundGenerationPlugin", "getModuleName", (void*)getModuleName}, {"SoundGenerationPlugin", "primitiveApplyReverb", (void*)primitiveApplyReverb}, {"SoundGenerationPlugin", "primitiveMixFMSound", (void*)primitiveMixFMSound}, {"SoundGenerationPlugin", "primitiveMixLoopedSampledSound", (void*)primitiveMixLoopedSampledSound}, {"SoundGenerationPlugin", "primitiveMixPluckedSound", (void*)primitiveMixPluckedSound}, {"SoundGenerationPlugin", "primitiveMixSampledSound", (void*)primitiveMixSampledSound}, {"SoundGenerationPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SoundPlugin/SoundPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from SoundPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "SoundPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "SoundPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveSoundAvailableSpace(void); EXPORT(sqInt) primitiveSoundGetRecordingSampleRate(void); EXPORT(sqInt) primitiveSoundGetVolume(void); EXPORT(sqInt) primitiveSoundInsertSamples(void); EXPORT(sqInt) primitiveSoundPlaySamples(void); EXPORT(sqInt) primitiveSoundPlaySilence(void); EXPORT(sqInt) primitiveSoundRecordSamples(void); EXPORT(sqInt) primitiveSoundSetLeftVolume(void); EXPORT(sqInt) primitiveSoundSetRecordLevel(void); EXPORT(sqInt) primitiveSoundStart(void); EXPORT(sqInt) primitiveSoundStartRecording(void); EXPORT(sqInt) primitiveSoundStartWithSemaphore(void); EXPORT(sqInt) primitiveSoundStop(void); EXPORT(sqInt) primitiveSoundStopRecording(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SoundPlugin VMMaker-oscog.dtl.57 (i)" #else "SoundPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return soundInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Returns the number of bytes of available sound output buffer space. This should be (frames*4) if the device is in stereo mode, or (frames*2) otherwise */ EXPORT(sqInt) primitiveSoundAvailableSpace(void) { sqInt frames; sqInt _return_value; /* -1 if sound output not started */ frames = snd_AvailableSpace(); interpreterProxy->success(frames >= 0); _return_value = interpreterProxy->positive32BitIntegerFor(frames); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Return a float representing the actual sampling rate during recording. Fail if not currently recording. */ EXPORT(sqInt) primitiveSoundGetRecordingSampleRate(void) { double rate; sqInt _return_value; /* fail if not recording */ rate = snd_GetRecordingSampleRate(); _return_value = interpreterProxy->floatObjectOf(rate); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Set the sound input recording level. */ EXPORT(sqInt) primitiveSoundGetVolume(void) { double left; sqInt results; double right; left = 0; right = 0; snd_Volume((double *) &left,(double *) &right); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(right)); interpreterProxy->pushRemappableOop(interpreterProxy->floatObjectOf(left)); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); results = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, results, interpreterProxy->popRemappableOop()); interpreterProxy->storePointerofObjectwithValue(1, results, interpreterProxy->popRemappableOop()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, results); return null; } /* Insert a buffer's worth of sound samples into the currently playing buffer. Used to make a sound start playing as quickly as possible. The new sound is mixed with the previously buffered sampled. */ /* Details: Unlike primitiveSoundPlaySamples, this primitive always starts with the first sample the given sample buffer. Its third argument specifies the number of samples past the estimated sound output buffer position the inserted sound should start. If successful, it returns the number of samples inserted. */ EXPORT(sqInt) primitiveSoundInsertSamples(void) { usqInt *buf; sqInt frameCount; sqInt framesPlayed; sqInt leadTime; sqInt _return_value; frameCount = interpreterProxy->stackIntegerValue(2); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(1))); buf = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); leadTime = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(frameCount <= (interpreterProxy->slotSizeOf(((sqInt)(long)(buf) - 4)))); if (!(interpreterProxy->failed())) { framesPlayed = snd_InsertSamplesFromLeadTime(frameCount, (void *)buf, leadTime); interpreterProxy->success(framesPlayed >= 0); } _return_value = interpreterProxy->positive32BitIntegerFor(framesPlayed); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* Output a buffer's worth of sound samples. */ EXPORT(sqInt) primitiveSoundPlaySamples(void) { usqInt *buf; sqInt frameCount; sqInt framesPlayed; sqInt startIndex; sqInt _return_value; frameCount = interpreterProxy->stackIntegerValue(2); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(1))); buf = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); startIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success((startIndex >= 1) && (((startIndex + frameCount) - 1) <= (interpreterProxy->slotSizeOf(((sqInt)(long)(buf) - 4))))); if (!(interpreterProxy->failed())) { framesPlayed = snd_PlaySamplesFromAtLength(frameCount, (void *)buf, startIndex - 1); interpreterProxy->success(framesPlayed >= 0); } _return_value = interpreterProxy->positive32BitIntegerFor(framesPlayed); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* Output a buffer's worth of silence. Returns the number of sample frames played. */ EXPORT(sqInt) primitiveSoundPlaySilence(void) { sqInt framesPlayed; sqInt _return_value; /* -1 if sound output not started */ framesPlayed = snd_PlaySilence(); interpreterProxy->success(framesPlayed >= 0); _return_value = interpreterProxy->positive32BitIntegerFor(framesPlayed); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Record a buffer's worth of 16-bit sound samples. */ EXPORT(sqInt) primitiveSoundRecordSamples(void) { usqInt *buf; sqInt bufLen; char*bufPtr; sqInt bufSizeInBytes; sqInt byteOffset; sqInt samplesRecorded; sqInt startWordIndex; sqInt _return_value; interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(1))); buf = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); startWordIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->failed())) { bufSizeInBytes = (interpreterProxy->slotSizeOf(((sqInt)(long)(buf) - 4))) * 4; interpreterProxy->success((startWordIndex >= 1) && (((startWordIndex - 1) * 2) < bufSizeInBytes)); } if (!(interpreterProxy->failed())) { byteOffset = (startWordIndex - 1) * 2; bufPtr = (((char*) buf)) + byteOffset; bufLen = bufSizeInBytes - byteOffset; samplesRecorded = snd_RecordSamplesIntoAtLength(bufPtr, 0, bufLen); } _return_value = interpreterProxy->positive32BitIntegerFor(samplesRecorded); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Set the sound input recording level. */ EXPORT(sqInt) primitiveSoundSetLeftVolume(void) { double aLeftVolume; double aRightVolume; aLeftVolume = interpreterProxy->stackFloatValue(1); aRightVolume = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->failed())) { snd_SetVolume(aLeftVolume,aRightVolume); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Set the sound input recording level. */ EXPORT(sqInt) primitiveSoundSetRecordLevel(void) { sqInt level; level = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->failed())) { snd_SetRecordLevel(level); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Start the double-buffered sound output with the given buffer size, sample rate, and stereo flag. */ EXPORT(sqInt) primitiveSoundStart(void) { sqInt bufFrames; sqInt samplesPerSec; sqInt stereoFlag; bufFrames = interpreterProxy->stackIntegerValue(2); samplesPerSec = interpreterProxy->stackIntegerValue(1); stereoFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(snd_Start(bufFrames, samplesPerSec, stereoFlag, 0)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* Start recording sound with the given parameters. */ EXPORT(sqInt) primitiveSoundStartRecording(void) { sqInt desiredSamplesPerSec; sqInt semaIndex; sqInt stereoFlag; desiredSamplesPerSec = interpreterProxy->stackIntegerValue(2); stereoFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); semaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } snd_StartRecording(desiredSamplesPerSec, stereoFlag, semaIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* Start the double-buffered sound output with the given buffer size, sample rate, stereo flag, and semaphore index. */ EXPORT(sqInt) primitiveSoundStartWithSemaphore(void) { sqInt bufFrames; sqInt samplesPerSec; sqInt semaIndex; sqInt stereoFlag; bufFrames = interpreterProxy->stackIntegerValue(3); samplesPerSec = interpreterProxy->stackIntegerValue(2); stereoFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); semaIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(snd_Start(bufFrames, samplesPerSec, stereoFlag, semaIndex)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } /* Stop double-buffered sound output. */ EXPORT(sqInt) primitiveSoundStop(void) { snd_Stop(); if (interpreterProxy->failed()) { return null; } return null; } /* Stop recording sound. */ EXPORT(sqInt) primitiveSoundStopRecording(void) { snd_StopRecording(); if (interpreterProxy->failed()) { return null; } return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return soundShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SoundPlugin_exports[][3] = { {"SoundPlugin", "getModuleName", (void*)getModuleName}, {"SoundPlugin", "initialiseModule", (void*)initialiseModule}, {"SoundPlugin", "primitiveSoundAvailableSpace", (void*)primitiveSoundAvailableSpace}, {"SoundPlugin", "primitiveSoundGetRecordingSampleRate", (void*)primitiveSoundGetRecordingSampleRate}, {"SoundPlugin", "primitiveSoundGetVolume", (void*)primitiveSoundGetVolume}, {"SoundPlugin", "primitiveSoundInsertSamples", (void*)primitiveSoundInsertSamples}, {"SoundPlugin", "primitiveSoundPlaySamples", (void*)primitiveSoundPlaySamples}, {"SoundPlugin", "primitiveSoundPlaySilence", (void*)primitiveSoundPlaySilence}, {"SoundPlugin", "primitiveSoundRecordSamples", (void*)primitiveSoundRecordSamples}, {"SoundPlugin", "primitiveSoundSetLeftVolume", (void*)primitiveSoundSetLeftVolume}, {"SoundPlugin", "primitiveSoundSetRecordLevel", (void*)primitiveSoundSetRecordLevel}, {"SoundPlugin", "primitiveSoundStart", (void*)primitiveSoundStart}, {"SoundPlugin", "primitiveSoundStartRecording", (void*)primitiveSoundStartRecording}, {"SoundPlugin", "primitiveSoundStartWithSemaphore", (void*)primitiveSoundStartWithSemaphore}, {"SoundPlugin", "primitiveSoundStop", (void*)primitiveSoundStop}, {"SoundPlugin", "primitiveSoundStopRecording", (void*)primitiveSoundStopRecording}, {"SoundPlugin", "setInterpreter", (void*)setInterpreter}, {"SoundPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/Squeak3D/Squeak3D.c ================================================ /* Automatically generated from Squeak on 15 June 2010 5:06:07 pm by VMMaker 4.2.4 */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "b3d.h" #include "b3d.h" #include "sqMemoryAccess.h" /*** Constants ***/ #define AmbientPart 0 #define DiffusePart 4 #define EmissionAlpha 15 #define EmissionBlue 14 #define EmissionGreen 13 #define EmissionRed 12 #define FlagAmbientPart 256 #define FlagAttenuated 4 #define FlagDiffusePart 512 #define FlagDirectional 2 #define FlagHasSpot 8 #define FlagM44Identity 1 #define FlagM44NoPerspective 2 #define FlagM44NoTranslation 4 #define FlagPositional 1 #define FlagSpecularPart 1024 #define InAllMask 1365 #define InBackBit 1024 #define InBottomBit 64 #define InFrontBit 256 #define InLeftBit 1 #define InRightBit 4 #define InTopBit 16 #define MaterialShininess 16 #define MaterialSize 17 #define OutAllMask 2730 #define OutBackBit 2048 #define OutBottomBit 128 #define OutFrontBit 512 #define OutLeftBit 2 #define OutRightBit 8 #define OutTopBit 32 #define PrimLightAttenuationConstant 18 #define PrimLightAttenuationLinear 19 #define PrimLightAttenuationSquared 20 #define PrimLightDirection 15 #define PrimLightDirectionX 15 #define PrimLightDirectionY 16 #define PrimLightDirectionZ 17 #define PrimLightFlags 21 #define PrimLightPositionX 12 #define PrimLightPositionY 13 #define PrimLightPositionZ 14 #define PrimLightSize 32 #define PrimTypeMax 6 #define PrimVertexSize 16 #define PrimVtxClipFlags 13 #define PrimVtxColor32 12 #define PrimVtxNormal 3 #define PrimVtxNormalX 3 #define PrimVtxNormalY 4 #define PrimVtxNormalZ 5 #define PrimVtxPosition 0 #define PrimVtxPositionX 0 #define PrimVtxPositionY 1 #define PrimVtxPositionZ 2 #define PrimVtxRasterPosW 11 #define PrimVtxRasterPosX 8 #define PrimVtxRasterPosY 9 #define PrimVtxRasterPosZ 10 #define PrimVtxTexCoordU 6 #define PrimVtxTexCoordV 7 #define PrimVtxTexCoords 6 #define SpecularPart 8 #define SpotLightDeltaCos 24 #define SpotLightExponent 25 #define SpotLightMinCos 22 #define VBTrackAmbient 1 #define VBTrackDiffuse 2 #define VBTrackEmission 8 #define VBTrackSpecular 4 #define VBTwoSidedLighting 64 #define VBUseLocalViewer 128 #define VBVtxHasNormals 16 /*** Function Prototypes ***/ static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale); static sqInt analyzeMatrix3x3Length(float *m); static sqInt analyzeMatrix(float *m); #pragma export on EXPORT(sqInt) b3dClipPolygon(void); EXPORT(sqInt) b3dComputeMinIndexZ(void); EXPORT(sqInt) b3dComputeMinZ(void); EXPORT(sqInt) b3dDetermineClipFlags(void); EXPORT(sqInt) b3dInitPrimitiveObject(void); EXPORT(sqInt) b3dInitializeRasterizerState(void); EXPORT(sqInt) b3dInplaceHouseHolderInvert(void); EXPORT(sqInt) b3dLoadIndexArray(void); EXPORT(sqInt) b3dLoadVertexBuffer(void); EXPORT(sqInt) b3dMapVertexBuffer(void); EXPORT(sqInt) b3dOrthoNormInverseMatrix(void); EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void); EXPORT(sqInt) b3dPrimitiveObjectSize(void); EXPORT(sqInt) b3dPrimitiveTextureSize(void); EXPORT(sqInt) b3dRasterizerVersion(void); EXPORT(sqInt) b3dShadeVertexBuffer(void); EXPORT(sqInt) b3dShaderVersion(void); EXPORT(sqInt) b3dStartRasterizer(void); EXPORT(sqInt) b3dTransformDirection(void); EXPORT(sqInt) b3dTransformMatrixWithInto(void); EXPORT(sqInt) b3dTransformPoint(void); EXPORT(sqInt) b3dTransformPrimitiveNormal(void); EXPORT(sqInt) b3dTransformPrimitivePosition(void); EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void); EXPORT(sqInt) b3dTransformVertexBuffer(void); EXPORT(sqInt) b3dTransformerVersion(void); EXPORT(sqInt) b3dTransposeMatrix(void); #pragma export off static double backClipValueFromto(sqInt last, sqInt next); static double bottomClipValueFromto(sqInt last, sqInt next); static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask); static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n); static sqInt computeAttenuation(void); static sqInt computeDirection(void); static sqInt computeSpecularDirection(void); static double computeSpotFactor(void); static sqInt determineClipFlagscount(void *vtxArray, sqInt count); static double dotProductOfFloatwithDouble(float * v1, double *v2); static void* fetchLightSourceofObject(sqInt index, sqInt anArray); static double frontClipValueFromto(sqInt last, sqInt next); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out); static double inverseLengthOfDouble(double * aVector); static double inverseLengthOfFloat(float * aVector); static double leftClipValueFromto(sqInt last, sqInt next); static sqInt loadObjectsFrom(sqInt stackIndex); static sqInt loadPrimitiveLightSource(void); static sqInt loadPrimitiveVertex(void); static sqInt loadRasterizerState(sqInt stackIndex); static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr); static sqInt loadTexturesFrom(sqInt stackIndex); static sqInt loadViewportFrom(sqInt stackIndex); static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray); #pragma export on EXPORT(sqInt) moduleUnloaded(char * aModuleName); #pragma export off static sqInt msg(char * s); #pragma export on EXPORT(sqInt) primitiveSetBitBltPlugin(void); #pragma export off static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize); static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize); static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize); static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize); static double rightClipValueFromto(sqInt last, sqInt next); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static sqInt shadeVertex(void); static sqInt stackLightArrayValue(sqInt stackIndex); static void * stackMaterialValue(sqInt stackIndex); static void* stackMatrix(sqInt index); static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex); static void* stackPrimitiveVertex(sqInt index); static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems); static sqInt storeObjectsInto(sqInt stackIndex); static sqInt storePrimitiveVertex(void); static double topClipValueFromto(sqInt last, sqInt next); static sqInt transformMatrixwithinto(float *src, float *arg, float *dst); static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale); static sqInt transformPrimitivePositionby(float *pVertex, float *matrix); static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix); static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix); static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix); static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags); static void* vbLoadArraysize(sqInt oop, sqInt count); /*** Variables ***/ static char bbPluginName[256] = "BitBltPlugin"; static sqInt copyBitsFn; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static double l2vDirection[3]; static double l2vDistance; static double l2vSpecDir[3]; static sqInt lightFlags; static double lightScale; static float* litVertex; static sqInt loadBBFn; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Squeak3D 15 June 2010 (i)" #else "Squeak3D 15 June 2010 (e)" #endif ; static float* primLight; static float* primMaterial; static B3DRasterizerState state; static sqInt vbFlags; static B3DPrimitiveViewport viewport; static double vtxInColor[4]; static double vtxOutColor[4]; /* Add the given light part to the output color, scaled by the given scale factor. If the given flag is set in vbFlags then load the part from the primitive vertex */ static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale) { double gPart; double bPart; double rPart; double aPart; if (vbFlags & vbTrackFlag) { rPart = ((vtxInColor[0]) * (lightPart[0])) * scale; gPart = ((vtxInColor[1]) * (lightPart[1])) * scale; bPart = ((vtxInColor[2]) * (lightPart[2])) * scale; aPart = ((vtxInColor[3]) * (lightPart[3])) * scale; } else { /* Note: This should be pre-computed. */ rPart = ((materialPart[0]) * (lightPart[0])) * scale; gPart = ((materialPart[1]) * (lightPart[1])) * scale; bPart = ((materialPart[2]) * (lightPart[2])) * scale; aPart = ((materialPart[3]) * (lightPart[3])) * scale; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart); vtxOutColor[1] = ((vtxOutColor[1]) + gPart); vtxOutColor[2] = ((vtxOutColor[2]) + bPart); vtxOutColor[3] = ((vtxOutColor[3]) + aPart); } /* Check if the matrix scales normals to non-unit length. */ static sqInt analyzeMatrix3x3Length(float *m) { double det; det = (((((((m[0]) * (m[5])) * (m[10])) - (((m[2]) * (m[5])) * (m[8]))) + (((m[4]) * (m[9])) * (m[2]))) - (((m[6]) * (m[9])) * (m[0]))) + (((m[8]) * (m[1])) * (m[6]))) - (((m[10]) * (m[1])) * (m[4])); return (det < 0.99) || (det > 1.01); } /* Analyze the matrix and return the appropriate flags */ static sqInt analyzeMatrix(float *m) { sqInt flags; flags = 0; if (((m[12]) == 0.0) && (((m[13]) == 0.0) && (((m[14]) == 0.0) && ((m[15]) == 1.0)))) { /* Check translation */ flags = flags | FlagM44NoPerspective; if (((m[3]) == 0.0) && (((m[7]) == 0.0) && ((m[11]) == 0.0))) { /* Check for identity */ flags = flags | FlagM44NoTranslation; if (((m[0]) == 1.0) && (((m[5]) == 1.0) && (((m[10]) == 1.0) && (((m[1]) == 0.0) && (((m[2]) == 0.0) && (((m[4]) == 0.0) && (((m[6]) == 0.0) && (((m[8]) == 0.0) && ((m[9]) == 0.0))))))))) { flags = flags | FlagM44Identity; } } } return flags; } /* Primitive. Clip the polygon given in the vertexArray using the temporary vertex array which is assumed to have sufficient size. */ EXPORT(sqInt) b3dClipPolygon(void) { sqInt vtxCount; sqInt outMask; int *vtxArray; int *tempVtxArray; sqInt count; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } outMask = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount + 4); tempVtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount + 4); if ((vtxArray == null) || ((tempVtxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } vtxArray -= PrimVertexSize; tempVtxArray -= PrimVertexSize; count = clipPolygoncountwithmask(vtxArray, vtxCount, tempVtxArray, outMask); interpreterProxy->pop(5); interpreterProxy->pushInteger(count); } /* Primitive. Compute and return the index for the minimal z value of all objects in the vertex buffer. */ EXPORT(sqInt) b3dComputeMinIndexZ(void) { sqInt primType; int *idxArray; sqInt idxSize; float *vtxArray; sqInt vtxSize; sqInt minIndex; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(0); vtxSize = interpreterProxy->stackIntegerValue(2); primType = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if ((primType < 1) || (primType > 6)) { return interpreterProxy->primitiveFail(); } if (primType <= 3) { minIndex = processNonIndexedIDXofSize(vtxArray, vtxSize); } else { minIndex = processIndexedIDXofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(6); interpreterProxy->pushInteger(minIndex); } } /* Primitive. Compute and return the minimal z value of all objects in the vertex buffer. */ EXPORT(sqInt) b3dComputeMinZ(void) { sqInt primType; int *idxArray; sqInt idxSize; float *vtxArray; sqInt vtxSize; double minZ; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(0); vtxSize = interpreterProxy->stackIntegerValue(2); primType = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if ((primType < 1) || (primType > 6)) { return interpreterProxy->primitiveFail(); } if (primType <= 3) { minZ = processNonIndexedofSize(vtxArray, vtxSize); } else { minZ = processIndexedofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(6); interpreterProxy->pushFloat(minZ); } } /* Primitive. Determine the clipping flags for all vertices. */ EXPORT(sqInt) b3dDetermineClipFlags(void) { sqInt vtxCount; sqInt result; void *vtxArray; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } vtxCount = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount); if ((vtxArray == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } result = determineClipFlagscount(vtxArray, vtxCount); if (!(interpreterProxy->failed())) { interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } } EXPORT(sqInt) b3dInitPrimitiveObject(void) { sqInt vtxSize; int *vtxArray; void *primObj; int *idxArray; sqInt idxSize; sqInt primSize; sqInt primOop; sqInt textureIndex; sqInt primitive; if (!((interpreterProxy->methodArgumentCount()) == 8)) { return interpreterProxy->primitiveFail(); } textureIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } loadViewportFrom(1); if (interpreterProxy->failed()) { return null; } vtxSize = interpreterProxy->stackIntegerValue(4); vtxArray = stackPrimitiveVertexArrayofSize(5, vtxSize); if (vtxArray == null) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(2); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(3, idxSize, 1, vtxSize); if (idxArray == null) { return interpreterProxy->primitiveFail(); } primitive = interpreterProxy->stackIntegerValue(6); if ((primitive < 1) || (primitive > PrimTypeMax)) { return interpreterProxy->primitiveFail(); } if (!((primitive == 3) || ((primitive == 5) || (primitive == 6)))) { return interpreterProxy->primitiveFail(); } primOop = interpreterProxy->stackObjectValue(7); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(primOop))) { return interpreterProxy->primitiveFail(); } primObj = interpreterProxy->firstIndexableField(primOop); /* Do the work */ primSize = interpreterProxy->byteSizeOf(primOop); if (primitive == 3) { if (b3dAddPolygonObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } if (primitive == 5) { if (b3dAddIndexedTriangleObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputFace*) idxArray, idxSize / 3, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } if (primitive == 6) { if (b3dAddIndexedQuadObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputQuad*) idxArray, idxSize / 4, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(9); interpreterProxy->push(primOop); } /* Primitive. Initialize the primitive level objects of the given rasterizer. */ EXPORT(sqInt) b3dInitializeRasterizerState(void) { sqInt objOop; sqInt objLen; sqInt stateOop; void *obj; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } stateOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 7))) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(0, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeFaceAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(1, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeEdgeAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(2, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeAttrAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(3, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeAET(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(4, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeEdgeList(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(5, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeFillList(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } /* Primitive. Perform an inplace house holder matrix inversion */ EXPORT(sqInt) b3dInplaceHouseHolderInvert(void) { sqInt j; double sigma; sqInt r; sqInt i; double beta; double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; float *rcvr; double m[4][4]; double d[4][4]; double sum; sqInt k; double s; ; rcvr = stackMatrix(0); for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { (m[i])[j] = (rcvr[(i * 4) + j]); } } for (j = 0; j <= 3; j += 1) { sigma = 0.0; for (i = j; i <= 3; i += 1) { sigma += ((m[i])[j]) * ((m[i])[j]); } if (sigma < 1.0e-10) { return interpreterProxy->primitiveFail(); } if (((m[j])[j]) < 0.0) { s = sqrt(sigma); } else { s = 0.0 - (sqrt(sigma)); } for (r = 0; r <= 3; r += 1) { (d[j])[r] = s; } beta = 1.0 / ((s * ((m[j])[j])) - sigma); (m[j])[j] = (((m[j])[j]) - s); for (k = (j + 1); k <= 3; k += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((m[i])[j]) * ((m[i])[k]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (m[i])[k] = (((m[i])[k]) + (((m[i])[j]) * sum)); } } for (r = 0; r <= 3; r += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((x[i])[r]) * ((m[i])[j]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (x[i])[r] = (((x[i])[r]) + (sum * ((m[i])[j]))); } } } for (r = 0; r <= 3; r += 1) { for (i = 3; i >= 0; i += -1) { for (j = (i + 1); j <= 3; j += 1) { (x[i])[r] = (((x[i])[r]) - (((x[j])[r]) * ((m[i])[j]))); } (x[i])[r] = (((x[i])[r]) / ((d[i])[r])); } } for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { rcvr[(i * 4) + j] = (((float) ((x[i])[j]))); } } } /* Primitive. Load the given index array into the receiver. NOTE: dstStart is a zero-based index. */ EXPORT(sqInt) b3dLoadIndexArray(void) { int *srcPtr; sqInt i; sqInt count; sqInt dstStart; sqInt dstSize; sqInt vtxOffset; sqInt dstArray; sqInt idx; int *dstPtr; sqInt srcArray; sqInt maxValue; vtxOffset = interpreterProxy->stackIntegerValue(0); maxValue = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(2); srcArray = interpreterProxy->stackObjectValue(3); dstStart = interpreterProxy->stackIntegerValue(4); dstArray = interpreterProxy->stackObjectValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(srcArray))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(srcArray)) < count) { return interpreterProxy->primitiveFail(); } /* Check dstArray */ srcPtr = ((int*) (interpreterProxy->firstIndexableField(srcArray))); /* Check if there is enough room left in dstArray */ dstSize = interpreterProxy->slotSizeOf(dstArray); if ((dstStart + count) > dstSize) { return interpreterProxy->primitiveFail(); } /* Do the actual work */ dstPtr = ((int *) (interpreterProxy->firstIndexableField(dstArray))); for (i = 0; i <= (count - 1); i += 1) { idx = srcPtr[i]; if ((idx < 1) || (idx > maxValue)) { return interpreterProxy->primitiveFail(); } dstPtr[dstStart + i] = (idx + vtxOffset); } interpreterProxy->pop(7); interpreterProxy->pushInteger(count); } /* Primitive. Load the data into the given vertex buffer. NOTE: dstStart is a zero-based index. */ EXPORT(sqInt) b3dLoadVertexBuffer(void) { int *normalPtr; sqInt i; int *colorPtr; sqInt count; int *vtxPtr; sqInt dstStart; int *defaultTexCoords; int *defaultNormal; int *texPtr; int *dstPtr; int *defaultColor; int *defaultVtx; int *pVtx; defaultVtx = stackPrimitiveVertex(0); count = interpreterProxy->stackIntegerValue(1); texPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(2), 2 * count); colorPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(3), count); normalPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(4), 3 * count); vtxPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(5), 3 * count); dstStart = interpreterProxy->stackIntegerValue(6); /* Check for all problems above */ dstPtr = stackPrimitiveVertexArrayofSize(7, dstStart + count); if ((dstPtr == null) || ((defaultVtx == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if (normalPtr == null) { defaultNormal = defaultVtx + PrimVtxNormal; } else { defaultNormal = normalPtr; } if (texPtr == null) { defaultTexCoords = defaultVtx + PrimVtxTexCoords; } else { defaultTexCoords = texPtr; } if (colorPtr == null) { defaultColor = defaultVtx + PrimVtxColor32; } else { defaultColor = colorPtr; } pVtx = dstPtr + (dstStart * PrimVertexSize); for (i = 0; i <= (count - 1); i += 1) { pVtx[PrimVtxPositionX] = (vtxPtr[0]); pVtx[PrimVtxPositionY] = (vtxPtr[1]); pVtx[PrimVtxPositionZ] = (vtxPtr[2]); pVtx[PrimVtxNormalX] = (defaultNormal[0]); pVtx[PrimVtxNormalY] = (defaultNormal[1]); pVtx[PrimVtxNormalZ] = (defaultNormal[2]); pVtx[PrimVtxColor32] = (defaultColor[0]); pVtx[PrimVtxTexCoordU] = (defaultTexCoords[0]); pVtx[PrimVtxTexCoordV] = (defaultTexCoords[1]); pVtx += PrimVertexSize; vtxPtr += 3; if (!(normalPtr == null)) { defaultNormal += 3; } if (!(colorPtr == null)) { defaultColor += 1; } if (!(texPtr == null)) { defaultTexCoords += 2; } } interpreterProxy->pop(9); interpreterProxy->pushInteger(count); } /* Primitive. Determine the bounds for all vertices in the vertex buffer. */ EXPORT(sqInt) b3dMapVertexBuffer(void) { sqInt vtxCount; sqInt boxArray; void *vtxArray; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } boxArray = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(((interpreterProxy->fetchClassOf(boxArray)) == (interpreterProxy->classArray())) && ((interpreterProxy->slotSizeOf(boxArray)) == 4))) { return interpreterProxy->primitiveFail(); } vtxCount = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(2, vtxCount); if ((vtxArray == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } mapVBofSizeinto(vtxArray, vtxCount, boxArray); if (!(interpreterProxy->failed())) { interpreterProxy->pop(3); } } EXPORT(sqInt) b3dOrthoNormInverseMatrix(void) { sqInt dstOop; double z; float *dst; double y; float *src; double x; double rz; sqInt srcOop; double ry; double rx; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* Transpose upper 3x3 matrix */ /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[4] = (src[1]); dst[6] = (src[9]); dst[8] = (src[2]); dst[9] = (src[6]); x = src[3]; y = src[7]; z = src[11]; rx = ((x * (dst[0])) + (y * (dst[1]))) + (z * (dst[2])); ry = ((x * (dst[4])) + (y * (dst[5]))) + (z * (dst[6])); rz = ((x * (dst[8])) + (y * (dst[9]))) + (z * (dst[10])); dst[3] = (((float) (0.0 - rx))); dst[7] = (((float) (0.0 - ry))); dst[11] = (((float) (0.0 - rz))); interpreterProxy->pop(1); interpreterProxy->push(dstOop); } /* Primitive. Return the next clipped triangle from the vertex buffer and return its index. */ EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void) { int *vtxArray; sqInt i; sqInt vtxCount; sqInt idx3; int *idxArray; sqInt firstIndex; sqInt idx2; sqInt triMask; sqInt idxCount; sqInt idx1; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxCount = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); firstIndex = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxCount, 1, vtxCount); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } idxArray -= 1; vtxArray -= PrimVertexSize; for (i = firstIndex; i <= idxCount; i += 3) { idx1 = idxArray[i]; idx2 = idxArray[i + 1]; idx3 = idxArray[i + 2]; if (!((idx1 == 0) || ((idx2 == 0) || (idx3 == 0)))) { /* Check if tri is completely inside */ triMask = (vtxArray[(idx1 * PrimVertexSize) + PrimVtxClipFlags]) & ((vtxArray[(idx2 * PrimVertexSize) + PrimVtxClipFlags]) & (vtxArray[(idx3 * PrimVertexSize) + PrimVtxClipFlags])); if (!((InAllMask & triMask) == InAllMask)) { if (triMask & OutAllMask) { idxArray[i] = 0; idxArray[i + 1] = 0; idxArray[i + 2] = 0; } else { interpreterProxy->pop(6); interpreterProxy->pushInteger(i); return null; } } } } interpreterProxy->pop(6); interpreterProxy->pushInteger(0); } /* Primitive. Return the minimal number of words needed for a primitive object. */ EXPORT(sqInt) b3dPrimitiveObjectSize(void) { sqInt objSize; objSize = (((sqInt) (sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex)) >> 2)) + 1; interpreterProxy->pop(1); interpreterProxy->pushInteger(objSize); } /* Primitive. Return the minimal number of words needed for a primitive object. */ EXPORT(sqInt) b3dPrimitiveTextureSize(void) { sqInt objSize; objSize = (((sqInt) (sizeof(B3DTexture)) >> 2)) + 1; interpreterProxy->pop(1); interpreterProxy->pushInteger(objSize); } /* Primitive. Return the version of the rasterizer. */ EXPORT(sqInt) b3dRasterizerVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } /* Primitive. Shade all the vertices in the vertex buffer using the given array of primitive light sources. Return true on success. */ EXPORT(sqInt) b3dShadeVertexBuffer(void) { float *vtxArray; sqInt j; sqInt i; sqInt vtxCount; sqInt lightArray; sqInt lightCount; sqInt lightOop; sqInt rgba; sqInt a; sqInt r; sqInt g; sqInt b; vbFlags = interpreterProxy->stackIntegerValue(0); primMaterial = stackMaterialValue(1); lightArray = stackLightArrayValue(2); vtxCount = interpreterProxy->stackIntegerValue(3); vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount); if ((vtxArray == null) || ((primMaterial == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } litVertex = vtxArray; /* Go over all vertices */ lightCount = interpreterProxy->slotSizeOf(lightArray); for (i = 1; i <= vtxCount; i += 1) { /* begin loadPrimitiveVertex */ rgba = (((int*) litVertex))[PrimVtxColor32]; vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0)); if (vbFlags & VBTrackEmission) { vtxOutColor[0] = ((vtxInColor[0]) + (primMaterial[EmissionRed])); vtxOutColor[1] = ((vtxInColor[1]) + (primMaterial[EmissionGreen])); vtxOutColor[2] = ((vtxInColor[2]) + (primMaterial[EmissionBlue])); vtxOutColor[3] = ((vtxInColor[3]) + (primMaterial[EmissionAlpha])); } else { vtxOutColor[0] = (primMaterial[EmissionRed]); vtxOutColor[1] = (primMaterial[EmissionGreen]); vtxOutColor[2] = (primMaterial[EmissionBlue]); vtxOutColor[3] = (primMaterial[EmissionAlpha]); } for (j = 0; j <= (lightCount - 1); j += 1) { /* begin fetchLightSource:ofObject: */ lightOop = interpreterProxy->fetchPointerofObject(j, lightArray); primLight = interpreterProxy->firstIndexableField(lightOop); /* begin loadPrimitiveLightSource */ lightFlags = (((int*) primLight))[PrimLightFlags]; shadeVertex(); } /* begin storePrimitiveVertex */ r = ((sqInt) ((vtxOutColor[0]) * 255) ); r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255))); g = ((sqInt) ((vtxOutColor[1]) * 255) ); g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255))); b = ((sqInt) ((vtxOutColor[2]) * 255) ); b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255))); a = ((sqInt) ((vtxOutColor[3]) * 255) ); a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255))); (((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8)); litVertex += PrimVertexSize; } interpreterProxy->pop(6); interpreterProxy->pushBool(1); } /* Return the current shader version. */ EXPORT(sqInt) b3dShaderVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } /* Primitive. Start the rasterizer. */ EXPORT(sqInt) b3dStartRasterizer(void) { sqInt errCode; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } if (!(loadRasterizerState(2))) { return interpreterProxy->primitiveFail(); } loadTexturesFrom(0); if (interpreterProxy->failed()) { return null; } loadObjectsFrom(1); if (interpreterProxy->failed()) { return null; } errCode = b3dMainLoop(&state, B3D_NO_ERROR); storeObjectsInto(1); interpreterProxy->pop(4); interpreterProxy->pushInteger(errCode); } EXPORT(sqInt) b3dTransformDirection(void) { sqInt v3Oop; double z; double y; double x; float *matrix; double rz; double ry; double rx; float *vertex; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); interpreterProxy->pop(2); interpreterProxy->push(v3Oop); } /* Transform two matrices into the third */ EXPORT(sqInt) b3dTransformMatrixWithInto(void) { float *m3; float *m2; float *m1; m3 = stackMatrix(0); m2 = stackMatrix(1); m1 = stackMatrix(2); if (((m1 == null) || (m2 == null)) || (m3 == null)) { return interpreterProxy->primitiveFail(); } if (m2 == m3) { return interpreterProxy->primitiveFail(); } transformMatrixwithinto(m1, m2, m3); interpreterProxy->pop(3); } EXPORT(sqInt) b3dTransformPoint(void) { sqInt v3Oop; double z; double y; double x; float *matrix; double rz; double ry; double rx; double rw; float *vertex; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); if (rw == 1.0) { vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); } else { if (rw == 0.0) { rw = 0.0; } else { rw = 1.0 / rw; } vertex[0] = (((float) (rx * rw))); vertex[1] = (((float) (ry * rw))); vertex[2] = (((float) (rz * rw))); } interpreterProxy->pop(2); interpreterProxy->push(v3Oop); } /* Transform the normal of the given primitive vertex using the argument matrix and rescale the normal if necessary. */ EXPORT(sqInt) b3dTransformPrimitiveNormal(void) { float *matrix; sqInt rescale; float *pVertex; rescale = interpreterProxy->stackValue(0); if (!(rescale == (interpreterProxy->nilObject()))) { rescale = interpreterProxy->booleanValueOf(rescale); } matrix = stackMatrix(1); pVertex = stackPrimitiveVertex(2); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } if ((rescale != 1) && (rescale != 0)) { rescale = analyzeMatrix3x3Length(matrix); } transformPrimitiveNormalbyrescale(pVertex, matrix, rescale); interpreterProxy->pop(3); } /* Transform the position of the given primitive vertex the given matrix and store the result back inplace. */ EXPORT(sqInt) b3dTransformPrimitivePosition(void) { float *matrix; float *pVertex; matrix = stackMatrix(0); pVertex = stackPrimitiveVertex(1); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } transformPrimitivePositionby(pVertex, matrix); interpreterProxy->pop(2); } /* Transform the position of the given primitive vertex the given matrix and store the result in homogenous coordinates at rasterPos. */ EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void) { float *matrix; float *pVertex; matrix = stackMatrix(0); pVertex = stackPrimitiveVertex(1); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } transformPrimitiveRasterPositionby(pVertex, matrix); interpreterProxy->pop(2); } /* Transform an entire vertex buffer using the supplied modelview and projection matrix. */ EXPORT(sqInt) b3dTransformVertexBuffer(void) { float *projectionMatrix; sqInt vtxCount; sqInt flags; float *modelViewMatrix; float *vtxArray; flags = interpreterProxy->stackIntegerValue(0); projectionMatrix = stackMatrix(1); modelViewMatrix = stackMatrix(2); vtxCount = interpreterProxy->stackIntegerValue(3); vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount); if (((projectionMatrix == null) || (modelViewMatrix == null)) || (vtxArray == null)) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } transformVBcountbyandflags(vtxArray, vtxCount, modelViewMatrix, projectionMatrix, flags); interpreterProxy->pop(5); } /* Return the current version of the transformer */ EXPORT(sqInt) b3dTransformerVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } EXPORT(sqInt) b3dTransposeMatrix(void) { float *dst; sqInt dstOop; sqInt srcOop; float *src; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[3] = (src[12]); dst[4] = (src[1]); dst[6] = (src[9]); dst[7] = (src[13]); dst[8] = (src[2]); dst[9] = (src[6]); dst[11] = (src[14]); dst[12] = (src[3]); dst[13] = (src[7]); dst[14] = (src[11]); interpreterProxy->pop(1); interpreterProxy->push(dstOop); } static double backClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); } static double bottomClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); } static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask) { sqInt count; if (outMask == OutLeftBit) { return clipPolygonLeftFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutRightBit) { return clipPolygonRightFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutTopBit) { return clipPolygonTopFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutBottomBit) { return clipPolygonBottomFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutFrontBit) { return clipPolygonFrontFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutBackBit) { return clipPolygonBackFromtocount(tempVtxArray, vtxArray, vtxCount); } count = vtxCount; count = clipPolygonLeftFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonRightFromtocount(tempVtxArray, vtxArray, count); if (count == 0) { return 0; } count = clipPolygonTopFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonBottomFromtocount(tempVtxArray, vtxArray, count); if (count == 0) { return 0; } count = clipPolygonFrontFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonBackFromtocount(tempVtxArray, vtxArray, count); return count; } static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InBackBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InBackBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InBottomBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InBottomBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InFrontBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InFrontBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InLeftBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InLeftBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InRightBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InRightBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n) { sqInt inNext; sqInt j; sqInt outIndex; sqInt i; int *last; int *next; double t; sqInt inLast; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InTopBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InTopBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } /* Compute the attenuation for the current light and vertex */ static sqInt computeAttenuation(void) { lightScale = 1.0; if (lightFlags & FlagAttenuated) { lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared]))))); } } /* Compute the direction for the current light and vertex */ static sqInt computeDirection(void) { double scale; if (lightFlags & FlagPositional) { l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX])); l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY])); l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ])); l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2])); if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) { l2vDistance = sqrt(l2vDistance); scale = -1.0 / l2vDistance; } l2vDirection[0] = ((l2vDirection[0]) * scale); l2vDirection[1] = ((l2vDirection[1]) * scale); l2vDirection[2] = ((l2vDirection[2]) * scale); } else { if (lightFlags & FlagDirectional) { l2vDirection[0] = (primLight[PrimLightDirectionX]); l2vDirection[1] = (primLight[PrimLightDirectionY]); l2vDirection[2] = (primLight[PrimLightDirectionZ]); } } } /* Computes l2vSpecDir _ l2vSpecDir - vtx position safelyNormalized. */ static sqInt computeSpecularDirection(void) { double scale; scale = inverseLengthOfFloat(litVertex + PrimVtxPosition); l2vSpecDir[0] = ((l2vSpecDir[0]) - ((litVertex[PrimVtxPositionX]) * scale)); l2vSpecDir[1] = ((l2vSpecDir[1]) - ((litVertex[PrimVtxPositionY]) * scale)); l2vSpecDir[2] = ((l2vSpecDir[2]) - ((litVertex[PrimVtxPositionZ]) * scale)); } /* Compute the spot factor for a spot light */ static double computeSpotFactor(void) { double deltaCos; double cosAngle; double minCos; cosAngle = dotProductOfFloatwithDouble(primLight + PrimLightDirection, l2vDirection); cosAngle = 0.0 - cosAngle; minCos = primLight[SpotLightMinCos]; if (cosAngle < minCos) { return 0.0; } deltaCos = primLight[SpotLightDeltaCos]; if (deltaCos <= 1.0e-5) { return 1.0; } cosAngle = (cosAngle - minCos) / deltaCos; return pow(cosAngle,(primLight[SpotLightExponent])); } static sqInt determineClipFlagscount(void *vtxArray, sqInt count) { sqInt flags; sqInt i; double z; float *vtxPtr; double y; double x; double w; double w2; sqInt fullMask; vtxPtr = ((float *) vtxArray); fullMask = InAllMask + OutAllMask; for (i = 1; i <= count; i += 1) { w = vtxPtr[PrimVtxRasterPosW]; w2 = 0.0 - w; flags = 0; x = vtxPtr[PrimVtxRasterPosX]; if (x >= w2) { flags = flags | InLeftBit; } else { flags = flags | OutLeftBit; } if (x <= w) { flags = flags | InRightBit; } else { flags = flags | OutRightBit; } y = vtxPtr[PrimVtxRasterPosY]; if (y >= w2) { flags = flags | InBottomBit; } else { flags = flags | OutBottomBit; } if (y <= w) { flags = flags | InTopBit; } else { flags = flags | OutTopBit; } z = vtxPtr[PrimVtxRasterPosZ]; if (z >= w2) { flags = flags | InFrontBit; } else { flags = flags | OutFrontBit; } if (z <= w) { flags = flags | InBackBit; } else { flags = flags | OutBackBit; } fullMask = fullMask & flags; (((int *) vtxPtr))[PrimVtxClipFlags] = flags; vtxPtr += PrimVertexSize; } return fullMask; } static double dotProductOfFloatwithDouble(float * v1, double *v2) { return (((v1[0]) * (v2[0])) + ((v1[1]) * (v2[1]))) + ((v1[2]) * (v2[2])); } /* Fetch the primitive light source from the given array. Note: No checks are done within here - that happened in stackLightArrayValue: */ static void* fetchLightSourceofObject(sqInt index, sqInt anArray) { sqInt lightOop; lightOop = interpreterProxy->fetchPointerofObject(index, anArray); return interpreterProxy->firstIndexableField(lightOop); } static double frontClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { loadBBFn = interpreterProxy->ioLoadFunctionFrom("loadBitBltFrom", bbPluginName); copyBitsFn = interpreterProxy->ioLoadFunctionFrom("copyBitsFromtoat", bbPluginName); return (loadBBFn != 0) && (copyBitsFn != 0); } /* Interpolate the primitive vertices last/next at the parameter t */ static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out) { sqInt flags; unsigned int nextValue; double z; double y; double x; double delta; unsigned int newValue; double w; unsigned int lastValue; unsigned int rgbaLast; unsigned int rgbaNext; double w2; delta = (next[PrimVtxRasterPosX]) - (last[PrimVtxRasterPosX]); x = (last[PrimVtxRasterPosX]) + (delta * t); out[PrimVtxRasterPosX] = (((float) x)); delta = (next[PrimVtxRasterPosY]) - (last[PrimVtxRasterPosY]); y = (last[PrimVtxRasterPosY]) + (delta * t); out[PrimVtxRasterPosY] = (((float) y)); delta = (next[PrimVtxRasterPosZ]) - (last[PrimVtxRasterPosZ]); z = (last[PrimVtxRasterPosZ]) + (delta * t); out[PrimVtxRasterPosZ] = (((float) z)); delta = (next[PrimVtxRasterPosW]) - (last[PrimVtxRasterPosW]); w = (last[PrimVtxRasterPosW]) + (delta * t); out[PrimVtxRasterPosW] = (((float) w)); w2 = 0.0 - w; flags = 0; if (x >= w2) { flags = flags | InLeftBit; } else { flags = flags | OutLeftBit; } if (x <= w) { flags = flags | InRightBit; } else { flags = flags | OutRightBit; } if (y >= w2) { flags = flags | InBottomBit; } else { flags = flags | OutBottomBit; } if (y <= w) { flags = flags | InTopBit; } else { flags = flags | OutTopBit; } if (z >= w2) { flags = flags | InFrontBit; } else { flags = flags | OutFrontBit; } if (z <= w) { flags = flags | InBackBit; } else { flags = flags | OutBackBit; } (((int *) out))[PrimVtxClipFlags] = flags; rgbaLast = (((unsigned int *) last))[PrimVtxColor32]; lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; rgbaNext = (((unsigned int *) next))[PrimVtxColor32]; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue = ((sqInt) (lastValue + delta) ); lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt) (lastValue + delta) )) << 8; lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt) (lastValue + delta) )) << 16; lastValue = rgbaLast & 255; nextValue = rgbaNext & 255; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt) (lastValue + delta) )) << 24; (((unsigned int*) out))[PrimVtxColor32] = newValue; delta = (next[PrimVtxTexCoordU]) - (last[PrimVtxTexCoordU]); out[PrimVtxTexCoordU] = (((float) ((last[PrimVtxTexCoordU]) + (delta * t)))); delta = (next[PrimVtxTexCoordV]) - (last[PrimVtxTexCoordV]); out[PrimVtxTexCoordV] = (((float) ((last[PrimVtxTexCoordV]) + (delta * t)))); } static double inverseLengthOfDouble(double * aVector) { double scale; scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2])); if ((scale == 0.0) || (scale == 1.0)) { return scale; } return 1.0 / (sqrt(scale)); } static double inverseLengthOfFloat(float * aVector) { double scale; scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2])); if ((scale == 0.0) || (scale == 1.0)) { return scale; } return 1.0 / (sqrt(scale)); } static double leftClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); } static sqInt loadObjectsFrom(sqInt stackIndex) { B3DPrimitiveObject **objArray; sqInt i; sqInt arraySize; sqInt objOop; sqInt arrayOop; B3DPrimitiveObject *objPtr; arrayOop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(arrayOop); if (arraySize > (state.nObjects)) { return interpreterProxy->primitiveFail(); } objArray = state.objects; for (i = 0; i <= (arraySize - 1); i += 1) { objOop = interpreterProxy->fetchPointerofObject(i, arrayOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objPtr = ((B3DPrimitiveObject*) (interpreterProxy->firstIndexableField(objOop))); if (objPtr->magic != B3D_PRIMITIVE_OBJECT_MAGIC) { return interpreterProxy->primitiveFail(); } objPtr->__oop__ = objOop; objArray[i] = objPtr; } } static sqInt loadPrimitiveLightSource(void) { lightFlags = (((int*) primLight))[PrimLightFlags]; } /* Load the necessary values from the current primitive vertex */ static sqInt loadPrimitiveVertex(void) { sqInt rgba; rgba = (((int*) litVertex))[PrimVtxColor32]; vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0)); } /* Load the rasterizer state from the given stack index. */ static sqInt loadRasterizerState(sqInt stackIndex) { sqInt objLen; sqInt stateOop; void *objPtr; sqInt obj; if ((copyBitsFn == 0) || (loadBBFn == 0)) { if (!(initialiseModule())) { return 0; } } stateOop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return 0; } if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 10))) { return 0; } obj = interpreterProxy->fetchPointerofObject(0, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.faceAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(1, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.edgeAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(2, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.attrAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(3, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.aet = objPtr; obj = interpreterProxy->fetchPointerofObject(4, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.addedEdges = objPtr; obj = interpreterProxy->fetchPointerofObject(5, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.fillList = objPtr; obj = interpreterProxy->fetchPointerofObject(6, stateOop); if (obj == (interpreterProxy->nilObject())) { state.nObjects = 0; state.objects = NULL; } else { if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objLen = interpreterProxy->slotSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.objects = (B3DPrimitiveObject **)objPtr; state.nObjects = objLen; } obj = interpreterProxy->fetchPointerofObject(7, stateOop); if (obj == (interpreterProxy->nilObject())) { state.nTextures = 0; state.textures = NULL; } else { if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objLen = interpreterProxy->byteSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.textures = (B3DTexture *)objPtr; state.nTextures = objLen / sizeof(B3DTexture); } obj = interpreterProxy->fetchPointerofObject(8, stateOop); if (obj == (interpreterProxy->nilObject())) { state.spanSize = 0; state.spanBuffer = NULL; } else { if (!((interpreterProxy->fetchClassOf(obj)) == (interpreterProxy->classBitmap()))) { return 0; } objLen = interpreterProxy->slotSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.spanBuffer = (unsigned int *)objPtr; state.spanSize = objLen; } obj = interpreterProxy->fetchPointerofObject(9, stateOop); if (obj == (interpreterProxy->nilObject())) { state.spanDrawer = NULL; } else { if (!(((int (*) (int))loadBBFn)(obj))) { return 0; } state.spanDrawer = (b3dDrawBufferFunction) copyBitsFn; } return !(interpreterProxy->failed()); } /* Note: This still uses the old-style textures */ static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr) { sqInt formWidth; sqInt formDepth; sqInt form; sqInt formHeight; sqInt formBits; sqInt texInterpolate; sqInt texEnvMode; void *bitsPtr; sqInt texWrap; form = textureOop; if (!(interpreterProxy->isPointers(form))) { return 0; } if ((interpreterProxy->slotSizeOf(form)) < 8) { return 0; } formBits = interpreterProxy->fetchPointerofObject(0, form); formWidth = interpreterProxy->fetchIntegerofObject(1, form); formHeight = interpreterProxy->fetchIntegerofObject(2, form); formDepth = interpreterProxy->fetchIntegerofObject(3, form); texWrap = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(5, form)); texInterpolate = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(6, form)); texEnvMode = interpreterProxy->fetchIntegerofObject(7, form); if (interpreterProxy->failed()) { return 0; } if ((formWidth < 1) || ((formHeight < 1) || (formDepth != 32))) { return 0; } if (!((interpreterProxy->fetchClassOf(formBits)) == (interpreterProxy->classBitmap()))) { return 0; } if (!((interpreterProxy->byteSizeOf(formBits)) == ((formWidth * formHeight) * 4))) { return 0; } if ((texEnvMode < 0) || (texEnvMode > 1)) { return 0; } /* Set the texture parameters */ bitsPtr = interpreterProxy->firstIndexableField(formBits); return b3dLoadTexture(destPtr, formWidth, formHeight, formDepth, (unsigned int*) bitsPtr, 0, NULL) == B3D_NO_ERROR; } static sqInt loadTexturesFrom(sqInt stackIndex) { sqInt i; B3DTexture *destPtr; sqInt n; sqInt arrayOop; sqInt textureOop; arrayOop = interpreterProxy->stackObjectValue(stackIndex); if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } n = interpreterProxy->slotSizeOf(arrayOop); n = ((n < (state.nTextures)) ? n : (state.nTextures)); for (i = 0; i <= (n - 1); i += 1) { destPtr = state.textures + i; textureOop = interpreterProxy->fetchPointerofObject(i, arrayOop); if (!(loadTextureinto(textureOop, destPtr))) { return interpreterProxy->primitiveFail(); } } return 0; } /* Load the viewport from the given stack index */ static sqInt loadViewportFrom(sqInt stackIndex) { sqInt y0; sqInt oop; sqInt x1; sqInt x0; sqInt p2; sqInt y1; sqInt p1; oop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isPointers(oop))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(oop)) < 2) { return interpreterProxy->primitiveFail(); } p1 = interpreterProxy->fetchPointerofObject(0, oop); p2 = interpreterProxy->fetchPointerofObject(1, oop); if (!((interpreterProxy->fetchClassOf(p1)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->fetchClassOf(p2)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } x0 = interpreterProxy->fetchIntegerofObject(0, p1); y0 = interpreterProxy->fetchIntegerofObject(1, p1); x1 = interpreterProxy->fetchIntegerofObject(0, p2); y1 = interpreterProxy->fetchIntegerofObject(1, p2); if (interpreterProxy->failed()) { return null; } viewport.x0 = x0; viewport.y0 = y0; viewport.x1 = x1; viewport.y1 = y1; return 0; } static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray) { sqInt flags; double bottom; sqInt i; double top; float *vtxPtr; double y; sqInt oop; double x; double left; double w; double right; sqInt floatOop; vtxPtr = ((float *) vtxArray); for (i = 1; i <= vtxCount; i += 1) { flags = (((int *) vtxPtr))[PrimVtxClipFlags]; w = vtxPtr[PrimVtxRasterPosW]; if (!(w == 0.0)) { w = 1.0 / w; } if ((flags & OutLeftBit) != 0) { x = -1.0; } else { if ((flags & OutRightBit) != 0) { x = 1.0; } else { x = (vtxPtr[PrimVtxRasterPosX]) * w; } } if ((flags & OutTopBit) != 0) { y = -1.0; } else { if ((flags & OutBottomBit) != 0) { y = 1.0; } else { y = (vtxPtr[PrimVtxRasterPosY]) * w; } } if (i == 1) { left = right = x; top = bottom = y; } if (x < left) { left = x; } if (x > right) { right = x; } if (y < top) { top = y; } if (y > bottom) { bottom = y; } vtxPtr += PrimVertexSize; } oop = boxArray; interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(left); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(top); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(right); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(2, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(bottom); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(3, oop, floatOop); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char * aModuleName) { if ((strcmp(aModuleName, bbPluginName)) == 0) { /* BitBlt just shut down. How nasty. */ loadBBFn = 0; copyBitsFn = 0; } } static sqInt msg(char * s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Primitive. Set the BitBlt plugin to use. */ EXPORT(sqInt) primitiveSetBitBltPlugin(void) { sqInt length; sqInt i; sqInt needReload; sqInt pluginName; char *ptr; /* Must be string to work */ pluginName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(pluginName))) { return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(pluginName); if (length >= 256) { return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(pluginName); needReload = 0; for (i = 0; i <= (length - 1); i += 1) { if (!((bbPluginName[i]) == (ptr[i]))) { bbPluginName[i] = (ptr[i]); needReload = 1; } } if (!((bbPluginName[length]) == 0)) { bbPluginName[length] = 0; needReload = 1; } if (needReload) { if (!(initialiseModule())) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(1); } static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) { sqInt i; float *vtxPtr; sqInt index; double zValue; double wValue; double minZ; minZ = 10.0; for (i = 1; i <= idxSize; i += 1) { index = idxArray[i]; if (index > 0) { vtxPtr = vtxArray + ((index - 1) * PrimVertexSize); zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if (zValue < minZ) { minZ = zValue; } } } return minZ; } static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) { sqInt i; float *vtxPtr; sqInt minIndex; sqInt index; double zValue; double wValue; double minZ; minZ = 10.0; minIndex = 0; for (i = 1; i <= idxSize; i += 1) { index = idxArray[i]; if (index > 0) { vtxPtr = vtxArray + ((index - 1) * PrimVertexSize); zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if ((minIndex == 0) || (zValue < minZ)) { minIndex = i; minZ = zValue; } } } return minIndex; } static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize) { sqInt i; float *vtxPtr; double zValue; double wValue; double minZ; minZ = 10.0; vtxPtr = vtxArray; for (i = 1; i <= vtxSize; i += 1) { zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if (zValue < minZ) { minZ = zValue; } } return minZ; } static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize) { sqInt i; float *vtxPtr; sqInt minIndex; double zValue; double wValue; double minZ; minZ = 10.0; minIndex = 0; vtxPtr = vtxArray; for (i = 1; i <= vtxSize; i += 1) { zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if ((minIndex == 0) || (zValue < minZ)) { minIndex = i; minZ = zValue; } } return minIndex; } static double rightClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine* anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt shadeVertex(void) { double cosAngle; double specularFactor; double gPart; double bPart; double rPart; double aPart; double gPart1; double bPart1; double rPart1; double aPart1; double gPart2; double bPart2; double rPart2; double aPart2; double scale; /* begin computeDirection */ if (lightFlags & FlagPositional) { l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX])); l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY])); l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ])); l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2])); if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) { l2vDistance = sqrt(l2vDistance); scale = -1.0 / l2vDistance; } l2vDirection[0] = ((l2vDirection[0]) * scale); l2vDirection[1] = ((l2vDirection[1]) * scale); l2vDirection[2] = ((l2vDirection[2]) * scale); } else { if (lightFlags & FlagDirectional) { l2vDirection[0] = (primLight[PrimLightDirectionX]); l2vDirection[1] = (primLight[PrimLightDirectionY]); l2vDirection[2] = (primLight[PrimLightDirectionZ]); } } /* begin computeAttenuation */ lightScale = 1.0; if (lightFlags & FlagAttenuated) { lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared]))))); } if (lightFlags & FlagHasSpot) { lightScale = lightScale * (computeSpotFactor()); } if (lightScale > 0.001) { if (lightFlags & FlagAmbientPart) { /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackAmbient) { rPart = ((vtxInColor[0]) * ((primLight + AmbientPart)[0])) * lightScale; gPart = ((vtxInColor[1]) * ((primLight + AmbientPart)[1])) * lightScale; bPart = ((vtxInColor[2]) * ((primLight + AmbientPart)[2])) * lightScale; aPart = ((vtxInColor[3]) * ((primLight + AmbientPart)[3])) * lightScale; } else { rPart = (((primMaterial + AmbientPart)[0]) * ((primLight + AmbientPart)[0])) * lightScale; gPart = (((primMaterial + AmbientPart)[1]) * ((primLight + AmbientPart)[1])) * lightScale; bPart = (((primMaterial + AmbientPart)[2]) * ((primLight + AmbientPart)[2])) * lightScale; aPart = (((primMaterial + AmbientPart)[3]) * ((primLight + AmbientPart)[3])) * lightScale; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart); vtxOutColor[1] = ((vtxOutColor[1]) + gPart); vtxOutColor[2] = ((vtxOutColor[2]) + bPart); vtxOutColor[3] = ((vtxOutColor[3]) + aPart); } if (lightFlags & FlagDiffusePart) { /* Compute angle from light->vertex to vertex normal */ /* For one-sided lighting negate cosAngle if necessary */ cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vDirection); if (((vbFlags & VBTwoSidedLighting) == 0) && (cosAngle < 0.0)) { cosAngle = 0.0 - cosAngle; } if (cosAngle > 0.0) { /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackDiffuse) { rPart1 = ((vtxInColor[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle); gPart1 = ((vtxInColor[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle); bPart1 = ((vtxInColor[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle); aPart1 = ((vtxInColor[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle); } else { rPart1 = (((primMaterial + DiffusePart)[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle); gPart1 = (((primMaterial + DiffusePart)[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle); bPart1 = (((primMaterial + DiffusePart)[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle); aPart1 = (((primMaterial + DiffusePart)[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle); } vtxOutColor[0] = ((vtxOutColor[0]) + rPart1); vtxOutColor[1] = ((vtxOutColor[1]) + gPart1); vtxOutColor[2] = ((vtxOutColor[2]) + bPart1); vtxOutColor[3] = ((vtxOutColor[3]) + aPart1); } } } if ((lightFlags & FlagSpecularPart) && ((primMaterial[MaterialShininess]) > 0.0)) { l2vSpecDir[0] = (l2vDirection[0]); l2vSpecDir[1] = (l2vDirection[1]); l2vSpecDir[2] = (l2vDirection[2]); if (vbFlags & VBUseLocalViewer) { computeSpecularDirection(); } else { l2vSpecDir[2] = ((l2vSpecDir[2]) - 1.0); } cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vSpecDir); if (cosAngle > 0.0) { /* Normalize the angle */ /* cosAngle should be somewhere between 0 and 1. If not, then the vertex normal was not normalized */ cosAngle = cosAngle * (inverseLengthOfDouble(l2vSpecDir)); if (cosAngle > 1.0) { specularFactor = pow(cosAngle,(primMaterial[MaterialShininess])); } else { if (cosAngle == 0.0) { specularFactor = 1.0; } else { specularFactor = pow(cosAngle,(primMaterial[MaterialShininess])); } } /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackSpecular) { rPart2 = ((vtxInColor[0]) * ((primLight + SpecularPart)[0])) * specularFactor; gPart2 = ((vtxInColor[1]) * ((primLight + SpecularPart)[1])) * specularFactor; bPart2 = ((vtxInColor[2]) * ((primLight + SpecularPart)[2])) * specularFactor; aPart2 = ((vtxInColor[3]) * ((primLight + SpecularPart)[3])) * specularFactor; } else { rPart2 = (((primMaterial + SpecularPart)[0]) * ((primLight + SpecularPart)[0])) * specularFactor; gPart2 = (((primMaterial + SpecularPart)[1]) * ((primLight + SpecularPart)[1])) * specularFactor; bPart2 = (((primMaterial + SpecularPart)[2]) * ((primLight + SpecularPart)[2])) * specularFactor; aPart2 = (((primMaterial + SpecularPart)[3]) * ((primLight + SpecularPart)[3])) * specularFactor; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart2); vtxOutColor[1] = ((vtxOutColor[1]) + gPart2); vtxOutColor[2] = ((vtxOutColor[2]) + bPart2); vtxOutColor[3] = ((vtxOutColor[3]) + aPart2); } } } /* Load an Array of B3DPrimitiveLights from the given stack index */ static sqInt stackLightArrayValue(sqInt stackIndex) { sqInt array; sqInt i; sqInt arraySize; sqInt oop; array = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(array); for (i = 0; i <= (arraySize - 1); i += 1) { oop = interpreterProxy->fetchPointerofObject(i, array); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimLightSize))) { return interpreterProxy->primitiveFail(); } } return array; } /* Load a B3DMaterial from the given stack index */ static void * stackMaterialValue(sqInt stackIndex) { sqInt oop; oop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == MaterialSize)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a 4x4 transformation matrix from the interpreter stack. Return a pointer to the matrix data if successful, nil otherwise. */ static void* stackMatrix(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive index array from the interpreter stack. If aBool is true then check that all the indexes are in the range (1,maxIndex). Return a pointer to the index data if successful, nil otherwise. */ static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex) { sqInt i; sqInt oop; sqInt index; sqInt oopSize; int *idxPtr; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (!(interpreterProxy->isWords(oop))) { return null; } oopSize = interpreterProxy->slotSizeOf(oop); if (oopSize < nItems) { return null; } idxPtr = ((int *) (interpreterProxy->firstIndexableField(oop))); if (aBool) { for (i = 0; i <= (nItems - 1); i += 1) { index = idxPtr[i]; if ((index < 0) || (index > maxIndex)) { return null; } } } return idxPtr; } /* Load a primitive vertex from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertex(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimVertexSize)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive vertex array from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems) { sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if (interpreterProxy->isWords(oop)) { oopSize = interpreterProxy->slotSizeOf(oop); if (((oopSize >= nItems) * PrimVertexSize) && ((oopSize % PrimVertexSize) == 0)) { return interpreterProxy->firstIndexableField(oop); } } return null; } static sqInt storeObjectsInto(sqInt stackIndex) { sqInt i; sqInt arraySize; sqInt objOop; sqInt arrayOop; arrayOop = interpreterProxy->stackObjectValue(stackIndex); arraySize = state.nObjects; for (i = 0; i <= (arraySize - 1); i += 1) { objOop = state.objects[i]->__oop__; interpreterProxy->storePointerofObjectwithValue(i, arrayOop, objOop); } } /* Store the computed output color back into the current primitive vertex. Clamp the r,g,b,a part to be in the range 0-255. */ static sqInt storePrimitiveVertex(void) { sqInt a; sqInt r; sqInt g; sqInt b; r = ((sqInt) ((vtxOutColor[0]) * 255) ); r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255))); g = ((sqInt) ((vtxOutColor[1]) * 255) ); g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255))); b = ((sqInt) ((vtxOutColor[2]) * 255) ); b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255))); a = ((sqInt) ((vtxOutColor[3]) * 255) ); /* The following is equal to b + (g << 8) + (r << 16) + (a << 24) */ a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255))); (((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8)); } static double topClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); } /* Transform src with arg into dst. It is allowed that src == dst but not arg == dst */ static sqInt transformMatrixwithinto(float *src, float *arg, float *dst) { float *m3; sqInt i; float *m2; float *m1; float c4; float c3; float c2; float c1; m1 = ((float *) src); m2 = ((float *) arg); m3 = ((float *) dst); for (i = 0; i <= 3; i += 1) { /* Compute next row */ c1 = ((((m1[0]) * (m2[0])) + ((m1[1]) * (m2[4]))) + ((m1[2]) * (m2[8]))) + ((m1[3]) * (m2[12])); c2 = ((((m1[0]) * (m2[1])) + ((m1[1]) * (m2[5]))) + ((m1[2]) * (m2[9]))) + ((m1[3]) * (m2[13])); c3 = ((((m1[0]) * (m2[2])) + ((m1[1]) * (m2[6]))) + ((m1[2]) * (m2[10]))) + ((m1[3]) * (m2[14])); /* Store result */ c4 = ((((m1[0]) * (m2[3])) + ((m1[1]) * (m2[7]))) + ((m1[2]) * (m2[11]))) + ((m1[3]) * (m2[15])); m3[0] = c1; m3[1] = c2; m3[2] = c3; m3[3] = c4; m1 += 4; m3 += 4; } } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale) { double dot; double z; double y; double x; double rz; double ry; double rx; x = pVertex[PrimVtxNormalX]; y = pVertex[PrimVtxNormalY]; z = pVertex[PrimVtxNormalZ]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); if (rescale) { dot = ((rx * rx) + (ry * ry)) + (rz * rz); if (dot < 1.0e-20) { rx = ry = rz = 0.0; } else { if (!(dot == 1.0)) { dot = 1.0 / (sqrt(dot)); rx = rx * dot; ry = ry * dot; rz = rz * dot; } } } pVertex[PrimVtxNormalX] = (((float) rx)); pVertex[PrimVtxNormalY] = (((float) ry)); pVertex[PrimVtxNormalZ] = (((float) rz)); } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitivePositionby(float *pVertex, float *matrix) { double z; double y; double x; double rz; double ry; double rx; double rw; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); if (rw == 1.0) { pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } else { if (rw == 0.0) { rw = 0.0; } else { rw = 1.0 / rw; } pVertex[PrimVtxPositionX] = (((float) (rx * rw))); pVertex[PrimVtxPositionY] = (((float) (ry * rw))); pVertex[PrimVtxPositionZ] = (((float) (rz * rw))); } } /* Transform the position of the given primitive vertex assuming that matrix a41 = a42 = a43 = 0.0 and a44 = 1.0 */ static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix) { double z; double y; double x; double rz; double ry; double rx; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } /* Transform the position of the given primitive vertex assuming that matrix a14 = a24 = a34 = a41 = a42 = a43 = 0.0 and a44 = 1.0 */ static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix) { double z; double y; double x; double rz; double ry; double rx; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix) { double z; double y; double x; double rz; double ry; double rx; double rw; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); pVertex[PrimVtxRasterPosX] = (((float) rx)); pVertex[PrimVtxRasterPosY] = (((float) ry)); pVertex[PrimVtxRasterPosZ] = (((float) rz)); pVertex[PrimVtxRasterPosW] = (((float) rw)); } /* Transform the entire vertex array by the given matrices */ /* TODO: Check the actual trade-offs between vtxCount and analyzing */ static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags) { sqInt mvFlags; sqInt i; sqInt prFlags; float *pVertex; sqInt hasNormals; sqInt rescale; mvFlags = analyzeMatrix(modelViewMatrix); prFlags = analyzeMatrix(projectionMatrix); pVertex = ((float *) vtxArray); /* Check if we have to rescale the normals */ hasNormals = flags & VBVtxHasNormals; if (hasNormals) { if (mvFlags & FlagM44Identity) { rescale = 0; } else { rescale = analyzeMatrix3x3Length(modelViewMatrix); } } if ((mvFlags & FlagM44NoPerspective) && (prFlags == 0)) { if ((mvFlags == FlagM44NoTranslation) == 0) { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionFastby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } else { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionFasterby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } return null; } if ((mvFlags & prFlags) & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]); pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]); pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]); pVertex[PrimVtxRasterPosW] = 1.0; pVertex += PrimVertexSize; } return null; } if (mvFlags & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } return null; } if (prFlags & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } if (mvFlags == (FlagM44NoPerspective + FlagM44NoPerspective)) { transformPrimitivePositionFasterby(pVertex, modelViewMatrix); } else { if (mvFlags == FlagM44NoPerspective) { transformPrimitivePositionFastby(pVertex, modelViewMatrix); } else { transformPrimitivePositionby(pVertex, modelViewMatrix); } } pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]); pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]); pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]); pVertex[PrimVtxRasterPosW] = 1.0; pVertex += PrimVertexSize; } return null; } for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } /* Load the word based array of size count from the given oop */ static void* vbLoadArraysize(sqInt oop, sqInt count) { if (oop == null) { interpreterProxy->primitiveFail(); return null; } if (oop == (interpreterProxy->nilObject())) { return null; } if (!(interpreterProxy->isWords(oop))) { interpreterProxy->primitiveFail(); return null; } if (!((interpreterProxy->slotSizeOf(oop)) == count)) { interpreterProxy->primitiveFail(); return null; } return interpreterProxy->firstIndexableField(oop); } #ifdef SQUEAK_BUILTIN_PLUGIN void* Squeak3D_exports[][3] = { {"Squeak3D", "b3dShaderVersion", (void*)b3dShaderVersion}, {"Squeak3D", "b3dTransformPrimitiveNormal", (void*)b3dTransformPrimitiveNormal}, {"Squeak3D", "b3dClipPolygon", (void*)b3dClipPolygon}, {"Squeak3D", "b3dOrthoNormInverseMatrix", (void*)b3dOrthoNormInverseMatrix}, {"Squeak3D", "b3dTransformVertexBuffer", (void*)b3dTransformVertexBuffer}, {"Squeak3D", "b3dComputeMinZ", (void*)b3dComputeMinZ}, {"Squeak3D", "b3dInitializeRasterizerState", (void*)b3dInitializeRasterizerState}, {"Squeak3D", "b3dDetermineClipFlags", (void*)b3dDetermineClipFlags}, {"Squeak3D", "getModuleName", (void*)getModuleName}, {"Squeak3D", "setInterpreter", (void*)setInterpreter}, {"Squeak3D", "b3dTransformPrimitiveRasterPosition", (void*)b3dTransformPrimitiveRasterPosition}, {"Squeak3D", "primitiveSetBitBltPlugin", (void*)primitiveSetBitBltPlugin}, {"Squeak3D", "b3dTransformMatrixWithInto", (void*)b3dTransformMatrixWithInto}, {"Squeak3D", "b3dStartRasterizer", (void*)b3dStartRasterizer}, {"Squeak3D", "b3dShadeVertexBuffer", (void*)b3dShadeVertexBuffer}, {"Squeak3D", "b3dRasterizerVersion", (void*)b3dRasterizerVersion}, {"Squeak3D", "b3dInitPrimitiveObject", (void*)b3dInitPrimitiveObject}, {"Squeak3D", "b3dLoadVertexBuffer", (void*)b3dLoadVertexBuffer}, {"Squeak3D", "b3dTransformDirection", (void*)b3dTransformDirection}, {"Squeak3D", "moduleUnloaded", (void*)moduleUnloaded}, {"Squeak3D", "b3dPrimitiveTextureSize", (void*)b3dPrimitiveTextureSize}, {"Squeak3D", "b3dComputeMinIndexZ", (void*)b3dComputeMinIndexZ}, {"Squeak3D", "b3dMapVertexBuffer", (void*)b3dMapVertexBuffer}, {"Squeak3D", "initialiseModule", (void*)initialiseModule}, {"Squeak3D", "b3dTransformerVersion", (void*)b3dTransformerVersion}, {"Squeak3D", "b3dTransposeMatrix", (void*)b3dTransposeMatrix}, {"Squeak3D", "b3dPrimitiveNextClippedTriangle", (void*)b3dPrimitiveNextClippedTriangle}, {"Squeak3D", "b3dTransformPoint", (void*)b3dTransformPoint}, {"Squeak3D", "b3dTransformPrimitivePosition", (void*)b3dTransformPrimitivePosition}, {"Squeak3D", "b3dPrimitiveObjectSize", (void*)b3dPrimitiveObjectSize}, {"Squeak3D", "b3dLoadIndexArray", (void*)b3dLoadIndexArray}, {"Squeak3D", "b3dInplaceHouseHolderInvert", (void*)b3dInplaceHouseHolderInvert}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/SqueakFFIPrims/SqueakFFIPrims.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from ReentrantIA32FFIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "ReentrantIA32FFIPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" #include "sqAssert.h" /* for assert */ #undef halt /* sqAssert.h provides a halt used in the interpreter */ #ifdef _MSC_VER # define alloca _alloca #endif #if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)) # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp)) # define getsp() ({ void *esp; asm volatile ("movl %%esp,%0" : "=r"(esp) : ); esp;}) #endif #if !defined(getsp) # define getsp() 0 #endif #if !defined(setsp) # define setsp(ignored) 0 #endif #if __APPLE__ && __MACH__ && __i386__ # define STACK_ALIGN_BYTES 16 #elif __linux__ && __i386__ # define STACK_ALIGN_BYTES 16 #elif defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64) # define STACK_ALIGN_BYTES 16 #elif defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__) # define STACK_ALIGN_BYTES 16 #elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must preceed 32-bit sparc defs */ # define STACK_ALIGN_BYTES 16 #elif defined(sparc) || defined(__sparc__) || defined(__sparclite__) # define STACK_ALIGN_BYTES 8 #else # define STACK_ALIGN_BYTES 0 #endif #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) /* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size * less than or equal to eight bytes in length in registers. Linux never does so. */ # if __linux__ # define WIN32_X86_STRUCT_RETURN 0 # else # define WIN32_X86_STRUCT_RETURN 1 # endif # if WIN32 # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1 # else # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0 # endif # if defined(__MINGW32__) && (__GNUC__ >= 3) /* * cygwin -mno-cygwin (MinGW) gcc 3.4.x's alloca is a library routine that answers * %esp + 4, so the outgoing stack is offset by one word if uncorrected. * Grab the actual stack pointer to correct. */ # define ALLOCA_LIES_SO_USE_GETSP 1 # endif #endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */ #if !defined(ALLOCA_LIES_SO_USE_GETSP) # define ALLOCA_LIES_SO_USE_GETSP 0 #endif /* The dispatchOn:in:with:with: generates an unwanted call on error. Just squash it. */ #define error(foo) 0 /* but print assert failures. */ void warning(char *s) { /* Print an error message but don't exit. */ printf("\n%s\n", s); } typedef struct { char *argVector; char *currentArg; char *limit; sqInt structReturnSize; sqInt callFlags; void *ffiArgSpec; sqInt ffiArgSpecSize; sqInt ffiArgHeader; sqInt ffiRetHeader; sqInt stringArgIndex; char *stringArgs[15]; } CalloutState; #define ReentrantFFICalloutState CalloutState /*** Constants ***/ #define BaseHeaderSize 4 #define BytesPerOop 4 #define DefaultMaxStackSize 16384 #define ExternalFunctionArgTypesIndex 2 #define ExternalFunctionFlagsIndex 1 #define ExternalFunctionStackSizeIndex 3 #define FFIAtomicTypeMask 0xF000000 #define FFIAtomicTypeShift 24 #define FFICallTypeApi 1 #define FFIErrorAddressNotFound 13 #define FFIErrorAttemptToPassVoid 14 #define FFIErrorBadAddress 11 #define FFIErrorBadArg 3 #define FFIErrorBadArgs 2 #define FFIErrorBadAtomicType 5 #define FFIErrorBadExternalFunction 17 #define FFIErrorBadExternalLibrary 16 #define FFIErrorBadReturn 10 #define FFIErrorCallFrameTooBig 19 #define FFIErrorCallType 9 #define FFIErrorCoercionFailed 6 #define FFIErrorIntAsPointer 4 #define FFIErrorInvalidPointer 18 #define FFIErrorModuleNotFound 15 #define FFIErrorNoModule 12 #define FFIErrorNotFunction 1 #define FFIErrorStructSize 8 #define FFIErrorWrongType 7 #define FFIFlagAtomic 0x40000 #define FFIFlagPointer 0x20000 #define FFIFlagStructure 0x10000 #define FFINoCalloutAvailable -1 #define FFIStructSizeMask 0xFFFF #define FFITypeBool 1 #define FFITypeDoubleFloat 13 #define FFITypeSignedByte 3 #define FFITypeSignedChar 11 #define FFITypeSignedInt 7 #define FFITypeSignedLongLong 9 #define FFITypeSignedShort 5 #define FFITypeSingleFloat 12 #define FFITypeUnsignedByte 2 #define FFITypeVoid 0 #define MaxNumArgs 15 #define PrimErrBadArgument 3 #define PrimErrBadMethod 12 #define PrimErrBadNumArgs 5 #define PrimErrBadReceiver 2 #define PrimErrNoCMemory 10 /*** Function Prototypes ***/ static sqInt atomicTypeOf(sqInt typeSpec); static void cleanupCalloutState(CalloutState *calloutState); static sqInt externalFunctionHasStackSizeSlot(void); static sqInt ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState); static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState); static sqInt ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState); static sqInt ffiAtomicStructByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState); static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState); static sqInt ffiCallArgArrayOrNilNumArgs(sqInt externalFunction, sqInt argArrayOrNil, sqInt nArgs); static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState); static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode); static sqInt ffiCreateIntegralResultOopofAtomicTypein(usqLong retVal, sqInt atomicType, CalloutState *calloutState); static sqInt ffiFail(sqInt reason); static double ffiFloatValueOf(sqInt oop); static sqInt ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); static sqInt ffiLoadCalloutAddress(sqInt lit); static sqInt ffiLoadCalloutModule(sqInt module); static void ffiLogCallout(sqInt lit); EXPORT(sqInt) ffiLogCallsTo(char*fileName); static sqInt ffiPushDoubleFloatin(double value, CalloutState *calloutState); static sqInt ffiPushPointerContentsOfin(sqInt oop, CalloutState *calloutState); static sqInt ffiPushPointerin(void *pointer, CalloutState *calloutState); static sqInt ffiPushSignedBytein(sqInt value, CalloutState *calloutState); static sqInt ffiPushSignedCharin(sqInt value, CalloutState *calloutState); static sqInt ffiPushSignedIntin(sqInt value, CalloutState *calloutState); static sqInt ffiPushSignedLongLongOopin(sqInt oop, CalloutState *calloutState); static sqInt ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState); static sqInt ffiPushSignedShortin(sqInt value, CalloutState *calloutState); static sqInt ffiPushSingleFloatin(float value, CalloutState *calloutState); static sqInt ffiPushStringOfLengthin(char *pointer, sqInt length, CalloutState *calloutState); static sqInt ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState); static sqInt ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState); static sqInt ffiPushUnsignedBytein(sqInt value, CalloutState *calloutState); static sqInt ffiPushUnsignedCharin(sqInt value, CalloutState *calloutState); static sqInt ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState); static sqInt ffiPushUnsignedLongLongOopin(sqInt oop, CalloutState *calloutState); static sqInt ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState); static sqInt ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState); static sqInt ffiPushVoidin(sqInt ignored, CalloutState *calloutState); static sqInt ffiReturnCStringFrom(sqInt cPointer); static sqInt ffiReturnPointerofTypein(usqLong retVal, sqInt retType, CalloutState *calloutState); static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState); static sqInt ffiReturnType(sqInt specOnStack); static sqInt ffiSupportsCallingConvention(sqInt aCallingConvention); static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt isAlien(sqInt anOop); static sqInt isAtomicType(sqInt typeSpec); static sqInt isDirectAlien(sqInt oop); static sqInt msg(char *s); static sqInt nonRegisterStructReturnIsViaImplicitFirstArgument(void); EXPORT(void) primitiveCallout(void); EXPORT(void) primitiveCalloutWithArgs(void); EXPORT(sqInt) primitiveCreateManualSurface(void); EXPORT(sqInt) primitiveDestroyManualSurface(void); EXPORT(sqInt) primitiveFFIAllocate(void); EXPORT(sqInt) primitiveFFIDoubleAt(void); EXPORT(sqInt) primitiveFFIDoubleAtPut(void); EXPORT(sqInt) primitiveFFIFloatAt(void); EXPORT(sqInt) primitiveFFIFloatAtPut(void); EXPORT(sqInt) primitiveFFIFree(void); EXPORT(sqInt) primitiveFFIGetLastError(void); EXPORT(sqInt) primitiveFFIIntegerAt(void); EXPORT(sqInt) primitiveFFIIntegerAtPut(void); EXPORT(sqInt) primitiveForceLoad(void); EXPORT(sqInt) primitiveLogCallsTo(void); EXPORT(sqInt) primitiveSetManualSurfacePointer(void); static sqInt registerArgsSlop(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt sizeField(sqInt oop); static sqInt startOfData(sqInt oop); /*** Variables ***/ static sqInt externalFunctionInstSize; static sqInt ffiLastError; static sqInt ffiLogEnabled; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SqueakFFIPrims VMMaker-oscog.dtl.57 (i)" #else "SqueakFFIPrims VMMaker-oscog.dtl.57 (e)" #endif ; /*** Macros ***/ #define allocaLiesSoUseGetsp() ALLOCA_LIES_SO_USE_GETSP #define cStackAlignment() STACK_ALIGN_BYTES #define dispatchFunctionPointer(aFunctionPointer) (aFunctionPointer)() #define ffiAlloc(bytes) (usqInt)malloc(bytes) #define ffiFree(pointer) free((void *)(pointer)) #define isCalleePopsConvention(callType) (PLATFORM_API_USES_CALLEE_POPS_CONVENTION && (callType) == FFICallTypeApi) #define returnStructInRegisters(sz) (WIN32_X86_STRUCT_RETURN && (sz) <= 8 && !((sz)&((sz)-1))) static sqInt atomicTypeOf(sqInt typeSpec) { return ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; } /* Free any temporary arg strings. */ static void cleanupCalloutState(CalloutState *calloutState) { while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } } static sqInt externalFunctionHasStackSizeSlot(void) { return externalFunctionInstSize > ExternalFunctionStackSizeIndex; } /* return an int of the address of the byteSize slot (byte, short, int, whatever) at byteOffset in rcvr. Nominally intended for use with ExternalAddress objects, this code will work (for obscure historical reasons) with plain Byte or Word Arrays as well. */ static sqInt ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize) { sqInt addr; sqInt rcvrClass; sqInt rcvrSize; if (!(interpreterProxy->isBytes(rcvr))) { return interpreterProxy->primitiveFail(); } if (!(byteOffset > 0)) { return interpreterProxy->primitiveFail(); } rcvrClass = interpreterProxy->fetchClassOf(rcvr); rcvrSize = interpreterProxy->byteSizeOf(rcvr); if (rcvrClass == (interpreterProxy->classExternalAddress())) { if (!(rcvrSize == 4)) { return interpreterProxy->primitiveFail(); } /* don't you dare to read from object memory! */ addr = interpreterProxy->fetchPointerofObject(0, rcvr); if ((addr == 0) || (interpreterProxy->isInMemory(addr))) { return interpreterProxy->primitiveFail(); } } else { if (!(((byteOffset + byteSize) - 1) <= rcvrSize)) { return interpreterProxy->primitiveFail(); } addr = ((int) (interpreterProxy->firstIndexableField(rcvr))); } addr = (addr + byteOffset) - 1; return addr; } /* Support for generic callout. Prepare an argument by value for a callout. */ static sqInt ffiArgByValuein(sqInt oop, CalloutState *calloutState) { sqInt atomicType; double floatValue; sqInt intValue; sqInt oopClass; sqInt oopClass1; sqInt typeSpec; /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiArgHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType < 0) || (atomicType > FFITypeDoubleFloat)) { return FFIErrorBadAtomicType; } if (atomicType < FFITypeSingleFloat) { if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { /* integer types */ /* ffi support code must coerce longlong */ intValue = oop; } else { /* begin ffiIntegerValueOf: */ if ((oop & 1)) { intValue = (oop >> 1); goto l1; } if (oop == (interpreterProxy->nilObject())) { intValue = 0; goto l1; } if (oop == (interpreterProxy->falseObject())) { intValue = 0; goto l1; } if (oop == (interpreterProxy->trueObject())) { intValue = 1; goto l1; } oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { intValue = ((sqInt)(interpreterProxy->floatValueOf(oop))); goto l1; } if (oopClass == (interpreterProxy->classCharacter())) { intValue = interpreterProxy->fetchIntegerofObject(0, oop); goto l1; } if (oopClass == (interpreterProxy->classLargePositiveInteger())) { intValue = interpreterProxy->positive32BitValueOf(oop); goto l1; } intValue = interpreterProxy->signed32BitValueOf(oop); l1: /* end ffiIntegerValueOf: */; } if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } switch (atomicType) { case 0: return FFIErrorAttemptToPassVoid; case 1: return ffiPushUnsignedIntin(intValue, calloutState); case 2: return ffiPushUnsignedBytein(intValue, calloutState); case 3: return ffiPushSignedBytein(intValue, calloutState); case 4: return ffiPushUnsignedShortin(intValue, calloutState); case 5: return ffiPushSignedShortin(intValue, calloutState); case 6: return ffiPushUnsignedIntin(intValue, calloutState); case 7: return ffiPushSignedIntin(intValue, calloutState); case 8: return ffiPushUnsignedLongLongOopin(intValue, calloutState); case 9: return ffiPushSignedLongLongOopin(intValue, calloutState); case 10: return ffiPushUnsignedCharin(intValue, calloutState); case 11: return ffiPushSignedCharin(intValue, calloutState); default: error("Case not found"); return -1; } } /* begin ffiFloatValueOf: */ oopClass1 = interpreterProxy->fetchClassOf(oop); if (oopClass1 == (interpreterProxy->classFloat())) { floatValue = interpreterProxy->floatValueOf(oop); goto l2; } floatValue = ((double) (ffiIntegerValueOf(oop)) ); l2: /* end ffiFloatValueOf: */; if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } if (atomicType == FFITypeSingleFloat) { /* begin ffiPushSingleFloat:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } else { /* begin ffiPushDoubleFloat:in: */ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeFloatAtPointerfrom((calloutState->currentArg), floatValue); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } } /* Callout support. Prepare the given oop as argument. argSpec defines the compiled spec for the argument. argClass (if non-nil) defines the required (super)class for the argument. */ static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState) { sqInt *argSpec1; sqInt *argSpec2; sqInt argSpecSize; sqInt argSpecSize1; sqInt atomicType; sqInt atomicType1; sqInt atomicType2; char *copy; sqInt err; double floatValue; sqInt intValue; sqInt isAlien; sqInt isString; sqInt isStruct; sqInt length; sqInt nilOop; sqInt oopClass; sqInt oopClass1; sqInt oopClass2; char *pointer; void *pointer1; void *pointer2; void *pointer3; sqInt ptrAddress; sqInt ptrClass; sqInt ptrType; sqInt roundedSize; sqInt roundedSize1; sqInt spec; sqInt specOop; sqInt specType; sqInt structSize; sqInt structSize1; sqInt typeSpec; sqInt typeSpec1; sqInt typeSpec2; sqInt valueOop; sqInt valueOop1; /* Prefetch class (we'll need it) */ oopClass = interpreterProxy->fetchClassOf(oop); /* Do the necessary type checks */ nilOop = interpreterProxy->nilObject(); if (!(argClass == nilOop)) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { return FFIErrorWrongType; } if (!((nilOop == oop) || (interpreterProxy->includesBehaviorThatOf(oopClass, argClass)))) { return FFIErrorCoercionFailed; } } isStruct = 0; if (!(((oop & 1)) || (oop == nilOop))) { if (interpreterProxy->isPointers(oop)) { /* #isPointers: will fail if oop is SmallInteger so don't even attempt to use it */ isStruct = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classExternalStructure()); if (!((argClass == nilOop) || (isStruct))) { return FFIErrorCoercionFailed; } } } if (isStruct) { valueOop = interpreterProxy->fetchPointerofObject(0, oop); } else { valueOop = oop; } if ((argSpec & 1)) { return FFIErrorWrongType; } if (!(interpreterProxy->isWords(argSpec))) { return FFIErrorWrongType; } (calloutState->ffiArgSpecSize = interpreterProxy->slotSizeOf(argSpec)); if (((calloutState->ffiArgSpecSize)) == 0) { return FFIErrorWrongType; } (calloutState->ffiArgSpec = interpreterProxy->firstIndexableField(argSpec)); (calloutState->ffiArgHeader = longAt((calloutState->ffiArgSpec))); if (((calloutState->ffiArgHeader)) & FFIFlagStructure) { if (!(isStruct)) { return FFIErrorCoercionFailed; } if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) { return FFIErrorWrongType; } /* begin ffiPushStructureContentsOf:in: */ ptrClass = interpreterProxy->fetchClassOf(valueOop); if (ptrClass == (interpreterProxy->classExternalAddress())) { /* ExternalAddress is bytes */ /* There is no way we can make sure the structure is valid. But we can at least check for attempts to pass pointers to ST memory. */ ptrAddress = interpreterProxy->fetchPointerofObject(0, valueOop); if (interpreterProxy->isInMemory(ptrAddress)) { return FFIErrorInvalidPointer; } /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */ structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask; argSpec2 = (calloutState->ffiArgSpec); argSpecSize = (calloutState->ffiArgSpecSize); roundedSize = (structSize + 3) & (~3); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); return 0; } if (ptrClass == (interpreterProxy->classByteArray())) { if (!((interpreterProxy->byteSizeOf(valueOop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) { return FFIErrorStructSize; } ptrAddress = ((int) (interpreterProxy->firstIndexableField(valueOop))); if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) { /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */ structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask; argSpec1 = (calloutState->ffiArgSpec); argSpecSize1 = (calloutState->ffiArgSpecSize); roundedSize1 = (structSize1 + 3) & (~3); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) { return FFIErrorStructSize; } ptrAddress = interpreterProxy->fetchPointerofObject(0, valueOop); if (interpreterProxy->isInMemory(ptrAddress)) { return FFIErrorInvalidPointer; } /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } return FFIErrorBadArg; } if (((calloutState->ffiArgHeader)) & FFIFlagPointer) { if ((oop & 1)) { return FFIErrorIntAsPointer; } if (oop == (interpreterProxy->nilObject())) { /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), null); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) { if (isStruct) { /* begin ffiAtomicStructByReference:Class:in: */ if (!(oopClass == (interpreterProxy->classExternalData()))) { return FFIErrorCoercionFailed; } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiArgHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType != FFITypeVoid) { /* begin ffiValidateExternalData:AtomicType: */ ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { err = FFIErrorWrongType; goto l3; } if (!(interpreterProxy->isPointers(ptrType))) { err = FFIErrorWrongType; goto l3; } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { err = FFIErrorWrongType; goto l3; } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { err = FFIErrorWrongType; goto l3; } if (!(interpreterProxy->isWords(specOop))) { err = FFIErrorWrongType; goto l3; } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { err = FFIErrorWrongType; goto l3; } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { err = FFIErrorWrongType; goto l3; } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { err = FFIErrorCoercionFailed; goto l3; } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { err = FFIErrorCoercionFailed; goto l3; } } err = 0; l3: /* end ffiValidateExternalData:AtomicType: */; if (err != 0) { return err; } } valueOop1 = interpreterProxy->fetchPointerofObject(0, oop); return ffiPushPointerContentsOfin(valueOop1, calloutState); } else { /* begin ffiAtomicArgByReference:Class:in: */ /* begin atomicTypeOf: */ typeSpec2 = (calloutState->ffiArgHeader); atomicType2 = ((usqInt) (typeSpec2 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType2 == FFITypeBool) { return FFIErrorCoercionFailed; } isAlien = ((isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString())) ? 0 : interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classAlien())); if ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { if (isString) { /* begin ffiPushString:OfLength:in: */ pointer = interpreterProxy->firstIndexableField(oop); length = interpreterProxy->byteSizeOf(oop); if (((calloutState->stringArgIndex)) >= MaxNumArgs) { return -PrimErrBadNumArgs; } copy = malloc(length + 1); if (copy == null) { return -PrimErrNoCMemory; } memcpy(copy, pointer, length); copy[length] = 0; ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy; (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1); /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), copy); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } atomicType2 = FFITypeUnsignedByte; } if ((atomicType2 == FFITypeVoid) || ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) { if (isString || (oopClass == (interpreterProxy->classByteArray()))) { /* begin ffiPushPointer:in: */ pointer1 = interpreterProxy->firstIndexableField(oop); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer1); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (isAlien) { /* begin ffiPushPointer:in: */ pointer2 = pointerForIndex_xxx_dmu(((longAt(oop + BaseHeaderSize)) > 0 ? (oop + BaseHeaderSize) + BytesPerOop : longAt((oop + BaseHeaderSize) + BytesPerOop))); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer2); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (!(atomicType2 == FFITypeVoid)) { return FFIErrorCoercionFailed; } } if ((atomicType2 <= FFITypeSignedInt) || (atomicType2 == FFITypeSingleFloat)) { if (interpreterProxy->isWords(oop)) { /* begin ffiPushPointer:in: */ pointer3 = interpreterProxy->firstIndexableField(oop); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer3); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } } return FFIErrorCoercionFailed; } } if (!(isStruct)) { return FFIErrorCoercionFailed; } return ffiPushPointerContentsOfin(valueOop, calloutState); } if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) { /* begin ffiArgByValue:in: */ /* begin atomicTypeOf: */ typeSpec1 = (calloutState->ffiArgHeader); atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType1 < 0) || (atomicType1 > FFITypeDoubleFloat)) { return FFIErrorBadAtomicType; } if (atomicType1 < FFITypeSingleFloat) { if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { /* integer types */ /* ffi support code must coerce longlong */ intValue = valueOop; } else { /* begin ffiIntegerValueOf: */ if ((valueOop & 1)) { intValue = (valueOop >> 1); goto l1; } if (valueOop == (interpreterProxy->nilObject())) { intValue = 0; goto l1; } if (valueOop == (interpreterProxy->falseObject())) { intValue = 0; goto l1; } if (valueOop == (interpreterProxy->trueObject())) { intValue = 1; goto l1; } oopClass2 = interpreterProxy->fetchClassOf(valueOop); if (oopClass2 == (interpreterProxy->classFloat())) { intValue = ((sqInt)(interpreterProxy->floatValueOf(valueOop))); goto l1; } if (oopClass2 == (interpreterProxy->classCharacter())) { intValue = interpreterProxy->fetchIntegerofObject(0, valueOop); goto l1; } if (oopClass2 == (interpreterProxy->classLargePositiveInteger())) { intValue = interpreterProxy->positive32BitValueOf(valueOop); goto l1; } intValue = interpreterProxy->signed32BitValueOf(valueOop); l1: /* end ffiIntegerValueOf: */; } if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } switch (atomicType1) { case 0: return FFIErrorAttemptToPassVoid; case 1: return ffiPushUnsignedIntin(intValue, calloutState); case 2: return ffiPushUnsignedBytein(intValue, calloutState); case 3: return ffiPushSignedBytein(intValue, calloutState); case 4: return ffiPushUnsignedShortin(intValue, calloutState); case 5: return ffiPushSignedShortin(intValue, calloutState); case 6: return ffiPushUnsignedIntin(intValue, calloutState); case 7: return ffiPushSignedIntin(intValue, calloutState); case 8: return ffiPushUnsignedLongLongOopin(intValue, calloutState); case 9: return ffiPushSignedLongLongOopin(intValue, calloutState); case 10: return ffiPushUnsignedCharin(intValue, calloutState); case 11: return ffiPushSignedCharin(intValue, calloutState); default: error("Case not found"); return -1; } } /* begin ffiFloatValueOf: */ oopClass1 = interpreterProxy->fetchClassOf(valueOop); if (oopClass1 == (interpreterProxy->classFloat())) { floatValue = interpreterProxy->floatValueOf(valueOop); goto l2; } floatValue = ((double) (ffiIntegerValueOf(valueOop)) ); l2: /* end ffiFloatValueOf: */; if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } if (atomicType1 == FFITypeSingleFloat) { /* begin ffiPushSingleFloat:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } else { /* begin ffiPushDoubleFloat:in: */ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeFloatAtPointerfrom((calloutState->currentArg), floatValue); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } } return FFIErrorWrongType; } /* Support for generic callout. Prepare a pointer reference to an atomic type for callout. Note: for type 'void*' we allow ByteArray/String/Symbol, wordVariableSubclass or Alien. */ static sqInt ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState) { sqInt atomicType; char *copy; sqInt isAlien; sqInt isString; sqInt length; char *pointer; void *pointer1; void *pointer2; void *pointer3; sqInt typeSpec; /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiArgHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType == FFITypeBool) { return FFIErrorCoercionFailed; } isAlien = ((isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString())) ? 0 : interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classAlien())); if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { if (isString) { /* begin ffiPushString:OfLength:in: */ pointer = interpreterProxy->firstIndexableField(oop); length = interpreterProxy->byteSizeOf(oop); if (((calloutState->stringArgIndex)) >= MaxNumArgs) { return -PrimErrBadNumArgs; } copy = malloc(length + 1); if (copy == null) { return -PrimErrNoCMemory; } memcpy(copy, pointer, length); copy[length] = 0; ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy; (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1); /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), copy); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } atomicType = FFITypeUnsignedByte; } if ((atomicType == FFITypeVoid) || ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) { if (isString || (oopClass == (interpreterProxy->classByteArray()))) { /* begin ffiPushPointer:in: */ pointer1 = interpreterProxy->firstIndexableField(oop); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer1); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (isAlien) { /* begin ffiPushPointer:in: */ pointer2 = pointerForIndex_xxx_dmu(((longAt(oop + BaseHeaderSize)) > 0 ? (oop + BaseHeaderSize) + BytesPerOop : longAt((oop + BaseHeaderSize) + BytesPerOop))); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer2); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (!(atomicType == FFITypeVoid)) { return FFIErrorCoercionFailed; } } if ((atomicType <= FFITypeSignedInt) || (atomicType == FFITypeSingleFloat)) { if (interpreterProxy->isWords(oop)) { /* begin ffiPushPointer:in: */ pointer3 = interpreterProxy->firstIndexableField(oop); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer3); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } } return FFIErrorCoercionFailed; } /* Support for generic callout. Prepare an external pointer reference to an atomic type for callout. */ static sqInt ffiAtomicStructByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState) { sqInt atomicType; sqInt err; sqInt ptrType; sqInt spec; sqInt specOop; sqInt specType; sqInt typeSpec; sqInt valueOop; if (!(oopClass == (interpreterProxy->classExternalData()))) { return FFIErrorCoercionFailed; } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiArgHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType != FFITypeVoid) { /* begin ffiValidateExternalData:AtomicType: */ ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { err = FFIErrorWrongType; goto l1; } if (!(interpreterProxy->isPointers(ptrType))) { err = FFIErrorWrongType; goto l1; } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { err = FFIErrorWrongType; goto l1; } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { err = FFIErrorWrongType; goto l1; } if (!(interpreterProxy->isWords(specOop))) { err = FFIErrorWrongType; goto l1; } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { err = FFIErrorWrongType; goto l1; } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { err = FFIErrorWrongType; goto l1; } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { err = FFIErrorCoercionFailed; goto l1; } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { err = FFIErrorCoercionFailed; goto l1; } } err = 0; l1: /* end ffiValidateExternalData:AtomicType: */; if (err != 0) { return err; } } valueOop = interpreterProxy->fetchPointerofObject(0, oop); return ffiPushPointerContentsOfin(valueOop, calloutState); } /* Go out, call this guy and create the return value. This *must* be inlined because of the alloca of the outgoing stack frame in ffiCall:WithFlags:NumArgs:Args:AndTypes: */ static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState) { sqInt argTypes; sqInt argTypes1; sqInt atomicType; sqInt atomicType1; sqInt classOop; char *cString; sqInt ffiRetType; double floatRet; sqInt i; usqLong intRet; sqInt oop; sqInt oop1; sqInt *ptr; sqInt retClass; sqInt retClass1; sqInt retOop; sqInt retOop1; sqInt retType; sqInt specLiteral; sqInt specLiteral1; sqInt strLen; sqInt strOop; char *strPtr; sqInt typeSpec; sqInt typeSpec1; if ((0 + (cStackAlignment())) > 0) { setsp((calloutState->argVector)); } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiRetHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { floatRet = dispatchFunctionPointer(((double (*)()) procAddr)); } else { intRet = dispatchFunctionPointer(((usqLong (*)()) procAddr)); } if (isCalleePopsConvention((calloutState->callFlags))) { setsp((calloutState->argVector)); } if (((calloutState->ffiRetHeader)) & FFIFlagPointer) { /* begin ffiReturnPointer:ofType:in: */ /* begin ffiReturnType: */ specLiteral1 = (specOnStack ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1); retType = interpreterProxy->fetchPointerofObject(0, argTypes1); retClass1 = interpreterProxy->fetchPointerofObject(1, retType); if (retClass1 == (interpreterProxy->nilObject())) { /* begin atomicTypeOf: */ typeSpec1 = (calloutState->ffiRetHeader); atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* begin ffiReturnCStringFrom: */ if ((((usqInt) intRet)) == null) { return interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); } cString = ((char *) (((usqInt) intRet))); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i = 0; i <= (strLen - 1); i += 1) { strPtr[i] = (cString[i]); } return interpreterProxy->methodReturnValue(strOop); } interpreterProxy->pushRemappableOop(retType); oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr = interpreterProxy->firstIndexableField(oop1); ptr[0] = (((sqInt) intRet)); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); /* return type */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1); return interpreterProxy->methodReturnValue(retOop1); } interpreterProxy->pushRemappableOop(retClass1); if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr = interpreterProxy->firstIndexableField(oop1); ptr[0] = (((sqInt) intRet)); /* return class */ retClass1 = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); return interpreterProxy->methodReturnValue(retOop1); } if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { /* begin ffiReturnStruct:ofType:in: */ /* begin ffiReturnType: */ specLiteral = (specOnStack ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral); ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes); retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); interpreterProxy->pushRemappableOop(retOop); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize)); if (returnStructInRegisters((calloutState->structReturnSize))) { memcpy(interpreterProxy->firstIndexableField(oop), (&intRet), (calloutState->structReturnSize)); } else { memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize)); } retOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->methodReturnValue(retOop); } if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { return interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet)); } return interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState)); } /* Generic callout. Does the actual work. If argArrayOrNil is nil it takes args from the stack and the spec from the method. If argArrayOrNil is not nil takes args from argArrayOrNil and the spec from the receiver. */ static sqInt ffiCallArgArrayOrNilNumArgs(sqInt externalFunction, sqInt argArrayOrNil, sqInt nArgs) { sqInt address; sqInt address1; sqInt addressPtr; char *allocation; sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypeArray; sqInt argTypes; sqInt argTypes1; sqInt atomicType; sqInt atomicType1; CalloutState *calloutState; sqInt classOop; char *cString; sqInt err; sqInt ffiRetType; sqInt flags; double floatRet; sqInt functionName; sqInt i; sqInt i1; usqLong intRet; sqInt oop; sqInt oop1; sqInt oop2; void *pointer; int *ptr; sqInt *ptr1; sqInt requiredStackSize; sqInt result; sqInt retClass; sqInt retClass1; sqInt retOop; sqInt retOop1; sqInt retType; sqInt specLiteral; sqInt specLiteral1; sqInt stackSize; sqInt strLen; sqInt strOop; char *strPtr; CalloutState theCalloutState; sqInt typeSpec; sqInt typeSpec1; if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) { return ffiFail(FFIErrorNotFunction); } flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (interpreterProxy->failed()) { return ffiFail(FFIErrorBadArgs); } /* must be array of arg types */ argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction); if (!((interpreterProxy->isArray(argTypeArray)) && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) { return ffiFail(FFIErrorBadArgs); } if (!(1)) { return ffiFail(FFIErrorCallType); } /* begin ffiLoadCalloutAddress: */ /* Lookup the address */ /* Make sure it's an external handle */ addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction); /* begin ffiContentsOfHandle:errCode: */ if ((addressPtr & 1)) { address1 = ffiFail(FFIErrorBadAddress); goto l3; } if (!(interpreterProxy->isBytes(addressPtr))) { address1 = ffiFail(FFIErrorBadAddress); goto l3; } if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) { address1 = ffiFail(FFIErrorBadAddress); goto l3; } address1 = interpreterProxy->fetchPointerofObject(0, addressPtr); l3: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { address = 0; goto l4; } if (address1 == 0) { if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) { interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1)); } if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) { address = ffiFail(FFIErrorNoModule); goto l4; } address1 = ffiLoadCalloutAddressFrom(externalFunction); if (interpreterProxy->failed()) { address = 0; goto l4; } ptr = interpreterProxy->firstIndexableField(addressPtr); ptr[0] = address1; } address = address1; l4: /* end ffiLoadCalloutAddress: */; if (interpreterProxy->failed()) { return 0; } requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex ? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction) : -1); if (interpreterProxy->failed()) { return interpreterProxy->primitiveFailFor((argArrayOrNil == null ? PrimErrBadMethod : PrimErrBadReceiver)); } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize : requiredStackSize); null; calloutState = (&theCalloutState); memset(calloutState, 0, sizeof(CalloutState)); ; (calloutState->callFlags = flags); argType = interpreterProxy->fetchPointerofObject(0, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { return ffiFail(err); } allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment())); if (allocaLiesSoUseGetsp()) { allocation = getsp(); } if ((cStackAlignment()) != 0) { allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1)))); } (calloutState->argVector = allocation); (calloutState->currentArg = allocation + 0); (calloutState->limit = (allocation + stackSize) + 0); if ((((calloutState->structReturnSize)) > 0) && (1 && (!(returnStructInRegisters((calloutState->structReturnSize)))))) { /* begin ffiPushPointer:in: */ pointer = (calloutState->limit); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { goto l1; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + 4); l1: /* end ffiPushPointer:in: */; } for (i = 1; i <= nArgs; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = (argArrayOrNil == null ? interpreterProxy->stackValue(nArgs - i) : interpreterProxy->fetchPointerofObject(i - 1, argArrayOrNil)); err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState); if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } return ffiFail(err); } } assert(!(interpreterProxy->failed())); /* begin ffiLogCallout: */ if (ffiLogEnabled) { functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction); if (!(interpreterProxy->isBytes(functionName))) { goto l2; } ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName)); } l2: /* end ffiLogCallout: */; if ((requiredStackSize < 0) && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) { stackSize = ((calloutState->currentArg)) - ((calloutState->argVector)); interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize); } /* begin ffiCalloutTo:SpecOnStack:in: */ if ((0 + (cStackAlignment())) > 0) { setsp((calloutState->argVector)); } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiRetHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { floatRet = dispatchFunctionPointer(((double (*)()) address)); } else { intRet = dispatchFunctionPointer(((usqLong (*)()) address)); } if (isCalleePopsConvention((calloutState->callFlags))) { setsp((calloutState->argVector)); } if (((calloutState->ffiRetHeader)) & FFIFlagPointer) { /* begin ffiReturnPointer:ofType:in: */ /* begin ffiReturnType: */ specLiteral1 = (argArrayOrNil != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1); retType = interpreterProxy->fetchPointerofObject(0, argTypes1); retClass1 = interpreterProxy->fetchPointerofObject(1, retType); if (retClass1 == (interpreterProxy->nilObject())) { /* begin atomicTypeOf: */ typeSpec1 = (calloutState->ffiRetHeader); atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* begin ffiReturnCStringFrom: */ if ((((usqInt) intRet)) == null) { result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); goto l5; } cString = ((char *) (((usqInt) intRet))); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i1 = 0; i1 <= (strLen - 1); i1 += 1) { strPtr[i1] = (cString[i1]); } result = interpreterProxy->methodReturnValue(strOop); goto l5; } interpreterProxy->pushRemappableOop(retType); oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); /* return type */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l5; } interpreterProxy->pushRemappableOop(retClass1); if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); /* return class */ retClass1 = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l5; } if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { /* begin ffiReturnStruct:ofType:in: */ /* begin ffiReturnType: */ specLiteral = (argArrayOrNil != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral); ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes); retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); interpreterProxy->pushRemappableOop(retOop); oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize)); if (returnStructInRegisters((calloutState->structReturnSize))) { memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize)); } else { memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize)); } retOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2); result = interpreterProxy->methodReturnValue(retOop); goto l5; } if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet)); goto l5; } result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState)); l5: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } return result; } /* Make sure we can return an object of the given type */ static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState) { sqInt ffiRetSpec; if (!(retClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(retClass, interpreterProxy->classExternalStructure()))) { return FFIErrorBadReturn; } } if (!(interpreterProxy->isWords(retSpec))) { return FFIErrorWrongType; } if ((interpreterProxy->slotSizeOf(retSpec)) == 0) { return FFIErrorWrongType; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(retSpec))); (calloutState->ffiRetHeader = longAt(ffiRetSpec)); if (!(isAtomicType((calloutState->ffiRetHeader)))) { if (retClass == (interpreterProxy->nilObject())) { return FFIErrorBadReturn; } } if ((((calloutState->ffiRetHeader)) & (FFIFlagPointer | FFIFlagStructure)) == FFIFlagStructure) { (calloutState->structReturnSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask); } return 0; } /* Make sure that the given oop is a valid external handle */ static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode) { if ((oop & 1)) { return ffiFail(errCode); } if (!(interpreterProxy->isBytes(oop))) { return ffiFail(errCode); } if (!((interpreterProxy->byteSizeOf(oop)) == 4)) { return ffiFail(errCode); } return interpreterProxy->fetchPointerofObject(0, oop); } /* Callout support. Return the appropriate oop for the given atomic type */ static sqInt ffiCreateIntegralResultOopofAtomicTypein(usqLong retVal, sqInt atomicType, CalloutState *calloutState) { sqInt byteSize; sqInt mask; sqInt shift; sqInt value; assert(atomicType < FFITypeSingleFloat); if (atomicType == FFITypeBool) { /* Make sure bool honors the byte size requested */ byteSize = ((calloutState->ffiRetHeader)) & FFIStructSizeMask; value = (byteSize == 4 ? retVal : retVal & ((1 << (byteSize * 8)) - 1)); return (value == 0 ? interpreterProxy->falseObject() : interpreterProxy->trueObject()); } if (atomicType <= FFITypeSignedInt) { if (atomicType <= FFITypeSignedShort) { /* these are all generall integer returns */ /* byte/short. first extract partial word, then sign extend */ /* # of significant bits */ shift = (((usqInt) atomicType) >> 1) * 8; value = retVal & ((1 << shift) - 1); if (atomicType & 1) { /* make the guy signed */ mask = 1 << (shift - 1); value = (value & (mask - 1)) - (value & mask); } return ((value << 1) | 1); } return (atomicType & 1 ? interpreterProxy->signed32BitIntegerFor(retVal) : interpreterProxy->positive32BitIntegerFor(retVal)); } if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { return (atomicType & 1 ? interpreterProxy->signed64BitIntegerFor(retVal) : interpreterProxy->positive64BitIntegerFor(retVal)); } else { return interpreterProxy->fetchPointerofObject(retVal & 255, interpreterProxy->characterTable()); } } /* Map the FFI error code into a primitive error code. If reason is negative it encodes one of the standard PrimErr... codes, negated to distinguish it from the FFIError codes. If it is an FFIError... code then add the size of the primitive error table + 2 to disambiguate it from the PrimErr... codes. For historic reasons the FFIError codes range from -1 on up hence adding size + 2 maps them to size of table + 1 on up. This OFFSET IS undone by ExternalFunction class>>externalCallFailedWith:. Thus we can communicate back both PrimErr.. and FFIError codes. Complex but necessary. */ static sqInt ffiFail(sqInt reason) { ffiLastError = reason; return interpreterProxy->primitiveFailFor((reason >= FFINoCalloutAvailable ? (reason + 2) + (interpreterProxy->slotSizeOf(interpreterProxy->primitiveErrorTable())) : -reason)); } /* Support for generic callout. Return a float value that is coerced as C would do. */ static double ffiFloatValueOf(sqInt oop) { sqInt oopClass; oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { return interpreterProxy->floatValueOf(oop); } return ((double) (ffiIntegerValueOf(oop)) ); } /* Support for generic callout. Return an integer value that is coerced as C would do. */ static sqInt ffiIntegerValueOf(sqInt oop) { sqInt oopClass; if ((oop & 1)) { return (oop >> 1); } if (oop == (interpreterProxy->nilObject())) { return 0; } if (oop == (interpreterProxy->falseObject())) { return 0; } if (oop == (interpreterProxy->trueObject())) { return 1; } oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { return ((sqInt)(interpreterProxy->floatValueOf(oop))); } if (oopClass == (interpreterProxy->classCharacter())) { return interpreterProxy->fetchIntegerofObject(0, oop); } if (oopClass == (interpreterProxy->classLargePositiveInteger())) { return interpreterProxy->positive32BitValueOf(oop); } return interpreterProxy->signed32BitValueOf(oop); } /* Load the function address for a call out to an external function */ static sqInt ffiLoadCalloutAddressFrom(sqInt oop) { sqInt address; sqInt ffiModuleName; sqInt functionLength; sqInt functionName; sqInt module; sqInt moduleHandle; sqInt moduleHandle1; sqInt moduleHandlePtr; sqInt moduleLength; int *ptr; sqInt rcvr; /* First find and load the module */ module = interpreterProxy->fetchPointerofObject(externalFunctionInstSize + 1, oop); /* begin ffiLoadCalloutModule: */ if (interpreterProxy->isBytes(module)) { /* plain module name */ ffiModuleName = module; moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle1 = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if ((interpreterProxy->failed()) || (moduleHandle1 == 0)) { moduleHandle = ffiFail(FFIErrorModuleNotFound); goto l2; } moduleHandle = moduleHandle1; goto l2; } rcvr = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); if (!(interpreterProxy->isKindOfClass(rcvr, interpreterProxy->classExternalLibrary()))) { moduleHandle = ffiFail(FFIErrorNoModule); goto l2; } moduleHandlePtr = interpreterProxy->fetchPointerofObject(0, rcvr); /* begin ffiContentsOfHandle:errCode: */ if ((moduleHandlePtr & 1)) { moduleHandle1 = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!(interpreterProxy->isBytes(moduleHandlePtr))) { moduleHandle1 = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!((interpreterProxy->byteSizeOf(moduleHandlePtr)) == 4)) { moduleHandle1 = ffiFail(FFIErrorBadExternalLibrary); goto l1; } moduleHandle1 = interpreterProxy->fetchPointerofObject(0, moduleHandlePtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { moduleHandle = 0; goto l2; } if (moduleHandle1 == 0) { /* need to reload module */ ffiModuleName = interpreterProxy->fetchPointerofObject(1, rcvr); if (!(interpreterProxy->isBytes(ffiModuleName))) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l2; } moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle1 = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if ((interpreterProxy->failed()) || (moduleHandle1 == 0)) { moduleHandle = ffiFail(FFIErrorModuleNotFound); goto l2; } ptr = interpreterProxy->firstIndexableField(moduleHandlePtr); ptr[0] = moduleHandle1; } moduleHandle = moduleHandle1; l2: /* end ffiLoadCalloutModule: */; if (interpreterProxy->failed()) { return 0; } functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, oop); if (!(interpreterProxy->isBytes(functionName))) { return ffiFail(FFIErrorBadExternalFunction); } functionLength = interpreterProxy->byteSizeOf(functionName); address = interpreterProxy->ioLoadSymbolOfLengthFromModule(((int) (interpreterProxy->firstIndexableField(functionName))), functionLength, moduleHandle); if ((interpreterProxy->failed()) || (address == 0)) { return ffiFail(FFIErrorAddressNotFound); } return address; } /* Load the address of the foreign function from the given object */ static sqInt ffiLoadCalloutAddress(sqInt lit) { sqInt address; sqInt addressPtr; int *ptr; /* Lookup the address */ /* Make sure it's an external handle */ addressPtr = interpreterProxy->fetchPointerofObject(0, lit); /* begin ffiContentsOfHandle:errCode: */ if ((addressPtr & 1)) { address = ffiFail(FFIErrorBadAddress); goto l1; } if (!(interpreterProxy->isBytes(addressPtr))) { address = ffiFail(FFIErrorBadAddress); goto l1; } if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) { address = ffiFail(FFIErrorBadAddress); goto l1; } address = interpreterProxy->fetchPointerofObject(0, addressPtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } if (address == 0) { if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) { interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, lit, ((-1 << 1) | 1)); } if ((interpreterProxy->slotSizeOf(lit)) < 5) { return ffiFail(FFIErrorNoModule); } address = ffiLoadCalloutAddressFrom(lit); if (interpreterProxy->failed()) { return 0; } ptr = interpreterProxy->firstIndexableField(addressPtr); ptr[0] = address; } return address; } /* Load the given module and return its handle */ static sqInt ffiLoadCalloutModule(sqInt module) { sqInt ffiModuleName; sqInt moduleHandle; sqInt moduleHandlePtr; sqInt moduleLength; int *ptr; sqInt rcvr; if (interpreterProxy->isBytes(module)) { /* plain module name */ ffiModuleName = module; moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if ((interpreterProxy->failed()) || (moduleHandle == 0)) { return ffiFail(FFIErrorModuleNotFound); } return moduleHandle; } rcvr = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); if (!(interpreterProxy->isKindOfClass(rcvr, interpreterProxy->classExternalLibrary()))) { return ffiFail(FFIErrorNoModule); } moduleHandlePtr = interpreterProxy->fetchPointerofObject(0, rcvr); /* begin ffiContentsOfHandle:errCode: */ if ((moduleHandlePtr & 1)) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!(interpreterProxy->isBytes(moduleHandlePtr))) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!((interpreterProxy->byteSizeOf(moduleHandlePtr)) == 4)) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } moduleHandle = interpreterProxy->fetchPointerofObject(0, moduleHandlePtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } if (moduleHandle == 0) { /* need to reload module */ ffiModuleName = interpreterProxy->fetchPointerofObject(1, rcvr); if (!(interpreterProxy->isBytes(ffiModuleName))) { return ffiFail(FFIErrorBadExternalLibrary); } moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if ((interpreterProxy->failed()) || (moduleHandle == 0)) { return ffiFail(FFIErrorModuleNotFound); } ptr = interpreterProxy->firstIndexableField(moduleHandlePtr); ptr[0] = moduleHandle; } return moduleHandle; } /* fetch the function name */ static void ffiLogCallout(sqInt lit) { sqInt functionName; if (ffiLogEnabled) { functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, lit); if (!(interpreterProxy->isBytes(functionName))) { return; } ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName)); } } /* This is a special entry point exposed such that client code can enable and disable logging of FFI calls. */ EXPORT(sqInt) ffiLogCallsTo(char*fileName) { sqInt ok; if (fileName == null) { /* disable logging */ ok = ffiLogFileNameOfLength(null, 0); if (!(ok)) { return 0; } ffiLogEnabled = 0; } else { /* enable logging */ ok = ffiLogFileNameOfLength(fileName, strlen(fileName)); if (!(ok)) { return 0; } ffiLogEnabled = 1; } return 1; } static sqInt ffiPushDoubleFloatin(double value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeFloatAtPointerfrom((calloutState->currentArg), value); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } /* Push the contents of the given external structure */ static sqInt ffiPushPointerContentsOfin(sqInt oop, CalloutState *calloutState) { sqInt ptrAddress; sqInt ptrClass; ptrClass = interpreterProxy->fetchClassOf(oop); if (ptrClass == (interpreterProxy->classExternalAddress())) { /* Don't you dare to pass pointers into object memory */ ptrAddress = interpreterProxy->fetchPointerofObject(0, oop); if (interpreterProxy->isInMemory(ptrAddress)) { return FFIErrorInvalidPointer; } /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (ptrClass == (interpreterProxy->classByteArray())) { ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop))); /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } if (interpreterProxy->includesBehaviorThatOf(ptrClass, interpreterProxy->classAlien())) { ptrAddress = ((longAt(oop + BaseHeaderSize)) > 0 ? (oop + BaseHeaderSize) + BytesPerOop : longAt((oop + BaseHeaderSize) + BytesPerOop)); /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } return FFIErrorBadArg; } static sqInt ffiPushPointerin(void *pointer, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushSignedBytein(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((signed char) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushSignedCharin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((signed char) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushSignedIntin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), value); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } /* Push a longlong type (e.g., a 64bit integer). Note: Coercions from float are *not* supported. */ static sqInt ffiPushSignedLongLongOopin(sqInt oop, CalloutState *calloutState) { sqLong value; if ((oop == (interpreterProxy->nilObject())) || (oop == (interpreterProxy->falseObject()))) { value = 0; } else { if (oop == (interpreterProxy->trueObject())) { value = 1; } else { value = interpreterProxy->signed64BitValueOf(oop); if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } } } /* begin ffiPushSignedLongLong:in: */ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((usqInt) value)); longAtput(((calloutState->currentArg)) + 4, ((usqInt) (((unsigned sqLong )value) >> 32))); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } static sqInt ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((usqInt) value)); longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32))); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } static sqInt ffiPushSignedShortin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((signed short) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushSingleFloatin(float value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } storeSingleFloatAtPointerfrom((calloutState->currentArg), value); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushStringOfLengthin(char *pointer, sqInt length, CalloutState *calloutState) { char *copy; if (((calloutState->stringArgIndex)) >= MaxNumArgs) { return -PrimErrBadNumArgs; } copy = malloc(length + 1); if (copy == null) { return -PrimErrNoCMemory; } memcpy(copy, pointer, length); copy[length] = 0; ((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy; (calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1); /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), copy); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } /* Push the contents of the given external structure */ static sqInt ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState) { sqInt *argSpec; sqInt *argSpec1; sqInt argSpecSize; sqInt argSpecSize1; sqInt ptrAddress; sqInt ptrClass; sqInt roundedSize; sqInt roundedSize1; sqInt structSize; sqInt structSize1; ptrClass = interpreterProxy->fetchClassOf(oop); if (ptrClass == (interpreterProxy->classExternalAddress())) { /* ExternalAddress is bytes */ /* There is no way we can make sure the structure is valid. But we can at least check for attempts to pass pointers to ST memory. */ ptrAddress = interpreterProxy->fetchPointerofObject(0, oop); if (interpreterProxy->isInMemory(ptrAddress)) { return FFIErrorInvalidPointer; } /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */ structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask; argSpec = (calloutState->ffiArgSpec); argSpecSize = (calloutState->ffiArgSpecSize); roundedSize = (structSize + 3) & (~3); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); return 0; } if (ptrClass == (interpreterProxy->classByteArray())) { if (!((interpreterProxy->byteSizeOf(oop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) { return FFIErrorStructSize; } ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop))); if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) { /* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */ structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask; argSpec1 = (calloutState->ffiArgSpec); argSpecSize1 = (calloutState->ffiArgSpecSize); roundedSize1 = (structSize1 + 3) & (~3); if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1); return 0; } if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) { return FFIErrorStructSize; } ptrAddress = interpreterProxy->fetchPointerofObject(0, oop); if (interpreterProxy->isInMemory(ptrAddress)) { return FFIErrorInvalidPointer; } /* begin ffiPushPointer:in: */ if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ptrAddress); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } return FFIErrorBadArg; } static sqInt ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState) { sqInt roundedSize; roundedSize = (structSize + 3) & (~3); if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } memcpy((calloutState->currentArg), pointer, structSize); (calloutState->currentArg = ((calloutState->currentArg)) + roundedSize); return 0; } static sqInt ffiPushUnsignedBytein(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((unsigned char) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushUnsignedCharin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((unsigned char) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } static sqInt ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), value); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } /* Push an unsigned longlong type (e.g., a 64bit integer). Note: Coercions from float are *not* supported. */ static sqInt ffiPushUnsignedLongLongOopin(sqInt oop, CalloutState *calloutState) { usqLong value; if ((oop == (interpreterProxy->nilObject())) || (oop == (interpreterProxy->falseObject()))) { value = 0; } else { if (oop == (interpreterProxy->trueObject())) { value = 1; } else { value = interpreterProxy->positive64BitValueOf(oop); if (interpreterProxy->failed()) { return FFIErrorCoercionFailed; } } } /* begin ffiPushUnsignedLongLong:in: */ if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((usqInt) value)); longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32))); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } static sqInt ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((usqInt) value)); longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32))); (calloutState->currentArg = ((calloutState->currentArg)) + 8); return 0; } static sqInt ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState) { if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { return FFIErrorCallFrameTooBig; } longAtput((calloutState->currentArg), ((unsigned short) value)); (calloutState->currentArg = ((calloutState->currentArg)) + 4); return 0; } /* This is a fallback in case somebody tries to pass a 'void' value. We could simply ignore the argument but I think it's better to let the caller know what he did */ static sqInt ffiPushVoidin(sqInt ignored, CalloutState *calloutState) { return FFIErrorAttemptToPassVoid; } /* Create a Smalltalk string from a zero terminated C string */ static sqInt ffiReturnCStringFrom(sqInt cPointer) { char *cString; sqInt i; sqInt strLen; sqInt strOop; char *strPtr; if (cPointer == null) { return interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); } cString = ((char *) cPointer); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i = 0; i <= (strLen - 1); i += 1) { strPtr[i] = (cString[i]); } return interpreterProxy->methodReturnValue(strOop); } /* Generic callout support. Create a pointer return value from an external function call */ static sqInt ffiReturnPointerofTypein(usqLong retVal, sqInt retType, CalloutState *calloutState) { sqInt atomicType; sqInt classOop; char *cString; sqInt i; sqInt oop; sqInt *ptr; sqInt retClass; sqInt retOop; sqInt strLen; sqInt strOop; char *strPtr; sqInt typeSpec; retClass = interpreterProxy->fetchPointerofObject(1, retType); if (retClass == (interpreterProxy->nilObject())) { /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiRetHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* begin ffiReturnCStringFrom: */ if ((((usqInt) retVal)) == null) { return interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); } cString = ((char *) (((usqInt) retVal))); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i = 0; i <= (strLen - 1); i += 1) { strPtr[i] = (cString[i]); } return interpreterProxy->methodReturnValue(strOop); } interpreterProxy->pushRemappableOop(retType); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = (((sqInt) retVal)); interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); /* return type */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop, oop); return interpreterProxy->methodReturnValue(retOop); } interpreterProxy->pushRemappableOop(retClass); if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = (((sqInt) retVal)); /* return class */ retClass = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); /* external address */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->methodReturnValue(retOop); } /* Create a structure return value from an external function call. The value as been stored in alloca'ed space pointed to by the calloutState. */ static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState) { sqInt oop; sqInt retClass; sqInt retOop; retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); interpreterProxy->pushRemappableOop(retOop); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize)); if (returnStructInRegisters((calloutState->structReturnSize))) { memcpy(interpreterProxy->firstIndexableField(oop), (&longLongRet), (calloutState->structReturnSize)); } else { memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize)); } retOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->methodReturnValue(retOop); } /* Answer the return type object for the current invocation */ static sqInt ffiReturnType(sqInt specOnStack) { sqInt argTypes; sqInt specLiteral; specLiteral = (specOnStack ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral); return interpreterProxy->fetchPointerofObject(0, argTypes); } /* Currently all target platforms (Mac OS X ppc or x86, linux x86, Win32) answer true for the two calling conventions, FFICallTypeCDecl FFICallTypeApi, so let's not waste time by testing for these. The only issue is whether the FFICallTypeApi is callee pops or not (which itself is of little importance to an alloca-based implementation, but does save a few instructions if not). Subclasses can still override if necessary. */ static sqInt ffiSupportsCallingConvention(sqInt aCallingConvention) { return 1; } /* Validate if the given oop (an instance of ExternalData) can be passed as a pointer to the given atomic type. */ static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType) { sqInt ptrType; sqInt spec; sqInt specOop; sqInt specType; ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { return FFIErrorWrongType; } if (!(interpreterProxy->isPointers(ptrType))) { return FFIErrorWrongType; } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { return FFIErrorWrongType; } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { return FFIErrorWrongType; } if (!(interpreterProxy->isWords(specOop))) { return FFIErrorWrongType; } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { return FFIErrorWrongType; } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { return FFIErrorWrongType; } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { return FFIErrorCoercionFailed; } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { return FFIErrorCoercionFailed; } } return 0; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* By default, disable logging */ EXPORT(sqInt) initialiseModule(void) { /* Get the instSize of ExternalFunction to know whether it contains a cache of the stackSize, and what the offset of ExternalLibraryFunction's functionName and moduleName slots are. */ ffiLogEnabled = 0; externalFunctionInstSize = interpreterProxy->instanceSizeOf(interpreterProxy->classExternalFunction()); initSurfacePluginFunctionPointers(); return 1; } static sqInt isAlien(sqInt anOop) { return interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()); } static sqInt isAtomicType(sqInt typeSpec) { return typeSpec & FFIFlagAtomic; } static sqInt isDirectAlien(sqInt oop) { assert(isAlien(oop)); return (longAt(oop + BaseHeaderSize)) > 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Answer if a struct returned in memory is returned to the referent of a pointer passed as an implciit first argument. It almost always is. Subclasses can override if not. */ static sqInt nonRegisterStructReturnIsViaImplicitFirstArgument(void) { return 1; } /* IMPORTANT: IF YOU CHANGE THE NAME OF THIS METHOD YOU MUST CHANGE Interpreter>>primitiveCalloutToFFI TO REFLECT THE CHANGE. */ /* Perform a function call to a foreign function. Only invoked from method containing explicit external call spec. */ EXPORT(void) primitiveCallout(void) { sqInt address; sqInt address1; sqInt addressPtr; char *allocation; sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypeArray; sqInt argTypes; sqInt argTypes1; sqInt atomicType; sqInt atomicType1; CalloutState *calloutState; sqInt classOop; char *cString; sqInt err; sqInt externalFunction; sqInt ffiRetType; sqInt flags; double floatRet; sqInt functionName; sqInt i; sqInt i1; usqLong intRet; sqInt meth; sqInt nArgs; sqInt oop; sqInt oop1; sqInt oop2; void *pointer; int *ptr; sqInt *ptr1; sqInt requiredStackSize; sqInt result; sqInt retClass; sqInt retClass1; sqInt retOop; sqInt retOop1; sqInt retType; sqInt specLiteral; sqInt specLiteral1; sqInt stackSize; sqInt strLen; sqInt strOop; char *strPtr; CalloutState theCalloutState; sqInt typeSpec; sqInt typeSpec1; meth = interpreterProxy->primitiveMethod(); if (!((interpreterProxy->literalCountOf(meth)) > 0)) { interpreterProxy->primitiveFailFor(PrimErrBadMethod); return; } externalFunction = interpreterProxy->literalofMethod(0, meth); /* begin ffiCall:ArgArrayOrNil:NumArgs: */ nArgs = interpreterProxy->methodArgumentCount(); if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) { ffiFail(FFIErrorNotFunction); goto l3; } flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (interpreterProxy->failed()) { ffiFail(FFIErrorBadArgs); goto l3; } /* must be array of arg types */ argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction); if (!((interpreterProxy->isArray(argTypeArray)) && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); goto l3; } if (!(1)) { ffiFail(FFIErrorCallType); goto l3; } /* begin ffiLoadCalloutAddress: */ /* Lookup the address */ /* Make sure it's an external handle */ addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction); /* begin ffiContentsOfHandle:errCode: */ if ((addressPtr & 1)) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } if (!(interpreterProxy->isBytes(addressPtr))) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } address1 = interpreterProxy->fetchPointerofObject(0, addressPtr); l4: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { address = 0; goto l5; } if (address1 == 0) { if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) { interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1)); } if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) { address = ffiFail(FFIErrorNoModule); goto l5; } address1 = ffiLoadCalloutAddressFrom(externalFunction); if (interpreterProxy->failed()) { address = 0; goto l5; } ptr = interpreterProxy->firstIndexableField(addressPtr); ptr[0] = address1; } address = address1; l5: /* end ffiLoadCalloutAddress: */; if (interpreterProxy->failed()) { goto l3; } requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex ? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction) : -1); if (interpreterProxy->failed()) { interpreterProxy->primitiveFailFor((null == null ? PrimErrBadMethod : PrimErrBadReceiver)); goto l3; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize : requiredStackSize); null; calloutState = (&theCalloutState); memset(calloutState, 0, sizeof(CalloutState)); ; (calloutState->callFlags = flags); argType = interpreterProxy->fetchPointerofObject(0, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { ffiFail(err); goto l3; } allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment())); if (allocaLiesSoUseGetsp()) { allocation = getsp(); } if ((cStackAlignment()) != 0) { allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1)))); } (calloutState->argVector = allocation); (calloutState->currentArg = allocation + 0); (calloutState->limit = (allocation + stackSize) + 0); if ((((calloutState->structReturnSize)) > 0) && (1 && (!(returnStructInRegisters((calloutState->structReturnSize)))))) { /* begin ffiPushPointer:in: */ pointer = (calloutState->limit); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { goto l1; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + 4); l1: /* end ffiPushPointer:in: */; } for (i = 1; i <= nArgs; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = (null == null ? interpreterProxy->stackValue(nArgs - i) : interpreterProxy->fetchPointerofObject(i - 1, null)); err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState); if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } ffiFail(err); goto l3; } } assert(!(interpreterProxy->failed())); /* begin ffiLogCallout: */ if (ffiLogEnabled) { functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction); if (!(interpreterProxy->isBytes(functionName))) { goto l2; } ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName)); } l2: /* end ffiLogCallout: */; if ((requiredStackSize < 0) && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) { stackSize = ((calloutState->currentArg)) - ((calloutState->argVector)); interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize); } /* begin ffiCalloutTo:SpecOnStack:in: */ if ((0 + (cStackAlignment())) > 0) { setsp((calloutState->argVector)); } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiRetHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { floatRet = dispatchFunctionPointer(((double (*)()) address)); } else { intRet = dispatchFunctionPointer(((usqLong (*)()) address)); } if (isCalleePopsConvention((calloutState->callFlags))) { setsp((calloutState->argVector)); } if (((calloutState->ffiRetHeader)) & FFIFlagPointer) { /* begin ffiReturnPointer:ofType:in: */ /* begin ffiReturnType: */ specLiteral1 = (null != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1); retType = interpreterProxy->fetchPointerofObject(0, argTypes1); retClass1 = interpreterProxy->fetchPointerofObject(1, retType); if (retClass1 == (interpreterProxy->nilObject())) { /* begin atomicTypeOf: */ typeSpec1 = (calloutState->ffiRetHeader); atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* begin ffiReturnCStringFrom: */ if ((((usqInt) intRet)) == null) { result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); goto l6; } cString = ((char *) (((usqInt) intRet))); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i1 = 0; i1 <= (strLen - 1); i1 += 1) { strPtr[i1] = (cString[i1]); } result = interpreterProxy->methodReturnValue(strOop); goto l6; } interpreterProxy->pushRemappableOop(retType); oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); /* return type */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l6; } interpreterProxy->pushRemappableOop(retClass1); if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); /* return class */ retClass1 = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l6; } if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { /* begin ffiReturnStruct:ofType:in: */ /* begin ffiReturnType: */ specLiteral = (null != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral); ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes); retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); interpreterProxy->pushRemappableOop(retOop); oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize)); if (returnStructInRegisters((calloutState->structReturnSize))) { memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize)); } else { memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize)); } retOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2); result = interpreterProxy->methodReturnValue(retOop); goto l6; } if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet)); goto l6; } result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState)); l6: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } l3: /* end ffiCall:ArgArrayOrNil:NumArgs: */; return; } /* Perform a function call to a foreign function. Only invoked from ExternalFunction>>invokeWithArguments: */ EXPORT(void) primitiveCalloutWithArgs(void) { sqInt address; sqInt address1; sqInt addressPtr; char *allocation; sqInt argArray; sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypeArray; sqInt argTypes; sqInt argTypes1; sqInt atomicType; sqInt atomicType1; CalloutState *calloutState; sqInt classOop; char *cString; sqInt err; sqInt externalFunction; sqInt ffiRetType; sqInt flags; double floatRet; sqInt functionName; sqInt i; sqInt i1; usqLong intRet; sqInt nArgs; sqInt oop; sqInt oop1; sqInt oop2; void *pointer; int *ptr; sqInt *ptr1; sqInt requiredStackSize; sqInt result; sqInt retClass; sqInt retClass1; sqInt retOop; sqInt retOop1; sqInt retType; sqInt specLiteral; sqInt specLiteral1; sqInt stackSize; sqInt strLen; sqInt strOop; char *strPtr; CalloutState theCalloutState; sqInt typeSpec; sqInt typeSpec1; if (!((interpreterProxy->methodArgumentCount()) == 1)) { interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); return; } externalFunction = interpreterProxy->stackValue(1); argArray = interpreterProxy->stackValue(0); if (!(interpreterProxy->isArray(argArray))) { interpreterProxy->primitiveFailFor(PrimErrBadArgument); return; } nArgs = interpreterProxy->slotSizeOf(argArray); /* begin ffiCall:ArgArrayOrNil:NumArgs: */ if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) { ffiFail(FFIErrorNotFunction); goto l3; } flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction); if (interpreterProxy->failed()) { ffiFail(FFIErrorBadArgs); goto l3; } /* must be array of arg types */ argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction); if (!((interpreterProxy->isArray(argTypeArray)) && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) { ffiFail(FFIErrorBadArgs); goto l3; } if (!(1)) { ffiFail(FFIErrorCallType); goto l3; } /* begin ffiLoadCalloutAddress: */ /* Lookup the address */ /* Make sure it's an external handle */ addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction); /* begin ffiContentsOfHandle:errCode: */ if ((addressPtr & 1)) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } if (!(interpreterProxy->isBytes(addressPtr))) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) { address1 = ffiFail(FFIErrorBadAddress); goto l4; } address1 = interpreterProxy->fetchPointerofObject(0, addressPtr); l4: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { address = 0; goto l5; } if (address1 == 0) { if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) { interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1)); } if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) { address = ffiFail(FFIErrorNoModule); goto l5; } address1 = ffiLoadCalloutAddressFrom(externalFunction); if (interpreterProxy->failed()) { address = 0; goto l5; } ptr = interpreterProxy->firstIndexableField(addressPtr); ptr[0] = address1; } address = address1; l5: /* end ffiLoadCalloutAddress: */; if (interpreterProxy->failed()) { goto l3; } requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex ? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction) : -1); if (interpreterProxy->failed()) { interpreterProxy->primitiveFailFor((argArray == null ? PrimErrBadMethod : PrimErrBadReceiver)); goto l3; } stackSize = (requiredStackSize < 0 ? DefaultMaxStackSize : requiredStackSize); null; calloutState = (&theCalloutState); memset(calloutState, 0, sizeof(CalloutState)); ; (calloutState->callFlags = flags); argType = interpreterProxy->fetchPointerofObject(0, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) { ffiFail(err); goto l3; } allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment())); if (allocaLiesSoUseGetsp()) { allocation = getsp(); } if ((cStackAlignment()) != 0) { allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1)))); } (calloutState->argVector = allocation); (calloutState->currentArg = allocation + 0); (calloutState->limit = (allocation + stackSize) + 0); if ((((calloutState->structReturnSize)) > 0) && (1 && (!(returnStructInRegisters((calloutState->structReturnSize)))))) { /* begin ffiPushPointer:in: */ pointer = (calloutState->limit); if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) { goto l1; } longAtput((calloutState->currentArg), pointer); (calloutState->currentArg = ((calloutState->currentArg)) + 4); l1: /* end ffiPushPointer:in: */; } for (i = 1; i <= nArgs; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypeArray); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = (argArray == null ? interpreterProxy->stackValue(nArgs - i) : interpreterProxy->fetchPointerofObject(i - 1, argArray)); err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState); if (err != 0) { /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } ffiFail(err); goto l3; } } assert(!(interpreterProxy->failed())); /* begin ffiLogCallout: */ if (ffiLogEnabled) { functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction); if (!(interpreterProxy->isBytes(functionName))) { goto l2; } ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName)); } l2: /* end ffiLogCallout: */; if ((requiredStackSize < 0) && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) { stackSize = ((calloutState->currentArg)) - ((calloutState->argVector)); interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize); } /* begin ffiCalloutTo:SpecOnStack:in: */ if ((0 + (cStackAlignment())) > 0) { setsp((calloutState->argVector)); } /* begin atomicTypeOf: */ typeSpec = (calloutState->ffiRetHeader); atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { floatRet = dispatchFunctionPointer(((double (*)()) address)); } else { intRet = dispatchFunctionPointer(((usqLong (*)()) address)); } if (isCalleePopsConvention((calloutState->callFlags))) { setsp((calloutState->argVector)); } if (((calloutState->ffiRetHeader)) & FFIFlagPointer) { /* begin ffiReturnPointer:ofType:in: */ /* begin ffiReturnType: */ specLiteral1 = (argArray != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1); retType = interpreterProxy->fetchPointerofObject(0, argTypes1); retClass1 = interpreterProxy->fetchPointerofObject(1, retType); if (retClass1 == (interpreterProxy->nilObject())) { /* begin atomicTypeOf: */ typeSpec1 = (calloutState->ffiRetHeader); atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* begin ffiReturnCStringFrom: */ if ((((usqInt) intRet)) == null) { result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject()); goto l6; } cString = ((char *) (((usqInt) intRet))); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i1 = 0; i1 <= (strLen - 1); i1 += 1) { strPtr[i1] = (cString[i1]); } result = interpreterProxy->methodReturnValue(strOop); goto l6; } interpreterProxy->pushRemappableOop(retType); oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); /* return type */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l6; } interpreterProxy->pushRemappableOop(retClass1); if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr1 = interpreterProxy->firstIndexableField(oop1); ptr1[0] = (((sqInt) intRet)); /* return class */ retClass1 = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop1); retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0); /* external address */ oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); result = interpreterProxy->methodReturnValue(retOop1); goto l6; } if (((calloutState->ffiRetHeader)) & FFIFlagStructure) { /* begin ffiReturnStruct:ofType:in: */ /* begin ffiReturnType: */ specLiteral = (argArray != null ? interpreterProxy->stackValue(1) : interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod())); argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral); ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes); retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType); retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0); interpreterProxy->pushRemappableOop(retOop); oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize)); if (returnStructInRegisters((calloutState->structReturnSize))) { memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize)); } else { memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize)); } retOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2); result = interpreterProxy->methodReturnValue(retOop); goto l6; } if ((atomicType == FFITypeSingleFloat) || (atomicType == FFITypeDoubleFloat)) { result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet)); goto l6; } result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState)); l6: /* end ffiCalloutTo:SpecOnStack:in: */; /* begin cleanupCalloutState: */ while (((calloutState->stringArgIndex)) > 0) { free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]); } l3: /* end ffiCall:ArgArrayOrNil:NumArgs: */; return; } /* arguments: name(type, stack offset) width(Integer, 4) height(Integer, 3) rowPitch(Integer, 2) depth(Integer, 1) isMSB(Boolean, 0) */ EXPORT(sqInt) primitiveCreateManualSurface(void) { sqInt depth; sqInt height; sqInt isMSB; sqInt result; sqInt rowPitch; sqInt width; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } width = interpreterProxy->stackIntegerValue(4); height = interpreterProxy->stackIntegerValue(3); rowPitch = interpreterProxy->stackIntegerValue(2); depth = interpreterProxy->stackIntegerValue(1); isMSB = interpreterProxy->stackObjectValue(0); isMSB = interpreterProxy->booleanValueOf(isMSB); if (interpreterProxy->failed()) { return null; } ; ; ; ; ; result = createManualSurface(width, height, rowPitch, depth, isMSB); if (result < 0) { return interpreterProxy->primitiveFail(); } result = interpreterProxy->signed32BitIntegerFor(result); return interpreterProxy->popthenPush(6, result); } /* arguments: name(type, stack offset) surfaceID(Integer, 0) */ EXPORT(sqInt) primitiveDestroyManualSurface(void) { sqInt result; sqInt surfaceID; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } surfaceID = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = destroyManualSurface(surfaceID); if (result == 0) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } /* Primitive. Allocate an object on the external heap. */ EXPORT(sqInt) primitiveFFIAllocate(void) { sqInt addr; sqInt byteSize; sqInt oop; int *ptr; byteSize = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } addr = ffiAlloc(byteSize); if (addr == 0) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = addr; interpreterProxy->popthenPush(2, oop); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIDoubleAt(void) { sqInt addr; sqInt byteOffset; double floatValue; sqInt rcvr; byteOffset = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 8); if (interpreterProxy->failed()) { return 0; } ((int*)(&floatValue))[0] = ((int*)addr)[0]; ((int*)(&floatValue))[1] = ((int*)addr)[1]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIDoubleAtPut(void) { sqInt addr; sqInt byteOffset; sqInt floatOop; double floatValue; sqInt rcvr; floatOop = interpreterProxy->stackValue(0); if ((floatOop & 1)) { floatValue = ((double) ((floatOop >> 1))); } else { floatValue = ((double) (interpreterProxy->floatValueOf(floatOop))); } byteOffset = interpreterProxy->stackIntegerValue(1); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 8); if (interpreterProxy->failed()) { return 0; } ((int*)addr)[0] = ((int*)(&floatValue))[0]; ((int*)addr)[1] = ((int*)(&floatValue))[1]; interpreterProxy->popthenPush(3, floatOop); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIFloatAt(void) { sqInt addr; sqInt byteOffset; float floatValue; sqInt rcvr; byteOffset = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 4); if (interpreterProxy->failed()) { return 0; } ((int*)(&floatValue))[0] = ((int*)addr)[0]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIFloatAtPut(void) { sqInt addr; sqInt byteOffset; sqInt floatOop; float floatValue; sqInt rcvr; floatOop = interpreterProxy->stackValue(0); if ((floatOop & 1)) { floatValue = ((float) ((floatOop >> 1))); } else { floatValue = ((float) (interpreterProxy->floatValueOf(floatOop))); } byteOffset = interpreterProxy->stackIntegerValue(1); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 4); if (interpreterProxy->failed()) { return 0; } ((int*)addr)[0] = ((int*)(&floatValue))[0]; interpreterProxy->popthenPush(3, floatOop); } /* Primitive. Free the object pointed to on the external heap. */ EXPORT(sqInt) primitiveFFIFree(void) { sqInt addr; sqInt oop; int *ptr; oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(oop)) == (interpreterProxy->classExternalAddress()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->byteSizeOf(oop)) == 4)) { return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(oop); /* Don't you dare to free Squeak's memory! */ addr = ptr[0]; if ((addr == 0) || (interpreterProxy->isInMemory(addr))) { return interpreterProxy->primitiveFail(); } ffiFree(addr); return ptr[0] = 0; } /* Primitive. Return the error code from a failed call to the foreign function interface. This is for backwards-compatibility. Thread-safe access to the error code is via the primitive error code. */ EXPORT(sqInt) primitiveFFIGetLastError(void) { interpreterProxy->pop(1); return interpreterProxy->pushInteger(ffiLastError); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIIntegerAt(void) { sqInt addr; sqInt byteOffset; sqInt byteSize; sqInt isSigned; sqInt mask; sqInt rcvr; sqInt value; isSigned = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); byteSize = interpreterProxy->stackIntegerValue(1); byteOffset = interpreterProxy->stackIntegerValue(2); rcvr = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return 0; } if (!((byteOffset > 0) && ((byteSize == 1) || ((byteSize == 2) || (byteSize == 4))))) { return interpreterProxy->primitiveFail(); } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, byteSize); if (interpreterProxy->failed()) { return 0; } if (byteSize < 4) { if (byteSize == 1) { /* short/byte */ value = byteAt(addr); } else { value = *((short int *) addr); } if (isSigned) { /* sign extend value */ mask = 1 << ((byteSize * 8) - 1); value = (value & (mask - 1)) - (value & mask); } value = ((value << 1) | 1); } else { /* general 32 bit integer */ value = longAt(addr); value = (isSigned ? interpreterProxy->signed32BitIntegerFor(value) : interpreterProxy->positive32BitIntegerFor(value)); } interpreterProxy->popthenPush(4, value); } /* Store a (signed or unsigned) n byte integer at the given byte offset. */ EXPORT(sqInt) primitiveFFIIntegerAtPut(void) { sqInt addr; sqInt byteOffset; sqInt byteSize; sqInt isSigned; sqInt max; sqInt rcvr; sqInt value; sqInt valueOop; isSigned = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); byteSize = interpreterProxy->stackIntegerValue(1); valueOop = interpreterProxy->stackValue(2); byteOffset = interpreterProxy->stackIntegerValue(3); rcvr = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return 0; } if (!((byteOffset > 0) && ((byteSize == 1) || ((byteSize == 2) || (byteSize == 4))))) { return interpreterProxy->primitiveFail(); } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, byteSize); if (interpreterProxy->failed()) { return 0; } if (isSigned) { value = interpreterProxy->signed32BitValueOf(valueOop); } else { value = interpreterProxy->positive32BitValueOf(valueOop); } if (interpreterProxy->failed()) { return 0; } if (byteSize < 4) { if (isSigned) { max = 1 << ((8 * byteSize) - 1); if (value >= max) { return interpreterProxy->primitiveFail(); } if (value < (0 - max)) { return interpreterProxy->primitiveFail(); } } else { if (value >= (1 << (8 * byteSize))) { return interpreterProxy->primitiveFail(); } } if (byteSize == 1) { byteAtput(addr, value); } else { *((short int *) addr) = value; } } else { longAtput(addr, value); } interpreterProxy->popthenPush(5, valueOop); } /* Primitive. Force loading the receiver (an instance of ExternalLibrary). */ EXPORT(sqInt) primitiveForceLoad(void) { sqInt ffiModuleName; sqInt moduleHandle; sqInt moduleHandlePtr; int *ptr; sqInt rcvr; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } rcvr = interpreterProxy->stackValue(0); if (!(interpreterProxy->isKindOfClass(rcvr, interpreterProxy->classExternalLibrary()))) { return ffiFail(FFIErrorBadExternalLibrary); } moduleHandlePtr = interpreterProxy->fetchPointerofObject(0, rcvr); /* begin ffiContentsOfHandle:errCode: */ if ((moduleHandlePtr & 1)) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!(interpreterProxy->isBytes(moduleHandlePtr))) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } if (!((interpreterProxy->byteSizeOf(moduleHandlePtr)) == 4)) { moduleHandle = ffiFail(FFIErrorBadExternalLibrary); goto l1; } moduleHandle = interpreterProxy->fetchPointerofObject(0, moduleHandlePtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } ffiModuleName = interpreterProxy->fetchPointerofObject(1, rcvr); if (!(interpreterProxy->isBytes(ffiModuleName))) { return ffiFail(FFIErrorBadExternalLibrary); } moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), interpreterProxy->byteSizeOf(ffiModuleName)); if (interpreterProxy->failed()) { return ffiFail(FFIErrorModuleNotFound); } ptr = interpreterProxy->firstIndexableField(moduleHandlePtr); ptr[0] = moduleHandle; return 0; } /* Enable logging of FFI calls by providing it with a log file name. */ EXPORT(sqInt) primitiveLogCallsTo(void) { sqInt logFile; sqInt ok; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } logFile = interpreterProxy->stackObjectValue(0); if (logFile == (interpreterProxy->nilObject())) { /* disable logging */ ok = ffiLogFileNameOfLength(null, 0); if (!(ok)) { return interpreterProxy->primitiveFail(); } ffiLogEnabled = 0; } else { if (!(interpreterProxy->isBytes(logFile))) { return interpreterProxy->primitiveFail(); } ok = ffiLogFileNameOfLength(interpreterProxy->firstIndexableField(logFile), interpreterProxy->byteSizeOf(logFile)); if (!(ok)) { return interpreterProxy->primitiveFail(); } ffiLogEnabled = 1; } return interpreterProxy->pop(1); } /* Create a 'manual surface' data-structure. See the ExternalForm class in the FFI package for example usage. */ /* arguments: name(type, stack offset) surfaceID(Integer, 1) ptr(uint32, 0) */ EXPORT(sqInt) primitiveSetManualSurfacePointer(void) { unsigned int ptr; sqInt result; sqInt surfaceID; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } surfaceID = interpreterProxy->stackIntegerValue(1); ptr = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } ; ; result = setManualSurfacePointer(surfaceID, (void*)ptr); if (result == 0) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } /* Answer any space needed to prevent the alloca'ed outgoing arguments marshalling area from being overwritten by any register arguments during calls during marshalling. On x86 this is 0 */ static sqInt registerArgsSlop(void) { return 0; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Answer the first field of oop which is assumed to be an Alien of at least 8 bytes */ static sqInt sizeField(sqInt oop) { return longAt(oop + BaseHeaderSize); } /* <Alien oop> ^<Integer> */ /* Answer the start of oop's data. For direct aliens this is the address of the second field. For indirect and pointer aliens it is what the second field points to. */ static sqInt startOfData(sqInt oop) { return ((longAt(oop + BaseHeaderSize)) > 0 ? (oop + BaseHeaderSize) + BytesPerOop : longAt((oop + BaseHeaderSize) + BytesPerOop)); } #if defined(SQUEAK_BUILTIN_PLUGIN) || defined(ROAR_VM) void* SqueakFFIPrims_exports[][3] = { {"SqueakFFIPrims", "ffiLogCallsTo", (void*)ffiLogCallsTo}, {"SqueakFFIPrims", "getModuleName", (void*)getModuleName}, {"SqueakFFIPrims", "initialiseModule", (void*)initialiseModule}, {"SqueakFFIPrims", "primitiveCallout", (void*)primitiveCallout}, {"SqueakFFIPrims", "primitiveCalloutWithArgs", (void*)primitiveCalloutWithArgs}, {"SqueakFFIPrims", "primitiveCreateManualSurface", (void*)primitiveCreateManualSurface}, {"SqueakFFIPrims", "primitiveDestroyManualSurface", (void*)primitiveDestroyManualSurface}, {"SqueakFFIPrims", "primitiveFFIAllocate", (void*)primitiveFFIAllocate}, {"SqueakFFIPrims", "primitiveFFIDoubleAt", (void*)primitiveFFIDoubleAt}, {"SqueakFFIPrims", "primitiveFFIDoubleAtPut", (void*)primitiveFFIDoubleAtPut}, {"SqueakFFIPrims", "primitiveFFIFloatAt", (void*)primitiveFFIFloatAt}, {"SqueakFFIPrims", "primitiveFFIFloatAtPut", (void*)primitiveFFIFloatAtPut}, {"SqueakFFIPrims", "primitiveFFIFree", (void*)primitiveFFIFree}, {"SqueakFFIPrims", "primitiveFFIGetLastError", (void*)primitiveFFIGetLastError}, {"SqueakFFIPrims", "primitiveFFIIntegerAt", (void*)primitiveFFIIntegerAt}, {"SqueakFFIPrims", "primitiveFFIIntegerAtPut", (void*)primitiveFFIIntegerAtPut}, {"SqueakFFIPrims", "primitiveForceLoad", (void*)primitiveForceLoad}, {"SqueakFFIPrims", "primitiveLogCallsTo", (void*)primitiveLogCallsTo}, {"SqueakFFIPrims", "primitiveSetManualSurfacePointer", (void*)primitiveSetManualSurfacePointer}, {"SqueakFFIPrims", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/StarSqueakPlugin/StarSqueakPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from StarSqueakPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "StarSqueakPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static unsigned int * checkedUnsignedIntPtrOf(sqInt oop); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveDiffuseFromToWidthHeightDelta(void); EXPORT(sqInt) primitiveEvaporateRate(void); EXPORT(sqInt) primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "StarSqueakPlugin VMMaker-oscog.dtl.57 (i)" #else "StarSqueakPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Return an unsigned int pointer to the first indexable word of oop, which must be a words object. */ static unsigned int * checkedUnsignedIntPtrOf(sqInt oop) { interpreterProxy->success(interpreterProxy->isWords(oop)); if (interpreterProxy->failed()) { return 0; } return ((unsigned int *) (interpreterProxy->firstIndexableField(oop))); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Diffuse the integer values of the source patch variable Bitmap into the output Bitmap. Each cell of the output is the average of the NxN area around it in the source, where N = (2 * delta) + 1. */ EXPORT(sqInt) primitiveDiffuseFromToWidthHeightDelta(void) { sqInt area; sqInt delta; unsigned int *dst; sqInt dstOop; sqInt endX; sqInt endY; sqInt height; sqInt rowStart; unsigned int *src; sqInt srcOop; sqInt startX; sqInt startY; sqInt sum; sqInt width; sqInt x; sqInt x2; sqInt y; sqInt y2; srcOop = interpreterProxy->stackValue(4); dstOop = interpreterProxy->stackValue(3); width = interpreterProxy->stackIntegerValue(2); height = interpreterProxy->stackIntegerValue(1); delta = interpreterProxy->stackIntegerValue(0); /* begin checkedUnsignedIntPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(srcOop)); if (interpreterProxy->failed()) { src = 0; goto l1; } src = ((unsigned int *) (interpreterProxy->firstIndexableField(srcOop))); l1: /* end checkedUnsignedIntPtrOf: */; /* begin checkedUnsignedIntPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(dstOop)); if (interpreterProxy->failed()) { dst = 0; goto l2; } dst = ((unsigned int *) (interpreterProxy->firstIndexableField(dstOop))); l2: /* end checkedUnsignedIntPtrOf: */; interpreterProxy->success((interpreterProxy->stSizeOf(srcOop)) == (interpreterProxy->stSizeOf(dstOop))); interpreterProxy->success((interpreterProxy->stSizeOf(srcOop)) == (width * height)); if (interpreterProxy->failed()) { return null; } area = ((2 * delta) + 1) * ((2 * delta) + 1); for (y = 0; y <= (height - 1); y += 1) { startY = y - delta; if (startY < 0) { startY = 0; } endY = y + delta; if (endY >= height) { endY = height - 1; } for (x = 0; x <= (width - 1); x += 1) { startX = x - delta; if (startX < 0) { startX = 0; } endX = x + delta; if (endX >= width) { endX = width - 1; } sum = 0; for (y2 = startY; y2 <= endY; y2 += 1) { rowStart = y2 * width; for (x2 = startX; x2 <= endX; x2 += 1) { sum += src[rowStart + x2]; } } dst[(y * width) + x] = (sum / area); } } interpreterProxy->pop(5); } /* Evaporate the integer values of the source Bitmap at the given rate. The rate is an integer between 0 and 1024, where 1024 is a scale factor of 1.0 (i.e., no evaporation). */ EXPORT(sqInt) primitiveEvaporateRate(void) { sqInt i; unsigned int *patchVar; sqInt patchVarOop; sqInt rate; sqInt sz; patchVarOop = interpreterProxy->stackValue(1); rate = interpreterProxy->stackIntegerValue(0); /* begin checkedUnsignedIntPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(patchVarOop)); if (interpreterProxy->failed()) { patchVar = 0; goto l1; } patchVar = ((unsigned int *) (interpreterProxy->firstIndexableField(patchVarOop))); l1: /* end checkedUnsignedIntPtrOf: */; sz = interpreterProxy->stSizeOf(patchVarOop); if (interpreterProxy->failed()) { return null; } for (i = 0; i <= (sz - 1); i += 1) { patchVar[i] = (((usqInt) ((patchVar[i]) * rate)) >> 10); } interpreterProxy->pop(2); } EXPORT(sqInt) primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift(void) { unsigned int *dst; sqInt dstIndex; sqInt dstOop; sqInt h; sqInt level; sqInt offset; sqInt patchSize; sqInt pixel; sqInt rgbFlags; sqInt rgbMult; sqInt rowStart; sqInt shiftAmount; unsigned int *src; sqInt srcIndex; sqInt srcOop; sqInt w; sqInt x; sqInt y; srcOop = interpreterProxy->stackValue(6); dstOop = interpreterProxy->stackValue(5); w = interpreterProxy->stackIntegerValue(4); h = interpreterProxy->stackIntegerValue(3); patchSize = interpreterProxy->stackIntegerValue(2); rgbFlags = interpreterProxy->stackIntegerValue(1); shiftAmount = interpreterProxy->stackIntegerValue(0); /* begin checkedUnsignedIntPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(srcOop)); if (interpreterProxy->failed()) { src = 0; goto l1; } src = ((unsigned int *) (interpreterProxy->firstIndexableField(srcOop))); l1: /* end checkedUnsignedIntPtrOf: */; /* begin checkedUnsignedIntPtrOf: */ interpreterProxy->success(interpreterProxy->isWords(dstOop)); if (interpreterProxy->failed()) { dst = 0; goto l2; } dst = ((unsigned int *) (interpreterProxy->firstIndexableField(dstOop))); l2: /* end checkedUnsignedIntPtrOf: */; interpreterProxy->success((interpreterProxy->stSizeOf(dstOop)) == (w * h)); interpreterProxy->success((interpreterProxy->stSizeOf(dstOop)) == (((interpreterProxy->stSizeOf(srcOop)) * patchSize) * patchSize)); if (interpreterProxy->failed()) { return null; } rgbMult = 0; if ((rgbFlags & 4) > 0) { rgbMult += 65536; } if ((rgbFlags & 2) > 0) { rgbMult += 256; } if ((rgbFlags & 1) > 0) { rgbMult += 1; } srcIndex = -1; for (y = 0; y <= ((h / patchSize) - 1); y += 1) { for (x = 0; x <= ((w / patchSize) - 1); x += 1) { level = ((shiftAmount < 0) ? ((usqInt) (src[(srcIndex += 1)]) >> -shiftAmount) : ((usqInt) (src[(srcIndex += 1)]) << shiftAmount)); if (level > 255) { level = 255; } if (level <= 0) { /* non-transparent black */ pixel = 1; } else { pixel = level * rgbMult; } offset = ((y * w) + x) * patchSize; for (rowStart = offset; rowStart <= (offset + ((patchSize - 1) * w)); rowStart += w) { for (dstIndex = rowStart; dstIndex <= ((rowStart + patchSize) - 1); dstIndex += 1) { dst[dstIndex] = pixel; } } } } interpreterProxy->pop(7); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* StarSqueakPlugin_exports[][3] = { {"StarSqueakPlugin", "getModuleName", (void*)getModuleName}, {"StarSqueakPlugin", "primitiveDiffuseFromToWidthHeightDelta", (void*)primitiveDiffuseFromToWidthHeightDelta}, {"StarSqueakPlugin", "primitiveEvaporateRate", (void*)primitiveEvaporateRate}, {"StarSqueakPlugin", "primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift", (void*)primitiveMapFromToWidthHeightPatchSizeRgbFlagsShift}, {"StarSqueakPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/UUIDPlugin/UUIDPlugin.c ================================================ /* Automatically generated by SmartSyntaxPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from UUIDPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "UUIDPlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "UUIDPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); EXPORT(sqInt) initialiseModule(void); static sqInt msg(char *s); EXPORT(sqInt) primitiveMakeUUID(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); static void sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "UUIDPlugin VMMaker-oscog.dtl.57 (i)" #else "UUIDPlugin VMMaker-oscog.dtl.57 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } EXPORT(sqInt) initialiseModule(void) { return sqUUIDInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } EXPORT(sqInt) primitiveMakeUUID(void) { char*location; sqInt oop; oop = interpreterProxy->stackObjectValue(0); if ((interpreterProxy->failed()) || (((interpreterProxy->methodArgumentCount()) != 0) || ((!(interpreterProxy->isBytes(oop))) || ((interpreterProxy->byteSizeOf(oop)) != 16)))) { return interpreterProxy->primitiveFail(); } location = interpreterProxy->firstIndexableField(oop); MakeUUID(location); return oop; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return sqUUIDShutdown(); } static void sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* UUIDPlugin_exports[][3] = { {"UUIDPlugin", "getModuleName", (void*)getModuleName}, {"UUIDPlugin", "initialiseModule", (void*)initialiseModule}, {"UUIDPlugin", "primitiveMakeUUID", (void*)primitiveMakeUUID}, {"UUIDPlugin", "setInterpreter", (void*)setInterpreter}, {"UUIDPlugin", "shutdownModule", (void*)shutdownModule}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:04 pm by VMMaker 4.4.7 */ // added bu dmu #define AIO_X (1<<0) /* handle for exceptions */ #define AIO_R (1<<1) /* handle for read */ #define AIO_W (1<<2) /* handle for write */ #define AIO_SEQ (1<<3) /* call handlers sequentially */ #define AIO_EXT (1<<4) /* external fd -- don't close on aio shutdown */ #define AIO_RW (AIO_R | AIO_W) #define AIO_RX (AIO_R | AIO_X) #define AIO_WX (AIO_W | AIO_X) #define AIO_RWX (AIO_R | AIO_W | AIO_X) #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include <sys/types.h> /* D T Lewis - UnixOSProcessPlugin.c translated from class UnixOSProcessPlugin of OSProcessPlugin version 4.3.3 */ #include <sys/time.h> #include <sys/wait.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <signal.h> #include <pthread.h> #include <sys/stat.h> #include <errno.h> #include "config.h" #define FILEHANDLETYPE FILE * /* the type of low level stream to be used in a struct SQFile */ #ifndef SQAIO_H # define SQAIO_H "aio.h" /* aio.h has been renamed to sqaio.h */ #endif # if Configure_Squeak_Code_for_Tilera // xxx_dmu # undef SQAIO_H // xxx_dmu # define SQAIO_H "sqaio.h" // xxx_dmu # endif #include SQAIO_H #include "FilePlugin.h" #include "SocketPlugin.h" #define SESSIONIDENTIFIERTYPE int #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static void aioForwardwithDataandFlags(int fd, void *data, int flags); static char * cStringFromString(sqInt aString); static void * callocWrappersize(sqInt count, sqInt objectSize); static sqInt copyBytesFromtolength(void *charArray1, void *charArray2, sqInt len); static sqInt createPipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr); static sqInt descriptorTableSize(void); static void dupToStdErr(sqInt anSQFileDataStructure); static void dupToStdIn(sqInt anSQFileDataStructure); static void dupToStdOut(sqInt anSQFileDataStructure); static sqInt fileDescriptorFrom(sqInt aSQFileByteArray); static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray); static sqInt fileRecordSize(void); static SQFile * fileValueOf(sqInt anSQFileRecord); static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count); static sqInt forkAndExecInDirectory(sqInt useSignalHandler); #pragma export on EXPORT(pid_t) forkSqueak(sqInt useSignalHandler); #pragma export off static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt getThisSessionIdentifier(void); static sqInt halt(void); static void handleSignal(int sigNum); static void * handleSignalFunctionAddress(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt initializeModuleForPlatform(void); static sqInt isNonNullSQFile(sqInt objectPointer); static sqInt isNullSQSocket(sqInt objectPointer); static sqInt isSQFileObject(sqInt objectPointer); static sqInt isSQSocketObject(sqInt objectPointer); static sqInt isValidFileSession(sqInt objectPointer); static sqInt isVmThread(void); static sqInt makePipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr); static sqInt maskForThisThreadAndResend(int sigNum); static sqInt maskSignalForThisThread(int sigNum); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); static sqInt newPthreadTypeByteArray(sqInt aPthreadType); static sqInt newSQFileByteArray(void); static sqInt newSQSocketByteArray(void); static void ** originalSignalHandlers(void); static void * pointerFrom(sqInt aByteArray); #pragma export on EXPORT(sqInt) primitiveAioDisable(void); EXPORT(sqInt) primitiveAioEnable(void); EXPORT(sqInt) primitiveAioHandle(void); EXPORT(sqInt) primitiveAioSuspend(void); EXPORT(sqInt) primitiveArgumentAt(void); EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid); EXPORT(sqInt) primitiveChdir(void); EXPORT(sqInt) primitiveCreatePipe(void); EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveDupTo(sqInt oldFileDescriptor, sqInt newFileDescriptor); EXPORT(sqInt) primitiveEnvironmentAt(void); EXPORT(sqInt) primitiveEnvironmentAtSymbol(void); EXPORT(sqInt) primitiveErrorMessageAt(void); EXPORT(sqInt) primitiveFileProtectionMask(void); EXPORT(sqInt) primitiveFileStat(void); EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void); EXPORT(sqInt) primitiveForkAndExecInDirectory(void); EXPORT(sqInt) primitiveForkExec(void); EXPORT(sqInt) primitiveForkSqueak(void); EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void); EXPORT(sqInt) primitiveForwardSignalToSemaphore(void); EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void); EXPORT(sqInt) primitiveGetEGid(void); EXPORT(sqInt) primitiveGetEUid(void); EXPORT(sqInt) primitiveGetGid(void); EXPORT(sqInt) primitiveGetPGid(void); EXPORT(sqInt) primitiveGetPGrp(void); EXPORT(sqInt) primitiveGetPPid(void); EXPORT(sqInt) primitiveGetPid(void); EXPORT(sqInt) primitiveGetSession(void); EXPORT(sqInt) primitiveGetStdErrHandle(void); EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdInHandle(void); EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdOutHandle(void); EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetThreadID(void); EXPORT(sqInt) primitiveGetUid(void); EXPORT(sqInt) primitiveIsAtEndOfFile(void); EXPORT(sqInt) primitiveKillOnExit(void); EXPORT(sqInt) primitiveLockFileRegion(void); EXPORT(sqInt) primitiveMakePipe(void); EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveModuleName(void); EXPORT(sqInt) primitiveNice(void); EXPORT(sqInt) primitivePutEnv(void); EXPORT(sqInt) primitiveRealpath(void); EXPORT(sqInt) primitiveReapChildProcess(void); EXPORT(sqInt) primitiveSQFileFlush(void); EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetBlocking(void); EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetNonBlocking(void); EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetUnbuffered(void); EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void); EXPORT(sqInt) primitiveSemaIndexFor(void); EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSetPGid(void); EXPORT(sqInt) primitiveSetPGrp(void); EXPORT(sqInt) primitiveSetSemaIndex(void); EXPORT(sqInt) primitiveSetSid(void); EXPORT(sqInt) primitiveSigChldNumber(void); EXPORT(sqInt) primitiveSigHupNumber(void); EXPORT(sqInt) primitiveSigIntNumber(void); EXPORT(sqInt) primitiveSigKillNumber(void); EXPORT(sqInt) primitiveSigPipeNumber(void); EXPORT(sqInt) primitiveSigQuitNumber(void); EXPORT(sqInt) primitiveSigTermNumber(void); EXPORT(sqInt) primitiveSigUsr1Number(void); EXPORT(sqInt) primitiveSigUsr2Number(void); EXPORT(sqInt) primitiveSizeOfInt(void); EXPORT(sqInt) primitiveSizeOfPointer(void); EXPORT(sqInt) primitiveTestEndOfFileFlag(void); EXPORT(sqInt) primitiveTestLockableFileRegion(void); EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber); EXPORT(sqInt) primitiveUnixFileNumber(void); EXPORT(sqInt) primitiveUnlockFileRegion(void); EXPORT(sqInt) primitiveUnsetEnv(void); EXPORT(sqInt) primitiveVersionString(void); #pragma export off static void reapChildProcess(int sigNum); static sqInt resendSignal(int sigNum); static void restoreDefaultSignalHandlers(void); static sqInt sandboxSecurity(void); static sqInt securityHeurisitic(void); static unsigned char * semaphoreIndices(void); static sqInt sendSignaltoPid(sqInt sig, sqInt pid); static void sendSignalToPids(void); static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray); static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static void setSigChldDefaultHandler(void); static void setSigChldHandler(void); static void setSigIntDefaultHandler(void); static void setSigIntIgnore(void); static void setSigPipeDefaultHandler(void); static sqInt setSigPipeHandler(void); static void setSigPipeIgnore(void); static void * setSignalNumberhandler(sqInt anInteger, void *signalHandlerAddress); #pragma export on EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sigAbrtNumber(void); static sqInt sigAlrmNumber(void); static sqInt sigChldNumber(void); static sqInt sigContNumber(void); static void * sigDefaultNumber(void); static void * sigErrorNumber(void); static sqInt sigHupNumber(void); static void * sigIgnoreNumber(void); static sqInt sigIntNumber(void); static sqInt sigKillNumber(void); static sqInt sigPipeNumber(void); static sqInt sigQuitNumber(void); static sqInt sigStopNumber(void); static sqInt sigTermNumber(void); static sqInt sigUsr1Number(void); static sqInt sigUsr2Number(void); static sqInt signalArraySize(void); static void ** signalHandlers(void); static sqInt sizeOfInt(void); static sqInt sizeOfPointer(void); static sqInt sizeOfSession(void); static int socketDescriptorFrom(sqInt sqSocketOop); static sqInt socketRecordSize(void); static SQSocket * socketValueOf(sqInt anSQSocketRecord); static sqInt stringFromCString(const char *aCString); static char * transientCStringFromString(sqInt aString); static int unixFileNumber(FILEHANDLETYPE fileHandle); static char * versionString(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "UnixOSProcessPlugin 23 January 2011 (i)" #else "UnixOSProcessPlugin 23 January 2011 (e)" #endif ; static void *originalSigHandlers[NSIG]; static int osprocessSandboxSecurity; static pid_t *pidArray = NULL; static sqInt pidCount; static unsigned char semaIndices[NSIG]; static sqInt sigChldSemaIndex; static void *sigHandlers[NSIG]; static int sigNumToSend = SIGTERM; static pthread_t vmThread; /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* This function is called to signal a Smalltalk Semaphore when an asynchronous event is detected. When translated to C, the name of this method is aioForwardwithDataandFlags. The event handler is set up by #primitiveAioHandle. */ static void aioForwardwithDataandFlags(int fd, void *data, int flags) { sqInt *pfd; sqInt semaIndex; pfd = data; semaIndex = *pfd; interpreterProxy->signalSemaphoreWithIndex(semaIndex); } /* Answer a new null-terminated C string copied from aString. The C string is allocated from the C runtime heap. See transientCStringFromString for a version which allocates from object memory. Caution: This may invoke the garbage collector. */ static char * cStringFromString(sqInt aString) { char *cString; sqInt len; char *sPtr; sPtr = interpreterProxy->arrayValueOf(aString); len = interpreterProxy->sizeOfSTArrayFromCPrimitive(sPtr); /* Space for a null terminated C string. */ cString = callocWrappersize(len + 1, 1); (char *) strncpy (cString, sPtr, len); return cString; } /* Using malloc() and calloc() is something I would like to avoid, since it is likely to cause problems some time in the future if somebody redesigns object memory allocation. This wrapper just makes it easy to find senders of calloc() in my code. -dtl */ static void * callocWrappersize(sqInt count, sqInt objectSize) { return calloc(count, objectSize); } /* self cCode: 'memcpy(charArray2, charArray1, len' */ static sqInt copyBytesFromtolength(void *charArray1, void *charArray2, sqInt len) { memcpy(charArray2, charArray1, len); } /* Create a pipe and populate the readerIOStream and writerIOStream variables. The SIGPIPE handler must have been set before creating the pipe. Answer true for success, else false. */ static sqInt createPipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr) { int filedes[2]; if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } /* Answer the size of the file descriptor table for a process. I am not sure of the most portable way to do this. If this implementation does not work on your Unix platform, try changing it to answer the value of FOPEN:=MAX, which will hopefully be defined in stdio.h. If all else fails, just hard code it to answer 20, which would be safe for any Unix. */ static sqInt descriptorTableSize(void) { return getdtablesize(); } /* Dup a file descriptor to allow it to be attached as the standard error when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdErr(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 2)) { fflush(stderr); dup2(filenoToDup, 2); } } } /* Dup a file descriptor to allow it to be attached as the standard input when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdIn(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 0)) { fflush(stdin); dup2(filenoToDup, 0); rewind(stdin); } } } /* Dup a file descriptor to allow it to be attached as the standard output when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdOut(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 1)) { fflush(stdout); dup2(filenoToDup, 1); } } } /* Answer the OS file descriptor, an integer value, from a SQFile data structure byte array, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). */ /* return type should be int, but skip the declaration to permit inlining */ static sqInt fileDescriptorFrom(sqInt aSQFileByteArray) { if (!((((interpreterProxy->isBytes(aSQFileByteArray)) && ((interpreterProxy->byteSizeOf(aSQFileByteArray)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(aSQFileByteArray))))) && (isNonNullSQFile(aSQFileByteArray)))) { return -1; } return fileno(fileHandleFrom(aSQFileByteArray)); } /* Answer a file handle from a SQFile structure. On most platforms, this will be a (FILE *). On Win32, it is a HANDLE. */ static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray) { SQFile *sqFile; sqFile = interpreterProxy->arrayValueOf(sqFileStructByteArray); return sqFile->file; } /* Answer the size of a SQFile data structure in bytes. */ static sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the SQFile data structure file record within anSQFileRecord, which is expected to be a ByteArray of size self>>fileRecordSize. */ static SQFile * fileValueOf(sqInt anSQFileRecord) { return interpreterProxy->arrayValueOf(anSQFileRecord); } /* Use the address offsets in offsetArray to fix up the pointers in cStringArray. The result is a C array of pointers to char, used for argv and env vectors. */ static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count) { sqInt idx; char **ptr; ptr = ((char **) flattenedArrayOfStrings); idx = 0; while (idx < count) { ptr[idx] = (flattenedArrayOfStrings + (((offsetArray[idx]) >> 1))); idx += 1; } } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. If useSignalHandler is true, set the signal handler for SIGCHLD. Otherwise, assume that death of child events are handled through some other mechanism. In this implementation, memory for the argument and environment arrays is allocated in the image prior to calling this primitive. This allows us to avoid invoking the garbage collector in this primitive (thereby moving the locations of environment and argument memory), but comes at the cost of twiddling C pointers here in the primitive. An alternative to this whole mess is just to malloc the environment and argument vectors, but I think it is a good idea to avoid malloc as much as possible so as not to limit future ObjectMemory implementations. This primitive replaces #primitiveForkAndExec from earlier versions of the plugin. The new name permits backward compatibility for an image running on a VM which does not yet have the updated plugin. This implementation uses a different argument format on the stack, and differs functionally in that the child now closes all file descriptors (including sockets) not required (that is, everything except stdin, stdout, and stderr on descriptors 0, 1 and 2). This eliminates some flakey behavior in child processes connected to Squeak by pipes, which failed to exit at expected times due to the old file descriptors remaining open. This is also cleaner in that garbage descriptors are not left hanging around the the child. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ static sqInt forkAndExecInDirectory(sqInt useSignalHandler) { sqInt argCount; sqInt *argOffsetPtr; sqInt argOffsets; sqInt argVecBuffer; char **args; char *argsPtr; char **env; sqInt envCount; sqInt *envOffsetPtr; sqInt envOffsets; char *envPtr; extern char **envVec; sqInt envVecBuffer; sqInt executableFile; sqInt handleCount; sqInt idx; struct itimerval intervalTimer; pid_t pid; char *progNamePtr; sqInt pwd; char *pwdPtr; struct itimerval saveIntervalTimer; sqInt stdErr; sqInt stdIn; sqInt stdOut; sqInt workingDir; sqInt sigNum; if (useSignalHandler) { setSigChldHandler(); } if ((sandboxSecurity()) == 1) { interpreterProxy->pop(10); interpreterProxy->pushInteger(-1); } else { intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if ((pid = vfork()) == 0) { /* This is the new child process */ workingDir = interpreterProxy->stackObjectValue(0); envOffsets = interpreterProxy->stackObjectValue(1); envVecBuffer = interpreterProxy->stackObjectValue(2); argOffsets = interpreterProxy->stackObjectValue(3); argVecBuffer = interpreterProxy->stackObjectValue(4); stdErr = interpreterProxy->stackObjectValue(5); stdOut = interpreterProxy->stackObjectValue(6); stdIn = interpreterProxy->stackObjectValue(7); /* If a new working directory has been specified, try to chdir() to it. */ executableFile = interpreterProxy->stackObjectValue(8); if (workingDir != (interpreterProxy->nilObject())) { pwdPtr = interpreterProxy->firstIndexableField(workingDir); if (pwdPtr == 0) { fprintf(stderr, "bad workingDir parameter\n"); _exit(-1); } else { pwd = chdir(pwdPtr); if (pwd != 0) { perror("chdir"); _exit(-1); } } } /* Dup the file handles to attach the new child process to the right streams on descriptors 0, 1 and 2. */ progNamePtr = interpreterProxy->arrayValueOf(executableFile); if (!(stdErr == (interpreterProxy->nilObject()))) { dupToStdErr(stdErr); } if (!(stdOut == (interpreterProxy->nilObject()))) { dupToStdOut(stdOut); } if (!(stdIn == (interpreterProxy->nilObject()))) { dupToStdIn(stdIn); } /* First Unix file descriptor after stdin, stdout, stderr. */ idx = 3; handleCount = descriptorTableSize(); while (idx < handleCount) { close(idx); idx += 1; } if (envVecBuffer == (interpreterProxy->nilObject())) { env = envVec; } else { envCount = interpreterProxy->stSizeOf(envOffsets); envPtr = interpreterProxy->arrayValueOf(envVecBuffer); envOffsetPtr = interpreterProxy->firstIndexableField(envOffsets); fixPointersInArrayOfStringswithOffsetscount(envPtr, envOffsetPtr, envCount); env = ((char **) envPtr); } argCount = interpreterProxy->stSizeOf(argOffsets); argsPtr = interpreterProxy->arrayValueOf(argVecBuffer); argOffsetPtr = interpreterProxy->firstIndexableField(argOffsets); fixPointersInArrayOfStringswithOffsetscount(argsPtr, argOffsetPtr, argCount); /* Clean things up before clobbering the running image. */ /* Note: If any file descriptors, signal handlers, or other references to external resources need to be cleaned up, do it here. */ args = ((char **) argsPtr); /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } if ((execve(progNamePtr, args, env)) == -1) { perror(progNamePtr); _exit(-1); } else { /* Can't get here from there */; } } else { setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); interpreterProxy->pop(10); interpreterProxy->pushInteger(pid); } } } /* Fork a child process, and continue running squeak in the child process. Answer the result of the fork() call, either the child pid or zero. After calling fork(), two OS processes exist, one of which is the child of the other. On systems which implement copy-on-write memory management, and which support the fork() system call, both processes will be running Smalltalk images, and will be sharing the same memory space. In the original OS process, the resulting value of pid is the process id of the child process (a non-zero integer). In the child process, the value of pid is zero. The child recreates sufficient external resources to continue running. This is done by attaching to a new X session. The child is otherwise a copy of the parent process, and will continue executing the Smalltalk image at the same point as its parent. The return value of this primitive may be used by the two running Smalltalk images to determine which is the parent and which is the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. The new child image does not start itself from the image in the file system; rather it is a clone of the parent image as it existed at the time of primitiveForkSqueak. For this reason, the parent and child should agree in advance as to whom is allowed to save the image to the file system, otherwise one Smalltalk may overwrite the image of the other. This is a simple call to fork(), rather than the more common idiom of vfork() followed by exec(). The vfork() call cannot be used here because it is designed to be followed by an exec(), and its semantics require the parent process to wait for the child to exit. See the BSD programmers documentation for details. */ EXPORT(pid_t) forkSqueak(sqInt useSignalHandler) { struct itimerval intervalTimer; pid_t pid; struct itimerval saveIntervalTimer; intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if (useSignalHandler) { setSigChldHandler(); } /* Enable the timer again before resuming Smalltalk. */ pid = fork(); setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); return pid; } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero, the handler is unregistered, and the VM returns to its default behavior for handling that signal. A handler must be unregistered before it can be registered again. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex) { void *oldHandler; if (semaphoreIndex == 0) { if ((semaIndices[sigNum]) > 0) { /* Disable the handler */ oldHandler = originalSigHandlers[sigNum]; setSignalNumberhandler(sigNum, oldHandler); semaIndices[sigNum] = 0; return oldHandler; } else { return sigErrorNumber(); } } if ((semaIndices[sigNum]) > 0) { return sigErrorNumber(); } oldHandler = setSignalNumberhandler(sigNum, handleSignalFunctionAddress()); if (oldHandler != (sigErrorNumber())) { originalSigHandlers[sigNum] = oldHandler; semaIndices[sigNum] = semaphoreIndex; } return oldHandler; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt getThisSessionIdentifier(void) { return interpreterProxy->getThisSessionID(); } static sqInt halt(void) { ; } /* This is a signal handler function which runs when a signal is received from the operating system. When the signal is received, a Smalltalk Semaphore is signaled. This effectively passes the external signal to Squeak to allow it to be handled in Smalltalk. */ static void handleSignal(int sigNum) { sqInt semaIndex; semaIndex = semaIndices[sigNum]; forwardSignaltoSemaphoreAt(sigNum, semaIndex); if (isVmThread()) { if (semaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(semaIndex); } } else { maskForThisThreadAndResend(sigNum); } } static void * handleSignalFunctionAddress(void) { return handleSignal; } EXPORT(sqInt) initialiseModule(void) { osprocessSandboxSecurity = -1; initializeModuleForPlatform(); return 1; } /* Platform specific initialization */ static sqInt initializeModuleForPlatform(void) { pidCount = 0; atexit(sendSignalToPids); vmThread = pthread_self(); } /* Check for the common failure mode of a SQFile record with all zeros. */ static sqInt isNonNullSQFile(sqInt objectPointer) { sqInt idx; unsigned char *sqFileBytes; sqFileBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (fileRecordSize())) { if ((sqFileBytes[idx]) != 0) { return 1; } idx += 1; } return 0; } /* Check for the common failure mode of a SQSocket record with all zeros. */ static sqInt isNullSQSocket(sqInt objectPointer) { sqInt idx; unsigned char *sqSocketBytes; sqSocketBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (socketRecordSize())) { if ((sqSocketBytes[idx]) != 0) { return 0; } idx += 1; } return 1; } /* Answer true if objectPointer appears to be a valid SQFile ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid file reference. */ static sqInt isSQFileObject(sqInt objectPointer) { return (((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))))) && (isNonNullSQFile(objectPointer)); } /* Answer true if objectPointer appears to be a valid SQSocket ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid socket reference. */ static sqInt isSQSocketObject(sqInt objectPointer) { return ((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (socketRecordSize()))) && (!(isNullSQSocket(objectPointer))); } /* Answer true if the file session matches the current interpreter session identifier. */ static sqInt isValidFileSession(sqInt objectPointer) { return (interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))); } /* Answer true if this method is executing in the context of the pthread in which the interpreter executes. */ static sqInt isVmThread(void) { pthread_t thisThread; thisThread = pthread_self(); return pthread_equal(thisThread, vmThread); } /* Create a pipe and populate the readerIOStream and writerIOStream variables. Make sure the SIGPIPE handler is set before creating the pipe. Answer true for success, else false */ static sqInt makePipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr) { int filedes[2]; /* begin setSigPipeHandler */ /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } /* Prevent any future instances of signal sigNum from being delivered to this pthread, and reschedule the current signal to be delivered to this OS process. Any pthread other than the interpreter thread will call this method. Eventually the signal will be delivered to the interpreter thread, which will handle it in the context of the interpreter thread. */ static sqInt maskForThisThreadAndResend(int sigNum) { maskSignalForThisThread(sigNum); resendSignal(sigNum); } /* Prevent future invocations of signal sigNum from being delivered to this pthread. */ static sqInt maskSignalForThisThread(int sigNum) { sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, sigNum); pthread_sigmask(SIG_BLOCK, &sigset, NULL); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* A pthread_t is an unsigned long, which may be 8 bytes on some 64 bit platforms. This stores the value in a byte array that can be easily passed to the image. */ static sqInt newPthreadTypeByteArray(sqInt aPthreadType) { sqInt byteArray; sqInt len; pthread_t *ptr; len = sizeof(pthread_t); byteArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), len); ptr = interpreterProxy->arrayValueOf(byteArray); *ptr = aPthreadType; return byteArray; } /* Answer a new ByteArray sized to contain a SQFile data structure. */ static sqInt newSQFileByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); } /* Answer a new ByteArray sized to contain a SQSocket data structure. */ static sqInt newSQSocketByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); } /* An array of signal handler function addresses, one for each signal type. The value at each entry is the address of the original signal handler function prior to having set a handler. */ static void ** originalSignalHandlers(void) { return originalSigHandlers; } /* Answer the pointer represented by aByteArray. */ static void * pointerFrom(sqInt aByteArray) { sqInt idx; union {void *address; unsigned char bytes[sizeof(void *)];} pointerUnion; unsigned char *ptr; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfPointer())))) { return null; } ptr = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfPointer())) { pointerUnion.bytes[idx] = ptr[idx]; idx += 1; } return pointerUnion.address; } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Definitively disable asynchronous event notification for a descriptor. The parameter is a sqFile ByteArray representing the ioHandle for a file. */ EXPORT(sqInt) primitiveAioDisable(void) { int fd; sqInt sqFile; sqFile = interpreterProxy->stackObjectValue(0); /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } aioDisable(fd); interpreterProxy->pop(2); interpreterProxy->pushInteger(fd); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Enable asynchronous notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, the second parameter is the index of a Semaphore to be notified, and the third parameter is a flag indicating that sqFile represents an external object and should not be closed on termination of aio handling. Answer the semaphore index. */ EXPORT(sqInt) primitiveAioEnable(void) { static int eventSemaphoreIndices[FD_SETSIZE]; sqInt externalObject; int fd; int flags; sqInt semaIndex; sqInt sqFile; sqFile = interpreterProxy->stackObjectValue(2); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } semaIndex = interpreterProxy->stackIntegerValue(1); eventSemaphoreIndices[semaIndex] = semaIndex; externalObject = interpreterProxy->stackObjectValue(0); if (externalObject == (interpreterProxy->trueObject())) { flags = AIO_EXT; } else { flags = 0; } aioEnable(fd, &(eventSemaphoreIndices[semaIndex]), flags); interpreterProxy->pop(4); interpreterProxy->pushInteger(semaIndex); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Handle asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioHandle(void) { sqInt exceptionWatch; int fd; int flags; sqInt readWatch; sqInt sqFile; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioHandle(fd, aioForwardwithDataandFlags, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Temporarily suspend asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioSuspend(void) { sqInt exceptionWatch; int fd; int flags; sqInt readWatch; sqInt sqFile; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioSuspend(fd, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Answer a string containing the OS process argument at index (an Integer) in the argument list. */ EXPORT(sqInt) primitiveArgumentAt(void) { extern int argCnt; extern char **argVec; sqInt index; sqInt s; char *sPtr; index = interpreterProxy->stackIntegerValue(0); if ((index > argCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = argVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Send a null signal to the OS process identified by anIntegerPid. Answer false for a bad parameter on the stack (the common case is for anIntegerPid equal to nil, for which case we should answer false). Answer true if the process exists and can receive signals from this process, otherwise false. This test is useful for determining if a child process still exists following a Squeak image restart. */ EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid) { pid_t pidToSignal; int result; if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, 0); interpreterProxy->pop(2); if (result == 0) { interpreterProxy->push(interpreterProxy->trueObject()); } else { interpreterProxy->push(interpreterProxy->falseObject()); } } else { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->falseObject()); } } /* Call chdir(2) to change current working directory to the specified path string. Answer nil for success, or errno on failure. */ EXPORT(sqInt) primitiveChdir(void) { extern int errno; char *path; path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); if (chdir(path)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipe(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Call dup2() to duplicate a file descriptor. Answer the duplicated file descriptor or -1 on failure. */ EXPORT(sqInt) primitiveDupTo(sqInt oldFileDescriptor, sqInt newFileDescriptor) { int newfd; int oldfd; int result; newfd = interpreterProxy->stackIntegerValue(0); oldfd = interpreterProxy->stackIntegerValue(1); result = dup2(oldfd, newfd); interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } /* Answer a string containing the OS process environment string at index (an Integer) in the environment list. */ EXPORT(sqInt) primitiveEnvironmentAt(void) { sqInt envCnt; extern char **envVec; sqInt index; char **p; sqInt s; char *sPtr; p = envVec; envCnt = 0; while (*p++) envCnt++; index = interpreterProxy->stackIntegerValue(0); if ((index > envCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = envVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Answer the value of an environment variable keyed by a Symbol. */ EXPORT(sqInt) primitiveEnvironmentAtSymbol(void) { char * getenvResult; getenvResult = getenv(transientCStringFromString(interpreterProxy->stackObjectValue(0))); if (getenvResult == 0) { return interpreterProxy->primitiveFail(); } else { interpreterProxy->pop(2); interpreterProxy->push(stringFromCString(getenvResult)); } } /* Answer a string describing an error message */ EXPORT(sqInt) primitiveErrorMessageAt(void) { sqInt errMessage; sqInt index; char *p; index = interpreterProxy->stackIntegerValue(0); p = ((char *) (strerror(index))); errMessage = stringFromCString(p); interpreterProxy->pop(2); interpreterProxy->push(errMessage); } /* Call stat(2) to obtain the file protection mask for a file. Answer an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileProtectionMask(void) { sqInt buffer; extern int errno; sqInt mode; char *path; sqInt result; struct stat *statBuf; buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); interpreterProxy->stObjectatput(result, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(result, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Call stat(2) to obtain the file protection mask for a file. Answer errno on failure, or on success answer an array with: UID with: GID with: protectionMask. The protectionMask is an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileStat(void) { sqInt buffer; extern int errno; sqInt gid; sqInt mask; sqInt mode; char *path; sqInt result; struct stat *statBuf; sqInt uid; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); uid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(uid_t)); gid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(gid_t)); mask = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; interpreterProxy->stObjectatput(mask, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(mask, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(mask, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(mask, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, mask); interpreterProxy->stObjectatput(result, 2, (((statBuf->st_gid) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, (((statBuf->st_uid) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* This primitive exists only for purposes of testing the fixPointersInArrayOfStrings:withOffsets:count: method. I believe it to be reasonably machine and compiler independent, but have no way of verifying this on a variety of machines, so I'll leave this test method here in case someone runs into problems on other hardware or compilers. -dtl */ EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void) { sqInt cStringArray; sqInt count; char *flattenedArrayOfStrings; sqInt offsetArray; sqInt *offsets; count = interpreterProxy->stackIntegerValue(0); offsetArray = interpreterProxy->stackObjectValue(1); cStringArray = interpreterProxy->stackObjectValue(2); offsets = interpreterProxy->firstIndexableField(offsetArray); flattenedArrayOfStrings = interpreterProxy->arrayValueOf(cStringArray); fixPointersInArrayOfStringswithOffsetscount(flattenedArrayOfStrings, offsets, count); interpreterProxy->pop(4); interpreterProxy->push(cStringArray); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkAndExecInDirectory(void) { return forkAndExecInDirectory(1); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkExec(void) { return forkAndExecInDirectory(0); } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueak(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(1); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(0); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero or nil, the handler is unregistered, and the VM returns to its default behavior for handling that signal. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ EXPORT(sqInt) primitiveForwardSignalToSemaphore(void) { char *hPtr; void *handler; sqInt idx; sqInt index; union {void *handler; unsigned char bytes[sizeof(void *)];} priorHandler; sqInt priorHandlerObject; sqInt semaphoreIndex; sqInt sigNum; index = interpreterProxy->stackValue(0); if (index == (interpreterProxy->nilObject())) { semaphoreIndex = 0; } else { if ((index & 1)) { semaphoreIndex = interpreterProxy->stackIntegerValue(0); } else { return interpreterProxy->primitiveFail(); } } sigNum = interpreterProxy->stackIntegerValue(1); handler = forwardSignaltoSemaphoreAt(sigNum, semaphoreIndex); if (handler == (sigErrorNumber())) { return interpreterProxy->primitiveFail(); } priorHandlerObject = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeOfPointer()); hPtr = interpreterProxy->arrayValueOf(priorHandlerObject); priorHandler.handler = handler; idx = 0; while (idx < (sizeOfPointer())) { hPtr[idx] = priorHandler.bytes[idx]; idx += 1; } interpreterProxy->popthenPush(3, priorHandlerObject); } /* Answer a string containing the current working directory. */ EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void) { char *buffer; sqInt bufferSize; char *cwd; sqInt cwdString; sqInt incrementBy; sqInt maxSize; bufferSize = 100; incrementBy = 100; maxSize = 5000; while (1) { cwdString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); buffer = interpreterProxy->arrayValueOf(cwdString); /* getcwd(buffer, bufferSize) */ cwd = getcwd(buffer, bufferSize); if (!((cwd == 0) && (bufferSize < maxSize))) break; bufferSize += incrementBy; } if (cwd == 0) { return interpreterProxy->primitiveFail(); } else { cwdString = stringFromCString(cwd); interpreterProxy->pop(1); interpreterProxy->push(cwdString); } } /* Answer the effective group ID of my OS process */ EXPORT(sqInt) primitiveGetEGid(void) { gid_t eGid; eGid = getegid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eGid); } /* Answer the effective user ID of my OS process */ EXPORT(sqInt) primitiveGetEUid(void) { uid_t eUid; eUid = geteuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eUid); } /* Answer the group ID of my OS process */ EXPORT(sqInt) primitiveGetGid(void) { gid_t gid; gid = getgid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(gid); } /* Answer the process group ID of the process identified by pid */ EXPORT(sqInt) primitiveGetPGid(void) { pid_t pgid; pid_t pid; pid = interpreterProxy->stackIntegerValue(0); pgid = getpgid(pid); if (pgid == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); interpreterProxy->pushInteger(pgid); } /* Answer the process group ID of this OS process */ EXPORT(sqInt) primitiveGetPGrp(void) { pid_t pgid; pgid = getpgrp(); if (pgid == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); interpreterProxy->pushInteger(pgid); } /* Answer the process ID of the parent process of my OS process */ EXPORT(sqInt) primitiveGetPPid(void) { pid_t ppid; ppid = getppid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(ppid); } /* Answer the process ID of my OS process */ EXPORT(sqInt) primitiveGetPid(void) { pid_t pid; pid = getpid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } /* Answer the unique session identifier for this Smalltalk instance running in this OS process. The C integer value is coerced into a Smalltalk ByteArray to preserve the full range of possible values. */ EXPORT(sqInt) primitiveGetSession(void) { unsigned char *sessionByteArrayPointer; sqInt sessionIDSize; sqInt sessionOop; SESSIONIDENTIFIERTYPE thisSessionID; thisSessionID = interpreterProxy->getThisSessionID(); sessionIDSize = sizeof(thisSessionID); sessionOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sessionIDSize); sessionByteArrayPointer = interpreterProxy->arrayValueOf(sessionOop); if (thisSessionID == null) { return interpreterProxy->primitiveFail(); } copyBytesFromtolength((unsigned char *)&thisSessionID, sessionByteArrayPointer, sessionIDSize); interpreterProxy->pop(1); interpreterProxy->push(sessionOop); } /* Answer the file handle for standard error of my OS process */ EXPORT(sqInt) primitiveGetStdErrHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard error of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process */ EXPORT(sqInt) primitiveGetStdInHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process */ EXPORT(sqInt) primitiveGetStdOutHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the ID of the pthread that is currently executing (the interpreter thread). A thread ID may be a 64 bit value on some platforms, so answer a byte array containing the value in machine-dependent byte order. */ EXPORT(sqInt) primitiveGetThreadID(void) { interpreterProxy->popthenPush(1, newPthreadTypeByteArray(vmThread)); } /* Answer the user ID of my OS process */ EXPORT(sqInt) primitiveGetUid(void) { uid_t uid; uid = getuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(uid); } /* Take a struct SQFile from the stack, and call feof(3) to determine if the file has reached end of file. */ /* Deprecated. The return values are reversed. Use primitiveTestEndOfFileFlag. */ EXPORT(sqInt) primitiveIsAtEndOfFile(void) { FILEHANDLETYPE file; sqInt result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); if (file == 0) { return primitiveFail(); } if (feof(file)) { result = interpreterProxy->trueObject(); } else { result = interpreterProxy->falseObject(); } interpreterProxy->pop(2); interpreterProxy->push(result); } /* Set a list of pids to kill with signum when VM exits. If the signum parameter is nil, the default value of SIGTERM will be used. */ EXPORT(sqInt) primitiveKillOnExit(void) { sqInt count; pid_t *p; pid_t pid; sqInt *pidPointer; sqInt pids; sqInt signum; pids = interpreterProxy->stackValue(1); signum = interpreterProxy->stackValue(0); pidCount = interpreterProxy->stSizeOf(pids); if (interpreterProxy->failed()) { return null; } if (!(pidArray == 0)) { free(pidArray); } pidArray = malloc(pidCount * sizeof(pid_t)); if (pidArray == 0) { pidCount = 0; return interpreterProxy->primitiveFail(); } pidPointer = interpreterProxy->firstIndexableField(pids); count = 0; p = pidArray; while (count <= pidCount) { pid = ((*pidPointer++) >> 1); *p++ = pid; count += 1; } if (!(signum == (interpreterProxy->nilObject()))) { sigNumToSend = interpreterProxy->checkedIntegerValueOf(signum); } if (interpreterProxy->failed()) { pidCount = 0; } interpreterProxy->pop(2); } /* Take a struct SQFile from the stack, and request a lock on the specified region. If the exclusive flag is true, then request an exclusive (F_WRLCK) lock on the file. Otherwise, request a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). Answer the result of the call to fcntl(). If length is zero, then the entire file will be locked, including region extents that have not yet been allocated for the file. */ EXPORT(sqInt) primitiveLockFileRegion(void) { sqInt exclusive; int fileNo; sqInt len; struct flock lockStruct; int result; sqInt sqFileOop; sqInt start; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipe(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Answer a string containing the module name string for this plugin. */ EXPORT(sqInt) primitiveModuleName(void) { interpreterProxy->popthenPush(1, stringFromCString(moduleName)); } /* Change the scheduling priority of this process by the given nice increment. A positive increment decreases the priority. Only the superuser can specify a negative value (to increase the priority). See man(2) nice. Different versions of Unix are inconsistent in their return values. The only reliable test for success is to clear errno prior to the call, and test its value if the result of nice() is -1. */ EXPORT(sqInt) primitiveNice(void) { extern int errno; int niceIncrement; sqInt result; niceIncrement = interpreterProxy->stackIntegerValue(0); errno = 0; result = nice(niceIncrement); if (result == -1) { if (!(errno == 0)) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Set an environment variable using a string of the form 'KEY=value'. This implementation allocates a C string using malloc to allocate from the C heap (using cStringFromString rather than transientCStringFromString). This is necessary because the C runtime library does not make a copy of the string into separately allocated environment memory. */ EXPORT(sqInt) primitivePutEnv(void) { char *cStringPtr; sqInt keyValueString; keyValueString = interpreterProxy->stackObjectValue(0); cStringPtr = cStringFromString(keyValueString); if ((putenv(cStringPtr)) == 0) { interpreterProxy->pop(2); interpreterProxy->push(keyValueString); } else { return interpreterProxy->primitiveFail(); } } /* Answer the real path for a path string as determined by realpath(). */ EXPORT(sqInt) primitiveRealpath(void) { char *buffer; sqInt bufferSize; sqInt newPathString; char *pathString; char * realpathResult; sqInt s; bufferSize = 1024; newPathString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); interpreterProxy->pushRemappableOop(newPathString); pathString = transientCStringFromString(interpreterProxy->stackObjectValue(0)); newPathString = interpreterProxy->popRemappableOop(); buffer = interpreterProxy->arrayValueOf(newPathString); realpathResult = realpath(pathString, buffer); if (realpathResult == 0) { return interpreterProxy->primitiveFail(); } else { if ((strlen(realpathResult)) >= 1024) { perror("warning: statically allocated array exceeded in UnixOSProcessPlugin>>primitiveRealPath, object memory may have been corrupted"); return interpreterProxy->primitiveFail(); } s = stringFromCString(realpathResult); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Clean up after the death of a child, and answer an array with the pid and the exit status of the child process. Answer nil if the pidToHandle does not exist. */ EXPORT(sqInt) primitiveReapChildProcess(void) { sqInt *arrayPtr; int exitStatus; pid_t pidResult; sqInt pidToHandle; sqInt resultArray; /* Force C code translator to declare the variable */ exitStatus = 0; pidToHandle = interpreterProxy->stackIntegerValue(0); pidResult = waitpid ( pidToHandle, &exitStatus, WNOHANG ); if (pidResult <= 0) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { /* Answer an array with pid and result status */ resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); arrayPtr = interpreterProxy->firstIndexableField(resultArray); arrayPtr[0] = integerObjectOf(pidResult); arrayPtr[1] = integerObjectOf(exitStatus); interpreterProxy->pop(2); interpreterProxy->push(resultArray); } } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. */ EXPORT(sqInt) primitiveSQFileFlush(void) { int result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } result = fflush(fileHandleFrom(sqFileOop)); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void) { int result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } result = fflush(fileHandleFrom(sqFileOop)); interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetBlocking(void) { sqInt descriptor; int flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor == -1) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void) { sqInt descriptor; sqInt flags; sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetNonBlocking(void) { sqInt descriptor; int flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void) { sqInt descriptor; sqInt flags; sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. */ EXPORT(sqInt) primitiveSQFileSetUnbuffered(void) { FILEHANDLETYPE file; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); retVal = fflush(file); setbuf(file, 0); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void) { sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { retVal = fflush(sqFile->file); setbuf(sqFile->file, NULL); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Answer the registration index of the semaphore currently associated with the signal handler for sigNum. */ EXPORT(sqInt) primitiveSemaIndexFor(void) { sqInt index; sqInt sigNum; sigNum = interpreterProxy->stackIntegerValue(0); index = semaIndices[sigNum]; interpreterProxy->pop(2); interpreterProxy->pushInteger(index); } /* Send SIGABRT (abort) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigAbrtNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGALRM (alarm clock) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigAlrmNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCHLD (child status has changed, usually death of child) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigChldNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCONT (continue) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigContNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGHUP (hangup) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigHupNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGINT (interrupt) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigIntNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGKILL (kill, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigKillNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGPIPE (broken pipe) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigPipeNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGQUIT (quit) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigQuitNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGSTOP (stop, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigStopNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGTERM (termination) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigTermNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR1 (User-defined signal 1) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigUsr1Number(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR2 (User-defined signal 2) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigUsr2Number(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Set the process group ID of the process identified by pid to a new process group ID. */ EXPORT(sqInt) primitiveSetPGid(void) { pid_t pgid; pid_t pid; pid = interpreterProxy->stackIntegerValue(1); pgid = interpreterProxy->stackIntegerValue(0); if ((setpgid(pid, pgid)) == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); } /* Set a new process group for this OS process. Newly created child processes will be members of the new process group. Note: Use setpgid(0,0) rather than the equivalent setpgrp() because setpgrp() is implemented differently on some flavors of Unix. */ EXPORT(sqInt) primitiveSetPGrp(void) { if ((setpgid(0, 0)) == -1) { return interpreterProxy->primitiveFail(); } } /* Set the index of the semaphore used by the OSProcess with which I collaborate. My OSProcess should set this value so that I can use it when handling SIGCHLD signals (death of child). In the C translation this is a static int which would be shared by all instances of UnixOSProcessPlugin, which is expected to be a singleton. Answer the value of the semaphore index. */ EXPORT(sqInt) primitiveSetSemaIndex(void) { sigChldSemaIndex = interpreterProxy->stackIntegerValue(0); interpreterProxy->pop(2); interpreterProxy->pushInteger(sigChldSemaIndex); } /* Quoted from Linux man pages: setsid() creates a new session if the calling process is not a process group leader. The calling process is the leader of the new session, the process group leader of the new process group, and has no controlling tty. The process group ID and session ID of the calling process are set to the PID of the calling process. The calling process will be the only process in this new process group and in this new session. */ EXPORT(sqInt) primitiveSetSid(void) { pid_t sessionId; sessionId = setsid(); if (sessionId == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); interpreterProxy->pushInteger(sessionId); } /* Integer value corresponding to SIGCHLD */ EXPORT(sqInt) primitiveSigChldNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigChldNumber()); } /* Integer value corresponding to SIGHUP */ EXPORT(sqInt) primitiveSigHupNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigHupNumber()); } /* Integer value corresponding to SIGINT */ EXPORT(sqInt) primitiveSigIntNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigIntNumber()); } /* Integer value corresponding to SIGKILL */ EXPORT(sqInt) primitiveSigKillNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigKillNumber()); } /* Integer value corresponding to SIGPIPE */ EXPORT(sqInt) primitiveSigPipeNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigPipeNumber()); } /* Integer value corresponding to SIGQUIT */ EXPORT(sqInt) primitiveSigQuitNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigQuitNumber()); } /* Integer value corresponding to SIGTERM */ EXPORT(sqInt) primitiveSigTermNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigTermNumber()); } /* Integer value corresponding to SIGUSR1 */ EXPORT(sqInt) primitiveSigUsr1Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr1Number()); } /* Integer value corresponding to SIGUSR2 */ EXPORT(sqInt) primitiveSigUsr2Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr2Number()); } /* Size in bytes of an integer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfInt(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfInt()); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfPointer(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfPointer()); } /* Take a struct SQFile from the stack, and call feof(3) to determine if the file has reached end of file. The flag is set only by a previous read operation, so end of file is not detected until an actual EOF condition has been detected by a read attempt. */ EXPORT(sqInt) primitiveTestEndOfFileFlag(void) { FILEHANDLETYPE file; sqInt result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); if (file == 0) { return primitiveFail(); } if (feof(file)) { result = interpreterProxy->trueObject(); } else { result = interpreterProxy->falseObject(); } interpreterProxy->pop(2); interpreterProxy->push(result); } /* Take a struct SQFile from the stack, and check for ability to lock the specified region. If the exclusive flag is true, then specify an exclusive (F_WRLCK) lock on the file. Otherwise, specify a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). If length is zero, then the request is for the entire file to be locked, including region extents that have not yet been allocated for the file. If the fcntl() call fails, answer -1 (the result of the failed call). Otherwise, answer an array with the following six fields: lockable (true or false) l_pid (pid of the process preventing this lock request, or nil) l_type (request type F_WRLCK or F_RDLOCK of the process preventing this lock request) l_whence (the SEEK_SET, SEEK_CUR, or SEEK_END value of the lock preventing this lock request). l_start (offset of the region lock preventing this lock request) l_len (length of the region lock preventing this lock request) */ EXPORT(sqInt) primitiveTestLockableFileRegion(void) { sqInt canObtainLock; sqInt exclusive; int fileNo; sqInt len; struct flock lockStruct; int result; sqInt resultArray; sqInt sqFileOop; sqInt start; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_GETLK, &lockStruct); if (result == -1) { interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } else { if (lockStruct.l_type == F_UNLCK) { canObtainLock = interpreterProxy->trueObject(); } else { canObtainLock = interpreterProxy->falseObject(); } resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 6); interpreterProxy->stObjectatput(resultArray, 1, canObtainLock); interpreterProxy->stObjectatput(resultArray, 2, (((lockStruct.l_pid) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 3, (((lockStruct.l_type) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 4, (((lockStruct.l_whence) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 5, (((lockStruct.l_start) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 6, (((lockStruct.l_len) << 1) | 1)); interpreterProxy->popthenPush(5, resultArray); } } /* Close a file handle at the close(2) level, using a handle returned by #primitiveUnixFileNumber. */ EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber) { int handle; int result; handle = interpreterProxy->stackIntegerValue(0); result = close(handle); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and answer the value of its Unix file number. The Unix file number is not directly useful to Squeak, but may be interesting for debugging problems involving failure to close unused file handles. */ EXPORT(sqInt) primitiveUnixFileNumber(void) { int fileNo; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); interpreterProxy->pop(2); interpreterProxy->pushInteger(fileNo); } /* Take a struct SQFile from the stack, and unlock the specified region. Answer the result of the call to fcntl(). If the region is in the file lock cache, remove it, but otherwise ignore the cache. The cache supports Win32 semantics within a single Squeak image, but not across separate images, therefore the unlock should be attempted regardless of whether this image thinks that the region has previously been locked. Answer the result of the call to fcntl(). */ EXPORT(sqInt) primitiveUnlockFileRegion(void) { int fileNo; sqInt len; struct flock lockStruct; int result; sqInt sqFileOop; sqInt start; len = interpreterProxy->stackIntegerValue(0); start = interpreterProxy->stackIntegerValue(1); sqFileOop = interpreterProxy->stackValue(2); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); lockStruct.l_type = F_UNLCK; lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(4); interpreterProxy->pushInteger(result); } /* Unset an environment variable. */ /* FIXME: unsetenv() is not portable. For Solaris or any other system which does not support unsetenv(), just comment it out in this method and rebuild the plugin. */ EXPORT(sqInt) primitiveUnsetEnv(void) { unsetenv(transientCStringFromString(interpreterProxy->stackObjectValue(0))); interpreterProxy->pop(1); } /* Answer a string containing the version string for this plugin. */ EXPORT(sqInt) primitiveVersionString(void) { interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(versionString())); } /* This is a signal handler for SIGCHLD. It is not meant to be called from Smalltalk, and should only be called indirectly as a result of a death of child signal from the operating system. Child processes must be cleaned up by the parent, otherwise they continue to exist as zombies until the parent exits. This handler resets the signal handler to catch the next SIGCHLD signal, then sets a semaphore to notify the system that a child process needs to be cleaned up. The actual clean up is done by a Smalltalk process which waits on the semaphore, then calls primitiveReapChildProcess. Note: If child processes die faster than we can clean them up, signals will be lost and child processes will remain as zombies. */ static void reapChildProcess(int sigNum) { setSigChldHandler(); if (sigChldSemaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(sigChldSemaIndex); } } /* Signal sigNum has been caught by a thread other than the pthread in which the interpreter is executing. Rather than handling it in this thread, resend it to the interpreter thread. */ static sqInt resendSignal(int sigNum) { pthread_kill(vmThread, sigNum); } /* Restore signal handlers to their original behaviors. */ static void restoreDefaultSignalHandlers(void) { sqInt sigNum; sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Answer 1 if running in secure mode, else 0. The osprocessSandboxSecurity variable is initialized to -1. On the first call to this method, set its value to either 0 (user has full access to the plugin) or 1 (user is not permitted to do dangerous things). */ static sqInt sandboxSecurity(void) { if (osprocessSandboxSecurity < 0) { osprocessSandboxSecurity = securityHeurisitic(); } return osprocessSandboxSecurity; } /* Answer 0 to permit full access to OSProcess functions, or 1 if access should be restricted for dangerous functions. The rules are: - If the security plugin is not present, grant full access - If the security plugin can be loaded, restrict access unless user has all of secCanWriteImage, secHasFileAccess and secHasSocketAccess */ /* FIXME: This function has not been tested. -dtl */ /* If the security plugin can be loaded, use it to check. If not, assume it's ok */ static sqInt securityHeurisitic(void) { sqInt canWriteImage; sqInt hasFileAccess; sqInt hasSocketAccess; void (*sCWIfn)(void); void (*sHFAfn)(void); void (*sHSAfn)(void); sCWIfn = interpreterProxy->ioLoadFunctionFrom("secCanWriteImage", "SecurityPlugin"); if (sCWIfn == 0) { return 0; } canWriteImage = ((int (*) (void)) sCWIfn)(); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); if (sHFAfn == 0) { return 0; } hasFileAccess = ((int (*) (void)) sHFAfn)(); sHSAfn = interpreterProxy->ioLoadFunctionFrom("secHasSocketAccess", "SecurityPlugin"); if (sHSAfn == 0) { return 0; } hasSocketAccess = ((int (*) (void)) sHSAfn)(); if ((canWriteImage && (hasFileAccess)) && (hasSocketAccess)) { return 0; } else { return 1; } } /* An array of Smalltalk Semaphore indices, one for each signal type for which a handler has been set. If an entry is zero, then no handler is active. */ static unsigned char * semaphoreIndices(void) { return semaIndices; } /* kill(pid, sig) */ static sqInt sendSignaltoPid(sqInt sig, sqInt pid) { return kill(pid, sig); } /* Exit function to be registered with atexit() to signal child processes on VM exit. */ static void sendSignalToPids(void) { sqInt count; pid_t pid; sqInt sig; count = 0; while (count < pidCount) { pid = pidArray[count]; /* begin sendSignal:toPid: */ sig = sigNumToSend; kill(pid, sig); count += 1; } } /* Answer a session ID represented by aByteArray. The session ID is used in the SQFile structure. If that data structure changes, we should see compiler warnings about type mismatch with SESSIONIDENTIFIERTYPE. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray) { sqInt idx; unsigned char *session; union {SESSIONIDENTIFIERTYPE session; unsigned char bytes[sizeof(SESSIONIDENTIFIERTYPE)];} sessionUnion; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfSession())))) { return null; } session = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfSession())) { sessionUnion.bytes[idx] = session[idx]; idx += 1; } return sessionUnion.session; } /* Answer the session identifier from a SQFile structure. For a valid file reference, this identifier will match the session identifier supplied by the interpreter. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile) { return sqFile->sessionID; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void setSigChldDefaultHandler(void) { setSignalNumberhandler(sigChldNumber(), sigDefaultNumber()); } /* Set the SIGCHLD signal handler in the virtual machine. */ static void setSigChldHandler(void) { if ((signal(SIGCHLD, reapChildProcess)) == (sigErrorNumber())) { perror("signal"); } } static void setSigIntDefaultHandler(void) { setSignalNumberhandler(sigIntNumber(), sigDefaultNumber()); } /* Set the SIGINT signal handler in the virtual machine to ignore interrupts. */ static void setSigIntIgnore(void) { setSignalNumberhandler(sigIntNumber(), sigIgnoreNumber()); } static void setSigPipeDefaultHandler(void) { setSignalNumberhandler(sigPipeNumber(), sigDefaultNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. If a pipe is opened to a child process, and the child exits, then subsequent writes to the pipe generate a SIGPIPE signal. If this signal is not handled, the VM will exit without warning. */ static sqInt setSigPipeHandler(void) { /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. */ static void setSigPipeIgnore(void) { setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } /* Set a signal handler. The C code translator will convert #sig:nal: into 'signal(parm1, parm2)' */ static void * setSignalNumberhandler(sqInt anInteger, void *signalHandlerAddress) { return signal(anInteger, signalHandlerAddress); } EXPORT(sqInt) shutdownModule(void) { sqInt sigNum; /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Abort signal from abort(3) */ static sqInt sigAbrtNumber(void) { return SIGABRT; } /* Timer signal from alarm(2) */ static sqInt sigAlrmNumber(void) { return SIGALRM; } /* Child status has changed (POSIX). */ static sqInt sigChldNumber(void) { return SIGCHLD; } /* Continue if stopped */ static sqInt sigContNumber(void) { return SIGCONT; } /* Default action for a signal */ static void * sigDefaultNumber(void) { return SIG_DFL; } /* Error return from signal() */ static void * sigErrorNumber(void) { return SIG_ERR; } /* Hangup detected on controlling terminal or death of controlling process */ static sqInt sigHupNumber(void) { return SIGHUP; } /* Ignore action for a signal */ static void * sigIgnoreNumber(void) { return SIG_IGN; } /* Interrupt (ANSI). */ static sqInt sigIntNumber(void) { return SIGINT; } /* Kill signal */ static sqInt sigKillNumber(void) { return SIGKILL; } /* Broken pipe (POSIX). */ static sqInt sigPipeNumber(void) { return SIGPIPE; } /* Quit from keyboard */ static sqInt sigQuitNumber(void) { return SIGQUIT; } /* Stop process */ static sqInt sigStopNumber(void) { return SIGSTOP; } /* Termination signal. This is the default signal sent by the unix kill(1) command. */ static sqInt sigTermNumber(void) { return SIGTERM; } /* User defined signal number 1. This is value is platform-dependent, so the inSmalltalk default of 10 may be wrong on some platforms. */ static sqInt sigUsr1Number(void) { return SIGUSR1; } /* User defined signal number 2. This is value is platform-dependent, so the inSmalltalk default of 12 may be wrong on some platforms. */ static sqInt sigUsr2Number(void) { return SIGUSR2; } /* Number of possible signals for this OS plus one. The signal handler arrays declared in #declareCVarsIn: are this size. */ static sqInt signalArraySize(void) { return NSIG; } /* An array of signal handler function addresses, with each entry corresponding to a signal type. */ static void ** signalHandlers(void) { return sigHandlers; } /* Size in bytes of an integer, for this C compiler on this machine. */ static sqInt sizeOfInt(void) { return sizeof(int); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ static sqInt sizeOfPointer(void) { return sizeof(void *); } /* Size of a SESSIONIDENTIFIERTYPE. Should match usage in the SQFile data structure, otherwise we should get compiler warnings. */ static sqInt sizeOfSession(void) { return sizeof(SESSIONIDENTIFIERTYPE); } /* Answer the OS file descriptor, an integer value, from a SQSocket data structure, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). Warning: The first element of privateSocketStruct happens to be the Unix file number of the socket. See sqUnixSocket.c for the definition. This method takes advantage of this, and will break if anyone ever redefines the data structure. */ static int socketDescriptorFrom(sqInt sqSocketOop) { void *privateSocketStruct; SQSocket *sqSocket; sqSocket = interpreterProxy->arrayValueOf(sqSocketOop); privateSocketStruct = sqSocket->privateSocketPtr; if (privateSocketStruct == 0) { return -1; } return * (int *) privateSocketStruct; } /* Answer the size of a SQSocket data structure in bytes. */ static sqInt socketRecordSize(void) { return sizeof(SQSocket); } /* Return a pointer to the first byte of of the SQsocket data structure socket record within anSQSocketRecord, which is expected to be a ByteArray of size self>>socketRecordSize. */ static SQSocket * socketValueOf(sqInt anSQSocketRecord) { return interpreterProxy->arrayValueOf(anSQSocketRecord); } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char *aCString) { sqInt len; sqInt newString; len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } /* Answer a new null-terminated C string copied from aString. The string is allocated in object memory, and will be moved without warning by the garbage collector. Any C pointer reference the the result is valid only until the garbage collector next runs. Therefore, this method should only be used within a single primitive in a section of code in which the garbage collector is guaranteed not to run. Note also that this method may itself invoke the garbage collector prior to allocating the new C string. Warning: The result of this method will be invalidated by the next garbage collection, including a GC triggered by creation of a new object within a primitive. Do not call this method twice to obtain two string pointers. */ static char * transientCStringFromString(sqInt aString) { char *cString; sqInt len; sqInt newString; char *stringPtr; /* Allocate space for a null terminated C string. */ len = interpreterProxy->sizeOfSTArrayFromCPrimitive(interpreterProxy->arrayValueOf(aString)); interpreterProxy->pushRemappableOop(aString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len + 1); stringPtr = interpreterProxy->arrayValueOf(interpreterProxy->popRemappableOop()); /* Point to the actual C string. */ cString = interpreterProxy->arrayValueOf(newString); (char *)strncpy(cString, stringPtr, len); cString[len] = 0; return cString; } /* Answer the integer Unix file number corresponding to a file handle (FILE* ). */ static int unixFileNumber(FILEHANDLETYPE fileHandle) { return fileno(fileHandle); } /* Answer a string containing the version string for this plugin. Handle MNU errors, which can occur if class InterpreterPlugin has been removed from the system. Important: When this method is changed, the class side method must also be changed to match. */ /* 4.0 supports 64bit code base */ static char * versionString(void) { static char version[]= "4.3.3"; return version; } #ifdef SQUEAK_BUILTIN_PLUGIN void* UnixOSProcessPlugin_exports[][3] = { {"UnixOSProcessPlugin", "primitiveSQFileSetBlocking", (void*)primitiveSQFileSetBlocking}, {"UnixOSProcessPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"UnixOSProcessPlugin", "primitiveSigTermNumber", (void*)primitiveSigTermNumber}, {"UnixOSProcessPlugin", "primitiveSigQuitNumber", (void*)primitiveSigQuitNumber}, {"UnixOSProcessPlugin", "primitiveSigHupNumber", (void*)primitiveSigHupNumber}, {"UnixOSProcessPlugin", "primitiveSendSigquitTo", (void*)primitiveSendSigquitTo}, {"UnixOSProcessPlugin", "forkSqueak", (void*)forkSqueak}, {"UnixOSProcessPlugin", "primitiveFileStat", (void*)primitiveFileStat}, {"UnixOSProcessPlugin", "primitiveFileProtectionMask", (void*)primitiveFileProtectionMask}, {"UnixOSProcessPlugin", "primitiveSQFileFlush", (void*)primitiveSQFileFlush}, {"UnixOSProcessPlugin", "primitiveForkSqueak", (void*)primitiveForkSqueak}, {"UnixOSProcessPlugin", "primitiveGetPid", (void*)primitiveGetPid}, {"UnixOSProcessPlugin", "shutdownModule", (void*)shutdownModule}, {"UnixOSProcessPlugin", "primitiveVersionString", (void*)primitiveVersionString}, {"UnixOSProcessPlugin", "primitiveGetCurrentWorkingDirectory", (void*)primitiveGetCurrentWorkingDirectory}, {"UnixOSProcessPlugin", "primitiveForkExec", (void*)primitiveForkExec}, {"UnixOSProcessPlugin", "primitiveTestEndOfFileFlag", (void*)primitiveTestEndOfFileFlag}, {"UnixOSProcessPlugin", "primitiveGetPGrp", (void*)primitiveGetPGrp}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandleWithSessionIdentifier", (void*)primitiveGetStdOutHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetStdInHandleWithSessionIdentifier", (void*)primitiveGetStdInHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSigUsr1Number", (void*)primitiveSigUsr1Number}, {"UnixOSProcessPlugin", "primitiveGetGid", (void*)primitiveGetGid}, {"UnixOSProcessPlugin", "primitiveForkSqueakWithoutSigHandler", (void*)primitiveForkSqueakWithoutSigHandler}, {"UnixOSProcessPlugin", "primitiveSendSigabrtTo", (void*)primitiveSendSigabrtTo}, {"UnixOSProcessPlugin", "primitivePutEnv", (void*)primitivePutEnv}, {"UnixOSProcessPlugin", "primitiveGetEGid", (void*)primitiveGetEGid}, {"UnixOSProcessPlugin", "primitiveSigIntNumber", (void*)primitiveSigIntNumber}, {"UnixOSProcessPlugin", "primitiveSigKillNumber", (void*)primitiveSigKillNumber}, {"UnixOSProcessPlugin", "primitiveTestLockableFileRegion", (void*)primitiveTestLockableFileRegion}, {"UnixOSProcessPlugin", "primitiveSetPGid", (void*)primitiveSetPGid}, {"UnixOSProcessPlugin", "primitiveSetSemaIndex", (void*)primitiveSetSemaIndex}, {"UnixOSProcessPlugin", "primitiveLockFileRegion", (void*)primitiveLockFileRegion}, {"UnixOSProcessPlugin", "primitiveSendSigusr1To", (void*)primitiveSendSigusr1To}, {"UnixOSProcessPlugin", "primitiveAioHandle", (void*)primitiveAioHandle}, {"UnixOSProcessPlugin", "primitiveGetThreadID", (void*)primitiveGetThreadID}, {"UnixOSProcessPlugin", "primitiveSendSigalrmTo", (void*)primitiveSendSigalrmTo}, {"UnixOSProcessPlugin", "primitiveMakePipe", (void*)primitiveMakePipe}, {"UnixOSProcessPlugin", "primitiveGetSession", (void*)primitiveGetSession}, {"UnixOSProcessPlugin", "primitiveForkAndExecInDirectory", (void*)primitiveForkAndExecInDirectory}, {"UnixOSProcessPlugin", "primitiveGetUid", (void*)primitiveGetUid}, {"UnixOSProcessPlugin", "primitiveSigPipeNumber", (void*)primitiveSigPipeNumber}, {"UnixOSProcessPlugin", "primitiveSizeOfInt", (void*)primitiveSizeOfInt}, {"UnixOSProcessPlugin", "primitiveChdir", (void*)primitiveChdir}, {"UnixOSProcessPlugin", "primitiveSendSighupTo", (void*)primitiveSendSighupTo}, {"UnixOSProcessPlugin", "primitiveSendSigchldTo", (void*)primitiveSendSigchldTo}, {"UnixOSProcessPlugin", "primitiveForwardSignalToSemaphore", (void*)primitiveForwardSignalToSemaphore}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlocking", (void*)primitiveSQFileSetNonBlocking}, {"UnixOSProcessPlugin", "primitiveSetSid", (void*)primitiveSetSid}, {"UnixOSProcessPlugin", "primitiveRealpath", (void*)primitiveRealpath}, {"UnixOSProcessPlugin", "primitiveSendSigpipeTo", (void*)primitiveSendSigpipeTo}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandle", (void*)primitiveGetStdOutHandle}, {"UnixOSProcessPlugin", "primitiveSendSigintTo", (void*)primitiveSendSigintTo}, {"UnixOSProcessPlugin", "primitiveAioSuspend", (void*)primitiveAioSuspend}, {"UnixOSProcessPlugin", "primitiveSendSigtermTo", (void*)primitiveSendSigtermTo}, {"UnixOSProcessPlugin", "setInterpreter", (void*)setInterpreter}, {"UnixOSProcessPlugin", "primitiveSQFileSetBlockingWithSessionIdentifier", (void*)primitiveSQFileSetBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetPPid", (void*)primitiveGetPPid}, {"UnixOSProcessPlugin", "initialiseModule", (void*)initialiseModule}, {"UnixOSProcessPlugin", "primitiveSigUsr2Number", (void*)primitiveSigUsr2Number}, {"UnixOSProcessPlugin", "primitiveSendSigusr2To", (void*)primitiveSendSigusr2To}, {"UnixOSProcessPlugin", "primitiveSendSigkillTo", (void*)primitiveSendSigkillTo}, {"UnixOSProcessPlugin", "primitiveSemaIndexFor", (void*)primitiveSemaIndexFor}, {"UnixOSProcessPlugin", "primitiveReapChildProcess", (void*)primitiveReapChildProcess}, {"UnixOSProcessPlugin", "primitiveErrorMessageAt", (void*)primitiveErrorMessageAt}, {"UnixOSProcessPlugin", "primitiveArgumentAt", (void*)primitiveArgumentAt}, {"UnixOSProcessPlugin", "primitiveGetPGid", (void*)primitiveGetPGid}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandle", (void*)primitiveGetStdErrHandle}, {"UnixOSProcessPlugin", "primitiveUnixFileClose", (void*)primitiveUnixFileClose}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlockingWithSessionIdentifier", (void*)primitiveSQFileSetNonBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveAioEnable", (void*)primitiveAioEnable}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbuffered", (void*)primitiveSQFileSetUnbuffered}, {"UnixOSProcessPlugin", "primitiveUnixFileNumber", (void*)primitiveUnixFileNumber}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandleWithSessionIdentifier", (void*)primitiveGetStdErrHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveKillOnExit", (void*)primitiveKillOnExit}, {"UnixOSProcessPlugin", "primitiveCanReceiveSignals", (void*)primitiveCanReceiveSignals}, {"UnixOSProcessPlugin", "primitiveMakePipeWithSessionIdentifier", (void*)primitiveMakePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetEUid", (void*)primitiveGetEUid}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbufferedWithSessionIdentifier", (void*)primitiveSQFileSetUnbufferedWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSizeOfPointer", (void*)primitiveSizeOfPointer}, {"UnixOSProcessPlugin", "primitiveDupTo", (void*)primitiveDupTo}, {"UnixOSProcessPlugin", "primitiveSigChldNumber", (void*)primitiveSigChldNumber}, {"UnixOSProcessPlugin", "primitiveGetStdInHandle", (void*)primitiveGetStdInHandle}, {"UnixOSProcessPlugin", "primitiveCreatePipe", (void*)primitiveCreatePipe}, {"UnixOSProcessPlugin", "primitiveUnlockFileRegion", (void*)primitiveUnlockFileRegion}, {"UnixOSProcessPlugin", "primitiveModuleName", (void*)primitiveModuleName}, {"UnixOSProcessPlugin", "primitiveFixPointersInArrayOfStrings", (void*)primitiveFixPointersInArrayOfStrings}, {"UnixOSProcessPlugin", "primitiveUnsetEnv", (void*)primitiveUnsetEnv}, {"UnixOSProcessPlugin", "primitiveNice", (void*)primitiveNice}, {"UnixOSProcessPlugin", "primitiveSendSigcontTo", (void*)primitiveSendSigcontTo}, {"UnixOSProcessPlugin", "primitiveEnvironmentAt", (void*)primitiveEnvironmentAt}, {"UnixOSProcessPlugin", "primitiveSendSigstopTo", (void*)primitiveSendSigstopTo}, {"UnixOSProcessPlugin", "primitiveEnvironmentAtSymbol", (void*)primitiveEnvironmentAtSymbol}, {"UnixOSProcessPlugin", "primitiveSetPGrp", (void*)primitiveSetPGrp}, {"UnixOSProcessPlugin", "primitiveCreatePipeWithSessionIdentifier", (void*)primitiveCreatePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveIsAtEndOfFile", (void*)primitiveIsAtEndOfFile}, {"UnixOSProcessPlugin", "getModuleName", (void*)getModuleName}, {"UnixOSProcessPlugin", "primitiveAioDisable", (void*)primitiveAioDisable}, {"UnixOSProcessPlugin", "primitiveSQFileFlushWithSessionIdentifier", (void*)primitiveSQFileFlushWithSessionIdentifier}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/intplugins/ZipPlugin/ZipPlugin.c ================================================ /* Automatically generated by VMPluginCodeGenerator VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 from DeflatePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 */ static char __buildInfo[] = "DeflatePlugin VMMaker-oscog.dtl.57 uuid: c1d30608-04dd-53b7-209a-34f7a46c1508 " __DATE__ ; #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ #define DeflateHashMask 0x7FFF #define DeflateHashShift 5 #define DeflateHashTableSize 32768 #define DeflateMaxDistance 0x8000 #define DeflateMaxDistanceCodes 30 #define DeflateMaxLiteralCodes 0x11E #define DeflateMaxMatch 258 #define DeflateMinMatch 3 #define DeflateWindowMask 0x7FFF #define DeflateWindowSize 32768 #define MaxBits 16 #define StateNoMoreData 1 /*** Function Prototypes ***/ static sqInt comparewithmin(sqInt here, sqInt matchPos, sqInt minLength); static sqInt deflateBlockchainLengthgoodMatch(sqInt lastIndex, sqInt chainLength, sqInt goodMatch); static sqInt encodeLiteral(sqInt lit); static sqInt encodeMatchdistance(sqInt length, sqInt dist); static sqInt findMatchlastLengthlastMatchchainLengthgoodMatch(sqInt here, sqInt lastLength, sqInt lastMatch, sqInt maxChainLength, sqInt goodMatch); static VirtualMachine * getInterpreter(void); EXPORT(const char*) getModuleName(void); static sqInt halt(void); static sqInt insertStringAt(sqInt here); static sqInt loadDeflateStreamFrom(sqInt rcvr); static sqInt loadZipEncoderFrom(sqInt rcvr); static sqInt msg(char *s); static sqInt nextZipBitsput(sqInt nBits, sqInt value); EXPORT(sqInt) primitiveDeflateBlock(void); EXPORT(sqInt) primitiveDeflateUpdateHashTable(void); EXPORT(sqInt) primitiveInflateDecompressBlock(void); EXPORT(sqInt) primitiveUpdateAdler32(void); EXPORT(sqInt) primitiveUpdateGZipCrc32(void); EXPORT(sqInt) primitiveZipSendBlock(void); static sqInt sendBlockwithwithwith(sqInt literalStream, sqInt distanceStream, sqInt litTree, sqInt distTree); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt shouldFlush(void); static sqInt updateHashAt(sqInt here); static sqInt updateHash(sqInt nextValue); static sqInt zipDecodeValueFromsize(unsigned int *table, sqInt tableSize); static sqInt zipDecompressBlock(void); static sqInt zipNextBits(sqInt n); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "ZipPlugin VMMaker-oscog.dtl.57 (i)" #else "ZipPlugin VMMaker-oscog.dtl.57 (e)" #endif ; static unsigned int zipBaseDistance[] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576}; static unsigned int zipBaseLength[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0}; static sqInt zipBitBuf; static sqInt zipBitPos; static sqInt zipBlockPos; static sqInt zipBlockStart; static unsigned char* zipCollection; static sqInt zipCollectionSize; static unsigned int zipCrcTable[] = { 0, 1996959894, 3993919788U, 2567524794U, 124634137, 1886057615, 3915621685U, 2657392035U, 249268274, 2044508324, 3772115230U, 2547177864U, 162941995, 2125561021, 3887607047U, 2428444049U, 498536548, 1789927666, 4089016648U, 2227061214U, 450548861, 1843258603, 4107580753U, 2211677639U, 325883990, 1684777152, 4251122042U, 2321926636U, 335633487, 1661365465, 4195302755U, 2366115317U, 997073096, 1281953886, 3579855332U, 2724688242U, 1006888145, 1258607687, 3524101629U, 2768942443U, 901097722, 1119000684, 3686517206U, 2898065728U, 853044451, 1172266101, 3705015759U, 2882616665U, 651767980, 1373503546, 3369554304U, 3218104598U, 565507253, 1454621731, 3485111705U, 3099436303U, 671266974, 1594198024, 3322730930U, 2970347812U, 795835527, 1483230225, 3244367275U, 3060149565U, 1994146192, 31158534, 2563907772U, 4023717930U, 1907459465, 112637215, 2680153253U, 3904427059U, 2013776290, 251722036, 2517215374U, 3775830040U, 2137656763, 141376813, 2439277719U, 3865271297U, 1802195444, 476864866, 2238001368U, 4066508878U, 1812370925, 453092731, 2181625025U, 4111451223U, 1706088902, 314042704, 2344532202U, 4240017532U, 1658658271, 366619977, 2362670323U, 4224994405U, 1303535960, 984961486, 2747007092U, 3569037538U, 1256170817, 1037604311, 2765210733U, 3554079995U, 1131014506, 879679996, 2909243462U, 3663771856U, 1141124467, 855842277, 2852801631U, 3708648649U, 1342533948, 654459306, 3188396048U, 3373015174U, 1466479909, 544179635, 3110523913U, 3462522015U, 1591671054, 702138776, 2966460450U, 3352799412U, 1504918807, 783551873, 3082640443U, 3233442989U, 3988292384U, 2596254646U, 62317068, 1957810842, 3939845945U, 2647816111U, 81470997, 1943803523, 3814918930U, 2489596804U, 225274430, 2053790376, 3826175755U, 2466906013U, 167816743, 2097651377, 4027552580U, 2265490386U, 503444072, 1762050814, 4150417245U, 2154129355U, 426522225, 1852507879, 4275313526U, 2312317920U, 282753626, 1742555852, 4189708143U, 2394877945U, 397917763, 1622183637, 3604390888U, 2714866558U, 953729732, 1340076626, 3518719985U, 2797360999U, 1068828381, 1219638859, 3624741850U, 2936675148U, 906185462, 1090812512, 3747672003U, 2825379669U, 829329135, 1181335161, 3412177804U, 3160834842U, 628085408, 1382605366, 3423369109U, 3138078467U, 570562233, 1426400815, 3317316542U, 2998733608U, 733239954, 1555261956, 3268935591U, 3050360625U, 752459403, 1541320221, 2607071920U, 3965973030U, 1969922972, 40735498, 2617837225U, 3943577151U, 1913087877, 83908371, 2512341634U, 3803740692U, 2075208622, 213261112, 2463272603U, 3855990285U, 2094854071, 198958881, 2262029012U, 4057260610U, 1759359992, 534414190, 2176718541U, 4139329115U, 1873836001, 414664567, 2282248934U, 4279200368U, 1711684554, 285281116, 2405801727U, 4167216745U, 1634467795, 376229701, 2685067896U, 3608007406U, 1308918612, 956543938, 2808555105U, 3495958263U, 1231636301, 1047427035, 2932959818U, 3654703836U, 1088359270, 936918000, 2847714899U, 3736837829U, 1202900863, 817233897, 3183342108U, 3401237130U, 1404277552, 615818150, 3134207493U, 3453421203U, 1423857449, 601450431, 3009837614U, 3294710456U, 1567103746, 711928724, 3020668471U, 3272380065U, 1510334235, 755167117}; static unsigned int zipDistanceCodes[] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}; static unsigned int* zipDistanceFreq; static unsigned int* zipDistances; static unsigned int* zipDistTable; static sqInt zipDistTableSize; static unsigned int zipExtraDistanceBits[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; static unsigned int zipExtraLengthBits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; static unsigned int* zipHashHead; static unsigned int* zipHashTail; static sqInt zipHashValue; static sqInt zipLiteralCount; static unsigned int* zipLiteralFreq; static sqInt zipLiteralSize; static unsigned char* zipLiterals; static unsigned int* zipLitTable; static sqInt zipLitTableSize; static sqInt zipMatchCount; static unsigned int zipMatchLengthCodes[] = { 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284}; static sqInt zipPosition; static sqInt zipReadLimit; static unsigned char* zipSource; static sqInt zipSourceLimit; static sqInt zipSourcePos; static sqInt zipState; /* Compare the two strings and return the length of matching characters. minLength is a lower bound for match lengths that will be accepted. Note: here and matchPos are zero based. */ static sqInt comparewithmin(sqInt here, sqInt matchPos, sqInt minLength) { sqInt length; if (!((zipCollection[here + minLength]) == (zipCollection[matchPos + minLength]))) { return 0; } if (!((zipCollection[(here + minLength) - 1]) == (zipCollection[(matchPos + minLength) - 1]))) { return 0; } if (!((zipCollection[here]) == (zipCollection[matchPos]))) { return 0; } if (!((zipCollection[here + 1]) == (zipCollection[matchPos + 1]))) { return 1; } length = 2; while ((length < DeflateMaxMatch) && ((zipCollection[here + length]) == (zipCollection[matchPos + length]))) { length += 1; } return length; } /* Continue deflating the receiver's collection from blockPosition to lastIndex. Note that lastIndex must be at least MaxMatch away from the end of collection */ static sqInt deflateBlockchainLengthgoodMatch(sqInt lastIndex, sqInt chainLength, sqInt goodMatch) { sqInt distance; sqInt flushNeeded; sqInt hasMatch; sqInt here; sqInt here1; sqInt hereLength; sqInt hereMatch; sqInt i; sqInt literal; sqInt matchResult; sqInt newLength; sqInt newMatch; sqInt prevEntry; sqInt prevEntry1; sqInt prevEntry2; if (zipBlockPos > lastIndex) { return 0; } if (zipLiteralCount >= zipLiteralSize) { return 1; } hasMatch = 0; here = zipBlockPos; while (here <= lastIndex) { if (!(hasMatch)) { /* Find the first match */ matchResult = findMatchlastLengthlastMatchchainLengthgoodMatch(here, DeflateMinMatch - 1, here, chainLength, goodMatch); /* begin insertStringAt: */ zipHashValue = ((((usqInt) zipHashValue << 5)) ^ (zipCollection[(here + DeflateMinMatch) - 1])) & DeflateHashMask; prevEntry = zipHashHead[zipHashValue]; zipHashHead[zipHashValue] = here; zipHashTail[here & DeflateWindowMask] = prevEntry; hereMatch = matchResult & 65535; hereLength = ((usqInt) matchResult >> 16); } matchResult = findMatchlastLengthlastMatchchainLengthgoodMatch(here + 1, hereLength, hereMatch, chainLength, goodMatch); newMatch = matchResult & 65535; /* Now check if the next match is better than the current one. If not, output the current match (provided that the current match is at least MinMatch long) */ newLength = ((usqInt) matchResult >> 16); if ((hereLength >= newLength) && (hereLength >= DeflateMinMatch)) { /* begin encodeMatch:distance: */ zipLiterals[zipLiteralCount] = (hereLength - DeflateMinMatch); zipDistances[zipLiteralCount] = (here - hereMatch); literal = zipMatchLengthCodes[hereLength - DeflateMinMatch]; zipLiteralFreq[literal] = ((zipLiteralFreq[literal]) + 1); if ((here - hereMatch) < 257) { distance = zipDistanceCodes[(here - hereMatch) - 1]; } else { distance = zipDistanceCodes[256 + (((usqInt) ((here - hereMatch) - 1) >> 7))]; } zipDistanceFreq[distance] = ((zipDistanceFreq[distance]) + 1); zipLiteralCount += 1; zipMatchCount += 1; flushNeeded = (zipLiteralCount == zipLiteralSize) || (((zipLiteralCount & 4095) == 0) && (shouldFlush())); for (i = 1; i <= (hereLength - 1); i += 1) { /* begin insertStringAt: */ here1 = here += 1; zipHashValue = ((((usqInt) zipHashValue << 5)) ^ (zipCollection[(here1 + DeflateMinMatch) - 1])) & DeflateHashMask; prevEntry1 = zipHashHead[zipHashValue]; zipHashHead[zipHashValue] = here1; zipHashTail[here1 & DeflateWindowMask] = prevEntry1; } hasMatch = 0; here += 1; } else { /* begin encodeLiteral: */ zipLiterals[zipLiteralCount] = (zipCollection[here]); zipDistances[zipLiteralCount] = 0; zipLiteralFreq[zipCollection[here]] = ((zipLiteralFreq[zipCollection[here]]) + 1); zipLiteralCount += 1; flushNeeded = (zipLiteralCount == zipLiteralSize) || (((zipLiteralCount & 4095) == 0) && (shouldFlush())); here += 1; if ((here <= lastIndex) && (!flushNeeded)) { /* begin insertStringAt: */ zipHashValue = ((((usqInt) zipHashValue << 5)) ^ (zipCollection[(here + DeflateMinMatch) - 1])) & DeflateHashMask; prevEntry2 = zipHashHead[zipHashValue]; zipHashHead[zipHashValue] = here; zipHashTail[here & DeflateWindowMask] = prevEntry2; hasMatch = 1; hereMatch = newMatch; hereLength = newLength; } } if (flushNeeded) { zipBlockPos = here; return 1; } } zipBlockPos = here; return 0; } /* Encode the given literal */ static sqInt encodeLiteral(sqInt lit) { zipLiterals[zipLiteralCount] = lit; zipDistances[zipLiteralCount] = 0; zipLiteralFreq[lit] = ((zipLiteralFreq[lit]) + 1); zipLiteralCount += 1; return (zipLiteralCount == zipLiteralSize) || (((zipLiteralCount & 4095) == 0) && (shouldFlush())); } /* Encode the given match of length length starting at dist bytes ahead */ static sqInt encodeMatchdistance(sqInt length, sqInt dist) { sqInt distance; sqInt literal; zipLiterals[zipLiteralCount] = (length - DeflateMinMatch); zipDistances[zipLiteralCount] = dist; literal = zipMatchLengthCodes[length - DeflateMinMatch]; zipLiteralFreq[literal] = ((zipLiteralFreq[literal]) + 1); if (dist < 257) { distance = zipDistanceCodes[dist - 1]; } else { distance = zipDistanceCodes[256 + (((usqInt) (dist - 1) >> 7))]; } zipDistanceFreq[distance] = ((zipDistanceFreq[distance]) + 1); zipLiteralCount += 1; zipMatchCount += 1; return (zipLiteralCount == zipLiteralSize) || (((zipLiteralCount & 4095) == 0) && (shouldFlush())); } /* Find the longest match for the string starting at here. If there is no match longer than lastLength return lastMatch/lastLength. Traverse at most maxChainLength entries in the hash table. Stop if a match of at least goodMatch size has been found. */ static sqInt findMatchlastLengthlastMatchchainLengthgoodMatch(sqInt here, sqInt lastLength, sqInt lastMatch, sqInt maxChainLength, sqInt goodMatch) { sqInt bestLength; sqInt chainLength; sqInt distance; sqInt length; sqInt length1; sqInt limit; sqInt matchPos; sqInt matchResult; /* Compute the default match result */ /* There is no way to find a better match than MaxMatch */ matchResult = (((usqInt) lastLength << 16)) | lastMatch; if (lastLength >= DeflateMaxMatch) { return matchResult; } /* Compute the distance to the (possible) match */ matchPos = zipHashHead[((((usqInt) zipHashValue << 5)) ^ (zipCollection[(here + DeflateMinMatch) - 1])) & DeflateHashMask]; /* Note: It is required that 0 < distance < MaxDistance */ distance = here - matchPos; if (!((distance > 0) && (distance < DeflateMaxDistance))) { return matchResult; } /* Max. nr of match chain to search */ chainLength = maxChainLength; if (here > DeflateMaxDistance) { /* Limit for matches that are too old */ limit = here - DeflateMaxDistance; } else { limit = 0; } bestLength = lastLength; while (1) { /* begin compare:with:min: */ if (!((zipCollection[here + bestLength]) == (zipCollection[matchPos + bestLength]))) { length = 0; goto l1; } if (!((zipCollection[(here + bestLength) - 1]) == (zipCollection[(matchPos + bestLength) - 1]))) { length = 0; goto l1; } if (!((zipCollection[here]) == (zipCollection[matchPos]))) { length = 0; goto l1; } if (!((zipCollection[here + 1]) == (zipCollection[matchPos + 1]))) { length = 1; goto l1; } length1 = 2; while ((length1 < DeflateMaxMatch) && ((zipCollection[here + length1]) == (zipCollection[matchPos + length1]))) { length1 += 1; } length = length1; l1: /* end compare:with:min: */; if ((here + length) > zipPosition) { length = zipPosition - here; } if ((length == DeflateMinMatch) && ((here - matchPos) > (((sqInt) DeflateMaxDistance >> 2)))) { length = DeflateMinMatch - 1; } if (length > bestLength) { /* We have a new (better) match than before */ /* Compute the new match result */ matchResult = (((usqInt) length << 16)) | matchPos; /* There is no way to find a better match than MaxMatch */ bestLength = length; if (bestLength >= DeflateMaxMatch) { return matchResult; } if (bestLength > goodMatch) { return matchResult; } } if (!(((chainLength -= 1)) > 0)) { return matchResult; } matchPos = zipHashTail[matchPos & DeflateWindowMask]; if (matchPos <= limit) { return matchResult; } } } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; return 0; } /* Insert the string at the given start position into the hash table. Note: The hash value is updated starting at MinMatch-1 since all strings before have already been inserted into the hash table (and the hash value is updated as well). */ static sqInt insertStringAt(sqInt here) { sqInt prevEntry; zipHashValue = ((((usqInt) zipHashValue << 5)) ^ (zipCollection[(here + DeflateMinMatch) - 1])) & DeflateHashMask; prevEntry = zipHashHead[zipHashValue]; zipHashHead[zipHashValue] = here; zipHashTail[here & DeflateWindowMask] = prevEntry; } static sqInt loadDeflateStreamFrom(sqInt rcvr) { sqInt oop; if (!((interpreterProxy->isPointers(rcvr)) && ((interpreterProxy->slotSizeOf(rcvr)) >= 15))) { return 0; } oop = interpreterProxy->fetchPointerofObject(0, rcvr); if ((oop & 1)) { return 0; } if (!(interpreterProxy->isBytes(oop))) { return 0; } zipCollection = interpreterProxy->firstIndexableField(oop); zipCollectionSize = interpreterProxy->byteSizeOf(oop); zipPosition = interpreterProxy->fetchIntegerofObject(1, rcvr); /* zipWriteLimit := interpreterProxy fetchInteger: 3 ofObject: rcvr. */ zipReadLimit = interpreterProxy->fetchIntegerofObject(2, rcvr); oop = interpreterProxy->fetchPointerofObject(4, rcvr); if (((oop & 1)) || (!(interpreterProxy->isWords(oop)))) { return 0; } if (!((interpreterProxy->slotSizeOf(oop)) == DeflateHashTableSize)) { return 0; } zipHashHead = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(5, rcvr); if (((oop & 1)) || (!(interpreterProxy->isWords(oop)))) { return 0; } if (!((interpreterProxy->slotSizeOf(oop)) == DeflateWindowSize)) { return 0; } zipHashTail = interpreterProxy->firstIndexableField(oop); zipHashValue = interpreterProxy->fetchIntegerofObject(6, rcvr); /* zipBlockStart := interpreterProxy fetchInteger: 8 ofObject: rcvr. */ zipBlockPos = interpreterProxy->fetchIntegerofObject(7, rcvr); oop = interpreterProxy->fetchPointerofObject(9, rcvr); if (((oop & 1)) || (!(interpreterProxy->isBytes(oop)))) { return 0; } zipLiteralSize = interpreterProxy->slotSizeOf(oop); zipLiterals = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(10, rcvr); if (((oop & 1)) || (!(interpreterProxy->isWords(oop)))) { return 0; } if ((interpreterProxy->slotSizeOf(oop)) < zipLiteralSize) { return 0; } zipDistances = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(11, rcvr); if (((oop & 1)) || (!(interpreterProxy->isWords(oop)))) { return 0; } if (!((interpreterProxy->slotSizeOf(oop)) == DeflateMaxLiteralCodes)) { return 0; } zipLiteralFreq = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(12, rcvr); if (((oop & 1)) || (!(interpreterProxy->isWords(oop)))) { return 0; } if (!((interpreterProxy->slotSizeOf(oop)) == DeflateMaxDistanceCodes)) { return 0; } zipDistanceFreq = interpreterProxy->firstIndexableField(oop); zipLiteralCount = interpreterProxy->fetchIntegerofObject(13, rcvr); zipMatchCount = interpreterProxy->fetchIntegerofObject(14, rcvr); return !(interpreterProxy->failed()); } static sqInt loadZipEncoderFrom(sqInt rcvr) { sqInt oop; if (!((interpreterProxy->isPointers(rcvr)) && ((interpreterProxy->slotSizeOf(rcvr)) >= 6))) { return 0; } oop = interpreterProxy->fetchPointerofObject(0, rcvr); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(oop))) { return interpreterProxy->primitiveFail(); } zipCollection = interpreterProxy->firstIndexableField(oop); zipCollectionSize = interpreterProxy->byteSizeOf(oop); zipPosition = interpreterProxy->fetchIntegerofObject(1, rcvr); /* zipWriteLimit := interpreterProxy fetchInteger: 3 ofObject: rcvr. */ zipReadLimit = interpreterProxy->fetchIntegerofObject(2, rcvr); zipBitBuf = interpreterProxy->fetchIntegerofObject(4, rcvr); zipBitPos = interpreterProxy->fetchIntegerofObject(5, rcvr); return !(interpreterProxy->failed()); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); return 0; } /* Require: zipCollection, zipCollectionSize, zipPosition, zipBitBuf, zipBitPos. */ static sqInt nextZipBitsput(sqInt nBits, sqInt value) { if (!((value >= 0) && ((1 << nBits) > value))) { return interpreterProxy->primitiveFail(); } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) value >> -zipBitPos) : ((usqInt) value << zipBitPos))); zipBitPos += nBits; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } } /* Primitive. Deflate the current contents of the receiver. */ EXPORT(sqInt) primitiveDeflateBlock(void) { sqInt chainLength; sqInt goodMatch; sqInt lastIndex; sqInt rcvr; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } goodMatch = interpreterProxy->stackIntegerValue(0); chainLength = interpreterProxy->stackIntegerValue(1); lastIndex = interpreterProxy->stackIntegerValue(2); rcvr = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return null; } ; if (!(loadDeflateStreamFrom(rcvr))) { return interpreterProxy->primitiveFail(); } result = deflateBlockchainLengthgoodMatch(lastIndex, chainLength, goodMatch); if (!(interpreterProxy->failed())) { interpreterProxy->storeIntegerofObjectwithValue(6, rcvr, zipHashValue); interpreterProxy->storeIntegerofObjectwithValue(7, rcvr, zipBlockPos); interpreterProxy->storeIntegerofObjectwithValue(13, rcvr, zipLiteralCount); interpreterProxy->storeIntegerofObjectwithValue(14, rcvr, zipMatchCount); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(4); interpreterProxy->pushBool(result); } } /* Primitive. Update the hash tables after data has been moved by delta. */ EXPORT(sqInt) primitiveDeflateUpdateHashTable(void) { sqInt delta; sqInt entry; sqInt i; sqInt table; int *tablePtr; sqInt tableSize; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } delta = interpreterProxy->stackIntegerValue(0); table = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(table))) { return interpreterProxy->primitiveFail(); } tableSize = interpreterProxy->slotSizeOf(table); tablePtr = interpreterProxy->firstIndexableField(table); for (i = 0; i <= (tableSize - 1); i += 1) { entry = tablePtr[i]; if (entry >= delta) { tablePtr[i] = (entry - delta); } else { tablePtr[i] = 0; } } interpreterProxy->pop(2); } /* Primitive. Inflate a single block. */ EXPORT(sqInt) primitiveInflateDecompressBlock(void) { sqInt oop; sqInt rcvr; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(oop))) { return interpreterProxy->primitiveFail(); } zipDistTable = interpreterProxy->firstIndexableField(oop); /* literal table */ zipDistTableSize = interpreterProxy->slotSizeOf(oop); oop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(oop))) { return interpreterProxy->primitiveFail(); } zipLitTable = interpreterProxy->firstIndexableField(oop); /* Receiver (InflateStream) */ zipLitTableSize = interpreterProxy->slotSizeOf(oop); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isPointers(rcvr))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(rcvr)) < 9) { return interpreterProxy->primitiveFail(); } zipReadLimit = interpreterProxy->fetchIntegerofObject(2, rcvr); zipState = interpreterProxy->fetchIntegerofObject(3, rcvr); zipBitBuf = interpreterProxy->fetchIntegerofObject(4, rcvr); zipBitPos = interpreterProxy->fetchIntegerofObject(5, rcvr); zipSourcePos = interpreterProxy->fetchIntegerofObject(7, rcvr); zipSourceLimit = interpreterProxy->fetchIntegerofObject(8, rcvr); if (interpreterProxy->failed()) { return null; } zipReadLimit -= 1; zipSourcePos -= 1; /* collection */ zipSourceLimit -= 1; oop = interpreterProxy->fetchPointerofObject(0, rcvr); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(oop))) { return interpreterProxy->primitiveFail(); } zipCollection = interpreterProxy->firstIndexableField(oop); /* source */ zipCollectionSize = interpreterProxy->byteSizeOf(oop); oop = interpreterProxy->fetchPointerofObject(6, rcvr); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(oop))) { return interpreterProxy->primitiveFail(); } /* do the primitive */ zipSource = interpreterProxy->firstIndexableField(oop); zipDecompressBlock(); if (!(interpreterProxy->failed())) { interpreterProxy->storeIntegerofObjectwithValue(2, rcvr, zipReadLimit + 1); interpreterProxy->storeIntegerofObjectwithValue(3, rcvr, zipState); interpreterProxy->storeIntegerofObjectwithValue(4, rcvr, zipBitBuf); interpreterProxy->storeIntegerofObjectwithValue(5, rcvr, zipBitPos); interpreterProxy->storeIntegerofObjectwithValue(7, rcvr, zipSourcePos + 1); interpreterProxy->pop(2); } } /* Primitive. Update a 32bit CRC value. */ EXPORT(sqInt) primitiveUpdateAdler32(void) { unsigned int adler32; sqInt b; unsigned char *bytePtr; sqInt collection; sqInt i; sqInt length; sqInt s1; sqInt s2; sqInt startIndex; sqInt stopIndex; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } collection = interpreterProxy->stackObjectValue(0); stopIndex = interpreterProxy->stackIntegerValue(1); startIndex = interpreterProxy->stackIntegerValue(2); adler32 = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(3)); if (interpreterProxy->failed()) { return 0; } if (!((interpreterProxy->isBytes(collection)) && ((stopIndex >= startIndex) && (startIndex > 0)))) { return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(collection); if (!(stopIndex <= length)) { return interpreterProxy->primitiveFail(); } bytePtr = interpreterProxy->firstIndexableField(collection); startIndex -= 1; stopIndex -= 1; s1 = adler32 & 65535; s2 = (((usqInt) adler32) >> 16) & 65535; for (i = startIndex; i <= stopIndex; i += 1) { b = bytePtr[i]; s1 = (s1 + b) % 65521; s2 = (s2 + s1) % 65521; } adler32 = (((usqInt) s2 << 16)) + s1; interpreterProxy->pop(5); interpreterProxy->push(interpreterProxy->positive32BitIntegerFor(adler32)); } /* Primitive. Update a 32bit CRC value. */ EXPORT(sqInt) primitiveUpdateGZipCrc32(void) { unsigned char *bytePtr; sqInt collection; unsigned int crc; sqInt i; sqInt length; sqInt startIndex; sqInt stopIndex; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } collection = interpreterProxy->stackObjectValue(0); stopIndex = interpreterProxy->stackIntegerValue(1); startIndex = interpreterProxy->stackIntegerValue(2); crc = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(3)); if (interpreterProxy->failed()) { return 0; } if (!((interpreterProxy->isBytes(collection)) && ((stopIndex >= startIndex) && (startIndex > 0)))) { return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(collection); if (!(stopIndex <= length)) { return interpreterProxy->primitiveFail(); } bytePtr = interpreterProxy->firstIndexableField(collection); ; startIndex -= 1; stopIndex -= 1; for (i = startIndex; i <= stopIndex; i += 1) { crc = (zipCrcTable[(crc ^ (bytePtr[i])) & 255]) ^ (((usqInt) crc) >> 8); } interpreterProxy->pop(5); interpreterProxy->push(interpreterProxy->positive32BitIntegerFor(crc)); } EXPORT(sqInt) primitiveZipSendBlock(void) { sqInt code; sqInt dist; unsigned int *distArray; unsigned int *distBitLengths; sqInt distBlCount; unsigned int *distCodes; sqInt distStream; sqInt distTree; sqInt extra; sqInt lit; unsigned char *litArray; sqInt litBlCount; sqInt litLimit; sqInt litPos; sqInt litStream; sqInt litTree; unsigned int *llBitLengths; unsigned int *llCodes; sqInt oop; sqInt rcvr; sqInt result; sqInt sum; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } distTree = interpreterProxy->stackObjectValue(0); litTree = interpreterProxy->stackObjectValue(1); distStream = interpreterProxy->stackObjectValue(2); litStream = interpreterProxy->stackObjectValue(3); rcvr = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return null; } if (!(loadZipEncoderFrom(rcvr))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isPointers(distTree)) && ((interpreterProxy->slotSizeOf(distTree)) >= 2))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isPointers(litTree)) && ((interpreterProxy->slotSizeOf(litTree)) >= 2))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isPointers(litStream)) && ((interpreterProxy->slotSizeOf(litStream)) >= 3))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isPointers(distStream)) && ((interpreterProxy->slotSizeOf(distStream)) >= 3))) { return interpreterProxy->primitiveFail(); } ; /* begin sendBlock:with:with:with: */ oop = interpreterProxy->fetchPointerofObject(0, litStream); litPos = interpreterProxy->fetchIntegerofObject(1, litStream); litLimit = interpreterProxy->fetchIntegerofObject(2, litStream); if (!((!((oop & 1))) && ((litPos <= litLimit) && ((litLimit <= (interpreterProxy->byteSizeOf(oop))) && (interpreterProxy->isBytes(oop)))))) { result = interpreterProxy->primitiveFail(); goto l7; } litArray = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, distStream); if (!((!((oop & 1))) && (((interpreterProxy->fetchIntegerofObject(1, distStream)) == litPos) && ((interpreterProxy->fetchIntegerofObject(2, distStream)) == litLimit)))) { result = interpreterProxy->primitiveFail(); goto l7; } if (!((interpreterProxy->isWords(oop)) && (litLimit <= (interpreterProxy->slotSizeOf(oop))))) { result = interpreterProxy->primitiveFail(); goto l7; } distArray = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, litTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } litBlCount = interpreterProxy->slotSizeOf(oop); llBitLengths = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(1, litTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } if (!(litBlCount == (interpreterProxy->slotSizeOf(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } llCodes = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, distTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } distBlCount = interpreterProxy->slotSizeOf(oop); distBitLengths = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(1, distTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } if (!(distBlCount == (interpreterProxy->slotSizeOf(oop)))) { result = interpreterProxy->primitiveFail(); goto l7; } distCodes = interpreterProxy->firstIndexableField(oop); if (interpreterProxy->failed()) { result = null; goto l7; } /* begin nextZipBits:put: */ if (!((0 >= 0) && ((1 << 0) > 0))) { interpreterProxy->primitiveFail(); goto l6; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) 0 >> -zipBitPos) : ((usqInt) 0 << zipBitPos))); zipBitPos += 0; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l6: /* end nextZipBits:put: */; sum = 0; while ((litPos < litLimit) && ((zipPosition + 4) < zipCollectionSize)) { lit = litArray[litPos]; dist = distArray[litPos]; litPos += 1; if (dist == 0) { /* literal */ sum += 1; if (!(lit < litBlCount)) { result = interpreterProxy->primitiveFail(); goto l7; } /* begin nextZipBits:put: */ if (!(((llCodes[lit]) >= 0) && ((1 << (llBitLengths[lit])) > (llCodes[lit])))) { interpreterProxy->primitiveFail(); goto l1; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (llCodes[lit]) >> -zipBitPos) : ((usqInt) (llCodes[lit]) << zipBitPos))); zipBitPos += llBitLengths[lit]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l1: /* end nextZipBits:put: */; } else { /* match */ sum = (sum + lit) + DeflateMinMatch; if (!(lit < 256)) { result = interpreterProxy->primitiveFail(); goto l7; } code = zipMatchLengthCodes[lit]; if (!(code < litBlCount)) { result = interpreterProxy->primitiveFail(); goto l7; } /* begin nextZipBits:put: */ if (!(((llCodes[code]) >= 0) && ((1 << (llBitLengths[code])) > (llCodes[code])))) { interpreterProxy->primitiveFail(); goto l4; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (llCodes[code]) >> -zipBitPos) : ((usqInt) (llCodes[code]) << zipBitPos))); zipBitPos += llBitLengths[code]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l4: /* end nextZipBits:put: */; extra = zipExtraLengthBits[code - 257]; if (!(extra == 0)) { lit -= zipBaseLength[code - 257]; /* begin nextZipBits:put: */ if (!((lit >= 0) && ((1 << extra) > lit))) { interpreterProxy->primitiveFail(); goto l2; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) lit >> -zipBitPos) : ((usqInt) lit << zipBitPos))); zipBitPos += extra; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l2: /* end nextZipBits:put: */; } dist -= 1; if (!(dist < 32768)) { result = interpreterProxy->primitiveFail(); goto l7; } if (dist < 256) { code = zipDistanceCodes[dist]; } else { code = zipDistanceCodes[256 + (((usqInt) dist) >> 7)]; } if (!(code < distBlCount)) { result = interpreterProxy->primitiveFail(); goto l7; } /* begin nextZipBits:put: */ if (!(((distCodes[code]) >= 0) && ((1 << (distBitLengths[code])) > (distCodes[code])))) { interpreterProxy->primitiveFail(); goto l5; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (distCodes[code]) >> -zipBitPos) : ((usqInt) (distCodes[code]) << zipBitPos))); zipBitPos += distBitLengths[code]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l5: /* end nextZipBits:put: */; extra = zipExtraDistanceBits[code]; if (!(extra == 0)) { dist -= zipBaseDistance[code]; /* begin nextZipBits:put: */ if (!((dist >= 0) && ((1 << extra) > dist))) { interpreterProxy->primitiveFail(); goto l3; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) dist >> -zipBitPos) : ((usqInt) dist << zipBitPos))); zipBitPos += extra; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l3: /* end nextZipBits:put: */; } } } if (interpreterProxy->failed()) { result = null; goto l7; } interpreterProxy->storeIntegerofObjectwithValue(1, litStream, litPos); interpreterProxy->storeIntegerofObjectwithValue(1, distStream, litPos); result = sum; l7: /* end sendBlock:with:with:with: */; if (!(interpreterProxy->failed())) { interpreterProxy->storeIntegerofObjectwithValue(1, rcvr, zipPosition); interpreterProxy->storeIntegerofObjectwithValue(4, rcvr, zipBitBuf); interpreterProxy->storeIntegerofObjectwithValue(5, rcvr, zipBitPos); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } } /* Require: zipCollection, zipCollectionSize, zipPosition, zipBitBuf, zipBitPos. */ static sqInt sendBlockwithwithwith(sqInt literalStream, sqInt distanceStream, sqInt litTree, sqInt distTree) { sqInt code; sqInt dist; unsigned int *distArray; unsigned int *distBitLengths; sqInt distBlCount; unsigned int *distCodes; sqInt extra; sqInt lit; unsigned char *litArray; sqInt litBlCount; sqInt litLimit; sqInt litPos; unsigned int *llBitLengths; unsigned int *llCodes; sqInt oop; sqInt sum; oop = interpreterProxy->fetchPointerofObject(0, literalStream); litPos = interpreterProxy->fetchIntegerofObject(1, literalStream); litLimit = interpreterProxy->fetchIntegerofObject(2, literalStream); if (!((!((oop & 1))) && ((litPos <= litLimit) && ((litLimit <= (interpreterProxy->byteSizeOf(oop))) && (interpreterProxy->isBytes(oop)))))) { return interpreterProxy->primitiveFail(); } litArray = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, distanceStream); if (!((!((oop & 1))) && (((interpreterProxy->fetchIntegerofObject(1, distanceStream)) == litPos) && ((interpreterProxy->fetchIntegerofObject(2, distanceStream)) == litLimit)))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isWords(oop)) && (litLimit <= (interpreterProxy->slotSizeOf(oop))))) { return interpreterProxy->primitiveFail(); } distArray = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, litTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { return interpreterProxy->primitiveFail(); } litBlCount = interpreterProxy->slotSizeOf(oop); llBitLengths = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(1, litTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { return interpreterProxy->primitiveFail(); } if (!(litBlCount == (interpreterProxy->slotSizeOf(oop)))) { return interpreterProxy->primitiveFail(); } llCodes = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(0, distTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { return interpreterProxy->primitiveFail(); } distBlCount = interpreterProxy->slotSizeOf(oop); distBitLengths = interpreterProxy->firstIndexableField(oop); oop = interpreterProxy->fetchPointerofObject(1, distTree); if (!((!((oop & 1))) && (interpreterProxy->isWords(oop)))) { return interpreterProxy->primitiveFail(); } if (!(distBlCount == (interpreterProxy->slotSizeOf(oop)))) { return interpreterProxy->primitiveFail(); } distCodes = interpreterProxy->firstIndexableField(oop); if (interpreterProxy->failed()) { return null; } /* begin nextZipBits:put: */ if (!((0 >= 0) && ((1 << 0) > 0))) { interpreterProxy->primitiveFail(); goto l6; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) 0 >> -zipBitPos) : ((usqInt) 0 << zipBitPos))); zipBitPos += 0; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l6: /* end nextZipBits:put: */; sum = 0; while ((litPos < litLimit) && ((zipPosition + 4) < zipCollectionSize)) { lit = litArray[litPos]; dist = distArray[litPos]; litPos += 1; if (dist == 0) { /* literal */ sum += 1; if (!(lit < litBlCount)) { return interpreterProxy->primitiveFail(); } /* begin nextZipBits:put: */ if (!(((llCodes[lit]) >= 0) && ((1 << (llBitLengths[lit])) > (llCodes[lit])))) { interpreterProxy->primitiveFail(); goto l1; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (llCodes[lit]) >> -zipBitPos) : ((usqInt) (llCodes[lit]) << zipBitPos))); zipBitPos += llBitLengths[lit]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l1: /* end nextZipBits:put: */; } else { /* match */ sum = (sum + lit) + DeflateMinMatch; if (!(lit < 256)) { return interpreterProxy->primitiveFail(); } code = zipMatchLengthCodes[lit]; if (!(code < litBlCount)) { return interpreterProxy->primitiveFail(); } /* begin nextZipBits:put: */ if (!(((llCodes[code]) >= 0) && ((1 << (llBitLengths[code])) > (llCodes[code])))) { interpreterProxy->primitiveFail(); goto l4; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (llCodes[code]) >> -zipBitPos) : ((usqInt) (llCodes[code]) << zipBitPos))); zipBitPos += llBitLengths[code]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l4: /* end nextZipBits:put: */; extra = zipExtraLengthBits[code - 257]; if (!(extra == 0)) { lit -= zipBaseLength[code - 257]; /* begin nextZipBits:put: */ if (!((lit >= 0) && ((1 << extra) > lit))) { interpreterProxy->primitiveFail(); goto l2; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) lit >> -zipBitPos) : ((usqInt) lit << zipBitPos))); zipBitPos += extra; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l2: /* end nextZipBits:put: */; } dist -= 1; if (!(dist < 32768)) { return interpreterProxy->primitiveFail(); } if (dist < 256) { code = zipDistanceCodes[dist]; } else { code = zipDistanceCodes[256 + (((usqInt) dist) >> 7)]; } if (!(code < distBlCount)) { return interpreterProxy->primitiveFail(); } /* begin nextZipBits:put: */ if (!(((distCodes[code]) >= 0) && ((1 << (distBitLengths[code])) > (distCodes[code])))) { interpreterProxy->primitiveFail(); goto l5; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) (distCodes[code]) >> -zipBitPos) : ((usqInt) (distCodes[code]) << zipBitPos))); zipBitPos += distBitLengths[code]; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l5: /* end nextZipBits:put: */; extra = zipExtraDistanceBits[code]; if (!(extra == 0)) { dist -= zipBaseDistance[code]; /* begin nextZipBits:put: */ if (!((dist >= 0) && ((1 << extra) > dist))) { interpreterProxy->primitiveFail(); goto l3; } zipBitBuf = zipBitBuf | (((zipBitPos < 0) ? ((usqInt) dist >> -zipBitPos) : ((usqInt) dist << zipBitPos))); zipBitPos += extra; while ((zipBitPos >= 8) && (zipPosition < zipCollectionSize)) { zipCollection[zipPosition] = (zipBitBuf & 255); zipPosition += 1; zipBitBuf = ((usqInt) zipBitBuf) >> 8; zipBitPos -= 8; } l3: /* end nextZipBits:put: */; } } } if (interpreterProxy->failed()) { return null; } interpreterProxy->storeIntegerofObjectwithValue(1, literalStream, litPos); interpreterProxy->storeIntegerofObjectwithValue(1, distanceStream, litPos); return sum; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* Check if we should flush the current block. Flushing can be useful if the input characteristics change. */ static sqInt shouldFlush(void) { sqInt nLits; if (zipLiteralCount == zipLiteralSize) { return 1; } if (!((zipLiteralCount & 4095) == 0)) { return 0; } if ((zipMatchCount * 10) <= zipLiteralCount) { return 0; } nLits = zipLiteralCount - zipMatchCount; if (nLits <= zipMatchCount) { return 0; } return (nLits * 4) <= zipMatchCount; } /* Update the hash value at position here (one based) */ static sqInt updateHashAt(sqInt here) { return ((((usqInt) zipHashValue << 5)) ^ (zipCollection[here])) & DeflateHashMask; } /* Update the running hash value based on the next input byte. Return the new updated hash value. */ static sqInt updateHash(sqInt nextValue) { return ((((usqInt) zipHashValue << 5)) ^ nextValue) & DeflateHashMask; } /* Decode the next value in the receiver using the given huffman table. */ static sqInt zipDecodeValueFromsize(unsigned int *table, sqInt tableSize) { sqInt bits; sqInt bits1; sqInt bitsNeeded; sqInt byte; sqInt index; sqInt tableIndex; sqInt value; /* Initial bits needed */ bitsNeeded = ((usqInt) (table[0]) >> 24); if (bitsNeeded > MaxBits) { interpreterProxy->primitiveFail(); return 0; } /* First real table */ tableIndex = 2; while (1) { /* begin zipNextBits: */ while (zipBitPos < bitsNeeded) { byte = zipSource[(zipSourcePos += 1)]; zipBitBuf += byte << zipBitPos; zipBitPos += 8; } bits1 = zipBitBuf & ((1 << bitsNeeded) - 1); zipBitBuf = ((usqInt) zipBitBuf) >> bitsNeeded; zipBitPos -= bitsNeeded; bits = bits1; index = (tableIndex + bits) - 1; if (index >= tableSize) { interpreterProxy->primitiveFail(); return 0; } /* Lookup entry in table */ value = table[index]; if ((value & 1056964608) == 0) { return value; } /* Table offset in low 16 bit */ tableIndex = value & 65535; /* Additional bits in high 8 bit */ bitsNeeded = (((usqInt) value >> 24)) & 255; if (bitsNeeded > MaxBits) { interpreterProxy->primitiveFail(); return 0; } } return 0; } static sqInt zipDecompressBlock(void) { sqInt distance; sqInt dstPos; sqInt extra; sqInt i; sqInt length; sqInt max; sqInt oldBitPos; sqInt oldBits; sqInt oldPos; sqInt srcPos; sqInt value; max = zipCollectionSize - 1; while ((zipReadLimit < max) && (zipSourcePos <= zipSourceLimit)) { /* Back up stuff if we're running out of space */ oldBits = zipBitBuf; oldBitPos = zipBitPos; oldPos = zipSourcePos; value = zipDecodeValueFromsize(zipLitTable, zipLitTableSize); if (value < 256) { zipCollection[(zipReadLimit += 1)] = value; } else { if (value == 256) { /* length/distance or end of block */ /* End of block */ zipState = zipState & StateNoMoreData; return 0; } extra = (((usqInt) value >> 16)) - 1; length = value & 65535; if (extra > 0) { length += zipNextBits(extra); } value = zipDecodeValueFromsize(zipDistTable, zipDistTableSize); extra = ((usqInt) value >> 16); distance = value & 65535; if (extra > 0) { distance += zipNextBits(extra); } if ((zipReadLimit + length) >= max) { zipBitBuf = oldBits; zipBitPos = oldBitPos; zipSourcePos = oldPos; return 0; } dstPos = zipReadLimit; srcPos = zipReadLimit - distance; for (i = 1; i <= length; i += 1) { zipCollection[dstPos + i] = (zipCollection[srcPos + i]); } zipReadLimit += length; } } } static sqInt zipNextBits(sqInt n) { sqInt bits; sqInt byte; while (zipBitPos < n) { byte = zipSource[(zipSourcePos += 1)]; zipBitBuf += byte << zipBitPos; zipBitPos += 8; } bits = zipBitBuf & ((1 << n) - 1); zipBitBuf = ((usqInt) zipBitBuf) >> n; zipBitPos -= n; return bits; } #ifdef SQUEAK_BUILTIN_PLUGIN void* ZipPlugin_exports[][3] = { {"ZipPlugin", "getModuleName", (void*)getModuleName}, {"ZipPlugin", "primitiveDeflateBlock", (void*)primitiveDeflateBlock}, {"ZipPlugin", "primitiveDeflateUpdateHashTable", (void*)primitiveDeflateUpdateHashTable}, {"ZipPlugin", "primitiveInflateDecompressBlock", (void*)primitiveInflateDecompressBlock}, {"ZipPlugin", "primitiveUpdateAdler32", (void*)primitiveUpdateAdler32}, {"ZipPlugin", "primitiveUpdateGZipCrc32", (void*)primitiveUpdateGZipCrc32}, {"ZipPlugin", "primitiveZipSendBlock", (void*)primitiveZipSendBlock}, {"ZipPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/CMakeLists.txt ================================================ # Yes, it's true: you can write makefiles in COBOL. # # Last edited: 2010-05-13 12:54:20 by piumarta on emilia-2.local PROJECT (squeak) CMAKE_MINIMUM_REQUIRED (VERSION 2.6.2) IF (NOT DEFINED VM_HOST OR NOT DEFINED VM_VERSION) MESSAGE (FATAL_ERROR " You MUST NOT run CMake directly the first time you configure a build. Run 'platforms/unix/cmake/configure' from within your build directory." ) ENDIF (NOT DEFINED VM_HOST OR NOT DEFINED VM_VERSION) SET (prefix ${CMAKE_INSTALL_PREFIX}) SET (version ${VM_VERSION}) SET (bindir bin) SET (imgdir lib/squeak) SET (plgdir lib/squeak/${version}) SET (mandir man/man1) SET (docdir share/doc/squeak-${version}) GET_CMAKE_PROPERTY (vars VARIABLES) FOREACH (opt ${vars}) IF (opt MATCHES "OPT--.*") STRING (REGEX REPLACE "OPT--(.*)" "\\1" var ${opt}) MESSAGE (STATUS "Setting ${var}=${${opt}}") SET (${var} ${${opt}}) ENDIF () ENDFOREACH (opt) SET (CMAKE_INSTALL_PREFIX ${prefix}) SET (bld ${CMAKE_BINARY_DIR}) SET (unix ${CMAKE_SOURCE_DIR}) SET (config ${unix}/cmake) GET_FILENAME_COMPONENT (cross ${unix}/../Cross ABSOLUTE) IF (OPT--src) GET_FILENAME_COMPONENT (src ${OPT--src} ABSOLUTE) ELSE (SRC) SET (src ${unix}/src) ENDIF (OPT--src) IF (NOT EXISTS ${src}) MESSAGE (FATAL_ERROR " Source directory ${src} does not exist." ) ENDIF (NOT EXISTS ${src}) INCLUDE (${config}/Utils.cmake) INCLUDE (${config}/Plugins.cmake) STRING (REGEX REPLACE "([^-]*)-([^-]*)-([^-]*).*" "\\1" VM_HOST_CPU ${VM_HOST}) STRING (REGEX REPLACE "([^-]*)-([^-]*)-([^-]*).*" "\\2" VM_HOST_VENDOR ${VM_HOST}) STRING (REGEX REPLACE "([^-]*)-([^-]*)-([^-]*).*" "\\3" VM_HOST_OS ${VM_HOST}) SET (vm-host "${VM_HOST}") SET (vm-host-os "${VM_HOST_OS}") SET (vm-host-cpu "${VM_HOST_CPU}") IF (OPT--CFLAGS) SET (CMAKE_C_FLAGS "${OPT--CFLAGS}") ENDIF () IF (CMAKE_ARCH_FLAGS STREQUAL "-m32") IF (VM_HOST_CPU STREQUAL "x86_64") SET (VM_HOST_CPU "i386") ENDIF () ENDIF () IF (NOT CMAKE_C_FLAGS) IF (CMAKE_COMPILER_IS_GNUCC) IF (VM_HOST_CPU MATCHES "i.86") SET (CMAKE_C_FLAGS "-g -O2 -fomit-frame-pointer") ELSEIF (VM_HOST_CPU STREQUAL "ppc" OR VM_HOST_CPU STREQUAL "powerpc") SET (CMAKE_C_FLAGS "-g -O3 -funroll-loops -mcpu=750 -mno-fused-madd") ENDIF () ELSE () SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_RELEASE}") ENDIF (CMAKE_COMPILER_IS_GNUCC) ENDIF (NOT CMAKE_C_FLAGS) IF (NOT CMAKE_C_FLAGS) SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_RELEASE}") ENDIF (NOT CMAKE_C_FLAGS) IF (CMAKE_ARCH_FLAGS) SET (CMAKE_C_FLAGS "${CMAKE_ARCH_FLAGS} ${CMAKE_C_FLAGS}") ENDIF (CMAKE_ARCH_FLAGS) MESSAGE (STATUS "Using CFLAGS ${CMAKE_C_FLAGS}") MACRO (USE_LIBRARY lib) LIST (APPEND squeak_libs "${lib}") ENDMACRO (USE_LIBRARY) MACRO (USE_FRAMEWORK fwk) USE_LIBRARY ("-framework ${fwk}") ENDMACRO (USE_FRAMEWORK) MACRO (CONFIG_DEFINE var) LIST (APPEND config_vars "${var}") ENDMACRO (CONFIG_DEFINE var) SET (UNIX 1) CONFIG_DEFINE (UNIX) SET (ioMicroSecondClock ioMicroSeconds) CONFIG_DEFINE (ioMicroSecondClock) SET (ioUtcWithOffset sqUnixUtcWithOffset) CONFIG_DEFINE (ioUtcWithOffset) SET (CMAKE_SKIP_BUILD_RPATH TRUE) SET (CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET (CMAKE_INSTALL_RPATH "") SET (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) INCLUDE (${unix}/vm/config.cmake) CONFIGURE_PLUGINS () LIST (REMOVE_DUPLICATES config_vars) FILE (WRITE ${bld}/config.h.in "") FOREACH (var ${config_vars}) FILE (APPEND ${bld}/config.h.in "#cmakedefine ${var} @${var}@\n") ENDFOREACH (var) CONFIGURE_FILE (${bld}/config.h.in ${bld}/config.h) INCLUDE (${unix}/vm/build.cmake) BUILD_PLUGINS () ADD_SUBDIRECTORY (${unix}/npsqueak) SET (cmake ${unix}/../../cmake) IF (EXISTS ${cmake}/Packages.cmake) INCLUDE (${cmake}/Packages.cmake) ENDIF () GET_CMAKE_PROPERTY (tmp VARIABLES) LIST (REMOVE_ITEM tmp tmp) LIST (SORT tmp) FILE (WRITE ${bld}/config.status "") FOREACH (var ${tmp}) FILE (APPEND ${bld}/config.status "${var}=${${var}}\n") ENDFOREACH () ================================================ FILE: vm/src/from_squeak/unix/ChangeLog ================================================ 2006-06-05 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * plugins/FilePlugin/sqUnixFile.c (dir_Delete): Invalidate cached info when deleting lastPath. 2006-04-24 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * vm/acinclude.m4: Add CoreServices framework to link libs on Darwin. * vm/sqUnixMain.c (sqGetFilenameFromString): Resolve links and aliases if resolveAliases is nonzero. * vm/mac-alias.c: Added. * plugins/AioPlugin/Makefile.inc (XCPPFLAGS): XCPPFLAGS defines SQAIO_H="sqaio.h". * vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Reset interruptCheckCounter iff > 1/25 sec has elapsed. ---------------------------------------------------------------- 2006-04-23 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * 3.9-6 released. * vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Reset interrupt check counter at end of sleep. * config/config.h.in: Add HAVE_NANOSLEEP. * vm/acinclude.m4: Define HAVE_NANOSLEEP if nanosleep() available. * vm/aio.c (aioSleep): For small timeouts always nanosleep() if available. * vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Obey the requested timeout without testing for overdue wakeup ticks. ---------------------------------------------------------------- 2006-04-19 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * 3.9-4 released. * doc/3.9-4.RELEASE_NOTES: Created. 2006-04-18 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * plugins/FloatMathPlugin/Makefile.inc (CFLAGS): Define NO_ISNAN=1. * vm-display-X11/sqUnixX11.c (handleEvent): Suppress reporting key up when KeyRelease event is from autorepeat. 2006-04-17 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * vm/aio.c (aioSleep): Sleep in aioPoll (i.e, select) or nanosleep, for timeouts < 1 timeslice. * vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Nanosecond sleep moved to aioSleep(). * vm-display-X11/sqUnixX11.c (display_ioRelinquishProcessorForMicroseconds): * vm-display-Quartz/sqUnixQuartz.m (display_ioRelinquishProcessorForMicroseconds): * vm-display-null/sqUnixDisplayNull.c (display_ioRelinquishProcessorForMicroseconds): * vm-display-fbdev/sqUnixFBDev.c (display_ioRelinquishProcessorForMicroseconds): * vm-display-custom/sqUnixCustomWindow.c (display_ioRelinquishProcessorForMicroseconds): Call aioSleep() instead of aioPoll(). 2006-04-14 Ian Piumarta <com -dot- gmail -at- piumarta (backwards)> * vm/aio.c (aioInit): SIGIO handled by forceInterruptCheck(). * vm/aio.c (aioEnable): Set ASYNC on internal descriptors. * vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Don't nanosleep if events can be processed. * vm/aio.c (FPRINTF): Absolute and relative timestamps on debug messages. * plugins/SocketPlugin/sqUnixSocket.c (FPRINTF): Absolute and relative timestamps on debug messages. * plugins/SocketPlugin/sqUnixSocket.c (socketOptions): Enable SO_REUSEPORT. 2006-04-10 Ian Piumarta <ian.piumarta@squeakland.org> * src: Regeneratated. 2006-04-06 Ian Piumarta <ian.piumarta@squeakland.org> * config/acinclude.m4: Define VM_BUILD_STRING. * config/config.h.in: Declare VM_BUILD_STRING. * vm/sqUnixMain.c (getAttribute): Answer VM_BUILD_STRING for attribute 1006. * sqMemoryAccess.h: Clean up recent edits. Rename INLINING_WORKS_FOR_SMALL_ACCESSORS -> USE_INLINE_MEMORY_ACCESSORS. * plugins/UUIDPlugin/acinclude.m4: Require <uuid/uuid.h>. Link against libuuid, if present. * plugins/UUIDPlugin/sqUnixUUID.c: Implemented. 2006-04-05 Ian Piumarta <ian.piumarta@squeakland.org> * UnixOSProcessPlugin.c (SQAIO_H): Rename aio.h -> sqaio.h. * vm-display-Quartz/sqUnixQuartz.m (noteKeyboardEvent): Set utf32code to 0, for now. * vm/sqUnixMain.c (ioGatherEntropy): Implemented. * plugins/SocketPlugin/sqUnixSocket.c (sqSocketBindToPort) (sqSocketSetReusable): Implemented. * vm/sqUnixMain.c (sqGetFilenameFromString): Copy input to output. ---------------------------------------------------------------- 2005-03-31 Ian Piumarta <ian.piumarta@squeakland.org> * 3.8a-2 released. 2005-03-31 Ian Piumarta <ian.piumarta@squeakland.org> * platforms/Cross/plugins/SocketPlugin/SocketPlugin.h: 64-bit clean. * plugins/SocketPlugin/sqUnixSocket.c: 64-bit clean. ---------------------------------------------------------------- 2005-03-29 Ian Piumarta <ian.piumarta@squeakland.org> * Initial 64-bit merge complete. 2005-03-29 Ian Piumarta <ian.piumarta@squeakland.org> * platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/motion.c (mpeg3video_calc_dmv): Don't inline on Solaris. * platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c: Fix unaligned accesses to 64-bit members of SQFile. * platforms/Cross/vm/sqVirtualMachine.c: 64-bit cleaned. * platforms/Cross/vm/sqMemoryAccess.h: Conditionally include "interp.h"; warn obnoxiously if missing. * platforms/Cross/vm/sq.h: Thorough cleanup. * plugins/SecurityPlugin/sqUnixSecurity.c (ioInitSecurity): Obey SQUEAK_USERDIR if set. * vm/sqUnixMemory.c (sqAllocateMemory): Answer an oop (not a pointer). * vm/sqPlatformSpecific.h: Allocation anwsers an oop (not a pointer); undefine prim dispatch nonsense left over from sq.h; declare alloca(). * vm/sqUnixExternalPrims.c: Fix uses of sprintf() when snprintf() missing. Cosmetic improvements. * vm-sound-OSS/sqUnixSoundOSS.c: 64-bit cleaned. * config/Makefile.install (install-doc): Deal with compressed manpages. * config/acinclude.m4 (ac_optflags): Compiler flags default to '-O'. * config/config.h.in: Set HAVE_ALLOCA, HAVE_ALLOCA_H, and HAVE_UNSETENV. * config/configure.ac: Detect alloca() and interp.h; add src/vm to INCLUDES. * config/gnuify: Use 64-bit types. * Cross/plugins/Mpeg3Plugin/libmpeg/video (mpeg3video_calc_dmv): don't inline on Solaris. ---------------------------------------------------------------- 2005-03-19 Ian Piumarta <ian.piumarta@squeakland.org> * 3.7-7 Released. 2005-03-19 Ian Piumarta <ian.piumarta@squeakland.org> * config/configure.ac (INCLUDES): Version is 3.7-7. * config/acinclude.m4 (ac_optflags): Default optimisation flags are '-O'. * config/configure.ac (INCLUDES): Check for alloca(). * plugins/UnixOSProcessPlugin/acinclude.m4: Check for libc::unsetenv(). * plugins/AioPlugin/Makefile.inc (XCPPFLAGS): Search FilePlugin and SocketPlugin for includes. 2005-03-17 Ian Piumarta <ian.piumarta@hp.com> * src: Imported from generated sources. * README, README.SVN: Updated. * Makefile: Added for 'easy build'. * doc/HowToBuildFromSource.*: Updated URIs and revised for 'easy build' instructions. * doc/README.Sound, npsqueak/npsqueak.c, plugins/SqueakFFIPrims/00README, vm-display-Quartz/Resources/SqueakHelp/SqueakHelp.html, vm-display-fbdev/00_README.fbdev: E-mail and URL contact details updated. * config/configure.ac: Version is 3.7g-6. 2005-03-16 Ian Piumarta <ian.piumarta@hp.com> * README.SVN (added): Brief instructions for SVN source builds. * doc/squeak.1: Update URLs and email addresses. 2005-03-15 Ian Piumarta <ian.piumarta@hp.com> * vm/sqUnixMain.c (getImageName): Getter for global variable, FWIW. 2005-03-09 Ian Piumarta <ian.piumarta@hp.com> * vm/sqUnixEvent.c (recordMouseEvent): Clear windowIndex field in events. * vm-display-Quartz/sqUnixQuartz.m (noteMouseEvent): Clear windowIndex field in events. 2005-03-09 Bert Freudenberg <bert@squeakland.de> * platforms/unix/npsqueak: Check for image file in system and home dir. Modifications to npsqueakrun, runs with bash, other shells untested. Make sure Squeak really gets killed. Fixed browser crash when closing plugin page. * platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c: Check for SQUEAK_USERDIR, otherwise untrusted dir is 'My Squeak'. 2005-03-09 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/config/Makefile.install: NPSqueak (un)install changes as suggested by Bert. * platforms/unix/config/configure.ac: Version 3.7b-6. 2004-05-26 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (findOption): Nul-terminate the converted option name before looking it up. 2004-04-17 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/vm/sqPlatformSpecific.h: Include <unistd.h>. Define sqFTruncate(). 2004-04-12 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/config/gnuify: Insert #error into output file if processing failed. * platforms/unix/vm-display-fbdev/Makefile.in ($(TARGET)): Remove $(X_LIBS) from the link command. 2004-04-11 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/config/gnuify: Escape all occurences of '{' within regular expressions. 2004-04-10 Ian Piumarta <ian.piumarta@hp.com> * platforms/unix/config/gnuify: Remove gnu specifics. 2004-04-06 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/config/configure.ac: Version is 3.7b-5. * platforms/unix/npsqueak/npsqueak.c: Add failureUrl to SqueakPlugin struct. (NPP_New): Check for and use explicit imageName. (NPP_New): Check for explicit failureUrl. (NPP_New): Check for access on imageName, set failureUrl if missing. (NPP_NewStream): Redirect to failureUrl if set. (Run): Do not start VM if failureUrl set. 2004-04-04 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm-display-X11/sqUnixXdnd.c: New file. XDND-based drag-and-drop support. * platforms/unix/vm-display-X11/sqUnixX11.c: New option "-noxdnd" with attendant flag, command-line option, env var, and help entry. Include "sqUnixXdnd.c" appropriately. (handleEvent): Pass SelectionNotify to dnd if enabled. (handleEvent): Pass ClientMessage to dnd if enabled. (initWindow): Add EnterWindowMask to stParent event_mask if dnd enabled. (initWindow): Call dndInitialise() if dnd enabled. 2004-04-03 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm/dlfcn-dyld.c (dlsym): Don't automatically return on error from NSIsSymbolNameDefinedInImage(). (dlinit): Install error handlers for multiply-defined symbols to choose definition from most recently loaded plugin. 2004-04-02 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm-sound-NAS/Makefile.inc (PLIBS): Add -laudio to the link command. * platforms/unix/config/acinclude.m4: Quote all macro names in AC_DEFUN()s. * platforms/unix/vm/sqGnu.h: Use __asm__() instead of asm(). * platforms/unix/vm-display-fbdev/sqUnixFBDev.c (DEBUG): Only define if not already defined. * platforms/unix/vm-display-X11/sqUnixX11.c: Remove unused globals 'current' and 'allRenderer'. (sendSelection): Clean up targets[] initialisation. (sendSelection): Clean up list[] initialisation. (getSelectionFrom): Remove unused variable 'xreturn'. (display_ioGLcreateRenderer): Remove unused variable 'index'. (printVisual): Reset gl error flag at end. (display_winOpen): Get saved window size only if debugging. (display_printUsage): Add new flag '-glxdebug'. (display_parseArgument): Add new flag '-glxdebug'. * platforms/unix/vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Calculate relinquish time only if a delay is pending. * platforms/unix/vm/sqUnixExternalPrims.c (ioFindExternalFunctionIn): Squash error messages for shutdownModule when sqIgnorePluginErrors is set. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c: Additional checks for null privateSocketStruct. ---------------------------------------------------------------- 2004-04-02 Ian Piumarta <ian.piumarta@inria.fr> * 3.6-3 Released. 2004-04-02 Ian Piumarta <ian.piumarta@inria.fr> * vm-sound-MacOSX/sqUnixSoundMacOSX.c: Substantial rewrite for OS 10.3. * vm-display-fbdev/sqUnixFBDevMousePS2.c: Increase all timeouts to 100ms. * vm-display-fbdev/sqUnixFBDevKeyboard.c: Add diagnostic code. * vm-display-fbdev/sqUnixFBDevFramebuffer.c: Use accessors for all struct members. Fix problems when xres * bytesPerPix != bytes per line. * vm-display-fbdev/sqUnixFBDev.c: Add diagnostic code. * vm-display-X11/sqUnixX11.c (initCharmap): Fix prototype. (x2sqKeyInput): Print more useful diagnostic on setlocale() failure. * vm-display-X11/Makefile.in (XINCLUDES): Include /usr/X11R6/include explicitly. * vm/sqUnixMain.c: Add runInterpreter (for display modules to inhibit entry to interpreter loop). Reinstate -nomixer as a global option. * vm/sqUnixCharConv.c: Use Solaris encoding names on Sparc. * vm/glibc.h: Force all ctype operations to functions. Alias realpath() to glibc version 2.0. * plugins/SocketPlugin/sqUnixSocket.c (sqSocketConnectionStatus): Don't check for connection closed by peer. 2003-10-28 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/plugins/FilePlugin/sqUnixFile.c: Use ctime for creationDate and mtime for modificationDate (consistent with 'ls -l'). 2003-09-16 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/doc/squeak.1: Updated for '-nointl', SQUEAK_NOINTL, and LC_CTYPE/LC_ALL. * platforms/unix/vm-display-X11/sqUnixX11.c: Make x2sqKey a function pointer. (x2sqKeyInput): Add support for international keyboards and diacritical marks via dead keys. (display_parseEnvironment): Enable international support if either LC_CTYPE or LC_ALL is set in the environment. (display_parseEnvironment): SQUEAK_NOINTL disables international support. (display_parseArgument): '-nointl' disables international support. (display_printUsage): Add help for '-nointl' option. 2003-09-05 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm-display-X11/sqUnixX11.c (display_parseArgument): Fix browserPipes argv indices. (display_parseArgument): Add missing comma in debug printf(). 2003-09-03 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm-display-Quartz/sqUnixQuartz.m (setUpDock): Remove warning for CPSEnableForegroundOperation, which always fails -- even when it succeeds. * platforms/unix/config/configure.ac: Version 3.6-beta11 3.6b-5411. * platforms/unix/vm/sqGnu.h (PRIM_DISPATCH): Changes for global struct. (GP_REG): Enable for PowerPC. * platforms/unix/plugins/PseudoTTYPlugin/sqUnixPseudoTTYPlugin.c (ptyForkAndExec): Add diagnostic DPRINTF(). * platforms/unix/config/gnuify: Insert GP_REG for global struct in interpret(). Recognise optional 'foo->' before primitiveIndex for prim dispatch rewrite. * platforms/unix/config/config.h.in: Add HAVE_LIBUTIL_H for pty plugin on FreeBSD. * platforms/unix/vm/sqUnixExternalPrims.c (ioFindExternalFunctionIn): Suppress warning for missing "setInterpreter" or "getModuleName". 2003-09-02 Ian Piumarta <ian.piumarta@inria.fr> * platforms/Cross/plugins/B3DAcceleratorPlugin/sqOpenGLRenderer.c: Fix ARGB vs. RGBA problem and adhere to glColorMaterial recommendations. * platforms/unix/vm/sqUnixMain.c: Emergency dump conditional on IMAGE_DUMP (default is disasbled at compiled time). * platforms/unix/vm/sqUnixMain.c (ioProcessEvents): Create a synchronous emergency image dump after SIGHUP received. (sigquit): Create an asynchronous emergency image dump when SIGQUIT received. (Disabled at compile time by default.) * platforms/unix/vm-display-Quartz/sqUnixQuartz.m ([Squeak -sendEvent:]): Add inverted CtrlKeyBit to modifiers for mouse wheel events. 2003-09-01 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/config/configure.ac: Version 3.6-beta9. * platforms/Cross/plugins/SocketPlugin/SocketPlugin.h (sqSocketListenOnPortBacklogSizeInterface): Added. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (sqSocketListenOnPortBacklogSizeInterface): Add i/f address argument. (sqSocketListenOnPortBacklogSize): Punt to above with INADDR_ANY. 2003-08-31 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/config/configure.ac: Version 3.6-beta8 3.6b-5402. * platforms/unix/config/Makefile.install (install-squeak) (uninstall-squeak): (Un)install app icons on Darwin. * platforms/unix/config/make.cfg.in (VM_APP_ICONS): Define VM_APP_ICONS. * platforms/unix/config/configure.ac: Define and export VM_APP_ICONS for Darwin. * platforms/unix/vm-display-Quartz/sqUnixQuartz.m: Remove explicit init of dock icon. Only setIcon if !fromFinder. ([SqueakWindow -setIcon]): Try to find icon file in cwd, vmlibdir and resourcePath. * platforms/unix/config/inisqueak.in: Run the VM if Squeak is already installed. 2003-08-30 Ian Piumarta <ian.piumarta@inria.fr> * util/Squeak-vm.spec, util/Squeak-image.spec, util/Squeak-sources.spec (%install): Install everything as 'root.bin'. * platforms/unix/config/make.cfg.in (INSTALL_PROG, INSTALL_DATA): Pass $(INSTALL_ARGS) to install program. * platforms/unix/config/configure.ac: Version 3.6-beta7. * platforms/unix/vm-display-Quartz/Info.plist.in: Modify icon associations. * platforms/unix/vm-display-X11/sqUnixX11.c (_renderContext) (_renderWindow): Lvalue companions to render{Window,Context}(). * platforms/unix/vm/sqUnixMain.c (jitArgs): Change // comments to /* */. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (_PSP): Lvalue companion to PSP(). 2003-08-23 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/config/Makefile.in ($(squeak)): Reduce verbiage. * platforms/unix/vm-display-X11/sqUnixX11.c (handleEvents): Don't reset interrupt check counter. * platforms/unix/vm-display-Quartz/Resources/SqueakHelp/SqueakHelp.html: Explain where to put image/sources files. * platforms/unix/vm/aio.c (aioPoll): Bound total interrupted select() waiting time by the original timeout. * platforms/unix/vm-display-Quartz/sqUnixQuartz.m ([Squeak -applicationDidFinishLaunching:]): Don't reset the vmPath when starting up. * platforms/unix/vm/sqUnixMain.c (recordFullPathForVmName): stat() the result of readlink() to avoid embarassement on early linux kernels. (ioRelinquishProcessorForMicroseconds): Really sleep for < 1 timeslice then poll for i/o on Mach. * util/Makefile.rpm (%.spec): Unconditional rebuild. * platforms/unix/vm-display-X11/sqUnixX11.c (handleEvents): Return true if there are events waiting in the squeak queue. (display_ioRelinquishProcessorForMicroseconds): Don't block if handleEvents returns true. * platforms/unix/vm-display-Quartz/sqUnixQuartz.m (qz2sqButton): Enable button mapping for 3-button mice. * platforms/unix/vm/sqUnixMain.c (recordFullPathForVmName): Read absolute path of executable out of /proc on Linux. * platforms/unix/vm/sqUnixExternalPrims.c: vmLibDir moved to sqUnixMain. 2003-08-22 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm/sqUnixMain.c (ioRelinquishProcessorForMicroseconds): Cap the sleep time if it's larger than the time to next wakeup tick. (ioMSecs): Resync lowResMSecs on every call. 2003-08-21 Ian Piumarta <piumarta@felina.inria.fr> * platforms/unix/doc/squeak.1: Add entries for -vtlock/-vtswitch and equivalent environment variables. * platforms/unix/vm-display-fbdev/sqUnixFBDev.c: * platforms/unix/vm-display-fbdev/sqUnixFBDevKeyboard.c: Add support for vt switching. * platforms/unix/doc/squeak.1: Update '-kbmap' for changed keymap behaviour. * platforms/unix/vm-display-fbdev/sqUnixFBDev.c (display_printUsage): Update printUsage() for changed keymap behaviour. * platforms/unix/vm-display-fbdev/sqUnixFBDevKeymap.c (kb_initKeyMap): Load default keymap from kernel rather than from fixed data. 2003-08-20 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/vm/glibc.h: Eliminate glibc2.3 dependencies on toupper() and realpath(). * platforms/unix/config/config.h.in: Include "glibc.h" if HAVE_FEATURES_H. * platforms/unix/config/configure.ac: Check for <features.h>. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c: Set socket fd to -1 on close. Don't attempt to re-close sockets with fd < 0. * platforms/unix/vm/aio.c (aioEnable, aioHandle, aioSuspend, aioDisable): Ignore descriptors < 0. * platforms/unix/vm-display-fbdev: Framebuffer display driver added. 2003-08-14 Ian Piumarta <ian.piumarta@inria.fr> * src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c: Generate new plugin source. * src/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c: Regenerate source from version 3.1.1. * platforms/unix/plugins/XDisplayControlPlugin/acinclude.m4: Disable plugin when X is not available. * platforms/unix/plugins/XDisplayControlPlugin/Makefile.inc (XCPPFLAGS): Add X includes and libs to compile/link command. * platforms/unix/plugins/UnixOSProcessPlugin/acinclude.m4: Deleted. * platforms/unix/plugins/UnixOSProcessPlugin/Makefile.inc (XCPPFLAGS): Remove X includes and libs. * platforms/unix/vm/sqUnixExternalPrims.c (tryLoading): Don't skip non-existent files (for default search). Only print dlerror message when file exists. 2003-08-14 Ian Piumarta <piumarta@ina.inria.fr> * platforms/unix/doc/squeak.1: Update for new options and module system. * platforms/unix/npsqueak/Makefile (npsqueak.so, npsqueakrun, npsqueakregister): Use explicit first dependency rather than $< (for BSD make). * platforms/unix/vm-display-X11/sqUnixX11.c: Provide PRIMARY rather than CLIPBOARD for Squeak selection when requestor clears CUT_BUFFER0. * platforms/unix/vm/sqUnixExternalPrims.c (ioLoadModule): Search X11 library path for plugins. (ioLoadModule): Search build location for plugins. 2003-08-08 Ian Piumarta <piumarta@cartman.inria.fr> * platforms/unix/plugins/B3DAcceleratorPlugin/Makefile.inc (XLDFLAGS): Pass location of X libs to link command. * platforms/unix/vm-display-Quartz/Info.plist.in (CFBundleExecutable): Fix capitalization to avoid confusing the Finder on case-sensitive filesystems. 2003-08-08 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/plugins/UnixOSProcessPlugin/Makefile.inc (XCPPFLAGS): Pass location of X includes to compile command. (XLDFLAGS): Pass location of X libraries to link command. * platforms/unix/vm-display-X11/sqUnixX11.c (sendSelection): Use precomputed value of targetProperty in call to XChangeProperty(). * platforms/unix/vm/sqUnixMain.c: Add support for '-vm' option and SQUEAK_VM environment variable. Add support for default module detection and loading. 2003-08-07 Ian Piumarta <ian.piumarta@inria.fr> * platforms/unix/config/make.ext.in (LINK): Use -rpath $(plgdir) instead of $(libdir) to get correct install_name on OSX. * platforms/unix/vm/acinclude.m4 (AC_ICONV): Disable check for libiconv on Mac OS X to avoid pollution from /usr/local/lib. * platforms/unix/config/configure.ac (AC_CHECK_FUN(dlopen)): Check for _dyld_present before dlopen to avoid unwanted import of dlcompat on Mac OS X. * platforms/unix/config/acinclude.m4 (AC_C_DOUBLE_ORDER): Fix "improved" test so that it _really_ works and identifies big-endian machines correctly. (Never, _ever_ trust an endian-sensitive function contributed by an Intel user! ;) 2003-08-07 Ian Piumarta <piumarta@cartman.inria.fr> * platforms/unix/config/acinclude.m4 (AC_C_DOUBLE_ORDER): Use improved test that isn't fooled by over-zealous compiler optimisations. * platforms/unix/vm-display-X11/sqUnixX11.c: Numerous changes from Ned Konz to add support for COMPOUND_TEXT and fix some problems with UTF8_STRING. * platforms/unix/vm/sqUnixCharConv.c: Numerous changes from Ned Konz to improve UTF-8 handling. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (socketValid): Fail validation if thisNetSession is zero. * platforms/unix/vm/sqUnixMain.c (sigsegv): Call abort() after segv, to leave a core for debugging. ---------------------------------------------------------------- 2003-03-04 Ian Piumarta <ian.piumarta@inria.fr> * 3.4-1 Released. 2002-12-01--2003-08-07 piumarta <piumarta@emilia.inria.fr> * platforms/unix/*/*: First pass at refactoring sound and display code into runtime-loadable modules. 2002-12-01 piumarta <piumarta@calvin.inria.fr> * platforms/unix/config/mkacinc: Add `-dlopen lib' to library list. 2002-12-01 Ian Piumarta <piumarta@calvin.inria.fr> * platforms/unix/vm/dlfcn-dyld.c: Added. * platforms/unix/config/config.h.in: Add HAVE_DYLD, DARWIN. * platforms/unix/config/configure.ac: Remove check for dlfcn.h. Check for _dyld_present in libc and define HAVE_DYLD. Checking for dlfcn.h and -ldl only if !HAVE_DYLD. Define DARWIN if compiling on Darwin. * platforms/unix/config/make.cfg.in (SOFLAGS): Substituted by configure. * platforms/unix/vm/sqUnixExternalPrims.c: Include dlopen wrappers for dyld on Mach. Fix prototype for dlsym(). Provide definition for RTLD_GLOBAL if missing. (tryLoading): Check for dir before calling dlopen(). (tryLoading): Make prefix/suffix selection be table driven. (ioLoadModule): Logic simplified (prefix/suffix now handled by tryLoading). * platforms/unix/vm/sqXWindow.c (imageNotFound): Fix multi-line string literals. 2002-11-25 Ian Piumarta <piumarta@dilbert.inria.fr> * platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c: Added missing stubs for sqSec*(). 2002-11-25 Bert Freudenberg <bert@isg.cs.uni-magdeburg.de> * platforms/unix/plugins/B3DAcceleratorPlugin/sqUnixOpenGL.c: New version, updated for Croquet. 2002-10-27 piumarta <ian.piumarta@inria.fr> * platforms/unix/config/verstamp: Remove Apple-specific garbage from gcc version string on Darwin. 2002-10-26 piumarta <ian.piumarta@inria.fr> * platforms/unix/vm/sqUnixMozilla.c (browserProcessCommand): Fix signature to avoid link errors on BSD. * util/Makefile.dist (BINREL): Use `-nox' suffix on tarball if configured --without-x. * platforms/unix/config/configure.ac: Define and substitute `NOX' as `-nox' when building --without-x, empty otherwise. (disabled_plugins): Disable UnixOSProcessPlugin when building --without-x. * platforms/unix/config/make.cfg.in (NOX): Import definition of NOX from configure. * platforms/unix/config/Makefile.in: Define `squeak' as `squeak' or `squeak-nox'. Use `$(squeak)' instead of `squeak' throughout. * platforms/unix/config/Makefile.install: Use $(squeak) instead of `squeak'. 2002-10-26 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/SoundPlugin/sqUnixSoundSun.c: * platforms/unix/plugins/SoundPlugin/sqUnixSoundNAS.c: * platforms/unix/plugins/SoundPlugin/sqUnixSound.c: * platforms/unix/plugins/SerialPlugin/sqUnixSerial.c: * platforms/unix/plugins/SecurityPlugin/sqUnixSecurity.c: * platforms/unix/plugins/MIDIPlugin/sqUnixMIDI.c: * plugins/JoystickTabletPlugin/sqUnixJoystickTablet.c: * platforms/unix/plugins/FileCopyPlugin/sqUnixFileCopyPlugin.c: * platforms/unix/plugins/FilePlugin/sqUnixFile.c: Systematically include generated plugin header. * platforms/unix/plugins/FilePlugin/sqUnixFile.c (dir_Lookup): Type of sizeIfFile is squeakFileOffsetType not int. (Many thanks to Alain Fischer for finding this.) 2002-10-24 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqUnixExternalPrims.c: Fix several DPRINTF()s that failed to specify the stream. (ioFindExternalFunctionIn): If set, prepend VM_DLSYM_PREFIX to lookupName. * platforms/unix/config/configure.ac: On Darwin add `-no-cpp-precomp' to CFLAGS, disable npsqueak, and define VM_DLSYM_PREFIX to "_". * platforms/unix/config/config.h.in: Add VM_DLYSM_PREFIX for targets that require `_' before dlsym names (i.e., Darwin). * platforms/unix/config/config.guess, platforms/unix/config/config.sub: updated to autoconf-2.54. 2002-10-24 root <piumarta@emilia.inria.fr> * /usr/share/aclocal/libtool.m4 (archive_cmds for darwin): Remove double quotes around "x$module" (allowing libtool to recognise `-module' flag when building loadable modules on Darwin). 2002-10-23 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c: Remove spurious `#' from front of __snprintf extern declaration. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (MAXHOSTNAMELEN): If not defined after including netdb.h (nasty, wicked, evil Solaris) then define it as 256. 2002-10-20 Ian Piumarta <piumarta@emilia.inria.fr> * util/Squeak-vm.spec: (AutoReqProv): Inhibit automatic dependency generation (too much noise from plugins). (Requires): Add (lib{X11,Xext,m}) as explicit dependencies. * src/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c: Updated to 3.0.2. 2002-10-17 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/config/Makefile.install (install-npsqueak): Add npsqueak dependency to force build if required. 2002-10-16 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/npsqueak/npsqueakrun.in: Add version directory to `File' comment. * platforms/unix/vm/sqXWindow.c: Remove `secure' and the corresponding option and env var. * platforms/unix/doc/squeak.1: Remove `-secure'. ---------------------------------------------------------------- 2002-10-16 Ian Piumarta <piumarta@emilia.inria.fr> * 3.2-5 Released. 2002-10-16 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c: Add useItimer (enabled by default, -notimer disables) and iconified. (SetUpWindow): Set wmHint IconicState if iconified. (ioLowResMSecs): Check useItimer. (SetUpTimers): Check useItimer. (usage): Add -iconic, -notimer. (ParseEnvironment): Add SQUEAK_ICONIC, SQUEAK_NOTIMER. (ParseArguments): Add -iconic, -notimer. * platforms/unix/doc/squeak.1: Add -iconic and -notimer. * platforms/unix/plugins/SqueakFFIPrims/sqUnixFFI.c (FFI_TYPE_STRUCT): Define if neccessary. (Value is not exported from ffi.h in libffi-2.) * platforms/unix/plugins/SqueakFFIPrims/acinclude.m4: Added. 2002-09-29 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c (ioSetFullScreen): Resize stWindow (not sqParent) for browser's benefit. 2002-09-27 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/config/Makefile.install (install-npsqueak): new target. * platforms/unix/config/Makefile.in (npsqueak): new target. * platforms/unix/config/configure.ac: add `--with-browser' setting NPSQUEAK_SO appropriately. * platforms/unix/config/configure.ac: renamed from configure.in to keep debian's autoconf happy. * platforms/unix/config/acinclude.m4 (AC_GNU_INTERP): force AWK=gawk if --with-gnu-awk. * platforms/unix/config/config.h.in: additional undefines for HAVE_[__]SNPRINTF. * platforms/unix/vm/sqXWindow.c (SetUpWindow): Create initial window with extent = screen extent when -fullscreen specified. 2002-09-26 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c (SetUpWindow): `-iconic' option sets initial_state WM hint to Iconic. 2002-09-16 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/aio.c (aioSuspend,aioDisable): remove check for null descriptor (it's a valid fd). 2002-08-21 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/SoundPlugin/sqUnixSoundOSS.c (output): Loop until write() completes (for broken alsa drivers). (Suggested by Lex Spoon.) 2002-08-03 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c (forgetXDisplay): aioDisable the X fd before closing it. (From Dave Lewis.) 2002-07-17 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqGnu.h: Define all undefined XX_REGs to be empty to prevent build errors on unsupported platforms. (Thanks to Tommy Thorn for spotting the problem.) * platforms/unix/config/*: Many diverse changes for autoconf 2.53 and libtool 1.4.2. 2002-07-12 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/PseudoTTYPlugin/sqUnixPseudoTTYPlugin.c (validate): Fail primitive if f->state is 0. * platforms/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c (validate): Fail primitive if f->state is 0. ---------------------------------------------------------------- 2002-07-11 Ian Piumarta <piumarta@emilia.inria.fr> * 3.2-4 Released. 2002-07-11 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/PseudoTTYPlugin/openpty.h: Include libutil.h if present (FreeBSD's name for util.h). * platforms/unix/plugins/PseudoTTYPlugin/acinclude.m4: Use test -r on /dev/ptmx. Check for `libutil.h'. (Thanks to Eric Dorman.) 2002-07-10 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c (asyncFileAttach): Broken out from asyncFileOpen() for use by PtyPlugin. * platforms/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.h: Export asyncFileAttach(). * platforms/unix/plugins/PseudoTTYPlugin/openpty.h: Provide local implementations of openpty() and login_tty() if not supported by libc. * platforms/unix/plugins/PseudoTTYPlugin/sqUnixPseudoTTYPlugin.c: Various portability fixes. Use openpty() if available. Avoid use of nanosleep. ptyFork() and ptyClose() perform all the work of AsyncFile creation and destruction. ---------------------------------------------------------------- 2002-07-09 Ian Piumarta <piumarta@emilia.inria.fr> * 3.2-3 Released. 2002-07-09 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c: Various stubs to allow OSProcess to (mostly) work when compiled -DHEADLESS. * platforms/unix/vm/sqXWindow.c (ioGetWindow, ioGetDisplay): implemented. * platforms/unix/plugins/B3DAcceleratorPlugin/sqUnixOpenGL.c (glInitialize): Retrieve stDisplay and stWindow via ioGet functions. 2002-07-08 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (acceptHandler, sqSocketCreate...): Remove OOBINLINE hack. * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (sqSocketSetOptions...): Interpret option as a string and convert it to an int before setsockopt(). * platforms/unix/config/Makefile.in (squeak.1): Avoid $< in rule for squeak.1. * platforms/unix/vm/sqUnixMozilla.c (primitivePluginBrowserReady): Fail primitive if not running in browser. (Eliminates infuriating three second pause on return from snapshot.) * platforms/unix/vm/sqXWindow.c: Fix conditional compilation in various places -DHEADLESS. (Many thanks to Colin Putney.) * platforms/unix/vm/osExports.c (os_exports): Don't export browser functions if compiling -DHEADLESS. * platforms/unix/config/make.int.in: Run RANLIB on final archive. 2002-07-06 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/PseudoTTYPlugin/sqUnixPseudoTTYPlugin.c: Implemented. * platforms/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c: Implemented. 2002-07-01 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/plugins/SocketPlugin/sqUnixSocket.c (acceptHandler, sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID): Set option SO_OOBINLINE on new sockets (for the benefit of telnet, which needs to pick up IAC as urgent-mode data). (dataHandler): Read (and discard) out-of-band data on exception, leaving the socket status alone. ---------------------------------------------------------------- 2002-06-10 Ian Piumarta <piumarta@emilia.inria.fr> * 3.2-2 Released. 2002-06-10 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/vm/sqXWindow.c (handleEvent): Add missing break in SelectionClear case. (Thanks to Ned Konz.) (getAttribute): Return full path of VM for sysAttr(0). [Thanks also to Ned Konz for spotting this.] * platforms/unix/vm/sqXWindow.c (recordKeyboardEvent): modifiers to use passed as argument (for mouse wheel). (handleEvent): Mouse wheel uses inverted ctrl key modifier. 2002-06-08 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/config/Makefile.install (install-image): install compressed image/changes files. image/changes and inisqueak installed in imgdir. * platforms/unix/config/inisqueak.in: use compressed image/changes files. image/changes installed in imgdir. * platforms/unix/vm/sqPlatformSpecific.h: include <sys/types.h> to pick up off_t. ---------------------------------------------------------------- 2002-06-07 Ian Piumarta <piumarta@emilia.inria.fr> * 3.2-1 Released. 2002-06-06 Ian Piumarta <piumarta@emilia.inria.fr> * platforms/unix/doc/squeak.1: image/changes files in version independent libdir. * platforms/unix/config/verstamp: Use abbreviated date in ISO 8601 format. (Requires the local plarform have a POSIX-compliant `date' command.) 2002-06-03 <piumarta@emilia.inria.fr> * platforms/unix/doc/squeak.1: Add `-plugins' option. * platforms/unix/vm/sqUnixExternalPrims.c (ioLoadModule): If set, try loading plugins through `squeakPlugins' before the default locations. * platforms/unix/vm/sqXWindow.c: Add option `-plugins'. 2002-05-31 <piumarta@emilia.inria.fr> * sqXWindow.c (x2sqModifier): Ignore mod[345] to avoid possible numLock problems. 2002-05-27 <piumarta@emilia.inria.fr> * squeak.1: Add `-noevents' (missing) and `-nomixer' (new). * sqUnixSoundNAS.c (snd_Start): Select sound format based on byte order of the local machine. 2002-05-26 <piumarta@emilia.inria.fr> * acinclude.m4: Clean up checks for audio support. Check for native support (oss, sun) before network support (nas). 2002-05-25 Ian Piumarta <piumarta@emilia.inria.fr> * sqGnu.h: CB_REG defined for intel when gcc >= 2.95. 2002-05-22 Ian Piumarta <piumarta@emilia.inria.fr> * sqUnixSoundOSS.c (outHandler): Defined only when playSema enabled. (snd_Start): Fail primitive when semaIndex > 0 and play semaphore disabled. Do not call aioEnable() when playSema disabled. (snd_AvailableSpace): Only call aioHandle() when playSema enabled. 2002-05-21 Ian Piumarta <piumarta@emilia.inria.fr> * sqUnixSocket.c (sqSocketReceiveDataAvailable): Change socket state to OtherEndClosed on EOF. (dataHandler): Change socket state to OtherEndClosed on EOF. 2002-05-17 Ian Piumarta <piumarta@emilia.inria.fr> * sqUnixSoundOSS.c: Rewritten from scratch. * sqUnixSound.c: Broken into separate files: `sqUnixSound{OSS,NAS,Sun,None}.c'. 2002-05-12 Ian Piumarta <piumarta@emilia.inria.fr> * sqXWindow.c (ioShowDisplay): Clamp affected{R,B} at {width,height} instead of {width,height} - 1. 2002-05-09 Ian Piumarta <piumarta@felina.inria.fr> * sqXWindow.c (ioBeep): Check for server connection before trying to ring the bell. * sqUnixSound.c: New NAS/OSS recording code from Lex Spoon. (Modified for aio compatiblity.) * sqUnixExternalPrims.c (tryLoading): Fail silently when attempting to load a plugin that names a directory. [sf] * squeak.1: Remove `-swapmod'. * sqXWindow.c: Remove `-swapmod'. (x2sqModifier): All modifiers map to Command. * sqXWindow.c (ioGetButtonState, recordMouseEvent): Honour `-swapbtn' for Ctrl/Command-RedButton clicks. * squeak.1: Default image name is `squeak.image'. * sqXWindow.c (ParseEnvironment, usage): Default image name is `squeak.image'. [sf] * sqXWindow.c (ioFormPrint): Print form to PostScript printer using pnmtops. [sf] 2002-05-08 Ian Piumarta <piumarta@emilia.inria.fr> * sqXWindow.c: Total rewrite of window resizing to fix incorrect assumptions about the behaviour of the image. * sqXWindow.c (SetUpWindow): Calculate initial window geometry based on parent window if running in a browser. (Avoids X protocol errors.) * sqUnixSecurity.c (ioGetSecureUserDirectory): Fail primitive if security not initialised. * sqXWindow.c (ioScreenSize): Answer size of saved window when not connected to a display. [sf] 2002-05-07 Ian Piumarta <piumarta@emilia.inria.fr> * sqXWindow.c (handleEvent): Fixed possible infinite recursion (observed by Lex Spoon) in completion event handling. * sqXWindow.c: Increase default heap size to 48MB. * sqUnixMozilla.c (browserPostURLRequest): Comment out unused function to avoid compilation errors. * sqUnixAsynchFile.c: Remove stale security code. * sqUnixSocket.c: Remove stale security code. * sqUnixFile.c: Remove stale security functions. * sqUnixSecurity.c: New version from Bert Freudenberg. [sf] * sqUnixFile.c: Remove stale browser support code. * sqXWindow.c: Support for new browser plugin. [sf] * sqUnixFile.c: Include <errno.h> and <string.h>. [sf] * sqUnixFile.c (dir_Lookup): Retry readdir() on interrupted system call. [sf] * sqXWindow.c: Handle the CLIPBOARD selection. [sf] * sqXWindow.c (SetUpWindow): Extra bit in valuemask for parent window to avoid errors on Sun. [sf] 2002-05-07 Ian Piumarta <piumarta@emilia.inria.fr> * sqUnixSocket.c: Immediate detection of remote reset on connection. * sqUnixSocket.c (dataHandler): Don't signal the connection semaphore on error. ================================================ FILE: vm/src/from_squeak/unix/Makefile ================================================ # Last edited: 2005-03-16 22:47:32 by piumarta on squeak.hpl.hp.com all : .force [ -d bld ] || mkdir bld [ -f bld/Makefile ] || ( cd bld; ../config/configure; ) ( cd bld; $(MAKE) $(MFLAGS); ) install : all ( cd bld; $(MAKE) $(MFLAGS) install; ) clean : .force /bin/rm -rf bld .force : ================================================ FILE: vm/src/from_squeak/unix/README ================================================ Building Unix Squeak -------------------- Full documentation can be found in: platforms/unix/doc/HowToBuildFromSource.{txt,html,ps,pdf} For the impatient: 1. Change to the 'platforms/unix' directory (if you aren't already there) and type 'make' to build the VM and plugins: cd platforms/unix make 2. Install the VM, plugins, man pages and documentation (as root, note the 'sudo' command to gain superuser privileges): sudo make install 3. If you haven't used Squeak before, read the manual: man squeak 4. Enjoy! Note: The latest documentation and releases are available from: http://squeakvm.org/ ---- Last edited: 2006-04-10 12:55:06 by piumarta on emilia.local ================================================ FILE: vm/src/from_squeak/unix/README.CMake ================================================ Building Unix Squeak from SVN (Subversion) Sources using CMake ============================================================== Executive summary ----------------- svn co http://squeakvm.org/squeak/trunk squeak cd squeak mkdir bld cd bld ../platforms/unix/cmake/configure make Detailed instructions --------------------- 1 Checkout the sources. svn co http://squeakvm.org/squeak/trunk squeak This will create a directory called 'squeak'. Descend into it with 'cd squeak'. 2 You can use the supplied interpreter sources in 'platforms/unix/src' or you can generate your own. If you generate your own then I recommend you place then in a directory next to 'platofrms/unix/src' and call them something else, 'platforms/unix/vmm' for example. 3 Create a build directory. This can be anywhere you want. In this README we will 'mkdir bld' to create the build directory in 'squeak', next to the 'platforms' directory. Building directly in the source tree (starting in platforms/unix) should work but is UNTESTED and UNSUPPORTED and discrouraged by CMake people too. 4 Descend into your build directory. 'cd bld'. 5 Configure your build: '../platforms/unix/cmake/configure'. (You can pass arguments to this script; run 'cmake/configure --help' to see a list of them.) 6 Build it: just type 'make', sit back, and enjoy the pretty colours (assuming your terminal supports them). This should leave you with an executable called 'squeak' in your build directory. 7 You can test the binary in-place by running 'squeak' with a path to an image file as argument; e.g: ./squeak ../../squeak.image 8 If it works, install it by typing 'make install' in your build directory. 9 If you modify the sources you can safely type 'make' in the build directory and everything affected will be rebuilt. If you want to reconfigure and rebuild only affected files, type 'cmake .' and then 'make'. If you want to rebuild everything type 'make clean' and then 'make'. If you want to reconfigure everything and then rebuild everything just delete your build directory and start again from step 3. ---- Last edited: 2009-08-30 23:56:00 by piumarta on ubuntu.piumarta.com ================================================ FILE: vm/src/from_squeak/unix/README.SVN ================================================ Building Unix Squeak from SVN (SubVersion) Sources ================================================== Part 0 -- Stuff you have to do, regardless ------------------------------------------ 0.1 Checkout the sources (duh). $ svn co http://squeakvm.org/squeak/trunk squeak This will checkout a directory called "squeak". Part 1 -- Building the EASY way ------------------------------- 1.0 You just completed step 0.1. 1.1 Everything you need is already there. Just descend into the squeak/platforms/unix directory and type 'make', like this: $ cd squeak/platforms/unix $ make This will create a build directory called 'bld' and, if nothing goes wrong, will build a VM and a set of plugins in it. Just type 'sudo make install' to install it all in /usr/local/*. Part 2 -- Building the HARD way ------------------------------- 2.0 You just completed step 0.1. 2.1 If you are generating your own interpreter sources from within the Squeak image, put them in 'squeak/src'. 2.2 You can now go back to step 1.1 and the build will use your new 'squeak/src' instead of the built-in 'src' directory. Or you can continue to do it the traditional way... 2.3 Create a build directory in 'squeak' and descend into it. $ cd squeak $ mkdir bld $ cd bld 2.4 Configure the build by running the 'configure' script in the 'platforms/unix/config' directory: $ ../platforms/unix/config/configure --with-src=srcNN where srcNN is src32 or src64, depending on whether you want to build a 32- or 64-bit VM. 2.5 Build the VM and plugins and (if you like) install them. $ make $ sudo make install ---- Last edited: 2006-04-05 10:44:30 by piumarta on emilia.local ================================================ FILE: vm/src/from_squeak/unix/cmake/Fixes.cmake ================================================ # RETURN () # # Some binary distrbutions are built badly. Attempt to work around only those bugs that we need to fix. # # # # Last edited: 2009-08-15 12:27:17 by piumarta on emilia-2.local # IF (NOT DEFINED CMAKE_FIND_LIBRARY_PREFIXES) # IF (UNIX) # SET (CMAKE_FIND_LIBRARY_PREFIXES lib) # ENDIF (UNIX) # ENDIF (NOT DEFINED CMAKE_FIND_LIBRARY_PREFIXES) # IF (NOT DEFINED CMAKE_FIND_LIBRARY_SUFFIXES) # IF (UNIX) # IF (APPLE) # SET (CMAKE_FIND_LIBRARY_SUFFIXES .a .dylib) # ELSE (APPLE) # SET (CMAKE_FIND_LIBRARY_SUFFIXES .a .so) # ENDIF (APPLE) # ENDIF (UNIX) # ENDIF (NOT DEFINED CMAKE_FIND_LIBRARY_SUFFIXES) ================================================ FILE: vm/src/from_squeak/unix/cmake/PluginExternal.cmake ================================================ ADD_DEFINITIONS (${@plugin@_definitions}) LINK_DIRECTORIES (${@plugin@_link_directories}) INCLUDE_DIRECTORIES (${@plugin@_include_directories} ${bld} ${src}/vm ${cross}/vm ${src}/plugins/@plugin@ ${src}/vm/intplugins/@plugin@ ${unix}/vm ${unix}/plugins/@plugin@ ${unix}/@plugin@ ${cross}/plugins/@plugin@ ) ADD_LIBRARY (@plugin@ MODULE @plugin_sources@) TARGET_LINK_LIBRARIES (@plugin@ ${@plugin@_link_libraries}) INSTALL (TARGETS @plugin@ LIBRARY DESTINATION @plgdir@) ================================================ FILE: vm/src/from_squeak/unix/cmake/PluginInternal.cmake ================================================ ADD_DEFINITIONS (-DSQUEAK_BUILTIN_PLUGIN=1 ${@plugin@_definitions}) LINK_DIRECTORIES (${@plugin@_link_directories}) INCLUDE_DIRECTORIES (${@plugin@_include_directories} ${bld} ${src}/vm ${cross}/vm ${src}/plugins/@plugin@ ${src}/vm/intplugins/@plugin@ ${unix}/vm ${unix}/plugins/@plugin@ ${unix}/@plugin@ ${cross}/plugins/@plugin@ ) ADD_LIBRARY (@plugin@ STATIC @plugin_sources@) ================================================ FILE: vm/src/from_squeak/unix/cmake/Plugins.cmake ================================================ # Figure out which plugins to build and create a configuration for each. # # Last edited: 2011-01-27 12:16:13 by piumarta on emilia.ipe.media.kyoto-u.ac.jp FILE (STRINGS ${src}/plugins.int plugins_int) STRING (REGEX REPLACE ".*= (.*)" "\\1" plugins_int ${plugins_int}) STRING (REPLACE " " ";" plugins_int ${plugins_int}) FILE (STRINGS ${src}/plugins.ext plugins_ext) STRING (REGEX REPLACE ".*= (.*)" "\\1" plugins_ext ${plugins_ext}) STRING (REPLACE " " ";" plugins_ext ${plugins_ext}) FILE (GLOB plugins_vm RELATIVE ${unix} ${unix}/vm-*) FILE_COPY (${bld}/disabledPlugins.c ${config}/disabledPlugins.c) MACRO (DISABLED_PLUGIN plugin) FILE (APPEND ${bld}/disabledPlugins.c "disabled(${plugin})\n") ENDMACRO (DISABLED_PLUGIN) MACRO (INTERNAL_PLUGIN plugin) SET (plugin_sources "") IF (DEFINED ${plugin}_sources) SET (plugin_sources ${${plugin}_sources}) ELSE (DEFINED ${plugin}_sources) FOREACH (dir ${src}/vm/intplugins ${cross}/plugins ${unix}/plugins) SET (tmp "") AUX_SOURCE_DIRECTORY (${dir}/${plugin} tmp) STRING_APPEND (plugin_sources "${tmp}") ENDFOREACH (dir) ENDIF (DEFINED ${plugin}_sources) FILE (WRITE ${bld}/${plugin}/CMakeLists.in "") FOREACH (dir ${unix}/plugins ${unix}) FILE_APPEND (${bld}/${plugin}/CMakeLists.in ${dir}/${plugin}/build.cmake) ENDFOREACH (dir) FILE_APPEND (${bld}/${plugin}/CMakeLists.in ${config}/PluginInternal.cmake) CONFIGURE_FILE (${bld}/${plugin}/CMakeLists.in ${bld}/${plugin}/CMakeLists.txt @ONLY) ADD_SUBDIRECTORY (${bld}/${plugin} ${bld}/${plugin}) ENDMACRO (INTERNAL_PLUGIN) MACRO (EXTERNAL_PLUGIN plugin) SET (plugin_sources) IF (DEFINED ${plugin}_sources) SET (plugin_sources ${${plugin}_sources}) ELSE (DEFINED ${plugin}_sources) FOREACH (dir ${src}/plugins ${cross}/plugins ${unix}/plugins ${unix}) SET (tmp "") AUX_SOURCE_DIRECTORY (${dir}/${plugin} tmp) STRING_APPEND (plugin_sources "${tmp}") ENDFOREACH (dir) ENDIF (DEFINED ${plugin}_sources) IF (DEFINED ${plugin}_extra_sources) STRING_APPEND (plugin_sources "${${plugin}_extra_sources}") ENDIF (DEFINED ${plugin}_extra_sources) FILE (WRITE ${bld}/${plugin}/CMakeLists.in "") FOREACH (dir ${unix}/plugins ${unix}) FILE_APPEND (${bld}/${plugin}/CMakeLists.in ${dir}/${plugin}/build.cmake) ENDFOREACH (dir) FILE_APPEND (${bld}/${plugin}/CMakeLists.in ${config}/PluginExternal.cmake) CONFIGURE_FILE (${bld}/${plugin}/CMakeLists.in ${bld}/${plugin}/CMakeLists.txt @ONLY) ADD_SUBDIRECTORY (${bld}/${plugin} ${bld}/${plugin}) ENDMACRO (EXTERNAL_PLUGIN) MACRO (PLUGIN_DISABLE) SET (plugin_disabled 1) ENDMACRO (PLUGIN_DISABLE) MACRO (PLUGIN_SOURCES) SET (${plugin}_sources ${ARGV}) ENDMACRO (PLUGIN_SOURCES) MACRO (PLUGIN_DEFINITIONS) LIST_APPEND (${plugin}_definitions ${ARGV}) ENDMACRO (PLUGIN_DEFINITIONS) MACRO (PLUGIN_INCLUDE_DIRECTORIES) LIST_APPEND (${plugin}_include_directories ${ARGV}) ENDMACRO (PLUGIN_INCLUDE_DIRECTORIES) MACRO (PLUGIN_LINK_DIRECTORIES) LIST_APPEND (${plugin_target}_link_directories ${ARGV}) ENDMACRO (PLUGIN_LINK_DIRECTORIES) MACRO (PLUGIN_LINK_LIBRARIES) LIST_APPEND (${plugin_target}_link_libraries ${ARGV}) ENDMACRO (PLUGIN_LINK_LIBRARIES) MACRO (CONFIGURE_PLUGIN_LIST plugins_list) SET (plugins ${${plugins_list}}) FOREACH (plugin ${plugins}) FILE (MAKE_DIRECTORY ${bld}/${plugin}) FILE (WRITE ${bld}/${plugin}/config.cmake "") FOREACH (dir ${unix}/plugins ${unix}) FILE_APPEND (${bld}/${plugin}/config.cmake ${dir}/${plugin}/config.cmake) ENDFOREACH (dir) #MESSAGE ("-- plugin ${plugin}") IF (${plugins_list} STREQUAL "plugins_int") SET (plugin_target "vm") ELSE () SET (plugin_target "${plugin}") ENDIF (${plugins_list} STREQUAL "plugins_int") SET (plugin_disabled) INCLUDE (${bld}/${plugin}/config.cmake) IF (without-${plugin}) SET (plugin_disabled 1) ENDIF () IF (DEFINED plugin_disabled) LIST (REMOVE_ITEM ${plugins_list} ${plugin}) IF (${plugins_list} STREQUAL "plugins_int") LIST (APPEND plugins_dis ${plugin}) ENDIF (${plugins_list} STREQUAL "plugins_int") MESSAGE ("!! ${plugin} disabled") SET (${plugin}_disabled 1) ELSE (DEFINED plugin_disabled) IF (${plugins_list} STREQUAL "plugins_int") USE_LIBRARY (${plugin}) ENDIF (${plugins_list} STREQUAL "plugins_int") SET (${plugin}_disabled) ENDIF (DEFINED plugin_disabled) ENDFOREACH (plugin) ENDMACRO (CONFIGURE_PLUGIN_LIST) MACRO (CONFIGURE_PLUGINS) CONFIGURE_PLUGIN_LIST (plugins_int) CONFIGURE_PLUGIN_LIST (plugins_ext) CONFIGURE_PLUGIN_LIST (plugins_vm) ENDMACRO (CONFIGURE_PLUGINS) MACRO (BUILD_PLUGINS) FOREACH (plugin ${plugins_dis}) DISABLED_PLUGIN (${plugin}) ENDFOREACH (plugin) FOREACH (plugin ${plugins_int}) INTERNAL_PLUGIN (${plugin}) ENDFOREACH (plugin) FOREACH (plugin ${plugins_ext}) EXTERNAL_PLUGIN (${plugin}) ENDFOREACH (plugin) FOREACH (plugin ${plugins_vm}) EXTERNAL_PLUGIN (${plugin}) ENDFOREACH (plugin) ENDMACRO (BUILD_PLUGINS) MACRO (PLUGIN_MESSAGE msg) MESSAGE (STATUS "${plugin}: ${msg}") ENDMACRO (PLUGIN_MESSAGE) MACRO (PLUGIN_FIND_INCLUDE VAR NAME) FIND_PATH (${VAR}_H ${NAME} ${${plugin_target}_include_directories} ${ARGN}) IF (${VAR}_H) PLUGIN_MESSAGE ("${${VAR}_H}/${NAME}") SET (HAVE_${VAR}_H 1) PLUGIN_INCLUDE_DIRECTORIES (${${VAR}_H}) ELSE () PLUGIN_MESSAGE ("${NAME} not found") ENDIF () ENDMACRO () MACRO (PLUGIN_REQUIRE_INCLUDE VAR NAME) PLUGIN_FIND_INCLUDE(${VAR} ${NAME} ${ARGN}) IF (NOT ${VAR}_H) PLUGIN_DISABLE () ENDIF () ENDMACRO () MACRO (PLUGIN_FIND_LIBRARY VAR NAME) FIND_LIBRARY (LIB${VAR} ${NAME}) IF (LIB${VAR}) PLUGIN_MESSAGE ("${LIB${VAR}}") SET (HAVE_LIB${VAR} 1) PLUGIN_LINK_LIBRARIES (${LIB${VAR}}) ELSE () PLUGIN_MESSAGE ("lib${NAME} not found") ENDIF () ENDMACRO () MACRO (PLUGIN_REQUIRE_LIBRARY VAR NAME) PLUGIN_FIND_LIBRARY(${VAR} ${NAME}) if (NOT LIB${VAR}) PLUGIN_DISABLE () ENDIF () ENDMACRO () MACRO (PLUGIN_FIND_PACKAGE VAR NAME) IF (PKG_CONFIG_FOUND) PKG_CHECK_MODULES (${VAR} ${NAME}) IF (${VAR}_FOUND) PLUGIN_MESSAGE ("${NAME} found") SET (HAVE_${VAR} 1) PLUGIN_INCLUDE_DIRECTORIES (${${VAR}_INCLUDE_DIRS}) PLUGIN_LINK_DIRECTORIES (${${VAR}_LIBRARY_DIRS}) PLUGIN_LINK_LIBRARIES (${${VAR}_LIBRARIES}) ENDIF () ENDIF () ENDMACRO () MACRO (PLUGIN_REQUIRE_PACKAGE VAR NAME) PLUGIN_FIND_PACKAGE(${VAR} ${NAME}) IF (NOT ${VAR}_FOUND) PLUGIN_DISABLE () ENDIF () ENDMACRO () MACRO (EXPECT_UNDEFINED_SYMBOLS) IF (APPLE) SET (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress") SET (CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace -undefined suppress") ENDIF (APPLE) ENDMACRO (EXPECT_UNDEFINED_SYMBOLS) ================================================ FILE: vm/src/from_squeak/unix/cmake/Utils.cmake ================================================ # Some random useful things to avoid repetition # # Last edited: 2009-08-26 10:41:32 by piumarta on ubuntu.piumarta.com MACRO (STRING_APPEND var str) IF (DEFINED ${var}) SET (${var} "${${var}} ${str}") ELSE (DEFINED ${var}) SET (${var} "${str}") ENDIF (DEFINED ${var}) ENDMACRO (STRING_APPEND) MACRO (LIST_APPEND list) LIST (APPEND ${list} "${ARGN}") LIST (REMOVE_DUPLICATES ${list}) ENDMACRO (LIST_APPEND) MACRO (FILE_APPEND to from) IF (EXISTS ${from}) FILE (READ ${from} tmp) FILE (APPEND ${to} "${tmp}") ENDIF (EXISTS ${from}) ENDMACRO (FILE_APPEND) MACRO (FILE_COPY to from) IF (EXISTS ${from}) FILE (READ ${from} tmp) FILE (WRITE ${to} "${tmp}") ENDIF (EXISTS ${from}) ENDMACRO (FILE_COPY) ================================================ FILE: vm/src/from_squeak/unix/cmake/config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-10-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner <per@bothner.com>. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # This shell variable is my proudest work .. or something. --bje set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; (old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; dummy=$tmpdir/dummy ; files="$dummy.c $dummy.o $dummy.rel $dummy" ; trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $files ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; unset files' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. eval $set_cc_for_build cat <<EOF >$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null if test "$?" = 0 ; then case `$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; 3-1307) UNAME_MACHINE="alphaev7" ;; esac fi rm -f $dummy.s $dummy && rmdir $tmpdir echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <sys/systemcfg.h> main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include <stdlib.h> #include <unistd.h> int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy && rmdir $tmpdir fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <unistd.h> int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <features.h> #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c && rmdir $tmpdir test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <features.h> #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says <Richard.M.Bartel@ccMail.Census.GOV> echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes <hewes@openmarket.com>. # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c <<EOF #ifdef _SEQUENT_ # include <sys/types.h> # include <sys/utsname.h> #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include <sys/param.h> printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include <sys/param.h> # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 <<EOF $0: unable to guess system type This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from ftp://ftp.gnu.org/pub/gnu/config/ If the version you run ($0) is already up to date, please send the following data and any information you think might be pertinent to <config-patches@gnu.org> in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: vm/src/from_squeak/unix/cmake/config.in ================================================ #!/bin/sh # echo "Configuring `basename $1` -> `basename $2`" >&2 sed " s%\[version\]%@version@%g s%\[major\]%@major@%g s%\[minor\]%@minor@%g s%\[patch\]%@patch@%g s%\[bindir\]%@prefix@/@bindir@%g s%\[imgdir\]%@prefix@/@imgdir@%g s%\[plgdir\]%@prefix@/@plgdir@%g s%\[mandir\]%@prefix@/@mandir@%g s%\[docdir\]%@prefix@/@docdir@%g s%\[useoss\]%@useoss@%g " < $1 > $2 ================================================ FILE: vm/src/from_squeak/unix/cmake/config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-09-05' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39 | mipstx39el \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic4x | c4x*) basic_machine=tic4x-unknown os=-coff ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: vm/src/from_squeak/unix/cmake/configure ================================================ #!/bin/sh # Last edited: 2010-04-10 19:38:50 by piumarta on ubuntu RELEASE_TAG="" help() { cat <<EOF Usage: $0 [options...] Options include: --help print this message and then exit --src=<directory> look for generated interpreter sources in <directory> --prefix=<directory> install into <prefix>/{bin,lib,man} --CFLAGS=<flags> override default compiler flags --without-<plugin> do not build the named plugin --without-gl disable everything that depends on OpenGL --without-SUGAR disable support for SUGAR environment Notes: 1. By default the CFLAGS will be set to create optimised binaries. If you are debugging the VM you probably want to use '--CFLAGS=-g' when invoking this script. 2. --CFLAGS and -without-* settings will be preserved in subsequent invocations of CMake, including those driven implicitly by changed dependencies. If you need to turn off a seting (to re-enable a plugin or restore the default CFLAGS) just give the relevant options with empty arguments, like this: $0 --CFLAGS= --without-UUIDPlugin= 3. Wizards can set any CMake variable from the command line with the option: --<CMakeVariableName>=<value> 4. In case it isn't already obvious, this is NOT the autotools 'configure' script. It is named so that 'configure; make' works in the expected way. 5. Bug reports, bug fixes and suggestions for improvement should be sent to the author (Ian Piumarta) at: <firstName> (at) <lastName> (dot) com EOF stop=true } config="`dirname \"$0\"`" unix="`dirname \"${config}\"`" guess=`"${config}"/config.guess` host=`"${config}"/config.sub ${guess}` src="${unix}/src" stop=false cflags="" error () { echo "$*" >&2 } dump () { echo "VM_VERSION = ${VM_VERSION}" echo "unix = ${unix}" echo "config = ${config}" echo "host = ${host}" echo "src = ${src}" echo "args = ${args}" stop=true } while [ $# -gt 0 ]; do case "$1" in --help) help; exit 0;; --debug-configure) dump;; --src=*) rel="`echo \"$1\" | sed 's/\-\-src=//'`" if test -d "${rel}"; then src="`(cd \"${rel}\"; pwd)`" else src="${rel}" fi args="${args} -DOPT--src=${src}";; --CFLAGS=*) cflags="`echo \"$1\" | sed 's/\-\-CFLAGS=//'`";; -CFLAGS=*) cflags="`echo \"$1\" | sed 's/\-CFLAGS=//'`";; --*=*) args="${args} -DOPT${1}";; --*) args="${args} -DOPT${1}=1";; -*) args="${args} ${1}";; *) error "unknown option: $1";; esac shift done interp_h="${src}/vm/interp.h" if test ! -f "${interp_h}"; then echo "problem locating generated source file: ${interp_h}" echo "use --src=<directory> to locate sources relative to ${unix}" echo "current value is: --src=\"${src}\"" exit 1 fi vmmversion="`tr '\015 ' '\012\012' < \"${interp_h}\" | sed '1,/VMMaker/d;q'`" if test -d "${unix}/.svn"; then svnversion=`svn info "${unix}/ChangeLog" | fgrep Revision: | awk '{print $2}'` echo "${svnversion}" > "${unix}/svnversion" else svnversion=`cat "${unix}/svnversion"` fi VM_VERSION="${vmmversion}-${svnversion}${RELEASE_TAG}" PLATFORM_SOURCE_VERSION="${svnversion}" if ${stop}; then exit 1 fi echo "-- Configuring squeak ${VM_VERSION} for ${host}" echo "-- Using source directory ${src}" if test -n "${cflags}"; then cmake "${unix}" -DVM_HOST="${host}" -DVM_VERSION="${VM_VERSION}" -DPLATFORM_SOURCE_VERSION="${PLATFORM_SOURCE_VERSION}" -DOPT--CMAKE_C_FLAGS="${cflags}" ${args} else cmake "${unix}" -DVM_HOST="${host}" -DVM_VERSION="${VM_VERSION}" -DPLATFORM_SOURCE_VERSION="${PLATFORM_SOURCE_VERSION}" ${args} fi ================================================ FILE: vm/src/from_squeak/unix/cmake/disabledPlugins.c ================================================ typedef struct { void *a, *b, *c; } sqExport; #define disabled(NAME) sqExport NAME##_exports = { 0, 0, 0 }; ================================================ FILE: vm/src/from_squeak/unix/cmake/gnuify ================================================ #!/bin/sh # # Last edited: 2009-09-17 08:47:30 by piumarta on ubuntu.piumarta.com gfy="$1" src="$2" dst="$3" log="${dst}.log" rm -f "${dst}" "${log}" exec >> "${log}" 2>&1 set -x try () { "$1" -f "${gfy}" "${src}" > "${dst}" 2>> "${log}"; } try gawk || try awk || cp -p "${src}" "${dst}" ================================================ FILE: vm/src/from_squeak/unix/cmake/gnuify.awk ================================================ #!/usr/bin/awk -f # # Rewrite the interpreter source in $1 to use GNU C extensions, writing the # modified file to stdout. # # Author: Ian.Piumarta@INRIA.Fr # # Last edited: 2009-09-17 08:34:23 by piumarta on ubuntu.piumarta.com # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. BEGIN { print "/* This file has been post-processed for GNU C */\n\n"; # print "copying first section of file" > "/dev/stderr"; stage= 0; } /#include "sq.h"/ { print "#include \"sqGnu.h\"\n"; next; } # An inlining comment means the interpreter was not inlined /inline\: true/ { # print NR, $0 > "/dev/stderr"; # print "" > "/dev/stderr"; # print "*** interpreter was not inlined: bailing out! ***" > "/dev/stderr"; # print "" > "/dev/stderr"; stage= -1; } (stage == 0) && /^int interpret\(void\) \{/ { # print "interpret: adding static register assignments" > "/dev/stderr"; stage= 1; print; next; } (stage == 0) && /^sqInt interpret\(void\) \{/ { # print "interpret: adding static register assignments" > "/dev/stderr"; stage= 1; print; next; } (stage == 1) && /^ char\* localIP;/ { print " register char* localIP IP_REG;"; next; } (stage == 1) && /^register struct foo \* foo = &fum;/ { print " register struct foo * foo GP_REG= &fum;"; next; } (stage == 1) && /^ char\* localSP;/ { print " register char* localSP SP_REG;"; next; } (stage == 1) && /^ int currentBytecode;/ { print " register int currentBytecode CB_REG;"; next; } (stage == 1) && /^ sqInt currentBytecode;/ { print " register int currentBytecode CB_REG;"; next; } (stage == 1) && /^$/ { # print "interpret: adding bytecode dispatch table" > "/dev/stderr"; print " JUMP_TABLE;\n"; # print "interpret: rewriting case labels and outer breaks" > "/dev/stderr"; stage= 2; FS=" "; # FS="[ :]+"; next; } (stage == 2) && /^ case / { print " CASE(" (($NF) + 0) ")"; # print " CASE(" $3 ")"; next; } (stage == 2) && /^ break;/ { print " BREAK;"; next; } (stage == 2) && /^\}/ { stage= -1; print; next; } (stage == 3) && /^int primitiveResponse\(/ { print; # print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr"; print " PRIM_TABLE;\n"; # print "primitiveResponse: rewriting case labels" > "/dev/stderr"; stage= 4; FS=" "; # FS="[ :]+"; next; } (stage == 3) && /^sqInt primitiveResponse\(/ { print; # print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr"; print " PRIM_TABLE;\n"; # print "primitiveResponse: rewriting case labels" > "/dev/stderr"; stage= 4; FS=" "; # FS="[ :]+"; next; } (stage == 4) && /^ switch \(primitiveIndex\) \{/ { # print "primitiveResponse: adding primitive dispatch" > "/dev/stderr"; print " PRIM_DISPATCH;"; print; next; } (stage == 4) && /^ switch \(foo->primitiveIndex\) \{/ { # print "primitiveResponse: adding primitive dispatch" > "/dev/stderr"; print " PRIM_DISPATCH;"; print; next; } (stage == 4) && /^ case / { print " CASE(" (($NF) + 0) ")"; # print " CASE(" $3 ")"; next; } (stage == 4) && /^\}/ { # print "copying last section of file" > "/dev/stderr"; stage= -1; FS=" "; print; next; } # default { print; next; } END { if (stage != -1) { print "#error GNUIFICATION FAILED (", stage, ")" } } ================================================ FILE: vm/src/from_squeak/unix/cmake/squeak.in ================================================ #!/bin/sh # # Launch squeakvm from the command line or a menu script, with a good # plugin path, text encodings and pulseaudio kludge # # Last edited: 2010-05-13 14:15:38 by piumarta on emilia-2.local PATH=/usr/bin:/bin realpath () { path="$1" while test -L "${path}"; do dir=`dirname "${path}"` dir=`cd "${dir}" && pwd -P` path=`basename "${path}"` path=`ls -l "${dir}/${path}" | sed 's,.* -> ,,'` if test `expr "${path}" : "/"` -eq 0; then path="${dir}/${path}" fi done if test -d "${path}"; then (cd "${path}" && pwd -P) else dir=`dirname "${path}"` base=`basename "${path}"` (cd "${dir}" && echo "`pwd -P`/${base}") fi } bindir=`realpath "${0}"` bindir=`dirname "${bindir}"` prefix=`dirname "${bindir}"` libdir="${prefix}/lib/squeak" plgdir="${libdir}/[version]" useoss="[useoss]" vm="squeakvm" plugins="" wrapper="" for opt in $*; do case ${opt} in -vm-sound*) useoss="false";; -vm) case "$2" in sound*) useoss="false"; esac;; esac done # find the vm and set the plugin path if test -x "${plgdir}/${vm}"; then # bin/squeak -> lib/squeak/x.y-z/squeakvm vm="${plgdir}/${vm}" plugins="${plgdir}" elif test -x "${bindir}/${vm}"; then # bld/squeak -> bld/squeakvm vm="${bindir}/${vm}" plugins="${bindir}/%n" elif test -x `which ${vm}`; then vm=`which ${vm}` plugins="" else echo "cannot find ${vm}" >&2 exit 1 fi # command-line overrides environment, so communicate anything we decide here via the environment if test -z "${SQUEAK_PATHENC}"; then SQUEAK_PATHENC="UTF-8"; export SQUEAK_PATHENC; fi if test -z "${SQUEAK_ENCODING}"; then SQUEAK_ENCODING="UTF-8"; export SQUEAK_ENCODING; fi if test -z "${SQUEAK_PLUGINS}"; then if test -n "${plugins}"; then SQUEAK_PLUGINS="${plugins}" export SQUEAK_PLUGINS fi fi # deal with pulseaudio if it is running if test -z "${SQUEAK_VM}"; then if ${useoss}; then if pulseaudio --check 2>/dev/null; then if padsp true 2>/dev/null; then wrapper="padsp" SQUEAK_VM="sound-OSS" export SQUEAK_VM fi fi fi fi # fix broken locales if test -z "$LC_ALL"; then LC_ALL="$LANG" export LC_ALL fi # debug output if test "0$SQUEAK_DEBUG" -gt "0"; then set | fgrep SQUEAK_ set -x fi # run the vm exec ${wrapper} "${vm}" "$@" ================================================ FILE: vm/src/from_squeak/unix/cmake/squeak.sh.in ================================================ #!/bin/sh # # Launch squeak from a menu, prompting for and/or installing an image # # Last edited: 2010-04-09 04:35:35 by piumarta on ubuntu PATH=/usr/bin:/bin if pwd -P 2>/dev/null 1>&2; then pwd="pwd -P"; else pwd="pwd"; fi me=`basename $0` bindir=`dirname $0` bindir=`cd ${bindir}; ${pwd}` prefix=`dirname ${bindir}` libdir="${prefix}/lib/squeak" vm="squeak" # find a way to display dialogues if test -n "$DISPLAY" -a -x "`which kdialog 2>/dev/null`"; then error () { kdialog --error "${me}: $*"; exit 1; } confirm () { if kdialog --yesno "${1} ${2}?"; then result="${2}"; else result=""; fi; } chooseItem () { title="$1"; shift; result=`kdialog --combobox "${title}" $*`; } findFile () { result=`kdialog --title "$1" --getopenfilename . '*.image'`; } findDirectory () { result=`kdialog --title "$1" --getexistingdirectory .`; } elif [ -n "$DISPLAY" -a -x "`which zenity 2>/dev/null`" ]; then error () { zenity --error --text "${me}: $*"; exit 1; } confirm () { if zenity --question --text="${1} ${2}?"; then result="${2}"; else result=""; fi; } chooseItem () { title="$1"; shift; result=`zenity --title "${title}" --list --column Images $*`; } findFile () { result=`zenity --title "$1" --file-selection --file-filter='*.image'`; } findDirectory () { result=`zenity --title "$1" --file-selection --directory`; } else error () { echo "${me}: $*" >&2; exit 1; } confirm () { error "this cannot happen"; } chooseItem () { error "this cannot happen"; } findFile () { error "no image name specified"; } findDirectory () { error "this cannot happen"; } fi # succeed if there are two or more arguments plural () { test -n "$2"; } # find the VM if test -x "${bindir}/${vm}"; then vm="${bindir}/${vm}" elif test -x "`which ${vm} 2>/dev/null`"; then vm="`which ${vm} 2>/dev/null`" else error "Cannot find ${vm}" fi # if we have arguments then assume an image name was given or we came # from a command line if test $# -gt 0; then exec "${vm}" "$@" fi findFile "Choose a saved image to resume or cancel to install a new one" if test -z "${result}"; then images="" if test -d "${libdir}"; then images=`cd "${libdir}"; ls *.image 2>/dev/null` fi if test -z "${images}"; then error "no image name specified and no images found in ${libdir}" exit 1 fi if plural ${images}; then chooseItem "Choose an image to install" ${images} else confirm "Install image" ${images} fi if test -z "${result}"; then exit 0 fi image=${result} changes=`basename ${image} .image`.changes findDirectory "Choose a destination directory for the image" if test -z "${result}"; then exit 0 fi if test -e "${result}/${image}"; then confirm "Overwrite existing ${image} in" "${result}" if test -z "${result}"; then exit 0; fi fi cp -p "${libdir}/${image}" "${result}/." cp -p "${libdir}/${changes}" "${result}/." ln -s "${libdir}"/*.sources "${result}/." image="${result}/${image}" else image="${result}" fi cd "`dirname ${image}`" exec "${vm}" "`basename ${image}`" ================================================ FILE: vm/src/from_squeak/unix/cmake/testDoubleWordAlignment.c ================================================ int f(void *i) { *(double *)i= *(double *)(i + 4); return *(char *)i; } int main() { char b[12]; b[0]=1; b[1]=2; b[2]=3; b[3]=4; b[4]=0; b[5]=0; b[6]=0; b[7]=0; b[8]=0; b[9]=0; b[10]=0; b[11]=0; return f(b); } ================================================ FILE: vm/src/from_squeak/unix/cmake/testDoubleWordOrder.c ================================================ union { double d; int i[2]; } d; int main(void) { d.d= 1.0; return d.i[0] == 0; } ================================================ FILE: vm/src/from_squeak/unix/cmake/testLanginfoCodeset.c ================================================ #include <langinfo.h> int main(int argc, char **argv) { char *cs= nl_langinfo(CODESET); return 0; } ================================================ FILE: vm/src/from_squeak/unix/cmake/verstamp ================================================ #!/bin/sh # # Write a version stamp into $1. $2 is the compiler name. # # Last edited: 2002-06-08 18:32:53 by piumarta on emilia.inria.fr if test -f $1; then SERIAL=`head -1 $1 | cut -d ' ' -f 3 | sed 's/;//'` SERIAL=`expr $SERIAL + 1` else SERIAL=1 fi if expr "$2" : ".*gcc" >/dev/null ; then CC=`$2 -v 2>&1 | tail -1 | sed 's/.*based on//g' | awk '{print $1 , $3} '` else CC=$2 fi cat <<_EOF >$1 int vm_serial= $SERIAL; char *vm_date= "`date`"; char *cc_version= "$CC"; char *ux_version= "`uname -a | sed 's, unknown,,g'`"; _EOF ================================================ FILE: vm/src/from_squeak/unix/config/Makefile ================================================ configure : .force ./mkacinc > acplugins.m4 aclocal autoconf rm acplugins.m4 .force : ================================================ FILE: vm/src/from_squeak/unix/config/Makefile.cpp-plg.in ================================================ # Makefile.plg.in -- default rules for plugins -*- makefile -*- # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: ian.piumarta@inria.fr # # Last edited: Wed Sep 1 19:01:21 PDT 2010 by eliot; alternative for c++ [make_cfg] [make_plg] XINCLUDES = [includes] OBJS = [targets] TARGET = [target] PLIBS = [plibs] [make_inc] $(TARGET) : $(OBJS) Makefile $(LINKXX) $(TARGET) $(OBJS) $(PLIBS) $(RANLIB) $(TARGET) [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/config/Makefile.in ================================================ # Makefile.in for Unix Squeak using VMMaker -*- makefile -*- # # Copyright (C) 1996-2005 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: ian.piumarta@inria.fr # # Last edited: Tue Mar 2 16:59:47 PST 2010 by eliot @make_cfg@ @make_prg@ la = .la SQLIBS = [targets] PLUGINS_LA = [plugins] squeak = squeak squeaksh = squeak.sh binsqueaksh = bin.squeak.sh all : $(squeak) plugins squeak.1 $(npsqueak) # VM $(squeak) : config.sh $(SQLIBS) version.o $(LINK) $(squeak) $(SQLIBS) version.o $(LIBS) [plibs] vm/vm.a @echo @size $(squeak) @echo @./$(squeak) -version @echo version.o : version.c $(COMPILE) version.o version.c version.c : $(SQLIBS) ${cfgdir}/verstamp version.c $(CC) plugins : config.sh $(PLUGINS_LA) # nuke everything but plugins.int & plugins.ext reallyclean: for f in *; do case "$$f" in plugins.[ie][nx]t) ;; *) rm -rf $$f; esac; done # npsqueak npsqueak : nps/npsqueak.so nps : mkdir nps $(SHELL) -ec 'cd nps; ln -s $(topdir)/platforms/unix/npsqueak/* .' nps/npsqueak.so : nps $(SHELL) -ec 'cd nps; $(MAKE) plgdir=$(plgdir) bindir=$(bindir) imgdir=$(imgdir)' # OSX app bundle osxdir=$(topdir)/platforms/unix/vm-display-Quartz app=Squeak-$(VM_MAJOR).$(VM_MINOR)-$(VM_RELEASE).app appdir=$(app)/Contents Squeak.app : squeak plugins Info.plist /bin/rm -rf $(app) mkdir -p $(appdir)/MacOS cp -p squeak $(appdir)/MacOS/. cp -p */.libs/* $(appdir)/MacOS/. rm -f $(appdir)/MacOS/*.la rm -f $(appdir)/MacOS/*.lai cp -p Info.plist $(appdir)/. cp -p $(osxdir)/PkgInfo $(appdir)/. cp -pr $(osxdir)/Resources $(appdir)/. -find $(app) -name '*~' | xargs rm -f bndl_version=${VM_VERSION} (${SQ_VERSION}) Info.plist : $(osxdir)/Info.plist.in $(osxdir)/mkinfo $(osxdir)/mkinfo $(osxdir)/Info.plist.in Info.plist.tmp "${bndl_version}" mv Info.plist.tmp Info.plist # OSX plugin bundle nposxdir=$(topdir)/platforms/unix/vm-display-Quartz npapp=NPSqueak.bundle npappdir=$(npapp)/Contents NPSqueak.bundle : NPSqueak plugins /bin/rm -rf $(npapp) mkdir -p $(npappdir)/MacOS cp -p squeak $(npappdir)/MacOS/. cp -p */.libs/*.so $(npappdir)/MacOS/. cp -p Info.plist $(npappdir)/. cp -p $(nposxdir)/PkgInfo $(npappdir)/. cp -pr $(nposxdir)/Resources $(npappdir)/. -find $(npapp) -name '*~' | xargs rm -f NPOBJS = vm-display-Quartz/sqUnixSafari.o vm-sound-MacOSX/sqUnixSoundMacOSX.o vm-display-Quartz/sqUnixQuartz.o NPLIBS = $(NPOBJS) -framework CoreAudio -framework AudioToolbox NPSqueak : config.sh $(SQLIBS) version.o $(NPOBJS) gcc -bundle -flat_namespace -undefined suppress -o NPSqueak \ $(NPLIBS) $(SQLIBS) version.o $(LIBS) vm/vm.a # manual page squeak.1 : $(topdir)/platforms/unix/doc/squeak.1 $(cfgdir)/mkman $(VM_MAJOR) $(VM_VERSION) \ $(bindir) $(imgdir) $(plgdir) $(mandir) $(docdir) \ < $(topdir)/platforms/unix/doc/squeak.1 > $@ # install/distrib (these just get in the way -- suck 'em in from elsewhere) @Makefile_install@ @Makefile_dist@ @Makefile_rpm@ @Makefile_deb@ # VMM configuration changes config.sh : $(vmmcfg)/plugins.int $(vmmcfg)/plugins.ext ./config.status @echo @echo "configuration changed: please run make again" @echo @exit 1 [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/config/Makefile.install ================================================ # Makefile.install for Unix Squeak using VMMaker -*- makefile -*- # # Author: ian.piumarta@inria.fr # # Last edited: 2005-03-22 13:05:47 by piumarta on squeak.hpl.hp.com DOCFILES = COPYING COPYRIGHT LICENSE \ README.Contributing README.Keyboard README.Sound ICONS = $(topdir)/platforms/unix/vm-display-Quartz/Resources/SqueakVM.icns install : install-squeak install-plugins install-doc $(install_nps) uninstall : uninstall-squeak uninstall-plugins uninstall-doc $(uninstall_nps) # squeak install-squeak : $(squeak) $(MKINSTALLDIRS) $(ROOT)$(plgdir) $(MKINSTALLDIRS) $(ROOT)$(bindir) $(INSTALL_PROG) $(squeak) $(ROOT)$(plgdir) $(INSTALL_SCRIPT) $(squeaksh) $(ROOT)$(exec_prefix)/$(squeak) $(INSTALL_SCRIPT) $(binsqueaksh) $(ROOT)$(bindir)/$(squeak) if test -n "$(VM_APP_ICONS)"; then \ $(INSTALL_DATA) $(ICONS) $(ROOT)$(VM_APP_ICONS); \ fi uninstall-squeak : .force if test -n "$(VM_APP_ICONS)"; then \ $(UNINSTALL) $(ROOT)$(VM_APP_ICONS); \ fi @$(UNINSTALL) $(ROOT)$(plgdir) $(squeak) @$(UNINSTALL) $(ROOT)$(bindir) $(squeak) # plugins install-plugins : plugins $(MKINSTALLDIRS) $(ROOT)$(plgdir) @list='$(PLUGINS_LA)'; for p in $$list; do \ if test -f */$$p; then \ echo "$(LIBTOOL) --mode=install $(INSTALL_PROG) $$p $(ROOT)$(plgdir)/$$p"; \ $(LIBTOOL) --mode=install $(INSTALL_PROG) */$$p $(ROOT)$(plgdir)/$$p; \ else :; fi; \ done -rm $(ROOT)$(plgdir)/*.la uninstall-plugins : .force @list='$(PLUGINS_LA)'; for p in $$list; do \ filename=$(ROOT)/$(plgdir)/`basename $$p .la`;\ if test -f $$filename; then \ echo "$(LIBTOOL) --mode=uninstall rm -f $$filename"; \ $(LIBTOOL) --mode=uninstall rm -f $$filename; \ else echo "$$filename does not exist"; fi; \ done @$(UNINSTALL) $(ROOT)$(plgdir) # doc install-doc : squeak.1 $(MKINSTALLDIRS) $(ROOT)$(docdir) @list='$(DOCFILES)'; for f in $$list; do \ echo $(INSTALL_DATA) $(topdir)/platforms/unix/doc/$$f $(ROOT)$(docdir); \ $(INSTALL_DATA) $(topdir)/platforms/unix/doc/$$f $(ROOT)$(docdir); \ done gzip -f9 $(ROOT)$(docdir)/* $(MKINSTALLDIRS) $(ROOT)$(mandir)/man1 $(INSTALL_DATA) squeak.1 $(ROOT)$(mandir)/man1 rm -f $(ROOT)$(mandir)/man1/inisqueak.1 $(ROOT)$(mandir)/man1/inisqueak.1.gz if test -f $(ROOT)$(mandir)/man1/squeak.1; then $(LN) $(ROOT)$(mandir)/man1/squeak.1 $(ROOT)$(mandir)/man1/inisqueak.1; fi if test -f $(ROOT)$(mandir)/man1/squeak.1.gz; then $(LN) $(ROOT)$(mandir)/man1/squeak.1.gz $(ROOT)$(mandir)/man1/inisqueak.1.gz; fi uninstall-doc : @list='$(DOCFILES)'; for f in $$list; do \ rm -fv $(ROOT)$(docdir)/$$f.gz; \ done @$(UNINSTALL) $(ROOT)$(docdir) $(DOCFILES) @$(UNINSTALL) $(ROOT)$(mandir)/man1 squeak.1 inisqueak.1 # image install-image : inisqueak $(topdir)/Squeak$(SQ_VERSION).image.gz $(topdir)/Squeak$(SQ_VERSION).changes.gz $(MKINSTALLDIRS) $(ROOT)$(imgdir) $(INSTALL_PROG) inisqueak $(ROOT)$(imgdir) $(INSTALL_DATA) $(topdir)/Squeak$(SQ_VERSION).image.gz $(ROOT)$(imgdir) $(INSTALL_DATA) $(topdir)/Squeak$(SQ_VERSION).changes.gz $(ROOT)$(imgdir) $(LN_S) Squeak$(SQ_VERSION).image.gz $(ROOT)$(imgdir)/squeak.image.gz $(LN_S) Squeak$(SQ_VERSION).changes.gz $(ROOT)$(imgdir)/squeak.changes.gz $(MKINSTALLDIRS) $(ROOT)$(bindir) ( path=`$(cfgdir)/relpath $(bindir) $(imgdir)`; \ cd $(ROOT)$(bindir); \ rm -f inisqueak; \ $(LN_S) $$path/inisqueak .; ) uninstall-image : @$(UNINSTALL) $(ROOT)$(plgdir) Squeak$(SQ_VERSION).image.gz @$(UNINSTALL) $(ROOT)$(plgdir) Squeak$(SQ_VERSION).changes.gz @$(UNINSTALL) $(ROOT)$(plgdir) inisqueak # sources install-sources : $(MKINSTALLDIRS) $(ROOT)$(imgdir) $(INSTALL_DATA) $(topdir)/SqueakV$(SQ_MAJOR).sources $(ROOT)$(imgdir) uninstall-sources : @$(UNINSTALL) $(ROOT)$(imgdir) SqueakV$(SQ_MAJOR).sources # npsqueak install-npsqueak : npsqueak .force $(SHELL) -ec 'cd nps; $(MAKE) install ROOT=$(ROOT) VM_VERSION=$(VM_VERSION) plgdir=$(plgdir) bindir=$(bindir) imgdir=$(imgdir)' uninstall-npsqueak : npsqueak .force $(SHELL) -ec 'cd nps; $(MAKE) uninstall ROOT=$(ROOT) VM_VERSION=$(VM_VERSION) plgdir=$(plgdir) bindir=$(bindir) imgdir=$(imgdir)' ================================================ FILE: vm/src/from_squeak/unix/config/Makefile.plg.in ================================================ # Makefile.plg.in -- default rules for plugins -*- makefile -*- # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: ian.piumarta@inria.fr # # Last edited: 2006-10-18 10:13:37 by piumarta on emilia.local [make_cfg] [make_plg] XINCLUDES = [includes] OBJS = [targets] TARGET = [target] PLIBS = [plibs] [make_inc] $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) $(PLIBS) $(RANLIB) $(TARGET) [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/config/README ================================================ Assuming you know how to update these files and want to run make to make a new configure, a word to the wise. Do _not_ run make on eg. Mac OS X. It will not produce a valid configure. Instead things will appear to work until libtool is invoked. libtool will go into an infinite recursion. Instead, run make on e.g. linux. make configure did work on e.g. Mac OS X 10.4 but at least on 10.6 it fails. Eliot Miranda Jan 2010 ================================================ FILE: vm/src/from_squeak/unix/config/Squeak.spec.in ================================================ Name: Squeak Version: [version] Release: [release] Requires: Summary: A portable implementation of the Smalltalk programming system. Vendor: Squeak.org Source: [source] Copyright: Squeak Software License Group: Development/Languages BuildRoot: /var/tmp/%{name}-root %description Squeak is a full-featured implementation of the Smalltalk programming language and environment based on (and largely compatible with) the original Smalltalk-80 system. Squeak has very powerful 2- and 3-D graphics, sound, video, MIDI, animation and other multimedia capabilities -- and one of the most impressive development environments ever created. It also includes a customisable framework for creating dynamic HTTP servers and interactively extensible Web sites. The entire Squeak system is open source software, distributed freely with a liberal license. See <http://Squeak.org> for further information. This package contains the binaries, libraries and data files needed to run version [version] of Squeak. %prep %setup -q %build mkdir bld-rpm cd bld-rpm ../platforms/unix/config/configure --prefix=/usr make %install rm -rf $RPM_BUILD_ROOT cd bld-rpm make install-bin install-image install-sources ROOT=$RPM_BUILD_ROOT cd .. # # package file lists # find $RPM_BUILD_ROOT \( -type f -o -type l \) -print | sed "s,$RPM_BUILD_ROOT,,;s,^//,/," > sq-files %clean echo "rm -rf $RPM_BUILD_ROOT" echo "rm -rf bld-rpm" %files -f sq-files %files -f ffi-files ffi ================================================ FILE: vm/src/from_squeak/unix/config/acinclude.m4 ================================================ # Local autoconf macros for configuring Unix Squeak -*- sh -*- # # Copyright (C) 1996-2005 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: Ian.Piumarta@squeakland.org # # Last edited: Tue Jan 26 11:07:40 PST 2010 by eliot AC_DEFUN([AC_CHECK_VMM_DIR],[ AC_MSG_CHECKING([sanity of generated src directory]) vmmcheck () { if test ! ${2} ${3}; then AC_MSG_RESULT(bad) echo "missing ${1}: ${3}" exit 1 fi } vmmcheck dir -d ${vmmcfg} vmmcheck file -f ${vmmcfg}/plugins.int vmmcheck file -f ${vmmcfg}/plugins.ext vmmcheck dir -d ${vmmdir} vmmcheck dir -d ${vmmdir}/plugins vmmcheck dir -d ${vmmdir}/vm vmmcheck file -f ${vmmdir}/vm/cogit.c vmmcheck file -f ${vmmdir}/vm/cogit.h vmmcheck file -f ${vmmdir}/vm/cogmethod.h vmmcheck file -f ${vmmdir}/vm/cointerp.c vmmcheck file -f ${vmmdir}/vm/cointerp.h vmmcheck file -f ${vmmdir}/vm/gcc3x-cointerp.c AC_MSG_RESULT(okay)]) AC_DEFUN([AC_VM_VERSION],[ VM_MAJOR=$1 VM_MINOR=$2 VM_RELEASE=$3 SQ_MAJOR=$4 SQ_MINOR=$5 SQ_UPDATE=$6 ]) AC_DEFUN([AC_CHECK_VERSION],[ gendir="${vmmdir}/vm" version=`${cfgdir}/version ${gendir}/cointerp.c` SQ_MAJOR=`echo ${version} | cut -d ' ' -f 1` SQ_MINOR=`echo ${version} | cut -d ' ' -f 2` SQ_UPDATE=`echo ${version} | cut -d ' ' -f 3` ]) AC_SUBST(NM) AC_SUBST(LD) AC_DEFUN([AC_REQUIRE_SIZEOF],[ AC_MSG_CHECKING("size of $1") AC_TRY_RUN([#include <sys/types.h> int main(){return(sizeof($1) == $2)?0:1;}], AC_MSG_RESULT("okay"), AC_MSG_RESULT("bad") AC_MSG_ERROR("one or more basic data types has an incompatible size: giving up"))]) # Try to find a 64-bit integer data type. # NOTE: `long long' is 64 bits in ANSI C99 [ISO/IEC 9899:1999 (E)]. AC_DEFUN([AC_CHECK_INT64_T],[ AC_CACHE_CHECK([for 64-bit integer type],ac_cv_int64_t, AC_TRY_RUN([int main(){return(sizeof(long) == 8)?0:1;}], ac_cv_int64_t="long", AC_TRY_RUN([int main(){return(sizeof(long long) == 8)?0:1;}], ac_cv_int64_t="long long", ac_cv_int64_t="no"))) if test "$ac_cv_int64_t" = ""; then AC_MSG_ERROR([could not find a 64-bit integer type]) fi SQUEAK_INT64_T="$ac_cv_int64_t" AC_DEFINE_UNQUOTED(squeakInt64, $ac_cv_int64_t)]) AC_DEFUN([AC_NEED_SUNOS_H], [case "$host" in *-sunos*) AC_DEFINE(NEED_SUNOS_H, 1) esac]) AC_DEFUN([AC_PROG_CC_WALL], [AC_PROG_CC test "$GCC" = yes && WFLAGS="-Wall -Wno-unknown-pragmas" AC_SUBST(WFLAGS)]) AC_DEFUN([AC_GNU_OPT], [AC_MSG_CHECKING([for $host_cpu optimisation flags]) ac_optflags="no" if test "$GCC" = yes; then case $host_cpu in # Leave this to the configure command # i?86) # ac_optflags="-fomit-frame-pointer" # ;; powerpc|ppc) ac_optflags="-O3 -funroll-loops -mcpu=750 -mno-fused-madd" ;; esac AC_DEFINE(VM_BUILD_STRING, ["Unix built on "__DATE__ " "__TIME__" Compiler: "__VERSION__]) else ac_optflags="-O" ac_vm_build_date="`date`" AC_DEFINE(VM_BUILD_STRING, ["Unix built on ${ac_vm_build_date}"]) fi if test "$ac_optflags" = "no"; then AC_MSG_RESULT([(none)]) else CFLAGS="$CFLAGS $ac_optflags" AC_MSG_RESULT("$ac_optflags") fi]) AC_DEFUN([AC_GNU_INTERP], [INTERP="cointerp" AC_SUBST(INTERP) AC_PROG_AWK AC_MSG_CHECKING(whether we can compile gcc3x-cointerp.c) if test "$GCC" = "yes"; then INTERP="gcc3x-$INTERP"; AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi]) AC_DEFUN([AC_PROG_AS_GNU], [AC_CHECK_PROG(AS,as,as) AC_MSG_CHECKING(for GNU as) case "$GAS" in yes|no) ;; *) if test "$AS" = "as" && as -v /dev/null </dev/null 2>&1 | fgrep -i gnu >/dev/null then GAS=yes else GAS=no fi ;; esac AC_MSG_RESULT($GAS)]) AC_DEFUN([AC_CHECK_ATEXIT], [AC_CACHE_CHECK([for atexit or on_exit], ac_cv_atexit, AC_TRY_COMPILE([#include <stdlib.h>],[atexit(0);], ac_cv_atexit="atexit", AC_TRY_COMPILE([#include <stdlib.h>],[on_exit(0);], ac_cv_atexit="on_exit", ac_cv_atexit="no"))) if test "$ac_cv_atexit" != "no"; then AC_DEFINE_UNQUOTED(AT_EXIT, $ac_cv_atexit) fi]) AC_DEFUN([AC_CHECK_SOCKLEN_T], [AC_CACHE_CHECK([for socklen_t in sys/socket.h], ac_cv_socklen_t, AC_TRY_COMPILE([#include <sys/socket.h>],[sizeof(socklen_t);], ac_cv_socklen_t="yes", ac_cv_socklen_t="no")) test "$ac_cv_socklen_t" != "yes" && AC_DEFINE(socklen_t, int)]) AC_DEFUN([AC_CHECK_TZSET], [AC_CACHE_CHECK([for tzset], ac_cv_tzset, AC_TRY_COMPILE([#include <time.h>],[tzet();], ac_cv_tzset="yes", ac_cv_tzset="no")) test "$ac_cv_tzset" != "no" && AC_DEFINE(HAVE_TZSET)]) AC_DEFUN([AC_CHECK_GMTOFF], [AC_CACHE_CHECK([for gmtoff in struct tm], ac_cv_tm_gmtoff, AC_TRY_COMPILE([#include <time.h>],[struct tm tm; tm.tm_gmtoff;], ac_cv_tm_gmtoff="yes", ac_cv_tm_gmtoff="no")) test "$ac_cv_tm_gmtoff" != "no" && AC_DEFINE(HAVE_TM_GMTOFF)]) AC_DEFUN([AC_CHECK_TIMEZONE], [AC_CACHE_CHECK([for timezone and daylight variables], ac_cv_timezone, AC_TRY_COMPILE([extern long timezone; extern int daylight;],[timezone;daylight;], ac_cv_timezone="yes", ac_cv_timezone="no")) test "$ac_cv_timezone" != "no" && AC_DEFINE(HAVE_TIMEZONE)]) AC_DEFUN([AC_CHECK_GETHOSTNAME], [AC_CACHE_CHECK([for gethostname in unistd.h], ac_cv_gethostname_p, AC_TRY_COMPILE([#include <unistd.h>],[return (int)gethostname;], ac_cv_gethostname_p="yes", ac_cv_gethostname_p="no")) test "$ac_cv_gethostname_p" = "no" && AC_DEFINE(NEED_GETHOSTNAME_P)]) if test -x /bin/test; then test=/bin/test else if test -x /usr/bin/test; then test=/usr/bin/test else test=test fi fi AC_DEFUN([AC_C_BYTEORDER], [AC_C_BIGENDIAN if test $ac_cv_c_bigendian != yes then CFLAGS="$CFLAGS -DLSB_FIRST=1" fi]) AC_DEFUN([AC_C_DOUBLE_ALIGNMENT], [AC_CACHE_CHECK([whether unaligned access to doubles is ok], ac_cv_double_align, AC_TRY_RUN([f(int i){*(double *)i=*(double *)(i+4);} int main(){char b[[12]];f(b);return 0;}], ac_cv_double_align="yes", ac_cv_double_align="no")) test "$ac_cv_double_align" = "no" && AC_DEFINE(DOUBLE_WORD_ALIGNMENT)]) # this assumes that libtool has already been configured and built -- # if not then err on the side of conservatism. AC_DEFUN([AC_MODULE_LIB_PREFIX], [AC_CACHE_CHECK([for prefix to use for loadable modules], ac_cv_module_prefix, if test -x ./libtool && test "`./libtool --config | fgrep need_lib_prefix`" = "need_lib_prefix=no" then ac_cv_module_prefix="(none)"; else ac_cv_module_prefix="lib" fi) AC_DEFINE_UNQUOTED(VM_MODULE_PREFIX,"$mkfrags_lib_prefix") test "$ac_cv_module_prefix" = lib && mkfrags_lib_prefix=lib]) AC_DEFUN([AC_64BIT_ARCH], [AC_MSG_CHECKING(for compiler flags to force 32-bit addresses) case $host in alpha*) CFLAGS_32="-taso" test "$GCC" = "yes" && CC="\$(utldir)/decgcc" ;; esac AC_MSG_RESULT($CFLAGS_32)]) ### plugin support # AC_PLUGIN_SUBST(varname,value) AC_DEFUN([AC_PLUGIN_DISABLE_PLUGIN],[ AC_MSG_RESULT([******** disabling $1]) disabled_plugins="${disabled_plugins} $1"]) AC_DEFUN([AC_PLUGIN_DISABLE],[ AC_PLUGIN_DISABLE_PLUGIN(${plugin})]) AC_DEFUN([AC_PLUGIN_USE_LIB],[ plibs="${plibs} $1"]) AC_DEFUN([AC_PLUGIN_DEFINE_UNQUOTED],[ echo 's%[\['$1'\]]%'$2'%g' >> ${plugin}.sub]) # AC_PLUGIN_SEARCH_LIBS(function,libs...) AC_DEFUN([AC_PLUGIN_SEARCH_LIBS],[ AC_SEARCH_LIBS($1,$2,, AC_MSG_RESULT([******** disabling ${plugin} due to missing libraries]) disabled_plugins="${disabled_plugins} ${plugin}")]) # AC_PLUGIN_CHECK_LIB(lib,func,ok,bad) AC_DEFUN([AC_PLUGIN_CHECK_LIB],[ AC_CHECK_LIB($1,$2, plibs="${plibs} $1", AC_MSG_RESULT([******** disabling ${plugin} due to missing libraries]) disabled_plugins="${disabled_plugins} ${plugin}")]) ================================================ FILE: vm/src/from_squeak/unix/config/aclocal.m4 ================================================ # generated automatically by aclocal 1.9.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # serial 48 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) # ----------------------------------------------------------- # If this macro is not defined by Autoconf, define it here. m4_ifdef([AC_PROVIDE_IFELSE], [], [m4_define([AC_PROVIDE_IFELSE], [m4_ifdef([AC_PROVIDE_$1], [$2], [$3])])]) # AC_PROG_LIBTOOL # --------------- AC_DEFUN([AC_PROG_LIBTOOL], [AC_REQUIRE([_AC_PROG_LIBTOOL])dnl dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. AC_PROVIDE_IFELSE([AC_PROG_CXX], [AC_LIBTOOL_CXX], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX ])]) dnl And a similar setup for Fortran 77 support AC_PROVIDE_IFELSE([AC_PROG_F77], [AC_LIBTOOL_F77], [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 ])]) dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [ifdef([AC_PROG_GCJ], [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([A][M_PROG_GCJ], [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([LT_AC_PROG_GCJ], [define([LT_AC_PROG_GCJ], defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) ])])# AC_PROG_LIBTOOL # _AC_PROG_LIBTOOL # ---------------- AC_DEFUN([_AC_PROG_LIBTOOL], [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl # Prevent multiple expansion define([AC_PROG_LIBTOOL], []) ])# _AC_PROG_LIBTOOL # AC_LIBTOOL_SETUP # ---------------- AC_DEFUN([AC_LIBTOOL_SETUP], [AC_PREREQ(2.50)dnl AC_REQUIRE([AC_ENABLE_SHARED])dnl AC_REQUIRE([AC_ENABLE_STATIC])dnl AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_LD])dnl AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([AC_PROG_LN_S])dnl AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl AC_LIBTOOL_SYS_MAX_CMD_LEN AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE AC_LIBTOOL_OBJDIR AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' [sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] # Same as above, but do not quote variable references. [double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" AC_CHECK_TOOL(AR, ar, false) AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then AC_PATH_MAGIC fi ;; esac AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes AC_ARG_WITH([pic], [AC_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= AC_LIBTOOL_LANG_C_CONFIG _LT_AC_TAGCONFIG ])# AC_LIBTOOL_SETUP # _LT_AC_SYS_COMPILER # ------------------- AC_DEFUN([_LT_AC_SYS_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_AC_SYS_COMPILER # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. AC_DEFUN([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. AC_DEFUN([_LT_COMPILER_BOILERPLATE], [ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. AC_DEFUN([_LT_LINKER_BOILERPLATE], [ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* ])# _LT_LINKER_BOILERPLATE # _LT_AC_SYS_LIBPATH_AIX # ---------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], [AC_LINK_IFELSE(AC_LANG_PROGRAM,[ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_AC_SYS_LIBPATH_AIX # _LT_AC_SHELL_INIT(ARG) # ---------------------- AC_DEFUN([_LT_AC_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_AC_SHELL_INIT # _LT_AC_PROG_ECHO_BACKSLASH # -------------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], [_LT_AC_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac echo=${ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat <<EOF [$]* EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string=`eval $cmd`) 2>/dev/null && echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(ECHO) ])])# _LT_AC_PROG_ECHO_BACKSLASH # _LT_AC_LOCK # ----------- AC_DEFUN([_LT_AC_LOCK], [AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) LD="${LD-ld} -64" ;; esac ;; esac fi rm -rf conftest* ;; AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; ]) esac need_locks="$enable_libtool_lock" ])# _LT_AC_LOCK # AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [AC_REQUIRE([LT_AC_PROG_SED]) AC_CACHE_CHECK([$1], [$2], [$2=no ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $rm conftest* ]) if test x"[$]$2" = xyes; then ifelse([$5], , :, [$5]) else ifelse([$6], , :, [$6]) fi ])# AC_LIBTOOL_COMPILER_OPTION # AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ------------------------------------------------------------ # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then ifelse([$4], , :, [$4]) else ifelse([$5], , :, [$5]) fi ])# AC_LIBTOOL_LINKER_OPTION # AC_LIBTOOL_SYS_MAX_CMD_LEN # -------------------------- AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [# find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done teststring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi ])# AC_LIBTOOL_SYS_MAX_CMD_LEN # _LT_AC_CHECK_DLFCN # ------------------ AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h)dnl ])# _LT_AC_CHECK_DLFCN # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # --------------------------------------------------------------------- AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF [#line __oline__ "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_AC_TRY_DLOPEN_SELF # AC_LIBTOOL_DLOPEN_SELF # ---------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ])# AC_LIBTOOL_DLOPEN_SELF # AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) # --------------------------------- # Check to see if options -c and -o are simultaneously supported by compiler AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* ]) ])# AC_LIBTOOL_PROG_CC_C_O # AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) # ----------------------------------------- # Check to see if we can do hard links to lock some files if needed AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_REQUIRE([_LT_AC_LOCK])dnl hard_links="nottested" if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi ])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS # AC_LIBTOOL_OBJDIR # ----------------- AC_DEFUN([AC_LIBTOOL_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir ])# AC_LIBTOOL_OBJDIR # AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) # ---------------------------------------------- # Check hardcoding attributes. AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_AC_TAGVAR(hardcode_action, $1)= if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existant directories. if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_AC_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_AC_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_AC_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi ])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH # AC_LIBTOOL_SYS_LIB_STRIP # ------------------------ AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], [striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi ])# AC_LIBTOOL_SYS_LIB_STRIP # AC_LIBTOOL_SYS_DYNAMIC_LINKER # ----------------------------- # PORTME Fill in your ld.so characteristics AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # find out which ABI we are using libsuff= case "$host_cpu" in x86_64*|s390x*|powerpc64*) echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; esac fi rm -rf conftest* ;; esac # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi ])# AC_LIBTOOL_SYS_DYNAMIC_LINKER # _LT_AC_TAGCONFIG # ---------------- AC_DEFUN([_LT_AC_TAGCONFIG], [AC_ARG_WITH([tags], [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], [include additional configurations @<:@automatic@:>@])], [tagnames="$withval"]) if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then AC_MSG_WARN([output file `$ofile' does not exist]) fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) else AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) fi fi if test -z "$LTCFLAGS"; then eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in "") ;; *) AC_MSG_ERROR([invalid tag name: $tagname]) ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then AC_MSG_ERROR([tag name \"$tagname\" already exists]) fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_LIBTOOL_LANG_CXX_CONFIG else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then AC_LIBTOOL_LANG_F77_CONFIG else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then AC_LIBTOOL_LANG_GCJ_CONFIG else tagname="" fi ;; RC) AC_LIBTOOL_LANG_RC_CONFIG ;; *) AC_MSG_ERROR([Unsupported tag name: $tagname]) ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" AC_MSG_ERROR([unable to update list of available tagged configurations.]) fi fi ])# _LT_AC_TAGCONFIG # AC_LIBTOOL_DLOPEN # ----------------- # enable checks for dlopen support AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_DLOPEN # AC_LIBTOOL_WIN32_DLL # -------------------- # declare package support for building win32 DLLs AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_WIN32_DLL # AC_ENABLE_SHARED([DEFAULT]) # --------------------------- # implement the --enable-shared flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([shared], [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]AC_ENABLE_SHARED_DEFAULT) ])# AC_ENABLE_SHARED # AC_DISABLE_SHARED # ----------------- # set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no) ])# AC_DISABLE_SHARED # AC_ENABLE_STATIC([DEFAULT]) # --------------------------- # implement the --enable-static flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([static], [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]AC_ENABLE_STATIC_DEFAULT) ])# AC_ENABLE_STATIC # AC_DISABLE_STATIC # ----------------- # set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no) ])# AC_DISABLE_STATIC # AC_ENABLE_FAST_INSTALL([DEFAULT]) # --------------------------------- # implement the --enable-fast-install flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([fast-install], [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) ])# AC_ENABLE_FAST_INSTALL # AC_DISABLE_FAST_INSTALL # ----------------------- # set the default to --disable-fast-install AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_FAST_INSTALL(no) ])# AC_DISABLE_FAST_INSTALL # AC_LIBTOOL_PICMODE([MODE]) # -------------------------- # implement the --with-pic flag # MODE is either `yes' or `no'. If omitted, it defaults to `both'. AC_DEFUN([AC_LIBTOOL_PICMODE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl pic_mode=ifelse($#,1,$1,default) ])# AC_LIBTOOL_PICMODE # AC_PROG_EGREP # ------------- # This is predefined starting with Autoconf 2.54, so this conditional # definition can be removed once we require Autoconf 2.54 or later. m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], [AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi]) EGREP=$ac_cv_prog_egrep AC_SUBST([EGREP]) ])]) # AC_PATH_TOOL_PREFIX # ------------------- # find a file program which can recognise shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="ifelse([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi ])# AC_PATH_TOOL_PREFIX # AC_PATH_MAGIC # ------------- # find a file program which can recognise a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# AC_PATH_MAGIC # AC_PROG_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH([gnu-ld], [AC_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no]) AC_REQUIRE([LT_AC_PROG_SED])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$lt_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_PROG_LD_GNU ])# AC_PROG_LD # AC_PROG_LD_GNU # -------------- AC_DEFUN([AC_PROG_LD_GNU], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac]) with_gnu_ld=$lt_cv_prog_gnu_ld ])# AC_PROG_LD_GNU # AC_PROG_LD_RELOAD_FLAG # ---------------------- # find reload flag for linker # -- PORTME Some linkers may need a different reload flag. AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], [AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag, [lt_cv_ld_reload_flag='-r']) reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac ])# AC_PROG_LD_RELOAD_FLAG # AC_DEPLIBS_CHECK_METHOD # ----------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], [AC_CACHE_CHECK([how to recognise dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump'. lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | kfreebsd*-gnu | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix3*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown ])# AC_DEPLIBS_CHECK_METHOD # AC_PROG_NM # ---------- # find the pathname to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" ])# AC_PROG_NM # AC_CHECK_LIBM # ------------- # check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac ])# AC_CHECK_LIBM # AC_LIBLTDL_CONVENIENCE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl convenience library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-convenience to the configure arguments. Note that # AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, # it is assumed to be `libltdl'. LIBLTDL will be prefixed with # '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' # (note the single quotes!). If your package is not flat and you're not # using automake, define top_builddir and top_srcdir appropriately in # the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_CONVENIENCE # AC_LIBLTDL_INSTALLABLE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl installable library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-install to the configure arguments. Note that # AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, # and an installed libltdl is not found, it is assumed to be `libltdl'. # LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and top_srcdir # appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, lt_dlinit, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_INSTALLABLE # AC_LIBTOOL_CXX # -------------- # enable support for C++ libraries AC_DEFUN([AC_LIBTOOL_CXX], [AC_REQUIRE([_LT_AC_LANG_CXX]) ])# AC_LIBTOOL_CXX # _LT_AC_LANG_CXX # --------------- AC_DEFUN([_LT_AC_LANG_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) ])# _LT_AC_LANG_CXX # _LT_AC_PROG_CXXCPP # ------------------ AC_DEFUN([_LT_AC_PROG_CXXCPP], [ AC_REQUIRE([AC_PROG_CXX]) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP fi ])# _LT_AC_PROG_CXXCPP # AC_LIBTOOL_F77 # -------------- # enable support for Fortran 77 libraries AC_DEFUN([AC_LIBTOOL_F77], [AC_REQUIRE([_LT_AC_LANG_F77]) ])# AC_LIBTOOL_F77 # _LT_AC_LANG_F77 # --------------- AC_DEFUN([_LT_AC_LANG_F77], [AC_REQUIRE([AC_PROG_F77]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) ])# _LT_AC_LANG_F77 # AC_LIBTOOL_GCJ # -------------- # enable support for GCJ libraries AC_DEFUN([AC_LIBTOOL_GCJ], [AC_REQUIRE([_LT_AC_LANG_GCJ]) ])# AC_LIBTOOL_GCJ # _LT_AC_LANG_GCJ # --------------- AC_DEFUN([_LT_AC_LANG_GCJ], [AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) ])# _LT_AC_LANG_GCJ # AC_LIBTOOL_RC # ------------- # enable support for Windows resource files AC_DEFUN([AC_LIBTOOL_RC], [AC_REQUIRE([LT_AC_PROG_RC]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) ])# AC_LIBTOOL_RC # AC_LIBTOOL_LANG_C_CONFIG # ------------------------ # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) AC_DEFUN([_LT_AC_LANG_C_CONFIG], [lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_C_CONFIG # AC_LIBTOOL_LANG_CXX_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], [AC_LANG_PUSH(C++) AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Dependencies to place before and after the object being linked: _LT_AC_TAGVAR(predep_objects, $1)= _LT_AC_TAGVAR(postdep_objects, $1)= _LT_AC_TAGVAR(predeps, $1)= _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration AC_PROG_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_AC_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes ; then lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before switch to ELF _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' ;; *) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix3*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; linux*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc*) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC*) # Portland Group C++ compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; openbsd2*) # C++ shared libraries are fairly broken _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd='echo' ;; osf3*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. We must also pass each convience library through # to the system linker between allextract/defaultextract. # The C++ compiler will combine linker options so we # cannot just pass the convience library names through # without $wl. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. # So that behaviour is only enabled if SCOABSPATH is set to a # non-empty value in the environment. Most likely only useful for # creating official distributions of packages. # This is a hack until libtool officially supports absolute path # names for shared libraries. _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_AC_TAGVAR(GCC, $1)="$GXX" _LT_AC_TAGVAR(LD, $1)="$LD" AC_LIBTOOL_POSTDEP_PREDEP($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld ])# AC_LIBTOOL_LANG_CXX_CONFIG # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) # ------------------------------------ # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... ifelse([$1],[],[cat > conftest.$ac_ext <<EOF int a; void foo (void) { a = 0; } EOF ],[$1],[CXX],[cat > conftest.$ac_ext <<EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; EOF ],[$1],[F77],[cat > conftest.$ac_ext <<EOF subroutine foo implicit none integer*4 a a=0 return end EOF ],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF public class foo { private int a; public void bar (void) { a = 0; } }; EOF ]) dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then _LT_AC_TAGVAR(predep_objects, $1)="$p" else _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then _LT_AC_TAGVAR(postdep_objects, $1)="$p" else _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $rm -f confest.$objext # PORTME: override above test on systems where it is broken ifelse([$1],[CXX], [case $host_os in interix3*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_AC_TAGVAR(predep_objects,$1)= _LT_AC_TAGVAR(postdep_objects,$1)= _LT_AC_TAGVAR(postdeps,$1)= ;; solaris*) case $cc_basename in CC*) # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun' ;; esac ;; esac ]) case " $_LT_AC_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac ])# AC_LIBTOOL_POSTDEP_PREDEP # AC_LIBTOOL_LANG_F77_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) AC_DEFUN([_LT_AC_LANG_F77_CONFIG], [AC_REQUIRE([AC_PROG_F77]) AC_LANG_PUSH(Fortran 77) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code=" subroutine t\n return\n end\n" # Code to be used in simple link tests lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_AC_TAGVAR(GCC, $1)="$G77" _LT_AC_TAGVAR(LD, $1)="$LD" AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_F77_CONFIG # AC_LIBTOOL_LANG_GCJ_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], [AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_RESTORE CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_GCJ_CONFIG # AC_LIBTOOL_LANG_RC_CONFIG # ------------------------- # Ensure that the configuration vars for the Windows resource compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) AC_DEFUN([_LT_AC_LANG_RC_CONFIG], [AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes AC_LIBTOOL_CONFIG($1) AC_LANG_RESTORE CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_RC_CONFIG # AC_LIBTOOL_CONFIG([TAGNAME]) # ---------------------------- # If TAGNAME is not passed, then create an initial libtool script # with a default configuration from the untagged config vars. Otherwise # add code to config.status for appending the configuration named by # TAGNAME from the matching tagged config vars. AC_DEFUN([AC_LIBTOOL_CONFIG], [# The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ _LT_AC_TAGVAR(compiler, $1) \ _LT_AC_TAGVAR(CC, $1) \ _LT_AC_TAGVAR(LD, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ _LT_AC_TAGVAR(old_archive_cmds, $1) \ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ _LT_AC_TAGVAR(predep_objects, $1) \ _LT_AC_TAGVAR(postdep_objects, $1) \ _LT_AC_TAGVAR(predeps, $1) \ _LT_AC_TAGVAR(postdeps, $1) \ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ _LT_AC_TAGVAR(archive_cmds, $1) \ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ _LT_AC_TAGVAR(postinstall_cmds, $1) \ _LT_AC_TAGVAR(postuninstall_cmds, $1) \ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ _LT_AC_TAGVAR(allow_undefined_flag, $1) \ _LT_AC_TAGVAR(no_undefined_flag, $1) \ _LT_AC_TAGVAR(export_symbols_cmds, $1) \ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ _LT_AC_TAGVAR(hardcode_automatic, $1) \ _LT_AC_TAGVAR(module_cmds, $1) \ _LT_AC_TAGVAR(module_expsym_cmds, $1) \ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ _LT_AC_TAGVAR(exclude_expsyms, $1) \ _LT_AC_TAGVAR(include_expsyms, $1); do case $var in _LT_AC_TAGVAR(old_archive_cmds, $1) | \ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ _LT_AC_TAGVAR(archive_cmds, $1) | \ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ _LT_AC_TAGVAR(module_cmds, $1) | \ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\[$]0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` ;; esac ifelse([$1], [], [cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" AC_MSG_NOTICE([creating $ofile])], [cfgfile="$ofile"]) cat <<__EOF__ >> "$cfgfile" ifelse([$1], [], [#! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG], [# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) # Is the compiler the GNU C compiler? with_gcc=$_LT_AC_TAGVAR(GCC, $1) gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_[]_LT_AC_TAGVAR(LD, $1) # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) # Commands used to build and install a shared archive. archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_[]_LT_AC_TAGVAR(predep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_[]_LT_AC_TAGVAR(postdep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) # Flag that forces no undefined symbols. no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" # Set to yes if exported symbols are required. always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) # The commands to list exported symbols. export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) # Symbols that must always be exported. include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) ifelse([$1],[], [# ### END LIBTOOL CONFIG], [# ### END LIBTOOL TAG CONFIG: $tagname]) __EOF__ ifelse([$1],[], [ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ]) else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ])# AC_LIBTOOL_CONFIG # AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi ])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; linux*) if test "$host_cpu" = ia64; then symcode='[[ABCDGIRSTW]]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat <<EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <<EOF >> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[[]] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) # --------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], [_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) ifelse([$1],[CXX],[ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; icpc* | ecpc*) # Intel C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC*) # Portland Group C++ compiler. _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; vxworks*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; newsos6) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" ;; esac # # Check to make sure the static flag actually works. # wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) ]) # AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) # ------------------------------------ # See if the linker supports building shared libraries. AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ],[ runpath_var= _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)= _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_AC_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. _LT_CC_BASENAME([$compiler]) case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_AC_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <<EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; interix3*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <<EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=yes _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # see comment about different semantics on the GNU ld section _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; bsdi[[45]]*) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ;; dgux*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; openbsd*) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi ;; os2*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' if test "$GCC" = yes; then wlarc='${wl}' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; *) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_AC_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_AC_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_AC_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) _LT_AC_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac ])# AC_LIBTOOL_PROG_LD_SHLIBS # _LT_AC_FILE_LTDLL_C # ------------------- # Be careful that the start marker always follows a newline. AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include <windows.h> # #undef WIN32_LEAN_AND_MEAN # #include <stdio.h> # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include <cygwin/cygwin_dll.h> # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ ])# _LT_AC_FILE_LTDLL_C # _LT_AC_TAGVAR(VARNAME, [TAGNAME]) # --------------------------------- AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) AC_DEFUN([LT_AC_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj, no) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS) ]) AC_DEFUN([LT_AC_PROG_RC], [AC_CHECK_TOOL(RC, windres, no) ]) # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # # LT_AC_PROG_SED # -------------- # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. AC_DEFUN([LT_AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ]) m4_include([acinclude.m4]) ================================================ FILE: vm/src/from_squeak/unix/config/bin.squeak.sh.in ================================================ #!/bin/sh BIN=`/usr/bin/dirname $0`/../@expanded_relative_imgdir@ # At least on linux LD_LIBRARY_PATH's components must be absolute path names case "$BIN" in /*) PLUGINS="$BIN";; *) PLUGINS="`pwd`/$BIN" esac # prepending is less flexible but safer because it ensures we find the plugins # in the same directory as the VM. LD_LIBRARY_PATH=$PLUGINS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} exec "$BIN/squeak" "$@" ================================================ FILE: vm/src/from_squeak/unix/config/build ================================================ #!/bin/bash # This script is really intended for "batch-mode" nightly builds of # Squeak binary distributions. It is therefore intended mainly for # the VM maintainer (who runs it from cron) rather than VM hackers in # general (who would probably prefer to run it from the command line). # Nevertheless it does attempt to be interactive (and even makes some # concessions towards user-friendliness ;) for those who cannot be # bothered to type `mkdir bld; cd bld; ../.../configure; make') -- but # your kilometrage may vary (enormously). # # Run `build -h' for a list of options (without much explanation). # Last edited: 2002-06-07 06:12:13 by piumarta on emilia.inria.fr UTS_SYS=`(uname -s) 2>/dev/null` if [ -x /usr/5bin/echo ]; then # SunOS SysV echo echo=/usr/5bin/echo elif [ -z "`(echo -e a) 2>/dev/null | fgrep e`" ]; then # GNU bash, etc. echo="echo -e" else # generic SysV echo=echo fi if [ "${UTS_SYS}" = QNX ]; then echo=echo fi ouch () { $echo $echo 'Ouch! That hurts!!' exit 1 } trap ouch 2 srcdir="" blddir="" batch="" doConfig=yes doMake=tes getYN() { if [ "${batch}" ]; then YN="y" else YN="" while [ ! "${YN}" ]; do read YN case ${YN} in y|Y|n|N) ;; *) $echo "Did you mean Y or N ? \c" >&2; YN="" ;; esac done fi $echo ${YN} } getN () { N=0 while [ ${N} -eq 0 ]; do read n let n="${n}" if [ "${n}" -a \( ${n} -gt 0 \) -a \( ${n} -le ${1} \) ]; then N=${n} else $echo "Please answer a number in the range [1-${1}]: \c" fi done $echo ${N} } usage () { $echo "usage: ${0} [-c] [-h] [-m] [-y] [-s srcdir] [-b blddir]" >&2 } help () { usage cat >&2 <<\EOF -b dir build in `dir' -c run `configure' only (don't make) -h show this help message -m run `make' only (don't configure) -s dir VMMaker sources are in `dir' -y assume `y' to all questions and work silently (`batch' mode) EOF exit 0 } notFound () { $echo "VMMaker src directory not found" >&2 exit 1 } while [ $# -gt 0 ]; do case $1 in -b) shift; blddir="${1}"; shift;; -c) shift; doMake="";; -h) help;; -m) shift; doConfig="";; -s) shift; srcdir="${1}"; shift;; -y) shift; batch=yes;; *) usage; exit 1;; esac done [ $# -gt 0 ] && usage && exit 1 if [ "${srcdir}" ]; then srcdirs="${srcdir}" else srcdirs=`$echo src*` fi [ ! "${srcdirs}" ] && notFound count=0; for d in ${srcdirs}; do [ -d ${d} ] && let count="${count}+1" done chooseDir () { $echo "We found the following source directories:" i=0 for d in ${srcdirs}; do let i="${i}+1" list="${list} [${i}] ${d} " done $echo $echo "${list}" if [ "${batch}" ]; then $echo "batch mode failed!" >&2 exit 1 fi $echo "Which would you like to use [1-${i}]? \c" n=`getN ${count}` srcdir=`$echo "${list}" | fgrep "[$n]" | sed "s,^\[.*\] ,,"` [ "${srcdir}" ] || notFound } case ${count} in 0) notFound ;; 1) srcdir=${srcdirs} ;; *) chooseDir ;; esac $echo "Using source directory: ${srcdir}" if [ ! "${blddir}" ]; then vers=`$echo ${srcdir} | sed 's,^src,,'` mach=`uname -m | sed 's,i.86,i386,;s,sun4.,sparc,'` blddir="bld${vers}-${mach}" fi $echo "Using build directory: ${blddir}" if [ ! "${batch}" ]; then $echo "Is this okay [y/n]? \c" case `getYN` in y|Y) ;; n|N) $echo "Goodybye" >&2; exit 1 ;; *) $echo "Huh?" >&2; exit 1 ;; esac fi [ -d ${blddir} ] || mkdir ${blddir} cd ${blddir} if [ "${doConfig}" ]; then $echo $echo '-------------------------------------------------------------------------------' $echo "Configuring in ${PWD}" $echo '-------------------------------------------------------------------------------' $echo ../platforms/unix/config/configure --with-src=${srcdir} || exit 1 fi if [ "${doMake}" ]; then $echo $echo '-------------------------------------------------------------------------------' $echo "Building in ${PWD}" $echo '-------------------------------------------------------------------------------' $echo make || exit 1 fi $echo $echo '-------------------------------------------------------------------------------' if [ ! -x squeak ]; then $echo "The build appears to have failed. We can't really continue." >&2 $echo "Goodbye." >&2 exit 1 fi $echo "The build appears to have succeeded." [ "${batch}" ] && exit 0 if [ "`whoami`" != "root" ]; then $echo "We cannot install Squeak because you are not root" >&2 exit 0 fi $echo "Would you like me to install Squeak in the default location [y/n]? \c" case `getYN` in y|Y) ;; n|N) $echo "Less work for us that way."; exit 0 ;; *) $echo "Huh?"; exit 1 ;; esac $echo make install $echo $echo "We're done. Happy Squeaking!" ================================================ FILE: vm/src/from_squeak/unix/config/config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-10-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner <per@bothner.com>. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # This shell variable is my proudest work .. or something. --bje set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; (old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; dummy=$tmpdir/dummy ; files="$dummy.c $dummy.o $dummy.rel $dummy" ; trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $files ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; unset files' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. eval $set_cc_for_build cat <<EOF >$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null if test "$?" = 0 ; then case `$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; 3-1307) UNAME_MACHINE="alphaev7" ;; esac fi rm -f $dummy.s $dummy && rmdir $tmpdir echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <sys/systemcfg.h> main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include <stdlib.h> #include <unistd.h> int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy && rmdir $tmpdir fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <unistd.h> int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <features.h> #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c && rmdir $tmpdir test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <features.h> #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says <Richard.M.Bartel@ccMail.Census.GOV> echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes <hewes@openmarket.com>. # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c <<EOF #ifdef _SEQUENT_ # include <sys/types.h> # include <sys/utsname.h> #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include <sys/param.h> printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include <sys/param.h> # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 <<EOF $0: unable to guess system type This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from ftp://ftp.gnu.org/pub/gnu/config/ If the version you run ($0) is already up to date, please send the following data and any information you think might be pertinent to <config-patches@gnu.org> in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: vm/src/from_squeak/unix/config/config.h.in ================================================ /* config.h.in -- template for config.h -*- C -*- * * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Ian.Piumarta@squeakland.org * * Last edited: 2006-04-23 12:34:41 by piumarta on emilia.local */ #ifndef __sq_config_h #define __sq_config_h /* explicit image width */ #undef HAVE_INTERP_H /* package options */ #undef USE_X11 #undef USE_X11_GLX #undef USE_QUARTZ #undef USE_QUARTZ_CGL #undef USE_RFB /* libraries */ #undef HAVE_LIBX11 #undef HAVE_LIBXEXT #undef HAVE_LIBDL #undef HAVE_DYLD #undef HAVE_LIBFFI #undef HAVE_ICONV #undef USE_AUDIO_NONE #undef USE_AUDIO_SUN #undef USE_AUDIO_NAS #undef USE_AUDIO_OSS #undef USE_AUDIO_MACOSX #undef OSS_DEVICE /* header files */ #undef HAVE_UNISTD_H #undef NEED_GETHOSTNAME_P #undef HAVE_DIRENT_H #undef HAVE_SYS_NDIR_H #undef HAVE_SYS_DIR_H #undef HAVE_NDIR_H #undef HAVE_DLFCN_H #undef HAVE_ICONV_H #undef HAVE_SYS_TIME_H #undef TIME_WITH_SYS_TIME #undef HAVE_SYS_FILIO_H #undef HAVE_SYS_AUDIOIO_H #undef HAVE_SUN_AUDIOIO_H #undef HAVE_PTY_H #undef HAVE_UTIL_H #undef HAVE_LIBUTIL_H #undef HAVE_STROPTS_H #undef HAVE_GL_GL_H #undef HAVE_OPENGL_GL_H #undef NEED_SUNOS_H /* system calls/library functions */ #undef AT_EXIT #undef HAVE_TZSET #undef HAVE_OPENPTY #undef HAVE_UNIX98_PTYS #undef HAVE_SNPRINTF #undef HAVE___SNPRINTF #undef HAVE_MMAP #undef HAVE_DYLD #undef HAVE_LANGINFO_CODESET #undef HAVE_ALLOCA #undef HAVE_ALLOCA_H #undef HAVE_UNSETENV #undef HAVE_NANOSLEEP /* widths of primitive types */ #undef SIZEOF_INT #undef SIZEOF_LONG #undef SIZEOF_LONG_LONG #undef SIZEOF_VOID_P /* structures */ #undef HAVE_TM_GMTOFF #undef HAVE_TIMEZONE /* typedefs */ #undef size_t #undef socklen_t #undef squeakInt64 /* architecture */ #undef OS_TYPE #undef VM_HOST #undef VM_HOST_CPU #undef VM_HOST_VENDOR #undef VM_HOST_OS #undef VM_BUILD_STRING #undef WORDS_BIGENDIAN #undef DOUBLE_WORD_ALIGNMENT /* damage containment */ #undef DARWIN #ifdef NEED_SUNOS_H # include "sunos.h" #endif /* other configured variables */ #undef SQ_VERSION #undef VM_VERSION #undef VM_MODULE_PREFIX #undef VM_DLSYM_PREFIX #undef VM_X11DIR /* avoid dependencies on glibc2.3 */ #undef HAVE_FEATURES_H #if defined(HAVE_FEATURES_H) # include "glibc.h" #endif #endif /* __sq_config_h */ ================================================ FILE: vm/src/from_squeak/unix/config/config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-09-05' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39 | mipstx39el \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic4x | c4x*) basic_machine=tic4x-unknown os=-coff ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: vm/src/from_squeak/unix/config/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<EOF $* EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string=`eval $cmd`) 2>/dev/null && echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi tagnames=${tagnames+${tagnames},}CXX tagnames=${tagnames+${tagnames},}F77 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="config.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #if HAVE_SYS_TYPES_H # include <sys/types.h> #endif #if HAVE_SYS_STAT_H # include <sys/stat.h> #endif #if STDC_HEADERS # include <stdlib.h> # include <stddef.h> #else # if HAVE_STDLIB_H # include <stdlib.h> # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include <memory.h> # endif # include <string.h> #endif #if HAVE_STRINGS_H # include <strings.h> #endif #if HAVE_INTTYPES_H # include <inttypes.h> #else # if HAVE_STDINT_H # include <stdint.h> # endif #endif #if HAVE_UNISTD_H # include <unistd.h> #endif" ac_subst_vars='NM LD SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS topdir cfgdir vmmdir vmmcfg blddir SQ_MAJOR SQ_MINOR SQ_UPDATE SQ_VERSION VM_MAJOR VM_MINOR VM_RELEASE VM_VERSION imgdir expanded_relative_imgdir plgdir build build_cpu build_vendor build_os host host_cpu host_vendor host_os SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT WFLAGS AS RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN CPP EGREP SED LN_S ECHO AR ac_ct_AR STRIP ac_ct_STRIP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INCLUDES HAVE_INTERP_H ALLOCA INTERP AWK VM_APP_ICONS npsqueak install_nps uninstall_nps SQ_LIBDIR int_modules ext_modules HAVE_LANGINFO_CODESET HAVE_NANOSLEEP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS X_CPPFLAGS X_INCLUDES LIBM_CFLAGS LIB_UUID int_plugins ext_plugins LIBOBJS LTLIBOBJS' ac_subst_files='make_cfg make_int make_ext make_prg Makefile_install Makefile_dist Makefile_rpm Makefile_deb' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX ac_cv_env_CXX_set=${CXX+set} ac_cv_env_CXX_value=$CXX ac_env_CXXFLAGS_set=${CXXFLAGS+set} ac_env_CXXFLAGS_value=$CXXFLAGS ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} ac_cv_env_CXXFLAGS_value=$CXXFLAGS ac_env_CXXCPP_set=${CXXCPP+set} ac_env_CXXCPP_value=$CXXCPP ac_cv_env_CXXCPP_set=${CXXCPP+set} ac_cv_env_CXXCPP_value=$CXXCPP ac_env_F77_set=${F77+set} ac_env_F77_value=$F77 ac_cv_env_F77_set=${F77+set} ac_cv_env_F77_value=$F77 ac_env_FFLAGS_set=${FFLAGS+set} ac_env_FFLAGS_value=$FFLAGS ac_cv_env_FFLAGS_set=${FFLAGS+set} ac_cv_env_FFLAGS_value=$FFLAGS # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-iconv disable iconv support default=enabled --enable-mpg-mmx enable MMX support in Mpeg3Plugin default=no --enable-mpg-pthreads enable pthread support in Mpeg3Plugin default=no Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-src=dir generated src directory default=src --with-vmmcfg=dir vm configuration directory containing plugins.int and plugins.ext default=. --with-gnu-awk assume that awk is GNU gawk default=no --with-gnu-as assume that as is the GNU assembler default=no --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] --without-rfb disable Remote FrameBuffer support default=enabled --without-npsqueak disable browser plugin support default=enabled --with-custom-display enable custom window support default=disabled --without-quartz disable MacOSX Window System support default=enabled --without-x disable X Window System support default=enabled --without-gl disable OpenGL support default=enabled --with-x use the X Window System --with-custom-sound enable custom sound support default=disabled --without-vm-sound-OSS disable OSS vm sound support default=enabled --without-vm-display-fbdev disable frame buffer vm display support default=enabled Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu VM_MAJOR=3 VM_MINOR=9 VM_RELEASE=7 SQ_MAJOR=3 SQ_MINOR=9a SQ_UPDATE=7024 topdir=`cd ${srcdir}/../../..; pwd` cfgdir=`cd ${srcdir}; pwd` # Check whether --with-src or --without-src was given. if test "${with_src+set}" = set; then withval="$with_src" vmmsrc="${with_src}" else vmmsrc="src" fi; vmmdir="${topdir}/${vmmsrc}" if test ! -d "${topdir}/${vmmsrc}"; then if test -d "${topdir}/platforms/unix/${vmmsrc}"; then vmmdir="${topdir}/platforms/unix/${vmmsrc}" echo "$as_me:$LINENO: result: using built-in src directory" >&5 echo "${ECHO_T}using built-in src directory" >&6 fi fi echo "$as_me:$LINENO: result: ${vmmdir}" >&5 echo "${ECHO_T}${vmmdir}" >&6 blddir=`pwd` # Check whether --with-vmmcfg or --without-vmmcfg was given. if test "${with_vmmcfg+set}" = set; then withval="$with_vmmcfg" vmmcfg="${with-vmmcfg}" else vmmcfg="${blddir}" fi; # Check the generated src dir looks sane echo "$as_me:$LINENO: checking sanity of generated src directory" >&5 echo $ECHO_N "checking sanity of generated src directory... $ECHO_C" >&6 vmmcheck () { if test ! ${2} ${3}; then echo "$as_me:$LINENO: result: bad" >&5 echo "${ECHO_T}bad" >&6 echo "missing ${1}: ${3}" exit 1 fi } vmmcheck dir -d ${vmmcfg} vmmcheck file -f ${vmmcfg}/plugins.int vmmcheck file -f ${vmmcfg}/plugins.ext vmmcheck dir -d ${vmmdir} vmmcheck dir -d ${vmmdir}/plugins vmmcheck dir -d ${vmmdir}/vm vmmcheck file -f ${vmmdir}/vm/cogit.c vmmcheck file -f ${vmmdir}/vm/cogit.h vmmcheck file -f ${vmmdir}/vm/cogmethod.h vmmcheck file -f ${vmmdir}/vm/cointerp.c vmmcheck file -f ${vmmdir}/vm/cointerp.h vmmcheck file -f ${vmmdir}/vm/gcc3x-cointerp.c echo "$as_me:$LINENO: result: okay" >&5 echo "${ECHO_T}okay" >&6 SQ_VERSION=${SQ_MAJOR}.${SQ_MINOR}-${SQ_UPDATE} cat >>confdefs.h <<_ACEOF #define SQ_VERSION "${SQ_VERSION}" _ACEOF VM_VERSION=${VM_MAJOR}.${VM_MINOR}-${VM_RELEASE} cat >>confdefs.h <<_ACEOF #define VM_VERSION "${VM_VERSION}" _ACEOF # libdir contains ${exec_prefix}, so we have to default and expand early test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' imgdir=`eval echo ${libdir}/squeak` expanded_relative_imgdir=`eval echo lib/squeak/${VM_VERSION}` plgdir='${imgdir}/'`eval echo ${VM_VERSION}` cat >>confdefs.h <<\_ACEOF #define OS_TYPE "unix" _ACEOF ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` host_cpu=`echo $host | sed 's,-.*,,'` host=`echo $host | sed 's,-unknown,,'` cat >>confdefs.h <<_ACEOF #define VM_HOST "$host" _ACEOF cat >>confdefs.h <<_ACEOF #define VM_HOST_OS "$host_os" _ACEOF cat >>confdefs.h <<_ACEOF #define VM_HOST_CPU "$host_cpu" _ACEOF echo echo "Configuring Squeak ${VM_VERSION} (${SQ_VERSION}) for ${host}" echo # Checks for programs. # Check whether --with-gnu-awk or --without-gnu-awk was given. if test "${with_gnu_awk+set}" = set; then withval="$with_gnu_awk" GAWK="$withval" else case $host_os in darwin*) GAWK="yes";; *) GAWK="unknown";; esac fi; # Check whether --with-gnu-as or --without-gnu-as was given. if test "${with_gnu_as+set}" = set; then withval="$with_gnu_as" GAS="$withval" else GAS="unknown" fi; echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 (eval $ac_compiler --version </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 (eval $ac_compiler -v </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 (eval $ac_compiler -V </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include <stdlib.h> int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu test "$GCC" = yes && WFLAGS="-Wall -Wno-unknown-pragmas" # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="as" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then echo "$as_me:$LINENO: result: $AS" >&5 echo "${ECHO_T}$AS" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi echo "$as_me:$LINENO: checking for GNU as" >&5 echo $ECHO_N "checking for GNU as... $ECHO_C" >&6 case "$GAS" in yes|no) ;; *) if test "$AS" = "as" && as -v /dev/null </dev/null 2>&1 | fgrep -i gnu >/dev/null then GAS=yes else GAS=no fi ;; esac echo "$as_me:$LINENO: result: $GAS" >&5 echo "${ECHO_T}$GAS" >&6 if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 if test "${lt_cv_path_NM+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 echo "${ECHO_T}$lt_cv_path_NM" >&6 NM="$lt_cv_path_NM" # Extract the first word of "ln", so it can be a program name with args. set dummy ln; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_LN+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$LN"; then ac_cv_prog_LN="$LN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LN="ln" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi LN=$ac_cv_prog_LN if test -n "$LN"; then echo "$as_me:$LINENO: result: $LN" >&5 echo "${ECHO_T}$LN" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Check size assumptions of basic data types echo "$as_me:$LINENO: checking \"size of int\"" >&5 echo $ECHO_N "checking \"size of int\"... $ECHO_C" >&6 if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> int main(){return(sizeof(int) == 4)?0:1;} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: \"okay\"" >&5 echo "${ECHO_T}\"okay\"" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) echo "$as_me:$LINENO: result: \"bad\"" >&5 echo "${ECHO_T}\"bad\"" >&6 { { echo "$as_me:$LINENO: error: \"one or more basic data types has an incompatible size: giving up\"" >&5 echo "$as_me: error: \"one or more basic data types has an incompatible size: giving up\"" >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: checking \"size of double\"" >&5 echo $ECHO_N "checking \"size of double\"... $ECHO_C" >&6 if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> int main(){return(sizeof(double) == 8)?0:1;} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: \"okay\"" >&5 echo "${ECHO_T}\"okay\"" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) echo "$as_me:$LINENO: result: \"bad\"" >&5 echo "${ECHO_T}\"bad\"" >&6 { { echo "$as_me:$LINENO: error: \"one or more basic data types has an incompatible size: giving up\"" >&5 echo "$as_me: error: \"one or more basic data types has an incompatible size: giving up\"" >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: checking for 64-bit integer type" >&5 echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6 if test "${ac_cv_int64_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main(){return(sizeof(long) == 8)?0:1;} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_int64_t="long" else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main(){return(sizeof(long long) == 8)?0:1;} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_int64_t="long long" else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_int64_t="no" fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_int64_t" >&5 echo "${ECHO_T}$ac_cv_int64_t" >&6 if test "$ac_cv_int64_t" = ""; then { { echo "$as_me:$LINENO: error: could not find a 64-bit integer type" >&5 echo "$as_me: error: could not find a 64-bit integer type" >&2;} { (exit 1); exit 1; }; } fi SQUEAK_INT64_T="$ac_cv_int64_t" cat >>confdefs.h <<_ACEOF #define squeakInt64 $ac_cv_int64_t _ACEOF ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <string.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ctype.h> #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6 if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((int *) 0) return 0; if (sizeof (int)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6 echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6 if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_int" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (int)); } unsigned long ulongval () { return (long) (sizeof (int)); } #include <stdio.h> #include <stdlib.h> int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (int))) < 0) { long i = longval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_int=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6 if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((long *) 0) return 0; if (sizeof (long)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6 echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6 if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_long" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (long)); } unsigned long ulongval () { return (long) (sizeof (long)); } #include <stdio.h> #include <stdlib.h> int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (long))) < 0) { long i = longval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_long=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF echo "$as_me:$LINENO: checking for long long" >&5 echo $ECHO_N "checking for long long... $ECHO_C" >&6 if test "${ac_cv_type_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((long long *) 0) return 0; if (sizeof (long long)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_long_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long_long=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 echo "${ECHO_T}$ac_cv_type_long_long" >&6 echo "$as_me:$LINENO: checking size of long long" >&5 echo $ECHO_N "checking size of long long... $ECHO_C" >&6 if test "${ac_cv_sizeof_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_long_long" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long_long=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (long long)); } unsigned long ulongval () { return (long) (sizeof (long long)); } #include <stdio.h> #include <stdlib.h> int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (long long))) < 0) { long i = longval (); if (i != ((long) (sizeof (long long)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (long long)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_long_long=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long _ACEOF echo "$as_me:$LINENO: checking for void *" >&5 echo $ECHO_N "checking for void *... $ECHO_C" >&6 if test "${ac_cv_type_void_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((void * *) 0) return 0; if (sizeof (void *)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_void_p=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_void_p=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5 echo "${ECHO_T}$ac_cv_type_void_p" >&6 echo "$as_me:$LINENO: checking size of void *" >&5 echo $ECHO_N "checking size of void *... $ECHO_C" >&6 if test "${ac_cv_sizeof_void_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_void_p" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_void_p=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (void *)); } unsigned long ulongval () { return (long) (sizeof (void *)); } #include <stdio.h> #include <stdlib.h> int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (void *))) < 0) { long i = longval (); if (i != ((long) (sizeof (void *)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (void *)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_void_p=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_void_p=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5 echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_VOID_P $ac_cv_sizeof_void_p _ACEOF # libtool configuration # Check whether --enable-static or --disable-static was given. if test "${enable_static+set}" = set; then enableval="$enable_static" p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi; # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi; # Check whether --enable-fast-install or --disable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval="$enable_fast_install" p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi; echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 if test "${lt_cv_path_SED+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done fi SED=$lt_cv_path_SED echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6 # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then echo "$as_me:$LINENO: result: $LD" >&5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac fi echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 with_gnu_ld=$lt_cv_prog_gnu_ld echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 if test "${lt_cv_ld_reload_flag+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_ld_reload_flag='-r' fi echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac echo "$as_me:$LINENO: checking whether ln -s works" >&5 echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no, using $LN_S" >&5 echo "${ECHO_T}no, using $LN_S" >&6 fi echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 if test "${lt_cv_deplibs_check_method+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump'. lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | kfreebsd*-gnu | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix3*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac fi echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" fi; test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5851 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 if test "${lt_cv_cc_needs_belf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then lt_cv_cc_needs_belf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) LD="${LD-ld} -64" ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CXX" && break done test -n "$ac_ct_CXX" || ac_ct_CXX="g++" CXX=$ac_ct_CXX fi # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 (eval $ac_compiler --version </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 (eval $ac_compiler -v </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 (eval $ac_compiler -V </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-g" echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include <stdlib.h> int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 if test -z "$CXXCPP"; then if test "${ac_cv_prog_CXXCPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi echo "$as_me:$LINENO: result: $CXXCPP" >&5 echo "${ECHO_T}$CXXCPP" >&6 ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu fi ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then echo "$as_me:$LINENO: result: $F77" >&5 echo "${ECHO_T}$F77" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_F77="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 echo "${ECHO_T}$ac_ct_F77" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_F77" && break done F77=$ac_ct_F77 fi # Provide some information about the compiler. echo "$as_me:6868:" \ "checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 (eval $ac_compiler --version </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 (eval $ac_compiler -v </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 (eval $ac_compiler -V </dev/null >&5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 if test "${ac_cv_f77_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_f77_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else FFLAGS=-g cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_f77_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_f77_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi G77=`test $ac_compiler_gnu = yes && echo yes` ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! # find the maximum length of command line arguments echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 if test "${lt_cv_sys_max_cmd_len+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done teststring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 else echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6 fi # Check for command to grab the raw symbol name followed by C symbol from nm. echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; linux*) if test "$host_cpu" = ia64; then symcode='[ABCDGIRSTW]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} EOF if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat <<EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <<EOF >> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then echo "$as_me:$LINENO: result: failed" >&5 echo "${ECHO_T}failed" >&6 else echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6 fi echo "$as_me:$LINENO: checking for objdir" >&5 echo $ECHO_N "checking for objdir... $ECHO_C" >&6 if test "${lt_cv_objdir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 echo "${ECHO_T}$lt_cv_objdir" >&6 objdir=$lt_cv_objdir case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 echo "${ECHO_T}$ac_ct_AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi AR=$ac_ct_AR else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo "$as_me:$LINENO: checking for file" >&5 echo $ECHO_N "checking for file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi else MAGIC_CMD=: fi fi fi ;; esac enable_dlopen=no enable_win32_dll=no # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" fi; test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Check whether --with-pic or --without-pic was given. if test "${with_pic+set}" = set; then withval="$with_pic" pic_mode="$withval" else pic_mode=default fi; test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7931: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7935: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic='-qnocommon' lt_prog_compiler_wl='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 echo "${ECHO_T}$lt_prog_compiler_pic" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8199: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8203: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 if test x"$lt_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works=yes fi else lt_prog_compiler_static_works=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 if test x"$lt_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8303: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:8307: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag= enable_shared_with_static_runtimes=no archive_cmds= archive_expsym_cmds= old_archive_From_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported link_all_deplibs=unknown hardcode_automatic=no module_cmds= module_expsym_cmds= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix3*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs=no ;; esac fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld='-rpath $libdir' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs" >&5 echo "${ECHO_T}$ld_shlibs" >&6 test "$ld_shlibs" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 echo "${ECHO_T}$archive_cmds_need_lc" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # find out which ABI we are using libsuff= case "$host_cpu" in x86_64*|s390x*|powerpc64*) echo '#line 9772 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; esac fi rm -rf conftest* ;; esac # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var" || \ test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action" >&5 echo "${ECHO_T}$hardcode_action" >&6 if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi ;; *) echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 if test "${ac_cv_func_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef shl_load /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else char (*f) () = shl_load; #endif #ifdef __cplusplus } #endif int main () { return f != shl_load; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6 if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); int main () { shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 if test "${ac_cv_func_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef dlopen /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else char (*f) () = dlopen; #endif #ifdef __cplusplus } #endif int main () { return f != dlopen; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6 if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dld_link (); int main () { dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF #line 10669 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6 if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF #line 10769 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Report which library types will actually be built echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6 echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6 echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler \ CC \ LD \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_prog_compiler_no_builtin_flag \ export_dynamic_flag_spec \ thread_safe_flag_spec \ whole_archive_flag_spec \ enable_shared_with_static_runtimes \ old_archive_cmds \ old_archive_from_new_cmds \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ archive_cmds \ archive_expsym_cmds \ postinstall_cmds \ postuninstall_cmds \ old_archive_from_expsyms_cmds \ allow_undefined_flag \ no_undefined_flag \ export_symbols_cmds \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ hardcode_automatic \ module_cmds \ module_expsym_cmds \ lt_cv_prog_compiler_c_o \ exclude_expsyms \ include_expsyms; do case $var in old_archive_cmds | \ old_archive_from_new_cmds | \ archive_cmds | \ archive_expsym_cmds | \ module_cmds | \ module_expsym_cmds | \ old_archive_from_expsyms_cmds | \ export_symbols_cmds | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" { echo "$as_me:$LINENO: creating $ofile" >&5 echo "$as_me: creating $ofile" >&6;} cat <<__EOF__ >> "$cfgfile" #! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_predep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_postdep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_compiler_lib_search_path | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" # Check whether --with-tags or --without-tags was given. if test "${with_tags+set}" = set; then withval="$with_tags" tagnames="$withval" fi; if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} else { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi if test -z "$LTCFLAGS"; then eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 echo "$as_me: error: invalid tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} { (exit 1); exit 1; }; } fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then echo "$as_me:$LINENO: result: $LD" >&5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac fi echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_CXX=yes else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='' link_all_deplibs_CXX=yes if test "$GXX" = yes ; then lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_CXX=no ;; esac fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_CXX='+b $libdir' ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix3*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; linux*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc*) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC*) # Portland Group C++ compiler archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd='echo' ;; osf3*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. We must also pass each convience library through # to the system linker between allextract/defaultextract. # The C++ compiler will combine linker options so we # cannot just pass the convience library names through # without $wl. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. # So that behaviour is only enabled if SCOABSPATH is set to a # non-empty value in the environment. Most likely only useful for # creating official distributions of packages. # This is a hack until libtool officially supports absolute path # names for shared libraries. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6 test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" cat > conftest.$ac_ext <<EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; EOF if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $rm -f confest.$objext # PORTME: override above test on systems where it is broken case $host_os in interix3*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; solaris*) case $cc_basename in CC*) # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. postdeps_CXX='-lCstd -lCrun' ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_CXX='-qnocommon' lt_prog_compiler_wl_CXX='-Wl,' ;; esac ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; icpc* | ecpc*) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC*) # Portland Group C++ compiler. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13112: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:13116: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_CXX=yes fi else lt_prog_compiler_static_works_CXX=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6 if test x"$lt_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_CXX=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13216: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:13220: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6 test "$ld_shlibs_CXX" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_CXX=no else archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # find out which ABI we are using libsuff= case "$host_cpu" in x86_64*|s390x*|powerpc64*) echo '#line 13752 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; esac fi rm -rf conftest* ;; esac # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ test -n "$runpath_var_CXX" || \ test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 echo "${ECHO_T}$hardcode_action_CXX" >&6 if test "$hardcode_action_CXX" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_CXX \ CC_CXX \ LD_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_static_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ export_dynamic_flag_spec_CXX \ thread_safe_flag_spec_CXX \ whole_archive_flag_spec_CXX \ enable_shared_with_static_runtimes_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ postuninstall_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ export_symbols_cmds_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ hardcode_automatic_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do case $var in old_archive_cmds_CXX | \ old_archive_from_new_cmds_CXX | \ archive_cmds_CXX | \ archive_expsym_cmds_CXX | \ module_cmds_CXX | \ module_expsym_cmds_CXX | \ old_archive_from_expsyms_cmds_CXX | \ export_symbols_cmds_CXX | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_CXX # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_CXX old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_predep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_postdep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_CXX # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_CXX # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_CXX" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # Code to be used in simple compile tests lt_simple_compile_test_code=" subroutine t\n return\n end\n" # Code to be used in simple link tests lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6 echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6 echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 GCC_F77="$G77" LD_F77="$LD" lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_F77='-qnocommon' lt_prog_compiler_wl_F77='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-fpic' lt_prog_compiler_static_F77='-Bstatic' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; solaris*) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_F77='-Qoption ld ';; *) lt_prog_compiler_wl_F77='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; unicos*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_can_build_shared_F77=no ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14810: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:14814: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 if test x"$lt_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_F77=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_F77=yes fi else lt_prog_compiler_static_works_F77=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6 if test x"$lt_prog_compiler_static_works_F77" = xyes; then : else lt_prog_compiler_static_F77= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_F77=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14914: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:14918: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag_F77= enable_shared_with_static_runtimes_F77=no archive_cmds_F77= archive_expsym_cmds_F77= old_archive_From_new_cmds_F77= old_archive_from_expsyms_cmds_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= thread_safe_flag_spec_F77= hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_direct_F77=no hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported link_all_deplibs_F77=unknown hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= always_export_symbols_F77=no export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <<EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_F77=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_F77=no fi ;; interix3*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_F77=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <<EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = no; then runpath_var= hardcode_libdir_flag_spec_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_F77=yes else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77='$convenience' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # see comment about different semantics on the GNU ld section ld_shlibs_F77=no ;; bsdi[45]*) export_dynamic_flag_spec_F77=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_F77=no hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='' link_all_deplibs_F77=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_F77=no ;; esac fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; *) hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: link_all_deplibs_F77=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; openbsd*) hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi hardcode_libdir_separator_F77=: ;; solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag_F77='${wl}-z,text' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_F77='${wl}-z,text' allow_undefined_flag_F77='${wl}-z,nodefs' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 echo "${ECHO_T}$ld_shlibs_F77" >&6 test "$ld_shlibs_F77" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 pic_flag=$lt_prog_compiler_pic_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # find out which ABI we are using libsuff= case "$host_cpu" in x86_64*|s390x*|powerpc64*) echo '#line 16363 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; esac fi rm -rf conftest* ;; esac # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ test -n "$runpath_var_F77" || \ test "X$hardcode_automatic_F77" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 echo "${ECHO_T}$hardcode_action_F77" >&6 if test "$hardcode_action_F77" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_F77 \ CC_F77 \ LD_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ export_dynamic_flag_spec_F77 \ thread_safe_flag_spec_F77 \ whole_archive_flag_spec_F77 \ enable_shared_with_static_runtimes_F77 \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ predep_objects_F77 \ postdep_objects_F77 \ predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ postuninstall_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ export_symbols_cmds_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ hardcode_automatic_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do case $var in old_archive_cmds_F77 | \ old_archive_from_new_cmds_F77 | \ archive_cmds_F77 | \ archive_expsym_cmds_F77 | \ module_cmds_F77 | \ module_expsym_cmds_F77 | \ old_archive_from_expsyms_cmds_F77 | \ export_symbols_cmds_F77 | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_F77 # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_F77 old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_predep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_postdep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_F77 # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_F77 # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_F77 # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_F77" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o objext_GCJ=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no old_archive_cmds_GCJ=$old_archive_cmds lt_prog_compiler_no_builtin_flag_GCJ= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17141: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17145: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl_GCJ= lt_prog_compiler_pic_GCJ= lt_prog_compiler_static_GCJ= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_static_GCJ='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_GCJ='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_GCJ=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_GCJ=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_GCJ='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' else lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_GCJ='-qnocommon' lt_prog_compiler_wl_GCJ='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_GCJ='-non_shared' ;; newsos6) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-fpic' lt_prog_compiler_static_GCJ='-Bstatic' ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_GCJ='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; solaris*) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_GCJ='-Qoption ld ';; *) lt_prog_compiler_wl_GCJ='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_GCJ='-Qoption ld ' lt_prog_compiler_pic_GCJ='-PIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_GCJ='-Kconform_pic' lt_prog_compiler_static_GCJ='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; unicos*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_can_build_shared_GCJ=no ;; uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_GCJ=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_GCJ"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17409: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17413: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; esac else lt_prog_compiler_pic_GCJ= lt_prog_compiler_can_build_shared_GCJ=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= ;; *) lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_GCJ=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_GCJ=yes fi else lt_prog_compiler_static_works_GCJ=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6 if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then : else lt_prog_compiler_static_GCJ= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_GCJ=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17513: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:17517: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag_GCJ= enable_shared_with_static_runtimes_GCJ=no archive_cmds_GCJ= archive_expsym_cmds_GCJ= old_archive_From_new_cmds_GCJ= old_archive_from_expsyms_cmds_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= thread_safe_flag_spec_GCJ= hardcode_libdir_flag_spec_GCJ= hardcode_libdir_flag_spec_ld_GCJ= hardcode_libdir_separator_GCJ= hardcode_direct_GCJ=no hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=unsupported link_all_deplibs_GCJ=unknown hardcode_automatic_GCJ=no module_cmds_GCJ= module_expsym_cmds_GCJ= always_export_symbols_GCJ=no export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_GCJ= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_GCJ=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_GCJ= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no cat <<EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_GCJ=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_GCJ=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_GCJ=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_GCJ='-L$libdir' allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_GCJ=no fi ;; interix3*) hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_GCJ=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <<EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_GCJ=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac ;; sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac if test "$ld_shlibs_GCJ" = no; then runpath_var= hardcode_libdir_flag_spec_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=yes archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_GCJ='' hardcode_direct_GCJ=yes hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_GCJ=yes else # We have old collect2 hardcode_direct_GCJ=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_GCJ=yes hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_GCJ=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_GCJ='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_GCJ='$convenience' archive_cmds_need_lc_GCJ=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # see comment about different semantics on the GNU ld section ld_shlibs_GCJ=no ;; bsdi[45]*) export_dynamic_flag_spec_GCJ=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_GCJ=' ' allow_undefined_flag_GCJ=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_GCJ=no hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported whole_archive_flag_spec_GCJ='' link_all_deplibs_GCJ=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_GCJ=no ;; esac fi ;; dgux*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; freebsd1*) ld_shlibs_GCJ=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no ;; *) hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: link_all_deplibs_GCJ=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; newsos6) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_shlibpath_var_GCJ=no ;; openbsd*) hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' ;; *) archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes allow_undefined_flag_GCJ=unsupported archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' fi hardcode_libdir_separator_GCJ=: ;; solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs_GCJ=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; sysv4) case $host_vendor in sni) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_GCJ='$CC -r -o $output$reload_objs' hardcode_direct_GCJ=no ;; motorola) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv4.3*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_GCJ=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag_GCJ='${wl}-z,text' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_GCJ='${wl}-z,text' allow_undefined_flag_GCJ='${wl}-z,nodefs' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; *) ld_shlibs_GCJ=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 echo "${ECHO_T}$ld_shlibs_GCJ" >&6 test "$ld_shlibs_GCJ" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_GCJ" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_GCJ=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_GCJ in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ pic_flag=$lt_prog_compiler_pic_GCJ compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ allow_undefined_flag_GCJ= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_GCJ=no else archive_cmds_need_lc_GCJ=yes fi allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # find out which ABI we are using libsuff= case "$host_cpu" in x86_64*|s390x*|powerpc64*) echo '#line 18982 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *64-bit*) libsuff=64 sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" ;; esac fi rm -rf conftest* ;; esac # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ test -n "$runpath_var_GCJ" || \ test "X$hardcode_automatic_GCJ" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && test "$hardcode_minus_L_GCJ" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_GCJ=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_GCJ=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_GCJ=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 echo "${ECHO_T}$hardcode_action_GCJ" >&6 if test "$hardcode_action_GCJ" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_GCJ \ CC_GCJ \ LD_GCJ \ lt_prog_compiler_wl_GCJ \ lt_prog_compiler_pic_GCJ \ lt_prog_compiler_static_GCJ \ lt_prog_compiler_no_builtin_flag_GCJ \ export_dynamic_flag_spec_GCJ \ thread_safe_flag_spec_GCJ \ whole_archive_flag_spec_GCJ \ enable_shared_with_static_runtimes_GCJ \ old_archive_cmds_GCJ \ old_archive_from_new_cmds_GCJ \ predep_objects_GCJ \ postdep_objects_GCJ \ predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ postuninstall_cmds_GCJ \ old_archive_from_expsyms_cmds_GCJ \ allow_undefined_flag_GCJ \ no_undefined_flag_GCJ \ export_symbols_cmds_GCJ \ hardcode_libdir_flag_spec_GCJ \ hardcode_libdir_flag_spec_ld_GCJ \ hardcode_libdir_separator_GCJ \ hardcode_automatic_GCJ \ module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do case $var in old_archive_cmds_GCJ | \ old_archive_from_new_cmds_GCJ | \ archive_cmds_GCJ | \ archive_expsym_cmds_GCJ | \ module_cmds_GCJ | \ module_expsym_cmds_GCJ | \ old_archive_from_expsyms_cmds_GCJ | \ export_symbols_cmds_GCJ | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_GCJ # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_GCJ # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_GCJ # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_GCJ pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_GCJ # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_GCJ old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_GCJ archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_GCJ module_expsym_cmds=$lt_module_expsym_cmds_GCJ # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_predep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_postdep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_GCJ # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_GCJ # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_GCJ # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_GCJ # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_GCJ # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_GCJ # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_GCJ # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_GCJ" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_GCJ # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_GCJ # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_GCJ # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; RC) # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o objext_RC=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_RC \ CC_RC \ LD_RC \ lt_prog_compiler_wl_RC \ lt_prog_compiler_pic_RC \ lt_prog_compiler_static_RC \ lt_prog_compiler_no_builtin_flag_RC \ export_dynamic_flag_spec_RC \ thread_safe_flag_spec_RC \ whole_archive_flag_spec_RC \ enable_shared_with_static_runtimes_RC \ old_archive_cmds_RC \ old_archive_from_new_cmds_RC \ predep_objects_RC \ postdep_objects_RC \ predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ postuninstall_cmds_RC \ old_archive_from_expsyms_cmds_RC \ allow_undefined_flag_RC \ no_undefined_flag_RC \ export_symbols_cmds_RC \ hardcode_libdir_flag_spec_RC \ hardcode_libdir_flag_spec_ld_RC \ hardcode_libdir_separator_RC \ hardcode_automatic_RC \ module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ exclude_expsyms_RC \ include_expsyms_RC; do case $var in old_archive_cmds_RC | \ old_archive_from_new_cmds_RC | \ archive_cmds_RC | \ archive_expsym_cmds_RC | \ module_cmds_RC | \ module_expsym_cmds_RC | \ old_archive_from_expsyms_cmds_RC | \ export_symbols_cmds_RC | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_RC # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` gcc_ver=\`gcc -dumpversion\` # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_RC # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_RC # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_RC pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_RC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_RC old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_RC archive_expsym_cmds=$lt_archive_expsym_cmds_RC postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_RC module_expsym_cmds=$lt_module_expsym_cmds_RC # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=\`echo $lt_predep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=\`echo $lt_postdep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_RC # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_RC # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_RC # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_RC # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_RC # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_RC # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_RC # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_RC # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_RC # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_RC" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_RC # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_RC # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_RC # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ;; *) { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 echo "$as_me: error: Unsupported tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 echo "$as_me: error: unable to update list of available tagged configurations." >&2;} { (exit 1); exit 1; }; } fi fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion # Configured headers (pretty much everybody needs blddir and vm) INCLUDES="-I${blddir} -I${vmmcfg} -I${topdir}/platforms/unix/vm -I${topdir}/platforms/Cross/vm -I${vmmdir}/vm" # Checks for header files. case "$host" in *-sunos*) cat >>confdefs.h <<\_ACEOF #define NEED_SUNOS_H 1 _ACEOF esac echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <string.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <ctype.h> #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi for ac_header in unistd.h string.h fcntl.h sys/file.h sys/param.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/time.h sys/filio.h sys/select.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in features.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in alloca.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # SunOS5 echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 if test "${ac_cv_header_time+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <sys/time.h> #include <time.h> int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_time=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_time=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 echo "${ECHO_T}$ac_cv_header_time" >&6 if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF #define TIME_WITH_SYS_TIME 1 _ACEOF fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in dir; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi else echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_opendir=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_opendir" = no; then for ac_lib in x; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char opendir (); int main () { opendir (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_opendir="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6 if test "$ac_cv_search_opendir" != no; then test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" fi fi if test -f "${vmmdir}/vm/interp.h"; then cat >>confdefs.h <<\_ACEOF #define HAVE_INTERP_H 1 _ACEOF fi echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6 if test "${ac_cv_struct_tm+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <time.h> int main () { struct tm *tp; tp->tm_sec; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_struct_tm=time.h else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_struct_tm=sys/time.h fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 echo "${ECHO_T}$ac_cv_struct_tm" >&6 if test $ac_cv_struct_tm = sys/time.h; then cat >>confdefs.h <<\_ACEOF #define TM_IN_SYS_TIME 1 _ACEOF fi echo "$as_me:$LINENO: checking for struct tm.tm_zone" >&5 echo $ECHO_N "checking for struct tm.tm_zone... $ECHO_C" >&6 if test "${ac_cv_member_struct_tm_tm_zone+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <$ac_cv_struct_tm> int main () { static struct tm ac_aggr; if (ac_aggr.tm_zone) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_tm_tm_zone=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <$ac_cv_struct_tm> int main () { static struct tm ac_aggr; if (sizeof ac_aggr.tm_zone) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_tm_tm_zone=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_tm_tm_zone=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_member_struct_tm_tm_zone" >&5 echo "${ECHO_T}$ac_cv_member_struct_tm_tm_zone" >&6 if test $ac_cv_member_struct_tm_tm_zone = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TM_TM_ZONE 1 _ACEOF fi if test "$ac_cv_member_struct_tm_tm_zone" = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_TM_ZONE 1 _ACEOF else echo "$as_me:$LINENO: checking for tzname" >&5 echo $ECHO_N "checking for tzname... $ECHO_C" >&6 if test "${ac_cv_var_tzname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <time.h> #ifndef tzname /* For SGI. */ extern char *tzname[]; /* RS6000 and others reject char **tzname. */ #endif int main () { atoi(*tzname); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_var_tzname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_var_tzname=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_var_tzname" >&5 echo "${ECHO_T}$ac_cv_var_tzname" >&6 if test $ac_cv_var_tzname = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_TZNAME 1 _ACEOF fi fi echo "$as_me:$LINENO: checking for socklen_t in sys/socket.h" >&5 echo $ECHO_N "checking for socklen_t in sys/socket.h... $ECHO_C" >&6 if test "${ac_cv_socklen_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/socket.h> int main () { sizeof(socklen_t); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_socklen_t="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_socklen_t="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_socklen_t" >&5 echo "${ECHO_T}$ac_cv_socklen_t" >&6 test "$ac_cv_socklen_t" != "yes" && cat >>confdefs.h <<\_ACEOF #define socklen_t int _ACEOF echo "$as_me:$LINENO: checking for atexit or on_exit" >&5 echo $ECHO_N "checking for atexit or on_exit... $ECHO_C" >&6 if test "${ac_cv_atexit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> int main () { atexit(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_atexit="atexit" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <stdlib.h> int main () { on_exit(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_atexit="on_exit" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_atexit="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_atexit" >&5 echo "${ECHO_T}$ac_cv_atexit" >&6 if test "$ac_cv_atexit" != "no"; then cat >>confdefs.h <<_ACEOF #define AT_EXIT $ac_cv_atexit _ACEOF fi echo "$as_me:$LINENO: checking for tzset" >&5 echo $ECHO_N "checking for tzset... $ECHO_C" >&6 if test "${ac_cv_tzset+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <time.h> int main () { tzet(); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_tzset="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_tzset="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_tzset" >&5 echo "${ECHO_T}$ac_cv_tzset" >&6 test "$ac_cv_tzset" != "no" && cat >>confdefs.h <<\_ACEOF #define HAVE_TZSET 1 _ACEOF echo "$as_me:$LINENO: checking for gmtoff in struct tm" >&5 echo $ECHO_N "checking for gmtoff in struct tm... $ECHO_C" >&6 if test "${ac_cv_tm_gmtoff+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <time.h> int main () { struct tm tm; tm.tm_gmtoff; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_tm_gmtoff="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_tm_gmtoff="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_tm_gmtoff" >&5 echo "${ECHO_T}$ac_cv_tm_gmtoff" >&6 test "$ac_cv_tm_gmtoff" != "no" && cat >>confdefs.h <<\_ACEOF #define HAVE_TM_GMTOFF 1 _ACEOF echo "$as_me:$LINENO: checking for timezone and daylight variables" >&5 echo $ECHO_N "checking for timezone and daylight variables... $ECHO_C" >&6 if test "${ac_cv_timezone+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern long timezone; extern int daylight; int main () { timezone;daylight; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_timezone="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_timezone="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_timezone" >&5 echo "${ECHO_T}$ac_cv_timezone" >&6 test "$ac_cv_timezone" != "no" && cat >>confdefs.h <<\_ACEOF #define HAVE_TIMEZONE 1 _ACEOF echo "$as_me:$LINENO: checking for gethostname in unistd.h" >&5 echo $ECHO_N "checking for gethostname in unistd.h... $ECHO_C" >&6 if test "${ac_cv_gethostname_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <unistd.h> int main () { return (int)gethostname; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_gethostname_p="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_gethostname_p="no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_gethostname_p" >&5 echo "${ECHO_T}$ac_cv_gethostname_p" >&6 test "$ac_cv_gethostname_p" = "no" && cat >>confdefs.h <<\_ACEOF #define NEED_GETHOSTNAME_P 1 _ACEOF # Display options. # Check whether --with-rfb or --without-rfb was given. if test "${with_rfb+set}" = set; then withval="$with_rfb" have_rfb="$withval" else have_rfb="no" fi; test $have_rfb = "yes" && cat >>confdefs.h <<\_ACEOF #define USE_RFB 1 _ACEOF # Checks for libraries. echo "$as_me:$LINENO: checking for yp_bind in -lnsl" >&5 echo $ECHO_N "checking for yp_bind in -lnsl... $ECHO_C" >&6 if test "${ac_cv_lib_nsl_yp_bind+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char yp_bind (); int main () { yp_bind (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_nsl_yp_bind=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_yp_bind=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_yp_bind" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_yp_bind" >&6 if test $ac_cv_lib_nsl_yp_bind = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6 if test "${ac_cv_lib_socket_socket+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char socket (); int main () { socket (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_socket_socket=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_socket=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6 if test $ac_cv_lib_socket_socket = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi echo "$as_me:$LINENO: checking for sin in -lm" >&5 echo $ECHO_N "checking for sin in -lm... $ECHO_C" >&6 if test "${ac_cv_lib_m_sin+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char sin (); int main () { sin (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_m_sin=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_m_sin=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_m_sin" >&5 echo "${ECHO_T}$ac_cv_lib_m_sin" >&6 if test $ac_cv_lib_m_sin = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pthread_create (); int main () { pthread_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_pthread_pthread_create=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_create=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 if test $ac_cv_lib_pthread_pthread_create = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi # this seems to add no benefit #AC_CHECK_LIB(rt, clock_nanosleep) #AC_CHECK_FUNC(dlopen, [ # AC_DEFINE(HAVE_LIBDL,[1]) #],[ # AC_CHECK_LIB(dl, dlopen, [ # LIBS="-ldl $LIBS" # AC_DEFINE(HAVE_LIBDL,[1]) # ],[ # AC_CHECK_FUNC(_dyld_present, [ # AC_DEFINE(HAVE_DYLD,[1]) # ]) # ]) #]) echo "$as_me:$LINENO: checking for _dyld_present" >&5 echo $ECHO_N "checking for _dyld_present... $ECHO_C" >&6 if test "${ac_cv_func__dyld_present+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define _dyld_present to an innocuous variant, in case <limits.h> declares _dyld_present. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define _dyld_present innocuous__dyld_present /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _dyld_present (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef _dyld_present /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _dyld_present (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__dyld_present) || defined (__stub____dyld_present) choke me #else char (*f) () = _dyld_present; #endif #ifdef __cplusplus } #endif int main () { return f != _dyld_present; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func__dyld_present=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__dyld_present=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func__dyld_present" >&5 echo "${ECHO_T}$ac_cv_func__dyld_present" >&6 if test $ac_cv_func__dyld_present = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DYLD 1 _ACEOF else for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 if test "${ac_cv_func_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef dlopen /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else char (*f) () = dlopen; #endif #ifdef __cplusplus } #endif int main () { return f != dlopen; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6 if test $ac_cv_func_dlopen = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIBDL 1 _ACEOF else echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then LIBS="-ldl $LIBS" cat >>confdefs.h <<\_ACEOF #define HAVE_LIBDL 1 _ACEOF fi fi fi for ac_func in snprintf __snprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_header in stdlib.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getpagesize do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for working mmap" >&5 echo $ECHO_N "checking for working mmap... $ECHO_C" >&6 if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_mmap_fixed_mapped=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default /* malloc might have been renamed as rpl_malloc. */ #undef malloc /* Thanks to Mike Haertel and Jim Avera for this test. Here is a matrix of mmap possibilities: mmap private not fixed mmap private fixed at somewhere currently unmapped mmap private fixed at somewhere already mapped mmap shared not fixed mmap shared fixed at somewhere currently unmapped mmap shared fixed at somewhere already mapped For private mappings, we should verify that changes cannot be read() back from the file, nor mmap's back from the file at a different address. (There have been systems where private was not correctly implemented like the infamous i386 svr4.0, and systems where the VM page cache was not coherent with the file system buffer cache like early versions of FreeBSD and possibly contemporary NetBSD.) For shared mappings, we should conversely verify that changes get propagated back to all the places they're supposed to be. Grep wants private fixed already mapped. The main things grep needs to know about mmap are: * does it exist and is it safe to write into the mmap'd area * how to use it (BSD variants) */ #include <fcntl.h> #include <sys/mman.h> #if !STDC_HEADERS && !HAVE_STDLIB_H char *malloc (); #endif /* This mess was copied from the GNU getpagesize.h. */ #if !HAVE_GETPAGESIZE /* Assume that all systems that can run configure have sys/param.h. */ # if !HAVE_SYS_PARAM_H # define HAVE_SYS_PARAM_H 1 # endif # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # if HAVE_SYS_PARAM_H # include <sys/param.h> # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ int main () { char *data, *data2, *data3; int i, pagesize; int fd; pagesize = getpagesize (); /* First, make a file with some known garbage in it. */ data = (char *) malloc (pagesize); if (!data) exit (1); for (i = 0; i < pagesize; ++i) *(data + i) = rand (); umask (0); fd = creat ("conftest.mmap", 0600); if (fd < 0) exit (1); if (write (fd, data, pagesize) != pagesize) exit (1); close (fd); /* Next, try to mmap the file at a fixed address which already has something else allocated at it. If we can, also make sure that we see the same garbage. */ fd = open ("conftest.mmap", O_RDWR); if (fd < 0) exit (1); data2 = (char *) malloc (2 * pagesize); if (!data2) exit (1); data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1); if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) exit (1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) exit (1); /* Finally, make sure that changes to the mapped area do not percolate back to the file as seen by read(). (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = (char *) malloc (pagesize); if (!data3) exit (1); if (read (fd, data3, pagesize) != pagesize) exit (1); for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) exit (1); close (fd); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_mmap_fixed_mapped=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_mmap_fixed_mapped=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6 if test $ac_cv_func_mmap_fixed_mapped = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_MMAP 1 _ACEOF fi rm -f conftest.mmap # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo "$as_me:$LINENO: checking for working alloca.h" >&5 echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6 if test "${ac_cv_working_alloca_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <alloca.h> int main () { char *p = (char *) alloca (2 * sizeof (int)); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_working_alloca_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_working_alloca_h=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 echo "${ECHO_T}$ac_cv_working_alloca_h" >&6 if test $ac_cv_working_alloca_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ALLOCA_H 1 _ACEOF fi echo "$as_me:$LINENO: checking for alloca" >&5 echo $ECHO_N "checking for alloca... $ECHO_C" >&6 if test "${ac_cv_func_alloca_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include <malloc.h> # define alloca _alloca # else # if HAVE_ALLOCA_H # include <alloca.h> # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_alloca_works=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_alloca_works=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 echo "${ECHO_T}$ac_cv_func_alloca_works" >&6 if test $ac_cv_func_alloca_works = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ALLOCA 1 _ACEOF else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=alloca.$ac_objext cat >>confdefs.h <<\_ACEOF #define C_ALLOCA 1 _ACEOF echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6 if test "${ac_cv_os_cray+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if defined(CRAY) && ! defined(CRAY2) webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 echo "${ECHO_T}$ac_cv_os_cray" >&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6 if test "${ac_cv_c_stack_direction+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_c_stack_direction=0 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int find_stack_direction () { static char *addr = 0; auto char dummy; if (addr == 0) { addr = &dummy; return find_stack_direction (); } else return (&dummy > addr) ? 1 : -1; } int main () { exit (find_stack_direction () < 0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_stack_direction=1 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_stack_direction=-1 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 echo "${ECHO_T}$ac_cv_c_stack_direction" >&6 cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi #AC_ARG_ENABLE(jit, #[ --enable-jit enable J4 support [default=no]], #JIT="yes", JIT="no") # #test $JIT = "yes" && J_CFLAGS="-DJ_ENABLED" #AC_SUBST(J_CFLAGS) # Checks for platform characteristics. echo "$as_me:$LINENO: checking for $host_cpu optimisation flags" >&5 echo $ECHO_N "checking for $host_cpu optimisation flags... $ECHO_C" >&6 ac_optflags="no" if test "$GCC" = yes; then case $host_cpu in # Leave this to the configure command # i?86) # ac_optflags="-fomit-frame-pointer" # ;; powerpc|ppc) ac_optflags="-O3 -funroll-loops -mcpu=750 -mno-fused-madd" ;; esac cat >>confdefs.h <<\_ACEOF #define VM_BUILD_STRING "Unix built on "__DATE__ " "__TIME__" Compiler: "__VERSION__ _ACEOF else ac_optflags="-O" ac_vm_build_date="`date`" cat >>confdefs.h <<\_ACEOF #define VM_BUILD_STRING "Unix built on ${ac_vm_build_date}" _ACEOF fi if test "$ac_optflags" = "no"; then echo "$as_me:$LINENO: result: (none)" >&5 echo "${ECHO_T}(none)" >&6 else CFLAGS="$CFLAGS $ac_optflags" echo "$as_me:$LINENO: result: \"$ac_optflags\"" >&5 echo "${ECHO_T}\"$ac_optflags\"" >&6 fi INTERP="cointerp" for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether we can compile gcc3x-cointerp.c" >&5 echo $ECHO_N "checking whether we can compile gcc3x-cointerp.c... $ECHO_C" >&6 if test "$GCC" = "yes"; then INTERP="gcc3x-$INTERP"; echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi echo "$as_me:$LINENO: checking for prefix to use for loadable modules" >&5 echo $ECHO_N "checking for prefix to use for loadable modules... $ECHO_C" >&6 if test "${ac_cv_module_prefix+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -x ./libtool && test "`./libtool --config | fgrep need_lib_prefix`" = "need_lib_prefix=no" then ac_cv_module_prefix="(none)"; else ac_cv_module_prefix="lib" fi fi echo "$as_me:$LINENO: result: $ac_cv_module_prefix" >&5 echo "${ECHO_T}$ac_cv_module_prefix" >&6 cat >>confdefs.h <<_ACEOF #define VM_MODULE_PREFIX "$mkfrags_lib_prefix" _ACEOF test "$ac_cv_module_prefix" = lib && mkfrags_lib_prefix=lib echo "$as_me:$LINENO: checking for compiler flags to force 32-bit addresses" >&5 echo $ECHO_N "checking for compiler flags to force 32-bit addresses... $ECHO_C" >&6 case $host in alpha*) CFLAGS_32="-taso" test "$GCC" = "yes" && CC="\$(utldir)/decgcc" ;; esac echo "$as_me:$LINENO: result: $CFLAGS_32" >&5 echo "${ECHO_T}$CFLAGS_32" >&6 CFLAGS="$CFLAGS_32 $CFLAGS -msse" echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <sys/param.h> int main () { #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/types.h> #include <sys/param.h> int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long l; char c[sizeof (long)]; } u; u.l = 1; exit (u.c[sizeof (long) - 1] == 1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6 case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac if test $ac_cv_c_bigendian != yes then CFLAGS="$CFLAGS -DLSB_FIRST=1" fi echo "$as_me:$LINENO: checking whether unaligned access to doubles is ok" >&5 echo $ECHO_N "checking whether unaligned access to doubles is ok... $ECHO_C" >&6 if test "${ac_cv_double_align+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ f(int i){*(double *)i=*(double *)(i+4);} int main(){char b[12];f(b);return 0;} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_double_align="yes" else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_double_align="no" fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_double_align" >&5 echo "${ECHO_T}$ac_cv_double_align" >&6 test "$ac_cv_double_align" = "no" && cat >>confdefs.h <<\_ACEOF #define DOUBLE_WORD_ALIGNMENT 1 _ACEOF case $host_os in darwin*) cat >>confdefs.h <<\_ACEOF #define DARWIN 1 _ACEOF # CFLAGS="-no-cpp-precomp $CFLAGS" with_npsqueak=no VM_APP_ICONS="${imgdir}/SqueakVM.icns" ;; *) VM_APP_ICONS="" ;; esac # Checks for browser support # Check whether --with-npsqueak or --without-npsqueak was given. if test "${with_npsqueak+set}" = set; then withval="$with_npsqueak" with_npsqueak="$withval" else with_npsqueak="yes" fi; if test "$with_npsqueak" = "no"; then npsqueak="" install_nps="" uninstall_nps="" else npsqueak=npsqueak install_nps=install-npsqueak uninstall_nps=uninstall-npsqueak fi # Install locations if test "x${prefix}" = xNONE; then SQ_LIBDIR=${ac_default_prefix}/lib/squeak/${SQ_VERSION} else SQ_LIBDIR=${prefix}/lib/squeak/${SQ_VERSION} fi cat >>confdefs.h <<_ACEOF #define SQ_LIBDIR "${SQ_LIBDIR}" _ACEOF # Configure files make_cfg=${blddir}/make.cfg make_int=${blddir}/make.int make_ext=${blddir}/make.ext make_prg=${blddir}/make.prg Makefile_install=${cfgdir}/Makefile.install Makefile_dist=${topdir}/util/Makefile.dist Makefile_rpm=${topdir}/util/Makefile.rpm Makefile_deb=${topdir}/util/Makefile.deb # Configure VM modules xxx MAKE INTERNAL WORK int_modules="vm" ext_modules="`cd ${topdir}/platforms/unix; echo vm-*`" # Configure plugins disabled_plugins="" rm -f plugins.exc plugin="vm" plibs="" rm -f vm.sub vm.lib # Check whether --enable-iconv or --disable-iconv was given. if test "${enable_iconv+set}" = set; then enableval="$enable_iconv" with_iconv="$withval" else with_iconv="yes" fi; case $host_os in darwin*) LIBS="$LIBS -framework CoreFoundation -framework CoreServices";; *) ;; esac if test "$with_iconv" = "yes"; then for ac_header in iconv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for _dyld_present" >&5 echo $ECHO_N "checking for _dyld_present... $ECHO_C" >&6 if test "${ac_cv_func__dyld_present+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define _dyld_present to an innocuous variant, in case <limits.h> declares _dyld_present. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define _dyld_present innocuous__dyld_present /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _dyld_present (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef _dyld_present /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _dyld_present (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__dyld_present) || defined (__stub____dyld_present) choke me #else char (*f) () = _dyld_present; #endif #ifdef __cplusplus } #endif int main () { return f != _dyld_present; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func__dyld_present=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__dyld_present=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func__dyld_present" >&5 echo "${ECHO_T}$ac_cv_func__dyld_present" >&6 if test $ac_cv_func__dyld_present = yes; then : else echo "$as_me:$LINENO: checking for iconv_open in -liconv" >&5 echo $ECHO_N "checking for iconv_open in -liconv... $ECHO_C" >&6 if test "${ac_cv_lib_iconv_iconv_open+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char iconv_open (); int main () { iconv_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_iconv_iconv_open=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_iconv_iconv_open=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_iconv_open" >&5 echo "${ECHO_T}$ac_cv_lib_iconv_iconv_open" >&6 if test $ac_cv_lib_iconv_iconv_open = yes; then ac_cv_iconv=yes else echo "$as_me:$LINENO: checking for libiconv_open in -liconv" >&5 echo $ECHO_N "checking for libiconv_open in -liconv... $ECHO_C" >&6 if test "${ac_cv_lib_iconv_libiconv_open+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char libiconv_open (); int main () { libiconv_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_iconv_libiconv_open=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_iconv_libiconv_open=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_libiconv_open" >&5 echo "${ECHO_T}$ac_cv_lib_iconv_libiconv_open" >&6 if test $ac_cv_lib_iconv_libiconv_open = yes; then ac_cv_iconv=yes else ac_cv_iconv=no fi fi if test $ac_cv_iconv = yes; then LIBS="$LIBS -liconv" fi fi echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5 echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6 if test "${ac_cv_langinfo_codeset+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <langinfo.h> int main () { char *cs= nl_langinfo(CODESET); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_langinfo_codeset=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_langinfo_codeset=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_langinfo_codeset" >&5 echo "${ECHO_T}$ac_cv_langinfo_codeset" >&6 if test $ac_cv_langinfo_codeset = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LANGINFO_CODESET 1 _ACEOF fi else echo "$as_me:$LINENO: result: ******** disabling iconv" >&5 echo "${ECHO_T}******** disabling iconv" >&6 fi echo "$as_me:$LINENO: checking for nanosleep" >&5 echo $ECHO_N "checking for nanosleep... $ECHO_C" >&6 if test "${ac_cv_func_nanosleep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define nanosleep to an innocuous variant, in case <limits.h> declares nanosleep. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define nanosleep innocuous_nanosleep /* System header to define __stub macros and hopefully few prototypes, which can conflict with char nanosleep (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef nanosleep /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char nanosleep (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_nanosleep) || defined (__stub___nanosleep) choke me #else char (*f) () = nanosleep; #endif #ifdef __cplusplus } #endif int main () { return f != nanosleep; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_nanosleep=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_nanosleep=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_nanosleep" >&5 echo "${ECHO_T}$ac_cv_func_nanosleep" >&6 if test $ac_cv_func_nanosleep = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_NANOSLEEP 1 _ACEOF fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-display-custom" plibs="" rm -f vm-display-custom.sub vm-display-custom.lib # -*- sh -*- echo "$as_me:$LINENO: checking for custom display support" >&5 echo $ECHO_N "checking for custom display support... $ECHO_C" >&6 # Check whether --with-custom-display or --without-custom-display was given. if test "${with_custom_display+set}" = set; then withval="$with_custom_display" have_dpy_custom="$withval" else have_dpy_custom="no" fi; if test "$have_dpy_custom" = "yes"; then # check for libraries, headers, etc., here... echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-display-fbdev" plibs="" rm -f vm-display-fbdev.sub vm-display-fbdev.lib # -*- sh -*- for ac_header in linux/fb.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi done if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-display-Quartz" plibs="" rm -f vm-display-Quartz.sub vm-display-Quartz.lib # -*- sh -*- # Check whether --with-quartz or --without-quartz was given. if test "${with_quartz+set}" = set; then withval="$with_quartz" have_quartz="$withval" else have_quartz="yes" fi; case $host_os in darwin*) ;; *) have_quartz="no";; esac if test "$have_quartz" = "yes"; then cat >>confdefs.h <<\_ACEOF #define USE_QUARTZ 1 _ACEOF if test "$have_gl" = ""; then have_gl="no"; fi for ac_header in OpenGL/gl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF have_gl=yes cat >>confdefs.h <<\_ACEOF #define USE_QUARTZ_CGL 1 _ACEOF fi done else echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-display-X11" plibs="" rm -f vm-display-X11.sub vm-display-X11.lib # -*- sh -*- # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then withval="$with_x" have_x="$withval" else have_x="yes" fi; # Check whether --with-gl or --without-gl was given. if test "${with_gl+set}" = set; then withval="$with_gl" have_gl="$withval" else have_gl="yes" fi; ###xxx FIXME (AGAIN): mandrake needs explicit -lpthread VMLIBS=${LIBS} VMCFLAGS=${CFLAGS} VMCPPFLAGS=${CPPFLAGS} VMINCLUDES=${INCLUDES} if test "$have_x" = "yes"; then echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then withval="$with_x" fi; # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then # Both variables are already set. have_x=yes else if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -fr conftest.dir if mkdir conftest.dir; then cd conftest.dir # Make sure to not put "make" in the Imakefile rules, since we grep it out. cat >Imakefile <<'_ACEOF' acfindx: @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' _ACEOF if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl; do if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && test -f $ac_im_libdir/libX11.$ac_extension; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /lib) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -fr conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <X11/Xlib.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <X11/Xlib.h> int main () { XrmInitialize () ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do if test -r $ac_dir/libXt.$ac_extension; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then # Didn't find X anywhere. Cache the known absence of X. ac_cv_have_x="have_x=no" else # Record where we found X for the cache. ac_cv_have_x="have_x=yes \ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" fi fi fi eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$have_x" >&6 no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes \ ac_x_includes=$x_includes ac_x_libraries=$x_libraries" echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. cat >>confdefs.h <<\_ACEOF #define X_DISPLAY_MISSING 1 _ACEOF X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . case `(uname -sr) 2>/dev/null` in "SunOS 5"*) echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_R_nospace=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_R_nospace=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test $ac_R_nospace = yes; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 X_LIBS="$X_LIBS -R$x_libraries" else LIBS="$ac_xsave_LIBS -R $x_libraries" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_R_space=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_R_space=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test $ac_R_space = yes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 X_LIBS="$X_LIBS -R $x_libraries" else echo "$as_me:$LINENO: result: neither works" >&5 echo "${ECHO_T}neither works" >&6 fi fi LIBS=$ac_xsave_LIBS esac fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char XOpenDisplay (); int main () { XOpenDisplay (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main () { dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dnet_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_dnet_ntoa=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 if test $ac_cv_lib_dnet_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main () { dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dnet_stub_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. echo "$as_me:$LINENO: checking for gethostbyname" >&5 echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 if test "${ac_cv_func_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef gethostbyname /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) choke me #else char (*f) () = gethostbyname; #endif #ifdef __cplusplus } #endif int main () { return f != gethostbyname; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostbyname=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 if test $ac_cv_func_gethostbyname = no; then echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); int main () { gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_nsl_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostbyname=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 if test $ac_cv_lib_nsl_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname (); int main () { gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_bsd_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bsd_gethostbyname=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 if test $ac_cv_lib_bsd_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. echo "$as_me:$LINENO: checking for connect" >&5 echo $ECHO_N "checking for connect... $ECHO_C" >&6 if test "${ac_cv_func_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define connect to an innocuous variant, in case <limits.h> declares connect. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef connect /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char connect (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_connect) || defined (__stub___connect) choke me #else char (*f) () = connect; #endif #ifdef __cplusplus } #endif int main () { return f != connect; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_connect=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 echo "${ECHO_T}$ac_cv_func_connect" >&6 if test $ac_cv_func_connect = no; then echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 if test "${ac_cv_lib_socket_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char connect (); int main () { connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_socket_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_connect=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 if test $ac_cv_lib_socket_connect = yes; then X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. echo "$as_me:$LINENO: checking for remove" >&5 echo $ECHO_N "checking for remove... $ECHO_C" >&6 if test "${ac_cv_func_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define remove to an innocuous variant, in case <limits.h> declares remove. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define remove innocuous_remove /* System header to define __stub macros and hopefully few prototypes, which can conflict with char remove (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef remove /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char remove (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_remove) || defined (__stub___remove) choke me #else char (*f) () = remove; #endif #ifdef __cplusplus } #endif int main () { return f != remove; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_remove=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 echo "${ECHO_T}$ac_cv_func_remove" >&6 if test $ac_cv_func_remove = no; then echo "$as_me:$LINENO: checking for remove in -lposix" >&5 echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 if test "${ac_cv_lib_posix_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char remove (); int main () { remove (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_posix_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_posix_remove=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 if test $ac_cv_lib_posix_remove = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo "$as_me:$LINENO: checking for shmat" >&5 echo $ECHO_N "checking for shmat... $ECHO_C" >&6 if test "${ac_cv_func_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shmat to an innocuous variant, in case <limits.h> declares shmat. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define shmat innocuous_shmat /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shmat (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef shmat /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shmat (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shmat) || defined (__stub___shmat) choke me #else char (*f) () = shmat; #endif #ifdef __cplusplus } #endif int main () { return f != shmat; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shmat=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 echo "${ECHO_T}$ac_cv_func_shmat" >&6 if test $ac_cv_func_shmat = no; then echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 if test "${ac_cv_lib_ipc_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shmat (); int main () { shmat (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_ipc_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ipc_shmat=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 if test $ac_cv_lib_ipc_shmat = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char IceConnectionNumber (); int main () { IceConnectionNumber (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_ICE_IceConnectionNumber=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi LIBS="${X_PRE_LIBS} ${X_LIBS} ${X_EXTRA_LIBS} ${LIBS}" # if test "${x_libraries}" != ""; then # CFLAGS="${X_CFLAGS} ${CFLAGS} -L${x_libraries}" # fi if test "${x_includes}" != ""; then CPPFLAGS="${CPPFLAGS} -I${x_includes}" INCLUDES="${INCLUDES} -I${x_includes}" X_INCLUDES="-I${x_includes}" fi echo "$as_me:$LINENO: checking for XOpenDisplay in -lX11" >&5 echo $ECHO_N "checking for XOpenDisplay in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XOpenDisplay+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char XOpenDisplay (); int main () { XOpenDisplay (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_X11_XOpenDisplay=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_X11_XOpenDisplay=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_X11_XOpenDisplay" >&5 echo "${ECHO_T}$ac_cv_lib_X11_XOpenDisplay" >&6 if test $ac_cv_lib_X11_XOpenDisplay = yes; then cat >>confdefs.h <<\_ACEOF #define USE_X11 1 _ACEOF cat >>confdefs.h <<_ACEOF #define VM_X11DIR "${x_libraries}" _ACEOF LIBS="${LIBS} -lX11" echo "$as_me:$LINENO: checking for XShmAttach in -lXext" >&5 echo $ECHO_N "checking for XShmAttach in -lXext... $ECHO_C" >&6 if test "${ac_cv_lib_Xext_XShmAttach+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lXext $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char XShmAttach (); int main () { XShmAttach (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_Xext_XShmAttach=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_Xext_XShmAttach=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XShmAttach" >&5 echo "${ECHO_T}$ac_cv_lib_Xext_XShmAttach" >&6 if test $ac_cv_lib_Xext_XShmAttach = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBXEXT 1 _ACEOF LIBS="-lXext $LIBS" fi if test "$have_gl" = ""; then have_gl="no"; fi for ac_header in GL/gl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF have_gl=yes cat >>confdefs.h <<\_ACEOF #define USE_X11_GLX 1 _ACEOF echo "$as_me:$LINENO: checking for glIsEnabled in -lGL" >&5 echo $ECHO_N "checking for glIsEnabled in -lGL... $ECHO_C" >&6 if test "${ac_cv_lib_GL_glIsEnabled+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGL $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char glIsEnabled (); int main () { glIsEnabled (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_GL_glIsEnabled=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_GL_glIsEnabled=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glIsEnabled" >&5 echo "${ECHO_T}$ac_cv_lib_GL_glIsEnabled" >&6 if test $ac_cv_lib_GL_glIsEnabled = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGL 1 _ACEOF LIBS="-lGL $LIBS" fi fi done else echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi else echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi X_LIBS=${LIBS} X_CFLAGS=${CFLAGS} X_CPPFLAGS=${CPPFLAGS} X_INCLUDES=${INCLUDES} LIBS=${VMLIBS} CFLAGS=${VMCFLAGS} CPPFLAGS=${VMCPPFLAGS} INCLUDES=${VMINCLUDES} if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-ALSA" plibs="" rm -f vm-sound-ALSA.sub vm-sound-ALSA.lib # -*- sh -*- echo "$as_me:$LINENO: checking for Advanced Linux Sound Architecture" >&5 echo $ECHO_N "checking for Advanced Linux Sound Architecture... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <alsa/asoundlib.h> int main () { (void)snd_pcm_open; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-custom" plibs="" rm -f vm-sound-custom.sub vm-sound-custom.lib # -*- sh -*- echo "$as_me:$LINENO: checking for custom sound support" >&5 echo $ECHO_N "checking for custom sound support... $ECHO_C" >&6 # Check whether --with-custom-sound or --without-custom-sound was given. if test "${with_custom_sound+set}" = set; then withval="$with_custom_sound" have_snd_custom="$withval" else have_snd_custom="no" fi; if test "$have_snd_custom" = "yes"; then # check for libraries, headers, etc., here... echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-MacOSX" plibs="" rm -f vm-sound-MacOSX.sub vm-sound-MacOSX.lib # -*- sh -*- echo "$as_me:$LINENO: checking for Mac OS X CoreAudio" >&5 echo $ECHO_N "checking for Mac OS X CoreAudio... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <CoreAudio/CoreAudio.h> int main () { kAudioHardwareNoError; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-NAS" plibs="" rm -f vm-sound-NAS.sub vm-sound-NAS.lib # -*- sh -*- echo "$as_me:$LINENO: checking for Network Audio System" >&5 echo $ECHO_N "checking for Network Audio System... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <audio/audio.h> int main () { AuElementNotifyKindLowWater; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-null" plibs="" rm -f vm-sound-null.sub vm-sound-null.lib # -*- sh -*- # empty to provoke config/mkacinc into including vm-sound-null for consideration if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-OSS" plibs="" rm -f vm-sound-OSS.sub vm-sound-OSS.lib # -*- sh -*- if test "$with_vm_sound_OSS"="yes"; then echo "$as_me:$LINENO: checking for Open Sound System" >&5 echo $ECHO_N "checking for Open Sound System... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/soundcard.h> int main () { OPEN_SOUND_SYSTEM; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="vm-sound-Sun" plibs="" rm -f vm-sound-Sun.sub vm-sound-Sun.lib # -*- sh -*- echo "$as_me:$LINENO: checking for SunOS/Solaris audio" >&5 echo $ECHO_N "checking for SunOS/Solaris audio... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sys/audioio.h> int main () { AUDIO_SUNVTS; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<_ACEOF #define HAVE_SYS_AUDIOIO_H 1 _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <sun/audioio.h> int main () { AUDIO_SUNVTS; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<_ACEOF #define HAVE_SUN_AUDIOIO_H 1 _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="B3DAcceleratorPlugin" plibs="" rm -f B3DAcceleratorPlugin.sub B3DAcceleratorPlugin.lib if test "${have_gl}" != "yes"; then echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="FloatMathPlugin" plibs="" rm -f FloatMathPlugin.sub FloatMathPlugin.lib libm_cflags="-O" echo 'FloatMathPlugin/acinclude.m4:$host_cpu='$host_cpu if test "$GCC" = yes; then case $host_cpu in i?86) libm_cflags="-O -fomit-frame-pointer -DLSB_FIRST=1" ;; powerpc|ppc) libm_cflags="-O3 -funroll-loops -mcpu=750 -mno-fused-madd -DLSB_FIRST=0" ;; esac fi LIBM_CFLAGS=$libm_cflags if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="MIDIPlugin" plibs="" rm -f MIDIPlugin.sub MIDIPlugin.lib echo "$as_me:$LINENO: checking for MIDI support via ALSA" >&5 echo $ECHO_N "checking for MIDI support via ALSA... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <alsa/asoundlib.h> int main () { ; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define USE_MIDI_ALSA 1 _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="Mpeg3Plugin" plibs="" rm -f Mpeg3Plugin.sub Mpeg3Plugin.lib # Add `--enable-mpg-[mmx,pthreads]' switches # Check whether --enable-mpg-mmx or --disable-mpg-mmx was given. if test "${enable_mpg_mmx+set}" = set; then enableval="$enable_mpg_mmx" XDEFS="-DUSE_MMX" else XDEFS="" fi; # Check whether --enable-mpg-pthreads or --disable-mpg-pthreads was given. if test "${enable_mpg_pthreads+set}" = set; then enableval="$enable_mpg_pthreads" else XDEFS="$XDEFS -DNOPTHREADS" fi; # Define `[xdefs]' in Makefile.in echo 's%\['xdefs'\]%'$XDEFS'%g' >> ${plugin}.sub if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="PseudoTTYPlugin" plibs="" rm -f PseudoTTYPlugin.sub PseudoTTYPlugin.lib for ac_header in util.h libutil.h pty.h stropts.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to the AC_PACKAGE_NAME lists. ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for library containing openpty" >&5 echo $ECHO_N "checking for library containing openpty... $ECHO_C" >&6 if test "${ac_cv_search_openpty+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_openpty=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char openpty (); int main () { openpty (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_openpty="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_openpty" = no; then for ac_lib in util; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char openpty (); int main () { openpty (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_openpty="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_openpty" >&5 echo "${ECHO_T}$ac_cv_search_openpty" >&6 if test "$ac_cv_search_openpty" != no; then test "$ac_cv_search_openpty" = "none required" || LIBS="$ac_cv_search_openpty $LIBS" cat >>confdefs.h <<\_ACEOF #define HAVE_OPENPTY 1 _ACEOF else if test -r /dev/ptmx; then echo "$as_me:$LINENO: checking for grantpt" >&5 echo $ECHO_N "checking for grantpt... $ECHO_C" >&6 if test "${ac_cv_func_grantpt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define grantpt to an innocuous variant, in case <limits.h> declares grantpt. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define grantpt innocuous_grantpt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char grantpt (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef grantpt /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char grantpt (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_grantpt) || defined (__stub___grantpt) choke me #else char (*f) () = grantpt; #endif #ifdef __cplusplus } #endif int main () { return f != grantpt; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_grantpt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_grantpt=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_grantpt" >&5 echo "${ECHO_T}$ac_cv_func_grantpt" >&6 if test $ac_cv_func_grantpt = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_UNIX98_PTYS 1 _ACEOF fi fi fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="UnixOSProcessPlugin" plibs="" rm -f UnixOSProcessPlugin.sub UnixOSProcessPlugin.lib echo "$as_me:$LINENO: checking for unsetenv" >&5 echo $ECHO_N "checking for unsetenv... $ECHO_C" >&6 if test "${ac_cv_func_unsetenv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define unsetenv to an innocuous variant, in case <limits.h> declares unsetenv. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define unsetenv innocuous_unsetenv /* System header to define __stub macros and hopefully few prototypes, which can conflict with char unsetenv (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef unsetenv /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char unsetenv (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_unsetenv) || defined (__stub___unsetenv) choke me #else char (*f) () = unsetenv; #endif #ifdef __cplusplus } #endif int main () { return f != unsetenv; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_unsetenv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_unsetenv=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_unsetenv" >&5 echo "${ECHO_T}$ac_cv_func_unsetenv" >&6 if test $ac_cv_func_unsetenv = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_UNSETENV 1 _ACEOF fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="UUIDPlugin" plibs="" rm -f UUIDPlugin.sub UUIDPlugin.lib # -*- sh -*- echo "$as_me:$LINENO: checking for UUID support" >&5 echo $ECHO_N "checking for UUID support... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <uuid/uuid.h> int main () { uuid_generate; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 echo "$as_me:$LINENO: checking for uuid_generate in -luuid" >&5 echo $ECHO_N "checking for uuid_generate in -luuid... $ECHO_C" >&6 if test "${ac_cv_lib_uuid_uuid_generate+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-luuid $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char uuid_generate (); int main () { uuid_generate (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_uuid_uuid_generate=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_uuid_uuid_generate=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_generate" >&5 echo "${ECHO_T}$ac_cv_lib_uuid_uuid_generate" >&6 if test $ac_cv_lib_uuid_uuid_generate = yes; then LIB_UUID="-luuid" fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi plugin="XDisplayControlPlugin" plibs="" rm -f XDisplayControlPlugin.sub XDisplayControlPlugin.lib # Require X11 echo "$as_me:$LINENO: checking for XOpenDisplay in -lX11" >&5 echo $ECHO_N "checking for XOpenDisplay in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XOpenDisplay+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char XOpenDisplay (); int main () { XOpenDisplay (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_X11_XOpenDisplay=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_X11_XOpenDisplay=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_X11_XOpenDisplay" >&5 echo "${ECHO_T}$ac_cv_lib_X11_XOpenDisplay" >&6 if test $ac_cv_lib_X11_XOpenDisplay = yes; then plibs="${plibs} X11" else echo "$as_me:$LINENO: result: ******** disabling ${plugin}" >&5 echo "${ECHO_T}******** disabling ${plugin}" >&6 disabled_plugins="${disabled_plugins} ${plugin}" fi if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi #AC_ARG_WITH(vm-sound-null, #[ --without-vm-sound-null disable null vm sound support [default=enabled]], # [with_vm_sound_null="$withval"], # [with_vm_sound_null="yes"]) #if test "$with_vm_sound_null"="no"; then # AC_PLUGIN_DISABLE_PLUGIN(vm-sound-null); #fi # Check whether --with-vm-sound-OSS or --without-vm-sound-OSS was given. if test "${with_vm_sound_OSS+set}" = set; then withval="$with_vm_sound_OSS" with_vm_sound_OSS="$withval" else with_vm_sound_OSS="yes" fi; if test "$with_vm_sound_OSS"="no"; then echo "$as_me:$LINENO: result: ******** disabling vm-sound-OSS" >&5 echo "${ECHO_T}******** disabling vm-sound-OSS" >&6 disabled_plugins="${disabled_plugins} vm-sound-OSS"; fi # Check whether --with-vm-display-fbdev or --without-vm-display-fbdev was given. if test "${with_vm_display_fbdev+set}" = set; then withval="$with_vm_display_fbdev" with_vm_display_fbdev="$withval" else with_display_fbdev="yes" fi; if test "$with_display_fbdev"="no"; then echo "$as_me:$LINENO: result: ******** disabling vm-display-fbdev" >&5 echo "${ECHO_T}******** disabling vm-display-fbdev" >&6 disabled_plugins="${disabled_plugins} vm-display-fbdev"; fi # Plugins not generated by VMM must be listed here... int_plugins="" ext_plugins="" #if test "$have_x" = "no"; then # AC_PLUGIN_DISABLE_PLUGIN(UnixOSProcessPlugin) #fi if test "${disabled_plugins}" != ""; then echo ${disabled_plugins} | tr ' ' '\012' | sort -u > plugins.exc fi # for some reason configure leaves an empty a.out lying around test -f a.out && rm a.out # Create the build environment ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files mkconfig make.cfg make.int make.ext make.prg inisqueak squeak.sh bin.squeak.sh Makefile" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # cfgdir=${cfgdir} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "mkconfig" ) CONFIG_FILES="$CONFIG_FILES mkconfig" ;; "make.cfg" ) CONFIG_FILES="$CONFIG_FILES make.cfg" ;; "make.int" ) CONFIG_FILES="$CONFIG_FILES make.int" ;; "make.ext" ) CONFIG_FILES="$CONFIG_FILES make.ext" ;; "make.prg" ) CONFIG_FILES="$CONFIG_FILES make.prg" ;; "inisqueak" ) CONFIG_FILES="$CONFIG_FILES inisqueak" ;; "squeak.sh" ) CONFIG_FILES="$CONFIG_FILES squeak.sh" ;; "bin.squeak.sh" ) CONFIG_FILES="$CONFIG_FILES bin.squeak.sh" ;; "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@NM@,$NM,;t t s,@LD@,$LD,;t t s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@topdir@,$topdir,;t t s,@cfgdir@,$cfgdir,;t t s,@vmmdir@,$vmmdir,;t t s,@vmmcfg@,$vmmcfg,;t t s,@blddir@,$blddir,;t t s,@SQ_MAJOR@,$SQ_MAJOR,;t t s,@SQ_MINOR@,$SQ_MINOR,;t t s,@SQ_UPDATE@,$SQ_UPDATE,;t t s,@SQ_VERSION@,$SQ_VERSION,;t t s,@VM_MAJOR@,$VM_MAJOR,;t t s,@VM_MINOR@,$VM_MINOR,;t t s,@VM_RELEASE@,$VM_RELEASE,;t t s,@VM_VERSION@,$VM_VERSION,;t t s,@imgdir@,$imgdir,;t t s,@expanded_relative_imgdir@,$expanded_relative_imgdir,;t t s,@plgdir@,$plgdir,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@WFLAGS@,$WFLAGS,;t t s,@AS@,$AS,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@LN@,$LN,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@SED@,$SED,;t t s,@LN_S@,$LN_S,;t t s,@ECHO@,$ECHO,;t t s,@AR@,$AR,;t t s,@ac_ct_AR@,$ac_ct_AR,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@CXX@,$CXX,;t t s,@CXXFLAGS@,$CXXFLAGS,;t t s,@ac_ct_CXX@,$ac_ct_CXX,;t t s,@CXXCPP@,$CXXCPP,;t t s,@F77@,$F77,;t t s,@FFLAGS@,$FFLAGS,;t t s,@ac_ct_F77@,$ac_ct_F77,;t t s,@LIBTOOL@,$LIBTOOL,;t t s,@INCLUDES@,$INCLUDES,;t t s,@HAVE_INTERP_H@,$HAVE_INTERP_H,;t t s,@ALLOCA@,$ALLOCA,;t t s,@INTERP@,$INTERP,;t t s,@AWK@,$AWK,;t t s,@VM_APP_ICONS@,$VM_APP_ICONS,;t t s,@npsqueak@,$npsqueak,;t t s,@install_nps@,$install_nps,;t t s,@uninstall_nps@,$uninstall_nps,;t t s,@SQ_LIBDIR@,$SQ_LIBDIR,;t t s,@int_modules@,$int_modules,;t t s,@ext_modules@,$ext_modules,;t t s,@HAVE_LANGINFO_CODESET@,$HAVE_LANGINFO_CODESET,;t t s,@HAVE_NANOSLEEP@,$HAVE_NANOSLEEP,;t t s,@X_CFLAGS@,$X_CFLAGS,;t t s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t s,@X_LIBS@,$X_LIBS,;t t s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t s,@X_CPPFLAGS@,$X_CPPFLAGS,;t t s,@X_INCLUDES@,$X_INCLUDES,;t t s,@LIBM_CFLAGS@,$LIBM_CFLAGS,;t t s,@LIB_UUID@,$LIB_UUID,;t t s,@int_plugins@,$int_plugins,;t t s,@ext_plugins@,$ext_plugins,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t /@make_cfg@/r $make_cfg s,@make_cfg@,,;t t /@make_int@/r $make_int s,@make_int@,,;t t /@make_ext@/r $make_ext s,@make_ext@,,;t t /@make_prg@/r $make_prg s,@make_prg@,,;t t /@Makefile_install@/r $Makefile_install s,@Makefile_install@,,;t t /@Makefile_dist@/r $Makefile_dist s,@Makefile_dist@,,;t t /@Makefile_rpm@/r $Makefile_rpm s,@Makefile_rpm@,,;t t /@Makefile_deb@/r $Makefile_deb s,@Makefile_deb@,,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in default ) chmod +x mkconfig inisqueak ${SHELL} -ec "./mkconfig; ${cfgdir}/mktargets; ${cfgdir}/mkmf" ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi ================================================ FILE: vm/src/from_squeak/unix/config/configure.ac ================================================ # configure.in (version 4) for Unix Squeak -*- sh -*- # # Process this file with autoconf to produce a configure script # Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: Ian.Piumarta@SqueakLand.org # # Last edited: Tue Jan 26 11:51:29 PST 2010 by eliot AC_INIT([config.h.in]) AC_VM_VERSION(3,9,7, 3,9a,7024) topdir=`cd ${srcdir}/../../..; pwd` cfgdir=`cd ${srcdir}; pwd` AC_ARG_WITH(src, [ --with-src=dir generated src directory [default=src]], [ vmmsrc="${with_src}"], [ vmmsrc="src"]) vmmdir="${topdir}/${vmmsrc}" if test ! -d "${topdir}/${vmmsrc}"; then if test -d "${topdir}/platforms/unix/${vmmsrc}"; then vmmdir="${topdir}/platforms/unix/${vmmsrc}" AC_MSG_RESULT([using built-in src directory]) fi fi AC_MSG_RESULT(${vmmdir}) blddir=`pwd` AC_ARG_WITH(vmmcfg, [ --with-vmmcfg=dir vm configuration directory containing plugins.int and plugins.ext [default=.]], [ vmmcfg="${with-vmmcfg}"], [ vmmcfg="${blddir}"]) # Check the generated src dir looks sane AC_CHECK_VMM_DIR AC_SUBST(topdir) AC_SUBST(cfgdir) AC_SUBST(vmmdir) AC_SUBST(vmmcfg) AC_SUBST(blddir) SQ_VERSION=${SQ_MAJOR}.${SQ_MINOR}-${SQ_UPDATE} AC_DEFINE_UNQUOTED(SQ_VERSION, "${SQ_VERSION}") AC_SUBST(SQ_MAJOR) AC_SUBST(SQ_MINOR) AC_SUBST(SQ_UPDATE) AC_SUBST(SQ_VERSION) VM_VERSION=${VM_MAJOR}.${VM_MINOR}-${VM_RELEASE} AC_DEFINE_UNQUOTED(VM_VERSION, "${VM_VERSION}") AC_SUBST(VM_MAJOR) AC_SUBST(VM_MINOR) AC_SUBST(VM_RELEASE) AC_SUBST(VM_VERSION) # libdir contains ${exec_prefix}, so we have to default and expand early test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' imgdir=`eval echo ${libdir}/squeak` expanded_relative_imgdir=`eval echo lib/squeak/${VM_VERSION}` plgdir='${imgdir}/'`eval echo ${VM_VERSION}` AC_SUBST(imgdir) AC_SUBST(expanded_relative_imgdir) AC_SUBST(plgdir) AC_DEFINE(OS_TYPE, "unix") AC_CANONICAL_HOST host_cpu=`echo $host | sed 's,-.*,,'` host=`echo $host | sed 's,-unknown,,'` AC_SUBST(host) AC_SUBST(host_cpu) AC_SUBST(host_vendor) AC_SUBST(host_os) AC_DEFINE_UNQUOTED(VM_HOST, "$host") AC_DEFINE_UNQUOTED(VM_HOST_OS, "$host_os") AC_DEFINE_UNQUOTED(VM_HOST_CPU, "$host_cpu") echo echo "Configuring Squeak ${VM_VERSION} (${SQ_VERSION}) for ${host}" echo # Checks for programs. AC_ARG_WITH(gnu-awk, [ --with-gnu-awk assume that awk is GNU gawk [default=no]], [GAWK="$withval"], [case $host_os in darwin*) GAWK="yes";; *) GAWK="unknown";; esac]) AC_ARG_WITH(gnu-as, [ --with-gnu-as assume that as is the GNU assembler [default=no]], [GAS="$withval"], [GAS="unknown"]) AC_PROG_MAKE_SET AC_PROG_CC_WALL AC_PROG_AS_GNU AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_NM AC_CHECK_PROG(LN, ln, ln) # Check size assumptions of basic data types AC_REQUIRE_SIZEOF(int, 4) AC_REQUIRE_SIZEOF(double, 8) AC_CHECK_INT64_T AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(void *) # libtool configuration AC_DISABLE_STATIC AC_PROG_LIBTOOL # Configured headers (pretty much everybody needs blddir and vm) INCLUDES="-I${blddir} -I${vmmcfg} -I${topdir}/platforms/unix/vm -I${topdir}/platforms/Cross/vm -I${vmmdir}/vm" AC_SUBST(INCLUDES) # Checks for header files. AC_NEED_SUNOS_H AC_STDC_HEADERS AC_HAVE_HEADERS(unistd.h string.h fcntl.h sys/file.h sys/param.h) AC_HAVE_HEADERS(sys/time.h sys/filio.h sys/select.h) AC_HAVE_HEADERS(features.h) AC_HAVE_HEADERS(alloca.h) # SunOS5 AC_HEADER_TIME AC_HEADER_DIRENT if test -f "${vmmdir}/vm/interp.h"; then AC_DEFINE(HAVE_INTERP_H, 1) fi AC_SUBST(HAVE_INTERP_H) AC_STRUCT_TIMEZONE AC_CHECK_SOCKLEN_T AC_CHECK_ATEXIT AC_CHECK_TZSET AC_CHECK_GMTOFF AC_CHECK_TIMEZONE AC_CHECK_GETHOSTNAME # Display options. AC_ARG_WITH(rfb, [ --without-rfb disable Remote FrameBuffer support [default=enabled]], [have_rfb="$withval"], [have_rfb="no"]) test $have_rfb = "yes" && AC_DEFINE(USE_RFB,[1]) # Checks for libraries. AC_CHECK_LIB(nsl, yp_bind) AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(m, sin) AC_CHECK_LIB(pthread, pthread_create) # this seems to add no benefit #AC_CHECK_LIB(rt, clock_nanosleep) #AC_CHECK_FUNC(dlopen, [ # AC_DEFINE(HAVE_LIBDL,[1]) #],[ # AC_CHECK_LIB(dl, dlopen, [ # LIBS="-ldl $LIBS" # AC_DEFINE(HAVE_LIBDL,[1]) # ],[ # AC_CHECK_FUNC(_dyld_present, [ # AC_DEFINE(HAVE_DYLD,[1]) # ]) # ]) #]) AC_CHECK_FUNC(_dyld_present, [ AC_DEFINE(HAVE_DYLD,[1]) ],[ AC_HAVE_HEADERS(dlfcn.h) AC_CHECK_FUNC(dlopen, [ AC_DEFINE(HAVE_LIBDL,[1]) ],[ AC_CHECK_LIB(dl, dlopen, [ LIBS="-ldl $LIBS" AC_DEFINE(HAVE_LIBDL,[1]) ]) ]) ]) AC_CHECK_FUNCS(snprintf __snprintf,[break]) AC_FUNC_MMAP AC_FUNC_ALLOCA #AC_ARG_ENABLE(jit, #[ --enable-jit enable J4 support [default=no]], #JIT="yes", JIT="no") # #test $JIT = "yes" && J_CFLAGS="-DJ_ENABLED" #AC_SUBST(J_CFLAGS) # Checks for platform characteristics. AC_GNU_OPT AC_GNU_INTERP AC_MODULE_LIB_PREFIX AC_64BIT_ARCH CFLAGS="$CFLAGS_32 $CFLAGS -msse" AC_C_BYTEORDER AC_C_DOUBLE_ALIGNMENT case $host_os in darwin*) AC_DEFINE(DARWIN,[1]) # CFLAGS="-no-cpp-precomp $CFLAGS" with_npsqueak=no VM_APP_ICONS="${imgdir}/SqueakVM.icns" ;; *) VM_APP_ICONS="" ;; esac AC_SUBST(VM_APP_ICONS) # Checks for browser support AC_SUBST(npsqueak) AC_SUBST(install_nps) AC_SUBST(uninstall_nps) AC_ARG_WITH(npsqueak, [ --without-npsqueak disable browser plugin support [default=enabled]], [with_npsqueak="$withval"], [with_npsqueak="yes"]) if test "$with_npsqueak" = "no"; then npsqueak="" install_nps="" uninstall_nps="" else npsqueak=npsqueak install_nps=install-npsqueak uninstall_nps=uninstall-npsqueak fi # Install locations if test "x${prefix}" = xNONE; then SQ_LIBDIR=${ac_default_prefix}/lib/squeak/${SQ_VERSION} else SQ_LIBDIR=${prefix}/lib/squeak/${SQ_VERSION} fi AC_SUBST(SQ_LIBDIR) AC_DEFINE_UNQUOTED(SQ_LIBDIR,["${SQ_LIBDIR}"]) # Configure files make_cfg=${blddir}/make.cfg make_int=${blddir}/make.int make_ext=${blddir}/make.ext make_prg=${blddir}/make.prg AC_SUBST_FILE(make_cfg) AC_SUBST_FILE(make_int) AC_SUBST_FILE(make_ext) AC_SUBST_FILE(make_prg) Makefile_install=${cfgdir}/Makefile.install Makefile_dist=${topdir}/util/Makefile.dist Makefile_rpm=${topdir}/util/Makefile.rpm Makefile_deb=${topdir}/util/Makefile.deb AC_SUBST_FILE(Makefile_install) AC_SUBST_FILE(Makefile_dist) AC_SUBST_FILE(Makefile_rpm) AC_SUBST_FILE(Makefile_deb) # Configure VM modules xxx MAKE INTERNAL WORK int_modules="vm" ext_modules="`cd ${topdir}/platforms/unix; echo vm-*`" AC_SUBST(int_modules) AC_SUBST(ext_modules) # Configure plugins disabled_plugins="" rm -f plugins.exc sinclude(acplugins.m4) #AC_ARG_WITH(vm-sound-null, #[ --without-vm-sound-null disable null vm sound support [default=enabled]], # [with_vm_sound_null="$withval"], # [with_vm_sound_null="yes"]) #if test "$with_vm_sound_null"="no"; then # AC_PLUGIN_DISABLE_PLUGIN(vm-sound-null); #fi AC_ARG_WITH(vm-sound-OSS, [ --without-vm-sound-OSS disable OSS vm sound support [default=enabled]], [with_vm_sound_OSS="$withval"], [with_vm_sound_OSS="yes"]) if test "$with_vm_sound_OSS"="no"; then AC_PLUGIN_DISABLE_PLUGIN(vm-sound-OSS); fi AC_ARG_WITH(vm-display-fbdev, [ --without-vm-display-fbdev disable frame buffer vm display support [default=enabled]], [with_vm_display_fbdev="$withval"], [with_display_fbdev="yes"]) if test "$with_display_fbdev"="no"; then AC_PLUGIN_DISABLE_PLUGIN(vm-display-fbdev); fi # Plugins not generated by VMM must be listed here... int_plugins="" ext_plugins="" AC_SUBST(int_plugins) AC_SUBST(ext_plugins) #if test "$have_x" = "no"; then # AC_PLUGIN_DISABLE_PLUGIN(UnixOSProcessPlugin) #fi if test "${disabled_plugins}" != ""; then echo ${disabled_plugins} | tr ' ' '\012' | sort -u > plugins.exc fi # for some reason configure leaves an empty a.out lying around test -f a.out && rm a.out # Create the build environment AC_CONFIG_HEADER(config.h) AC_CONFIG_FILES(mkconfig make.cfg make.int make.ext make.prg inisqueak squeak.sh bin.squeak.sh Makefile) AC_CONFIG_COMMANDS([default],[ chmod +x mkconfig inisqueak ${SHELL} -ec "./mkconfig; ${cfgdir}/mktargets; ${cfgdir}/mkmf"],[ cfgdir=${cfgdir} ]) AC_OUTPUT ================================================ FILE: vm/src/from_squeak/unix/config/gnuify ================================================ #!/usr/bin/gawk -f # # Rewrite the interpreter source in $1 to use GNU C extensions, writing the # modified file to stdout. # # Author: Ian.Piumarta@INRIA.Fr # # Last edited: 2006-10-18 10:14:33 by piumarta on emilia.local # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. BEGIN { print "/* This file has been post-processed for GNU C */\n\n"; # print "copying first section of file" > "/dev/stderr"; stage= 0; } /#include "sq.h"/ { print "#include \"sqGnu.h\"\n"; next; } # An inlining comment means the interpreter was not inlined /inline\: true/ { # print NR, $0 > "/dev/stderr"; # print "" > "/dev/stderr"; # print "*** interpreter was not inlined: bailing out! ***" > "/dev/stderr"; # print "" > "/dev/stderr"; stage= -1; } (stage == 0) && /^int interpret\(void\) \{/ { # print "interpret: adding static register assignments" > "/dev/stderr"; stage= 1; print; next; } (stage == 0) && /^sqInt interpret\(void\) \{/ { # print "interpret: adding static register assignments" > "/dev/stderr"; stage= 1; print; next; } (stage == 1) && /^ char\* localIP;/ { print " register char* localIP IP_REG;"; next; } (stage == 1) && /^register struct foo \* foo = &fum;/ { print " register struct foo * foo GP_REG= &fum;"; next; } (stage == 1) && /^ char\* localSP;/ { print " register char* localSP SP_REG;"; next; } (stage == 1) && /^ int currentBytecode;/ { print " register int currentBytecode CB_REG;"; next; } (stage == 1) && /^ sqInt currentBytecode;/ { print " register int currentBytecode CB_REG;"; next; } (stage == 1) && /^$/ { # print "interpret: adding bytecode dispatch table" > "/dev/stderr"; print " JUMP_TABLE;\n"; # print "interpret: rewriting case labels and outer breaks" > "/dev/stderr"; stage= 2; FS=" "; # FS="[ :]+"; next; } (stage == 2) && /^ case / { print " CASE(" (($NF) + 0) ")"; # print " CASE(" $3 ")"; next; } (stage == 2) && /^ break;/ { print " BREAK;"; next; } (stage == 2) && /^\}/ { stage= -1; print; next; } (stage == 3) && /^int primitiveResponse\(/ { print; # print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr"; print " PRIM_TABLE;\n"; # print "primitiveResponse: rewriting case labels" > "/dev/stderr"; stage= 4; FS=" "; # FS="[ :]+"; next; } (stage == 3) && /^sqInt primitiveResponse\(/ { print; # print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr"; print " PRIM_TABLE;\n"; # print "primitiveResponse: rewriting case labels" > "/dev/stderr"; stage= 4; FS=" "; # FS="[ :]+"; next; } (stage == 4) && /^ switch \(primitiveIndex\) \{/ { # print "primitiveResponse: adding primitive dispatch" > "/dev/stderr"; print " PRIM_DISPATCH;"; print; next; } (stage == 4) && /^ switch \(foo->primitiveIndex\) \{/ { # print "primitiveResponse: adding primitive dispatch" > "/dev/stderr"; print " PRIM_DISPATCH;"; print; next; } (stage == 4) && /^ case / { print " CASE(" (($NF) + 0) ")"; # print " CASE(" $3 ")"; next; } (stage == 4) && /^\}/ { # print "copying last section of file" > "/dev/stderr"; stage= -1; FS=" "; print; next; } # default { print; next; } END { if (stage != -1) { print "#error GNUIFICATION FAILED (", stage, ")" } } ================================================ FILE: vm/src/from_squeak/unix/config/inisqueak.in ================================================ #!/bin/sh # # inisqueak -- setup a directory for use with Squeak # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: Ian.Piumarta@INRIA.Fr # # Last edited: 2006-10-18 10:14:20 by piumarta on emilia.local MAJOR=@SQ_MAJOR@ VERSION=@SQ_VERSION@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ imgdir=@imgdir@ plgdir=@plgdir@ if test ! -w .; then echo "You don't have write permission in this directory." >&2 exit 1 fi # Sun's /bin/sh does not understand "test -e", but [/usr]/bin/test does test="`which test`" list=false startup=true batch=false interactive=true while true; do case "$1" in -l) list=true; shift;; -n) startup=false; shift;; -b) batch=true; interactive=false; shift;; -h|-help|--help) echo "`basename $0` [-option...] [rootdir]" echo ' -b batch (avoid interaction, exit status reflects success)' echo ' -h you already know about' echo ' -help same as -h' echo ' -l always present a list of alternative images (overrides -b)' echo ' -n do not run Squeak after installing the files' echo ' --help same as -help' exit 0;; *) break;; esac done if test "$1" != ""; then bindir=${1}/${bindir} imgdir=${1}/${imgdir} plgdir=${1}/${plgdir} fi SQUEAK=${bindir}/squeak SOURCES=SqueakV${MAJOR}.sources IMAGE=squeak.image.gz CHANGES=squeak.changes.gz # local install function missing() { echo "The file ${1} is missing." >&2 echo "Please check your Squeak installation." >&2 exit 1 } if ${test} \( -f squeak.image \) -a \( -f squeak.changes \) -a \( -e ${SOURCES} \) then if ${startup}; then if test ! -x ${SQUEAK}; then missing "${SQUEAK}" fi if ${interactive}; then echo "Running ${SQUEAK}"; fi exec ${SQUEAK} else if ${interactive}; then echo "Squeak is already installed in this directory" >&2 fi exit 1 fi fi install() { cpy="${1}" src="${2}" red="${3}" dst="${4}" if ${test} ! -e ${dst}; then if ${test} -e ${src}; then if ${interactive}; then echo "+ ${cpy} ${src} ${red} ${dst}"; fi eval ${cpy} ${src} ${red} ${dst} else missing "${src}" fi else echo "${dst} is already present -- leaving it alone" # startup=false fi } # choose an image to install if ${list}; then :; else if ${test} \( ! -e ${imgdir}/${IMAGE} \) \ -o \( ! -e ${imgdir}/${CHANGES} \) ; then if ${batch}; then echo "Could not find default image to install -- giving up." >&2 exit 1; fi list=true echo "No default image, looking for alternatives..." echo fi fi if ${list}; then images=`ls -1 ${imgdir}/*.image.gz 2>/dev/null | \ sed "s.${imgdir}/..;s/.image.gz//"` if test "$images" = ""; then echo "I could not find an image to install." >&2 echo "Please check your Squeak installation." >&2 exit 1 fi nimg=`echo ${images} | tr ' ' '\012' | wc -l` nimg=`echo ${nimg}` more=true while ${more}; do echo "I found the following images:" echo ${images} | tr ' ' '\012' | cat -n if echo ${images} | fgrep "Squeak${VERSION}" >/dev/null; then echo "(of which I might recommend Squeak${VERSION}, unless you know better)." fi echo -n "Which one should I install [1-${nimg}]? " read reply case ${reply} in [1-9]) ;; [1-9][0-9]) ;; *) echo echo "Let's try that again, with a NUMBER between 1 and ${nimg}." echo continue;; esac if test \( ${reply} -ge 1 \) -a \( ${reply} -le ${nimg} \); then more=false fi if ${more}; then echo echo "Ha ha, very clever. Now give me a number between 1 and ${nimg}" echo "(or hit your interrupt key [^C or whatever] if you don't like" echo "the look of any of them)." echo fi done IMAGE=`echo ${images} | tr ' ' '\012' | tail +${reply} | head -1` CHANGES=${IMAGE}.changes.gz IMAGE=${IMAGE}.image.gz fi if ${interactive}; then echo "Installing ${IMAGE} in `pwd`"; fi install "ln -s" "${imgdir}/${SOURCES}" " " "${SOURCES}" install "gunzip -dc" "${imgdir}/${IMAGE}" ">" "squeak.image" install "gunzip -dc" "${imgdir}/${CHANGES}" ">" "squeak.changes" if ${startup}; then if test ! -x ${SQUEAK}; then missing "${SQUEAK}" fi if ${interactive}; then echo "Running ${SQUEAK}"; fi exec ${SQUEAK} fi ================================================ FILE: vm/src/from_squeak/unix/config/install-sh ================================================ #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" # CYGNUS LOCAL: exeext variable exeext="" # END CYGNUS LOCAL while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; # CYGNUS LOCAL: -x option -x=*) exeext=`echo $1 | sed 's/-x=//'` shift continue;; -x) exeext=".exe" shift continue;; # END CYGNUS LOCAL *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # CYGNUS LOCAL noer # Win32-based gcc automatically appends .exe to produced executables, # whether asked for or not. This breaks installs. The following # changes the value of $src to $src.exe if $src is missing if [ -f $src ] then true elif [ -f $src.exe ] then echo "install: $src does not exist, trying with .exe appended" src="$src".exe fi # end CYGNUS LOCAL noer # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi # CYGNUS LOCAL: Use exeext case "`basename $dst`" in *.*) ;; *) dst="$dst$exeext" ;; esac # END CYGNUS LOCAL fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 ================================================ FILE: vm/src/from_squeak/unix/config/ltcf-c.sh ================================================ #### This script is meant to be sourced by ltconfig. # ltcf-c.sh - Create a C compiler specific configuration # # Copyright (C) 1996-2000, 2001 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='main(){return(0);}' ## Linker Characteristics case $host_os in cygwin* | mingw*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$with_gcc" != yes; then with_gnu_ld=no fi ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken ld_shlibs=no cat <<EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //; p; }" -e d < $0 > $output_objdir/impgen.c~ test -f $output_objdir/impgen.exe || (cd $output_objdir && \ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ else $CC -o impgen impgen.c ; fi)~ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' # cygwin and mingw dlls have different entry points and sets of symbols # to exclude. # FIXME: what about values for MSVC? dll_entry=__cygwin_dll_entry@12 dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ case $host_os in mingw*) # mingw values dll_entry=_DllMainCRTStartup@12 dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ ;; esac # mingw and cygwin differ, and it's simplest to just exclude the union # of the two symbol sets. dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one (in ltdll.c) if test "x$lt_cv_need_dllmain" = "xyes"; then ltdll_obj='$output_objdir/$soname-ltdll.'"$objext " ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $output_objdir/$soname-ltdll.c~ test -f $output_objdir/$soname-ltdll.$objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' else ltdll_obj= ltdll_cmds= fi # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. # Be careful not to strip the DATA tag left be newer dlltools. export_symbols_cmds="$ltdll_cmds"' $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is. # If DATA tags from a recent dlltool are present, honour them! archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname-def; else echo EXPORTS > $output_objdir/$soname-def; _lt_hint=1; cat $export_symbols | while read symbol; do set dummy \$symbol; case \[$]# in 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;; esac; _lt_hint=`expr 1 + \$_lt_hint`; done; fi~ '"$ltdll_cmds"' $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' ;; darwin* | rhapsody*) allow_undefined_flag='-undefined suppress' if test .$module = .yes; then archive_cmds='$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts' else archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts -install_name $rpath/$soname `test -n "$verstring" -a x$verstring != x0.0 && echo $verstring`' fi # We need to add '_' to the symbols in $export_symbols first #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' hardcode_direct=yes hardcode_shlibpath_var=no whole_archive_flag_spec='-all_load $convenience' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$with_gcc" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. if test "$with_gcc" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # Test if we are trying to use run time linking, or normal AIX style linking. # If -brtl is somewhere in LDFLAGS, we need to do run time linking. aix_use_runtimelinking=no for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl" ); then aix_use_runtimelinking=yes break fi done exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # -bexpall does not export symbols beginning with underscore (_) always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other run time loading flags (-brtl), -berok will # link without error, but may produce a broken library. allow_undefined_flag=' ${wl}-berok' hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else allow_undefined_flag=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec=' ' build_libtool_need_lc=yes hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case $host_os in hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6*) if test "$with_gcc" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$with_gcc" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$with_gcc" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # cc supports -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag=' -z defs' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5uw7* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi ## Compiler Characteristics: PIC flags, static flags, etc if test "X${ac_cv_prog_cc_pic+set}" = Xset; then : else ac_cv_prog_cc_pic= ac_cv_prog_cc_shlib= ac_cv_prog_cc_wl= ac_cv_prog_cc_static= ac_cv_prog_cc_no_builtin= ac_cv_prog_cc_can_build_shared=$can_build_shared if test "$with_gcc" = yes; then ac_cv_prog_cc_wl='-Wl,' ac_cv_prog_cc_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_cv_prog_cc_static='-Bstatic' else lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. ac_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; cygwin* | mingw* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). ac_cv_prog_cc_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_cv_prog_cc_pic='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all ac_cv_prog_cc_pic= ;; sysv4*MP*) if test -d /usr/nec; then ac_cv_prog_cc_pic=-Kconform_pic fi ;; *) ac_cv_prog_cc_pic='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case $host_os in aix*) # All AIX code is PIC. ac_cv_prog_cc_static="$ac_cv_prog_cc_static ${ac_cv_prog_cc_wl}-lC" ;; hpux9* | hpux10* | hpux11*) # Is there a better ac_cv_prog_cc_static that works with the bundled CC? ac_cv_prog_cc_wl='-Wl,' ac_cv_prog_cc_static="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" ac_cv_prog_cc_pic='+Z' ;; irix5* | irix6*) ac_cv_prog_cc_wl='-Wl,' ac_cv_prog_cc_static='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). ac_cv_prog_cc_pic='-DDLL_EXPORT' ;; newsos6) ac_cv_prog_cc_pic='-KPIC' ac_cv_prog_cc_static='-Bstatic' ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. ac_cv_prog_cc_wl='-Wl,' ac_cv_prog_cc_static='-non_shared' ;; sco3.2v5*) ac_cv_prog_cc_pic='-Kpic' ac_cv_prog_cc_static='-dn' ac_cv_prog_cc_shlib='-belf' ;; solaris*) ac_cv_prog_cc_pic='-KPIC' ac_cv_prog_cc_static='-Bstatic' ac_cv_prog_cc_wl='-Wl,' ;; sunos4*) ac_cv_prog_cc_pic='-PIC' ac_cv_prog_cc_static='-Bstatic' ac_cv_prog_cc_wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) ac_cv_prog_cc_pic='-KPIC' ac_cv_prog_cc_static='-Bstatic' ac_cv_prog_cc_wl='-Wl,' ;; uts4*) ac_cv_prog_cc_pic='-pic' ac_cv_prog_cc_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then ac_cv_prog_cc_pic='-Kconform_pic' ac_cv_prog_cc_static='-Bstatic' fi ;; *) ac_cv_prog_cc_can_build_shared=no ;; esac fi case "$host_os" in # Platforms which do not suport PIC and -DPIC is meaningless # on them: *djgpp*) ac_cv_prog_cc_pic= ;; *) ac_cv_prog_cc_pic="$ac_cv_prog_cc_pic -DPIC" ;; esac fi need_lc=yes if test "$enable_shared" = yes && test "$with_gcc" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo $ac_n "checking whether -lc should be explicitly linked in... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_archive_cmds_needs_lc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 need_lc=$ac_cv_archive_cmds_needs_lc else $rm conftest* echo "static int dummy;" > conftest.$ac_ext if { (eval echo ltcf-c.sh:need_lc: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then # Append any warnings to the config.log. cat conftest.err 1>&5 soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$ac_cv_prog_cc_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo ltcf-c.sh:need_lc: \"$archive_cmds\") 1>&5; (eval $archive_cmds) 2>&1 | grep " -lc " 1>&5 ; }; then need_lc=no fi allow_undefined_flag=$save_allow_undefined_flag else cat conftest.err 1>&5 fi fi $rm conftest* echo "$ac_t$need_lc" 1>&6 ;; esac fi ac_cv_archive_cmds_needs_lc=$need_lc ================================================ FILE: vm/src/from_squeak/unix/config/ltconfig ================================================ #! /bin/sh # ltconfig - Create a system-specific libtool. # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A lot of this script is taken from autoconf-2.10. # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} echo=echo if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec "$SHELL" "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<EOF $* EOF exit 0 fi # Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) PATH_SEPARATOR=';' ;; *) PATH_SEPARATOR=':' ;; esac fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string="`eval $cmd`") 2>/dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running ltconfig again with it. ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec "${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}}" "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # The name of this program. progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` # Constants: PROGRAM=ltconfig PACKAGE=libtool VERSION=1.4a TIMESTAMP=" (1.641.2.255 2001/05/22 10:39:30)" ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' rm="rm -f" help="Try \`$progname --help' for more information." # Global variables: default_ofile=libtool can_build_shared=yes enable_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). enable_static=yes enable_fast_install=yes enable_dlopen=unknown enable_win32_dll=no pic_mode=default ltmain= silent= srcdir= ac_config_guess= ac_config_sub= host= build=NONE nonopt=NONE ofile="$default_ofile" verify_host=yes tagname= with_gcc=no with_gnu_ld=no need_locks=yes ac_ext=c libext=a cache_file= max_cmd_len= ## Dependencies to place before and after the object being linked: predep_objects= postdep_objects= predeps= postdeps= compiler_lib_search_path= ## Link characteristics: allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= striplib= old_striplib= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_into_libs=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= link_all_deplibs=unknown always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= ## Tools: old_AR="$AR" old_AR_FLAGS="$AR_FLAGS" old_CC="$CC" old_CFLAGS="$CFLAGS" old_CPPFLAGS="$CPPFLAGS" old_LDFLAGS="$LDFLAGS" old_LIBS="$LIBS" old_MAGIC_CMD="$MAGIC_CMD" old_LD="$LD" old_LN_S="$LN_S" old_LTCC="$LTCC" old_NM="$NM" old_RANLIB="$RANLIB" old_STRIP="$STRIP" old_AS="$AS" old_DLLTOOL="$DLLTOOL" old_OBJDUMP="$OBJDUMP" old_OBJEXT="$OBJEXT" old_EXEEXT="$EXEEXT" old_reload_flag="$reload_flag" old_deplibs_check_method="$deplibs_check_method" old_file_magic_cmd="$file_magic_cmd" # Parse the command line options. args= prev= for option do case $option in -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then eval "$prev=\$option" prev= continue fi case $option in --help) cat <<EOM Usage: $progname [OPTION]... LTMAIN [HOST] Generate a system-specific libtool script. --build configure for building on BUILD [BUILD=HOST] --debug enable verbose shell tracing --disable-shared do not build shared libraries --disable-static do not build static libraries --disable-fast-install do not optimize for fast installation --enable-dlopen enable dlopen support --enable-win32-dll enable building dlls on win32 hosts --help display this help and exit --no-verify do not verify that HOST is a valid host type -o, --output=FILE specify the output file [default=$default_ofile] --quiet same as \`--silent' --silent do not print informational messages --srcdir=DIR find \`config.guess' in DIR --version output version information and exit --add-tag=TAG append an alternate configuration --with-gcc assume that the GNU C compiler will be used --with-gnu-ld assume that the C compiler uses the GNU linker --prefer-pic try to use only PIC objects --prefer-non-pic try to use only non-PIC objects --disable-lock disable file locking --cache-file=FILE configure cache file LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program that provides basic libtool functionality. HOST is the canonical host system name [default=guessed]. EOM exit 0 ;; --build) prev=build ;; --build=*) build="$optarg" ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --disable-shared) enable_shared=no ;; --disable-static) enable_static=no ;; --disable-fast-install) enable_fast_install=no ;; --enable-dlopen) enable_dlopen=yes ;; --enable-win32-dll) enable_win32_dll=yes ;; --quiet | --silent) silent=yes ;; --srcdir) prev=srcdir ;; --srcdir=*) srcdir="$optarg" ;; --no-verify) verify_host=no ;; --output | -o) prev=ofile ;; --output=*) ofile="$optarg" ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;; --add-tag) prev=tagname ;; --add-tag=*) tagname="$optarg" ;; --with-gcc) with_gcc=yes ;; --with-gnu-ld) with_gnu_ld=yes ;; --prefer-pic) pic_mode=yes ;; --prefer-non-pic) pic_mode=no ;; --disable-lock) need_locks=no ;; --cache-file=*) cache_file="$optarg" ;; -*) echo "$progname: unrecognized option \`$option'" 1>&2 echo "$help" 1>&2 exit 1 ;; *) if test -z "$ltmain"; then ltmain="$option" elif test -z "$host"; then # This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 # if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then # echo "$progname: warning \`$option' is not a valid host type" 1>&2 # fi host="$option" else echo "$progname: too many arguments" 1>&2 echo "$help" 1>&2 exit 1 fi ;; esac done if test -z "$ltmain"; then echo "$progname: you must specify a LTMAIN file" 1>&2 echo "$help" 1>&2 exit 1 fi if test ! -f "$ltmain"; then echo "$progname: \`$ltmain' does not exist" 1>&2 echo "$help" 1>&2 exit 1 fi if test -n "$tagname"; then # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's/[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]//g'` in "") ;; *) echo "$progname: invalid tag name: $tagname" 1>&2 exit 1 ;; esac if grep "^### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$ofile" > /dev/null; then echo "$progname: tag name $tagname already exists" 1>&2 exit 1 fi if test ! -f "$ofile"; then echo "$progname: warning: output file \`$ofile' does not exist" 1>&2 fi if test -z "$LTCC"; then eval "`$SHELL $ofile --config | grep '^LTCC='`" if test -z "$LTCC"; then echo "$progname: warning: output file \`$ofile' does not look like a libtool script" 1>&2 else echo "$progname: warning: using \`LTCC=$LTCC', extracted from \`$ofile'" 1>&2 fi fi fi # Quote any args containing shell metacharacters. ltconfig_args= for arg do case $arg in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ltconfig_args="$ltconfig_args '$arg'" ;; *) ltconfig_args="$ltconfig_args $arg" ;; esac done # A relevant subset of AC_INIT. # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 5 compiler messages saved in config.log # 6 checking for... messages and results if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>>./config.log # NLS nuisances. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi if test -n "$cache_file" && test -r "$cache_file" && test -f "$cache_file"; then echo "loading cache $cache_file within ltconfig" . $cache_file fi if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi if test -z "$srcdir"; then # Assume the source directory is the same one as the path to LTMAIN. srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` test "$srcdir" = "$ltmain" && srcdir=. fi trap "$rm conftest*; exit 1" 1 2 15 if test "$verify_host" = yes; then # Check for config.guess and config.sub. ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/config.guess; then ac_aux_dir=$ac_dir break fi done if test -z "$ac_aux_dir"; then echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 echo "$help" 1>&2 exit 1 fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub # Make sure we can run config.sub. if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : else echo "$progname: cannot run $ac_config_sub" 1>&2 echo "$help" 1>&2 exit 1 fi echo $ac_n "checking host system type""... $ac_c" 1>&6 host_alias=$host case $host_alias in "") # Force config.guess to use the C compiler. # CC_FOR_BUILD overrides the CC variable in config.guess but I had # problems with it so do it this way for now. CC="$LTCC" if host_alias=`$SHELL $ac_config_guess`; then : else echo "$progname: cannot guess host type; you must specify one" 1>&2 echo "$help" 1>&2 exit 1 fi # Restore the C compiler. CC="$old_CC" ;; esac host=`$SHELL $ac_config_sub $host_alias` echo "$ac_t$host" 1>&6 # Make sure the host verified. test -z "$host" && exit 1 # Check for the build system type echo $ac_n "checking build system type... $ac_c" 1>&6 build_alias=$build case $build_alias in NONE) case $nonopt in NONE) build_alias=$host_alias ;; *) build_alias=$nonopt ;; esac ;; esac build=`$SHELL $ac_config_sub $build_alias` build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$build" 1>&6 elif test -z "$host"; then echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 echo "$help" 1>&2 exit 1 else host_alias=$host build_alias=$host_alias build=$host fi if test x"$host" != x"$build"; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case $host_os in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" fi # Source the script associated with the $tagname tag configuration. if test -n "$tagname"; then . $ltmain else # FIXME: We should use a variable here # Configure for a C compiler . $srcdir/ltcf-c.sh fi # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$NM" && NM=nm test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$objext" && objext=o echo $ac_n "checking for objdir... $ac_c" 1>&6 rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null echo "$ac_t$objdir" 1>&6 # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. set dummy $CC compiler="$2" # We assume here that the value for ac_cv_prog_cc_pic will not be cached # in isolation, and that seeing it set (from the cache) indicates that # the associated values are set (in the cache) correctly too. echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 echo "$progname:678:checking for $compiler option to produce PIC" 1>&5 if test -z "$ac_cv_prog_cc_pic"; then echo "$ac_t"none 1>&6 else echo "$ac_t""$ac_cv_prog_cc_pic" 1>&6 # Check to make sure the pic_flag actually works. echo $ac_n "checking if $compiler PIC flag $ac_cv_prog_cc_pic works... $ac_c" 1>&6 echo "$progname:687:checking that $compiler PIC flag $ac_cv_prog_cc_pic works." 1>&5 if test "X${ac_cv_prog_cc_pic_works+set}" = Xset && \ test "X${ac_cv_prog_cc_pic_works}" != X; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_prog_cc_pic_works=yes $rm conftest* echo $lt_simple_compile_test_code > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_cv_prog_cc_pic -DPIC" if { (eval echo $progname:697: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then # Append any warnings to the config.log. cat conftest.err 1>&5 case $host_os in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then # they create non-PIC objects. So, if there were any warnings, we # assume that PIC is not supported. if test -s conftest.err; then ac_cv_prog_cc_pic_works=no ac_cv_prog_cc_can_build_shared=no ac_cv_prog_cc_pic= else ac_cv_prog_cc_pic_works=yes ac_cv_prog_cc_pic=" $ac_cv_prog_cc_pic" fi ;; *) ac_cv_prog_cc_pic_works=yes ac_cv_prog_cc_pic=" $ac_cv_prog_cc_pic" ;; esac else # Append any errors to the config.log. cat conftest.err 1>&5 ac_cv_prog_cc_pic_works=no ac_cv_prog_cc_can_build_shared=no ac_cv_prog_cc_pic= fi CFLAGS="$save_CFLAGS" $rm conftest* fi # Belt *and* braces to stop my trousers falling down: if test "X$ac_cv_prog_cc_pic_works" = Xno; then ac_cv_prog_cc_pic= ac_cv_prog_cc_can_build_shared=no fi echo "$ac_t""$ac_cv_prog_cc_pic_works" 1>&6 fi # Check for any special shared library compilation flags. if test -n "$ac_cv_prog_cc_shlib"; then echo "$progname: warning: \`$CC' requires \`$ac_cv_prog_cc_shlib' to build shared libraries" 1>&2 if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$ac_cv_prog_cc_shlib[ ]" >/dev/null; then : else echo "$progname: add \`$ac_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" 1>&2 ac_cv_prog_cc_can_build_shared=no fi fi echo $ac_n "checking if $compiler static flag $ac_cv_prog_cc_static works... $ac_c" 1>&6 echo "$progname:749: checking if $compiler static flag $ac_cv_prog_cc_static works" >&5 if test "X${ac_cv_prog_cc_static_works+set}" = Xset && \ test "X${ac_cv_prog_cc_static_works}" != X; then echo $ac_n "(cached) $ac_c" 1>&6 else $rm conftest* echo $lt_simple_link_test_code > conftest.$ac_ext save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $ac_cv_prog_cc_static" if { (eval echo $progname:758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_static_works=yes else ac_cv_prog_cc_static_works=no ac_cv_prog_cc_static= fi LDFLAGS="$save_LDFLAGS" $rm conftest* fi # Belt *and* braces to stop my trousers falling down: if test "X$ac_cv_prog_cc_static_works" = Xno; then ac_cv_prog_cc_static= fi echo "$ac_t""$ac_cv_prog_cc_static_works" 1>&6 pic_flag="$ac_cv_prog_cc_pic" special_shlib_compile_flags="$ac_cv_prog_cc_shlib" wl="$ac_cv_prog_cc_wl" link_static_flag="$ac_cv_prog_cc_static" no_builtin_flag="$ac_cv_prog_cc_no_builtin" can_build_shared="$ac_cv_prog_cc_can_build_shared" # find the maximum length of command line arguments echo "$progname:780: finding the maximum length of command line arguments" 1>&5 echo $ac_n "finding the maximum length of command line arguments... $ac_c" 1>&6 if test "${lt_cv_sys_max_cmd_len+set}" = set; then echo $ac_n "(cached) $ac_c" 1>&6 else i=0 testring="ABCD" # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while test "X"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ = "XX$testring" && new_result=`expr "X$testring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 18 # 1 MB should be enough do i=`expr $i + 1` testring=$testring$testring done testring= # add a significant safety factor because C++ compilers can tack on massive amounts # of additional arguments before passing them to the linker. 1/4 should be good. len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len - $len` fi echo "$progname:@lineno@: result: $lt_cv_sys_max_cmd_len" 1>&5 echo "${ac_t}$lt_cv_sys_max_cmd_len" 1>&6 if test -n $lt_cv_sys_max_cmd_len ; then max_cmd_len=$lt_cv_sys_max_cmd_len else max_cmd_len=none fi # Check to see if options -o and -c are simultaneously supported by compiler echo $ac_n "checking if $compiler supports -c -o file.$objext... $ac_c" 1>&6 if test "${lt_cv_compiler_c_o+set}" = set; then echo $ac_n "(cached) $ac_c" 1>&6 else $rm -r conftest 2>/dev/null mkdir conftest cd conftest $rm conftest* echo $lt_simple_compile_test_code > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$objext" echo "$progname:833: checking if $compiler supports -c -o file.$objext" >&5 if { (eval echo $progname:834: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then lt_cv_compiler_c_o=no else lt_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&5 lt_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null fi compiler_c_o=$lt_cv_compiler_c_o echo "${ac_t}$compiler_c_o" 1>&6 # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$ac_t$hard_links" 1>&6 $rm conftest* if test "$hard_links" = no; then echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 need_locks=warn fi else need_locks=no fi if test "$with_gcc" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 $rm conftest* echo $lt_simple_compile_test_code > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" echo "$progname:887: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 if { (eval echo $progname:888: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then echo "$ac_t"no 1>&6 compiler_rtti_exceptions=no else echo "$ac_t"yes 1>&6 compiler_rtti_exceptions=yes fi else # Append any errors to the config.log. cat conftest.err 1>&5 compiler_rtti_exceptions=no echo "$ac_t"no 1>&6 fi CFLAGS="$save_CFLAGS" $rm conftest* if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi # See if the linker supports building shared libraries. echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 echo "$ac_t$ld_shlibs" 1>&6 test "$ld_shlibs" = no && can_build_shared=no # Check hardcoding attributes. echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$ac_t$hardcode_action" 1>&6 echo $ac_n "checking whether stripping libraries is possible... $ac_c" 1>&6 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" echo "${ac_t}yes" 1>&6 else echo "${ac_t}no" 1>&6 fi case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' test -z "$deplibs_check_method" && deplibs_check_method=unknown # PORTME Fill in your ld.so characteristics library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH else # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. # We preserve .a as extension for shared libraries though AIX4.2 # and later linker supports .so if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so instead of # lib<name>.a to let people know that these are not typical AIX shared libraries. library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' else # We preserve .a as extension for shared libraries though AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}.so$major.o' fi # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | egrep '(GNU)' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi shlibpath_var=LIBPATH deplibs_check_method=pass_all case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. can_build_shared=no fi ;; esac fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows need_version=no need_lib_prefix=no case $with_gcc,$host_os in yes,cygwin*) library_names_spec='$libname.dll.a' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | [sed -e 's/[.]/-/g']`${versuffix}.dll' postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog .libs/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll; $rm \$dlpath' ;; yes,mingw*) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' ;; *) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}.`test .$module = .yes && echo so || echo dylib` ${libname}${release}${major}.$`test .$module = .yes && echo so || echo dylib` ${libname}.`test .$module = .yes && echo so || echo dylib`' soname_spec='${libname}${release}${major}.`test .$module = .yes && echo so || echo dylib`' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lc=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; *) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6*) version_type=irix need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' case $host_os in irix5*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) need_lib_prefix=no need_version=no version_type=sunos if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes sys_lib_dlsearch_path_spec="/usr/lib" sys_lib_search_path_spec="/usr/lib" ;; newsos6) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos if test "$with_gnu_ld" = yes; then need_lib_prefix=no need_version=no fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no soname_spec='${libname}${release}.so' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac echo "$ac_t$dynamic_linker" 1>&6 test "$dynamic_linker" = no && can_build_shared=no # Check for command to grab the raw symbol name followed by C symbol from nm. echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" ;; irix*) symcode='[BCDEGRST]' ;; solaris* | sysv5*) symcode='[BDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $host_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[ABCDGISTW]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no $rm conftest* cat > conftest.$ac_ext <<EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} EOF echo "$progname:1432: checking if global_symbol_pipe works" >&5 if { (eval echo $progname:1433: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then # Now try to grab the symbols. nlist=conftest.nm if { echo "$progname:1436: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat <<EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' cat <<EOF >> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$objext conftstm.$objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$objext" CFLAGS="$CFLAGS$no_builtin_flag" if { (eval echo $progname:1488: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then pipe_works=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi LIBS="$save_LIBS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi $rm conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else global_symbol_pipe= fi done if test "$pipe_works" = yes; then echo "${ac_t}ok" 1>&6 else echo "${ac_t}failed" 1>&6 fi if test -z "$global_symbol_pipe"; then global_symbol_to_cdecl= fi # Report the final consequences. echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 # Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in # configure.in, otherwise build static only libraries. case $host_os in cygwin* | mingw* | pw32* | os2*) if test x$can_build_shared = xyes; then test x$enable_win32_dll = xno && can_build_shared=no echo "checking if package supports dlls... $can_build_shared" 1>&6 fi ;; esac echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) test "$enable_shared" = yes && enable_static=no ;; esac echo "$ac_t$enable_shared" 1>&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "checking whether to build static libraries... $enable_static" 1>&6 if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$with_gcc" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # Check whether we must set pic_mode to default test -z "$pic_flag" && pic_mode=default if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else if test "X${lt_cv_dlopen+set}" != Xset; then lt_cv_dlopen=no lt_cv_dlopen_libs= echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 echo "$progname:1592: checking for dlopen in -ldl" >&5 if test "X${ac_cv_lib_dl_dlopen+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <<EOF #line 1599 "ltconfig" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen(); int main() { dlopen() ; return 0; } EOF if { (eval echo $progname:1612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_lib_dl_dlopen=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_lib_dl_dlopen=no fi rm -f conftest* LIBS="$ac_save_LIBS" fi if test "X$ac_cv_lib_dl_dlopen" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen""... $ac_c" 1>&6 echo "$progname:1631: checking for dlopen" >&5 if test "X${ac_cv_func_dlopen+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF #line 1636 "ltconfig" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen(); below. */ #include <assert.h> /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else dlopen(); #endif ; return 0; } EOF if { (eval echo $progname:1661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_dlopen=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_func_dlopen=no fi rm -f conftest* fi if test "X$ac_cv_func_dlopen" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6 echo "$progname:1678: checking for dlopen in -lsvld" >&5 if test "X${ac_cv_lib_svld_dlopen+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsvld $LIBS" cat > conftest.$ac_ext <<EOF #line 1685 "ltconfig" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen(); int main() { dlopen() ; return 0; } EOF if { (eval echo $progname:1698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_lib_svld_dlopen=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_lib_svld_dlopen=no fi rm -f conftest* LIBS="$ac_save_LIBS" fi if test "X$ac_cv_lib_svld_dlopen" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 echo "$progname:1717: checking for dld_link in -ldld" >&5 if test "X${ac_cv_lib_dld_dld_link+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <<EOF #line 1724 "ltconfig" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link(); int main() { dld_link() ; return 0; } EOF if { (eval echo $progname:1737: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_lib_dld_dld_link=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_lib_dld_dld_link=no fi rm -f conftest* LIBS="$ac_save_LIBS" fi if test "X$ac_cv_lib_dld_dld_link" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for shl_load""... $ac_c" 1>&6 echo "$progname:1756: checking for shl_load" >&5 if test "X${ac_cv_func_shl_load+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF #line 1761 "ltconfig" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load(); below. */ #include <assert.h> /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else shl_load(); #endif ; return 0; } EOF if { (eval echo $progname:1786: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_shl_load=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_func_shl_load=no fi rm -f conftest* fi if test "X$ac_cv_func_shl_load" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 echo "$progname:1804: checking for shl_load in -ldld" >&5 if test "X${ac_cv_lib_dld_shl_load+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <<EOF #line 1811 "ltconfig" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load(); int main() { shl_load() ; return 0; } EOF if { (eval echo $progname:1825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_lib_dld_shl_load=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_lib_dld_shl_load=no fi rm -f conftest* LIBS="$ac_save_LIBS" fi if test "X$ac_cv_lib_dld_shl_load" = Xyes; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else echo "$ac_t""no" 1>&6 fi fi fi fi fi fi fi if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) for ac_hdr in dlfcn.h; do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "$progname:1872: checking for $ac_hdr" >&5 if eval "test \"`echo 'X$''{'ac_cv_header_$ac_safe'+set}'`\" = Xset"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF #line 1877 "ltconfig" #include <$ac_hdr> int fnord = 0; int main () { return(0); } EOF ac_try="$ac_compile >/dev/null 2>conftest.out" { (eval echo $progname:1883: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi done if test "x$ac_cv_header_dlfcn_h" = xyes; then CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" fi eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" LIBS="$lt_cv_dlopen_libs $LIBS" echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 echo "$progname:1911: checking whether a program can dlopen itself" >&5 if test "X${lt_cv_dlopen_self+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then lt_cv_dlopen_self=cross else cat > conftest.$ac_ext <<EOF #line 1919 "ltconfig" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LTDL_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LTDL_GLOBAL DL_GLOBAL # else # define LTDL_GLOBAL 0 # endif #endif /* We may have to define LTDL_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LTDL_LAZY_OR_NOW # ifdef RTLD_LAZY # define LTDL_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LTDL_LAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LTDL_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LTDL_LAZY_OR_NOW DL_NOW # else # define LTDL_LAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42; } int main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } EOF if { (eval echo $progname:1966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then lt_cv_dlopen_self=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* lt_cv_dlopen_self=no fi rm -fr conftest* fi fi echo "$ac_t""$lt_cv_dlopen_self" 1>&6 if test "$lt_cv_dlopen_self" = yes; then LDFLAGS="$LDFLAGS $link_static_flag" echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 echo "$progname:1985: checking whether a statically linked program can dlopen itself" >&5 if test "X${lt_cv_dlopen_self_static+set}" = Xset; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then lt_cv_dlopen_self_static=cross else cat > conftest.$ac_ext <<EOF #line 1993 "ltconfig" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LTDL_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LTDL_GLOBAL DL_GLOBAL # else # define LTDL_GLOBAL 0 # endif #endif /* We may have to define LTDL_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LTDL_LAZY_OR_NOW # ifdef RTLD_LAZY # define LTDL_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LTDL_LAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LTDL_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LTDL_LAZY_OR_NOW DL_NOW # else # define LTDL_LAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42; } int main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } EOF if { (eval echo $progname:2040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then lt_cv_dlopen_self_static=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* lt_cv_dlopen_self_static=no fi rm -fr conftest* fi fi echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 fi ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Copy echo and quote the copy, instead of the original, because it is # used later. ltecho="$echo" if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then ltecho="$CONFIG_SHELL \$0 --fallback-echo" fi LTSHELL="$SHELL" LTCONFIG_VERSION="$VERSION" # Only quote variables if we're using ltmain.sh. case $ltmain in *.sh) # Now quote all the things that may contain metacharacters. for var in ltecho old_AR old_AR_FLAGS old_CC old_LTCC old_CFLAGS old_CPPFLAGS \ old_MAGIC_CMD old_LD old_LDFLAGS old_LIBS \ old_LN_S old_NM old_RANLIB old_STRIP \ old_AS old_DLLTOOL old_OBJDUMP \ old_OBJEXT old_EXEEXT old_reload_flag \ old_deplibs_check_method old_file_magic_cmd \ AR AR_FLAGS CC LTCC LD LN_S NM LTSHELL LTCONFIG_VERSION \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ predep_objects postdep_objects predeps postdeps compiler_lib_search_path \ old_striplib striplib file_magic_cmd export_symbols_cmds \ deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o need_locks exclude_expsyms include_expsyms; do case $var in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ### testsuite: skip nested quoting test ;; *) eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ### testsuite: skip nested quoting test ;; esac done case $ltecho in *'\$0 --fallback-echo"') ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac if test -z "$tagname"; then trap "$rm \"$ofile\"; exit 1" 1 2 15 echo "creating $ofile" $rm "$ofile" cat <<EOF > "$ofile" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. # # Copyright (C) 1996-2000 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="sed -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # The names of the tagged configurations supported by this script. available_tags= ### BEGIN LIBTOOL CONFIG EOF else echo "appending configuration tag \"$tagname\" to $ofile" echo "### BEGIN LIBTOOL TAG CONFIG: $tagname" >> "$ofile" fi cfgfile="$ofile" ;; *) # Double-quote the variables that need it (for aesthetics). for var in old_AR old_AR_FLAGS old_CC old_LTCC old_CFLAGS old_CPPFLAGS \ old_MAGIC_CMD old_LD old_LDFLAGS old_LIBS \ old_LN_S old_NM old_RANLIB old_STRIP \ old_AS old_DLLTOOL old_OBJDUMP \ old_OBJEXT old_EXEEXT old_reload_flag \ old_deplibs_check_method old_file_magic_cmd; do eval "$var=\\\"\$var\\\"" done # Just create a config file. cfgfile="$ofile.cfg" if test -z "$tagname"; then trap "$rm \"$cfgfile\"; exit 1" 1 2 15 echo "creating $cfgfile" $rm "$cfgfile" cat <<EOF > "$cfgfile" # `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) ### BEGIN LIBTOOL CONFIG EOF else echo "appending to $cfgfile" echo "### BEGIN LIBTOOL TAG CONFIG: $tagname" >> "$ofile" fi ;; esac cat <<EOF >> "$cfgfile" # Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # # AR=$old_AR AR_FLAGS=$old_AR_FLAGS LTCC=$old_LTCC CC=$old_CC \\ # CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ # MAGIC_CMD=$old_MAGIC_CMD LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ # LN_S=$old_LN_S NM=$old_NM RANLIB=$old_RANLIB STRIP=$old_STRIP \\ # AS=$old_AS DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP \\ # objext=$old_OBJEXT exeext=$old_EXEEXT reload_flag=$old_reload_flag \\ # deplibs_check_method=$old_deplibs_check_method \\ # file_magic_cmd=$old_file_magic_cmd \\ # $0$ltconfig_args # # Compiler and other test output produced by $progname, useful for # debugging $progname, is in ./config.log if it exists. # The version of $progname that generated this script. LTCONFIG_VERSION=$LTCONFIG_VERSION # Shell to use when invoking shell scripts. SHELL=$LTSHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$need_lc # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$ltecho # The archiver. AR=$AR AR_FLAGS=$AR_FLAGS # A C compiler. LTCC=$LTCC # A language-specific compiler. CC=$CC # Is the compiler the GNU C compiler? with_gcc=$with_gcc # The linker used to build libraries. LD=$LD # Whether we need hard or soft links. LN_S=$LN_S # A BSD-compatible nm program. NM=$NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$reload_flag reload_cmds=$reload_cmds # How to pass a linker flag through the compiler. wl=$wl # Object file suffix (normally "o"). objext="$objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$pic_flag pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$compiler_c_o # Must we lock files when doing compilation ? need_locks=$need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$library_names_spec # The coded name of the library, if different from the real name. soname_spec=$soname_spec # Commands used to build and install an old-style archive. RANLIB=$RANLIB old_archive_cmds=$old_archive_cmds old_postinstall_cmds=$old_postinstall_cmds old_postuninstall_cmds=$old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$archive_cmds archive_expsym_cmds=$archive_expsym_cmds postinstall_cmds=$postinstall_cmds postuninstall_cmds=$postuninstall_cmds # Commands to strip libraries. old_striplib=$old_striplib striplib=$striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$predep_objects # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$postdep_objects # Dependencies to place before the objects being linked to create a # shared library. predeps=$predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$global_symbol_to_cdecl # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$exclude_expsyms # Symbols that must always be exported. include_expsyms=$include_expsyms EOF if test -z "$tagname"; then echo '### END LIBTOOL CONFIG' >> "$ofile" else echo "### END LIBTOOL TAG CONFIG: $tagname" >> "$ofile" fi case $ltmain in *.sh) echo >> "$ofile" if test -z "$tagname"; then case $host_os in aix3*) cat <<\EOF >> "$ofile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) cat <<'EOF' >> "$ofile" # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include <windows.h> # #undef WIN32_LEAN_AND_MEAN # #include <stdio.h> # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include <cygwin/cygwin_dll.h> # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include <stdio.h> /* for printf() */ # #include <unistd.h> /* for open(), lseek(), read() */ # #include <fcntl.h> /* for O_RDONLY, O_BINARY */ # #include <string.h> /* for strdup() */ # # /* O_BINARY isn't required (or even defined sometimes) under Unix */ # #ifndef O_BINARY # #define O_BINARY 0 # #endif # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (dll < 1) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i<nexp; i++) # { # unsigned long name_rva = pe_as32 (erva+name_rvas+i*4); # printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i); # } # # return 0; # } # /* impgen.c ends here */ EOF ;; esac # Append the ltmain.sh script. sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? chmod +x "$ofile" fi ;; *) # Compile the libtool program. echo "FIXME: would compile $ltmain" ;; esac # Update the list of available tags. if test -n "$tagname"; then # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" $ofile | sed -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` # Append the new tag name to the list of available tags. available_tags="$available_tags $tagname" # Now substitute the updated of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' ${ofile} > ${ofile}.new"; then mv ${ofile}.new ${ofile} chmod +x "$ofile" else rm -f ${ofile}.new echo "$progname: unable to update list of available tagged configurations." exit 1 fi fi # Don't cache tagged configuration! test -n "$cache_file" && test -z "$tagname" || exit 0 # AC_CACHE_SAVE trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: vm/src/from_squeak/unix/config/ltmain.sh ================================================ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<EOF $* EOF exit 0 fi # The name of this program. progname=`$echo "$0" | sed 's%^.*/%%'` modename="$progname" # Constants. PROGRAM=ltmain.sh PACKAGE=libtool VERSION=1.4.2 TIMESTAMP=" (1.922.2.53 2001/09/11 03:18:52)" default_mode= help="Try \`$progname --help' for more information." magic="%%%MAGIC variable%%%" mkdir="mkdir" mv="mv -f" rm="rm -f" # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' SP2NL='tr \040 \012' NL2SP='tr \015\012 \040\040' # NLS nuisances. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). # We save the old values to restore during execute mode. if test "${LC_ALL+set}" = set; then save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL fi if test "${LANG+set}" = set; then save_LANG="$LANG"; LANG=C; export LANG fi # Make sure IFS has a sensible default : ${IFS=" "} if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then echo "$modename: not configured to build any kind of library" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" # Parse our command line options once, thoroughly. while test $# -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" exit 0 ;; --config) sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 exit 0 ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --quiet | --silent) show=: ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then case $nonopt in *cc | *++ | gcc* | *-gcc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= prev= lastarg= srcfile="$nonopt" suppress_output= user_target=no for arg do case $prev in "") ;; xcompiler) # Aesthetically quote the previous argument. prev= lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac # Accept any command-line options. case $arg in -o) if test "$user_target" != "no"; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi user_target=next ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) prev=xcompiler continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac case $user_target in next) # The next one is the -o target name user_target=yes continue ;; yes) # We got the output file user_target=set libobj="$arg" continue ;; esac # Accept the current argument as the source file. lastarg="$srcfile" srcfile="$arg" # Aesthetically quote the previous argument. # Backslashify any backslashes, double quotes, and dollar signs. # These are the only characters that are still specially # interpreted inside of double-quoted scrings. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $lastarg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi done case $user_target in set) ;; no) # Get the name of the library object. libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; *) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSfmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $libobj" else removelist="$libobj" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" else # Don't build PIC code command="$base_compile $srcfile" fi if test "$build_old_libs" = yes; then lo_libobj="$libobj" dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$libobj"; then dir="$objdir" else dir="$dir/$objdir" fi libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` if test -d "$dir"; then $show "$rm $libobj" $run $rm $libobj else $show "$mkdir $dir" $run $mkdir $dir status=$? if test $status -ne 0 && test ! -d $dir; then exit $status fi fi fi if test "$compiler_o_lo" = yes; then output_obj="$libobj" command="$command -o $output_obj" elif test "$compiler_c_o" = yes; then output_obj="$obj" command="$command -o $output_obj" fi $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test x"$output_obj" != x"$libobj"; then $show "$mv $output_obj $libobj" if $run $mv $output_obj $libobj; then : else error=$? $run $rm $removelist exit $error fi fi # If we have no pic_flag, then copy the object into place and finish. if (test -z "$pic_flag" || test "$pic_mode" != default) && test "$build_old_libs" = yes; then # Rename the .lo from within objdir to obj if test -f $obj; then $show $rm $obj $run $rm $obj fi $show "$mv $libobj $obj" if $run $mv $libobj $obj; then : else error=$? $run $rm $removelist exit $error fi xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` # Now arrange that obj and lo_libobj become the same file $show "(cd $xdir && $LN_S $baseobj $libobj)" if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 else error=$? $run $rm $removelist exit $error fi fi # Allow error messages only from the first compilation. suppress_output=' >/dev/null 2>&1' fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $srcfile" else # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" output_obj="$obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test x"$output_obj" != x"$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Create an invalid libtool object if no PIC, so that we do not # accidentally link it into a program. if test "$build_libtool_libs" != yes; then $show "echo timestamp > $libobj" $run eval "echo timestamp > \$libobj" || exit $? else # Move the .lo from within objdir $show "$mv $libobj $lo_libobj" if $run $mv $libobj $lo_libobj; then : else error=$? $run $rm $removelist exit $error fi fi fi # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 ;; # libtool link mode link | relink) modename="$modename: link" case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invokation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args="$nonopt" compile_command="$nonopt" finalize_command="$nonopt" compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= # We need to know -static, to get the right output filenames. for arg do case $arg in -all-static | -static) if test "X$arg" = "X-all-static"; then if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test $# -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n $prev prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.lo | *.$objext) # A library or standard object. if test "$prev" = dlfiles; then # This file was specified with -dlopen. if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $arg" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` prev= else case $arg in *.lo) libobjs="$libobjs $arg" ;; *) objs="$objs $arg" ;; esac fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d $output_objdir; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac libs="$libs $deplib" done deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test $linkmode = prog; then # Determine which files to process case $pass in dlopen) libs="$dlfiles" save_deplibs="$deplibs" # Collect dlpreopened libraries deplibs= ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test $linkmode = oldlib && test $linkmode = obj; then $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 continue fi if test $pass = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do # Search the libtool library lib="$searchdir/lib${name}.la" if test -f "$lib"; then found=yes break fi done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test $pass = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi if test $pass = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test $pass = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then echo echo "*** Warning: This library needs some functionality provided by $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." else echo echo "*** Warning: Linking the shared library $output against the" echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test $pass != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test $found = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variable installed. installed=yes # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test $linkmode = oldlib && test $linkmode = obj; }; then # Add dl[pre]opened files of deplib test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test $pass = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac tmp_libs="$tmp_libs $deplib" done elif test $linkmode != prog && test $linkmode != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test $pass = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. dlprefiles="$dlprefiles $lib" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test $pass = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test $linkmode = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" fi continue fi if test $linkmode = prog && test $pass != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test $linkalldeplibs = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # Link against this shared library if test "$linkmode,$pass" = "prog,link" || { test $linkmode = lib && test $hardcode_into_libs = yes; }; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac if test $linkmode = prog; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi fi fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`echo $soroot | sed -e 's/^.*\///'` newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n $old_archive_from_expsyms_cmds if test $linkmode = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test $linkmode = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test $linkmode = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" add="-l$name" fi if test $linkmode = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test $linkmode = prog; then if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi # Try to link the static library # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo echo "*** Warning: This library needs some functionality provided by $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** Therefore, libtool will create a static module, that should work " echo "*** as long as the dlopening application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test $linkmode = lib; then if test -n "$dependency_libs" && { test $hardcode_into_libs != yes || test $build_old_libs = yes || test $link_static = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac tmp_libs="$tmp_libs $deplib" done if test $link_all_deplibs != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="-L$absdir/$objdir" else eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="-L$absdir" fi ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test $pass = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test $pass != dlopen; then test $pass != scan && dependency_libs="$newdependency_libs" if test $pass != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do case $deplib in -L*) new_libs="$deplib $new_libs" ;; *) case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi if test "$pass" = "conv" && { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then libs="$deplibs" # reset libs deplibs= fi done # for pass if test $linkmode = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else echo echo "*** Warning: Linking the shared library $output against the non-libtool" echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test $# -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. libext=al oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi current="$2" revision="$3" age="$4" # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test $age -gt $current; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix) major=`expr $current - $age + 1` verstring="sgi$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test $loop != 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="sgi$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test $loop != 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= verstring="0.0" case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring="" ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs. $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'` deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'` dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test $hardcode_into_libs != yes || test $build_old_libs = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd*) # Do not include libc due to us having libc/libc_r. ;; *) # Add libc to deplibs on all other systems if necessary. if test $build_libtool_need_lc = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behaviour. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c <<EOF int main() { return 0; } EOF $rm conftest $CC -o conftest conftest.c $deplibs if test $? -eq 0 ; then ldd_output=`ldd conftest` for i in $deplibs; do name="`expr $i : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` deplib_matches=`eval \\$echo \"$library_names_spec\"` set dummy $deplib_matches deplib_match=$2 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then newdeplibs="$newdeplibs $i" else droppeddeps=yes echo echo "*** Warning: This library needs some functionality provided by $i." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." fi else newdeplibs="$newdeplibs $i" fi done else # Error occured in the first compile. Let's try to salvage the situation: # Compile a seperate program for each library. for i in $deplibs; do name="`expr $i : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then $rm conftest $CC -o conftest conftest.c $i # Did it work? if test $? -eq 0 ; then ldd_output=`ldd conftest` libname=`eval \\$echo \"$libname_spec\"` deplib_matches=`eval \\$echo \"$library_names_spec\"` set dummy $deplib_matches deplib_match=$2 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then newdeplibs="$newdeplibs $i" else droppeddeps=yes echo echo "*** Warning: This library needs some functionality provided by $i." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." fi else droppeddeps=yes echo echo "*** Warning! Library $i is needed by this library but I was not able to" echo "*** make it link in! You will probably need to install it or some" echo "*** library that it depends on before this library will be fully" echo "*** functional. Installing it before continuing would be even better." fi else newdeplibs="$newdeplibs $i" fi done fi ;; file_magic*) set dummy $deplibs_check_method file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | sed 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | sed 10q \ | egrep "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: This library needs some functionality provided by $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do if eval echo \"$potent_lib\" 2>/dev/null \ | sed 10q \ | egrep "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: This library needs some functionality provided by $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | grep . >/dev/null; then echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" echo "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test $allow_undefined = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test $hardcode_into_libs = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi test -z "$dlname" && dlname=$soname lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Ensure that we have .o objects for linkers which dislike .lo # (e.g. aix) in case we are running --disable-static for obj in $libobjs; do xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` if test ! -f $xdir/$oldobj; then $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? fi done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. $show "echo timestamp > $libobj" $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" else # Just create a symlink. $show $rm $libobj $run $rm $libobj xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$libobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` $show "(cd $xdir && $LN_S $oldobj $baseobj)" $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | sed -e 's%^.*/%%'` $run eval 'echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test $need_relink = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="cd `pwd`; $relink_command" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`echo $output|sed 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe ;; *) exeext= ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # win32 systems need to use the prog path for dll # lookup to work *-*-cygwin* | *-*-pw32*) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ # Export the path to the program. PATH=\"\$progdir:\$PATH\" export PATH exec \$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else # Ensure that we have .o objects in place in case we decided # not to build a shared library, and have fallen back to building # static libs even though --disable-static was passed! for oldobj in $oldobjs; do if test ! -f $oldobj; then xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$oldobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` $show "(cd $xdir && ${LN_S} $obj $baseobj)" $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? fi done eval cmds=\"$old_archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="cd `pwd`; $SHELL $0 --mode=relink $libtool_args" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test $need_relink = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test $# -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 continue fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then notinst_deplibs= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in /usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`echo $destfile | sed -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = ":" && exit 0 echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do echo " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" echo "more information, such as the ld(1) and ld.so(8) manual pages." echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved enviroment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd='"$cmd"$args' else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$objdir" else objdir="$dir/$objdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test $mode = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test $mode = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test $mode = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) if test "$build_old_libs" = yes; then oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` rmfiles="$rmfiles $dir/$oldobj" fi ;; *) # Do a test to see if this is a libtool program. if test $mode = clean && (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$file rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: vm/src/from_squeak/unix/config/make.cfg.in ================================================ # make.cfg.in -- mf fragment for configured variables -*- makefile -*- # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # Author: Ian.Piumarta@inria.fr # # Last edited: Tue Jan 26 11:48:03 PST 2010 by eliot MAKEFLAGS= --no-print-directory @SET_MAKE@ VM_MAJOR= @VM_MAJOR@ VM_MINOR= @VM_MINOR@ VM_RELEASE= @VM_RELEASE@ VM_VERSION= @VM_VERSION@ SQ_MAJOR= @SQ_MAJOR@ SQ_MINOR= @SQ_MINOR@ SQ_UPDATE= @SQ_UPDATE@ SQ_VERSION= @SQ_VERSION@ DEVEL= @DEVEL@ host= @host@ host_cpu= @host_cpu@ host_vendor= @host_vendor@ host_os= @host_os@ topdir= @topdir@ cfgdir= @cfgdir@ srcdir= @vmmdir@ vmmcfg= @vmmcfg@ blddir= @blddir@ top_builddir= @blddir@ prefix= @prefix@ exec_prefix= @exec_prefix@ bindir= @bindir@ libdir= @libdir@ datadir= @datadir@ mandir= @mandir@ imgdir= @imgdir@ plgdir= @plgdir@ docdir= $(prefix)/doc/squeak SHELL= @SHELL@ MKINSTALLDIRS= mkdir -p INSTALL= @INSTALL@ INSTALL_PROG= @INSTALL_PROGRAM@ $(INSTALL_ARGS) INSTALL_SCRIPT= @INSTALL_SCRIPT@ $(INSTALL_ARGS) INSTALL_DATA= @INSTALL_DATA@ $(INSTALL_ARGS) UNINSTALL= $(SHELL) $(cfgdir)/uninstall AS= @AS@ AWK= @AWK@ RANLIB= @RANLIB@ LIBTOOL= @LIBTOOL@ NM= @NM@ LN= @LN@ LN_S= @LN_S@ CC= @CC@ DEFS= @DEFS@ INCLUDES= @INCLUDES@ CPPFLAGS= @CPPFLAGS@ CFLAGS= @CFLAGS@ WFLAGS= @WFLAGS@ LDFLAGS= @LDFLAGS@ SOFLAGS= @SOFLAGS@ LIBM_CFLAGS= @LIBM_CFLAGS@ LIBS= @LIBS@ X_CFLAGS= @X_CFLAGS@ X_INCLUDES= @X_INCLUDES@ X_LIBS= @X_LIBS@ LIB_UUID= @LIB_UUID@ FFI_DIR= @FFI_DIR@ FFI_C= @FFI_C@ FFI_S= @FFI_S@ FFI_O= @FFI_O@ PYLIBPATH= @PYLIBPATH@ PYINCLUDES= @PYINCLUDES@ INTERP= @INTERP@ VM_APP_ICONS= @VM_APP_ICONS@ npsqueak= @npsqueak@ install_nps= @install_nps@ uninstall_nps= @uninstall_nps@ ================================================ FILE: vm/src/from_squeak/unix/config/make.ext.in ================================================ # make.ext.in -- mf fragment for external plugins -*- makefile -*- # # Author: Ian.Piumarta@inria.fr # # Last edited: Sep 1 18:56:15 PDT 2010 by eliot; LINKXX for plugins using C++ o = .lo a = .la COMPILE = $(LIBTOOL) --mode=compile \ $(CC) $(CFLAGS) $(XCFLAGS) $(DEFS) $(XDEFS) \ $(INCLUDES) $(XINCLUDES) $(CPPFLAGS) $(XCPPFLAGS) -c -o CXXFLAGS = $(CFLAGS) # Hack; can't be bothered to add CXXFLAGS to the configure mess COMPILE.cpp = $(LIBTOOL) --mode=compile \ $(CXX) $(CXXFLAGS) $(XCFLAGS) $(DEFS) $(XDEFS) \ $(INCLUDES) $(XINCLUDES) $(CPPFLAGS) $(XCPPFLAGS) -c -o LINK = $(LIBTOOL) --mode=link \ $(CC) $(CFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -avoid-version -module -rpath $(plgdir) -o LINKXX = $(LIBTOOL) --mode=link \ $(CXX) $(CFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -avoid-version -module -rpath $(plgdir) -o RANLIB = : ================================================ FILE: vm/src/from_squeak/unix/config/make.int.in ================================================ # make.int.in -- mf fragment for internal plugins -*- makefile -*- # # Author: Ian.Piumarta@inria.fr # # Last edited: 2002-07-08 20:31:51 by piumarta on emilia.inria.fr o = .o a = .a COMPILE = $(CC) $(CFLAGS) $(XCFLAGS) $(DEFS) $(XDEFS) -DSQUEAK_BUILTIN_PLUGIN \ $(INCLUDES) $(XINCLUDES) $(CPPFLAGS) $(XCPPFLAGS) -c -o LINK = $(AR) -rc RANLIB = @RANLIB@ ================================================ FILE: vm/src/from_squeak/unix/config/make.prg.in ================================================ # make.prg.in -- mf fragment for programs -*- makefile -*- # # Author: Ian.Piumarta@inria.fr # # Last edited: Thu Jan 21 14:59:38 PST 2010 by eliot (support for .cpp) o = .o a = .a x = COMPILE = $(CC) $(CFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -export-dynamic -c -o COMPILEIFP = $(CC) $(CFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -export-dynamic -fno-omit-frame-pointer -c -o CXXFLAGS = $(CFLAGS) # Hack; can't be bothered to add CXXFLAGS to the configure mess COMPILE.cpp = $(CXX) $(CXXFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -export-dynamic -c -o LINK = $(LIBTOOL) --mode=link \ $(CC) $(CFLAGS) $(XCFLAGS) \ $(LDFLAGS) $(XLDFLAGS) -export-dynamic -R$(libdir) -o RANLIB = : ================================================ FILE: vm/src/from_squeak/unix/config/mkacinc ================================================ #!/bin/sh includes="`echo ../vm*/acinclude.m4 ../plugins/*/acinclude.m4`"; if test "${includes}" != ""; then for i in ${includes}; do echo " + $i" >&2 p=`echo $i | sed 's,../,,;s,plugins/,,;s,/acinclude.m4,,'` cat <<EOF plugin="${p}" plibs="" rm -f ${p}.sub ${p}.lib EOF cat $i cat <<\EOF if test "${plibs}"; then llibs="${LIBS}" for l in ${plibs}; do llibs="${llibs} -l${l}" done echo ${llibs} > ${plugin}.lib fi EOF done fi ================================================ FILE: vm/src/from_squeak/unix/config/mkconfig.in ================================================ #!/bin/sh int_modules="@int_modules@" ext_modules="@ext_modules@" int_plugins="@int_plugins@ `grep -v '^#' @vmmcfg@/plugins.int | sed 's/INTERNAL_PLUGINS = //' | tr -d '\\\\\\012';echo`" ext_plugins="@ext_plugins@ `grep -v '^#' @vmmcfg@/plugins.ext | sed 's/EXTERNAL_PLUGINS = //' | tr -d '\\\\\\012';echo`" if test -f plugins.exc; then nlsp='tr \012\015 \040\040' spnl='tr \040\040 \012\012' int_modules="`echo ${int_modules} | $spnl | fgrep -v -f plugins.exc | $nlsp`" ext_modules="`echo ${ext_modules} | $spnl | fgrep -v -f plugins.exc | $nlsp`" int_plugins="`echo ${int_plugins} | $spnl | fgrep -v -f plugins.exc | $nlsp`" ext_plugins="`echo ${ext_plugins} | $spnl | fgrep -v -f plugins.exc | $nlsp`" exc_plugins="`cat plugins.exc | $nlsp`" else exc_plugins="" fi platforms="@topdir@/platforms" vmi_conf="${platforms}/unix" plg_conf="${vmi_conf}/plugins" vmi_dirs="@vmmdir@ ${platforms}/Cross ${vmi_conf}" int_dirs="@vmmdir@/plugins ${platforms}/Cross/plugins ${plg_conf}" ext_dirs="@vmmdir@/plugins ${platforms}/Cross/plugins ${plg_conf}" cat > config.sh <<EOF srcdir="@vmmdir@" blddir="@blddir@" topdir="@topdir@" cfgdir="@cfgdir@" int_modules="${int_modules}" ext_modules="${ext_modules}" int_plugins="${int_plugins}" ext_plugins="${ext_plugins}" exc_plugins="${exc_plugins}" vmi_dirs="${vmi_dirs}" int_dirs="${int_dirs}" ext_dirs="${ext_dirs}" EOF chmod +x config.sh ================================================ FILE: vm/src/from_squeak/unix/config/mkinstalldirs ================================================ #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman <friedman@prep.ai.mit.edu> # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs 990 2005-03-09 09:04:06Z piumarta $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here ================================================ FILE: vm/src/from_squeak/unix/config/mkman ================================================ #!/bin/sh sed "s%\[major\]%$1%g s%\[version\]%$2%g s%\[bindir\]%$3%g s%\[imgdir\]%$4%g s%\[plgdir\]%$5%g s%\[mandir\]%$6%g s%\[docdir\]%$7%g" ================================================ FILE: vm/src/from_squeak/unix/config/mkmf ================================================ #!/bin/sh # mkmf -- configure subdirectory Makefiles -*- sh -*- # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: ian.piumarta@inria.fr # # Last edited: Thu Jan 21 14:10:49 PST 2010 by eliot (add support for .cpp) . ./config.sh findFiles() { suffix=$1 shift while test $# -gt 0; do echo $1/*${suffix} shift done } findDirs() { prefix=$1 shift dirs="" while test $# -gt 0; do dirs="${dirs} ${prefix}`dirname $1`" shift done echo ${dirs} | tr ' ' '\012' | sort | uniq | tr '\012' ' ' } plibs="" mkmf() { default=$1 name=$2 shift 2 dirs="$*" makefile_in="" makefile_inc="" makefile_plg=Makefile.plg.in make_targets="${name}/make.targets" objs="${name}/.objs" excluded="${name}/.excluded" targets="" includes="" srcs="" hdrs="" echo "creating ${name}/Makefile" test -d ${name} || mkdir ${name} echo "" > ${make_targets} echo "" > ${excluded} # collect source and header files for x in ${dirs}; do d=${x}/${name} if test -d ${d}; then dd=${d} if test -f ${d}/mkmf.subdirs; then subdirs="`cat ${d}/mkmf.subdirs | tr '\012' ' '`" for sd in ${subdirs}; do dd="${dd} ${topdir}/${sd}"; done fi srcs="${srcs} `findFiles .c ${dd}`" srcs="${srcs} `findFiles .cc ${dd}`" srcs="${srcs} `findFiles .cpp ${dd}`" srcs="${srcs} `findFiles .S ${dd}`" srcs="${srcs} `findFiles .m ${dd}`" hdrs="${hdrs} `findFiles .h ${dd}`" # override Makefile.in if test -f "${d}/Makefile.in"; then makefile_in="${d}/Makefile.in" fi # include Makefile.inc if test -f "${d}/Makefile.inc"; then makefile_inc="${makefile_inc} ${d}/Makefile.inc" fi test -f "${d}/Targets.exclude" && cat "${d}/Targets.exclude" >>${excluded} fi done srcs="`echo ${srcs} | tr ' ' '\012' | fgrep -v '*'`" hdrs="`echo ${hdrs} | tr ' ' '\012' | fgrep -v '*'`" # create targets and rules if test "${srcs}" != ""; then # objs is used to make the list of targets unique so that a platform can # override a file in Cross/plugins/Foo. # e.g qWebcam.cpp in both platforms/{Cross,unix}/plugins/QWebcamPlugin # excluded is used to exclude unneeded targets (specify a targets.exclude # in the platform plugin dir) echo "" > ${objs} for c in ${srcs}; do o=`basename ${c} | sed 's,\.cp*,$o,;s,\.m,$o,;s,\.S,$o,'` grep -qs "^$o$" ${excluded} || grep -qs "^$o$" ${objs} || targets="${targets} ${o}" echo "$o" >>${objs} echo >> ${make_targets} echo "${o} : ${c}" >> ${make_targets} case ${c} in *.cpp|*.cc) echo ' $(COMPILE.cpp) '"${o} ${c}" >> ${make_targets} makefile_plg=Makefile.cpp-plg.in;; *) echo ' $(COMPILE) '"${o} ${c}" >> ${make_targets} esac done rm -f ${objs} ${excluded} fi # create includes if test "${hdrs}" != ""; then includes="${includes} `findDirs -I ${hdrs}`" fi # default Makefile.in if no override if test ! -f "${makefile_in}"; then makefile_in=${cfgdir}/${makefile_plg} fi # include Makefile.inc(s) if test "${makefile_inc}" != ""; then cp ${makefile_in} makefile.in makefile_in="makefile.in" for inc in ${makefile_inc}; do sed "/\[make_inc\]/r ${inc}" < ${makefile_in} > makefile.out mv makefile.out makefile.in done fi # substitutions if test -f "${name}.sub"; then sed -f ${name}.sub < ${makefile_in} > makefile.sub makefile_in="makefile.sub" fi sed "s%\[make_inc\]%%g s%\[target\]%${name}"'$a'"%g s%\[targets\]%${targets}%g s%\[includes\]%${includes}%g /\[make_cfg\]/r ${blddir}/make.cfg s%\[make_cfg\]%%g /\[make_prg\]/r ${bldir}/make.prg s%\[make_prg\]%%g /\[make_plg\]/r ${blddir}/make.${default} s%\[make_plg\]%%g s%\[plibs\]%${plibs}%g /\[make_targets\]/r ${make_targets} s%\[make_targets\]%%g" < ${makefile_in} > ${name}/Makefile /bin/rm -f ${make_targets} makefile.in makefile.sub } if test "${int_modules}" != ""; then for p in ${int_modules}; do mkmf int ${p} ${vmi_dirs} done fi if test "${ext_modules}" != ""; then for p in ${ext_modules}; do if test -f ${p}.lib; then plibs="`cat ${p}.lib`" else plibs="" fi mkmf ext ${p} ${vmi_dirs} done fi if test "${int_plugins}" != ""; then for p in ${int_plugins}; do mkmf int ${p} ${int_dirs} done fi if test "${ext_plugins}" != ""; then for p in ${ext_plugins}; do if test -f ${p}.lib; then plibs="`cat ${p}.lib`" else plibs="" fi mkmf ext ${p} ${ext_dirs} done fi ================================================ FILE: vm/src/from_squeak/unix/config/mktargets ================================================ #!/bin/sh # mktargets -- configure top-level library targets -*- sh -*- # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: ian.piumarta@inria.fr # # Last edited: 2006-10-18 10:12:29 by piumarta on emilia.local . ./config.sh no_exports="disabledPlugins" make_targets="make.targets" la='${la}' a='$a' o='$o' plugins="" if test "${ext_modules}${ext_plugins}" != ""; then for p in ${ext_modules} ${ext_plugins}; do plugins="${plugins} ${p}${la}" done fi echo "" > ${make_targets} targets="" plibs="" if test "${int_modules}${int_plugins}" != ""; then for p in ${int_modules} ${int_plugins}; do targets="${targets} ${p}/${p}$a" echo >> ${make_targets} echo "${p}/${p}$a : .force" >> ${make_targets} echo ' @$(SHELL) -ec '"'cd ${p}; "'$(MAKE) '"${p}$a'" >> ${make_targets} test -f ${p}.lib && plibs="${plibs} `cat ${p}.lib`" done fi if test "${ext_modules}${ext_plugins}" != ""; then for p in ${ext_modules} ${ext_plugins}; do echo >> ${make_targets} echo "${p}${la} :" >> ${make_targets} echo ' @$(SHELL) -ec '"'cd ${p}; "'$(MAKE) '"${p}${la}'" >> ${make_targets} done fi if test "${exc_plugins}" != ""; then targets="${targets} ${no_exports}$o" cat > ${no_exports}.c <<EOF /* this should be in a header file, but it isn't. ho hum. */ typedef struct { char *pluginName; char *primitiveName; void *primitiveAddress; } sqExport; `for p in ${exc_plugins}; do echo "sqExport ${p}_exports[] = { 0, 0, 0 };"; done | sed 's/-/_/g'` EOF cat >> ${make_targets} <<EOF ${no_exports}$o : ${no_exports}.c \$(COMPILE) ${no_exports}$o ${no_exports}.c EOF fi mv Makefile Makefile.tmp sed "s%\[targets\]%${targets}%g s%\[plugins\]%${plugins}%g s%\[plibs\]%${plibs}%g /\[make_targets\]/r ${make_targets} s%\[make_targets\]%%g" < Makefile.tmp > Makefile rm Makefile.tmp ================================================ FILE: vm/src/from_squeak/unix/config/relpath ================================================ #!/bin/sh # # relpath -- construct path relative to cwd # # Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors # listed elsewhere in this file. # All rights reserved. # # This file is part of Unix Squeak. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Author: Ian.Piumarta@INRIA.Fr # # Last edited: 2006-10-18 10:12:08 by piumarta on emilia.local if test $# -ne 2; then echo "usage: $0 srcdir path" fi cwd=$1 path=$2 for dir in `echo $cwd | tr '/' ' '`; do if expr $path : "/$dir" >/dev/null; then path=`echo $path | sed "s,^/$dir,,"` cwd=`echo $cwd | sed "s,^/$dir,,"` fi done path=`echo $path | sed 's,^/,,'` for dir in `echo $cwd | tr '/' ' '`; do path="../$path" done echo $path ================================================ FILE: vm/src/from_squeak/unix/config/squeak.sh.in ================================================ #!/bin/sh BIN=`/usr/bin/dirname $0`/@expanded_relative_imgdir@ # At least on linux LD_LIBRARY_PATH's components must be absolute path names case "$BIN" in /*) PLUGINS="$BIN";; *) PLUGINS="`pwd`/$BIN" esac # prepending is less flexible but safer because it ensures we find the plugins # in the same directory as the VM. LD_LIBRARY_PATH=$PLUGINS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} exec "$BIN/squeak" "$@" ================================================ FILE: vm/src/from_squeak/unix/config/uninstall ================================================ #!/bin/sh # # uninstall -- uninstall files/directories # # Author: Ian.Piumarta@INRIA.Fr # # Last edited: 2002-06-06 05:12:25 by piumarta on emilia.inria.fr test=`which test` if test $# -lt 1; then echo "usage: $0 dir files..." fi dir=$1 shift if test -d ${dir}; then for file in $*; do if $test -f "${dir}/${file}" -o -L "${dir}/${file}"; then echo "rm -f ${dir}/${file}" rm -f ${dir}/${file} fi done fi while test "${dir}" != "/" -a "${dir}" != "."; do if test -d ${dir}; then test "`echo ${dir}/*`" != "${dir}/*" && break; echo "rmdir ${dir}" rmdir ${dir} fi dir=`dirname ${dir}` done ================================================ FILE: vm/src/from_squeak/unix/config/version ================================================ #!/bin/sh fgrep 'const char *interpreterVersion = ' $1 | sed 's,.*"Squeak,,;s, .*#,\.,;s,].*,,;s,\., ,g;s,$,,' ================================================ FILE: vm/src/from_squeak/unix/config/version.stamp ================================================ 20020601 ================================================ FILE: vm/src/from_squeak/unix/config/verstamp ================================================ #!/bin/sh # # Write a version stamp into $1. $2 is the compiler name. # # Last edited: 2002-06-08 18:32:53 by piumarta on emilia.inria.fr if test -f $1; then SERIAL=`head -1 $1 | cut -d ' ' -f 3 | sed 's/;//'` SERIAL=`expr $SERIAL + 1` else SERIAL=1 fi if expr "$2" : ".*gcc" >/dev/null ; then CC=`$2 -v 2>&1 | tail -1 | sed 's/.*based on//g' | awk '{print $1 , $3} '` else CC=$2 fi cat <<_EOF >$1 int vm_serial= $SERIAL; char *vm_date= "`date`"; char *cc_version= "$CC"; char *ux_version= "`uname -a | sed 's, unknown,,g'`"; _EOF ================================================ FILE: vm/src/from_squeak/unix/doc/3.10-1.RELEASE_NOTES ================================================ Changes since 3.9-12: VM generated from 3.10-7159 with latest plugins from package universe where available; OSProcess and XDisplay from Dave Lewis's download page. Network support for IPv6 added. Quartz display driver tries to keep the fullscreen window on the correct screen on multi-head machines. The image should now receive key events for all input has valid UCS4 code. Keyboard and mouse wheel events record UCS4 code in the input buffer for older images that still poll for input. Window event generated for window close to give the image chance to cancel or save before the implied quit. Various small changes for OLPC compatibility. Xdnd supports dragging items out of the image. Support for locale plugin added. Platform support added for locales, dead keys, compose key and multikey characters. VM tries to do 'the right thing' according to locale environment variables. Manual page updated to reflect new options and environment variables: SQUEAK_COMPOSITIONINPUT -compositioninput enables the overlay window for composed character input. Needs the XImm plugin (not yet bundled) to work. SQUEAK_XICFONT -xicfont <fontName> specifies the font name to use in the overlay window. SQUEAK_PLAYBACK, SQUEAK_CAPTURE -playback <name> -capture <name> specify the devices to use for sound playback and capture in ALSA. Build environment: Latest VMM running in 3.10 emits CR instead of LF on Unix. vm/Makefile.in now deals with this by converting CR to LF before gnuification. ================================================ FILE: vm/src/from_squeak/unix/doc/3.10-2.RELEASE_NOTES ================================================ Changes since 3.10-1: SoundPlugin and sound driver support for device selection and mixer control. DragDropPlugin and display driver support for dragging items out of squeak. New plugins and platform support (not all are pre-built in binary distributions): AioPlugin ClipboardExtendedPlugin DBusPlugin GStreamerPlugin OggPlugin RomePlugin OLPC 'Sugar' UI support added. ================================================ FILE: vm/src/from_squeak/unix/doc/3.10-3.RELEASE_NOTES ================================================ Changes since 3.10-2: Interpreter and vmm patches from Dave Lewis applied to make 32- and 64-bit clean VM. Entire generated sources tree (platforms/unix/src) rebuilt. FileCopy and FFI plugins are now external. ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-1.RELEASE_NOTES ================================================ This VM should work with any 3.3 or earlier image. The major changes since 3.1-pre2 are as follows: - Lots of changes based on patches applied to the SF tree. (See the ChangeLog file in the source distribution for a comprehensive list of these changes and the authors of the SF patches, where relevant.) - The VM version number (3.2-1) is now decoupled from the image version (3.3alpha-4857) used produced the generated files, as seems to be the case with Mac and Win32 VMs. For bug reporting purposes, `squeak -version' reports both these version numbers. - Build process completely rewritten to accommodate VMMaker. (Lots of documentation in the source distrib under platforms/unix/doc. Plugin developers who want their code to run on Unix absolutely must read this stuff.) - New option: `-plugins <path>' (env: SQUEAK_PLUGINS='<path>') appends <path> to the list of places the VM seaches for plugins. Each occurrence of `%n' in <path> is replaced by the name of the plugin being loaded. To run a newly-compiled VM without first installing it, use: .../blddir/squeak -plugins .../blddir/%n/.libs - Modifier keys are handled more intelligently. The default is the "traditional" Unix behaviour: mod1 is mapped to Command, Ctrl+mod1 is mapped to Option, and other modifiers are ignored. (This is usually what GNU/Linux systems with PC hardware [mod1=Alt] want.) - For the rest of us, two new options: `-cmdmod <n>' and `-optmod <n>' (env: SQUEAK_CMDMOD=n and SQUEAK_OPTMOD=n). If one or both of these are set then the X11 modifier `mod<n>' is mapped to Squeak's Command and/or Option, respectively. For example, to map a Sun keyboard so that the physical locations of the modifier keys ("Alt" = mod1 and "<>" [meta] = mod4) correspond precisely to their homologues on an Apple keyboard ("Option" and "Command") use: -cmdmod 4 -optmod 1 (or set `export SQUEAK_CMDMOD=4; export SQUEAK_OPTMOD=1' in your .profile to make the change permanent). (Note that setting a modifier for just one of these keys will entirely disable the other.) - New option: `-swapbtn' (env: SQUEAK_SWAPBTN=1) reverses the "yellow" and "blue" buttons which might be useful for people having two-button mice (or who have 3-button mice and no respect for historical precedents). - Various manual page updates (mainly for new/missing options). - New Netscape plugin code from Bert Freudenberg. (Not tested because my Netscape's dynamic loading is broken.) - OSS sound rewritten from scratch. (Full-duplex is supported but the image contains bugs which might prevent it from ever being attempted.) Both input and output have been tested extensively on Linux 2.4.18 with ALSA 0.9rc1 drivers (www.alsa-project.org) and the the OSS compatibility modules (snd-pcm-oss/mixer) that come with them. (This is the only [non-commercial] OSS implementation I've found that respects the published OSS API sufficiently to permit any kind of serious development work.) With the new implementation, playing and recording should only comsume a fraction of 1% of the CPU. Your kilometrage may vary depending on the (quite possibly lamentable) state of your OSS drivers. - New option: `-nomixer' (env: SQUEAK_NOMIXER=1). For people who prefer that Squeak not arbitrarily set the input gain to 50% every time recording is started, this turns off the mixer primitives. With this option your external mixer program retains control of the settings (as it should). - Changes to gnuification should make this thing 5-10% faster on Intel. - Major overhaul of socket code should prevent lockups. (There are still outstanding issues but they concern very obscure situations.) - Lots and lots of smallish changes to the X11 code. Plus some biggish ones: responsiveness should be better and occasional crashes (or freezes) observed when resizing the window should no longer occur. (`-xshm -xasync' not yet extensively tested with the new code.) - Copy/Paste problems encountered between Squeak and some applications (probably mainly KDE and anything that uses Qt or gtk) are fixed. - The default image name is now `squeak.image' (for compatibility with other platforms). - Default heap size increased to 48MB to cope with recent images. Still to do: - mmap()-based memory allocator (when I have time to think about portability). - Revisit the socket code to make a few minor tweaks for the obscure cases and to pull connection reset detection forward into the getSockState primitive (cf the Mac implementation). - Add sources and support for building the VM as a Netscape plugin. - Arrange for -USE_MMX in MpegPlugin on 386. Don't Panic! - Just send me mail if something is broken: ian.piumarta@inria.fr ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-2.RELEASE_NOTES ================================================ Since 3.2-1: - RPMs for ppc and i386 binaries, and noarch .image/.changes and .sources, are available (with prefix /usr) - fixes serious problem in selection handling (many thanks to Ned Konz for spotting the missing "break" :o) - sysAttr #0 is now full pathname to VM (as per method comment in the image) - control key behaviour is inverted as per Ned's insistence: mouse wheel to scroll pane, ctrl+wheel to scroll selection - images are now in version-independent libdir and are installed compressed to save space. inisqueak uncompresses them to squeak.{image,changes} in the cwd - lots of subtle changes to cope with automated builds of tarballs and RPMs from cron jobs - slight version numbering shuffle to allow tarballs and RPMs to have exactly the same version numbers for corresponding files ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-3.RELEASE_NOTES ================================================ Since 3.2-2: Build * Make problems fixed. OpenBSD should now work: $< no longer used anywhere and ranlib run on all static libs. (Craig, you should submit a PR to OpenBSD about the $< thing: it's a bug in make.) VM * Socket options processing improved. * Everything compiles cleanly (and has been tested and is known to work) with -DHEADLESS. (Many thanks to Colin Putney who submitted some of the necessary changes. I added a bunch more to make it work with OSProcess too.) * Small change to browser support code to bring it into line with what the image expects (fail primBrowserReady if not running in a browser). FWIW: this cures (and was hunted down because of) an infuriating three-second pause on return from snapshot. Plugins * B3DAccelerator fixes (many thanks to Joshua Gargus). However it doesn't want to work for me (either internal or external): X Error of failed request: GLXBadDrawable Major opcode of failed request: 143 (GLX) Minor opcode of failed request: 11 (X_GLXSwapBuffers) but that doesn't necessarily mean it won't work for other people. I'll look into this sometime (but I don't consider it urgent, and it might just be my Xserver is broken or maybe libGL hasn't been tested very much on bigendian processors...). * AsynchFilePlugin support has been implemented (and tested). * UnixOSProcessPlugin now bundled with the sources (and built as external plugin in the precompiled VMs). * New plugin: PseudoTTYPlugin (extends AsynchFilePlugin) adding support for pseudo ttys (necessary if processes spawned from Squeak are to believe themselves connected to a real terminal). The changesets for PseudoTTY and PseudoTTYPlugin are in the platform plugin dir (unix/plugins/PseudoTTYPlugin/*.cs). Maybe Dave will take a look at this and pull the functionality into OSProcess (which is probably where it belongs). Enjoy! Ian ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-4.RELEASE_NOTES ================================================ This release is mainly for the BSD folks. It fixes some portability issues in the PTY plugin (I've now built and tested it on GNU/Linux, NetBSD and Solaris and I'm hopeful that it will compile out of the box and work on almost any Unix now) and ties up the last of the loose ends in BSD build. Since 3.2-3: * PtyPlugin rewritten to use either /dev/ptmx or openpty(), as availablility permits. * Minor tweaks to build process (thanks to Steve Elkins for spotting the problems). * A couple of buglets fixed in AsynchFilePlugin (the *class*, not the support code) to prevent core dumps when AsyncFiles are left open across snapshot. (The changes have been sent to John Mc who was, I believe, the original author. Apologies if this isn't so. In any case the changes file is in the unix/plugins/AsynchFilePlugin directory and they're in the Unix VM source/binaries [since I've had core dumps from these bugs recently].) That's it. Ian ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-5.RELEASE_NOTES ================================================ 3.2-5 released on 2002-10-16. Major changes since 3.2-4: VM: Option `-fullscreen' should work better. New option: `-iconic' which does the obvious thing. New option: `-notimer' disables use of itimers and reverts to gettimeofday() for low-res clock. Selection handling support for compatibility with latest Qt (based on code from Ned Konz -- thanks!). Delicious new browser support code from Bert Freudenberg. (Tested under Mozilla on GNU/Linux PPC, but YKMV.) Minor tweaks to closing the X connection via OSProcPlug. (Thanks to Dave Lewis for spotting the problem.) Minor tweak in sound output to cope with incomplete writes (which shouldn't happen, but some ALSA drivers just don't want to respect the rules). (Thanks to Lex for this one.) Broken versions of Solaris that lack snprintf() should no longer cause compile/link errors. As a failsafe, sqGnu.h now defines (empty) all xx_REG symbols on platforms it doesn't recognise. (Thanks to Tommy Thorn for spotting the problem.) aio can now manage fd 0 (stdin). Plugins: RePlugin is now bundled with the VM. Minor tweaks to PseudoTTYPlugin to avoid potential SEGV from stale AsyncFile handles. PTYPlugin is now external by default, to ease the task of compiling on systems that have broken (or no) pty support. (There might still be problems on old [pre-2.8] Solaris, Irix and HP/UX. Not having accounts on such machines I cannot really test it all.) SqueakFFIPrims is now enabled and bundled with the VM as an external plugin (and various patches for PPC have been submitted to the libffi folks as a result ;). Hopefully this will allow Unix Squeakers to drink tea on the croquet lawn along with everyone else. Build: Build process now uses a configure script generated from the VERY LATEST autoconf (2.53) and libtool (1.4.2) that I downloaded _direct_ from gnu.org and lovingly installed by hand (rather than using the broken ones that were in pkgsrc and which created practically unusable configure scripts in 3.2-4). Many associated diverse changes in the *.{ac,in} files due to incompatibilities in the new autoconf. (Obviously this only applies to `configure' as shipped from our factory. If you regenerate `configure' for yourself then everything depends on your autoconf [not mine] and your [fictitious] warranty is immediately void. ;) configure now recognises `--with-gnu-awk[=gawk]' to force gawk even on systems where mawk is the default. PLEASE use this flag if you have problems rather than complaining to me about gnuify not working. configure now recognises `--without-npsqueak' to exclude browser support (npsqueak) in the build. (Browser support is experimental and not [yet] quite the final thing that Bert and I are aiming for. Use at your own risk.) SqueakFFIPrims is enabled conditionally on ffi.h and libffi.so (the latter becomes a library dependency of the plugin). The header and library must be in your compiler's default search paths. Support: inisqueak now looks first for `squeak.{image,changes}' in the libdir, to let sysadmins link to the preferred VM. If more than one VM is in libdir then inisqueak presents a list and lets you choose. It also has some options: -b avoid all interaction (exit status => success) -l list available VM versions -n install but don't start up Manual page updated to include the new options, etc. Prebuilt distributions: I can't be bothered rebooting my powerbook to make a NetBSD/macppc distribution. (In the whole time that I have been making BSD binaries available, only two people ever downloaded them.) If I'm wrong (maybe hundreds of BSD fans are secretly downloading them from uiuc?) then tell me and I'll get off my rear end and build one. ================================================ FILE: vm/src/from_squeak/unix/doc/3.2-6.RELEASE_NOTES ================================================ 3.2-6 released on 2002-11-27. This release consolidates the VM support required by Croquet (which is missing in 3.2) and that required by several 3.2 plugins (that are missing in Croquet). It should work just fine with 3.2, 3.4 and Croquet images. Major changes since 3.2-5: VM: New VM sources generated (for Croquet compatibility). The core is now generated out of a 3.4a-5125 image and runs Croquet fine on the build machine. Various small changes in several places for Darwin compatibility. The `-secure' option has been removed. Plugins: Updated OpenGL code for B3DAcceleratorPlugin. _Many_ thanks to Bert Freudenberg for this. OSProcessPlugin updated to 3.0.2. Build: Updated to autoconf-2.54. Builds out of the box on Darwin, either headless or with X11 support (tested with XDarwin 4.2.1.1 on darwin6.2). NOTE: there are still bugs in autoconf (more precisely, in aclocal and libtool) concerning darwin. If you rebuild the configure script (by running `autoconf' or `make' in the config dir) then the resulting configure script may not work (the build will fail when trying to create shared libs for external plugins). If you are affected by this then I can send you my patched versions of ltcf-c.sh and aclocal.m4. You have been warned! Problems with libGLs that depend on libpthread should be fixed. Link errors in sqUnixMozilla on BSD should no longer occur. Removed the majority of the ridiculous dependencies in the RPM. ================================================ FILE: vm/src/from_squeak/unix/doc/3.5-1devel.RELEASE_NOTES ================================================ Major departures from 3.4: - MacOSX is now fully supported (Quartz window, audio input/output, drag&drop, etc.). X11 is also supported (if installed on the host machine). - Display and sound support code has been moved out of the main executable into runtime modules. The choice of display method (Quartz, X11, no display at all) and sound (MacOSX CoreAudio, OSS, NAS, Sun, no sound at all) can be changed via command-line options when staring the VM. - A new option `-nodisplay' has been added. It differs from `-headless' in that the former disables display entirely (making the memory footprint of the VM smaller) while the latter loads the display code but does not open the Window (but allowing the possibility of retroactively opening the window at a some later time). - A new option `-nosound' has been added and does for sound what `-nodisplay' does for the display. - Memory allocation for the heap is now dynamic, based on mmap(). The heap will grow and shrink as the image's memory requirements change over time. This can be disabled by giving the option `-memory <N>[nk]' which tells the VM to use a fixed-size heap. A new option `-mmap <N>[mk]' is provided to limit the size to which mmap() will dynamically grow the heap (the default is 1Gbyte or 75% of your available virtual memory, whichever is smaller). If both options are given then `-memory' has precedence (disabling the mmap()-based memory allocator). - The configure option `--with-audio=...' has been removed. configure will arrange to build as many sound modules for which it can find the required headers/libraries. - configure will also build as many window system support modules for which it can find headers/libraries. The options `--without-x' and `--without-quartz' are available to explicitly disable one or both. ================================================ FILE: vm/src/from_squeak/unix/doc/3.6-3.RELEASE_NOTES ================================================ 3.6-3 released on 2004-04-03. This release finalises the long series of 3.6 beta and gamma releases and includes significant changes in the VM since 3.4. It should be compatible with all image versions. Changes since 3.4-2: VM: Substantial rewrite of Mac OS X sound code for OS 10.3 (Panther). Better scroll wheel and 3-button mouse behaviour on OS X. Improved dock icon behaviour on OSX. New icons for OSX (thanks to Bert Freudenberg). Improvements to character set conversion on Solaris. Date/time reported on files now consistent with output from "ls". New dead key support for X11 (activated if LC_CTYPE/LC_ALL set) New option "-nointl" turns off dead key support in X11. Various OpenGL fixes. Improved timing for Delays. Copy/paste compatibility problems with Qt fixed (thanks to Ned Konz). Display/sound drivers are now dynamically loaded (and can be selected) at startup. New display driver "fbdev" for running on the Linux console. Plugins: New OSProcessPlugin from Dave Lewis. Support for new Socket primitive listenOn:backlogSize:interface:. Problems with plugin and shared library searching fixed. Build: Mac OS X dependency on libiconv removed. Dependencies on glibc2.3 in the 386 GNU/Linux version removed. RPMs have "root.bin" ownership on everything. Please report bugs to: ian.piumarta@inria.fr ================================================ FILE: vm/src/from_squeak/unix/doc/3.7-7.RELEASE_NOTES ================================================ Changes since 3.6 "final": VM: Netscape plugin understands "imageName" and "failureURL" attributes in <embed ...> tags. sqGnu.h asm() statemtnts fixed for gcc-3.1 compatibility. Less noise from dlopen() and friends when probing for plugins. Problems preventing more than one external plugin from loading in Mac OS X fixed. Use of alloca() made more portable. Obscure bug fixed that prevented socket options being set on some platforms. NPSqueak improvements and bug fixes from Bert Freudenberg and Jens Lincke. New environment variable SQUEAK_USERDIR used to find plugin image; defaults to 'My Squeak'. (May break for users of shells other than bash. Contact Bert if you have problems.) Interpreter changes from Ned to avoid image segment loading errors caused by oops >= 2GB. VM drivers: Preliminary drag-and-drop support added to the X11 display driver. vm-sound-NAS driver explicitly depends on libaudio. New option '-glxdebug <n>' sets OpenGL debug message level for X11 display. Plugins: Additional checks for external data in SocketPlugin. New OSProcessPlugin (including XDpyPlg and AioPlg). Build: Optimisation flags default to '-O' if compiler not recognised. SVN repository now includes contents of 'src' directory used to build Unix binaries. No more endless searching for the right combination of obscure VMM version and image updates. Build instructions updated for SVN and recent organisational changes. 'gnuify' inserts a #error into gnu-interp.c if it detects a problem (causing cpp to barf cleanly with a comprehensible error message, rather than leaving the compiler to spew hundreds of obscure error messages). Documentation: URIs updated to reflect recent organisational changes. ================================================ FILE: vm/src/from_squeak/unix/doc/3.7b-2.RELEASE_NOTES ================================================ Changes since 3.6 "final": VM: sqGnu.h asm() statemtnts fixed for gcc-3.1 compatibility. Less noise from dlopen() and friends when probing for plugins. Problems preventing more than one external plugin from loading in Mac OS X fixed. VM drivers: vm-sound-NAS driver explicitly depends on libaudio. New option '-glxdebug <n>' sets OpenGL debug message level for X11 display. Plugins: Additional checks for external data in SocketPlugin. ================================================ FILE: vm/src/from_squeak/unix/doc/3.7b-3.RELEASE_NOTES ================================================ Changes since 3.6 "final": VM: sqGnu.h asm() statemtnts fixed for gcc-3.1 compatibility. Less noise from dlopen() and friends when probing for plugins. Problems preventing more than one external plugin from loading in Mac OS X fixed. VM drivers: Preliminary drag-and-drop support added to the X11 display driver. vm-sound-NAS driver explicitly depends on libaudio. New option '-glxdebug <n>' sets OpenGL debug message level for X11 display. Plugins: Additional checks for external data in SocketPlugin. ================================================ FILE: vm/src/from_squeak/unix/doc/3.7b-4.RELEASE_NOTES ================================================ Changes since 3.6 "final": VM: sqGnu.h asm() statemtnts fixed for gcc-3.1 compatibility. Less noise from dlopen() and friends when probing for plugins. Problems preventing more than one external plugin from loading in Mac OS X fixed. VM drivers: Preliminary drag-and-drop support added to the X11 display driver. vm-sound-NAS driver explicitly depends on libaudio. New option '-glxdebug <n>' sets OpenGL debug message level for X11 display. Plugins: Additional checks for external data in SocketPlugin. ================================================ FILE: vm/src/from_squeak/unix/doc/3.7b-5.RELEASE_NOTES ================================================ Changes since 3.6 "final": VM: Netscape plugin understands "imageName" and "failureURL" attributes in <embed ...> tags. sqGnu.h asm() statemtnts fixed for gcc-3.1 compatibility. Less noise from dlopen() and friends when probing for plugins. Problems preventing more than one external plugin from loading in Mac OS X fixed. VM drivers: Preliminary drag-and-drop support added to the X11 display driver. vm-sound-NAS driver explicitly depends on libaudio. New option '-glxdebug <n>' sets OpenGL debug message level for X11 display. Plugins: Additional checks for external data in SocketPlugin. ================================================ FILE: vm/src/from_squeak/unix/doc/3.9-4.RELEASE_NOTES ================================================ Changes since 3.7-7: VM: The VM is now fully compatible with Croquet and will run both Squeak and Croquet images. Attribute 1006 answers a string describing the VM build environment. VM drivers: vm-display-X11 no longer generates Squeak KeyUp events for X KeyRelease events that came from autorepeat. Plugins: Parts of aio and sqUnixSocket modified to support asynchronous notification of i/o, and a new entry point (aioSleep) added for the benefit of the Mac VM. (In some cases it's trivial to demonstrate a factor of 2000 improvement in socket throughput.) See Additional Notes below if rebuilding from source. SO_REUSEPORT has been enabled for any architectures that support it. At the time of writing Darwin does but Linux does not. UUID plugin now supported and bundled. OSProcess and XDisplayControl plugins updated from Dave Lewis's distributions and bundled. CroquetPlugin and FloatMathPlugin from Andreas are now bundled for full Croquet compatibility. Securiry plugin now obeys SQUEAK_USERDIR if set. Additional Notes: The socket improvements depend on a tiny (and otherwise insignificant) change in the Interpreter. If you are regenerating source code from VMMaker, first open a browser and navigate to Interpreter>>forceInterruptCheck. If this method is defined as forceInterruptCheck "force an interrupt check ASAP" interruptCheckCounter := -1000 then you *must* append one line to it: forceInterruptCheck "force an interrupt check ASAP" interruptCheckCounter := -1000. nextPollTick := 0 before generating the core VM source. Without this modification the socket support code changes will have no effect whatsoever on the latency and throughput achievable from Squeak code. ================================================ FILE: vm/src/from_squeak/unix/doc/3.9-7.RELEASE_NOTES ================================================ Changes since 3.9-4: VM: Add code to resolve links (and aliases on OS X) in path names. Check for and use nanosleep() on all platforms. This prevents the VM comsuming 100% CPU on some platforms due to small (1ms) timeouts in ioRelinquishProcessor() coming from the idle process. Reset interruptCheckCounter at the end of ioRelinquishProcessor to ensure input semaphore signalled promptly after events. Plugins: Added Balloon3DEngine (aka Squeak3D) plugin and bundled it. Added AioPlugin plugin and bundled it. ================================================ FILE: vm/src/from_squeak/unix/doc/COPYING ================================================ Source files below 'platforms/Cross' in this distribution that do not contain individual copyright and license notices, and Source files below 'platforms/unix/src' in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Viewpoints Research Institute and other authors/contributors as listed. All rights reserved. All other source files below platforms/unix in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Ian Piumarta and other authors/contributors listed in individual source files. All rights reserved. For all of the above files: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: vm/src/from_squeak/unix/doc/COPYRIGHT ================================================ Source files below 'platforms/Cross' in this distribution that do not contain individual copyright and license notices, and Source files below 'platforms/unix/src' in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Viewpoints Research Institute and other authors/contributors as listed. All rights reserved. All other source files below platforms/unix in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Ian Piumarta and other authors/contributors listed in individual source files. All rights reserved. For all of the above files: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node1.html ================================================ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!--Converted with LaTeX2HTML 2002-2-1 (1.70) original version by: Nikos Drakos, CBLU, University of Leeds * revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan * with significant contributions from: Jens Lippmann, Marek Rouchal, Martin Wilck and others --> <HTML> <HEAD> <TITLE>Contents

Contents



2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node2.html ================================================ 0 The easy way

0 The easy way

Beginning with version 3.7-7, everything you need is included with the Unix sources regardless of how you obtained them - either as a tarball or by repository checkout. (This was done to eliminate frequent problems encountered by people combining the repository Unix and Cross sources with a set of incompatible generated sources.)

If you extract a tarball then you will have a top-level directory named Squeak-X.Y-Z (for some values of X, Y, and Z). If you are checking out from a repository, you can call the direcory anything you like; for example:


  $ svn co http://squeak.hpl.hp.com/svn/squeak/trunk squeak

will leave you with a directory called squeak. (We'll assume from now on that the directory is called squeak.)

Next change to the 'unix' directory within the sources that you just checked out (or extracted from the tarball):


  $ cd squeak/platforms/unix

Build the VM and plugins by running make:


  $ make

Then install the VM, plugins and manual pages by running make again (with superuser privileges):


  $ sudo make install

To delete the temporary files created during the build process, run make one last time:


  $ make clean

That's all there is to it.

2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node3.html ================================================ 1 The hard way: configure, build, install

1 The hard way: configure, build, install

Unix Squeak is built using the (almost) universal ``configure; make; make install''. If you haven't come across this before, read on...

Create a build directory (which we will call `blddir' from now on) and then `cd' to it:


  $ mkdir blddir
  $ cd blddir

A convenient place is just next to the platforms directory, like this:


  $ cd squeak
  $ ls
  platforms src ...
  $ mkdir bld
  $ cd bld

Create the build environment by running the script configure which lives in the platforms/unix/config directory.

Note: The configure script accepts lots of options. To see a list of them, run: `configure --help'

Assuming you've created the blddir next to platforms, this would be:


  $ ../platforms/unix/config/configure

Note: This assumes that the VMMaker sources are in `../src'. However, since the Unix Squeak support code is independent of the image version from which VMMaker generated the interpreter/plugin sources, it is possible that your source distribution comes with more than one src directory (corresponding to more than one image version used to generate the sources). In such cases you will have to tell configure which source version to use, via the `--with-src' option. For example, if there are two source directories called src-3.2gamma-4857 and src-3.3.alpha-4881 then you would use one of the following commands:

  $ .../configure --with-src=src-3.2gamma-4857
        or
  $ .../configure --with-src=src-3.3alpha-4881

Build the VM and plugins by running make:


  $ make

Note: If you want to build just the VM (without external plugins) or just the external plugins (without the VM) then you can use: `make squeak' or `make plugins' respectively.

Finally install the VM, plugins and manual pages:


  $ su root
  $ make install

2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node4.html ================================================ 2 Generating your own VM and plugin sources Subsections

2 Generating your own VM and plugin sources

Generating your own VM/plugin sources might be necessary for various reasons:

  • you want to change the mix of internal vs. external plugins
  • you want to remove some plugins from the VM that you will never use
  • you've pulled in some updates that modify the Interpreter or plugins
  • you've filed-in (or written) a whole new plugin
  • etc...

Version 3.2 (and later) of Unix Squeak use VMMaker to generate the core interpreter and plugin sources.

Start Squeak in the top-level directory (the one containing the platforms directory); for example:


  $ ls
  src platforms ...
  $ squeak MyCoolPlugin.image

Open a VMMakerTool and modify the setup to your liking.

Note: The VMMaker configuration used to build the distributions of Unix Squeak is available in platforms/unix/config/VMMaker.config.

Then click on the relevant ``generate ...'' button. You can now `configure; make; make install' in your blddir (as described above).

Note: You only need to run configure once for a given blddir (on the same host). If you modify the choice of plugins (or change whether they're internal/external) then you can update the build environment by running the config.status script in the bldddir, like this:
  $ squeak MyCoolPlugin.image
  ... generate new sources ...
  $ cd blddir
  $ ./config.status
  $ make
This is much faster than running configure all over again. (In fact, make should detect any changes to the plugin configuration and re-run config.status for you automatically.)

Note: `configure' doesn't actually create any files. The last thing it does is run `config.status' to create the configured files in blddir from the corresponding file.ins in the unix/config directory. So in the remainder of this document the phrase `during configuration' means either when running `configure' for the first time or running `config.status' to update an already configured build environment.

2.1 How configure finds the src directory

Starting with version 3.7 configure looks in two places for the src directory, in the following order, and uses the first one that it finds:

  • the top-level directory (the one containing the platforms directory);
  • the platforms/unix directory.

In other words, if you want to use your own generated sources without deleting the built-in generated sources, generating them into a src directory next to platforms (and then re-running configure) will do what you want.

2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node5.html ================================================ 3 Adding your own plugins Subsections

3 Adding your own plugins

Note: This section is intended primarily for plugin developers.

If your plugin requires no platform-specific tweaks then there's nothing for you to do. configure (and config.status) will provide a default Makefile for it that should work. If your plugin requires only platform-independent tweaks (and/or additional hand-written code) then these go in platforms/Cross/plugins, and there's nothing for you to do (in Unixland).

On the other hand, if you require special configure tests or additional declarations/rules in your plugin's Makefile then you need to specify them explicitly.

Note: Unix Squeak subscribes to the following philopsophy:

Absolutely everything that is specific to Unix (sources, headers, configure and Makefile extensions, etc.) lives under platforms/unix.

In other words: there is not (nor aught there be) any Unix-related information under the platforms/Cross directory. (Unix Squeak is entirely encapsulated under platforms/unix and is utterly immune to ``random junk'' elsewhere in the platforms tree.)

First you must create a new directory under platforms/unix/plugins named after your plugin. This directory will hold the files describing the additional configuration checks and/or Makefile contents. For example, if your plugin is called ``MyCoolPlugin'' then


  $ mkdir platforms/unix/plugins/MyCoolPlugin

would be the thing to do. (The following sections will refer to this directory as platdep since the full path is quite a mouthful of typing for my lazy fingers.)

3.1 Plugin-specific configuration

Your plugin can ask configure to run additional tests (and to set additional variables in its output files) simply by including a file called acinclude.m4 in it's platdep directory.

Note: The configure script is `compiled' from several other files. If you create a `platdep./acinclude.m4' file then you must `recompile' configure. You can do this by `cd'ing to unix/config and running `make', or (if you have GNU make) from the blddir like this:

  $ make -C ../platforms/unix/config

In addition to the usual autoconf macros, the following macros are available specifically for Squeak plugins to use:

3.1.1 AC_PLUGIN_CHECK_LIB(lib,func)

This is similar to the autoconf `AC_CHECK_LIB' macro.

func is the name of a function required by the plugin, defined in the external (system) library lib. The macro checks that the library is available (via `-llib') and then adds it to the list of libraries required by the plugin (see the explanation of [plibs] in Section 3.2.1 for a description of how library dependencies for plugins are handled).

If func cannot be found in lib then the plugin will be disabled and a message to that effect printed during configuration. (The VM can still be built, without rerunning VMMaker or reconfiguring, and the plugin will simply be ommitted from it.)

3.1.2 AC_PLUGIN_DEFINE_UNQUOTED(keyword,text)

This is similar to the autoconf `AC_DEFINE_UNQUOTED' macro.

keyword is a Makefile keyword (usually of the form `[name]') and text is arbitrary text to be associated with it. Calling this macro causes mkmf to substitute text for all occurrences of keyword in the Makefile generated for the plugin.

3.1.3 Plugin-specific variables

The following variables are also set during the execution of a plugin-specific acinclude.m4:

${plugin} is the name of the plugin;
${topdir} is the path to the top-level directory (containing platforms);
${vmmdir} is the path to the VMMaker `src' directory.

3.2 Plugin-specific Makefile declarations and rules

Three mechanisms are avilable for this:

  1. scanning additional dirrectories for sources and headers;
  2. including a few additional lines into the default Makefile; and
  3. replacing entirely the default Makefile with a hand-written one.
(The last option isn't as scary as it might sound: read on...)

3.2.1 The anatomy of a plugin's Makefile

Before proceeding, let's take a minute to understand how Unix Squeak compiles and links files in its default Makefile for plugins. The default Makefile looks like this:

# default Makefile for Unix Squeak plugins

[make_cfg]
[make_plg]

XINCLUDES       = [includes]
OBJS            = [targets]
TARGET          = [target]
PLIBS           = [plibs]

[make_inc]

$(TARGET) : $(OBJS) Makefile
        $(LINK) $(TARGET) $(OBJS) $(PLIBS)

[make_targets]

.force :

Note: The keywords appearing between `[ square brackets ]' are substituted during configuration by a preprocessor called `mkmf' according to the kind of plugin (internal/external) being built.

[make_cfg] is the configured variable section. It contains the platform-specific information gleaned by configure while it was figuring out which compiler you have, what flags your linker needs, where to install stuff, and so on.

[make_plg] contains a handful of definitions which depend on whether the plugin is being compiled as internal or external:

o    the extension for object files
a    the extension for plugins
COMPILE    the command to compile a source file into an object file
LINK    the command to link one or more object files into a plugin

For internal plugins: $o is `.o' and $a is `.a'. $(COMPILE) is the C compiler (`$(CC) ... -o', so the first thing after the command must be the output filename) and $(LINK) is archiver (`ar -rc', again requiring the output file to follow immediately). Note that internal plugins are built as `ar' archives before being linked into the final binary.

For external plugins: $o is `.lo', $a is `.la', and $(COMPILE) and $(LINK) are invocations of `libtool' to create position-independent objects and shared libraries (with a `-o' appearing right at the end, so the first thing after the command must be the output filename).

[includes] is a list of `-Idir' compiler flags, one for each of the directories

  src/plugins/name
  src/vm/intplugins/name
  platforms/Cross/plugins/name
  platforms/unix/plugins/name
in which at least one header file is present.

[targets] is a list of object files corresponding to the source (.c) files found in the directories:

  src/plugins/name/*.c
  src/vm/intplugins/name/*.c
  platforms/Cross/plugins/name/*.c
  platforms/unix/plugins/name/*.c
where each source file has been stripped of the directory name and had the `.c' converted into `$o'.

[target] is the name of the plugin, including the $a extension.

[plibs] is a list of zero or more libraries on which the plugin depends (as detected using the macro AC_PLUGIN_CHECK_LIB in the plugin-specific acinclude.m4). If the plugin is being built internally then this list is empty and the required libraries are included in the final link command. If the plugin is being built externally then the plugin itself (a shared object) is linked against these libraries (via [plist]) rather than with the main VM binary.

(This is to ensure that a missing shared object needed by an external plugin will only affect the operation of that plugin and not prevent the rest of the VM from running, which would be the case if the entire VM were linked against it.)

[make_inc] is the contents of the Makefile.inc file in your plugin's platdep directory (or empty if this file doesn't exist).

[make_targets] is a list of rules for building the files listed in [targets]. Each rule looks like this:

        name$o : original/source/dir/name.c
                $(COMPILE) name$o original/source/dir/name.c

3.2.2 A note about $(COMPILE) and $(LINK) commands

You should never pass additional flags to these commands explicitly. This is because you cannot know how they are defined. (Their definitions depend on whether the plugin is being built internally or externally -- and might even change radically in future releases of Unix Squeak.)

Instead you should pass additional compiler/linker flags to these commands by setting the following variables in `Makefile.inc' or `Makefile.in':

XCPPFLAGS    `-I' flags for cpp
XDEFS    `-D' flags for cpp
XCFLAGS    anything to be passed to the compiler
XLDFLAGS    anything to be passed to the linker
Note: `mkmf' already uses `XINCLUDES' to pass the list of directories containing plugin header files to cpp. You can redefine it if you like, but make sure that `[includes]' appears in its definition (or in the definition of `XCPPFLAGS').

3.2.3 Specifying additional source directories

mkmf looks for a file in your plugin's platdep directory called `mkmf.subdirs'. If this file exists then it should contain a list of directory names relative to the top-level directory (the one containing the src and platform directories). These directories will be added to the list of locations searched for `.c' and `.h' files while constructing the substitutions for `[includes]', `[targets]' and `[make_targets]'.

3.2.4 Including additional material in the default Makefile

If the file platdep/Makefile.inc exists then mkmf will substitute its contents into the Makefile in place of the [make_inc] keyword.

Note: Makefile.inc is read into the Makefile under construction before mkmf performs substitutions on the `[keyword]'s. In other words, your Makefile.inc can use the above keywords to include relevant declarations and rules without worrying about whether the plugin is internal or external.

3.2.5 Replacing the default Makefile entirely

If neither of the above are sufficient then you can create a complete Makefile template called platdep/Makefile.in. mkmf will use this template instead of the default Makefile template shown earlier, and will perform keyword substitutions on it as described above to create the final Makefile. (In other words, simply copying the default template shown earlier will result in a Makefile identical to the one that mkmf would have produced by default.

3.3 Examples taken from existing plugins

By way of example we'll look at how two existing plugins specialise their configuration and Makefiles.

3.3.1 Configuration

The B3DAcceleratorPlugin requires OpenGL in order to compile. The file unix/plugins/B3DAcceleratorPlugin/acinclude.m4 contains a single call to an autoconf-style macro:

    AC_PLUGIN_SEARCH_LIBS(glIsEnabled, GL)

This works similarly to the autoconf `AC_SEARCH_LIBS' macro: If a library libGL.{a,so} (OpenGL) exists and exports the function glIsEnabled() then `-lGL' is added to the final VM link command. Otherwise the plugin is disabled (and a message warning of the fact is printed).

Note: There's a bug here. This should also check for `GL_VERSION_1_1' in headers.

3.3.2 Customising the Makefile

The Mpeg3Plugin requires a (modified) libmpeg to be compiled along with it. The sources for this library are in (several) subdirectories of Cross/Meg3Plugin and they require additional cpp definitions in order to compile correctly.

To cope with the additional directories, unix/plugins/Mpeg3Plugin/mkmf.subdirs simply lists them:

  platforms/Cross/plugins/Mpeg3Plugin/libmpeg
  platforms/Cross/plugins/Mpeg3Plugin/libmpeg/audio
  platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video

To cope with the additional cpp definitions, we could have written a tiny Makefile.inc containing:

    XDEFS   = -DNOPTHREADS

Unfortunately the additional source directories contain various utility and test programs (which must not be built) so we cannot rely on mkmf generating the correct [targets] list.

Instead we just copy the default Makefile ``template'' (shown above) as Mpeg3Plugin/Makefile.in and insert the required list of targets (and cpp definition) manually. The end result looks like this:

# Makefile.in for Mpeg3Plugin in Unix Squeak

[make_cfg]
[make_plg]

TARGET  = Mpeg3Plugin$a

PLUGIN  = Mpeg3Plugin$o
VIDEO   = getpicture$o headers$o idct$o macroblocks$o etc...
AUDIO   = dct$o header$o layer1$o layer2$o layer3$o etc...
LIBMPEG = bitstream$o changesForSqueak$o libmpeg3$o etc...

OBJS    = $(PLUGIN) $(VIDEO) $(AUDIO) $(LIBMPEG)

XINCLUDES       = [includes]
XDEFS           = -DNOPTHREADS

$(TARGET) : $(OBJS) Makefile
        $(LINK) $(TARGET) $(OBJS)

[make_targets]

.force :

Note: The default `[make_targets]' will contain additional rules for the objects that we're trying to avoid building (because it's built from an exhaustive list of `.c' files in the source directories). This does no harm since the offending rules can never be triggered (their targets are not listed in `OBJS').

3.4 Coping with VMMaker quirks

VMMaker will refuse to compile a plugin if it thinks the plugin requires platform support. This is ``all-or-nothing'': if platform support is required on one platform then it is required on all platforms (even if the plugin compiles quite happily without platform support in Unix).

The easiest way to add ``null'' platform support is to place an empty `Makefile.inc' in the plugin's platdep directory. (To see this in action, look in unix/plugins/JPEGReadWriter2Plugin.)

3.5 If all else fails

(Where ``all else failing'' is defined as: ``after trying for 20 minutes and still getting nowhere''.)

If you're writing a plugin that needs platform support (beyond dumb inclusion of a few additional `.c' files) and this document has been of no help at all (or if you understood it but you're still suffering from ``all else failing'') then send me mail and I'll be happy to help you with the various platdep files.

2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node6.html ================================================ Index

Index

$(COMPILE)
3.2.2
$(LINK)
3.2.2
$(XCFLAGS)
3.2.2
$(XCPPFLAGS)
3.2.2
$(XDEFS)
3.2.2
$(XINCLUDES)
3.2.2
$(XLDFLAGS)
3.2.2
[includes]
3.2.1
[make_cfg]
3.2.1
[make_inc]
3.2.1
[make_plg]
3.2.1
[make_targets]
3.2.1
[plibs]
3.2.1
[target]
3.2.1
[targets]
3.2.1
AC_PLUGIN_CHECK_LIB
3.1.1
AC_PLUGIN_DEFINE_UNQUOTED
3.1.2
acinclude.m4
3.1
example
3.3.1
additional plugin source directories
3.2.3
build directory
configuring
1
creating
1
config.status
2
versus configure
2
configure
3.1
macros for plugins
3.1
recreating
3.1
emergency services
3.5
Makefile
3.2.1
avoiding $(XINCLUDES)
3.2.2
compile/link commands
3.2.2
keyword substitution
3.2.1
passing extra flags
3.2.2
replacing
3.2.5
target rules
3.2.1
Makefile keywords
[includes]
3.2.1
[make_cfg]
3.2.1
[make_inc]
3.2.1
[make_plg]
3.2.1
[make_targets]
3.2.1
[plibs]
3.2.1
[target]
3.2.1
[targets]
3.2.1
Makefile.in
3.2.5
example
3.3.2
Makefile.inc
3.2.4
example
3.3.2
keyword substitution
3.2.4
mkmf
3.2.1
additional source directories
3.2.3
default header directories
3.2.1
default source directories
3.2.1
mkmf.subdirs
3.2.3
example
3.3.2
plugin
Makefile
3.2
Makefile anatomy
3.2.1
adding your own
3
configuring
3.1
target rules
3.2.1
Unix-specific directory
3
Unix-specific files
3
VMMaker
configuration file
2
missing platform support
3.4
reference
2



2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource-node7.html ================================================ About this document ...

About this document ...

Building Unix Squeak (>= 3.2) from source

This document was generated using the LaTeX2HTML translator Version 2002-2-1 (1.70)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -dir tmp -local_icons -auto_prefix -show_section_numbers -split 4 HowToBuildFromSource.tex

The translation was initiated by on 2005-03-17


2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource.css ================================================ /* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ .MATH { font-family: "Century Schoolbook", serif; } .MATH I { font-family: "Century Schoolbook", serif; font-style: italic } .BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold } /* implement both fixed-size and relative sizes */ SMALL.XTINY { font-size : xx-small } SMALL.TINY { font-size : x-small } SMALL.SCRIPTSIZE { font-size : smaller } SMALL.FOOTNOTESIZE { font-size : small } SMALL.SMALL { } BIG.LARGE { } BIG.XLARGE { font-size : large } BIG.XXLARGE { font-size : x-large } BIG.HUGE { font-size : larger } BIG.XHUGE { font-size : xx-large } /* heading styles */ H1 { } H2 { } H3 { } H4 { } H5 { } /* mathematics styles */ DIV.displaymath { } /* math displays */ TD.eqno { } /* equation-number cells */ /* document-specific styles come next */ DIV.navigation { } DIV.alltt { } DIV.quote { } SPAN.tt { } SPAN.textit { font-style: italic } SPAN.arabic { } SPAN.textbf { font-weight: bold } SPAN.textsf { font-style: italic } #hue544 { color: #0000ff; } #hue546 { color: #0000ff; } #hue548 { color: #0000ff; } #hue550 { color: #0000ff; } #hue552 { color: #0000ff; } #hue554 { color: #0000ff; } #hue556 { color: #0000ff; } #hue558 { color: #0000ff; } #hue560 { color: #ff0000; } #hue562 { color: #0000ff; } #hue564 { color: #0000ff; } #hue566 { color: #0000ff; } #hue570 { color: #ff0000; } #hue574 { color: #0000ff; } #hue579 { color: #ff0000; } #hue593 { color: #000000; } #hue608 { color: #000000; } #hue613 { color: #000000; } #hue655 { color: #000000; } #txt149 { text-decoration: underline; } ================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/HowToBuildFromSource.html ================================================ Building Unix Squeak ( 3.2) from source

Building Unix Squeak (>= 3.2) from source

Ian Piumarta

<ian.piumarta@squeakland.org>

Last edited: 2005-03-17 12:43:23 by piumarta on squeak.hpl.hp.com
Translated to .ps/.pdf/.html/.txt: March 17, 2005





2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.html/index.html ================================================ Building Unix Squeak ( 3.2) from source

Building Unix Squeak (>= 3.2) from source

Ian Piumarta

<ian.piumarta@squeakland.org>

Last edited: 2005-03-17 12:43:23 by piumarta on squeak.hpl.hp.com
Translated to .ps/.pdf/.html/.txt: March 17, 2005





2005-03-17
================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.ps ================================================ %!PS-Adobe-2.0 %%Creator: dvips(k) 5.92b Copyright 2002 Radical Eye Software %%Title: HowToBuildFromSource.dvi %%Pages: 13 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o HowToBuildFromSource.ps %+ HowToBuildFromSource.dvi %DVIPSParameters: dpi=600, compressed %DVIPSSource: TeX output 2005.03.17:1243 %%BeginProcSet: texc.pro %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B /chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ /cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 {2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ 1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: special.pro %! TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N /vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N /rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N /@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ /hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B /@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ /urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known {userdict/md get type/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup length 20 add dict copy def}if end md begin /letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale }if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState save N userdict maxlength dict begin/magscale true def normalscale currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts /psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def @MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N /@beginspecial{SDict begin/SpecialSave save N gsave normalscale currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N} N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N /setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{ pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B /rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end %%EndProcSet %%BeginProcSet: color.pro %! TeXDict begin/setcmykcolor where{pop}{/setcmykcolor{dup 10 eq{pop setrgbcolor}{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll }repeat setrgbcolor pop}ifelse}B}ifelse/TeXcolorcmyk{setcmykcolor}def /TeXcolorrgb{setrgbcolor}def/TeXcolorgrey{setgray}def/TeXcolorgray{ setgray}def/TeXcolorhsb{sethsbcolor}def/currentcmykcolor where{pop}{ /currentcmykcolor{currentrgbcolor 10}B}ifelse/DC{exch dup userdict exch known{pop pop}{X}ifelse}B/GreenYellow{0.15 0 0.69 0 setcmykcolor}DC /Yellow{0 0 1 0 setcmykcolor}DC/Goldenrod{0 0.10 0.84 0 setcmykcolor}DC /Dandelion{0 0.29 0.84 0 setcmykcolor}DC/Apricot{0 0.32 0.52 0 setcmykcolor}DC/Peach{0 0.50 0.70 0 setcmykcolor}DC/Melon{0 0.46 0.50 0 setcmykcolor}DC/YellowOrange{0 0.42 1 0 setcmykcolor}DC/Orange{0 0.61 0.87 0 setcmykcolor}DC/BurntOrange{0 0.51 1 0 setcmykcolor}DC /Bittersweet{0 0.75 1 0.24 setcmykcolor}DC/RedOrange{0 0.77 0.87 0 setcmykcolor}DC/Mahogany{0 0.85 0.87 0.35 setcmykcolor}DC/Maroon{0 0.87 0.68 0.32 setcmykcolor}DC/BrickRed{0 0.89 0.94 0.28 setcmykcolor}DC/Red{ 0 1 1 0 setcmykcolor}DC/OrangeRed{0 1 0.50 0 setcmykcolor}DC/RubineRed{ 0 1 0.13 0 setcmykcolor}DC/WildStrawberry{0 0.96 0.39 0 setcmykcolor}DC /Salmon{0 0.53 0.38 0 setcmykcolor}DC/CarnationPink{0 0.63 0 0 setcmykcolor}DC/Magenta{0 1 0 0 setcmykcolor}DC/VioletRed{0 0.81 0 0 setcmykcolor}DC/Rhodamine{0 0.82 0 0 setcmykcolor}DC/Mulberry{0.34 0.90 0 0.02 setcmykcolor}DC/RedViolet{0.07 0.90 0 0.34 setcmykcolor}DC /Fuchsia{0.47 0.91 0 0.08 setcmykcolor}DC/Lavender{0 0.48 0 0 setcmykcolor}DC/Thistle{0.12 0.59 0 0 setcmykcolor}DC/Orchid{0.32 0.64 0 0 setcmykcolor}DC/DarkOrchid{0.40 0.80 0.20 0 setcmykcolor}DC/Purple{ 0.45 0.86 0 0 setcmykcolor}DC/Plum{0.50 1 0 0 setcmykcolor}DC/Violet{ 0.79 0.88 0 0 setcmykcolor}DC/RoyalPurple{0.75 0.90 0 0 setcmykcolor}DC /BlueViolet{0.86 0.91 0 0.04 setcmykcolor}DC/Periwinkle{0.57 0.55 0 0 setcmykcolor}DC/CadetBlue{0.62 0.57 0.23 0 setcmykcolor}DC /CornflowerBlue{0.65 0.13 0 0 setcmykcolor}DC/MidnightBlue{0.98 0.13 0 0.43 setcmykcolor}DC/NavyBlue{0.94 0.54 0 0 setcmykcolor}DC/RoyalBlue{1 0.50 0 0 setcmykcolor}DC/Blue{1 1 0 0 setcmykcolor}DC/Cerulean{0.94 0.11 0 0 setcmykcolor}DC/Cyan{1 0 0 0 setcmykcolor}DC/ProcessBlue{0.96 0 0 0 setcmykcolor}DC/SkyBlue{0.62 0 0.12 0 setcmykcolor}DC/Turquoise{0.85 0 0.20 0 setcmykcolor}DC/TealBlue{0.86 0 0.34 0.02 setcmykcolor}DC /Aquamarine{0.82 0 0.30 0 setcmykcolor}DC/BlueGreen{0.85 0 0.33 0 setcmykcolor}DC/Emerald{1 0 0.50 0 setcmykcolor}DC/JungleGreen{0.99 0 0.52 0 setcmykcolor}DC/SeaGreen{0.69 0 0.50 0 setcmykcolor}DC/Green{1 0 1 0 setcmykcolor}DC/ForestGreen{0.91 0 0.88 0.12 setcmykcolor}DC /PineGreen{0.92 0 0.59 0.25 setcmykcolor}DC/LimeGreen{0.50 0 1 0 setcmykcolor}DC/YellowGreen{0.44 0 0.74 0 setcmykcolor}DC/SpringGreen{ 0.26 0 0.76 0 setcmykcolor}DC/OliveGreen{0.64 0 0.95 0.40 setcmykcolor} DC/RawSienna{0 0.72 1 0.45 setcmykcolor}DC/Sepia{0 0.83 1 0.70 setcmykcolor}DC/Brown{0 0.81 1 0.60 setcmykcolor}DC/Tan{0.14 0.42 0.56 0 setcmykcolor}DC/Gray{0 0 0 0.50 setcmykcolor}DC/Black{0 0 0 1 setcmykcolor}DC/White{0 0 0 0 setcmykcolor}DC end %%EndProcSet TeXDict begin 39158280 55380996 1000 600 600 (HowToBuildFromSource.dvi) @start %DVIPSBitmapFont: Fa cmbx12 12 37 /Fa 37 122 df12 D45 DI 49 DII<163FA25E5E5D5DA25D5D 5D5DA25D92B5FCEC01F7EC03E7140715C7EC0F87EC1F07143E147E147C14F8EB01F0EB03 E0130714C0EB0F80EB1F00133E5BA25B485A485A485A120F5B48C7FC123E5A12FCB91280 A5C8000F90C7FCAC027FB61280A531417DC038>I<0007150301E0143F01FFEB07FF91B6 FC5E5E5E5E5E16804BC7FC5D15E092C8FC01C0C9FCAAEC3FF001C1B5FC01C714C001DF14 F09039FFE03FFC9138000FFE01FC6D7E01F06D13804915C0497F6C4815E0C8FC6F13F0A3 17F8A4EA0F80EA3FE0487E12FF7FA317F05B5D6C4815E05B007EC74813C0123E003F4A13 80D81FC0491300D80FF0495AD807FEEBFFFC6CB612F0C65D013F1480010F01FCC7FC0101 13C02D427BC038>I67 D69 D72 DI77 D80 D86 D<903801FFE0011F13FE017F 6D7E48B612E03A03FE007FF84848EB1FFC6D6D7E486C6D7EA26F7FA36F7F6C5A6C5AEA00 F090C7FCA40203B5FC91B6FC1307013F13F19038FFFC01000313E0000F1380381FFE0048 5A5B127F5B12FF5BA35DA26D5B6C6C5B4B13F0D83FFE013EEBFFC03A1FFF80FC7F0007EB FFF86CECE01FC66CEB8007D90FFCC9FC322F7DAD36>97 D99 DIII< DAFFE0137E010F9039FE03FF80013FEBFF8F90B812C048D9C07F133F489038001FF84848 EB0FFC4848903907FE1F80001F9238FF0F00496D90C7FCA2003F82A8001F93C7FCA26D5B 000F5D6C6C495A6C6C495A6C9038C07FF04890B55A1680D8078F49C8FC018013E0000F90 CAFCA47F7F7F90B612C016FC6CEDFF8017E06C826C16FC7E000382000F82D81FF0C77ED8 3FC014074848020113808248C9FC177FA46D15FF007F17006D5C6C6C4A5A6C6C4A5AD80F FEEC3FF83B07FFC001FFF0000190B612C06C6C92C7FC010F14F8D9007F90C8FC32427DAC 38>II<137C48B4FC4813804813C0A24813E0A56C13C0A26C13806C1300EA007C90C7FCAAEB 7FC0EA7FFFA512037EB3AFB6FCA518467CC520>I107 DI<90277F8007FEEC0FFCB590263FFFC090387FFF8092B5D8F001B512 E002816E4880913D87F01FFC0FE03FF8913D8FC00FFE1F801FFC0003D99F009026FF3E00 7F6C019E6D013C130F02BC5D02F86D496D7EA24A5D4A5DA34A5DB3A7B60081B60003B512 FEA5572D7CAC5E>I<90397F8007FEB590383FFF8092B512E0028114F8913987F03FFC91 388F801F000390399F000FFE6C139E14BC02F86D7E5CA25CA35CB3A7B60083B512FEA537 2D7CAC3E>II<90397FC00F F8B590B57E02C314E002CF14F89139DFC03FFC9139FF001FFE000301FCEB07FF6C496D13 804A15C04A6D13E05C7013F0A2EF7FF8A4EF3FFCACEF7FF8A318F017FFA24C13E06E15C0 6E5B6E4913806E4913006E495A9139DFC07FFC02CFB512F002C314C002C091C7FCED1FF0 92C9FCADB67EA536407DAC3E>II<90387F807FB53881FFE0028313F0028F13F8ED8FFC91389F1FFE000313 BE6C13BC14F8A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5B612E0A5272D7DAC2E >I<90391FFC038090B51287000314FF120F381FF003383FC00049133F48C7121F127E00 FE140FA215077EA27F01E090C7FC13FE387FFFF014FF6C14C015F06C14FC6C800003806C 15806C7E010F14C0EB003F020313E0140000F0143FA26C141F150FA27EA26C15C06C141F A26DEB3F8001E0EB7F009038F803FE90B55A00FC5CD8F03F13E026E007FEC7FC232F7CAD 2C>III 119 DII E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fb cmss10 10 7 /Fb 7 117 df<12FEA70707788617>46 D97 D101 D<903907E001F890383FFC1F90397F FE7FFC90B6FC5A3A03F81FF8003907F00FE0EBE00748486C7EA248486C7EA86C6C485AA2 6C6C485AEBF00F6C6C485A48B55A92C7FC485BEB3FFCEB07E090C9FCA37F7F6CB512C015 FC15FF4815804815C03A3F80007FE048C7EA0FF0007E140700FEEC03F8481401A46C1403 007E15F0D87F80130F6C6CEB1FE03A1FFC01FFC06CB612806C1500000114FC6C6C13F001 0790C7FC26387EA52A>103 D110 D<14F0EAFC07130F133F137F13FF00FD130013FCEAFFF05B5BA25B90C7FCA35AB3A41426 7AA51C>114 D116 D E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fc cmsy10 10 3 /Fc 3 104 df15 D102 D<12FCEAFFC0EA07F0EA01FCEA007E7F80131F 80130FB3A7801307806D7E6D7EEB007EEC1FF0EC07F8EC1FF0EC7E00495A495A495A5C13 0F5CB3A7131F5C133F91C7FC137E485AEA07F0EAFFC000FCC8FC1D537ABD2A>I E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fd cmti10 10 30 /Fd 30 122 df12 D<150C151C153815F0EC01E0EC03C0EC0780EC0F00141E5C147C5C5C495A1303 495A5C130F49C7FCA2133EA25BA25BA2485AA212035B12075BA2120F5BA2121FA290C8FC A25AA2123EA2127EA2127CA412FC5AAD1278A57EA3121C121EA2120E7EA26C7E6C7EA212 001E5274BD22>40 D<140C140E80EC0380A2EC01C015E0A2140015F0A21578A4157C153C AB157CA715FCA215F8A21401A215F0A21403A215E0A21407A215C0140F1580A2141F1500 A2143EA25CA25CA2495AA2495A5C1307495A91C7FC5B133E133C5B5B485A12035B48C8FC 120E5A12785A12C01E527FBD22>I44 D<120EEA3F80127F12FFA31300127E123C0909778819>46 D65 D<003FB539800FFFFEA326007F80C7EA7F8091C8EA3F00173E4915 3CA2491538A20001167817705BA2000316F05F5BA2000715015F5BA2000F15035F5BA200 1F150794C7FC5BA2003F5D160E5BA2007F151E161C90C8FCA2163C4815385A16781670A2 16F04B5A5E1503007E4A5A4BC8FC150E6C143E6C6C5B15F0390FC003E03907F01FC00001 B5C9FC38007FFCEB1FE0373B70B83E>85 D<14F8EB07FE90381F871C90383E03FE137CEB F801120148486C5A485A120FEBC001001F5CA2EA3F801403007F5C1300A21407485C5AA2 140F5D48ECC1C0A2141F15831680143F1587007C017F1300ECFF076C485B9038038F8E39 1F0F079E3907FE03FC3901F000F0222677A42A>97 D<133FEA1FFFA3C67E137EA313FE5B A312015BA312035BA31207EBE0F8EBE7FE9038EF0F80390FFC07C013F89038F003E013E0 D81FC013F0A21380A2123F1300A214075A127EA2140F12FE4814E0A2141F15C05AEC3F80 A215005C147E5C387801F8007C5B383C03E0383E07C0381E1F80D80FFEC7FCEA01F01C3B 77B926>I<147F903803FFC090380FC1E090381F0070017E13784913383901F801F83803 F003120713E0120FD81FC013F091C7FC485AA2127F90C8FCA35A5AA45AA3153015381578 007C14F0007EEB01E0003EEB03C0EC0F806CEB3E00380F81F83803FFE0C690C7FC1D2677 A426>II<147F903803FFC090380FC1E090383F00F0017E13785B485A485A485A12 0F4913F8001F14F0383F8001EC07E0EC1F80397F81FF00EBFFF891C7FC90C8FC5A5AA55A A21530007C14381578007E14F0003EEB01E0EC03C06CEB0F806CEB3E00380781F83803FF E0C690C7FC1D2677A426>IIIII107 DIII<147F903803FFC090380FC1F09038 1F00F8017E137C5B4848137E4848133E0007143F5B120F485AA2485A157F127F90C7FCA2 15FF5A4814FEA2140115FC5AEC03F8A2EC07F015E0140F007C14C0007EEB1F80003EEB3F 00147E6C13F8380F83F03803FFC0C648C7FC202677A42A>I<9039078007C090391FE03F F090393CF0787C903938F8E03E9038787FC00170497EECFF00D9F0FE148013E05CEA01E1 13C15CA2D80003143FA25CA20107147FA24A1400A2010F5C5E5C4B5A131F5EEC80035E01 3F495A6E485A5E6E48C7FC017F133EEC70FC90387E3FF0EC0F8001FEC9FCA25BA21201A2 5BA21203A25B1207B512C0A3293580A42A>I<3903C003F0390FF01FFC391E783C0F381C 7C703A3C3EE03F8038383FC0EB7F800078150000701300151CD8F07E90C7FCEAE0FE5BA2 120012015BA312035BA312075BA3120F5BA3121F5BA3123F90C9FC120E212679A423> 114 D<14FE903807FF8090380F83C090383E00E04913F00178137001F813F00001130313 F0A215E00003EB01C06DC7FC7FEBFFC06C13F814FE6C7F6D13807F010F13C01300143F14 1F140F123E127E00FE1480A348EB1F0012E06C133E00705B6C5B381E03E06CB45AD801FE C7FC1C267AA422>II<13 F8D803FEEB01C0D8078FEB03E0390E0F8007121E121C0038140F131F007815C01270013F 131F00F0130000E015805BD8007E133FA201FE14005B5D120149137EA215FE120349EBFC 0EA20201131E161C15F813E0163CD9F003133814070001ECF07091381EF8F03A00F83C78 E090393FF03FC090390FC00F00272679A42D>I<01F0130ED803FC133FD8071EEB7F80EA 0E1F121C123C0038143F49131F0070140FA25BD8F07E140000E08013FEC6485B150E1201 5B151E0003141C5BA2153C000714385B5DA35DA24A5A140300035C6D48C7FC0001130E38 00F83CEB7FF8EB0FC0212679A426>I<01F01507D803FC903903801F80D8071E903907C0 3FC0D80E1F130F121C123C0038021F131F49EC800F00701607A249133FD8F07E168000E0 ED000313FEC64849130718000001147E5B03FE5B0003160E495BA2171E00070101141C01 E05B173C1738A217781770020314F05F0003010713016D486C485A000190391E7C078028 00FC3C3E0FC7FC90393FF81FFE90390FE003F0322679A437>I<903907E007C090391FF8 1FF89039787C383C9038F03E703A01E01EE0FE3803C01F018013C0D8070014FC48148000 0E1570023F1300001E91C7FC121CA2C75AA2147EA214FEA25CA21301A24A1370A2010314 F016E0001C5B007E1401010714C000FEEC0380010F1307010EEB0F0039781CF81E903838 7C3C393FF03FF03907C00FC027267CA427>I<13F0D803FCEB01C0D8071EEB03E0D80E1F 1307121C123C0038140F4914C01270A249131FD8F07E148012E013FEC648133F16001201 5B5D0003147E5BA215FE00075C5BA214015DA314035D14070003130FEBF01F3901F87FE0 38007FF7EB1FC7EB000F5DA2141F003F5C48133F92C7FC147E147C007E13FC387001F8EB 03E06C485A383C1F80D80FFEC8FCEA03F0233679A428>I E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fe cmitt10 10 24 /Fe 24 122 df46 D<1738177C177E17FEEE01FC160317F8EE07F0EE0FE0A2EE1FC0EE3F80A2EE7F0016 FEA24B5A4B5AA24B5A4B5A151F5E4B5A4BC7FCA215FE4A5AA24A5A4A5AA24A5A4A5A143F 5D4AC8FC14FEA2495A495AA2495A495AA2495A495A137F91C9FC13FE485AA2485A485AA2 485A485AA2485A48CAFC5A5A5A5A12702F417CB92C>I77 D97 DII<9138 03FF804A13C0A380EC001F1680A2153FA21600A25DA2157EEB03F090380FFCFEEB3FFF49 5B90B5FC3801FE1F3803FC0FD807F85B380FF00713E0EA1FC001805B123F13005A007E5C A2140F12FE485CA291381FC180EDC7E0EC3F87A2EC7F8F02FF13C049130F6C5AD87E07EB 1F80D87F0F133F6CB612006C13DFEC8FFE3907FE07FC3901F801F0233376B22C>I<147F 903803FFC0010F13F0013F13F84913FCEBFFC13801FE004848137E485AD80FE013FE15FC 485A383F800190380007F848133F90B512F015E01580B5EAFE0014F000FCC8FCA6127E15 1C007F143E6C6C13FEEBC00F6CB5FC6C14FC6C14F0000114C039007FFE001F2475A32C> III<140FEC1F80EC3FC0A4EC1F80EC0F0091C7FCA8133FEBFFC0 000313F05A487FEA1FE1EA3FC11381EA7F01127EEAFE0300FC5B13075C1200130F5C131F A25C133FEC0060EC01F8137F137EEBFE0301FC13F01407EC0FE0141FEC3FC090B512806D 13005CEB1FF8EB07E01D3475B32C>105 D107 DII<3901F007F03907F81FFC39 0FFC7FFE486CB5FC48B6128090383FFE1F14F8007E13F014E0EB7FC012FE00FC13801400 49133FC6481400A348485B157EA24913FE0003ECFC18167EEBF00115F8000715FE020313 FC01E013F015F1000F15F8EDF3F001C013FF6E13E016C0496C13806CC7EA3E0027247AA3 2C>I<14FE903807FF80011F13E04913F090B5FC48EB83F83903FE01FCEBF800485A4848 137E485AA2485A90C7FC5A127EA215FE12FE4814FCA2140115F81403EC07F0A2EC0FE000 7EEB1FC0EC3F80007F13FFD83F8313006CB45A14F86C5B000313C0C648C7FC1F2476A32C >I<903907C00FC090391FF03FF090393FF8FFFCEB7FFD91B57E9039FE7FF87F01FC497E D801F801E01380EDC01FECFF8000031400495AA2EBF1FCEA00015CA20103143FA24A1400 A201075C167E16FE5E010F13014B5A15076E485A011F495A6E485A91B55A93C7FC495BEC 9FF8EC07E091C9FC5BA2137EA213FEA25BA21201A25BA2387FFFE0A2B57E6C5BA2293680 A32C>I114 DII<01F8EB01C0D803FEEB03E0486C13075A481380D83F9F130F131F007F15C0127E 013F131F00FE130000FC15805B017E133F120001FE14005B5D120149137EA2EDFE180003 157E9038F001FCA2140316FE913807F8FC140F9038F81FF92601FC3F13F890B6FC6C15F0 90397FFE7FE090393FF83FC090390FE00F8027247AA32C>I<003C903803800E003FECC0 1F267F8007EB3F80123F01C0141F0007130F1580A3141F000F020013001380A2001F495B D9003E133E5A123E027E137E007E157C007C137CA202FC13FC00FC5D485B010113015EA2 0103130300FC01FC5BD87C0713073A7E0FFE0FC0007FB6FC6C01BF5B6C011F90C7FC6C48 6C5A3903F803F8292479A32C>119 D<90391FC01F809039FFF07FE0489038F9FFF80007 90B5FC4815FCD81FF013F03A3FC07FE07E9039803FC0FED87F001381007E148300FE1403 48EC01FC16F891387F00F0C71400147EA214FEA25CA201011418001E157E003F5B127F01 8314FE00FF15FC01031301D8FE07EB03F839FC0FFC073A7E1FFE1FF0007FB612E06C15C0 023F1300390FFC1FFE3903F007F027247AA32C>I<017E143848B46C137C486D13FC5A48 7FD81FC71301D83F8714F81307127FD87E0F130300FE01C013F012FC131FEC8007000015 E0133F1400150F4914C0137E151FA201FE148049133FA2157F16005D5CEB7E0390387F0F FE14FF7F7F6D5BEB01FC90C7FC14015DA21403D807805B380FC007486C485A4A5AA29038 C07F804AC7FCEB83FEEBFFFC6C5B6C13E06C5BC648C8FC26367AA32C>I E %EndDVIPSBitmapFont %DVIPSBitmapFont: Ff cmtt10 10 75 /Ff 75 126 df<010F133C90381F807EA8013F13FE4A5AA4007FB612F0B712F8A4003F15 F03A007E01F800A5EBFE0301FC5BA6003FB612F0B712F8A46C15F03A01F807E000A30003 130F01F05BA86C486C5A25337DB22C>35 DI<143814FC13011303EB07F8EB0FF0EB1FC0EB3F80EB7F0013FE485A485A 5B12075B120F5B485AA2123F90C7FCA25A127EA312FE5AAC7E127EA3127F7EA27F121FA2 6C7E7F12077F12037F6C7E6C7E137FEB3F80EB1FC0EB0FF0EB07F8EB03FC130113001438 164272B92C>40 D<127012FC7E7E6C7E6C7EEA0FE06C7E6C7E6C7E6C7E137F7F1480131F 14C0130FEB07E0A214F01303A214F81301A314FC1300AC130114F8A3130314F0A2130714 E0A2EB0FC0131F1480133F14005B13FE485A485A485A485AEA3FC0485A48C7FC5A5A1270 164279B92C>II44 D<007FB6FCB71280A46C150021067B9B2C >I<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B708A2C>I<1507ED0F80151F A2153F16005D157E15FE5D14015D14035DA214075D140F5D141F5D143F92C7FC5C147E14 FE5CA213015C13035C13075C130F5C131F5CA2133F91C8FC5B137E13FE5B12015B12035B 12075BA2120F5B121F5B123F90C9FC5A127E12FE5AA25A127821417BB92C>I<1307497E A2131FA2133F137F13FF5A1207127FB5FC13DF139FEA7C1F1200B3AE007FB512E0B612F0 A36C14E01C3477B32C>49 DII I<000FB512FE4880A35D0180C8FCADEB83FE90389FFF8090B512E015F8819038FE03FE90 38F000FF01C07F49EB3F8090C7121F6C15C0C8120FA2ED07E0A4123C127EB4FC150F16C0 A248141F007EEC3F80007FEC7F006C6C5B6D485A391FF80FFC6CB55A6C5C000114C06C6C 90C7FCEB0FF823347CB22C>I<1278B712C016E0A316C000FCC7EA3F80ED7F0015FE0078 5CC712014A5A4A5A5D140F5D4A5A143F92C7FC5C147E14FE5C13015CA2495AA213075CA3 495AA4495AA5133F91C8FCAA131E23357CB32C>55 DI<121FEA3F80EA7FC0EAFFE0A5EA7F C0EA3F80EA1F00C7FCAE121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B2470A32C >58 DI<007FB612F0B712F8A4003F15F0CAFCA8003FB612F0B712F8A46C15F025 147DA22C>61 D<14FE497EA4497FA214EFA2130781A214C7A2010F7FA314C390381F83F0 A590383F01F8A490387E00FCA549137E90B512FEA34880A29038F8003FA34848EB1F80A4 000715C049130FD87FFEEBFFFC6D5AB514FE6C15FC497E27347EB32C>65 D<007FB512E015F8B612FE6C8016C03903F0003FED0FE0ED07F01503A2ED01F8A6ED03F0 A21507ED0FE0ED1FC0EDFF8090B612005D5D15FF16C09039F0001FE0ED07F0ED03F81501 ED00FCA216FE167EA616FE16FC1501ED03F8150FED3FF0007FB612E016C0B712806CECFE 0015F027337FB22C>I<02FF13700107EBE0F84913F9013F13FD4913FFEBFF813901FE00 7F4848131FD807F0130F1507485A491303485A150148C7FCA25A007EEC00F01600A212FE 5AAB7E127EA3007F15F06CEC01F8A26C7EA26C6C13036D14F06C6C130716E0D803FC131F 6C6CEB3FC03A00FF81FF806DB512006D5B010F5B6D13F00100138025357DB32C>I<007F B5FCB612C015F0816C803907E003FEEC00FFED7F80153FED1FC0ED0FE0A2150716F01503 16F81501A4ED00FCACED01F8A3150316F0A2150716E0150FED1FC0153FED7F80EDFF00EC 03FE007FB55AB65A5D15C06C91C7FC26337EB22C>I<007FB612F0B712F8A37E3903F000 01A7ED00F01600A4EC01E04A7EA490B5FCA5EBF003A46E5A91C8FCA5163C167EA8007FB6 12FEB7FCA36C15FC27337EB22C>I<007FB612F8B712FCA37ED803F0C7FCA716781600A5 15F04A7EA490B5FCA5EBF001A46E5A92C7FCAD387FFFE0B5FC805C7E26337EB22C>I<90 3901FC038090390FFF87C04913EF017F13FF90B6FC4813073803FC01497E4848137F4848 133F49131F121F5B003F140F90C7FCA2127EED078092C7FCA212FE5AA8913803FFF84A13 FCA27E007E6D13F89138000FC0A36C141FA27F121F6D133F120F6D137F6C7E6C6C13FF6D 5A3801FF076C90B5FC6D13EF011F13CF6DEB0780D901FCC7FC26357DB32C>II<007FB512F8B612FCA36C14F839000FC000B3B3A5 007FB512F8B612FCA36C14F81E3379B22C>I<0107B512804914C0A36D148090390003F0 00B3AF1218127EA2B4FCA24A5A48130F007F131F9038C07FC06CB55A6C91C7FC6C5B0003 13F838007FC022347BB22C>II<387FFFE0B57EA36C5BD803F0C8FCB3AE16F0ED01F8A8007FB6FCB7FCA36C15F02533 7DB22C>IIII<007FB512C0B612F88115FF6C15802603F00013C0153FED 0FE0ED07F0A2150316F81501A6150316F01507A2ED0FE0ED3FC015FF90B61280160015FC 5D15C001F0C8FCB0387FFF80B57EA36C5B25337EB22C>II<387FFFFCB67E15 E015F86C803907E007FE1401EC007F6F7E151FA26F7EA64B5AA2153F4BC7FCEC01FE1407 90B55A5D15E081819038E007FCEC01FE1400157F81A8160FEE1F80A5D87FFEEB1FBFB5EC FF00815E6C486D5AC8EA01F029347EB22C>I<90381FF80790B5EA0F804814CF000714FF 5A381FF01F383FC003497E48C7FC007E147F00FE143F5A151FA46CEC0F00007E91C7FC12 7F7FEA3FE0EA1FFCEBFFC06C13FC0003EBFFC06C14F06C6C7F01077F9038007FFEEC07FF 02001380153FED1FC0A2ED0FE0A20078140712FCA56CEC0FC0A26CEC1F806D133F01E0EB 7F009038FE01FF90B55A5D00F914F0D8F83F13C0D8700790C7FC23357CB32C>I<007FB6 12FCB712FEA43AFC007E007EA70078153CC71400B3AF90383FFFFCA2497F6D5BA227337E B22C>I<3B7FFF803FFFC0B56C4813E0A36C496C13C03B03F00001F800B3AF6D13030001 5DA26D130700005D6D130F017F495A6D6C485AECE0FF6DB5C7FC6D5B010313F86D5B9038 003F802B3480B22C>III< 3A3FFF03FFE0484913F0148714076C6D13E03A01F800FE007F0000495A13FE017E5BEB7F 03013F5B1487011F5B14CF010F5B14FF6D5BA26D90C7FCA26D5AA26D5AA2497EA2497EA2 497F81EB0FCF81EB1FC7EC87F0EB3F83EC03F8EB7F01017E7FEBFE00497F0001147E4913 7F000380491480151FD87FFEEBFFFC6D5AB514FE6C15FC497E27337EB22C>II<003FB612C048 15E0A4007EC7EA1FC0ED3F80A2ED7F00157E15FE4A5A003C5CC712034A5AA24A5A4A5AA2 4A5A4AC7FCA214FE495AA2495A495AA2495A495AA2495A49C8FCA213FE485AA24848EB03 C049EB07E01207485A5B121F485AA248C7FCB7FCA46C15C023337CB22C>I<387FFFFCB5 12FEA314FC00FCC7FCB3B3B3B512FC14FEA36C13FC17416FB92C>I<127812F87EA27E12 7E127F7E7F121F7F120F7F1207A27F12037F12017F12007F137E137F7F80131FA280130F 801307801303801301801300A280147E147F8081141F81140F811407811403A281140181 140081157E157F811680151FA2150FED070021417BB92C>I<387FFFFCB512FEA37EC712 7EB3B3B3387FFFFEB5FCA36C13FC17417DB92C>I<007FB6FCB71280A46C150021067B7D 2C>95 D<3801FFF0000713FE001F6D7E15E048809038C01FF81407EC01FC381F80000006 C77EC8127EA3ECFFFE131F90B5FC1203120F48EB807E383FF800EA7FC090C7FC12FE5AA4 7E007F14FEEB8003383FE01F6CB612FC6C15FE6C14BF0001EBFE1F3A003FF007FC27247C A32C>97 DI<903803FFE0011F13F8017F13FE48B5FC48804848C6FCEA0FF0485A49 137E4848131890C9FC5A127EA25AA8127EA2127F6C140F6DEB1F806C7E6D133F6C6CEB7F 003907FE03FF6CB55A6C5C6C6C5B011F13E0010390C7FC21247AA32C>IIIIII<1307EB1FC0A2497EA36D5AA20107C7FC90C8FCA7387FFFC080B5FC7EA2EA0007B3A8 007FB512FCB612FEA36C14FC1F3479B32C>I107 D<387FFFE0B57EA37EEA0003B3B3A5 007FB61280B712C0A36C158022337BB22C>I<3A7F83F007E09039CFFC1FF83AFFDFFE3F FCD87FFF13FF91B57E3A07FE1FFC3E01FCEBF83F496C487E01F013E001E013C0A301C013 80B33B7FFC3FF87FF0027F13FFD8FFFE6D13F8D87FFC4913F0023F137F2D2481A32C>I< 397FF01FE039FFF87FFC9038F9FFFE01FB7F6CB6FC00019038F03F80ECC01F02807FEC00 0F5B5BA25BB3267FFFE0B5FCB500F11480A36C01E0140029247FA32C>II<397FF0 1FE039FFF8FFF801FB13FE90B6FC6C158000019038F07FC09138801FE091380007F049EB 03F85BED01FC491300A216FE167EA816FE6D14FCA2ED01F86D13036DEB07F0150F913880 1FE09138E07FC091B51280160001FB5B01F813F8EC3FC091C8FCAD387FFFE0B57EA36C5B 27367FA32C>I<903903FC078090391FFF0FC0017F13CF48B512EF4814FF3807FE07380F F00148487E49137F4848133F90C7FC48141F127E150F5AA87E007E141FA26C143F7F6C6C 137F6D13FF380FF0033807FC0F6CB6FC6C14EF6C6C138F6D130FEB07F890C7FCAD0203B5 FC4A1480A36E140029367DA32C>II<90387FF8700003B512F8120F5A5A387FC00F387E00034813015AA3 6CEB00F0007F140013F0383FFFC06C13FE6CEBFF80000314E0C66C13F8010113FCEB0007 EC00FE0078147F00FC143F151F7EA26C143F6D133E6D13FE9038F007FC90B5FC15F815E0 00F8148039701FFC0020247AA32C>I<131E133FA9007FB6FCB71280A36C1500D8003FC8 FCB1ED03C0ED07E0A5EC800F011FEB1FC0ECE07F6DB51280160001035B6D13F89038003F E0232E7EAD2C>I<3A7FF003FF80486C487FA3007F7F0001EB000FB3A3151FA2153F6D13 7F3900FE03FF90B7FC6D15807F6D13CF902603FE07130029247FA32C>I<3A7FFF01FFFC B514FE148314016C15FC3A03E0000F80A26D131F00011500A26D5B0000143EA26D137E01 7C137CA2017E13FC013E5BA2EB3F01011F5BA21483010F5BA214C701075BA214EF01035B A214FF6D90C7FCA26D5A147C27247EA32C>II<3A3FFF03FFF048018713F8A36C010313F03A00FC007E005D90387E01F8013F5B EB1F83EC87E090380FCFC0903807EF80EB03FF6D90C7FC5C6D5A147C14FE130180903803 EF80903807CFC0EB0FC7EC83E090381F01F0013F7FEB7E00017C137C49137E0001803A7F FF01FFFC1483B514FE6C15FC140127247EA32C>I<3A7FFF01FFFCB5008113FE14831481 6C010113FC3A03E0000F806C7E151F6D140012005D6D133E137C017E137E013E137CA201 3F13FC6D5BA2EB0F815DA2EB07C1ECC3E0A2EB03E3ECE7C0130114F75DEB00FFA292C7FC 80A2143EA2147E147CA214FC5CA2EA0C01003F5BEA7F83EB87E0EA7E0F495A387FFF806C 90C8FC6C5A6C5AEA07E027367EA32C>I<15FF02071380141F147F91B512004913C04AC7 FCEB03F85CB31307EB1FE013FF007F5BB55A49C8FC6D7E6C7FC67F131FEB07F01303B380 EB01FEECFFC06D13FF6E1380141F14070200130021417BB92C>123 D125 D E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fg cmr10 10 79 /Fg 79 125 df11 DIII<001C131C007F137F39FF80FF80A26D13C0A3007F137F001C 131C00001300A40001130101801380A20003130301001300485B00061306000E130E485B 485B485B006013601A197DB92A>34 D<121C127FEAFF80A213C0A3127F121C1200A41201 1380A2120313005A1206120E5A5A5A12600A1979B917>39 D<146014E0EB01C0EB0380EB 0700130E131E5B5BA25B485AA2485AA212075B120F90C7FCA25A121EA2123EA35AA65AB2 127CA67EA3121EA2121F7EA27F12077F1203A26C7EA26C7E1378A27F7F130E7FEB0380EB 01C0EB00E01460135278BD20>I<12C07E12707E7E7E120F6C7E6C7EA26C7E6C7EA21378 A2137C133C133E131EA2131F7FA21480A3EB07C0A6EB03E0B2EB07C0A6EB0F80A31400A2 5B131EA2133E133C137C1378A25BA2485A485AA2485A48C7FC120E5A5A5A5A5A13527CBD 20>I<121C127FEAFF80A213C0A3127F121C1200A412011380A2120313005A1206120E5A 5A5A12600A19798817>44 DI<121C127FEAFF80A5EA7F00121C 0909798817>I<150C151E153EA2153C157CA2157815F8A215F01401A215E01403A215C0 1407A21580140FA215005CA2141E143EA2143C147CA2147814F8A25C1301A25C1303A249 5AA25C130FA291C7FC5BA2131E133EA2133C137CA2137813F8A25B1201A25B1203A25B12 07A25B120FA290C8FC5AA2121E123EA2123C127CA2127812F8A25A12601F537BBD2A>I< EB03F8EB1FFF90387E0FC09038F803E03901E000F0484813780007147C48487FA248C77E A2481580A3007EEC0FC0A600FE15E0B3007E15C0A4007F141F6C1580A36C15006D5B000F 143EA26C6C5B6C6C5B6C6C485A6C6C485A90387E0FC0D91FFFC7FCEB03F8233A7DB72A> I III<1538A2157815F8 A2140114031407A2140F141F141B14331473146314C313011483EB030313071306130C13 1C131813301370136013C01201EA038013005A120E120C5A123812305A12E0B712F8A3C7 3803F800AB4A7E0103B512F8A325397EB82A>I<0006140CD80780133C9038F003F890B5 FC5D5D158092C7FC14FC38067FE090C9FCABEB07F8EB3FFE9038780F803907E007E09038 8003F0496C7E12066E7EC87EA28181A21680A4123E127F487EA490C71300485C12E00060 5C12700030495A00385C6C1303001E495A6C6C485A3907E03F800001B5C7FC38007FFCEB 1FE0213A7CB72A>II<12301238123E003FB612E0A3 16C05A168016000070C712060060140E5D151800E01438485C5D5DC712014A5A92C7FC5C 140E140C141C5CA25CA214F0495AA21303A25C1307A2130FA3495AA3133FA5137FA96DC8 FC131E233B7BB82A>III<121C12 7FEAFF80A5EA7F00121CC7FCB2121C127FEAFF80A5EA7F00121C092479A317>I<121C12 7FEAFF80A5EA7F00121CC7FCB2121C127F5A1380A4127F121D1201A412031300A25A1206 A2120E5A121812385A1260093479A317>I<1538A3157CA315FEA34A7EA34A6C7EA20207 7FEC063FA2020E7FEC0C1FA2021C7FEC180FA202387FEC3007A202707FEC6003A202C07F 1501A2D901807F81A249C77F167FA20106810107B6FCA24981010CC7121FA2496E7EA349 6E7EA3496E7EA213E0707E1201486C81D80FFC02071380B56C90B512FEA3373C7DBB3E> 65 DI<913A01FF800180020FEBE003027F13F8903A01FF807E0790 3A03FC000F0FD90FF0EB039F4948EB01DFD93F80EB00FF49C8127F01FE153F1201484815 1F4848150FA248481507A2485A1703123F5B007F1601A35B00FF93C7FCAD127F6DED0180 A3123F7F001F160318006C7E5F6C7E17066C6C150E6C6C5D00001618017F15386D6C5CD9 1FE05C6D6CEB03C0D903FCEB0F80902701FF803FC7FC9039007FFFFC020F13F002011380 313D7BBA3C>IIII III76 DIIII82 DI<003FB812E0A3D9C003EB001F273E00 01FE130348EE01F00078160000701770A300601730A400E01738481718A4C71600B3B091 3807FF80011FB612E0A335397DB83C>IIII<007FB590383FFFFCA3C601F8 01071380D97FE0D903FCC7FC013FEC01F06D6C5C5F6D6C5C6D6C13034CC8FC6D6C130616 0E6D6C5B6DEB8018163891387FC0306E6C5A16E06E6C5A91380FF18015FB6EB4C9FC5D14 036E7EA26E7F6F7EA24B7E15DF9138019FF09138038FF8150F91380607FC91380E03FE14 0C4A6C7EEC38000230804A6D7E14E04A6D7E49486D7E130391C76C7E01066E7E130E010C 6E7E011C1401013C8101FE822607FF80010713E0B500E0013FEBFF80A339397EB83E>I< B500FE91383FFFE0A3000301E0913807FE00C649EC03F0017F6F5A606D6C5D6D6C140395 C7FC6D6C1406A26D6C5C6D6C141C17186D6C143817306D6D5B6E6C13E05F91383FE0015F 91381FF003DA0FF890C8FC1606913807FC0E160C913803FE1C913801FF185E6E13B016E0 157F6F5AB3A24B7E023FB512C0A33B397FB83E>I<003FB7FCA39039FC0001FE01C01303 49495A003EC7FC003C4A5A5E0038141F00784A5A12704B5A5E006014FF4A90C7FCA24A5A 5DC712074A5AA24A5A5D143F4A5AA24A5A92C8FC5B495AA2495A5C130F4948EB0180A249 5A5C137F495A16034890C7FC5B1203485AEE0700485A495C001F5D48485C5E4848495A49 130FB8FCA329397BB833>II<3901 800180000313033907000700000E130E485B001813180038133800301330007013700060 1360A200E013E0485BA400CE13CE39FF80FF806D13C0A3007F137FA2393F803F80390E00 0E001A1974B92A>II96 DIIIII<147E903803FF8090 380FC1E0EB1F8790383F0FF0137EA213FCA23901F803C091C7FCADB512FCA3D801F8C7FC B3AB487E387FFFF8A31C3B7FBA19>IIIIIII<2703F00FF0EB1FE000FFD93FFCEB 7FF8913AF03F01E07E903BF1C01F83803F3D0FF3800FC7001F802603F70013CE01FE14DC 49D907F8EB0FC0A2495CA3495CB3A3486C496CEB1FE0B500C1B50083B5FCA340257EA445 >I<3903F00FF000FFEB3FFCECF03F9039F1C01F803A0FF3800FC03803F70013FE496D7E A25BA35BB3A3486C497EB500C1B51280A329257EA42E>II<3903F01F E000FFEB7FF89038F1E07E9039F3801F803A0FF7000FC0D803FEEB07E049EB03F04914F8 49130116FC150016FEA3167FAA16FEA3ED01FCA26DEB03F816F06D13076DEB0FE001F614 C09039F7803F009038F1E07E9038F0FFF8EC1FC091C8FCAB487EB512C0A328357EA42E> II<3807E01F00FFEB7FC09038E1E3E09038E387F0380FE707EA03E613EE9038EC03E0 9038FC0080491300A45BB3A2487EB512F0A31C257EA421>II<1318A51338A31378A313F812011203 1207001FB5FCB6FCA2D801F8C7FCB215C0A93800FC011580EB7C03017E13006D5AEB0FFE EB01F81A347FB220>IIIIII<003FB512FCA2EB8003D83E0013F8003CEB07F00038EB0F E012300070EB1FC0EC3F800060137F150014FE495AA2C6485A495AA2495A495A495AA290 387F000613FEA2485A485A0007140E5B4848130C4848131CA24848133C48C7127C48EB03 FC90B5FCA21F247EA325>III E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fh cmbx10 10 44 /Fh 44 122 df<913803FFC0027F13F00103B512FC010FEB00FED93FF8133FD97FE0EBFF 8049485A5A1480484A13C04A6C1380A36F1300167E93C7FCA592383FFFC0B8FCA4000390 C7FCB3ABB5D8FC3F13FFA4303A7EB935>12 D39 D44 DII<49B4FC010F13E0017F13FC9038FF83FE4848C67E4848EB7F80 4848EB3FC04848EB1FE0A2001F15F0A24848EB0FF8A3007F15FCA500FF15FEB3007F15FC A4003F15F8A26D131F001F15F0A2000F15E06D133F000715C06C6CEB7F806C6CEBFF0039 00FF83FE6DB45A011F13F0010190C7FC27387CB630>48 D<141E143E14FE1307133FB5FC A313CFEA000FB3B3A6007FB61280A4213779B630>IIII<001C15C0D81F80130701F8137F90B61280A216005D5D 15F05D15804AC7FC14F090C9FCA8EB07FE90383FFFE090B512F89038FC07FC9038E003FF D98001138090C713C0120EC813E0157F16F0A216F8A21206EA3F80EA7FE012FF7FA44914 F0A26C4813FF90C713E0007C15C06C5B6C491380D9C0071300390FF01FFE6CB512F80001 14E06C6C1380D90FF8C7FC25387BB630>I58 D65 D67 D71 D73 D77 D80 D82 DI<003FB91280A4D9F800EBF003D87FC09238007FC049161F007EC7150FA2007C 1707A200781703A400F818E0481701A4C892C7FCB3AE010FB7FCA43B387DB742>I86 D97 D<13FFB5FCA412077EAF4AB47E020F13F0023F13FC9138FE03FFDAF000 13804AEB7FC00280EB3FE091C713F0EE1FF8A217FC160FA217FEAA17FCA3EE1FF8A217F0 6E133F6EEB7FE06E14C0903AFDF001FF80903AF8FC07FE009039F03FFFF8D9E00F13E0D9 C00390C7FC2F3A7EB935>I<903801FFC0010F13FC017F13FFD9FF8013802603FE0013C0 48485AEA0FF8121F13F0123F6E13804848EB7F00151C92C7FC12FFA9127FA27F123FED01 E06C7E15036C6CEB07C06C6C14806C6C131FC69038C07E006DB45A010F13F00101138023 257DA42A>I I<903803FF80011F13F0017F13FC3901FF83FE3A03FE007F804848133F484814C0001FEC 1FE05B003FEC0FF0A2485A16F8150712FFA290B6FCA301E0C8FCA4127FA36C7E1678121F 6C6C14F86D14F000071403D801FFEB0FE06C9038C07FC06DB51200010F13FC010113E025 257DA42C>II<161FD907FEEBFFC090387FFFE348B6EAEFE02607FE07138F260FF801131F48486C13 8F003F15CF4990387FC7C0EEC000007F81A6003F5DA26D13FF001F5D6C6C4890C7FC3907 FE07FE48B512F86D13E0261E07FEC8FC90CAFCA2123E123F7F6C7E90B512F8EDFF8016E0 6C15F86C816C815A001F81393FC0000F48C8138048157F5A163FA36C157F6C16006D5C6C 6C495AD81FF0EB07FCD807FEEB3FF00001B612C06C6C91C7FC010713F02B377DA530>I< 13FFB5FCA412077EAFED7FC0913803FFF8020F13FE91381F03FFDA3C01138014784A7E4A 14C05CA25CA291C7FCB3A3B5D8FC3F13FFA4303A7DB935>II<13FFB5 FCA412077EB3B3ACB512FCA4163A7DB91B>108 D<01FED97FE0EB0FFC00FF902601FFFC 90383FFF80020701FF90B512E0DA1F81903983F03FF0DA3C00903887801F000749DACF00 7F00034914DE6D48D97FFC6D7E4A5CA24A5CA291C75BB3A3B5D8FC1FB50083B512F0A44C 257DA451>I<01FEEB7FC000FF903803FFF8020F13FE91381F03FFDA3C01138000071378 0003497E6D4814C05CA25CA291C7FCB3A3B5D8FC3F13FFA430257DA435>I<903801FFC0 010F13F8017F13FFD9FF807F3A03FE003FE048486D7E48486D7E48486D7EA2003F814913 03007F81A300FF1680A9007F1600A3003F5D6D1307001F5DA26C6C495A6C6C495A6C6C49 5A6C6C6CB45A6C6CB5C7FC011F13FC010113C029257DA430>I<9039FF01FF80B5000F13 F0023F13FC9138FE07FFDAF00113800007496C13C06C0180EB7FE091C713F0EE3FF8A2EE 1FFCA3EE0FFEAA17FC161FA217F8163F17F06E137F6E14E06EEBFFC0DAF00313809139FC 07FE0091383FFFF8020F13E0020390C7FC91C9FCACB512FCA42F357EA435>I<9038FE03 F000FFEB0FFEEC3FFF91387C7F809138F8FFC000075B6C6C5A5CA29138807F80ED3F0015 0C92C7FC91C8FCB3A2B512FEA422257EA427>114 D<90383FF0383903FFFEF8000F13FF 381FC00F383F0003007E1301007C130012FC15787E7E6D130013FCEBFFE06C13FCECFF80 6C14C06C14F06C14F81203C614FC131F9038007FFE140700F0130114007E157E7E157C6C 14FC6C14F8EB80019038F007F090B512C000F8140038E01FF81F257DA426>I<130FA55B A45BA25B5BA25A1207001FEBFFE0B6FCA3000390C7FCB21578A815F86CEB80F014816CEB C3E090383FFFC06D1380903803FE001D357EB425>I<01FFEC3FC0B5EB3FFFA400071401 6C80B3A35DA25DA26C5C6E4813E06CD9C03E13FF90387FFFFC011F13F00103138030257D A435>IIIII E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fi cmbx12 14.4 33 /Fi 33 122 df12 D44 D<913803FFC0023F13FC91B6FC010315C0010F018113F0 903A1FFC003FF849486D7E49486D7E49486D7E48496D138048496D13C0A24817E04890C8 13F0A34817F8A24817FC49157FA3007F17FEA600FF17FFB3A5007F17FEA6003F17FCA26D 15FFA26C17F8A36C17F0A26C6D4913E0A26C6D4913C06C17806E5B6C6D4913006D6C495A D91FFCEB3FF8903A0FFF81FFF06D90B55A01011580D9003F01FCC7FC020313C0384F7BCD 43>48 D<157815FC14031407141F14FF130F0007B5FCB6FCA2147F13F0EAF800C7FCB3B3 B3A6007FB712FEA52F4E76CD43>II<91380FFFC091 B512FC0107ECFF80011F15E090263FF8077F9026FF800113FC4848C76C7ED803F86E7E49 1680D807FC8048B416C080486D15E0A4805CA36C17C06C5B6C90C75AD801FC1680C9FC4C 13005FA24C5A4B5B4B5B4B13C04B5BDBFFFEC7FC91B512F816E016FCEEFF80DA000713E0 030113F89238007FFE707E7013807013C018E07013F0A218F8A27013FCA218FEA2EA03E0 EA0FF8487E487E487EB57EA318FCA25E18F891C7FC6C17F0495C6C4816E001F04A13C06C 484A1380D80FF84A13006CB44A5A6CD9F0075BC690B612F06D5D011F1580010302FCC7FC D9001F1380374F7ACD43>I58 D<171F4D7E4D7EA24D7EA34C7FA24C7FA34C7FA34C7FA24C7FA34C8083047F80167E 8304FE804C7E03018116F8830303814C7E03078116E083030F814C7E031F81168083033F 8293C77E4B82157E8403FE824B800201835D840203834B800207835D844AB87EA24A83A3 DA3F80C88092C97E4A84A2027E8202FE844A82010185A24A820103854A82010785A24A82 010F855C011F717FEBFFFCB600F8020FB712E0A55B547BD366>65 D<932601FFFCEC01C0047FD9FFC013030307B600F81307033F03FE131F92B8EA803F0203 DAE003EBC07F020F01FCC7383FF0FF023F01E0EC0FF94A01800203B5FC494848C9FC4901 F8824949824949824949824949824990CA7E494883A2484983485B1B7F485B481A3FA248 49181FA3485B1B0FA25AA298C7FC5CA2B5FCAE7EA280A2F307C07EA36C7FA21B0F6C6D19 80A26C1A1F6C7F1C006C6D606C6D187EA26D6C606D6D4C5A6D6D16036D6D4C5A6D6D4C5A 6D01FC4C5A6D6DEE7F806D6C6C6C4BC7FC6E01E0EC07FE020F01FEEC1FF80203903AFFE0 01FFF0020091B612C0033F93C8FC030715FCDB007F14E0040101FCC9FC525479D261>67 D<932601FFFCEC01C0047FD9FFC013030307B600F81307033F03FE131F92B8EA803F0203 DAE003EBC07F020F01FCC7383FF0FF023F01E0EC0FF94A01800203B5FC494848C9FC4901 F8824949824949824949824949824990CA7E494883A2484983485B1B7F485B481A3FA248 49181FA3485B1B0FA25AA298C8FC5CA2B5FCAE6C057FB712E0A280A36C94C7003FEBC000 A36C7FA36C7FA27E6C7FA26C7F6C7FA26D7E6D7F6D7F6D6D5E6D7F6D01FC93B5FC6D13FF 6D6C6D5C6E01F0EC07FB020F01FEEC1FF10203903AFFF001FFE0020091B6EAC07F033FEE 001F030703FC1307DB007F02E01301040149CAFC5B5479D26A>71 D73 D77 D<003FBC1280A59126C0 003F9038C0007F49C71607D87FF8060113C001E08449197F49193F90C8171FA2007E1A0F A3007C1A07A500FC1BE0481A03A6C994C7FCB3B3AC91B912F0A553517BD05E>84 D86 D97 DI<913801FFF8021FEBFF8091B612F0010315FC010F9038C0 0FFE903A1FFE0001FFD97FFC491380D9FFF05B4817C048495B5C5A485BA2486F138091C7 FC486F1300705A4892C8FC5BA312FFAD127F7FA27EA2EF03E06C7F17076C6D15C07E6E14 0F6CEE1F806C6DEC3F006C6D147ED97FFE5C6D6CEB03F8010F9038E01FF0010390B55A01 001580023F49C7FC020113E033387CB63C>I<4DB47E0407B5FCA5EE001F1707B3A49138 01FFE0021F13FC91B6FC010315C7010F9038E03FE74990380007F7D97FFC0101B5FC4948 7F4849143F484980485B83485B5A91C8FC5AA3485AA412FFAC127FA36C7EA37EA26C7F5F 6C6D5C7E6C6D5C6C6D49B5FC6D6C4914E0D93FFED90FEFEBFF80903A0FFFC07FCF6D90B5 128F0101ECFE0FD9003F13F8020301C049C7FC41547CD24B>I<913803FFC0023F13FC49 B6FC010715C04901817F903A3FFC007FF849486D7E49486D7E4849130F48496D7E481780 48497F18C0488191C7FC4817E0A248815B18F0A212FFA490B8FCA318E049CAFCA6127FA2 7F7EA218E06CEE01F06E14037E6C6DEC07E0A26C6DEC0FC06C6D141F6C6DEC3F806D6CEC FF00D91FFEEB03FE903A0FFFC03FF8010390B55A010015C0021F49C7FC020113F034387C B63D>I103 DI<137F497E000313E0 487FA2487FA76C5BA26C5BC613806DC7FC90C8FCADEB3FF0B5FCA512017EB3B3A6B612E0 A51B547BD325>I108 D110 D<913801FFE0021F13FE91B612C0010315F0010F9038807FFC903A1FFC 000FFED97FF86D6C7E49486D7F48496D7F48496D7F4A147F48834890C86C7EA24883A248 486F7EA3007F1880A400FF18C0AC007F1880A3003F18006D5DA26C5FA26C5F6E147F6C5F 6C6D4A5A6C6D495B6C6D495B6D6C495BD93FFE011F90C7FC903A0FFF807FFC6D90B55A01 0015C0023F91C8FC020113E03A387CB643>I<903A3FF001FFE0B5010F13FE033FEBFFC0 92B612F002F301017F913AF7F8007FFE0003D9FFE0EB1FFFC602806D7F92C76C7F4A824A 6E7F4A6E7FA2717FA285187F85A4721380AC1A0060A36118FFA2615F616E4A5BA26E4A5B 6E4A5B6F495B6F4990C7FC03F0EBFFFC9126FBFE075B02F8B612E06F1480031F01FCC8FC 030313C092CBFCB1B612F8A5414D7BB54B>I<90397FE003FEB590380FFF80033F13E04B 13F09238FE1FF89139E1F83FFC0003D9E3E013FEC6ECC07FECE78014EF150014EE02FEEB 3FFC5CEE1FF8EE0FF04A90C7FCA55CB3AAB612FCA52F367CB537>114 D<903903FFF00F013FEBFE1F90B7FC120348EB003FD80FF81307D81FE0130148487F4980 127F90C87EA24881A27FA27F01F091C7FC13FCEBFFC06C13FF15F86C14FF16C06C15F06C 816C816C81C681013F1580010F15C01300020714E0EC003F030713F015010078EC007F00 F8153F161F7E160FA27E17E07E6D141F17C07F6DEC3F8001F8EC7F0001FEEB01FE9039FF C00FFC6DB55AD8FC1F14E0D8F807148048C601F8C7FC2C387CB635>I<143EA6147EA414 FEA21301A313031307A2130F131F133F13FF5A000F90B6FCB8FCA426003FFEC8FCB3A9EE 07C0AB011FEC0F8080A26DEC1F0015806DEBC03E6DEBF0FC6DEBFFF86D6C5B021F5B0203 13802A4D7ECB34>II119 D<007FB500F090387FFFFEA5C66C48C7000F90C7FC6D6CEC07 F86D6D5C6D6D495A6D4B5A6F495A6D6D91C8FC6D6D137E6D6D5B91387FFE014C5A6E6C48 5A6EEB8FE06EEBCFC06EEBFF806E91C9FCA26E5B6E5B6F7E6F7EA26F7F834B7F4B7F92B5 FCDA01FD7F03F87F4A486C7E4A486C7E020F7FDA1FC0804A486C7F4A486C7F02FE6D7F4A 6D7F495A49486D7F01076F7E49486E7E49486E7FEBFFF0B500FE49B612C0A542357EB447 >II E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fj cmr9 9 36 /Fj 36 122 df<123C127EB4FCA21380A2127F123D1201A412031300A25A1206120E120C 121C5A5A126009177A8715>44 DI<123C127E12FFA4127E123C 08087A8715>I<1530157815F8A215F01401A215E01403A215C01407A21580140FA21500 5CA2143EA2143C147CA2147814F8A25C1301A25C1303A25C1307A2495AA291C7FC5BA213 1E133EA2133C137CA2137813F8A25B1201A25B1203A2485AA25B120FA290C8FC5AA2121E 123EA2123C127CA2127812F8A25A12601D4B7CB726>II<13075B5B137FEA07FFB5FC13BFEAF83F1200B3B3A2497E 007FB51280A319327AB126>IIII<000C14C0380FC00F90B5128015005C5C14 F014C0D80C18C7FC90C8FCA9EB0FC0EB7FF8EBF07C380FC03F9038001F80EC0FC0120E00 0CEB07E0A2C713F01403A215F8A41218127E12FEA315F0140712F8006014E01270EC0FC0 6C131F003C14806CEB7F00380F80FE3807FFF8000113E038003F801D347CB126>I<1230 123C003FB6FCA34814FEA215FC0070C7123800601430157015E04814C01401EC0380C7EA 07001406140E5C141814385CA25CA2495A1303A3495AA2130FA3131F91C7FCA25BA55BA9 131C20347CB126>55 D<123C127E12FFA4127E123C1200B0123C127E12FFA4127E123C08 207A9F15>58 D76 DI<007F B712FEA390398007F001D87C00EC003E0078161E0070160EA20060160600E01607A34816 03A6C71500B3AB4A7E011FB512FCA330337DB237>84 D97 DII<153FEC0FFFA3EC007F81 AEEB07F0EB3FFCEBFC0F3901F003BF3907E001FF48487E48487F8148C7FCA25A127E12FE AA127E127FA27E6C6C5BA26C6C5B6C6C4813803A03F007BFFC3900F81E3FEB3FFCD90FE0 130026357DB32B>III104 DI 107 DI<2703F01FE013FF 00FF90267FF80313C0903BF1E07C0F03E0903BF3803E1C01F02807F7003F387FD803FE14 70496D486C7EA2495CA2495CB3486C496C487EB53BC7FFFE3FFFF0A33C217EA041>I<39 03F01FC000FFEB7FF09038F1E0FC9038F3807C3907F7007EEA03FE497FA25BA25BB3486C EB7F80B538C7FFFCA326217EA02B>II<3903F03F8000FFEBFFE09038F3C0F89038F7007ED807FE7F6C48EB1F804914 C049130F16E0ED07F0A3ED03F8A9150716F0A216E0150F16C06D131F6DEB3F80160001FF 13FC9038F381F89038F1FFE0D9F07FC7FC91C8FCAA487EB512C0A325307EA02B>I<9038 07F00390383FFC07EBFC0F3901F8038F3807E001000F14DF48486CB4FC497F123F90C77E 5AA25A5AA9127FA36C6C5B121F6D5B000F5B3907E003BF3903F0073F3800F81EEB3FF8EB 0FE090C7FCAAED7F8091380FFFFCA326307DA029>I<3803E07C38FFE1FF9038E38F8090 38E71FC0EA07EEEA03ECA29038FC0F8049C7FCA35BB2487EB512E0A31A217FA01E>II<1330A51370A313F0A21201A212 031207381FFFFEB5FCA23803F000AF1403A814073801F806A23800FC0EEB7E1CEB1FF8EB 07E0182F7FAD1E>II120 D<3A7FFF807FF8A33A07F8001FC00003EC0F800001EC070015066C6C5BA26D131C017E13 18A26D5BA2EC8070011F1360ECC0E0010F5BA2903807E180A214F3010390C7FC14FBEB01 FEA26D5AA31478A21430A25CA214E05CA2495A1278D8FC03C8FCA21306130EEA701CEA78 38EA1FF0EA0FC025307F9F29>I E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fk cmtt12 12 23 /Fk 23 118 df<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B6C8A33>46 D<161E167E16FF15035DED1FFE157FEDFFF8020313F04A13C0021F138091383FFE00ECFF F8495B010713C0495BD93FFEC7FC495A3801FFF0485B000F13804890C8FCEA7FFC5BEAFF E05B7FEA7FF87FEA1FFF6C7F000313E06C7F38007FFC6D7E90380FFF806D7F010113F06D 7FEC3FFE91381FFF80020713C06E13F0020013F8ED7FFE151FED07FF811500167E161E28 337BB733>60 D<1278127EB4FC13C07FEA7FF813FEEA1FFF6C13C000037F6C13F86C6C7E EB1FFF6D7F010313E06D7F9038007FFC6E7E91380FFF806E13C0020113F06E13F8ED3FFE 151FED07FF815DED1FFE153FEDFFF84A13F0020713C04A138091383FFE004A5A903801FF F0495B010F13804990C7FCEB7FFC48485A4813E0000F5B4890C8FCEA7FFE13F8EAFFE05B 90C9FC127E127828337BB733>62 D64 D77 D97 D99 DIIII<14E0EB03F8A2497EA36D5AA2EB00E091C8FCAA383FFFF8487FA47EEA0001B3 AD007FB612C0B712E016F0A216E06C15C0243E78BD33>105 D107 D<383FFFFC487FB5FCA27E7EC7FCB3B3AD003FB612F84815FCB7 12FEA26C15FC6C15F8273D7ABC33>I<02FC137E3B7FC3FF01FF80D8FFEF01877F90B500 CF7F15DF92B57E6C010F13872607FE07130301FC01FE7F9039F803FC01A201F013F8A401 E013F0B3A53C7FFE0FFF07FF80B548018F13C0A46C486C01071380322C80AB33>I<4AB4 FC263FFC0713C0267FFE1F13F000FF017F7F91B5FC6CB67E6CEC07FEC6EBF801ECF0004A 7F4A7F5CA291C7FCA35BB3A43B3FFFF80FFFFC486D4813FEB56C4813FFA26C496C13FE6C 496C13FC302C7FAB33>I II<02FF137C0107EBE0FE011F13F0017F13FC90B512FE4814FF4813C03907FE003F4848 131F01F0130F484813071503485A491301127F90C7FC15005A5AA97E7E15017F123F6D13 0315076C7E6C6C130F6D131FD807FE137F3903FF81FF6CEBFFFE6C14FC6D13F86D13F001 0F13C0903801FE0090C8FCAF92387FFFFC92B512FEA46F13FC2F427CAB33>II<90381FFE0F90B5EA8F80000314FF120F5A5AEBF007387F800190C7FC00FE147F5A15 3FA37E007FEC1F0001C090C7FCEA3FF8EBFFC06C13FF6C14E0000314F8C680011F13FF01 001480020713C0EC007FED1FE0007C140F00FEEC07F01503A27EA27F15076D14E06D130F 6DEB3FC09038FE01FF90B61280160000FD5C00FC14F8D8F83F13E0D8780790C7FC242E79 AC33>III E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fl cmr12 12 9 /Fl 9 118 df 73 D 80 D97 D105 D109 D<3901FC01FE00FF903807FFC091381E07F091383801F800 0701707F0003EBE0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8486CECFF80B5D8F8 3F13FEA32F2C7DAB36>I<3903F803F000FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C0 00015B13FBEC007E153C01FF13005BA45BB3A748B4FCB512FEA3202C7DAB26>114 D<1306A5130EA4131EA3133E137EA213FE12011207001FB512F0B6FCA2C648C7FCB3A415 0CAA017E131C017F1318A26D133890381F8030ECC070903807E0E0903801FFC09038007F 001E3E7EBC26>116 DI E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fm cmmi12 17.28 1 /Fm 1 63 df<127812FE6C7E13E013F8EA3FFE380FFF80000313E0C613F8EB3FFE90380F FF80010313E0010013F8EC3FFE91380FFF80020313E0020013F8ED3FFE92380FFF800303 13F0030013FCEE3FFF040F13C0040313F0040013FCEF1FFF050713C0050113F09438007F FCF01FFF060713C0060113F09538007FFCF11FFF070713C0070113F09638007FFCF21FFF 080713E0080113F0F2007FA2F201FF080713E0081F1300F27FFC963801FFF0070713C007 1F90C7FCF17FFC953801FFF0060713C0061F90C8FCF07FFC943801FFF0050713C0051F90 C9FCEFFFFC040313F0040F13C0043F90CAFCEEFFFC030313F0030F1380DB3FFECBFCEDFF F8020313E0020F1380DA3FFECCFCECFFF8010313E0010F1380D93FFECDFCEBFFF8000313 E0000F1380D83FFECEFCEAFFF813E0138048CFFC1278545274CC6D>62 D E %EndDVIPSBitmapFont %DVIPSBitmapFont: Fn cmr17 17.28 26 /Fn 26 121 df<150E151E153C157815F0EC01E0EC03C01407EC0F80EC1F00143EA25C5C 13015C495A13075C130F5C131F91C7FC5B133E137E137C13FCA2485AA3485AA3485AA312 0F5BA3121F5BA3123FA390C8FCA25AA5127EA312FEB3A7127EA3127FA57EA27FA3121FA3 7F120FA37F1207A36C7EA36C7EA36C7EA2137C137E133E133F7F80130F8013078013036D 7E801300147C80A280EC0F80EC07C01403EC01E0EC00F01578153C151E150E1F8F73EA33 >40 D<12E07E12787E7E7E6C7E7F6C7E6C7E6C7EA2137C7F133F7F6D7E80130780130380 130180130080147C147EA280A3EC1F80A3EC0FC0A315E01407A315F01403A315F8A31401 A215FCA51400A315FEB3A715FCA31401A515F8A21403A315F0A3140715E0A3140F15C0A3 EC1F80A3EC3F00A3147EA2147C14FC5C13015C13035C13075C130F5C49C7FC5B133E5B5B A2485A485A485A5B48C8FC121E5A5A5A5A1F8F7AEA33>I<120FEA3FC0EA7FE0EAFFF0A6 EA7FE0EA3FC0EA0F000C0C748B24>46 D50 D<913803FF80023F13F8 49B512FE01076E7E90261FFC0013E0D93FC0EB3FF8017EC7EA0FFC01F86E7E48486E7E48 486E13804848804916C048C9EA7FE013E013F8486CED3FF07FA66C5A6C5AEA01E0CAEA7F E0A318C017FF18805E18005E5F4C5A4C5A4C5A4C5AEE7F804CC7FCED03FC913801FFF091 B512C05E16F891380001FE9238003F80EE1FE0EE07F8707E707E83701380EF7FC018E017 3F18F018F8171FA218FCA2170F18FEA21207EA1FC0EA7FF0A2487EA5EF1FFC5B5B6C4816 F80078C9123F18F07EEF7FE07E001FEEFFC06C6C4A13806C7E6C6C4A1300D801F84A5AD8 00FEEC1FF8D93FC0495A903A1FFC01FFE00107B6128001014AC7FCD9003F13F002031380 37607BDD42>I<007FBD1280BE12C0A36C1C80D1FCB3A3007FBD1280BE12C0A36C1C805A 1F7AB267>61 D66 D83 D85 D97 D<4AB47E020F13F8023F13FE9139FF007F80D903FCEB07E0D907F0EB01 F0D91FE0EB007849488049488049C87E48485D4915FF00034B138048485CA2485AA2485A A2003F6F130049EC007C94C7FC127FA35B12FFAD127F7FA4123F7FA2001FEE01C07F000F 16036D168012076C6C15076D160000015E6C6C151E6D6C5C6D6C5C6D6C5CD90FF8495AD9 03FCEB07C0903A00FF803F8091263FFFFEC7FC020F13F80201138032417CBF3A>99 D<181EEF3FFEEE07FFA4EE000F1703A21701B3AAEDFF80020F13F8023F13FE9139FF803F 81903A03FC0007C14948EB01E1D91FE0EB00F94948147D4948143D49C8121F4848150F49 1507120348481503491501120F121F5BA2123F5B127FA45B12FFAD127F7FA3123FA27F12 1FA26C6C1503A26C6C150712036D150F6C6C151F0000163D137F6D6CECF9FF6D6CEB01F1 D90FF0D903C113C06D6CD90F81EBFF80D901FFEB7F019039007FFFFC021F13E002010100 91C7FC41657CE349>IIII<133C13FF487F487FA66C5B6C90C7FC133C90C8FCB3A2EB03C0EA07FF12 7FA41201EA007FA2133FB3B3AC497E497EB612E0A41B5F7DDE23>105 D107 DIIII113 D<9039078003F8D807FF EB0FFFB5013F13C092387C0FE0913881F01F9238E03FF00001EB838039007F8700148FEB 3F8E029CEB1FE0EE0FC00298EB030002B890C7FCA214B014F0A25CA55CB3B0497EEBFFF8 B612FCA42C3F7CBE33>I<9139FFE00180010FEBFC03017FEBFF073A01FF001FCFD803F8 EB03EFD807E0EB01FF48487F4848147F48C8123F003E151F007E150F127CA200FC1507A3 16037EA27E7F6C7E6D91C7FC13F8EA3FFE381FFFF06CEBFF806C14F86C14FF6C15C06C6C 14F0011F80010714FED9007F7F02031480DA003F13C01503030013E0167F00E0ED1FF016 0F17F86C15071603A36C1501A37EA26C16F016037E17E06D14076DEC0FC06D1580D8FDF0 141FD8F8F8EC7F00013E14FC3AF01FC00FF80107B512E0D8E001148027C0003FF8C7FC2D 417DBF34>I117 D<007FB500C0010FB512E0A4C691C70003EBFC00D93FFE6E13E0D90FFC16807148C7FC01 075E6D6C4A5A6D6C5D6D6D495A606E6C495A6E6C49C8FC6E6C130E171E6E6C5B6E6C5B6E 6C5B5F913801FF016EEB83C092387FC780033F90C9FC16EFED1FFE6F5A6F5A826F7E6F7E 5D834B7F92380F3FE0ED1E1F033C7F9238380FF892387807FCEDF003DA01E07F4A486C7E 707F4A486D7E4AC7FC021E6E7E021C6E7E023C6E7E5C4A6E7E01016F7E49486E7E130701 0F6F7F013F83D9FFF04A7F00076D4A13FCB56C020FEBFFF8A4453E80BD46>120 D E %EndDVIPSBitmapFont end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%PaperSize: A4 end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop Black Black Black Black 676 872 a Fn(Building)47 b(Unix)d(Squeak)f(\()p Fm(>)p Fn(=)h(3.2\))e(from)g (source)1660 1196 y Fl(Ian)33 b(Piumarta)1204 1313 y Fk()807 1525 y Fj(Last)26 b(edited:)34 b(2005-03-17)28 b(12:43:23)h(b)n(y)24 b(piumarta)h(on)h (squeak.hpl.hp.com)1103 1625 y(T)-6 b(ranslated)26 b(to)g(.ps/.p)r (df/.h)n(tml/.txt:)35 b(Marc)n(h)26 b(17,)h(2005)515 1995 y Fi(Con)l(ten)l(ts)515 2212 y Fh(0)76 b(The)32 b(easy)g(w)m(a)m(y)2128 b(2)515 2429 y(1)76 b(The)32 b(hard)h(w)m(a)m(y:con\014gure,)f(build,)f(install)1122 b(3)515 2646 y(2)76 b(Generating)32 b(y)m(our)h(o)m(wn)e(VM)h(and)g (plugin)f(sources)803 b(4)639 2780 y Fg(2.1)84 b(Ho)n(w)28 b Ff(configure)c Fg(\014nds)k(the)g Ff(src)f Fg(directory)75 b(.)42 b(.)g(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(5)p Black 515 2997 a Fh(3)76 b(Adding)32 b(y)m(our)g(o)m(wn)g(plugins)1637 b(5)639 3131 y Fg(3.1)84 b(Plugin-sp)r(eci\014c)27 b(con\014guration)k(.)42 b(.)g(.)f(.)h(.)f(.) h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(6)p Black 830 3265 a(3.1.1)94 b Ff(AC)p 1189 3265 27 4 v 30 w(PLUGIN)p 1483 3265 V 29 w(CHECK)p 1732 3265 V 30 w(LIB\()p Fe(lib)p Ff(,)p Fe(func)9 b Ff(\))70 b Fg(.)42 b(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(6)p Black 830 3399 a(3.1.2)94 b Ff(AC)p 1189 3399 V 30 w(PLUGIN)p 1483 3399 V 29 w(DEFINE)p 1776 3399 V 29 w(UNQUOTED\()p Fe(keyword)p Ff(,)o Fe(te)o(xt)8 b Ff(\))22 b Fg(.)41 b(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(7)p Black 830 3533 a(3.1.3)94 b(Plugin-sp)r(eci\014c)27 b(v)-5 b(ariables)54 b(.)41 b(.)h(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h (.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(7)p Black 639 3667 a(3.2)84 b(Plugin-sp)r(eci\014c)27 b Ff(Makefile)d Fg(declarations)i(and)i(rules)47 b(.)41 b(.)h(.)g(.)f(.)h(.)f(.)h(.)f (.)h(.)p Black 131 w(7)p Black 830 3801 a(3.2.1)94 b(The)28 b(anatom)n(y)e(of)h(a)h(plugin's)f Ff(Makefile)40 b Fg(.)h(.)h(.)f(.)h (.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 131 w(7)p Black 830 3935 a(3.2.2)94 b(A)28 b(note)f(ab)r(out)h Ff($\(COMPILE\))23 b Fg(and)28 b Ff($\(LINK\))d Fg(commands)39 b(.)j(.)f(.)h(.)p Black 131 w(9)p Black 830 4069 a(3.2.3)94 b(Sp)r(ecifying)28 b(additional)f(source)f(directories)20 b(.)42 b(.)f(.)h(.)g(.)f(.)h(.)f (.)h(.)f(.)h(.)p Black 90 w(10)p Black 830 4203 a(3.2.4)94 b(Including)28 b(additional)f(material)f(in)i(the)g(default)g Ff(Makefile)65 b Fg(.)42 b(.)p Black 90 w(10)p Black 830 4337 a(3.2.5)94 b(Replacing)27 b(the)h(default)g Ff(Makefile)c Fg(en)n(tirely)51 b(.)41 b(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.) h(.)p Black 90 w(10)p Black 639 4470 a(3.3)84 b(Examples)27 b(tak)n(en)g(from)g(existing)g(plugins)83 b(.)41 b(.)h(.)g(.)f(.)h(.)f (.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 90 w(10)p Black 830 4604 a(3.3.1)94 b(Con\014guration)37 b(.)42 b(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)g (.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 90 w(11)p Black 830 4738 a(3.3.2)94 b(Customising)27 b(the)h Ff(Makefile)18 b Fg(.)42 b(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f (.)h(.)p Black 90 w(11)p Black 639 4872 a(3.4)84 b(Coping)27 b(with)h(VMMak)n(er)f(quirks)33 b(.)42 b(.)f(.)h(.)f(.)h(.)f(.)h(.)g(.) f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 90 w(12)p Black 639 5006 a(3.5)84 b(If)28 b(all)g(else)f(fails)43 b(.)e(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)g (.)f(.)h(.)f(.)h(.)g(.)f(.)h(.)f(.)h(.)f(.)h(.)p Black 90 w(12)p Black Black 1926 5255 a(1)p Black eop end %%Page: 2 2 TeXDict begin 2 1 bop Black Black 515 523 a Fh(Index)2533 b(12)515 839 y Fi(0)134 b(The)45 b(easy)h(w)l(a)l(y)515 1062 y Fg(Beginning)35 b(with)i(v)n(ersion)d(3.7-7,)i(ev)n(erything)f (y)n(ou)g(need)i(is)e(included)i(with)f(the)h(Unix)515 1162 y(sources)18 b(regardless)f(of)j(ho)n(w)f(y)n(ou)g(obtained)g (them)i({)e(either)g(as)g(a)h(tarball)f(or)f(b)n(y)i(rep)r(ository)515 1262 y(c)n(hec)n(k)n(out.)34 b(\(This)23 b(w)n(as)f(done)h(to)f (eliminate)h(frequen)n(t)g(problems)f(encoun)n(tered)g(b)n(y)h(p)r (eople)515 1361 y(com)n(bining)36 b(the)h(rep)r(ository)f(Unix)h(and)g (Cross)e(sources)g(with)j(a)e(set)h(of)g(incompatible)515 1461 y(generated)26 b(sources.\))515 1602 y(If)19 b(y)n(ou)f(extract)g (a)h(tarball)f(then)h(y)n(ou)f(will)h(ha)n(v)n(e)f(a)g(top-lev)n(el)g (directory)g(named)h Ff(Squeak-)t(X.)515 1702 y(Y-)t(Z)24 b Fg(\(for)h(some)g(v)-5 b(alues)25 b(of)g(X,)h(Y,)g(and)f(Z\).)g(If)h (y)n(ou)f(are)f(c)n(hec)n(king)g(out)i(from)f(a)g(rep)r(ository)-7 b(,)515 1801 y(y)n(ou)27 b(can)g(call)g(the)h(direcory)e(an)n(ything)h (y)n(ou)g(lik)n(e;)g(for)g(example:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 2009 a Ff($)43 b(svn)f(co)h (http://squeak.hpl)o(.h)o(p.)o(com)o(/s)o(vn/)o(sq)o(uea)o(k/)o(tr)o (unk)37 b(squeak)p Black 515 2216 a Fg(will)28 b(lea)n(v)n(e)f(y)n(ou)g (with)i(a)f(directory)f(called)h Ff(squeak)p Fg(.)36 b(\(W)-7 b(e'll)29 b(assume)e(from)h(no)n(w)g(on)g(that)515 2316 y(the)g(directory)e(is)i(called)f Ff(squeak)p Fg(.\))515 2457 y(Next)c(c)n(hange)f(to)h(the)h('unix')f(directory)f(within)i(the) g(sources)d(that)j(y)n(ou)e(just)i(c)n(hec)n(k)n(ed)e(out)515 2557 y(\(or)27 b(extracted)g(from)g(the)h(tarball\):)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 2764 a Ff($)43 b(cd)g(squeak/platforms)o(/u)o(nix)p Black 515 2972 a Fg(Build)28 b(the)g(VM)g(and)f(plugins)g(b)n(y)h(running)f Ff(make)p Fg(:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 3180 a Ff($)43 b(make)p Black 515 3387 a Fg(Then)32 b(install)h(the)f(VM,)h(plugins)f(and)g(man)n(ual)g(pages)f(b)n(y)h (running)g Ff(make)f Fg(again)g(\(with)515 3487 y(sup)r(eruser)26 b(privileges\):)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 3694 a Ff($)43 b(sudo)f(make)g(install)p Black 515 3902 a Fg(T)-7 b(o)34 b(delete)h(the)g(temp)r(orary)e(\014les)i (created)e(during)i(the)g(build)g(pro)r(cess,)g(run)f Ff(make)f Fg(one)515 4001 y(last)27 b(time:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 4209 a Ff($)43 b(make)f(clean)p Black 515 4417 a Fg(That's)27 b(all)g(there)h(is)f(to)h(it.)p Black 1926 5255 a(2)p Black eop end %%Page: 3 3 TeXDict begin 3 2 bop Black Black 515 523 a Fi(1)134 b(The)45 b(hard)g(w)l(a)l(y:)h(con\014gure,)f(build,)g(install)515 746 y Fg(Unix)18 b(Squeak)g(is)g(built)i(using)e(the)g(\(almost\))h (univ)n(ersal)e(\\)p Ff(configure;make)o(;ma)o(ke)o(in)o(sta)o(ll)o Fg(".)515 846 y(If)28 b(y)n(ou)f(ha)n(v)n(en't)f(come)i(across)d(this)j (b)r(efore,)f(read)g(on.)14 b(.)g(.)515 987 y(Create)33 b(a)h(build)h(directory)e(\(whic)n(h)h(w)n(e)g(will)g(call)g(`)p Ff(blddir)p Fg(')e(from)i(no)n(w)f(on\))i(and)f(then)515 1087 y(`)p Ff(cd)p Fg(')27 b(to)g(it:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 1294 a Ff($)43 b(mkdir)f(blddir)602 1394 y($)h(cd)g(blddir)p Black 515 1602 a Fg(A)28 b(con)n(v)n(enien)n (t)e(place)h(is)h(just)g(next)g(to)f(the)h Ff(platforms)c Fg(directory)-7 b(,)27 b(lik)n(e)g(this:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 1809 a Ff($)43 b(cd)g(squeak)602 1909 y($)g(ls)602 2008 y(platforms)d(src)i(...)602 2108 y($)h(mkdir)f(bld)602 2208 y($)h(cd)g(bld)p Black 515 2415 a Fg(Create)31 b(the)i(build)g(en)n(vironmen)n(t)f(b)n(y)g (running)g(the)h(script)f Ff(configure)d Fg(whic)n(h)j(liv)n(es)g(in) 515 2515 y(the)c Ff(platforms/unix/c)o(on)o(fi)o(g)22 b Fg(directory)-7 b(.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 2739 a(Note:)88 b(The)31 b Ff(configure)c Fg(script)k(accepts)f(lots)h(of)g(options.)46 b(T)-7 b(o)31 b(see)g(a)f(list)722 2839 y(of)e(them,)g(run:)37 b(`)p Ff(configure)j(--help)p Fg(')p Black 515 3063 a(Assuming)27 b(y)n(ou'v)n(e)f(created)h(the)h Ff(blddir)d Fg(next)j(to)g Ff(platforms)p Fg(,)c(this)k(w)n(ould)f(b)r(e:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 3270 a Ff($)43 b(../platforms/uni)o(x/c)o(on)o(fig)o(/c)o(on)o(fig)o(ur)o(e)p Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 3561 a Fg(Note:)107 b(This)36 b(assumes)f(that)h(the)g(VMMak)n(er)f(sources) g(are)g(in)h(`)p Ff(../src)p Fg('.)722 3660 y(Ho)n(w)n(ev)n(er,)25 b(since)i(the)h(Unix)f(Squeak)f(supp)r(ort)h(co)r(de)g(is)f(indep)r (enden)n(t)i(of)f(the)722 3760 y(image)18 b(v)n(ersion)f(from)h(whic)n (h)g(VMMak)n(er)f(generated)h(the)g(in)n(terpreter/plugin)722 3860 y(sources,)24 b(it)h(is)f(p)r(ossible)h(that)f(y)n(our)g(source)f (distribution)h(comes)g(with)h(more)722 3959 y(than)i(one)g Ff(src)e Fg(directory)h(\(corresp)r(onding)f(to)i(more)e(than)i(one)g (image)f(v)n(er-)722 4059 y(sion)33 b(used)h(to)f(generate)f(the)i (sources\).)53 b(In)34 b(suc)n(h)f(cases)f(y)n(ou)h(will)g(ha)n(v)n(e)g (to)722 4159 y(tell)21 b Ff(configure)16 b Fg(whic)n(h)21 b(source)e(v)n(ersion)f(to)i(use,)i(via)e(the)g(`)p Ff(-)t(-)t(with-)t (src)p Fg(')d(op-)722 4258 y(tion.)39 b(F)-7 b(or)28 b(example,)g(if)g(there)g(are)g(t)n(w)n(o)f(source)g(directories)g (called)h Ff(src-)t(3.)722 4358 y(2gamma-)t(4857)23 b Fg(and)k Ff(src-)t(3.3.alpha-)t(488)o(1)21 b Fg(then)28 b(y)n(ou)e(w)n(ould)h(use)g Fd(one)34 b Fg(of)722 4457 y(the)28 b(follo)n(wing)f(commands:)p 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 809 4657 a Ff($)44 b(.../configure)38 b(--with-src=src-3)o(.2)o(gam)o(ma)o(-4)o(857)1071 4756 y Fe(or)809 4856 y Ff($)44 b(.../configure)38 b(--with-src=src-3)o (.3)o(alp)o(ha)o(-4)o(881)p 1 0 0 TeXcolorrgb Black 1926 5255 a Fg(3)p 1 0 0 TeXcolorrgb eop end %%Page: 4 4 TeXDict begin 4 3 bop 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb Black 515 523 a Fg(Build)28 b(the)g(VM)g(and)f(plugins)g(b)n(y)h (running)f Ff(make)p Fg(:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 721 a Ff($)43 b(make)p Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 995 a Fg(Note:)74 b(If)28 b(y)n(ou)e(w)n(an)n(t)h(to)g(build)h(just)g(the)f(VM)h(\(without)g (external)e(plugins\))722 1095 y(or)37 b(just)i(the)f(external)f (plugins)h(\(without)h(the)f(VM\))h(then)f(y)n(ou)f(can)h(use:)722 1194 y(`)p Ff(make)k(squeak)p Fg(')26 b(or)g(`)p Ff(make)42 b(plugins)p Fg(')25 b(resp)r(ectiv)n(ely)-7 b(.)p Black 515 1408 a(Finally)27 b(install)h(the)g(VM,)g(plugins)f(and)h(man)n (ual)f(pages:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 1606 a Ff($)43 b(su)g(root)602 1706 y($)g(make)f(install)p Black 515 2078 a Fi(2)134 b(Generating)46 b(y)l(our)f(o)l(wn)h(VM)e (and)g(plugin)h(sources)515 2298 y Fg(Generating)20 b(y)n(our)g(o)n(wn) g(VM/plugin)h(sources)f(migh)n(t)h(b)r(e)g(necessary)f(for)g(v)-5 b(arious)20 b(reasons:)p Black 639 2497 a Fc(\017)p Black 41 w Fg(y)n(ou)27 b(w)n(an)n(t)g(to)h(c)n(hange)e(the)i(mix)g(of)f(in)n (ternal)g(vs.)37 b(external)26 b(plugins)p Black 639 2660 a Fc(\017)p Black 41 w Fg(y)n(ou)h(w)n(an)n(t)g(to)h(remo)n(v)n(e) d(some)i(plugins)h(from)f(the)h(VM)g(that)g(y)n(ou)f(will)h(nev)n(er)e (use)p Black 639 2823 a Fc(\017)p Black 41 w Fg(y)n(ou'v)n(e)h(pulled)h (in)g(some)f(up)r(dates)g(that)h(mo)r(dify)g(the)g(In)n(terpreter)f(or) f(plugins)p Black 639 2986 a Fc(\017)p Black 41 w Fg(y)n(ou'v)n(e)h (\014led-in)g(\(or)g(written\))h(a)g(whole)f(new)g(plugin)p Black 639 3149 a Fc(\017)p Black 41 w Fg(etc.)14 b(.)g(.)515 3347 y(V)-7 b(ersion)30 b(3.2)g(\(and)h(later\))g(of)g(Unix)g(Squeak)g (use)f(VMMak)n(er)g(to)h(generate)f(the)h(core)f(in-)515 3447 y(terpreter)c(and)i(plugin)f(sources.)515 3585 y(Start)k(Squeak)g (in)h(the)g(top-lev)n(el)f(directory)g(\(the)h(one)f(con)n(taining)g (the)h Ff(platforms)c Fg(di-)515 3684 y(rectory\);)e(for)h(example:)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 3883 a Ff($)43 b(ls)602 3982 y(src)f(platforms)e(...)602 4082 y($)j(squeak)e(MyCoolPlugin.imag)o(e)p Black 515 4280 a Fg(Op)r(en)27 b(a)h(VMMak)n(erT)-7 b(o)r(ol)26 b(and)h(mo)r(dify)h (the)g(setup)g(to)f(y)n(our)g(liking.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 4494 a(Note:)77 b(The)28 b(VMMak)n(er)f(con\014guration)g(used)h(to)g(build)h(the)g (distributions)722 4594 y(of)34 b(Unix)g(Squeak)f(is)h(a)n(v)-5 b(ailable)32 b(in)i Ff(platforms/unix/c)o(on)o(fig)o(/V)o(MMa)o(ke)o (r.)722 4693 y(config)p Fg(.)p Black 515 4907 a(Then)h(clic)n(k)g(on)g (the)h(relev)-5 b(an)n(t)35 b(\\)p Fb(generate)f(...)p Fg(")60 b(button.)h(Y)-7 b(ou)35 b(can)g(no)n(w)g(`)p Ff(configure;)515 5006 y(make;makeinstall)o Fg(')22 b(in)28 b(y)n(our)e Ff(blddir)f Fg(\(as)i(describ)r(ed)h(ab)r(o)n(v)n(e\).)p Black 1926 5255 a(4)p Black eop end %%Page: 5 5 TeXDict begin 5 4 bop Black Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 523 a Fg(Note:)94 b(Y)-7 b(ou)33 b(only)f(need)h(to)f(run)g Ff(configure)d Fh(once)p 2262 536 187 4 v 33 w Fg(for)j(a)g(giv)n(en)g Ff(blddir)722 623 y Fg(\(on)e(the)h(same)e(host\).)45 b(If)30 b(y)n(ou)g(mo)r(dify)g (the)h(c)n(hoice)e(of)h(plugins)g(\(or)g(c)n(hange)722 722 y(whether)37 b(they're)f(in)n(ternal/external\))f(then)i(y)n(ou)f (can)h(up)r(date)g(the)g(build)722 822 y(en)n(vironmen)n(t)28 b(b)n(y)h(running)f(the)i Ff(config.status)23 b Fg(script)29 b(in)g(the)g Ff(bldddir)p Fg(,)722 922 y(lik)n(e)e(this:)p 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 722 1090 a Ff($)43 b(squeak)f(MyCoolPlugin.im)o(age)37 b(...)42 b(generate)e(new)j(sources)d(...)j($)g(cd)722 1189 y(blddir)e($)j(./config.status)37 b($)43 b(make)p 1 0 0 TeXcolorrgb 722 1358 a Fg(This)24 b(is)f Fd(much)29 b Fg(faster)23 b(than)g(running)g Ff(configure)d Fg(all)j(o)n(v)n(er)e (again.)35 b(\(In)23 b(fact,)722 1457 y Ff(make)k Fg(should)i(detect)g (an)n(y)f(c)n(hanges)f(to)i(the)g(plugin)g(con\014guration)e(and)h(re-) 722 1557 y(run)g Ff(config.status)22 b Fg(for)27 b(y)n(ou)g (automatically)-7 b(.\))p Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 1789 a(Note:)138 b(`)p Ff(configure)p Fg(')40 b(do)r(esn't)k(actually)f(create)g(an)n(y)f(\014les.)85 b(The)44 b(last)722 1889 y(thing)33 b(it)g(do)r(es)f(is)h(run)f(`)p Ff(config.status)p Fg(')c(to)k(create)g(the)h(con\014gured)e Fd(\014le)6 b Fg(s)722 1989 y(in)37 b Ff(blddir)c Fg(from)j(the)g (corresp)r(onding)e Fd(\014le.in)6 b Fg(s)37 b(in)g(the)f Ff(unix/config)c Fg(di-)722 2088 y(rectory)-7 b(.)58 b(So)34 b(in)h(the)h(remainder)e(of)g(this)i(do)r(cumen)n(t)f(the)g (phrase)f(`during)722 2188 y(con\014guration')29 b(means)g Fd(either)40 b Fg(when)31 b(running)e(`)p Ff(configure)p Fg(')e(for)i(the)i(\014rst)722 2288 y(time)25 b Fd(or)33 b Fg(running)23 b(`)p Ff(config.status)p Fg(')c(to)k(up)r(date)h(an)g (already)e Ff(configure)p Fg(d)722 2387 y(build)28 b(en)n(vironmen)n (t.)p Black 515 2695 a Fa(2.1)112 b(Ho)m(w)38 b Fk(configure)i Fa(\014nds)f(the)e Fk(src)h Fa(directory)515 2878 y Fg(Starting)30 b(with)h(v)n(ersion)e(3.7)g Ff(configure)e Fg(lo)r(oks)j(in)g(t)n(w)n (o)g(places)g(for)g(the)h Ff(src)e Fg(directory)-7 b(,)515 2977 y(in)28 b(the)g(follo)n(wing)e(order,)g(and)i(uses)f(the)h (\014rst)f(one)h(that)f(it)h(\014nds:)p Black 639 3158 a Fc(\017)p Black 41 w Fg(the)g(top-lev)n(el)f(directory)f(\(the)j(one) e(con)n(taining)f(the)i Ff(platforms)c Fg(directory\);)p Black 639 3312 a Fc(\017)p Black 41 w Fg(the)k Ff(platforms/unix)22 b Fg(directory)-7 b(.)515 3492 y(In)26 b(other)f(w)n(ords,)g(if)i(y)n (ou)e(w)n(an)n(t)g(to)h(use)g(y)n(our)e(o)n(wn)h(generated)g(sources)g (without)h(deleting)515 3592 y(the)37 b(built-in)h(generated)f (sources,)h(generating)e(them)i(in)n(to)f(a)g Ff(src)f Fg(directory)g(next)h(to)515 3692 y Ff(platforms)24 b Fg(\(and)j(then)i(re-running)d Ff(configure)p Fg(\))e(will)k(do)f(what) h(y)n(ou)f(w)n(an)n(t.)515 3990 y Fi(3)134 b(Adding)45 b(y)l(our)g(o)l(wn)g(plugins)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 4199 a Fg(Note:)74 b(This)28 b(section)f(is)g(in) n(tended)h(primarily)f(for)g(plugin)h(dev)n(elop)r(ers.)p Black 515 4379 a(If)19 b(y)n(our)e(plugin)i(requires)e(no)i (platform-sp)r(eci\014c)f(t)n(w)n(eaks)f(then)i(there's)g(nothing)f (for)g(y)n(ou)g(to)515 4479 y(do.)34 b Ff(configure)18 b Fg(\(and)k Ff(config.status)p Fg(\))16 b(will)22 b(pro)n(vide)e(a)i (default)g Ff(Makefile)c Fg(for)j(it)h(that)515 4579 y(should)j(w)n(ork.)35 b(If)26 b(y)n(our)e(plugin)i(requires)e(only)h (platform-indep)r(enden)n(t)h(t)n(w)n(eaks)e(\(and/or)515 4678 y(additional)d(hand-written)g(co)r(de\))h(then)g(these)g(go)f(in)h Ff(platforms/Cross/)o(pl)o(ug)o(ins)o Fg(,)17 b(and)515 4778 y(there's)27 b(nothing)g(for)g(y)n(ou)g(to)h(do)f(\(in)h (Unixland\).)515 4907 y(On)c(the)g(other)f(hand,)i(if)g(y)n(ou)e (require)g(sp)r(ecial)h Ff(configure)c Fg(tests)k(or)f(additional)h (declara-)515 5006 y(tions/rules)i(in)i(y)n(our)e(plugin's)i Ff(Makefile)c Fg(then)k(y)n(ou)f(need)g(to)h(sp)r(ecify)g(them)g (explicitly)-7 b(.)p Black 1926 5255 a(5)p Black eop end %%Page: 6 6 TeXDict begin 6 5 bop Black Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 523 a Fg(Note:)74 b(Unix)28 b(Squeak)f(subscrib)r (es)g(to)g(the)h(follo)n(wing)f(philopsoph)n(y:)722 654 y Fd(A)n(bsolutely)22 b(everything)g(that)f(is)h(sp)l(e)l(ci\014c)g(to) f(Unix)g(\(sour)l(c)l(es,)i(he)l(aders,)i Fe(configure)722 754 y Fd(and)31 b Fe(Makefile)40 b Fd(extensions,)30 b(etc.\))39 b(lives)30 b(under)g Fe(platforms/)10 b(unix)j Fd(.)722 885 y Fg(In)30 b(other)g(w)n(ords:)40 b(there)29 b(is)h(not)g(\(nor)f(augh)n(t)g(there)h(b)r(e\))h Fd(any)37 b Fg(Unix-related)722 985 y(information)25 b(under)g(the)g Ff(platforms/Cross)19 b Fg(directory)-7 b(.)35 b(\(Unix)25 b(Squeak)g(is)722 1084 y(en)n(tirely)f(encapsulated)f(under)h Ff(platforms/unix)18 b Fg(and)23 b(is)h(utterly)g(imm)n(une)722 1184 y(to)k(\\random)e(junk")i(elsewhere)e(in)i(the)g Ff(platforms)c Fg(tree.\))p Black 515 1397 a(First)j(y)n(ou)g(m)n(ust)h (create)e(a)h(new)h(directory)e(under)i Ff(platforms/unix/)o(plu)o(gi)o (ns)21 b Fg(named)515 1496 y(after)35 b(y)n(our)f(plugin.)59 b(This)36 b(directory)d(will)j(hold)f(the)h(\014les)f(describing)f(the) i(additional)515 1596 y(con\014guration)27 b(c)n(hec)n(ks)h(and/or)g Ff(Makefile)e Fg(con)n(ten)n(ts.)41 b(F)-7 b(or)28 b(example,)h(if)h(y) n(our)e(plugin)h(is)515 1696 y(called)e(\\MyCo)r(olPlugin")e(then)p 0 0 1 TeXcolorrgb Black 0 0 1 TeXcolorrgb 602 1893 a Ff($)43 b(mkdir)f(platforms/unix/)o(plu)o(gi)o(ns)o(/My)o(Co)o(olP)o (lu)o(gin)p Black 515 2091 a Fg(w)n(ould)27 b(b)r(e)g(the)h(thing)g(to) f(do.)37 b(\(The)27 b(follo)n(wing)g(sections)f(will)i(refer)f(to)g (this)h(directory)e(as)515 2191 y Ff(platdep)f Fg(since)i(the)h(full)g (path)g(is)f(quite)h(a)f(mouthful)i(of)e(t)n(yping)h(for)f(m)n(y)g (lazy)g(\014ngers.\))515 2460 y Fa(3.1)112 b(Plugin-sp)s(eci\014c)36 b(con\014guration)515 2652 y Fg(Y)-7 b(our)32 b(plugin)h(can)f(ask)f Ff(configure)e Fg(to)k(run)f(additional)g(tests)h(\(and)g(to)f(set)h (additional)515 2751 y(v)-5 b(ariables)29 b(in)i(its)g(output)g (\014les\))g(simply)g(b)n(y)g(including)f(a)h(\014le)g(called)f Ff(acinclude.m4)c Fg(in)515 2851 y(it's)i Ff(platdep)c Fg(directory)-7 b(.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 3064 a(Note:)67 b(The)21 b Ff(configure)c Fg(script)k(is)g (`compiled')g(from)f(sev)n(eral)f(other)i(\014les.)34 b(If)722 3163 y(y)n(ou)d(create)g(a)g(`)p Ff(platdep./acinclud)o(e.)o (m4)p Fg(')25 b(\014le)32 b(then)g(y)n(ou)f Fd(must)39 b Fg(`recom-)722 3263 y(pile')c Ff(configure)p Fg(.)56 b(Y)-7 b(ou)35 b(can)f(do)h(this)g(b)n(y)g(`)p Ff(cd)p Fg('ing)e(to)i Ff(unix/config)c Fg(and)722 3363 y(running)37 b(`)p Ff(make)p Fg(',)h(or)e(\(if)i(y)n(ou)e(ha)n(v)n(e)g(GNU)i Ff(make)p Fg(\))d(from)i(the)g Ff(blddir)e Fg(lik)n(e)722 3462 y(this:)p 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 1 0 0 TeXcolorrgb 809 3653 a Ff($)44 b(make)e(-C)g(../platforms/unix)o(/c)o (onf)o(ig)p 1 0 0 TeXcolorrgb Black 515 3926 a Fg(In)33 b(addition)g(to)g(the)h(usual)e Ff(autoconf)e Fg(macros,)j(the)h(follo) n(wing)e(macros)f(are)h(a)n(v)-5 b(ailable)515 4026 y(sp)r (eci\014cally)27 b(for)g(Squeak)g(plugins)g(to)h(use:)515 4278 y Fh(3.1.1)93 b Ff(AC)p 899 4278 27 4 v 31 w(PLUGIN)p 1194 4278 V 29 w(CHECK)p 1443 4278 V 29 w(LIB\()p Fe(lib)p Ff(,)p Fe(func)10 b Ff(\))515 4470 y Fg(This)27 b(is)h(similar)f(to)g (the)h Ff(autoconf)c Fg(`)p Ff(AC_CHECK_LIB)p Fg(')f(macro.)515 4608 y Fd(func)36 b Fg(is)c(the)g(name)g(of)g(a)f(function)i(required)d (b)n(y)i(the)g(plugin,)h(de\014ned)g(in)f(the)g(external)515 4707 y(\(system\))22 b(library)f Fd(lib)p Fg(.)36 b(The)22 b(macro)e(c)n(hec)n(ks)h(that)h(the)g(library)f(is)h(a)n(v)-5 b(ailable)21 b(\(via)g(`)p Ff(-l)p Fe(lib)13 b Fg('\))515 4807 y(and)19 b(then)g(adds)g(it)g(to)g(the)g(list)g(of)g(libraries)f (required)g(b)n(y)g(the)i(plugin)f(\(see)g(the)g(explanation)515 4907 y(of)41 b Ff([plibs])32 b Fg(in)j(Section)f(3.2.1)g(for)g(a)g (description)g(of)h(ho)n(w)f(library)g(dep)r(endencies)h(for)515 5006 y(plugins)27 b(are)g(handled\).)p Black 1926 5255 a(6)p Black eop end %%Page: 7 7 TeXDict begin 7 6 bop Black Black 515 523 a Fg(If)32 b Fd(func)k Fg(cannot)31 b(b)r(e)h(found)g(in)g Fd(lib)38 b Fg(then)32 b(the)g(plugin)g(will)f(b)r(e)i(disabled)e(and)g(a)g (message)515 623 y(to)c(that)g(e\013ect)h(prin)n(ted)f(during)f (con\014guration.)35 b(\(The)28 b(VM)f(can)g(still)g(b)r(e)h(built,)g Fd(without)515 722 y Fg(rerunning)h(VMMak)n(er)g(or)g(recon\014guring,) f(and)i(the)g(plugin)g(will)g(simply)g(b)r(e)g(ommitted)515 822 y(from)d(it.\))515 1079 y Fh(3.1.2)93 b Ff(AC)p 899 1079 27 4 v 31 w(PLUGIN)p 1194 1079 V 29 w(DEFINE)p 1487 1079 V 29 w(UNQUOTED\()p Fe(keyword)o Ff(,)p Fe(t)o(ext)8 b Ff(\))515 1273 y Fg(This)27 b(is)h(similar)f(to)g(the)h Ff(autoconf)c Fg(`)p Ff(AC_DEFINE_UNQUOTE)o(D)p Fg(')e(macro.)515 1414 y Fd(keywor)l(d)37 b Fg(is)27 b(a)g Ff(Makefile)d Fg(k)n(eyw)n(ord)i(\(usually)h(of)g(the)h(form)f(`[)p Fd(name)6 b Fg(]'\))29 b(and)e Fd(text)34 b Fg(is)27 b(arbi-)515 1514 y(trary)22 b(text)i(to)g(b)r(e)g(asso)r(ciated)e(with) i(it.)36 b(Calling)23 b(this)h(macro)e(causes)h Ff(mkmf)f Fg(to)h(substitute)515 1614 y Fd(text)34 b Fg(for)27 b(all)h(o)r(ccurrences)e(of)h Fd(keywor)l(d)38 b Fg(in)28 b(the)g Ff(Makefile)c Fg(generated)i(for)i(the)g(plugin.)515 1871 y Fh(3.1.3)93 b(Plugin-sp)s(eci\014c)31 b(v)-5 b(ariables)515 2065 y Fg(The)37 b(follo)n(wing)g(v)-5 b(ariables)36 b(are)g(also)h(set)g(during)g(the)h(execution)f(of)g(a)g(plugin-sp)r (eci\014c)515 2165 y Ff(acinclude.m4)p Fg(:)p Black Black 722 2388 a Ff($)p Fc(f)p Ff(plugin)p Fc(g)24 b Fg(is)k(the)g(name)f(of) h(the)f(plugin;)p Black Black 722 2554 a Ff($)p Fc(f)p Ff(topdir)p Fc(g)d Fg(is)k(the)g(path)f(to)h(the)g(top-lev)n(el)e (directory)h(\(con)n(taining)g Ff(platforms)p Fg(\);)p Black Black 722 2720 a Ff($)p Fc(f)p Ff(vmmdir)p Fc(g)d Fg(is)k(the)g(path)f(to)h(the)g(VMMak)n(er)e(`)p Ff(src)p Fg(')h(directory)-7 b(.)515 2993 y Fa(3.2)112 b(Plugin-sp)s(eci\014c)36 b Fk(Makefile)j Fa(declarations)e(and)h(rules)515 3188 y Fg(Three)27 b(mec)n(hanisms)g(are)f(a)n(vilable)h(for)g(this:)p Black 616 3394 a(1.)p Black 41 w(scanning)g(additional)g(dirrectories)f (for)h(sources)f(and)h(headers;)p Black 616 3560 a(2.)p Black 41 w(including)h(a)f(few)h(additional)f(lines)h(in)n(to)f(the)h (default)g Ff(Makefile)p Fg(;)d(and)p Black 616 3726 a(3.)p Black 41 w(replacing)i(en)n(tirely)g(the)h(default)g Ff(Makefile)c Fg(with)k(a)f(hand-written)h(one.)515 3933 y(\(The)g(last)f(option)g(isn't)h(as)f(scary)f(as)h(it)h(migh)n(t)g (sound:)f(read)g(on.)13 b(.)h(.)g(\))515 4190 y Fh(3.2.1)93 b(The)33 b(anatom)m(y)e(of)h(a)g(plugin's)e Ff(Makefile)515 4384 y Fg(Before)22 b(pro)r(ceeding,)h(let's)h(tak)n(e)e(a)h(min)n(ute) h(to)f(understand)g(ho)n(w)f(Unix)i(Squeak)f(compiles)515 4484 y(and)37 b(links)h(\014les)g(in)g(its)g(default)h Ff(Makefile)34 b Fg(for)k(plugins.)67 b(The)38 b(default)h Ff(Makefile)34 b Fg(is)515 4584 y(sho)n(wn)27 b(in)g(Figure)g(1.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 4807 a(Note:)93 b(The)32 b(k)n(eyw)n(ords)e(app)r(earing)h(b)r(et)n(w)n(een)h(`)p Ff([)g Fg(square)f(brac)n(k)n(ets)g Ff(])p Fg(')h(are)722 4907 y(substituted)c(during)f(con\014guration)e(b)n(y)i(a)g(prepro)r (cessor)d(called)j(`)p Ff(mkmf)p Fg(')e(ac-)722 5006 y(cording)i(to)g(the)h(kind)g(of)g(plugin)f(\(in)n(ternal/external\))f (b)r(eing)i(built.)p Black 1926 5255 a(7)p 1 0 0 TeXcolorrgb eop end %%Page: 8 8 TeXDict begin 8 7 bop 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb Black Black Black Black Black Black Black 905 491 a Ff(#)43 b(default)e(Makefile)f(for)i(Unix)g(Squeak)f(plugins)905 690 y([make_cfg])905 790 y([make_plg])905 989 y(XINCLUDES)301 b(=)43 b([includes])905 1089 y(OBJS)521 b(=)43 b([targets])905 1188 y(TARGET)433 b(=)43 b([target])905 1288 y(PLIBS)477 b(=)43 b([plibs])905 1487 y([make_inc])905 1686 y($\(TARGET\))d(:)j ($\(OBJS\))e(Makefile)1254 1786 y($\(LINK\))f($\(TARGET\))g($\(OBJS\))h ($\(PLIBS\))905 1985 y([make_targets])905 2184 y(.force)g(:)p Black 1010 2450 a Fg(Figure)27 b(1:)36 b(Default)29 b Ff(Makefile)24 b Fg(\\template")j(for)g(plugins.)p Black 1 0 0 TeXcolorrgb Black 515 2715 a Ff([make)p 740 2715 27 4 v 29 w(cfg])g Fg(is)g(the)i(con\014gured)e(v)-5 b(ariable)27 b(section.)38 b(It)28 b(con)n(tains)f(the)i(platform-sp)r (eci\014c)515 2815 y(information)23 b(gleaned)h(b)n(y)g Ff(configure)d Fg(while)j(it)h(w)n(as)e(\014guring)h(out)g(whic)n(h)g (compiler)g(y)n(ou)515 2915 y(ha)n(v)n(e,)i(what)i(\015ags)e(y)n(our)h (link)n(er)g(needs,)g(where)g(to)h(install)f(stu\013,)h(and)g(so)f(on.) 515 3056 y Ff([make)p 740 3056 V 29 w(plg])d Fg(con)n(tains)g(a)h (handful)h(of)f(de\014nitions)g(whic)n(h)g(dep)r(end)h(on)f(whether)g (the)h(plu-)515 3155 y(gin)h(is)h(b)r(eing)f(compiled)h(as)f(in)n (ternal)g(or)f(external:)p Black Black 722 3357 a Ff(o)392 b Fg(the)28 b(extension)f(for)g(ob)5 b(ject)28 b(\014les)722 3457 y Ff(a)392 b Fg(the)28 b(extension)f(for)g(plugins)722 3557 y Ff(COMPILE)128 b Fg(the)28 b(command)f(to)h(compile)f(a)g (source)g(\014le)h(in)n(to)f(an)g(ob)5 b(ject)28 b(\014le)722 3656 y Ff(LINK)260 b Fg(the)28 b(command)f(to)h(link)g(one)f(or)f(more) h(ob)5 b(ject)28 b(\014les)f(in)n(to)g(a)h(plugin)515 3860 y(F)-7 b(or)32 b(in)n(ternal)g(plugins:)48 b Ff($o)32 b Fg(is)h(`)p Ff(.o)p Fg(')f(and)h Ff($a)f Fg(is)h(`)p Ff(.a)p Fg('.)52 b Ff($\(COMPILE\))29 b Fg(is)j(the)i(C)f(compiler)515 3960 y(\(`)p Ff($\(CC\))42 b(...)g(-o)p Fg(',)i(so)c(the)i(\014rst)e (thing)i(after)e(the)i(command)f Fd(must)48 b Fg(b)r(e)41 b(the)h(output)515 4059 y(\014lename\))29 b(and)h Ff($\(LINK\))d Fg(is)i(arc)n(hiv)n(er)f(\(`)p Ff(ar)43 b(-rc)p Fg(',)29 b(again)f(requiring)g(the)i(output)g(\014le)g(to)515 4159 y(follo)n(w)24 b(immediately\).)37 b(Note)25 b(that)g(in)n(ternal) g(plugins)g(are)f(built)i(as)f(`)p Ff(ar)p Fg(')f(arc)n(hiv)n(es)f(b)r (efore)515 4259 y(b)r(eing)k(link)n(ed)h(in)n(to)f(the)h(\014nal)g (binary)-7 b(.)515 4400 y(F)g(or)37 b(external)f(plugins:)56 b Ff($o)37 b Fg(is)g(`)p Ff(.lo)p Fg(',)i Ff($a)e Fg(is)g(`)p Ff(.la)p Fg(',)i(and)e Ff($\(COMPILE\))d Fg(and)j Ff($\(LINK\))515 4499 y Fg(are)27 b(in)n(v)n(o)r(cations)f(of)i(`)p Ff(libtool)p Fg(')d(to)j(create)f(p)r(osition-indep)r(enden)n(t)i(ob)5 b(jects)27 b(and)h(shared)515 4599 y(libraries)35 b(\(with)j(a)f(`)p Ff(-)t(o)p Fg(')f(app)r(earing)g(righ)n(t)g(at)h(the)h(end,)h(so)e(the) g(\014rst)g(thing)g(after)g(the)515 4699 y(command)27 b Fd(must)34 b Fg(b)r(e)28 b(the)g(output)h(\014lename\).)515 4840 y Ff([includes])f Fg(is)k(a)g(list)h(of)f(`)p Ff(-)t(I\\emph{dir}) p Fg(')c(compiler)k(\015ags,)h(one)f(for)f(eac)n(h)h(of)g(the)h(di-)515 4939 y(rectories)p 0 TeXcolorgray Black 1926 5255 a(8)p 0 TeXcolorgray eop end %%Page: 9 9 TeXDict begin 9 8 bop 0 TeXcolorgray Black 0 TeXcolorgray 0 TeXcolorgray 0 TeXcolorgray 515 523 a Ff(src/plugins/)p Fe(name)51 b Ff(src/vm/intplugin)o(s/)p Fe(n)o(am)o(e)h Ff(platforms/Cross/)o(plu)o(gi)o(ns)o(/)p Fe(na)o(me)515 623 y Ff(platforms/unix/p)o(lu)o(gi)o(ns/)o Fe(na)o(me)p Black 515 820 a Fg(in)28 b(whic)n(h)f(at)h(least)f(one)g(header)g (\014le)g(is)h(presen)n(t.)515 958 y Ff([targets])21 b Fg(is)j(a)h(list)g(of)f(ob)5 b(ject)25 b(\014les)g(corresp)r(onding)d (to)j(the)g(source)f(\()p Ff(.c)p Fg(\))g(\014les)h(found)g(in)515 1057 y(the)j(directories:)p 0 TeXcolorgray 0 TeXcolorgray 0 TeXcolorgray 515 1254 a Ff(src/plugins/)p Fe(name)8 b Ff(/*.c)41 b(src/vm/intplugins)o(/)p Fe(na)o(me)8 b Ff(/*.c)42 b(platforms/Cross)o(/pl)o(ug)o(ins)o(/)p Fe(n)o(ame)8 b Ff(/*.c)515 1354 y(platforms/unix/p)o(lu)o(gi)o(ns/)o Fe(na)o(me)g Ff(/*.c)p Black 515 1551 a Fg(where)25 b(eac)n(h)f(source) g(\014le)i(has)e(b)r(een)i(stripp)r(ed)g(of)f(the)h(directory)e(name)h (and)g(had)g(the)h(`)p Ff(.c)p Fg(')515 1651 y(con)n(v)n(erted)g(in)n (to)h(`)p Ff($o)p Fg('.)515 1788 y Ff([target])d Fg(is)k(the)g(name)f (of)h(the)f(plugin,)h(including)g(the)g Ff($a)f Fg(extension.)515 1926 y Ff([plibs])52 b Fg(is)27 b(a)g(list)h(of)g(zero)e(or)h(more)f (libraries)g(on)h(whic)n(h)h(the)g(plugin)f(dep)r(ends)h(\(as)f(de-)515 2026 y(tected)d(using)f(the)h(macro)f Ff(AC)p 1451 2026 27 4 v 30 w(PLUGIN)p 1745 2026 V 29 w(CHECK)p 1994 2026 V 29 w(LIB)g Fg(in)h(the)g(plugin-sp)r(eci\014c)f Ff(acinclude.)515 2125 y(m4)p Fg(\).)53 b(If)34 b(the)g(plugin)f(is)g(b)r(eing)h(built)g (in)n(ternally)e(then)i(this)g(list)f(is)h(empt)n(y)f(and)g(the)h(re-) 515 2225 y(quired)d(libraries)f(are)h(included)h(in)g(the)g(\014nal)f (link)h(command.)49 b(If)32 b(the)g(plugin)f(is)h(b)r(eing)515 2325 y(built)g(externally)e(then)i(the)f(plugin)h(itself)f(\(a)g (shared)g(ob)5 b(ject\))31 b(is)g(link)n(ed)g(against)f(these)515 2424 y(libraries)c(\(via)h Ff([plist])p Fg(\))e(rather)i(than)h(with)g (the)g(main)f(VM)h(binary)-7 b(.)515 2562 y(\(This)34 b(is)g(to)g(ensure)f(that)i(a)e(missing)h(shared)f(ob)5 b(ject)34 b(needed)g(b)n(y)g(an)g(external)f(plugin)515 2662 y(will)26 b(only)f(a\013ect)h(the)g(op)r(eration)e(of)i(that)g (plugin)g(and)f(not)h(prev)n(en)n(t)f(the)h(rest)f(of)h(the)g(VM)515 2761 y(from)f(running,)h(whic)n(h)f(w)n(ould)h(b)r(e)g(the)g(case)e(if) i(the)g(en)n(tire)g(VM)g(w)n(ere)e(link)n(ed)i(against)e(it.\))515 2899 y Ff([make)p 740 2899 V 29 w(inc])29 b Fg(is)i(the)g(con)n(ten)n (ts)f(of)h(the)g Ff(Makefile.inc)26 b Fg(\014le)31 b(in)h(y)n(our)d (plugin's)i Ff(platdep)515 2998 y Fg(directory)26 b(\(or)h(empt)n(y)h (if)g(this)g(\014le)f(do)r(esn't)h(exist\).)515 3136 y Ff([make)p 740 3136 V 29 w(targets])20 b Fg(is)j(a)g(list)g(of)g (rules)f(for)h(building)g(the)h(\014les)f(listed)g(in)h Ff([targets])p Fg(.)31 b(Eac)n(h)515 3236 y(rule)c(lo)r(oks)g(lik)n(e)g (this:)p Black Black 863 3448 a Ff(name$o)42 b(:)h Fe(original/source)o (/di)o(r/)8 b Ff(name.c)1212 3547 y($\(COMPILE\))40 b(name$o)h Fe(original/source)o(/di)o(r/)8 b Ff(name.c)515 3800 y Fh(3.2.2)93 b(A)32 b(note)g(ab)s(out)g Ff($\(COMPILE\))27 b Fh(and)33 b Ff($\(LINK\))c Fh(commands)515 3991 y Fg(Y)-7 b(ou)33 b(should)h Fd(never)43 b Fg(pass)33 b(additional)g(\015ags)g (to)g(these)h(commands)f(explicitly)-7 b(.)56 b(This)33 b(is)515 4091 y(b)r(ecause)e(y)n(ou)h(cannot)f(kno)n(w)h(ho)n(w)f(they) h(are)g(de\014ned.)50 b(\(Their)32 b(de\014nitions)h(dep)r(end)f(on)515 4190 y(whether)k(the)h(plugin)g(is)g(b)r(eing)g(built)g(in)n(ternally)f (or)g(externally)g(|)g(and)h(migh)n(t)g(ev)n(en)515 4290 y(c)n(hange)26 b(radically)g(in)i(future)g(releases)e(of)i(Unix)g (Squeak.\))515 4428 y(Instead)e(y)n(ou)h(should)f(pass)h(additional)f (compiler/link)n(er)f(\015ags)h(to)h(these)g(commands)f(b)n(y)515 4527 y(setting)h(the)h(follo)n(wing)f(v)-5 b(ariables)26 b(in)i(`)p Ff(Makefile.inc)p Fg(')23 b(or)k(`)p Ff(Makefile.in)p Fg(':)p Black Black 722 4719 a Ff(XCPPFLAGS)127 b Fg(`)p Ff(-)t(I)p Fg(')27 b(\015ags)g(for)g Ff(cpp)722 4819 y(XDEFS)303 b Fg(`)p Ff(-)t(D)p Fg(')27 b(\015ags)g(for)g Ff(cpp)722 4918 y(XCFLAGS)215 b Fg(an)n(ything)27 b(to)h(b)r(e)g (passed)f(to)g(the)h(compiler)722 5018 y Ff(XLDFLAGS)171 b Fg(an)n(ything)27 b(to)h(b)r(e)g(passed)f(to)g(the)h(link)n(er)p Black 1926 5255 a(9)p Black eop end %%Page: 10 10 TeXDict begin 10 9 bop Black Black 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 523 a Fg(Note:)70 b(`)p Ff(mkmf)p Fg(')23 b(already)f(uses)i(`)p Ff(XINCLUDES)p Fg(')c(to)k(pass)f(the)h (list)g(of)g(directories)722 623 y(con)n(taining)g(plugin)h(header)f (\014les)h(to)g Ff(cpp)p Fg(.)35 b(Y)-7 b(ou)25 b(can)f(rede\014ne)h (it)g(if)h(y)n(ou)e(lik)n(e,)722 722 y(but)j(mak)n(e)e(sure)g(that)h(`) p Ff([includes])p Fg(')21 b(app)r(ears)k(in)h(its)g(de\014nition)g (\(or)f(in)h(the)722 822 y(de\014nition)i(of)g(`)p Ff(XCPPFLAGS)p Fg('\).)p Black 515 1162 a Fh(3.2.3)93 b(Sp)s(ecifying)32 b(additional)f(source)h(directories)515 1357 y Ff(mkmf)27 b Fg(lo)r(oks)g(for)h(a)g(\014le)h(in)g(y)n(our)e(plugin's)i Ff(platdep)c Fg(directory)j(called)g(`)p Ff(mkmf.subdirs)p Fg('.)515 1457 y(If)38 b(this)h(\014le)f(exists)g(then)h(it)g(should)f (con)n(tain)f(a)h(list)g(of)g(directory)f(names)h(relativ)n(e)f(to)515 1556 y(the)31 b(top-lev)n(el)f(directory)f(\(the)i(one)g(con)n(taining) e(the)j Ff(src)d Fg(and)i Ff(platform)c Fg(directories\).)515 1656 y(These)d(directories)g(will)h(b)r(e)h(added)e(to)h(the)h(list)f (of)g(lo)r(cations)f(searc)n(hed)f(for)i(`)p Ff(.c)p Fg(')f(and)h(`)p Ff(.h)p Fg(')515 1756 y(\014les)40 b(while)h (constructing)f(the)h(substitutions)g(for)f(`)p Ff([includes])p Fg(',)g(`)p Ff([targets])p Fg(')d(and)515 1855 y(`)p Ff([make)p 763 1855 27 4 v 29 w(targets])p Fg('.)515 2112 y Fh(3.2.4)93 b(Including)32 b(additional)f(material)g(in)g(the)h (default)g Ff(Makefile)515 2307 y Fg(If)e(the)g(\014le)h Ff(platdep/Makefil)o(e.i)o(nc)23 b Fg(exists)30 b(then)g Ff(mkmf)f Fg(will)h(substitute)h(its)f(con)n(ten)n(ts)515 2407 y(in)n(to)d(the)h Ff(Makefile)c Fg(in)k(place)f(of)h(the)g Ff([make)p 1974 2407 V 29 w(inc])e Fg(k)n(eyw)n(ord.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 2631 a(Note:)73 b Ff(Makefile.inc)21 b Fg(is)26 b(read)g(in)n(to)g(the)g Ff(Makefile)d Fg(under)j(construction)722 2731 y Fd(b)l(efor)l(e)43 b Ff(mkmf)34 b Fg(p)r(erforms)h(substitutions)h(on)f(the)h(`)p Ff([keyword])p Fg('s.)57 b(In)36 b(other)722 2830 y(w)n(ords,)e(y)n (our)e Ff(Makefile.inc)d Fg(can)k(use)g(the)h(ab)r(o)n(v)n(e)e(k)n(eyw) n(ords)f(to)i(include)722 2930 y(relev)-5 b(an)n(t)25 b(declarations)g(and)g(rules)h(without)g(w)n(orrying)e(ab)r(out)h (whether)h(the)722 3029 y(plugin)i(is)f(in)n(ternal)g(or)g(external.)p Black 515 3370 a Fh(3.2.5)93 b(Replacing)31 b(the)h(default)g Ff(Makefile)d Fh(en)m(tirely)515 3565 y Fg(If)h(neither)g(of)f(the)i (ab)r(o)n(v)n(e)d(are)h(su\016cien)n(t)h(then)g(y)n(ou)f(can)g(create)g (a)h(complete)f Ff(Makefile)515 3664 y Fg(template)i(called)f Ff(platdep/Makefil)o(e.i)o(n)p Fg(.)39 b Ff(mkmf)29 b Fg(will)i(use)f(this)h(template)g(instead)f(of)515 3764 y(the)d(default)g Ff(Makefile)c Fg(template)k(sho)n(wn)f(earlier,)f (and)i(will)f(p)r(erform)h(k)n(eyw)n(ord)d(substi-)515 3863 y(tutions)k(on)g(it)h(as)f(describ)r(ed)g(ab)r(o)n(v)n(e)f(to)h (create)f(the)i(\014nal)f Ff(Makefile)p Fg(.)36 b(\(In)29 b(other)e(w)n(ords,)515 3963 y(simply)38 b(cop)n(ying)f(the)i(default)g (template)f(sho)n(wn)g(earlier)e(will)j(result)f(in)g(a)g Ff(Makefile)515 4063 y Fg(iden)n(tical)27 b(to)h(the)g(one)f(that)h Ff(mkmf)e Fg(w)n(ould)h(ha)n(v)n(e)f(pro)r(duced)i(b)n(y)f(default.)515 4337 y Fa(3.3)112 b(Examples)37 b(tak)m(en)h(from)e(existing)g(plugins) 515 4531 y Fg(By)30 b(w)n(a)n(y)f(of)h(example)g(w)n(e'll)g(lo)r(ok)g (at)g(ho)n(w)g(t)n(w)n(o)g(existing)g(plugins)g(sp)r(ecialise)f(their)i (con-)515 4631 y(\014guration)26 b(and)i Ff(Makefile)p Fg(s.)p Black 1905 5255 a(10)p Black eop end %%Page: 11 11 TeXDict begin 11 10 bop Black Black 515 523 a Fh(3.3.1)93 b(Con\014guration)515 707 y Fg(The)38 b Ff(B3DAcceleratorP)o(lug)o(in) 31 b Fg(requires)37 b(Op)r(enGL)h(in)g(order)e(to)i(compile.)67 b(The)38 b(\014le)515 807 y Ff(unix/plugins/B3D)o(Ac)o(ce)o(ler)o(at)o (orP)o(lu)o(gi)o(n/a)o(ci)o(ncl)o(ud)o(e.m)o(4)17 b Fg(con)n(tains)23 b(a)g(single)g(call)g(to)515 906 y(an)k Ff(autoconf)p Fg(-st)n(yle)d(macro:)p Black Black 689 1092 a Ff(AC)p 782 1092 27 4 v 31 w(PLUGIN)p 1077 1092 V 29 w(SEARCH)p 1370 1092 V 28 w(LIBS\(glIsEnabled,)37 b(GL\))515 1278 y Fg(This)d(w)n(orks)f(similarly)g(to)h(the)h Ff(autoconf)c Fg(`)p Ff(AC\\_SEARCH_LIBS)p Fg(')e(macro:)49 b(If)34 b(a)g(library)515 1378 y Ff(libGL.\\{a,)t(so\\})h Fg(\(Op)r(enGL\))42 b(exists)f(and)g(exp)r(orts)g(the)h(function)f Ff(glIsEnabled\(\))515 1477 y Fg(then)33 b(`)p Ff(-)t(lGL)p Fg(')f(is)h(added)g(to)f(the)i (\014nal)f(VM)g(link)g(command.)53 b(Otherwise)32 b(the)h(plugin)g(is) 515 1577 y(disabled)27 b(\(and)h(a)f(message)f(w)n(arning)g(of)i(the)g (fact)g(is)f(prin)n(ted\).)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 1763 a(Note:)66 b(There's)19 b(a)g(bug)g(here.)34 b(This)19 b(should)g(also)g(c)n(hec)n(k)f(for)h(`)p Ff(GL\\_VERSION\\) 722 1863 y(_1\\_1)p Fg(')26 b(in)i(headers.)p Black 515 2160 a Fh(3.3.2)93 b(Customising)29 b(the)j Ff(Makefile)515 2344 y Fg(The)d Ff(Mpeg3Plugin)24 b Fg(requires)k(a)g(\(mo)r (di\014ed\))i Ff(libmpeg)c Fg(to)j(b)r(e)h(compiled)e(along)g(with)i (it.)515 2444 y(The)23 b(sources)e(for)h(this)i(library)d(are)h(in)h (\(sev)n(eral\))f(sub)r(directories)g(of)h Ff(Cross/Meg3Plugi)o(n)515 2543 y Fg(and)k(they)h(require)e(additional)i Ff(cpp)e Fg(de\014nitions)i(in)g(order)e(to)h(compile)h(correctly)-7 b(.)515 2674 y(T)g(o)42 b(cop)r(e)g(with)h(the)g(additional)f (directories,)j Ff(unix/plugins/Mpeg)o(3Pl)o(ug)o(in)o(/mk)o(mf)o(.)515 2773 y(subdirs)25 b Fg(simply)i(lists)h(them:)p Black Black 602 2959 a Ff(platforms/Cross/)o(pl)o(ugi)o(ns)o(/Mp)o(eg)o(3P)o (lug)o(in)o(/li)o(bm)o(peg)602 3059 y(platforms/Cross/)o(pl)o(ugi)o(ns) o(/Mp)o(eg)o(3P)o(lug)o(in)o(/li)o(bm)o(peg)o(/a)o(ud)o(io)602 3159 y(platforms/Cross/)o(pl)o(ugi)o(ns)o(/Mp)o(eg)o(3P)o(lug)o(in)o (/li)o(bm)o(peg)o(/v)o(id)o(eo)515 3345 y Fg(T)-7 b(o)44 b(cop)r(e)g(with)h(the)f(additional)g Ff(cpp)f Fg(de\014nitions,)49 b(w)n(e)44 b(could)g(ha)n(v)n(e)g(written)g(a)g(tin)n(y)515 3444 y Ff(Makefile.inc)22 b Fg(con)n(taining:)p Black Black 689 3630 a Ff(XDEFS)129 b(=)43 b(-DNOPTHREADS)515 3816 y Fg(Unfortunately)29 b(the)g(additional)g(source)f(directories)f (con)n(tain)i(v)-5 b(arious)27 b(utilit)n(y)j(and)f(test)515 3916 y(programs)e(\(whic)n(h)k Fd(must)f(not)38 b Fg(b)r(e)30 b(built\))h(so)f(w)n(e)f(cannot)h(rely)f(on)h Ff(mkmf)e Fg(generating)h(the)515 4016 y(correct)d Ff([targets])e Fg(list.)515 4146 y(Instead)18 b(w)n(e)g(just)h(cop)n(y)e(the)i (default)g Ff(Makefile)c Fg(\\template")j(\(sho)n(wn)g(ab)r(o)n(v)n (e\))f(as)h Ff(Mpeg3Plugin/)515 4245 y(Makefile.in)23 b Fg(and)28 b(insert)f(the)i(required)e(list)h(of)g(targets)e(\(and)i Ff(cpp)f Fg(de\014nition\))i(man)n(u-)515 4345 y(ally)-7 b(.)36 b(The)28 b(end)g(result)f(is)g(sho)n(wn)g(in)h(Figure)f(2.)p 1 0 0 TeXcolorrgb Black 1 0 0 TeXcolorrgb 722 4531 a(Note:)73 b(The)26 b(default)g(`)p Ff([make\\_targets])p Fg(')20 b(will)26 b(con)n(tain)g(additional)f(rules)722 4631 y(for)f(the)g(ob)5 b(jects)24 b(that)g(w)n(e're)f(trying)h(to)g(a)n(v)n (oid)e(building)j(\(b)r(ecause)e(it's)i(built)722 4730 y(from)31 b(an)g(exhaustiv)n(e)f(list)h(of)g(`)p Ff(.c)p Fg(')g(\014les)g(in)g(the)h(source)d(directories\).)47 b(This)722 4830 y(do)r(es)26 b(no)g(harm)g(since)g(the)h(o\013ending)f (rules)g(can)g(nev)n(er)f(b)r(e)i(triggered)d(\(their)722 4930 y(targets)j(are)f(not)i(listed)g(in)g(`)p Ff(OBJS)p Fg('\).)p Black Black 1905 5255 a(11)p Black eop end %%Page: 12 12 TeXDict begin 12 11 bop Black Black Black Black Black Black Black 722 491 a Ff(#)43 b(Makefile.in)c(for)k(Mpeg3Plugin)c(in)k (Unix)f(Squeak)722 690 y([make_cfg])722 790 y([make_plg])722 989 y(TARGET)85 b(=)43 b(Mpeg3Plugin$a)722 1188 y(PLUGIN)85 b(=)43 b(Mpeg3Plugin$o)722 1288 y(VIDEO)129 b(=)43 b(getpicture$o)c (headers$o)h(idct$o)h(macroblocks$o)d Fe(etc...)722 1387 y Ff(AUDIO)129 b(=)43 b(dct$o)f(header$o)e(layer1$o)g(layer2$o)g (layer3$o)h Fe(etc...)722 1487 y Ff(LIBMPEG)g(=)i(bitstream$o)c (changesForSqueak$)o(o)e(libmpeg3$o)j Fe(etc...)722 1686 y Ff(OBJS)173 b(=)43 b($\(PLUGIN\))d($\(VIDEO\))g($\(AUDIO\))h ($\(LIBMPEG\))722 1886 y(XINCLUDES)302 b(=)43 b([includes])722 1985 y(XDEFS)478 b(=)43 b(-DNOPTHREADS)722 2184 y($\(TARGET\))d(:)j ($\(OBJS\))e(Makefile)1071 2284 y($\(LINK\))g($\(TARGET\))f($\(OBJS\)) 722 2483 y([make_targets])722 2683 y(.force)h(:)p Black 981 2948 a Fg(Figure)27 b(2:)36 b Ff(unix/plugins/Mpe)o(g3P)o(lu)o(gin) o(/M)o(ak)o(efi)o(le)o(.in)p Black Black 515 3197 a Fa(3.4)112 b(Coping)37 b(with)f(VMMak)m(er)i(quirks)515 3383 y Fg(VMMak)n(er)31 b(will)h(refuse)f(to)h(compile)g(a)f(plugin)h(if)g(it)h(thinks)f(the)g (plugin)g(requires)e(plat-)515 3483 y(form)h(supp)r(ort.)49 b(This)32 b(is)f(\\all-or-nothing":)e(if)j(platform)f(supp)r(ort)h(is)g (required)e(on)i Fd(one)515 3582 y Fg(platform)c(then)i(it)f(is)g (required)f(on)h Fd(al)t(l)38 b Fg(platforms)29 b(\(ev)n(en)f(if)i(the) f(plugin)g(compiles)g(quite)515 3682 y(happily)e(without)h(platform)f (supp)r(ort)h(in)g(Unix\).)515 3814 y(The)22 b(easiest)e(w)n(a)n(y)h (to)h(add)f(\\n)n(ull")g(platform)g(supp)r(ort)h(is)g(to)f(place)g(an)h (empt)n(y)g(`)p Ff(Makefile.)515 3914 y(inc)p Fg(')33 b(in)i(the)g(plugin's)g Ff(platdep)d Fg(directory)-7 b(.)57 b(\(T)-7 b(o)34 b(see)g(this)h(in)g(action,)h(lo)r(ok)e(in)h Ff(unix/)515 4013 y(plugins/JPEGRead)o(Wr)o(it)o(er2)o(Pl)o(ugi)o(n)p Fg(.\))515 4274 y Fa(3.5)112 b(If)37 b(all)f(else)h(fails)515 4460 y Fg(\(Where)h(\\all)f(else)h(failing")f(is)h(de\014ned)g(as:)g (\\after)f(trying)g(for)h(20)f(min)n(utes)h(and)g(still)515 4559 y(getting)27 b(no)n(where".\))515 4691 y(If)h(y)n(ou're)e(writing) h(a)g(plugin)g(that)h(needs)f(platform)g(supp)r(ort)g(\(b)r(ey)n(ond)h (dum)n(b)f(inclusion)515 4791 y(of)j(a)f(few)h(additional)f(`)p Ff(.c)p Fg(')h(\014les\))g(and)f(this)h(do)r(cumen)n(t)g(has)g(b)r(een) g(of)g(no)f(help)h(at)g(all)g(\(or)515 4890 y(if)g(y)n(ou)f(understo)r (o)r(d)h(it)g(but)g(y)n(ou're)f(still)h(su\013ering)f(from)h(\\all)f (else)g(failing"\))h(then)g(send)515 4990 y(me)d(mail)h(and)f(I'll)h(b) r(e)g(happ)n(y)f(to)h(help)g(y)n(ou)f(with)h(the)g(v)-5 b(arious)26 b(platdep)i(\014les.)p Black 1905 5255 a(12)p Black eop end %%Page: 13 13 TeXDict begin 13 12 bop Black Black Black 515 648 a Fi(Index)p Black 515 813 a Ff([includes])p Fg(,)23 b(8)515 913 y Ff([make)p 740 913 27 4 v 29 w(cfg])p Fg(,)j(8)515 1013 y Ff([make)p 740 1013 V 29 w(inc])p Fg(,)g(9)515 1112 y Ff([make)p 740 1112 V 29 w(plg])p Fg(,)g(8)515 1212 y Ff([make)p 740 1212 V 29 w(targets])p Fg(,)e(9)515 1312 y Ff([plibs])p Fg(,)h(9)515 1411 y Ff([target])p Fg(,)f(9)515 1511 y Ff([targets])p Fg(,)g(9)515 1610 y Ff($\(COMPILE\))p Fg(,)f(9)515 1710 y Ff($\(LINK\))p Fg(,)i(9)515 1810 y Ff($\(XCFLAGS\))p Fg(,)e(9)515 1909 y Ff($\(XCPPFLAGS\))p Fg(,)g(9)515 2009 y Ff($\(XDEFS\))p Fg(,)h(9)515 2109 y Ff($\(XINCLUDES\))p Fg(,)f(10)515 2208 y Ff($\(XLDFLAGS\))p Fg(,)g(9)515 2389 y Ff(AC)p 608 2389 V 30 w(PLUGIN)p 902 2389 V 29 w(CHECK)p 1151 2389 V 30 w(LIB)p Fg(,)j(6)515 2489 y Ff(AC)p 608 2489 V 30 w(PLUGIN)p 902 2489 V 29 w(DEFINE)p 1195 2489 V 29 w(UNQUOTED)p Fg(,)f(7)515 2588 y Ff(acinclude.m4)p Fg(,)e(6)681 2688 y(example,)k(11)515 2788 y(additional)c(plugin)h (source)f(directories,)847 2887 y(10)515 3068 y(build)28 b(directory)681 3168 y(con\014guring,)e(3)681 3268 y(creating,)g(3)515 3449 y Ff(config.status)p Fg(,)c(5)681 3548 y(v)n(ersus)k Ff(configure)p Fg(,)e(5)515 3648 y Ff(configure)p Fg(,)g(6)681 3748 y(macros)i(for)h(plugins,)g(6)681 3847 y(recreating,)f(6)515 4028 y(emergency)g(services,)g(12)515 4209 y Ff(Makefile)p Fg(,)e(7)681 4309 y(a)n(v)n(oiding)j Ff($\(XINCLUDES\))p Fg(,)22 b(10)681 4408 y(compile/link)27 b(commands,)g(9)681 4508 y(k)n(eyw)n(ord)e(substitution,)k(7)681 4608 y(passing)d(extra)h (\015ags,)g(9)681 4707 y(replacing,)f(10)681 4807 y(target)g(rules,)i (9)515 4907 y Ff(Makefile)c Fg(k)n(eyw)n(ords)681 5006 y Ff([includes])p Fg(,)f(8)p Black Black 2258 813 a Ff([make)p 2483 813 V 30 w(cfg])p Fg(,)j(8)2258 913 y Ff([make)p 2483 913 V 30 w(inc])p Fg(,)g(9)2258 1013 y Ff([make)p 2483 1013 V 30 w(plg])p Fg(,)g(8)2258 1112 y Ff([make)p 2483 1112 V 30 w(targets])p Fg(,)e(9)2258 1212 y Ff([plibs])p Fg(,)h(9)2258 1312 y Ff([target])p Fg(,)g(9)2258 1411 y Ff([targets])p Fg(,)f(9)2092 1511 y Ff(Makefile.in)p Fg(,)f(10)2258 1610 y(example,)k(11)2092 1710 y Ff(Makefile.inc)p Fg(,)c(10)2258 1810 y(example,)k(11)2258 1909 y(k)n(eyw)n(ord)f (substitution,)i(10)2092 2009 y Ff(mkmf)p Fg(,)e(7)2258 2109 y(additional)18 b(source)f(directories,)i(10)2258 2208 y(default)28 b(header)f(directories,)f(8)2258 2308 y(default)i(source)f(directories,)f(9)2092 2407 y Ff(mkmf.subdirs)p Fg(,)d(10)2258 2507 y(example,)k(11)2092 2690 y(plugin)2258 2789 y Ff(Makefile)p Fg(,)e(7)2258 2889 y Ff(Makefile)g Fg(anatom)n(y)-7 b(,)26 b(7)2258 2989 y(adding)h(y)n(our)g(o)n(wn,)g(5) 2258 3088 y(con\014guring,)f(6)2258 3188 y(target)h(rules,)g(9)2258 3287 y(Unix-sp)r(eci\014c)h(directory)-7 b(,)26 b(6)2092 3470 y(Unix-sp)r(eci\014c)i(\014les,)f(6)2092 3653 y(VMMak)n(er)2258 3752 y(con\014guration)f(\014le,)i(4)2258 3852 y(missing)f(platform)h (supp)r(ort,)f(12)2258 3952 y(reference,)g(4)p Black 1905 5255 a(13)p Black eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF ================================================ FILE: vm/src/from_squeak/unix/doc/HowToBuildFromSource.txt ================================================ ****** Building Unix Squeak (>= 3.2) from source ****** Ian Piumarta Last edited: 2005-03-17 12:43:23 by piumarta on squeak.hpl.hp.com Translated to .ps/.pdf/.html/.txt: March 17, 2005 ***** Contents ***** * 0_The_easy_way * 1_The_hard_way:_configure,_build,_install * 2_Generating_your_own_VM_and_plugin_sources o 2.1_How_configure_finds_the_src_directory * 3_Adding_your_own_plugins o 3.1_Plugin-specific_configuration o 3.2_Plugin-specific_Makefile_declarations_and_rules o 3.3_Examples_taken_from_existing_plugins o 3.4_Coping_with_VMMaker_quirks o 3.5_If_all_else_fails * Index ****** 0 The easy way ****** Beginning with version 3.7-7, everything you need is included with the Unix sources regardless of how you obtained them - either as a tarball or by repository checkout. (This was done to eliminate frequent problems encountered by people combining the repository Unix and Cross sources with a set of incompatible generated sources.) If you extract a tarball then you will have a top-level directory named Squeak- X.Y-Z (for some values of X, Y, and Z). If you are checking out from a repository, you can call the direcory anything you like; for example: $ svn co http://squeak.hpl.hp.com/svn/squeak/trunk squeak will leave you with a directory called squeak. (We'll assume from now on that the directory is called squeak.) Next change to the 'unix' directory within the sources that you just checked out (or extracted from the tarball): $ cd squeak/platforms/unix Build the VM and plugins by running make: $ make Then install the VM, plugins and manual pages by running make again (with superuser privileges): $ sudo make install To delete the temporary files created during the build process, run make one last time: $ make clean That's all there is to it. ****** 1 The hard way: configure, build, install ****** Unix Squeak is built using the (almost) universal ``configure; make; make install''. If you haven't come across this before, read on... Create a build directory (which we will call `blddir' from now on) and then `cd' to it: $ mkdir blddir $ cd blddir A convenient place is just next to the platforms directory, like this: $ cd squeak $ ls platforms src ... $ mkdir bld $ cd bld Create the build environment by running the script configure which lives in the platforms/unix/config directory. Note: The configure script accepts lots of options. To see a list of them, run: `configure --help' Assuming you've created the blddir next to platforms, this would be: $ ../platforms/unix/config/configure Note: This assumes that the VMMaker sources are in `../src'. However, since the Unix Squeak support code is independent of the image version from which VMMaker generated the interpreter/plugin sources, it is possible that your source distribution comes with more than one src directory (corresponding to more than one image version used to generate the sources). In such cases you will have to tell configure which source version to use, via the `--with-src' option. For example, if there are two source directories called src-3.2gamma-4857 and src-3.3.alpha-4881 then you would use one of the following commands: $ .../configure --with-src=src-3.2gamma-4857 nbsp;CLASS="textit">or $ .../configure --with-src=src-3.3alpha-4881 Build the VM and plugins by running make: $ make Note: If you want to build just the VM (without external plugins) or just the external plugins (without the VM) then you can use: `make squeak' or `make plugins' respectively. Finally install the VM, plugins and manual pages: $ su root $ make install ****** 2 Generating your own VM and plugin sources ****** Generating your own VM/plugin sources might be necessary for various reasons: * you want to change the mix of internal vs. external plugins * you want to remove some plugins from the VM that you will never use * you've pulled in some updates that modify the Interpreter or plugins * you've filed-in (or written) a whole new plugin * etc... Version 3.2 (and later) of Unix Squeak use VMMaker to generate the core interpreter and plugin sources. Start Squeak in the top-level directory (the one containing the platforms directory); for example: $ ls src platforms ... $ squeak MyCoolPlugin.image Open a VMMakerTool and modify the setup to your liking. Note: The VMMaker configuration used to build the distributions of Unix Squeak is available in platforms/unix/config/VMMaker.config. Then click on the relevant ``generate ...'' button. You can now `configure; make; make install' in your blddir (as described above). Note: You only need to run configure once for a given blddir (on the same host). If you modify the choice of plugins (or change whether they're internal/external) then you can update the build environment by running the config.status script in the bldddir, like this: $ squeak MyCoolPlugin.image ... generate new sources ... $ cd blddir $ ./config.status $ make This is much faster than running configure all over again. (In fact, make should detect any changes to the plugin configuration and re-run config.status for you automatically.) Note: `configure' doesn't actually create any files. The last thing it does is run `config.status' to create the configured files in blddir from the corresponding file.ins in the unix/config directory. So in the remainder of this document the phrase `during configuration' means either when running `configure' for the first time or running `config.status' to update an already configured build environment. ***** 2.1 How configure finds the src directory ***** Starting with version 3.7 configure looks in two places for the src directory, in the following order, and uses the first one that it finds: * the top-level directory (the one containing the platforms directory); * the platforms/unix directory. In other words, if you want to use your own generated sources without deleting the built-in generated sources, generating them into a src directory next to platforms (and then re-running configure) will do what you want. ****** 3 Adding your own plugins ****** Note: This section is intended primarily for plugin developers. If your plugin requires no platform-specific tweaks then there's nothing for you to do. configure (and config.status) will provide a default Makefile for it that should work. If your plugin requires only platform-independent tweaks (and/or additional hand-written code) then these go in platforms/Cross/plugins, and there's nothing for you to do (in Unixland). On the other hand, if you require special configure tests or additional declarations/rules in your plugin's Makefile then you need to specify them explicitly. Note: Unix Squeak subscribes to the following philopsophy: Absolutely everything that is specific to Unix (sources, headers, configure and Makefile extensions, etc.) lives under platforms/unix. In other words: there is not (nor aught there be) any Unix-related information under the platforms/Cross directory. (Unix Squeak is entirely encapsulated under platforms/unix and is utterly immune to ``random junk'' elsewhere in the platforms tree.) First you must create a new directory under platforms/unix/plugins named after your plugin. This directory will hold the files describing the additional configuration checks and/or Makefile contents. For example, if your plugin is called ``MyCoolPlugin'' then $ mkdir platforms/unix/plugins/MyCoolPlugin would be the thing to do. (The following sections will refer to this directory as platdep since the full path is quite a mouthful of typing for my lazy fingers.) ***** 3.1 Plugin-specific configuration ***** Your plugin can ask configure to run additional tests (and to set additional variables in its output files) simply by including a file called acinclude.m4 in it's platdep directory. Note: The configure script is `compiled' from several other files. If you create a `platdep./acinclude.m4' file then you must `recompile' configure. You can do this by `cd'ing to unix/config and running `make', or (if you have GNU make) from the blddir like this: $ make -C ../platforms/unix/config In addition to the usual autoconf macros, the following macros are available specifically for Squeak plugins to use: **** 3.1.1 AC_PLUGIN_CHECK_LIB(lib,func) **** This is similar to the autoconf `AC_CHECK_LIB' macro. func is the name of a function required by the plugin, defined in the external (system) library lib. The macro checks that the library is available (via `- llib') and then adds it to the list of libraries required by the plugin (see the explanation of [plibs] in Section 3.2.1 for a description of how library dependencies for plugins are handled). If func cannot be found in lib then the plugin will be disabled and a message to that effect printed during configuration. (The VM can still be built, without rerunning VMMaker or reconfiguring, and the plugin will simply be ommitted from it.) **** 3.1.2 AC_PLUGIN_DEFINE_UNQUOTED(keyword,text) **** This is similar to the autoconf `AC_DEFINE_UNQUOTED' macro. keyword is a Makefile keyword (usually of the form `[name]') and text is arbitrary text to be associated with it. Calling this macro causes mkmf to substitute text for all occurrences of keyword in the Makefile generated for the plugin. **** 3.1.3 Plugin-specific variables **** The following variables are also set during the execution of a plugin-specific acinclude.m4: ${plugin} is the name of the plugin; ${topdir} is the path to the top-level directory (containing platforms); ${vmmdir} is the path to the VMMaker `src' directory. ***** 3.2 Plugin-specific Makefile declarations and rules ***** Three mechanisms are avilable for this: 1. scanning additional dirrectories for sources and headers; 2. including a few additional lines into the default Makefile; and 3. replacing entirely the default Makefile with a hand-written one. (The last option isn't as scary as it might sound: read on...) **** 3.2.1 The anatomy of a plugin's Makefile **** Before proceeding, let's take a minute to understand how Unix Squeak compiles and links files in its default Makefile for plugins. The default Makefile looks like this: # default Makefile for Unix Squeak plugins [make_cfg] [make_plg] XINCLUDES = [includes] OBJS = [targets] TARGET = [target] PLIBS = [plibs] [make_inc] $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) $(PLIBS) [make_targets] .force : Note: The keywords appearing between `[ square brackets ]' are substituted during configuration by a preprocessor called `mkmf' according to the kind of plugin (internal/external) being built. [make_cfg] is the configured variable section. It contains the platform- specific information gleaned by configure while it was figuring out which compiler you have, what flags your linker needs, where to install stuff, and so on. [make_plg] contains a handful of definitions which depend on whether the plugin is being compiled as internal or external: o the extension for object files a the extension for plugins COMPILE the command to compile a source file into an object file LINK the command to link one or more object files into a plugin For internal plugins: $o is `.o' and $a is `.a'. $(COMPILE) is the C compiler (`$(CC) ... -o', so the first thing after the command must be the output filename) and $(LINK) is archiver (`ar -rc', again requiring the output file to follow immediately). Note that internal plugins are built as `ar' archives before being linked into the final binary. For external plugins: $o is `.lo', $a is `.la', and $(COMPILE) and $(LINK) are invocations of `libtool' to create position-independent objects and shared libraries (with a `-o' appearing right at the end, so the first thing after the command must be the output filename). [includes] is a list of `-Idir' compiler flags, one for each of the directories src/plugins/nbsp;CLASS="textit">name src/vm/intplugins/ nbsp;CLASS="textit">name platforms/Cross/plugins/ nbsp;CLASS="textit">name platforms/unix/plugins/ nbsp;CLASS="textit">name in which at least one header file is present. [targets] is a list of object files corresponding to the source (.c) files found in the directories: src/plugins/nbsp;CLASS="textit">name/*.c src/vm/intplugins/ nbsp;CLASS="textit">name/*.c platforms/Cross/plugins/ nbsp;CLASS="textit">name/*.c platforms/unix/plugins/ nbsp;CLASS="textit">name/*.c where each source file has been stripped of the directory name and had the `.c' converted into `$o'. [target] is the name of the plugin, including the $a extension. [plibs] is a list of zero or more libraries on which the plugin depends (as detected using the macro AC_PLUGIN_CHECK_LIB in the plugin-specific acinclude.m4). If the plugin is being built internally then this list is empty and the required libraries are included in the final link command. If the plugin is being built externally then the plugin itself (a shared object) is linked against these libraries (via [plist]) rather than with the main VM binary. (This is to ensure that a missing shared object needed by an external plugin will only affect the operation of that plugin and not prevent the rest of the VM from running, which would be the case if the entire VM were linked against it.) [make_inc] is the contents of the Makefile.inc file in your plugin's platdep directory (or empty if this file doesn't exist). [make_targets] is a list of rules for building the files listed in [targets]. Each rule looks like this: name$o : nbsp;CLASS="textit">original/source/dir/name.c $(COMPILE) name$o nbsp;CLASS="textit">original/source/dir/name.c **** 3.2.2 A note about $(COMPILE) and $(LINK) commands **** You should never pass additional flags to these commands explicitly. This is because you cannot know how they are defined. (Their definitions depend on whether the plugin is being built internally or externally -- and might even change radically in future releases of Unix Squeak.) Instead you should pass additional compiler/linker flags to these commands by setting the following variables in `Makefile.inc' or `Makefile.in': XCPPFLAGS `-I' flags for cpp XDEFS `-D' flags for cpp XCFLAGS anything to be passed to the compiler XLDFLAGS anything to be passed to the linker Note: `mkmf' already uses `XINCLUDES' to pass the list of directories containing plugin header files to cpp. You can redefine it if you like, but make sure that `[includes]' appears in its definition (or in the definition of `XCPPFLAGS'). **** 3.2.3 Specifying additional source directories **** mkmf looks for a file in your plugin's platdep directory called `mkmf.subdirs'. If this file exists then it should contain a list of directory names relative to the top-level directory (the one containing the src and platform directories). These directories will be added to the list of locations searched for `.c' and `.h' files while constructing the substitutions for `[includes]', `[targets]' and `[make_targets]'. **** 3.2.4 Including additional material in the default Makefile **** If the file platdep/Makefile.inc exists then mkmf will substitute its contents into the Makefile in place of the [make_inc] keyword. Note: Makefile.inc is read into the Makefile under construction before mkmf performs substitutions on the `[keyword]'s. In other words, your Makefile.inc can use the above keywords to include relevant declarations and rules without worrying about whether the plugin is internal or external. **** 3.2.5 Replacing the default Makefile entirely **** If neither of the above are sufficient then you can create a complete Makefile template called platdep/Makefile.in. mkmf will use this template instead of the default Makefile template shown earlier, and will perform keyword substitutions on it as described above to create the final Makefile. (In other words, simply copying the default template shown earlier will result in a Makefile identical to the one that mkmf would have produced by default. ***** 3.3 Examples taken from existing plugins ***** By way of example we'll look at how two existing plugins specialise their configuration and Makefiles. **** 3.3.1 Configuration **** The B3DAcceleratorPlugin requires OpenGL in order to compile. The file unix/ plugins/B3DAcceleratorPlugin/acinclude.m4 contains a single call to an autoconf-style macro: AC_PLUGIN_SEARCH_LIBS(glIsEnabled, GL) This works similarly to the autoconf `AC_SEARCH_LIBS' macro: If a library libGL.{a,so} (OpenGL) exists and exports the function glIsEnabled() then `-lGL' is added to the final VM link command. Otherwise the plugin is disabled (and a message warning of the fact is printed). Note: There's a bug here. This should also check for `GL_VERSION_1_1' in headers. **** 3.3.2 Customising the Makefile **** The Mpeg3Plugin requires a (modified) libmpeg to be compiled along with it. The sources for this library are in (several) subdirectories of Cross/Meg3Plugin and they require additional cpp definitions in order to compile correctly. To cope with the additional directories, unix/plugins/Mpeg3Plugin/mkmf.subdirs simply lists them: platforms/Cross/plugins/Mpeg3Plugin/libmpeg platforms/Cross/plugins/Mpeg3Plugin/libmpeg/audio platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video To cope with the additional cpp definitions, we could have written a tiny Makefile.inc containing: XDEFS = -DNOPTHREADS Unfortunately the additional source directories contain various utility and test programs (which must not be built) so we cannot rely on mkmf generating the correct [targets] list. Instead we just copy the default Makefile ``template'' (shown above) as Mpeg3Plugin/Makefile.in and insert the required list of targets (and cpp definition) manually. The end result looks like this: # Makefile.in for Mpeg3Plugin in Unix Squeak [make_cfg] [make_plg] TARGET = Mpeg3Plugin$a PLUGIN = Mpeg3Plugin$o VIDEO = getpicture$o headers$o idct$o macroblocks$o nbsp;CLASS="textit">etc... AUDIO = dct$o header$o layer1$o layer2$o layer3$o nbsp;CLASS="textit">etc... LIBMPEG = bitstream$o changesForSqueak$o libmpeg3$o nbsp;CLASS="textit">etc... OBJS = $(PLUGIN) $(VIDEO) $(AUDIO) $(LIBMPEG) XINCLUDES = [includes] XDEFS = -DNOPTHREADS $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) [make_targets] .force : Note: The default `[make_targets]' will contain additional rules for the objects that we're trying to avoid building (because it's built from an exhaustive list of `.c' files in the source directories). This does no harm since the offending rules can never be triggered (their targets are not listed in `OBJS'). ***** 3.4 Coping with VMMaker quirks ***** VMMaker will refuse to compile a plugin if it thinks the plugin requires platform support. This is ``all-or-nothing'': if platform support is required on one platform then it is required on all platforms (even if the plugin compiles quite happily without platform support in Unix). The easiest way to add ``null'' platform support is to place an empty `Makefile.inc' in the plugin's platdep directory. (To see this in action, look in unix/plugins/JPEGReadWriter2Plugin.) ***** 3.5 If all else fails ***** (Where ``all else failing'' is defined as: ``after trying for 20 minutes and still getting nowhere''.) If you're writing a plugin that needs platform support (beyond dumb inclusion of a few additional `.c' files) and this document has been of no help at all (or if you understood it but you're still suffering from ``all else failing'') then send me mail and I'll be happy to help you with the various platdep files. ***** Index ***** $(COMPILE) 3.2.2 $(LINK) 3.2.2 $(XCFLAGS) 3.2.2 $(XCPPFLAGS) 3.2.2 $(XDEFS) 3.2.2 $(XINCLUDES) 3.2.2 $(XLDFLAGS) 3.2.2 [includes] 3.2.1 [make_cfg] 3.2.1 [make_inc] 3.2.1 [make_plg] 3.2.1 [make_targets] 3.2.1 [plibs] 3.2.1 [target] 3.2.1 [targets] 3.2.1 AC_PLUGIN_CHECK_LIB 3.1.1 AC_PLUGIN_DEFINE_UNQUOTED 3.1.2 acinclude.m4 3.1 example 3.3.1 additional plugin source directories 3.2.3 build directory configuring 1 creating 1 config.status 2 versus configure 2 configure 3.1 macros for plugins 3.1 recreating 3.1 emergency services 3.5 Makefile 3.2.1 avoiding $(XINCLUDES) 3.2.2 compile/link commands 3.2.2 keyword substitution 3.2.1 passing extra flags 3.2.2 replacing 3.2.5 target rules 3.2.1 Makefile keywords [includes] 3.2.1 [make_cfg] 3.2.1 [make_inc] 3.2.1 [make_plg] 3.2.1 [make_targets] 3.2.1 [plibs] 3.2.1 [target] 3.2.1 [targets] 3.2.1 Makefile.in 3.2.5 example 3.3.2 Makefile.inc 3.2.4 example 3.3.2 keyword substitution 3.2.4 mkmf 3.2.1 additional source directories 3.2.3 default header directories 3.2.1 default source directories 3.2.1 mkmf.subdirs 3.2.3 example 3.3.2 plugin Makefile 3.2 Makefile anatomy 3.2.1 adding your own 3 configuring 3.1 target rules 3.2.1 Unix-specific directory 3 Unix-specific files 3 VMMaker configuration file 2 missing platform support 3.4 reference 2 =============================================================================== 2005-03-17 ================================================ FILE: vm/src/from_squeak/unix/doc/LICENSE ================================================ Source files below 'platforms/Cross' in this distribution that do not contain individual copyright and license notices, and Source files below 'platforms/unix/src' in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Viewpoints Research Institute and other authors/contributors as listed. All rights reserved. All other source files below platforms/unix in this distribution that do not contain individual copyright and license notices are: Copyright (C) 1996-2006 by Ian Piumarta and other authors/contributors listed in individual source files. All rights reserved. For all of the above files: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: vm/src/from_squeak/unix/doc/Makefile ================================================ MAIN = HowToBuildFromSource all : $(MAIN).ps $(MAIN).html/$(MAIN).html $(MAIN).pdf $(MAIN).txt dvi : $(MAIN).dvi .SUFFIXES : .tex .dvi .ps .pdf .html .txt .ps.pdf : ps2pdf $< $@ .dvi.ps : # dvips -P cmz -o $@ $< dvips -o $@ $< .tex.dvi : .force latex $(MAIN).tex latex $(MAIN).tex makeindex $(MAIN).idx latex $(MAIN).tex $(MAIN).html/%.html : %.tex Makefile test -d tmp || mkdir tmp latex2html -dir tmp -local_icons -auto_prefix -show_section_numbers -split 4 $(MAIN).tex test -d $(MAIN).html || mkdir $(MAIN).html cp -p tmp/*.html tmp/*.css tmp/*.png $(MAIN).html/. /bin/rm -rf tmp $(MAIN).txt : $(MAIN).tex html2text.rc Makefile test -d tmp || mkdir tmp latex2html -dir tmp -nonavigation -noinfo -show_section_numbers -split 0 $(MAIN).tex html2text -rcfile html2text.rc -nobs tmp/$(MAIN).html | uniq > $@ /bin/rm -rf tmp clean : .force /bin/rm -f *~ *.{aux,idx,ilg,ind,log,out,toc} distclean : clean /bin/rm -rf $(MAIN).html /bin/rm -f *.{dvi,ps,pdf,txt} .force : ================================================ FILE: vm/src/from_squeak/unix/doc/README.Contributing ================================================ If you plan on contributing code or submitting patches to fix bugs then PLEASE adhere to the following coding conventions. Doing so makes my life easier (since I *will* reformat myself any code that doesn't conform) and makes your code much more likely to be accepted (since any code that is difficult to read because of formatting problems simply won't get read, and if I haven't read it then it isn't going into my sources -- period). Of course, if you're submitting an entire file full of stuff (and you are therefore the original author of the file) then you can format it any way you like (and tell the rest of us how we have to format our code to get it included in your file. ;-) The following guidelines are sufficiently close to the GNU Coding Standards that you shouldn't need to change any of Emacs's C-mode variables from their default settings. FORMATTING CODE --------------- Tabs stops are every TWO characters. Regardless of what Torvalds might say, if tab stops were meant to be 8 characters apart then humans would have evolved wide-angle vision shortly after the invention of the Newbury terminal. (If your editor doesn't remind you about the matching delimiter when a block is more than a page long then it's time you evolved to Emacs. ;-) Always use C-style comment delimiters. Unix Squeak runs on lots of platforms where GNU gcc is not the standard compiler. Many of these compilers choke (quite rightly) on C++ style comments. Similarly, always comment-out any additional explanatory text appearing after `#else' and `#endif'. Use `#if defined(...)' in preference to `#ifdef ...'. Indent preprocessor commands to reflect the nesting of conditional sections, and place a comment after any `#else' or `#endif' that isn't utterly obvious: #if defined(LAZY) # include # ... # if defined(VERY_LAZY) # include # ... # endif # ... #else /* !LAZY */ # include #endif Declarations and external definitions should start in column zero. The only exception is for small conditional sections where indentation helps to show the "scope" of the conditional code. Hence: #if defined(EAT_DONUTS) # include int donutCounter= 0; /* number of donuts consumed since startup */ #endif /* EAT_DONUTS */ But don't overdo this -- the start/end of the conditional section should remain clearly visible while looking at indented declarations. Always use ANSI prototypes, and put the return types of functions and their identifiers on the same line (unless you rely on tools that prefer function names to start in column zero, in which case you're forgiven in advance). Hence: static char *concat(char *s1, char *s2) { ... } If the arguments don't fit nicely on one line, and the function identifier is short, split the declaration like this: int lotsOfArgs(int anInteger, long aLong, short aShort, double aDouble, float aFloat) ... If the identifier is enormous (which sometimes happens because of the frequent association between C functions and Squeak selectors) then put the opening parenthesis on the next line, indented by four characters. (That way Emacs knows how to indent the rest of the arguments nicely.) Like this: int ioDoSomethingObscureWithFarTooMuchBabbleInTheIdentifier (int anInteger, long aLong, short aShort, double aDouble, float aFloat) ... Put spaces on either side of an arithmetic or relational operator. One of the most common (and most difficult to debug) problems in C is caused by writing `=' when you meant `=='. To avoid such mistakes, it is a great help to omit the space before an operator that side-effects its l-value. For example: if (x == 42) x= 666; while (ptr >= base) processWord(ptr-= 4); (In my three years of writing C before adopting this convention I spent many tens of hours tracking down `=' vs. `==' bugs. In the fifteen years since the instant that I adopted the above convention I have suffered from that bug precisely ONCE.) For similar reasons it's also a good idea to place constant values on the left side of a comparison. Most compilers will happily let this this pass: int c= getchar(); if (c= EOF) ... but will detect the problem if the comparison is written the other way round: int c= getchar(); if (EOF= c) ... Character constants are characters: void terminate(char *string, size_t len) { string[len]= '\0'; /* NOT `string[len]= 0;' !!! */ } Always initialise a variable, even if you're just about to give it a value: int min= 0; if (x < y) min= x; else min= y; ... Just about every compiler in existence can optimise away the assignment. On the hand, always assigning an initial value avoids warning messages about possibly uninitialised variables from several compilers when their optimisation dials are `cranked up to 11'. Vertically align related elements in dense program sections, such as a long series of assignments or declarations: int a= 42; /* current data value */ int counter= 0; /* how many we've counted */ int moreToDo= 1; /* 1 if we've got more to count */ This applies to the _identifiers_ when indirection is present: int a= 42; /* current data value */ int *current= 0; /* current data location */ int **dataLists= 0; /* current data list */ Don't be tempted to write `C++ style' types. Respect also the proper placement of whitespace in casts, which should have spaces in exactly the same places as would the equivalent declaration. Hence: /* ptr to (ptr to int) fn of ptr to ptr to int */ typedef int *(*ppifpi)(int **); ppifpi myPpifpi= 0; int ioSetPpifpi(int sqFunctionIndex) { myPpifpi= (int *(*)(int **))sqFunctionIndex; } (Outside Squeak code too, I guarantee that you'll come up against many more brick walls trying to use the `C++ style' "int* foo" [ugh -- it _isn't_ the `int' that's the pointer in there!!] and suchlike than you will if you stick to the old-fashioned, and _rational_, C syntax.) Put a space between a keyword and a parenthesised argument. Put spaces after commas. Don't put a space between a function name and the argument list, and never put a space after an opening parenthesis or before a closing parenthesis: if (x < foo(y, z)) haha= bar[4] + 5; else { while (z) { haha+= foo(z, z); --z; } return ++x + bar(); } When you split an expression into multiple lines, split it BEFORE an operator, not after one. Here is the right way: if (fooThisIsLong && bar > win(x, y, z) && remaining_condition) ... Avoid having two operators of different precedence at the same level of indentation. For example, don't write this: mode= (inmode[j] == VOIDmode || GET_MODE_SIZE(outmode[j]) > GET_MODE_SIZE(inmode[j]) ? outmode[j] : inmode[j]); Instead, use extra parentheses so that the indentation shows the logical nesting: mode= ((inmode[j] == VOIDmode || (GET_MODE_SIZE(outmode[j]) > GET_MODE_SIZE(inmode[j]))) ? outmode[j] : inmode[j]); Insert extra parentheses so that Emacs will indent the code properly. For example, the following indentation looks nice if you do it by hand, but Emacs would mess it up: v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000; But adding a set of parentheses solves the problem: v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000); With very few exceptions, braces should always go on a line by themselves. Instead of this: if (x < y) { z= x; } else { z= y; } write this: if (x < y) { z= x; } else { z= y; } Never, ever, put an `else' and a brace on the same line. Format do-while statements like this: do { a= foo(a); } while (a > 0); Empty `while' and `for' loops should have their trailing semicolon on a line by itself, to make the absence of the body utterly obvious: for (i= 1; i < argc; processArg(i++)) ; while ('\0' != (*dst++= *src++)) ; Introduce redundant braces to restrict the scope of temporaries to the smallest possible region. This is WRONG: void foo(void) { int i; /* ... lots of code ... */ for (i= 0; i < LIMIT; ++i) { ... } /* ... lots of code ... */ for (i= 0; i < LIMIT; ++i) { ... } } while this is right: void foo(void) { /* ... lots of code ... */ { int i= 0; for (i= 0; i < LIMIT; ++i) { ... } } /* ... lots of code ... */ { int i= 0; for (i= 0; i < LIMIT; ++i) { ... } } } The above is not just to help small-brained coders (like me) remember to delete variables when the code that uses them is removed. It's preferable because some compilers are hopelessly bad at live-range splitting. Reducing the scope of variables to the absolute minimum encourages them to produce _much_ better code. (You'll also be far less tempted to use the value of an iteration variable after the end of the loop, which is unforgivably bad programming style.) Just like a good composer, a good programmer knows that rarefied zones are the most effective media in which to produce contrast. Leave lots of vertical whitespace between logically independent program sections, with a minimum of comment `decoration' to make them stand out. For example: 1 line of whitespace within function bodies to separate variable declarations from statements 1 line of whitespace between groups of external declarations. 2 lines of whitespace between function definitions. Begin a new "logical section" of the code with three blank lines, a comment explaining what the section is all about, and then three more blank lines before the section itself. and so on. Just use common sense. In particular, when there are many lines of declarations/definitions in a given section, the following is much kinder on the reader: ... /*** variable declarations ***/ /* counters */ int a= 0; int b= 0; /* pointers */ void *start= 0; /* initial address */ void *position= 0; /* current address, post-incremented */ void *end= 0; /* last address + 1 */ /*** function definitions ***/ /* accessors */ int getA(void) { return a; } /* predicates */ bool atEnd(void) { return position == end; } ... (and more effective) than the `noisy' equivalent: ... /*****************************/ /*****************************/ /*** ***/ /*** variable declarations ***/ /*** ***/ /*****************************/ /*****************************/ /****************/ /*** counters ***/ /****************/ int a= 0; int b= 0; /****************************/ /****************************/ /*** ***/ /*** function definitions ***/ /*** ***/ /****************************/ /****************************/ /*****************/ /*** accessors ***/ /*****************/ int getA(void) { return a; } /******************/ /*** predicates ***/ /******************/ bool atEnd(void) { return position == end; } ... where the details are hopelessly lost in the noisy comments, which serve only to make the program HARDER to read. (Besides, it looks just plain ugly. Typographers have known for centuries about the importance of maintaining a consistent `density' in the characters that make up an aesthetically-pleasing and easy to read font. The same applies to programs. Avoid large horizontal blobs of asterisks and other `dense' material intended to make things stand out -- they simply distract the reader's attention away from the essential. Use whitespace instead!) One final comment: remember that a crystal clear program is a MUCH more impressive achievement in the eyes of the vast majority of readers compared to a program designed to show off the author's cleverness in using obscure and obfuscating `C-isms' and cramming the maximum possible amount of functionality in the minimum number of source lines. Also, the time you spend making your program visually pleasing (and consistent) will be paid back many times over when you eventually have to go bug hunting. PORTABILITY ----------- Stick to ANSI Standard C in source code. Resist the temptation to introduce GNU-specific extensions, even if you think your code is only ever going to run in a GNU environment. If you use gcc then be sure your code compiles without warnings when `-Wall' is in effect (which is the case for all source files in the "unix" source directory). Ideally, your code should compile without warnings when "-pedantic" is turned on too, but I'm not insisting on this -- yet. ABSOLUTELY avoid GNU make-specific stuff in Makefiles. If your wizz-bang Squeak feature requires a GNU make-specific rule or conditional section in a Makefile someplace then go away and rethink your feature. (If the entire GNU compiler suite can be built using the tiniest imaginable subset of Makefile features, then so can Squeak.) Another way to avoid GNU make features in Makefiles is to run a script from `configure' to make a `fragment' and then AC_SUBST_FILE() it into the Makefile.in. If you do this then please, please make sure that the script is *strict* Bourne shell. (If you're on a system that has bash as its standard shell then you must ABSOLUTELY install ash [or something similar] and exercise every path through the script with the first line set to "#!/bin/ash", before changing it to "#!/bin/sh".) If you normally develop on a GNU-based Linux system (or any similarly well-documented system) then check the "CONFORMING TO" or "STANDARDS" section of the manual page for every library function and system call that you use. Avoid functions that don't conform to ANSI or POSIX, and pay particular attention to functions that are missing in either BSD or SysV. (These should be used with extreme caution, and only if the necessary conditional stuff [with a suitable fallback] is present.) ================================================ FILE: vm/src/from_squeak/unix/doc/README.Keyboard ================================================ By default the newer VMs implement the "traditional" Unix VM behaviour: Squeak X11 ------ --- shift Shift ^ Lock ctrl Control command Mod1 option Mod1 & Control For keyboards that have more than one modifier key (Apple, Sun, etc.) a more Macintosh Squeak-like behaviour is possible by specifying which modifier keys should map to Option and Command, either on the command line or by setting the corresponding environment variables: Key X11 modifier VM option Environment --- ----------- --------- ----------- Option mod -optmod n export SQUEAK_OPTMOD=n Command mod -cmdmod n export SQUEAK_CMDMOD=n Examples: Apple keyboard, GNU/Linux, XFree86 4.0: -cmdmod 1 -optmod 2 Apple keyboard, NetBSD, XFree86 4.2: -cmdmod 2 -optmod 1 (these map "Option" to Option [duh] and "Apple" to Command) Sun keyboard, Solaris: -cmdmod 4 -optmod 1 (this maps "Alt" to Option and "<>" [Meta] to Command) If you don't know which modifiers are bound to which keys, then: executing `xmodmap -pm' will print the keycodes and keysyms associated with each modifier; running`xev' and hitting modifier keys will generate KeyRelease events in which the "state" field has bit N+2 set to 1 for mod (bit 0 is the least significant); i.e: state=0x8 corresponds to mod1 (N = 1, N+2 = 3, 1<<3 = 8), state=0x40 is mod4, and state=0x48 means both mod1 and mod4 are active simultaneously. With a properly mapped Command key the pointer buttons and keyboard shortcuts should work as follows (Option is generally ignored by the image and is not considered below): Pointer mappings: Button1 (red) -> select (world menu on background) Button2 (yellow) -> window menu (personal menu on background) Button3 (blue) -> morph halos Button1 + Shift -> extend selection (find window menu on background) Button2 + Shift -> window "more" menu (find window on background) Button3 + Shift -> morph halos Button1 + Ctrl -> window menu (personal menu on b/g) = acts like Button2 Button2 + Ctrl -> morph menu Button3 + Ctrl -> morph menu Button1 + Command -> morph halos = acts like Button3 Button2 + Command -> window menu (personal menu on b/g) Button3 + Command -> morph halos Button1 + Shift + Ctrl -> (topmost) morph menu Button2 + Shift + Ctrl -> (topmost) morph menu Button3 + Shift + Ctrl -> (bottommost) morph menu Button1 + Shift + Command -> extend selection (find window on b/g) Button2 + Shift + Command -> window "more" menu (find window on b/g) Button3 + Shift + Command -> morph halos Button1 + Ctrl + Command -> morph menu Button2 + Ctrl + Command -> morph menu Button3 + Ctrl + Command -> morph menu Button1 + Shift + Ctrl + Command -> (topmost) morph menu Button2 + Shift + Ctrl + Command -> (topmost) morph menu Button3 + Shift + Ctrl + Command -> (topmost) morph menu Keyboard mappings (with reference to "World Menu -> help... -> command-key help"): key -> lowercase key key + Shift -> uppercase key key + Ctrl -> uppercase command key key + Command -> lowercase command key key + Shift + Ctrl -> uppercase command key key + Shift + Command -> uppercase command key key + Ctrl + Command -> uppercase command key key + Shift + Ctrl + Command -> uppercase command key (kilometrage with the others [delimiters, styles, kerning, etc.] will vary according to whether particular symbols are shifted or unshifted on a given keyboard.) ================================================ FILE: vm/src/from_squeak/unix/doc/README.Sound ================================================ 0. Contents -------- 1. VM options relating to sound 2. Configuring sound support in Squeak 3. Sound system-specific notes 3.1. Open Sound System 3.1.1 Possible Problems with OSS 3.2. Network Audio System 3.3. SunOS/Solaris 4. The future of Squeak sound on Unix 1. VM options relating to sound ---------------------------- Squeak includes primitives to modify the recording and playback levels. These primitives are sometimes invoked automatically on your behalf by "helpful" code in the image. (E.g., the recording level is set to 50% whenever the SoundRecorder is started.) Many people (including myself) find this to be totally unnacceptable behaviour; mixer settings are the responsibility of an (external) mixer program and Squeak has no business whatsoever fiddling with them. If the VM is started with the option `-nomixer' (or if the variable SQUEAK_NOMIXER is set in the environment) then the primitives which write mixer levels are disabled. (The image will think they succeed but in fact they do nothing at all.) 2. Configuring sound support in Squeak ----------------------------------- The `configure' script should figure out which sound support to use (if any) all by itself. It looks for sound support in this order: Open Sound System (or Linux native sound) SunOS/Solaris Network Audio System and chooses the first one it finds. If it doesn't find any of the above then the VM will still compile but sound support will be disabled. If you have more than one kind of sound support on your system (Sparc systems might have all three installed) then you can specify which one to use explicitly, like this: .../configure --with-audio=oss or .../configure --with-audio=sun or .../configure --with-audio=nas or .../configure --with-audio=none The default (not shown in the above list) is `auto' which means: "use the first of the above sound systems that appears to be available". Specifying `none' turns off sound support in the VM even if it is available. If you explicitly choose the desired sound support this way but `configure' cannot find the necessary header files then sound support will be disabled totally (i.e., `configure' isn't about to hassle itself with hunting for alternatives when the particular support you asked for is unavailable). 3. Sound system-specific notes --------------------------- Below are some notes on the different sound systems supported in Unix Squeak. 3.1. Open Sound System Full support for playback and recording is implemented and should work perfectly. Full-duplex (simultaneous recording and playback) should work on devices that support it. (You'll need to change `canRecordWhilePlaying' in the image preferences, and then fix all the bugs in the SoundPlayer and SoundRecorder which effectively prevent the latter from ever starting up when the former is active.) Note that OSS is available in three flavours: 1. Linux native sound drivers (bundled with the kernel). Many of these are hopelessly broken. I've had bad experiences on both PowerMac (awacs chip) and stock PC hardware (using the NM256 codec and AC97 mixer chips). Whether the OSS support works for you largely depends on how well your particular sound drivers are implemented. 2. Commercial version (http://www.opensound.com). I've no idea how well these work. (I refuse to pay for software of any kind.) Experience reports (either good or bad) would be appreciated. 3. The snd-pcm-oss compatibility module in the ALSA (Advanced Linux Sound Architecture) drivers (http://www.alsa-project.org). Squeak sound works flawlessly with this driver. (This isn't surprising: after 10 days of total failure to make the Linux native OSS support work I installed ALSA and finished the work using snd-pcm-oss.) If you experience any problems at all with either the Linux native sound or commercial OSS then you are strongly encouraged to switch to ALSA instead. You might also consider turning on `soundStopWhenDone' in the image preferences since this will make Squeak much friendlier towards any other sound applications or daemons that might want to make noises from time to time and which would otherwise find /dev/dsp to be unavailable after Squeak has played its first sound. 3.1.1 Possible Problems with OSS Ned Konz discovered that it's sometimes necessary to tell Linux (using ALSA and OSS compatibility modules) that Squeak wants to open the sound device in non-blocking mode. If sound output in Squeak seems to be playing things ``on top of themselves'' then you might want to try the following (or something similar) as root to see if it cures the problem: # echo "squeak 0 0 block" > /proc/asound/card0/pcm0p/oss 3.2. Network Audio System Support for playback and recording is implemented. Playback should work perfectly but I've had some problems making recording work. (I've had trouvle with the NAS utility `aurecord' too, so the fault is not necessarily with Squeak.) The latest source for the NAS daemon and utilites can be found at: http://www.radscan.com/nas.html. (You'll have to compile it for yourself.) Note that NAS is broken on big-endian Linux machines. I've patched the daemon to fix this. If you want the patches, send me email (mailto:ian.piumarta@squeakland.org). 3.3. SunOS/Solaris The support hasn't been tested in ages. I haven't a clue if it still works. 4. The future of Squeak sound on Unix ---------------------------------- Direct support for the ALSA drivers is on the TO-DO list. Plans are afoot to add "modules" to the Unix VM. This will make many configure-time options (such as sound support, window support, etc.) irrelevant. Instead `configure' will figure out what's available, compile support for everything into separate modules, and then leave you to pick which one(s) you want to use at run time. The remainder of this file isn't for reading. It's here in case you have problems with OSS support. Turn on `#define DEBUG' near the top of `sqUnixSoundOSS.c' and recompile. In the "more about music" project you can record and then playback a sound and the OSS code will tell you what it's doing, which should be something like the following. [piumarta@emilia current]$ date Mon May 27 20:34:52 CEST 2002 [piumarta@emilia current]$ bld/squeak Squeak3.1c-4478 sound: stop sound: start recording sound: /dev/dsp: opened with mode 0 sound: /dev/dsp: driver formats (1f9): MU_LAW U8 S16_LE S16_BE S8 U16_LE U16_BE sound: /dev/dsp: driver capabilities (3201): REALTIME TRIGGER MMAP sound: /dev/dsp: trying format 20: S16_BE sound: /dev/dsp: selected driver format 20: S16_BE sound: /dev/dsp: requesting 1 channels sound: /dev/dsp: using 1 channels sound: /dev/dsp: driver: 2 bytes/frame sound: /dev/dsp: squeak: 2 bytes/frame sound: /dev/dsp: 11025 samples/sec sound: /dev/dsp: fragment size set to 2048 (1102 frames requested in 1 channels) sound: input conversion: none (0x10016af4) sound: output conversion: none (0x10015cb0) sound: /dev/dsp: aio enabled, semaphore 2 sound: /dev/mixer: opened with mode 2 sound: /dev/mixer: available devices: vol speaker line mic cd igain sound: /dev/mixer: rec: device not available sound: /dev/mixer: igain: level set to 50% + 50% sound: stop recording sound: /dev/dsp: aio disabled sound: /dev/dsp: device closed sound: stop recording sound: stop recording sound: stop sound: start sound: /dev/dsp1: No such file or directory sound: /dev/dsp: opened with mode 1 sound: /dev/dsp: driver formats (1f9): MU_LAW U8 S16_LE S16_BE S8 U16_LE U16_BE sound: /dev/dsp: driver capabilities (3201): REALTIME TRIGGER MMAP sound: /dev/dsp: trying format 20: S16_BE sound: /dev/dsp: selected driver format 20: S16_BE sound: /dev/dsp: requesting 2 channels sound: /dev/dsp: using 2 channels sound: /dev/dsp: driver: 4 bytes/frame sound: /dev/dsp: squeak: 4 bytes/frame sound: /dev/dsp: 22050 samples/sec sound: /dev/dsp: fragment size set to 8192 (2644 frames requested in 2 channels) sound: input conversion: none (0x10016af4) sound: output conversion: none (0x10015cb0) sound: /dev/dsp: aio enabled, semaphore 2 sound: stop sound: /dev/dsp: aio disabled sound: /dev/dsp: device closed sound: stop [piumarta@emilia current]$ ================================================ FILE: vm/src/from_squeak/unix/doc/RELEASE_NOTES_3.11.3.2135 ================================================ Changes since 3.10-6: Numbering scheme changed to X.Y.Z.R where X.Y.Z = VMMaker version used to generate the Interpreter and R is the subversion revision of the platform support code. VMMaker and plugins updated to most recent versions; generated source regenerated: Balloon3D-Plugins-ar.4.mcz DBus-Plugin-bf.32.mcz GStreamer-Plugins-JMM.16.mcz Kedama-Plugins-yo.1.mcz Rome-Plugin-yo.39.mcz OSProcessPlugin-dtl.16.mcz VMConstruction-Plugins-AioPlugin-dtl.9.mcz VMConstruction-Plugins-XDisplayControlPlugin-dtl.7.mcz VMMaker-dtl.138.mcz Build system rewritten using CMake instead of autotools. Big THANK-YOU to Bert, Subbu and Dave Lewis for providing invaluable feedback. Any plugin can now be turned off in configure with the option '--without-'. Experimental PulseAudio driver (vm-sound-pulse) added, thanks to Derek O'Connell. Default is still OSS on Linux; if you want pulse you have to ask for it in one of the usual ways. FFI tweaked on Linux to avoid a potential FPU stack overflow. ClipboardExtendedPlugin will no longer try to build if you don't have X11 development headers and libs. FileCopyPlugin made resilient to EINTR. VM renamed to 'squeakvm'. 'squeak' is now a script that looks for 'squeakvm', figures out if you need any obscure command-line options, and then launches 'squeakvm' for you. This in turn allows... Plugin search stretegy rationalised and simplified. Default location is now the executable directory (where 'squeakvm' is installed). The -plugins argument can be a colon-separated list of locations to search, just like PATH. Plugins are named 'so.plugin' to make interference with FFI libraries less likely. NOTE: FFI libraries are no longer searched for in every single nook and cranny, which means you might have to set LD_LIBRARY_PATH (or your local equivalent) for FFI-based programs to work properly. Failure to load a plugin because of unresolved symbols is now always reported on the terminal. Another script 'squeak.sh' is provided for launching squeak from a menu. This isn't finished and suggestions are welcome. Default path and text encoding is now UTF-8. X11 driver no longer reports SHIFT pressed when CAPS LOCK engaged. SerialPlugin now supports named ports. All occurences of dprintf() renamed to avoid a name conflict with a less-than-stellar decision by POSIX to introduce a standard function of the same name. RomePlugin is no longer built if cairo was built without Pango support. iconv_open() no longer spams you with thousands of error messages if you are missing conversion tables. Valid unicode characters that have no corresponding keycode are reported with keycode zero to avoid an invalid index error in the image. XImmPlugin should now work on MacOS X/Darwin too. Sound driver on MacOS X now works on Intel as well as PowerPC. Various changes to make the VM compile and run on GNU/Linux running on DEC Alpha. vm-sound-Sun now uses asynchronous i/o. Various changes to fix compilation on Solaris. ================================================ FILE: vm/src/from_squeak/unix/doc/RELEASE_NOTES_4.0.3.2196 ================================================ Changes since 3.11.3.2135: Generated sources rebuilt from VMMaker-dtl.169. Re-enabled MIDI support via ALSA on Linux. Broken locales should no longer cause line ends to go missing during copy and paste. Add support for "platform source version" primitive. Remove debugging beep on first clipboard copy under X11. Allow fully-qualified pathnames when loading modules. Bundle FreetypePlugin with source and binary releases. Various fixes for 64-bit cleanliness (many thanks to Dave Lewis). Add microsecond clock support. Fix launching from a menu under KDE. Fix --CFLAGS option in configure script. Serial plugin invalidates cached port names on close. Better handling of symlinks when looking for absolute path to VM binary. ================================================ FILE: vm/src/from_squeak/unix/doc/RELEASE_NOTES_4.0.3.2202 ================================================ Changes since 4.0.3.2196: Changes to pulseaudio driver from Derek O'Connell, as used in Scratch. (Fixes bad behaviour on Karmic.) UUIDPlugin is now internal. Top-level Makefile in source archive uses cmake/configure and no longer fails because of bogus dependency bld/squeakvm. ================================================ FILE: vm/src/from_squeak/unix/doc/squeak.1 ================================================ .\" squeak.1 -- manual page for Unix Squeak -*- nroff -*- .\" .\" Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors .\" listed elsewhere in this file. .\" All rights reserved. .\" .\" This file is part of Unix Squeak. .\" .\" You are NOT ALLOWED to distribute modified versions of this file .\" under its original name. If you modify this file then you MUST .\" rename it before making your modifications available publicly. .\" .\" This file is distributed in the hope that it will be useful, but WITHOUT .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or .\" FITNESS FOR A PARTICULAR PURPOSE. .\" .\" You may use and/or distribute this file ONLY as part of Squeak, under .\" the terms of the Squeak License as described in `LICENSE' in the base of .\" this distribution, subject to the following additional restrictions: .\" .\" 1. The origin of this software must not be misrepresented; you must not .\" claim that you wrote the original software. If you use this software .\" in a product, an acknowledgment to the original author(s) (and any .\" other contributors mentioned herein) in the product documentation .\" would be appreciated but is not required. .\" .\" 2. You must not distribute (or make publicly available by any .\" means) a modified copy of this file unless you first rename it. .\" .\" 3. This notice must not be removed or altered in any source distribution. .\" .\" Using (or modifying this file for use) in any context other than Squeak .\" changes these copyright conditions. Read the file `COPYING' in the .\" directory `platforms/unix/doc' before proceeding with any such use. .\" .\" Last edited: 2005-03-16 21:52:26 by piumarta on squeak.hpl.hp.com .\" .if @@\*(lq@ \{\ . ds lq " . if t .ds lq `` . if !@@\(lq@ .ds lq "\(lq .\} .if @@\*(rq@ \{\ . ds rq " . if t .ds rq '' . if !@@\(rq@ .ds rq "\(rq .\} .de Id .ds Rv \\$3 .ds Dt \\$4 .. .de Sp .if n .sp .if t .sp 0.4 .. .TH SQUEAK 1 "\*(Dt" "Squeak Smalltalk System" "Squeak Smalltalk System" .SH NAME squeak, inisqueak \- Unix Squeak virtual machine and installer .SH SYNOPSIS .B inisqueak .br .B squeak .RI "[ " option ".\|.\|. ] [ " image " ] [ " script " [ " argument ".\|.\|. ] ]" .SH DESCRIPTION .B squeak is the virtual machine for the Squeak Smalltalk system. It requires three files to operate correctly: an .B image file containing a `snapshot' of a live Squeak session, a .B changes file containing the source code for modified methods in the image, and a copy of (or a link to) a shared system .B sources file containing the source code for methods that have not been modified since the last major version increment. .PP The image and changes files contain the state of a user's Squeak session, which is persistent between consecutive sessions. Private copies of these files are therefore normally required. The .B inisqueak script checks that the local Squeak installation appears sane, and then copies the required files to the current working directory. If .B inisqueak encounters no problems, it will finish by running .B squeak to start a Squeak session using the newly copied image and changes files. .PP .B inisqueak should be run .I once\c \&, when using Squeak for the first time, to create a new 'personal' Squeak session. Afterwards, .B squeak should be run each time that session is to be resumed. .PP .SH INVOCATION .B inisqueak has no options or arguments. Simply 'cd' to the directory that is to contain the working copies of the image and changes files, then run it. .PP .B squeak accepts various .I options (described below), and then an optional .I image name (which must not begin with a minus sign '\-'). If an .I image name is given on the command line then .B squeak tries to run that image. Otherwise .B squeak checks the environment variable .B SQUEAK_IMAGE and, if it is set, uses its value as the name of the image to run. Otherwise .B squeak looks for an image called 'squeak.image' in the current directory. If the image file does not exist then .B squeak prints a message indicating which image file it failed to find and then exits. If the extension '.image' is missing in the .I image argument or in the value of the .B SQUEAK_IMAGE variable, it will be appended automatically. .PP The .I image argument can be followed by a .I script name. This is the name of a 'document' that should contain Smalltalk code to be executed on startup. The document can be either the name of a file or a URL starting with 'http:'. Any .I argument\c s that appear after the .I script name are ignored, but are made available to the .I script from within Squeak via the method .B getSystemAttribute:\c \&. (See the section .B SCRIPTS below.) .PP If .I image is given as '--' then .B squeak immediately stops argument processing (and behaves as if .I image was not specified). This is useful to specify a .I script (possibly with script arguments) without specifying an explicit .I image\c \&. .SH OPTIONS Command line options fall into two categories: 'common' options that are recognised by the base VM and 'specific' options that are tied to a particular display or sound driver. Common options will always be recognised by .B squeak\c , whereas a given specific option will be recognised only after .B squeak has loaded the driver to which it relates. Refer to the '-vm' option below for more details. .PP The common options recognised by .B squeak are as follows: .TP .BI "\-encoding " "enc" specifies the internal character encoding to be used by Squeak. This affects the translation that the VM performs when importing text (from the keyboard or via 'paste' from an external selection) or exporting text (pasting text from Squeak to another application, or when generating filenames containing special characters). In other words, it affects the correspondence between what Squeak displays on the screen and what it sends to (or receives from) external applications. The correct value depends on the way Squeak's internal fonts are encoded. Current images are delivered with traditional Macintosh \&'New York' fonts that use .B Mac Roman encoding, and so this is the default internal encoding. If other fonts (from X11 or elsewhere) are imported into the image and used as system fonts then the this default translation will give incorrect results for diacritical marks and special characters. In such cases the .B \-encoding option can be used to change the internal encoding, for example .sp .nf \ \ \ \ \-encoding ISO-8859-15 .fi .sp (aka .B Latin9\c ) which would be appropriate for many of the fonts designed for European languages. .TP .B \-help prints a short summary of the command-line syntax, options and available drivers, then exits. .TP .BI "-memory " "size"[mk] requests that a fixed heap of .I size bytes be allocated for the Squeak image. If the suffix `\c .B k\c \&' is given then the argument is expressed in kilobytes. If the suffux `\c .B m\c \&' is given then the argument is expressed in megabytes. This option SHOULD NOT be used, unless there is a good reason to do so, since it places an arbitrary limit on Squeak's object memory size. .TP .BI "-mmap " "size"[mk] requests that a variable heap of at most .I size bytes be allocated. (The suffixes are as described for the \&'\-memory' option.) .B squeak will initially allocate a heap that is large enough to hold the image, with a small amount of headroom. If at any time Squeak requires more memory for its image then additional space will be allocated dynamically. Likewise, when memory is no longer needed it will deallocated and returned to the system. The .I size argument places an upper limit on how big the heap can grow in this fashion. .B squeak uses a dynamic heap by default with the maximum size set to 75% of the available virtual memory or 1 gigabyte, whichever is smaller. .TP .B \-noevents disables the new (image 2.8 and later) event-driven input mechanism. This option is only useful for testing backwards compatibility with older images and should not be used. .TP .B \-notimer disables the use of the interval timer for keeping track of low-resolution time. (If you are having problems with file, sound or socket i/o reporting `interrupted system call' then setting this flag might help.) .TP .BI "\-pathenc " "enc" specifies the external character encoding to be used by Squeak when accessing the filesystem (file and directory pathnames). The correct value depends on the local platform's characteristics. If no encoding conversion should be performed then this should be set to the same encoding as Squeak uses internally (see the .I \-encoding option). Otherwise .B ISO-8859-15 (aka .B Latin9\c ) might make sense on a filesystem supporting 8\-bit characters, and .B UTF-8 for filesystems that use Unicode-based pathnames. The default is .B UTF-8 which is correct for Mac OS X and very recent GNU/Linux distributions, and which (in an ideal world) will eventually be adopted by all Unix variants. .TP .BI "-plugins " "path" specifies an alternative location for external plugins (collections of named primitives) and drivers (for display and sound). The .I path argument contains a pattern in which any occurrences of `\c .B %n\c \&' will be replaced by the name of the plugin or driver being loaded. The .I path can name either a directory or the plugin itself and can be absolute or relative (to the directory in which .B squeak was run). If a plugin or driver cannot be found in the location specified by .I path then the search continues in the default locations. .TP .BI "\-textenc " "enc" specifies the external character encoding to be used by Squeak when exchanging clipboard text with other applications. The default is .B UTF-8 on Mac OS X and .B ISO-8859-15 (aka .B Latin9\c ) on other Unix systems. Note that X11 applications requesting the selection converted to .B UTF8_STRING data will (correctly) receive the clipboard text encoded as .B UTF-8\c , regardless of this setting. .sp Squeak recognises a subset of the encoding names defined by the IANA. (If you prefer to use the international currency symbol rather than the Euro symbol in external text then you might want to set this to .B ISO-8859-1\c , aka .B Latin1\c \&.) .TP .B \-version prints three or more lines of version information, as follows: .RS .TP \ \ \ \(bu the architecture configured for the virtual machine at compile time, the compilation `sequence number', the time and date of compilation, and the name (and version, if known) of the compiler that was used to compile .B squeak\c ; .TP \ \ \ \(bu the complete .BR uname (1) information for the host on which the virtual machine was compiled; .TP \ \ \ \(bu the default installed location for plugins and drivers; .PP After printing the above, the virtual machine exits. .RE .TP .BI "\-vm " "driver" asks .B squeak to load a sound/display driver. For each supported device there is a corresponding driver that .B squeak loads during initialisation. Unless told otherwise, .B squeak will figure out sensible default drivers to load. This choice can be overridden using this option. The .I driver argument is a list of one or more 'assignments' of the form .sp \ \ \ \ .I class\c =\c .I device .sp separated by spaces or commas. The supported combinations are currently: .RS .TP .B \ \ \ display=X11 to display the Squeak window on a local or remote X Window System server. .TP .B \ \ \ display=Quartz to display on the local Mac OS X desktop. .TP .B \ \ \ display=none to disable the display (and keyboard/mouse) entirely. (This driver is useful primarily for running 'server' applications in Squeak.) .TP .B \ \ \ sound=OSS provides sound input and output via the Open Sound System. (If you have a device called '/dev/dsp' then this is likely the one you want.) .TP .B \ \ \ sound=MacOSX provides sound input/output via Core Audio on Mac OS X. .TP .B \ \ \ sound=NAS provides sound i/o via the Network Audio System. .TP .B \ \ \ sound=Sun provides sound on Sun Microsystems hardware. .TP .B \ \ \ sound=none disables sound entirely. .B squeak will not attempt to play or record sounds when this driver is loaded. .RE .PP .RS Note that only those drivers relevant to the local platform will be available. Attempting to load an unsupported driver will cause .B squeak to exit with an error message. A list of available drivers is printed by the '-help' option. If a particular driver cannot load system libraries on which it depends then it will neither be listed nor be available to load at runtime. .RE .PP .RS Note also that on Mac OS X both the X11 and Quartz display drivers are supported, although the former will refuse to load if the X11 client libraries are not installed on the local machine. The Quartz driver will happily load (and Squeak will run as a fully-fledged application) even when .B squeak is invoked from the command line. Exercise caution when logged into Mac OS X from another machine: forgetting to set DISPLAY before trying to run .B squeak on the remote display could cause embarrassement. .RE .PP Options specific to the X11 display driver are as follows: .TP .BI "\-browserWindow " "id" specifies the .I id of the window that .B squeak should use for its display. This option is intended for use when Squeak is running as a web browser plugin. .TP .BI "\-display " "server" specifies that Squeak should connect to the given display .I server instead of looking in the environment variable .B DISPLAY (the default behaviour) to find the name of the server to use. .TP .B \-fullscreen causes the Squeak window to occupy as much of the screen area as possible. Implies '\c .B \-notitle\c \&'. .TP .B \-headless disables the graphical display and mouse/keyboard input. This mode of operation is useful primarily for servers. .TP .B \-iconic asks the window manager to iconify the Squeak window at startup. .TP .B \-lazy causes Squeak to `snooze' whenever the main winodw is unmapped. This can be used if Squeak appears to be using consuming CPU time while idling (which should not normally be the case). Note that if this option is in effect, when the Squeak window is unmapped .B squeak will not respond to any external stimuli (other than to provide the X selection to requestors, when Squeak is the owner). .TP .B \-mapdelbs maps the Delete key onto Backspace. Backspace deletes the character to the left of the cursor and Delete normally deletes the character to the right of the cursor. With this option, Deletes will behave like Backspace. The behaviour of Backspace is not changed. .TP .B \-nointl disables the handling of dead keys on international keyboards. Without this option, dead key handling is enabled if either .B LC_ALL or .B LC_CTYPE is set in the environment. .TP .B \-notitle disables the title bar on the Squeak window (if the window manager supports it). This option is implied by '\c .B \-fullscreen\c \&'. .TP .B \-swapbtn swaps the yellow and blue buttons. (Traditionally, the red button is on the left, yellow in the middle and blue on the right. The colourful names come from the Xerox Alto on which Smalltalk was first implemented.) Squeak normally maps X buttons 1, 2 and 3 to the .B red\c , .B yellow and .B blue buttons, in that order. With this option, it maps X buttons 1, 2 and 3 to the .B red\c , .B blue and .B yellow buttons.) .TP .B \-xasync causes Squeak to use asynchronous display updates. The virtual machine normally flushes and synchronises the display connection at regular intervals. Using this option disables synchronisation, which will be performed only when the image explicitly requests it. .TP .B \-xshm enables the use of the X Shared Memory extension on servers that support it. This can dramatically improve display performance, but works only when Squeak is running on the server. .PP Options specific to the FBDev display driver are as follows: .TP .BI "\-fbdev " "device" Use the given framebuffer .I device instead of the default '/dev/fb0'. .TP .BI "\-kbmap " "mapfile" Load the keyboard map from the given .I mapfile instead of reading it from the running kernel. Note that .B squeak cannot (currently) read compressed or 'shorthand' map files (as found in /usr/share/keymaps or /lib/kbd/keymaps). To generate a keymap file usable by .B squeak\c \&, execute the following program from the console: .sp \ \ \ \ dumpkeys -f -n --keys-only > key.map .sp If .B squeak encounters a problem while trying to load .I mapfile\c \&, it will print an error message and exit. See .BR keymaps (5) for more information about the keymap file format. The programs .BR dumpkeys (1)\c , .BR loadkeys (1)\c , and .BR showkey (1) can be used to modify the keyboard map before creating a keymap file for .B squeak\c \&. .TP .BI "\-msdev " "device" Use the given mouse .I device instead of the default. The default is to try \&'/dev/psaux', '/dev/input/mice' and '/dev/adbmouse', in that order, and to use the first one that has a physical device attached. .TP .BI "\-msproto " "protocol" Use the given mouse .I protocol instead of the default. The supported protocols are 'ps2' and 'adb'. The default is 'ps2' for mice attached to '/dev/psaux' or '/dev/input/mice', and 'adb' for mice attached to '/dev/adbmouse'. .TP .B \-vtlock Disallows VT switching, regardless of whether the request comes from the keyboard or from another program such as .BR chvt (1)\c \&. .TP .B \-vtswitch Enables keyboard VT switching. Note that this option is effectively disabled if the '\c .B \-vtlock\c \&' option is also enabled. .PP Options specific to the OSS and MacOSX sound drivers are as follows: .TP .B \-nomixer disables the primitives that change mixer (sound) settings. If you prefer that Squeak leave these alone (they are, after all, really the reponsibility of whichever mixer program or sound control panel you use) then this option is for you. .PP Several common options are deprecated and are provided only for backward compatibility. These options should not be used and will be removed in a future release: .TP .BI "\-display " "dpy" is equivalent to '\-vm display=X11 \-display .I dpy\c \&'. .TP .B \-headless is equivalent to '\-vm display=X11 \-headless'. .TP .B \-nodisplay is equivalent to '\-vm display=none'. .TP .B \-nosound is equivalent to '\-vm sound=none'. .TP .B \-quartz is equivalent to '-vm display=Quartz'. .SH ENVIRONMENT Many of the options that can be set on the command line can also be set from environment variables. .TP .B SQUEAK_ASYNC if set in the environment then equivalent to the '\c .B \-xasync\c \&' flag. (The value is ignored.) .TP .B SQUEAK_ENCODING the name of the internal character encoding used by Squeak. Equivalent to giving the '\c .B \-encoding\c \&' command-line option if set. .TP .B SQUEAK_FBDEV the name of the framebuffer device to use when running on the console. See the '\c .B \-fbdev\c \&' option. .TP .B SQUEAK_FULLSCREEN equivalent to '\c .B \-fullscreen\c \&' if set. .TP .B SQUEAK_ICONIC equivalent to the '\c .B \-iconic\c \&' flag. .TP .B SQUEAK_IMAGE the name of the image file to execute if no .I image argument is given on the command line. .TP .B SQUEAK_KBMAP the name of the keymap file to use when running on the console. See the '\c .B \-kbmap\c \&' option. .TP .B SQUEAK_LAZY equivalent to the '\c .B \-lazy\c \&' flag. .TP .B SQUEAK_MAPDELBS equivalent to the '\c .B \-mapdelbs\c \&' flag. .TP .B SQUEAK_MEMORY the initial size of the heap, with optional 'k' or 'm' suffix. Equivalent to the '\c .BI "-memory " size [km]\c \&' flag. .TP .B SQUEAK_MSDEV the name of the mouse device to use when running on the console. See the '\c .B \-msdev\c \&' option. .TP .B SQUEAK_MSPROTO the name of the mouse protocl to use when running on the console. See the '\c .B \-msproto\c \&' option. .TP .B SQUEAK_VTLOCK if set then equivalent to specifying the '\c .B \-vtlock\c \&' option on the command line. .TP .B SQUEAK_VTSWITCH if set then equivalent to specifying the '\c .B \-vtswitch\c \&' option on the command line. .TP .B SQUEAK_NOEVENTS if set, equivalent to '\c .B \-noevents\c \&'. .TP .B SQUEAK_NOINTL equivalent to '\c .B \-nointl\c \&' if set. .TP .B SQUEAK_NOMIXER equivalent to '\c .B \-nomixer\c \&' if set. .TP .B SQUEAK_NOTIMER equivalent to '\c .B \-notimer\c \&' if set. .TP .B SQUEAK_NOTITLE if set, equivalent to '\c .B \-notitle\c \&'. .TP .B SQUEAK_PATHENC the name of the character encoding used to construct file and directory names. Equivalent to giving the '\c .B \-pathenc\c \&' command-line option if set. .TP .B SQUEAK_PLUGINS see '\c .B \-plugins\c \&'. .TP .B SQUEAK_SWAPBTN equivalent to '\c .B \-swapbtn\c \&' if set. .TP .B SQUEAK_TEXTENC the name of the character encoding used to copy/paste text from/to external applications. Equivalent to giving the '\c .B \-textenc\c \&' command-line option if set. .TP .B SQUEAK_VM contains the names of one or more drivers to be loaded during initialisation. See the '\c .B \-vm\c \&' option for details. .TP .B SQUEAK_XSHM equivalent to '\c .B \-xshm\c \&'. .PP If an environment variable and a command-line option conflict over a particular value then normally the value in the command line takes precedence. The exception to this rule is the '\-vm' option. Environment variables are processed before command-line arguments and \&'\-vm' cannnot be used to unload a driver that was loaded while processing the contents of 'SQUEAK_VM'. .PP .B squeak also checks the environment for .B LC_ALL and .B LC_CTYPE\c \&. If either of these variables is set then support for international keyboards (including dead keys for diacritical marks) is enabled. To prevent this support being enabled even when one or both of these variables is set, use the '\-nointl' option (or set .B SQUEAK_NOINTL in the environment). For example, to start .B squeak with support for dead keys on Spanish keyboards, with Latin-1 encoding of external characters and the default MacRoman internal font encoding, run .B squeak like this: .sp .RS .nf export LC_CTYPE=es_ES export SQUEAK_TEXTENC=latin1 squeak .fi .RE .SH SCRIPTS Squeak can load and execute a 'script' file containing Smalltalk code at startup. The name of the file should be given as the .I script argument to .B squeak\c \&. For example, assuming that the image 'foo.image' contains an open Transcript window, then the following represents the 'hello world' program for Squeak: .sp .RS .nf Transcript cr; show: 'Hello, world'. .fi .RE .sp If this script is in a file called 'hello.sq', then it could be run like this: .sp .RS .nf squeak foo.image hello.sq .fi .RE .PP It is also possible to make 'self interpreting' scripts by adding an 'interpreter line' to the start of the script. The 'hello.sq' file could be changed to .sp .RS .nf #![bindir]/squeak -- Transcript cr; show: 'Hello, world'. .fi .RE .sp and then made executable with .sp .RS .nf chmod +x hello.sq .fi .RE .sp and then invoked by running the script file directly: .sp .RS .nf SQUEAK_IMAGE="foo.image" export SQUEAK_IMAGE \&./hello.sq .fi .RE .PP If any .I argument\c s are present after the .I script name then they can be retrieved from within the script using the method .sp .RS .nf Smalltalk getSystemAttribute: \c .I n .fi .RE .sp where .I n is the index of the argument, starting at 3 for the first argument. (See the method comment for .sp .RS .nf SystemDictionary>>getSystemAttribute: .fi .RE .sp in the image for an explanation of the meanings of the indices.) .PP As an example of this, here is the 'echo' program written as a Squeak script: .sp .RS .nf #![bindir]/squeak -- "Echo arguments to the Transcript." | i a | i := 2. [(a := Smalltalk getSystemAttribute: (i := i + 1)) notNil] whileTrue: [Transcript space; show: a]. .fi .RE .sp When run as .sp .RS .nf \&./echo.sq one two three .fi .RE .sp this would print 'one two three' in the Transcript window. .SH DIAGNOSTICS .TP .B inisqueak prints several informational messages while doing its stuff. If it encounters a problem it prints an appropriate message before bailing out. The messages should be self-explanatory. .TP .B squeak normally does not print anything at all. If it prints something then there is a problem. The messages should be self-explanatory. .\" .PP .\" Sending .\" .B squeak .\" a SIGHUP or SIGQUIT signal will cause it dump the executing image into .\" the working directy and then exit. Both of these should be .\" considered 'last resort' measures to save an image that contains .\" valuable recent changes. SIGHUP is synchronous (it works when the VM .\" is in a known state) and the chances of obtaining a working image are .\" fairly good, but it relies on the event polling loop being called. .\" SIGQUIT is asynchronous, and the chances of recovering a working image .\" after using it are fairly poor. In either case, when restaring the .\" "dumped" image, the first think that should be done is to execute .\" .sp .\" .RS .\" .nf .\" Smalltalk processStartUpList: true .\" .fi .\" .RE .\" .sp .\" in a workspace. Recover what is needed from the image, then destroy .\" the image (whose integrity should certainly not be trusted). .SH FILES .I [imgdir]/SqueakV[major].sources .RS Shared system sources file for the Squeak image. There must be a copy of (or link to) this file in the working directory when running .B squeak\c \&. .RE .sp .I [imgdir]/Squeak*.image .I [imgdir]/Squeak*.changes .RS Distributed image and changes files holding a `shapshot' of a live Squeak session. (The contents of these files change during a session, and so private copies should always be made before running .B squeak for the first time. See .BR inisqueak (1)\c ). .RE .sp .I ./SqueakV[major].sources .RS A link to the system sources file. .RE .sp .IR ./ name .image .br .IR ./ name .changes .RS Private copies of image and changes files. .RE .sp .I [plgdir]/*.so .br .I [plgdir]/*.la .RS Virtual machine 'plugins' (containing primitives that are loaded on demand) and drivers (for different types of display and sound hardware). .RE .sp .I [bindir]/squeak .br .I [bindir]/inisqueak .RS The Squeak virtual machine and personal image installer script. .RE .sp .I [mandir]/squeak.1 .RS This manual page. .RE .sp .I [docdir]/* .RS Miscellaneous documentation. .RE .SH NOTES This manual page documents version [version] of Unix Squeak. It may not be appropriate for any other version. .PP The image and changes files containing a saved Squeak session are intimately related. They should always be used together, never be separated, and under no circumstances should an image be run with a changes file that has been used with a different image. Failure to adhere to the above could cause the source code for the methods in the image to become garbled and impossible to retrieve. .PP The Unix Squeak virtual machine fully supports OpenGL in both the X11 and Quartz display drivers. Open Croquet will run just fine with either of these drivers (and many Mac OS X users will even have the choice of which driver to use :). .SH BUGS If a 'binary' option is enabled by an environment variable, there is no way to disable it on the command line. .PP Similarly, drivers specified in the .I SQUEAK_VM environment variable cannot be overridden by passing options on the command line. .PP .B squeak should never crash. In the unlikely event that it does crash, or prints any kind of message that .I does not appear to be caused by incorrect arguments or illegal operations from within a Squeak program, please send a bug report to: . (Do not send bug reports to the general-purpose 'squeak-dev' mailing list. They will not be read. If you feel you must post a bug report to a mailing list, send it to the Squeak 'vm-dev' mailing list in addition to the above email address.) .SH AUTHOR This manual page was written by Ian Piumarta. .SH SEE ALSO Dan Ingalls, Ted Kaehler, John Maloney, Scott Wallace and Alan Kay, \c .I Back to the Future: The Story of Squeak, A Practical Smalltalk Written in Itself\c \&. Proc. OOPSLA'97. .PP The official Squeak home page: .RS .B http://squeak.org .RE .PP The general-purpose 'squeak-dev' mailing list (not for VM-related bug reports): .RS .B http://lists.squeakfoundation.org/listinfo/squeak-dev .RE .PP The Squeak 'vm-dev' mailing list (amongst others): .RS .B http://discuss.squeakfoundation.org/ .RE .PP The latest source and binary distributions of Unix Squeak: .RS .B http://squeak.hpl.hp.com/~piumarta/squeak .RE .\".PP .\"The list of IANA-registered character encoding names, of which a proper subset is recognised by Squeak: .\".RS .\".B http://www.iana.org/assignments/character-sets .\".RE ================================================ FILE: vm/src/from_squeak/unix/misc/00_README ================================================ VMM38b4-64bit-image1-ikp.1.cs VMM38b4-64bit-image2-ikp.1.cs Contain image-side support for 64-bit images. File-in image1 before image2. System-Tracing.2.cs Contains the SystemTracer64 which writes a copy of the running image in 64-bit format. File-in image1 and image2 before System-Tracing. VMMaker-tpr.14.mcz Contains the version of VMMaker to which 64-bit support has been added. (This file does not itself contain any 64-bit support.) VMM38b4-64bit-vm1-ikp.1.cs Contains 64-bit support for the CCodeGenerator, ObjectMemory, core Interpreter, and the three essential plugins: BitBlt, Balloon and FilePlugin. You must file this in on top of VMMaker-tpr.14. VMM38b4-64bit-vm2-ikp.2.cs Contains 64-bit support for the SocketPlugin, and for the SmartSyntaxInterperterPlugin (and its variant of the CCodeGenerator) required to translate it. ---------------------------------------------------------------- OSProcessPluginV3-3.sar XDisplayControlPluginV1-0.sar AioPluginV1-1.sar The latest OSProcessPlugin from Dave Lewis. Not part of the standard VM distributions, but bundled with the Unix distribution for your convenience. ---------------------------------------------------------------- GLXUnix-ikp.2.cs Contains GLX support (as required by Croquet) that takes into account the differences between big- and little-endian machines. File this into a Croquet0.01 image before trying to run it on Unix. (If you don't know what Croquet is then you don't need this file.) ================================================ FILE: vm/src/from_squeak/unix/misc/GLXUnix-ikp.2.cs ================================================ 'From TeaSqueak3.2 of 19 September 2002 [latest update: #362] on 5 February 2003 at 10:43:22 am'! GLX subclass: #GLXUnixQuartz instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tea-GLX'! GLX subclass: #GLXUnixX11BE instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tea-GLX'! GLXUnixX11BE subclass: #GLXUnixX11LE instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tea-GLX'! !GLX class methodsFor: 'instance creation' stamp: 'ikp 2/3/2003 17:06'! new Smalltalk platformName = 'Win32' ifTrue:[^GLXWin32 basicNew initialize]. Smalltalk platformName = 'unix' ifTrue: [(Smalltalk windowSystemName = 'X11') ifTrue: [Smalltalk isLittleEndian ifTrue: [^GLXUnixX11LE basicNew initialize] ifFalse: [^GLXUnixX11BE basicNew initialize]]. (Smalltalk windowSystemName = 'Quartz') "implicitly big endian" ifTrue: [^GLXUnixQuartz basicNew initialize]. self error: 'I cannot create a GLX for this window system']. Smalltalk platformName = 'Mac OS' ifTrue:[ Smalltalk osVersion asNumber < 1000 ifTrue: [^GLXMacOS9 basicNew initialize] ifFalse:[^GLXMacOSX basicNew initialize]. ]. ^self error:'Cannot identify platform'! ! !GLXUnixQuartz methodsFor: 'accessing' stamp: 'ikp 1/7/2003 21:14'! imagePixelFormat32 ^GLBgra! ! !GLXUnixQuartz methodsFor: 'accessing' stamp: 'ikp 1/7/2003 21:14'! imagePixelType32 ^GLUnsignedInt8888Rev! ! !GLXUnixQuartz methodsFor: 'accessing' stamp: 'ikp 1/7/2003 21:14'! textureInternalFormat ^GLRgba! ! !GLXUnixQuartz methodsFor: 'accessing' stamp: 'ikp 1/7/2003 21:14'! texturePixelFormat ^GLBgra! ! !GLXUnixQuartz methodsFor: 'accessing' stamp: 'ikp 1/7/2003 21:14'! texturePixelType ^GLUnsignedInt8888Rev! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glAccum: op with: value "This method was automatically generated." "void glAccum(GLenum op, GLfloat value);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glActiveTextureARB: texture "This method was automatically generated." "void glActiveTextureARB(GLenum texture);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glAlphaFunc: func with: ref "This method was automatically generated." "void glAlphaFunc(GLenum func, GLclampf ref);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glAreTexturesResident: n with: texturez with: residences "This method was automatically generated." "GLboolean glAreTexturesResident(GLsizei n, GLuint* textures, GLboolean* residences);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glAreTexturesResidentEXT: n with: texturez with: residences "This method was automatically generated." "GLboolean glAreTexturesResidentEXT(GLsizei n, GLuint* textures, GLboolean* residences);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glArrayElement: i "This method was automatically generated." "void glArrayElement(GLint i);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glArrayElementEXT: i "This method was automatically generated." "void glArrayElementEXT(GLint i);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBegin: mode "This method was automatically generated." "void glBegin(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBindTexture: targt with: texture "This method was automatically generated." "void glBindTexture(GLenum target, GLuint texture);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBitmap: width with: height with: xorig with: yorig with: xmove with: ymove with: bitmap "This method was automatically generated." "void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte* bitmap);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBlendColor: red with: green with: blue with: alpha "This method was automatically generated." "void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBlendEquation: mode "This method was automatically generated." "void glBlendEquation(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glBlendFunc: sfactor with: dfactor "This method was automatically generated." "void glBlendFunc(GLenum sfactor, GLenum dfactor);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCallList: list "This method was automatically generated." "void glCallList(GLuint list);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCallLists: n with: type with: lists "This method was automatically generated." "void glCallLists(GLsizei n, GLenum type, GLvoid* lists);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClear: mask "This method was automatically generated." "void glClear(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClearAccum: red with: green with: blue with: alpha "This method was automatically generated." "void glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClearColor: red with: green with: blue with: alpha "This method was automatically generated." "void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClearDepth: depth "This method was automatically generated." "void glClearDepth(GLclampd depth);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClearIndex: c "This method was automatically generated." "void glClearIndex(GLfloat c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClearStencil: s "This method was automatically generated." "void glClearStencil(GLint s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClientActiveTextureARB: texture "This method was automatically generated." "void glClientActiveTextureARB(GLenum texture);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glClipPlane: plane with: equation "This method was automatically generated." "void glClipPlane(GLenum plane, GLdouble* equation);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3b: red with: green with: blue "This method was automatically generated." "void glColor3b(GLbyte red, GLbyte green, GLbyte blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3bv: v "This method was automatically generated." "void glColor3bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3d: red with: green with: blue "This method was automatically generated." "void glColor3d(GLdouble red, GLdouble green, GLdouble blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3dv: v "This method was automatically generated." "void glColor3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3f: red with: green with: blue "This method was automatically generated." "void glColor3f(GLfloat red, GLfloat green, GLfloat blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3fv: v "This method was automatically generated." "void glColor3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3i: red with: green with: blue "This method was automatically generated." "void glColor3i(GLint red, GLint green, GLint blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3iv: v "This method was automatically generated." "void glColor3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3s: red with: green with: blue "This method was automatically generated." "void glColor3s(GLshort red, GLshort green, GLshort blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3sv: v "This method was automatically generated." "void glColor3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3ub: red with: green with: blue "This method was automatically generated." "void glColor3ub(GLubyte red, GLubyte green, GLubyte blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3ubv: v "This method was automatically generated." "void glColor3ubv(GLubyte* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3ui: red with: green with: blue "This method was automatically generated." "void glColor3ui(GLuint red, GLuint green, GLuint blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3uiv: v "This method was automatically generated." "void glColor3uiv(GLuint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3us: red with: green with: blue "This method was automatically generated." "void glColor3us(GLushort red, GLushort green, GLushort blue);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor3usv: v "This method was automatically generated." "void glColor3usv(GLushort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4b: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4bv: v "This method was automatically generated." "void glColor4bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4d: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4dv: v "This method was automatically generated." "void glColor4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4f: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4fv: v "This method was automatically generated." "void glColor4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4i: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4i(GLint red, GLint green, GLint blue, GLint alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4iv: v "This method was automatically generated." "void glColor4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4s: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4sv: v "This method was automatically generated." "void glColor4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4ub: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4ubv: v "This method was automatically generated." "void glColor4ubv(GLubyte* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4ui: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4uiv: v "This method was automatically generated." "void glColor4uiv(GLuint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4us: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColor4usv: v "This method was automatically generated." "void glColor4usv(GLushort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorMask: red with: green with: blue with: alpha "This method was automatically generated." "void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorMaterial: face with: mode "This method was automatically generated." "void glColorMaterial(GLenum face, GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorSubTable: targt with: start with: count with: format with: type with: data "This method was automatically generated." "void glColorSubTable(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, GLvoid* data);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorTable: targt with: internalformat with: width with: format with: type with: table "This method was automatically generated." "void glColorTable(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, GLvoid* table);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorTableParameterfv: targt with: pname with: params "This method was automatically generated." "void glColorTableParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glColorTableParameteriv: targt with: pname with: params "This method was automatically generated." "void glColorTableParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionFilter1D: targt with: internalformat with: width with: format with: type with: image "This method was automatically generated." "void glConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionFilter2D: targt with: internalformat with: width with: height with: format with: type with: image "This method was automatically generated." "void glConvolutionFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionParameterf: targt with: pname with: params "This method was automatically generated." "void glConvolutionParameterf(GLenum target, GLenum pname, GLfloat params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionParameterfv: targt with: pname with: params "This method was automatically generated." "void glConvolutionParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionParameteri: targt with: pname with: params "This method was automatically generated." "void glConvolutionParameteri(GLenum target, GLenum pname, GLint params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glConvolutionParameteriv: targt with: pname with: params "This method was automatically generated." "void glConvolutionParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyColorSubTable: targt with: start with: x with: y with: width "This method was automatically generated." "void glCopyColorSubTable(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyColorTable: targt with: internalformat with: x with: y with: width "This method was automatically generated." "void glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyConvolutionFilter1D: targt with: internalformat with: x with: y with: width "This method was automatically generated." "void glCopyConvolutionFilter1D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyConvolutionFilter2D: targt with: internalformat with: x with: y with: width with: height "This method was automatically generated." "void glCopyConvolutionFilter2D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyPixels: x with: y with: width with: height with: type "This method was automatically generated." "void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyTexImage1D: targt with: level with: internalformat with: x with: y with: width with: border "This method was automatically generated." "void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyTexImage2D: targt with: level with: internalformat with: x with: y with: width with: height with: border "This method was automatically generated." "void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyTexSubImage1D: targt with: level with: xoffset with: x with: y with: width "This method was automatically generated." "void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyTexSubImage2D: targt with: level with: xoffset with: yoffset with: x with: y with: width with: height "This method was automatically generated." "void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCopyTexSubImage3D: targt with: level with: xoffset with: yoffset with: zoffset with: x with: y with: width with: height "This method was automatically generated." "void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glCullFace: mode "This method was automatically generated." "void glCullFace(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDeleteLists: list with: range "This method was automatically generated." "void glDeleteLists(GLuint list, GLsizei range);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDeleteTextures: n with: textures "This method was automatically generated." "void glDeleteTextures(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDeleteTexturesEXT: n with: textures "This method was automatically generated." "void glDeleteTexturesEXT(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDepthFunc: func "This method was automatically generated." "void glDepthFunc(GLenum func);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDepthMask: flag "This method was automatically generated." "void glDepthMask(GLboolean flag);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDepthRange: zNear with: zFar "This method was automatically generated." "void glDepthRange(GLclampd zNear, GLclampd zFar);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDisable: cap "This method was automatically generated." "void glDisable(GLenum cap);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDisableClientState: array "This method was automatically generated." "void glDisableClientState(GLenum array);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawArrays: mode with: first with: count "This method was automatically generated." "void glDrawArrays(GLenum mode, GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawArraysEXT: mode with: first with: count "This method was automatically generated." "void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawBuffer: mode "This method was automatically generated." "void glDrawBuffer(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawElements: mode with: count with: type with: indices "This method was automatically generated." "void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid* indices);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawPixels: width with: height with: format with: type with: pixels "This method was automatically generated." "void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glDrawRangeElements: mode with: start with: end with: count with: type with: indices "This method was automatically generated." "void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLvoid* indices);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEdgeFlag: flag "This method was automatically generated." "void glEdgeFlag(GLboolean flag);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEdgeFlagPointer: stride with: pointer "This method was automatically generated." "void glEdgeFlagPointer(GLsizei stride, GLboolean* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEdgeFlagPointerEXT: stride with: count with: pointer "This method was automatically generated." "void glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, GLboolean* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEdgeFlagv: flag "This method was automatically generated." "void glEdgeFlagv(GLboolean* flag);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEnable: cap "This method was automatically generated." "void glEnable(GLenum cap);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEnableClientState: array "This method was automatically generated." "void glEnableClientState(GLenum array);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEnd "This method was automatically generated." "void glEnd();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEndList "This method was automatically generated." "void glEndList();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord1d: u "This method was automatically generated." "void glEvalCoord1d(GLdouble u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord1dv: u "This method was automatically generated." "void glEvalCoord1dv(GLdouble* u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord1f: u "This method was automatically generated." "void glEvalCoord1f(GLfloat u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord1fv: u "This method was automatically generated." "void glEvalCoord1fv(GLfloat* u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord2d: u with: v "This method was automatically generated." "void glEvalCoord2d(GLdouble u, GLdouble v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord2dv: u "This method was automatically generated." "void glEvalCoord2dv(GLdouble* u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord2f: u with: v "This method was automatically generated." "void glEvalCoord2f(GLfloat u, GLfloat v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalCoord2fv: u "This method was automatically generated." "void glEvalCoord2fv(GLfloat* u);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalMesh1: mode with: i1 with: i2 "This method was automatically generated." "void glEvalMesh1(GLenum mode, GLint i1, GLint i2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalMesh2: mode with: i1 with: i2 with: j1 with: j2 "This method was automatically generated." "void glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalPoint1: i "This method was automatically generated." "void glEvalPoint1(GLint i);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glEvalPoint2: i with: j "This method was automatically generated." "void glEvalPoint2(GLint i, GLint j);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFeedbackBuffer: size with: type with: buffer "This method was automatically generated." "void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat* buffer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFinish "This method was automatically generated." "void glFinish();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFlush "This method was automatically generated." "void glFlush();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFogf: pname with: param "This method was automatically generated." "void glFogf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFogfv: pname with: params "This method was automatically generated." "void glFogfv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFogi: pname with: param "This method was automatically generated." "void glFogi(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFogiv: pname with: params "This method was automatically generated." "void glFogiv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFrontFace: mode "This method was automatically generated." "void glFrontFace(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glFrustum: left with: right with: bottom with: top with: zNear with: zFar "This method was automatically generated." "void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/8/2003 00:18'! glGenLists: range "This method was automatically generated." "GLuint glGenLists(GLsizei range);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGenTextures: n with: textures "This method was automatically generated." "void glGenTextures(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGenTexturesEXT: n with: textures "This method was automatically generated." "void glGenTexturesEXT(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetBooleanv: pname with: params "This method was automatically generated." "void glGetBooleanv(GLenum pname, GLboolean* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetClipPlane: plane with: equation "This method was automatically generated." "void glGetClipPlane(GLenum plane, GLdouble* equation);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetColorTable: targt with: format with: type with: table "This method was automatically generated." "void glGetColorTable(GLenum target, GLenum format, GLenum type, GLvoid* table);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetColorTableParameterfv: targt with: pname with: params "This method was automatically generated." "void glGetColorTableParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetColorTableParameteriv: targt with: pname with: params "This method was automatically generated." "void glGetColorTableParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetConvolutionFilter: targt with: format with: type with: image "This method was automatically generated." "void glGetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetConvolutionParameterfv: targt with: pname with: params "This method was automatically generated." "void glGetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetConvolutionParameteriv: targt with: pname with: params "This method was automatically generated." "void glGetConvolutionParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetDoublev: pname with: params "This method was automatically generated." "void glGetDoublev(GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetError "This method was automatically generated." "GLenum glGetError();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetFloatv: pname with: params "This method was automatically generated." "void glGetFloatv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetHistogram: targt with: reset with: format with: type with: values "This method was automatically generated." "void glGetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetHistogramParameterfv: targt with: pname with: params "This method was automatically generated." "void glGetHistogramParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetHistogramParameteriv: targt with: pname with: params "This method was automatically generated." "void glGetHistogramParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetIntegerv: pname with: params "This method was automatically generated." "void glGetIntegerv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetLightfv: light with: pname with: params "This method was automatically generated." "void glGetLightfv(GLenum light, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetLightiv: light with: pname with: params "This method was automatically generated." "void glGetLightiv(GLenum light, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMapdv: targt with: query with: v "This method was automatically generated." "void glGetMapdv(GLenum target, GLenum query, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMapfv: targt with: query with: v "This method was automatically generated." "void glGetMapfv(GLenum target, GLenum query, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMapiv: targt with: query with: v "This method was automatically generated." "void glGetMapiv(GLenum target, GLenum query, GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMaterialfv: face with: pname with: params "This method was automatically generated." "void glGetMaterialfv(GLenum face, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMaterialiv: face with: pname with: params "This method was automatically generated." "void glGetMaterialiv(GLenum face, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMinmax: targt with: reset with: format with: type with: values "This method was automatically generated." "void glGetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMinmaxParameterfv: targt with: pname with: params "This method was automatically generated." "void glGetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetMinmaxParameteriv: targt with: pname with: params "This method was automatically generated." "void glGetMinmaxParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPixelMapfv: map with: values "This method was automatically generated." "void glGetPixelMapfv(GLenum map, GLfloat* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPixelMapuiv: map with: values "This method was automatically generated." "void glGetPixelMapuiv(GLenum map, GLuint* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPixelMapusv: map with: values "This method was automatically generated." "void glGetPixelMapusv(GLenum map, GLushort* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPointerv: pname with: params "This method was automatically generated." "void glGetPointerv(GLenum pname, GLvoid** params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPointervEXT: pname with: params "This method was automatically generated." "void glGetPointervEXT(GLenum pname, GLvoid** params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetPolygonStipple: mask "This method was automatically generated." "void glGetPolygonStipple(GLubyte* mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetSeparableFilter: targt with: format with: type with: row with: column with: span "This method was automatically generated." "void glGetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid* row, GLvoid* column, GLvoid* span);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetString: name "This method was automatically generated." "GLubyte* glGetString(GLenum name);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexEnvfv: targt with: pname with: params "This method was automatically generated." "void glGetTexEnvfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexEnviv: targt with: pname with: params "This method was automatically generated." "void glGetTexEnviv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexGendv: coord with: pname with: params "This method was automatically generated." "void glGetTexGendv(GLenum coord, GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexGenfv: coord with: pname with: params "This method was automatically generated." "void glGetTexGenfv(GLenum coord, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexGeniv: coord with: pname with: params "This method was automatically generated." "void glGetTexGeniv(GLenum coord, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexImage: targt with: level with: format with: type with: pixels "This method was automatically generated." "void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexLevelParameterfv: targt with: level with: pname with: params "This method was automatically generated." "void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexLevelParameteriv: targt with: level with: pname with: params "This method was automatically generated." "void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexParameterfv: targt with: pname with: params "This method was automatically generated." "void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glGetTexParameteriv: targt with: pname with: params "This method was automatically generated." "void glGetTexParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glHint: targt with: mode "This method was automatically generated." "void glHint(GLenum target, GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glHistogram: targt with: width with: internalformat with: sink "This method was automatically generated." "void glHistogram(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexMask: mask "This method was automatically generated." "void glIndexMask(GLuint mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexPointer: type with: stride with: pointer "This method was automatically generated." "void glIndexPointer(GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexPointerEXT: type with: stride with: count with: pointer "This method was automatically generated." "void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexd: c "This method was automatically generated." "void glIndexd(GLdouble c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexdv: c "This method was automatically generated." "void glIndexdv(GLdouble* c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexf: c "This method was automatically generated." "void glIndexf(GLfloat c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexfv: c "This method was automatically generated." "void glIndexfv(GLfloat* c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexi: c "This method was automatically generated." "void glIndexi(GLint c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexiv: c "This method was automatically generated." "void glIndexiv(GLint* c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexs: c "This method was automatically generated." "void glIndexs(GLshort c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexsv: c "This method was automatically generated." "void glIndexsv(GLshort* c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexub: c "This method was automatically generated." "void glIndexub(GLubyte c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIndexubv: c "This method was automatically generated." "void glIndexubv(GLubyte* c);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glInitNames "This method was automatically generated." "void glInitNames();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glInterleavedArrays: format with: stride with: pointer "This method was automatically generated." "void glInterleavedArrays(GLenum format, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIsEnabled: cap "This method was automatically generated." "GLboolean glIsEnabled(GLenum cap);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIsList: list "This method was automatically generated." "GLboolean glIsList(GLuint list);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIsTexture: texture "This method was automatically generated." "GLboolean glIsTexture(GLuint texture);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glIsTextureEXT: texture "This method was automatically generated." "GLboolean glIsTextureEXT(GLuint texture);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightModelf: pname with: param "This method was automatically generated." "void glLightModelf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightModelfv: pname with: params "This method was automatically generated." "void glLightModelfv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightModeli: pname with: param "This method was automatically generated." "void glLightModeli(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightModeliv: pname with: params "This method was automatically generated." "void glLightModeliv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightf: light with: pname with: param "This method was automatically generated." "void glLightf(GLenum light, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightfv: light with: pname with: params "This method was automatically generated." "void glLightfv(GLenum light, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLighti: light with: pname with: param "This method was automatically generated." "void glLighti(GLenum light, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLightiv: light with: pname with: params "This method was automatically generated." "void glLightiv(GLenum light, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLineStipple: factor with: pattern "This method was automatically generated." "void glLineStipple(GLint factor, GLushort pattern);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLineWidth: width "This method was automatically generated." "void glLineWidth(GLfloat width);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glListBase: base "This method was automatically generated." "void glListBase(GLuint base);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLoadIdentity "This method was automatically generated." "void glLoadIdentity();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLoadMatrixd: m "This method was automatically generated." "void glLoadMatrixd(GLdouble* m);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLoadMatrixf: m "This method was automatically generated." "void glLoadMatrixf(GLfloat* m);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLoadName: name "This method was automatically generated." "void glLoadName(GLuint name);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLockArraysEXT: first with: count "This method was automatically generated." "void glLockArraysEXT(GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glLogicOp: opcode "This method was automatically generated." "void glLogicOp(GLenum opcode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMap1d: targt with: u1 with: u2 with: stride with: order with: points "This method was automatically generated." "void glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, GLdouble* points);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMap1f: targt with: u1 with: u2 with: stride with: order with: points "This method was automatically generated." "void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, GLfloat* points);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMap2d: targt with: u1 with: u2 with: ustride with: uorder with: v1 with: v2 with: vstride with: vorder with: points "This method was automatically generated." "void glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble* points);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMap2f: targt with: u1 with: u2 with: ustride with: uorder with: v1 with: v2 with: vstride with: vorder with: points "This method was automatically generated." "void glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat* points);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMapGrid1d: un with: u1 with: u2 "This method was automatically generated." "void glMapGrid1d(GLint un, GLdouble u1, GLdouble u2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMapGrid1f: un with: u1 with: u2 "This method was automatically generated." "void glMapGrid1f(GLint un, GLfloat u1, GLfloat u2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMapGrid2d: un with: u1 with: u2 with: vn with: v1 with: v2 "This method was automatically generated." "void glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMapGrid2f: un with: u1 with: u2 with: vn with: v1 with: v2 "This method was automatically generated." "void glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMaterialf: face with: pname with: param "This method was automatically generated." "void glMaterialf(GLenum face, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMaterialfv: face with: pname with: params "This method was automatically generated." "void glMaterialfv(GLenum face, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMateriali: face with: pname with: param "This method was automatically generated." "void glMateriali(GLenum face, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMaterialiv: face with: pname with: params "This method was automatically generated." "void glMaterialiv(GLenum face, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMatrixMode: mode "This method was automatically generated." "void glMatrixMode(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMinmax: targt with: internalformat with: sink "This method was automatically generated." "void glMinmax(GLenum target, GLenum internalformat, GLboolean sink);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultMatrixd: m "This method was automatically generated." "void glMultMatrixd(GLdouble* m);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultMatrixf: m "This method was automatically generated." "void glMultMatrixf(GLfloat* m);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1dARB: targt with: s "This method was automatically generated." "void glMultiTexCoord1dARB(GLenum target, GLdouble s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1dvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord1dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1fARB: targt with: s "This method was automatically generated." "void glMultiTexCoord1fARB(GLenum target, GLfloat s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1fvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord1fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1iARB: targt with: s "This method was automatically generated." "void glMultiTexCoord1iARB(GLenum target, GLint s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1ivARB: targt with: v "This method was automatically generated." "void glMultiTexCoord1ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1sARB: targt with: s "This method was automatically generated." "void glMultiTexCoord1sARB(GLenum target, GLshort s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord1svARB: targt with: v "This method was automatically generated." "void glMultiTexCoord1svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2dARB: targt with: s with: t "This method was automatically generated." "void glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2dvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord2dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2fARB: targt with: s with: t "This method was automatically generated." "void glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2fvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord2fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2iARB: targt with: s with: t "This method was automatically generated." "void glMultiTexCoord2iARB(GLenum target, GLint s, GLint t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2ivARB: targt with: v "This method was automatically generated." "void glMultiTexCoord2ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2sARB: targt with: s with: t "This method was automatically generated." "void glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord2svARB: targt with: v "This method was automatically generated." "void glMultiTexCoord2svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3dARB: targt with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3dvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord3dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3fARB: targt with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3fvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord3fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3iARB: targt with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3ivARB: targt with: v "This method was automatically generated." "void glMultiTexCoord3ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3sARB: targt with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord3svARB: targt with: v "This method was automatically generated." "void glMultiTexCoord3svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4dARB: targt with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4dvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord4dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4fARB: targt with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4fvARB: targt with: v "This method was automatically generated." "void glMultiTexCoord4fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4iARB: targt with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4ivARB: targt with: v "This method was automatically generated." "void glMultiTexCoord4ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4sARB: targt with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glMultiTexCoord4svARB: targt with: v "This method was automatically generated." "void glMultiTexCoord4svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNewList: list with: mode "This method was automatically generated." "void glNewList(GLuint list, GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3b: nx with: ny with: nz "This method was automatically generated." "void glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3bv: v "This method was automatically generated." "void glNormal3bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3d: nx with: ny with: nz "This method was automatically generated." "void glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3dv: v "This method was automatically generated." "void glNormal3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3f: nx with: ny with: nz "This method was automatically generated." "void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3fv: v "This method was automatically generated." "void glNormal3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3i: nx with: ny with: nz "This method was automatically generated." "void glNormal3i(GLint nx, GLint ny, GLint nz);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3iv: v "This method was automatically generated." "void glNormal3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3s: nx with: ny with: nz "This method was automatically generated." "void glNormal3s(GLshort nx, GLshort ny, GLshort nz);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormal3sv: v "This method was automatically generated." "void glNormal3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormalPointer: type with: stride with: pointer "This method was automatically generated." "void glNormalPointer(GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glNormalPointerEXT: type with: stride with: count with: pointer "This method was automatically generated." "void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glOrtho: left with: right with: bottom with: top with: zNear with: zFar "This method was automatically generated." "void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPassThrough: token "This method was automatically generated." "void glPassThrough(GLfloat token);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelMapfv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapfv(GLenum map, GLint mapsize, GLfloat* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelMapuiv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapuiv(GLenum map, GLint mapsize, GLuint* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelMapusv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapusv(GLenum map, GLint mapsize, GLushort* values);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelStoref: pname with: param "This method was automatically generated." "void glPixelStoref(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelStorei: pname with: param "This method was automatically generated." "void glPixelStorei(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelTransferf: pname with: param "This method was automatically generated." "void glPixelTransferf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelTransferi: pname with: param "This method was automatically generated." "void glPixelTransferi(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPixelZoom: xfactor with: yfactor "This method was automatically generated." "void glPixelZoom(GLfloat xfactor, GLfloat yfactor);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPointSize: size "This method was automatically generated." "void glPointSize(GLfloat size);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPolygonMode: face with: mode "This method was automatically generated." "void glPolygonMode(GLenum face, GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPolygonOffset: factor with: units "This method was automatically generated." "void glPolygonOffset(GLfloat factor, GLfloat units);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPolygonStipple: mask "This method was automatically generated." "void glPolygonStipple(GLubyte* mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPopAttrib "This method was automatically generated." "void glPopAttrib();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPopClientAttrib "This method was automatically generated." "void glPopClientAttrib();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPopMatrix "This method was automatically generated." "void glPopMatrix();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPopName "This method was automatically generated." "void glPopName();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPrioritizeTextures: n with: texturez with: priorities "This method was automatically generated." "void glPrioritizeTextures(GLsizei n, GLuint* textures, GLclampf* priorities);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPushAttrib: mask "This method was automatically generated." "void glPushAttrib(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPushClientAttrib: mask "This method was automatically generated." "void glPushClientAttrib(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPushMatrix "This method was automatically generated." "void glPushMatrix();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glPushName: name "This method was automatically generated." "void glPushName(GLuint name);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2d: x with: y "This method was automatically generated." "void glRasterPos2d(GLdouble x, GLdouble y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2dv: v "This method was automatically generated." "void glRasterPos2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2f: x with: y "This method was automatically generated." "void glRasterPos2f(GLfloat x, GLfloat y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2fv: v "This method was automatically generated." "void glRasterPos2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2i: x with: y "This method was automatically generated." "void glRasterPos2i(GLint x, GLint y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2iv: v "This method was automatically generated." "void glRasterPos2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2s: x with: y "This method was automatically generated." "void glRasterPos2s(GLshort x, GLshort y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos2sv: v "This method was automatically generated." "void glRasterPos2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3d: x with: y with: z "This method was automatically generated." "void glRasterPos3d(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3dv: v "This method was automatically generated." "void glRasterPos3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3f: x with: y with: z "This method was automatically generated." "void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3fv: v "This method was automatically generated." "void glRasterPos3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3i: x with: y with: z "This method was automatically generated." "void glRasterPos3i(GLint x, GLint y, GLint z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3iv: v "This method was automatically generated." "void glRasterPos3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3s: x with: y with: z "This method was automatically generated." "void glRasterPos3s(GLshort x, GLshort y, GLshort z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos3sv: v "This method was automatically generated." "void glRasterPos3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4d: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4dv: v "This method was automatically generated." "void glRasterPos4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4f: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4fv: v "This method was automatically generated." "void glRasterPos4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4i: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4i(GLint x, GLint y, GLint z, GLint w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4iv: v "This method was automatically generated." "void glRasterPos4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4s: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRasterPos4sv: v "This method was automatically generated." "void glRasterPos4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glReadBuffer: mode "This method was automatically generated." "void glReadBuffer(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glReadPixels: x with: y with: width with: height with: format with: type with: pixels "This method was automatically generated." "void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectd: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectdv: v1 with: v2 "This method was automatically generated." "void glRectdv(GLdouble* v1, GLdouble* v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectf: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectfv: v1 with: v2 "This method was automatically generated." "void glRectfv(GLfloat* v1, GLfloat* v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRecti: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRecti(GLint x1, GLint y1, GLint x2, GLint y2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectiv: v1 with: v2 "This method was automatically generated." "void glRectiv(GLint* v1, GLint* v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRects: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRectsv: v1 with: v2 "This method was automatically generated." "void glRectsv(GLshort* v1, GLshort* v2);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRenderMode: mode "This method was automatically generated." "GLint glRenderMode(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glResetHistogram: target "This method was automatically generated." "void glResetHistogram(GLenum target);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glResetMinmax: target "This method was automatically generated." "void glResetMinmax(GLenum target);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRotated: angle with: x with: y with: z "This method was automatically generated." "void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glRotatef: angle with: x with: y with: z "This method was automatically generated." "void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glScaled: x with: y with: z "This method was automatically generated." "void glScaled(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glScalef: x with: y with: z "This method was automatically generated." "void glScalef(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glScissor: x with: y with: width with: height "This method was automatically generated." "void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glSelectBuffer: size with: buffer "This method was automatically generated." "void glSelectBuffer(GLsizei size, GLuint* buffer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glSeparableFilter2D: targt with: internalformat with: width with: height with: format with: type with: row with: column "This method was automatically generated." "void glSeparableFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* row, GLvoid* column);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glShadeModel: mode "This method was automatically generated." "void glShadeModel(GLenum mode);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glStencilFunc: func with: ref with: mask "This method was automatically generated." "void glStencilFunc(GLenum func, GLint ref, GLuint mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glStencilMask: mask "This method was automatically generated." "void glStencilMask(GLuint mask);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glStencilOp: fail with: zfail with: zpass "This method was automatically generated." "void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1d: s "This method was automatically generated." "void glTexCoord1d(GLdouble s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1dv: v "This method was automatically generated." "void glTexCoord1dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1f: s "This method was automatically generated." "void glTexCoord1f(GLfloat s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1fv: v "This method was automatically generated." "void glTexCoord1fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1i: s "This method was automatically generated." "void glTexCoord1i(GLint s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1iv: v "This method was automatically generated." "void glTexCoord1iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1s: s "This method was automatically generated." "void glTexCoord1s(GLshort s);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord1sv: v "This method was automatically generated." "void glTexCoord1sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2d: s with: t "This method was automatically generated." "void glTexCoord2d(GLdouble s, GLdouble t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2dv: v "This method was automatically generated." "void glTexCoord2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2f: s with: t "This method was automatically generated." "void glTexCoord2f(GLfloat s, GLfloat t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2fv: v "This method was automatically generated." "void glTexCoord2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2i: s with: t "This method was automatically generated." "void glTexCoord2i(GLint s, GLint t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2iv: v "This method was automatically generated." "void glTexCoord2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2s: s with: t "This method was automatically generated." "void glTexCoord2s(GLshort s, GLshort t);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord2sv: v "This method was automatically generated." "void glTexCoord2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3d: s with: t with: r "This method was automatically generated." "void glTexCoord3d(GLdouble s, GLdouble t, GLdouble r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3dv: v "This method was automatically generated." "void glTexCoord3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3f: s with: t with: r "This method was automatically generated." "void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3fv: v "This method was automatically generated." "void glTexCoord3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3i: s with: t with: r "This method was automatically generated." "void glTexCoord3i(GLint s, GLint t, GLint r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3iv: v "This method was automatically generated." "void glTexCoord3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3s: s with: t with: r "This method was automatically generated." "void glTexCoord3s(GLshort s, GLshort t, GLshort r);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord3sv: v "This method was automatically generated." "void glTexCoord3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4d: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4dv: v "This method was automatically generated." "void glTexCoord4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4f: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4fv: v "This method was automatically generated." "void glTexCoord4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4i: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4i(GLint s, GLint t, GLint r, GLint q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4iv: v "This method was automatically generated." "void glTexCoord4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4s: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoord4sv: v "This method was automatically generated." "void glTexCoord4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoordPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexCoordPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexEnvf: targt with: pname with: param "This method was automatically generated." "void glTexEnvf(GLenum target, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexEnvfv: targt with: pname with: params "This method was automatically generated." "void glTexEnvfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexEnvi: targt with: pname with: param "This method was automatically generated." "void glTexEnvi(GLenum target, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexEnviv: targt with: pname with: params "This method was automatically generated." "void glTexEnviv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGend: coord with: pname with: param "This method was automatically generated." "void glTexGend(GLenum coord, GLenum pname, GLdouble param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGendv: coord with: pname with: params "This method was automatically generated." "void glTexGendv(GLenum coord, GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGenf: coord with: pname with: param "This method was automatically generated." "void glTexGenf(GLenum coord, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGenfv: coord with: pname with: params "This method was automatically generated." "void glTexGenfv(GLenum coord, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGeni: coord with: pname with: param "This method was automatically generated." "void glTexGeni(GLenum coord, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexGeniv: coord with: pname with: params "This method was automatically generated." "void glTexGeniv(GLenum coord, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexImage1D: targt with: level with: internalformat with: width with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexImage2D: targt with: level with: internalformat with: width with: height with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexImage3D: targt with: level with: internalformat with: width with: height with: depth with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexParameterf: targt with: pname with: param "This method was automatically generated." "void glTexParameterf(GLenum target, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexParameterfv: targt with: pname with: params "This method was automatically generated." "void glTexParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexParameteri: targt with: pname with: param "This method was automatically generated." "void glTexParameteri(GLenum target, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexParameteriv: targt with: pname with: params "This method was automatically generated." "void glTexParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexSubImage1D: targt with: level with: xoffset with: width with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexSubImage2D: targt with: level with: xoffset with: yoffset with: width with: height with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTexSubImage3D: targt with: level with: xoffset with: yoffset with: zoffset with: width with: height with: depth with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTranslated: x with: y with: z "This method was automatically generated." "void glTranslated(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glTranslatef: x with: y with: z "This method was automatically generated." "void glTranslatef(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glUnlockArraysEXT "This method was automatically generated." "void glUnlockArraysEXT();" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2d: x with: y "This method was automatically generated." "void glVertex2d(GLdouble x, GLdouble y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2dv: v "This method was automatically generated." "void glVertex2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2f: x with: y "This method was automatically generated." "void glVertex2f(GLfloat x, GLfloat y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2fv: v "This method was automatically generated." "void glVertex2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2i: x with: y "This method was automatically generated." "void glVertex2i(GLint x, GLint y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2iv: v "This method was automatically generated." "void glVertex2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2s: x with: y "This method was automatically generated." "void glVertex2s(GLshort x, GLshort y);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex2sv: v "This method was automatically generated." "void glVertex2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3d: x with: y with: z "This method was automatically generated." "void glVertex3d(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3dv: v "This method was automatically generated." "void glVertex3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3f: x with: y with: z "This method was automatically generated." "void glVertex3f(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3fv: v "This method was automatically generated." "void glVertex3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3i: x with: y with: z "This method was automatically generated." "void glVertex3i(GLint x, GLint y, GLint z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3iv: v "This method was automatically generated." "void glVertex3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3s: x with: y with: z "This method was automatically generated." "void glVertex3s(GLshort x, GLshort y, GLshort z);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex3sv: v "This method was automatically generated." "void glVertex3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4d: x with: y with: z with: w "This method was automatically generated." "void glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4dv: v "This method was automatically generated." "void glVertex4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4f: x with: y with: z with: w "This method was automatically generated." "void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4fv: v "This method was automatically generated." "void glVertex4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4i: x with: y with: z with: w "This method was automatically generated." "void glVertex4i(GLint x, GLint y, GLint z, GLint w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4iv: v "This method was automatically generated." "void glVertex4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4s: x with: y with: z with: w "This method was automatically generated." "void glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertex4sv: v "This method was automatically generated." "void glVertex4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertexPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glVertexPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixQuartz methodsFor: 'OpenGL API' stamp: 'ikp 1/7/2003 21:14'! glViewport: x with: y with: width with: height "This method was automatically generated." "void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixQuartz class methodsFor: 'as yet unclassified' stamp: 'ikp 1/16/2003 05:38'! test "GLXUnixOSX test" ^self error: 'test failed'! ! !GLXUnixQuartz class methodsFor: 'as yet unclassified' stamp: 'ikp 1/16/2003 05:39'! test: x with: y "GLXUnixOSX test: 6 with: 7" ^self error: 'test failed'! ! !GLXUnixX11BE methodsFor: 'accessing' stamp: 'bf 10/21/2002 19:10'! imagePixelFormat32 ^GLBgra! ! !GLXUnixX11BE methodsFor: 'accessing' stamp: 'ikp 2/3/2003 17:01'! imagePixelType32 ^GLUnsignedInt8888Rev! ! !GLXUnixX11BE methodsFor: 'accessing' stamp: 'bf 10/21/2002 19:15'! textureInternalFormat ^GLRgba! ! !GLXUnixX11BE methodsFor: 'accessing' stamp: 'bf 10/21/2002 19:09'! texturePixelFormat ^GLBgra! ! !GLXUnixX11BE methodsFor: 'accessing' stamp: 'ikp 2/3/2003 17:02'! texturePixelType ^GLUnsignedInt8888Rev! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glAccum: op with: value "This method was automatically generated." "void glAccum(GLenum op, GLfloat value);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glActiveTextureARB: texture "This method was automatically generated." "void glActiveTextureARB(GLenum texture);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glAlphaFunc: func with: ref "This method was automatically generated." "void glAlphaFunc(GLenum func, GLclampf ref);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glAreTexturesResident: n with: textures with: residences "This method was automatically generated." "GLboolean glAreTexturesResident(GLsizei n, GLuint* textures, GLboolean* residences);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glAreTexturesResidentEXT: n with: textures with: residences "This method was automatically generated." "GLboolean glAreTexturesResidentEXT(GLsizei n, GLuint* textures, GLboolean* residences);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glArrayElement: i "This method was automatically generated." "void glArrayElement(GLint i);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glArrayElementEXT: i "This method was automatically generated." "void glArrayElementEXT(GLint i);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBegin: mode "This method was automatically generated." "void glBegin(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBindTexture: target with: texture "This method was automatically generated." "void glBindTexture(GLenum target, GLuint texture);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBitmap: width with: height with: xorig with: yorig with: xmove with: ymove with: bitmap "This method was automatically generated." "void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte* bitmap);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBlendColor: red with: green with: blue with: alpha "This method was automatically generated." "void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBlendEquation: mode "This method was automatically generated." "void glBlendEquation(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glBlendFunc: sfactor with: dfactor "This method was automatically generated." "void glBlendFunc(GLenum sfactor, GLenum dfactor);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCallList: list "This method was automatically generated." "void glCallList(GLuint list);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCallLists: n with: type with: lists "This method was automatically generated." "void glCallLists(GLsizei n, GLenum type, GLvoid* lists);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClear: mask "This method was automatically generated." "void glClear(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClearAccum: red with: green with: blue with: alpha "This method was automatically generated." "void glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClearColor: red with: green with: blue with: alpha "This method was automatically generated." "void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClearDepth: depth "This method was automatically generated." "void glClearDepth(GLclampd depth);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClearIndex: c "This method was automatically generated." "void glClearIndex(GLfloat c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClearStencil: s "This method was automatically generated." "void glClearStencil(GLint s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClientActiveTextureARB: texture "This method was automatically generated." "void glClientActiveTextureARB(GLenum texture);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glClipPlane: plane with: equation "This method was automatically generated." "void glClipPlane(GLenum plane, GLdouble* equation);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3b: red with: green with: blue "This method was automatically generated." "void glColor3b(GLbyte red, GLbyte green, GLbyte blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3bv: v "This method was automatically generated." "void glColor3bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3d: red with: green with: blue "This method was automatically generated." "void glColor3d(GLdouble red, GLdouble green, GLdouble blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3dv: v "This method was automatically generated." "void glColor3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3f: red with: green with: blue "This method was automatically generated." "void glColor3f(GLfloat red, GLfloat green, GLfloat blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3fv: v "This method was automatically generated." "void glColor3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3i: red with: green with: blue "This method was automatically generated." "void glColor3i(GLint red, GLint green, GLint blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3iv: v "This method was automatically generated." "void glColor3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3s: red with: green with: blue "This method was automatically generated." "void glColor3s(GLshort red, GLshort green, GLshort blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3sv: v "This method was automatically generated." "void glColor3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3ub: red with: green with: blue "This method was automatically generated." "void glColor3ub(GLubyte red, GLubyte green, GLubyte blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3ubv: v "This method was automatically generated." "void glColor3ubv(GLubyte* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3ui: red with: green with: blue "This method was automatically generated." "void glColor3ui(GLuint red, GLuint green, GLuint blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3uiv: v "This method was automatically generated." "void glColor3uiv(GLuint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3us: red with: green with: blue "This method was automatically generated." "void glColor3us(GLushort red, GLushort green, GLushort blue);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor3usv: v "This method was automatically generated." "void glColor3usv(GLushort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4b: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4bv: v "This method was automatically generated." "void glColor4bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4d: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4dv: v "This method was automatically generated." "void glColor4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4f: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4fv: v "This method was automatically generated." "void glColor4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4i: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4i(GLint red, GLint green, GLint blue, GLint alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4iv: v "This method was automatically generated." "void glColor4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4s: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4sv: v "This method was automatically generated." "void glColor4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4ub: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4ubv: v "This method was automatically generated." "void glColor4ubv(GLubyte* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4ui: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4uiv: v "This method was automatically generated." "void glColor4uiv(GLuint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4us: red with: green with: blue with: alpha "This method was automatically generated." "void glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColor4usv: v "This method was automatically generated." "void glColor4usv(GLushort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorMask: red with: green with: blue with: alpha "This method was automatically generated." "void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorMaterial: face with: mode "This method was automatically generated." "void glColorMaterial(GLenum face, GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorSubTable: target with: start with: count with: format with: type with: data "This method was automatically generated." "void glColorSubTable(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, GLvoid* data);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorTable: target with: internalformat with: width with: format with: type with: table "This method was automatically generated." "void glColorTable(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, GLvoid* table);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorTableParameterfv: target with: pname with: params "This method was automatically generated." "void glColorTableParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glColorTableParameteriv: target with: pname with: params "This method was automatically generated." "void glColorTableParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionFilter1D: target with: internalformat with: width with: format with: type with: image "This method was automatically generated." "void glConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionFilter2D: target with: internalformat with: width with: height with: format with: type with: image "This method was automatically generated." "void glConvolutionFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionParameterf: target with: pname with: params "This method was automatically generated." "void glConvolutionParameterf(GLenum target, GLenum pname, GLfloat params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionParameterfv: target with: pname with: params "This method was automatically generated." "void glConvolutionParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionParameteri: target with: pname with: params "This method was automatically generated." "void glConvolutionParameteri(GLenum target, GLenum pname, GLint params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glConvolutionParameteriv: target with: pname with: params "This method was automatically generated." "void glConvolutionParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyColorSubTable: target with: start with: x with: y with: width "This method was automatically generated." "void glCopyColorSubTable(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyColorTable: target with: internalformat with: x with: y with: width "This method was automatically generated." "void glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyConvolutionFilter1D: target with: internalformat with: x with: y with: width "This method was automatically generated." "void glCopyConvolutionFilter1D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyConvolutionFilter2D: target with: internalformat with: x with: y with: width with: height "This method was automatically generated." "void glCopyConvolutionFilter2D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyPixels: x with: y with: width with: height with: type "This method was automatically generated." "void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyTexImage1D: target with: level with: internalformat with: x with: y with: width with: border "This method was automatically generated." "void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyTexImage2D: target with: level with: internalformat with: x with: y with: width with: height with: border "This method was automatically generated." "void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyTexSubImage1D: target with: level with: xoffset with: x with: y with: width "This method was automatically generated." "void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyTexSubImage2D: target with: level with: xoffset with: yoffset with: x with: y with: width with: height "This method was automatically generated." "void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCopyTexSubImage3D: target with: level with: xoffset with: yoffset with: zoffset with: x with: y with: width with: height "This method was automatically generated." "void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glCullFace: mode "This method was automatically generated." "void glCullFace(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDeleteLists: list with: range "This method was automatically generated." "void glDeleteLists(GLuint list, GLsizei range);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDeleteTextures: n with: textures "This method was automatically generated." "void glDeleteTextures(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDeleteTexturesEXT: n with: textures "This method was automatically generated." "void glDeleteTexturesEXT(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDepthFunc: func "This method was automatically generated." "void glDepthFunc(GLenum func);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDepthMask: flag "This method was automatically generated." "void glDepthMask(GLboolean flag);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDepthRange: zNear with: zFar "This method was automatically generated." "void glDepthRange(GLclampd zNear, GLclampd zFar);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDisable: cap "This method was automatically generated." "void glDisable(GLenum cap);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDisableClientState: array "This method was automatically generated." "void glDisableClientState(GLenum array);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawArrays: mode with: first with: count "This method was automatically generated." "void glDrawArrays(GLenum mode, GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawArraysEXT: mode with: first with: count "This method was automatically generated." "void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawBuffer: mode "This method was automatically generated." "void glDrawBuffer(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawElements: mode with: count with: type with: indices "This method was automatically generated." "void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid* indices);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawPixels: width with: height with: format with: type with: pixels "This method was automatically generated." "void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glDrawRangeElements: mode with: start with: end with: count with: type with: indices "This method was automatically generated." "void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLvoid* indices);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEdgeFlag: flag "This method was automatically generated." "void glEdgeFlag(GLboolean flag);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEdgeFlagPointer: stride with: pointer "This method was automatically generated." "void glEdgeFlagPointer(GLsizei stride, GLboolean* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEdgeFlagPointerEXT: stride with: count with: pointer "This method was automatically generated." "void glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, GLboolean* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEdgeFlagv: flag "This method was automatically generated." "void glEdgeFlagv(GLboolean* flag);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEnable: cap "This method was automatically generated." "void glEnable(GLenum cap);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEnableClientState: array "This method was automatically generated." "void glEnableClientState(GLenum array);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEnd "This method was automatically generated." "void glEnd();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEndList "This method was automatically generated." "void glEndList();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord1d: u "This method was automatically generated." "void glEvalCoord1d(GLdouble u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord1dv: u "This method was automatically generated." "void glEvalCoord1dv(GLdouble* u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord1f: u "This method was automatically generated." "void glEvalCoord1f(GLfloat u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord1fv: u "This method was automatically generated." "void glEvalCoord1fv(GLfloat* u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord2d: u with: v "This method was automatically generated." "void glEvalCoord2d(GLdouble u, GLdouble v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord2dv: u "This method was automatically generated." "void glEvalCoord2dv(GLdouble* u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord2f: u with: v "This method was automatically generated." "void glEvalCoord2f(GLfloat u, GLfloat v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalCoord2fv: u "This method was automatically generated." "void glEvalCoord2fv(GLfloat* u);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalMesh1: mode with: i1 with: i2 "This method was automatically generated." "void glEvalMesh1(GLenum mode, GLint i1, GLint i2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalMesh2: mode with: i1 with: i2 with: j1 with: j2 "This method was automatically generated." "void glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalPoint1: i "This method was automatically generated." "void glEvalPoint1(GLint i);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glEvalPoint2: i with: j "This method was automatically generated." "void glEvalPoint2(GLint i, GLint j);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFeedbackBuffer: size with: type with: buffer "This method was automatically generated." "void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat* buffer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFinish "This method was automatically generated." "void glFinish();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFlush "This method was automatically generated." "void glFlush();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFogf: pname with: param "This method was automatically generated." "void glFogf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFogfv: pname with: params "This method was automatically generated." "void glFogfv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFogi: pname with: param "This method was automatically generated." "void glFogi(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFogiv: pname with: params "This method was automatically generated." "void glFogiv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFrontFace: mode "This method was automatically generated." "void glFrontFace(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glFrustum: left with: right with: bottom with: top with: zNear with: zFar "This method was automatically generated." "void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGenLists: range "This method was automatically generated." "GLuint glGenLists(GLsizei range);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGenTextures: n with: textures "This method was automatically generated." "void glGenTextures(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGenTexturesEXT: n with: textures "This method was automatically generated." "void glGenTexturesEXT(GLsizei n, GLuint* textures);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetBooleanv: pname with: params "This method was automatically generated." "void glGetBooleanv(GLenum pname, GLboolean* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetClipPlane: plane with: equation "This method was automatically generated." "void glGetClipPlane(GLenum plane, GLdouble* equation);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetColorTable: target with: format with: type with: table "This method was automatically generated." "void glGetColorTable(GLenum target, GLenum format, GLenum type, GLvoid* table);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetColorTableParameterfv: target with: pname with: params "This method was automatically generated." "void glGetColorTableParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetColorTableParameteriv: target with: pname with: params "This method was automatically generated." "void glGetColorTableParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetConvolutionFilter: target with: format with: type with: image "This method was automatically generated." "void glGetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid* image);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetConvolutionParameterfv: target with: pname with: params "This method was automatically generated." "void glGetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetConvolutionParameteriv: target with: pname with: params "This method was automatically generated." "void glGetConvolutionParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetDoublev: pname with: params "This method was automatically generated." "void glGetDoublev(GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetError "This method was automatically generated." "GLenum glGetError();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetFloatv: pname with: params "This method was automatically generated." "void glGetFloatv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetHistogram: target with: reset with: format with: type with: values "This method was automatically generated." "void glGetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetHistogramParameterfv: target with: pname with: params "This method was automatically generated." "void glGetHistogramParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetHistogramParameteriv: target with: pname with: params "This method was automatically generated." "void glGetHistogramParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetIntegerv: pname with: params "This method was automatically generated." "void glGetIntegerv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetLightfv: light with: pname with: params "This method was automatically generated." "void glGetLightfv(GLenum light, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetLightiv: light with: pname with: params "This method was automatically generated." "void glGetLightiv(GLenum light, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMapdv: target with: query with: v "This method was automatically generated." "void glGetMapdv(GLenum target, GLenum query, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMapfv: target with: query with: v "This method was automatically generated." "void glGetMapfv(GLenum target, GLenum query, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMapiv: target with: query with: v "This method was automatically generated." "void glGetMapiv(GLenum target, GLenum query, GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMaterialfv: face with: pname with: params "This method was automatically generated." "void glGetMaterialfv(GLenum face, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMaterialiv: face with: pname with: params "This method was automatically generated." "void glGetMaterialiv(GLenum face, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMinmax: target with: reset with: format with: type with: values "This method was automatically generated." "void glGetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMinmaxParameterfv: target with: pname with: params "This method was automatically generated." "void glGetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetMinmaxParameteriv: target with: pname with: params "This method was automatically generated." "void glGetMinmaxParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPixelMapfv: map with: values "This method was automatically generated." "void glGetPixelMapfv(GLenum map, GLfloat* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPixelMapuiv: map with: values "This method was automatically generated." "void glGetPixelMapuiv(GLenum map, GLuint* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPixelMapusv: map with: values "This method was automatically generated." "void glGetPixelMapusv(GLenum map, GLushort* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPointerv: pname with: params "This method was automatically generated." "void glGetPointerv(GLenum pname, GLvoid** params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPointervEXT: pname with: params "This method was automatically generated." "void glGetPointervEXT(GLenum pname, GLvoid** params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetPolygonStipple: mask "This method was automatically generated." "void glGetPolygonStipple(GLubyte* mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetSeparableFilter: target with: format with: type with: row with: column with: span "This method was automatically generated." "void glGetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid* row, GLvoid* column, GLvoid* span);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetString: name "This method was automatically generated." "GLubyte* glGetString(GLenum name);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexEnvfv: target with: pname with: params "This method was automatically generated." "void glGetTexEnvfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexEnviv: target with: pname with: params "This method was automatically generated." "void glGetTexEnviv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexGendv: coord with: pname with: params "This method was automatically generated." "void glGetTexGendv(GLenum coord, GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexGenfv: coord with: pname with: params "This method was automatically generated." "void glGetTexGenfv(GLenum coord, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexGeniv: coord with: pname with: params "This method was automatically generated." "void glGetTexGeniv(GLenum coord, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexImage: target with: level with: format with: type with: pixels "This method was automatically generated." "void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexLevelParameterfv: target with: level with: pname with: params "This method was automatically generated." "void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexLevelParameteriv: target with: level with: pname with: params "This method was automatically generated." "void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexParameterfv: target with: pname with: params "This method was automatically generated." "void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glGetTexParameteriv: target with: pname with: params "This method was automatically generated." "void glGetTexParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glHint: target with: mode "This method was automatically generated." "void glHint(GLenum target, GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glHistogram: target with: width with: internalformat with: sink "This method was automatically generated." "void glHistogram(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexMask: mask "This method was automatically generated." "void glIndexMask(GLuint mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexPointer: type with: stride with: pointer "This method was automatically generated." "void glIndexPointer(GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexPointerEXT: type with: stride with: count with: pointer "This method was automatically generated." "void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexd: c "This method was automatically generated." "void glIndexd(GLdouble c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexdv: c "This method was automatically generated." "void glIndexdv(GLdouble* c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexf: c "This method was automatically generated." "void glIndexf(GLfloat c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexfv: c "This method was automatically generated." "void glIndexfv(GLfloat* c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexi: c "This method was automatically generated." "void glIndexi(GLint c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexiv: c "This method was automatically generated." "void glIndexiv(GLint* c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexs: c "This method was automatically generated." "void glIndexs(GLshort c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexsv: c "This method was automatically generated." "void glIndexsv(GLshort* c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexub: c "This method was automatically generated." "void glIndexub(GLubyte c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIndexubv: c "This method was automatically generated." "void glIndexubv(GLubyte* c);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glInitNames "This method was automatically generated." "void glInitNames();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glInterleavedArrays: format with: stride with: pointer "This method was automatically generated." "void glInterleavedArrays(GLenum format, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIsEnabled: cap "This method was automatically generated." "GLboolean glIsEnabled(GLenum cap);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIsList: list "This method was automatically generated." "GLboolean glIsList(GLuint list);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIsTexture: texture "This method was automatically generated." "GLboolean glIsTexture(GLuint texture);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glIsTextureEXT: texture "This method was automatically generated." "GLboolean glIsTextureEXT(GLuint texture);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightModelf: pname with: param "This method was automatically generated." "void glLightModelf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightModelfv: pname with: params "This method was automatically generated." "void glLightModelfv(GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightModeli: pname with: param "This method was automatically generated." "void glLightModeli(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightModeliv: pname with: params "This method was automatically generated." "void glLightModeliv(GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightf: light with: pname with: param "This method was automatically generated." "void glLightf(GLenum light, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightfv: light with: pname with: params "This method was automatically generated." "void glLightfv(GLenum light, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLighti: light with: pname with: param "This method was automatically generated." "void glLighti(GLenum light, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLightiv: light with: pname with: params "This method was automatically generated." "void glLightiv(GLenum light, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLineStipple: factor with: pattern "This method was automatically generated." "void glLineStipple(GLint factor, GLushort pattern);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLineWidth: width "This method was automatically generated." "void glLineWidth(GLfloat width);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glListBase: base "This method was automatically generated." "void glListBase(GLuint base);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLoadIdentity "This method was automatically generated." "void glLoadIdentity();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLoadMatrixd: m "This method was automatically generated." "void glLoadMatrixd(GLdouble* m);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLoadMatrixf: m "This method was automatically generated." "void glLoadMatrixf(GLfloat* m);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLoadName: name "This method was automatically generated." "void glLoadName(GLuint name);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLockArraysEXT: first with: count "This method was automatically generated." "void glLockArraysEXT(GLint first, GLsizei count);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glLogicOp: opcode "This method was automatically generated." "void glLogicOp(GLenum opcode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMap1d: target with: u1 with: u2 with: stride with: order with: points "This method was automatically generated." "void glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, GLdouble* points);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMap1f: target with: u1 with: u2 with: stride with: order with: points "This method was automatically generated." "void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, GLfloat* points);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMap2d: target with: u1 with: u2 with: ustride with: uorder with: v1 with: v2 with: vstride with: vorder with: points "This method was automatically generated." "void glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble* points);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMap2f: target with: u1 with: u2 with: ustride with: uorder with: v1 with: v2 with: vstride with: vorder with: points "This method was automatically generated." "void glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat* points);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMapGrid1d: un with: u1 with: u2 "This method was automatically generated." "void glMapGrid1d(GLint un, GLdouble u1, GLdouble u2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMapGrid1f: un with: u1 with: u2 "This method was automatically generated." "void glMapGrid1f(GLint un, GLfloat u1, GLfloat u2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMapGrid2d: un with: u1 with: u2 with: vn with: v1 with: v2 "This method was automatically generated." "void glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMapGrid2f: un with: u1 with: u2 with: vn with: v1 with: v2 "This method was automatically generated." "void glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMaterialf: face with: pname with: param "This method was automatically generated." "void glMaterialf(GLenum face, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMaterialfv: face with: pname with: params "This method was automatically generated." "void glMaterialfv(GLenum face, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMateriali: face with: pname with: param "This method was automatically generated." "void glMateriali(GLenum face, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMaterialiv: face with: pname with: params "This method was automatically generated." "void glMaterialiv(GLenum face, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMatrixMode: mode "This method was automatically generated." "void glMatrixMode(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMinmax: target with: internalformat with: sink "This method was automatically generated." "void glMinmax(GLenum target, GLenum internalformat, GLboolean sink);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultMatrixd: m "This method was automatically generated." "void glMultMatrixd(GLdouble* m);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultMatrixf: m "This method was automatically generated." "void glMultMatrixf(GLfloat* m);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1dARB: target with: s "This method was automatically generated." "void glMultiTexCoord1dARB(GLenum target, GLdouble s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1dvARB: target with: v "This method was automatically generated." "void glMultiTexCoord1dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1fARB: target with: s "This method was automatically generated." "void glMultiTexCoord1fARB(GLenum target, GLfloat s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1fvARB: target with: v "This method was automatically generated." "void glMultiTexCoord1fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1iARB: target with: s "This method was automatically generated." "void glMultiTexCoord1iARB(GLenum target, GLint s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1ivARB: target with: v "This method was automatically generated." "void glMultiTexCoord1ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1sARB: target with: s "This method was automatically generated." "void glMultiTexCoord1sARB(GLenum target, GLshort s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord1svARB: target with: v "This method was automatically generated." "void glMultiTexCoord1svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2dARB: target with: s with: t "This method was automatically generated." "void glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2dvARB: target with: v "This method was automatically generated." "void glMultiTexCoord2dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2fARB: target with: s with: t "This method was automatically generated." "void glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2fvARB: target with: v "This method was automatically generated." "void glMultiTexCoord2fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2iARB: target with: s with: t "This method was automatically generated." "void glMultiTexCoord2iARB(GLenum target, GLint s, GLint t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2ivARB: target with: v "This method was automatically generated." "void glMultiTexCoord2ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2sARB: target with: s with: t "This method was automatically generated." "void glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord2svARB: target with: v "This method was automatically generated." "void glMultiTexCoord2svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3dARB: target with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3dvARB: target with: v "This method was automatically generated." "void glMultiTexCoord3dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3fARB: target with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3fvARB: target with: v "This method was automatically generated." "void glMultiTexCoord3fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3iARB: target with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3ivARB: target with: v "This method was automatically generated." "void glMultiTexCoord3ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3sARB: target with: s with: t with: r "This method was automatically generated." "void glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord3svARB: target with: v "This method was automatically generated." "void glMultiTexCoord3svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4dARB: target with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4dvARB: target with: v "This method was automatically generated." "void glMultiTexCoord4dvARB(GLenum target, GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4fARB: target with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4fvARB: target with: v "This method was automatically generated." "void glMultiTexCoord4fvARB(GLenum target, GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4iARB: target with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4ivARB: target with: v "This method was automatically generated." "void glMultiTexCoord4ivARB(GLenum target, GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4sARB: target with: s with: t with: r with: q "This method was automatically generated." "void glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glMultiTexCoord4svARB: target with: v "This method was automatically generated." "void glMultiTexCoord4svARB(GLenum target, GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glNewList: list with: mode "This method was automatically generated." "void glNewList(GLuint list, GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glNormal3b: nx with: ny with: nz "This method was automatically generated." "void glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:48'! glNormal3bv: v "This method was automatically generated." "void glNormal3bv(GLbyte* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3d: nx with: ny with: nz "This method was automatically generated." "void glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3dv: v "This method was automatically generated." "void glNormal3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3f: nx with: ny with: nz "This method was automatically generated." "void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3fv: v "This method was automatically generated." "void glNormal3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3i: nx with: ny with: nz "This method was automatically generated." "void glNormal3i(GLint nx, GLint ny, GLint nz);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3iv: v "This method was automatically generated." "void glNormal3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3s: nx with: ny with: nz "This method was automatically generated." "void glNormal3s(GLshort nx, GLshort ny, GLshort nz);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormal3sv: v "This method was automatically generated." "void glNormal3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormalPointer: type with: stride with: pointer "This method was automatically generated." "void glNormalPointer(GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glNormalPointerEXT: type with: stride with: count with: pointer "This method was automatically generated." "void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glOrtho: left with: right with: bottom with: top with: zNear with: zFar "This method was automatically generated." "void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPassThrough: token "This method was automatically generated." "void glPassThrough(GLfloat token);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelMapfv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapfv(GLenum map, GLint mapsize, GLfloat* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelMapuiv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapuiv(GLenum map, GLint mapsize, GLuint* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelMapusv: map with: mapsize with: values "This method was automatically generated." "void glPixelMapusv(GLenum map, GLint mapsize, GLushort* values);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelStoref: pname with: param "This method was automatically generated." "void glPixelStoref(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelStorei: pname with: param "This method was automatically generated." "void glPixelStorei(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelTransferf: pname with: param "This method was automatically generated." "void glPixelTransferf(GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelTransferi: pname with: param "This method was automatically generated." "void glPixelTransferi(GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPixelZoom: xfactor with: yfactor "This method was automatically generated." "void glPixelZoom(GLfloat xfactor, GLfloat yfactor);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPointSize: size "This method was automatically generated." "void glPointSize(GLfloat size);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPolygonMode: face with: mode "This method was automatically generated." "void glPolygonMode(GLenum face, GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPolygonOffset: factor with: units "This method was automatically generated." "void glPolygonOffset(GLfloat factor, GLfloat units);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPolygonStipple: mask "This method was automatically generated." "void glPolygonStipple(GLubyte* mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPopAttrib "This method was automatically generated." "void glPopAttrib();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPopClientAttrib "This method was automatically generated." "void glPopClientAttrib();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPopMatrix "This method was automatically generated." "void glPopMatrix();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPopName "This method was automatically generated." "void glPopName();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPrioritizeTextures: n with: textures with: priorities "This method was automatically generated." "void glPrioritizeTextures(GLsizei n, GLuint* textures, GLclampf* priorities);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPushAttrib: mask "This method was automatically generated." "void glPushAttrib(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPushClientAttrib: mask "This method was automatically generated." "void glPushClientAttrib(GLbitfield mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPushMatrix "This method was automatically generated." "void glPushMatrix();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glPushName: name "This method was automatically generated." "void glPushName(GLuint name);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2d: x with: y "This method was automatically generated." "void glRasterPos2d(GLdouble x, GLdouble y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2dv: v "This method was automatically generated." "void glRasterPos2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2f: x with: y "This method was automatically generated." "void glRasterPos2f(GLfloat x, GLfloat y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2fv: v "This method was automatically generated." "void glRasterPos2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2i: x with: y "This method was automatically generated." "void glRasterPos2i(GLint x, GLint y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2iv: v "This method was automatically generated." "void glRasterPos2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2s: x with: y "This method was automatically generated." "void glRasterPos2s(GLshort x, GLshort y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos2sv: v "This method was automatically generated." "void glRasterPos2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3d: x with: y with: z "This method was automatically generated." "void glRasterPos3d(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3dv: v "This method was automatically generated." "void glRasterPos3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3f: x with: y with: z "This method was automatically generated." "void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3fv: v "This method was automatically generated." "void glRasterPos3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3i: x with: y with: z "This method was automatically generated." "void glRasterPos3i(GLint x, GLint y, GLint z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3iv: v "This method was automatically generated." "void glRasterPos3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3s: x with: y with: z "This method was automatically generated." "void glRasterPos3s(GLshort x, GLshort y, GLshort z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos3sv: v "This method was automatically generated." "void glRasterPos3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4d: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4dv: v "This method was automatically generated." "void glRasterPos4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4f: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4fv: v "This method was automatically generated." "void glRasterPos4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4i: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4i(GLint x, GLint y, GLint z, GLint w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4iv: v "This method was automatically generated." "void glRasterPos4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4s: x with: y with: z with: w "This method was automatically generated." "void glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRasterPos4sv: v "This method was automatically generated." "void glRasterPos4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glReadBuffer: mode "This method was automatically generated." "void glReadBuffer(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glReadPixels: x with: y with: width with: height with: format with: type with: pixels "This method was automatically generated." "void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectd: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectdv: v1 with: v2 "This method was automatically generated." "void glRectdv(GLdouble* v1, GLdouble* v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectf: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectfv: v1 with: v2 "This method was automatically generated." "void glRectfv(GLfloat* v1, GLfloat* v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRecti: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRecti(GLint x1, GLint y1, GLint x2, GLint y2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectiv: v1 with: v2 "This method was automatically generated." "void glRectiv(GLint* v1, GLint* v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRects: x1 with: y1 with: x2 with: y2 "This method was automatically generated." "void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRectsv: v1 with: v2 "This method was automatically generated." "void glRectsv(GLshort* v1, GLshort* v2);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRenderMode: mode "This method was automatically generated." "GLint glRenderMode(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glResetHistogram: target "This method was automatically generated." "void glResetHistogram(GLenum target);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glResetMinmax: target "This method was automatically generated." "void glResetMinmax(GLenum target);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRotated: angle with: x with: y with: z "This method was automatically generated." "void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glRotatef: angle with: x with: y with: z "This method was automatically generated." "void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glScaled: x with: y with: z "This method was automatically generated." "void glScaled(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glScalef: x with: y with: z "This method was automatically generated." "void glScalef(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glScissor: x with: y with: width with: height "This method was automatically generated." "void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glSelectBuffer: size with: buffer "This method was automatically generated." "void glSelectBuffer(GLsizei size, GLuint* buffer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glSeparableFilter2D: target with: internalformat with: width with: height with: format with: type with: row with: column "This method was automatically generated." "void glSeparableFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* row, GLvoid* column);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glShadeModel: mode "This method was automatically generated." "void glShadeModel(GLenum mode);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glStencilFunc: func with: ref with: mask "This method was automatically generated." "void glStencilFunc(GLenum func, GLint ref, GLuint mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glStencilMask: mask "This method was automatically generated." "void glStencilMask(GLuint mask);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glStencilOp: fail with: zfail with: zpass "This method was automatically generated." "void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1d: s "This method was automatically generated." "void glTexCoord1d(GLdouble s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1dv: v "This method was automatically generated." "void glTexCoord1dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1f: s "This method was automatically generated." "void glTexCoord1f(GLfloat s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1fv: v "This method was automatically generated." "void glTexCoord1fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1i: s "This method was automatically generated." "void glTexCoord1i(GLint s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1iv: v "This method was automatically generated." "void glTexCoord1iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1s: s "This method was automatically generated." "void glTexCoord1s(GLshort s);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord1sv: v "This method was automatically generated." "void glTexCoord1sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2d: s with: t "This method was automatically generated." "void glTexCoord2d(GLdouble s, GLdouble t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2dv: v "This method was automatically generated." "void glTexCoord2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2f: s with: t "This method was automatically generated." "void glTexCoord2f(GLfloat s, GLfloat t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2fv: v "This method was automatically generated." "void glTexCoord2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2i: s with: t "This method was automatically generated." "void glTexCoord2i(GLint s, GLint t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2iv: v "This method was automatically generated." "void glTexCoord2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2s: s with: t "This method was automatically generated." "void glTexCoord2s(GLshort s, GLshort t);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord2sv: v "This method was automatically generated." "void glTexCoord2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3d: s with: t with: r "This method was automatically generated." "void glTexCoord3d(GLdouble s, GLdouble t, GLdouble r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3dv: v "This method was automatically generated." "void glTexCoord3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3f: s with: t with: r "This method was automatically generated." "void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3fv: v "This method was automatically generated." "void glTexCoord3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3i: s with: t with: r "This method was automatically generated." "void glTexCoord3i(GLint s, GLint t, GLint r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3iv: v "This method was automatically generated." "void glTexCoord3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3s: s with: t with: r "This method was automatically generated." "void glTexCoord3s(GLshort s, GLshort t, GLshort r);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord3sv: v "This method was automatically generated." "void glTexCoord3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4d: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4dv: v "This method was automatically generated." "void glTexCoord4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4f: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4fv: v "This method was automatically generated." "void glTexCoord4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4i: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4i(GLint s, GLint t, GLint r, GLint q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4iv: v "This method was automatically generated." "void glTexCoord4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4s: s with: t with: r with: q "This method was automatically generated." "void glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoord4sv: v "This method was automatically generated." "void glTexCoord4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoordPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexCoordPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexEnvf: target with: pname with: param "This method was automatically generated." "void glTexEnvf(GLenum target, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexEnvfv: target with: pname with: params "This method was automatically generated." "void glTexEnvfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexEnvi: target with: pname with: param "This method was automatically generated." "void glTexEnvi(GLenum target, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexEnviv: target with: pname with: params "This method was automatically generated." "void glTexEnviv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGend: coord with: pname with: param "This method was automatically generated." "void glTexGend(GLenum coord, GLenum pname, GLdouble param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGendv: coord with: pname with: params "This method was automatically generated." "void glTexGendv(GLenum coord, GLenum pname, GLdouble* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGenf: coord with: pname with: param "This method was automatically generated." "void glTexGenf(GLenum coord, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGenfv: coord with: pname with: params "This method was automatically generated." "void glTexGenfv(GLenum coord, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGeni: coord with: pname with: param "This method was automatically generated." "void glTexGeni(GLenum coord, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexGeniv: coord with: pname with: params "This method was automatically generated." "void glTexGeniv(GLenum coord, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexImage1D: target with: level with: internalformat with: width with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexImage2D: target with: level with: internalformat with: width with: height with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexImage3D: target with: level with: internalformat with: width with: height with: depth with: border with: format with: type with: pixels "This method was automatically generated." "void glTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexParameterf: target with: pname with: param "This method was automatically generated." "void glTexParameterf(GLenum target, GLenum pname, GLfloat param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexParameterfv: target with: pname with: params "This method was automatically generated." "void glTexParameterfv(GLenum target, GLenum pname, GLfloat* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexParameteri: target with: pname with: param "This method was automatically generated." "void glTexParameteri(GLenum target, GLenum pname, GLint param);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexParameteriv: target with: pname with: params "This method was automatically generated." "void glTexParameteriv(GLenum target, GLenum pname, GLint* params);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexSubImage1D: target with: level with: xoffset with: width with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexSubImage2D: target with: level with: xoffset with: yoffset with: width with: height with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTexSubImage3D: target with: level with: xoffset with: yoffset with: zoffset with: width with: height with: depth with: format with: type with: pixels "This method was automatically generated." "void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid* pixels);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTranslated: x with: y with: z "This method was automatically generated." "void glTranslated(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glTranslatef: x with: y with: z "This method was automatically generated." "void glTranslatef(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glUnlockArraysEXT "This method was automatically generated." "void glUnlockArraysEXT();" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2d: x with: y "This method was automatically generated." "void glVertex2d(GLdouble x, GLdouble y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2dv: v "This method was automatically generated." "void glVertex2dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2f: x with: y "This method was automatically generated." "void glVertex2f(GLfloat x, GLfloat y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2fv: v "This method was automatically generated." "void glVertex2fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2i: x with: y "This method was automatically generated." "void glVertex2i(GLint x, GLint y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2iv: v "This method was automatically generated." "void glVertex2iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2s: x with: y "This method was automatically generated." "void glVertex2s(GLshort x, GLshort y);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex2sv: v "This method was automatically generated." "void glVertex2sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3d: x with: y with: z "This method was automatically generated." "void glVertex3d(GLdouble x, GLdouble y, GLdouble z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3dv: v "This method was automatically generated." "void glVertex3dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3f: x with: y with: z "This method was automatically generated." "void glVertex3f(GLfloat x, GLfloat y, GLfloat z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3fv: v "This method was automatically generated." "void glVertex3fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3i: x with: y with: z "This method was automatically generated." "void glVertex3i(GLint x, GLint y, GLint z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3iv: v "This method was automatically generated." "void glVertex3iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3s: x with: y with: z "This method was automatically generated." "void glVertex3s(GLshort x, GLshort y, GLshort z);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex3sv: v "This method was automatically generated." "void glVertex3sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4d: x with: y with: z with: w "This method was automatically generated." "void glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4dv: v "This method was automatically generated." "void glVertex4dv(GLdouble* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4f: x with: y with: z with: w "This method was automatically generated." "void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4fv: v "This method was automatically generated." "void glVertex4fv(GLfloat* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4i: x with: y with: z with: w "This method was automatically generated." "void glVertex4i(GLint x, GLint y, GLint z, GLint w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4iv: v "This method was automatically generated." "void glVertex4iv(GLint* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4s: x with: y with: z with: w "This method was automatically generated." "void glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertex4sv: v "This method was automatically generated." "void glVertex4sv(GLshort* v);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertexPointer: size with: type with: stride with: pointer "This method was automatically generated." "void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glVertexPointerEXT: size with: type with: stride with: count with: pointer "This method was automatically generated." "void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, GLvoid* pointer);" ^self externalCallFailed! ! !GLXUnixX11BE methodsFor: 'OpenGL API' stamp: 'bf 10/21/2002 19:49'! glViewport: x with: y with: width with: height "This method was automatically generated." "void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);" ^self externalCallFailed! ! !GLXUnixX11LE methodsFor: 'intitialize' stamp: 'ikp 2/3/2003 17:00'! beginFrame super beginFrame. self glPixelStorei: GLUnpackLsbFirst with: 0. ! ! !GLXUnixX11LE methodsFor: 'accessing' stamp: 'ikp 2/3/2003 17:01'! imagePixelType32 ^GLUnsignedByte! ! !GLXUnixX11LE methodsFor: 'accessing' stamp: 'ikp 2/3/2003 17:02'! texturePixelType ^GLUnsignedByte! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'ikp 2/3/2003 16:56'! windowSystemName "Smalltalk windowSystemName" "Answer the name of the window system currently being used for display." ^self getSystemAttribute: 1005! ! ================================================ FILE: vm/src/from_squeak/unix/misc/System-Tracing.2.cs ================================================ 'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6548] on 31 March 2005 at 11:00:30 am'! "Change Set: System-Tracing Date: 19 October 2004 Author: Anthony Hannan, Stephen Pair, Dan Ingalls This changeSet defines SystemTracer2 (ajh), a more flexible and reliable SystemTracer. It also includes RehashingSystemTracer (svp) which allows changing identityHashes and SystemTracer64 (di) which will write 64-bit images. If you find tracing to be unduly slow, locate and fileIn NoAssocDict-ajh for faster dictionary management."! Stream subclass: #PositionableStream instanceVariableNames: 'collection position readLimit ' classVariableNames: 'IntBuffer ' poolDictionaries: '' category: 'Collections-Streams'! Object subclass: #SystemTracer2 instanceVariableNames: 'swapMap oopMap traceQueue byteStream nextChunk displayBox nilOop wordSize' classVariableNames: 'LargeIdentityDict' poolDictionaries: '' category: 'System-Tracing'! !SystemTracer2 commentStamp: '' prior: 0! This is a rewrite of SystemTracer. It makes it easier to convert images, although it requires more space. Use it by subclassing it and overriding desired methods in: 'object relacement' to create replacement objects for desired objects (swapMap); 'object encoding' to specify bit representation of objects; 'clone startup' to initialize the new image on first startup. The default is to trace and write the system in V3 image format. To run the tracer do "YourTracerSubclass writeImage: 'newImageFile.image'". The .changes file will be copied as well. The tracer requires a lot of space to run since it is keeps an oopMap for every object in the system, and a swapMap for every object replacement. And because these maps are very large and Squeak has a poor identityHash function, the tracer runs slowly. Structure: swapMap IdentityDictionary (oldObject -> newObject) When an object is visited, swapMap is checked to see if it has a replacement, and if so the new object is traced and written instead of the original. You can add to the swapMap in initSwapMapPreShutdown or initSwapMapPostShutdown before tracing starts, or you can add to it during tracing in convert:pointer:field:. The tracer automatically adds itself and the active process to swapMap so it own execution won't be traced (pvtWriteImageConverted). oopMap IdentityDictionary (object -> oop) Maps objects to their new oops. The tracer checks this in case a visited object has already been reached. traceQueue OrderedCollection (object) Queue of objects that have been reached by the tracer and assigned a new oop, but have not yet been written and traced themselves. The image is traced by adding specialObjectArray to the queue, then repeatedly removing the first object and tracing it until the queue is empty. An object is traced by adding all its field values (including the class field) that haven't already been reached (oopMap) to the queue. byteStream FileStream The target image file that gets written to during tracing. Oops equal stream positions. nextChunk Integer Oop (minus header size) assigned to the next object reached by the tracer. displayBox Rectangle Bounds of Squeak window; written in image header. nilOop Integer Oop of new nil object. Need here since nil can't be added as a key to oopMap dictionary. Class Vars: LargeIdentityDict IdentityDictionary class The tracer uses this class for its large maps, so link your favorite large dictionary class to this. ! SystemTracer2 subclass: #RehashingSystemTracer instanceVariableNames: 'lastHash hashMap' classVariableNames: '' poolDictionaries: '' category: 'System-Tracing'! !RehashingSystemTracer commentStamp: 'svp 8/23/2002 20:28' prior: 0! I am just like SystemTracer2, except that I write new identity hashes for objects. I rehash some special sets (like MethodDictionaries) prior to writing the clone image, and the clone image will rehash all objects when it starts up. My instance variables: lastHash - the lastHash that was assigned...I use the same algorithm to generate hashes as the VM hashMap - A dictionary of all assigned identity hashes Subclasses can extend me if they need to write new images with modified hash values.! SystemTracer2 subclass: #SystemTracer64 instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'System-Tracing'! !SystemTracer64 commentStamp: '' prior: 0! This variant of SystemTracer will write an image designed to be loaded and run on 64-bit machines. Note that this version does not do rehashing, in order that it can avoid the huge rehash at startup that takes forever in simulation. It is intended that you do one write with SystemTracer2, and then an *identical* write with SystemTracer64. Then you can write execution logs from the 32-bit version and use them to verify the 64-bit version. This first pass attempts to make minimal changes to the Tracer framework, by simply padding most fields with 0 in the high 32 bits, and sign-extending the small integers. The object header written is as follows... Squeak 3.8 64-bit header 3 bits reserved for gc (mark, old, dirty) same 12 bits object hash (for HashSets) same 5 bits compact class index same 4 bits object format same 6 bits object size in 32-bit words 5 bits object size in 64-bit words 1 bit high bit of the 3-bit size residue; the low 2 bits are in format as before 2 bits header type (0: 3-word, 1: 2-word, same 2: forbidden, 3: 1-word) Note that as of this writing, the change for 64-bit modulus of bitmaps has not yet been made. While we would never want to live with this header format, it makes only one very local change: ! !ProtoObject methodsFor: 'system primitives' stamp: 'ajh 7/12/2001 19:58'! basicSize "Primitive. Answer the number of indexable variables in the receiver. This value is the same as the largest legal subscript. Essential. Do not override in any subclass. See Object documentation whatIsAPrimitive." "The number of indexable fields of fixed-length objects is 0" ^ 0! ! !ProtoObject methodsFor: 'system tracing' stamp: 'ajh 4/3/2004 07:07'! forSystemTracer: swapMap "May want to create a new object and add it to swapMap under self. Be sure to check that self has not already been added to swapMap, since self may receive this message multiple times if it is referenced by multiple objects. Return the new object that is to substitute for self, or self is there is no substitute. It is ok for the substitute to have pointers to objects that still need to be converted. They will be converted when the substitute is traced by the system tracer. Alternatively, you can convert them right away by sending forSystemTracer: to them. If you know only certain classes will be converted then it may be faster to override this method in subclasses that get converted and make this method just return self, but be sure you don't neglect objects that are added to the swapMap by the tracer itself (see references to swapMap in SystemTracer2)" ^ swapMap at: self ifAbsent: [self]! ! !ProtoObject methodsFor: 'system tracing' stamp: 'ajh 8/20/2002 23:27'! forSystemTracer: swapMap pointer: pointer field: index "May want to create a new object and add it to swapMap under self. pointer is the object pointing to obj via its field at index. You may want to convert obj to different objects depending on who is pointing to it. If this is the case you will want to remember the multiple mappings in swapMap. You can do this by keeping another map inside the swapMap keyed at a special symbol" ^ self forSystemTracer: swapMap! ! !ProtoObject methodsFor: '*systemtracer2' stamp: 'svp 8/22/2002 21:45'! rehashWithoutBecome "Do nothing. Here so sending this to a Set does not have to do a time consuming respondsTo:" ^self rehash! ! !Object methodsFor: 'testing' stamp: 'di 5/4/2004 18:07'! isContextPart ^ false! ! !Behavior methodsFor: 'system tracing' stamp: 'ajh 1/18/2002 20:12'! indexIfCompactForConversion "subclasses may override this to change cc index during conversion. You must update the compact classes array yourself" ^ self indexIfCompact! ! !CompiledMethod class methodsFor: 'class initialization' stamp: 'ajh 7/7/2001 16:37'! fullFrameSize ^ LargeFrame! ! !ContextPart methodsFor: 'query' stamp: 'di 5/4/2004 17:44'! isContextPart ^ true! ! !BlockContext methodsFor: 'private' stamp: 'ajh 7/7/2001 16:44'! frameSize ^ home ifNil: [CompiledMethod fullFrameSize] ifNotNil: [self method frameSize]! ! !MethodContext methodsFor: 'private' stamp: 'ajh 7/7/2001 16:44'! frameSize ^ method ifNil: [CompiledMethod fullFrameSize] ifNotNil: [self method frameSize]! ! !PositionableStream methodsFor: 'nonhomogeneous accessing' stamp: 'ajh 10/13/2001 15:11'! nextLongPut: positiveInt "Write positiveInt in the next four bytes preserving the current endianess" self nextPutAll: (IntBuffer at: 1 put: positiveInt; yourself) ! ! !PositionableStream class methodsFor: 'instance creation' stamp: 'ajh 10/13/2001 15:12'! initialize IntBuffer _ WordArray new: 1.! ! !Set methodsFor: 'private' stamp: 'svp 8/23/2002 09:24'! compare: element with: object ^element = object! ! !Set methodsFor: 'private' stamp: 'svp 8/23/2002 09:48'! findElementOrNil: anObject hash: hash "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." | index | index _ self scanFor: anObject hash: hash. index > 0 ifTrue: [^index]. "Bad scene. Neither have we found a matching element nor even an empty slot. No hashed set is ever supposed to get completely full." self error: 'There is no free space in this set!!'.! ! !Set methodsFor: 'private' stamp: 'svp 8/23/2002 09:47'! scanFor: anObject hash: hash "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." ^self scanFor: anObject startingAt: (hash \\ array size) + 1 ! ! !Set methodsFor: 'private' stamp: 'svp 8/23/2002 10:09'! scanFor: anObject startingAt: start "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element | "Search from (hash mod size) to the end." start to: array size do: [:index | ((element _ array at: index) == nil or: [self compare: element with: anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == nil or: [self compare: element with: anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !IdentityDictionary methodsFor: '*systemtracer2' stamp: 'ajh 4/3/2004 18:33'! cloneUsingHashesFrom: tracer | object newDict | newDict := self shallowCopy. newDict withArray: (Array new: array size). 1 to: array size do: [ :i | object := array at: i. object ifNotNil: [newDict noCheckAdd: object hash: (tracer newHashFor: object key)]]. ^newDict! ! !IdentityDictionary methodsFor: '*systemtracer2' stamp: 'svp 8/23/2002 18:36'! noCheckAdd: anObject hash: hash "Variant to allow the hash to be specified by the caller. 8/23/02 svp" array at: (self findElementOrNil: anObject key hash: hash) put: anObject. tally _ tally + 1! ! !MethodDictionary methodsFor: 'private' stamp: 'svp 8/23/2002 17:32'! scanFor: anObject startingAt: start "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements." | element | "Search from (hash mod size) to the end." start to: array size do: [:index | ((element _ self basicAt: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ self basicAt: index) == nil or: [element == anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !MethodDictionary methodsFor: '*systemtracer2' stamp: 'ajh 4/3/2004 18:33'! cloneUsingHashesFrom: tracer | newDict key | newDict := self class basicNew: self basicSize. newDict init: array size. 1 to: self basicSize do: [ :i | key := self basicAt: i. key ifNotNil: [newDict noCheckAt: key put: (array at: i) hash: (tracer newHashFor: key)]]. ^newDict! ! !MethodDictionary methodsFor: '*systemtracer2' stamp: 'svp 8/23/2002 16:26'! noCheckAt: key put: value hash: identityHash "Set the value at key to be value." | index | index _ self findElementOrNil: key hash: identityHash. (self basicAt: index) == nil ifTrue: [tally _ tally + 1. self basicAt: index put: key]. array at: index put: value. ^ value! ! !String methodsFor: '*systemtracer2' stamp: 'svp 8/22/2002 22:45'! hashMappedBy: map "My hash is independent of my oop." "While this statement is technically correct, it is misleading. My hash does depend on the identity hash of my species, therefore it does need special care when cloning an image with new identity hashes - svp" ^String stringHash: self initialHash: (self species hashMappedBy: map)! ! !Symbol methodsFor: '*systemtracer2' stamp: 'svp 11/15/2002 16:14'! hashMappedBy: map "** DELETEME ** Overridden here to work with DVS packaging mechanism." ^super hashMappedBy: map! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'ikp 3/26/2005 21:59'! wordSize "Answer the size (in bytes) of an object pointer." "Smalltalk wordSize" ^[SmalltalkImage current vmParameterAt: 27] on: Error do: [4]! ! !SystemDictionary methodsFor: '*systemtracer2' stamp: 'di 5/5/2004 13:59'! rehashEntireImage "Note, we cannot use allObjectsDo: because some objects like to swap identities during a rehash...this means that allObjectsDo: will not find all objects. Also, this algorithm delays become operations to the very end where we can do them all at once. -svp" "Smalltalk rehashEntireImage" | objectCount allObjects numMdicts oldObjs newObjs newObject | numMdicts := MethodDictionary allInstances size. oldObjs := OrderedCollection new: numMdicts. newObjs := OrderedCollection new: numMdicts. "Create an array big enough to hold all objects in memory" objectCount := 0. self systemNavigation allObjectsDo: [ :ea | objectCount := objectCount + 1]. allObjects := Array new: objectCount + 500. "Now fill the array" objectCount := 0. self systemNavigation allObjectsDo: [ :ea | allObjects at: (objectCount := objectCount + 1) put: ea ]. "Progress bar disabled until proven innocent here..." "'Rehashing the image: ', objectCount printString, ' objects' displayProgressAt: Display center from: 1 to: objectCount during: [:bar | " objectCount := 0. allObjects do: [ :ea | "bar value:" (objectCount := objectCount + 1). newObject := ea rehashWithoutBecome. (newObject ~~ ea) ifTrue: [oldObjs add: ea. newObjs add: newObject]. ]. oldObjs asArray elementsExchangeIdentityWith: newObjs asArray. "]."! ! !SystemTracer2 methodsFor: 'run' stamp: 'di 5/5/2004 14:32'! writeImage: imageFileName "Trace all object in the image and write them out to imageFileName. See class comment for details." "SystemTracer2 writeImage: 'clone.image'" | doProcessStartup | "Build some of swapMap if desired" self initialize: self class numObjects. self initSwapMapPreShutdown. Smalltalk garbageCollect. "Open image file" byteStream _ FileStream newFileNamed: imageFileName. byteStream binary. "Copy changes file" (SourceFiles at: 2) ifNotNil:[ Smalltalk saveChangesInFileNamed: (Smalltalk fullNameForChangesNamed: imageFileName)]. "DisplayBox needed for image header" displayBox _ Display boundingBox. "Shutdown extraneous processes (like snapshot) then trace image. If error happen restart extraneous processes so we can debug. In either case, close image file when done. If we proceed from debugger we won't need to startup processes afterwards." doProcessStartup _ true. [ [ self processShutdown. self isolateAndTrace. "** New clone image will start up from here **" ] on: Error do: [:ex | self processStartup. doProcessStartup _ false. ex pass. ] ] ensure: [self isStartingClone ifFalse: [byteStream close]]. "isStartingClone will be true in clone image but false in tracing image" "Startup image processes. If in clone do special startup if desired" self isStartingClone ifTrue: [self clonePreStartup]. doProcessStartup ifTrue: [self processStartup]. self isStartingClone ifTrue: [self clonePostStartup]. self isStartingClone ifFalse: [self inform: 'Done tracing!!']. ! ! !SystemTracer2 methodsFor: 'object replacement' stamp: 'ajh 4/3/2004 06:38'! convert: obj pointer: pointer field: index "May want to substitute a new object for obj. And you may want to substitute diferent objects depending on the pointer. pointer is the object pointing to obj via its field at index. Delegate to obj so it can decide if it wants to convert and how. Make sure they check the swapMap in case a substitute has already been created for them in initSwapMapPreShutdown or initSwapMapPostShutdown or pvtWriteImageConverted. Each SystemTracer subclass should probably use a different convert message that looks like 'forSubclassName:...' so each subclass can have its own set of conversion methods. You can model them after the forSystemTracer:... methods." ^ obj forSystemTracer: swapMap pointer: pointer field: index! ! !SystemTracer2 methodsFor: 'object replacement' stamp: 'ajh 4/3/2004 04:29'! initSwapMapPostShutdown "Subclasses may want to add converted objects to swap map before starting trace but after shuting down extra processes" ! ! !SystemTracer2 methodsFor: 'object replacement' stamp: 'ajh 4/3/2004 04:32'! initSwapMapPreShutdown "Subclasses may want to add converted objects to swapMap before starting trace and before shuting down extra processes" ! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 5/4/2004 14:21'! compactHeaderSizeMax "This is the max number of words (plus 1 for header) for a compact object" ^ 16r3F! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'ajh 4/3/2004 09:52'! hashMask ^ 16rFFF! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 5/4/2004 13:07'! headersFor: class classOop: classOop hash: hash numFields: length "Return header words for new object. Three possibilities: {length, class, baseHeader} {class, baseHeader} {baseHeader}" | header3 header2 header1 cix sizeFld lowBits | "3 gc bits" header1 _ 0. "Mark, old, dirty" "Add hash" header1 _ header1 bitShift: 12. "next fld is 12 bits" header1 _ header1 + (hash bitAnd: self hashMask). "Add compact class index or class header" header1 _ header1 bitShift: 5. cix _ class indexIfCompactForConversion. "0 means need full word" header2 _ classOop. header1 _ header1 + (cix bitAnd: 16r1F). "Add object format (with low bits of size)" header1 _ header1 bitShift: 4. header1 _ header1 + class instSpec. class isWords ifFalse: [lowBits _ (wordSize-1) - (length + (wordSize-1) bitAnd: (wordSize-1)). "For byte objects: size = wordSize - spec.lowBits" header1 _ header1 + lowBits]. "Note code above will generate low bits up to 7 for wordSize = 8, but format codes are not prepared to accept this" "Add size in long words (includes base header)" header1 _ header1 bitShift: 6. sizeFld _ (class isBytes ifTrue: [length + (wordSize-1) // wordSize] ifFalse: [length]) + 1. sizeFld > 16r3F ifTrue: [header3 _ sizeFld bitShift: 2. sizeFld _ 0] ifFalse: [header3 _ 0]. header1 _ header1 + sizeFld. header1 _ header1 bitShift: 2. header3 > 0 ifTrue: ["3-word: type=0" ^ WordArray with: header3 + 0 with: header2 + 0 with: header1 + 0]. cix = 0 ifTrue: [ "2-word: type=1" ^ WordArray with: header2 + 1 with: header1 + 1]. "1-word: type=3" ^ WordArray with: header1 + 3! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'ajh 8/20/2002 19:53'! identityHashFor: object "object is the new object if the original was converted. If you change the identity hash, you will want to rehash all objects in cloneStartUp. However, if you change the identity hash of selectors (Symbols), then you should convert MethodDictionaries and selectors up front, before/during tracing" ^ object identityHash! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 6/3/2004 19:34'! imageHeaderSize ^ 64 "bytes" ! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'ajh 8/20/2002 16:50'! integerOopOf: value value < 0 ifTrue: [^ ((16r80000000 + value) << 1) + 1] ifFalse: [^ (value << 1) + 1]! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'ajh 4/3/2004 04:26'! lastHash ^ Object new identityHash! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 5/4/2004 19:30'! lengthAndHeaderSizeFor: object numFields: n "Return instance word length (including base header), and instance header size (including base header). This method should be consistent with headersFor:classOop:hash:numFields:" | cix size class | class _ object class. class isBits ifTrue: [class isBytes "Note literal bloat of CMs has been dealt with by caller" ifTrue: [size _ n + (wordSize-1) // wordSize + 1] ifFalse: [size _ n + (wordSize//4-1) // (wordSize//4) + 1]] ifFalse: [size _ n + 1]. "size in long words, incl hdr0" cix _ class indexIfCompactForConversion. "0 means need full word" size > self compactHeaderSizeMax ifTrue: [^ {size. 3}]. cix = 0 ifTrue: [^ {size. 2}]. ^ {size. 1}! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'ikp 9/2/2004 15:34'! versionNumber "Image format version number" ^6502! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 4/7/2004 22:49'! wordSize "# bytes per word -- override for 64-bit images" ^ 4! ! !SystemTracer2 methodsFor: 'object encoding' stamp: 'di 5/4/2004 15:29'! wordSizeNowRunning "# bytes per word *of this image* -- change if you're running in 64 bits" ^ 4! ! !SystemTracer2 methodsFor: 'object field enumeration' stamp: 'di 6/14/2004 13:44'! fixedPlusIndexableSizeFor: object "Return my total number of fields" (object isContextPart) ifTrue: [^ object class instSize + object frameSize]. object isCompiledMethod ifTrue: [^ object basicSize + (self pcDeltaForMethod: object)]. ^ object class instSize + object basicSize! ! !SystemTracer2 methodsFor: 'object field enumeration' stamp: 'di 7/22/2004 10:57'! object: object allFieldsWithIndex: block collect: sequenceableCollectionClass "Evaluate block against each of the pointer fields with index, and collect the results in an instance of sequenceableCollectionClass" | fixedSize results varSize nilResults | object isCompiledMethod ifTrue: [results _ sequenceableCollectionClass new: 1 + object numLiterals. 1 to: 1 + object numLiterals do: [:j | results at: j put: (block value: (object objectAt: j) value: j)]. ^ results]. fixedSize _ object class instSize. varSize _ object basicSize. results _ sequenceableCollectionClass new: fixedSize + varSize. 1 to: fixedSize do: [:j | results at: j put: (block value: (object instVarAt: j) value: j)]. 1 to: varSize do: [:j | results at: fixedSize + j put: (block value: (object basicAt: j) value: fixedSize + j)]. object isContextPart ifTrue: [(object instVarAt: 2) ifNotNil: ["May need to adjust PC and startPC if changing wordSize..." results at: 2 put: (block value: (object instVarAt: 2)+(self pcDeltaForMethod: object method) value: 2)]. ((object isMemberOf: BlockContext) and: [object home notNil]) ifTrue: [results at: 5 put: (block value: (object instVarAt: 5)+(self pcDeltaForMethod: object method) value: 5)]. "Need to fill out the nils beyond the knowable end of stack" nilResults _ sequenceableCollectionClass new: object frameSize - object basicSize. 1 to: nilResults size do: [:j | nilResults at: j put: (block value: nil value: j)]. ^ results , nilResults]. ^ results! ! !SystemTracer2 methodsFor: 'object field enumeration' stamp: 'di 6/14/2004 13:43'! pcDeltaForMethod: method ^ (wordSize - self wordSizeNowRunning) * (method numLiterals + 1)! ! !SystemTracer2 methodsFor: 'clone startup' stamp: 'ajh 8/22/2002 11:14'! clonePostStartup "This will be executed when the new clone starts up, but after processStartup. Subclasses may want to open a greeting window or something"! ! !SystemTracer2 methodsFor: 'clone startup' stamp: 'ajh 8/22/2002 11:15'! clonePreStartup "This will be executed right away when the new clone starts up, before processStartup. Subclasses may want to rehash all objects or something"! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 4/8/2004 00:02'! initialize: numObjects self class initialize. "To pick up latest large Dictionary class" wordSize _ self wordSize. swapMap _ LargeIdentityDict new: 4000. oopMap _ LargeIdentityDict new: numObjects. traceQueue _ OrderedCollection new: numObjects // 4. ! ! !SystemTracer2 methodsFor: 'private' stamp: 'ajh 8/20/2002 16:38'! isStartingClone "byteStream will be nil in new image" ^ byteStream == nil! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 6/3/2004 19:33'! isolateAndTrace "Make own execution invisible from tracer by putting dummies in swapMap" "Map self to empty and thisContext to nil so they don't get traced" swapMap at: self put: self class basicNew. swapMap at: thisContext put: nil. "Make new image start up in sender (writeImageFile:) right after this call. Push nil since the first instr after the call will be pop" thisContext sender push: nil. swapMap at: Processor activeProcess put: (Process forContext: thisContext sender priority: Processor activePriority). "Trace and write image" nextChunk _ self imageHeaderSize. 'Tracing and writing ', (oopMap capacity * 3//4) printString, ' objects' displayProgressAt: Display center from: self imageHeaderSize to: self class imageSize during: [:bar | self initSwapMapPostShutdown. Smalltalk garbageCollect. self traceImage: bar]. "Write header" self writeFileHeader. "Pop nil that was pushed above for clone image" thisContext sender pop. ^ nil! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 5/4/2004 15:26'! lengthAndHeaderSizeFor: object "Return two sizes in an array: 1. object's size in words including my base header, 2. my header size in words including base header" ^ self lengthAndHeaderSizeFor: object numFields: (self fixedPlusIndexableSizeFor: object)! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 6/15/2004 11:41'! processShutdown (Object respondsTo: #flushDependents) ifTrue: [Object flushDependents]. (Object respondsTo: #flushEvents) ifTrue: [Object flushEvents]. Smalltalk processShutDownList: false. "false means not quiting" "Note: the next two lines can be omitted when not writing, eg, a 64-bit image, but I leave them in so I can debug the 64-bit system against a similar 32. They are needed for the 64, lest Forms decompress into old bitmaps." Form allInstancesDo: [:f | f unhibernate]. ColorForm allInstancesDo: [:f | f unhibernate]. Cursor write show. ! ! !SystemTracer2 methodsFor: 'private' stamp: 'ajh 8/22/2002 11:17'! processStartup Cursor normal show. Smalltalk setGCParameters. self isStartingClone ifTrue: [Smalltalk clearExternalObjects]. Smalltalk processStartUpList: self isStartingClone. self isStartingClone ifTrue: [ Smalltalk setPlatformPreferences. Smalltalk readDocumentFile]. Smalltalk isMorphic ifTrue: [SystemWindow wakeUpTopWindowUponStartup]. ! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 4/7/2004 23:11'! reserve: object "Add object to write queue and return its oop" | lengthAndHeaderSize objectSize hdrSize oop | "Calculate oop and reserve space (advance nextChunk)" lengthAndHeaderSize _ self lengthAndHeaderSizeFor: object. objectSize _ lengthAndHeaderSize at: 1. hdrSize _ lengthAndHeaderSize at: 2. oop _ nextChunk + ((hdrSize - 1) * wordSize). nextChunk _ oop + (objectSize * wordSize). "Add object to fill queue and remember its oop" oopMap at: object put: oop. traceQueue addLast: object. ^ oop! ! !SystemTracer2 methodsFor: 'private' stamp: 'ajh 8/20/2002 19:24'! reserve: obj from: pointer field: index "Add obj to write queue and return its oop" | object | obj class = SmallInteger ifTrue: [^ self integerOopOf: obj]. "Return oop if already visited obj" object _ self convert: obj pointer: pointer field: index. object ifNil: [^ nilOop]. oopMap at: object ifPresent: [:itsOop | ^ itsOop]. ^ self reserve: object! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 4/7/2004 23:12'! traceImage: progressBar "Trace image starting with true, false, nil, and specialObjectsArray" | lengthAndHeaderSize object oop | "Add true and false in front so the VM can assume it will never move (see Interpreter>>interpret)" self reserve: true. self reserve: false. "Need to add nil separately because it can't be added as a key to oopMap" lengthAndHeaderSize _ self lengthAndHeaderSizeFor: nil. nilOop _ nextChunk + ((lengthAndHeaderSize second - 1) * wordSize). nextChunk _ nilOop + (lengthAndHeaderSize first * wordSize). self writeAndTrace: nil. "Add specialObjectArray next. Use new array in swap map if present. This is done explicitly here so swap map does not have to be tested on every Array write" object _ swapMap at: Smalltalk specialObjectsArray ifAbsent: [Smalltalk specialObjectsArray]. lengthAndHeaderSize _ self lengthAndHeaderSizeFor: object. oop _ nextChunk + ((lengthAndHeaderSize second - 1) * wordSize). nextChunk _ oop + (lengthAndHeaderSize first * wordSize). oopMap at: Smalltalk specialObjectsArray put: oop. oopMap at: object put: oop. self writeAndTrace: object. "Write and trace rest of image" [traceQueue isEmpty] whileFalse: [ oop _ self writeAndTrace: traceQueue removeFirst. progressBar value: oop ]. ! ! !SystemTracer2 methodsFor: 'private' stamp: 'di 5/4/2004 20:21'! writeAndTrace: object "Write the image representation of me on byteStream at my oop, and add my not-yet-seen fields to traceQueue." | lengthAndHeaderSize oop byteSize byteBuffer | lengthAndHeaderSize _ self lengthAndHeaderSizeFor: object. oop _ oopMap at: object ifAbsent: [object isNil ifTrue: [nilOop] ifFalse: [self halt: 'oop should have been added to oopMap when object was add to traceQueue']]. "Write header" byteStream position: oop - ((lengthAndHeaderSize second - 1) * wordSize). byteStream nextPutAll: (self headersFor: object class classOop: (self reserve: object class from: object field: -1 "class field") hash: (self identityHashFor: object) numFields: (self fixedPlusIndexableSizeFor: object) ). "Write fields" (object class isPointers or: [object class == CompiledMethod]) ifTrue: [ byteStream nextPutAll: (self object: object allFieldsWithIndex: [:val :i | self reserve: val from: object field: i] collect: WordArray). ] ifFalse: [ "isBits" byteStream nextPutAll: object. object class isBytes ifTrue: [ "fill bytes unused in last word" 1 to: (wordSize-1) - (object basicSize + (wordSize-1) \\ wordSize) do: [:i | byteStream nextPut: 0]] ifFalse: [(wordSize = 8 and: [object basicSize odd]) ifTrue: [ "fill word unused in last long8" byteStream nextPutAll: (WordArray with: 0)]]. ]. object class == CompiledMethod ifTrue: [ byteSize _ object basicSize - object initialPC + 1. byteBuffer _ ByteArray new: byteSize. byteBuffer replaceFrom: 1 to: byteSize with: object startingAt: object initialPC. "intermediate ByteArray needed since byteStream (a file) cannot putAll from a subclass of ByteArray (CompiledMethod)" byteStream nextPutAll: byteBuffer. "fill bytes unused in last word" 1 to: (wordSize-1) - (byteBuffer size + (wordSize-1) \\ wordSize) do: [:i | byteStream nextPut: 0]. ]. "Double check that fields take up expected size" byteStream position = (oop + (lengthAndHeaderSize first * wordSize)) ifFalse: [ self error: 'object size discrepency']. ^ oop! ! !SystemTracer2 methodsFor: 'private' stamp: 'ikp 9/2/2004 15:33'! writeFileHeader | specialObjectsOop | specialObjectsOop _ oopMap at: Smalltalk specialObjectsArray. byteStream position: 0. byteStream nextLongPut: self versionNumber. byteStream nextLongPut: self imageHeaderSize. byteStream nextLongPut: nextChunk - self imageHeaderSize. byteStream nextLongPut: self imageHeaderSize. "start of memory" byteStream nextLongPut: specialObjectsOop. byteStream nextLongPut: self lastHash. byteStream nextLongPut: displayBox width * 16r10000 + displayBox height. byteStream nextLongPut: 0. "fullScreenFlag" byteStream nextLongPut: Smalltalk extraVMMemory. byteStream padTo: self imageHeaderSize put: 0. ! ! !RehashingSystemTracer methodsFor: 'rehashing' stamp: 'di 5/5/2004 13:59'! initSwapMapPostShutdown "Subclasses may want to add converted objects to swap map before starting trace but after shuting down extra processes" "Note if we pre-hash, eg, IdentityDicts, then this should be called inside the progress bar of isolateAndTrace, since it adds morphs to the world" | sets elementCount clone | sets _ self specialSets. elementCount _ sets inject: 0 into: [:c :set | c _ c + set size]. hashMap := LargeIdentityDict new: elementCount. lastHash := 999. sets do: [ :ea | clone := ea cloneUsingHashesFrom: self. swapMap at: ea put: clone]. ! ! !RehashingSystemTracer methodsFor: 'rehashing' stamp: 'ajh 4/3/2004 18:36'! newHashFor: object "This is called by cloneUsingHashesFrom: (and compatibility with #hashMappedBy methods?)" ^ hashMap at: object ifAbsentPut: [self newObjectHash]! ! !RehashingSystemTracer methodsFor: 'rehashing' stamp: 'ajh 4/3/2004 18:39'! newObjectHash "Answer a new pseudo-random number for use as an identity hash." lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ^ lastHash bitAnd: self hashMask ! ! !RehashingSystemTracer methodsFor: 'rehashing' stamp: 'ajh 4/3/2004 22:07'! specialSets "The sets listed here get rehashed using the newly assigned identity hash values before the clone is written. On startup, the clone image will rehash all objects to ensure that all hashed structures are properly arranged. Rehashing is done in this two step process to retain maximum flexibility (if we tried to do everything up front, we would need to update the tracer every time a new type of Set is added with a different hashing and scanning algorithm, plus it would make the hashMap very large and slow)." ^ MethodDictionary allInstances ! ! !RehashingSystemTracer methodsFor: 'clone startup' stamp: 'svp 8/22/2002 22:01'! clonePreStartup Smalltalk rehashEntireImage! ! !RehashingSystemTracer methodsFor: 'object encoding' stamp: 'ajh 4/3/2004 18:32'! identityHashFor: object "Don not add to hashMap since this is only called once per object" ^ hashMap at: object ifAbsent: [self newObjectHash] ! ! !RehashingSystemTracer methodsFor: 'object encoding' stamp: 'svp 8/21/2002 12:46'! lastHash ^lastHash! ! !SystemTracer2 class methodsFor: 'image' stamp: 'ajh 7/9/2001 19:08'! imageSize ^ Smalltalk vmParameterAt: 2! ! !SystemTracer2 class methodsFor: 'image' stamp: 'ajh 7/3/2001 00:53'! numObjects "SystemTracer2 numObjects" | count object | count _ 0. object _ 0 someObject. [object == 0] whileFalse: [ count _ count + 1. object _ object nextObject]. ^ count! ! !SystemTracer2 class methodsFor: 'initialize' stamp: 'di 6/3/2004 19:34'! initialize LargeIdentityDict _ Smalltalk at: #LargeIdentityDictionary ifAbsent: [Smalltalk at: #NoAssocIdentityDictionary ifAbsent: [IdentityDictionary]]. ! ! !SystemTracer2 class methodsFor: 'initialize' stamp: 'ajh 4/3/2004 22:01'! largeDictClass: aIdentityDictionaryClass "The tracer will use this class for its large maps" LargeIdentityDict _ aIdentityDictionaryClass! ! !SystemTracer2 class methodsFor: 'run' stamp: 'ajh 4/3/2004 08:48'! writeImage: imageFileName "Trace all object in the image and write them out to imageFileName. See class comment for details." "SystemTracer2 writeImage: 'clone.image'" ^ self new writeImage: imageFileName! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 5/5/2004 00:30'! alignBitmap: bits forForm: form "Check to see that the raster is a multiple of 64 bits. If so, return bits. If not, return a copy extended so that it is." | raster padded pStart bStart | (raster _ form bitsSize // form height) even ifTrue: [^ bits]. padded _ Bitmap new: bits size + form height. "One word of padding per line" pStart _ bStart _ 1. 1 to: form height do: [:y | padded replaceFrom: pStart to: pStart+raster-1 with: bits startingAt: bStart. pStart _ pStart + raster + 1. bStart _ bStart + raster]. ^ padded! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 5/4/2004 14:21'! compactHeaderSizeMax "This is the max number of words (plus 1 for header) for a compact object" ^ 16r1F! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 7/20/2004 14:11'! headersFor: class classOop: classOop hash: hash numFields: length "Return header words for new object." "Three possibilities: {length, class, baseHeader} {class, baseHeader} {baseHeader}" | header3 header2 header1 cix sizeFld header32 header64 lowBits lowBits4 lengthInBytes | "3 gc bits" header1 _ 0. "Mark, old, dirty" "Add hash" header1 _ header1 bitShift: 12. "next fld is 12 bits" header1 _ header1 + (hash bitAnd: self hashMask). "Add compact class index or class header" header1 _ header1 bitShift: 5. cix _ class indexIfCompactForConversion. "0 means need full word" header2 _ classOop. header1 _ header1 + (cix bitAnd: 16r1F). "Add object format (with low bits of size)" header1 _ header1 bitShift: 4. header1 _ header1 + class instSpec. class isPointers ifTrue: [lowBits4 _ 0] ifFalse: [lengthInBytes _ (class isBytes ifTrue: [1] ifFalse: [4]) * length. lowBits _ (wordSize-1) - (lengthInBytes + (wordSize-1) bitAnd: (wordSize-1)). "For byte objects: size = wordSize - spec.lowBits" "Note: lowBits may have the 4 bit on in a 64-bit image. This bit must for now be put in the now-unused bit of the word-size field (see below)." lowBits4 _ lowBits bitShift: -2. header1 _ header1 + (lowBits bitAnd: 3)]. "Add size in long words (includes base header)" header1 _ header1 bitShift: 6. sizeFld _ (class isPointers ifTrue: [length] ifFalse: [lengthInBytes + (wordSize-1) // wordSize]) + 1. sizeFld _ sizeFld * 2. sizeFld > 16r3F ifTrue: [header3 _ sizeFld bitShift: 2. sizeFld _ 0] ifFalse: [header3 _ 0]. "Here we stick in the 4's bit of lowBits..." header1 _ header1 + sizeFld + lowBits4. header1 _ header1 bitShift: 2. header3 > 0 ifTrue: ["3-word: type=0" header32 _ WordArray with: header3 + 0 with: header2 + 0 with: header1 + 0] ifFalse: [cix = 0 ifTrue: [ "2-word: type=1" header32 _ WordArray with: header2 + 1 with: header1 + 1] ifFalse: ["1-word: type=3" header32 _ WordArray with: header1 + 3]]. header64 _ WordArray new: header32 size * 2. header32 withIndexDo: [:hdrWord :i | header64 at: i*2-1 put: 0. "Zero-fill above 32-bit headers" header64 at: i*2 put: hdrWord]. ^ header64! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 6/3/2004 19:32'! imageHeaderSize "64-bit images have twice as big a header" ^ super imageHeaderSize * 2! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 5/5/2004 15:00'! initSwapMapPostShutdown | aligned | super initSwapMapPostShutdown. " Forms must be uncompressed first... Form allSubInstancesDo: [:f | aligned _ self alignBitmap: f bits forForm: f. aligned == f bits ifFalse: [swapMap at: f bits put: aligned]] "! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 4/13/2004 11:59'! object: object allFieldsWithIndex: fieldAndIndexBlock collect: collectionClass | fields32 fields64 fill | fields32 _ super object: object allFieldsWithIndex: fieldAndIndexBlock collect: collectionClass. fields64 _ collectionClass new: fields32 size * 2. fields32 withIndexDo: [:field :i | field odd ifTrue: [(field bitAnd: 16r80000000) = 0 ifTrue: [fill _ 0] ifFalse: [fill _ 16rFFFFFFFF]] "Sign-extend SmallIntegers" ifFalse: [fill _ 0]. "Zero-fill above oops" fields64 at: i*2-1 put: fill. fields64 at: i*2 put: field]. ^ fields64! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'ikp 9/2/2004 15:34'! versionNumber "Image format version number" ^68000! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'di 4/7/2004 22:58'! wordSize "# bytes per word in target image" ^ 8! ! !SystemTracer64 methodsFor: 'as yet unclassified' stamp: 'ikp 9/2/2004 15:33'! writeFileHeader "Note here it is assumed that this image is less than 4GB in size. Otherwise a few items should be full 8-byte quantities" | specialObjectsOop | specialObjectsOop _ oopMap at: Smalltalk specialObjectsArray. byteStream position: 0. byteStream nextLongPut: 0. byteStream nextLongPut: self versionNumber. byteStream nextLongPut: 0. byteStream nextLongPut: self imageHeaderSize. byteStream nextLongPut: 0. byteStream nextLongPut: nextChunk - self imageHeaderSize. byteStream nextLongPut: 0. byteStream nextLongPut: self imageHeaderSize. "start of memory" byteStream nextLongPut: 0. byteStream nextLongPut: specialObjectsOop. byteStream nextLongPut: 0. byteStream nextLongPut: self lastHash. byteStream nextLongPut: 0. byteStream nextLongPut: displayBox width * 16r10000 + displayBox height. byteStream nextLongPut: 0. byteStream nextLongPut: 0. "fullScreenFlag" byteStream nextLongPut: 0. byteStream nextLongPut: Smalltalk extraVMMemory. byteStream padTo: self imageHeaderSize put: 0. ! ! !WeakSet methodsFor: 'private' stamp: 'svp 8/23/2002 17:32'! scanFor: anObject startingAt: start "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements" | element | "Search from (hash mod size) to the end." start to: array size do: [:index | ((element _ array at: index) == flag or: [self compare: element with: anObject]) ifTrue: [^ index ]]. "Search from 1 to where we started." 1 to: start-1 do: [:index | ((element _ array at: index) == flag or: [self compare: element with: anObject]) ifTrue: [^ index ]]. ^ 0 "No match AND no empty slot"! ! !WeakSet methodsFor: '*systemtracer2' stamp: 'svp 8/23/2002 16:26'! cloneUsingHashesFrom: tracer | newSet object | newSet := self class basicNew init: array size. 1 to: array size do: [ :i | object := array at: i. (object == flag or: [object == nil]) ifFalse: [newSet noCheckAdd: object hash: (object hashMappedBy: tracer)]]. ^newSet! ! !WeakSet methodsFor: '*systemtracer2' stamp: 'svp 8/23/2002 16:27'! noCheckAdd: anObject hash: hash array at: (self findElementOrNil: anObject hash: hash) put: anObject. tally _ tally + 1! ! SystemTracer2 initialize! PositionableStream initialize! Stream subclass: #PositionableStream instanceVariableNames: 'collection position readLimit' classVariableNames: 'IntBuffer' poolDictionaries: '' category: 'Collections-Streams'! ================================================ FILE: vm/src/from_squeak/unix/misc/VMM38b4-64bit-image1-ikp.1.cs ================================================ 'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6548] on 31 March 2005 at 11:13:48 am'! "Change Set: VMM38b4-64bit-image1-ikp Date: 2005-03-31 Author: ian.piumarta@squeakland.org Changes relative to 3.8g-6548 that add 64-bit support to the image. File this in BEFORE filing in VMM38b4-64bit-image2."! !SystemDictionary methodsFor: 'sources, change log' stamp: 'ikp 3/26/2005 21:59'! wordSize "Answer the size (in bytes) of an object pointer." "Smalltalk wordSize" ^[SmalltalkImage current vmParameterAt: 27] on: Error do: [4]! ! ================================================ FILE: vm/src/from_squeak/unix/misc/VMM38b4-64bit-image2-ikp.1.cs ================================================ 'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6548] on 31 March 2005 at 11:13:52 am'! "Change Set: VMM38b4-64bit-image2-ikp Date: 2005-03-31 Author: ian.piumarta@squeakland.org Changes relative to 3.8g-6548 that add 64-bit support to the image. File in VMM38b4-64bit-image1 BEFORE this file."! !Class methodsFor: 'subclass creation' stamp: 'di 10/6/2004 10:54'! variableLongSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class (the receiver) in which the subclass is to have indexable word-sized nonpointer variables." ^(ClassBuilder new) superclass: self variableLongSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat ! ! !ClassBuilder methodsFor: 'class format' stamp: 'di 10/6/2004 10:51'! computeFormat: type instSize: newInstSize forSuper: newSuper ccIndex: ccIndex "Compute the new format for making oldClass a subclass of newSuper. Return the format or nil if there is any problem." | instSize isVar isPointers isWeak | instSize _ newInstSize + (newSuper ifNil:[0] ifNotNil:[newSuper instSize]). instSize > 254 ifTrue:[ self error: 'Class has too many instance variables (', instSize printString,')'. ^nil]. type == #compiledMethod ifTrue:[^CompiledMethod instSpec]. type == #normal ifTrue:[isVar _ isWeak _ false. isPointers _ true]. type == #weak ifTrue:[isVar _ isWeak _ isPointers _ true]. type == #variable ifTrue:[isVar _ isPointers _ true. isWeak _ false]. type == #bytes ifTrue:[isVar _ true. isPointers _ isWeak _ false]. type == #words ifTrue:[isVar _ true. isPointers _ isWeak _ false]. type == #longs ifTrue:[isVar _ true. isPointers _ isWeak _ false]. (isPointers not and:[instSize > 0]) ifTrue:[ self error:'A non-pointer class cannot have instance variables'. ^nil]. ^(self format: instSize variable: isVar words: type pointers: isPointers weak: isWeak) + (ccIndex bitShift: 11).! ! !ClassBuilder methodsFor: 'class format' stamp: 'di 10/6/2004 10:49'! format: nInstVars variable: isVar words: fieldType pointers: isPointers weak: isWeak "Compute the format for the given instance specfication." | cClass instSpec sizeHiBits fmt | self flag: #instSizeChange. " Smalltalk browseAllCallsOn: #instSizeChange. Smalltalk browseAllImplementorsOf: #fixedFieldsOf:. Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:. " " NOTE: This code supports the backward-compatible extension to 8 bits of instSize. For now the format word is... <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0> But when we revise the image format, it should become... <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0> " sizeHiBits _ (nInstVars+1) // 64. cClass _ 0. "for now" instSpec _ isWeak ifTrue:[4] ifFalse:[isPointers ifTrue: [isVar ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]] ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]] ifFalse: [fieldType == #longs ifTrue: [7] ifFalse: [fieldType == #words ifTrue: [6] ifFalse: [fieldType == #bytes ifTrue: [8] ifFalse: [self error: 'bad fieldType']]]]]. fmt _ sizeHiBits. fmt _ (fmt bitShift: 5) + cClass. fmt _ (fmt bitShift: 4) + instSpec. fmt _ (fmt bitShift: 6) + ((nInstVars+1)\\64). "+1 since prim size field includes header" fmt _ (fmt bitShift: 1). "This shift plus integer bit lets wordSize work like byteSize" ^fmt! ! !ClassBuilder methodsFor: 'public' stamp: 'di 10/6/2004 10:53'! superclass: aClass variableLongSubclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat "This is the standard initialization message for creating a new class as a subclass of an existing class in which the subclass is to have indexable word-sized nonpointer variables." (aClass instSize > 0) ifTrue: [^self error: 'cannot make a word subclass of a class with named fields']. (aClass isVariable and: [aClass isBytes]) ifTrue: [^self error: 'cannot make a word subclass of a class with byte fields']. (aClass isVariable and: [aClass isPointers]) ifTrue: [^self error: 'cannot make a word subclass of a class with pointer fields']. ^self name: t inEnvironment: aClass environment subclassOf: aClass type: #longs instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat! ! !CompiledMethod methodsFor: 'accessing' stamp: 'di 6/29/2004 12:28'! initialPC "Answer the program counter for the receiver's first bytecode." ^ (self numLiterals + 1) * Smalltalk wordSize + 1 ! ! !FileList methodsFor: 'private' stamp: 'di 7/2/2004 11:35'! readContentsHex: brevity "retrieve the contents from the external file unless it is too long. Don't create a file here. Check if exists." | f size data hexData s | f := directory oldFileOrNoneNamed: self fullName. f == nil ifTrue: [^ 'For some reason, this file cannot be read' translated]. ((size := f size)) > 5000 & brevity ifTrue: [data := f next: 10000. f close. brevityState := #briefHex] ifFalse: [data := f contentsOfEntireFile. brevityState := #fullHex]. s := WriteStream on: (String new: data size*4). 0 to: data size-1 by: 16 do: [:loc | s nextPutAll: loc hex; space; nextPut: $(; print: loc; nextPut: $); space; tab. loc+1 to: (loc+16 min: data size) do: [:i | s nextPutAll: (data at: i) hex; space]. s tab; nextPutAll: '|' , ((data copyFrom: loc+1 to: (loc+16 min: data size)) copyReplaceAll: Character cr asString with: '/') asString , '|'. s cr]. hexData := s contents. ^ contents := ((size > 5000) & brevity ifTrue: ['File ''{1}'' is {2} bytes long. You may use the ''get'' command to read the entire file. Here are the first 5000 characters... ------------------------------------------ {3} ------------------------------------------ ... end of the first 5000 characters.' translated format: {fileName. size. hexData}] ifFalse: [hexData]). ! ! !Form methodsFor: 'other' stamp: 'di 6/19/2004 12:25'! bitsSize64 | pixPerWord | depth == nil ifTrue: [depth _ 1]. pixPerWord _ 64 // self depth. ^ width + pixPerWord - 1 // pixPerWord * height " | nBytes nBytes64 | nBytes _ nBytes64 _ 0. Form allInstances , ColorForm allinstances do: [:f | f unhibernate. nBytes _ nBytes + (f bitsSize*4). nBytes64 _ nBytes64 + (f bitsSize64*8). f hibernate]. {nBytes. nBytes64} "! ! !Text methodsFor: 'accessing' stamp: 'ikp 3/31/2005 07:52'! stamp ^'unknown'! ! ================================================ FILE: vm/src/from_squeak/unix/misc/VMM38b4-64bit-vm1-ikp.1.cs ================================================ 'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6548] on 31 March 2005 at 2:51:49 pm'! "Change Set: VMM38b4-64bit-vm Date: 2005-03-31 Author: ian.piumarta@squeakland.org Changes relative to VMMaker-tpr.14 that add 64-bit support to the VM."! CArray subclass: #BalloonArray instanceVariableNames: 'simArray' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! !BalloonArray commentStamp: '' prior: 0! BalloonArray keeps a shadow copy of its raw memory data in a Smalltalk array. This allows support for C's inhomogeneous access, returning floats where Floats were stored, and negative ints where they were stored. This ruse only works, of course where we have control over all the access.! BalloonEnginePlugin subclass: #BalloonEngineSimulation instanceVariableNames: 'bbObj workBufferArray ' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! Object subclass: #InterpreterSimulationObject instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-Plugins'! Object subclass: #ObjectMemory instanceVariableNames: 'memory youngStart endOfMemory memoryLimit nilObj falseObj trueObj specialObjectsOop rootTable rootTableCount child field parentField freeBlock lastHash allocationCount lowSpaceThreshold signalLowSpace compStart compEnd fwdTableNext fwdTableLast remapBuffer remapBufferCount allocationsBetweenGCs tenuringThreshold statFullGCs statFullGCMSecs statIncrGCs statIncrGCMSecs statTenures statRootTableOverflows freeContexts freeLargeContexts interruptCheckCounter totalObjectCount shrinkThreshold growHeadroom headerTypeBytes youngStartLocal ' classVariableNames: 'AllButHashBits AllButMarkBit AllButMarkBitAndTypeMask AllButRootBit AllButTypeMask BaseHeaderSize BlockContextProto CharacterTable ClassArray ClassBitmap ClassBlockContext ClassByteArray ClassCharacter ClassCompiledMethod ClassExternalAddress ClassExternalData ClassExternalFunction ClassExternalLibrary ClassExternalStructure ClassFloat ClassInteger ClassLargeNegativeInteger ClassLargePositiveInteger ClassMessage ClassMethodContext ClassPoint ClassProcess ClassPseudoContext ClassSemaphore ClassString ClassTranslatedMethod CompactClassMask CompactClasses ConstMinusOne ConstOne ConstTwo ConstZero CtxtTempFrameStart DoAssertionChecks DoBalanceChecks Done ExternalObjectsArray FalseObject FloatProto GCTopMarker HashBits HashBitsOffset HeaderTypeClass HeaderTypeFree HeaderTypeGC HeaderTypeShort HeaderTypeSizeAndClass LargeContextBit LargeContextSize MarkBit MethodContextProto NilContext NilObject RemapBufferSize RootBit RootTableRedZone RootTableSize SchedulerAssociation SelectorAboutToReturn SelectorCannotInterpret SelectorCannotReturn SelectorDoesNotUnderstand SelectorMustBeBoolean SelectorRunWithIn SizeMask SmallContextSize SpecialSelectors StackStart StartField StartObj TheDisplay TheFinalizationSemaphore TheInputSemaphore TheInterruptSemaphore TheLowSpaceSemaphore TheTimerSemaphore TrueObject TypeMask Upward Bytes3to0Mask Size4Bit Byte1Shift Byte4Shift Byte7Shift Bytes7to4Mask ContextFixedSizePlusHeader Byte7ShiftNegated Byte2Mask Byte4ShiftNegated Byte1ShiftNegated Byte0Shift Byte5Mask Byte1Mask Byte3Shift Byte6Shift BytesPerWord Byte4Mask Byte0Mask Byte7Mask Byte3Mask LongSizeMask Byte2Shift Byte5ShiftNegated Byte6Mask Byte5Shift WordMask Byte3ShiftNegated ShiftForWord ' poolDictionaries: '' category: 'VMMaker-Interpreter'! !ObjectMemory commentStamp: '' prior: 0! This class describes a 32-bit direct-pointer object memory for Smalltalk. The model is very simple in principle: a pointer is either a SmallInteger or a 32-bit direct object pointer. SmallIntegers are tagged with a low-order bit equal to 1, and an immediate 31-bit 2s-complement signed value in the rest of the word. All object pointers point to a header, which may be followed by a number of data fields. This object memory achieves considerable compactness by using a variable header size (the one complexity of the design). The format of the 0th header word is as follows: 3 bits reserved for gc (mark, root, unused) 12 bits object hash (for HashSets) 5 bits compact class index 4 bits object format 6 bits object size in 32-bit words 2 bits header type (0: 3-word, 1: 2-word, 2: forbidden, 3: 1-word) If a class is in the compact class table, then this is the only header information needed. If it is not, then it will have another header word at offset -4 bytes with its class in the high 30 bits, and the header type repeated in its low 2 bits. It the objects size is greater than 255 bytes, then it will have yet another header word at offset -8 bytes with its full word size in the high 30 bits and its header type repeated in the low two bits. The object format field provides the remaining information as given in the formatOf: method (including isPointers, isVariable, isBytes, and the low 2 size bits of byte-sized objects). This implementation includes incremental (2-generation) and full garbage collection, each with compaction and rectification of direct pointers. It also supports a bulk-become (exchange object identity) feature that allows many objects to be becomed at once, as when all instances of a class must be grown or shrunk. There is now a simple 64-bit version of the object memory. It is the simplest possible change that could work. It merely sign-extends all integer oops, and extends all object headers and oops by adding 32 zeroes in the high bits. The format of the base header word is changed in one minor, not especially elegant, way. Consider the old 32-bit header: ggghhhhhhhhhhhhcccccffffsssssstt The 64-bit header is almost identical, except that the size field (now being in units of 8 bytes, has a zero in its low-order bit. At the same time, the byte-size residue bits for byte objects, which are in the low order bits of formats 8-11 and 12-15, are now in need of another bit of residue. So, the change is as follows: ggghhhhhhhhhhhhcccccffffsssssrtt where bit r supplies the 4's bit of the byte size residue for byte objects. Oh, yes, this is also needed now for 'variableWord' objects, since their size in 32-bit words requires a low-order bit. See the comment in formatOf: for the change allowing for 64-bit wide bitmaps, now dubbed 'variableLong'.! Interpreter subclass: #InterpreterSimulator instanceVariableNames: 'byteCount sendCount traceOn myBitBlt displayForm filesOpen imageName pluginList mappedPluginEntries inputSem quitBlock transcript logging displayView ' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! InterpreterSimulatorLSB subclass: #InterpreterSimulatorLSB64 instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! InterpreterSimulatorMSB subclass: #InterpreterSimulatorMSB64 instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! !Object methodsFor: '*VMMaker-translation support' stamp: 'di 7/14/2004 12:15'! isCObjectAccessor ^ false! ! !Array methodsFor: 'converting' stamp: 'di 5/9/2004 09:55'! coerceTo: cTypeString sim: interpreterSimulator ^ self! ! !CArray methodsFor: 'converting' stamp: 'di 7/15/2004 16:55'! asCArrayAccessor ^ (CArrayAccessor on: self) += -1 "Defeat the +1 offset in the accessor"! ! !CArray methodsFor: 'converting' stamp: 'tpr 3/23/2005 12:36'! coerceTo: cTypeString sim: interpreterSimulator cTypeString = 'int' ifTrue: [^ self ptrAddress]. cTypeString = 'float *' ifTrue: [^ self asCArrayAccessor asFloatAccessor]. cTypeString = 'int *' ifTrue: [^ self asCArrayAccessor asIntAccessor]. cTypeString = 'unsigned' ifTrue: [^ self ptrAddress]. ^ self! ! !CArray methodsFor: 'accessing' stamp: 'di 7/6/2004 09:32'! at: offset ptrOffset = 0 ifFalse: [self error: 'only expect base address to receive at: message']. unitSize = 1 ifTrue: [^ interpreter byteAt: arrayBaseAddress + offset]. unitSize = 4 ifTrue: [^ interpreter long32At: arrayBaseAddress + (offset * 4)]. self halt: 'Can''t handle unitSize ', unitSize printString ! ! !CArray methodsFor: 'accessing' stamp: 'di 7/19/2004 12:01'! at: offset put: val ptrOffset = 0 ifFalse: [self error: 'only expect base address to receive at:put: message']. unitSize = 1 ifTrue: [^ interpreter byteAt: arrayBaseAddress + offset put: val]. unitSize = 4 ifTrue: [^ interpreter long32At: arrayBaseAddress + (offset * 4) put: val]. self halt: 'Can''t handle unitSize ', unitSize printString ! ! !CArray methodsFor: 'accessing' stamp: 'di 7/16/2004 12:45'! floatAt: index ^ Float fromIEEE32Bit: (self at: index)! ! !CArray methodsFor: 'accessing' stamp: 'di 7/16/2004 12:45'! floatAt: index put: value ^ self at: index put: value asIEEE32BitWord! ! !CArray methodsFor: 'accessing' stamp: 'di 7/16/2004 12:45'! intAt: index ^ (self at: index) signedIntFromLong! ! !CArray methodsFor: 'accessing' stamp: 'di 7/16/2004 12:45'! intAt: index put: signedInt ^ self at: index put: signedInt signedIntToLong! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/16/2004 12:14'! at: index | value | value _ simArray at: index+1. "Debug only..." value ifNil: [self error: 'attempt to read an uninitialized field'. ^ super at: index "Maybe it was set in Squeak. Return the raw value"]. (self bitsOf: value) ~= (super at: index) ifTrue: [self error: 'inconsistent values']. ^ value! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/16/2004 11:28'! at: index put: value super at: index put: (self bitsOf: value). ^ simArray at: index + 1 put: value. ! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 13:34'! bitsOf: value "Convert pos and neg ints and floats to 32-bit representations expected by C" value isInteger ifTrue: [value >= 0 ifTrue: [^ value]. ^ value + 16r80000000 + 16r80000000]. value isFloat ifTrue: [^ value asIEEE32BitWord]. self error: 'unexpected value for 32 bits'. ^ 0! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 16:04'! floatAt: index | value | value _ self at: index. value isFloat ifFalse: [value = 0 ifTrue: [^ 0.0]. self error: 'non-float was stored'. ^ Float fromIEEE32Bit: value]. ^ value! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 13:00'! floatAt: index put: value value isFloat ifFalse: [self error: 'inconsistent values']. ^ self at: index put: value! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 13:02'! intAt: index | value | value _ self at: index. value isInteger ifFalse: [self error: 'inconsistent values']. ^ value! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 13:01'! intAt: index put: value value isInteger ifFalse: [self error: 'inconsistent values']. ^ self at: index put: value! ! !BalloonArray methodsFor: 'memory access' stamp: 'di 7/15/2004 13:17'! setSimArray: anArray simArray _ anArray! ! !CCodeGenerator methodsFor: 'public' stamp: 'ikp 9/2/2004 14:19'! storeHeaderOnFile: fileName bytesPerWord: bytesPerWord "Store C header code for this interpreter on the given file." | aStream | aStream _ CrLfFileStream forceNewFileNamed: fileName. aStream ifNil: [Error signal: 'Could not open C header file: ', fileName]. aStream nextPutAll: '/* Automatically generated from Squeak on '; print: Time dateAndTimeNow; nextPutAll: ' */'; cr; cr; nextPutAll: '#define SQ_VI_BYTES_PER_WORD '; print: bytesPerWord; cr; close! ! !CCodeGenerator methodsFor: 'utilities' stamp: 'ikp 6/13/2004 22:22'! builtin: sel "Answer true if the given selector is one of the builtin selectors." ((sel = #byteAt:) or: [sel = #byteAt:put:]) ifTrue: [ ^true ]. ((sel = #shortAt:) or: [sel = #shortAt:put:]) ifTrue: [ ^true ]. ((sel = #intAt:) or: [sel = #intAt:put:]) ifTrue: [ ^true ]. ((sel = #longAt:) or: [(sel = #longAt:put:) or: [sel = #error:]]) ifTrue: [ ^true ]. ((sel = #byteAtPointer:) or: [sel = #byteAtPointer:put:]) ifTrue: [ ^true ]. ((sel = #shortAtPointer:) or: [sel = #shortAtPointer:put:]) ifTrue: [ ^true ]. ((sel = #longAtPointer:) or: [(sel = #longAtPointer:put:) or: [sel = #error:]]) ifTrue: [ ^true ]. ^translationDict includesKey: sel! ! !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 8/3/2004 20:16'! cLiteralFor: anObject "Return a string representing the C literal value for the given object." (anObject isKindOf: Integer) ifTrue: [ (anObject < 16r7FFFFFFF) ifTrue: [^ anObject printString] ifFalse: [^ anObject printString , ObjectMemory unsignedIntegerSuffix "ikp"]]. (anObject isKindOf: String) ifTrue: [^ '"', anObject, '"' ]. (anObject isKindOf: Float) ifTrue: [^ anObject printString ]. anObject == nil ifTrue: [^ 'null' ]. anObject == true ifTrue: [^ '1' ]. "ikp" anObject == false ifTrue: [^ '0' ]. "ikp" (anObject isKindOf: Character) ifTrue:[^anObject asString printString]. "ar" self error: "ikp" 'Warning: A Smalltalk literal could not be translated into a C constant: ', anObject printString. ^'"XXX UNTRANSLATABLE CONSTANT XXX"'! ! !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 6/9/2004 16:04'! emitCHeaderForPrimitivesOn: aStream "Write a C file header for compiled primitives onto the given stream." aStream nextPutAll: '/* Automatically generated from Squeak on '. aStream nextPutAll: Time dateAndTimeNow printString. aStream nextPutAll: ' */'; cr; cr. aStream nextPutAll: '#include "sq.h"'; cr; cr. "Additional header files" headerFiles do:[:hdr| aStream nextPutAll:'#include '; nextPutAll: hdr; cr]. aStream nextPutAll: ' #include "sqMemoryAccess.h" /*** Imported Functions/Variables ***/ extern sqInt stackValue(sqInt); extern sqInt stackIntegerValue(sqInt); extern sqInt successFlag; /* allows accessing Strings in both C and Smalltalk */ #define asciiValue(c) c '. aStream cr.! ! !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 6/9/2004 16:06'! emitCHeaderOn: aStream "Write a C file header onto the given stream." aStream nextPutAll: '/* Automatically generated from Squeak on '. aStream nextPutAll: Time dateAndTimeNow printString. aStream nextPutAll: ' */'; cr; cr. self emitGlobalStructFlagOn: aStream. aStream nextPutAll: '#include "sq.h"'; cr. "Additional header files" headerFiles do:[:hdr| aStream nextPutAll:'#include '; nextPutAll: hdr; cr]. aStream nextPutAll: ' #include "sqMemoryAccess.h" sqInt printCallStack(void); void error(char *s); void error(char *s) { /* Print an error message and exit. */ static sqInt printingStack = false; printf("\n%s\n\n", s); if (!!printingStack) { /* flag prevents recursive error when trying to print a broken stack */ printingStack = true; printCallStack(); } exit(-1); } '. aStream cr.! ! !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 6/9/2004 16:04'! emitCVariablesOn: aStream "Store the global variable declarations on the given stream." | varString | aStream nextPutAll: '/*** Variables ***/'; cr. variables asSortedCollection do: [:var | varString _ var asString. self isGeneratingPluginCode ifTrue: [varString = 'interpreterProxy' ifTrue: ["quite special..." aStream cr; nextPutAll: '#ifdef SQUEAK_BUILTIN_PLUGIN'. aStream cr; nextPutAll: 'extern'. aStream cr; nextPutAll: '#endif'; cr] ifFalse: [aStream nextPutAll: 'static ']]. (variableDeclarations includesKey: varString) ifTrue: [aStream nextPutAll: (variableDeclarations at: varString) , ';'; cr] ifFalse: ["default variable declaration" aStream nextPutAll: 'sqInt ' , varString , ';'; cr]]. aStream cr! ! !CCodeGenerator methodsFor: 'C translation' stamp: 'ikp 6/9/2004 16:13'! generateAsInteger: msgNode on: aStream indent: level "Generate the C code for this message onto the given stream." aStream nextPutAll:'((sqInt) '. self emitCExpression: msgNode receiver on: aStream. aStream nextPutAll: ' )'.! ! !CCodeGenerator methodsFor: 'C translation' stamp: 'ikp 8/4/2004 16:29'! generateBitShift: msgNode on: aStream indent: level "Generate the C code for this message onto the given stream." | arg rcvr | arg _ msgNode args first. rcvr _ msgNode receiver. arg isConstant ifTrue: [ "bit shift amount is a constant" aStream nextPutAll: '((usqInt) '. self emitCExpression: rcvr on: aStream. arg value < 0 ifTrue: [ aStream nextPutAll: ' >> ', arg value negated printString. ] ifFalse: [ aStream nextPutAll: ' << ', arg value printString. ]. aStream nextPutAll: ')'. ] ifFalse: [ "bit shift amount is an expression" aStream nextPutAll: '(('. self emitCExpression: arg on: aStream. aStream nextPutAll: ' < 0) ? ((usqInt) '. self emitCExpression: rcvr on: aStream. aStream nextPutAll: ' >> -'. self emitCExpression: arg on: aStream. aStream nextPutAll: ') : ((usqInt) '. self emitCExpression: rcvr on: aStream. aStream nextPutAll: ' << '. self emitCExpression: arg on: aStream. aStream nextPutAll: '))'. ].! ! !CCodeGenerator methodsFor: 'C translation' stamp: 'ikp 6/9/2004 16:14'! generateDivide: msgNode on: aStream indent: level "Generate the C code for this message onto the given stream." | rcvr arg divisor | rcvr _ msgNode receiver. arg _ msgNode args first. (arg isConstant and: [UseRightShiftForDivide and: [(divisor _ arg value) isInteger and: [divisor isPowerOfTwo and: [divisor > 0 and: [divisor <= (1 bitShift: 31)]]]]]) ifTrue: [ "use signed (arithmetic) right shift instead of divide" aStream nextPutAll: '((sqInt) '. self emitCExpression: rcvr on: aStream. aStream nextPutAll: ' >> ', (divisor log: 2) asInteger printString. aStream nextPutAll: ')'. ] ifFalse: [ self emitCExpression: rcvr on: aStream. aStream nextPutAll: ' / '. self emitCExpression: arg on: aStream]. ! ! !CCodeGenerator methodsFor: 'C translation' stamp: 'ikp 8/4/2004 18:25'! generateShiftRight: msgNode on: aStream indent: level "Generate the C code for this message onto the given stream." aStream nextPutAll: '((usqInt) '. self emitCExpression: msgNode receiver on: aStream. aStream nextPutAll: ')'. aStream nextPutAll: ' >> '. self emitCExpression: msgNode args first on: aStream.! ! !CCodeGeneratorGlobalStructure methodsFor: 'C code generator' stamp: 'ikp 6/9/2004 16:05'! emitCVariablesOn: aStream "Store the global variable declarations on the given stream. break logic into vars for structure and vars for non-structure" | varString structure nonstruct target | structure _ WriteStream on: (String new: 32768). nonstruct _ WriteStream on: (String new: 32768). aStream nextPutAll: '/*** Variables ***/'; cr. structure nextPutAll: 'struct foo {'; cr. self buildSortedVariablesCollection do: [ :var | varString _ var asString. target _ (self placeInStructure: var) ifTrue: [structure] ifFalse: [nonstruct]. (self isGeneratingPluginCode) ifTrue:[ varString = 'interpreterProxy' ifTrue:[ "quite special..." aStream cr; nextPutAll: '#ifdef SQUEAK_BUILTIN_PLUGIN'. aStream cr; nextPutAll: 'extern'. aStream cr; nextPutAll: '#endif'; cr. ] ifFalse:[aStream nextPutAll:'static ']. ]. (variableDeclarations includesKey: varString) ifTrue: [ target nextPutAll: (variableDeclarations at: varString), ';'; cr. ] ifFalse: [ "default variable declaration" target nextPutAll: 'sqInt ', varString, ';'; cr. ]. ]. structure nextPutAll: ' } fum;';cr. "if the machine needs the fum structure defining locally, do it now" localStructDef ifTrue:[structure nextPutAll: 'struct foo * foo = &fum;';cr;cr]. aStream nextPutAll: structure contents. aStream nextPutAll: nonstruct contents. aStream cr.! ! !CObjectAccessor methodsFor: 'converting' stamp: 'di 7/14/2004 17:36'! asFloatAccessor ^ self asPluggableAccessor atBlock: [:obj :index | obj floatAt: index] atPutBlock: [:obj :index :value | obj floatAt: index put: value]! ! !CObjectAccessor methodsFor: 'converting' stamp: 'di 7/14/2004 17:36'! asIntAccessor ^ self asPluggableAccessor atBlock: [:obj :index | obj intAt: index] atPutBlock: [:obj :index :value | obj intAt: index put: value]! ! !CObjectAccessor methodsFor: 'converting' stamp: 'di 7/14/2004 11:55'! asPluggableAccessor ^ (CPluggableAccessor on: object) += offset! ! !CObjectAccessor methodsFor: 'converting' stamp: 'di 7/14/2004 17:38'! coerceTo: cTypeString sim: interpreterSimulator cTypeString = 'float *' ifTrue: [^ self asFloatAccessor]. cTypeString = 'int *' ifTrue: [^ self asIntAccessor]. ^ self! ! !CObjectAccessor methodsFor: 'accessing' stamp: 'di 7/14/2004 12:13'! isCObjectAccessor ^ true! ! !CPluggableAccessor methodsFor: 'initialize' stamp: 'di 7/14/2004 11:55'! atBlock: rBlock atPutBlock: wBlock readBlock _ rBlock. writeBlock _ wBlock! ! !CompiledMethod methodsFor: 'accessing' stamp: 'di 6/29/2004 12:28'! initialPC "Answer the program counter for the receiver's first bytecode." ^ (self numLiterals + 1) * Smalltalk wordSize + 1 ! ! !Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'di 7/16/2004 15:06'! signedIntFromLong "Self is an unsigned 32-bit integer" | sign | self < 0 ifTrue: [self error: 'only valid for unsigned ints']. sign _ self bitAnd: 16r80000000. sign = 0 ifTrue: [^ self]. ^ self - sign - sign! ! !Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'di 7/16/2004 15:06'! signedIntFromShort "Self is an unsigned 16-bit integer in twos-comp form" | sign | self < 0 ifTrue: [self error: 'only valid for unsigned ints']. sign _ self bitAnd: 16r8000. sign = 0 ifTrue: [^ self]. ^ self - sign - sign! ! !Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'di 7/14/2004 12:27'! signedIntToLong "Produces a 32-bit value in twos-comp form. Sorry no error checking" self >= 0 ifTrue: [^ self] ifFalse: [^ self + 16r80000000 + 16r80000000] ! ! !Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'di 7/14/2004 12:26'! signedIntToShort "Produces a 16-bit value (0-65k) in twos-comp form. Sorry no error checking" self >= 0 ifTrue: [^ self] ifFalse: [^ self + 16r8000 + 16r8000] ! ! !InterpreterPlugin methodsFor: 'initialize' stamp: 'ikp 8/3/2004 19:18'! getInterpreter "Note: This is coded so that plugins can be run from Squeak." self returnTypeC: 'VirtualMachine *'. ^interpreterProxy! ! !BalloonEngineBase methodsFor: 'accessing state' stamp: 'ar 7/11/2004 13:43'! workBufferPut: wbOop workBuffer := interpreterProxy firstIndexableField: wbOop.! ! !BalloonEngineBase methodsFor: 'displaying' stamp: 'ikp 8/9/2004 18:22'! fillSpan: fill from: leftX to: rightX "Fill the span buffer from leftX to rightX with the given fill. Clip before performing any operations. Return true if the fill must be handled by some Smalltalk code." | x0 x1 type | self var: #fill type: 'unsigned int'. self inline: false. fill = 0 ifTrue:[^false]. "Nothing to do" "Start from spEnd - we must not paint pixels twice at a scan line" leftX < self spanEndAAGet ifTrue:[x0 _ self spanEndAAGet] ifFalse:[x0 _ leftX]. rightX > (self spanSizeGet << self aaShiftGet) ifTrue:[x1 _ (self spanSizeGet << self aaShiftGet)] ifFalse:[x1 _ rightX]. "Clip left and right values" x0 < self fillMinXGet ifTrue:[x0 _ self fillMinXGet]. x1 > self fillMaxXGet ifTrue:[x1 _ self fillMaxXGet]. "Adjust start and end values of span" x0 < self spanStartGet ifTrue:[self spanStartPut: x0]. x1 > self spanEndGet ifTrue:[self spanEndPut: x1]. x1 > self spanEndAAGet ifTrue:[self spanEndAAPut: x1]. x0 >= x1 ifTrue:[^false]. "Nothing to do" (self isFillColor: fill) ifTrue:[ self fillColorSpan: fill from: x0 to: x1. ] ifFalse:[ "Store the values for the dispatch" self lastExportedFillPut: fill. self lastExportedLeftXPut: x0. self lastExportedRightXPut: x1. type _ self fillTypeOf: fill. type <= 1 ifTrue:[^true]. self dispatchOn: type in: FillTable. ]. ^false! ! !BalloonEngineBase methodsFor: 'GET processing' stamp: 'di 7/14/2004 13:09'! initializeGETProcessing "Initialization stuff that needs to be done before any processing can take place." self inline: false. "Make sure aaLevel is initialized" self setAALevel: self aaLevelGet. self clipMinXGet < 0 ifTrue:[self clipMinXPut: 0]. self clipMaxXGet > self spanSizeGet ifTrue:[self clipMaxXPut: self spanSizeGet]. "Convert clipRect to aaLevel" self fillMinXPut: self clipMinXGet << self aaShiftGet. self fillMinYPut: self clipMinYGet << self aaShiftGet. self fillMaxXPut: self clipMaxXGet << self aaShiftGet. self fillMaxYPut: self clipMaxYGet << self aaShiftGet. "Reset GET and AET" self getUsedPut: 0. self aetUsedPut: 0. getBuffer _ objBuffer + objUsed. aetBuffer _ objBuffer + objUsed. "Create the global edge table" self createGlobalEdgeTable. engineStopped ifTrue:[^nil]. self getUsedGet = 0 ifTrue:[ "Nothing to do" self currentYPut: self fillMaxYGet. ^0]. "Sort entries in the GET" self sortGlobalEdgeTable. "Find the first y value to be processed" self currentYPut: (self edgeYValueOf: (getBuffer at: 0)). self currentYGet < self fillMinYGet ifTrue:[self currentYPut: self fillMinYGet]. "Load and clear the span buffer" self spanStartPut: 0. self spanEndPut: (self spanSizeGet << self aaShiftGet) - 1. self clearSpanBuffer. "@@: Is this really necessary?!!"! ! !BalloonEngineBase methodsFor: 'private' stamp: 'ikp 6/14/2004 15:14'! copyBitsFrom: x0 to: x1 at: yValue copyBitsFn = 0 ifTrue: [ "We need copyBits here so try to load it implicitly" self initialiseModule ifFalse: [^false]. ]. ^self cCode: '((sqInt (*)(sqInt, sqInt, sqInt))copyBitsFn)(x0, x1, yValue)'! ! !BalloonEngineBase methodsFor: 'private' stamp: 'ikp 6/14/2004 15:14'! loadBitBltFrom: bbObj loadBBFn = 0 ifTrue: [ "We need copyBits here so try to load it implicitly" self initialiseModule ifFalse:[^false]. ]. ^self cCode: '((sqInt (*)(sqInt))loadBBFn)(bbObj)'! ! !BalloonEngineBase methodsFor: 'loading state' stamp: 'ar 7/11/2004 13:42'! loadWorkBufferFrom: wbOop "Load the working buffer from the given oop" self inline: false. (interpreterProxy isIntegerObject: wbOop) ifTrue:[^false]. (interpreterProxy isWords: wbOop) ifFalse:[^false]. (interpreterProxy slotSizeOf: wbOop) < GWMinimalSize ifTrue:[^false]. self workBufferPut: wbOop. self magicNumberGet = GWMagicNumber ifFalse:[^false]. "Sanity checks" (self wbSizeGet = (interpreterProxy slotSizeOf: wbOop)) ifFalse:[^false]. self objStartGet = GWHeaderSize ifFalse:[^false]. "Load buffers" objBuffer _ workBuffer + self objStartGet. getBuffer _ objBuffer + self objUsedGet. aetBuffer _ getBuffer + self getUsedGet. "Make sure we don't exceed the work buffer" GWHeaderSize + self objUsedGet + self getUsedGet + self aetUsedGet > self wbSizeGet ifTrue:[^false]. ^true! ! !BalloonEngineBase methodsFor: 'primitives-other' stamp: 'ar 7/11/2004 13:42'! primitiveInitializeBuffer | wbOop size | self export: true. self inline: false. interpreterProxy methodArgumentCount = 1 ifFalse:[^interpreterProxy primitiveFail]. wbOop _ interpreterProxy stackObjectValue: 0. interpreterProxy failed ifTrue:[^nil]. (interpreterProxy isWords: wbOop) ifFalse:[^interpreterProxy primitiveFail]. (size _ interpreterProxy slotSizeOf: wbOop) < GWMinimalSize ifTrue:[^interpreterProxy primitiveFail]. self workBufferPut: wbOop. objBuffer _ workBuffer + GWHeaderSize. self magicNumberPut: GWMagicNumber. self wbSizePut: size. self wbTopPut: size. self statePut: GEStateUnlocked. self objStartPut: GWHeaderSize. self objUsedPut: 4. "Dummy fill object" self objectTypeOf: 0 put: GEPrimitiveFill. self objectLengthOf: 0 put: 4. self objectIndexOf: 0 put: 0. self getStartPut: 0. self getUsedPut: 0. self aetStartPut: 0. self aetUsedPut: 0. self stopReasonPut: 0. self needsFlushPut: 0. self clipMinXPut: 0. self clipMaxXPut: 0. self clipMinYPut: 0. self clipMaxYPut: 0. self currentZPut: 0. self resetGraphicsEngineStats. self initEdgeTransform. self initColorTransform. interpreterProxy pop: 2. interpreterProxy push: wbOop.! ! !BalloonEnginePlugin methodsFor: 'fills-bitmaps' stamp: 'ikp 6/14/2004 15:22'! bitmapValue: bmFill bits: bits atX: xp y: yp | bmDepth bmRaster value rShift cMask r g b a | self inline: true. bmDepth _ self bitmapDepthOf: bmFill. bmRaster _ self bitmapRasterOf: bmFill. bmDepth = 32 ifTrue: [ value _ (self cCoerce: bits to:'int*') at: (bmRaster * yp) + xp. (value ~= 0 and: [(value bitAnd: 16rFF000000) = 0]) ifTrue: [value _ value bitOr: 16rFF000000]. ^self uncheckedTransformColor: value]. "rShift - shift value to convert from pixel to word index" rShift _ self rShiftTable at: bmDepth. value _ self makeUnsignedFrom: ((self cCoerce: bits to:'int*') at: (bmRaster * yp) + (xp >> rShift)). "cMask - mask out the pixel from the word" cMask _ (1 << bmDepth) - 1. "rShift - shift value to move the pixel in the word to the lowest bit position" rShift _ 32 - bmDepth - ((xp bitAnd: (1 << rShift - 1)) * bmDepth). value _ (value >> rShift) bitAnd: cMask. bmDepth = 16 ifTrue: [ "Must convert by expanding bits" value = 0 ifFalse: [ b _ (value bitAnd: 31) << 3. b _ b + (b >> 5). g _ (value >> 5 bitAnd: 31) << 3. g _ g + (g >> 5). r _ (value >> 10 bitAnd: 31) << 3. r _ r + (r >> 5). a _ 255. value _ b + (g << 8) + (r << 16) + (a << 24)]. ] ifFalse: [ "Must convert by using color map" (self bitmapCmSizeOf: bmFill) = 0 ifTrue: [value _ 0] ifFalse: [value _ self makeUnsignedFrom: ((self colormapOf: bmFill) at: value)]. ]. ^self uncheckedTransformColor: value.! ! !BalloonEnginePlugin methodsFor: 'shapes-compressed' stamp: 'di 7/16/2004 15:19'! checkCompressedFillIndexList: fillList max: maxIndex segments: nSegs "Check the fill indexes in the run-length encoded fillList" | length runLength runValue nFills fillPtr | self inline: false. self var: #fillPtr declareC:'int *fillPtr'. length _ interpreterProxy slotSizeOf: fillList. fillPtr _ interpreterProxy firstIndexableField: fillList. nFills _ 0. 0 to: length-1 do:[:i | runLength _ self shortRunLengthAt: i from: fillPtr. runValue _ self shortRunValueAt: i from: fillPtr. (runValue >= 0 and:[runValue <= maxIndex]) ifFalse:[^false]. nFills _ nFills + runLength. ]. ^nFills = nSegs! ! !BalloonEnginePlugin methodsFor: 'shapes-compressed' stamp: 'di 7/16/2004 15:13'! checkCompressedFills: indexList "Check if the indexList (containing fill handles) is okay." | fillPtr length fillIndex | self inline: false. self var: #fillPtr declareC:'int *fillPtr'. "First check if the oops have the right format" (interpreterProxy isWords: indexList) ifFalse:[^false]. "Then check the fill entries" length _ interpreterProxy slotSizeOf: indexList. fillPtr _ interpreterProxy firstIndexableField: indexList. 0 to: length-1 do:[:i | fillIndex _ fillPtr at: i. "Make sure the fill is okay" (self isFillOkay: fillIndex) ifFalse:[^false]]. ^ true! ! !BalloonEngineSimulation methodsFor: 'simulation' stamp: 'di 7/13/2004 16:42'! copyBitsFrom: x0 to: x1 at: y "Simulate the copyBits primitive" | bb | bbObj isInteger ifTrue: ["Create a proxy object to handle BitBlt calls" bb _ BitBltSimulator new. bb initialiseModule. bb setInterpreter: interpreterProxy. (bb loadBitBltFrom: bbObj) ifTrue: [bbObj _ bb] ifFalse: [^ self]]. bbObj copyBitsFrom: x0 to: x1 at: y. " interpreterProxy showDisplayBits: bbObj destForm Left: bb affectedLeft Top: bb affectedTop Right: bb affectedRight Bottom: bb affectedBottom. "! ! !BalloonEngineSimulation methodsFor: 'simulation' stamp: 'di 7/16/2004 15:07'! loadPointShortAt: index from: intArray "Load the short value from the given index in intArray" | long | long _ intArray at: index // 2. ^ ((index bitAnd: 1) = 0 ifTrue:[interpreterProxy halfWordHighInLong32: long] ifFalse:[interpreterProxy halfWordLowInLong32: long]) signedIntFromShort ! ! !BalloonEngineSimulation methodsFor: 'simulation' stamp: 'di 7/16/2004 15:11'! shortRunLengthAt: index from: runArray "Load the short value from the given index in intArray" ^ interpreterProxy halfWordHighInLong32: (runArray at: index)! ! !BalloonEngineSimulation methodsFor: 'simulation' stamp: 'di 7/16/2004 15:10'! shortRunValueAt: index from: runArray "Load the short value from the given index in intArray" ^ (interpreterProxy halfWordLowInLong32: (runArray at: index)) signedIntFromShort ! ! !BalloonEngineSimulation methodsFor: 'simulation' stamp: 'di 7/16/2004 12:37'! workBufferPut: wbOop interpreterProxy isInterpreterProxy ifTrue:[^super workBufferPut: wbOop]. workBuffer := ((interpreterProxy firstIndexableField: wbOop) as: BalloonArray) asCArrayAccessor. workBufferArray ifNil: [workBufferArray _ Array new: (interpreterProxy slotSizeOf: wbOop)]. workBuffer getObject setSimArray: workBufferArray! ! !BalloonEngineSimulation methodsFor: 'initialize' stamp: 'di 7/12/2004 15:54'! initialiseModule super initialiseModule. ^ true! ! !BalloonEngineSimulation methodsFor: 'initialize' stamp: 'di 7/15/2004 16:19'! loadWordTransformFrom: transformOop into: destPtr length: n "Load a float array transformation from the given oop" | srcPtr wordDestPtr | true ifTrue: [^ super loadWordTransformFrom: transformOop into: destPtr length: n]. srcPtr _ interpreterProxy firstIndexableField: transformOop. wordDestPtr _ destPtr as: CArrayAccessor. "Remove float conversion shell" 0 to: n-1 do: [:i | wordDestPtr at: i put: (srcPtr at: i)].! ! !BalloonEngineSimulation methodsFor: 'initialize' stamp: 'di 7/16/2004 12:06'! primitiveInitializeBuffer "Fix an uninitialized variable (should probably go into the real engine too)" super primitiveInitializeBuffer. self spanEndAAPut: 0.! ! !BalloonEngineSimulation methodsFor: 'initialize' stamp: 'di 7/12/2004 16:15'! primitiveSetBitBltPlugin "Primitive. Set the BitBlt plugin to use." | pluginName | pluginName _ interpreterProxy stackValue: 0. "Must be string to work" (interpreterProxy isBytes: pluginName) ifFalse:[^interpreterProxy primitiveFail]. (interpreterProxy stringOf: pluginName) = bbPluginName ifTrue: [interpreterProxy pop: 1. "Return receiver"] ifFalse: [^interpreterProxy primitiveFail]! ! !BitBltSimulation methodsFor: 'combination rules' stamp: 'ikp 6/11/2004 16:38'! merge: sourceWord with: destinationWord | mergeFnwith | "Sender warpLoop is too big to include this in-line" self var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'. mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'. mergeFnwith. "null ref for compiler" ^ self mergeFn: sourceWord with: destinationWord! ! !BitBltSimulation methodsFor: 'inner loop' stamp: 'ikp 8/4/2004 18:03'! alphaSourceBlendBits32 "This version assumes combinationRule = 34 sourcePixSize = destPixSize = 32 sourceForm ~= destForm. Note: The inner loop has been optimized for dealing with the special cases of srcAlpha = 0.0 and srcAlpha = 1.0 " | srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY srcY dstY | self inline: false. "This particular method should be optimized in itself" "Give the compile a couple of hints" "The following should be declared as pointers so the compiler will notice that they're used for accessing memory locations (good to know on an Intel architecture) but then the increments would be different between ST code and C code so must hope the compiler notices what happens (MS Visual C does)" deltaY _ bbH + 1. "So we can pre-decrement" srcY _ sy. dstY _ dy. "This is the outer loop" [(deltaY _ deltaY - 1) ~= 0] whileTrue:[ srcIndex _ sourceBits + (srcY * sourcePitch) + (sx * 4). dstIndex _ destBits + (dstY * destPitch) + (dx * 4). deltaX _ bbW + 1. "So we can pre-decrement" "This is the inner loop" [(deltaX _ deltaX - 1) ~= 0] whileTrue:[ sourceWord _ self srcLongAt: srcIndex. srcAlpha _ sourceWord >> 24. srcAlpha = 255 ifTrue:[ self dstLongAt: dstIndex put: sourceWord. srcIndex _ srcIndex + 4. dstIndex _ dstIndex + 4. "Now copy as many words as possible with alpha = 255" [(deltaX _ deltaX - 1) ~= 0 and:[ (sourceWord _ self srcLongAt: srcIndex) >> 24 = 255]] whileTrue:[ self dstLongAt: dstIndex put: sourceWord. srcIndex _ srcIndex + 4. dstIndex _ dstIndex + 4. ]. "Adjust deltaX" deltaX _ deltaX + 1. ] ifFalse:[ "srcAlpha ~= 255" srcAlpha = 0 ifTrue:[ srcIndex _ srcIndex + 4. dstIndex _ dstIndex + 4. "Now skip as many words as possible," [(deltaX _ deltaX - 1) ~= 0 and:[ (sourceWord _ self srcLongAt: srcIndex) >> 24 = 0]] whileTrue:[ srcIndex _ srcIndex + 4. dstIndex _ dstIndex + 4. ]. "Adjust deltaX" deltaX _ deltaX + 1. ] ifFalse:[ "0 < srcAlpha < 255" "If we have to mix colors then just copy a single word" destWord _ self dstLongAt: dstIndex. destWord _ self alphaBlendScaled: sourceWord with: destWord. self dstLongAt: dstIndex put: destWord. srcIndex _ srcIndex + 4. dstIndex _ dstIndex + 4. ]. ]. ]. srcY _ srcY + 1. dstY _ dstY + 1. ].! ! !BitBltSimulation methodsFor: 'inner loop' stamp: 'ikp 6/11/2004 16:27'! copyLoop | prevWord thisWord skewWord halftoneWord mergeWord hInc y unskew skewMask notSkewMask mergeFnwith destWord | "This version of the inner loop assumes noSource = false." self inline: false. self var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'. mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'. mergeFnwith. "null ref for compiler" hInc _ hDir*4. "Byte delta" "degenerate skew fixed for Sparc. 10/20/96 ikp" skew == -32 ifTrue: [skew _ unskew _ skewMask _ 0] ifFalse: [skew < 0 ifTrue: [unskew _ skew+32. skewMask _ AllOnes << (0-skew)] ifFalse: [skew = 0 ifTrue: [unskew _ 0. skewMask _ AllOnes] ifFalse: [unskew _ skew-32. skewMask _ AllOnes >> skew]]]. notSkewMask _ skewMask bitInvert32. noHalftone ifTrue: [halftoneWord _ AllOnes. halftoneHeight _ 0] ifFalse: [halftoneWord _ self halftoneAt: 0]. y _ dy. 1 to: bbH do: "here is the vertical loop" [ :i | halftoneHeight > 1 ifTrue: "Otherwise, its always the same" [halftoneWord _ self halftoneAt: y. y _ y + vDir]. preload ifTrue: ["load the 64-bit shifter" prevWord _ self srcLongAt: sourceIndex. sourceIndex _ sourceIndex + hInc] ifFalse: [prevWord _ 0]. "Note: the horizontal loop has been expanded into three parts for speed:" "This first section requires masking of the destination store..." destMask _ mask1. thisWord _ self srcLongAt: sourceIndex. "pick up next word" sourceIndex _ sourceIndex + hInc. skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew) bitOr: "32-bit rotate" ((thisWord bitAnd: skewMask) bitShift: skew). prevWord _ thisWord. destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: destWord. destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. destIndex _ destIndex + hInc. "This central horizontal loop requires no store masking" destMask _ AllOnes. combinationRule = 3 ifTrue: [(skew = 0) & (halftoneWord = AllOnes) ifTrue: ["Very special inner loop for STORE mode with no skew -- just move words" hDir = -1 ifTrue: ["Woeful patch: revert to older code for hDir = -1" 2 to: nWords-1 do: [ :word | thisWord _ self srcLongAt: sourceIndex. sourceIndex _ sourceIndex + hInc. self dstLongAt: destIndex put: thisWord. destIndex _ destIndex + hInc]] ifFalse: [2 to: nWords-1 do: [ :word | "Note loop starts with prevWord loaded (due to preload)" self dstLongAt: destIndex put: prevWord. destIndex _ destIndex + hInc. prevWord _ self srcLongAt: sourceIndex. sourceIndex _ sourceIndex + hInc]]] ifFalse: ["Special inner loop for STORE mode -- no need to call merge" 2 to: nWords-1 do: [ :word | thisWord _ self srcLongAt: sourceIndex. sourceIndex _ sourceIndex + hInc. skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew) bitOr: "32-bit rotate" ((thisWord bitAnd: skewMask) bitShift: skew). prevWord _ thisWord. self dstLongAt: destIndex put: (skewWord bitAnd: halftoneWord). destIndex _ destIndex + hInc]] ] ifFalse: [2 to: nWords-1 do: "Normal inner loop does merge:" [ :word | thisWord _ self srcLongAt: sourceIndex. "pick up next word" sourceIndex _ sourceIndex + hInc. skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew) bitOr: "32-bit rotate" ((thisWord bitAnd: skewMask) bitShift: skew). prevWord _ thisWord. mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: (self dstLongAt: destIndex). self dstLongAt: destIndex put: mergeWord. destIndex _ destIndex + hInc] ]. "This last section, if used, requires masking of the destination store..." nWords > 1 ifTrue: [destMask _ mask2. thisWord _ self srcLongAt: sourceIndex. "pick up next word" sourceIndex _ sourceIndex + hInc. skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew) bitOr: "32-bit rotate" ((thisWord bitAnd: skewMask) bitShift: skew). destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: destWord. destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. destIndex _ destIndex + hInc]. sourceIndex _ sourceIndex + sourceDelta. destIndex _ destIndex + destDelta]! ! !BitBltSimulation methodsFor: 'inner loop' stamp: 'ikp 6/11/2004 16:27'! copyLoopNoSource "Faster copyLoop when source not used. hDir and vDir are both positive, and perload and skew are unused" | halftoneWord mergeWord mergeFnwith destWord | self inline: false. self var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'. mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'. mergeFnwith. "null ref for compiler" 1 to: bbH do: "here is the vertical loop" [ :i | noHalftone ifTrue: [halftoneWord _ AllOnes] ifFalse: [halftoneWord _ self halftoneAt: dy+i-1]. "Note: the horizontal loop has been expanded into three parts for speed:" "This first section requires masking of the destination store..." destMask _ mask1. destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: halftoneWord with: destWord. destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. destIndex _ destIndex + 4. "This central horizontal loop requires no store masking" destMask _ AllOnes. combinationRule = 3 ifTrue: ["Special inner loop for STORE" destWord _ halftoneWord. 2 to: nWords-1 do:[ :word | self dstLongAt: destIndex put: destWord. destIndex _ destIndex + 4]. ] ifFalse:[ "Normal inner loop does merge" 2 to: nWords-1 do:[ :word | "Normal inner loop does merge" destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: halftoneWord with: destWord. self dstLongAt: destIndex put: mergeWord. destIndex _ destIndex + 4]. ]. "This last section, if used, requires masking of the destination store..." nWords > 1 ifTrue: [destMask _ mask2. destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: halftoneWord with: destWord. destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. destIndex _ destIndex + 4]. destIndex _ destIndex + destDelta]! ! !BitBltSimulation methodsFor: 'inner loop' stamp: 'ikp 6/11/2004 16:28'! copyLoopPixMap "This version of the inner loop maps source pixels to a destination form with different depth. Because it is already unweildy, the loop is not unrolled as in the other versions. Preload, skew and skewMask are all overlooked, since pickSourcePixels delivers its destination word already properly aligned. Note that pickSourcePixels could be copied in-line at the top of the horizontal loop, and some of its inits moved out of the loop." "ar 12/7/1999: The loop has been rewritten to use only one pickSourcePixels call. The idea is that the call itself could be inlined. If we decide not to inline pickSourcePixels we could optimize the loop instead." | skewWord halftoneWord mergeWord scrStartBits nSourceIncs startBits endBits sourcePixMask destPixMask mergeFnwith nPix srcShift dstShift destWord words srcShiftInc dstShiftInc dstShiftLeft mapperFlags | self inline: false. self var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'. mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'. mergeFnwith. "null ref for compiler" "Additional inits peculiar to unequal source and dest pix size..." sourcePPW _ 32//sourceDepth. sourcePixMask _ maskTable at: sourceDepth. destPixMask _ maskTable at: destDepth. mapperFlags _ cmFlags bitAnd: ColorMapNewStyle bitInvert32. sourceIndex _ sourceBits + (sy * sourcePitch) + ((sx // sourcePPW) *4). scrStartBits _ sourcePPW - (sx bitAnd: sourcePPW-1). bbW < scrStartBits ifTrue: [nSourceIncs _ 0] ifFalse: [nSourceIncs _ (bbW - scrStartBits)//sourcePPW + 1]. sourceDelta _ sourcePitch - (nSourceIncs * 4). "Note following two items were already calculated in destmask setup!!" startBits _ destPPW - (dx bitAnd: destPPW-1). endBits _ ((dx + bbW - 1) bitAnd: destPPW-1) + 1. bbW < startBits ifTrue:[startBits _ bbW]. "Precomputed shifts for pickSourcePixels" srcShift _ ((sx bitAnd: sourcePPW - 1) * sourceDepth). dstShift _ ((dx bitAnd: destPPW - 1) * destDepth). srcShiftInc _ sourceDepth. dstShiftInc _ destDepth. dstShiftLeft _ 0. sourceMSB ifTrue:[ srcShift _ 32 - sourceDepth - srcShift. srcShiftInc _ 0 - srcShiftInc]. destMSB ifTrue:[ dstShift _ 32 - destDepth - dstShift. dstShiftInc _ 0 - dstShiftInc. dstShiftLeft _ 32 - destDepth]. 1 to: bbH do: "here is the vertical loop" [ :i | "*** is it possible at all that noHalftone == false? ***" noHalftone ifTrue:[halftoneWord _ AllOnes] ifFalse: [halftoneWord _ self halftoneAt: dy+i-1]. "setup first load" srcBitShift _ srcShift. dstBitShift _ dstShift. destMask _ mask1. nPix _ startBits. "Here is the horizontal loop..." words _ nWords. ["pick up the word" skewWord _ self pickSourcePixels: nPix flags: mapperFlags srcMask: sourcePixMask destMask: destPixMask srcShiftInc: srcShiftInc dstShiftInc: dstShiftInc. "align next word to leftmost pixel" dstBitShift _ dstShiftLeft. destMask = AllOnes ifTrue:["avoid read-modify-write" mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: (self dstLongAt: destIndex). self dstLongAt: destIndex put: (destMask bitAnd: mergeWord). ] ifFalse:[ "General version using dest masking" destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: (destWord bitAnd: destMask). destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. ]. destIndex _ destIndex + 4. words = 2 "e.g., is the next word the last word?" ifTrue:["set mask for last word in this row" destMask _ mask2. nPix _ endBits] ifFalse:["use fullword mask for inner loop" destMask _ AllOnes. nPix _ destPPW]. (words _ words - 1) = 0] whileFalse. "--- end of inner loop ---" sourceIndex _ sourceIndex + sourceDelta. destIndex _ destIndex + destDelta] ! ! !BitBltSimulation methodsFor: 'inner loop' stamp: 'ikp 8/2/2004 19:49'! warpLoop "This version of the inner loop traverses an arbirary quadrilateral source, thus producing a general affine transformation." | skewWord halftoneWord mergeWord startBits deltaP12x deltaP12y deltaP43x deltaP43y pAx pAy pBx pBy xDelta yDelta smoothingCount sourceMapOop nSteps nPix words destWord endBits mergeFnwith dstShiftInc dstShiftLeft mapperFlags | self inline: false. self var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'. mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'. mergeFnwith. "null ref for compiler" (interpreterProxy slotSizeOf: bitBltOop) >= (BBWarpBase+12) ifFalse: [^ interpreterProxy primitiveFail]. nSteps _ height-1. nSteps <= 0 ifTrue: [nSteps _ 1]. pAx _ self fetchIntOrFloat: BBWarpBase ofObject: bitBltOop. words _ self fetchIntOrFloat: BBWarpBase+3 ofObject: bitBltOop. deltaP12x _ self deltaFrom: pAx to: words nSteps: nSteps. deltaP12x < 0 ifTrue: [pAx _ words - (nSteps*deltaP12x)]. pAy _ self fetchIntOrFloat: BBWarpBase+1 ofObject: bitBltOop. words _ self fetchIntOrFloat: BBWarpBase+4 ofObject: bitBltOop. deltaP12y _ self deltaFrom: pAy to: words nSteps: nSteps. deltaP12y < 0 ifTrue: [pAy _ words - (nSteps*deltaP12y)]. pBx _ self fetchIntOrFloat: BBWarpBase+9 ofObject: bitBltOop. words _ self fetchIntOrFloat: BBWarpBase+6 ofObject: bitBltOop. deltaP43x _ self deltaFrom: pBx to: words nSteps: nSteps. deltaP43x < 0 ifTrue: [pBx _ words - (nSteps*deltaP43x)]. pBy _ self fetchIntOrFloat: BBWarpBase+10 ofObject: bitBltOop. words _ self fetchIntOrFloat: BBWarpBase+7 ofObject: bitBltOop. deltaP43y _ self deltaFrom: pBy to: words nSteps: nSteps. deltaP43y < 0 ifTrue: [pBy _ words - (nSteps*deltaP43y)]. interpreterProxy failed ifTrue: [^ false]. "ie if non-integers above" interpreterProxy methodArgumentCount = 2 ifTrue: [smoothingCount _ interpreterProxy stackIntegerValue: 1. sourceMapOop _ interpreterProxy stackValue: 0. sourceMapOop = interpreterProxy nilObject ifTrue: [sourceDepth < 16 ifTrue: ["color map is required to smooth non-RGB dest" ^ interpreterProxy primitiveFail]] ifFalse: [(interpreterProxy slotSizeOf: sourceMapOop) < (1 << sourceDepth) ifTrue: ["sourceMap must be long enough for sourceDepth" ^ interpreterProxy primitiveFail]. sourceMapOop _ self oopForPointer: (interpreterProxy firstIndexableField: sourceMapOop)]] ifFalse: [smoothingCount _ 1. sourceMapOop _ interpreterProxy nilObject]. nSteps _ width-1. nSteps <= 0 ifTrue: [nSteps _ 1]. startBits _ destPPW - (dx bitAnd: destPPW-1). endBits _ ((dx + bbW - 1) bitAnd: destPPW-1) + 1. bbW < startBits ifTrue:[startBits _ bbW]. destY < clipY ifTrue:[ "Advance increments if there was clipping in y" pAx _ pAx + (clipY - destY * deltaP12x). pAy _ pAy + (clipY - destY * deltaP12y). pBx _ pBx + (clipY - destY * deltaP43x). pBy _ pBy + (clipY - destY * deltaP43y)]. "Setup values for faster pixel fetching." self warpLoopSetup. "Setup color mapping if not provided" (smoothingCount > 1 and:[(cmFlags bitAnd: ColorMapNewStyle) = 0]) ifTrue:[ cmLookupTable == nil ifTrue:[ destDepth = 16 ifTrue:[self setupColorMasksFrom: 8 to: 5]. ] ifFalse:[ self setupColorMasksFrom: 8 to: cmBitsPerColor. ]. ]. mapperFlags _ cmFlags bitAnd: ColorMapNewStyle bitInvert32. destMSB ifTrue:[ dstShiftInc _ 0 - destDepth. dstShiftLeft _ 32 - destDepth] ifFalse:[ dstShiftInc _ destDepth. dstShiftLeft _ 0]. 1 to: bbH do: [ :i | "here is the vertical loop..." xDelta _ self deltaFrom: pAx to: pBx nSteps: nSteps. xDelta >= 0 ifTrue: [sx _ pAx] ifFalse: [sx _ pBx - (nSteps*xDelta)]. yDelta _ self deltaFrom: pAy to: pBy nSteps: nSteps. yDelta >= 0 ifTrue: [sy _ pAy] ifFalse: [sy _ pBy - (nSteps*yDelta)]. destMSB ifTrue:[dstBitShift _ 32 - ((dx bitAnd: destPPW - 1) + 1 * destDepth)] ifFalse:[dstBitShift _ (dx bitAnd: destPPW - 1) * destDepth]. (destX < clipX) ifTrue:[ "Advance increments if there was clipping in x" sx _ sx + (clipX - destX * xDelta). sy _ sy + (clipX - destX * yDelta). ]. noHalftone ifTrue: [halftoneWord _ AllOnes] ifFalse: [halftoneWord _ self halftoneAt: dy+i-1]. destMask _ mask1. nPix _ startBits. "Here is the inner loop..." words _ nWords. ["pick up word" smoothingCount = 1 ifTrue:["Faster if not smoothing" skewWord _ self warpPickSourcePixels: nPix xDeltah: xDelta yDeltah: yDelta xDeltav: deltaP12x yDeltav: deltaP12y dstShiftInc: dstShiftInc flags: mapperFlags. ] ifFalse:["more difficult with smoothing" skewWord _ self warpPickSmoothPixels: nPix xDeltah: xDelta yDeltah: yDelta xDeltav: deltaP12x yDeltav: deltaP12y sourceMap: sourceMapOop smoothing: smoothingCount dstShiftInc: dstShiftInc. ]. "align next word access to left most pixel" dstBitShift _ dstShiftLeft. destMask = AllOnes ifTrue:["avoid read-modify-write" mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: (self dstLongAt: destIndex). self dstLongAt: destIndex put: (destMask bitAnd: mergeWord). ] ifFalse:[ "General version using dest masking" destWord _ self dstLongAt: destIndex. mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord) with: (destWord bitAnd: destMask). destWord _ (destMask bitAnd: mergeWord) bitOr: (destWord bitAnd: destMask bitInvert32). self dstLongAt: destIndex put: destWord. ]. destIndex _ destIndex + 4. words = 2 "e.g., is the next word the last word?" ifTrue:["set mask for last word in this row" destMask _ mask2. nPix _ endBits] ifFalse:["use fullword mask for inner loop" destMask _ AllOnes. nPix _ destPPW]. (words _ words - 1) = 0] whileFalse. "--- end of inner loop ---" pAx _ pAx + deltaP12x. pAy _ pAy + deltaP12y. pBx _ pBx + deltaP43x. pBy _ pBy + deltaP43y. destIndex _ destIndex + destDelta]! ! !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'ikp 8/2/2004 20:25'! warpPickSmoothPixels: nPixels xDeltah: xDeltah yDeltah: yDeltah xDeltav: xDeltav yDeltav: yDeltav sourceMap: sourceMap smoothing: n dstShiftInc: dstShiftInc "Pick n (sub-) pixels from the source form, mapped by sourceMap, average the RGB values, map by colorMap and return the new word. This version is only called from WarpBlt with smoothingCount > 1" | rgb x y a r g b xx yy xdh ydh xdv ydv dstMask destWord i j k nPix | self inline: false. "nope - too much stuff in here" dstMask _ maskTable at: destDepth. destWord _ 0. n = 2 "Try avoiding divides for most common n (divide by 2 is generated as shift)" ifTrue:[xdh _ xDeltah // 2. ydh _ yDeltah // 2. xdv _ xDeltav // 2. ydv _ yDeltav // 2] ifFalse:[xdh _ xDeltah // n. ydh _ yDeltah // n. xdv _ xDeltav // n. ydv _ yDeltav // n]. i _ nPixels. [ x _ sx. y _ sy. a _ r _ g _ b _ 0. "Pick and average n*n subpixels" nPix _ 0. "actual number of pixels (not clipped and not transparent)" j _ n. [ xx _ x. yy _ y. k _ n. [ "get a single subpixel" rgb _ self pickWarpPixelAtX: xx y: yy. (combinationRule=25 "PAINT" and: [rgb = 0]) ifFalse:[ "If not clipped and not transparent, then tally rgb values" nPix _ nPix + 1. sourceDepth < 16 ifTrue:[ "Get RGBA values from sourcemap table" rgb _ self long32At: sourceMap + (rgb << 2). ] ifFalse:["Already in RGB format" sourceDepth = 16 ifTrue:[rgb _ self rgbMap16To32: rgb] ifFalse:[rgb _ self rgbMap32To32: rgb]]. b _ b + (rgb bitAnd: 255). g _ g + (rgb >> 8 bitAnd: 255). r _ r + (rgb >> 16 bitAnd: 255). a _ a + (rgb >> 24)]. xx _ xx + xdh. yy _ yy + ydh. (k _ k - 1) = 0] whileFalse. x _ x + xdv. y _ y + ydv. (j _ j - 1) = 0] whileFalse. (nPix = 0 or: [combinationRule=25 "PAINT" and: [nPix < (n * n // 2)]]) ifTrue:[ rgb _ 0 "All pixels were 0, or most were transparent" ] ifFalse:[ "normalize rgba sums" nPix = 4 "Try to avoid divides for most common n" ifTrue:[r _ r >> 2. g _ g >> 2. b _ b >> 2. a _ a >> 2] ifFalse:[ r _ r // nPix. g _ g // nPix. b _ b // nPix. a _ a // nPix]. rgb _ (a << 24) + (r << 16) + (g << 8) + b. "map the pixel" rgb = 0 ifTrue: [ "only generate zero if pixel is really transparent" (r + g + b + a) > 0 ifTrue: [rgb _ 1]]. rgb _ self mapPixel: rgb flags: cmFlags. ]. "Mix it in" destWord _ destWord bitOr: (rgb bitAnd: dstMask) << dstBitShift. dstBitShift _ dstBitShift + dstShiftInc. sx _ sx + xDeltah. sy _ sy + yDeltah. (i _ i - 1) = 0] whileFalse. ^destWord ! ! !BitBltSimulation methodsFor: 'interpreter interface' stamp: 'ikp 8/2/2004 19:48'! loadBitBltDestForm "Load the dest form for BitBlt. Return false if anything is wrong, true otherwise." | destBitsSize | self inline: true. destBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: destForm. destWidth _ interpreterProxy fetchInteger: FormWidthIndex ofObject: destForm. destHeight _ interpreterProxy fetchInteger: FormHeightIndex ofObject: destForm. (destWidth >= 0 and: [destHeight >= 0]) ifFalse: [^ false]. destDepth _ interpreterProxy fetchInteger: FormDepthIndex ofObject: destForm. destMSB _ destDepth > 0. destDepth < 0 ifTrue:[destDepth _ 0 - destDepth]. "Ignore an integer bits handle for Display in which case the appropriate values will be obtained by calling ioLockSurfaceBits()." (interpreterProxy isIntegerObject: destBits) ifTrue:[ "Query for actual surface dimensions" (self queryDestSurface: (interpreterProxy integerValueOf: destBits)) ifFalse:[^false]. destPPW _ 32 // destDepth. destBits _ destPitch _ 0. ] ifFalse:[ destPPW _ 32 // destDepth. destPitch _ destWidth + (destPPW-1) // destPPW * 4. destBitsSize _ interpreterProxy byteSizeOf: destBits. ((interpreterProxy isWordsOrBytes: destBits) and: [destBitsSize = (destPitch * destHeight)]) ifFalse: [^ false]. "Skip header since external bits don't have one" destBits _ self oopForPointer: (interpreterProxy firstIndexableField: destBits). ]. ^true! ! !BitBltSimulation methodsFor: 'interpreter interface' stamp: 'ikp 8/2/2004 19:48'! loadBitBltSourceForm "Load the source form for BitBlt. Return false if anything is wrong, true otherwise." | sourceBitsSize | self inline: true. sourceBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: sourceForm. sourceWidth _ self fetchIntOrFloat: FormWidthIndex ofObject: sourceForm. sourceHeight _ self fetchIntOrFloat: FormHeightIndex ofObject: sourceForm. (sourceWidth >= 0 and: [sourceHeight >= 0]) ifFalse: [^ false]. sourceDepth _ interpreterProxy fetchInteger: FormDepthIndex ofObject: sourceForm. sourceMSB _ sourceDepth > 0. sourceDepth < 0 ifTrue:[sourceDepth _ 0 - sourceDepth]. "Ignore an integer bits handle for Display in which case the appropriate values will be obtained by calling ioLockSurfaceBits()." (interpreterProxy isIntegerObject: sourceBits) ifTrue:[ "Query for actual surface dimensions" (self querySourceSurface: (interpreterProxy integerValueOf: sourceBits)) ifFalse:[^false]. sourcePPW _ 32 // sourceDepth. sourceBits _ sourcePitch _ 0. ] ifFalse:[ sourcePPW _ 32 // sourceDepth. sourcePitch _ sourceWidth + (sourcePPW-1) // sourcePPW * 4. sourceBitsSize _ interpreterProxy byteSizeOf: sourceBits. ((interpreterProxy isWordsOrBytes: sourceBits) and: [sourceBitsSize = (sourcePitch * sourceHeight)]) ifFalse: [^ false]. "Skip header since external bits don't have one" sourceBits _ self oopForPointer: (interpreterProxy firstIndexableField: sourceBits). ]. ^true! ! !BitBltSimulation methodsFor: 'interpreter interface' stamp: 'ikp 8/2/2004 19:49'! loadHalftoneForm "Load the halftone form" | halftoneBits | self inline: true. noHalftone ifTrue:[ halftoneBase _ nil. ^true]. ((interpreterProxy isPointers: halftoneForm) and: [(interpreterProxy slotSizeOf: halftoneForm) >= 4]) ifTrue: ["Old-style 32xN monochrome halftone Forms" halftoneBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: halftoneForm. halftoneHeight _ interpreterProxy fetchInteger: FormHeightIndex ofObject: halftoneForm. (interpreterProxy isWords: halftoneBits) ifFalse: [noHalftone _ true]] ifFalse: ["New spec accepts, basically, a word array" ((interpreterProxy isPointers: halftoneForm) not and: [interpreterProxy isWords: halftoneForm]) ifFalse: [^ false]. halftoneBits _ halftoneForm. halftoneHeight _ interpreterProxy slotSizeOf: halftoneBits]. halftoneBase _ self oopForPointer: (interpreterProxy firstIndexableField: halftoneBits). ^true! ! !BitBltSimulation methodsFor: 'memory access' stamp: 'ikp 8/2/2004 20:25'! dstLongAt: idx ^self long32At: idx! ! !BitBltSimulation methodsFor: 'memory access' stamp: 'ikp 8/2/2004 20:29'! dstLongAt: idx put: value ^self long32At: idx put: value! ! !BitBltSimulation methodsFor: 'memory access' stamp: 'ikp 8/2/2004 20:25'! halftoneAt: idx "Return a value from the halftone pattern." ^self long32At: halftoneBase + (idx \\ halftoneHeight * 4)! ! !BitBltSimulation methodsFor: 'memory access' stamp: 'ikp 8/2/2004 20:25'! srcLongAt: idx ^self long32At: idx! ! !BitBltSimulation methodsFor: 'initialize-release' stamp: 'ikp 6/10/2004 15:02'! initBBOpTable self cCode: 'opTable[0+1] = (void *)clearWordwith'. self cCode: 'opTable[1+1] = (void *)bitAndwith'. self cCode: 'opTable[2+1] = (void *)bitAndInvertwith'. self cCode: 'opTable[3+1] = (void *)sourceWordwith'. self cCode: 'opTable[4+1] = (void *)bitInvertAndwith'. self cCode: 'opTable[5+1] = (void *)destinationWordwith'. self cCode: 'opTable[6+1] = (void *)bitXorwith'. self cCode: 'opTable[7+1] = (void *)bitOrwith'. self cCode: 'opTable[8+1] = (void *)bitInvertAndInvertwith'. self cCode: 'opTable[9+1] = (void *)bitInvertXorwith'. self cCode: 'opTable[10+1] = (void *)bitInvertDestinationwith'. self cCode: 'opTable[11+1] = (void *)bitOrInvertwith'. self cCode: 'opTable[12+1] = (void *)bitInvertSourcewith'. self cCode: 'opTable[13+1] = (void *)bitInvertOrwith'. self cCode: 'opTable[14+1] = (void *)bitInvertOrInvertwith'. self cCode: 'opTable[15+1] = (void *)destinationWordwith'. self cCode: 'opTable[16+1] = (void *)destinationWordwith'. self cCode: 'opTable[17+1] = (void *)destinationWordwith'. self cCode: 'opTable[18+1] = (void *)addWordwith'. self cCode: 'opTable[19+1] = (void *)subWordwith'. self cCode: 'opTable[20+1] = (void *)rgbAddwith'. self cCode: 'opTable[21+1] = (void *)rgbSubwith'. self cCode: 'opTable[22+1] = (void *)OLDrgbDiffwith'. self cCode: 'opTable[23+1] = (void *)OLDtallyIntoMapwith'. self cCode: 'opTable[24+1] = (void *)alphaBlendwith'. self cCode: 'opTable[25+1] = (void *)pixPaintwith'. self cCode: 'opTable[26+1] = (void *)pixMaskwith'. self cCode: 'opTable[27+1] = (void *)rgbMaxwith'. self cCode: 'opTable[28+1] = (void *)rgbMinwith'. self cCode: 'opTable[29+1] = (void *)rgbMinInvertwith'. self cCode: 'opTable[30+1] = (void *)alphaBlendConstwith'. self cCode: 'opTable[31+1] = (void *)alphaPaintConstwith'. self cCode: 'opTable[32+1] = (void *)rgbDiffwith'. self cCode: 'opTable[33+1] = (void *)tallyIntoMapwith'. self cCode: 'opTable[34+1] = (void *)alphaBlendScaledwith'. self cCode: 'opTable[35+1] = (void *)alphaBlendScaledwith'. self cCode: 'opTable[36+1] = (void *)alphaBlendScaledwith'. self cCode: 'opTable[37+1] = (void *)rgbMulwith'. self cCode: 'opTable[38+1] = (void *)pixSwapwith'. self cCode: 'opTable[39+1] = (void *)pixClearwith'. self cCode: 'opTable[40+1] = (void *)fixAlphawith'.! ! !BitBltSimulation methodsFor: 'surface support' stamp: 'ikp 6/9/2004 22:51'! lockSurfaces "Get a pointer to the bits of any OS surfaces." "Notes: * For equal source/dest handles only one locking operation is performed. This is to prevent locking of overlapping areas which does not work with certain APIs (as an example, DirectDraw prevents locking of overlapping areas). A special case for non-overlapping but equal source/dest handle would be possible but we would have to transfer this information over to unlockSurfaces somehow (currently, only one unlock operation is performed for equal source and dest handles). Also, this would require a change in the notion of ioLockSurface() which is right now interpreted as a hint and not as a requirement to lock only the specific portion of the surface. * The arguments in ioLockSurface() provide the implementation with an explicit hint what area is affected. It can be very useful to know the max. affected area beforehand if getting the bits requires expensive copy operations (e.g., like a roundtrip to the X server or a glReadPixel op). However, the returned pointer *MUST* point to the virtual origin of the surface and not to the beginning of the rectangle. The promise made by BitBlt is to never access data outside the given rectangle (aligned to 4byte boundaries!!) so it is okay to return a pointer to the virtual origin that is actually outside the valid memory area. * The area provided in ioLockSurface() is already clipped (e.g., it will always be inside the source and dest boundingBox) but it is not aligned to word boundaries yet. It is up to the support code to compute accurate alignment if necessary. * Warping always requires the entire source surface to be locked because there is no beforehand knowledge about what area will actually be traversed. " | sourceHandle destHandle l r t b fn | self inline: true. "If the CCodeGen learns how to inline #cCode: methods" self var: #fn declareC:'sqInt (*fn)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt)'. hasSurfaceLock _ false. destBits = 0 ifTrue:["Blitting *to* OS surface" lockSurfaceFn = 0 ifTrue:[self loadSurfacePlugin ifFalse:[^nil]]. fn _ self cCoerce: lockSurfaceFn to: 'sqInt (*)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt)'. destHandle _ interpreterProxy fetchInteger: FormBitsIndex ofObject: destForm. (sourceBits = 0 and:[noSource not]) ifTrue:[ sourceHandle _ interpreterProxy fetchInteger: FormBitsIndex ofObject: sourceForm. "Handle the special case of equal source and dest handles" (sourceHandle = destHandle) ifTrue:[ "If we have overlapping source/dest we lock the entire area so that there is only one area transmitted" isWarping ifFalse:[ "When warping we always need the entire surface for the source" sourceBits _ self cCode:'fn(sourceHandle, &sourcePitch, 0,0, sourceWidth, sourceHeight)'. ] ifTrue:[ "Otherwise use overlapping area" l _ sx min: dx. r _ (sx max: dx) + bbW. t _ sy min: dy. b _ (sy max: sy) + bbH. sourceBits _ self cCode:'fn(sourceHandle, &sourcePitch, l, t, r-l, b-t)'. ]. destBits _ sourceBits. destPitch _ sourcePitch. hasSurfaceLock _ true. ^destBits ~~ 0 ]. "Fall through - if not equal it'll be handled below" ]. destBits _ self cCode:'fn(destHandle, &destPitch, dx, dy, bbW, bbH)'. hasSurfaceLock _ true. ]. (sourceBits == 0 and:[noSource not]) ifTrue:["Blitting *from* OS surface" sourceHandle _ interpreterProxy fetchInteger: FormBitsIndex ofObject: sourceForm. lockSurfaceFn = 0 ifTrue:[self loadSurfacePlugin ifFalse:[^nil]]. fn _ self cCoerce: lockSurfaceFn to: 'sqInt (*)(sqInt, sqInt*, sqInt, sqInt, sqInt, sqInt)'. "Warping requiring the entire surface" isWarping ifTrue:[ sourceBits _ self cCode:'fn(sourceHandle, &sourcePitch, 0, 0, sourceWidth, sourceHeight)'. ] ifFalse:[ sourceBits _ self cCode:'fn(sourceHandle, &sourcePitch, sx, sy, bbW, bbH)'. ]. hasSurfaceLock _ true. ]. ^destBits ~~ 0 and:[sourceBits ~~ 0 or:[noSource]].! ! !BitBltSimulation methodsFor: 'surface support' stamp: 'ikp 6/9/2004 22:52'! queryDestSurface: handle "Query the dimension of an OS surface. This method is provided so that in case the inst vars of the source form are broken, *actual* values of the OS surface can be obtained. This might, for instance, happen if the user resizes the main window. Note: Moved to a separate function for better inlining of the caller." querySurfaceFn = 0 ifTrue:[self loadSurfacePlugin ifFalse:[^false]]. ^(self cCode:' ((sqInt (*) (sqInt, sqInt*, sqInt*, sqInt*, sqInt*))querySurfaceFn) (handle, &destWidth, &destHeight, &destDepth, &destMSB)' inSmalltalk:[false])! ! !BitBltSimulation methodsFor: 'surface support' stamp: 'ikp 6/9/2004 22:57'! querySourceSurface: handle "Query the dimension of an OS surface. This method is provided so that in case the inst vars of the source form are broken, *actual* values of the OS surface can be obtained. This might, for instance, happen if the user resizes the main window. Note: Moved to a separate function for better inlining of the caller." querySurfaceFn = 0 ifTrue:[self loadSurfacePlugin ifFalse:[^false]]. ^(self cCode:' ((sqInt (*) (sqInt, sqInt*, sqInt*, sqInt*, sqInt*))querySurfaceFn) (handle, &sourceWidth, &sourceHeight, &sourceDepth, &sourceMSB)' inSmalltalk:[false])! ! !BitBltSimulation methodsFor: 'surface support' stamp: 'ikp 6/11/2004 16:54'! unlockSurfaces "Unlock the bits of any OS surfaces." "See the comment in lockSurfaces. Similar rules apply. That is, the area provided in ioUnlockSurface can be used to determine the dirty region after drawing. If a source is unlocked, then the area will be (0,0,0,0) to indicate that no portion is dirty." | sourceHandle destHandle destLocked fn | self var: #fn declareC:'sqInt (*fn)(sqInt, sqInt, sqInt, sqInt, sqInt)'. hasSurfaceLock ifTrue:[ unlockSurfaceFn = 0 ifTrue:[self loadSurfacePlugin ifFalse:[^nil]]. fn _ self cCoerce: unlockSurfaceFn to: 'sqInt (*)(sqInt, sqInt, sqInt, sqInt, sqInt)'. destLocked _ false. destHandle _ interpreterProxy fetchPointer: FormBitsIndex ofObject: destForm. (interpreterProxy isIntegerObject: destHandle) ifTrue:[ destHandle _ interpreterProxy integerValueOf: destHandle. "The destBits are always assumed to be dirty" self cCode:'fn(destHandle, affectedL, affectedT, affectedR-affectedL, affectedB-affectedT)'. destBits _ destPitch _ 0. destLocked _ true. ]. noSource ifFalse:[ sourceHandle _ interpreterProxy fetchPointer: FormBitsIndex ofObject: sourceForm. (interpreterProxy isIntegerObject: sourceHandle) ifTrue:[ sourceHandle _ interpreterProxy integerValueOf: sourceHandle. "Only unlock sourceHandle if different from destHandle" (destLocked and:[sourceHandle = destHandle]) ifFalse:[self cCode: 'fn(sourceHandle, 0, 0, 0, 0)']. sourceBits _ sourcePitch _ 0. ]. ]. hasSurfaceLock _ false. ].! ! !BitBltSimulation methodsFor: 'primitives' stamp: 'ikp 6/10/2004 12:46'! primitiveDisplayString | kernDelta xTable glyphMap stopIndex startIndex sourceString bbObj maxGlyph ascii glyphIndex sourcePtr left quickBlt | self export: true. self var: #sourcePtr type: 'unsigned char *'. interpreterProxy methodArgumentCount = 6 ifFalse:[^interpreterProxy primitiveFail]. kernDelta _ interpreterProxy stackIntegerValue: 0. xTable _ interpreterProxy stackObjectValue: 1. glyphMap _ interpreterProxy stackObjectValue: 2. ((interpreterProxy fetchClassOf: xTable) = interpreterProxy classArray and:[ (interpreterProxy fetchClassOf: glyphMap) = interpreterProxy classArray]) ifFalse:[^interpreterProxy primitiveFail]. (interpreterProxy slotSizeOf: glyphMap) = 256 ifFalse:[^interpreterProxy primitiveFail]. interpreterProxy failed ifTrue:[^nil]. maxGlyph _ (interpreterProxy slotSizeOf: xTable) - 2. stopIndex _ interpreterProxy stackIntegerValue: 3. startIndex _ interpreterProxy stackIntegerValue: 4. sourceString _ interpreterProxy stackObjectValue: 5. (interpreterProxy isBytes: sourceString) ifFalse:[^interpreterProxy primitiveFail]. (startIndex > 0 and:[stopIndex > 0 and:[ stopIndex <= (interpreterProxy byteSizeOf: sourceString)]]) ifFalse:[^interpreterProxy primitiveFail]. bbObj _ interpreterProxy stackObjectValue: 6. (self loadBitBltFrom: bbObj) ifFalse:[^interpreterProxy primitiveFail]. (combinationRule = 30 or:[combinationRule = 31]) "needs extra source alpha" ifTrue:[^interpreterProxy primitiveFail]. "See if we can go directly into copyLoopPixMap (usually we can)" quickBlt _ destBits ~= 0 "no OS surfaces please" and:[sourceBits ~= 0 "and again" and:[noSource = false "needs a source" and:[sourceForm ~= destForm "no blits onto self" and:[(cmFlags ~= 0 or:[sourceMSB ~= destMSB or:[sourceDepth ~= destDepth]]) "no point using slower version" ]]]]. left _ destX. sourcePtr _ interpreterProxy firstIndexableField: sourceString. startIndex to: stopIndex do:[:charIndex| ascii _ interpreterProxy byteAtPointer: sourcePtr + charIndex - 1. glyphIndex _ interpreterProxy fetchInteger: ascii ofObject: glyphMap. (glyphIndex < 0 or:[glyphIndex > maxGlyph]) ifTrue:[^interpreterProxy primitiveFail]. sourceX _ interpreterProxy fetchInteger: glyphIndex ofObject: xTable. width _ (interpreterProxy fetchInteger: glyphIndex+1 ofObject: xTable) - sourceX. interpreterProxy failed ifTrue:[^nil]. self clipRange. "Must clip here" (bbW > 0 and:[bbH > 0]) ifTrue: [ quickBlt ifTrue:[ self destMaskAndPointerInit. self copyLoopPixMap. "both, hDir and vDir are known to be > 0" affectedL _ dx. affectedR _ dx + bbW. affectedT _ dy. affectedB _ dy + bbH. ] ifFalse:[self copyBits]]. interpreterProxy failed ifTrue:[^nil]. destX _ destX + width + kernDelta. ]. affectedL _ left. self showDisplayBits. interpreterProxy pop: 6. "pop args, return rcvr"! ! !BitBltSimulator methodsFor: 'debug support' stamp: 'ikp 8/2/2004 20:25'! dstLongAt: dstIndex interpreterProxy isInterpreterProxy ifTrue:[^dstIndex long32At: 0]. ((dstIndex anyMask: 3) or:[dstIndex + 4 < destBits or:[ dstIndex > (destBits + (destPitch * destHeight))]]) ifTrue:[self error:'Out of bounds']. ^self long32At: dstIndex! ! !BitBltSimulator methodsFor: 'debug support' stamp: 'ikp 8/2/2004 20:29'! dstLongAt: dstIndex put: value interpreterProxy isInterpreterProxy ifTrue:[^dstIndex long32At: 0 put: value]. ((dstIndex anyMask: 3) or:[dstIndex < destBits or:[ dstIndex >= (destBits + (destPitch * destHeight))]]) ifTrue:[self error:'Out of bounds']. ^self long32At: dstIndex put: value! ! !BitBltSimulator methodsFor: 'debug support' stamp: 'ikp 8/2/2004 20:25'! srcLongAt: srcIndex interpreterProxy isInterpreterProxy ifTrue:[^srcIndex long32At: 0]. ((srcIndex anyMask: 3) or:[srcIndex + 4 < sourceBits or:[ srcIndex > (sourceBits + (sourcePitch * sourceHeight))]]) ifTrue:[self error:'Out of bounds']. ^self long32At: srcIndex! ! !BitBltSimulator methodsFor: 'simulation' stamp: 'ikp 8/2/2004 20:25'! tableLookup: table at: index ^ self long32At: (table + (index * 4))! ! !FFIPlugin methodsFor: 'primitive support' stamp: 'di 7/4/2004 08:38'! addressOf: rcvr startingAt: byteOffset size: byteSize | rcvrClass rcvrSize addr | (interpreterProxy isBytes: rcvr) ifFalse:[^interpreterProxy primitiveFail]. (byteOffset > 0) ifFalse:[^interpreterProxy primitiveFail]. rcvrClass _ interpreterProxy fetchClassOf: rcvr. rcvrSize _ interpreterProxy byteSizeOf: rcvr. rcvrClass == interpreterProxy classExternalAddress ifTrue:[ (rcvrSize = 4) ifFalse:[^interpreterProxy primitiveFail]. addr _ interpreterProxy fetchPointer: 0 ofObject: rcvr. "don't you dare to read from object memory!!" (addr == 0 or:[interpreterProxy isInMemory: addr]) ifTrue:[^interpreterProxy primitiveFail]. ] ifFalse:[ (byteOffset+byteSize-1 <= rcvrSize) ifFalse:[^interpreterProxy primitiveFail]. addr _ self cCoerce: (interpreterProxy firstIndexableField: rcvr) to: 'int'. ]. addr _ addr + byteOffset - 1. ^addr! ! !FFIPlugin methodsFor: 'callout support' stamp: 'di 7/4/2004 08:39'! ffiContentsOfHandle: oop errCode: errCode "Make sure that the given oop is a valid external handle" self inline: true. (interpreterProxy isIntegerObject: oop) ifTrue:[^self ffiFail: errCode]. (interpreterProxy isBytes: oop) ifFalse:[^self ffiFail: errCode]. ((interpreterProxy byteSizeOf: oop) == 4) ifFalse:[^self ffiFail: errCode]. ^interpreterProxy fetchPointer: 0 ofObject: oop! ! !FFIPlugin methodsFor: 'callout support' stamp: 'di 7/4/2004 08:40'! ffiPushPointerContentsOf: oop "Push the contents of the given external structure" | ptrValue ptrClass ptrAddress | self inline: false. ptrValue _ oop. ptrClass _ interpreterProxy fetchClassOf: ptrValue. ptrClass == interpreterProxy classExternalAddress ifTrue:[ ptrAddress _ interpreterProxy fetchPointer: 0 ofObject: ptrValue. "Don't you dare to pass pointers into object memory" (interpreterProxy isInMemory: ptrAddress) ifTrue:[^self ffiFail: FFIErrorInvalidPointer]. ^self ffiPushPointer: ptrAddress]. ptrClass == interpreterProxy classByteArray ifTrue:[ ptrAddress _ self cCoerce: (interpreterProxy firstIndexableField: ptrValue) to: 'int'. ^self ffiPushPointer: ptrAddress]. ^self ffiFail: FFIErrorBadArg! ! !FFIPlugin methodsFor: 'callout support' stamp: 'di 7/4/2004 08:43'! ffiPushStructureContentsOf: oop "Push the contents of the given external structure" | ptrValue ptrClass ptrAddress | self inline: true. ptrValue _ oop. ptrClass _ interpreterProxy fetchClassOf: ptrValue. ptrClass == interpreterProxy classExternalAddress ifTrue:[ ptrAddress _ interpreterProxy fetchPointer: 0 ofObject: ptrValue. "There is no way we can make sure the structure is valid. But we can at least check for attempts to pass pointers to ST memory." (interpreterProxy isInMemory: ptrAddress) ifTrue:[^self ffiFail: FFIErrorInvalidPointer]. ^self ffiPush: ptrAddress Structure: (self cCoerce: ffiArgSpec to:'int*') OfLength: ffiArgSpecSize]. ptrClass == interpreterProxy classByteArray ifTrue:[ "The following is a somewhat pessimistic test but I like being sure..." (interpreterProxy byteSizeOf: ptrValue) = (ffiArgHeader bitAnd: FFIStructSizeMask) ifFalse:[^self ffiFail: FFIErrorStructSize]. ptrAddress _ self cCoerce: (interpreterProxy firstIndexableField: ptrValue) to: 'int'. (ffiArgHeader anyMask: FFIFlagPointer) ifFalse:[ ^self ffiPush: ptrAddress Structure: (self cCoerce: ffiArgSpec to: 'int*') OfLength: ffiArgSpecSize]. "If FFIFlagPointer + FFIFlagStructure is set use ffiPushPointer on the contents" (ffiArgHeader bitAnd: FFIStructSizeMask) = 4 ifFalse:[^self ffiFail: FFIErrorStructSize]. ptrAddress _ interpreterProxy fetchPointer: 0 ofObject: ptrValue. (interpreterProxy isInMemory: ptrAddress) ifTrue:[^self ffiFail: FFIErrorInvalidPointer]. ^self ffiPushPointer: ptrAddress]. ^self ffiFail: FFIErrorBadArg! ! !FFIPlugin methodsFor: 'callout support' stamp: 'di 7/4/2004 08:40'! ffiValidateExternalData: oop AtomicType: atomicType "Validate if the given oop (an instance of ExternalData) can be passed as a pointer to the given atomic type." | ptrType specOop spec specType | self inline: true. ptrType _ interpreterProxy fetchPointer: 1 ofObject: oop. (interpreterProxy isIntegerObject: ptrType) ifTrue:[^self ffiFail: FFIErrorWrongType]. (interpreterProxy isPointers: ptrType) ifFalse:[^self ffiFail: FFIErrorWrongType]. (interpreterProxy slotSizeOf: ptrType) < 2 ifTrue:[^self ffiFail: FFIErrorWrongType]. specOop _ interpreterProxy fetchPointer: 0 ofObject: ptrType. (interpreterProxy isIntegerObject: specOop) ifTrue:[^self ffiFail: FFIErrorWrongType]. (interpreterProxy isWords: specOop) ifFalse:[^self ffiFail: FFIErrorWrongType]. (interpreterProxy slotSizeOf: specOop) = 0 ifTrue:[^self ffiFail: FFIErrorWrongType]. spec _ interpreterProxy fetchPointer: 0 ofObject: specOop. (self isAtomicType: spec) ifFalse:[^self ffiFail: FFIErrorWrongType]. specType _ self atomicTypeOf: spec. specType ~= atomicType ifTrue:[ "allow for signed/unsigned conversion but nothing else" (atomicType > FFITypeBool and:[atomicType < FFITypeSingleFloat]) ifFalse:[^self ffiFail: FFIErrorCoercionFailed]. ((atomicType >> 1) = (specType >> 1)) ifFalse:[^self ffiFail: FFIErrorCoercionFailed]]. ^0! ! !FFIPlugin methodsFor: 'primitives' stamp: 'di 6/23/2004 14:28'! primitiveFFIIntegerAt "Return a (signed or unsigned) n byte integer from the given byte offset." | isSigned byteSize byteOffset rcvr addr value mask | self export: true. self inline: false. isSigned _ interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize _ interpreterProxy stackIntegerValue: 1. byteOffset _ interpreterProxy stackIntegerValue: 2. rcvr _ interpreterProxy stackObjectValue: 3. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and:[byteSize = 1 or:[byteSize = 2 or:[byteSize = 4]]]) ifFalse:[^interpreterProxy primitiveFail]. addr _ self addressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. byteSize < 4 ifTrue:[ "short/byte" byteSize = 1 ifTrue:[value _ interpreterProxy byteAt: addr] ifFalse:[ value _ self cCode: '*((short int *) addr)' inSmalltalk: [interpreterProxy shortAt: addr]]. isSigned ifTrue:["sign extend value" mask _ 1 << (byteSize * 8 - 1). value _ (value bitAnd: mask-1) - (value bitAnd: mask)]. "note: byte/short never exceed SmallInteger range" value _ interpreterProxy integerObjectOf: value. ] ifFalse:[ "general 32 bit integer" value _ interpreterProxy longAt: addr. isSigned ifTrue:[value _ interpreterProxy signed32BitIntegerFor: value] ifFalse:[value _ interpreterProxy positive32BitIntegerFor: value]. ]. interpreterProxy pop: 4. ^interpreterProxy push: value ! ! !FFIPlugin methodsFor: 'primitives' stamp: 'di 6/23/2004 14:33'! primitiveFFIIntegerAtPut "Store a (signed or unsigned) n byte integer at the given byte offset." | isSigned byteSize byteOffset rcvr addr value max valueOop | self export: true. self inline: false. isSigned _ interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize _ interpreterProxy stackIntegerValue: 1. valueOop _ interpreterProxy stackValue: 2. byteOffset _ interpreterProxy stackIntegerValue: 3. rcvr _ interpreterProxy stackObjectValue: 4. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and:[byteSize = 1 or:[byteSize = 2 or:[byteSize = 4]]]) ifFalse:[^interpreterProxy primitiveFail]. addr _ self addressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. isSigned ifTrue:[value _ interpreterProxy signed32BitValueOf: valueOop] ifFalse:[value _ interpreterProxy positive32BitValueOf: valueOop]. interpreterProxy failed ifTrue:[^0]. byteSize < 4 ifTrue:[ isSigned ifTrue:[ max _ 1 << (8 * byteSize - 1). value >= max ifTrue:[^interpreterProxy primitiveFail]. value < (0 - max) ifTrue:[^interpreterProxy primitiveFail]. ] ifFalse:[ value >= (1 << (8*byteSize)) ifTrue:[^interpreterProxy primitiveFail]. ]. "short/byte" byteSize = 1 ifTrue:[interpreterProxy byteAt: addr put: value] ifFalse:[ self cCode: '*((short int *) addr) = value' inSmalltalk: [interpreterProxy shortAt: addr put: value]]. ] ifFalse:[interpreterProxy longAt: addr put: value]. interpreterProxy pop: 5. ^interpreterProxy push: valueOop.! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ikp 6/14/2004 14:53'! primitiveDirectoryCreate | dirName dirNameIndex dirNameSize okToCreate | self var: #dirNameIndex type: 'char *'. self export: true. dirName _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: dirName) ifFalse: [^interpreterProxy primitiveFail]. dirNameIndex _ interpreterProxy firstIndexableField: dirName. dirNameSize _ interpreterProxy byteSizeOf: dirName. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCCPfn ~= 0 ifTrue: [okToCreate _ self cCode: ' ((sqInt (*)(char *, sqInt))sCCPfn)(dirNameIndex, dirNameSize)'. okToCreate ifFalse: [^interpreterProxy primitiveFail]]. (self cCode: 'dir_Create(dirNameIndex, dirNameSize)' inSmalltalk: [false]) ifFalse: [^interpreterProxy primitiveFail]. interpreterProxy pop: 1! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ikp 6/14/2004 14:54'! primitiveDirectoryDelete | dirName dirNameIndex dirNameSize okToDelete | self var: #dirNameIndex type: 'char *'. self export: true. dirName _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: dirName) ifFalse: [^interpreterProxy primitiveFail]. dirNameIndex _ interpreterProxy firstIndexableField: dirName. dirNameSize _ interpreterProxy byteSizeOf: dirName. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCDPfn ~= 0 ifTrue: [okToDelete _ self cCode: ' ((sqInt (*)(char *, sqInt))sCDPfn)(dirNameIndex, dirNameSize)'. okToDelete ifFalse: [^interpreterProxy primitiveFail]]. (self cCode: 'dir_Delete(dirNameIndex, dirNameSize)' inSmalltalk: [false]) ifFalse: [^interpreterProxy primitiveFail]. interpreterProxy pop: 1! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ikp 6/14/2004 14:56'! primitiveDirectoryGetMacTypeAndCreator | creatorString typeString fileName creatorStringIndex typeStringIndex fileNameIndex fileNameSize okToGet | self var: 'creatorStringIndex' type: 'char *'. self var: 'typeStringIndex' type: 'char *'. self var: 'fileNameIndex' type: 'char *'. self export: true. creatorString _ interpreterProxy stackValue: 0. typeString _ interpreterProxy stackValue: 1. fileName _ interpreterProxy stackValue: 2. ((interpreterProxy isBytes: creatorString) and: [(interpreterProxy byteSizeOf: creatorString) = 4]) ifFalse: [^interpreterProxy primitiveFail]. ((interpreterProxy isBytes: typeString) and: [(interpreterProxy byteSizeOf: typeString) = 4]) ifFalse: [^interpreterProxy primitiveFail]. (interpreterProxy isBytes: fileName) ifFalse: [^interpreterProxy primitiveFail]. creatorStringIndex _ interpreterProxy firstIndexableField: creatorString. typeStringIndex _ interpreterProxy firstIndexableField: typeString. fileNameIndex _ interpreterProxy firstIndexableField: fileName. fileNameSize _ interpreterProxy byteSizeOf: fileName. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCGFTfn ~= 0 ifTrue: [okToGet _ self cCode: ' ((sqInt (*)(char *, sqInt))sCGFTfn)(fileNameIndex, fileNameSize)'. okToGet ifFalse: [^interpreterProxy primitiveFail]]. (self cCode: 'dir_GetMacFileTypeAndCreator(fileNameIndex, fileNameSize, typeStringIndex, creatorStringIndex)' inSmalltalk: [true]) ifFalse: [^interpreterProxy primitiveFail]. interpreterProxy pop: 3! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ikp 6/14/2004 14:57'! primitiveDirectoryLookup | index pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag fileSize okToList | self var: 'entryName' declareC: 'char entryName[256]'. self var: 'pathNameIndex' type: 'char *'. self var: 'fileSize' type: 'squeakFileOffsetType'. self export: true. index _ interpreterProxy stackIntegerValue: 0. pathName _ interpreterProxy stackValue: 1. (interpreterProxy isBytes: pathName) ifFalse: [^interpreterProxy primitiveFail]. pathNameIndex _ interpreterProxy firstIndexableField: pathName. pathNameSize _ interpreterProxy byteSizeOf: pathName. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCLPfn ~= 0 ifTrue: [okToList _ self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)'] ifFalse: [okToList _ true]. okToList ifTrue: [status _ self cCode: 'dir_Lookup(pathNameIndex, pathNameSize, index, entryName, &entryNameSize, &createDate, &modifiedDate, &dirFlag, &fileSize)'] ifFalse: [status _ DirNoMoreEntries]. interpreterProxy failed ifTrue: [^nil]. status = DirNoMoreEntries ifTrue: ["no more entries; return nil" interpreterProxy pop: 3. "pop pathName, index, rcvr" interpreterProxy push: interpreterProxy nilObject. ^nil]. status = DirBadPath ifTrue: [^interpreterProxy primitiveFail]. "bad path" interpreterProxy pop: 3. "pop pathName, index, rcvr" interpreterProxy push: (self makeDirEntryName: entryName size: entryNameSize createDate: createDate modDate: modifiedDate isDir: dirFlag fileSize: fileSize)! ! !FilePlugin methodsFor: 'directory primitives' stamp: 'ikp 6/14/2004 14:58'! primitiveDirectorySetMacTypeAndCreator | creatorString typeString fileName creatorStringIndex typeStringIndex fileNameIndex fileNameSize okToSet | self var: 'creatorStringIndex' type: 'char *'. self var: 'typeStringIndex' type: 'char *'. self var: 'fileNameIndex' type: 'char *'. self export: true. creatorString _ interpreterProxy stackValue: 0. typeString _ interpreterProxy stackValue: 1. fileName _ interpreterProxy stackValue: 2. ((interpreterProxy isBytes: creatorString) and: [(interpreterProxy byteSizeOf: creatorString) = 4]) ifFalse: [^interpreterProxy primitiveFail]. ((interpreterProxy isBytes: typeString) and: [(interpreterProxy byteSizeOf: typeString) = 4]) ifFalse: [^interpreterProxy primitiveFail]. (interpreterProxy isBytes: fileName) ifFalse: [^interpreterProxy primitiveFail]. creatorStringIndex _ interpreterProxy firstIndexableField: creatorString. typeStringIndex _ interpreterProxy firstIndexableField: typeString. fileNameIndex _ interpreterProxy firstIndexableField: fileName. fileNameSize _ interpreterProxy byteSizeOf: fileName. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCSFTfn ~= 0 ifTrue: [okToSet _ self cCode: ' ((sqInt (*)(char *, sqInt))sCSFTfn)(fileNameIndex, fileNameSize)'. okToSet ifFalse: [^interpreterProxy primitiveFail]]. (self cCode: 'dir_SetMacFileTypeAndCreator(fileNameIndex, fileNameSize,typeStringIndex, creatorStringIndex)' inSmalltalk: [true]) ifFalse: [^interpreterProxy primitiveFail]. interpreterProxy pop: 3! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ikp 6/14/2004 14:01'! fileOpenName: nameIndex size: nameSize write: writeFlag secure: secureFlag "Open the named file, possibly checking security. Answer the file oop." | file fileOop okToOpen | self var: #file type: 'SQFile *'. self var: 'nameIndex' type: 'char *'. self export: true. fileOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: self fileRecordSize. file _ self fileValueOf: fileOop. interpreterProxy failed ifFalse: [ secureFlag ifTrue: [ "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCOFfn ~= 0 ifTrue: [okToOpen _ self cCode: '((sqInt (*) (char *, sqInt, sqInt)) sCOFfn)(nameIndex, nameSize, writeFlag)' inSmalltalk:[true]. okToOpen ifFalse: [interpreterProxy primitiveFail]]]]. interpreterProxy failed ifFalse: [self cCode: 'sqFileOpen(file, oopForPointer(nameIndex), nameSize, writeFlag)' inSmalltalk: [file]]. ^ fileOop! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ikp 8/2/2004 19:49'! primitiveFileDelete | namePointer nameIndex nameSize okToDelete | self var: 'nameIndex' type: 'char *'. self export: true. namePointer _ interpreterProxy stackValue: 0. (interpreterProxy isBytes: namePointer) ifFalse: [^ interpreterProxy primitiveFail]. nameIndex _ interpreterProxy firstIndexableField: namePointer. nameSize _ interpreterProxy byteSizeOf: namePointer. "If the security plugin can be loaded, use it to check for permission. If not, assume it's ok" sCDFfn ~= 0 ifTrue: [okToDelete _ self cCode: ' ((sqInt (*)(char *, sqInt))sCDFfn)(nameIndex, nameSize)'. okToDelete ifFalse: [^ interpreterProxy primitiveFail]]. self sqFileDeleteName: (self oopForPointer: nameIndex) Size: nameSize. interpreterProxy failed ifFalse: [interpreterProxy pop: 1]! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ikp 8/2/2004 19:49'! primitiveFileRead | count startIndex array file byteSize arrayIndex bytesRead | self var: 'file' declareC: 'SQFile *file'. self var: 'arrayIndex' type: 'char *'. self var: 'count' type: 'size_t'. self var: 'startIndex' type: 'size_t'. self var: 'byteSize' type: 'size_t'. self export: true. count _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0). startIndex _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 1). array _ interpreterProxy stackValue: 2. file _ self fileValueOf: (interpreterProxy stackValue: 3). "buffer can be any indexable words or bytes object except CompiledMethod" (interpreterProxy isWordsOrBytes: array) ifFalse: [^interpreterProxy primitiveFail]. (interpreterProxy isWords: array) ifTrue: [byteSize _ 4] ifFalse: [byteSize _ 1]. ((startIndex >= 1) and: [(startIndex + count - 1) <= (interpreterProxy slotSizeOf: array)]) ifFalse: [^interpreterProxy primitiveFail]. arrayIndex _ interpreterProxy firstIndexableField: array. "Note: adjust startIndex for zero-origin indexing" bytesRead _ self sqFile: file Read: (count * byteSize) Into: (self oopForPointer: arrayIndex) At: ((startIndex - 1) * byteSize). interpreterProxy failed ifFalse: [ interpreterProxy pop: 5. "pop rcvr, file, array, startIndex, count" interpreterProxy pushInteger: bytesRead // byteSize. "push # of elements read" ].! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ikp 8/2/2004 19:50'! primitiveFileRename | oldNamePointer newNamePointer oldNameIndex oldNameSize newNameIndex newNameSize okToRename | self var: 'oldNameIndex' type: 'char *'. self var: 'newNameIndex' type: 'char *'. self export: true. newNamePointer _ interpreterProxy stackValue: 0. oldNamePointer _ interpreterProxy stackValue: 1. ((interpreterProxy isBytes: newNamePointer) and: [interpreterProxy isBytes: oldNamePointer]) ifFalse: [^interpreterProxy primitiveFail]. newNameIndex _ interpreterProxy firstIndexableField: newNamePointer. newNameSize _ interpreterProxy byteSizeOf: newNamePointer. oldNameIndex _ interpreterProxy firstIndexableField: oldNamePointer. oldNameSize _ interpreterProxy byteSizeOf: oldNamePointer. "If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok" sCRFfn ~= 0 ifTrue: [okToRename _ self cCode: ' ((sqInt (*)(char *, sqInt))sCRFfn)(oldNameIndex, oldNameSize)'. okToRename ifFalse: [^interpreterProxy primitiveFail]]. self sqFileRenameOld: (self oopForPointer: oldNameIndex) Size: oldNameSize New: (self oopForPointer: newNameIndex) Size: newNameSize. interpreterProxy failed ifFalse: [interpreterProxy pop: 2]! ! !FilePlugin methodsFor: 'file primitives' stamp: 'ikp 8/2/2004 19:50'! primitiveFileWrite | count startIndex array file byteSize arrayIndex bytesWritten | self var: 'file' declareC: 'SQFile *file'. self var: 'arrayIndex' type: 'char *'. self var: 'count' type: 'size_t'. self var: 'startIndex' type: 'size_t'. self var: 'byteSize' type: 'size_t'. self export: true. count _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0). startIndex _ interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 1). array _ interpreterProxy stackValue: 2. file _ self fileValueOf: (interpreterProxy stackValue: 3). "buffer can be any indexable words or bytes object except CompiledMethod" (interpreterProxy isWordsOrBytes: array) ifFalse: [^interpreterProxy primitiveFail]. (interpreterProxy isWords: array) ifTrue: [ byteSize _ 4 ] ifFalse: [ byteSize _ 1 ]. ((startIndex >= 1) and: [(startIndex + count - 1) <= (interpreterProxy slotSizeOf: array)]) ifFalse: [^interpreterProxy primitiveFail]. interpreterProxy failed ifFalse: [ arrayIndex _ interpreterProxy firstIndexableField: array. "Note: adjust startIndex for zero-origin indexing" bytesWritten _ self sqFile: file Write: (count * byteSize) From: (self oopForPointer: arrayIndex) At: ((startIndex - 1) * byteSize). ]. interpreterProxy failed ifFalse: [ interpreterProxy pop: 5. "pop rcvr, file, array, startIndex, count" interpreterProxy pushInteger: bytesWritten // byteSize. "push # of elements written" ].! ! !FilePlugin methodsFor: 'security primitives' stamp: 'ikp 8/4/2004 11:31'! primitiveDisableFileAccess self export: true. "If the security plugin can be loaded, use it to turn off file access If not, assume it's ok" sDFAfn ~= 0 ifTrue: [self cCode: ' ((sqInt (*)(void))sDFAfn)()']. interpreterProxy failed ifFalse: [interpreterProxy pop: 1]! ! !FilePlugin methodsFor: 'security primitives' stamp: 'ikp 8/4/2004 11:31'! primitiveHasFileAccess | hasAccess | self export: true. "If the security plugin can be loaded, use it to check . If not, assume it's ok" sHFAfn ~= 0 ifTrue: [hasAccess _ self cCode: ' ((sqInt (*)(void))sHFAfn)()' inSmalltalk: [true]] ifFalse: [hasAccess _ true]. interpreterProxy pop: 1. interpreterProxy pushBool: hasAccess! ! !FilePluginSimulator methodsFor: 'simulation' stamp: 'di 6/23/2004 14:18'! oopForPointer: pointer "This gets implemented by Macros in C, where its types will also be checked. oop is the width of a machine word, and pointer is a raw address." ^ pointer! ! !FloatArrayPlugin methodsFor: 'access primitives' stamp: 'di 6/29/2004 14:05'! primitiveAtPut | value floatValue index rcvr floatPtr | self export: true. self var: #floatValue declareC: 'double floatValue'. self var: #floatPtr declareC:'float *floatPtr'. value _ interpreterProxy stackValue: 0. (interpreterProxy isIntegerObject: value) ifTrue:[floatValue _ (interpreterProxy integerValueOf: value) asFloat] ifFalse:[floatValue _ interpreterProxy floatValueOf: value]. index _ interpreterProxy stackIntegerValue: 1. rcvr _ interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^nil]. interpreterProxy success: (interpreterProxy isWords: rcvr). interpreterProxy success: (index > 0 and:[index <= (interpreterProxy slotSizeOf: rcvr)]). interpreterProxy failed ifTrue:[^nil]. floatPtr _ interpreterProxy firstIndexableField: rcvr. floatPtr at: index-1 put: (self cCoerce: floatValue to:'float'). interpreterProxy failed ifFalse: [interpreterProxy pop: 3 thenPush: value].! ! !InterpreterPlugin class methodsFor: 'translation' stamp: 'ikp 8/3/2004 18:55'! buildCodeGeneratorUpTo: aPluginClass "Build a CCodeGenerator for the plugin" | cg theClass | cg _ self codeGeneratorClass new initialize. cg pluginName: self moduleName. "Add an extra declaration for module name" cg declareModuleName: self moduleNameAndVersion. theClass _ aPluginClass. [theClass == Object | (theClass == InterpreterSimulationObject)] whileFalse:[ cg addClass: theClass. theClass _ theClass superclass]. ^cg! ! !BalloonEngineBase class methodsFor: 'translation' stamp: 'ikp 6/14/2004 15:19'! declareCVarsIn: cg "Buffers" cg var: #workBuffer type: #'int*'. cg var: #objBuffer type: #'int*'. cg var: #getBuffer type: #'int*'. cg var: #aetBuffer type: #'int*'. cg var: #spanBuffer type: #'unsigned int*'. cg var: #edgeTransform declareC: 'float edgeTransform[6]'. cg var: #doProfileStats declareC: 'int doProfileStats = 0'. cg var: 'bbPluginName' declareC:'char bbPluginName[256] = "BitBltPlugin"'. "Functions" cg var: 'copyBitsFn' type: 'void *'. cg var: 'loadBBFn' type: 'void *'.! ! !BitBltSimulation class methodsFor: 'translation' stamp: 'ikp 8/4/2004 18:08'! declareCVarsIn: aCCodeGenerator aCCodeGenerator var: 'opTable' declareC: 'void *opTable[' , OpTableSize printString , ']'. aCCodeGenerator var: 'maskTable' declareC:'int maskTable[33] = { 0, 1, 3, 0, 15, 31, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 }'. aCCodeGenerator var: 'ditherMatrix4x4' declareC:'const int ditherMatrix4x4[16] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 }'. aCCodeGenerator var: 'ditherThresholds16' declareC:'const int ditherThresholds16[8] = { 0, 2, 4, 6, 8, 12, 14, 16 }'. aCCodeGenerator var: 'ditherValues16' declareC:'const int ditherValues16[32] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }'. aCCodeGenerator var: 'warpBitShiftTable' declareC:'int warpBitShiftTable[32]'. aCCodeGenerator var:'cmShiftTable' declareC:'int *cmShiftTable'. aCCodeGenerator var:'cmMaskTable' declareC:'unsigned int *cmMaskTable'. aCCodeGenerator var:'cmLookupTable' declareC:'unsigned int *cmLookupTable'. aCCodeGenerator var: 'dither8Lookup' declareC:' unsigned char dither8Lookup[4096]'. aCCodeGenerator var: 'querySurfaceFn' declareC: 'void *querySurfaceFn'. aCCodeGenerator var: 'lockSurfaceFn' declareC: 'void *lockSurfaceFn'. aCCodeGenerator var: 'unlockSurfaceFn' declareC: 'void *unlockSurfaceFn'! ! !FilePlugin class methodsFor: 'translation' stamp: 'ikp 6/14/2004 13:52'! declareCVarsIn: aCCodeGenerator aCCodeGenerator var: 'sCCPfn' type: 'void *'. aCCodeGenerator var: 'sCDPfn' type: 'void *'. aCCodeGenerator var: 'sCGFTfn' type: 'void *'. aCCodeGenerator var: 'sCLPfn' type: 'void *'. aCCodeGenerator var: 'sCSFTfn' type: 'void *'. aCCodeGenerator var: 'sDFAfn' type: 'void *'. aCCodeGenerator var: 'sCDFfn' type: 'void *'. aCCodeGenerator var: 'sCOFfn' type: 'void *'. aCCodeGenerator var: 'sCRFfn' type: 'void *'. aCCodeGenerator var: 'sHFAfn' type: 'void *'. aCCodeGenerator addHeaderFile: '"FilePlugin.h"'! ! !InterpreterSimulationObject methodsFor: 'memory access' stamp: 'di 8/5/2004 20:56'! long32At: byteAddress "Simulation support. Answer the 32-bit word at byteAddress which must be 0 mod 4." ^self getInterpreter long32At: byteAddress! ! !InterpreterSimulationObject methodsFor: 'memory access' stamp: 'di 8/5/2004 20:56'! long32At: byteAddress put: a32BitValue "Simulation support. Store the 32-bit value at byteAddress which must be 0 mod 4." ^self getInterpreter long32At: byteAddress put: a32BitValue! ! !InterpreterSimulationObject methodsFor: 'memory access' stamp: 'ikp 8/3/2004 15:56'! oopForPointer: aPointer "Simulation support. Pointers and oops are the same when simulating; answer aPointer." ^aPointer! ! !InterpreterSimulationObject methodsFor: 'memory access' stamp: 'ikp 8/3/2004 15:56'! pointerForOop: anOop "Simulation support. Pointers and oops are the same when simulating; answer anOop." ^anOop! ! !InterpreterSimulationObject methodsFor: 'simulation' stamp: 'di 8/5/2004 18:55'! cCoerce: value to: cTypeString "Here the Simulator has a chance to create properly typed flavors of CArray access." value isCObjectAccessor ifTrue: [^ self getInterpreter cCoerce: value to: cTypeString]. (value isMemberOf: CArray) ifTrue: [^ self getInterpreter cCoerce: value to: cTypeString]. ^ value! ! !Matrix2x3Plugin methodsFor: 'primitives' stamp: 'di 6/29/2004 13:42'! primitiveComposeMatrix | m1 m2 m3 result | self cCode: '' "Make this fail in simulation" inSmalltalk: [interpreterProxy success: false. ^ nil]. self export: true. self inline: false. self var: #m1 declareC:'float *m1'. self var: #m2 declareC:'float *m2'. self var: #m3 declareC:'float *m3'. m3 _ self loadArgumentMatrix: (result _ interpreterProxy stackObjectValue: 0). m2 _ self loadArgumentMatrix: (interpreterProxy stackObjectValue: 1). m1 _ self loadArgumentMatrix: (interpreterProxy stackObjectValue: 2). interpreterProxy failed ifTrue:[^nil]. self matrix2x3ComposeMatrix: m1 with: m2 into: m3. interpreterProxy pop: 3. interpreterProxy push: result.! ! !ObjectMemory methodsFor: 'gc -- mark and sweep' stamp: 'di 7/1/2004 15:47'! startField "Examine and possibly trace the next field of the object being traced. See comment in markAndTrace for explanation of tracer state variables." | typeBits childType | self inline: true. child _ self longAt: field. typeBits _ child bitAnd: TypeMask. (typeBits bitAnd: 1) = 1 ifTrue: ["field contains a SmallInteger; skip it" field _ field - BytesPerWord. ^ StartField]. typeBits = 0 ifTrue: ["normal oop, go down" self longAt: field put: parentField. parentField _ field. ^ StartObj]. typeBits = 2 ifTrue: ["reached the header; do we need to process the class word? " (child bitAnd: CompactClassMask) ~= 0 ifTrue: ["object's class is compact; we're done" "restore the header type bits" child _ child bitAnd: AllButTypeMask. childType _ self rightType: child. self longAt: field put: (child bitOr: childType). ^ Upward] ifFalse: ["object has a full class word; process that class" child _ self longAt: field - BytesPerWord. "class word" child _ child bitAnd: AllButTypeMask. "clear type bits" self longAt: field - BytesPerWord put: parentField. parentField _ field - BytesPerWord bitOr: 1. "point at class word; mark as working on the class. " ^ StartObj]]! ! !ObjectMemory methodsFor: 'gc -- mark and sweep' stamp: 'di 7/1/2004 15:48'! startObj "Start tracing the object 'child' and answer the next action. The object may be anywhere in the middle of being swept itself. See comment in markAndTrace for explanation of tracer state variables." | oop header lastFieldOffset | self inline: true. oop _ child. oop < youngStartLocal ifTrue: ["old object; skip it" field _ oop. ^ Upward]. header _ self longAt: oop. (header bitAnd: MarkBit) = 0 ifTrue: ["unmarked; mark and trace" "Do not trace the object's indexed fields if it's a weak class " (self isWeakNonInt: oop) ifTrue: ["Set lastFieldOffset before the weak fields in the receiver " lastFieldOffset _ (self nonWeakFieldsOf: oop) << ShiftForWord] ifFalse: ["Do it the usual way" lastFieldOffset _ self lastPointerOf: oop]. header _ header bitAnd: AllButTypeMask. header _ (header bitOr: MarkBit) bitOr: HeaderTypeGC. self longAt: oop put: header. field _ oop + lastFieldOffset. ^ StartField "trace its fields and class"] ifFalse: ["already marked; skip it" field _ oop. ^ Upward]! ! !ObjectMemory methodsFor: 'gc -- mark and sweep' stamp: 'di 7/1/2004 15:57'! sweepPhase "Sweep memory from youngStart through the end of memory. Free all inaccessible objects and coalesce adjacent free chunks. Clear the mark bits of accessible objects. Compute the starting point for the first pass of incremental compaction (compStart). Return the number of surviving objects. " "Details: Each time a non-free object is encountered, decrement the number of available forward table entries. If all entries are spoken for (i.e., entriesAvailable reaches zero), set compStart to the last free chunk before that object or, if there is no free chunk before the given object, the first free chunk after it. Thus, at the end of the sweep phase, compStart through compEnd spans the highest collection of non-free objects that can be accomodated by the forwarding table. This information is used by the first pass of incremental compaction to ensure that space is initially freed at the end of memory. Note that there should always be at least one free chunk--the one at the end of the heap." | entriesAvailable survivors freeChunk firstFree oop oopHeader oopHeaderType hdrBytes oopSize freeChunkSize endOfMemoryLocal | self inline: false. entriesAvailable _ self fwdTableInit: BytesPerWord*2. survivors _ 0. freeChunk _ nil. firstFree _ nil. "will be updated later" endOfMemoryLocal _ endOfMemory. oop _ self oopFromChunk: youngStart. [oop < endOfMemoryLocal] whileTrue: ["get oop's header, header type, size, and header size" oopHeader _ self baseHeader: oop. oopHeaderType _ oopHeader bitAnd: TypeMask. hdrBytes _ headerTypeBytes at: oopHeaderType. (oopHeaderType bitAnd: 1) = 1 ifTrue: [oopSize _ oopHeader bitAnd: SizeMask] ifFalse: [oopHeaderType = HeaderTypeSizeAndClass ifTrue: [oopSize _ (self sizeHeader: oop) bitAnd: LongSizeMask] ifFalse: ["free chunk" oopSize _ oopHeader bitAnd: LongSizeMask]]. (oopHeader bitAnd: MarkBit) = 0 ifTrue: ["object is not marked; free it" "<-- Finalization support: We need to mark each oop chunk as free -->" self longAt: oop - hdrBytes put: HeaderTypeFree. freeChunk ~= nil ifTrue: ["enlarge current free chunk to include this oop" freeChunkSize _ freeChunkSize + oopSize + hdrBytes] ifFalse: ["start a new free chunk" freeChunk _ oop - hdrBytes. "chunk may start 4 or 8 bytes before oop" freeChunkSize _ oopSize + (oop - freeChunk). "adjust size for possible extra header bytes" firstFree = nil ifTrue: [firstFree _ freeChunk]]] ifFalse: ["object is marked; clear its mark bit and possibly adjust the compaction start" self longAt: oop put: (oopHeader bitAnd: AllButMarkBit). "<-- Finalization support: Check if we're running about a weak class -->" (self isWeakNonInt: oop) ifTrue: [self finalizeReference: oop]. entriesAvailable > 0 ifTrue: [entriesAvailable _ entriesAvailable - 1] ifFalse: ["start compaction at the last free chunk before this object" firstFree _ freeChunk]. freeChunk ~= nil ifTrue: ["record the size of the last free chunk" self longAt: freeChunk put: ((freeChunkSize bitAnd: LongSizeMask) bitOr: HeaderTypeFree). freeChunk _ nil]. survivors _ survivors + 1]. oop _ self oopFromChunk: oop + oopSize]. freeChunk ~= nil ifTrue: ["record size of final free chunk" self longAt: freeChunk put: ((freeChunkSize bitAnd: LongSizeMask) bitOr: HeaderTypeFree)]. oop = endOfMemory ifFalse: [self error: 'sweep failed to find exact end of memory']. firstFree = nil ifTrue: [self error: 'expected to find at least one free object'] ifFalse: [compStart _ firstFree]. ^ survivors! ! !ObjectMemory methodsFor: 'gc -- mark and sweep' stamp: 'di 7/1/2004 15:58'! upward "Return from marking an object below. Incoming: field = oop we just worked on, needs to be put away parentField = where to put it in our object NOTE: Type field of object below has already been restored!!!!!! " | type header | self inline: true. (parentField bitAnd: 1) = 1 ifTrue: [parentField = GCTopMarker ifTrue: ["top of the chain" header _ (self longAt: field) bitAnd: AllButTypeMask. type _ self rightType: header. self longAt: field put: (header bitOr: type). "install type on class oop" ^ Done] ifFalse: ["was working on the extended class word" child _ field. "oop of class" field _ parentField - 1. "class word, ** clear the low bit **" parentField _ self longAt: field. header _ self longAt: field + BytesPerWord. "base header word" type _ self rightType: header. self longAt: field put: (child bitOr: type). "install type on class oop" field _ field + BytesPerWord. "point at header" "restore type bits" header _ header bitAnd: AllButTypeMask. self longAt: field put: (header bitOr: type). ^ Upward]] ifFalse: ["normal" child _ field. "who we worked on below" field _ parentField. "where to put it" parentField _ self longAt: field. self longAt: field put: child. field _ field - BytesPerWord. "point at header" ^ StartField]! ! !ObjectMemory methodsFor: 'finalization' stamp: 'di 7/1/2004 15:45'! finalizeReference: oop "During sweep phase we have encountered a weak reference. Check if its object has gone away (or is about to) and if so, signal a semaphore. " "Do *not* inline this in sweepPhase - it is quite an unlikely case to run into a weak reference" | weakOop oopGone chunk firstField lastField | self inline: false. firstField _ BaseHeaderSize + ((self nonWeakFieldsOf: oop) << ShiftForWord). lastField _ self lastPointerOf: oop. firstField to: lastField by: BytesPerWord do: [:i | weakOop _ self longAt: oop + i. (weakOop == nilObj or: [self isIntegerObject: weakOop]) ifFalse: ["Check if the object is being collected. If the weak reference points * backward: check if the weakOops chunk is free * forward: check if the weakOoop has been marked by GC" weakOop < oop ifTrue: [chunk _ self chunkFromOop: weakOop. oopGone _ ((self longAt: chunk) bitAnd: TypeMask) = HeaderTypeFree] ifFalse: [oopGone _ ((self baseHeader: weakOop) bitAnd: MarkBit) = 0]. oopGone ifTrue: ["Store nil in the pointer and signal the interpreter " self longAt: oop + i put: nilObj. self signalFinalization: oop]]]! ! !ObjectMemory methodsFor: 'object enumeration' stamp: 'di 6/11/2004 13:20'! lastPointerOf: oop "Return the byte offset of the last pointer field of the given object. Works with CompiledMethods, as well as ordinary objects. Can be used even when the type bits are not correct." | fmt sz methodHeader header contextSize | self inline: true. header _ self baseHeader: oop. fmt _ header >> 8 bitAnd: 15. fmt <= 4 ifTrue: [(fmt = 3 and: [self isContextHeader: header]) ifTrue: ["contexts end at the stack pointer" contextSize _ self fetchStackPointerOf: oop. ^ CtxtTempFrameStart + contextSize * BytesPerWord]. sz _ self sizeBitsOfSafe: oop. ^ sz - BaseHeaderSize "all pointers"]. fmt < 12 ifTrue: [^ 0]. "no pointers" "CompiledMethod: contains both pointers and bytes:" methodHeader _ self longAt: oop + BaseHeaderSize. ^ (methodHeader >> 10 bitAnd: 255) * BytesPerWord + BaseHeaderSize! ! !ObjectMemory methodsFor: 'object enumeration' stamp: 'ikp 3/26/2005 14:04'! startOfMemory "Return the start of object memory." ^memory! ! !ObjectMemory methodsFor: 'initialization' stamp: 'ikp 3/27/2005 18:06'! adjustAllOopsBy: bytesToShift "Adjust all oop references by the given number of bytes. This is done just after reading in an image when the new base address of the object heap is different from the base address in the image." "di 11/18/2000 - return number of objects found" | oop totalObjects | self inline: false. bytesToShift = 0 ifTrue: [^300000]. "this is probably an improvement over the previous answer of nil, but maybe we should do the obejct counting loop and simply guard the adjustFieldsAndClass... with a bytesToShift = 0 ifFalse: ?" totalObjects _ 0. oop _ self firstObject. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [totalObjects _ totalObjects + 1. self adjustFieldsAndClassOf: oop by: bytesToShift]. oop _ self objectAfter: oop]. ^totalObjects! ! !ObjectMemory methodsFor: 'initialization' stamp: 'ikp 3/26/2005 14:21'! adjustFieldsAndClassOf: oop by: offsetBytes "Adjust all pointers in this object by the given offset." | fieldAddr fieldOop classHeader newClassOop | self inline: true. offsetBytes = 0 ifTrue: [^nil]. fieldAddr _ oop + (self lastPointerOf: oop). [fieldAddr > oop] whileTrue: [fieldOop _ self longAt: fieldAddr. (self isIntegerObject: fieldOop) ifFalse: [self longAt: fieldAddr put: fieldOop + offsetBytes]. fieldAddr _ fieldAddr - BytesPerWord]. (self headerType: oop) ~= HeaderTypeShort ifTrue: ["adjust class header if not a compact class" classHeader _ self longAt: oop - BytesPerWord. newClassOop _ (classHeader bitAnd: AllButTypeMask) + offsetBytes. self longAt: oop - BytesPerWord put: (newClassOop bitOr: (classHeader bitAnd: TypeMask))]! ! !ObjectMemory methodsFor: 'initialization' stamp: 'ikp 9/2/2004 13:54'! bytesPerWord "Answer the size of an object pointer in bytes." ^BytesPerWord! ! !ObjectMemory methodsFor: 'initialization' stamp: 'ikp 9/2/2004 13:00'! initializeMemoryFirstFree: firstFree "Initialize endOfMemory to the top of oop storage space, reserving some space for forwarding blocks, and create the freeBlock from which space is allocated. Also create a fake free chunk at endOfMemory to act as a sentinal for memory scans. " "Note: The amount of space reserved for forwarding blocks should be chosen to ensure that incremental compactions can usually be done in a single pass. However, there should be enough forwarding blocks so a full compaction can be done in a reasonable number of passes, say ten. (A full compaction requires N object-moving passes, where N = number of non-garbage objects / number of forwarding blocks). di 11/18/2000 Re totalObjectCount: Provide a margin of one byte per object to be used for forwarding pointers at GC time. Since fwd blocks are 8 bytes, this means an absolute worst case of 8 passes to compact memory. In most cases it will be adequate to do compaction in a single pass. " | fwdBlockBytes | "reserve space for forwarding blocks" fwdBlockBytes _ totalObjectCount bitAnd: WordMask - BytesPerWord + 1. memoryLimit - fwdBlockBytes >= (firstFree + BaseHeaderSize) ifFalse: ["reserve enough space for a minimal free block of BaseHeaderSize bytes" fwdBlockBytes _ memoryLimit - (firstFree + BaseHeaderSize)]. "set endOfMemory and initialize freeBlock" endOfMemory _ memoryLimit - fwdBlockBytes. freeBlock _ firstFree. self setSizeOfFree: freeBlock to: endOfMemory - firstFree. "bytes available for oops" "make a fake free chunk at endOfMemory for use as a sentinel in memory scans" self setSizeOfFree: endOfMemory to: BaseHeaderSize. DoAssertionChecks ifTrue: [(freeBlock < endOfMemory and: [endOfMemory < memoryLimit]) ifFalse: [self error: 'error in free space computation']. (self oopFromChunk: endOfMemory) = endOfMemory ifFalse: [self error: 'header format must have changed']. (self objectAfter: freeBlock) = endOfMemory ifFalse: [self error: 'free block not properly initialized']]! ! !ObjectMemory methodsFor: 'become' stamp: 'di 8/3/2004 12:23'! allYoung: array1 and: array2 "Return true if all the oops in both arrays, and the arrays themselves, are in the young object space." | fieldOffset | array1 < youngStart ifTrue: [^ false]. array2 < youngStart ifTrue: [^ false]. fieldOffset _ self lastPointerOf: array1. "same size as array2" [fieldOffset >= BaseHeaderSize] whileTrue: [(self longAt: array1 + fieldOffset) < youngStart ifTrue: [^ false]. (self longAt: array2 + fieldOffset) < youngStart ifTrue: [^ false]. fieldOffset _ fieldOffset - BytesPerWord]. ^ true! ! !ObjectMemory methodsFor: 'become' stamp: 'di 8/3/2004 13:12'! containOnlyOops: array1 and: array2 "Return true if neither array contains a small integer. You can't become: integers!!" | fieldOffset | fieldOffset _ self lastPointerOf: array1. "same size as array2" [fieldOffset >= BaseHeaderSize] whileTrue: [(self isIntegerObject: (self longAt: array1 + fieldOffset)) ifTrue: [^ false]. (self isIntegerObject: (self longAt: array2 + fieldOffset)) ifTrue: [^ false]. fieldOffset _ fieldOffset - BytesPerWord]. ^ true! ! !ObjectMemory methodsFor: 'become' stamp: 'tpr 3/23/2005 12:05'! prepareForwardingTableForBecoming: array1 with: array2 twoWay: twoWayFlag "Ensure that there are enough forwarding blocks to accomodate this become, then prepare forwarding blocks for the pointer swap. Return true if successful." "Details: Doing a GC might generate enough space for forwarding blocks if we're short. However, this is an uncommon enough case that it is better handled by primitive fail code at the Smalltalk level." "Important note on multiple references to same object - since the preparation of fwdBlocks is NOT idempotent we get VM crashes if the same object is referenced more than once in such a way as to require multiple fwdBlocks. oop1 forwardBecome: oop1 is ok since only a single fwdBlock is needed. oop1 become: oop1 would fail because the second fwdBlock woudl not have the actual object header but rather the mutated ref to the first fwdBlock. Further problems can arise with an array1 or array2 that refer multiply to the same object. This would notbe expected input for programmer writen code but might arise from automatic usage such as in ImageSegment loading. To avoid the simple and rather common case of oop1 become*: oop1, we skip such pairs and simply avoid making fwdBlocks - it is redundant anyway" | entriesNeeded entriesAvailable fieldOffset oop1 oop2 fwdBlock fwdBlkSize | entriesNeeded := (self lastPointerOf: array1) // BytesPerWord. "need enough entries for all oops" "Note: Forward blocks must be quadword aligned - see fwdTableInit:." twoWayFlag ifTrue: ["Double the number of blocks for two-way become" entriesNeeded _ entriesNeeded * 2. fwdBlkSize _ BytesPerWord * 2] ifFalse: ["One-way become needs backPointers in fwd blocks." fwdBlkSize _ BytesPerWord * 4]. entriesAvailable _ self fwdTableInit: fwdBlkSize. entriesAvailable < entriesNeeded ifTrue: [self initializeMemoryFirstFree: freeBlock. "re-initialize the free block" ^ false]. fieldOffset _ self lastPointerOf: array1. [fieldOffset >= BaseHeaderSize] whileTrue: [oop1 _ self longAt: array1 + fieldOffset. oop2 _ self longAt: array2 + fieldOffset. "if oop1 == oop2, no need to do any work for this pair. May still be other entries in the arrays though so keep looking" oop1 = oop2 ifFalse: [fwdBlock _ self fwdBlockGet: fwdBlkSize. self initForwardBlock: fwdBlock mapping: oop1 to: oop2 withBackPtr: twoWayFlag not. twoWayFlag ifTrue: ["Second block maps oop2 back to oop1 for two-way become" fwdBlock _ self fwdBlockGet: fwdBlkSize. self initForwardBlock: fwdBlock mapping: oop2 to: oop1 withBackPtr: twoWayFlag not]]. fieldOffset _ fieldOffset - BytesPerWord]. ^ true! ! !ObjectMemory methodsFor: 'become' stamp: 'di 7/22/2004 17:50'! restoreHeaderOf: oop "Restore the original header of the given oop from its forwarding block." | fwdHeader fwdBlock | fwdHeader _ self longAt: oop. fwdBlock _ (fwdHeader bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [(fwdHeader bitAnd: MarkBit) = 0 ifTrue: [self error: 'attempting to restore the header of an object that has no forwarding block']. self fwdBlockValidate: fwdBlock]. self longAt: oop put: (self longAt: fwdBlock + BytesPerWord)! ! !ObjectMemory methodsFor: 'become' stamp: 'tpr 3/23/2005 12:07'! restoreHeadersAfterBecoming: list1 with: list2 "Restore the headers of all oops in both lists. Exchange their hash bits so becoming objects in identity sets and dictionaries doesn't change their hash value." "See also prepareForwardingTableForBecoming:with:woWay: for notes regarding the case of oop1 = oop2" | fieldOffset oop1 oop2 hdr1 hdr2 | fieldOffset _ self lastPointerOf: list1. [fieldOffset >= BaseHeaderSize] whileTrue: [oop1 _ self longAt: list1 + fieldOffset. oop2 _ self longAt: list2 + fieldOffset. oop1 = oop2 ifFalse: [self restoreHeaderOf: oop1. self restoreHeaderOf: oop2. "Exchange hash bits of the two objects." hdr1 _ self longAt: oop1. hdr2 _ self longAt: oop2. self longAt: oop1 put: ((hdr1 bitAnd: AllButHashBits) bitOr: (hdr2 bitAnd: HashBits)). self longAt: oop2 put: ((hdr2 bitAnd: AllButHashBits) bitOr: (hdr1 bitAnd: HashBits))]. fieldOffset _ fieldOffset - BytesPerWord]! ! !ObjectMemory methodsFor: 'become' stamp: 'di 7/22/2004 17:59'! restoreHeadersAfterForwardBecome: copyHashFlag "Forward become leaves us with no original oops in the mutated object list, so we must enumerate the (four-word) forwarding blocks where we have stored backpointers." "This loop start is copied from fwdTableInit:" | oop1 fwdBlock oop2 hdr1 hdr2 | fwdBlock _ endOfMemory + BaseHeaderSize + 7 bitAnd: WordMask - 7. fwdBlock _ fwdBlock + 16. "fwdBlockGet: did a pre-increment" [fwdBlock <= fwdTableNext "fwdTableNext points to the last active block"] whileTrue: [oop1 _ self longAt: fwdBlock + (BytesPerWord*2). "Backpointer to mutated object." oop2 _ self longAt: fwdBlock. self restoreHeaderOf: oop1. copyHashFlag ifTrue: ["Change the hash of the new oop (oop2) to be that of the old (oop1) so mutated objects in hash structures will be happy after the change." hdr1 _ self longAt: oop1. hdr2 _ self longAt: oop2. self longAt: oop2 put: ((hdr2 bitAnd: AllButHashBits) bitOr: (hdr1 bitAnd: HashBits))]. fwdBlock _ fwdBlock + (BytesPerWord*4)]! ! !ObjectMemory methodsFor: 'allocation' stamp: 'ikp 3/27/2005 18:07'! allocate: byteSize headerSize: hdrSize h1: baseHeader h2: classOop h3: extendedSize doFill: doFill with: fillWord "Allocate a new object of the given size and number of header words. (Note: byteSize already includes space for the base header word.) Initialize the header fields of the new object and fill the remainder of the object with the given value. May cause a GC" | newObj remappedClassOop end i | self inline: true. self var: #i type: 'usqInt'. self var: #end type: 'usqInt'. "remap classOop in case GC happens during allocation" hdrSize > 1 ifTrue: [self pushRemappableOop: classOop]. newObj _ self allocateChunk: byteSize + (hdrSize - 1 * BytesPerWord). hdrSize > 1 ifTrue: [remappedClassOop _ self popRemappableOop]. hdrSize = 3 ifTrue: [self longAt: newObj put: (extendedSize bitOr: HeaderTypeSizeAndClass). self longAt: newObj + BytesPerWord put: (remappedClassOop bitOr: HeaderTypeSizeAndClass). self longAt: newObj + (BytesPerWord*2) put: (baseHeader bitOr: HeaderTypeSizeAndClass). newObj _ newObj + (BytesPerWord*2)]. hdrSize = 2 ifTrue: [self longAt: newObj put: (remappedClassOop bitOr: HeaderTypeClass). self longAt: newObj + BytesPerWord put: (baseHeader bitOr: HeaderTypeClass). newObj _ newObj + BytesPerWord]. hdrSize = 1 ifTrue: [self longAt: newObj put: (baseHeader bitOr: HeaderTypeShort)]. "clear new object" doFill ifTrue: [end _ newObj + byteSize. i _ newObj + BytesPerWord. [i < end] whileTrue: [self longAt: i put: fillWord. i _ i + BytesPerWord]]. DoAssertionChecks ifTrue: [self okayOop: newObj. self oopHasOkayClass: newObj. (self objectAfter: newObj) = freeBlock ifFalse: [self error: 'allocate bug: did not set header of new oop correctly']. (self objectAfter: freeBlock) = endOfMemory ifFalse: [self error: 'allocate bug: did not set header of freeBlock correctly']]. ^newObj! ! !ObjectMemory methodsFor: 'allocation' stamp: 'ikp 8/4/2004 18:29'! allocateChunk: byteSize "Allocate a chunk of the given size. Sender must be sure that the requested size includes enough space for the header word(s). " "Details: To limit the time per incremental GC, do one every so many allocations. The number is settable via primitiveVMParameter to tune your memory system" | enoughSpace newFreeSize newChunk | self inline: true. allocationCount >= allocationsBetweenGCs ifTrue: ["do an incremental GC every so many allocations to keep pauses short" self incrementalGC]. enoughSpace _ self sufficientSpaceToAllocate: byteSize. enoughSpace ifFalse: ["signal that space is running low, but proceed with allocation if possible" signalLowSpace _ true. lowSpaceThreshold _ 0. "disable additional interrupts until lowSpaceThreshold is reset by image" self forceInterruptCheck]. (self cCoerce: (self sizeOfFree: freeBlock) to: 'usqInt ') < (self cCoerce: byteSize + BaseHeaderSize to: 'usqInt ') ifTrue: [self error: 'out of memory']. "if we get here, there is enough space for allocation to succeed " newFreeSize _ (self sizeOfFree: freeBlock) - byteSize. newChunk _ freeBlock. freeBlock _ freeBlock + byteSize. "Assume: client will initialize object header of free chunk, so following is not needed:" "self setSizeOfFree: newChunk to: byteSize." self setSizeOfFree: freeBlock to: newFreeSize. allocationCount _ allocationCount + 1. ^newChunk! ! !ObjectMemory methodsFor: 'allocation' stamp: 'di 8/3/2004 12:25'! clone: oop "Return a shallow copy of the given object. May cause GC" "Assume: Oop is a real object, not a small integer." | extraHdrBytes bytes newChunk remappedOop fromIndex toIndex lastFrom newOop header hash | self inline: false. extraHdrBytes _ self extraHeaderBytes: oop. bytes _ self sizeBitsOf: oop. bytes _ bytes + extraHdrBytes. "allocate space for the copy, remapping oop in case of a GC" self pushRemappableOop: oop. newChunk _ self allocateChunk: bytes. remappedOop _ self popRemappableOop. "copy old to new including all header words" toIndex _ newChunk - BytesPerWord. "loop below uses pre-increment" fromIndex _ (remappedOop - extraHdrBytes) - BytesPerWord. lastFrom _ fromIndex + bytes. [fromIndex < lastFrom] whileTrue: [ self longAt: (toIndex _ toIndex + BytesPerWord) put: (self longAt: (fromIndex _ fromIndex + BytesPerWord))]. newOop _ newChunk + extraHdrBytes. "convert from chunk to oop" "fix base header: compute new hash and clear Mark and Root bits" hash _ self newObjectHash. header _ (self longAt: newOop) bitAnd: 16r1FFFF. "use old ccIndex, format, size, and header-type fields" header _ header bitOr: ((hash << 17) bitAnd: 16r1FFE0000). self longAt: newOop put: header. ^newOop ! ! !ObjectMemory methodsFor: 'allocation' stamp: 'ikp 8/4/2004 18:30'! sufficientSpaceAfterGC: minFree "Return true if there is enough free space after doing a garbage collection. If not, signal that space is low." | growSize | self inline: false. self incrementalGC. "try to recover some space" (self cCoerce: (self sizeOfFree: freeBlock) to: 'usqInt ') < (self cCoerce: minFree to: 'usqInt ') ifTrue: [signalLowSpace ifTrue: [^false]. "give up; problem is already noted" self fullGC. "try harder" "for stability, require more free space after doing an expensive full GC" (self cCoerce: (self sizeOfFree: freeBlock) to: 'usqInt ') >= ((self cCoerce: minFree to: 'usqInt ') + 15000) ifTrue: [^ true]. "still not enough; attempt to grow object memory" growSize _ minFree - (self sizeOfFree: freeBlock) + growHeadroom. self growObjectMemory: growSize. (self cCoerce: (self sizeOfFree: freeBlock) to: 'usqInt ') >= ((self cCoerce: minFree to: 'usqInt ') + 15000) ifTrue: [^true]. "still not enough" ^false]. ^true! ! !ObjectMemory methodsFor: 'allocation' stamp: 'ikp 8/4/2004 18:30'! sufficientSpaceToAllocate: bytes "Return true if there is enough space to allocate the given number of bytes, perhaps after doing a garbage collection." | minFree | self inline: true. minFree _ lowSpaceThreshold + bytes + BaseHeaderSize. "check for low-space" (self cCoerce: (self sizeOfFree: freeBlock) to: 'usqInt ') >= (self cCoerce: minFree to: 'usqInt ') ifTrue: [^true] ifFalse: [^self sufficientSpaceAfterGC: minFree].! ! !ObjectMemory methodsFor: 'header access' stamp: 'di 6/13/2004 06:55'! classHeader: oop ^ self longAt: oop - BaseHeaderSize! ! !ObjectMemory methodsFor: 'header access' stamp: 'di 10/6/2004 10:26'! formatOf: oop " 0 no fields 1 fixed fields only (all containing pointers) 2 indexable fields only (all containing pointers) 3 both fixed and indexable fields (all containing pointers) 4 both fixed and indexable weak fields (all containing pointers). 5 unused 6 indexable word fields only (no pointers) 7 indexable long (64-bit) fields (only in 64-bit images) 8-11 indexable byte fields only (no pointers) (low 2 bits are low 2 bits of size) 12-15 compiled methods: # of literal oops specified in method header, followed by indexable bytes (same interpretation of low 2 bits as above) " ^ ((self baseHeader: oop) >> 8) bitAnd: 16rF! ! !ObjectMemory methodsFor: 'header access' stamp: 'di 6/11/2004 16:34'! sizeBitsOf: oop "Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words." "Note: byte indexable objects need to have low bits subtracted from this size." | header | header _ self baseHeader: oop. (header bitAnd: TypeMask) = HeaderTypeSizeAndClass ifTrue: [ ^ (self sizeHeader: oop) bitAnd: LongSizeMask ] ifFalse: [ ^ header bitAnd: SizeMask ].! ! !ObjectMemory methodsFor: 'header access' stamp: 'di 6/11/2004 13:15'! sizeHeader: oop ^ self longAt: oop - (BytesPerWord*2)! ! !ObjectMemory methodsFor: 'garbage collection' stamp: 'di 7/2/2004 12:29'! incrementalGC "Do a mark/sweep garbage collection of just the young object area of object memory (i.e., objects above youngStart), using the root table to identify objects containing pointers to young objects from the old object area." | survivorCount startTime | self inline: false. rootTableCount >= RootTableSize ifTrue: ["root table overflow; cannot do an incremental GC (this should be very rare)" statRootTableOverflows _ statRootTableOverflows + 1. ^ self fullGC]. DoAssertionChecks ifTrue: [self reverseDisplayFrom: 8 to: 15. self validateRoots; validate]. self preGCAction: false. "incremental GC and compaction" startTime _ self ioMicroMSecs. self markPhase. survivorCount _ self sweepPhase. self incrementalCompaction. allocationCount _ 0. statIncrGCs _ statIncrGCs + 1. statIncrGCMSecs _ statIncrGCMSecs + (self ioMicroMSecs - startTime). self forceInterruptCheck. "Force an an interrupt check ASAP.We could choose to be clever here and only do this under certain time conditions. Keep it simple for now" (survivorCount > tenuringThreshold or: [rootTableCount >= RootTableRedZone]) ifTrue: ["move up the young space boundary if * there are too many survivors: this limits the number of objects that must be processed on future incremental GC's * we're about to overflow the roots table this limits the number of full GCs that may be caused by root table overflows in the near future" statTenures _ statTenures + 1. self clearRootsTable. youngStart _ freeBlock]. self postGCAction. DoAssertionChecks ifTrue: [self validateRoots; validate. self reverseDisplayFrom: 8 to: 15]! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 14:28'! beRootWhileForwarding: oop "Record that the given oop in the old object area points to an object in the young area when oop may be forwarded." "Warning: No young objects should be recorded as roots. Callers are responsible for ensuring this constraint is not violated." | header fwdBlock | header _ self longAt: oop. (header bitAnd: MarkBit) ~= 0 ifTrue: ["This oop is forwarded" fwdBlock _ (header bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [ self fwdBlockValidate: fwdBlock ]. self noteAsRoot: oop headerLoc: fwdBlock + BytesPerWord] ifFalse: ["Normal -- no forwarding" self noteAsRoot: oop headerLoc: oop]! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:29'! fwdTableInit: blkSize "Set the limits for a table of two- or three-word forwarding blocks above the last used oop. The pointer fwdTableNext moves up to fwdTableLast. Used for compaction of memory and become-ing objects. Returns the number of forwarding blocks available." | | self inline: false. "set endOfMemory to just after a minimum-sized free block" self setSizeOfFree: freeBlock to: BaseHeaderSize. endOfMemory _ freeBlock + BaseHeaderSize. "make a fake free chunk at endOfMemory for use as a sentinal in memory scans" self setSizeOfFree: endOfMemory to: BaseHeaderSize. "use all memory free between freeBlock and memoryLimit for forwarding table" "Note: Forward blocks must be quadword aligned." fwdTableNext _ (endOfMemory + BaseHeaderSize + 7) bitAnd: WordMask-7. self flag: #Dan. "Above line does not do what it says (quadword is 16 or 32 bytes)" fwdTableLast _ memoryLimit - blkSize. "last forwarding table entry" "return the number of forwarding blocks available" ^ (fwdTableLast - fwdTableNext) // blkSize "round down"! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:30'! fwdTableSize: blkSize "Estimate the number of forwarding blocks available for compaction" | eom fwdFirst fwdLast | self inline: false. eom _ freeBlock + BaseHeaderSize. "use all memory free between freeBlock and memoryLimit for forwarding table" "Note: Forward blocks must be quadword aligned." fwdFirst _ (eom + BaseHeaderSize + 7) bitAnd: WordMask-7. self flag: #Dan. "Above line does not do what it says (quadword is 16 or 32 bytes)" fwdLast _ memoryLimit - blkSize. "last forwarding table entry" "return the number of forwarding blocks available" ^ (fwdLast - fwdFirst) // blkSize "round down"! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 14:55'! incCompBody "Move objects to consolidate free space into one big chunk. Return the newly created free chunk." | bytesFreed | self inline: false. "reserve memory for forwarding table" self fwdTableInit: BytesPerWord*2. "Two-word blocks" "assign new oop locations, reverse their headers, and initialize forwarding blocks" bytesFreed _ self incCompMakeFwd. "update pointers to point at new oops" self mapPointersInObjectsFrom: youngStart to: endOfMemory. "move the objects and restore their original headers; return the new free chunk" ^ self incCompMove: bytesFreed! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 14:56'! incCompMakeFwd "Create and initialize forwarding blocks for all non-free objects following compStart. If the supply of forwarding blocks is exhausted, set compEnd to the first chunk above the area to be compacted; otherwise, set it to endOfMemory. Return the number of bytes to be freed." | bytesFreed oop fwdBlock newOop | self inline: false. bytesFreed _ 0. oop _ self oopFromChunk: compStart. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifTrue: [bytesFreed _ bytesFreed + (self sizeOfFree: oop)] ifFalse: ["create a forwarding block for oop" fwdBlock _ self fwdBlockGet: BytesPerWord*2. "Two-word block" fwdBlock = nil ifTrue: ["stop; we have used all available forwarding blocks" compEnd _ self chunkFromOop: oop. ^ bytesFreed]. newOop _ oop - bytesFreed. self initForwardBlock: fwdBlock mapping: oop to: newOop withBackPtr: false]. oop _ self objectAfterWhileForwarding: oop]. compEnd _ endOfMemory. ^ bytesFreed! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 14:58'! incCompMove: bytesFreed "Move all non-free objects between compStart and compEnd to their new locations, restoring their headers in the process. Create a new free block at the end of memory. Return the newly created free chunk. " "Note: The free block used by the allocator always must be the last free block in memory. It may take several compaction passes to make all free space bubble up to the end of memory." | oop next fwdBlock newOop header bytesToMove firstWord lastWord newFreeChunk sz target | self inline: false. newOop _ nil. oop _ self oopFromChunk: compStart. [oop < compEnd] whileTrue: [next _ self objectAfterWhileForwarding: oop. (self isFreeObject: oop) ifFalse: ["a moving object; unwind its forwarding block" fwdBlock _ ((self longAt: oop) bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [self fwdBlockValidate: fwdBlock]. newOop _ self longAt: fwdBlock. header _ self longAt: fwdBlock + BytesPerWord. self longAt: oop put: header. "restore the original header" bytesToMove _ oop - newOop. "move the oop (including any extra header words) " sz _ self sizeBitsOf: oop. firstWord _ oop - (self extraHeaderBytes: oop). lastWord _ oop + sz - BaseHeaderSize. target _ firstWord - bytesToMove. firstWord to: lastWord by: BytesPerWord do: [:w | self longAt: target put: (self longAt: w). target _ target + BytesPerWord]]. oop _ next]. newOop = nil ifTrue: ["no objects moved" oop _ self oopFromChunk: compStart. ((self isFreeObject: oop) and: [(self objectAfter: oop) = (self oopFromChunk: compEnd)]) ifTrue: [newFreeChunk _ oop] ifFalse: [newFreeChunk _ freeBlock]] ifFalse: ["initialize the newly freed memory chunk" "newOop is the last object moved; free chunk starts right after it" newFreeChunk _ newOop + (self sizeBitsOf: newOop). self setSizeOfFree: newFreeChunk to: bytesFreed]. DoAssertionChecks ifTrue: [(self objectAfter: newFreeChunk) = (self oopFromChunk: compEnd) ifFalse: [self error: 'problem creating free chunk after compaction']]. (self objectAfter: newFreeChunk) = endOfMemory ifTrue: [self initializeMemoryFirstFree: newFreeChunk] ifFalse: ["newFreeChunk is not at end of memory; re-install freeBlock " self initializeMemoryFirstFree: freeBlock]. ^ newFreeChunk! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:00'! initForwardBlock: fwdBlock mapping: oop to: newOop withBackPtr: backFlag "Initialize the given forwarding block to map oop to newOop, and replace oop's header with a pointer to the fowarding block. " "Details: The mark bit is used to indicate that an oop is forwarded. When an oop is forwarded, its header (minus the mark bit) contains the address of its forwarding block. (The forwarding block address is actually shifted right by one bit so that its top-most bit does not conflict with the header's mark bit; since fowarding blocks are stored on word boundaries, the low two bits of the address are always zero.) The first word of the forwarding block is the new oop; the second word is the oop's orginal header. In the case of a forward become, a four-word block is used, with the third field being a backpointer to the old oop (for header fixup), and the fourth word is unused. The type bits of the forwarding header are the same as those of the original header. " | originalHeader originalHeaderType | self inline: true. originalHeader _ self longAt: oop. DoAssertionChecks ifTrue: [fwdBlock = nil ifTrue: [self error: 'ran out of forwarding blocks in become']. (originalHeader bitAnd: MarkBit) ~= 0 ifTrue: [self error: 'object already has a forwarding table entry']]. originalHeaderType _ originalHeader bitAnd: TypeMask. self longAt: fwdBlock put: newOop. self longAt: fwdBlock + BytesPerWord put: originalHeader. backFlag ifTrue: [self longAt: fwdBlock + (BytesPerWord*2) put: oop]. self longAt: oop put: (fwdBlock >> 1 bitOr: (MarkBit bitOr: originalHeaderType))! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:04'! lastPointerWhileForwarding: oop "The given object may have its header word in a forwarding block. Find the offset of the last pointer in the object in spite of this obstacle. " | header fwdBlock fmt size methodHeader contextSize | self inline: true. header _ self longAt: oop. (header bitAnd: MarkBit) ~= 0 ifTrue: ["oop is forwarded; get its real header from its forwarding table entry" fwdBlock _ (header bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [self fwdBlockValidate: fwdBlock]. header _ self longAt: fwdBlock + BytesPerWord]. fmt _ header >> 8 bitAnd: 15. fmt <= 4 ifTrue: [(fmt = 3 and: [self isContextHeader: header]) ifTrue: ["contexts end at the stack pointer" contextSize _ self fetchStackPointerOf: oop. ^ CtxtTempFrameStart + contextSize * BytesPerWord]. "do sizeBitsOf: using the header we obtained" (header bitAnd: TypeMask) = HeaderTypeSizeAndClass ifTrue: [size _ (self sizeHeader: oop) bitAnd: AllButTypeMask] ifFalse: [size _ header bitAnd: SizeMask]. ^ size - BaseHeaderSize]. fmt < 12 ifTrue: [^ 0]. "no pointers" methodHeader _ self longAt: oop + BaseHeaderSize. ^ (methodHeader >> 10 bitAnd: 255) * BytesPerWord + BaseHeaderSize! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:35'! objectAfterWhileForwarding: oop "Return the oop of the object after the given oop when the actual header of the oop may be in the forwarding table." | header fwdBlock realHeader sz | self inline: true. header _ self longAt: oop. (header bitAnd: MarkBit) = 0 ifTrue: [ ^ self objectAfter: oop ]. "oop not forwarded" "Assume: mark bit cannot be set on a free chunk, so if we get here, oop is not free and it has a forwarding table entry" fwdBlock _ (header bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [ self fwdBlockValidate: fwdBlock ]. realHeader _ self longAt: fwdBlock + BytesPerWord. "following code is like sizeBitsOf:" (realHeader bitAnd: TypeMask) = HeaderTypeSizeAndClass ifTrue: [ sz _ (self sizeHeader: oop) bitAnd: LongSizeMask ] ifFalse: [ sz _ realHeader bitAnd: SizeMask ]. ^ self oopFromChunk: (oop + sz)! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:37'! remapClassOf: oop "Update the class of the given object, if necessary, using its forwarding table entry." "Note: Compact classes need not be remapped since the compact class field is just an index into the compact class table. The header type bits show if this object has a compact class; we needn't look up the oop's real header." | classHeader classOop fwdBlock newClassOop newClassHeader | (self headerType: oop) = HeaderTypeShort ifTrue: [^ nil]. "compact classes needn't be mapped" classHeader _ self longAt: oop - BytesPerWord. classOop _ classHeader bitAnd: AllButTypeMask. (self isObjectForwarded: classOop) ifTrue: [fwdBlock _ ((self longAt: classOop) bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [self fwdBlockValidate: fwdBlock]. newClassOop _ self longAt: fwdBlock. newClassHeader _ newClassOop bitOr: (classHeader bitAnd: TypeMask). self longAt: oop - BytesPerWord put: newClassHeader. "The following ensures that become: into an old object's class makes it a root. It does nothing during either incremental or full compaction because oop will never be < youngStart." (oop < youngStart and: [newClassOop >= youngStart]) ifTrue: [self beRootWhileForwarding: oop]]! ! !ObjectMemory methodsFor: 'gc -- compaction' stamp: 'di 7/1/2004 15:37'! remapFieldsAndClassOf: oop "Replace all forwarded pointers in this object with their new oops, using the forwarding table. Remap its class as well, if necessary. " "Note: The given oop may be forwarded itself, which means that its real header is in its forwarding table entry." | fieldOffset fieldOop fwdBlock newOop | self inline: true. fieldOffset _ self lastPointerWhileForwarding: oop. [fieldOffset >= BaseHeaderSize] whileTrue: [fieldOop _ self longAt: oop + fieldOffset. (self isObjectForwarded: fieldOop) ifTrue: ["update this oop from its forwarding block" fwdBlock _ ((self longAt: fieldOop) bitAnd: AllButMarkBitAndTypeMask) << 1. DoAssertionChecks ifTrue: [self fwdBlockValidate: fwdBlock]. newOop _ self longAt: fwdBlock. self longAt: oop + fieldOffset put: newOop. "The following ensures that become: into old object makes it a root. It does nothing during either incremental or full compaction because oop will never be < youngStart." (oop < youngStart and: [newOop >= youngStart]) ifTrue: [self beRootWhileForwarding: oop]]. fieldOffset _ fieldOffset - BytesPerWord]. self remapClassOf: oop! ! !ObjectMemory methodsFor: 'memory access' stamp: 'tpr 3/17/2005 18:40'! validate "null method just to stop compilation of interp.c from barfing"! ! !ObjectMemory methodsFor: 'memory access' stamp: 'di 7/1/2004 17:22'! validateRoots "Verify that every old object that points to a new object has its root bit set, and appears in the rootTable. This method should not be called if the rootTable is full, because roots are no longer recorded, and incremental collections are not attempted. If DoAssertionChecks is true, this routine will halt on an unmarked root. Otherwise, this routine will merely return true in that case." | oop fieldAddr fieldOop header badRoot | badRoot _ false. oop _ self firstObject. [oop < youngStart] whileTrue: [(self isFreeObject: oop) ifFalse: [fieldAddr _ oop + (self lastPointerOf: oop). [fieldAddr > oop] whileTrue: [fieldOop _ self longAt: fieldAddr. (fieldOop >= youngStart and: [(self isIntegerObject: fieldOop) not]) ifTrue: ["fieldOop is a pointer to a young object" header _ self longAt: oop. (header bitAnd: RootBit) = 0 ifTrue: ["Forbidden: points to young obj but root bit not set." DoAssertionChecks ifTrue: [self error: 'root bit not set']. badRoot _ true] ifFalse: ["Root bit is set" "Extreme test -- validate that oop was entered in rootTable too..." "Disabled for now... found _ false. 1 to: rootTableCount do: [:i | oop = (rootTable at: i) ifTrue: [found _ true]]. found ifFalse: [DoAssertionChecks ifTrue: [self error: 'root table not set']. badRoot _ true]. ..." ]]. fieldAddr _ fieldAddr - BytesPerWord]]. oop _ self objectAfter: oop]. ^ badRoot! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 6/9/2004 23:16'! fetchByte: byteIndex ofObject: oop ^ self byteAt: oop + BaseHeaderSize + byteIndex! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/4/2004 08:34'! fetchLong32: fieldIndex ofObject: oop "index by 32-bit units, and return a 32-bit value" ^ self long32At: oop + BaseHeaderSize + (fieldIndex << 2)! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/4/2004 11:11'! fetchLong32LengthOf: objectPointer "Gives size appropriate for, eg, fetchLong32" | sz | sz _ self sizeBitsOf: objectPointer. ^ (sz - BaseHeaderSize) >> 2! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/4/2004 08:33'! fetchPointer: fieldIndex ofObject: oop "index by word size, and return a pointer as long as the word size" ^ self longAt: oop + BaseHeaderSize + (fieldIndex << ShiftForWord)! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 8/2/2004 17:33'! fetchWord: fieldIndex ofObject: oop "This message is deprecated. Use fetchLong32, fetchLong64 or fetchPointer" self error: 'deprecated -- do not use -- and then delete me'! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/4/2004 09:34'! fetchWordLengthOf: objectPointer "NOTE: this gives size appropriate for fetchPointer: n, but not in general for, eg, fetchLong32, etc." | sz | sz _ self sizeBitsOf: objectPointer. ^ (sz - BaseHeaderSize) >> ShiftForWord! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 3/27/2005 18:07'! instantiateClass: classPointer indexableSize: size "NOTE: This method supports the backward-compatible split instSize field of the class format word. The sizeHiBits will go away and other shifts change by 2 when the split fields get merged in an (incompatible) image change." | hash header1 header2 cClass byteSize format binc header3 hdrSize fillWord newObj sizeHiBits bm1 classFormat | self inline: false. DoAssertionChecks ifTrue: [size < 0 ifTrue: [self error: 'cannot have a negative indexable field count']]. hash _ self newObjectHash. classFormat _ self formatOfClass: classPointer. "Low 2 bits are 0" header1 _ (classFormat bitAnd: 16r1FF00) bitOr: (hash << HashBitsOffset bitAnd: HashBits). header2 _ classPointer. header3 _ 0. sizeHiBits _ (classFormat bitAnd: 16r60000) >> 9. cClass _ header1 bitAnd: CompactClassMask. "compact class field from format word" byteSize _ (classFormat bitAnd: SizeMask + Size4Bit) + sizeHiBits. "size in bytes -- low 2 bits are 0" "Note this byteSize comes from the format word of the class which is pre-shifted to 4 bytes per field. Need another shift for 8 bytes per word..." byteSize _ byteSize << (ShiftForWord-2). format _ classFormat >> 8 bitAnd: 15. self flag: #sizeLowBits. format < 8 ifTrue: [format = 6 ifTrue: ["long32 bitmaps" bm1 _ BytesPerWord-1. byteSize _ byteSize + (size * 4) + bm1 bitAnd: LongSizeMask. "round up" binc _ bm1 - ((size * 4) + bm1 bitAnd: bm1). "odd bytes" "extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits)" header1 _ header1 bitOr: (binc bitAnd: 4)] ifFalse: [byteSize _ byteSize + (size * BytesPerWord) "Arrays and 64-bit bitmaps"] ] ifFalse: ["Strings and Methods" bm1 _ BytesPerWord-1. byteSize _ byteSize + size + bm1 bitAnd: LongSizeMask. "round up" binc _ bm1 - (size + bm1 bitAnd: bm1). "odd bytes" "low bits of byte size go in format field" header1 _ header1 bitOr: (binc bitAnd: 3) << 8. "extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits)" header1 _ header1 bitOr: (binc bitAnd: 4)]. byteSize > 255 ifTrue: ["requires size header word" header3 _ byteSize. header1 _ header1] ifFalse: [header1 _ header1 bitOr: byteSize]. header3 > 0 ifTrue: ["requires full header" hdrSize _ 3] ifFalse: [cClass = 0 ifTrue: [hdrSize _ 2] ifFalse: [hdrSize _ 1]]. format <= 4 ifTrue: ["if pointers, fill with nil oop" fillWord _ nilObj] ifFalse: [fillWord _ 0]. newObj _ self allocate: byteSize headerSize: hdrSize h1: header1 h2: header2 h3: header3 doFill: true with: fillWord. ^ newObj! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/7/2004 16:46'! instantiateContext: classPointer sizeInBytes: sizeInBytes "This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include four bytes for the base header word." | hash header1 header2 hdrSize | hash _ self newObjectHash. header1 _ (hash << HashBitsOffset bitAnd: HashBits) bitOr: (self formatOfClass: classPointer). header2 _ classPointer. (header1 bitAnd: CompactClassMask) > 0 "are contexts compact?" ifTrue: [hdrSize _ 1] ifFalse: [hdrSize _ 2]. sizeInBytes <= SizeMask ifTrue: ["OR size into header1. Must not do this if size > SizeMask" header1 _ header1 + (sizeInBytes - (header1 bitAnd: SizeMask))] ifFalse: [hdrSize _ 3. "Zero the size field of header1 if large" header1 _ header1 - (header1 bitAnd: SizeMask)]. self flag: #Dan. "Check details of context sizes" ^ self allocate: sizeInBytes headerSize: hdrSize h1: header1 h2: header2 h3: LargeContextSize doFill: false with: 0! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 8/2/2004 17:04'! instantiateSmallClass: classPointer sizeInBytes: sizeInBytes fill: fillValue "This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include 4 or 8 bytes for the base header word. NOTE this code will only work for sizes that are an integral number of words (like not a 32-bit LargeInteger in a 64-bit system). May cause a GC" | hash header1 header2 hdrSize | (sizeInBytes bitAnd: (BytesPerWord-1)) = 0 ifFalse: [self error: 'size must be integral number of words']. hash _ self newObjectHash. header1 _ (hash << HashBitsOffset bitAnd: HashBits) bitOr: (self formatOfClass: classPointer). header2 _ classPointer. (header1 bitAnd: CompactClassMask) > 0 "is this a compact class" ifTrue: [hdrSize _ 1] ifFalse: [hdrSize _ 2]. header1 _ header1 + (sizeInBytes - (header1 bitAnd: SizeMask+Size4Bit)). ^ self allocate: sizeInBytes headerSize: hdrSize h1: header1 h2: header2 h3: 0 doFill: true with: fillValue! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 8/4/2004 15:32'! integerObjectOf: value ^(value << 1) + 1! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 8/4/2004 15:29'! isIntegerValue: valueWord ^ valueWord >= 16r-40000000 and: [valueWord <= 16r3FFFFFFF]! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 6/9/2004 23:16'! storeByte: byteIndex ofObject: oop withValue: valueByte ^ self byteAt: oop + BaseHeaderSize + byteIndex put: valueByte! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 7/4/2004 08:48'! storeLong32: fieldIndex ofObject: oop withValue: valueWord ^ self long32At: oop + BaseHeaderSize + (fieldIndex << 2) put: valueWord! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 6/23/2004 13:49'! storePointer: fieldIndex ofObject: oop withValue: valuePointer "Note must check here for stores of young objects into old ones." (oop < youngStart) ifTrue: [ self possibleRootStoreInto: oop value: valuePointer. ]. ^ self longAt: oop + BaseHeaderSize + (fieldIndex << ShiftForWord) put: valuePointer! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'di 6/23/2004 13:49'! storePointerUnchecked: fieldIndex ofObject: oop withValue: valuePointer "Like storePointer:ofObject:withValue:, but the caller guarantees that the object being stored into is a young object or is already marked as a root." ^ self longAt: oop + BaseHeaderSize + (fieldIndex << ShiftForWord) put: valuePointer ! ! !ObjectMemory methodsFor: 'interpreter access' stamp: 'ikp 3/26/2005 14:29'! storeWord: fieldIndex ofObject: oop withValue: valueWord "This message is deprecated. Use storeLong32, storeLong64 or storePointer" self abort! ! !Interpreter methodsFor: 'message sending' stamp: 'di 6/15/2004 23:34'! activateNewMethod | newContext methodHeader initialIP tempCount nilOop where | methodHeader _ self headerOf: newMethod. newContext _ self allocateOrRecycleContext: (methodHeader bitAnd: LargeContextBit). initialIP _ ((LiteralStart + (self literalCountOfHeader: methodHeader)) * BytesPerWord) + 1. tempCount _ (methodHeader >> 19) bitAnd: 16r3F. "Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores." where _ newContext + BaseHeaderSize. self longAt: where + (SenderIndex << ShiftForWord) put: activeContext. self longAt: where + (InstructionPointerIndex << ShiftForWord) put: (self integerObjectOf: initialIP). self longAt: where + (StackPointerIndex << ShiftForWord) put: (self integerObjectOf: tempCount). self longAt: where + (MethodIndex << ShiftForWord) put: newMethod. "Copy the reciever and arguments..." 0 to: argumentCount do: [:i | self longAt: where + ((ReceiverIndex+i) << ShiftForWord) put: (self stackValue: argumentCount-i)]. "clear remaining temps to nil in case it has been recycled" nilOop _ nilObj. argumentCount+1+ReceiverIndex to: tempCount+ReceiverIndex do: [:i | self longAt: where + (i << ShiftForWord) put: nilOop]. self pop: argumentCount + 1. reclaimableContextCount _ reclaimableContextCount + 1. self newActiveContext: newContext.! ! !Interpreter methodsFor: 'message sending' stamp: 'di 6/14/2004 16:50'! createActualMessageTo: aClass "Bundle up the selector, arguments and lookupClass into a Message object. In the process it pops the arguments off the stack, and pushes the message object. This can then be presented as the argument of e.g. #doesNotUnderstand:. ikp 11/20/1999 03:59 -- added hook for external runtime compilers." "remap lookupClass in case GC happens during allocation" | argumentArray message lookupClass | self pushRemappableOop: aClass. argumentArray _ self instantiateClass: (self splObj: ClassArray) indexableSize: argumentCount. "remap argumentArray in case GC happens during allocation" self pushRemappableOop: argumentArray. message _ self instantiateClass: (self splObj: ClassMessage) indexableSize: 0. argumentArray _ self popRemappableOop. lookupClass _ self popRemappableOop. self beRootIfOld: argumentArray. compilerInitialized ifTrue: [self compilerCreateActualMessage: message storingArgs: argumentArray] ifFalse: [self transfer: argumentCount from: stackPointer - (argumentCount - 1 * BytesPerWord) to: argumentArray + BaseHeaderSize. self pop: argumentCount thenPush: message]. argumentCount _ 1. self storePointer: MessageSelectorIndex ofObject: message withValue: messageSelector. self storePointer: MessageArgumentsIndex ofObject: message withValue: argumentArray. (self lastPointerOf: message) >= (MessageLookupClassIndex * BytesPerWord + BaseHeaderSize) ifTrue: ["Only store lookupClass if message has 3 fields (old images don't)" self storePointer: MessageLookupClassIndex ofObject: message withValue: lookupClass]! ! !Interpreter methodsFor: 'message sending' stamp: 'di 6/14/2004 16:53'! internalActivateNewMethod | methodHeader newContext tempCount argCount2 needsLarge where | self inline: true. methodHeader _ self headerOf: newMethod. needsLarge _ methodHeader bitAnd: LargeContextBit. (needsLarge = 0 and: [freeContexts ~= NilContext]) ifTrue: [newContext _ freeContexts. freeContexts _ self fetchPointer: 0 ofObject: newContext] ifFalse: ["Slower call for large contexts or empty free list" self externalizeIPandSP. newContext _ self allocateOrRecycleContext: needsLarge. self internalizeIPandSP]. tempCount _ (methodHeader >> 19) bitAnd: 16r3F. "Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores." where _ newContext + BaseHeaderSize. self longAt: where + (SenderIndex << ShiftForWord) put: activeContext. self longAt: where + (InstructionPointerIndex << ShiftForWord) put: (self integerObjectOf: (((LiteralStart + (self literalCountOfHeader: methodHeader)) * BytesPerWord) + 1)). self longAt: where + (StackPointerIndex << ShiftForWord) put: (self integerObjectOf: tempCount). self longAt: where + (MethodIndex << ShiftForWord) put: newMethod. "Copy the reciever and arguments..." argCount2 _ argumentCount. 0 to: argCount2 do: [:i | self longAt: where + ((ReceiverIndex+i) << ShiftForWord) put: (self internalStackValue: argCount2-i)]. "clear remaining temps to nil in case it has been recycled" methodHeader _ nilObj. "methodHeader here used just as faster (register?) temp" argCount2+1+ReceiverIndex to: tempCount+ReceiverIndex do: [:i | self longAt: where + (i << ShiftForWord) put: methodHeader]. self internalPop: argCount2 + 1. reclaimableContextCount _ reclaimableContextCount + 1. self internalNewActiveContext: newContext. ! ! !Interpreter methodsFor: 'message sending' stamp: 'ikp 6/10/2004 14:10'! primitiveCalloutToFFI "Perform a function call to a foreign function. Only invoked from method containing explicit external call spec. Due to this we use the pluggable prim mechanism explicitly here (the first literal of any FFI spec'ed method is an ExternalFunction and not an array as used in the pluggable primitive mechanism)." | function moduleName functionName | self var: #function declareC: 'static void *function = 0'. self var: #moduleName declareC: 'static char *moduleName = "SqueakFFIPrims"'. self var: #functionName declareC: 'static char *functionName = "primitiveCallout"'. function = 0 ifTrue: [ function _ self ioLoadExternalFunction: (self oopForPointer: functionName) OfLength: 16 FromModule: (self oopForPointer: moduleName) OfLength: 14. function == 0 ifTrue: [^self primitiveFail]]. ^self cCode: '((sqInt (*)(void))function)()'. ! ! !Interpreter methodsFor: 'method lookup cache' stamp: 'ikp 3/26/2005 13:35'! addNewMethodToCache "Add the given entry to the method cache. The policy is as follows: Look for an empty entry anywhere in the reprobe chain. If found, install the new entry there. If not found, then install the new entry at the first probe position and delete the entries in the rest of the reprobe chain. This has two useful purposes: If there is active contention over the first slot, the second or third will likely be free for reentry after ejection. Also, flushing is good when reprobe chains are getting full." | probe hash | self inline: false. self compilerTranslateMethodHook. "newMethod x lkupClass -> newNativeMethod (may cause GC !!)" hash _ messageSelector bitXor: lkupClass. "drop low-order zeros from addresses" primitiveFunctionPointer _ self functionPointerFor: primitiveIndex inClass: lkupClass. 0 to: CacheProbeMax-1 do: [:p | probe _ (hash >> p) bitAnd: MethodCacheMask. (methodCache at: probe + MethodCacheSelector) = 0 ifTrue: ["Found an empty entry -- use it" methodCache at: probe + MethodCacheSelector put: messageSelector. methodCache at: probe + MethodCacheClass put: lkupClass. methodCache at: probe + MethodCacheMethod put: newMethod. methodCache at: probe + MethodCachePrim put: primitiveIndex. methodCache at: probe + MethodCacheNative put: newNativeMethod. methodCache at: probe + MethodCachePrimFunction put: (self cCoerce: primitiveFunctionPointer to: 'long'). ^ nil]]. "OK, we failed to find an entry -- install at the first slot..." probe _ hash bitAnd: MethodCacheMask. "first probe" methodCache at: probe + MethodCacheSelector put: messageSelector. methodCache at: probe + MethodCacheClass put: lkupClass. methodCache at: probe + MethodCacheMethod put: newMethod. methodCache at: probe + MethodCachePrim put: primitiveIndex. methodCache at: probe + MethodCacheNative put: newNativeMethod. methodCache at: probe + MethodCachePrimFunction put: (self cCoerce: primitiveFunctionPointer to: 'long'). "...and zap the following entries" 1 to: CacheProbeMax-1 do: [:p | probe _ (hash >> p) bitAnd: MethodCacheMask. methodCache at: probe + MethodCacheSelector put: 0]. ! ! !Interpreter methodsFor: 'method lookup cache' stamp: 'ikp 8/2/2004 17:54'! functionPointerFor: primIdx inClass: theClass "Find an actual function pointer for this primitiveIndex. This is an opportunity to specialise the prim for the relevant class (format for example). Default for now is simply the entry in the base primitiveTable." self returnTypeC: 'void *'. ^primitiveTable at: primIdx! ! !Interpreter methodsFor: 'method lookup cache' stamp: 'ikp 3/26/2005 13:36'! lookupInMethodCacheSel: selector class: class "This method implements a simple method lookup cache. If an entry for the given selector and class is found in the cache, set the values of 'newMethod' and 'primitiveIndex' and return true. Otherwise, return false." "About the re-probe scheme: The hash is the low bits of the XOR of two large addresses, minus their useless lowest two bits. If a probe doesn't get a hit, the hash is shifted right one bit to compute the next probe, introducing a new randomish bit. The cache is probed CacheProbeMax times before giving up." "WARNING: Since the hash computation is based on the object addresses of the class and selector, we must rehash or flush when compacting storage. We've chosen to flush, since that also saves the trouble of updating the addresses of the objects in the cache." | hash probe | self inline: true. hash _ selector bitXor: class. "shift drops two low-order zeros from addresses" probe _ hash bitAnd: MethodCacheMask. "first probe" (((methodCache at: probe + MethodCacheSelector) = selector) and: [(methodCache at: probe + MethodCacheClass) = class]) ifTrue: [newMethod _ methodCache at: probe + MethodCacheMethod. primitiveIndex _ methodCache at: probe + MethodCachePrim. newNativeMethod _ methodCache at: probe + MethodCacheNative. primitiveFunctionPointer _ self cCoerce: (methodCache at: probe + MethodCachePrimFunction) to: 'void *'. ^ true "found entry in cache; done"]. probe _ (hash >> 1) bitAnd: MethodCacheMask. "second probe" (((methodCache at: probe + MethodCacheSelector) = selector) and: [(methodCache at: probe + MethodCacheClass) = class]) ifTrue: [newMethod _ methodCache at: probe + MethodCacheMethod. primitiveIndex _ methodCache at: probe + MethodCachePrim. newNativeMethod _ methodCache at: probe + MethodCacheNative. primitiveFunctionPointer _ self cCoerce: (methodCache at: probe + MethodCachePrimFunction) to: 'void *'. ^ true "found entry in cache; done"]. probe _ (hash >> 2) bitAnd: MethodCacheMask. (((methodCache at: probe + MethodCacheSelector) = selector) and: [(methodCache at: probe + MethodCacheClass) = class]) ifTrue: [newMethod _ methodCache at: probe + MethodCacheMethod. primitiveIndex _ methodCache at: probe + MethodCachePrim. newNativeMethod _ methodCache at: probe + MethodCacheNative. primitiveFunctionPointer _ self cCoerce: (methodCache at: probe + MethodCachePrimFunction) to: 'void *'. ^ true "found entry in cache; done"]. ^ false ! ! !Interpreter methodsFor: 'method lookup cache' stamp: 'ikp 3/26/2005 14:24'! rewriteMethodCacheSel: selector class: class primIndex: localPrimIndex "Rewrite the cache entry with the given primitive index and matching function pointer" | primPtr | self var: #primPtr type: 'void *'. self inline: false. localPrimIndex = 0 ifTrue: [primPtr _ 0] ifFalse: [primPtr _ primitiveTable at: localPrimIndex]. self rewriteMethodCacheSel: selector class: class primIndex: localPrimIndex primFunction: primPtr! ! !Interpreter methodsFor: 'method lookup cache' stamp: 'ikp 3/26/2005 14:24'! rewriteMethodCacheSel: selector class: class primIndex: localPrimIndex primFunction: localPrimAddress "Rewrite an existing entry in the method cache with a new primitive index & function address. Used by primExternalCall to make direct jumps to found external prims" | probe hash | self inline: false. self var: #localPrimAddress type: 'void *'. hash := selector bitXor: class. 0 to: CacheProbeMax - 1 do: [:p | probe := hash >> p bitAnd: MethodCacheMask. ((methodCache at: probe + MethodCacheSelector) = selector and: [(methodCache at: probe + MethodCacheClass) = class]) ifTrue: [methodCache at: probe + MethodCachePrim put: localPrimIndex. methodCache at: probe + MethodCachePrimFunction put: (self cCoerce: localPrimAddress to: 'long'). ^ nil]]! ! !Interpreter methodsFor: 'plugin primitive support' stamp: 'ikp 8/2/2004 17:47'! callExternalPrimitive: functionID "Call the external plugin function identified. In the VM this is an address, see InterpreterSimulator for it's version. dispatch... is a macro in the VM C code." self var: #functionID type: 'void *'. self dispatchFunctionPointer: functionID! ! !Interpreter methodsFor: 'plugin primitive support' stamp: 'ikp 8/3/2004 18:16'! classNameOf: aClass Is: className "Check if aClass's name is className" | srcName name length | self var: #className declareC: 'char *className'. self var: #srcName declareC: 'char *srcName'. (self lengthOf: aClass) <= 6 ifTrue: [^ false]. "Not a class but might be behavior" name _ self fetchPointer: 6 ofObject: aClass. (self isBytes: name) ifFalse: [^ false]. length _ self stSizeOf: name. srcName _ self cCoerce: (self arrayValueOf: name) to: 'char *'. 0 to: length - 1 do: [:i | (srcName at: i) = (className at: i) ifFalse: [^ false]]. "Check if className really ends at this point" ^ (className at: length) = 0! ! !Interpreter methodsFor: 'plugin primitive support' stamp: 'di 7/4/2004 08:51'! flushExternalPrimitiveOf: methodPtr "methodPtr is a CompiledMethod containing an external primitive. Flush the function address and session ID of the CM" | lit | (self literalCountOf: methodPtr) > 0 ifFalse:[^nil]. "Something's broken" lit _ self literal: 0 ofMethod: methodPtr. ((self isArray: lit) and:[(self lengthOf: lit) = 4]) ifFalse:[^nil]. "Something's broken" self storePointer: 2 ofObject: lit withValue: ConstZero. self storePointer: 3 ofObject: lit withValue: ConstZero. ! ! !Interpreter methodsFor: 'debug support' stamp: 'di 6/14/2004 17:52'! balancedStack: delta afterPrimitive: primIdx withArgs: nArgs "Return true if the stack is still balanced after executing primitive primIndex with nArgs args. Delta is 'stackPointer - activeContext' which is a relative measure for the stack pointer (so we don't have to relocate it during the primitive)" (primIdx >= 81 and:[primIdx <= 88]) ifTrue:[^true]. "81-88 are control primitives after which the stack may look unbalanced" successFlag ifTrue:[ "Successful prim, stack must have exactly nArgs arguments popped off" ^(stackPointer - activeContext + (nArgs * BytesPerWord)) = delta ]. "Failed prim must leave stack intact" ^(stackPointer - activeContext) = delta ! ! !Interpreter methodsFor: 'debug support' stamp: 'ikp 3/26/2005 21:05'! okayOop: signedOop "Verify that the given oop is legitimate. Check address, header, and size but not class." | sz type fmt unusedBit oop | self var: #oop type: 'usqInt'. oop := self cCoerce: signedOop to: 'usqInt'. "address and size checks" (self isIntegerObject: oop) ifTrue: [ ^true ]. (oop < endOfMemory) ifFalse: [ self error: 'oop is not a valid address' ]. ((oop \\ BytesPerWord) = 0) ifFalse: [ self error: 'oop is not a word-aligned address' ]. sz _ self sizeBitsOf: oop. (oop + sz) < endOfMemory ifFalse: [ self error: 'oop size would make it extend beyond the end of memory' ]. "header type checks" type _ self headerType: oop. type = HeaderTypeFree ifTrue: [ self error: 'oop is a free chunk, not an object' ]. type = HeaderTypeShort ifTrue: [ (((self baseHeader: oop) >> 12) bitAnd: 16r1F) = 0 ifTrue: [ self error: 'cannot have zero compact class field in a short header' ]. ]. type = HeaderTypeClass ifTrue: [ ((oop >= BytesPerWord) and: [(self headerType: oop - BytesPerWord) = type]) ifFalse: [ self error: 'class header word has wrong type' ]. ]. type = HeaderTypeSizeAndClass ifTrue: [ ((oop >= (BytesPerWord*2)) and: [(self headerType: oop - (BytesPerWord*2)) = type and: [(self headerType: oop - BytesPerWord) = type]]) ifFalse: [ self error: 'class header word has wrong type' ]. ]. "format check" fmt _ self formatOf: oop. ((fmt = 5) | (fmt = 7)) ifTrue: [ self error: 'oop has an unknown format type' ]. "mark and root bit checks" unusedBit _ 16r20000000. BytesPerWord = 8 ifTrue: [unusedBit _ unusedBit << 16. unusedBit _ unusedBit << 16]. ((self longAt: oop) bitAnd: unusedBit) = 0 ifFalse: [ self error: 'unused header bit 30 is set; should be zero' ]. "xxx ((self longAt: oop) bitAnd: MarkBit) = 0 ifFalse: [ self error: 'mark bit should not be set except during GC' ]. xxx" (((self longAt: oop) bitAnd: RootBit) = 1 and: [oop >= youngStart]) ifTrue: [ self error: 'root bit is set in a young object' ]. ^true ! ! !Interpreter methodsFor: 'debug support' stamp: 'ikp 3/26/2005 21:06'! oopHasOkayClass: signedOop "Attempt to verify that the given oop has a reasonable behavior. The class must be a valid, non-integer oop and must not be nilObj. It must be a pointers object with three or more fields. Finally, the instance specification field of the behavior must match that of the instance." | oop oopClass formatMask behaviorFormatBits oopFormatBits | self var: #oop type: 'usqInt'. self var: #oopClass type: 'usqInt'. oop := self cCoerce: signedOop to: 'usqInt'. self okayOop: oop. oopClass := self cCoerce: (self fetchClassOf: oop) to: 'usqInt'. (self isIntegerObject: oopClass) ifTrue: [ self error: 'a SmallInteger is not a valid class or behavior' ]. self okayOop: oopClass. ((self isPointers: oopClass) and: [(self lengthOf: oopClass) >= 3]) ifFalse: [ self error: 'a class (behavior) must be a pointers object of size >= 3' ]. (self isBytes: oop) ifTrue: [ formatMask _ 16rC00 ] "ignore extra bytes size bits" ifFalse: [ formatMask _ 16rF00 ]. behaviorFormatBits _ (self formatOfClass: oopClass) bitAnd: formatMask. oopFormatBits _ (self baseHeader: oop) bitAnd: formatMask. behaviorFormatBits = oopFormatBits ifFalse: [ self error: 'object and its class (behavior) formats differ' ]. ^true! ! !Interpreter methodsFor: 'utilities' stamp: 'di 6/23/2004 12:24'! arrayValueOf: arrayOop "Return the address of first indexable field of resulting array object, or fail if the instance variable does not contain an indexable bytes or words object." "Note: May be called by translated primitive code." self returnTypeC: 'void *'. ((self isIntegerObject: arrayOop) not and: [self isWordsOrBytes: arrayOop]) ifTrue: [^ self cCode: '(void *)pointerForOop(arrayOop + BaseHeaderSize)']. self primitiveFail. ! ! !Interpreter methodsFor: 'utilities' stamp: 'ikp 6/10/2004 11:08'! externalizeIPandSP "Copy the local instruction and stack pointer to global variables for use in primitives and other functions outside the interpret loop." instructionPointer _ self oopForPointer: localIP. stackPointer _ self oopForPointer: localSP. theHomeContext _ localHomeContext. ! ! !Interpreter methodsFor: 'utilities' stamp: 'ikp 8/4/2004 11:42'! fetchIntegerOrTruncFloat: fieldIndex ofObject: objectPointer "Return the integer value of the given field of the given object. If the field contains a Float, truncate it and return its integral part. Fail if the given field does not contain a small integer or Float, or if the truncated Float is out of the range of small integers." "Note: May be called by translated primitive code." | intOrFloat floatVal frac trunc | self inline: false. self var: #floatVal declareC: 'double floatVal'. self var: #frac declareC: 'double frac'. self var: #trunc declareC: 'double trunc'. intOrFloat _ self fetchPointer: fieldIndex ofObject: objectPointer. (self isIntegerObject: intOrFloat) ifTrue: [^ self integerValueOf: intOrFloat]. self assertClassOf: intOrFloat is: (self splObj: ClassFloat). successFlag ifTrue: [ self cCode: '' inSmalltalk: [floatVal _ Float new: 2]. self fetchFloatAt: intOrFloat + BaseHeaderSize into: floatVal. self cCode: 'frac = modf(floatVal, &trunc)'. "the following range check is for C ints, with range -2^31..2^31-1" self flag: #Dan. "The ranges are INCORRECT if SmallIntegers are wider than 31 bits." self cCode: 'success((-2147483648.0 <= trunc) && (trunc <= 2147483647.0))'.]. successFlag ifTrue: [^ self cCode: '((sqInt) trunc)' inSmalltalk: [floatVal truncated]] ifFalse: [^ 0]. ! ! !Interpreter methodsFor: 'utilities' stamp: 'di 6/14/2004 17:48'! floatValueOf: oop "Fetch the instance variable at the given index of the given object. Return the C double precision floating point value of that instance variable, or fail if it is not a Float." "Note: May be called by translated primitive code." | result | self flag: #Dan. "None of the float stuff has been converted for 64 bits" self returnTypeC: 'double'. self var: #result declareC: 'double result'. self assertClassOf: oop is: (self splObj: ClassFloat). successFlag ifTrue: [self cCode: '' inSmalltalk: [result _ Float new: 2]. self fetchFloatAt: oop + BaseHeaderSize into: result] ifFalse: [result _ 0.0]. ^ result! ! !Interpreter methodsFor: 'utilities' stamp: 'ikp 6/10/2004 11:08'! internalizeIPandSP "Copy the local instruction and stack pointer to local variables for rapid access within the interpret loop." localIP _ self pointerForOop: instructionPointer. localSP _ self pointerForOop: stackPointer. localHomeContext _ theHomeContext. ! ! !Interpreter methodsFor: 'utilities' stamp: 'di 6/14/2004 17:49'! makePointwithxValue: xValue yValue: yValue | pointResult | pointResult _ self instantiateSmallClass: (self splObj: ClassPoint) sizeInBytes: 3*BytesPerWord fill: nilObj. self storePointer: XIndex ofObject: pointResult withValue: (self integerObjectOf: xValue). self storePointer: YIndex ofObject: pointResult withValue: (self integerObjectOf: yValue). ^ pointResult! ! !Interpreter methodsFor: 'utilities' stamp: 'ikp 6/10/2004 14:23'! sizeOfSTArrayFromCPrimitive: cPtr "Return the number of indexable fields of the given object. This method is to be called from an automatically generated C primitive. The argument is assumed to be a pointer to the first indexable field of a words or bytes object; the object header starts 4 bytes before that." "Note: Only called by translated primitive code." | oop | self var: #cPtr declareC: 'void *cPtr'. oop _ (self oopForPointer: cPtr) - BaseHeaderSize. (self isWordsOrBytes: oop) ifFalse: [ self primitiveFail. ^0]. ^self lengthOf: oop ! ! !Interpreter methodsFor: 'utilities' stamp: 'di 7/4/2004 08:59'! storeInteger: fieldIndex ofObject: objectPointer withValue: integerValue "Note: May be called by translated primitive code." (self isIntegerValue: integerValue) ifTrue: [self storePointer: fieldIndex ofObject: objectPointer withValue: (self integerObjectOf: integerValue)] ifFalse: [self primitiveFail]! ! !Interpreter methodsFor: 'utilities' stamp: 'di 8/3/2004 14:33'! transfer: count from: src to: dst | in out lastIn | self flag: #Dan. "Need to check all senders before converting this for 64 bits" self inline: true. in _ src - BytesPerWord. lastIn _ in + (count * BytesPerWord). out _ dst - BytesPerWord. [in < lastIn] whileTrue: [self longAt: (out _ out + BytesPerWord) put: (self longAt: (in _ in + BytesPerWord))]! ! !Interpreter methodsFor: 'utilities' stamp: 'di 6/15/2004 22:55'! transfer: count fromIndex: firstFrom ofObject: fromOop toIndex: firstTo ofObject: toOop "Transfer the specified fullword fields, as from calling context to called context" "Assume: beRootIfOld: will be called on toOop." | fromIndex toIndex lastFrom | self flag: #Dan. "Need to check all senders before converting this for 64 bits" self inline: true. fromIndex _ fromOop + (firstFrom * BytesPerWord). toIndex _ toOop + (firstTo * BytesPerWord). lastFrom _ fromIndex + (count * BytesPerWord). [fromIndex < lastFrom] whileTrue: [fromIndex _ fromIndex + BytesPerWord. toIndex _ toIndex + BytesPerWord. self longAt: toIndex put: (self longAt: fromIndex)]! ! !Interpreter methodsFor: 'compiled methods' stamp: 'di 6/14/2004 17:02'! primitiveNewMethod | header bytecodeCount class size theMethod literalCount | header _ self popStack. bytecodeCount _ self popInteger. self success: (self isIntegerObject: header). successFlag ifFalse: [self unPop: 2]. class _ self popStack. size _ (self literalCountOfHeader: header) + 1 * BytesPerWord + bytecodeCount. theMethod _ self instantiateClass: class indexableSize: size. self storePointer: HeaderIndex ofObject: theMethod withValue: header. literalCount _ self literalCountOfHeader: header. 1 to: literalCount do: [:i | self storePointer: i ofObject: theMethod withValue: nilObj]. self push: theMethod! ! !Interpreter methodsFor: 'compiled methods' stamp: 'di 7/19/2004 14:59'! tempCountOf: methodPointer ^ ((self headerOf: methodPointer) >> 19) bitAnd: 16r3F! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 14:05'! fetchContextRegisters: activeCntx "Note: internalFetchContextRegisters: should track changes to this method." | tmp | self inline: true. tmp _ self fetchPointer: MethodIndex ofObject: activeCntx. (self isIntegerObject: tmp) ifTrue: ["if the MethodIndex field is an integer, activeCntx is a block context" tmp _ self fetchPointer: HomeIndex ofObject: activeCntx. tmp < youngStart ifTrue: [self beRootIfOld: tmp]] ifFalse: ["otherwise, it is a method context and is its own home context " tmp _ activeCntx]. theHomeContext _ tmp. receiver _ self fetchPointer: ReceiverIndex ofObject: tmp. method _ self fetchPointer: MethodIndex ofObject: tmp. "the instruction pointer is a pointer variable equal to method oop + ip + BaseHeaderSize -1 for 0-based addressing of fetchByte -1 because it gets incremented BEFORE fetching currentByte " tmp _ self quickFetchInteger: InstructionPointerIndex ofObject: activeCntx. instructionPointer _ method + tmp + BaseHeaderSize - 2. "the stack pointer is a pointer variable also..." tmp _ self quickFetchInteger: StackPointerIndex ofObject: activeCntx. stackPointer _ activeCntx + BaseHeaderSize + (TempFrameStart + tmp - 1 * BytesPerWord)! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/23/2004 12:33'! internalFetchContextRegisters: activeCntx "Inlined into return bytecodes. The only difference between this method and fetchContextRegisters: is that this method sets the local IP and SP." | tmp | self inline: true. tmp _ self fetchPointer: MethodIndex ofObject: activeCntx. (self isIntegerObject: tmp) ifTrue: [ "if the MethodIndex field is an integer, activeCntx is a block context" tmp _ self fetchPointer: HomeIndex ofObject: activeCntx. (tmp < youngStart) ifTrue: [ self beRootIfOld: tmp ]. ] ifFalse: [ "otherwise, it is a method context and is its own home context" tmp _ activeCntx. ]. localHomeContext _ tmp. receiver _ self fetchPointer: ReceiverIndex ofObject: tmp. method _ self fetchPointer: MethodIndex ofObject: tmp. "the instruction pointer is a pointer variable equal to method oop + ip + BaseHeaderSize -1 for 0-based addressing of fetchByte -1 because it gets incremented BEFORE fetching currentByte" tmp _ self quickFetchInteger: InstructionPointerIndex ofObject: activeCntx. localIP _ self pointerForOop: method + tmp + BaseHeaderSize - 2. "the stack pointer is a pointer variable also..." tmp _ self quickFetchInteger: StackPointerIndex ofObject: activeCntx. localSP _ self pointerForOop: activeCntx + BaseHeaderSize + ((TempFrameStart + tmp - 1) * BytesPerWord)! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:32'! internalPop: nItems localSP _ localSP - (nItems * BytesPerWord).! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/23/2004 13:40'! internalPop: nItems thenPush: oop self longAtPointer: (localSP _ localSP - ((nItems - 1) * BytesPerWord)) put: oop. ! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/23/2004 13:40'! internalPush: object self longAtPointer: (localSP _ localSP + BytesPerWord) put: object.! ! !Interpreter methodsFor: 'contexts' stamp: 'ikp 6/10/2004 11:16'! internalStackTop ^ self longAtPointer: localSP! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/23/2004 13:40'! internalStackValue: offset ^ self longAtPointer: localSP - (offset * BytesPerWord)! ! !Interpreter methodsFor: 'contexts' stamp: 'di 7/4/2004 08:56'! internalStoreContextRegisters: activeCntx "The only difference between this method and fetchContextRegisters: is that this method stores from the local IP and SP." "InstructionPointer is a pointer variable equal to method oop + ip + BaseHeaderSize -1 for 0-based addressing of fetchByte -1 because it gets incremented BEFORE fetching currentByte" self inline: true. self storePointer: InstructionPointerIndex ofObject: activeCntx withValue: (self integerObjectOf: ((self oopForPointer: localIP) + 2 - (method + BaseHeaderSize))). self storePointer: StackPointerIndex ofObject: activeCntx withValue: (self integerObjectOf: ((((self oopForPointer: localSP) - (activeCntx + BaseHeaderSize)) >> ShiftForWord) - TempFrameStart + 1)). ! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:33'! pop: nItems "Note: May be called by translated primitive code." stackPointer _ stackPointer - (nItems*BytesPerWord).! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:33'! pop: nItems thenPush: oop | sp | self longAt: (sp _ stackPointer - ((nItems - 1) * BytesPerWord)) put: oop. stackPointer _ sp. ! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:34'! popStack | top | top _ self longAt: stackPointer. stackPointer _ stackPointer - BytesPerWord. ^ top! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:34'! push: object | sp | self longAt: (sp _ stackPointer + BytesPerWord) put: object. stackPointer _ sp.! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:34'! stackFloatValue: offset "Note: May be called by translated primitive code." | result floatPointer | self returnTypeC: 'double'. self var: #result declareC: 'double result'. floatPointer _ self longAt: stackPointer - (offset*BytesPerWord). (self fetchClassOf: floatPointer) = (self splObj: ClassFloat) ifFalse:[self primitiveFail. ^0.0]. self cCode: '' inSmalltalk: [result _ Float new: 2]. self fetchFloatAt: floatPointer + BaseHeaderSize into: result. ^ result! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:34'! stackIntegerValue: offset | integerPointer | integerPointer _ self longAt: stackPointer - (offset*BytesPerWord). ^self checkedIntegerValueOf: integerPointer! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:34'! stackObjectValue: offset "Ensures that the given object is a real object, not a SmallInteger." | oop | oop _ self longAt: stackPointer - (offset * BytesPerWord). (self isIntegerObject: oop) ifTrue: [self primitiveFail. ^ nil]. ^ oop ! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 14:14'! stackPointerIndex "Return the 0-based index rel to the current context. (This is what stackPointer used to be before conversion to pointer" ^ (stackPointer - activeContext - BaseHeaderSize) >> ShiftForWord! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:35'! stackValue: offset ^ self longAt: stackPointer - (offset*BytesPerWord)! ! !Interpreter methodsFor: 'contexts' stamp: 'di 7/4/2004 08:58'! storeContextRegisters: activeCntx "Note: internalStoreContextRegisters: should track changes to this method." "InstructionPointer is a pointer variable equal to method oop + ip + BaseHeaderSize -1 for 0-based addressing of fetchByte -1 because it gets incremented BEFORE fetching currentByte" self inline: true. self storePointer: InstructionPointerIndex ofObject: activeCntx withValue: (self integerObjectOf: (instructionPointer - method - (BaseHeaderSize - 2))). self storePointer: StackPointerIndex ofObject: activeCntx withValue: (self integerObjectOf: (self stackPointerIndex - TempFrameStart + 1)). ! ! !Interpreter methodsFor: 'contexts' stamp: 'di 7/4/2004 08:58'! storeInstructionPointerValue: value inContext: contextPointer "Assume: value is an integerValue" self storePointer: InstructionPointerIndex ofObject: contextPointer withValue: (self integerObjectOf: value).! ! !Interpreter methodsFor: 'contexts' stamp: 'di 7/4/2004 08:59'! storeStackPointerValue: value inContext: contextPointer "Assume: value is an integerValue" self storePointer: StackPointerIndex ofObject: contextPointer withValue: (self integerObjectOf: value).! ! !Interpreter methodsFor: 'contexts' stamp: 'di 6/14/2004 16:35'! unPop: nItems stackPointer _ stackPointer + (nItems*BytesPerWord)! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'ikp 8/4/2004 18:26'! commonVariable: rcvr at: index cacheIndex: atIx "This code assumes the reciever has been identified at location atIx in the atCache." | stSize fmt fixedFields result | stSize _ atCache at: atIx+AtCacheSize. ((self cCoerce: index to: 'usqInt ') >= 1 and: [(self cCoerce: index to: 'usqInt ') <= (self cCoerce: stSize to: 'usqInt ')]) ifTrue: [fmt _ atCache at: atIx+AtCacheFmt. fmt <= 4 ifTrue: [fixedFields _ atCache at: atIx+AtCacheFixedFields. ^ self fetchPointer: index + fixedFields - 1 ofObject: rcvr]. fmt < 8 ifTrue: "Bitmap" [result _ self fetchLong32: index - 1 ofObject: rcvr. result _ self positive32BitIntegerFor: result. ^ result]. fmt >= 16 "Note fmt >= 16 is an artificial flag for strings" ifTrue: "String" [^ self characterForAscii: (self fetchByte: index - 1 ofObject: rcvr)] ifFalse: "ByteArray" [^ self integerObjectOf: (self fetchByte: index - 1 ofObject: rcvr)]]. self primitiveFail! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'ikp 8/4/2004 18:27'! commonVariable: rcvr at: index put: value cacheIndex: atIx "This code assumes the reciever has been identified at location atIx in the atCache." | stSize fmt fixedFields valToPut | self inline: true. stSize _ atCache at: atIx+AtCacheSize. ((self cCoerce: index to: 'usqInt ') >= 1 and: [(self cCoerce: index to: 'usqInt ') <= (self cCoerce: stSize to: 'usqInt ')]) ifTrue: [fmt _ atCache at: atIx+AtCacheFmt. fmt <= 4 ifTrue: [fixedFields _ atCache at: atIx+AtCacheFixedFields. ^ self storePointer: index + fixedFields - 1 ofObject: rcvr withValue: value]. fmt < 8 ifTrue: "Bitmap" [valToPut _ self positive32BitValueOf: value. successFlag ifTrue: [self storeLong32: index - 1 ofObject: rcvr withValue: valToPut]. ^ nil]. fmt >= 16 "Note fmt >= 16 is an artificial flag for strings" ifTrue: [valToPut _ self asciiOfCharacter: value. successFlag ifFalse: [^ nil]] ifFalse: [valToPut _ value]. (self isIntegerObject: valToPut) ifTrue: [valToPut _ self integerValueOf: valToPut. ((valToPut >= 0) and: [valToPut <= 255]) ifFalse: [^ self primitiveFail]. ^ self storeByte: index - 1 ofObject: rcvr withValue: valToPut]]. self primitiveFail! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'ikp 8/4/2004 18:27'! commonVariableInternal: rcvr at: index cacheIndex: atIx "This code assumes the reciever has been identified at location atIx in the atCache." | stSize fmt fixedFields result | self inline: true. stSize _ atCache at: atIx+AtCacheSize. ((self cCoerce: index to: 'usqInt ') >= 1 and: [(self cCoerce: index to: 'usqInt ') <= (self cCoerce: stSize to: 'usqInt ')]) ifTrue: [fmt _ atCache at: atIx+AtCacheFmt. fmt <= 4 ifTrue: [fixedFields _ atCache at: atIx+AtCacheFixedFields. ^ self fetchPointer: index + fixedFields - 1 ofObject: rcvr]. fmt < 8 ifTrue: "Bitmap" [result _ self fetchLong32: index - 1 ofObject: rcvr. self externalizeIPandSP. result _ self positive32BitIntegerFor: result. self internalizeIPandSP. ^ result]. fmt >= 16 "Note fmt >= 16 is an artificial flag for strings" ifTrue: "String" [^ self characterForAscii: (self fetchByte: index - 1 ofObject: rcvr)] ifFalse: "ByteArray" [^ self integerObjectOf: (self fetchByte: index - 1 ofObject: rcvr)]]. self primitiveFail! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'di 7/4/2004 11:28'! lengthOf: oop baseHeader: hdr format: fmt "Return the number of indexable bytes or words in the given object. Assume the given oop is not an integer. For a CompiledMethod, the size of the method header (in bytes) should be subtracted from the result of this method." | sz | self inline: true. (hdr bitAnd: TypeMask) = HeaderTypeSizeAndClass ifTrue: [ sz _ (self sizeHeader: oop) bitAnd: LongSizeMask ] ifFalse: [ sz _ (hdr bitAnd: SizeMask)]. sz _ sz - (hdr bitAnd: Size4Bit). fmt <= 4 ifTrue: [ ^ (sz - BaseHeaderSize) >> ShiftForWord "words"]. fmt < 8 ifTrue: [ ^ (sz - BaseHeaderSize) >> 2 "32-bit longs"] ifFalse: [ ^ (sz - BaseHeaderSize) - (fmt bitAnd: 3) "bytes"]! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'ikp 8/4/2004 18:28'! stObject: array at: index "Return what ST would return for at: index." | hdr fmt totalLength fixedFields stSize | self inline: false. hdr _ self baseHeader: array. fmt _ (hdr >> 8) bitAnd: 16rF. totalLength _ self lengthOf: array baseHeader: hdr format: fmt. fixedFields _ self fixedFieldsOf: array format: fmt length: totalLength. (fmt = 3 and: [self isContextHeader: hdr]) ifTrue: [stSize _ self fetchStackPointerOf: array] ifFalse: [stSize _ totalLength - fixedFields]. ((self cCoerce: index to: 'usqInt ') >= 1 and: [(self cCoerce: index to: 'usqInt ') <= (self cCoerce: stSize to: 'usqInt ')]) ifTrue: [^ self subscript: array with: (index + fixedFields) format: fmt] ifFalse: [successFlag _ false. ^ 0].! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'ikp 8/4/2004 18:28'! stObject: array at: index put: value "Do what ST would return for at: index put: value." | hdr fmt totalLength fixedFields stSize | self inline: false. hdr _ self baseHeader: array. fmt _ (hdr >> 8) bitAnd: 16rF. totalLength _ self lengthOf: array baseHeader: hdr format: fmt. fixedFields _ self fixedFieldsOf: array format: fmt length: totalLength. (fmt = 3 and: [self isContextHeader: hdr]) ifTrue: [stSize _ self fetchStackPointerOf: array] ifFalse: [stSize _ totalLength - fixedFields]. ((self cCoerce: index to: 'usqInt ') >= 1 and: [(self cCoerce: index to: 'usqInt ') <= (self cCoerce: stSize to: 'usqInt ')]) ifTrue: [self subscript: array with: (index + fixedFields) storing: value format: fmt] ifFalse: [successFlag _ false]! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'di 7/4/2004 08:43'! subscript: array with: index format: fmt "Note: This method assumes that the index is within bounds!!" self inline: true. fmt <= 4 ifTrue: [ "pointer type objects" ^ self fetchPointer: index - 1 ofObject: array]. fmt < 8 ifTrue: [ "long-word type objects" ^ self positive32BitIntegerFor: (self fetchLong32: index - 1 ofObject: array) ] ifFalse: [ "byte-type objects" ^ self integerObjectOf: (self fetchByte: index - 1 ofObject: array) ].! ! !Interpreter methodsFor: 'array and stream primitive support' stamp: 'di 7/4/2004 09:00'! subscript: array with: index storing: oopToStore format: fmt "Note: This method assumes that the index is within bounds!!" | valueToStore | self inline: true. fmt <= 4 ifTrue: ["pointer type objects" self storePointer: index - 1 ofObject: array withValue: oopToStore] ifFalse: [fmt < 8 ifTrue: ["long-word type objects" valueToStore _ self positive32BitValueOf: oopToStore. successFlag ifTrue: [self storeLong32: index - 1 ofObject: array withValue: valueToStore]] ifFalse: ["byte-type objects" (self isIntegerObject: oopToStore) ifFalse: [successFlag _ false]. valueToStore _ self integerValueOf: oopToStore. (valueToStore >= 0 and: [valueToStore <= 255]) ifFalse: [successFlag _ false]. successFlag ifTrue: [self storeByte: index - 1 ofObject: array withValue: valueToStore]]]! ! !Interpreter methodsFor: 'object format' stamp: 'di 6/14/2004 16:37'! byteSizeOf: oop | slots | self flag: #Dan. (self isIntegerObject: oop) ifTrue:[^0]. slots _ self slotSizeOf: oop. (self isBytesNonInt: oop) ifTrue:[^slots] ifFalse:[^slots * 4]! ! !Interpreter methodsFor: 'object format' stamp: 'di 7/4/2004 13:33'! floatObjectOf: aFloat | newFloatObj | self flag: #Dan. self var: #aFloat declareC: 'double aFloat'. newFloatObj _ self instantiateSmallClass: (self splObj: ClassFloat) sizeInBytes: 8+BaseHeaderSize fill: 0. self storeFloatAt: newFloatObj + BaseHeaderSize from: aFloat. ^ newFloatObj. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/4/2004 17:28'! byteSwapByteObjectsFrom: startOop to: stopAddr "Byte-swap the words of all bytes objects in a range of the image, including Strings, ByteArrays, and CompiledMethods. This returns these objects to their original byte ordering after blindly byte-swapping the entire image. For compiled methods, byte-swap only their bytecodes part." | oop fmt wordAddr methodHeader | oop _ startOop. [oop < stopAddr] whileTrue: [(self isFreeObject: oop) ifFalse: [fmt _ self formatOf: oop. fmt >= 8 ifTrue: ["oop contains bytes" wordAddr _ oop + BaseHeaderSize. fmt >= 12 ifTrue: ["compiled method; start after methodHeader and literals" methodHeader _ self longAt: oop + BaseHeaderSize. wordAddr _ wordAddr + BytesPerWord + ((methodHeader >> 10 bitAnd: 255) * BytesPerWord)]. self reverseBytesFrom: wordAddr to: oop + (self sizeBitsOf: oop)]. (fmt = 6 and: [BytesPerWord = 8]) ifTrue: ["Object contains 32-bit half-words packed into 64-bit machine words." wordAddr _ oop + BaseHeaderSize. self reverseWordsFrom: wordAddr to: oop + (self sizeBitsOf: oop)]]. oop _ self objectAfter: oop]! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 9/22/2004 12:01'! byteSwapped: w "Answer the given integer with its bytes in the reverse order." BytesPerWord = 4 ifTrue: [^ ((w bitShift: Byte3ShiftNegated) bitAnd: Byte0Mask) + ((w bitShift: Byte1ShiftNegated) bitAnd: Byte1Mask) + ((w bitShift: Byte1Shift ) bitAnd: Byte2Mask) + ((w bitShift: Byte3Shift ) bitAnd: Byte3Mask)] ifFalse: [^ ((w bitShift: Byte7ShiftNegated) bitAnd: Byte0Mask) + ((w bitShift: Byte5ShiftNegated) bitAnd: Byte1Mask) + ((w bitShift: Byte3ShiftNegated) bitAnd: Byte2Mask) + ((w bitShift: Byte1ShiftNegated) bitAnd: Byte3Mask) + ((w bitShift: Byte1Shift ) bitAnd: Byte4Mask) + ((w bitShift: Byte3Shift ) bitAnd: Byte5Mask) + ((w bitShift: Byte5Shift ) bitAnd: Byte6Mask) + ((w bitShift: Byte7Shift ) bitAnd: Byte7Mask)]! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/3/2004 19:49'! checkImageVersionFrom: f startingAt: imageOffset "Read and verify the image file version number and return true if the the given image file needs to be byte-swapped. As a side effect, position the file stream just after the version number of the image header. This code prints a warning and does a hard-exit if it cannot find a valid version number." "This code is based on C code by Ian Piumarta." | version firstVersion | self var: #f declareC: 'sqImageFile f'. self var: #imageOffset declareC: 'squeakFileOffsetType imageOffset'. "check the version number" self sqImageFile: f Seek: imageOffset. version _ firstVersion _ self getLongFromFile: f swap: false. (self readableFormat: version) ifTrue: [^ false]. "try with bytes reversed" self sqImageFile: f Seek: imageOffset. version _ self getLongFromFile: f swap: true. (self readableFormat: version) ifTrue: [^ true]. "Note: The following is only meaningful if not reading an embedded image" imageOffset = 0 ifTrue:[ "try skipping the first 512 bytes (prepended by certain Mac file transfer utilities)" self sqImageFile: f Seek: 512. version _ self getLongFromFile: f swap: false. (self readableFormat: version) ifTrue: [^ false]. "try skipping the first 512 bytes with bytes reversed" self sqImageFile: f Seek: 512. version _ self getLongFromFile: f swap: true. (self readableFormat: version) ifTrue: [^ true]]. "hard failure; abort" self print: 'This interpreter (vers. '. self printNum: self imageFormatVersion. self print: ') cannot read image file (vers. '. self printNum: firstVersion. self print: ').'. self cr. self print: 'Press CR to quit...'. self getchar. self ioExit. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/4/2004 11:38'! getLongFromFile: aFile swap: swapFlag "Answer the next word read from aFile, byte-swapped according to the swapFlag." | w | self var: #aFile declareC: 'sqImageFile aFile'. w _ 0. self cCode: 'sqImageFileRead(&w, sizeof(w), 1, aFile)'. swapFlag ifTrue: [^ self byteSwapped: w] ifFalse: [^ w]. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 9/2/2004 15:38'! imageFormatVersion "Return a magic constant that changes when the image format changes. Since the image reading code uses this to detect byte ordering, one must avoid version numbers that are invariant under byte reversal." BytesPerWord == 4 ifTrue: [^6502] ifFalse: [^68000]! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/4/2004 11:37'! putLong: aWord toFile: aFile "Append aWord to aFile in this platforms 'natural' byte order. (Bytes will be swapped, if necessary, when the image is read on a different platform.) Set successFlag to false if the write fails." | objectsWritten | self var: #aFile declareC: 'sqImageFile aFile'. objectsWritten _ self cCode: 'sqImageFileWrite(&aWord, sizeof(aWord), 1, aFile)'. self success: objectsWritten = 1. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 3/26/2005 14:05'! readImageFromFile: f HeapSize: desiredHeapSize StartingAt: imageOffset "Read an image from the given file stream, allocating the given amount of memory to its object heap. Fail if the image has an unknown format or requires more than the given amount of memory." "Details: This method detects when the image was stored on a machine with the opposite byte ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header information to start 512 bytes into the file, since some file transfer programs for the Macintosh apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix area could also be used to store an exec command on Unix systems, allowing one to launch Smalltalk by invoking the image name as a command." "This code is based on C code by Ian Piumarta and Smalltalk code by Tim Rowledge. Many thanks to both of you!!!!" | swapBytes headerStart headerSize dataSize oldBaseAddr minimumMemory memStart bytesRead bytesToShift heapSize | self var: #f declareC: 'sqImageFile f'. self var: #headerStart declareC: 'squeakFileOffsetType headerStart'. self var: #dataSize declareC: 'size_t dataSize'. self var: #imageOffset declareC: 'squeakFileOffsetType imageOffset'. swapBytes _ self checkImageVersionFrom: f startingAt: imageOffset. headerStart _ (self sqImageFilePosition: f) - BytesPerWord. "record header start position" headerSize _ self getLongFromFile: f swap: swapBytes. dataSize _ self getLongFromFile: f swap: swapBytes. oldBaseAddr _ self getLongFromFile: f swap: swapBytes. specialObjectsOop _ self getLongFromFile: f swap: swapBytes. lastHash _ self getLongFromFile: f swap: swapBytes. savedWindowSize _ self getLongFromFile: f swap: swapBytes. fullScreenFlag _ self getLongFromFile: f swap: swapBytes. extraVMMemory _ self getLongFromFile: f swap: swapBytes. lastHash = 0 ifTrue: [ "lastHash wasn't stored (e.g. by the cloner); use 999 as the seed" lastHash _ 999]. "decrease Squeak object heap to leave extra memory for the VM" heapSize _ self cCode: 'reserveExtraCHeapBytes(desiredHeapSize, extraVMMemory)'. "compare memory requirements with availability". minimumMemory _ dataSize + 100000. "need at least 100K of breathing room" heapSize < minimumMemory ifTrue: [ self insufficientMemorySpecifiedError]. "allocate a contiguous block of memory for the Squeak heap" memory _ self cCode: 'sqAllocateMemory(minimumMemory, heapSize)'. memory = nil ifTrue: [self insufficientMemoryAvailableError]. memStart _ self startOfMemory. memoryLimit _ (memStart + heapSize) - 24. "decrease memoryLimit a tad for safety" endOfMemory _ memStart + dataSize. "position file after the header" self sqImageFile: f Seek: headerStart + headerSize. "read in the image in bulk, then swap the bytes if necessary" bytesRead _ self cCode: 'sqImageFileRead(pointerForOop(memory), sizeof(unsigned char), dataSize, f)'. bytesRead ~= dataSize ifTrue: [self unableToReadImageError]. headerTypeBytes at: 0 put: BytesPerWord * 2. "3-word header (type 0)" headerTypeBytes at: 1 put: BytesPerWord. "2-word header (type 1)" headerTypeBytes at: 2 put: 0. "free chunk (type 2)" headerTypeBytes at: 3 put: 0. "1-word header (type 3)" swapBytes ifTrue: [self reverseBytesInImage]. "compute difference between old and new memory base addresses" bytesToShift _ memStart - oldBaseAddr. self initializeInterpreter: bytesToShift. "adjusts all oops to new location" ^ dataSize ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'di 8/3/2004 14:26'! reverseBytesFrom: startAddr to: stopAddr "Byte-swap the given range of memory (not inclusive of stopAddr!!)." | addr | self flag: #Dan. addr _ startAddr. [addr < stopAddr] whileTrue: [self longAt: addr put: (self byteSwapped: (self longAt: addr)). addr _ addr + BytesPerWord].! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/4/2004 17:24'! reverseWordsFrom: startAddr to: stopAddr "Word-swap the given range of memory, excluding stopAddr." | addr | addr _ startAddr. [addr < stopAddr] whileTrue: [self longAt: addr put: (self wordSwapped: (self longAt: addr)). addr _ addr + BytesPerWord].! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 8/3/2004 18:24'! snapshot: embedded "update state of active context" | activeProc dataSize rcvr setMacType | self var: #setMacType type: 'void *'. compilerInitialized ifTrue: [self compilerPreSnapshot] ifFalse: [self storeContextRegisters: activeContext]. "update state of active process" activeProc _ self fetchPointer: ActiveProcessIndex ofObject: self schedulerPointer. self storePointer: SuspendedContextIndex ofObject: activeProc withValue: activeContext. "compact memory and compute the size of the memory actually in use" self incrementalGC. "maximimize space for forwarding table" self fullGC. self snapshotCleanUp. dataSize _ freeBlock - self startOfMemory. "Assume all objects are below the start of the free block" successFlag ifTrue: [rcvr _ self popStack. "pop rcvr" self push: trueObj. self writeImageFile: dataSize. embedded ifFalse: ["set Mac file type and creator; this is a noop on other platforms" setMacType _ self ioLoadFunction: 'setMacFileTypeAndCreator' From: 'FilePlugin'. setMacType = 0 ifFalse: [self cCode: '((sqInt (*)(char *, char *, char *))setMacType)(imageName, "STim", "FAST")']]. self pop: 1]. "activeContext was unmarked in #snapshotCleanUp, mark it old " self beRootIfOld: activeContext. successFlag ifTrue: [self push: falseObj] ifFalse: [self push: rcvr]. compilerInitialized ifTrue: [self compilerPostSnapshot]! ! !Interpreter methodsFor: 'image save/restore' stamp: 'di 6/14/2004 17:44'! snapshotCleanUp "Clean up right before saving an image, sweeping memory and: * nilling out all fields of contexts above the stack pointer. * flushing external primitives * clearing the root bit of any object in the root table " | oop header fmt sz | oop _ self firstObject. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [header _ self longAt: oop. fmt _ header >> 8 bitAnd: 15. "Clean out context" (fmt = 3 and: [self isContextHeader: header]) ifTrue: [sz _ self sizeBitsOf: oop. (self lastPointerOf: oop) + BytesPerWord to: sz - BaseHeaderSize by: BytesPerWord do: [:i | self longAt: oop + i put: nilObj]]. "Clean out external functions" fmt >= 12 ifTrue: ["This is a compiled method" (self primitiveIndexOf: oop) = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oop]]]. oop _ self objectAfter: oop]. self clearRootsTable! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 9/22/2004 12:05'! wordSwapped: w "Return the given 64-bit integer with its halves in the reverse order." BytesPerWord = 8 ifFalse: [self error: 'This cannot happen.']. ^ ((w bitShift: Byte4ShiftNegated) bitAnd: Bytes3to0Mask) + ((w bitShift: Byte4Shift ) bitAnd: Bytes7to4Mask) ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 6/10/2004 12:10'! writeImageFile: imageBytes | fn | self var: #fn declareC: 'void *fn'. self writeImageFileIO: imageBytes. "set Mac file type and creator; this is a noop on other platforms" fn _ self ioLoadFunction: 'setMacFileTypeAndCreator' From: 'FilePlugin'. fn = 0 ifFalse:[ self cCode:'((sqInt (*)(char*, char*, char*))fn)(imageName, "STim", "FAST")'. ]. ! ! !Interpreter methodsFor: 'image save/restore' stamp: 'ikp 3/26/2005 16:41'! writeImageFileIO: imageBytes | headerStart headerSize f bytesWritten sCWIfn okToWrite | self var: #f declareC: 'sqImageFile f'. self var: #headerStart declareC: 'squeakFileOffsetType headerStart'. self var: #sCWIfn declareC: 'void *sCWIfn'. "If the security plugin can be loaded, use it to check for write permission. If not, assume it's ok" sCWIfn _ self ioLoadFunction: 'secCanWriteImage' From: 'SecurityPlugin'. sCWIfn ~= 0 ifTrue:[okToWrite _ self cCode: '((sqInt (*)(void))sCWIfn)()'. okToWrite ifFalse:[^self primitiveFail]]. "local constants" headerStart _ 0. headerSize _ 64. "header size in bytes; do not change!!" f _ self cCode: 'sqImageFileOpen(imageName, "wb")'. f = nil ifTrue: [ "could not open the image file for writing" self success: false. ^ nil]. headerStart _ self cCode: 'sqImageFileStartLocation(f,imageName,headerSize+imageBytes)'. self cCode: '/* Note: on Unix systems one could put an exec command here, padded to 512 bytes */'. "position file to start of header" self sqImageFile: f Seek: headerStart. self putLong: (self imageFormatVersion) toFile: f. self putLong: headerSize toFile: f. self putLong: imageBytes toFile: f. self putLong: (self startOfMemory) toFile: f. self putLong: specialObjectsOop toFile: f. self putLong: lastHash toFile: f. self putLong: (self ioScreenSize) toFile: f. self putLong: fullScreenFlag toFile: f. self putLong: extraVMMemory toFile: f. 1 to: 7 do: [:i | self putLong: 0 toFile: f]. "fill remaining header words with zeros" successFlag ifFalse: [ "file write or seek failure" self cCode: 'sqImageFileClose(f)'. ^ nil]. "position file after the header" self sqImageFile: f Seek: headerStart + headerSize. "write the image data" bytesWritten _ self cCode: 'sqImageFileWrite(pointerForOop(memory), sizeof(unsigned char), imageBytes, f)'. self success: bytesWritten = imageBytes. self cCode: 'sqImageFileClose(f)'. ! ! !Interpreter methodsFor: 'I/O primitive support' stamp: 'di 7/7/2004 16:34'! reverseDisplayFrom: startIndex to: endIndex "Reverse the given range of Display words (at different bit depths, this will reverse different numbers of pixels). Used to give feedback during VM activities such as garbage collection when debugging. It is assumed that the given word range falls entirely within the first line of the Display." | displayObj dispBitsPtr w reversed | displayObj _ self splObj: TheDisplay. ((self isPointers: displayObj) and: [(self lengthOf: displayObj) >= 4]) ifFalse: [^ nil]. w _ self fetchInteger: 1 ofObject: displayObj. dispBitsPtr _ self fetchPointer: 0 ofObject: displayObj. (self isIntegerObject: dispBitsPtr) ifTrue: [^ nil]. dispBitsPtr _ dispBitsPtr + BaseHeaderSize. dispBitsPtr + (startIndex * 4) to: dispBitsPtr + (endIndex * 4) by: 4 do: [:ptr | reversed _ (self long32At: ptr) bitXor: 4294967295. self longAt: ptr put: reversed]. successFlag _ true. self displayBitsOf: displayObj Left: 0 Top: 0 Right: w Bottom: 1. self ioForceDisplayUpdate! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'di 8/3/2004 13:27'! copyObj: oop toSegment: segmentWordArray addr: lastSeg stopAt: stopAddr saveOopAt: oopPtr headerAt: hdrPtr "Copy this object into the segment beginning at lastSeg. Install a forwarding pointer, and save oop and header. Fail if out of space. Return the next segmentAddr if successful." "Copy the object..." | extraSize bodySize hdrAddr | self flag: #Dan. "None of the imageSegment stuff has been updated for 64 bits" successFlag ifFalse: [^ lastSeg]. extraSize _ self extraHeaderBytes: oop. bodySize _ self sizeBitsOf: oop. (lastSeg + extraSize + bodySize) >= stopAddr ifTrue: [^ self primitiveFail]. self transfer: extraSize + bodySize // BytesPerWord "wordCount" from: oop - extraSize to: lastSeg+BytesPerWord. "Clear root and mark bits of all headers copied into the segment" hdrAddr _ lastSeg+BytesPerWord + extraSize. self longAt: hdrAddr put: ((self longAt: hdrAddr) bitAnd: AllButRootBit - MarkBit). self forward: oop to: (lastSeg+BytesPerWord + extraSize - segmentWordArray) savingOopAt: oopPtr andHeaderAt: hdrPtr. "Return new end of segment" ^ lastSeg + extraSize + bodySize! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'ikp 3/26/2005 21:05'! oopHasAcceptableClass: signedOop "Similar to oopHasOkayClass:, except that it only returns true or false." | oopClass formatMask behaviorFormatBits oopFormatBits oop | (self isIntegerObject: signedOop) ifTrue: [^ true]. self var: #oop type: 'usqInt'. self var: #oopClass type: 'usqInt'. oop := self cCoerce: signedOop to: 'usqInt'. oop < endOfMemory ifFalse: [^ false]. ((oop \\ BytesPerWord) = 0) ifFalse: [^ false]. (oop + (self sizeBitsOf: oop)) < endOfMemory ifFalse: [^ false]. oopClass := self cCoerce: (self fetchClassOf: oop) to: 'usqInt'. (self isIntegerObject: oopClass) ifTrue: [^ false]. (oopClass < endOfMemory) ifFalse: [^ false]. ((oopClass \\ BytesPerWord) = 0) ifFalse: [^ false]. (oopClass + (self sizeBitsOf: oopClass)) < endOfMemory ifFalse: [^ false]. ((self isPointers: oopClass) and: [(self lengthOf: oopClass) >= 3]) ifFalse: [^ false]. (self isBytes: oop) ifTrue: [ formatMask _ 16rC00 ] "ignore extra bytes size bits" ifFalse: [ formatMask _ 16rF00 ]. behaviorFormatBits _ (self formatOfClass: oopClass) bitAnd: formatMask. oopFormatBits _ (self baseHeader: oop) bitAnd: formatMask. behaviorFormatBits = oopFormatBits ifFalse: [^ false]. ^ true! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'di 8/3/2004 13:41'! primitiveFailAfterCleanup: outPointerArray "If the storeSegment primitive fails, it must clean up first." | i lastAddr | "Store nils throughout the outPointer array." lastAddr _ outPointerArray + (self lastPointerOf: outPointerArray). i _ outPointerArray + BaseHeaderSize. [i <= lastAddr] whileTrue: [self longAt: i put: nilObj. i _ i + BytesPerWord]. DoAssertionChecks ifTrue: [self verifyCleanHeaders]. self primitiveFail! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'di 8/3/2004 13:49'! primitiveLoadImageSegment "This primitive is called from Squeak as... loadSegmentFrom: aWordArray outPointers: anArray." "This primitive will load a binary image segment created by primitiveStoreImageSegment. It expects the outPointer array to be of the proper size, and the wordArray to be well formed. It will return as its value the original array of roots, and the erstwhile segmentWordArray will have been truncated to a size of zero. If this primitive should fail, the segmentWordArray will, sadly, have been reduced to an unrecognizable and unusable jumble. But what more could you have done with it anyway?" | outPointerArray segmentWordArray endSeg segOop fieldPtr fieldOop doingClass lastPtr extraSize mapOop lastOut outPtr hdrTypeBits header data | DoAssertionChecks ifTrue: [self verifyCleanHeaders]. outPointerArray _ self stackTop. lastOut _ outPointerArray + (self lastPointerOf: outPointerArray). segmentWordArray _ self stackValue: 1. endSeg _ segmentWordArray + (self sizeBitsOf: segmentWordArray) - BaseHeaderSize. "Essential type checks" ((self formatOf: outPointerArray) = 2 "Must be indexable pointers" and: [(self formatOf: segmentWordArray) = 6]) "Must be indexable words" ifFalse: [^ self primitiveFail]. "Version check. Byte order of the WordArray now" data _ self longAt: segmentWordArray + BaseHeaderSize. (self readableFormat: (data bitAnd: 16rFFFF "low 2 bytes")) ifFalse: [ "Not readable -- try again with reversed bytes..." self reverseBytesFrom: segmentWordArray + BaseHeaderSize to: endSeg + BytesPerWord. data _ self longAt: segmentWordArray + BaseHeaderSize. (self readableFormat: (data bitAnd: 16rFFFF "low 2 bytes")) ifFalse: [ "Still NG -- put things back and fail" self reverseBytesFrom: segmentWordArray + BaseHeaderSize to: endSeg + BytesPerWord. DoAssertionChecks ifTrue: [self verifyCleanHeaders]. ^ self primitiveFail]]. "Reverse the Byte type objects if the data from opposite endian machine" "Test top byte. $d on the Mac or $s on the PC. Rest of word is equal" data = self imageSegmentVersion ifFalse: [ "Reverse the byte-type objects once" segOop _ self oopFromChunk: segmentWordArray + BaseHeaderSize + BytesPerWord. "Oop of first embedded object" self byteSwapByteObjectsFrom: segOop to: endSeg + BytesPerWord]. "Proceed through the segment, remapping pointers..." segOop _ self oopFromChunk: segmentWordArray + BaseHeaderSize + BytesPerWord. [segOop <= endSeg] whileTrue: [(self headerType: segOop) <= 1 ifTrue: ["This object has a class field (type = 0 or 1) -- start with that." fieldPtr _ segOop - BytesPerWord. doingClass _ true] ifFalse: ["No class field -- start with first data field" fieldPtr _ segOop + BaseHeaderSize. doingClass _ false]. lastPtr _ segOop + (self lastPointerOf: segOop). "last field" lastPtr > endSeg ifTrue: [ DoAssertionChecks ifTrue: [self verifyCleanHeaders]. ^ self primitiveFail "out of bounds"]. "Go through all oops, remapping them..." [fieldPtr > lastPtr] whileFalse: ["Examine each pointer field" fieldOop _ self longAt: fieldPtr. doingClass ifTrue: [hdrTypeBits _ self headerType: fieldPtr. fieldOop _ fieldOop - hdrTypeBits]. (self isIntegerObject: fieldOop) ifTrue: ["Integer -- nothing to do" fieldPtr _ fieldPtr + BytesPerWord] ifFalse: [(fieldOop bitAnd: 3) = 0 ifFalse: [^ self primitiveFail "bad oop"]. (fieldOop bitAnd: 16r80000000) = 0 ifTrue: ["Internal pointer -- add segment offset" mapOop _ fieldOop + segmentWordArray] ifFalse: ["External pointer -- look it up in outPointers" outPtr _ outPointerArray + (fieldOop bitAnd: 16r7FFFFFFF). outPtr > lastOut ifTrue: [^ self primitiveFail "out of bounds"]. mapOop _ self longAt: outPtr]. doingClass ifTrue: [self longAt: fieldPtr put: mapOop + hdrTypeBits. fieldPtr _ fieldPtr + 8. doingClass _ false] ifFalse: [self longAt: fieldPtr put: mapOop. fieldPtr _ fieldPtr + BytesPerWord]. segOop < youngStart ifTrue: [self possibleRootStoreInto: segOop value: mapOop]. ]]. segOop _ self objectAfter: segOop]. "Again, proceed through the segment checking consistency..." segOop _ self oopFromChunk: segmentWordArray + BaseHeaderSize + BytesPerWord. [segOop <= endSeg] whileTrue: [(self oopHasAcceptableClass: segOop) ifFalse: [^ self primitiveFail "inconsistency"]. fieldPtr _ segOop + BaseHeaderSize. "first field" lastPtr _ segOop + (self lastPointerOf: segOop). "last field" "Go through all oops, remapping them..." [fieldPtr > lastPtr] whileFalse: ["Examine each pointer field" fieldOop _ self longAt: fieldPtr. (self oopHasAcceptableClass: fieldOop) ifFalse: [^ self primitiveFail "inconsistency"]. fieldPtr _ fieldPtr + BytesPerWord]. segOop _ self objectAfter: segOop]. "Truncate the segment word array to size = BytesPerWord (vers stamp only)" extraSize _ self extraHeaderBytes: segmentWordArray. hdrTypeBits _ self headerType: segmentWordArray. extraSize = 8 ifTrue: [self longAt: segmentWordArray-extraSize put: BaseHeaderSize + BytesPerWord + hdrTypeBits] ifFalse: [header _ self longAt: segmentWordArray. self longAt: segmentWordArray put: header - (header bitAnd: SizeMask) + BaseHeaderSize + BytesPerWord]. "and return the roots array which was first in the segment" DoAssertionChecks ifTrue: [self verifyCleanHeaders]. self pop: 3 thenPush: (self oopFromChunk: segmentWordArray + BaseHeaderSize + BytesPerWord). ! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'ikp 8/3/2004 20:01'! primitiveStoreImageSegment "This primitive is called from Squeak as... storeSegmentFor: arrayOfRoots into: aWordArray outPointers: anArray." "This primitive will store a binary image segment (in the same format as the Squeak image file) of the receiver and every object in its proper tree of subParts (ie, that is not refered to from anywhere else outside the tree). All pointers from within the tree to objects outside the tree will be copied into the array of outpointers. In their place in the image segment will be an oop equal to the offset in the outPointer array (the first would be 4). but with the high bit set." "The primitive expects the array and wordArray to be more than adequately long. In this case it returns normally, and truncates the two arrays to exactly the right size. To simplify truncation, both incoming arrays are required to be 256 bytes or more long (ie with 3-word headers). If either array is too small, the primitive will fail, but in no other case. During operation of the primitive, it is necessary to convert from both internal and external oops to their mapped values. To make this fast, the headers of the original objects in question are replaced by the mapped values (and this is noted by adding the forbidden XX header type). Tables are kept of both kinds of oops, as well as of the original headers for restoration. To be specific, there are two similar two-part tables, the outpointer array, and one in the upper fifth of the segmentWordArray. Each grows oops from the bottom up, and preserved headers from halfway up. In case of either success or failure, the headers must be restored. In the event of primitive failure, the table of outpointers must also be nilled out (since the garbage in the high half will not have been discarded." | outPointerArray segmentWordArray savedYoungStart lastOut lastIn firstIn lastSeg endSeg segOop fieldPtr fieldOop mapOop doingClass lastPtr extraSize hdrTypeBits arrayOfRoots hdrBaseIn hdrBaseOut header firstOut versionOffset | outPointerArray _ self stackTop. segmentWordArray _ self stackValue: 1. arrayOfRoots _ self stackValue: 2. "Essential type checks" ((self formatOf: arrayOfRoots) = 2 "Must be indexable pointers" and: [(self formatOf: outPointerArray) = 2 "Must be indexable pointers" and: [(self formatOf: segmentWordArray) = 6]]) "Must be indexable words" ifFalse: [^ self primitiveFail]. ((self headerType: outPointerArray) = HeaderTypeSizeAndClass "Must be 3-word header" and: [(self headerType: segmentWordArray) = HeaderTypeSizeAndClass]) "Must be 3-word header" ifFalse: [^ self primitiveFail]. DoAssertionChecks ifTrue: [self verifyCleanHeaders]. "Use the top half of outPointers for saved headers." firstOut _ outPointerArray + BaseHeaderSize. lastOut _ firstOut - BytesPerWord. hdrBaseOut _ outPointerArray + ((self lastPointerOf: outPointerArray) // (BytesPerWord*2) * BytesPerWord). "top half" lastSeg _ segmentWordArray. endSeg _ segmentWordArray + (self sizeBitsOf: segmentWordArray) - BytesPerWord. "Write a version number for byte order and version check" versionOffset _ BytesPerWord. lastSeg _ lastSeg + versionOffset. lastSeg > endSeg ifTrue: [^ self primitiveFail]. self longAt: lastSeg put: self imageSegmentVersion. "Allocate top 1/8 of segment for table of internal oops and saved headers" firstIn _ endSeg - ((self sizeBitsOf: segmentWordArray) // (BytesPerWord*8) * BytesPerWord). "Take 1/8 of seg" lastIn _ firstIn - BytesPerWord. hdrBaseIn _ firstIn + ((self sizeBitsOf: segmentWordArray) // (BytesPerWord*16) * BytesPerWord). "top half of that" "First mark the rootArray and all root objects." self longAt: arrayOfRoots put: ((self longAt: arrayOfRoots) bitOr: MarkBit). lastPtr _ arrayOfRoots + (self lastPointerOf: arrayOfRoots). fieldPtr _ arrayOfRoots + BaseHeaderSize. [fieldPtr <= lastPtr] whileTrue: [fieldOop _ self longAt: fieldPtr. (self isIntegerObject: fieldOop) ifFalse: [self longAt: fieldOop put: ((self longAt: fieldOop) bitOr: MarkBit)]. fieldPtr _ fieldPtr + BytesPerWord]. "Then do a mark pass over all objects. This will stop at our marked roots, thus leaving our segment unmarked in their shadow." savedYoungStart _ youngStart. youngStart _ self startOfMemory. "process all of memory" "clear the recycled context lists" freeContexts _ NilContext. freeLargeContexts _ NilContext. self markAndTraceInterpreterOops. "and special objects array" youngStart _ savedYoungStart. "Finally unmark the rootArray and all root objects." self longAt: arrayOfRoots put: ((self longAt: arrayOfRoots) bitAnd: AllButMarkBit). fieldPtr _ arrayOfRoots + BaseHeaderSize. [fieldPtr <= lastPtr] whileTrue: [fieldOop _ self longAt: fieldPtr. (self isIntegerObject: fieldOop) ifFalse: [self longAt: fieldOop put: ((self longAt: fieldOop) bitAnd: AllButMarkBit)]. fieldPtr _ fieldPtr + BytesPerWord]. "All external objects, and only they, are now marked. Copy the array of roots into the segment, and forward its oop." lastIn _ lastIn + BytesPerWord. lastIn >= hdrBaseIn ifTrue: [successFlag _ false]. lastSeg _ self copyObj: arrayOfRoots toSegment: segmentWordArray addr: lastSeg stopAt: firstIn saveOopAt: lastIn headerAt: hdrBaseIn + (lastIn - firstIn). successFlag ifFalse: [lastIn _ lastIn - BytesPerWord. self restoreHeadersFrom: firstIn to: lastIn from: hdrBaseIn and: firstOut to: lastOut from: hdrBaseOut. ^ self primitiveFailAfterCleanup: outPointerArray]. "Now run through the segment fixing up all the pointers. Note that more objects will be added to the segment as we make our way along." segOop _ self oopFromChunk: segmentWordArray + versionOffset + BaseHeaderSize. [segOop <= lastSeg] whileTrue: [(self headerType: segOop) <= 1 ifTrue: ["This object has a class field (type=0 or 1) -- start with that." fieldPtr _ segOop - BytesPerWord. doingClass _ true] ifFalse: ["No class field -- start with first data field" fieldPtr _ segOop + BaseHeaderSize. doingClass _ false]. lastPtr _ segOop + (self lastPointerOf: segOop). "last field" "Go through all oops, remapping them..." [fieldPtr > lastPtr] whileFalse: ["Examine each pointer field" fieldOop _ self longAt: fieldPtr. doingClass ifTrue: [hdrTypeBits _ fieldOop bitAnd: TypeMask. fieldOop _ fieldOop - hdrTypeBits]. (self isIntegerObject: fieldOop) ifTrue: ["Just an integer -- nothing to do" fieldPtr _ fieldPtr + BytesPerWord] ifFalse: [header _ self longAt: fieldOop. (header bitAnd: TypeMask) = HeaderTypeFree ifTrue: ["Has already been forwarded -- this is the link" mapOop _ header bitAnd: AllButTypeMask] ifFalse: [((self longAt: fieldOop) bitAnd: MarkBit) = 0 ifTrue: ["Points to an unmarked obj -- an internal pointer. Copy the object into the segment, and forward its oop." lastIn _ lastIn + BytesPerWord. lastIn >= hdrBaseIn ifTrue: [successFlag _ false]. lastSeg _ self copyObj: fieldOop toSegment: segmentWordArray addr: lastSeg stopAt: firstIn saveOopAt: lastIn headerAt: hdrBaseIn + (lastIn - firstIn). successFlag ifFalse: ["Out of space in segment" lastIn _ lastIn - BytesPerWord. self restoreHeadersFrom: firstIn to: lastIn from: hdrBaseIn and: firstOut to: lastOut from: hdrBaseOut. ^ self primitiveFailAfterCleanup: outPointerArray]. mapOop _ (self longAt: fieldOop) bitAnd: AllButTypeMask] ifFalse: ["Points to a marked obj -- an external pointer. Map it as a tagged index in outPointers, and forward its oop." lastOut _ lastOut + BytesPerWord. lastOut >= hdrBaseOut ifTrue: ["Out of space in outPointerArray" lastOut _ lastOut - BytesPerWord. self restoreHeadersFrom: firstIn to: lastIn from: hdrBaseIn and: firstOut to: lastOut from: hdrBaseOut. ^ self primitiveFailAfterCleanup: outPointerArray]. . mapOop _ lastOut - outPointerArray bitOr: 16r80000000. self forward: fieldOop to: mapOop savingOopAt: lastOut andHeaderAt: hdrBaseOut + (lastOut - firstOut)]]. "Replace the oop by its mapped value" doingClass ifTrue: [self longAt: fieldPtr put: mapOop + hdrTypeBits. fieldPtr _ fieldPtr + (BytesPerWord*2). doingClass _ false] ifFalse: [self longAt: fieldPtr put: mapOop. fieldPtr _ fieldPtr + BytesPerWord]. ]]. segOop _ self objectAfter: segOop]. self restoreHeadersFrom: firstIn to: lastIn from: hdrBaseIn and: firstOut to: lastOut from: hdrBaseOut. "Truncate the outPointerArray..." ((outPointerArray + (self lastPointerOf: outPointerArray) - lastOut) < 12 or: [(endSeg - lastSeg) < 12]) ifTrue: ["Not enough room to insert simple 3-word headers" ^ self primitiveFailAfterCleanup: outPointerArray]. extraSize _ self extraHeaderBytes: segmentWordArray. hdrTypeBits _ self headerType: segmentWordArray. "Copy the 3-word wordArray header to establish a free chunk." self transfer: 3 from: segmentWordArray - extraSize to: lastOut+BytesPerWord. "Adjust the size of the original as well as the free chunk." self longAt: lastOut+BytesPerWord put: outPointerArray + (self lastPointerOf: outPointerArray) - lastOut - extraSize + hdrTypeBits. self longAt: outPointerArray-extraSize put: lastOut - firstOut + (BytesPerWord*2) + hdrTypeBits. "Note that pointers have been stored into roots table" self beRootIfOld: outPointerArray. "Truncate the image segment..." "Copy the 3-word wordArray header to establish a free chunk." self transfer: 3 from: segmentWordArray - extraSize to: lastSeg+BytesPerWord. "Adjust the size of the original as well as the free chunk." self longAt: segmentWordArray-extraSize put: lastSeg - segmentWordArray + BaseHeaderSize + hdrTypeBits. self longAt: lastSeg+BytesPerWord put: endSeg - lastSeg - extraSize + hdrTypeBits. DoAssertionChecks ifTrue: [self verifyCleanHeaders]. self pop: 3. "...leaving the reciever on the stack as return value" ! ! !Interpreter methodsFor: 'image segment in/out' stamp: 'di 8/3/2004 14:05'! restoreHeadersFrom: firstIn to: lastIn from: hdrBaseIn and: firstOut to: lastOut from: hdrBaseOut "Restore headers smashed by forwarding links" | tablePtr oop header | tablePtr _ firstIn. [tablePtr <= lastIn] whileTrue: [oop _ self longAt: tablePtr. header _ self longAt: hdrBaseIn + (tablePtr-firstIn). self longAt: oop put: header. tablePtr _ tablePtr + BytesPerWord]. tablePtr _ firstOut. [tablePtr <= lastOut] whileTrue: [oop _ self longAt: tablePtr. header _ self longAt: hdrBaseOut + (tablePtr-firstOut). self longAt: oop put: header. tablePtr _ tablePtr + BytesPerWord]. "Clear all mark bits" oop _ self firstObject. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [self longAt: oop put: ((self longAt: oop) bitAnd: AllButMarkBit)]. oop _ self objectAfter: oop]. ! ! !Interpreter methodsFor: 'debug printing' stamp: 'ikp 8/3/2004 21:39'! printNameOfClass: classOop count: cnt "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object." cnt <= 0 ifTrue: [ ^ self print: 'bad class' ]. (self sizeBitsOf: classOop) = (7 * BytesPerWord) "(Metaclass instSize+1 * 4)" ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) count: cnt - 1. self print: ' class'] ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]! ! !Interpreter methodsFor: 'stack bytecodes' stamp: 'ikp 6/10/2004 11:04'! experimentalBytecode "Note: This bytecode is not currently generated by the compiler." "This range of six bytecodes can replace the pushTemporaryVariable[0..5] bytecode at the beginning of a sequence of either the form: pushTemp pushTemp | pushConstantOne | pushLiteralConstant <= longJumpIfFalse or the form: pushTemp pushTemp | pushConstantOne | pushLiteralConstant + popIntoTemp (optional) If two values pushed are not small integers, this bytecode acts like the pushTemp bytecode it replaces. However, if they are small integers, then the given arithmetic or comparison operation is performed. The result of that operation is either pushed onto the stack or, if one of the expected bytecodes follows it, then that bytecode is performed immediately. In such cases, the entire four instruction sequence is performed without doing any stack operations." | arg1 byte2 byte3 byte4 arg1Val arg2Val result offset | arg1 _ self temporary: currentBytecode - 138. byte2 _ self byteAtPointer: localIP + 1. "fetch ahead" byte3 _ self byteAtPointer: localIP + 2. "fetch ahead" byte4 _ self byteAtPointer: localIP + 3. "fetch ahead" "check first arg" (self isIntegerObject: arg1) ifTrue: [ arg1Val _ self integerValueOf: arg1. ] ifFalse: [ self fetchNextBytecode. ^ self internalPush: arg1. "abort; first arg is not an integer" ]. "get and check second arg" byte2 < 32 ifTrue: [ arg2Val _ self temporary: (byte2 bitAnd: 16rF). (self isIntegerObject: arg2Val) ifTrue: [ arg2Val _ self integerValueOf: arg2Val. ] ifFalse: [ self fetchNextBytecode. ^ self internalPush: arg1. "abort; second arg is not an integer" ]. ] ifFalse: [ byte2 > 64 ifTrue: [ arg2Val _ 1. ] ifFalse: [ arg2Val _ self literal: (byte2 bitAnd: 16r1F). (self isIntegerObject: arg2Val) ifTrue: [ arg2Val _ self integerValueOf: arg2Val. ] ifFalse: [ self fetchNextBytecode. ^ self internalPush: arg1. "abort; second arg is not an integer" ]. ]. ]. byte3 < 178 ifTrue: [ "do addition, possibly followed by a storeAndPopTemp" result _ arg1Val + arg2Val. (self isIntegerValue: result) ifTrue: [ ((byte4 > 103) and: [byte4 < 112]) ifTrue: [ "next instruction is a storeAndPopTemp" localIP _ localIP + 3. self storePointerUnchecked: (byte4 bitAnd: 7) + TempFrameStart ofObject: localHomeContext withValue: (self integerObjectOf: result). ] ifFalse: [ localIP _ localIP + 2. self internalPush: (self integerObjectOf: result). ]. ] ifFalse: [ self fetchNextBytecode. ^ self internalPush: arg1. "abort; result is not an integer" ]. ] ifFalse: [ "do comparison operation, followed by a longJumpIfFalse" offset _ self byteAtPointer: localIP + 4. arg1Val <= arg2Val ifTrue: [localIP _ localIP + 3 + 1] "jump not taken; skip extra instruction byte" ifFalse: [localIP _ localIP + 3 + 1 + offset]. self fetchNextBytecode. ]. ! ! !Interpreter methodsFor: 'primitive support' stamp: 'ikp 10/5/2004 15:47'! positive32BitIntegerFor: integerValue | newLargeInteger | "Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:." integerValue >= 0 ifTrue: [(self isIntegerValue: integerValue) ifTrue: [^ self integerObjectOf: integerValue]]. BytesPerWord = 4 ifTrue: ["Faster instantiateSmallClass: currently only works with integral word size." newLargeInteger _ self instantiateSmallClass: (self splObj: ClassLargePositiveInteger) sizeInBytes: BaseHeaderSize + 4 fill: 0] ifFalse: ["Cant use instantiateSmallClass: due to integral word requirement." newLargeInteger _ self instantiateClass: (self splObj: ClassLargePositiveInteger) indexableSize: 4]. self storeByte: 3 ofObject: newLargeInteger withValue: ((integerValue >> 24) bitAnd: 16rFF). self storeByte: 2 ofObject: newLargeInteger withValue: ((integerValue >> 16) bitAnd: 16rFF). self storeByte: 1 ofObject: newLargeInteger withValue: ((integerValue >> 8) bitAnd: 16rFF). self storeByte: 0 ofObject: newLargeInteger withValue: (integerValue bitAnd: 16rFF). ^ newLargeInteger! ! !Interpreter methodsFor: 'primitive support' stamp: 'tpr 3/17/2005 17:47'! positive64BitIntegerFor: integerValue | newLargeInteger value check | "Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:." self var: 'integerValue' type: 'sqLong'. (self sizeof: integerValue) = 4 ifTrue: [^self positive32BitIntegerFor: integerValue]. self cCode: 'check = integerValue >> 32'. "Why not run this in sim?" check = 0 ifTrue: [^self positive32BitIntegerFor: integerValue]. newLargeInteger _ self instantiateSmallClass: (self splObj: ClassLargePositiveInteger) sizeInBytes: BaseHeaderSize + 8 fill: 0. 0 to: 7 do: [:i | self cCode: 'value = ( integerValue >> (i * 8)) & 255'. self storeByte: i ofObject: newLargeInteger withValue: value]. ^ newLargeInteger! ! !Interpreter methodsFor: 'primitive support' stamp: 'tpr 3/17/2005 17:47'! positive64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargePositiveInteger." | sz szsqLong value | self returnTypeC: 'sqLong'. self var: 'value' type: 'sqLong'. (self isIntegerObject: oop) ifTrue: [ value _ self integerValueOf: oop. value < 0 ifTrue: [^ self primitiveFail]. ^ value]. self assertClassOf: oop is: (self splObj: ClassLargePositiveInteger). successFlag ifFalse: [^ self primitiveFail]. szsqLong _ self cCode: 'sizeof(sqLong)'. sz _ self lengthOf: oop. sz > szsqLong ifTrue: [^ self primitiveFail]. value _ 0. 0 to: sz - 1 do: [:i | value _ value + ((self cCoerce: (self fetchByte: i ofObject: oop) to: 'sqLong') << (i*8))]. ^value.! ! !Interpreter methodsFor: 'primitive support' stamp: 'tpr 3/17/2005 17:48'! signed64BitIntegerFor: integerValue "Return a Large Integer object for the given integer value" | newLargeInteger value largeClass intValue check | self inline: false. self var: 'integerValue' type: 'sqLong'. self var: 'value' type: 'sqLong'. integerValue < 0 ifTrue:[ largeClass _ self classLargeNegativeInteger. value _ 0 - integerValue] ifFalse:[ largeClass _ self classLargePositiveInteger. value _ integerValue]. (self sizeof: value) = 4 ifTrue: [^self signed32BitIntegerFor: integerValue]. self cCode: 'check = value >> 32'. check = 0 ifTrue: [^self signed32BitIntegerFor: integerValue]. newLargeInteger _ self instantiateSmallClass: largeClass sizeInBytes: 12 fill: 0. 0 to: 7 do: [:i | self cCode: 'intValue = ( value >> (i * 8)) & 255'. self storeByte: i ofObject: newLargeInteger withValue: intValue]. ^ newLargeInteger! ! !Interpreter methodsFor: 'primitive support' stamp: 'tpr 3/17/2005 17:48'! signed64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargeInteger." | sz value largeClass negative szsqLong | self inline: false. self returnTypeC: 'sqLong'. self var: 'value' type: 'sqLong'. (self isIntegerObject: oop) ifTrue: [^self cCoerce: (self integerValueOf: oop) to: 'sqLong']. largeClass _ self fetchClassOf: oop. largeClass = self classLargePositiveInteger ifTrue:[negative _ false] ifFalse:[largeClass = self classLargeNegativeInteger ifTrue:[negative _ true] ifFalse:[^self primitiveFail]]. szsqLong _ self cCode: 'sizeof(sqLong)'. sz _ self lengthOf: oop. sz > szsqLong ifTrue: [^ self primitiveFail]. value _ 0. 0 to: sz - 1 do: [:i | value _ value + ((self cCoerce: (self fetchByte: i ofObject: oop) to: 'sqLong') << (i*8))]. negative ifTrue:[^0 - value] ifFalse:[^value]! ! !Interpreter methodsFor: 'interpreter shell' stamp: 'ikp 6/10/2004 11:01'! fetchByte "This method uses the preIncrement builtin function which has no Smalltalk equivalent. Thus, it must be overridden in the simulator." ^ self byteAtPointer: localIP preIncrement! ! !Interpreter methodsFor: 'plugin support' stamp: 'ikp 6/10/2004 12:26'! addToExternalPrimitiveTable: functionAddress "Add the given function address to the external primitive table and return the index where it's stored. This function doesn't need to be fast since it is only called when an external primitive has been looked up (which takes quite a bit of time itself). So there's nothing specifically complicated here. Note: Return index will be one-based (ST convention)" self var: #functionAddress declareC: 'void *functionAddress'. 0 to: MaxExternalPrimitiveTableSize-1 do: [ :i | (externalPrimitiveTable at: i) = 0 ifTrue: [ externalPrimitiveTable at: i put: functionAddress. ^i+1]]. "if no space left, return zero so it'll looked up again" ^0! ! !Interpreter methodsFor: 'plugin support' stamp: 'ikp 8/2/2004 16:52'! findObsoleteNamedPrimitive: functionName length: functionLength "Search the obsolete named primitive table for the given function. Return the index if it's found, -1 otherwise." | entry index chIndex | self var: #functionName type:'char *'. self var: #entry type:'const char *'. index _ 0. [true] whileTrue:[ entry _ self cCode: 'obsoleteNamedPrimitiveTable[index][0]' inSmalltalk: [ (CArrayAccessor on: (obsoleteNamedPrimitiveTable at: index)) at: 0 ]. entry == nil ifTrue:[^-1]. "at end of table" self cCode: '' inSmalltalk: [ entry _ CArrayAccessor on: entry ]. "Compare entry with functionName" chIndex _ 0. [(entry at: chIndex) = (self cCode: 'functionName[chIndex]' inSmalltalk: [self byteAtPointer: functionName + chIndex]) and:[chIndex < functionLength]] whileTrue:[chIndex _ chIndex + 1]. (chIndex = functionLength and:[(entry at: chIndex) = 0]) ifTrue:[^index]. "match" index _ index + 1. ].! ! !Interpreter methodsFor: 'plugin support' stamp: 'di 6/23/2004 12:26'! firstFixedField: oop self returnTypeC: 'void *'. ^ self pointerForOop: oop + BaseHeaderSize! ! !Interpreter methodsFor: 'plugin support' stamp: 'di 7/17/2004 13:02'! firstIndexableField: oop "NOTE: copied in InterpreterSimulator, so please duplicate any changes" | hdr fmt totalLength fixedFields | self returnTypeC: 'void *'. hdr _ self baseHeader: oop. fmt _ (hdr >> 8) bitAnd: 16rF. totalLength _ self lengthOf: oop baseHeader: hdr format: fmt. fixedFields _ self fixedFieldsOf: oop format: fmt length: totalLength. fmt < 8 ifTrue: [fmt = 6 ifTrue: ["32 bit field objects" ^ self pointerForOop: oop + BaseHeaderSize + (fixedFields << 2)]. "full word objects (pointer or bits)" ^ self pointerForOop: oop + BaseHeaderSize + (fixedFields << ShiftForWord)] ifFalse: ["Byte objects" ^ self pointerForOop: oop + BaseHeaderSize + fixedFields]! ! !Interpreter methodsFor: 'control primitives' stamp: 'di 7/4/2004 08:56'! primitiveBlockCopy | context methodContext contextSize newContext initialIP | context _ self stackValue: 1. (self isIntegerObject: (self fetchPointer: MethodIndex ofObject: context)) ifTrue: ["context is a block; get the context of its enclosing method" methodContext _ self fetchPointer: HomeIndex ofObject: context] ifFalse: [methodContext _ context]. contextSize _ self sizeBitsOf: methodContext. "in bytes, including header" context _ nil. "context is no longer needed and is not preserved across allocation" "remap methodContext in case GC happens during allocation" self pushRemappableOop: methodContext. newContext _ self instantiateContext: (self splObj: ClassBlockContext) sizeInBytes: contextSize. methodContext _ self popRemappableOop. initialIP _ self integerObjectOf: (instructionPointer+1+3) - (method+BaseHeaderSize). "Was instructionPointer + 3, but now it's greater by 1 due to preIncrement" "Assume: have just allocated a new context; it must be young. Thus, can use uncheck stores. See the comment in fetchContextRegisters." self storePointer: InitialIPIndex ofObject: newContext withValue: initialIP. self storePointer: InstructionPointerIndex ofObject: newContext withValue: initialIP. self storeStackPointerValue: 0 inContext: newContext. self storePointerUnchecked: BlockArgumentCountIndex ofObject: newContext withValue: (self stackValue: 0). self storePointerUnchecked: HomeIndex ofObject: newContext withValue: methodContext. self storePointerUnchecked: SenderIndex ofObject: newContext withValue: nilObj. self pop: 2 thenPush: newContext.! ! !Interpreter methodsFor: 'control primitives' stamp: 'tpr 3/23/2005 15:08'! primitiveExecuteMethodArgsArray "receiver, argsArray, then method are on top of stack. Execute method against receiver and args" | argCnt argumentArray | newMethod _ self popStack. primitiveIndex _ self primitiveIndexOf: newMethod. argCnt _ self argumentCountOf: newMethod. argumentArray _ self popStack. "If the argArray isnt actually an Array we have to unPop both the above" (self isArray: argumentArray) ifFalse:[self unPop: 2. ^self primitiveFail]. successFlag ifTrue: [self success: (argCnt = (self fetchWordLengthOf: argumentArray))]. successFlag ifTrue: [self transfer: argCnt from: argumentArray + BaseHeaderSize to: stackPointer + BytesPerWord. self unPop: argCnt. argumentCount _ argCnt. self executeNewMethod] ifFalse: [self unPop: 2]. ! ! !Interpreter methodsFor: 'control primitives' stamp: 'tpr 3/23/2005 15:23'! primitiveInvokeObjectAsMethod "Primitive. 'Invoke' an object like a function, sending the special message run: originalSelector with: arguments in: aReceiver. " | runSelector runReceiver runArgs newReceiver lookupClass | runArgs _ self instantiateClass: (self splObj: ClassArray) indexableSize: argumentCount. self beRootIfOld: runArgs. "do we really need this?" self transfer: argumentCount from: stackPointer - ((argumentCount - 1) * BytesPerWord) to: runArgs + BaseHeaderSize. runSelector _ messageSelector. runReceiver _ self stackValue: argumentCount. self pop: argumentCount+1. "stack is clean here" newReceiver _ newMethod. messageSelector _ self splObj: SelectorRunWithIn. argumentCount _ 3. self push: newReceiver. self push: runSelector. self push: runArgs. self push: runReceiver. lookupClass _ self fetchClassOf: newReceiver. self findNewMethodInClass: lookupClass. self executeNewMethodFromCache. "Recursive xeq affects successFlag" successFlag _ true. ! ! !Interpreter methodsFor: 'jump bytecodes' stamp: 'ikp 6/10/2004 11:01'! jump: offset localIP _ localIP + offset + 1. currentBytecode _ self byteAtPointer: localIP. ! ! !Interpreter methodsFor: 'float primitives' stamp: 'ikp 6/9/2004 16:23'! primitiveExponent "Exponent part of this float." | rcvr frac pwr | self var: #rcvr declareC: 'double rcvr'. self var: #frac declareC: 'double frac'. self var: #pwr declareC: 'int pwr'. rcvr _ self popFloat. successFlag ifTrue: [ "rcvr = frac * 2^pwr, where frac is in [0.5..1.0)" self cCode: 'frac = frexp(rcvr, &pwr)' inSmalltalk: [pwr _ rcvr exponent]. self pushInteger: pwr - 1] ifFalse: [self unPop: 1].! ! !Interpreter methodsFor: 'float primitives' stamp: 'ikp 8/4/2004 11:42'! primitiveTruncated | rcvr frac trunc | self var: #rcvr declareC: 'double rcvr'. self var: #frac declareC: 'double frac'. self var: #trunc declareC: 'double trunc'. rcvr _ self popFloat. successFlag ifTrue: [self cCode: 'frac = modf(rcvr, &trunc)' inSmalltalk: [trunc _ rcvr truncated]. self flag: #Dan. "The ranges are INCORRECT if SmallIntegers are wider than 31 bits." self cCode: 'success((-1073741824.0 <= trunc) && (trunc <= 1073741823.0))' inSmalltalk: [self success: (trunc between: SmallInteger minVal and: SmallInteger maxVal)]]. successFlag ifTrue: [self cCode: 'pushInteger((sqInt) trunc)' inSmalltalk: [self pushInteger: trunc]] ifFalse: [self unPop: 1]! ! !Interpreter methodsFor: 'object access primitives' stamp: 'di 8/3/2004 13:40'! primitiveChangeClass "Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have." | arg rcvr argClass classHdr sizeHiBits byteSize argFormat rcvrFormat ccIndex | arg _ self stackObjectValue: 0. rcvr _ self stackObjectValue: 1. successFlag ifFalse:[^nil]. "Get the class we want to convert the receiver into" argClass _ self fetchClassOf: arg. "Check what the format of the class says" classHdr _ self formatOfClass: argClass. "Low 2 bits are 0" "Compute the size of instances of the class (used for fixed field classes only)" sizeHiBits _ (classHdr bitAnd: 16r60000) >> 9. classHdr _ classHdr bitAnd: 16r1FFFF. byteSize _ (classHdr bitAnd: SizeMask) + sizeHiBits. "size in bytes -- low 2 bits are 0" "Check the receiver's format against that of the class" argFormat _ (classHdr >> 8) bitAnd: 16rF. rcvrFormat _ self formatOf: rcvr. argFormat = rcvrFormat ifFalse:[^self primitiveFail]. "no way" "For fixed field classes, the sizes must match. Note: base header size is included in class size." argFormat < 2 ifTrue:[(byteSize - BaseHeaderSize) = (self byteSizeOf: rcvr) ifFalse:[^self primitiveFail]]. (self headerType: rcvr) = HeaderTypeShort ifTrue:[ "Compact classes. Check if the arg's class is compact and exchange ccIndex" ccIndex _ classHdr bitAnd: CompactClassMask. ccIndex = 0 ifTrue:[^self primitiveFail]. "class is not compact" self longAt: rcvr put: (((self longAt: rcvr) bitAnd: CompactClassMask bitInvert32) bitOr: ccIndex)] ifFalse:["Exchange the class pointer, which could make rcvr a root for argClass" self longAt: rcvr-BaseHeaderSize put: (argClass bitOr: (self headerType: rcvr)). (rcvr < youngStart) ifTrue: [self possibleRootStoreInto: rcvr value: argClass]]. "Flush cache because rcvr's class has changed" self flushMethodCache. successFlag ifTrue: [ self pop: 1 ]! ! !Interpreter methodsFor: 'object access primitives' stamp: 'di 6/14/2004 17:26'! primitiveObjectPointsTo | rcvr thang lastField | thang _ self popStack. rcvr _ self popStack. (self isIntegerObject: rcvr) ifTrue: [^self pushBool: false]. lastField _ self lastPointerOf: rcvr. BaseHeaderSize to: lastField by: BytesPerWord do: [:i | (self longAt: rcvr + i) = thang ifTrue: [^ self pushBool: true]]. self pushBool: false.! ! !Interpreter methodsFor: 'object access primitives' stamp: 'di 6/14/2004 17:27'! primitiveStoreStackp "Atomic store into context stackPointer. Also ensures that any newly accessible cells are initialized to nil " | ctxt newStackp stackp | ctxt _ self stackValue: 1. newStackp _ self stackIntegerValue: 0. self success: newStackp >= 0. self success: newStackp <= (LargeContextSize - BaseHeaderSize // BytesPerWord - CtxtTempFrameStart). successFlag ifFalse: [^ self primitiveFail]. stackp _ self fetchStackPointerOf: ctxt. newStackp > stackp ifTrue: ["Nil any newly accessible cells" stackp + 1 to: newStackp do: [:i | self storePointer: i + CtxtTempFrameStart - 1 ofObject: ctxt withValue: nilObj]]. self storeStackPointerValue: newStackp inContext: ctxt. self pop: 1! ! !Interpreter methodsFor: 'object access primitives' stamp: 'ikp 8/4/2004 18:28'! sufficientSpaceToInstantiate: classOop indexableSize: size "Return the number of bytes required to allocate an instance of the given class with the given number of indexable fields." "Details: For speed, over-estimate space needed for fixed fields or literals; the low space threshold is a blurry line." | format okay | self inline: true. format _ (self formatOfClass: classOop) >> 8 bitAnd: 15. "fail if attempting to call new: on non-indexable class" ((self cCoerce: size to: 'usqInt ') > 0 and: [format < 2]) ifTrue: [^ false]. format < 8 ifTrue: ["indexable fields are words or pointers" okay _ self sufficientSpaceToAllocate: 2500 + (size * BytesPerWord)] ifFalse: ["indexable fields are bytes" okay _ self sufficientSpaceToAllocate: 2500 + size]. ^ okay! ! !Interpreter methodsFor: 'array and stream primitives' stamp: 'ikp 6/10/2004 12:15'! install: rcvr inAtCache: cache at: atIx string: stringy "Install the oop of this object in the given cache (at or atPut), along with its size, format and fixedSize" | hdr fmt totalLength fixedFields | self var: #cache declareC: 'sqInt *cache'. hdr _ self baseHeader: rcvr. fmt _ (hdr >> 8) bitAnd: 16rF. (fmt = 3 and: [self isContextHeader: hdr]) ifTrue: ["Contexts must not be put in the atCache, since their size is not constant" ^ self primitiveFail]. totalLength _ self lengthOf: rcvr baseHeader: hdr format: fmt. fixedFields _ self fixedFieldsOf: rcvr format: fmt length: totalLength. cache at: atIx+AtCacheOop put: rcvr. stringy ifTrue: [cache at: atIx+AtCacheFmt put: fmt + 16] "special flag for strings" ifFalse: [cache at: atIx+AtCacheFmt put: fmt]. cache at: atIx+AtCacheFixedFields put: fixedFields. cache at: atIx+AtCacheSize put: totalLength - fixedFields. ! ! !Interpreter methodsFor: 'array and stream primitives' stamp: 'ikp 3/29/2005 22:34'! primitiveStringReplace " primReplaceFrom: start to: stop with: replacement startingAt: repStart " | array start stop repl replStart hdr arrayFmt totalLength arrayInstSize replFmt replInstSize srcIndex | array _ self stackValue: 4. start _ self stackIntegerValue: 3. stop _ self stackIntegerValue: 2. repl _ self stackValue: 1. replStart _ self stackIntegerValue: 0. successFlag ifFalse: [^ self primitiveFail]. (self isIntegerObject: repl) ifTrue: ["can happen in LgInt copy" ^ self primitiveFail]. hdr _ self baseHeader: array. arrayFmt _ hdr >> 8 bitAnd: 15. totalLength _ self lengthOf: array baseHeader: hdr format: arrayFmt. arrayInstSize _ self fixedFieldsOf: array format: arrayFmt length: totalLength. (start >= 1 and: [start - 1 <= stop and: [stop + arrayInstSize <= totalLength]]) ifFalse: [^ self primitiveFail]. hdr _ self baseHeader: repl. replFmt _ hdr >> 8 bitAnd: 15. totalLength _ self lengthOf: repl baseHeader: hdr format: replFmt. replInstSize _ self fixedFieldsOf: repl format: replFmt length: totalLength. (replStart >= 1 and: [stop - start + replStart + replInstSize <= totalLength]) ifFalse: [^ self primitiveFail]. "Array formats (without byteSize bits, if bytes array) must be same " arrayFmt < 8 ifTrue: [arrayFmt = replFmt ifFalse: [^ self primitiveFail]] ifFalse: [(arrayFmt bitAnd: 12) = (replFmt bitAnd: 12) ifFalse: [^ self primitiveFail]]. srcIndex _ replStart + replInstSize - 1. "- 1 for 0-based access" arrayFmt <= 4 ifTrue: ["pointer type objects" start + arrayInstSize - 1 to: stop + arrayInstSize - 1 do: [:i | self storePointer: i ofObject: array withValue: (self fetchPointer: srcIndex ofObject: repl). srcIndex _ srcIndex + 1]] ifFalse: [arrayFmt < 8 ifTrue: ["32-bit-word type objects" start + arrayInstSize - 1 to: stop + arrayInstSize - 1 do: [:i | self storeLong32: i ofObject: array withValue: (self fetchLong32: srcIndex ofObject: repl). srcIndex _ srcIndex + 1]] ifFalse: ["byte-type objects" start + arrayInstSize - 1 to: stop + arrayInstSize - 1 do: [:i | self storeByte: i ofObject: array withValue: (self fetchByte: srcIndex ofObject: repl). srcIndex _ srcIndex + 1]]]. "We might consider comparing stop - start to some value here and using forceInterruptCheck" self pop: argumentCount "leave rcvr on stack"! ! !Interpreter methodsFor: 'I/O primitives' stamp: 'ikp 6/10/2004 14:05'! displayBitsOf: aForm Left: l Top: t Right: r Bottom: b "Repaint the portion of the Smalltalk screen bounded by the affected rectangle. Used to synchronize the screen after a Bitblt to the Smalltalk Display object." | displayObj dispBits w h dispBitsIndex d left right top bottom surfaceHandle | displayObj _ self splObj: TheDisplay. aForm = displayObj ifFalse: [^ nil]. self success: ((self isPointers: displayObj) and: [(self lengthOf: displayObj) >= 4]). successFlag ifTrue: [ dispBits _ self fetchPointer: 0 ofObject: displayObj. w _ self fetchInteger: 1 ofObject: displayObj. h _ self fetchInteger: 2 ofObject: displayObj. d _ self fetchInteger: 3 ofObject: displayObj. ]. l < 0 ifTrue:[left _ 0] ifFalse: [left _ l]. r > w ifTrue: [right _ w] ifFalse: [right _ r]. t < 0 ifTrue: [top _ 0] ifFalse: [top _ t]. b > h ifTrue: [bottom _ h] ifFalse: [bottom _ b]. ((left <= right) and: [top <= bottom]) ifFalse: [^nil]. successFlag ifTrue: [ (self isIntegerObject: dispBits) ifTrue: [ surfaceHandle _ self integerValueOf: dispBits. showSurfaceFn = 0 ifTrue: [ showSurfaceFn _ self ioLoadFunction: 'ioShowSurface' From: 'SurfacePlugin'. showSurfaceFn = 0 ifTrue: [^self success: false]]. self cCode:'((sqInt (*)(sqInt, sqInt, sqInt, sqInt, sqInt))showSurfaceFn)(surfaceHandle, left, top, right-left, bottom-top)'. ] ifFalse: [ dispBitsIndex _ dispBits + BaseHeaderSize. "index in memory byte array" self cCode: 'ioShowDisplay(dispBitsIndex, w, h, d, left, right, top, bottom)' inSmalltalk: [self showDisplayBits: dispBitsIndex w: w h: h d: d left: left right: right top: top bottom: bottom] ]. ].! ! !Interpreter methodsFor: 'I/O primitives' stamp: 'di 7/4/2004 08:41'! primitiveBeCursor "Set the cursor to the given shape. The Mac only supports 16x16 pixel cursors. Cursor offsets are handled by Smalltalk." | cursorObj maskBitsIndex maskObj bitsObj extentX extentY depth offsetObj offsetX offsetY cursorBitsIndex ourCursor | self flag: #Dan. "This is disabled until we convert bitmaps appropriately" BytesPerWord = 8 ifTrue: [^ self pop: argumentCount]. argumentCount = 0 ifTrue: [ cursorObj _ self stackTop. maskBitsIndex _ nil]. argumentCount = 1 ifTrue: [ cursorObj _ self stackValue: 1. maskObj _ self stackTop]. self success: (argumentCount < 2). self success: ((self isPointers: cursorObj) and: [(self lengthOf: cursorObj) >= 5]). successFlag ifTrue: [ bitsObj _ self fetchPointer: 0 ofObject: cursorObj. extentX _ self fetchInteger: 1 ofObject: cursorObj. extentY _ self fetchInteger: 2 ofObject: cursorObj. depth _ self fetchInteger: 3 ofObject: cursorObj. offsetObj _ self fetchPointer: 4 ofObject: cursorObj]. self success: ((self isPointers: offsetObj) and: [(self lengthOf: offsetObj) >= 2]). successFlag ifTrue: [ offsetX _ self fetchInteger: 0 ofObject: offsetObj. offsetY _ self fetchInteger: 1 ofObject: offsetObj. self success: ((extentX = 16) and: [extentY = 16 and: [depth = 1]]). self success: ((offsetX >= -16) and: [offsetX <= 0]). self success: ((offsetY >= -16) and: [offsetY <= 0]). self success: ((self isWords: bitsObj) and: [(self lengthOf: bitsObj) = 16]). cursorBitsIndex _ bitsObj + BaseHeaderSize. self cCode: '' inSmalltalk: [ourCursor _ Cursor extent: extentX @ extentY fromArray: ((1 to: 16) collect: [:i | ((self fetchLong32: i-1 ofObject: bitsObj) >> (BytesPerWord*8 - 16)) bitAnd: 16rFFFF]) offset: offsetX @ offsetY]]. argumentCount = 1 ifTrue: [ self success: ((self isPointers: maskObj) and: [(self lengthOf: maskObj) >= 5]). successFlag ifTrue: [ bitsObj _ self fetchPointer: 0 ofObject: maskObj. extentX _ self fetchInteger: 1 ofObject: maskObj. extentY _ self fetchInteger: 2 ofObject: maskObj. depth _ self fetchInteger: 3 ofObject: maskObj]. successFlag ifTrue: [ self success: ((extentX = 16) and: [extentY = 16 and: [depth = 1]]). self success: ((self isWords: bitsObj) and: [(self lengthOf: bitsObj) = 16]). maskBitsIndex _ bitsObj + BaseHeaderSize]]. successFlag ifTrue: [ argumentCount = 0 ifTrue: [self cCode: 'ioSetCursor(cursorBitsIndex, offsetX, offsetY)' inSmalltalk: [ourCursor show]] ifFalse: [self cCode: 'ioSetCursorWithMask(cursorBitsIndex, maskBitsIndex, offsetX, offsetY)' inSmalltalk: [ourCursor show]]. self pop: argumentCount]. ! ! !Interpreter methodsFor: 'I/O primitives' stamp: 'ikp 8/3/2004 19:59'! primitiveFormPrint "On platforms that support it, this primitive prints the receiver, assumed to be a Form, to the default printer." | landscapeFlag vScale hScale rcvr bitsArray w h depth pixelsPerWord wordsPerLine bitsArraySize ok | self var: #vScale declareC: 'double vScale'. self var: #hScale declareC: 'double hScale'. landscapeFlag _ self booleanValueOf: self stackTop. vScale _ self floatValueOf: (self stackValue: 1). hScale _ self floatValueOf: (self stackValue: 2). rcvr _ self stackValue: 3. (rcvr isIntegerObject: rcvr) ifTrue: [self success: false]. successFlag ifTrue: [ ((self isPointers: rcvr) and: [(self lengthOf: rcvr) >= 4]) ifFalse: [self success: false]]. successFlag ifTrue: [ bitsArray _ self fetchPointer: 0 ofObject: rcvr. w _ self fetchInteger: 1 ofObject: rcvr. h _ self fetchInteger: 2 ofObject: rcvr. depth _ self fetchInteger: 3 ofObject: rcvr. (w > 0 and: [h > 0]) ifFalse: [self success: false]. pixelsPerWord _ 32 // depth. wordsPerLine _ (w + (pixelsPerWord - 1)) // pixelsPerWord. ((rcvr isIntegerObject: rcvr) not and: [self isWordsOrBytes: bitsArray]) ifTrue: [ bitsArraySize _ self byteLengthOf: bitsArray. self success: (bitsArraySize = (wordsPerLine * h * 4))] ifFalse: [self success: false]]. successFlag ifTrue: [ BytesPerWord = 8 ifTrue: [ok _ self cCode: 'ioFormPrint(bitsArray + 8, w, h, depth, hScale, vScale, landscapeFlag)'] ifFalse: [ok _ self cCode: 'ioFormPrint(bitsArray + 4, w, h, depth, hScale, vScale, landscapeFlag)']. self success: ok]. successFlag ifTrue: [ self pop: 3]. "pop hScale, vScale, and landscapeFlag; leave rcvr on stack" ! ! !Interpreter methodsFor: 'plugin primitives' stamp: 'tpr 3/23/2005 16:33'! primitiveExternalCall "Call an external primitive. The external primitive methods contain as first literal an array consisting of: * The module name (String | Symbol) * The function name (String | Symbol) * The session ID (SmallInteger) [OBSOLETE] * The function index (Integer) in the externalPrimitiveTable For fast failures the primitive index of any method where the external prim is not found is rewritten in the method cache with zero. This allows for ultra fast responses as long as the method stays in the cache. The fast failure response relies on lkupClass being properly set. This is done in #addToMethodCacheSel:class:method:primIndex: to compensate for execution of methods that are looked up in a superclass (such as in primitivePerformAt). With the latest modifications (e.g., actually flushing the function addresses from the VM), the session ID is obsolete. But for backward compatibility it is still kept around. Also, a failed lookup is reported specially. If a method has been looked up and not been found, the function address is stored as -1 (e.g., the SmallInteger -1 to distinguish from 16rFFFFFFFF which may be returned from the lookup). It is absolutely okay to remove the rewrite if we run into any problems later on. It has an approximate speed difference of 30% per failed primitive call which may be noticable but if, for any reasons, we run into problems (like with J3) we can always remove the rewrite. " | lit addr moduleName functionName moduleLength functionLength index | self var: #addr declareC: 'void *addr'. "Fetch the first literal of the method" self success: (self literalCountOf: newMethod) > 0. "@@: Could this be omitted for speed?!!" successFlag ifFalse: [^ nil]. lit _ self literal: 0 ofMethod: newMethod. "Check if it's an array of length 4" self success: ((self isArray: lit) and: [(self lengthOf: lit) = 4]). successFlag ifFalse: [^ nil]. "Look at the function index in case it has been loaded before" index _ self fetchPointer: 3 ofObject: lit. index _ self checkedIntegerValueOf: index. successFlag ifFalse: [^ nil]. "Check if we have already looked up the function and failed." index < 0 ifTrue: ["Function address was not found in this session, Rewrite the mcache entry with a zero primitive index." self rewriteMethodCacheSel: messageSelector class: lkupClass primIndex: 0. ^ self success: false]. "Try to call the function directly" (index > 0 and: [index <= MaxExternalPrimitiveTableSize]) ifTrue: [addr _ externalPrimitiveTable at: index - 1. addr ~= 0 ifTrue: [self rewriteMethodCacheSel: messageSelector class: lkupClass primIndex: (1000 + index) primFunction: addr. self callExternalPrimitive: addr. ^ nil]. "if we get here, then an index to the external prim was kept on the ST side although the underlying prim table was already flushed" ^ self primitiveFail]. "Clean up session id and external primitive index" self storeInteger: 2 ofObject: lit withValue: ConstZero. self storeInteger: 3 ofObject: lit withValue: ConstZero. "The function has not been loaded yet. Fetch module and function name." moduleName _ self fetchPointer: 0 ofObject: lit. moduleName = nilObj ifTrue: [moduleLength _ 0] ifFalse: [self success: (self isBytes: moduleName). moduleLength _ self lengthOf: moduleName. self cCode: '' inSmalltalk: [ (#('FloatArrayPlugin' 'Matrix2x3Plugin') includes: (self stringOf: moduleName)) ifTrue: [moduleLength _ 0 "Cause all of these to fail"]]]. functionName _ self fetchPointer: 1 ofObject: lit. self success: (self isBytes: functionName). functionLength _ self lengthOf: functionName. successFlag ifFalse: [^ nil]. "Backward compatibility: Attempt to map any old-style named primitives into the new ones. The old ones are exclusively bound into the VM so we don't need to check if a module is given." addr _ 0. "Addr ~= 0 indicates we have a compat match later" moduleLength = 0 ifTrue: ["Search the obsolete named primitive table for a match " index _ self findObsoleteNamedPrimitive: ((self pointerForOop: functionName) + BaseHeaderSize) length: functionLength. "The returned value is the index into the obsolete primitive table. If the index is found, use the 'C-style' version of the lookup. " index < 0 ifFalse: [addr _ self ioLoadFunction: (self cCoerce: ((obsoleteNamedPrimitiveTable at: index) at: 2) to: 'char*') From: (self cCoerce: ((obsoleteNamedPrimitiveTable at: index) at: 1) to: 'char*')]]. addr = 0 ifTrue: ["Only if no compat version was found" addr _ self ioLoadExternalFunction: functionName + BaseHeaderSize OfLength: functionLength FromModule: moduleName + BaseHeaderSize OfLength: moduleLength]. addr = 0 ifTrue: [index _ -1] ifFalse: ["add the function to the external primitive table" index _ self addToExternalPrimitiveTable: addr]. self success: index >= 0. "Store the index (or -1 if failure) back in the literal" self storePointer: 3 ofObject: lit withValue: (self integerObjectOf: index). "If the function has been successfully loaded process it" (successFlag and: [addr ~= 0]) ifTrue: [self rewriteMethodCacheSel: messageSelector class: lkupClass primIndex: (1000 + index) primFunction: addr. self callExternalPrimitive: addr] ifFalse: ["Otherwise rewrite the primitive index" self rewriteMethodCacheSel: messageSelector class: lkupClass primIndex: 0]! ! !Interpreter methodsFor: 'plugin primitives' stamp: 'tpr 3/23/2005 15:28'! primitiveUnloadModule "Primitive. Unload the module with the given name." "Reloading of the module will happen *later* automatically, when a function from it is called. This is ensured by invalidating current sessionID." | moduleName | self methodArgumentCount = 1 ifFalse:[^self primitiveFail]. moduleName _ self stackTop. (self isIntegerObject: moduleName) ifTrue:[^self primitiveFail]. (self isBytes: moduleName) ifFalse:[^self primitiveFail]. (self ioUnloadModule: (self oopForPointer: (self firstIndexableField: moduleName)) OfLength: (self byteSizeOf: moduleName)) ifFalse:[^self primitiveFail]. self flushExternalPrimitives. self forceInterruptCheck. self pop: 1 "pop moduleName; return receiver"! ! !Interpreter methodsFor: 'sound primitives' stamp: 'di 7/7/2004 16:21'! primitiveConstantFill "Fill the receiver, which must be an indexable bytes or words objects, with the given integer value." | fillValue rcvr rcvrIsBytes end i | fillValue _ self positive32BitValueOf: self stackTop. rcvr _ self stackValue: 1. self success: (self isWordsOrBytes: rcvr). rcvrIsBytes _ self isBytes: rcvr. rcvrIsBytes ifTrue: [self success: (fillValue >= 0 and: [fillValue <= 255])]. successFlag ifTrue: [end _ rcvr + (self sizeBitsOf: rcvr). i _ rcvr + BaseHeaderSize. rcvrIsBytes ifTrue: [[i < end] whileTrue: [self byteAt: i put: fillValue. i _ i + 1]] ifFalse: [[i < end] whileTrue: [self long32At: i put: fillValue. i _ i + 4]]. self pop: 1]! ! !Interpreter methodsFor: 'sound primitives' stamp: 'ikp 6/13/2004 22:22'! primitiveIntegerAt "Return the 32bit signed integer contents of a words receiver" | index rcvr sz addr value | index _ self stackIntegerValue: 0. rcvr _ self stackValue: 1. (self isIntegerObject: rcvr) ifTrue: [^self success: false]. (self isWords: rcvr) ifFalse: [^self success: false]. sz _ self lengthOf: rcvr. "number of fields" self success: ((index >= 1) and: [index <= sz]). successFlag ifTrue: [ addr _ rcvr + BaseHeaderSize - 4 "for zero indexing" + (index * 4). value _ self intAt: addr. self pop: 2. "pop rcvr, index" "push element value" (self isIntegerValue: value) ifTrue: [self pushInteger: value] ifFalse: [self push: (self signed32BitIntegerFor: value)]. ].! ! !Interpreter methodsFor: 'sound primitives' stamp: 'ikp 6/13/2004 22:22'! primitiveIntegerAtPut "Return the 32bit signed integer contents of a words receiver" | index rcvr sz addr value valueOop | valueOop _ self stackValue: 0. index _ self stackIntegerValue: 1. rcvr _ self stackValue: 2. (self isIntegerObject: rcvr) ifTrue:[^self success: false]. (self isWords: rcvr) ifFalse:[^self success: false]. sz _ self lengthOf: rcvr. "number of fields" ((index >= 1) and: [index <= sz]) ifFalse:[^self success: false]. (self isIntegerObject: valueOop) ifTrue:[value _ self integerValueOf: valueOop] ifFalse:[value _ self signed32BitValueOf: valueOop]. successFlag ifTrue:[ addr _ rcvr + BaseHeaderSize - 4 "for zero indexing" + (index * 4). value _ self intAt: addr put: value. self pop: 3 thenPush: valueOop. "pop all; return value" ]. ! ! !Interpreter methodsFor: 'sound primitives' stamp: 'ikp 6/11/2004 16:44'! primitiveShortAt "Treat the receiver, which can be indexible by either bytes or words, as an array of signed 16-bit values. Return the contents of the given index. Note that the index specifies the i-th 16-bit entry, not the i-th byte or word." | index rcvr sz addr value | index _ self stackIntegerValue: 0. rcvr _ self stackValue: 1. self success: ((self isIntegerObject: rcvr) not and: [self isWordsOrBytes: rcvr]). successFlag ifFalse: [ ^ nil ]. sz _ ((self sizeBitsOf: rcvr) - BaseHeaderSize) // 2. "number of 16-bit fields" self success: ((index >= 1) and: [index <= sz]). successFlag ifTrue: [ addr _ rcvr + BaseHeaderSize + (2 * (index - 1)). value _ self shortAt: addr. self pop: 2. "pop rcvr, index" self pushInteger: value. "push element value" ]! ! !Interpreter methodsFor: 'sound primitives' stamp: 'ikp 6/11/2004 16:44'! primitiveShortAtPut "Treat the receiver, which can be indexible by either bytes or words, as an array of signed 16-bit values. Set the contents of the given index to the given value. Note that the index specifies the i-th 16-bit entry, not the i-th byte or word." | index rcvr sz addr value | value _ self stackIntegerValue: 0. index _ self stackIntegerValue: 1. rcvr _ self stackValue: 2. self success: ((self isIntegerObject: rcvr) not and: [self isWordsOrBytes: rcvr]). successFlag ifFalse: [ ^ nil ]. sz _ ((self sizeBitsOf: rcvr) - BaseHeaderSize) // 2. "number of 16-bit fields" self success: ((index >= 1) and: [index <= sz]). self success: ((value >= -32768) and: [value <= 32767]). successFlag ifTrue: [ addr _ rcvr + BaseHeaderSize + (2 * (index - 1)). self shortAt: addr put: value. self pop: 2. "pop index and value; leave rcvr on stack" ]! ! !Interpreter methodsFor: 'other primitives' stamp: 'ikp 6/10/2004 12:08'! primitiveImageName "When called with a single string argument, record the string as the current image file name. When called with zero arguments, return a string containing the current image file name." | s sz sCRIfn okToRename | self var: #sCRIfn declareC: 'void *sCRIfn'. argumentCount = 1 ifTrue: [ "If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok" sCRIfn _ self ioLoadFunction: 'secCanRenameImage' From: 'SecurityPlugin'. sCRIfn ~= 0 ifTrue:[okToRename _ self cCode:' ((sqInt (*)(void))sCRIfn)()'. okToRename ifFalse:[^self primitiveFail]]. s _ self stackTop. self assertClassOf: s is: (self splObj: ClassString). successFlag ifTrue: [ sz _ self stSizeOf: s. self imageNamePut: (s + BaseHeaderSize) Length: sz. self pop: 1. "pop s, leave rcvr on stack" ]. ] ifFalse: [ sz _ self imageNameSize. s _ self instantiateClass: (self splObj: ClassString) indexableSize: sz. self imageNameGet: (s + BaseHeaderSize) Length: sz. self pop: 1. "rcvr" self push: s. ]. ! ! !Interpreter methodsFor: 'other primitives' stamp: 'ikp 6/10/2004 14:15'! primitiveObsoleteIndexedPrimitive "Primitive. Invoke an obsolete indexed primitive." | pluginName functionName functionAddress | self var: #pluginName declareC: 'char *pluginName'. self var: #functionName declareC: 'char *functionName'. self var: #functionAddress declareC: 'void *functionAddress'. functionAddress _ self cCoerce: ((obsoleteIndexedPrimitiveTable at: primitiveIndex) at: 2) to: 'void *'. functionAddress = nil ifFalse: [^self cCode: '((sqInt (*)(void))functionAddress)()' inSmalltalk: [self callExternalPrimitive: functionAddress]]. pluginName _ (obsoleteIndexedPrimitiveTable at: primitiveIndex) at: 0. functionName _ (obsoleteIndexedPrimitiveTable at: primitiveIndex) at: 1. (pluginName = nil and: [functionName = nil]) ifTrue: [^self primitiveFail]. functionAddress _ self ioLoadFunction: functionName From: pluginName. functionAddress = 0 ifFalse: ["Cache for future use" (obsoleteIndexedPrimitiveTable at: primitiveIndex) at: 2 put: (self cCoerce: functionAddress to: 'char*'). ^self cCode: '((sqInt (*)(void))functionAddress)()' inSmalltalk: [self callExternalPrimitive: functionAddress]]. ^self primitiveFail! ! !Interpreter methodsFor: 'other primitives' stamp: 'ikp 3/31/2005 11:48'! primitiveVMParameter "Behaviour depends on argument count: 0 args: return an Array of VM parameter values; 1 arg: return the indicated VM parameter; 2 args: set the VM indicated parameter. VM parameters are numbered as follows: 1 end of old-space (0-based, read-only) 2 end of young-space (read-only) 3 end of memory (read-only) 4 allocationCount (read-only) 5 allocations between GCs (read-write) 6 survivor count tenuring threshold (read-write) 7 full GCs since startup (read-only) 8 total milliseconds in full GCs since startup (read-only) 9 incremental GCs since startup (read-only) 10 total milliseconds in incremental GCs since startup (read-only) 11 tenures of surving objects since startup (read-only) 12-20 specific to the translating VM 21 root table size (read-only) 22 root table overflows since startup (read-only) 23 bytes of extra memory to reserve for VM buffers, plugins, etc. 24 memory headroom when growing object memory (rw) 25 memory threshold above which shrinking object memory (rw) 26 interruptChecksEveryNms - force an ioProcessEvents every N milliseconds, in case the image is not calling getNextEvent often (rw) 27 BytesPerWord for this image Note: Thanks to Ian Piumarta for this primitive." | mem paramsArraySize result arg index | mem _ self startOfMemory. paramsArraySize _ 27. argumentCount = 0 ifTrue: [ result _ self instantiateClass: (self splObj: ClassArray) indexableSize: paramsArraySize. 0 to: paramsArraySize - 1 do: [:i | self storePointer: i ofObject: result withValue: (self integerObjectOf: 0)]. self storePointer: 0 ofObject: result withValue: (self integerObjectOf: youngStart - mem). self storePointer: 1 ofObject: result withValue: (self integerObjectOf: freeBlock - mem). self storePointer: 2 ofObject: result withValue: (self integerObjectOf: endOfMemory - mem). self storePointer: 3 ofObject: result withValue: (self integerObjectOf: allocationCount). self storePointer: 4 ofObject: result withValue: (self integerObjectOf: allocationsBetweenGCs). self storePointer: 5 ofObject: result withValue: (self integerObjectOf: tenuringThreshold). self storePointer: 6 ofObject: result withValue: (self integerObjectOf: statFullGCs). self storePointer: 7 ofObject: result withValue: (self integerObjectOf: statFullGCMSecs). self storePointer: 8 ofObject: result withValue: (self integerObjectOf: statIncrGCs). self storePointer: 9 ofObject: result withValue: (self integerObjectOf: statIncrGCMSecs). self storePointer: 10 ofObject: result withValue: (self integerObjectOf: statTenures). self storePointer: 20 ofObject: result withValue: (self integerObjectOf: rootTableCount). self storePointer: 21 ofObject: result withValue: (self integerObjectOf: statRootTableOverflows). self storePointer: 22 ofObject: result withValue: (self integerObjectOf: extraVMMemory). self storePointer: 23 ofObject: result withValue: (self integerObjectOf: shrinkThreshold). self storePointer: 24 ofObject: result withValue: (self integerObjectOf: growHeadroom). self storePointer: 25 ofObject: result withValue: (self integerObjectOf: interruptChecksEveryNms). self storePointer: 26 ofObject: result withValue: (self integerObjectOf: BytesPerWord). self pop: 1 thenPush: result. ^nil]. arg _ self stackTop. (self isIntegerObject: arg) ifFalse: [^self primitiveFail]. arg _ self integerValueOf: arg. argumentCount = 1 ifTrue: [ "read VM parameter" (arg < 1 or: [arg > paramsArraySize]) ifTrue: [^self primitiveFail]. arg = 1 ifTrue: [result _ youngStart - mem]. arg = 2 ifTrue: [result _ freeBlock - mem]. arg = 3 ifTrue: [result _ endOfMemory - mem]. arg = 4 ifTrue: [result _ allocationCount]. arg = 5 ifTrue: [result _ allocationsBetweenGCs]. arg = 6 ifTrue: [result _ tenuringThreshold]. arg = 7 ifTrue: [result _ statFullGCs]. arg = 8 ifTrue: [result _ statFullGCMSecs]. arg = 9 ifTrue: [result _ statIncrGCs]. arg = 10 ifTrue: [result _ statIncrGCMSecs]. arg = 11 ifTrue: [result _ statTenures]. ((arg >= 12) and: [arg <= 20]) ifTrue: [result _ 0]. arg = 21 ifTrue: [result _ rootTableCount]. arg = 22 ifTrue: [result _ statRootTableOverflows]. arg = 23 ifTrue: [result _ extraVMMemory]. arg = 24 ifTrue: [result _ shrinkThreshold]. arg = 25 ifTrue: [result _ growHeadroom]. arg = 26 ifTrue: [result _ interruptChecksEveryNms]. arg = 27 ifTrue: [result _ BytesPerWord]. self pop: 2 thenPush: (self integerObjectOf: result). ^nil]. "write a VM parameter" argumentCount = 2 ifFalse: [^self primitiveFail]. index _ self stackValue: 1. (self isIntegerObject: index) ifFalse: [^self primitiveFail]. index _ self integerValueOf: index. index <= 0 ifTrue: [^self primitiveFail]. successFlag _ false. index = 5 ifTrue: [ result _ allocationsBetweenGCs. allocationsBetweenGCs _ arg. successFlag _ true]. index = 6 ifTrue: [ result _ tenuringThreshold. tenuringThreshold _ arg. successFlag _ true]. index = 23 ifTrue: [ result _ extraVMMemory. extraVMMemory _ arg. successFlag _ true]. index = 24 ifTrue: [ result _ shrinkThreshold. arg > 0 ifTrue:[ shrinkThreshold _ arg. successFlag _ true]]. index = 25 ifTrue: [ result _ growHeadroom. arg > 0 ifTrue:[ growHeadroom _ arg. successFlag _ true]]. index = 26 ifTrue: [ arg > 1 ifTrue:[ result _ interruptChecksEveryNms. interruptChecksEveryNms _ arg. successFlag _ true]]. successFlag ifTrue: [ self pop: 3 thenPush: (self integerObjectOf: result). "return old value" ^ nil]. self primitiveFail. "attempting to write a read-only parameter" ! ! !Interpreter methodsFor: 'Ian fixes for missing stuff' stamp: 'ikp 8/2/2004 18:08'! dispatchFunctionPointer: aFunctionPointer self var: #aFunctionPointer type: 'void *'. self cCode: '((void (*)(void))aFunctionPointer)()' inSmalltalk: [self error: 'my simulator should simulate me']! ! !Interpreter methodsFor: 'Ian fixes for missing stuff' stamp: 'ikp 8/2/2004 18:18'! dispatchFunctionPointerOn: primIdx in: primTable "Call the primitive at index primIdx in the primitiveTable." self var: #primTable declareC: 'void *primTable[]'. ^self dispatchFunctionPointer: (primTable at: primIdx)! ! !Interpreter methodsFor: 'bitblt support' stamp: 'ikp 6/10/2004 14:04'! copyBits "This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin_copyBits and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided" | fn | self var: #fn declareC: 'void *fn'. fn _ self ioLoadFunction: 'copyBits' From: 'BitBltPlugin'. fn = 0 ifTrue: [^self primitiveFail]. ^self cCode: '((sqInt (*)(void))fn)()'! ! !Interpreter methodsFor: 'bitblt support' stamp: 'ikp 6/10/2004 11:47'! copyBitsFrom: x0 to: x1 at: y "This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin_copyBitsFrom:to:at: and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided" | fn | self var: #fn declareC: 'void *fn'. fn _ self ioLoadFunction: 'copyBitsFromtoat' From: 'BitBltPlugin'. fn = 0 ifTrue: [^self primitiveFail]. ^self cCode: '((sqInt (*)(sqInt, sqInt, sqInt))fn)(x0, x1, y)'! ! !Interpreter methodsFor: 'bitblt support' stamp: 'ikp 6/10/2004 11:52'! loadBitBltFrom: bb "This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin_loadBitBltFrom and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided" | fn | self var: #fn declareC: 'void *fn'. fn _ self ioLoadFunction: 'loadBitBltFrom' From: 'BitBltPlugin'. fn = 0 ifTrue: [^self primitiveFail]. ^self cCode: '((sqInt (*)(sqInt))fn)(bb)'! ! !InterpreterSimulator methodsFor: 'interpreter shell' stamp: 'ikp 8/2/2004 17:59'! functionPointerFor: primIndex inClass: lookupClass "Override Interpreter to handle the external primitives caching. See also internalExecuteNewMethod." ^(primIndex between: 1 and: MaxPrimitiveIndex) ifTrue: [primitiveTable at: primIndex + 1]! ! !InterpreterSimulator methodsFor: 'interpreter shell' stamp: 'tpr 6/23/2004 15:12'! internalExecuteNewMethod "Override the Interpreter version to trap cached external prims. These have a 'prim index' of 1000 + the externalPrimitiveTableIndex normally used" primitiveIndex < 1000 ifTrue:[^super internalExecuteNewMethod]. self externalizeIPandSP. self callExternalPrimitive: (externalPrimitiveTable at: primitiveIndex - 1001). self internalizeIPandSP! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:09'! byteAtPointer: pointer "This gets implemented by Macros in C, where its types will also be checked. pointer is a raw address, and byte is an 8-bit quantity." ^ self byteAt: pointer! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:13'! byteAtPointer: pointer put: byteValue "This gets implemented by Macros in C, where its types will also be checked. pointer is a raw address, and byteValue is an 8-bit quantity." ^ self byteAt: pointer put: byteValue! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 7/17/2004 12:59'! firstIndexableField: oop "NOTE: overridden from Interpreter to add coercion to CArray" | hdr fmt totalLength fixedFields | self returnTypeC: 'void *'. hdr _ self baseHeader: oop. fmt _ (hdr >> 8) bitAnd: 16rF. totalLength _ self lengthOf: oop baseHeader: hdr format: fmt. fixedFields _ self fixedFieldsOf: oop format: fmt length: totalLength. fmt < 8 ifTrue: [fmt = 6 ifTrue: ["32 bit field objects" ^ self cCoerce: (self pointerForOop: oop + BaseHeaderSize + (fixedFields << 2)) to: 'int *']. "full word objects (pointer or bits)" ^ self cCoerce: (self pointerForOop: oop + BaseHeaderSize + (fixedFields << ShiftForWord)) to: 'oop *'] ifFalse: ["Byte objects" ^ self cCoerce: (self pointerForOop: oop + BaseHeaderSize + fixedFields) to: 'char *']! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 7/16/2004 14:56'! halfWordHighInLong32: long32 ^self subclassResponsibility! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 7/16/2004 14:57'! halfWordLowInLong32: long32 ^self subclassResponsibility! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 8/5/2004 22:09'! integerObjectOf: value "The simulator works with strictly positive bit patterns" value < 0 ifTrue: [^ ((16r80000000 + value) << 1) + 1] ifFalse: [^ (value << 1) + 1]! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 7/3/2004 10:47'! long32At: byteAddress "Return the 32-bit word at byteAddress which must be 0 mod 4." ^ self longAt: byteAddress! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 7/3/2004 10:47'! long32At: byteAddress put: a32BitValue "Store the 32-bit value at byteAddress which must be 0 mod 4." ^ self longAt: byteAddress put: a32BitValue! ! !InterpreterSimulator methodsFor: 'memory access'! longAt: byteAddress "Note: Adjusted for Smalltalk's 1-based array indexing." ^memory at: (byteAddress // 4) + 1! ! !InterpreterSimulator methodsFor: 'memory access'! longAt: byteAddress put: a32BitValue "Note: Adjusted for Smalltalk's 1-based array indexing." ^memory at: (byteAddress // 4) + 1 put: a32BitValue! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:03'! longAtPointer: pointer "This gets implemented by Macros in C, where its types will also be checked. pointer is a raw address, and the result is the width of a machine word." ^ self longAt: pointer! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:05'! longAtPointer: pointer put: longValue "This gets implemented by Macros in C, where its types will also be checked. pointer is a raw address, and longValue is the width of a machine word." ^ self longAt: pointer put: longValue! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:07'! oopForPointer: pointer "This gets implemented by Macros in C, where its types will also be checked. oop is the width of a machine word, and pointer is a raw address." ^ pointer! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:07'! pointerForOop: oop "This gets implemented by Macros in C, where its types will also be checked. oop is the width of a machine word, and pointer is a raw address." ^ oop! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:29'! shortAt: byteAddress "Return the half-word at byteAddress which must be even." ^self subclassResponsibility! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 6/23/2004 14:32'! shortAt: byteAddress put: a16BitValue ^ self subclassResponsibility! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 5/11/2004 18:29'! sqGrowMemory: oldLimit By: delta transcript show: 'grow memory from ', oldLimit printString, ' by ', delta printString; cr. memory _ memory , (memory class new: delta // 4). ^ memory size * 4! ! !InterpreterSimulator methodsFor: 'memory access' stamp: 'di 5/11/2004 18:29'! sqShrinkMemory: oldLimit By: delta transcript show: 'shrink memory from ', oldLimit printString, ' by ', delta printString, ' remember it doesn''t actually shrink in simulation'; cr. ^ oldLimit! ! !InterpreterSimulator methodsFor: 'plugin support' stamp: 'di 7/17/2004 10:23'! loadNewPlugin: pluginString | plugin simClass | transcript cr; show:'Looking for module ', pluginString. (#('FloatArrayPlugin' 'Matrix2x3Plugin') includes: pluginString) ifTrue: [transcript show: ' ... defeated'. ^ nil]. plugin _ simClass _ nil. InterpreterPlugin allSubclassesDo:[:plg| plg moduleName asString = pluginString asString ifTrue:[ simClass _ plg simulatorClass. plugin ifNil:[plugin _ simClass] ifNotNil:[plugin == simClass ifFalse:[^self error:'This won''t work...']]. ]. ]. plugin ifNil:[transcript show: ' ... not found'. ^nil]. plugin _ plugin new. plugin setInterpreter: self. "Ignore return value from setInterpreter" (plugin respondsTo: #initialiseModule) ifTrue:[ plugin initialiseModule ifFalse:[transcript show: ' ... initialiser failed'.^nil]. "module initialiser failed" ]. pluginList _ pluginList copyWith: (pluginString asString -> plugin). transcript show:' ... loaded'. ^pluginList last! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/20/2004 12:07'! allObjectsDo: objBlock | oop | oop _ self firstObject. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [objBlock value: oop]. oop _ self objectAfter: oop]. ! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/20/2004 12:11'! allObjectsSelect: objBlock "self allObjectsSelect: [:oop | (self baseHeader: oop) = 1234]" | oop selected | oop _ self firstObject. selected _ OrderedCollection new. [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [(objBlock value: oop) ifTrue: [selected addLast: oop]]. oop _ self objectAfter: oop]. ^ selected! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/21/2004 15:05'! byteCount "So you can call this from temp debug statements in, eg, Interpreter, such as self byteCount = 12661 ifTrue: [self halt]. " ^ byteCount! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/28/2004 17:24'! checkForInterrupts "Prevent interrupts so that traces are consistent during detailed debugging" true ifTrue: [^ self]. ^ super checkForInterrupts! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/21/2004 15:58'! fullDisplayUpdate "Preserve successFlag when call asynchronously from Simulator" | s | s _ successFlag. successFlag _ true. super fullDisplayUpdate. successFlag _ s! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 5/11/2004 18:26'! fullGC transcript cr; show:''.! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 14:39'! longPrint: oop | lastPtr val lastLong hdrType prevVal | (self isIntegerObject: oop) ifTrue: [^ self shortPrint: oop]. ^ String streamContents: [:strm | lastPtr _ 64*BytesPerWord min: (self lastPointerOf: oop). hdrType _ self headerType: oop. hdrType = 2 ifTrue: [lastPtr _ 0]. prevVal _ 0. (self headerStart: oop) to: lastPtr by: BytesPerWord do: [:a | val _ self longAt: oop+a. (a > 0 and: [(val = prevVal) & (a ~= lastPtr)]) ifTrue: [prevVal = (self longAt: oop+a-(BytesPerWord*2)) ifFalse: [strm cr; nextPutAll: ' ...etc...']] ifFalse: [strm cr; nextPutAll: (a<16 ifTrue: [' ', a hex] ifFalse: [a hex]); space; space; space; nextPutAll: val hex8; space; space. a = (BytesPerWord*2) negated ifTrue: [strm nextPutAll: 'size = ' , (val - hdrType) hex]. a = BytesPerWord negated ifTrue: [strm nextPutAll: '<' , (self nameOfClass: (val - hdrType)) , '>']. a = 0 ifTrue: [strm cr; tab; nextPutAll: (self dumpHeader: val)]. a > 0 ifTrue: [strm nextPutAll: (self shortPrint: val)]. a = BytesPerWord ifTrue: [(self fetchClassOf: oop) = (self splObj: ClassCompiledMethod) ifTrue: [strm cr; tab; nextPutAll: (self dumpMethodHeader: val)]]]. prevVal _ val]. lastLong _ 256 min: (self sizeBitsOf: oop) - BaseHeaderSize. hdrType = 2 ifTrue: ["free" strm cr; nextPutAll: (oop+(self longAt: oop)-2) hex; space; space; nextPutAll: (oop+(self longAt: oop)-2) printString] ifFalse: [(self formatOf: oop) = 3 ifTrue: [strm cr; tab; nextPutAll: '/ next 3 fields are above SP... /'. lastPtr+BytesPerWord to: lastPtr+(3*BytesPerWord) by: BytesPerWord do: [:a | val _ self longAt: oop+a. strm cr; nextPutAll: a hex; space; space; space; nextPutAll: val hex8; space; space. (self validOop: val) ifTrue: [strm nextPutAll: (self shortPrint: val)]]] ifFalse: [lastPtr+BytesPerWord to: lastLong by: BytesPerWord do: [:a | val _ self longAt: oop+a. strm cr; nextPutAll: (a<16 ifTrue: [' ', a hex] ifFalse: [a hex]); space; space; space. strm nextPutAll: val hex8; space; space; nextPutAll: (self charsOfLong: val)]]]. ]! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/29/2004 14:27'! lookupMethodInClass: class | currentClass dictionary found rclass | "This method overrides the interp, causing a halt on MNU." "true ifTrue: [^ super lookupMethodInClass: class]." "Defeat debug support" currentClass _ class. [currentClass ~= nilObj] whileTrue: [dictionary _ self fetchPointer: MessageDictionaryIndex ofObject: currentClass. dictionary = nilObj ifTrue: ["MethodDict pointer is nil (hopefully due a swapped out stub) -- raise exception #cannotInterpret:." self pushRemappableOop: currentClass. "may cause GC!!" self createActualMessageTo: class. currentClass _ self popRemappableOop. messageSelector _ self splObj: SelectorCannotInterpret. ^ self lookupMethodInClass: (self superclassOf: currentClass)]. found _ self lookupMethodInDictionary: dictionary. found ifTrue: [^ methodClass _ currentClass]. currentClass _ self superclassOf: currentClass]. "Could not find #doesNotUnderstand: -- unrecoverable error." messageSelector = (self splObj: SelectorDoesNotUnderstand) ifTrue: [self error: 'Recursive not understood error encountered']. self halt: (self stringOf: messageSelector). "Cound not find a normal message -- raise exception #doesNotUnderstand:" self pushRemappableOop: class. "may cause GC!!" self createActualMessageTo: class. rclass _ self popRemappableOop. messageSelector _ self splObj: SelectorDoesNotUnderstand. ^ self lookupMethodInClass: rclass! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/13/2004 07:00'! nameOfClass: classOop (self sizeBitsOf: classOop) = (Metaclass instSize +1*BytesPerWord) ifTrue: [^ (self nameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop)) , ' class']. ^ self stringOf: (self fetchPointer: 6 "name" ofObject: classOop)! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 14:48'! printStack ^ self printStack: false! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 14:49'! printStack: includeTemps | ctxt | ctxt _ activeContext. ^ String streamContents: [:strm | [self printStackFrame: ctxt onStream: strm. includeTemps ifTrue: [self printStackTemps: ctxt onStream: strm]. (ctxt _ (self fetchPointer: SenderIndex ofObject: ctxt)) = nilObj] whileFalse: []. ]! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 14:49'! printStackFrame: ctxt onStream: strm | classAndSel home | home _ (self fetchClassOf: ctxt) = (self splObj: ClassBlockContext) ifTrue: [self fetchPointer: HomeIndex ofObject: ctxt] ifFalse: [ctxt]. classAndSel _ self classAndSelectorOfMethod: (self fetchPointer: MethodIndex ofObject: home) forReceiver: (self fetchPointer: ReceiverIndex ofObject: home). strm cr; nextPutAll: ctxt hex8. ctxt = home ifFalse: [strm nextPutAll: ' [] in']. strm space; nextPutAll: (self nameOfClass: classAndSel first). strm nextPutAll: '>>'; nextPutAll: (self shortPrint: classAndSel last). ! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/20/2004 22:23'! printStackTemps: ctxt onStream: strm | home cMethod nArgs nTemps oop | home _ (self fetchClassOf: ctxt) = (self splObj: ClassBlockContext) ifTrue: [self fetchPointer: HomeIndex ofObject: ctxt] ifFalse: [ctxt]. cMethod _ self fetchPointer: MethodIndex ofObject: home. nArgs _ nTemps _ 0. home = ctxt ifTrue: [strm cr; tab; nextPutAll: 'args: '. nArgs _ self argumentCountOf: cMethod. 1 to: nArgs do: [:i | oop _ self fetchPointer: TempFrameStart + i-1 ofObject: ctxt. strm nextPutAll: oop hex; space]. strm cr; tab; nextPutAll: 'temps: '. nTemps _ self tempCountOf: cMethod. nArgs+1 to: nTemps do: [:i | oop _ self fetchPointer: TempFrameStart + i-1 ofObject: ctxt. strm nextPutAll: oop hex; space]]. strm cr; tab; nextPutAll: 'stack: '. nTemps + 1 to: (self lastPointerOf: ctxt)//BytesPerWord - TempFrameStart do: [:i | oop _ self fetchPointer: TempFrameStart + i-1 ofObject: ctxt. strm nextPutAll: oop hex; space]. ! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 15:28'! printStackWithTemps ^ self printStack: true! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/15/2004 09:21'! printTop: n "Print important fields of the top n contexts" | ctxt classAndSel home top ip sp | ctxt _ activeContext. ^ String streamContents: [:strm | 1 to: n do: [:i | home _ (self fetchClassOf: ctxt) = (self splObj: ClassBlockContext) ifTrue: [self fetchPointer: HomeIndex ofObject: ctxt] ifFalse: [ctxt]. classAndSel _ self classAndSelectorOfMethod: (self fetchPointer: MethodIndex ofObject: home) forReceiver: (self fetchPointer: ReceiverIndex ofObject: home). strm cr; nextPutAll: ctxt hex8. ctxt = home ifFalse: [strm nextPutAll: ' [] in']. strm space; nextPutAll: (self nameOfClass: classAndSel first). strm nextPutAll: '>>'; nextPutAll: (self shortPrint: classAndSel last). ctxt = activeContext ifTrue: [ip _ instructionPointer - method - (BaseHeaderSize - 2). sp _ self stackPointerIndex - TempFrameStart + 1. top _ self stackTop] ifFalse: [ip _ self integerValueOf: (self fetchPointer: InstructionPointerIndex ofObject: ctxt). sp _ self integerValueOf: (self fetchPointer: StackPointerIndex ofObject: ctxt). top _ self longAt: ctxt + (self lastPointerOf: ctxt)]. strm cr; tab; nextPutAll: 'ip = '; print: ip. strm cr; tab; nextPutAll: 'sp = '; print: sp. strm cr; tab; nextPutAll: 'top = '; nextPutAll: (self shortPrint: top). (ctxt _ (self fetchPointer: SenderIndex ofObject: ctxt)) = nilObj ifTrue: [^strm contents]. ]. ]! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 7/19/2004 14:35'! shortPrint: oop | name classOop | (self isIntegerObject: oop) ifTrue: [^ '=' , (self integerValueOf: oop) printString , ' (' , (self integerValueOf: oop) hex , ')']. classOop _ self fetchClassOf: oop. (self sizeBitsOf: classOop) = (Metaclass instSize +1*BytesPerWord) ifTrue: [ ^ 'class ' , (self nameOfClass: oop)]. name _ self nameOfClass: classOop. name size = 0 ifTrue: [name _ '??']. name = 'String' ifTrue: [^ (self stringOf: oop) printString]. name = 'Symbol' ifTrue: [^ '#' , (self stringOf: oop)]. name = 'Character' ifTrue: [^ '=' , (Character value: (self integerValueOf: (self fetchPointer: 0 ofObject: oop))) printString]. name = 'UndefinedObject' ifTrue: [^ 'nil']. name = 'False' ifTrue: [^ 'false']. name = 'True' ifTrue: [^ 'true']. name = 'Float' ifTrue: [successFlag _ true. ^ '=' , (self floatValueOf: oop) printString]. name = 'Association' ifTrue: [^ '(' , (self shortPrint: (self longAt: oop + BaseHeaderSize)) , ' -> ' , (self longAt: oop + BaseHeaderSize + BytesPerWord) hex8 , ')']. ('AEIOU' includes: name first) ifTrue: [^ 'an ' , name] ifFalse: [^ 'a ' , name]! ! !InterpreterSimulator methodsFor: 'debug support' stamp: 'di 6/13/2004 07:07'! stringOf: oop | size long nLongs chars | ^ String streamContents: [:strm | size _ 100 min: (self stSizeOf: oop). nLongs _ size-1//BytesPerWord+1. 1 to: nLongs do: [:i | long _ self longAt: oop + BaseHeaderSize + (i-1*BytesPerWord). chars _ self charsOfLong: long. strm nextPutAll: (i=nLongs ifTrue: [chars copyFrom: 1 to: size-1\\BytesPerWord+1] ifFalse: [chars])]]! ! !InterpreterSimulator methodsFor: 'I/O primitives' stamp: 'di 7/9/2004 11:05'! fullDisplay | t | displayForm == nil ifTrue: [^ self]. t _ successFlag. successFlag _ true. self displayBitsOf: (self splObj: TheDisplay) Left: 0 Top: 0 Right: displayForm width Bottom: displayForm height. successFlag _ t! ! !InterpreterSimulator methodsFor: 'I/O primitives' stamp: 'di 4/20/2004 23:59'! primitiveBeDisplay "Extended to create a scratch Form for use by showDisplayBits." | rcvr destWidth destHeight destDepth | rcvr _ self stackTop. self success: ((self isPointers: rcvr) and: [(self lengthOf: rcvr) >= 4]). successFlag ifTrue: [ destWidth _ self fetchInteger: 1 ofObject: rcvr. destHeight _ self fetchInteger: 2 ofObject: rcvr. destDepth _ self fetchInteger: 3 ofObject: rcvr. ]. successFlag ifTrue: [ "create a scratch form the same size as Smalltalk displayObj" displayForm _ Form extent: destWidth @ destHeight depth: destDepth. displayView ifNotNil: [displayView image: displayForm]. ]. super primitiveBeDisplay.! ! !InterpreterSimulator methodsFor: 'I/O primitives' stamp: 'di 4/21/2004 00:21'! primitiveMousePoint | relPt | self pop: 1. displayForm == nil ifTrue: [self push: (self makePointwithxValue: 99 yValue: 66)] ifFalse: [relPt _ Sensor cursorPoint - self displayLocation. self push: (self makePointwithxValue: relPt x yValue: relPt y)]! ! !InterpreterSimulator methodsFor: 'I/O primitives' stamp: 'di 7/6/2004 10:48'! showDisplayBits: destBits w: w h: h d: d left: left right: right top: top bottom: bottom | raster pixPerWord simDisp realDisp rect | pixPerWord _ 32 // d. raster _ displayForm width + (pixPerWord - 1) // pixPerWord. simDisp _ Form new hackBits: memory. displayForm unhibernate. realDisp _ Form new hackBits: displayForm bits. realDisp copy: (0 @ (top * raster) extent: 4 @ (bottom - top * raster)) from: 0 @ (destBits // 4 + (top * raster)) in: simDisp rule: Form over. displayView ifNotNil: [^ displayView changed]. "If running without a view, just blat the bits onto the screen..." rect _ 0 @ top corner: displayForm width @ bottom. Display copy: (rect translateBy: self displayLocation) from: rect topLeft in: displayForm rule: Form over! ! !InterpreterSimulator methodsFor: 'initialization' stamp: 'di 5/8/2004 16:42'! convertToArray "I dont believe it -- this *just works*" memory _ memory as: Array! ! !InterpreterSimulator methodsFor: 'initialization' stamp: 'di 8/5/2004 22:10'! initialize "Initialize the InterpreterSimulator when running the interpreter inside Smalltalk. The primary responsibility of this method is to allocate Smalltalk Arrays for variables that will be declared as statically-allocated global arrays in the translated code." "initialize class variables" ObjectMemory initBytesPerWord: self bytesPerWord. ObjectMemory initialize. Interpreter initialize. "Note: we must initialize ConstMinusOne differently for simulation, due to the fact that the simulator works only with +ve 32-bit values" ConstMinusOne _ self integerObjectOf: -1. methodCache _ Array new: MethodCacheSize. atCache _ Array new: AtCacheTotalSize. self flushMethodCache. rootTable _ Array new: RootTableSize. remapBuffer _ Array new: RemapBufferSize. semaphoresUseBufferA _ true. semaphoresToSignalA _ Array new: SemaphoresToSignalSize. semaphoresToSignalB _ Array new: SemaphoresToSignalSize. externalPrimitiveTable _ CArrayAccessor on: (Array new: MaxExternalPrimitiveTableSize). primitiveTable _ self class primitiveTable. obsoleteNamedPrimitiveTable _ CArrayAccessor on: (self class obsoleteNamedPrimitiveTable copyWith: (Array new: 3)). obsoleteIndexedPrimitiveTable _ CArrayAccessor on: (self class obsoleteIndexedPrimitiveTable collect:[:spec| CArrayAccessor on: (spec ifNil:[Array new: 3] ifNotNil:[Array with: spec first with: spec second with: nil])]). pluginList _ #(). mappedPluginEntries _ #(). "initialize InterpreterSimulator variables used for debugging" byteCount _ 0. sendCount _ 0. quitBlock _ [^ self]. traceOn _ true. myBitBlt _ BitBltSimulator new setInterpreter: self. filesOpen _ OrderedCollection new. headerTypeBytes _ CArrayAccessor on: (Array with: BytesPerWord*2 with: BytesPerWord with: 0 with: 0). transcript _ Transcript. displayForm _ 'Display has not yet been installed' asDisplayText form. ! ! !InterpreterSimulator methodsFor: 'initialization' stamp: 'di 7/1/2004 14:15'! openOn: fileName "(InterpreterSimulator new openOn: 'clonex.image') test" self openOn: fileName extraMemory: 2500000.! ! !InterpreterSimulator methodsFor: 'initialization' stamp: 'di 6/11/2004 13:17'! openOn: fileName extraMemory: extraBytes "InterpreterSimulator new openOn: 'clone.im' extraMemory: 100000" | f version headerSize count oldBaseAddr bytesToShift swapBytes | "open image file and read the header" ["begin ensure block..." f _ FileStream readOnlyFileNamed: fileName. imageName _ f fullName. f binary. version _ self nextLongFrom: f. "current version: 16r1966 (=6502)" (self readableFormat: version) ifTrue: [swapBytes _ false] ifFalse: [(version _ self byteSwapped: version) = self imageFormatVersion ifTrue: [swapBytes _ true] ifFalse: [self error: 'incomaptible image format']]. headerSize _ self nextLongFrom: f swap: swapBytes. endOfMemory _ self nextLongFrom: f swap: swapBytes. "first unused location in heap" oldBaseAddr _ self nextLongFrom: f swap: swapBytes. "object memory base address of image" specialObjectsOop _ self nextLongFrom: f swap: swapBytes. lastHash _ self nextLongFrom: f swap: swapBytes. "Should be loaded from, and saved to the image header" lastHash = 0 ifTrue: [lastHash _ 999]. savedWindowSize _ self nextLongFrom: f swap: swapBytes. fullScreenFlag _ self nextLongFrom: f swap: swapBytes. extraVMMemory _ self nextLongFrom: f swap: swapBytes. "allocate interpreter memory" memoryLimit _ endOfMemory + extraBytes. "read in the image in bulk, then swap the bytes if necessary" f position: headerSize. memory _ Bitmap new: memoryLimit // 4. count _ f readInto: memory startingAt: 1 count: endOfMemory // 4. count ~= (endOfMemory // 4) ifTrue: [self halt]. ] ensure: [f close]. swapBytes ifTrue: [Utilities informUser: 'Swapping bytes of foreign image...' during: [self reverseBytesInImage]]. self initialize. bytesToShift _ 0 - oldBaseAddr. "adjust pointers for zero base address" endOfMemory _ endOfMemory. Utilities informUser: 'Relocating object pointers...' during: [self initializeInterpreter: bytesToShift]. ! ! !InterpreterSimulator methodsFor: 'I/O primitives support' stamp: 'di 7/1/2004 13:55'! ioMSecs "Return the value of the millisecond clock." "NOT. Actually, we want something a lot slower and, for exact debugging, something more repeatable than real time. IO have an idea: use the byteCount..." ^ byteCount // 100 "At 20k bytecodes per second, this gives us aobut 200 ticks per second, or about 1/5 of what you'd expect for the real time clock. This should still service events at one or two per second"! ! !InterpreterSimulator methodsFor: 'I/O primitives support' stamp: 'di 8/3/2004 14:50'! sizeof: var self flag: #Dan. ^ 4! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 5/11/2004 18:26'! cr traceOn ifTrue: [ transcript cr; endEntry ].! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 5/11/2004 18:28'! print: s traceOn ifTrue: [ transcript show: s ]! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 5/11/2004 18:28'! printChar: aByte traceOn ifTrue: [ transcript nextPut: aByte asCharacter ].! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 5/11/2004 18:28'! printNum: anInteger traceOn ifTrue: [ transcript show: anInteger printString ].! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 6/15/2004 09:53'! symbolic: byte at: ip inMethod: meth "Print a bytecode in simple symbolic form" | type offset | type _ byte // 16. offset _ byte \\ 16. type=0 ifTrue: [^ 'pushRcvr ' , offset printString]. type=1 ifTrue: [^ 'pushTemp ' , offset printString]. type=2 ifTrue: [^ 'pushLit ' , offset printString]. type=3 ifTrue: [^ 'pushLit ' , (offset+16) printString]. type=4 ifTrue: [^ 'pushLitVar ' , offset printString]. type=5 ifTrue: [^ 'pushLitVar ' , (offset+16) printString]. type=6 ifTrue: [offset<8 ifTrue: [^ 'storePopRcvr ' , offset printString] ifFalse: [^ 'storePopTemp ' , (offset-8) printString]]. type=7 ifTrue: [offset=0 ifTrue: [^ 'pushRcvr']. offset<8 ifTrue: [^ 'pushConst ' , ( #(true false nil -1 0 1 2) at: offset) printString]. offset=8 ifTrue: [^ 'returnSelf']. offset<12 ifTrue: [^ 'returnConst ' , ( #(true false nil -1 0 1 2) at: offset-8) printString]. offset=12 ifTrue: [^ 'returnTop']. offset=13 ifTrue: [^ 'blockReturnTop']. offset>13 ifTrue: [^ 'unusedBytecode']]. type=8 ifTrue: [^ self symbolicExtensions: offset at: ip inMethod: meth]. type=9 ifTrue: "short jumps" [offset<8 ifTrue: [^ 'jump ' , (offset+1) printString]. ^ 'jumpIfFalse ' , (offset-8+1) printString]. type=10 ifTrue: "long jumps" [offset<8 ifTrue: [^ 'extendedJump']. offset<12 ifTrue: [^ 'extendedJumpIfTrue']. true ifTrue: [^ 'extendedJumpIfFalse']]. type=11 ifTrue: [^ 'sendSpl ' , (Smalltalk specialSelectorAt: offset+1)]. type=12 ifTrue: [^ 'sendSpl ' , (Smalltalk specialSelectorAt: offset+17)]. type>12 ifTrue: [^ 'send ' , (self stringOf: (self literal: offset))]! ! !InterpreterSimulator methodsFor: 'debug printing' stamp: 'di 6/15/2004 10:11'! symbolicExtensions: offset at: ip inMethod: meth | type offset2 byte2 byte3 | offset <=6 ifTrue: ["Extended op codes 128-134" byte2 _ self byteAt: ip+1. offset <= 2 ifTrue: ["128-130: extended pushes and pops" type _ byte2 // 64. offset2 _ byte2 \\ 64. offset = 0 ifTrue: [type = 0 ifTrue: [^ 'pushRcvr ' , offset2 printString]. type = 1 ifTrue: [^ 'pushTemp ' , offset2 printString]. type = 2 ifTrue: [^ 'pushLit ' , (offset2 + 1) printString]. type = 3 ifTrue: [^ 'pushLitVar ' , (offset2 + 1) printString]]. offset = 1 ifTrue: [type = 0 ifTrue: [^ 'storeIntoRcvr ' , offset2 printString]. type = 1 ifTrue: [^ 'storeIntoTemp ' , offset2 printString]. type = 2 ifTrue: [^ 'illegalStore']. type = 3 ifTrue: [^ 'storeIntoLitVar ' , (offset2 + 1) printString]]. offset = 2 ifTrue: [type = 0 ifTrue: [^ 'storePopRcvr ' , offset2 printString]. type = 1 ifTrue: [^ 'storePopTemp ' , offset2 printString]. type = 2 ifTrue: [^ 'illegalStore']. type = 3 ifTrue: [^ 'storePopLitVar ' , (offset2 + 1) printString]]]. "131-134: extended sends" offset = 3 ifTrue: "Single extended send" [^ 'send ' , (self stringOf: (self literal: byte2 \\ 32))]. offset = 4 ifTrue: "Double extended do-anything" [byte3 _ self byteAt: ip+2. type _ byte2 // 32. type = 0 ifTrue: [^ 'send ' , (self stringOf: (self literal: byte3))]. type = 1 ifTrue: [^ 'superSend ' , (self stringOf: (self literal: byte3))]. type = 2 ifTrue: [^ 'pushRcvr ' , byte3 printString]. type = 3 ifTrue: [^ 'pushLit ' , byte3 printString]. type = 4 ifTrue: [^ 'pushLitVar ' , byte3 printString]. type = 5 ifTrue: [^ 'storeIntoRcvr ' , byte3 printString]. type = 6 ifTrue: [^ 'storePopRcvr ' , byte3 printString]. type = 7 ifTrue: [^ 'storeIntoLitVar ' , byte3 printString]]. offset = 5 ifTrue: "Single extended send to super" [^ 'superSend ' , (self stringOf: (self literal: byte2 \\ 32))]. offset = 6 ifTrue: "Second extended send" [^ 'send ' , (self stringOf: (self literal: byte2 \\ 64))]]. offset = 7 ifTrue: [^ 'doPop']. offset = 8 ifTrue: [^ 'doDup']. offset = 9 ifTrue: [^ 'pushActiveContext']. ^ 'unusedBytecode'! ! !InterpreterSimulator methodsFor: 'float primitives' stamp: 'di 6/13/2004 10:31'! fetchFloatAt: floatBitsAddress into: aFloat aFloat at: 1 put: (self long32At: floatBitsAddress). aFloat at: 2 put: (self long32At: floatBitsAddress+4). ! ! !InterpreterSimulator methodsFor: 'float primitives' stamp: 'di 6/13/2004 10:45'! storeFloatAt: floatBitsAddress from: aFloat. self long32At: floatBitsAddress put: (aFloat at: 1). self long32At: floatBitsAddress+4 put: (aFloat at: 2). ! ! !InterpreterSimulator methodsFor: 'file primitives' stamp: 'di 7/2/2004 12:35'! primitiveDirectoryLookup | index pathName array result | index _ self stackIntegerValue: 0. pathName _ (self stringOf: (self stackValue: 1)). successFlag ifFalse: [ ^self primitiveFail. ]. array _ FileDirectory default primLookupEntryIn: pathName index: index. array == nil ifTrue: [ self pop: 3. self push: nilObj. ^array. ]. array == #badDirectoryPath ifTrue: [self halt. ^self primitiveFail. ]. result _ self makeDirEntryName: (array at: 1) size: (array at: 1) size createDate: (array at: 2) modDate: (array at: 3) isDir: (array at: 4) fileSize: (array at: 5). self pop: 3. self push: result. ! ! !InterpreterSimulator methodsFor: 'file primitives' stamp: 'di 7/2/2004 14:20'! primitiveImageName "Note: For now, this only implements getting, not setting, the image file name." | result imageNameSize | self pop: 1. imageNameSize _ imageName size. result _ self instantiateClass: (self splObj: ClassString) indexableSize: imageNameSize. 1 to: imageNameSize do: [:i | self storeByte: i-1 ofObject: result withValue: (imageName at: i) asciiValue]. self push: result.! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/21/2004 15:40'! logOfBytesVerify: nBytes fromFileNamed: fileName fromStart: loggingStart "Verify a questionable interpreter against a successful run" "self logOfBytesVerify: 10000 fromFileNamed: 'clone32Bytecodes.log' " | logFile rightByte prevCtxt | logFile _ (FileStream readOnlyFileNamed: fileName) binary. logging _ loggingStart. transcript clear. byteCount _ 0. quitBlock _ [^ self]. self internalizeIPandSP. self fetchNextBytecode. prevCtxt _ 0. prevCtxt _ prevCtxt. [byteCount < nBytes] whileTrue: [ " byteCount > 14560 ifTrue: [self externalizeIPandSP. prevCtxt = activeContext ifFalse: [prevCtxt _ activeContext. transcript cr; nextPutAll: (self printTop: 2); endEntry]. transcript cr; print: byteCount; nextPutAll: ': ' , (activeContext hex); space; print: (instructionPointer - method - (BaseHeaderSize - 2)); nextPutAll: ': <' , (self byteAt: localIP) hex , '>'; space; nextPutAll: (self symbolic: currentBytecode at: localIP inMethod: method); space; print: (self stackPointerIndex - TempFrameStart + 1); endEntry. byteCount = 14590 ifTrue: [self halt]]. " logging ifTrue: [rightByte _ logFile next. currentBytecode = rightByte ifFalse: [self halt]]. self dispatchOn: currentBytecode in: BytecodeTable. byteCount _ byteCount + 1. byteCount \\ 10000 = 0 ifTrue: [self fullDisplayUpdate]]. self externalizeIPandSP. logFile close. self inform: nBytes printString , ' bytecodes verfied.'! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/21/2004 15:52'! logOfBytesWrite: nBytes toFileNamed: fileName fromStart: loggingStart "Write a log file for testing a flaky interpreter on the same image" "self logOfBytesWrite: 10000 toFileNamed: 'clone32Bytecodes.log' " | logFile | logFile _ (FileStream newFileNamed: fileName) binary. logging _ loggingStart. transcript clear. byteCount _ 0. quitBlock _ [^ self]. self internalizeIPandSP. self fetchNextBytecode. [logging not or: [byteCount < nBytes]] whileTrue: [logging ifTrue: [logFile nextPut: currentBytecode]. self dispatchOn: currentBytecode in: BytecodeTable. byteCount _ byteCount + 1. byteCount \\ 10000 = 0 ifTrue: [self fullDisplayUpdate]]. self externalizeIPandSP. logFile close. ! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/21/2004 15:39'! logOfSendsVerify: nSends fromFileNamed: fileName fromStart: loggingStart "Write a log file for testing a flaky interpreter on the same image" "self logOfSendsWrite: 10000 toFileNamed: 'clone32Messages.log' " | logFile priorContext rightSelector prevCtxt | logFile _ FileStream readOnlyFileNamed: fileName. logging _ loggingStart. transcript clear. byteCount _ 0. sendCount _ 0. priorContext _ activeContext. quitBlock _ [^ self]. self internalizeIPandSP. self fetchNextBytecode. prevCtxt _ 0. prevCtxt _ prevCtxt. [sendCount < nSends] whileTrue: [ " byteCount>500 ifTrue: [byteCount>550 ifTrue: [self halt]. self externalizeIPandSP. prevCtxt = activeContext ifFalse: [prevCtxt _ activeContext. transcript cr; nextPutAll: (self printTop: 2); endEntry]. transcript cr; print: byteCount; nextPutAll: ': ' , (activeContext hex); space; print: (instructionPointer - method - (BaseHeaderSize - 2)); nextPutAll: ': <' , (self byteAt: localIP) hex , '>'; space; nextPutAll: (self symbolic: currentBytecode at: localIP inMethod: method); space; print: (self stackPointerIndex - TempFrameStart + 1); endEntry. ]. " self dispatchOn: currentBytecode in: BytecodeTable. activeContext == priorContext ifFalse: [sendCount _ sendCount + 1. logging ifTrue: [rightSelector _ logFile nextLine. (self stringOf: messageSelector) = rightSelector ifFalse: [self halt]]. priorContext _ activeContext]. byteCount _ byteCount + 1. byteCount \\ 10000 = 0 ifTrue: [self fullDisplayUpdate]]. self externalizeIPandSP. logFile close. self inform: nSends printString , ' sends verfied.'! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/21/2004 15:53'! logOfSendsWrite: nSends toFileNamed: fileName fromStart: loggingStart "Write a log file for testing a flaky interpreter on the same image" "self logOfSendsWrite: 10000 toFileNamed: 'clone32Messages.log' " | logFile priorContext | logFile _ FileStream newFileNamed: fileName. logging _ loggingStart. transcript clear. byteCount _ 0. sendCount _ 0. priorContext _ activeContext. quitBlock _ [^ self]. self internalizeIPandSP. self fetchNextBytecode. [logging not or: [sendCount < nSends]] whileTrue: [self dispatchOn: currentBytecode in: BytecodeTable. activeContext == priorContext ifFalse: [logging ifTrue: [sendCount _ sendCount + 1. logFile nextPutAll: (self stringOf: messageSelector); cr]. priorContext _ activeContext]. byteCount _ byteCount + 1. byteCount \\ 10000 = 0 ifTrue: [self fullDisplayUpdate]]. self externalizeIPandSP. logFile close. ! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 5/11/2004 18:28'! profile: nBytecodes "(InterpreterSimulator new openOn: 'clonex.image') profile: 60000" transcript clear. byteCount _ 0. MessageTally spyOn: [self runForNBytes: nBytecodes]. self close! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 8/3/2004 14:52'! stats | oop fieldAddr fieldOop last stats v d | stats _ Bag new. oop _ self firstObject. 'Scanning the image...' displayProgressAt: Sensor cursorPoint from: oop to: endOfMemory during: [:bar | [oop < endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [stats add: #objects. fieldAddr _ oop + (self lastPointerOf: oop). [fieldAddr > oop] whileTrue: [fieldOop _ self longAt: fieldAddr. (self isIntegerObject: fieldOop) ifTrue: [v _ self integerValueOf: fieldOop. (v between: -16000 and: 16000) ifTrue: [stats add: #ints32k] ifFalse: [stats add: #intsOther]] ifFalse: [fieldOop = nilObj ifTrue: [stats add: #nil] ifFalse: [d _ fieldOop - oop. (d between: -16000 and: 16000) ifTrue: [stats add: #oops32k] ifFalse: [stats add: #oopsOther]]]. fieldAddr _ fieldAddr - BytesPerWord]]. bar value: oop. last _ oop. last _ last. oop _ self objectAfter: oop]]. ^ stats sortedElements! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/19/2004 17:30'! test transcript clear. byteCount _ 0. quitBlock _ [^ self]. self internalizeIPandSP. self fetchNextBytecode. [true] whileTrue: [self dispatchOn: currentBytecode in: BytecodeTable. byteCount _ byteCount + 1. byteCount \\ 10000 = 0 ifTrue: [self fullDisplay]]. self externalizeIPandSP. ! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 5/11/2004 18:30'! validate | oop prev | transcript show: 'Validating...'. oop _ self firstObject. [oop < endOfMemory] whileTrue: [ self validate: oop. prev _ oop. "look here if debugging prev obj overlapping this one" oop _ self objectAfter: oop. ]. prev _ prev. "Don't offer to delete this please" transcript show: 'done.'; cr! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'di 7/1/2004 17:29'! validate: oop | header type cc sz fmt nextChunk | header _ self longAt: oop. type _ header bitAnd: 3. type = 2 ifFalse: [type = (self rightType: header) ifFalse: [self halt]]. sz _ (header bitAnd: SizeMask) >> 2. (self isFreeObject: oop) ifTrue: [ nextChunk _ oop + (self sizeOfFree: oop) ] ifFalse: [ nextChunk _ oop + (self sizeBitsOf: oop) ]. nextChunk > endOfMemory ifTrue: [oop = endOfMemory ifFalse: [self halt]]. (self headerType: nextChunk) = 0 ifTrue: [ (self headerType: (nextChunk + (BytesPerWord*2))) = 0 ifFalse: [self halt]]. (self headerType: nextChunk) = 1 ifTrue: [ (self headerType: (nextChunk + BytesPerWord)) = 1 ifFalse: [self halt]]. type = 2 ifTrue: ["free block" ^ self]. fmt _ (header >> 8) bitAnd: 16rF. cc _ (header >> 12) bitAnd: 31. cc > 16 ifTrue: [self halt]. "up to 32 are legal, but not used" type = 0 ifTrue: ["three-word header" ((self longAt: oop-BytesPerWord) bitAnd: 3) = type ifFalse: [self halt]. ((self longAt: oop-(BytesPerWord*2)) bitAnd: 3) = type ifFalse: [self halt]. ((self longAt: oop-BytesPerWord) = type) ifTrue: [self halt]. "Class word is 0" sz = 0 ifFalse: [self halt]]. type = 1 ifTrue: ["two-word header" ((self longAt: oop-BytesPerWord) bitAnd: 3) = type ifFalse: [self halt]. cc > 0 ifTrue: [sz = 1 ifFalse: [self halt]]. sz = 0 ifTrue: [self halt]]. type = 3 ifTrue: ["one-word header" cc = 0 ifTrue: [self halt]]. fmt = 5 ifTrue: [self halt]. fmt = 7 ifTrue: [self halt]. fmt >= 12 ifTrue: ["CompiledMethod -- check for integer header" (self isIntegerObject: (self longAt: oop + BytesPerWord)) ifFalse: [self halt]].! ! !InterpreterSimulator methodsFor: 'testing' stamp: 'ikp 8/3/2004 18:43'! validateOopsIn: object | fieldPtr limit former header | "for each oop in me see if it is legal" fieldPtr _ object + BaseHeaderSize. "first field" limit _ object + (self lastPointerOf: object). "a good field" [fieldPtr > limit] whileFalse: [ former _ self longAt: fieldPtr. (self validOop: former) ifFalse: [self error: 'invalid oop in pointers object']. fieldPtr _ fieldPtr + BytesPerWord]. "class" header _ self baseHeader: object. (header bitAnd: CompactClassMask) = 0 ifTrue: [ former _ (self classHeader: object) bitAnd: AllButTypeMask. (self validOop: former) ifFalse: [self halt]].! ! !InterpreterSimulator methodsFor: 'other primitives' stamp: 'di 7/4/2004 09:01'! primBitmapdecompressfromByteArrayat | indexInt index baOop bmOop baSize bmSize ba bm | indexInt _ self stackTop. (self isIntegerValue: indexInt) ifFalse: [^ self primitiveFail]. index _ self integerValueOf: indexInt. baOop _ self stackValue: 1. bmOop _ self stackValue: 2. baSize _ self stSizeOf: baOop. bmSize _ self stSizeOf: bmOop. ba _ ByteArray new: baSize. bm _ Bitmap new: bmSize. "Copy the byteArray into ba" 1 to: baSize do: [:i | ba at: i put: (self fetchByte: i-1 ofObject: baOop)]. "Decompress ba into bm" bm decompress: bm fromByteArray: ba at: index. "Then copy bm into the Bitmap" 1 to: bmSize do: [:i | self storeLong32: i-1 ofObject: bmOop withValue: (bm at: i)]. self pop: 3! ! !InterpreterSimulator methodsFor: 'image save/restore' stamp: 'di 8/3/2004 14:57'! writeImageFileIO: numberOfBytesToWrite "Actually emit the first numberOfBytesToWrite object memory bytes onto the snapshot." | headerSize file | BytesPerWord = 4 ifFalse: [self error: 'Not rewritten for 64 bits yet']. headerSize _ 64. [ file _ (FileStream fileNamed: imageName) binary. file == nil ifTrue: [^nil]. { self imageFormatVersion. headerSize. numberOfBytesToWrite. self startOfMemory. specialObjectsOop. lastHash. self ioScreenSize. fullScreenFlag. extraVMMemory } do: [:long | self putLong: long toFile: file]. "Pad the rest of the header." 7 timesRepeat: [self putLong: 0 toFile: file]. "Position the file after the header." file position: headerSize. "Write the object memory." 1 to: numberOfBytesToWrite // 4 do: [:index | self putLong: (memory at: index) toFile: file]. self success: true ] ensure: [file close]! ! !InterpreterSimulator methodsFor: 'debugging traps' stamp: 'di 7/20/2004 11:58'! allocate: byteSize headerSize: hdrSize h1: baseHeader h2: classOop h3: extendedSize doFill: doFill with: fillWord | newObj | newObj _ super allocate: byteSize headerSize: hdrSize h1: baseHeader h2: classOop h3: extendedSize doFill: doFill with: fillWord. "byteCount < 600000 ifTrue: [^ newObj]." "(self baseHeader: newObj) = 16r0FCC0600 ifTrue: [self halt]." ^ newObj! ! !InterpreterSimulator methodsFor: 'debugging traps' stamp: 'di 7/22/2004 18:36'! normalSend "Catch errors before we start the whole morphic error process" "(byteCount > 4000000 and: [(self stringOf: messageSelector) = 'sorts:before:']) ifTrue: [self halt]." ^ super normalSend! ! !InterpreterSimulator methodsFor: 'debugging traps' stamp: 'di 7/20/2004 10:57'! primitiveFail "(primitiveIndex = 61 and: [byteCount > 210000]) ifTrue: [self halt]." successFlag _ false.! ! !InterpreterSimulator methodsFor: 'debugging traps' stamp: 'di 7/22/2004 12:31'! primitiveResume "Catch errors before we start the whole morphic error process" byteCount > 1000000 ifTrue: [self halt]. "Ignore early process activity" ^ super primitiveResume! ! !InterpreterSimulator methodsFor: 'debugging traps' stamp: 'di 7/22/2004 12:31'! primitiveSuspend "Catch errors before we start the whole morphic error process" byteCount > 1000000 ifTrue: [self halt]. "Ignore early process activity" ^ super primitiveSuspend! ! !InterpreterSimulator methodsFor: 'UI' stamp: 'di 4/21/2004 00:09'! byteCountText ^ byteCount printString asText! ! !InterpreterSimulator methodsFor: 'UI' stamp: 'di 4/21/2004 00:31'! openAsMorph "Open a morphic view on this simulation." | window localImageName | localImageName _ FileDirectory default localNameFor: imageName. window _ (SystemWindow labelled: 'Simulation of ' , localImageName) model: self. window addMorph: (displayView _ ImageMorph new image: displayForm) frame: (0@0 corner: 1@0.8). transcript _ TranscriptStream on: (String new: 10000). window addMorph: (PluggableTextMorph on: transcript text: nil accept: nil readSelection: nil menu: #codePaneMenu:shifted:) frame: (0@0.8 corner: 0.7@1). window addMorph: (PluggableTextMorph on: self text: #byteCountText accept: nil) hideScrollBarIndefinitely frame: (0.7@0.8 corner: 1@1). window openInWorld! ! !InterpreterSimulatorLSB methodsFor: 'memory access' stamp: 'di 7/16/2004 14:59'! halfWordHighInLong32: long32 "Used by Balloon" ^ long32 bitAnd: 16rFFFF! ! !InterpreterSimulatorLSB methodsFor: 'memory access' stamp: 'di 7/16/2004 14:59'! halfWordLowInLong32: long32 "Used by Balloon" ^ long32 bitShift: -16! ! !InterpreterSimulatorLSB methodsFor: 'memory access' stamp: 'di 6/23/2004 14:29'! shortAt: byteAddress "Return the half-word at byteAddress which must be even." | lowBits long | lowBits _ byteAddress bitAnd: 2. long _ self longAt: byteAddress - lowBits. ^ lowBits = 2 ifTrue: [ long bitShift: -16 ] ifFalse: [ long bitAnd: 16rFFFF ]. ! ! !InterpreterSimulatorLSB methodsFor: 'memory access' stamp: 'di 6/23/2004 14:31'! shortAt: byteAddress put: a16BitValue "Return the half-word at byteAddress which must be even." | lowBits long longAddress | lowBits _ byteAddress bitAnd: 2. lowBits = 0 ifTrue: [ "storing into LS word" long _ self longAt: byteAddress. self longAt: byteAddress put: ((long bitAnd: 16rFFFF0000) bitOr: a16BitValue) ] ifFalse: [longAddress _ byteAddress - 2. long _ self longAt: longAddress. self longAt: longAddress put: ((long bitAnd: 16rFFFF) bitOr: (a16BitValue bitShift: 16)) ]! ! !InterpreterSimulatorLSB methodsFor: 'initialization' stamp: 'di 6/22/2004 14:53'! nextLongFrom: aStream "Read a 32- or 64-bit quantity from the given (binary) stream." ^ aStream nextLittleEndianNumber: BytesPerWord! ! !InterpreterSimulatorLSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/13/2004 10:55'! bytesPerWord "overridden for 64-bit images..." ^ 8! ! !InterpreterSimulatorLSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/13/2004 10:56'! long32At: byteAddress "Return the 32-bit word at byteAddress which must be 0 mod 4." | lowBits long | lowBits _ byteAddress bitAnd: 4. long _ self longAt: byteAddress - lowBits. ^ lowBits = 4 ifTrue: [ long bitShift: -32 ] ifFalse: [ long bitAnd: 16rFFFFFFFF ]. ! ! !InterpreterSimulatorLSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/13/2004 11:01'! long32At: byteAddress put: a32BitValue "Store the 32-bit value at byteAddress which must be 0 mod 4." | lowBits long64 longAddress | lowBits _ byteAddress bitAnd: 4. lowBits = 0 ifTrue: [ "storing into LS word" long64 _ self longAt: byteAddress. self longAt: byteAddress put: ((long64 bitAnd: 16rFFFFFFFF00000000) bitOr: a32BitValue) ] ifFalse: [longAddress _ byteAddress - 4. long64 _ self longAt: longAddress. self longAt: longAddress put: ((long64 bitAnd: 16rFFFFFFFF) bitOr: (a32BitValue bitShift: 32)) ]! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 6/22/2004 14:52'! byteAt: byteAddress | lowBits bpwMinus1 | bpwMinus1 _ BytesPerWord-1. lowBits _ byteAddress bitAnd: bpwMinus1. ^ ((self longAt: byteAddress - lowBits) bitShift: (lowBits - bpwMinus1) * 8) bitAnd: 16rFF! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 7/3/2004 11:00'! byteAt: byteAddress put: byte | longWord shift lowBits bpwMinus1 longAddress | bpwMinus1 _ BytesPerWord-1. lowBits _ byteAddress bitAnd: bpwMinus1. longAddress _ byteAddress - lowBits. longWord _ self longAt: longAddress. shift _ (bpwMinus1 - lowBits) * 8. longWord _ longWord - (longWord bitAnd: (16rFF bitShift: shift)) + (byte bitShift: shift). self longAt: longAddress put: longWord! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 7/16/2004 14:58'! halfWordHighInLong32: long32 "Used by Balloon" ^ long32 bitShift: -16! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 7/16/2004 14:58'! halfWordLowInLong32: long32 "Used by Balloon" ^ long32 bitAnd: 16rFFFF! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 7/3/2004 11:06'! shortAt: byteAddress "Return the half-word at byteAddress which must be even." | lowBits bpwMinus2 | bpwMinus2 _ BytesPerWord-2. lowBits _ byteAddress bitAnd: bpwMinus2. ^ ((self longAt: byteAddress - lowBits) bitShift: (lowBits - bpwMinus2) * 8) bitAnd: 16rFFFF ! ! !InterpreterSimulatorMSB methodsFor: 'memory access' stamp: 'di 7/3/2004 11:00'! shortAt: byteAddress put: a16BitValue "Return the half-word at byteAddress which must be even." | longWord shift lowBits bpwMinus2 longAddress | bpwMinus2 _ BytesPerWord-2. lowBits _ byteAddress bitAnd: bpwMinus2. longAddress _ byteAddress - lowBits. longWord _ self longAt: longAddress. shift _ (bpwMinus2 - lowBits) * 8. longWord _ longWord - (longWord bitAnd: (16rFFFF bitShift: shift)) + (a16BitValue bitShift: shift). self longAt: longAddress put: longWord ! ! !InterpreterSimulatorMSB methodsFor: 'debug support' stamp: 'di 6/22/2004 14:52'! charsOfLong: long ^ (BytesPerWord to: 1 by: -1) collect: [:i | ((long digitAt: i) between: 14 and: 126) ifTrue: [(long digitAt: i) asCharacter] ifFalse: [$?]]! ! !InterpreterSimulatorMSB methodsFor: 'initialization' stamp: 'di 6/22/2004 14:52'! nextLongFrom: aStream "Read a 32- or 64-bit quantity from the given (binary) stream." ^ aStream nextNumber: BytesPerWord! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/9/2004 12:17'! byteSwapped: w "Return the given integer with its bytes in the reverse order." ^ (super byteSwapped: ((w bitShift: -32) bitAnd: 16rFFFFFFFF)) + ((super byteSwapped: (w bitAnd: 16rFFFFFFFF)) bitShift: 32)! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/3/2004 16:16'! bytesPerWord "overridden for 64-bit images..." ^ 8! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 7/3/2004 10:40'! long32At: byteAddress "Return the 32-bit word at byteAddress which must be 0 mod 4." ^ super longAt: byteAddress! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 7/3/2004 10:41'! long32At: byteAddress put: a32BitValue "Store the 32-bit value at byteAddress which must be 0 mod 4." super longAt: byteAddress put: a32BitValue! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/9/2004 15:43'! longAt: byteAddress "Note: Adjusted for Smalltalk's 1-based array indexing." ^ ((super longAt: byteAddress) bitShift: 32) bitOr: (super longAt: byteAddress + 4)! ! !InterpreterSimulatorMSB64 methodsFor: 'as yet unclassified' stamp: 'di 6/9/2004 15:48'! longAt: byteAddress put: a64BitValue "Note: Adjusted for Smalltalk's 1-based array indexing." super longAt: byteAddress put: (a64BitValue bitShift: -32). super longAt: byteAddress + 4 put: (a64BitValue bitAnd: 16rFFFFFFFF). ^ a64BitValue! ! !ObjectMemory class methodsFor: 'translation' stamp: 'ikp 3/26/2005 14:20'! declareCVarsIn: aCCodeGenerator aCCodeGenerator var: #memory type:#'usqInt'. aCCodeGenerator var: #remapBuffer declareC: 'sqInt remapBuffer[', (RemapBufferSize + 1) printString, ']'. aCCodeGenerator var: #rootTable declareC: 'sqInt rootTable[', (RootTableSize + 1) printString, ']'. aCCodeGenerator var: #headerTypeBytes declareC: 'sqInt headerTypeBytes[4]'. aCCodeGenerator var: #youngStart type: 'usqInt'. aCCodeGenerator var: #endOfMemory type: 'usqInt'. aCCodeGenerator var: #memoryLimit type: 'usqInt'. aCCodeGenerator var: #youngStartLocal type: 'usqInt'. ! ! !ObjectMemory class methodsFor: 'translation' stamp: 'ikp 8/3/2004 20:17'! unsignedIntegerSuffix "Answer the suffix that should be appended to unsigned integer literals in generated code." ^BytesPerWord = 4 ifTrue: ['U'] ifFalse: ['ULL']! ! !ObjectMemory class methodsFor: 'initialization' stamp: 'ikp 9/22/2004 12:05'! initBytesPerWord: nBytes BytesPerWord _ nBytes. ShiftForWord _ (BytesPerWord log: 2) rounded. "The following is necessary to avoid confusing the compiler with shifts that are larger than the width of the type on which they operate. In gcc, such shifts cause incorrect code to be generated." BytesPerWord = 8 ifTrue: "64-bit VM" [Byte0Mask _ 16r00000000000000FF. Byte0Shift _ 0. Byte1Mask _ 16r000000000000FF00. Byte1Shift _ 8. Byte2Mask _ 16r0000000000FF0000. Byte2Shift _ 16. Byte3Mask _ 16r00000000FF000000. Byte3Shift _ 24. Byte4Mask _ 16r000000FF00000000. Byte4Shift _ 32. Byte5Mask _ 16r0000FF0000000000. Byte5Shift _ 40. Byte6Mask _ 16r00FF000000000000. Byte6Shift _ 48. Byte7Mask _ 16rFF00000000000000. Byte7Shift _ 56. Bytes3to0Mask _ 16r00000000FFFFFFFF. Bytes7to4Mask _ 16rFFFFFFFF00000000] ifFalse: "32-bit VM" [Byte0Mask _ 16r00000000000000FF. Byte0Shift _ 0. Byte1Mask _ 16r000000000000FF00. Byte1Shift _ 8. Byte2Mask _ 16r0000000000FF0000. Byte2Shift _ 16. Byte3Mask _ 16r00000000FF000000. Byte3Shift _ 24. Byte4Mask _ 16r0000000000000000. Byte4Shift _ 0. "unused" Byte5Mask _ 16r0000000000000000. Byte5Shift _ 0. "unused" Byte6Mask _ 16r0000000000000000. Byte6Shift _ 0. "unused" Byte7Mask _ 16r0000000000000000. Byte7Shift _ 0. "unused" Bytes3to0Mask _ 16r0000000000000000. "unused" Bytes7to4Mask _ 16r0000000000000000 "unused"]. Byte1ShiftNegated _ Byte1Shift negated. Byte3ShiftNegated _ Byte3Shift negated. Byte4ShiftNegated _ Byte4Shift negated. Byte5ShiftNegated _ Byte5Shift negated. Byte7ShiftNegated _ Byte7Shift negated.! ! !ObjectMemory class methodsFor: 'initialization' stamp: 'di 7/20/2004 10:50'! initialize "ObjectMemory initialize" "Translation flags (booleans that control code generation via conditional translation):" DoAssertionChecks _ false. "generate assertion checks" DoBalanceChecks _ false. "generate stack balance checks" self initializeSpecialObjectIndices. self initializeObjectHeaderConstants. CtxtTempFrameStart _ 6. "Copy of TempFrameStart in Interp" ContextFixedSizePlusHeader _ CtxtTempFrameStart + 1. SmallContextSize _ ContextFixedSizePlusHeader + 16 * BytesPerWord. "16 indexable fields" "Large contexts have 56 indexable fileds. Max with single header word." "However note that in 64 bits, for now, large contexts have 3-word headers" LargeContextSize _ ContextFixedSizePlusHeader + 56 * BytesPerWord. LargeContextBit _ 16r40000. "This bit set in method headers if large context is needed." NilContext _ 1. "the oop for the integer 0; used to mark the end of context lists" RemapBufferSize _ 25. RootTableSize _ 2500. "number of root table entries (4 bytes/entry)" RootTableRedZone _ RootTableSize - 100. "red zone of root table - when reached we force IGC" "tracer actions" StartField _ 1. StartObj _ 2. Upward _ 3. Done _ 4.! ! !ObjectMemory class methodsFor: 'initialization' stamp: 'di 7/1/2004 14:44'! initializeObjectHeaderConstants BytesPerWord ifNil: [BytesPerWord _ 4]. "May get called on fileIn, so supply default" BaseHeaderSize _ BytesPerWord. WordMask _ (1 bitShift: BytesPerWord*8) - 1. "masks for type field" TypeMask _ 3. AllButTypeMask _ WordMask - TypeMask. "type field values" HeaderTypeSizeAndClass _ 0. HeaderTypeClass _ 1. HeaderTypeFree _ 2. HeaderTypeShort _ 3. "type field values used during the mark phase of GC" HeaderTypeGC _ 2. GCTopMarker _ 3. "neither an oop, nor an oop+1, this value signals that we have crawled back up to the top of the marking phase." "Base header word bit fields" HashBits _ 16r1FFE0000. AllButHashBits _ WordMask - HashBits. HashBitsOffset _ 17. SizeMask _ 16rFC. Size4Bit _ 0. BytesPerWord = 8 ifTrue: [SizeMask _ 16rF8. "Lose the 4 bit in temp 64-bit chunk format" Size4Bit _ 4]. "But need it for ST size" "Note SizeMask + Size4Bit gives the mask needed for size fits of format word in classes. This is used in instantiateClass:indexableSize: " LongSizeMask _ WordMask - 16rFF + SizeMask. CompactClassMask _ 16r1F000. "masks for root and mark bits" MarkBit _ 1 bitShift: BytesPerWord*8 - 1. "Top bit" RootBit _ 1 bitShift: BytesPerWord*8 - 2. "Next-to-Top bit" AllButMarkBit _ WordMask - MarkBit. AllButRootBit _ WordMask - RootBit. AllButMarkBitAndTypeMask _ AllButTypeMask - MarkBit.! ! !ObjectMemory class methodsFor: 'accessing' stamp: 'ikp 9/2/2004 14:08'! bytesPerWord "Answer the width of an object pointer, in bytes." ^BytesPerWord! ! !Interpreter class methodsFor: 'translation' stamp: 'tpr 3/17/2005 11:36'! declareCVarsIn: aCCodeGenerator aCCodeGenerator var: #interpreterProxy type: #'struct VirtualMachine*'. aCCodeGenerator var: #primitiveTable declareC: 'void *primitiveTable[', (MaxPrimitiveIndex +2) printString, '] = ', self primitiveTableString. aCCodeGenerator var: #primitiveFunctionPointer declareC: 'void *primitiveFunctionPointer' . "xxxx FIX THIS STUPIDITY xxxx - ikp. What he means is use a better type than void *, apparently - tpr" aCCodeGenerator var: #methodCache declareC: 'long methodCache[', (MethodCacheSize + 1) printString, ']'. aCCodeGenerator var: #atCache declareC: 'sqInt atCache[', (AtCacheTotalSize + 1) printString, ']'. aCCodeGenerator var: #localIP type: #'char*'. aCCodeGenerator var: #localSP type: #'char*'. aCCodeGenerator var: #showSurfaceFn type: #'void*'. aCCodeGenerator var: 'semaphoresToSignalA' declareC: 'sqInt semaphoresToSignalA[', (SemaphoresToSignalSize + 1) printString, ']'. aCCodeGenerator var: 'semaphoresToSignalB' declareC: 'sqInt semaphoresToSignalB[', (SemaphoresToSignalSize + 1) printString, ']'. aCCodeGenerator var: #compilerHooks declareC: 'sqInt (*compilerHooks[', (CompilerHooksSize + 1) printString, '])()'. aCCodeGenerator var: #interpreterVersion declareC: 'const char *interpreterVersion = "', Smalltalk datedVersion, ' [', Smalltalk lastUpdateString,']"'. aCCodeGenerator var: #obsoleteIndexedPrimitiveTable declareC: 'char* obsoleteIndexedPrimitiveTable[][3] = ', self obsoleteIndexedPrimitiveTableString. aCCodeGenerator var: #obsoleteNamedPrimitiveTable declareC: 'const char* obsoleteNamedPrimitiveTable[][3] = ', self obsoleteNamedPrimitiveTableString. aCCodeGenerator var: #externalPrimitiveTable declareC: 'void *externalPrimitiveTable[', (MaxExternalPrimitiveTableSize + 1) printString, ']'. ! ! !Interpreter class methodsFor: 'initialization' stamp: 'tpr 3/17/2005 10:40'! initializeCaches | atCacheEntrySize | MethodCacheEntries _ 512. MethodCacheSelector _ 1. MethodCacheClass _ 2. MethodCacheMethod _ 3. MethodCachePrim _ 4. MethodCacheNative _ 5. MethodCachePrimFunction _ 6. MethodCacheEntrySize _ 8. "Must be power of two for masking scheme." MethodCacheMask _ (MethodCacheEntries - 1) * MethodCacheEntrySize. MethodCacheSize _ MethodCacheEntries * MethodCacheEntrySize. CacheProbeMax _ 3. AtCacheEntries _ 8. "Must be a power of two" AtCacheOop _ 1. AtCacheSize _ 2. AtCacheFmt _ 3. AtCacheFixedFields _ 4. atCacheEntrySize _ 4. "Must be power of two for masking scheme." AtCacheMask _ (AtCacheEntries-1) * atCacheEntrySize. AtPutBase _ AtCacheEntries * atCacheEntrySize. AtCacheTotalSize _ AtCacheEntries * atCacheEntrySize * 2. ! ! !Interpreter class methodsFor: 'initialization' stamp: 'di 6/14/2004 18:03'! initializeContextIndices "Class MethodContext" SenderIndex _ 0. InstructionPointerIndex _ 1. StackPointerIndex _ 2. MethodIndex _ 3. ReceiverIndex _ 5. TempFrameStart _ 6. "Note this is in two places!!" "Class BlockContext" CallerIndex _ 0. BlockArgumentCountIndex _ 3. InitialIPIndex _ 4. HomeIndex _ 5. "Class BlockClosure" BlockMethodIndex _ 0. ! ! !Interpreter class methodsFor: 'initialization' stamp: 'tpr 3/17/2005 11:32'! primitiveTableString "Interpreter initializePrimitiveTable primitiveTableString" | table | table := self primitiveTable. ^ String streamContents: [:s | s nextPut: ${. table withIndexDo: [:primSpec :index | s cr; tab; nextPutAll: '/* '; nextPutAll: (index - 1) printString; nextPutAll: '*/ '; nextPutAll: '(void *)'; nextPutAll: primSpec; nextPut: $,]. s cr; nextPutAll: ' 0 }']! ! !SmalltalkImage methodsFor: 'vm parameters' stamp: 'tpr 3/17/2005 12:56'! vmParameterAt: parameterIndex "parameterIndex is a positive integer corresponding to one of the VM's internal parameter/metric registers. Answer with the current value of that register. Fail if parameterIndex has no corresponding register. VM parameters are numbered as follows: 1 end of old-space (0-based, read-only) 2 end of young-space (read-only) 3 end of memory (read-only) 4 allocationCount (read-only) 5 allocations between GCs (read-write) 6 survivor count tenuring threshold (read-write) 7 full GCs since startup (read-only) 8 total milliseconds in full GCs since startup (read-only) 9 incremental GCs since startup (read-only) 10 total milliseconds in incremental GCs since startup (read-only) 11 tenures of surving objects since startup (read-only) 12-20 specific to the translating VM 21 root table size (read-only) 22 root table overflows since startup (read-only) 23 bytes of extra memory to reserve for VM buffers, plugins, etc. 24 memory headroom when growing object memory (rw) 25 memory threshold above which shrinking object memory (rw) 26 number of mSecs between VM forced interrupt checks (rw) 27 VM word size - 4 or 8 (read-only)" self primitiveFailed! ! !SystemDictionary methodsFor: 'sources, change log' stamp: 'ikp 3/26/2005 21:59'! wordSize "Answer the size (in bytes) of an object pointer." "Smalltalk wordSize" ^[SmalltalkImage current vmParameterAt: 27] on: Error do: [4]! ! !SystemDictionary methodsFor: 'deprecated' stamp: 'tpr 3/17/2005 12:55'! vmParameterAt: parameterIndex "parameterIndex is a positive integer corresponding to one of the VM's internal parameter/metric registers. Answer with the current value of that register. Fail if parameterIndex has no corresponding register. VM parameters are numbered as follows: 1 end of old-space (0-based, read-only) 2 end of young-space (read-only) 3 end of memory (read-only) 4 allocationCount (read-only) 5 allocations between GCs (read-write) 6 survivor count tenuring threshold (read-write) 7 full GCs since startup (read-only) 8 total milliseconds in full GCs since startup (read-only) 9 incremental GCs since startup (read-only) 10 total milliseconds in incremental GCs since startup (read-only) 11 tenures of surving objects since startup (read-only) 12-20 specific to the translating VM 21 root table size (read-only) 22 root table overflows since startup (read-only) 23 bytes of extra memory to reserve for VM buffers, plugins, etc. 24 memory headroom when growing object memory (rw) 25 memory threshold above which shrinking object memory (rw) 26 26 number of mSecs between VM forced interrupt checks (rw) 27 VM word size - 4 or 8 (read-only)" ^ self deprecated: 'Use SmalltalkImage current vmParameterAt:' block: [SmalltalkImage current vmParameterAt: parameterIndex] ! ! !TMethod methodsFor: 'inlining' stamp: 'ikp 6/9/2004 16:15'! inlineSend: aSendNode directReturn: directReturn exitVar: exitVar in: aCodeGen "Answer a collection of statments to replace the given send. directReturn indicates that the send is the expression of a return statement, so returns can be left in the body of the inlined method. If exitVar is nil, the value returned by the send is not used; thus, returns need not assign to the output variable." | sel meth exitLabel labelUsed inlineStmts | sel _ aSendNode selector. meth _ (aCodeGen methodNamed: sel) copy. meth renameVarsForInliningInto: self in: aCodeGen. meth renameLabelsForInliningInto: self. self addVarsDeclarationsAndLabelsOf: meth. meth hasReturn ifTrue: [ directReturn ifTrue: [ "propagate the return type, if necessary" returnType = meth returnType ifFalse: [ self halt ]. "caller's return type should be declared by user" returnType _ meth returnType. ] ifFalse: [ exitLabel _ self unusedLabelForInliningInto: self. labelUsed _ meth exitVar: exitVar label: exitLabel. labelUsed ifTrue: [ labels add: exitLabel ] ifFalse: [ exitLabel _ nil ]. ]. "propagate type info if necessary" ((exitVar ~= nil) and: [meth returnType ~= 'sqInt']) ifTrue: [ declarations at: exitVar put: meth returnType, ' ', exitVar. ]. ]. inlineStmts _ OrderedCollection new: 100. inlineStmts add: (TLabeledCommentNode new setComment: 'begin ', sel). inlineStmts addAll: (self argAssignmentsFor: meth args: aSendNode args in: aCodeGen). inlineStmts addAll: meth statements. "method body" (directReturn and: [meth endsWithReturn not]) ifTrue: [ inlineStmts add: (TReturnNode new setExpression: (TVariableNode new setName: 'nil')). ]. exitLabel ~= nil ifTrue: [ inlineStmts add: (TLabeledCommentNode new setLabel: exitLabel comment: 'end ', meth selector). ]. ^inlineStmts! ! !TMethod methodsFor: 'C code generation' stamp: 'ikp 6/9/2004 16:15'! emitCFunctionPrototype: aStream generator: aCodeGen "Emit a C function header for this method onto the given stream." | arg | export ifTrue:[aStream nextPutAll:'EXPORT('; nextPutAll: returnType; nextPutAll:') '] ifFalse:[(aCodeGen isGeneratingPluginCode and:[self isStatic]) ifTrue:[aStream nextPutAll:'static ']. aStream nextPutAll: returnType; space]. aStream nextPutAll: (aCodeGen cFunctionNameFor: selector), '('. args isEmpty ifTrue: [ aStream nextPutAll: 'void' ]. 1 to: args size do: [ :i | arg _ args at: i. (declarations includesKey: arg) ifTrue: [ aStream nextPutAll: (declarations at: arg). ] ifFalse: [ aStream nextPutAll: 'sqInt ', (args at: i). ]. i < args size ifTrue: [ aStream nextPutAll: ', ' ]. ]. aStream nextPutAll: ')'.! ! !TMethod methodsFor: 'C code generation' stamp: 'ikp 6/9/2004 16:15'! emitCHeaderOn: aStream generator: aCodeGen "Emit a C function header for this method onto the given stream." aStream cr. self emitCFunctionPrototype: aStream generator: aCodeGen. aStream nextPutAll: ' {'; cr. self emitGlobalStructReferenceOn: aStream. locals do: [ :var | aStream nextPutAll: ' '. aStream nextPutAll: (declarations at: var ifAbsent: [ 'sqInt ', var]), ';'; cr. ]. locals isEmpty ifFalse: [ aStream cr ].! ! !TMethod methodsFor: 'C code generation' stamp: 'ikp 6/9/2004 16:15'! emitInlineOn: aStream level: level generator: aCodeGen "Emit C code for this method onto the given stream. All calls to inlined methods should already have been expanded." self removeUnusedTemps. sharedLabel ifNotNil:[ aStream crtab: level-1; nextPutAll: sharedLabel; nextPutAll:':'. aStream crtab: level. aStream nextPutAll: '/* '; nextPutAll: selector; nextPutAll: ' */'. aStream crtab: level. ]. aStream nextPutAll:'{'; cr. locals do: [ :var | aStream tab: level+1. aStream nextPutAll: (declarations at: var ifAbsent: [ 'sqInt ', var]), ';'; cr. ]. parseTree emitCCodeOn: aStream level: level+1 generator: aCodeGen. aStream tab: level; nextPutAll: '}'; cr.! ! !TMethod methodsFor: 'C code generation' stamp: 'ikp 6/9/2004 16:15'! emitProxyFunctionPrototype: aStream generator: aCodeGen "Emit an indirect C function header for this method onto the given stream." | arg | aStream nextPutAll: returnType; space. aStream nextPutAll: '(*', (aCodeGen cFunctionNameFor: selector), ')('. args isEmpty ifTrue: [ aStream nextPutAll: 'void' ]. 1 to: args size do: [ :i | arg _ args at: i. (declarations includesKey: arg) ifTrue: [ aStream nextPutAll: (declarations at: arg). ] ifFalse: [ aStream nextPutAll: 'sqInt ', (args at: i). ]. i < args size ifTrue: [ aStream nextPutAll: ', ' ]. ]. aStream nextPutAll: ')'.! ! !TMethod methodsFor: 'initialization' stamp: 'ikp 6/9/2004 16:16'! setSelector: sel args: argList locals: localList block: aBlockNode primitive: aNumber "Initialize this method using the given information." selector _ sel. returnType _ 'sqInt'. "assume return type is long for now" args _ argList asOrderedCollection collect: [:arg | arg key]. locals _ localList asOrderedCollection collect: [:arg | arg key]. declarations _ Dictionary new. primitive _ aNumber. parseTree _ aBlockNode asTranslatorNode. labels _ OrderedCollection new. complete _ false. "set to true when all possible inlining has been done" export _ self extractExportDirective. static _ self extractStaticDirective. self extractSharedCase. self removeFinalSelfReturn. self recordDeclarations. globalStructureBuildMethodHasFoo _ 0.! ! !VMMaker methodsFor: 'target directories' stamp: 'ikp 9/2/2004 14:11'! interpreterFilename "Answer the filename for the core interpreter. Default is 'interp.c'." ^'interp.c'! ! !VMMaker methodsFor: 'target directories' stamp: 'ikp 9/2/2004 14:11'! interpreterHeaderName "Answer the filename for the core interpreter header. Default is 'interp.h'." ^'interp.h'! ! !VMMaker methodsFor: 'initialize' stamp: 'svp 11/14/2002 21:01'! initialize logger := Transcript. inline _ true. forBrowser _ false. internalPlugins _ SortedCollection new. externalPlugins _ SortedCollection new. platformName _ self class machinesDirName. allFilesList _ Dictionary new. interpreterClassName _ 'Interpreter'.! ! !VMMaker methodsFor: 'generate sources' stamp: 'ikp 9/2/2004 14:13'! generateInterpreterFile "Translate the Smalltalk description of the virtual machine into C. If 'self doInlining' is true, small method bodies are inlined to reduce procedure call overhead. On the PPC, this results in a factor of three speedup with only 30% increase in code size. Subclasses can use specialised versions of CCodeGenerator and interpreterClass." self needsToRegenerateInterpreterFile ifFalse: [^nil]. self interpreterClass initialize. ObjectMemory initialize. self createCodeGenerator addClass: self interpreterClass; addClass: ObjectMemory; storeHeaderOnFile: self interpreterHeaderPath bytesPerWord: ObjectMemory bytesPerWord; storeCodeOnFile: self interpreterFilePath doInlining: self doInlining! ! !VMMaker methodsFor: 'generate sources' stamp: 'ikp 9/2/2004 14:09'! interpreterFilePath "Answer the fully-qualified path for the generated interpreter file." ^self coreVMDirectory fullNameFor: self interpreterFilename! ! !VMMaker methodsFor: 'generate sources' stamp: 'ikp 9/2/2004 14:10'! interpreterHeaderPath "Answer the fully-qualified path for the generated interpreter header file." ^self coreVMDirectory fullNameFor: self interpreterHeaderName! ! !RiscOSVMMaker methodsFor: 'generate sources' stamp: 'tpr 3/17/2005 16:26'! interpreterHeaderPath "return the full path for the interpreter header file" "RiscOS keeps the interp file in a 'h' subdirectory of coreVMDirectory" self coreVMDirectory assureExistenceOfPath: 'h'. ^(self coreVMDirectory directoryNamed: 'h') fullNameFor: self interpreterFilename! ! !VMPluginCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 6/9/2004 17:36'! emitCHeaderOn: aStream "Write a C file header onto the given stream." aStream nextPutAll: '/* Automatically generated from Squeak on '. aStream nextPutAll: Time dateAndTimeNow printString. aStream nextPutAll: ' */';cr. aStream nextPutAll:' #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using ''null'' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif '. "Additional header files" headerFiles do:[:hdr| aStream nextPutAll:'#include '; nextPutAll: hdr; cr]. aStream nextPutAll: ' #include "sqMemoryAccess.h" '. aStream cr.! ! ObjectMemory initialize! InterpreterSimulatorMSB removeSelector: #halfWordAt:! InterpreterSimulatorMSB removeSelector: #halfWordAt:put:! InterpreterSimulatorLSB removeSelector: #halfWordAt:! InterpreterSimulatorLSB removeSelector: #halfWordAt:put:! Interpreter subclass: #InterpreterSimulator instanceVariableNames: 'byteCount sendCount traceOn myBitBlt displayForm filesOpen imageName pluginList mappedPluginEntries inputSem quitBlock transcript displayView logging' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! Object subclass: #ObjectMemory instanceVariableNames: 'memory youngStart endOfMemory memoryLimit nilObj falseObj trueObj specialObjectsOop rootTable rootTableCount child field parentField freeBlock lastHash allocationCount lowSpaceThreshold signalLowSpace compStart compEnd fwdTableNext fwdTableLast remapBuffer remapBufferCount allocationsBetweenGCs tenuringThreshold statFullGCs statFullGCMSecs statIncrGCs statIncrGCMSecs statTenures statRootTableOverflows freeContexts freeLargeContexts interruptCheckCounter totalObjectCount shrinkThreshold growHeadroom headerTypeBytes youngStartLocal' classVariableNames: 'AllButHashBits AllButMarkBit AllButMarkBitAndTypeMask AllButRootBit AllButTypeMask BaseHeaderSize BlockContextProto Byte0Mask Byte0Shift Byte1Mask Byte1Shift Byte1ShiftNegated Byte2Mask Byte2Shift Byte3Mask Byte3Shift Byte3ShiftNegated Byte4Mask Byte4Shift Byte4ShiftNegated Byte5Mask Byte5Shift Byte5ShiftNegated Byte6Mask Byte6Shift Byte7Mask Byte7Shift Byte7ShiftNegated Bytes3to0Mask Bytes7to4Mask BytesPerWord CharacterTable ClassArray ClassBitmap ClassBlockContext ClassByteArray ClassCharacter ClassCompiledMethod ClassExternalAddress ClassExternalData ClassExternalFunction ClassExternalLibrary ClassExternalStructure ClassFloat ClassInteger ClassLargeNegativeInteger ClassLargePositiveInteger ClassMessage ClassMethodContext ClassPoint ClassProcess ClassPseudoContext ClassSemaphore ClassString ClassTranslatedMethod CompactClassMask CompactClasses ConstMinusOne ConstOne ConstTwo ConstZero ContextFixedSizePlusHeader CtxtTempFrameStart DoAssertionChecks DoBalanceChecks Done ExternalObjectsArray FalseObject FloatProto GCTopMarker HashBits HashBitsOffset HeaderTypeClass HeaderTypeFree HeaderTypeGC HeaderTypeShort HeaderTypeSizeAndClass LargeContextBit LargeContextSize LongSizeMask MarkBit MethodContextProto NilContext NilObject RemapBufferSize RootBit RootTableRedZone RootTableSize SchedulerAssociation SelectorAboutToReturn SelectorCannotInterpret SelectorCannotReturn SelectorDoesNotUnderstand SelectorMustBeBoolean SelectorRunWithIn ShiftForWord Size4Bit SizeMask SmallContextSize SpecialSelectors StackStart StartField StartObj TheDisplay TheFinalizationSemaphore TheInputSemaphore TheInterruptSemaphore TheLowSpaceSemaphore TheTimerSemaphore TrueObject TypeMask Upward WordMask' poolDictionaries: '' category: 'VMMaker-Interpreter'! LargeIntegersPlugin removeSelector: #flag:! !FilePluginSimulator reorganize! ('simulation' fileValueOf: makeDirEntryName:size:createDate:modDate:isDir:fileSize: oopForPointer: primitiveDirectoryLookup primitiveFileDelete primitiveFileOpen primitiveFileRename sqFile:Read:Into:At: sqFile:SetPosition: sqFile:Truncate: sqFile:Write:From:At: sqFileAtEnd: sqFileClose: sqFileFlush: sqFileGetPosition: sqFileSize:) ('file security' ioCanCreatePath:OfSize: ioCanDeleteFile:OfSize: ioCanDeletePath:OfSize: ioCanGetFileType:OfSize: ioCanListPath:OfSize: ioCanOpenFile:OfSize:Writable: ioCanRenameFile:OfSize: ioCanSetFileType:OfSize:) ! !BitBltSimulator reorganize! ('debug support' dstLongAt: dstLongAt:put: srcLongAt:) ('simulation' initBBOpTable initializeDitherTables mergeFn:with: tableLookup:at:) ! BalloonEnginePlugin subclass: #BalloonEngineSimulation instanceVariableNames: 'bbObj workBufferArray' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-InterpreterSimulation'! BalloonEngineBase removeSelector: #fillSpan:from:to:max:! ================================================ FILE: vm/src/from_squeak/unix/misc/VMM38b4-64bit-vm2-ikp.2.cs ================================================ 'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6548] on 31 March 2005 at 3:46:37 pm'! "Change Set: VMM38b4-64bit-vm2-ikp Date: 2005-03-31 Author: ian.piumarta@squeakland.org Changes relative to VMM38b4-64bit-vm1 that add 64-bit support to SmartSyntaxInterpreterPlugins. Needed to correctly translate the SocketPlugin."! !Object class methodsFor: 'plugin generation' stamp: 'ikp 3/31/2005 14:20'! ccgDeclareCForVar: aSymbolOrString ^'sqInt ', aSymbolOrString! ! !Array class methodsFor: 'plugin generation' stamp: 'ikp 3/31/2005 14:20'! ccgDeclareCForVar: aSymbolOrString ^'sqInt *', aSymbolOrString! ! !Oop class methodsFor: 'plugin generation' stamp: 'ikp 3/31/2005 14:20'! ccgDeclareCForVar: aSymbolOrString ^'sqInt ', aSymbolOrString! ! !SmartSyntaxPluginCodeGenerator methodsFor: 'translating builtins' stamp: 'ikp 3/31/2005 15:46'! generateCPtrAsOop: aNode on: aStream indent: anInteger aStream nextPutAll: '((sqInt)(long)('. self emitCExpression: aNode receiver on: aStream. aStream nextPutAll: ') - sizeof(sqInt))'.! ! !SmartSyntaxPluginTMethod methodsFor: 'private' stamp: 'ikp 3/31/2005 14:23'! oopVariable: aString (locals includes: aString) ifFalse: [locals add: aString. declarations at: aString put: 'sqInt ', aString]. ^TVariableNode new setName: aString! ! !SmartSyntaxPluginTMethod methodsFor: 'generating C code' stamp: 'ikp 3/31/2005 14:23'! emitCHeaderOn: aStream generator: aCodeGen "Emit a C function header for this method onto the given stream." aStream cr. self emitCFunctionPrototype: aStream generator: aCodeGen. aStream nextPutAll: ' {'; cr. locals do: [ :var | aStream tab; nextPutAll: (declarations at: var ifAbsent: [ 'sqInt ', var]); nextPut: $;; cr]. locals isEmpty ifFalse: [ aStream cr ].! ! !SmartSyntaxPluginTMethod methodsFor: 'initializing' stamp: 'ikp 3/31/2005 14:01'! setSelector: sel args: argList locals: localList block: aBlockNode primitive: aNumber "Initialize this method using the given information." selector _ sel. returnType _ 'sqInt'. "assume return type is sqInt for now" args _ argList asOrderedCollection collect: [:arg | arg key]. locals _ localList asOrderedCollection collect: [:arg | arg key]. declarations _ Dictionary new. primitive _ aNumber. parseTree _ aBlockNode asTranslatorNode. labels _ OrderedCollection new. complete _ false. "set to true when all possible inlining has been done" export _ self extractExportDirective. static _ self extractStaticDirective. self extractSharedCase. isPrimitive _ false. "set to true only if you find a primtive direction." suppressingFailureGuards _ self extractSuppressFailureGuardDirective. self recordDeclarations. self extractPrimitiveDirectives. ! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:12'! intToNetAddress: addr "Convert the given 32-bit integer into an internet network address represented as a four-byte ByteArray." | netAddressOop naPtr | self var: #naPtr declareC: 'char * naPtr'. netAddressOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: 4. naPtr _ netAddressOop asCharPtr. naPtr at: 0 put: (self cCoerce: ((addr >> 24) bitAnd: 16rFF) to: 'char'). naPtr at: 1 put: (self cCoerce: ((addr >> 16) bitAnd: 16rFF) to: 'char'). naPtr at: 2 put: (self cCoerce: ((addr >> 8) bitAnd: 16rFF) to: 'char'). naPtr at: 3 put: (self cCoerce: (addr bitAnd: 16rFF) to: 'char'). ^ netAddressOop! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:03'! primitiveSocket: socket getOptions: optionName | s optionNameStart optionNameSize returnedValue errorCode results | self var: #s declareC: 'SocketPtr s'. self var: #optionNameStart declareC: 'char *optionNameStart'. self primitive: 'primitiveSocketGetOptions' parameters: #(Oop Oop). s _ self socketValueOf: socket. interpreterProxy success: (interpreterProxy isBytes: optionName). optionNameStart _ self cCoerce: (interpreterProxy firstIndexableField: optionName) to: 'char *'. optionNameSize _ interpreterProxy slotSizeOf: optionName. interpreterProxy failed ifTrue: [^nil]. returnedValue _ 0. errorCode _ self sqSocketGetOptions: s optionNameStart: optionNameStart optionNameSize: optionNameSize returnedValue: (self cCode: '&returnedValue'). interpreterProxy pushRemappableOop: returnedValue asSmallIntegerObj. interpreterProxy pushRemappableOop: errorCode asSmallIntegerObj. interpreterProxy pushRemappableOop: (interpreterProxy instantiateClass: (interpreterProxy classArray) indexableSize: 2). results _ interpreterProxy popRemappableOop. interpreterProxy storePointer: 0 ofObject: results withValue: interpreterProxy popRemappableOop. interpreterProxy storePointer: 1 ofObject: results withValue: interpreterProxy popRemappableOop. ^ results! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:08'! primitiveSocket: socket receiveDataBuf: array start: startIndex count: count | s byteSize arrayBase bufStart bytesReceived | self var: #s declareC: 'SocketPtr s'. self var: #arrayBase declareC: 'char *arrayBase'. self var: #bufStart declareC: 'char *bufStart'. self primitive: 'primitiveSocketReceiveDataBufCount' parameters: #(Oop Oop SmallInteger SmallInteger ). s _ self socketValueOf: socket. "buffer can be any indexable words or bytes object" interpreterProxy success: (interpreterProxy isWordsOrBytes: array). (interpreterProxy isWords: array) ifTrue: [byteSize _ 4] ifFalse: [byteSize _ 1]. interpreterProxy success: (startIndex >= 1 and: [count >= 0 and: [startIndex + count - 1 <= (interpreterProxy slotSizeOf: array)]]). interpreterProxy failed ifFalse: ["Note: adjust bufStart for zero-origin indexing" arrayBase _ self cCoerce: (interpreterProxy firstIndexableField: array) to: 'char *'. bufStart _ arrayBase + (startIndex - 1 * byteSize). bytesReceived _ self sqSocket: s ReceiveDataBuf: bufStart Count: count * byteSize]. ^ (bytesReceived // byteSize) asSmallIntegerObj! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:09'! primitiveSocket: socket receiveUDPDataBuf: array start: startIndex count: count | s byteSize arrayBase bufStart bytesReceived results address port moreFlag | self var: #s declareC: 'SocketPtr s'. self var: #arrayBase declareC: 'char *arrayBase'. self var: #bufStart declareC: 'char *bufStart'. self primitive: 'primitiveSocketReceiveUDPDataBufCount' parameters: #(Oop Oop SmallInteger SmallInteger ). s _ self socketValueOf: socket. "buffer can be any indexable words or bytes object" interpreterProxy success: (interpreterProxy isWordsOrBytes: array). (interpreterProxy isWords: array) ifTrue: [byteSize _ 4] ifFalse: [byteSize _ 1]. interpreterProxy success: (startIndex >= 1 and: [count >= 0 and: [startIndex + count - 1 <= (interpreterProxy slotSizeOf: array)]]). interpreterProxy failed ifFalse: ["Note: adjust bufStart for zero-origin indexing" arrayBase _ self cCoerce: (interpreterProxy firstIndexableField: array) to: 'char *'. bufStart _ arrayBase + (startIndex - 1 * byteSize). "allocate storage for results, remapping newly allocated oops in case GC happens during allocation" address _ 0. port _ 0. moreFlag _ 0. bytesReceived _ self sqSocket: s ReceiveUDPDataBuf: bufStart Count: count * byteSize address: (self cCode: '&address') port: (self cCode: '&port') moreFlag: (self cCode: '&moreFlag'). interpreterProxy pushRemappableOop: port asSmallIntegerObj. interpreterProxy pushRemappableOop: (self intToNetAddress: address). interpreterProxy pushRemappableOop: (bytesReceived // byteSize) asSmallIntegerObj. interpreterProxy pushRemappableOop: (interpreterProxy instantiateClass: (interpreterProxy classArray) indexableSize: 4). results _ interpreterProxy popRemappableOop. interpreterProxy storePointer: 0 ofObject: results withValue: interpreterProxy popRemappableOop. interpreterProxy storePointer: 1 ofObject: results withValue: interpreterProxy popRemappableOop. interpreterProxy storePointer: 2 ofObject: results withValue: interpreterProxy popRemappableOop. moreFlag ifTrue: [ interpreterProxy storePointer: 3 ofObject: results withValue: interpreterProxy trueObject ] ifFalse: [ interpreterProxy storePointer: 3 ofObject: results withValue: interpreterProxy falseObject ]. ]. ^ results! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:05'! primitiveSocket: socket sendData: array start: startIndex count: count | s byteSize arrayBase bufStart bytesSent | self var: #s declareC: 'SocketPtr s'. self var: #arrayBase declareC: 'char *arrayBase'. self var: #bufStart declareC: 'char *bufStart'. self primitive: 'primitiveSocketSendDataBufCount' parameters: #(Oop Oop SmallInteger SmallInteger ). s _ self socketValueOf: socket. "buffer can be any indexable words or bytes object except CompiledMethod " interpreterProxy success: (interpreterProxy isWordsOrBytes: array). (interpreterProxy isWords: array) ifTrue: [byteSize _ 4] ifFalse: [byteSize _ 1]. interpreterProxy success: (startIndex >= 1 and: [count >= 0 and: [startIndex + count - 1 <= (interpreterProxy slotSizeOf: array)]]). interpreterProxy failed ifFalse: ["Note: adjust bufStart for zero-origin indexing" arrayBase _ self cCoerce: (interpreterProxy firstIndexableField: array) to: 'char *'. bufStart _ arrayBase + (startIndex - 1 * byteSize). bytesSent _ self sqSocket: s SendDataBuf: bufStart Count: count * byteSize]. ^ (bytesSent // byteSize) asSmallIntegerObj! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:06'! primitiveSocket: socket sendUDPData: array toHost: hostAddress port: portNumber start: startIndex count: count | s byteSize arrayBase bufStart bytesSent address | self var: #s declareC: 'SocketPtr s'. self var: #arrayBase declareC: 'char *arrayBase'. self var: #bufStart declareC: 'char *bufStart'. self primitive: 'primitiveSocketSendUDPDataBufCount' parameters: #(Oop Oop ByteArray SmallInteger SmallInteger SmallInteger ). s _ self socketValueOf: socket. "buffer can be any indexable words or bytes object except CompiledMethod " interpreterProxy success: (interpreterProxy isWordsOrBytes: array). (interpreterProxy isWords: array) ifTrue: [byteSize _ 4] ifFalse: [byteSize _ 1]. interpreterProxy success: (startIndex >= 1 and: [count >= 0 and: [startIndex + count - 1 <= (interpreterProxy slotSizeOf: array)]]). interpreterProxy failed ifFalse: ["Note: adjust bufStart for zero-origin indexing" arrayBase _ self cCoerce: (interpreterProxy firstIndexableField: array) to: 'char *'. bufStart _ arrayBase + (startIndex - 1 * byteSize). address _ self netAddressToInt: (self cCoerce: hostAddress to: 'unsigned char *'). bytesSent _ self sqSocket: s toHost: address port: portNumber SendDataBuf: bufStart Count: count * byteSize]. ^ (bytesSent // byteSize) asSmallIntegerObj! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:06'! primitiveSocket: socket setOptions: optionName value: optionValue | s optionNameStart optionNameSize optionValueStart optionValueSize returnedValue errorCode results | self var: #s declareC: 'SocketPtr s'. self var: #optionNameStart declareC: 'char *optionNameStart'. self var: #optionValueStart declareC: 'char *optionValueStart'. self primitive: 'primitiveSocketSetOptions' parameters: #(Oop Oop Oop). s _ self socketValueOf: socket. interpreterProxy success: (interpreterProxy isBytes: optionName). optionNameStart _ self cCoerce: (interpreterProxy firstIndexableField: optionName) to: 'char *'. optionNameSize _ interpreterProxy slotSizeOf: optionName. interpreterProxy success: (interpreterProxy isBytes: optionValue). optionValueStart_ self cCoerce: (interpreterProxy firstIndexableField: optionValue) to: 'char *'. optionValueSize _ interpreterProxy slotSizeOf: optionValue. interpreterProxy failed ifTrue: [^nil]. returnedValue _ 0. errorCode _ self sqSocketSetOptions: s optionNameStart: optionNameStart optionNameSize: optionNameSize optionValueStart: optionValueStart optionValueSize: optionValueSize returnedValue: (self cCode: '&returnedValue'). interpreterProxy pushRemappableOop: returnedValue asSmallIntegerObj. interpreterProxy pushRemappableOop: errorCode asSmallIntegerObj. interpreterProxy pushRemappableOop: (interpreterProxy instantiateClass: (interpreterProxy classArray) indexableSize: 2). results _ interpreterProxy popRemappableOop. interpreterProxy storePointer: 0 ofObject: results withValue: interpreterProxy popRemappableOop. interpreterProxy storePointer: 1 ofObject: results withValue: interpreterProxy popRemappableOop. ^ results! ! !SocketPlugin methodsFor: 'primitives' stamp: 'ikp 3/31/2005 14:08'! socketValueOf: socketOop "Return a pointer to the first byte of of the socket record within the given Smalltalk object, or nil if socketOop is not a socket record." | socketIndex | self returnTypeC: 'SQSocket *'. self var: #socketIndex type: 'void *'. interpreterProxy success: ((interpreterProxy isBytes: socketOop) and: [(interpreterProxy byteSizeOf: socketOop) = self socketRecordSize]). interpreterProxy failed ifTrue: [^ nil] ifFalse: [socketIndex _ self cCoerce: (interpreterProxy firstIndexableField: socketOop) to: 'void *'. ^ self cCode: '(SQSocket *) socketIndex']! ! !SocketPlugin class methodsFor: 'translation' stamp: 'ikp 3/31/2005 13:43'! declareCVarsIn: aCCodeGenerator aCCodeGenerator var: 'sDSAfn' type: 'void *'. aCCodeGenerator var: 'sHSAfn' type: 'void *'. aCCodeGenerator var: 'sCCTPfn' type: 'void *'. aCCodeGenerator var: 'sCCLOPfn' type: 'void *'. aCCodeGenerator var: 'sCCSOTfn' type: 'void *'. aCCodeGenerator addHeaderFile: '"SocketPlugin.h"'! ! !Unsigned methodsFor: 'as yet unclassified' stamp: 'ikp 3/31/2005 14:19'! ccgDeclareCForVar: aSymbolOrString ^'unsigned int ', aSymbolOrString! ! !WordArray class methodsFor: 'plugin generation' stamp: 'ikp 3/31/2005 14:19'! ccgDeclareCForVar: aSymbolOrString ^'usqInt *', aSymbolOrString! ! ================================================ FILE: vm/src/from_squeak/unix/misc/threadValidate/Makefile ================================================ INCLUDES=-I. -I../../../Cross/vm -I../../../../src/vm -I../../vm # __USE_GNU declares pthread_yield CFLAGS=-g2 -O1 -msse2 -Wall -D_GNU_SOURCE LDFLAGS=-lpthread all: testi testt testi: sqTicker.c sqUnixHeartbeat.c threadValidate.c cc -o $@ -DITIMER_HEARTBEAT=1 -DYIELD_IN_TICKER $(CFLAGS) $(INCLUDES) $^ $(LDFLAGS) testt: sqTicker.c sqUnixHeartbeat.c threadValidate.c cc -o $@ -DONLY_ONE_THREAD_PRIORITY=1 $(CFLAGS) $(INCLUDES) $^ $(LDFLAGS) ================================================ FILE: vm/src/from_squeak/unix/misc/threadValidate/config.h ================================================ #define HAVE_INTERP_H 1 #define SIZEOF_VOID_P 4 ================================================ FILE: vm/src/from_squeak/unix/misc/threadValidate/sqTicker.c ================================================ /* sqTicker.c * Core cross-platform tickers. tick.er (n): one who ticks a tickee * * Authors: Eliot Miranda & Josh Gargus * * Copyright (C) 2010 by Teleplace, Inc. * * All rights reserved. * * This file is part of Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* High-priority and synchronous tickee function support. * * Tickers provide the ability to register a tickee function that will be * called at a regular interval. There are two sets of tickers. The high- * priority ticker is asynchronous and if possible, runs in a high-priority * thread or if not, from an interrupt. Running from an interrupt is undesir- * able because it is much easier to create deadlock, for example by interrupt- * ing the VM when it has acquired some lock, and a tickee tries to acquire * the same lock. But the use of an interrupt is forced on linux because as * of 2006 and the 2.6.x kernel there is no way for a non-root process to * create threads of different priorities. * * The synchronous ticker runs in the VM thread at the earliest opportunity once * the tick has occurred. The VM calls the ticker from its event check. * * This file implements the cross-platform components, registering tickers and * calling tickers if deadlines have been reached. The platform-specific heart- * beats implement the threads or interrupts and the clocks. * * For the moment the number of asynchronous and synchronous tickees is * hard-wired, but they could easily be defined by a command-line argument etc. */ #include "sq.h" #include "sqAssert.h" #include "sqAtomicOps.h" #include "sqMemoryFence.h" #define NUM_ASYNCHRONOUS_TICKEES 4 #define NUM_SYNCHRONOUS_TICKEES 4 #define MicrosecondsPerMillisecond 1000 typedef struct { void (*tickee)(void); long inProgress; /* used only in high-priority ticker */ usqLong tickeeDeadlineUsecs; usqLong tickeePeriodUsecs; } Tickee; static int numSyncTickees = 0; static Tickee synch[NUM_SYNCHRONOUS_TICKEES]; #if ITIMER_HEARTBEAT /* See platforms/unix/vm/sqUnixHeartbeat.c */ static volatile int shouldYieldToHighPriorityTickerThread; #endif /* Add or remove a synchronous tickee. If periodms is non zero add the tickee * calling it every periodms, aligned to roundms, if non-zero. If periodms is * zero, remove tickee. */ void addSynchronousTickee(void (*tickee)(void), unsigned periodms, unsigned roundms) { int i; if (!periodms) { for (i = 0; i < numSyncTickees; i++) if (synch[i].tickee == tickee) { --numSyncTickees; if (i < numSyncTickees) memmove(synch + i, synch + i + 1, sizeof(synch[i]) * (numSyncTickees - i)); return; } return; } for (i = 0; i < NUM_SYNCHRONOUS_TICKEES; i++) if (i >= numSyncTickees || !synch[i].tickee || synch[i].tickee == tickee) { synch[i].tickee = tickee; synch[i].tickeePeriodUsecs = periodms * MicrosecondsPerMillisecond; synch[i].tickeeDeadlineUsecs = synch[i].tickeePeriodUsecs + ioUTCMicroseconds(); if (roundms) { synch[i].tickeeDeadlineUsecs -= synch[i].tickeeDeadlineUsecs % (roundms * MicrosecondsPerMillisecond); if (synch[i].tickeeDeadlineUsecs < ioUTCMicroseconds()) synch[i].tickeeDeadlineUsecs += synch[i].tickeePeriodUsecs; } if (i >= numSyncTickees) ++numSyncTickees; return; } error("ran out of synchronous tickee slots"); } void ioSynchronousCheckForEvents() { int i; #if ITIMER_HEARTBEAT extern void yieldToHighPriorityTickerThread(void); sqLowLevelMFence(); if (shouldYieldToHighPriorityTickerThread) yieldToHighPriorityTickerThread(); #endif for (i = 0; i < numSyncTickees; i++) if (synch[i].tickee && ioUTCMicroseconds() >= synch[i].tickeeDeadlineUsecs) { synch[i].tickeeDeadlineUsecs += synch[i].tickeePeriodUsecs; synch[i].tickee(); } } static int numAsyncTickees = 0; static Tickee async[NUM_ASYNCHRONOUS_TICKEES]; /* Add or remove an asynchronous tickee. If periodms is non zero add the * tickee, calling it every periodms. * * N.B. addHighPriorityTickee is called from the VM thread, whereas * checkHighPriorityTickees is called from the high-priority heartbeat thread * (or an interrupt). The above 64-bit variables must therefore be read and * written atomically to avoid either thread reading or writing a modified * half of the variable while the other half has yet to be updated. */ void addHighPriorityTickee(void (*tickee)(void), unsigned periodms) { int i; if (!periodms) { for (i = 0; i < numAsyncTickees; i++) /* We cannot safely copy the data to keep used tickees contiguous * because checkHighPriorityTickees could be called during the move. * This implies first checking for an existing tickee below before * using an empty slot because an empty slot can be created before * a used (and subsequently modified) tickee. */ if (async[i].tickee == tickee) { async[i].tickee = 0; sqLowLevelMFence(); return; } return; } for (i = 0; i < numAsyncTickees; i++) if (async[i].tickee == tickee) break; if (i >= numAsyncTickees) for (i = 0; i < NUM_ASYNCHRONOUS_TICKEES; i++) if (i >= numAsyncTickees || !async[i].tickee) break; if (i >= NUM_ASYNCHRONOUS_TICKEES) error("ran out of asyncronous tickee slots"); /* first disable the tickee while updating the entry. */ async[i].tickee = 0; sqLowLevelMFence(); async[i].tickeePeriodUsecs = periodms * MicrosecondsPerMillisecond; async[i].tickeeDeadlineUsecs = async[i].tickeePeriodUsecs + ioUTCMicroseconds(); async[i].inProgress = 0; async[i].tickee = tickee; if (i >= numAsyncTickees) ++numAsyncTickees; sqLowLevelMFence(); } void checkHighPriorityTickees(usqLong utcMicrosecondClock) { int i; #if ITIMER_HEARTBEAT extern void unblockVMThreadAfterYieldToHighPriorityTickerThread(void); shouldYieldToHighPriorityTickerThread = 1; #endif /* Since this runs either in a high-priority thread or in an interrupt only * one fence is needed. Since the VM thread will not disturb any non-zero * entry (except for changing the period) we can read the entry without * locking. But we need to lock the attempt to run the tickee in case for * any reason checkHighPriorityTickees is miscalled reentrantly. */ sqLowLevelMFence(); for (i = 0; i < numAsyncTickees; i++) if (async[i].tickee && !async[i].inProgress && utcMicrosecondClock >= async[i].tickeeDeadlineUsecs) { int previousInProgress; sqCompareAndSwapRes(async[i].inProgress,0,1,previousInProgress); if (previousInProgress == 0) { assert(async[i].inProgress); async[i].tickeeDeadlineUsecs += async[i].tickeePeriodUsecs; async[i].tickee(); async[i].inProgress = 0; } } #if ITIMER_HEARTBEAT shouldYieldToHighPriorityTickerThread = 0; sqLowLevelMFence(); unblockVMThreadAfterYieldToHighPriorityTickerThread(); #endif } ================================================ FILE: vm/src/from_squeak/unix/misc/threadValidate/sqUnixHeartbeat.c ================================================ /**************************************************************************** * PROJECT: Unix (pthread or setitimer) heartbeat logic for Stack VM * FILE: sqUnixHeartbeat.c * CONTENT: * * AUTHOR: Eliot Miranda * ADDRESS: * EMAIL: eliot@qwaq.com * RCSID: $Id$ * * NOTES: * July 31st, 2008, EEM added heart-beat thread. * Aug 20th, 2009, EEM added 64-bit microsecond clock support code * *****************************************************************************/ #include "sq.h" #include #if ITIMER_HEARTBEAT # include #else # include #endif #include #include #define SecondsFrom1901To1970 2177452800ULL #define MicrosecondsFrom1901To1970 2177452800000000ULL #define MicrosecondsPerSecond 1000000ULL #define MillisecondsPerSecond 1000ULL #define MicrosecondsPerMillisecond 1000ULL static unsigned volatile long long utcMicrosecondClock; static unsigned volatile long long localMicrosecondClock; static unsigned long long utcStartMicroseconds; /* for the ioMSecs clock. */ static long long vmGMTOffset = 0; static unsigned long long frequencyMeasureStart = 0; static unsigned long heartbeats; /* * Update the utc and local microsecond clocks. Since this is invoked from * interupt code, and since the clocks are 64-bit values that are read * concurrently by the VM, care must be taken to access these values atomically * on 32-bit systems. If they are not access atomically there is a possibility * of fetching the two halves of the clock from different ticks which would * cause a jump in the clock of 2^32 microseconds (1 hr, 11mins, 34 secs). * * Since an interrupt could occur between any two instructions the clock must be * read atomically as well as written atomically. If possible this can be * implemented without locks using atomic 64-bit reads and writes. */ #include "sqAtomicOps.h" static void updateMicrosecondClock() { struct timeval utcNow; unsigned long long newUtcMicrosecondClock; unsigned long long newLocalMicrosecondClock; gettimeofday(&utcNow,0); newUtcMicrosecondClock = ((utcNow.tv_sec * MicrosecondsPerSecond) + utcNow.tv_usec) + MicrosecondsFrom1901To1970; newLocalMicrosecondClock = newUtcMicrosecondClock + vmGMTOffset; set64(utcMicrosecondClock,newUtcMicrosecondClock); set64(localMicrosecondClock,newLocalMicrosecondClock); } void ioUpdateVMTimezone() { time_t utctt; updateMicrosecondClock(); utctt = (get64(utcMicrosecondClock) - MicrosecondsFrom1901To1970) / MicrosecondsPerSecond; vmGMTOffset = localtime(&utctt)->tm_gmtoff * MicrosecondsPerSecond; } int ioMSecs() { return ((get64(utcMicrosecondClock) - utcStartMicroseconds) / MicrosecondsPerMillisecond) & 0x3FFFFFFF; } sqLong ioHighResClock(void) { /* return the value of the high performance counter */ sqLong value = 0; #if defined(__GNUC__) && ( defined(i386) || defined(__i386) || defined(__i386__) \ || defined(i486) || defined(__i486) || defined (__i486__) \ || defined(intel) || defined(x86) || defined(i86pc) ) __asm__ __volatile__ ("rdtsc" : "=A"(value)); #else # error "no high res clock defined" #endif return value; } #if !macintoshSqueak static unsigned int lowResMSecs= 0; static struct timeval startUpTime; /* * Answer the millisecond clock as computed on Unix prior to the 64-bit * microsecond clock. This is to help verify that the new clock is correct. */ sqInt ioOldMSecs(void) { struct timeval now; unsigned int nowMSecs; #if 1 /* HAVE_HIGHRES_COUNTER */ /* if we have a cheap, high-res counter use that to limit the frequency of calls to gettimeofday to something reasonable. */ static unsigned int baseMSecs = 0; /* msecs when we took base tick */ static sqLong baseTicks = 0;/* base tick for adjustment */ static sqLong tickDelta = 0;/* ticks / msec */ static sqLong nextTick = 0; /* next tick to check gettimeofday */ sqLong thisTick = ioHighResClock(); if(thisTick < nextTick) return lowResMSecs; #endif gettimeofday(&now, 0); if ((now.tv_usec-= startUpTime.tv_usec) < 0) { now.tv_usec+= 1000000; now.tv_sec-= 1; } now.tv_sec-= startUpTime.tv_sec; nowMSecs = (now.tv_usec / 1000 + now.tv_sec * 1000); #if 1 /* HAVE_HIGHRES_COUNTER */ { unsigned int msecsDelta; /* Adjust our rdtsc rate every 10...100 msecs as needed. This also covers msecs clock-wraparound. */ msecsDelta = nowMSecs - baseMSecs; if(msecsDelta < 0 || msecsDelta > 100) { /* Either we've hit a clock-wraparound or we are being sampled in intervals larger than 100msecs. Don't try any fancy adjustments */ baseMSecs = nowMSecs; baseTicks = thisTick; nextTick = 0; tickDelta = 0; } else if(msecsDelta >= 10) { /* limit the rate of adjustments to 10msecs */ baseMSecs = nowMSecs; tickDelta = (thisTick - baseTicks) / msecsDelta; nextTick = baseTicks = thisTick; } nextTick += tickDelta; } #endif return lowResMSecs= nowMSecs; } #endif /* !macintoshSqueak */ /* Note: ioMicroMSecs returns *milli*seconds */ int ioMicroMSecs(void) { updateMicrosecondClock(); return ioMSecs(); } /* returns the local wall clock time */ int ioSeconds(void) { return get64(localMicrosecondClock) / MicrosecondsPerSecond; } /* This is an expensive interface for use by profiling code that wants the time * now rather than as of the last heartbeat. */ usqLong ioUTCMicrosecondsNow() { updateMicrosecondClock(); return get64(utcMicrosecondClock); } usqLong ioUTCMicroseconds() { return get64(utcMicrosecondClock); } usqLong ioLocalMicroseconds() { return get64(localMicrosecondClock); } int ioUTCSeconds(void) { return get64(utcMicrosecondClock) / MicrosecondsPerSecond; } /* * On Mac OS X use the following. * On Unix use dpy->ioRelinquishProcessorForMicroseconds */ #if macintoshSqueak int ioRelinquishProcessorForMicroseconds(int microSeconds) { long realTimeToWait; extern usqLong getNextWakeupUsecs(); usqLong nextWakeupUsecs = getNextWakeupUsecs(); usqLong utcNow = get64(utcMicrosecondClock); if (nextWakeupUsecs <= utcNow) { /* if nextWakeupUsecs is non-zero the next wakeup time has already * passed and we shopuld not wait. */ if (nextWakeupUsecs != 0) return 0; realTimeToWait = microSeconds; } else { realTimeToWait = nextWakeupUsecs - utcNow; if (realTimeToWait > microSeconds) realTimeToWait = microSeconds; } aioSleepForUsecs(realTimeToWait); return 0; } #endif /* !macintoshSqueak */ void ioInitTime(void) { ioUpdateVMTimezone(); /* does updateMicrosecondClock as a side-effect */ updateMicrosecondClock(); /* this can now compute localUTCMicroseconds */ utcStartMicroseconds = utcMicrosecondClock; #if !macintoshSqueak /* This is only needed for ioOldMSecs */ gettimeofday(&startUpTime, 0); #endif } static void heartbeat() { updateMicrosecondClock(); if (get64(frequencyMeasureStart) == 0) { set64(frequencyMeasureStart,utcMicrosecondClock); heartbeats = 0; } else heartbeats += 1; #if ITIMER_HEARTBEAT { void prodHighPriorityThread(void); prodHighPriorityThread(); } #else checkHighPriorityTickees(utcMicrosecondClock); #endif forceInterruptCheckFromHeartbeat(); } #if ITIMER_HEARTBEAT /* Hack for linux server to avoid the thread priority issue, i.e. that * linux doesn't provide priorities for SCHED_OTHER and won't let a non- * superuser process set the scheduling policy to anything else). * * Solution is to drive heartbeat from an interval timer instead of a high- * priority thread blocking in a sleep. We use ITIMER_REAL/SIGALRM (see * below). setitimer(2) claims max itimer resolution on 2.6.13 is 4 * milliseconds, but on 2.6.18-128.el5 one can see periods of 1.2ms. * * The high-priority tickees cannot be run from the interrupt-driven heart- * beat and must be run from a separate thread to avoid numerous sources * of deadlock (e.g. the lock in malloc). But since the thread has the * same priority as the VM thread we arrange that the VM yields to the * high-priority ticker when it is running. This is co-ordinated in * sqTicker.c by ioSynchronousCheckForEvents (the synchronous ticker) * yielding if requested by checkHighPriorityTickees. To perform the yield, * these functions use yieldToHighPriorityTickerThread and * unblockVMThreadAfterYieldToHighPriorityTickerThread to do the dirty work. * * The itimer signal handler ensures it is running on the VM thread and * then invokes a signal handler on the high-priority thread (see * prodHighPriorityThread). This signal breaks the high-priority thread * out of its nanosleep and it calls checkHighPriorityTickees. */ #define TICKER_SIGNAL SIGUSR2 /* SIGURSR1 dumps the stack */ static pthread_t tickerThread; void prodHighPriorityThread() { /* invoke the tickerThread's signal handler */ pthread_kill(tickerThread, TICKER_SIGNAL); } static void high_performance_tick_handler(int sig, struct siginfo *sig_info, void *context) { static int tickCheckInProgress; if (tickCheckInProgress) return; tickCheckInProgress = 1; checkHighPriorityTickees(ioUTCMicroseconds()); tickCheckInProgress = 0; } static void tickerSleepCycle(void *ignored) { struct timespec naptime; naptime.tv_sec = 3600; naptime.tv_nsec = 0; while (1) (void)nanosleep(&naptime, 0); } /* N.B. This is laziness. If needed on other than linux one would have to * initializea mutexattr with PTHREAD_ERRORCHECK_MUTEX type. We require * the errr check because we're lazy in preventing multiple attempts at * locking yield_mutex in yieldToHighPriorityTickerThread. */ static pthread_mutex_t yield_sync = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; static pthread_mutex_t yield_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; static pthread_cond_t yield_cond = PTHREAD_COND_INITIALIZER; /* Private to sqTicker.c ioSynchronousCheckForEvents */ void yieldToHighPriorityTickerThread() { int err; if ((err = pthread_mutex_lock(&yield_mutex))) { if (err != EDEADLK) fprintf(stderr,"pthread_mutex_lock yield_mutex %s\n", strerror(err)); } /* If lock fails then unblockVMThreadAfterYieldToHighPriorityTickerThread * has locked and we should not block. */ if ((err = pthread_mutex_lock(&yield_sync))) { if (err != EDEADLK) fprintf(stderr,"pthread_mutex_lock yield_sync %s\n", strerror(err)); } else if ((err = pthread_cond_wait(&yield_cond, &yield_mutex))) fprintf(stderr,"pthread_cond_wait %s\n", strerror(err)); } /* Private to sqTicker.c checkHighPriorityTickees */ void unblockVMThreadAfterYieldToHighPriorityTickerThread() { /* If yield_sync is already locked the VM thread is very likely blocking in * yieldToHighPriorityTickerThread and so yield_cond should be signalled. */ if (pthread_mutex_trylock(&yield_sync) == 0) /* success */ pthread_mutex_unlock(&yield_sync); else pthread_cond_signal(&yield_cond); } #if !defined(DEFAULT_BEAT_MS) # define DEFAULT_BEAT_MS 2 #endif static int beatMilliseconds = DEFAULT_BEAT_MS; /* Use ITIMER_REAL/SIGALRM because the VM can enter a sleep in the OS via * e.g. ioRelinquishProcessorForMicroseconds in which the OS will assume the * process is not running and not deliver the signals. */ #if 0 # define THE_ITIMER ITIMER_PROF # define ITIMER_SIGNAL SIGPROF #elif 0 # define THE_ITIMER ITIMER_VIRTUAL # define ITIMER_SIGNAL SIGVTALRM #else # define THE_ITIMER ITIMER_REAL # define ITIMER_SIGNAL SIGALRM #endif /* With ticker support it may be that a ticker function invoked heartbeat takes * so long that another timer interrupt occurs before heartbeat has finished. * The absence of SA_NODEFER in heartbeat_handler_action.sa_flags prevents * reentrancy, if available. * * With lots of threads it may be that the kernel delivers the signal on some * other thread. */ #if !defined(SA_NODEFER) static int handling_heartbeat = 0; #endif static void heartbeat_handler(int sig, struct siginfo *sig_info, void *context) { if (!ioOSThreadsEqual(ioCurrentOSThread(),getVMThread())) { pthread_kill(getVMThread(),sig); return; } #if !defined(SA_NODEFER) { int zeroAndPreviousHandlingHeartbeat = 0; sqCompareAndSwap(handling_heartbeat,zeroAndPreviousHandlingHeartbeat,1); if (zeroAndPreviousHandlingHeartbeat) return; } handling_heartbeat = 1; #endif heartbeat(); #if 0 if (heartbeats % 250 == 0) { printf("."); fflush(stdout); } #endif #if !defined(SA_NODEFER) handling_heartbeat = 0; #endif } #define NEED_SIGALTSTACK 1 /* for safety; some time need to turn off and test */ #if NEED_SIGALTSTACK /* If the ticker is run from the heartbeat signal handler one needs to use an * alternative stack to avoid overflowing the VM's stack pages. Keep * the structure around for reference during debugging. */ #define SIGNAL_STACK_SIZE (1024 * sizeof(void *) * 16) static stack_t signal_stack; #endif /* NEED_SIGALTSTACK */ void ioInitHeartbeat() { int er; struct timespec halfAMo; struct sigaction heartbeat_handler_action, ticker_handler_action; struct itimerval pulse; #if NEED_SIGALTSTACK signal_stack.ss_flags = 0; signal_stack.ss_size = SIGNAL_STACK_SIZE; if (!(signal_stack.ss_sp = malloc(signal_stack.ss_size))) { perror("ioInitHeartbeat malloc"); exit(1); } if (sigaltstack(&signal_stack, 0) < 0) { perror("ioInitHeartbeat sigaltstack"); exit(1); } #endif /* NEED_SIGALTSTACK */ halfAMo.tv_sec = 0; halfAMo.tv_nsec = 1000 * 100; if ((er= pthread_create(&tickerThread, (const pthread_attr_t *)0, tickerSleepCycle, 0))) { errno = er; perror("beat thread creation failed"); exit(errno); } ticker_handler_action.sa_sigaction = high_performance_tick_handler; /* N.B. We _do not_ include SA_NODEFER to specifically prevent reentrancy * during the heartbeat. We /must/ include SA_RESTART to avoid issues with * e.g. ODBC connections. */ ticker_handler_action.sa_flags = SA_RESTART | SA_ONSTACK; sigemptyset(&ticker_handler_action.sa_mask); if (sigaction(TICKER_SIGNAL, &ticker_handler_action, 0)) { perror("ioInitHeartbeat sigaction"); exit(1); } heartbeat_handler_action.sa_sigaction = heartbeat_handler; /* N.B. We _do not_ include SA_NODEFER to specifically prevent reentrancy * during the heartbeat. */ #if 0 heartbeat_handler_action.sa_flags = SA_RESTART | SA_ONSTACK; #else /* restarting increases the chance of deadlock? */ heartbeat_handler_action.sa_flags = SA_ONSTACK; #endif sigemptyset(&heartbeat_handler_action.sa_mask); if (sigaction(ITIMER_SIGNAL, &heartbeat_handler_action, 0)) { perror("ioInitHeartbeat sigaction"); exit(1); } pulse.it_interval.tv_sec = beatMilliseconds / 1000; pulse.it_interval.tv_usec = (beatMilliseconds % 1000) * 1000; pulse.it_value = pulse.it_interval; if (setitimer(THE_ITIMER, &pulse, &pulse)) { perror("ioInitHeartbeat setitimer"); exit(1); } } void ioSetHeartbeatMilliseconds(int ms) { beatMilliseconds = ms; ioInitHeartbeat(); } #else /* ITIMER_HEARTBEAT */ typedef enum { dead, condemned, nascent, quiescent, active } machine_state; static int stateMachinePolicy; static struct sched_param stateMachinePriority; static machine_state beatState = nascent; #if !defined(DEFAULT_BEAT_MS) # define DEFAULT_BEAT_MS 2 #endif static int beatMilliseconds = DEFAULT_BEAT_MS; static struct timespec beatperiod = { 0, DEFAULT_BEAT_MS * 1000 * 1000 }; static void * beatStateMachine(void *careLess) { int er; #if !ONLY_ONE_THREAD_PRIORITY if ((er = pthread_setschedparam(pthread_self(), stateMachinePolicy, &stateMachinePriority))) { /* linux pthreads as of 2009 does not support setting the priority of * threads other than with real-time scheduling policies. But such * policies are only available to processes with superuser privileges. */ errno = er; perror("pthread_setschedparam failed"); exit(errno); } #endif /* !ONLY_ONE_THREAD_PRIORITY */ beatState = active; while (beatState != condemned) { # define MINSLEEPNS 2000 /* don't bother sleeping for short times */ struct timespec naptime = beatperiod; while (nanosleep(&naptime, &naptime) == -1 && (naptime.tv_sec > 0 || naptime.tv_nsec > MINSLEEPNS)) /*repeat*/ if (errno != EINTR) { perror("nanosleep"); exit(1); } heartbeat(); } beatState = dead; return 0; } void ioInitHeartbeat() { int er; struct timespec halfAMo; pthread_t careLess; if ((er = pthread_getschedparam(pthread_self(), &stateMachinePolicy, &stateMachinePriority))) { errno = er; perror("pthread_getschedparam failed"); exit(errno); } ++stateMachinePriority.sched_priority; halfAMo.tv_sec = 0; halfAMo.tv_nsec = 1000 * 100; if ((er= pthread_create(&careLess, (const pthread_attr_t *)0, beatStateMachine, 0))) { errno = er; perror("beat thread creation failed"); exit(errno); } while (beatState == nascent) nanosleep(&halfAMo, 0); } void ioSetHeartbeatMilliseconds(int ms) { beatMilliseconds = ms; beatperiod.tv_sec = beatMilliseconds / 1000; beatperiod.tv_nsec = (beatMilliseconds % 1000) * 1000 * 1000; } #endif /* ITIMER_HEARTBEAT */ int ioHeartbeatMilliseconds() { return beatMilliseconds; } /* Answer the average heartbeats per second since the stats were last reset. */ unsigned long ioHeartbeatFrequency(int resetStats) { unsigned duration = (ioUTCMicroseconds() - get64(frequencyMeasureStart)) / MicrosecondsPerSecond; unsigned frequency = duration ? heartbeats / duration : 0; if (resetStats) { unsigned long long zero = 0; set64(frequencyMeasureStart,zero); } return frequency; } ================================================ FILE: vm/src/from_squeak/unix/misc/threadValidate/threadValidate.c ================================================ /* * Linux thread validation. * * Main thread simulates VM running for 10 seconds incrementing a 64-bit * counter, measuring time against the heartbeat's clock, and running any * synchronous tickers that are installed. If the heartbeat gets locked out * its clock will not advance, and the system will lock up. * * High-performance thread spins blocking on some long sleep. heartbeat uses * pthread_kill to deliver a signal to the high-performance thread whose handler * runs the ticker. The heartbeat also install a synchronous ticker that causes * the VM to yield somehow, but installs it only for the duration of the high- * performance thread's tick. i.e. the high-performance thread uninstalls the * ticker when done with each tick. * The yield can be implemented in different ways and we will experiment there- * with. For example, block briefly in a short sleep, call shed_yield, do * a pthreasd_cond_timedwait with a short timeout. * * The high-performance thread's ticker loops for a few milliseconds increment- * ing its own 64-bit counter, simulating work, and then returns. It also * measures time against the heartbeat's clock, and again if the heartbeat gets * locked out its clock will not advance and the system will lockup. * * Main difference this has from current Mac/Win32 codee is that on those * systems the ticker shuts out the clock. Here the heartbeat will simply * leave the thread alone if the ticker is already running (via the inProgress * flag). So this could be better. */ #include #include #include #include #include #include /* for ioNumProcesors */ #include /* for ioNumProcesors */ #include /* for ioNumProcesors */ #include "sq.h" #include "sqAtomicOps.h" #include "sqMemoryFence.h" #define SECS 5 /* run for 5 seconds */ #define CHECK_COUNT (unsigned long long)(100 * 1000 * 1000) pthread_t ioVMThread; static unsigned long long vmcount, hpcount; static volatile int checkForEvents, yield; static int hptickperiodms = 20; static int yield_count = 0, not_blocked_count = 0, unblock_count = 0; static long long hptickusecs = 5 * 1000; static long yieldusecs = 1; /* default */ char *method = "none"; void printAndQuit() { double idealRatio = (double)hptickusecs / (double)(hptickperiodms * 1000); printf("hp/vm %1.3f ideal %1.3f cpus %d yield method %s (usecs %ld)\n", (double)hpcount / (double)vmcount, ioNumProcessors() == 1 ? idealRatio : idealRatio / (1.0 + idealRatio), ioNumProcessors(), method, yieldusecs); printf("vm %10lld hp %9lld hp+vm %10lld yields %d (%d,%d,%d) clk hz %ld\n", vmcount, hpcount, vmcount + hpcount, yield_count, SECS * 1000 / hptickperiodms, unblock_count, not_blocked_count, ioHeartbeatFrequency(0)); exit(0); } void lockedup(int arg) { fprintf(stderr,"system locked %s, time not advancing (yield method %s)\n", arg == SIGINT ? "" : (char *)arg, method); printf("vm %10lld hp %9lld hp+vm %10lld yields %d (%d,%d,%d) clk hz %ld\n", vmcount, hpcount, vmcount + hpcount, yield_count, SECS * 1000 / hptickperiodms, unblock_count, not_blocked_count, ioHeartbeatFrequency(0)); exit(4); } static pthread_mutex_t yield_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; static pthread_cond_t yield_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t yield_sync = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; enum { no_yield, yield_via_sched_yield, yield_via_pthread_yield, yield_via_nanosleep, yield_via_cond_timedwait, yield_via_wait_signal } yieldMethod; #if !YIELD_IN_TICKER void maybeYield() { sqLowLevelMFence(); if (!yield) return; yield_count += 1; switch (yieldMethod) { case no_yield: break; case yield_via_sched_yield: sched_yield(); break; case yield_via_pthread_yield: pthread_yield(); break; case yield_via_nanosleep: { struct timespec yieldtime; yieldtime.tv_sec = 0; yieldtime.tv_nsec = 10 * 1000; break; } case yield_via_cond_timedwait: { struct timespec yieldtime; yieldtime.tv_sec = 0; yieldtime.tv_nsec = 10 * 1000; pthread_cond_timedwait(&yield_cond, &yield_mutex, &yieldtime); break; } case yield_via_wait_signal: { int err; if ((err = pthread_mutex_lock(&yield_mutex))) { if (err != EDEADLK) fprintf(stderr,"pthread_mutex_lock yield_mutex %s\n", strerror(err)); } else if ((err = pthread_mutex_lock(&yield_sync))) { if (err != EDEADLK) fprintf(stderr,"pthread_mutex_lock yield_sync %s\n", strerror(err)); } else { sqLowLevelMFence(); if (yield && (err = pthread_cond_wait(&yield_cond, &yield_mutex))) fprintf(stderr,"pthread_cond_wait %s\n", strerror(err)); } break; } default: fprintf(stderr,"unrecognized yield method\n"); exit(5); } } #endif /* !YIELD_IN_TICKER */ void hptick(void) { unsigned long long start = ioUTCMicroseconds(); yield = 1; sqLowLevelMFence(); while (ioUTCMicroseconds() - start < hptickusecs) if ((hpcount += 1ULL) % CHECK_COUNT == 0 && ioHeartbeatFrequency(0) == 0) lockedup("in hptick"); yield = 0; sqLowLevelMFence(); if (yieldMethod == yield_via_wait_signal) { if (pthread_mutex_trylock(&yield_sync) == 0) {/* success */ pthread_mutex_unlock(&yield_sync); not_blocked_count += 1; } else { pthread_cond_signal(&yield_cond); unblock_count += 1; } } } void forceInterruptCheckFromHeartbeat() { checkForEvents = 1; } void fakevm() { while (1) { (void)ioUTCMicroseconds(); if ((vmcount += 1ULL) % CHECK_COUNT == 0 && ioHeartbeatFrequency(0) == 0) lockedup("in vm"); if (checkForEvents) { checkForEvents = 0; ioSynchronousCheckForEvents(); } } } int main(int argc, char *argv[]) { int err; signal(SIGINT, lockedup); ioVMThread = pthread_self(); ioInitTime(); ioInitHeartbeat(); addSynchronousTickee(printAndQuit, SECS * 1000, 0); if (argc > 1) { method = argv[1]; if (!strcmp(argv[1],"none")) yieldMethod = no_yield; else if (!strcmp(argv[1],"sched_yield")) yieldMethod = yield_via_sched_yield; else if (!strcmp(argv[1],"pthread_yield")) yieldMethod = yield_via_pthread_yield; else if (!strcmp(argv[1],"nanosleep")) yieldMethod = yield_via_nanosleep; else if (!strcmp(argv[1],"cond_timedwait")) { if ((err = pthread_mutex_lock(&yield_mutex))) return 2; yieldMethod = yield_via_cond_timedwait; } else if (!strcmp(argv[1],"wait_signal")) yieldMethod = yield_via_wait_signal; else { fprintf(stderr, "usage: %s [none] [sched_yield] [nanosleep] [cond_timedwait] [wait_signal] [yield usecs]\n", argv[0]); return 3; } if (argc > 2) yieldusecs = atoi(argv[2]); #if !YIELD_IN_TICKER addSynchronousTickee(maybeYield, 2, 0); #endif /* !YIELD_IN_TICKER */ } addHighPriorityTickee(hptick, hptickperiodms); fakevm(); /* should exit through printAndQuit */ return 1; } int ioNumProcessors(void) { # if defined(CTL_HW) && defined(HW_AVAILCPU) int count; size_t size = sizeof(count); int hw_availproc[2]; hw_availproc[0] = CTL_HW; hw_availproc[1] = HW_AVAILCPU; return sysctl(hw_availproc, 2, &count, &size, 0, 0) ? 1 : count; # elif defined(_SC_NPROCESSORS_ONLN) int count; return (count = sysconf(_SC_NPROCESSORS_ONLN)) == -1 ? 1 : count; # else printf("could not determine number of processors; assuming 1\n"); return 1; # endif } void warning(char *msg) { fprintf(stderr,"%s\n", msg); } ================================================ FILE: vm/src/from_squeak/unix/npsqueak/Makefile ================================================ # Netscape Plugin for Squeak on Unix platforms # Author: Bert Freudenberg # Last edited: 2005-02-28 16:57:51 by jens on impara.de ############ Customize flags here ####################### INC = -I./include -I/usr/X11R6/include CC = gcc CFLAGS = $(INC) -O2 -fPIC -Wall LD = gcc LDFLAGS = -shared # usually overridden from top level makefile VM_VERSION= 3.7b-5 bindir= /usr/local/bin imgdir= /usr/local/share/squeak plgdir= /usr/local/lib/squeak/$(VM_VERSION) # configuration scriptdir= $(imgdir) npsqueakrun= npsqueakrun ############ compile and link ########################### all: npsqueak.so npsqueakrun npsqueak.so : npsqueak.o npunix.o $(LD) $(LDFLAGS) npsqueak.o npunix.o -o npsqueak.so npsqueak.o: npsqueak.c ../config.h $(CC) -c $(CFLAGS) \ -DSYSTEM_BIN_DIR=\"$(scriptdir)\" \ -DSYSTEM_IMG_DIR=\"$(imgdir)\" \ -DNPSQUEAKRUN=\"$(npsqueakrun)\" $< npunix.o: npunix.c $(CC) -c $(CFLAGS) $< npsqueakrun: npsqueakrun.in sed "s|@imgdir@|$(imgdir)|; \ s|@VM_VERSION@|$(VM_VERSION)|" \ npsqueakrun.in > $@ chmod +x $@ npsqueakregister: npsqueakregister.in sed "s|@NPSQUEAK_SO@|$(plgdir)/npsqueak.so|" \ npsqueakregister.in > $@ chmod +x $@ clean: -rm -f *.o *.so *~ .*~ */*~ */.*~ ############ install #################################### $(ROOT)$(scriptdir): install -d $@ $(ROOT)$(plgdir): install -d $@ $(ROOT)$(plgdir)/npsqueak.so: npsqueak.so $(ROOT)$(plgdir) cp npsqueak.so $@ strip $@ $(ROOT)$(scriptdir)/npsqueakrun: npsqueakrun $(ROOT)$(scriptdir) cp npsqueakrun $@ $(ROOT)$(imgdir)/npsqueakregister: npsqueakregister $(ROOT)$(scriptdir) cp npsqueakregister $@ ### Go! ### NPSQUEAK_TARGETS= \ $(ROOT)$(plgdir)/npsqueak.so \ $(ROOT)$(scriptdir)/npsqueakrun \ $(ROOT)$(scriptdir)/npsqueakregister install: $(NPSQUEAK_TARGETS) uninstall: rmdir --ignore-fail-on-non-empty $(ROOT)$(imgdir) rm -rf $(NPSQUEAK_TARGETS) ================================================ FILE: vm/src/from_squeak/unix/npsqueak/README.npsqueak ================================================ ================================================================= Netscape Plugin for Squeak on Unix platforms Author: Bert Freudenberg Version: @VM_VERSION@ Last edited: 2005-02-28 15:50:31 by jens on impara.de ================================================================ Files: Makefile README.npsqueak npsqueak.c npunix.c (modified copy from Netscape Plugin SDK) include/* (unmodified headers from Netscape Plugin SDK) test/* ================================================================= The Squeak plugin should be automatically compiled and installed with the normal squeak build process. This installs squeak into (probably) imgdir=/usr/local/lib/squeak You will need an image. Copy it to ${imgdir}/SqueakPlugin.image A good place to look for an image suited as plugin is http://squeakland.org/plugin/installers/files.html To register the plugin run ${imgdir}/npsqueakregister. It looks for various browsers in various directories and creates links to the plugin. If your browser is not found, hack the npsqueakregister script or symlink the plugin manually: ln -s ${imgdir}/@VM_VERSION@/npsqueak.so \ /usr/lib/mybrowser/plugins/ Exit and restart the browser. Check if the Squeak plugin was recognized by selecting the Help>>About Plugins menu item. Open the html file in the test/ directory. This should activate the Squeak plugin. Since this is the first time the plugin is executed, a .npsqueak folder will be created in your home directory and the plugin image is installed into it. ================================================================= NOTE: If you are not the super user of your machine you can install everything into your home directory. Put npsqueak.so somewhere your browser will find it. Make a .npsqueak dir in your home directory with subdirectories and files like shown below. Also create a .npsqueak/npsqueakrun file which points to a Squeak VM. ================================================================= DOCUMENTATION * On the first run for each user, the npsqueakrun will create a directory structure like this: $(HOME)/ | +--- .npsqueak/ | +--- SqueakPlugin.image | |--- *.image | +--- secure/ | +--- My Squeak/ $(imgdir)/ | +--- SqueakPlugin.image * Environment Variables: SQUEAK_USERDIR Identifies the sandbox directory, e.g., a place which can be accessed from any (potentially unsafe) Squeaklet. * path must be absolute * Default: "~/.npsqueak/My Squeak" NPSQUEAK_DEBUG logs debug info to /tmp/npsqueak.log Default: don't log * Mimetypes: application/x-squeak-source:sts:Squeak source application/x-squeak-object:sqo:Squeak object application/x-squeak-project:pr:Squeak project * Parameters: parameters in EMBED tag used by Squeak: SRC=... MEMORY=... (not by unix npsqueak) FAILUREURL=... IMAGENAME=... * Communication with VM is via Pipes ================================================================= TODO * loop on read() and write() until all data is sent and received. * make plugin not wait for browser when the url is loaded into a target. * use autoconf ================================================================= Change log Jan 2005: * npsqueak checks for image file in system and home dir * modified npsqueakrun, runs with bash, other shells untested * renamed untrusted -> My Squeak * fixed make sure Squeak really gets killed * fixed crashing the browser when closing plugin page Apr 2004: * (ikp) handle imageName and failureUrl tags Oct 2002: * modified install from home directory to system-wide Sep 2002: * hack to work with Mozilla >= 1.0 which deletes the delivered file immediately. We just create a hard link before and delete that after opening the file. Mar 2002: * uses aio now for command pipe * moved stuff from ~/.netscape/squeak to ~/.npsqueak directory * implemented SecurityPlugin May 2001: * updated for squeakland.org image. * TODO: SecurityManager Feb 2001: * updated for Squeak 3.0 Nov 2000: * introduced -browserPipes command line * this fixed the bug of plugins in tables * cleaned up a lot of hacks * this fixed crashing Mozilla 0.6 * made widget destroy work more often than not * Problems: crashes when closing Netscape window * pipe is polled for now - should use select in sqXWindow Apr 2000: * url requests through browser Nov 1999 * report attributes to vm Aug 1999 * initial version ================================================ FILE: vm/src/from_squeak/unix/npsqueak/include/jri.h ================================================ /* -*- Mode: C; tab-width: 4; -*- */ /******************************************************************************* * Java Runtime Interface * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. ******************************************************************************/ #ifndef JRI_H #define JRI_H #include "jritypes.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /******************************************************************************* * JRIEnv ******************************************************************************/ /* The type of the JRIEnv interface. */ typedef struct JRIEnvInterface JRIEnvInterface; /* The type of a JRIEnv instance. */ typedef const JRIEnvInterface* JRIEnv; /******************************************************************************* * JRIEnv Operations ******************************************************************************/ #define JRI_LoadClass(env, buf, bufLen) \ (((*(env))->LoadClass)(env, JRI_LoadClass_op, buf, bufLen)) #define JRI_FindClass(env, name) \ (((*(env))->FindClass)(env, JRI_FindClass_op, name)) #define JRI_Throw(env, obj) \ (((*(env))->Throw)(env, JRI_Throw_op, obj)) #define JRI_ThrowNew(env, clazz, message) \ (((*(env))->ThrowNew)(env, JRI_ThrowNew_op, clazz, message)) #define JRI_ExceptionOccurred(env) \ (((*(env))->ExceptionOccurred)(env, JRI_ExceptionOccurred_op)) #define JRI_ExceptionDescribe(env) \ (((*(env))->ExceptionDescribe)(env, JRI_ExceptionDescribe_op)) #define JRI_ExceptionClear(env) \ (((*(env))->ExceptionClear)(env, JRI_ExceptionClear_op)) #define JRI_NewGlobalRef(env, ref) \ (((*(env))->NewGlobalRef)(env, JRI_NewGlobalRef_op, ref)) #define JRI_DisposeGlobalRef(env, gref) \ (((*(env))->DisposeGlobalRef)(env, JRI_DisposeGlobalRef_op, gref)) #define JRI_GetGlobalRef(env, gref) \ (((*(env))->GetGlobalRef)(env, JRI_GetGlobalRef_op, gref)) #define JRI_SetGlobalRef(env, gref, ref) \ (((*(env))->SetGlobalRef)(env, JRI_SetGlobalRef_op, gref, ref)) #define JRI_IsSameObject(env, a, b) \ (((*(env))->IsSameObject)(env, JRI_IsSameObject_op, a, b)) #define JRI_NewObject(env) ((*(env))->NewObject) #define JRI_NewObjectV(env, clazz, methodID, args) \ (((*(env))->NewObjectV)(env, JRI_NewObject_op_va_list, clazz, methodID, args)) #define JRI_NewObjectA(env, clazz, method, args) \ (((*(env))->NewObjectA)(env, JRI_NewObject_op_array, clazz, methodID, args)) #define JRI_GetObjectClass(env, obj) \ (((*(env))->GetObjectClass)(env, JRI_GetObjectClass_op, obj)) #define JRI_IsInstanceOf(env, obj, clazz) \ (((*(env))->IsInstanceOf)(env, JRI_IsInstanceOf_op, obj, clazz)) #define JRI_GetMethodID(env, clazz, name, sig) \ (((*(env))->GetMethodID)(env, JRI_GetMethodID_op, clazz, name, sig)) #define JRI_CallMethod(env) ((*(env))->CallMethod) #define JRI_CallMethodV(env, obj, methodID, args) \ (((*(env))->CallMethodV)(env, JRI_CallMethod_op_va_list, obj, methodID, args)) #define JRI_CallMethodA(env, obj, methodID, args) \ (((*(env))->CallMethodA)(env, JRI_CallMethod_op_array, obj, methodID, args)) #define JRI_CallMethodBoolean(env) ((*(env))->CallMethodBoolean) #define JRI_CallMethodBooleanV(env, obj, methodID, args) \ (((*(env))->CallMethodBooleanV)(env, JRI_CallMethodBoolean_op_va_list, obj, methodID, args)) #define JRI_CallMethodBooleanA(env, obj, methodID, args) \ (((*(env))->CallMethodBooleanA)(env, JRI_CallMethodBoolean_op_array, obj, methodID, args)) #define JRI_CallMethodByte(env) ((*(env))->CallMethodByte) #define JRI_CallMethodByteV(env, obj, methodID, args) \ (((*(env))->CallMethodByteV)(env, JRI_CallMethodByte_op_va_list, obj, methodID, args)) #define JRI_CallMethodByteA(env, obj, methodID, args) \ (((*(env))->CallMethodByteA)(env, JRI_CallMethodByte_op_array, obj, methodID, args)) #define JRI_CallMethodChar(env) ((*(env))->CallMethodChar) #define JRI_CallMethodCharV(env, obj, methodID, args) \ (((*(env))->CallMethodCharV)(env, JRI_CallMethodChar_op_va_list, obj, methodID, args)) #define JRI_CallMethodCharA(env, obj, methodID, args) \ (((*(env))->CallMethodCharA)(env, JRI_CallMethodChar_op_array, obj, methodID, args)) #define JRI_CallMethodShort(env) ((*(env))->CallMethodShort) #define JRI_CallMethodShortV(env, obj, methodID, args) \ (((*(env))->CallMethodShortV)(env, JRI_CallMethodShort_op_va_list, obj, methodID, args)) #define JRI_CallMethodShortA(env, obj, methodID, args) \ (((*(env))->CallMethodShortA)(env, JRI_CallMethodShort_op_array, obj, methodID, args)) #define JRI_CallMethodInt(env) ((*(env))->CallMethodInt) #define JRI_CallMethodIntV(env, obj, methodID, args) \ (((*(env))->CallMethodIntV)(env, JRI_CallMethodInt_op_va_list, obj, methodID, args)) #define JRI_CallMethodIntA(env, obj, methodID, args) \ (((*(env))->CallMethodIntA)(env, JRI_CallMethodInt_op_array, obj, methodID, args)) #define JRI_CallMethodLong(env) ((*(env))->CallMethodLong) #define JRI_CallMethodLongV(env, obj, methodID, args) \ (((*(env))->CallMethodLongV)(env, JRI_CallMethodLong_op_va_list, obj, methodID, args)) #define JRI_CallMethodLongA(env, obj, methodID, args) \ (((*(env))->CallMethodLongA)(env, JRI_CallMethodLong_op_array, obj, methodID, args)) #define JRI_CallMethodFloat(env) ((*(env))->CallMethodFloat) #define JRI_CallMethodFloatV(env, obj, methodID, args) \ (((*(env))->CallMethodFloatV)(env, JRI_CallMethodFloat_op_va_list, obj, methodID, args)) #define JRI_CallMethodFloatA(env, obj, methodID, args) \ (((*(env))->CallMethodFloatA)(env, JRI_CallMethodFloat_op_array, obj, methodID, args)) #define JRI_CallMethodDouble(env) ((*(env))->CallMethodDouble) #define JRI_CallMethodDoubleV(env, obj, methodID, args) \ (((*(env))->CallMethodDoubleV)(env, JRI_CallMethodDouble_op_va_list, obj, methodID, args)) #define JRI_CallMethodDoubleA(env, obj, methodID, args) \ (((*(env))->CallMethodDoubleA)(env, JRI_CallMethodDouble_op_array, obj, methodID, args)) #define JRI_GetFieldID(env, clazz, name, sig) \ (((*(env))->GetFieldID)(env, JRI_GetFieldID_op, clazz, name, sig)) #define JRI_GetField(env, obj, fieldID) \ (((*(env))->GetField)(env, JRI_GetField_op, obj, fieldID)) #define JRI_GetFieldBoolean(env, obj, fieldID) \ (((*(env))->GetFieldBoolean)(env, JRI_GetFieldBoolean_op, obj, fieldID)) #define JRI_GetFieldByte(env, obj, fieldID) \ (((*(env))->GetFieldByte)(env, JRI_GetFieldByte_op, obj, fieldID)) #define JRI_GetFieldChar(env, obj, fieldID) \ (((*(env))->GetFieldChar)(env, JRI_GetFieldChar_op, obj, fieldID)) #define JRI_GetFieldShort(env, obj, fieldID) \ (((*(env))->GetFieldShort)(env, JRI_GetFieldShort_op, obj, fieldID)) #define JRI_GetFieldInt(env, obj, fieldID) \ (((*(env))->GetFieldInt)(env, JRI_GetFieldInt_op, obj, fieldID)) #define JRI_GetFieldLong(env, obj, fieldID) \ (((*(env))->GetFieldLong)(env, JRI_GetFieldLong_op, obj, fieldID)) #define JRI_GetFieldFloat(env, obj, fieldID) \ (((*(env))->GetFieldFloat)(env, JRI_GetFieldFloat_op, obj, fieldID)) #define JRI_GetFieldDouble(env, obj, fieldID) \ (((*(env))->GetFieldDouble)(env, JRI_GetFieldDouble_op, obj, fieldID)) #define JRI_SetField(env, obj, fieldID, value) \ (((*(env))->SetField)(env, JRI_SetField_op, obj, fieldID, value)) #define JRI_SetFieldBoolean(env, obj, fieldID, value) \ (((*(env))->SetFieldBoolean)(env, JRI_SetFieldBoolean_op, obj, fieldID, value)) #define JRI_SetFieldByte(env, obj, fieldID, value) \ (((*(env))->SetFieldByte)(env, JRI_SetFieldByte_op, obj, fieldID, value)) #define JRI_SetFieldChar(env, obj, fieldID, value) \ (((*(env))->SetFieldChar)(env, JRI_SetFieldChar_op, obj, fieldID, value)) #define JRI_SetFieldShort(env, obj, fieldID, value) \ (((*(env))->SetFieldShort)(env, JRI_SetFieldShort_op, obj, fieldID, value)) #define JRI_SetFieldInt(env, obj, fieldID, value) \ (((*(env))->SetFieldInt)(env, JRI_SetFieldInt_op, obj, fieldID, value)) #define JRI_SetFieldLong(env, obj, fieldID, value) \ (((*(env))->SetFieldLong)(env, JRI_SetFieldLong_op, obj, fieldID, value)) #define JRI_SetFieldFloat(env, obj, fieldID, value) \ (((*(env))->SetFieldFloat)(env, JRI_SetFieldFloat_op, obj, fieldID, value)) #define JRI_SetFieldDouble(env, obj, fieldID, value) \ (((*(env))->SetFieldDouble)(env, JRI_SetFieldDouble_op, obj, fieldID, value)) #define JRI_IsSubclassOf(env, a, b) \ (((*(env))->IsSubclassOf)(env, JRI_IsSubclassOf_op, a, b)) #define JRI_GetStaticMethodID(env, clazz, name, sig) \ (((*(env))->GetStaticMethodID)(env, JRI_GetStaticMethodID_op, clazz, name, sig)) #define JRI_CallStaticMethod(env) ((*(env))->CallStaticMethod) #define JRI_CallStaticMethodV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodV)(env, JRI_CallStaticMethod_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodA)(env, JRI_CallStaticMethod_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodBoolean(env) ((*(env))->CallStaticMethodBoolean) #define JRI_CallStaticMethodBooleanV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodBooleanV)(env, JRI_CallStaticMethodBoolean_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodBooleanA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodBooleanA)(env, JRI_CallStaticMethodBoolean_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodByte(env) ((*(env))->CallStaticMethodByte) #define JRI_CallStaticMethodByteV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodByteV)(env, JRI_CallStaticMethodByte_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodByteA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodByteA)(env, JRI_CallStaticMethodByte_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodChar(env) ((*(env))->CallStaticMethodChar) #define JRI_CallStaticMethodCharV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodCharV)(env, JRI_CallStaticMethodChar_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodCharA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodCharA)(env, JRI_CallStaticMethodChar_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodShort(env) ((*(env))->CallStaticMethodShort) #define JRI_CallStaticMethodShortV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodShortV)(env, JRI_CallStaticMethodShort_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodShortA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodShortA)(env, JRI_CallStaticMethodShort_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodInt(env) ((*(env))->CallStaticMethodInt) #define JRI_CallStaticMethodIntV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodIntV)(env, JRI_CallStaticMethodInt_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodIntA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodIntA)(env, JRI_CallStaticMethodInt_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodLong(env) ((*(env))->CallStaticMethodLong) #define JRI_CallStaticMethodLongV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodLongV)(env, JRI_CallStaticMethodLong_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodLongA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodLongA)(env, JRI_CallStaticMethodLong_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodFloat(env) ((*(env))->CallStaticMethodFloat) #define JRI_CallStaticMethodFloatV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodFloatV)(env, JRI_CallStaticMethodFloat_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodFloatA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodFloatA)(env, JRI_CallStaticMethodFloat_op_array, clazz, methodID, args)) #define JRI_CallStaticMethodDouble(env) ((*(env))->CallStaticMethodDouble) #define JRI_CallStaticMethodDoubleV(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodDoubleV)(env, JRI_CallStaticMethodDouble_op_va_list, clazz, methodID, args)) #define JRI_CallStaticMethodDoubleA(env, clazz, methodID, args) \ (((*(env))->CallStaticMethodDoubleA)(env, JRI_CallStaticMethodDouble_op_array, clazz, methodID, args)) #define JRI_GetStaticFieldID(env, clazz, name, sig) \ (((*(env))->GetStaticFieldID)(env, JRI_GetStaticFieldID_op, clazz, name, sig)) #define JRI_GetStaticField(env, clazz, fieldID) \ (((*(env))->GetStaticField)(env, JRI_GetStaticField_op, clazz, fieldID)) #define JRI_GetStaticFieldBoolean(env, clazz, fieldID) \ (((*(env))->GetStaticFieldBoolean)(env, JRI_GetStaticFieldBoolean_op, clazz, fieldID)) #define JRI_GetStaticFieldByte(env, clazz, fieldID) \ (((*(env))->GetStaticFieldByte)(env, JRI_GetStaticFieldByte_op, clazz, fieldID)) #define JRI_GetStaticFieldChar(env, clazz, fieldID) \ (((*(env))->GetStaticFieldChar)(env, JRI_GetStaticFieldChar_op, clazz, fieldID)) #define JRI_GetStaticFieldShort(env, clazz, fieldID) \ (((*(env))->GetStaticFieldShort)(env, JRI_GetStaticFieldShort_op, clazz, fieldID)) #define JRI_GetStaticFieldInt(env, clazz, fieldID) \ (((*(env))->GetStaticFieldInt)(env, JRI_GetStaticFieldInt_op, clazz, fieldID)) #define JRI_GetStaticFieldLong(env, clazz, fieldID) \ (((*(env))->GetStaticFieldLong)(env, JRI_GetStaticFieldLong_op, clazz, fieldID)) #define JRI_GetStaticFieldFloat(env, clazz, fieldID) \ (((*(env))->GetStaticFieldFloat)(env, JRI_GetStaticFieldFloat_op, clazz, fieldID)) #define JRI_GetStaticFieldDouble(env, clazz, fieldID) \ (((*(env))->GetStaticFieldDouble)(env, JRI_GetStaticFieldDouble_op, clazz, fieldID)) #define JRI_SetStaticField(env, clazz, fieldID, value) \ (((*(env))->SetStaticField)(env, JRI_SetStaticField_op, clazz, fieldID, value)) #define JRI_SetStaticFieldBoolean(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldBoolean)(env, JRI_SetStaticFieldBoolean_op, clazz, fieldID, value)) #define JRI_SetStaticFieldByte(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldByte)(env, JRI_SetStaticFieldByte_op, clazz, fieldID, value)) #define JRI_SetStaticFieldChar(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldChar)(env, JRI_SetStaticFieldChar_op, clazz, fieldID, value)) #define JRI_SetStaticFieldShort(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldShort)(env, JRI_SetStaticFieldShort_op, clazz, fieldID, value)) #define JRI_SetStaticFieldInt(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldInt)(env, JRI_SetStaticFieldInt_op, clazz, fieldID, value)) #define JRI_SetStaticFieldLong(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldLong)(env, JRI_SetStaticFieldLong_op, clazz, fieldID, value)) #define JRI_SetStaticFieldFloat(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldFloat)(env, JRI_SetStaticFieldFloat_op, clazz, fieldID, value)) #define JRI_SetStaticFieldDouble(env, clazz, fieldID, value) \ (((*(env))->SetStaticFieldDouble)(env, JRI_SetStaticFieldDouble_op, clazz, fieldID, value)) #define JRI_NewString(env, unicode, len) \ (((*(env))->NewString)(env, JRI_NewString_op, unicode, len)) #define JRI_GetStringLength(env, string) \ (((*(env))->GetStringLength)(env, JRI_GetStringLength_op, string)) #define JRI_GetStringChars(env, string) \ (((*(env))->GetStringChars)(env, JRI_GetStringChars_op, string)) #define JRI_NewStringUTF(env, utf, len) \ (((*(env))->NewStringUTF)(env, JRI_NewStringUTF_op, utf, len)) #define JRI_GetStringUTFLength(env, string) \ (((*(env))->GetStringUTFLength)(env, JRI_GetStringUTFLength_op, string)) #define JRI_GetStringUTFChars(env, string) \ (((*(env))->GetStringUTFChars)(env, JRI_GetStringUTFChars_op, string)) #define JRI_NewScalarArray(env, length, elementSig, initialElements) \ (((*(env))->NewScalarArray)(env, JRI_NewScalarArray_op, length, elementSig, initialElements)) #define JRI_GetScalarArrayLength(env, array) \ (((*(env))->GetScalarArrayLength)(env, JRI_GetScalarArrayLength_op, array)) #define JRI_GetScalarArrayElements(env, array) \ (((*(env))->GetScalarArrayElements)(env, JRI_GetScalarArrayElements_op, array)) #define JRI_NewObjectArray(env, length, elementClass, initialElement) \ (((*(env))->NewObjectArray)(env, JRI_NewObjectArray_op, length, elementClass, initialElement)) #define JRI_GetObjectArrayLength(env, array) \ (((*(env))->GetObjectArrayLength)(env, JRI_GetObjectArrayLength_op, array)) #define JRI_GetObjectArrayElement(env, array, index) \ (((*(env))->GetObjectArrayElement)(env, JRI_GetObjectArrayElement_op, array, index)) #define JRI_SetObjectArrayElement(env, array, index, value) \ (((*(env))->SetObjectArrayElement)(env, JRI_SetObjectArrayElement_op, array, index, value)) #define JRI_RegisterNatives(env, clazz, nameAndSigArray, nativeProcArray) \ (((*(env))->RegisterNatives)(env, JRI_RegisterNatives_op, clazz, nameAndSigArray, nativeProcArray)) #define JRI_UnregisterNatives(env, clazz) \ (((*(env))->UnregisterNatives)(env, JRI_UnregisterNatives_op, clazz)) /******************************************************************************* * JRIEnv Interface ******************************************************************************/ struct java_lang_Class; struct java_lang_Throwable; struct java_lang_Object; struct java_lang_String; struct JRIEnvInterface { void* reserved0; void* reserved1; void* reserved2; struct java_lang_Class* (*LoadClass)(JRIEnv* env, jint op, jbyte* a, jsize aLen); struct java_lang_Class* (*FindClass)(JRIEnv* env, jint op, const char* a); void (*Throw)(JRIEnv* env, jint op, struct java_lang_Throwable* a); void (*ThrowNew)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b); struct java_lang_Throwable* (*ExceptionOccurred)(JRIEnv* env, jint op); void (*ExceptionDescribe)(JRIEnv* env, jint op); void (*ExceptionClear)(JRIEnv* env, jint op); jglobal (*NewGlobalRef)(JRIEnv* env, jint op, void* a); void (*DisposeGlobalRef)(JRIEnv* env, jint op, jglobal a); void* (*GetGlobalRef)(JRIEnv* env, jint op, jglobal a); void (*SetGlobalRef)(JRIEnv* env, jint op, jglobal a, void* b); jbool (*IsSameObject)(JRIEnv* env, jint op, void* a, void* b); void* (*NewObject)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); void* (*NewObjectV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); void* (*NewObjectA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); struct java_lang_Class* (*GetObjectClass)(JRIEnv* env, jint op, void* a); jbool (*IsInstanceOf)(JRIEnv* env, jint op, void* a, struct java_lang_Class* b); jint (*GetMethodID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); void* (*CallMethod)(JRIEnv* env, jint op, void* a, jint b, ...); void* (*CallMethodV)(JRIEnv* env, jint op, void* a, jint b, va_list c); void* (*CallMethodA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jbool (*CallMethodBoolean)(JRIEnv* env, jint op, void* a, jint b, ...); jbool (*CallMethodBooleanV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jbool (*CallMethodBooleanA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jbyte (*CallMethodByte)(JRIEnv* env, jint op, void* a, jint b, ...); jbyte (*CallMethodByteV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jbyte (*CallMethodByteA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jchar (*CallMethodChar)(JRIEnv* env, jint op, void* a, jint b, ...); jchar (*CallMethodCharV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jchar (*CallMethodCharA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jshort (*CallMethodShort)(JRIEnv* env, jint op, void* a, jint b, ...); jshort (*CallMethodShortV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jshort (*CallMethodShortA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jint (*CallMethodInt)(JRIEnv* env, jint op, void* a, jint b, ...); jint (*CallMethodIntV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jint (*CallMethodIntA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jlong (*CallMethodLong)(JRIEnv* env, jint op, void* a, jint b, ...); jlong (*CallMethodLongV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jlong (*CallMethodLongA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jfloat (*CallMethodFloat)(JRIEnv* env, jint op, void* a, jint b, ...); jfloat (*CallMethodFloatV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jfloat (*CallMethodFloatA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jdouble (*CallMethodDouble)(JRIEnv* env, jint op, void* a, jint b, ...); jdouble (*CallMethodDoubleV)(JRIEnv* env, jint op, void* a, jint b, va_list c); jdouble (*CallMethodDoubleA)(JRIEnv* env, jint op, void* a, jint b, JRIValue* c); jint (*GetFieldID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); void* (*GetField)(JRIEnv* env, jint op, void* a, jint b); jbool (*GetFieldBoolean)(JRIEnv* env, jint op, void* a, jint b); jbyte (*GetFieldByte)(JRIEnv* env, jint op, void* a, jint b); jchar (*GetFieldChar)(JRIEnv* env, jint op, void* a, jint b); jshort (*GetFieldShort)(JRIEnv* env, jint op, void* a, jint b); jint (*GetFieldInt)(JRIEnv* env, jint op, void* a, jint b); jlong (*GetFieldLong)(JRIEnv* env, jint op, void* a, jint b); jfloat (*GetFieldFloat)(JRIEnv* env, jint op, void* a, jint b); jdouble (*GetFieldDouble)(JRIEnv* env, jint op, void* a, jint b); void (*SetField)(JRIEnv* env, jint op, void* a, jint b, void* c); void (*SetFieldBoolean)(JRIEnv* env, jint op, void* a, jint b, jbool c); void (*SetFieldByte)(JRIEnv* env, jint op, void* a, jint b, jbyte c); void (*SetFieldChar)(JRIEnv* env, jint op, void* a, jint b, jchar c); void (*SetFieldShort)(JRIEnv* env, jint op, void* a, jint b, jshort c); void (*SetFieldInt)(JRIEnv* env, jint op, void* a, jint b, jint c); void (*SetFieldLong)(JRIEnv* env, jint op, void* a, jint b, jlong c); void (*SetFieldFloat)(JRIEnv* env, jint op, void* a, jint b, jfloat c); void (*SetFieldDouble)(JRIEnv* env, jint op, void* a, jint b, jdouble c); jbool (*IsSubclassOf)(JRIEnv* env, jint op, struct java_lang_Class* a, struct java_lang_Class* b); jint (*GetStaticMethodID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); void* (*CallStaticMethod)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); void* (*CallStaticMethodV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); void* (*CallStaticMethodA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jbool (*CallStaticMethodBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jbool (*CallStaticMethodBooleanV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jbool (*CallStaticMethodBooleanA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jbyte (*CallStaticMethodByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jbyte (*CallStaticMethodByteV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jbyte (*CallStaticMethodByteA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jchar (*CallStaticMethodChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jchar (*CallStaticMethodCharV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jchar (*CallStaticMethodCharA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jshort (*CallStaticMethodShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jshort (*CallStaticMethodShortV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jshort (*CallStaticMethodShortA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jint (*CallStaticMethodInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jint (*CallStaticMethodIntV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jint (*CallStaticMethodIntA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jlong (*CallStaticMethodLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jlong (*CallStaticMethodLongV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jlong (*CallStaticMethodLongA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jfloat (*CallStaticMethodFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jfloat (*CallStaticMethodFloatV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jfloat (*CallStaticMethodFloatA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jdouble (*CallStaticMethodDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, ...); jdouble (*CallStaticMethodDoubleV)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, va_list c); jdouble (*CallStaticMethodDoubleA)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, JRIValue* c); jint (*GetStaticFieldID)(JRIEnv* env, jint op, struct java_lang_Class* a, const char* b, const char* c); void* (*GetStaticField)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jbool (*GetStaticFieldBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jbyte (*GetStaticFieldByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jchar (*GetStaticFieldChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jshort (*GetStaticFieldShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jint (*GetStaticFieldInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jlong (*GetStaticFieldLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jfloat (*GetStaticFieldFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); jdouble (*GetStaticFieldDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b); void (*SetStaticField)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, void* c); void (*SetStaticFieldBoolean)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jbool c); void (*SetStaticFieldByte)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jbyte c); void (*SetStaticFieldChar)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jchar c); void (*SetStaticFieldShort)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jshort c); void (*SetStaticFieldInt)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jint c); void (*SetStaticFieldLong)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jlong c); void (*SetStaticFieldFloat)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jfloat c); void (*SetStaticFieldDouble)(JRIEnv* env, jint op, struct java_lang_Class* a, jint b, jdouble c); struct java_lang_String* (*NewString)(JRIEnv* env, jint op, const jchar* a, jint b); jint (*GetStringLength)(JRIEnv* env, jint op, struct java_lang_String* a); const jchar* (*GetStringChars)(JRIEnv* env, jint op, struct java_lang_String* a); struct java_lang_String* (*NewStringUTF)(JRIEnv* env, jint op, const jbyte* a, jint b); jint (*GetStringUTFLength)(JRIEnv* env, jint op, struct java_lang_String* a); const jbyte* (*GetStringUTFChars)(JRIEnv* env, jint op, struct java_lang_String* a); void* (*NewScalarArray)(JRIEnv* env, jint op, jint a, const char* b, const jbyte* c); jint (*GetScalarArrayLength)(JRIEnv* env, jint op, void* a); jbyte* (*GetScalarArrayElements)(JRIEnv* env, jint op, void* a); void* (*NewObjectArray)(JRIEnv* env, jint op, jint a, struct java_lang_Class* b, void* c); jint (*GetObjectArrayLength)(JRIEnv* env, jint op, void* a); void* (*GetObjectArrayElement)(JRIEnv* env, jint op, void* a, jint b); void (*SetObjectArrayElement)(JRIEnv* env, jint op, void* a, jint b, void* c); void (*RegisterNatives)(JRIEnv* env, jint op, struct java_lang_Class* a, char** b, void** c); void (*UnregisterNatives)(JRIEnv* env, jint op, struct java_lang_Class* a); }; /******************************************************************************* * JRIEnv Operation IDs ******************************************************************************/ typedef enum JRIEnvOperations { JRI_Reserved0_op, JRI_Reserved1_op, JRI_Reserved2_op, JRI_LoadClass_op, JRI_FindClass_op, JRI_Throw_op, JRI_ThrowNew_op, JRI_ExceptionOccurred_op, JRI_ExceptionDescribe_op, JRI_ExceptionClear_op, JRI_NewGlobalRef_op, JRI_DisposeGlobalRef_op, JRI_GetGlobalRef_op, JRI_SetGlobalRef_op, JRI_IsSameObject_op, JRI_NewObject_op, JRI_NewObject_op_va_list, JRI_NewObject_op_array, JRI_GetObjectClass_op, JRI_IsInstanceOf_op, JRI_GetMethodID_op, JRI_CallMethod_op, JRI_CallMethod_op_va_list, JRI_CallMethod_op_array, JRI_CallMethodBoolean_op, JRI_CallMethodBoolean_op_va_list, JRI_CallMethodBoolean_op_array, JRI_CallMethodByte_op, JRI_CallMethodByte_op_va_list, JRI_CallMethodByte_op_array, JRI_CallMethodChar_op, JRI_CallMethodChar_op_va_list, JRI_CallMethodChar_op_array, JRI_CallMethodShort_op, JRI_CallMethodShort_op_va_list, JRI_CallMethodShort_op_array, JRI_CallMethodInt_op, JRI_CallMethodInt_op_va_list, JRI_CallMethodInt_op_array, JRI_CallMethodLong_op, JRI_CallMethodLong_op_va_list, JRI_CallMethodLong_op_array, JRI_CallMethodFloat_op, JRI_CallMethodFloat_op_va_list, JRI_CallMethodFloat_op_array, JRI_CallMethodDouble_op, JRI_CallMethodDouble_op_va_list, JRI_CallMethodDouble_op_array, JRI_GetFieldID_op, JRI_GetField_op, JRI_GetFieldBoolean_op, JRI_GetFieldByte_op, JRI_GetFieldChar_op, JRI_GetFieldShort_op, JRI_GetFieldInt_op, JRI_GetFieldLong_op, JRI_GetFieldFloat_op, JRI_GetFieldDouble_op, JRI_SetField_op, JRI_SetFieldBoolean_op, JRI_SetFieldByte_op, JRI_SetFieldChar_op, JRI_SetFieldShort_op, JRI_SetFieldInt_op, JRI_SetFieldLong_op, JRI_SetFieldFloat_op, JRI_SetFieldDouble_op, JRI_IsSubclassOf_op, JRI_GetStaticMethodID_op, JRI_CallStaticMethod_op, JRI_CallStaticMethod_op_va_list, JRI_CallStaticMethod_op_array, JRI_CallStaticMethodBoolean_op, JRI_CallStaticMethodBoolean_op_va_list, JRI_CallStaticMethodBoolean_op_array, JRI_CallStaticMethodByte_op, JRI_CallStaticMethodByte_op_va_list, JRI_CallStaticMethodByte_op_array, JRI_CallStaticMethodChar_op, JRI_CallStaticMethodChar_op_va_list, JRI_CallStaticMethodChar_op_array, JRI_CallStaticMethodShort_op, JRI_CallStaticMethodShort_op_va_list, JRI_CallStaticMethodShort_op_array, JRI_CallStaticMethodInt_op, JRI_CallStaticMethodInt_op_va_list, JRI_CallStaticMethodInt_op_array, JRI_CallStaticMethodLong_op, JRI_CallStaticMethodLong_op_va_list, JRI_CallStaticMethodLong_op_array, JRI_CallStaticMethodFloat_op, JRI_CallStaticMethodFloat_op_va_list, JRI_CallStaticMethodFloat_op_array, JRI_CallStaticMethodDouble_op, JRI_CallStaticMethodDouble_op_va_list, JRI_CallStaticMethodDouble_op_array, JRI_GetStaticFieldID_op, JRI_GetStaticField_op, JRI_GetStaticFieldBoolean_op, JRI_GetStaticFieldByte_op, JRI_GetStaticFieldChar_op, JRI_GetStaticFieldShort_op, JRI_GetStaticFieldInt_op, JRI_GetStaticFieldLong_op, JRI_GetStaticFieldFloat_op, JRI_GetStaticFieldDouble_op, JRI_SetStaticField_op, JRI_SetStaticFieldBoolean_op, JRI_SetStaticFieldByte_op, JRI_SetStaticFieldChar_op, JRI_SetStaticFieldShort_op, JRI_SetStaticFieldInt_op, JRI_SetStaticFieldLong_op, JRI_SetStaticFieldFloat_op, JRI_SetStaticFieldDouble_op, JRI_NewString_op, JRI_GetStringLength_op, JRI_GetStringChars_op, JRI_NewStringUTF_op, JRI_GetStringUTFLength_op, JRI_GetStringUTFChars_op, JRI_NewScalarArray_op, JRI_GetScalarArrayLength_op, JRI_GetScalarArrayElements_op, JRI_NewObjectArray_op, JRI_GetObjectArrayLength_op, JRI_GetObjectArrayElement_op, JRI_SetObjectArrayElement_op, JRI_RegisterNatives_op, JRI_UnregisterNatives_op } JRIEnvOperations; #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* JRI_H */ /******************************************************************************/ ================================================ FILE: vm/src/from_squeak/unix/npsqueak/include/jri_md.h ================================================ /* -*- Mode: C; tab-width: 4; -*- */ /******************************************************************************* * Java Runtime Interface - Machine Dependent Types * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. ******************************************************************************/ #ifndef JRI_MD_H #define JRI_MD_H #include #ifdef __cplusplus extern "C" { #endif /******************************************************************************* * WHAT'S UP WITH THIS FILE? * * This is where we define the mystical JRI_PUBLIC_API macro that works on all * platforms. If you're running with Visual C++, Symantec C, or Borland's * development environment on the PC, you're all set. Or if you're on the Mac * with Metrowerks, Symantec or MPW with SC you're ok too. For UNIX it shouldn't * matter. * * On UNIX though you probably care about a couple of other symbols though: * IS_LITTLE_ENDIAN must be defined for little-endian systems * HAVE_LONG_LONG must be defined on systems that have 'long long' integers * HAVE_ALIGNED_LONGLONGS must be defined if long-longs must be 8 byte aligned * HAVE_ALIGNED_DOUBLES must be defined if doubles must be 8 byte aligned * IS_64 must be defined on 64-bit machines (like Dec Alpha) ******************************************************************************/ /* DLL Entry modifiers... */ /* PC */ #if defined(XP_PC) || defined(_WINDOWS) || defined(WIN32) || defined(_WIN32) # include # if defined(_MSC_VER) # if defined(WIN32) || defined(_WIN32) # define JRI_PUBLIC_API(ResultType) _declspec(dllexport) ResultType # define JRI_CALLBACK # else /* !_WIN32 */ # if defined(_WINDLL) # define JRI_PUBLIC_API(ResultType) ResultType __cdecl __export __loadds # define JRI_CALLBACK __loadds # else /* !WINDLL */ # define JRI_PUBLIC_API(ResultType) ResultType __cdecl __export # define JRI_CALLBACK __export # endif /* !WINDLL */ # endif /* !_WIN32 */ # elif defined(__BORLANDC__) # if defined(WIN32) || defined(_WIN32) # define JRI_PUBLIC_API(ResultType) __export ResultType # define JRI_CALLBACK # else /* !_WIN32 */ # define JRI_PUBLIC_API(ResultType) ResultType _cdecl _export _loadds # define JRI_CALLBACK _loadds # endif # else # error Unsupported PC development environment. # endif # ifndef IS_LITTLE_ENDIAN # define IS_LITTLE_ENDIAN # endif /* Mac */ #elif macintosh || Macintosh || THINK_C # if defined(__MWERKS__) /* Metrowerks */ # if !__option(enumsalwaysint) # error You need to define 'Enums Always Int' for your project. # endif # if defined(GENERATING68K) && !GENERATINGCFM # if !__option(fourbyteints) # error You need to define 'Struct Alignment: 68k' for your project. # endif # endif /* !GENERATINGCFM */ # elif defined(__SC__) /* Symantec */ # error What are the Symantec defines? (warren@netscape.com) # elif macintosh && applec /* MPW */ # error Please upgrade to the latest MPW compiler (SC). # else # error Unsupported Mac development environment. # endif # define JRI_PUBLIC_API(ResultType) ResultType # define JRI_CALLBACK /* Unix or else */ #else # define JRI_PUBLIC_API(ResultType) ResultType # define JRI_CALLBACK #endif #ifndef FAR /* for non-Win16 */ #define FAR #endif /******************************************************************************/ /* Java Scalar Types */ typedef unsigned char jbool; typedef char jbyte; typedef short jchar; typedef short jshort; #ifdef IS_64 /* XXX ok for alpha, but not right on all 64-bit architectures */ typedef unsigned int juint; typedef int jint; #else typedef unsigned long juint; typedef long jint; #endif typedef float jfloat; typedef double jdouble; typedef juint jsize; /******************************************************************************* * jlong : long long (64-bit signed integer type) support. ******************************************************************************/ /* ** Bit masking macros. (n must be <= 31 to be portable) */ #define JRI_BIT(n) ((juint)1 << (n)) #define JRI_BITMASK(n) (JRI_BIT(n) - 1) #ifdef HAVE_LONG_LONG #if !(defined(WIN32) || defined(_WIN32)) typedef long long jlong; typedef unsigned long long julong; #define jlong_MAXINT 0x7fffffffffffffffLL #define jlong_MININT 0x8000000000000000LL #define jlong_ZERO 0x0LL #else typedef LONGLONG jlong; typedef DWORDLONG julong; #define jlong_MAXINT 0x7fffffffffffffffi64 #define jlong_MININT 0x8000000000000000i64 #define jlong_ZERO 0x0i64 #endif #define jlong_IS_ZERO(a) ((a) == 0) #define jlong_EQ(a, b) ((a) == (b)) #define jlong_NE(a, b) ((a) != (b)) #define jlong_GE_ZERO(a) ((a) >= 0) #define jlong_CMP(a, op, b) ((a) op (b)) #define jlong_AND(r, a, b) ((r) = (a) & (b)) #define jlong_OR(r, a, b) ((r) = (a) | (b)) #define jlong_XOR(r, a, b) ((r) = (a) ^ (b)) #define jlong_OR2(r, a) ((r) = (r) | (a)) #define jlong_NOT(r, a) ((r) = ~(a)) #define jlong_NEG(r, a) ((r) = -(a)) #define jlong_ADD(r, a, b) ((r) = (a) + (b)) #define jlong_SUB(r, a, b) ((r) = (a) - (b)) #define jlong_MUL(r, a, b) ((r) = (a) * (b)) #define jlong_DIV(r, a, b) ((r) = (a) / (b)) #define jlong_MOD(r, a, b) ((r) = (a) % (b)) #define jlong_SHL(r, a, b) ((r) = (a) << (b)) #define jlong_SHR(r, a, b) ((r) = (a) >> (b)) #define jlong_USHR(r, a, b) ((r) = (julong)(a) >> (b)) #define jlong_ISHL(r, a, b) ((r) = ((jlong)(a)) << (b)) #define jlong_L2I(i, l) ((i) = (int)(l)) #define jlong_L2UI(ui, l) ((ui) =(unsigned int)(l)) #define jlong_L2F(f, l) ((f) = (l)) #define jlong_L2D(d, l) ((d) = (l)) #define jlong_I2L(l, i) ((l) = (i)) #define jlong_UI2L(l, ui) ((l) = (ui)) #define jlong_F2L(l, f) ((l) = (f)) #define jlong_D2L(l, d) ((l) = (d)) #define jlong_UDIVMOD(qp, rp, a, b) \ (*(qp) = ((julong)(a) / (b)), \ *(rp) = ((julong)(a) % (b))) #else /* !HAVE_LONG_LONG */ typedef struct { #ifdef IS_LITTLE_ENDIAN juint lo, hi; #else juint hi, lo; #endif } jlong; typedef jlong julong; extern jlong jlong_MAXINT, jlong_MININT, jlong_ZERO; #define jlong_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) #define jlong_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) #define jlong_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) #define jlong_GE_ZERO(a) (((a).hi >> 31) == 0) /* * NB: jlong_CMP and jlong_UCMP work only for strict relationals (<, >). */ #define jlong_CMP(a, op, b) (((int32)(a).hi op (int32)(b).hi) || \ (((a).hi == (b).hi) && ((a).lo op (b).lo))) #define jlong_UCMP(a, op, b) (((a).hi op (b).hi) || \ (((a).hi == (b).hi) && ((a).lo op (b).lo))) #define jlong_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ (r).hi = (a).hi & (b).hi) #define jlong_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ (r).hi = (a).hi | (b).hi) #define jlong_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ (r).hi = (a).hi ^ (b).hi) #define jlong_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ (r).hi = (r).hi | (a).hi) #define jlong_NOT(r, a) ((r).lo = ~(a).lo, \ (r).hi = ~(a).hi) #define jlong_NEG(r, a) ((r).lo = -(int32)(a).lo, \ (r).hi = -(int32)(a).hi - ((r).lo != 0)) #define jlong_ADD(r, a, b) { \ jlong _a, _b; \ _a = a; _b = b; \ (r).lo = _a.lo + _b.lo; \ (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ } #define jlong_SUB(r, a, b) { \ jlong _a, _b; \ _a = a; _b = b; \ (r).lo = _a.lo - _b.lo; \ (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ } \ /* * Multiply 64-bit operands a and b to get 64-bit result r. * First multiply the low 32 bits of a and b to get a 64-bit result in r. * Then add the outer and inner products to r.hi. */ #define jlong_MUL(r, a, b) { \ jlong _a, _b; \ _a = a; _b = b; \ jlong_MUL32(r, _a.lo, _b.lo); \ (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ } /* XXX _jlong_lo16(a) = ((a) << 16 >> 16) is better on some archs (not on mips) */ #define _jlong_lo16(a) ((a) & JRI_BITMASK(16)) #define _jlong_hi16(a) ((a) >> 16) /* * Multiply 32-bit operands a and b to get 64-bit result r. * Use polynomial expansion based on primitive field element (1 << 16). */ #define jlong_MUL32(r, a, b) { \ juint _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ _a1 = _jlong_hi16(a), _a0 = _jlong_lo16(a); \ _b1 = _jlong_hi16(b), _b0 = _jlong_lo16(b); \ _y0 = _a0 * _b0; \ _y1 = _a0 * _b1; \ _y2 = _a1 * _b0; \ _y3 = _a1 * _b1; \ _y1 += _jlong_hi16(_y0); /* can't carry */ \ _y1 += _y2; /* might carry */ \ if (_y1 < _y2) _y3 += 1 << 16; /* propagate */ \ (r).lo = (_jlong_lo16(_y1) << 16) + _jlong_lo16(_y0); \ (r).hi = _y3 + _jlong_hi16(_y1); \ } /* * Divide 64-bit unsigned operand a by 64-bit unsigned operand b, setting *qp * to the 64-bit unsigned quotient, and *rp to the 64-bit unsigned remainder. * Minimize effort if one of qp and rp is null. */ #define jlong_UDIVMOD(qp, rp, a, b) jlong_udivmod(qp, rp, a, b) extern JRI_PUBLIC_API(void) jlong_udivmod(julong *qp, julong *rp, julong a, julong b); #define jlong_DIV(r, a, b) { \ jlong _a, _b; \ juint _negative = (int32)(a).hi < 0; \ if (_negative) { \ jlong_NEG(_a, a); \ } else { \ _a = a; \ } \ if ((int32)(b).hi < 0) { \ _negative ^= 1; \ jlong_NEG(_b, b); \ } else { \ _b = b; \ } \ jlong_UDIVMOD(&(r), 0, _a, _b); \ if (_negative) \ jlong_NEG(r, r); \ } #define jlong_MOD(r, a, b) { \ jlong _a, _b; \ juint _negative = (int32)(a).hi < 0; \ if (_negative) { \ jlong_NEG(_a, a); \ } else { \ _a = a; \ } \ if ((int32)(b).hi < 0) { \ jlong_NEG(_b, b); \ } else { \ _b = b; \ } \ jlong_UDIVMOD(0, &(r), _a, _b); \ if (_negative) \ jlong_NEG(r, r); \ } /* * NB: b is a juint, not jlong or julong, for the shift ops. */ #define jlong_SHL(r, a, b) { \ if (b) { \ jlong _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = _a.lo << (b); \ (r).hi = (_a.hi << (b)) | (_a.lo >> (32 - (b))); \ } else { \ (r).lo = 0; \ (r).hi = _a.lo << ((b) & 31); \ } \ } else { \ (r) = (a); \ } \ } /* a is an int32, b is int32, r is jlong */ #define jlong_ISHL(r, a, b) { \ if (b) { \ jlong _a; \ _a.lo = (a); \ _a.hi = 0; \ if ((b) < 32) { \ (r).lo = (a) << (b); \ (r).hi = ((a) >> (32 - (b))); \ } else { \ (r).lo = 0; \ (r).hi = (a) << ((b) & 31); \ } \ } else { \ (r).lo = (a); \ (r).hi = 0; \ } \ } #define jlong_SHR(r, a, b) { \ if (b) { \ jlong _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> (b)); \ (r).hi = (int32)_a.hi >> (b); \ } else { \ (r).lo = (int32)_a.hi >> ((b) & 31); \ (r).hi = (int32)_a.hi >> 31; \ } \ } else { \ (r) = (a); \ } \ } #define jlong_USHR(r, a, b) { \ if (b) { \ jlong _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> (b)); \ (r).hi = _a.hi >> (b); \ } else { \ (r).lo = _a.hi >> ((b) & 31); \ (r).hi = 0; \ } \ } else { \ (r) = (a); \ } \ } #define jlong_L2I(i, l) ((i) = (l).lo) #define jlong_L2UI(ui, l) ((ui) = (l).lo) #define jlong_L2F(f, l) { double _d; jlong_L2D(_d, l); (f) = (float) _d; } #define jlong_L2D(d, l) { \ int32 _negative; \ jlong _absval; \ \ _negative = (l).hi >> 31; \ if (_negative) { \ jlong_NEG(_absval, l); \ } else { \ _absval = l; \ } \ (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ if (_negative) \ (d) = -(d); \ } #define jlong_I2L(l, i) ((l).hi = (i) >> 31, (l).lo = (i)) #define jlong_UI2L(l, ui) ((l).hi = 0, (l).lo = (ui)) #define jlong_F2L(l, f) { double _d = (double) f; jlong_D2L(l, _d); } #define jlong_D2L(l, d) { \ int _negative; \ double _absval, _d_hi; \ jlong _lo_d; \ \ _negative = ((d) < 0); \ _absval = _negative ? -(d) : (d); \ \ (l).hi = (juint)(_absval / 4.294967296e9); \ (l).lo = 0; \ jlong_L2D(_d_hi, l); \ _absval -= _d_hi; \ _lo_d.hi = 0; \ if (_absval < 0) { \ _lo_d.lo = (juint) -_absval; \ jlong_SUB(l, l, _lo_d); \ } else { \ _lo_d.lo = (juint) _absval; \ jlong_ADD(l, l, _lo_d); \ } \ \ if (_negative) \ jlong_NEG(l, l); \ } #endif /* !HAVE_LONG_LONG */ /******************************************************************************/ /* ** JDK Stuff -- This stuff is still needed while we're using the JDK ** dynamic linking strategy to call native methods. */ typedef union JRI_JDK_stack_item { /* Non pointer items */ jint i; jfloat f; jint o; /* Pointer items */ void *h; void *p; unsigned char *addr; #ifdef IS_64 double d; long l; /* == 64bits! */ #endif } JRI_JDK_stack_item; typedef union JRI_JDK_Java8Str { jint x[2]; jdouble d; jlong l; void *p; float f; } JRI_JDK_Java8; #ifdef HAVE_ALIGNED_LONGLONGS #define JRI_GET_INT64(_t,_addr) ( ((_t).x[0] = ((jint*)(_addr))[0]), \ ((_t).x[1] = ((jint*)(_addr))[1]), \ (_t).l ) #define JRI_SET_INT64(_t, _addr, _v) ( (_t).l = (_v), \ ((jint*)(_addr))[0] = (_t).x[0], \ ((jint*)(_addr))[1] = (_t).x[1] ) #else #define JRI_GET_INT64(_t,_addr) (*(jlong*)(_addr)) #define JRI_SET_INT64(_t, _addr, _v) (*(jlong*)(_addr) = (_v)) #endif /* If double's must be aligned on doubleword boundaries then define this */ #ifdef HAVE_ALIGNED_DOUBLES #define JRI_GET_DOUBLE(_t,_addr) ( ((_t).x[0] = ((jint*)(_addr))[0]), \ ((_t).x[1] = ((jint*)(_addr))[1]), \ (_t).d ) #define JRI_SET_DOUBLE(_t, _addr, _v) ( (_t).d = (_v), \ ((jint*)(_addr))[0] = (_t).x[0], \ ((jint*)(_addr))[1] = (_t).x[1] ) #else #define JRI_GET_DOUBLE(_t,_addr) (*(jdouble*)(_addr)) #define JRI_SET_DOUBLE(_t, _addr, _v) (*(jdouble*)(_addr) = (_v)) #endif /******************************************************************************/ #ifdef __cplusplus } #endif #endif /* JRI_MD_H */ /******************************************************************************/ ================================================ FILE: vm/src/from_squeak/unix/npsqueak/include/jritypes.h ================================================ /* -*- Mode: C; tab-width: 4; -*- */ /******************************************************************************* * Java Runtime Interface * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. ******************************************************************************/ #ifndef JRITYPES_H #define JRITYPES_H #include "jri_md.h" #include #include #include #ifdef __cplusplus extern "C" { #endif /******************************************************************************* * Types ******************************************************************************/ struct JRIEnvInterface; typedef void* JRIRef; typedef void* JRIGlobalRef; typedef jint JRIInterfaceID[4]; typedef jint JRIFieldID; typedef jint JRIMethodID; /* synonyms: */ typedef JRIGlobalRef jglobal; typedef JRIRef jref; typedef union JRIValue { jbool z; jbyte b; jchar c; jshort s; jint i; jlong l; jfloat f; jdouble d; jref r; } JRIValue; typedef JRIValue jvalue; typedef enum JRIBoolean { JRIFalse = 0, JRITrue = 1 } JRIBoolean; typedef enum JRIConstant { JRIUninitialized = -1 } JRIConstant; /* convenience types: */ typedef JRIRef jbooleanArray; typedef JRIRef jbyteArray; typedef JRIRef jcharArray; typedef JRIRef jshortArray; typedef JRIRef jintArray; typedef JRIRef jlongArray; typedef JRIRef jfloatArray; typedef JRIRef jdoubleArray; typedef JRIRef jobjectArray; typedef JRIRef jstringArray; typedef JRIRef jarrayArray; #define JRIConstructorMethodName "" /******************************************************************************* * Signature Construction Macros ******************************************************************************/ /* ** These macros can be used to construct signature strings. Hopefully their names ** are a little easier to remember than the single character they correspond to. ** For example, to specify the signature of the method: ** ** public int read(byte b[], int off, int len); ** ** you could write something like this in C: ** ** char* readSig = JRISigMethod(JRISigArray(JRISigByte) ** JRISigInt ** JRISigInt) JRISigInt; ** ** Of course, don't put commas between the types. */ #define JRISigArray(T) "[" T #define JRISigByte "B" #define JRISigChar "C" #define JRISigClass(name) "L" name ";" #define JRISigFloat "F" #define JRISigDouble "D" #define JRISigMethod(args) "(" args ")" #define JRISigNoArgs "" #define JRISigInt "I" #define JRISigLong "J" #define JRISigShort "S" #define JRISigVoid "V" #define JRISigBoolean "Z" /******************************************************************************* * Environments ******************************************************************************/ extern JRI_PUBLIC_API(const struct JRIEnvInterface**) JRI_GetCurrentEnv(void); /******************************************************************************* * Specific Scalar Array Types ******************************************************************************/ /* ** The JRI Native Method Interface does not support boolean arrays. This ** is to allow Java runtime implementations to optimize boolean array ** storage. Using the ScalarArray operations on boolean arrays is bound ** to fail, so convert any boolean arrays to byte arrays in Java before ** passing them to a native method. */ #define JRI_NewByteArray(env, length, initialValues) \ JRI_NewScalarArray(env, length, JRISigByte, (jbyte*)(initialValues)) #define JRI_GetByteArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetByteArrayElements(env, array) \ JRI_GetScalarArrayElements(env, array) #define JRI_NewCharArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jchar)), JRISigChar, (jbyte*)(initialValues)) #define JRI_GetCharArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetCharArrayElements(env, array) \ ((jchar*)JRI_GetScalarArrayElements(env, array)) #define JRI_NewShortArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jshort)), JRISigShort, (jbyte*)(initialValues)) #define JRI_GetShortArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetShortArrayElements(env, array) \ ((jshort*)JRI_GetScalarArrayElements(env, array)) #define JRI_NewIntArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jint)), JRISigInt, (jbyte*)(initialValues)) #define JRI_GetIntArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetIntArrayElements(env, array) \ ((jint*)JRI_GetScalarArrayElements(env, array)) #define JRI_NewLongArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jlong)), JRISigLong, (jbyte*)(initialValues)) #define JRI_GetLongArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetLongArrayElements(env, array) \ ((jlong*)JRI_GetScalarArrayElements(env, array)) #define JRI_NewFloatArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jfloat)), JRISigFloat, (jbyte*)(initialValues)) #define JRI_GetFloatArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetFloatArrayElements(env, array) \ ((jfloat*)JRI_GetScalarArrayElements(env, array)) #define JRI_NewDoubleArray(env, length, initialValues) \ JRI_NewScalarArray(env, ((length) * sizeof(jdouble)), JRISigDouble, (jbyte*)(initialValues)) #define JRI_GetDoubleArrayLength(env, array) \ JRI_GetScalarArrayLength(env, array) #define JRI_GetDoubleArrayElements(env, array) \ ((jdouble*)JRI_GetScalarArrayElements(env, array)) /******************************************************************************/ #ifdef __cplusplus } #endif #endif /* JRITYPES_H */ /******************************************************************************/ ================================================ FILE: vm/src/from_squeak/unix/npsqueak/include/npapi.h ================================================ /* -*- Mode: C; tab-width: 4; -*- */ /* * npapi.h $Revision: 1.3 $ * Netscape client plug-in API spec */ #ifndef _NPAPI_H_ #define _NPAPI_H_ #include "jri.h" /* Java Runtime Interface */ /* XXX this needs to get out of here */ #if defined(__MWERKS__) #ifndef XP_MAC #define XP_MAC #endif #endif /*----------------------------------------------------------------------*/ /* Plugin Version Constants */ /*----------------------------------------------------------------------*/ #define NP_VERSION_MAJOR 0 #define NP_VERSION_MINOR 9 /*----------------------------------------------------------------------*/ /* Definition of Basic Types */ /*----------------------------------------------------------------------*/ #ifndef _UINT16 typedef unsigned short uint16; #endif #ifndef _UINT32 #if defined(__alpha) typedef unsigned int uint32; #else /* __alpha */ typedef unsigned long uint32; #endif /* __alpha */ #endif #ifndef _INT16 typedef short int16; #endif #ifndef _INT32 #if defined(__alpha) typedef int int32; #else /* __alpha */ typedef long int32; #endif /* __alpha */ #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif #ifndef NULL #define NULL (0L) #endif typedef unsigned char NPBool; typedef void* NPEvent; typedef int16 NPError; typedef int16 NPReason; typedef char* NPMIMEType; /*----------------------------------------------------------------------*/ /* Structures and definitions */ /*----------------------------------------------------------------------*/ /* * NPP is a plug-in's opaque instance handle */ typedef struct _NPP { void* pdata; /* plug-in private data */ void* ndata; /* netscape private data */ } NPP_t; typedef NPP_t* NPP; typedef struct _NPStream { void* pdata; /* plug-in private data */ void* ndata; /* netscape private data */ const char* url; uint32 end; uint32 lastmodified; void* notifyData; } NPStream; typedef struct _NPByteRange { int32 offset; /* negative offset means from the end */ uint32 length; struct _NPByteRange* next; } NPByteRange; typedef struct _NPSavedData { int32 len; void* buf; } NPSavedData; typedef struct _NPRect { uint16 top; uint16 left; uint16 bottom; uint16 right; } NPRect; #ifdef XP_UNIX /* * Unix specific structures and definitions */ #include /* * Callback Structures. * * These are used to pass additional platform specific information. */ enum { NP_SETWINDOW = 1 }; typedef struct { int32 type; } NPAnyCallbackStruct; typedef struct { int32 type; Display* display; Visual* visual; Colormap colormap; unsigned int depth; } NPSetWindowCallbackStruct; /* * List of variable names for which NPP_GetValue shall be implemented */ typedef enum { NPPVpluginNameString = 1, NPPVpluginDescriptionString } NPPVariable; /* * List of variable names for which NPN_GetValue is implemented by Mozilla */ typedef enum { NPNVxDisplay = 1, NPNVxtAppContext } NPNVariable; #endif /* XP_UNIX */ typedef struct _NPWindow { void* window; /* Platform specific window handle */ uint32 x; /* Position of top left corner relative */ uint32 y; /* to a netscape page. */ uint32 width; /* Maximum window size */ uint32 height; NPRect clipRect; /* Clipping rectangle in port coordinates */ /* Used by MAC only. */ #ifdef XP_UNIX void * ws_info; /* Platform-dependent additonal data */ #endif /* XP_UNIX */ } NPWindow; typedef struct _NPFullPrint { NPBool pluginPrinted; /* Set TRUE if plugin handled fullscreen */ /* printing */ NPBool printOne; /* TRUE if plugin should print one copy */ /* to default printer */ void* platformPrint; /* Platform-specific printing info */ } NPFullPrint; typedef struct _NPEmbedPrint { NPWindow window; void* platformPrint; /* Platform-specific printing info */ } NPEmbedPrint; typedef struct _NPPrint { uint16 mode; /* NP_FULL or NP_EMBED */ union { NPFullPrint fullPrint; /* if mode is NP_FULL */ NPEmbedPrint embedPrint; /* if mode is NP_EMBED */ } print; } NPPrint; #ifdef XP_MAC /* * Mac-specific structures and definitions. */ #include #include typedef struct NP_Port { CGrafPtr port; /* Grafport */ int32 portx; /* position inside the topmost window */ int32 porty; } NP_Port; /* * Non-standard event types that can be passed to HandleEvent */ #define getFocusEvent (osEvt + 16) #define loseFocusEvent (osEvt + 17) #define adjustCursorEvent (osEvt + 18) #endif /* XP_MAC */ /* * Values for mode passed to NPP_New: */ #define NP_EMBED 1 #define NP_FULL 2 /* * Values for stream type passed to NPP_NewStream: */ #define NP_NORMAL 1 #define NP_SEEK 2 #define NP_ASFILE 3 #define NP_ASFILEONLY 4 #define NP_MAXREADY (((unsigned)(~0)<<1)>>1) /*----------------------------------------------------------------------*/ /* Error and Reason Code definitions */ /*----------------------------------------------------------------------*/ /* * Values of type NPError: */ #define NPERR_BASE 0 #define NPERR_NO_ERROR (NPERR_BASE + 0) #define NPERR_GENERIC_ERROR (NPERR_BASE + 1) #define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2) #define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3) #define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4) #define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5) #define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6) #define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7) #define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8) #define NPERR_INVALID_PARAM (NPERR_BASE + 9) #define NPERR_INVALID_URL (NPERR_BASE + 10) #define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11) #define NPERR_NO_DATA (NPERR_BASE + 12) #define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13) /* * Values of type NPReason: */ #define NPRES_BASE 0 #define NPRES_DONE (NPRES_BASE + 0) #define NPRES_NETWORK_ERR (NPRES_BASE + 1) #define NPRES_USER_BREAK (NPRES_BASE + 2) /* * Don't use these obsolete error codes any more. */ #define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR #define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR #define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK /* * Version feature information */ #define NPVERS_HAS_STREAMOUTPUT 8 #define NPVERS_HAS_NOTIFICATION 9 #define NPVERS_HAS_LIVECONNECT 9 /*----------------------------------------------------------------------*/ /* Function Prototypes */ /*----------------------------------------------------------------------*/ #if defined(_WINDOWS) && !defined(WIN32) #define NP_LOADDS _loadds #else #define NP_LOADDS #endif #ifdef __cplusplus extern "C" { #endif /* * NPP_* functions are provided by the plugin and called by the navigator. */ #ifdef XP_UNIX char* NPP_GetMIMEDescription(void); NPError NPP_GetValue(void *instance, NPPVariable variable, void *value); #endif /* XP_UNIX */ NPError NPP_Initialize(void); void NPP_Shutdown(void); NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save); NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window); NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint); int16 NPP_HandleEvent(NPP instance, void* event); void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData); jref NPP_GetJavaClass(void); /* * NPN_* functions are provided by the navigator and called by the plugin. */ #ifdef XP_UNIX NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value); #endif /* XP_UNIX */ void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor); NPError NPN_GetURLNotify(NPP instance, const char* url, const char* target, void* notifyData); NPError NPN_GetURL(NPP instance, const char* url, const char* target); NPError NPN_PostURLNotify(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData); NPError NPN_PostURL(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file); NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList); NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream); int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer); NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason); void NPN_Status(NPP instance, const char* message); const char* NPN_UserAgent(NPP instance); void* NPN_MemAlloc(uint32 size); void NPN_MemFree(void* ptr); uint32 NPN_MemFlush(uint32 size); void NPN_ReloadPlugins(NPBool reloadPages); JRIEnv* NPN_GetJavaEnv(void); jref NPN_GetJavaPeer(NPP instance); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* _NPAPI_H_ */ ================================================ FILE: vm/src/from_squeak/unix/npsqueak/include/npupp.h ================================================ /* -*- Mode: C; tab-width: 4; -*- */ /* * npupp.h $Revision: 1.3 $ * function call mecahnics needed by platform specific glue code. */ #ifndef _NPUPP_H_ #define _NPUPP_H_ #ifndef GENERATINGCFM #define GENERATINGCFM 0 #endif #ifndef _NPAPI_H_ #include "npapi.h" #endif #include "jri.h" /****************************************************************************************** plug-in function table macros for each function in and out of the plugin API we define typedef NPP_FooUPP #define NewNPP_FooProc #define CallNPP_FooProc for mac, define the UPP magic for PPC/68K calling *******************************************************************************************/ /* NPP_Initialize */ #if GENERATINGCFM typedef UniversalProcPtr NPP_InitializeUPP; enum { uppNPP_InitializeProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) | RESULT_SIZE(SIZE_CODE(0)) }; #define NewNPP_InitializeProc(FUNC) \ (NPP_InitializeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_InitializeProcInfo, GetCurrentArchitecture()) #define CallNPP_InitializeProc(FUNC) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_InitializeProcInfo) #else typedef void (*NPP_InitializeUPP)(void); #define NewNPP_InitializeProc(FUNC) \ ((NPP_InitializeUPP) (FUNC)) #define CallNPP_InitializeProc(FUNC) \ (*(FUNC))() #endif /* NPP_Shutdown */ #if GENERATINGCFM typedef UniversalProcPtr NPP_ShutdownUPP; enum { uppNPP_ShutdownProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) | RESULT_SIZE(SIZE_CODE(0)) }; #define NewNPP_ShutdownProc(FUNC) \ (NPP_ShutdownUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_ShutdownProcInfo, GetCurrentArchitecture()) #define CallNPP_ShutdownProc(FUNC) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_ShutdownProcInfo) #else typedef void (*NPP_ShutdownUPP)(void); #define NewNPP_ShutdownProc(FUNC) \ ((NPP_ShutdownUPP) (FUNC)) #define CallNPP_ShutdownProc(FUNC) \ (*(FUNC))() #endif /* NPP_New */ #if GENERATINGCFM typedef UniversalProcPtr NPP_NewUPP; enum { uppNPP_NewProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPMIMEType))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(uint16))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int16))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char **))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(char **))) | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(NPSavedData *))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_NewProc(FUNC) \ (NPP_NewUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewProcInfo, GetCurrentArchitecture()) #define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewProcInfo, \ (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) #else typedef NPError (*NPP_NewUPP)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); #define NewNPP_NewProc(FUNC) \ ((NPP_NewUPP) (FUNC)) #define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) #endif /* NPP_Destroy */ #if GENERATINGCFM typedef UniversalProcPtr NPP_DestroyUPP; enum { uppNPP_DestroyProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPSavedData **))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_DestroyProc(FUNC) \ (NPP_DestroyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyProcInfo, GetCurrentArchitecture()) #define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyProcInfo, (ARG1), (ARG2)) #else typedef NPError (*NPP_DestroyUPP)(NPP instance, NPSavedData** save); #define NewNPP_DestroyProc(FUNC) \ ((NPP_DestroyUPP) (FUNC)) #define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ (*(FUNC))((ARG1), (ARG2)) #endif /* NPP_SetWindow */ #if GENERATINGCFM typedef UniversalProcPtr NPP_SetWindowUPP; enum { uppNPP_SetWindowProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPWindow *))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_SetWindowProc(FUNC) \ (NPP_SetWindowUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetWindowProcInfo, GetCurrentArchitecture()) #define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetWindowProcInfo, (ARG1), (ARG2)) #else typedef NPError (*NPP_SetWindowUPP)(NPP instance, NPWindow* window); #define NewNPP_SetWindowProc(FUNC) \ ((NPP_SetWindowUPP) (FUNC)) #define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ (*(FUNC))((ARG1), (ARG2)) #endif /* NPP_NewStream */ #if GENERATINGCFM typedef UniversalProcPtr NPP_NewStreamUPP; enum { uppNPP_NewStreamProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPBool))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(uint16 *))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_NewStreamProc(FUNC) \ (NPP_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewStreamProcInfo, GetCurrentArchitecture()) #define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewStreamProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) #else typedef NPError (*NPP_NewStreamUPP)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); #define NewNPP_NewStreamProc(FUNC) \ ((NPP_NewStreamUPP) (FUNC)) #define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) #endif /* NPP_DestroyStream */ #if GENERATINGCFM typedef UniversalProcPtr NPP_DestroyStreamUPP; enum { uppNPP_DestroyStreamProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_DestroyStreamProc(FUNC) \ (NPP_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, GetCurrentArchitecture()) #define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, (NPParg), (NPStreamPtr), (NPReasonArg)) #else typedef NPError (*NPP_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); #define NewNPP_DestroyStreamProc(FUNC) \ ((NPP_DestroyStreamUPP) (FUNC)) #define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ (*(FUNC))((NPParg), (NPStreamPtr), (NPReasonArg)) #endif /* NPP_WriteReady */ #if GENERATINGCFM typedef UniversalProcPtr NPP_WriteReadyUPP; enum { uppNPP_WriteReadyProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | RESULT_SIZE(SIZE_CODE(sizeof(int32))) }; #define NewNPP_WriteReadyProc(FUNC) \ (NPP_WriteReadyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, GetCurrentArchitecture()) #define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, (NPParg), (NPStreamPtr)) #else typedef int32 (*NPP_WriteReadyUPP)(NPP instance, NPStream* stream); #define NewNPP_WriteReadyProc(FUNC) \ ((NPP_WriteReadyUPP) (FUNC)) #define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ (*(FUNC))((NPParg), (NPStreamPtr)) #endif /* NPP_Write */ #if GENERATINGCFM typedef UniversalProcPtr NPP_WriteUPP; enum { uppNPP_WriteProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int32))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(void*))) | RESULT_SIZE(SIZE_CODE(sizeof(int32))) }; #define NewNPP_WriteProc(FUNC) \ (NPP_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteProcInfo, GetCurrentArchitecture()) #define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteProcInfo, (NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) #else typedef int32 (*NPP_WriteUPP)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); #define NewNPP_WriteProc(FUNC) \ ((NPP_WriteUPP) (FUNC)) #define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ (*(FUNC))((NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) #endif /* NPP_StreamAsFile */ #if GENERATINGCFM typedef UniversalProcPtr NPP_StreamAsFileUPP; enum { uppNPP_StreamAsFileProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) | RESULT_SIZE(SIZE_CODE(0)) }; #define NewNPP_StreamAsFileProc(FUNC) \ (NPP_StreamAsFileUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, GetCurrentArchitecture()) #define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, (ARG1), (ARG2), (ARG3)) #else typedef void (*NPP_StreamAsFileUPP)(NPP instance, NPStream* stream, const char* fname); #define NewNPP_StreamAsFileProc(FUNC) \ ((NPP_StreamAsFileUPP) (FUNC)) #define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ (*(FUNC))((ARG1), (ARG2), (ARG3)) #endif /* NPP_Print */ #if GENERATINGCFM typedef UniversalProcPtr NPP_PrintUPP; enum { uppNPP_PrintProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPrint *))) | RESULT_SIZE(SIZE_CODE(0)) }; #define NewNPP_PrintProc(FUNC) \ (NPP_PrintUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_PrintProcInfo, GetCurrentArchitecture()) #define CallNPP_PrintProc(FUNC, NPParg, voidPtr) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_PrintProcInfo, (NPParg), (voidPtr)) #else typedef void (*NPP_PrintUPP)(NPP instance, NPPrint* platformPrint); #define NewNPP_PrintProc(FUNC) \ ((NPP_PrintUPP) (FUNC)) #define CallNPP_PrintProc(FUNC, NPParg, NPPrintArg) \ (*(FUNC))((NPParg), (NPPrintArg)) #endif /* NPP_HandleEvent */ #if GENERATINGCFM typedef UniversalProcPtr NPP_HandleEventUPP; enum { uppNPP_HandleEventProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void *))) | RESULT_SIZE(SIZE_CODE(sizeof(int16))) }; #define NewNPP_HandleEventProc(FUNC) \ (NPP_HandleEventUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_HandleEventProcInfo, GetCurrentArchitecture()) #define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ (int16)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_HandleEventProcInfo, (NPParg), (voidPtr)) #else typedef int16 (*NPP_HandleEventUPP)(NPP instance, void* event); #define NewNPP_HandleEventProc(FUNC) \ ((NPP_HandleEventUPP) (FUNC)) #define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ (*(FUNC))((NPParg), (voidPtr)) #endif /* NPP_URLNotify */ #if GENERATINGCFM typedef UniversalProcPtr NPP_URLNotifyUPP; enum { uppNPP_URLNotifyProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) | RESULT_SIZE(SIZE_CODE(SIZE_CODE(0))) }; #define NewNPP_URLNotifyProc(FUNC) \ (NPP_URLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, GetCurrentArchitecture()) #define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) #else typedef void (*NPP_URLNotifyUPP)(NPP instance, const char* url, NPReason reason, void* notifyData); #define NewNPP_URLNotifyProc(FUNC) \ ((NPP_URLNotifyUPP) (FUNC)) #define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) #endif /* * Netscape entry points */ #ifdef XP_UNIX /* NPN_GetValue */ #if GENERATINGCFM typedef UniversalProcPtr NPN_GetValueUPP; enum { uppNPN_GetValueProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_GetValueProc(FUNC) \ (NPN_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetValueProcInfo, GetCurrentArchitecture()) #define CallNPN_GetURNotifyLProc(FUNC, ARG1, ARG2, ARG3) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) #else typedef NPError (*NPN_GetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); #define NewNPN_GetValueProc(FUNC) \ ((NPN_GetValueUPP) (FUNC)) #define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ (*(FUNC))((ARG1), (ARG2), (ARG3)) #endif #endif /* XP_UNIX */ /* NPN_GetUrlNotify */ #if GENERATINGCFM typedef UniversalProcPtr NPN_GetURLNotifyUPP; enum { uppNPN_GetURLNotifyProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_GetURLNotifyProc(FUNC) \ (NPN_GetURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, GetCurrentArchitecture()) #define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) #else typedef NPError (*NPN_GetURLNotifyUPP)(NPP instance, const char* url, const char* window, void* notifyData); #define NewNPN_GetURLNotifyProc(FUNC) \ ((NPN_GetURLNotifyUPP) (FUNC)) #define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) #endif /* NPN_PostUrlNotify */ #if GENERATINGCFM typedef UniversalProcPtr NPN_PostURLNotifyUPP; enum { uppNPN_PostURLNotifyProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(void*))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_PostURLNotifyProc(FUNC) \ (NPN_PostURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, GetCurrentArchitecture()) #define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) #else typedef NPError (*NPN_PostURLNotifyUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); #define NewNPN_PostURLNotifyProc(FUNC) \ ((NPN_PostURLNotifyUPP) (FUNC)) #define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) #endif /* NPN_GetUrl */ #if GENERATINGCFM typedef UniversalProcPtr NPN_GetURLUPP; enum { uppNPN_GetURLProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_GetURLProc(FUNC) \ (NPN_GetURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLProcInfo, GetCurrentArchitecture()) #define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLProcInfo, (ARG1), (ARG2), (ARG3)) #else typedef NPError (*NPN_GetURLUPP)(NPP instance, const char* url, const char* window); #define NewNPN_GetURLProc(FUNC) \ ((NPN_GetURLUPP) (FUNC)) #define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ (*(FUNC))((ARG1), (ARG2), (ARG3)) #endif /* NPN_PostUrl */ #if GENERATINGCFM typedef UniversalProcPtr NPN_PostURLUPP; enum { uppNPN_PostURLProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_PostURLProc(FUNC) \ (NPN_PostURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLProcInfo, GetCurrentArchitecture()) #define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) #else typedef NPError (*NPN_PostURLUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file); #define NewNPN_PostURLProc(FUNC) \ ((NPN_PostURLUPP) (FUNC)) #define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) #endif /* NPN_RequestRead */ #if GENERATINGCFM typedef UniversalProcPtr NPN_RequestReadUPP; enum { uppNPN_RequestReadProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPByteRange *))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_RequestReadProc(FUNC) \ (NPN_RequestReadUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_RequestReadProcInfo, GetCurrentArchitecture()) #define CallNPN_RequestReadProc(FUNC, stream, range) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RequestReadProcInfo, (stream), (range)) #else typedef NPError (*NPN_RequestReadUPP)(NPStream* stream, NPByteRange* rangeList); #define NewNPN_RequestReadProc(FUNC) \ ((NPN_RequestReadUPP) (FUNC)) #define CallNPN_RequestReadProc(FUNC, stream, range) \ (*(FUNC))((stream), (range)) #endif /* NPN_NewStream */ #if GENERATINGCFM typedef UniversalProcPtr NPN_NewStreamUPP; enum { uppNPN_NewStreamProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPStream **))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_NewStreamProc(FUNC) \ (NPN_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_NewStreamProcInfo, GetCurrentArchitecture()) #define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_NewStreamProcInfo, (npp), (type), (window), (stream)) #else typedef NPError (*NPN_NewStreamUPP)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); #define NewNPN_NewStreamProc(FUNC) \ ((NPN_NewStreamUPP) (FUNC)) #define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ (*(FUNC))((npp), (type), (window), (stream)) #endif /* NPN_Write */ #if GENERATINGCFM typedef UniversalProcPtr NPN_WriteUPP; enum { uppNPN_WriteProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) | RESULT_SIZE(SIZE_CODE(sizeof(int32))) }; #define NewNPN_WriteProc(FUNC) \ (NPN_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_WriteProcInfo, GetCurrentArchitecture()) #define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_WriteProcInfo, (npp), (stream), (len), (buffer)) #else typedef int32 (*NPN_WriteUPP)(NPP instance, NPStream* stream, int32 len, void* buffer); #define NewNPN_WriteProc(FUNC) \ ((NPN_WriteUPP) (FUNC)) #define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ (*(FUNC))((npp), (stream), (len), (buffer)) #endif /* NPN_DestroyStream */ #if GENERATINGCFM typedef UniversalProcPtr NPN_DestroyStreamUPP; enum { uppNPN_DestroyStreamProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP ))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPN_DestroyStreamProc(FUNC) \ (NPN_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, GetCurrentArchitecture()) #define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, (npp), (stream), (reason)) #else typedef NPError (*NPN_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); #define NewNPN_DestroyStreamProc(FUNC) \ ((NPN_DestroyStreamUPP) (FUNC)) #define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ (*(FUNC))((npp), (stream), (reason)) #endif /* NPN_Status */ #if GENERATINGCFM typedef UniversalProcPtr NPN_StatusUPP; enum { uppNPN_StatusProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *))) }; #define NewNPN_StatusProc(FUNC) \ (NPN_StatusUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_StatusProcInfo, GetCurrentArchitecture()) #define CallNPN_StatusProc(FUNC, npp, msg) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_StatusProcInfo, (npp), (msg)) #else typedef void (*NPN_StatusUPP)(NPP instance, const char* message); #define NewNPN_StatusProc(FUNC) \ ((NPN_StatusUPP) (FUNC)) #define CallNPN_StatusProc(FUNC, npp, msg) \ (*(FUNC))((npp), (msg)) #endif /* NPN_UserAgent */ #if GENERATINGCFM typedef UniversalProcPtr NPN_UserAgentUPP; enum { uppNPN_UserAgentProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | RESULT_SIZE(SIZE_CODE(sizeof(const char *))) }; #define NewNPN_UserAgentProc(FUNC) \ (NPN_UserAgentUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_UserAgentProcInfo, GetCurrentArchitecture()) #define CallNPN_UserAgentProc(FUNC, ARG1) \ (const char*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_UserAgentProcInfo, (ARG1)) #else typedef const char* (*NPN_UserAgentUPP)(NPP instance); #define NewNPN_UserAgentProc(FUNC) \ ((NPN_UserAgentUPP) (FUNC)) #define CallNPN_UserAgentProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /* NPN_MemAlloc */ #if GENERATINGCFM typedef UniversalProcPtr NPN_MemAllocUPP; enum { uppNPN_MemAllocProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) | RESULT_SIZE(SIZE_CODE(sizeof(void *))) }; #define NewNPN_MemAllocProc(FUNC) \ (NPN_MemAllocUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemAllocProcInfo, GetCurrentArchitecture()) #define CallNPN_MemAllocProc(FUNC, ARG1) \ (void*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemAllocProcInfo, (ARG1)) #else typedef void* (*NPN_MemAllocUPP)(uint32 size); #define NewNPN_MemAllocProc(FUNC) \ ((NPN_MemAllocUPP) (FUNC)) #define CallNPN_MemAllocProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /* NPN__MemFree */ #if GENERATINGCFM typedef UniversalProcPtr NPN_MemFreeUPP; enum { uppNPN_MemFreeProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *))) }; #define NewNPN_MemFreeProc(FUNC) \ (NPN_MemFreeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFreeProcInfo, GetCurrentArchitecture()) #define CallNPN_MemFreeProc(FUNC, ARG1) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFreeProcInfo, (ARG1)) #else typedef void (*NPN_MemFreeUPP)(void* ptr); #define NewNPN_MemFreeProc(FUNC) \ ((NPN_MemFreeUPP) (FUNC)) #define CallNPN_MemFreeProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /* NPN_MemFlush */ #if GENERATINGCFM typedef UniversalProcPtr NPN_MemFlushUPP; enum { uppNPN_MemFlushProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) | RESULT_SIZE(SIZE_CODE(sizeof(uint32))) }; #define NewNPN_MemFlushProc(FUNC) \ (NPN_MemFlushUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFlushProcInfo, GetCurrentArchitecture()) #define CallNPN_MemFlushProc(FUNC, ARG1) \ (uint32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFlushProcInfo, (ARG1)) #else typedef uint32 (*NPN_MemFlushUPP)(uint32 size); #define NewNPN_MemFlushProc(FUNC) \ ((NPN_MemFlushUPP) (FUNC)) #define CallNPN_MemFlushProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /* NPN_ReloadPlugins */ #if GENERATINGCFM typedef UniversalProcPtr NPN_ReloadPluginsUPP; enum { uppNPN_ReloadPluginsProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPBool))) | RESULT_SIZE(SIZE_CODE(0)) }; #define NewNPN_ReloadPluginsProc(FUNC) \ (NPN_ReloadPluginsUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, GetCurrentArchitecture()) #define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, (ARG1)) #else typedef void (*NPN_ReloadPluginsUPP)(NPBool reloadPages); #define NewNPN_ReloadPluginsProc(FUNC) \ ((NPN_ReloadPluginsUPP) (FUNC)) #define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /* NPN_GetJavaEnv */ #if GENERATINGCFM typedef UniversalProcPtr NPN_GetJavaEnvUPP; enum { uppNPN_GetJavaEnvProcInfo = kThinkCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(JRIEnv*))) }; #define NewNPN_GetJavaEnvProc(FUNC) \ (NPN_GetJavaEnvUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo, GetCurrentArchitecture()) #define CallNPN_GetJavaEnvProc(FUNC) \ (JRIEnv*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo) #else typedef JRIEnv* (*NPN_GetJavaEnvUPP)(void); #define NewNPN_GetJavaEnvProc(FUNC) \ ((NPN_GetJavaEnvUPP) (FUNC)) #define CallNPN_GetJavaEnvProc(FUNC) \ (*(FUNC))() #endif /* NPN_GetJavaPeer */ #if GENERATINGCFM typedef UniversalProcPtr NPN_GetJavaPeerUPP; enum { uppNPN_GetJavaPeerProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) | RESULT_SIZE(SIZE_CODE(sizeof(jref))) }; #define NewNPN_GetJavaPeerProc(FUNC) \ (NPN_GetJavaPeerUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, GetCurrentArchitecture()) #define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, (ARG1)) #else typedef jref (*NPN_GetJavaPeerUPP)(NPP instance); #define NewNPN_GetJavaPeerProc(FUNC) \ ((NPN_GetJavaPeerUPP) (FUNC)) #define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ (*(FUNC))((ARG1)) #endif /****************************************************************************************** * The actual plugin function table definitions *******************************************************************************************/ typedef struct _NPPluginFuncs { uint16 size; uint16 version; NPP_NewUPP newp; NPP_DestroyUPP destroy; NPP_SetWindowUPP setwindow; NPP_NewStreamUPP newstream; NPP_DestroyStreamUPP destroystream; NPP_StreamAsFileUPP asfile; NPP_WriteReadyUPP writeready; NPP_WriteUPP write; NPP_PrintUPP print; NPP_HandleEventUPP event; NPP_URLNotifyUPP urlnotify; JRIGlobalRef javaClass; } NPPluginFuncs; typedef struct _NPNetscapeFuncs { uint16 size; uint16 version; NPN_GetURLUPP geturl; NPN_PostURLUPP posturl; NPN_RequestReadUPP requestread; NPN_NewStreamUPP newstream; NPN_WriteUPP write; NPN_DestroyStreamUPP destroystream; NPN_StatusUPP status; NPN_UserAgentUPP uagent; NPN_MemAllocUPP memalloc; NPN_MemFreeUPP memfree; NPN_MemFlushUPP memflush; NPN_ReloadPluginsUPP reloadplugins; NPN_GetJavaEnvUPP getJavaEnv; NPN_GetJavaPeerUPP getJavaPeer; NPN_GetURLNotifyUPP geturlnotify; NPN_PostURLNotifyUPP posturlnotify; #ifdef XP_UNIX NPN_GetValueUPP getvalue; #endif /* XP_UNIX */ } NPNetscapeFuncs; #ifdef XP_MAC /****************************************************************************************** * Mac platform-specific plugin glue stuff *******************************************************************************************/ /* * Main entry point of the plugin. * This routine will be called when the plugin is loaded. The function * tables are passed in and the plugin fills in the NPPluginFuncs table * and NPPShutdownUPP for Netscape's use. */ #if GENERATINGCFM typedef UniversalProcPtr NPP_MainEntryUPP; enum { uppNPP_MainEntryProcInfo = kThinkCStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPNetscapeFuncs*))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPluginFuncs*))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPP_ShutdownUPP*))) | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) }; #define NewNPP_MainEntryProc(FUNC) \ (NPP_MainEntryUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_MainEntryProcInfo, GetCurrentArchitecture()) #define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ CallUniversalProc((UniversalProcPtr)(FUNC), (ProcInfoType)uppNPP_MainEntryProcInfo, (netscapeFunc), (pluginFunc), (shutdownUPP)) #else typedef NPError (*NPP_MainEntryUPP)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownUPP*); #define NewNPP_MainEntryProc(FUNC) \ ((NPP_MainEntryUPP) (FUNC)) #define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ (*(FUNC))((netscapeFunc), (pluginFunc), (shutdownUPP)) #endif #endif /* MAC */ #ifdef _WINDOWS #ifdef __cplusplus extern "C" { #endif /* plugin meta member functions */ NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs); NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs); NPError WINAPI NP_Shutdown(); #ifdef __cplusplus } #endif #endif /* _WINDOWS */ #ifdef XP_UNIX #ifdef __cplusplus extern "C" { #endif /* plugin meta member functions */ char* NP_GetMIMEDescription(void); NPError NP_Initialize(NPNetscapeFuncs*, NPPluginFuncs*); NPError NP_Shutdown(void); #ifdef __cplusplus } #endif #endif /* XP_UNIX */ #endif /* _NPUPP_H_ */ ================================================ FILE: vm/src/from_squeak/unix/npsqueak/npsqueak.c ================================================ /* -*- Mode: C; tab-width: 8; -*- * * Browser Plugin for Squeak on Unix platforms * * Author: Bert Freudenberg * * Last edited: 2005-03-17 12:15:48 by piumarta on squeak.hpl.hp.com * * History: * Jan 2005 - looking for image and npsqueakrun in system and home dir * kill squeak window when destroyed * Apr 2004 - (ikp) handle imageName and failureUrl tags * Oct 2002 - system-wide install * Sep 2002 - create hard links for streamed files * Mar 2002 - moved to ~/.npsqueak dir * Nov 2000 - browserPipes interface replaces X events * Apr 2000 - url requests through browser * Nov 1999 - report attributes to vm * Aug 99 - initial version */ #define XP_UNIX #include #include #include #include #include #include #include #include #include #include #include #include #undef DEBUG #if defined (DEBUG) static void DPRINT(char *format, ...) { static int debug= 42; if (42 == debug) debug= (NULL != getenv("NPSQUEAK_DEBUG")); if (!debug) { return; } else { static FILE *file= 0; if (!file) { file= fopen("/tmp/npsqueak.log", "a+"); fprintf(file, "=== START PLUGIN ===\n"); } { va_list ap; va_start(ap, format); vfprintf(file, format, ap); va_end(ap); fflush(file); } } } #else static void DPRINT(char *format, ...) { } #endif /*********************************************************************** * Plugin instance data ***********************************************************************/ #define CMD_BROWSER_WINDOW 1 #define CMD_GET_URL 2 #define CMD_POST_URL 3 #define CMD_RECEIVE_DATA 4 #define MAX_STREAMS 128 #define SQUEAK_READ 0 #define PLUGIN_WRITE 1 #define PLUGIN_READ 2 #define SQUEAK_WRITE 3 /* plugin state */ typedef struct SqueakPlugin { NPP instance; /* plugin instance */ pid_t pid; /* the child process pid */ Display *display; Window nswindow; /* the netscape window */ Window sqwindow; /* the Squeak window */ XtInputId input; /* handler for command pipe */ Bool embedded; /* false if we have the whole window */ char **argv; /* the commandline for Squeak vm */ int argc; char vmName[PATH_MAX]; char imageName[PATH_MAX]; int pipes[4]; /* 4 ends of 2 pipes */ char* srcUrl; /* set by browser in first NewStream */ char* srcFilename; int srcId; /* if requested */ char *failureUrl; } SqueakPlugin; /* URL notify data */ typedef struct SqueakStream { int id; /* request id (0 if finished) */ } SqueakStream; /*********************************************************************** * Prototypes ***********************************************************************/ static void DeliverFile(SqueakPlugin *, int id, const char* fname); static void SetWindow(SqueakPlugin*, Window window, int width, int height); static void SetUpWindow(SqueakPlugin*); static void SetUpSqueakWindow(SqueakPlugin*); static void Run(SqueakPlugin*); static void GetUrl(SqueakPlugin*); static void PostUrl(SqueakPlugin*); static void DestroyCallback(Widget widget, SqueakPlugin *, XtPointer calldata); static void InputCallback(SqueakPlugin *, int *source, XtInputId*); static char* NPN_StrDup(const char* s) { return strcpy(NPN_MemAlloc(strlen(s) + 1), s); } /*********************************************************************** * Plugin registration ***********************************************************************/ char* NPP_GetMIMEDescription(void) { return("application/x-squeak-source:sts:Squeak source" ";application/x-squeak-object:sqo:Squeak object" ";application/x-squeak-project:pr:Squeak project"); } NPError NPP_GetValue(void *instance, NPPVariable variable, void *value) { switch (variable) { case NPPVpluginNameString: *((char **)value)= "Squeak"; break; case NPPVpluginDescriptionString: *((char **)value) = "Squeak is a modern open source" " Smalltalk environment. The Squeak Plugin handles Squeaklets.

" "The Squeak Plugin for Unix was developed by" " Bert Freudenberg," " it uses the Squeak VM developed by" " Ian Piumarta" " and others."; break; default: return NPERR_GENERIC_ERROR; } return NPERR_NO_ERROR; } /*********************************************************************** * search filename in list of dirs and write path into result * returns 0 if filename not found ***********************************************************************/ static char* findFileInPaths(char* result, char *filename, int dirn, char *dirv[PATH_MAX]){ int i; char path[PATH_MAX]; for(i= 0; i < dirn; i++){ DPRINT("NP: search \"%s\" in \"%s\" \n",filename,dirv[i]); strcpy(path, dirv[i]); strcat(path, filename); if (access(path, R_OK) == 0){ DPRINT("NP: \"%s\" in \"%s\" found\n",filename,dirv[i]); return strcpy(result, path); } } DPRINT("NP: nothing found\n"); return 0; } /*********************************************************************** * Plugin loading and termination ***********************************************************************/ static int IgnoreErrors(Display *display, XErrorEvent *evt) { DPRINT("NP: X Error ignored.\n"); return 1; } NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) { SqueakPlugin *plugin; char imagename[PATH_MAX]; char *failureUrl= 0; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; plugin= (SqueakPlugin*) NPN_MemAlloc(sizeof(SqueakPlugin)); if (!plugin) return NPERR_OUT_OF_MEMORY_ERROR; plugin->argv= (char**) NPN_MemAlloc(sizeof(char*) * (16 + 2 * argc)); if (!plugin->argv) return NPERR_OUT_OF_MEMORY_ERROR; /* Default settings */ strcpy(imagename, "SqueakPlugin.image"); plugin->instance= instance; plugin->pid= 0; plugin->nswindow= 0; plugin->sqwindow= 0; plugin->display= NULL; plugin->input= 0; plugin->embedded= (mode == NP_EMBED); plugin->srcUrl= NULL; plugin->srcFilename= NULL; plugin->srcId= -1; plugin->failureUrl= 0; plugin->argv[0]= NPN_StrDup(plugin->vmName); plugin->argv[1]= NPN_StrDup("-display"); plugin->argv[2]= NULL; /* inserted later */ plugin->argv[3]= NPN_StrDup("-browserPipes"); plugin->argv[4]= NULL; /* inserted later */ plugin->argv[5]= NULL; /* inserted later */ plugin->argv[7]= NPN_StrDup(""); /* empty document file on cmdline! */ plugin->argc= 8; if (plugin->embedded) { int i; for (i= 0; i < argc; i++) { if (!strcasecmp(argn[i], "imagename")) { strcpy(imagename, argv[i]); } else if (!strcasecmp(argn[i], "failureurl")) failureUrl= argv[i]; plugin->argv[plugin->argc++]= NPN_StrDup(argn[i]); plugin->argv[plugin->argc++]= NPN_StrDup(argv[i] ? argv[i] : ""); if (strcasecmp("SRC", argn[i]) == 0) plugin->srcUrl= NPN_StrDup(argv[i]); } if (!plugin->srcUrl) plugin->srcUrl= NPN_StrDup(""); /* we were embedded without a SRC */ /* find npsqueakrun and image */ { char user_bin_dir[PATH_MAX]; char user_img_dir[PATH_MAX]; char* home= getenv("HOME"); if (home == 0) { fprintf(stderr, "Squeak Plugin: No home directory?!\n"); return NPERR_GENERIC_ERROR; } strcpy(user_bin_dir, home); strcat(user_bin_dir, "/.npsqueak/"); strcpy(user_img_dir, home); strcat(user_img_dir, "/.npsqueak/"); { char* bin_dir_v[PATH_MAX]= {user_bin_dir, SYSTEM_BIN_DIR"/"}; if (findFileInPaths(plugin->vmName, NPSQUEAKRUN, 2 , bin_dir_v) == 0){ fprintf(stderr, "Squeak Plugin: npsqueakrun not found!\n"); return NPERR_GENERIC_ERROR; } } { char* img_dir_v[PATH_MAX]= {user_img_dir, SYSTEM_IMG_DIR"/"}; if (findFileInPaths(plugin->imageName, imagename, 2, img_dir_v) == 0){ fprintf(stderr, "Squeak Plugin: Image file not found: %s\n", imagename); if (failureUrl){ fprintf(stderr, "Squeak Plugin: going to failure URL: %s\n", failureUrl); plugin->failureUrl= NPN_StrDup(failureUrl); }else { fprintf(stderr, "Squeak Plugin: no failure URL: \n"); return NPERR_GENERIC_ERROR; } } plugin->argv[6]= NPN_StrDup(plugin->imageName); } } } else { /* if not embedded srcUrl will be set in NewStream */ plugin->srcUrl= NULL; } plugin->argv[plugin->argc]= 0; if (pipe(&plugin->pipes[SQUEAK_READ]) || pipe(&plugin->pipes[PLUGIN_READ])) { perror("Squeak Plugin: Creating pipes failed"); return NPERR_GENERIC_ERROR; } DPRINT("NP: Created pipes (VM read: %d <- %d, NP read: %d <- %d)\n", plugin->pipes[SQUEAK_READ], plugin->pipes[PLUGIN_WRITE], plugin->pipes[PLUGIN_READ], plugin->pipes[SQUEAK_WRITE]); instance->pdata= (void*) plugin; return NPERR_NO_ERROR; } NPError NPP_Destroy(NPP instance, NPSavedData** save) { SqueakPlugin *plugin; DPRINT("NP: NPP_Destroy\n"); if (!instance) return NPERR_INVALID_INSTANCE_ERROR; plugin= (SqueakPlugin*) instance->pdata; if (plugin) { int i; if (plugin->sqwindow && plugin->display) { DPRINT("NP: DestroyWindow %x\n", plugin->sqwindow); XSetErrorHandler(IgnoreErrors); XSync(plugin->display,0); XKillClient(plugin->display, plugin->sqwindow); XSync(plugin->display,0); } if (plugin->pid) { DPRINT("NP: kill 0x%i\n", plugin->pid); kill(plugin->pid, SIGTERM); plugin->pid= 0; } if (plugin->input) { XtRemoveInput(plugin->input); } for (i= 0; i < 4; i++) if (plugin->pipes[i]) { close(plugin->pipes[i]); plugin->pipes[i]= 0; } if (plugin->srcUrl) { NPN_MemFree(plugin->srcUrl); plugin->srcUrl= NULL; } if (plugin->srcFilename) { NPN_MemFree(plugin->srcFilename); plugin->srcFilename= NULL; } if (plugin->failureUrl) { NPN_MemFree(plugin->failureUrl); plugin->failureUrl= NULL; } if (plugin->argv) { for (i= 0; i < plugin->argc; i++) { if (plugin->argv[i]) NPN_MemFree(plugin->argv[i]); } plugin->argc= 0; NPN_MemFree(plugin->argv); plugin->argv= NULL; } NPN_MemFree(plugin); } instance->pdata= NULL; return NPERR_NO_ERROR; } /*********************************************************************** * Plugin events we need to handle ***********************************************************************/ NPError NPP_SetWindow(NPP instance, NPWindow *pNPWindow) { SqueakPlugin *plugin; if (!instance) return NPERR_INVALID_INSTANCE_ERROR; plugin= (SqueakPlugin*) instance->pdata; if (!plugin) return NPERR_GENERIC_ERROR; if (plugin->failureUrl) { DPRINT("NP: opening failure URL"); NPN_GetURL(plugin->instance, plugin->failureUrl, "_self"); return NPERR_NO_ERROR; } if (pNPWindow == NULL) return NPERR_NO_ERROR; if (!plugin->display) { /* first time only */ plugin->display= ((NPSetWindowCallbackStruct *)pNPWindow->ws_info)->display; } SetWindow(plugin, (Window) pNPWindow->window, pNPWindow->width, pNPWindow->height); if (!plugin->pid) Run(plugin); return NPERR_NO_ERROR; } NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) { SqueakPlugin *plugin= (SqueakPlugin*) instance->pdata; DPRINT("NP: NewStream(%s, id=%i)\n", stream->url, stream->notifyData ? ((SqueakStream*) stream->notifyData)->id : -1); if (!stream->notifyData && !plugin->srcUrl) { /* We did not request this stream, so it is our SRC file. */ plugin->srcUrl= NPN_StrDup(stream->url); plugin->argv[plugin->argc++]= NPN_StrDup("SRC"); plugin->argv[plugin->argc++]= NPN_StrDup(plugin->srcUrl); DPRINT("NP: got srcUrl=%s\n", plugin->srcUrl); Run(plugin); } *stype= NP_ASFILEONLY; /* We want the file after download */ return NPERR_NO_ERROR; } NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { /* We'll clean up in URLNotify */ DPRINT("NP: DestroyStream(%s, id=%i)\n", stream->url, stream->notifyData ? ((SqueakStream*) stream->notifyData)->id : -1); return NPERR_NO_ERROR; } void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname) { int id= stream->notifyData ? ((SqueakStream*) stream->notifyData)->id : -1; char lname[PATH_MAX]; SqueakPlugin *plugin= (SqueakPlugin*) instance->pdata; DPRINT("NP: StreamAsFile(%s, id=%i)\n", stream->url, id); DPRINT("NP: fname=%s\n", fname ? fname : ""); if (!plugin || !fname) return; /* need to copy file because it might be deleted after return */ strncpy(lname, fname, PATH_MAX); strcat(lname, "$"); DPRINT("NP: lname=%s\n", lname); if (-1 == link(fname, lname)) DPRINT("NP: Link failed: %s\n", strerror(errno)); fname= lname; if (!stream->notifyData && !plugin->srcFilename) { /* We did not request this stream, so it is our SRC file. */ plugin->srcFilename= NPN_StrDup(fname); DPRINT("NP: got srcFilename=%s\n", plugin->srcFilename); if (plugin->srcId >= 0) { /* plugin wanted it already */ DeliverFile(plugin, plugin->srcId, plugin->srcFilename); plugin->srcId= -1; } return; } DeliverFile(plugin, id, fname); /* signal URLNotify that we're done */ ((SqueakStream*) stream->notifyData)->id= -1; } void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) { int id= notifyData ? ((SqueakStream*) notifyData)->id : -1; int ok= reason == NPRES_DONE; SqueakPlugin *plugin= (SqueakPlugin*) instance->pdata; DPRINT("NP: URLNotify(%s, id=%i, ok=%i)\n", url, id, ok); if (notifyData) NPN_MemFree(notifyData); if (!plugin || -1 == id) return; DeliverFile(plugin, id, NULL); } /*********************************************************************** * Plugin stubs ***********************************************************************/ NPError NPP_Initialize(void) { return NPERR_NO_ERROR; } void NPP_Shutdown(void) { } /* We don't have an associated java class */ jref NPP_GetJavaClass() { return NULL; } /* We don't really stream */ int32 NPP_WriteReady(NPP instance, NPStream *stream) { return 0X0FFFFFFF; } int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) { return len; } /* We don't print */ void NPP_Print(NPP instance, NPPrint* printInfo) { } /*********************************************************************** * Our functions ***********************************************************************/ /* Read from command pipe. */ static void Receive(SqueakPlugin *plugin, void *buf, size_t count) { ssize_t n; do { n= read(plugin->pipes[PLUGIN_READ], buf, count); } while (n == -1 && errno == EINTR); if (n == -1) perror("Squeak plugin pipe read failed:"); if (n < count) fprintf(stderr, "Squeak plugin read too few data from pipe\n"); } /* Write to command pipe. */ static void Send(SqueakPlugin *plugin, const void *buf, size_t count) { ssize_t n; do { n= write(plugin->pipes[PLUGIN_WRITE], buf, count); } while (n == -1 && errno == EINTR); if (n == -1) perror("Squeak plugin write failed:"); if (n < count) fprintf(stderr, "Squeak plugin wrote too few data to pipe\n"); } static void SendInt(SqueakPlugin *plugin, int value) { Send(plugin, &value, 4); } static void DeliverFile(SqueakPlugin *plugin, int id, const char* fname) { int ok= fname != NULL; DPRINT("NP: Send RECEIVE_DATA id=%i state=%i\n", id, ok); errno= 0; SendInt(plugin, CMD_RECEIVE_DATA); SendInt(plugin, id); SendInt(plugin, ok); if (ok) { int length= strlen(fname); SendInt(plugin, length); Send(plugin, fname, length); } if (errno) perror("Squeak Plugin (StreamAsFile)"); } static void Run(SqueakPlugin *plugin) { if (plugin->pid || !plugin->nswindow || !plugin->srcUrl ||plugin->failureUrl) return; plugin->pid= fork(); if (plugin->pid == -1) { perror("Squeak fork() failed"); plugin->pid= 0; return; } DPRINT("NP: fork() -> %i\n", plugin->pid); if (plugin->pid == 0) { char tmp1[16], tmp2[16]; plugin->argv[2]= NPN_StrDup(DisplayString(plugin->display)); sprintf(tmp1, "%i", plugin->pipes[SQUEAK_READ]); plugin->argv[4]= NPN_StrDup(tmp1); sprintf(tmp2, "%i", plugin->pipes[SQUEAK_WRITE]); plugin->argv[5]= NPN_StrDup(tmp2); DPRINT("NP(child): Running Squeak VM with arguments\n"); { int i; for (i= 1; iargc; i++) DPRINT(" %s\n", plugin->argv[i]); } /* this is from the XLib manual ... */ if ((fcntl(ConnectionNumber(plugin->display), F_SETFD, FD_CLOEXEC)) == -1) DPRINT("NP: Cannot disinherit X connection fd\n"); DPRINT("NP(child): trying %s\n", plugin->vmName); execv(plugin->vmName, plugin->argv); /* ~/.npsqueak/npsqueakrun could not be executed */ strcpy(plugin->vmName, SYSTEM_BIN_DIR "/" NPSQUEAKRUN); NPN_MemFree(plugin->argv[0]); plugin->argv[0]= NPN_StrDup(plugin->vmName); DPRINT("NP(child): trying %s\n", plugin->vmName); execv(plugin->vmName, plugin->argv); /* npsqueakrun could not be executed either */ fprintf(stderr, "Squeak Plugin: running \"%s\"\n", plugin->vmName); perror("Squeak execv() failed"); _exit(1); } else { /* establish communication via command pipes */ XtAppContext app= XtDisplayToApplicationContext(plugin->display); plugin->input= XtAppAddInput(app, plugin->pipes[PLUGIN_READ], (XtPointer) XtInputReadMask, (XtInputCallbackProc) InputCallback, plugin); /* send browser window */ DPRINT("NP: Sending browser window=0x%X\n", plugin->nswindow); SendInt(plugin, plugin->nswindow); } } static void SetWindow(SqueakPlugin *plugin, Window window, int width, int height) { DPRINT("NP: SetWindow(0x%X, %i@%i)\n", window, width, height); if (plugin->nswindow == window) { XResizeWindow(plugin->display, plugin->nswindow, width, height); } else { /* New window */ plugin->nswindow= window; SetUpWindow(plugin); if (plugin->sqwindow) { DPRINT("NP: Reparenting to plugin window 0x%X\n", plugin->nswindow); XReparentWindow(plugin->display, plugin->sqwindow, plugin->nswindow, 0, 0); XMapWindow(plugin->display, plugin->sqwindow); /* notify Squeak */ SendInt(plugin, CMD_BROWSER_WINDOW); SendInt(plugin, plugin->nswindow); } } if (plugin->sqwindow) XResizeWindow(plugin->display, plugin->sqwindow, width, height); } static void SetUpWindow(SqueakPlugin *plugin) { Widget w= XtWindowToWidget(plugin->display, plugin->nswindow); DPRINT("NP: SetUpWindow(0x%X)\n", plugin->nswindow); XSelectInput(plugin->display, plugin->nswindow, 0); if (plugin->embedded) { /* need to capture destroys when page is re-layouted */ XtAddCallback(w, XtNdestroyCallback, (XtCallbackProc) DestroyCallback, plugin); } } static void SetUpSqueakWindow(SqueakPlugin *plugin) { Receive(plugin, &plugin->sqwindow, 4); DPRINT("NP: got squeak window=0x%X\n", plugin->sqwindow); DPRINT("NP: resizing squeak window\n"); { XWindowAttributes attr; XGetWindowAttributes(plugin->display, plugin->nswindow, &attr); XResizeWindow(plugin->display, plugin->sqwindow, attr.width, attr.height); } DPRINT("NP: mapping squeak window\n"); XMapWindow(plugin->display, plugin->sqwindow); } static void DestroyCallback(Widget widget, SqueakPlugin *plugin, XtPointer data) { int (*previous)(Display *, XErrorEvent *); DPRINT("NP: DestroyCallback()\n"); /* Ignore errors due to the window being closed */ XSync(plugin->display, False); previous= XSetErrorHandler(IgnoreErrors); /* Save Squeak window from being destroyed by page re-layout */ DPRINT("NP: Reparenting to root window\n"); XUnmapWindow(plugin->display, plugin->sqwindow); XReparentWindow(plugin->display, plugin->sqwindow, DefaultRootWindow(plugin->display), 0, 0); /* Report errors */ XSync(plugin->display, False); XSetErrorHandler(previous); } static void InputCallback(SqueakPlugin *plugin, int *source, XtInputId* id) { int cmd; DPRINT("NP: InputCallback()\n"); if (!plugin->sqwindow) { /* read sqwindow */ SetUpSqueakWindow(plugin); return; } Receive(plugin, &cmd, 4); switch (cmd) { case CMD_GET_URL: GetUrl(plugin); break; case CMD_POST_URL: PostUrl(plugin); break; default: fprintf(stderr, "Unknown command from Squeak: %i\n", cmd); } } static void GetUrl(SqueakPlugin *plugin) { char *url, *target; int id, urlSize, targetSize; errno= 0; Receive(plugin, &id, 4); /* Read URL from pipe */ Receive(plugin, &urlSize, 4); if (urlSize > 0) { url= NPN_MemAlloc(urlSize+1); Receive(plugin, url, urlSize); url[urlSize]= 0; } else url= NULL; /* Read target from pipe */ Receive(plugin, &targetSize, 4); if (targetSize > 0) { target= NPN_MemAlloc(targetSize+1); Receive(plugin, target, targetSize); target[targetSize]= 0; } else target= NULL; if (errno) { perror("Squeak Plugin (GetUrl)"); } else { DPRINT("NP: GetUrl(%s, %s)\n", url, target ? target : "NULL"); if (strcmp(url, plugin->srcUrl)==0) { if (plugin->srcFilename) DeliverFile(plugin, id, plugin->srcFilename); else plugin->srcId= id; } else { SqueakStream* notifyData= (SqueakStream*) NPN_MemAlloc(sizeof(SqueakStream)); if (!notifyData) { fprintf(stderr, "Squeak Plugin (GetUrl): alloc failed\n"); } else { DPRINT("NP: GetURLNotify(%s, id=%i)\n", url, id); notifyData->id= id; NPN_GetURLNotify(plugin->instance, url, target, notifyData); } } } if (url) NPN_MemFree(url); if (target) NPN_MemFree(target); } static void PostUrl(SqueakPlugin *plugin) { char *url, *target, *data; int id, urlSize, targetSize, dataSize; errno= 0; Receive(plugin, &id, 4); /* Read URL from pipe */ Receive(plugin, &urlSize, 4); if (urlSize > 0) { url= NPN_MemAlloc(urlSize+1); Receive(plugin, url, urlSize); url[urlSize]= 0; } else url= NULL; /* Read target from pipe */ Receive(plugin, &targetSize, 4); if (targetSize > 0) { target= NPN_MemAlloc(targetSize+1); Receive(plugin, target, targetSize); target[targetSize]= 0; } else target= NULL; /* Read post data from pipe */ Receive(plugin, &dataSize, 4); if (dataSize > 0) { data= NPN_MemAlloc(dataSize); Receive(plugin, data, dataSize); } else data= NULL; if (errno) { perror("Squeak Plugin (PostUrl)"); } else { SqueakStream* notifyData= (SqueakStream*) NPN_MemAlloc(sizeof(SqueakStream)); if (!notifyData) { fprintf(stderr, "Squeak Plugin (PostUrl): alloc failed\n"); } else { DPRINT("NP: PostURLNotify(%s, id=%i)\n", url, id); notifyData->id= id; NPN_PostURLNotify(plugin->instance, url, target, dataSize, data, FALSE, notifyData); } } if (url) NPN_MemFree(url); if (target) NPN_MemFree(target); if (data) NPN_MemFree(data); } ================================================ FILE: vm/src/from_squeak/unix/npsqueak/npsqueakregister.in ================================================ #! /bin/sh # File: npsqueakregister # Author: Bert Freudenberg # Description: Script to register the npsqueak plugin with # various browsers. # Rerun after you installed a new browser! # Parameters: -u unregister NPSQUEAK_SO=@NPSQUEAK_SO@ BROWSERS="netscape mozilla mozilla-firefox opera MozillaFirefox/lib" BROWSER_DIRS="/usr/local/lib /usr/lib /opt" SYSTEM_BROWSER_DIR="/usr/lib/browser-plugins" ACTION=register usage() { echo "Usage: $0 [-u] [PLUGIN]" echo "Registers the Squeak browser plugin for known browsers" echo " -u unregister plugin" echo " PLUGIN absolute path to npsqueak.so" echo " (default is @NPSQUEAK_SO@)" exit } register() { echo Registering ${1} rm -f ${1} ln -sv $NPSQUEAK_SO ${1} } unregister() { echo Unregistering ${1} rm -f ${1} } case "$1" in -u) ACTION=unregister ;; "") ACTION=register ;; /*.so) NPSQUEAK_SO="$1" ;; *) usage exit 1 ;; esac if [ ! -e "$NPSQUEAK_SO" ] ; then echo File not found: $NPSQUEAK_SO echo Aborting. exit 1 fi for browser in $BROWSERS do for bdir in $BROWSER_DIRS do dirs=`ls -d ${bdir}/${browser}* 2>/dev/null` for dir in $dirs do pdirs=`find $dir -name plugins -print` for pdir in $pdirs do $ACTION ${pdir}/npsqueak.so done done done done if [ -e $SYSTEM_BROWSER_DIR ]; then $ACTION $SYSTEM_BROWSER_DIR/npsqueak.so fi ================================================ FILE: vm/src/from_squeak/unix/npsqueak/npsqueakrun.in ================================================ #! /bin/bash # File: npsqueakrun # Author: Bert Freudenberg # Last edited: 2005-02-28 18:42:20 by jens on impara.de # Description: Script to start the Squeak VM binary # from the Browser Plugin (npsqueak.so) # If necessary, sets up $HOME/.npsqueak/* first. VM_VERSION=@VM_VERSION@ imgdir=@imgdir@ IMAGE=${imgdir}/SqueakPlugin.image VM=squeak VMOPTIONS=" -mmap 1024 -vm-display-x11 -swapbtn " LOGFILE=/tmp/npsqueak.log pdebug() { if [ ! -z $NPSQUEAK_DEBUG ]; then echo -e "npsqueak: $@" >> $LOGFILE fi } perror() { if [ ! -z $NPSQUEAK_DEBUG ]; then echo -e "npsqueak error: $@" | tee -a $LOGFILE >&2 else echo -e "npsqueak error: $@" >&2 fi } # is there a clever way to determine if you are local? if [ $DISPLAY = ":0.0" ]; then VMOPTIONS=$VMOPTIONS" -xshm " pdebug "using x shared memory" else pdebug "disabling x shared memory, because we are not local" fi if [ -e /usr/bin/squeakvm ]; then VM=squeakvm fi ensuredir() { if [ ! -d "${1}" ] ; then if mkdir "${1}" ; then pdebug "Created ${1}" if [ -n "${2}" ] ; then chmod "${2}" "${1}" fi else perror "Could not create ${1}!" fi fi } ensurefile() { if [ ! -e "${1}" ] ; then if cp "${2}" "${1}" ; then pdebug "Created ${1}" else perror "Could not create ${1}" if [ ! -r "${2}" ] ; then perror "because ${2} is missing" fi fi fi } ensureimage() { if [ `dirname "${1}"` = "${HOME}/.npsqueak" ] ; then IMAGE=$1 else IMAGE="${HOME}/.npsqueak/"`basename "$1"` ensurefile "$IMAGE" "$1" fi } ensure() { if [ `dirname "${1}"` = "${HOME}/.npsqueak" ] ; then IMAGE=$1 else IMAGE="${HOME}/.npsqueak/"`basename "$1"` ensurefile "$IMAGE" "$1" fi } if [ -e "${HOME}/.npsqueak" ] ; then pdebug "don't create MySqueak link on desktop," pdebug "because ${HOME}/.npsqueak exists" else pdebug "create MySqueak link on desktop" ln -s "${HOME}/.npsqueak/My Squeak" "${HOME}/Desktop/My Squeak" fi parameter_to_array(){ i=0 for p in "$@"; do i=$(( $i + 1 )) parameter[i]=$p done } ensuredir "${HOME}/.npsqueak" ensuredir "${HOME}/.npsqueak/secure" 700 if [ ! -z "$SQUEAK_USERDIR" ]; then pdebug "using SQUEAK_USERDIR" pdebug "My Squeak -> $SQUEAK_USERDIR" else pdebug "My Squeak -> ${HOME}/.npsqueak/My Squeak" ensuredir "${HOME}/.npsqueak/My Squeak" fi if [ -z "$1" ]; then pdebug "start squeak direct" ensureimage $IMAGE $VM $VMOPTIONS $IMAGE else pdebug "start squeak from plugin" IMAGE="${6}" ensureimage $IMAGE parameter_to_array "$@" parameter[6]=$IMAGE $VM $VMOPTIONS "${parameter[@]}" fi ================================================ FILE: vm/src/from_squeak/unix/npsqueak/npunix.c ================================================ /* * npunix.c * * Netscape Client Plugin API * - Wrapper function to interface with the Netscape Navigator * * dp Suresh * *---------------------------------------------------------------------- * PLUGIN DEVELOPERS: * YOU WILL NOT NEED TO EDIT THIS FILE. *---------------------------------------------------------------------- * * At the official Netscape site there's only the PluginSDK30b5 for unix: * * !!! I had to add the missing URLNotify stuff here. If you find an official * !!! version of this file which has it, use it instead. * !!! April 2000, Bert Freudenberg * */ #define XP_UNIX 1 #include #include "npapi.h" #include "npupp.h" /* * Define PLUGIN_TRACE to have the wrapper functions print * messages to stderr whenever they are called. */ #ifdef PLUGIN_TRACE #include #define PLUGINDEBUGSTR(msg) fprintf(stderr, "%s\n", msg) #else #define PLUGINDEBUGSTR(msg) #endif /*********************************************************************** * * Globals * ***********************************************************************/ static NPNetscapeFuncs gNetscapeFuncs; /* Netscape Function table */ /*********************************************************************** * * Wrapper functions : plugin calling Netscape Navigator * * These functions let the plugin developer just call the APIs * as documented and defined in npapi.h, without needing to know * about the function table and call macros in npupp.h. * ***********************************************************************/ void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor) { *plugin_major = NP_VERSION_MAJOR; *plugin_minor = NP_VERSION_MINOR; /* Major version is in high byte */ *netscape_major = gNetscapeFuncs.version >> 8; /* Minor version is in low byte */ *netscape_minor = gNetscapeFuncs.version & 0xFF; } NPError NPN_GetValue(NPP instance, NPNVariable variable, void *r_value) { return CallNPN_GetValueProc(gNetscapeFuncs.getvalue, instance, variable, r_value); } NPError NPN_GetURL(NPP instance, const char* url, const char* window) { return CallNPN_GetURLProc(gNetscapeFuncs.geturl, instance, url, window); } NPError NPN_GetURLNotify(NPP instance, const char* url, const char* window, void* notifyData) { int navMinorVers = gNetscapeFuncs.version & 0xFF; if (navMinorVers < NPVERS_HAS_NOTIFICATION) return NPERR_INCOMPATIBLE_VERSION_ERROR; return CallNPN_GetURLNotifyProc(gNetscapeFuncs.geturlnotify, instance, url, window, notifyData); } NPError NPN_PostURL(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file) { return CallNPN_PostURLProc(gNetscapeFuncs.posturl, instance, url, window, len, buf, file); } NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData) { int navMinorVers = gNetscapeFuncs.version & 0xFF; if (navMinorVers < NPVERS_HAS_NOTIFICATION) return NPERR_INCOMPATIBLE_VERSION_ERROR; return CallNPN_PostURLNotifyProc(gNetscapeFuncs.posturlnotify, instance, url, window, len, buf, file, notifyData); } NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList) { return CallNPN_RequestReadProc(gNetscapeFuncs.requestread, stream, rangeList); } NPError NPN_NewStream(NPP instance, NPMIMEType type, const char *window, NPStream** stream_ptr) { return CallNPN_NewStreamProc(gNetscapeFuncs.newstream, instance, type, window, stream_ptr); } int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer) { return CallNPN_WriteProc(gNetscapeFuncs.write, instance, stream, len, buffer); } NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason) { return CallNPN_DestroyStreamProc(gNetscapeFuncs.destroystream, instance, stream, reason); } void NPN_Status(NPP instance, const char* message) { CallNPN_StatusProc(gNetscapeFuncs.status, instance, message); } const char* NPN_UserAgent(NPP instance) { return CallNPN_UserAgentProc(gNetscapeFuncs.uagent, instance); } void* NPN_MemAlloc(uint32 size) { return CallNPN_MemAllocProc(gNetscapeFuncs.memalloc, size); } void NPN_MemFree(void* ptr) { CallNPN_MemFreeProc(gNetscapeFuncs.memfree, ptr); } uint32 NPN_MemFlush(uint32 size) { return CallNPN_MemFlushProc(gNetscapeFuncs.memflush, size); } void NPN_ReloadPlugins(NPBool reloadPages) { CallNPN_ReloadPluginsProc(gNetscapeFuncs.reloadplugins, reloadPages); } JRIEnv* NPN_GetJavaEnv() { return CallNPN_GetJavaEnvProc(gNetscapeFuncs.getJavaEnv); } jref NPN_GetJavaPeer(NPP instance) { return CallNPN_GetJavaPeerProc(gNetscapeFuncs.getJavaPeer, instance); } /*********************************************************************** * * Wrapper functions : Netscape Navigator -> plugin * * These functions let the plugin developer just create the APIs * as documented and defined in npapi.h, without needing to * install those functions in the function table or worry about * setting up globals for 68K plugins. * ***********************************************************************/ NPError Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) { NPError ret; PLUGINDEBUGSTR("New"); ret = NPP_New(pluginType, instance, mode, argc, argn, argv, saved); return ret; } NPError Private_Destroy(NPP instance, NPSavedData** save) { PLUGINDEBUGSTR("Destroy"); return NPP_Destroy(instance, save); } NPError Private_SetWindow(NPP instance, NPWindow* window) { NPError err; PLUGINDEBUGSTR("SetWindow"); err = NPP_SetWindow(instance, window); return err; } NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) { NPError err; PLUGINDEBUGSTR("NewStream"); err = NPP_NewStream(instance, type, stream, seekable, stype); return err; } int32 Private_WriteReady(NPP instance, NPStream* stream) { unsigned int result; PLUGINDEBUGSTR("WriteReady"); result = NPP_WriteReady(instance, stream); return result; } int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) { unsigned int result; PLUGINDEBUGSTR("Write"); result = NPP_Write(instance, stream, offset, len, buffer); return result; } void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { PLUGINDEBUGSTR("StreamAsFile"); NPP_StreamAsFile(instance, stream, fname); } void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) { PLUGINDEBUGSTR("URLNotify"); NPP_URLNotify(instance, url, reason, notifyData); } NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason) { NPError err; PLUGINDEBUGSTR("DestroyStream"); err = NPP_DestroyStream(instance, stream, reason); return err; } void Private_Print(NPP instance, NPPrint* platformPrint) { PLUGINDEBUGSTR("Print"); NPP_Print(instance, platformPrint); } JRIGlobalRef Private_GetJavaClass(void) { jref clazz = NPP_GetJavaClass(); if (clazz) { JRIEnv* env = NPN_GetJavaEnv(); return JRI_NewGlobalRef(env, clazz); } return NULL; } /*********************************************************************** * * These functions are located automagically by netscape. * ***********************************************************************/ /* * NP_GetMIMEDescription * - Netscape needs to know about this symbol * - Netscape uses the return value to identify when an object instance * of this plugin should be created. */ char * NP_GetMIMEDescription(void) { return NPP_GetMIMEDescription(); } /* * NP_GetValue [optional] * - Netscape needs to know about this symbol. * - Interfaces with plugin to get values for predefined variables * that the navigator needs. */ NPError NP_GetValue(void *future, NPPVariable variable, void *value) { return NPP_GetValue(future, variable, value); } /* * NP_Initialize * - Netscape needs to know about this symbol. * - It calls this function after looking up its symbol before it * is about to create the first ever object of this kind. * * PARAMETERS * nsTable - The netscape function table. If developers just use these * wrappers, they dont need to worry about all these function * tables. * RETURN * pluginFuncs * - This functions needs to fill the plugin function table * pluginFuncs and return it. Netscape Navigator plugin * library will use this function table to call the plugin. * */ NPError NP_Initialize(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs) { NPError err = NPERR_NO_ERROR; PLUGINDEBUGSTR("NP_Initialize"); /* validate input parameters */ if ((nsTable == NULL) || (pluginFuncs == NULL)) err = NPERR_INVALID_FUNCTABLE_ERROR; /* * Check the major version passed in Netscape's function table. * We won't load if the major version is newer than what we expect. * Also check that the function tables passed in are big enough for * all the functions we need (they could be bigger, if Netscape added * new APIs, but that's OK with us -- we'll just ignore them). * */ if (err == NPERR_NO_ERROR) { if ((nsTable->version >> 8) > NP_VERSION_MAJOR) err = NPERR_INCOMPATIBLE_VERSION_ERROR; if (nsTable->size < sizeof(NPNetscapeFuncs)) err = NPERR_INVALID_FUNCTABLE_ERROR; if (pluginFuncs->size < sizeof(NPPluginFuncs)) err = NPERR_INVALID_FUNCTABLE_ERROR; } if (err == NPERR_NO_ERROR) { /* * Copy all the fields of Netscape function table into our * copy so we can call back into Netscape later. Note that * we need to copy the fields one by one, rather than assigning * the whole structure, because the Netscape function table * could actually be bigger than what we expect. */ gNetscapeFuncs.version = nsTable->version; gNetscapeFuncs.size = nsTable->size; gNetscapeFuncs.posturl = nsTable->posturl; gNetscapeFuncs.geturl = nsTable->geturl; gNetscapeFuncs.requestread = nsTable->requestread; gNetscapeFuncs.newstream = nsTable->newstream; gNetscapeFuncs.write = nsTable->write; gNetscapeFuncs.destroystream = nsTable->destroystream; gNetscapeFuncs.status = nsTable->status; gNetscapeFuncs.uagent = nsTable->uagent; gNetscapeFuncs.memalloc = nsTable->memalloc; gNetscapeFuncs.memfree = nsTable->memfree; gNetscapeFuncs.memflush = nsTable->memflush; gNetscapeFuncs.reloadplugins = nsTable->reloadplugins; gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv; gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer; gNetscapeFuncs.getvalue = nsTable->getvalue; if ((nsTable->version & 0xFF) >= NPVERS_HAS_NOTIFICATION) { gNetscapeFuncs.posturlnotify = nsTable->posturlnotify; gNetscapeFuncs.geturlnotify = nsTable->geturlnotify; } /* * Set up the plugin function table that Netscape will use to * call us. Netscape needs to know about our version and size * and have a UniversalProcPointer for every function we * implement. */ pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; pluginFuncs->size = sizeof(NPPluginFuncs); pluginFuncs->newp = NewNPP_NewProc(Private_New); pluginFuncs->destroy = NewNPP_DestroyProc(Private_Destroy); pluginFuncs->setwindow = NewNPP_SetWindowProc(Private_SetWindow); pluginFuncs->newstream = NewNPP_NewStreamProc(Private_NewStream); pluginFuncs->destroystream = NewNPP_DestroyStreamProc(Private_DestroyStream); pluginFuncs->asfile = NewNPP_StreamAsFileProc(Private_StreamAsFile); pluginFuncs->urlnotify = NewNPP_URLNotifyProc(Private_URLNotify); pluginFuncs->writeready = NewNPP_WriteReadyProc(Private_WriteReady); pluginFuncs->write = NewNPP_WriteProc(Private_Write); pluginFuncs->print = NewNPP_PrintProc(Private_Print); pluginFuncs->event = NULL; pluginFuncs->javaClass = Private_GetJavaClass(); err = NPP_Initialize(); } return err; } /* * NP_Shutdown [optional] * - Netscape needs to know about this symbol. * - It calls this function after looking up its symbol after * the last object of this kind has been destroyed. * */ NPError NP_Shutdown(void) { PLUGINDEBUGSTR("NP_Shutdown"); NPP_Shutdown(); return NPERR_NO_ERROR; } ================================================ FILE: vm/src/from_squeak/unix/npsqueak/test/plugintest.html ================================================ Squeak Plugin Test

Squeak Plugin Test


Embedded mode:


Fullwindow mode: plugintest.sts

================================================ FILE: vm/src/from_squeak/unix/npsqueak/test/plugintest.sts ================================================ "If you see this message as a text file something went wrong. You may go back and try the embedded Squeak version. If this works, the server isn't sending the right mime type. If not, the Squeak plugin is not installed correctly. " StringHolder new textContents: ('Hello Plugin World!! This window was opened by some code in the file plugintest.sts, which was downloaded by your web browser and executed by the Squeak Plugin Virtual Machine (', (Smalltalk getSystemAttribute: 0), ') in an object image (', (Smalltalk getSystemAttribute: 1),'). Since you are reading this I guess all is okay then ... On most platforms, you can also run Squeak as a stand-alone program if you start the VM with the image. ') withSqueakLineEndings; openLabel: 'Plugin Startup' ================================================ FILE: vm/src/from_squeak/unix/plugins/AioPlugin/Makefile.inc ================================================ XCPPFLAGS= -I$(topdir)/platforms/Cross/plugins/FilePlugin -I$(topdir)/platforms/Cross/plugins/SocketPlugin -DSQAIO_H=\"sqaio.h\" ================================================ FILE: vm/src/from_squeak/unix/plugins/AioPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/AioPlugin/config.cmake ================================================ PLUGIN_DEFINITIONS (-DSQAIO_H=\"sqaio.h\") PLUGIN_INCLUDE_DIRECTORIES (${cross}/plugins/FilePlugin ${cross}/plugins/SocketPlugin) ================================================ FILE: vm/src/from_squeak/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c ================================================ /* sqUnixAsynchFile.c -- non-blocking file i/o * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Author: Ian.Piumarta@INRIA.Fr */ /* Experimental support for asynchronous file reading and writing. When a read or write operation is initiated, control is returned to Squeak immediately. A semaphore is signaled when the operation completes, at which time the client can find out how many bytes were actually read or written and copy the results of the read operation from the file buffer into a Squeak buffer. Only one operation may be in progress on a given file at a given time, but operations on different files may be done in parallel. The semaphore is signalled once for each transfer operation that is successfully started, even if that operation later fails. Write operations always write their entire buffer if they succeed, but read operations may transfer less than their buffer size if they are started less than a buffer's size from the end of the file. The state of a file is kept in the following structure, which is stored directly in a Squeak ByteArray object: typedef struct { int sessionID; void *state; // private to the implementation } AsyncFile; The session ID is used to detect stale files--files that were open when the image was saved. The state pointer of such files is meaningless. Async file handles use the same session ID as ordinary file handles. Note: These primitives are experimental! They need not be implemented on every platform, and they may be withdrawn or replaced in a future release. */ #include "sq.h" #include "AsynchFilePlugin.h" #include "sqUnixAsynchFile.h" /*** module initialisation ***/ #include "sqVirtualMachine.h" #include "sqaio.h" #include #include #include int sqUnixAsyncFileSessionID= 0; static struct VirtualMachine *vm= 0; static fd_set fds; static int nfd= 0; #define isValid(f) (f->sessionID == sqUnixAsyncFileSessionID) #define validate(f) if ((!isValid(f)) || (!(f->state))) return vm->primitiveFail() int asyncFileInit(void) { vm= sqGetInterpreterProxy(); sqUnixAsyncFileSessionID= clock() + time(0); FD_ZERO(&fds); nfd= 0; return 1; } int asyncFileShutdown(void) { /* protect against calling stale aio handlers */ int i; for (i= 0; i < nfd; ++i) if (FD_ISSET(i, &fds)) aioDisable(i); nfd= 0; FD_ZERO(&fds); sqUnixAsyncFileSessionID= 0; return 1; } /*** module ***/ #include #include #include #include #ifdef __GNUC__ # define INLINE inline #else # define INLINE #endif #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) static void readHandler(int fd, void *data, int flags); static void writeHandler(int fd, void *data, int flags); INLINE static FilePtr newFileRec(int fd, int sema) { FilePtr fp= (FilePtr)calloc(1, sizeof(FileRec)); if (fp) { fp->fd= fd; fp->sema= sema; fp->rd.status= Busy; /* read not ready */ fp->wr.status= Busy; /* write not complete */ } return fp; } INLINE static allocateBuffer(struct FileBuf *buf, int size) { if (buf->capacity >= size) return 1; if (buf->capacity > 0) { free(buf->bytes); buf->capacity= 0; } buf->bytes= (char *)malloc(size); if (!buf->bytes) { fprintf(stderr, "out of memory\n"); return 0; } buf->capacity= size; return 1; } FilePtr asyncFileAttach(AsyncFile *f, int fd, int semaIndex) { FilePtr fp= newFileRec(fd, semaIndex); if (fp) { f->sessionID= sqUnixAsyncFileSessionID; f->state= (void *)fp; aioEnable(fd, (void *)fp, 0); FD_SET(fd, &fds); nfd= max(nfd, fd + 1); return fp; /* success */ } fprintf(stderr, "out of memory\n"); f->sessionID= 0; f->state= 0; return 0; } /*** public functions ***/ int asyncFileOpen(AsyncFile *f, int fileNamePtr, int fileNameSize, int writeFlag, int semaIndex) { int fd= 0; char *name= alloca(fileNameSize + 1); memcpy((void *)name, (void *)fileNamePtr, fileNameSize); name[fileNameSize]= '\0'; /* if opening for wr then open for rw so that we can use these primitives to read bidirectional files (e.g., master ptys for interactive child processes) */ fd= (writeFlag ? open(name, O_RDWR | O_CREAT, 0644) : open(name, O_RDONLY)); if (fd >= 0) { if (asyncFileAttach(f, fd, semaIndex)) return 0; /* success */ close(fd); } vm->primitiveFail(); return 0; /* failure */ } int asyncFileClose(AsyncFile *f) { FilePtr fp= 0; validate(f); if ((fp= (FilePtr)f->state)) { if (fp->fd >= 0) { aioDisable(fp->fd); FD_CLR(fp->fd, &fds); close(fp->fd); } if (fp->buf.bytes) free((void *)fp->buf.bytes); free((void *)fp); f->state= 0; } return 0; /* success */ } /* this no longer appears to be used */ int asyncFileRecordSize(void) { fprintf(stderr, "asyncFileRecordSize() called -- why?\n"); vm->primitiveFail(); return 0; } int asyncFileReadResult(AsyncFile *f, int bufferPtr, int bufferSize) { FilePtr fp= 0; int n= 0; validate(f); fp= (FilePtr)f->state; n= read(fp->fd, (void *)bufferPtr, bufferSize); if ((n < 0) && (errno == EWOULDBLOCK)) return fp->rd.status= Busy; else if (n <= 0) return fp->rd.status= Error; else /* (n > 0) */ fp->rd.pos += n; return fp->rd.status= n; } static void readHandler(int fd, void *data, int flags) { signalSemaphoreWithIndex(((FilePtr)data)->sema); } int asyncFileReadStart(AsyncFile *f, int fPosition, int count) { FilePtr fp= 0; validate(f); fp= (FilePtr)f->state; if (( (fPosition >= 0)) /* (fPos < 0) => current position */ && (fp->rd.pos != fPosition)) /* avoid EPIPE on pty */ { if (lseek(fp->fd, fPosition, SEEK_SET) < 0) { perror("lseek"); goto fail; } fp->rd.pos= fPosition; } fp->rd.status= Busy; aioHandle(fp->fd, readHandler, AIO_R); return 0; fail: fp->rd.status= Error; vm->primitiveFail(); return 0; } int asyncFileWriteResult(AsyncFile *f) { int n= 0; FilePtr fp= 0; validate(f); fp= (FilePtr)f->state; n= fp->wr.status; fp->wr.status= Busy; return n; } static void writeBuffer(FilePtr fp) { int n= 0; while ((n= fp->buf.size - fp->buf.pos) > 0) { n= write(fp->fd, (void *)(fp->buf.bytes + fp->buf.pos), n); if (n < 0) switch (errno) { case EWOULDBLOCK: aioHandle(fp->fd, writeHandler, AIO_W); return; default: fp->wr.status= Error; return; } fp->buf.pos += n; fp->wr.pos += n; } /* completed */ fp->wr.status= fp->buf.size; signalSemaphoreWithIndex(fp->sema); } static void writeHandler(int fd, void *data, int flags) { writeBuffer((FilePtr)data); } int asyncFileWriteStart(AsyncFile *f, int fPosition, int bufferPtr, int count) { FilePtr fp= 0; validate(f); fp= (FilePtr)f->state; if (( (fPosition >= 0)) /* (fPos < 0) => current position */ && (fp->wr.pos != fPosition)) /* avoid EPIPE on tty */ { if (lseek(fp->fd, fPosition, SEEK_SET) < 0) { perror("lseek"); goto fail; } fp->wr.pos= fPosition; } if (count < 1) { fp->wr.status= 0; signalSemaphoreWithIndex(fp->sema); return 0; } if (!allocateBuffer(&fp->buf, count)) { fprintf(stderr, "out of memory\n"); goto fail; } memcpy((void *)fp->buf.bytes, (void *)bufferPtr, count); fp->buf.pos= 0; /* current output pointer */ fp->buf.size= count; /* bytes to transfer */ fp->wr.status= Busy; /* transfer in progress */ writeBuffer(fp); /* begin transfer */ return 0; fail: fp->wr.status= Error; vm->primitiveFail(); return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.h ================================================ /* private file data */ typedef struct { int fd; /* descriptor */ int sema; /* completion semaphore */ struct { int pos; /* file position */ int status; /* number of bytes transferred, or: */ # define Busy -1 /* operation in progress */ # define Error -2 /* operation aborted */ } rd, wr; /* one each for read and write */ struct FileBuf { char *bytes; /* write buffer */ int capacity; /* capacity */ int size; /* contents size */ int pos; /* position */ } buf; } FileRec, *FilePtr; extern int sqUnixAsyncFileSessionID; extern FilePtr asyncFileAttach(AsyncFile *f, int fd, int semaIndex); ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/Makefile.inc ================================================ XCFLAGS=$(WFLAGS) $(X_CFLAGS) $(X_INCLUDES) XLDFLAGS=$(X_LIBS) ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/NOTES ================================================ added in sqOpenGLRenderer.h #elif defined(UNIX) # include # include "sqUnixOpenGL.h" added in platform.exports #ifdef UNIX XFN(stDisplay) XFN(stWindow) #endif added "-lGL" in Makefile to line B3DAcceleratorPlugin.la : ... ... -lGL ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/acinclude.m4 ================================================ if test "${have_gl}" != "yes"; then AC_PLUGIN_DISABLE fi ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/build.cmake ================================================ # B3DAccel depends on the main display plugin having GL (vm-display-X11) or AGL # (vm-display-Quartz) as a dependency. This lets 3D work in both X11 and Quartz # on MacOS. EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/config.cmake ================================================ IF (OPENGL_FOUND OR AGL_FOUND) SET (USE_OPENGL 1) PLUGIN_INCLUDE_DIRECTORIES (${OPENGL_INCLUDE_DIR}) ELSE () PLUGIN_DISABLE () ENDIF () IF (OPENGL_FOUND) SET (USE_X11_GLX 1) ENDIF () IF (AGL_FOUND) SET (USE_QUARTZ_CGL 1) SET (HAVE_OPENGL_GL_H 1) ENDIF () IF (OPENGL_FOUND OR AGL_FOUND) CHECK_INCLUDE_FILE (GL/gl.h HAVE_GL_GL_H -I${OPENGL_INCLUDE_DIR}) ENDIF (OPENGL_FOUND OR AGL_FOUND) CONFIG_DEFINE (USE_OPENGL) CONFIG_DEFINE (USE_X11_GLX) CONFIG_DEFINE (USE_QUARTZ_CGL) CONFIG_DEFINE (HAVE_GL_GL_H) CONFIG_DEFINE (HAVE_OPENGL_GL_H) ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/sqUnixOpenGL.c ================================================ /* sqUnixOpenGL.c -- support for accelerated 3D rendering * * Author: Bert Freudenberg * * Modified to work with both GLX and Quartz by: Ian.Piumarta@INRIA.Fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Note: the os-specific parts (ioGL* functions) are defined in * sqUnixX11.c (for X11/GLX on Unix) and * sqUnixQuartz.m (for Quartz/CoreGL on MacOSX). */ #include "sq.h" #include "B3DAcceleratorPlugin.h" #include "sqOpenGLRenderer.h" #include "SqDisplay.h" #include #include extern struct VirtualMachine *interpreterProxy; static struct SqDisplay *dpy= 0; static glRenderer *current= 0; static glRenderer renderers[MAX_RENDERER]; static float blackLight[4]= { 0.0f, 0.0f, 0.0f, 0.0f }; int glInitialize(void) { int i; for (i= 0; i < MAX_RENDERER; ++i) renderers[i].used= 0; if (!(dpy= ioGetDisplayModule())) return 0; dpy->ioGLinitialise(); return 1; } int glShutdown(void) { int i; for (i= 0; i < MAX_RENDERER; ++i) if (renderers[i].used) glDestroyRenderer(i); dpy= 0; return 1; } int glMakeCurrentRenderer(glRenderer *renderer) { if (current == renderer) return 1; if (renderer) { if (!renderer->used) return 0; if (!dpy->ioGLmakeCurrentRenderer(renderer)) { DPRINTF3D(1, (fp, "glMakeCurrentRenderer failed\n")); return 0; } } else dpy->ioGLmakeCurrentRenderer(0); current= renderer; return 1; } int glCreateRendererFlags(int x, int y, int w, int h, int flags) { glRenderer *renderer= 0; int index; if (flags & ~(B3D_HARDWARE_RENDERER | B3D_SOFTWARE_RENDERER | B3D_STENCIL_BUFFER)) { DPRINTF3D(1, (fp, "ERROR: Unsupported renderer flags (%d)\r", flags)); return -1; } for (index= 0; index < MAX_RENDERER; ++index) if (!renderers[index].used) break; if (index == MAX_RENDERER) { DPRINTF3D(1, (fp, "ERROR: Maximum number of renderers (%d) exceeded\r", MAX_RENDERER)); return -1; } renderer= renderers + index; renderer->drawable= 0; renderer->context= 0; DPRINTF3D(3, (fp, "---- Creating new renderer ----\r\r")); if ((w < 0) || (h < 0)) { DPRINTF3D(1, (fp, "Negative extent (%i@%i)!\r", w, h)); goto fail; } else if (dpy->ioGLcreateRenderer(renderer, x, y, w, h, flags)) { renderer->used = 1; renderer->bufferRect[0] = x; renderer->bufferRect[1] = y; renderer->bufferRect[2] = w; renderer->bufferRect[3] = h; if (!glMakeCurrentRenderer(renderer)) { DPRINTF3D(1, (fp, "Failed to make context current\r")); glDestroyRenderer(index); return -1; } DPRINTF3D(3, (fp, "\r### Renderer created! ###\r")); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_DITHER); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glDepthFunc(GL_LEQUAL); glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glShadeModel(GL_SMOOTH); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, blackLight); glErrorCheck(); return index; } fail: DPRINTF3D(1, (fp, "OpenGL initialization failed\r")); return -1; } glRenderer *glRendererFromHandle(int handle) { DPRINTF3D(7, (fp, "Looking for renderer id: %i\r", handle)); if ((handle >= 0) && (handle < MAX_RENDERER) && renderers[handle].used) return renderers + handle; return 0; } int glDestroyRenderer(int handle) { glRenderer *renderer= glRendererFromHandle(handle); DPRINTF3D(3, (fp, "\r--- Destroying renderer ---\r")); if (renderer) { if (!glMakeCurrentRenderer(0)) return 0; dpy->ioGLdestroyRenderer(renderer); renderer->drawable = 0; renderer->context = 0; renderer->used = 0; } return 1; } int glIsOverlayRenderer(int handle) { return 1; } int glSwapBuffers(glRenderer *renderer) { if (renderer && renderer->used) dpy->ioGLswapBuffers(renderer); return 1; } int glSetBufferRect(int handle, int x, int y, int w, int h) { glRenderer *renderer= glRendererFromHandle(handle); if (renderer && glMakeCurrentRenderer(renderer) && (w > 0) && (h > 0)) { renderer->bufferRect[0]= x; renderer->bufferRect[1]= y; renderer->bufferRect[2]= w; renderer->bufferRect[3]= h; dpy->ioGLsetBufferRect(renderer, x, y, w, h); return 1; } return 0; } /* Verbose level for debugging purposes: 0 - print NO information ever 1 - print critical debug errors 2 - print debug warnings 3 - print extra information 4 - print extra warnings 5 - print information about primitive execution ... 10 - print information about each vertex and face */ int glSetVerboseLevel(int level) { verboseLevel= level; return 1; } int glGetIntPropertyOS(int handle, int prop) { GLint v; glRenderer *renderer= glRendererFromHandle(handle); if (renderer && glMakeCurrentRenderer(renderer)) switch (prop) { case 1: /* backface culling */ if (!glIsEnabled(GL_CULL_FACE)) return 0; glGetIntegerv(GL_FRONT_FACE, &v); switch (v) { case GL_CW: return 1; case GL_CCW: return -1; } break; case 2: /* polygon mode */ glGetIntegerv(GL_POLYGON_MODE, &v); glErrorCheck(); return v; case 3: /* point size */ glGetIntegerv(GL_POINT_SIZE, &v); glErrorCheck(); return v; case 4: /* line width */ glGetIntegerv(GL_LINE_WIDTH, &v); glErrorCheck(); return v; } return 0; } int glSetIntPropertyOS(int handle, int prop, int value) { glRenderer *renderer= glRendererFromHandle(handle); if (renderer && glMakeCurrentRenderer(renderer)) switch (prop) { case 1: /* backface culling */ if (!value) glDisable(GL_CULL_FACE); else { glEnable(GL_CULL_FACE); glFrontFace((value == 1) ? GL_CCW : GL_CW); } glErrorCheck(); return 1; case 2: /* polygon mode */ switch (value) { case 0: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case 1: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; case 2: glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break; default: return 0; } glErrorCheck(); return 1; case 3: /* point size */ glPointSize(value); glErrorCheck(); return 1; case 4: /* line width */ glLineWidth(value); glErrorCheck(); return 1; } return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/sqUnixOpenGL.h ================================================ #ifndef __sqUnixOpenGL_h #define __sqUnixOpenGL_h #include "config.h" typedef struct glRenderer { int bufferRect[4]; int viewport[4]; int used; void *drawable; void *context; } glRenderer; #if defined(USE_X11_GLX) || defined (USE_QUARTZ_CGL) # define GL_RENDERER_DEFINED 1 # define MAX_RENDERER 16 # if defined(HAVE_GL_GL_H) # include # else # if defined(HAVE_OPENGL_GL_H) # include # else # error *** cannot find gl.h # endif # endif #endif extern sqInt ioGLinitialise(void); extern sqInt ioGLcreateRenderer(glRenderer *r, sqInt x, sqInt y, sqInt w, sqInt h, sqInt flags); extern void ioGLdestroyRenderer(glRenderer *r); extern sqInt ioGLmakeCurrentRenderer(glRenderer *r); extern void ioGLswapBuffers(glRenderer *r); extern void ioGLsetBufferRect(glRenderer *r, sqInt x, sqInt y, sqInt w, sqInt h); #define glErrorCheck() ERROR_CHECK #endif /* __sqUnixOpenGL_h */ ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/zzz/sqUnixOpenGL.OSX ================================================ /* sqUnixOpenGLOSX.c -- accelerated 3D rendering on Mac OS X using CoreGL -*- C -*- * * Author: Ian.Piumarta@inria.fr * * Copyright (C) 1996-2002 Ian Piumarta and other authors/contributors * as listed elsewhere in this file. * All rights reserved. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you want to modify it and then make * your modifications available publicly, rename the file first. * * This file is part of Unix Squeak. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. * * Last edited: 2003-01-31 21:53:21 by piumarta on emilia.local. */ #include #include "sqVirtualMachine.h" #include "sqPlatformSpecific.h" #include "B3DAcceleratorPlugin.h" #if defined (B3DX_GL) #include "sqUnixOpenGL.h" #include "sqOpenGLRenderer.h" #include extern void *ioGLcreateView(int x, int y, int w, int h, int flags); extern void *ioGLcreateContext(void *drawable); extern int ioGLsetCurrentContext(void *ctx); extern int ioGLdestroyContext(void *ctx); extern int ioGLdestroyView(void *drawable); extern int ioGLflushBuffer(void *drawable, void *ctx); int verboseLevel= 1; extern struct VirtualMachine *interpreterProxy; static glRenderer *current= 0; static glRenderer renderers[MAX_RENDERER]; static float blackLight[4]= { 0.0f, 0.0f, 0.0f, 0.0f }; #define TRACE() fprintf(stderr, "--- %s\n", __PRETTY_FUNCTION__) int glInitialize(void) { int i; TRACE(); for (i= 0; i < MAX_RENDERER; ++i) renderers[i].used= 0; return 1; } int glShutdown(void) { TRACE(); } int glMakeCurrentRenderer(glRenderer *renderer) { GLboolean ok; GLint err; //DPRINTF("glMakeCurrentRenderer(%p)\n", renderer); if (current == renderer) return 1; if (renderer && ((!renderer->used) || (!renderer->context))) return 0; ok= ioGLsetCurrentContext(renderer ? renderer->context : 0); if ((err= glGetError()) != GL_NO_ERROR) fprintf(stderr, "glMakeCurrentRenderer: %s\n", CGLErrorString(err)); if (!ok) { fprintf(stderr, "glMakeCurrentRenderer: glSetCurrentContext failed\n"); return 0; } current= renderer; return 1; } int glCreateRendererFlags(int x, int y, int w, int h, int flags) { void *drawable= 0; void *context= 0; glRenderer *renderer= 0; int i; //printf("glCreateRendererFlags(%d, %d, %d, %d, 0x%x)\n", x, y, w, h, flags); for (i= 0; i < MAX_RENDERER; ++i) if (!renderers[i].used) break; if (i == MAX_RENDERER) { fprintf(stderr, "glCreateRenderer: too many renderers\n"); return -1; } renderer= renderers+i; //printf(" renderer = %p handle %d\n", renderer, i); drawable= ioGLcreateView(x, y, w, h, flags); //printf(" drawable = %p\n", drawable); if (!drawable) return -1; context= ioGLcreateContext(drawable); //printf(" context = %p\n", context); if (!context) { ioGLdestroyView(drawable); return -1; } renderer->context= context; renderer->drawable= drawable; renderer->used= 1; #if 0 renderer->finished = 0; #endif renderer->bufferRect[0] = x; renderer->bufferRect[1] = y; renderer->bufferRect[2] = w; renderer->bufferRect[3] = h; glMakeCurrentRenderer(renderer); //DPRINTF(" vendor: %s\n", glGetString(GL_VENDOR)); //DPRINTF(" renderer: %s\n", glGetString(GL_RENDERER)); //DPRINTF(" version: %s\n", glGetString(GL_VERSION)); //DPRINTF(" extensions: %s\n", glGetString(GL_EXTENSIONS)); ERROR_CHECK; //DPRINTF(" renderer created, handle = %d\n", i); /* setup user context */ glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_DITHER); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glDepthFunc(GL_LEQUAL); glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glShadeModel(GL_SMOOTH); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, blackLight); ERROR_CHECK; return i; } glRenderer *glRendererFromHandle(int handle) { if ((handle < 0) || (handle >= MAX_RENDERER)) { fprintf(stderr, "GL: illegal handle: %d\n", handle); return 0; } return renderers+0; } int glDestroyRenderer(int handle) { glRenderer *renderer= glRendererFromHandle(handle); TRACE(); if (!renderer) return 1; /* already destroyed */ if (!glMakeCurrentRenderer(0)) return 0; ioGLdestroyContext(renderer->context); ioGLdestroyView(renderer->drawable); renderer->context= 0; renderer->used= 0; return 1; } int glIsOverlayRenderer(int handle) { TRACE(); return 1; } int glSwapBuffers(glRenderer *renderer) { ioGLflushBuffer(renderer->drawable, renderer->context); } int glSetBufferRect(int handle, int x, int y, int w, int h) { glRenderer *renderer= 0; printf("glSetBufferRect(%d, %d, %d, %d, %d)\n", handle, x, y, w, h); renderer= glRendererFromHandle(handle); if (!renderer || !glMakeCurrentRenderer(renderer)) return 0; if (w < 1 || h < 1) return 0; renderer->bufferRect[0]= x; renderer->bufferRect[1]= y; renderer->bufferRect[2]= w; renderer->bufferRect[3]= h; ioGLsetBufferRect(renderer->context); return 1; } int glSetVerboseLevel(int level) { TRACE(); /*exit(1);*/ } int glGetIntPropertyOS(int handle, int prop) { TRACE(); exit(1); } int glSetIntPropertyOS(int handle, int prop, int value) { TRACE(); exit(1); } #endif /* defined(B3DX_GL) */ ================================================ FILE: vm/src/from_squeak/unix/plugins/B3DAcceleratorPlugin/zzz/sqUnixOpenGL.X11 ================================================ /* sqUnixOpenGLX11.c -- support for accelerated 3D rendering under X11 -*- C -*- * * Author: Bert Freudenberg * * Based on Andreas Raab's sqWin32OpenGL.c * * Last edited: 2003-01-31 22:40:39 by piumarta on emilia.local. * * History * Nov 02: added TGraphicsTest conformant log support * Oct 02: added Tea initialization support w/ stencil * May 01: initial revision */ #include #include "sqVirtualMachine.h" #include "sqConfig.h" #include "sqPlatformSpecific.h" #include "B3DAcceleratorPlugin.h" #if defined (B3DX_GL) #include "sqUnixOpenGL.h" #include #include #include "sqOpenGLRenderer.h" /* Plugin refs */ extern struct VirtualMachine *interpreterProxy; static void printVisual(XVisualInfo* visinfo); static void listVisuals(); static Display *stDisplay= NULL; /* Squeak's display */ static Window stWindow= 0; /* Squeak's main window */ static glRenderer *current= NULL; static glRenderer allRenderer[MAX_RENDERER]; static int visualAttributes[]= { GLX_STENCIL_SIZE, 0, /* filled in later - must be first item! */ GLX_ALPHA_SIZE, 1, /* filled in later - must be second item! */ GLX_RGBA, /* no indexed colors */ GLX_DOUBLEBUFFER, /* will swap */ GLX_LEVEL, 0, /* frame buffer, not overlay */ GLX_DEPTH_SIZE, 16, /* decent depth */ GLX_AUX_BUFFERS, 0, /* no aux buffers */ GLX_ACCUM_RED_SIZE, 0, /* no accumulation */ GLX_ACCUM_GREEN_SIZE, 0, GLX_ACCUM_BLUE_SIZE, 0, GLX_ACCUM_ALPHA_SIZE, 0, None }; static float blackLight[4]= { 0.0f, 0.0f, 0.0f, 0.0f }; /* Verbose level for debugging purposes: 0 - print NO information ever 1 - print critical debug errors 2 - print debug warnings 3 - print extra information 4 - print extra warnings 5 - print information about primitive execution 10 - print information about each vertex and face */ int verboseLevel= 1; /*** create / destroy a renderer ***/ int glCreateRendererFlags(int x, int y, int w, int h, int flags) { glRenderer *renderer; XVisualInfo* visinfo= 0; int index= -1; if (flags & ~(B3D_HARDWARE_RENDERER | B3D_SOFTWARE_RENDERER | B3D_STENCIL_BUFFER)) { DPRINTF3D(1, (fp, "ERROR: Unsupported renderer flags (%d)\r", flags)); return -1; } if (flags & B3D_STENCIL_BUFFER) visualAttributes[1]= 1; else visualAttributes[1]= 0; /* find unused renderer */ { int i; for (i= 0; i < MAX_RENDERER; i++) { if (!allRenderer[i].used) { index= i; break; } } } if (index == -1) { DPRINTF3D(1, (fp, "ERROR: Maximum number of renderers (%d) exceeded\r", MAX_RENDERER)); return 0; } renderer= &allRenderer[index]; renderer->used= True; renderer->window= 0; renderer->context= NULL; DPRINTF3D(3, (fp, "---- Creating new renderer ----\r\r")); /* sanity checks */ if (w < 0 || h < 0) { DPRINTF3D(1, (fp, "Negative extent (%i@%i)!\r", w, h)); goto FAILED; } /* choose visual and create context */ if (verboseLevel >= 3) listVisuals(); { visinfo= glXChooseVisual(stDisplay, DefaultScreen(stDisplay), visualAttributes); if (!visinfo) { /* retry without alpha */ visualAttributes[3]= 0; visinfo= glXChooseVisual(stDisplay, DefaultScreen(stDisplay), visualAttributes); } if (!visinfo) { DPRINTF3D(1, (fp, "No OpenGL visual found!\r")); goto FAILED; } DPRINTF3D(3, (fp, "\r#### Selected GLX visual ID 0x%lx ####\r", visinfo->visualid)); if (verboseLevel >= 3) printVisual(visinfo); renderer->context= glXCreateContext(stDisplay, visinfo, 0, GL_TRUE); if (!renderer->context) { DPRINTF3D(1, (fp, "Creating GLX context failed!\r")); goto FAILED; } DPRINTF3D(3, (fp, "\r#### Created GLX context ####\r" )); /* create window */ { XSetWindowAttributes attributes; unsigned long valuemask= 0; attributes.colormap= XCreateColormap(stDisplay, DefaultRootWindow(stDisplay), visinfo->visual, AllocNone); valuemask|= CWColormap; attributes.background_pixel= BlackPixel(stDisplay, DefaultScreen(stDisplay)); valuemask|= CWBackPixel; renderer->window= XCreateWindow(stDisplay, stWindow, x, y, w, h, 0, visinfo->depth, InputOutput, visinfo->visual, valuemask, &attributes); if (!renderer->window) { DPRINTF3D(1, (fp, "Failed to create client window\r")); goto FAILED; } XMapWindow(stDisplay, renderer->window); } DPRINTF3D(3, (fp, "\r#### Created window ####\r" )); XFree(visinfo); visinfo= 0; } /* Make the context current */ if (!glXMakeCurrent(stDisplay, renderer->window, renderer->context)) { DPRINTF3D(1, (fp, "Failed to make context current\r")); goto FAILED; } renderer->bufferRect[0]= x; renderer->bufferRect[1]= y; renderer->bufferRect[2]= w; renderer->bufferRect[3]= h; DPRINTF3D(3, (fp, "\r### Renderer created! ###\r")); /* setup user context */ glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_DITHER); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glDepthFunc(GL_LEQUAL); glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glShadeModel(GL_SMOOTH); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, blackLight); ERROR_CHECK; return index; FAILED: /* do necessary cleanup */ DPRINTF3D(1, (fp, "OpenGL initialization failed\r")); if (visinfo) XFree(visinfo); if (renderer->context) glXDestroyContext(stDisplay, renderer->context); if (renderer->window) XDestroyWindow(stDisplay, renderer->window); return -1; } int glDestroyRenderer(int handle) { glRenderer *renderer= glRendererFromHandle(handle); DPRINTF3D(3, (fp, "\r--- Destroying renderer ---\r")); if (!renderer) return 1; /* already destroyed */ if (!glMakeCurrentRenderer(NULL)) return 0; glXDestroyContext(stDisplay, renderer->context); XDestroyWindow(stDisplay, renderer->window); renderer->window= 0; renderer->context= NULL; renderer->used= False; return 1; } /*** helpers ***/ glRenderer *glRendererFromHandle(int handle) { DPRINTF3D(7, (fp, "Looking for renderer id: %i\r", handle)); if (handle < 0 || handle >= MAX_RENDERER) return NULL; if (allRenderer[handle].used) return allRenderer+handle; return NULL; } int glIsOverlayRenderer(int handle) { /* we always use overlay renderers */ return 1; } int glSwapBuffers(glRenderer *renderer) { if (!renderer || !renderer->used) return 0; glXSwapBuffers(stDisplay, renderer->window); return 1; } int glMakeCurrentRenderer(glRenderer *renderer) { if (current == renderer) return 1; if (renderer && !renderer->used) return 0; if (renderer) { if (!glXMakeCurrent(stDisplay, renderer->window, renderer->context)) { DPRINTF3D(1, (fp, "Failed to make context current\r")); return 0; } } else { glXMakeCurrent(stDisplay, 0, NULL); } current= renderer; return 1; } int glSetBufferRect(int handle, int x, int y, int w, int h) { glRenderer *renderer= glRendererFromHandle(handle); if (!renderer || !glMakeCurrentRenderer(renderer)) return 0; if (w < 1 || h < 1) return 0; XMoveResizeWindow(stDisplay, renderer->window, x, y, w, h); renderer->bufferRect[0]= x; renderer->bufferRect[1]= y; renderer->bufferRect[2]= w; renderer->bufferRect[3]= h; return 1; } int glSetVerboseLevel(int level) { verboseLevel= level; return 1; } int glGetIntPropertyOS(int handle, int prop) { GLint v; glRenderer *renderer= glRendererFromHandle(handle); if (!renderer || !glMakeCurrentRenderer(renderer)) return 0; switch(prop) { case 1: /* backface culling */ if (!glIsEnabled(GL_CULL_FACE)) return 0; glGetIntegerv(GL_FRONT_FACE, &v); if (v == GL_CW) return 1; if (v == GL_CCW) return -1; return 0; case 2: /* polygon mode */ glGetIntegerv(GL_POLYGON_MODE, &v); ERROR_CHECK; return v; case 3: /* point size */ glGetIntegerv(GL_POINT_SIZE, &v); ERROR_CHECK; return v; case 4: /* line width */ glGetIntegerv(GL_LINE_WIDTH, &v); ERROR_CHECK; return v; } return 0; } int glSetIntPropertyOS(int handle, int prop, int value) { glRenderer *renderer= glRendererFromHandle(handle); if (!renderer || !glMakeCurrentRenderer(renderer)) return 0; switch(prop) { case 1: /* backface culling */ if (!value) { glDisable(GL_CULL_FACE); ERROR_CHECK; return 1; } glEnable(GL_CULL_FACE); glFrontFace(value == 1 ? GL_CCW : GL_CW); ERROR_CHECK; return 1; case 2: /* polygon mode */ if (value == 0) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else if (value == 1) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else if (value == 2) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); else return 0; ERROR_CHECK; return 1; case 3: /* point size */ glPointSize(value); ERROR_CHECK; return 1; case 4: /* line width */ glLineWidth(value); ERROR_CHECK; return 1; } return 0; } /* GLX_CONFIG_CAVEAT might not be supported */ /* but the test below is worded so it does not matter */ #ifndef GLX_CONFIG_CAVEAT # define GLX_CONFIG_CAVEAT 0x20 # define GLX_SLOW_CONFIG 0x8001 #endif static void printVisual(XVisualInfo* visinfo) { int isOpenGL; glXGetConfig(stDisplay, visinfo, GLX_USE_GL, &isOpenGL); if (isOpenGL) { int slow= 0; int red, green, blue, alpha, stencil, depth; glXGetConfig(stDisplay, visinfo, GLX_CONFIG_CAVEAT, &slow); glXGetConfig(stDisplay, visinfo, GLX_RED_SIZE, &red); glXGetConfig(stDisplay, visinfo, GLX_GREEN_SIZE, &green); glXGetConfig(stDisplay, visinfo, GLX_BLUE_SIZE, &blue); glXGetConfig(stDisplay, visinfo, GLX_ALPHA_SIZE, &alpha); glXGetConfig(stDisplay, visinfo, GLX_STENCIL_SIZE, &stencil); glXGetConfig(stDisplay, visinfo, GLX_DEPTH_SIZE, &depth); if (slow != GLX_SLOW_CONFIG) DPRINTF3D(3, (fp,"===> OpenGL visual\r")) else DPRINTF3D(3, (fp,"---> slow OpenGL visual\r")); DPRINTF3D(3, (fp,"rgbaBits = %i+%i+%i+%i\r", red, green, blue, alpha)); DPRINTF3D(3, (fp,"stencilBits = %i\r", stencil)); DPRINTF3D(3, (fp,"depthBits = %i\r", depth)); } } static void listVisuals() { XVisualInfo* visinfo; int nvisuals, i; visinfo= XGetVisualInfo(stDisplay, VisualNoMask, NULL, &nvisuals); for (i= 0; i < nvisuals; i++) { DPRINTF3D(3, (fp,"#### Checking pixel format (visual ID 0x%lx)\r", visinfo[i].visualid)); printVisual(&visinfo[i]); } XFree(visinfo); } /*** Module initializers ***/ int glInitialize(void) { int i, p; int fn; fn= interpreterProxy->ioLoadFunctionFrom("ioGetDisplay", NULL); stDisplay= (fn ? ((Display *(*)(void))fn)() : 0); if (!stDisplay) { DPRINTF3D(1,(fp,"ERROR: Failed to look up stDisplay\r")); return 0; } fn= interpreterProxy->ioLoadFunctionFrom("ioGetWindow", NULL); stWindow= (fn ? ((Window (*)(void))fn)() : 0); if (!stWindow) { DPRINTF3D(1,(fp,"ERROR: Failed to look up stWindow\r")); return 0; } for (i= 0; i < MAX_RENDERER; i++) { allRenderer[i].used= False; } return 1; } int glShutdown(void) { int i; for (i=0; i< MAX_RENDERER; i++) { if (allRenderer[i].used) { glDestroyRenderer(i); } } return 1; } #endif /* defined(B3DX_GL) */ ================================================ FILE: vm/src/from_squeak/unix/plugins/CameraPlugin/sqCamera.c ================================================ /* * V4L2 for Scratch (Derek O'Connell, 2009) * * This code can be used and distributed without restrictions. * */ #include "sq.h" #include #include #include #include #include /* getopt_long() */ #include /* low-level i/o */ #include #include #include #include #include #include #include #include #include #include /* for videodev2.h */ #include /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ /* #define USE_LIBV4L2x #ifdef USE_LIBV4L2 #include #endif */ void *hLibv4l2 = NULL; int (*vd_open)(const char *, int, ...); int (*vd_close)(int); int (*vd_dup)(int); int (*vd_ioctl)(int, unsigned long int, ...); ssize_t (*vd_read)(int, void *, size_t); void * (*vd_mmap)(void *, size_t, int, int, int, int64_t); int (*vd_munmap)(void *, size_t); /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ #define CLEAR(x) memset (&(x), 0, sizeof (x)) typedef enum { IO_METHOD_READ, IO_METHOD_MMAP, IO_METHOD_USERPTR, } io_method; struct buffer { void * start; size_t length; }; struct camInfo_t { int devNum; int fileDesc; int bmWidth, bmHeight; io_method ioMethod; int pixelformat; struct buffer * buffers; unsigned int nBuffers; struct v4l2_buffer read_buf; void *sqBuffer; long sqBufferBytes; long sqPixels; long frameCount; } camInfo[10]; typedef struct camInfo_t *camPtr; static char * videoDevName0 = "/dev/video0"; /* ================================== FUNCTION PROTOTYPES */ /* LIBRARY CONSTRUCTOR/DESCTRUCTOR */ void __attribute__ ((constructor)) libCon(void); void __attribute__ ((destructor)) libDes(void); /* UTILITY */ inline int camIsOpen( camPtr cam) { return (-1 != cam->fileDesc); } inline int camIsClosed(camPtr cam) { return (-1 == cam->fileDesc); } /* V4L ACCESS */ /* SQUEAK INTERFACE */ sqInt CameraGetParam(int camNum, int paramNum); sqInt CameraGetFrame(int camNum, unsigned char* buf, int pixelCount); sqInt CameraExtent(int camNum); char* CameraName(int camNum); void CameraClose(int camNum); sqInt CameraOpen(int camNum, int frameWidth, int frameHeight); /* ================================== ??? */ /* LIBRARY CONSTRUCTOR/DESCTRUCTOR */ void __attribute__ ((constructor)) libCon(void) { int devNum; camPtr cam; vd_open = open; vd_close = close; vd_dup = dup; vd_ioctl = ioctl; vd_read = read; vd_mmap = mmap; vd_munmap = munmap; /* printf("libv4l2: use if available..."); */ hLibv4l2 = dlopen("libv4l2.so", RTLD_LAZY); if (hLibv4l2) { /* printf("yay!\n"); */ vd_open = dlsym(hLibv4l2, "v4l2_open"); vd_close = dlsym(hLibv4l2, "v4l2_close"); vd_dup = dlsym(hLibv4l2, "v4l2_dup"); vd_ioctl = dlsym(hLibv4l2, "v4l2_ioctl"); vd_read = dlsym(hLibv4l2, "v4l2_read"); vd_mmap = dlsym(hLibv4l2, "v4l2_mmap"); vd_munmap = dlsym(hLibv4l2, "v4l2_munmap"); } else { /* printf("nay, %s\n", dlerror()); */ } for (devNum = 0; devNum < 10; ++devNum) { cam = &camInfo[devNum]; CLEAR(*cam); cam->devNum = devNum; cam->fileDesc = -1; cam->ioMethod = IO_METHOD_MMAP; cam->read_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cam->read_buf.memory = V4L2_MEMORY_MMAP; cam->nBuffers = 1; /* Pixel format now auto selected according to ease/speed of conversion cam->pixelformat = V4L2_PIX_FMT_YUYV; cam->pixelformat = V4L2_PIX_FMT_RGB24; */ /* cam->fileDesc = 0; cam->bmWidth = 0; cam->bmHeight = 0; cam->buffers = NULL; cam->nBuffers = 0; cam->read_buf = NULL; cam->sqBuffer = 0; cam->sqBufferBytes = 0; cam->sqPixels = 0; cam->frameCount = 0; */ } } void __attribute__ ((destructor)) libDes(void) { int camNum; for (camNum = 1; camNum < 11; ++camNum) CameraClose(camNum); /* if (hLibv4l2) dlclose(hLibv4l2); */ } /* V4L ACCESS */ static int xioctl (camPtr cam, int request, void * arg) { int r; do r = vd_ioctl (cam->fileDesc, request, arg); while (-1 == r && EINTR == errno); return r; } /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from: palettes.c in VideoForLinuxPlugin from: http://en.wikipedia.org/wiki/YUV422 Originally (here) a quick hack for XO-1 but libv4l version worked anyway. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ inline unsigned char clipPixel(const int pixel) { int result; result = ((pixel < 0) ? 0 : pixel); return (unsigned char) ((result > 255) ? 255: result); } inline void convertPixelYUV444toARGB32( const unsigned char y, const unsigned char u, const unsigned char v, unsigned char* dest) { const int C = (y - 16) * 298 + 128; const int D = u - 128; const int E = v - 128; /* ARGB */ dest[0] = clipPixel(( C + 516 * D ) >> 8); dest[1] = clipPixel(( C - 100 * D - 208 * E) >> 8); dest[2] = clipPixel(( C + 409 * E) >> 8); dest[3] = 255; } inline void convertImageYUYVToARGB32 (camPtr cam, int bufIdx) { int i; const unsigned char* src = cam->buffers[bufIdx].start; unsigned char* dst = cam->sqBuffer; unsigned long int *pdst; unsigned long int pixelCount = cam->sqPixels; unsigned char u, y1, v, y2; for (i = 0; i < pixelCount; i += 2) { y1 = *src++; u = *src++; y2 = *src++; v = *src++; convertPixelYUV444toARGB32(y1, u, v, dst); pdst = (unsigned long *)dst; dst += 4; if (y2 == y1) *(unsigned long *)dst = *pdst; else convertPixelYUV444toARGB32(y2, u, v, dst); dst += 4; } } /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ static void convertImageRGB24toARGB32 (camPtr cam, int bufIdx) /* const void *src, const void *dst) */ { unsigned char *src = cam->buffers[bufIdx].start; unsigned long int *dst = cam->sqBuffer; unsigned long int pixelCount = cam->sqPixels; unsigned long int pixel; int i; if (0 == dst) return; for ( i = 0; i < pixelCount; i++) { pixel = 0xFF000000 | (*src++ << 16); pixel = pixel | (*src++ << 8); *dst++ = pixel | *src++; } } static void convertImageRGB444toARGB32 (camPtr cam, int bufIdx) /* const void *src, const void *dst) */ { unsigned char *src = cam->buffers[bufIdx].start; unsigned long int *dst = cam->sqBuffer; unsigned long int pixelCount = cam->sqPixels; unsigned long int r,g,b,pixel; int i; if (0 == dst) return; /* Byte0: (g)ggg(b)bbb, Byte1: xxxx(r)rrr */ for ( i = 0; i < pixelCount; i++) { r = *src << 4; g = *src++ & 0xF0; b = (*src++ & 0x0F) << 4; pixel = 0xFF000000; pixel |= (r << 16); pixel |= (g << 8); pixel |= b; *dst++ = pixel; } } static void convertImageRGB565toARGB32 (camPtr cam, int bufIdx) /* const void *src, const void *dst) */ { unsigned char *src = cam->buffers[bufIdx].start; unsigned long int *dst = cam->sqBuffer; unsigned long int pixelCount = cam->sqPixels; unsigned long int r,g,b,pixel; int i; if (0 == dst) return; /* Byte0: ggg(r)rrrr, Byte1: (b)bbbb(g)gg */ for ( i = 0; i < pixelCount; i++) { r = (*src & 0x1F) << 3; g = (*src++ & 0xE0) >> 5; g |= (*src & 0x07) << 5; b = *src++ & 0xF8; pixel = 0xFF000000; pixel |= (b << 16); pixel |= (g << 8); pixel |= r; *dst++ = pixel; } } void convertImage (camPtr cam, int bufIdx) { /* func pts to be used at later date */ if (cam->pixelformat == V4L2_PIX_FMT_YUYV) { convertImageYUYVToARGB32 (cam, bufIdx); return; } if (cam->pixelformat == V4L2_PIX_FMT_RGB565) { convertImageRGB565toARGB32 (cam, bufIdx); return; } if (cam->pixelformat == V4L2_PIX_FMT_RGB444) { convertImageRGB444toARGB32 (cam, bufIdx); return; } if (cam->pixelformat == V4L2_PIX_FMT_RGB24) { convertImageRGB24toARGB32 (cam, bufIdx); return; } } static int read_frame (camPtr cam) { struct v4l2_buffer buf; cam->frameCount += 1; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl (cam, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: case EIO: return 0; default: return -1; } } if (buf.index < cam->nBuffers) convertImage (cam, buf.index); if (-1 == xioctl (cam, VIDIOC_QBUF, &buf)) return -1; return 0; } static int getFrame(camPtr cam) { int fd = cam->fileDesc; unsigned int retry; fd_set fds; struct timeval tv; int r; retry = 1; while (retry-- > 0) { FD_ZERO (&fds); FD_SET (fd, &fds); /* Timeout. */ tv.tv_sec = 1; tv.tv_usec = 0; r = select (fd + 1, &fds, NULL, NULL, &tv); if (-1 == r) { if (EINTR == errno) continue; return -1; } if (0 == r) return -1; if (0 == read_frame (cam)) return 0; /* EAGAIN - retry */ } } static int stream_off (camPtr cam) { enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl (cam, VIDIOC_STREAMOFF, &type); return 0; } static int stream_on (camPtr cam) { enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl (cam, VIDIOC_STREAMON, &type)) return -1; return 0; } static int uninit_device (camPtr cam) { unsigned int i; for (i = 0; i < cam->nBuffers; ++i) if (-1 == vd_munmap (cam->buffers[i].start, cam->buffers[i].length)) return -1; free (cam->buffers); return 0; } static int queue_buffers (camPtr cam) { unsigned int i; for (i = 0; i < cam->nBuffers; ++i) { struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (-1 == xioctl (cam, VIDIOC_QBUF, &buf)) return -1; } return 0; } static int init_mmap (camPtr cam) { struct v4l2_requestbuffers req; int bufIdx; CLEAR (req); req.count = cam->nBuffers; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl (cam, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { return -1; } else { return -1; } } if (req.count < 1) return -1; cam->buffers = calloc (req.count, sizeof (*(cam->buffers))); if (!cam->buffers) return -1; for (bufIdx = 0; bufIdx < req.count; ++bufIdx) { struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = bufIdx; if (-1 == xioctl (cam, VIDIOC_QUERYBUF, &buf)) return -1; cam->buffers[bufIdx].length = buf.length; cam->buffers[bufIdx].start = vd_mmap (NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, cam->fileDesc, buf.m.offset); if (MAP_FAILED == cam->buffers[bufIdx].start) return -1; } return 0; } static int set_format (camPtr cam, struct v4l2_format *fmt, int pixelformat, int w, int h) { /* fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; fmt->fmt.pix.field = V4L2_FIELD_TOP; */ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; fmt->fmt.pix.pixelformat = pixelformat; fmt->fmt.pix.field = V4L2_FIELD_NONE; /* V4L2_FIELD_INTERLACED; */ if (-1 == xioctl (cam, VIDIOC_S_FMT, fmt)) return -1; /* Note VIDIOC_S_FMT may change width and height. */ if ((w != fmt->fmt.pix.width) | (h != fmt->fmt.pix.height) | (fmt->fmt.pix.pixelformat != pixelformat)) { return -1; } cam->pixelformat = pixelformat; return 0; } static int init_device (camPtr cam, int w, int h) { struct v4l2_capability cap; struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format fmt; int bpp; unsigned int min; if (-1 == xioctl (cam, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno) { return -1; } else { return -1; } } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) return -1; if (!(cap.capabilities & V4L2_CAP_STREAMING)) return -1; /* Select video input, video standard and tune here. */ CLEAR (cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (0 == xioctl (cam, VIDIOC_CROPCAP, &cropcap)) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; /* reset to default */ if (-1 == xioctl (cam, VIDIOC_S_CROP, &crop)) { if (EINVAL == errno) { /* Cropping not supported (ignored) */ } else { /* Errors ignored. */ } } } else { /* Errors ignored. */ } CLEAR (fmt); /* The order of preference of formats... */ if (-1 == set_format(cam, &fmt, V4L2_PIX_FMT_RGB24, w, h)) if (-1 == set_format(cam, &fmt, V4L2_PIX_FMT_YUYV, w, h)) if (-1 == set_format(cam, &fmt, V4L2_PIX_FMT_RGB565, w, h)) if (-1 == set_format(cam, &fmt, V4L2_PIX_FMT_RGB444, w, h)) return -1; /* For reference: V4L2_PIX_FMT_RGB24 : 3 bytes == 1 dst pixel V4L2_PIX_FMT_RGB565: 2 bytes == 1 dst pixel V4L2_PIX_FMT_RGB444: 2 bytes == 1 dst pixel V4L2_PIX_FMT_YUYV : 4 bytes == 2 dst pixels */ switch (fmt.fmt.pix.pixelformat) { case V4L2_PIX_FMT_RGB24: /* printf("V4L2_PIX_FMT_RGB24\n"); */ bpp = 3; break; case V4L2_PIX_FMT_RGB565: /* printf("V4L2_PIX_FMT_RGB565\n"); */ bpp = 2; break; case V4L2_PIX_FMT_RGB444: /* printf("V4L2_PIX_FMT_RGB444\n"); */ bpp = 2; break; case V4L2_PIX_FMT_YUYV: /* printf("V4L2_PIX_FMT_YUYV\n"); */ bpp = 4; break; } /* Buggy driver paranoia >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ min = fmt.fmt.pix.width * bpp; if (fmt.fmt.pix.bytesperline < min) fmt.fmt.pix.bytesperline = min; min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; if (fmt.fmt.pix.sizeimage < min) fmt.fmt.pix.sizeimage = min; /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ if (0 > init_mmap(cam)) return -1; if (0 > queue_buffers(cam)) return -1; /* cache returned dims (make fmt a global?) */ cam->bmWidth = fmt.fmt.pix.width; cam->bmHeight = fmt.fmt.pix.height; cam->sqPixels = cam->bmWidth * cam->bmHeight; cam->sqBufferBytes = cam->sqPixels * 4; /* Bytes to tx to Squeak (always RGB32) */ return 0; } static int close_device (camPtr cam) { if (-1 == vd_close (cam->fileDesc)) return -1; cam->fileDesc = -1; return 0; } static int open_device (camPtr cam) { char deviceName[12]; struct stat st; strcpy(deviceName, videoDevName0); deviceName[10] = cam->devNum + '0'; if (-1 == stat (deviceName, &st)) return -1; if (!S_ISCHR (st.st_mode)) return -1; cam->fileDesc = vd_open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0); if (camIsClosed(cam)) return -1; return 0; } int InitCamera(camPtr cam, int w, int h) { cam->read_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cam->read_buf.memory = V4L2_MEMORY_MMAP; cam->ioMethod = IO_METHOD_MMAP; if (0 > open_device(cam)) return -1; if (0 > init_device(cam, w, h)) { close_device(cam); return -1; } if (0 > stream_on(cam)) { uninit_device(cam); close_device(cam); return -1; } return 0; } /* ============================================= SCRATCH I/F ==================================================== */ sqInt CameraGetParam(int camNum, int paramNum) { camPtr cam = &camInfo[camNum-1]; return 0; } /* "Copy a camera frame into the given Bitmap. The Bitmap should be for a Form of depth 32 that is the same width and height as the current camera frame. Fail if the camera is not open or if the bitmap is not the right size. If successful, answer the number of frames received from the camera since the last call. If this is zero, then there has been no change." ??? */ sqInt CameraGetFrame(int camNum, unsigned char* buf, int pixelCount) { camPtr cam = &camInfo[camNum-1]; if (camIsClosed(cam)) return false; if (pixelCount != cam->sqPixels) return false; cam->sqBuffer = (void *)buf; if (0 != getFrame(cam)) return 0; return 1; } sqInt CameraExtent(int camNum) { camPtr cam = &camInfo[camNum-1]; if (camIsClosed(cam)) return 0; return (cam->bmWidth << 16) + cam->bmHeight; } char* CameraName(int camNum) { camPtr cam = &camInfo[camNum-1]; if (camIsClosed(cam)) return "camera not open"; return "default camera"; } void CameraClose(int camNum) { camPtr cam = &camInfo[camNum-1]; if (camIsClosed(cam)) return; stream_off(cam); uninit_device(cam); close_device(cam); } sqInt CameraOpen(int camNum, int frameWidth, int frameHeight) { camPtr cam = &camInfo[camNum-1]; if (camIsOpen(cam)) return false; if (0 != InitCamera(cam, frameWidth, frameHeight)) return false; return true; } ================================================ FILE: vm/src/from_squeak/unix/plugins/ClipboardExtendedPlugin/Makefile.inc ================================================ XINCLUDES= $(X_INCLUDES) XLDFLAGS= $(X_LIBS) ================================================ FILE: vm/src/from_squeak/unix/plugins/ClipboardExtendedPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/ClipboardExtendedPlugin/config.cmake ================================================ IF (NOT X11_FOUND) PLUGIN_DISABLE() ENDIF () ================================================ FILE: vm/src/from_squeak/unix/plugins/ClipboardExtendedPlugin/sqUnixExtendedClipboard.c ================================================ /* sqUnixExtendedClipboard.c -- support for clipboard with multiple types * * Copyright (C) 2007 by Viewpoints Research Institute and other * authors/contributors as listed. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #ifdef CLIPBOARD_TEST #include typedef int sqInt; #else #include "sqVirtualMachine.h" extern struct VirtualMachine* interpreterProxy; #endif /* ifdef CLIPBOARD_TEST */ extern Display * stDisplay; char ** clipboardGetTypeNames(); sqInt clipboardSizeWithType(char * typeName, int ntypeName); sqInt clipboardReadIntoAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex); void * firstIndexableField(sqInt oop); void clipboardWriteWithType(char * data, size_t ndata, char * typeName, size_t ntypeName, int isDnd, int isClaiming); #ifndef CLIPBOARD_TEST void sqPasteboardClear( sqInt inPasteboard ) { /* NOT IMPLEMENTED YET */ } /* Return a number of types. * Update it only if the selection is CLIPBOARD */ int sqPasteboardGetItemCount(sqInt inPasteboard) { int i= 0; char ** types; types= clipboardGetTypeNames(); if (NULL == types) return 0; for (i= 0; NULL != types[i]; i++) free(types[i]); /* XFree() is better */ free(types); return i; } /* Answer a type name at index. */ int sqPasteboardCopyItemFlavorsitemNumber (sqInt inPasteboard, int formatNumber) { size_t length; int outData; char * dest; char ** types; char * type; if (formatNumber < 1) return interpreterProxy->nilObject(); /* TODO: clipboardGetTypeNames() is should be cached. */ /* TODO: types should be free(). */ types= clipboardGetTypeNames(); if (types == NULL) return interpreterProxy->nilObject(); type= types[formatNumber - 1]; if (type == NULL) return interpreterProxy->nilObject(); length= strlen(type); outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), length); dest = ((char *) (interpreterProxy->firstIndexableField(outData))); memcpy(dest, type, length); return outData; } /* In X11 clipboard is global in a display, so it just return 1 */ sqInt sqCreateClipboard( void ) { return 1; } void sqPasteboardPutItemFlavordatalengthformatTypeformatLength ( sqInt inPasteboard, char * data, int ndata, char * typeName, int ntypeName) { clipboardWriteWithType(data, ndata, typeName, ntypeName, 0, 1); } /* Read the clipboard */ int sqPasteboardCopyItemFlavorDataformatformatLength (sqInt inPasteboard, char* format, int formatLength) { int bytes= 0; sqInt outData; bytes= clipboardSizeWithType(format, formatLength); outData = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), bytes); clipboardReadIntoAt(bytes, (sqInt) firstIndexableField(outData), 0); return outData; } #endif /* #ifndef CLIPBOARD_TEST */ #ifdef CLIPBOARD_TEST static Display * display; Display * ioGetDisplay() { return display; } char * getSelectionData(Atom selection, Atom target, size_t * bytes, XEvent * event) { char * answer= "Hello world!"; *bytes= strlen(answer) + 1; char * result= calloc(*bytes, 1); memcpy(result, answer, *bytes); return result; } void updateInputTargets(Atom * newTargets, int targetSize) { } int main () { Window window; int i; size_t nitems; display= XOpenDisplay(NULL); if(display == NULL) { printf("Cannot open display\n"); return 1; } window= XCreateSimpleWindow(display, DefaultRootWindow(display), 10, 10, 100, 100, 1, 0, 0); getItemFravors(); getItemFravors(); printf("\n"); char * text= (char *) getSelectionData( atom("CLIPBOARD"), atom("STRING"), &nitems); printf("String contents: %s\n", text); return 0; } #endif /* CLIPBOARD_TEST */ ================================================ FILE: vm/src/from_squeak/unix/plugins/DBusPlugin/Makefile.inc ================================================ XCPPFLAGS= [DBUS_CFLAGS] XLDFLAGS= [DBUS_LIBS] ================================================ FILE: vm/src/from_squeak/unix/plugins/DBusPlugin/acinclude.m4 ================================================ PKG_CHECK_MODULES(DBUS,dbus-1,,AC_PLUGIN_DISABLE) AC_PLUGIN_DEFINE_UNQUOTED(DBUS_CFLAGS,$DBUS_CFLAGS) AC_PLUGIN_DEFINE_UNQUOTED(DBUS_LIBS,$DBUS_LIBS); ================================================ FILE: vm/src/from_squeak/unix/plugins/DBusPlugin/config.cmake ================================================ PLUGIN_REQUIRE_PACKAGE (DBUS1 dbus-1) ================================================ FILE: vm/src/from_squeak/unix/plugins/DropPlugin/Makefile.inc ================================================ XCPPFLAGS= -I$(topdir)/platforms/Cross/plugins/FilePlugin ================================================ FILE: vm/src/from_squeak/unix/plugins/DropPlugin/sqUnixDragDrop.c ================================================ /* sqUnixDragDrop.c -- support for drag and drop, for those UIs that have it * * Author: Ian Piumarta * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Why on earth does this plugin exist at all? Brain death strikes * again. And why are half the functions never called from the VM? * Could it be that they are only there for certain ports (we'll * mention no names) in which the core support needs to grub around in * this plugin via ioLoadFunctionFromModule (and, putting disbelief * aside for a moment, maybe even VICE-VERSA)? It seems to me that * truth is very definitely not beauty today. Sigh... */ #include "sq.h" #include "sqVirtualMachine.h" #include "FilePlugin.h" #include "DropPlugin.h" #include extern struct VirtualMachine *interpreterProxy; extern int uxDropFileCount; extern char **uxDropFileNames; int dropInit(void) { return 1; } int dropShutdown(void) { return 1; } char *dropRequestFileName(int dropIndex) // in st coordinates { if ((dropIndex > 0) && (dropIndex <= uxDropFileCount)) { assert(uxDropFileNames); dndReceived(uxDropFileNames[dropIndex - 1]); return uxDropFileNames[dropIndex - 1]; } return 0; } int dropRequestFileHandle(int dropIndex) { char *path= dropRequestFileName(dropIndex); if (path) { // you cannot be serious? int handle= instantiateClassindexableSize(classByteArray(), fileRecordSize()); sqFileOpen((SQFile *)fileValueOf(handle), (int)path, strlen(path), 0); return handle; } return interpreterProxy->nilObject(); } int sqSecFileAccessCallback(void *callback) { return 0; } void sqSetNumberOfDropFiles(int numberOfFiles) { } void sqSetFileInformation(int dropIndex, void *dropFile) { } ================================================ FILE: vm/src/from_squeak/unix/plugins/FT2Plugin/FT2PluginHeaderFix-ikp.1.cs ================================================ 'From Squeak3.10.2 of ''5 June 2008'' [latest update: #7179] on 2 April 2010 at 7:58:47 am'! "Change Set: FT2PluginHeaderFix-ikp Date: 2 April 2010 Author: Ian Piumarta freetype-config -cflags adds /usr/include/freetype2 to include paths under which exists freetype/tttables.h so we need to use the two-level relative path when including that file."! !FT2Plugin class methodsFor: 'translation' stamp: 'ikp 4/2/2010 07:55'! declareCVarsIn: cg cg addHeaderFile: ''. cg addHeaderFile: ''. cg addHeaderFile: 'FT_FREETYPE_H'. cg addHeaderFile: 'FT_OUTLINE_H'. cg var: 'library' declareC: 'FT_Library library'. cg var: 'errorCode' type: 'int'.! ! ================================================ FILE: vm/src/from_squeak/unix/plugins/FT2Plugin/config.cmake ================================================ PLUGIN_FIND_PACKAGE (FREETYPE freetype2) IF (NOT FREETYPE_FOUND) CHECK_INCLUDE_FILE (freetype.h HAVE_FREETYPE_H) CHECK_INCLUDE_FILE (freetype2/freetype.h HAVE_FREETYPE2_FREETYPE_H) IF (NOT HAVE_FREETYPE_H AND NOT HAVE_FREETYPE2_FREETYPE_H) PLUGIN_DISABLE () ELSE () PLUGIN_REQUIRE_LIBRARY (FREETYPE freetype) PLUGIN_REQUIRE_LIBRARY (Z z) ENDIF () ENDIF () ================================================ FILE: vm/src/from_squeak/unix/plugins/FileCopyPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/FileCopyPlugin/sqUnixFileCopyPlugin.c ================================================ /* sqUnixFileCopyPlugin.c -- fast file copy, preserving permissions * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Author: ian.piumarta@inria.fr * * NOTE: * This plugin is kind of ridiculous. Nevertheless, after seeing what * somebody (and I honestly have no idea who) decided would be a good * implementation of this (it might still be on SourceForge if you're * perverse wough to want to look at it) I was dumbfounded into writing * a version that didn't open pipes to forked processes. (Now I bet * you can't possibly resist having a peek for the original. ;^p) * (Besides, the original version had BUGS -- in a one page program. 8^o) * * CAVEATS: * - we should use mmap() only if the file is "large" (define that as * you will), preferring a few block-sized read()/write()s otherwise * - we should fall back onto the loop if mmap fails (we might simply * have a file larger than available memory) * * BUGS: * - some of the system calls should handle EAGAIN and/or EINTR (this * will cause problems on Solaris) * (the following could be fixed if we had a real "config.h":) * - we assume but not everyone has this * - we assume alloca() but not everyone has this (ANSI does not define it) * - use of stat.st_blksize is extremely non-portable * * COMPILE: * gcc -Wall -W -pedantic -o copy copy.c */ #include "sq.h" #include "FileCopyPlugin.h" #include "config.h" #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_MMAP # include #endif static int copy(char *from, char *to) { int status= 1; /* exit status: assume failure */ int in; struct stat stat; if (((in= open(from, O_RDONLY)) < 0) || (fstat(in, &stat) != 0)) return -1; { int out; if ((out= open(to, O_WRONLY | O_CREAT | O_TRUNC, stat.st_mode)) < 0) return -1; { # ifdef HAVE_MMAP static const char *_dev_zero= "/dev/zero"; int zero; if ((zero= open(_dev_zero, O_RDWR)) >= 0) { void *mem; if (MAP_FAILED != (mem= mmap(0, stat.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero, 0))) { if (( (read(in, mem, stat.st_size) != stat.st_size) >= 0) && (write(out, mem, stat.st_size) != stat.st_size) >= 0) { status= 0; /* success */ } munmap(mem, stat.st_size); } close(zero); } # else /* !HAVE_MMAP */ char *buf= (char *)alloca(stat.st_blksize); int n; while (( ((n= read(in, buf, stat.st_blksize)) > 0)) && (n == write(out, buf, n))) ; if (n == 0) status= 0; /* success */ # endif /* !HAVE_MMAP */ close(out); } close(in); } return status; } int sqCopyFilesizetosize(char *srcName, int srcNameSize, char *dstName, int dstNameSize) { int status= 0; char *from= (char *)alloca(srcNameSize + 1); char *to= (char *)alloca(dstNameSize + 1); sqFilenameFromString(from, (int)srcName, srcNameSize); sqFilenameFromString(to, (int)dstName, dstNameSize); return copy(from, to); } ================================================ FILE: vm/src/from_squeak/unix/plugins/FilePlugin/config.cmake ================================================ CHECK_INCLUDE_FILE (dirent.h HAVE_DIRENT_H) CHECK_INCLUDE_FILE (sys/ndir.h HAVE_SYS_NDIR_H) CHECK_INCLUDE_FILE (sys/dir.h HAVE_SYS_DIR_H) CHECK_INCLUDE_FILE (ndir.h HAVE_NDIR_H) CHECK_INCLUDE_FILE (unistd.h HAVE_UNISTD_H) CONFIG_DEFINE (HAVE_DIRENT_H) CONFIG_DEFINE (HAVE_SYS_NDIR_H) CONFIG_DEFINE (HAVE_SYS_DIR_H) CONFIG_DEFINE (HAVE_NDIR_H) CONFIG_DEFINE (HAVE_UNISTD_H) ================================================ FILE: vm/src/from_squeak/unix/plugins/FilePlugin/sqUnixFile.c ================================================ /* sqUnixFile.c -- directory operations for Unix * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.Fr */ #include "sq.h" #include "FilePlugin.h" #include "sqUnixCharConv.h" #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif #ifdef HAVE_UNISTD_H # include # include #endif #include #include #include #include #include /*** The interface to the directory primitive is path based. That is, the client supplies a Squeak string describing the path to the directory on every call. To avoid traversing this path on every call, a cache is maintained of the last path seen, along with the Mac volume and folder reference numbers corresponding to that path. ***/ /*** Constants ***/ #define ENTRY_FOUND 0 #define NO_MORE_ENTRIES 1 #define BAD_PATH 2 #define DELIMITER '/' /*** Variables ***/ char lastPath[MAXPATHLEN+1]; int lastPathValid = false; int lastIndex= -1; DIR *openDir= 0; /*** Functions ***/ extern time_t convertToSqueakTime(time_t unixTime); sqInt dir_Create(char *pathString, sqInt pathStringLength) { /* Create a new directory with the given path. By default, this directory is created relative to the cwd. */ char name[MAXPATHLEN+1]; int i; if (pathStringLength >= MAXPATHLEN) return false; if (!sq2uxPath(pathString, pathStringLength, name, MAXPATHLEN, 1)) return false; return mkdir(name, 0777) == 0; /* rwxrwxrwx & ~umask */ } sqInt dir_Delete(char *pathString, sqInt pathStringLength) { /* Delete the existing directory with the given path. */ char name[MAXPATHLEN+1]; int i; if (pathStringLength >= MAXPATHLEN) return false; if (!sq2uxPath(pathString, pathStringLength, name, MAXPATHLEN, 1)) return false; if (lastPathValid && !strcmp(lastPath, name)) { closedir(openDir); lastPathValid= false; lastIndex= -1; lastPath[0]= '\0'; } return rmdir(name) == 0; } sqInt dir_Delimitor(void) { return DELIMITER; } static int maybeOpenDir(char *unixPath) { /* if the last opendir was to the same directory, re-use the directory pointer from last time. Otherwise close the previous directory, open the new one, and save its name. Return true if the operation was successful, false if not. */ if (!lastPathValid || strcmp(lastPath, unixPath)) { /* invalidate the old, open the new */ if (lastPathValid) closedir(openDir); lastPathValid= false; strcpy(lastPath, unixPath); if ((openDir= opendir(unixPath)) == 0) return false; lastPathValid= true; lastIndex= 0; /* first entry is index 1 */ } return true; } sqInt dir_Lookup(char *pathString, sqInt pathStringLength, sqInt index, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries 2 if the given path has bad syntax or does not reach a directory */ int i; int nameLen= 0; struct dirent *dirEntry= 0; char unixPath[MAXPATHLEN+1]; struct stat statBuf; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) strcpy(unixPath, "."); else if (!sq2uxPath(pathString, pathStringLength, unixPath, MAXPATHLEN, 1)) return BAD_PATH; /* get file or directory info */ if (!maybeOpenDir(unixPath)) return BAD_PATH; if (++lastIndex == index) index= 1; /* fake that the dir is rewound and we want the first entry */ else { rewinddir(openDir); /* really rewind it, and read to the index */ lastIndex= index; } for (i= 0; i < index; i++) { nextEntry: do { errno= 0; dirEntry= readdir(openDir); } while ((dirEntry == 0) && (errno == EINTR)); if (!dirEntry) return NO_MORE_ENTRIES; nameLen= NAMLEN(dirEntry); /* ignore '.' and '..' (these are not *guaranteed* to be first) */ if (nameLen < 3 && dirEntry->d_name[0] == '.') if (nameLen == 1 || dirEntry->d_name[1] == '.') goto nextEntry; } *nameLength= ux2sqPath(dirEntry->d_name, nameLen, name, MAXPATHLEN, 0); { char terminatedName[MAXPATHLEN]; strncpy(terminatedName, dirEntry->d_name, nameLen); terminatedName[nameLen]= '\0'; strcat(unixPath, "/"); strcat(unixPath, terminatedName); if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) { /* We can't stat the entry, but failing here would invalidate the whole directory --bertf */ return ENTRY_FOUND; } } /* last change time */ *creationDate= convertToSqueakTime(statBuf.st_ctime); /* modification time */ *modificationDate= convertToSqueakTime(statBuf.st_mtime); if (S_ISDIR(statBuf.st_mode)) *isDirectory= true; else *sizeIfFile= statBuf.st_size; return ENTRY_FOUND; } sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char* nameString, sqInt nameStringLength, /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile) { /* Lookup the given name in the given directory, Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). Return: 0 if a entry is found at the given index 1 if there is no such entry in the directory 2 if the given path has bad syntax or does not reach a directory */ char unixPath[MAXPATHLEN+1]; struct stat statBuf; /* default return values */ *name = 0; *nameLength = 0; *creationDate = 0; *modificationDate = 0; *isDirectory = false; *sizeIfFile = 0; if ((pathStringLength == 0)) strcpy(unixPath, "."); else if (!sq2uxPath(pathString, pathStringLength, unixPath, MAXPATHLEN, 1)) return BAD_PATH; char terminatedName[MAXPATHLEN+1]; strncpy(terminatedName, nameString, nameStringLength); terminatedName[nameStringLength]= '\0'; strcat(unixPath, "/"); strcat(unixPath, terminatedName); if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) { return NO_MORE_ENTRIES; } /* To match the results of dir_Lookup, copy back the file name */ *nameLength = ux2sqPath(nameString, nameStringLength, name, 256, 0); /* last change time */ *creationDate= convertToSqueakTime(statBuf.st_ctime); /* modification time */ *modificationDate= convertToSqueakTime(statBuf.st_mtime); if (S_ISDIR(statBuf.st_mode)) *isDirectory= true; else *sizeIfFile= statBuf.st_size; return ENTRY_FOUND; } /* unix files are untyped, and the creator is correct by default */ sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { return true; } sqInt dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { return true; } /* * The following is useful in a debugging context when the VM's output has been * directed to a log file. It binds stdout to /dev/tty, arranging that output * of debugging print routines such as printOop appear on stdout. */ void sqStdoutToDevTTY() { if (!freopen("/dev/tty","w",stdout)) perror("sqStdoutToDevTTY freopen(\"/dev/tty\",\"w\",stdout):"); } ================================================ FILE: vm/src/from_squeak/unix/plugins/FloatMathPlugin/Makefile.inc ================================================ CFLAGS = $(LIBM_CFLAGS) -DNO_ISNAN=1 ================================================ FILE: vm/src/from_squeak/unix/plugins/FloatMathPlugin/acinclude.m4 ================================================ libm_cflags="-O" if test "$GCC" = yes; then case $host_cpu in i?86) libm_cflags="-O -fomit-frame-pointer -DLSB_FIRST=1" ;; powerpc|ppc) libm_cflags="-O3 -funroll-loops -mcpu=750 -mno-fused-madd -DLSB_FIRST=0" ;; esac fi AC_SUBST(LIBM_CFLAGS, $libm_cflags) ================================================ FILE: vm/src/from_squeak/unix/plugins/FloatMathPlugin/build.cmake ================================================ SET (CMAKE_C_FLAGS "${LIBM_CFLAGS}") ================================================ FILE: vm/src/from_squeak/unix/plugins/FloatMathPlugin/config.cmake ================================================ PLUGIN_DEFINITIONS (-DNO_ISNAN=1) # fdlibm.h does not recognize x86_64, so set endianness here for all platforms. TEST_BIG_ENDIAN (IS_BIG_ENDIAN) IF (NOT IS_BIG_ENDIAN) PLUGIN_DEFINITIONS (-D__LITTLE_ENDIAN=1) ENDIF () # GCC optimizations break fdlibm so disable them for now. IF (CMAKE_COMPILER_IS_GNUCC) SET (LIBM_CFLAGS "${CMAKE_C_FLAGS} -O0 -mno-fused-madd") ELSE () SET (LIBM_CFLAGS "${CMAKE_C_FLAGS}") ENDIF () ================================================ FILE: vm/src/from_squeak/unix/plugins/GStreamerPlugin/Makefile.inc ================================================ XCPPFLAGS= [GSTREAMER_CFLAGS] XLDFLAGS= [GSTREAMER_LIBS] ================================================ FILE: vm/src/from_squeak/unix/plugins/GStreamerPlugin/acinclude.m4 ================================================ PKG_CHECK_MODULES(GSTREAMER,gstreamer-0.10,,AC_PLUGIN_DISABLE) AC_PLUGIN_DEFINE_UNQUOTED(GSTREAMER_CFLAGS,$GSTREAMER_CFLAGS) AC_PLUGIN_DEFINE_UNQUOTED(GSTREAMER_LIBS,$GSTREAMER_LIBS); ================================================ FILE: vm/src/from_squeak/unix/plugins/GStreamerPlugin/config.cmake ================================================ PLUGIN_REQUIRE_PACKAGE (GLIB2 glib-2.0) PLUGIN_REQUIRE_PACKAGE (XML2 libxml-2.0) PLUGIN_REQUIRE_PACKAGE (GSTREAMER gstreamer-0.10) ================================================ FILE: vm/src/from_squeak/unix/plugins/HostWindowPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/HostWindowPlugin/config.cmake ================================================ IF (NOT X11_FOUND) PLUGIN_DISABLE () ENDIF (NOT X11_FOUND) ================================================ FILE: vm/src/from_squeak/unix/plugins/HostWindowPlugin/sqUnixHostWindowPlugin.c ================================================ /* sqUnixHostWindowPlugin.c -- support for multiple host windows * * Copyright (C) 2009 by Bert Freudenberg and other * authors/contributors as listed. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #define AVOID_OPENGL_H 1 #include "sq.h" #include "SqDisplay.h" #include "HostWindowPlugin.h" #define FPRINTF(x) fprintf x static struct SqDisplay *dpy= 0; #define noDisplay ( (!dpy && !(dpy= ioGetDisplayModule())) || (dpy->version < 0x10002) ) /* closeWindow: arg is int windowIndex. Fail (return 0) if anything goes wrong * - typically the windowIndex invalid or similar */ int closeWindow(int index) { if (noDisplay) return 0; else return dpy->hostWindowClose(index); } /* createWindow: takes int width, height and origin x/y plus a char* list of * as yet undefined attributes. Returns an int window index or 0 for failure * Failure may occur because of an inability to add the window, too many * windows already extant (platform dependant), the specified size being * unreasonable etc. */ int createWindowWidthheightoriginXyattrlength( int w, int h, int x, int y, char *list, int attributeListLength) { if (noDisplay) return 0; else return dpy->hostWindowCreate(w, h, x, y, list, attributeListLength); } /* ioShowDisplayOnWindow: similar to ioShowDisplay but adds the int windowIndex * Return true if ok, false if not, but not currently checked */ sqInt ioShowDisplayOnWindow( unsigned char *dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB, sqInt windowIndex) { if (noDisplay) return 0; else return dpy->hostWindowShowDisplay( dispBitsIndex, width, height, depth, affectedL, affectedR, affectedT, affectedB, windowIndex); } /* ioSizeOfWindow: arg is int windowIndex. Return the size of the specified * window in (width<<16 || height) format like ioScreenSize. * Return -1 for failure - typically invalid windowIndex * -1 is chosen since itwould correspond to a window size of 64k@64k which * I hope is unlikely for some time to come */ int ioSizeOfWindow(int windowIndex) { if (noDisplay) return -1; else return dpy->hostWindowGetSize(windowIndex); } /* ioSizeOfWindowSetxy: args are int windowIndex, int w & h for the * width / height to make the window. Return the actual size the OS * produced in (width<<16 || height) format or -1 for failure as above. */ int ioSizeOfWindowSetxy(int windowIndex, int w, int h) { if (noDisplay) return -1; else return dpy->hostWindowSetSize(windowIndex, w, h); } /* ioPositionOfWindow: arg is int windowIndex. Return the pos of the specified * window in (left<<16 || top) format like ioScreenSize. * Return -1 (as above) for failure - typically invalid windowIndex */ int ioPositionOfWindow(int windowIndex) { if (noDisplay) return -1; else return dpy->hostWindowGetPosition(windowIndex); } /* ioPositionOfWindowSetxy: args are int windowIndex, int x & y for the * origin x/y for the window. Return the actual origin the OS * produced in (left<<16 || top) format or -1 for failure, as above */ int ioPositionOfWindowSetxy(int windowIndex, int x, int y) { if (noDisplay) return -1; else return dpy->hostWindowSetPosition(windowIndex, x, y); } /* ioSetTitleOfWindow: args are int windowIndex, char* newTitle and * int size of new title. Fail with -1 if windowIndex is invalid, string is too * long for platform etc. Leave previous title in place on failure */ int ioSetTitleOfWindow(int windowIndex, char *newTitle, int sizeOfTitle) { if (noDisplay) return -1; else return dpy->hostWindowSetTitle(windowIndex, newTitle, sizeOfTitle); } /* ioCloseAllWindows: intended for VM shutdown. * Close all the windows that appear to be open. * No useful return value since we're getting out of Dodge anyway. */ int ioCloseAllWindows(void) { if (noDisplay) return 0; else return dpy->hostWindowCloseAll(); } ================================================ FILE: vm/src/from_squeak/unix/plugins/ImmX11Plugin/acinclude.m4 ================================================ # xicfont options. AC_ARG_ENABLE(xicfont-option, AC_HELP_STRING([--enable-xicfont-option], [enable -xicfont option @<:@default=no@:>@]), AC_DEFINE(USE_XICFONT_OPTION, 1)) AC_ARG_ENABLE(xicfont-resource, AC_HELP_STRING([--enable-xicfont-resource], [read XResource for xicfont @<:@default=no@:>@]), AC_DEFINE(USE_XICFONT_RESOURCE, 1)) AC_ARG_ENABLE(xicfont-default, AC_HELP_STRING([--enable-xicfont-default], [read XDefault for xicfont @<:@default=no@:>@]), AC_DEFINE(USE_XICFONT_DEFAULT, 1)) ================================================ FILE: vm/src/from_squeak/unix/plugins/ImmX11Plugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/ImmX11Plugin/config.cmake ================================================ IF (NOT X11_FOUND) PLUGIN_DISABLE () ENDIF (NOT X11_FOUND) CONFIG_DEFINE(USE_XICFONT_OPTION) CONFIG_DEFINE(USE_XICFONT_RESOURCE) CONFIG_DEFINE(USE_XICFONT_DEFAULT) ================================================ FILE: vm/src/from_squeak/unix/plugins/JPEGReadWriter2Plugin/Makefile.inc ================================================ # this Makefile.inc intentionally left blank # # (to persuade VMMaker to generate the plugin) ================================================ FILE: vm/src/from_squeak/unix/plugins/JoystickTabletPlugin/sqUnixJoystickTablet.c ================================================ /* sqUnixJoystickTablet.c -- support for joysticks and graphics tablets * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.Fr */ #include "sq.h" #include "JoystickTabletPlugin.h" /* we don't have any joysticks */ void *joySticks= 0; int joystickRead(int index) { return 0; } int joystickInit(void) { return 0; } /* we don't have any tablets either */ int tabletInit(void) { return 0; } int tabletGetParameters(int cursorIndex, int result[]) { return 0; } int tabletRead(int cursorIndex, int result[]) { return 0; } int tabletResultSize(void) { return 0; } int joystickShutdown(void) { return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/LocalePlugin/sqUnixLocale.c ================================================ /* * sqUnixLocale.c * SqueakLocale stubs for Unix, so we can have the timezone. */ #include "sqUnixLocale.h" sqInt sqLocInitialize(void) { return 1; } /************** Country and language ******************/ /* write the country code into the string ptr. ISO 3166 is the relevant source * here; see http://www.unicode.org/onlinedat/countries.html for details. * Using the 3 character Alpha-3 codes */ void sqLocGetCountryInto(char * str) { str[0]=0; str[1]=0; str[2]=0; } /* write the 3 char string describing the language in use into string ptr. * ISO 639 is the relevant source here; * see http://www.w3.org/WAI/ER/IG/ert/iso639.html * for details */ void sqLocGetLanguageInto(char * str) { str[0]=0; str[1]=0; str[2]=0; } /***************** Currency ********************/ /* return 1 (true) if the currency symbol is to be placed in front of the *currency amount */ sqInt sqLocCurrencyNotation(void) { return 1; } /* return the length in chars of the curency symbol string */ sqInt sqLocCurrencySymbolSize(void) { return 1; } /* write the currency symbol into the string ptr */ void sqLocGetCurrencySymbolInto(char * str) { strcpy(str, "$"); } /***************** Numbers and measurements **************/ /* return true if the metric measurements system is to be used, false otherwise * (USA is about it) */ sqInt sqLocMeasurementMetric(void) { return 1; } /* write the 1 char used for digit grouping into string ptr. * Usually this is . or , as in 1,000,000 */ void sqLocGetDigitGroupingSymbolInto(char * str) { strncpy(str, ",", 1); } /* write the 1 char used for decimal separation into string ptr. * Usually this is . or , */ void sqLocGetDecimalSymbolInto(char * str) { strncpy(str, ".", 1); } /****************** time and date *********************/ sqInt sqLocGetVMOffsetToUTC(void) { /* return 0 for now */ return 0; } sqInt sqLocGetTimezoneOffset(void) { struct tm * timeBlock; time_t theTime; theTime = time((time_t)NULL); timeBlock = localtime(&theTime); return timeBlock->tm_gmtoff / 60; } /* return true if DST is in use, false otherwise */ sqInt sqLocDaylightSavings(void) { struct tm * timeBlock; time_t theTime; theTime = time((time_t)NULL); timeBlock = localtime(&theTime); return timeBlock->tm_isdst; } /* return the size in chars of the long date format string */ sqInt sqLocLongDateFormatSize(void) { return 0; } /*Write the string describing the long date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetLongDateFormatInto(char * str) { strcpy(str, ""); } /* return the size in chars of the short date format string */ sqInt sqLocShortDateFormatSize(void) { return 0; } /*Write the string describing the short date formatting into string ptr. * Format is made up of * d day, m month, y year, * double symbol is null padded, single not padded (m=6, mm=06) * dddd weekday * mmmm month name */ void sqLocGetShortDateFormatInto(char * str) { strcpy(str, ""); } /* return the size in chars of the time format string */ sqInt sqLocTimeFormatSize(void) { return 0; } /* write the string describing the time formatting into string ptr. * Format is made up of * h hour (h 12, H 24), m minute, s seconds, x (am/pm String) * double symbol is null padded, single not padded (h=6, hh=06) */ void sqLocGetTimeFormatInto(char * str) { strcpy(str, ""); } ================================================ FILE: vm/src/from_squeak/unix/plugins/LocalePlugin/sqUnixLocale.h ================================================ /* * sqUnixLocale.h * SqueakLocale stubs */ #include "sqMemoryAccess.h" #include #include #include "sq.h" ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/Makefile.inc ================================================ XLDFLAGS= -lasound ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/acinclude.m4 ================================================ AC_MSG_CHECKING([for MIDI support via ALSA]) AC_TRY_COMPILE([ #include ],[;],[ AC_MSG_RESULT(yes) AC_DEFINE(USE_MIDI_ALSA, 1) ],[ AC_MSG_RESULT(no) AC_PLUGIN_DISABLE ]) ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/config.cmake ================================================ PLUGIN_REQUIRE_INCLUDE (ALSA_SOUNDLIB alsa/asoundlib.h) PLUGIN_REQUIRE_LIBRARY (ASOUND asound) IF (HAVE_ALSA_SOUNDLIB_H AND HAVE_LIBASOUND) SET (USE_MIDI_ALSA 1) CONFIG_DEFINE (USE_MIDI_ALSA) ENDIF () ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/sqUnixMIDI.c ================================================ /* sqUnixMIDI.c -- Unix MIDI support * * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.FR * * Last edited: 2007-03-11 16:56:02 by piumarta on emilia.local */ #include "sq.h" #include "MIDIPlugin.h" #include "config.h" #if defined(USE_MIDI_ALSA) # include "sqUnixMIDIALSA.inc" #else # include "sqUnixMIDINone.inc" #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/sqUnixMIDIALSA.inc ================================================ /* sqUnixMIDIALSA.c -- Unix MIDI support via ALSA * * Copyright (C) 1996-2007 by Florian Hars and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Florian@Hars.de * * Reformatted for and integrated into Squeak build by: ian at * squeakland dot oh are gee * * Last edited: 2009-08-19 04:39:12 by piumarta on emilia-2.local */ /*** MIDI Parameters (used with sqMIDIParameter function) ***/ /* TODO: Why is this not in Cross/plugins/MIDIPlugin/MIDIPlugin.h ??? */ #define sqMIDIInstalled 1 /* Read-only. Return 1 if a MIDI driver is installed, 0 if not. On OMS-based MIDI drivers, this returns 1 only if the OMS system is properly installed and configured. */ #define sqMIDIVersion 2 /* Read-only. Return the integer version number of this MIDI driver. The version numbering sequence is relative to a particular driver. That is, version 3 of the Macintosh MIDI driver is not necessarily related to version 3 of the Win95 MIDI driver. */ #define sqMIDIHasBuffer 3 /* Read-only. Return 1 if this MIDI driver has a time-stamped output buffer, 0 otherwise. Such a buffer allows the client to schedule MIDI output packets to be sent later. This can allow more precise timing, since the driver uses timer interrupts to send the data at the right time even if the processor is in the midst of a long-running Squeak primitive or is running some other application or system task. */ #define sqMIDIHasDurs 4 /* Read-only. Return 1 if this MIDI driver supports an extended primitive for note-playing that includes the note duration and schedules both the note-on and the note-off messages in the driver. Otherwise, return 0. */ #define sqMIDICanSetClock 5 /* Read-only. Return 1 if this MIDI driver's clock can be set via an extended primitive, 0 if not. */ #define sqMIDICanUseSemaphore 6 /* Read-only. Return 1 if this MIDI driver can signal a semaphore when MIDI input arrives. Otherwise, return 0. If this driver supports controller caching and it is enabled, then incoming controller messages will not signal the semaphore. */ #define sqMIDIEchoOn 7 /* Read-write. If this flag is set to a non-zero value, and if the driver supports echoing, then incoming MIDI events will be echoed immediately. If this driver does not support echoing, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIUseControllerCache 8 /* Read-write. If this flag is set to a non-zero value, and if the driver supports a controller cache, then the driver will maintain a cache of the latest value seen for each MIDI controller, and control update messages will be filtered out of the incoming MIDI stream. An extended MIDI primitive allows the client to poll the driver for the current value of each controller. If this driver does not support a controller cache, then queries of this parameter will always return 0 and attempts to change its value will do nothing. */ #define sqMIDIEventsAvailable 9 /* Read-only. Return the number of MIDI packets in the input queue. */ #define sqMIDIFlushDriver 10 /* Write-only. Setting this parameter to any value forces the driver to flush its I/0 buffer, discarding all unprocessed data. Reading this parameter returns 0. Setting this parameter will do nothing if the driver does not support buffer flushing. */ #define sqMIDIClockTicksPerSec 11 /* Read-only. Return the MIDI clock rate in ticks per second. */ #define sqMIDIHasInputClock 12 /* Read-only. Return 1 if this MIDI driver timestamps incoming MIDI data with the current value of the MIDI clock, 0 otherwise. If the driver does not support such timestamping, then the client must read input data frequently and provide its own timestamping. */ /* Put the given port into MIDI mode, which uses a clock supplied by an external MIDI interface adaptor to determine the data rate. Possible external clock rates: 31.25 KHz, 0.5 MHz, 1 MHz, or 2 MHz. */ #include static snd_seq_t *seq = 0; static int queue = 0; static int in_port = -1; static int out_port = -1; /* MIDI Parser */ enum {idle, want1of2, want2of2, want1of1, sysExclusive}; static int state = idle; static int argByte1 = 0; static int argByte2 = 0; static int lastCmdByte = 0; /* number of argument bytes for each MIDI command */ char argumentBytes[128] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static void performMIDICmd(snd_seq_event_t *ev, int cmdByte, int arg1, int arg2); static void processMIDIByte(snd_seq_event_t *ev, int aByte); static void startMIDICommand(snd_seq_event_t *ev, int cmdByte); extern struct VirtualMachine *interpreterProxy; /* Close the given MIDI port. Do nothing if the port is not open. Fail if there is no port of the given number. */ int sqMIDIClosePort(int portNum) { int ret= 0; if (portNum == 0) { if (out_port >= 0) ret= snd_seq_delete_simple_port(seq, out_port); out_port= -1; } else if (portNum == 1) { if (in_port >= 0) ret= snd_seq_delete_simple_port(seq, in_port); in_port= -1; } else return interpreterProxy->success(false); return ret; } /* Return the current value of the clock used to schedule MIDI events. The MIDI clock is assumed to wrap at or before half the maximum positive SmallInteger value. This allows events to be scheduled into the future without overflowing into LargePositiveIntegers. This implementation does not support event scheduling, so it just returns the value of the Squeak millisecond clock. */ int sqMIDIGetClock(void) { debugf("sqMIDIGetClock\n"); success(false); return 0; } /* Return the number of available MIDI interfaces, including both hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ int sqMIDIGetPortCount(void) { debugf("sqMIDIGetPortCount\n"); success(true); return 1; } /* Return an integer indicating the directionality of the given port where: 1 = input, 2 = output, 3 = bidirectional. Fail if there is no port of the given number. */ int sqMIDIGetPortDirectionality(int portNum) { switch (portNum) { case 0: return 2; case 1: return 1; } return interpreterProxy->success(false); } /* Copy the name of the given MIDI port into the string at the given address. Copy at most length characters, and return the number of characters copied. Fail if there is no port of the given number. */ int sqMIDIGetPortName(int portNum, int namePtr, int length) { static char *userName[] = { "out", "in" }; if (portNum == 0 || portNum == 1) { int count= strlen(userName[portNum]); if (count > length) count= length; memcpy((void *)namePtr, userName, count); return count; } return interpreterProxy->success(false); } /* Open the given port, if possible. If non-zero, readSemaphoreIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Note that not all implementations support read semaphores (this one does not); see sqMIDICanUseSemaphore. The interfaceClockRate parameter specifies the clock speed for an external MIDI interface adaptor on platforms that use such adaptors (e.g., Macintosh). Fail if there is no port of the given number. */ int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate) { debugf("sqMIDIOpenPort(%d, %d, %d)\n", portNum, readSemaIndex, interfaceClockRate); int type= SND_SEQ_PORT_TYPE_APPLICATION; switch (portNum) { case 0: if (out_port < 0) { int caps_out= SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ; out_port= snd_seq_create_simple_port(seq, "out", caps_out, type); if (out_port < 0) { success(false); return 0; } } break; case 1: if (in_port < 0) { int caps_in= SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE; in_port= snd_seq_create_simple_port(seq, "in", caps_in, type); if (in_port < 0) { success(false); return 0; } } break; default: return interpreterProxy->success(false); } snd_seq_queue_tempo_t *tempo= 0; snd_seq_queue_tempo_alloca(&tempo); snd_seq_queue_tempo_set_tempo(tempo, interfaceClockRate); snd_seq_set_queue_tempo(seq, queue, tempo); success(true); return 0; } /* Read or write the given MIDI driver parameter. If modify is 0, then newValue is ignored and the current value of the specified parameter is returned. If modify is non-zero, then the specified parameter is set to newValue. Note that many MIDI driver parameters are read-only; attempting to set one of these parameters fails. For boolean parameters, true = 1, false = 0. */ int sqMIDIParameter(int whichParameter, int modify, int newValue) { if (modify == 0) { switch (whichParameter) { case sqMIDIInstalled: return 1; break; case sqMIDIVersion: return 100; break; case sqMIDIHasBuffer: return 1; break; case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: case sqMIDIEchoOn: case sqMIDIUseControllerCache: return 0; break; case sqMIDIEventsAvailable: return 1; /* pretend that events are always available */ break; case sqMIDIFlushDriver: return 0; break; case sqMIDIClockTicksPerSec: { snd_seq_queue_tempo_t *tempo= 0; snd_seq_queue_tempo_alloca(&tempo); snd_seq_get_queue_tempo(seq, queue, &tempo); return snd_seq_queue_tempo_get_tempo(tempo) / 1000.0; } break; case sqMIDIHasInputClock: return 0; break; default: return interpreterProxy->success(false); } } else /* modify != 0 */ { switch (whichParameter) { case sqMIDIInstalled: case sqMIDIVersion: case sqMIDIHasBuffer: case sqMIDIHasDurs: case sqMIDICanSetClock: case sqMIDICanUseSemaphore: return interpreterProxy->success(false); break; case sqMIDIEchoOn: /* no-op; echoing not supported */ break; case sqMIDIUseControllerCache: /* no-op; controller cache not supported */ break; case sqMIDIEventsAvailable: return interpreterProxy->success(false); break; case sqMIDIFlushDriver: snd_seq_drain_output(seq); break; case sqMIDIClockTicksPerSec: { snd_seq_queue_tempo_t *tempo= 0; snd_seq_queue_tempo_alloca(&tempo); snd_seq_queue_tempo_set_tempo(tempo, 1000.0 * newValue); snd_seq_set_queue_tempo(seq, queue, tempo); } break; default: return interpreterProxy->success(false); } } return 0; } /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Copy up to (length - 4) bytes of incoming MIDI data into that buffer, preceded by a 4-byte timestamp in the units of the MIDI clock, most significant byte first. Implementations that do not support timestamping of incoming data as it arrives (see sqMIDIHasInputClock) simply set the timestamp to the value of the MIDI clock when this function is called. Return the total number of bytes read, including the timestamp bytes. Return zero if no data is available. Fail if the buffer is shorter than five bytes, since there must be enough room for the timestamp plus at least one data byte. */ int sqMIDIPortReadInto(int portNum, int count, int bufferPtr) { debugf("sqMIDIPortRead\n"); success(false); return 0; } /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Send its contents to the given port when the MIDI clock reaches the given time. If time equals zero, then send the data immediately. Implementations that do not support a timestamped output queue, such as this one, always send the data immediately; see sqMIDIHasBuffer. */ int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time) { if (portNum == 0) { int i; snd_seq_event_t ev; unsigned char *bytePtr= (unsigned char *)bufferPtr; debugf("Port %d Write:", portNum); for (i= 0; i < count; ++i) debugf(" %d", (int)bytePtr[i]); debugf(" at %d\n", time); snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, out_port); snd_seq_ev_set_subs(&ev); snd_seq_ev_schedule_tick(&ev, queue, 0, time); for (i= 0; i < count; ++i) processMIDIByte(&ev, *bytePtr++); snd_seq_event_output(seq, &ev); snd_seq_drain_output(seq); success(true); return count; } return interpreterProxy->success(false); } int midiInit(void) { if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT|SND_SEQ_OPEN_OUTPUT, 0) < 0) { success(false); return 0; } snd_seq_set_client_name(seq, "Squeak"); queue= snd_seq_alloc_queue(seq); if (queue < 0) { snd_seq_close(seq); seq= NULL; success(false); return 0; } snd_seq_start_queue(seq, queue, NULL); success(true); return true; } int sqMIDIParameterSet(int whichParameter, int newValue) { sqMIDIParameter(whichParameter, true, newValue); return 0; } int sqMIDIParameterGet(int whichParameter) { sqMIDIParameter(whichParameter, false, 0); return 0; } int midiShutdown(void) { debugf("midiShutdown\n"); success(false); return 0; } static void performMIDICmd(snd_seq_event_t *ev, int cmdByte, int arg1, int arg2) { int cmd= cmdByte & 0xF0; int ch= cmdByte & 0x0F; switch (cmd) { case 128: /* note off */ debugf("Note off %d, %d\n", ch, arg1); snd_seq_ev_set_noteoff(ev, ch, arg1, 0); break; case 144: /* note on */ debugf("Note on %d, %d, %d\n", ch, arg1, arg2); snd_seq_ev_set_noteon(ev, ch, arg1, arg2); break; case 176: /* control change */ { int val= ((arg1 >= 32) && (arg1 <= 63)) ? (arg2 << 1) /* LSB of controllers 0-31 */ : (arg2 << 8); /* scale MSB to QT controller range */ snd_seq_ev_set_controller(ev, ch, arg1, val); } break; case 192: /* program change */ { int instrument= arg1 + 1; snd_seq_ev_set_pgmchange(ev, ch, instrument); } break; case 224: /* pitch bend */ { int bend= ((arg2 << 7) + arg1) - (64 << 7); bend /= 32; /* default sensitivity = +/- 2 semitones */ snd_seq_ev_set_pitchbend(ev, ch, bend); } break; } } static void processMIDIByte(snd_seq_event_t *ev, int aByte) { if (aByte > 247) return; /* skip all real-time messages */ switch (state) { case idle: if (aByte >= 128) /* start a new command using the action table */ startMIDICommand(ev, aByte); else /* data byte arrived in idle state: use running status if possible */ { if (lastCmdByte == 0) /* last command byte is not defined; just skip this byte */ return; else { /* process this data as if it had the last command byte in front of it */ startMIDICommand(ev, lastCmdByte); /* the previous line put us into a new state; we now do a recursive call to process the data byte in this new state */ processMIDIByte(ev, aByte); return; } } break; case want1of2: argByte1= aByte; state= want2of2; break; case want2of2: argByte2= aByte; performMIDICmd(ev, lastCmdByte, argByte1, argByte2); state= idle; break; case want1of1: argByte1= aByte; performMIDICmd(ev, lastCmdByte, argByte1, 0); state= idle; break; case sysExclusive: if (aByte < 128) { /* skip a system exclusive data byte */ } else { if (aByte < 248) { /* a system exclusive message can be terminated by any non-real-time command byte */ state= idle; if (aByte != 247) { processMIDIByte(ev, aByte); /* if not endSysExclusive, byte is the start the next command */ } } } break; } } static void startMIDICommand(snd_seq_event_t *ev, int cmdByte) { int argCount= argumentBytes[cmdByte - 128]; switch (argCount) { case 0: /* start a zero argument command (e.g., a real-time message) */ /* Stay in the current state and don't change active status. Real-time messages may arrive between data bytes without disruption. */ performMIDICmd(ev, cmdByte, 0, 0); break; case 1: /* start a one argument command */ lastCmdByte= cmdByte; state= want1of1; break; case 2: /* start a two argument command */ lastCmdByte= cmdByte; state= want1of2; break; case 3: /* start a variable length 'system exclusive' command */ /* a system exclusive command clears running status */ lastCmdByte= 0; state= sysExclusive; break; } } ================================================ FILE: vm/src/from_squeak/unix/plugins/MIDIPlugin/sqUnixMIDINone.inc ================================================ /* sqUnixMIDINone.c -- Unix with no MIDI support * * Copyright (C) 1996-2007 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Author: Ian.Piumarta@INRIA.FR * * Last edited: 2007-03-11 13:30:32 by piumarta on emilia.local */ /* Put the given port into MIDI mode, which uses a clock supplied by an external MIDI interface adaptor to determine the data rate. Possible external clock rates: 31.25 KHz, 0.5 MHz, 1 MHz, or 2 MHz. */ int serialPortMidiClockRate(int portNum, int interfaceClockRate) { success(false); return 0; } /* Close the given MIDI port. Do nothing if the port is not open. Fail if there is no port of the given number.*/ int sqMIDIClosePort(int portNum) { success(false); return 0; } /* Return the current value of the clock used to schedule MIDI events. The MIDI clock is assumed to wrap at or before half the maximum positive SmallInteger value. This allows events to be scheduled into the future without overflowing into LargePositiveIntegers. This implementation does not support event scheduling, so it just returns the value of the Squeak millisecond clock. */ int sqMIDIGetClock(void) { success(false); return 0; } /* Return the number of available MIDI interfaces, including both hardware ports and software entities that act like ports. Ports are numbered from 0 to N-1, where N is the number returned by this primitive. */ int sqMIDIGetPortCount(void) { success(false); return 0; } /* Return an integer indicating the directionality of the given port where: 1 = input, 2 = output, 3 = bidirectional. Fail if there is no port of the given number. */ int sqMIDIGetPortDirectionality(int portNum) { success(false); return 0; } /* Copy the name of the given MIDI port into the string at the given address. Copy at most length characters, and return the number of characters copied. Fail if there is no port of the given number.*/ int sqMIDIGetPortName(int portNum, int namePtr, int length) { success(false); return 0; } /* Open the given port, if possible. If non-zero, readSemaphoreIndex specifies the index in the external objects array of a semaphore to be signalled when incoming MIDI data is available. Note that not all implementations support read semaphores (this one does not); see sqMIDICanUseSemaphore. The interfaceClockRate parameter specifies the clock speed for an external MIDI interface adaptor on platforms that use such adaptors (e.g., Macintosh). Fail if there is no port of the given number.*/ int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate) { success(false); return 0; } /* Read or write the given MIDI driver parameter. If modify is 0, then newValue is ignored and the current value of the specified parameter is returned. If modify is non-zero, then the specified parameter is set to newValue. Note that many MIDI driver parameters are read-only; attempting to set one of these parameters fails. For boolean parameters, true = 1, false = 0. */ int sqMIDIParameter(int whichParameter, int modify, int newValue) { success(false); return 0; } /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Copy up to (length - 4) bytes of incoming MIDI data into that buffer, preceded by a 4-byte timestamp in the units of the MIDI clock, most significant byte first. Implementations that do not support timestamping of incoming data as it arrives (see sqMIDIHasInputClock) simply set the timestamp to the value of the MIDI clock when this function is called. Return the total number of bytes read, including the timestamp bytes. Return zero if no data is available. Fail if the buffer is shorter than five bytes, since there must be enough room for the timestamp plus at least one data byte. */ int sqMIDIPortReadInto(int portNum, int count, int bufferPtr) { success(false); return 0; } /* bufferPtr is the address of the first byte of a Smalltalk ByteArray of the given length. Send its contents to the given port when the MIDI clock reaches the given time. If time equals zero, then send the data immediately. Implementations that do not support a timestamped output queue, such as this one, always send the data immediately; see sqMIDIHasBuffer. */ int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time) { success(false); return 0; } int midiInit(void) { success(false); return 0; } int sqMIDIParameterGet(int which) { success(false); return 0; } int sqMIDIParameterSet(int which, int value) { success(false); return 0; } int midiShutdown(void) { success(false); return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/Mpeg3Plugin/Makefile.in ================================================ # Makefile.in for Mpeg3Plugin on Unix # # Author: ian.piumarta@inria.fr # # Last edited: 2002-07-10 23:52:17 by piumarta on emilia.inria.fr [make_cfg] [make_plg] TARGET = Mpeg3Plugin$a PLUGIN = Mpeg3Plugin$o VIDEO = getpicture$o headers$o idct$o macroblocks$o mmxtest$o motion$o \ mpeg3video$o output$o reconstruct$o seek$o slice$o vlc$o AUDIO = dct$o header$o layer1$o layer2$o layer3$o mpeg3audio$o pcm$o \ synthesizers$o tables$o LIBMPEG = bitstream$o changesForSqueak$o libmpeg3$o mpeg3atrack$o \ mpeg3demux$o mpeg3io$o mpeg3title$o mpeg3vtrack$o OBJS = $(PLUGIN) $(VIDEO) $(AUDIO) $(LIBMPEG) XINCLUDES = [includes] XDEFS = [xdefs] $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) $(RANLIB) $(TARGET) [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/plugins/Mpeg3Plugin/acinclude.m4 ================================================ # Add `--enable-mpg-[mmx,pthreads]' switches AC_ARG_ENABLE(mpg-mmx, [ --enable-mpg-mmx enable MMX support in Mpeg3Plugin [default=no]], XDEFS="-DUSE_MMX", XDEFS="") AC_ARG_ENABLE(mpg-pthreads, [ --enable-mpg-pthreads enable pthread support in Mpeg3Plugin [default=no]], , XDEFS="$XDEFS -DNOPTHREADS") # Define `[xdefs]' in Makefile.in AC_PLUGIN_DEFINE_UNQUOTED([xdefs], $XDEFS) ================================================ FILE: vm/src/from_squeak/unix/plugins/Mpeg3Plugin/config.cmake ================================================ IF (VM_HOST_CPU MATCHES "i[3456789]86") PLUGIN_DEFINITIONS (-DUSE_MMX=1) ENDIF () PLUGIN_DEFINITIONS (-DNOPTHREADS=1) SET (lmp3 "${cross}/plugins/Mpeg3Plugin/libmpeg") LIST(APPEND ${plugin}_extra_sources ${lmp3}/bitstream.c ${lmp3}/libmpeg3.c ${lmp3}/mpeg3atrack.c ${lmp3}/mpeg3demux.c ${lmp3}/mpeg3io.c ${lmp3}/mpeg3title.c ${lmp3}/mpeg3vtrack.c ${lmp3}/changesForSqueak.c ${lmp3}/audio/dct.c ${lmp3}/audio/header.c ${lmp3}/audio/layer2.c ${lmp3}/audio/layer3.c ${lmp3}/audio/mpeg3audio.c ${lmp3}/audio/pcm.c ${lmp3}/audio/synthesizers.c ${lmp3}/audio/tables.c ${lmp3}/video/getpicture.c ${lmp3}/video/headers.c ${lmp3}/video/idct.c ${lmp3}/video/macroblocks.c ${lmp3}/video/mmxtest.c ${lmp3}/video/motion.c ${lmp3}/video/mpeg3video.c ${lmp3}/video/output.c ${lmp3}/video/reconstruct.c ${lmp3}/video/seek.c ${lmp3}/video/slice.c ${lmp3}/video/vlc.c ) PLUGIN_INCLUDE_DIRECTORIES (${lmp3} ${lmp3}/audio ${lmp3}/video) ================================================ FILE: vm/src/from_squeak/unix/plugins/Mpeg3Plugin/mkmf.subdirs ================================================ platforms/Cross/plugins/Mpeg3Plugin/libmpeg platforms/Cross/plugins/Mpeg3Plugin/libmpeg/audio platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video ================================================ FILE: vm/src/from_squeak/unix/plugins/OggPlugin/Makefile.inc ================================================ PLIBS = -logg -lvorbis -lvorbisenc -lspeex ================================================ FILE: vm/src/from_squeak/unix/plugins/OggPlugin/acinclude.m4 ================================================ # -*- sh -*- AC_MSG_CHECKING([for Ogg Vorbis and Speex support]) AC_TRY_COMPILE([ #include #include #include ],[;],[ AC_CHECK_LIB(ogg, ogg_sync_buffer, AC_CHECK_LIB(vorbis, vorbis_synthesis_headerin, AC_CHECK_LIB(speex, speex_packet_to_header, AC_MSG_RESULT(yes), AC_MSG_RESULT(no) AC_PLUGIN_DISABLE), AC_MSG_RESULT(no) AC_PLUGIN_DISABLE), AC_MSG_RESULT(no) AC_PLUGIN_DISABLE) ],[ AC_MSG_RESULT(no) AC_PLUGIN_DISABLE ]) ================================================ FILE: vm/src/from_squeak/unix/plugins/OggPlugin/config.cmake ================================================ PLUGIN_REQUIRE_INCLUDE (VORBIS_CODEC vorbis/codec.h) PLUGIN_REQUIRE_INCLUDE (VORBIS_VORBISENC vorbis/vorbisenc.h) PLUGIN_REQUIRE_INCLUDE (SPEEX_SPEEX speex/speex.h) PLUGIN_REQUIRE_LIBRARY (OGG ogg) PLUGIN_REQUIRE_LIBRARY (VORBIS vorbis) PLUGIN_REQUIRE_LIBRARY (SPEEX speex) IF (APPLE) PLUGIN_DISABLE () # ogg framework headers are broken on 10.5.7 ENDIF () ================================================ FILE: vm/src/from_squeak/unix/plugins/PrintJobPlugin/sqPrinting.c ================================================ #include "PrintJobPlugin.h" #include /* none of these setup, cleanup, preprocess, postprocess, *etc. commands make any sense on Unix. Well, I suppose such a *thing could* be implemented, but it would all have to be done by *hand */ int ioPrintSetup(PrintingLogicPtr *printJob) { *printJob= (PrintingLogicPtr) 1234; /* I would like to put NULL here, but NULL is considered an error.... */ return 0; } int ioPrintPreProcessing(PrintingLogicPtr printJob,int numberOfPages) { return 0; } int ioPrintPostProcessing(PrintingLogicPtr printJob) { return 0; } int ioPrintCleanup(PrintingLogicPtr *printJob) { return 0; } int ioInitPrintJob(void) { return 1; /* it would be nice to have a standard on which functions return 0 for success and which functions return non-zero... */ } int ioShutdownPrintJob(void) { return 1; } int ioPagePreProcessing(PrintingLogicPtr printJob) { return 0; } int ioPagePostProcessing(PrintingLogicPtr printJob) { return 0; } /* ioGetFirstPageNumber and ioGetLastPageNumber -- Since the above operations aren't actually performed, there are no page numbers, or any other info, to be returned from the plugin. These functions just return page 1. */ int ioPrintGetFirstPageNumber(PrintingLogicPtr printJob) { return 1; } int ioPrintGetLastPageNumber(PrintingLogicPtr printJob) { return 1; } /* ioPrint -- theoretically this should be where the printing happens, but that means recording each portion of the print job. It should be fixed up at some point to do so; users should be able, for example, to cancel a print job. Then again, for the common application of printing out the current desktop, it doesn't matter */ int ioPrint(PrintingLogicPtr printJob) { return 0; } /* ioPagePostscript -- print out a posstcript file. This just popen's lpr */ /* XXX the exact print command should probably be configurable */ int ioPagePostscript(PrintingLogicPtr printJob,char *postscript,int postscriptLength) { FILE *lprOutput; size_t written; lprOutput=popen("lpr", "w"); if(lprOutput == NULL) { perror("lpr"); return 1; } written = fwrite(postscript, postscriptLength, 1, lprOutput); if(written < 1) { perror("fwrite"); pclose(lprOutput); return 1; } pclose(lprOutput); return 0; } /* ioPageForm -- print out a form */ int ioPageForm(PrintingLogicPtr printJob, char *aBitMap,int h,int w,int d,float sh,float sw,int oh,int ow) { /* just call the original primitive for form-printing */ return ioFormPrint((int)aBitMap, w, h, d, sw, sh, 1); } ================================================ FILE: vm/src/from_squeak/unix/plugins/PrintJobPlugin/sqPrinting.h ================================================ /* sqPrinting.h for Unix */ typedef int PrintingLogic; typedef PrintingLogic *PrintingLogicPtr; int ioPrintSetup(PrintingLogicPtr *printJob); int ioPrintPreProcessing(PrintingLogicPtr printJob,int numberOfPages); int ioPrint(PrintingLogicPtr printJob); int ioPrintPostProcessing(PrintingLogicPtr printJob); int ioPrintCleanup(PrintingLogicPtr *printJob); int ioInitPrintJob(void); int ioShutdownPrintJob(void); int ioPagePreProcessing(PrintingLogicPtr printJob); int ioPagePostProcessing(PrintingLogicPtr printJob); int ioPagePostscript(PrintingLogicPtr printJob,char *postscript,int postscriptLength); int ioPageForm(PrintingLogicPtr printJob, char *aBitMap,int h,int w,int d,float sh,float sw,int oh,int ow); int ioPrintGetFirstPageNumber(PrintingLogicPtr printJob); int ioPrintGetLastPageNumber(PrintingLogicPtr printJob); ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/PseudoTTY.st ================================================ 'From Squeak3.2gamma of 15 January 2002 [latest update: #4881] on 11 July 2002 at 6:06:32 am'! AsyncFile subclass: #PseudoTTY instanceVariableNames: 'inputBuffer outputBuffer ioError ' classVariableNames: 'AsyncFileError ' poolDictionaries: '' category: 'Communications-Endpoints'! !PseudoTTY commentStamp: '' prior: 0! I am a very particular kind of AsyncFile connected to the `master' half of a pseudo TTY (pty). My purpose in life is to provide communication with a process (in the fork+exec sense) that is connected to the `slave' half of the pty. (Writing to a master pty causes the data to appear on the slave's stdin, and anything written to the slave's stdout/stderr is available for subsequent reading on the master pty.) You create me by sending my class command: programNameString arguments: arrayOfArgumentStrings which will spawn a new process running the named program with the given arguments. You can subsequently send me #nextPut: (or #nextPutAll:) to send stuff to the stdin of the program, and #upToEnd to retrieve data that the program writes to its stdout or stderr. You can also send me #close which will shut down the program (by sending it SIGTERM followed shortly thereafter by SIGKILL if it's being stubborn) and both halves of the pseudo tty. The spawned program runs in a new session, will be its own session and process group leader and will have the slave half of the pty as its controlling terminal. (In plain English this means that the program will behave exactly as if it were being run from login, in particular: shells will enable job control, screen-oriented programs like Emacs will work properly, the user's login tmode settings will be inherited, intr/quit/etc. characters will be cooked into the corresponding signals, and window geometry changes will be propagated to the program. Neat, huh? ;-) Note that you need both the AsynchFile and PseudoTTY plugins in order for any of this to work. Note also that I am really intended to be used by a ProcessEndpoint as part of a ProtocolStack (along with a terminal emulator and a TeletypeMorph to provide interaction with the subprocess). ! !PseudoTTY methodsFor: 'initialize-release' stamp: 'ikp 7/10/2002 21:58'! close "Close the master half of the pty. The subprocess should exit (EOF on stdin) although badly written programs might start looping." fileHandle isNil ifTrue: [^self]. self primClosePts: fileHandle. fileHandle _ nil. Smalltalk unregisterExternalObject: semaphore. ioError _ AsyncFileError. semaphore signal. "wake up waiters" semaphore _ nil! ! !PseudoTTY methodsFor: 'initialize-release' stamp: 'ikp 7/11/2002 02:47'! command: programName arguments: argumentArray "Create a pseudo tty and then spawn programName with its stdin, out and err connected to the slave end of the pty." | semaIndex | "AsyncFile" name _ programName. writeable _ true. semaphore _ Semaphore new. semaIndex _ Smalltalk registerExternalObject: semaphore. "PseudoTTY" inputBuffer _ ByteArray new: 8192. outputBuffer _ ByteArray new: 1. ioError _ 0. fileHandle _ self forkAndExecWithPts: programName arguments: (argumentArray isNil ifTrue: [#()] ifFalse: [argumentArray]) semaIndex: semaIndex. fileHandle isNil ifTrue: [ Smalltalk unregisterExternalObject: semaphore. semaphore _ nil. ioError _ AsyncFileError. ^nil]. Processor yield. semaphore signal. ^self! ! !PseudoTTY methodsFor: 'accessing' stamp: 'ikp 7/11/2002 01:36'! name "Answer the name of the program." ^name! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 02:56'! ioError "Return the last error code received during read/write. If this is ever non-zero it means the subprocess has probably died." ^ioError! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 06:22'! isConnected ^fileHandle notNil and: [ioError == 0]! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 06:16'! nextPut: aCharacterOrInteger "Send a single character to the stdin of my subprocess." fileHandle isNil ifTrue: [^self]. outputBuffer at: 1 put: aCharacterOrInteger asInteger. self primWriteStart: fileHandle fPosition: -1 fromBuffer: outputBuffer at: 1 count: 1! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 06:16'! nextPutAll: aStringOrByteArray "Send an entire string to the stdin of my subprocess." fileHandle isNil ifTrue: [^self]. self primWriteStart: fileHandle fPosition: -1 fromBuffer: aStringOrByteArray at: 1 count: aStringOrByteArray size! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 13:28'! noteWindowSize: aPoint self primWindowSize: fileHandle cols: aPoint x rows: aPoint y! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/9/2002 06:15'! peekUpToEnd "Answer everything the subprocess has written to stdout or stderr since the last send of #upToEnd. Note that stuff written to stderr might arrive earlier than stuff written to stdout if the former is unbuffered and the latter line buffered in the subprocess's stdio library." | n | self isConnected ifFalse: [^nil]. n _ self primReadResult: fileHandle intoBuffer: inputBuffer at: 1 count: inputBuffer size. ^(self isConnected and: [n > 0]) ifTrue: [inputBuffer copyFrom: 1 to: n] ifFalse: [nil]! ! !PseudoTTY methodsFor: 'input/output' stamp: 'ikp 7/7/2002 21:28'! upToEnd "Answer everything the subprocess has written to stdout or stderr since the last send of #upToEnd. Note that stuff written to stderr might arrive earlier than stuff written to stdout if the former is unbuffered and the latter line buffered in the subprocess's stdio library." | n | [self isConnected and: [(n _ self startRead: inputBuffer size; primReadResult: fileHandle intoBuffer: inputBuffer at: 1 count: inputBuffer size) == Busy]] whileTrue: [self waitForCompletion]. (self isConnected and: [n > 0]) ifTrue: [^inputBuffer copyFrom: 1 to: n] ifFalse: [ioError _ AsyncFileError. ^nil] "subprocess has died or closed stdout"! ! !PseudoTTY methodsFor: 'private' stamp: 'ikp 7/10/2002 22:57'! forkAndExecWithPts: aCommand arguments: argArray semaIndex: semaIndex "Run aCommand as an inferior process and connect its std{in,out,err} to the receiver through a pseudo tty." ^self primForkAndExec: aCommand arguments: argArray semaIndex: semaIndex! ! !PseudoTTY methodsFor: 'private' stamp: 'ikp 7/7/2002 03:07'! startRead: count "Indicate interest in receiving more data from stdout/stderr of the subprocess." self primReadStart: fileHandle fPosition: -1 count: count! ! !PseudoTTY methodsFor: 'primitives' stamp: 'ikp 7/7/2002 05:11'! primClosePts: fHandle "Kill the process whose pts is associated with our pty." ^nil! ! !PseudoTTY methodsFor: 'primitives' stamp: 'ikp 7/10/2002 21:48'! primForkAndExec: command arguments: arguments semaIndex: semaIndex "Fork and exec command with the given arguments connecting the new process to a slave tty created from the receiver (which is the master half of a pseudo tty)." ^nil! ! !PseudoTTY methodsFor: 'primitives' stamp: 'ikp 7/7/2002 06:41'! primWindowSize: fHandle cols: cols rows: rows "Set the size of the terminal connected to the pty." ^nil! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PseudoTTY class instanceVariableNames: ''! !PseudoTTY class methodsFor: 'class initialization' stamp: 'ikp 7/7/2002 02:25'! initialize "Can't rely on Error because the compiler finds the global before the class var. Ho hum." "PseudoTTY initialize" AsyncFileError _ -2! ! !PseudoTTY class methodsFor: 'instance creation' stamp: 'ikp 7/7/2002 04:33'! command: commandString arguments: argumentArray "(PseudoTTY command: '/bin/bash' arguments: #('-c' 'pwd')) upToEnd asString" ^self new command: commandString arguments: argumentArray! ! !PseudoTTY class methodsFor: 'examples' stamp: 'ikp 7/10/2002 23:00'! example "Show the user's current tty mode settings." "PseudoTTY example" | pty output buf | pty _ self command: '/bin/stty' arguments: #('-a'). pty isNil ifTrue: [^self error: 'Could not create pty or process.']. output _ WriteStream on: String new. output nextPutAll: 'Your tty modes are: '; cr; space; cr. [(buf _ pty upToEnd) isNil] whileFalse: [output nextPutAll: buf asString]. pty close. self inform: output contents! ! PseudoTTY initialize! ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/PseudoTTYPlugin.st ================================================ 'From Squeak3.2gamma of 15 January 2002 [latest update: #4881] on 11 July 2002 at 12:42:23 am'! TestInterpreterPlugin subclass: #PseudoTTYPlugin instanceVariableNames: 'sCOAFfn ' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Plugins'! !PseudoTTYPlugin commentStamp: '' prior: 0! Author: Ian Piumarta Date: 2002-07-06 Version: 1.0 This plugin extends AsynchFilePlugin with support for Unix98-style pseudo ttys. Pseudo ttys (ptys) are a means for some program A (e.g., Squeak) to spawn a child process B and have B's std{in,out,err} connected to something that smells (to B) like a terminal (the `slave' tty) but which is in fact connected directly to A via another device (the `master' tty). One example of this would be Squeak spawning an interactive shell. If we were to use pipes (or sockets) to communicate with the shell's std{in,out,err} then various screen-oriented programs (such as Emacs) would refuse to run, the shell itself would refuse to implement job control and `cooked' characters (intr, quit, suspend, etc.) would be ignored -- all because pipes (and sockets) are absolutely not the same thing as a tty. Connecting the shell to a slave tty (and talking to it indirectly through our master tty) allows such programs (and shells and interrupts, etc.) to work properly, since they believe themselves to be connected to a `real' terminal. To use this plugin on any system that supports Unix98 pseudo ttys you would do something like this: - open an AsyncFile on /dev/ptmx (the Pseudo Tty master MultipleXor) which returns a handle on the master tty (and creates the slave tty device -- usually something like /dev/ttyN or /dev/pts/N); - prepare the slave tty for use by an inferior process by calling primGrantPt and primUnlockPt on the master; - call primPtsName on the master to obtain the name of the allocated slave tty device; - open the slave tty for read (stdin), write (stdout) and again for write (stderr); - fork; - connect the inferior process's std{in,out,err} to the slave tty device through the three descriptors just opened; - exec the shell (or whatever) in the inferior process. After all that the parent process can write (via the original AsyncFile) to the master tty (to provide data for the inferior process's stdin) and read (via the AsyncFile) from the master (to retrieve data written to std{out,err} by the inferior process). If the inferior process tests std{in,out,err} with isatty() it will be told that it is connected to a login terminal. This plugin provides four primitives, as implied by the above, all of which apply to AsyncFiles: primitivePtGrant - prepare the slave tty for use primitivePtUnlock - allow connections (open) to the slave tty primitivePtsNameLength - return the size of the slave tty's device name primitivePtsName - read the slave tty's device name into a String (designed to be easily useable in conjunction with OSProcess) and one more (just for my convenience) which does all of the above steps atomically (and also promotes the inferior process to a process group leader, and installs a handler to finalise the inferior process on exit and close its parent's master tty -- without the need to use OSProcess at all): primitiveForkAndExecWithPts - create an inferior process connected to a slave tty Note that `Unix98' does NOT imply that this will only work on Unix systems!! Unix98 is the name of a *standard* (describing one possible implementation of pseudo ttys) which can be adopted by any OS, be it Unix or something entirely different. (Unix98 ptys have been adopted by both BSD and Linux, which is why we consider it the most interesting standard to implement here. However, be warned that if [for some bizarre, masochistic reason] you have disabled Unix98 pty support in your BSD or Linux kernel then this plugin will explode in your face. [Although you should never get that far since the initial open of /dev/ptmx will fail.]) Finally note that this plugin might (should) go away in the future if (when) OSProcess implements the required support for pseudo ttys and asynchronous i/o on their master devices. Dave: are you reading this?! !PseudoTTYPlugin methodsFor: 'initialize-release' stamp: 'ikp 7/10/2002 22:41'! initialiseModule self export: true. "We have to load AsyncFile first, to get the sessionID." interpreterProxy ioLoadFunction: 'initializeModule' From: 'AsynchFilePlugin'. ^self cCode: 'ptyInit()' inSmalltalk: [true]! ! !PseudoTTYPlugin methodsFor: 'initialize-release' stamp: 'ikp 7/7/2002 02:29'! shutdownModule self export: true. ^self cCode: 'ptyShutdown()' inSmalltalk: [true]! ! !PseudoTTYPlugin methodsFor: 'primitives' stamp: 'ikp 7/7/2002 05:44'! primitivePtyClose: fHandle | f | self var: #f declareC: 'AsyncFile *f'. self primitive: 'primPtyClose' parameters: #(Oop). f _ self asyncFileValueOf: fHandle. interpreterProxy failed ifFalse: [self cCode: 'ptyClose(f)'].! ! !PseudoTTYPlugin methodsFor: 'primitives' stamp: 'ikp 7/10/2002 22:31'! primitivePtyForkAndExec: cmd arguments: args semaIndex: semaIndex | f cmdLen cmdIdx argLen argIdx fOop | self var: #f declareC: 'AsyncFile *f'. self primitive: 'primPtyForkAndExec' parameters: #(Oop Oop SmallInteger). interpreterProxy success: (interpreterProxy isBytes: cmd). interpreterProxy success: (interpreterProxy isPointers: args). interpreterProxy failed ifTrue: [^nil]. cmdIdx _ self cCoerce: (interpreterProxy firstIndexableField: cmd) to: 'int'. cmdLen _ interpreterProxy slotSizeOf: cmd. "in bytes" argIdx _ self cCoerce: (interpreterProxy firstIndexableField: args) to: 'int'. argLen _ interpreterProxy slotSizeOf: args. "in fields" fOop _ interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: (self cCode: 'sizeof(AsyncFile)'). f _ self asyncFileValueOf: fOop. interpreterProxy failed ifFalse: [self cCode: 'ptyForkAndExec(f, semaIndex, cmdIdx, cmdLen, argIdx, argLen)']. ^fOop! ! !PseudoTTYPlugin methodsFor: 'primitives' stamp: 'ikp 7/7/2002 06:38'! primitivePtyWindowSize: fHandle cols: cols rows: rows | f | self var: #f declareC: 'AsyncFile *f'. self primitive: 'primPtyWindowSize' parameters: #(Oop SmallInteger SmallInteger). f _ self asyncFileValueOf: fHandle. interpreterProxy failed ifFalse: [self cCode: 'ptyWindowSize(f, cols, rows)'].! ! !PseudoTTYPlugin methodsFor: 'private' stamp: 'ikp 7/6/2002 19:08'! asyncFileValueOf: oop "Return a pointer to the first byte of the async file record within the given Smalltalk bytes object, or nil if oop is not an async file record." self returnTypeC: 'AsyncFile *'. interpreterProxy success: ((interpreterProxy isIntegerObject: oop) not and: [(interpreterProxy isBytes: oop) and: [(interpreterProxy slotSizeOf: oop) = (self cCode: 'sizeof(AsyncFile)')]]). interpreterProxy failed ifTrue: [^ nil]. ^ self cCode: '(AsyncFile *) (oop + 4)' ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! PseudoTTYPlugin class instanceVariableNames: ''! !PseudoTTYPlugin class methodsFor: 'translation' stamp: 'ikp 7/6/2002 21:18'! hasHeaderFile ^true! ! !PseudoTTYPlugin class methodsFor: 'translation' stamp: 'ikp 7/6/2002 21:12'! requiresPlatformFiles ^true! ! ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/README ================================================ /* This directory contains the PseudoTTYPlugin, a means for Squeak to * fork an interactive program that believes itself to be running on a * login terminal when, in fact, Squeak is providing it with data for * its stdin and recovering the output it writes to its stdout/stderr. * * The Squeak plugin source code is in `PseudoTTYPlugin.st'. * The Squeak class needed to use the plugin is in `PseudoTTY.st'. * * The plugin has been built and tested on the following architecures: * * GNU/Linux (libc2.3) * NetBSD 1.5ZC * Solaris 2.8 * * The remainder of this file is a C program designed to ease the * process of porting this plugin to unsupported architectures. * * ---------------------------------------------------------------- * * This program forks a child process to run /bin/stty and then * collects and prints its output. If the child is not connected to a * login terminal then stty will complain (printing something like * "stdin: not a tty") and you have a problem somewhere in "opentty.h" * which you must FIND AND FIX before the plugin will work. OTOH, if * it prints a bunch (about ten lines) of tty mode information then * all is well and the plugin should work just fine. * * (Do I really need to mention that you have to rename this file to * "pty.c" or somesuch before trying to compile it? ;) */ /* For the plugin the HAVE_* macros are set in config.h by acinclude.m4. * In this test file you need to set them manually for your architecture. * If you invent new HAVE_* macros then you'll need to modify acinclude.m4 * and regenerate configure (run `make' in ../../config) before building * the VM. * * If it is available then we use openpty() in preference to Unix98 ptys: * * HAVE_OPENPTY -- defined if you have openpty() and login_tty() * HAVE_UTIL_H -- defined if you have /usr/include/util.h * HAVE_PTY_H -- defined if you have /usr/include/pty.h * * If you don't have openpty() then we fake it from /dev/ptmx: * * HAVE_UNIX98_PTY -- defined if you have /dev/ptmx and grantpt() et al. * HAVE_STROPTS_H -- defined if you have /usr/include/stropts.h * * We assume you have /usr/include/utmp.h; if you don't then you need to * buy a real computer before trying to compile this plugin. * * Suggested compile command is shown with each architecture. * If you have to add new libraries then you'll need to modify acinclude.m4 * and regenerate configure (run `make' in ../../config) before building the * VM. */ #if defined(__NetBSD__) /* cc -o pty pty.c -lutil */ # define HAVE_OPENPTY # define HAVE_UTIL_H #elif defined(__OpenBSD__) /* cc -o pty pty.c -lutil */ # define HAVE_OPENPTY # define HAVE_UTIL_H #elif defined(__linux__) /* cc -o pty pty.c -lutil */ # define HAVE_UNIX98_PTY # define HAVE_OPENPTY # define HAVE_PTY_H #elif defined(__sun__) /* cc -o pty pty.c */ # define HAVE_UNIX98_PTY # define HAVE_STROPTS_H #else # error: defines for your architecture go here #endif /* Absolutely everybody has these. */ #include #include #include #include #include #include #include /* This gets the obscure (interesting ;) stuff. */ #include "openpty.h" /* Here we go! ... */ static char *prog= "/bin/stty"; static char *argv[]= { "stty", "-a", 0 }; extern char **environ; static int ptm= -1, pts= -1; static void sigchld(int signum) { close(pts); /* force i/o error or EOF on ptm */ } int main() { char tty[32]; pid_t pid= 0; if (openpty(&ptm, &pts, tty, 0, 0) == -1) { perror("openpty"); exit(1); } printf("using %s (ptm %d pts %d)\n", tty, ptm, pts); signal(SIGCHLD, sigchld); pid= fork(); switch (pid) { case -1: perror("fork"); exit(1); break; case 0: /* child */ close(ptm); if (login_tty(pts) == -1) { perror("login_tty"); exit(1); } execve(prog, argv, environ); perror(argv[0]); exit(1); break; default: /* parent */ { char buf[128]; int n, status; printf("---------------- from child:\n"); while (((n= read(ptm, buf, sizeof(buf) - 1)) > 0) || ((n == -1) && (errno == EINTR))) if (n > 0) { buf[n]= '\0'; printf("%s", buf); } printf("----------------\n"); if (n < 0) perror("read"); else printf("EOF\n"); close(ptm); pid= wait(&status); printf("child exited with status %d\n", status); } break; } return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/acinclude.m4 ================================================ AC_HAVE_HEADERS(util.h libutil.h pty.h stropts.h) AC_SEARCH_LIBS(openpty, util, AC_DEFINE(HAVE_OPENPTY, 1),[ if test -r /dev/ptmx; then AC_CHECK_FUNC(grantpt, AC_DEFINE(HAVE_UNIX98_PTYS, 1)) fi]) ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/config.cmake ================================================ PLUGIN_FIND_INCLUDE (UTIL util.h) PLUGIN_FIND_INCLUDE (LIBUTIL libutil.h) PLUGIN_FIND_LIBRARY (UTIL util) PLUGIN_FIND_INCLUDE (PTY pty.h) PLUGIN_FIND_INCLUDE (STROPTS stropts.h) CHECK_FUNCTION_EXISTS (openpty OPENPTY) IF (OPENPTY) SET (HAVE_OPENPTY 1) ENDIF () IF (NOT HAVE_OPENPTY AND HAVE_LIBUTIL) CHECK_LIBRARY_EXISTS (util openpty "" UTIL_OPENPTY) IF (UTIL_OPENPTY) PLUGIN_LINK_LIBRARIES (util) SET (HAVE_OPENPTY 1) ENDIF () ENDIF () IF (NOT HAVE_OPENPTY AND EXISTS /dev/ptmx) CHECK_FUNCTION_EXISTS (grantpt HAVE_UNIX98_PTYS) IF (NOT HAVE_UNIX98_PTYS) PLUGIN_DISABLE () ENDIF (NOT HAVE_UNIX98_PTYS) ENDIF (NOT HAVE_OPENPTY AND EXISTS /dev/ptmx) PLUGIN_INCLUDE_DIRECTORIES (${unix}/plugins/AsynchFilePlugin) CONFIG_DEFINE (HAVE_UTIL_H) CONFIG_DEFINE (HAVE_LIBUTIL_H) CONFIG_DEFINE (HAVE_PTY_H) CONFIG_DEFINE (HAVE_STROPTS_H) CONFIG_DEFINE (HAVE_OPENPTY) CONFIG_DEFINE (HAVE_UNIX98_PTYS) ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/openpty.h ================================================ /* openpty.h -- provides openpty() and login_tty() * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Author: Ian.Piumarta@inria.fr */ #if defined(HAVE_OPENPTY) # include /* login_tty() */ # if defined(HAVE_PTY_H) # include /* openpty() */ # elif defined(HAVE_UTIL_H) # include /* openpty() */ # elif defined(HAVE_LIBUTIL_H) # include /* openpty() on FreeBSD */ # else # error: cannot find headers for openpty() # endif #else /* !HAVE_OPENPTY */ # if defined(HAVE_UNIX98_PTYS) /* we'll just roll our own, it ain't hard */ # include /* ptsname(), grantpt(), unlockpt() */ # include # include # include # if defined(HAVE_STROPTS_H) # include # include # endif static int openpty(int *ptmp, int *ptsp, char *ttyp, void *termiosp, void *winp) { int ptm= -1, pts= -1; char *tty= 0; if ((ptm= open("/dev/ptmx", O_RDWR, 0)) == -1) return -1; tty= ptsname(ptm); if (grantpt(ptm) == -1) return -1; if (unlockpt(ptm) == -1) return -1; if ((pts= open(tty, O_RDWR, 0)) == -1) return -1; *ptmp= ptm; *ptsp= pts; strcpy(ttyp, tty); return 0; } static int login_tty(int pts) { #if defined(HAVE_STROPTS_H) /* push a terminal onto stream head */ if (ioctl(pts, I_PUSH, "ptem") == -1) return -1; if (ioctl(pts, I_PUSH, "ldterm") == -1) return -1; #endif setsid(); #if defined(TIOCSCTTY) ioctl(pts, TIOCSCTTY, 0); #endif dup2(pts, 0); dup2(pts, 1); dup2(pts, 2); if (pts > 2) close(pts); return 0; } # else /* !HAVE_UNIX98_PTYS */ # error: cannot open a pty -- this plugin will not work # endif #endif /* !HAVE_OPENPTY */ ================================================ FILE: vm/src/from_squeak/unix/plugins/PseudoTTYPlugin/sqUnixPseudoTTYPlugin.c ================================================ /* PseudoTTYPlugin.c -- support for Unix98-style pseudo ttys -*- C -*- * * Author: Ian Piumarta * Version: 1.1 * Last edited: 2003-09-03 18:06:13 by piumarta on emilia.inria.fr * * This plugin extends AsynchFilePlugin with support for Unix98-style * pseudo ttys. See the PseudoTTY and PseudoTTYPlugin class comments * for details. * * Note that `Unix98' does NOT imply that this will only work on Unix * systems! Unix98 is the name of a *standard* describing (amonst * many other things) one possible implementation of pseudo ttys that * could be adopted by any OS, be it Unix or something entirely * different. (Unix98 ptys have been adopted by both BSD and Linux, * which is why we consider it the most interesting standard to * implement here. However, be warned that if [for some bizarre, * masochistic reason] you have disabled Unix98 pty support in your * BSD or Linux kernel then this plugin will explode in your face. * [Although you should never get that far since the initial open of * /dev/ptmx will fail.]) * * Finally note that this plugin might (should) go away in the future * if (when) OSProcess implements the required support for pseudo ttys * and asynchronous i/o on their master devices. (Dave: are you * reading this?) * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "sq.h" #include "PseudoTTYPlugin.h" /* Ian says: never EVER #include things in the Unix Squeak sources using relative paths. Never. Ever. Period. Write a Makefile.inc with the right XCPPFLAGS instead. Having said that... */ #include "../AsynchFilePlugin/sqUnixAsynchFile.h" #include #include #include #include #include #include #include "openpty.h" /* hide the gory details ;) */ #if 0 # define DPRINTF(ARGS) printf ARGS #else # define DPRINTF(ARGS) #endif typedef struct Slave { pid_t pid; /* process */ int status; /* exit status */ int pts; /* pts (child pty) */ FilePtr pty; /* ptm (parent pty) */ struct Slave *next; /* list */ } SlaveRec, *SlavePtr; static SlavePtr slaves= 0; typedef void (*sighandler_t)(int); static sighandler_t prevchld= 0; static int reaping= 0; #define isValid(f) (f->sessionID == sqUnixAsyncFileSessionID) #define validate(f) if ((!isValid(f)) || (!(f->state))) return vm->primitiveFail() /*** initialise-release ***/ #include "sqVirtualMachine.h" static struct VirtualMachine *vm= 0; static void sigchld(int signum) { int status= 0; SlavePtr zombie= 0; pid_t pid= wait(&status); if (!slaves) fprintf(stderr, "unexpected SIGCHLD for pid %d\n", pid); else for (zombie= slaves; zombie; zombie= zombie->next) if (zombie->pid == pid) break; if (!zombie) fprintf(stderr, "failed to clean up for pid %d\n", pid); else { /* force any image server loop to exit */ /* close(zombie->pty->fd); */ zombie->pty->rd.status= -2; signalSemaphoreWithIndex(zombie->pty->sema); DPRINTF(("closed pty for pid %d\n", pid)); } } int ptyInit(void) { DPRINTF(("ptyInit: AsyncFileSession is %d\n", sqUnixAsyncFileSessionID)); vm= sqGetInterpreterProxy(); slaves= 0; prevchld= signal(SIGCHLD, sigchld); if ((prevchld != SIG_DFL) && (prevchld != SIG_IGN)) { fprintf(stderr, "declining responsibility for child processes!\n"); signal(SIGCHLD, prevchld); reaping= 0; } else reaping= 1; return 1; } int ptyShutdown(void) { if (reaping) { SlavePtr slave= 0; for (slave= slaves; slave; slave= slave->next) kill(slave->pid, SIGTERM); usleep(200*1000); for (slave= slaves; slave; slave= slave->next) kill(slave->pid, SIGKILL); usleep(200*1000); signal(SIGCHLD, prevchld); while (slaves) { slave= slaves->next; fprintf(stderr, "child process %d refused to die\n", slaves->pid); free(slaves); slaves= slave; } } slaves= 0; return 1; } /*** primitives ***/ #include #include int ptyForkAndExec(AsyncFile *f, int semaIndex, int cmdIndex, int cmdLen, int argIndex, int argLen) { int ptm= -1, pts= -1; char tty[32]; FilePtr fp= 0; DPRINTF(("ptyForkAndExec\n")); /* Module init must succeed in loading the AsyncFile plugin */ if (sqUnixAsyncFileSessionID == 0) { vm->primitiveFail(); return 0; } DPRINTF(("AsyncFileSession is %d\n", sqUnixAsyncFileSessionID)); if (openpty(&ptm, &pts, tty, 0, 0) == -1) { perror("pty: openpty"); goto failDetached; } DPRINTF(("pty: using %s (ptm %d pts %d)\n", tty, ptm, pts)); if ((fp= asyncFileAttach(f, ptm, semaIndex)) == 0) goto failDetached; /* fork the child on the new pts (from now on we must detach on fail) */ { extern char **environ; char *cmd= (char *)alloca(cmdLen + 1); char **argv= (char **)alloca(sizeof(char *) * (argLen + 2)); int i= 0; SlavePtr slave= 0; memcpy((void *)cmd, (void *)cmdIndex, cmdLen); cmd[cmdLen]= '\0'; DPRINTF(("pty: command: %s\n", cmd)); argv[0]= cmd; for (i= 1; i <= argLen; ++i) { int argOop= ((int *)argIndex)[i - 1]; char *arg= 0; int len= 0; if (!vm->isBytes(argOop)) goto fail; len= vm->stSizeOf(argOop); DPRINTF(("pty: arg %d len %d\n", i, len)); arg= (char *)alloca(len + 1); memcpy((void *)arg, (void *)vm->firstIndexableField(argOop), len); arg[len]= '\0'; argv[i]= arg; DPRINTF(("pty: argv[%d]: %s\n", i, argv[i])); } argv[argLen+1]= 0; /* argv terminator */ /* put slave on list in case of immediate exit in child */ slave= (SlavePtr)malloc(sizeof(SlaveRec)); slave->next= slaves; slaves= slave; slave->pts= pts; slave->pty= fp; slave->pid= fork(); switch (slave->pid) { case -1: /* error */ slaves= slaves->next; free(slave); perror("pty: fork"); goto fail; break; case 0: /* child */ close(ptm); login_tty(pts); execve(cmd, argv, environ); fprintf(stderr, "pty: "); perror(cmd); exit(1); break; default: /* parent */ close(pts); break; } return 0; } fail: asyncFileClose(f); ptm= -1; failDetached: if (ptm >= 0) close(ptm); if (pts >= 0) close(pts); vm->primitiveFail(); return 0; } int ptyClose(AsyncFile *f) { SlavePtr slave= 0, prev= 0; FilePtr pty= (FilePtr)f->state; validate(f); DPRINTF(("pty: close %d\n", pty->fd)); if (pty->fd >= 0) { for (prev= 0, slave= slaves; slave; prev= slave, slave= slave->next) if (slave->pty == pty) { int pid= slave->pid; DPRINTF(("killing pid %d connected to pts %d\n", pid, slave->pts)); /* terminate with increasing degrees of violence... */ kill(pid, SIGTERM); usleep(200*1000); kill(pid, SIGKILL); /* delete from list */ if (prev) prev->next= slave->next; else slaves= slave->next; break; } if (slave) free(slave); else fprintf(stderr, "pty %d not in active process list\n", pty->fd); } asyncFileClose(f); return 0; } ptyWindowSize(AsyncFile *f, int cols, int rows) { #if defined(TIOCSWINSZ) struct winsize sz; FilePtr pty= (FilePtr)f->state; validate(f); DPRINTF(("pty %d size %d %d\n", pty->fd, cols, rows)); sz.ws_col= cols; sz.ws_row= rows; sz.ws_xpixel= sz.ws_ypixel= 0; if (ioctl(pty->fd, TIOCSWINSZ, &sz) == -1) perror("pty: TIOCSWINSZ"); #endif return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/RomePlugin/Makefile.inc ================================================ SURFACE_CFLAGS=-I$(topdir)/platforms/Cross/plugins/SurfacePlugin XCPPFLAGS= [FREETYPE_CFLAGS] [PANGOCAIRO_CFLAGS] $(SURFACE_CFLAGS) XLDFLAGS= [FREETYPE_LIBS] [PANGOCAIRO_LIBS] ================================================ FILE: vm/src/from_squeak/unix/plugins/RomePlugin/acinclude.m4 ================================================ SAVED_CFLAGS="$CFLAGS" PKG_CHECK_MODULES(PANGOCAIRO,pangocairo, PKG_CHECK_MODULES(FREETYPE,freetype2, AC_MSG_CHECKING([for FreeType support in Cairo]) CFLAGS="$CFLAGS $FREETYPE_CFLAGS $PANGOCAIRO_CFLAGS" AC_TRY_COMPILE([ #include ],[;],[ AC_MSG_RESULT(yes) AC_PLUGIN_DEFINE_UNQUOTED(FREETYPE_CFLAGS,$FREETYPE_CFLAGS) AC_PLUGIN_DEFINE_UNQUOTED(FREETYPE_LIBS,$FREETYPE_LIBS) AC_PLUGIN_DEFINE_UNQUOTED(PANGOCAIRO_CFLAGS,$PANGOCAIRO_CFLAGS) AC_PLUGIN_DEFINE_UNQUOTED(PANGOCAIRO_LIBS,$PANGOCAIRO_LIBS) ],[ AC_MSG_RESULT(no) AC_PLUGIN_DISABLE ]) ,AC_PLUGIN_DISABLE) ,AC_PLUGIN_DISABLE) CFLAGS="$SAVED_CFLAGS" ================================================ FILE: vm/src/from_squeak/unix/plugins/RomePlugin/config.cmake ================================================ PLUGIN_REQUIRE_PACKAGE (PANGOCAIRO pangocairo) PLUGIN_REQUIRE_PACKAGE (FREETYPE freetype2) PLUGIN_REQUIRE_INCLUDE (CAIRO_FT cairo-ft.h) PLUGIN_INCLUDE_DIRECTORIES (${cross}/plugins/SurfacePlugin) ================================================ FILE: vm/src/from_squeak/unix/plugins/SecurityPlugin/sqUnixSecurity.c ================================================ /* sqUnixSecurity.c -- directory operations for Unix * * Author: Bert Freudenberg (heavily based on Andreas Raab's sqWin32Security.c) * * Last edited: 2005-03-19 20:47:40 by piumarta on squeak.hpl.hp.com * * Note: According to Ian Piumarta, the Unix VM is inherently insecure since * pluggable primitives can access all of libc! It would need * some linker magic to hide these from dlsym(). * * A workaround would be to disallow lookups via dlsym() when * fileaccess is disallowed - internal plugins should still work ... */ #include "sq.h" #include "SecurityPlugin.h" #include static char secureUserDirectory[MAXPATHLEN]; /* imagepath/secure/ */ static char untrustedUserDirectory[MAXPATHLEN]; /* imagepath/untrusted/ */ static int untrustedUserDirectoryLen; static char* fromSqueak(char* string, int len) { static char buf[MAXPATHLEN]; strncpy(buf, string, len); buf[len]= '\0'; return buf; } /* file security ***********************************************************/ static sqInt allowFileAccess= 1; /* full access to files */ static int isAccessiblePathName(char *pathName) { char realPathName[MAXPATHLEN]; int realPathLen; realpath(pathName, realPathName); realPathLen= strlen(realPathName); return (realPathLen >= untrustedUserDirectoryLen && 0 == strncmp(realPathName, untrustedUserDirectory, untrustedUserDirectoryLen)); } static int isAccessibleFileName(char *fileName) { char pathName[MAXPATHLEN]; int pathLen= strrchr(fileName, '/') - fileName; strncpy(pathName, fileName, pathLen); pathName[pathLen]= '\0'; return isAccessiblePathName(pathName); } /* directory access */ sqInt ioCanCreatePathOfSize(char* pathString, sqInt pathStringLength) { if (allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanListPathOfSize(char* pathString, sqInt pathStringLength) { if (allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanDeletePathOfSize(char* pathString, sqInt pathStringLength) { if (allowFileAccess) return 1; return isAccessiblePathName(fromSqueak(pathString, pathStringLength)); } /* file access */ sqInt ioCanOpenFileOfSizeWritable(char* pathString, sqInt pathStringLength, sqInt writeFlag) { if (allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanOpenAsyncFileOfSizeWritable(char* pathString, sqInt pathStringLength, sqInt writeFlag) { return ioCanOpenFileOfSizeWritable(pathString, pathStringLength, writeFlag); } sqInt ioCanDeleteFileOfSize(char* pathString, sqInt pathStringLength) { if (allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanRenameFileOfSize(char* pathString, sqInt pathStringLength) { if (allowFileAccess) return 1; return isAccessibleFileName(fromSqueak(pathString, pathStringLength)); } sqInt ioCanGetFileTypeOfSize(char* pathString, sqInt pathStringLength) { return 1; /* we don't have file types */ } sqInt ioCanSetFileTypeOfSize(char* pathString, sqInt pathStringLength) { return 1; /* we don't have file types */ } /* disabling/querying */ sqInt ioDisableFileAccess(void) { allowFileAccess= 0; return 1; } sqInt ioHasFileAccess(void) { return allowFileAccess; } /* image security **********************************************************/ static sqInt allowImageWrite= 1; /* allow writing the image */ sqInt ioCanRenameImage(void) { return allowImageWrite; /* only when we're allowed to save the image */ } sqInt ioCanWriteImage(void) { return allowImageWrite; } sqInt ioDisableImageWrite(void) { allowImageWrite= 0; return 1; } /* socket security - for now it's all or nothing ***************************/ static sqInt allowSocketAccess= 1; /* allow access to sockets */ sqInt ioCanCreateSocketOfType(sqInt netType, sqInt socketType) { return allowSocketAccess; } sqInt ioCanConnectToPort(sqInt netAddr, sqInt port) { return allowSocketAccess; } sqInt ioCanListenOnPort(sqInt s, sqInt port) { return allowSocketAccess; } sqInt ioDisableSocketAccess() { allowSocketAccess= 0; return 1; } sqInt ioHasSocketAccess() { return allowSocketAccess; } /* SecurityPlugin primitive support ****************************************/ char *ioGetSecureUserDirectory(void) { if (secureUserDirectory[0] == '\0') return (char *)success(false); return secureUserDirectory; } char *ioGetUntrustedUserDirectory(void) { return untrustedUserDirectory; } /* note: following is called from VM directly, not from plugin */ sqInt ioInitSecurity(void) { int imagePathLen= strrchr(imageName, '/') - imageName; char *squeakUserDirectory= 0; /* establish the secure user directory */ strncpy(secureUserDirectory, imageName, imagePathLen); strcpy(secureUserDirectory + imagePathLen, "/secure"); /* establish untrusted user directory */ squeakUserDirectory= getenv("SQUEAK_USERDIR"); if (0 == squeakUserDirectory) { strncpy(untrustedUserDirectory, imageName, imagePathLen); strcpy(untrustedUserDirectory + imagePathLen, "/My Squeak"); } else { int lastChar= strlen(squeakUserDirectory); /* path is not allowed to end with "/" */ if ('/' == squeakUserDirectory[lastChar - 1]) squeakUserDirectory[lastChar - 1]= '\0'; strcpy(untrustedUserDirectory, squeakUserDirectory); } untrustedUserDirectoryLen= strlen(untrustedUserDirectory); return 1; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SerialPlugin/sqUnixSerial.c ================================================ /* sqUnixSerial.c -- Unix serial support * * Author: Ned Konz, July 14, 2000 * * Last edited: 2002-10-26 14:36:11 by piumarta on emilia.inria.fr * * Separated from MIDI, plus various portability problems fixed, by: * Ian Piumarta */ #include "sq.h" #include "SerialPlugin.h" #include #include #include #include #include #include /*** Module variables ***/ /* portNum 0=/dev/ttyS0, etc. */ /* include 1 byte for NUL at end */ #define PORT_NAME_SIZE 11 static const char serialPortBaseName[] = "/dev/ttyS0"; /* stopBits 0=1.5, 1=1, 2=2 */ /* I don't know how to get 1.5 stop bits. Oh well. So you get 2 instead */ #define MAX_STOP_BITS 2 /* c_cflag definitions */ static const unsigned int stopBitsDecode[MAX_STOP_BITS+1] = { CSTOPB, 0, CSTOPB }; /* dataBits number of bits per character (5..8) */ /* note that since CS5 is 0, you will get 5 data bits if you ask for 0..4 * as well */ #define MAX_DATA_BITS 8 /* c_cflag definitions */ static const unsigned int dataBitsDecode[MAX_DATA_BITS+1] = { 0, 0, 0, 0, 0, CS5, CS6, CS7, CS8 }; /* parityType 0=no, 1=odd, 2=even */ #define MAX_PARITY_TYPE 2 /* c_cflag definitions */ static const unsigned int parityTypeDecode[MAX_PARITY_TYPE+1] = { 0, /* none */ PARENB|PARODD, /* odd */ PARENB /* even */ }; /* inFlowCtrl 0=none, 1=XOn/XOff, 2=hardware handshaking * outFlowCtrl 0=none, 1=XOn/XOff, 2=hardware handshaking */ #define MAX_FLOW_CTRL 2 /* must be <= 10, because of 1-digit filename generation */ #define MAX_SERIAL_PORTS 10 static int serialFileDescriptors[MAX_SERIAL_PORTS]; /* index=squeak port# */ static struct termios savedSerialTermios[MAX_SERIAL_PORTS]; /* index=squeak port# */ /* dataRate rate in bps */ typedef struct drDecode { int dataRate; speed_t code; } drDecode; static drDecode dataRateDecode[] = { { 0, B0 }, /* hang up */ { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 }, # if defined(B57600) /* missing on SunOS 4 */ { 57600, B57600 }, { 115200, B115200 }, # endif # if defined(B230400) /* missing on Digital Unix (ex DEC OSF/1) */ { 230400, B230400 }, # endif # if defined(B460800) /* missing on FreeBSD */ { 460800, B460800 }, # endif # if defined(B500000) /* missing on GNU/Linux prior to 2.2 */ { 500000, B500000 }, { 576000, B576000 }, { 921600, B921600 }, { 1000000, B1000000 }, { 1152000, B1152000 }, { 1500000, B1500000 }, { 2000000, B2000000 }, { 2500000, B2500000 }, { 3000000, B3000000 }, { 3500000, B3500000 }, { 4000000, B4000000 }, # endif { -1, B0 } /* end marker */ }; /* This is the default setting for a termios structure on open */ static struct termios defaultTermios; /*** Private Functions ***/ /* return the speed_t corresponding to the given data rate in bps, * or B0 if not found */ static speed_t serialDecodeSpeed(int speed) { drDecode* p; for( p = dataRateDecode; p->dataRate >= 0; p++) { if (p->dataRate == speed) return p->code; } return B0; } /*** Public Functions ***/ /* return value ignored */ int serialPortClose(int portNum) { int fd; if (portNum < 0 || portNum >= MAX_SERIAL_PORTS ) { success(false); return 0; } /* Squeak wants to close already-closed ports... */ if ((fd = serialFileDescriptors[ portNum ]) < 0) { success(true); return 0; } serialFileDescriptors[ portNum ] = -1; if (tcsetattr(fd, TCSAFLUSH, savedSerialTermios + portNum) || close(fd)) { success(false); return 0; } success(true); return 0; } /* Open the given serial port using the given settings. The data rate can be * any number that is in the table above; the driver is not as flexible * about the speed as the Mac driver, apparently. */ /* return value ignored */ int serialPortOpen( int portNum, int dataRate, int stopBitsType, int parityType, int dataBits, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar) { int fd; char serialPortName[ PORT_NAME_SIZE ]; speed_t speed = serialDecodeSpeed( dataRate ); struct termios flags; /* validate arguments */ if (portNum < 0 || portNum >= MAX_SERIAL_PORTS || speed == B0 || stopBitsType < 0 || stopBitsType > MAX_STOP_BITS || parityType < 0 || parityType > MAX_PARITY_TYPE || dataBits < 0 || dataBits > MAX_DATA_BITS || inFlowCtrl < 0 || inFlowCtrl > MAX_FLOW_CTRL || outFlowCtrl < 0 || outFlowCtrl > MAX_FLOW_CTRL || (( inFlowCtrl == 1 || outFlowCtrl == 1 ) && ( xOnChar < 0 || xOnChar > 255 || xOffChar < 0 || xOffChar > 255 ))) { success(false); return 0; } /* generate a filename (with last digit set to port number) */ strcpy(serialPortName, serialPortBaseName); serialPortName[ PORT_NAME_SIZE - 2 ] = portNum + '0'; /* open the device */ if ((fd = open(serialPortName, O_RDWR|O_NONBLOCK|O_NOCTTY)) < 0) { success(false); return 0; } /* save the file descriptor */ serialFileDescriptors[ portNum ] = fd; /* save the old state */ if (tcgetattr(fd, savedSerialTermios + portNum)) { success(false); return 0; } /* set up the new modes */ flags = defaultTermios; /* input & output data rate */ cfsetispeed(&flags, speed); cfsetospeed(&flags, speed); /* stop bits */ flags.c_cflag &= ~CSTOPB; flags.c_cflag |= stopBitsDecode[ stopBitsType ]; /* parity */ flags.c_cflag &= ~(PARENB|PARODD); flags.c_cflag |= parityTypeDecode[ parityType ]; /* data bits */ flags.c_cflag &= ~CSIZE; flags.c_cflag |= dataBitsDecode[ dataBits ]; /* flow control characters */ if (inFlowCtrl == 1 || outFlowCtrl == 1) { flags.c_cc[ VSTART ] = xOnChar; flags.c_cc[ VSTOP ] = xOffChar; } flags.c_iflag &= ~(IXON|IXOFF|IXANY); if (inFlowCtrl == 1) flags.c_iflag |= IXOFF; if (outFlowCtrl == 1) flags.c_iflag |= IXON; # if defined(CRTSCTS) flags.c_cflag &= ~CRTSCTS; if (inFlowCtrl == 2 || outFlowCtrl == 2) flags.c_cflag |= CRTSCTS; # else /* not defined in IRIX!? */ if (inFlowCtrl == 2 || outFlowCtrl == 2) { fprintf(stderr, "CRTSCTS not supported.\n"); success(false); return 0; } # endif if (tcsetattr(fd, TCSANOW, &flags)) /* set it NOW */ { success(false); return 0; } success(true); return 0; } /* Read up to count bytes from the given serial port into the given byte array. Read only up to the number of bytes in the port's input buffer; if fewer bytes than count have been received, do not wait for additional data to arrive. Return zero if no data is available, else number of bytes read */ int serialPortReadInto(int portNum, int count, int startPtr) { int fd; ssize_t bytesRead; void* buffer = (void*)startPtr; /* ints as pointers?? */ if (portNum < 0 || portNum >= MAX_SERIAL_PORTS || (fd = serialFileDescriptors[ portNum ]) < 0) { success(false); return 0; } bytesRead = read(fd, buffer, (size_t)count); if (bytesRead == (ssize_t)-1) { if (errno == EAGAIN) bytesRead = 0; else { success(false); return 0; } } success(true); return (int)bytesRead; } /* Write count bytes from the given byte array to the given serial port's output buffer. Return the number of bytes written. This implementation is synchronous: it doesn't return until the data has been sent. However, other implementations may return before transmission is complete. */ int serialPortWriteFrom(int portNum, int count, int startPtr) { int fd; int bytesWritten; char* buffer = (void*)startPtr; if (portNum < 0 || portNum >= MAX_SERIAL_PORTS || (fd = serialFileDescriptors[ portNum ]) < 0) { success(false); return 0; } bytesWritten = write(fd, buffer, (size_t)count); if (bytesWritten == (ssize_t)-1) { success(false); return 0; } success(true); return bytesWritten; } /* return true on success */ int serialPortInit(void) { int i; /* initialize the file descriptors to invalid */ for (i = 0; i < MAX_SERIAL_PORTS; i++) serialFileDescriptors[ i ] = -1; /* initialize our default termios structure (already 0'd) */ defaultTermios.c_iflag = IGNBRK | IGNPAR; /* ignore break, parity/framing errs */ /* tcflag_t c_oflag output modes */ /* defaultTermios.c_oflag = 0; */ /* tcflag_t c_cflag control modes */ defaultTermios.c_cflag = CREAD; /* tcflag_t c_lflag local modes */ /* defaultTermios.c_lflag = 0; */ /* cc_t c_cc[NCCS] control chars */ defaultTermios.c_cc[VTIME] = 0; defaultTermios.c_cc[VMIN] = 0; success(true); return 1; } /* return true on success */ int serialPortShutdown(void) { success(true); return 1; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SocketPlugin/config.cmake ================================================ PLUGIN_FIND_LIBRARY(SOCKET socket) PLUGIN_FIND_LIBRARY(NSL nsl) ================================================ FILE: vm/src/from_squeak/unix/plugins/SocketPlugin/sqUnixSocket.c ================================================ /* sqUnixSocket.c -- Unix socket support * * Copyright (C) 1996-2006 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Author: Ian.Piumarta@inria.fr * * Support for BSD-style "accept" primitives contributed by: * Lex Spoon * * Notes: * Sockets are completely asynchronous, but the resolver is still * synchronous. * * BUGS: * Now that the image has real UDP primitives, the TCP/UDP duality in * many of the connection-oriented functions should be removed and * cremated. */ #include "sq.h" #include "SocketPlugin.h" #include "sqaio.h" #undef AIO_DEBUG #undef DEBUG #ifdef ACORN # include # define __time_t # include # include "inetlib.h" # include "socklib.h" # include "netdb.h" # include "unixlib.h" # include "sys/ioctl.h" # include "sys/errno.h" # define h_errno errno # define MAXHOSTNAMELEN 256 # define socklen_t int # define strncpy(dst, src, len) copyNCharsFromTo(len, src, dst) #else /* !ACORN */ # ifdef NEED_GETHOSTNAME_P extern int gethostname(); # endif # ifdef HAVE_SYS_TIME_H # include # else # include # endif # include # include # include # include # include # include # include # include # include #endif /* !ACORN */ /* Solaris sometimes fails to define this in netdb.h */ #ifndef MAXHOSTNAMELEN # define MAXHOSTNAMELEN 256 #endif /* debugging stuff. can probably be deleted */ #ifdef DEBUG # ifdef ACORN # define FPRINTF(s) \ { \ extern os_error privateErr; \ extern void platReportError(os_error *e); \ privateErr.errnum = (bits)0; \ sprintf s; \ platReportError((os_error *)&privateErr); \ }; # else /* !ACORN */ extern int aioLastTick, aioThisTick; # define FPRINTF(X) { aioThisTick= ioMSecs(); fprintf(stderr, "%8d %8d ", aioThisTick, aioThisTick - aioLastTick); aioLastTick= aioThisTick; fprintf X; } # endif #else /* !DEBUG */ # define FPRINTF(X) #endif /*** Socket types ***/ #define TCPSocketType 0 #define UDPSocketType 1 #define RAWSocketType 2 /*** Resolver states ***/ #define ResolverUninitialised 0 #define ResolverSuccess 1 #define ResolverBusy 2 #define ResolverError 3 /*** TCP Socket states ***/ #define Invalid -1 #define Unconnected 0 #define WaitingForConnection 1 #define Connected 2 #define OtherEndClosed 3 #define ThisEndClosed 4 #define LINGER_SECS 1 static int thisNetSession= 0; static int one= 1; static char localHostName[MAXHOSTNAMELEN]; static u_long localHostAddress; /* GROSS IPv4 ASSUMPTION! */ typedef struct privateSocketStruct { int s; /* Unix socket */ int connSema; /* connection io notification semaphore */ int readSema; /* read io notification semaphore */ int writeSema; /* write io notification semaphore */ int sockState; /* connection + data state */ int sockError; /* errno after socket error */ struct sockaddr_in peer; /* default send/recv address for UDP */ int multiListen; /* whether to listen for multiple connections */ int acceptedSock; /* a connection that has been accepted */ } privateSocketStruct; #define CONN_NOTIFY (1<<0) #define READ_NOTIFY (1<<1) #define WRITE_NOTIFY (1<<2) #define PING(S,EVT) \ { \ interpreterProxy->signalSemaphoreWithIndex((S)->EVT##Sema); \ FPRINTF((stderr, "notify %d %s\n", (S)->s, #EVT)); \ } #define notify(SOCK,MASK) \ { \ if ((MASK) & CONN_NOTIFY) PING(SOCK,conn); \ if ((MASK) & READ_NOTIFY) PING(SOCK,read); \ if ((MASK) & WRITE_NOTIFY) PING(SOCK,write); \ } /*** Accessors for private socket members from a Squeak socket pointer ***/ #define _PSP(S) (((S)->privateSocketPtr)) #define PSP(S) ((privateSocketStruct *)((S)->privateSocketPtr)) #define SOCKET(S) (PSP(S)->s) #define SOCKETSTATE(S) (PSP(S)->sockState) #define SOCKETERROR(S) (PSP(S)->sockError) #define SOCKETPEER(S) (PSP(S)->peer) /*** Resolver state ***/ static char lastName[MAXHOSTNAMELEN+1]; static int lastAddr= 0; static int lastError= 0; static int resolverSema= 0; /*** Variables ***/ extern struct VirtualMachine *interpreterProxy; int setHookFn; static void acceptHandler(int, void *, int); static void connectHandler(int, void *, int); static void dataHandler(int, void *, int); static void closeHandler(int, void *, int); /* this MUST be turned on if DEBUG is turned on in aio.c */ #ifdef AIO_DEBUG char *socketHandlerName(aioHandler h) { if (h == acceptHandler) return "acceptHandler"; if (h == connectHandler) return "connectHandler"; if (h == dataHandler) return "dataHandler"; if (h == closeHandler) return "closeHandler"; return "***unknownHandler***"; } #endif /*** module initialisation/shutdown ***/ sqInt socketInit(void) { return 1; } sqInt socketShutdown(void) { /* shutdown the network */ sqNetworkShutdown(); return 1; } /*** miscellaneous sundries ***/ /* set linger on a connected stream */ static void setLinger(int fd, int flag) { struct linger linger= { flag, flag * LINGER_SECS }; setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)); } /* answer the hostname for the given IP address */ static const char *addrToName(int netAddress) { u_long nAddr; struct hostent *he; lastError= 0; /* for the resolver */ nAddr= htonl(netAddress); if ((he= gethostbyaddr((char *)&nAddr, sizeof(nAddr), AF_INET))) return he->h_name; lastError= h_errno; /* ditto */ return ""; } /* answer the IP address for the given hostname */ static int nameToAddr(char *hostName) { struct hostent *he; lastError= 0; /* ditto */ if ((he= gethostbyname(hostName))) return ntohl(*(long *)(he->h_addr_list[0])); lastError= h_errno; /* and one more ditto */ return 0; } /* answer whether the given socket is valid in this net session */ static int socketValid(SocketPtr s) { if (s && s->privateSocketPtr && thisNetSession && (s->sessionID == thisNetSession)) return true; interpreterProxy->success(false); return false; } /* answer 1 if the given socket is readable, 0 if read would block, or -1 if the socket is no longer connected */ static int socketReadable(int s) { char buf[1]; int n= recv(s, (void *)buf, 1, MSG_PEEK); if (n > 0) return 1; if ((n < 0) && (errno == EWOULDBLOCK)) return 0; return -1; /* EOF */ } /* answer whether the socket can be written without blocking */ static int socketWritable(int s) { struct timeval tv= { 0, 0 }; fd_set fds; FD_ZERO(&fds); FD_SET(s, &fds); return select(s+1, 0, &fds, 0, &tv) > 0; } /* answer the error condition on the given socket */ static int socketError(int s) { int error= 0; socklen_t errsz= sizeof(error); /* Solaris helpfuly returns -1 if there is an error on the socket, so we can't check the success of the getsockopt call itself. Ho hum. */ getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&error, &errsz); return error; } /*** asynchronous io handlers ***/ /* accept() can now be performed for the socket: call accept(), and replace the server socket with the new client socket leaving the client socket unhandled */ static void acceptHandler(int fd, void *data, int flags) { privateSocketStruct *pss= (privateSocketStruct *)data; FPRINTF((stderr, "acceptHandler(%d, %p ,%d)\n", fd, data, flags)); if (flags & AIO_X) /* -- exception */ { /* error during listen() */ aioDisable(fd); pss->sockError= socketError(fd); pss->sockState= Invalid; pss->s= -1; close(fd); fprintf(stderr, "acceptHandler: aborting server %d pss=%p\n", fd, pss); } else /* (flags & AIO_R) -- accept() is ready */ { int newSock= accept(fd, 0, 0); if (newSock < 0) { if (errno == ECONNABORTED) { /* let's just pretend this never happened */ aioHandle(fd, acceptHandler, AIO_RX); return; } /* something really went wrong */ pss->sockError= errno; pss->sockState= Invalid; perror("acceptHandler"); aioDisable(fd); close(fd); fprintf(stderr, "acceptHandler: aborting server %d pss=%p\n", fd, pss); } else /* newSock >= 0 -- connection accepted */ { pss->sockState= Connected; setLinger(newSock, 1); if (pss->multiListen) { pss->acceptedSock= newSock; } else /* traditional listen -- replace server with client in-place */ { aioDisable(fd); close(fd); pss->s= newSock; aioEnable(newSock, pss, 0); } } } notify(pss, CONN_NOTIFY); } /* connect() has completed: check errors, leaving the socket unhandled */ static void connectHandler(int fd, void *data, int flags) { privateSocketStruct *pss= (privateSocketStruct *)data; FPRINTF((stderr, "connectHandler(%d, %p, %d)\n", fd, data, flags)); if (flags & AIO_X) /* -- exception */ { /* error during asynchronous connect() */ aioDisable(fd); pss->sockError= socketError(fd); pss->sockState= Unconnected; perror("connectHandler"); } else /* (flags & AIO_W) -- connect completed */ { /* connect() has completed */ int error= socketError(fd); if (error) { FPRINTF((stderr, "connectHandler: error %d (%s)\n", error, strerror(error))); pss->sockError= error; pss->sockState= Unconnected; } else { pss->sockState= Connected; setLinger(pss->s, 1); } } notify(pss, CONN_NOTIFY); } /* read or write data transfer is now possible for the socket. */ static void dataHandler(int fd, void *data, int flags) { privateSocketStruct *pss= (privateSocketStruct *)data; FPRINTF((stderr, "dataHandler(%d=%d, %p, %d)\n", fd, pss->s, data, flags)); if (pss == NULL) { fprintf(stderr, "dataHandler: pss is NULL fd=%d data=%p flags=0x%x\n", fd, data, flags); return; } if (flags & AIO_R) { int n= socketReadable(fd); if (n == 0) { fprintf(stderr, "dataHandler: selected socket fd=%d flags=0x%x would block (why?)\n", fd, flags); } if (n != 1) { pss->sockError= socketError(fd); pss->sockState= OtherEndClosed; } } if (flags & AIO_X) { /* assume out-of-band data has arrived */ /* NOTE: Squeak's socket interface is currently incapable of reading * OOB data. We have no choice but to discard it. Ho hum. */ char buf[1]; int n= recv(fd, (void *)buf, 1, MSG_OOB); if (n == 1) fprintf(stderr, "socket: received OOB data: %02x\n", buf[0]); } if (flags & AIO_R) notify(pss, READ_NOTIFY); if (flags & AIO_W) notify(pss, WRITE_NOTIFY); } /* a non-blocking close() has completed -- finish tidying up */ static void closeHandler(int fd, void *data, int flags) { privateSocketStruct *pss= (privateSocketStruct *)data; aioDisable(fd); FPRINTF((stderr, "closeHandler(%d, %p, %d)\n", fd, data, flags)); pss->sockState= Unconnected; pss->s= -1; notify(pss, CONN_NOTIFY); } /*** Squeak network functions ***/ /* start a new network session */ sqInt sqNetworkInit(sqInt resolverSemaIndex) { if (0 != thisNetSession) return 0; /* already initialised */ gethostname(localHostName, MAXHOSTNAMELEN); localHostAddress= nameToAddr(localHostName); thisNetSession= clock() + time(0); if (0 == thisNetSession) thisNetSession= 1; /* 0 => uninitialised */ resolverSema= resolverSemaIndex; return 0; } /* terminate the current network session (invalidates all open sockets) */ void sqNetworkShutdown(void) { thisNetSession= 0; resolverSema= 0; aioFini(); } /*** Squeak Generic Socket Functions ***/ /* create a new socket */ void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaID(SocketPtr s, sqInt netType, sqInt socketType, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex) { sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(s, netType, socketType,recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, sqInt netType, sqInt socketType, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex, sqInt readSemaIndex, sqInt writeSemaIndex) { int newSocket= -1; privateSocketStruct *pss; s->sessionID= 0; if (TCPSocketType == socketType) { /* --- TCP --- */ newSocket= socket(AF_INET, SOCK_STREAM, 0); } else if (UDPSocketType == socketType) { /* --- UDP --- */ newSocket= socket(AF_INET, SOCK_DGRAM, 0); } if (-1 == newSocket) { /* socket() failed, or incorrect socketType */ interpreterProxy->success(false); return; } setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); /* private socket structure */ pss= (privateSocketStruct *)calloc(1, sizeof(privateSocketStruct)); if (pss == NULL) { fprintf(stderr, "acceptFrom: out of memory\n"); interpreterProxy->success(false); return; } pss->s= newSocket; pss->connSema= semaIndex; pss->readSema= readSemaIndex; pss->writeSema= writeSemaIndex; /* UDP sockets are born "connected" */ if (UDPSocketType == socketType) { pss->sockState= Connected; aioEnable(pss->s, pss, 0); } else { pss->sockState= Unconnected; } pss->sockError= 0; /* initial UDP peer := wildcard */ memset(&pss->peer, 0, sizeof(pss->peer)); pss->peer.sin_family= AF_INET; pss->peer.sin_port= 0; pss->peer.sin_addr.s_addr= INADDR_ANY; /* Squeak socket */ s->sessionID= thisNetSession; s->socketType= socketType; s->privateSocketPtr= pss; FPRINTF((stderr, "create(%d) -> %lx\n", SOCKET(s), (unsigned long)PSP(s))); /* Note: socket is in BLOCKING mode until aioEnable is called for it! */ } void sqSocketCreateRawProtoTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, sqInt netType, sqInt protocol, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex, sqInt readSemaIndex, sqInt writeSemaIndex) { int newSocket= -1; privateSocketStruct *pss; s->sessionID= 0; switch(protocol) { case 1: newSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); break; } if (-1 == newSocket) { /* socket() failed, or incorrect protocol type */ fprintf(stderr, "primSocketCreateRAW: socket() failed; protocol = %d, errno = %d\n", protocol, errno); interpreterProxy->success(false); return; } /* private socket structure */ pss= (privateSocketStruct *)calloc(1, sizeof(privateSocketStruct)); if (pss == NULL) { fprintf(stderr, "acceptFrom: out of memory\n"); interpreterProxy->success(false); return; } pss->s= newSocket; pss->connSema= semaIndex; pss->readSema= readSemaIndex; pss->writeSema= writeSemaIndex; /* RAW sockets are born "connected" */ pss->sockState= Connected; aioEnable(pss->s, pss, 0); pss->sockError= 0; /* initial UDP peer := wildcard */ memset(&pss->peer, 0, sizeof(pss->peer)); pss->peer.sin_family= AF_INET; pss->peer.sin_port= 0; pss->peer.sin_addr.s_addr= INADDR_ANY; /* Squeak socket */ s->sessionID= thisNetSession; s->socketType= RAWSocketType; s->privateSocketPtr= pss; FPRINTF((stderr, "create(%d) -> %lx\n", SOCKET(s), (unsigned long)PSP(s))); /* Note: socket is in BLOCKING mode until aioEnable is called for it! */ } /* return the state of a socket */ sqInt sqSocketConnectionStatus(SocketPtr s) { if (!socketValid(s)) return Invalid; /* we now know that the net session is valid, so if state is Invalid... */ if (SOCKETSTATE(s) == Invalid) /* see acceptHandler() */ { fprintf(stderr, "socketStatus: freeing invalidated pss=%p\n", PSP(s)); /*free(PSP(s));*/ /* this almost never happens -- safer not to free()?? */ _PSP(s)= 0; interpreterProxy->success(false); return Invalid; } #if 0 /* check for connection closed by peer */ if (SOCKETSTATE(s) == Connected) { int fd= SOCKET(s); int n= socketReadable(fd); if (n < 0) { FPRINTF((stderr, "socketStatus(%d): detected other end closed\n", fd)); SOCKETSTATE(s)= OtherEndClosed; } } #endif FPRINTF((stderr, "socketStatus(%d) -> %d\n", SOCKET(s), SOCKETSTATE(s))); return SOCKETSTATE(s); } /* TCP => start listening for incoming connections. * UDP => associate the local port number with the socket. */ void sqSocketListenOnPort(SocketPtr s, sqInt port) { sqSocketListenOnPortBacklogSize(s, port, 1); } void sqSocketListenOnPortBacklogSizeInterface(SocketPtr s, sqInt port, sqInt backlogSize, sqInt addr) { struct sockaddr_in saddr; if (!socketValid(s)) return; /* only TCP sockets have a backlog */ if ((backlogSize > 1) && (s->socketType != TCPSocketType)) { interpreterProxy->success(false); return; } PSP(s)->multiListen= (backlogSize > 1); FPRINTF((stderr, "listenOnPortBacklogSize(%d, %d)\n", SOCKET(s), backlogSize)); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family= AF_INET; saddr.sin_port= htons((short)port); saddr.sin_addr.s_addr= htonl(addr); bind(SOCKET(s), (struct sockaddr*) &saddr, sizeof(saddr)); if (TCPSocketType == s->socketType) { /* --- TCP --- */ listen(SOCKET(s), backlogSize); SOCKETSTATE(s)= WaitingForConnection; aioEnable(SOCKET(s), PSP(s), 0); aioHandle(SOCKET(s), acceptHandler, AIO_RX); /* R => accept() */ } else { /* --- UDP/RAW --- */ } } void sqSocketListenOnPortBacklogSize(SocketPtr s, sqInt port, sqInt backlogSize) { sqSocketListenOnPortBacklogSizeInterface(s, port, backlogSize, INADDR_ANY); } /* TCP => open a connection. * UDP => set remote address. */ void sqSocketConnectToPort(SocketPtr s, sqInt addr, sqInt port) { struct sockaddr_in saddr; if (!socketValid(s)) return; FPRINTF((stderr, "connectTo(%d)\n", SOCKET(s))); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family= AF_INET; saddr.sin_port= htons((short)port); saddr.sin_addr.s_addr= htonl(addr); if (TCPSocketType != s->socketType) { /* --- UDP/RAW --- */ if (SOCKET(s) >= 0) { memcpy((void *)&SOCKETPEER(s), (void *)&saddr, sizeof(SOCKETPEER(s))); SOCKETSTATE(s)= Connected; } } else { /* --- TCP --- */ int result; aioEnable(SOCKET(s), PSP(s), 0); result= connect(SOCKET(s), (struct sockaddr *)&saddr, sizeof(saddr)); FPRINTF((stderr, "connect() => %d\n", result)); if (result == 0) { /* connection completed synchronously */ SOCKETSTATE(s)= Connected; notify(PSP(s), CONN_NOTIFY); setLinger(SOCKET(s), 1); } else { if (errno == EINPROGRESS || errno == EWOULDBLOCK) { /* asynchronous connection in progress */ SOCKETSTATE(s)= WaitingForConnection; aioHandle(SOCKET(s), connectHandler, AIO_WX); /* W => connect() */ } else { /* connection error */ perror("sqConnectToPort"); SOCKETSTATE(s)= Unconnected; SOCKETERROR(s)= errno; notify(PSP(s), CONN_NOTIFY); } } } } void sqSocketAcceptFromRecvBytesSendBytesSemaID(SocketPtr s, SocketPtr serverSocket, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex) { sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(s, serverSocket, recvBufSize, sendBufSize, semaIndex, semaIndex, semaIndex); } void sqSocketAcceptFromRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, SocketPtr serverSocket, sqInt recvBufSize, sqInt sendBufSize, sqInt semaIndex, sqInt readSemaIndex, sqInt writeSemaIndex) { /* The image has already called waitForConnection, so there is no need to signal the server's connection semaphore again. */ struct privateSocketStruct *pss; FPRINTF((stderr, "acceptFrom(%p, %d)\n", s, SOCKET(serverSocket))); /* sanity checks */ if (!socketValid(serverSocket) || !PSP(serverSocket)->multiListen) { FPRINTF((stderr, "accept failed: (multi->%d)\n", PSP(serverSocket)->multiListen)); interpreterProxy->success(false); return; } /* check that a connection is there */ if (PSP(serverSocket)->acceptedSock < 0) { fprintf(stderr, "acceptFrom: no socket available\n"); interpreterProxy->success(false); return; } /* got connection -- fill in the structure */ s->sessionID= 0; pss= (privateSocketStruct *)calloc(1, sizeof(privateSocketStruct)); if (pss == NULL) { fprintf(stderr, "acceptFrom: out of memory\n"); interpreterProxy->success(false); return; } _PSP(s)= pss; pss->s= PSP(serverSocket)->acceptedSock; PSP(serverSocket)->acceptedSock= -1; SOCKETSTATE(serverSocket)= WaitingForConnection; aioHandle(SOCKET(serverSocket), acceptHandler, AIO_RX); s->sessionID= thisNetSession; pss->connSema= semaIndex; pss->readSema= readSemaIndex; pss->writeSema= writeSemaIndex; pss->sockState= Connected; pss->sockError= 0; aioEnable(SOCKET(s), PSP(s), 0); } /* close the socket */ void sqSocketCloseConnection(SocketPtr s) { int result= 0; if (!socketValid(s)) return; FPRINTF((stderr, "closeConnection(%d)\n", SOCKET(s))); if (SOCKET(s) < 0) return; /* already closed */ aioDisable(SOCKET(s)); SOCKETSTATE(s)= ThisEndClosed; result= close(SOCKET(s)); if ((result == -1) && (errno != EWOULDBLOCK)) { /* error */ SOCKETSTATE(s)= Unconnected; SOCKETERROR(s)= errno; notify(PSP(s), CONN_NOTIFY); perror("closeConnection"); } else if (0 == result) { /* close completed synchronously */ SOCKETSTATE(s)= Unconnected; FPRINTF((stderr, "closeConnection: disconnected\n")); SOCKET(s)= -1; } else { /* asynchronous close in progress */ SOCKETSTATE(s)= ThisEndClosed; aioHandle(SOCKET(s), closeHandler, AIO_RWX); /* => close() done */ FPRINTF((stderr, "closeConnection: deferred [aioHandle is set]\n")); } } /* close the socket without lingering */ void sqSocketAbortConnection(SocketPtr s) { FPRINTF((stderr, "abortConnection(%d)\n", SOCKET(s))); if (!socketValid(s)) return; setLinger(SOCKET(s), 0); sqSocketCloseConnection(s); } /* Release the resources associated with this socket. If a connection is open, abort it. */ void sqSocketDestroy(SocketPtr s) { if (!socketValid(s)) return; FPRINTF((stderr, "destroy(%d)\n", SOCKET(s))); if (SOCKET(s)) sqSocketAbortConnection(s); /* close if necessary */ if (PSP(s)) free(PSP(s)); /* release private struct */ _PSP(s)= 0; } /* answer the OS error code for the last socket operation */ sqInt sqSocketError(SocketPtr s) { if (!socketValid(s)) return -1; return SOCKETERROR(s); } /* return the local IP address bound to a socket */ sqInt sqSocketLocalAddress(SocketPtr s) { struct sockaddr_in saddr; socklen_t saddrSize= sizeof(saddr); if (!socketValid(s)) return -1; if (getsockname(SOCKET(s), (struct sockaddr *)&saddr, &saddrSize) || (AF_INET != saddr.sin_family)) return 0; return ntohl(saddr.sin_addr.s_addr); } /* return the peer's IP address */ sqInt sqSocketRemoteAddress(SocketPtr s) { struct sockaddr_in saddr; socklen_t saddrSize= sizeof(saddr); if (!socketValid(s)) return -1; if (TCPSocketType == s->socketType) { /* --- TCP --- */ if (getpeername(SOCKET(s), (struct sockaddr *)&saddr, &saddrSize) || (AF_INET != saddr.sin_family)) return 0; return ntohl(saddr.sin_addr.s_addr); } /* --- UDP/RAW --- */ return ntohl(SOCKETPEER(s).sin_addr.s_addr); } /* return the local port number of a socket */ sqInt sqSocketLocalPort(SocketPtr s) { struct sockaddr_in saddr; socklen_t saddrSize= sizeof(saddr); if (!socketValid(s)) return -1; if (getsockname(SOCKET(s), (struct sockaddr *)&saddr, &saddrSize) || (AF_INET != saddr.sin_family)) return 0; return ntohs(saddr.sin_port); } /* return the peer's port number */ sqInt sqSocketRemotePort(SocketPtr s) { struct sockaddr_in saddr; socklen_t saddrSize= sizeof(saddr); if (!socketValid(s)) return -1; if (TCPSocketType == s->socketType) { /* --- TCP --- */ if (getpeername(SOCKET(s), (struct sockaddr *)&saddr, &saddrSize) || (AF_INET != saddr.sin_family)) return 0; return ntohs(saddr.sin_port); } /* --- UDP/RAW --- */ return ntohs(SOCKETPEER(s).sin_port); } /* answer whether the socket has data available for reading: if the socket is not connected, answer "false"; if the socket is open and data can be read, answer "true". if the socket is open and no data is currently readable, answer "false"; if the socket is closed by peer, change the state to OtherEndClosed and answer "false"; */ sqInt sqSocketReceiveDataAvailable(SocketPtr s) { if (!socketValid(s)) return false; if (SOCKETSTATE(s) == Connected) { int fd= SOCKET(s); int n= socketReadable(fd); if (n > 0) { FPRINTF((stderr, "receiveDataAvailable(%d) -> true\n", fd)); return true; } else if (n < 0) { FPRINTF((stderr, "receiveDataAvailable(%d): other end closed\n", fd)); SOCKETSTATE(s)= OtherEndClosed; } } else /* (SOCKETSTATE(s) != Connected) */ { FPRINTF((stderr, "receiveDataAvailable(%d): socket not connected\n", SOCKET(s))); } aioHandle(SOCKET(s), dataHandler, AIO_RX); FPRINTF((stderr, "receiveDataAvailable(%d) -> false [aioHandle is set]\n", SOCKET(s))); return false; } /* answer whether the socket has space to receive more data */ sqInt sqSocketSendDone(SocketPtr s) { if (!socketValid(s)) return false; if (SOCKETSTATE(s) == Connected) { if (socketWritable(SOCKET(s))) return true; aioHandle(SOCKET(s), dataHandler, AIO_WX); } return false; } /* read data from the socket s into buf for at most bufSize bytes. answer the number actually read. For UDP, fill in the peer's address with the approriate value. */ sqInt sqSocketReceiveDataBufCount(SocketPtr s, char *buf, sqInt bufSize) { int nread= 0; if (!socketValid(s)) return -1; if (TCPSocketType != s->socketType) { /* --- UDP/RAW --- */ socklen_t addrSize= sizeof(SOCKETPEER(s)); if ((nread= recvfrom(SOCKET(s), buf, bufSize, 0, (struct sockaddr *)&SOCKETPEER(s), &addrSize)) <= 0) { if ((nread == -1) && (errno == EWOULDBLOCK)) { FPRINTF((stderr, "UDP receiveData(%d) < 1 [blocked]\n", SOCKET(s))); return 0; } SOCKETERROR(s)= errno; FPRINTF((stderr, "UDP receiveData(%d) < 1 [a:%d]\n", SOCKET(s), errno)); return 0; } } else { /* --- TCP --- */ if ((nread= read(SOCKET(s), buf, bufSize)) <= 0) { if ((nread == -1) && (errno == EWOULDBLOCK)) { FPRINTF((stderr, "TCP receiveData(%d) < 1 [blocked]\n", SOCKET(s))); return 0; } /* connection reset */ SOCKETSTATE(s)= OtherEndClosed; SOCKETERROR(s)= errno; FPRINTF((stderr, "TCP receiveData(%d) < 1 [b:%d]\n", SOCKET(s), errno)); notify(PSP(s), CONN_NOTIFY); return 0; } } /* read completed synchronously */ FPRINTF((stderr, "receiveData(%d) done = %d\n", SOCKET(s), nread)); return nread; } /* write data to the socket s from buf for at most bufSize bytes. answer the number of bytes actually written. */ sqInt sqSocketSendDataBufCount(SocketPtr s, char *buf, sqInt bufSize) { int nsent= 0; if (!socketValid(s)) return -1; if (TCPSocketType != s->socketType) { /* --- UDP/RAW --- */ FPRINTF((stderr, "UDP sendData(%d, %d)\n", SOCKET(s), bufSize)); if ((nsent= sendto(SOCKET(s), buf, bufSize, 0, (struct sockaddr *)&SOCKETPEER(s), sizeof(SOCKETPEER(s)))) <= 0) { if (errno == EWOULDBLOCK) /* asynchronous write in progress */ return 0; FPRINTF((stderr, "UDP send failed\n")); SOCKETERROR(s)= errno; return 0; } } else { /* --- TCP --- */ FPRINTF((stderr, "TCP sendData(%d, %d)\n", SOCKET(s), bufSize)); if ((nsent= write(SOCKET(s), buf, bufSize)) <= 0) { if ((nsent == -1) && (errno == EWOULDBLOCK)) { FPRINTF((stderr, "TCP sendData(%d, %d) -> %d [blocked]", SOCKET(s), bufSize, nsent)); return 0; } else { /* error: most likely "connection closed by peer" */ SOCKETSTATE(s)= OtherEndClosed; SOCKETERROR(s)= errno; FPRINTF((stderr, "TCP write failed -> %d", errno)); return 0; } } } /* write completed synchronously */ FPRINTF((stderr, "sendData(%d) done = %d\n", SOCKET(s), nsent)); return nsent; } /* read data from the UDP socket s into buf for at most bufSize bytes. answer the number of bytes actually read. */ sqInt sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, char *buf, sqInt bufSize, sqInt *address, sqInt *port, sqInt *moreFlag) { if (socketValid(s) && (TCPSocketType != s->socketType)) { struct sockaddr_in saddr; socklen_t addrSize= sizeof(saddr); FPRINTF((stderr, "recvFrom(%d)\n", SOCKET(s))); memset(&saddr, 0, sizeof(saddr)); { int nread= recvfrom(SOCKET(s), buf, bufSize, 0, (struct sockaddr *)&saddr, &addrSize); if (nread >= 0) { *address= ntohl(saddr.sin_addr.s_addr); *port= ntohs(saddr.sin_port); return nread; } if (errno == EWOULDBLOCK) /* asynchronous read in progress */ return 0; SOCKETERROR(s)= errno; FPRINTF((stderr, "receiveData(%d)= %da\n", SOCKET(s), 0)); } } interpreterProxy->success(false); return 0; } /* write data to the UDP socket s from buf for at most bufSize bytes. * answer the number of bytes actually written. */ sqInt sqSockettoHostportSendDataBufCount(SocketPtr s, sqInt address, sqInt port, char *buf, sqInt bufSize) { if (socketValid(s) && (TCPSocketType != s->socketType)) { struct sockaddr_in saddr; FPRINTF((stderr, "sendTo(%d)\n", SOCKET(s))); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family= AF_INET; saddr.sin_port= htons((short)port); saddr.sin_addr.s_addr= htonl(address); { int nsent= sendto(SOCKET(s), buf, bufSize, 0, (struct sockaddr *)&saddr, sizeof(saddr)); if (nsent >= 0) return nsent; if (errno == EWOULDBLOCK) /* asynchronous write in progress */ return 0; FPRINTF((stderr, "UDP send failed\n")); SOCKETERROR(s)= errno; } } interpreterProxy->success(false); return 0; } /*** socket options ***/ /* NOTE: we only support the portable options here as an incentive for people to write portable Squeak programs. If you need non-portable socket options then go write yourself a plugin specific to your platform. This decision is unilateral and non-negotiable. - ikp NOTE: we only support the integer-valued options because the code in SocketPlugin doesn't seem able to cope with the others. (Personally I think that things like SO_SNDTIMEO et al would by far more interesting than the majority of things on this list, but there you go...) NOTE: if your build fails because of a missing option in this list, simply DELETE THE OPTION (or comment it out) and then send me mail (ian.piumarta@inria.fr) to let me know about it. */ typedef struct { char *name; /* name as known to Squeak */ int optlevel; /* protocol level */ int optname; /* name as known to Unix */ } socketOption; #ifndef SOL_IP # define SOL_IP IPPROTO_IP #endif #ifndef SOL_UDP # define SOL_UDP IPPROTO_UDP #endif #ifndef SOL_TCP # define SOL_TCP IPPROTO_TCP #endif static socketOption socketOptions[]= { { "SO_DEBUG", SOL_SOCKET, SO_DEBUG }, { "SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR }, { "SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE }, { "SO_BROADCAST", SOL_SOCKET, SO_BROADCAST }, { "SO_SNDBUF", SOL_SOCKET, SO_SNDBUF }, { "SO_RCVBUF", SOL_SOCKET, SO_RCVBUF }, { "SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE }, { "SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE }, { "SO_LINGER", SOL_SOCKET, SO_LINGER }, { "IP_TTL", SOL_IP, IP_TTL }, { "IP_HDRINCL", SOL_IP, IP_HDRINCL }, { "IP_MULTICAST_IF", SOL_IP, IP_MULTICAST_IF }, { "IP_MULTICAST_TTL", SOL_IP, IP_MULTICAST_TTL }, { "IP_MULTICAST_LOOP", SOL_IP, IP_MULTICAST_LOOP }, #ifdef IP_ADD_MEMBERSHIP { "IP_ADD_MEMBERSHIP", SOL_IP, IP_ADD_MEMBERSHIP }, { "IP_DROP_MEMBERSHIP", SOL_IP, IP_DROP_MEMBERSHIP }, #endif { "TCP_MAXSEG", SOL_TCP, TCP_MAXSEG }, { "TCP_NODELAY", SOL_TCP, TCP_NODELAY }, #ifdef SO_REUSEPORT { "SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT }, #endif #if 0 /*** deliberately unsupported options -- do NOT enable these! ***/ { "SO_PRIORITY", SOL_SOCKET, SO_PRIORITY }, { "SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT }, { "SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT }, { "IP_RCVOPTS", SOL_IP, IP_RCVOPTS }, { "IP_RCVDSTADDR", SOL_IP, IP_RCVDSTADDR }, { "UDP_CHECKSUM", SOL_UDP, UDP_CHECKSUM }, { "TCP_ABORT_THRESHOLD", SOL_TCP, TCP_ABORT_THRESHOLD }, { "TCP_CONN_NOTIFY_THRESHOLD", SOL_TCP, TCP_CONN_NOTIFY_THRESHOLD }, { "TCP_CONN_ABORT_THRESHOLD", SOL_TCP, TCP_CONN_ABORT_THRESHOLD }, { "TCP_NOTIFY_THRESHOLD", SOL_TCP, TCP_NOTIFY_THRESHOLD }, { "TCP_URGENT_PTR_TYPE", SOL_TCP, TCP_URGENT_PTR_TYPE }, #endif { (char *)0, 0, 0 } }; static socketOption *findOption(char *name, size_t nameSize) { if (nameSize < 32) { socketOption *opt= 0; char buf[32]; buf[nameSize]= '\0'; strncpy(buf, name, nameSize); for (opt= socketOptions; opt->name != 0; ++opt) if (!strcmp(buf, opt->name)) return opt; fprintf(stderr, "SocketPlugin: ignoring unknown option '%s'\n", buf); } return 0; } /* set the given option for the socket. the option comes in as a * String. (why on earth we might think this a good idea eludes me * ENTIRELY, so... if the string doesn't smell like an integer then we * copy it verbatim, assuming it's really a ByteArray pretending to be * a struct. caveat hackor.) */ sqInt sqSocketSetOptionsoptionNameStartoptionNameSizeoptionValueStartoptionValueSizereturnedValue(SocketPtr s, char *optionName, sqInt optionNameSize, char *optionValue, sqInt optionValueSize, sqInt *result) { if (socketValid(s)) { socketOption *opt= findOption(optionName, (size_t)optionNameSize); if (opt != 0) { int val= 0; char buf[32]; char *endptr; /* this is JUST PLAIN WRONG (I mean the design in the image rather than the implementation here, which is probably correct w.r.t. the broken design) */ if (optionValueSize > sizeof(buf) - 1) goto barf; memset((void *)buf, 0, sizeof(buf)); memcpy((void *)buf, optionValue, optionValueSize); if (optionValueSize == 1) /* character `1' or `0' */ { val= strtol(buf, &endptr, 0); if (endptr != buf) { memcpy((void *)buf, (void *)&val, sizeof(val)); optionValueSize= sizeof(val); } } if ((setsockopt(PSP(s)->s, opt->optlevel, opt->optname, (const void *)buf, optionValueSize)) < 0) { perror("setsockopt"); goto barf; } /* it isn't clear what we're supposed to return here, since setsockopt isn't supposed to have any value-result parameters (go grok that `const' on the buffer argument if you don't believe me). the image says "the result of the negotiated value". what the fuck is there to negotiate? either setsockopt sets the value or it barfs. and i'm not about to go calling getsockopt just to see if the value got changed or not (the image should send getOption: to the Socket if it really wants to know). if the following is wrong then I could probably care (a lot) less... fix the logic in the image and then maybe i'll care about fixing the logic in here. (i know that isn't very helpful, but it's 05:47 in the morning and i'm severely grumpy after fixing several very unpleasant bugs that somebody introduced into this file while i wasn't looking.) */ *result= val; return 0; } } barf: interpreterProxy->success(false); return false; } /* query the socket for the given option. */ sqInt sqSocketGetOptionsoptionNameStartoptionNameSizereturnedValue(SocketPtr s, char *optionName, sqInt optionNameSize, sqInt *result) { if (socketValid(s)) { socketOption *opt= findOption(optionName, (size_t)optionNameSize); if (opt != 0) { int optval; /* NOT sqInt */ socklen_t optlen= sizeof(optval); if ((getsockopt(PSP(s)->s, opt->optlevel, opt->optname, (void *)&optval, &optlen)) < 0) goto barf; if (optlen != sizeof(optval)) goto barf; *result= optval; return 0; } } barf: interpreterProxy->success(false); return errno; } void sqSocketBindToPort(SocketPtr s, int addr, int port) { int result; struct sockaddr_in inaddr; privateSocketStruct *pss= PSP(s); if (!socketValid(s)) return; /* bind the socket */ memset(&inaddr, 0, sizeof(inaddr)); inaddr.sin_family= AF_INET; inaddr.sin_port= htons(port); inaddr.sin_addr.s_addr= htonl(addr); if (bind(SOCKET(s), (struct sockaddr *)&inaddr, sizeof(struct sockaddr_in)) < 0) { pss->sockError= errno; interpreterProxy->success(false); return; } } void sqSocketSetReusable(SocketPtr s) { char optionValue[256]; size_t bufSize; unsigned char buf[4]; int err; if (!socketValid(s)) return; *(int *)buf= 1; bufSize= 4; if (setsockopt(SOCKET(s), SOL_SOCKET, SO_REUSEADDR, buf, bufSize) < 0) { PSP(s)->sockError= errno; interpreterProxy->success(false); return; } } /*** Resolver functions ***/ /* Note: the Mac and Win32 implementations implement asynchronous lookups * in the DNS. I can't think of an easy way to do this in Unix without * going totally ott with threads or somesuch. If anyone knows differently, * please tell me about it. - Ian */ /*** irrelevancies ***/ void sqResolverAbort(void) {} void sqResolverStartAddrLookup(sqInt address) { const char *res; res= addrToName(address); strncpy(lastName, res, MAXHOSTNAMELEN); FPRINTF((stderr, "startAddrLookup %s\n", lastName)); } sqInt sqResolverStatus(void) { if (!thisNetSession) return ResolverUninitialised; if (lastError != 0) return ResolverError; return ResolverSuccess; } /*** trivialities ***/ sqInt sqResolverAddrLookupResultSize(void) { return strlen(lastName); } sqInt sqResolverError(void) { return lastError; } sqInt sqResolverLocalAddress(void) { return nameToAddr(localHostName); } sqInt sqResolverNameLookupResult(void) { return lastAddr; } void sqResolverAddrLookupResult(char *nameForAddress, sqInt nameSize) { memcpy(nameForAddress, lastName, nameSize); } /*** name resolution ***/ void sqResolverStartNameLookup(char *hostName, sqInt nameSize) { int len= (nameSize < MAXHOSTNAMELEN) ? nameSize : MAXHOSTNAMELEN; memcpy(lastName, hostName, len); lastName[len]= lastError= 0; FPRINTF((stderr, "name lookup %s\n", lastName)); lastAddr= nameToAddr(lastName); /* we're done before we even started */ interpreterProxy->signalSemaphoreWithIndex(resolverSema); } ================================================ FILE: vm/src/from_squeak/unix/plugins/SoundPlugin/sqUnixSound.c ================================================ /* sqUnixSound.c -- sound support for various Unix sound systems * * Author: Ian.Piumarta@inria.fr * * Last edited: 2008-04-21 11:43:42 by piumarta on emilia * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * NOTE: The real sound support code is in one of the following files according * to the output driver selected by `configure': * * sqUnixSoundOSS.c (Open Sound System [incl. Linux native & ALSA compat]) * sqUnixSoundNAS.c (Network Audio System) * sqUnixSoundSun.c (SunOS/Solaris) * sqUnixSoundMacOSX.c (Mac OS 10 CoreAudio) * sqUnixSoundNull.c (sound disabled) */ #include "sq.h" #include "SoundPlugin.h" #include "SqModule.h" #include "SqSound.h" extern sqInt snd_Stop(void); /*** module initialisation/shutdown ***/ extern struct SqModule *soundModule; extern struct SqModule *loadModule(char *type, char *name); static struct SqSound *snd= 0; sqInt soundInit(void) { if (!soundModule # if 0 && !(soundModule= getenv("SQUEAK_SOUND_OSS") ? loadModule("sound", "OSS") : 0) && !(soundModule= getenv("SQUEAK_SOUND_NAS") ? loadModule("sound", "NAS") : 0) && !(soundModule= getenv("SQUEAK_SOUND_SUN") ? loadModule("sound", "Sun") : 0) && !(soundModule= getenv("SQUEAK_SOUND_MACOSX") ? loadModule("sound", "MacOSX") : 0) && !(soundModule= getenv("AUDIOSERVER") ? loadModule("sound", "NAS") : 0) && !(soundModule= loadModule("sound", "OSS")) && !(soundModule= loadModule("sound", "Sun")) && !(soundModule= loadModule("sound", "MacOSX")) && !(soundModule= loadModule("sound", "null")) # endif ) { fprintf(stderr, "could not find any sound module\n"); abort(); } //printf("soundModule %p %s\n", soundModule, soundModule->name); snd= (struct SqSound *)soundModule->makeInterface(); if (SqSoundVersion != snd->version) { fprintf(stderr, "module %s interface version %x does not have required version %x\n", soundModule->name, snd->version, SqSoundVersion); abort(); } return 1; } sqInt soundShutdown(void) { if (snd) snd->snd_Stop(); return 1; } /* output */ sqInt snd_AvailableSpace(void) { return snd->snd_AvailableSpace(); } sqInt snd_InsertSamplesFromLeadTime(sqInt frameCount, void *srcBufPtr, sqInt samplesOfLeadTime) { return snd->snd_InsertSamplesFromLeadTime(frameCount, srcBufPtr, samplesOfLeadTime); } sqInt snd_PlaySamplesFromAtLength(sqInt frameCount, void *srcBufPtr, sqInt startIndex) { return snd->snd_PlaySamplesFromAtLength(frameCount, srcBufPtr, startIndex); } sqInt snd_PlaySilence(void) { return snd->snd_PlaySilence(); } sqInt snd_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex) { return snd->snd_Start(frameCount, samplesPerSec, stereo, semaIndex); } sqInt snd_Stop(void) { return snd->snd_Stop(); } /* input */ sqInt snd_StartRecording(sqInt desiredSamplesPerSec, sqInt stereo, sqInt semaIndex) { return snd->snd_StartRecording(desiredSamplesPerSec, stereo, semaIndex); } sqInt snd_StopRecording(void) { return snd->snd_StopRecording(); } double snd_GetRecordingSampleRate(void) { return snd->snd_GetRecordingSampleRate(); } sqInt snd_RecordSamplesIntoAtLength(void *buf, sqInt startSliceIndex, sqInt bufferSizeInBytes) { return snd->snd_RecordSamplesIntoAtLength(buf, startSliceIndex, bufferSizeInBytes); } /* mixer */ void snd_Volume(double *left, double *right) { snd->snd_Volume(left, right); } void snd_SetVolume(double left, double right) { snd->snd_SetVolume(left, right); } int snd_SetRecordLevel(sqInt level) { return snd->snd_SetRecordLevel(level); } sqInt snd_GetSwitch(sqInt id, sqInt captureFlag, sqInt channel) { return snd->snd_GetSwitch(id, captureFlag, channel); } sqInt snd_SetSwitch(sqInt id, sqInt captureFlag, sqInt parameter) { return snd->snd_SetSwitch(id, captureFlag, parameter); } sqInt snd_SetDevice(sqInt id, char *name) { return snd->snd_SetDevice(id, name); } ================================================ FILE: vm/src/from_squeak/unix/plugins/SoundPlugin/zzz/Buffer.h ================================================ #include #include #include #include enum { Block_Free; Block_Busy; Block_Full; Block_Done; }; typedef struct { int state; int capacity; int size; char *data; } Block; Block *Block_new(int size) { size &= ~(4 * sizeof(double) - 1); Block *b= (Block *)calloc(1, sizeof(Block)); if (b) { b->state= Block_Free; b->capacity= size; if ((b->data= (char *)calloc(1, size))) return b; free(b); } return 0; } void Block_delete(Block *b) { free(b->data); free(b); } void Block_reset(Block *b) { b->state= Block_Free; b->size= 0; } typedef struct { Block *input; Block *output; } Buffer; Buffer *Buffer_new(int size) { Buffer *b= (Buffer *)calloc(1, sizeof(Buffer)); if (b) { if ((b->input= Block_new(size))) { if ((b->output= Block_new(size))) return b; Buffer_delete(b->input); } free(b); } return 0; } void Buffer_delete(Buffer *b) { Block_delete(b->input); Block_delete(b->output); delete(b); } int Buffer_swap(Buffer *b) { if (input->state == Block_Full) { Block *b= input; Block_reset(b->output); b->input= b->output; b->output= b->input; return 1; } output->state= Block_done; return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SoundPlugin/zzz/DoubleBuffer.h ================================================ #include #include #include #include enum { Buffer_Free, Buffer_Busy, Buffer_Full, Buffer_Done }; typedef struct { int state; int size; int iptr; int optr; // 0 <= optr <= iptr <= size char *data; } Buffer; Buffer *Buffer_new(int size) { Buffer *b= (Buffer *)calloc(1, sizeof(Buffer)); if (b) { b->state= Buffer_Free; b->size= size; if ((b->data= (char *)calloc(1, size))) return b; free(b); } return 0; } void Buffer_delete(Buffer *b) { assert(b && b->data); free(b->data); free(b); } void Buffer_reset(Buffer *b) { b->state= Buffer_Free; b->iptr= b->optr= 0; } int Buffer_avail(Buffer *b) { return b->iptr - b->optr; } int Buffer_free(Buffer *b) { return b->size - b->iptr; } typedef struct { Buffer *input; Buffer *output; } DBuffer; DBuffer *DBuffer_new(int size) { DBuffer *d= (DBuffer *)calloc(1, sizeof(DBuffer)); if (d) { if ((d->input= Buffer_new(size))) { if ((d->output= Buffer_new(size))) return d; Buffer_delete(d->input); } free(d); } return 0; } void DBuffer_delete(DBuffer *d) { assert(d && d->input && d->output); Buffer_delete(d->input); Buffer_delete(d->output); free(d); } int DBuffer_swap(DBuffer *d) { if (d->input->state == Buffer_Full) { Buffer *i= d->output; Buffer *o= d->input; d->input= i; d->output= o; Buffer_reset(i); return 1; } d->output->state= Buffer_done; return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SoundPlugin/zzz/Fifo.h ================================================ #include #include #include #include // NOTE: requires the client to define min and max on ints typedef struct { char *data; int size; int avail; int iptr; int optr; } Buffer; Buffer *Buffer_new(int size) { Buffer *b= (Buffer *)malloc(sizeof(Buffer)); if (!b) return 0; if (!(b->data= (char *)malloc(size))) { free(b); return 0; } b->size= size; b->avail= 0; b->iptr= 0; b->optr= 0; return b; } void Buffer_delete(Buffer *b) { assert(b && b->data); free(b->data); free(b); } inline int Buffer_avail(Buffer *b) { assert(!(b->avail & 3)); return b->avail; } inline int Buffer_free(Buffer *b) { return b->size - Buffer_avail(b); } inline void Buffer_getOutputPointers(Buffer *b, char **p1, int *n1, char **p2, int *n2) { int optr= b->optr; int avail= Buffer_avail(b); int headroom= b->size - optr; if (avail == 0) { *p1= *p2= 0; *n1= *n2= 0; } else if (avail <= headroom) { *p1= b->data + optr; *p2= 0; *n1= avail; *n2= 0; } else { *p1= b->data + optr; *p2= b->data; *n1= headroom; *n2= avail - headroom; } assert(!(*n1 & 3)); assert(!(*n2 & 3)); } inline int Buffer_getOutputPointer(Buffer *b, char **ptr) { int optr= b->optr; int avail= Buffer_avail(b); int headroom= b->size - optr; if (headroom < avail) avail= headroom; assert((optr + avail) <= b->size); *ptr= b->data + optr; return avail; } inline int Buffer_getInputPointer(Buffer *b, char **ptr) { int iptr= b->iptr; int free= Buffer_free(b); int headroom= b->size - iptr; if (headroom < free) free= headroom; assert((iptr + free) <= b->size); *ptr= b->data + iptr; return free; } inline void Buffer_advanceOutputPointer(Buffer *b, int size) { int optr= b->optr; int avail= b->avail; assert(!(size & 3)); optr+= size; avail-= size; assert(optr <= b->size); assert(avail >= 0); if (optr == b->size) optr= 0; b->optr= optr; b->avail= avail; } inline void Buffer_advanceInputPointer(Buffer *b, int size) { int iptr= b->iptr; assert(!(size & 3)); { int free= Buffer_free(b); free-= size; assert(free >= 0); } iptr += size; assert(iptr <= b->size); if (iptr == b->size) iptr= 0; b->iptr= iptr; b->avail += size; } inline void Buffer_prefill(Buffer *b, int bytes) { char *ptr; int size= Buffer_getInputPointer(b, &ptr); assert(!(bytes & 3)); assert(bytes <= size); memset(ptr, 0, size); Buffer_advanceInputPointer(b, bytes); } inline int Buffer_write(Buffer *b, char *buf, int nbytes) { int iptr= b->iptr; int bytesToCopy= min(nbytes, Buffer_free(b)); int headroom= b->size - iptr; int bytesCopied= 0; assert(!(nbytes & 3)); if (bytesToCopy >= headroom) { memcpy(b->data + iptr, buf, headroom); iptr= 0; bytesToCopy -= headroom; bytesCopied += headroom; if (bytesToCopy) { memcpy(b->data, buf + bytesCopied, bytesToCopy); iptr= bytesToCopy; bytesCopied += bytesToCopy; } } else { memcpy(b->data + iptr, buf, bytesToCopy); iptr += bytesToCopy; bytesCopied= bytesToCopy; } b->iptr= iptr; b->avail += bytesCopied; return bytesCopied; } inline int Buffer_read(Buffer *b, char *buf, int nbytes) { int optr= b->optr; int bytesToCopy= min(nbytes, Buffer_avail(b)); int headroom= b->size - optr; int bytesCopied= 0; assert(!(nbytes & 3)); if (bytesToCopy >= headroom) { memcpy(buf, b->data + optr, headroom); optr= 0; bytesToCopy -= headroom; bytesCopied += headroom; if (bytesToCopy) { memcpy(buf + bytesCopied, b->data, bytesToCopy); optr= bytesToCopy; bytesCopied += bytesToCopy; } } else { memcpy(buf, b->data + optr, bytesToCopy); optr += bytesToCopy; bytesCopied= bytesToCopy; } b->optr= optr; b->avail -= bytesCopied; return bytesCopied; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SoundPlugin/zzz/ring.h ================================================ // ring.h -- lightweight ring buffers for sound i/o // // Author: Ian.Piumarta@INRIA.Fr // // Last edited: // // Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors // listed elsewhere in this file. // All rights reserved. // // This file is part of Unix Squeak. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. typedef struct _ring { char **bufs; int bufCount; int bufSize; int iBuf; int oBuf; int nBufs; } ring; static ring *ring_new(int bufCount, int bufSize) { ring *r= (ring *)malloc(sizeof(ring)); if (r) { if ((r->bufs= (char **)malloc(bufCount * sizeof(char *)))) { // Would there be any advantage to allocating wired memory // via mmap() and mlock()? int i; for (i= 0; i < bufCount; ++i) if (!(r->bufs[i]= (char *)malloc(bufSize))) goto fail; r->bufCount = bufCount; r->bufSize = bufSize; r->iBuf = 0; r->oBuf = 0; r->nBufs = 0; return r; fail: printf("sound: could not allocate ring buffer memory\n"); while (i--) free(r->bufs[i]); free(r->bufs); } free(r); } return 0; } static void ring_delete(ring *r) { int i; assert(r); assert(r->bufs); for (i= 0; i < r->bufCount; ++i) { assert(r->bufs[i]); free(r->bufs[i]); } free(r->bufs); free(r); } // counting the number of filled buffers saves an awful lot of tedious // logic involving the front and back pointers, which in turn saves an // awful lot of tedious locking of mutexes. the incr/decrs are // effectively atomic and races will always fail conservatively (no // data for input when 1 buffer has just been filled by the ioproc, no // space for output when 1 buffer was just emptied by the ioproc) and // cause an immediate retry (since the reader/writer is always the // image -- the ioproc chugs along happily irrespective of the // apparent buffer state). static inline int ring_isEmpty(ring *r) { return r->nBufs == 0; } static inline int ring_freeBufs(ring *r) { return r->bufCount - r->nBufs; } static inline int ring_availBufs(ring *r) { return r->nBufs; } static inline int ring_freeBytes(ring *r) { return ring_freeBufs(r) * r->bufSize; } static inline int ring_availBytes(ring *r) { return ring_availBufs(r) * r->bufSize; } static inline void ring_oAdvance(ring *r) { assert(r->nBufs > 0); r->oBuf= (r->oBuf + 1) % r->bufCount; r->nBufs--; } static inline void ring_iAdvance(ring *r) { assert(r->nBufs < r->bufCount); r->iBuf= (r->iBuf + 1) % r->bufCount; r->nBufs++; } static inline char *ring_inputPointer(ring *r) { return r->bufs[r->iBuf]; } #if 0 static int ring_copyIn(ring *r, char *bytes, int size) { int freeBufs= ring_freeBufs(r); char *in= bytes; while (freeBufs-- && (size >= r->bufSize)) { memcpy(r->bufs[r->iBuf], bytes, r->bufSize); in += r->bufSize; size -= r->bufSize; ring_iAdvance(r); } return in - bytes; } #endif static int ring_copyOut(ring *r, char *bytes, int size) { int availBufs= ring_availBufs(r); char *out= bytes; while (availBufs-- && (size >= r->bufSize)) { memcpy(out, r->bufs[r->oBuf], r->bufSize); out += r->bufSize; size -= r->bufSize; ring_oAdvance(r); } return out - bytes; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/00README ================================================ WARNING: This code is obsolete. The new ThreadedFFIPlugin code requires little or no support code (see platforms/Cross/plugins/SqueakFFIPlugin). But it is complete only on x86 and so some of these files may be useful for reference on PPC. eem. 2009-11-30 =============== This directory contains support code for the Squeak FFI (foreign function interface) primitives. You should not even be here reading this unless (i) the configure script refuses to include FFI support in your build, or (ii) you want to try to make your FFI calls go lots faster by avoiding the use of libffi. About the FFI primitives ------------------------ Squeak can dynamically construct callouts to C code at runtime via one of two mechanisms, `apicall' and `cdecl'. The `cdecl' method constructs a `call interface description' (a data structure representing a function's signature) which is used by libffi [1] to construct and invoke a call to the foreign function. This method is portable but horribly slow. The `apicall' method constructs a stack frame on-the-fly which is used to invoke the foreign function directly. The `apicall' method is MUCH faster than `cdecl' (more than FOUR times faster) but relies on horribly platform-dependent code. Support for the `apicall' method is now available for a few platforms on Unix: - PowerPC and x86 using the SVr4 ABI (found on most GNU/Linux and BSD-like systems, with the notable exception of Darwin/MacOSX) - PowerPC using the Darwin ABI (similar to Mach) Testing your FFI support ------------------------ First run the script `ffi-test-config' (no arguments) which will look to see if your platform has support for the `apicall' method. If it prints `any-libffi' then you must either install libffi [1] before you can use the FFI primitives or implement the missing support [2]. If it prints anything else then it has found what it thinks is suitable support for your platform [3]. To run the test suite, just type `make' [4]. This will build a program called `main' that tries quite hard to break the FFI support code. If it fails using the built-in support code then you've found a bug in either the support code or the test code [5]. If you want to try again with libffi, then type: make clean make CPU=any ABI=libffi LIB=-lffi ./main If it fails again you've found a bug either in libffi (send bug reports to the relevant mailing list, not me) or in the test code. To tidy up afterwards, type `make clean'. Notes ----- [1] libffi is now part of gcc. If you need to install it, download just the contents of the top-level `gcc' directory and the `libffi' subdirectory. Then `cd' to `libffi' and type: ./configure make sudo make install If it breaks, you get to keep the pieces. [2] Figure out your canonical cpu and abi (os) name. Write a bunch of C code to create a stack frame in `${cpu}-${abi}.c' and the assembler `trampoline' that pused it and jumps to the destination function in the file `${cpu}-${abi}-asm.S'. This will allow the configure script to find and use your support. [3] If it doesn't find support code for your platform and you think it should (based on the cpu-abi variants available) then add your canonical host/os names to the tests in ffi-test-config. If the resulting program works, make similar changes in `acinclude.m4' so that the support is included in the Squeak VM. Then mail the modified files to me [5]. [4] By default the Makefile will try to figure this out for itself using rules similar to those in the configure script. You must be using GNU make for this to work. [5] Send bug reports and support code for new platforms to: ian.piumarta@squeakland.org ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/Makefile ================================================ # Makefile.in for FFIPlugin on Unix # # Author: ian.piumarta@inria.fr # # Last edited: 16 Jun 2010 by eliot miranda [make_cfg] [make_plg] TARGET= SqueakFFIPrims$a OBJS= SqueakFFIPrims$o sqFFIPlugin$o sqManualSurface$o sqFFITestFuncs$o XINCLUDES= [includes] $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) $(RANLIB) $(TARGET) [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/Makefile.in ================================================ # Makefile.in for FFIPlugin on Unix # # Author: ian.piumarta@inria.fr # # Last edited: Dec 1 2009 by eliot miranda [make_cfg] [make_plg] TARGET= SqueakFFIPrims$a OBJS= SqueakFFIPrims$o sqFFIPlugin$o sqManualSurface$o sqFFITestFuncs$o XINCLUDES= [includes] $(TARGET) : $(OBJS) Makefile $(LINK) $(TARGET) $(OBJS) $(RANLIB) $(TARGET) [make_targets] .force : ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/acinclude.m4 ================================================ AC_MSG_CHECKING([for FFI support]) FFI_DIR=${topdir}/platforms/unix/plugins/SqueakFFIPrims AC_ARG_WITH(ffi, [ --with-ffi=ffi use FFI support [default=auto]], [with_ffi="$withval"], [with_ffi="auto"]) if test "${with_ffi}" != "auto"; then ffi_cpu_abi="${with_ffi}" else ffi_cpu_abi=`${FFI_DIR}/ffi-config ${cfgdir} ${FFI_DIR} -cpu-abi` fi if test "${ffi_cpu_abi}" != "any-libffi"; then AC_MSG_RESULT([${ffi_cpu_abi}]) else AC_MSG_RESULT([requires libffi]) ffi_cpu_abi=any-libffi AC_CHECK_HEADER(ffi.h, AC_CHECK_LIB(ffi, ffi_call, AC_PLUGIN_USE_LIB(ffi), AC_PLUGIN_DISABLE), AC_PLUGIN_DISABLE) fi FFI_C=${ffi_cpu_abi} FFI_S=${ffi_cpu_abi}-asm FFI_O="${FFI_C}\$o ${FFI_S}\$o" AC_SUBST(FFI_DIR) AC_SUBST(FFI_C) AC_SUBST(FFI_S) AC_SUBST(FFI_O) ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/any-libffi-asm.S ================================================ ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/any-libffi.c ================================================ /**************************************************************************** * PROJECT: Squeak foreign function interface * FILE: sqUnixFFI.c * CONTENT: Unix support for the foreign function interface * * AUTHOR: Andreas Raab (ar) * ADDRESS: Walt Disney Imagineering, Glendale, CA * EMAIL: andreasr@wdi.disney.com * RCSID: $Id: any-libffi.c 966 2005-03-09 08:50:45Z piumarta $ * * NOTES: The Unix version of the FFI support code relies on libffi from * http://sourceware.cygnus.com/libffi/ * *****************************************************************************/ #include "sq.h" #include "sqFFI.h" #ifndef NO_FFI_SUPPORT #include #ifndef FFI_TYPE_STRUCT /* this is private in libffi-2 */ # define FFI_TYPE_STRUCT 13 #endif #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else extern struct VirtualMachine *interpreterProxy; # define primitiveFail() interpreterProxy->primitiveFail(); #endif #if 1 #define HAVE_LONGLONG #endif /* Check if HAVE_LONGLONG is defined (should be figured out by configure */ #ifdef HAVE_LONGLONG #define HAS_LONGLONG 1 #define LONGLONG long long #endif /* Error if LONGLONG is not defined */ #if HAS_LONGLONG #ifndef LONGLONG #error "You must define LONGLONG if HAS_LONGLONG is defined" #endif #endif /* Max number of arguments in call */ #define FFI_MAX_ARGS 32 static ffi_type* ffiTypes[FFI_MAX_ARGS]; static void* ffiArgs[FFI_MAX_ARGS]; static char ffiBytes[FFI_MAX_ARGS]; static short ffiShorts[FFI_MAX_ARGS]; static int ffiInts[FFI_MAX_ARGS]; static float ffiFloats[FFI_MAX_ARGS]; static double ffiDoubles[FFI_MAX_ARGS]; static int ffiArgIndex = 0; static ffi_type* ffiStructTypes[FFI_MAX_ARGS]; static int ffiStructIndex = 0; /* helpers */ #define CHECK_ARGS() if(ffiArgIndex >= FFI_MAX_ARGS) return primitiveFail(); #define PUSH_TYPE(type) { CHECK_ARGS(); ffiTypes[ffiArgIndex] = &type; } #define PUSH(where, what, type) { \ PUSH_TYPE(type); where[ffiArgIndex] = what; \ ffiArgs[ffiArgIndex] = (void*) (where + ffiArgIndex); \ ffiArgIndex++;\ } #define BARG_PUSH(value, type) PUSH(ffiBytes, value, type) #define SARG_PUSH(value, type) PUSH(ffiShorts, value, type) #define IARG_PUSH(value, type) PUSH(ffiInts, value, type) #define FARG_PUSH(value) PUSH(ffiFloats, value, ffi_type_float) #define DARG_PUSH(value) PUSH(ffiDoubles, value, ffi_type_double) #if HAS_LONGLONG static LONGLONG ffiLongLongs[FFI_MAX_ARGS]; #define LARG_PUSH(value, type) PUSH(ffiLongLongs, value, type) #endif /* The 64bit return value storage area - aligned by the C compiler */ static double returnValue; /* Storage area for large structure returns */ static ffi_type* structReturnType = NULL; static void *structReturnValue = NULL; /* The area for temporarily allocated strings */ static char *ffiTempStrings[FFI_MAX_ARGS]; /* The number of temporarily allocated strings */ static int ffiTempStringCount = 0; /*****************************************************************************/ /*****************************************************************************/ /* ffiInitialize: Announce that the VM is about to do an external function call. */ int ffiInitialize(void) { ffiArgIndex = 0; ffiTempStringCount = 0; ffiStructIndex = 0; structReturnType = NULL; structReturnValue = NULL; return 1; } /* ffiSupportsCallingConvention: Return true if the support code supports the given calling convention */ int ffiSupportsCallingConvention(int callType) { if(callType == FFICallTypeCDecl) return 1; return 0; } /* ffiAlloc: Allocate space from the external heap */ int ffiAlloc(int byteSize) { return (int)malloc(byteSize); } /* ffiFree: Free space from the external heap */ int ffiFree(int pointer) { if(pointer) free((void*)pointer); return 1; } /*****************************************************************************/ /*****************************************************************************/ int ffiPushSignedByte(int value) { BARG_PUSH((char)value, ffi_type_sint8); return 1; } int ffiPushUnsignedByte(int value) { BARG_PUSH((char)value, ffi_type_uint8); return 1; } int ffiPushSignedShort(int value) { SARG_PUSH((short)value, ffi_type_sint16); return 1; } int ffiPushUnsignedShort(int value) { SARG_PUSH((short)value, ffi_type_uint16); return 1; } int ffiPushSignedInt(int value) { IARG_PUSH(value, ffi_type_sint32); return 1; } int ffiPushUnsignedInt(int value) { IARG_PUSH(value, ffi_type_uint32); return 1; } int ffiPushSignedLongLong(int low, int high) { #if HAS_LONGLONG LONGLONG value = (((LONGLONG) high) << 32) | ((LONGLONG) (unsigned) low); LARG_PUSH(value, ffi_type_sint64); return 1; #else return primitiveFail(); #endif } int ffiPushUnsignedLongLong(int low, int high) { #if HAS_LONGLONG LONGLONG value = (((LONGLONG) high) << 32) | ((LONGLONG) (unsigned) low); LARG_PUSH(value, ffi_type_uint64); return 1; #else return primitiveFail(); #endif } int ffiPushSignedChar(int value) { BARG_PUSH(value, ffi_type_sint8); return 1; } int ffiPushUnsignedChar(int value) { BARG_PUSH(value, ffi_type_uint8); return 1; } int ffiPushBool(int value) { IARG_PUSH(value, ffi_type_uint8); return 1; } int ffiPushSingleFloat(double value) { FARG_PUSH((float)value); return 1; } int ffiPushDoubleFloat(double value) { DARG_PUSH(value); return 1; } ffi_type* ffiCreateType(int *structSpec, int structSize) { ffi_type *structType, **newTypes; int nTypes, i, typeSpec; /* count the number of atomic types we need to create */ nTypes = 0; for(i=0; isize = (*structSpec) & FFIStructSizeMask; structType->alignment = 4; structType->type = FFI_TYPE_STRUCT; structType->elements = newTypes; /* now go over the structure and fill in the fields */ nTypes = 0; for(i=0; i> FFIAtomicTypeShift) { case FFITypeBool: newTypes[nTypes++] = &ffi_type_uint8; break; case FFITypeUnsignedByte: newTypes[nTypes++] = &ffi_type_uint8; break; case FFITypeSignedByte: newTypes[nTypes++] = &ffi_type_sint8; break; case FFITypeUnsignedShort: newTypes[nTypes++] = &ffi_type_uint16; break; case FFITypeSignedShort: newTypes[nTypes++] = &ffi_type_sint16; break; case FFITypeUnsignedInt: newTypes[nTypes++] = &ffi_type_uint32; break; case FFITypeSignedInt: newTypes[nTypes++] = &ffi_type_sint32; break; case FFITypeUnsignedLongLong: newTypes[nTypes++] = &ffi_type_uint64; break; case FFITypeSignedLongLong: newTypes[nTypes++] = &ffi_type_sint64; break; case FFITypeUnsignedChar: newTypes[nTypes++] = &ffi_type_uint8; break; case FFITypeSignedChar: newTypes[nTypes++] = &ffi_type_sint8; break; case FFITypeSingleFloat: newTypes[nTypes++] = &ffi_type_float; break; case FFITypeDoubleFloat: newTypes[nTypes++] = &ffi_type_double; break; default: printf("Warning: unknown atomic type (%x) in ffiCreateTypes\n", typeSpec); free(newTypes); free(structType); return NULL; }; } newTypes[nTypes++] = NULL; return structType; } int ffiPushStructureOfLength(int pointer, int* structSpec, int structSize) { ffi_type *structType; if(pointer == 0) return primitiveFail(); CHECK_ARGS(); /* fail early on */ structType = ffiCreateType(structSpec, structSize); if(structType == NULL) return primitiveFail(); ffiStructTypes[ffiStructIndex++] = structType; ffiTypes[ffiArgIndex] = structType; ffiArgs[ffiArgIndex] = (void*) pointer; ffiArgIndex++; return 1; } int ffiPushPointer(int pointer) { IARG_PUSH(pointer, ffi_type_pointer); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; ptr = (char*) malloc(length+1); if(!ptr) return primitiveFail(); memcpy(ptr, (void*)srcIndex, length); ptr[length] = 0; ffiTempStrings[ffiTempStringCount++] = ptr; IARG_PUSH((int)ptr, ffi_type_pointer); return 1; } /*****************************************************************************/ /*****************************************************************************/ /* ffiCanReturn: Return true if the support code can return the given type. */ int ffiCanReturn(int *structSpec, int specSize) { int header = *structSpec; if(header & FFIFlagPointer) return 1; if(header & FFIFlagStructure) { int structSize = header & FFIStructSizeMask; structReturnType = ffiCreateType(structSpec, specSize); if(!structReturnType) return 0; if(structSize > 8) { structReturnValue = calloc(1,structSize); if(!structReturnValue) return 0; return 1; } } return 1; } /* ffiReturnFloatValue: Return the value from a previous ffi call with float return type. */ double ffiReturnFloatValue(void) { return returnValue; } /* ffiLongLongResultLow: Return the low 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultLow(void) { #if HAS_LONGLONG return (int) ( (*(LONGLONG*)&returnValue) & (LONGLONG)0xFFFFFFFFU); #else return 0; #endif } /* ffiLongLongResultHigh: Return the high 32bit from the 64bit result of a call to an external function */ int ffiLongLongResultHigh(void) { #if HAS_LONGLONG return (int) ( (*(LONGLONG*)&returnValue) >> 32); #else return 0; #endif } /* ffiStoreStructure: Store the structure result of a previous ffi call into the given address*/ int ffiStoreStructure(int address, int structSize) { if(structReturnValue) { memcpy((void*)address, (void*)structReturnValue, structSize); } else { memcpy((void*)address, (void*)&returnValue, structSize); } return 1; } /* ffiCleanup: Cleanup after a foreign function call has completed. The generic support code only frees the temporarily allocated strings. */ int ffiCleanup(void) { int i; for(i=0; ielements); free(ffiStructTypes[i]); ffiStructTypes[i]=NULL; } if(structReturnType) { free(structReturnType->elements); free(structReturnType); structReturnType = NULL; } if(structReturnValue) { free(structReturnValue); structReturnValue = NULL; } ffiTempStringCount = 0; ffiStructIndex = 0; return 1; } /*****************************************************************************/ /*****************************************************************************/ int ffiCallAddress(int fn, ffi_type *returnType, int atomicArgType) { ffi_cif cif; ffi_status result; int retVal; result = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, ffiArgIndex, returnType, ffiTypes); if(result != FFI_OK) return primitiveFail(); if(structReturnValue) { ffi_call(&cif, (void *)fn, (void *)structReturnValue, (void **)ffiArgs); return (int) structReturnValue; } ffi_call(&cif, (void *)fn, (void *)&returnValue, (void **)ffiArgs); retVal = *(int*)&returnValue; #ifdef FFI_MIPS_N32 /* Note: MIPS N32 ABI returns 64bit for integer/pointer whatever. This seems to be a bug in the fficall implementation. */ retVal = ((int*)(&returnValue))[1]; #endif /* Promote certain return types to integral size */ switch(atomicArgType) { case FFITypeUnsignedChar: case FFITypeUnsignedByte: retVal = *(unsigned char*) &retVal; break; case FFITypeSignedChar: case FFITypeSignedByte: retVal = *(signed char*) &retVal; break; case FFITypeUnsignedShort: retVal = *(unsigned short*) &retVal; break; case FFITypeSignedShort: retVal = *(signed short*) &retVal; break; case FFITypeSingleFloat: returnValue = *(float*)&returnValue; break; } return retVal; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return ffiCallAddress(fn, &ffi_type_pointer,-1); } int ffiCallAddressOfWithStructReturn(int fn, int callType, int *structSpec, int specSize) { if(!structReturnType) return primitiveFail(); return ffiCallAddress(fn, structReturnType,-1); } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { ffi_type *returnType; int atomicType; atomicType = (typeSpec & FFIAtomicTypeMask) >> FFIAtomicTypeShift; switch(atomicType) { case FFITypeVoid: returnType = &ffi_type_void; break; case FFITypeBool: returnType = &ffi_type_uint8; break; case FFITypeUnsignedByte: returnType = &ffi_type_uint8; break; case FFITypeSignedByte: returnType = &ffi_type_sint8; break; case FFITypeUnsignedShort: returnType = &ffi_type_uint16; break; case FFITypeSignedShort: returnType = &ffi_type_sint16; break; case FFITypeUnsignedInt: returnType = &ffi_type_uint32; break; case FFITypeSignedInt: returnType = &ffi_type_sint32; break; case FFITypeUnsignedLongLong: returnType = &ffi_type_uint64; break; case FFITypeSignedLongLong: returnType = &ffi_type_sint64; break; case FFITypeUnsignedChar: returnType = &ffi_type_uint8; break; case FFITypeSignedChar: returnType = &ffi_type_sint8; break; case FFITypeSingleFloat: returnType = &ffi_type_float; break; case FFITypeDoubleFloat: returnType = &ffi_type_double; break; default: return primitiveFail(); } return ffiCallAddress(fn, returnType, atomicType); } #if defined(FFI_TEST) void ffiDoAssertions(void) {} #endif #endif /* NO_FFI_SUPPORT */ ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/config.cmake ================================================ SET (USE_LIBFFI) IF (OPT_without-ffi) PLUGIN_DISABLE () ELSE () IF (vm-host-cpu STREQUAL "powerpc" OR vm-host-cpu STREQUAL "ppc") SET (cpu ppc) ELSEIF (vm-host-cpu MATCHES "i[3456789]86") SET (cpu x86) ELSEIF (vm-host-cpu STREQUAL "x86_64" AND CMAKE_ARCH_FLAGS STREQUAL "-m32") SET (cpu x86) ELSE () SET (USE_LIBFFI 1) ENDIF () IF (vm-host-os STREQUAL "linux") SET (abi sysv) ELSEIF (vm-host-os MATCHES "darwin.*") SET (abi darwin) ELSE () SET (USE_LIBFFI 1) ENDIF () IF (USE_LIBFFI OR NOT EXISTS "${unix}/plugins/${plugin}/${cpu}-${abi}.c" OR NOT EXISTS "${unix}/plugins/${plugin}/${cpu}-${abi}-asm.S") SET (cpu any) SET (abi libffi) PLUGIN_MESSAGE ("${cpu}-${abi}") PLUGIN_FIND_PACKAGE (LIBFFI libffi) IF (NOT LIBFFI_FOUND) CHECK_INCLUDE_FILE (ffi.h HAVE_FFI_H) CHECK_INCLUDE_FILE (ffi/ffi.h HAVE_FFI_FFI_H) IF (NOT HAVE_FFI_H AND NOT HAVE_FFI_FFI_H) PLUGIN_DISABLE () ELSE () PLUGIN_REQUIRE_LIBRARY (FFI ffi) ENDIF () ENDIF () ENDIF () IF (EXISTS "${src}/plugins/${plugin}/${plugin}.c") SET (SQFFIC "${src}/plugins/${plugin}/${plugin}.c") ELSEIF (EXISTS "${src}/vm/intplugins/${plugin}/${plugin}.c") SET (SQFFIC "${src}/vm/intplugins/${plugin}/${plugin}.c") ELSE () PLUGIN_DISABLE () ENDIF () ENABLE_LANGUAGE (ASM) PLUGIN_SOURCES ("${cross}/plugins/${plugin}/sqManualSurface.c ${SQFFIC} ${unix}/plugins/${plugin}/${cpu}-${abi}.c ${unix}/plugins/${plugin}/${cpu}-${abi}-asm.S") IF (CMAKE_COMPILER_IS_GNUCC) SET (CMAKE_ASM_COMPILER "${CMAKE_C_COMPILER}") SET (CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -c") ENDIF (CMAKE_COMPILER_IS_GNUCC) ENDIF () CONFIG_DEFINE (HAVE_FFI_H) CONFIG_DEFINE (HAVE_FFI_FFI_H) ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ffi-config ================================================ #!/bin/sh # # ffi-config [cfgdir] [options...] # # -cpu print the supported cpu name or `any' # -abi print the supported abu name or `libffi' # -lib print nothing if supported, otherwise `-lffi' # -query exit with status 0 if supported, 1 if libffi required cfgdir=../../config if [ $# -gt 0 ]; then case $1 in -*) ;; *) cfgdir=$1; shift;; esac fi ffidir=. if [ $# -gt 0 ]; then case $1 in -*) ;; *) ffidir=$1; shift;; esac fi guess=`${cfgdir}/config.guess` host=`${cfgdir}/config.sub ${guess}` cpu=`echo ${host} | sed 's/-.*//'` abi=`echo ${host} | sed 's/[^-]*-[^-]*-//;s/-.*//'` lib= case ${cpu} in powerpc|ppc) cpu=ppc;; i[3456789]86) cpu=x86;; *) cpu=any;; esac case ${abi} in linux) abi=sysv;; freebsd) abi=sysv;; darwin*) abi=darwin;; *) abi=libffi; lib="-lffi";; esac if [ ! -f ${ffidir}/${cpu}-${abi}.c ] || [ ! -f ${ffidir}/${cpu}-${abi}-asm.S ]; then cpu=any abi=libffi lib="-lffi" fi if [ ! -f ${ffidir}/${cpu}-${abi}.c ] || [ ! -f ${ffidir}/${cpu}-${abi}-asm.S ]; then echo "Could not find ${cpu}-${abi}.c and ${cpu}-${abi}-asm.S" >&2 exit 1 fi if [ $# -eq 0 ]; then echo "${cpu}-${abi}" "${lib}" else while [ $# -gt 0 ]; do case $1 in -cpu) echo ${cpu};; -abi) echo ${abi};; -lib) echo ${lib};; -cpu-abi) echo ${cpu}-${abi};; -query) if [ ${abi} = "libffi" ]; then exit 1; else exit 0; fi;; *) echo "$0: I don't understand \`$1'" >&1; exit 1;; esac shift done fi exit 0 ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ffi-test-main.c ================================================ /* ffi-test-main.c -- try hard to break the FFI from C * * Author: Ian.Piumarta@INRIA.Fr * * Based on a similar test suite in libffi, which contains the following text... * * Copyright (c) 1996, 1997, 1998, 2002, 2003 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * ``Software''), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include "sqFFI.h" #if 0 # define DPRINTF(ARGS) printf ARGS # define puts(ARG) puts(ARG) #else # define DPRINTF(ARGS) # define puts(ARG) #endif #if 1 # define long_double double # define Lf "f" #else # define long_double long double # define Lf "Lf" #endif #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 static int failed= 0; static int fail(char *file, int line) { fprintf(stderr, "%s: failed at line %d\n", file, line); ++failed; //exit(EXIT_FAILURE); return 0; } #define MAX_ARGS 256 static size_t my_strlen(char *s) { return strlen(s); } static int promotion(signed char sc, signed short ss, unsigned char uc, unsigned short us) { int r= (int)sc + (int)ss + (int)uc + (int)us; return r; } static signed char return_sc(signed char sc) { return sc; } static unsigned char return_uc(unsigned char uc) { return uc; } static long long return_ll(long long ll) { return ll; } static int floating(int a, float b, double c, long_double d, int e) { int i; DPRINTF(("%d %f %f %"Lf" %d\n", a, (double)b, c, d, e)); i= (int)((float)a/b + ((float)c/(float)d)); return i; } static float many(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14, float f15) { DPRINTF(("%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", (double)f1, (double)f2, (double)f3, (double)f4, (double)f5, (double)f6, (double)f7, (double)f8, (double)f9, (double)f10, (double)f11, (double)f12, (double)f13, (double)f14, (double)f15)); return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12+f13/f14) * f15); } static double dblit(float f) { return f/3.0; } static long_double ldblit(float f) { return (long_double)(((long_double)f)/ (long_double)3.0); } #define TYPE(T,S) ((FFIType##T << FFIAtomicTypeShift) | (S) | FFIFlagAtomic) typedef struct { unsigned char uc; double d; unsigned int ui; } test_structure_1; static int spec_structure_1[]= { FFIFlagStructure | sizeof(test_structure_1), TYPE(UnsignedChar,4), TYPE(DoubleFloat,8), TYPE(UnsignedInt,4) }; static test_structure_1 struct1(test_structure_1 ts) { DPRINTF(("%d %f %d\n", ts.uc, ts.d, ts.ui)); ts.uc++; ts.d--; ts.ui++; return ts; } typedef struct { double d1; double d2;} test_structure_2; static int spec_structure_2[]= { FFIFlagStructure | sizeof(test_structure_2), TYPE(DoubleFloat,8), TYPE(DoubleFloat,8) }; static test_structure_2 struct2(test_structure_2 ts) { ts.d1--; ts.d2--; return ts; } typedef struct { int si; } test_structure_3; static int spec_structure_3[]= { FFIFlagStructure | sizeof(test_structure_3), TYPE(SignedInt,4) }; static test_structure_3 struct3(test_structure_3 ts) { ts.si= -(ts.si*2); return ts; } typedef struct { unsigned ui1; unsigned ui2; unsigned ui3; } test_structure_4; static int spec_structure_4[]= { FFIFlagStructure | sizeof(test_structure_4), TYPE(UnsignedInt,4), TYPE(UnsignedInt,4), TYPE(UnsignedInt,4) }; static test_structure_4 struct4(test_structure_4 ts) { ts.ui3= ts.ui1 * ts.ui2 * ts.ui3; return ts; } typedef struct { char c1; char c2; } test_structure_5; static int spec_structure_5[]= { FFIFlagStructure | sizeof(test_structure_5), TYPE(SignedChar,1), TYPE(SignedChar,1) }; static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2) { DPRINTF(("%d %d %d %d\n", ts1.c1, ts1.c2, ts2.c1, ts2.c2)); ts1.c1 += ts2.c1; ts1.c2 -= ts2.c2; return ts1; } typedef struct { float f; double d; } test_structure_6; static int spec_structure_6[]= { FFIFlagStructure | sizeof(test_structure_6), TYPE(SingleFloat,4), TYPE(DoubleFloat,8) }; static test_structure_6 struct6 (test_structure_6 ts) { ts.f += 1; ts.d += 1; return ts; } typedef struct { float f1; float f2; double d; } test_structure_7; static int spec_structure_7[]= { FFIFlagStructure | sizeof(test_structure_7), TYPE(SingleFloat,4), TYPE(SingleFloat,4), TYPE(DoubleFloat,8) }; static test_structure_7 struct7 (test_structure_7 ts) { ts.f1 += 1; ts.f2 += 1; ts.d += 1; return ts; } typedef struct { float f1; float f2; float f3; float f4; } test_structure_8; static int spec_structure_8[]= { FFIFlagStructure | sizeof(test_structure_8), TYPE(SingleFloat,4), TYPE(SingleFloat,4), TYPE(SingleFloat,4), TYPE(SingleFloat,4) }; static test_structure_8 struct8 (test_structure_8 ts) { ts.f1 += 1; ts.f2 += 1; ts.f3 += 1; ts.f4 += 1; return ts; } typedef struct { float f; int i; } test_structure_9; static int spec_structure_9[]= { FFIFlagStructure | sizeof(test_structure_9), TYPE(SingleFloat,4), TYPE(SignedInt,4) }; static test_structure_9 struct9 (test_structure_9 ts) { ts.f += 1; ts.i += 1; return ts; } #define SPEC(S) spec_##S, (sizeof(spec_##S) / sizeof(int)) #define GO(T,F) ffiCallAddressOfWithReturnType((int)(F), FFICallTypeCDecl, \ (T) << FFIAtomicTypeShift) #define GOS(S,F) ffiCallAddressOfWithStructReturn((int)(F), FFICallTypeCDecl, SPEC(S)) void ctests(void) { CHECK(sizeof(char) == 1); CHECK(sizeof(short) == 2); CHECK(sizeof(int) == 4); CHECK(sizeof(long) == 4); CHECK(sizeof(long long) == 8); CHECK(sizeof(float) == 4); CHECK(sizeof(double) == 8); CHECK(sizeof(long_double) == 8); //xxx BOGUS BOGUS BOGUS BOGUS BOGUS puts("long long tests..."); { long long ll, rll; for (ll= 0LL; ll < 100LL; ++ll) { ffiInitialize(); ffiPushSignedLongLong(ll % 0x100000000, ll / 0x100000000); GO(FFITypeSignedLongLong, return_ll); rll= ffiLongLongResultHigh() * 0x100000000LL + ffiLongLongResultLow(); ffiCleanup(); DPRINTF(("%lld %lld\n", ll, rll)); CHECK(rll == ll); } for (ll= 55555555555000LL; ll < 55555555555100LL; ll++) { ffiInitialize(); ffiPushSignedLongLong(ll % 0x100000000, ll / 0x100000000); GO(FFITypeSignedLongLong, return_ll); rll= ffiLongLongResultHigh() * 0x100000000LL + ffiLongLongResultLow(); ffiCleanup(); CHECK(rll == ll); } } puts("char tests..."); { signed char sc; unsigned char uc; int rint; for (sc= (signed char)-127; sc < (signed char)127; ++sc) { ffiInitialize(); ffiPushSignedChar(sc); rint= GO(FFITypeSignedInt, return_sc); ffiCleanup(); CHECK(rint == (int)sc); } for (uc= (unsigned char)'\x00'; uc < (unsigned char)'\xff'; ++uc) { ffiInitialize(); ffiPushUnsignedChar(uc); rint= GO(FFITypeSignedInt, return_uc); ffiCleanup(); CHECK(rint == (int)uc); } } puts("long double tests..."); { float f= 3.14159; long_double ld; DPRINTF(("%"Lf"\n", ldblit(f))); ld= 666; ffiInitialize(); ffiPushSingleFloat(f); GO(FFITypeDoubleFloat, ldblit); ld= ffiReturnFloatValue(); ffiCleanup(); DPRINTF(("%"Lf", %"Lf", %"Lf", %"Lf"\n", ld, ldblit(f), ld - ldblit(f), (long_double)LDBL_EPSILON)); /* These are not always the same!! Check for a reasonable delta */ CHECK(ld - ldblit(f) < LDBL_EPSILON); } puts("float arg tests..."); { int si1= 6; float f= 3.14159; double d= (double)1.0/(double)3.0; long_double ld= 2.71828182846L; int si2= 10; int rint; floating(si1, f, d, ld, si2); ffiInitialize(); ffiPushSignedInt(si1); ffiPushSingleFloat(f); ffiPushDoubleFloat(d); ffiPushDoubleFloat(ld); ffiPushSignedInt(si2); rint= GO(FFITypeSignedInt, floating); ffiCleanup(); DPRINTF(("%d vs %d\n", (int)rint, floating(si1, f, d, ld, si2))); CHECK(rint == floating(si1, f, d, ld, si2)); } puts("double return tests..."); { float f= 3.14159; double d; ffiInitialize(); ffiPushSingleFloat(f); GO(FFITypeDoubleFloat, dblit); d= ffiReturnFloatValue(); ffiCleanup(); CHECK(d - dblit(f) < DBL_EPSILON); } puts("strlen tests..."); { char *s= "a"; int rint; ffiInitialize(); ffiPushPointer((int)s); rint= GO(FFITypeSignedInt, my_strlen); ffiCleanup(); CHECK(rint == 1); s= "1234567"; ffiInitialize(); ffiPushPointer((int)s); rint= GO(FFITypeSignedInt, my_strlen); ffiCleanup(); CHECK(rint == 7); s= "1234567890123456789012345"; ffiInitialize(); ffiPushPointer((int)s); rint= GO(FFITypeSignedInt, my_strlen); ffiCleanup(); CHECK(rint == 25); } puts("many arg tests..."); { unsigned long ul; float f, ff; float fa[15]; for (ul= 0; ul < 15; ++ul) fa[ul]= (float)ul; ff= many(fa[0], fa[1], fa[2], fa[3], fa[4], fa[5], fa[6], fa[7], fa[8], fa[9], fa[10], fa[11], fa[12], fa[13], fa[14]); ffiInitialize(); for (ul= 0; ul < 15; ++ul) ffiPushSingleFloat(fa[ul]); GO(FFITypeSingleFloat, many); f= ffiReturnFloatValue(); ffiCleanup(); CHECK(f - ff < FLT_EPSILON); } puts("promotion tests..."); { signed char sc; unsigned char uc; signed short ss; unsigned short us; int rint; for (sc= (signed char)-127; sc <= (signed char)120; sc += 1) for (ss= -30000; ss <= 30000; ss += 10000) for (uc= (unsigned char)0; uc <= (unsigned char)200; uc += 20) for (us= 0; us <= 60000; us += 10000) { ffiInitialize(); ffiPushSignedChar(sc); ffiPushSignedShort(ss); ffiPushUnsignedChar(uc); ffiPushUnsignedShort(us); rint= GO(FFITypeSignedInt, promotion); ffiCleanup(); CHECK((int)rint == (signed char)sc + (signed short)ss + (unsigned char)uc + (unsigned short)us); } } puts("struct tests..."); { test_structure_1 ts1_arg, ts1_result; ts1_arg.uc= '\x01'; ts1_arg.d= 3.14159; ts1_arg.ui= 555; ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_1))); ffiPushStructureOfLength((int)&ts1_arg, SPEC(structure_1)); GOS(structure_1, struct1); ffiStoreStructure((int)&ts1_result, sizeof(ts1_result)); ffiCleanup(); DPRINTF(("%d %g\n", ts1_result.ui, ts1_result.d)); CHECK(ts1_result.ui == 556); CHECK(ts1_result.d == 3.14159 - 1); } { test_structure_2 ts2_arg, ts2_result; ts2_arg.d1= 5.55; ts2_arg.d2= 6.66; DPRINTF(("%g\n", ts2_result.d1)); /*xxx this is junk!*/ DPRINTF(("%g\n", ts2_result.d2)); ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_2))); ffiPushStructureOfLength((int)&ts2_arg, SPEC(structure_2)); GOS(structure_2, struct2); ffiStoreStructure((int)&ts2_result, sizeof(ts2_result)); ffiCleanup(); DPRINTF(("%g\n", ts2_result.d1)); DPRINTF(("%g\n", ts2_result.d2)); CHECK(ts2_result.d1 == 5.55 - 1); CHECK(ts2_result.d2 == 6.66 - 1); } { int compare_value; test_structure_3 ts3_arg, ts3_result; ts3_arg.si= -123; compare_value= ts3_arg.si; ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_3))); ffiPushStructureOfLength((int)&ts3_arg, SPEC(structure_3)); GOS(structure_3, struct3); ffiStoreStructure((int)&ts3_result, sizeof(ts3_result)); ffiCleanup(); DPRINTF(("%d %d\n", ts3_result.si, -(compare_value*2))); CHECK(ts3_result.si == -(ts3_arg.si*2)); } { test_structure_4 ts4_arg, ts4_result; ts4_arg.ui1= 2; ts4_arg.ui2= 3; ts4_arg.ui3= 4; ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_4))); ffiPushStructureOfLength((int)&ts4_arg, SPEC(structure_4)); GOS(structure_4, struct4); ffiStoreStructure((int)&ts4_result, sizeof(ts4_result)); ffiCleanup(); CHECK(ts4_result.ui3 == 2U * 3U * 4U); } { test_structure_5 ts5_arg1, ts5_arg2, ts5_result; ts5_arg1.c1= 2; ts5_arg1.c2= 6; ts5_arg2.c1= 5; ts5_arg2.c2= 3; struct5(ts5_arg1, ts5_arg2); ts5_arg1.c1= 2; ts5_arg1.c2= 6; ts5_arg2.c1= 5; ts5_arg2.c2= 3; ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_5))); ffiPushStructureOfLength((int)&ts5_arg1, SPEC(structure_5)); ffiPushStructureOfLength((int)&ts5_arg2, SPEC(structure_5)); GOS(structure_5, struct5); ffiStoreStructure((int)&ts5_result, sizeof(ts5_result)); ffiCleanup(); DPRINTF(("%d %d\n", ts5_result.c1, ts5_result.c2)); CHECK(ts5_result.c1 == 7 && ts5_result.c2 == 3); } { test_structure_6 ts6_arg, ts6_result; ts6_arg.f= 5.55f; ts6_arg.d= 6.66; DPRINTF(("%g\n", ts6_arg.f)); DPRINTF(("%g\n", ts6_arg.d)); ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_6))); ffiPushStructureOfLength((int)&ts6_arg, SPEC(structure_6)); GOS(structure_6, struct6); ffiStoreStructure((int)&ts6_result, sizeof(ts6_result)); ffiCleanup(); DPRINTF(("%g\n", ts6_result.f)); DPRINTF(("%g\n", ts6_result.d)); CHECK(ts6_result.f == 5.55f + 1); CHECK(ts6_result.d == 6.66 + 1); } { test_structure_7 ts7_arg, ts7_result; ts7_arg.f1= 5.55f; ts7_arg.f2= 55.5f; ts7_arg.d= 6.66; DPRINTF(("%g\n", ts7_arg.f1)); DPRINTF(("%g\n", ts7_arg.f2)); DPRINTF(("%g\n", ts7_arg.d)); ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_7))); ffiPushStructureOfLength((int)&ts7_arg, SPEC(structure_7)); GOS(structure_7, struct7); ffiStoreStructure((int)&ts7_result, sizeof(ts7_result)); ffiCleanup(); DPRINTF(("%g\n", ts7_result.f1)); DPRINTF(("%g\n", ts7_result.f2)); DPRINTF(("%g\n", ts7_result.d)); CHECK(ts7_result.f1 == 5.55f + 1); CHECK(ts7_result.f2 == 55.5f + 1); CHECK(ts7_result.d == 6.66 + 1); } { test_structure_8 ts8_arg, ts8_result; ts8_arg.f1= 5.55f; ts8_arg.f2= 55.5f; ts8_arg.f3= -5.55f; ts8_arg.f4= -55.5f; DPRINTF(("%g\n", ts8_arg.f1)); DPRINTF(("%g\n", ts8_arg.f2)); DPRINTF(("%g\n", ts8_arg.f3)); DPRINTF(("%g\n", ts8_arg.f4)); ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_8))); ffiPushStructureOfLength((int)&ts8_arg, SPEC(structure_8)); GOS(structure_8, struct8); ffiStoreStructure((int)&ts8_result, sizeof(ts8_result)); ffiCleanup(); DPRINTF(("%g\n", ts8_result.f1)); DPRINTF(("%g\n", ts8_result.f2)); DPRINTF(("%g\n", ts8_result.f3)); DPRINTF(("%g\n", ts8_result.f4)); CHECK(ts8_result.f1 == 5.55f + 1); CHECK(ts8_result.f2 == 55.5f + 1); CHECK(ts8_result.f3 == -5.55f + 1); CHECK(ts8_result.f4 == -55.5f + 1); } { test_structure_9 ts9_arg, ts9_result; ts9_arg.f= 5.55f; ts9_arg.i= 5; DPRINTF(("%g\n", ts9_arg.f)); DPRINTF(("%d\n", ts9_arg.i)); ffiInitialize(); CHECK(ffiCanReturn(SPEC(structure_9))); ffiPushStructureOfLength((int)&ts9_arg, SPEC(structure_9)); GOS(structure_9, struct9); ffiStoreStructure((int)&ts9_result, sizeof(ts9_result)); ffiCleanup(); DPRINTF(("%g\n", ts9_result.f)); DPRINTF(("%d\n", ts9_result.i)); CHECK(ts9_result.f == 5.55f + 1); CHECK(ts9_result.i == 5 + 1); } } #define C(C) ffiPushSignedChar(C) #define S(S) ffiPushSignedShort(S) #define I(I) ffiPushSignedInt(I) #define F(F) ffiPushSingleFloat(F) #define D(D) ffiPushDoubleFloat(D) #define P(P) ffiPushPointer(P) #define GO(T,F) ffiCallAddressOfWithReturnType((int)(F), FFICallTypeCDecl, \ (T) << FFIAtomicTypeShift) static void assert(int pred, const char *gripe) { if (pred) return; fprintf(stderr, "%s\n", gripe); exit(1); } #include "ffi-test.h" void stests(void) { double d; char *s; ffiInitialize(); C('A'); C(65); C(65); C(1); GO(FFITypeSignedInt, ffiTestChars); ffiCleanup(); ffiInitialize(); S('A'); S(65); S(65); S(1); GO(FFITypeSignedInt, ffiTestShorts); ffiCleanup(); ffiInitialize(); I('A'); I(65); I(65); I(1); GO(FFITypeSignedInt, ffiTestInts); ffiCleanup(); ffiInitialize(); F(65); F(65.0); GO(FFITypeSingleFloat, ffiTestFloats); d= ffiReturnFloatValue(); ffiCleanup(); DPRINTF(("%f\n", d)); assert(d == 130.0, "single floats don't work"); ffiInitialize(); D(41.0L); D(1); GO(FFITypeDoubleFloat, ffiTestDoubles); d= ffiReturnFloatValue(); ffiCleanup(); assert(d == 42.0, "problem with doubles"); /*xxx this does not really test strings, but the corresponding call in the image's FFITester does */ ffiInitialize(); P((int)"Hello World!"); s= (char *)ffiCallAddressOfWithPointerReturn((int)ffiPrintString, FFICallTypeCDecl); ffiCleanup(); assert(!strcmp(s, "Hello World!"), "Problem with strings"); { int spec[]= { FFIFlagStructure | 8, TYPE(SignedInt,4), TYPE(SignedInt,4) }; ffiTestPoint2 pt1= { 1, 2 }, pt2= { 3, 4 }, pt3; ffiInitialize(); assert(ffiCanReturn((int *)&spec, 3), "cannot return struct"); ffiPushStructureOfLength((int)&pt1, (int *)&spec, 3); ffiPushStructureOfLength((int)&pt2, (int *)&spec, 3); ffiCallAddressOfWithStructReturn((int)ffiTestStruct64, FFICallTypeCDecl, spec, 3); ffiStoreStructure((int)&pt3, sizeof(pt3)); ffiCleanup(); assert((pt3.x == 4) && (pt3.y == 6), "Problem passing 64bit structures"); } { int spec[]= { FFIFlagStructure | 16, TYPE(SignedInt,4), TYPE(SignedInt,4), TYPE(SignedInt,4), TYPE(SignedInt,4) }; ffiTestPoint4 pt1= { 1, 2, 3, 4 }, pt2= { 5, 6, 7, 8 }, pt3= { 9, 10, 11, 12 }; ffiInitialize(); assert(ffiCanReturn((int *)&spec, 3), "cannot return struct"); ffiPushStructureOfLength((int)&pt1, (int *)&spec, 5); ffiPushStructureOfLength((int)&pt2, (int *)&spec, 5); ffiPushStructureOfLength((int)&pt3, (int *)&spec, 5); ffiCallAddressOfWithStructReturn((int)ffiTestStructBig, FFICallTypeCDecl, spec, 5); ffiStoreStructure((int)&pt3, sizeof(pt3)); ffiCleanup(); assert((pt3.x == 6) && (pt3.y == 8) && (pt3.z == 10) && (pt3.w == 12), "Problem passing large structures"); } { ffiTestPoint4 pt1= { 1, 2, 3, 4 }, pt2= { 5, 6, 7, 8 }, *pt3; ffiInitialize(); ffiPushPointer((int)&pt1); ffiPushPointer((int)&pt2); pt3= (ffiTestPoint4 *) ffiCallAddressOfWithPointerReturn((int)ffiTestPointers, 0); ffiCleanup(); assert((pt3->x == 6) && (pt3->y == 8) && (pt3->z == 10) && (pt3->w == 12), "Problem passing pointers"); free((void *)pt3); } } extern void ffiDoAssertions(void); int main() { # define report(who) \ printf("%s %s (%d failed)\n", failed ? "FAILED" : "passed", who, failed); failed= 0; ffiDoAssertions(); report("ffi assertions"); failed= 0; stests(); report("FFITester support check"); failed= 0; ctests(); report("C test suite"); return 0; } ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ffi-test-sq.h ================================================ #include #include #include #define EXPORT(T) T ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ffi-test.c ================================================ /* last edited: 2003-01-29 21:48:36 by piumarta on emilia.inria.fr */ #if !defined(NO_FFI_TEST) #include #include #if !defined(LONGLONG) # define LONGLONG long long #endif #if 0 # define DPRINTF(ARGS) printf ARGS #else # define DPRINTF(ARGS) #endif #include "ffi-test.h" char ffiTestChars(char c1, char c2, char c3, char c4) { DPRINTF(("4 characters came in as\nc1 = %c (%x)\nc2 = %c (%x)\nc3 = %c (%x)\nc4 = %c (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4)); return 'C'; } short ffiTestShorts(short c1, short c2, short c3, short c4) { DPRINTF(("4 shorts came in as\ns1 = %d (%x)\ns2 = %d (%x)\ns3 = %d (%x)\ns4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4)); return -42; } int ffiTestInts(int c1, int c2, int c3, int c4) { DPRINTF(("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4)); return 42; } int ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8) { DPRINTF(("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\ni5 = %d (%x)\ni6 = %d (%x)\ni7 = %d (%x)\ni8 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4, c5, c5, c6, c6, c7, c7, c8, c8)); return 42; } int ffiTestInts9(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8, int c9) { DPRINTF(("4 ints came in as\ni1 = %d (%x)\ni2 = %d (%x)\ni3 = %d (%x)\ni4 = %d (%x)\ni5 = %d (%x)\ni6 = %d (%x)\ni7 = %d (%x)\ni8 = %d (%x)\ni9 = %d (%x)\n", c1, c1, c2, c2, c3, c3, c4, c4, c5, c5, c6, c6, c7, c7, c8, c8, c9, c9)); return 42; } float ffiTestFloats(float f1, float f2) { DPRINTF(("The two floats are %f and %f\n", (double)f1, (double)f2)); return (float) (f1 + f2); } float ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7) { DPRINTF(("The 7 floats are %f %f %f %f %f %f %f\n", (double)f1, (double)f2, (double)f3, (double)f4, (double)f5, (double)f6, (double)f7)); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7); } float ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13) { DPRINTF(("The 13 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f\n", (double)f1, (double)f2, (double)f3, (double)f4, (double)f5, (double)f6, (double)f7, (double)f8, (double)f9, (double)f10, (double)f11, (double)f12, (double)f13)); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13); } float ffiTestFloats15(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14, float f15) { DPRINTF(("The 15 floats are %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", (double)f1, (double)f2, (double)f3, (double)f4, (double)f5, (double)f6, (double)f7, (double)f8, (double)f9, (double)f10, (double)f11, (double)f12, (double)f13, (double)f14, (double)f15)); return (float) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15); } double ffiTestDoubles(double d1, double d2) { DPRINTF(("The two doubles are %f and %f\n", d1, d2)); return d1+d2; } double ffiTestDoubles15(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15) { DPRINTF(("The 15 doubles are %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15)); return (double) (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15); } char *ffiPrintString(char *string) { DPRINTF(("%s\n", string)); return string; } ffiTestPoint2 ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2) { ffiTestPoint2 result; DPRINTF(("pt1.x = %d\npt1.y = %d\npt2.x = %d\npt2.y = %d\n", pt1.x, pt1.y, pt2.x, pt2.y)); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; return result; } ffiTestPoint4 ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2) { ffiTestPoint4 result; DPRINTF(("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1.x, pt1.y, pt1.z, pt1.w)); DPRINTF(("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2.x, pt2.y, pt2.z, pt2.w)); result.x = pt1.x + pt2.x; result.y = pt1.y + pt2.y; result.z = pt1.z + pt2.z; result.w = pt1.w + pt2.w; return result; } ffiTestPoint4 *ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2) { ffiTestPoint4 *result; DPRINTF(("pt1.x = %d\npt1.y = %d\npt1.z = %d\npt1.w = %d\n", pt1->x, pt1->y, pt1->z, pt1->w)); DPRINTF(("pt2.x = %d\npt2.y = %d\npt2.z = %d\npt2.w = %d\n", pt2->x, pt2->y, pt2->z, pt2->w)); result = (ffiTestPoint4*) malloc(sizeof(ffiTestPoint4)); result->x = pt1->x + pt2->x; result->y = pt1->y + pt2->y; result->z = pt1->z + pt2->z; result->w = pt1->w + pt2->w; return result; } LONGLONG ffiTestLongLong(LONGLONG i1, LONGLONG i2) { DPRINTF(("longlong %lld %lld\n", i1, i2)); return i1 + i2; } #endif /* !NO_FFI_TEST */ ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ffi-test.h ================================================ typedef struct ffiTestPoint2 { int x; int y; } ffiTestPoint2; typedef struct ffiTestPoint4 { int x; int y; int z; int w; } ffiTestPoint4; extern char ffiTestChars(char c1, char c2, char c3, char c4); extern short ffiTestShorts(short c1, short c2, short c3, short c4); extern int ffiTestInts(int c1, int c2, int c3, int c4); extern int ffiTestInts8(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8); extern int ffiTestInts9(int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8, int c9); extern float ffiTestFloats(float f1, float f2); extern float ffiTestFloats7(float f1, float f2, float f3, float f4, float f5, float f6, float f7); extern float ffiTestFloats13(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13); extern float ffiTestFloats15(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, float f14, float f15); extern double ffiTestDoubles(double d1, double d2); extern double ffiTestDoubles15(double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8, double f9, double f10, double f11, double f12, double f13, double f14, double f15); extern char *ffiPrintString(char *string); extern ffiTestPoint2 ffiTestStruct64(ffiTestPoint2 pt1, ffiTestPoint2 pt2); extern ffiTestPoint4 ffiTestStructBig(ffiTestPoint4 pt1, ffiTestPoint4 pt2); extern ffiTestPoint4 *ffiTestPointers(ffiTestPoint4 *pt1, ffiTestPoint4 *pt2); extern long long ffiTestLongLong(long long i1, long long i2); ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ppc-darwin-asm.S ================================================ /* ppc-sysv-asm.S -- PowerPC FFI trampoline for Mach-O -*- asm -*- * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-08-15 15:36:13 by piumarta on emilia.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. */ /* Mach-O PPC stack frames look like this (higher addresses first): * * | caller's lr | * | caller's cr | * caller's sp->| caller's caller's sp | * | fpr save area | * | gpr save area | * | [alignment pad] | * | local variables | * sp + 24 -> | param save area | * sp + 20 -> | caller's toc | * sp + 16 -> | reserved | * sp + 12 -> | reserved | * sp + 8 -> | (callee-save) lr | * sp + 4 -> | (callee-save) cr | * sp + 0 -> | caller's sp | */ #define GPR_MAX 8 #define FPR_MAX 13 #define ARG_MAX 512 #define FRAMESZ 32 #include "ppc-global.h" #define sp r1 .text .globl _ffiCallAddressOf _ffiCallAddressOf: stwu sp, -FRAMESZ(sp) // push trampoline frame mflr r0 stw r0, (FRAMESZ+8)(sp) mfcr r0 stw r0, (FRAMESZ+4)(sp) // saved ccr mtlr r3 // destination fn address stw r4, (FRAMESZ-4)(sp) // globals lwz r5, stackIndex(r4) slwi r10, r5, 2 // param save area size addi r10, r10, 32+15 // round to quad word rlwinm r10, r10, 0,0,27 neg r10, r10 stwux sp, sp, r10 // push ffi caller frame cmpwi r5, 0 // have params? beq+ 2f mtctr r5 // words to move la r10, (stack-4)(r4) // ffi param stack - 4 addi r11, sp, 24-4 // param save area - 4 1: lwzu r0, 4(r10) // copy param save area stwu r0, 4(r11) bdnz 1b 2: lwz r5, fprCount(r4) cmpwi r5, 0 beq+ 4f // no fp args la r11, fprs(r4) cmpwi r5, 4 ble+ 3f lfd f5, 32(r11) lfd f6, 40(r11) lfd f7, 48(r11) lfd f8, 56(r11) # if (FPR_MAX > 8) lfd f9, 64(r11) lfd f10, 72(r11) lfd f11, 80(r11) lfd f12, 88(r11) lfd f13, 96(r11) # endif 3: lfd f1, 0(r11) lfd f2, 8(r11) lfd f3, 16(r11) lfd f4, 24(r11) 4: lwz r5, gprCount(r4) cmpwi r5, 0 beq- 6f // no int args la r11, gprs(r4) cmpwi r5, 4 ble+ 5f lwz r7, 16(r11) lwz r8, 20(r11) lwz r9, 24(r11) lwz r10, 28(r11) 5: lwz r3, 0(r11) lwz r4, 4(r11) lwz r5, 8(r11) lwz r6, 12(r11) 6: blrl // callout lwz sp, 0(sp) // pop ffi caller frame lwz r5, (FRAMESZ-4)(sp) // globals stw r3, longReturnValue+0(r5) stw r4, longReturnValue+4(r5) stfd f1, floatReturnValue(r5) lwz r0, (FRAMESZ+8)(sp) mtlr r0 lwz r0, (FRAMESZ+4)(sp) // saved ccr mtcr r0 addi sp, sp, FRAMESZ // pop trampoline frame blr ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ppc-darwin.c ================================================ /* ppc-darwin.c -- FFI support for PowerPC on Mach-O (Darwin) * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2004-04-03 02:59:34 by piumarta on emilia.local * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Notes: * * This is a complete rewrite of the version for MacPPC. (The latter * is hopelessly broken when passing long longs or structs containing * an element of alignment less strict than int.) * * Bugs: * * Because of the way strings are handled, this implementation is * neither reentrant nor thread safe. * * References: * * Mach-O Runtime Architecture, Apple Computer Inc., July 2002. */ #include "sq.h" #include "sqFFI.h" #include #include #include #ifndef LONGLONG # define LONGLONG long long #endif #if 0 # define DPRINTF(ARGS) printf ARGS; fflush(stdout) #else # define DPRINTF(ARGS) #endif extern struct VirtualMachine *interpreterProxy; #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else # define primitiveFail() interpreterProxy->primitiveFail(); #endif #define GPR_MAX 8 #define FPR_MAX 13 #define ARG_MAX 512 static char *strings[ARG_MAX]; static int stringCount= 0; #if 0 static char structs[ARG_MAX * sizeof(int)]; static int structCount= 0; #endif /* the following avoids an awful lot of _very_ inefficient junk in the asm */ static struct { int _gprCount; // 0 int _fprCount; // 4 int _stackIndex; // 8 int *_structReturnValue; // 12 (everything below is 8-byte aligned) LONGLONG _longReturnValue; // 16 double _floatReturnValue; // 24 int _gprs[GPR_MAX]; // 32 double _fprs[FPR_MAX]; // 32 + 4*GPR_MAX int _stack[ARG_MAX]; // 32 + 4*GPR_MAX + 8*FPR_MAX } global; #define gprCount global._gprCount #define fprCount global._fprCount #define stackIndex global._stackIndex #define structReturnValue global._structReturnValue #define longReturnValue global._longReturnValue #define floatReturnValue global._floatReturnValue #define gprs global._gprs #define fprs global._fprs #define stack global._stack extern int ffiCallAddressOf(void *addr, void *globals); int ffiInitialize(void) { DPRINTF(("ffiInitialize\n")); stackIndex= gprCount= fprCount= 0; #if 0 structCount= 0; #endif floatReturnValue= 0.0; return 1; } int ffiSupportsCallingConvention(int callType) { return (callType == FFICallTypeCDecl) || (callType == FFICallTypeApi); } int ffiAlloc(int byteSize) { int ptr= (int)malloc(byteSize); DPRINTF(("ffiAlloc(%d) => %08x\n", byteSize, ptr)); return ptr; } int ffiFree(int ptr) { DPRINTF(("ffiFree(%08x)\n", ptr)); if (ptr) free((void *)ptr); return 1; } #define checkStack() \ if (stackIndex >= ARG_MAX) \ return primitiveFail() #define checkGPR() \ if ((gprCount >= GPR_MAX) && (stackIndex >= ARG_MAX)) \ return primitiveFail() #define qalignStack() stackIndex += (stackIndex & 1) #define pushGPR(value) \ checkGPR(); \ if (gprCount < GPR_MAX) \ gprs[gprCount++]= value; \ stack[stackIndex++]= value #define qalignGPR() gprCount += (gprCount & 1) int ffiPushSignedChar(int value) { DPRINTF(("ffiPushSignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedChar(int value) { DPRINTF(("ffiPushUnsignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedByte(int value) { DPRINTF(("ffiPushSignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedByte(int value) { DPRINTF(("ffiPushUnsignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedShort(int value) { DPRINTF(("ffiPushSignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedShort(int value) { DPRINTF(("ffiPushUnsignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedInt(int value) { DPRINTF(("ffiPushSignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedInt(int value) { DPRINTF(("ffiPushUnsignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedLongLong(int low, int high) { DPRINTF(("ffiPushSignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushUnsignedLongLong(int low, int high) { DPRINTF(("ffiPushUnsignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushPointer(int pointer) { DPRINTF(("ffiPushPointer %08x\n", pointer)); pushGPR(pointer); return 1; } int ffiPushSingleFloat(double value) { DPRINTF(("ffiPushSingleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) fprs[fprCount++]= value; { float floatValue= (float)value; pushGPR(*(int *)&floatValue); } return 1; } int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) fprs[fprCount++]= value; pushGPR(((int *)&value)[0]); pushGPR(((int *)&value)[1]); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; DPRINTF(("ffiPushStringOfLength %d\n", length)); checkGPR(); ptr= (char *)malloc(length + 1); if (!ptr) return primitiveFail(); memcpy(ptr, (void *)srcIndex, length); ptr[length]= '\0'; strings[stringCount++]= ptr; pushGPR((int)ptr); return 1; } static inline int min(int x, int y) { return (x < y) ? x : y; } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int i; char *data = (char *)pointer; char *argp = (char *)&stack[stackIndex]; #define argl (char *)&stack[ARG_MAX] int argSize = *structSpec & FFIStructSizeMask; char *gprp = (char *)&gprs[gprCount]; #define gprl (char *)&gprs[GPR_MAX] int gprSize = min(argSize, gprl - gprp); DPRINTF(("ffiPush %08x Structure %p OfLength %d\n", pointer, structSpec, specSize)); if (gprSize < 4) gprp += (4 - gprSize); if (argSize < 4) argp += (4 - gprSize); if (argp + argSize > argl) return primitiveFail(); memcpy((void *)gprp, (void *)data, gprSize); memcpy((void *)argp, (void *)data, argSize); gprCount += (gprSize + sizeof(int) - 1) / sizeof(int); stackIndex += (argSize + sizeof(int) - 1) / sizeof(int); #undef argl #undef gprl for (i= 0; i < specSize; ++i) { int typeSpec= structSpec[i]; if (typeSpec & FFIFlagPointer) continue; else if (typeSpec & FFIFlagStructure) continue; else { int atomicType= (typeSpec & FFIAtomicTypeMask) >> FFIAtomicTypeShift; switch (atomicType) { case FFITypeSingleFloat: if (fprCount < FPR_MAX) fprs[fprCount++]= *(float *)data; break; case FFITypeDoubleFloat: if (fprCount < FPR_MAX) fprs[fprCount++]= *(double *)data; break; default: break; } data += typeSpec & FFIStructSizeMask; } } return 1; } int ffiCanReturn(int *structSpec, int specSize) { int header= *structSpec; DPRINTF(("ffiCanReturn %p %d\n", structSpec, specSize)); if (header & FFIFlagPointer) return 1; if (header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize= header & FFIStructSizeMask; structReturnValue= malloc(structSize); if (!structReturnValue) return 0; pushGPR((int)structReturnValue); } return 1; } double ffiReturnFloatValue(void) { return floatReturnValue; } int ffiLongLongResultLow(void) { return ((int *)&longReturnValue)[1]; } int ffiLongLongResultHigh(void) { return ((int *)&longReturnValue)[0]; } int ffiStoreStructure(int address, int structSize) { DPRINTF(("ffiStoreStructure %08x %d\n", address, structSize)); memcpy((void *)address, structReturnValue ? (void *)structReturnValue : (void *)&longReturnValue, structSize); return 1; } int ffiCleanup(void) { int i; DPRINTF(("ffiCleanup\n")); for (i= 0; i < stringCount; ++i) free(strings[i]); stringCount= 0; if (structReturnValue) { free(structReturnValue); structReturnValue= 0; } return 1; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { DPRINTF(("ffiCallAddressOfWithPointerReturn %08x %d\n", fn, callType)); return ffiCallAddressOf((void *)fn, (void *)&global); } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { DPRINTF(("ffiCallAddressOfWithStructReturn %08x %d %p %d\n", fn, callType, structSpec, specSize)); return ffiCallAddressOf((void *)fn, (void *)&global); } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { DPRINTF(("ffiCallAddressOfWithReturnType %08x %d %d\n", fn, callType, typeSpec)); return ffiCallAddressOf((void *)fn, (void *)&global); } #if !defined(NO_FFI_TEST) #undef gprCount #undef fprCount #undef stackIndex #undef structReturnValue #undef longReturnValue #undef floatReturnValue #undef gprs #undef fprs #undef stack #include "ppc-global.h" #define offset(field) ((char *)&global._##field - (char *)&global._gprCount) #include void ffiDoAssertions(void) { assert(gprCount == offset(gprCount)); assert(fprCount == offset(fprCount)); assert(stackIndex == offset(stackIndex)); assert(structReturnValue == offset(structReturnValue)); assert(longReturnValue == offset(longReturnValue)); assert(floatReturnValue == offset(floatReturnValue)); assert(gprs == offset(gprs)); assert(fprs == offset(fprs)); assert(stack == offset(stack)); assert(stack + (ARG_MAX * sizeof(int)) == sizeof(global)); } #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ppc-global.h ================================================ #define gprCount ( 0) #define fprCount ( 4) #define stackIndex ( 8) #define structReturnValue (12) #define longReturnValue (16) #define floatReturnValue (24) #define gprs (32) #define fprs (32 + 4*GPR_MAX) #define stack (32 + 4*GPR_MAX + 8*FPR_MAX) ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ppc-sysv-asm.S ================================================ /* ppc-sysv-asm.S -- PowerPC FFI trampoline for SVr4-like ABIs -*- asm -*- * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-01-28 11:32:14 by piumarta on emilia.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. */ #define r0 0 #define sp 1 #define r2 2 #define r3 3 #define r4 4 #define r5 5 #define r6 6 #define r7 7 #define r8 8 #define r9 9 #define r10 10 #define r11 11 #define r12 12 #define f1 1 #define f2 2 #define f3 3 #define f4 4 #define f5 5 #define f6 6 #define f7 7 #define f8 8 #define f9 9 #define f10 10 #define f11 11 #define f12 12 #define f13 13 /* V.4 stack frames look like this (higher addresses first): old SP--> | back chain to caller's caller | | Save area for FP registers (F) | 8+P+A+V+L+X+C+G | Save area for GP registers (G) | 8+P+A+V+L+X+C | saved CR (C) | 8+P+A+V+L+X | Float/int conversion temporary (X) | 8+P+A+V+L | Local variable space (L) | 8+P+A+V | Varargs save area (V) | 8+P+A | Alloca space (A) | 8+P | Parameter save area (P) | 8 | caller's saved LR | 4 SP--> | back chain to caller | 0 */ #define fn r3 #define ngpr r4 #define nfpr r5 #define nparam r6 .text .globl ffiCallAddressOf ffiCallAddressOf: stwu sp, -16(sp) // push trampoline frame mflr r0 stw r0, 20(sp) mfcr r0 stw r0, 12(sp) // saved ccr mtlr fn // destination fn address slwi r10, nparam, 2 // param save area size addi r10, r10, 16+15 // round to quad word rlwinm r10, r10, 0,0,27 neg r10, r10 stwux sp, sp, r10 // push ffi caller frame cmpwi nparam, 0 // have params? beq+ 2f mtctr nparam // words to move lis r10, (ffiStack-4)@ha la r10, (ffiStack-4)@l(r10) // ffi param stack - 4 addi r11, sp, 4 // param save area - 4 1: lwzu r0, 4(r10) // copy param save area stwu r0, 4(r11) bdnz 1b 2: cmpwi nfpr, 0 beq+ 4f // no fp args lis r11, ffiFPRs@ha la r11, ffiFPRs@l(r11) cmpwi nfpr, 4 ble+ 3f lfd f5, 32(r11) lfd f6, 40(r11) lfd f7, 48(r11) lfd f8, 56(r11) 3: lfd f1, 0(r11) lfd f2, 8(r11) lfd f3, 16(r11) lfd f4, 24(r11) 4: cmpwi ngpr, 0 beq- 6f // no int args lis r11, ffiGPRs@ha la r11, ffiGPRs@l(r11) cmpwi ngpr, 4 ble+ 5f lwz r7, 16(r11) lwz r8, 20(r11) lwz r9, 24(r11) lwz r10, 28(r11) 5: lwz r3, 0(r11) lwz r4, 4(r11) lwz r5, 8(r11) lwz r6, 12(r11) 6: blrl // callout lwz sp, 0(sp) // pop ffi caller frame lis r5, ffiLongReturnValue@ha la r5, ffiLongReturnValue@l(r5) stw r3, 0(r5) stw r4, 4(r5) lis r5, ffiFloatReturnValue@ha stfd f1, ffiFloatReturnValue@l(r5) lwz r0, 20(sp) mtlr r0 lwz r0, 12(sp) // saved ccr mtcr r0 addi sp, sp, 16 // pop trampoline frame blr ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/ppc-sysv.c ================================================ /* ppc-sysv.c -- FFI support for PowerPC SVr4 ABI * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-01-30 00:18:07 by piumarta on emilia.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * BUGS: * * Because of the way strings and structs are handled, this implementation * is neither reentrant nor thread safe. * * References: * * System V Application Binary Interface, Third Edition, * Unix System Laboratories, 1994, ISBN 0-13-100439-5. * * System V Application Binary Interface, PowerPC Processor Supplement, * Sun Microsystems and IBM, 1995. */ /* Differences between the SVr4 PPC ABI and the implementation found on * GNU-based systems (which is implemented herein): * * Float arguments are passed as doubles when in registers but as * floats when on the stack. (The ABI says they should always be * passed as doubles, even on the stack.) * * All structures are passed by reference (to a copy), even when * small (< 8 bytes). The ABI would have small structs passed in * registers. (GCC copies such structs to the top of the param save * area, after the actual arguments, at the start of the alloca * area. The implementation in this file copies them into a * temporary static array, which makes stack management simpler * and seems to work just fine.) * * Structures are always returned via a pointer to caller-allocated * memory (passed as a hidden first argument), even when small. * (The ABI would have small structs, < 8 bytes, returned in r3 and * r4.) */ #include "sq.h" #include "sqFFI.h" #include #include #ifndef LONGLONG # define LONGLONG long long #endif #if 0 # define DPRINTF(ARGS) printf ARGS #else # define DPRINTF(ARGS) #endif #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else extern struct VirtualMachine *interpreterProxy; # define primitiveFail() interpreterProxy->primitiveFail() #endif enum { GPR_MAX= 8, FPR_MAX= 8, ARG_MAX= 512 }; int ffiGPRs[GPR_MAX]; static int gprCount= 0; double ffiFPRs[FPR_MAX]; static int fprCount= 0; int ffiStack[ARG_MAX]; static int stackIndex= 0; static char *strings[ARG_MAX]; static int stringCount= 0; static char structs[ARG_MAX * sizeof(int)]; static int structCount= 0; LONGLONG ffiLongReturnValue; double ffiFloatReturnValue; static int *structReturnValue= 0; extern int ffiCallAddressOf(void *addr, int nGPR, int nFPR, int nStack); int ffiInitialize(void) { stackIndex= gprCount= fprCount= structCount= 0; ffiFloatReturnValue= 0.0; return 1; } int ffiSupportsCallingConvention(int callType) { return (callType == FFICallTypeCDecl) || (callType == FFICallTypeApi); } int ffiAlloc(int byteSize) { return (int)malloc(byteSize); } int ffiFree(int ptr) { if (ptr) free((void *)ptr); return 1; } #define checkStack() \ if (stackIndex >= ARG_MAX) \ return primitiveFail() #define checkGPR() \ if ((gprCount >= GPR_MAX) && (stackIndex >= ARG_MAX)) \ return primitiveFail() #define qalignStack() stackIndex += (stackIndex & 1) #define pushGPR(value) \ checkGPR(); \ if (gprCount < GPR_MAX) \ ffiGPRs[gprCount++]= value; \ else \ ffiStack[stackIndex++]= value #define qalignGPR() gprCount += (gprCount & 1) int ffiPushSignedChar(int value) { DPRINTF(("ffiPushSignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedChar(int value) { DPRINTF(("ffiPushUnsignedChar %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedByte(int value) { DPRINTF(("ffiPushSignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedByte(int value) { DPRINTF(("ffiPushUnsignedByte %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedShort(int value) { DPRINTF(("ffiPushSignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedShort(int value) { DPRINTF(("ffiPushUnsignedShort %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedInt(int value) { DPRINTF(("ffiPushSignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushUnsignedInt(int value) { DPRINTF(("ffiPushUnsignedInt %d\n", value)); pushGPR(value); return 1; } int ffiPushSignedLongLong(int low, int high) { DPRINTF(("ffiPushSignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushUnsignedLongLong(int low, int high) { DPRINTF(("ffiPushUnsignedLongLong %d %d\n", low, high)); qalignGPR(); qalignStack(); pushGPR(high); pushGPR(low); return 1; } int ffiPushPointer(int pointer) { DPRINTF(("ffiPushPointer %d\n", pointer)); pushGPR(pointer); return 1; } #define checkFPR() \ if ((fprCount >= FPR_MAX) && (stackIndex >= ARG_MAX)) \ return primitiveFail() #define dalignStack() stackIndex += (stackIndex & 1) int ffiPushSingleFloat(double value) { DPRINTF(("ffiPushSingleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) ffiFPRs[fprCount++]= value; else { float floatValue= (float)value; checkStack(); ffiStack[stackIndex++]= *(int *)&floatValue; } return 1; } int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) ffiFPRs[fprCount++]= value; else { dalignStack(); checkStack(); ffiStack[stackIndex++]= ((int *)(&value))[0]; checkStack(); ffiStack[stackIndex++]= ((int *)(&value))[1]; } return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; DPRINTF(("ffiPushStringOfLength %d\n", length)); checkGPR(); ptr= (char *)malloc(length + 1); if (!ptr) return primitiveFail(); memcpy(ptr, (void *)srcIndex, length); ptr[length]= '\0'; strings[stringCount++]= ptr; pushGPR((int)ptr); return 1; } #define salign(size) \ structCount= (structCount + (size) - 1) & ~(size) #define pushStruct(type, value) \ { \ DPRINTF((" ++ "#type"\n")); \ if ((structCount + sizeof(type)) > sizeof(structs)) \ return primitiveFail(); \ *(type *)(structs + structCount)= value; \ structCount += sizeof(type); \ } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int size= *structSpec & FFIStructSizeMask; DPRINTF(("ffiPushStructureOfLength %d (%db)\n", specSize, size)); salign(16); if (structCount + size > sizeof(structs)) return primitiveFail(); ffiPushPointer((int)(structs + structCount)); memcpy((void *)(structs + structCount), (void *)pointer, size); structCount += size; return 1; } /* answer true if the support code can return the given type. */ int ffiCanReturn(int *structSpec, int specSize) { int header= *structSpec; if (header & FFIFlagPointer) return 1; if (header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize= header & FFIStructSizeMask; structReturnValue= malloc(structSize); if (!structReturnValue) return 0; pushGPR((int)structReturnValue); } return 1; } double ffiReturnFloatValue(void) { return ffiFloatReturnValue; } int ffiLongLongResultLow(void) { return ((int *)&ffiLongReturnValue)[1]; } int ffiLongLongResultHigh(void) { return ((int *)&ffiLongReturnValue)[0]; } int ffiStoreStructure(int address, int structSize) { memcpy((void *)address, (void *)structReturnValue, structSize); return 1; } int ffiCleanup(void) { int i; for (i= 0; i < stringCount; ++i) free(strings[i]); stringCount= 0; if (structReturnValue) { free(structReturnValue); structReturnValue= 0; } return 1; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return ffiCallAddressOf((void *)fn, gprCount, fprCount, stackIndex); } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { return ffiCallAddressOf((void *)fn, gprCount, fprCount, stackIndex); } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { return ffiCallAddressOf((void *)fn, gprCount, fprCount, stackIndex); } #if defined(FFI_TEST) void ffiDoAssertions(void) { } #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/x86-sysv-asm.S ================================================ /* x86-sysv-asm.S -- 386 FFI trampoline for SVr4-like ABIs -*- asm -*- * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: Tue Jan 28 16:53:52 2003 by piumarta (Ian Piumarta) on xombul * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. */ .text .globl ffiCallAddressOf ffiCallAddressOf: /* 8=addr, 12=stack, 16=stackSize */ pushl %ebp movl %esp, %ebp movl 16(%ebp), %ecx testl %ecx, %ecx je 2f subl %ecx, %esp subl $4, %ecx movl 12(%ebp), %edx 1: movl (%edx,%ecx,1), %eax movl %eax, (%esp,%ecx,1) subl $4, %ecx jnc 1b 2: call *8(%ebp) movl %eax, ffiIntReturnValue movl %edx, ffiLongReturnValue fstl ffiFloatReturnValue movl %ebp, %esp popl %ebp ret ================================================ FILE: vm/src/from_squeak/unix/plugins/SqueakFFIPrims/x86-sysv.c ================================================ /* ppc-sysv.c -- FFI support for PowerPC SVr4 ABI * * Author: Ian.Piumarta@INRIA.Fr * * Last edited: 2003-02-06 20:08:58 by piumarta on felina.inria.fr * * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * BUGS: * * Because of the way strings and structs are handled, this implementation * is neither reentrant nor thread safe. */ #include "sq.h" #include "sqFFI.h" #include #include #include #ifndef LONGLONG # define LONGLONG long long #endif #if 0 # define DPRINTF(ARGS)printf ARGS #else # define DPRINTF(ARGS) #endif #if defined(FFI_TEST) static int primitiveFail(void) { puts("primitive fail"); exit(1); return 0; } #else extern struct VirtualMachine *interpreterProxy; # define primitiveFail() interpreterProxy->primitiveFail() #endif enum { FFI_MAX_STACK= 512 }; int ffiStack[FFI_MAX_STACK]; int ffiStackIndex= 0; static char *ffiTempStrings[FFI_MAX_STACK]; static int ffiTempStringCount= 0; int ffiIntReturnValue; int ffiLongReturnValue; double ffiFloatReturnValue; int *ffiStructReturnValue; extern int ffiCallAddressOf(void *addr, void *stack, int size); static FILE *ffiLogFile = NULL; int ffiLogFileNameOfLength(void *nameIndex, int nameLength) { char fileName[MAXPATHLEN]; FILE *fp; if(nameIndex && nameLength) { if(nameLength >= MAXPATHLEN) return 0; strncpy(fileName, nameIndex, nameLength); fileName[nameLength] = 0; /* attempt to open the file and if we can't fail */ fp = fopen(fileName, "at"); if(fp == NULL) return 0; /* close the old log file if needed and use the new one */ if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = fp; fprintf(ffiLogFile, "------- Log started -------\n"); fflush(fp); } else { if(ffiLogFile) fclose(ffiLogFile); ffiLogFile = NULL; } return 1; } int ffiLogCallOfLength(void *nameIndex, int nameLength) { if(ffiLogFile == NULL) return 0; fprintf(ffiLogFile, "%.*s\n", nameIndex, nameLength); fflush(ffiLogFile); } int ffiInitialize(void) { ffiStackIndex= 0; ffiFloatReturnValue= 0.0; return 1; } int ffiSupportsCallingConvention(int callType) { return (callType == FFICallTypeCDecl) || (callType == FFICallTypeApi); } int ffiAlloc(int byteSize) { return (int)malloc(byteSize); } int ffiFree(int ptr) { if (ptr) free((void *)ptr); return 1; } #define checkStack() \ if (ffiStackIndex >= FFI_MAX_STACK) \ return primitiveFail(); #define pushInt(value) \ checkStack(); \ ffiStack[ffiStackIndex++]= (value) int ffiCanReturn(int *structSpec, int specSize) { int header= *structSpec; if (header & FFIFlagPointer) return 1; if (header & FFIFlagStructure) { /* structs are always returned as pointers to hidden structures */ int structSize= header & FFIStructSizeMask; ffiStructReturnValue= malloc(structSize); if (!ffiStructReturnValue) return 0; pushInt((int)ffiStructReturnValue); } return 1; } int ffiPushSignedChar(int value) { DPRINTF(("ffiPushSignedChar %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedChar(int value) { DPRINTF(("ffiPushUnsignedChar %d\n", value)); pushInt(value); return 1; } int ffiPushSignedByte(int value) { DPRINTF(("ffiPushSignedByte %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedByte(int value) { DPRINTF(("ffiPushUnsignedByte %d\n", value)); pushInt(value); return 1; } int ffiPushSignedShort(int value) { DPRINTF(("ffiPushSignedShort %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedShort(int value) { DPRINTF(("ffiPushUnsignedShort %d\n", value)); pushInt(value); return 1; } int ffiPushSignedInt(int value) { DPRINTF(("ffiPushSignedInt %d\n", value)); pushInt(value); return 1; } int ffiPushUnsignedInt(int value) { DPRINTF(("ffiPushUnsignedInt %d\n", value)); pushInt(value); return 1; } int ffiPushSignedLongLong(int low, int high) { DPRINTF(("ffiPushSignedLongLong %d %d\n", low, high)); pushInt(low); pushInt(high); return 1; } int ffiPushUnsignedLongLong(int low, int high) { DPRINTF(("ffiPushUnsignedLongLong %d %d\n", low, high)); pushInt(low); pushInt(high); return 1; } int ffiPushPointer(int pointer) { DPRINTF(("ffiPushPointer %d\n", pointer)); pushInt(pointer); return 1; } int ffiPushSingleFloat(double value) { float f= (float)value; DPRINTF(("ffiPushSingleFloat %f\n", value)); pushInt(*(int *)&f); return 1; } int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", value)); pushInt(((int *)&value)[0]); pushInt(((int *)&value)[1]); return 1; } int ffiPushStringOfLength(int srcIndex, int length) { char *ptr; DPRINTF(("ffiPushStringOfLength %d\n", length)); checkStack(); ptr= (char *)malloc(length + 1); if (!ptr) return primitiveFail(); DPRINTF((" ++ alloc string\n")); memcpy(ptr, (void *)srcIndex, length); ptr[length]= '\0'; ffiTempStrings[ffiTempStringCount++]= ptr; pushInt((int)ptr); return 1; } int ffiPushStructureOfLength(int pointer, int *structSpec, int specSize) { int lbs= *structSpec & FFIStructSizeMask; int size= (lbs + sizeof(int) - 1) / sizeof(int); DPRINTF(("ffiPushStructureOfLength %d (%db %dw)\n", specSize, lbs, size)); if (ffiStackIndex + size > FFI_MAX_STACK) return primitiveFail(); memcpy((void *)(ffiStack + ffiStackIndex), (void *)pointer, lbs); ffiStackIndex += size; return 1; } double ffiReturnFloatValue(void) { return ffiFloatReturnValue; } int ffiLongLongResultLow(void) { return ffiIntReturnValue; } int ffiLongLongResultHigh(void) { return ffiLongReturnValue; } int ffiStoreStructure(int address, int structSize) { DPRINTF(("ffiStoreStructure %d %d\n", address, structSize)); memcpy((void *)address, (ffiStructReturnValue ? (void *)ffiStructReturnValue : (void *)&ffiIntReturnValue), structSize); return 1; } int ffiCleanup(void) { int i; DPRINTF(("ffiCleanup\n")); for (i= 0; i < ffiTempStringCount; ++i) { DPRINTF((" ++ free string\n")); free(ffiTempStrings[i]); } ffiTempStringCount= 0; if (ffiStructReturnValue) { DPRINTF((" ++ free struct\n")); free(ffiStructReturnValue); ffiStructReturnValue= 0; } return 1; } int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { return ffiCallAddressOf((void *)fn, (void *)ffiStack, ffiStackIndex * sizeof(int)); } #if defined(FFI_TEST) void ffiDoAssertions(void) {} #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/UUIDPlugin/Makefile.inc ================================================ XCFLAGS=-DHAVE_UUID_UUID_H=1 XLDFLAGS = $(LIB_UUID) ================================================ FILE: vm/src/from_squeak/unix/plugins/UUIDPlugin/acinclude.m4 ================================================ # -*- sh -*- AC_MSG_CHECKING([for UUID support]) AC_TRY_COMPILE([#include ],[uuid_generate;],[ AC_MSG_RESULT(yes) AC_CHECK_LIB(uuid, uuid_generate, LIB_UUID="-luuid" ) ],[ AC_MSG_RESULT(no) AC_PLUGIN_DISABLE ]) AC_SUBST(LIB_UUID) ================================================ FILE: vm/src/from_squeak/unix/plugins/UUIDPlugin/config.cmake ================================================ PLUGIN_FIND_INCLUDE (UUID uuid.h /usr/include/uuid) CONFIG_DEFINE (HAVE_UUID_H) PLUGIN_FIND_INCLUDE (SYS_UUID sys/uuid.h) CONFIG_DEFINE (HAVE_SYS_UUID_H) PLUGIN_FIND_LIBRARY (UUID uuid) IF (HAVE_LIBUUID) SET (CMAKE_REQUIRED_LIBRARIES uuid) ENDIF (HAVE_LIBUUID) CHECK_FUNCTION_EXISTS (uuidgen HAVE_UUIDGEN) CONFIG_DEFINE (HAVE_UUIDGEN) CHECK_FUNCTION_EXISTS (uuid_generate HAVE_UUID_GENERATE) CONFIG_DEFINE (HAVE_UUID_GENERATE) # IF (UUID_UUID_GENERATE) # SET (HAVE_UUID_GENERATE 1) # PLUGIN_LINK_LIBRARIES (uuid) # ENDIF (UUID_UUID_GENERATE) ================================================ FILE: vm/src/from_squeak/unix/plugins/UUIDPlugin/sqUnixUUID.c ================================================ #include "squeak_adapters.h" #include "config.h" #if defined(HAVE_SYS_UUID_H) # include # include #endif #if defined(HAVE_UUID_UUID_H) # include #endif #if defined(HAVE_UUID_H) # include #endif #include "sq.h" int MakeUUID(char *location) { uuid_t uuid; #if defined(HAVE_UUIDGEN) uuidgen(&uuid, 1); #elif defined(HAVE_UUID_GENERATE) uuid_generate(uuid); #endif memcpy((void *)location, (void *)&uuid, sizeof(uuid)); return 1; } #if defined(__linux__) # include # include static sigjmp_buf env; static void sigsegvHandler(int signal) { siglongjmp(env, 1); } int sqUUIDInit(void) { /* check if we get a segmentation fault when using libuuid */ int pluginAvailable= 0; struct sigaction originalAction; uuid_t uuid; if (!sigsetjmp(env, 1)) { struct sigaction newAction; newAction.sa_handler= sigsegvHandler; newAction.sa_flags= 0; sigemptyset(&newAction.sa_mask); if (sigaction(SIGSEGV, &newAction, &originalAction)) /* couldn't change the signal handler: give up now */ return 0; else pluginAvailable= MakeUUID((char *)&uuid); } sigaction(SIGSEGV, &originalAction, NULL); return pluginAvailable; } #else /* !__linux__ */ int sqUUIDInit(void) { return 1; } #endif /* !__linux__ */ int sqUUIDShutdown(void) { return 1; } ================================================ FILE: vm/src/from_squeak/unix/plugins/UnixOSProcessPlugin/Makefile.inc ================================================ XCPPFLAGS= -I$(topdir)/platforms/Cross/plugins/FilePlugin -I$(topdir)/platforms/Cross/plugins/SocketPlugin -DSQAIO_H=\"sqaio.h\" ================================================ FILE: vm/src/from_squeak/unix/plugins/UnixOSProcessPlugin/acinclude.m4 ================================================ AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV, 1)) ================================================ FILE: vm/src/from_squeak/unix/plugins/UnixOSProcessPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/UnixOSProcessPlugin/config.cmake ================================================ PLUGIN_REQUIRE_LIBRARY (PTHREAD pthread) PLUGIN_INCLUDE_DIRECTORIES (${cross}/plugins/FilePlugin ${cross}/plugins/SocketPlugin) PLUGIN_DEFINITIONS (-DSQAIO_H=\"sqaio.h\") CHECK_FUNCTION_EXISTS (unsetenv HAVE_UNSETENV) CONFIG_DEFINE (HAVE_UNSETENV) ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/Video4Squeak-dgd.8.cs ================================================ 'From OLPC1.0 of 17 August 2006 [latest update: #1108] on 3 November 2006 at 3:30:07 pm'! "Change Set: Video4Squeak-dgd Date: 3 November 2006 Author: Diego Gomez Deck "! SymbolListType subclass: #ImageResolutionType instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Morphic'! !ImageResolutionType commentStamp: 'dgd 8/1/2004 21:04' prior: 0! New type for VideoDevices' eToy vocabulary! Object subclass: #ParameterDescription instanceVariableNames: 'name type label target getSelector options help keepRatio value originalValue' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! UpdatingStringMorph subclass: #UpdatingNumericStringMorph instanceVariableNames: 'min max' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Morphic'! !UpdatingNumericStringMorph commentStamp: '' prior: 0! Similar to UpdatingStringMorph, but adds some new features for handling numbers.! ProtoObject subclass: #V4LPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! !V4LPlugin commentStamp: 'dgd 8/1/2004 21:04' prior: 0! Plugin to access Video4Linux devices. ! Object subclass: #VideoDevice instanceVariableNames: 'isSleeping isExecutor brightness contrast implementation lastErrorTimestamp' classVariableNames: 'Registry' poolDictionaries: '' category: 'VideoForSqueak-Core'! !VideoDevice commentStamp: 'dgd 8/1/2004 21:06' prior: 0! VideoDevice is the access point for Video4Squeak framework. How to use: VideoDevice default. ! Object subclass: #VideoDeviceImplementor instanceVariableNames: 'description' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! !VideoDeviceImplementor commentStamp: 'dgd 7/28/2004 17:31' prior: 0! This class is the superclass for the Implementor hierarchy for the Bridge composed with VideoDevice. VideoDevice holds an implementor and it can be changed on the fly. It allows, for instance, to switch the implementor base on the operative system where Squeak is being started. ! VideoDeviceImplementor subclass: #TestDeviceImplementor instanceVariableNames: 'opened extent type isShowingTime' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! VideoDeviceImplementor subclass: #V4LDeviceImplementor instanceVariableNames: 'deviceHandle buffer deviceID desiredExtent desiredPalette' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! Object subclass: #VideoDeviceImplementorDescription instanceVariableNames: 'type id name' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Core'! RectangleMorph subclass: #VideoMorph instanceVariableNames: 'videoSource form resolution autoExtent configurationDialog' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Morphic'! AlignmentMorph subclass: #VideoMorphConfiguration instanceVariableNames: 'target parameters' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Morphic'! ObjectPropertiesMorph subclass: #VideoPropertiesMorph instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VideoForSqueak-Morphic'! !ImageResolutionType methodsFor: 'initialization' stamp: 'dgd 7/1/2004 13:30'! initialize "initialize the receiver's" super initialize. "" self vocabularyName: #ImageResolution. self symbols: VideoMorph resolutions! ! !ImageResolutionType methodsFor: 'tiles' stamp: 'dgd 8/20/2006 11:30'! representsAType ^ true! ! !ImageResolutionType class methodsFor: 'class initialization' stamp: 'dgd 8/20/2006 11:44'! initialize Vocabulary initialize! ! !ParameterDescription methodsFor: 'creation' stamp: 'dgd 8/10/2004 14:17'! asBooleanMorph | cb lab | cb := EtoyUpdatingThreePhaseButtonMorph checkBox. cb target: self; actionSelector: #switchValue; getSelector: #value. help isEmpty ifFalse: [cb setBalloonText: help]. "" lab := StringMorph contents: ' ' , label. lab setBalloonText: help. help isEmpty ifFalse: [lab setBalloonText: help]. "" ^self inARow: { cb. lab}! ! !ParameterDescription methodsFor: 'creation' stamp: 'dgd 8/10/2004 12:36'! asExtentMorph | lab x y kr | lab := StringMorph contents: label , ': '. help isEmpty ifFalse: [lab setBalloonText: help]. "" x := UpdatingNumericStringMorph on: self selector: #getPointX. x putSelector: #setPointX:. x min: 16. x max: 640. x setBalloonText: 'width in pixels' translated. "" y := UpdatingNumericStringMorph on: self selector: #getPointY. y putSelector: #setPointY:. y min: 12. y max: 480. y setBalloonText: 'height in pixels' translated. "" kr := EtoyUpdatingThreePhaseButtonMorph checkBox. kr target: self; actionSelector: #switchKeepRatio; getSelector: #keepRatio. kr setBalloonText: 'keep ratio' translated. "" ^ self inARow: {lab. StringMorph contents: ' width=' translated. self inABox: x. StringMorph contents: ' height=' translated. self inABox: y. StringMorph contents: ' '. kr}! ! !ParameterDescription methodsFor: 'creation' stamp: 'dgd 8/10/2004 12:06'! asMorph type == #boolean ifTrue: [^ self asBooleanMorph]. type == #extent ifTrue: [^ self asExtentMorph]. type == #option ifTrue: [^ self asOptionMorph]. "" ^ StringMorph contents: 'unknown type: ' , type asString! ! !ParameterDescription methodsFor: 'creation' stamp: 'dgd 8/10/2004 12:33'! asOptionMorph | lab button | lab := StringMorph contents: label , ': '. help isEmpty ifFalse: [lab setBalloonText: help]. "" button := UpdatingSimpleButtonMorph newWithLabel: '-'. button target: self; wordingSelector: #wordingForOption; actionSelector: #showOptions; color: Color white; borderWidth: 1; borderColor: Color black; cornerStyle: #square. help isEmpty ifFalse: [button setBalloonText: help]. "" ^ self inARow: {lab. button}! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:17'! getPointX ^(self value) x! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:17'! getPointY ^(self value) y! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/9/2004 19:10'! inABox: aMorph "private - answer a row with the given morphs" | box | box := AlignmentMorph newRow. box color: Color white. box borderWidth: 1. box borderColor: Color black. "" box addMorphBack: aMorph. "" ^ box! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/9/2004 17:38'! inARow: aCollection "private - answer a row with the given morphs" | row | row := AlignmentMorph newRow. row color: Color transparent. "" aCollection do: [:each | row addMorphBack: each]. "" ^ row! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:17'! setPointX: aNumber | newX currentX newY | newX := aNumber asInteger min: 640 max: 16. currentX := self getPointX. newX = currentX ifTrue: [^self]. newY := keepRatio ifTrue: [(newX / currentX * self getPointY) rounded] ifFalse: [self getPointY]. "" self value: newX @ newY! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:17'! setPointY: aNumber | newY currentY newX | newY := aNumber asInteger min: 480 max: 12. currentY := self getPointY. newY = currentY ifTrue: [^self]. newX := keepRatio ifTrue: [(newY / currentY * self getPointX) rounded] ifFalse: [self getPointX]. "" self value: newX @ newY! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:17'! showOptions | menu | menu := MenuMorph new. menu color: Color white. menu borderWidth: 1. menu borderColor: Color black. menu cornerStyle: #square. options do: [:pair | "" menu add: pair first target: self selector: #value: argumentList: { pair second}]. menu popUpInWorld! ! !ParameterDescription methodsFor: 'private' stamp: 'dgd 8/10/2004 14:18'! wordingForOption | option wording | option := self value. wording := options detect: [:pair | pair second = option] ifNone: [^'' translated]. ^wording first! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/10/2004 20:14'! hasChanged ^ value ~= originalValue! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/9/2004 20:23'! keepRatio ^keepRatio! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/10/2004 20:09'! name "answer the receiver's name" ^ name! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/9/2004 20:24'! switchKeepRatio keepRatio := keepRatio not! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/10/2004 14:18'! switchValue value := value not ! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/10/2004 14:13'! value ^value! ! !ParameterDescription methodsFor: 'accessing' stamp: 'dgd 8/10/2004 14:13'! value: anObject value _anObject! ! !ParameterDescription methodsFor: 'initialization' stamp: 'dgd 8/9/2004 20:23'! initialize "initialize the receiver" keepRatio := true! ! !ParameterDescription methodsFor: 'initialization' stamp: 'dgd 8/10/2004 20:09'! initializeName: nameSymbol type: typeSymbol label: labelString value: anObject options: aCollection help: helpString "initialize the receiver" name := nameSymbol. type := typeSymbol. label := labelString. value := originalValue := anObject. options := aCollection. help := helpString! ! !ParameterDescription class methodsFor: 'instance creation' stamp: 'dgd 8/10/2004 20:10'! booleanParameterNamed: nameSymbol label: labelString value: anObject help: helpString ^ self new initializeName: nameSymbol type: #boolean label: labelString value: anObject options: nil help: helpString! ! !ParameterDescription class methodsFor: 'instance creation' stamp: 'dgd 8/10/2004 20:11'! extentParameterNamed: nameSymbol label: labelString value: anObject help: helpString ^ self new initializeName: nameSymbol type: #extent label: labelString value: anObject options: nil help: helpString! ! !ParameterDescription class methodsFor: 'instance creation' stamp: 'dgd 8/9/2004 20:13'! new "answer a new instance of the receiver" ^ super new initialize! ! !ParameterDescription class methodsFor: 'instance creation' stamp: 'dgd 8/10/2004 20:12'! optionParameterNamed: nameSymbol label: labelString value: anObject options: aCollection help: helpString ^ self new initializeName: nameSymbol type: #option label: labelString value: anObject options: aCollection help: helpString! ! !Player methodsFor: '*VideoForSqueak-playing commands' stamp: 'dgd 8/9/2004 20:56'! configureVideoDevice self sendMessageToCostume: #configureVideoDevice! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 8/6/2004 19:54'! getAutoExtent "answer whateve the receiver is in auto extent mode" ^ costume renderedMorph getAutoExtent! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 6/30/2004 23:21'! getBrightness "Answer the numeric value contained in my costume" ^ costume renderedMorph getBrightness! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 6/30/2004 23:21'! getContrast "Answer the numeric value contained in my costume" ^ costume renderedMorph getContrast! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 7/1/2004 18:24'! getLastFrame "Answer the lastFrame in my costume" ^ costume renderedMorph getLastFrame assuredPlayer! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 7/1/2004 13:23'! getResolution "Answer the numeric value contained in my costume" ^ costume renderedMorph getResolution! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 8/6/2004 19:55'! setAutoExtent: aBoolean "Set the receiver's boolean value. This is passed on to the costume" costume renderedMorph setAutoExtent: aBoolean! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 6/30/2004 23:22'! setBrightness: amt "Set the receiver's numeric value to the amount. This is passed on to the costume" costume renderedMorph setBrightness: amt! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 6/30/2004 23:22'! setContrast: amt "Set the receiver's numeric value to the amount. This is passed on to the costume" costume renderedMorph setContrast: amt! ! !Player methodsFor: '*VideoForSqueak-slot getters/setters' stamp: 'dgd 7/1/2004 13:22'! setResolution: aSymbol "Set the receiver's value. This is passed on to the costume" costume renderedMorph setResolution: aSymbol! ! !UpdatingNumericStringMorph methodsFor: 'target access' stamp: 'sw 9/13/2002 17:54'! acceptValueFromTarget: v "Accept a value from my target" ^ super acceptValueFromTarget: ((self format == #default and: [v isNumber]) ifTrue: [| t | t _ v. min ifNotNil: [t _ t max: min]. max ifNotNil: [t _ t min: max]] ifFalse: [v])! ! !UpdatingNumericStringMorph methodsFor: 'accessing' stamp: 'NS 6/24/2000 16:31'! max ^ max! ! !UpdatingNumericStringMorph methodsFor: 'accessing' stamp: 'NS 6/24/2000 16:31'! max: aNumber max _ aNumber! ! !UpdatingNumericStringMorph methodsFor: 'accessing' stamp: 'NS 6/24/2000 16:32'! min ^ min! ! !UpdatingNumericStringMorph methodsFor: 'accessing' stamp: 'NS 6/24/2000 16:31'! min: aNumber min _ aNumber! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 8/1/2004 20:41'! primitiveDeviceClose | device | self export: true. self var: #device type: 'Device'. device := self cCoerce: (interpreterProxy stackIntegerValue: 0) to: 'Device'. self closeDevice: device. "" interpreterProxy pop: 1! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 8/5/2004 22:27'! primitiveDeviceCreate | palette height width devicePointer deviceID | self export: true. "" palette := interpreterProxy stackIntegerValue: 0. height := interpreterProxy stackIntegerValue: 1. width := interpreterProxy stackIntegerValue: 2. deviceID := interpreterProxy stackIntegerValue: 3. "" devicePointer := self cCode: '(int) createDevice(deviceID, width, height, palette)'. devicePointer <= 0 ifTrue: [^ interpreterProxy primitiveFail]. "" interpreterProxy pop: 5 thenPush: (interpreterProxy integerObjectOf: devicePointer) ! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 7/29/2004 17:49'! primitiveDeviceDescribe | deviceID deviceName deviceNamePointer deviceNameSize | self export: true. self var: #deviceNamePointer type: 'void*'. "" deviceName := interpreterProxy stackValue: 0. (interpreterProxy isBytes: deviceName) ifFalse: [^ interpreterProxy primitiveFail]. deviceNamePointer := interpreterProxy firstIndexableField: deviceName. deviceNameSize := interpreterProxy byteSizeOf: deviceName. deviceNameSize = 32 ifFalse: [^ interpreterProxy primitiveFail]. "" deviceID := interpreterProxy stackIntegerValue: 1. "" self cCode: 'describeDevice(deviceID, deviceNamePointer)'. "" interpreterProxy pop: 2! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 7/21/2004 17:43'! primitiveDeviceGetHeight | device result | self export: true. self var: #device type: 'Device'. device := self cCoerce: (interpreterProxy stackIntegerValue: 0) to: 'Device'. result := self cCode: 'device->vwindow.height'. interpreterProxy pop: 2 thenPush: (interpreterProxy integerObjectOf: result)! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 7/21/2004 17:48'! primitiveDeviceGetWidth | device result | self export: true. self var: #device type: 'Device'. device := self cCoerce: (interpreterProxy stackIntegerValue: 0) to: 'Device'. result := self cCode: 'device->vwindow.width'. interpreterProxy pop: 2 thenPush: (interpreterProxy integerObjectOf: result)! ! !V4LPlugin methodsFor: 'primitives' stamp: 'dgd 8/6/2004 14:32'! primitiveDeviceNextFrameIntoBrightnessAndContrast "set the capture extent and pixel format to use" | contrast brightness bitsArrayPointer bitsArraySize device result dest src imageSize final | self export: true. self var: #device type: 'Device'. self var: #dest type: 'unsigned char*'. self var: #src type: 'unsigned char*'. self var: #final type: 'unsigned char*'. self var: #brightness type: 'double'. self var: #contrast type: 'double'. "" contrast := interpreterProxy stackFloatValue: 0. brightness := interpreterProxy stackFloatValue: 1. brightness := brightness min: 1.0. brightness := brightness max: -1.0. contrast := contrast min: 1.0. contrast := contrast max: -1.0. "" bitsArrayPointer := interpreterProxy stackValue: 2. interpreterProxy success: (interpreterProxy isPointers: bitsArrayPointer) not. interpreterProxy failed ifTrue: [^ nil]. bitsArraySize := interpreterProxy byteSizeOf: bitsArrayPointer. "" device := self cCoerce: (interpreterProxy stackIntegerValue: 3) to: 'Device'. "" result := self nextFrameFromDevice: device. result ifFalse: [^ interpreterProxy primitiveFail]. "" dest := self cCoerce: (interpreterProxy firstIndexableField: bitsArrayPointer) to: 'unsigned char*'. src := self cCode: 'device->buffer24'. "" imageSize := device width * device height * 4. final := dest + (imageSize min: bitsArraySize). "" [dest < final] whileTrue: [| blue green red | "blue" blue := self pixel: (src at: 2) brightness: brightness contrast: contrast. dest at: 0 put: blue. "green" green := self pixel: (src at: 1) brightness: brightness contrast: contrast. dest at: 1 put: green. "red" red := self pixel: (src at: 0) brightness: brightness contrast: contrast. dest at: 2 put: red. "alpha" dest at: 3 put: 255. "" dest := dest + 4. src := src + 3]. "" interpreterProxy pop: 4! ! !V4LPlugin methodsFor: 'helper functions' stamp: 'dgd 8/5/2004 22:51'! height: device self inline: true. self var: #device type: 'Device'. ^ self cCode: 'device->vwindow.height'! ! !V4LPlugin methodsFor: 'helper functions' stamp: 'dgd 8/20/2006 10:45'! pixel: pixel brightness: brightness contrast: contrast | result c | self inline: true. self var: #brightness type: 'double'. self var: #contrast type: 'double'. self var: #c type: 'double'. "contrast" c := 1.0 + contrast. c := c * c. result := pixel - 0.5 * c + 0.5. "brightness" result := result + (brightness * 256) asInteger. "bound checking" result < 0 ifTrue: [result := 0]. result > 255 ifTrue: [result := 255]. ^ result asInteger! ! !V4LPlugin methodsFor: 'helper functions' stamp: 'dgd 7/21/2004 21:02'! width: device self inline: true. self var: #device type: 'Device'. ^ self cCode: 'device->vwindow.width' ! ! !V4LPlugin class methodsFor: 'translation' stamp: 'dgd 6/26/2004 18:12'! hasHeaderFile "If there is a single intrinsic header file to be associated with the plugin, here is where you want to flag" ^ true! ! !V4LPlugin class methodsFor: 'translation' stamp: 'dgd 8/5/2004 22:50'! translate " V4LPlugin translate. " | directory | directory := FileDirectory forFileName: '/home/dgd/squeak-vm37/src/plugins/V4LPlugin/'. directory assureExistence. self translateInDirectory: directory doInlining: true! ! !VideoDevice methodsFor: 'private' stamp: 'dgd 7/11/2004 20:50'! benchmark "capture and display 100 frames from the device" | iterations time statistics | iterations := 100. time := Time millisecondsToRun: ["" iterations timesRepeat: [self next display]]. "" Display restore. "" statistics := String new writeStream. statistics nextPutAll: '------------------------------------------------------------'. statistics cr. statistics nextPutAll: 'Frame Extent: ' , self extent asString. statistics cr. statistics nextPutAll: 'Iterations: ' , iterations asString. statistics cr. statistics nextPutAll: 'Ellapsed time:' , time asString , 'ms (each ' , (time / iterations) asFloat rounded asString , 'ms)'. statistics cr. statistics nextPutAll: 'Frames per second:' , (1000.0 / (time / iterations) roundTo: 0.01) asString. statistics cr. statistics nextPutAll: '------------------------------------------------------------'. statistics cr. "" statistics contents openInWorkspaceWithTitle: 'benchmark'! ! !VideoDevice methodsFor: 'private' stamp: 'dgd 8/9/2004 19:44'! changedExtent self triggerEvent:#extent! ! !VideoDevice methodsFor: 'private' stamp: 'dgd 8/1/2004 13:08'! closedFrame "private" ^ self frameColor: Color blue twiceDarker withMessage: 'closed' translated! ! !VideoDevice methodsFor: 'private' stamp: 'dgd 8/1/2004 12:49'! frameColor: aColor withMessage: aString "private - create a frame of the given color with aString as the message" | result | result := Form extent: self extent depth: 32. result fillColor: aColor. result getCanvas drawString: aString at: 5 @ 2 font: Preferences windowTitleFont color: Color lightGreen. ^ result! ! !VideoDevice methodsFor: 'private' stamp: 'dgd 8/1/2004 20:47'! poisonedFrame "private" ^ self frameColor: Color red muchDarker withMessage: ('no connected video device id: {1}' translated format: {self deviceID})! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/11/2004 20:55'! brightness "answer the receiver's brightness" ^ brightness! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/28/2004 17:08'! brightness: aNumber "change the receiver's brightness" brightness := aNumber asFloat min: 1.0 max: -1.0! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/11/2004 20:55'! contrast "answer the receiver's contrast" ^ contrast! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/28/2004 17:08'! contrast: aNumber "change the receiver's contrast" contrast := aNumber asFloat min: 1.0 max: -1.0! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:20'! deviceID "answer the receiver's deviceID" ^ implementation deviceID! ! !VideoDevice methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:19'! extent "answer the receiver's extent" ^implementation extent! ! !VideoDevice methodsFor: 'dying / reviving' stamp: 'dgd 8/1/2004 20:16'! bePoisoned "change the receiver to be poisoned" lastErrorTimestamp := Time millisecondClockValue. [self closeIfCorresponds] on: Error do: [:exception | ]! ! !VideoDevice methodsFor: 'dying / reviving' stamp: 'dgd 8/1/2004 19:59'! isPoisoned "answer whatever the receiver is poisoned" ^ lastErrorTimestamp notNil! ! !VideoDevice methodsFor: 'dying / reviving' stamp: 'dgd 8/1/2004 20:51'! isTimeToRevive "answer if it's time to try to revive the receiver" | elapsed | self isPoisoned ifFalse: [^ false]. elapsed := Time millisecondsSince: lastErrorTimestamp. ^ elapsed > 5000! ! !VideoDevice methodsFor: 'dying / reviving' stamp: 'dgd 8/1/2004 20:51'! tryToRevive "private - trying to revive the receiver" self flag: #todo. "try to connect to another device if the current deviceID is unavailable." "" lastErrorTimestamp := nil. self open! ! !VideoDevice methodsFor: 'dying / reviving' stamp: 'dgd 8/1/2004 20:12'! tryToReviveIfCorresponds "private - try to revive if it's time to" self isTimeToRevive ifTrue:[ self tryToRevive]! ! !VideoDevice methodsFor: 'opening / closing' stamp: 'dgd 8/1/2004 13:11'! close "close the receiver" isSleeping ifTrue: ["" isSleeping := false. ^ self]. "" self isOpened ifFalse: [^ self error: 'device not opened']. "" [implementation close] on: Error do: [:exception | exception]. self class unregister: self! ! !VideoDevice methodsFor: 'opening / closing' stamp: 'dgd 7/11/2004 20:48'! closeIfCorresponds "close the receiver if it's opened, otherwise do nothing" self isOpened ifTrue: [self close]! ! !VideoDevice methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 20:19'! isOpened "answer whatever the receiver is opened" ^ implementation isOpened! ! !VideoDevice methodsFor: 'opening / closing' stamp: 'dgd 8/10/2004 21:27'! open "open the device represented by the receiver" self isOpened ifTrue: [^ self error: 'device already opened']. "" [implementation open. self class register: self. self triggerEvent: #extent. isSleeping := false] on: Error do: [:exception | self bePoisoned]! ! !VideoDevice methodsFor: 'opening / closing' stamp: 'dgd 7/11/2004 20:48'! openIfCorresponds "open the receiver if it isn't opened, otherwise do nothing" self isOpened ifFalse: [self open]! ! !VideoDevice methodsFor: 'configuration' stamp: 'dgd 8/10/2004 21:27'! applyParameters: aCollection "apply the (possible changed) collection of parameters" self isPoisoned ifFalse: [self close]. implementation applyParameters: aCollection. self isPoisoned ifFalse: [self open]. ! ! !VideoDevice methodsFor: 'configuration' stamp: 'dgd 8/10/2004 14:59'! parameters "answer a collection of parameters to configure the receiver" ^ implementation parameters! ! !VideoDevice methodsFor: 'sleeping' stamp: 'dgd 8/1/2004 20:14'! awake "if the receiver is sleeping, awake it" isExecutor ifTrue: [^ self]. "" isSleeping ifFalse: [^ self]. "" self open. isSleeping := false! ! !VideoDevice methodsFor: 'sleeping' stamp: 'dgd 8/1/2004 13:11'! sleep "if the receiver is opened, put it to sleep" isExecutor ifTrue: [^ self]. "" self isOpened ifFalse: [^ self]. "" self close. isSleeping := true! ! !VideoDevice methodsFor: 'initialization' stamp: 'dgd 8/1/2004 17:58'! initialize "initialize the receiver" isSleeping := false. isExecutor := false. "" brightness := 0.0. contrast := 0.0! ! !VideoDevice methodsFor: 'initialization' stamp: 'dgd 8/9/2004 19:43'! initializeImplementation: anImplementor "initialize the receiver's description" implementation := anImplementor. implementation when: #extent send: #changedExtent to: self! ! !VideoDevice methodsFor: 'capturing' stamp: 'dgd 8/1/2004 20:47'! next "answer the next frame from the device represented by the receiver" self tryToReviveIfCorresponds. "" self isPoisoned ifTrue: [^ self poisonedFrame]. self isOpened ifFalse: [^ self closedFrame]. "" [^ implementation nextWithBrightness: self brightness contrast: self contrast] on: Error do: [:exception | self bePoisoned. ^ self poisonedFrame]! ! !VideoDevice methodsFor: 'finalization' stamp: 'dgd 8/1/2004 21:07'! actAsExecutor "prepare the receiver to act as executor for any resources associated with it" super actAsExecutor. "an executor will not to go sleep becouse the original instance will close the device for its own" isExecutor := true! ! !VideoDevice methodsFor: 'finalization' stamp: 'dgd 7/11/2004 20:49'! finalize "the receiver is going to die, let's clean up" self closeIfCorresponds! ! !VideoDevice class methodsFor: 'system startup' stamp: 'dgd 7/11/2004 20:46'! shutDown: quitting quitting ifFalse:[^self]. "" self allSubInstances do: [:each | each sleep]! ! !VideoDevice class methodsFor: 'system startup' stamp: 'dgd 7/11/2004 20:46'! startUp: resuming resuming ifFalse:[^self]. "" self allSubInstances do: [:each | each awake]! ! !VideoDevice class methodsFor: 'initialize-release' stamp: 'dgd 7/28/2004 21:14'! initialize " VideoDevice initialize. " Smalltalk addToStartUpList: self. Smalltalk addToShutDownList: self! ! !VideoDevice class methodsFor: 'initialize-release' stamp: 'dgd 7/28/2004 21:15'! unload Smalltalk removeFromStartUpList: self. Smalltalk removeFromShutDownList: self! ! !VideoDevice class methodsFor: 'registry' stamp: 'dgd 7/11/2004 20:45'! register: anObject "register anObject to receive the finalization signal" WeakArray isFinalizationSupported ifFalse: [^ self]. self registry add: anObject! ! !VideoDevice class methodsFor: 'registry' stamp: 'dgd 7/11/2004 20:45'! registry "anwer the registry for finalization" WeakArray isFinalizationSupported ifFalse: [^ nil]. ^ Registry ifNil: [Registry := WeakRegistry new]! ! !VideoDevice class methodsFor: 'registry' stamp: 'dgd 7/11/2004 20:45'! unregister: anObject WeakArray isFinalizationSupported ifFalse: [^ self]. self registry remove: anObject ifAbsent: []! ! !VideoDevice class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 19:19'! default "answer the default video device" " VideoDevice default. " ^ self implementation: self firstAvailableDeviceImplementor! ! !VideoDevice class methodsFor: 'instance creation' stamp: 'dgd 11/3/2006 14:27'! firstAvailableDeviceImplementor "private - answer the first available video device implementor" | descriptions | descriptions := self descriptions asSortedCollection: [:x :y | x id <= y id]. descriptions isEmpty ifTrue: [^self error: 'no video devices detected']. descriptions do: [:eachDescription | [^ eachDescription newImplementor] on: Error do: [:exception | ] ]. ! ! !VideoDevice class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 20:16'! implementation: anImplementor "answer an instance of the receiver using the given implementor" ^ self new initializeImplementation: anImplementor! ! !VideoDevice class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 20:30'! new "answer a new instance of the receiver" ^ super new initialize ! ! !VideoDevice class methodsFor: 'enumerating' stamp: 'dgd 8/5/2004 19:30'! descriptions "answer a collection of VideoDeviceDescription of available video devices" " VideoDevice descriptions. " | result | result := Set new. self workingImplementors do: [:each | result addAll: each descriptions]. "" ^ result ! ! !VideoDevice class methodsFor: 'enumerating' stamp: 'dgd 8/5/2004 19:28'! workingImplementors "private - answer a collection of implementors working on the current environment" ^ VideoDeviceImplementor allSubclasses select: [:each | each workOnCurrentEnvironment]! ! !VideoDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 18:24'! applyParameters: aCollection "apply the (possible changed) collection of parameters" ! ! !VideoDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 14:59'! parameters "answer a collection of parameters to configure the receiver" ^ {}! ! !VideoDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:38'! description "answer the receiver's description" ^ description! ! !VideoDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:37'! deviceID "answer the receiver's deviceID" ^ self subclassResponsibility! ! !VideoDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:37'! extent "answer the receiver's extent" ^ self subclassResponsibility! ! !VideoDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:10'! close "private - close the receiver" self subclassResponsibility! ! !VideoDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:14'! isOpened "answer whatever the receiver is opened" ^ self subclassResponsibility! ! !VideoDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:11'! open "open the device represented by the receiver" self subclassResponsibility! ! !VideoDeviceImplementor methodsFor: 'initialization' stamp: 'dgd 7/28/2004 17:17'! initialize "initialize the receiver" ! ! !VideoDeviceImplementor methodsFor: 'initialization' stamp: 'dgd 7/28/2004 20:18'! initializeDescription: aDescription "initialiaze the receiver's description" description := aDescription! ! !VideoDeviceImplementor methodsFor: 'capturing' stamp: 'dgd 7/28/2004 20:26'! nextWithBrightness: brightnessFloat contrast: contrastFloat "answer the next frame from the device represented by the receiver" ^ self subclassResponsibility! ! !TestDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 7/28/2004 20:07'! deviceID "answer the receiver's deviceID" ^ 10! ! !TestDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 8/10/2004 18:23'! extent "answer the receiver's extent" ^ extent! ! !TestDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 8/10/2004 19:41'! extent: aPoint "change the receiver's extent" extent = aPoint ifTrue: [^ self]. "" extent _ aPoint. self triggerEvent:#extent! ! !TestDeviceImplementor methodsFor: 'private' stamp: 'dgd 8/9/2004 21:04'! colorBars | result canvas testColors barWidth | result := Form extent: self extent depth: 32. "" result fillColor: Color black. canvas := result getCanvas. "" testColors := (Color cyan wheel: 32). barWidth := result width // testColors size. "" testColors withIndexDo: [:color :index | "" canvas fillRectangle: (index - 1 * barWidth @ 0 rect: index * barWidth @ result height) color: color]. ^ result! ! !TestDeviceImplementor methodsFor: 'private' stamp: 'dgd 8/9/2004 21:04'! lenna ^ Form extent: 320 @ 240 depth: 32 fromArray: #(4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293037952 4292775807 4293035907 4293038208 4292906107 4292906619 4292970616 4292773745 4292773491 4292842358 4292969583 4292969839 4292381298 4293165676 4292643449 4292641404 4293297515 4292708211 4292972157 4293364086 4293300605 4292973432 4293632385 4293237633 4293629301 4293236353 4292974974 4293429370 4292378479 4292902779 4291451748 4289811557 4289348176 4288103014 4288888938 4289087570 4289022553 4289677920 4289546593 4290005077 4290007900 4290072153 4289417307 4290008422 4290005600 4290006617 4290465881 4289875290 4290007644 4290073436 4289416026 4290530135 4289811036 4290335323 4290207072 4291125601 4291122522 4291125601 4290667613 4291191136 4291650658 4291453282 4291125598 4291717991 4292044643 4291717989 4291191660 4291321700 4291129456 4291520874 4292110947 4291257694 4291782250 4291323230 4291783271 4291914337 4291519846 4291717216 4291914862 4291324528 4292044642 4291586661 4291980392 4291980392 4291782504 4292044132 4291716969 4292111459 4292439653 4291783789 4291652198 4291585632 4292045929 4291456615 4292045928 4291651941 4291849325 4292045928 4291587682 4291979880 4291981674 4291391079 4292439913 4290864753 4291457392 4291980139 4291521130 4291389283 4291126632 4291717990 4291979108 4291717216 4291389291 4291128426 4291784546 4291455595 4291848040 4291586662 4292109665 4291782500 4292111459 4292111460 4292111203 4291587689 4292044643 4291586662 4291848035 4291849069 4291786865 4291520617 4291585893 4291061096 4292439398 4291126370 4291980910 4291519072 4291192164 4291783526 4291125857 4291455600 4291258472 4291454301 4291651686 4291258472 4290929256 4292045160 4290863721 4291716703 4290995823 4291322973 4291322732 4291192680 4290600802 4290994033 4290731876 4290273388 4290403422 4289419359 4289548122 4289546595 4289939787 4290732130 4291322463 4292048489 4291916390 4292116594 4292249210 4292708206 4292840817 4292644725 4292514428 4292511084 4292509553 4292772208 4292576877 4292445808 4292903790 4292641660 4292839282 4292642163 4292512893 4292838779 4292970095 4292641637 4292248688 4293165404 4292576887 4292838512 4292838514 4292576106 4293035633 4292445806 4292969840 4292970867 4292250743 4292904297 4292839284 4292774777 4292970867 4292642164 4292446322 4293169517 4293705093 4294037154 4294037668 4294037409 4294038694 4294038694 4294038696 4294167951 4293176455 4291065452 4289284963 4288956510 4289484116 4289548647 4289944159 4290535007 4290272611 4290797412 4290274669 4290271838 4290338917 4290994271 4290797154 4290277240 4290337892 4290207075 4291125343 4290731872 4291322720 4291125087 4290600805 4290994782 4291322980 4290076264 4291323753 4290928990 4291322464 4290075231 4290667113 4291323751 4290601837 4290797923 4291256671 4290996578 4290536289 4291256415 4290141024 4290861405 4290206559 4290666084 4292772984 4292712336 4293499777 4292047205 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293037952 4292776064 4293231997 4293234041 4293038209 4293101445 4292905334 4292774279 4292970609 4292383868 4292837742 4292774005 4292839285 4292772719 4292839284 4292642163 4292773748 4292773747 4293299581 4292971646 4293366643 4293302908 4293629818 4293172097 4293566332 4293564795 4293628027 4293298564 4292901977 4292117114 4291518562 4290336614 4289282640 4288691558 4288299595 4288956509 4289022558 4289677921 4289481814 4290532454 4290007900 4289414487 4290070614 4290007899 4290008156 4289415769 4289877085 4290529622 4290009439 4289417052 4289547354 4289939543 4290466908 4290337112 4290139742 4291190359 4290533727 4290599511 4291454305 4290993757 4291257439 4291651426 4291387490 4291914849 4291585121 4291717991 4291585375 4291389549 4291522406 4291914862 4291586661 4291978596 4291322727 4291848545 4291127146 4291782496 4291127657 4291519585 4291653730 4291455339 4292373094 4291782248 4292111458 4291914600 4292111714 4291454575 4292505701 4292045667 4291914856 4291455339 4291848799 4292177252 4291586405 4291849326 4291717732 4291257954 4291849326 4291586405 4291980137 4292112996 4291980135 4291849325 4291849324 4291126891 4291063661 4291390570 4291586667 4292045663 4291061098 4291520348 4292177252 4291455078 4291650661 4291063147 4291717477 4291913577 4291848798 4291848810 4291979364 4291848799 4291914858 4292111459 4292111203 4291981926 4291913315 4292111971 4291453280 4291456870 4292442485 4291455082 4291980127 4290995306 4292111203 4291126371 4291521131 4291782752 4291192163 4291783525 4291191403 4292046444 4291192162 4291257956 4291192418 4291913064 4291126889 4291979362 4291586149 4291454566 4291126888 4291518561 4291258210 4291257960 4290600029 4291125859 4290733670 4290272615 4290403422 4290009193 4290074974 4289480021 4289940821 4290730591 4291322719 4292046949 4292180079 4292706416 4292183671 4292904819 4292840313 4292839799 4292514684 4292708204 4292574052 4292314478 4292313965 4293101168 4292642676 4292706939 4292643706 4292837741 4292644991 4292839282 4292772719 4292838513 4292904049 4292575603 4293035888 4292444522 4292640350 4293035890 4292380270 4292903007 4292773482 4292577915 4293101940 4292445548 4292643194 4292840312 4292839284 4292903535 4292446322 4293235053 4293705350 4294101904 4294037904 4294037411 4294038694 4294038694 4294038696 4294167695 4293110663 4290999660 4289350756 4288956508 4289680232 4289482073 4290469216 4290535006 4289750130 4290929242 4290209886 4290206048 4291191903 4290074975 4290208355 4290538605 4290272357 4290273387 4291388255 4290797664 4290534496 4291125087 4290667874 4290732388 4291322980 4290602086 4291257187 4290732389 4290929247 4290729820 4290798179 4291126376 4291127150 4290929764 4291124831 4290929508 4291323755 4290600031 4290797408 4290141280 4290272095 4290731877 4292116086 4293630342 4293500548 4292244837 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293037953 4292578683 4292906874 4292840332 4293036659 4292709242 4293101427 4292773747 4292970867 4292970874 4292970095 4292968300 4292577388 4292838255 4292839541 4292969838 4292773749 4292969585 4292644478 4293169012 4292907891 4293235591 4293632383 4293565057 4293564283 4293565052 4293562494 4293562222 4292443237 4292638841 4290993756 4290336615 4289282640 4288955993 4288690781 4288891228 4289022815 4289415005 4289481057 4290006616 4290006618 4290072410 4289481818 4289417565 4290070614 4290006875 4290531417 4289941083 4289415770 4290072410 4289480024 4290136919 4289878111 4290335324 4290730590 4291125858 4291124061 4290534753 4291388768 4291125856 4291453283 4291650915 4291190364 4291520098 4292044900 4291847267 4291718247 4291716185 4292111721 4291454821 4291914345 4291717472 4291519072 4291519073 4291324004 4291520606 4291781226 4291651680 4292045929 4292046185 4291520095 4291849582 4291980392 4292308843 4292045923 4292111714 4291980131 4292439910 4292241766 4291588195 4291782506 4292109414 4291782505 4292046183 4291257452 4291652453 4291980392 4292111458 4292505445 4291586411 4291455594 4291585645 4292111718 4291324526 4292045942 4291784061 4291126885 4291585382 4291585381 4291914603 4291783264 4291716458 4291389020 4291453804 4291784801 4291322214 4291521389 4291651680 4291846493 4291192686 4292176994 4291914857 4291520871 4292176995 4292111459 4292307815 4291847267 4291455339 4291586927 4291717732 4291454823 4291783008 4292044644 4291980128 4291914602 4291782751 4291322471 4292112233 4291060322 4291455858 4291453536 4291323491 4291256940 4291193192 4291125858 4291323238 4292045928 4290863721 4291126889 4291257437 4291584870 4290472562 4290600547 4291125860 4290731876 4290337630 4289812832 4290008669 4289417051 4289546339 4290006612 4290795349 4291388511 4291457382 4292245104 4292312422 4292249458 4292511609 4292840055 4292842363 4292644981 4292904821 4292116589 4292772970 4292969586 4292248428 4292772208 4292707956 4292511339 4292838255 4292839284 4292773749 4292970095 4292838512 4292378984 4292837726 4292838516 4292837726 4292641139 4292838256 4293035632 4292380528 4292970097 4292969839 4292446835 4292641129 4292970867 4292840313 4292446834 4292641385 4292314995 4292777065 4293639060 4293904265 4294037157 4294037409 4294038694 4294038694 4294038696 4294102674 4293178243 4291590760 4288562526 4289022046 4289679450 4289549404 4289944160 4290337888 4290336596 4290141799 4290863724 4290864219 4290075749 4291060580 4290797930 4290144872 4290928484 4289682778 4290994271 4290600032 4291321942 4291322464 4290010716 4291388518 4290798682 4290602082 4291454820 4290732388 4291585375 4290009439 4291455337 4290535785 4291126377 4291454046 4291256670 4290471784 4291519326 4290536285 4290729821 4290730851 4290075231 4290667097 4292968052 4292776837 4293823605 4290599012 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293036920 4292970615 4293035132 4293231717 4292970887 4293037175 4293231979 4292968556 4292511350 4293100139 4292970096 4292707184 4292970096 4292838512 4292640879 4292577389 4292970096 4292444773 4293232252 4293495671 4293629565 4293628276 4293171592 4293565301 4293566333 4293564279 4293562745 4293363564 4292510324 4292175459 4290994528 4290400087 4288887902 4288624731 4288691290 4289283420 4289150797 4289806947 4290072162 4289416282 4289414743 4290005592 4289873749 4290070871 4289415001 4290070091 4289285212 4290005331 4290070866 4290005337 4289416270 4290006619 4289875034 4290335059 4290731610 4290664021 4291124319 4291257184 4291323233 4291124822 4291716446 4291189588 4291846747 4291519324 4292111460 4291651680 4291323239 4291717217 4291322983 4291126627 4291979364 4290928996 4291980138 4292046441 4292110180 4291717218 4291455079 4291846750 4291979364 4291520096 4292373095 4291783272 4291586405 4291520869 4292242022 4291977831 4292439910 4291849577 4292109153 4292308056 4291783265 4291914339 4292045411 4291782248 4292110433 4292109415 4292111714 4291324268 4292046184 4291454564 4291455596 4292177250 4291782242 4291389291 4291063401 4291322984 4291590764 4291585636 4291783527 4291257437 4292110437 4291651168 4291650919 4291194211 4291326582 4291585118 4291324261 4291715678 4291914850 4291914336 4291520871 4292307302 4292046426 4291125351 4292177764 4291583331 4291586919 4291914335 4292045928 4291324268 4292243043 4291256162 4291717473 4290994789 4291650143 4290996337 4291651168 4291585377 4291257182 4291192419 4291716193 4290929514 4291847775 4291781994 4291651942 4291783008 4291388007 4291454813 4291192419 4291912037 4291126372 4291650656 4291191390 4291125087 4290732132 4290207335 4290403679 4289877598 4290006105 4289481818 4289414225 4290338914 4291126118 4291454819 4291980899 4292182901 4292247915 4292773492 4292840568 4292840055 4292840056 4292970614 4292905077 4292640881 4292640349 4292773752 4292246885 4292905333 4292444789 4292642421 4292380014 4292970096 4293100397 4292707184 4292970096 4292970355 4292574558 4292970355 4292970096 4292380269 4292838515 4292640094 4292380526 4293231213 4292380012 4292904822 4292577658 4292971124 4292837999 4293232759 4292313709 4292117610 4293173623 4293706905 4294102416 4294037668 4294037923 4294038694 4294038696 4294038420 4294101902 4293172860 4290339931 4288759134 4289742682 4289549680 4290009951 4290338144 4290273127 4290925651 4290208093 4290140512 4291125599 4290142818 4290928477 4291061098 4290206818 4290207853 4290142314 4290929252 4290798181 4290797926 4290798684 4291519582 4290535788 4290404190 4291256671 4290667109 4291256671 4290995039 4290469480 4290928989 4291191908 4291060068 4290994533 4291454563 4291126117 4291454046 4290468959 4291256927 4291257701 4291521388 4290271328 4288496467 4286719046 4284290634 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292969838 4292905332 4293035888 4293035645 4293232512 4293035132 4293036143 4292707184 4293100140 4293101686 4292706927 4293100397 4292970096 4292772720 4292575343 4292970353 4292707184 4293494636 4293167220 4292908411 4293235331 4293630070 4293563766 4293565560 4293563768 4293563770 4293431150 4293165164 4292507998 4292441451 4291320921 4290334811 4289085264 4289216333 4288626775 4289019213 4289348691 4289807957 4289676629 4290201429 4290136150 4290135894 4289545295 4290072667 4289480280 4289351004 4290595929 4289939789 4289546580 4290202963 4290005080 4289877086 4290531161 4289745245 4290860380 4290139999 4291188820 4291059809 4291190614 4290994791 4291323232 4291256932 4291191904 4291454815 4291125352 4291781476 4291520097 4292110437 4291914593 4291717218 4291454302 4292045921 4291454049 4291847268 4291586145 4291650907 4291914594 4291651682 4291979108 4292177508 4291585889 4291585888 4292111459 4292111459 4292176231 4292440151 4291652967 4292109158 4291914339 4291914859 4291717478 4292373095 4291520096 4292114027 4291127148 4291848799 4291717482 4292177507 4291781475 4292046185 4291585887 4291979108 4292045667 4291519840 4291125606 4292637029 4292109916 4290930544 4291782751 4291519841 4291453794 4291978078 4291193193 4291586668 4291979613 4292111980 4291715662 4291715943 4291257694 4291651425 4292045411 4291782762 4291780708 4291914858 4291846493 4291849569 4292175712 4291388775 4291783520 4292438630 4291783265 4291846750 4291912549 4291389022 4291519841 4291848544 4291387489 4290995045 4291848545 4291585634 4291255643 4291126372 4291781732 4291191644 4291061355 4292043364 4291126109 4291780709 4291651431 4291125598 4290994532 4291125598 4291192165 4291322462 4290076007 4290863463 4290205277 4290335579 4290465625 4290006617 4289480023 4289940569 4290860121 4291060324 4291980397 4291654259 4292183164 4292247914 4292511609 4292840311 4292776062 4292775791 4292772206 4292839798 4292838256 4292642421 4292839542 4292904303 4292970095 4293100139 4292971125 4292576105 4293034860 4293101680 4292904560 4293100397 4292970353 4292772720 4292970096 4292838257 4292574558 4292970355 4292838258 4292577389 4293101173 4292380012 4293100913 4292445549 4292772708 4292445806 4292577135 4292575079 4292774768 4293440896 4293970060 4294036384 4294038437 4294038180 4294037923 4294038698 4294103186 4293770869 4291658354 4289285210 4288695641 4289679194 4289418334 4290531930 4290338144 4290208350 4290337887 4290863462 4290206302 4290208354 4291059807 4289550692 4290207077 4291782237 4290731103 4290667356 4291060320 4290798940 4291388774 4291059295 4291519838 4290731615 4291454304 4291256927 4290863712 4291191136 4291454302 4291322975 4291323749 4291126373 4291322973 4291127147 4291125859 4291324265 4291126890 4291388511 4291717473 4290269787 4287705164 4284486211 4284095560 4284224322 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292706927 4293233268 4293232236 4292246638 4293101677 4292904303 4293034605 4293036147 4293036143 4292511092 4293101682 4293034861 4292772720 4292970095 4292970356 4292771934 4292772721 4292905333 4292774250 4293694323 4293694833 4293169278 4293565815 4293564537 4293565043 4293562989 4293236339 4293230957 4292506974 4291979103 4291586150 4290333271 4289085264 4288626775 4288623956 4289348177 4289349472 4289414741 4289544786 4289415257 4290201423 4289874265 4290595410 4289546328 4290071630 4290464858 4290070352 4289940052 4290596186 4289545039 4290007132 4290529872 4289811037 4290335836 4290794844 4290076001 4290666080 4291126374 4291060326 4291256927 4290992983 4291453531 4291780954 4291519588 4291779926 4291521376 4291715935 4291651169 4291256930 4292240737 4291520097 4290929770 4291914592 4291979108 4292177508 4291781733 4291651681 4291453538 4292110434 4291979364 4291846750 4291848297 4291914857 4292242022 4291848035 4292046180 4292109159 4292111971 4292045924 4292241761 4291980132 4291322976 4291848035 4291521126 4292370786 4291915369 4292307559 4291780957 4291586145 4291980393 4292045667 4291979363 4291585386 4291651680 4291913059 4291651439 4290928995 4292111202 4291454310 4291717483 4291913310 4291519330 4290994788 4291978594 4291127146 4291651424 4291717219 4291717474 4291651682 4292044644 4291586662 4291585631 4292179041 4291389030 4291455079 4291649124 4292045924 4291649379 4291846756 4291389542 4291454823 4292243299 4291454310 4291519072 4292241767 4291453537 4291585634 4291783008 4291125869 4291848544 4291388264 4291192420 4291780708 4291652200 4291452762 4291586407 4291587181 4291520096 4291651170 4291389022 4291717479 4291322974 4291060069 4291322463 4290075230 4290732392 4290926940 4290337118 4289810779 4290006885 4289483100 4289283925 4289286759 4290797149 4290930030 4292439143 4292180591 4292116338 4292577401 4292643192 4292971901 4292905081 4293101425 4292969838 4292774006 4292772462 4292969839 4293429100 4293035887 4292905332 4293037178 4292706669 4293035647 4292904302 4292904303 4292904560 4292772719 4292970095 4292706928 4293101680 4292970097 4292707187 4293099611 4292970355 4292182107 4293166961 4292117371 4292381042 4292116589 4292642670 4292182884 4292247919 4292313195 4292973446 4293705347 4294102947 4294037666 4294037409 4294038694 4294038694 4294038955 4293971855 4293830258 4290867314 4289414481 4289612633 4289679195 4289418334 4289877085 4290862945 4291322981 4290140766 4290272869 4290864738 4290601565 4291584863 4290140767 4290207078 4290140767 4290731360 4290731103 4290994272 4290075749 4290994783 4290732389 4290863973 4290666335 4291125087 4290929248 4291519839 4290403941 4291388511 4291125599 4291322974 4291518818 4291125342 4291455075 4291586668 4291914854 4291126624 4290137433 4286458182 4284748614 4284356925 4284291908 4284291907 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293233267 4292969597 4293166443 4293101682 4292708213 4293036144 4293034859 4292839027 4293297515 4292708213 4293035887 4292970096 4292772720 4292970099 4292707184 4293100398 4292970350 4293168506 4293366133 4293302399 4292973683 4293302397 4293628799 4293236592 4293236081 4293430900 4293299575 4292838496 4292899932 4292834143 4290992719 4289808216 4289348692 4288624723 4289281870 4288496207 4289412429 4289610579 4289676886 4290071384 4289283673 4290597467 4289284954 4290072154 4289352031 4290530380 4289545553 4290004820 4290004813 4289676632 4289414738 4289941084 4290337111 4290858324 4290664792 4291451227 4290535521 4291122266 4291125344 4291059552 4291125857 4291453533 4291780190 4291519580 4291979362 4291517786 4291519580 4292109928 4291716705 4292045157 4291585121 4292243043 4292111716 4292110183 4291388519 4292045924 4291651681 4291847519 4292308568 4291388520 4291847517 4291782506 4292111715 4291913572 4291913828 4292241766 4291849824 4291847780 4292636004 4292242264 4291715941 4292177507 4291915113 4291979618 4291849060 4292109416 4292110422 4291782763 4291847266 4292046440 4291059301 4291848553 4292175205 4291980650 4292111715 4292045410 4291454823 4292111971 4291912292 4291454301 4291847781 4291650142 4291717217 4292045668 4291848800 4292438888 4291388770 4291649118 4291783521 4292044644 4291782505 4292243308 4292111459 4291914083 4292242787 4292045668 4291389286 4292045156 4291847524 4291849056 4291716449 4291191142 4291913832 4291455853 4291913059 4291586398 4291519841 4291979621 4291388263 4291323486 4291585634 4291783009 4291584864 4291257955 4291257439 4291453025 4291519328 4291584866 4290994270 4292044900 4291192937 4291191908 4291060067 4291125861 4290666597 4291322206 4289616225 4289877341 4290466651 4289943388 4290073180 4290070613 4289415009 4290336859 4291192168 4291522417 4291654256 4292772207 4292510835 4292837740 4292972414 4293102199 4293036921 4292708211 4293101422 4292971124 4292510835 4293233015 4292839539 4293036916 4293298802 4293364859 4292970349 4292840053 4293429106 4293034604 4292970101 4292708470 4292970095 4292904304 4292904561 4292969310 4292772980 4292772464 4292577135 4292248429 4292969584 4292903791 4292773750 4292248428 4292970615 4291855209 4292247662 4292839018 4293241720 4293838215 4294036899 4294037666 4294038694 4294038694 4294038694 4294038698 4293968263 4292251494 4289810261 4289611362 4288828257 4289614942 4290008927 4290270292 4290730851 4290928480 4290272095 4290141542 4290732115 4290797665 4290862944 4290076764 4291256413 4291256415 4290143078 4290142043 4290731877 4291387999 4290798437 4290534238 4291322460 4291125862 4290731871 4290666079 4291257701 4291322975 4291125599 4291127146 4290928740 4291257181 4291586668 4291849318 4291651680 4290336607 4287179081 4284819793 4283895611 4284158526 4284291907 4284489033 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293035388 4292905587 4293035891 4292904303 4293035890 4293231979 4292970112 4293232235 4292839031 4292904558 4293034605 4292707185 4292773738 4292772720 4293100396 4292840052 4293429882 4292973680 4293300863 4293302389 4292974465 4293302132 4293302384 4293301617 4293235569 4293430389 4293494892 4293494125 4292442210 4292176218 4291321442 4290400602 4289150800 4288103258 4288628315 4289215822 4289151058 4289612122 4290069586 4290005850 4290464850 4289874773 4290006874 4289940826 4290006874 4289940057 4289806419 4290072668 4289416536 4289610827 4290201682 4289874258 4290334555 4290138713 4290727758 4290535258 4291122524 4291125081 4291059552 4291191392 4291518813 4291060321 4291191127 4291586148 4291255641 4291978592 4291322979 4291715934 4291321954 4291454305 4292243044 4291191911 4291780965 4291783776 4291650913 4291781220 4291846756 4291388769 4292175722 4291783520 4291979108 4291520352 4292044637 4291520610 4292109408 4291849578 4292437603 4292111971 4292043622 4291715428 4292045667 4291322982 4292373094 4291849321 4292242016 4291519069 4292109672 4291587173 4291782505 4292046183 4291848296 4291848297 4291585123 4291782499 4291979619 4291586662 4292044642 4292109414 4291388774 4292044899 4291979364 4292044900 4291849057 4291651425 4291454055 4291586145 4291847509 4292045670 4292177509 4291389278 4291585632 4292505445 4291650920 4292374380 4290798441 4291650656 4292046442 4292044894 4291453280 4292111979 4291585888 4292044900 4291781987 4291717216 4291322727 4291126884 4291978853 4291519323 4291126110 4292044390 4291126110 4291585633 4291584879 4291191660 4291651168 4290995300 4292043620 4291717473 4291388775 4291717990 4291454310 4290928739 4291126634 4290797148 4290666597 4290600288 4290927959 4289745252 4290402652 4289944172 4289418589 4289482341 4289545554 4290006885 4290075483 4291913593 4292310636 4292116849 4292443773 4292642675 4292970615 4292644478 4293299574 4292906367 4293036658 4292906622 4293102457 4292841080 4292971129 4292971889 4293561728 4293103727 4293364590 4292970351 4292970350 4292904303 4292904303 4293493353 4292904560 4292904560 4293034861 4293035120 4292903774 4293168241 4292116332 4292772465 4292705893 4292314222 4292511340 4292969328 4292707701 4292446323 4292511086 4292114278 4293237113 4293703302 4294100090 4294038184 4294038180 4294038694 4294038694 4294038697 4293971854 4293310607 4291461223 4289218648 4289679451 4289548380 4290005848 4290401116 4290339677 4289679965 4290272352 4290863461 4290665824 4290665568 4291717472 4290862944 4290665823 4290732134 4290140510 4290731876 4290733672 4290797406 4290599774 4291323493 4291191136 4290733146 4291257445 4290994533 4291322974 4291257439 4291191646 4291586150 4291586150 4291783270 4291850858 4291715934 4289742423 4286587719 4284616514 4284359751 4284752461 4284094524 4284687182 4284423496 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292904558 4292904303 4293297514 4292904560 4292904307 4292969325 4293232236 4292839024 4293230440 4293231484 4292970863 4293034861 4293100397 4292511350 4293231982 4293364858 4293168247 4292973442 4293302644 4293234558 4293300851 4293693306 4292907884 4293300605 4293431667 4293233268 4293167728 4292706161 4292572764 4291847516 4291584352 4290333015 4289281098 4288625740 4289280076 4288496464 4289151052 4289612116 4290071380 4289282125 4291055706 4289875029 4289873751 4290532187 4290069844 4289940056 4290071378 4289546586 4290201418 4290201683 4289479755 4290464084 4290270294 4290792788 4290665825 4291187034 4291123798 4291057493 4291454052 4290994016 4291257696 4291912032 4291453534 4291715167 4291913574 4291847013 4291453787 4291718249 4291519330 4291912286 4291979876 4291585889 4292307800 4292109416 4292110432 4292109671 4291783520 4291848294 4291520593 4292174952 4292242278 4292505702 4291454833 4292373335 4291914341 4291914848 4292307558 4291651177 4292112494 4291914856 4291915113 4291977831 4291651415 4292439911 4292374374 4291913829 4292109664 4291977062 4292373349 4291125868 4292438885 4291520352 4292177251 4292111459 4291980648 4291651439 4291980649 4291913570 4292046440 4291782762 4291781981 4291847523 4291847524 4291849056 4291848041 4292045412 4291651682 4291454561 4291387745 4292044900 4292111459 4291850603 4292243051 4292375649 4292505446 4291979107 4292044899 4291453280 4291521645 4291650655 4292044900 4291980131 4291979108 4291849313 4291715684 4291782241 4291651937 4291715684 4291781482 4291126109 4292174946 4291256418 4291979107 4291717472 4291520103 4291847016 4290930281 4291978083 4291520102 4291978851 4291323239 4291914080 4291191651 4290798700 4290600803 4291256671 4290599262 4290861917 4290203738 4290471529 4290005590 4290008154 4289547375 4289414227 4290337638 4291059551 4291918193 4292247669 4292051057 4292771947 4292382079 4293363575 4292710526 4292711795 4293233784 4293036667 4293035373 4293167219 4293561721 4292973435 4292970609 4292841589 4293168512 4293167218 4292969598 4293233267 4293037435 4292970350 4293035893 4292904558 4292903021 4293035118 4292968558 4292706928 4293102710 4292640880 4292510313 4292445037 4292315508 4292182124 4292183667 4292445037 4291919461 4292248430 4292639343 4293308023 4293839265 4294035852 4294037667 4294037923 4294038694 4294038694 4294038441 4294101900 4293172858 4290338912 4289545569 4289612633 4289482843 4289941595 4290338145 4290928736 4290861405 4290142556 4291321952 4290010973 4291125087 4290928736 4290272351 4290339420 4290732636 4291258482 4290076249 4290994536 4290799713 4290732388 4291322205 4290472564 4291585628 4291716961 4291257956 4291322471 4291913828 4291978850 4292046185 4291849319 4291127137 4289480532 4285733699 4284419651 4283831862 4284157260 4284291906 4284094783 4284877110 4284554309 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292904561 4292969837 4292709258 4293034603 4293233519 4292969069 4292970351 4293167737 4293167727 4292970351 4293034604 4293101682 4292707183 4292772463 4292905589 4293232499 4292842107 4292973426 4293103727 4293563000 4292777596 4293235566 4293366912 4293232754 4293628793 4293430905 4293100910 4292968540 4292507503 4292244847 4291125863 4290007389 4289349216 4288691278 4288560208 4289282643 4289741903 4289544788 4289808465 4289806926 4290070102 4290070101 4290532187 4289283416 4290005592 4290005336 4289349465 4290660947 4289742416 4289350999 4290005588 4290399322 4290268241 4290730078 4290729814 4290664535 4290535267 4291323234 4290468440 4291124568 4291584605 4291125857 4290861911 4292044897 4291716700 4291650405 4292109155 4291651163 4291912543 4291586402 4292110951 4292044900 4291782756 4291388518 4292177507 4291521126 4292046441 4291780963 4292175976 4291389542 4291781219 4291979363 4291979363 4291716191 4291781988 4292373094 4291193453 4292701529 4291847779 4292111715 4292242024 4292044128 4292109672 4291651427 4292242023 4291848029 4292373601 4291518307 4291717481 4292638561 4291258988 4292175206 4291717225 4291783273 4292109925 4291388511 4292111715 4292373350 4291520367 4291847266 4291914344 4291324012 4291322469 4291520359 4291717734 4291848800 4291716705 4291649637 4292110686 4291979364 4291980649 4291980135 4291980134 4291717741 4291980134 4291716968 4291848040 4291717990 4291455595 4291848291 4291848296 4291651439 4291848806 4291519073 4291716961 4291517796 4291912548 4291718246 4291717990 4291716459 4291454562 4291650651 4291322210 4291781477 4291519328 4291914090 4291717215 4291715946 4291322726 4291321953 4291978852 4291585639 4291059811 4290538348 4291191138 4290534751 4291253336 4290665054 4290927710 4289810786 4289875812 4290531416 4289416023 4289545814 4289811301 4290733164 4290864497 4291783789 4292772204 4292313484 4292708982 4292905074 4293036406 4293038723 4293168252 4293037181 4292841839 4293232506 4292971886 4292972419 4292973434 4293429369 4292973422 4293169530 4293035628 4292838767 4293035885 4292840052 4293233271 4293231226 4292904816 4292968556 4292904560 4293363308 4292182892 4292969585 4292575591 4292118388 4293361001 4292183667 4292707948 4292576119 4292445549 4292640626 4292116060 4292707181 4293965173 4293904524 4294037925 4294038180 4294038694 4294038694 4293973160 4294036882 4294032262 4292184951 4288429906 4289481552 4289547365 4290007643 4290336605 4290272100 4290270047 4290206560 4290665824 4291651167 4290863718 4290010715 4291520101 4290863462 4290667100 4290862686 4291060325 4290078819 4291256419 4290601321 4290732387 4291257186 4291126891 4291453024 4291322470 4292111976 4291520613 4292308844 4292243043 4291125855 4289675345 4285604426 4284354363 4284029001 4284422978 4284093515 4284687180 4284487740 4284355148 4284815677 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293035389 4293101684 4292904301 4293034859 4292577142 4293427817 4292972149 4293165931 4293167474 4293233266 4292904305 4292708216 4292970097 4292970095 4292970612 4292841582 4293365893 4293366643 4293495928 4293368438 4292580210 4293823859 4292972918 4293103728 4293298803 4293233530 4293559914 4292836718 4292967008 4292373862 4291257437 4290468458 4288759121 4288232527 4289216336 4288889423 4289085516 4289349208 4290201687 4290005331 4289942872 4290464857 4290005842 4290071124 4289939027 4290072663 4289676368 4289349454 4290007390 4290135632 4290069579 4289808723 4290336350 4290859098 4290141531 4290728020 4291190096 4291188572 4291124825 4291059809 4291125857 4291256157 4291519070 4291060064 4291387740 4291715941 4291257950 4291913061 4291782245 4291781214 4292177508 4291388000 4292043367 4291652710 4291977575 4292044899 4291782761 4292044900 4291913827 4291849057 4291651169 4291583588 4292110183 4292111972 4291781220 4291913827 4292109414 4292176743 4291979107 4291781727 4291914325 4292308073 4291715683 4291848548 4291649891 4292373607 4291125607 4292044898 4292111971 4291847021 4292109664 4291716191 4292043361 4291718496 4292309353 4291848298 4291650921 4291388000 4292110435 4292044643 4291392624 4291783269 4291519846 4291980128 4291454822 4291980138 4291257185 4291978079 4291454562 4291846756 4291585887 4291848808 4291849325 4291851374 4291786867 4292373603 4291585903 4291716958 4292111977 4291847523 4291322470 4291651679 4292047206 4291322471 4291520097 4291520097 4291912548 4291322470 4291520098 4292110687 4291978837 4291191145 4291190626 4291585121 4291322984 4291715172 4291914085 4291454560 4291979108 4291519586 4291913310 4291191646 4291126629 4291124571 4290996345 4290665828 4290672504 4290729819 4290138459 4290337374 4290532697 4289874017 4290073188 4289414486 4290532698 4290139483 4291783787 4291982436 4292118392 4292837482 4292446073 4292970869 4293234044 4293038715 4293037691 4292973177 4293234047 4292839281 4293036666 4293234045 4292970615 4293039723 4292970874 4293364344 4292841088 4293231466 4292840056 4293296762 4292970349 4292643707 4293295976 4292708470 4292774005 4292839542 4292706415 4292511600 4292510838 4292969328 4292707434 4292250745 4291855209 4292510829 4292247918 4292248174 4292444266 4292311911 4293171579 4293837704 4294036898 4294037668 4294037923 4293972902 4294236583 4293973143 4293905551 4293830257 4290079594 4289414488 4289617506 4289414743 4290404706 4290333527 4290273642 4290928223 4290141024 4290796896 4290076764 4291323500 4290534239 4290667099 4290733417 4290208353 4290077284 4291322211 4290602604 4290603370 4291323496 4291125859 4291979615 4291127401 4291717732 4291783534 4291981668 4292047724 4291782501 4289084752 4286193734 4283700795 4283698239 4284622155 4284097358 4284357438 4284487750 4284160837 4284947520 4284488516 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292904559 4292707183 4293100394 4292970110 4293429104 4292773230 4292969598 4293233261 4292839797 4293035887 4292903550 4293036139 4293034108 4293034602 4292839538 4293430918 4293366635 4292581505 4293432958 4292643182 4293103990 4292776309 4293038453 4293168506 4293101683 4293299322 4293035373 4293492586 4292116591 4292373606 4291717218 4289811297 4288627537 4288755276 4288821840 4288693587 4289741898 4289938511 4289872468 4289482069 4290007394 4289873484 4290530644 4289479755 4290596180 4289350736 4290071125 4290005583 4290004814 4290005595 4289940046 4290398291 4290334812 4290203476 4290792528 4290732901 4290531931 4291256159 4291059032 4291387487 4291519323 4291649371 4291780961 4291060063 4291388515 4291913310 4291978080 4291651937 4292045669 4292175202 4291520609 4291847524 4291849312 4291455079 4291849312 4291781219 4291518570 4291257949 4292175207 4291586401 4291846750 4292112228 4292111971 4291979364 4291781476 4291914339 4292046179 4292043622 4291783786 4291781989 4291979360 4291715679 4292175457 4291323233 4292308071 4291845467 4292044898 4291586160 4291518044 4292308071 4292112229 4292107353 4291322979 4292045924 4291978088 4291256410 4291715173 4292110949 4291389790 4291650405 4292108890 4291651937 4291913317 4291453793 4291781476 4291126884 4291780703 4291323743 4291715173 4291651936 4292176493 4291848296 4291454820 4291914861 4291256937 4291389285 4292110433 4291258477 4291454047 4292044899 4291323244 4291847267 4292373351 4291455069 4291717218 4291651938 4292110686 4291323758 4291583320 4291124835 4291388515 4291192159 4291649116 4291782499 4291585116 4291519580 4291715423 4291519586 4291518047 4291715423 4291847780 4291585122 4291518818 4291125860 4290600548 4290666596 4290665050 4290732649 4290861917 4290335578 4289286503 4290075229 4290071137 4289481303 4290008166 4289745755 4291060840 4291848554 4292117119 4292379778 4292511608 4292839024 4292710530 4292971387 4292644737 4293431932 4293166959 4293234048 4292840295 4292971128 4293234045 4292645756 4293232499 4293166956 4292907383 4292971380 4293035886 4292707183 4293297772 4292904303 4293034861 4292970095 4292968300 4292182892 4292904048 4292707434 4292706416 4292511597 4292116846 4292772207 4292837745 4292182381 4292445294 4292445551 4292442469 4292246633 4292576106 4293636232 4293970315 4294036367 4294038697 4294038694 4293972902 4294171048 4294037926 4293576337 4292711010 4289612885 4289544789 4289484640 4290532187 4289811286 4290338138 4290206561 4290271319 4290075489 4290860115 4290797664 4290996316 4290863721 4290732635 4290140511 4290797669 4290665566 4290733925 4290865258 4290472305 4291455334 4290930030 4291652202 4291849325 4291783533 4292113260 4292241761 4288823116 4285143621 4284490573 4284355660 4284163149 4284488775 4284556623 4284291908 4284159300 4284750143 4285404726 4284947780 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293166701 4292970097 4292706428 4293035644 4293102199 4293363570 4293363562 4292969598 4293233266 4293035133 4293036139 4293035389 4292904300 4293037177 4292972414 4292973682 4292973445 4293431923 4292974196 4293039228 4293103477 4293627007 4292841590 4293231209 4293101934 4293299060 4293363572 4292837213 4292573536 4292571486 4291256414 4290400347 4289348681 4288626001 4288690253 4289348685 4289085518 4289740621 4289676875 4289415002 4290530386 4289873491 4289874522 4289806163 4290007126 4290005331 4290135889 4290005839 4289610828 4289415246 4289939029 4290334295 4290334799 4290270815 4290728284 4290661961 4291191651 4291059031 4291125604 4291058255 4290993498 4291125081 4291782743 4291585891 4291714395 4291913830 4291123801 4291584867 4291520856 4291586402 4292175201 4292045156 4291650405 4291649630 4291781476 4292175719 4291322207 4291322727 4291847011 4291912548 4291584100 4292109665 4291781220 4291847013 4291584094 4292242024 4292374631 4292439654 4291911521 4291715931 4292109668 4291781470 4291782501 4291781213 4292109412 4292112760 4291653482 4292373092 4291978599 4291977057 4291715934 4292110436 4292043100 4291977572 4291779411 4291914081 4291519834 4291452506 4292108893 4291452517 4291519586 4291715173 4291519579 4291780959 4291519586 4291520098 4291780703 4291520355 4292108635 4291256162 4292242526 4291453536 4291716457 4291848807 4291848807 4291848296 4292109414 4291651679 4291454311 4292175974 4291389542 4292111203 4291388001 4291978085 4291716191 4291648860 4291715423 4291715172 4291717218 4291780959 4291782498 4291583583 4291322467 4291585122 4291321954 4291978335 4291518048 4291781983 4291322467 4291452248 4291915116 4291585121 4291321435 4291125859 4290536042 4291190619 4290996602 4290731355 4290137700 4290399832 4290007899 4289415513 4289481560 4289549415 4289353319 4290404198 4291060582 4291916397 4291655541 4292706157 4292707951 4292774023 4293103744 4292711032 4293103489 4292840315 4293037956 4292974191 4293232002 4293036913 4292906623 4292904817 4293167219 4293036923 4292905578 4293234555 4293035886 4292706927 4292970098 4292904303 4293036147 4292969842 4292774005 4292838255 4292903791 4292248429 4293101424 4292509802 4292379758 4292706672 4292577133 4292247918 4292641130 4292443751 4292116854 4291853675 4292245864 4293039473 4293311372 4294101903 4294037667 4294038694 4293972902 4294170534 4294170793 4294169234 4293702522 4291132275 4289348695 4289612371 4289417053 4290008671 4290270558 4291127645 4290272352 4291584862 4290076006 4290600031 4291585375 4290534239 4290864733 4291256160 4290667356 4290928478 4290077031 4291389289 4291125345 4290995823 4291126375 4291258727 4292374122 4292047974 4291716708 4289412428 4285800275 4285283939 4283833164 4283830079 4284158775 4284552005 4284223038 4284420914 4285140807 4284748854 4285015120 4285472844 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293362281 4292708468 4292969341 4292969066 4293363570 4292970357 4293299312 4293167726 4292970355 4292905586 4293035898 4292969852 4293035884 4292971129 4293561975 4293234555 4293759606 4292973434 4293365628 4292973937 4293364084 4293101683 4293036920 4292841344 4293364340 4293299059 4293101941 4293230957 4292444260 4292374121 4291319892 4289938769 4289477450 4289215310 4288098379 4288754766 4289151565 4289742674 4289872469 4290005843 4290464077 4290399578 4290463825 4290008927 4289348695 4290071130 4289414995 4290070356 4290136151 4290135122 4290399566 4290924883 4290268757 4290266700 4290729045 4290730072 4290535265 4291125602 4291057492 4291191130 4291780699 4291125857 4291648865 4291192677 4291519586 4291912549 4291716191 4291322984 4291322210 4292304229 4291586657 4291257192 4291454043 4292109154 4291847780 4291847779 4291256934 4292045928 4291650409 4291455334 4291979363 4291979620 4291781477 4291846997 4291649633 4292176217 4291781982 4291519587 4292109921 4292109929 4291980373 4291584102 4291584100 4292308070 4291520623 4291717478 4292701031 4291718245 4291980639 4291782244 4292043362 4291845209 4291387233 4292108887 4291650402 4291909985 4291518562 4291781466 4291452512 4291913829 4291453792 4292108647 4291519842 4291387746 4291387746 4291979104 4291191904 4291387484 4291585890 4291192678 4291321691 4291782507 4291322720 4291519846 4292111976 4291388517 4291980130 4292174950 4291652454 4291782505 4292110177 4291390317 4291584858 4291322210 4291454049 4291979109 4291257185 4291979876 4291387489 4291388513 4291585890 4291519843 4291780952 4291322979 4292044645 4291519330 4291323743 4291780959 4291715423 4292110950 4291321946 4291453282 4291126628 4291061099 4291125084 4290535528 4291125601 4290602865 4291321179 4289745244 4290399833 4289875546 4290006618 4290004564 4290532183 4289617519 4291518831 4291651191 4292309095 4292116848 4292576144 4292840818 4293297534 4293036661 4292972412 4293103484 4292448114 4293431421 4293166465 4292905074 4292905074 4293036921 4293232755 4292905332 4293035887 4292970094 4293233269 4293035890 4292708213 4293101426 4292904303 4292904302 4293101429 4292772719 4292642421 4292707956 4292444788 4292773493 4292313965 4292969328 4292380787 4292182124 4292641911 4292445550 4292312167 4291853933 4291983968 4292510062 4293504887 4294101395 4294036385 4294038180 4293972902 4294170534 4294368678 4293972648 4294101900 4292976758 4289484124 4289481301 4289940560 4289943135 4290469473 4289614173 4291192678 4290667879 4290668648 4291387998 4290535269 4291126111 4290665312 4290667613 4290598236 4290995820 4290077280 4291125603 4290666852 4291323234 4292308322 4292045671 4291915632 4292109400 4288823890 4285733444 4283633466 4284620619 4284421184 4283960648 4284615992 4284225605 4284814136 4284684864 4285337141 4285406789 4285931594 4285207093 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292971899 4293035889 4292970349 4293429100 4292970351 4293101941 4293298028 4293100651 4293166979 4293035891 4292970349 4293232754 4292578687 4293824887 4293235575 4293303923 4292975227 4292973178 4293302126 4293168001 4292840299 4292970350 4293035890 4292905074 4292972138 4293298811 4293102702 4293165422 4292835918 4292307046 4291518027 4290334543 4289083985 4288691021 4288690510 4289150800 4289678159 4289805906 4289481037 4290071130 4289283667 4290005330 4289874265 4289939544 4290531931 4290005324 4289547869 4289414995 4290071129 4289545297 4289939795 4290335325 4290332492 4290269533 4290730584 4290664278 4291122780 4291124824 4291125602 4291058775 4290994273 4291323233 4291454291 4291191904 4291584860 4291519581 4291913568 4291780955 4291585123 4291126367 4291978847 4291912542 4291978341 4291520353 4291256935 4291848291 4292504678 4290733423 4291780450 4291454304 4292439143 4291716451 4292175463 4291980133 4291651937 4291388002 4291650148 4292177005 4292110688 4291912550 4291912546 4291977569 4291781726 4292305764 4292043359 4291586661 4292308842 4291521649 4292110955 4291978604 4291845729 4291452767 4291977316 4291517528 4291190879 4291190102 4291648851 4291125343 4291583834 4292108642 4291520616 4291454049 4291583577 4291060320 4291387997 4291583578 4291190365 4292044896 4291321954 4291453276 4291717986 4291650147 4291782240 4291585632 4291257190 4292108901 4291651695 4291849064 4291847009 4292111976 4291455595 4292111202 4291520872 4291585115 4292108392 4290994526 4291650658 4291584865 4291060836 4291454055 4291387745 4291518047 4291913063 4291453275 4290994527 4291780959 4292174946 4291124834 4291124833 4291979620 4291322984 4291388513 4291453282 4290993758 4291126118 4291123804 4291125598 4290533991 4291322720 4289611864 4290862944 4290923350 4290400344 4289876068 4290335339 4290797923 4290995047 4291914601 4292049533 4292116591 4292575608 4292642694 4292774275 4292708485 4293234043 4292972417 4293102972 4292970368 4292907628 4292709242 4293298289 4292709241 4293036921 4292708212 4293233007 4293167734 4292970354 4292971113 4293297516 4292511350 4292970093 4293101684 4292708213 4292968300 4292971637 4292642164 4292904819 4292643451 4292707177 4292248429 4292576880 4292969584 4292379756 4292247918 4292313967 4292312425 4292378219 4291917920 4292775789 4293837452 4294101903 4294037669 4294038694 4293972902 4294104742 4294170790 4294104236 4293770608 4291594105 4289214796 4289483102 4290072923 4289811806 4290928216 4290205783 4290140769 4290732892 4290798181 4290666341 4290667357 4290732893 4290665312 4291454821 4290206813 4290666341 4291454820 4291388253 4291258473 4291455084 4292245101 4290797153 4289478736 4285928253 4283699015 4284548165 4284488252 4283898183 4284421701 4283831863 4284879433 4284619070 4285013062 4285077566 4285538895 4284421178 4285148242 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292970350 4293167731 4293166972 4292969854 4293167476 4293560689 4293101941 4293167476 4293167474 4292971378 4293364602 4293168497 4292972923 4292907891 4293300099 4293301379 4293301366 4293300861 4293693561 4293038192 4293167215 4293233011 4292707458 4292839298 4293561971 4293430644 4293233526 4293560172 4292770405 4292504408 4291125596 4290333268 4289151053 4287969870 4289279050 4288430928 4289544018 4289415000 4290003540 4289349721 4290595928 4289811550 4290532696 4289544776 4289941084 4290005587 4289676374 4290201681 4290006615 4290070349 4289874266 4290333528 4290334548 4290267474 4290728788 4290665313 4291124319 4291124825 4291059808 4291191649 4291320922 4291126113 4291256164 4291649119 4291783523 4291321177 4291519587 4291387746 4291323743 4291585634 4291322722 4291847262 4291125609 4291582811 4291913573 4291913316 4291453536 4291520614 4292045923 4291913828 4290994022 4291914346 4291584611 4291979363 4292109671 4292175463 4291389024 4291847779 4291977062 4291978860 4292109919 4292043879 4291454817 4291847011 4291192428 4291848808 4291915112 4292109156 4291914338 4292046442 4291586657 4291519586 4291518298 4291584092 4291582552 4291649885 4291255637 4291715170 4291388254 4291190879 4291124057 4292111205 4291715429 4291781221 4291780959 4291519837 4291453539 4290994528 4292240739 4290797148 4291976802 4291914345 4291324012 4291323494 4291583848 4291520869 4291586405 4291322987 4291980910 4291257444 4291389547 4291715683 4291388263 4291059806 4291586663 4291453282 4291321955 4291782496 4291388263 4291650657 4291782497 4291715424 4291715673 4291125609 4292044644 4291387746 4290928990 4291847525 4291781732 4291520353 4291715172 4291978852 4291783009 4291914337 4290994015 4291124060 4290534246 4291255388 4290075745 4290862174 4290793560 4290270555 4289877609 4289875031 4290336352 4290733180 4291060325 4291917422 4292307557 4291986305 4292838781 4292642415 4292970368 4293100666 4293036655 4293103746 4292643446 4293102454 4292774023 4292773487 4293101960 4292707952 4293430137 4292970350 4292970351 4293166187 4292970358 4293035889 4293035891 4293100138 4292903806 4292903548 4293101677 4292904816 4292968043 4292839540 4292643194 4292642666 4292969844 4292905076 4292248428 4292904047 4292574832 4292445549 4292246375 4292312425 4292312683 4291982944 4292311657 4293504633 4293838219 4294037395 4294038185 4293972906 4294368935 4294170276 4293972903 4294235305 4293308012 4290273374 4289348942 4289482841 4289941592 4290927711 4290139743 4290994263 4290729821 4290863975 4291060569 4290861150 4290667101 4290732635 4290666859 4290666340 4291322462 4291126116 4291323491 4291127145 4292113245 4290993246 4289545037 4285600060 4283893820 4284354876 4284488509 4284420414 4284685380 4284420669 4284619589 4284619069 4285208638 4285143359 4285077823 4285338679 4284948037 4285275463 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293166443 4293165690 4292970109 4293362278 4293102198 4293100394 4293167221 4292971379 4293166962 4293366143 4293101424 4293169029 4293301107 4293695614 4293302133 4292975482 4293366900 4292974202 4292907895 4293561455 4293167214 4292971643 4293035885 4293167469 4293299061 4293233262 4293300074 4293099628 4293164399 4292637008 4291453272 4290529112 4289217610 4289282129 4288625744 4289545551 4289085522 4289282894 4289742674 4289871948 4289808985 4290530135 4289810011 4290006876 4290008415 4290134864 4289611089 4289611083 4289676632 4289545297 4290465107 4290268243 4290333266 4290269784 4290729823 4290596426 4291124055 4291123286 4291125345 4290994274 4291584862 4290927704 4291518299 4291453533 4291126368 4291780960 4291783266 4291321954 4291912798 4292109160 4291717473 4290929509 4292109401 4290928992 4291781726 4291454568 4291520097 4291914083 4291977831 4291782755 4292175463 4291781213 4291782244 4292110696 4291913827 4292109670 4292175462 4291192166 4291848547 4291782754 4292177004 4291387497 4291649636 4292175712 4292042854 4292175461 4291716194 4291717225 4292373607 4291518551 4292238687 4291651693 4291911511 4291518555 4291584098 4291125335 4290994531 4290927959 4291715165 4291254859 4291584098 4291780959 4291060063 4291190370 4291454564 4291846496 4291453534 4291714906 4291060320 4291323233 4291190620 4291519328 4291716713 4291978594 4291980393 4291323237 4291387232 4291389029 4291521129 4291979106 4291520612 4291913315 4291585120 4291190887 4291651425 4291387484 4291979093 4291651179 4291650657 4290994526 4291585896 4291585122 4291518042 4291651425 4291323496 4291060063 4292240739 4291124827 4291585378 4291124577 4291979364 4291388263 4290928738 4291256691 4291387233 4291059808 4291125600 4291124318 4290073428 4290926430 4290202465 4290335332 4289873748 4290333270 4290334820 4290141019 4291126632 4291520127 4291783529 4291653998 4292444283 4292575355 4292446328 4292970864 4292972413 4292708230 4293299830 4293036661 4292970117 4292775032 4292970608 4292577401 4292906879 4293232755 4292839802 4293233269 4293231724 4292904794 4292905334 4292773748 4293166957 4292708211 4293035390 4293100139 4292316274 4292969584 4292775291 4292969583 4292971870 4292970373 4292837996 4292904830 4292576116 4292183665 4292446076 4292116340 4292444522 4292375640 4291917151 4292770672 4293571190 4294100851 4294037122 4294038145 4293972372 4294172085 4294368676 4293973161 4294365838 4292780456 4289943935 4289678968 4289877626 4289875801 4290928472 4290730592 4290139743 4290730838 4290600033 4291062108 4291060320 4290207334 4290733409 4290863458 4290666852 4291192424 4290996078 4292309097 4290796644 4289745503 4286194522 4284024658 4284552024 4283895639 4284752715 4284357954 4284619588 4284484668 4285080909 4285142589 4284882501 4285338680 4285143359 4284683320 4285340735 4285277777 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292971897 4292970355 4292970349 4292970354 4293363311 4293168762 4292972143 4293364345 4292971127 4292971646 4293169011 4292776058 4293301627 4293235316 4293236350 4293365371 4293235573 4293365638 4293302122 4293102192 4292970354 4293233011 4293035890 4292970351 4293299060 4293299067 4293297773 4293231214 4292376399 4292702802 4291254102 4289939531 4289348683 4288099917 4288102992 4289084751 4289546066 4289415000 4289674832 4290007645 4290726230 4289808211 4290529875 4290004819 4289414733 4290071118 4290007390 4290200657 4289807691 4290332753 4290200660 4290529616 4290269275 4290205022 4290728787 4291254878 4291122781 4291123798 4291060066 4291385932 4291321951 4291387487 4291322455 4291125857 4291649370 4291780954 4291520098 4291519586 4291715429 4291584351 4292175457 4291715941 4291454042 4291979360 4291452518 4292108641 4291976796 4291716197 4291847780 4291389542 4292176230 4292175720 4291781470 4291518553 4292176232 4291389798 4291847779 4291847779 4292109158 4291452776 4291650918 4291847010 4292175713 4291782244 4291257440 4291519337 4292702057 4292242277 4291256169 4292108904 4291650912 4291845717 4291452770 4291584091 4291584091 4291190878 4291320411 4291322207 4291320916 4290863458 4291714911 4290994528 4291651427 4291849061 4290992206 4290994275 4291059031 4291124575 4291321950 4291518298 4291256157 4291781733 4291585637 4290863977 4291322206 4292046703 4291323237 4291388771 4291848824 4291455592 4291586934 4291520101 4291780707 4291651686 4291190887 4291454055 4291126885 4291978851 4291322209 4291781220 4291583588 4291192159 4291781216 4291322210 4292044639 4291322204 4291322203 4291583846 4291519586 4291979365 4291715173 4291257438 4291126371 4291715690 4290928735 4291386970 4291058526 4291122779 4291321438 4289613659 4290335835 4290272094 4289940576 4290990937 4290206044 4290732647 4290993755 4292307041 4292111738 4292180075 4292707453 4292576626 4292510321 4292904322 4292380278 4292970864 4292970113 4292711043 4292970111 4293166699 4292775291 4292970867 4293101165 4292905332 4293101425 4292969581 4292512380 4293101426 4293298547 4292577914 4292576628 4293101425 4292905586 4292642933 4293362298 4292511349 4293363048 4292771708 4292839285 4292839282 4292839541 4292509038 4292183922 4292773493 4292772206 4292246887 4292706675 4291982943 4291852140 4292114796 4293633142 4293838475 4294037672 4293972391 4294170791 4294104751 4294368419 4294170533 4294038182 4293835398 4291065708 4289281885 4289547089 4289417309 4290335581 4290925139 4290140761 4290731873 4290863199 4290798181 4291125087 4291387998 4290535513 4291062134 4291191393 4291521132 4292243305 4291783266 4289349964 4285796669 4284223029 4284288067 4284156235 4284224313 4283963979 4285409102 4284356931 4285668931 4284817484 4285469503 4285473357 4285077565 4285341259 4285078853 4285538893 4284945218 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292969338 4293167475 4293167221 4293167475 4292972159 4292972664 4293364344 4293298807 4293169285 4293103212 4293300357 4293694070 4293171573 4293628530 4293693305 4292844147 4293759599 4292843368 4293693297 4293100396 4293166443 4292969598 4292839794 4293363314 4293299054 4293233262 4293496688 4293165677 4292900704 4292504408 4291453529 4290332757 4289151821 4288099918 4289279050 4289085520 4289478735 4289806417 4289872724 4289610833 4289940302 4289871955 4289415252 4289546324 4289546074 4289480788 4289741904 4289480787 4289676375 4290007388 4289349466 4290399315 4290269275 4290859604 4290728283 4290072407 4291256922 4290531155 4291125858 4291057750 4291058527 4291124568 4291191649 4290994015 4291321693 4291060319 4291388521 4291714395 4291716449 4292109144 4291849323 4291454817 4291911261 4292108893 4291518298 4291781990 4290797151 4291124831 4292109147 4291914084 4291386468 4291386973 4292371564 4291977561 4291912799 4291321953 4291322726 4291979620 4291191392 4291914855 4291652474 4291848551 4291584867 4292175719 4291649893 4292043104 4291453539 4292109927 4292175712 4291386981 4291322460 4292044132 4291716448 4291583835 4291321690 4292042856 4291190356 4291320160 4290929767 4292107359 4291191658 4291717203 4291387742 4291452757 4291059291 4291059288 4291125603 4291059288 4291059032 4291191649 4291125856 4291453276 4291388520 4291389029 4292045417 4291322468 4292110696 4291256938 4290799729 4292045671 4291061869 4291388261 4291584361 4291191143 4291585888 4291782250 4291913309 4291847780 4291126110 4291978340 4291519841 4291124834 4291781209 4291583840 4291124828 4292175208 4291323240 4291976796 4291519580 4291518048 4291781208 4291388514 4291847275 4291190619 4291321177 4291582564 4291060320 4291122520 4290601834 4290795867 4290205789 4290859352 4290989398 4289678936 4290267999 4291059055 4291190641 4291126638 4292111993 4292179563 4291590256 4292116337 4292577657 4292707697 4292906367 4292446072 4292773746 4293363824 4292775031 4292577657 4292837741 4292970868 4292905333 4292970868 4292905589 4292510836 4293232493 4292708212 4292905339 4293166957 4292576885 4293101684 4293035390 4293231978 4292708468 4292772460 4292970629 4292773221 4292642165 4292642164 4292839541 4292904047 4292182380 4292576374 4292576630 4292246631 4292248431 4292312939 4292377193 4292311128 4292050024 4293834115 4293904267 4294038695 4293972901 4294170543 4293908145 4294172082 4293973158 4294233491 4292909944 4289681749 4289347657 4289611353 4290007644 4289682010 4291450973 4290664541 4290863456 4290732133 4290667099 4290798698 4291126121 4291980132 4291127145 4292505700 4291125087 4288362575 4285798976 4283697981 4284157502 4284157245 4284356932 4284292164 4284619072 4284619597 4285013056 4285013830 4285536322 4285078076 4285144390 4284553277 4285142588 4285277776 4284618812 4284682813 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292972930 4292971122 4292972142 4292970094 4292971385 4293298802 4293364345 4292971886 4293103217 4293300350 4293302642 4293236351 4293430391 4293629055 4293170288 4293496175 4293235053 4293694064 4293233007 4293299324 4293167470 4292970092 4293169023 4292971379 4293298804 4293299067 4293299567 4293033580 4292443749 4292374379 4291320654 4290334288 4288885323 4288753992 4288690767 4288492877 4289612108 4289151828 4289874263 4290135882 4290529876 4289416797 4289742155 4289480782 4290071386 4289676368 4289742167 4289480793 4289480787 4290201431 4289610825 4290399573 4290267737 4290204245 4290729566 4290730327 4290533728 4291123541 4291125602 4291124062 4291124062 4290468696 4291255389 4291192422 4291125856 4291519076 4291453276 4291782756 4290796374 4291453284 4291520353 4291780709 4291584607 4290994785 4291648599 4291322466 4291585890 4291979877 4291650404 4291454561 4292046180 4291978081 4291716964 4291848032 4291124828 4291519585 4291781738 4291453793 4291913566 4292175462 4291584615 4292043621 4291584874 4291847006 4291454043 4292043873 4292045413 4291386717 4291977825 4292043361 4291452767 4292043357 4291518042 4291322461 4291847526 4291190877 4291843928 4291388517 4291255386 4291255893 4291320674 4291256415 4291715169 4291516509 4290992470 4291582046 4291058511 4291124064 4291125601 4291059809 4291125856 4291256414 4291387739 4292043876 4291125350 4291257452 4290929255 4291455338 4291848301 4291585374 4291388774 4292176484 4291387744 4291060062 4292044645 4291322720 4291715941 4292176231 4291913572 4291452516 4291715428 4292044901 4291322210 4291388002 4291453538 4291124833 4291583583 4291715424 4291913831 4291715672 4291452518 4291519585 4291781220 4291256162 4291321955 4290994527 4291124059 4291059059 4290664537 4291125876 4290208104 4290333281 4289678680 4290791268 4290202720 4290599514 4291126113 4290798957 4292308581 4292573564 4292050046 4292706412 4292378237 4292510835 4292707442 4292511609 4292904816 4292774278 4292381564 4292972413 4292773490 4292775290 4292969581 4292708213 4293297258 4292971127 4292315002 4292969844 4293101422 4292904560 4292968556 4292772719 4292904558 4293233271 4292708211 4293364597 4292706668 4292971388 4292969844 4292838255 4292838255 4292838512 4292575089 4292508773 4292772464 4292640882 4292247146 4292311657 4291983199 4292375912 4291785565 4293629310 4293640312 4294036642 4293973159 4294368932 4294170286 4293973424 4294172082 4294038697 4294297981 4291724639 4289085015 4288824911 4289483101 4290530906 4290138195 4290207330 4290795869 4290141023 4290731359 4290667113 4290535528 4291126632 4291849581 4291126626 4288429646 4286061119 4283500871 4284685385 4283700303 4284356676 4284091196 4284423494 4284885837 4285148756 4285540182 4285474122 4285278545 4284948300 4284751177 4285210440 4285076800 4284224074 4284748348 4284751944 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293561725 4293102974 4293364339 4293101684 4293101683 4293497209 4292970871 4293168772 4293300597 4293301122 4293300867 4293235566 4293235318 4293233012 4293430639 4293431152 4293038957 4293233264 4293233520 4293494897 4292970100 4293365108 4293298305 4293101683 4293496430 4293299060 4293100653 4293231470 4292900173 4292570207 4290927955 4290591561 4289152334 4288099148 4288688971 4289414227 4288888143 4289676372 4289676374 4289941853 4290135888 4289676631 4290003534 4290201687 4289610832 4290071117 4289415252 4290201686 4289873233 4289676624 4289415004 4290070347 4290858062 4290137174 4290730584 4291188052 4291123541 4291125859 4291124567 4291060066 4291649115 4291059809 4291191648 4291059552 4291125079 4290993496 4290927704 4291846752 4291846752 4291060318 4291453026 4291192159 4291649376 4291256157 4291190877 4291583845 4291518046 4291322209 4291845735 4291452509 4292043624 4292110944 4291977575 4292043105 4291715423 4292176487 4291454048 4291715428 4291649636 4291650659 4291716969 4291584099 4292046179 4291847012 4291845736 4291714663 4292175712 4291387754 4291845990 4291977831 4291845992 4291845986 4291584357 4291976796 4291125859 4290862941 4291125343 4292108884 4291584092 4291321431 4290991438 4291056973 4291060324 4291058511 4291058785 4291191384 4291058786 4291124048 4291125083 4291123029 4291387999 4291515995 4291717219 4291060836 4291716961 4291651167 4291062127 4291912295 4291389802 4291125868 4291651423 4291322977 4291584362 4291847268 4291388512 4291256679 4290994525 4291913316 4291322726 4291716194 4291781220 4291124827 4291781732 4291781732 4291387745 4291650914 4291585116 4291519837 4291518041 4291256931 4292109409 4291716197 4291190625 4291321954 4291321954 4291582563 4291124574 4290072409 4290730846 4290664290 4290860120 4290204762 4290926683 4290204260 4290859350 4291189346 4291125105 4292372066 4291718009 4292243561 4291786596 4292510079 4292116335 4292576371 4292709242 4292577144 4292513149 4292838528 4292839280 4292970113 4293168248 4292576371 4292774005 4293297518 4292708469 4292969844 4292969838 4292837999 4292774005 4292838255 4292575600 4292838512 4292772718 4293100925 4292971123 4292708213 4292970094 4292772462 4292577141 4292838255 4292445559 4292772207 4292117358 4292640096 4292183152 4292246889 4292246618 4292309344 4292377450 4292310374 4292310119 4292378458 4293833091 4294102672 4294037413 4293972901 4294170543 4294171568 4294369714 4293972903 4294167695 4293505923 4290078050 4289544785 4289612891 4289351772 4291056218 4290335579 4290925914 4290206310 4290797151 4290600547 4291455336 4291390058 4291126626 4289347656 4285733959 4283897156 4284222780 4283962439 4284550217 4284683843 4284159300 4284947006 4284750408 4285340998 4284947264 4284750143 4284946755 4285471295 4284814391 4285272379 4284685118 4284746814 4284551493 4284748605 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292970092 4292971385 4293364345 4293299065 4293101683 4293364338 4292840567 4292974201 4293693828 4292909169 4293301893 4293430381 4293496439 4293232492 4293232493 4293299312 4293298030 4293296747 4293232237 4293496437 4293101940 4293100395 4293364857 4293101684 4293496180 4293298805 4293102192 4292968302 4292441423 4292373862 4291189848 4289874511 4288952398 4288754764 4288754507 4288561999 4289216594 4289414743 4289546317 4290201430 4289611089 4289349460 4290596435 4289940057 4289414995 4290007133 4290135632 4290005844 4289676625 4289676625 4290007376 4290004562 4290857805 4290860124 4290072663 4290663772 4291124575 4291124825 4291124825 4291057750 4291057493 4291191649 4291125599 4291125857 4291912289 4291649370 4291321950 4291190622 4291583839 4291584363 4291783522 4291190364 4291584608 4291781216 4291976796 4291650916 4292108647 4291454048 4292436840 4291651691 4291649885 4291386981 4291911520 4291519340 4291255895 4292175719 4291845728 4291584355 4292176486 4291649635 4291649891 4291977318 4292175463 4291585117 4291584349 4292175720 4291782244 4292109152 4291191137 4292241505 4291452767 4291452511 4292374119 4291585125 4291911261 4292109149 4291911517 4291518305 4291256413 4291321692 4291387230 4291058004 4291055946 4291123541 4291122257 4291124053 4291121232 4290730577 4291188044 4290535268 4291123285 4291059289 4291125857 4291387235 4291125599 4291454050 4292110690 4290863978 4291257954 4292045417 4291649899 4291190368 4291191399 4291585120 4291191142 4291257708 4291649124 4291715938 4291389803 4291783023 4291518051 4291583588 4291323757 4291520352 4291649892 4291125607 4291387746 4291518304 4291715680 4291780959 4291848037 4291519585 4291714146 4290928479 4291059551 4291060064 4291122522 4291191905 4291254107 4290729049 4290206569 4290336358 4290269016 4290334808 4289613412 4290665307 4291190899 4291715936 4291783532 4291852139 4292244852 4292115310 4292116849 4292444031 4292574828 4292183664 4292577145 4292707954 4292446073 4292643191 4292775289 4292968299 4292970095 4292904559 4292772463 4292839540 4292839284 4292445804 4292969842 4292772719 4292970355 4292772719 4292772976 4292772719 4292772719 4293100395 4292903807 4292970351 4292968556 4292838770 4292508765 4292575346 4292902255 4292181866 4292245350 4292640113 4292704607 4291917928 4291983456 4292375131 4291916638 4292178021 4292973164 4293837964 4294038163 4293973161 4294170531 4294171827 4294104226 4294368675 4293973431 4293968775 4292382317 4289087317 4289676625 4289548893 4290006105 4289353055 4289810267 4290336861 4290403678 4290667872 4291324784 4291715678 4289478728 4286391108 4284289859 4284091709 4284419657 4284159037 4284290615 4284619588 4284947782 4285014603 4285343818 4285278032 4284686152 4285012291 4285078851 4284424268 4284488516 4284685118 4284485446 4285142066 4284553286 4284551492 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293496441 4292969836 4292972144 4293101683 4293364858 4292971127 4293167998 4293302390 4293566070 4293432704 4293496684 4293298030 4292706911 4293362540 4293297003 4293166961 4293297003 4293297003 4293299311 4293299566 4293298810 4293101678 4292774004 4293166956 4293038200 4293299566 4293233777 4293558632 4292836980 4292110418 4291385685 4289676881 4289217613 4288097352 4288689739 4289413971 4289085516 4290069589 4289546580 4289611094 4290136145 4290529875 4289481049 4290005330 4290135889 4290005587 4290071124 4289414990 4289546324 4289676631 4290070359 4290399315 4290269532 4290136407 4291319379 4290599775 4291122781 4291058768 4291058528 4291582043 4290994530 4291519068 4291520101 4291320916 4291060320 4291716452 4291190372 4291781969 4291387997 4291322977 4291649119 4291453795 4291190621 4291322204 4291519842 4291584100 4292044134 4291650664 4291652207 4291451995 4291848037 4291913822 4291125091 4291583066 4291716453 4291782761 4291779942 4292175718 4292109670 4291848546 4291649635 4292176487 4291518562 4292173675 4291780199 4291978075 4291389800 4291980131 4291911009 4291585381 4291911510 4291452768 4292370527 4292108647 4291453523 4291976289 4291583068 4291255383 4291057755 4291192951 4290996577 4291334559 4291262345 4290941591 4291065987 4290673290 4290799481 4291128679 4289943142 4290663760 4290598484 4291123798 4291124568 4291190871 4291060066 4291058269 4290994790 4291191390 4290994015 4291321698 4290862164 4292045157 4291780964 4291520353 4291847268 4291191142 4291322208 4292110188 4291388772 4291323236 4291979107 4291650659 4292109413 4292109415 4291125600 4292045412 4291717730 4291911255 4291715677 4291125602 4291715428 4291781989 4291060319 4291519842 4291388767 4290994528 4291122778 4290598759 4290138457 4290206567 4290338142 4290206302 4290333014 4290267734 4290860645 4291252566 4291058522 4291190898 4292374376 4292180591 4292179309 4292115567 4292705133 4292247140 4292444288 4292642162 4292116851 4292771950 4292708984 4292707442 4292642163 4292839284 4292773749 4292969842 4292838255 4292642164 4292643707 4292706157 4292839797 4292772719 4293100396 4292904816 4293100397 4293100653 4292772976 4292970096 4292970352 4292968814 4292641651 4292443237 4292968817 4292246889 4291918944 4292768360 4292247658 4292244324 4292246121 4292770399 4292311914 4292245604 4292702814 4292246121 4292377960 4293436788 4294168722 4293971105 4294171047 4294104739 4294302895 4294106034 4294170790 4294102930 4293768569 4290470491 4288627284 4289676118 4289483100 4290007131 4290929249 4290269017 4290208110 4290995044 4290797924 4288954193 4285865028 4284092233 4283898439 4284158781 4284159037 4284290372 4284685381 4284554052 4285077824 4284687953 4285275206 4285408330 4285537856 4284751689 4284816453 4284816713 4285341511 4284746557 4284551494 4284945977 4284750397 4284550981 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293300354 4292971384 4293168767 4293167219 4292970092 4292972671 4293366130 4293235326 4293628280 4293430125 4293101936 4292969326 4293427051 4293165677 4293034097 4292639050 4293427054 4293297002 4293299068 4292971883 4293301111 4293496436 4293167219 4293103232 4293495922 4293233268 4293692781 4293100142 4292769359 4292769905 4291125337 4289874010 4289412687 4288034382 4289345099 4288494672 4289217101 4289609039 4289479509 4290201686 4290071379 4290070358 4290005336 4290006875 4290005587 4289808214 4289415258 4290201674 4289611096 4290071380 4289939277 4290267477 4290270039 4290202969 4290731361 4290598237 4291058262 4291845211 4290993753 4291322207 4291386708 4291256421 4291189587 4291256416 4291912289 4291059543 4291387998 4291913825 4291518053 4292044901 4290928990 4291649381 4291518303 4291913830 4291649636 4292374113 4291386980 4291845477 4291453032 4292044909 4292371561 4291584356 4291518046 4291715941 4291452772 4292180835 4292176231 4291322463 4292439141 4291586159 4291650659 4291912545 4292044136 4291780187 4291585382 4291978332 4291977824 4292440941 4290994013 4292304232 4291517538 4291387227 4291584887 4290862174 4291921305 4290933359 4290871170 4291198348 4290805134 4291266440 4291407532 4291925623 4292061341 4292713365 4291539629 4291532942 4292130727 4291865249 4291865776 4291472563 4290543498 4290476659 4290007130 4291122263 4291120974 4291122767 4291058526 4291321438 4291125343 4291322728 4291780709 4291190626 4291649374 4291847526 4291518040 4291585890 4291781475 4291519341 4291388775 4291848563 4291518310 4291848040 4291125350 4291190624 4291649124 4291322209 4291322210 4291911516 4291518303 4291389544 4291583582 4291583839 4291649375 4291256162 4290994271 4291646816 4290468446 4291254106 4290665311 4290861916 4290139752 4291382613 4290203737 4290530903 4290268759 4290141289 4291123803 4291257707 4291585644 4292244075 4292113776 4292509053 4292114799 4292181106 4292310881 4292378750 4292641403 4292509292 4292578184 4292511608 4292707699 4292643450 4292969581 4292774005 4292640879 4292838511 4292706413 4292444543 4292838254 4292772720 4292904816 4292968557 4292641905 4293035117 4292968814 4292772978 4292837730 4292575079 4292902237 4292574819 4292181353 4292247146 4292180852 4291919201 4292705136 4292311138 4292311657 4291919207 4291785055 4292311914 4292311898 4291917928 4292571238 4293234550 4293507472 4294102946 4293972388 4294170533 4294368430 4294171825 4294170275 4293972648 4294102155 4292844420 4289808215 4289552226 4289613403 4289287006 4290926941 4290208093 4290406246 4291190364 4288494159 4285995840 4283897142 4283960392 4284421699 4284555338 4284288580 4284488010 4284619587 4284488002 4284621903 4285538120 4285015116 4285343567 4285079629 4285341254 4285014092 4285077820 4284552509 4284160070 4284814141 4284487237 4284289612 4284945976 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293496189 4293101425 4293299064 4293364857 4293101689 4293560697 4292907649 4293695350 4293173110 4293430389 4293296746 4293427307 4292640096 4293100133 4292769869 4292838006 4292705362 4293232240 4293103986 4293101422 4293298804 4293101428 4293167219 4292971128 4293496953 4293430905 4293428335 4293100141 4292835422 4292438629 4291650646 4290399060 4288888400 4288755789 4288034382 4289216592 4289151565 4289413715 4289740875 4289676887 4289545302 4290004818 4290005592 4290007131 4289349459 4290661204 4289479760 4290530133 4289740878 4289611089 4289808982 4291315783 4290728540 4290731617 4290596176 4291119697 4291385435 4290992214 4291059289 4291385948 4290993753 4291256414 4292045154 4291189845 4291322205 4291649378 4291781210 4291649887 4291846757 4290928734 4292175203 4291256930 4292108892 4291845466 4291584356 4292173412 4291125344 4292374887 4291584862 4291584349 4291584355 4291845735 4291848286 4291845735 4291716451 4291650148 4291386717 4291716203 4291125606 4292242022 4291584356 4292371550 4291518821 4292176730 4291845724 4291845978 4291715170 4291123289 4292375672 4291456628 4291197822 4291261575 4291331721 4290873229 4291134848 4290872203 4290674579 4291528583 4291206309 4292121991 4292055951 4292061877 4291208097 4291405471 4291599507 4292458924 4292124569 4292263089 4292257170 4292457896 4292919467 4292453542 4291409592 4291142043 4290541705 4290467672 4291189081 4290073939 4290664541 4291189596 4290469728 4291257184 4290994016 4290994015 4291519075 4291454049 4291454566 4291192430 4291127677 4291256934 4291258224 4290995815 4292045410 4291191142 4291324007 4291846495 4291519841 4291911528 4291911527 4291716961 4291322465 4291388002 4291716453 4291649637 4290994528 4291516505 4291125857 4290533725 4291252824 4290073692 4290793559 4290730076 4290335590 4290333269 4290334808 4290204268 4291125854 4291190884 4292176490 4292244075 4292179311 4292246115 4292179566 4291854185 4292117112 4292770408 4291854465 4292640622 4292379753 4292510580 4292905076 4292641907 4292643706 4292969841 4292445302 4292968556 4292642678 4292968811 4292772976 4292772976 4293100396 4292839281 4293493610 4293035119 4292509542 4293164907 4292378483 4293034863 4292444277 4292574559 4292641397 4292638813 4292313195 4291982686 4292707446 4291981660 4292310375 4292705120 4292245604 4292310117 4292312171 4292375124 4292246377 4292114279 4293567346 4293838215 4294037410 4293973158 4293973938 4293973424 4294171826 4294170276 4294104492 4293835122 4291131998 4289152858 4289481048 4290533726 4290139486 4290798943 4291189335 4289022035 4285995072 4283696967 4284355141 4284159293 4284091453 4284291141 4284682039 4284619844 4284292168 4285736780 4284290624 4285475661 4285278031 4284687182 4285146188 4285211470 4284488514 4284549182 4284419647 4284812607 4284685375 4285142591 4284945975 4284684608 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293298807 4292971385 4293364851 4292969843 4293166962 4293235067 4293238387 4293631360 4293628531 4293233519 4293363053 4292638814 4293229399 4292375904 4292834658 4292835188 4292771424 4292838770 4293301104 4293759612 4293103471 4292971891 4293364346 4293298808 4293037934 4293430650 4293232499 4293624425 4292311650 4293030499 4291779931 4289743182 4289412679 4288100687 4288754250 4289085520 4289347152 4289479244 4289675347 4289609297 4290530899 4289940057 4289545302 4290201429 4289742161 4289349197 4290596443 4289808724 4290466126 4290070354 4290267464 4291251798 4290596947 4291187025 4291122012 4291058775 4291384922 4291322468 4291256670 4291322207 4290993753 4291713625 4291584098 4291124308 4292112232 4291124051 4291322462 4291781223 4291190620 4291651684 4291649881 4291781215 4291452260 4291586673 4292111715 4291518563 4292175975 4291911526 4291912801 4292306020 4291913581 4291845728 4291650661 4291911521 4291650148 4291649892 4292176488 4292110424 4292309596 4291911777 4291780455 4291978593 4291845985 4291845979 4291518049 4291582835 4291718521 4290741140 4291133832 4291397263 4291527296 4291398796 4291200649 4291070356 4291395720 4291330444 4291203999 4292129441 4291924098 4291665047 4291467927 4291600015 4292520856 4292130476 4292126887 4291142049 4292060312 4291932319 4291995805 4291931039 4292387991 4291801760 4292917940 4292393895 4292983716 4291474110 4290944667 4289817725 4290664800 4290204503 4290726741 4291125080 4291125602 4291125344 4291059551 4290994015 4291322973 4291978855 4290931057 4291716205 4291584359 4291584360 4291518569 4291191398 4292174951 4291124827 4292042600 4291322464 4291125090 4291715672 4292042601 4291125089 4292042850 4291255130 4290992989 4291583076 4291124060 4290667366 4290532699 4291251541 4290730857 4290859095 4289809495 4289876326 4290334553 4290073690 4291909469 4291717750 4292111455 4291719024 4291787624 4292770925 4292115056 4292180341 4292770922 4291853187 4292312419 4292640878 4292444030 4292576371 4292773491 4292642164 4292707956 4292838254 4292248428 4293231725 4292577143 4293166188 4292772976 4292968813 4292511607 4293164651 4292707697 4293100912 4292836445 4292838250 4292706658 4292507486 4292509537 4292574065 4292245863 4292246377 4292310123 4292312169 4292702300 4291983719 4292310629 4292244839 4292703581 4292310631 4292374371 4291982431 4292310374 4292180071 4292969071 4293769861 4293905055 4294037666 4293972900 4294172082 4294302381 4294502322 4293906852 4294169769 4293501555 4290862680 4289219163 4290272353 4290798942 4290994266 4288497489 4285993533 4283896118 4283960389 4284157500 4284748357 4284748358 4284091453 4284225606 4284946492 4284424268 4284947264 4285209926 4285472587 4285274951 4285211469 4285080138 4284685381 4284226628 4284484927 4284419385 4284944953 4285073469 4284681529 4284748103 4284553278 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293299065 4293101683 4293297521 4293300601 4292905845 4293628792 4293629049 4293170537 4293430390 4293035374 4293425769 4292835418 4292440416 4292571229 4292899169 4292440911 4292770143 4293428075 4293298812 4292908390 4292973182 4292970874 4292906345 4293693560 4293628289 4293365100 4293495149 4292772209 4293229141 4292373337 4291649366 4290330194 4289150283 4288295755 4288166222 4289149517 4289217357 4288822608 4290267730 4290006100 4290070358 4289940057 4290005069 4290005850 4289480531 4290072664 4290070346 4290069841 4290070359 4289874522 4290333780 4290727508 4290726483 4290530901 4291122771 4291123294 4290991949 4291452004 4291844191 4291255893 4291320669 4291189581 4291648856 4291518561 4292043100 4291913058 4291714904 4291517784 4291190101 4291387996 4291715430 4291453794 4291782238 4292241249 4291386718 4292175975 4292107613 4291782500 4292110183 4291912801 4292306019 4291781733 4291914341 4291387999 4292108648 4291649886 4292043105 4291584095 4291978082 4291846754 4291845984 4291845990 4291911524 4291779694 4291654007 4291329405 4290608780 4291724159 4291068801 4292251274 4291003008 4290736255 4291134593 4291199090 4290805899 4291399569 4292189325 4291403931 4291534227 4291664023 4291861660 4291406761 4292389537 4292191908 4292454797 4292061851 4291801001 4292058005 4291533464 4291074965 4291998369 4292323231 4291472776 4292392874 4292258195 4292984235 4292787886 4292393639 4291931816 4291005584 4289749615 4290727252 4290596945 4291124318 4291125600 4291124578 4291060582 4290994531 4291060841 4290928993 4291388000 4291716195 4292307814 4291190112 4291388769 4291847525 4291191136 4291781989 4291583838 4291649638 4290797406 4291913574 4291385954 4290991707 4291124062 4291059800 4291122779 4290598759 4291255901 4290729564 4290204506 4290205800 4290465122 4289874005 4290923861 4290793560 4290404713 4291586148 4292308843 4291587695 4292835178 4291855235 4292113002 4291984255 4292114028 4292770923 4292050550 4292442747 4292116592 4292642163 4291986295 4292970611 4292445043 4293034877 4292642677 4292641136 4292705891 4292641393 4292838512 4292378986 4293034608 4292640864 4292444019 4292968283 4292641909 4292444276 4292507486 4292510582 4292966496 4292574579 4292179541 4292638045 4292243555 4292310374 4291918176 4292310629 4292703085 4292245093 4292310375 4291983456 4291985251 4292374373 4292245094 4292377449 4291785309 4293432685 4293706628 4294102434 4293973159 4294170531 4294104494 4294303919 4294369713 4294170276 4294166154 4292316791 4290007644 4290994528 4291060578 4289350491 4285929534 4283896646 4284155723 4284418875 4283962695 4284092224 4284225079 4284620101 4284287293 4285208636 4285670219 4284949323 4284947011 4285274687 4285340223 4284488258 4284357961 4284817223 4284419900 4284422461 4284554566 4284684863 4285274687 4284683322 4284551737 4284747071 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293299054 4293101685 4293496172 4293496441 4293235573 4293563768 4293563001 4293629045 4293233520 4293428334 4292377188 4292506193 4292831051 4292043100 4292637278 4292505694 4293097569 4292970610 4293430644 4293627509 4293496429 4293628018 4293496186 4293232761 4293170536 4293430401 4293429356 4293166959 4292770142 4292637280 4291189327 4290334031 4289018190 4287574347 4288821838 4289084238 4289215562 4289347408 4289675347 4289676110 4289872468 4290006100 4289806926 4290070100 4289414997 4290071123 4289415252 4290135377 4290464852 4290069322 4289939032 4290924365 4290072668 4291254877 4291059295 4291057757 4291516243 4291845476 4291384914 4291255133 4291256677 4291649884 4291125348 4291977314 4291452767 4291650144 4291715936 4291911009 4291584096 4291518310 4292042843 4292045925 4292374632 4291059039 4291715678 4291780199 4291845992 4291584349 4292107882 4291780193 4291977826 4291780444 4291585376 4292105562 4291650917 4291650654 4291650658 4291650659 4292172896 4291451995 4291847265 4291257449 4291454322 4290799484 4291001984 4290872719 4290998649 4290674825 4291594132 4291266953 4290936209 4290148976 4290736007 4291594890 4291134595 4291856262 4291267457 4292516502 4291136143 4291927189 4292189065 4291599259 4292587410 4291666332 4291868341 4291405992 4291865494 4291404198 4291141790 4292322447 4291469723 4292327853 4291535762 4292260010 4292065437 4292261294 4292587931 4292854968 4292655009 4292721829 4292524472 4290280072 4290529876 4291187800 4291122779 4291124575 4291123284 4291059808 4291191387 4291322483 4291649121 4291847522 4291583330 4291455853 4291321440 4291256935 4290863460 4291847524 4291190882 4291451233 4291256675 4291450457 4291322211 4291386202 4291060321 4291122779 4291189084 4290727767 4290140254 4290204764 4290204508 4290925144 4289875288 4289350489 4290336364 4290137175 4291125599 4291782249 4291848807 4292834409 4292180838 4292639596 4292641650 4292703593 4292116081 4292114803 4292639595 4292641135 4292116592 4292378493 4292641904 4292512121 4292903788 4292642676 4292904047 4292706672 4292509553 4292509552 4293034605 4292706930 4292509025 4292509025 4292575347 4292444534 4292900703 4292902752 4292901220 4292507998 4292507505 4292571993 4292576375 4292639339 4292244837 4292245350 4292702310 4292637805 4292179029 4292310375 4291983713 4292310117 4292704369 4292244308 4292703840 4291983713 4291980384 4292244837 4293505146 4293970315 4294038440 4293972643 4294172079 4294105785 4294107069 4294369714 4293972133 4294165636 4291392356 4290864479 4289676372 4286259013 4283897155 4284026182 4284027451 4283963725 4284224841 4284555081 4284553795 4285145164 4285013314 4285211727 4284490316 4285211470 4284750398 4284947011 4285014604 4284552260 4284092989 4284419899 4284818767 4284489804 4285339965 4284682815 4284750399 4284748863 4284550975 4284685120 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293429356 4293297776 4293234816 4292971893 4293629816 4293565043 4293564019 4293430639 4293297006 4293033823 4292505920 4292505182 4292040789 4292108388 4291912537 4292573538 4293033307 4293560942 4293431157 4293430900 4292908398 4293495680 4293233778 4293236089 4293628281 4293627768 4293365359 4293560179 4292704611 4292962905 4291388246 4290331471 4289018702 4288294729 4288229193 4289214283 4289018188 4289281616 4290004297 4289413203 4289152085 4290070094 4289872726 4289543761 4290661448 4289938516 4289480794 4289808727 4289740884 4289876055 4290464339 4289807697 4290858584 4290662490 4291320925 4291055949 4291386976 4291253834 4291714139 4291256151 4291255900 4291843928 4291584353 4291584095 4291584103 4291977046 4291518305 4291911766 4291584098 4291518303 4291979366 4291124828 4291845468 4291845980 4292175977 4292043867 4291388513 4292043873 4291979111 4291782751 4291845986 4291976034 4291911259 4291453272 4291714907 4291912541 4291519094 4291520107 4291787147 4291919487 4290931583 4290667116 4289883004 4291198582 4291856519 4291068274 4291132546 4291002751 4291066494 4291330429 4291525493 4291393930 4291333004 4291266173 4291328885 4291397268 4291397522 4291527552 4291467932 4291265411 4291859081 4291728263 4290810774 4292714889 4291273119 4292391071 4291928483 4292586896 4291994271 4291538592 4292517770 4292127144 4292326043 4291864218 4291864991 4292327063 4292588971 4292130211 4292787133 4293248172 4292721826 4292919469 4291405480 4289423216 4290726994 4291252567 4290599775 4291124576 4290929530 4291452765 4290799736 4290864240 4290995558 4291387753 4290928734 4291321696 4291913060 4291583845 4291256156 4291388514 4291844703 4291322205 4291060064 4291124318 4291124318 4291123291 4290007644 4290729564 4290731359 4290726229 4290797151 4290858069 4289878122 4290136660 4290270299 4290729564 4291060063 4291584105 4292244589 4292114290 4292637033 4292574575 4292179813 4292247657 4292309858 4292115057 4292443261 4292575597 4292444286 4292640617 4292445066 4292378233 4292707715 4292510835 4292706672 4292707688 4292509553 4292575344 4292509809 4292575604 4292573020 4292575606 4292574050 4292574031 4292575863 4292179286 4292509028 4292573538 4292573790 4292180845 4292637012 4292244838 4292246889 4292307302 4291851619 4292637806 4292635980 4292639347 4292243283 4292640628 4292638815 4292245096 4292245079 4292376168 4292309610 4292241254 4292905571 4293703558 4294102413 4294038717 4293973947 4294106030 4294303662 4294303664 4294369971 4294169509 4293239417 4289742415 4286719305 4283827266 4284026438 4283634505 4284026176 4284615747 4284158524 4284226627 4285407302 4284490574 4285603139 4284881218 4285408072 4284946754 4285144390 4285144390 4284880457 4284815419 4284224580 4284818768 4284687181 4284947273 4284682557 4284618303 4284157751 4284616519 4284489287 4285076020 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293299065 4293233272 4293627511 4293562993 4293565828 4293170542 4293627000 4293232500 4292967515 4293162594 4292505165 4291778388 4291583061 4291123269 4292437864 4292509296 4292707700 4293167216 4293038699 4293628021 4293235051 4293235824 4293430132 4293627507 4293561977 4293169782 4293429358 4293033305 4293100403 4292571469 4291581025 4290004811 4289018702 4288293702 4287771465 4288754250 4288760416 4289414478 4289871955 4289217615 4289412939 4289938262 4289676874 4289940057 4289348176 4290267474 4289872718 4289937235 4290331208 4290466653 4289742936 4290989138 4290792792 4290073429 4290662490 4291124568 4290467671 4291123799 4290993249 4291320147 4291321436 4291255899 4291190363 4291321950 4291256669 4290863202 4291256413 4291451494 4290861646 4291847010 4291322466 4291583584 4291913823 4291649894 4291387230 4291845730 4292043880 4292043873 4291387231 4291845980 4291387998 4292170085 4290996338 4291580525 4291260288 4291790745 4291594373 4291987343 4290214529 4291193721 4289485419 4290796895 4290670980 4290144881 4290996857 4290934143 4291132275 4290806138 4291131523 4291196275 4291262335 4291661195 4292051326 4291463563 4291131507 4291397247 4291594119 4291401353 4291397269 4291992205 4291532707 4292188808 4291924634 4291466648 4292392089 4291925647 4291990678 4291472023 4292191889 4291336598 4291933853 4292454288 4291735463 4292394669 4292193693 4292130229 4292787622 4292852126 4292130206 4292328113 4292723125 4292722091 4292721578 4292723379 4290086802 4290071136 4290201683 4291256418 4290601314 4291124060 4291124576 4291060578 4291649398 4290994268 4291582561 4291125620 4290994013 4291387490 4290928991 4291910245 4291451746 4290994528 4291122522 4290532443 4291123291 4291123548 4291187545 4290531417 4291253081 4290728537 4290270054 4290004307 4290070099 4289940579 4290336604 4290726229 4291059037 4291124576 4292439909 4292112492 4292180837 4292574062 4292641393 4292049777 4292705648 4292311397 4292180579 4292834682 4292049516 4292446084 4291983226 4292116848 4292574829 4292510837 4292641390 4292838017 4292901983 4292509810 4292574817 4292180824 4292575863 4292574816 4292574564 4292571997 4292576118 4292180327 4292967536 4292115544 4292573041 4292572236 4292573553 4292179302 4292638044 4292245351 4292703069 4292245351 4291916896 4292637533 4292243815 4292243299 4292179542 4292637550 4292245096 4291983712 4292178018 4291917151 4292439644 4293829739 4293906082 4294037921 4293972899 4294368430 4294303919 4294303406 4294303921 4293973160 4294233754 4289676882 4283500354 4283635271 4284484419 4284223049 4284422210 4284291399 4284292420 4284616004 4284552763 4285604940 4285076796 4284947780 4285014860 4284946754 4285341770 4285276741 4284291144 4284621389 4284226371 4284683321 4284751430 4284682044 4284620101 4284554047 4284814153 4284485939 4284812851 4284814908 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293035890 4293693303 4293171588 4293564023 4293566590 4293563258 4293363820 4293494380 4293493357 4292571231 4291845716 4291053903 4290724941 4291251023 4292044884 4292770672 4293032793 4293365105 4293233524 4293564275 4293429626 4293629049 4293365364 4293365619 4293561972 4293562996 4293561197 4293494638 4293032796 4292964451 4291979339 4290004563 4289083981 4288361804 4287903052 4288493899 4288167244 4288624717 4289151564 4289546072 4289480279 4289350739 4289610581 4289545039 4290003785 4289283667 4289479504 4290267468 4289349967 4290135638 4290071897 4289808729 4290203995 4291316818 4290595928 4291121236 4291450970 4291057502 4291385939 4291319386 4291060065 4290994529 4291975000 4290862937 4291843167 4291583570 4291846239 4291584091 4291256672 4291583057 4291583841 4291781215 4291452511 4291650911 4291911522 4291650405 4291649886 4291651173 4291910233 4292040549 4292039011 4292243811 4293178016 4291985801 4292381830 4291265935 4291132017 4290606465 4290733161 4290603375 4291321687 4290929280 4290208369 4290078331 4290670704 4290803079 4290670194 4290668140 4291259760 4290407021 4291856247 4290999922 4291129713 4291135371 4291461505 4291791764 4291592834 4291855236 4291593603 4291073685 4292842892 4291533466 4291600805 4292255630 4291595930 4291402389 4291993752 4292519065 4291867306 4292585616 4291859092 4292131763 4292784535 4292259988 4292329133 4292260501 4292588191 4292195751 4292655790 4292786330 4292522662 4292723124 4292657075 4293182381 4292985015 4291471767 4289553012 4290202460 4290338157 4290729050 4291124574 4291124317 4291124059 4291125600 4291060064 4291058267 4291125600 4290992732 4291648355 4290992989 4290994784 4291125344 4291125857 4291124574 4290532443 4291122009 4291122266 4291189340 4290139228 4290334553 4290398806 4289876059 4290135893 4289415256 4289807958 4290599260 4291974499 4291651690 4292110180 4292639340 4292574575 4292574061 4292508525 4292639854 4292244322 4292115059 4292703851 4292510320 4292641136 4292639338 4292114541 4292115055 4292576629 4292708212 4292902509 4292707688 4292511095 4292509552 4292966498 4292571998 4292573535 4292573041 4292178526 4292573554 4292572748 4292508270 4292966752 4292574578 4292573038 4292508255 4292573296 4292638043 4292638832 4292244838 4292179558 4292703069 4292244322 4292638316 4292637514 4292179560 4292638834 4292572508 4292637271 4292311915 4292245336 4292767324 4292177764 4292705636 4293703552 4293904797 4294038179 4293973936 4293908924 4294304699 4294435760 4294567339 4294234248 4288357704 4283040560 4283567933 4284091204 4284420675 4284159565 4284292163 4284617796 4284488511 4285407305 4285472586 4285078854 4285406271 4284554053 4285015630 4284879925 4284550980 4284616515 4284619587 4284487744 4285738844 4284226888 4285078850 4284027197 4284621646 4284684873 4284812594 4285736010 4285273144 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293495935 4293169268 4293628784 4293565561 4293564267 4293562223 4293298031 4293034084 4292441696 4292110159 4291120720 4289806922 4289675338 4291124308 4292635994 4292444515 4293624170 4293036143 4293628538 4293562996 4293236592 4293430388 4293432685 4293364603 4293562989 4293364859 4293560168 4293298544 4292706145 4292963933 4291517276 4290070354 4288559183 4287834950 4287311689 4288887375 4288755790 4288626257 4289085264 4288953679 4289478737 4289676117 4289676367 4289217359 4289610576 4289349203 4289742411 4289676889 4289938004 4289545553 4290465102 4289807943 4290333529 4290729560 4290663260 4291122266 4291450969 4291058519 4291056724 4291385178 4291060065 4291125601 4290929250 4291385427 4291650145 4291450715 4291190878 4292042839 4291583333 4291584091 4291583840 4291322467 4291911522 4291911516 4291453029 4292106850 4291453018 4291713382 4291385433 4291134855 4291520363 4291454565 4291059816 4290999406 4291062897 4290602084 4290733935 4290142569 4290800239 4290798690 4290535031 4290208096 4290273911 4290342755 4291129216 4291193965 4290344822 4290669696 4289489014 4291325038 4290936707 4290340477 4290935680 4291593848 4291460473 4291661451 4291332221 4291070860 4291728280 4292124059 4291594892 4291923075 4292124822 4291268231 4291471770 4291861157 4291800737 4292261025 4291664026 4291475360 4291933876 4292390287 4291736998 4292785048 4292123811 4292261793 4292852644 4292062370 4292195742 4292789176 4292787361 4292457646 4292854453 4293380016 4292985510 4292656821 4292721076 4290480774 4289023845 4290333268 4290793817 4290729307 4290599518 4291124318 4291124318 4291124061 4291125600 4291125600 4291058525 4291059800 4291646561 4291060320 4291124062 4291122779 4291124830 4291121247 4290530134 4291187801 4290203481 4289875813 4289875802 4290005079 4290005849 4289608782 4290335580 4291251797 4290927965 4292043366 4292702824 4292572009 4292572779 4292444785 4292968813 4292573806 4292182121 4292705646 4292047726 4292639597 4292116850 4292444542 4292444542 4292639596 4292575341 4292378493 4292509807 4292509296 4292706671 4292774007 4292115816 4292182124 4292640099 4292572507 4292572014 4292965728 4292508515 4292966755 4292116589 4292571745 4292508511 4292968048 4292571483 4292246378 4292180585 4292638043 4292639088 4292179559 4292638302 4292179558 4292637551 4292638046 4292246105 4292246378 4292246122 4292246375 4292701289 4291916899 4291851113 4292114022 4293956721 4293641879 4294037922 4293972656 4294303918 4294239164 4294502069 4294500509 4293100639 4283236402 4283501385 4283831114 4283831104 4284157501 4284354371 4284618052 4284684348 4284816457 4285341511 4284948299 4284750920 4284686152 4285014605 4285272380 4284553285 4284289348 4284223300 4284488259 4285278288 4284946752 4284616004 4284421182 4284223808 4284945977 4285076019 4284750915 4285276235 4285537861 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293169006 4293630590 4293501313 4293565559 4293563270 4293429099 4293166962 4292770894 4292701276 4291646547 4290198852 4288756304 4290132298 4291384920 4292044629 4292507489 4293166960 4293035887 4293629044 4293628782 4293235570 4293235825 4293430644 4293431155 4293563509 4293627506 4293563005 4293493098 4292770399 4292373352 4292042579 4290004039 4288754246 4287902538 4287378253 4288426569 4288164939 4289279050 4289085264 4289414480 4289283151 4289348687 4288822351 4289480531 4289610576 4289742411 4289742425 4289742153 4289481050 4289611094 4290660950 4290399834 4289807698 4290335325 4290397257 4290729304 4290534496 4291122263 4291123294 4291123798 4291124320 4291057228 4291452254 4290990674 4291321956 4291256412 4291321699 4291126113 4291255635 4291256158 4291651171 4291125340 4291911779 4291518297 4291518566 4291648096 4291912280 4291386976 4292371803 4294424446 4291774025 4290664800 4291192168 4290601066 4290667375 4290732648 4290730842 4290273387 4290207340 4290207337 4290865269 4290274666 4290143596 4291325557 4290410880 4291063679 4290145140 4290208362 4290931571 4290606465 4291001472 4290998891 4291129972 4291131763 4291134594 4290872205 4290803066 4291726221 4291790189 4291924871 4291594632 4291004554 4291730074 4291594119 4292389784 4292189571 4291139489 4291865244 4292784798 4292784810 4292261279 4292720033 4292124829 4292129957 4292326808 4292261273 4292589740 4292655005 4292849047 4292587169 4292131254 4292787882 4292524463 4292130483 4292328629 4292920236 4292985253 4292592307 4291207324 4289487986 4289872978 4289810779 4290992221 4290729563 4290729050 4290732902 4290663002 4291126114 4291124574 4291122523 4291059294 4291122523 4291123797 4290599519 4290665054 4290600287 4290662489 4291255389 4290792277 4289812324 4290660178 4289810267 4290071127 4289546338 4290660691 4290071651 4291124317 4291783011 4292111723 4292572009 4292443502 4293229165 4292444272 4292510065 4292573288 4292572780 4292574318 4292640109 4292114800 4292245859 4292115568 4292639852 4292443262 4292443002 4292640878 4292576886 4292706927 4292705132 4292575601 4292637544 4292179301 4292178026 4292639073 4292507230 4292506975 4292507745 4292506974 4292969587 4292506716 4292571500 4292574304 4292180328 4292639327 4292573553 4292570969 4292178020 4292638302 4292639073 4292178019 4292638045 4292247917 4292244324 4292639583 4292638574 4292639594 4292310374 4291983455 4292308328 4292115303 4293697908 4294104230 4294170789 4294500527 4294304180 4294302361 4294424436 4286453823 4282712893 4284027968 4283893571 4284484420 4284355140 4284226892 4284552259 4285012547 4285146702 4285340744 4284881218 4285669189 4285668422 4285208123 4284355646 4284289350 4284093245 4284552516 4285079107 4285273404 4285144901 4283963966 4284484671 4284419385 4284683066 4284683577 4285537862 4285471033 4284550970 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293564280 4293499766 4293763956 4293564268 4293366388 4293232495 4292967771 4292967014 4291912806 4291120709 4288561232 4288030789 4289282639 4291122762 4292636264 4292902496 4293165421 4293496181 4293170807 4293235569 4293038193 4293628788 4293629044 4293167988 4293627501 4292972664 4293429613 4293032031 4293099348 4292964192 4291517516 4290136660 4289213771 4287180874 4288097862 4287770441 4288297550 4288691537 4288759378 4289019215 4289347152 4289085516 4289676367 4289806156 4289610831 4289807960 4289217363 4289414743 4289742165 4289742166 4289547097 4290265939 4290399565 4290004310 4290463825 4290073429 4291251543 4291122773 4291122772 4290532701 4291124055 4291122264 4291056470 4291059040 4291389023 4291256420 4291321949 4291321949 4291256420 4291256413 4291649633 4291712605 4291911773 4291322718 4291583069 4291519068 4291710299 4291320150 4293704087 4291915620 4287575369 4290399073 4290142830 4290796636 4290537583 4290206821 4290864236 4290141029 4290799721 4290208356 4290274146 4290204247 4291191675 4290670445 4290603642 4291393389 4290996073 4290473842 4290147445 4291129214 4290736499 4291127919 4291001989 4290342012 4290804362 4291130742 4291066497 4291595391 4290873239 4291200393 4291596678 4291332490 4291799964 4292584600 4291337128 4291602588 4292127899 4292389530 4292391333 4291735704 4292780698 4291868063 4292721060 4292257176 4292654241 4292328876 4292652442 4292061094 4292197026 4292589731 4292589217 4292524722 4292920502 4292721055 4292525240 4292525239 4292394422 4292262573 4292984997 4292787118 4289556081 4289283671 4289150538 4290530915 4289810019 4290338150 4290204764 4290663251 4291252825 4290010723 4291254107 4290535778 4291188572 4290599774 4290598492 4291185749 4290795869 4289808214 4290925400 4289810532 4290334306 4291055447 4289086549 4290003537 4289218136 4290859608 4290993501 4292305511 4292702567 4292506473 4292902001 4292772204 4292444016 4292968557 4292510066 4292573287 4292576113 4292113261 4291590007 4292769641 4292115313 4292179821 4292113773 4292310368 4292115057 4292049008 4292575344 4292706928 4292576888 4292180310 4292638830 4292636010 4292180566 4292571757 4292900448 4292505966 4292967790 4292508514 4292573793 4292179302 4292572253 4292640371 4292572509 4292179301 4292574304 4292637548 4292179301 4292245094 4292637548 4292572520 4292180326 4292640369 4292179046 4292246118 4292247916 4292244067 4292313196 4292245862 4292179557 4292838002 4294035338 4293971876 4294369192 4294038956 4294557043 4288756307 4283170879 4283371335 4284222790 4283701577 4283832640 4284091454 4284815687 4284618812 4285800519 4285277000 4285144133 4285079365 4285604430 4285473611 4284490572 4284286788 4284223287 4284619845 4285078083 4285145676 4284161092 4284223037 4284486462 4284618822 4284684349 4285340992 4285668680 4285538115 4283566389 4283238710 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293564022 4293565571 4293500035 4293561727 4293363826 4293688935 4293032801 4292504935 4291845208 4289411659 4288163401 4288162630 4289347662 4291121997 4292109419 4292508002 4293230170 4293235828 4293628788 4293562996 4293563257 4293627252 4292842862 4293495667 4293562228 4293430644 4293625706 4293559405 4292702049 4292962905 4291517018 4290660171 4288559439 4287966790 4287375690 4288429135 4288821326 4288757834 4289348179 4289217106 4289740110 4289480534 4289480278 4289217364 4289217364 4289612115 4289217364 4289414736 4289742167 4289742160 4289741910 4289940307 4290464595 4289744732 4290859093 4290728539 4290531419 4291122772 4291121493 4290532957 4291122260 4291124055 4291124576 4291121745 4290994786 4291582042 4290993247 4291450969 4291649894 4291715169 4290796630 4291847015 4291453024 4291584090 4291518561 4291517521 4291716200 4291385944 4293230174 4290794071 4289613659 4290859352 4290731871 4290598748 4291322981 4290141021 4290207078 4290733406 4291127932 4290599791 4290207594 4290340205 4290210671 4290079861 4291257709 4290736244 4289621099 4290209911 4290670201 4290602349 4291000707 4291130738 4290736244 4291259247 4291132275 4291329656 4291134324 4290739842 4291460471 4291989378 4291464331 4292055432 4292119943 4291866027 4292126596 4291928478 4292257943 4292452750 4291799710 4292457117 4292326549 4292325277 4292718751 4291933846 4292785312 4291471521 4292656303 4292851865 4292522407 4292523434 4292523681 4292722091 4292458928 4292722877 4293051822 4292985516 4292196003 4292198590 4292919989 4293051823 4292987832 4291207075 4289351009 4289543503 4290074205 4289939287 4290464599 4290923864 4290138712 4291385171 4290531418 4291254620 4290531161 4291254876 4291121753 4291255133 4290203225 4289811291 4290335589 4289873749 4289875802 4290399827 4290071127 4289217877 4290530391 4290729316 4290990943 4292176486 4292113261 4292573291 4292444527 4292968316 4292839022 4292378481 4292903020 4292444528 4292573805 4292639854 4292311394 4291919746 4292833638 4291592052 4292179566 4292243819 4291589234 4292768616 4292574318 4292903021 4292510570 4292572525 4292509040 4292572763 4292571757 4292508016 4292900192 4292508495 4292508786 4292509538 4292508769 4292573296 4292573280 4292180840 4292570969 4292639087 4292572521 4292179300 4292640370 4292179300 4292179299 4292574577 4292574576 4292507502 4292572250 4292574578 4292571737 4292641653 4292180069 4292641137 4292509809 4292704873 4293697143 4294104747 4294169751 4294752358 4289085272 4282974778 4284026182 4284159047 4283832383 4284026183 4284352581 4284421176 4284750142 4285210184 4284357187 4285012291 4284751689 4285277000 4285538123 4285012803 4284224579 4284224835 4284749885 4284620102 4285079106 4284356169 4284160317 4284290629 4284420926 4284748092 4284490575 4285408330 4285408329 4284158780 4283238454 4283304246 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293565570 4293562992 4293564531 4293562990 4293429870 4293164646 4292899680 4291713623 4290136390 4288556874 4287770183 4288163401 4289545041 4291451992 4292242260 4292506976 4292968302 4293298800 4293628783 4293564013 4293563257 4293364595 4293429869 4293170560 4293561977 4293365876 4293428594 4293099612 4292767827 4292831833 4291648089 4289611859 4288752712 4287375175 4287442759 4288492619 4288101713 4289344330 4288561999 4288758865 4288956758 4289546336 4288891744 4289546839 4289480015 4289546330 4289873488 4289414743 4289612115 4289546323 4289350746 4289871698 4289941596 4290398807 4290203739 4290727508 4291189846 4291125345 4290528849 4291187546 4291124312 4290532444 4291124318 4291124576 4291123285 4290993247 4291058005 4291452005 4291450970 4291190362 4291649640 4291257180 4291975771 4291647581 4291912038 4291912031 4291385942 4291853172 4289874251 4290728026 4290795357 4290727769 4290601057 4291256928 4290599260 4291189096 4290076263 4290994013 4290668394 4290732650 4290797152 4290141548 4290800499 4291260017 4290605941 4290475139 4291127923 4291128953 4290079346 4291132030 4291062382 4290867586 4291452762 4290015862 4291068293 4289946734 4290734983 4291789430 4291983485 4291726992 4292054142 4291728524 4292124301 4291860369 4292193702 4292453776 4291859082 4291475363 4292518287 4291600548 4291799986 4292392341 4291797403 4292126109 4292197553 4292918178 4292588702 4291999414 4292984996 4292653982 4292458161 4292920495 4292919461 4292261284 4292722612 4292328629 4292787625 4292788145 4292459445 4292986047 4292985781 4293315496 4291276469 4289744481 4288953420 4289611338 4288825431 4289546073 4289612121 4290333528 4290794330 4290729820 4291320412 4290071897 4290795356 4290139228 4290334808 4290399329 4290335587 4290400600 4289873493 4289876326 4290203747 4289676629 4290070100 4290204517 4291123033 4291386722 4292768103 4292966254 4292444528 4292837227 4292968317 4293034087 4292902780 4292968571 4292509806 4292575600 4292640111 4292243300 4292113005 4292244075 4292242536 4291719536 4292242793 4292111722 4292114030 4292575857 4292575088 4292510064 4292967538 4292506984 4292965986 4292506956 4292507761 4292507502 4292900715 4292901216 4292902262 4292506716 4292573280 4292573295 4292572778 4292179301 4292638042 4292179302 4292573789 4292966258 4292573293 4292573790 4292506716 4292967010 4292509042 4292508783 4292967539 4292116073 4292573032 4292511351 4293034603 4292443007 4293827701 4294034043 4293958777 4288361288 4283435314 4284157774 4284029766 4284224316 4284356165 4284551998 4284422715 4285013059 4284421182 4285863997 4284291909 4285209148 4284489030 4285668418 4284227402 4284484412 4284029254 4285080395 4285539148 4285604939 4284881224 4284687181 4284092733 4284619587 4284488516 4284880962 4285934412 4286461005 4284949065 4283106874 4283304244 4283828285 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293565313 4293565054 4293563251 4293626477 4293297262 4292770654 4292636249 4290991957 4289215816 4288294730 4287180359 4288754765 4289676871 4291121484 4291913827 4292901202 4293361515 4293233520 4293235825 4293235328 4293170813 4293562494 4293564536 4293364595 4293562227 4293364846 4293232750 4293361773 4292834893 4292046954 4291714124 4290267213 4288688457 4287377994 4287375175 4287772239 4289410378 4287971408 4289413714 4289216593 4289545557 4289677655 4289283164 4289483875 4289217630 4289873493 4289150029 4289610836 4289347408 4289808734 4289544268 4290071636 4289480786 4290466395 4290269274 4290792535 4290729565 4290531161 4291255642 4290534240 4290532686 4291123293 4291124575 4291121750 4290994264 4291583078 4290992470 4291714138 4291255894 4291648089 4291584346 4292106596 4291387739 4292107102 4291255139 4291515221 4292770162 4292767841 4289678169 4290729565 4291189591 4290664791 4291252825 4290140511 4290268248 4290074460 4291386203 4290076008 4290797152 4290667363 4290669426 4291322982 4290338158 4291131506 4290665055 4290931053 4290802026 4290343032 4291128434 4291785834 4291656049 4291128175 4290273399 4291067778 4291390070 4291660424 4291457642 4291003782 4291134326 4290671997 4291989892 4292053130 4291728011 4292386955 4292053377 4291866011 4292450196 4292189077 4292327329 4292327321 4292716433 4292259232 4292130990 4292721317 4292587164 4292327342 4292591285 4292785053 4292457905 4293051316 4293047713 4292392616 4292657333 4292920239 4292918433 4292393646 4292328118 4292722609 4292330175 4292918704 4292986302 4292986048 4293708976 4291474078 4289093489 4287836226 4288756811 4289413189 4289545804 4289283409 4290530392 4289744218 4290335836 4290859353 4290205020 4290334552 4290334051 4289875544 4289808993 4290399842 4290336604 4290464853 4289610836 4289479506 4289676629 4290267477 4291124828 4291912825 4292111463 4292443758 4293228909 4292707952 4292968295 4293623414 4292969834 4292771436 4292511350 4292573804 4292574318 4292637802 4292569702 4291454317 4291915374 4291520100 4292177507 4292109925 4292177259 4292244577 4292575601 4292772721 4292443748 4292507759 4292506714 4292507762 4292901728 4292900466 4292442716 4292508786 4292507998 4292573538 4292113767 4292965728 4292507228 4292573553 4292573278 4292573294 4292572783 4292508254 4292573037 4292180584 4292572782 4292509538 4292573535 4292573278 4292510069 4292574559 4292903279 4292444016 4292968812 4292969581 4293560686 4292835944 4287703362 4283567944 4283700800 4284683075 4283964736 4283960392 4284552263 4284422717 4284748867 4284815936 4284620359 4285077053 4285537860 4285275722 4285602631 4285013060 4284616503 4283830598 4284553794 4285737294 4285536320 4284420672 4284228426 4284091963 4284224566 4285080653 4285342279 4285932872 4286330713 4284947268 4283829318 4283303986 4282843199 4287648100 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293564796 4293564535 4293562228 4293232495 4293229408 4292965473 4291582813 4290200646 4288623693 4287705161 4288490567 4288689739 4289478741 4291126372 4292307556 4292440671 4293363053 4293430896 4293628790 4293564012 4293562233 4293563255 4293365887 4293364843 4293562235 4293563509 4293230954 4293361770 4292704611 4293092190 4291255126 4289742413 4288752198 4287312202 4288622151 4287706447 4289281102 4288823123 4288693585 4289216592 4289481058 4289282898 4289480277 4289611864 4289414485 4289612121 4289414742 4289807958 4289610580 4289348943 4289742423 4289610838 4290726485 4289742680 4290400602 4290333779 4290140768 4291253337 4290531162 4291123292 4291121236 4291121754 4290533206 4291059545 4291976291 4291515986 4290992471 4291254610 4290928994 4291256670 4290863457 4291584090 4291911767 4291453274 4291713382 4291912542 4293707915 4291118673 4290073694 4290729565 4291254101 4290139992 4290794075 4290268761 4290137432 4290796906 4290666079 4290796892 4290406273 4291522167 4290663772 4290535522 4291129457 4291191143 4290076771 4290603373 4291523712 4291325290 4291196784 4291064180 4290211709 4291126645 4291265403 4291129197 4291197284 4291061614 4290544767 4291130496 4290936709 4291792525 4290739840 4291595396 4291725954 4291075491 4292252045 4291528326 4291931041 4292392341 4292319639 4292324260 4292195752 4292716174 4292258732 4292195998 4292656046 4292588968 4292522149 4292920489 4292588966 4292129449 4292657588 4293248181 4292654750 4292722091 4292722869 4292394408 4292787370 4292920237 4292788401 4292396215 4292588969 4292522158 4292788412 4292987073 4292066502 4288969878 4289296524 4288366952 4288363079 4289282129 4289547354 4290266452 4289222240 4290925145 4290334553 4290334810 4290400601 4289939543 4290530647 4290004307 4290466393 4290002788 4289283410 4290070109 4288889949 4290990433 4291054941 4291650399 4292508795 4292967279 4292510575 4293295992 4293230200 4292577907 4293428859 4292969067 4292444014 4292509807 4292575601 4292245092 4291783529 4292110434 4290863203 4291060581 4290926683 4291584356 4292110180 4292507005 4292574316 4292444528 4293229423 4292834139 4292837239 4292834399 4292900451 4292378721 4293229426 4292837999 4292444259 4292897629 4292966253 4292441691 4292572015 4292570968 4292573552 4292573037 4292575329 4292573535 4292509042 4292573532 4292967539 4292509542 4292573291 4292509538 4292902236 4292444275 4293165162 4292705900 4293166205 4293887591 4292574063 4288296013 4284290368 4284092988 4284683338 4283896131 4284422206 4284223032 4284287293 4284224837 4284618813 4285736006 4284883788 4285472067 4285667390 4284487998 4284944182 4284158278 4284417080 4284748605 4285209926 4285275718 4284621646 4284884302 4284224064 4284491087 4284555084 4285406791 4284948298 4285937500 4285734211 4284356158 4283172658 4282974271 4287053145 4292314240 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293565303 4293561977 4293363826 4293363053 4292769372 4292503384 4290858053 4289214544 4288167240 4288427084 4287770441 4288099663 4289939531 4291451222 4292176466 4292507230 4293361515 4293233777 4293169259 4293564026 4293562226 4293563256 4293169268 4293627520 4293365613 4293560941 4293429870 4292968301 4293163875 4292045653 4291581782 4289807949 4288752198 4287376967 4287966791 4288361292 4288754251 4288558925 4289480021 4289150800 4289677655 4289085264 4289478737 4289610579 4289610579 4289807958 4289414742 4289349206 4289807952 4289481050 4290069843 4289480786 4290071641 4290466388 4289809498 4289811037 4290859096 4290596697 4291124311 4291125088 4291121754 4290533718 4291122780 4291126115 4290992212 4290991708 4290995041 4291908964 4291451747 4291778903 4292104798 4291125854 4291911786 4291255140 4291319637 4292969841 4293031511 4290269013 4291253323 4290728539 4290135890 4290333272 4290267728 4290204767 4291319899 4290666335 4290797664 4290073692 4291585373 4290008666 4290671991 4291323238 4291190882 4290536285 4290669174 4290999919 4291128171 4290144888 4291125609 4291326834 4291655023 4291392897 4291260774 4290539636 4290931325 4291132804 4290599789 4291198581 4291724161 4291133055 4292248706 4290937980 4291989897 4291723378 4291403940 4292063384 4291858581 4292323227 4291999381 4292128161 4292717464 4292066233 4292720030 4292652445 4292195743 4292655525 4292786330 4292520354 4292525490 4292787619 4292524720 4292458928 4292723381 4292524721 4292787105 4292196012 4292460726 4292458665 4292127400 4291669676 4292065468 4292068803 4293053632 4293252549 4294106311 4293978063 4293713614 4291415494 4289942635 4287837003 4289085006 4289677658 4290072410 4290464598 4289875546 4290466394 4290005335 4289480533 4289283928 4290596439 4289939542 4289677909 4289612643 4289086813 4290923090 4289613668 4291124827 4291913336 4292112746 4292508781 4292969325 4292837995 4293166956 4293427318 4293100665 4292706940 4292968314 4292968315 4292510064 4292244836 4292241504 4291322978 4291058525 4291188571 4291190366 4290469728 4291781732 4292439651 4292573292 4292574318 4292444528 4292510579 4292832346 4292836189 4292443506 4292899424 4292706655 4293162351 4292835938 4292900447 4292440683 4292966513 4292508768 4292572510 4292506971 4292573037 4292574319 4292507503 4292965468 4292509298 4292508781 4292507245 4292508782 4292508527 4293163631 4292641648 4292771437 4293298035 4293036399 4292970099 4291054932 4284551486 4284418890 4283765827 4283962182 4284420679 4284156989 4283895362 4284486724 4284948298 4285013315 4285668422 4285079365 4285472845 4285077822 4285338430 4284353869 4284027709 4284488773 4285210694 4284883786 4285473363 4284423238 4283831878 4284685123 4284619074 4284816967 4285144388 4285874271 4285472839 4283634236 4283173186 4282975035 4285608264 4291458162 4293170051 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293562239 4293363824 4293560170 4293033068 4292898400 4291254870 4290134603 4288556105 4288294987 4288298577 4288360779 4288755274 4289086037 4291057490 4292437847 4292442226 4293559133 4293232238 4293629301 4293562745 4293173109 4293562745 4293564785 4293562489 4293562990 4293363564 4293429869 4293165679 4292769873 4292765542 4291254869 4289808467 4288755532 4287376455 4287378765 4288360779 4288759633 4289147722 4289217106 4288956757 4289679211 4289480277 4289610579 4289677914 4289414742 4289217106 4289480278 4289610579 4289742423 4289938002 4290071635 4289349465 4290464850 4290267736 4290925146 4290204765 4290796639 4290665311 4291122516 4291120977 4290532180 4291121498 4291124066 4291055191 4291322719 4291582043 4291058269 4290929248 4291256412 4291844961 4290863193 4291254098 4291846494 4292040538 4291845974 4293822582 4290662996 4290861662 4290727765 4290138203 4290529107 4290271069 4290268001 4290140265 4290731871 4290797665 4290138201 4290862694 4290006363 4291324529 4290599251 4291062655 4290009699 4291257969 4291128940 4291061369 4290603117 4290732133 4290734701 4291653999 4291062898 4291065459 4291062898 4290997371 4291328364 4290933631 4290738547 4291330179 4291395956 4292116341 4291396743 4291985011 4291595663 4292255122 4292120198 4291795350 4292392852 4292651177 4292191886 4292654514 4292590757 4292652442 4292059806 4292197539 4292719775 4292060826 4292196529 4292788398 4292721057 4292521377 4292723391 4292985510 4292522910 4292655281 4292262060 4292783265 4291668394 4291868346 4292133314 4293185731 4293382081 4293776579 4293580229 4293906882 4293841860 4294171848 4294108878 4294567630 4291937730 4288296255 4288753738 4288625743 4289545814 4289283937 4289547610 4289676116 4289546328 4289283414 4290528593 4289348701 4290072163 4289546851 4289546329 4289085004 4289678167 4290201959 4290597977 4291715937 4292309607 4292967537 4292706412 4293623677 4292969578 4292968827 4293560167 4293034362 4292640619 4293559662 4292575856 4292574832 4292374117 4291190627 4290991706 4290004047 4290071641 4290528852 4291124829 4291518314 4292769642 4292505959 4292969070 4292444272 4292836723 4292834141 4292509042 4292770659 4293162084 4292835937 4292443504 4292507759 4292572251 4292509553 4292506716 4292508016 4292964973 4292507499 4292509297 4292899932 4292442225 4292898137 4292445301 4292901216 4292836465 4292444530 4292837741 4292837229 4292707695 4292969584 4293625966 4291386974 4286063690 4283963980 4283764543 4284487237 4284161085 4284547901 4284490568 4284681796 4284421700 4285273659 4284751435 4285471299 4284882244 4285143101 4285076018 4284551487 4284419384 4284554302 4285406524 4285275977 4285275204 4284359756 4283964750 4284160315 4284619597 4284292167 4285080137 4285739350 4286856292 4285080651 4283565884 4283371332 4285473614 4289291386 4292051591 4293366651 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293363562 4293495674 4292640879 4292703322 4292110435 4290793300 4288758859 4288162118 4288231503 4288887117 4288165967 4288688458 4289480788 4291911770 4291980391 4292901724 4293361259 4293234545 4293561711 4293562990 4293563770 4293562225 4293563776 4293170287 4293627507 4293167739 4293495412 4293164892 4292443235 4292306785 4291713875 4289479241 4288689740 4287966791 4287375175 4288361036 4288755789 4289085520 4289217106 4289348692 4289478479 4289412943 4289676372 4288953936 4289612115 4289677658 4289217106 4289807958 4289807958 4289546585 4289478738 4290201685 4289874265 4290333528 4290205015 4290924113 4290138196 4290665568 4291056986 4290598493 4291123293 4291125593 4291058526 4291192160 4291517029 4291256925 4291126368 4291582307 4291126368 4291256932 4291254097 4291386214 4291911772 4291780194 4292112744 4291977044 4291056981 4290727765 4290135891 4290924119 4289612388 4290859351 4290728545 4291255387 4290732646 4290138201 4290205533 4290665314 4291388510 4290930034 4291191396 4290600545 4291256931 4290602851 4290733942 4290079599 4290734448 4290663514 4291196286 4290864246 4290603377 4291128436 4291262576 4290736242 4290471789 4291127656 4291000453 4291923840 4291390312 4291789698 4291659642 4291466388 4291989137 4290999432 4291732636 4292912273 4291730846 4292590243 4292981915 4292585889 4292190113 4292591535 4292652700 4292649373 4292065198 4292722350 4292587932 4292523688 4292917931 4292590765 4292851360 4292128157 4292261026 4292322715 4291670198 4291936192 4293053123 4293513410 4293446334 4293316289 4293646022 4293183165 4293644480 4293186499 4293512898 4293841604 4294040264 4294108621 4294371795 4290935674 4287243584 4287706446 4289413708 4289808723 4289414230 4289414485 4289547102 4290005077 4289480793 4289611863 4289609808 4289480020 4288759893 4289415530 4289348433 4290401379 4290664290 4291519598 4292702053 4292509294 4292835953 4293100393 4293362041 4293035377 4292969324 4292968828 4293296743 4292443774 4293232239 4292507243 4292767848 4291125084 4291316561 4288823116 4289217100 4289085522 4290268760 4290665820 4292043883 4292507256 4292508781 4292903277 4292836207 4292836976 4292441179 4293160545 4292769120 4292444257 4293228405 4292834655 4292508768 4292899183 4292900191 4292900190 4292442222 4292902515 4292506457 4292902255 4292509025 4292900972 4292899677 4292442720 4293162611 4293164888 4292770418 4292706411 4293427576 4293560684 4292699745 4287441481 4283697204 4284228167 4283830594 4283963707 4284353603 4284291389 4284161093 4284684605 4285666879 4285147217 4284682805 4285472325 4285340224 4285078340 4284424267 4284028494 4284746556 4284752459 4285210441 4285801294 4284095298 4284552775 4284161100 4284090685 4284749370 4284752970 4285869920 4286727778 4285676132 4285405765 4283698746 4285473616 4289093741 4290937978 4292970870 4293040756 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293431420 4293558375 4292705903 4292962905 4291384659 4289676106 4288032585 4288755788 4288821838 4287575630 4288753736 4288559182 4289217873 4291056468 4292701542 4292442976 4293165677 4293429357 4293563509 4293564782 4293561971 4293367417 4293564018 4293430643 4293561984 4293430893 4293232751 4293361242 4292834147 4292307042 4291647059 4290527823 4288557899 4287967562 4287311431 4288886860 4288624718 4289085264 4289151570 4289544273 4289413200 4289808739 4289153366 4289873488 4289807959 4289217363 4289480021 4289610579 4289217363 4289611864 4289480793 4290005592 4289941589 4290398801 4290336093 4290205022 4290727506 4291251287 4290599254 4290598236 4291123292 4291122003 4291058262 4291060066 4290927693 4291515746 4290928992 4291322205 4291320410 4291449953 4291650139 4291583320 4291452768 4291978345 4291715928 4290992984 4290727509 4290138204 4290793554 4290728539 4290794578 4290730591 4290666335 4291191134 4290732391 4290730078 4290731624 4290601317 4291124321 4290534501 4290928733 4290141544 4290731875 4290798698 4290136149 4290800497 4290666843 4290671993 4290732899 4291524993 4290404970 4291458684 4290992994 4291063669 4291652199 4291326847 4291588973 4290932851 4291589747 4290798182 4292512647 4291458414 4291594879 4292386963 4292382337 4291926928 4292195228 4292653980 4292059300 4292197025 4292654490 4292586137 4292126625 4292592311 4292717210 4292191381 4292787888 4292655779 4292718757 4292128411 4291861395 4291733676 4292195766 4292133571 4293512640 4293776321 4293317828 4293313467 4293316802 4293314750 4293643198 4293251781 4293642941 4293185217 4293972931 4293448130 4294235332 4293714379 4293910217 4292267982 4289418847 4287047750 4288297809 4288561231 4289874517 4289217108 4289677657 4289807701 4289414485 4289481051 4288694366 4289743192 4289545823 4289150815 4289152603 4290465121 4290598233 4291585133 4292505720 4292507754 4292444529 4293426790 4292969837 4292640365 4293232500 4293231208 4292836986 4292969853 4292838767 4292509038 4292703594 4291389288 4290795613 4289085007 4287705419 4287705419 4289018188 4290989400 4291256420 4292110441 4292704876 4292508524 4292641410 4292834132 4292441967 4292837217 4292835186 4292508786 4292834391 4292900192 4292506222 4292507740 4292509041 4292507759 4292900190 4292900713 4292507501 4292902254 4292507997 4292509041 4292509040 4292507997 4292770930 4292770674 4293098091 4292969083 4293298043 4292901482 4289020754 4284158534 4283962696 4283828551 4284221503 4284746552 4284615486 4284288332 4285535542 4285143102 4284882500 4284947523 4285342282 4285471300 4285208893 4284552773 4284091198 4284420919 4285011270 4285668668 4286127171 4284817993 4283698495 4284161097 4284291650 4284685122 4284818768 4285146711 4286197840 4286067550 4285934676 4284159552 4285603658 4288764008 4291067759 4292510072 4292841342 4292972150 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293295978 4292968284 4293358181 4291650892 4290200147 4288626251 4288162888 4288756559 4288754250 4288166993 4289281102 4288952653 4290201682 4291124055 4292043615 4292900449 4293165933 4293232492 4293562747 4293562996 4293170800 4293563768 4293562233 4293170294 4293629042 4293167733 4293492840 4293163872 4292833633 4292372819 4291382608 4289090905 4289279050 4287180873 4288032841 4288229708 4289280845 4289019728 4289217106 4289151570 4289478737 4289807958 4289610323 4289414743 4289349206 4289610321 4289614183 4289546327 4289414742 4289807958 4289872466 4290005849 4290135637 4289810011 4290334554 4290139486 4291253843 4290600289 4290663773 4291122010 4291123036 4291059296 4291646296 4290994784 4291517286 4291385946 4291713121 4291256670 4291321950 4291255892 4291190629 4291387220 4291650657 4292701281 4291253328 4290857046 4290203219 4290464594 4290858328 4290137689 4290729308 4290731872 4290731110 4290730855 4290140523 4290732388 4290666852 4291450454 4290667367 4291322995 4290076006 4290271837 4290865255 4290139230 4290210939 4290865255 4291191659 4290538870 4291128946 4291259004 4291854703 4290863215 4291594874 4291191902 4291000957 4291063659 4291131519 4291067510 4290995305 4291331974 4291850867 4291395720 4292055942 4291659655 4292385693 4292386191 4292121742 4292588213 4292654744 4292650652 4292194215 4292590245 4292788399 4292587163 4292065199 4292328612 4292782480 4291667107 4291466386 4291731633 4291147709 4293510843 4293381312 4292988610 4293643711 4293708992 4292922562 4293313980 4293315006 4292988610 4293313980 4293315006 4293251266 4293116088 4293249727 4293643969 4293055685 4294236102 4294038725 4294569682 4291936456 4287310907 4287771468 4288888401 4288494413 4289545545 4289085265 4289545815 4289283156 4289543759 4289743192 4289282890 4289741919 4289086028 4289674849 4289221212 4291252823 4291125606 4292505961 4292964971 4292378734 4293035907 4292969324 4293296745 4292837996 4292705900 4293034619 4293296744 4292444271 4292507499 4292638058 4291715940 4290924889 4288035407 4287046985 4287178823 4287310153 4289217358 4291255902 4291324524 4292044137 4292575086 4292901737 4292836466 4292902257 4292440170 4293162339 4292378720 4292902006 4292443762 4292506969 4292966515 4292509039 4292507743 4292898652 4292442221 4292509297 4292834397 4292507761 4292899932 4292836723 4292770930 4293100138 4292772204 4292771709 4293625966 4293165422 4290924622 4284946505 4283762757 4284223282 4284026176 4283960370 4284224327 4284748862 4285273404 4284883534 4285276233 4285078855 4285143612 4284685385 4285013571 4284552516 4284291133 4284092990 4284684606 4285340223 4285276234 4284816969 4284223814 4284093245 4284617795 4284750658 4284225862 4285407814 4286264413 4286136419 4285344342 4285275462 4286196814 4288501354 4291064952 4292249979 4291789944 4291789937 4292645251 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293426275 4292837479 4292044366 4291316554 4288429131 4288686920 4288756559 4289279306 4288626254 4288757329 4288623690 4289086033 4289215559 4291124579 4292374602 4292834659 4293427049 4293036406 4293431917 4293563252 4293563001 4293563000 4293563506 4293628025 4293169270 4293693556 4293298286 4292640883 4292901459 4292306007 4291583831 4289807947 4288559182 4287967049 4287247952 4288427082 4288626263 4289150799 4289019471 4289217106 4289283156 4289610579 4289414999 4289610322 4289807952 4289546329 4289482074 4290332500 4289742166 4289151827 4289807958 4289676629 4289283673 4290465364 4290268757 4290791505 4291189343 4290662995 4290597718 4291121739 4291124056 4291122259 4291057501 4290992990 4291321685 4291450973 4291189852 4291254098 4291256676 4291256414 4291913056 4291124829 4291848034 4291255131 4290662747 4290136914 4290136150 4289938773 4290205277 4290795098 4290730081 4290732385 4290727253 4290665313 4290734701 4291256157 4290732388 4290011249 4291387742 4290073683 4290929253 4290271330 4290140004 4290733406 4290668137 4291126123 4291132537 4291124835 4291588973 4291527283 4291062125 4291786087 4291455348 4290934902 4291389303 4290935924 4291986051 4291192699 4291528566 4291191674 4291792251 4292710799 4291985020 4292514434 4291990665 4292124056 4292716182 4292588951 4292187020 4292129436 4292717463 4292586395 4292522391 4292657586 4292784038 4292118394 4291464862 4291667113 4292328890 4292660677 4293577662 4293187783 4294036670 4293248444 4293576379 4292985772 4293379517 4293315519 4293381055 4292985788 4292986045 4293313980 4293774782 4292924613 4292985011 4293707452 4293252549 4293120965 4294237897 4293776581 4294042317 4291075495 4287309378 4287114311 4289607243 4287971409 4289413714 4288825172 4289281873 4288759634 4289677408 4288627810 4289282124 4288953696 4289217361 4290464855 4291120990 4291584612 4292308324 4292507755 4292968573 4292837736 4293232491 4292836988 4293230200 4292707694 4293493112 4292969067 4292640895 4292900459 4292638058 4291979619 4290204508 4288559695 4286651719 4285797702 4286060871 4288822606 4290466133 4291321954 4292374890 4292373624 4292510832 4292901488 4292837741 4292443505 4293161550 4293161331 4292770650 4292834404 4292899439 4292441433 4292900978 4292507741 4292507758 4292900720 4292835936 4293227619 4292441692 4292442223 4292769116 4293554540 4292965995 4292639600 4293754980 4293822064 4291522407 4286915399 4283895101 4283828024 4284223290 4284549177 4284681536 4284614974 4284421438 4284948036 4285076803 4285472835 4285472067 4284947526 4286062665 4284619586 4284355399 4283893572 4284292935 4285209670 4285342282 4285078079 4284159299 4284290630 4284617796 4284882245 4285742956 4285217376 4285932623 4285677155 4286132575 4285606727 4285674335 4288760686 4290541176 4291200377 4292117629 4291263608 4291919987 4292248695 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292770404 4292506203 4291779157 4289479242 4288623691 4288755531 4288166736 4288035664 4289216592 4289213514 4288690510 4288493133 4289546326 4291123798 4292636008 4292443232 4293033838 4293299573 4293365370 4293563245 4293564018 4293563263 4293365106 4293365113 4293237366 4293037938 4293296748 4293493087 4292440929 4292372831 4291319123 4289742675 4289280846 4287179847 4288687174 4287574604 4289410122 4288496464 4289348178 4289151056 4289478737 4289871953 4289412943 4289808739 4289348943 4289546329 4290071127 4289284194 4289546322 4289873494 4289349206 4289610837 4290531413 4290269532 4290334292 4290138204 4290728787 4290598751 4291188052 4291123294 4291123293 4291123036 4290994008 4291582821 4291255131 4291255893 4291648608 4291584346 4291714404 4291321178 4291125603 4292373100 4291318607 4290664029 4290138197 4290857554 4290203995 4290924119 4290728280 4290730344 4290138970 4290794329 4290074983 4291454303 4290665822 4290731110 4290072152 4291454565 4290139484 4290929004 4290205795 4290206558 4290731357 4291127928 4291125605 4291128180 4290533725 4291129717 4291128170 4291260290 4291589228 4290862697 4291328131 4291454315 4291391850 4291918719 4290736503 4292114284 4291261557 4291725680 4292048762 4291921517 4292316815 4291590785 4292384907 4292581255 4292185479 4292585373 4292654746 4292125083 4292125588 4292262314 4292979609 4292056199 4291728515 4291269027 4292263097 4293051319 4292988868 4293774526 4293644482 4294035899 4293248445 4292986301 4292656823 4292919996 4293381313 4292985788 4292986044 4292986301 4292919737 4293053120 4292985788 4293773243 4293318597 4293313723 4293314750 4293314237 4293185729 4293844169 4293844168 4293844428 4289957778 4287636798 4287181132 4288951883 4288757072 4288692815 4288956494 4289412963 4288891230 4289412941 4288104292 4289347663 4289217364 4290070101 4291123546 4291452516 4292768104 4292507756 4292771946 4293296776 4292968825 4293165415 4293428328 4292707441 4292575855 4292378479 4292509547 4292707200 4292504935 4291258476 4291059292 4289020498 4286654535 4285272634 4285993284 4287572551 4288756303 4291451740 4290732132 4292899431 4292573035 4292510321 4292837741 4292901745 4292441967 4292835695 4292835179 4292836972 4292507758 4292508015 4292834652 4292900977 4292507500 4292507499 4292509039 4292443761 4292832092 4293228658 4292834928 4292246893 4293426024 4293361020 4293625192 4292967789 4288885066 4284420419 4283829044 4283960899 4284093258 4284289598 4284419391 4284619325 4285340991 4285473869 4285472835 4285013830 4284815683 4285800518 4284357186 4284750925 4283700799 4284355133 4286194755 4285408844 4285207867 4284356925 4284288580 4284224836 4284553791 4284622928 4285277002 4285539666 4285343825 4286072185 4285869912 4286656857 4288763752 4289952379 4291723891 4291527560 4292053878 4291527029 4290867317 4291721823 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4293291345 4292043867 4290397260 4289018190 4288165454 4288165197 4288691537 4289280589 4289085520 4288690253 4288626513 4289147722 4289284428 4291122261 4292109664 4292572767 4293033308 4293296489 4293628032 4293562738 4293170038 4293627762 4293169527 4293562738 4293561722 4293431407 4293101674 4292967773 4292899425 4292174692 4291318604 4290136397 4288623947 4287966279 4287180874 4289083982 4288037457 4289281615 4288430157 4289415009 4289478736 4289217620 4289481309 4289611864 4289414486 4289546323 4290071385 4289348943 4289807959 4289151827 4289742166 4290071129 4289808723 4290989138 4289677145 4290924371 4290073694 4291252307 4290533464 4291124055 4291122259 4290993503 4291453279 4290993751 4291256933 4291322207 4291252558 4292108905 4290927959 4290862168 4292240992 4291451984 4290923090 4289614687 4290528078 4290728795 4290270557 4289612633 4290795356 4290796894 4290136662 4290667370 4291453538 4291122521 4290140515 4290272351 4290535520 4290272608 4289877334 4290335588 4290207591 4290732132 4290599773 4291323239 4291326058 4290729823 4291129200 4290929783 4291528316 4291715939 4290867571 4292117363 4290995555 4292049008 4291328883 4291591294 4292311678 4291130223 4292315267 4292115591 4291265669 4291263349 4291987327 4292450183 4292380049 4291333253 4292325024 4292653986 4292580235 4292129187 4292719258 4292453787 4291591022 4291004051 4291668663 4292590516 4293511873 4293248446 4294102720 4293315520 4292853945 4292788666 4292853945 4292986045 4293447105 4292854195 4293445301 4292987585 4292986045 4293445565 4293051838 4292722359 4293117373 4292853945 4292985275 4292988097 4292989123 4293317571 4292858821 4293843912 4293779915 4294040006 4292859343 4288630886 4287244870 4287967819 4287773009 4288887629 4288231760 4288233294 4288366673 4288824402 4288889937 4288561231 4289413971 4289414742 4290599015 4291977060 4292111204 4292964972 4292772204 4292838524 4293165944 4293166201 4292970367 4293426790 4292968296 4293361528 4292642180 4292444526 4292639083 4292439395 4291058803 4288825164 4287244107 4285072185 4284354104 4286321475 4288952395 4289807701 4291190366 4291584611 4292506989 4292509038 4292836203 4292837999 4292442716 4292899182 4292377436 4292900979 4292506196 4292506219 4292901234 4292833644 4292901727 4292835441 4292898924 4292902252 4292835165 4292379507 4292772448 4293294972 4292771961 4293232254 4293099117 4290332236 4285205564 4284025663 4285352810 4284822872 4285014609 4284550980 4284748605 4285407818 4285408332 4285405507 4284815939 4285538124 4285079365 4284948556 4284619588 4283897151 4284224836 4285210182 4285144648 4285407304 4284292425 4284226115 4284619840 4284749885 4285340223 4285015890 4285211722 4285869661 4286071661 4286460002 4286659932 4287975025 4289949317 4291852150 4291527287 4291988352 4292709491 4290278006 4290998130 4291725953 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4292632923 4291122242 4289675343 4288033355 4288230733 4289216593 4289676874 4287904080 4289282640 4288033869 4289281102 4288560721 4289281353 4291714139 4292109664 4292573539 4293099619 4293102456 4293235574 4293627257 4293170805 4293630322 4293365106 4293561977 4293562995 4293365104 4293493867 4293166192 4292899153 4292044365 4291450463 4289741385 4288690511 4287310918 4288098377 4287773264 4288820812 4288692827 4289479764 4289348435 4289283156 4289281358 4289412945 4289873488 4289217364 4289807952 4289742423 4289412944 4289610579 4289349201 4290267223 4289941589 4289939795 4290333529 4290335061 4290139486 4290794326 4290532958 4291188828 4291123036 4291057757 4291646298 4290994009 4290993247 4291973716 4290928993 4291060066 4291254617 4291256413 4291913313 4291255893 4290662996 4289613148 4291055947 4289547612 4291253337 4290925400 4290860386 4290795098 4290136662 4290733419 4291254875 4290600799 4290600038 4290863200 4290272352 4290337116 4290465634 4289220709 4290337379 4290732131 4291323495 4291126893 4290537577 4290602863 4290800751 4290995815 4292118137 4291391600 4291460982 4291130742 4291326063 4291790465 4291260528 4291721599 4292378225 4291722618 4292245872 4290867829 4291394417 4291917940 4292049789 4291525748 4292049800 4291925897 4292782240 4292646023 4292190610 4292721311 4292450444 4292445831 4291198835 4290945459 4292789953 4292986300 4293511616 4293114791 4293840056 4292787123 4292722359 4292855485 4293446335 4292990149 4292985788 4293248443 4292985781 4292722866 4293575606 4292985787 4292919994 4292788408 4292919994 4292855227 4292989893 4292987841 4294037953 4293252035 4293645251 4293646021 4293844169 4294238667 4293383621 4294173644 4292263612 4287639621 4287376198 4287509838 4287968331 4288493133 4288428880 4288297296 4288494924 4288756560 4288692814 4289217372 4289415266 4291255900 4291256417 4292769643 4292507499 4292771950 4293428078 4293364077 4292968827 4292903274 4293165674 4293232000 4292903273 4292576109 4293227623 4292376958 4291783789 4291191646 4289545300 4286588743 4285074742 4283697991 4285274946 4287114827 4288367443 4290398294 4291518559 4292177512 4292573548 4292900462 4292770929 4293228140 4292769902 4293228661 4292834396 4292442480 4292967265 4292441436 4292507757 4292443761 4292899165 4292442973 4292443505 4292835440 4293161064 4292705394 4292967276 4293558134 4293365102 4292501853 4286323520 4283699020 4284027468 4283896383 4284487739 4284353340 4285009719 4284355910 4285142588 4285275466 4285602621 4285011516 4284685641 4285603395 4284879178 4284488509 4284224837 4284880444 4285801289 4285672009 4284681788 4284423751 4284620873 4284553795 4284751431 4284488000 4284752972 4285608292 4285280084 4286593883 4286003557 4288041063 4289685625 4290609024 4291330177 4291528574 4292118128 4291790727 4290932338 4291724657 4292448647 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4291451727 4289676366 4289016907 4288753736 4288166737 4289217354 4288496209 4289216336 4289083469 4288759377 4288753480 4288624462 4289283661 4291122776 4292109666 4292574547 4292771169 4293558120 4293035886 4293431161 4293628536 4293170813 4293628797 4293170301 4293627513 4293365869 4293495406 4293033837 4292507232 4292438106 4291056462 4290133581 4289148491 4287377482 4287509066 4287314266 4288168015 4289611092 4289348436 4289282899 4289481818 4289480278 4289676372 4289349207 4289412944 4289742423 4289544786 4289415516 4289546586 4289807696 4289217872 4290005593 4290070103 4290399316 4290202189 4290858581 4290664286 4291188307 4290532188 4290599775 4291122516 4291057743 4291123543 4291058783 4290993246 4291582819 4290994271 4291650661 4291649380 4291257193 4291124318 4290138973 4290398807 4290135377 4291384922 4291188828 4290076770 4290268247 4290141031 4290797158 4290730075 4290076000 4290729568 4291321694 4289809240 4290402653 4289873504 4289811299 4290925670 4290208364 4290730587 4291129712 4290929524 4291129198 4291125604 4291061363 4291786087 4291388268 4291461495 4291650147 4291198339 4291722110 4291851892 4292050025 4291592322 4292052855 4291850591 4290013307 4292379763 4290799472 4291461237 4292182397 4291854195 4292385935 4292776582 4292185727 4292262813 4292253324 4292184962 4291198322 4289494917 4291929004 4293380796 4293051839 4293642170 4292986045 4292920509 4292655536 4292920252 4292986046 4293512384 4292923075 4293641657 4293445823 4292722873 4292854202 4292459445 4292130222 4292262585 4292986814 4292722359 4293446848 4293317573 4293776580 4293317829 4293511611 4292988354 4293379003 4292987841 4293250754 4293120708 4294303433 4294170309 4294437842 4289759128 4287703871 4286917188 4286983751 4287509839 4287378253 4288560464 4287707216 4288757072 4288691536 4289151049 4290006116 4291123034 4291715422 4292702312 4292509295 4292771693 4293232497 4292968827 4293033573 4292838783 4293033577 4292903273 4293101443 4292640636 4292641406 4292639081 4291782242 4290862430 4288626002 4287899723 4284090419 4283959607 4284355660 4286391377 4288889437 4289349216 4291126369 4292045668 4292636519 4292509295 4292903277 4292379249 4292836460 4292375642 4292509810 4292963178 4292442480 4292965726 4292442477 4292964715 4292376940 4292900977 4292834395 4292835184 4292770399 4292967278 4293294956 4293821029 4292836206 4289017154 4284025156 4283960381 4284286789 4283962696 4284354884 4284420938 4284357700 4286192963 4285012284 4284816708 4285405763 4286129228 4284687178 4285272375 4283962687 4283696184 4284748349 4285080135 4285931331 4285603140 4283896382 4284421692 4284553795 4285143619 4284422464 4284621388 4285275221 4285539921 4286135144 4286070375 4288107377 4290080390 4290805621 4291593091 4291527815 4292050544 4291658863 4290406769 4291592306 4292120186 4292121721 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290659661 4289152078 4288098891 4288231758 4288756301 4289085265 4289150544 4289019472 4289348685 4288689997 4288099403 4288559182 4290069321 4290727766 4292308316 4292571230 4292378209 4293298287 4293430901 4293430904 4293171061 4293627261 4293629047 4293430903 4293364856 4293628295 4293232492 4293034094 4292507999 4292243053 4291121992 4289746266 4289213515 4287376198 4287379795 4288493130 4289019981 4288561743 4288825172 4289348436 4289480015 4289480279 4289019728 4289808215 4289806417 4289742420 4289742423 4289544787 4290069836 4289481050 4289742166 4289940057 4289940045 4289808462 4290989652 4290139479 4290664029 4291122259 4291323746 4290533728 4291122260 4291124056 4291057244 4291582300 4290928471 4291517027 4290994528 4291516513 4290995557 4291190365 4290796894 4290860636 4289679195 4290274665 4290135637 4290730077 4290793561 4290202969 4290795605 4290664797 4291256419 4290664797 4290336347 4290727511 4290270041 4290337378 4289813085 4289814382 4291387996 4290536049 4290668651 4290533221 4291197298 4290928237 4290473073 4291520602 4290868344 4291590253 4290926946 4291461495 4291654249 4291852922 4292049764 4292116865 4292380789 4291323500 4290869122 4291657331 4291260788 4291787129 4292114814 4291327861 4292709254 4291985537 4291924619 4292782745 4292516234 4291459442 4290604404 4291073694 4292915381 4293250491 4292985529 4293248435 4292985786 4293248443 4292985271 4292854716 4293248444 4293840054 4292392885 4293707963 4292723386 4292457905 4292722096 4292656566 4292987073 4292985788 4293116856 4293841345 4292919995 4292854202 4293445306 4292656567 4292919738 4292853945 4292527039 4293052607 4292986558 4293381824 4292989123 4292923074 4293120450 4294366148 4293385421 4290096818 4288042371 4287444040 4287573575 4287574860 4287377996 4288426827 4289414225 4288688458 4289019728 4289873486 4290795868 4291716197 4292243044 4292899436 4293165417 4292836986 4293427830 4292969083 4293427573 4292837996 4292902522 4293297528 4292837225 4292444526 4292964716 4292440166 4291321951 4289478214 4287046728 4285400888 4283636806 4284029768 4285209924 4287379531 4288824913 4290791509 4291060576 4292503145 4292572265 4292509038 4292836208 4293098607 4293555552 4292439654 4292442719 4292964443 4292440939 4292899693 4292376941 4293294194 4292376682 4293162866 4292771184 4292705136 4293493112 4293689701 4293362542 4291515983 4285403710 4284355647 4283828281 4284026163 4284420665 4284091454 4284488771 4285144901 4285342283 4285605456 4285667643 4284815940 4284817997 4285270329 4284683583 4284680254 4284290124 4285473347 4285734729 4286127683 4284223805 4284486205 4284752975 4284882759 4284949323 4285211980 4285738062 4285606229 4284883528 4285741172 4288302703 4289096831 4290871157 4291199865 4291789700 4291987835 4290936951 4290738564 4291789945 4292119417 4292383100 4292318608 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288954192 4288688458 4288230990 4288166736 4289215053 4289282893 4288759373 4289150544 4288625744 4288691792 4289213771 4289083981 4289218131 4291188569 4291977302 4292571482 4292969090 4293494121 4293430894 4293561977 4293432435 4293693053 4292842611 4293430904 4293364844 4293363567 4293495406 4293033306 4292505196 4292239952 4291058778 4290135627 4288624718 4287311946 4288097350 4287769414 4288166734 4289346640 4289414485 4289282899 4289676896 4289218645 4289480278 4289873495 4288954193 4289414737 4289610574 4289349201 4289939800 4289676623 4289610839 4290596434 4289874266 4290466647 4289742424 4290205277 4291253082 4291124311 4291122781 4291123021 4291123294 4291122262 4291059296 4291320922 4291517284 4291257189 4291319376 4291257449 4292570720 4291056723 4290662747 4290728281 4290731359 4291319643 4290139228 4290203225 4290859353 4290206559 4290729308 4290730846 4290074979 4291255645 4290072922 4290798693 4290533488 4290733420 4290928230 4290206557 4290139744 4290666084 4291325028 4291128945 4290536034 4291131507 4291124578 4290344058 4292116085 4290799985 4291527286 4291649659 4290802029 4291853440 4291258471 4291853178 4291916400 4291394933 4291587693 4290930796 4292048751 4291918447 4291657848 4291918977 4291654764 4292055688 4292385166 4292251781 4290932846 4289684330 4291932343 4292785316 4292658613 4293112489 4293118146 4292525495 4292392875 4293051832 4293316034 4293445566 4292459958 4292786865 4292986301 4292788665 4292522158 4292264894 4292589997 4292853945 4293513668 4293313979 4292525493 4292525237 4292393651 4292788408 4292854459 4292788408 4292722359 4293446848 4293052607 4292986814 4292988353 4292987841 4293381824 4293317571 4293710274 4293448901 4293907396 4294765264 4292336078 4289367705 4286455362 4286916938 4287573830 4287968845 4287770699 4288296782 4289151055 4289217623 4291253081 4291715679 4292440427 4292899435 4292378992 4293297531 4292969578 4292903274 4292970372 4293428326 4293034618 4292902520 4292772474 4292706172 4292575086 4292241766 4291188571 4288757839 4287114830 4285271610 4284419134 4284096074 4285011264 4285468219 4288034640 4289414731 4291321696 4291191904 4292571499 4292508012 4293164142 4292705644 4293162083 4292443745 4292900978 4292440683 4292508270 4293225822 4292833371 4292442222 4292835182 4292771184 4292705135 4293165434 4293689443 4293099377 4292176232 4286981963 4283827781 4283962167 4283894086 4284221510 4284289598 4284554565 4285537350 4285998667 4285275722 4285603396 4285210442 4285209919 4285537091 4284485444 4284223813 4283964479 4285140795 4286390345 4285867336 4284158282 4284290371 4284224837 4284687181 4285079114 4285209410 4284750680 4285080647 4285341786 4285279305 4287117150 4288964216 4291262591 4291395969 4291854207 4291463035 4292183930 4290605940 4291133559 4292186500 4292056962 4292317834 4292253055 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288757072 4288165965 4288757328 4289281872 4288494672 4289150800 4288558413 4289150800 4288757587 4288625744 4289281102 4288493133 4289347147 4291188566 4291584090 4292638828 4292769626 4293364079 4292970355 4293627775 4293038439 4292972163 4293692801 4293561979 4293563773 4293430655 4293102197 4292838258 4292965984 4292242533 4291056727 4290202194 4289149517 4287900742 4287377738 4288425801 4288757586 4289281098 4288953935 4289348949 4289412943 4289677652 4289610580 4289151564 4289677908 4289807703 4289349201 4289807953 4289479251 4290071386 4289743699 4289545046 4289940052 4290332748 4290269532 4290792535 4290595671 4290598237 4290533207 4291189591 4290532189 4291124055 4291122002 4291059040 4291124312 4291318094 4291125086 4292637289 4291980376 4290595416 4290333006 4290858584 4290726486 4290535257 4291254365 4290139228 4290268761 4290268761 4290729564 4290860379 4290140254 4291255137 4290728288 4290732904 4290665569 4291452506 4290009707 4291451997 4290079607 4291126892 4291125350 4290736749 4291125350 4290338153 4291657085 4291191667 4292113504 4291918464 4290928486 4291918448 4292048750 4291263357 4291983987 4291918453 4290863727 4291591278 4290735228 4291128946 4290933876 4291262080 4291391599 4291329402 4292314245 4292383380 4292577145 4290142052 4290804620 4292394679 4292986550 4292457902 4292982174 4292394684 4292392355 4293643195 4292788926 4292917155 4293641907 4293182910 4293182650 4292393909 4292985270 4292788667 4292656046 4293513154 4292129708 4292657079 4292327859 4292656822 4292920252 4293051837 4293051838 4292854202 4293839549 4292986045 4293052864 4292987071 4292987071 4293380799 4293380542 4292988097 4293315006 4293314750 4292859333 4293645509 4293120964 4294171849 4294436301 4293450958 4289893531 4288890191 4286978886 4287574087 4288099405 4287837515 4288689997 4289612110 4290662746 4291583839 4292702568 4292509295 4292509808 4292903275 4293494651 4292837738 4293427575 4292837243 4292705899 4292970347 4292968585 4292448127 4292571495 4292307815 4290534239 4290004815 4287571270 4285142341 4284748855 4284157247 4283893561 4285404734 4286783304 4288295755 4289874002 4291911269 4291912294 4292636519 4292771692 4293227884 4292377181 4292836726 4293160542 4292901475 4292506219 4292442733 4292901235 4292441947 4293162867 4293098605 4293032814 4293294698 4293362282 4293229673 4289346377 4284351027 4283697464 4284287047 4283632957 4284353598 4284812606 4284551741 4285472067 4285471042 4285800264 4285081163 4285210183 4285668421 4285341514 4284357447 4284353598 4284878134 4285474125 4285210438 4284749898 4284748347 4284556109 4284682031 4285670476 4284555853 4285277516 4284621385 4285078876 4285801558 4286070131 4288631926 4291066484 4291459455 4291264897 4291460978 4291659645 4291462522 4290936181 4291923847 4292383610 4292318594 4292253056 4292711050 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287708496 4288297805 4288756816 4288562000 4289348173 4289282637 4289085265 4289282637 4289150544 4289282128 4287968333 4289216591 4289283417 4291187274 4291783016 4292639073 4292771423 4292969070 4293692541 4293365621 4293235845 4293693556 4292843399 4293235073 4293627778 4293429365 4293100909 4293492830 4292441952 4292239960 4291188821 4290465108 4288757843 4287900742 4287376967 4288361292 4288755018 4289150800 4289282643 4289085515 4289873752 4289217364 4289610573 4289874275 4289151569 4289546586 4289610579 4289349206 4289612121 4289742167 4289283402 4290071643 4289939271 4290334552 4290859090 4290728019 4291187025 4291125089 4291123798 4290533727 4291125337 4291123286 4291124576 4291122522 4291060322 4290994017 4291455074 4292307556 4290992730 4290267479 4290469730 4289610836 4290203995 4291253082 4291122515 4290729308 4290206303 4290203225 4291385692 4289549919 4290924376 4290073179 4290796638 4290139997 4290728793 4290665571 4291322204 4290011510 4291389289 4291586927 4291063407 4291058269 4291458670 4292114802 4290930791 4292315007 4291786365 4290734447 4292380546 4292046692 4291324527 4291721325 4291128449 4292114785 4290995312 4290997619 4291653225 4290996071 4291590258 4291392881 4292115826 4291129710 4290473331 4290932844 4290077046 4291533715 4292853422 4292918703 4292984750 4292918709 4292196277 4293050779 4292657847 4292653467 4292721576 4292460218 4292392623 4293048230 4292459703 4292722608 4292854717 4293182127 4292591545 4292390829 4292394165 4293379772 4293314751 4292262835 4293707184 4293315777 4293379516 4292987328 4292985788 4293379772 4293381312 4292985788 4292985788 4293381311 4292986814 4292988353 4293774783 4293052091 4293710273 4293577149 4293251267 4293839804 4293840833 4294436044 4293387220 4290083700 4285470268 4287373896 4287048775 4287377481 4288821326 4288954188 4291318874 4291126623 4292569961 4292573292 4292444273 4293100907 4292640893 4293231994 4293165671 4292837244 4293101163 4292443774 4293494647 4292837483 4292572010 4292110432 4291188572 4289283150 4287572301 4285597756 4284489546 4284091960 4284483636 4284552770 4286056509 4287574606 4289939283 4290135630 4291651427 4292504681 4292965228 4292379763 4292901997 4292770401 4292834913 4292505691 4292506974 4292898156 4292834910 4292836725 4292770142 4292705394 4293034089 4293298028 4293493363 4290729045 4285598521 4284288583 4283960382 4284157758 4284353349 4284617029 4284619592 4285600832 4285146442 4285340739 4285340227 4286060866 4285014606 4284686921 4285270329 4284485444 4284881984 4285276234 4285866823 4285409366 4284682812 4284552259 4284884817 4284816714 4284946496 4284947527 4284686925 4284554825 4284816706 4285609576 4288962667 4289951608 4291592835 4291002741 4291393408 4291002743 4291002744 4290933875 4291791492 4292120960 4292318607 4292711808 4292318593 4291793016 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288821325 4288755789 4288691536 4289216078 4289085008 4288496208 4289479245 4288561233 4288627280 4288625744 4289346125 4288757331 4289348687 4290665569 4292174946 4292573022 4293098354 4293429612 4293036146 4293430398 4293301366 4293431677 4293430140 4293693046 4293234808 4293233523 4293363821 4292968558 4292900449 4292438110 4291122517 4289610836 4288889426 4287900485 4287377738 4288361804 4288756046 4288627536 4288693325 4289414224 4289480529 4289085521 4289478737 4289546584 4289546328 4290528845 4289545044 4289610580 4289349201 4289807953 4289742417 4289806932 4290069842 4290333011 4290267993 4290137429 4290728283 4290597715 4291123293 4290535265 4291124063 4291125081 4291124319 4290534239 4291122002 4290664792 4293238918 4291121482 4290856788 4289479760 4289544789 4289415251 4290594127 4290072410 4291452253 4290665311 4290794844 4290137690 4290664790 4290860379 4290731359 4290795100 4290793303 4290205533 4290863974 4290074465 4290664804 4290864216 4291261048 4291059555 4290800245 4291396483 4291782264 4291656574 4292116106 4292245111 4290803317 4291587182 4291260784 4291723393 4291195774 4290800239 4291394677 4291848056 4291063665 4291128945 4291129204 4291128429 4290997106 4291854447 4291062899 4290078830 4290405991 4290476433 4292126109 4292782492 4292722340 4292850344 4292723391 4292854451 4292919989 4292849583 4292916903 4292524729 4292587681 4292786856 4292590768 4292129727 4292591024 4292722611 4292521896 4292327091 4293182649 4293052095 4293707192 4292591544 4293641656 4293447362 4292393653 4293643710 4293314237 4293379772 4292987328 4292986045 4292985780 4292987072 4293248186 4292788409 4292987327 4292986814 4292987071 4292986815 4293316545 4293710787 4292923331 4293252035 4293184447 4293514950 4294105543 4292994773 4288499035 4285401407 4286849864 4287573830 4288298322 4289085260 4290794075 4291847008 4291782243 4292572010 4292837741 4293230458 4293035375 4292836987 4292968297 4293231206 4292968330 4293099365 4292904316 4292835951 4292573803 4292242022 4291124574 4289480017 4287575378 4285274173 4284681527 4284417863 4284615738 4284550196 4284812343 4285993536 4287901258 4289807433 4291190624 4292043875 4292438889 4292900445 4292836981 4293227360 4292441704 4292506734 4292505946 4292833134 4292832603 4292836723 4292771185 4293096815 4292837757 4293950824 4291916392 4287570755 4284089925 4283896630 4284550476 4284554301 4284223814 4284946488 4284945474 4285208632 4285602108 4285801546 4285011266 4284947526 4285540685 4284816457 4284684861 4284552517 4284750399 4285540172 4285142588 4284091959 4284418872 4284488772 4285012290 4285013059 4285542734 4284160846 4284620616 4283963721 4285606493 4288173424 4290344836 4291790711 4291329921 4291068279 4291134328 4291131764 4291129460 4291134587 4292119941 4292383616 4292318606 4291924606 4292318607 4292317320 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288165709 4288756558 4288823116 4288627299 4289348171 4289150544 4287970896 4289022282 4289348174 4288691280 4288035408 4288627535 4289546069 4290597202 4292373612 4292112726 4293163101 4292773495 4293299065 4293496184 4292709999 4293102455 4293234551 4293039477 4293232746 4293496449 4293100651 4293231468 4292506972 4292242793 4291124055 4289283152 4288099156 4287968341 4287966277 4288427340 4288165454 4289412176 4289282637 4288953679 4289151058 4289151058 4289413201 4289807957 4289808738 4289545043 4289414743 4289610574 4289610574 4289349207 4289742167 4290071379 4289874517 4290333011 4290268754 4290859610 4290664285 4290662490 4291121497 4291125592 4291123037 4291123037 4290533462 4291252825 4290858327 4292905851 4293828215 4291317335 4289348689 4290070615 4290530648 4289545045 4290399320 4290269018 4290793043 4290729565 4290730839 4290660951 4291253082 4290075231 4290859096 4290138971 4290205287 4290271068 4290074726 4291453787 4291127668 4291124319 4290993760 4291000180 4291588719 4290862177 4291329653 4291918959 4291328884 4291461238 4291647062 4290409595 4292115311 4291851115 4291724164 4292245112 4292308853 4290937207 4290929527 4291195257 4290600294 4290603890 4291260530 4290077552 4290731881 4289879414 4291993492 4293180855 4292586654 4292519312 4292913055 4292526256 4293575588 4292656821 4292522917 4292524969 4292522412 4292787623 4292000444 4292587177 4292788132 4292655269 4292585111 4292522411 4292459438 4293445566 4292854459 4293248443 4293117371 4292920251 4292393909 4293839550 4292986045 4292657080 4293247928 4292854458 4293051581 4292919737 4292987328 4293448386 4292985788 4293380800 4293379516 4293381312 4292986044 4293051581 4293051067 4292989636 4293383107 4293317058 4293252293 4293582537 4293512896 4294301639 4292002237 4285471030 4285994566 4287703623 4287835977 4289282894 4290333267 4291454043 4292242024 4292572009 4292772207 4293427045 4292969085 4293231206 4293034364 4292839283 4293295733 4292642156 4293164935 4292444780 4292768638 4292242788 4291125857 4289480016 4287508044 4285665855 4284420422 4284814653 4284488256 4284615739 4284287285 4285074748 4286782793 4288821324 4289939794 4291386958 4292109923 4292636267 4292572761 4292510836 4292507502 4292964701 4292506205 4292833885 4292898160 4292442972 4293162354 4292706925 4293100137 4293098352 4289543242 4284025922 4284224068 4284353865 4284486972 4284288838 4284420925 4284747320 4285865803 4285406789 4285144394 4285406786 4285211722 4285471810 4284948299 4284554051 4284354878 4284684348 4285407305 4284751431 4284948041 4284224573 4284358475 4285209926 4285341769 4284683835 4284357962 4284094521 4284882008 4285342800 4287053150 4289620345 4291790467 4291593350 4291462277 4291129457 4290275697 4290278787 4291659643 4292185734 4292055432 4292055937 4292318592 4292384143 4292122752 4292317064 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288758608 4288624206 4289412171 4288628297 4288757326 4289348429 4289216336 4289083214 4289346634 4288626001 4289346381 4288556874 4289546317 4291256163 4291716430 4292964703 4292706673 4293232236 4293299059 4293037177 4293562994 4293234302 4293693309 4293430397 4293628037 4293168239 4293299321 4293623670 4292507758 4292242792 4291384144 4290333264 4288890204 4287310660 4287443016 4287838286 4288297037 4289216593 4288691785 4289217107 4289546066 4289480529 4289610580 4289610580 4289414741 4289217107 4289612114 4289349201 4290003796 4289740368 4289546579 4289610839 4290070088 4290333786 4290333009 4290139743 4291253843 4290532957 4291190624 4290597981 4290596685 4291188308 4291253338 4290073692 4290987858 4293771397 4293692788 4290658888 4289478220 4290396240 4290335579 4290136919 4289811293 4290403423 4289678170 4290270556 4290333271 4291255134 4290532182 4291318617 4290071384 4290730846 4290729568 4290666336 4291254874 4290471541 4291322199 4290206070 4291914596 4291452762 4291783548 4291717756 4291851372 4292249220 4291718231 4290404472 4290343793 4292178792 4290733675 4292379262 4291061883 4291916911 4291196546 4291061355 4291129715 4290012266 4290734444 4290994528 4290603640 4290139743 4290409086 4292259994 4292714126 4292854184 4292915110 4292522647 4292458153 4293245846 4292784556 4292523424 4292588197 4292524457 4292590256 4292521643 4292656543 4292589992 4292583578 4292064695 4292588722 4292723385 4292722616 4292525495 4293181878 4292657080 4293445566 4293445565 4292921534 4292852402 4293448901 4292722359 4292722872 4293051837 4293447104 4293051581 4293051580 4292986044 4293051837 4293051837 4293051837 4292919737 4292985530 4292985529 4292329917 4293117630 4292987584 4293317315 4293710018 4293580742 4293516489 4293582025 4293189576 4288766079 4288560201 4287046214 4287441482 4288822091 4289676880 4291779417 4292044369 4292573807 4292837742 4293035374 4292903531 4292902525 4292904814 4293034361 4292706938 4293099897 4292968311 4292510062 4292572008 4291914339 4291517793 4289217107 4288098635 4285996361 4284550205 4284420677 4285402683 4284484672 4284418363 4284811319 4285730366 4287047241 4289412939 4290790732 4291387736 4292043612 4292176746 4292703335 4292572759 4292503380 4292635479 4292963937 4292507468 4292508271 4292705393 4293032813 4293624701 4291451981 4285601344 4284026692 4284157502 4283961654 4284289350 4284420924 4284883787 4285537092 4285340995 4285207351 4285470784 4285145162 4285601850 4285276233 4284883017 4284354364 4284488516 4285015115 4285537866 4284883016 4284553804 4284160579 4284620101 4285406018 4285998153 4284488525 4284419906 4283567945 4284422214 4286725481 4289489286 4291659136 4291921798 4292051328 4291527027 4291132278 4290014581 4291397244 4291856503 4292055164 4292776842 4291990401 4292383612 4291989375 4292384144 4292122236 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288759117 4289413709 4288562001 4289216080 4289150800 4288625488 4288625488 4289022282 4288757582 4288755533 4288166737 4288691792 4289217365 4290661717 4291847767 4292573808 4293099628 4292969325 4293299060 4293495929 4293235058 4293693816 4292973176 4293233009 4293167478 4293693571 4293103229 4292837741 4292508512 4292242010 4291386717 4289940057 4288755531 4287376453 4287378520 4288556624 4288298064 4288624461 4289478483 4288953936 4289544268 4289217366 4289873746 4289151821 4289612121 4289546327 4289742945 4289807701 4289349206 4289546585 4289676372 4289742419 4291056229 4290335571 4290205535 4290791248 4291123286 4291185751 4290532180 4290664534 4290731104 4290140768 4290201942 4290136159 4291455078 4294037153 4292311126 4290132816 4289545815 4290529361 4290268257 4289284954 4290466138 4290269017 4290858071 4290729821 4290793300 4290663251 4290664286 4290598236 4291323745 4291125600 4291124058 4291124835 4291126118 4291124569 4291063423 4291190368 4290142836 4291390845 4291262319 4291852911 4292117111 4291322976 4290667901 4291456867 4291587449 4291192953 4291722357 4291258733 4291982701 4292049008 4290930791 4291388517 4291192942 4291324527 4290925141 4289744479 4289547879 4290611101 4292389794 4292971900 4292524207 4292654230 4292855493 4292915880 4292523432 4292520851 4292522648 4292522655 4292524716 4292788400 4292394145 4292719780 4292057236 4292589743 4292526265 4292590509 4292723129 4292523698 4292459701 4293247924 4292721330 4293379772 4292854202 4292854202 4293511101 4292722873 4293115573 4293118913 4292722615 4293313979 4292854202 4292985530 4293117373 4292986043 4292788408 4292788407 4292985530 4292594371 4292592318 4292594114 4293116860 4292988610 4293447360 4292990405 4292924613 4293644481 4293909705 4293845194 4294173645 4291483848 4288564822 4285861700 4287049543 4288754251 4290070873 4290995559 4292701547 4292505699 4292901739 4292706158 4292903534 4293099368 4292904062 4293427572 4292838530 4293232491 4292902776 4292640894 4292965227 4292242278 4291122778 4289480278 4287508808 4285929542 4285339704 4285076037 4284420671 4285207360 4284352820 4284418358 4284156213 4285793851 4287113292 4288889423 4289741894 4290662483 4291129974 4291531413 4291995050 4292520622 4291464597 4292110417 4292569440 4292382347 4293358179 4293232238 4292766033 4287046216 4283764035 4284355140 4284156989 4284554059 4284418876 4284552774 4285208123 4285144383 4285606224 4285406788 4285009722 4285603652 4285408075 4285078597 4284488002 4284685895 4285471302 4285145934 4285211726 4284288828 4284553794 4285210437 4285472587 4285867850 4284552764 4284553788 4283369798 4283763774 4285934680 4288568950 4291199106 4292314496 4291986045 4290740867 4290605939 4290474868 4291593849 4292185216 4292448391 4291987584 4292188029 4291988874 4292317569 4292383883 4291793783 4292382859 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289346384 4288759123 4288755786 4288757581 4289216336 4288234317 4289413200 4287970897 4288888909 4288757329 4288165194 4288689998 4289085261 4290728270 4292373610 4292507240 4293164383 4292969326 4293299060 4293431154 4293235067 4293430136 4293431159 4293627774 4293430647 4293430652 4293496447 4293231211 4292900192 4292043606 4291387228 4289873492 4288099670 4287377737 4288097349 4287772238 4288298065 4288624202 4289480272 4289348938 4289346897 4289283401 4289150031 4289873752 4289544786 4290071385 4290071384 4289348949 4289480278 4289742682 4290071905 4290007397 4289875544 4289808216 4290923606 4290141538 4290727249 4290535009 4291252825 4291189085 4290596953 4290794074 4290465366 4289741917 4294033303 4294295162 4291781220 4289346383 4290071384 4289349988 4290005590 4289940056 4290529364 4290203738 4290792535 4291254876 4290072154 4290664542 4291252560 4290597210 4291712865 4291058523 4290928505 4291123802 4290404445 4291454318 4291125855 4291061357 4291652462 4290864238 4292379776 4292110434 4290731626 4291391867 4291719773 4291063179 4291522926 4291326561 4290802549 4291786618 4291852418 4290934385 4291912545 4289358199 4291455341 4289808734 4289219944 4289551720 4291734176 4293243543 4292587172 4292457120 4292654489 4293242527 4292655516 4292457888 4292585628 4292587678 4292520601 4292787878 4292589993 4292586645 4292254611 4291667115 4292655014 4292657595 4293182392 4292851381 4293051320 4292657080 4292525237 4292655527 4292591545 4292525493 4293511359 4293051837 4293051838 4292853944 4292198587 4293117373 4293117374 4292854458 4293576894 4292593089 4292461501 4292129202 4292919993 4292395966 4293117373 4293117886 4293055685 4293052350 4293051324 4293051324 4292988353 4292987584 4293381568 4293315776 4293251780 4293516232 4293844938 4294305488 4292133810 4286123835 4286650951 4287771979 4289350228 4291518036 4291848804 4292637802 4292444785 4293099627 4293099371 4292706158 4292773232 4292902523 4293100911 4292836985 4293100153 4292642931 4292573291 4292110182 4291321693 4289546589 4287048522 4286062409 4284551991 4284483910 4284944952 4284682047 4284550210 4284681525 4284549431 4283959348 4284549437 4286915133 4288302443 4291603632 4293315521 4293449929 4293777865 4294564037 4292987842 4291926703 4292588218 4293054148 4292713353 4292571235 4288756046 4284814404 4283895110 4284418116 4284095292 4284684876 4284620103 4284683835 4285080656 4285863238 4285538116 4285274694 4284684866 4285474902 4284950359 4285604425 4284424011 4285209670 4284750398 4285012803 4284880970 4284552246 4284489804 4285342536 4285472073 4285340479 4284618308 4284290371 4283960394 4284685639 4287582582 4290999424 4291463031 4292117893 4290869363 4291129711 4290344836 4291327870 4291725181 4292119941 4291989882 4292448892 4291989898 4292382340 4292317053 4292316032 4292186485 4292316791 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288758608 4288301138 4289281872 4288691280 4288691280 4288756816 4288033613 4289609290 4288624206 4288755789 4288754507 4288755790 4288692041 4290793820 4291847775 4292703338 4292313460 4293232236 4293299066 4293430391 4293300606 4293037939 4293495933 4293169014 4293496183 4293233271 4293299316 4292968299 4292900972 4292178028 4291453278 4289350748 4289346379 4287376204 4287378765 4288950089 4288754507 4289282641 4288496464 4289543760 4288953935 4289544787 4289871954 4289217614 4289283156 4289217364 4289282899 4289546072 4289019465 4289677393 4289481059 4290204248 4289941083 4290465618 4290333529 4290202705 4290726226 4291253338 4290007902 4290730583 4291252056 4290858066 4289807188 4291713374 4294237096 4293830260 4291974498 4289018959 4290071127 4290007130 4289610837 4290070101 4290858584 4290859866 4289481305 4291254621 4290662746 4291252055 4290661464 4290006101 4290203480 4291387485 4290467931 4291256931 4291648614 4290863200 4291979630 4290929772 4291587938 4291520879 4290863208 4290869112 4291593323 4291983471 4291389554 4291981907 4290864244 4291195516 4291981933 4292049010 4291126886 4290398812 4289882748 4291584607 4289747556 4289088603 4290411400 4292582565 4292708978 4292522155 4292457381 4292917424 4292912012 4292522658 4292322710 4292981153 4292523945 4292588205 4292592567 4292255379 4292120977 4292579217 4292590005 4292587930 4292917428 4292852395 4293115057 4292657337 4292393132 4293050550 4292854716 4292392627 4293444533 4292788668 4292984237 4292986045 4292722616 4292985787 4292853944 4292985787 4292854200 4292919737 4292328115 4292656309 4292986814 4292987070 4292788151 4292985787 4293117373 4292463036 4293444795 4293054146 4292922303 4292985273 4293052351 4292988097 4293381825 4292989123 4292924357 4293975240 4293779402 4294305486 4293387214 4287116112 4286651204 4287968076 4289480017 4291124575 4292307559 4292637545 4292510321 4293099627 4292706413 4293099370 4292902524 4293100907 4292705899 4293100155 4292706153 4292968571 4292573547 4292109926 4291323489 4289347404 4287051599 4286125381 4284419909 4284617277 4284553798 4284549952 4285142074 4283762748 4283764019 4283369531 4283828018 4287784580 4293251273 4293516482 4293646270 4294105032 4293180837 4292459448 4292722102 4293383364 4293973444 4294300611 4293844430 4291139482 4284942132 4283565129 4283699528 4284226630 4284353603 4284491593 4284419899 4284815945 4285539914 4284750144 4285538380 4284619847 4285406280 4285013571 4285801805 4285144644 4284161096 4285865797 4284884045 4284879670 4284682814 4284554052 4284948299 4285276743 4284945218 4284550980 4283893827 4284619852 4285145925 4287842417 4290014851 4291659394 4292118392 4291788670 4291066483 4290933119 4290936949 4292119421 4291988611 4292120968 4292383889 4291989115 4292446848 4291859833 4291987575 4292383620 4291989116 4292317063 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288295500 4288298832 4288756816 4288168016 4288756816 4288758864 4288757072 4288298061 4288758864 4288166737 4288755531 4288034126 4289348938 4290793299 4291716183 4292047472 4293230168 4293166706 4293299058 4293628542 4293235315 4293495934 4293037949 4293495932 4293037437 4293496190 4293299310 4293033837 4292441693 4292437846 4291058007 4289939280 4288298065 4287508038 4286917191 4288491850 4288229707 4288692049 4289278794 4288494672 4289282899 4288953678 4289283413 4289346895 4289348693 4289414222 4288562258 4289150794 4289546851 4289217886 4289414484 4289546072 4289610837 4290135893 4289742936 4290991195 4290138203 4290663002 4291383890 4290072917 4290793299 4289807443 4289412175 4292515208 4294171287 4293431403 4290925402 4289347409 4289809250 4290333269 4289609554 4290466651 4290138202 4290792277 4291256672 4291124054 4290662490 4290203216 4290729820 4290596971 4290730844 4290534501 4291255388 4290466136 4290996590 4291979641 4291061093 4291455597 4292113548 4291522145 4291325298 4291453797 4292312193 4291392114 4290991707 4290800756 4291979882 4291919224 4291850080 4291320926 4289025632 4289882478 4291122779 4289679970 4289353583 4291855247 4292387221 4292652444 4292580498 4292457881 4293445556 4292850338 4292588192 4292185480 4292713367 4292124300 4292588978 4292592566 4292649881 4292124323 4292192921 4292787895 4292521359 4292983736 4292456096 4292722613 4292852395 4292459959 4293248701 4292392106 4293050030 4292657338 4292458925 4293050285 4292657081 4292393652 4293183158 4292986045 4292722614 4292788150 4292131254 4292262840 4293117374 4293051838 4293248186 4293446848 4292527552 4292590773 4292985787 4293117117 4293052863 4292528065 4293185218 4292329660 4293117886 4293054146 4292986558 4292987841 4293448386 4292858564 4293909704 4293450439 4293714382 4290086794 4285073212 4287508038 4289414223 4291058524 4291848036 4292114544 4292508525 4293099626 4292902781 4293231210 4293232492 4292837741 4293034619 4292904818 4292968058 4292838524 4292638827 4291718502 4291254369 4289483354 4287640396 4285665854 4284422213 4284617278 4284681024 4284617013 4283566902 4284092209 4282977361 4283106112 4288841626 4293843405 4294104261 4294038215 4293575593 4292258465 4292392634 4292462529 4293316288 4293907909 4293383878 4293777094 4293907653 4293252292 4284749892 4283434819 4283767113 4284092997 4284161355 4284487752 4284291145 4285341511 4285408587 4285539147 4285012805 4285737294 4285014602 4285012290 4284095560 4285275205 4285079628 4284620359 4285604682 4284489805 4284749372 4284226890 4286063167 4286065495 4285209925 4284027709 4283765312 4284221501 4286723940 4289422214 4291593598 4291723918 4291921268 4291264898 4290869631 4291000177 4292119423 4292120454 4292056952 4291860094 4292315764 4292383110 4292187513 4292054662 4292447617 4291987830 4292382855 4292316278 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288498782 4288298830 4288166224 4288757072 4288757072 4288624205 4289215053 4288625744 4289216336 4288689997 4288754251 4288690767 4289279819 4290267472 4292108894 4292636521 4292772466 4292969324 4293101181 4293628028 4293167224 4293430385 4293431409 4293430654 4293233008 4293430653 4293299317 4293361513 4292901217 4292176741 4291452253 4289217880 4288818760 4286850375 4287572807 4287901769 4288428879 4288754251 4287970126 4289413965 4289151564 4289151058 4289546066 4289283151 4289283151 4289283151 4289807445 4289085515 4289676115 4289480272 4289611859 4289547867 4290071128 4289283928 4290530648 4289808472 4290202193 4290794331 4290136145 4290794588 4290659666 4289479765 4289872990 4294364576 4293835912 4293491047 4290924881 4289545302 4290069842 4289872978 4291121497 4289808983 4291448918 4289548647 4291382613 4290532701 4290598749 4291189085 4291189590 4290532442 4291255644 4290993005 4290535275 4291124575 4290994274 4291455338 4291519850 4291060064 4291524211 4292438900 4290929515 4291130488 4291584346 4290927712 4290933111 4291982190 4292114535 4291914084 4290469479 4290076273 4290535518 4289807195 4289152092 4290080385 4291924870 4292383881 4292645265 4292523169 4292523683 4292977034 4292458660 4292646026 4292060821 4292718240 4292058523 4292456092 4292717199 4292252292 4292191906 4292590250 4292982702 4292587930 4292587432 4291995536 4292589217 4292524977 4292524977 4292523422 4292917931 4292526008 4292456104 4293051058 4292131514 4292591030 4292525493 4292788666 4292525493 4292786092 4292195765 4291934652 4292788150 4292788408 4293511358 4292986045 4292658618 4293248186 4293053120 4293117374 4292722615 4292985788 4293051581 4293052863 4293052606 4293183678 4292530117 4293051067 4293118399 4293052350 4292989636 4292989123 4293644996 4293910987 4293779145 4292267984 4286651715 4286983240 4288560208 4290793563 4292045407 4292503399 4292575855 4292771694 4292969068 4292903277 4292904822 4293033577 4293164918 4293231739 4292903528 4292640893 4292638827 4292438887 4290073941 4289676882 4286982470 4285799238 4284550968 4284354117 4284288820 4283370549 4283699001 4282712131 4284358478 4289963446 4293646266 4294105803 4293643196 4292585098 4292128438 4292988356 4292989379 4293977549 4293842629 4294107595 4294108621 4294042829 4294107082 4294635220 4287065477 4282778435 4283896887 4284093253 4284224841 4284290370 4284947784 4285737551 4285405760 4284685641 4285076795 4285211464 4285802062 4285144390 4285144386 4284227147 4285011255 4285407306 4285275461 4284292165 4285341766 4284488517 4285931337 4284227146 4284554059 4284354371 4283631940 4285929804 4288764516 4290675074 4292315783 4291920255 4291395189 4291391100 4290804609 4291395973 4292119157 4291990153 4292842377 4291990415 4292384137 4292055689 4291593854 4292448388 4291988604 4292053633 4292054397 4292382081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288297294 4288232016 4288757072 4288691279 4288625744 4289413965 4289217102 4289217101 4289217101 4289151056 4288626257 4288622152 4289217866 4291319133 4291848030 4292638303 4292835420 4293428332 4293036140 4293627775 4293628278 4293366398 4293167223 4293430398 4293628022 4293234821 4293101678 4293428589 4292507229 4291846484 4291190360 4290070095 4288164169 4287506503 4287573831 4288098634 4287182159 4288820043 4289216593 4288953936 4289412688 4289546323 4289412940 4289676367 4289610575 4289610580 4289217620 4289283157 4289808215 4289151828 4289610579 4289676374 4290005592 4290660693 4290399577 4289677401 4291384149 4290662747 4290139743 4290792272 4290926172 4289018959 4291780698 4294435506 4293635962 4293500024 4291910241 4289479509 4289413715 4290071641 4289545557 4290400603 4290793813 4290398032 4289483102 4291189846 4291513684 4291123548 4290466908 4291453278 4290008417 4291257438 4291122005 4290799993 4291585635 4291190372 4291456370 4292175970 4291123805 4290998387 4291783770 4289482070 4289682558 4291721065 4292045419 4292113257 4291126376 4290402652 4291261556 4290861658 4289807966 4289088090 4290934911 4292648077 4292714909 4292582809 4292521630 4293309857 4292450186 4292578947 4292583574 4292128928 4292124315 4292192667 4292784032 4292252289 4291727763 4292254619 4292655003 4292587422 4292588448 4292061350 4292588699 4292590517 4292520873 4292722869 4292721584 4292524462 4292460216 4292984243 4292526008 4292850082 4292985002 4292195755 4292590263 4292588960 4292194485 4292130229 4292722871 4293379772 4292722872 4292986044 4292657079 4293445565 4293051838 4292722872 4292984757 4292985788 4293183167 4292656557 4292985788 4293117116 4292527039 4292921023 4293182652 4293117373 4292395452 4292592831 4293051067 4293052094 4292990405 4293582024 4293976523 4292797126 4289301149 4285927995 4288754763 4290859854 4292242010 4292703337 4292315014 4292968810 4292903276 4293231207 4292968572 4292839278 4292968826 4293230951 4293100155 4292903805 4292182632 4291912803 4290794844 4289348431 4287838031 4285140022 4283961909 4283567667 4283700029 4283239749 4282974263 4285613674 4292197573 4293581762 4294235853 4293378212 4291530116 4291345093 4293515205 4293579973 4293907653 4293777350 4294105030 4294104773 4294040520 4294041802 4294042572 4294437328 4291672506 4282384963 4283306835 4283832401 4283897406 4284355907 4284554051 4284291138 4285998153 4284815424 4285867337 4285535551 4284095816 4284552259 4284421188 4284683835 4284816971 4285078594 4284157767 4284226370 4284750920 4285605707 4284749890 4285734210 4284356933 4284288838 4285145936 4287581547 4290868112 4291462018 4292642674 4291330693 4290804611 4291002741 4291462007 4291791231 4292384395 4292382339 4291923579 4292448890 4291987583 4292054913 4292448133 4291989385 4292382597 4292448381 4292053368 4292053624 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288756816 4288757069 4288625743 4288823123 4289413964 4288430672 4289217100 4289348695 4289414474 4289017933 4289085520 4289083982 4288954190 4290794062 4291715683 4292634968 4292378724 4293165163 4293496705 4292972141 4293236351 4293563255 4293694584 4292842602 4293430143 4293233265 4293101936 4293165675 4292507760 4292636263 4291646038 4289216332 4288296268 4287506247 4287048519 4287442503 4288556102 4288231758 4288757581 4289480016 4288953679 4289217615 4289806155 4289349464 4289742417 4289807960 4289545038 4289545295 4289872718 4289742418 4289479509 4290267215 4289283929 4290399578 4289937993 4290922829 4290597725 4291187025 4290728787 4290204259 4290267990 4290263903 4291724674 4294302618 4293897075 4292834920 4291185234 4289152342 4290069331 4289019985 4290726485 4289810267 4290529365 4289677144 4291320412 4291125605 4290661207 4290598748 4291776862 4290533730 4291057752 4290006634 4290537328 4291387234 4291390321 4292309353 4291189335 4289876839 4291259505 4290597717 4288825690 4291193717 4292309864 4292112740 4291063920 4290928744 4291258474 4291454301 4290728794 4290268502 4290530661 4291133583 4292973696 4292579977 4292520595 4292980388 4292584858 4292451996 4293038210 4291661714 4292710272 4292056215 4292724154 4292714890 4291662999 4292651685 4292651154 4292588955 4292581004 4292585883 4292586393 4292589471 4292590522 4292586647 4292525484 4292981921 4292524970 4292587176 4292983466 4292460216 4292525237 4292526265 4292194224 4292261786 4292585636 4292128685 4292460214 4293839034 4292459958 4293510841 4293117114 4292722872 4292985787 4292920251 4292984243 4292854201 4292264381 4292656557 4292919737 4292132537 4292722101 4292593088 4293118655 4293182652 4292330173 4293182652 4292592575 4292593857 4293054402 4293051323 4292462016 4293317572 4293911244 4293844681 4292663248 4288496469 4287967560 4290201675 4291583842 4292309864 4292572264 4292578682 4293297277 4292968073 4293362790 4293166705 4292970109 4292903275 4292771692 4292444527 4293096301 4291455079 4291059808 4289413708 4286126918 4284483892 4283371325 4283371334 4283172414 4282844217 4288179348 4292729549 4293711046 4293973167 4292389521 4291200918 4292593860 4293055428 4293973189 4293841346 4293448901 4293841090 4293842117 4293382594 4294104261 4294103491 4293976010 4294372042 4293648852 4283961675 4283372103 4283830592 4283830591 4284420682 4285144643 4284883017 4284686152 4285539147 4285472591 4284421691 4285603659 4284225596 4285603396 4285670222 4284881987 4284550724 4284226622 4284357961 4285406279 4285143879 4285407304 4284424267 4284419655 4284621907 4287379035 4289622647 4290935935 4292315782 4291593348 4291460725 4290997871 4291264385 4291595395 4292447616 4292381565 4291923594 4292382597 4291989131 4292448891 4291988358 4292382587 4292381823 4292054396 4291660158 4292448383 4292053633 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288824658 4288625487 4289479507 4288561743 4289019472 4289478223 4289281360 4289742159 4288888144 4289412944 4289018189 4288952910 4289807176 4290137949 4291583057 4292638577 4292836959 4293362796 4293233267 4293628287 4293170036 4293628784 4293170052 4293431421 4293628534 4293364857 4293495405 4293361514 4292506972 4292176470 4291056966 4289741648 4288229448 4287444045 4287574346 4287443274 4287966022 4288232529 4288625741 4289282130 4289348949 4289806161 4289742680 4289545044 4289740619 4289283666 4289938255 4289872975 4290068307 4289873484 4289806926 4289940315 4290069584 4290333011 4290335581 4290202194 4290662227 4291122267 4290731103 4290272615 4290069586 4289346384 4294296213 4294168726 4293502093 4292832848 4290202713 4289347408 4289217362 4289547109 4290530647 4290004565 4290923346 4290138203 4291253843 4290731874 4290135115 4290137177 4291455586 4290659148 4289879148 4292109922 4291717477 4291455339 4291258216 4290467424 4290603899 4291387231 4290072670 4290011765 4291191398 4292113782 4291586923 4291453280 4290929257 4291521883 4290728538 4289679451 4289940311 4288758611 4291333012 4292908935 4292586145 4292515987 4292982179 4292517530 4292055705 4292711303 4292122773 4292120971 4292058528 4292719522 4292117883 4292055442 4292653474 4292588703 4292588193 4292650898 4292058266 4292581267 4292526261 4292915374 4292526523 4292588195 4292652455 4292129435 4292653219 4292197814 4292520102 4292786846 4292789440 4292852134 4292060570 4292585906 4292592569 4292983481 4293443757 4292262837 4293248442 4292328373 4292852137 4292985786 4293117114 4292788408 4292591287 4292986036 4292853945 4292919738 4292262583 4292592830 4292853944 4292985530 4293116860 4292528835 4293182652 4292528322 4293185474 4293118142 4293052607 4293116860 4293052350 4292989635 4293250497 4293712327 4293778119 4290490297 4287832891 4290332236 4291453270 4292767849 4292508785 4292642676 4292838269 4293166957 4293363820 4293100156 4293364080 4293231487 4292773231 4292968814 4292178017 4291848803 4290333266 4288365903 4286781504 4284026420 4283305019 4282909757 4283765566 4289501106 4293841863 4293973703 4293446838 4291793795 4290220967 4292527551 4293317316 4294366405 4293448386 4293578948 4293642941 4293120963 4293580230 4293643455 4293772213 4293382851 4294040520 4294306507 4293845708 4286069342 4282977615 4283765063 4284617544 4284817477 4284552003 4284488259 4285209148 4285013319 4285274429 4285210441 4284617020 4284488774 4285274429 4284222525 4284222784 4284223300 4284949322 4285078083 4284752715 4286195275 4284750918 4284816974 4283898175 4286454858 4288503158 4291000716 4292578695 4291987063 4291723134 4291262335 4291264641 4291659143 4292448388 4292317052 4291923590 4292777341 4292250487 4292382838 4291989126 4292384123 4291988358 4292383621 4292381824 4292120702 4291858293 4292381825 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288627280 4289216080 4288102988 4289150288 4289217100 4289151058 4289348687 4289085517 4289742159 4289085523 4289414736 4288952397 4289086550 4290858072 4291321687 4292505690 4292837217 4293099628 4293430645 4293564280 4293628535 4293170047 4293694324 4293627262 4293169530 4293628543 4293166955 4293427048 4292442224 4292635996 4291057504 4289939799 4288230219 4287441991 4287508039 4288097863 4287115852 4289346381 4289150800 4288693587 4289282894 4289677909 4289545044 4289545038 4289742418 4290070606 4289807189 4289676882 4289677132 4289611347 4290135377 4290332496 4290004818 4290333773 4290267736 4290139999 4291186508 4291121490 4290662234 4290337886 4290202474 4290069583 4294167464 4293770886 4294159207 4292638067 4290067274 4289543503 4289151827 4289939540 4289415000 4289939799 4290269531 4290859610 4290927455 4290067530 4288888914 4290929762 4290071394 4290535017 4292305769 4290864233 4290994531 4291848805 4290469475 4290733931 4290792020 4290074721 4290536042 4292703595 4291658604 4291321444 4290925663 4291126365 4291651693 4290599004 4290204763 4290595934 4289744485 4292250517 4292776595 4292518302 4292581517 4292589474 4292121229 4292644479 4292318341 4292252038 4292121499 4292719007 4292648079 4292121215 4292456366 4292586910 4292975753 4292588183 4292585361 4292192156 4292650647 4292523442 4292912774 4292724410 4292586133 4292657333 4292063390 4292652204 4292586648 4292587171 4292591788 4292063668 4292254594 4292059296 4292589493 4292985527 4293576634 4292984757 4292525233 4292983472 4292591545 4293116856 4292130995 4292454812 4292985267 4292986045 4292854201 4292591030 4292986045 4292853944 4292658626 4292461244 4292985530 4292593089 4293118656 4293182910 4292985530 4292986813 4292787638 4292658623 4292658367 4292396735 4293118399 4292526526 4293053633 4292988866 4293450439 4293189840 4289027441 4289476682 4291059289 4292375651 4292508784 4292969069 4293428585 4293165162 4292969332 4293166956 4293099626 4293035116 4292838771 4292508527 4292770927 4291125857 4290595662 4288692813 4285009466 4283107382 4282515518 4285282137 4290686396 4293582542 4294301635 4292525209 4291461498 4290814386 4293053635 4293318854 4293973189 4293448890 4293642946 4293249470 4293315520 4293774015 4293117884 4292788409 4292919740 4293579715 4294103235 4294043086 4294370769 4286599264 4282910795 4283764292 4284158283 4284485961 4284554050 4284685638 4284947012 4285537604 4285212241 4284814646 4284683071 4285274429 4285011523 4284812861 4284221765 4284422717 4285078341 4284683062 4285997129 4284554308 4284817231 4284354374 4284947008 4287579494 4290671246 4292447362 4291921799 4291855475 4291788927 4290871156 4291528059 4292119422 4292317061 4292250496 4292710271 4292250743 4292316546 4292183930 4291989381 4292775810 4291987830 4292053633 4292382080 4292053633 4292053367 4292448128 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289282637 4289151059 4289479760 4289348943 4289151058 4289348692 4289480274 4289283151 4289412946 4289283151 4289544275 4289086285 4289740364 4290663765 4292307296 4292373589 4292770148 4293362796 4293234286 4293234806 4293629559 4293694063 4292842889 4293236333 4293694330 4293169519 4293692280 4292969583 4292901474 4291979623 4291124039 4289283160 4288165454 4287441990 4287378509 4287836233 4288885835 4289084238 4289085264 4289151052 4289937491 4288954193 4289545294 4290003797 4289479252 4290006357 4290002770 4289807183 4290002764 4290135633 4290005850 4289415770 4290595152 4290203476 4290858584 4290727000 4291252057 4290533215 4291385684 4289872981 4289740360 4290990425 4294435246 4293836680 4293564021 4293167453 4290070360 4289018957 4290071641 4290201686 4289349208 4290466651 4290529364 4290596441 4288560460 4289613412 4291449945 4291124574 4291125856 4291125086 4291060318 4291978597 4290992473 4290864757 4291256667 4290071131 4290470781 4291192422 4291322485 4291980650 4290733168 4290339170 4291586411 4291718252 4291127146 4290271073 4290266193 4289944420 4292385172 4292906617 4292513408 4292977808 4292519831 4292645255 4292646539 4292251008 4291920786 4292714133 4292719265 4292118407 4292122771 4292979625 4292456594 4292980897 4292518297 4292058264 4292581793 4292586654 4292589746 4292588956 4292522161 4292585365 4292130741 4292061599 4292721588 4292587681 4292591021 4292585377 4292649118 4292647812 4292194493 4292592051 4292917170 4292654502 4292591545 4292591543 4292985013 4292982199 4292655262 4292591803 4293116085 4292721849 4292389791 4293182388 4292788667 4292854201 4292854193 4292788403 4293183151 4293118915 4292987842 4292984496 4292854202 4292524202 4291935935 4292526781 4292658624 4292593087 4293051065 4292658623 4293051580 4293052863 4293052350 4293053632 4292990149 4293646277 4292003019 4289354358 4291056972 4292437350 4292575585 4292771953 4292640366 4292969584 4293364078 4293297003 4293362795 4292969582 4292837233 4292181335 4292505449 4291253332 4288628554 4288360010 4283565621 4283633992 4287653511 4292069580 4294302666 4293907124 4292720029 4290872983 4291212734 4293118398 4293711044 4293905600 4293513408 4293643970 4293251257 4293445310 4292262066 4292919994 4292986045 4293313980 4293710529 4293055685 4294105030 4294107338 4294307029 4286793043 4282844746 4284157252 4284553798 4284226368 4284687183 4285210180 4284947783 4285010225 4284224319 4284483904 4284681534 4285079110 4284747581 4284355659 4284618308 4284618813 4284948036 4285603397 4285144647 4283831876 4284222523 4283701832 4286851170 4289553523 4292118158 4291987590 4292117630 4291526796 4291196541 4291330180 4292578942 4291990155 4292710015 4292121203 4292645511 4292250753 4292382839 4291988096 4292448390 4291987820 4292448648 4292053623 4291988088 4292447872 4291988871 4292644735 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289151053 4289348687 4289085517 4289544275 4289480530 4289217364 4289873490 4289152079 4289808211 4289676362 4289217866 4289674833 4289413705 4290728541 4291385942 4293031795 4292769889 4293166958 4293298811 4293301357 4293235588 4293169788 4293694843 4293628537 4293170542 4293629044 4293167476 4293559916 4292706398 4292963434 4291056469 4290005845 4289213770 4287181645 4288557129 4288361033 4288166993 4289214797 4288691795 4289414479 4289545038 4290005592 4289872719 4289415252 4289874257 4290002514 4290266702 4290070610 4290070865 4289938774 4289940045 4290398547 4290858068 4290792013 4290203734 4290138192 4290072143 4291254357 4290006619 4290990167 4289608547 4292243292 4294303406 4293771146 4293825897 4291583838 4290794331 4289609296 4290071898 4289609039 4290203225 4289874264 4290267479 4288361801 4289810026 4290862173 4290534495 4291120983 4291190622 4291192679 4291321436 4291256418 4291715434 4291122004 4290536313 4290866021 4291123288 4290928230 4291913835 4291389805 4291262851 4292508024 4291390064 4291914594 4290529877 4288887116 4290340214 4291984761 4292709238 4292519332 4292580490 4292578945 4292709500 4291922329 4292118662 4292320395 4292191912 4292118396 4292249462 4292056467 4293309865 4292454296 4292977822 4292520861 4292585881 4292056730 4292588952 4292587926 4292589475 4292586404 4292587676 4292587429 4292125069 4292720821 4292060312 4292656308 4292649110 4292318348 4291270320 4292650646 4292592053 4292521112 4292523166 4292851115 4293181106 4292985014 4292591535 4292986040 4292850357 4292915876 4292459958 4292722863 4292723130 4292392371 4292853673 4292986045 4292591031 4292722867 4292457125 4292985520 4292254608 4291409336 4292788151 4292525237 4292919737 4292985530 4293182909 4293248445 4292198330 4292658624 4293117372 4293117116 4292592831 4292592574 4293119169 4292989123 4293383364 4291809741 4291135649 4292239179 4292508004 4293099100 4293231470 4293164635 4293297261 4293165419 4292772207 4293296748 4292836702 4292706166 4291913047 4290204240 4289541189 4285339196 4286858342 4290291638 4293843148 4294040009 4293180585 4291666840 4291336865 4292133826 4293578946 4293973702 4293513408 4293644225 4293183935 4293313980 4293379774 4292722616 4292788408 4293117374 4292854202 4293248188 4293579715 4293841861 4294039237 4294107595 4293846992 4286202461 4282909254 4283568465 4284357696 4284816718 4285080137 4285080910 4285342280 4284815430 4284880184 4285469237 4285008708 4284681528 4284354110 4285011519 4284553276 4285931083 4284881475 4284553534 4285272381 4283893823 4283369020 4285012291 4288169834 4291068814 4292119673 4291724168 4292247673 4291131261 4291329905 4292185216 4291989382 4292382324 4292252290 4292316033 4292251518 4292381815 4291595390 4292447615 4291989381 4292120967 4292053375 4292053890 4292446331 4291396990 4292447862 4292251008 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289151058 4289480537 4289873484 4289217353 4289807948 4290003797 4289676875 4289936464 4290004041 4289084753 4289937998 4289346122 4289611342 4290989651 4291848544 4292439896 4292378467 4293428075 4293299064 4293235076 4293628021 4293694333 4292842874 4293629303 4293564548 4293562232 4293629562 4293231210 4293164147 4292308824 4291058265 4290069830 4289082956 4287836233 4287770697 4288884553 4288756814 4288562257 4289480009 4289019731 4290070866 4289218130 4290264651 4290006100 4290136151 4289480017 4290070360 4290465872 4290070361 4289741640 4290070611 4290595415 4290136665 4290859350 4290138204 4291251800 4291189856 4291120978 4291320152 4289938773 4289411148 4292842880 4294168983 4294166917 4293032301 4292108620 4290397782 4289281874 4288954187 4289676373 4289676630 4290069842 4289018958 4290467176 4290795354 4291520095 4291119701 4291128171 4291185998 4291254106 4291259486 4291190365 4290003538 4290536549 4291320173 4291190641 4290930281 4292304993 4291325806 4291652204 4291124314 4291125084 4291455077 4290071124 4288558152 4290472831 4292908930 4292711296 4292312445 4293169782 4292584857 4292311431 4291591533 4292249476 4292322202 4292783007 4291986050 4291724923 4292649630 4292583579 4292910214 4292522403 4292518039 4292581524 4292588712 4292588454 4292583319 4292584092 4292587410 4292588975 4292586906 4292651417 4292063410 4292583316 4292656557 4292122768 4291989899 4291927458 4293045899 4292525230 4292588967 4292981424 4292586392 4292587932 4292459178 4293047726 4292460216 4292525237 4292723129 4292460215 4292788408 4292459445 4292722615 4292920251 4292392370 4292986045 4293051839 4292198833 4292448906 4291594371 4291738817 4293248437 4292854201 4292264380 4292656565 4293182910 4292198586 4292461502 4292919480 4292919479 4292395965 4292658624 4293116858 4292461501 4292394939 4293120964 4292989379 4293644995 4293516490 4291529626 4292504132 4293163362 4292640883 4293164891 4293295980 4293165677 4293624425 4292969330 4292115803 4292375125 4291714905 4289676113 4287837017 4289364622 4292200905 4294304196 4293378990 4292261026 4291733912 4291603364 4292593092 4293514948 4293249728 4293579972 4293707708 4292919998 4293839285 4292854204 4293117365 4292591029 4292985787 4292919738 4292985789 4293710529 4293120707 4293448645 4294105030 4294106313 4293912005 4286196554 4283305534 4283766856 4284357443 4284423496 4284882248 4285341255 4285344075 4284618043 4284882507 4284355910 4284880951 4285144125 4284548932 4284620623 4284949069 4285996098 4285474126 4285077815 4283762504 4283173169 4283435078 4286854761 4290737525 4292182151 4292250503 4292183421 4291131005 4291788159 4291790214 4292382852 4292317060 4292252036 4292317834 4292316287 4292316279 4292316545 4292447616 4291988096 4292447873 4292052333 4292382338 4292053623 4292054136 4292119681 4292053889 4292380290 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289480273 4289217358 4289807954 4289414745 4289610318 4289283666 4289546325 4289612117 4289151823 4290069584 4288954445 4289872462 4289217098 4291513426 4291912279 4292570973 4293165423 4293166701 4292971385 4293234301 4293629047 4293169780 4293629303 4293562226 4293563006 4293564011 4293562234 4293494379 4292771678 4291980898 4291386719 4289806409 4289082956 4287769670 4288492621 4288295500 4288165454 4289215054 4289151566 4289544268 4289283660 4289805905 4289218392 4290201169 4289871441 4290791505 4289547092 4289940052 4290070604 4290002766 4289807178 4289938513 4290861146 4290135886 4290858317 4290729559 4290594630 4291188566 4290664543 4290202196 4289541207 4293967265 4294103974 4294031226 4292703328 4291253847 4289744988 4289741389 4289544274 4289019728 4289348949 4289941596 4290858584 4291319386 4290727255 4291120471 4290664534 4290656842 4289088860 4290798952 4290661717 4290068579 4291061868 4291845986 4290929507 4291518814 4291322212 4291061866 4291715680 4290007898 4290076263 4291324268 4289810263 4288954213 4290669683 4292119160 4292249219 4292579972 4292712844 4291457644 4292444013 4292185739 4292114806 4291596424 4292057980 4291393414 4292513939 4292980377 4292518308 4292581013 4292515481 4292581515 4292586910 4292588984 4292190092 4292984243 4292190873 4292713624 4292059025 4292060077 4292653469 4292190887 4292718745 4292587681 4292579984 4291595405 4292128166 4292653219 4292521876 4292584600 4292195748 4292588461 4292195758 4292192664 4292588709 4292524728 4292785822 4292525233 4292524975 4292981669 4292459958 4293051837 4292459444 4292459444 4292854460 4292854451 4292983981 4292450970 4290940049 4291931824 4292721318 4292722608 4292854202 4292919480 4292461759 4292985786 4292656565 4292985787 4292985787 4292461759 4292985015 4292197816 4292198073 4292787893 4292658625 4292986299 4293117886 4292465093 4293449927 4292988606 4292835181 4292705888 4293230427 4293165681 4293362523 4292640097 4292771168 4292444002 4292637277 4292504676 4290859862 4289623167 4291869636 4294105545 4293974211 4292984227 4291538596 4292326818 4292391599 4292463043 4293447874 4293709505 4293250498 4293379517 4292854195 4293051830 4292919997 4292788401 4292788409 4292985787 4292919994 4293184189 4293313723 4293186756 4293906882 4294169797 4294038212 4294237897 4293189590 4284354109 4283439690 4284089922 4284290370 4284422217 4284552259 4285078082 4284819025 4285014860 4285210694 4285274429 4284879949 4284748343 4284489285 4285734468 4284617526 4285472325 4285077052 4285208640 4283828274 4283303485 4285406027 4289290875 4291392906 4292120445 4292316039 4291460746 4291264638 4291199106 4292448126 4292317061 4292250494 4292776580 4291987582 4291988096 4292316545 4292382080 4291659905 4292118138 4292053632 4292053889 4292382336 4291988353 4292248452 4292052602 4292119672 4291725697 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289611865 4289480279 4289348945 4289414481 4289743957 4290068043 4290070101 4289349195 4289610581 4289938511 4289610838 4289216589 4290462291 4290924110 4292699482 4292898656 4292705887 4292969583 4293494897 4293628536 4293169272 4293629303 4293565829 4293563499 4293563768 4293563001 4293562233 4293428586 4292968046 4292505967 4291320652 4290596183 4289082699 4287770698 4287770697 4288361036 4288756046 4289147722 4289217357 4289217622 4290333016 4289481044 4289742417 4289806932 4289807188 4290006100 4289609291 4290136153 4290135628 4289675341 4289348682 4290790735 4290924372 4290268238 4290136923 4290204504 4290727763 4290730335 4290923089 4289741396 4288819786 4294495386 4294102677 4293633916 4292239950 4290729559 4291975001 4289283929 4289019728 4289873495 4289612376 4290136148 4291384153 4290661205 4289478482 4291122265 4290068306 4289547867 4292042596 4290533467 4290666091 4291257695 4290992473 4291125362 4291649121 4291455084 4291520121 4291715165 4290466653 4290732902 4290796647 4290925912 4289086557 4290932869 4293233262 4292449174 4292577153 4292711041 4292119933 4292115066 4291457910 4291720039 4292717493 4291262831 4291061880 4292449155 4292581264 4292517786 4292583321 4292517273 4292913301 4292521633 4292583823 4292714903 4292061858 4292645764 4292127903 4292060828 4292647574 4292652700 4292582816 4292655265 4292127660 4292381053 4291331466 4292387222 4292656549 4292587429 4292587171 4292583833 4292587678 4292590507 4292589724 4292586412 4292980381 4292525489 4292523183 4292981166 4292525744 4292456112 4292918187 4292788666 4292986045 4292591031 4293052078 4292854464 4291593076 4291662489 4292262325 4292328613 4292654004 4292131512 4292524980 4293051836 4292722101 4292527295 4292723385 4292788409 4292986044 4292722101 4292329915 4292395451 4292263865 4292590772 4292853685 4291739839 4292984758 4293249471 4293052350 4293053893 4292977564 4292702806 4293428848 4292837213 4292968819 4293163103 4292443232 4292574320 4292243039 4291523712 4291737539 4293252810 4293974457 4293510049 4292194465 4292195490 4292715934 4291739071 4293118657 4293840834 4293514163 4292921024 4293445308 4292919995 4292722617 4293511350 4292722617 4292985780 4292788409 4292919995 4293051837 4293313723 4293252293 4293644224 4293513666 4293776325 4294039750 4294236874 4293511604 4282318914 4283567695 4284490827 4284686411 4284816709 4284554051 4284749895 4284488258 4285078850 4285012805 4284878643 4284549433 4284421183 4284616510 4284291908 4285668165 4284815939 4285079373 4284223299 4283565892 4284157255 4287643236 4291063411 4291987845 4292316039 4291723390 4291788669 4291330434 4292315527 4292251525 4292317569 4292382587 4291923594 4292384380 4292316280 4292316280 4292382840 4292053623 4292447872 4292055174 4292447872 4291986810 4292447863 4291988353 4292119937 4292052603 4292118395 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289480278 4289151571 4290202708 4289742162 4289742161 4289349458 4289349201 4289610581 4289808215 4289347660 4289740878 4289938250 4289612374 4291778385 4291780698 4292899424 4293099099 4292903279 4293298028 4293235318 4293628024 4293563768 4293564784 4293564799 4293563261 4293564535 4293564287 4293495150 4292705886 4292768092 4290992217 4290071110 4288558412 4287770698 4289015367 4288164172 4288757329 4288562256 4289019473 4289283144 4289740626 4289545045 4289937998 4290006866 4289676625 4289611352 4289807183 4290070862 4289676882 4289479765 4290068307 4290070098 4289414225 4290268501 4291447885 4290071130 4291384403 4290201426 4289940314 4289216080 4290133066 4294369464 4293771655 4293560433 4291979870 4292176734 4290404194 4290530135 4289415257 4289413202 4290530647 4290399834 4290329673 4289481559 4290070100 4288952654 4290993498 4291383378 4290469736 4291387487 4290267220 4290532186 4292044133 4291452532 4292111721 4291060319 4290595923 4289942875 4291060854 4291319126 4290206565 4289544785 4290410113 4292570724 4291857035 4292642936 4292711811 4291589741 4292116350 4292050297 4292317326 4291856264 4290534990 4291722370 4292119959 4292645250 4292974978 4292515994 4292582027 4292520605 4292979352 4292649363 4292124053 4291729302 4292777857 4292059548 4292252575 4292589992 4292588723 4292187537 4292653976 4292712842 4292120457 4291730087 4292785558 4292586921 4292580488 4292588703 4292589226 4292585628 4292587668 4292059547 4292713612 4292198314 4292587934 4292583062 4292585873 4292525741 4292522930 4292983480 4292457900 4292854975 4292986293 4293052866 4292258473 4291794574 4291864228 4292392874 4292720295 4292129201 4292263598 4292919737 4292395701 4292198330 4292263865 4292394169 4292523441 4293051829 4292459445 4292788408 4292395709 4292985273 4292198329 4292264122 4292195765 4292985272 4291869884 4291869627 4292724161 4293184193 4292789691 4292966227 4293361515 4293165938 4293032519 4292836466 4292505430 4292638309 4292256436 4292857796 4293909696 4293249204 4292652947 4291803821 4292786085 4291601835 4292462017 4293118399 4293841346 4292988354 4292985533 4293511101 4292919995 4292788408 4292986044 4292722617 4292985787 4292985787 4292722873 4293248442 4292985788 4293316034 4293250496 4293186243 4293579973 4293841860 4294039239 4294304705 4290749846 4282581055 4284024906 4283831100 4284227659 4284816709 4284749382 4284749884 4284488260 4284816714 4285144900 4284487231 4284880191 4284225606 4284746551 4285472587 4284750403 4285797948 4284422978 4284158537 4285730371 4286065227 4290143113 4291592820 4291987848 4292051838 4292183681 4291264369 4291264643 4292382335 4292710773 4292317830 4291987582 4292317061 4292316287 4292316544 4292316544 4291987840 4292447873 4291988096 4292119158 4291659896 4292119680 4292053890 4292446577 4291461241 4292448130 4292382585 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289217107 4289677652 4289151573 4289545032 4289545302 4289740625 4289807954 4289349201 4289807959 4289150032 4289808456 4289348427 4290857552 4291383119 4292373076 4292833630 4292968833 4292641647 4293560428 4293169527 4293563249 4293563518 4293564024 4293565558 4293564797 4293564017 4293562994 4293429357 4293099886 4292439388 4291256930 4290660172 4289082700 4287769670 4287769671 4288886860 4288100941 4289348430 4289215306 4289283159 4289414737 4289414993 4289545045 4290266449 4289611346 4290397000 4290136403 4289611090 4289677138 4289872720 4290201157 4289545554 4290135378 4290398542 4290071631 4290857037 4290202453 4290596180 4289415255 4289018188 4291058528 4294435761 4294035856 4292444262 4293425771 4291517270 4291323490 4289477713 4290530904 4289940055 4289940836 4289675089 4289873236 4289742163 4289347406 4290666348 4289345613 4290337375 4291119443 4289150032 4290599516 4291126112 4290992732 4291126111 4290859869 4290593623 4290402929 4291585384 4291122519 4290140773 4289811818 4291985022 4292116582 4292115828 4292707697 4292249465 4292181617 4291723636 4291720298 4292317068 4292186759 4290204767 4291396487 4292448898 4292647840 4292645247 4291986306 4292449938 4292193705 4292651664 4292059564 4292120208 4292712083 4292123285 4292055713 4292709264 4292653728 4292979359 4292523424 4292654252 4292313741 4291723392 4292320918 4292262561 4292583311 4292583822 4292586153 4292056473 4292587929 4292588705 4292583835 4292651665 4292061601 4292450203 4292587164 4292654514 4292188053 4292583822 4292592316 4292525747 4292590506 4292586130 4292524456 4292649377 4291596944 4292128928 4292786362 4292263337 4292194721 4292786081 4292127121 4292129455 4292656302 4292654000 4292197048 4292656308 4292198844 4292589482 4292590768 4292588972 4292195752 4292656822 4292656308 4292329914 4292327094 4291802274 4292394171 4292000173 4292720306 4292527294 4292530633 4292443517 4292966744 4293033307 4292771696 4292442713 4292579726 4291803317 4293644743 4293513149 4292916380 4292653974 4292196782 4292125086 4292131258 4292988866 4293448386 4293379516 4292986045 4293117365 4292788408 4292133052 4292853936 4292788410 4292788409 4293117365 4292854459 4293117374 4292919986 4292986302 4293379772 4293250498 4293643969 4293971904 4293448901 4293777606 4294041033 4294631888 4289754228 4282515526 4283833423 4284230221 4284883533 4284489546 4284947784 4284488259 4285079108 4285274173 4284289854 4284485190 4284221758 4284420932 4284684862 4284881475 4285734214 4285473611 4284554055 4285669958 4286719052 4288630380 4291132286 4292116616 4292119172 4292509574 4291589754 4291657341 4291987336 4292316285 4292253067 4292316804 4292317061 4292775806 4291922303 4292316544 4292316544 4292382080 4291987830 4292316544 4292383111 4291922044 4291921544 4292119680 4292053891 4292118385 4292119682 4291723638 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289612116 4289807697 4289742417 4290070352 4289740620 4289808210 4289349201 4289545045 4289742423 4289808204 4289281870 4289807440 4290987597 4291253071 4292174684 4292900195 4292771163 4293233271 4293235571 4293628024 4293563512 4293566590 4293565303 4293564284 4293565313 4293565314 4293566084 4293626224 4292838255 4292964192 4291452751 4289479504 4288755784 4287837004 4287837004 4288361291 4288168017 4289282637 4289151566 4289478731 4289612380 4289806161 4289347403 4289481045 4289545045 4289872726 4289611346 4289938511 4289871184 4289872975 4289611096 4290071381 4289874254 4290007128 4291053648 4290859099 4289677390 4290399054 4289938261 4288886090 4292248949 4294302636 4293965176 4293497718 4292375902 4292109148 4291126370 4290397781 4290595414 4290070357 4290005335 4290400859 4291056987 4289219675 4290201684 4289545049 4290399576 4291450202 4289284183 4290928480 4291124317 4291452518 4291124574 4290532186 4291122775 4290930033 4291126888 4291059807 4291255900 4289940831 4291920001 4292446079 4292050555 4292512391 4292442745 4292246125 4291457661 4292378218 4292056988 4291654241 4290205286 4291593619 4292446093 4292446855 4292643186 4292186261 4292647061 4292712596 4292517525 4292190620 4292711562 4292123291 4292317830 4292252295 4292715930 4292128685 4291919991 4292457884 4292713367 4292319108 4291590536 4292318357 4292654744 4292583320 4292648868 4292190873 4292581259 4292587165 4292582041 4292584081 4292193189 4292581782 4292588968 4292585890 4292646537 4292192918 4292588975 4292586913 4292196263 4292648844 4292319891 4291725188 4292649111 4292192151 4292129443 4292721068 4292324238 4292126876 4292780958 4291735472 4292392120 4292260774 4292263097 4292195766 4292853423 4292722874 4292656821 4292194999 4292260005 4292655279 4292261296 4291932593 4292328889 4291999931 4292393143 4291931551 4292393387 4291866287 4291868588 4292328375 4292854201 4292390573 4292440676 4292966499 4292575361 4292589493 4292724410 4294038721 4292524449 4292457633 4292657326 4292652454 4292457128 4292789180 4293514171 4293315264 4293379517 4292986301 4292788408 4292788410 4292788408 4292985787 4292985789 4292985779 4292788408 4292854459 4293511358 4292919994 4292985788 4292985787 4292854459 4293313980 4293314750 4293120963 4294235333 4294103748 4294104773 4294240211 4286859362 4283703109 4283503946 4284424010 4284357702 4284752717 4284883015 4284685637 4285078083 4284684606 4284421183 4284417848 4284814398 4284883018 4285011011 4285406794 4284815423 4284950093 4286260049 4286260813 4287901793 4290012023 4291724427 4292117888 4292116088 4291592317 4291657597 4291987591 4292382077 4292318602 4292250493 4292316287 4292382596 4291923588 4292383626 4292316287 4292316544 4291988095 4292382854 4292776065 4291988086 4292119425 4292119681 4291920751 4292119673 4291921794 4291921792 4292118396 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289414737 4289414743 4289676887 4290200402 4289283660 4289414738 4289414739 4290003784 4289676882 4289938257 4289872970 4289937236 4290266701 4291318603 4292045159 4292964702 4292771954 4293102191 4293627770 4293562488 4293565298 4293562226 4293564535 4293566076 4293564283 4293566076 4293563253 4293432187 4293231213 4292507232 4291645008 4290071376 4288558155 4287770700 4288557129 4288297039 4288757578 4289480273 4288953936 4289281360 4289610825 4289349458 4289546582 4289939531 4289675085 4289677132 4289740627 4289479760 4289937485 4289479503 4289546837 4289413198 4290596437 4290070096 4290334037 4289677389 4290990165 4290462291 4288954956 4288426569 4293830791 4294170795 4293769848 4293627764 4292838249 4291981673 4291649367 4290729558 4289609299 4290071641 4289020494 4290464856 4290202456 4291251540 4290069862 4290929505 4289542992 4290074205 4291318873 4290594900 4291256670 4291124574 4290596182 4290534760 4291256435 4291126626 4291846501 4291188826 4289348958 4291392377 4292313200 4292575096 4291788426 4292382580 4292178795 4291651178 4291852146 4291858066 4291721063 4290206314 4291788672 4292446056 4292841614 4292251004 4292182668 4292647318 4292716946 4291526271 4291855233 4292513165 4292580745 4292252297 4292127656 4292646812 4292188296 4292717717 4292126368 4292181875 4291790715 4292118156 4292260503 4292649874 4292581774 4292649873 4292062113 4292649370 4292587423 4292580247 4292584335 4292585119 4292647307 4292586918 4292581269 4292259995 4292192172 4292585127 4292982698 4292522670 4292656035 4292318350 4291729563 4292129962 4292588961 4292586924 4292655017 4292193441 4291140773 4292453780 4292262832 4292326832 4292262834 4292719017 4292264637 4292721579 4291869119 4292655783 4292198063 4292718497 4292061602 4292654243 4292589742 4292785588 4292128937 4292392368 4292064941 4291341491 4292521890 4292132288 4291932319 4291867321 4292328362 4292397766 4292970887 4292385700 4292855480 4293842121 4293182882 4291798419 4292784281 4292522397 4292981937 4293248949 4293380289 4293380030 4293313981 4293379773 4292986293 4292919995 4292788410 4292986027 4292788410 4292985787 4292788408 4293116856 4293051838 4293445565 4292854202 4292985787 4292986037 4292788402 4292919987 4293381056 4292922561 4293644224 4293842117 4293711814 4294172106 4294108871 4285671493 4282910799 4284292932 4284489286 4284947016 4285080907 4284880199 4284424010 4285080652 4284749885 4284291141 4284419647 4284748606 4285013060 4285009476 4284947008 4285277012 4285274439 4285867853 4287048789 4288962679 4291655803 4292182924 4291920494 4291526798 4291131003 4291920255 4291921543 4292317316 4292252036 4292711045 4292250750 4291923077 4292382596 4292381822 4291988096 4292382080 4292053632 4292053632 4291988087 4292184958 4291922046 4292053880 4292118141 4292054136 4291987328 4292119424 4292119416 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290003789 4289151828 4289742417 4290135377 4290071637 4289806162 4289413196 4289349203 4289742418 4289479754 4289872971 4289610314 4291316816 4291252815 4292504148 4292439646 4292903262 4293559403 4293169012 4293563000 4293564793 4293564785 4293500286 4293565817 4293566077 4293566076 4293564549 4293430639 4292967514 4292965988 4291584086 4290332745 4289084239 4287834950 4287246666 4288358981 4288757586 4289016394 4289412945 4289283664 4290001482 4289740882 4289742417 4289546581 4289938254 4289872982 4289675341 4289938506 4289675341 4289742681 4289740619 4289938518 4289348430 4289741397 4290398542 4290400338 4290334032 4289611596 4289214283 4289212748 4294298269 4294104232 4293764978 4293631090 4292508529 4292504410 4291322720 4290595665 4289875277 4289281877 4291122779 4289744475 4290530648 4289281874 4289743448 4291381579 4290072923 4291842911 4290994014 4290533737 4291647072 4291120981 4290469482 4292041314 4291257964 4291453536 4290662232 4290070355 4291064950 4292641927 4292048771 4292117631 4292577151 4292179821 4291657331 4292374121 4291723635 4291721070 4290208103 4292113539 4292642686 4292118405 4292508279 4292252026 4292714142 4292120453 4291920502 4292843656 4291989397 4292119174 4292643982 4292588201 4292585633 4292588711 4292646284 4292188550 4292778646 4291592064 4292123297 4292651166 4292973712 4292587156 4292058785 4292186770 4292649098 4292588705 4292584091 4292582029 4292060829 4292647822 4292187283 4292647562 4292654751 4291859352 4292655014 4292592829 4292588966 4292585616 4292059804 4292127654 4292719005 4292650908 4292586908 4292587924 4292655017 4291869113 4292787118 4292127412 4292261530 4292721328 4292327858 4291934896 4292129707 4292263870 4292260006 4292716183 4292128679 4292127661 4292783783 4291867310 4292785324 4291736996 4292257961 4292065449 4292258724 4292129708 4291142049 4292130738 4291997623 4292326058 4291736236 4292786085 4292591285 4293119160 4293906091 4292654745 4292261285 4292590250 4292916658 4292395183 4292854709 4293379777 4293379757 4293182901 4293248443 4292919995 4292788408 4292985789 4292788401 4292854196 4292656823 4292854201 4292591029 4292920251 4293051837 4293182906 4293182907 4292986045 4292458926 4292459701 4292985532 4293315519 4293315006 4293578945 4293776581 4294105030 4294172619 4293712840 4283238208 4283174214 4284486726 4284288573 4284552515 4284682813 4284618310 4285082191 4285275973 4284750141 4284027972 4284812606 4284619327 4285209405 4284355395 4284949579 4285605195 4286130253 4286788451 4288369023 4290800000 4291725187 4292641916 4292509832 4291199087 4292116361 4291791486 4292055172 4292316804 4292316789 4292251268 4292645509 4292710270 4292317061 4291989381 4292382079 4291988096 4292447872 4292053631 4292053632 4292447872 4291659640 4292447864 4292053889 4292511866 4291266176 4292513408 4292053633 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289742946 4289414736 4289610580 4289742423 4289151827 4289413201 4289413203 4289612117 4289742424 4290068301 4289807185 4290070867 4290136143 4291123538 4291584853 4292964958 4293230194 4293232500 4293628269 4293564281 4293564785 4293498750 4293764473 4293499255 4293564273 4293565304 4293562994 4293627244 4293165934 4292964448 4291187282 4290335571 4289082443 4287770954 4287966279 4288362061 4288755789 4289085521 4289348938 4289281361 4289806925 4289347667 4289610831 4289414744 4289151829 4289938511 4289938506 4289283923 4289610832 4289545038 4289742675 4289609554 4290002765 4290399055 4290268501 4290069586 4290200137 4289807189 4289674849 4290067527 4294369987 4294036878 4293964402 4293503114 4293032024 4292969574 4291517526 4291914084 4290070359 4291977048 4290070616 4290004052 4289940054 4289349464 4290924376 4290924889 4290661463 4291057491 4292171868 4291055947 4291388003 4291062899 4291123545 4291257192 4291651167 4290925167 4289150798 4290540412 4292246394 4292380290 4291787623 4292704118 4292113785 4292178800 4291918193 4292120187 4290797413 4290271589 4291786622 4292313968 4292049274 4292182396 4291987087 4292117635 4292124829 4291592048 4292706941 4292052869 4292317064 4292646546 4292190885 4292644232 4292650136 4292195225 4292255900 4292314501 4291919497 4292316286 4292649870 4292587931 4292521374 4292578197 4292585105 4292582799 4292582039 4292187783 4292586911 4292584085 4292649125 4292189582 4292319127 4292253068 4292646555 4292654494 4292587163 4292650396 4292061085 4292585892 4292587419 4292652700 4292652692 4292194964 4292719263 4292125596 4292125861 4292719267 4292653995 4292263867 4292324523 4292326818 4292262074 4292720556 4292195756 4292650390 4292720028 4292062888 4292778388 4291733146 4292390059 4292391841 4291539122 4292518802 4291868088 4291931537 4291998630 4291405726 4292056723 4291139734 4291275177 4291800480 4292261291 4293052604 4293182895 4293046160 4292126865 4292920753 4292524720 4292459702 4292986036 4292986047 4293775297 4293379765 4292854720 4292984238 4292722874 4292985780 4292788410 4292788400 4293182651 4292854194 4292656823 4292985780 4292985788 4293051837 4292919995 4292854203 4293511606 4292656058 4292523421 4292524213 4292986044 4293379517 4293249727 4293511870 4294104261 4294038469 4294433215 4291667349 4282187834 4283631689 4284355140 4284486460 4284554831 4284680502 4285079621 4284618043 4284486723 4284616516 4284419402 4285076805 4285208894 4285208896 4285408329 4285014091 4284683588 4285671014 4286856290 4290011269 4291591278 4292708996 4291921783 4291524219 4291723390 4291593090 4291921543 4292317059 4292711561 4292252036 4292318602 4292250493 4292317318 4291922302 4292381823 4292382080 4292053632 4292053375 4292382854 4292382079 4291594886 4292119424 4292053632 4292119424 4292053888 4292119425 4292053623 4292119416 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289612120 4289676366 4289019729 4289480278 4289480279 4289610580 4289676361 4289217354 4289412941 4289545291 4289479754 4290068301 4290200662 4290598737 4291255639 4292770159 4292705886 4293362026 4293170299 4293565816 4293565305 4293565302 4293500802 4293565821 4293565047 4293566333 4293563512 4293628026 4292968557 4292571229 4291647569 4290333782 4288558411 4287769671 4287901255 4288294729 4288690511 4289281098 4289151566 4289283403 4289740878 4289938511 4289675342 4289938505 4289545295 4289740883 4289479759 4290004054 4289347660 4289806420 4289479753 4290201422 4289675850 4290333519 4291316308 4289809237 4290265674 4289874515 4289279562 4289936713 4294566830 4293903243 4293568639 4293962607 4292641640 4292899680 4292112230 4292110162 4291914084 4291254098 4291122773 4290796127 4290070095 4289808729 4291120213 4290070871 4290794586 4291122269 4288951885 4290729822 4291124317 4291122264 4291061351 4291715165 4290667368 4289743706 4290535797 4292312186 4292639606 4291921538 4292838525 4291128429 4290733674 4292312696 4292516504 4290991961 4290670205 4292311933 4292512373 4291460994 4291854962 4292444796 4292318098 4290933363 4291389790 4292776845 4291330176 4292777350 4292256414 4292583845 4292647817 4292060577 4292119437 4292576885 4292316286 4292117894 4292651170 4292980638 4292512898 4292582029 4292517266 4292580748 4292515480 4292975509 4292523415 4292582813 4292578173 4292519325 4292584089 4292647564 4292127913 4292252809 4292254884 4292645006 4292586404 4292059548 4292254881 4292588204 4292653992 4292194980 4292060319 4292781720 4291472554 4292386452 4292129182 4292260012 4292260261 4292721333 4291934390 4291801507 4292783776 4292195772 4292652438 4292718755 4291468709 4292845978 4292126371 4292516501 4291603617 4292194479 4292260781 4291867563 4291993750 4292059556 4291864481 4292056979 4291005847 4291074719 4291997347 4293380279 4293119664 4292519570 4292584086 4291730582 4292788654 4292852661 4292591279 4292919997 4293315777 4294102976 4293313981 4292920510 4293047716 4292197564 4292854201 4292788402 4292986037 4292854203 4292393652 4292656824 4292656822 4293116857 4292657079 4293445566 4292854194 4293511359 4292985537 4291996561 4292649370 4292523942 4292854708 4293182907 4293248445 4293840831 4294102976 4293775812 4294566611 4287585880 4282910531 4284091453 4284748343 4284619081 4284746555 4284686408 4285010495 4285080395 4284752974 4284092989 4284225604 4284681278 4284683327 4285932617 4284750920 4284552512 4284221511 4285802059 4289352823 4291131775 4291855232 4292445322 4291592061 4292180599 4291525504 4291988091 4292053631 4292710271 4292252794 4292316805 4291987581 4292318085 4291922046 4292776581 4292317061 4291988095 4292382079 4292055174 4292053375 4292316544 4292447606 4292053633 4292120198 4292053631 4292447617 4291989629 4292447361 4292053633 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289283156 4289281102 4289480529 4289282900 4289480273 4289480536 4289217615 4289741904 4289152080 4290003792 4289610832 4289347661 4289675855 4291120462 4291848533 4292963935 4292771424 4292970353 4293628276 4293562745 4293564786 4293563511 4293566077 4293564272 4293566077 4293564284 4293564529 4293430908 4293032283 4292572768 4291388258 4290399815 4288494159 4288359494 4287770954 4288819785 4289213771 4289019985 4289151054 4289283403 4289740877 4289872982 4289872969 4289872976 4289740883 4289938511 4289938518 4289479503 4289545296 4289742669 4289871185 4289937228 4290531157 4290069586 4289611090 4289939278 4290070605 4289677138 4289082964 4290596435 4294436030 4293837708 4293833076 4293172082 4292504932 4292904032 4292636009 4292441709 4290661964 4291654763 4290925901 4291318614 4289806928 4291055960 4290069074 4290927710 4290267477 4289678696 4289414495 4291321437 4290403172 4291190623 4290990679 4290796135 4289414747 4291126636 4292838783 4292175714 4291920512 4292772987 4290929516 4292310909 4291262070 4292515193 4290400085 4289616752 4292046186 4292184182 4292378249 4292181356 4292446341 4291857282 4292379766 4290734447 4292245114 4291652710 4292316552 4292120209 4292318079 4292654241 4292582313 4292711817 4292383362 4291390068 4292118408 4292654499 4292583823 4292518546 4292583570 4292119937 4292972664 4292519831 4292583323 4292516749 4292977556 4292523414 4292518313 4292973698 4292389267 4292649373 4292255897 4292646809 4292252551 4292255890 4292582549 4292581780 4292588438 4292587411 4292062881 4292651163 4292713607 4292062889 4292719268 4292651691 4292649112 4292258190 4292128688 4292197299 4292720813 4292391602 4292127909 4292716172 4292126630 4292128420 4292261041 4291798425 4291663767 4291669418 4292253582 4292128679 4292193955 4292193958 4292056468 4291012780 4291460979 4290940581 4291273635 4293051835 4293577141 4292655257 4292187542 4291667091 4292657076 4292788147 4292591288 4292920252 4293051840 4293774005 4293314240 4292986038 4292985780 4292459445 4292132797 4292722358 4292854201 4292854202 4292656823 4292854193 4293182651 4292788401 4292788409 4292920251 4293051838 4293117114 4293248444 4292986563 4292127118 4292383380 4291925132 4292651152 4292457903 4293117890 4293182910 4293642429 4293776581 4293776568 4293450692 4285209149 4283697980 4284286782 4284092222 4284419396 4284550980 4284882762 4285012547 4284886100 4284820049 4283764272 4285208135 4284749367 4285604429 4285276999 4285079626 4284352840 4284026435 4286527074 4289948550 4292118387 4292251007 4292509317 4291066239 4291854975 4292316039 4291857037 4292384379 4292250238 4292317578 4292316803 4292251524 4292711044 4292252036 4292252036 4292317828 4291987839 4292382080 4292381823 4291988861 4292579456 4291923847 4292447606 4292053633 4292053633 4292053622 4292381825 4291990397 4292381816 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289281359 4289480536 4289677652 4289478482 4289478732 4289412946 4289937490 4289152086 4289806156 4289546838 4289412947 4289347405 4289939278 4291123288 4291648848 4292573537 4292901474 4293495155 4293562734 4293564275 4293565304 4293566078 4293565045 4293564285 4293566075 4293566850 4293562743 4293626738 4292837471 4292964961 4291583315 4290203483 4289083981 4288360521 4287835977 4288298322 4288823373 4289019473 4289348937 4289281360 4289543504 4289677138 4289938260 4289676887 4289545039 4289545290 4289479504 4290071120 4289740621 4289742670 4289872970 4290068306 4289545560 4290135371 4289939535 4290465371 4290070610 4289938510 4288689491 4291123545 4294370225 4294099583 4293568637 4293760623 4293172868 4292378500 4291983200 4292704864 4291848035 4292304468 4291913307 4290069333 4290858835 4289874275 4290135888 4290069845 4289940311 4291516505 4290792020 4290601826 4292306526 4290333527 4289086036 4289216336 4291721328 4291855481 4292635506 4291526010 4292969839 4291650676 4291788655 4292244345 4292055415 4289941610 4290535017 4292113775 4292051841 4292377696 4292050559 4292579210 4292249216 4291463059 4291783270 4291716471 4292116348 4292117389 4291394174 4292973957 4291724164 4292182913 4292127900 4292182131 4291985797 4291989389 4292583060 4292974736 4292520096 4292584856 4292514204 4292974723 4291989912 4292646272 4292585107 4292583847 4292516502 4292582031 4292587414 4292583319 4292251025 4292116609 4292318088 4292653465 4292251528 4292251011 4292579976 4292650645 4292584345 4292715417 4292119689 4292320921 4292127916 4292125841 4292652189 4292195507 4292194978 4292650383 4292652697 4292654512 4292326057 4291800988 4292125852 4292715672 4292125614 4292784280 4292125859 4292326826 4292783277 4292188559 4292322723 4292384654 4291670179 4292519579 4291661195 4291332751 4291137935 4292526780 4293841325 4293114263 4291339671 4292650925 4292198055 4292981935 4292459702 4292722874 4293642429 4293445558 4293051066 4293248439 4292920237 4292854195 4292656825 4292722609 4292919721 4293182650 4292788409 4292986036 4292656823 4292656822 4292591029 4292986045 4293313979 4292919994 4292854458 4293445567 4293052090 4292326295 4292318101 4292119933 4291857553 4292647052 4292788142 4292918190 4292457365 4292589747 4294364865 4293775791 4292060572 4283170871 4283698758 4283569737 4284288579 4284815933 4284947522 4284683837 4284879927 4284749371 4284422215 4284617031 4284880951 4285075268 4284421443 4284947784 4284357960 4284227143 4285208907 4289418096 4291131518 4292184710 4292116620 4291461243 4292116616 4291593089 4292119422 4292382595 4292316548 4292318601 4292251778 4292252041 4292711044 4291856510 4292711045 4292317571 4292317061 4292382079 4291987839 4292382080 4292381824 4291988087 4292447615 4291988097 4292053622 4292448380 4291988871 4292382336 4291987841 4292316544 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289873740 4289217359 4289282895 4289480529 4289085267 4289350226 4289019725 4289480525 4289806414 4289610832 4289217610 4289742406 4289874524 4291120203 4291848036 4292571997 4293492585 4293233785 4293628020 4293564786 4293566078 4293565045 4293566852 4293566076 4293563004 4293566074 4293564805 4293626480 4293231471 4292505434 4291649115 4289676880 4289213771 4287770441 4287836490 4288360523 4288626001 4289217100 4289741910 4289020498 4289806412 4289740619 4289546586 4289807959 4289742417 4289479760 4290068557 4289872721 4289545289 4289545041 4289938506 4289677139 4289676620 4290070868 4289871944 4290070099 4290397001 4289545302 4288755026 4290793812 4294436285 4293702788 4293831029 4293697138 4293691762 4293431909 4292704097 4292704365 4292835407 4292571231 4291059038 4291057758 4291122509 4291121745 4288948037 4289613143 4290597980 4289806931 4290666598 4291583323 4291123292 4289938515 4289545809 4290995834 4292181375 4292312684 4291587706 4292439905 4290931584 4291783783 4292906632 4291132279 4290070354 4290076012 4291459700 4292248175 4292575354 4292378505 4291330678 4292184946 4291261054 4292708222 4292113269 4291725445 4292317326 4292252545 4292245880 4291062376 4292977053 4291396998 4292176750 4291331476 4292712333 4292584871 4292910482 4292514717 4292579458 4292580231 4292582298 4292122252 4292646301 4292185732 4292643212 4292582537 4292520609 4292580494 4292578427 4292185235 4292122268 4292318339 4291726225 4292711806 4292647581 4292125597 4292778130 4291793530 4292381309 4291532711 4292390804 4292320143 4292319883 4292127650 4292584088 4292653989 4292653989 4292063151 4292191139 4292128147 4292193695 4292321689 4292718237 4292124069 4292253071 4292127408 4292718752 4292126635 4292129182 4292055437 4292452760 4292119175 4292059803 4291596181 4290940308 4292521886 4293579199 4293313701 4291927954 4292062633 4292721579 4292523683 4292459703 4292788923 4293117368 4293248437 4293182892 4292788660 4292722099 4292129946 4292721329 4292525239 4292722608 4292722609 4292459445 4292854201 4292854201 4292854202 4292393651 4293183167 4292986044 4292525237 4293051838 4292986301 4293051838 4292984502 4293052596 4292253333 4292120190 4291528845 4292118907 4292324002 4292259491 4292049786 4292189081 4292786855 4293642674 4294435273 4287120451 4283238471 4284091461 4284951377 4284818253 4284685639 4284683836 4284883531 4284685895 4284619854 4283831863 4284549177 4284683328 4284944952 4284614468 4284159300 4285935458 4286460760 4287576163 4289947511 4292052609 4292708738 4291657582 4292180604 4291592058 4291987335 4292053630 4292317828 4292252036 4292316803 4292645252 4292316030 4292252293 4292710271 4292250494 4291990154 4292053374 4292382079 4292055173 4292053374 4292055947 4292053375 4292054405 4292447616 4292054405 4292054150 4292382081 4291790193 4292382328 4292316544 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289217366 4289480524 4289544268 4289480537 4289151052 4289348688 4289546061 4289282897 4289283146 4289478733 4289413203 4289938517 4289675091 4291122777 4291782742 4292573296 4292839539 4293494636 4293170033 4293238134 4293236856 4293170563 4293564528 4293565303 4293563260 4293565827 4293562219 4293430903 4292967513 4292965747 4291387478 4290071124 4287969101 4287837773 4288555846 4288230732 4289215053 4289414481 4289085516 4289544273 4289612379 4289807703 4289349200 4289151823 4290004053 4289740882 4289545297 4289545289 4289545047 4289545295 4289675341 4289872727 4289611341 4290265679 4290531164 4289741390 4289413969 4289873999 4288820564 4290337365 4294501052 4294162282 4293571972 4293628772 4292513649 4293231714 4292117117 4292899146 4292704370 4292372827 4292637022 4292109404 4291121750 4289807187 4289349977 4290002254 4289017421 4290925138 4291254877 4290596953 4290795868 4289741411 4291129973 4291914358 4292901734 4291982206 4292375401 4291128684 4291979366 4291920516 4291136377 4290728276 4289484395 4291588210 4292310634 4292379020 4292116074 4292643975 4291786605 4291327606 4291656318 4292180071 4292251531 4292382858 4291521652 4291786625 4291134338 4292049545 4292052350 4292708227 4291328127 4292775786 4292975000 4292515991 4292911779 4292515981 4292120963 4292579219 4292381835 4292582298 4292580251 4292649362 4292253839 4292052617 4293039228 4292125076 4292581024 4292579196 4292646538 4292579994 4292778125 4291663262 4292841853 4292186516 4291854961 4291528356 4292055687 4292188572 4292124570 4292255632 4292647076 4292650125 4292647073 4292058772 4292654000 4292719010 4291537054 4292254624 4291535008 4292849566 4292124303 4292190626 4291401125 4292384124 4292258479 4292130206 4292451232 4291994525 4291920247 4291464333 4291002503 4291995033 4292920498 4293314207 4292518544 4292126874 4292851874 4292588701 4292525495 4292591289 4293511607 4293247675 4293051312 4292984494 4292985788 4292524718 4292523435 4292655799 4292523436 4292590254 4292525238 4292459445 4292919994 4292656822 4292854201 4292656822 4292854201 4292788408 4292984243 4293051839 4292854202 4293379773 4292987064 4293579454 4292191386 4292053118 4291920772 4291924110 4292390561 4292720276 4290403422 4290870643 4292715674 4292851111 4293247901 4293119418 4283629614 4283898952 4283828537 4284489286 4284556875 4284882498 4284815679 4285471554 4284682808 4284617022 4284355391 4285666878 4285013317 4284287805 4284358472 4285081431 4286525514 4286987372 4289355642 4291592576 4292181880 4291396239 4292180343 4291657852 4291855248 4292185738 4292054915 4292317571 4292776324 4291922819 4292776580 4291922303 4292316286 4292645509 4292317061 4292382596 4292053375 4292054139 4292119941 4292053631 4292447615 4292382079 4292054407 4291858547 4292448134 4291859833 4292381815 4292053890 4292447617 4292053632 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289676362 4289282895 4288888144 4289348681 4289151054 4288953680 4288888144 4289414480 4289151060 4289085517 4289676362 4289740882 4289479760 4291122519 4292109669 4292508769 4293491543 4293233777 4293628794 4293564278 4293629571 4293630331 4293565303 4293172340 4293563254 4293564035 4293563251 4293430895 4293361771 4292506974 4291714645 4289479249 4289282641 4287769158 4287181901 4288360265 4288624718 4289282637 4289019472 4289283157 4289478218 4289350996 4290003797 4290004041 4289086544 4290004048 4289545289 4289938264 4289742667 4289543249 4289938507 4289807943 4290201933 4289741648 4289545554 4290069584 4290004042 4289151565 4288229707 4291324500 4294236339 4293505671 4294027360 4293497980 4293300853 4293297514 4293762396 4292310130 4292767065 4292180592 4292767835 4291189852 4290922837 4289677142 4289610573 4288953166 4290334291 4290203739 4290792792 4290333781 4289739850 4291065456 4292313218 4292377451 4291126651 4292440932 4291323752 4291915628 4291589760 4291919730 4289873752 4290076019 4291390842 4292374888 4292243305 4292116846 4292643977 4291853668 4292312702 4290668399 4292246649 4292710280 4291851117 4291396999 4291524481 4292253326 4292249478 4292576135 4291126376 4292247923 4292780187 4292050843 4292446599 4292646279 4292578937 4292708743 4292977057 4292515475 4292578942 4292580745 4292581775 4292580489 4292188569 4292710008 4291856536 4292641657 4292520847 4292581790 4292184958 4292712071 4292124051 4292514180 4291131522 4291988619 4291926951 4292122001 4292190616 4292318105 4292317592 4292651167 4292584590 4292187807 4292124055 4292122012 4292059537 4292588207 4292717723 4292125853 4292841623 4291794836 4291797422 4292452245 4292252565 4292320675 4292449176 4292192179 4291994007 4291399312 4290477982 4291990169 4292458157 4293578930 4292717717 4291993747 4292063644 4292652707 4292456619 4292591546 4292921539 4293248437 4293182902 4293051316 4292986287 4292524977 4291996826 4292196788 4292657080 4292195753 4292588973 4292525494 4293050293 4292854458 4292788409 4292854201 4292854201 4292854201 4292788408 4292985787 4292722872 4293445565 4292986045 4293314238 4293445558 4292920761 4291460983 4291792001 4291857808 4292390552 4292654484 4290469983 4290406511 4292383890 4292583331 4292588711 4293844925 4289820552 4282974261 4283763517 4283828550 4284287030 4284357701 4285476686 4284886101 4284683836 4284617279 4284221496 4284489030 4285537092 4285013060 4285010761 4284159302 4285604939 4286723692 4288564850 4290934915 4291657597 4292643717 4292706166 4291592318 4291133056 4291528569 4292842372 4291989124 4292383880 4291989123 4292055689 4291989123 4292382079 4292317318 4292316287 4292053375 4292054139 4292382596 4292121482 4292053374 4292447871 4291594112 4292447872 4292053622 4292119169 4292054405 4292054150 4292382079 4292119168 4291661180 4292119168 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289281103 4289744991 4289348431 4289151060 4289348682 4289546061 4289741904 4289151053 4289151565 4289544270 4289415245 4289347410 4290070358 4291123294 4291912282 4292900449 4292838257 4293364591 4293038447 4293627519 4293172594 4293171322 4293564796 4293564541 4293564797 4293566588 4293562744 4293430901 4293295977 4293294176 4291516753 4290333271 4288493133 4288359494 4288491593 4288163401 4289282641 4289021261 4289019215 4289546065 4289217621 4289610580 4289545294 4289545296 4289676368 4289150544 4289609040 4289742662 4289347412 4289349452 4289676877 4289872720 4289611354 4290003786 4290201933 4289675086 4289610827 4288954449 4288751180 4291655534 4294567346 4293962330 4293566336 4293763442 4293233522 4293037162 4292374894 4293691744 4292242783 4292503121 4292443504 4292502875 4290070350 4290333528 4289283669 4290530905 4290924120 4290269788 4290725202 4288888396 4291323783 4292509549 4291655792 4291915360 4291982192 4291123548 4292111996 4291984758 4291193700 4289418606 4290732130 4291124340 4292444525 4292117889 4291456124 4292312177 4291721838 4291457420 4291195247 4292706413 4291132545 4291193700 4290537337 4291921524 4292644743 4292773776 4292251786 4291128425 4292181637 4291526270 4292907130 4292648345 4292119945 4291592063 4292117631 4292382347 4292381321 4292586657 4292583059 4292250509 4292447367 4292446340 4292578681 4292581261 4292187012 4292383132 4292773249 4292583311 4292781203 4292309096 4291264886 4292119695 4291930016 4291858318 4292382608 4292318600 4292250492 4292713627 4292058275 4292646528 4292583581 4292645767 4292184699 4292715420 4292645019 4292647303 4292190362 4292188833 4291796890 4292186000 4292845459 4291797417 4291924362 4292187796 4291137677 4292120456 4291792534 4290939791 4292326306 4292855215 4293311110 4292448135 4292124300 4292981153 4292522404 4292592053 4293051573 4293445816 4293642174 4293051816 4292854187 4292655792 4292588973 4292196530 4292656305 4292590511 4292590255 4292589735 4292524719 4292722616 4292656823 4292591030 4293182649 4292985788 4292788408 4292788408 4292985787 4292919994 4292919995 4292985788 4293381056 4293314740 4293053125 4292318857 4291135117 4292120970 4292781461 4292522641 4290798696 4290344579 4291202442 4292844441 4292518807 4293048234 4294567383 4286658885 4283236424 4283895612 4284418884 4284682565 4284358217 4285143104 4284357960 4284422210 4284287045 4284225862 4284947261 4285601858 4284684604 4284289352 4285079112 4286526307 4287312230 4290142836 4291330688 4292908673 4292050298 4291525246 4291657597 4291856004 4292317069 4291987838 4292053373 4292317833 4292382595 4292316803 4292384394 4291987839 4292053631 4292053631 4292119941 4292054405 4292448389 4291595139 4292448389 4292054406 4292119424 4292053632 4292119167 4292119424 4292053631 4292447615 4291989638 4292119167 4292119942 4292382845 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289283146 4289282632 4289348682 4289151053 4289217102 4289085517 4289348688 4289151053 4289217102 4289020494 4290067789 4289282130 4290004560 4290991950 4291850079 4293161826 4293361513 4293299062 4293235062 4293565297 4293564798 4293631095 4293563779 4293564784 4293564535 4293564541 4293566072 4293430382 4292968557 4292964446 4291651421 4289217625 4289414477 4288294473 4287772236 4288886092 4288624461 4289085264 4289217106 4289282901 4289610836 4289806418 4289806418 4289740883 4289349452 4290002256 4289545558 4289938250 4289545295 4289938262 4290267481 4289611346 4289742413 4289872714 4289676884 4289414990 4289217867 4289411662 4288686661 4293042044 4294297999 4293502595 4294030185 4293432445 4293502576 4292571251 4293432171 4292246393 4292441192 4291715680 4292377447 4291255130 4291778648 4291123549 4290335067 4289543761 4290663002 4290068047 4290071634 4292113802 4291856498 4292111994 4292311147 4292111739 4291323238 4291061101 4291918694 4291390319 4289284186 4290734454 4291323763 4291920241 4291721585 4292244584 4292449153 4291716200 4291850605 4291851629 4292248172 4290670459 4290930542 4291393654 4292315010 4291526270 4292313983 4291918439 4291715427 4292117637 4292513675 4292711831 4292181640 4292643958 4292512903 4292118916 4291920791 4292773484 4292253589 4292448902 4292711295 4292117642 4292316059 4291726473 4292646801 4292513683 4292974219 4292582032 4292252553 4292314737 4290998399 4290606717 4292123021 4292322473 4292643962 4292712074 4292581525 4292647834 4292251797 4292249973 4292713369 4292385697 4292583835 4292581009 4292646559 4292119690 4292124058 4292055690 4292774794 4292317587 4292190888 4292057752 4291988347 4292515987 4291990676 4291462273 4291858577 4290739841 4292579728 4293245860 4292984226 4292518523 4292124307 4292520339 4292522655 4292787365 4293117368 4293511604 4293641902 4293050796 4292789167 4292523945 4292197309 4292589991 4292196010 4292591288 4292524719 4292524719 4292525495 4292722865 4292722616 4292656823 4292788409 4293379772 4292722872 4292788408 4292788408 4292985787 4292722615 4293051838 4293182649 4292987071 4293315263 4293315267 4293312176 4291460225 4291855993 4292059027 4292521878 4291195245 4291133330 4292450712 4292582800 4292119446 4292453023 4293185977 4292857783 4283367477 4283306569 4284093510 4284290628 4284815676 4284553796 4284751431 4284551488 4285149530 4283764020 4284812093 4284422980 4285012546 4284554060 4284290373 4285344094 4286194782 4289092204 4290935694 4292250244 4292380019 4291592319 4291721854 4292116089 4291921800 4292053629 4292382078 4292317833 4292316803 4291988613 4292381822 4291987839 4292447872 4292053632 4292447872 4292053631 4292053631 4292053365 4292448391 4291987830 4292119159 4292119416 4292119158 4292122252 4292119158 4292120199 4292053622 4292447617 4292119415 4292119169 4292053624 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289545816 4289283931 4289348436 4289151058 4288888143 4289544781 4289085523 4289611853 4289085518 4289479246 4289347660 4289611346 4290727513 4292042072 4292699224 4292768604 4292968302 4293299311 4293429882 4293565298 4293563006 4293171565 4293565308 4293564541 4293565559 4293563005 4293564536 4293562484 4293361257 4292509025 4291583324 4290465362 4288492107 4287836233 4287312716 4288361547 4288692049 4289281098 4289216589 4289480524 4290069590 4289349451 4289152086 4289806412 4289545296 4289938762 4289545296 4289545296 4289543505 4289152073 4289545033 4290068302 4289479755 4289675342 4289938512 4289611082 4289673294 4289018702 4288031043 4293305753 4293640834 4293966969 4293369735 4293900400 4293299571 4293630320 4292374875 4293759344 4292376426 4292639055 4292373614 4292638566 4291384398 4291781983 4290727762 4290465626 4289543504 4289085521 4291128177 4291125094 4292308587 4292179067 4291192427 4291982700 4291127417 4292183925 4290596696 4289550968 4290730849 4291518043 4291918969 4292115837 4292114812 4291984252 4292246892 4291786352 4291915115 4292117884 4290994537 4290731895 4291849595 4291789166 4292249478 4292315267 4291655038 4291192688 4291527301 4292511618 4292579707 4292579452 4292448396 4291984506 4291984757 4292971657 4292714132 4291853458 4292116340 4292183955 4291982984 4291131531 4291005850 4292711562 4292514966 4292976014 4292974213 4292512394 4291920497 4290674583 4292319382 4292384412 4292643962 4292646785 4292647577 4292053384 4292644991 4292188566 4292646536 4292251801 4292184459 4292648335 4292446083 4292253599 4292251269 4292124064 4291789710 4292842109 4291400086 4292118927 4292449429 4292122267 4292120466 4291596173 4291924898 4291133054 4291332747 4292850853 4292592043 4292719259 4292517006 4292518033 4292519835 4292984257 4292722853 4293378992 4292984234 4292392354 4292655776 4292587414 4292194451 4292652443 4292197030 4292588710 4292588974 4292722866 4292722866 4292721841 4292525237 4292459445 4292854203 4292788400 4292985788 4292722616 4292985787 4292985787 4292788409 4292985788 4292919994 4292986045 4293381055 4292986558 4293315263 4293447108 4291594371 4291462009 4291794841 4292454556 4290996850 4291530381 4292387477 4292578692 4291130494 4291591291 4293374891 4294373322 4289558390 4282648389 4284024386 4284027974 4284555078 4284357961 4284947007 4284749372 4284423750 4283633980 4284820306 4285209411 4285013835 4285080139 4284290374 4284426059 4285737808 4286396515 4290080890 4292117886 4291920782 4292117887 4291720827 4291068032 4292118662 4292119422 4292055173 4291988612 4292318600 4292251268 4292381822 4292055174 4292119424 4292052346 4292119424 4292053887 4292053631 4292448389 4291661189 4292053631 4292382080 4292054406 4292119424 4291725185 4292120700 4291725177 4292119158 4292119169 4292119424 4291725440 4292053632 4292382081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289085516 4289544017 4289480535 4289676116 4289676373 4289478732 4289348943 4289085268 4289480781 4289806156 4289872982 4289871434 4290923351 4290795862 4292372583 4292901213 4292837989 4293299056 4293431923 4293563250 4293565559 4293564285 4293566076 4293566077 4293564529 4293565817 4293563762 4293562491 4293361512 4292900973 4291914070 4290335588 4289478727 4287834951 4287901258 4288360265 4288755790 4289150801 4288628044 4289609811 4289215823 4289873746 4289608783 4289611082 4289347667 4290002256 4289545290 4289938256 4290069577 4289610583 4289349459 4289479754 4290068558 4289872976 4289938513 4288954958 4289739851 4289018959 4288618304 4293968012 4293972391 4293834876 4293968769 4293367167 4293768837 4293167219 4293041271 4292968806 4292970851 4292436818 4293099879 4292308831 4291980650 4291251020 4290266961 4290066769 4289150029 4291392878 4292441196 4291916656 4290795864 4291457394 4291323513 4290797672 4291657333 4291125351 4289550705 4290797666 4291321710 4291922295 4291783788 4292245100 4292181100 4292643459 4291585144 4291986033 4291325820 4289876850 4289946214 4292176486 4291724931 4292511374 4291916647 4292250759 4290861916 4292510599 4292514189 4292579707 4292379295 4292446079 4292644741 4292446103 4292248223 4291919500 4292580500 4291466171 4291141041 4290284451 4290086307 4288905623 4289292692 4288831104 4290014063 4288762472 4290403928 4291922833 4291989645 4292841614 4292646021 4292580235 4292646023 4292252807 4292446858 4292712578 4292184954 4292250254 4292645763 4292582562 4292644989 4292446855 4292123550 4292119690 4292320148 4292711064 4292384140 4291987347 4291990926 4291992726 4291393666 4291924123 4291724168 4291003270 4291133559 4292191651 4292656809 4293115041 4292579975 4292517518 4292524708 4292847781 4292984483 4293117616 4293707439 4292656557 4292129181 4292719522 4292193688 4291932841 4292325032 4292063399 4292655534 4292590512 4292524975 4292524719 4292524463 4292657073 4292854203 4292854194 4292920244 4293051840 4293313464 4292854459 4293248443 4292919995 4292985780 4292919987 4293051838 4292985532 4293316802 4293381825 4293449416 4292258457 4291066751 4291862418 4292319362 4290869875 4292386453 4292186241 4290798442 4289483358 4290865524 4292321677 4292990394 4294566868 4285405493 4282975813 4283962175 4284027719 4284291648 4284818510 4284816712 4284881480 4285213268 4284226112 4285210703 4285675358 4285340998 4284945728 4285080137 4284812879 4286391907 4288565863 4291655037 4292315011 4292249464 4291985034 4291199089 4292246907 4292054144 4292053631 4292316287 4292316286 4292251525 4292776063 4291988096 4292119167 4292053632 4292382336 4292053887 4292249736 4291988095 4292316287 4292448389 4292053631 4292382080 4292119168 4291725441 4292119415 4292119169 4292119159 4292119943 4292120709 4292119168 4292119424 4292447872 4292053623 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289478732 4289283151 4289282901 4289480529 4289283157 4289283151 4289085266 4289283145 4289871693 4289283923 4290069841 4290464600 4291119693 4292042327 4292108639 4292375407 4293427037 4293299311 4293429887 4293565053 4293566077 4293566077 4293565047 4293565046 4293564543 4293564786 4293562740 4293628020 4292968043 4292901228 4292111201 4289611081 4289147980 4287181130 4288556615 4288361289 4288166222 4289151056 4289347666 4288759637 4289281102 4289480536 4289610838 4289347661 4289479245 4289216080 4289217616 4289808211 4289282126 4289545289 4289938512 4289545297 4289479754 4289675086 4289742664 4289413199 4289413192 4288622665 4288095038 4293769379 4293904522 4294100612 4293762667 4294038680 4293625704 4293830001 4292969594 4293237606 4292569194 4292446066 4292767559 4293234814 4292241743 4291719016 4291052880 4289147722 4290992986 4291585403 4292966759 4291849323 4291258748 4291320411 4290866801 4292246401 4290665054 4289943661 4290801009 4290993246 4292182142 4292111991 4291785325 4291784299 4291524479 4292372578 4291128960 4291587944 4290731885 4291718251 4291193471 4290932865 4292447865 4291788932 4291329403 4290728538 4291719803 4292378758 4292446081 4292646278 4292843389 4292706943 4291328130 4289749110 4290275200 4289624455 4289490826 4290346129 4291786372 4291267732 4291855245 4289619835 4290873239 4291200125 4289755538 4288304774 4285338951 4292447119 4292909447 4292251778 4292446857 4292580743 4292184976 4292118406 4292053365 4292055718 4292644250 4292778640 4292120204 4292645506 4292253841 4292052611 4292841849 4292382344 4292118429 4292581241 4291990175 4292120720 4291921544 4292449678 4291331732 4291394156 4291462805 4291462543 4293048725 4293709488 4292713336 4292517777 4292058256 4292587688 4292459699 4292983987 4292917921 4293838259 4292787366 4292129957 4292719521 4291868066 4292720818 4292260508 4292261790 4292657081 4292591030 4292525237 4292722617 4292722608 4292854196 4292854195 4292854202 4292525494 4293313980 4292854459 4292722616 4293313979 4292985527 4293117374 4292722616 4293445566 4292985788 4293317058 4293313210 4292923074 4293447108 4291198598 4291730073 4292250755 4291267460 4291921534 4289809986 4288039005 4287839325 4289942369 4290869886 4293442996 4294238674 4292393643 4282777648 4283239496 4284024645 4284226109 4284293709 4284750920 4285341000 4284356680 4284358216 4284158788 4285406010 4285607504 4284751432 4285275971 4284555854 4285277777 4286459474 4290014343 4291790722 4292579207 4292114299 4291592572 4291722879 4291528829 4292447615 4291989381 4292711045 4292251525 4292382079 4291922304 4292382080 4291988096 4292447872 4292382080 4292119424 4291594111 4292447872 4292316544 4292053631 4292119424 4292053632 4292119415 4292119416 4292447864 4292053633 4292120957 4291725183 4292119168 4292119415 4292119424 4292119424 4291791233 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289480535 4289085265 4289676366 4289282901 4289151051 4289478481 4289677914 4289217358 4289545302 4289872456 4290399317 4290398551 4291120724 4291318619 4292505439 4293228113 4292968560 4293101942 4293431666 4293565816 4293564535 4293565047 4293565047 4293566078 4293564272 4293565562 4293565299 4293562228 4293362795 4292507486 4291714631 4289807190 4289149774 4287900742 4287311687 4288491594 4288165454 4289214797 4288496208 4289611346 4289873746 4289019724 4289610825 4290002257 4289413197 4289675853 4289217617 4289806157 4289806413 4289479761 4290068557 4289936464 4289611598 4290397259 4289873227 4289806414 4288954450 4288623176 4288092999 4293770393 4294168469 4293703814 4293840804 4293629036 4293703047 4293430382 4293109861 4292967004 4293040500 4293363806 4293035651 4293032776 4292970872 4292106841 4289610578 4289874262 4291520360 4291519587 4291125105 4291257192 4291716728 4291126115 4292115845 4290864996 4288956264 4290864486 4291057500 4291262324 4292707710 4292247150 4291785067 4291653756 4291849327 4291986038 4291258980 4289812338 4291719011 4290929775 4291854206 4291719033 4291849322 4291921017 4291710827 4291857027 4292312715 4291919736 4292575354 4292248190 4291259013 4287707487 4288237441 4289027726 4289355637 4288824425 4287382889 4288100966 4288762216 4291195766 4291852169 4289088868 4291593343 4291721607 4292119954 4290413715 4287252605 4289421924 4291919749 4292183153 4292778392 4292973693 4292975242 4292514432 4290147988 4289818753 4290937749 4291917947 4291855998 4292974227 4292250523 4292974482 4291394446 4290539146 4289091447 4286259266 4292386465 4292643732 4291858586 4290803064 4291135362 4290932356 4292056969 4293051821 4292916119 4292518033 4292120459 4292979879 4292459705 4292983725 4293246894 4293510313 4292720552 4292984233 4292130982 4292260513 4292260513 4292721322 4292196788 4292721842 4292197293 4292591030 4292525237 4292919986 4292656823 4292656823 4292986037 4292393653 4292985780 4293313980 4292657080 4293511349 4292919995 4292919994 4293051838 4292722615 4292920251 4293379773 4292985532 4293708734 4293187013 4293906117 4292256394 4292120711 4291792517 4292120186 4290271834 4287377222 4287507533 4288298572 4289414233 4290346130 4292191917 4293514183 4294307774 4288240472 4283039803 4283697459 4283500864 4284159027 4284683333 4284749884 4284554055 4284420675 4284813885 4284488773 4284882244 4286127682 4284356927 4284882010 4284750421 4285277516 4288698231 4291129467 4292576896 4292577413 4291657836 4292049292 4291987316 4292118150 4292054404 4292054916 4292250494 4292711045 4291987839 4292384380 4292316288 4292447872 4291594112 4292053887 4292053632 4292513408 4291594111 4292447872 4292053888 4292119424 4292119425 4292119424 4291921537 4292119425 4292119424 4292119168 4292119424 4292119424 4291922046 4291921537 4292119672 4291789947 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289217363 4289480535 4289676110 4289480279 4289085265 4289283156 4289480279 4289414737 4289545044 4290070358 4290200142 4290398290 4291119694 4291123797 4292306012 4292377188 4293426521 4293232237 4293563514 4293564024 4293563767 4293566078 4293499511 4293565046 4293566079 4293564529 4293563513 4293563001 4293298551 4292899434 4292242264 4290333518 4288559950 4287965770 4287440967 4287769414 4288823378 4289216592 4288691533 4289546066 4289610581 4289478738 4289217616 4289545295 4289349459 4289740877 4289545034 4289481040 4289479760 4290068556 4289675342 4289481553 4289872714 4289675854 4289476430 4289611339 4289152078 4289147209 4288027966 4293899658 4294103214 4294102678 4293764201 4293841830 4293694050 4292974967 4293559403 4292975743 4293362249 4292245362 4293166678 4292575607 4294017360 4291519592 4291122005 4291585380 4291056492 4291126371 4291060579 4291060841 4291386977 4291130231 4290207583 4289676891 4290928999 4290665593 4291522409 4292836474 4291585640 4291852656 4291652473 4291848551 4292511620 4290401373 4290533978 4291719287 4291323513 4290932335 4291719547 4292119944 4291060065 4291057781 4291264369 4292576906 4291985800 4292643969 4292114565 4290465134 4286922341 4289094015 4291465632 4291523718 4291587965 4290798698 4290798976 4289157484 4288433787 4286657376 4287970409 4287976062 4291464080 4292450721 4292777108 4292907657 4290939021 4288438167 4287255696 4287188628 4288044417 4289416045 4290010479 4292581523 4293695626 4292578964 4291663779 4289431962 4288367485 4290870166 4290736007 4291659157 4291273402 4287586943 4289956530 4286067843 4283501372 4290148756 4292055175 4291067547 4291456130 4292390560 4292983453 4292782745 4292185991 4292186250 4292586400 4292393378 4293512124 4293641909 4293051050 4292327338 4292917414 4292458408 4292591289 4292656303 4292262325 4292196516 4292720302 4292197291 4292656567 4292525238 4292656815 4292986046 4292656822 4292854201 4293116857 4292788410 4293116857 4292920251 4292985787 4292854459 4292920251 4292919995 4293248442 4293313979 4292854458 4293313980 4293316802 4293185474 4294235593 4292259999 4292121229 4292055433 4290932825 4287967049 4286984270 4287969874 4288756299 4288827243 4290470001 4292977044 4293578692 4294433216 4293775541 4284088362 4283500352 4283502131 4284221255 4285077049 4284554310 4284749886 4284619844 4284225093 4284355391 4285209405 4285471043 4285473612 4284489801 4284555100 4284752463 4286525785 4290799990 4291265668 4292117888 4291920493 4292050828 4291788651 4292117906 4292449411 4292054659 4292054916 4292316286 4292317061 4291987839 4292317061 4292382079 4291988096 4292447871 4292183944 4292119423 4291659903 4292315272 4292053887 4291922045 4292119425 4291922036 4291725442 4292119672 4291922046 4292119424 4291725441 4291790967 4291725441 4291987837 4292053375 4291331705 4292053631 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289807953 4289414743 4289019722 4289677658 4289480529 4289675853 4289085265 4289807953 4289742423 4289675083 4289676111 4290593871 4291054923 4291844953 4292831831 4293162592 4292967517 4293496690 4293563764 4293565560 4293566078 4293499255 4293763700 4293500286 4293564272 4293499775 4293562994 4293562997 4293690216 4292769635 4292043092 4290333519 4288624462 4287311430 4287376202 4288427853 4288162631 4288691793 4289282637 4289478738 4289676367 4289217615 4289413203 4289938254 4289676881 4290266195 4289807178 4290267475 4289609548 4290398039 4289807434 4290068557 4290003028 4289544269 4290265678 4289346635 4289411662 4289081929 4288093757 4293830537 4294171311 4293503620 4294168987 4293566839 4293837456 4294092128 4293107073 4293362013 4292310641 4293363551 4292637291 4293955939 4292374367 4293162848 4290992990 4291122778 4290733673 4290533211 4291122264 4291060066 4291064178 4291519591 4289153131 4290342261 4290533478 4291655014 4292770683 4291588460 4292439399 4291192174 4292050033 4291587174 4290009960 4290073949 4290996343 4291521131 4290864750 4291916926 4291984237 4291457644 4290731628 4291983468 4292246396 4291264647 4292509570 4292052359 4291390081 4288893809 4291000729 4291590780 4291982197 4290602106 4290273400 4290076018 4288369259 4288760171 4288959595 4287777390 4285995861 4287320711 4290746292 4292976799 4292055196 4293105569 4290734484 4288901024 4289231521 4289426848 4288967078 4288903088 4286204552 4286919011 4287054433 4290408318 4290078594 4291593364 4288767369 4288106085 4286990452 4284814390 4286003559 4285208163 4287974238 4287650674 4283170897 4285738836 4291924384 4291594122 4292390301 4293048998 4292185985 4292250493 4292250507 4292520612 4292656556 4292783520 4293246881 4292918961 4292985010 4292916136 4292525234 4292524720 4292788401 4292131772 4292655269 4292722617 4291868069 4292656824 4292525238 4292722608 4292986037 4292591030 4292854202 4292788408 4292920253 4292986036 4292722874 4292722616 4292986301 4293445566 4293051063 4292920251 4292919995 4292657080 4293051837 4293248446 4293775044 4293316545 4292914327 4292055940 4291064160 4289352782 4287375175 4287708496 4288429903 4288563032 4288758873 4290076271 4292315013 4292394675 4294038460 4294501836 4287644488 4283171896 4283501378 4284491334 4284418877 4284750399 4284750142 4284750142 4284814144 4284419385 4284747065 4285144647 4285276233 4285013312 4284487751 4284291908 4285539664 4288762728 4290934415 4292314749 4291985287 4291655291 4291657854 4291593344 4291921799 4292054658 4292384137 4291989124 4292316804 4291989381 4292381566 4292317829 4291988613 4292053631 4292053632 4292053887 4292119424 4292119424 4291659646 4292119424 4292119424 4292119424 4292119425 4292118138 4291725432 4291987582 4292119680 4291987581 4291922046 4292185216 4291593854 4291594101 4292185209 4291724924 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289347409 4289612116 4289676116 4289217363 4289019472 4289745764 4288496208 4289676116 4289807959 4289415252 4290333269 4290464081 4290990423 4292108374 4292571500 4292704358 4293558891 4293166702 4293562990 4293565561 4293565047 4293565303 4293499511 4293565046 4293500286 4293763955 4293497209 4293562222 4293233009 4293228114 4291650146 4289808212 4288756555 4287900743 4287965255 4288884809 4288756559 4288624462 4289217101 4289151571 4289085522 4289741904 4289545032 4289742424 4289742423 4289216338 4290004047 4289283672 4289740877 4289872969 4289414225 4290068557 4290003021 4290266187 4290136136 4289411915 4288823889 4289081672 4288093779 4293372033 4294167194 4294105005 4293897056 4293576863 4293831535 4293570440 4293895019 4293498483 4292836680 4291123548 4293100897 4292045149 4293699443 4292632662 4290072418 4290267990 4291188314 4291126629 4290468456 4291324265 4291584872 4288167258 4289943906 4291190105 4291456624 4291918961 4292310378 4291848555 4291130997 4292047981 4291061101 4290530658 4290208365 4291193457 4291322469 4291390074 4291586411 4290995822 4291062395 4290993761 4291194753 4292184964 4291715941 4292183420 4292511625 4291059835 4288760171 4291332760 4291987854 4291588216 4290274435 4288693347 4288171124 4289288059 4287314520 4285607502 4285800008 4285669458 4285145687 4286400382 4289892523 4291988875 4292972200 4290085797 4288770728 4289234603 4289816211 4287977349 4287981200 4286332536 4286070642 4285413492 4287786139 4285740912 4285213039 4284688728 4286592095 4285343073 4286526565 4284422489 4283568968 4284359234 4282846024 4283898693 4283041865 4282648639 4291006615 4293249731 4292586632 4291918974 4292314740 4292058009 4292524459 4293315507 4293246898 4293312166 4292984754 4292656555 4292523944 4292130476 4292523943 4292920502 4292524720 4292589734 4292656305 4292261303 4292262067 4292590254 4292788401 4292524981 4292854202 4292854202 4292854193 4292788410 4293182641 4292525497 4293117106 4293445557 4293380031 4292788658 4292986303 4292854203 4293380030 4293445558 4292986565 4294038966 4292719785 4292449894 4290278263 4289939281 4287509065 4287704908 4287773008 4288887888 4288035916 4289612640 4289547620 4291462802 4292983712 4293313971 4294106560 4291337873 4282777640 4283501642 4284156733 4283831364 4285079370 4284488516 4284748093 4284817478 4284025649 4284225856 4284615474 4285144647 4285800518 4284422472 4283371088 4284160578 4286660209 4290012551 4292118131 4292119174 4292050825 4291134082 4291919723 4291921801 4292447612 4292057231 4292316546 4292316029 4292777354 4291987325 4292318859 4292316029 4292317061 4292381822 4292053632 4292119167 4292053632 4292382079 4292449414 4292119423 4291922044 4291725439 4292119424 4292119424 4292119424 4291791232 4291397504 4291987838 4292119671 4291725441 4292119680 4291987839 4291922046 4292119673 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289807959 4289348944 4289611863 4289611859 4289677396 4289216594 4289743188 4289414737 4289283664 4290070616 4291317069 4291250264 4291187284 4292106835 4292309611 4293162818 4293297521 4293429101 4293564532 4293565561 4293565047 4293564542 4293566076 4293566595 4293565046 4293500285 4293564280 4293562997 4293296747 4292835683 4292042829 4290335065 4289147979 4287246666 4287442759 4287836233 4288164172 4289411144 4289480267 4289216589 4289348943 4289019730 4289808210 4289742421 4289938255 4289938510 4289479509 4289742424 4289479753 4289871184 4290068563 4289609805 4289546062 4290854222 4289740114 4289480266 4290461521 4289149513 4288750400 4292179558 4294304703 4293833840 4293902483 4293964145 4293771433 4293965686 4293435516 4293430113 4291456099 4293160788 4290856524 4293891178 4292569682 4289810012 4289743704 4290857557 4290665310 4291126374 4291125084 4290994794 4288036426 4290073956 4290601336 4291257975 4292510831 4291192173 4291455081 4291849324 4292504936 4291590256 4289943647 4290997373 4291716447 4290734718 4291585906 4292111465 4290935158 4291126636 4290468701 4291194745 4291917419 4292509063 4291852396 4291193209 4291125366 4289089654 4290082957 4291456116 4291787886 4290076559 4287838306 4288174195 4289945980 4288366179 4287644264 4289942908 4290140540 4287053930 4287386006 4288048282 4288767907 4290474627 4289163422 4289235879 4288902804 4288174214 4285476453 4285213015 4284490841 4284947039 4285675638 4288838584 4287386755 4283961932 4286530169 4285475929 4284355929 4284226108 4284029765 4283697216 4283831875 4283766108 4283698745 4282844227 4283634250 4288510879 4292984499 4292975486 4290868614 4292054919 4292590526 4292723892 4292591029 4293246117 4292984232 4292392874 4292723124 4292523438 4292590769 4292590513 4292722347 4292722090 4292524720 4292655528 4292129705 4292328621 4292394406 4292788403 4292328628 4292330165 4292722358 4292854203 4292788658 4292986045 4292591032 4292919467 4292786867 4292986303 4293182650 4293314495 4293510071 4293380022 4293577926 4293250747 4293047699 4291392104 4290073671 4288625233 4288166214 4288103503 4287708240 4288363344 4288231759 4288560716 4288824154 4289548903 4291725194 4292717739 4292982177 4294104513 4294564042 4285011241 4284033114 4283894838 4284093502 4285078596 4284422722 4284751431 4284619587 4284358217 4284420680 4284881480 4286127173 4285078854 4284881726 4283962181 4283763018 4285010496 4288304495 4291393393 4292117661 4291657596 4291460964 4291785079 4291788441 4292120194 4292383363 4291988098 4292384136 4291989896 4291989123 4292317829 4292381565 4291989380 4292382339 4291991178 4292447358 4292055174 4292119165 4292119167 4291659645 4291987335 4291987335 4291987335 4291791230 4291725439 4292119424 4291856768 4291659645 4291856768 4291790977 4291594109 4292185217 4291725688 4292119683 4292118387 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289217363 4289807959 4289546322 4289546074 4289613392 4289217109 4289677652 4289217364 4290003797 4289609805 4290726997 4291054671 4291644492 4291255131 4292897892 4292311908 4293360216 4293235822 4293629819 4293562738 4293371001 4293564529 4293564279 4293566077 4293564279 4293566077 4293564280 4293562228 4293298286 4292769902 4292635220 4290335819 4288491337 4287964998 4287441738 4287773007 4288885835 4288626001 4288561232 4288693330 4289544274 4289415256 4290003797 4289347660 4289347661 4289545302 4289938510 4289872975 4290068301 4289872976 4289807439 4289807188 4290136397 4290266952 4289611592 4290134094 4289348686 4289017163 4288293202 4290665285 4294500011 4293906085 4293898608 4293771692 4293967986 4293769357 4293829223 4293297760 4292962648 4290924117 4292112479 4291255369 4291913832 4290598747 4290140254 4290731879 4290138201 4290598746 4291719540 4288954448 4290009457 4290204512 4290796920 4291982186 4291520892 4292243320 4291520615 4291390572 4291654509 4289941350 4291192424 4291388781 4291389805 4292047741 4290342011 4290995048 4291455872 4291060325 4290931302 4292637831 4291722606 4292112504 4291719035 4291784563 4288365938 4289815659 4291984265 4291916422 4290143884 4286926970 4290340229 4291392650 4290204251 4289481604 4290608011 4290871459 4289032358 4287315571 4286065523 4286794111 4287188343 4286725233 4288640414 4288569991 4286394988 4285609576 4286069615 4285078095 4284684381 4288309403 4288049294 4284685386 4285148267 4285476983 4285804640 4286530424 4283306827 4283765316 4283633226 4283303732 4283572072 4283503955 4283110996 4287261605 4290876559 4293443745 4292120188 4290080895 4292120478 4292986561 4293117365 4293248440 4293510566 4293048491 4292657589 4292523423 4292524979 4292588958 4292589232 4292589992 4292524720 4292524720 4292591289 4292393902 4292327845 4292262068 4292590512 4292590255 4292591030 4292722352 4292722617 4292854441 4292984501 4292525494 4292854459 4292392357 4292722098 4293774015 4292920245 4293314230 4293579980 4293250749 4291928188 4289744972 4288363849 4287967564 4287051599 4287707726 4288432991 4288756302 4288955986 4288690508 4288824918 4290073949 4289356659 4292055191 4293309344 4293246365 4293841585 4294169764 4287645776 4283105338 4284027719 4283961661 4284683589 4284620359 4285472330 4285273148 4284358218 4284816963 4284619584 4284158263 4285668158 4285341001 4284422473 4283896900 4283632460 4285999194 4289027947 4292117632 4291854965 4291657854 4291590026 4291068032 4292382074 4291989123 4292319118 4292383107 4291988098 4292449672 4291923588 4292775549 4291923076 4292448905 4292054916 4292118653 4292055173 4292447356 4291858581 4291661186 4292184978 4291921542 4291791230 4291791230 4291987335 4291987335 4292119679 4291397248 4292185216 4291725440 4292119680 4292183930 4291331960 4291986553 4292119672 4291921794 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289414743 4289742416 4289676374 4290071378 4289741912 4289742411 4289610575 4289215568 4289676875 4290465371 4290727764 4291054672 4291577925 4292108634 4292766024 4292769903 4293558890 4293233014 4293172080 4293565560 4293563511 4293564542 4293566077 4293565047 4293565304 4293565303 4293564537 4293561457 4293494380 4293162589 4291649632 4289547093 4289279307 4287247693 4287374918 4289017420 4288098379 4289085521 4289414218 4289611603 4289413196 4289608784 4289481289 4290003793 4289742669 4289740876 4289872981 4289807189 4289677142 4289479753 4289872726 4290331721 4289741649 4290003022 4289740878 4289282638 4289870922 4289346639 4289014341 4289210175 4294500537 4293770877 4293905574 4293967472 4293573017 4293836937 4293831798 4293432936 4291254872 4291712338 4290397524 4291458928 4292112740 4290997872 4291122264 4291124834 4290074725 4291192936 4289022293 4289284962 4291384917 4291322995 4292769629 4292047486 4292374115 4291652475 4291653743 4291718250 4290008680 4290731628 4291124826 4290865266 4292113261 4290864495 4291653742 4291062129 4290861681 4290994788 4291783292 4292247915 4291588478 4291914597 4292049805 4289021546 4289686142 4291326359 4291191671 4291058539 4288304506 4290076542 4291324792 4290206067 4289355412 4289025675 4288701561 4286921837 4286855786 4284883540 4286197845 4286591853 4285670753 4286663800 4287585701 4287057795 4287455904 4286791794 4286263159 4287319443 4287785892 4285807714 4285342300 4286994317 4285869667 4284885581 4285351285 4285280105 4284819028 4284029509 4283304254 4283435327 4283369001 4282515522 4285871974 4292524201 4293571976 4290735737 4290737532 4291404198 4293112223 4292394420 4293378211 4293116847 4292720814 4292985008 4292524720 4292590770 4292589735 4292591805 4292196774 4292588960 4292526010 4292787882 4292523943 4292590769 4292195755 4292656305 4292656048 4292195752 4292591031 4292919979 4292525237 4292459445 4292788666 4293313980 4292986296 4293248170 4293314496 4293576894 4293774532 4293776061 4291727711 4288494665 4288624453 4287445070 4288297039 4288363344 4287838032 4288824143 4288889680 4287970123 4288757324 4288826206 4289614440 4291135127 4292973433 4293108891 4293575836 4293644715 4291393378 4285207860 4282975800 4284614463 4284091703 4284683846 4284684349 4285274173 4285013061 4284682813 4284226371 4284617796 4284424782 4285406016 4285668412 4285015372 4284288576 4283501646 4283501373 4287776614 4290670733 4292053638 4291591807 4291985518 4291133823 4292117379 4292053630 4292777353 4292252551 4292317305 4292384143 4291529346 4292907652 4291924361 4292447875 4291989380 4292119684 4292119684 4291726468 4292055172 4292183942 4292578940 4291267204 4292119422 4292119422 4291725440 4292119678 4291921799 4292118393 4291791232 4291725440 4292185216 4291528316 4291987337 4292053629 4291987329 4291528573 4292316285 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289544787 4289742160 4289678169 4289480537 4289546322 4289938261 4289545296 4289610826 4289479504 4290070615 4290528335 4291446344 4291186521 4292108638 4292765786 4292835423 4293165678 4293299056 4293629298 4293564542 4293565560 4293564785 4293564536 4293370226 4293564274 4293566335 4293562737 4293562235 4293232751 4293163102 4291848793 4290399054 4288493647 4287966021 4287377994 4288295756 4288754763 4289806417 4289741390 4289085517 4289478733 4289611088 4289807955 4289086288 4290004048 4289281868 4289676889 4290397773 4290068306 4289740877 4289218387 4290331728 4289807434 4289871441 4289741389 4289674833 4289216336 4288954961 4289145158 4288292421 4294296962 4293906868 4294100344 4293705118 4293967988 4293771676 4293699187 4293493358 4292506459 4291054678 4291189084 4292976778 4291717221 4293232239 4290729566 4291651169 4291453281 4289285487 4289020493 4290665853 4290470506 4291718249 4290994288 4292442986 4291586429 4291457138 4290931324 4290074456 4290471543 4291125857 4290995820 4291980151 4290930287 4291127150 4291061875 4291060583 4290993758 4291391345 4291590014 4292636273 4291652731 4291649898 4289283424 4289684602 4291389576 4290865526 4291062904 4290075526 4288827517 4290016668 4289227933 4288370588 4288109177 4285999707 4285341258 4285077842 4285472342 4285408353 4284619862 4285405763 4286263922 4287913626 4287057288 4288383147 4287054973 4288635807 4287058053 4288774307 4286327656 4288504210 4288508059 4283436337 4285476727 4284224853 4285744491 4287059075 4282910789 4283369789 4283636562 4283173180 4282384469 4287521417 4292001699 4292912004 4290137186 4290273137 4292521901 4293183404 4292457377 4292588442 4292522651 4292523168 4292590513 4292525496 4292589735 4292589231 4292590250 4292587933 4292588449 4292590763 4292587691 4292132015 4292655529 4292589230 4292721065 4292262052 4292262067 4292722359 4292196792 4292788144 4292132795 4292919987 4292854193 4292920253 4293510062 4292852917 4293446340 4294038712 4292983451 4289290851 4287314528 4287575883 4288432990 4288299608 4288366159 4288362832 4287642702 4288691788 4288891218 4289877625 4289945455 4290344068 4292317837 4292648334 4293049273 4293773214 4293710259 4290804847 4282777650 4283631944 4284746045 4284617285 4284618309 4284554051 4284883530 4284947268 4284617278 4285140802 4284424779 4284352823 4285274172 4285405507 4285211465 4284816966 4284355647 4283700811 4284819034 4289289325 4291591551 4291789176 4292249205 4291132291 4291523975 4291987834 4292055689 4292316545 4292317319 4292317576 4292710530 4292448900 4291528317 4292448899 4291990153 4292447357 4292054915 4292449161 4292118909 4292120709 4292119164 4291463825 4292184956 4292119165 4292119444 4292119421 4291725440 4291791231 4291791232 4292119680 4292183930 4291397504 4291856768 4291856767 4291134333 4292185470 4292052872 4291791232 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290071128 4289416539 4290135636 4290071378 4289546329 4289545300 4289347660 4289545290 4289872713 4289873237 4290792271 4291121238 4290989127 4291778390 4292637519 4292442226 4292967514 4293102698 4293627776 4293172596 4293630839 4293564024 4293563768 4293566078 4293564536 4293564529 4293565305 4293563508 4293494123 4292769893 4292241245 4290070610 4289147722 4287313744 4287376966 4289014854 4288165710 4289149261 4289151566 4289151566 4289479245 4289609040 4289806413 4289610826 4289740878 4289808205 4289676619 4289481049 4289545294 4289543505 4289938505 4290068308 4289611597 4289871184 4289740878 4289086794 4290199630 4289349195 4288559686 4288226627 4292975755 4294101912 4293506708 4293969291 4293703049 4294169221 4293633148 4293560159 4292239187 4292372578 4293101424 4292045158 4292577671 4291582289 4291855749 4291125601 4289808221 4289284442 4290138980 4290597985 4291520874 4291715942 4292115051 4291586172 4292047717 4291389819 4290662749 4290077552 4291388022 4291059033 4291521659 4291389029 4291061615 4290931840 4291060853 4291254873 4291917692 4292441194 4291782757 4292507787 4291652195 4288692847 4289356180 4290472842 4291128424 4291458424 4291520901 4289877883 4287976331 4287254900 4285607506 4285540951 4286263146 4286593135 4286201204 4285800280 4284621646 4285408086 4285668937 4286328429 4287782811 4286859889 4288906679 4286593906 4287188612 4284553278 4287055224 4287053693 4287453584 4288638852 4285407330 4286794380 4286533764 4283433554 4285680759 4286337671 4283105333 4283107657 4282712136 4284555099 4288707222 4293184170 4293037691 4289284958 4289487476 4292652452 4292918180 4292984475 4292521879 4292652445 4292259996 4292259233 4292197045 4292656304 4292196269 4292588966 4292588712 4292591543 4292652433 4292193449 4292590762 4292654767 4292195746 4292655023 4291671727 4292328622 4292262829 4292262570 4292264123 4292525237 4292788152 4292656815 4292656824 4292656823 4292657339 4293249982 4292589722 4290608238 4289426314 4289621626 4288756551 4289478738 4288758865 4288952135 4288167245 4288035402 4288822616 4289219685 4290144633 4291461495 4292775806 4293038980 4293107335 4293438362 4293309319 4293906874 4292457360 4283891754 4284027723 4284488252 4284618820 4284487237 4285076547 4284816969 4284881218 4285800007 4284683064 4284551487 4284027709 4284815934 4284883022 4285867079 4285671500 4285279832 4284029526 4284095813 4287381352 4290342018 4291854974 4292380540 4291722370 4290803312 4292184197 4292121224 4292056716 4292318861 4292384396 4291989639 4292318088 4291990408 4292448904 4292316803 4292054664 4292054148 4292121224 4292053890 4292120709 4292120452 4291726468 4292578684 4291529360 4291792516 4291790972 4291792518 4292119423 4292119423 4291725439 4292119424 4291791232 4291922304 4291790976 4291790976 4292185470 4291789201 4291397503 4291659636 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290005334 4289875043 4290728803 4289545044 4289481049 4289674832 4289872724 4289872981 4289807189 4290266709 4290463052 4290266706 4291054676 4291846748 4292240466 4292836196 4293820265 4293036404 4293629042 4293236343 4293237892 4293236861 4293564785 4293565304 4293565304 4293565561 4293562744 4293562740 4293430128 4292836191 4292043601 4290268488 4289151570 4287375432 4287507018 4287770697 4288298321 4288693328 4289282638 4289151053 4289544275 4289480787 4289217610 4289545297 4289806413 4289086544 4290266707 4289938248 4289545047 4289742668 4289740627 4289283917 4289938250 4289610318 4289807434 4290003793 4289545290 4289086030 4289213772 4287768134 4290926396 4294502337 4294098546 4293507224 4293967223 4293700744 4294031477 4292838520 4292971874 4291910206 4290995071 4292183157 4292770154 4291988613 4292043871 4290799470 4289021529 4289353072 4290138197 4291716702 4292441710 4291389800 4291256422 4291852160 4291126118 4290730856 4290076777 4291650933 4290994527 4290995302 4291650678 4292113526 4291127410 4290535010 4290991701 4291787137 4291921270 4291257451 4291064452 4292108897 4291061627 4287901524 4291198605 4291457652 4291652989 4291320946 4288629889 4287117931 4285147733 4285209933 4286920806 4287649425 4287121279 4285609052 4284948560 4284751173 4284749378 4285337429 4285275983 4287714443 4288573083 4288045465 4287388545 4286134630 4283959098 4284817250 4284554048 4287784099 4285740650 4286131814 4287059088 4286532732 4284292415 4283368511 4285484152 4284556117 4283304251 4282712132 4283044426 4290217613 4293179043 4292641384 4289088093 4290212486 4292721316 4292982176 4292917656 4292456088 4292650385 4292127648 4292127901 4292129955 4292655280 4292588967 4292653984 4292588970 4292589212 4292652444 4292194727 4292263338 4292653728 4292196524 4292653740 4292589488 4292721062 4292262069 4292656047 4292197049 4292590773 4292722609 4292459445 4292985529 4292854461 4293249205 4293247395 4289886822 4288169315 4287055977 4289757839 4289622914 4289222260 4288692038 4289544267 4288429407 4288758888 4290142579 4290604914 4291988862 4293171079 4292972414 4292778634 4293039494 4293370256 4293242263 4293645227 4292125831 4284549938 4283892292 4284289348 4284815933 4284682825 4285010224 4285145671 4285341769 4285537346 4284686922 4284550717 4284814398 4284224071 4284681273 4285733436 4284951628 4284878148 4284951141 4284098905 4285015899 4288764281 4291657342 4292249218 4291985777 4291331202 4291133058 4292513406 4291990407 4292318093 4292711031 4291924878 4292054401 4292710531 4292383106 4291989641 4292383106 4292055432 4292447100 4292055432 4292121225 4292053117 4292514436 4291334280 4292120452 4292120451 4291792258 4292052615 4291790974 4292119423 4291792773 4291987079 4292119679 4291856511 4291397248 4292119424 4292119424 4291791232 4291790200 4292184186 4291855751 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289352029 4290791507 4289875802 4290071128 4290201429 4290005849 4290071641 4289872468 4289677131 4289807183 4290135376 4290661968 4291316817 4291845712 4292506475 4292902241 4292771678 4293298028 4293562490 4293630072 4293235309 4293238651 4293630334 4293562993 4293564025 4293564786 4293564537 4293562228 4293622886 4293163356 4292109916 4290269278 4288624204 4287377481 4287443274 4288491593 4288818248 4288626257 4289215307 4289414730 4288888144 4289478733 4289610832 4289938511 4289545295 4289412946 4289479759 4289545040 4289742668 4289545040 4289610837 4289545040 4290071888 4290198608 4290397265 4289218381 4289742413 4289478734 4289020498 4288621641 4288751162 4294235562 4293840291 4294164604 4293307536 4294165891 4293765505 4294029680 4292770662 4291127930 4290927699 4293038202 4291583586 4293166194 4290934898 4289610332 4289085265 4291386968 4291126397 4291721857 4291782499 4292177787 4292048762 4291520623 4289483358 4289617516 4291256943 4290995316 4291387745 4291584377 4291060579 4291061872 4290406270 4291058026 4291913059 4292308854 4291453818 4291851628 4292373861 4291588217 4291128954 4287903854 4291130507 4291848821 4289614959 4287251830 4286327646 4284748381 4284815945 4288306082 4287718295 4284884564 4285211991 4284226371 4285343070 4284419131 4285605735 4283893833 4287380862 4289299629 4288700559 4288440711 4286526832 4284615503 4283959367 4283892275 4288050347 4287122561 4284949071 4287649925 4286995597 4284024638 4283107419 4282974264 4287327648 4286140822 4282515519 4284621653 4290152073 4293506702 4291455844 4290076011 4291593362 4293379778 4292916652 4292917655 4292523173 4292652445 4292127905 4292128413 4292784807 4292195756 4292653475 4292194723 4292130213 4292325540 4292261281 4292194203 4292719256 4292194460 4292654241 4292195764 4292655281 4292588188 4292261564 4292262306 4292590512 4292591029 4292525237 4292854187 4292919999 4292986282 4293578156 4291401341 4286458961 4286200669 4287257211 4288698248 4290281620 4289561747 4290737782 4289945467 4290277506 4291654239 4291858048 4293170556 4292974463 4293565312 4293235326 4292645770 4293429627 4293304719 4293173891 4294038200 4292124038 4284219433 4283632456 4284288839 4284616509 4284619070 4284750655 4285145159 4285146191 4285076795 4285276747 4285209404 4284488782 4284420926 4284155961 4284878643 4285406533 4285866569 4285672270 4284161607 4284357445 4286656084 4290538362 4291920768 4291855732 4291657855 4291392627 4291460729 4292447358 4292319622 4292317063 4292253326 4292579200 4291990413 4292319620 4291988616 4292186998 4292318089 4292055175 4292057231 4292383106 4292119426 4292122249 4291660674 4291986566 4292448387 4292120451 4291529360 4291856509 4291790976 4292119680 4291528060 4292185215 4291790975 4291858310 4291856511 4292119424 4291790976 4291856767 4291659145 4291658359 4291331710 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290465882 4289743704 4290070865 4289480536 4289480792 4289742165 4289676630 4289676878 4289872725 4289413974 4290004557 4291182407 4291776598 4291385687 4292306020 4292442465 4293427306 4293036153 4293564275 4293564023 4293237373 4293236845 4293171322 4293566334 4293564023 4293564025 4293564536 4293561984 4293691755 4292769121 4292175711 4290268236 4288691537 4287376454 4287508039 4287837004 4288164939 4289213771 4289283150 4288953680 4289348950 4289676617 4289543504 4289938517 4289742418 4289742675 4290068300 4289479760 4289938256 4289545039 4289349459 4289740877 4289740621 4289217102 4289872970 4290002771 4290201939 4289742663 4289215563 4288623948 4288093515 4293367916 4294234528 4293507736 4294033017 4293700229 4293969803 4293433459 4293765000 4292906862 4291062648 4292109913 4292774784 4291189332 4291323491 4289743445 4290270818 4291123568 4292111971 4291849065 4291717996 4292044643 4290536554 4290332755 4289612638 4291126391 4291060836 4291586419 4290996849 4291126890 4290535785 4291059557 4290796888 4289548918 4291395211 4291586682 4291784569 4292242555 4292242786 4292444553 4291851400 4289021290 4291128958 4289879404 4286000735 4285603932 4284421457 4286134898 4288504472 4285741147 4284157758 4283964233 4284220484 4285343819 4284486984 4284615761 4284292180 4283958840 4288374687 4288634502 4288897411 4286395488 4283897918 4284881491 4284287815 4287718818 4288507799 4285143898 4286596745 4286860407 4284357451 4282909242 4283833168 4282974276 4286999960 4285015136 4285675621 4291796630 4293439893 4291653221 4289088871 4291661967 4292657582 4293051058 4292458659 4292587166 4292195487 4292127638 4291668119 4292259493 4291670951 4292784038 4292195220 4292783524 4292127125 4291999391 4292718494 4292717731 4291671458 4292719782 4292194730 4292653984 4292196255 4292654505 4292262565 4292262068 4292590254 4292722873 4292657083 4292986289 4293317299 4291533175 4286197573 4286263384 4287057269 4286987872 4288961912 4287778402 4289427343 4290017171 4292248971 4293170047 4293758325 4293103486 4293891458 4292972673 4292974458 4292971391 4293368452 4292973701 4292909704 4293568654 4294104498 4293441947 4283761455 4283107395 4284419128 4284812606 4284619326 4285603397 4285669446 4285473611 4284488517 4285537604 4285274687 4284747321 4285144389 4284225854 4285603138 4284881734 4285669447 4284748597 4284156221 4283635277 4284422731 4288633466 4291131520 4292117618 4291657599 4291855504 4291327855 4291986807 4291991696 4292711806 4292251527 4292318604 4292253324 4292318603 4292318347 4292318861 4292318088 4292383112 4292053881 4292053635 4292448899 4291727241 4292119426 4292122249 4292120451 4291726468 4291726468 4292578685 4291792518 4291790974 4291725183 4292185990 4291790975 4291790975 4291856511 4291857542 4291791230 4291922304 4291463040 4291725181 4291725438 4291593850 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290465882 4289286493 4290070871 4289415000 4290071128 4289415000 4290071642 4289479246 4290136402 4289807692 4290201168 4290922574 4290399560 4291909212 4292437333 4292834908 4293164144 4293495916 4293562477 4293566592 4293629290 4293564799 4293563767 4293564529 4293564799 4293564786 4293564274 4293563258 4293231211 4293163361 4292109916 4290268240 4288560464 4287963978 4287376967 4288558412 4288757841 4288624462 4288691789 4289677389 4289085522 4289085523 4289413708 4289740883 4289479503 4289742412 4289677139 4289938255 4289546831 4289610832 4289545290 4290004048 4289545296 4290068557 4289348433 4290201426 4289741392 4290003792 4289086286 4289148235 4288226885 4291655529 4294369737 4294164598 4293504912 4294167960 4293897334 4293840017 4293301876 4292641145 4293569148 4291914604 4293107836 4291584613 4288887888 4290138991 4291127145 4291651937 4291589504 4291717494 4292901237 4291128961 4289808202 4288758636 4291847264 4291388005 4291060838 4291256692 4291321454 4291127147 4291060086 4290666853 4290598240 4290346130 4290012791 4287647092 4287641420 4289480020 4291915153 4293099641 4291587453 4288760927 4288169830 4285473627 4285741162 4284685651 4286268522 4287911290 4284685120 4285081959 4284354372 4283829815 4285606226 4285541215 4283958072 4284421461 4284682575 4286465907 4289366197 4285474641 4287052143 4284421183 4284484411 4284882266 4288112807 4289166751 4286922621 4286792308 4287589023 4283564092 4283039786 4285941651 4283170860 4283111743 4287191458 4286137449 4292451994 4293370508 4290402131 4289684337 4292189855 4292654488 4293639329 4292591535 4292653206 4292062879 4292781729 4292388768 4291669171 4292128166 4292784286 4291735190 4292192920 4291602594 4292522910 4291667865 4292194458 4292128929 4292128678 4292653483 4292588453 4292589731 4292591285 4292588967 4292588453 4292591289 4292788659 4292524721 4293248678 4293114527 4286592830 4286329424 4283433535 4286528863 4289297293 4287977854 4288174711 4288041849 4288440190 4290217616 4291857543 4292973961 4293037696 4292973694 4293300848 4293235586 4293693049 4293299845 4293237887 4293239713 4293570961 4294432416 4293048480 4285207088 4283238464 4284419134 4284222271 4284748862 4285078598 4284683063 4285274432 4285211465 4285210438 4285144902 4285080913 4284878385 4284485440 4285011256 4284160070 4285143868 4285538124 4284687694 4284223315 4284621641 4285605214 4290339959 4292053637 4291723391 4291985775 4290541181 4291722878 4292448645 4292318084 4292251528 4292319366 4292318590 4292317065 4292319363 4292253844 4292317053 4292383113 4291988098 4292383880 4292383880 4292053891 4291725699 4292119940 4292118909 4292054916 4292119684 4292119938 4291726724 4291790717 4291989136 4292120196 4291790718 4291397247 4292252294 4291396991 4291856766 4291658888 4291463038 4291922304 4291855482 4291855750 4291527557 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289808471 4290595927 4289941339 4290005335 4290530648 4290136150 4289676623 4289283672 4290396750 4290006096 4289872464 4290658890 4291119952 4291845727 4292699482 4292835163 4292968558 4293233782 4293430651 4293237101 4292844418 4293631094 4293566077 4293565304 4293565559 4293564025 4293564280 4293560432 4293691756 4292768865 4292307796 4290205018 4289150800 4287311430 4287574602 4287246153 4288756046 4289414221 4289085008 4289151565 4289610316 4289151571 4289413203 4290069577 4289938513 4289347405 4289545045 4289545039 4289413203 4289543504 4289806413 4289349459 4289152080 4289872971 4290201158 4289480276 4290463816 4289415511 4289676361 4288888914 4289015368 4289672516 4294300822 4293772707 4293972387 4293699180 4293906073 4293762413 4292969335 4293374096 4293430643 4292843642 4292504407 4291257696 4288952140 4290732392 4291321436 4291782259 4292243322 4292113247 4291256939 4290796638 4289747051 4290340209 4290536804 4291125600 4291127406 4290469743 4290075747 4291192940 4290601834 4290466647 4291917181 4291915626 4292504932 4292376170 4291127423 4288369530 4286657875 4289022057 4291060077 4288892013 4285539409 4284949842 4285213272 4286662004 4286656616 4285147993 4285407842 4285145668 4284880472 4285605207 4286593899 4283698237 4284221507 4284287298 4285540951 4287583619 4287976589 4284485950 4285734484 4285144396 4284553821 4287255172 4287784071 4285212510 4288637096 4287919532 4285210706 4282384440 4286009998 4285419406 4282581050 4284821873 4290153630 4292127390 4292116323 4290009178 4290798191 4292450453 4292789432 4292456855 4292985005 4292721066 4292194717 4292783772 4291798172 4292191903 4292325777 4292391338 4292259995 4292192929 4292457365 4291734171 4291864212 4292326050 4291924365 4291932320 4292260521 4291933616 4292654504 4292129436 4292980648 4292523423 4292525492 4292722348 4292589217 4292790712 4290875497 4283105333 4284683074 4288765053 4287253610 4285798989 4290941069 4288967830 4287647083 4289885075 4287252592 4290214268 4292251809 4292644987 4293103488 4293300863 4293237639 4293628537 4293172868 4293238660 4293634197 4293505954 4294497695 4293248413 4285336881 4283106366 4284420936 4284617285 4284748863 4284619327 4285208124 4285144648 4285079623 4285667644 4284684864 4284684607 4285668675 4284423237 4284355391 4284684864 4285274430 4285732413 4284947780 4284357956 4284553801 4285012288 4287710049 4290737270 4291330687 4291197054 4291786368 4291788926 4291922300 4292318345 4292711822 4292252294 4292319364 4292318607 4291792756 4292253071 4292777341 4291990159 4291793013 4292383625 4292318087 4292055176 4292056191 4292448649 4292055688 4291726468 4292513668 4292120450 4291725201 4292054670 4291856508 4291790717 4291791492 4292185733 4291790975 4291790718 4291858310 4291790974 4291922558 4291658631 4291858309 4292053372 4291857024 4291396989 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290399319 4289217879 4290005335 4290005335 4289546840 4289806418 4289676631 4290003795 4289611608 4289806927 4290201932 4289611860 4290070858 4291777105 4292109132 4292834421 4293360982 4293494638 4293236336 4293237116 4293631868 4293562230 4293565571 4293564534 4293564542 4293564529 4293566590 4293563514 4293232494 4292770659 4292636264 4290793293 4289082443 4287375431 4287505738 4287967562 4288753736 4288625998 4289085264 4289085008 4288758352 4289151564 4289479245 4289347661 4289413198 4289217610 4289808211 4289612618 4289543505 4289938762 4289282126 4290004048 4289543504 4289477712 4289940566 4290134094 4291120729 4290004812 4289807955 4290069834 4288429390 4288688724 4291719762 4294437839 4293835649 4294104733 4293965174 4293173648 4292839017 4293567871 4292781714 4293366637 4290665055 4288754762 4290466137 4291651691 4291717760 4290862943 4291125853 4291324546 4290796121 4289083733 4290604161 4291126371 4291256691 4291257723 4290535012 4290797667 4290076004 4291321967 4290598251 4291455337 4291849065 4292311660 4292704648 4291653767 4288828015 4288096319 4289221747 4287576171 4285801554 4286267495 4286006136 4285606752 4287119995 4287057536 4285609060 4285936743 4285605466 4284289881 4285539909 4288505499 4284357191 4283827771 4283762758 4284748384 4287188615 4285741146 4286791276 4284287292 4284749126 4285011022 4284884041 4287916439 4286325345 4287057278 4287454602 4285805408 4282843191 4286529675 4288189629 4283698245 4282056772 4287984303 4291800494 4291985782 4288762223 4290404724 4291207587 4292984992 4293378480 4292852393 4292849319 4292589745 4292129194 4291866782 4291733656 4291867304 4292849298 4291600798 4292391323 4292259232 4291863445 4291732376 4292520348 4291928978 4291801253 4291994258 4292063911 4292327596 4292654252 4292656563 4292130990 4292587429 4292982188 4292722083 4292523429 4289747524 4285996869 4285404741 4284157497 4287909733 4289948032 4286263905 4287514207 4290288274 4288895360 4288903559 4289420920 4288638595 4290480274 4291592575 4292446848 4293761407 4293171589 4293566590 4293567378 4293566847 4293571221 4294891427 4290671189 4285140266 4283503421 4284287028 4284287801 4284747322 4284813113 4285208895 4284818254 4285142331 4285013062 4285669190 4285210184 4285408330 4284552764 4285339977 4284683314 4284944186 4284553535 4285342283 4284683579 4284160588 4284554059 4285474906 4288699000 4290868865 4291593075 4291396480 4290998639 4291657342 4292447615 4292318848 4292252797 4292319380 4291989127 4292319363 4292317839 4292776583 4291925374 4292385171 4292383367 4291991167 4292383368 4292055935 4292120713 4292055417 4292448132 4291726468 4291726467 4292121993 4292118908 4291792258 4291595669 4292185731 4291792260 4291726725 4292119167 4291792518 4291790717 4292054158 4291397245 4291922559 4291856767 4291395974 4292119165 4291265661 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290925402 4290466138 4289875546 4290006618 4290005079 4290005593 4289482326 4289348944 4289938255 4289742669 4289218132 4290331467 4290725706 4291646039 4292044643 4292899918 4292968303 4293301362 4293629306 4293564784 4293564541 4293563260 4293565559 4293565303 4293498749 4293565560 4293564798 4293561965 4293691500 4293096541 4292438119 4290400334 4288755784 4287375946 4287506503 4287901769 4288756302 4288691793 4289085265 4288823882 4289217101 4289544788 4289413196 4289806419 4289741388 4289543504 4290002512 4289346123 4289741389 4290069585 4289545546 4289675342 4289677133 4289872713 4290594899 4290594124 4289808210 4291053385 4289874005 4289872720 4289283659 4288885066 4289477698 4294363532 4294105530 4293836163 4293907110 4293634695 4292575079 4293302409 4293565798 4293175189 4291784546 4289017421 4291783783 4291587687 4291389287 4291520871 4291191160 4291257440 4289678678 4290205806 4291584609 4291322990 4291191930 4291125613 4291190873 4290206071 4291518831 4291124336 4291650414 4292311162 4291650933 4292043885 4290401109 4289352043 4287839588 4285147225 4284945722 4285669459 4286661234 4285610877 4285996874 4286532727 4286661487 4285805926 4285279078 4285342546 4283434053 4284221491 4288177573 4287053926 4283695933 4283895110 4284155976 4285083992 4288174208 4286003046 4284617292 4284289607 4284682818 4286394481 4286786393 4286197346 4284552777 4284950624 4287783061 4283893582 4283564103 4288323767 4286803107 4282581031 4285016694 4291604659 4289550699 4288961131 4291062639 4291997608 4293376946 4293115052 4292787120 4292523681 4292588969 4292261285 4292392871 4292259744 4292130204 4292258717 4291668905 4291931813 4292456867 4291666848 4292326041 4291991964 4291732117 4291734956 4291995285 4291995292 4292391587 4292327597 4292327340 4292196268 4292654497 4292590245 4292129179 4292519329 4292448903 4289876838 4287048279 4287774559 4288171375 4286325320 4287648622 4288700275 4286793327 4288635511 4289759386 4288304750 4289231002 4288171371 4291003787 4291921552 4292905846 4293300357 4293627774 4293566076 4293499264 4293837998 4293907610 4288368195 4283629620 4284091974 4283961918 4283960378 4284421442 4284879162 4284945988 4284813874 4286190658 4284752972 4285670734 4284686404 4285935695 4285210438 4284554053 4284291389 4284550976 4284420416 4285404215 4285341001 4284883017 4284422206 4285276742 4286591575 4289817202 4291197057 4291129969 4291065728 4290274684 4292250245 4292317576 4292253069 4292646031 4292121721 4292318606 4292318349 4292318591 4291991686 4292384142 4292316288 4292383885 4291989383 4292384397 4292383623 4292055175 4292054665 4291988355 4292514432 4291660675 4292513667 4291661189 4292118909 4292120707 4291725182 4291726725 4292119166 4292119424 4291790717 4291858053 4291790716 4292120721 4291593086 4291856768 4291790717 4291265661 4292251008 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289809754 4289873751 4290531674 4289942364 4289877342 4290726228 4290071128 4289481050 4289740626 4289675085 4289938507 4289740869 4290265163 4290992978 4291911757 4292899169 4293428844 4293035893 4293563255 4293565054 4293565301 4293565315 4293564272 4293500286 4293763956 4293498738 4293565047 4293561979 4293231467 4293098338 4292438376 4290333770 4289148236 4287377738 4287573831 4287902284 4288822095 4288687687 4289281355 4289217358 4289347152 4289478732 4289676373 4289545300 4289740883 4289938512 4289480010 4289740877 4289938512 4289479759 4289543505 4290069069 4289938511 4289282646 4290661201 4289677141 4291055697 4289743183 4290072149 4290069837 4290004551 4289086543 4288685382 4291124559 4294170785 4293906865 4293903754 4293701502 4293175954 4293630069 4293176727 4293506429 4291125591 4290077551 4291651167 4291847796 4291258745 4291126913 4291126110 4290138721 4289681010 4291258213 4290995820 4291389294 4291125599 4290536297 4291059306 4290994822 4290075991 4291060851 4291916403 4291912838 4289811821 4288961403 4290139777 4290143340 4289811056 4289615739 4287514733 4288104047 4285408339 4285538128 4286397051 4287058292 4284816985 4284291658 4284092995 4283697223 4284420959 4287118456 4288904863 4285609070 4283500337 4283894604 4283960646 4285608299 4288174721 4286067303 4284287292 4284816451 4285670495 4284554047 4285931094 4284094548 4283830847 4286598255 4287059849 4283498573 4283962181 4288387268 4284883039 4287188863 4289364391 4287909486 4288958312 4288832911 4292524737 4293310870 4292985003 4292851123 4292524200 4292591028 4292260002 4292326052 4291866524 4291800746 4291733665 4292257438 4291669933 4292522393 4291866528 4291995541 4292120970 4291662997 4291799969 4292260256 4292324253 4291277224 4292392108 4292458148 4291540133 4292720304 4292194457 4292453021 4293113254 4293441189 4293174184 4292775817 4289281354 4287114317 4287510607 4288766343 4286788693 4287448930 4287517297 4287117924 4290020490 4289095558 4288701053 4289088369 4289557122 4291659163 4292969868 4293105293 4293566847 4293504412 4293973150 4294359937 4286980665 4283435332 4283896114 4284356934 4284682822 4284417850 4284880954 4284879154 4285472325 4285472583 4284552247 4285866826 4285537861 4286063437 4285012027 4284289342 4284420663 4284815945 4284748863 4284812855 4285342283 4284751688 4284358216 4285475423 4285867351 4288106344 4290342520 4290409844 4290278006 4290275441 4290540914 4291856767 4292385157 4292253573 4292646772 4292646031 4292318589 4292318606 4292186999 4291990146 4292317831 4292383880 4291989639 4292382855 4291988871 4291989639 4292383885 4292383103 4292382339 4291989128 4292449672 4292054659 4292120451 4291729039 4292120200 4292119940 4292512893 4291727498 4291725181 4291988365 4291791491 4291856510 4291462782 4291922560 4291856768 4291265916 4291592838 4291659645 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290465882 4289875546 4289875290 4290006618 4290201172 4289349464 4289480792 4289938003 4289742674 4289742675 4289740878 4289675854 4290069323 4291381324 4292306271 4292506203 4292706417 4293299310 4293561726 4293561979 4293171324 4293566849 4293565052 4293566077 4293499254 4293499511 4293564031 4293563763 4293494381 4292769617 4292110429 4290795090 4288557387 4287441482 4286982983 4287969101 4288360776 4288166993 4289216593 4289085008 4288953936 4289546066 4289019729 4289676373 4289610825 4289545290 4289609041 4289938518 4289872975 4289740883 4289741388 4289675340 4289413974 4290595918 4290135126 4290398797 4290202715 4290267470 4290266702 4290398031 4289611091 4289871949 4288954961 4287964744 4293107047 4294237102 4293905311 4293634428 4293901959 4293438350 4294029424 4292969849 4289012543 4292842862 4291977570 4290926939 4291060838 4291127402 4290731371 4290206572 4290534765 4291060079 4291389036 4290993773 4290609561 4290932132 4290800270 4290669449 4290138519 4289881480 4290798220 4291390084 4291980158 4291190888 4291585131 4288955731 4287774300 4289151586 4288428900 4286589790 4285870449 4287381367 4287912303 4287054964 4285146449 4283635785 4283894090 4283762502 4284748873 4286792312 4289167271 4285010235 4283697222 4284093511 4284879679 4285739879 4286722657 4285806701 4284881222 4284748106 4286260813 4284419901 4284095554 4284748362 4283565118 4286795654 4286727804 4283170889 4286207373 4287590581 4288964498 4291400859 4288772258 4285735503 4290077307 4289895598 4293179296 4293180328 4292458147 4292523938 4292590250 4292720816 4292259487 4292325545 4292456859 4291799193 4291799705 4292259222 4292324245 4291800998 4292323484 4291862433 4291468693 4291209378 4291998372 4292457379 4291670187 4291997602 4292458405 4291538858 4292127133 4292521369 4292388502 4293440701 4293307568 4293244601 4293374374 4292974481 4291649645 4289216077 4286723935 4286852173 4289558941 4287976819 4288172144 4287979140 4288964223 4289366168 4289425292 4288834181 4290080135 4291266434 4292774535 4293698945 4293640351 4294300559 4292573019 4285929529 4283829309 4284093501 4284616006 4284026174 4284812863 4284813625 4285471557 4285670737 4285275202 4285602365 4285273145 4285407300 4285012285 4284946748 4285801032 4284684605 4284620358 4284684606 4284681017 4284947782 4285538114 4285012290 4284947273 4285408338 4286657625 4289289338 4290215544 4291325566 4289883765 4289096054 4291523980 4292120967 4292318603 4292646800 4292253587 4292318347 4291990926 4292383623 4291988873 4292383609 4292383625 4291988857 4292317320 4292712063 4292318849 4292318073 4292382855 4292055432 4292055688 4292119426 4292119427 4292056457 4292118653 4292118909 4292120451 4291727240 4291727241 4292120451 4292119167 4292120964 4291857795 4291858826 4291528575 4291463040 4291856768 4291922560 4291463040 4292119165 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289809754 4290400346 4290531417 4289350746 4289676373 4290071385 4289610839 4289481037 4289544783 4289808211 4289545290 4289478225 4290462794 4290857548 4291781977 4292964192 4292704096 4293496432 4293630328 4293565827 4293630837 4293565058 4293566850 4293564015 4293501060 4293764474 4293499250 4293562740 4293624429 4293099125 4292110420 4290857809 4288560721 4287376966 4287572039 4287967562 4288360009 4288756302 4288624202 4288562000 4289282636 4289480281 4289546065 4289217620 4289413203 4289478734 4289217866 4289545296 4289543504 4289545295 4289938517 4289677142 4289742417 4289282133 4290070603 4289939288 4290726995 4291251795 4291252313 4290793815 4289941330 4289415498 4289477451 4288819529 4290200400 4294368693 4293769608 4293443216 4293702786 4293700992 4293771925 4291124829 4290734188 4293295212 4290795613 4291121744 4290994799 4291123576 4290270047 4290537333 4291323003 4291584862 4291521919 4289946498 4290995327 4290928222 4289679977 4289880972 4289883529 4290079368 4288634503 4288893315 4288701337 4289814404 4288759922 4286527084 4285407826 4287971181 4285868892 4287317100 4287315815 4287778680 4287255441 4286000223 4284292163 4284422747 4284225096 4284157253 4284749393 4287520648 4287979396 4284091972 4283961669 4284879941 4287586452 4284547901 4284227400 4285340227 4285342545 4285867362 4287187570 4287778206 4287187839 4287386514 4286129250 4288048807 4285938050 4285606500 4287389854 4287322503 4289291655 4289819024 4287585686 4288766088 4291932340 4291994796 4292654241 4292914849 4292195742 4292719007 4292130220 4291539373 4292784532 4292194463 4291733408 4291734425 4292061091 4291798952 4291734683 4292322452 4291732376 4291403679 4292061342 4292321435 4291932075 4292456870 4292325789 4291734950 4291538088 4292587426 4293505179 4293307555 4293767866 4293572006 4293574575 4293574819 4293700505 4292259475 4292703852 4290530388 4288691797 4287510363 4287052106 4289627298 4288170599 4286988398 4286787652 4290412161 4289428618 4289623192 4289687432 4291395975 4292581023 4293965463 4293239155 4288757065 4284287806 4284222781 4284486725 4284356164 4284291140 4284881726 4284418104 4285535808 4285603390 4284882501 4285998668 4285537351 4285012541 4285013831 4285668423 4285471811 4284750658 4284551486 4284351294 4285274944 4284945203 4285732413 4284949580 4284424010 4285146185 4285540188 4287709276 4289687932 4291065972 4290015350 4289357676 4290408823 4291200120 4292515724 4292253585 4292712338 4291925890 4292188290 4292054904 4292318088 4292382855 4292055950 4291991180 4292383624 4292318093 4292253325 4292316547 4292383112 4292056200 4292054399 4292120199 4292121224 4291659907 4292513411 4291662472 4292119684 4292120451 4292119683 4292119683 4292120452 4291726716 4291790719 4291398533 4291922046 4291462783 4291922304 4291856769 4291594110 4291922806 4291461766 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290333527 4290334810 4289811292 4290595927 4289349464 4290331731 4290529357 4290071387 4289742417 4289347404 4289479246 4289477450 4289346897 4291054155 4291716451 4292572512 4293099629 4293496694 4292971631 4293630332 4293172857 4293630838 4293564284 4293566077 4293564789 4293500285 4293564786 4293562484 4293232751 4293098587 4292701800 4290072400 4289147979 4287375175 4287506760 4287966278 4288363600 4288755018 4289217105 4289085264 4288953680 4289348937 4289281360 4289478739 4289610825 4289413197 4289609041 4290004298 4289545290 4289349459 4289675090 4289938505 4289413711 4290531156 4290529874 4290201940 4291120205 4290072412 4290074712 4290923603 4289743700 4290791250 4289741904 4289152076 4288554320 4293832584 4294369989 4293772192 4293638018 4293834357 4293840283 4292242804 4293363550 4291123810 4291124821 4290599004 4290862950 4289874772 4289219690 4290797665 4291258211 4290865025 4290864742 4289940072 4290335315 4289152358 4290798466 4292045163 4291979628 4291780472 4292045961 4291195767 4289092993 4287907950 4285014612 4285867090 4287248998 4285342550 4287642477 4287379304 4286725996 4287188094 4286856543 4285674332 4285080916 4285604687 4284097358 4283500616 4285801832 4287052647 4286990976 4284882772 4284948560 4285999955 4286201447 4284418878 4284554307 4284488515 4284226887 4285211471 4284747578 4285343055 4285211978 4284421189 4284618826 4286991736 4285015634 4285935465 4286595953 4286859152 4287056770 4289433014 4288501645 4291539622 4291725986 4291995306 4292258192 4292651669 4292127638 4292127398 4292326815 4292456858 4292389019 4291926427 4291731094 4292649625 4291144102 4291863959 4291990672 4291930005 4291995285 4291864483 4291798166 4292321694 4291799454 4291209126 4291667110 4292062628 4293178540 4293440944 4293243824 4293637801 4293179562 4293571753 4293574318 4293574318 4293573556 4293703093 4293300615 4292501607 4289870411 4287183955 4286392929 4284751668 4289886868 4287051857 4286003817 4286464101 4290151068 4289558920 4289492872 4290740626 4292646806 4292046180 4289943647 4286325578 4284023612 4284483653 4284355141 4284356676 4284288836 4284552773 4285078854 4285207864 4285141816 4285603655 4285472325 4285144126 4285603912 4285406787 4285406786 4285474638 4284814391 4284419392 4284226112 4284945721 4284487742 4285472325 4285012546 4284420680 4284882774 4286327886 4288697966 4290082156 4290146946 4290013045 4290015093 4289950082 4292447614 4291991699 4292386177 4291990653 4292384659 4292056978 4292055692 4292317831 4292383373 4292055934 4292448137 4291793788 4292383615 4292317832 4292383097 4291989128 4292054658 4292449407 4292056206 4292119943 4292121224 4292054402 4292122510 4292119938 4291728009 4291792003 4291792260 4291726468 4292120709 4292119166 4292185733 4291332741 4292251525 4291397248 4291791223 4292119165 4291527047 4291528831 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290333527 4290335065 4290465123 4289808727 4290071128 4289940307 4289611095 4289676880 4289938261 4289610832 4289283146 4289086286 4289543249 4290728014 4291321951 4292439111 4292772210 4293100652 4293431923 4293564290 4293237634 4293172084 4293566076 4293565563 4293566594 4293565820 4293565304 4293564281 4293689965 4292705635 4292176484 4291319120 4288625996 4287376967 4287572039 4287312202 4288556872 4287575118 4288691792 4289016650 4289807952 4289413203 4289611087 4289413196 4289545296 4289610834 4289347666 4289609039 4289740883 4289545295 4290004048 4289609805 4289872975 4289741397 4290724941 4290859099 4290660172 4290663003 4291384410 4290073430 4290596179 4290005586 4289676876 4288953936 4288556623 4293763958 4294104227 4294104487 4293574548 4293638788 4293572754 4293372788 4291914086 4290337372 4291322489 4291128185 4289547091 4289348178 4290337636 4290537854 4291322485 4291060339 4290797922 4289811317 4290073449 4291588720 4292374904 4291717493 4291190634 4289547391 4288759377 4292375421 4291323771 4289220477 4286195541 4286065513 4285346142 4284750677 4285212237 4286127195 4286593633 4287384702 4286922352 4286066284 4285342540 4283766084 4283963475 4285145168 4285805412 4285474909 4286658411 4287515770 4286466178 4285146701 4284027196 4284618318 4284748092 4284748606 4284813628 4284488258 4284555340 4284356155 4284487740 4284157250 4283565127 4285215854 4285671516 4287583864 4285678193 4285080953 4286205059 4288175246 4288247198 4289493641 4290745240 4292125069 4292784799 4292122775 4292390299 4292127654 4292849570 4291732898 4291534994 4291403422 4292252040 4291277226 4292649355 4291533721 4291930260 4292322474 4291928476 4292061074 4291403425 4292061846 4291794824 4291602098 4292983972 4293440175 4293706158 4293241769 4293245356 4293570475 4293571765 4293573284 4293572785 4293572786 4293573031 4293574305 4293303942 4292901753 4290856525 4289018444 4286656082 4285209673 4285999955 4288174464 4287907938 4284618062 4289558915 4289753241 4290477701 4290478489 4291135367 4291193964 4290073179 4287834697 4284221501 4284549190 4283896631 4284091967 4284484925 4284683070 4284881732 4285667908 4285275460 4285735753 4285669960 4285079370 4285535802 4285211209 4285013830 4285143613 4285077056 4284354106 4284614963 4284619328 4286194254 4285471299 4284488256 4284752723 4286129483 4286987879 4289819515 4290869378 4290474612 4289292909 4289880181 4291066238 4291398532 4292843149 4292319108 4291989901 4292384899 4291990909 4292383117 4292384644 4292059527 4292054665 4292055925 4292120713 4292055950 4292384396 4291990406 4292382855 4292054664 4292055432 4292448382 4291990670 4292447875 4292055432 4292121479 4291990664 4292447618 4292121480 4292119674 4292120197 4291725182 4292120965 4291725184 4292184950 4291790719 4291856511 4292185217 4291659645 4291331453 4291725181 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290399063 4289939543 4289875802 4290530391 4289349464 4290201429 4289415251 4289938261 4289479759 4289610832 4289479245 4289542478 4289084742 4290792789 4291779155 4292637534 4292772208 4293362024 4293431930 4293563260 4293631868 4293628273 4293564284 4293565819 4293565563 4293565820 4293565303 4293562489 4293035635 4293097064 4292636246 4290596434 4289345352 4287309639 4287441223 4288689226 4287181388 4288820042 4289414227 4289215568 4288888143 4290069845 4289806161 4289349458 4290003796 4289545044 4289808215 4289217620 4289806418 4289806419 4289086793 4290068563 4290201426 4289349710 4290399829 4289873231 4290663261 4291254356 4290072412 4290857041 4290205537 4290333774 4290200912 4289281869 4288554827 4293238151 4294171574 4294037666 4294101907 4293770631 4293705083 4293757799 4290926684 4291126374 4291124827 4291190875 4290664311 4290073975 4291518832 4290535542 4290861655 4290141548 4290073191 4291455609 4291982700 4292570230 4291585379 4291452269 4291455365 4289743964 4288239216 4290206819 4288889430 4288691031 4286722132 4286002544 4285605201 4285209685 4284946005 4283830616 4286525800 4286396511 4286461280 4285933660 4286791793 4285673060 4285278289 4284289364 4287055487 4284024397 4286070401 4287914380 4288436105 4284882517 4284024651 4284683572 4284622159 4284419899 4284424267 4284685122 4284884559 4284353859 4283898176 4283698759 4283827764 4285938535 4289616260 4289090932 4287642466 4285610099 4287789493 4288841640 4290156447 4291927451 4292514441 4292126624 4292127131 4292127901 4292128947 4292456856 4291340447 4291402652 4292648591 4291859593 4291403165 4291864481 4291732136 4291799960 4292325538 4291928467 4292189325 4291797678 4291865250 4291465875 4291863467 4293244064 4293308320 4293638578 4293508526 4293573286 4293571752 4293573298 4293574573 4293572786 4293507249 4293573029 4293572258 4293571999 4293699729 4292836983 4291446872 4290068303 4287574346 4285539667 4283302972 4286266455 4287910510 4286787161 4286987865 4289821328 4290080888 4290678683 4291921798 4292049271 4290139228 4286190915 4284619582 4283829054 4284549190 4284681021 4284355660 4285207354 4285668936 4285277772 4286062403 4284814139 4285933389 4285930816 4285868622 4285540430 4285733958 4284618813 4284486975 4284486969 4284419657 4284419891 4285077565 4285274172 4283898700 4284948039 4285737304 4288763254 4290602611 4290540660 4289228921 4290404974 4290212213 4291396986 4292186245 4291990404 4292318605 4292384914 4292252043 4292383374 4292319364 4291990668 4292055429 4292449159 4292055951 4292055176 4292055935 4292382600 4291991168 4292384399 4292055934 4292120712 4291989639 4292448904 4291593588 4292121993 4292054402 4292842631 4291990151 4292118672 4292121481 4291725182 4292120708 4292120452 4292120700 4292120710 4291792261 4291792517 4291790976 4291856768 4291922561 4291724671 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290008156 4289348951 4290005592 4290530391 4289414743 4289941595 4290071129 4289413959 4290133838 4289545290 4289347153 4288952653 4289020499 4290269527 4291190108 4292636764 4293098345 4293102457 4293299058 4293237370 4293238393 4293172601 4293566593 4293566337 4293566593 4293565563 4293566078 4293564275 4293231210 4293492077 4292110955 4291319376 4288426828 4287377994 4287505738 4287966790 4287771727 4289411917 4288496463 4289085007 4288759893 4289217358 4289152085 4289871697 4289283671 4289546580 4290003789 4289217621 4289545295 4289740883 4289543503 4289480015 4289675090 4289741390 4290595415 4290201939 4291253074 4291120473 4290661968 4290730335 4290727499 4290857295 4289873999 4289413709 4288884559 4293041032 4294171818 4294036638 4294038184 4293905312 4294162036 4291119693 4290595409 4290599004 4291128187 4290075227 4290600561 4290666846 4291060598 4290273116 4289347418 4290399602 4291389811 4292178039 4292176754 4291914362 4291847780 4291062147 4290270046 4288757332 4288229449 4288823137 4286716747 4285537096 4287581315 4286265704 4284226371 4284028996 4283503943 4284159047 4284226367 4286727813 4285868892 4286067565 4285875062 4287252335 4284883034 4284027717 4286333033 4284682825 4284620126 4288306841 4289297052 4286266980 4283695924 4284422732 4284616000 4284687437 4284683586 4283829319 4284487235 4284094024 4283631420 4283434046 4285212256 4288304518 4290539632 4287440467 4288430949 4288176553 4290221230 4290279817 4292194465 4292784789 4292585630 4292718483 4292062629 4292719271 4292720544 4292193959 4291799201 4291859851 4291595667 4291468708 4291665307 4292517014 4292259494 4291800738 4292059281 4291267982 4291465351 4291665294 4291924628 4292913821 4293506212 4293704617 4293573032 4293574062 4293772212 4293506981 4293573043 4293572773 4293574319 4293506981 4293772456 4293506737 4293509041 4293570208 4293567883 4293298310 4292107864 4289739855 4287836233 4286062663 4284289603 4283697979 4287715699 4286723937 4286458461 4289886865 4289950356 4290475395 4291659396 4291590273 4290399827 4284552261 4284748349 4284289341 4284680516 4284160069 4284815933 4284682042 4285141814 4285801547 4284684866 4285802314 4285339200 4284882245 4285344334 4285537604 4285143356 4284488773 4285013318 4284157760 4284681523 4285404730 4285342540 4284685380 4284159039 4285011018 4286595688 4290079602 4290477689 4290936952 4290014325 4289226608 4290345591 4291265929 4292121472 4292383882 4292382585 4291728762 4292777359 4291727995 4292383352 4292384917 4292054911 4292056705 4292383610 4292382843 4292383612 4291990409 4292383355 4292317817 4292384143 4291793787 4292383625 4291988872 4292450433 4292053635 4292121736 4291662216 4292120194 4292120450 4292120452 4292118910 4292121482 4292120452 4292118910 4291726725 4292119166 4292184960 4291725431 4291594111 4291920499 4291527559 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289416805 4290661718 4289544788 4290072410 4289416282 4290661463 4289414999 4289808740 4289283659 4289676369 4289085517 4289217357 4289214286 4290266951 4291453027 4292638301 4292770670 4293166450 4293037941 4293630587 4293563778 4293566075 4293565563 4293565819 4293564027 4293566076 4293565558 4293561977 4293689963 4293033330 4292372560 4290661455 4289214281 4287900743 4287443015 4287245383 4289018702 4288232016 4289413714 4288953935 4289741908 4290004053 4290133834 4289479765 4290135635 4289479508 4289545044 4289610837 4289872975 4289872969 4290398037 4290002770 4289741646 4290464596 4290267731 4290267993 4290663003 4291124567 4291189342 4290596697 4290664799 4290726482 4290334043 4289675340 4288950086 4293170040 4294171046 4294037681 4294035320 4294237874 4293229398 4289675344 4290200659 4291387744 4290598746 4290796901 4290732388 4291453041 4290669171 4290331727 4289615214 4290996337 4291783019 4292702072 4291193452 4292175722 4290337122 4291190615 4290670204 4287045453 4284679228 4285799999 4283763523 4285347172 4286726751 4284684610 4283763014 4284751171 4284423232 4284094557 4284093256 4286857318 4287055990 4285538129 4286198882 4287189895 4284357457 4283634759 4286396530 4285604434 4283368251 4286203019 4288180897 4289428914 4285341776 4284159025 4284091460 4283962428 4284748357 4284747581 4283108412 4283697207 4282910790 4284488011 4290345086 4289226872 4288171139 4287969358 4290743457 4290221221 4289236396 4291136428 4292523418 4292127897 4292652692 4292194973 4292654254 4292195242 4292326059 4291603609 4292187799 4291859081 4291858564 4291924359 4291663767 4291534736 4291998631 4291798687 4291665060 4291200134 4291596710 4293369997 4293045156 4293765533 4293243300 4293245611 4293638567 4293180329 4293573806 4293574062 4293574320 4293572000 4293506993 4293508526 4293508013 4293706419 4293706407 4293507751 4293570229 4293628287 4292238178 4290461515 4289475145 4285340994 4284552772 4284091970 4285471555 4287513449 4286065491 4288310139 4290149531 4290612641 4292117628 4291726486 4287703364 4285274178 4284292935 4284292173 4284618820 4284815933 4284421446 4285731387 4285734732 4285468984 4285606480 4285865280 4285211723 4286393930 4285604422 4285932875 4284752459 4284748094 4284682809 4284553280 4285011520 4285143359 4285470007 4284091714 4284488279 4285014597 4288236908 4290017402 4291328885 4290474869 4289228921 4290277236 4291659385 4291988096 4291856512 4292119166 4292055689 4292450709 4292253053 4292384141 4291990159 4292187258 4292384128 4292055686 4292055176 4292055177 4291859320 4292055944 4292383625 4291989639 4292384397 4292318088 4292317818 4292056192 4292055945 4292054658 4292121225 4292118652 4292120457 4292119683 4292120452 4292120709 4292118653 4292119684 4292120709 4292119684 4292120965 4291331455 4292513409 4292119671 4291593610 4291528313 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289546070 4289416282 4290072666 4289416026 4289613146 4289480536 4289807701 4289283670 4290003791 4289610576 4289348682 4288954193 4289346122 4290859601 4291190107 4292702316 4292771421 4293166444 4293495678 4293172103 4293563764 4293564540 4293566076 4293565563 4293566076 4293564283 4293565571 4293561974 4293234301 4293032027 4292636263 4290138453 4289215306 4287246666 4288029255 4288425543 4288230476 4288756557 4288759378 4289217106 4289478737 4289413201 4289349464 4289545043 4289677143 4289872723 4289676887 4289479501 4290068562 4289282130 4289479764 4289807188 4290136407 4290004822 4290529104 4290202706 4290727256 4291121746 4290531162 4291123029 4291121490 4290596950 4290792531 4289740619 4289476703 4291849820 4294304197 4294038179 4294036624 4294100375 4290595907 4290201422 4290333012 4289808470 4291387743 4290137442 4290206308 4290731367 4290397774 4290074482 4291782750 4291452531 4291321694 4290531668 4291259521 4291649882 4290794098 4291126901 4290536321 4286007142 4283895618 4284154439 4285079628 4286860657 4285930567 4284093762 4284750147 4284616259 4283830855 4284750911 4284027720 4284752736 4287317107 4286068083 4285932112 4286595699 4286199903 4284024632 4286335106 4284819029 4283631166 4284026189 4286530173 4289301169 4287321243 4287713680 4288108936 4284818774 4283499572 4283240775 4283435327 4283107655 4284156221 4290478467 4292841354 4288494698 4287907166 4291137191 4293176223 4291135370 4287915681 4290093477 4292982439 4292255126 4292260765 4292129714 4292589745 4292656300 4292128673 4292582027 4291598229 4291465863 4292120719 4291662737 4292059555 4292127393 4291933345 4292126354 4291923586 4292775050 4293238924 4292973708 4293306013 4293241763 4293310112 4293244846 4293571754 4293572774 4293706664 4293508271 4293574050 4293508271 4293706418 4293706162 4293640369 4293640112 4293640370 4293706677 4293571478 4293302929 4292376182 4290133317 4288561746 4286979909 4283500605 4284552522 4284748104 4287710303 4285473879 4287711066 4291138458 4291134101 4291665828 4291592071 4286521154 4283961674 4284813884 4284225607 4284746550 4284487239 4284814648 4285207865 4285930052 4285932100 4284685122 4285865547 4285933386 4285145674 4285867594 4285997901 4284420918 4284553280 4284946491 4284615732 4285601344 4284947526 4284684349 4284556108 4284816452 4286852698 4289226094 4290936953 4291263093 4290081398 4290340721 4291003011 4291462781 4291528576 4291134074 4291331454 4291856511 4291726467 4292448648 4292384397 4292385155 4291991699 4292319121 4292384397 4292055940 4292120712 4292055169 4292054409 4291793270 4292448649 4291988098 4292317321 4292385159 4292054151 4292055175 4292448904 4291660674 4292448132 4292120451 4291726468 4292120708 4292120195 4292121482 4291726468 4291725182 4292120966 4291725182 4291856768 4292119424 4291725687 4292052864 4291658627 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289741909 4289547611 4289612119 4290071127 4289546072 4289742165 4289283414 4289807696 4289546581 4289414737 4289283153 4289345613 4289152329 4290529111 4291059800 4292702299 4292837745 4292970357 4293236087 4293629051 4293566332 4293564539 4293564283 4293566594 4293565563 4293565820 4293565558 4293561727 4293429610 4293101688 4292371810 4290073437 4289480278 4287310662 4287375431 4289083213 4288164940 4288755789 4288757331 4289085007 4289086034 4289610580 4289807952 4289938260 4290068305 4290002768 4290201942 4289676887 4289479501 4289545300 4289938259 4289807187 4290070614 4290070358 4290464342 4290858841 4290201940 4291119697 4291125345 4291124056 4291121490 4291120985 4291187034 4290004306 4289478224 4290332745 4294300848 4294038434 4294106031 4293304174 4290985289 4290203479 4290267730 4289744219 4290266709 4290207841 4290335321 4290928227 4290010484 4291520106 4291255647 4292111482 4291849323 4288888162 4291125360 4290466904 4290664536 4290531433 4289153379 4287642451 4283893317 4284747588 4287120229 4287712381 4284026179 4284156223 4284026179 4284882760 4284619842 4284488266 4284487751 4284094534 4284883792 4287318130 4285999455 4285671254 4285869674 4284948320 4286336104 4286064237 4284421210 4284685142 4284885329 4289961410 4285209158 4285140791 4284686923 4284617276 4283240782 4283435315 4283303730 4282975800 4290085255 4292776578 4290465108 4290006889 4291267740 4292982689 4292710016 4291794592 4288375444 4289561263 4292130231 4292520855 4292713359 4292590516 4292720024 4292259993 4292452767 4291271332 4291857534 4291925406 4291662225 4291467168 4291799455 4292459179 4292190608 4291787401 4293234319 4293433227 4292975006 4292978063 4293700255 4293243811 4293243826 4293638566 4293573030 4293506994 4293706419 4293706419 4293508014 4293706419 4293706162 4293640112 4293904826 4294102976 4293772213 4293970877 4293507499 4293633662 4293034367 4291380818 4289804877 4287637832 4284613690 4283699005 4284289610 4286064709 4287576168 4286261327 4291203494 4291069853 4292058801 4290936186 4285469509 4285141304 4284619326 4284548676 4285013573 4284748855 4285077566 4285274946 4285209152 4285340996 4285407043 4285669959 4285210442 4285933129 4285868879 4285011259 4284487239 4284812345 4284683323 4284617531 4285338937 4285470775 4284094020 4284617544 4284948324 4287711068 4289556609 4291330935 4290674553 4290340978 4290080629 4291528574 4291922303 4292052872 4291790464 4291199610 4291725181 4291331197 4291856767 4291725181 4292119684 4292054663 4292450445 4292053633 4292120968 4292055936 4292384642 4292383113 4292382340 4292054659 4292054657 4292187256 4291990143 4292383629 4292383879 4291988354 4292121224 4292054658 4292120457 4291791235 4291725182 4292120709 4292118909 4292120709 4292448381 4292054134 4292120966 4291725440 4292119680 4291987328 4291594108 4291724928 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289480787 4289546072 4290071127 4289612376 4289546071 4290071385 4290070611 4289742424 4289610317 4289480280 4289348681 4289347153 4289085523 4289742674 4291979113 4292242519 4292837733 4293429099 4293234558 4293627516 4293171580 4293172098 4293566076 4293565563 4293500028 4293565820 4293565303 4293564281 4293691248 4292705119 4292768619 4291253843 4288625231 4287377481 4287572809 4287181130 4288885321 4288624974 4288957008 4289019215 4289478737 4290070870 4289348950 4289349206 4289611088 4290071381 4289611094 4289872466 4289677143 4289938259 4289677143 4289807188 4290136400 4290070871 4290330704 4290067787 4291068546 4291122261 4290531924 4291124311 4290465884 4291450963 4291120973 4290858319 4289805904 4289803101 4293965434 4294039477 4294237612 4292509295 4290401116 4290135895 4291255639 4291254620 4290138971 4291583068 4289611101 4289480797 4292113786 4291454563 4291125596 4290991963 4290599786 4287772240 4285999949 4287380070 4287377251 4285865805 4286722114 4286921065 4285932624 4284093507 4287583364 4286592598 4284091455 4284420932 4284155712 4285998167 4284352830 4285868890 4284356166 4284685130 4284093250 4286001501 4285872748 4285473615 4285409367 4285738091 4286594687 4284818258 4284953183 4284619875 4284816468 4288908201 4285868644 4283894087 4284090671 4283172936 4283435314 4283369524 4282581054 4289027443 4292977802 4291054683 4290200928 4291794356 4293181096 4292579980 4292645765 4292775821 4289165214 4289039013 4290223783 4290942383 4291927445 4292786601 4291534236 4292193962 4291861403 4292124042 4291863719 4291270549 4291664023 4291666323 4291997850 4291987074 4291983222 4293430150 4292973435 4292976272 4293369992 4293700513 4293176227 4293637805 4293572010 4293574576 4293506982 4293772457 4293508013 4293706420 4293706407 4293508014 4293640112 4293970619 4293904826 4293838520 4294102709 4294102709 4293640875 4293570977 4293299330 4291648858 4290395469 4288426055 4285600322 4283237951 4284485175 4285209160 4286657875 4285079129 4290276991 4291334296 4292520355 4291266445 4285338686 4284882764 4285209926 4284816704 4285928263 4285341252 4285998157 4285210440 4285014087 4285602108 4285079113 4285932618 4285869132 4285409616 4285866050 4285143102 4284552510 4284357440 4284880185 4285209407 4285079624 4284818250 4284484424 4283896905 4285999184 4288765795 4291001219 4291134585 4290801010 4289619062 4291331449 4291922303 4291793282 4291790975 4291528577 4291331453 4291988096 4291397246 4291134073 4291790216 4291857022 4292052615 4291790973 4291792260 4292121481 4292120453 4292118645 4292055419 4292056457 4292054659 4292054665 4292382848 4292056718 4292055943 4292055949 4292447874 4292120967 4292121224 4292120194 4292123024 4292512893 4291661189 4292120197 4292118911 4292055165 4292119169 4291725440 4292118138 4291725696 4291789957 4292051587 4291658615 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290331731 4289677906 4289416540 4290265934 4289482332 4289676629 4289938004 4289349200 4289414738 4289282900 4289085517 4289414474 4289019981 4290398286 4291255381 4292769648 4292377951 4292971900 4293299837 4293238387 4293629814 4293630839 4293564789 4293500802 4293764216 4293500802 4293566077 4293562995 4293036656 4293098602 4292372068 4290664029 4289282129 4287311688 4287508307 4287966277 4288230732 4289212488 4289018189 4289217106 4289282898 4289152607 4289807957 4289676629 4290201428 4290006372 4289610836 4290071641 4290068048 4289611604 4289938259 4289938516 4289413972 4290002512 4289742421 4291331195 4293302389 4290921551 4291120472 4291123550 4291122772 4291448912 4290531933 4290726220 4290334042 4289545301 4292374615 4294503881 4294171560 4292370776 4290990157 4290598494 4291124832 4291124574 4290205287 4289542990 4289482590 4291655043 4291781731 4291059829 4291784057 4290141029 4287645038 4288104558 4286918756 4286460750 4287511382 4285599035 4286063701 4287113536 4283632714 4284550204 4288244635 4285537612 4284027717 4283764287 4284292676 4286527596 4284490314 4285604679 4283962187 4284555337 4285538386 4284159043 4284948304 4285673055 4284292185 4284554054 4287714689 4286991231 4287846030 4284488258 4283959373 4287391371 4287846788 4283695669 4283239755 4283435320 4283369791 4282515512 4287780210 4293107078 4291585386 4289152103 4291988369 4292719509 4292513418 4292252808 4292316802 4292450982 4289167509 4290220205 4291736226 4290483869 4291866032 4292328373 4292589473 4292390564 4291662472 4292123555 4291992731 4292059289 4292125083 4291929248 4292117892 4292377457 4292972450 4292973702 4293432447 4292976538 4292977809 4293242021 4293240719 4293573792 4293571999 4293572774 4293572788 4293508514 4293508271 4293508269 4293508014 4293706151 4293970621 4293904826 4293508269 4294102976 4293706163 4294102723 4293838754 4293569692 4293369232 4292568684 4290854980 4289344843 4285404479 4283963971 4284221503 4284220995 4285865547 4286984281 4287119446 4290743961 4292778662 4291004803 4288035425 4284227143 4285539400 4283829562 4284816450 4285666877 4285340738 4285211464 4285406786 4285274947 4285801799 4285211466 4285801801 4285802058 4285931331 4284357445 4284159551 4284812088 4285078855 4284619328 4286127428 4284619587 4284092748 4283698752 4285805662 4289883262 4291263605 4291327850 4290342004 4290278004 4291463038 4292120713 4292120457 4292184959 4291462775 4291988097 4291528576 4291592828 4291658630 4291068805 4291199609 4291397245 4291199611 4291790717 4291724924 4291462783 4291858827 4292120709 4292119684 4292514692 4292120451 4292054665 4292056201 4291923312 4292120968 4292120199 4291728008 4291726210 4292120708 4291724924 4292121739 4292118909 4291725183 4292119424 4292119168 4292119425 4291593853 4292119681 4292447873 4292119679 4291791487 4291658629 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289874520 4290006875 4290072410 4289416796 4289741908 4289742422 4289546579 4289611866 4289677646 4289480280 4289544268 4288953937 4289411402 4290267988 4291125595 4292504665 4293164147 4293100907 4293496695 4293236354 4293632387 4293171570 4293566594 4293566337 4293500028 4293564789 4293565303 4293564012 4293298035 4293098864 4292307552 4290138715 4288824412 4287966791 4287376965 4288426066 4288232013 4289215308 4289282898 4289283155 4289808738 4289938257 4289872723 4290071384 4289349988 4290007130 4290397522 4289415257 4289677143 4289938253 4289479765 4289413972 4289872724 4289739856 4291780192 4292772962 4290136401 4291121999 4291124568 4291055961 4291057253 4291056202 4291123550 4291124063 4290725968 4290136662 4290859107 4293969295 4294435255 4292116840 4290923091 4291122773 4291121742 4291189590 4290733162 4289874778 4291258214 4291319636 4291848553 4291124830 4292113033 4292110970 4291647580 4290202717 4289615211 4288563049 4285405507 4284225855 4284554820 4283894595 4284026183 4285274707 4287585930 4285075262 4284023625 4283831098 4287183994 4285144638 4284686416 4285472851 4284158783 4284883013 4285081428 4283960393 4284552265 4285737045 4285341001 4283962450 4286330458 4288371355 4288838823 4285871218 4284616266 4284688468 4288315306 4283498549 4283304243 4283435321 4282515522 4287318121 4292846466 4292110950 4290270556 4291593354 4293047468 4292842383 4292982179 4292057755 4292122001 4292713632 4289429652 4290090160 4292583305 4292059814 4292193697 4292262578 4292262332 4291797911 4292122519 4291729558 4291992722 4291795353 4292056972 4292116077 4292968309 4292706956 4293365626 4293367950 4292973458 4293371036 4292978065 4293703591 4293176244 4293572254 4293572021 4293574576 4293574050 4293508272 4293706408 4293706163 4293706164 4293640359 4293904816 4293904570 4293904826 4293838519 4294036927 4294036915 4293574580 4293508266 4293698191 4292572024 4291119180 4289080134 4286782535 4284878134 4282976563 4284614718 4284421442 4287053672 4285668694 4291992483 4292122261 4291662223 4287445082 4284423498 4284423496 4285018718 4284224570 4285078854 4285209929 4285407050 4285538381 4285932874 4284818253 4285867593 4285738061 4285867851 4285536316 4285078598 4284550712 4284487746 4284944689 4285538118 4285472068 4284815680 4284223043 4284486723 4287841888 4290540920 4291134329 4291198071 4290078579 4291331450 4291856255 4292123271 4292120704 4291726469 4291922812 4291462784 4291528576 4291594112 4291594111 4291396988 4291659905 4291265403 4291265403 4291462525 4291464068 4291199610 4291396989 4291331197 4291594112 4291528575 4291856511 4292119423 4292513658 4292056459 4292121735 4292121735 4292119426 4292120456 4292120451 4291726724 4292118909 4291727755 4292119167 4292119424 4291725440 4291790967 4291791233 4291987838 4291922292 4291594110 4291790215 4292052591 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290660949 4289939799 4290070871 4289676373 4289546585 4289740624 4289742417 4289544788 4289217359 4289546066 4289151053 4288953936 4289349453 4290463831 4291712847 4292310382 4292770137 4293362288 4293235326 4293237371 4293236857 4293238137 4293566081 4293370229 4293564789 4293567110 4293566849 4293563007 4293560939 4292770146 4292111460 4290861153 4288824410 4287246677 4287378250 4289017170 4288229972 4288690782 4288693583 4289348692 4289807957 4289742422 4289479507 4290069842 4290071384 4290004050 4289741651 4289807187 4290068304 4289807189 4289872717 4290397780 4290070614 4290334035 4290597975 4290400602 4291187546 4290534753 4291121497 4291386717 4291385938 4291059298 4291122259 4291056979 4291125600 4290858071 4288822108 4292705638 4294637506 4293304449 4291120726 4291124055 4290597212 4290004049 4291188825 4292174434 4291322471 4290930023 4291057258 4291916160 4291584878 4291713394 4289086812 4290005864 4286782530 4284814148 4284095301 4285213534 4285865550 4283501378 4284419139 4283893817 4287912840 4284750405 4284159298 4285144136 4284949843 4284290373 4285672543 4284223044 4284490570 4285667415 4284818513 4284292164 4285736791 4284884561 4283828035 4285934435 4286922627 4286859387 4286066777 4287648396 4287253912 4287318400 4290357952 4285871465 4283106095 4282712894 4286197329 4292187273 4292636512 4289744476 4291195526 4292787883 4292908679 4292846999 4292521867 4292651951 4292714901 4291866790 4290284451 4289499044 4292384395 4291796106 4292655023 4292723387 4292918954 4292188571 4291928474 4292123032 4291793288 4291465362 4292444281 4292968569 4292708242 4293429118 4293301115 4292975506 4292971666 4293304198 4293240222 4293569197 4293572777 4293570477 4293572021 4293572774 4293574052 4293508271 4293706151 4293706165 4293640358 4293640371 4293772469 4293904569 4293838776 4294036926 4294036669 4294036671 4293904815 4293443251 4293633933 4292902776 4290790224 4289279563 4287702601 4284354360 4283107399 4284091452 4283830600 4287379545 4285209937 4291534500 4292057762 4290743449 4288561243 4285668422 4284424011 4284750662 4284751689 4286064204 4285143101 4285012805 4285540430 4285865801 4285867850 4286128967 4286129479 4285472837 4285472836 4284617021 4284750399 4284618814 4285340740 4285272629 4285275720 4283569471 4284093248 4286260819 4288046722 4291460213 4291330156 4290212471 4291258991 4291068536 4292579977 4292187517 4292055937 4292120967 4291726214 4292186235 4291856502 4291528576 4291528576 4291594112 4291396989 4291462782 4291265401 4291134343 4291199609 4291528319 4291396980 4291462783 4291199095 4290413437 4291462525 4291462269 4291332483 4292250494 4291792004 4292187785 4291792003 4291859337 4291792002 4292054672 4291790974 4291790719 4292185216 4291725440 4292185216 4291725441 4292185216 4291594109 4292052866 4291789429 4291987065 4291789943 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289940056 4290006874 4289416283 4290071378 4289742166 4289347409 4289479502 4290005336 4289283145 4289149520 4289151821 4289345614 4289415239 4290004311 4290994267 4292568151 4292836720 4292970607 4293430140 4293630082 4293629300 4293632130 4293632387 4293172860 4293565565 4293369710 4293565822 4293630582 4292969600 4292835673 4292703080 4290139477 4289214806 4287903060 4288033363 4287773270 4288364621 4288627277 4289546337 4288888141 4289676372 4289545043 4289546329 4289481049 4289872466 4289611350 4290070614 4290136150 4289611350 4290201942 4289611351 4289741395 4289940314 4290659667 4291187281 4291126380 4291121232 4290531161 4291123293 4291388255 4291253849 4291320923 4290993503 4291581017 4291647331 4290467918 4291186263 4291054406 4294365338 4293967523 4291581773 4290994267 4291121748 4291183960 4291587689 4291518562 4291060057 4291651966 4292110202 4290927698 4291324005 4288822091 4289217874 4287573581 4284815957 4284816708 4286133604 4287516536 4283566896 4283894599 4284026693 4283893827 4286859128 4286726262 4286393934 4285409634 4283962936 4285277270 4285345629 4284288837 4284947782 4284950611 4284945733 4284489287 4286397804 4285537625 4283960388 4284156989 4288505251 4285739102 4286657128 4285606241 4283762510 4283566137 4289764279 4284884068 4282646569 4285406289 4291531132 4292377973 4289811049 4290601850 4292522394 4292974986 4292449167 4292912780 4292588981 4292195482 4292716963 4291931816 4290346907 4289233563 4291859343 4292386965 4292589228 4292985526 4291799709 4291792775 4291596685 4291926166 4291992204 4292639361 4293034115 4292511619 4293496696 4292974228 4293369227 4292973986 4293367949 4293238414 4293634977 4293570975 4293570480 4293575333 4293573030 4293572776 4293574051 4293508527 4293706165 4293640358 4293838254 4293838264 4293772469 4293904570 4293904569 4293838776 4294036669 4294036669 4294036929 4293838497 4293505967 4293755523 4291778386 4289807955 4288489799 4285730106 4283567680 4283960141 4283699516 4285144144 4286065748 4290080396 4292452504 4291529879 4289089380 4285932620 4284224826 4284095299 4285209669 4285734471 4285605455 4285013316 4285406528 4285605966 4285013062 4286194503 4286131787 4285342795 4284751689 4284291141 4284749886 4285078598 4285076795 4285343828 4284685893 4284355142 4283961924 4287843429 4290738553 4291527300 4291131765 4290343798 4290540405 4291396988 4292123285 4292055422 4292121216 4292122774 4291991148 4291728529 4291792778 4291857029 4291922046 4291528320 4291528575 4291528574 4291791502 4291396988 4292053633 4290808189 4291659649 4291330938 4290479230 4291002758 4291659645 4290676609 4290870401 4291330938 4291462524 4291594112 4291396732 4291528318 4291923846 4291856510 4291790976 4292185215 4291199869 4291922560 4291790976 4292185207 4291593853 4291463040 4291594109 4292118392 4292053117 4292116093 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289806930 4290071128 4289480536 4289939541 4289546329 4289742422 4290070100 4289742423 4289478477 4289151565 4289151566 4289346382 4288819531 4290071118 4290993754 4292768365 4292639837 4292969067 4293694851 4293236351 4293238406 4292910448 4293236867 4293435764 4293566335 4293566595 4293564528 4293561720 4293363569 4292838000 4292241766 4290204509 4289282634 4287311444 4287377480 4288557124 4288168034 4289216078 4289019213 4289217106 4289480278 4289610323 4289678425 4289938003 4289611350 4289741395 4290726485 4289940313 4289611094 4290201686 4289545558 4290201943 4289413967 4290268506 4290594897 4291717224 4291447378 4291125345 4291056723 4290927968 4291517020 4291517020 4291583077 4290994264 4290993760 4291645271 4291449439 4291254116 4292771679 4293832570 4291450705 4291057758 4290789968 4291520871 4292109921 4292177784 4291452532 4291388776 4291456618 4290998409 4290728809 4288755808 4285272377 4284028230 4284945512 4284489553 4287256727 4286398571 4283957317 4284092992 4284158539 4284089415 4284160579 4288110478 4284882762 4283828550 4284225856 4286926205 4284818256 4284943686 4284882758 4285142107 4283829574 4285281635 4285998928 4284884561 4284419414 4284488261 4285938539 4283434812 4286268021 4285011268 4283107138 4283367485 4285881460 4288504991 4283629625 4290544774 4292706929 4289810270 4291060326 4292193185 4292578687 4292907398 4292517522 4292520083 4292588968 4292652964 4292326563 4292062118 4289105825 4288963436 4291602601 4292261039 4292132285 4292390810 4291336610 4291923587 4291530644 4292317568 4292771704 4292969864 4293036436 4293103734 4292973475 4292974238 4292975519 4293763190 4293238668 4293303687 4293240481 4293240979 4293181087 4293569437 4293571756 4293574563 4293574065 4293506725 4293838766 4293640372 4293838253 4293640102 4293838263 4293904816 4293904570 4293838777 4294036669 4294036669 4294036670 4293905072 4293572538 4293168767 4292111970 4290197834 4289278793 4286389065 4284028478 4283830860 4284287308 4283962692 4288101473 4287843683 4292780443 4292518813 4289022562 4285075767 4284291657 4285207874 4284685640 4285407818 4285144390 4285606736 4285342794 4284881987 4285604941 4285211722 4285929792 4285210441 4285276230 4284684349 4284618815 4284748599 4285539662 4285012547 4284225091 4283765060 4285076805 4288697463 4290934645 4291266171 4291132022 4290212212 4291199865 4292186245 4292188289 4292450710 4292054911 4292122238 4291661707 4292513919 4291924344 4291662456 4291464843 4291663229 4291857797 4291857028 4291462782 4291528566 4291462784 4291987841 4291528576 4291462525 4291396474 4290937222 4291134074 4290805372 4291004788 4290741889 4290545549 4291132786 4291134589 4291921801 4291199609 4291593852 4292119166 4292052873 4291725180 4291724416 4291528576 4291462267 4291856768 4292119680 4291987328 4291856259 4292511094 4291527794 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289676630 4289480793 4289742160 4289742166 4289546579 4289610324 4289349201 4289412946 4289480525 4289348688 4289151566 4289803847 4288823122 4290398542 4291451732 4292701790 4292838000 4293165947 4293430644 4293173383 4293630578 4293630339 4293370484 4293566084 4293498997 4293565564 4293565559 4293562495 4293299310 4292772206 4292439144 4290203987 4289280848 4287312715 4287441988 4287771998 4288822861 4289150799 4288825428 4289216336 4289481057 4289349205 4290070099 4289609296 4290005849 4290135893 4289941852 4289806418 4289806931 4289611350 4290136406 4289609810 4291055961 4290332757 4290792792 4290534238 4290468960 4291055961 4291384152 4291974486 4291385691 4290990670 4291122772 4291124312 4291055444 4291058519 4291322459 4291914343 4290992450 4292508775 4290857555 4291124568 4291123285 4292569440 4292376968 4292307561 4291131283 4290209423 4290079371 4289287544 4287773009 4285863503 4284359235 4286855547 4283960121 4283564095 4286797442 4285078875 4284219455 4285545329 4284422212 4284684363 4284023359 4284488255 4287054720 4284024891 4286727287 4287315557 4284552512 4284353609 4284751683 4284553289 4284219461 4286793826 4284615509 4287317611 4284028241 4284420676 4283369539 4285409112 4287387271 4284489301 4283238198 4283303991 4283502922 4288373409 4289556348 4293367926 4290401117 4290531677 4291861917 4292908413 4292972932 4292315786 4292645768 4292586131 4292588962 4292259749 4292391592 4291867570 4290812835 4288896389 4291602608 4292394406 4292784285 4291859861 4291858838 4291462022 4292314221 4292968583 4292773773 4292971652 4292971138 4292644516 4293367687 4293303432 4293303177 4293304458 4293303945 4293239455 4293633162 4293568413 4293571248 4293572268 4293573286 4293572787 4293574307 4293574321 4293508258 4293508271 4293706165 4293706151 4293838264 4293772458 4293904572 4294036915 4294036670 4294036669 4294036669 4294102979 4293509285 4293695612 4292636538 4291051601 4289676878 4286719815 4283833421 4284354107 4283567171 4284418878 4286925165 4287247703 4291928487 4292715687 4288364630 4285210435 4286130775 4284090440 4285210180 4285343051 4285866567 4285277258 4285932361 4285933129 4285474895 4285475919 4285408587 4285011257 4284422981 4285078340 4285406786 4285340224 4285276234 4284880182 4284221250 4284752463 4286727788 4289818745 4291331449 4291262314 4290736746 4291000198 4291068023 4292122768 4291859837 4291858293 4292121744 4292119943 4292121733 4292056718 4292120968 4291792266 4291992194 4292121998 4292119161 4292121999 4291792511 4291859083 4291857797 4291856502 4291528576 4291595398 4291593596 4290545538 4290805379 4290607991 4290808201 4291592826 4290413685 4290676621 4290739843 4290936437 4291134086 4290805359 4291331187 4291133560 4291462782 4291659905 4291397245 4291331453 4291856768 4292185217 4291790715 4292118387 4291790464 4291855222 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290136144 4290071379 4289676624 4289480794 4289807702 4289414737 4289612112 4289806413 4289610832 4289480537 4289151053 4288954450 4289347142 4289611096 4291519840 4292504154 4292442991 4293034601 4293236099 4293695864 4293172871 4293631096 4293566082 4293304693 4293763960 4293501313 4293566076 4293562231 4293429617 4293294195 4292834395 4290071900 4289215561 4287834958 4287967571 4288426566 4288165462 4288822093 4289150561 4288627790 4289678437 4289610320 4289742422 4289676886 4290071127 4290005848 4289939800 4289874777 4290726742 4289675859 4290266451 4290070614 4290268248 4290858585 4290071890 4291120472 4291451732 4291385435 4290402646 4291120992 4289875794 4291189342 4290005080 4290070360 4289678161 4290596442 4292835677 4291254604 4287704908 4290070624 4291123025 4290198607 4292965996 4291517291 4292701551 4290603410 4289159320 4289556620 4289619347 4288434527 4287378512 4283368516 4285542755 4285935967 4283434054 4282843192 4287784859 4285146964 4284750408 4286199665 4283697467 4285276746 4283895112 4284157506 4284682052 4287783323 4287649142 4285209411 4283960387 4284221754 4285145949 4284419142 4284287283 4287519132 4283433013 4285210460 4286331236 4284880981 4284882273 4283695153 4288906942 4285802066 4283106358 4283369779 4282713152 4286987352 4290807955 4290531166 4289415766 4291402411 4292978829 4292512637 4292578941 4292251266 4292120465 4292123035 4292654247 4292260273 4292194212 4292522913 4291405992 4290545559 4291537060 4292521123 4291794326 4291925915 4291593620 4292969589 4292971420 4292711570 4293298838 4293035147 4292645758 4293430411 4293303691 4293302923 4293301388 4292975263 4293238408 4293699214 4293238665 4293568671 4293570987 4293570206 4293573542 4293572789 4293573019 4293571499 4293573032 4293574308 4293508258 4293508015 4293838508 4293640116 4293772457 4293904572 4293838776 4294036669 4294036927 4293772200 4293508530 4293635985 4293098876 4290660175 4289479758 4288293448 4284551739 4283369285 4284092231 4284287033 4286789984 4286653512 4291926432 4293110952 4289157735 4285603418 4285734213 4284553275 4284684617 4285668675 4284751178 4285145158 4285539148 4285474124 4285803596 4286325317 4284949839 4284683837 4284552247 4284488517 4284552765 4285145671 4285405758 4284552516 4284158797 4285012044 4288433513 4290081925 4290871671 4290867060 4290867830 4291196264 4291725430 4292448649 4292383365 4292056720 4292119160 4292120200 4292120191 4292120711 4291791748 4291596664 4292120448 4292123028 4292055678 4292055687 4292449934 4291925627 4292119939 4291792261 4291856254 4291989126 4290873733 4290938754 4290939267 4291199100 4290545259 4291004548 4290805380 4290805370 4291462525 4290414218 4291002229 4291002499 4290936706 4290936697 4291199609 4291133815 4291461253 4292053888 4291988097 4291133818 4291659904 4292051571 4291396987 4292053122 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289611094 4290071385 4289611095 4290333008 4289348950 4289217365 4289807948 4289347662 4289413197 4289480531 4289348938 4289016394 4288888657 4290004556 4291124830 4292702313 4292641904 4293037433 4293365376 4292907911 4293695608 4293173385 4293566333 4293565307 4293501316 4293500545 4293565820 4293564792 4293495155 4292770145 4292306529 4291252561 4288953936 4287836744 4287376454 4288426057 4288822102 4288622930 4289348432 4289348693 4289610320 4289612901 4289546584 4289544784 4289481573 4289806417 4290136150 4290266194 4290202454 4290070614 4290070615 4290660432 4289808729 4290268754 4290728022 4291121494 4291058003 4291318865 4291582814 4291256668 4291975009 4291649114 4291972691 4291782238 4291384665 4291846489 4291921792 4287113289 4290402915 4292121211 4291862936 4290266706 4291320407 4291519632 4289488277 4289755798 4290011523 4290729820 4292110683 4290072428 4286387284 4284422980 4287523233 4285143630 4283107143 4282908731 4287589529 4286594165 4285014875 4283763513 4284358240 4284682825 4286068318 4285930337 4287915934 4286528868 4286131300 4284161349 4284548682 4284223803 4285540689 4283958857 4284749124 4286927746 4283695931 4284420420 4287848855 4285406034 4284156730 4286270858 4285542227 4283499571 4283700815 4282844222 4285606987 4291267971 4288825442 4287577179 4291922308 4292783250 4292512639 4292579719 4292580749 4292710530 4292054143 4291797919 4292653989 4292721072 4291604134 4292130216 4292455596 4291470227 4292063918 4291733153 4292254864 4292447095 4292445048 4293037725 4293103993 4293103245 4292646282 4293037964 4292971937 4293169810 4292975259 4293305758 4293304456 4293236875 4293632909 4293238921 4292908959 4293632390 4293569185 4293570204 4293570748 4293574806 4293573046 4293179297 4293571756 4293572775 4293574321 4293574062 4293442222 4293838509 4293838265 4293904815 4293838778 4294036926 4293838519 4293970621 4293839023 4293570968 4293033854 4291053906 4289674062 4288292935 4284157766 4284025911 4283896386 4283962699 4286328663 4286981970 4291200921 4293044131 4289883515 4286720077 4285211979 4285274951 4285540171 4285934424 4285605707 4285998153 4285081167 4285278540 4285867081 4285409102 4285734469 4284620103 4285144388 4284817995 4285208124 4285144133 4284816970 4284290368 4284026444 4285213005 4289357438 4290543223 4291328629 4290146935 4290077543 4291002745 4292184962 4292056192 4292383368 4292384383 4292055943 4292121998 4291725185 4291795087 4291792251 4291991423 4292119942 4292121213 4292450453 4292057219 4292055434 4292057234 4292123028 4291725954 4292186250 4291595377 4291987584 4291659648 4291330425 4290873477 4291461754 4290938756 4291133819 4291198581 4290085499 4290541940 4290871430 4291002487 4290805882 4290805110 4290805110 4290805893 4291133557 4290805369 4291396474 4291463040 4291986550 4291856000 4292119422 4291462524 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289740624 4289481050 4289742154 4289479246 4289613146 4289806160 4289742675 4289545289 4289543505 4289610831 4289544269 4288954192 4288954192 4289545046 4291320667 4292703851 4292837741 4293035132 4293365377 4293304694 4293564284 4293565562 4293566334 4293565306 4293501316 4293698424 4293500284 4293563768 4293101935 4292771424 4292768605 4291187548 4288626258 4287901522 4287443273 4287770696 4288230218 4289282639 4288496207 4289348428 4289677914 4289151569 4289544785 4289742944 4289677910 4290071641 4289808469 4289611350 4289611094 4290201686 4289545809 4290068560 4289874521 4290398038 4291187539 4290532693 4291054680 4291387230 4290924115 4291712855 4291582545 4290861398 4291322977 4291121484 4291123554 4291909976 4293110919 4292045904 4292699980 4293555017 4294883953 4292569443 4290729596 4288768140 4290343316 4291323524 4290664277 4291848546 4290929006 4285930819 4283699002 4285214332 4288113818 4284025662 4283566143 4283499075 4287326865 4287780755 4283761714 4283764291 4284551750 4283697477 4286197605 4287782267 4287054963 4286067549 4285473362 4284157760 4284091963 4284223298 4285342814 4284093770 4284886612 4286592612 4283564862 4284221756 4288048042 4284353611 4284090679 4287060099 4283630379 4284885106 4283765081 4284156731 4291070096 4292109418 4288425022 4290935179 4292853675 4292970877 4292516750 4292584597 4292713613 4291925128 4292052857 4292387738 4292653997 4292261281 4292325551 4292785829 4291013810 4292457129 4292326561 4292247405 4290333765 4291847793 4292639881 4291985276 4292838779 4292644505 4293235364 4293038717 4293433738 4293368205 4292976793 4293303945 4293238152 4293633935 4293566859 4293239711 4293698440 4293568673 4293567883 4293569186 4293570718 4293573291 4293571743 4293637549 4293573276 4293573291 4293573020 4293506984 4293706667 4293706154 4293706151 4293574324 4293904558 4294036927 4294102720 4293574320 4293706681 4293638034 4293300344 4291121495 4289080136 4286784330 4284876852 4284090696 4283830583 4284287043 4285277003 4285404486 4290479498 4293046698 4290476165 4286325832 4287313496 4284554823 4285935448 4285542992 4284751175 4284948557 4285735748 4285800264 4285737805 4285801543 4284421436 4284554052 4284620103 4285274684 4285078855 4285146959 4285011514 4283568463 4285275968 4287186548 4289687672 4291392114 4290674553 4290211958 4290935158 4291265660 4292119932 4292121472 4292056719 4292055169 4292056193 4292251009 4292123024 4292118398 4291990137 4291792268 4291990643 4291729041 4292054653 4292450437 4292057235 4292449420 4291859061 4292122496 4291726984 4292187019 4291857030 4291529595 4292054151 4290744184 4291396745 4290284924 4291133306 4290611075 4290479241 4291133302 4290805625 4290805635 4290805643 4291134339 4290870644 4290674050 4290476662 4291133560 4290348426 4291133557 4290934387 4291723386 4291396220 4291659636 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289546842 4289938002 4289743962 4289742423 4289347152 4289545300 4289545294 4289740627 4289938505 4289414995 4289085523 4289412944 4289082438 4289677144 4291779416 4292310121 4292506731 4292709226 4292972162 4292908940 4293631610 4293566336 4293566850 4293501316 4293500541 4293697906 4293500541 4293563000 4293495162 4292771422 4292570462 4290859089 4288691789 4287901512 4287375687 4289081179 4288232526 4288691542 4288757584 4289414247 4289217361 4290333014 4290071383 4290070374 4289676628 4289609294 4289742422 4289872467 4289742422 4289218134 4290134096 4290399834 4290268243 4290793814 4291121747 4291056733 4291842900 4290927447 4291646554 4290862432 4291648857 4292039519 4290662484 4292118930 4293905048 4292777579 4291652176 4283498551 4285073724 4285271874 4286976310 4290863978 4289293730 4289619083 4291062133 4291255640 4290726486 4291451737 4289216360 4284221760 4285675132 4286069600 4286667410 4282843185 4283500888 4284750938 4288444326 4286134626 4283564601 4284354373 4284490825 4286064990 4285935189 4285077568 4284356157 4285079629 4284485183 4284483145 4284421196 4284681794 4284490313 4284815939 4285737299 4284225104 4283957314 4285412965 4287193227 4284157247 4285278301 4287055991 4285279854 4283567422 4282975036 4288962407 4292581235 4288691032 4289943137 4292986811 4293236094 4292449410 4292583827 4292655261 4291925647 4292249476 4292116619 4292124816 4292654509 4292263099 4292263097 4292588725 4292984229 4292128911 4288103230 4287043898 4288428377 4290400867 4290072405 4291520626 4291784323 4292376689 4292113781 4292774292 4292842625 4293042077 4292975262 4293763447 4293240225 4293237903 4293633166 4293236875 4293237648 4293238407 4293174435 4293567098 4293568673 4293573545 4293574823 4293179298 4293572269 4293569949 4293571758 4293574566 4293508507 4293508260 4293508016 4293838241 4293904830 4293772213 4293970610 4293706669 4293639313 4293500823 4292904061 4290593608 4286848071 4285535040 4285142586 4284483897 4283828295 4284026683 4285798734 4286260063 4288768382 4293574052 4291133565 4286918224 4285340739 4285736275 4285801798 4285340999 4285608283 4285605193 4285410906 4286134618 4286265163 4285276236 4285668164 4284421180 4285341255 4284291652 4285603139 4285341512 4284226371 4284029513 4284818255 4288435575 4290410629 4290869621 4290737780 4290209907 4290540404 4291725437 4292448133 4292056199 4292120955 4292381567 4292121217 4291728011 4291922046 4292120436 4291792510 4291597695 4292119175 4292121719 4292121743 4291661192 4292121469 4292056462 4292121224 4292121486 4291790980 4291790710 4291922038 4291529863 4291528053 4291595399 4291659645 4291004806 4291790719 4290414211 4291198839 4290742670 4291265412 4291133816 4290742142 4291003014 4290674050 4291133302 4290348159 4290279809 4291133825 4290411125 4291068547 4290739830 4290998911 4291068279 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289740625 4289938259 4289479250 4289807958 4289546579 4289742423 4289740369 4289874520 4289742418 4289412946 4289544780 4288953936 4289086286 4290070091 4290928473 4292767850 4292575086 4293624942 4293629303 4293628288 4293565818 4293566336 4293501315 4293763958 4293500546 4293501317 4293564789 4293564786 4293297771 4292772467 4292372062 4290664287 4289282636 4287246672 4287510356 4287837255 4288364377 4288754759 4289149269 4289151567 4289283155 4289151571 4289546328 4290071383 4289415255 4290333794 4289217620 4289939798 4289479251 4289676630 4290006106 4290004048 4290595408 4290332759 4291186003 4291121995 4291058780 4291058263 4290927191 4291975512 4290861917 4291779423 4292039777 4294564528 4292380516 4289015872 4286455371 4283302967 4283697220 4283237962 4285144404 4290674579 4292523716 4292591282 4291974237 4289872465 4290138714 4288559435 4285007421 4284621389 4287186817 4286602386 4285473878 4283828295 4283565635 4286200942 4288646061 4285870956 4283564594 4285144400 4284680000 4284161093 4284945467 4284553803 4284686924 4285606486 4284091455 4283831110 4285474381 4284159299 4284421702 4285411423 4286264937 4285408590 4284944726 4285608560 4286859126 4285143900 4285741416 4284093263 4283106109 4282581044 4286792543 4293302917 4289479521 4289150294 4292655261 4292516997 4292910719 4292518293 4292523163 4292589735 4292249485 4291725690 4291724171 4292128679 4292196523 4292656822 4292656824 4292854962 4291140745 4288688457 4288887639 4289613936 4289744213 4289216595 4288953422 4289282130 4287771207 4288822362 4290401105 4290796383 4292966519 4292971653 4292975756 4292977052 4293700769 4293239710 4293631608 4293238409 4293698957 4293235342 4293632891 4293568420 4293567882 4293572526 4293572001 4293572001 4293568941 4293570464 4293574047 4293570984 4293573023 4293574065 4293508273 4293706143 4293838256 4293706410 4293773233 4293507993 4292973702 4292181874 4291188057 4288231239 4286128200 4285732160 4284681786 4284418363 4283960637 4284089418 4285211715 4286526316 4287318119 4293640119 4291658886 4289221493 4284947525 4285142597 4286329944 4284949832 4285342279 4284882764 4285867080 4286198091 4285211211 4285732922 4284552764 4284291404 4285078082 4285276743 4284423237 4285472073 4283766853 4284224582 4286722136 4288438902 4290934901 4291263604 4290542213 4290013044 4291200121 4292185734 4291991425 4292448386 4291595901 4292449158 4291660165 4292119669 4292120452 4292515196 4291726471 4291791997 4291792253 4292119668 4291332485 4292120442 4292120971 4291924854 4292121473 4292121225 4291990903 4291858046 4291528321 4291528319 4291925380 4291921780 4291529863 4291659390 4291595654 4291725182 4291005062 4290873215 4291398539 4290805636 4291528583 4290739833 4290541940 4290479755 4290673783 4291133826 4290476660 4290805635 4290280065 4290608502 4290345090 4290934644 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289676624 4289218658 4290137176 4289283414 4290003539 4289742423 4289481300 4290068043 4289676882 4289808211 4289085517 4289217357 4288886605 4289938510 4291386467 4292505693 4292837998 4292970109 4293234550 4293562497 4293566849 4293566337 4293566847 4293500543 4293763440 4293501315 4293567365 4293563516 4293431165 4293099097 4292766829 4290663252 4289017932 4287967056 4287441743 4287903062 4288363347 4288755541 4288891476 4289151056 4289677152 4289807957 4289480533 4289676629 4289742165 4289415256 4290071385 4290005849 4290136151 4290530382 4289675854 4290331470 4289808987 4290268242 4290727256 4290600290 4291122259 4291450970 4291254105 4291255393 4291388264 4290994012 4291518560 4294031229 4292054917 4287639624 4285732933 4284881214 4284090186 4285271358 4289354360 4291137451 4293894518 4294024031 4291581017 4287442505 4287310672 4286721105 4285143384 4285148249 4286596979 4288576431 4283105332 4283370327 4284687211 4287515784 4288512403 4285411939 4283761460 4284027714 4283630150 4285016146 4285676649 4285281375 4284093242 4285675623 4285013832 4284028986 4284948057 4284354869 4283960896 4283893572 4286526558 4287913626 4284352816 4286531719 4284492363 4285276772 4285478248 4283829053 4282976069 4285539662 4292119925 4290994018 4287969350 4292187805 4292648847 4292974988 4292452755 4292521363 4292919715 4292720546 4291659645 4292116620 4291862163 4292719781 4292654260 4292591801 4292462257 4292052343 4290661976 4292045669 4292903310 4292639868 4292510063 4291653496 4290993778 4289942883 4288692059 4286322751 4286587972 4286519875 4287509580 4289610832 4291786094 4293299342 4293500287 4293368718 4293304458 4292978087 4293304456 4293304714 4293171345 4293631860 4293569970 4293570473 4293572002 4293573273 4293568414 4293570204 4293567902 4293570208 4293572761 4293574312 4293574812 4293575084 4293903526 4293638043 4293432444 4291786351 4290466396 4290399055 4288034633 4287769159 4286453062 4285930052 4285138489 4284484916 4284353350 4283897157 4285012298 4285408334 4286529112 4293375146 4291334552 4289552998 4284290374 4284291401 4285735761 4286851655 4285738839 4285408587 4285801802 4285604423 4285078852 4284819283 4284948553 4284749365 4284227404 4285142332 4285540172 4284946752 4284619595 4284420670 4286528358 4290343034 4291329396 4290670975 4290472816 4290080630 4291725179 4292054149 4292712065 4292318339 4292447350 4291988604 4292119941 4292120701 4291725692 4291660935 4292513142 4292119933 4291791495 4292119167 4291792517 4292185477 4291397762 4291859082 4291725955 4292122752 4291792523 4291856255 4291529852 4291528576 4291921791 4291531404 4291528053 4291595399 4291593845 4291595654 4291659390 4291660930 4291397774 4291792257 4290545546 4291136388 4290610557 4291067510 4291133559 4290673784 4290151554 4290542196 4291199874 4290277746 4290016131 4290146420 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290726742 4290071384 4289676373 4289742422 4289546328 4289676623 4290003540 4289283665 4289874258 4289939021 4289478734 4289019729 4289019728 4289347663 4291385946 4292570972 4292836459 4293034105 4293693309 4293566587 4293565563 4293564789 4293566852 4293566080 4293501831 4293566851 4293565043 4293562755 4293692523 4292704099 4292375130 4290926165 4288690256 4287312457 4287379027 4288492616 4288297814 4288691535 4289280846 4289544786 4289217363 4289741908 4290072923 4289611093 4289676886 4289938259 4289479501 4289740625 4289479764 4289806932 4290202201 4289675854 4290398797 4290859099 4290726482 4290729047 4291189342 4290401628 4292040799 4290926939 4290796641 4291786611 4292767591 4291979108 4293562219 4290273876 4286259016 4284941872 4282976315 4283106367 4288894833 4291329149 4291909976 4287704650 4288892244 4286191168 4288103524 4287048025 4285013577 4286792838 4286599558 4285274679 4284024921 4284355917 4286335609 4287119238 4286338941 4287058300 4283170864 4283894092 4284294221 4286008178 4286063457 4284357181 4285483122 4285936730 4285675371 4283961150 4285537859 4283696966 4284288322 4283369532 4283959357 4286267252 4286924934 4286799768 4283695152 4287777935 4283896127 4283172676 4282777660 4290276982 4292646283 4289345609 4290873496 4293182117 4292709250 4292450960 4292915873 4292524721 4292855225 4291992460 4291983755 4291662471 4292191649 4292196283 4292265395 4292985011 4290930281 4290662741 4292898408 4292444540 4292970107 4292443511 4292835962 4293037717 4292905086 4292834425 4291190877 4290598506 4288756568 4288425032 4286653254 4286584389 4287373126 4288757327 4292376968 4292909182 4292972935 4293367949 4293298829 4293237903 4293697910 4293173413 4293570225 4293569945 4293571997 4293570220 4293568668 4293569947 4293573286 4293572769 4293568689 4293574561 4293764753 4293436554 4291982692 4290072656 4288362832 4287309634 4286196304 4287379026 4289286760 4289283680 4290137431 4289345607 4285993794 4285206326 4284224056 4283764551 4284685119 4286195291 4285937742 4292916928 4291856014 4290867322 4285668671 4284882506 4284817225 4285675085 4286197332 4286129222 4286131018 4285867594 4284947523 4284092981 4284555341 4284947266 4284814135 4285273655 4285211465 4285209668 4284356937 4285143640 4288432992 4290346631 4291132288 4290473072 4290079875 4290804074 4291659646 4292383363 4292710533 4291988346 4292054150 4292382598 4292119942 4291725184 4292119942 4292121475 4291726461 4292120711 4291790710 4291792519 4291856256 4291792251 4291924106 4291398019 4292186249 4291791484 4291662713 4291790720 4291858054 4291922049 4291463031 4291528320 4291989374 4291529597 4291595390 4291528062 4291529860 4291791759 4291595137 4291397773 4291529357 4291331461 4290936707 4290808204 4289888659 4291133302 4290608515 4290411392 4290214272 4290083202 4289951349 4289950839 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289676881 4289544273 4289546585 4289938001 4289481316 4290072666 4289480536 4289546586 4290068050 4289545290 4289742411 4288950859 4288954449 4289610828 4291385169 4292110690 4292903792 4292707182 4293234551 4293564540 4293566591 4293564015 4293566594 4293565559 4293566080 4293500544 4293566590 4293565827 4293494640 4292969584 4292767836 4290598238 4289412940 4287834705 4287968851 4288427091 4288232271 4288756812 4288823893 4289609809 4289610322 4289483365 4290005591 4290397523 4289611094 4289872724 4289938260 4289479765 4289806412 4289413968 4289872713 4289808729 4290070616 4290068300 4290859098 4290071122 4290726225 4291122266 4290924375 4291259246 4292840053 4292969598 4292507242 4292965997 4292773758 4289088613 4284549940 4286922600 4285541203 4281794624 4287912580 4291193463 4290406264 4288753487 4287642713 4288233564 4286455380 4284816713 4285607778 4287453067 4286201459 4283566947 4284094541 4286335606 4287914659 4284025156 4284886614 4289299384 4283696695 4283830603 4283765308 4286394214 4284947268 4283699790 4283959106 4285675121 4287715206 4285342790 4283762744 4283828532 4284551481 4284548934 4284484930 4284097361 4285808208 4288310683 4283435318 4285542751 4283499574 4282712110 4286595681 4292976001 4291518554 4290208378 4293378736 4292449658 4292908679 4292454548 4292915361 4292723381 4292064933 4291921544 4291528585 4292190353 4292196797 4293183923 4292787105 4289679430 4291384406 4292109937 4291585123 4292768635 4292702569 4291852677 4290332495 4292970350 4293102729 4292969600 4291320933 4292440671 4290460751 4289347664 4289477453 4288689481 4287378250 4288360529 4289676875 4292109436 4293367425 4292972410 4293365904 4293301133 4292841112 4293696118 4293567369 4293568673 4293571996 4293572513 4293569200 4293568412 4293571996 4293173917 4293305485 4293568406 4292444800 4289809752 4288097098 4288626013 4289548901 4289024355 4290995829 4291058793 4292441971 4291252035 4290594123 4289216336 4286192712 4286258762 4284288061 4284158535 4284287040 4286132048 4286653276 4293047199 4291661198 4290078583 4286655054 4284947268 4284422724 4286921303 4285143367 4286195270 4285671245 4285869645 4285144134 4284881730 4284685892 4284618300 4285144648 4285602886 4285670222 4285145933 4284882504 4285406797 4288634745 4290411382 4291394676 4289686903 4290209905 4291134331 4292580487 4292120690 4292319106 4292383883 4291989381 4292382583 4291858549 4292119160 4292447617 4291725942 4291790722 4292119424 4292119417 4291790968 4291790967 4292184705 4291332732 4292184695 4292120453 4291793539 4291791998 4292184952 4291858047 4291464052 4291922307 4291528567 4291528577 4291594112 4291529596 4292054661 4291529348 4291529603 4291529603 4291397774 4291659385 4291529103 4291005316 4291593594 4291200653 4290676593 4290085512 4290870655 4290477441 4290015616 4290279041 4290081921 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289545042 4289547365 4289807444 4289480535 4289547610 4289677655 4289546329 4289544782 4289808210 4289478734 4289086030 4289281867 4288951115 4289742930 4291583329 4292372834 4292444000 4293034860 4293430398 4293565557 4293500802 4293566594 4293565563 4293500802 4293500289 4293764986 4293500543 4293566070 4293101431 4292706159 4292703838 4291123294 4289083977 4287836233 4287376453 4287771982 4288887117 4288626000 4289545557 4288562257 4289677914 4290003025 4289676886 4289348179 4290071642 4289872718 4289545816 4290266962 4289346640 4290267732 4289872970 4289807178 4290266447 4290399317 4290397776 4291119956 4290072152 4291186772 4290990935 4292904818 4292904579 4292642674 4292509550 4292574316 4293625958 4292982166 4289032315 4291790729 4291656841 4287974243 4289558185 4291123541 4294019187 4289478744 4285474899 4285209924 4284029762 4285605730 4286657392 4288379831 4286460263 4286132069 4286065769 4287785895 4285738853 4282843196 4284157500 4288638610 4284686937 4284093767 4284093257 4286926715 4284486723 4283697986 4283762498 4285149031 4288243080 4286196830 4284155707 4284155962 4284483386 4284816959 4284549949 4284221507 4284221247 4284619849 4286727804 4283564076 4283041593 4284223798 4292582541 4290859610 4289679971 4292655271 4292582787 4292516238 4292451219 4292916638 4292591276 4292855224 4292716688 4291793306 4292057223 4292653222 4293316280 4291210382 4289608255 4290200143 4291513935 4290070349 4291054920 4290925643 4290990402 4290925646 4286251838 4289348685 4293167966 4291843670 4289544014 4290135895 4290331994 4291127161 4290792274 4290468198 4291051087 4290464852 4290527329 4291650655 4292769651 4292969884 4292837751 4293102215 4293693306 4293170574 4293569185 4293570201 4293570994 4293571495 4293571981 4293569200 4293571760 4293699741 4293040767 4291985029 4290991449 4289747561 4290270816 4290403675 4290862688 4288756040 4289018696 4290205007 4290003784 4287837520 4288229193 4288032842 4286259271 4286263888 4284289604 4283962431 4284094532 4286132316 4285670226 4292782240 4292120458 4290078327 4286989919 4284877113 4284881218 4285806426 4284949066 4285343053 4286262345 4285932619 4284486972 4284881728 4285076292 4285210183 4285144390 4285276233 4284619845 4284683844 4285211473 4286591574 4290015099 4291196544 4290343798 4290340712 4290602868 4291857014 4292054905 4292383111 4291987327 4292317046 4292381825 4291988097 4292447617 4292053634 4292053623 4292119172 4292120180 4291725442 4291725432 4292119426 4292119425 4291726973 4292184705 4291725941 4292120702 4292120444 4292119935 4291790969 4291462776 4291856516 4291922295 4291528578 4291528576 4291594111 4291659647 4290807941 4291660676 4291529348 4291923588 4291594881 4291465108 4290939266 4291396216 4291790977 4290873216 4290807949 4291133827 4290151552 4290605681 4290149250 4290082945 4289949824 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289610580 4289611858 4289547090 4289941861 4289939284 4289939542 4289544789 4289808204 4289151831 4289283146 4289283150 4288491851 4289081417 4289741385 4291124568 4292503652 4292902254 4293166706 4293627516 4293106819 4293764215 4293500545 4293498997 4293698425 4293698424 4293500287 4293566590 4293561980 4293037689 4293231468 4293031531 4291056723 4289281619 4287835976 4287376967 4288492361 4288165711 4289213770 4289217363 4289216594 4289610580 4289283671 4289872467 4290201943 4289741647 4289544013 4290398032 4289348682 4290462795 4289807434 4289412433 4290069069 4289742160 4289936977 4290660691 4288957276 4290599790 4290146446 4291983730 4292245347 4292446843 4292839281 4292643207 4292837758 4292969580 4293762156 4293956978 4293173639 4293499012 4291912543 4287047246 4286849600 4286192200 4283696957 4284692573 4284357213 4285278562 4286333814 4288245665 4286530412 4284682059 4287118982 4285937004 4287850635 4285342555 4283040823 4283631947 4285612649 4287057020 4283826244 4284421700 4287452540 4283829571 4283698236 4283894599 4284225850 4286662519 4287914640 4283172402 4284094016 4284552511 4284419135 4285141575 4284553529 4284748607 4283566135 4283896886 4284618344 4282646581 4289357164 4292840056 4288492883 4292254358 4292982164 4292514191 4292910475 4292849553 4292787377 4293182910 4293114036 4291604382 4292319115 4292586407 4293119172 4291469179 4288814906 4289083980 4289347660 4288951878 4289875021 4287176263 4286915911 4286980936 4286653004 4285138748 4286193733 4288687689 4285795650 4285272378 4286059586 4288624976 4291455586 4289477709 4292239990 4291191385 4291842656 4291975524 4291321440 4292439925 4292639861 4292968839 4292972151 4293296007 4293235340 4293567626 4293570991 4293571482 4293573544 4293572016 4293569418 4293634736 4293309353 4293298307 4292114806 4291061104 4291126362 4288494415 4287114313 4285534524 4285927743 4285602377 4286717256 4286585160 4286653767 4287704135 4287700039 4286984780 4285468215 4284551742 4283762500 4284617027 4287249256 4285273673 4292913567 4291664800 4289483877 4289024103 4284684612 4285076290 4286527564 4285211733 4286327881 4285211466 4285406018 4285078341 4284488517 4284684350 4284618813 4284947012 4285339966 4284424006 4283829061 4284685894 4288236653 4290738037 4291134596 4290477176 4289554539 4291132025 4291857026 4292448134 4292121720 4292383366 4292316032 4292186997 4292119161 4291659650 4292119415 4292448640 4292053615 4292053635 4292119415 4291922048 4292119417 4291790968 4291790712 4291792510 4291792255 4292119159 4291725959 4291725943 4292185209 4291397251 4292250734 4291397251 4291922295 4291922295 4291529862 4291594111 4291659647 4291595397 4291529603 4291921790 4291595139 4291398029 4291396998 4291134600 4290804854 4291136645 4291396228 4290479495 4290542466 4291134082 4290673781 4290345589 4290082945 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289610574 4289612123 4289610323 4289807951 4289610324 4289414743 4289610825 4289610833 4289872970 4289546312 4289018190 4289217618 4288555848 4289872980 4291386958 4292768365 4292442461 4292837485 4293497471 4293564021 4293500028 4293501317 4293500283 4293698940 4293500031 4293764215 4293500802 4293563772 4293496694 4293033305 4292177256 4291515986 4289281356 4287247695 4288032327 4288359495 4288230732 4288688715 4289283149 4289151821 4290004047 4290201938 4290136401 4289873493 4290265930 4290331729 4290004042 4289871185 4289216589 4290068564 4290069840 4289412945 4290263881 4289609295 4289677405 4291332770 4291204501 4292188027 4292115297 4292967278 4293164904 4292969597 4292771963 4292772445 4292904303 4292707697 4289742162 4291122264 4291789181 4287709026 4283957309 4283958852 4283237431 4283173973 4285676394 4286072947 4286922116 4287650706 4288840883 4285208150 4285473635 4287059856 4285608291 4288442789 4284752730 4283435851 4284291640 4286528620 4286005358 4284552516 4283700035 4287324286 4284288067 4283894855 4283959616 4283829335 4284291149 4288772512 4288306591 4284093247 4283893561 4284159546 4285141563 4285142324 4284090176 4283632699 4283503427 4282843187 4285411148 4292715411 4291056987 4290733435 4292987056 4292448126 4292517012 4292912526 4292785829 4293182387 4292657330 4292130210 4292652966 4292979092 4293382328 4290875748 4287371579 4287837514 4288031303 4287700809 4285599550 4286257737 4285536579 4285602628 4285664574 4285338171 4285929538 4285733187 4284552764 4284879926 4284419124 4284090164 4284743741 4286847040 4291124837 4292444545 4291845218 4291976812 4291910244 4292240496 4292374901 4292900971 4292771445 4293033348 4293101192 4293627003 4293568656 4293569946 4293572516 4293506995 4293508770 4293574826 4293310614 4293435784 4292245086 4288361038 4286652479 4285076543 4285793342 4285403455 4285601856 4285794363 4285206075 4285274173 4285669186 4285995848 4286389576 4286851655 4286590541 4284745526 4284551998 4283762764 4284287032 4286659945 4285270344 4292650397 4292650402 4288765551 4288824932 4286591830 4284027965 4285935963 4285671495 4285604423 4285737035 4285472836 4284617021 4284684350 4285274942 4284816194 4284882243 4285604940 4284226370 4283696201 4284748858 4288700539 4290937209 4291130472 4290146679 4291258992 4291068785 4292120183 4291988614 4292448125 4291594621 4292448391 4292053369 4292119408 4292119417 4291922047 4292052344 4292447866 4292382845 4292053891 4292119417 4292119407 4291725443 4292119424 4292119169 4292119933 4292119170 4291989619 4292120960 4291725177 4291922297 4291397241 4291922304 4291463041 4291528576 4291594111 4291594112 4291594112 4291594108 4291398032 4291595396 4290939012 4291725181 4291265404 4290216832 4291790717 4290805124 4290479472 4290150783 4290676352 4290084989 4290082945 4290148994 4290212992 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289282895 4289677646 4289480280 4289085265 4288957010 4289282901 4289544269 4289151565 4288953937 4289282894 4289147979 4288754764 4288165196 4289346379 4291120206 4292635990 4292443508 4293493610 4292841845 4293630333 4293500028 4293697907 4293699197 4293698684 4293698423 4293500291 4293764471 4293563263 4293230440 4293034350 4293097585 4290466131 4289347149 4287313225 4287375175 4288361546 4288754764 4288624974 4289083982 4288950858 4289413715 4289740620 4289611353 4290331471 4290331723 4289609806 4289479754 4290069070 4289545547 4289741390 4289741646 4290067018 4289149269 4289347407 4290743466 4292581767 4294500247 4293097824 4292177258 4292575328 4292444275 4292378221 4292969852 4293231227 4292314241 4291127675 4288039527 4284354121 4287251300 4287443541 4283565120 4283172928 4283106126 4286927751 4288507815 4287116146 4285609830 4288969909 4285737551 4287778956 4285739877 4286990984 4286662259 4288710588 4284422978 4283501654 4283633989 4286529392 4283564089 4286725511 4283830590 4287850153 4283960375 4283830847 4283893572 4283500604 4283631933 4285080664 4288444072 4288309924 4285672545 4282908720 4284352049 4285141822 4284814399 4283174217 4283303998 4283433012 4290741630 4291655276 4289479758 4292788659 4292910973 4292841612 4292716930 4292456086 4292851379 4292986294 4292459183 4292588206 4292588954 4292527542 4290943848 4287239744 4287503431 4287178824 4286385732 4285470016 4286190405 4285339708 4285276229 4285927229 4285206076 4285272628 4284352582 4285472841 4287316062 4287313233 4285403964 4284288562 4284484922 4284549180 4286845760 4291645277 4291719292 4291913321 4292501352 4291976806 4292437883 4292505440 4292835208 4292772980 4292968339 4293628794 4293175201 4293570219 4293508770 4293706419 4293640373 4293640619 4293635982 4291190367 4286652231 4285472585 4284618304 4285277003 4285535549 4286851141 4286717504 4285403709 4285471294 4285928770 4285801805 4285539144 4285537090 4287177802 4285730110 4285207094 4285141567 4283894583 4284029254 4286786394 4284616507 4292514956 4293044134 4289617770 4288106083 4285803592 4285736273 4285541458 4285736008 4285867851 4285406019 4284748855 4284487239 4284423237 4285208638 4284487742 4285602883 4285015116 4284292160 4284024394 4285145679 4289881203 4291659397 4290803573 4290080885 4291392381 4291922816 4292448391 4292382597 4291859066 4292119160 4292053623 4292119427 4292052348 4292448120 4291922303 4291791490 4291528309 4292119426 4292118130 4292119418 4292120192 4292119414 4292249729 4292119416 4291332734 4292184951 4291790978 4291725176 4292119673 4291790969 4291856770 4291856768 4291922295 4291528577 4291594112 4291396989 4291528059 4291398289 4291527800 4291659647 4291005061 4291462792 4290084988 4291724666 4290544766 4290676349 4290804864 4291002764 4290739584 4290476928 4290542978 4290345588 4290411394 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289151058 4289085266 4289546059 4289151059 4289216588 4289546066 4288953680 4289282893 4289085264 4288625741 4288758354 4287769157 4287705162 4289148488 4290664538 4292110180 4292901724 4292837486 4293693816 4293566077 4293500799 4293697908 4293498742 4293698423 4293501318 4293763440 4293501060 4293561969 4293694321 4292706405 4292504404 4291123552 4289542986 4287310919 4287375432 4288360007 4288689228 4289347147 4289215568 4289151821 4289283152 4289413198 4289545033 4289677133 4289216590 4289740876 4289741396 4289477968 4289806926 4289609544 4289083208 4288951883 4288751178 4292119937 4293838754 4293966228 4294231416 4291580745 4292703837 4292507249 4292836700 4293100911 4293233520 4290928223 4290867329 4289817463 4286915403 4286527830 4285930048 4283958329 4283500359 4283039801 4287525024 4288705195 4285409359 4283826222 4288443568 4284357954 4283962711 4286005886 4286924151 4286132333 4287590049 4288773025 4283898706 4283499319 4284096333 4286266735 4283698760 4285278036 4285146967 4288377760 4284489031 4284487751 4284554058 4284223286 4284222285 4283435077 4285674585 4288441497 4287190407 4287187071 4285208919 4284351547 4283763000 4283763007 4282712115 4287449703 4293172108 4288622656 4292122530 4293180581 4292842633 4292909195 4292518292 4292521361 4292591283 4293181880 4292657332 4292457381 4292986287 4291862662 4287042109 4288622407 4287114056 4286518856 4284747061 4285536831 4285206073 4285863235 4285205817 4285730116 4284550973 4285141588 4286585150 4287582327 4291276720 4291079361 4289485441 4285668164 4283891766 4284090163 4284022838 4286522697 4292239962 4292308838 4291649382 4292042594 4292700520 4292438907 4293161833 4292703882 4293361277 4293561981 4293568398 4293703851 4293838520 4293772214 4294235057 4293508502 4289939287 4284287291 4284553800 4284223303 4284621899 4285539410 4286525282 4288766855 4290411660 4288104285 4285204797 4284680502 4285600572 4285799747 4286192970 4285734468 4284812085 4286126148 4284422213 4284287807 4284616506 4286659171 4285466680 4291728280 4293046441 4289421427 4287382112 4285801027 4285472849 4286067285 4286329422 4285801290 4284816450 4285011527 4285010482 4285274431 4285143102 4285404727 4284817995 4284553792 4284291151 4283963971 4287905118 4290541689 4291656049 4291132022 4290606197 4291725435 4291595913 4292054899 4292054142 4292054910 4292054141 4292119428 4292053614 4292316288 4291856002 4291789938 4291592570 4292119673 4292316287 4291724413 4291922294 4292119424 4292118151 4291921793 4291725431 4292185217 4291725697 4291987581 4292119680 4292117380 4292119673 4291593845 4291922561 4291463041 4291725182 4291331453 4291725184 4290545799 4291593594 4290480014 4291593595 4291527545 4290674298 4291462791 4290346116 4290739576 4290805377 4290083202 4290082421 4290674037 4290542978 4289819765 4290475394 4289951092 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289085259 4289743451 4289480280 4289019214 4289019216 4289348944 4289085008 4288494413 4289150800 4288757585 4288293960 4287838029 4288359239 4289148489 4290662735 4292439659 4292900700 4292969326 4293431424 4293369967 4293566853 4293565308 4293566334 4293501831 4293499513 4293501832 4293565561 4293564286 4293297772 4292772197 4292504679 4291450194 4289281608 4287245383 4287967047 4288229450 4289214284 4288952910 4289151826 4289478739 4289610832 4289740877 4289479760 4290264144 4290069577 4289938519 4289675340 4289938762 4289543761 4289804878 4289542734 4289019214 4288751179 4293633670 4293372833 4294035852 4293293148 4290796897 4292112750 4292508252 4293099628 4293166702 4292442223 4287706470 4291851376 4290996084 4285999955 4287048534 4283040325 4283569741 4283829840 4285745272 4288113546 4285144663 4283367478 4286800026 4286463846 4282843203 4282780487 4286331248 4288574640 4287188357 4287585924 4287056247 4283633993 4283698244 4284162635 4285211719 4284154695 4283636044 4284221502 4287257978 4286268525 4284158530 4284683843 4284287814 4284552507 4284358212 4284028221 4284684864 4283697208 4285081161 4286467183 4284554314 4284220995 4282778418 4283762747 4292055177 4290927196 4289089904 4292987831 4292644981 4292516484 4292522905 4292584848 4292456363 4292986303 4292591033 4292853411 4293248697 4291930767 4286979643 4288886860 4288033870 4287043651 4285140796 4284614198 4284947524 4287510607 4285536829 4286063176 4285732939 4283236923 4285079104 4286921064 4286918739 4293245876 4293378746 4292065466 4290415257 4286455108 4285731902 4289152875 4287242819 4290992219 4292107369 4291778404 4292303715 4292043880 4292963174 4292574074 4292769638 4293363076 4293363590 4293566090 4293441971 4293904571 4294103481 4294234542 4291457377 4286059331 4284094787 4284552260 4284159296 4284093529 4286392382 4290615230 4288762976 4291601329 4291129462 4286916678 4285205819 4284156211 4285996102 4285405501 4285275205 4285470271 4285076287 4284748606 4283958328 4284685122 4287247709 4284153917 4292120197 4293111453 4289288831 4288103002 4286791520 4285933381 4286791000 4285670216 4286261066 4285276233 4284943934 4284814905 4284618814 4285015374 4284817482 4284554051 4284485961 4283897411 4285667922 4288697698 4290869369 4291593077 4291134329 4290472306 4291594109 4292119932 4292448383 4291987833 4292381815 4292449159 4291594093 4292579204 4291528308 4292119681 4292119683 4292119663 4292315525 4291461232 4291988087 4291987830 4291725443 4291987828 4291725688 4292185220 4291986552 4291789947 4291791223 4291856770 4291397505 4291856760 4291857017 4291658880 4291922561 4291922551 4291594113 4291528318 4291396473 4291462782 4291856510 4290676622 4290087557 4290739320 4290411125 4291133816 4290607989 4290279811 4290411381 4290214006 4290213251 4290278784 4290016884 4289624451 4289622660 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289414738 4289480273 4289348429 4288693331 4288627788 4289609805 4289151572 4289348429 4289346891 4288753995 4288296524 4287836234 4287835207 4288560459 4291253332 4292440154 4292115050 4293297517 4293628786 4293370743 4293565822 4293305465 4293565307 4293500286 4293698939 4293697911 4293501831 4293633413 4292969838 4292968290 4292570215 4291057743 4288888145 4287769671 4287770183 4288755276 4289082955 4289739850 4289283414 4289413196 4289479760 4289872720 4289872719 4289218386 4289545040 4289283660 4289939027 4289676877 4289611087 4289214541 4289347665 4289345612 4287634755 4290271584 4293046163 4293047670 4292919204 4292247678 4292310388 4292442475 4292968573 4292968813 4291982183 4290994801 4294023794 4288755020 4284683834 4285469266 4283304006 4284488279 4287320965 4287387268 4284481594 4283566910 4286334062 4286527065 4284685406 4283501645 4284681809 4285806184 4288707738 4286591865 4286932880 4287054721 4284751942 4283896398 4283766077 4284091209 4284354874 4284881227 4283304267 4284755796 4288443022 4285079638 4284552770 4284090166 4284549196 4284418876 4285014867 4284618052 4284156977 4284293962 4284029255 4283958841 4284621908 4286328949 4288895866 4292906096 4288885323 4292917421 4292981909 4293041274 4292652182 4292588191 4292521379 4292854965 4292985790 4292986029 4292920756 4292590745 4287246912 4290004565 4289149516 4286783558 4285600581 4284748599 4285533247 4287243333 4289746545 4287574602 4286789204 4288238448 4285272386 4285998151 4288435830 4284088363 4292656837 4292985012 4293444789 4292723129 4291393679 4287240508 4290993503 4290463827 4290329674 4291320922 4291447898 4291189604 4292501351 4292111993 4293225064 4292963446 4292967811 4293630330 4293502621 4293838776 4294038200 4294301632 4292387215 4288427331 4286979921 4285209150 4286724951 4284353341 4284750914 4286261061 4288300910 4287122540 4293046197 4291659913 4289738821 4285734474 4285008950 4285406016 4285598777 4285797955 4284880448 4285207096 4284753995 4284618308 4284552773 4287184499 4284284986 4291859101 4292519846 4290345603 4288424528 4287189371 4285799485 4286530407 4285210439 4285342795 4284686410 4285470008 4284816451 4285077563 4284814134 4284685895 4284419900 4284292163 4284423754 4286261838 4289817984 4291461995 4291391360 4290738293 4291066230 4291921266 4292448647 4291987840 4292644216 4291988097 4292053375 4292514183 4291528317 4291659647 4291791481 4292248693 4292315004 4291331187 4292185467 4291988095 4291920762 4292577906 4291462275 4292183933 4291594092 4291658362 4291988095 4291987331 4291592559 4291857017 4291659648 4291659637 4291922562 4291790709 4291134076 4291528318 4290217080 4291133829 4291134590 4291002490 4291790716 4290411395 4291133816 4290739840 4290411393 4290148995 4290082933 4289949571 4290017155 4289819508 4289492611 4289490819 4289163395 4290082419 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290003795 4289217363 4289743450 4289085265 4289807445 4289283151 4289414216 4288560209 4288689741 4288168785 4288885836 4288491079 4287180359 4289540939 4290662993 4292503640 4292965470 4292642934 4293628029 4293565313 4293501316 4293763704 4293501314 4293697907 4293700226 4293698682 4293500541 4293563777 4293495160 4293097566 4292243291 4291843929 4289413197 4288228166 4288360007 4288755020 4288559438 4289545038 4289414988 4289545041 4290135373 4290070605 4290266448 4290136402 4289611089 4290200913 4289808727 4289806414 4289545304 4290005325 4290004815 4288164170 4284809277 4288435534 4292259257 4285270077 4288498502 4294035106 4293834922 4292970091 4292771433 4292970357 4290663266 4287114821 4287506765 4284093503 4283303496 4283764043 4283502156 4286995088 4288044922 4284356698 4283564087 4286137468 4285935971 4284027472 4286534012 4284220493 4284160334 4287124364 4288440741 4285870697 4288908458 4286594164 4283700029 4283635271 4284816203 4284488007 4284227404 4284352576 4283369802 4285142343 4289167281 4285737561 4284484672 4284486728 4284026429 4284618808 4284949319 4284353592 4284155962 4284418879 4284091190 4283371334 4283367494 4284489529 4289293452 4287181389 4290210944 4292720289 4292050819 4290740859 4291464868 4292125089 4292525488 4293051839 4292264373 4292788662 4293117345 4289548133 4289676885 4291451996 4289809247 4289215053 4288689748 4286060612 4285729087 4288293712 4288891729 4290145404 4285601093 4286659676 4288170084 4287447648 4285597738 4288702635 4292924615 4293380031 4293445050 4293839547 4293174933 4288953184 4288885071 4291782245 4289802569 4291120722 4291055198 4292039266 4291452003 4292109158 4292963175 4292114553 4293693319 4293365379 4293505194 4293772725 4294102979 4293841587 4291979877 4288756053 4289815158 4285537082 4288762737 4287842913 4287903056 4287975023 4285269559 4290280354 4292978075 4292182412 4289284170 4286784072 4285402169 4285074999 4284483383 4285666622 4284748084 4285338938 4284353605 4284090435 4285341504 4287250531 4283957300 4291135887 4292523177 4291198854 4285999941 4287911275 4286196305 4287646558 4285275979 4286063170 4284618302 4284421176 4284422981 4285079108 4285144134 4285209926 4284554309 4284226627 4284879943 4286989929 4290670711 4291133306 4291265132 4290603634 4291002488 4291922562 4292120710 4292120444 4292055166 4292119169 4292119415 4292119425 4291594101 4292185476 4291789938 4291988097 4291791471 4291855743 4292052335 4291330431 4292185465 4291659898 4292512380 4292054392 4291985799 4291397497 4292185209 4292119673 4291791483 4291986554 4291857017 4291462525 4291789433 4291199859 4291528575 4291462782 4291264889 4291068282 4291462522 4291134084 4290542720 4290937477 4290673267 4290609038 4290345844 4290211700 4290016375 4289885303 4289687927 4289687414 4289360773 4289756540 4290939005 4291793288 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289546585 4289480278 4289217364 4289676360 4289480530 4289282900 4289415003 4288559951 4288693328 4288822608 4288295244 4287967047 4287375175 4288559182 4290204239 4291847527 4292509297 4293232241 4293628285 4293498747 4293699195 4293698168 4293500032 4293502089 4293699451 4293501319 4293763958 4293566332 4293298803 4292706674 4292570199 4291386199 4289086282 4288164941 4288229193 4288754764 4289148234 4289216336 4289740628 4289611340 4290530131 4290923087 4290005068 4290069585 4289874778 4290331987 4290070616 4290531663 4292044893 4288361285 4286388288 4285799751 4283893560 4283630393 4291731099 4290208893 4290685092 4293043858 4293970858 4294107604 4293837726 4290400076 4283959365 4283108423 4284091968 4283829067 4283959111 4283371842 4286860417 4287054944 4284945227 4284950111 4284620631 4286592878 4285214832 4284489022 4286198124 4285281125 4286133631 4287391119 4288638109 4286527872 4289367719 4286860676 4283435327 4284157258 4284687434 4284421704 4285409358 4284288834 4283567687 4284617535 4286665327 4285208145 4284225593 4284751943 4284419134 4284419391 4284554309 4285273150 4284157760 4283893822 4284419144 4283569744 4282977863 4289095300 4290141541 4287903832 4290753463 4291068292 4292121749 4292060050 4293047713 4292526521 4292985531 4292656817 4292854454 4292790438 4289414230 4289547350 4291256158 4291454048 4291781496 4291126109 4290401627 4289217617 4285858365 4286123070 4290072150 4290599780 4289291646 4286261842 4284617016 4285667914 4288110494 4292133055 4293576118 4293575348 4293771697 4293310895 4292972412 4291190119 4290853965 4292108643 4291119958 4291186259 4292174187 4291187035 4292171111 4292174950 4292375161 4292900967 4292575627 4293630581 4293638845 4294103488 4294103748 4293512367 4290333793 4289939550 4291001473 4290076816 4285868109 4287775836 4286990438 4286062406 4288765333 4291671737 4292842909 4292508555 4289869643 4286587720 4285730366 4285009212 4286385988 4285075766 4284681524 4284354107 4284419383 4284417603 4285870935 4286725214 4284089928 4291265694 4292979362 4291264900 4286193734 4287188084 4286788442 4286923618 4285537347 4285276234 4284618301 4285472322 4285275719 4284356931 4285737551 4285339967 4284552503 4284223044 4284355906 4288895087 4291003001 4291134328 4291129458 4290475906 4291725171 4291790711 4292119933 4292119943 4292119159 4292119426 4291659896 4292119681 4291594102 4291791216 4291921281 4291593591 4291855496 4291857016 4291593854 4292119166 4292052090 4291791481 4291920252 4292118396 4292119928 4291659638 4291462269 4291790717 4291988086 4291986554 4291659639 4291921267 4291397505 4291133817 4291002748 4291331196 4291199352 4291005317 4290542465 4291199867 4290476918 4290342770 4290871683 4290148212 4290015875 4290148214 4289425543 4289556341 4289687926 4289691008 4291004529 4292118917 4291793291 4292386195 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289610573 4289414743 4289414742 4289676117 4289019722 4289546072 4289283157 4289281098 4289414221 4288100945 4288427083 4287376967 4287375175 4288559182 4290858839 4292109658 4292903264 4292837229 4293234551 4293566332 4293698424 4293500805 4293698938 4293699451 4293501317 4293500802 4293501830 4293565314 4293430644 4293099872 4292240994 4291318092 4290070353 4288556872 4288820299 4288624974 4288954961 4289806413 4290596169 4289414227 4290529105 4290201940 4290267476 4290793306 4290923603 4289348176 4290987590 4289345864 4286392132 4284945477 4286725471 4286060876 4286595166 4289422720 4292520098 4290740627 4294021520 4293638561 4294967256 4294965695 4290869602 4284223309 4285873771 4283368518 4284157506 4282910535 4283763514 4286003566 4288042137 4286266487 4286465410 4285478247 4284221519 4285608554 4286268530 4286596492 4286463850 4287779457 4285737567 4287590565 4287584403 4285802065 4287856563 4287915677 4284421696 4284949583 4284354118 4283698744 4285275974 4284224073 4284746551 4284289603 4285736010 4284748357 4284948562 4285472072 4284487232 4284812350 4284356924 4284486726 4284091449 4283436346 4283238199 4283504206 4287054430 4292252037 4288228429 4291135879 4292653223 4292378992 4292650132 4292652700 4292525490 4292525237 4292330176 4292918948 4292655527 4289153095 4290663779 4292238714 4291319131 4292106598 4292243572 4292505973 4292374645 4290206060 4288164167 4288035148 4290069583 4291189099 4291589000 4290145938 4289879940 4290084764 4292459708 4292658617 4293181621 4294168511 4293773238 4293173651 4292634220 4293100654 4292240238 4290595922 4292309098 4291646558 4291578709 4292107874 4291715430 4292107878 4292108900 4293029238 4292969353 4293566090 4293641395 4294038725 4294104518 4293442473 4290069322 4289083208 4290142324 4291199367 4289292159 4287907454 4287909249 4289623731 4291147450 4292978098 4292058283 4292048242 4289476928 4286782023 4285536836 4285667648 4286057279 4286324554 4284489544 4284420412 4284753488 4285012288 4285804624 4286133086 4284092733 4289685104 4293112748 4291071129 4286656344 4287186289 4287251547 4287055961 4285606742 4284552249 4284554310 4284488516 4284748350 4284618814 4285669190 4284947780 4284554566 4284484416 4285343825 4288569967 4290936697 4290803317 4290804086 4291065715 4291725182 4292582033 4291660155 4292119169 4292120185 4291659896 4292577661 4291725697 4292053375 4292052858 4291266166 4292249468 4291987320 4291593844 4291860625 4291462527 4291265899 4292185476 4291790203 4291791480 4291790979 4292250745 4291200118 4292185465 4291987330 4292119424 4291133821 4292119672 4291199860 4291331197 4291396988 4291133817 4291330937 4290674041 4290542453 4290870902 4290936439 4290608759 4290344067 4289820022 4290541187 4289425270 4289753460 4290676611 4291658877 4291989112 4292581014 4292125058 4292651419 4292653192 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289742166 4289546322 4289611865 4289414736 4289480279 4289414482 4289546310 4289018190 4289149261 4288757326 4288363855 4287966279 4287244359 4289148235 4290728784 4292503911 4292835164 4293036403 4293495677 4293171580 4293566079 4293305207 4293698683 4293501318 4293502087 4293764215 4293501575 4293499765 4293627769 4292968301 4292637019 4291518812 4289740882 4289215566 4287445586 4289213770 4289542477 4289478224 4289873231 4291119697 4290792275 4290729052 4290728021 4291251539 4290596689 4291063409 4285074489 4284417090 4284418363 4285403965 4289156727 4290215056 4292251041 4292772486 4293041283 4293509315 4292780418 4294895022 4292187496 4285540151 4283302987 4283898682 4287585434 4282976575 4283305813 4285408863 4287455918 4289367741 4288111755 4286796158 4283236399 4283436106 4283564105 4286600089 4284353854 4287778439 4285874030 4285936487 4285871488 4287526816 4288509628 4284092753 4289109693 4288440477 4286531447 4285341509 4285213271 4283765317 4284486728 4284155696 4284353343 4284488523 4284554048 4284225609 4286063944 4284947267 4284881227 4284684348 4285016398 4284225086 4284156986 4283304256 4283173691 4284354120 4291989639 4290005586 4289484151 4293446844 4292580996 4292580496 4292585619 4292522913 4292657339 4292919733 4292527532 4292132268 4289280828 4291119964 4291322720 4291518305 4291519855 4291320921 4292572776 4292180616 4292441206 4293032293 4290996606 4290595163 4289281900 4289873751 4291450215 4292111455 4292380575 4292970646 4292513673 4292713371 4292915365 4293635995 4293042585 4293174953 4292250784 4292635773 4291714173 4292502641 4292240744 4291976289 4291844197 4291777891 4292108647 4292044410 4292105828 4292639609 4293624704 4293565322 4293639863 4294040263 4294169540 4292782750 4290996100 4289743719 4289940306 4291121785 4291657618 4291395988 4291659678 4292055977 4293042594 4291924889 4292442983 4290923596 4287770699 4285202485 4286326857 4286981192 4285865288 4286127432 4285471298 4284291146 4285081165 4284619079 4286397004 4286393942 4284353855 4289424782 4293175698 4291205789 4288038759 4287117645 4287189874 4285798720 4285670214 4285080145 4284550197 4284750410 4284091955 4284749113 4286061636 4284948037 4284484656 4284488262 4286593873 4290014589 4291003000 4291263606 4290144370 4291200122 4291922560 4291725700 4292184962 4291725432 4292119160 4292185219 4291331951 4291855484 4291857018 4291725174 4291067769 4291659647 4291987320 4291790978 4292185218 4291860110 4291658634 4292381296 4291790207 4292052866 4291791223 4291791233 4291659647 4291659638 4291528317 4291526510 4291463032 4291592312 4291331445 4291067767 4291067767 4291330937 4290542979 4290540145 4290608515 4290411650 4290610044 4290737011 4290016630 4290082167 4289622647 4290673528 4291728001 4292252048 4291796612 4292717469 4292128391 4292719242 4292981896 4293439119 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289482331 4290071384 4289741909 4289807701 4289612640 4289677646 4289609805 4289085264 4288626257 4288164427 4288361804 4288492106 4287897671 4288558668 4290400334 4291913831 4293294686 4292838767 4293497215 4293172338 4293566337 4293565822 4293698682 4293699197 4293699196 4293501832 4293698681 4293697913 4293561982 4293231210 4292571501 4291318609 4289348432 4288623435 4288752712 4289086290 4289479246 4290068557 4289545560 4290333780 4290074202 4291318353 4290597724 4290530898 4292109402 4289159764 4283760699 4284023612 4286458174 4289548155 4291662733 4292249999 4290936975 4292249738 4291522181 4291660173 4293638592 4289948522 4283106356 4283899488 4283766855 4283631967 4287321741 4287520666 4288041876 4287393177 4287122798 4284620106 4286534021 4284356685 4283108164 4283565125 4284291395 4287721128 4283237425 4286731655 4285937268 4285674346 4286135946 4287454087 4289236144 4286989708 4289305512 4286926983 4286923642 4285017690 4286925439 4283371328 4284420418 4283828553 4283962682 4284486717 4284420938 4284552515 4285011268 4284683070 4284682556 4285144901 4284552514 4284812089 4283566395 4283304250 4283105327 4288371034 4292444795 4288751935 4291863713 4292916640 4292514189 4292583826 4292587678 4292459442 4293445303 4293117866 4292329649 4289280570 4290004565 4291582047 4291714679 4291585636 4292111731 4291783033 4292834682 4292833909 4292376953 4292377207 4292571525 4291256156 4291914865 4291519091 4290399069 4291647839 4289539914 4290665566 4292701813 4291193697 4291849322 4290273135 4292313474 4292056988 4292648113 4292520873 4292976265 4292506995 4291844196 4292041831 4291648353 4291780964 4292237928 4292042854 4292501097 4292703609 4292638592 4293238689 4293703334 4294038725 4294106567 4293113262 4293368969 4292385449 4291596451 4291065464 4292642696 4292175212 4291320929 4292376182 4291262573 4289545046 4288754249 4287636809 4286975299 4285603650 4288298579 4287706185 4286389064 4286061125 4285406533 4284223804 4285672014 4284816455 4286067296 4285868098 4283370570 4289618811 4292714386 4291862684 4288764006 4285804636 4288695916 4285935180 4285932619 4284224827 4284554310 4285143098 4284685118 4285534010 4285409101 4284817224 4284684871 4286334557 4288760428 4290540919 4290935158 4290210419 4291195506 4291265917 4291856511 4292119943 4291725422 4292119417 4292513410 4291725432 4291723642 4291659647 4291462258 4291528060 4291397246 4291725182 4292053632 4292184951 4291792261 4291926670 4291462773 4291594112 4291725182 4291463032 4291856770 4291791232 4292185208 4291659639 4291528317 4291855473 4291133819 4291331445 4291199611 4290739576 4290805112 4290805111 4291265142 4290542980 4290476662 4289754485 4290540415 4289951618 4289885570 4290673529 4291332200 4292188551 4292320154 4292390516 4293110406 4292979589 4292980363 4293306751 4293046137 4292983964 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289872466 4289676373 4289547868 4289546329 4289480016 4289348437 4288430671 4289216592 4289213770 4288756559 4288359238 4287901511 4287310151 4288622665 4291119692 4292374362 4292443506 4293036147 4293431665 4293565315 4293566850 4293501059 4293501315 4293699198 4293831795 4293501576 4293700224 4293500027 4293629053 4292839282 4292964175 4291649367 4290201677 4287901769 4288755020 4289082443 4289283403 4290071108 4290070873 4290462539 4291384403 4290005337 4291251794 4290726232 4292107591 4290934127 4284153912 4285669437 4291786387 4291587700 4293042317 4291260025 4289950089 4290081947 4289948816 4292186240 4288368471 4284423245 4286133870 4285736540 4284290131 4284554322 4284223822 4288577188 4288442010 4285143393 4283632960 4287719586 4287059324 4283171381 4283829066 4284226138 4284291127 4287194792 4284096354 4286335338 4287191952 4283565639 4285609072 4287456158 4287848852 4287913120 4288773800 4286856567 4287454362 4288583609 4283827256 4283959098 4284552010 4284160839 4284750404 4284614461 4284421195 4284815932 4284485445 4284353341 4284753488 4284947264 4284484915 4283894076 4283304757 4283040831 4285144382 4291925653 4290396233 4289680491 4292526759 4292251005 4292582288 4292587924 4292523432 4293116602 4292527797 4292593066 4288624962 4289410382 4291775831 4291518819 4292112243 4292373364 4292441715 4292634998 4292375410 4292114567 4292573026 4292637319 4292180613 4292770440 4292508280 4292570741 4290728531 4291911531 4289676376 4291192951 4291129981 4290604174 4289941861 4290271096 4291134855 4292180620 4292381055 4292970380 4292376688 4291849336 4291842912 4291583073 4291583860 4291717244 4292237670 4292043112 4292106342 4292310900 4293098612 4293235081 4293506485 4294104261 4294106058 4292983209 4292776097 4292576621 4292508018 4292637556 4291783525 4290598009 4289484393 4289550709 4289613906 4287313001 4287374920 4286654792 4288626008 4287772494 4289543502 4287966026 4286256453 4285996103 4285466937 4284483897 4284750410 4284949324 4287315800 4285803081 4284288359 4289158000 4292977055 4291995040 4290210435 4285998931 4287780717 4286523977 4285406018 4284488516 4284619588 4284358732 4284484920 4285603911 4285734726 4284029507 4284685128 4286657871 4290275189 4290477689 4290935158 4290735731 4291066230 4291725173 4292120459 4292253305 4291790722 4291790977 4291725441 4292185208 4291594102 4292119167 4291856770 4291725182 4291594368 4291134076 4291526508 4291659638 4291528579 4291133552 4291659649 4292316536 4291134076 4291789433 4291725173 4291724674 4291659647 4291659637 4291790467 4291395964 4291199610 4291199601 4291132793 4291066732 4290870905 4290345336 4290606197 4290278004 4290343796 4290015875 4290870388 4290542456 4291529080 4291858308 4292387463 4292781703 4292849779 4292979081 4292916620 4292916629 4293243264 4292851849 4293045146 4293178760 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4290201686 4289480787 4289611858 4289938775 4288759374 4289808975 4289216080 4288101200 4288754507 4288887118 4287773008 4288032583 4287441479 4288032841 4290859603 4291781210 4292574046 4293034605 4293628280 4293564539 4293500544 4293698938 4293500804 4293699452 4293501576 4293699195 4293699453 4293500800 4293563524 4293165418 4293291097 4291386198 4289676621 4289081673 4288688713 4289148491 4288954193 4289740878 4289741648 4290267727 4290661722 4291254870 4290726487 4290857039 4290660950 4291987332 4289424762 4290935934 4291196312 4290142349 4290345627 4291730337 4289095529 4287313231 4285013834 4285869661 4286664827 4286855785 4284357956 4284483910 4283306555 4284093263 4283171924 4284822105 4289499832 4288183486 4287388572 4289496245 4287055498 4286995873 4285015122 4284556637 4283105347 4287124346 4285210475 4285674592 4287654063 4285212503 4284559735 4287585420 4287058323 4288970158 4288771762 4288247468 4288713136 4284421184 4283039806 4284556878 4284292419 4284353846 4284424011 4284620357 4284616253 4284095813 4285142339 4284750140 4284555853 4284226629 4284486203 4283566388 4283304245 4283170872 4290410615 4292377712 4289018190 4291593351 4292385932 4292187023 4292586140 4292519329 4292722612 4292527549 4292987049 4288693052 4289013318 4290660436 4291646551 4291781739 4292175476 4292045189 4292771958 4292768115 4292115851 4292770675 4292903561 4292310898 4292571490 4292507237 4292838524 4292046212 4292638841 4292571494 4291979638 4292111216 4292111476 4292047477 4291652465 4292314257 4292380817 4292380560 4292576135 4292114043 4292444049 4291856273 4291582563 4291975524 4292242039 4292372833 4292042600 4292043368 4292301670 4292634230 4292706452 4293559931 4293506997 4293905596 4294040777 4293968570 4292320922 4292579454 4292576392 4292243588 4291913590 4291518830 4291915126 4291124846 4292109439 4291059547 4288757844 4288951113 4288823122 4289938761 4288626510 4289016905 4286059589 4286651978 4284812087 4284550708 4285338936 4285405762 4286067532 4285672294 4284286009 4288764799 4292383115 4292457653 4290410110 4286326609 4287776618 4286062404 4284355911 4285078340 4284552246 4284616255 4284353842 4286461009 4285078076 4284550978 4284550201 4287775589 4290149243 4290803318 4290801267 4290078835 4291397493 4292184951 4292122252 4292118902 4291725441 4292185208 4291791223 4291593090 4292119167 4291200117 4292119167 4291659127 4291527303 4291528568 4291857283 4291725184 4291723886 4291725441 4292117871 4291265920 4291462773 4291725439 4291396991 4291396980 4291397247 4292052862 4291068015 4291396990 4290673783 4291330939 4290805112 4290411384 4290936696 4290608504 4290408821 4290346360 4290540147 4290212481 4290216579 4291989120 4292386201 4292455796 4292652683 4293110935 4292916373 4293179020 4293245829 4292850313 4293638535 4292850573 4292981372 4293178509 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289348949 4289611865 4289545815 4288759380 4288758866 4289150543 4288691536 4288296269 4288820299 4287773522 4288032841 4287507271 4287043143 4288753994 4290463052 4292242005 4292573296 4292904564 4293300605 4293237889 4293566851 4293698938 4293698683 4293699197 4293501831 4293700222 4293500546 4293567105 4293627255 4292969581 4292506992 4292043854 4290200913 4289079878 4288097094 4288624972 4289217357 4289806926 4289741643 4290923344 4290726991 4290529870 4291185742 4290792536 4290265681 4292437342 4292119678 4292377995 4292843668 4293174677 4291917680 4289418850 4287048553 4285478507 4285148242 4286332004 4287646579 4285278543 4283501894 4283763524 4284884328 4284421462 4284423250 4284027491 4285080412 4288844471 4288776372 4288377508 4288510642 4287194002 4284882004 4284554325 4283369030 4285477480 4286333550 4285078885 4287454597 4288242602 4286466942 4285279066 4285606227 4287324573 4287256966 4289564600 4286861185 4286530931 4286593127 4285409620 4284613698 4284291142 4284487997 4284813887 4284553278 4284815676 4285143884 4284554307 4284813628 4284551997 4283697976 4283698507 4282777654 4286527565 4292514950 4290793557 4290073178 4292985264 4292972673 4292976524 4292455833 4292656563 4292986033 4293449656 4289153848 4288162891 4290461004 4291123290 4291909735 4292237157 4292506741 4292834419 4292508807 4292706934 4292509830 4292640886 4292771716 4292837251 4292967559 4292642431 4292442724 4292833651 4292310902 4292311159 4292963681 4292376695 4292572798 4292575106 4292576391 4292905357 4292643497 4292841864 4292970126 4292448930 4292973710 4292507506 4291650165 4292174692 4292242803 4292503436 4292109924 4292367464 4292371048 4291779682 4293424003 4292908188 4293572787 4294102717 4294104262 4293510583 4293111213 4292387235 4293036181 4292774528 4292443254 4292113510 4292636788 4291781237 4291716448 4291386462 4290399319 4290465110 4289348951 4289941597 4289939025 4288690252 4287174983 4286457929 4284745782 4285338688 4285406277 4284816197 4286130760 4285672273 4284355923 4288239730 4292908677 4292585635 4290344847 4286328651 4286984527 4284818762 4285733180 4285537604 4284555854 4284161349 4285012027 4285999437 4284814395 4284156994 4284421433 4288367461 4290083963 4291326835 4290344310 4290144114 4291134073 4292185991 4292118900 4292120199 4292184960 4291134077 4292251010 4291791223 4291857026 4291724153 4291723896 4291659138 4291922551 4291659639 4292248182 4291462770 4291527297 4291528059 4291331446 4291856511 4291134076 4291987067 4291397247 4291659906 4291265661 4291132266 4291396992 4291133809 4291133560 4290739576 4290608497 4291134084 4290934388 4290606197 4290608504 4289425015 4290148219 4291069056 4292188029 4292715650 4292653711 4292981129 4292983711 4293574014 4293114503 4293506431 4293178766 4292720288 4292849543 4293179021 4293570693 4293309569 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289807958 4289414743 4289151051 4289348173 4288822861 4288691536 4288755789 4287642450 4288885835 4287837515 4287443786 4287764551 4285340488 4287833926 4290071119 4292110944 4292573278 4292970358 4293102461 4293237114 4293566333 4293500801 4293698682 4293699197 4293501831 4293501831 4293567879 4293566590 4293561720 4293166960 4292964688 4291583576 4289544778 4288556105 4288755277 4289082956 4289413201 4289084753 4290135879 4289938515 4290725966 4291252053 4290529358 4291185741 4290596441 4290923858 4292310392 4292383379 4292445825 4290335599 4289486705 4288435577 4284685649 4284488520 4287054703 4287649671 4286265435 4284554586 4283434824 4283831366 4286205313 4284357437 4285935714 4285936228 4287387276 4287188869 4285941637 4285873774 4286797181 4285805156 4284223294 4283828547 4283567932 4284620374 4285872260 4285082706 4283896918 4287656357 4288703665 4287255449 4287586726 4287386003 4286137720 4287061650 4284224585 4287651219 4284226633 4284553535 4284225092 4284551741 4284029246 4284486712 4284682566 4284223043 4284621642 4284225102 4284292160 4284226637 4283830595 4283369787 4283762486 4291003783 4291784293 4289016650 4292119435 4292649874 4292520340 4292456862 4292852150 4293182645 4293450686 4289552981 4287043651 4289871178 4290858582 4291448412 4291582292 4291914615 4292109684 4292375668 4292510343 4292837509 4292837251 4292773000 4293035915 4292905880 4292907143 4292970385 4293100188 4292377984 4292903813 4292839841 4292967825 4292644482 4292839331 4292843166 4293104795 4292907415 4293104773 4293039007 4292905364 4292843144 4292906633 4292177284 4292173920 4292177015 4292833656 4292374114 4292696171 4292107111 4291977575 4292630375 4292770182 4293363590 4293175223 4294102973 4294042061 4293837747 4292654766 4292849062 4292842634 4292250500 4292969354 4292575879 4292442488 4292372066 4291912290 4291913336 4291714652 4291121750 4290732393 4291384409 4289810010 4289674052 4286325576 4287046729 4285074235 4285404735 4285470269 4286194760 4286656853 4285739092 4283829822 4288369521 4292318612 4292392124 4290214522 4287116382 4286529379 4286197579 4285012288 4285143613 4284422462 4284221497 4284749113 4285734984 4284289842 4284355403 4284684870 4289356915 4291130228 4291064173 4290344055 4290606197 4291725179 4291790719 4292120967 4291725183 4291726973 4292644993 4291330174 4291857017 4291658361 4291724153 4291331711 4291725181 4291528834 4291723897 4291266175 4291725183 4291922552 4291790976 4291593852 4291331445 4291462783 4291593088 4291265394 4291528319 4291133817 4291199611 4291002232 4291199602 4291133304 4291133560 4291264889 4290148727 4290082936 4290410872 4289819255 4289884279 4291399306 4292057985 4293373588 4292523664 4293245574 4293508225 4293507968 4293048712 4293112454 4293310330 4293113988 4293177227 4293179792 4293047162 4292785546 4293178767 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289415000 4289609803 4289019729 4288756042 4288363854 4288166737 4288886603 4288359237 4288295756 4288558924 4287506759 4287111240 4286717512 4287242310 4290201168 4291649880 4292967020 4292837740 4293562230 4293237127 4293566080 4293764473 4293501319 4293700224 4293698941 4293699451 4293502088 4293565816 4293629305 4292967788 4292507730 4291846483 4289544267 4288624460 4288688713 4289278790 4289084748 4290004298 4290463312 4290333268 4290730074 4290596184 4291187033 4290726229 4291186258 4290339704 4290863222 4290602621 4288956530 4289942633 4289217894 4285668190 4286466177 4287384703 4288175761 4285607779 4284158530 4285079125 4283568456 4285012561 4286597259 4286064747 4286795412 4287982251 4288113807 4286987895 4283765060 4285544037 4287915170 4284950093 4283041859 4283895371 4285210726 4284423259 4286859889 4286597247 4284159086 4283305533 4288971954 4288780477 4288048279 4285144664 4286070642 4286068845 4289574613 4285413219 4283237440 4284225606 4284619843 4284422468 4284882759 4284223037 4284486718 4284289348 4284487752 4284752457 4284356948 4284097093 4283505234 4282583888 4287843438 4292776303 4289804365 4289679979 4292585884 4292518032 4292522399 4292916652 4292984755 4293515461 4290413407 4285468223 4290390598 4290202453 4292103517 4291842915 4292369508 4291847266 4292308084 4292374132 4292902249 4292772230 4292969089 4293035917 4293366157 4293367180 4293362826 4292775831 4293763190 4292974749 4292711583 4293103240 4292646540 4293103762 4293041818 4292713109 4293040027 4293039758 4293036937 4293041310 4293102986 4292972688 4292445322 4292439406 4292176503 4292967530 4292309109 4292439398 4291911527 4292370536 4291911783 4292630631 4292572037 4293235589 4292849337 4293970360 4294039494 4293971131 4292980654 4293174684 4292778922 4292971399 4292840061 4292509317 4292379512 4292243335 4292373876 4291716213 4292040539 4291583608 4291057496 4291187801 4289480792 4289151828 4287567430 4286389577 4285273661 4285602110 4285209668 4286130249 4286654280 4285080133 4283499347 4288301668 4292122273 4293243559 4291267216 4286590804 4286066251 4286391373 4284616511 4285669957 4283700536 4284812610 4285404472 4285211464 4283894841 4284549179 4286786129 4289751145 4290803575 4290738295 4290341234 4291263350 4291464582 4292186503 4291725173 4292119426 4292119415 4291528318 4291725182 4291857017 4291921276 4291462524 4291528058 4291988354 4291001976 4291988344 4291528577 4291725183 4291790966 4291068017 4291199869 4292052605 4291199868 4291265651 4291199354 4290611074 4291462524 4291331454 4291395438 4291133561 4291002747 4290805369 4290804076 4290082937 4290671221 4289622648 4290081654 4291137153 4292191367 4293110918 4292655265 4293575063 4293377415 4293705107 4293048453 4293507468 4293112454 4293114759 4293177229 4293309566 4293178244 4292785039 4293637511 4293113221 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289412684 4288430672 4289150287 4289216592 4288755789 4288887117 4287706190 4288426057 4288557129 4287377738 4287636551 4287176776 4287176007 4287835978 4289610313 4292372829 4292506476 4293296489 4293234558 4293236351 4293566851 4293501574 4293501055 4293697912 4293832052 4293435527 4293700479 4293500284 4293562738 4293166959 4292964704 4291583580 4290005066 4288556873 4288163914 4289148748 4289215819 4289348174 4290003027 4290070097 4290858066 4290661977 4290661203 4290664022 4290793319 4291582049 4289810560 4288824943 4290801826 4291135135 4288766894 4289433030 4289699772 4289696188 4287320700 4284818271 4284818506 4284357208 4285078357 4285083222 4288440993 4285541214 4288183215 4287716483 4287781798 4286134380 4285805177 4289037493 4286857074 4283237951 4283239499 4283567694 4284027715 4285147748 4287715483 4288969379 4286465669 4285280866 4285212262 4285809261 4288509618 4286661783 4288373165 4288785870 4288048003 4284683342 4285213011 4285144901 4284618311 4284683586 4284619596 4284685389 4284093501 4284550205 4284357699 4283964750 4284227395 4284028230 4283044435 4284418872 4292054648 4291716186 4288953937 4291598483 4292648600 4293307546 4292523681 4292458409 4293315248 4291603076 4285072958 4287965255 4289347404 4290988625 4291449430 4291714655 4291518057 4292107621 4292309895 4292767606 4292573303 4293359745 4292903059 4293034880 4292969866 4292974996 4293167231 4292972693 4293236110 4293765000 4292974237 4292972957 4293366407 4293102230 4293763699 4292973985 4292975501 4293037982 4293040797 4293039515 4292777876 4292577390 4292771703 4292113030 4292636512 4292311927 4292371321 4292896871 4291977063 4291977063 4292960619 4291910245 4293028472 4292837255 4293702054 4293772725 4294038982 4294103233 4293309608 4292323996 4292845971 4292842892 4292445857 4292509572 4292771195 4292638049 4292242552 4292174436 4291913316 4292170853 4291452258 4291057755 4290925660 4288888393 4288161096 4285863237 4285141579 4285338684 4285866052 4285665597 4286527319 4286390086 4283564100 4287710042 4292777893 4292785052 4291530148 4287117138 4285540683 4285734982 4284353342 4285538885 4284422719 4284486969 4285013574 4284423237 4284812094 4284684610 4287643733 4290668663 4291266426 4290734962 4290083449 4291265659 4292251270 4291726451 4292120965 4292119415 4292119426 4291856759 4291659646 4291723896 4291462523 4292119166 4291528577 4291593594 4291396990 4291725182 4291725182 4291725173 4291592832 4291265395 4291528567 4291593843 4291265405 4291331188 4291133817 4291330681 4290279799 4291133559 4291133560 4290411384 4290868597 4291000182 4290082936 4290409077 4289754743 4290213753 4291005302 4292844694 4292980617 4293180038 4293116032 4293575308 4293770883 4292984961 4293311387 4293245296 4293309818 4293113229 4292785044 4293374338 4293112709 4293440888 4292784008 4292983451 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289085264 4289413196 4288760660 4288756815 4288230733 4288363857 4287902798 4287904079 4287378252 4287574602 4287046986 4286784071 4286061128 4287967046 4289609808 4291845968 4292245350 4292904819 4293693303 4293237890 4293370228 4293764730 4293500803 4293698682 4293633663 4293698682 4293698682 4293500283 4293561984 4293428330 4292572769 4291515733 4289544778 4289149005 4288097094 4289148748 4288954450 4289609543 4290069069 4289674059 4290070109 4291316037 4290597497 4290470537 4290475683 4290414249 4289368257 4289958849 4291468214 4290948796 4288579485 4287916416 4286927992 4286266978 4285540180 4285013334 4285212756 4286134120 4285013594 4286594427 4286994314 4286263921 4288113564 4287389596 4286396265 4287784090 4288770723 4287515259 4284224574 4283041866 4284288066 4283697466 4284490316 4283831645 4284355651 4286532993 4287518104 4287653793 4288113051 4286599584 4285738851 4289041839 4289180349 4288241294 4284883535 4288900746 4288958062 4287116883 4287316568 4283237956 4284094523 4284882758 4284353859 4283964231 4284421186 4283832653 4284419657 4283175248 4283239744 4288042607 4293170551 4288755801 4289942117 4292982197 4292583053 4292458658 4292457127 4293183164 4292988844 4284880433 4286714181 4288884807 4289869902 4291122009 4291384415 4291843941 4292303720 4292042598 4292109941 4292964453 4292573306 4292772231 4292968562 4293035138 4292775064 4293365131 4292909476 4293760887 4293237642 4293304223 4292975257 4293305226 4293697676 4292977049 4292973473 4293367431 4293168788 4292977048 4292976536 4293436038 4292644237 4293362072 4292640887 4292771451 4292308080 4292572044 4292572770 4292177527 4292106086 4292175464 4291976033 4292826219 4292437347 4293035143 4293240743 4293836984 4294040006 4294103747 4293178794 4293108887 4292844177 4292385947 4293101442 4292445548 4292767861 4292112263 4292504674 4292308854 4292043896 4292108391 4291518818 4291450465 4291188563 4290137172 4286915139 4285931593 4284945727 4285077063 4286194248 4285409099 4287181388 4285142600 4283237440 4287313245 4292385424 4292845986 4291270040 4288105050 4285341509 4285272382 4284024883 4286195525 4283827779 4285077816 4285603397 4284682808 4284487750 4284486205 4289550188 4290346619 4291065193 4290278776 4291127150 4291923074 4292121474 4291725694 4292184705 4291397239 4291856769 4291659646 4291856768 4291659646 4291922816 4291855482 4291790974 4291134075 4292053889 4291331452 4291790209 4291594105 4291396991 4291725699 4290936956 4291331196 4291134591 4291199353 4291134599 4291199608 4290936954 4291133559 4291133816 4290673528 4291002489 4290212971 4290344581 4290148726 4290145918 4291528579 4292124031 4292849820 4292982139 4293837718 4293771928 4293770881 4293706391 4293639570 4293048198 4293508227 4293047695 4293570436 4293377135 4293176453 4292983711 4293179011 4293179276 4293311379 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288757071 4288102222 4289218660 4288232014 4288362318 4288361547 4287771980 4288556873 4288033098 4287574087 4287767879 4286783048 4286257991 4287308617 4290466389 4291846745 4292245093 4292772979 4293299313 4293236354 4293566337 4293500285 4293501574 4293501319 4293699453 4293698425 4293501318 4293566847 4293627505 4292839284 4292637003 4291517533 4289808980 4289079622 4288752711 4289083212 4289018702 4289673550 4289740109 4290201454 4290662250 4290148009 4291730093 4291462047 4291463849 4290999693 4291195264 4292116091 4291000719 4286133070 4283895366 4284094041 4286793841 4284819560 4284357975 4285738589 4285606492 4285277024 4285473625 4287059841 4287317383 4285479268 4287655081 4285740647 4288116401 4289035689 4287189638 4284819538 4283963459 4284490318 4283633992 4283895119 4284025923 4283831114 4284093784 4284820060 4286069368 4285805415 4288311973 4289757101 4288512432 4285215068 4282844214 4282843205 4285805915 4291004295 4290212466 4288698467 4287575912 4283635790 4284620613 4284291651 4284161097 4284225862 4284029254 4283766087 4283571273 4283567695 4283765314 4292383629 4290469986 4289743964 4291527562 4292718487 4292522904 4292851381 4293379239 4293583297 4286394942 4284284979 4286782535 4288752455 4289873225 4291644504 4291712597 4291976547 4291910502 4292042343 4292701816 4292440161 4293227143 4292576119 4292967033 4292836755 4293627011 4293235834 4293303946 4293236111 4293237389 4293305499 4293302685 4293302667 4293238666 4293369479 4293371292 4292976539 4293370247 4293367945 4292977049 4292974240 4293105534 4292907148 4292640632 4292441443 4292509580 4292900966 4292638075 4292896121 4292633705 4292176744 4293220709 4292370537 4292111734 4293293440 4293238189 4293838773 4294038469 4294103746 4293377464 4292650386 4292775829 4293234834 4292383118 4292904850 4292444777 4292767351 4292175458 4292567930 4291977060 4292108389 4291649656 4291844958 4291125600 4289476943 4287046727 4286586697 4284944701 4285866051 4286131019 4285997127 4287051084 4285010752 4283764297 4286719063 4292122269 4292781728 4292515462 4289093756 4285078336 4285209151 4284027188 4286193735 4284354360 4285209663 4285144648 4284683321 4284483901 4286522957 4289683557 4290806139 4291195509 4290212202 4291195766 4292185463 4292120454 4292119932 4291792253 4291856513 4291856769 4291397238 4292250754 4291462266 4291527302 4291331709 4291331454 4291856510 4291134074 4291593094 4291594369 4291396981 4291462775 4290936182 4291396733 4291396732 4291068285 4290870896 4291462524 4291199610 4291330938 4290805111 4290411384 4291000181 4290411128 4290410873 4290211700 4289885047 4291003776 4292451204 4292718733 4293246085 4293048455 4293772183 4293376383 4292984707 4293573778 4293376642 4293507969 4293048456 4293179781 4292982686 4293177730 4292786059 4293572999 4293113987 4292916889 4293509268 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288821589 4288296278 4288365134 4288427598 4287770955 4288492105 4288493900 4287967305 4287508295 4287112520 4286655560 4286914120 4286257735 4287441994 4289283148 4291453276 4292706417 4292772719 4293366393 4293237115 4293566336 4293501313 4293698163 4293697912 4293698426 4293502859 4293568135 4293564282 4293563001 4293165673 4292769399 4291582539 4289018696 4288033354 4288164938 4289279563 4289018702 4289150544 4290790988 4290081156 4291133055 4291190368 4290924116 4291122782 4289819014 4289357720 4289622685 4289089909 4286133336 4285208930 4285477475 4287317871 4285940854 4285210696 4285736802 4284423769 4285148755 4285080914 4286598527 4286070920 4285675378 4288047259 4287584412 4288513221 4289165459 4288509857 4284617526 4283895622 4284686944 4284683327 4284354114 4284423498 4284422734 4284027460 4283963455 4284291415 4286068827 4286401668 4284091962 4284687931 4287121240 4283828534 4283238719 4283503433 4287970653 4290344049 4290345850 4289351017 4285606469 4284291395 4284157261 4284160316 4284423237 4284224316 4284029254 4284226373 4283631691 4283371077 4287384685 4292382071 4289613920 4290073953 4292324514 4292517004 4292918702 4292589985 4293843148 4289169250 4282646578 4285401145 4286717769 4288824399 4290725716 4291517284 4291843166 4292041564 4291649895 4292240738 4292175973 4292504186 4292639351 4292966012 4292771943 4293233281 4292970382 4293365648 4293299085 4293237900 4293695865 4293238923 4293305501 4293302410 4293303177 4292977055 4293303943 4293369735 4292976283 4293305758 4293302923 4293365630 4292840844 4292903289 4292969351 4292967545 4292703862 4292638841 4292703096 4292899430 4292043367 4292109160 4291846504 4292106599 4292370530 4292902276 4293304218 4293839031 4294037697 4294038468 4293838775 4293043349 4292843157 4292383101 4293036677 4292642689 4292706681 4292703096 4292833657 4291846772 4292632424 4291846266 4291846243 4291125852 4291777377 4290005583 4286586183 4286062665 4283961661 4285931587 4285734988 4286195526 4286987352 4285208135 4284220231 4285343052 4292711819 4292188325 4291660665 4291133079 4284878132 4284813626 4284352308 4285207610 4284943930 4285339960 4284816708 4284549177 4284352828 4287248470 4290079598 4291198073 4291197290 4291127409 4291134586 4291790721 4292121474 4292119686 4291726717 4292184961 4291790966 4291923847 4291790967 4291922552 4291528577 4291725182 4291988088 4291396991 4291397237 4291790465 4291528314 4291658632 4291462773 4291331197 4291396723 4290805370 4291199344 4291265921 4290476921 4290805109 4290740093 4291068025 4290936697 4290212213 4290214264 4289688440 4289820280 4290737272 4292383873 4292850295 4293244560 4293441929 4293441674 4293574290 4293769858 4293443740 4293574791 4293638001 4293180316 4293507968 4293048458 4293376362 4292983200 4293376916 4293245330 4293247390 4293839262 4293181595 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287771723 4288558407 4287312203 4287968588 4288034380 4287376454 4288032842 4287509581 4287573575 4287048776 4287375688 4286323271 4285669192 4287437639 4290200394 4292046170 4292571754 4293166189 4292907381 4293697404 4293566851 4293565821 4293501575 4293697912 4293700225 4293698680 4293501058 4293566849 4293562238 4293359980 4292965208 4291253590 4290006090 4289212489 4288292166 4288036434 4289082442 4289544780 4289415257 4290531938 4290396751 4290728281 4290596695 4291255404 4291128986 4290072944 4288695395 4286267257 4288042892 4286794363 4286925165 4286400646 4285933650 4286327910 4285210442 4284554583 4286065262 4286992780 4288113318 4284093257 4285805668 4288838329 4288645803 4288505483 4284685132 4285015902 4285479295 4284554819 4284686920 4284488008 4284291397 4283897924 4284159050 4284159050 4284360019 4284356171 4283502910 4286394714 4286728578 4284750408 4287840078 4283829312 4283238463 4283827769 4288367456 4290472829 4290938501 4288826473 4288568184 4284421181 4284028992 4284289859 4283634746 4284155974 4284293958 4283435331 4283107654 4284292166 4292450957 4290602343 4290139497 4291394956 4293443241 4292851116 4292456083 4293117365 4291933841 4282974254 4284746815 4285797698 4287046981 4289281355 4290988887 4291255635 4292237156 4291256926 4292498531 4291713637 4292698987 4292965223 4292179064 4293425017 4292510330 4293295237 4292967809 4292972666 4293302669 4293304714 4293238667 4293699472 4293238150 4293239709 4293240993 4293304455 4293762954 4292909471 4293369226 4293237130 4293303434 4293301390 4293167749 4293102466 4292575093 4292902024 4292247162 4293097085 4292442728 4292767863 4292241510 4292242280 4292761963 4292109927 4292501605 4293098631 4293103244 4293706931 4294039239 4294040521 4293838261 4292649636 4292448384 4292841124 4292971138 4292840320 4292835716 4292704376 4292506979 4292700281 4291911267 4292436070 4292108393 4291977056 4291121228 4289149772 4285667392 4286849097 4284420413 4286325322 4285404218 4285802315 4288167501 4284487241 4284220994 4285534783 4292120216 4292583840 4290733687 4290812575 4285665596 4284617016 4283959112 4284419897 4285670722 4285471559 4285010226 4284488000 4284614722 4288104027 4291066481 4291460707 4291261817 4290409333 4291790975 4292121468 4292120188 4291726717 4292184953 4291791223 4291922306 4291462783 4291922305 4291265662 4291330680 4291790974 4291790719 4291134331 4291855225 4291199867 4291725180 4291199866 4291528320 4291134590 4291134592 4291592573 4291331453 4291133817 4291462523 4290740102 4291462008 4290412167 4290738539 4290477177 4290082424 4290474358 4290081910 4291989380 4292324984 4293702016 4292983175 4293835655 4293638514 4293178746 4293441674 4293048455 4293442178 4293246603 4293442176 4293180810 4293507966 4292917409 4293573243 4293180549 4293575835 4293575320 4293509526 4293445023 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287969357 4287967828 4287443787 4288164681 4287443018 4287574346 4287573575 4287049290 4287640138 4287770951 4286717511 4286457419 4286455368 4286851399 4290265166 4291189074 4292705134 4292705643 4293824638 4292907894 4293238922 4293370227 4293567111 4293370486 4293566854 4293501573 4293501315 4293566074 4293627768 4292968300 4292573535 4291518046 4289610831 4288624460 4287640140 4289346638 4289083981 4289348950 4289610322 4289350746 4290335067 4290137947 4290598748 4291647070 4291324517 4288363869 4287511671 4286067810 4285279840 4287385735 4288044703 4285932368 4288372624 4286986087 4284421456 4285540955 4287453852 4288180381 4284751707 4284029027 4287123338 4288779448 4286269579 4287454349 4284557403 4285808763 4286069599 4284487254 4284092998 4284091979 4284619594 4284884045 4284423495 4284487239 4284686409 4284290637 4284488264 4285015622 4284161609 4284422467 4287839828 4285142077 4283107122 4283632701 4287711844 4290210939 4290340213 4290416780 4288238429 4284156989 4283305275 4284027451 4284222272 4283305016 4284486988 4283238462 4282974259 4288762470 4291723885 4290136661 4290271078 4292920242 4292850318 4292852399 4292523426 4293842364 4284950589 4282779215 4284552768 4285208124 4288293448 4289086286 4291319126 4291383382 4291842404 4292502122 4291977576 4292370280 4292109671 4291713894 4293356137 4292312938 4292966014 4292312166 4293099396 4292970903 4293693306 4293235088 4293302674 4293237388 4293238687 4293631367 4293634206 4293240221 4292909466 4293368711 4293237388 4293696633 4293236882 4293168245 4293166219 4292968835 4292640648 4292638583 4292899176 4292445550 4292965225 4292504442 4292109159 4292370525 4292106600 4292109414 4292766844 4292768866 4292974492 4293705911 4294037954 4294038725 4293643198 4293042076 4292449417 4293168523 4292776335 4292837769 4292708220 4292310648 4292769146 4292370292 4292307849 4292042597 4292108392 4291779686 4291319126 4288689739 4286258248 4285668938 4284027191 4286456394 4284357962 4287047494 4288038490 4284746805 4284221251 4285666636 4291465098 4292581787 4290867580 4292845454 4285472071 4284222264 4284880445 4284617273 4286394446 4284814393 4284619328 4284877109 4284816190 4289154389 4290802797 4291262829 4291064180 4291134329 4292052860 4292120968 4292055436 4292119168 4291725423 4291658883 4291463031 4291922305 4291856759 4291922562 4291790965 4291134332 4291199611 4291659388 4291397247 4291331196 4290937212 4291331196 4291331187 4290805370 4291594104 4291133808 4291199611 4291067766 4291462781 4290870389 4290476919 4290542711 4291000438 4290540405 4289491578 4289684840 4291330941 4292516484 4292981128 4293246363 4293641355 4293376640 4292851873 4293637498 4293640086 4293245040 4293442434 4293245595 4293442174 4293639570 4293639314 4293508227 4293181856 4293641113 4293641885 4293707419 4293772966 4293379239 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288033364 4287510094 4287639625 4286983754 4287638598 4287639882 4287048263 4287179847 4287178314 4287178567 4286915656 4285865800 4285797445 4287441480 4290198855 4292109664 4292046700 4293035893 4292775037 4293303175 4293631353 4293566082 4293371513 4293172103 4293566849 4293500288 4293764214 4293499778 4293627768 4293100396 4293095004 4291847259 4289413711 4288686662 4287771465 4288754507 4288626000 4288953420 4289677911 4290005586 4290923603 4290726476 4291120983 4291056726 4291583335 4287175505 4286266228 4288638384 4289103801 4288443033 4285474645 4287511406 4289750656 4286722664 4286133603 4288702881 4287456138 4284358238 4283635772 4284685161 4285147748 4287788449 4288113326 4286073469 4286859396 4284883774 4285278825 4284685385 4283896131 4284292160 4285078602 4284752973 4284686408 4284095813 4284554569 4284293963 4284095551 4284622167 4284159289 4283961924 4287050567 4285272893 4282778686 4286457419 4288694358 4289817971 4288429943 4292583812 4291527288 4286461014 4282778422 4283305541 4283502908 4283762746 4283436345 4283500344 4283960896 4291990134 4290667879 4290139994 4291261311 4292656554 4292785570 4292591284 4293383355 4288836969 4282713155 4284094789 4285144644 4286060870 4286915655 4289609035 4290857814 4292238180 4291058512 4292105569 4292370537 4292307816 4292043623 4293355628 4292505721 4292639098 4293095784 4292966012 4292903285 4292838518 4293296520 4293234812 4293235324 4293629306 4293698954 4293239967 4293237892 4293634465 4293302663 4293303178 4293304716 4292908687 4293431424 4292577928 4293430891 4292706186 4292833124 4292835950 4292898148 4292704893 4292243319 4292832615 4292109673 4291842910 4292175978 4292109154 4292438881 4292443272 4292840088 4293571488 4294103490 4294040264 4294234047 4292649892 4292448386 4292778131 4292643205 4292708736 4292509576 4292639846 4292309878 4292440948 4292500581 4292108136 4291780454 4291257187 4290530384 4288361292 4286456392 4284618819 4284553534 4285602111 4285074227 4286455880 4287514448 4284810810 4284352586 4284482366 4292055184 4292978334 4290607995 4292124302 4287840095 4283826747 4284090420 4284288051 4286394188 4285277002 4284881472 4284291134 4287177799 4290407023 4291394414 4291130230 4290670953 4291660429 4292125317 4292056982 4292253032 4291659650 4292120191 4292119424 4291856769 4291856769 4291463032 4291725182 4291461758 4292117372 4291791231 4291199858 4291331197 4291133817 4291133817 4291331196 4291396732 4291068541 4291199344 4291134079 4290673782 4290936954 4290739318 4290282625 4290542455 4291000437 4290080885 4290015094 4290406258 4290345852 4292318585 4292982153 4293507204 4293572465 4293574037 4293704582 4293835652 4293376900 4293376898 4293442436 4293441676 4293639534 4293443996 4293375367 4293182595 4293181342 4293773212 4293247903 4294233759 4293445539 4293511330 4293576865 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287574345 4287048776 4287050828 4287704132 4287051862 4287115336 4287181385 4287179849 4286785095 4286851912 4286324808 4286585928 4285798725 4287571015 4289870410 4291453787 4292706416 4292575598 4293167218 4293694082 4293171066 4293566336 4293566337 4293630322 4293501316 4293698424 4293500545 4293564796 4293366650 4293361513 4292833888 4291978319 4289610320 4288752454 4287771466 4288821066 4288756820 4289547878 4289019470 4289676887 4289939030 4290793559 4291119960 4291054170 4290332290 4287319195 4290291909 4289563555 4288111492 4285343330 4286397032 4289488016 4287058829 4285275216 4288770994 4287192199 4284750426 4284752724 4285015908 4285214815 4283895646 4285085792 4288841656 4286595696 4287457175 4284224337 4285212499 4285276744 4284357723 4284292166 4285802828 4284158528 4284094534 4284423236 4283897142 4284614985 4283963717 4284358211 4287785870 4283827768 4284746038 4286196296 4283438151 4283564092 4289022823 4289225336 4287903840 4289153611 4293242529 4291594109 4285999435 4283043144 4283369533 4283568450 4283173182 4284219459 4288038485 4292314729 4290329678 4290009189 4292588208 4292849317 4293445043 4293316022 4292264619 4283301955 4283106363 4283832900 4285929790 4285864261 4287504202 4289413960 4290399064 4291448403 4291714658 4291910503 4292042850 4292109416 4292633450 4292570473 4293161064 4292965243 4292902519 4293098628 4292967047 4293427823 4292969349 4293495685 4293299602 4293236879 4292908190 4293302920 4293238691 4293631607 4293239180 4293300366 4293235585 4293761401 4292906642 4293626758 4292969096 4292771943 4292575103 4292964197 4292112778 4292962917 4292963175 4292175977 4292042589 4291715676 4292039521 4292175464 4291978615 4293032311 4293230480 4293173419 4293838774 4294040521 4294169024 4292978345 4292643725 4293103482 4292907646 4292115844 4292835958 4292117385 4292834167 4292374899 4291978104 4291912802 4292109920 4291517796 4290792529 4287438919 4285535550 4283960644 4285603652 4285336634 4285209924 4286458442 4287512145 4284483380 4284024901 4284155706 4291003528 4292978846 4291064709 4291857020 4288963444 4284488517 4283762233 4283960383 4286064461 4285078341 4284227143 4285271871 4288165962 4290605170 4291262829 4291130229 4290670698 4291725433 4292255372 4292057218 4292118658 4292119425 4292119160 4291792510 4291659390 4291856760 4291922562 4291921018 4291594370 4291134323 4291199868 4291528576 4291133816 4291331196 4291528575 4291133817 4291002748 4291199609 4291199611 4291067511 4291265402 4291265402 4291330682 4290870647 4290542712 4290540661 4290345593 4289950585 4289753977 4291856499 4292780423 4293177227 4293377153 4293837192 4293311105 4293900663 4293311364 4293442692 4293374089 4293442690 4292982663 4293639571 4293179539 4293772939 4293511336 4293839776 4293839520 4293839777 4293904024 4293511332 4293772698 4293183142 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287574088 4287050839 4287114323 4287705429 4287113539 4287181131 4287246679 4287310673 4286197322 4286917191 4286456904 4285602115 4285996361 4286325575 4290396237 4291255643 4292704620 4292838015 4293167217 4293170812 4293632384 4293566336 4293630335 4293172615 4293566851 4293697648 4293501318 4293562737 4293626481 4292968557 4292899424 4292174159 4289020752 4288228167 4287180358 4288293968 4289417569 4290477488 4289609291 4289675087 4290660945 4290132566 4290860658 4290804914 4289700012 4289956503 4287058030 4285212242 4284485963 4287052401 4290217902 4288502921 4285342287 4288579002 4287453300 4283633465 4284157284 4287256200 4285410149 4285872498 4284289371 4287128238 4289037500 4287057026 4289104824 4284947801 4284752711 4285146965 4285212244 4285143359 4286132823 4283766341 4284489279 4283830080 4284290114 4284227400 4283761224 4284555343 4286004310 4284748858 4285211463 4286062148 4283959614 4286455115 4288694622 4289823382 4290800230 4286584908 4290727515 4292189570 4292057233 4284419389 4283239490 4283305288 4284025158 4283957301 4290411895 4290863463 4289678424 4291125861 4292988605 4292918966 4293248447 4293845191 4286658352 4282778169 4283567171 4284881727 4286722127 4285733704 4288032586 4289410636 4290264908 4291384403 4291711323 4292109157 4292172137 4291977058 4292568170 4292700008 4292964987 4292767330 4292966524 4292705418 4293099615 4292969112 4292967807 4293101458 4293038965 4293694076 4293304979 4293237390 4293239178 4293630588 4293239180 4293300366 4293302670 4293037210 4293562244 4293103223 4292706424 4292772203 4293095033 4291977062 4292504933 4292175462 4292244349 4292307040 4292172138 4292172901 4292238687 4292106595 4293029736 4292570482 4292904847 4293238677 4293838518 4294038982 4294170310 4292979108 4292381815 4293166996 4292185476 4292968851 4292246391 4292771193 4292308594 4292833914 4292108897 4292109434 4291387491 4291713883 4289874005 4286522182 4285210185 4284095554 4285538380 4285210435 4286193225 4286262092 4288169551 4283893567 4283762999 4284284991 4290869120 4292517020 4291261063 4291266693 4290077821 4284947010 4283305279 4284618302 4285668412 4285210695 4284093763 4284812095 4288633948 4291589229 4291199601 4291129972 4291132280 4292186503 4292382596 4292187776 4291858292 4292118906 4292120183 4291790712 4291922306 4291463033 4291528567 4291463042 4291527294 4291856502 4291593851 4291265404 4291002748 4291133817 4291133817 4291199353 4291396988 4291067768 4291133048 4290939767 4290739320 4290802548 4290348669 4291001975 4290279544 4290936697 4290210922 4289360750 4290936435 4292253297 4292979851 4293508737 4293574295 4293113453 4293640087 4293374090 4293377412 4293178235 4293638015 4293769863 4293836931 4293114759 4293575579 4293641630 4293839520 4293839274 4293644455 4293379745 4294233759 4293313439 4293379231 4293445022 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287576401 4287639379 4287050570 4287116105 4287181655 4287246419 4286067017 4286852937 4286917191 4286916680 4286521929 4285274173 4285598781 4287113032 4290005069 4291321180 4292704877 4292773231 4293299064 4293693563 4293171334 4293632127 4292844157 4293236346 4293566851 4293501575 4293699452 4293497970 4293628021 4292968300 4292964959 4291386204 4289938515 4288162886 4288555080 4287636291 4289551208 4290148237 4288953423 4289083477 4290072949 4290741425 4291143094 4290805642 4290934662 4287903083 4283039798 4284095059 4286195824 4289491094 4291665081 4287052908 4287985070 4286332520 4283895626 4284290155 4283572301 4287656629 4285546348 4285081722 4284754026 4288912581 4288118441 4288241315 4286930047 4287059083 4283962426 4285012826 4285347429 4284949329 4285539686 4284091193 4283697990 4283830082 4283566912 4283833167 4284091712 4285801283 4287706954 4287771468 4287576401 4284484408 4287576159 4287509082 4288306049 4291991698 4292514441 4287836489 4285405763 4291323488 4292843637 4286260552 4283041331 4283435323 4282843953 4286330706 4292251261 4290268507 4288958557 4292453788 4293510836 4293380025 4293842107 4290613870 4282384440 4283697471 4283500606 4285078084 4287049294 4285664320 4288030023 4289017932 4290397001 4291121754 4291384159 4291386197 4292241002 4292109666 4292699243 4292110695 4292633958 4292966273 4293096041 4293098853 4292706442 4292904055 4292970365 4293166471 4293297807 4293232511 4293235345 4293697145 4293233552 4293235842 4293302159 4293301376 4293301633 4293302401 4293036421 4293364880 4293035143 4292837994 4292308840 4292240999 4292505192 4292307048 4292306790 4292438633 4291584358 4292433503 4291647062 4292238440 4291845735 4292764259 4292774048 4293305002 4293839029 4294038468 4294104260 4293575102 4292774264 4292777869 4292903049 4292642428 4293031287 4292704379 4292374387 4292439137 4291978106 4292174949 4292106849 4291256929 4288754505 4286980167 4284156233 4283830854 4285144389 4286261321 4285536576 4286917448 4287972700 4284351027 4283763014 4284416837 4289424233 4292387226 4290474096 4291988615 4290540411 4284753477 4283368248 4285013314 4285209927 4284751687 4284023875 4285934412 4289813873 4291394415 4291392865 4290670453 4291263601 4291990650 4292120958 4292054653 4292448136 4291858550 4292119161 4292119427 4291331704 4292250745 4291791235 4292119156 4291528578 4291134330 4291658632 4291462772 4291133817 4291331196 4291199352 4290742147 4291068285 4291328875 4290479730 4291001979 4291133559 4290805369 4291462266 4290279543 4291068281 4290016376 4289820026 4290277238 4292119666 4292127376 4293441913 4293376902 4293901685 4293574296 4293572723 4293375341 4293833861 4293442694 4293245042 4292984708 4293377433 4293707147 4293970075 4293773729 4293644959 4293644199 4293839776 4294233513 4293576091 4293575062 4293379487 4293575329 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287574602 4287574859 4287640394 4287114068 4287183438 4287181653 4287378516 4286786633 4286258503 4286457672 4285932361 4285862978 4285272635 4286589260 4289869380 4291519062 4292703341 4292575068 4293363843 4293300863 4293238661 4293565056 4293630592 4293566076 4293565562 4293500546 4293697906 4293496959 4293562484 4293427049 4292507232 4291714131 4289280586 4288293959 4287770696 4287704134 4289935945 4291268772 4289350275 4290073726 4291404201 4291658639 4289548150 4289883286 4290016401 4285867597 4284618066 4286328692 4289165723 4289560491 4287052626 4288177556 4287052126 4284750663 4284951155 4284095819 4286269569 4286531707 4287394217 4285544581 4286798237 4288512684 4286533760 4288970686 4285476949 4288974254 4284815701 4285212756 4285411419 4284357702 4285277771 4284354373 4283566135 4283436351 4283238456 4284025152 4285342282 4288496709 4290146686 4289085008 4287310406 4284548670 4288364376 4288040590 4290739343 4293242779 4293309078 4289814379 4283105348 4288034884 4290150008 4284815687 4283172661 4283369782 4282974260 4291066751 4290800990 4289683046 4290601062 4292720815 4293248688 4293314742 4291870107 4283170856 4283107385 4284156736 4282976056 4285670208 4287379276 4286191173 4288030024 4289081673 4290333777 4291182669 4291779429 4291582821 4292436329 4292042601 4291845991 4292633188 4292832874 4292961385 4292572537 4292769673 4293098626 4292903815 4293426035 4293166729 4293102981 4293100676 4293365118 4292908433 4293102474 4293302144 4293300880 4293302669 4293234065 4293429382 4293561223 4292969847 4293100149 4292639871 4292570981 4292637544 4292108648 4292109160 4292373096 4291649125 4292303716 4292106083 4291911005 4291845218 4292171880 4292573028 4292576140 4293303947 4293506229 4294103746 4294040264 4294102213 4292312425 4292708999 4292445820 4292705913 4292510317 4292376694 4292636807 4292109942 4292174435 4292438888 4291779686 4290529870 4288755787 4285406021 4283568955 4284292163 4284947012 4286129995 4285998663 4286722380 4288693843 4284221235 4283763001 4284024379 4289547635 4292057752 4290938768 4291267982 4290674309 4285341003 4282909745 4285207875 4284620098 4284157245 4284288058 4287050835 4291194481 4291265393 4291194731 4291064180 4291331968 4292513671 4291858801 4292120445 4292053624 4292315251 4291921796 4292119672 4292053376 4291331706 4291922552 4291265664 4291594360 4291592831 4291397235 4291725443 4290936955 4291396732 4291200128 4290478959 4291527805 4290282875 4291330426 4290936954 4290870904 4290672748 4290673528 4290214521 4290540652 4289623161 4290472306 4291722864 4292451207 4293308807 4293441932 4293377655 4293770619 4293311363 4293769609 4293572222 4293376395 4293376897 4293441923 4293772943 4293509528 4293839779 4293773729 4294167965 4293839017 4293839262 4293840044 4293184671 4293905312 4293247903 4293772955 4293707418 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287509078 4287575372 4287574615 4287181897 4286655314 4287246931 4286655304 4287374918 4286917707 4286455880 4286257475 4285406015 4285138744 4286650950 4289872974 4291584348 4292243815 4293165694 4293169515 4292909196 4293236869 4293565817 4293566593 4293564788 4293500028 4293698424 4293500801 4293565041 4293627765 4292968301 4292964193 4291453007 4289609041 4287508554 4288555079 4287770183 4288623433 4290269780 4291989405 4290804116 4290402941 4289152113 4289287297 4290733183 4290142828 4287639141 4285866853 4288628081 4290016907 4287451519 4285085049 4286928002 4285676391 4287393185 4284157509 4285806462 4287782809 4285674868 4288120501 4285339731 4287327651 4286932134 4287913632 4288717245 4286197618 4289039025 4284816457 4284354115 4284619077 4284752973 4285343309 4284092987 4283829312 4284157769 4283566389 4286261845 4285013069 4286194758 4289616227 4289414480 4285927232 4285937260 4287186793 4289949553 4289674057 4293441438 4293116066 4291919739 4283826744 4286191679 4287906383 4283105330 4283369781 4282975797 4286063672 4291594102 4290990166 4290074463 4291659422 4293184184 4293511348 4293842617 4284553533 4283042618 4284090688 4283566911 4283893567 4284948288 4288758367 4285996614 4287507015 4288557388 4290462285 4291448140 4291710041 4291979875 4292432733 4291977314 4292959851 4292309096 4292634218 4292963434 4292963961 4292903030 4293226617 4292903541 4292901496 4292969611 4293562247 4293099393 4293100932 4293363593 4293363831 4292972434 4293299834 4292972951 4293300090 4293693567 4292973182 4293232269 4292901499 4292901226 4292373095 4292307049 4292240744 4292042600 4292174181 4291912804 4291910754 4291515474 4292105828 4292238681 4292106599 4292569976 4292967057 4293299082 4293570727 4294103747 4294042573 4294038208 4292511120 4292514429 4292772475 4292509833 4292574054 4292180106 4292767606 4292504672 4292241786 4291714660 4291845725 4290071379 4288164434 4284550983 4284092236 4284685389 4284224053 4286785353 4285866055 4287377996 4287379792 4284613173 4283697467 4284812859 4287973471 4292253079 4291859103 4291394939 4290347143 4285538375 4282779194 4285604422 4283633211 4284685892 4284550474 4288105306 4291130985 4291197037 4291194987 4291065452 4292185465 4292384125 4292120959 4291923829 4292119936 4291725690 4292050540 4291725938 4291791227 4292185199 4291658884 4291725172 4291527804 4291922561 4291594115 4291199858 4291331197 4291133560 4291594110 4291200128 4291199609 4290936442 4291265145 4291133560 4290411127 4290477177 4290936696 4290804856 4290148729 4290082424 4290211701 4291790975 4293045639 4293244272 4293902732 4293769861 4293508758 4293374848 4293507446 4293770375 4293310601 4293639315 4292984448 4293903512 4293774242 4294167710 4293644189 4293839009 4293645216 4293839009 4293644188 4293839263 4293445550 4293839774 4293445537 4293511342 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288033353 4287509844 4287576400 4287114054 4286657879 4287244880 4286721864 4286853197 4286326855 4285932104 4285733700 4285271868 4285272893 4286647620 4289935684 4291388001 4292311142 4292838766 4292970375 4293694078 4293565311 4293566336 4293566079 4293566852 4293500545 4293698423 4293499771 4293565560 4293561973 4293756267 4292442450 4292105816 4289149514 4288818247 4287768648 4288556615 4287510350 4289150799 4289545555 4290466915 4289421708 4289031839 4289490835 4290145697 4291129992 4287249262 4284223820 4286135918 4288243090 4286659955 4286859912 4286791277 4287257758 4283895362 4286269579 4286728583 4285737577 4287396272 4287123580 4285805954 4286800283 4286202494 4287851428 4289898167 4286063988 4285747829 4284951139 4283369778 4283700809 4284093258 4284621387 4284489544 4284484425 4283962430 4283830606 4284487740 4285547641 4287055466 4286461523 4288232796 4285998158 4291137424 4290865503 4290335837 4287637832 4286915400 4289752161 4287976021 4284286516 4283763512 4285471307 4283370547 4283173701 4283170858 4288765300 4292115302 4290073955 4290207082 4293050043 4293907125 4293841334 4286929493 4283170860 4284027202 4284091705 4283959616 4283631159 4285999954 4288235341 4286650439 4287312199 4289607756 4289674833 4291119433 4291385435 4292236643 4291650151 4292175209 4292109672 4292435041 4292634730 4293160299 4292505979 4292965241 4292900983 4292967547 4292901753 4292903030 4293228402 4292970621 4293230979 4292838259 4292970383 4293103241 4293693310 4293167747 4292969871 4293298560 4293035133 4292969849 4292836459 4292309625 4292703080 4291649114 4291517285 4292237922 4292109415 4292309370 4292367201 4292238693 4291911010 4291514457 4292042601 4292373344 4292837769 4293168767 4293173928 4293973185 4294042060 4294170053 4292710796 4292707970 4292315019 4292706165 4292706684 4292376693 4292636511 4292177289 4291256419 4292370538 4290600029 4289478234 4286979907 4283239238 4284027718 4284749883 4285146446 4286654791 4285736778 4287376198 4287444046 4285404479 4283697204 4283697466 4288755038 4292580737 4291465626 4291788413 4290871928 4287315039 4283631931 4284488511 4284025145 4284550724 4285801031 4289222496 4291198588 4291525238 4291129451 4291589223 4292119427 4292055677 4292119422 4292120703 4292119159 4292119684 4291528559 4292249462 4291397489 4292251013 4291200373 4291988099 4291332731 4291725182 4291396981 4291658621 4291397236 4291594111 4291134335 4291068284 4291001975 4291462516 4290676612 4290936688 4291002747 4290868597 4290477176 4290674296 4289949045 4290277238 4290936692 4292977529 4292851081 4293835653 4293705861 4293311365 4293900150 4293311623 4293572726 4293311363 4293835140 4293051527 4293903513 4293381019 4294167711 4293578654 4293446054 4293839264 4293839265 4293839264 4293644200 4293839274 4293839528 4293839530 4293839529 4293839517 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287967827 4287509837 4287509065 4287575128 4287705159 4287114824 4287181900 4286788429 4286915143 4286520904 4285668163 4285601085 4284483127 4286388544 4289348169 4291384917 4292505438 4292575856 4293168764 4293170567 4293630847 4293566335 4293566336 4293500544 4293763958 4293501575 4293566851 4293564541 4293562989 4293427563 4293293397 4291517523 4290068302 4288164426 4287967047 4287770953 4288754247 4288951117 4289153633 4290275459 4290008976 4289481573 4290669442 4290671495 4289292177 4286063692 4286064999 4287450750 4286721123 4286135656 4287915164 4287386251 4285538915 4286399861 4286664319 4285738888 4285082721 4288776887 4284683880 4284817472 4286801571 4285737063 4287852963 4289241524 4286724487 4284624459 4287848865 4283367482 4283700036 4284817482 4283960888 4284421708 4285408069 4284488263 4284290372 4284154939 4285079366 4287054703 4285602882 4286916697 4289023309 4291529620 4290854725 4288622658 4285600059 4287192696 4287515494 4284553289 4283500857 4284422462 4284421449 4283040818 4283830582 4287776347 4291129439 4290268248 4291124061 4291661193 4293644978 4292121462 4290745729 4283105335 4283172922 4283238714 4284091707 4284091707 4284023864 4285738046 4289223534 4286323268 4288554570 4289016393 4290198603 4290791244 4291318872 4291059290 4292303454 4292305760 4292501094 4292242024 4292767338 4292370537 4293158249 4292703591 4293294206 4292705386 4293099912 4292968566 4292444538 4293097863 4293033857 4293232517 4293166472 4293100423 4293300860 4292970126 4293168260 4293363595 4292708220 4292575097 4292705658 4292377212 4292372833 4292171620 4291579992 4292436330 4292043367 4292896616 4292044134 4292106344 4292040806 4292105569 4291980388 4292633723 4292639858 4293169046 4293566873 4293773497 4294043856 4294169797 4292714127 4292572516 4292573828 4292901511 4292706682 4292442487 4291915129 4292241525 4292173415 4291584356 4290992738 4288823379 4284484920 4283765056 4283963975 4284815687 4284417852 4286521416 4287049289 4286787661 4286983754 4285142078 4284090421 4284680245 4286393166 4291266959 4292054674 4291197321 4291727235 4288305260 4283896121 4284419897 4283371323 4283435332 4287247175 4290141544 4292052327 4291657581 4291128681 4291265917 4292516227 4292054663 4292119928 4291790712 4291790978 4291790968 4291922555 4291659130 4291790712 4291200118 4291986296 4291725174 4291133821 4291790975 4291396981 4291397246 4291789704 4290674040 4291528565 4291330941 4291331188 4291133810 4291330169 4291133304 4291133561 4291066988 4290739578 4290474870 4290538355 4290147692 4292253820 4292977801 4293508479 4293706651 4293704325 4293507188 4293704842 4293572724 4293376899 4293573779 4293509770 4293837188 4293774244 4294167711 4294102174 4293578654 4293839265 4294167969 4293969815 4293445539 4293445281 4293839518 4293250206 4293839517 4293839273 4293839528 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287969872 4287443273 4288099928 4287508294 4287640396 4287050060 4287771209 4286653255 4286848840 4286324552 4286651978 4285533497 4284549175 4286386752 4289607496 4291387481 4292703582 4293101169 4293298807 4293694068 4293237888 4293172358 4293566335 4293566079 4293501315 4293501058 4293567622 4293565302 4293563520 4293558632 4292441441 4291649109 4289807949 4287703878 4287307845 4288228169 4289543524 4289687943 4291654557 4290075505 4290464342 4289352826 4290401404 4290729319 4288691812 4285539677 4287050606 4287319659 4286195557 4286729095 4289099950 4286134372 4286135921 4286134637 4286197878 4284290636 4287984291 4287390356 4283239223 4285082495 4288775356 4285475168 4287062700 4288715442 4287782298 4284223800 4288708792 4283500848 4283765324 4284354900 4284620885 4286399851 4284618048 4283829821 4283106872 4284685901 4285867338 4286725484 4288764260 4287979136 4288560467 4291852120 4292057997 4290474098 4288300908 4287842384 4285605706 4284091192 4283500602 4284421702 4283107133 4283367485 4288379802 4291394954 4289816933 4288563810 4288236389 4291330673 4291002998 4290809491 4290414472 4285539917 4284220985 4283435066 4284812347 4283960371 4284159052 4286326590 4288764011 4287439431 4287900231 4288622921 4289151822 4291447889 4291383639 4292236128 4292043624 4292172131 4292106851 4292109416 4292765802 4292832616 4292964733 4292572279 4293096296 4292507771 4293098599 4292903288 4293360244 4292903285 4292706182 4292904061 4293167226 4293100937 4293363593 4293166215 4293168258 4292972145 4293033348 4292967292 4292440420 4292703849 4291515234 4291119184 4291581278 4292109416 4292965225 4292244087 4292766586 4292834412 4292108903 4292172643 4292172138 4292439909 4292637050 4292971165 4293632666 4293838520 4294044369 4294169797 4292777874 4292050540 4292377463 4292379002 4292576106 4292177288 4292569954 4291912291 4291651946 4291058524 4290139742 4287244872 4283960899 4283961668 4284553532 4284751431 4284619324 4287178312 4286264141 4286851913 4286984011 4285601854 4283631669 4283632441 4286319675 4290740603 4291797404 4291528340 4292317046 4289028987 4285600830 4283765816 4283173706 4284418867 4288498785 4290344822 4291656816 4291330426 4291393909 4292248173 4291662725 4292118902 4291725176 4291856760 4291790978 4292185209 4291265912 4291789690 4291265910 4292184962 4291134068 4291790712 4291988336 4291396991 4291462783 4291725433 4290676852 4291593855 4291462784 4291462774 4291331197 4291264634 4290089859 4291133047 4291002482 4290739578 4290673005 4289751146 4290081142 4291000186 4292319614 4293047412 4293574293 4293837429 4293704327 4293704585 4293834614 4293311364 4293574037 4293705600 4293705876 4293641888 4293839265 4293578654 4293773729 4294167710 4293839522 4293248387 4293445542 4293839519 4293839530 4293445288 4293776308 4293510571 4293250470 4293839536 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288559951 4287314522 4288099401 4287509839 4287050572 4287705161 4287050058 4287245383 4286721096 4286913864 4286520649 4284878134 4284549175 4286714694 4289347662 4291321430 4292507243 4292967529 4293365892 4293236864 4293236870 4293632127 4293566335 4293566079 4293501315 4293764729 4293500290 4293564528 4293562745 4293099884 4292900188 4291976024 4290002510 4287506507 4287639113 4289481865 4290608278 4291261064 4290005329 4289675875 4290464592 4289811591 4290008175 4290731111 4287445101 4286459757 4285080893 4287382151 4286594945 4288705699 4287717516 4286199142 4286728051 4285082721 4286070646 4283500867 4288777416 4286004843 4283106387 4285344612 4287791022 4285935757 4286335086 4289240504 4288965291 4283171891 4287261836 4284750939 4284554056 4285872495 4285475663 4284026686 4284616511 4286065484 4282975794 4284157768 4285537599 4287575882 4289887339 4290075221 4284416830 4285210186 4287970130 4289682287 4284553532 4283698488 4283566131 4283370805 4284025139 4283632965 4282974254 4286204775 4292978838 4292908422 4292317060 4291463297 4290280591 4289624208 4291474855 4292849030 4289220433 4284088371 4283369781 4284290623 4284682810 4283960384 4283958084 4286001476 4289748327 4287835722 4287177287 4289083469 4290526534 4291121754 4291777373 4291780960 4291908445 4292175978 4292106850 4292699499 4292502378 4292568937 4293161064 4292572539 4292965245 4292965241 4292900727 4293098374 4292444793 4293294710 4293035655 4293034354 4292969351 4293231481 4292772471 4293234311 4292839290 4293034633 4293100936 4292444523 4292704124 4292639850 4291648358 4291117636 4292433761 4292766059 4292899436 4292897642 4292967023 4292505703 4292967023 4292304740 4291842902 4291911256 4292900461 4293625724 4293109665 4293838764 4294104008 4294301885 4292186764 4292442230 4292770936 4292377719 4292768123 4292636510 4292571768 4291912548 4291977057 4291649377 4289219159 4284617279 4283436358 4284289356 4284486211 4284554051 4284946756 4285998920 4286393418 4286917191 4286982987 4285536575 4284025651 4285011526 4283960636 4291131774 4292319893 4292117909 4291593346 4289949291 4284947776 4283567935 4283238455 4283761730 4288698470 4292049015 4292575081 4291919451 4290999148 4292119931 4292513661 4291727492 4292186502 4291790977 4292185208 4292119675 4291331437 4291528062 4291987326 4291265645 4291856504 4291331446 4291396992 4291265403 4290936955 4291265404 4291593855 4291265404 4291265395 4291528568 4291199354 4290805360 4291395706 4291330937 4290870904 4290146421 4290474870 4290343286 4290671733 4292251517 4292713602 4293509252 4293508500 4293836151 4293311366 4293506931 4293508760 4293376642 4293507450 4293640598 4293838232 4293904538 4294102430 4293773729 4293773729 4293773729 4293839520 4293511077 4293905312 4293839264 4293250207 4293905567 4293249960 4293709732 4293904819 4293445545 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287316560 4288689741 4287312459 4288100430 4287509067 4287575631 4287639881 4287048522 4287245127 4286849096 4286456905 4285730622 4284941368 4287047240 4289217615 4292108639 4292111202 4292837486 4293169267 4293236865 4293631103 4293564799 4293172357 4293566335 4293566079 4293500033 4293764729 4293501059 4293563518 4293362798 4292964703 4291518811 4290135889 4289283178 4289748615 4289617254 4289940053 4288887371 4288954191 4290069338 4290070620 4289420669 4291191933 4290074740 4286921323 4285801296 4284557409 4287975557 4287058824 4287783564 4287517561 4286920822 4285806693 4283827790 4285145964 4286799267 4287657107 4285804898 4283699796 4283306573 4287984814 4286925697 4285080947 4289041838 4289432248 4284287822 4286142847 4288510113 4283435084 4284816445 4284421445 4283766073 4285208125 4287447652 4283695928 4283698746 4284161355 4285608808 4284879935 4283368501 4284155707 4283829299 4286595184 4288702331 4287247954 4284221233 4283370560 4283565888 4284486215 4283304250 4282515495 4290026403 4291989382 4292713625 4292124827 4292714139 4293175951 4293375380 4292849554 4289683809 4284746551 4283697206 4284352822 4283698742 4285076019 4284485442 4283827253 4286525781 4288633190 4288426825 4287635523 4289541964 4290068049 4291121489 4291516759 4292041822 4292043366 4292304995 4292696679 4291845992 4292568170 4292962155 4292899195 4293160553 4292705130 4293096299 4292900476 4292903799 4292967290 4292901754 4292901239 4292706184 4293297529 4292838521 4293232267 4292839048 4293034629 4293035639 4292707467 4292444522 4292704121 4292441718 4291516006 4291576910 4292303714 4292964206 4292439638 4292831321 4292827461 4292702308 4293028960 4292109159 4292104801 4292366173 4292305514 4292901756 4293697143 4293508023 4293838240 4293708731 4292114285 4292377207 4292770936 4292312185 4292770168 4292244870 4291390587 4292043620 4291256418 4291189597 4287112784 4283632972 4284748859 4283372354 4284159051 4284489803 4284815683 4286586696 4286919757 4286391367 4287049292 4284811573 4285402942 4284876867 4283957309 4288897396 4292123807 4291730075 4291131504 4289751934 4285865288 4284157753 4282975812 4284878652 4289748072 4291790708 4292116580 4291460463 4291394426 4292121982 4291726462 4291857015 4291790977 4291856759 4291397241 4291856761 4291790721 4291725174 4291528569 4291790976 4291134076 4291856511 4291594104 4291856511 4291528575 4291331196 4290936955 4291594110 4291265406 4291331188 4291068542 4291462527 4290479472 4290674052 4290936438 4290805112 4290474613 4289819769 4290474099 4292449681 4292982152 4293572222 4293706118 4293704327 4293311107 4293704584 4293834613 4293705863 4293705347 4293838234 4293182855 4293839523 4293773985 4293773729 4294167965 4293839264 4293446309 4293576609 4293051556 4293839274 4293775268 4293511351 4293775267 4293709731 4293445299 4293839526 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287968331 4287903823 4287967048 4287967820 4288033612 4287443017 4287573062 4287705930 4287176775 4286784584 4286325832 4286586185 4285403967 4288030791 4289807952 4291585891 4292704621 4292575599 4293168510 4293628801 4293169023 4293632383 4293172357 4293566335 4293500544 4293764729 4293501060 4293566074 4293562488 4293165419 4292506717 4291583588 4290336625 4288758618 4287046722 4288358467 4287968333 4289282892 4289478738 4289807187 4290660946 4290138481 4290534278 4288764039 4287510111 4287312746 4285737062 4287910022 4286922622 4289035168 4288634778 4286921062 4285410926 4282843187 4284820602 4289637316 4287972482 4284818762 4285937539 4283631709 4287391632 4287388563 4286134918 4288315565 4291083200 4285540219 4284821075 4290158522 4283762751 4284357440 4283898185 4286724712 4285407045 4287381328 4283105841 4283501640 4283503418 4284684858 4285344354 4285015379 4283567180 4289954207 4290352550 4284088366 4283826742 4283632454 4283830594 4284619320 4283172928 4283303731 4283435330 4292655524 4292193444 4292785306 4292585884 4292588970 4292128666 4292128159 4288369500 4284024376 4284024628 4283501366 4283828540 4284485171 4284880204 4284549944 4284286534 4286065475 4288894313 4287902795 4288686409 4290067534 4289543505 4291120971 4291777632 4291778387 4292236888 4292107110 4292501854 4292435808 4292568171 4292767337 4293159787 4292702310 4293095051 4293028967 4292904315 4293096556 4293229685 4292837752 4293100663 4292968563 4292706183 4292903302 4292970106 4293230721 4293232261 4292839553 4293298057 4292966778 4292640380 4292832889 4291979874 4292235370 4292110181 4292831838 4292042844 4286385727 4284416064 4288159299 4290329157 4291054416 4292106837 4292108378 4292303451 4292436581 4293169304 4293636779 4293839280 4292645248 4292378748 4292379001 4292770680 4292576109 4292571748 4292440182 4292239459 4292043878 4291191648 4289152340 4284552255 4284354370 4283766348 4284094788 4284424785 4285473871 4285471547 4286326088 4287511120 4285275204 4287114828 4285074998 4285339963 4284418867 4283891768 4289224318 4292711577 4291664283 4291194733 4290609799 4286067279 4283764035 4283633485 4286132052 4290734187 4291462518 4291986289 4291525742 4291134324 4292513927 4292121469 4291791486 4291856769 4291856769 4291922562 4291725183 4291134067 4291593853 4291397238 4291789433 4291659379 4291396990 4291462783 4291265395 4291133561 4291133818 4291462268 4290611074 4291396724 4291199603 4290673778 4291199603 4291330674 4290476663 4290476923 4290805112 4290345337 4289227628 4291790709 4292255872 4293111182 4293835128 4293836153 4293836152 4293705863 4293705862 4293638534 4293705347 4293641614 4293904540 4293969819 4294167967 4293575835 4293839776 4293379747 4293839262 4293840289 4293839262 4293709734 4293709476 4293315506 4293315745 4293315503 4293904560 4293709987 4293445291 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287967049 4287968587 4287968844 4287312716 4287968073 4288032841 4287510608 4287048519 4287178056 4287242823 4286850632 4286325832 4286192712 4288229451 4290992472 4292110947 4292640109 4292772975 4293298807 4293693306 4293238917 4293172358 4293632127 4293566336 4293566079 4293501574 4293566850 4293565057 4293564286 4293297002 4292900705 4291716710 4290595156 4287967046 4287899463 4287770697 4288821582 4289019729 4289413196 4289872724 4289939028 4291055450 4289485434 4288562022 4286853982 4288363877 4286856032 4286596475 4287582343 4291135629 4288040825 4286069100 4283566934 4282974276 4286997912 4288775073 4284750431 4285150566 4287385739 4284359517 4286533513 4286928532 4286726281 4288310690 4289507500 4287712919 4283698759 4289174733 4283961667 4283437903 4284288067 4286987864 4286391875 4285736007 4284748346 4282975288 4283567160 4283238213 4283305023 4286527858 4286261864 4290087579 4290606451 4285007942 4284028479 4283832647 4284948295 4283698752 4283106873 4282318888 4287521411 4292056457 4292777606 4292720807 4292522657 4292524710 4293052076 4290080378 4282843176 4283762740 4284025922 4283762746 4284287808 4284749122 4285405240 4284944954 4284220477 4285802050 4289422964 4287642454 4289800773 4289545295 4290659146 4291053641 4291580496 4291386970 4292236889 4292172890 4291977573 4292436067 4292370027 4292962412 4292570217 4292833131 4292704874 4293032303 4293097070 4292510588 4292967543 4293293688 4292508537 4293098117 4293100147 4292970366 4293429637 4292837509 4292970356 4293230722 4292904587 4292380272 4292901741 4292442215 4292899454 4291710289 4292305503 4293157220 4291056979 4289281358 4287311946 4290136668 4290070355 4289934411 4289016651 4291053388 4292106084 4292371041 4293098858 4293305505 4293375138 4292907671 4292644748 4292769913 4292377722 4292376441 4292375673 4292767840 4292046711 4292109157 4291191391 4286916426 4284159304 4283961925 4284290378 4283765327 4285012537 4284552507 4285537866 4287508295 4286785609 4286457159 4287049807 4285009206 4285404736 4285404480 4283629627 4287709021 4292646791 4292191134 4289422448 4291332225 4286721604 4283369269 4285669447 4288297038 4291066481 4292116852 4292509033 4291853657 4292052349 4292054397 4292118903 4292119426 4291463032 4291331189 4291265653 4291988355 4291331446 4291397248 4291462782 4291462783 4291199611 4291659905 4291265404 4291528310 4291528576 4291331188 4291133809 4290870907 4291199602 4291199603 4291199612 4291265138 4290871163 4290870904 4290936696 4290408821 4290279800 4290539639 4291856499 4292650378 4294030451 4293837197 4293640326 4293638535 4293836151 4293638533 4293836680 4293640083 4293576097 4294102431 4293773985 4293773729 4293839519 4293510828 4293644443 4294167732 4293839011 4293643952 4293709232 4293643940 4293643939 4294298544 4293316530 4293315752 4293510560 4293841064 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287968076 4287314002 4288555846 4288557129 4287900743 4287968589 4288095814 4287574087 4287113031 4287181642 4287244103 4286719047 4287046983 4289346889 4290729308 4291849833 4292379260 4293100169 4293496186 4292843143 4293302661 4293631865 4293563520 4293566592 4293566079 4293566850 4293566850 4293565818 4293563261 4293494641 4292833373 4291977311 4290003016 4288622922 4288425031 4288363600 4288297546 4289217358 4290069583 4289545559 4290924115 4290073971 4289683590 4289087086 4287711089 4287903858 4286133606 4287513975 4285543531 4287120495 4286460770 4285542267 4282908724 4285810319 4289500082 4287320983 4284948556 4286336644 4286730638 4283369543 4286665863 4287786667 4286072691 4288114088 4288842669 4289495982 4285011025 4289176500 4285343568 4283107127 4283107134 4284813114 4284024899 4288899691 4291065458 4283895612 4283307342 4283369797 4283369525 4282909247 4287521158 4288771214 4285141320 4283500852 4284752464 4285405247 4284619838 4284816468 4284948280 4287444074 4289487967 4290934126 4292120701 4292908933 4292972930 4293765527 4291075983 4285734454 4283631162 4284155962 4284815673 4284944953 4284880184 4284418356 4285470021 4284486201 4284353858 4286525272 4289948785 4289018190 4288358726 4290201160 4291184467 4291647575 4291709525 4291975266 4292173152 4292172889 4292106860 4292501350 4291978594 4293224813 4292634472 4292964728 4292965239 4292966781 4292704362 4292966011 4292574587 4292769643 4292967291 4293099907 4292640648 4293295984 4292968068 4292969604 4293166730 4292969349 4293233019 4292772218 4292967034 4292706942 4292508263 4292107642 4291973983 4291907932 4292109151 4292830310 4292764773 4292569195 4292503136 4292367709 4290664538 4290463056 4291777118 4292103769 4292179591 4293047479 4292649097 4293104269 4292905846 4292509576 4292443253 4292440945 4292505458 4291652236 4291779424 4291587694 4290333787 4284683075 4284029515 4284359242 4284425031 4283698236 4285211993 4284095559 4286194760 4287310406 4286852940 4285670986 4287640395 4284943669 4285404735 4285668415 4282975030 4286130514 4291925394 4292317839 4290409085 4291332231 4287053665 4282974271 4285801545 4288958299 4291263345 4292249194 4291526760 4291263357 4291987828 4292120711 4291726470 4292120958 4291790968 4291856771 4291988089 4291264890 4292315252 4291528051 4291397247 4291265403 4291266689 4291659905 4291133550 4291134337 4291265403 4291528567 4291396734 4291396980 4291002741 4291068533 4291462517 4290673785 4291330940 4291000939 4290936954 4290212470 4290211959 4290540904 4292447874 4293109874 4293312135 4293704325 4293638535 4293706118 4293704326 4293442707 4293837702 4293904799 4294101642 4294036641 4293904024 4293578910 4293839273 4293250463 4294233246 4293773725 4293643954 4293710001 4293644710 4293839015 4293840558 4293250212 4293840044 4293839261 4293839529 4293839271 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287966278 4288100687 4287377225 4287969104 4287966791 4288030278 4287377994 4287574858 4287045703 4287176778 4287114823 4287115082 4287312714 4289542487 4291190107 4292113273 4292378748 4292708207 4293496188 4293693561 4292842630 4293695103 4293171590 4293171840 4293566335 4293566850 4293502344 4293566333 4293564029 4293297003 4292900450 4291520093 4290201421 4288753993 4287180359 4288358981 4288757586 4289280842 4289217871 4289806930 4291186532 4290405772 4290730353 4288168793 4287052893 4284748882 4286658144 4286926975 4286067039 4286659684 4284359512 4283433017 4285081955 4289431464 4287385470 4285080663 4286728829 4286004858 4286069621 4285604983 4285810534 4287787168 4285802094 4287457966 4287453585 4290226620 4286201739 4288841637 4287124101 4282908720 4283306565 4285801805 4283695163 4291393145 4293435523 4288760148 4283958841 4283304241 4282910545 4283766856 4288639649 4286334829 4284159556 4282581040 4287251823 4286987854 4289813115 4288632169 4289355638 4290676623 4288628553 4289945452 4290795104 4289747053 4291671723 4291547577 4284418097 4283302966 4283500601 4284288064 4285281631 4285287530 4285411927 4284812850 4285008183 4284354105 4284421452 4285802827 4290080886 4288825438 4289080903 4289741646 4291120463 4291841111 4291516238 4291975003 4292040554 4292172640 4292501586 4292177003 4292959839 4292437098 4292436584 4292963452 4293096811 4292899962 4293096043 4292575101 4292966266 4292964474 4292379499 4292901499 4293298035 4292639112 4293034866 4293230978 4293166725 4292970107 4292969351 4293034611 4293099399 4292378730 4292901997 4292703610 4292572004 4292635004 4292235879 4292565605 4292960104 4292502117 4292831588 4291905883 4292299875 4292438649 4292120737 4292716206 4293112245 4293440659 4293040272 4292710804 4292249475 4292576620 4292246664 4292244355 4292571507 4291321960 4292505190 4291454305 4287113549 4284026171 4284357698 4284357965 4283963984 4284226378 4284881987 4284751688 4285405766 4287972430 4286658136 4286916424 4286984267 4285139770 4285339966 4285008188 4284024640 4286189128 4291728012 4292126366 4290407792 4291200903 4288368226 4283960645 4285143874 4290799724 4292379748 4291986300 4292114781 4291461488 4292514441 4292054140 4292186495 4291725167 4292119427 4292185207 4291265921 4291331446 4291659649 4291790710 4291856512 4291199859 4291462783 4291462781 4291724168 4291462772 4291528575 4291199098 4290413695 4291068285 4291462525 4290936699 4291133304 4290936946 4291002482 4290870906 4290214253 4290475626 4290866292 4290805631 4292319099 4293177223 4293900663 4293639047 4293836151 4293638791 4293638531 4293837960 4293904267 4293904283 4294036641 4294036638 4293708193 4294167710 4293773728 4293839265 4293773729 4293773728 4293644700 4293643698 4293839782 4293840039 4293840554 4293511587 4293773725 4294233510 4293379753 4293709743 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288032841 4287444302 4287509324 4288097350 4287441990 4287312973 4288754505 4287442503 4287769159 4286523207 4287770952 4287507526 4288427607 4289216591 4291126371 4292112508 4292576882 4292970871 4293365633 4293235584 4293760378 4293169537 4293628794 4293564282 4293566336 4293500287 4293764729 4293500801 4293564029 4293492584 4292901470 4291844950 4290594892 4288032844 4287900742 4288362060 4288755789 4289019728 4289544786 4289413715 4290597214 4290141281 4291514218 4290009216 4284486228 4283434052 4285080409 4287056008 4285937766 4285737559 4284944995 4283436366 4288709805 4287712881 4283963977 4284487762 4286727560 4286068854 4285674590 4286796697 4286666127 4287519650 4286070398 4288053168 4286527610 4288517029 4288501409 4288710823 4289100453 4282975030 4283435070 4285734722 4283566149 4290339954 4293107304 4292384888 4284022841 4283238456 4282974264 4286603651 4285734475 4285996608 4285867609 4286133856 4287318348 4289353343 4289419378 4290676108 4292130483 4289950051 4289744220 4289280588 4289746790 4290677898 4294175696 4288959058 4282777671 4283895375 4284222780 4284355389 4284945984 4285736261 4284422725 4285208638 4285209407 4284354111 4284219456 4286526544 4290082425 4288953161 4288493131 4290000973 4291512911 4291580495 4291319131 4291714651 4292236886 4292043361 4292107104 4292106602 4292173667 4292567914 4292700521 4292960363 4292702567 4292963964 4293031021 4292833895 4292573307 4292771692 4292967551 4293031273 4292968581 4293034115 4293033859 4292640390 4292838260 4293232261 4292969604 4293230979 4292708219 4293034374 4292444552 4292900739 4292899687 4292310648 4292568936 4292110694 4292501609 4292441189 4292837767 4292377723 4292114548 4292774550 4293836730 4292984748 4293376428 4292980395 4293041547 4293496720 4292639860 4292575369 4292443253 4292508276 4292111991 4291718006 4291519589 4290860890 4284224317 4284030789 4284353602 4284620612 4284028996 4283505233 4285145929 4285341513 4285998933 4287710289 4287310663 4286790482 4286915398 4286062410 4286459463 4284354360 4284549186 4284549434 4291396744 4292583839 4290209380 4291003526 4287315804 4285208643 4286785101 4291132529 4292117617 4291329389 4292378740 4291068535 4292119924 4292120192 4291331448 4292185209 4291790977 4291397507 4291723887 4291922554 4291922553 4291134076 4291199869 4291855216 4291265661 4291002493 4290742644 4291528319 4291265404 4291133809 4291396734 4291396979 4290805371 4290740084 4291134068 4291133561 4290805112 4290936696 4290082682 4290148730 4289753710 4291659125 4292780148 4293507202 4293704840 4293704326 4293640329 4293835893 4293640858 4293837445 4293772185 4293708450 4294036638 4294102174 4293773729 4293773729 4293773986 4293839521 4293773728 4294102184 4293644715 4293710235 4293315506 4293511338 4293250988 4293315492 4294233253 4293184688 4293839021 4293644719 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287509067 4287575374 4287574860 4287508553 4287444559 4288688972 4287378508 4287574602 4287047754 4287311943 4286587975 4287574346 4287708493 4289415273 4291126375 4292246641 4292904303 4292970111 4292973446 4293365894 4292842872 4293696122 4293565313 4293566593 4293566079 4293567365 4293501058 4293566592 4293563004 4293298285 4292376432 4292505188 4290003534 4288100172 4287901769 4288427340 4288755789 4289282899 4289281358 4290004052 4289609294 4290531179 4291458179 4292446106 4286260306 4283368260 4285213271 4287056253 4285998158 4286067562 4284552284 4288250283 4287917197 4284555863 4283633495 4284293208 4286265451 4285740914 4285411183 4286665601 4287394468 4287190161 4287783063 4287524251 4285539697 4287458713 4288771494 4288315038 4289564844 4286003569 4283304261 4285146189 4284810809 4287382612 4291262600 4289738814 4284882755 4283107658 4284954450 4284884304 4282977097 4285935694 4289096834 4289223540 4290076037 4289751417 4290940319 4292785572 4291402372 4288690263 4288236366 4289880961 4290278516 4293775048 4291143045 4283435065 4283830861 4284358219 4284358222 4285078082 4285144901 4285145160 4285668676 4285210698 4285077565 4284814140 4283765579 4285870664 4290146946 4288366938 4288555846 4289414736 4290857296 4291384416 4291649120 4292499046 4292173152 4292107097 4292957536 4291911773 4292633699 4292700522 4292634217 4292767081 4293095532 4292703594 4293096557 4292572029 4292835945 4292963447 4292704103 4293098631 4293034115 4292902772 4293231235 4293233016 4293168776 4293034631 4292969605 4293035396 4293099137 4292838798 4292641382 4292641145 4293033340 4292245626 4293226087 4292636794 4292637302 4292969085 4293436046 4292717726 4293162623 4293367688 4293441699 4292918444 4293768619 4292981148 4292712852 4292775803 4292707455 4292444536 4291916923 4292570994 4291321704 4291651709 4291389801 4287904345 4283767114 4284620123 4284423240 4283963470 4284223812 4284161347 4284685388 4286261834 4285799749 4288631119 4286061893 4286857810 4287047754 4285272640 4286787661 4284485943 4284418117 4283498546 4290017924 4292781725 4290076268 4290807174 4287249491 4286654031 4287774542 4291327867 4292182383 4292115295 4292443240 4291988847 4292120713 4291725166 4291858303 4291790977 4291856759 4291922296 4291725184 4291725183 4291922552 4291592832 4291462774 4291462784 4291133561 4291331187 4291330940 4291528575 4291331196 4291133810 4291331188 4291133563 4291594102 4290936442 4291134078 4291132783 4290870904 4290477178 4290343529 4290146679 4290342507 4291660148 4292845963 4293505409 4293507444 4293704585 4293441139 4293640329 4293639551 4293837980 4294101900 4294102176 4294036640 4293773729 4293839521 4293773986 4294101385 4293773730 4293578654 4294167453 4293839777 4293839786 4293709476 4293644712 4294232984 4293643953 4293643940 4293315501 4293840818 4293840569 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287575631 4287640396 4287048262 4287574346 4287509324 4288033097 4287507017 4287573831 4287180615 4286782536 4286650696 4287573574 4288562258 4290071638 4291060583 4292114813 4292903289 4292643460 4293627002 4293235584 4293694068 4293171075 4293564538 4293565818 4293566851 4293566593 4293501830 4293565817 4293563268 4293232494 4293293913 4291848808 4290398542 4288753480 4287311945 4287246924 4288298065 4288757321 4289348949 4289481044 4290333018 4290800533 4292906137 4290401908 4286067293 4284683614 4285213526 4287188366 4284687455 4286990215 4288113054 4288774825 4285080136 4284751193 4283965527 4284358489 4285937253 4285872246 4284557671 4286069611 4287060382 4286266725 4287389849 4287853218 4286466444 4286469501 4288974256 4287519885 4288315309 4287981721 4285672546 4285606220 4287512184 4287053167 4288694614 4288494960 4285672285 4286263127 4285672011 4282910534 4283043401 4285872745 4290934907 4289951884 4290674309 4292058019 4292519575 4292132535 4288493636 4288236623 4288557157 4290931301 4292262587 4293118114 4284618816 4283962692 4284160068 4284820049 4285474384 4285145934 4284885332 4285605452 4285804109 4285669447 4285732931 4284355918 4284815942 4286459729 4289554805 4288893041 4289149773 4290593618 4290530905 4292236383 4291583334 4292107362 4291844962 4292043109 4291977316 4292109675 4292633701 4292436587 4293161836 4293093996 4293095530 4292702057 4293095274 4292769384 4292963960 4292703370 4292968060 4292510328 4293099654 4292575352 4292706439 4293033859 4293231481 4292643217 4293297265 4292903301 4292969095 4292444008 4292903050 4292508296 4292705402 4292508777 4292640383 4292833381 4292772729 4293168775 4293638314 4293376180 4292644500 4292974717 4293442229 4293704112 4292916390 4292983218 4293106325 4292578183 4292311412 4292441718 4292443771 4292243077 4292308838 4291456112 4291453281 4283896899 4284292937 4283768654 4283636560 4284226377 4283965005 4284425036 4286000213 4286130249 4285734985 4288368209 4286128969 4287378505 4286325831 4285932872 4286652488 4285474117 4284352330 4283958854 4289156203 4292650385 4290149257 4291134852 4287248976 4286657870 4289747059 4291395942 4292116838 4292311925 4291526502 4291987833 4292120703 4292119417 4291790977 4291922304 4291463041 4291528568 4291593597 4291397237 4291331456 4291856502 4291199603 4291462784 4291265403 4291528575 4291659648 4290542197 4291396989 4291199354 4291331197 4291396733 4291396732 4290413696 4291330683 4290541420 4290870906 4291132525 4290212471 4290081144 4290212717 4292185473 4293108079 4293377165 4293704584 4293836151 4293837199 4293834098 4293838238 4293381004 4294102177 4293708709 4294102924 4293773730 4293773985 4293969561 4294102432 4293773729 4294167454 4293578654 4293643933 4293643941 4293839786 4293643950 4293839795 4293644722 4293643937 4293840575 4293249963 4293839790 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287573062 4287051085 4287637575 4287573831 4287573831 4287571783 4287573837 4287574087 4287178824 4286127432 4287372615 4287048521 4287051095 4290074214 4291586407 4292113785 4292707711 4293363327 4292775793 4293301895 4293235847 4293629043 4293565570 4293564800 4293566079 4293501574 4293763701 4293501058 4293562999 4293756779 4292377698 4291715423 4290201163 4288099916 4287967562 4288557129 4288164427 4289151569 4289674830 4289476185 4290995568 4292773796 4290470003 4288830085 4286853483 4284951378 4285803116 4286329433 4287253129 4289235633 4287715975 4285341760 4285278311 4284027202 4283898973 4284355919 4285937767 4285805924 4286265708 4285346149 4286069623 4285475943 4287259798 4286599558 4286796685 4285607530 4288510895 4286071934 4289566385 4288767646 4285936482 4286527085 4287452544 4287644524 4287186283 4287055193 4284157509 4284488255 4285211470 4283041339 4285801307 4290423992 4291400104 4291659909 4291796642 4291273389 4292131758 4290282872 4288032842 4288955495 4288036680 4290274674 4293713326 4285212733 4283565876 4284158795 4284422468 4284356669 4284814392 4285338936 4285272887 4285472582 4286064714 4285868107 4284619586 4285470263 4284222276 4284814654 4289621379 4289091174 4289279052 4289741897 4291252815 4291186517 4291909721 4291648852 4292172640 4292567390 4291977061 4292173651 4292370286 4292502369 4292766826 4292833640 4292507262 4293161065 4292505721 4292635000 4292767846 4293095273 4292703079 4293293947 4293098599 4292575613 4293360499 4292704906 4292706661 4293164932 4292704645 4293100934 4292640632 4292509805 4292510059 4292575338 4292311672 4292575854 4292704888 4292772986 4293100409 4292975510 4293577139 4293247154 4292977055 4293368700 4293180342 4293443000 4293311658 4293377190 4292645255 4293231481 4292575879 4292179590 4292640357 4292308871 4292308838 4291979877 4287708505 4283829822 4284359242 4284358730 4283962173 4284618824 4284028997 4283700291 4286000204 4285407302 4286524239 4288297553 4286064457 4287379791 4286260554 4286455624 4286260292 4285008693 4284418362 4283434036 4287579230 4292843659 4290808974 4291135109 4286394702 4289223277 4290339170 4292378211 4292116840 4291719514 4291593591 4292185210 4291725942 4292119417 4291856513 4291463031 4291922560 4291724674 4291397238 4291265404 4291462783 4291397238 4291528577 4291265394 4291331196 4291133561 4290413680 4291265147 4291265136 4290674301 4291528061 4290608749 4290870907 4291790701 4291134070 4290870906 4290805369 4290674545 4290411642 4290473319 4290803319 4292054655 4293240194 4293770887 4293836408 4293834617 4293638277 4293838495 4293903751 4294102177 4294037409 4294036382 4294036384 4294102174 4293774500 4293380504 4293773729 4293839265 4293774499 4293839265 4293773727 4293839788 4293250724 4293710259 4293839781 4293644709 4293839538 4293840562 4293840561 4293839801 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287574346 4287049546 4287637575 4287574858 4287048522 4287050058 4287574087 4287572296 4287766343 4286783560 4286653255 4287572553 4288365134 4290072162 4291455613 4291786347 4292379777 4292775029 4292972419 4293758842 4292909943 4293234819 4293563002 4293566592 4293566079 4293501570 4293501575 4293566332 4293563775 4293232494 4293227613 4291913050 4290333008 4288100172 4287375175 4287179846 4289412687 4289016906 4289150027 4290335585 4291725736 4289943916 4289680492 4289158790 4285799228 4286194792 4285215070 4286527345 4289888938 4287980166 4283367482 4283961670 4285944433 4283701318 4285409104 4284357462 4286002551 4284887386 4286198903 4285342810 4286205056 4285673072 4286333801 4288509620 4284489296 4286004611 4287655060 4288112798 4289499823 4288378005 4287118713 4284420924 4290479257 4287907676 4284881480 4285602619 4284420668 4283236416 4286127427 4286790228 4288763758 4291264133 4291593587 4291004314 4292584599 4291936173 4292460705 4289215295 4289024859 4288691273 4288693078 4292723888 4288372821 4282384446 4284418366 4284288062 4285865789 4284355647 4285010739 4285271102 4285272375 4285207612 4287116366 4286061640 4284617783 4285207613 4284154942 4285669180 4288829798 4288958562 4289417309 4289477711 4290922316 4291578451 4291646300 4292499297 4292107359 4292106853 4292765285 4291911781 4292630876 4292437100 4292963693 4292568425 4293161323 4293028202 4293161321 4292571260 4292769130 4293095274 4292507005 4293096298 4292573309 4292836458 4292770955 4292837989 4292965757 4292575609 4292771975 4293166970 4292575355 4292770682 4292507017 4292315007 4292575369 4292573543 4292247674 4292968581 4292839578 4293306510 4294102719 4293378996 4292979122 4293237379 4293837497 4293378741 4293246110 4293374371 4293040270 4292710023 4291850869 4292507509 4292311434 4292242528 4291784063 4290798447 4285073728 4284161099 4284093258 4284684874 4284489289 4284554824 4283700030 4284752718 4286262088 4286064457 4286722379 4288298066 4286784582 4286722124 4286979912 4287049288 4285601860 4285666365 4284550195 4283893314 4287905119 4292120450 4290348163 4290801517 4287771987 4288896617 4290535008 4292181859 4292445299 4292115039 4292117361 4291727233 4292184953 4291790968 4291858302 4291922306 4291463041 4291790710 4291331447 4291397247 4291659388 4291265404 4291133817 4291331196 4291528319 4291528575 4291068285 4291199609 4290870907 4291134332 4290607990 4291528062 4290936442 4290282879 4290805615 4290542957 4291395438 4291132782 4290672248 4289882988 4290671730 4292580727 4293374835 4293900663 4293638792 4293638792 4293837430 4293771654 4294102690 4293708964 4294036383 4294036639 4294036639 4294036639 4294102174 4294102175 4294102174 4293513118 4294232989 4293184672 4294233255 4293840040 4293511101 4293775779 4293249711 4293775794 4293578414 4293839779 4293446587 4293840559 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287639367 4287114055 4287048776 4287637831 4287638343 4287043911 4287703624 4287180615 4286653259 4286849863 4286654538 4287574345 4287771468 4289416790 4291125598 4291654783 4292642159 4292970614 4293365627 4293234810 4293302146 4293631349 4293564283 4293566593 4293500544 4293698166 4293698937 4293501318 4293563504 4293299312 4292836976 4291649882 4290726471 4288752199 4287309895 4288622922 4288296781 4289016656 4289609820 4290936990 4290667639 4289677681 4291456113 4289355384 4285273434 4285800288 4287319417 4288765082 4288578468 4286462322 4283371331 4285012823 4285083987 4286135929 4285410160 4284819527 4286069098 4284224828 4286862202 4285671764 4285280111 4285804639 4285935719 4287984550 4284355934 4285806706 4287983267 4289362854 4287322501 4288244378 4289098663 4286527835 4293568905 4285727539 4284816458 4283958838 4285801802 4285869651 4287512664 4289615732 4289021025 4289424500 4291331988 4291205020 4292062114 4292857541 4290139736 4288168784 4288164940 4287970387 4291271073 4290483320 4282908729 4283828550 4284684871 4284945979 4285866059 4285537860 4285077824 4285668671 4284550451 4285408071 4287050058 4286523723 4284880448 4285142079 4285008707 4285468218 4288173670 4288563033 4288830568 4288884807 4290596950 4290596175 4291779424 4292040547 4292172896 4291912037 4292435800 4292305002 4292304740 4293026661 4292767338 4292634218 4292768103 4292966014 4292700775 4293093994 4292769644 4292766313 4293095530 4293029996 4292767076 4292966783 4292966266 4292640125 4292573048 4292836462 4292836458 4292575357 4293227883 4292248443 4292769399 4292770679 4292313208 4292708999 4292904829 4292707451 4293431925 4293177254 4294036668 4293903797 4292980386 4293299330 4293113001 4293904568 4293638324 4292979591 4293106059 4292509062 4292505968 4292509814 4291916165 4291588477 4291980903 4288824666 4283436870 4284356928 4284160844 4284423236 4284291650 4284160585 4284554822 4284751174 4286261587 4284818251 4288034638 4287641674 4286065482 4287509581 4285926717 4286525260 4285668931 4285078079 4284418110 4283826759 4286463071 4291924354 4291597214 4289948790 4287576399 4290276991 4291456101 4292180064 4291721303 4291788920 4291790454 4291856496 4291790970 4291856771 4291462775 4291725173 4291528578 4291265654 4291988346 4291789434 4291397238 4291528575 4291133560 4291331196 4291134324 4291331196 4291199353 4291133818 4291396979 4291068541 4291264890 4290676596 4291462260 4291264890 4291067770 4291133817 4290934391 4289491579 4289818219 4290343283 4291001441 4292450948 4293308022 4293509016 4293836150 4293966973 4293770635 4293904009 4294036641 4294036640 4294036364 4294036640 4294036383 4294102174 4293313955 4294102945 4293707937 4294167710 4293774499 4293904800 4293250206 4293316265 4293775791 4293446325 4294300327 4293184164 4294299313 4293250736 4293447344 4294168248 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287113290 4287245895 4287180615 4287113291 4287702087 4287769415 4287114824 4286653768 4287372359 4286129224 4287244103 4287639881 4287248473 4288759888 4291060344 4291982704 4292247432 4292774275 4293365631 4293236359 4293236608 4293628538 4293566849 4293565305 4293566850 4293501573 4293500804 4293764214 4293563519 4293495155 4292835933 4292175949 4290528589 4287508298 4287440967 4287181385 4288820050 4289019475 4290605454 4291064967 4289152615 4290528332 4291391353 4288434816 4285078862 4287054458 4287709052 4287060103 4288243608 4285342803 4284487235 4284752745 4284423250 4286004330 4285541977 4285938040 4285475175 4285279854 4285806955 4286727281 4284557142 4285542509 4285281627 4286402175 4287385730 4283501644 4284291927 4288047503 4289300411 4287256978 4288773791 4289956258 4291191395 4282581036 4283700548 4283696191 4285803335 4290605962 4289094277 4288104029 4288826726 4289753979 4291137435 4291663759 4292922821 4291200883 4287840074 4288165202 4288691799 4290144872 4292855198 4282908716 4283502911 4284089418 4286063940 4287180878 4284618819 4285013061 4284484409 4285996102 4285536574 4286126665 4286461261 4286984268 4286193482 4285074742 4284155961 4284813115 4289093223 4288300632 4289812078 4288490308 4289674832 4291775829 4291709007 4292435807 4291910486 4292960614 4292436057 4291845995 4292633949 4292436835 4293224046 4292701545 4293093996 4293031533 4293093996 4293030252 4292766313 4292766825 4293094252 4293093994 4292572798 4292834409 4292899946 4292442216 4293032063 4292835690 4292504456 4292510828 4292702583 4292376185 4292509545 4292769399 4292311675 4292510830 4292836743 4292969864 4292840618 4293308829 4293512128 4293909193 4292915124 4293174713 4294104258 4293905326 4293574843 4293376438 4292778656 4292441458 4291981943 4292439940 4291455350 4292308853 4291849595 4284945218 4283830596 4284225101 4284291391 4285016915 4284292939 4283962946 4284225858 4284949067 4286129478 4286589257 4286657358 4287771988 4286784582 4286788429 4285864775 4285866823 4286719306 4284814130 4284483911 4283892544 4286330721 4291460473 4291401108 4290736755 4287512668 4290273895 4291455583 4291983726 4291525477 4292183412 4291987832 4291792512 4291790970 4292184952 4291857544 4291856760 4291659647 4291922553 4291330682 4291265651 4291265662 4291265403 4291528575 4291265403 4291331722 4291331195 4291133817 4291594111 4291134075 4291001974 4291462781 4290476922 4291265146 4291199613 4291461221 4290739836 4290541165 4290280559 4290278510 4289753978 4291263348 4292778114 4293702267 4293704582 4293638534 4293770633 4293904266 4294036898 4294037153 4294036382 4294037410 4294036382 4293513119 4294036382 4294102945 4294101917 4293578653 4293839008 4293839264 4293250206 4293905320 4293710257 4293250224 4293906857 4293446323 4293906099 4293644720 4293511858 4293840561 4293578422 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287313741 4286193223 4286848072 4286784583 4286719303 4286656331 4287243847 4286720328 4287308872 4286718024 4287179080 4287047494 4287903307 4288759912 4291323492 4291127933 4292708477 4292970109 4292972417 4293694841 4293630329 4293171335 4293566591 4293566851 4293566850 4293501317 4293765243 4293501060 4293565815 4293297773 4292443490 4292043879 4290335575 4288227912 4287965511 4288554821 4287967053 4289618807 4291725215 4288822098 4289871952 4290596178 4290209918 4288300911 4285474656 4286329712 4283697204 4287917224 4286728555 4284225103 4285278291 4284357971 4286204273 4285014120 4284685910 4286072969 4284950102 4286797450 4285872481 4287056000 4286003563 4285346410 4285806692 4286003062 4286599812 4286860428 4283829838 4284950122 4288773784 4288769183 4287789996 4290091952 4284621903 4282976061 4282911817 4286133080 4291720066 4291918460 4292324521 4290420402 4290151080 4291335844 4292851878 4292462015 4292128909 4287374650 4289155930 4288824155 4289944676 4292462525 4285804356 4283439441 4283371850 4283566908 4287051854 4288759635 4285470268 4284357958 4284681267 4285996870 4285010749 4285799491 4285801030 4287642964 4285800510 4284876854 4284811331 4285467965 4288303976 4288363338 4289287277 4287903564 4290525517 4290399059 4291187018 4292497760 4292107616 4292041311 4292436064 4292699486 4292435558 4292567908 4292375911 4293158510 4292701289 4293095532 4292702313 4293095532 4292766569 4292634218 4292832106 4292702568 4293226607 4292440423 4292307560 4292966254 4292441448 4292898666 4292505444 4292573290 4292376952 4292378493 4292701305 4292507751 4292772477 4292839810 4292971392 4293102196 4293038194 4293363060 4293434235 4293431428 4293705886 4293971110 4293433747 4292710802 4293102456 4293436310 4293107093 4292110702 4291781752 4291913844 4292113272 4292048513 4289284432 4283635800 4284029508 4283764030 4284489029 4285016915 4284029764 4284357186 4284555080 4284685639 4286131018 4286458953 4287379022 4287184465 4286654022 4287968332 4286264653 4286456391 4287049548 4285400890 4284025140 4283565622 4285539925 4290937469 4292648859 4289815913 4289024365 4290145134 4292311649 4292441686 4292115556 4291197789 4291857020 4291792512 4292119408 4291790969 4291856760 4291594111 4291921267 4292119168 4291594361 4291265662 4291527024 4291331197 4291462783 4291462773 4291528318 4291331196 4291396476 4291002749 4291197802 4291462782 4290870905 4291528316 4291067769 4290674533 4291068286 4291197024 4290477693 4291196266 4290080376 4289162875 4291918438 4292650110 4293635187 4293706375 4293639812 4293904268 4293838749 4294101919 4293513632 4294102689 4293708707 4294036638 4294101919 4294036382 4293512861 4293512872 4294232743 4293578663 4293840033 4293839788 4293512107 4293839538 4293907637 4293511858 4293577650 4293250736 4293840553 4293840308 4293579182 4293839536 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4286917447 4286455112 4286324552 4286979400 4286850888 4287309127 4287246152 4286719048 4286719816 4287307080 4287177287 4287574858 4288426569 4288760925 4291192689 4291852140 4292379776 4292972155 4293431667 4292907403 4293302661 4293237630 4293564799 4293566336 4293565822 4293501573 4293501573 4293566850 4293565054 4293495148 4292836977 4292369487 4290790479 4287573833 4287377478 4287703630 4289281881 4291790494 4289153120 4289214033 4289674828 4290070633 4291329419 4287513455 4285210432 4284744786 4284227662 4287849612 4288837288 4285144389 4285147495 4284620356 4285213525 4285146446 4284227161 4285018210 4285672298 4285674080 4288373677 4286661732 4287453069 4285742712 4286071678 4286200684 4284687192 4288048284 4286268275 4283961931 4285213025 4285480041 4288508071 4288380840 4288511912 4283437903 4282515509 4290207597 4288494677 4289550714 4292122792 4293118910 4293313721 4293774000 4293248687 4292588956 4288032317 4289286235 4287901524 4289547086 4291404962 4290347112 4282777648 4283960894 4284090685 4283894839 4287704652 4288695885 4283959608 4285404224 4283893817 4285997125 4285864517 4285603138 4287051086 4286262089 4286588492 4284684345 4284745539 4285469245 4288434791 4287247178 4288500825 4288818759 4288952649 4290985802 4291972440 4291321174 4292367718 4292699999 4292435551 4292109671 4291911513 4292502879 4293026407 4292569442 4293158756 4292701034 4293095532 4292703594 4293095532 4292766569 4292374630 4293619568 4292176995 4293028970 4292896859 4292632161 4292372838 4292439402 4292637033 4292574318 4292439657 4292639852 4292964457 4292574832 4292376423 4293159533 4292111211 4292830822 4292567394 4292698475 4293093737 4292897917 4292900721 4293228935 4292770677 4293420667 4293487483 4292835703 4292309866 4290135913 4291255899 4291588218 4292245881 4291784302 4285011005 4284029769 4283961670 4284357699 4284620619 4284422983 4284686411 4284423497 4285014859 4285013316 4286067021 4285932615 4286852172 4287184206 4287311433 4287050575 4287507017 4285800264 4287116620 4284879161 4284025141 4284483654 4284617022 4290938501 4292123291 4289220701 4289485671 4291586917 4292050267 4291790199 4292114783 4291854455 4291857018 4291791738 4292119161 4291858311 4291397240 4292316547 4291134067 4291199613 4291462775 4291133561 4291331445 4291001975 4291134325 4291725699 4291002492 4291199097 4291005561 4291462012 4291068541 4290936697 4290740091 4291133831 4291199601 4291067771 4291263851 4290805628 4290670698 4290606712 4289884782 4289881964 4291134327 4293107578 4293375112 4293638788 4293968783 4293838216 4294036897 4294037152 4294037164 4294037152 4294036382 4294036381 4293512862 4294037153 4294102689 4294168224 4293579167 4293643943 4293773477 4294233767 4293054894 4293905844 4293251237 4293512626 4293513397 4293775534 4293249721 4293645475 4294233276 4293579686 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285930824 4285996872 4286586696 4285800008 4286390856 4286848072 4286720840 4287310152 4286784584 4286783048 4286586440 4287573830 4287903309 4288168539 4291257701 4292113786 4292772989 4292972672 4292972678 4293302660 4293237374 4293237893 4293567107 4293565048 4293501575 4293765243 4293501058 4293501316 4293564279 4293493873 4292836960 4292043608 4290069839 4287638344 4287373123 4288165210 4290672020 4290077039 4288295247 4289740363 4289219420 4291389055 4291527576 4287706218 4283896638 4283632724 4286464633 4284291657 4286993295 4285278051 4285082194 4284950365 4285608559 4285476451 4284751703 4283506010 4284817236 4285744263 4288315565 4286398065 4287715990 4288043915 4285677420 4285610612 4285475192 4285081938 4288574634 4286659197 4284690281 4287060390 4286728579 4288314033 4287713151 4288244391 4287850407 4293631911 4289360558 4288308897 4291340207 4293245111 4293708735 4293446074 4292724151 4289283652 4288957273 4289480532 4288691799 4290674041 4292659378 4282908719 4283437392 4283633456 4284554060 4284025919 4285274173 4288232018 4284091192 4284879412 4285010494 4285600316 4285406525 4286063945 4287047752 4286262346 4287705163 4283958067 4285074750 4285203252 4288703091 4287443270 4288695390 4287114311 4289081674 4291117643 4290990165 4292103511 4292433768 4292109919 4292109407 4292699482 4292630881 4293089888 4292437342 4292567908 4292370797 4292832352 4293028459 4292507257 4293095018 4293095274 4292834412 4292443246 4292634447 4289735748 4289343814 4290464324 4291516744 4291845970 4292044125 4292503135 4292307035 4292107618 4291912284 4292169806 4291841868 4291843664 4292173127 4291973710 4291776851 4291118419 4292695904 4292565340 4292310373 4293028962 4290066758 4290063420 4291117906 4290991440 4289542220 4289872720 4291520612 4292771964 4291919489 4289613926 4284422212 4283701326 4284355907 4284619586 4285146187 4284226114 4284291907 4284290364 4285800262 4285340484 4287183953 4285470016 4286789196 4287374924 4286064968 4287906386 4286259271 4285600319 4286457417 4286062654 4283893556 4284483646 4284156738 4291130492 4292123030 4289484655 4290670444 4291261031 4291918961 4292836704 4292052845 4291458414 4291659648 4291857520 4291791478 4291856514 4291988080 4291199863 4291988346 4291593597 4291396982 4291659907 4291265395 4291199098 4291528576 4291396219 4290676594 4291068286 4291659382 4290414462 4291133829 4290936697 4291199613 4290676586 4291264883 4291199602 4291199869 4290805112 4291132781 4290279801 4290146169 4289686882 4291987330 4292387683 4293832323 4293836938 4293838474 4294036898 4294036381 4294037922 4294036124 4293512862 4294102688 4294037164 4293512861 4294101917 4293773473 4293774498 4293838753 4293578650 4294168245 4293579173 4293511605 4293645477 4293841847 4293840049 4293709998 4293644463 4294168753 4293840062 4292989098 4293841589 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4286128968 4285733954 4285602883 4286587720 4286455880 4286850888 4286784840 4287306824 4286784072 4286717000 4287769415 4287573832 4287183436 4289810016 4290995068 4291855728 4292378760 4292971898 4292973184 4293697919 4293631871 4293173127 4293566078 4293567367 4293764472 4293501319 4293500800 4293698680 4293564281 4293495405 4292900192 4292107349 4289677399 4288295505 4286781506 4290937243 4291130760 4288952401 4289016911 4289280087 4290866052 4292839577 4291001477 4287047767 4284488800 4285934677 4287515525 4283565112 4284227646 4285145683 4285345365 4284622939 4286004584 4285411944 4285211746 4284290396 4284356964 4286271874 4288777649 4288244130 4287650710 4286531959 4287980189 4286924403 4285941359 4284685421 4285346394 4288311715 4288313773 4287191169 4284686938 4286272120 4285150842 4285801801 4291066753 4289820304 4289419622 4291862419 4292786872 4292392626 4294102463 4293053109 4289688952 4287902279 4289155163 4288822360 4289682022 4293449932 4287054670 4283367496 4284553787 4284554310 4285472840 4283960377 4284813107 4287182671 4285276229 4284417850 4285207866 4284944953 4285471293 4286128714 4285668411 4287048778 4287511377 4284811062 4284155955 4285205305 4288565852 4286325832 4288826203 4287313738 4288162374 4289807439 4290856006 4291778907 4291777609 4291649636 4292830569 4291911514 4292110177 4292106842 4292501350 4292110941 4293225052 4292702827 4293487470 4292964217 4292770412 4292899709 4293096301 4292967537 4291449940 4289084495 4289542744 4289407558 4288357704 4289210951 4290065219 4290394694 4290590278 4291115844 4291119689 4290461262 4290263626 4289803339 4289015624 4289276229 4289933127 4291050831 4291776340 4292233814 4292302427 4291312735 4289939019 4289082457 4289808987 4291385966 4290991705 4291388767 4292703610 4292051071 4292244846 4285406019 4283699013 4284094789 4284290364 4284356169 4285603912 4284290115 4284290115 4285342280 4284685122 4286327630 4286590794 4285406532 4287969874 4286656075 4286787915 4287773009 4286392136 4285071926 4287117134 4286590027 4284615736 4284158533 4284419394 4288962432 4291992202 4290143093 4290936967 4291915356 4292445552 4292245854 4292444784 4291593322 4292187017 4291396727 4291860358 4291856504 4291265655 4291988089 4291463033 4291594105 4291331446 4291856001 4291265404 4290808182 4291396467 4290479742 4291331200 4291068274 4291199097 4291462012 4291199353 4291133810 4290151040 4291330427 4290871162 4290871164 4291263852 4290870905 4290345594 4290211959 4289293422 4290211182 4292182892 4293110141 4293703301 4293770632 4294036366 4294037153 4293709476 4294036906 4294037921 4294102431 4293513633 4294036381 4294101917 4294036394 4293513116 4294167464 4293579421 4293838763 4294102695 4293644455 4293710255 4293839548 4293250209 4293514681 4293513140 4293382326 4294168486 4293579698 4294234290 4293774770 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285602887 4285800524 4285733954 4286062153 4285866568 4286980168 4286852680 4286783560 4286848584 4286850887 4287112518 4287576663 4287838055 4289548373 4291126117 4291590783 4292968569 4292972662 4292973182 4293238150 4293631871 4293566850 4293566851 4293369970 4293500804 4293698680 4293699709 4293697916 4293563000 4293100915 4292573549 4291782246 4290070351 4287636052 4290275977 4291987366 4288562004 4289080909 4288950861 4289418864 4292312212 4290868092 4290341511 4286590046 4284160835 4286661231 4284948291 4284226646 4283564614 4285541463 4285543800 4285213779 4285544820 4285212243 4285086306 4285475965 4284291168 4286598279 4288839344 4288116389 4287254916 4286796154 4287187858 4287191431 4287980203 4286926199 4285742470 4287056245 4289566383 4286991233 4285012810 4285348476 4283765580 4286530161 4291129996 4291261038 4292962908 4292891488 4293117884 4293714124 4293447364 4292523685 4287972432 4289807701 4288492116 4289549928 4292986041 4289890928 4282581056 4284355893 4285078598 4285272378 4284552504 4284093502 4284747059 4286064461 4286522179 4284290618 4284943930 4285996613 4285340743 4286128968 4285667907 4285803082 4287575888 4285272893 4285075782 4284353855 4288695916 4287113800 4287511631 4287444817 4288360009 4290002508 4290199118 4291318611 4291451737 4292369243 4291979105 4292236376 4292172635 4292043099 4291977316 4292435565 4293224814 4292634218 4292570217 4292831848 4292770156 4293163119 4292704364 4292901742 4292238440 4292107368 4292763491 4291648868 4291184217 4291380306 4290722642 4291315799 4292298576 4291973472 4292564073 4292104542 4291581029 4292041310 4292103276 4291710811 4292040541 4292102240 4293283686 4292961668 4292960640 4293095552 4292700821 4292828533 4292042609 4292112762 4292110695 4292571001 4292640874 4292507260 4289809240 4283370825 4284029252 4283832399 4284619586 4284687435 4284620875 4283765823 4283898184 4285209148 4285338431 4286723918 4285471559 4285865287 4287839311 4286722123 4286655563 4287773265 4286390856 4284681783 4286461005 4287117145 4284484924 4284551493 4284092221 4288696683 4292842624 4290079607 4291660672 4292113755 4292118140 4292378718 4292052074 4291592820 4292119161 4292186504 4292118903 4292185209 4291528569 4291528578 4291790717 4291528578 4291988088 4291331455 4291462782 4291593855 4291396476 4290873732 4290936183 4290939270 4290939013 4290873718 4291133564 4290742147 4290739062 4291462515 4291134077 4291330683 4290936946 4290476922 4290870125 4290015339 4290016113 4290276460 4292120952 4293042823 4293835126 4293904267 4294036641 4294037152 4294102442 4294037921 4293512614 4294103470 4294036896 4294101917 4293513633 4294101917 4294167452 4293774249 4293840304 4293579164 4294167976 4293709990 4293250480 4293840561 4293841076 4293840037 4293842360 4294234022 4293579688 4293840052 4293775795 4294102448 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285144905 4285864770 4286128969 4285603394 4286586696 4286388808 4286260040 4286850120 4286847815 4286195530 4287179336 4287579739 4287711570 4290007429 4291323489 4292116096 4292708209 4292972157 4292972408 4293697917 4292976506 4293631617 4293566850 4293567110 4293566851 4293502088 4293501318 4293500800 4293629558 4293429098 4292573547 4291648093 4289935962 4290147723 4292187563 4288626502 4288096066 4288688719 4288952924 4290996352 4292116631 4290535542 4289812857 4286528867 4285212752 4285015124 4286198874 4284682556 4285080412 4284026688 4284620864 4283437383 4286267502 4285343597 4284754510 4286988156 4283830877 4286140812 4289572550 4288639648 4285080682 4286598272 4287385990 4286663326 4286599541 4287979662 4286861180 4286992256 4285278051 4286729845 4287254677 4284954220 4287123600 4289162136 4292970102 4293817171 4292110181 4291711841 4292449410 4294567121 4292855227 4289360234 4288757341 4288562257 4289483354 4292321936 4292461988 4284089920 4283241801 4284686925 4285208891 4285210184 4284226630 4283895614 4284814911 4286260809 4286194763 4284681522 4284551994 4285736267 4286324290 4286128970 4285668930 4285998410 4286986320 4285208643 4284551997 4284616512 4288041063 4286062662 4287707982 4287575117 4287247180 4289673289 4290135114 4291710556 4291581522 4291451480 4292108629 4291845472 4292433505 4292108634 4292042854 4291977053 4292568171 4292110695 4292898154 4292831848 4292639104 4292378219 4292966525 4292704364 4293228143 4292308584 4292370015 4292501843 4292502870 4293088103 4292433261 4292826462 4293086293 4292958815 4293483889 4292503674 4293353079 4293554821 4292968615 4292837555 4293102234 4293036212 4293108386 4293175472 4292979898 4292981672 4293293965 4292501891 4292504710 4292182122 4291918717 4292639078 4292770687 4291455583 4284879686 4283830597 4284292427 4283897925 4285078339 4285865285 4284356682 4284160574 4284422205 4285538373 4285014858 4286851659 4284815944 4286457671 4287774282 4286656588 4287179848 4287641423 4287050062 4285206329 4287048781 4287052876 4284420925 4285206842 4283697215 4287448156 4292254356 4290346891 4292116334 4292376422 4292970616 4291918175 4292314233 4291396727 4292055662 4291398262 4291857273 4291659392 4291528569 4291594103 4291528578 4291331188 4291528579 4291396980 4291659906 4290936955 4290936947 4291659391 4291199354 4291133810 4291133565 4291133811 4291068541 4290936441 4291528051 4291068286 4290739319 4290675316 4291396221 4290674540 4290606200 4290476923 4289292642 4290668906 4292447353 4293177476 4293836938 4293839005 4294037153 4294037665 4293709229 4294102430 4293840549 4293578139 4294102688 4293512617 4294168737 4293512604 4293579177 4293839527 4293579175 4293644455 4293841069 4293251240 4293775536 4293774770 4293841845 4293841075 4293643448 4293644466 4293644466 4293840553 4293839527 4293579176 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285406275 4285275971 4286128969 4285996616 4286520904 4286392392 4286917192 4286850888 4286848072 4286848071 4287771209 4287378510 4288299869 4289417809 4290340480 4292377454 4292510835 4292970112 4293365114 4293238662 4293631873 4293370227 4293566595 4293567111 4293502829 4293699453 4293698681 4293567107 4293300100 4292708482 4292573299 4291187576 4291130510 4292251809 4288693065 4287113028 4288426313 4288622159 4289744223 4292117641 4289747574 4290532700 4289155450 4287839848 4285934699 4285012805 4287783590 4285409871 4285015373 4283303752 4284683865 4283501886 4286468232 4285869142 4284882505 4286929825 4283105347 4286470035 4290228665 4288179106 4284818775 4284621420 4286468491 4287455896 4287522461 4286594430 4286201458 4286596736 4284161874 4284819546 4288112286 4286928278 4288312998 4288966291 4292313745 4293163621 4292831837 4291709019 4291522418 4293320148 4291201145 4288951626 4289088857 4291127912 4292846989 4293249970 4286658626 4283110727 4284687693 4284554822 4285014093 4285013315 4284617787 4284093504 4284420409 4285601855 4285799748 4285865287 4284549939 4284814405 4286260555 4285274171 4286194249 4285866823 4287572553 4286128969 4284418366 4285602108 4286988881 4286195529 4287772497 4287052113 4287047497 4288229705 4289741391 4290661698 4291383385 4291382609 4291975524 4292038223 4291909724 4291714913 4292303711 4291977566 4292501351 4292435557 4292567915 4292897641 4292835949 4292770158 4293096043 4293097328 4292640880 4293160812 4292896098 4292370031 4292631385 4292435040 4293680473 4293025376 4292169058 4292825956 4293348955 4293747056 4293290120 4293033875 4293497465 4293701281 4293635470 4293632905 4293635739 4293637802 4293706169 4293307804 4293554560 4292304496 4292308866 4291918201 4293035146 4292570227 4291392881 4287575373 4283765059 4284224571 4283633225 4284555078 4285012547 4285407051 4284157496 4284091450 4284684607 4285668926 4285405244 4285470270 4285798723 4286918732 4287579997 4287178055 4287575887 4288360777 4285666372 4285537091 4286984269 4287512657 4284748356 4284485444 4284617797 4287774306 4291861916 4291525759 4291855229 4292049246 4291855467 4292836454 4291462261 4291922545 4291856260 4291463807 4291857791 4291661429 4291528313 4291528579 4291922295 4291922298 4291922296 4291594115 4291396980 4291659907 4291790713 4290807676 4290938997 4291067773 4291071096 4290871680 4291396732 4291133820 4290873733 4291462269 4291199600 4291528063 4290151281 4290608250 4290081132 4289754490 4289358204 4291064420 4292317318 4293506177 4293967992 4294037669 4294036895 4294037678 4293513373 4294168738 4293774756 4293775012 4294102432 4293644446 4293774765 4294102696 4294166961 4293579945 4294167718 4293840310 4293840294 4293840309 4293185715 4294234291 4293578673 4293645226 4293644456 4293644445 4293839785 4293839777 4293579424 4294101919 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285538117 4285079626 4285798722 4286127945 4285932360 4286455368 4286979656 4286325320 4286454085 4286259271 4287115596 4288102222 4288366435 4289413981 4291258475 4291588991 4292837739 4292513660 4293366151 4293236095 4293632126 4293172617 4293371513 4293565564 4293501316 4293501318 4293501317 4293566333 4293300622 4293172638 4291395489 4290734991 4291462301 4288693584 4287243076 4287508551 4287834956 4288691034 4290536318 4291596197 4289218411 4290137190 4287975283 4285802835 4286659198 4285672014 4289436089 4286130529 4283696959 4283961674 4283305284 4284819043 4287258515 4285607008 4284422231 4287126153 4284488289 4287065238 4290095031 4288770980 4285410414 4284161107 4286203762 4285741695 4286796946 4288577459 4287322504 4286268024 4285609583 4285213522 4286791524 4286532228 4288970683 4289097369 4291528872 4293030747 4292368232 4291125612 4292067016 4292329645 4286784316 4289879145 4291126882 4293632381 4292781957 4289093210 4283041342 4284426320 4284090697 4284555339 4285406013 4285144390 4284684349 4284618297 4285139000 4284420658 4285996613 4285537086 4284945721 4284749113 4285471293 4286194249 4285472840 4286064200 4286461005 4286064200 4284880189 4284486979 4286525516 4286454846 4287709009 4287182414 4286586950 4287969872 4289608778 4290529365 4291119182 4291448915 4292301923 4291188571 4291908183 4291582814 4291712093 4292498791 4291977304 4292568676 4292106082 4292374119 4292900460 4293160553 4292965501 4292640623 4293554543 4292705134 4292833386 4292374375 4292106340 4292305248 4292040024 4292042086 4293220198 4292435310 4293089118 4292957532 4293287788 4293489012 4293227143 4293227389 4293231750 4293228927 4293226110 4293225595 4293033617 4293229712 4292107371 4292310662 4291917688 4292510330 4292705641 4291917943 4291388263 4284090430 4283895349 4284289866 4283895615 4284226372 4285405757 4285208638 4284552762 4284223290 4284815679 4285273405 4286919247 4284550194 4284944189 4286786380 4289022552 4286457931 4287773518 4287118415 4286260295 4286522952 4286259781 4288041052 4285009717 4284487236 4283962180 4287445858 4292319890 4291135372 4291789686 4292510828 4292905852 4291919460 4292182897 4291594104 4291661430 4291924342 4291857535 4291857791 4291529599 4291792756 4291528323 4291528568 4291528570 4291594105 4291594106 4291659641 4290742140 4291265150 4290807686 4291790968 4291396221 4291067510 4291462259 4291068275 4291133821 4290479216 4291330684 4290871154 4290870649 4290476920 4290936698 4290013035 4289425007 4290211440 4292515452 4293834115 4293904267 4294036897 4294038952 4294038177 4294103214 4293512346 4294103457 4293773994 4294103457 4293578922 4293773982 4293774764 4293645983 4293839283 4293645226 4293577889 4293841080 4293841063 4293841069 4293775531 4294168737 4293643933 4293839008 4293644962 4293839264 4293773729 4294102176 4294035851 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285867084 4285535804 4285799748 4285734979 4285996104 4286520648 4286389320 4286521160 4285865288 4286454343 4287180617 4287247695 4289086555 4288627280 4291257187 4291851375 4292577411 4293363327 4292972922 4293302905 4293172358 4293632901 4293566594 4293501318 4293699453 4293698680 4293502859 4293566332 4293301395 4293037196 4293045913 4291655041 4290466639 4287568707 4287044424 4287506756 4287703894 4289679732 4291926955 4289547366 4289674605 4290204773 4288366195 4284748871 4285538905 4286734733 4288771478 4285012036 4284291149 4284161347 4284223064 4284952153 4287192225 4285077823 4288041886 4284363872 4286394237 4288517308 4289236903 4287585690 4288246951 4284091724 4286071676 4286533511 4284157785 4286139766 4288906428 4287060116 4288177037 4286597775 4287456939 4286860670 4289829046 4291268522 4290082711 4292707230 4291312472 4292118407 4294107590 4289096568 4289547874 4291984238 4293760109 4293514404 4290275698 4282912579 4284096336 4284751430 4284423492 4284948039 4285080909 4285211212 4284687182 4284421693 4284552247 4284817995 4285407052 4285406531 4285342283 4284617527 4285601852 4286197836 4286127176 4285603648 4286590538 4286654795 4284943928 4285143369 4286790996 4286788436 4287774288 4287247182 4286784583 4286982470 4288757587 4289611590 4290792791 4291120724 4290925396 4291711309 4291121231 4292302429 4291646555 4291715676 4292108128 4291847271 4292042338 4292108904 4292308069 4292702332 4292374371 4293161837 4292442749 4293161837 4292767849 4292765290 4292109161 4292307806 4291977300 4292236637 4291714146 4292436313 4292895331 4292959583 4292957540 4293551232 4293093494 4293355143 4293291909 4293290887 4293289863 4293355655 4293420935 4293156468 4292045443 4292312707 4292510328 4292313738 4291784299 4291456114 4287509322 4283829056 4283965263 4284096335 4283831359 4284226111 4285669956 4284422724 4284684350 4284750143 4285733695 4285207869 4286260810 4284552505 4285797184 4287246668 4288366426 4286588232 4287052620 4287116879 4287374662 4286392904 4285667655 4287974481 4285338429 4284945475 4284225096 4286331996 4291924881 4292186498 4292249723 4292706932 4292120957 4292442726 4291528826 4291856514 4291923072 4291462522 4291661430 4291856250 4291528568 4291593859 4291333235 4291987843 4291528568 4291594106 4291594106 4291659641 4290939520 4291593589 4291528053 4291528064 4290807931 4291199355 4290348163 4291134076 4291133819 4291068544 4290542970 4291132783 4291003506 4291002233 4290082682 4289623407 4289425008 4290864995 4293039225 4293376904 4294102690 4294038436 4294037921 4294038191 4294037407 4294103986 4294037664 4293708449 4294036895 4294037674 4294103993 4294102950 4293382071 4293644464 4293579431 4294169528 4293775275 4293776303 4293643675 4293643933 4293643934 4293446813 4293839523 4293446282 4293969820 4293773197 4293838747 4294036897 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285405507 4284552247 4285930309 4285798979 4286127689 4285994309 4286586952 4285996104 4286061640 4285734215 4287640652 4289083979 4287514976 4289412945 4290666345 4291390566 4292640877 4292971122 4293168251 4293235591 4293631868 4293370487 4293566339 4293699452 4293699452 4293501319 4293764986 4293566850 4293301635 4292708739 4292966004 4291255649 4289675079 4287835719 4287046726 4288032600 4288296026 4291792289 4291131524 4289018475 4289480538 4290473341 4286660194 4284750692 4284224576 4288776619 4288440201 4283829049 4284029254 4284946779 4283307334 4286535047 4286990982 4283502413 4286464885 4286726021 4285610088 4290161853 4287915951 4286134883 4288516543 4286989199 4286136433 4288443570 4285215591 4284950108 4286072690 4289496248 4286857080 4288710587 4288971431 4287779984 4287850382 4292517294 4291530133 4290999949 4291314533 4291133573 4292922305 4289615979 4291917946 4293431923 4293904549 4291199605 4285211451 4283701601 4285014858 4283833926 4284424781 4284621388 4285801805 4284424268 4285344592 4284359499 4284555339 4285014602 4285144901 4284946755 4284949323 4285669189 4284949839 4285079367 4286195527 4285736523 4286001485 4286656330 4285277005 4284945467 4286196300 4286918996 4286788426 4286198862 4286324039 4287181130 4288358982 4289936717 4290004551 4290922317 4290789958 4291515475 4290991958 4291384925 4291124828 4292107108 4291780700 4292110951 4292373097 4292307303 4292765035 4292506469 4292700777 4292767847 4293160553 4292703594 4292834925 4292242534 4292569194 4292633451 4292109418 4291977309 4292042860 4291977555 4292302176 4292235613 4292761696 4292959327 4292829544 4292763241 4293357948 4293092716 4292960361 4292434535 4292694117 4292110947 4292509559 4292248457 4292441461 4292246381 4291851378 4289874504 4285865792 4284089923 4284686409 4283831359 4284357699 4284816976 4285076291 4284161350 4285734979 4283767108 4285667902 4285867333 4285865796 4285142329 4285600320 4287772748 4287577418 4286522697 4288364361 4287703627 4286659152 4286389063 4286257478 4288567132 4284944955 4285537350 4284551748 4287183205 4291924625 4292055444 4291525739 4291920744 4293233269 4292182114 4291659632 4291923841 4291528047 4291529591 4291923584 4291923573 4291528578 4291528566 4291988360 4291464052 4291988608 4291528568 4291594105 4291396736 4291527796 4290939528 4291136126 4290807668 4291724671 4290544512 4290807667 4291001977 4290413954 4290413944 4290936183 4290870649 4290936698 4290081645 4290475631 4289687663 4289488253 4290212450 4292712834 4293574544 4294103201 4294037420 4294038189 4294037418 4294038436 4293512345 4294037677 4294103213 4294037664 4294037417 4293513894 4294038200 4294169256 4293710506 4294102965 4294102953 4293514145 4294167967 4293578398 4293839266 4293773730 4294167178 4293641629 4293641374 4294167966 4293773986 4293969560 4293708193 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285344081 4285471556 4285338685 4285274948 4285404733 4285802052 4286127178 4285734468 4285668675 4286388551 4287509838 4288563795 4288296781 4288494416 4291255389 4292637798 4292379007 4292642417 4293232001 4293302901 4293174153 4293371257 4293567110 4293501317 4293500803 4293698680 4293502088 4293566850 4293628545 4293035890 4292507757 4291912520 4289611095 4287899977 4286457925 4287308632 4289814632 4291531946 4288952939 4289415001 4290269278 4289615986 4285274966 4284882258 4285471571 4289500582 4287456134 4283498555 4285274692 4283175498 4283764288 4286864794 4285477979 4283960916 4284358495 4286204551 4286724485 4290170572 4288772787 4284818024 4286404487 4288970939 4287125908 4288445345 4286594429 4285409123 4284749413 4285812092 4288977340 4287984549 4287053162 4290218651 4285540963 4290021295 4290141818 4290087596 4290990687 4291007142 4292728011 4292968305 4293566330 4293634958 4293576074 4285666116 4283702881 4284358469 4284422988 4284687952 4284752460 4285211470 4285143613 4286063427 4284881730 4284617539 4284488268 4285539147 4284815935 4284618043 4284556110 4286455879 4285672010 4285210443 4286196556 4285734722 4286065739 4285998664 4285930307 4284553536 4286128967 4286985550 4286851659 4287445841 4285798982 4286263115 4287376967 4289082957 4290070091 4290529620 4290594385 4289871689 4291121498 4291578970 4291253840 4291712864 4291451735 4292108389 4292042339 4291976552 4292638311 4292632424 4292309623 4292700537 4292638331 4292963965 4292833382 4292897640 4292963946 4292567400 4292242024 4292501091 4292699494 4292042591 4291715426 4291319128 4291449943 4291906388 4291842390 4292433758 4291906651 4291905881 4292103780 4292106081 4292045428 4292448388 4292182427 4292638307 4292705898 4291918452 4290991184 4286719307 4285079365 4283896902 4283895615 4283501629 4284421701 4284554051 4284616502 4285407306 4285079368 4286522953 4284683834 4285601085 4285472839 4285535291 4285535039 4288304216 4287574611 4287115339 4287052108 4287051086 4287377996 4286324551 4286258502 4287840082 4286255934 4284945989 4283898180 4286856811 4292118650 4292121502 4291919722 4292316023 4292446070 4291723390 4291463026 4291529590 4291529600 4291398518 4291528312 4291529597 4291594112 4291594113 4291332217 4291595391 4291528310 4291595656 4291528311 4291793531 4291593857 4291790710 4290611079 4291004292 4290938740 4290545270 4291527539 4291133820 4290870908 4291265405 4290541943 4290348146 4290803565 4290346107 4290278511 4289555823 4288898154 4290405997 4292516991 4293902725 4294038181 4294038692 4294038703 4294038190 4294038177 4294102958 4294037407 4293579425 4293513898 4294103734 4293709494 4294104224 4293711033 4294103722 4294103980 4293513385 4294167968 4293512862 4294233248 4293772940 4293839266 4293773986 4293445283 4293644444 4293839020 4293773726 4293578666 4294101916 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284226632 4285208637 4285209408 4285603400 4285534780 4285468987 4285471294 4285467448 4285731904 4286260554 4287970639 4288431954 4288297553 4289084494 4290666593 4291389547 4292771180 4292247931 4293101167 4292908941 4293632385 4293566595 4293370485 4293501319 4293698937 4293699453 4293699451 4293566336 4293367164 4293166442 4292966514 4291322460 4290200910 4287179337 4287109190 4287310667 4289748342 4291135134 4288364128 4289808987 4289421439 4286200680 4283897143 4284292208 4286657107 4289300899 4287118439 4284027196 4284029516 4283501915 4284886620 4287387534 4285211470 4284554862 4283239743 4284358510 4287981485 4290623162 4289170095 4287186069 4284490857 4289566903 4287194018 4288313771 4286729604 4285939576 4285019249 4286670249 4288247975 4288841130 4288178601 4288107626 4286853739 4288311974 4287972723 4289491091 4290857295 4292065986 4292848810 4292309111 4292975745 4294429841 4286324029 4283240779 4284030026 4284096336 4284751687 4284029764 4284555083 4285078339 4285539919 4285865538 4285407050 4283765815 4284486454 4286193740 4284093768 4285079628 4284687175 4284816970 4285669447 4286521922 4285339196 4285406013 4286128200 4286063688 4285800003 4284751172 4285668680 4286593104 4285735496 4287447634 4285866055 4286389828 4287574858 4289407814 4288886092 4289478216 4290660168 4290397513 4291251536 4290462784 4291319130 4291777877 4291451998 4291910241 4292240996 4292042600 4292108902 4292110457 4292571491 4292964455 4292506983 4292507239 4292309111 4292570235 4292109666 4292636284 4292108646 4292108902 4292700521 4292108903 4292306790 4292374139 4292438119 4291256682 4291188573 4291125342 4291650422 4291979105 4292243574 4292378744 4292773758 4292509830 4292442228 4292439154 4292441223 4291720813 4286123580 4287509326 4284814658 4284157515 4284095303 4284095047 4284158269 4284751175 4285276743 4285012549 4285609291 4285933130 4285275200 4284947783 4285801034 4285077828 4285599292 4288632177 4287444299 4287573577 4287577928 4287708504 4286720840 4286389319 4286260298 4287907665 4285799751 4285867340 4285143365 4285936472 4291660948 4292518544 4291788139 4292708735 4292314736 4291919981 4292250747 4291464063 4291922557 4291529599 4291528065 4291990156 4291528320 4291595388 4291595143 4291593855 4291595655 4291593845 4291595399 4291529596 4291660934 4290939261 4291856246 4291070598 4290938756 4291004548 4290807425 4290676350 4290545010 4290739066 4290347903 4290804859 4290807923 4290145910 4289819246 4289622397 4289421661 4289880942 4292516981 4293904539 4294037665 4294038704 4294038703 4294037919 4294037431 4293513886 4294103728 4293578651 4294168489 4293709737 4294103733 4294037929 4294038197 4294102965 4293512613 4294167196 4294101918 4293839264 4293379746 4293840036 4293578653 4294167454 4294102943 4294167208 4293578650 4294168235 4293513629 4294037163 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285276230 4284552765 4285079111 4285471556 4285142327 4285996358 4285602367 4284945468 4285795389 4286523979 4289682276 4289087054 4288890969 4289482341 4291189595 4292111720 4292244584 4292509807 4293037170 4293694843 4293565817 4293566851 4293567111 4293763701 4293500804 4293501316 4293503114 4293566335 4293630082 4292970357 4292903262 4292109406 4290202450 4287769673 4287043653 4287374411 4289618823 4290347676 4289280079 4289412717 4287512164 4286330456 4285410154 4284422725 4286134620 4288574627 4285274431 4284620873 4283963724 4283107656 4284821343 4286269560 4283636547 4286002527 4283831383 4283633481 4288779701 4290159276 4288182198 4288841635 4285673594 4286408859 4289497269 4288379554 4287650465 4286797194 4288577460 4287517045 4284822902 4288378026 4289034403 4287579001 4284425551 4288970677 4288443544 4287980701 4288960124 4292649642 4292133828 4293763456 4294565274 4289022033 4283308618 4283834447 4284226628 4284488771 4284423496 4284489030 4284488002 4285473611 4285473357 4285996608 4285081167 4284226367 4284751175 4285474379 4284947779 4285407049 4284554309 4285079371 4285474379 4285276235 4285669961 4285801026 4286062664 4286063688 4286130249 4285404733 4284945982 4286129992 4285930311 4287575887 4285933385 4285602634 4286788685 4287837258 4289411148 4289084748 4289478226 4290594376 4290332499 4290596956 4291578967 4291320418 4291648607 4292567403 4291649632 4292042600 4292373094 4292108644 4292832122 4292375158 4292110966 4292962921 4292897639 4292307810 4292440441 4292373347 4292439140 4292440696 4292044149 4292242295 4292965480 4292508009 4292507750 4292966275 4292969350 4293033108 4293033335 4292837242 4292838777 4292836998 4292643458 4292967303 4292373360 4292508026 4292050033 4290073176 4283891767 4287181134 4284554306 4284225100 4283634232 4284225866 4284094524 4285014086 4284619845 4285276745 4285208893 4285147218 4284750143 4285274944 4285205812 4285273669 4284878658 4288892502 4287444298 4287574604 4287577167 4287642954 4286656073 4286390855 4286194246 4287840082 4286588999 4285795132 4285078343 4285080912 4291201665 4292515982 4292312931 4292252288 4292248440 4291658601 4291464321 4291528056 4291858055 4291726709 4291726956 4291528056 4291594103 4291659393 4291464307 4291594113 4291594111 4291594113 4291594102 4291659649 4291659645 4290939526 4291461498 4290873219 4290938740 4291396212 4290151294 4291004288 4290347137 4290413166 4290676355 4290345593 4290673529 4290279801 4289752941 4289097329 4289094771 4289751653 4292777832 4293904538 4294038693 4294038702 4293972910 4293973168 4294037931 4294103714 4294037161 4293711034 4294038198 4294103734 4294038701 4294038200 4294102953 4293513372 4294233504 4293579168 4293643932 4293643943 4293774241 4294102687 4294101673 4293579167 4293578151 4293579948 4293773994 4294037932 4294036907 4294037151 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284816713 4285012804 4285602628 4284816196 4285339973 4285205316 4285074491 4285076286 4284944959 4288231759 4289087318 4289876831 4288824909 4290007141 4291124577 4291455339 4292312172 4292573804 4292904834 4293301114 4293238151 4292977020 4293565820 4293501575 4293764729 4293500802 4293567108 4293566591 4293563009 4293233268 4292507999 4291455078 4290854727 4287640136 4287046994 4287374926 4289611611 4290674585 4289480299 4288501355 4287581039 4286986852 4285538888 4287185522 4285346395 4287121770 4284028488 4284619598 4283569742 4283107400 4285348196 4286926980 4284028483 4285476454 4284554602 4283898715 4287460257 4290553019 4287463081 4287120251 4288775350 4286332284 4289309120 4288378283 4287453841 4287456912 4287521933 4284950381 4286072967 4287065761 4290082712 4289742931 4284486233 4287721359 4287451258 4289360293 4290668163 4292988870 4293906873 4294693532 4292116324 4284618310 4283698763 4284028492 4284161091 4284622416 4284421447 4284226114 4284488255 4285669190 4285734471 4284882504 4285604939 4284222532 4284095042 4285736528 4284943920 4284882500 4285209926 4284029507 4284881471 4285277257 4285867082 4285801035 4286128712 4286063688 4286129224 4285339711 4284748082 4286260042 4285668674 4285932615 4286067277 4284882248 4286457159 4287703367 4287244874 4289543242 4289083208 4290069836 4290594376 4290987078 4290989909 4291907162 4292042340 4291715426 4292237917 4292370279 4292175994 4291979880 4292440696 4292174945 4292832122 4292505956 4292702330 4292767609 4292572516 4292702074 4292701816 4292508005 4292768632 4292507749 4292838284 4292574837 4293101969 4293429132 4292974480 4293366138 4293166467 4293231764 4293034352 4292970378 4292707452 4292311669 4292443515 4292640379 4291982439 4285993538 4284747581 4287379534 4284029506 4284091206 4283831871 4284620360 4284096070 4284750917 4284553796 4285868875 4285013576 4286523720 4284355901 4285866571 4285076024 4285012293 4285468989 4289616225 4287510349 4287573576 4287510855 4287575119 4287837260 4286129735 4287311689 4287773009 4286458699 4284681784 4285670216 4285536323 4291400851 4292451486 4292249974 4292711560 4291917659 4291462775 4291989376 4291529333 4291923326 4291529086 4291531140 4291594885 4291726212 4290940810 4290939013 4291725184 4291659647 4291068541 4291725185 4290873973 4291266447 4291790718 4290219390 4291135878 4290741375 4290939012 4291264634 4290479233 4291004273 4290348423 4290410871 4290871163 4290083435 4289819512 4289031296 4289228656 4289226114 4289159265 4292387716 4293904279 4294037665 4293973177 4294170798 4294170787 4294038705 4293514403 4294038177 4294038189 4294038177 4293513127 4294103715 4294037406 4293513385 4294168749 4293512602 4293839530 4293578406 4293774764 4294168748 4293513374 4294103458 4293708451 4294102688 4294036381 4294036637 4294036381 4294036638 4294036382 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284684606 4284488774 4284551741 4285601090 4284881731 4284947524 4284816450 4284881732 4285996361 4288168011 4289939532 4288825953 4289742680 4289807701 4291258213 4291782248 4292770157 4292115814 4293101425 4293235330 4293632127 4293632387 4293566850 4293566079 4293565824 4293567365 4293566593 4293566591 4293627266 4292970359 4292902496 4292108635 4290332501 4288231500 4287571014 4287571779 4286987353 4290013843 4289813114 4289287278 4287050846 4285739354 4285869153 4288043394 4286858865 4286659687 4284620615 4283962446 4283632715 4283501643 4286006125 4286857840 4283108167 4285212240 4285408599 4283960667 4286799507 4288905373 4286732681 4286338457 4288047513 4287255699 4287264922 4288908473 4287321742 4287981723 4286597764 4285873768 4285675904 4285611371 4288446635 4291645816 4291118948 4289101220 4285477729 4288045967 4288757592 4292583048 4294497977 4291137396 4283959615 4284228172 4283570767 4284621900 4284425036 4285015375 4284620614 4284818510 4284881738 4285143102 4285866571 4285932354 4284947524 4284029245 4284488259 4286064203 4284487742 4285536836 4286062660 4284619070 4284289599 4284746549 4285933389 4285406789 4285340731 4286128713 4286131020 4285470013 4285142073 4285603658 4286130248 4285996616 4286657615 4285339195 4285997129 4287311687 4286520647 4288095303 4288821837 4289152334 4289543505 4290004815 4291316553 4290595153 4291841371 4291847005 4292436076 4291781733 4292044899 4292306792 4292702564 4292440440 4292309110 4292570979 4292506981 4292375671 4292311419 4292900968 4292967802 4292837767 4292575351 4292640890 4292769892 4293102487 4293168264 4293301388 4293302411 4293302671 4292972687 4293034366 4293033873 4292576647 4292707449 4292379030 4292508277 4292117354 4289813352 4283498540 4285076542 4286196556 4284224322 4283635272 4284291397 4284030543 4283831620 4285079111 4285278289 4285472323 4286330190 4284881735 4285141558 4285996356 4284422463 4285340484 4285995327 4288831842 4288231755 4286918733 4288431705 4286985037 4287181385 4286784839 4287115596 4287773009 4286392138 4286061384 4286193221 4284619079 4291595660 4292452756 4292249717 4292712333 4291655008 4291331970 4291593848 4291334268 4291922303 4291334521 4291593344 4291662217 4290939013 4291724925 4291792006 4290939254 4290939270 4291790718 4290873990 4291724929 4291137398 4291790721 4290938741 4291070327 4291136134 4291069826 4290282621 4290216577 4290410874 4290870639 4290413696 4290476922 4290345592 4290016889 4289622637 4289227878 4288634736 4290011755 4292912773 4293707934 4294038948 4293972921 4293972910 4293972901 4294037922 4294037409 4294037420 4294037419 4294038434 4294102442 4293512602 4294103213 4293513372 4294036648 4294103212 4293513385 4294103201 4294103201 4293513385 4294103470 4294036381 4294036638 4294036382 4294036639 4294036639 4294036639 4293838489 4294036896 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284878650 4284880184 4285272639 4284749111 4285013067 4285076548 4284684348 4284554823 4286126144 4287903824 4289679968 4289742422 4288629333 4290531418 4290994789 4292438373 4291654246 4292576886 4293036161 4293498234 4293632128 4293238649 4293237638 4293041787 4293370743 4293566594 4293501574 4293567107 4293562229 4293560952 4292835420 4292108893 4290201419 4288229961 4286978630 4287442769 4288952657 4289090157 4288433254 4289285742 4287316853 4286525781 4285938279 4286989156 4287320434 4285675114 4284687193 4284161360 4283568971 4282976587 4286532715 4286855806 4283307332 4283503687 4285867874 4285606768 4286731125 4288642982 4286730132 4285875847 4287652238 4287919525 4287651232 4288511662 4287917731 4288116647 4287982245 4287324069 4285217899 4285345900 4289169333 4289223045 4293282386 4290151341 4284820051 4286928264 4288370048 4290278786 4292334541 4285015359 4283505223 4285276745 4283962947 4284552519 4284684618 4284357446 4284293195 4284357704 4284616502 4285604936 4285804366 4285864514 4285078336 4284027453 4284814921 4286064203 4284618301 4284357445 4286128708 4285140798 4284552503 4284817485 4285601083 4286324810 4285798723 4285668162 4286194249 4285407303 4285535806 4285471805 4286129481 4285668931 4286259266 4285798724 4285012547 4287510606 4286850631 4285533506 4287110984 4289016905 4289150287 4289609800 4290461519 4290397511 4291055177 4291384668 4292106838 4292373354 4292373096 4292108903 4291914345 4292438886 4292964708 4292505482 4292768628 4292375413 4292768374 4292639866 4292771191 4293034131 4293299588 4292708235 4292903577 4292970121 4293367934 4292975781 4293365629 4293301135 4293367695 4292774295 4293497228 4292644745 4292510857 4292770422 4292247689 4292577389 4287179591 4284024906 4285276229 4287047240 4283569224 4284290378 4284028485 4284029500 4284818254 4285146444 4285998153 4285406532 4286261321 4284551734 4286326347 4285671240 4285010232 4285928256 4285603650 4289550442 4287445078 4287574859 4287644763 4287706960 4286653513 4286654534 4287771724 4287772495 4285866820 4286589256 4285536856 4285537868 4291530637 4292321690 4292117870 4292843661 4290932332 4291856249 4291528322 4291728252 4291923060 4291530895 4291398514 4291660678 4290807410 4291726726 4290742145 4291593341 4291659647 4291331464 4291528059 4291790720 4290153595 4291135878 4290807674 4291921792 4290545027 4290676354 4290544769 4290675834 4290084991 4290476409 4290348157 4289951863 4290411128 4290016888 4289819002 4289227894 4288635240 4289687918 4292981908 4293840803 4294038704 4294236332 4293972912 4294038693 4294038180 4294038180 4294038180 4293513374 4294037422 4294036891 4294037676 4294037417 4294038189 4294038189 4294037676 4294036894 4294037666 4294037923 4294036381 4294036381 4294036639 4294036639 4294036639 4294036896 4293838489 4294036896 4293904539 4293772181 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284748607 4284554309 4284422980 4285077566 4284684604 4284552516 4284358474 4284355138 4286456647 4288757838 4288957520 4289810013 4288890710 4289019732 4291520351 4291914601 4292768618 4292509550 4292906109 4293300864 4293238149 4293042041 4293632388 4293436280 4293566852 4293500545 4293763699 4293500798 4293563773 4293299578 4292900972 4291454300 4290069583 4288293958 4286979399 4287509841 4288362055 4289288575 4287581811 4290338419 4286193222 4285082715 4285805425 4284291401 4288834701 4285280858 4284291914 4285081162 4284029004 4283305276 4286793076 4286463864 4283436091 4285146206 4284161876 4286199684 4287517575 4287328145 4287127954 4284553539 4284948337 4284754778 4288049320 4288049316 4288447926 4288773045 4287984292 4288113561 4287584417 4285017703 4289039782 4288766359 4291183467 4291270831 4287449457 4285017180 4288502902 4289089893 4293316275 4284617559 4286859098 4284686931 4283569234 4284163148 4284293708 4284883790 4284225856 4284884046 4284617786 4285871454 4286128709 4285669960 4284161610 4284222781 4285603395 4285736265 4284618814 4284551996 4284882245 4285342282 4284028231 4285011254 4284487999 4285078076 4285406278 4286194505 4285669186 4286259018 4285472061 4284881213 4286194249 4285734467 4286064456 4286129481 4285141819 4286983754 4287377486 4285926979 4285470016 4286716743 4288031303 4288754250 4289086799 4289544783 4290987335 4291384148 4291452511 4292303460 4292171877 4292175207 4292175993 4292240997 4292176758 4292374385 4292575114 4292377977 4292572771 4292903305 4292576636 4293036671 4292973203 4293039521 4293431157 4293167768 4292971919 4293366646 4292972951 4292971896 4293366413 4293366667 4292973454 4292644488 4292574859 4292573542 4292708226 4291589230 4284745528 4283632958 4287050063 4284619588 4283503431 4284554572 4284426063 4283765836 4284818252 4284555340 4285540172 4285408077 4285931331 4284615736 4286132558 4285143101 4285077566 4285340999 4286915400 4288767849 4288299089 4287377746 4288301388 4287051601 4287178568 4287181903 4286591051 4287179596 4286522180 4287051350 4284683074 4284942395 4291599772 4292255132 4292511864 4292382080 4291001196 4291659908 4291529598 4291728251 4291529087 4291857512 4291595144 4291528834 4290939527 4291725182 4291070340 4290939525 4291921791 4290022009 4291004290 4291005063 4291987061 4290939526 4291921791 4290873220 4290938224 4290676356 4291132791 4290413950 4290019195 4290348157 4290150512 4290410871 4290214008 4289885048 4289493105 4288638057 4289159028 4290475900 4293835924 4294102944 4293974194 4293973936 4294038435 4294038694 4294037409 4294036639 4294037666 4294036640 4294038434 4293513141 4294038443 4294037417 4294038189 4294038177 4294037409 4294037923 4294036382 4294036639 4294036639 4294036639 4294036896 4293838491 4294102689 4293838489 4294102690 4293904539 4293970845 4293838489 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284748349 4284552516 4284949065 4284882504 4284420426 4284420667 4285079371 4284357187 4286195278 4287640654 4288298576 4288890445 4289545552 4290201173 4291125856 4292112992 4292177767 4292707184 4293232500 4293301638 4293238919 4293631616 4293370228 4293370230 4293566078 4293566073 4293502602 4293565562 4293563767 4293298034 4292835424 4292241235 4290267731 4287639625 4287634502 4287574357 4287249230 4289088342 4289485937 4286590559 4285146456 4285670757 4285146703 4284553802 4289104296 4285342801 4284096589 4284752985 4284226374 4283701340 4285545570 4286462833 4283174730 4285147739 4283568727 4285412210 4287587481 4288508810 4286865038 4285080423 4284294722 4284225889 4285609851 4286865045 4288446631 4288511915 4286929052 4288642997 4287593393 4287125919 4288179609 4289757095 4291193227 4290873252 4290659407 4287385219 4286597989 4287315807 4284425792 4284950090 4287053660 4283899209 4284228683 4284554825 4286391625 4284291911 4284356928 4284294993 4284161096 4286259014 4286063688 4286195017 4285208892 4284226630 4284684607 4286327628 4284618044 4284555854 4284945717 4286457675 4285010223 4284224333 4285797696 4284226373 4286129996 4285735499 4285798467 4285405757 4285865028 4285538376 4286195273 4285734210 4286129996 4286129736 4285143875 4286458699 4287508810 4285406787 4285467705 4285073464 4286453832 4287046472 4288886090 4289671241 4289740109 4290921542 4291514969 4291714144 4291979368 4291780192 4291913322 4292570725 4292176760 4292964455 4292309624 4292640103 4292115851 4292704887 4292771975 4293296759 4293236375 4292711318 4292974481 4293299596 4293302669 4293299597 4293299852 4293365133 4292974749 4292976026 4293042308 4292904589 4292376952 4292118133 4291988604 4290464856 4284353591 4284551751 4286916679 4284423754 4284162636 4284687694 4284095821 4284161870 4284817995 4284620876 4285669958 4286263373 4285143616 4284615992 4286062660 4284749373 4284816453 4285864259 4286062404 4288831589 4288035928 4287444044 4288237421 4287115595 4287113033 4287707473 4287116107 4287835981 4285998909 4286918477 4286195269 4285008203 4291270281 4292912016 4292250238 4292384652 4291590760 4291199860 4291594106 4291660412 4291267978 4290941843 4291529586 4291004791 4291593598 4291199355 4290939525 4291921789 4290088330 4292118142 4290284939 4291069553 4290219404 4291395707 4290676607 4290873216 4290284417 4290807172 4290022010 4290739076 4290085247 4290804342 4290150784 4289822592 4290148469 4289557631 4289294448 4289291113 4288505464 4290541423 4293115033 4294104229 4294170540 4293973948 4294038436 4294037923 4294037409 4294037666 4294036896 4294037666 4294037409 4294037407 4294037429 4294038188 4294038188 4294037420 4294037665 4294037153 4294036639 4293838747 4293838489 4294102689 4293838748 4293904007 4293772440 4293970848 4293837956 4293772695 4293048462 4293505670 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284358730 4284614211 4284751686 4285211212 4284161090 4284488267 4284224567 4284486455 4285798978 4286723407 4288494159 4289087323 4288759382 4290927190 4291716962 4291914601 4292638828 4292641135 4293234295 4292908926 4293303669 4293566852 4293631872 4293566080 4293566847 4293501059 4293764472 4293501316 4293565053 4293496687 4292834909 4291849050 4290135119 4287900742 4286588999 4287179590 4288034122 4288957034 4289944438 4284093768 4284424007 4284752712 4283763544 4284756059 4288770445 4287055205 4283698259 4285475413 4285870443 4283567930 4286004846 4285673308 4283700554 4284620093 4283831387 4283566157 4288113051 4288905139 4288776108 4285869938 4283897174 4286132080 4285281897 4286337161 4287585953 4287916196 4288182182 4288447149 4288905656 4286995100 4287652246 4288701598 4290478241 4290020516 4286989689 4289218415 4287255136 4288174438 4283766858 4286722131 4283965516 4284032334 4284027980 4284292172 4284686924 4284425037 4284094795 4284225856 4285012032 4286195016 4286061639 4286064456 4285012292 4283765815 4285077821 4286985551 4283961667 4284423496 4284554310 4285867592 4284554568 4284552246 4284423238 4284945207 4284225859 4285932363 4286195273 4285405244 4285933389 4284420405 4285930563 4285539913 4285733952 4286197580 4285404731 4285802056 4286196810 4287706188 4284813879 4285076539 4284156978 4286583109 4287176777 4287836490 4289212489 4290070348 4291316041 4291125081 4291975264 4291583326 4291584873 4291781495 4292701796 4292307832 4292703846 4292376955 4292833657 4292510570 4292901767 4292575094 4293101453 4292972167 4292840583 4293299599 4293369737 4292972960 4293366920 4292973710 4292973452 4293039764 4293103245 4292512142 4292244613 4292707195 4291194735 4289608783 4283761470 4284224073 4286522950 4284095560 4284098385 4285014859 4284557136 4283901005 4284424267 4284620876 4286260550 4286329681 4284943416 4285473349 4284750148 4286127684 4285403968 4285077570 4287245130 4289554028 4288035928 4287441992 4288367961 4286458954 4287179077 4287641680 4287050062 4287771980 4286127431 4288101706 4285011025 4283960909 4292446851 4292387485 4292250227 4292843404 4291002480 4291331199 4291791216 4291004808 4291791997 4290939005 4291790721 4290807941 4291133048 4290219660 4291921790 4290807681 4291593351 4290219388 4291069569 4290938754 4291593351 4290219388 4291201670 4291069812 4290544258 4290610544 4290673541 4290085246 4290673528 4289951095 4290410871 4290476662 4289754503 4289622378 4289162882 4289291377 4288438121 4291726209 4293839005 4294038435 4294170554 4294172079 4293972901 4294038180 4294037666 4294036896 4294037666 4294037666 4294037409 4294038179 4294038190 4294038177 4294037420 4294037665 4294036382 4294036382 4294036897 4293837957 4294102946 4293706646 4293838232 4293706645 4293376649 4293507980 4293506441 4293500292 4293299297 4291455309 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285012799 4284620356 4284420413 4284355133 4284814141 4284680260 4284029757 4284621390 4285405507 4286391367 4288100174 4288300876 4289676882 4290271586 4291324779 4292108638 4292640367 4292641132 4292970368 4293761152 4293238407 4293631353 4292843142 4293632385 4293566850 4293567108 4293501573 4293566336 4293563766 4293429624 4293164652 4292109407 4289676622 4286917196 4286389843 4286129476 4287112778 4290278273 4286327625 4284619843 4284617290 4284029254 4285543775 4286333048 4286855510 4287184497 4284028998 4284884301 4286132049 4284620874 4286330983 4285280874 4283699780 4284029796 4284161861 4282778195 4287389319 4289303220 4287985824 4287651214 4284027465 4286334078 4285675902 4286531963 4287718559 4286334335 4288180136 4287848859 4288517295 4288645566 4288974008 4287191964 4288970156 4290940071 4292062647 4284882517 4285872750 4287515236 4287649392 4283702088 4283439952 4284361298 4284226370 4284360271 4284817996 4284620361 4284292934 4284490573 4284622161 4286063942 4285868618 4287247181 4284358732 4283831360 4285537347 4286196043 4284815678 4284751174 4285276230 4285012805 4285146959 4284618301 4285341256 4285013573 4284881728 4285405507 4285867596 4285275714 4285409102 4285999436 4284816197 4286259271 4285736011 4285145931 4285274947 4286063432 4287443274 4287310919 4286457674 4285339198 4285142585 4285336377 4285273143 4286716232 4287508813 4288229961 4289805386 4289413701 4290134858 4291120206 4290928217 4291582562 4291388262 4291256691 4291848030 4292439935 4292505444 4292442489 4292114053 4292772214 4292771716 4292967826 4293037194 4293432695 4292971428 4293369211 4293037968 4292512390 4293364615 4292709237 4292904848 4292378484 4292377993 4291853424 4291326062 4289807956 4283895113 4284358467 4285407836 4284230480 4284293707 4284885603 4284032334 4284819024 4284949582 4284425039 4285673033 4286328652 4284752459 4285869131 4285143356 4284882245 4285472067 4285078603 4287246922 4288765020 4287906385 4287510862 4287514199 4287772234 4286526027 4287577944 4288166224 4287574603 4286656075 4287316058 4286063185 4284748857 4291139482 4292448647 4292708729 4292119681 4291067769 4290871411 4290540151 4290282866 4291264882 4291462260 4291199354 4291462002 4290873733 4291330684 4290938754 4290481289 4290938753 4291330428 4291136133 4291004290 4290676095 4291790204 4291001990 4290284410 4290544769 4290084221 4290676353 4290541944 4289429887 4290282368 4290213495 4290082680 4290214007 4289427569 4289227620 4288702329 4288899440 4292386417 4293641630 4294038434 4294170543 4294170543 4293973157 4294038180 4294036896 4294036896 4294037666 4294037666 4294037409 4294038180 4294038179 4294038180 4294037665 4294037153 4294036382 4294036896 4293706388 4294168741 4293772695 4294034827 4293575057 4293440663 4293174379 4292841319 4291717190 4288956486 4286327112 4284421191 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284288836 4284288579 4284226885 4284619588 4284815938 4284224069 4284745532 4284096582 4284355644 4285996360 4287640140 4288629321 4289874785 4289743190 4291256419 4291783782 4292246122 4292839299 4293234299 4293234304 4293237632 4293631354 4293302910 4293172358 4293631612 4293567366 4293566594 4293565818 4293563261 4293298040 4292965727 4291453015 4289873488 4287113286 4285076544 4286129222 4290080670 4289553555 4286657869 4288572059 4284026682 4282912337 4286000729 4288307848 4285344078 4286199391 4284948550 4285672544 4285015144 4285541971 4286001502 4285212242 4284158792 4284029771 4284555102 4283040336 4284957305 4290092732 4288315056 4287784078 4284947798 4285608043 4286333811 4284818540 4286990697 4288047773 4287591081 4285939069 4287325065 4288712623 4287058071 4288247216 4288444078 4289501103 4291072935 4288704682 4289628602 4288768149 4290804871 4284820047 4283175759 4283369796 4283966031 4284029007 4284292936 4284425037 4284685898 4284096073 4285799750 4287047497 4286394445 4286851143 4284025667 4284290373 4285276745 4286264909 4284554054 4284292425 4284488003 4285734982 4285866824 4284683837 4284160062 4285339710 4284289342 4284487742 4285471810 4285341517 4286260295 4285734210 4285405766 4286131787 4286129479 4286195528 4285209411 4285472841 4287049290 4286656330 4287902537 4286324552 4285996103 4286258752 4285535552 4286914632 4285930053 4287046214 4287307846 4286651972 4287046212 4287179592 4288821835 4289019210 4289024085 4290139754 4290863218 4291124314 4291784043 4291980407 4292508273 4292115333 4292706678 4292245873 4292968578 4292710799 4293037707 4293431183 4292969351 4292379499 4292574836 4292902279 4292314244 4292704119 4291852397 4290996843 4291977806 4288689993 4283371316 4284487239 4284750654 4284424268 4284752718 4284096072 4284295761 4284949069 4284884046 4284620620 4286000975 4285079111 4285078083 4285735502 4284554567 4284618301 4285275977 4285670986 4286655049 4289221737 4288039013 4287513173 4287578713 4287576910 4287179849 4287643480 4287513423 4287575883 4287244873 4287248973 4285864771 4285408340 4291469467 4292447622 4292316544 4291725687 4290541678 4290405995 4289292658 4290473066 4291000698 4290936952 4290477176 4291068283 4290873209 4291001976 4290742147 4290284423 4291201669 4291070597 4291136133 4290938754 4291069826 4290807680 4290218873 4290938241 4291526774 4290021768 4290478461 4290936184 4289888127 4290082422 4290082934 4290082936 4290148215 4289228672 4289292915 4288700775 4288965501 4293111947 4294036122 4294038707 4294170788 4293972901 4294037923 4294037666 4294036896 4294037923 4294036896 4294037666 4294038437 4294037409 4294037666 4294036896 4294036382 4294036640 4294036897 4293904539 4293838233 4293509250 4293244567 4293638276 4293566582 4292249457 4290859589 4286850633 4285270075 4283633477 4283831869 4283633216 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284292419 4284355148 4285274165 4284358476 4284486200 4283961656 4284159308 4283962186 4284485181 4286127686 4287049804 4288694606 4288103247 4288693320 4291255127 4292046177 4292638572 4292970355 4292970870 4293302658 4293697145 4293238150 4292909707 4293696889 4293173115 4293238393 4293567622 4293566592 4293628798 4292970607 4292245350 4291451220 4289282892 4285666878 4285999711 4291071656 4293844411 4288759650 4289290373 4291399061 4283173701 4283306567 4284949084 4287053154 4285870944 4285012030 4286000733 4285408592 4284357956 4286526825 4284094538 4284423255 4284226373 4284030796 4284355930 4283500883 4284493670 4289174971 4288776111 4289566131 4286728593 4287061123 4286663038 4284684888 4285150572 4289165483 4288250539 4286860935 4285281381 4287391652 4286467725 4287789992 4289169333 4289765553 4289034919 4289296805 4289959847 4290949567 4290290102 4288442273 4283767871 4283572302 4283767375 4284162629 4284227665 4284554307 4284227143 4284818254 4284948294 4287445327 4286853451 4286656333 4284095298 4283699761 4285274940 4287050834 4284486458 4285473351 4284095044 4284618044 4285342793 4284357189 4285339709 4285078341 4284160318 4285929533 4284621387 4285273396 4285408592 4286195528 4285800514 4286194504 4285670987 4286195528 4285801027 4285405244 4285604934 4286785607 4288233043 4287771465 4286652999 4286782280 4285996871 4287050571 4287967322 4287249237 4287771219 4288364389 4289220698 4290071142 4289679472 4289613403 4289942383 4291124076 4291059297 4291386481 4291846513 4292174960 4292110211 4292574082 4292900996 4292511113 4292967824 4292968341 4293105291 4292710286 4292576913 4293230987 4292836250 4292707448 4292375168 4290537844 4290796906 4291259994 4290728028 4286655300 4284096334 4284356928 4284294480 4284687181 4284033875 4284100180 4284488525 4284951121 4284949582 4284225858 4285608787 4285605446 4285211985 4284947520 4285078852 4285011514 4284750148 4286719559 4286654538 4288829535 4288103772 4287511381 4287578199 4287643743 4286592084 4287116884 4287575119 4287642702 4286062661 4288034644 4285738065 4285800018 4292453259 4292319100 4292972929 4291526264 4289489783 4289290072 4289485915 4289289832 4290013014 4289883771 4290080107 4290275445 4290477176 4290805113 4290410872 4290673525 4290871420 4291199611 4290542456 4291461495 4290219145 4290610562 4291135363 4290478975 4290479232 4290938508 4289955702 4290019708 4290279554 4290082678 4289558663 4290410871 4288441973 4289556848 4288636776 4289159286 4290541178 4292852356 4294167968 4293973158 4294170790 4293973158 4294038438 4294036896 4294037153 4294036896 4294037923 4294037153 4294036127 4294037153 4294036382 4294036640 4294036640 4294034831 4293771908 4293772180 4293246871 4293503362 4292713583 4292376922 4288958293 4286653763 4284027453 4284223802 4283828543 4283830585 4284550969 4284683070 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284552260 4284945461 4284227148 4284815420 4284027711 4284157247 4284486200 4283764285 4284813631 4285274940 4287836746 4287970897 4288035406 4288755786 4290464600 4291519841 4292704621 4292575597 4292972158 4292972406 4293236870 4293632383 4293629561 4293565815 4293632128 4293172359 4293565305 4293566850 4293365362 4293428330 4292507249 4291188049 4288228942 4287903326 4291472069 4294304451 4287181363 4286256230 4288566626 4289100447 4283370819 4283565640 4283765831 4286729071 4286068584 4284686416 4285343055 4284951383 4285146708 4286133089 4284489024 4284489028 4283766862 4283962426 4283504206 4283500113 4284229476 4288317874 4288441764 4289436078 4288310688 4285542757 4286071408 4285212775 4284553325 4286532466 4288645808 4286727550 4284820587 4287658162 4288380348 4285279078 4288448933 4289827251 4289235624 4287124374 4284227648 4288761706 4289370540 4289831609 4288177316 4284951129 4283107134 4283240010 4284028219 4284030286 4284621901 4284027200 4285603143 4287967823 4286788430 4286263377 4284222517 4283502406 4285211209 4286785094 4284161354 4284160579 4284619588 4284422980 4285209670 4285209404 4284486728 4284620358 4285733700 4284355652 4285078851 4284947270 4285406784 4285933387 4285211723 4285406789 4286194760 4285276229 4286326602 4285470276 4285142336 4286983240 4287638604 4287443788 4288163913 4287706187 4289611335 4290860903 4290466657 4290992485 4291127150 4291980153 4292307830 4291848554 4291853442 4291918979 4291522672 4290930545 4291457392 4291723132 4291523964 4292378759 4292443252 4292580223 4292709768 4292514431 4292513145 4292644984 4292841597 4292907651 4292515206 4292451223 4292845974 4292908938 4292516001 4292714641 4292126380 4292912552 4290746783 4289159282 4285739872 4284753232 4283439686 4284359502 4284951635 4284882502 4283901262 4284687181 4284556366 4284686925 4286064201 4285145159 4285802062 4284488003 4284489801 4285209927 4284880184 4286065742 4286326861 4288959072 4287907925 4287575884 4287581784 4287577173 4287180885 4287052878 4288168792 4288163414 4286063688 4286723402 4286392155 4286263895 4292716956 4292314733 4292448643 4291193459 4288632658 4289686894 4289220950 4289419871 4289551717 4289487979 4290012775 4290012514 4289947772 4290277739 4289948268 4289491578 4290671477 4290214776 4290739576 4290608248 4290805112 4291856254 4290610819 4290742148 4291002236 4290347372 4290807684 4290016373 4289953663 4290019440 4290082167 4288967538 4289688447 4288637814 4289422707 4288372070 4291334280 4293638806 4294104230 4294038694 4293973158 4294037667 4294035336 4294036384 4294036384 4294037153 4294036896 4294036384 4294036621 4294036384 4294036641 4294035850 4294037155 4293969801 4293639825 4292782727 4293042555 4292118395 4290795595 4286851656 4284943936 4283960388 4284027192 4283370816 4283830591 4285405503 4285405501 4286194505 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285078597 4285539148 4285144644 4285209926 4284552516 4284354885 4283764029 4284091977 4283960632 4285799493 4287311431 4287575375 4287508811 4287639882 4290531413 4291783785 4292245091 4293033848 4292839285 4293367430 4293238661 4293237119 4293632384 4293172614 4293563263 4293632127 4293566336 4293566849 4293431160 4292969327 4292175698 4290269291 4289285478 4292195525 4294892979 4286591030 4287455371 4285536835 4289100922 4288237412 4283898699 4284427091 4283433789 4286990445 4286661993 4285344340 4285999197 4285801806 4286397291 4284226116 4284357700 4286594423 4283962947 4283766370 4284292164 4284025939 4286334599 4289233576 4287851944 4288112789 4288714168 4287320967 4285871712 4285675115 4284488273 4284685649 4286597746 4285479805 4287453863 4289110208 4288316315 4285873287 4286532748 4288582837 4289437619 4288973229 4286594946 4283896123 4285801318 4290621347 4291475388 4290024640 4284688218 4282977355 4283241042 4283963467 4283964749 4284685636 4285537351 4287378764 4287249742 4286850374 4283372102 4283631938 4286131786 4286786637 4284420418 4284619588 4284683836 4285405756 4284358732 4285603139 4284291132 4284882763 4285274172 4284486724 4284686152 4284813877 4285408330 4284816708 4286326089 4285405243 4286196041 4285800003 4285076023 4285667648 4285076280 4286129222 4287115081 4288099659 4287641681 4289414227 4290467175 4290072160 4291322483 4291519838 4291585135 4291715937 4292175972 4292110954 4292310123 4292439138 4292505187 4291914603 4291852656 4292114300 4292176483 4292442232 4292375926 4292575113 4292509813 4292578939 4292575352 4292574596 4292576139 4292511101 4292316295 4292970624 4292641918 4292643723 4293169539 4293172881 4292783003 4293506473 4293247396 4293051570 4292395189 4290026664 4287060093 4284690004 4283111751 4284425037 4283965008 4284294221 4284490316 4284291911 4285538891 4285144644 4284685382 4284094523 4284225868 4285540171 4284225603 4286131017 4286783558 4287976288 4288171632 4286985556 4287646818 4287642452 4286526540 4287771469 4287447631 4288100682 4287116364 4287966795 4286260287 4286066766 4292649629 4292379244 4292448386 4289751913 4289546072 4290141786 4289485153 4289613409 4289614429 4289353300 4290076269 4289485925 4289553488 4289488758 4289550686 4289620849 4288899699 4290144377 4289622382 4289621870 4289688441 4290476664 4290936697 4290607990 4290673525 4290742156 4289950837 4290674042 4289953662 4289755526 4290082166 4289229936 4289162351 4289359729 4288569712 4288898417 4292385146 4293970330 4294038694 4294037923 4294038438 4294036382 4294036641 4294037412 4294035593 4294037154 4294037923 4294036382 4294036640 4294036640 4294036108 4293904544 4293838231 4293639566 4292850311 4292909187 4292645764 4290144596 4286788174 4285403707 4283502402 4284028226 4283699004 4284552764 4285009719 4286128963 4286985550 4286851401 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285472845 4285277001 4285539149 4285212746 4285013315 4284486973 4284553797 4283961662 4284023858 4285931077 4286390344 4287182156 4287050828 4287311691 4289089104 4292111972 4292309089 4292511350 4293234301 4293301894 4293694846 4293238662 4293695353 4293238406 4293632382 4293172357 4293566851 4293566330 4293495934 4292706152 4292572023 4290927719 4293116110 4293840033 4287246651 4285935703 4286652990 4284289869 4288505226 4284951122 4283240263 4283502149 4282978642 4286397279 4287450227 4286132559 4284488278 4285935442 4285739111 4284752971 4284881236 4286861953 4284292166 4285212240 4284423256 4284160062 4285608041 4288706472 4288839332 4287648920 4288840348 4289237176 4286136953 4284425043 4283171392 4284424032 4286733712 4288115375 4287855274 4289438900 4286073223 4286465164 4286404493 4287915404 4289565359 4287646079 4288773002 4287845010 4284157747 4288176258 4291336355 4290881443 4289894595 4284292693 4283439949 4283768393 4284161347 4285014603 4286128709 4286787148 4287969874 4284948294 4284093516 4284357447 4286526031 4286132554 4284160840 4284553538 4285145164 4284292424 4284555339 4285669452 4284357187 4284747580 4284488774 4284684349 4284618300 4284816714 4284292940 4286063179 4285801026 4285209411 4285799241 4286260809 4285275714 4284617527 4285078592 4285405763 4287181388 4287902798 4288691532 4290792021 4291187544 4291453794 4291584360 4291716713 4292109413 4291124833 4291520352 4291847520 4291584871 4291980647 4292308841 4291127406 4291914601 4291651944 4292572537 4292442232 4292379516 4292573797 4292575368 4292640647 4292378745 4292444537 4291919997 4292704869 4292444027 4292378230 4292577161 4292513659 4292384402 4292781454 4293110153 4292982177 4293573542 4293705126 4293640611 4294099366 4293841850 4291408052 4287522696 4284756833 4283442507 4284358732 4284489803 4284422979 4285209669 4285080395 4284553536 4284159053 4284357184 4284685391 4285143619 4286067032 4286656587 4287974224 4288893296 4287049799 4287051851 4287843944 4287246411 4287115603 4287512153 4288166989 4287115339 4286721107 4285607013 4287576667 4292978581 4292052586 4291921531 4290274655 4289421423 4289289580 4290800500 4289355884 4289615453 4289550696 4289483619 4289616986 4289617011 4289614937 4289617785 4289421412 4289419868 4288896867 4289159542 4289750642 4289555056 4289556336 4289425273 4290082425 4289820026 4289885046 4290017144 4290083192 4289951095 4290279798 4289624711 4290082167 4289162623 4288769141 4288701057 4288832622 4292911499 4294101640 4294037668 4294038953 4294036107 4293838750 4294036110 4294035851 4294036643 4294036382 4294036382 4294036639 4294036639 4294036640 4294100624 4293837700 4293574030 4292982936 4292849561 4292450436 4291131754 4287973204 4285799748 4284421701 4283894078 4284223294 4284552253 4285866563 4286392396 4287837516 4287706702 4287180875 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4286326854 4285867847 4286064969 4285408589 4285144649 4285733436 4284685896 4284290365 4283897418 4285535548 4285802057 4287376967 4287243847 4287443273 4289479503 4291123542 4292308844 4292114532 4293297520 4292972920 4293302918 4293301630 4292910205 4293105022 4293171334 4293630591 4293565817 4293564033 4293234553 4293099909 4292048263 4293183435 4292845682 4286587450 4285995330 4287645290 4284422752 4285741155 4291533978 4282844220 4283371857 4283372106 4283304762 4285936222 4288107891 4285933401 4284949586 4285475667 4285082711 4284816716 4284815957 4286926963 4287120229 4284882779 4284423739 4283831150 4285671509 4285481078 4288378529 4288906672 4286596721 4288509865 4289302198 4285411455 4284360041 4285478004 4287123344 4288379822 4289242036 4287985562 4284950383 4286206853 4286399618 4286072707 4287524513 4288906153 4286398569 4286531442 4286331517 4286268003 4289566888 4289030289 4289634718 4290026951 4283240007 4283699780 4283963469 4284949063 4286066786 4286853450 4287905102 4285341771 4284094777 4284027724 4285278026 4286722913 4285211979 4284489543 4284752717 4284421705 4284421691 4284554566 4285867598 4284752458 4284618301 4285209927 4285604940 4285538380 4284945719 4285014087 4285670216 4285935439 4285209151 4285866828 4284487742 4285932876 4285141815 4285602627 4287838288 4288493133 4288494414 4289810791 4291190366 4290928735 4291847268 4291914339 4291452515 4291649380 4291191141 4291978877 4291325038 4291387754 4291717489 4292243064 4291455610 4292636791 4292112999 4292440952 4292376185 4292379260 4292444539 4292050028 4292507256 4292507513 4292115056 4292112536 4292115561 4292245895 4292577139 4292841603 4293172881 4292715661 4293045149 4293049245 4292983728 4293310881 4293247649 4293378466 4293641140 4294102186 4293774524 4292197557 4288706954 4284955239 4283702343 4283835471 4284815938 4284163665 4285146962 4284029758 4284097354 4284357438 4285014860 4285605961 4287842401 4288237136 4288239212 4287050590 4287120728 4287774817 4286065225 4286592333 4288364111 4287510350 4287179847 4287379808 4286262873 4287709023 4292850334 4292445038 4292117365 4289616998 4289946726 4290998905 4290408028 4290408034 4289288546 4290013547 4290074983 4289485659 4289549661 4289616488 4289419611 4289484646 4289023585 4289093227 4288893024 4288239963 4289815397 4288762196 4289815415 4289092971 4289552990 4288505977 4289750907 4289621870 4290081148 4289098097 4289818221 4288638072 4289359983 4288704377 4288568682 4288832625 4292649600 4293904281 4294037154 4294038695 4294036643 4293838216 4294034830 4294036901 4294035850 4294036640 4294036639 4294036639 4294036639 4294036896 4293640083 4293180054 4293374864 4292981380 4293171840 4292117876 4288367438 4285995074 4284221241 4284288313 4284421688 4285472068 4286063688 4286852173 4287640395 4288166737 4287509581 4287050574 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288894820 4287580250 4286657606 4286392648 4285997127 4285799747 4284815683 4284553274 4285143101 4285669188 4287048264 4286982472 4285668680 4286783559 4288231502 4290925905 4291913815 4292640368 4292903549 4293300600 4293238143 4293235846 4293695102 4293170311 4293630329 4293565312 4293632126 4293630844 4293299071 4292773780 4293842602 4292908156 4288296529 4286978883 4286260046 4286722916 4285078078 4292057758 4288896872 4283500359 4283305279 4283372370 4283237959 4284357703 4287186547 4286592859 4283564854 4285146457 4284815691 4284621382 4284683882 4286861424 4288502164 4285868378 4285934703 4285343301 4284687192 4283435347 4285216103 4289170869 4288309669 4285018465 4288446632 4287986354 4289104056 4289233849 4287988406 4289634992 4288780219 4284752477 4286793348 4285675633 4287392931 4286794639 4286531702 4288183714 4287586217 4285014865 4287852710 4289296287 4290683828 4289161876 4285209412 4290099889 4288443050 4283241284 4283765069 4284948554 4286127173 4286851398 4288034124 4284355652 4283830864 4283831100 4285804368 4287247946 4284027720 4284751174 4284883016 4284619587 4284619588 4284880444 4285277002 4285143356 4285077562 4284554567 4284619845 4285012546 4285080142 4284682548 4285999180 4285407043 4285473358 4286194247 4285539143 4285538117 4284946494 4285798723 4286787401 4287904337 4289675340 4290990938 4291122778 4291387747 4291256412 4291518308 4291583844 4291388001 4291190625 4291583841 4291518566 4292372857 4292110437 4291654765 4292637047 4292636769 4292439927 4292572261 4292573544 4292376440 4292573288 4292702565 4291919747 4292178534 4292180076 4292115307 4292114543 4292444026 4292511347 4292844175 4292777865 4293108618 4293045662 4292654497 4293246634 4293115293 4293443248 4293641642 4292984215 4293575349 4293575589 4294166692 4294101682 4292394928 4289430944 4285477212 4283438404 4284027448 4284225597 4283567932 4283502916 4283303999 4284618813 4286194247 4287185499 4286919252 4289026917 4286523975 4287249230 4287117398 4286787658 4287180619 4288102224 4287575375 4286719557 4286987351 4284947264 4288436586 4293176984 4292116836 4291130991 4290275436 4289949797 4290607983 4290538610 4291129196 4290803823 4290341229 4290014046 4290012784 4290078050 4289486182 4289616226 4289681517 4288761687 4288959318 4289745503 4289220441 4287646551 4288499560 4289221460 4288567403 4289684067 4289421678 4288436325 4288568163 4288306531 4289880942 4288701547 4288700005 4288766071 4288764767 4287846769 4289355881 4292979335 4293839004 4294036881 4294035853 4293838219 4293904011 4293839009 4294035850 4294036641 4294036639 4294036640 4294036639 4294036639 4294036897 4293837700 4293114501 4292587405 4292973699 4290799698 4287904584 4285797446 4284091961 4284550451 4285534523 4286259018 4285933128 4286851658 4287574859 4288689998 4287379789 4288100432 4287449168 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288967042 4288965510 4288763502 4287382613 4287313230 4286328395 4285999177 4285668937 4285733955 4286521417 4286453317 4285865800 4286125638 4285405250 4286918217 4289807440 4290927184 4292704623 4292904556 4293694594 4293629824 4293234814 4293238918 4293628538 4293630330 4293236868 4292975505 4293239712 4293312942 4292979083 4292967264 4290860374 4289348178 4287573583 4285736531 4288499567 4289299358 4290281846 4284881486 4283239236 4283897414 4283895357 4283371334 4284354370 4284884829 4287907954 4285147216 4286401661 4283040561 4283698246 4284488003 4286132826 4288371586 4286200672 4286069105 4285341771 4286534016 4282909499 4283630666 4287658120 4289363363 4288441755 4284949078 4284226371 4285872482 4286992768 4288049042 4289307324 4286005358 4285609068 4285745277 4287651729 4285412975 4287721632 4287324825 4287060884 4288110986 4287058312 4288245414 4290092201 4291994024 4288501100 4286200697 4285740375 4290427568 4285608293 4283829045 4285341000 4285538888 4286916937 4287446355 4284944702 4283570754 4283963463 4286721612 4287052365 4284486973 4284881725 4285078340 4284354877 4284423754 4284553277 4285538115 4285144134 4284291652 4285602366 4284292682 4284552260 4284357187 4284949324 4285277259 4286325831 4285146187 4286127944 4285406010 4285473872 4285602621 4285272644 4286458701 4287444046 4288888905 4290334811 4291126370 4291060064 4290927197 4292172392 4291584100 4291388257 4291583843 4291583843 4291125861 4291845991 4291785602 4291980132 4291979367 4291915387 4292440181 4292767609 4292375413 4292441206 4292439410 4291916925 4292768612 4291982205 4292113776 4292507514 4292639337 4292314239 4292971399 4293169796 4292318097 4293110925 4293047713 4293046942 4292983197 4293309863 4293509540 4293245854 4293181869 4293969315 4293444264 4293705643 4293838242 4294233013 4294563508 4292329400 4289233313 4284097873 4283238457 4283632688 4283305548 4283370546 4285207356 4285013058 4288033610 4286921560 4289028713 4286652224 4286660696 4287904864 4286788429 4286654792 4287577681 4287769669 4286196813 4286456387 4285604433 4289483878 4292714124 4291919992 4291788151 4289882731 4290607471 4291000440 4290277227 4290999918 4291459437 4290078316 4291128934 4290014056 4289883247 4290144613 4289486702 4289549923 4289684335 4289811813 4287973971 4288957529 4288302421 4289351009 4288302677 4288628571 4288498782 4288435296 4288040783 4288040024 4288827238 4287646035 4289223284 4289027168 4287649118 4287384160 4287448416 4288107101 4292580228 4294164601 4294036367 4294036902 4294034299 4293837198 4293838216 4294036898 4294036639 4294036640 4294035850 4294036641 4293838746 4293904796 4293839258 4293439377 4292909932 4290669154 4287047237 4284549437 4284486712 4285141816 4285799493 4286589769 4285801799 4286982471 4287048006 4288103250 4287968845 4287378253 4287969616 4288559695 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289557901 4289166215 4289228668 4289620595 4287253858 4287576659 4287378773 4285735749 4285800518 4287509834 4286389319 4286061641 4285339708 4285667908 4287112519 4289283152 4291449429 4292639582 4293099643 4292973191 4293302398 4293302918 4293236869 4293631866 4293236870 4293302403 4292913039 4293634452 4293631617 4293363829 4292311414 4291978847 4289284180 4286521162 4289092472 4289421171 4293576633 4285273145 4283697984 4283634246 4283501894 4283437642 4283828546 4284094786 4283501641 4285672011 4288372874 4287387271 4282974250 4283239493 4284093533 4285671253 4288180371 4287842937 4286461791 4285872485 4286925703 4282974265 4283106371 4284290397 4288245408 4289104043 4289034924 4286466186 4286269294 4286198386 4286797182 4288511911 4283567428 4287062938 4287061660 4286664065 4287323802 4287056254 4287789216 4288114095 4287061921 4287519633 4287980196 4288242553 4290227901 4286525293 4286464613 4286001009 4286198360 4289831097 4283962437 4285538122 4285142592 4286982986 4287640652 4284291650 4283634503 4284025141 4286852688 4287115597 4284680501 4284488517 4285078083 4284354877 4284489546 4283960640 4285341512 4285473611 4285406791 4284226633 4284421691 4284291134 4285930044 4285211465 4285405760 4285868107 4285734463 4286592590 4286062408 4285799490 4285535806 4284552247 4285341256 4287706446 4288759115 4290530393 4291186512 4291124832 4291387227 4291649631 4291191137 4291385696 4291585654 4291518049 4291584360 4291518566 4291915115 4291586925 4293094504 4292373093 4292571237 4292505189 4292574057 4292439412 4292246152 4292178280 4292112746 4292113770 4292573307 4291852411 4292576881 4292904319 4292970885 4292713118 4293108616 4293044622 4293046927 4293047715 4292982429 4293377420 4292982174 4293509531 4293704870 4292984499 4293904036 4293444520 4293640108 4293838243 4293772194 4294431160 4294431927 4292066490 4286206320 4283240767 4283370566 4283435832 4284420678 4285671243 4286853963 4287708249 4288305259 4286066257 4287379285 4286789710 4286262860 4286785350 4287707474 4287114828 4286851912 4286393170 4285800275 4289292394 4292713098 4292051307 4291000694 4291066492 4290871160 4290476663 4290871418 4291393131 4290281587 4291130987 4290933109 4290081143 4290343799 4290341493 4289949036 4290015086 4289488501 4289549924 4289748079 4289484904 4289089631 4288367709 4288628829 4288628304 4288561996 4288105575 4287449688 4287513686 4287318373 4288629598 4289550164 4289616226 4288894802 4287512150 4286393157 4288496477 4292121208 4293442184 4294102950 4294035852 4293839009 4293838218 4294036110 4294036384 4294036639 4294036896 4293838490 4294102689 4293772696 4293772436 4293374356 4292780169 4291330660 4287638608 4283760689 4284354872 4286390852 4286459723 4286327885 4287443017 4286851657 4286591822 4288231758 4287967821 4287838288 4288625744 4287838031 4287970136 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289365127 4290082941 4289625486 4289362312 4288503916 4289485937 4287186781 4287837261 4286657878 4287248465 4286328393 4285996360 4285275205 4285339197 4286589256 4289414218 4291385940 4292704879 4292772717 4293169275 4293300102 4293236089 4293629825 4293630330 4293171590 4293627518 4293632126 4293564798 4293170552 4293560696 4292574044 4291977059 4289018965 4288037739 4290146711 4290478458 4292190622 4283170875 4283964486 4283633471 4283634756 4284028991 4283962703 4284156995 4283635015 4284687959 4287387766 4287320703 4282908720 4283370566 4283305283 4284881238 4289562276 4287187326 4285739112 4287390606 4286861426 4283896145 4283632972 4283436350 4285346401 4287587474 4287786381 4289760701 4287582353 4286599558 4289042876 4287191951 4285477752 4284488532 4288314278 4287258533 4287782009 4288177578 4285345634 4289044153 4288178599 4287787174 4288972963 4289618308 4289226356 4290029503 4285407305 4283829050 4288833941 4288775311 4288701319 4283829558 4285341259 4287048521 4286590029 4284880456 4283830599 4283368509 4286922320 4286526028 4284227404 4284685380 4285278031 4284749371 4284816967 4284026683 4285278031 4285013059 4285476429 4284817992 4284752976 4284553538 4284358733 4285406791 4284620616 4285407305 4285474388 4287180872 4285803082 4285603912 4285538375 4285077053 4286128968 4287051084 4289086820 4289414743 4290728539 4290530387 4291057499 4290929248 4291910245 4291518564 4291715426 4292242021 4291782504 4291059830 4291191913 4292833892 4292110969 4292638311 4292374135 4292574058 4292439414 4292048233 4292508282 4292111206 4292506744 4292509309 4292113256 4292444540 4292707200 4292642931 4293170300 4292778123 4293108362 4292717971 4293111201 4292653971 4293440924 4292981665 4293047184 4292982944 4293311395 4293049746 4293573544 4293838502 4293640351 4293838259 4293772450 4293838771 4294102454 4294562488 4293185464 4288710304 4283833165 4283041854 4284092725 4285998918 4285928004 4287249738 4288435814 4286193730 4287443787 4286263886 4286393161 4286719814 4287705932 4287179334 4286853965 4286587462 4285077826 4290081918 4293041037 4291854451 4290669938 4290871674 4291265146 4290742403 4291133302 4290739578 4291396722 4290608249 4290345592 4290411640 4290474612 4290672758 4289949559 4290603625 4290080620 4290079330 4289490037 4290142044 4289420655 4289880419 4288432731 4288368737 4287908451 4287318856 4287512652 4287512406 4287251785 4289092705 4290078827 4289357398 4289878373 4287316813 4286591052 4286853457 4292316788 4293971103 4294036108 4294035855 4294036112 4293838217 4294036641 4294037923 4294036639 4293838489 4294036897 4293904798 4293770368 4293242758 4293040995 4291456861 4287312714 4284486973 4284682034 4286063690 4286787657 4287838031 4287182414 4286589771 4287183184 4287641174 4287312975 4287905360 4288561232 4287182669 4288627536 4287314511 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289888390 4288838547 4289694092 4289690251 4289165703 4289358971 4289353840 4287187797 4287577943 4287643727 4286657358 4287046728 4284943925 4285466937 4286720840 4288823889 4291449684 4292310890 4292774259 4293561467 4293236613 4293235073 4293629050 4293170043 4293695609 4293173127 4293565056 4293565569 4293562494 4293560938 4292574833 4291059033 4290079868 4290674834 4290341251 4291463554 4288169816 4283240261 4283763525 4283766858 4284223804 4283567678 4284091205 4282911049 4287122311 4289029790 4288831900 4286661738 4283369024 4282581562 4284024917 4287520914 4289629617 4285736269 4285938535 4287845494 4284553814 4284228427 4283436089 4285343848 4287716486 4286527852 4284486720 4285876087 4287784601 4288714163 4286399595 4285080168 4285544536 4285939087 4284291684 4288052642 4288114604 4287652244 4286990206 4288115106 4289438902 4288177313 4289036451 4288109945 4288170600 4288641907 4290157772 4283302708 4283503693 4288631425 4290355874 4285211734 4284685127 4287245899 4285798719 4283963976 4283897150 4283962939 4287115852 4287050573 4285404479 4284948298 4284686924 4284424267 4285013061 4284096070 4284226370 4285538890 4285604939 4285151062 4284814652 4284751171 4284881214 4284949324 4285603140 4285079623 4286194246 4285673548 4288165967 4285538890 4285472579 4284160323 4285472583 4287838288 4287055180 4289676631 4291256672 4291123292 4291516258 4290992989 4291125345 4291716452 4291583586 4291650678 4290927962 4291191658 4292110953 4292440185 4292570724 4292573802 4292375674 4292572006 4292375673 4292636772 4292374392 4292504164 4292441207 4292378233 4292441467 4292575337 4292706942 4292644237 4292777619 4292778122 4293041802 4293110414 4292652436 4293507745 4293375112 4292980386 4293046170 4292853404 4293310119 4293311653 4293245345 4293510314 4293705901 4293838232 4293772467 4293904808 4293838515 4294036651 4294300089 4294235325 4290423473 4284885076 4283044428 4285668421 4284947524 4286067285 4288437358 4285735494 4286395471 4287052626 4286325830 4287379536 4287708238 4286719814 4286329165 4285471046 4285471563 4291725707 4292120441 4292179044 4290409335 4291790718 4291527024 4291199353 4291134077 4290545009 4291133305 4290870903 4290477176 4290934387 4290345092 4290606195 4290476420 4290409845 4290999427 4289425518 4289883772 4289422448 4289555569 4289619049 4289159790 4289484381 4289091940 4288501611 4288039777 4288103513 4288566116 4290336094 4290539351 4291455328 4290073169 4287972436 4286916434 4288233043 4292909954 4293902725 4294037156 4294036641 4294035853 4294035853 4294037925 4294037666 4294036384 4294036641 4294035852 4294035848 4292980125 4292446561 4290728783 4285994562 4284089911 4284681271 4286522954 4287246924 4287641682 4287574603 4287575374 4287640909 4287445081 4287904846 4288563537 4288626770 4287775567 4287969360 4287772237 4288559181 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289691021 4289164673 4289495443 4289627543 4289367955 4289887642 4289491817 4289356669 4287844708 4288235598 4287641168 4286917451 4285403451 4284682041 4286848585 4289085006 4291909967 4292114288 4292969342 4293300870 4293234309 4293630585 4293170817 4293695104 4293172098 4293630580 4293565819 4293566076 4293628023 4292839029 4292965227 4290991705 4291987631 4293312429 4287048784 4290277250 4285344068 4283175246 4283832391 4283831880 4283767117 4283435837 4283632706 4283238203 4283239228 4288106610 4288770960 4289694397 4289035448 4288437400 4289234599 4289430433 4286722649 4286131297 4285870443 4285280347 4286204018 4283236427 4284424051 4289165725 4286861436 4285078847 4284751473 4287129233 4288643239 4285936735 4285611127 4284424256 4285478783 4286137968 4286072187 4285478501 4287720865 4288640168 4288637601 4288648381 4289101480 4288644532 4288051874 4289364910 4284880957 4283959121 4287525511 4288180135 4282516537 4284951644 4289297546 4288641950 4283765311 4286260294 4285474134 4284360527 4283897421 4283767628 4287248728 4286525259 4284686410 4285736272 4284555852 4285536327 4284292424 4283897156 4284948317 4285014604 4285605451 4285014090 4285474896 4284423755 4284947528 4284160840 4286326599 4285408845 4285999178 4286325832 4287773266 4286391882 4284618306 4285671504 4285470786 4287642457 4289151067 4289483357 4291252825 4290992220 4291909976 4291124057 4292304232 4292109926 4291256161 4290994786 4290798439 4292043882 4292504678 4292571238 4292574058 4292376957 4292572006 4292572006 4292377469 4292174694 4292637028 4292045927 4292441207 4292572776 4292575596 4292706441 4292644729 4292841342 4292775810 4292778634 4293105296 4293045647 4293110157 4292653462 4293044895 4292980620 4292983970 4293373851 4293309334 4293309578 4293245850 4293573788 4293312165 4293838248 4293838234 4293772197 4294102959 4293838502 4294036661 4294102208 4294563260 4291278767 4284953180 4284092214 4284091460 4285146693 4288105816 4285341254 4286065226 4286524489 4285932103 4286194757 4287839058 4286653766 4287639623 4284879943 4285471306 4291401622 4292969328 4290999660 4290935153 4291529853 4291265405 4291133817 4291068540 4291462270 4291199601 4291002491 4290805111 4291068283 4290542453 4290608247 4290608759 4290669426 4290017912 4291063156 4290081385 4290146680 4290079597 4289554278 4289617780 4289750375 4288437596 4289224304 4288567651 4287839831 4288893778 4289813856 4292046175 4291130713 4289746770 4288563544 4287048778 4289811799 4293176193 4293838747 4294035850 4294037154 4294037153 4294037154 4294036896 4294037668 4294037134 4294037391 4294102690 4293576613 4292976230 4290074457 4286061634 4283897415 4284486460 4285930824 4287711058 4288100432 4288036173 4287443275 4287509066 4287377482 4288430159 4288823375 4289022298 4288234318 4288431695 4287838288 4288557130 4287708752 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289228163 4288969874 4289300620 4289630603 4290154147 4289500043 4290085524 4289032071 4289880680 4287779174 4288166989 4286785862 4285797954 4284419123 4285865539 4288954954 4291257699 4292770156 4292773752 4293106305 4293631103 4293566592 4293237376 4293237633 4293630580 4293171585 4293566852 4293566075 4293629047 4292904821 4292439908 4292116108 4293974726 4292713865 4287313492 4287513177 4287248489 4285212757 4283763785 4283699010 4284419906 4283895101 4283896383 4283961676 4283766079 4285410911 4284814925 4284226885 4286594648 4287850629 4287845509 4285737039 4285672290 4286401414 4284489046 4285146976 4285280621 4286794116 4289101984 4288046469 4284481593 4283763027 4285739362 4288582331 4285538893 4284161090 4285739887 4284489318 4284422501 4286400632 4287059852 4285742453 4287058826 4287589278 4288837539 4288774306 4288511416 4288511403 4289495470 4289044408 4286859133 4282384435 4285939048 4291151301 4286203780 4283368253 4286986328 4291740100 4284945990 4285668934 4284884045 4283634502 4283766087 4283634765 4286133833 4286852172 4285078855 4285471552 4284424010 4285080394 4285014861 4283636802 4284948295 4285537599 4285541455 4285212239 4284555341 4285407044 4284489547 4284422208 4286458189 4285472326 4286523466 4286721611 4288232782 4288035142 4285209926 4285599545 4284880969 4287840335 4287904601 4289482845 4291253843 4290992221 4291191390 4291781989 4291518820 4291714664 4290992732 4290796892 4292834169 4292111718 4292440441 4292373348 4292831609 4292375929 4292572261 4292375419 4292572263 4292636772 4292374390 4292441465 4292570210 4292574316 4292511090 4292838782 4292971400 4292710270 4293104002 4292711068 4292712585 4293108360 4292716177 4293108635 4292652433 4293438858 4292983446 4292980880 4292982416 4292982182 4293311640 4293574060 4293573776 4293640354 4293838247 4293970603 4293706415 4294102712 4294036662 4294036404 4294037935 4294694330 4292263609 4285806695 4283500084 4285144648 4287644242 4285012544 4285538120 4286130506 4285537610 4286920268 4287180875 4286852173 4286457415 4284483396 4285405759 4292252053 4292512885 4291132273 4290933353 4291528576 4291265403 4291528575 4290870905 4291462268 4291199610 4290411127 4291067769 4291068025 4290739330 4290348160 4290607991 4290345591 4290674040 4290279544 4290148728 4289882742 4289622125 4289491323 4289557113 4289554798 4289815164 4289161592 4289357163 4288371311 4289289057 4290603601 4290997595 4291915104 4290402902 4288758350 4288427342 4292181360 4293179271 4294168481 4294037925 4294036897 4294037923 4294036896 4294037666 4294037666 4294036641 4293706391 4293838748 4293375343 4292446069 4288627791 4284288835 4284090427 4285670219 4287643474 4289347403 4287841359 4287903565 4287969871 4287967318 4287839567 4288629077 4288366413 4289941084 4288498004 4288625490 4287905358 4287116368 4289086801 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4288703369 4289887884 4289693580 4289432222 4289566884 4289629847 4289565324 4289888402 4289426300 4289488234 4287186521 4286787405 4285539146 4284155443 4286588486 4288953422 4291122006 4292376426 4292774004 4293365880 4293238406 4293631871 4293042298 4293237377 4293565819 4293566337 4293566847 4293565314 4293235067 4293230696 4292701285 4293172121 4294631628 4290734712 4288042368 4288101219 4283962181 4285408333 4284752715 4284029771 4285274958 4283766852 4284553294 4284093770 4285539665 4286596198 4283766084 4283238218 4285277274 4285937500 4285539414 4285999965 4284621385 4283962684 4285539418 4285938540 4286664310 4287057009 4286397534 4284882511 4283239236 4283565130 4288376988 4289107131 4283238204 4284689264 4285342801 4286071416 4285212254 4284950106 4286797972 4286994311 4285742212 4286203256 4287585956 4288972455 4288903587 4288509854 4288849599 4288777130 4290024358 4282714202 4282908727 4290743690 4292001752 4284683063 4287188369 4289693065 4287126151 4285860661 4284159042 4283698760 4283700295 4283831360 4286329697 4286656585 4285078599 4285341256 4284226375 4284489289 4284752460 4284095300 4284554826 4284750918 4285475920 4286391621 4284553795 4284291911 4284752460 4284292425 4286329166 4285999689 4286455878 4287115351 4288954187 4290137172 4285670216 4284683319 4284746559 4287443532 4287115847 4290665567 4291123292 4291513941 4291778141 4291848812 4291450460 4290401112 4291189085 4292371304 4292440438 4292441721 4292636771 4292438885 4292176504 4292636257 4292375676 4292574058 4292570725 4292310395 4292769147 4292309619 4292769915 4292313212 4292904833 4292839284 4292708227 4293169023 4292972158 4293496704 4293107077 4292713883 4292780173 4293438873 4293043100 4292979342 4293439113 4292981409 4292981138 4292981907 4293310110 4293638294 4293114534 4293771938 4293441959 4293838246 4293904798 4293838516 4294036906 4294036674 4294036403 4294037701 4294629308 4292263855 4285015632 4284881475 4287182672 4285669186 4285867334 4285539144 4285999945 4287380306 4287312204 4286788172 4286654278 4283897159 4286065231 4293237912 4292510056 4290803837 4290346105 4291396732 4291134334 4291725698 4290936185 4290282627 4291593597 4290608240 4291070855 4290345078 4290873722 4290935926 4290476919 4290805636 4290410871 4290214518 4291198340 4290542710 4290080118 4290211701 4289820024 4289753978 4289229167 4288965491 4289162355 4289616749 4289356376 4290472034 4291913313 4290997853 4290271826 4289220176 4289940057 4291990383 4294230394 4294036897 4294036897 4294037646 4294036897 4294037666 4294036896 4294037924 4294035853 4294035854 4293375357 4293175178 4290671194 4286390347 4283893820 4285602121 4287181130 4289086799 4287708001 4287776343 4288493902 4287773529 4288361546 4288498004 4289088595 4289547090 4289742681 4288824138 4287708238 4288495714 4288364108 4289022303 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4289427337 4288178037 4289491844 4289433493 4289630089 4289630618 4289630618 4289367444 4289754752 4289821830 4289354852 4287642967 4286062408 4284287794 4286326346 4288755786 4291779157 4292114289 4293167218 4293299586 4293238405 4293566850 4293631872 4293171584 4293565563 4293565562 4293566851 4293565301 4293300597 4292773492 4292964728 4293174931 4294304208 4288564329 4291134608 4290876830 4282581038 4283633982 4284024374 4284685380 4285277774 4285933901 4285014857 4285605972 4285869919 4286199892 4285409116 4283107398 4286331993 4286924143 4286063940 4284226629 4285212502 4285605201 4285082454 4284817994 4284029256 4283960900 4283899213 4284687947 4283700553 4284356697 4287587466 4287526041 4285804644 4283239232 4284558193 4285744505 4285940585 4285478526 4284953954 4287850661 4286205549 4286398071 4285942137 4289229986 4288646581 4288903581 4288775848 4287323008 4288512931 4287979671 4285015923 4288303980 4292849053 4289299373 4286465650 4286264906 4291144120 4284158289 4284160838 4283832397 4284557391 4283965007 4287051855 4285936472 4285276745 4285409100 4285277517 4284884304 4284949582 4284294735 4284949839 4284885586 4285932615 4286199128 4284752718 4284884047 4284885842 4285080396 4287183189 4286462287 4285800005 4286986841 4289874265 4289743195 4287182411 4283898953 4284092233 4286328908 4287839053 4290471536 4291451743 4291452516 4291516256 4290600799 4290006873 4290402918 4292244606 4292306788 4292373348 4292571257 4292374646 4292374392 4292638054 4292311935 4292572006 4292505190 4292571238 4292570980 4292504931 4292575086 4292508523 4292509805 4292969594 4292772990 4293169536 4292317054 4293170313 4292318862 4292711565 4293563262 4292712846 4292976519 4293045903 4292977034 4292977036 4293047699 4293373323 4292979859 4293310625 4293245324 4293638296 4293508255 4293838748 4293640097 4293904555 4294102702 4293838514 4294036660 4294036416 4294037686 4294038459 4294366909 4291276459 4284618056 4285932099 4285864512 4284946494 4285471293 4285997129 4286852169 4286260038 4287443788 4286658897 4283696958 4286656084 4292977814 4291981924 4291132787 4290935404 4291396989 4291462783 4291528310 4290742132 4290873203 4290542459 4290870648 4291134068 4291396466 4290804855 4291068027 4290870903 4290870902 4290608247 4290214276 4290410869 4290280324 4290279798 4289688696 4290211446 4290211701 4289556601 4289753464 4289096050 4289096041 4289552226 4289947735 4291062876 4291587155 4290995545 4290205782 4291123534 4293240450 4293839004 4294036639 4294037666 4294038439 4294036896 4294037666 4294037666 4294037924 4294101903 4293310847 4293243529 4292119646 4290140501 4286718022 4284617530 4286851401 4288758620 4288822095 4288298830 4289086546 4288498002 4288297037 4288494932 4289811038 4289484121 4290206822 4288891733 4289153377 4287773518 4287772237 4288430673 4289021266 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287057767 4288305015 4288705422 4289821321 4289432736 4289631381 4289567650 4289433496 4290024605 4290087054 4289490804 4287380041 4285931336 4285335097 4286456386 4288955216 4291125090 4292376169 4292708217 4293760635 4292976762 4293566077 4293565305 4293632387 4293371000 4293565050 4293502601 4293565819 4293366648 4293757045 4292310119 4292443248 4293643960 4287902569 4288561999 4290216567 4282843707 4283632957 4283505487 4284028214 4284291651 4284555081 4284028475 4284619074 4285479516 4285735759 4286459986 4284228428 4284552520 4284098124 4284025928 4284224343 4286725480 4286597497 4285147988 4284620617 4284157766 4283307083 4283960895 4286397285 4284424782 4283436872 4283898197 4286203240 4287982235 4284095586 4283964228 4285739100 4285080414 4285873263 4285869945 4285941102 4288507569 4286663555 4286790254 4288314270 4289496754 4288838567 4288644258 4287584147 4287917462 4289628578 4287057789 4287913871 4287582561 4289698223 4284950634 4283302732 4291348404 4286197347 4283635781 4284226117 4283503688 4283369799 4287184204 4286588230 4285802052 4285409869 4284291138 4284946750 4284620874 4283700813 4284881222 4285211980 4285343052 4286918225 4284031053 4285539143 4284685382 4284486971 4286063943 4286522951 4285670215 4287903560 4290663261 4291121743 4288560209 4285468991 4284352822 4287048522 4287968599 4290536296 4291584096 4291580767 4291121750 4289943394 4291584865 4292108646 4292438373 4292109946 4292637286 4292571238 4292570980 4292638313 4292505189 4292963944 4292508523 4292964204 4292308855 4292375671 4292768637 4292507496 4292706942 4292509548 4292837755 4292774533 4293038462 4292970888 4292710270 4293102973 4293104519 4292318348 4293108116 4293435010 4292648591 4293434497 4293045904 4292649874 4293371786 4293371273 4293309836 4293244060 4293246094 4293574048 4293508009 4293640353 4293970604 4293706402 4293904564 4294036661 4294036659 4294037186 4294036670 4294038469 4294892990 4290482589 4283894069 4285469757 4284352569 4285402940 4286192451 4287575630 4285800008 4287047751 4286195783 4283957318 4288167763 4292910224 4291655012 4290999654 4291265661 4290936957 4291725690 4290936957 4291133822 4290936186 4291199604 4290608507 4290739320 4290805112 4290674043 4290610801 4290870648 4291068282 4290542455 4290608246 4290411128 4290539891 4290083204 4290277493 4289360235 4289885561 4289556343 4289163391 4289687150 4289621873 4290013797 4290274656 4291524191 4291653982 4291387981 4289943896 4291853153 4293374100 4294166412 4294037924 4294037666 4294037409 4294037666 4294037409 4294038437 4294037153 4293904798 4293246104 4293107570 4291785823 4288497491 4285536837 4286327122 4287511888 4289284180 4288235086 4288296784 4288234831 4288168781 4288888668 4288957777 4290073181 4290663516 4289482587 4289087841 4288365903 4288300622 4288626005 4289349972 4288367197 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285671505 4286200415 4288306799 4289361285 4289495441 4289564310 4289961901 4290615704 4290485149 4290283909 4289688943 4288894568 4285799237 4284287800 4286325834 4289214538 4291451996 4292705635 4293100924 4293235584 4293632386 4293566850 4293566850 4293172871 4293565820 4293567367 4293764728 4293564801 4293366647 4293494383 4292768362 4292646028 4291394691 4288897147 4285934425 4284618293 4283041869 4284224067 4284160838 4283698247 4284027719 4284554824 4283961157 4284422468 4286594929 4283896890 4285343567 4285801033 4283766340 4284354122 4283175236 4284355404 4287519366 4287517825 4285276237 4285674585 4284357705 4283371334 4283305036 4286859635 4286530413 4282843716 4283436105 4285477740 4287783572 4287452790 4283240019 4285212256 4285415022 4285871732 4284885338 4285741184 4286732164 4287849631 4285413736 4288902565 4289171371 4288638871 4288641186 4289235637 4288310692 4289437113 4287050857 4288771484 4285468493 4289956236 4290419389 4282515502 4292126879 4288574087 4282908727 4283239749 4283701572 4283632702 4287314766 4285932871 4285798722 4285867854 4285536835 4284552764 4284880966 4283634750 4285472325 4284029767 4286326342 4286198605 4284814908 4284488260 4284159031 4284614975 4286195788 4286459722 4286783561 4288365651 4290402392 4290861151 4289808979 4285730367 4284747583 4285604424 4287969358 4289878116 4291649113 4290330447 4290402150 4291455078 4292309612 4292240482 4291976296 4292703334 4292373096 4292505956 4292767868 4292045671 4292375932 4292570980 4292374393 4292505445 4292572519 4292311419 4292573545 4292505959 4292705405 4292706429 4292641387 4293165175 4293036421 4292906361 4292710528 4293037695 4293104520 4292776583 4292713358 4293108107 4292711818 4293042839 4293040776 4293045648 4293371786 4292979087 4292979088 4293770650 4293244321 4293639827 4293508256 4293706135 4293838247 4293970603 4293838759 4294036917 4293838266 4294037172 4294037698 4294037440 4294104005 4294304198 4287915126 4285142078 4284092217 4284944704 4285733444 4286524232 4285601859 4286064969 4285141826 4283893318 4289022555 4293175700 4291652442 4291133296 4291134077 4291528559 4291528303 4291331190 4291199089 4291004798 4290742132 4290739064 4291462773 4291133560 4290739319 4291396475 4290805111 4290674042 4290542454 4290739844 4291067767 4290279288 4289820023 4290608247 4290279045 4290148215 4289687928 4289819512 4289555565 4289556861 4289817457 4291717731 4291984205 4291523929 4291651172 4291254606 4292248165 4293838469 4294036897 4294038437 4294037409 4294037666 4294037666 4294037666 4294036896 4294036641 4293970059 4293439352 4292052324 4291451223 4287179862 4286063684 4287707223 4288627278 4289153107 4288232024 4288758349 4288888145 4288824924 4289022559 4289613660 4290007130 4289418847 4289809497 4289153109 4288103500 4288754526 4289021257 4288302186 4289810266 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284288583 4284950343 4288042088 4288310166 4289231752 4289500303 4290486694 4290419104 4291207066 4289892508 4289428101 4288701797 4286984266 4283892280 4286061124 4288495690 4291320927 4292639084 4293035387 4293234566 4293633412 4293566079 4293566076 4293566849 4293566851 4293370485 4293566595 4293567364 4293563262 4293231208 4293097585 4292909956 4291538342 4289814638 4286590801 4285540176 4283700037 4283568448 4283896636 4284158532 4283829817 4284620614 4283503179 4286860394 4285343310 4283373648 4284883784 4284292431 4284817994 4283502149 4284222297 4284688720 4288045445 4287516046 4283433774 4287057521 4285343326 4283699527 4283433797 4285016924 4288309398 4284161099 4282976328 4285082729 4285940593 4285938544 4287583879 4284095303 4285411438 4286071664 4286726269 4284953955 4284885356 4287262118 4286135414 4288312485 4287583867 4287913878 4287521430 4289236408 4288902568 4290293172 4289168305 4290995832 4283630391 4283766331 4292925888 4286130804 4290676371 4291472294 4282646585 4283567159 4283698751 4283502149 4286591808 4285735499 4285144642 4286261835 4284684610 4285669965 4284292677 4284357700 4284292425 4285079114 4285801800 4285866056 4284753233 4285080394 4284685639 4284551730 4285735491 4286591054 4285932873 4289477970 4291386712 4291190105 4290267466 4286325572 4284679733 4286261318 4287444558 4289745775 4290528849 4290663513 4291977576 4292438114 4292505192 4292041833 4291847012 4292439656 4292373350 4292766589 4292505700 4292572266 4292572521 4292570727 4292505445 4292964202 4292439653 4293096570 4292506215 4292509550 4292506984 4292510062 4292706172 4292575851 4292771449 4293103482 4293035906 4293103487 4292645253 4293496963 4293105542 4292646796 4293174151 4292712333 4293045389 4293042570 4293371014 4293047700 4292980115 4292979601 4293309836 4293180318 4293573779 4293706148 4293640353 4293574315 4293904808 4293838781 4294036916 4294036415 4294036926 4294038468 4294037955 4294301627 4293053389 4286458178 4283698743 4284813619 4286387525 4285996615 4285795645 4286391363 4285209156 4284416066 4289948262 4292580745 4291979096 4290806647 4291198060 4291331189 4290739580 4291331188 4291594105 4290676597 4291133049 4291134069 4291462516 4290476923 4291200117 4290805111 4290608506 4291133818 4290870903 4290608247 4290148472 4290674040 4290343285 4290411384 4289951351 4289622136 4289753720 4289490552 4289951356 4289423972 4289949277 4291786584 4291850576 4291850337 4291524184 4291388764 4292972917 4293837449 4294038181 4294038695 4294037409 4294037666 4294037666 4294036896 4294038697 4294035851 4293707147 4292848273 4291719764 4288230731 4286918475 4287049546 4287970638 4288760660 4288298337 4288232779 4289219940 4288758351 4289021781 4289613659 4290010208 4290536555 4289874521 4288103004 4288824399 4288823137 4288104012 4289747310 4288892500 4288367462 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283434814 4284422204 4286463596 4287715946 4289230994 4290157479 4289829280 4290290094 4290749089 4290023564 4290149498 4289097324 4286853205 4284155698 4285797694 4288428876 4291517275 4292640367 4293037425 4293695616 4293173127 4293566849 4293567366 4293567366 4293565822 4293566596 4293567362 4293565816 4293563256 4293559657 4292246127 4293685334 4293441687 4288893818 4287184992 4286464871 4283172410 4283436352 4284160839 4284091462 4284291655 4284094019 4284356917 4287584386 4283896645 4284292675 4283700300 4284952660 4284424780 4284620614 4283961689 4285539666 4289098149 4287057781 4283500347 4285610600 4285670215 4283566133 4283763780 4283239232 4287848053 4286004097 4283435324 4283898956 4286930059 4285276241 4286203255 4287254410 4284553825 4286797962 4286992490 4286003833 4284554848 4285676130 4286925707 4288313507 4286462321 4288178827 4288246181 4287521941 4288840874 4290095029 4289832376 4288300405 4282779455 4282318924 4286796130 4288570000 4288114299 4292986571 4282318900 4283370562 4283303986 4283501628 4287048009 4285671758 4285733186 4286720584 4285405508 4284947267 4284815688 4283764280 4285076543 4284292682 4286331739 4285739342 4284357705 4285014089 4285082198 4284747058 4286259268 4285865032 4286979910 4290137166 4291124313 4291778642 4290073428 4287242313 4284548150 4284946752 4287050057 4288891230 4291256672 4291844696 4292108127 4292505449 4292306792 4292176740 4291980395 4292434538 4292637800 4292373350 4292505447 4292574061 4292504934 4292508525 4292965485 4292441193 4292572266 4292506727 4292506472 4292702585 4292705658 4292509804 4292837514 4292968055 4292970880 4292774275 4292971144 4292710528 4293299064 4293038468 4292646286 4293499520 4292712332 4293041543 4293435792 4292583311 4293438363 4292586387 4293832085 4293309085 4293243038 4293703313 4293574049 4293312422 4293705889 4293838245 4293772195 4293904562 4293838512 4294037429 4294036928 4294037697 4294037954 4294040010 4294303412 4291338413 4283498548 4284549440 4284552505 4286594913 4284613427 4285868616 4284943170 4284221501 4291458675 4291791482 4291323746 4290672248 4291134074 4291462785 4291528567 4291133820 4291133810 4291265139 4290935149 4290414198 4291068287 4291594101 4290606956 4290805369 4291264887 4290411127 4290936696 4290345336 4291002232 4290608248 4290542456 4290016376 4290082168 4290213752 4289622392 4289951097 4289622125 4290012787 4290538090 4291521121 4291653476 4292180564 4291326803 4291588442 4293437559 4293838215 4294037924 4294038695 4294037409 4294037409 4294037666 4294036899 4294037132 4294037160 4293837957 4292581225 4290073428 4287114315 4287508295 4287903321 4288560986 4288561744 4287707724 4288563539 4289152852 4288956245 4289611095 4290009183 4290534239 4290268506 4287317580 4288821839 4288757839 4287382859 4290004825 4288891731 4289940334 4288958559 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283631925 4284354873 4285077824 4286924651 4288441989 4289632408 4290487473 4290160031 4291339954 4290550426 4289171098 4289886065 4286789459 4284154675 4284746039 4288623686 4291387231 4292706158 4292903292 4293237120 4293632127 4293566081 4293172602 4293370227 4293567367 4293370485 4293567111 4293565563 4293563768 4293233775 4292838000 4291848035 4289743449 4291736011 4287647574 4286461267 4282974778 4283831367 4284359237 4283699017 4283963460 4284225095 4285742188 4285804369 4284289600 4283634760 4284226121 4284360272 4284159556 4284357694 4284354116 4285408862 4288772766 4286992769 4283632712 4285083992 4286394717 4283961924 4284156996 4283893314 4284357456 4288107129 4286264419 4283041592 4286337416 4285209176 4285214550 4287715730 4286531707 4286399337 4287322266 4287586446 4286733711 4284491630 4286135403 4287786916 4286068335 4288773300 4289035179 4287254411 4288512181 4290487478 4289829030 4288109703 4284621907 4283040831 4284290641 4289300674 4289295754 4293845459 4283630394 4283306315 4283371339 4283370550 4286590539 4285999434 4285996871 4286591822 4284814649 4284619070 4285010498 4284683574 4284358218 4284880444 4285475148 4287509836 4284095044 4285342542 4284883017 4284353848 4285604938 4285865032 4288492878 4290532446 4291189342 4291124570 4290201930 4286521416 4284023865 4285011260 4287511125 4289679463 4291515730 4291909210 4292108127 4292307305 4292109155 4292307049 4292241255 4292831339 4292175714 4292308323 4292898923 4292505446 4292965997 4292505190 4292439654 4292899949 4292506472 4292309880 4292509547 4292900715 4292638074 4292510062 4292835949 4292641645 4292772715 4292773248 4292972409 4292969597 4292712075 4292776067 4293103746 4293038471 4292712843 4293041298 4293372295 4293435011 4292979599 4293109387 4292980880 4292983444 4293375372 4292852130 4293639571 4293507998 4293838502 4293838257 4293904808 4293904562 4293838768 4294036673 4294037172 4294036927 4294038211 4294038725 4294104264 4294303161 4286988897 4283567671 4284876349 4285602109 4284811574 4286585930 4283762482 4284483134 4292377713 4291987831 4290536799 4291199088 4291528579 4291462765 4291265399 4291331190 4291002998 4291199356 4291265396 4290542444 4291528310 4290345336 4290476921 4291264888 4290411128 4290608248 4290542712 4290082680 4291068024 4290410872 4290082680 4290607992 4290214008 4289819513 4289951096 4289490809 4290080378 4290014052 4289092181 4291389799 4291789924 4292052322 4292779131 4292780157 4293376137 4293904009 4294038695 4294038180 4294037409 4294038437 4294037413 4294037903 4294036646 4294101628 4293571975 4291985504 4289020750 4287179592 4287838030 4288822607 4289021521 4287576151 4288431196 4289744221 4288892771 4289679708 4290007644 4290009440 4289611089 4287906637 4288363353 4288756812 4288757582 4289155172 4289810271 4289087581 4288432215 4288566128 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283370294 4283500339 4284224839 4286394713 4288838289 4289631382 4290356391 4290879910 4290748574 4290157735 4290219656 4289556864 4286987348 4283433778 4284155956 4287899466 4291060825 4292704366 4293036146 4293301121 4293566336 4293370742 4293632904 4293566080 4293565305 4293566596 4293764472 4293501316 4293565053 4293626483 4293099098 4292109407 4290072406 4293110924 4285341256 4284749115 4283372620 4284160580 4283633225 4283698245 4285015373 4284359501 4286262360 4284357960 4283765823 4284094534 4284424776 4284226883 4284025157 4284027461 4284423750 4285539912 4288970144 4286860422 4283236922 4285147991 4286858862 4285141573 4283501632 4283435836 4283305032 4284290112 4287976324 4286858882 4286332279 4285937776 4283631956 4285674850 4286728829 4285742979 4287060108 4287325342 4287653764 4287060124 4285081948 4286530684 4285676675 4288113293 4289429673 4288909487 4288638873 4289306038 4287455874 4284287031 4285675367 4283303996 4285998425 4291142328 4290482862 4293385423 4284026690 4283240779 4283371331 4283108162 4287312974 4286521928 4285866055 4287052111 4284815427 4285143876 4284226367 4283833936 4284620874 4284490318 4286328652 4285671754 4284290371 4284554051 4284683580 4284683576 4286324042 4284814906 4288757577 4290135625 4290267476 4291385426 4290069579 4288227660 4283960888 4285469755 4288823388 4289284179 4291518302 4291450962 4291912547 4292174699 4292042328 4292109156 4292439400 4292439656 4292043107 4293091423 4292899435 4292307560 4292308841 4292506729 4292901744 4292899692 4292508268 4292899432 4292900494 4292444779 4292904062 4292444530 4292901486 4292640636 4292969851 4292771704 4292971654 4293102452 4293103486 4292710789 4293104520 4292711564 4293041287 4293040773 4293041031 4292649628 4293111182 4292715410 4293046928 4293439130 4292981152 4293769880 4293180058 4293573790 4293706157 4293640104 4293772462 4293904573 4293838768 4294036660 4294036414 4294036926 4294038211 4294037954 4294037955 4294499521 4291600805 4283891761 4284419129 4285600574 4285074744 4284811319 4283566138 4285534789 4292314997 4292186502 4291128939 4291328868 4291463023 4291462788 4291265388 4291331181 4291132269 4291396983 4291134060 4290871167 4291462507 4290608252 4290936184 4290216818 4291001976 4290542456 4291002489 4290474614 4290146933 4290674296 4290542456 4290343285 4290477433 4289491308 4289556347 4289621616 4289424742 4289880418 4290341748 4291721065 4292120180 4293501313 4293241969 4293770375 4293969036 4294036897 4294037409 4294038180 4294038180 4294037411 4294037646 4294037157 4293838216 4293838990 4293237359 4291061334 4288099916 4288362574 4288757072 4288890194 4288103759 4288756302 4288890450 4289676888 4289612633 4289416796 4290534239 4290072659 4289611094 4288758351 4287641167 4288822352 4288037710 4289679197 4288957268 4289155692 4288565347 4288630626 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283369792 4283567170 4284421702 4286065754 4287718272 4289763224 4290421927 4290160562 4290684321 4291796634 4290089872 4289757307 4285603897 4283631934 4284221235 4287903309 4291713368 4292639838 4293101427 4293037185 4293567877 4293632391 4293173862 4293632390 4293172857 4293567110 4293501573 4293500544 4293565559 4293562485 4293493098 4292175717 4289152870 4287712344 4291006623 4283368507 4283108688 4284490570 4284488771 4283699768 4283962953 4285607762 4284423496 4284816453 4284159548 4284227143 4284028228 4283636305 4284292423 4283503952 4283567174 4286331242 4289631157 4286201454 4283630399 4284684874 4286924901 4284160576 4283566399 4283635015 4284884564 4283765846 4284884560 4286793834 4287256197 4286530428 4283962688 4286399606 4284425823 4287123596 4286335086 4287456670 4287189641 4286992263 4286070392 4286008192 4285936752 4286599820 4290091186 4289239736 4288906677 4289894319 4289697721 4284222525 4283633982 4286795647 4284612691 4289893035 4291408055 4292202951 4283236395 4283305026 4283370553 4283500343 4286657358 4285733437 4286064198 4288170586 4284159296 4284880452 4284356668 4284814146 4284618822 4285142085 4285671754 4285210695 4284554052 4284356169 4285082448 4285602365 4285996872 4286654541 4289152340 4290401104 4291514454 4290002505 4290201934 4288363079 4284878654 4285405258 4287905359 4290006361 4291583068 4291779425 4292566623 4292307550 4291976799 4292304228 4292439912 4292175209 4292637288 4292440681 4292440168 4292897377 4292965998 4292506986 4292505190 4292506987 4292570214 4292508012 4292443754 4292770941 4292443243 4292898666 4292444782 4292706427 4292574843 4292969594 4292773743 4292774779 4292905865 4292971640 4293102973 4292711822 4293500035 4292976275 4293041286 4293108116 4293041033 4293045133 4293044366 4292982422 4293045136 4292982675 4293311398 4293378202 4293705889 4293838256 4293904806 4293838769 4294036918 4294037174 4294037184 4294036926 4294037440 4294038211 4294038725 4294038725 4294697424 4286196543 4284089150 4284942648 4283959606 4285139769 4282713908 4286584124 4292514436 4292578421 4290734441 4291330419 4291462779 4291462766 4291265398 4291265407 4291396982 4291396725 4290607995 4291462507 4291264894 4290610802 4290870393 4290936184 4290673529 4290608249 4290214510 4290475626 4290669939 4290671989 4290017401 4290082680 4290277494 4289490811 4289621359 4289490021 4290141799 4290273375 4291588717 4292710779 4293961079 4293505936 4293705095 4293966725 4293838474 4294037154 4294038180 4294038695 4294037409 4294037667 4294036897 4294036641 4294168468 4293701749 4292253024 4289873994 4288036176 4288102224 4289478739 4289219410 4288692047 4288693329 4289742681 4289481813 4290071636 4289944153 4290072924 4288826456 4288497247 4288233038 4288233039 4288889937 4288890195 4289744735 4289087839 4289022052 4288566897 4288630373 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283369785 4283830089 4283897924 4285147986 4287912573 4289499542 4290617506 4291340200 4290618538 4290550169 4290221972 4289162609 4285802576 4283171897 4284942135 4287903052 4290665046 4292771698 4292904834 4293695099 4293566080 4293371257 4293632648 4293370486 4293567111 4293764473 4293501318 4293764730 4293499767 4293627764 4293034091 4292440164 4290078599 4290011769 4290411390 4282845248 4284294732 4284422222 4283831613 4283700557 4285214804 4284949583 4284030020 4284884047 4284161606 4284422976 4284163151 4284358727 4284618820 4284096587 4283894099 4287980949 4290089394 4286265948 4283106879 4283631417 4286990949 4285541462 4283236928 4285276246 4284686154 4283896391 4284951117 4284223318 4284160068 4285279317 4283567930 4286662784 4285080656 4287189630 4286792583 4287256458 4286728053 4285811313 4285675377 4286137981 4286005368 4286928769 4289496746 4289040821 4288903066 4288970400 4290094506 4286267258 4282910270 4284882003 4283696715 4289956505 4291935940 4291274407 4282318920 4283435067 4283307607 4283700030 4288298323 4286064712 4285669448 4288893023 4284030027 4285472584 4284489801 4284687697 4285339195 4284750915 4286524493 4285472843 4284354864 4284420677 4284422981 4285272892 4285929029 4288035151 4290267978 4290922318 4289019977 4290069582 4291058264 4288558154 4284941111 4285142588 4288629072 4289217365 4291973980 4292108383 4292307556 4292307301 4292109412 4292109411 4292632428 4292571992 4292505962 4292831842 4292898923 4292505960 4292307554 4292505704 4292505704 4292965470 4292508270 4292508012 4292964972 4292441961 4292902257 4292900715 4292705147 4292706428 4292838763 4293166970 4292575872 4292774532 4293100405 4292971144 4292515207 4293169025 4292711565 4293105028 4292715418 4292713367 4293042567 4293047971 4293044364 4293044877 4292979873 4293048467 4293309590 4293245604 4293706145 4293838255 4293772216 4294102710 4293838512 4294037430 4294036413 4294037954 4294037697 4294037440 4294037954 4294038725 4294565313 4290875543 4283629611 4284680505 4283763510 4284549942 4283106868 4287244103 4292644206 4292578680 4290540913 4291134068 4291462767 4291462777 4291659900 4291528567 4290739570 4291331191 4291594095 4291199102 4290479474 4291067508 4290676338 4290870649 4290739820 4290608250 4290476141 4290542714 4290083193 4290737526 4289886572 4290145655 4290017389 4289557103 4289556081 4290079856 4289750873 4291390304 4292384111 4293766027 4293637505 4293640322 4293639811 4293772701 4294036108 4294037667 4294038695 4294037153 4294038182 4294038160 4294037928 4294036110 4293706118 4292978296 4291586916 4288559688 4288625489 4289544781 4288170061 4288231756 4288758866 4289808473 4289547354 4290071642 4289812319 4291124319 4290006362 4289676624 4288233559 4288233039 4289021009 4288170076 4289939800 4289615200 4288431438 4288563545 4288631152 4288436062 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283370294 4283697210 4283961919 4285475419 4287913342 4290348951 4289829281 4290749856 4291274666 4290224802 4289499279 4289228403 4285934152 4283302964 4283303987 4288621388 4291518300 4292311381 4293035894 4293630069 4293567879 4293173117 4293566595 4293370486 4293566597 4293304696 4293764987 4293501575 4293565314 4293627764 4292836717 4292305762 4293372569 4289621369 4286266460 4283175752 4284949836 4283829062 4283501894 4285017168 4285343575 4284423239 4284094011 4284882755 4283960134 4284221515 4284489028 4284620614 4284027717 4283633992 4284619094 4288709799 4289038250 4285936213 4283368515 4283436606 4285542218 4286197335 4283566137 4285542732 4285671508 4283830092 4285086054 4284095565 4283565629 4284292191 4284687198 4285280858 4285937018 4284561262 4287584924 4286862461 4287589025 4286992522 4285678458 4285871992 4284885884 4287389606 4289038757 4289561258 4287058574 4289897398 4288575132 4288045969 4283436868 4283108679 4283957817 4288709013 4292069067 4286664543 4283369526 4283303740 4283239238 4284421435 4288234323 4285341244 4286458189 4287446099 4284746542 4285540430 4284422724 4284945206 4284161868 4285339710 4285935181 4284886870 4284355909 4284355134 4284944177 4286260555 4285208640 4288626258 4289281869 4289676367 4290987600 4291127140 4291779164 4288625996 4285533245 4285405506 4288432732 4289809495 4291515740 4292240997 4292109162 4291976541 4292501089 4292241507 4292508010 4292897388 4292832097 4293225318 4292440168 4292505960 4292699491 4292897890 4292700779 4292440168 4292570983 4292505191 4292506217 4292574573 4292509036 4292310653 4292508779 4292509805 4292705917 4292837755 4292577135 4293165703 4292904830 4292906367 4293104023 4292776838 4292777356 4292712844 4293106308 4293107346 4293045132 4293042569 4292652436 4293045920 4293440155 4292654488 4293375645 4293245859 4293771937 4293640105 4293772461 4293904562 4293838768 4294036671 4294036413 4294037183 4294036926 4294037440 4294038211 4294038725 4294170044 4293974461 4285530161 4284158523 4283500854 4284746551 4282975027 4288494933 4291986022 4292051058 4291132282 4291265910 4291725436 4291265398 4291330923 4291002494 4291396982 4291331181 4291133557 4291396972 4291133306 4291002483 4290674044 4290870903 4290542714 4290476921 4289948790 4290080887 4290540908 4290410873 4290016889 4289885305 4289687930 4289555823 4289488228 4290144365 4290272604 4291723653 4293701246 4293838470 4293905054 4293905055 4293770375 4293902728 4294036899 4294038437 4294038694 4294037923 4294037923 4294038701 4294036878 4294102676 4293637753 4292578404 4290401099 4288559949 4289348173 4288561744 4289215824 4289150288 4289545809 4289613147 4289415770 4289877077 4291058784 4289812824 4289415511 4288889675 4287055182 4288887631 4288298833 4289218389 4288826702 4289088085 4288564071 4288695142 4288633696 4288698227 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283370294 4283500345 4284749380 4287518321 4289565334 4290024609 4290290094 4290683301 4291076511 4289435287 4289426279 4285999440 4283565619 4285269050 4287967053 4290991437 4292310895 4293429097 4293235850 4293565306 4293765502 4293566338 4293567882 4293369971 4293370232 4293502605 4293763958 4293499771 4293562477 4293361241 4292633699 4292977040 4289357160 4285545320 4283239484 4285539664 4283569224 4285013329 4285934423 4284489544 4284160315 4284159566 4284486214 4284226619 4283696971 4285081679 4283434043 4283631687 4283172436 4286140813 4289690020 4288705938 4286263640 4283570251 4283306828 4284686150 4285082712 4283498560 4286137451 4285210185 4283767884 4284685894 4284754529 4284027202 4284097610 4284158534 4283832394 4286399092 4285280090 4286792558 4286796943 4288245667 4286793592 4285413486 4285676399 4284226381 4287518860 4290158517 4287787935 4288179879 4289436849 4287722129 4289237174 4288639134 4285541985 4283894085 4290812864 4289698481 4285078869 4288712386 4283105334 4283173695 4284554310 4287577171 4286129221 4286393930 4287113802 4284029253 4285733948 4285078077 4285143871 4285076287 4285079111 4285602629 4284948553 4285147732 4284422466 4285472069 4285998408 4287243079 4287509318 4291185999 4291121494 4291321692 4291844191 4291649110 4288822348 4284154682 4286128702 4289087308 4290464601 4291253584 4292240735 4292307305 4292307305 4292633190 4292175715 4292963179 4292242535 4292897643 4292440424 4292505960 4292701029 4292897890 4292307817 4292506216 4292962924 4292505704 4292898153 4292509550 4292312448 4292965996 4292509293 4292965741 4292510063 4292511092 4292445553 4292837497 4292577157 4292970861 4292905609 4292906620 4292711560 4293103489 4293105799 4292778123 4292780431 4293042834 4292975763 4293502855 4292980129 4292982670 4293046945 4293311897 4293245088 4293377955 4293444275 4293970599 4293706412 4294036917 4294036672 4294036402 4294037184 4294036155 4294038725 4294036669 4294038725 4294038726 4294434243 4289096313 4283301934 4283304759 4283632439 4282908722 4289746533 4292510306 4291787379 4291459954 4291461480 4291134330 4291330933 4290808181 4291200130 4291592562 4291002743 4291331181 4291265140 4290280817 4291198577 4290279545 4290936697 4290738541 4290409322 4290280570 4290541164 4290214267 4289688440 4289687930 4289491564 4289753721 4289753979 4289753968 4289224809 4291389802 4293109359 4293706902 4294103202 4294037935 4294036639 4293838215 4293839009 4294035593 4294037411 4294038694 4294038694 4294037925 4294037391 4294036884 4293837452 4293238641 4291982691 4288825934 4289018961 4289282637 4288692816 4288692816 4288104524 4289938769 4289546327 4290532701 4290338659 4290204757 4290600032 4289478500 4287513165 4288428888 4288757838 4288431955 4289746528 4288955997 4289221728 4288435307 4287841875 4288762737 4288038739 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283370295 4283566131 4284945223 4286794362 4289956748 4290024866 4290290077 4291209908 4291404191 4290155923 4289035136 4287049288 4282647604 4284549431 4286915657 4291124578 4292703837 4293364859 4293238130 4293370745 4293435769 4292976766 4293369970 4293632648 4293305466 4293897588 4293500292 4293564786 4293561710 4293360986 4292570457 4292184438 4287383664 4283499070 4283372872 4285144904 4284685131 4284884559 4284555333 4284093516 4283763773 4284354364 4284356675 4284158537 4284882504 4283635272 4283696962 4282974786 4284292435 4289632700 4288638352 4288377738 4285804881 4283369542 4283895357 4283568452 4284884045 4284356159 4286460254 4284160835 4285277515 4284286523 4284424268 4283503430 4285540694 4283635017 4284094041 4286067558 4284623446 4285084551 4285875054 4289233569 4287587734 4284224566 4284554089 4284423528 4287323537 4288912304 4288773549 4289695145 4289438903 4286263149 4286398568 4289960885 4286071933 4289034425 4290295992 4288902323 4289300134 4292205783 4284354361 4283172677 4284881979 4287705675 4285210431 4286654792 4285932360 4285932099 4284750916 4285670215 4285668412 4284291909 4285076795 4285537861 4284356931 4284423755 4285146954 4285209154 4285799239 4287836747 4290465637 4291516241 4291255643 4291584103 4291781720 4291189075 4288627273 4285202490 4286851661 4288167503 4289875546 4291712854 4292240999 4292109155 4292307049 4292637544 4292373346 4292440681 4292962914 4292440424 4292897635 4292832354 4292699500 4292440682 4292505961 4292962915 4292440410 4292505433 4292901745 4292506216 4292507754 4292509294 4292572779 4292509038 4292901486 4292903019 4292640636 4292968585 4292578163 4292970111 4293038463 4293037951 4293298309 4292646024 4293103233 4292778379 4292778381 4293041031 4293108104 4292652437 4293047441 4293045409 4292981146 4293376661 4293309862 4293573798 4294036649 4293772463 4293904560 4294036929 4294036659 4294036403 4294037184 4294037183 4294036926 4294037697 4294038211 4294038725 4294302401 4292978589 4282908718 4283304246 4283304247 4283367985 4290601576 4291983199 4292249717 4291064425 4291661707 4291528301 4291462776 4291462015 4291002731 4291068534 4290870908 4291594105 4291067769 4291198576 4291001198 4290280558 4290999414 4290478711 4290608250 4290476921 4290605687 4289755501 4290737272 4289621868 4290079864 4289753978 4289555823 4289489266 4289881192 4291521621 4293639322 4294168480 4294038192 4294038693 4294037666 4294036643 4294035850 4294037155 4294038180 4294038694 4294037923 4294038695 4294037928 4293904268 4293897848 4292774727 4290863962 4289477962 4289480776 4289019473 4288625744 4289216336 4289084752 4289348945 4290597211 4289810003 4290860380 4290991965 4289481300 4288301394 4288887374 4288232279 4289087058 4289154136 4288760917 4290009203 4288433242 4288630630 4288697956 4288697964 4287449704 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283435830 4283172922 4284420418 4286791782 4289230991 4290091424 4290225835 4291144098 4291140506 4290090371 4289624967 4286789958 4283958068 4284024372 4287570503 4290927968 4292704077 4293166981 4293629569 4293567623 4293370487 4293632130 4293567111 4293371256 4293566854 4293305468 4293763957 4293564531 4293562229 4293165933 4292437607 4291590512 4287844449 4283240778 4284684615 4284949586 4285475930 4285341771 4284088905 4284422207 4284157760 4284554059 4284288835 4283963974 4284421699 4283762751 4283372106 4284357720 4288707755 4288636552 4286528855 4287581823 4284750925 4283503179 4283239758 4283962190 4284357440 4285672024 4286002777 4284156212 4284819024 4283369784 4283499594 4284160837 4285673826 4285081164 4283433782 4285871715 4284687709 4285016670 4284029259 4288179602 4288772771 4284882277 4285017959 4286008211 4287786140 4288905381 4289035690 4289696432 4290028469 4289630388 4286461020 4290150829 4285404755 4289107122 4289962677 4287919500 4287725696 4287785073 4283237435 4283961655 4285277510 4287245899 4284420924 4286128201 4285736005 4286261321 4285208638 4284949839 4285670985 4285143356 4285605713 4285272630 4285208638 4284750400 4285468985 4286589772 4286589002 4288953415 4291778642 4291189081 4291649894 4291584102 4291584347 4291714141 4288754253 4284941877 4286659928 4288889930 4290335592 4292041814 4292108117 4292174943 4292108899 4292439401 4292373353 4292897377 4292440424 4292898924 4292766562 4292832100 4292242531 4292897620 4292897379 4292440424 4292964204 4292505704 4292439654 4292899948 4292899692 4292899435 4292507755 4292508780 4292706693 4292509806 4292509549 4292577135 4293165704 4292774531 4292969853 4292776318 4292906124 4293104002 4292711304 4292778379 4293107857 4293106575 4292716434 4293110414 4293044366 4293045903 4292979358 4293048491 4292982939 4293639589 4293311918 4293705638 4293774522 4293706164 4293838778 4294036670 4294037183 4294036412 4294037954 4294037697 4294037440 4294038725 4294106047 4294236098 4284750146 4283106868 4283304246 4283826227 4291193946 4291849060 4291526254 4291134324 4291661182 4290871157 4291856764 4290545269 4291462518 4291067513 4291330675 4291066736 4291134582 4290410873 4291199610 4291132013 4290217076 4291132269 4290804334 4289949547 4289425530 4290935150 4290212717 4289688188 4289753198 4289556079 4289490022 4290078312 4289682014 4291787124 4293835905 4294038437 4294038693 4294038694 4294037667 4294037134 4294036386 4294037666 4294038694 4294038694 4294038695 4294038182 4294036624 4293838475 4293632882 4292181082 4290267213 4289414986 4290003531 4289151053 4288560209 4288493645 4289414480 4289348688 4289942367 4289811287 4290927191 4289942366 4289347410 4288825181 4288168023 4288234572 4288498270 4288828502 4289941614 4288366168 4288631140 4288698227 4288630877 4287384159 4287052893 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283370294 4283631673 4284486985 4286924896 4288706963 4290091418 4290880166 4291275947 4290160548 4290089616 4289300622 4287316563 4283500082 4284679735 4287570760 4290335827 4292770658 4293166193 4293565308 4293566081 4293173372 4293568136 4293565568 4293567111 4293567879 4293370231 4293567368 4293172339 4293694324 4293230953 4292703338 4291324511 4287775594 4284226630 4285344344 4285999707 4283898182 4284159051 4283634745 4284160317 4284357190 4284486460 4284680260 4284423490 4283963970 4283305053 4284224840 4289627815 4286794607 4283630146 4287258252 4286925160 4285018699 4283831885 4283634496 4283701311 4284490574 4286333796 4285802322 4283502395 4285343308 4284288839 4283436597 4284552776 4285213781 4284753762 4283433526 4284689252 4285412447 4284554833 4285678209 4287262398 4287980958 4287784848 4286336904 4286664837 4287589536 4289299118 4289233823 4289760175 4286329690 4288841642 4289628091 4289300908 4290091964 4292593087 4288708744 4283498539 4282515522 4282712101 4285017693 4285932350 4286720846 4286194762 4283701314 4286851912 4285144386 4285867339 4284749891 4285472320 4285210442 4284617270 4286064971 4284685643 4285012547 4284621386 4286324291 4286785355 4287377224 4289808464 4291387737 4291977566 4291518560 4291518810 4291844441 4290858574 4287507272 4284743733 4287775578 4288955473 4290267479 4291978073 4292108122 4292109414 4292698980 4292371545 4292571753 4292898923 4292505705 4292832344 4293161325 4292767321 4292963181 4292440426 4292505704 4292505704 4292507242 4292898666 4292898666 4292442733 4292508012 4292901232 4292507755 4292573035 4292508524 4292510063 4292704891 4292969595 4292576880 4292838526 4292579450 4292839299 4292775806 4292776324 4293103747 4293104511 4293042589 4292714124 4293108875 4292717458 4293110156 4292652966 4293508489 4292654485 4293377187 4293245613 4293377952 4293705909 4293970096 4294102966 4293904302 4294036927 4294036412 4294036412 4294036155 4294037697 4294037697 4294038211 4294037957 4294499510 4288172642 4282777649 4283238709 4284090440 4291459437 4291981663 4291395688 4291132268 4291661450 4291330922 4290805363 4291462252 4290870909 4290807669 4290544756 4291134327 4291000685 4290348403 4290542457 4290476922 4290807667 4290542457 4290148987 4291001198 4290214265 4289885561 4289754234 4289752940 4288966001 4289620083 4290079588 4289879142 4290338398 4292185957 4293905310 4294037923 4294038695 4294038182 4294037155 4294035855 4294035595 4294037667 4294038694 4294038694 4294037153 4294036898 4294102419 4293440131 4292252264 4292109903 4290072410 4290005332 4290071382 4289612111 4289348682 4289414225 4289480261 4289677659 4290401361 4290338139 4290335060 4289545560 4288301396 4289281102 4288757838 4289087060 4289087838 4289810287 4288828248 4288565588 4288760679 4287972703 4287974241 4287642972 4287118676 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283435830 4283238715 4284156222 4286466157 4289430165 4289500824 4290290599 4290750898 4290814111 4290614938 4289889142 4287319912 4284024630 4284614199 4287045448 4290400848 4292770415 4293363570 4293564279 4293371256 4293566851 4293631616 4293239657 4293305191 4293303946 4293501299 4293436535 4293300611 4293166961 4292838015 4292311147 4290468213 4287779457 4285736526 4285540702 4285212756 4283764556 4284094024 4283831615 4284620875 4283896121 4284292164 4284749376 4283897168 4284485201 4285475930 4286201703 4285149000 4283172679 4284027970 4289100949 4286855786 4285805923 4283898170 4284094533 4283635789 4284816714 4286399602 4285670727 4283895107 4283962690 4283896655 4284157254 4283832384 4285605724 4285478748 4282843967 4284754265 4287516535 4284291414 4283700546 4285281628 4285607773 4287523503 4288772776 4288577455 4288048289 4289297820 4289238447 4287917198 4286525284 4286599289 4288969645 4289168039 4290092726 4291273141 4289169582 4286472858 4284618846 4284357702 4287189085 4283498547 4286657611 4284947271 4285211208 4286851148 4285209154 4285802058 4285406531 4285344847 4285471811 4285012285 4285998669 4284683062 4285013062 4285403968 4286392137 4287114310 4288296527 4290399311 4291780436 4291846244 4291715165 4291713632 4291584873 4291581514 4286849608 4285466940 4287577681 4288822862 4290858071 4291912036 4292240749 4292307284 4292241771 4292633191 4292373608 4292505703 4292505447 4292834670 4292767595 4292831843 4292242274 4292897379 4292440682 4292765027 4292505961 4292505705 4292505448 4292964699 4292441197 4292897367 4292508013 4292573292 4292574318 4292508525 4292508267 4292903549 4292642416 4292840070 4292772988 4292839555 4293103743 4292776325 4292776840 4292713358 4293105028 4293041799 4293107346 4293042568 4293044621 4293047198 4293047212 4292652964 4293377431 4293245601 4293443502 4293510051 4293641909 4293837750 4293576115 4293904312 4294036669 4294037184 4294037183 4294036926 4294036926 4294037440 4294038212 4294433987 4292124061 4282581032 4283172918 4284485177 4291654775 4292310113 4291195508 4291134333 4291462516 4291397508 4290870907 4291462774 4291132527 4290805623 4291199852 4290542974 4291264112 4290542459 4290738541 4291132527 4290280045 4290608250 4290475629 4290083694 4290409078 4289885816 4290606198 4289885561 4289621881 4289557117 4290079076 4290079582 4290078835 4292644477 4294035081 4294037153 4294038182 4294036880 4294036111 4293838217 4294036641 4294037409 4294038694 4294037923 4294038953 4294037653 4293968765 4293567353 4292571980 4290667352 4290795608 4289808978 4290004808 4289546583 4289676106 4289282902 4289414226 4289809491 4290991445 4290860638 4290467166 4289676883 4288432462 4288364626 4288364626 4288365904 4289088597 4289681257 4288696163 4288695144 4287975255 4288235597 4287514455 4286461267 4287182934 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435831 4283435831 4283304245 4284222528 4286595947 4288840339 4289565081 4290944676 4290685602 4290814890 4290025107 4289364349 4288044131 4285008951 4284155956 4287046473 4290466633 4292836208 4292970350 4293630846 4293565306 4293632385 4292909450 4293369221 4292974988 4292711801 4292973450 4293305218 4293366146 4292643708 4292772717 4291849587 4290145133 4289626279 4285145944 4283765824 4284949580 4283635015 4284094789 4284423491 4284352839 4284357956 4284686411 4283832912 4284094535 4285675875 4287650948 4284289341 4284027996 4283766847 4284619610 4287450228 4286266470 4287318635 4283632458 4284489801 4283566151 4285543001 4284687184 4285279835 4283832388 4284223813 4283833672 4284026431 4284422487 4285939817 4283632951 4284683865 4285082452 4286599034 4285605978 4283962943 4283567701 4283899478 4285543274 4288311457 4288252596 4289100713 4287715982 4289170611 4288377502 4287782790 4286134112 4286135131 4286142578 4288118944 4287455364 4290292137 4292784560 4289302194 4290678722 4288371585 4286202746 4288104797 4285078077 4284684604 4284945464 4284684352 4286527308 4287316829 4285143871 4285011517 4285669961 4285865796 4285141562 4284551993 4285008692 4287377481 4287375689 4288558925 4291185227 4291191391 4291911779 4291649628 4291453024 4291649883 4290926169 4286454599 4284747323 4288102225 4289744470 4290598493 4292239701 4292042329 4292307046 4292307043 4292043356 4292373865 4292898922 4292898666 4292835952 4292833882 4292833389 4292833388 4293160542 4292897621 4292110176 4292765278 4292700250 4292505962 4292439913 4292964955 4292440939 4292966768 4292506216 4292509294 4292967280 4292510063 4292509549 4292903034 4292774004 4293165447 4292383360 4292969596 4292971897 4293037694 4293103490 4292319378 4293170066 4292319131 4293174667 4292717973 4293110157 4292655770 4293506458 4292981921 4293311393 4293050288 4293575601 4293903800 4293378221 4294168501 4293838777 4294036671 4294037172 4294036413 4294037954 4294037697 4294037697 4294037441 4294169787 4293707711 4283827765 4282909748 4285471294 4292310110 4291982941 4291265130 4291199602 4291528065 4291072891 4291001970 4290279800 4291396467 4290871926 4290870394 4291066476 4290282612 4290543216 4290542714 4290672749 4291002235 4290542456 4290608250 4290279801 4290214008 4290082938 4289621612 4289753722 4289753199 4289555302 4289293672 4290536297 4291257954 4292975479 4293971360 4294037666 4294038437 4294036644 4293838216 4293838218 4294037412 4294038180 4294038694 4294038695 4294037669 4293904011 4293572730 4292776299 4291782741 4291058779 4290600284 4290990157 4289874518 4289347148 4289610570 4289480274 4289547864 4289480020 4289875797 4290466897 4289419101 4288956491 4289346896 4288036432 4289609547 4288040276 4289218657 4288235854 4289944435 4287840338 4288107620 4287382368 4287577435 4287710315 4287050570 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435830 4283435831 4283304245 4283895099 4286134618 4288768903 4289566352 4290814383 4291275170 4290684579 4290744714 4289759636 4288042844 4283892784 4284287028 4287112264 4290268501 4292376926 4293626483 4293563516 4293567107 4293567366 4293304183 4292909195 4293435526 4292450691 4292978063 4293304200 4292908911 4293429876 4292837485 4291653225 4291590026 4290211982 4285275987 4284951637 4283437638 4284092997 4284027718 4284159049 4284160829 4283894839 4285210696 4284882510 4284027960 4285346909 4285014855 4283502908 4284686405 4284620103 4283504198 4287778420 4286401135 4286722648 4284750666 4283373902 4285474901 4284886618 4283962167 4284949580 4284553286 4284491086 4284554820 4284424271 4284485184 4285018972 4284752477 4284553302 4286663800 4287253378 4284422476 4283766338 4283237437 4283765080 4284755809 4288247469 4289500086 4288439695 4288315568 4288640922 4288903861 4286792549 4287649158 4282581038 4283170870 4285082183 4286066510 4283566405 4284289332 4287251792 4287908170 4287454847 4289626782 4289758131 4289425057 4289563568 4288245145 4289161868 4287250009 4285338940 4286391114 4284814909 4284617270 4286128709 4284683577 4285077567 4285603396 4287704903 4288362318 4289152087 4291515720 4291649896 4291518559 4291845729 4292109672 4292043103 4290399819 4286522698 4285866048 4288036945 4289546590 4291450975 4292108122 4292109408 4292505187 4292373608 4292831340 4292699492 4292899179 4292439910 4292834412 4292833132 4292832600 4292833644 4292440169 4292373354 4292240990 4292308325 4292963429 4292832092 4292898925 4292505192 4292509808 4292505442 4292965229 4292505960 4292510319 4292706431 4292509546 4292642703 4292837496 4292773502 4292840307 4292971656 4292512391 4293038468 4293039747 4293105543 4293038470 4292844684 4292714384 4293175949 4292717714 4293111715 4292982156 4292982178 4293312170 4293311911 4293443243 4293115813 4293707700 4293904571 4293706420 4294036915 4294036414 4294036412 4294037183 4294036926 4294037697 4294038212 4294103995 4294303410 4286985042 4282515504 4286392390 4292045928 4291130725 4291527798 4290673785 4291265133 4291072135 4291133546 4291134080 4290610547 4290282099 4290347635 4291068276 4290542202 4291132268 4290476922 4291002235 4290214508 4291001978 4290543207 4290936947 4289950585 4290674541 4289556602 4289556346 4289555825 4289488986 4290799719 4290079840 4291915101 4293108608 4293971103 4294038694 4294038440 4294035063 4293839266 4294034832 4294035594 4293972646 4294038694 4294038182 4294036367 4294167191 4293240683 4292834639 4291126117 4291122509 4291255890 4289612631 4290596948 4289742156 4289480526 4289217097 4290071119 4290005326 4289942367 4290008160 4289938250 4288626768 4288167760 4288756560 4288169295 4289286512 4288894040 4289220713 4288366687 4287974232 4288825192 4288036178 4287513696 4287579729 4287580771 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283435836 4283435830 4283369787 4283566397 4285347428 4288310400 4290157213 4291075745 4290686381 4290617768 4291272860 4289628821 4287978846 4284483900 4284484666 4286522184 4290728270 4292374360 4293233526 4293236866 4293566336 4293566076 4293566852 4293436277 4293042301 4293763975 4293436020 4293631870 4293499257 4293234797 4293294958 4292838010 4291392648 4288563313 4284685894 4284949061 4284292430 4284489287 4284092732 4285015884 4284355651 4284357700 4284621387 4284288064 4283963715 4284094794 4283765570 4285015374 4285409625 4284094790 4284029257 4286333015 4286134634 4285541462 4284554824 4284160586 4285608541 4284620358 4283698509 4284690257 4285473869 4284225614 4284419907 4283699523 4283567684 4285278036 4284884062 4283895362 4287782023 4286135913 4282647094 4285807752 4282908725 4284293970 4285806720 4286997130 4288837282 4285480559 4289763008 4286071679 4287784578 4289363366 4287718018 4286329448 4283040570 4284947772 4287059581 4283565117 4283502902 4287378763 4282384442 4282778419 4285999172 4285805125 4284552766 4289884777 4288636790 4287778402 4287781509 4286457416 4285145924 4285013062 4285408586 4284883022 4284551480 4285340740 4286327627 4287443017 4288689998 4290201418 4291975272 4291584351 4291518302 4292110446 4291190880 4291914081 4290264140 4285996103 4286588746 4289218141 4289151060 4291714646 4292637036 4292500577 4292241257 4292637544 4292109671 4292571752 4292505447 4292898666 4292900205 4292439910 4292768108 4293157733 4292833627 4292571498 4292373860 4292765533 4292109924 4292963172 4292505689 4292505448 4292965228 4292508013 4292509551 4292899435 4292508781 4292901486 4292904060 4292640632 4292640378 4292839038 4292970366 4292772988 4292970109 4293103486 4292775811 4292778119 4293104007 4292384145 4293174153 4292717715 4293110157 4292717200 4293047972 4292982188 4293442721 4292982692 4293246129 4293969592 4293838262 4293772212 4293904826 4293838777 4294036669 4294036412 4294037183 4294037183 4294036926 4294037697 4294037442 4294564802 4290541435 4281860138 4288101201 4291850596 4291788388 4291527540 4290542460 4290873455 4291593591 4291134584 4291330419 4291134060 4291198841 4290151027 4291263600 4290348403 4290542460 4290608999 4289951855 4291199604 4290542457 4290411629 4290214265 4290345850 4290146666 4290411386 4289687149 4289557104 4289754737 4289426560 4290276959 4291914845 4292782990 4293838213 4294037410 4294038439 4294036113 4293706119 4294034832 4293970849 4294236839 4293973158 4294037413 4294103443 4293641095 4293301099 4292047191 4290990925 4290597983 4290600796 4291055442 4289217876 4289612117 4289150796 4289546068 4289480527 4290529870 4290531159 4289611342 4288890960 4288756816 4288231760 4288821064 4289219677 4288826710 4289022814 4289355373 4287709009 4287907671 4288105560 4287380051 4287579231 4287514718 4287580000 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283369781 4283369781 4283369785 4283830604 4285080140 4287847553 4289696652 4290355624 4290684064 4291470752 4290486683 4289694848 4287912033 4285077822 4284155443 4287113288 4290401104 4292899950 4293034859 4293236355 4293566589 4293566852 4293566595 4293566596 4293436794 4293370231 4293567882 4293566849 4293237875 4293495938 4292968538 4291916389 4290542997 4288694897 4284553540 4284094029 4284421701 4285410139 4284091960 4283961926 4284027975 4284224059 4284292430 4284226635 4284226379 4284029762 4284883789 4285476956 4284227400 4283437636 4285407318 4285872995 4285542742 4284686924 4283831879 4285081167 4284226635 4284356172 4284292428 4285475664 4285674587 4284026681 4284092989 4283370816 4283699519 4286067035 4283238473 4283962434 4287455365 4286070897 4283302461 4283899978 4286796440 4285738092 4286007421 4286664327 4288509863 4287324312 4287981208 4288316322 4286991763 4288706979 4288773536 4288509341 4284350533 4284158521 4288375935 4283105336 4285669192 4284685641 4282977349 4285339964 4286264399 4285340223 4283899211 4285672012 4283899198 4285865287 4287579976 4289362291 4285472583 4285733958 4284487229 4285339967 4284683577 4285406787 4287834953 4288428622 4288626253 4290857813 4291715155 4291124570 4291781222 4291584867 4291913572 4292110696 4288429389 4284747320 4287641178 4289087571 4289810003 4292308330 4292108643 4292307549 4292241001 4292373352 4292571751 4292700522 4292441706 4292898666 4292439910 4292833386 4293160558 4292376170 4292898671 4292505945 4292765287 4292699750 4292308073 4292505960 4292572780 4292570983 4292506987 4292504934 4292506474 4292899436 4292509038 4292508780 4292311674 4292771964 4292445295 4292905862 4292577155 4292839812 4292644472 4292776325 4292842376 4292776583 4293105543 4292844171 4292778638 4293106825 4293110414 4292718230 4293047443 4293114011 4292588703 4293442732 4293310888 4292984493 4293509806 4293970619 4293772212 4293904313 4294036926 4294036669 4294036412 4294036412 4294037183 4294036926 4294037699 4294301618 4292390832 4281860131 4289019985 4291781719 4291788388 4291263614 4291134067 4291005307 4291659126 4291265665 4290151025 4291002237 4290871163 4291593845 4290739578 4290017134 4290411372 4290542460 4290804077 4290476921 4290607992 4290608249 4290674041 4290541420 4290214267 4289556601 4289951099 4289491310 4289556336 4290341728 4291126364 4291390553 4293237112 4293772678 4293904542 4294038698 4293838219 4293902203 4293838476 4294036383 4293973159 4294038696 4294037904 4293838733 4293964666 4292053094 4291714122 4291058009 4290533464 4291318606 4289680224 4290596690 4289414226 4288693581 4289149257 4289612118 4289480533 4289677391 4288956746 4288295758 4288232016 4288167246 4289022546 4288955724 4289419104 4290008188 4287645781 4288561758 4288039767 4287974243 4288036699 4287447902 4288302691 4287450206 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283960640 4283501890 4283304255 4284025154 4284883529 4287979395 4290023317 4289893013 4290815666 4290815394 4290026390 4289957775 4287847019 4284748348 4284288818 4287048521 4290334798 4292111976 4293100653 4293694327 4293565819 4293370229 4293436024 4293370488 4293567111 4293436023 4293370488 4293370744 4293172856 4293694324 4292967274 4292050303 4291135382 4289811308 4285013062 4284815686 4283963464 4285211721 4284353350 4284488005 4283895099 4283766092 4285015373 4283763772 4283897157 4284819030 4286133592 4285411420 4283828541 4284490848 4283898429 4285672037 4285212502 4285540424 4285475419 4284819534 4283305279 4283833160 4284028227 4284227144 4286861175 4283959367 4283698502 4283897917 4284883031 4285146695 4283301954 4285675631 4286333031 4285215345 4286402954 4283568724 4286663804 4286860676 4285676136 4287583613 4285939559 4288376733 4287259544 4287060102 4286138234 4287588001 4289036707 4290025136 4286730368 4283499048 4288113563 4283238439 4285602879 4283567941 4283568440 4286065229 4285865535 4285736785 4284093499 4286393931 4285472325 4285931331 4284353847 4287050314 4286259783 4284489030 4284815934 4284024884 4285206070 4286456905 4287510351 4288757073 4289283661 4291250509 4291257184 4291977322 4291649886 4292046181 4291913567 4291321175 4288492619 4285011527 4288035148 4289746032 4290728532 4292371557 4292505443 4292108387 4292571752 4292571239 4292700525 4292899178 4292898666 4292441449 4292834669 4293095021 4292769885 4292506731 4292441706 4292766567 4291979359 4292571754 4292963165 4292897379 4292505704 4292505706 4292897881 4292834673 4292900445 4292442477 4292507243 4292508782 4292574060 4292509805 4292707460 4292642159 4292838785 4292970867 4292643466 4292775806 4292841603 4292776583 4293105799 4292776327 4292778379 4293106311 4292718229 4293044366 4293506443 4292655264 4293504673 4292982949 4293509293 4293443243 4293575600 4293838006 4293641906 4293839799 4293904313 4294036669 4294036412 4294037183 4294037954 4294036926 4294036927 4294169788 4293711032 4284678203 4288628304 4291585639 4291789674 4291397237 4290674558 4291790208 4290088060 4291199355 4291067516 4291134058 4291134069 4290542459 4291789938 4290608498 4291133565 4291068273 4290476921 4290739835 4290348145 4290607992 4290279800 4289819770 4290082925 4289622895 4289491309 4289754235 4290869369 4290472039 4291589476 4291257952 4292577142 4293307504 4293839246 4293966457 4293969299 4293902717 4293838220 4294037924 4294038694 4294038695 4294037157 4293903504 4293373030 4293033060 4290795345 4291124056 4291188312 4290728541 4289874772 4290005595 4289743182 4288495696 4289216589 4289677384 4289548118 4288625488 4288427596 4287179848 4288822350 4289154145 4288957524 4289942127 4289088099 4288432474 4288759898 4287186258 4288891509 4287253074 4288235875 4287380814 4288038501 4288237421 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283238466 4283697202 4283501881 4283894592 4284816454 4287519845 4289498013 4290025370 4290946721 4290160035 4290549916 4289826444 4288440434 4284881728 4285405502 4287045448 4290335055 4292309339 4293100910 4293300350 4293238151 4293436279 4293173375 4293369972 4293632131 4293173898 4293369971 4293566082 4293631352 4293298027 4292769896 4292709514 4292115849 4290080640 4284617535 4285738067 4284352828 4284884558 4283635785 4283960629 4283893322 4284358477 4284554823 4283437640 4286530159 4288106359 4285343303 4284752460 4284094788 4283764555 4284161348 4285739095 4284884045 4284754257 4285342795 4284554825 4284425036 4284751432 4283573074 4283962951 4285214285 4284489806 4283698243 4284091466 4284688198 4285016170 4282712634 4287717001 4285214310 4284489814 4287060097 4285739875 4282843948 4286604949 4287715747 4285744521 4286400149 4286934683 4288447151 4287982762 4285807719 4284487762 4286399344 4288770970 4290222273 4286196567 4286926965 4284225599 4285142088 4282975036 4284096330 4286391367 4285211465 4284355132 4284749373 4285801541 4286263116 4285405251 4284686924 4285141557 4285278797 4284488259 4284159302 4284880954 4285403963 4286785351 4287968590 4289083726 4290398798 4291120985 4291256412 4291582300 4291519842 4291650661 4291715431 4290597458 4286455622 4285012293 4288167515 4289611866 4290992731 4292110178 4292306793 4292241256 4292964458 4292441450 4292900204 4292439910 4292505447 4292899948 4292767337 4293097074 4292834413 4292833130 4292833388 4292633699 4292964716 4292505961 4292307555 4292505960 4292898925 4292898138 4292832862 4292898652 4292441196 4292897896 4292902513 4292902000 4292508525 4292509807 4292902505 4292446587 4292970093 4292772993 4292774771 4293169280 4292710789 4293170056 4292711304 4292776327 4292778123 4293108103 4292718486 4293502599 4292259995 4293112736 4292983465 4293049507 4293115047 4293443500 4293442987 4293313963 4293838006 4293641650 4293576113 4294036670 4294036412 4294037183 4294036155 4294037183 4294037183 4294037699 4294237629 4288368753 4289283409 4291391581 4292050781 4290871936 4291131505 4290939758 4291330430 4290216577 4290413939 4291134088 4291199603 4290216576 4290476923 4291265150 4290216560 4291133308 4290871412 4290936184 4290542199 4290542200 4290545266 4290016888 4290214010 4290344557 4289556603 4290278253 4289884268 4290804067 4291914602 4291260255 4292047188 4292905067 4293437035 4293244023 4293242996 4293832822 4293904268 4294037668 4293973159 4294037410 4294037395 4293903229 4293502841 4292309834 4291123039 4290597718 4290726992 4290859342 4289940053 4289807947 4288626000 4289215823 4288759380 4289808732 4289545038 4288298065 4287308869 4288032842 4288301136 4289810020 4289875557 4288366682 4288564562 4288628046 4287251294 4287383124 4288694102 4287906911 4288105045 4288303997 4287450976 4287514717 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284028211 4284027722 4283698243 4283565885 4284421445 4286729324 4289300117 4289501337 4290290611 4290814616 4291076000 4289759881 4288373619 4286395465 4285141307 4287048776 4290070350 4292506988 4292968813 4293301364 4293436021 4293566597 4293566851 4293566852 4293238909 4293436022 4293567111 4293567623 4293562488 4293104241 4292834665 4292378494 4292974207 4290598266 4284290363 4287909753 4283897405 4284553288 4283370820 4283437641 4283633478 4284619081 4285474640 4286991742 4287053663 4284555071 4284027467 4284223802 4283306571 4284226897 4285213783 4285671251 4285280090 4284554567 4284028998 4283897416 4285934166 4284556622 4284557135 4283110481 4284817996 4286728831 4283042118 4285672537 4283765822 4284885865 4285215581 4285544803 4285211727 4285080422 4286267494 4288047015 4282318926 4283106356 4288053932 4289378768 4287457686 4288974266 4287259269 4287456400 4287124868 4285346930 4284490849 4287853490 4287980695 4288314796 4287851179 4286332775 4289505747 4283236393 4284160068 4286457416 4284882765 4284751428 4285407044 4285865545 4285998406 4284226112 4285471296 4284750658 4285078852 4284750149 4284485433 4285206070 4286127684 4287707472 4287707217 4289215813 4291318107 4291579991 4291385692 4291584096 4291518304 4291977053 4291125336 4290071897 4285274947 4286786124 4288498000 4289350501 4291585379 4292239965 4292439401 4292373351 4292833386 4292832873 4292834413 4292898669 4292441194 4292835951 4292767596 4293093704 4292440170 4292831842 4293160285 4292832858 4292440426 4292700249 4292571753 4292373097 4292506201 4292242285 4292963156 4292439914 4292965228 4292442732 4292507499 4292508525 4292510319 4292706430 4292706173 4292510834 4292837499 4292773503 4292970367 4292774019 4292971641 4292776325 4292971902 4293106562 4292778124 4292779919 4293107591 4293044107 4292784537 4293111436 4293048732 4292652449 4293181352 4293310889 4293050029 4293773493 4293838005 4293904570 4293904313 4294036669 4294036412 4294037183 4294037183 4294037183 4294036412 4294036928 4294432946 4291332237 4289807955 4292441700 4291592563 4290605924 4289424485 4290673533 4290477681 4291000685 4291329905 4290674291 4290216562 4291070591 4291725166 4290807418 4290282624 4290282096 4291133307 4290282096 4290936711 4291068029 4289885302 4290410873 4290411128 4289622649 4290279545 4290411642 4290475385 4291260268 4291196772 4291719266 4291786074 4291721308 4291919713 4292972398 4292318050 4293439363 4293904267 4293972646 4294236582 4293972649 4294036863 4294033539 4293237349 4291455828 4291056471 4290727753 4290267995 4290464335 4289544789 4289348944 4288625484 4288693330 4289874267 4288693067 4288365646 4287902796 4287508295 4287118937 4289283668 4289748321 4288826711 4288563548 4288695913 4287841364 4288035421 4288037718 4288040549 4288105827 4287972444 4287383632 4287648359 4287116628 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284026682 4283436096 4283501881 4283238207 4283962423 4286990959 4288772231 4289632160 4290552220 4290816686 4291271570 4289694860 4288705663 4286722373 4285932361 4286325575 4290399308 4292309598 4292969069 4293300617 4293631356 4293370744 4293370229 4293697153 4292911486 4293042301 4293632132 4293371000 4293564267 4293298810 4292837485 4292112745 4292976527 4289944179 4285405770 4288238699 4284226119 4284553543 4283501646 4283569743 4284620367 4286465382 4287515759 4284948295 4284163405 4283701319 4283898952 4284029253 4283698759 4284094530 4285805418 4284883537 4286132831 4284423239 4284424780 4285081167 4285607510 4286198369 4285017169 4284357451 4283044423 4285739863 4285213783 4284292427 4283762763 4285017171 4288046238 4284420930 4283635272 4284620612 4284815953 4287260283 4285478517 4283436367 4283108677 4285415518 4286201473 4287918481 4287197617 4287983002 4285411936 4284617282 4284291940 4286599550 4288377521 4290027439 4289229745 4289110718 4288705668 4282712125 4284554308 4285603143 4284748086 4283437375 4286063684 4285143102 4284881477 4285143098 4284553279 4285143615 4284355129 4284750400 4284747572 4285535548 4286325577 4288031814 4289021002 4290070361 4291188821 4290927447 4291649883 4291323235 4291583840 4291584347 4291386207 4288558663 4284419647 4287706447 4288890188 4290796638 4292109666 4292241514 4292439144 4292571495 4292833130 4292900206 4292442202 4292898412 4292835165 4292770159 4292768619 4293160815 4292440167 4292898923 4292374633 4292505448 4292505705 4292765031 4292175208 4292373859 4293223775 4292898394 4292242021 4292572522 4292508268 4292899435 4292900718 4292510577 4292899949 4292640364 4292509550 4292511092 4292837755 4293362553 4292380534 4292839813 4293102196 4292841344 4292775551 4292776585 4292777607 4292647807 4292777870 4292784021 4293175436 4292260252 4293505176 4293442478 4292982692 4293575085 4293115825 4293573036 4293642420 4293904569 4293838776 4294036669 4294036669 4294036412 4294037183 4294036412 4294037183 4294036926 4294104005 4293642939 4290725447 4292247910 4291656797 4290015087 4288959841 4289096043 4288964458 4290080370 4290082161 4290606702 4290936188 4290674284 4291199863 4290742132 4291594115 4290870908 4290085244 4290807677 4290544500 4290153065 4290739336 4290282603 4290151026 4290213497 4290083437 4291064427 4291396202 4291197796 4291526514 4292181346 4292180067 4291261278 4291912788 4291194451 4292838256 4293243762 4294101903 4294171305 4293972904 4294038420 4294100628 4293506682 4292971117 4291846993 4291056205 4290793303 4289875799 4289544264 4288759638 4289150543 4288101203 4289677137 4289348431 4289479758 4288428110 4287375941 4287247953 4289347667 4288761689 4289876839 4289153119 4288431181 4288430941 4287380811 4287513953 4287315795 4288037979 4288171621 4287972184 4288370802 4287052875 4286853709 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283829312 4283501875 4283697210 4283700035 4283632963 4286332250 4289036429 4289565853 4290683806 4289763491 4290025107 4289825932 4289230198 4286659157 4285338175 4287572295 4290069329 4292571211 4292773490 4293495934 4293565557 4293566082 4293435765 4292976251 4293501816 4293632132 4293370487 4293566853 4293565558 4293627775 4292969326 4291716195 4292973702 4289949804 4285930313 4287516269 4285014089 4284224322 4284289850 4283898190 4284489808 4284816452 4284357444 4283966029 4284619843 4284226380 4284026692 4284554828 4284224585 4284096592 4285146451 4285411669 4285739619 4284751688 4284097350 4285279065 4285080660 4284555077 4285278039 4285343052 4285079624 4285805147 4284421186 4283699520 4282975304 4285610853 4287059840 4284421444 4283434568 4283897172 4285150554 4287787178 4286987624 4285348210 4283700047 4284029764 4283700803 4283699541 4286073717 4288714415 4287061907 4283699537 4284488016 4285674097 4285217642 4288574374 4291147964 4289899696 4284290368 4284222774 4285143102 4286194244 4283962958 4284485169 4286391114 4285278035 4284881471 4284227404 4285405759 4284353600 4284027962 4284814905 4285468477 4285339197 4286787403 4287966793 4288692299 4291448660 4290991195 4291515482 4291584347 4291781989 4291583840 4291715677 4291187792 4286454857 4284816717 4288038735 4289283170 4292043357 4292174688 4292963677 4292109667 4292571496 4292898922 4292439910 4292898411 4292441706 4292832618 4293161582 4292771953 4292834155 4292833129 4292767596 4293161567 4292769136 4292900191 4292441692 4292571498 4292373092 4292439654 4292835185 4292897121 4292506987 4292506473 4292899692 4292507755 4292507242 4292510320 4292901488 4292903277 4292509295 4292445554 4292641921 4292707954 4292446068 4292839301 4292382591 4293168768 4292775812 4293171079 4292778895 4292845452 4292781714 4293110670 4293109899 4292653733 4293047710 4293048743 4292982692 4292983977 4293247656 4293705393 4293970361 4294036926 4294036669 4294036669 4294036412 4294037183 4294037183 4294037183 4294037183 4294037184 4294236092 4291257708 4292313189 4290735962 4288039755 4287907151 4289157726 4288827218 4289159264 4289093479 4289031288 4289424227 4290540154 4290080631 4291068026 4290870125 4291199870 4291528310 4290479235 4290610548 4290478722 4290217074 4290476411 4290476923 4290673785 4290476915 4291265662 4291592304 4291921787 4291789409 4291985266 4291787356 4291394912 4291323747 4291395178 4292182632 4293638545 4294038438 4294170790 4293973160 4294037909 4294101399 4293438048 4292967507 4291321431 4291120465 4290270551 4290071125 4289480531 4289348428 4288558413 4289545550 4289809506 4288824652 4287771211 4287378767 4287311947 4288693066 4288169038 4290006886 4288235610 4288893026 4288301913 4287971933 4287445588 4287316832 4288825433 4287253078 4287514185 4287515499 4287578975 4287382093 4285801030 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283829567 4283698494 4283697467 4283436858 4283567173 4286991469 4289233822 4289630604 4289895076 4290289316 4290616990 4289564815 4288639356 4286726230 4285800262 4286915655 4290332748 4292307556 4292969327 4293299313 4293171581 4293632128 4293566851 4293632389 4293369973 4293566596 4293370488 4293566077 4293564797 4293627769 4292903005 4291913832 4292575089 4289685386 4285998666 4286987355 4285278806 4284096324 4283896651 4283699768 4284159547 4284423240 4284488773 4284358470 4283766351 4284291130 4283833159 4284818520 4283503173 4286003293 4284619849 4286196575 4284227142 4284424287 4284949845 4286992751 4285606742 4283765826 4284292429 4284225855 4285147470 4284552767 4283636291 4283566413 4283697976 4286796409 4284423239 4284620616 4283898953 4283896146 4286925444 4288443555 4288445096 4284687699 4286529396 4284422989 4284620877 4283108685 4283698750 4286997895 4289565621 4283764283 4284357977 4287125381 4286924924 4285213266 4288579485 4287650942 4283039792 4284684864 4285668926 4285209664 4283434802 4284945981 4285735496 4284357187 4284355128 4284550976 4284878388 4284026683 4284551483 4285340992 4285273405 4285537604 4287770439 4287576147 4290070601 4291121232 4291579996 4291451219 4291385179 4291584102 4291256414 4291649621 4289018193 4284488262 4285933125 4288887632 4290269522 4291913830 4292306782 4292571755 4292637288 4292374635 4292440167 4292898666 4292833129 4292832873 4292834413 4292769384 4292833899 4292377195 4293160559 4292768347 4293096801 4293095774 4292767597 4293226607 4292831837 4292505946 4292505707 4292831826 4292899182 4292505192 4292508269 4292901231 4292442219 4292965998 4292510064 4292510063 4292508013 4292707183 4292968058 4292837755 4292838251 4292840070 4292971898 4292841345 4292776311 4292843899 4292383629 4293172357 4292712331 4293108618 4292715922 4293044619 4293505960 4292653990 4293048986 4293376940 4293181618 4293247142 4293903798 4293378999 4293904312 4294036669 4294036669 4294036412 4294036412 4294037183 4294036926 4294037183 4294036927 4294171071 4292845724 4292242507 4288628558 4288759114 4286918734 4287975756 4287969616 4287842379 4287712073 4288958546 4290011242 4289030499 4289685866 4289425520 4289948793 4290608506 4290082681 4291002492 4290477164 4290345336 4290542203 4290284923 4290476667 4290345580 4291329390 4291066477 4291922814 4291724389 4292707956 4292113746 4292245846 4291521884 4291458390 4292113511 4292053350 4293904520 4294037668 4294171046 4293973162 4294036607 4293837456 4293040224 4292046947 4290991440 4290728272 4290135117 4289610308 4288757838 4288755277 4288693072 4288890448 4289152076 4288560975 4287440969 4287442760 4288559950 4288563305 4288959333 4288892760 4289086544 4288431960 4288693856 4287312980 4287974231 4288628310 4287843942 4288959082 4287449430 4287647843 4287183437 4286326601 4286062664 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283829563 4283501877 4283501877 4283696967 4283962946 4287052645 4288312195 4289565842 4290290599 4291341740 4290815395 4290222743 4288770932 4286591312 4285801286 4287048010 4290132549 4292178025 4292575326 4293759105 4293697659 4293171585 4293631616 4293370229 4293435508 4293632903 4293370486 4293567367 4293565302 4293561980 4293428059 4292306522 4291125600 4289290875 4285935182 4287515254 4286195275 4283695687 4283569219 4284029255 4284554826 4284885585 4284226112 4284621903 4284227140 4284094533 4283634503 4284357194 4285147737 4285278283 4284754776 4285344590 4284162122 4283636812 4284952913 4285938020 4285608013 4283831364 4284028224 4283763023 4284752456 4284359500 4283829822 4284156226 4284224836 4286270585 4283894068 4284751698 4285740641 4284027468 4285409118 4287787937 4287915674 4288773547 4283962681 4285804373 4284161367 4282910271 4284357703 4285149280 4285348180 4284950372 4283960896 4287193751 4288376470 4287121288 4288178814 4286530661 4283760693 4285798718 4285997894 4284550712 4283899461 4284684607 4285075761 4284947522 4285013316 4285075764 4283631670 4284483638 4284813621 4285535806 4286066508 4286195271 4287967818 4289412423 4290860891 4291122012 4290992462 4291449946 4291388767 4291453790 4291387229 4291123538 4287637318 4284028487 4287247438 4288627280 4291913314 4292636266 4292439396 4292240989 4292175209 4292571495 4292898922 4292441450 4292899948 4292834412 4292375401 4293163122 4292834155 4292770416 4293161309 4292767596 4292767083 4292770674 4292832087 4292374634 4292897635 4292505707 4292505960 4292897391 4292440154 4292571994 4292504936 4292506729 4292966512 4292443759 4292901743 4292706688 4292510063 4292509551 4292904305 4292642676 4292445042 4292641152 4292644474 4292841345 4292775552 4293103748 4292777357 4292776844 4293105286 4293040262 4293108877 4292783251 4292718485 4293111711 4293047723 4292981916 4292983468 4293509557 4293510585 4293707441 4293904313 4294102461 4294036412 4294038211 4294036412 4294037183 4294037954 4294036926 4294037697 4294104263 4293641136 4289548890 4287771727 4286919758 4286586440 4287904074 4286458440 4287706962 4287575121 4287382863 4287184973 4288562508 4288499542 4289286246 4289095783 4289816156 4289096044 4289555306 4290082428 4289885562 4290017145 4290214507 4290739320 4290348929 4291396736 4291988329 4292119163 4291990388 4291720278 4291524702 4290867033 4291652191 4291916126 4291722332 4293438085 4294166673 4294038438 4293972902 4294038187 4294101634 4293769069 4292643679 4291912538 4290662736 4290529348 4289215563 4287641424 4287900743 4287641166 4289086033 4289088077 4289019982 4287377225 4287048006 4287444046 4287707725 4289222242 4290005345 4288300127 4288432217 4288040293 4287842646 4287970644 4287775839 4289484652 4288697956 4288103519 4287515734 4287183702 4286855248 4286063944 4285143874 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283697462 4283567421 4283369781 4283238713 4284353860 4285408575 4288048269 4290683030 4291341236 4290620074 4290751141 4289829529 4290478462 4286989655 4285865797 4285865542 4290331733 4292240972 4292901998 4293167219 4292908923 4293302896 4293239947 4293435507 4293239182 4293041785 4293567111 4293698938 4293499512 4293563502 4293494637 4292637805 4291322977 4289091962 4286526818 4286791516 4286921566 4283043142 4283633471 4284226112 4286000731 4284159554 4284418374 4283570496 4284290123 4283832397 4284292172 4285803338 4285673826 4283635784 4285411161 4285540693 4283308625 4284358213 4285803112 4284818759 4286657634 4284227659 4284554565 4284225088 4284026421 4283959622 4284620873 4283501895 4284554832 4284226120 4283831877 4284429691 4285280606 4288311989 4287320724 4286729873 4288577691 4289306294 4285084273 4283894597 4285414499 4286397822 4283699003 4285146188 4284554566 4284093262 4284750407 4288247727 4285277519 4287452790 4288968356 4284880451 4284091960 4284685379 4285930047 4283369786 4284618040 4285407049 4284159558 4284290373 4284027704 4284289595 4284353596 4284551990 4285075769 4285340743 4286917706 4287639881 4288164943 4289940298 4291647315 4290991445 4291319900 4291842653 4291647062 4290928218 4291780183 4289609545 4284022846 4285998665 4287969359 4289808728 4292307290 4292306788 4292241253 4292373604 4292439145 4292571751 4292897130 4292899174 4292377196 4292834156 4293163365 4292771442 4292375402 4293226092 4292375916 4292834157 4292769886 4292834414 4292834671 4292898908 4292832101 4292832859 4292897380 4292506204 4292897381 4292505705 4292965999 4292505193 4292507998 4292505946 4292509041 4292442458 4292901747 4292510064 4292509551 4292706670 4292643961 4292839279 4292839559 4292774516 4292971643 4293038469 4293104252 4292778119 4292776588 4292780430 4293107847 4292717973 4293114002 4292717456 4293047980 4293046950 4292982948 4293247658 4293640878 4293708222 4293970104 4293576634 4294036669 4294036412 4294036412 4294037183 4294036926 4294037697 4294037441 4294038971 4294039499 4290071632 4286654022 4288297038 4287049290 4287709789 4286654024 4286588485 4287114312 4287705163 4287575376 4287511120 4288036172 4287384142 4287315789 4288040019 4287908176 4289223012 4288700777 4288701799 4289357685 4289686653 4290083194 4290148216 4291330930 4291528563 4292121479 4292120688 4292052859 4291393120 4290732113 4290865500 4291651669 4292119149 4293834902 4294036364 4293973161 4294236587 4294038659 4293969026 4293500010 4292901203 4291190357 4289938761 4288954194 4288296783 4287375176 4287314002 4288951885 4288956491 4289676619 4287773010 4286980933 4287509839 4288625742 4288563280 4289222007 4288365644 4287709779 4288628825 4287843170 4287971923 4287907422 4288039254 4287844707 4288829027 4287319135 4287711585 4286724170 4286526032 4285207867 4286194506 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283369781 4283369782 4283435836 4283369786 4283438142 4285210715 4288704902 4290157462 4290748318 4290620332 4291209637 4290550930 4289693588 4287781980 4285666372 4286654026 4289805383 4291913812 4292967540 4292971379 4293367667 4293303944 4293237622 4293632389 4293436279 4293237621 4293566592 4293698939 4293500285 4293562734 4293492842 4292704349 4290796129 4289027706 4286985042 4286662236 4287250282 4283500610 4283503427 4285014607 4285340220 4284093516 4283963973 4284355916 4283898186 4283831885 4284029760 4286200166 4284292170 4283767370 4286198367 4284226635 4283899725 4284030286 4285739596 4285539925 4285475916 4284883790 4284489289 4284094010 4283702613 4284029252 4284686408 4284751946 4284489030 4283239756 4285082704 4286338442 4282318915 4285940840 4287916697 4286071665 4288573361 4287522444 4289834434 4285413754 4284488280 4285279834 4285410138 4285805419 4287053948 4285804894 4287189885 4289571757 4283761477 4285145668 4286003532 4284881474 4284550968 4285929790 4284288058 4283698490 4285210691 4284552511 4283895609 4284553791 4284684359 4284092989 4284287802 4284418100 4285999695 4285536576 4287771981 4287836236 4288758346 4291449941 4291056729 4291453016 4290993745 4290925396 4291386718 4291191389 4290662477 4286257731 4283762748 4286853716 4288496985 4290732129 4292242531 4292505189 4292042837 4292964443 4292175459 4292175208 4292505959 4292441450 4293225836 4292768876 4292768622 4292835439 4292833626 4292833132 4292439640 4292836210 4293094237 4292766808 4292898667 4292373863 4292832101 4292832859 4292506221 4292109392 4292964444 4292307562 4292440155 4292964190 4292508014 4292966770 4292441962 4292900977 4292835935 4292901483 4292509808 4292444015 4292903036 4292839042 4292971124 4292839558 4292774516 4292776326 4292777601 4292776072 4293172105 4292711052 4293106310 4293108620 4293112207 4292784293 4293047452 4292982185 4293179562 4293311665 4292984236 4293576120 4293970105 4293576635 4294102205 4294036669 4294036412 4293710274 4294036155 4294036926 4294038468 4294037442 4294499778 4290475124 4286719558 4287511889 4288101197 4287447119 4287574604 4287641425 4287051086 4286461006 4287181902 4286591306 4287116623 4287181646 4287181134 4287772496 4287116368 4287053646 4287578957 4287579980 4287449175 4288043094 4289027430 4289883762 4290871166 4291331694 4292252288 4292118888 4291788386 4291395947 4291856997 4292183134 4291656799 4292315509 4294099833 4294037928 4294236584 4293973142 4294102422 4293571191 4292839009 4291716176 4290267460 4289217360 4288426569 4287441737 4287443273 4287968846 4288235344 4288955982 4288821070 4287377995 4287572040 4287774029 4289284960 4289220450 4289352555 4287710282 4288432227 4287974233 4288628311 4287250262 4288105048 4288500587 4288764785 4287974764 4288302435 4287053910 4286919766 4285999689 4285798720 4285799491 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4283567178 4283699508 4283304246 4283304245 4283499582 4284620356 4288771470 4290286733 4290684594 4291143585 4291341480 4290485663 4289041283 4288833137 4286258754 4285932874 4289346119 4292239965 4292116585 4293102457 4292974719 4293302138 4293304442 4293237639 4293042558 4293631617 4293502343 4293698681 4293501058 4293561465 4293560172 4292769632 4288952133 4289755531 4287575405 4287909992 4286200927 4283367999 4283371070 4285145929 4284222787 4283832902 4284357180 4283503427 4283634759 4284225599 4286266215 4285736787 4283635020 4284095295 4286135653 4284554322 4283768655 4284292422 4285018458 4285540179 4285935969 4284620874 4285804379 4285209675 4283501876 4284485454 4284225092 4284227659 4284817996 4284686153 4284490310 4284162114 4283237954 4283239748 4286994327 4285675119 4287521681 4288176534 4288251040 4289695926 4288114081 4283631672 4285413233 4287387263 4288309396 4288507271 4285273144 4285796661 4283636025 4284290118 4284224572 4285144134 4285803081 4284424783 4284486451 4284486457 4285210691 4284223289 4284420667 4284093755 4284680506 4284289594 4284421701 4284813619 4285798723 4285735496 4288166222 4288100174 4290201677 4291188570 4291059282 4290994266 4291579745 4291387742 4291058521 4291122249 4288295500 4283695165 4284682555 4288298834 4289285972 4292110946 4292896598 4292569443 4292439141 4292308074 4292830818 4292506216 4293028461 4292439910 4292834669 4292834670 4292766550 4292836209 4292767339 4292767598 4293159771 4292768877 4293096554 4293160815 4292310636 4293619040 4292767322 4292831846 4292898394 4292373607 4292109663 4292571754 4292962645 4292439899 4292573809 4292439382 4293228917 4292833643 4292441964 4292510321 4292509808 4292902765 4292641391 4292641133 4292969084 4292579451 4292840054 4292776064 4292971646 4293172355 4292318853 4293565057 4292712332 4292780175 4292783508 4292782735 4293111455 4292982951 4293181095 4293050289 4293706928 4293182129 4293641658 4293970105 4293708221 4294036669 4294036669 4294101691 4294037183 4294036926 4294037697 4294037441 4294302658 4292124310 4286455869 4287510096 4288102226 4288168785 4288104539 4287972175 4288033869 4288100432 4287576652 4287115854 4287179077 4286787401 4286260550 4285735494 4286461005 4286392393 4286458441 4285869901 4286525004 4286326858 4287186510 4287449425 4289620570 4291128422 4291063123 4291854693 4291987821 4292846706 4292646758 4292117358 4292314475 4292714868 4294036109 4294038439 4293973160 4294038680 4293901694 4293368179 4292375893 4290860371 4289346377 4287967306 4286521927 4286585415 4288163654 4287770955 4289085265 4287771211 4287969358 4287443281 4287246923 4289218653 4288960612 4288564309 4287706954 4287906902 4288761190 4287972957 4287250260 4288627788 4287908441 4289548390 4287844971 4288234849 4287449941 4287841113 4286395469 4285275973 4285471293 4285275461 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284943934 4283566907 4283632437 4283829812 4283829056 4285013570 4288311171 4289502111 4291338661 4291079605 4291276448 4291009436 4289566359 4289098611 4285471557 4286653766 4288953674 4291650907 4292967533 4293234552 4293300610 4293697402 4292909954 4293501300 4293436281 4293369971 4293567624 4293567624 4293565306 4293566329 4293429614 4291845728 4286588493 4289950091 4287513952 4286856030 4286528096 4283238462 4285015631 4284489285 4284026692 4284028483 4284091719 4284025924 4284095049 4286860150 4284881986 4284884301 4283567174 4283700298 4286266981 4284358729 4284093762 4284096592 4286459495 4285276228 4285936983 4285278297 4285277514 4284884560 4284489029 4283567674 4285606224 4284290367 4284622672 4285015631 4283896908 4283699011 4283505744 4284555084 4283303733 4287191967 4286729103 4288114074 4287985589 4288180896 4289436597 4287057547 4289493676 4287581572 4287055206 4287913863 4286402690 4284553274 4283634499 4284027186 4284552505 4285144391 4285801032 4284157239 4283896636 4284422475 4284618044 4284353344 4284090170 4284223285 4284353596 4284288058 4284549952 4285010745 4286587466 4287244614 4288363602 4289347144 4290857289 4291059289 4291382863 4291517023 4291320404 4291059028 4291320652 4290065740 4283957300 4283829815 4286917709 4289086811 4290928222 4292501597 4292765536 4292505948 4292571483 4292765027 4292308073 4292505703 4292833385 4292900461 4292439910 4292833130 4293161072 4292767338 4293161565 4292768877 4292770672 4292833899 4292377454 4292832603 4292833886 4292700771 4292833390 4292834911 4292505452 4292505947 4293290069 4292505963 4292113258 4292964206 4292506972 4292570731 4292508765 4292508522 4292966255 4292506986 4292509808 4292903021 4292444016 4292443759 4292642673 4292838529 4292775037 4293166979 4292776581 4292775811 4292843150 4292710535 4293108107 4292779148 4293176462 4292783764 4292719783 4293111196 4292982438 4293574827 4293245874 4292984235 4294101692 4293641648 4293839807 4293904055 4293708221 4293710531 4294101691 4294037183 4294037697 4294037441 4294104251 4293970363 4287308618 4287969103 4288694098 4287909459 4288760408 4287971921 4287972177 4288628816 4287903833 4287511631 4287640910 4286655563 4286853194 4285867336 4285602624 4285667906 4285408071 4285207095 4284683063 4284816452 4285211212 4286458188 4287511887 4288762453 4289614678 4292116838 4292654214 4293311627 4292981100 4291855973 4292316023 4293701487 4293905057 4294038437 4294038700 4294036115 4294098285 4292842095 4291715654 4290004296 4287770186 4286063943 4286257736 4286718535 4287510351 4288690254 4287312203 4287574089 4287443019 4287970639 4288497488 4289091182 4289221214 4288498021 4287907935 4288035404 4287380309 4287447124 4288039010 4287904597 4287973719 4287844976 4288895335 4287384415 4287712599 4286789720 4285932358 4285800003 4285471550 4285536318 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4284619327 4284945207 4285274690 4285472836 4285209415 4285212241 4289292920 4289501334 4290684842 4291276455 4291145640 4291208354 4290026906 4288770165 4286129991 4286522953 4289348431 4292110430 4292116328 4293102458 4292973943 4293237378 4293502072 4292910461 4293303931 4293238154 4293371002 4293372028 4293566083 4293564530 4293626479 4290926678 4286852176 4289756545 4286394976 4285604943 4285341520 4283108935 4284949836 4283634761 4283830844 4284489023 4283239741 4284225613 4285541970 4285998414 4283635278 4285343831 4284359238 4283898954 4285542753 4284160585 4283174730 4284753484 4286002262 4284555340 4285343053 4284687179 4285474912 4284224067 4285213011 4285278542 4284096069 4283240008 4284222795 4284884041 4284753998 4284095046 4284490314 4283897410 4283500105 4283569743 4286402954 4288045479 4288513951 4288974261 4286860684 4289628841 4287387519 4287253633 4286792317 4284817484 4287912834 4286136184 4283697209 4283960644 4284945720 4285277001 4284485176 4284683837 4284226886 4285145930 4284292172 4283503675 4285078848 4284025660 4283699508 4284681283 4284418867 4285469755 4286326088 4286984268 4288756817 4290005065 4291120725 4291581026 4290926165 4291516501 4291319645 4291124812 4291446605 4285471043 4283828287 4285076035 4288036431 4290598245 4291846759 4292176994 4292373349 4292571243 4292505962 4292897635 4292505960 4292505703 4292898924 4292439910 4292964459 4292440168 4292766807 4292834670 4292441194 4292834412 4292832360 4292837490 4292832361 4292836210 4292768862 4293095537 4292833884 4292833133 4292440410 4292700777 4292244072 4292307547 4292964446 4292439898 4292963420 4292505450 4292572267 4292571753 4292507757 4292575858 4292576886 4292509553 4292904306 4292970353 4292969341 4292576881 4292969323 4292383362 4292578425 4293103231 4293169026 4292712583 4293106053 4292387990 4292779662 4292783507 4293175176 4292719269 4293046949 4292983727 4293115033 4293706933 4293509805 4293510328 4293642427 4293774013 4294102461 4294101948 4293709503 4294037183 4294037697 4294037698 4294037687 4294302146 4289092702 4287181385 4288039505 4288760158 4288564832 4288629844 4288631384 4288629087 4288562761 4287904335 4287970896 4287575888 4287770696 4286851913 4285933386 4286194249 4285143360 4285076792 4283699016 4284552242 4284025651 4284422719 4285668682 4287444300 4290275178 4293112202 4294034316 4293376901 4293242227 4292515942 4292382826 4293768839 4294101902 4294037671 4294038660 4294100356 4293308275 4292575049 4289940305 4287572044 4287836743 4285667656 4286849096 4287179847 4287574603 4287445073 4287640652 4287048777 4287510860 4287906893 4289021295 4289748573 4288829021 4288037978 4288102987 4287448152 4287575381 4287579222 4288101460 4287186517 4289351780 4288501085 4287975280 4287515999 4287183705 4286396237 4285602368 4286261066 4285470013 4285470782 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4285207611 4286459727 4287050573 4286393418 4285866051 4286853980 4288044396 4290286991 4291209388 4291277988 4291669939 4291277226 4290421148 4289096560 4285934150 4286522694 4289348431 4291452763 4293033588 4293101163 4292580743 4293696891 4293435765 4293501817 4293107323 4293042302 4293633903 4293566855 4293371256 4293693049 4293299570 4290005340 4287772755 4291069844 4287773277 4285473614 4285080650 4283500867 4285212244 4283370556 4284225862 4284029258 4285802838 4285146186 4284158272 4284029514 4283899718 4285606223 4284025660 4283832397 4284095048 4286001242 4283763776 4285411417 4285607511 4285343832 4284686924 4285211466 4284752715 4284949071 4284359244 4284883019 4283763003 4284224839 4283238459 4283437895 4286526809 4284683339 4283962434 4285345370 4284095047 4283832395 4283631932 4285808759 4287915673 4288979637 4288054960 4287722657 4288576426 4285279838 4287387804 4289163413 4289759134 4286789212 4283173942 4283961154 4285340734 4284750146 4283828282 4284552251 4284550451 4284091706 4284159027 4284025666 4284025658 4283764276 4284746563 4284486458 4285207865 4286391114 4287771209 4288362831 4289217609 4290858582 4291449425 4291317840 4291582038 4291318868 4291125332 4291449935 4286584899 4283500354 4284550967 4287116361 4290137943 4291912030 4292504145 4291912547 4292637276 4292571483 4292307812 4292897635 4292505704 4292897388 4292832600 4292898924 4292439912 4292440167 4293160814 4292834668 4292441194 4292835695 4292768619 4292769903 4293161053 4292768620 4292769136 4293159771 4292375130 4292768111 4293224286 4292832860 4292831845 4292897629 4292505449 4292508785 4292505434 4292964190 4292505192 4292508528 4292963419 4292506458 4292575859 4292573019 4292444275 4293034348 4292379763 4292904577 4292773745 4292970367 4292970110 4292972415 4292318346 4293104007 4293042572 4292779917 4293172617 4292717971 4292784021 4293113247 4293047722 4293048740 4292983469 4293313194 4293182130 4293576119 4293641656 4294168254 4293510327 4294036669 4294037440 4294036412 4294036926 4294037697 4294037443 4294433717 4291135888 4287048785 4287973197 4288694367 4289092444 4288957273 4288630870 4288499039 4288433751 4287974237 4288430924 4287971159 4287510095 4287837261 4286331729 4285997127 4285340739 4284357445 4284945470 4283568456 4283829048 4283306565 4283696704 4286855254 4293105272 4293641109 4294165890 4293708161 4292848225 4292639838 4292975222 4294034556 4294038422 4294038444 4294037637 4294099331 4292582238 4291649353 4288099919 4287177798 4285668424 4286455880 4287309639 4287640652 4287575374 4287641423 4287112262 4287047747 4287904864 4289155177 4289090901 4288501097 4288759656 4287447635 4286985814 4287642188 4287644513 4287050316 4287449175 4288693353 4288502624 4288631668 4288827493 4287514719 4287249228 4285801032 4286197323 4284945726 4285538888 4285799491 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287773262 4288298575 4287576911 4287771983 4287184470 4287055710 4288307317 4289496976 4291404190 4291669670 4291999918 4291210401 4290355099 4289493624 4287053142 4286457414 4289413973 4291779923 4292246119 4293037179 4293366905 4293436791 4293303690 4293043063 4293236864 4293632132 4293568882 4293765762 4293237369 4292976499 4292969579 4290137188 4289282913 4290150788 4289088631 4284753231 4284224316 4284224329 4284686922 4284226893 4284489031 4286333546 4285147469 4284421445 4283964479 4284027206 4283965511 4284817997 4284490321 4284030281 4284226379 4285475674 4284423236 4285738840 4284685899 4285082455 4285475411 4284819283 4285345884 4285277255 4283898430 4283962949 4283899210 4283897417 4284487235 4284026435 4283567928 4285409882 4284225856 4286727527 4285080403 4283962947 4283765571 4282779459 4286135137 4288706998 4288510884 4288317884 4288578228 4287058321 4287390352 4286921575 4288237147 4289295522 4283303737 4284291398 4285210437 4284224831 4284422205 4283963449 4284027200 4284025152 4284420668 4284484660 4283632706 4284226882 4284617274 4284352569 4285602628 4287903565 4287312460 4288757582 4290464335 4291188823 4290991702 4290990671 4290994525 4291450958 4291517522 4287637830 4284682040 4283763002 4285930818 4288954966 4291582806 4292570216 4291714646 4292505195 4292373349 4292373348 4292308067 4292897380 4292507243 4292505447 4292898924 4292439912 4293228126 4292767595 4292767849 4292767595 4293225306 4292704623 4293161838 4292835694 4292376940 4292835696 4292833369 4292770417 4292834674 4293224777 4292374893 4292439898 4292898909 4292440171 4292505705 4292898651 4292505452 4292442204 4292964206 4292505176 4292506732 4292574832 4292572779 4292509041 4292573275 4292444274 4293231722 4292380290 4292643446 4292773248 4292970366 4292578427 4292841846 4293038729 4293106822 4293106566 4292648590 4293569946 4292715406 4293044634 4293048744 4292981927 4293443250 4292982955 4293510827 4293575864 4293707449 4293641656 4293839550 4294102461 4293838262 4293709503 4294037954 4294036155 4294037698 4294170047 4293377452 4287245123 4287381072 4287843912 4288562525 4289420128 4289679454 4289419872 4289025382 4288563794 4288694879 4288105819 4287511383 4287053902 4286724440 4287049800 4286062152 4285407300 4284812594 4284224562 4283372365 4283239232 4283369788 4288755017 4293043572 4294100882 4294036099 4294298247 4292644965 4292050776 4293176966 4293970577 4294035858 4294037912 4294166404 4293702017 4292309831 4287048009 4286718023 4285800008 4285929541 4286391112 4286656586 4287771980 4287116364 4287180361 4286524486 4287446624 4288496971 4288893528 4290076285 4287975254 4287445587 4287052383 4287773791 4287052119 4287051085 4287642190 4287380817 4288436328 4289223797 4288765812 4288040802 4286989909 4287314013 4286395212 4285933898 4286261321 4284814907 4286195017 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4287579990 4287514457 4287578710 4287578709 4287580514 4287450207 4288768125 4289562511 4290748833 4291145641 4291801762 4291210658 4290290078 4289955449 4287580509 4286459467 4288824660 4291977046 4292247659 4293298292 4292973946 4293697409 4292912002 4293501560 4293632387 4293173373 4293371519 4293831797 4293566080 4293696377 4293164651 4290140000 4288760931 4290212486 4286793830 4286657110 4283369796 4284092739 4284028475 4285408845 4284686924 4284620618 4284357445 4284160060 4284227143 4284355651 4284554569 4284226114 4284552775 4283965512 4284488772 4284489032 4284885325 4285542241 4284224066 4285279833 4285936992 4285608033 4285211722 4285278296 4283765565 4284292172 4283962687 4283503170 4284556622 4284818248 4283173189 4285079625 4285871457 4285279829 4285013831 4284686409 4284027989 4284357704 4285148262 4285674327 4287456415 4289103009 4289963954 4288709294 4286529665 4286596471 4288249004 4288178312 4283699519 4284686924 4284420413 4284158778 4284158778 4284224320 4284226111 4284028986 4284092981 4283698236 4283894069 4284550709 4284681787 4285534780 4287049289 4287575116 4287835721 4289413963 4290858069 4291123536 4291517275 4291515739 4291059027 4291123024 4287307588 4283236408 4284749115 4286261842 4288757582 4291189334 4291847267 4291911767 4292372832 4292439146 4292439125 4292373604 4292963181 4292440154 4292899950 4292506986 4292898666 4292505703 4292439912 4293161069 4292767849 4292833386 4292374375 4293163378 4292375400 4292834156 4292834155 4293096302 4292768621 4292835696 4292832859 4292440171 4292898660 4292901745 4292439913 4292898138 4292831843 4292833389 4292505433 4292899953 4292505433 4292571242 4292570727 4292573292 4292507499 4292902001 4292508527 4292509808 4292641136 4292838252 4292970370 4292772714 4292772991 4292841601 4292971386 4293105283 4292384658 4293038215 4293435009 4292646540 4293110669 4293047198 4293047197 4293048230 4292983468 4293181357 4293050550 4293641655 4293314228 4293707193 4293839549 4293773757 4294036669 4294037183 4294036412 4294037183 4294037699 4294103984 4293974213 4288693587 4287312205 4288103773 4288565333 4289683305 4288237660 4289681249 4288892495 4289025118 4288628306 4288104531 4287511886 4287579726 4287773536 4286788172 4286461519 4286129479 4285474381 4284226629 4284288312 4283961151 4283500607 4289150034 4292843875 4293772168 4293903743 4293640063 4293171561 4292582000 4293505924 4293902717 4294035842 4294099075 4293636469 4291524183 4288886858 4285928775 4285930568 4285602882 4286522696 4286851655 4287772237 4287111753 4286654791 4287179590 4287575129 4288628557 4289220973 4289157994 4288564315 4287381332 4287051606 4287182414 4287116364 4287116364 4287641687 4287513172 4288039278 4289420908 4289291635 4288564842 4288107629 4287643475 4286658645 4286921560 4286457414 4286063431 4285277259 4286129735 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 4278190081 ) offset: 0 @ 0! ! !TestDeviceImplementor methodsFor: 'private' stamp: 'dgd 8/9/2004 21:12'! scaledLenna | lenna result warpBlt | lenna := self lenna. self extent = lenna extent ifTrue: [^ lenna]. "" result := Form extent: self extent depth: 32. warpBlt := WarpBlt current toForm: result. warpBlt sourceForm: lenna. warpBlt cellSize: 2; combinationRule: Form over. warpBlt copyQuad: lenna boundingBox innerCorners toRect: (0 @ 0 extent: self extent). "" ^ result ! ! !TestDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:34'! close "private - close the receiver" opened := false! ! !TestDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:34'! isOpened "answer whatever the receiver is opened" ^ opened! ! !TestDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 7/28/2004 17:34'! open "open the device represented by the receiver" opened := true! ! !TestDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 21:18'! applyParameters: aCollection "apply the (possible changed) collection of parameters" aCollection do: [:parameter | parameter name == #extent ifTrue: [self extent: parameter value]. parameter name == #type ifTrue: [type := parameter value]. parameter name == #isShowingTime ifTrue: [isShowingTime := parameter value]]! ! !TestDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 20:16'! parameters "answer a collection of parameters to configure the receiver" | extentParameter showTimeParameter typeParameter | extentParameter := ParameterDescription extentParameterNamed: #extent label: 'Frame extent' translated value: extent help: 'the frame extent in pixels' translated. typeParameter := ParameterDescription optionParameterNamed: #type label: 'Type' translated value: type options: {{'Lenna'. #lenna}. {'Color Bars'. #colorBars}} help: 'the type of the test image' translated. showTimeParameter := ParameterDescription booleanParameterNamed: #isShowingTime label: 'show time' translated value: isShowingTime help: 'the test image includes the time' translated. ^ {extentParameter. typeParameter. showTimeParameter}! ! !TestDeviceImplementor methodsFor: 'capturing' stamp: 'dgd 8/9/2004 21:14'! nextWithBrightness: brightnessFloat contrast: contrastFloat "answer the next frame from the device represented by the receiver" | result | result := type == #lenna ifTrue: [self scaledLenna] ifFalse: [self colorBars]. "" isShowingTime ifTrue: ["" result getCanvas drawString: Time now print24 at: 5 @ 2 font: Preferences windowTitleFont color: Color white]. "" ^result! ! !TestDeviceImplementor methodsFor: 'initialization' stamp: 'dgd 11/3/2006 15:02'! initialize "initialize the receiver" super initialize. type := #lenna. "type := #colorBars." isShowingTime := true. opened := true. extent := 320 @ 240. ! ! !V4LDeviceImplementor methodsFor: 'printing' stamp: 'dgd 8/10/2004 20:53'! printOn: aStream "append to aStream a sequence of characters that identifies the receiver" super printOn: aStream. "" aStream nextPutAll: ', deviceHandle='; nextPutAll: deviceHandle asString; nextPutAll: ', deviceID:'; nextPutAll: self deviceID asString! ! !V4LDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 8/6/2004 18:52'! close "close the receiver" | dh | dh := deviceHandle. "" deviceHandle := nil. buffer := nil. "" self deviceClose: dh! ! !V4LDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 8/6/2004 18:52'! isOpened "answer whatever the receiver is opened" ^ deviceHandle notNil! ! !V4LDeviceImplementor methodsFor: 'opening / closing' stamp: 'dgd 8/10/2004 20:53'! open "open the device represented by the receiver" | w h | deviceHandle := self deviceCreate: deviceID with: desiredExtent x height: desiredExtent y palette: desiredPalette. "" w := self deviceGetWidth: deviceHandle. h := self deviceGetHeight: deviceHandle. "" buffer := Form extent: w @ h depth: 32! ! !V4LDeviceImplementor methodsFor: 'primitives' stamp: 'dgd 7/28/2004 18:16'! deviceClose: deviceInteger ^ self error: 'can''t open device ''' , deviceInteger asString , ''''! ! !V4LDeviceImplementor methodsFor: 'primitives' stamp: 'dgd 8/5/2004 22:50'! deviceCreate: deviceIDInteger with: widthInteger height: heightInteger palette: paletteInteger ^ self error: 'can''t create device id ''' , deviceIDInteger asString , ''''! ! !V4LDeviceImplementor methodsFor: 'primitives' stamp: 'dgd 7/28/2004 18:17'! deviceGetHeight: deviceInteger ^ self error: 'primitive failed for device ''' , deviceInteger asString , ''''! ! !V4LDeviceImplementor methodsFor: 'primitives' stamp: 'dgd 7/28/2004 18:17'! deviceGetWidth: deviceInteger ^ self error: 'primitive failed for device ''' , deviceInteger asString , ''''! ! !V4LDeviceImplementor methodsFor: 'primitives' stamp: 'dgd 7/28/2004 18:16'! deviceNextFrame: deviceInteger into: bits brightness: brightnessFloat contrast: contrastFloat ^ self error: 'can''t capture frame in device ''' , deviceInteger asString , ''''! ! !V4LDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 8/5/2004 22:49'! deviceID "answer the receiver's deviceID" ^ deviceID! ! !V4LDeviceImplementor methodsFor: 'accessing' stamp: 'dgd 8/5/2004 22:49'! extent "answer the receiver's extent" ^ buffer isNil ifTrue: [320 @ 240] ifFalse: [buffer extent]! ! !V4LDeviceImplementor methodsFor: 'capturing' stamp: 'dgd 8/6/2004 18:52'! nextWithBrightness: brightnessFloat contrast: contrastFloat "answer the next frame from the device represented by the receiver" buffer unhibernate. self deviceNextFrame: deviceHandle into: buffer bits brightness: brightnessFloat contrast: contrastFloat. " self deviceNextFrame: self deviceHandle into: buffer bits. " ^ buffer deepCopy! ! !V4LDeviceImplementor methodsFor: 'initialization' stamp: 'dgd 8/5/2004 22:19'! initializeDescription: aDescription "initialiaze the receiver's description" super initializeDescription: aDescription. "" self initializeDevice: aDescription id extent: self class defaultExtent palette: self class defaultPalette open: true! ! !V4LDeviceImplementor methodsFor: 'initialization' stamp: 'dgd 8/10/2004 20:53'! initializeDevice: deviceIDInteger extent: aPoint palette: paletteInteger open: aBoolean "initialize the receiver" deviceID := deviceIDInteger asInteger. desiredExtent := aPoint asIntegerPoint. desiredPalette := paletteInteger asInteger. "" deviceHandle := nil. buffer := nil. "" aBoolean ifTrue: [self open]! ! !V4LDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 21:26'! applyParameters: aCollection "apply the (possible changed) collection of parameters" aCollection do: [:parameter | parameter name == #extent ifTrue: [ desiredExtent := parameter value. ]. parameter name == #palette ifTrue: [desiredPalette := parameter value]]! ! !V4LDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 21:21'! palettes | palettes | palettes := OrderedCollection new. palettes add: {'DEFAULT - The palette the camera most like' translated. 0}. "palettes add: {'GREY - Linear greyscale' translated. 1}." "palettes add: {'HI240 - High 240 cube (BT848)' translated. 2}." "palettes add: {'RGB565 - 565 16 bit RGB' translated. 3}." palettes add: {'RGB24 - 24bit RGB' translated. 4}. palettes add: {'RGB32 - 32bit RGB' translated. 5}. "palettes add: {'RGB555 - 555 15bit RGB' translated. 6}." "palettes add: {'YUV422 - YUV422 capture' translated. 7}." "palettes add: {'YUYV' translated. 8}." "palettes add: {'UYVY' translated. 9}." palettes add: {'YUV420' translated. 10}. "palettes add: {'YUV411 - YUV411 capture' translated. 11}." "palettes add: {'RAW - RAW capture (BT848)' translated. 12}." "palettes add: {'YUV422P - YUV 4:2:2 Planar' translated. 13}." "palettes add: {'YUV411P - YUV 4:1:1 Planar' translated. 14}." palettes add: {'YUV420P - YUV 4:2:0 Planar' translated. 15}. "palettes add: {'YUV410P - YUV 4:1:0 Planar' translated. 16}." ^ palettes! ! !V4LDeviceImplementor methodsFor: 'configuration' stamp: 'dgd 8/10/2004 21:07'! parameters "answer a collection of parameters to configure the receiver" | extentParameter paletteParameter | extentParameter := ParameterDescription extentParameterNamed: #extent label: 'Frame extent' translated value: desiredExtent help: 'the frame extent in pixels' translated. paletteParameter := ParameterDescription optionParameterNamed: #palette label: 'Palette' translated value: desiredPalette options: self palettes help: 'the palette of the test image' translated. ^ {extentParameter. paletteParameter}! ! !VideoDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 17:17'! new "answer a new instance of the receiver" ^ super new initialize! ! !VideoDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 20:21'! newFromDescription: aDescription "answer a new instance of the receiver represented by the given description" ^ self new initializeDescription: aDescription! ! !VideoDeviceImplementor class methodsFor: 'testing' stamp: 'dgd 7/28/2004 17:16'! workOnCurrentEnvironment "Answer whatever ther receiver can work on the current environment. Usually the platform name is used to decide" ^ self subclassResponsibility! ! !VideoDeviceImplementor class methodsFor: 'enumerating' stamp: 'dgd 8/5/2004 19:26'! descriptions "answer a collection of VideoDeviceDescription of available video devices" ^self subclassResponsibility! ! !VideoDeviceImplementor class methodsFor: 'private' stamp: 'dgd 7/28/2004 18:42'! descriptionForId: anInteger name: aString "private - answer a description for the given id and name" ^ VideoDeviceImplementorDescription type: self id: anInteger name: aString ! ! !TestDeviceImplementor class methodsFor: 'enumerating' stamp: 'dgd 8/5/2004 19:26'! descriptions "answer a collection of VideoDeviceDescription of available video devices" ^{ self descriptionForId: 10 name: 'Test Video Device'}! ! !TestDeviceImplementor class methodsFor: 'testing' stamp: 'dgd 7/28/2004 17:34'! workOnCurrentEnvironment "Answer whatever ther receiver can work on the current environment. Usually the platform name is used to decide" "the test video device always works" ^ true! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 18:11'! defaulfDevice "answer the default device for instances of the receiver" ^ 0! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 18:11'! defaultExtent "answer the default extent for instances of the receiver" ^ 320 @ 240! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 18:11'! defaultPalette "answer the default extent for instances of the receiver" ^ 0! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 7/28/2004 18:11'! device: idInteger "answer an instance of the receiver" " LinuxCamera device: '/dev/video' " ^ self device: idInteger extent: self defaultExtent! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:19'! device: idInteger extent: aPoint "answer an instance of the receiver" ^ self device: idInteger extent: aPoint palette: self defaultPalette! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:20'! device: idInteger extent: aPoint palette: paletteInteger "answer an instance of the receiver" ^ self device: idInteger extent: aPoint palette: paletteInteger open: true! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:21'! device: idInteger extent: aPoint palette: paletteInteger open: aBoolean "answer an instance of the receiver" "VIDEO_PALETTE_RGB24 = 4. --> depth=24" "VIDEO_PALETTE_YUV420 = 10. --> depth=12" ^ super new initializeDevice: idInteger extent: aPoint palette: paletteInteger open: aBoolean! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:19'! extent: aPoint "answer an instance of the receiver" ^ self extent: aPoint palette: self defaultPalette! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:20'! extent: aPoint palette: paletteInteger "answer an instance of the receiver" ^ self device: self defaulfDevice extent: aPoint palette: paletteInteger! ! !V4LDeviceImplementor class methodsFor: 'instance creation' stamp: 'dgd 8/5/2004 22:20'! newOpen: aBoolean "answer an instance of the receiver" ^ self device: self defaulfDevice extent: self defaultExtent palette: self defaultPalette open: aBoolean! ! !V4LDeviceImplementor class methodsFor: 'enumerating' stamp: 'dgd 7/28/2004 18:10'! descriptionForDeviceID: deviceID "answer the description for the device with the given ID" | buffer deviceName | buffer := ByteArray new: 32. self deviceDescribe: deviceID in: buffer. "" deviceName := buffer asString reject: [:each | each asciiValue = 0]. "" ^ deviceName! ! !V4LDeviceImplementor class methodsFor: 'enumerating' stamp: 'dgd 8/5/2004 19:30'! descriptions "answer a collection of VideoDeviceDescription of available video devices" " V4LDeviceImplementor descriptions. Time millisecondsToRun:[ V4LDeviceImplementor descriptions ] " | result | result := Set new. 0 to: 9 do: [:deviceID | | deviceName | deviceName := self descriptionForDeviceID: deviceID. deviceName isEmpty ifFalse: [result add: (self descriptionForId: deviceID name: deviceName)]]. ^ result! ! !V4LDeviceImplementor class methodsFor: 'enumerating' stamp: 'dgd 8/20/2006 12:33'! workOnCurrentEnvironment "Answer whatever ther receiver can work on the current environment. Usually the platform name is used to decide" ((Smalltalk respondsTo: #osVersion) and: [Smalltalk osVersion = 'linux-gnu']) ifTrue:[^ true]. Smalltalk at:#SmalltalkImage ifPresent:[:klass | ^ klass current osVersion = 'linux-gnu' ]. ^ false. ! ! !V4LDeviceImplementor class methodsFor: 'primitives' stamp: 'dgd 11/3/2006 11:50'! deviceDescribe: deviceIDInteger in: deviceName ^ self error: 'can''t describe device id ''' , deviceIDInteger asString , ''''! ! !VideoDeviceImplementorDescription methodsFor: 'comparing' stamp: 'dgd 7/26/2004 19:37'! hash "Answer a SmallInteger whose value is related to the receiver's identity." ^ (self type hash bitXor: self id hash) bitXor: self name hash! ! !VideoDeviceImplementorDescription methodsFor: 'comparing' stamp: 'dgd 7/26/2004 19:35'! = aVideoDeviceDescription "answer whatever the receiver is equivalent to aVideoDeviceDescription" ^ self class = aVideoDeviceDescription class and: [self type = aVideoDeviceDescription type] and: [self id = aVideoDeviceDescription id] and: [self name = aVideoDeviceDescription name] ! ! !VideoDeviceImplementorDescription methodsFor: 'accessing' stamp: 'dgd 7/26/2004 19:15'! id "answer the receiver's id" ^ id! ! !VideoDeviceImplementorDescription methodsFor: 'accessing' stamp: 'dgd 7/26/2004 19:15'! name "answer the receiver's name" ^ name! ! !VideoDeviceImplementorDescription methodsFor: 'accessing' stamp: 'dgd 7/26/2004 19:16'! type "answer the receiver's type" ^ type! ! !VideoDeviceImplementorDescription methodsFor: 'printing' stamp: 'dgd 7/26/2004 19:15'! printOn: aStream "Append to aStream a sequence of characters that identifies the receiver." super printOn: aStream. "" aStream nextPutAll: ' name:'; nextPutAll: self name asString; nextPutAll: ', id:'; nextPutAll: self id asString; nextPutAll: ', type:'; nextPutAll: self type asString! ! !VideoDeviceImplementorDescription methodsFor: 'initialization' stamp: 'dgd 7/26/2004 19:08'! initializeType: aClass id: anInteger name: aString "initialize the receiver" type := aClass. id := anInteger. name := aString ! ! !VideoDeviceImplementorDescription methodsFor: 'factory' stamp: 'dgd 7/28/2004 18:44'! newImplementor "answer the implementor instance represented by the receiver" ^ type newFromDescription: self! ! !VideoDeviceImplementorDescription class methodsFor: 'instance creation' stamp: 'dgd 7/26/2004 19:08'! type: aClass id: anInteger name: aString "answer a new instance of the receiver" ^ self new initializeType: aClass id: anInteger name: aString! ! !VideoMorph methodsFor: 'meta-actions' stamp: 'dgd 8/6/2004 19:17'! openAPropertySheet VideoPropertiesMorph basicNew targetMorph: self; initialize; openNearTarget! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/11/2004 21:36'! arrowDeltaFor: aGetSelector "Answer a number indicating the default arrow delta to be used in a numeric readout with the given get-selector. This is a hook that subclasses of Morph can reimplement." (#(#getBrightness #getContrast ) includes: aGetSelector) ifTrue: [^ 0.1]. ^ super arrowDeltaFor: aGetSelector! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/11/2004 21:36'! defaultFloatPrecisionFor: aGetSelector "Answer a number indicating the default float precision to be used in a numeric readout for which the receiver provides the data. Individual morphs can override this. Showing fractional values for readouts of getCursor was in response to an explicit request from ack" (#(#getBrightness #getContrast ) includes: aGetSelector) ifTrue: [^ 0.01]. "" ^ super defaultFloatPrecisionFor: aGetSelector! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 8/9/2004 20:47'! forgetConfigurationDialog configurationDialog_nil! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 8/6/2004 19:56'! getAutoExtent ^ self autoExtent! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/3/2004 16:02'! getBrightness ^ videoSource isNil ifTrue: [0] ifFalse: [videoSource brightness]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/3/2004 16:02'! getContrast ^ videoSource isNil ifTrue: [0] ifFalse: [videoSource contrast]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 6/28/2004 11:35'! getIsRunning ^ videoSource notNil and: [videoSource isOpened]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/1/2004 18:34'! getLastFrame videoSource isNil ifTrue: [^ self presenter standardPlayer costume]. videoSource isOpened ifFalse: [^ self presenter standardPlayer costume]. "" self updateForm. ^ SketchMorph withForm: form deepCopy! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/1/2004 13:23'! getResolution ^ resolution! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 6/28/2004 11:34'! play videoSource isNil ifFalse: [videoSource openIfCorresponds]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 8/6/2004 19:57'! setAutoExtent: aBoolean self autoExtent: aBoolean! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 8/3/2004 13:35'! setBrightness: amt videoSource isNil ifFalse:[videoSource brightness: amt]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 8/3/2004 13:36'! setContrast: amt videoSource isNil ifFalse:[videoSource contrast: amt]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 7/1/2004 13:37'! setResolution: aSymbol | newResolution | newResolution := aSymbol asSymbol. resolution := (self class resolutions includes: newResolution) ifTrue: [newResolution] ifFalse: [self class resolutions first]! ! !VideoMorph methodsFor: 'e-toy support' stamp: 'dgd 6/28/2004 11:33'! stop videoSource isNil ifFalse: [videoSource closeIfCorresponds]! ! !VideoMorph methodsFor: 'submorphs-add/remove' stamp: 'dgd 8/9/2004 19:22'! delete "Remove the receiver as a submorph of its owner and make its new owner be nil." self videoSource: nil. super delete.! ! !VideoMorph methodsFor: 'initialization' stamp: 'dgd 8/9/2004 11:12'! initialize "initialize the receiver" super initialize. autoExtent := true. "" resolution := #original. "" self extent: 320 @ 240. self borderWidth: 0. self updateForm! ! !VideoMorph methodsFor: 'initialization' stamp: 'dgd 8/6/2004 19:45'! initializeOn: aVideoSource "initialize the receiver's videoSource" self videoSource: aVideoSource. self tryToAutoExtent! ! !VideoMorph methodsFor: 'accessing' stamp: 'dgd 8/6/2004 19:47'! autoExtent "answer the receiver's autoExtent" ^ autoExtent! ! !VideoMorph methodsFor: 'accessing' stamp: 'dgd 8/6/2004 19:45'! autoExtent: aBoolean "change the receiver's autoExtent" autoExtent := aBoolean. self tryToAutoExtent! ! !VideoMorph methodsFor: 'accessing' stamp: 'dgd 8/6/2004 20:22'! borderWidth: anInteger super borderWidth: anInteger. self tryToAutoExtent ! ! !VideoMorph methodsFor: 'accessing' stamp: 'dgd 8/6/2004 20:02'! switchAutoExtent ^ self autoExtent: self autoExtent not! ! !VideoMorph methodsFor: 'accessing' stamp: 'dgd 8/9/2004 19:45'! videoSource: aVideoSource "change the receiver's videoSource" videoSource == aVideoSource ifTrue: [^ self]. "" videoSource isNil ifFalse: ["" videoSource removeActionsWithReceiver: self. videoSource closeIfCorresponds]. "" videoSource := aVideoSource. videoSource when: #extent send: #tryToAutoExtent to: self ! ! !VideoMorph methodsFor: 'private' stamp: 'dgd 6/28/2004 11:52'! freeAreaExtent "private - answer the extent to fill (or filled) with tha image" ^ self extent - (self borderWidth * 2)! ! !VideoMorph methodsFor: 'private' stamp: 'dgd 8/9/2004 19:23'! scaledForm "private - answer the form, but scaled to fit the morph" | freeAreaExtent formExtent outForm warpBlt | freeAreaExtent := self freeAreaExtent. formExtent := form extent. (freeAreaExtent = formExtent or: [formExtent isZero]) ifTrue: [^ form]. "" outForm := Form extent: freeAreaExtent depth: form depth. warpBlt := WarpBlt current toForm: outForm. warpBlt sourceForm: form. warpBlt cellSize: 2; combinationRule: Form over. warpBlt copyQuad: form boundingBox innerCorners toRect: (0 @ 0 extent: freeAreaExtent). "" ^ outForm! ! !VideoMorph methodsFor: 'private' stamp: 'dgd 8/9/2004 19:24'! tryToAutoExtent "private - if corresponds, try to change the receiver's extent" autoExtent ifTrue: [self extent: 0 @ 0]! ! !VideoMorph methodsFor: 'private' stamp: 'dgd 7/13/2004 20:28'! updateForm "private - update the form from the videoSource" videoSource isNil ifTrue: ["" form := Form extent: 320 @ 240 depth: 32. form fillColor: Color blue twiceDarker] ifFalse: ["" form := videoSource next]. "" resolution == #'256 colors' ifTrue: [form := form asFormOfDepth: 8]. resolution == #'256 grays' ifTrue: [form := form asGrayScale]. resolution == #'4 grays' ifTrue: [form := form asFormOfDepth: 2]. resolution == #'black and white' ifTrue: [form := form asFormOfDepth: 1]! ! !VideoMorph methodsFor: 'configuration' stamp: 'dgd 8/10/2004 18:15'! applyParameters: aCollection "apply the (possible changed) collection of parameters" videoSource isNil ifTrue: [^ self]. videoSource applyParameters: aCollection! ! !VideoMorph methodsFor: 'configuration' stamp: 'dgd 8/9/2004 20:51'! bringUpConfigurationDialog configurationDialog comeToFront. configurationDialog topLeft: self topLeft + 5. configurationDialog flash. ! ! !VideoMorph methodsFor: 'configuration' stamp: 'dgd 8/9/2004 20:50'! configureVideoDevice "creates a dialog to configure the receiver's videoSource" videoSource isNil ifTrue: [^ self]. "" configurationDialog isNil ifTrue: [self createConfigurationDialog] ifFalse: [self bringUpConfigurationDialog] ! ! !VideoMorph methodsFor: 'configuration' stamp: 'dgd 8/10/2004 14:59'! createConfigurationDialog | parameters | parameters := videoSource parameters. parameters isEmpty ifTrue: [^ self inform: 'the video device has not parameters to configure' translated]. "" configurationDialog := VideoMorphConfiguration target: self parameters: parameters. self addMorphBack: configurationDialog. configurationDialog topLeft: self topLeft + 5! ! !VideoMorph methodsFor: 'stepping and presenter' stamp: 'dgd 7/11/2004 22:12'! step "Do some periodic activity" videoSource isNil ifTrue: [^ self]. "" self updateForm. self changed! ! !VideoMorph methodsFor: 'stepping and presenter' stamp: 'dgd 8/1/2004 20:22'! stepTime "Answer the desired time between steps in milliseconds" ^ 100! ! !VideoMorph methodsFor: 'menus' stamp: 'dgd 8/9/2004 20:41'! addCustomMenuItems: aMenu hand: aHandMorph super addCustomMenuItems: aMenu hand: aHandMorph. aMenu add: 'configure video device' translated action: #configureVideoDevice! ! !VideoMorph methodsFor: 'halos and balloon help' stamp: 'dgd 8/6/2004 20:06'! okayToResizeEasily ^ self autoExtent not! ! !VideoMorph methodsFor: 'halos and balloon help' stamp: 'dgd 8/6/2004 20:09'! wantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph aSelector == #addDupHandle: ifTrue: [^ false]. ^ super wantsHaloHandleWithSelector: aSelector inHalo: aHaloMorph ! ! !VideoMorph methodsFor: 'drawing' stamp: 'dgd 7/3/2004 16:13'! drawOn: aCanvas "draw the receiver on aCanvas" super drawOn: aCanvas. "" aCanvas paintImage: self scaledForm at: bounds origin + self borderWidth! ! !VideoMorph methodsFor: 'geometry' stamp: 'dgd 8/6/2004 19:43'! extent: aPoint | newExtent | newExtent := autoExtent ifTrue: [videoSource isNil ifTrue: [320 @ 240] ifFalse: [videoSource extent + (self borderWidth * 2)]] ifFalse: [aPoint]. "" super extent: newExtent ! ! !VideoMorph class methodsFor: 'parts bin' stamp: 'dgd 7/28/2004 21:02'! descriptionForPartsBin ^ self partName: 'Video Device' categories: #('Multimedia' ) documentation: 'A player for video devices like cameras, video capturers, etc.' ! ! !VideoMorph class methodsFor: 'parts bin' stamp: 'dgd 7/28/2004 21:02'! newStandAlone ^ self on: (VideoDevice default)! ! !VideoMorph class methodsFor: 'misc' stamp: 'dgd 7/13/2004 20:28'! resolutions "answer a collection of valid resolutions" ^ #(#original #'256 colors' #'256 grays' #'4 grays' #'black and white' )! ! !VideoMorph class methodsFor: 'instance creation' stamp: 'dgd 6/4/2003 20:49'! on: aVideoSource "answer an instance of the receiver on aVideoSource" ^ super new initializeOn: aVideoSource! ! !VideoMorph class methodsFor: 'scripting' stamp: 'dgd 8/20/2006 11:11'! additionsToViewerCategories "Answer a list of ( ) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories." ^ #( (graphics ( (slot graphic 'The picture currently being worn' Graphic readOnly Player getGraphic unused unused) ) ) (video ( (command play 'Start playing the movie/sound') (command stop 'Stop playing the movie/sound') (slot isRunning 'Whether the movie/sound is being played' Boolean readOnly Player getIsRunning unused unused) (slot autoExtent 'Whether the morph is in auto-extent mode' Boolean readWrite Player getAutoExtent Player setAutoExtent:) (slot lastFrame 'A morph with the last frame' Player readOnly Player getLastFrame unused unused) (slot resolution 'Video resolution' ImageResolution readWrite Player getResolution Player setResolution:) (slot brightness 'Video brightness' Number readWrite Player getBrightness Player setBrightness:) (slot contrast 'Video contrast' Number readWrite Player getContrast Player setContrast:) (command configureVideoDevice 'Open a dialog to configure the video device') ) ) ) ! ! !VideoMorph class methodsFor: 'class initialization' stamp: 'dgd 11/3/2006 15:18'! initialize " VideoMorph initialize. " | morph | morph := self on: (VideoDevice implementation: TestDeviceImplementor new). morph updateForm. PartsBin cacheThumbnail: (Thumbnail new makeThumbnailFromForm: morph imageForm) forSymbol: 'Video Device'. ! ! !VideoMorphConfiguration methodsFor: 'building' stamp: 'dgd 8/10/2004 20:13'! build self addMorphBack: (StringMorph contents: 'Video Device Configuration' translated font: Preferences windowTitleFont). "" self addMorphBack: self spacer. parameters do: [:each | self addMorphBack: each asMorph]. self addMorphBack: self spacer. "" self addMorphBack: self buttonsRow! ! !VideoMorphConfiguration methodsFor: 'building' stamp: 'dgd 8/10/2004 14:12'! buttonsRow "private - create a row with accept/cancel buttons" | acept cancel | acept := self buttonNamed: 'Accept' translated action: #doAccept color: Color green darker help: 'keep changes made and close panel' translated. cancel := self buttonNamed: 'Cancel' translated action: #doCancel color: Color red darker help: 'cancel changes made and close panel' translated. ^ (self inARow: {acept. cancel}) ! ! !VideoMorphConfiguration methodsFor: 'building' stamp: 'dgd 8/10/2004 21:18'! doAccept | changes | changes := parameters select: [:each | each hasChanged]. changes isEmpty ifFalse:[ target applyParameters: changes]. self delete! ! !VideoMorphConfiguration methodsFor: 'building' stamp: 'dgd 8/9/2004 17:11'! doCancel self delete! ! !VideoMorphConfiguration methodsFor: 'initialization' stamp: 'dgd 8/10/2004 14:05'! initialize super initialize. "" self color: (Color lightYellow alpha: 0.9). self borderColor: self color muchDarker. self listDirection: #topToBottom. self borderWidth: 4. self layoutInset: 5. self cellInset: 2. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. self useRoundedCorners! ! !VideoMorphConfiguration methodsFor: 'initialization' stamp: 'dgd 8/9/2004 20:47'! initializeTarget: aVideoMorph parameters: aCollection "initialize the receiver's parameters" target _ aVideoMorph. parameters := aCollection. self build! ! !VideoMorphConfiguration methodsFor: 'private' stamp: 'dgd 8/10/2004 12:33'! buttonNamed: aString action: aSymbol color: aColor help: helpString "private - answer a new button" | button | button := SimpleButtonMorph new. button target: self. button label: aString. button color: aColor. button borderColor: aColor muchDarker. button actionSelector: aSymbol. helpString isEmpty ifFalse:[ button setBalloonText: helpString]. ^ button! ! !VideoMorphConfiguration methodsFor: 'private' stamp: 'dgd 8/9/2004 20:04'! inARow: aCollectionOfMorphs "private - create a row of morphs" | row | row := AlignmentMorph newRow. row color: Color transparent; vResizing: #shrinkWrap; layoutInset: 2; wrapCentering: #center; cellPositioning: #leftCenter; cellInset: 2. aCollectionOfMorphs do: [:each | row addMorphBack: each]. ^ row! ! !VideoMorphConfiguration methodsFor: 'private' stamp: 'dgd 8/9/2004 20:35'! spacer ^StringMorph contents: ' '! ! !VideoMorphConfiguration methodsFor: 'submorphs-add/remove' stamp: 'dgd 8/9/2004 20:48'! delete target forgetConfigurationDialog. super delete.! ! !VideoMorphConfiguration class methodsFor: 'instance creation' stamp: 'dgd 8/9/2004 20:46'! target: aVideoMorph parameters: aCollection "answer a new instance of the receiver" ^ self new initializeTarget: aVideoMorph parameters: aCollection! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:37'! brightness "answer the receiver's brightness" ^ myTarget getBrightness! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:41'! brightnessTitle ^ ' Brightness ({1}%)' translated format: {(self brightness * 100.0) rounded}! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:43'! brightness: aNumber "answer the receiver's brightness" ^ myTarget setBrightness: aNumber! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:37'! contrast "answer the receiver's contrast" ^ myTarget getContrast! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:40'! contrastTitle ^ ' Contrast ({1}%)' translated format: {(self contrast * 100.0) rounded}! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 20:44'! contrast: aNumber "answer the receiver's contrast" ^ myTarget setContrast: aNumber! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/9/2004 20:40'! doConfigureVideoDevice myTarget configureVideoDevice! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 21:41'! resolution "answer the receiver's resolution" ^ myTarget getResolution! ! !VideoPropertiesMorph methodsFor: 'actions' stamp: 'dgd 8/6/2004 21:41'! resolution: aSymbol "change the receiver's resolution" ^ myTarget setResolution: aSymbol! ! !VideoPropertiesMorph methodsFor: 'building' stamp: 'dgd 8/6/2004 20:32'! brightnessIcon ^ Form extent: 22 @ 22 depth: 16 fromArray: #(0 0 0 0 0 65537 0 0 0 0 0 1 65536 0 0 0 65537 0 0 0 1 65536 1 65537 0 0 0 0 0 0 0 65537 65536 0 65537 0 0 65537 65537 65537 0 0 65537 0 0 0 0 65537 65537 65537 65537 65537 0 0 0 0 0 1 65537 766332664 1671258013 1324886445 65537 65536 0 0 0 0 65537 207901432 1742694367 1740530622 1673420734 1255606371 65537 0 0 0 0 65537 1392011231 1809803231 1742694334 1673420734 1604143831 65537 0 0 0 1 77229 1742695391 1809804255 1742694334 1673421758 1604148125 697106433 65536 0 0 1 85752 1742694367 1809803231 1742694334 1673420734 1604148125 1188495361 65536 0 65537 1 91037 1740531679 1742694367 1740530622 1673420734 1604148125 1467744257 65536 65537 65537 1 90013 1673422782 1740531646 1673421758 1673420701 1604148125 1467744257 65536 65537 0 1 85752 1673421758 1673421758 1673421758 1604149149 1537039261 1188429825 65536 0 0 1 76205 1606311870 1673420734 1606311837 1604148125 1537039260 629932033 65536 0 0 0 65537 1255628701 1604149149 1604149149 1537039261 1536968406 65537 0 0 0 0 65537 140724951 1537039261 1537039261 1537039260 1188431971 65537 0 0 0 0 1 65537 697124567 1467766652 1188439436 65537 65536 0 0 0 0 0 65537 65537 65537 65537 65537 0 0 0 0 65537 0 0 65537 65537 65537 0 0 65537 0 1 65537 0 0 0 0 0 0 0 65537 65536 1 65536 0 0 0 65537 0 0 0 1 65536 0 0 0 0 0 65537 0 0 0 0 0 ) offset: 0 @ 0! ! !VideoPropertiesMorph methodsFor: 'building' stamp: 'dgd 8/7/2004 20:48'! contrastIcon ^ Form extent: 16 @ 16 depth: 16 fromArray: #(0 0 1 65537 65537 65536 0 0 0 1 65537 65537 65537 65537 65536 0 0 65537 77229 1324901277 835659116 348520449 65537 0 1 68708 1392011231 1742694334 837825007 837756268 69271553 65536 1 86776 1742695391 1742694367 837825007 837759471 627834881 65536 65537 766339039 1809804255 1809803231 837825007 837759471 768545990 65537 65537 1324902367 1742695391 1742694367 837825007 837759471 768550251 65537 65537 1671260094 1742694367 1742694334 837825007 837759471 768552398 65537 65537 1604150206 1740531646 1740530622 837759471 837758415 768552398 65537 65537 1324901310 1673421758 1673421758 837759471 837758415 768549227 65537 65537 699228094 1606312894 1606311870 837759471 768552399 768480454 65537 1 84695 1604149149 1604149149 768552399 768552398 560660481 65536 1 67683 1255627677 1537039261 768552399 768483691 69271553 65536 0 65537 76173 1188517756 768483691 348520449 65537 0 0 1 65537 65537 65537 65537 65536 0 0 0 1 65537 65537 65536 0 0 ) offset: 0 @ 0! ! !VideoPropertiesMorph methodsFor: 'building' stamp: 'dgd 8/6/2004 20:19'! paneForAutoExtentToggle ^self inARow: { self directToggleButtonFor: myTarget getter: #autoExtent setter: #switchAutoExtent help: 'Turn auto-extent on or off' translated. self lockedString: ' Auto Extent' translated. } ! ! !VideoPropertiesMorph methodsFor: 'building' stamp: 'dgd 8/8/2004 20:04'! paneForVideoParameters | resolutionCombo brightnessSlider contrastSlider configureButton button | brightnessSlider := self buildSlider: #brightnessTitle selector: #brightness help: 'Drag in here to change the Brightness' icon: self brightnessIcon. contrastSlider := self buildSlider: #contrastTitle selector: #contrast help: 'Drag in here to change the Contrast' icon: self contrastIcon. resolutionCombo := self createComboLabel: 'resolution' target: self readSelector: #resolution writeSelector: #resolution: options: VideoMorph resolutions. configureButton := self buttonNamed: 'Configure Video Device' translated action: #doConfigureVideoDevice color: color lighter help: 'press here to configure the video device' translated. button := configureButton submorphs anyOne. button borderWidth: 2; borderRaised; extent: button extent + 6. "" ^ (self inAColumn: {brightnessSlider. contrastSlider. resolutionCombo. configureButton}) cellPositioning: #topLeft; layoutInset: 0; cellInset: 2! ! !VideoPropertiesMorph methodsFor: 'building' stamp: 'dgd 8/7/2004 21:39'! rebuild self removeAllMorphs. self addARow: {self lockedString: ('Properties for {1}' translated format: {myTarget externalName})}. self addARow: {self inAColumn: {self paneForCornerRoundingToggle. self paneForStickinessToggle. self paneForLockedToggle. self paneForAutoExtentToggle}}. self addARow: {self paneForVideoParameters}. self addARow: {self paneForBorderColorPicker. self paneForShadowColorPicker}. self addARow: {self buttonNamed: 'Accept' translated action: #doAccept color: color lighter help: 'keep changes made and close panel' translated. self buttonNamed: 'Cancel' translated action: #doCancel color: color lighter help: 'cancel changes made and close panel' translated}. thingsToRevert := Dictionary new. thingsToRevert at: #hasDropShadow: put: myTarget hasDropShadow. thingsToRevert at: #shadowColor: put: myTarget shadowColor. thingsToRevert at: #borderColor: put: myTarget borderColor. thingsToRevert at: #borderWidth: put: myTarget borderWidth. thingsToRevert at: #cornerStyle: put: myTarget cornerStyle. thingsToRevert at: #sticky: put: myTarget isSticky. thingsToRevert at: #lock: put: myTarget isLocked. thingsToRevert at: #autoExtent: put: myTarget autoExtent. thingsToRevert at: #setContrast: put: myTarget getContrast. thingsToRevert at: #setBrightness: put: myTarget getBrightness. thingsToRevert at: #setResolution: put: myTarget getResolution! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/10/2004 12:34'! buildSlider: nameStringOrSymbol selector: aSymbol help: helpString icon: aForm | title slider icon titleRow col | title := (nameStringOrSymbol isKindOf: Symbol) ifTrue: [UpdatingStringMorph new useStringFormat; getSelector: nameStringOrSymbol; target: self; growable: true; minimumWidth: 24; lock] ifFalse: [self lockedString: nameStringOrSymbol]. "" slider := SimpleSliderMorph new color: self color twiceDarker darker; extent: 370 @ 2; target: self; actionSelector: (aSymbol , ':') asSymbol; minVal: -1.0; maxVal: 1.0; yourself. slider adjustToValue: (self perform: aSymbol). "" icon := ImageMorph new image: aForm. titleRow := self inARow: {icon. title}. titleRow hResizing: #shrinkWrap; cellInset: 3. col := self inAColumn: {titleRow. slider}. "" col borderWidth: 1; borderColor: color darker; color: color lighter; hResizing: #shrinkWrap; layoutInset: 5; cellInset: 5; useRoundedCorners. helpString isEmpty ifFalse:[col setBalloonText: helpString.]. "" ^ col! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/6/2004 22:15'! createComboLabel: aString target: targetObject readSelector: readSelectorSymbol writeSelector: writeSelectorSymbol options: optionsArray "private - create a combo" | button row | button := SimpleButtonMorph newWithLabel: '-'. self updateButton: button for: targetObject readSelector: readSelectorSymbol options: optionsArray. button borderWidth: 1; cornerStyle: #square; borderColor: #inset; color: self color darker. button target: self; actionSelector: #popUpComboTarget:readSelector:writeSelector:options:button:; arguments: {targetObject. readSelectorSymbol. writeSelectorSymbol. optionsArray. button}. "" row := AlignmentMorph newRow. row borderWidth: 1; borderColor: color darker; color: color lighter; hResizing: #shrinkWrap; layoutInset: 5; cellInset: 5; useRoundedCorners. row addMorphBack: (StringMorph contents: aString , ': '). row addMorphBack: button. ^ row! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/10/2004 12:25'! getLabelFor: targetObject readSelector: readSelectorSymbol options: optionsArray | currentValue | currentValue := targetObject perform: readSelectorSymbol. ^ (optionsArray includes: currentValue) ifTrue: [currentValue] ifFalse: [^ '' translated]! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/6/2004 21:29'! performComboOption: writeSelectorSymbol argument: argumentObject readSelector: readSelectorSymbol target: targetObject button: button options: optionsArray targetObject perform: writeSelectorSymbol with: argumentObject. "" self updateButton: button for: targetObject readSelector: readSelectorSymbol options: optionsArray! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/6/2004 22:11'! popUpComboTarget: targetObject readSelector: readSelectorSymbol writeSelector: writeSelectorSymbol options: optionsArray button: button | menu | menu := MenuMorph new. menu color: self color twiceLighter. optionsArray do: [:option | "" menu add: option target: self selector: #performComboOption:argument:readSelector:target:button:options: argumentList: {writeSelectorSymbol. option . readSelectorSymbol. targetObject. button. optionsArray}]. menu popUpInWorld! ! !VideoPropertiesMorph methodsFor: 'widget creation' stamp: 'dgd 8/6/2004 22:14'! updateButton: button for: targetObject readSelector: readSelectorSymbol options: optionsArray | label | label := self getLabelFor: targetObject readSelector: readSelectorSymbol options: optionsArray. button label: ' ',label,' '! ! !VideoPropertiesMorph methodsFor: 'initialization' stamp: 'dgd 8/6/2004 21:37'! initialize "initialize the receiver" super initialize. "" myTarget isNil ifTrue: [myTarget := RectangleMorph new openInWorld]. self color: (Color r: 0.476 g: 0.575 b: 0.869). self borderColor: self color darker. self rebuild ! ! VideoMorph initialize! VideoDevice initialize! ImageResolutionType initialize! "Postscript:" PartsBin cacheThumbnail: (Thumbnail new makeThumbnailFromForm: (VideoMorph on: (VideoDevice implementation: TestDeviceImplementor new) ) updateForm imageForm) forSymbol: 'Video Device'. ! ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/VideoForLinuxPlugin.c ================================================ /* Automatically generated from Squeak on #(7 March 2007 2:25:53 pm) */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "VideoForLinuxPlugin.h" /* memory access macros */ #define byteAt(i) (*((unsigned char *) (i))) #define byteAtput(i, val) (*((unsigned char *) (i)) = val) #define longAt(i) (*((int *) (i))) #define longAtput(i, val) (*((int *) (i)) = val) /*** Constants ***/ /*** Function Prototypes ***/ static int clipPixel(int pixel); static int copyFrominto16destSizebrightnesscontrast(unsigned char* src2, unsigned char* dest2, int destSize, double brightness, double contrast); static int copyFrominto32destSizebrightnesscontrast(unsigned char* src2, unsigned char* dest2, int destSize, double brightness, double contrast); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static int halt(void); static int height(Device device); static int msg(char *s); static int pixelbrightness256contrastFactor2(int pixel, int brightness, int contrastFactor); #pragma export on EXPORT(int) primitiveDeviceClose(void); EXPORT(int) primitiveDeviceCreate(void); EXPORT(int) primitiveDeviceDescribe(void); EXPORT(int) primitiveDeviceGetHeight(void); EXPORT(int) primitiveDeviceGetWidth(void); EXPORT(int) primitiveDeviceNextFrameIntoBrightnessContrastFormDepth(void); EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter); #pragma export off static int storeRedgreenbluebrightness256contrastFactor2into16Bits(int red, int green, int blue, int brig256, int contInteger, unsigned char* dest); static int storeRedgreenbluebrightness256contrastFactor2into32Bits(int red, int green, int blue, int brig256, int contInteger, unsigned char* dest); static int storeRedgreenblueinto16Bits(int red, int green, int blue, unsigned char* dest); static int storeRedgreenblueinto32Bits(int red, int green, int blue, unsigned char* dest); static int width(Device device); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "VideoForLinuxPlugin 7 March 2007 (i)" #else "VideoForLinuxPlugin 7 March 2007 (e)" #endif ; static int clipPixel(int pixel) { int result; result = ((pixel < 0) ? 0 : pixel); return ((result < 255) ? result : 255); } static int copyFrominto16destSizebrightnesscontrast(unsigned char* src2, unsigned char* dest2, int destSize, double brightness, double contrast) { unsigned char* dest; unsigned char* final; int brig256; unsigned char* src; int contInteger; double cont; dest = dest2; src = src2; final = dest + (destSize * 2); if ((contrast == 0.0) && (brightness == 0.0)) { while (dest < final) { storeRedgreenblueinto16Bits(src[0], src[1], src[2], dest); dest += 2; src += 3; } } else { brig256 = ((int) (brightness * 256) ); cont = 1.0 + contrast; contInteger = ((int) ((cont * cont) * 32767) ); while (dest < final) { storeRedgreenbluebrightness256contrastFactor2into16Bits(src[0], src[1], src[2], brig256, contInteger, dest); dest += 2; src += 3; } } } static int copyFrominto32destSizebrightnesscontrast(unsigned char* src2, unsigned char* dest2, int destSize, double brightness, double contrast) { unsigned char* dest; unsigned char* final; int brig256; unsigned char* src; int contInteger; double cont; dest = dest2; src = src2; final = dest + (destSize * 4); if ((contrast == 0.0) && (brightness == 0.0)) { while (dest < final) { storeRedgreenblueinto32Bits(src[0], src[1], src[2], dest); dest += 4; src += 3; } } else { brig256 = ((int) (brightness * 256) ); cont = 1.0 + contrast; contInteger = ((int) ((cont * cont) * 32767) ); while (dest < final) { storeRedgreenbluebrightness256contrastFactor2into32Bits(src[0], src[1], src[2], brig256, contInteger, dest); dest += 4; src += 3; } } } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static int halt(void) { ; } static int height(Device device) { return device->vwindow.height; } static int msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } static int pixelbrightness256contrastFactor2(int pixel, int brightness, int contrastFactor) { int result; result = ((((int) ((pixel - 128) * (contrastFactor / 32767.0)) )) + 128) + brightness; return result; } EXPORT(int) primitiveDeviceClose(void) { Device device; device = ((Device) (interpreterProxy->stackIntegerValue(0))); closeDevice(device); interpreterProxy->pop(1); } EXPORT(int) primitiveDeviceCreate(void) { int devicePointer; int deviceID; int palette; int height; int width; palette = interpreterProxy->stackIntegerValue(0); height = interpreterProxy->stackIntegerValue(1); width = interpreterProxy->stackIntegerValue(2); /* */ deviceID = interpreterProxy->stackIntegerValue(3); devicePointer = (int) createDevice(deviceID, width, height, palette); if (devicePointer <= 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->popthenPush(5, ((devicePointer << 1) | 1)); } EXPORT(int) primitiveDeviceDescribe(void) { int deviceID; int deviceNameSize; int deviceName; char* deviceNamePointer; deviceName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(deviceName))) { return interpreterProxy->primitiveFail(); } deviceNamePointer = interpreterProxy->firstIndexableField(deviceName); deviceNameSize = interpreterProxy->byteSizeOf(deviceName); if (!(deviceNameSize == 32)) { return interpreterProxy->primitiveFail(); } deviceID = interpreterProxy->stackIntegerValue(1); describeDevice(deviceID, deviceNamePointer); interpreterProxy->pop(2); } EXPORT(int) primitiveDeviceGetHeight(void) { Device device; int result; device = ((Device) (interpreterProxy->stackIntegerValue(0))); result = device->vwindow.height; interpreterProxy->popthenPush(2, ((result << 1) | 1)); } EXPORT(int) primitiveDeviceGetWidth(void) { Device device; int result; device = ((Device) (interpreterProxy->stackIntegerValue(0))); result = device->vwindow.width; interpreterProxy->popthenPush(2, ((result << 1) | 1)); } EXPORT(int) primitiveDeviceNextFrameIntoBrightnessContrastFormDepth(void) { int formDepth; double brightness; Device device; unsigned char* src; int bitsArrayPointer; double contrast; formDepth = interpreterProxy->stackIntegerValue(0); contrast = interpreterProxy->stackFloatValue(1); contrast = ((contrast < 1.0) ? contrast : 1.0); contrast = ((contrast < -1.0) ? -1.0 : contrast); brightness = interpreterProxy->stackFloatValue(2); brightness = ((brightness < 1.0) ? brightness : 1.0); brightness = ((brightness < -1.0) ? -1.0 : brightness); bitsArrayPointer = interpreterProxy->stackValue(3); interpreterProxy->success(!(interpreterProxy->isPointers(bitsArrayPointer))); if (interpreterProxy->failed()) { return null; } /* Capture */ device = ((Device) (interpreterProxy->stackIntegerValue(4))); if (!(captureFrameFromDevice(device))) { return interpreterProxy->primitiveFail(); } if (!(convertBufferTo24(device))) { return interpreterProxy->primitiveFail(); } /* Convert */ src = device->buffer24; if (formDepth == 16) { copyFrominto16destSizebrightnesscontrast(src, ((unsigned char*) (interpreterProxy->firstIndexableField(bitsArrayPointer))), (width(device)) * (height(device)), brightness, contrast); } else { copyFrominto32destSizebrightnesscontrast(src, ((unsigned char*) (interpreterProxy->firstIndexableField(bitsArrayPointer))), (width(device)) * (height(device)), brightness, contrast); } interpreterProxy->pop(5); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter) { int ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static int storeRedgreenbluebrightness256contrastFactor2into16Bits(int red, int green, int blue, int brig256, int contInteger, unsigned char* dest) { int sr; int sg; int sb; int r; int g; int b; int result; int result1; int result2; int result3; int result4; int result5; /* begin pixel:brightness256:contrastFactor2: */ result = ((((int) ((red - 128) * (contInteger / 32767.0)) )) + 128) + brig256; r = result; /* begin clipPixel: */ result1 = ((r < 0) ? 0 : r); r = ((result1 < 255) ? result1 : 255); /* begin pixel:brightness256:contrastFactor2: */ result2 = ((((int) ((green - 128) * (contInteger / 32767.0)) )) + 128) + brig256; g = result2; /* begin clipPixel: */ result3 = ((g < 0) ? 0 : g); g = ((result3 < 255) ? result3 : 255); /* begin pixel:brightness256:contrastFactor2: */ result4 = ((((int) ((blue - 128) * (contInteger / 32767.0)) )) + 128) + brig256; b = result4; /* begin clipPixel: */ result5 = ((b < 0) ? 0 : b); b = ((result5 < 255) ? result5 : 255); sr = ((unsigned) r >> 3); sg = ((unsigned) g >> 3); sb = ((unsigned) b >> 3); dest[0] = ((((unsigned) sg << 5)) | sb); dest[1] = (((((unsigned) sr << 2)) | (((unsigned) sg >> 3))) | 128); } static int storeRedgreenbluebrightness256contrastFactor2into32Bits(int red, int green, int blue, int brig256, int contInteger, unsigned char* dest) { int r; int g; int b; int result; int result1; int result2; int result3; int result4; int result5; /* begin pixel:brightness256:contrastFactor2: */ result3 = ((((int) ((red - 128) * (contInteger / 32767.0)) )) + 128) + brig256; r = result3; /* begin clipPixel: */ result = ((r < 0) ? 0 : r); r = ((result < 255) ? result : 255); /* begin pixel:brightness256:contrastFactor2: */ result4 = ((((int) ((green - 128) * (contInteger / 32767.0)) )) + 128) + brig256; g = result4; /* begin clipPixel: */ result1 = ((g < 0) ? 0 : g); g = ((result1 < 255) ? result1 : 255); /* begin pixel:brightness256:contrastFactor2: */ result5 = ((((int) ((blue - 128) * (contInteger / 32767.0)) )) + 128) + brig256; b = result5; /* begin clipPixel: */ result2 = ((b < 0) ? 0 : b); b = ((result2 < 255) ? result2 : 255); dest[0] = b; dest[1] = g; dest[2] = r; dest[3] = 255; } static int storeRedgreenblueinto16Bits(int red, int green, int blue, unsigned char* dest) { int sr; int sg; int sb; sr = ((unsigned) red >> 3); sg = ((unsigned) green >> 3); sb = ((unsigned) blue >> 3); dest[0] = ((((unsigned) sg << 5)) | sb); dest[1] = (((((unsigned) sr << 2)) | (((unsigned) sg >> 3))) | 128); } static int storeRedgreenblueinto32Bits(int red, int green, int blue, unsigned char* dest) { dest[0] = blue; dest[1] = green; dest[2] = red; dest[3] = 255; } static int width(Device device) { return device->vwindow.width; } #ifdef SQUEAK_BUILTIN_PLUGIN void* VideoForLinuxPlugin_exports[][3] = { {"VideoForLinuxPlugin", "primitiveDeviceClose", (void*)primitiveDeviceClose}, {"VideoForLinuxPlugin", "primitiveDeviceGetHeight", (void*)primitiveDeviceGetHeight}, {"VideoForLinuxPlugin", "primitiveDeviceNextFrameIntoBrightnessContrastFormDepth", (void*)primitiveDeviceNextFrameIntoBrightnessContrastFormDepth}, {"VideoForLinuxPlugin", "primitiveDeviceDescribe", (void*)primitiveDeviceDescribe}, {"VideoForLinuxPlugin", "primitiveDeviceCreate", (void*)primitiveDeviceCreate}, {"VideoForLinuxPlugin", "getModuleName", (void*)getModuleName}, {"VideoForLinuxPlugin", "primitiveDeviceGetWidth", (void*)primitiveDeviceGetWidth}, {"VideoForLinuxPlugin", "setInterpreter", (void*)setInterpreter}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/VideoForLinuxPlugin.h ================================================ #ifndef _VIDEO_FOR_LINUX_PLUGIN_H #define _VIDEO_FOR_LINUX_PLUGIN_H #include "videolib.h" #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/acinclude.m4 ================================================ AC_MSG_CHECKING([for VideoForLinux support]) AC_TRY_COMPILE([ #include #include ],[;],[ AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) AC_PLUGIN_DISABLE ]) ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/ccvt.h ================================================ /* CCVT: ColourConVerT: simple library for converting colourspaces Copyright (C) 2002 Nemosoft Unv. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For questions, remarks, patches, etc. for this program, the author can be reached at nemosoft@smcc.demon.nl. */ /* $Log: ccvt.h,v $ Revision 1.10 2003/10/24 16:55:18 nemosoft removed erronous log messages Revision 1.9 2002/11/03 22:46:25 nemosoft Adding various RGB to RGB functions. Adding proper copyright header too. Revision 1.8 2002/04/14 01:00:27 nemosoft Finishing touches: adding const, adding libs for 'show' */ #ifndef CCVT_H #define CCVT_H #ifdef __cplusplus extern "C" { #endif /* Colour ConVerT: going from one colour space to another. ** NOTE: the set of available functions is far from complete! ** Format descriptions: 420i = "4:2:0 interlaced" YYYY UU YYYY UU even lines YYYY VV YYYY VV odd lines U/V data is subsampled by 2 both in horizontal and vertical directions, and intermixed with the Y values. 420p = "4:2:0 planar" YYYYYYYY N lines UUUU N/2 lines VVVV N/2 lines U/V is again subsampled, but all the Ys, Us and Vs are placed together in separate buffers. The buffers may be placed in one piece of contiguous memory though, with Y buffer first, followed by U, followed by V. yuyv = "4:2:2 interlaced" YUYV YUYV YUYV ... N lines The U/V data is subsampled by 2 in horizontal direction only. bgr24 = 3 bytes per pixel, in the order Blue Green Red (whoever came up with that idea...) rgb24 = 3 bytes per pixel, in the order Red Green Blue (which is sensible) rgb32 = 4 bytes per pixel, in the order Red Green Blue Alpha, with Alpha really being a filler byte (0) bgr32 = last but not least, 4 bytes per pixel, in the order Blue Green Red Alpha, Alpha again a filler byte (0) */ /* 4:2:0 YUV planar to RGB/BGR */ void ccvt_420p_bgr24(int width, int height, const void *src, void *dst); void ccvt_420p_rgb24(int width, int height, const void *src, void *dst); void ccvt_420p_bgr32(int width, int height, const void *src, void *dst); void ccvt_420p_rgb32(int width, int height, const void *src, void *dst); /* 4:2:2 YUYV interlaced to RGB/BGR */ void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst); void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst); /* 4:2:2 YUYV interlaced to 4:2:0 YUV planar */ void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv); /* RGB/BGR to 4:2:0 YUV interlaced */ /* RGB/BGR to 4:2:0 YUV planar */ void ccvt_rgb24_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv); void ccvt_bgr24_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv); /* RGB/BGR to RGB/BGR */ void ccvt_bgr24_bgr32(int width, int height, const void *const src, void *const dst); void ccvt_bgr24_rgb32(int width, int height, const void *const src, void *const dst); void ccvt_bgr32_bgr24(int width, int height, const void *const src, void *const dst); void ccvt_bgr32_rgb24(int width, int height, const void *const src, void *const dst); void ccvt_rgb24_bgr32(int width, int height, const void *const src, void *const dst); void ccvt_rgb24_rgb32(int width, int height, const void *const src, void *const dst); void ccvt_rgb32_bgr24(int width, int height, const void *const src, void *const dst); void ccvt_rgb32_rgb24(int width, int height, const void *const src, void *const dst); #ifdef __cplusplus } #endif #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/ccvt_c2.c ================================================ /* * Convert an image from yuv colourspace to rgb * * Code by Tony Hague (C) 2001. */ #include "ccvt.h" #include "ccvt_types.h" /* by suitable definition of PIXTYPE, can do yuv to rgb or bgr, with or without word alignment */ /* This doesn't exactly earn a prize in a programming beauty contest. */ #define WHOLE_FUNC2RGB(type) \ const unsigned char *y1, *y2, *u, *v; \ PIXTYPE_##type *l1, *l2; \ int r, g, b, cr, cg, cb, yp, j, i; \ \ if ((width & 1) || (height & 1)) \ return; \ \ l1 = (PIXTYPE_##type *)dst; \ l2 = l1 + width; \ y1 = (unsigned char *)src; \ y2 = y1 + width; \ u = (unsigned char *)src + width * height; \ v = u + (width * height) / 4; \ j = height / 2; \ while (j--) { \ i = width / 2; \ while (i--) { \ /* Since U & V are valid for 4 pixels, repeat code 4 \ times for different Y */ \ cb = ((*u-128) * 454)>>8; \ cr = ((*v-128) * 359)>>8; \ cg = ((*v-128) * 183 + (*u-128) * 88)>>8; \ \ yp = *(y1++); \ r = yp + cr; \ b = yp + cb; \ g = yp - cg; \ SAT(r); \ SAT(g); \ SAT(b); \ l1->b = b; \ l1->g = g; \ l1->r = r; \ l1++; \ \ yp = *(y1++); \ r = yp + cr; \ b = yp + cb; \ g = yp - cg; \ SAT(r); \ SAT(g); \ SAT(b); \ l1->b = b; \ l1->g = g; \ l1->r = r; \ l1++; \ \ yp = *(y2++); \ r = yp + cr; \ b = yp + cb; \ g = yp - cg; \ SAT(r); \ SAT(g); \ SAT(b); \ l2->b = b; \ l2->g = g; \ l2->r = r; \ l2++; \ \ yp = *(y2++); \ r = yp + cr; \ b = yp + cb; \ g = yp - cg; \ SAT(r); \ SAT(g); \ SAT(b); \ l2->b = b; \ l2->g = g; \ l2->r = r; \ l2++; \ \ u++; \ v++; \ } \ y1 = y2; \ y2 += width; \ l1 = l2; \ l2 += width; \ } void ccvt_420p_bgr32(int width, int height, const void *src, void *dst) { WHOLE_FUNC2RGB(bgr32) } void ccvt_420p_bgr24(int width, int height, const void *src, void *dst) { WHOLE_FUNC2RGB(bgr24) } void ccvt_420p_rgb32(int width, int height, const void *src, void *dst) { WHOLE_FUNC2RGB(rgb32) } void ccvt_420p_rgb24(int width, int height, const void *src, void *dst) { WHOLE_FUNC2RGB(rgb24) } ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/ccvt_misc.c ================================================ /* CCVT: ColourConVerT: simple library for converting colourspaces Copyright (C) 2002 Nemosoft Unv. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For questions, remarks, patches, etc. for this program, the author can be reached at nemosoft@smcc.demon.nl. */ /* This file contains CCVT functions that aren't available in assembly yet (or are not worth programming) */ /* * $Log: ccvt_misc.c,v $ * Revision 1.7 2003/01/02 04:10:19 nemosoft * Adding ''upside down" conversion to rgb/bgr routines * * Revision 1.6 2002/12/03 23:29:11 nemosoft * *** empty log message *** * * Revision 1.5 2002/12/03 23:27:41 nemosoft * fixing log messages (gcc 3.2 complaining) * Revision 1.4 2002/12/03 22:29:07 nemosoft Fixing up FTP stuff and some video Revision 1.3 2002/11/03 22:46:25 nemosoft Adding various RGB to RGB functions. Adding proper copyright header too. */ #include "ccvt.h" #include "ccvt_types.h" /* YUYV: two Y's and one U/V */ void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst) { } void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst) { const unsigned char *s; PIXTYPE_bgr32 *d; int l, c; int r, g, b, cr, cg, cb, y1, y2; l = height; s = src; d = dst; while (l--) { c = width >> 2; while (c--) { y1 = *s++; cb = ((*s - 128) * 454) >> 8; cg = (*s++ - 128) * 88; y2 = *s++; cr = ((*s - 128) * 359) >> 8; cg = (cg + (*s++ - 128) * 183) >> 8; r = y1 + cr; b = y1 + cb; g = y1 - cg; SAT(r); SAT(g); SAT(b); d->b = b; d->g = g; d->r = r; d++; r = y2 + cr; b = y2 + cb; g = y2 - cg; SAT(r); SAT(g); SAT(b); d->b = b; d->g = g; d->r = r; d++; } } } void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv) { int n, l, j; const unsigned char *s1, *s2; unsigned char *dy, *du, *dv; dy = (unsigned char *)dsty; du = (unsigned char *)dstu; dv = (unsigned char *)dstv; s1 = (unsigned char *)src; s2 = s1; // keep pointer n = width * height; for (; n > 0; n--) { *dy = *s1; dy++; s1 += 2; } /* Two options here: average U/V values, or skip every second row */ s1 = s2; // restore pointer s1++; // point to U for (l = 0; l < height; l += 2) { s2 = s1 + width * 2; // odd line for (j = 0; j < width; j += 2) { *du = (*s1 + *s2) / 2; du++; s1 += 2; s2 += 2; *dv = (*s1 + *s2) / 2; dv++; s1 += 2; s2 += 2; } s1 = s2; } } /* RGB/BGR to RGB/BGR */ #define RGBBGR_BODY24(TIN, TOUT) \ void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *const dst) \ { \ const PIXTYPE_ ## TIN *in = src; \ PIXTYPE_ ## TOUT *out = dst; \ int l, c, stride = 0; \ \ if (height < 0) { stride = width; height = -height; } \ out += ((height - 1) * width); \ stride *= 2; \ for (l = 0; l < height; l++) { \ for (c = 0; c < width; c++) { \ out->r = in->r; \ out->g = in->g; \ out->b = in->b; \ in++; \ out++; \ } \ out -= stride; \ } \ } #define RGBBGR_BODY32(TIN, TOUT) \ void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *const dst) \ { \ const PIXTYPE_ ## TIN *in = src; \ PIXTYPE_ ## TOUT *out = dst; \ int l, c, stride = 0; \ \ if (height < 0) { stride = width; height = -height; } \ out += ((height - 1) * width); \ stride *= 2; \ for (l = 0; l < height; l++) { \ for (c = 0; c < width; c++) { \ out->r = in->r; \ out->g = in->g; \ out->b = in->b; \ out->z = 0; \ in++; \ out++; \ } \ out -= stride; \ } \ } RGBBGR_BODY32(bgr24, bgr32) RGBBGR_BODY32(bgr24, rgb32) RGBBGR_BODY32(rgb24, bgr32) RGBBGR_BODY32(rgb24, rgb32) RGBBGR_BODY24(bgr32, bgr24) RGBBGR_BODY24(bgr32, rgb24) RGBBGR_BODY24(rgb32, bgr24) RGBBGR_BODY24(rgb32, rgb24) ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/ccvt_types.h ================================================ /* CCVT: ColourConVerT: simple library for converting colourspaces Copyright (C) 2002 Nemosoft Unv. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For questions, remarks, patches, etc. for this program, the author can be reached at nemosoft@smcc.demon.nl. */ #ifndef CCVT_TYPES_H #define CCVT_TYPES_H typedef struct { unsigned char b; unsigned char g; unsigned char r; unsigned char z; } PIXTYPE_bgr32; typedef struct { unsigned char b; unsigned char g; unsigned char r; } PIXTYPE_bgr24; typedef struct { unsigned char r; unsigned char g; unsigned char b; unsigned char z; } PIXTYPE_rgb32; typedef struct { unsigned char r; unsigned char g; unsigned char b; } PIXTYPE_rgb24; #define SAT(c) \ if (c & (~255)) { if (c < 0) c = 0; else c = 255; } #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/palettes.c ================================================ #include "ccvt.h" #include #include "palettes.h" struct palette_info { int id; char* name; float bytesPerPixel; Converter converterFunction24; Converter converterFunction16; int depth; }; inline void BGR24ToRGB32(int width, int height, const void *voidSrc, void *voidDst) { int i; unsigned char* dest = (unsigned char*) voidDst; unsigned char* src = (unsigned char*) voidSrc; unsigned char red, green, blue; const unsigned int widthTimesHeight = width * height; for (i = 0; i < widthTimesHeight; i++) { blue = *src++; green = *src++; red = *src++; *dest++ = red; *dest++ = green; *dest++ = blue; *dest++ = 255; } } inline void RGB565ToRGB24(int width, int height, const void *voidSrc, void *voidDst) { int i; const unsigned char* src = (unsigned char*) voidSrc; unsigned char* dest = (unsigned char*) voidDst; unsigned char b1, b2; unsigned char red, green, blue; const unsigned int widthTimesHeight = width * height; for (i = 0; i < widthTimesHeight; i++) { b2 = *src++; b1 = *src++; red = b1 & 248 /* 11111000 */; green = (b1 << 5) | (b2 >> 5); blue = b2 << 3; *dest++ = red; *dest++ = green; *dest++ = blue; } } inline void BGR24ToRGB24(int width, int height, const void *voidSrc, void *voidDst) { int i; unsigned char* dest = (unsigned char*) voidDst; unsigned char* src = (unsigned char*) voidSrc; unsigned char red, green, blue; const unsigned int widthTimesHeight = width * height; for (i = 0; i < widthTimesHeight; i++) { blue = *src++; green = *src++; red = *src++; *dest++ = red; *dest++ = green; *dest++ = blue; } } inline unsigned char clip(const int pixel) { int result; result = ((pixel < 0) ? 0 : pixel); return (unsigned char) ((result < 255) ? result : 255); } // from: http://en.wikipedia.org/wiki/YUV422 inline void YUV444toRGB888(const unsigned char y, const unsigned char u, const unsigned char v, unsigned char* dest) { const int C = y - 16; const int D = u - 128; const int E = v - 128; dest[0] = clip(( 298 * C + 409 * E + 128) >> 8); dest[1] = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8); dest[2] = clip(( 298 * C + 516 * D + 128) >> 8); } // from: http://en.wikipedia.org/wiki/YUV422 inline void YUYVToRGB24(int width, int height, const void *voidSrc, void *voidDst) { int i; const unsigned char* src = (unsigned char*) voidSrc; unsigned char* dest = (unsigned char*) voidDst; unsigned char u, y1, v, y2; const unsigned int widthTimesHeight = width * height; for (i = 0; i < widthTimesHeight; i += 2) { y1 = *src++; u = *src++; y2 = *src++; v = *src++; YUV444toRGB888(y1, u, v, dest); dest += 3; YUV444toRGB888(y2, u, v, dest); dest += 3; } } inline void YUV422ToRGB24(int width, int height, const void *voidSrc, void *voidDst) { int i; unsigned char* dest = (unsigned char*) voidDst; unsigned char* src = (unsigned char*) voidSrc; unsigned char u, y1, v, y2; const unsigned int widthTimesHeight = width * height; for (i = 0; i < widthTimesHeight; i += 2) { u = *src++; y1 = *src++; v = *src++; y2 = *src++; YUV444toRGB888(y1, u, v, dest); dest += 3; YUV444toRGB888(y2, u, v, dest); dest += 3; } } static struct palette_info palette_info_list[] = { { 0, "UNKOWN - Unkown palette", 0.0, 0, 0, 0}, { 1, "GREY - Linear greyscale", 0.0, 0, 0, 8}, { 2, "HI240 - High 240 cube (BT848)", 0.0, 0, 0, 8}, { 3, "RGB565 - 565 16 bit RGB", 2.0, RGB565ToRGB24, 0, 16}, { 4, "RGB24 - 24bit RGB", 3.0, BGR24ToRGB24, 0, 24}, { 5, "RGB32 - 32bit RGB", 4.0, ccvt_bgr32_rgb24, 0, 32}, { 6, "RGB555 - 555 15bit RGB", 0.0, 0, 0, 16}, { 7, "YUV422 - YUV422 capture", 1.5, YUV422ToRGB24, 0, 16}, { 8, "YUYV", 2.0, YUYVToRGB24, 0, 16}, { 9, "UYVY - The great thing about standards is ...", 0.0, 0, 0, 16}, {10, "YUV420", 1.5, ccvt_420p_rgb24, 0, 16}, {11, "YUV411 - YUV411 capture", 0.0, 0, 0, 12}, {12, "RAW - RAW capture (BT848)", 0.0, 0, 0, 8}, {13, "YUV422P - YUV 4:2:2 Planar", 0.0, 0, 0, 16}, {14, "YUV411P - YUV 4:1:1 Planar", 0.0, 0, 0, 12}, {15, "YUV420P - YUV 4:2:0 Planar", 1.5, ccvt_420p_rgb24, 0, 12}, {16, "YUV410P - YUV 4:1:0 Planar", 0.0, 0, 0, 9} }; inline float paletteBytesPerPixel(int palette) { float bytesPerPixel; if (palette < 1 || palette > 16) { fprintf(stdout, "* Invalid palette=%d\n", palette); return 0; } bytesPerPixel = palette_info_list[palette].bytesPerPixel; if (bytesPerPixel == 0) { fprintf(stdout, "* Palette=%d not yet supported\n", palette); return 0; } return bytesPerPixel; } inline char* paletteName(int palette) { if (palette == 0) { return "*automatic*"; } if (palette < 0 || palette > 16) { return "*UNKOWN*"; } return palette_info_list[palette].name; } inline Converter converterFunction(const int palette) { Converter funct; if (palette < 1 || palette > 16) { fprintf(stdout, "* Invalid palette=%d\n", palette); return 0; } funct = palette_info_list[palette].converterFunction24; if (funct == 0) { fprintf(stdout, "* Palette=%d not yet supported\n", palette); return 0; } return funct; } inline int paletteConvert24(const int palette, const int width, const int height, const void *src, void *dst) { Converter funct = converterFunction(palette); if (funct == 0) { return 0; } funct(width, height, src, dst); return 1; } inline int paletteDepth(int palette) { int depth; if (palette < 1 || palette > 16) { fprintf(stdout, "* Invalid palette=%d\n", palette); return 0; } depth = palette_info_list[palette].depth; if (depth == 0) { fprintf(stdout, "* Palette=%d not yet supported\n", palette); return 0; } return depth; } ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/palettes.h ================================================ #ifndef _PALETTES_H #define _PALETTES_H typedef void (*Converter)(int width, int height, const void *src, void *dst); inline char* paletteName (int palette); inline float paletteBytesPerPixel(int palette); inline int paletteDepth (int palette); inline Converter converterFunction (const int palette); inline int paletteConvert24 (int palette, int width, int height, const void *src, void *dst); #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/videolib.c ================================================ #include #include #include #include #include #include #include #include #include #include #include #include "palettes.h" #include "videolib.h" #define DEVICE_NAME_SIZE 12 static const char* videoDeviceBaseName = "/dev/video0"; /* thanks ned! */ #define EINTR_RETRY(expression) \ (__extension__ \ ({ \ long int __result; \ do { \ sigset_t ss1, ss2; \ \ sigemptyset(&ss1); /* init empty set of signals */ \ sigaddset(&ss1, SIGALRM); /* add ALRM to set of blocked signals */ \ /* can add more signals to block here */ \ sigprocmask(SIG_BLOCK, &ss1, &ss2); /* block some signals */ \ \ __result = (long int) (expression); \ \ sigprocmask(SIG_SETMASK, &ss2, NULL); /* restore */ \ } \ while ((__result == -1L) && (errno == EINTR)); \ __result; \ }) \ ) static int xioctl(int fd, int request, void *arg) { int r; do r = ioctl(fd, request, arg); while (-1 == r && EINTR == errno); return r; } int getBrightness(Device device) { return device->vpicture.brightness; } int getContrast(Device device) { return device->vpicture.contrast; } int getSaturation(Device device) { return device->vpicture.colour; } int getHue(Device device) { return device->vpicture.hue; } void showDeviceInformation(Device device) { fprintf(stdout, " - Device Information:\n"); fprintf(stdout, " ================================================================\n"); fprintf(stdout, " V4L1 Capabilities\n"); fprintf(stdout, " -----------------\n"); fprintf(stdout, " Name: %s\n", device->vcapability.name); fprintf(stdout, " Type: %d\n", device->vcapability.type); if (device->vcapability.type & VID_TYPE_CAPTURE) { fprintf(stdout, " Can capture to memory\n"); } if (device->vcapability.type & VID_TYPE_TUNER) { fprintf(stdout, " Has a tuner of some form\n"); } if (device->vcapability.type & VID_TYPE_TELETEXT) { fprintf(stdout, " Has teletext capability\n"); } if (device->vcapability.type & VID_TYPE_OVERLAY) { fprintf(stdout, " Can overlay its image onto the frame buffer\n"); } if (device->vcapability.type & VID_TYPE_CHROMAKEY) { fprintf(stdout, " Overlay is Chromakeyed\n"); } if (device->vcapability.type & VID_TYPE_CLIPPING) { fprintf(stdout, " Overlay clipping is supported\n"); } if (device->vcapability.type & VID_TYPE_FRAMERAM) { fprintf(stdout, " Overlay overwrites frame buffer memory\n"); } if (device->vcapability.type & VID_TYPE_SCALES) { fprintf(stdout, " The hardware supports image scaling\n"); } if (device->vcapability.type & VID_TYPE_MONOCHROME) { fprintf(stdout, " Image capture is grey scale only\n"); } if (device->vcapability.type & VID_TYPE_SUBCAPTURE) { fprintf(stdout, " Capture can be of only part of the image\n"); } if (device->vcapability.type & VID_TYPE_MPEG_ENCODER) { fprintf(stdout, " Can encode MPEG streams"); } if (device->vcapability.type & VID_TYPE_MJPEG_DECODER) { fprintf(stdout, " Can decode MJPEG streams"); } if (device->vcapability.type & VID_TYPE_MJPEG_ENCODER) { fprintf(stdout, " Can encode MJPEG streams"); } if (device->vcapability.type & VID_TYPE_MPEG_DECODER) { fprintf(stdout, " Can decode MPEG streams\n"); } fprintf(stdout, " Channels: %d Audios: %d MinExtent: %d@%d MaxExtent: %d@%d\n", device->vcapability.channels, device->vcapability.audios, device->vcapability.minwidth, device->vcapability.minheight, device->vcapability.maxwidth, device->vcapability.maxheight); if (device->isV4L2) { fprintf(stdout, " ----------------------------------------------------------------\n"); fprintf(stdout, " V4L2 Capabilities\n"); fprintf(stdout, " -----------------\n"); printf(" Driver: %s\n", device->v4l2Capability.driver); printf(" Card: %s\n", device->v4l2Capability.card); printf(" BusInfo: %s\n", device->v4l2Capability.bus_info); fprintf(stdout, " Capabilities: %d\n", device->v4l2Capability.capabilities); if (device->v4l2Capability.capabilities & V4L2_CAP_VIDEO_CAPTURE ) { fprintf(stdout, " Video Capture\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_VIDEO_OUTPUT ) { fprintf(stdout, " Video Output\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_VIDEO_OVERLAY ) { fprintf(stdout, " Video Overlay\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_VBI_CAPTURE ) { fprintf(stdout, " VBI Capture\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_VBI_OUTPUT ) { fprintf(stdout, " VBI Output\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_RDS_CAPTURE ) { fprintf(stdout, " RDS Capture\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_TUNER ) { fprintf(stdout, " Tuner\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_AUDIO ) { fprintf(stdout, " Audio\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_READWRITE ) { fprintf(stdout, " Read/Write\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_ASYNCIO ) { fprintf(stdout, " Async IO\n"); } if (device->v4l2Capability.capabilities & V4L2_CAP_STREAMING ) { fprintf(stdout, " Streaming\n"); } } fprintf(stdout, " ================================================================\n"); } void initDevice(Device device, char* deviceName, int width, int height, int palette) { device->deviceName = (char*) malloc(1024); memset(device->deviceName, 0, 1024); strcpy(device->deviceName, deviceName); device->desiredWidth = width; device->desiredHeight = height; device->desiredPalette = palette; device->fd = 0; device->buffer = 0; device->memoryMap = 0; device->mmaps = 0; device->imageSize = 0; device->bufferIndex = 0; device->buffer24 = 0; device->forceRead = FALSE; device->usingMMap = FALSE; device->isV4L2 = FALSE; device->converterFunction = 0; } void setupMMap(Device device) { int i; int mmapsSize; device->usingMMap = FALSE; fprintf(stdout, " - Seting up MMAP for device %p\n", device); if (EINTR_RETRY(xioctl(device->fd, VIDIOCGMBUF, &device->memoryBuffer)) < 0) { /* failed to retrieve information about capture memory space */ perror("VIDIOCGMBUF"); return; } fprintf(stdout, " - The device has %d buffers\n", device->memoryBuffer.frames); /* obtain memory mapped area */ device->memoryMap = (char*) mmap(0, device->memoryBuffer.size, PROT_READ /*| PROT_WRITE*/, MAP_SHARED, device->fd, 0); if (device->memoryMap < (char*)0) { fprintf(stdout, " * Failed to retrieve pointer to memory mapped area\n"); return; } /* allocate structures */ mmapsSize = device->memoryBuffer.frames * 32 * 4 /* sizeof(struct video_mmap)*/; fprintf(stdout, " - Allocing %d bytes\n", mmapsSize); device->mmaps = (struct video_mmap*) malloc(mmapsSize); if (device->mmaps == 0) { fprintf(stdout, " * Not enough memory\n"); return; } /* fill out the fields */ for (i = 0; i < device->memoryBuffer.frames; i++) { fprintf(stdout, " - Creating the mmap #%d\n", i); device->mmaps[i].frame = i; device->mmaps[i].width = device->vwindow.width; device->mmaps[i].height = device->vwindow.height; device->mmaps[i].format = device->vpicture.palette; } device->usingMMap = TRUE; } BOOLEAN startCaptureInBuffers(Device device) { int i; for (i = 0; i < (device->memoryBuffer.frames - 1); i++) { fprintf(stdout, "- Capturing buffer #%d (1st pass)\n", i); if (EINTR_RETRY(xioctl(device->fd, VIDIOCMCAPTURE, &device->mmaps[i])) < 0) { //if (xioctl(device->fd, VIDIOCMCAPTURE, &device->mmaps[i]) < 0) { perror("VIDIOCMCAPTURE1"); return FALSE; } } device->bufferIndex = device->memoryBuffer.frames - 1; return TRUE; } BOOLEAN switchToRead(Device device) { device->usingMMap = FALSE; device->buffer = (char*) malloc(device->imageSize); if (!device->buffer) { fprintf(stdout, "* Out of memory.\n"); return FALSE; } return TRUE; } BOOLEAN rawSetupPalette(Device device) { if (device->desiredPalette && (device->vpicture.palette != device->desiredPalette)) { fprintf(stdout, " - Changing the palette from %d (%s) to %d (%s) and depth from %d to %d\n", device->vpicture.palette, paletteName(device->vpicture.palette), device->desiredPalette, paletteName(device->desiredPalette), device->vpicture.depth, paletteDepth(device->desiredPalette)); device->vpicture.palette = device->desiredPalette; device->vpicture.depth = paletteDepth(device->desiredPalette); if (EINTR_RETRY(xioctl(device->fd, VIDIOCSPICT, &device->vpicture)) < 0) { perror("VIDIOCSPICT"); return FALSE; } if (paletteDepth(device->desiredPalette) != device->vpicture.depth) { fprintf(stdout, " * The device can't change the depth\n"); return FALSE; } if (device->desiredPalette != device->vpicture.palette) { fprintf(stdout, " * The device can't change the palette\n"); return FALSE; } } fprintf(stdout, " - Depth=%d Palette=%d (%s)\n", device->vpicture.depth, device->vpicture.palette, paletteName(device->vpicture.palette)); return TRUE; } /* let's try to change the bit depth and palette */ BOOLEAN setupPalette(Device device) { // The OLPC webcam supports palette 3 and 8, but 8 has better // quality. Let's try to use palette 8 and let's fallback in a // good way. if (device->desiredPalette == 0) { if (device->vpicture.palette == 3) { device->desiredPalette = 8; fprintf(stdout, " - Trying palette 8 instead of 3 (for better quality)\n"); if (rawSetupPalette(device)) { fprintf(stdout, " - Palette 8 set!\n"); return TRUE; } fprintf(stdout, " * Palette 8 can't be set!\n"); device->desiredPalette = 0; } } return rawSetupPalette(device); } BOOLEAN setupDevice(Device device) { BOOLEAN change; fprintf(stdout, "- Seting up device %p\n", device); /* check (again) for a valid device */ if (!(device->vcapability.type & VID_TYPE_CAPTURE)) { fprintf(stdout, " * The device can't capture video\n"); return FALSE; } if (device->vcapability.channels == 0) { fprintf(stdout, " * The device hasn't inputs\n"); return FALSE; } /* ---------------------------------------------------------------------- */ /* let's try to change the capture width & height */ change = FALSE; if (EINTR_RETRY(xioctl(device->fd, VIDIOCGWIN, &device->vwindow)) < 0) { perror("VIDIOCGWIN1"); return FALSE; } if (device->desiredWidth && (device->vwindow.width != device->desiredWidth)) { fprintf(stdout, " - Changing the width from %d to %d\n", device->vwindow.width, device->desiredWidth); device->vwindow.width = device->desiredWidth; change = TRUE; } if (device->desiredHeight && (device->vwindow.height != device->desiredHeight)) { fprintf(stdout, " - Changing the height from %d to %d\n", device->vwindow.height, device->desiredHeight); device->vwindow.height = device->desiredHeight; change = TRUE; } if (change) { if (EINTR_RETRY(xioctl(device->fd, VIDIOCSWIN, &device->vwindow)) < 0) { perror("VIDIOCGWIN2"); return FALSE; } if (EINTR_RETRY(xioctl(device->fd, VIDIOCGWIN, &device->vwindow)) < 0) { perror("VIDIOCGWIN3"); return FALSE; } if (device->desiredWidth != device->vwindow.width) { fprintf(stdout, " * The device can't change the capture width (now=%d)\n", device->vwindow.width); return FALSE; } if (device->desiredHeight != device->vwindow.height) { fprintf(stdout, " * The device can't change the capture height (now=%d)\n", device->vwindow.height); return FALSE; } } fprintf(stdout, " - Extent=%d@%d\n", device->vwindow.width, device->vwindow.height); if (EINTR_RETRY(xioctl(device->fd, VIDIOCGPICT, &device->vpicture)) < 0) { perror("VIDIOCGPICT"); return FALSE; } fprintf(stdout, " - Brightness=%d, Contrast=%d, Saturation=%d, Hue=%d\n", getBrightness(device), getContrast(device), getSaturation(device), getHue(device)); /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ if (!setupPalette(device)) { return FALSE; } /* ---------------------------------------------------------------------- */ device->imageSize = (int) device->vwindow.width * device->vwindow.height * (paletteBytesPerPixel(device->vpicture.palette)); device->buffer24 = (char*) malloc(device->vwindow.width * device->vwindow.height * 3); if (device->forceRead) { fprintf(stdout, " - Capturing using (forced) read()\n"); if (!switchToRead(device)) { return FALSE; } } else { setupMMap(device); if (device->usingMMap) { fprintf(stdout, " - Capturing using mmap()\n"); if (!startCaptureInBuffers(device)) { fprintf(stdout, " * Falling back to read()\n"); if (!switchToRead(device)) { return FALSE; } } } else { fprintf(stdout, " - Capturing using read()\n"); if (!switchToRead(device)) { return FALSE; } } } return TRUE; } void initializeDevice(Device device) { device->isV4L2 = FALSE; //if (EINTR_RETRY(xioctl(device->fd, VIDIOC_QUERYCAP, &cap)) < 0) { if (EINTR_RETRY(xioctl(device->fd, VIDIOC_QUERYCAP, &device->v4l2Capability)) < 0) { perror("VIDIOC_QUERYCAP"); fprintf(stderr, " - It doesn't appear to be a v4l2 device\n"); } else { device->isV4L2 = TRUE; } } BOOLEAN openDevice(Device device) { fprintf(stdout, "- Opening device in %p\n", device); /* open the video device */ device->fd = EINTR_RETRY(open(device->deviceName, O_RDWR)); if (device->fd < 0) { perror(device->deviceName); return FALSE; } fprintf(stdout, " - Opened %s with fd=%d\n", device->deviceName, device->fd); /* try to lock the device */ if (EINTR_RETRY(flock(device->fd, LOCK_EX | LOCK_NB)) < 0) { perror("FLOCK"); fprintf(stdout, " * Can't lock device\n"); return FALSE; } /* check for a valid device */ if (EINTR_RETRY(xioctl(device->fd, VIDIOCGCAP, &device->vcapability)) < 0) { perror("VIDIOCGCAP"); return FALSE; } initializeDevice(device); showDeviceInformation(device); return setupDevice(device); } Device createDevice(int deviceID, int width, int height, int palette) { char deviceName[DEVICE_NAME_SIZE]; strcpy(deviceName, videoDeviceBaseName); deviceName[DEVICE_NAME_SIZE - 2] = deviceID + '0'; Device device; fprintf(stdout, "- Creating Device: id=%d, deviceName=%s, extent=%d@%d, palette=%d-%s\n", deviceID, deviceName, width, height, palette, paletteName(palette)); device = (Device) malloc(SIZE_OF_DEVICE); if (device == 0) { fprintf(stdout, " * Not enough memory\n"); return 0; } fprintf(stdout, " - Structure created in %p\n", device); initDevice(device, deviceName, width, height, palette); if (openDevice(device)) { return device; } else { closeDevice(device); return 0; } } BOOLEAN nextFrameMMap(Device device) { //fprintf(stdout, "- capturing buffer #%d\n", device->bufferIndex); /* send a request to begin capturing to the currently indexed buffer */ if (EINTR_RETRY(xioctl(device->fd, VIDIOCMCAPTURE, &device->mmaps[device->bufferIndex])) < 0) { //if (xioctl(device->fd, VIDIOCMCAPTURE, &device->mmaps[device->bufferIndex]) < 0) { perror("VIDIOCMCAPTURE2"); return FALSE; } /* move bufferIndex to the next frame */ device->bufferIndex++; /* if bufferIndex is indexing beyond the last buffer set it to the first buffer */ device->bufferIndex %= device->memoryBuffer.frames; //fprintf(stdout, "- syncing buffer #%d\n", device->bufferIndex); /* wait for the currently indexed frame to complete capture */ if (EINTR_RETRY(xioctl(device->fd, VIDIOCSYNC, &(device->mmaps[device->bufferIndex]))) < 0) { //if (xioctl(device->fd, VIDIOCSYNC, &(device->mmaps[device->bufferIndex])) < 0) { /* sync request failed */ perror("VIDIOCSYNC"); return FALSE; } //fprintf(stdout, "- processing buffer #%d\n", device->bufferIndex); /* return the address of the frame data for the current buffer index */ device->buffer = device->memoryMap + device->memoryBuffer.offsets[device->bufferIndex]; return TRUE; } void closeDevice(Device device) { fprintf(stdout, "- Closing device in %p\n", device); if (device->deviceName) { free(device->deviceName); device->deviceName = 0; } if (device->buffer24) { free(device->buffer24); device->buffer24 = 0; } if (device->usingMMap) { if (device->mmaps) { free(device->mmaps); device->mmaps = 0; munmap(device->memoryMap, device->memoryBuffer.size); } } else { if (device->buffer) { free(device->buffer); } } if (device->fd > 0) { if (EINTR_RETRY(flock(device->fd, LOCK_UN)) < 0) { perror("FLOCK"); fprintf(stdout, " * Can't unlock device\n"); } close(device->fd); device->fd = 0; } fprintf(stdout, "- Destroying device in %p\n", device); free(device); } BOOLEAN convertBufferTo24(Device device) { if (device->converterFunction == 0) { device->converterFunction = converterFunction(device->vpicture.palette); if (device->converterFunction == 0) { return FALSE; } } device->converterFunction(device->vwindow.width, device->vwindow.height, device->buffer, device->buffer24); return TRUE; } BOOLEAN captureFrameFromDevice(Device device) { /* fprintf(stdout, "- Capturing from device in %p\n", device); */ if (device->usingMMap) { if (!nextFrameMMap(device)) { return FALSE; } } else { /* fprintf(stdout, "- reading...\n"); */ if (read(device->fd, device->buffer, device->imageSize) != device->imageSize) { fprintf(stdout, "\nThe device didn't answered the correct bytes.\n"); return FALSE; } } return TRUE; } BOOLEAN nextFrameFromDevice(Device device) { if (!captureFrameFromDevice(device)) { return FALSE; } return convertBufferTo24(device); //return TRUE; } void savePPM(char* fileName, Device device) { char *src = device->buffer24; char red, green, blue; unsigned int i; FILE* ppmFile = fopen(fileName, "w+"); fprintf(ppmFile, "P6\n%d %d 255\n", device->vwindow.width, device->vwindow.height); for (i = 0; i < device->vwindow.width * device->vwindow.height; i++) { red = *src++; green = *src++; blue = *src++; fputc(red, ppmFile); fputc(green, ppmFile); fputc(blue, ppmFile); } fclose(ppmFile); } int getPalette(Device device) { return device->vpicture.palette; } /* void setBrightness(Device device, int brightness) { device->vpicture.brightness = brightness; } void setContrast(Device device, int contrast) { device->vpicture.contrast = contrast; } void setSaturation(Device device, int saturation) { device->vpicture.colour = saturation; } void setHue(Device device, int hue) { device->vpicture.hue = hue; } */ BOOLEAN updatePicture(Device device) { if (EINTR_RETRY(xioctl(device->fd, VIDIOCSPICT, &device->vpicture)) < 0) { perror("VIDIOCSPICT"); return FALSE; } return TRUE; } void describeDevice(int deviceID, char* deviceName) { int fd; char device[DEVICE_NAME_SIZE]; memset(deviceName, 0, 32); strcpy(device, videoDeviceBaseName); device[DEVICE_NAME_SIZE - 2] = deviceID + '0'; //fprintf(stdout, "** trying to open: %d...\n", deviceID); fd = EINTR_RETRY(open(device, O_RDWR)); if (fd < 0) { return; } //fprintf(stdout, "** trying to lock: %d...\n", deviceID); /* try to lock the device */ if (EINTR_RETRY(flock(fd, LOCK_EX | LOCK_NB)) < 0) { close(fd); return; } struct video_capability vcapability; //fprintf(stdout, "** trying to see if it's a video device: %d...\n", deviceID); if (EINTR_RETRY(xioctl(fd, VIDIOCGCAP, &vcapability)) < 0) { close(fd); return; } memcpy(deviceName, vcapability.name, 32); fprintf(stdout, "- Detected Device: id=%d name=%s\n", deviceID, deviceName); close(fd); } ================================================ FILE: vm/src/from_squeak/unix/plugins/VideoForLinuxPlugin/videolib.h ================================================ #ifndef _VIDEOLIB_H #define _VIDEOLIB_H #include "palettes.h" #include typedef int BOOLEAN; #define TRUE 1 #define FALSE 0 struct dev { char* deviceName; unsigned int desiredWidth; unsigned int desiredHeight; char desiredPalette; int fd; struct video_capability vcapability; struct video_window vwindow; struct video_picture vpicture; char *buffer; struct video_mbuf memoryBuffer; char* memoryMap; struct video_mmap* mmaps; int imageSize; int bufferIndex; char *buffer24; BOOLEAN forceRead; BOOLEAN usingMMap; // Bitmap conversor Converter converterFunction; // V4L2 stuff BOOLEAN isV4L2; struct v4l2_capability v4l2Capability; }; typedef struct dev* Device; #define SIZE_OF_DEVICE sizeof(struct dev) void describeDevice(int deviceID, char* deviceName); Device createDevice(int deviceID, int width, int height, int palette); BOOLEAN convertBufferTo24 (Device device); BOOLEAN captureFrameFromDevice(Device device); BOOLEAN nextFrameFromDevice (Device device); int getPalette(Device device); /* int getBrightness(Device device); int getContrast (Device device); int getSaturation(Device device); int getHue (Device device); void setBrightness(Device device, int brightness); void setContrast (Device device, int contrast); void setSaturation(Device device, int saturation); void setHue (Device device, int hue); */ BOOLEAN updatePicture(Device device); void closeDevice(Device device); void savePPM(char* fileName, Device device); #endif ================================================ FILE: vm/src/from_squeak/unix/plugins/XDisplayControlPlugin/Makefile.inc ================================================ XCPPFLAGS= -I$(topdir)/platforms/Cross/plugins/FilePlugin -I$(topdir)/platforms/Cross/plugins/SocketPlugin XINCLUDES= $(X_INCLUDES) XLDFLAGS= $(X_LIBS) ================================================ FILE: vm/src/from_squeak/unix/plugins/XDisplayControlPlugin/acinclude.m4 ================================================ # Require X11 AC_CHECK_LIB(X11,XOpenDisplay, [AC_PLUGIN_USE_LIB(X11)], [AC_PLUGIN_DISABLE]) ================================================ FILE: vm/src/from_squeak/unix/plugins/XDisplayControlPlugin/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/plugins/XDisplayControlPlugin/config.cmake ================================================ IF (NOT X11_FOUND) PLUGIN_DISABLE () ELSE () PLUGIN_INCLUDE_DIRECTORIES (${cross}/plugins/FilePlugin ${cross}/plugins/SocketPlugin) ENDIF () ================================================ FILE: vm/src/from_squeak/unix/src/plugins/AioPlugin/AioPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:03 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include #define FILEHANDLETYPE FILE * /* the type of low level stream to be used in a struct SQFile */ #include "FilePlugin.h" #include "SocketPlugin.h" #include "config.h" #ifndef SQAIO_H # define SQAIO_H "aio.h" /* aio.h has been renamed to sqaio.h */ #endif #define SESSIONIDENTIFIERTYPE int #include SQAIO_H #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static void aioForwardwithDataandFlags(int fd, void *data, int flags); static sqInt fileDescriptorFrom(sqInt aSQFileByteArray); static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray); static sqInt fileRecordSize(void); static SQFile * fileValueOf(sqInt anSQFileRecord); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt getThisSessionIdentifier(void); static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt isNonNullSQFile(sqInt objectPointer); static sqInt isNullSQSocket(sqInt objectPointer); static sqInt isSQFileObject(sqInt objectPointer); static sqInt isSQSocketObject(sqInt objectPointer); static sqInt isValidFileSession(sqInt objectPointer); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveAioDisable(void); EXPORT(sqInt) primitiveAioEnable(void); EXPORT(sqInt) primitiveAioHandle(void); EXPORT(sqInt) primitiveAioSuspend(void); EXPORT(sqInt) primitiveModuleName(void); EXPORT(sqInt) primitiveOSFileHandle(void); EXPORT(sqInt) primitiveOSSocketHandle(void); EXPORT(sqInt) primitiveVersionString(void); #pragma export off static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static int socketDescriptorFrom(sqInt sqSocketOop); static sqInt socketRecordSize(void); static SQSocket * socketValueOf(sqInt anSQSocketRecord); static sqInt stringFromCString(const char *aCString); static char * versionString(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "AioPlugin 23 January 2011 (i)" #else "AioPlugin 23 January 2011 (e)" #endif ; /* This function is called to signal a Smalltalk Semaphore when an asynchronous event is detected. When translated to C, the name of this method is aioForwardwithDataandFlags. The event handler is set up by #primitiveAioHandle. */ static void aioForwardwithDataandFlags(int fd, void *data, int flags) { int *pfd; sqInt semaIndex; pfd = data; semaIndex = *pfd; interpreterProxy->signalSemaphoreWithIndex(semaIndex); } /* Answer the OS file descriptor, an integer value, from a SQFile data structure byte array, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). */ /* return type should be int, but skip the declaration to permit inlining */ static sqInt fileDescriptorFrom(sqInt aSQFileByteArray) { if (!((((interpreterProxy->isBytes(aSQFileByteArray)) && ((interpreterProxy->byteSizeOf(aSQFileByteArray)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(aSQFileByteArray))))) && (isNonNullSQFile(aSQFileByteArray)))) { return -1; } return fileno(fileHandleFrom(aSQFileByteArray)); } /* Answer a file handle from a SQFile structure. On most platforms, this will be a (FILE *). On Win32, it is a HANDLE. */ static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray) { SQFile *sqFile; sqFile = interpreterProxy->arrayValueOf(sqFileStructByteArray); return sqFile->file; } /* Answer the size of a SQFile data structure in bytes. */ static sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the SQFile data structure file record within anSQFileRecord, which is expected to be a ByteArray of size self>>fileRecordSize. */ static SQFile * fileValueOf(sqInt anSQFileRecord) { return interpreterProxy->arrayValueOf(anSQFileRecord); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt getThisSessionIdentifier(void) { return interpreterProxy->getThisSessionID(); } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { return 1; } /* Check for the common failure mode of a SQFile record with all zeros. */ static sqInt isNonNullSQFile(sqInt objectPointer) { sqInt idx; unsigned char *sqFileBytes; sqFileBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (fileRecordSize())) { if ((sqFileBytes[idx]) != 0) { return 1; } idx += 1; } return 0; } /* Check for the common failure mode of a SQSocket record with all zeros. */ static sqInt isNullSQSocket(sqInt objectPointer) { sqInt idx; unsigned char *sqSocketBytes; sqSocketBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (socketRecordSize())) { if ((sqSocketBytes[idx]) != 0) { return 0; } idx += 1; } return 1; } /* Answer true if objectPointer appears to be a valid SQFile ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid file reference. */ static sqInt isSQFileObject(sqInt objectPointer) { return (((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))))) && (isNonNullSQFile(objectPointer)); } /* Answer true if objectPointer appears to be a valid SQSocket ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid socket reference. */ static sqInt isSQSocketObject(sqInt objectPointer) { return ((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (socketRecordSize()))) && (!(isNullSQSocket(objectPointer))); } /* Answer true if the file session matches the current interpreter session identifier. */ static sqInt isValidFileSession(sqInt objectPointer) { return (interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Definitively disable asynchronous event notification for a descriptor. The parameter is an OS level integer file descriptor. */ EXPORT(sqInt) primitiveAioDisable(void) { sqInt fd; if ((interpreterProxy->nilObject()) == (interpreterProxy->stackValue(0))) { return interpreterProxy->primitiveFail(); } fd = interpreterProxy->stackIntegerValue(0); if (fd < 0) { return interpreterProxy->primitiveFail(); } aioDisable(fd); interpreterProxy->pop(2); interpreterProxy->pushInteger(fd); } /* Enable asynchronous notification for a descriptor. The first parameter is an OS level integer file descriptor. The second parameter is the index of a Semaphore to be notified, and the third parameter is a flag indicating that descriptor represents an external object and should not be closed on termination of aio handling. Answer the semaphore index. */ EXPORT(sqInt) primitiveAioEnable(void) { static int eventSemaphoreIndices[FD_SETSIZE]; sqInt externalObject; sqInt fd; sqInt flags; sqInt semaIndex; if ((interpreterProxy->nilObject()) == (interpreterProxy->stackValue(2))) { return interpreterProxy->primitiveFail(); } fd = interpreterProxy->stackIntegerValue(2); if (fd < 0) { return interpreterProxy->primitiveFail(); } semaIndex = interpreterProxy->stackIntegerValue(1); eventSemaphoreIndices[semaIndex] = semaIndex; externalObject = interpreterProxy->stackObjectValue(0); if (externalObject == (interpreterProxy->trueObject())) { flags = AIO_EXT; } else { flags = 0; } aioEnable(fd, &(eventSemaphoreIndices[semaIndex]), flags); interpreterProxy->pop(4); interpreterProxy->pushInteger(semaIndex); } /* Handle asynchronous event notification for a descriptor. The first parameter is an OS level integer file descriptor. The remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioHandle(void) { sqInt exceptionWatch; sqInt fd; sqInt flags; sqInt readWatch; sqInt writeWatch; if ((interpreterProxy->nilObject()) == (interpreterProxy->stackValue(3))) { return interpreterProxy->primitiveFail(); } fd = interpreterProxy->stackIntegerValue(3); if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioHandle(fd, aioForwardwithDataandFlags, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Temporarily suspend asynchronous event notification for a descriptor. The first parameter is an OS level integer file descriptor. The remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioSuspend(void) { sqInt exceptionWatch; sqInt fd; sqInt flags; sqInt readWatch; sqInt writeWatch; if ((interpreterProxy->nilObject()) == (interpreterProxy->stackValue(3))) { return interpreterProxy->primitiveFail(); } fd = interpreterProxy->stackIntegerValue(3); if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioSuspend(fd, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Answer a string containing the module name string for this plugin. */ EXPORT(sqInt) primitiveModuleName(void) { interpreterProxy->popthenPush(1, stringFromCString(moduleName)); } /* Take a struct SQFile from the stack, and answer the value of its Unix file number. */ EXPORT(sqInt) primitiveOSFileHandle(void) { sqInt fileNo; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { fileNo = -1; goto l1; } fileNo = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; interpreterProxy->pop(2); interpreterProxy->pushInteger(fileNo); } /* Take a struct SQSocket from the stack, and answer the value of its Unix file number. */ EXPORT(sqInt) primitiveOSSocketHandle(void) { sqInt fileNo; sqInt sqSocketOop; sqSocketOop = interpreterProxy->stackValue(0); if (!(((interpreterProxy->isBytes(sqSocketOop)) && ((interpreterProxy->byteSizeOf(sqSocketOop)) == (socketRecordSize()))) && (!(isNullSQSocket(sqSocketOop))))) { return interpreterProxy->primitiveFail(); } fileNo = socketDescriptorFrom(sqSocketOop); if (fileNo < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); interpreterProxy->pushInteger(fileNo); } /* Answer a string containing the version string for this plugin. */ EXPORT(sqInt) primitiveVersionString(void) { interpreterProxy->popthenPush(1, stringFromCString(versionString())); } /* Answer the session identifier from a SQFile structure. For a valid file reference, this identifier will match the session identifier supplied by the interpreter. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile) { return sqFile->sessionID; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { } /* Answer the OS file descriptor, an integer value, from a SQSocket data structure, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). Warning: The first element of privateSocketStruct happens to be the Unix file number of the socket. See sqUnixSocket.c for the definition. This method takes advantage of this, and will break if anyone ever redefines the data structure. */ static int socketDescriptorFrom(sqInt sqSocketOop) { void *privateSocketStruct; SQSocket *sqSocket; sqSocket = interpreterProxy->arrayValueOf(sqSocketOop); privateSocketStruct = sqSocket->privateSocketPtr; if (privateSocketStruct == 0) { return -1; } return * (int *) privateSocketStruct; } /* Answer the size of a SQSocket data structure in bytes. */ static sqInt socketRecordSize(void) { return sizeof(SQSocket); } /* Return a pointer to the first byte of of the SQsocket data structure socket record within anSQSocketRecord, which is expected to be a ByteArray of size self>>socketRecordSize. */ static SQSocket * socketValueOf(sqInt anSQSocketRecord) { return interpreterProxy->arrayValueOf(anSQSocketRecord); } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char *aCString) { sqInt len; sqInt newString; len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } /* Answer a string containing the version string for this plugin. Handle MNU errors, which can occur if class InterpreterPlugin has been removed from the system. Important: When this method is changed, the class side method must also be changed to match. */ /* 2.0 supports 64bit code base */ static char * versionString(void) { static char version[]= "2.2.2"; return version; } #ifdef SQUEAK_BUILTIN_PLUGIN void* AioPlugin_exports[][3] = { {"AioPlugin", "getModuleName", (void*)getModuleName}, {"AioPlugin", "primitiveOSSocketHandle", (void*)primitiveOSSocketHandle}, {"AioPlugin", "primitiveOSFileHandle", (void*)primitiveOSFileHandle}, {"AioPlugin", "primitiveAioHandle", (void*)primitiveAioHandle}, {"AioPlugin", "primitiveAioEnable", (void*)primitiveAioEnable}, {"AioPlugin", "primitiveVersionString", (void*)primitiveVersionString}, {"AioPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"AioPlugin", "primitiveModuleName", (void*)primitiveModuleName}, {"AioPlugin", "setInterpreter", (void*)setInterpreter}, {"AioPlugin", "primitiveAioSuspend", (void*)primitiveAioSuspend}, {"AioPlugin", "shutdownModule", (void*)shutdownModule}, {"AioPlugin", "initialiseModule", (void*)initialiseModule}, {"AioPlugin", "primitiveAioDisable", (void*)primitiveAioDisable}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 6:31:52 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "B3DAcceleratorPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static void* fetchLightSourceofObject(sqInt index, sqInt anArray); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveAllocateTexture(void); EXPORT(sqInt) primitiveClearDepthBuffer(void); EXPORT(sqInt) primitiveClearViewport(void); EXPORT(sqInt) primitiveCompositeTexture(void); EXPORT(sqInt) primitiveCreateRenderer(void); EXPORT(sqInt) primitiveCreateRendererFlags(void); EXPORT(sqInt) primitiveDestroyRenderer(void); EXPORT(sqInt) primitiveDestroyTexture(void); EXPORT(sqInt) primitiveFinishRenderer(void); EXPORT(sqInt) primitiveFlushRenderer(void); EXPORT(sqInt) primitiveGetIntProperty(void); EXPORT(sqInt) primitiveGetRendererColorMasks(void); EXPORT(sqInt) primitiveGetRendererSurfaceDepth(void); EXPORT(sqInt) primitiveGetRendererSurfaceHandle(void); EXPORT(sqInt) primitiveGetRendererSurfaceHeight(void); EXPORT(sqInt) primitiveGetRendererSurfaceWidth(void); EXPORT(sqInt) primitiveIsOverlayRenderer(void); EXPORT(sqInt) primitiveRenderVertexBuffer(void); EXPORT(sqInt) primitiveRendererVersion(void); EXPORT(sqInt) primitiveSetBufferRect(void); EXPORT(sqInt) primitiveSetFog(void); EXPORT(sqInt) primitiveSetIntProperty(void); EXPORT(sqInt) primitiveSetLights(void); EXPORT(sqInt) primitiveSetMaterial(void); EXPORT(sqInt) primitiveSetTransform(void); EXPORT(sqInt) primitiveSetVerboseLevel(void); EXPORT(sqInt) primitiveSetViewport(void); EXPORT(sqInt) primitiveSwapRendererBuffers(void); EXPORT(sqInt) primitiveTextureByteSex(void); EXPORT(sqInt) primitiveTextureDepth(void); EXPORT(sqInt) primitiveTextureGetColorMasks(void); EXPORT(sqInt) primitiveTextureSurfaceHandle(void); EXPORT(sqInt) primitiveTextureUpload(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt stackLightArrayValue(sqInt stackIndex); static void * stackMaterialValue(sqInt stackIndex); static void* stackMatrix(sqInt index); static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex); static void* stackPrimitiveVertex(sqInt index); static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "B3DAcceleratorPlugin 23 January 2011 (i)" #else "B3DAcceleratorPlugin 23 January 2011 (e)" #endif ; /* Fetch the primitive light source from the given array. Note: No checks are done within here - that happened in stackLightArrayValue: */ static void* fetchLightSourceofObject(sqInt index, sqInt anArray) { sqInt lightOop; lightOop = interpreterProxy->fetchPointerofObject(index, anArray); return interpreterProxy->firstIndexableField(lightOop); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { return b3dxInitialize(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primitiveAllocateTexture(void) { sqInt d; sqInt h; sqInt renderer; sqInt result; sqInt w; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); d = interpreterProxy->stackIntegerValue(2); renderer = interpreterProxy->stackIntegerValue(3); if (interpreterProxy->failed()) { return null; } result = b3dxAllocateTexture(renderer, w, h, d); if (result == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(5); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveClearDepthBuffer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxClearDepthBuffer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveClearViewport(void) { sqInt handle; sqInt pv; sqInt result; sqInt rgba; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } pv = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); rgba = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(1)); handle = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } result = b3dxClearViewport(handle, rgba, pv); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveCompositeTexture(void) { sqInt h; sqInt rendererHandle; sqInt result; sqInt texHandle; sqInt translucent; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 7)) { return interpreterProxy->primitiveFail(); } translucent = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); h = interpreterProxy->stackIntegerValue(1); w = interpreterProxy->stackIntegerValue(2); y = interpreterProxy->stackIntegerValue(3); x = interpreterProxy->stackIntegerValue(4); texHandle = interpreterProxy->stackIntegerValue(5); rendererHandle = interpreterProxy->stackIntegerValue(6); if (interpreterProxy->failed()) { return null; } result = b3dxCompositeTexture(rendererHandle, texHandle, x, y, w, h, translucent); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(7); } /* NOTE: This primitive is obsolete but should be supported for older images */ EXPORT(sqInt) primitiveCreateRenderer(void) { sqInt allowHardware; sqInt allowSoftware; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); allowHardware = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(4)); allowSoftware = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(5)); if (interpreterProxy->failed()) { return null; } result = b3dxCreateRenderer(allowSoftware, allowHardware, x, y, w, h); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(7); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveCreateRendererFlags(void) { sqInt flags; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); flags = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxCreateRendererFlags(x, y, w, h, flags); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(6); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveDestroyRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxDestroyRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDestroyTexture(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxDestroyTexture(renderer, handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } EXPORT(sqInt) primitiveFinishRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxFinishRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveFlushRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxFlushRenderer(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveGetIntProperty(void) { sqInt handle; sqInt prop; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } prop = interpreterProxy->stackIntegerValue(0); handle = interpreterProxy->stackIntegerValue(1); result = b3dxGetIntProperty(handle, prop); interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererColorMasks(void) { sqInt array; sqInt arrayOop; sqInt handle; sqInt i; int masks[4]; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } array = interpreterProxy->stackObjectValue(0); handle = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(array)) == 4)) { return interpreterProxy->primitiveFail(); } result = b3dxGetRendererColorMasks(handle, masks); if (!(result)) { return interpreterProxy->primitiveFail(); } arrayOop = array; for (i = 0; i <= 3; i += 1) { interpreterProxy->pushRemappableOop(arrayOop); result = interpreterProxy->positive32BitIntegerFor(masks[i]); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, result); } return interpreterProxy->pop(2); } EXPORT(sqInt) primitiveGetRendererSurfaceDepth(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceDepth(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceHandle(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceHandle(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceHeight(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceHeight(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveGetRendererSurfaceWidth(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxGetRendererSurfaceWidth(handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveIsOverlayRenderer(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxIsOverlayRenderer(handle); interpreterProxy->pop(2); return interpreterProxy->pushBool(result); } EXPORT(sqInt) primitiveRenderVertexBuffer(void) { sqInt flags; sqInt handle; int *idxArray; sqInt idxCount; sqInt primType; sqInt result; sqInt texHandle; float *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 8)) { return interpreterProxy->primitiveFail(); } idxCount = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); texHandle = interpreterProxy->stackIntegerValue(4); flags = interpreterProxy->stackIntegerValue(5); primType = interpreterProxy->stackIntegerValue(6); handle = interpreterProxy->stackIntegerValue(7); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxCount, 1, vtxCount); if ((vtxArray == null) || ((idxArray == null) || ((primType < 1) || ((primType > 6) || (interpreterProxy->failed()))))) { return interpreterProxy->primitiveFail(); } result = b3dxRenderVertexBuffer(handle, primType, flags, texHandle, vtxArray, vtxCount, idxArray, idxCount); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(8); } EXPORT(sqInt) primitiveRendererVersion(void) { if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); return interpreterProxy->pushInteger(1); } /* Primitive. Set the buffer rectangle (e.g., the pixel area on screen) to use for this renderer. The viewport is positioned within the buffer rectangle. */ EXPORT(sqInt) primitiveSetBufferRect(void) { sqInt h; sqInt handle; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); handle = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxSetBufferRect(handle, x, y, w, h); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(5); } EXPORT(sqInt) primitiveSetFog(void) { double density; sqInt fogType; sqInt handle; sqInt result; sqInt rgba; double start; double stop; if (!((interpreterProxy->methodArgumentCount()) == 6)) { return interpreterProxy->primitiveFail(); } rgba = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); stop = interpreterProxy->floatValueOf(interpreterProxy->stackValue(1)); start = interpreterProxy->floatValueOf(interpreterProxy->stackValue(2)); density = interpreterProxy->floatValueOf(interpreterProxy->stackValue(3)); fogType = interpreterProxy->stackIntegerValue(4); handle = interpreterProxy->stackIntegerValue(5); if (interpreterProxy->failed()) { return null; } result = b3dxSetFog(handle, fogType, density, start, stop, rgba); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(6); } EXPORT(sqInt) primitiveSetIntProperty(void) { sqInt handle; sqInt prop; sqInt result; sqInt value; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } value = interpreterProxy->stackIntegerValue(0); prop = interpreterProxy->stackIntegerValue(1); handle = interpreterProxy->stackIntegerValue(2); result = b3dxSetIntProperty(handle, prop, value); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveSetLights(void) { sqInt handle; sqInt i; void* light; sqInt lightArray; sqInt lightCount; sqInt lightOop; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } lightArray = stackLightArrayValue(0); handle = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!(b3dxDisableLights(handle))) { return interpreterProxy->primitiveFail(); } if (lightArray == null) { return null; } /* For each enabled light source */ lightCount = interpreterProxy->slotSizeOf(lightArray); for (i = 0; i <= (lightCount - 1); i += 1) { /* begin fetchLightSource:ofObject: */ lightOop = interpreterProxy->fetchPointerofObject(i, lightArray); light = interpreterProxy->firstIndexableField(lightOop); if (!(b3dxLoadLight(handle, i, light))) { return interpreterProxy->primitiveFail(); } } return interpreterProxy->pop(2); } EXPORT(sqInt) primitiveSetMaterial(void) { sqInt handle; void*material; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } material = stackMaterialValue(0); handle = interpreterProxy->stackIntegerValue(1); if (!(b3dxLoadMaterial(handle, material))) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } /* Transform an entire vertex buffer using the supplied modelview and projection matrix. */ EXPORT(sqInt) primitiveSetTransform(void) { sqInt handle; float *modelViewMatrix; float *projectionMatrix; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } projectionMatrix = stackMatrix(0); modelViewMatrix = stackMatrix(1); handle = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } b3dxSetTransform(handle, modelViewMatrix, projectionMatrix); return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveSetVerboseLevel(void) { sqInt level; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } level = interpreterProxy->stackIntegerValue(0); result = b3dxSetVerboseLevel(level); interpreterProxy->pop(2); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveSetViewport(void) { sqInt h; sqInt handle; sqInt result; sqInt w; sqInt x; sqInt y; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } h = interpreterProxy->stackIntegerValue(0); w = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(3); handle = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } result = b3dxSetViewport(handle, x, y, w, h); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(5); } EXPORT(sqInt) primitiveSwapRendererBuffers(void) { sqInt handle; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = b3dxSwapRendererBuffers(handle); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } EXPORT(sqInt) primitiveTextureByteSex(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxTextureByteSex(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushBool(result); } EXPORT(sqInt) primitiveTextureDepth(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxActualTextureDepth(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveTextureGetColorMasks(void) { sqInt array; sqInt arrayOop; sqInt handle; sqInt i; int masks[4]; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } array = interpreterProxy->stackObjectValue(0); handle = interpreterProxy->stackIntegerValue(1); renderer = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(array)) == 4)) { return interpreterProxy->primitiveFail(); } result = b3dxTextureColorMasks(renderer, handle, masks); if (!(result)) { return interpreterProxy->primitiveFail(); } arrayOop = array; for (i = 0; i <= 3; i += 1) { interpreterProxy->pushRemappableOop(arrayOop); result = interpreterProxy->positive32BitIntegerFor(masks[i]); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, result); } return interpreterProxy->pop(3); } EXPORT(sqInt) primitiveTextureSurfaceHandle(void) { sqInt handle; sqInt renderer; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } handle = interpreterProxy->stackIntegerValue(0); renderer = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } result = b3dxTextureSurfaceHandle(renderer, handle); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(3); return interpreterProxy->pushInteger(result); } EXPORT(sqInt) primitiveTextureUpload(void) { sqInt bits; void*bitsPtr; sqInt d; sqInt form; sqInt h; sqInt handle; sqInt ppw; sqInt renderer; sqInt result; sqInt w; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } form = interpreterProxy->stackValue(0); if (!((interpreterProxy->isPointers(form)) && ((interpreterProxy->slotSizeOf(form)) >= 4))) { return interpreterProxy->primitiveFail(); } bits = interpreterProxy->fetchPointerofObject(0, form); w = interpreterProxy->fetchIntegerofObject(1, form); h = interpreterProxy->fetchIntegerofObject(2, form); d = interpreterProxy->fetchIntegerofObject(3, form); ppw = 32 / d; if (!(interpreterProxy->isWords(bits))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->slotSizeOf(bits)) == ((((w + ppw) - 1) / ppw) * h))) { return interpreterProxy->primitiveFail(); } bitsPtr = interpreterProxy->firstIndexableField(bits); handle = interpreterProxy->stackIntegerValue(1); renderer = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } result = b3dxUploadTexture(renderer, handle, w, h, d, bitsPtr); if (!(result)) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(3); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return b3dxShutdown(); } /* Load an Array of B3DPrimitiveLights from the given stack index */ static sqInt stackLightArrayValue(sqInt stackIndex) { sqInt array; sqInt arraySize; sqInt i; sqInt oop; array = interpreterProxy->stackObjectValue(stackIndex); if (array == null) { return null; } if (array == (interpreterProxy->nilObject())) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(array); for (i = 0; i <= (arraySize - 1); i += 1) { oop = interpreterProxy->fetchPointerofObject(i, array); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 32))) { return interpreterProxy->primitiveFail(); } } return array; } /* Load a B3DMaterial from the given stack index */ static void * stackMaterialValue(sqInt stackIndex) { sqInt oop; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (oop == (interpreterProxy->nilObject())) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 17)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a 4x4 transformation matrix from the interpreter stack. Return a pointer to the matrix data if successful, nil otherwise. */ static void* stackMatrix(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if (oop == (interpreterProxy->nilObject())) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive index array from the interpreter stack. If aBool is true then check that all the indexes are in the range (1,maxIndex). Return a pointer to the index data if successful, nil otherwise. */ static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex) { sqInt i; int *idxPtr; sqInt index; sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (!(interpreterProxy->isWords(oop))) { return null; } oopSize = interpreterProxy->slotSizeOf(oop); if (oopSize < nItems) { return null; } idxPtr = ((int *) (interpreterProxy->firstIndexableField(oop))); if (aBool) { for (i = 0; i <= (nItems - 1); i += 1) { index = idxPtr[i]; if ((index < 0) || (index > maxIndex)) { return null; } } } return idxPtr; } /* Load a primitive vertex from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertex(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive vertex array from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems) { sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if (interpreterProxy->isWords(oop)) { oopSize = interpreterProxy->slotSizeOf(oop); if (((oopSize >= nItems) * 16) && ((oopSize % 16) == 0)) { return interpreterProxy->firstIndexableField(oop); } } return null; } #ifdef SQUEAK_BUILTIN_PLUGIN void* B3DAcceleratorPlugin_exports[][3] = { {"B3DAcceleratorPlugin", "primitiveTextureByteSex", (void*)primitiveTextureByteSex}, {"B3DAcceleratorPlugin", "primitiveSetVerboseLevel", (void*)primitiveSetVerboseLevel}, {"B3DAcceleratorPlugin", "primitiveSetIntProperty", (void*)primitiveSetIntProperty}, {"B3DAcceleratorPlugin", "primitiveDestroyRenderer", (void*)primitiveDestroyRenderer}, {"B3DAcceleratorPlugin", "primitiveRenderVertexBuffer", (void*)primitiveRenderVertexBuffer}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceDepth", (void*)primitiveGetRendererSurfaceDepth}, {"B3DAcceleratorPlugin", "primitiveSwapRendererBuffers", (void*)primitiveSwapRendererBuffers}, {"B3DAcceleratorPlugin", "shutdownModule", (void*)shutdownModule}, {"B3DAcceleratorPlugin", "primitiveTextureGetColorMasks", (void*)primitiveTextureGetColorMasks}, {"B3DAcceleratorPlugin", "primitiveTextureDepth", (void*)primitiveTextureDepth}, {"B3DAcceleratorPlugin", "primitiveCreateRendererFlags", (void*)primitiveCreateRendererFlags}, {"B3DAcceleratorPlugin", "primitiveSetLights", (void*)primitiveSetLights}, {"B3DAcceleratorPlugin", "primitiveTextureSurfaceHandle", (void*)primitiveTextureSurfaceHandle}, {"B3DAcceleratorPlugin", "primitiveGetRendererColorMasks", (void*)primitiveGetRendererColorMasks}, {"B3DAcceleratorPlugin", "getModuleName", (void*)getModuleName}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceHeight", (void*)primitiveGetRendererSurfaceHeight}, {"B3DAcceleratorPlugin", "primitiveCompositeTexture", (void*)primitiveCompositeTexture}, {"B3DAcceleratorPlugin", "primitiveFinishRenderer", (void*)primitiveFinishRenderer}, {"B3DAcceleratorPlugin", "primitiveRendererVersion", (void*)primitiveRendererVersion}, {"B3DAcceleratorPlugin", "setInterpreter", (void*)setInterpreter}, {"B3DAcceleratorPlugin", "primitiveSetViewport", (void*)primitiveSetViewport}, {"B3DAcceleratorPlugin", "primitiveSetBufferRect", (void*)primitiveSetBufferRect}, {"B3DAcceleratorPlugin", "primitiveSetMaterial", (void*)primitiveSetMaterial}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceWidth", (void*)primitiveGetRendererSurfaceWidth}, {"B3DAcceleratorPlugin", "primitiveTextureUpload", (void*)primitiveTextureUpload}, {"B3DAcceleratorPlugin", "primitiveSetTransform", (void*)primitiveSetTransform}, {"B3DAcceleratorPlugin", "primitiveSetFog", (void*)primitiveSetFog}, {"B3DAcceleratorPlugin", "primitiveClearDepthBuffer", (void*)primitiveClearDepthBuffer}, {"B3DAcceleratorPlugin", "primitiveFlushRenderer", (void*)primitiveFlushRenderer}, {"B3DAcceleratorPlugin", "initialiseModule", (void*)initialiseModule}, {"B3DAcceleratorPlugin", "primitiveDestroyTexture", (void*)primitiveDestroyTexture}, {"B3DAcceleratorPlugin", "primitiveClearViewport", (void*)primitiveClearViewport}, {"B3DAcceleratorPlugin", "primitiveAllocateTexture", (void*)primitiveAllocateTexture}, {"B3DAcceleratorPlugin", "primitiveCreateRenderer", (void*)primitiveCreateRenderer}, {"B3DAcceleratorPlugin", "primitiveIsOverlayRenderer", (void*)primitiveIsOverlayRenderer}, {"B3DAcceleratorPlugin", "primitiveGetRendererSurfaceHandle", (void*)primitiveGetRendererSurfaceHandle}, {"B3DAcceleratorPlugin", "primitiveGetIntProperty", (void*)primitiveGetIntProperty}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/ClipboardExtendedPlugin/ClipboardExtendedPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:50 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) ioAddClipboardData(void); EXPORT(sqInt) ioClearClipboard(void); EXPORT(sqInt) ioCreateClipboard(void); EXPORT(sqInt) ioGetClipboardFormat(void); EXPORT(sqInt) ioReadClipboardData(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "ClipboardExtendedPlugin 23 January 2011 (i)" #else "ClipboardExtendedPlugin 23 January 2011 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) ioAddClipboardData(void) { sqInt clipboardAddress; sqInt formatLength; sqInt dataLength; sqInt clipboard; char *data; char *aFormat; clipboard = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); data = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aFormat = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); dataLength = interpreterProxy->slotSizeOf((oopForPointer( data ) - BASE_HEADER_SIZE)); formatLength = interpreterProxy->slotSizeOf((oopForPointer( aFormat ) - BASE_HEADER_SIZE)); sqPasteboardPutItemFlavordatalengthformatTypeformatLength(clipboardAddress, data, dataLength, aFormat, formatLength); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) ioClearClipboard(void) { sqInt clipboardAddress; sqInt clipboard; clipboard = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); sqPasteboardClear(clipboardAddress); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) ioCreateClipboard(void) { sqInt clipboardAddress; clipboardAddress = interpreterProxy->positive32BitIntegerFor(sqCreateClipboard()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, clipboardAddress); return null; } EXPORT(sqInt) ioGetClipboardFormat(void) { sqInt clipboardAddress; sqInt itemCount; sqInt clipboard; sqInt formatNumber; sqInt _return_value; clipboard = interpreterProxy->stackValue(1); formatNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); itemCount = sqPasteboardGetItemCount(clipboardAddress); if (itemCount > 0) { _return_value = sqPasteboardCopyItemFlavorsitemNumber(clipboardAddress, formatNumber); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) ioReadClipboardData(void) { sqInt clipboardAddress; sqInt formatLength; sqInt clipboard; char *format; sqInt _return_value; clipboard = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); format = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } clipboardAddress = interpreterProxy->positive32BitValueOf(clipboard); formatLength = interpreterProxy->slotSizeOf((oopForPointer( format ) - BASE_HEADER_SIZE)); _return_value = sqPasteboardCopyItemFlavorDataformatformatLength(clipboardAddress, format, formatLength); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* ClipboardExtendedPlugin_exports[][3] = { {"ClipboardExtendedPlugin", "getModuleName", (void*)getModuleName}, {"ClipboardExtendedPlugin", "ioClearClipboard", (void*)ioClearClipboard}, {"ClipboardExtendedPlugin", "setInterpreter", (void*)setInterpreter}, {"ClipboardExtendedPlugin", "ioGetClipboardFormat", (void*)ioGetClipboardFormat}, {"ClipboardExtendedPlugin", "ioCreateClipboard", (void*)ioCreateClipboard}, {"ClipboardExtendedPlugin", "ioAddClipboardData", (void*)ioAddClipboardData}, {"ClipboardExtendedPlugin", "ioReadClipboardData", (void*)ioReadClipboardData}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/DBusPlugin/DBusPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:51 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "aio.h" #define DBUS_API_SUBJECT_TO_CHANGE #include typedef struct sqDBusData { DBusConnection* con; DBusWatch* watch; int semaphore; } sqDBusData; #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt argumentsAddBooltoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddBytetoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddDoubletoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddInt16toIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddInt32toIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddInt64toIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddObjectPathtoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddSignaturetoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddStringtoIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddUInt16toIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddUInt32toIter(sqInt oop, DBusMessageIter*iter); static sqInt argumentsAddUInt64toIter(sqInt oop, DBusMessageIter*iter); static sqInt buildStringOopFromCharP(const char*charP); static sqInt closeConnection(sqInt index); static DBusMessage * createErrorTofrom(char*dest, sqInt msgOop); static DBusMessage * createReplyTofrom(char*dest, sqInt msgOop); static char * fetchStringofObject(sqInt n, sqInt oop); static sqInt getBasicTypevalue(int t, void*val); static DBusConnection * getConnectionFromOop(sqInt aDBusConnection); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt handleflag(int fd, int flag); static sqInt handleReadForFDwithDataandFlag(int fd, sqDBusData*data, int flag); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt iterOpenContainercontains(sqInt t, char*s); static sqInt msg(char *s); static sqDBusData* newDataStructWithConnectionandSemaphore(DBusConnection *con, int semaphore); #pragma export on EXPORT(sqInt) primitiveDBusAddMatch(void); EXPORT(sqInt) primitiveDBusAppendBasicArgument(void); EXPORT(sqInt) primitiveDBusArgumentGetBool(void); EXPORT(sqInt) primitiveDBusArgumentGetByte(void); EXPORT(sqInt) primitiveDBusArgumentGetDouble(void); EXPORT(sqInt) primitiveDBusArgumentGetInt16(void); EXPORT(sqInt) primitiveDBusArgumentGetInt32(void); EXPORT(sqInt) primitiveDBusArgumentGetInt64(void); EXPORT(sqInt) primitiveDBusArgumentGetObjectPath(void); EXPORT(sqInt) primitiveDBusArgumentGetSignature(void); EXPORT(sqInt) primitiveDBusArgumentGetString(void); EXPORT(sqInt) primitiveDBusArgumentGetType(void); EXPORT(sqInt) primitiveDBusArgumentGetUInt16(void); EXPORT(sqInt) primitiveDBusArgumentGetUInt32(void); EXPORT(sqInt) primitiveDBusArgumentGetUInt64(void); EXPORT(sqInt) primitiveDBusConnectionClose(void); EXPORT(sqInt) primitiveDBusConnectionDispatchStatus(void); EXPORT(sqInt) primitiveDBusConnectionPopMessage(void); EXPORT(sqInt) primitiveDBusCreateMessageFrom(void); EXPORT(sqInt) primitiveDBusInitializeWriteIterator(void); EXPORT(sqInt) primitiveDBusIterCloseContainer(void); EXPORT(sqInt) primitiveDBusIterOpenContainerContains(void); EXPORT(sqInt) primitiveDBusIteratorSignature(void); EXPORT(sqInt) primitiveDBusMessageGetDestination(void); EXPORT(sqInt) primitiveDBusMessageGetErrorName(void); EXPORT(sqInt) primitiveDBusMessageGetInterface(void); EXPORT(sqInt) primitiveDBusMessageGetMember(void); EXPORT(sqInt) primitiveDBusMessageGetNoReply(void); EXPORT(sqInt) primitiveDBusMessageGetPath(void); EXPORT(sqInt) primitiveDBusMessageGetReplySerial(void); EXPORT(sqInt) primitiveDBusMessageGetSender(void); EXPORT(sqInt) primitiveDBusMessageGetSerial(void); EXPORT(sqInt) primitiveDBusMessageGetSignature(void); EXPORT(sqInt) primitiveDBusMessageHasArguments(void); EXPORT(sqInt) primitiveDBusNextIterator(void); EXPORT(sqInt) primitiveDBusPopMessageIterator(void); EXPORT(sqInt) primitiveDBusPushMessageIterator(void); EXPORT(sqInt) primitiveDBusRegisterName(void); EXPORT(sqInt) primitiveDBusReleaseName(void); EXPORT(sqInt) primitiveDBusRemoveMatch(void); EXPORT(sqInt) primitiveDBusSendMessageTimeout(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); static dbus_bool_t sqDBusPluginAddWatchwithData(DBusWatch*watch, void*data); static void sqDBusPluginFreeWatchData(void*data); static void sqDBusPluginRemoveWatchwithData(DBusWatch*watch, void*data); static void sqDBusPluginToggleWatchwithData(DBusWatch*watch, void*data); static char * stringOopToChar(sqInt oop); /*** Variables ***/ static DBusConnection* connections[2]; static int curIter; static int curWriteIter; static dbus_bool_t hasArgument; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static DBusMessage* message; static DBusMessageIter messageIter[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH]; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "DBusPlugin 23 January 2011 (i)" #else "DBusPlugin 23 January 2011 (e)" #endif ; static DBusMessage* writeMessage; static DBusMessageIter writeMessageIter[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH]; static sqInt argumentsAddBooltoIter(sqInt oop, DBusMessageIter*iter) { int arg; arg = 1; if (oop == (interpreterProxy->falseObject())) { arg = 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &arg))) { msg("Can not add Boolean argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddBytetoIter(sqInt oop, DBusMessageIter*iter) { sqInt intArg; intArg = interpreterProxy->checkedIntegerValueOf(oop); if (interpreterProxy->failed()) { msg("Wrong oop type"); return 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &intArg))) { msg("Can not add Byte argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddDoubletoIter(sqInt oop, DBusMessageIter*iter) { double arg; if (!(interpreterProxy->isFloatObject(oop))) { return interpreterProxy->primitiveFail(); } arg = interpreterProxy->floatValueOf(oop); if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_DOUBLE, &arg))) { msg("Can not add Double argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddInt16toIter(sqInt oop, DBusMessageIter*iter) { dbus_int16_t intArg; if (!((oop & 1))) { msg("Oop is no integer value"); return interpreterProxy->primitiveFail(); } intArg = (oop >> 1); if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &intArg))) { msg("Can not add Int16 argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddInt32toIter(sqInt oop, DBusMessageIter*iter) { dbus_int32_t intArg; intArg = interpreterProxy->signed32BitValueOf(oop); if (interpreterProxy->failed()) { msg("Wrong oop type"); return 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &intArg))) { msg("Can not add Int32 argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddInt64toIter(sqInt oop, DBusMessageIter*iter) { dbus_int64_t intArg; intArg = interpreterProxy->signed64BitValueOf(oop); if (interpreterProxy->failed()) { msg("Wrong oop type"); return 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &intArg))) { msg("Can not add Int64 argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddObjectPathtoIter(sqInt oop, DBusMessageIter*iter) { char*arg; arg = stringOopToChar(oop); if (!(arg == null)) { if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &arg))) { msg("Can not add Path argument."); } free(arg); } } static sqInt argumentsAddSignaturetoIter(sqInt oop, DBusMessageIter*iter) { char*arg; arg = stringOopToChar(oop); if (!(arg == null)) { if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_SIGNATURE, &arg))) { msg("Can not add Signature argument."); } free(arg); } } static sqInt argumentsAddStringtoIter(sqInt oop, DBusMessageIter*iter) { char*arg; arg = stringOopToChar(oop); if (!(arg == null)) { if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &arg))) { msg("Can not add String argument."); } free(arg); } } static sqInt argumentsAddUInt16toIter(sqInt oop, DBusMessageIter*iter) { dbus_uint16_t intArg; if (!((oop & 1))) { msg("Oop is no integer value"); return interpreterProxy->primitiveFail(); } intArg = (oop >> 1); if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &intArg))) { msg("Can not add UInt16 argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddUInt32toIter(sqInt oop, DBusMessageIter*iter) { dbus_uint32_t intArg; intArg = interpreterProxy->positive32BitValueOf(oop); if (interpreterProxy->failed()) { msg("Wrong oop type"); return 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &intArg))) { msg("Can not add UInt32 argument."); return interpreterProxy->primitiveFail(); } } static sqInt argumentsAddUInt64toIter(sqInt oop, DBusMessageIter*iter) { dbus_uint64_t intArg; intArg = interpreterProxy->positive64BitValueOf(oop); if (interpreterProxy->failed()) { msg("Wrong oop type"); return 0; } if (!(dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &intArg))) { msg("Can not add UInt64 argument."); return interpreterProxy->primitiveFail(); } } /* answers an string oop for the char pointer */ static sqInt buildStringOopFromCharP(const char*charP) { char *strPtr; sqInt strObj; int size; if (charP == null) { return interpreterProxy->nilObject(); } size = 0; size = strlen(charP); strObj = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), size); if (interpreterProxy->failed()) { return null; } strPtr = ((char *) interpreterProxy->firstIndexableField(strObj)); memcpy(strPtr, charP, size); return strObj; } static sqInt closeConnection(sqInt index) { if (!((connections[index]) == null)) { dbus_connection_close(connections[index]); dbus_connection_unref(connections[index]); connections[index] = null; return 1; } return 0; } /* creates an error message for a received message */ static DBusMessage * createErrorTofrom(char*dest, sqInt msgOop) { sqInt serialOop; dbus_uint32_t serial; char * name; DBusMessage *error; sqInt p; serialOop = interpreterProxy->fetchPointerofObject(7, msgOop); if (interpreterProxy->failed()) { return null; } /* extract the name of the error oop */ serial = interpreterProxy->positive32BitValueOf(serialOop); /* begin fetchString:ofObject: */ p = interpreterProxy->fetchPointerofObject(8, msgOop); name = stringOopToChar(p); error = null; error = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); dbus_message_set_destination(error, dest); dbus_message_set_error_name(error, name); dbus_message_set_no_reply(error, TRUE); dbus_message_set_reply_serial(error, serial); free(name); return error; } /* answers a message to be sent as reply to a previously received message */ static DBusMessage * createReplyTofrom(char*dest, sqInt msgOop) { sqInt reply; sqInt serialOop; dbus_uint32_t serial; serialOop = interpreterProxy->fetchPointerofObject(7, msgOop); if (interpreterProxy->failed()) { return null; } serial = interpreterProxy->positive32BitValueOf(serialOop); if (interpreterProxy->failed()) { return null; } reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); dbus_message_set_destination(reply, dest); dbus_message_set_no_reply(reply, TRUE); dbus_message_set_reply_serial(reply, serial); return reply; } static char * fetchStringofObject(sqInt n, sqInt oop) { sqInt p; p = interpreterProxy->fetchPointerofObject(n, oop); return stringOopToChar(p); } static sqInt getBasicTypevalue(int t, void*val) { int type; if (!(hasArgument)) { return interpreterProxy->primitiveFail(); } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == t)) { msg("Wrong argument type"); return interpreterProxy->primitiveFail(); } dbus_message_iter_get_basic(&messageIter[curIter], val ); } /* answers the dbus connection. if necessary, open the dbus connection and register the watch functions. The first instance variable of aDBusConnection is 0 or 1 indicating the session or system bus. Second instance variable is a semaphore index. */ static DBusConnection * getConnectionFromOop(sqInt aDBusConnection) { sqInt semaIndex; sqInt h; DBusConnection*conn; DBusError error; sqDBusData*data; h = interpreterProxy->fetchIntegerofObject(0, aDBusConnection); if ((interpreterProxy->failed()) || ((h < 0) || (h > 1))) { msg("handle must be 0 or 1"); return null; } semaIndex = interpreterProxy->fetchIntegerofObject(1, aDBusConnection); if (interpreterProxy->failed()) { msg("semaphore index must be an integer"); return null; } conn = connections[h]; if (conn != null) { return conn; } dbus_error_init(&error); conn = dbus_bus_get_private(h==1?DBUS_BUS_SYSTEM:DBUS_BUS_SESSION, &error); if (dbus_error_is_set (&error)) { msg(error.message); dbus_error_free(&error); return null; } connections[h] = conn; data = newDataStructWithConnectionandSemaphore(conn, semaIndex); if (data != null) { if (!(dbus_connection_set_watch_functions( conn, sqDBusPluginAddWatchwithData, sqDBusPluginRemoveWatchwithData, sqDBusPluginToggleWatchwithData, data, sqDBusPluginFreeWatchData))) { msg("Can not set the watch functions"); free(data); data = null; } } if (data == null) { closeConnection(h); return null; } return conn; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } static sqInt handleflag(int fd, int flag) { aioHandle(fd, handleReadForFDwithDataandFlag , flag); } /* a handler function which is called when new messages arrived in the dbus queue */ static sqInt handleReadForFDwithDataandFlag(int fd, sqDBusData*data, int flag) { sqInt semaphore; dbus_watch_handle(data->watch, DBUS_WATCH_READABLE); handleflag(fd, flag); semaphore = data->semaphore; interpreterProxy->signalSemaphoreWithIndex(semaphore); } EXPORT(sqInt) initialiseModule(void) { connections[0] = null; connections[1] = null; return 1; } /* opens a new container and increase writeIterator. arrays, structs, dictionarys and variants are container types in dbus */ static sqInt iterOpenContainercontains(sqInt t, char*s) { sqInt success; success = dbus_message_iter_open_container( &writeMessageIter[curWriteIter], t, s, &writeMessageIter[curWriteIter+1]); if (!(s == null)) { free(s); } if (success) { curWriteIter += 1; } else { msg("Could not create container"); return interpreterProxy->primitiveFail(); } return interpreterProxy->trueObject(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* answers an new data struct which is needed for handling watchers */ static sqDBusData* newDataStructWithConnectionandSemaphore(DBusConnection *con, int semaphore) { sqDBusData*t; t = null; t = (sqDBusData*)malloc(sizeof(sqDBusData)); if (t == null) { msg("Cannot allocate memory for watch data structure"); return null; } t->con = con; t->semaphore = semaphore; t->watch = NULL; return t; } /* Register a match rule */ EXPORT(sqInt) primitiveDBusAddMatch(void) { sqInt rcvOop; char*rule; DBusConnection *conn; DBusError error; sqInt ruleOop; sqInt _return_value; ruleOop = interpreterProxy->stackValue(0); rcvOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } rule = stringOopToChar(ruleOop); if (interpreterProxy->failed()) { return null; } dbus_error_init(&error); dbus_bus_add_match( conn, rule, &error); dbus_connection_flush(conn); if (dbus_error_is_set(&error)) { msg(((char*) (error.message))); dbus_error_free(&error); interpreterProxy->primitiveFail(); } free(rule); _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* append a basic type argument to the currently topmost iterator in the iterator stack */ EXPORT(sqInt) primitiveDBusAppendBasicArgument(void) { DBusMessageIter*iter; sqInt arg; sqInt t; sqInt _return_value; arg = interpreterProxy->stackValue(1); t = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } iter = &(writeMessageIter[curWriteIter]); if (t == (DBUS_TYPE_BYTE)) { _return_value = argumentsAddBytetoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_INT16)) { _return_value = argumentsAddInt16toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_INT32)) { _return_value = argumentsAddInt32toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_INT64)) { _return_value = argumentsAddInt64toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_UINT16)) { _return_value = argumentsAddUInt16toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_UINT32)) { _return_value = argumentsAddUInt32toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_UINT64)) { _return_value = argumentsAddUInt64toIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_DOUBLE)) { _return_value = argumentsAddDoubletoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_STRING)) { _return_value = argumentsAddStringtoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_BOOLEAN)) { _return_value = argumentsAddBooltoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_OBJECT_PATH)) { _return_value = argumentsAddObjectPathtoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (t == (DBUS_TYPE_SIGNATURE)) { _return_value = argumentsAddSignaturetoIter(arg, iter); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } msg("unknown argument type"); interpreterProxy->primitiveFail(); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* returns a bool argument */ EXPORT(sqInt) primitiveDBusArgumentGetBool(void) { int type; int value; sqInt _return_value; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == (DBUS_TYPE_BOOLEAN))) { msg("Wrong argument type: DBUS_TYPE_BOOLEAN."); interpreterProxy->primitiveFail(); return null; } value = 0; dbus_message_iter_get_basic(&messageIter[curIter], &value ); if (value) { _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } _return_value = interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a char argument and return a SmallIntegerOop */ EXPORT(sqInt) primitiveDBusArgumentGetByte(void) { char value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_BYTE, &value); _return_value = interpreterProxy->integerObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a double argument and answer float oop */ EXPORT(sqInt) primitiveDBusArgumentGetDouble(void) { int type; double value; sqInt _return_value; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == (DBUS_TYPE_DOUBLE))) { msg("Wrong argument type: DBUS_TYPE_DOUBLE."); interpreterProxy->primitiveFail(); return null; } value = 0; dbus_message_iter_get_basic(&messageIter[curIter], &value ); _return_value = interpreterProxy->floatObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a signed integer argument and return a SmallIntegerOop */ EXPORT(sqInt) primitiveDBusArgumentGetInt16(void) { dbus_int16_t value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_INT16, &value); _return_value = interpreterProxy->integerObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a signed long argument and return a LargeIntegerOop depends on the sign */ EXPORT(sqInt) primitiveDBusArgumentGetInt32(void) { dbus_int32_t value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_INT32, &value); _return_value = interpreterProxy->signed32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a signed long long argument and return a LargeIntegerOop depends on the sign */ EXPORT(sqInt) primitiveDBusArgumentGetInt64(void) { dbus_int64_t value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_INT64, &value); _return_value = interpreterProxy->signed64BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns path to an object argument as a string */ EXPORT(sqInt) primitiveDBusArgumentGetObjectPath(void) { int type; char *str; sqInt _return_value; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == (DBUS_TYPE_OBJECT_PATH))) { msg("Wrong argument type: DBUS_TYPE_OBJECT_PATH."); interpreterProxy->primitiveFail(); return null; } str = ""; dbus_message_iter_get_basic(&messageIter[curIter], &str ); _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a signature from the arguments */ EXPORT(sqInt) primitiveDBusArgumentGetSignature(void) { char*value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_SIGNATURE, &value); _return_value = buildStringOopFromCharP(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the readed string argument as oop */ EXPORT(sqInt) primitiveDBusArgumentGetString(void) { int type; char *str; sqInt _return_value; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == (DBUS_TYPE_STRING))) { msg("Wrong argument type: DBUS_TYPE_STRING."); interpreterProxy->primitiveFail(); return null; } str = ""; dbus_message_iter_get_basic(&messageIter[curIter], &str ); _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the type of the current argument or nil) */ EXPORT(sqInt) primitiveDBusArgumentGetType(void) { int type; sqInt _return_value; if (!(hasArgument)) { _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } type = dbus_message_iter_get_arg_type(&messageIter[curIter]); _return_value = interpreterProxy->integerObjectOf(type); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a unsigned int argument and return a SmallIntegerOop */ EXPORT(sqInt) primitiveDBusArgumentGetUInt16(void) { dbus_uint16_t value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_UINT16, &value); _return_value = interpreterProxy->integerObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a unsigned long argument and returns a LargeInteger oop */ EXPORT(sqInt) primitiveDBusArgumentGetUInt32(void) { dbus_uint32_t value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_UINT32, &value); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read a unsigned long long argument and returns a LargeInteger oop */ EXPORT(sqInt) primitiveDBusArgumentGetUInt64(void) { long long value; sqInt _return_value; value = 0; getBasicTypevalue(DBUS_TYPE_UINT64, &value); _return_value = interpreterProxy->positive64BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* close the receiver's connection */ EXPORT(sqInt) primitiveDBusConnectionClose(void) { sqInt rcvOop; sqInt h; sqInt _return_value; rcvOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } h = interpreterProxy->fetchIntegerofObject(0, rcvOop); if ((interpreterProxy->failed()) || ((h < 0) || (h > 1))) { msg("handle must be 0 or 1"); interpreterProxy->primitiveFail(); return null; } _return_value = ((closeConnection(h))? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* answer the status of the connection */ EXPORT(sqInt) primitiveDBusConnectionDispatchStatus(void) { sqInt rcvOop; sqInt status; DBusConnection*conn; sqInt _return_value; rcvOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } status = null; status = dbus_connection_get_dispatch_status(conn); _return_value = interpreterProxy->integerObjectOf(status); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* read the connection for next available message */ EXPORT(sqInt) primitiveDBusConnectionPopMessage(void) { sqInt rcvOop; int msgType; DBusConnection *conn; sqInt _return_value; rcvOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } if (!(message == null)) { hasArgument = 0; curIter = 0; dbus_message_unref(message); } message = dbus_connection_pop_message(conn); if (message == null) { _return_value = interpreterProxy->integerObjectOf(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* if message contains argument initialize iterator */ msgType = dbus_message_get_type(message); hasArgument = dbus_message_iter_init(message, &(messageIter[curIter])); _return_value = interpreterProxy->integerObjectOf(msgType); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* create a dbus message from the given oop */ EXPORT(sqInt) primitiveDBusCreateMessageFrom(void) { DBusMessage *tmpMsg; int msgType; char * path; char * destination; char * interface; char * method; sqInt m; sqInt _return_value; sqInt p; sqInt p1; sqInt p2; sqInt p3; m = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } msgType = interpreterProxy->fetchIntegerofObject(0, m); if (interpreterProxy->failed()) { msg("Can not fetch message type."); interpreterProxy->primitiveFail(); return null; } /* begin fetchString:ofObject: */ p1 = interpreterProxy->fetchPointerofObject(1, m); path = stringOopToChar(p1); if ((interpreterProxy->fetchPointerofObject(2, m)) == (interpreterProxy->nilObject())) { interface = null; } else { /* begin fetchString:ofObject: */ p = interpreterProxy->fetchPointerofObject(2, m); interface = stringOopToChar(p); } /* begin fetchString:ofObject: */ p2 = interpreterProxy->fetchPointerofObject(3, m); method = stringOopToChar(p2); /* begin fetchString:ofObject: */ p3 = interpreterProxy->fetchPointerofObject(5, m); destination = stringOopToChar(p3); /* create Signal */ tmpMsg = null; if (msgType == 4) { tmpMsg = dbus_message_new_signal(path, interface, method); } if (msgType == 1) { tmpMsg = dbus_message_new_method_call(destination, path, interface, method); } if (msgType == 2) { tmpMsg = createReplyTofrom(destination, m); } if (msgType == 3) { tmpMsg = createErrorTofrom(destination, m); } if (tmpMsg == null) { msg("Can not create a message."); interpreterProxy->primitiveFail(); return null; } /* cleaning */ writeMessage = tmpMsg; if (!(path == null)) { free(path); } if (!(interface == null)) { free(interface); } if (!(method == null)) { free(method); } if (!(destination == null)) { free(destination); } _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* initialize an interator to write message arguments */ EXPORT(sqInt) primitiveDBusInitializeWriteIterator(void) { if (writeMessage == null) { null; } else { curWriteIter = 0; dbus_message_iter_init_append(writeMessage, &writeMessageIter[curWriteIter]); } if (interpreterProxy->failed()) { return null; } return null; } /* pops the topmost container from the iterator stack */ EXPORT(sqInt) primitiveDBusIterCloseContainer(void) { if (curWriteIter == 0) { msg("No open container available"); interpreterProxy->primitiveFail(); return null; } if (dbus_message_iter_close_container( &writeMessageIter[curWriteIter-1], &writeMessageIter[curWriteIter])) { curWriteIter -= 1; } else { msg("Could not close container"); interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->failed()) { return null; } return null; } /* push a new container to the iterator stack. s is the signature which describes the content of the container */ EXPORT(sqInt) primitiveDBusIterOpenContainerContains(void) { char*cSig; sqInt isContainer; sqInt t; sqInt s; sqInt _return_value; t = interpreterProxy->stackIntegerValue(1); s = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } /* struct and dict entry must not set signature */ cSig = null; isContainer = 0; if (t == (DBUS_TYPE_ARRAY)) { isContainer = 1; if (!(s == (interpreterProxy->nilObject()))) { cSig = stringOopToChar(s); } if (cSig == null) { msg("To write an array you have to specify the signature of the contained elements"); interpreterProxy->primitiveFail(); return null; } } if (t == (DBUS_TYPE_VARIANT)) { isContainer = 1; if (!(s == (interpreterProxy->nilObject()))) { cSig = stringOopToChar(s); } if (cSig == null) { msg("To write a variant you have to specify the signature of the contained element"); interpreterProxy->primitiveFail(); return null; } } if (t == (DBUS_TYPE_STRUCT)) { isContainer = 1; } if (t == (DBUS_TYPE_DICT_ENTRY)) { isContainer = 1; } if (!(isContainer)) { fprintf(stderr, "\n%d is no container type", t); interpreterProxy->primitiveFail(); return null; } _return_value = iterOpenContainercontains(t, cSig); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* answer the signature of the current iterator */ EXPORT(sqInt) primitiveDBusIteratorSignature(void) { sqInt strOop; char*sig; sig = dbus_message_iter_get_signature(&messageIter[curIter]); strOop = buildStringOopFromCharP(sig); dbus_free(sig); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, strOop); return null; } /* returns the destination of the received message or nil if there is none set */ EXPORT(sqInt) primitiveDBusMessageGetDestination(void) { const char *str; sqInt _return_value; str = null; str = dbus_message_get_destination(message); if (str == null) { return null; } _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* answer the name name of the received error (ERROR only) */ EXPORT(sqInt) primitiveDBusMessageGetErrorName(void) { int msgType; const char *str; sqInt _return_value; /* check if it is an error message */ msgType = 0; msgType = dbus_message_get_type(message); if (!(msgType == 3)) { _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } str = dbus_message_get_error_name(message); _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the interface the message is being sent to (METHOD_CALL) or emitted from (SIGNAL) */ EXPORT(sqInt) primitiveDBusMessageGetInterface(void) { const char *str; sqInt _return_value; str = dbus_message_get_interface(message); _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the interface member beeing invoked (METHOD_CALL) or emitted (SIGNAL) */ EXPORT(sqInt) primitiveDBusMessageGetMember(void) { const char *str; sqInt _return_value; str = null; str = dbus_message_get_member(message); _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns true if the method call expects no reply otherwise returns false */ EXPORT(sqInt) primitiveDBusMessageGetNoReply(void) { sqInt _return_value; if (dbus_message_get_no_reply(message)) { _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } _return_value = interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the object path the message is being sent to (METHOD_CALL) or being emitted from (SIGNAL) */ EXPORT(sqInt) primitiveDBusMessageGetPath(void) { const char *path; sqInt _return_value; path = dbus_message_get_path(message); _return_value = buildStringOopFromCharP(path); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the serial of the message to which this message is a reply or 0 if none has been specified */ EXPORT(sqInt) primitiveDBusMessageGetReplySerial(void) { dbus_uint32_t serial; sqInt _return_value; serial = 0; serial = dbus_message_get_reply_serial(message); _return_value = interpreterProxy->positive32BitIntegerFor(serial); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the unique name of the connection which orginatet the message, or nil if unknown or inapplicable */ EXPORT(sqInt) primitiveDBusMessageGetSender(void) { const char *str; sqInt _return_value; str = null; str = dbus_message_get_sender(message); if (str == null) { return null; } _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the serial of the message or 0 if none has been specified */ EXPORT(sqInt) primitiveDBusMessageGetSerial(void) { dbus_uint32_t serial; sqInt _return_value; serial = 0; serial = dbus_message_get_serial(message); _return_value = interpreterProxy->positive32BitIntegerFor(serial); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns the type signature of the message */ EXPORT(sqInt) primitiveDBusMessageGetSignature(void) { const char *str; sqInt _return_value; str = null; str = dbus_message_get_signature(message); if (str == null) { return null; } _return_value = buildStringOopFromCharP(str); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* returns true if the received message has arguments */ EXPORT(sqInt) primitiveDBusMessageHasArguments(void) { sqInt _return_value; if (!(hasArgument)) { _return_value = interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* set the next message iterator as the current. anwers if there is a next iterator */ EXPORT(sqInt) primitiveDBusNextIterator(void) { sqInt _return_value; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } hasArgument = dbus_message_iter_next(&messageIter[curIter]); _return_value = (hasArgument? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* pops a message iterator from the iterator stack */ EXPORT(sqInt) primitiveDBusPopMessageIterator(void) { sqInt _return_value; if (curIter > 0) { curIter -= 1; hasArgument = 1; _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } _return_value = interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* push an iterator for reading variants, arrays or structs */ EXPORT(sqInt) primitiveDBusPushMessageIterator(void) { int type; if (!(hasArgument)) { interpreterProxy->primitiveFail(); return null; } type = 0; type = dbus_message_iter_get_arg_type(&messageIter[curIter]); if (!(type == (DBUS_TYPE_VARIANT))) { if (!(type == (DBUS_TYPE_ARRAY))) { if (!(type == (DBUS_TYPE_DICT_ENTRY))) { if (!(type == (DBUS_TYPE_STRUCT))) { fprintf(stderr, "Wrong argument type: %s", dbus_message_iter_get_signature(&messageIter[curIter]) ); interpreterProxy->primitiveFail(); return null; } } } } dbus_message_iter_recurse(&messageIter[curIter], &messageIter[curIter+1]); curIter += 1; hasArgument = 1; if (interpreterProxy->failed()) { return null; } return null; } /* Register a name at the connection */ EXPORT(sqInt) primitiveDBusRegisterName(void) { sqInt rcvOop; int ret; char*name; DBusConnection *conn; DBusError error; sqInt nameOop; sqInt _return_value; nameOop = interpreterProxy->stackValue(0); rcvOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } name = stringOopToChar(nameOop); if (interpreterProxy->failed()) { return null; } dbus_error_init(&error); ret = 0; ret = dbus_bus_request_name( conn, name, DBUS_NAME_FLAG_REPLACE_EXISTING, &error); if (dbus_error_is_set(&error)) { msg(((char*) (error.message))); dbus_error_free(&error); interpreterProxy->primitiveFail(); } free(name); _return_value = interpreterProxy->integerObjectOf(ret); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Release a registered name */ EXPORT(sqInt) primitiveDBusReleaseName(void) { sqInt rcvOop; int ret; char*name; DBusConnection *conn; DBusError error; sqInt nameOop; sqInt _return_value; nameOop = interpreterProxy->stackValue(0); rcvOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } name = stringOopToChar(nameOop); if (interpreterProxy->failed()) { return null; } dbus_error_init(&error); ret = 0; ret = dbus_bus_release_name( conn, name, &error); if (dbus_error_is_set(&error)) { msg(((char*) (error.message))); dbus_error_free(&error); interpreterProxy->primitiveFail(); } free(name); _return_value = interpreterProxy->integerObjectOf(ret); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Remove match rule */ EXPORT(sqInt) primitiveDBusRemoveMatch(void) { sqInt rcvOop; char*rule; DBusConnection *conn; DBusError error; sqInt ruleOop; sqInt _return_value; ruleOop = interpreterProxy->stackValue(0); rcvOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } rule = stringOopToChar(ruleOop); if (interpreterProxy->failed()) { return null; } dbus_error_init(&error); dbus_bus_remove_match( conn, rule, &error); dbus_connection_flush(conn); if (dbus_error_is_set(&error)) { msg(((char*) (error.message))); dbus_error_free(&error); interpreterProxy->primitiveFail(); } free(rule); _return_value = interpreterProxy->trueObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* send the previously created message and return the serial of the message. If timeout is 0, do not generate a timeout error. If timeout is -1, use a default timeout. */ EXPORT(sqInt) primitiveDBusSendMessageTimeout(void) { sqInt rcvOop; dbus_uint32_t serial; DBusConnection *conn; dbus_bool_t msgSent; sqInt timeoutMilliseconds; sqInt _return_value; timeoutMilliseconds = interpreterProxy->stackIntegerValue(0); rcvOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } conn = getConnectionFromOop(rcvOop); if (conn == null) { interpreterProxy->primitiveFail(); return null; } if (writeMessage == null) { msg("no current message"); interpreterProxy->primitiveFail(); return null; } serial = 0; msgSent = 1; if (timeoutMilliseconds == 0) { msgSent = dbus_connection_send(conn, writeMessage, &serial); } else { msgSent = dbus_connection_send_with_reply(conn, writeMessage, NULL, timeoutMilliseconds); serial = dbus_message_get_serial(writeMessage); } dbus_message_unref(writeMessage); if (!(msgSent)) { msg("message send failed"); interpreterProxy->primitiveFail(); return null; } _return_value = interpreterProxy->integerObjectOf(serial); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* if connected to a bus disconnect */ EXPORT(sqInt) shutdownModule(void) { sqInt i; for (i = 0; i <= 1; i += 1) { closeConnection(i); } return 1; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } /* is called when the dbus want to add a watch handle. a filedescriptor for the watch will registered in the squeak loop */ static dbus_bool_t sqDBusPluginAddWatchwithData(DBusWatch*watch, void*data) { sqInt fd; sqInt flag; /* get the file descriptor of the watch */ flag = dbus_watch_get_flags(watch); /* set watch in data structure */ fd = dbus_watch_get_fd(watch); ((sqDBusData*)data)->watch = watch; if (flag & DBUS_WATCH_READABLE) { aioEnable(fd, data, NULL); aioHandle(fd, handleReadForFDwithDataandFlag , 1<<0 | 1<<1 | 1<<3); } return 1; } /* function is called after a watch is dissabled an the data of the watch can be freed */ static void sqDBusPluginFreeWatchData(void*data) { free(data); } /* is called when the dbus want to remove a watch handle, the filedescriptor will disabled */ static void sqDBusPluginRemoveWatchwithData(DBusWatch*watch, void*data) { sqInt fd; fd = dbus_watch_get_fd(watch); aioDisable(fd); } /* toggle the filedescriptor */ static void sqDBusPluginToggleWatchwithData(DBusWatch*watch, void*data) { sqInt enable; sqInt fd; enable = dbus_watch_get_enabled(watch); fd = dbus_watch_get_fd(watch); if (enable) { ((sqDBusData*)data)->watch = watch; aioEnable(fd, data, NULL); } else { aioDisable(fd); } } /* convert a string oop to an char pointer which stores the content of the oop */ static char * stringOopToChar(sqInt oop) { char *tmpStr; int size; char *t; tmpStr = ((char*) (interpreterProxy->arrayValueOf(oop))); if (interpreterProxy->failed()) { msg("not a string"); return null; } size = interpreterProxy->byteSizeOf(oop); t = ((char*) (malloc(size+1))); memcpy(t, tmpStr, size); t[size] = 0; return t; } #ifdef SQUEAK_BUILTIN_PLUGIN void* DBusPlugin_exports[][3] = { {"DBusPlugin", "primitiveDBusMessageHasArguments", (void*)primitiveDBusMessageHasArguments}, {"DBusPlugin", "primitiveDBusArgumentGetBool", (void*)primitiveDBusArgumentGetBool}, {"DBusPlugin", "primitiveDBusMessageGetReplySerial", (void*)primitiveDBusMessageGetReplySerial}, {"DBusPlugin", "initialiseModule", (void*)initialiseModule}, {"DBusPlugin", "primitiveDBusAddMatch", (void*)primitiveDBusAddMatch}, {"DBusPlugin", "primitiveDBusArgumentGetType", (void*)primitiveDBusArgumentGetType}, {"DBusPlugin", "primitiveDBusArgumentGetObjectPath", (void*)primitiveDBusArgumentGetObjectPath}, {"DBusPlugin", "primitiveDBusArgumentGetUInt32", (void*)primitiveDBusArgumentGetUInt32}, {"DBusPlugin", "primitiveDBusNextIterator", (void*)primitiveDBusNextIterator}, {"DBusPlugin", "primitiveDBusArgumentGetUInt16", (void*)primitiveDBusArgumentGetUInt16}, {"DBusPlugin", "primitiveDBusPopMessageIterator", (void*)primitiveDBusPopMessageIterator}, {"DBusPlugin", "primitiveDBusArgumentGetInt64", (void*)primitiveDBusArgumentGetInt64}, {"DBusPlugin", "primitiveDBusArgumentGetDouble", (void*)primitiveDBusArgumentGetDouble}, {"DBusPlugin", "primitiveDBusArgumentGetByte", (void*)primitiveDBusArgumentGetByte}, {"DBusPlugin", "getModuleName", (void*)getModuleName}, {"DBusPlugin", "primitiveDBusMessageGetInterface", (void*)primitiveDBusMessageGetInterface}, {"DBusPlugin", "primitiveDBusMessageGetMember", (void*)primitiveDBusMessageGetMember}, {"DBusPlugin", "primitiveDBusArgumentGetString", (void*)primitiveDBusArgumentGetString}, {"DBusPlugin", "primitiveDBusConnectionDispatchStatus", (void*)primitiveDBusConnectionDispatchStatus}, {"DBusPlugin", "primitiveDBusSendMessageTimeout", (void*)primitiveDBusSendMessageTimeout}, {"DBusPlugin", "primitiveDBusMessageGetSignature", (void*)primitiveDBusMessageGetSignature}, {"DBusPlugin", "primitiveDBusIterCloseContainer", (void*)primitiveDBusIterCloseContainer}, {"DBusPlugin", "primitiveDBusAppendBasicArgument", (void*)primitiveDBusAppendBasicArgument}, {"DBusPlugin", "primitiveDBusPushMessageIterator", (void*)primitiveDBusPushMessageIterator}, {"DBusPlugin", "primitiveDBusCreateMessageFrom", (void*)primitiveDBusCreateMessageFrom}, {"DBusPlugin", "primitiveDBusIteratorSignature", (void*)primitiveDBusIteratorSignature}, {"DBusPlugin", "primitiveDBusRegisterName", (void*)primitiveDBusRegisterName}, {"DBusPlugin", "primitiveDBusArgumentGetUInt64", (void*)primitiveDBusArgumentGetUInt64}, {"DBusPlugin", "primitiveDBusMessageGetDestination", (void*)primitiveDBusMessageGetDestination}, {"DBusPlugin", "setInterpreter", (void*)setInterpreter}, {"DBusPlugin", "primitiveDBusIterOpenContainerContains", (void*)primitiveDBusIterOpenContainerContains}, {"DBusPlugin", "primitiveDBusReleaseName", (void*)primitiveDBusReleaseName}, {"DBusPlugin", "primitiveDBusMessageGetNoReply", (void*)primitiveDBusMessageGetNoReply}, {"DBusPlugin", "primitiveDBusMessageGetErrorName", (void*)primitiveDBusMessageGetErrorName}, {"DBusPlugin", "primitiveDBusMessageGetSerial", (void*)primitiveDBusMessageGetSerial}, {"DBusPlugin", "primitiveDBusMessageGetPath", (void*)primitiveDBusMessageGetPath}, {"DBusPlugin", "primitiveDBusInitializeWriteIterator", (void*)primitiveDBusInitializeWriteIterator}, {"DBusPlugin", "primitiveDBusConnectionClose", (void*)primitiveDBusConnectionClose}, {"DBusPlugin", "primitiveDBusRemoveMatch", (void*)primitiveDBusRemoveMatch}, {"DBusPlugin", "primitiveDBusArgumentGetSignature", (void*)primitiveDBusArgumentGetSignature}, {"DBusPlugin", "primitiveDBusMessageGetSender", (void*)primitiveDBusMessageGetSender}, {"DBusPlugin", "primitiveDBusArgumentGetInt32", (void*)primitiveDBusArgumentGetInt32}, {"DBusPlugin", "primitiveDBusConnectionPopMessage", (void*)primitiveDBusConnectionPopMessage}, {"DBusPlugin", "shutdownModule", (void*)shutdownModule}, {"DBusPlugin", "primitiveDBusArgumentGetInt16", (void*)primitiveDBusArgumentGetInt16}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/FileCopyPlugin/FileCopyPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:53 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveFileCopyNamedTo(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "FileCopyPlugin 23 January 2011 (i)" #else "FileCopyPlugin 23 January 2011 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primitiveFileCopyNamedTo(void) { sqInt srcSz; sqInt dstSz; sqInt ok; char *srcName; char *dstName; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); srcName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); dstName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } srcSz = interpreterProxy->slotSizeOf((oopForPointer( srcName ) - BASE_HEADER_SIZE)); dstSz = interpreterProxy->slotSizeOf((oopForPointer( dstName ) - BASE_HEADER_SIZE)); ok = sqCopyFilesizetosize(srcName, srcSz, dstName, dstSz); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* FileCopyPlugin_exports[][3] = { {"FileCopyPlugin", "getModuleName", (void*)getModuleName}, {"FileCopyPlugin", "setInterpreter", (void*)setInterpreter}, {"FileCopyPlugin", "primitiveFileCopyNamedTo", (void*)primitiveFileCopyNamedTo}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/GStreamerPlugin/GStreamerPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:55 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include #include #include "squeakAudioVideoPipeLineSignalInterface.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt cbnewpad(sqInt element, sqInt newPad, sqInt *data); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt initialiseModule(void); static sqInt msg(char *s); static sqInt positive64BitIntegerForOverride(sqLong integerValue); #pragma export on EXPORT(sqInt) primitiveSqueakSinkAllocate(void); EXPORT(sqInt) primitiveSqueakSinkAudioGetData(void); EXPORT(sqInt) primitiveSqueakSinkFree(void); EXPORT(sqInt) primitiveSqueakSinkGetFrameRateDenominator(void); EXPORT(sqInt) primitiveSqueakSinkGetFrameRateNumerator(void); EXPORT(sqInt) primitiveSqueakSinkGetHeight(void); EXPORT(sqInt) primitiveSqueakSinkGetWidth(void); EXPORT(sqInt) primitiveSqueakSinkVideo(void); EXPORT(sqInt) primitiveSqueakSrc(void); EXPORT(sqInt) primitiveSqueakSrcWithTime(void); EXPORT(sqInt) primitiveSqueakSrcAllocate(void); EXPORT(sqInt) primitivecallbacksignalseenfor(void); EXPORT(sqInt) primitivegetinterpreterproxy(void); EXPORT(sqInt) primitivegetoop(void); EXPORT(sqInt) primitivegobjectclasslistproperties(void); EXPORT(sqInt) primitivegobjectclasslistpropertyboolatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertydoubleatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyenumatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyfloatatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyintatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertylongatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertylonglongatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertymetaDataatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertypointeratIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertystringatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyuintatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyulongatIndex(void); EXPORT(sqInt) primitivegobjectclasslistpropertyulonglongatIndex(void); EXPORT(sqInt) primitivegobjectfree(void); EXPORT(sqInt) primitivegobjectgetboolfrom(void); EXPORT(sqInt) primitivegobjectgetdoublefrom(void); EXPORT(sqInt) primitivegobjectgetfloatfrom(void); EXPORT(sqInt) primitivegobjectgetlongfrom(void); EXPORT(sqInt) primitivegobjectgetlonglongfrom(void); EXPORT(sqInt) primitivegobjectgetpointerfrom(void); EXPORT(sqInt) primitivegobjectgetsmalltalkobject(void); EXPORT(sqInt) primitivegobjectgetstringfrom(void); EXPORT(sqInt) primitivegobjectgetulongfrom(void); EXPORT(sqInt) primitivegobjectgetulonglongfrom(void); EXPORT(sqInt) primitivegobjectsetboolon(void); EXPORT(sqInt) primitivegobjectsetdoubleon(void); EXPORT(sqInt) primitivegobjectsetfloaton(void); EXPORT(sqInt) primitivegobjectsetlonglongon(void); EXPORT(sqInt) primitivegobjectsetlongon(void); EXPORT(sqInt) primitivegobjectsetpointeron(void); EXPORT(sqInt) primitivegobjectsetstringon(void); EXPORT(sqInt) primitivegobjectsetulonglongon(void); EXPORT(sqInt) primitivegobjectsetulongon(void); EXPORT(sqInt) primitivegsignalconnect(void); EXPORT(sqInt) primitivegstbinadd(void); EXPORT(sqInt) primitivegstbinnew(void); EXPORT(sqInt) primitivegstbushavepending(void); EXPORT(sqInt) primitivegstbuspeek(void); EXPORT(sqInt) primitivegstbuspop(void); EXPORT(sqInt) primitivegstbuspopfilter(void); EXPORT(sqInt) primitivegstcapsfromstring(void); EXPORT(sqInt) primitivegstcapstostring(void); EXPORT(sqInt) primitivegstelementadd(void); EXPORT(sqInt) primitivegstelementfactorycreate(void); EXPORT(sqInt) primitivegstelementfactoryfind(void); EXPORT(sqInt) primitivegstelementfactorygetauthor(void); EXPORT(sqInt) primitivegstelementfactorygetdescription(void); EXPORT(sqInt) primitivegstelementfactorygetklass(void); EXPORT(sqInt) primitivegstelementfactorygetlongname(void); EXPORT(sqInt) primitivegstelementfactorygeturitype(void); EXPORT(sqInt) primitivegstelementfactorymake(void); EXPORT(sqInt) primitivegstelementgetcompatiblepad(void); EXPORT(sqInt) primitivegstelementgetrequestpad(void); EXPORT(sqInt) primitivegstelementgetstate(void); EXPORT(sqInt) primitivegstelementgetstaticpad(void); EXPORT(sqInt) primitivegstelementgsignalconnect(void); EXPORT(sqInt) primitivegstelementlink(void); EXPORT(sqInt) primitivegstelementlinkfiltered(void); EXPORT(sqInt) primitivegstelementqueryconvert(void); EXPORT(sqInt) primitivegstelementqueryduration(void); EXPORT(sqInt) primitivegstelementqueryposition(void); EXPORT(sqInt) primitivegstelementreleaserequestpad(void); EXPORT(sqInt) primitivegstelementseek(void); EXPORT(sqInt) primitivegstelementseeksimple(void); EXPORT(sqInt) primitivegstelementsetstate(void); EXPORT(sqInt) primitivegstghostpadnew(void); EXPORT(sqInt) primitivegstinitcheck(void); EXPORT(sqInt) primitivegstmessageparsebuffering(void); EXPORT(sqInt) primitivegstmessageparseduration(void); EXPORT(sqInt) primitivegstmessageparseerror(void); EXPORT(sqInt) primitivegstmessageparseinfo(void); EXPORT(sqInt) primitivegstmessageparsesegmentdone(void); EXPORT(sqInt) primitivegstmessageparsesegmentstart(void); EXPORT(sqInt) primitivegstmessageparsestatechanged(void); EXPORT(sqInt) primitivegstmessageparsewarning(void); EXPORT(sqInt) primitivegstmessagesrc(void); EXPORT(sqInt) primitivegstmessagetypestring(void); EXPORT(sqInt) primitivegstmessageunref(void); EXPORT(sqInt) primitivegstobjectunref(void); EXPORT(sqInt) primitivegstpadacceptcaps(void); EXPORT(sqInt) primitivegstpadgetcaps(void); EXPORT(sqInt) primitivegstpadgetparentelement(void); EXPORT(sqInt) primitivegstpadlink(void); EXPORT(sqInt) primitivegstpadsetactive(void); EXPORT(sqInt) primitivegstpadsetcaps(void); EXPORT(sqInt) primitivegstpipelineautoclock(void); EXPORT(sqInt) primitivegstpipelinegetautoflushbus(void); EXPORT(sqInt) primitivegstpipelinegetbus(void); EXPORT(sqInt) primitivegstpipelinegetclock(void); EXPORT(sqInt) primitivegstpipelinegetdelay(void); EXPORT(sqInt) primitivegstpipelinegetlaststreamtime(void); EXPORT(sqInt) primitivegstpipelinenew(void); EXPORT(sqInt) primitivegstpipelinesetautoflushbus(void); EXPORT(sqInt) primitivegstpipelinesetclock(void); EXPORT(sqInt) primitivegstpipelinesetdelay(void); EXPORT(sqInt) primitivegstpipelinesetnewstreamtime(void); EXPORT(sqInt) primitivegstpipelineuseclock(void); EXPORT(sqInt) primitivegstregistryforksetenabled(void); EXPORT(sqInt) primitivegstsegtrapisenabled(void); EXPORT(sqInt) primitivegstsegtrapsetenabled(void); EXPORT(sqInt) primitivegstversionstring(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static sqInt shutdownModule(void); static sqInt signed32BitValueOfOverride(sqInt oop); static sqInt signed64BitIntegerForOverride(sqLong integerValue); static sqLong signed64BitValueOfOverride(sqInt oop); static sqInt sqAssert(sqInt aBool); static sqInt stringFromCString(const char *aCString); /*** Variables ***/ static gboolean callbackForPadHookupElement[128]; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "GStreamerPlugin 23 January 2011 (i)" #else "GStreamerPlugin 23 January 2011 (e)" #endif ; /* Ok the trick here is on the signal pad_add we may have multiple pads being created. Therefore we must find the sink pad that can handle the request. Note for ogg you could have the audio and video stream for example */ static sqInt cbnewpad(sqInt element, sqInt newPad, sqInt *data) { sqInt result; sqInt i; GstPad* gstPadValue; sqInt max; GstCaps* gstCapsValue; max = data[0]; gstCapsValue = null; gstPadValue = null; ; ; result = 0; for (i = 1; i <= max; i += 1) { gstPadValue = ((GstPad*) (data[i])); gstCapsValue = gst_pad_get_caps (newPad); result = gst_pad_accept_caps (gstPadValue, gstCapsValue); if (result) { if (i < 128) { callbackForPadHookupElement[i] = 1; } gst_pad_link (newPad, gstPadValue); return null; } } } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } /* Initialise the module */ static sqInt initialiseModule(void) { return 1; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:. */ static sqInt positive64BitIntegerForOverride(sqLong integerValue) { sqInt newLargeInteger; unsigned char *where; sqInt highWord; sqInt value; sqInt i; sqInt sz; if ((sizeof(integerValue)) == 4) { return interpreterProxy->positive32BitIntegerFor(integerValue); } /* shift is coerced to usqInt otherwise */ highWord = integerValue >> 32; if (highWord == 0) { return interpreterProxy->positive32BitIntegerFor(integerValue); } sz = 5; if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } newLargeInteger = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classLargePositiveInteger(), sz); where = interpreterProxy->firstIndexableField(newLargeInteger); for (i = 0; i <= (sz - 1); i += 1) { value = (integerValue >> (i * 8)) & 255; where[i] = value; } return newLargeInteger; } EXPORT(sqInt) primitiveSqueakSinkAllocate(void) { SqueakAudioVideoSinkPtr squeaker; GstElement* gstElement; sqInt type; sqInt semaphoreIndex; sqInt gstElementOoop; sqInt _return_value; type = interpreterProxy->stackIntegerValue(2); semaphoreIndex = interpreterProxy->stackIntegerValue(1); gstElementOoop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); squeaker = 0; squeaker = g_malloc0(sizeof(SqueakAudioVideoSink)); if (type) squeaker->handler = squeakVideoHandOff; else squeaker->handler = squeakAudioHandOff; squeaker->owner = gstElement; squeaker->interpreterProxy = interpreterProxy; squeaker->semaphoreIndexForSink = semaphoreIndex; squeaker->prerollCounter = 5; ; ; _return_value = interpreterProxy->positive32BitIntegerFor(squeaker); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSinkAudioGetData(void) { SqueakAudioVideoSinkPtr sink; sqInt newBytes; sqInt aSqueakSinkObject; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } sink = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); newBytes = 0; ; GST_LOCK(sink->owner); if (sink->copyToSendToSqueakAudio && GST_BUFFER_DATA(sink->copyToSendToSqueakAudio) && GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio)) { /* Got data, yes lets move that into Squeak object space */ /* Also turn the semaphore off */ newBytes = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio)); if (newBytes) memcpy(interpreterProxy->arrayValueOf(newBytes), GST_BUFFER_DATA(sink->copyToSendToSqueakAudio), GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio)); GST_BUFFER_OFFSET_END(sink->copyToSendToSqueakAudio) = 0; } sink->semaphoreWasSignaled = 0; GST_UNLOCK(sink->owner); if (newBytes == 0) { _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, newBytes); return null; } EXPORT(sqInt) primitiveSqueakSinkFree(void) { SqueakAudioVideoSinkPtr squeakSinkObject; sqInt aSqueakSinkObject; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } squeakSinkObject = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); if (squeakSinkObject-> copyToSendToSqueakAudio) gst_buffer_unref(squeakSinkObject-> copyToSendToSqueakAudio); if (squeakSinkObject-> copyToSendToSqueakVideo) g_free(squeakSinkObject->copyToSendToSqueakVideo); g_free(squeakSinkObject); ; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSqueakSinkGetFrameRateDenominator(void) { SqueakAudioVideoSinkPtr squeakSinkObject; sqInt value; sqInt aSqueakSinkObject; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } squeakSinkObject = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); ; value = 0; value = squeakSinkObject->fps_d; _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSinkGetFrameRateNumerator(void) { SqueakAudioVideoSinkPtr squeakSinkObject; sqInt value; sqInt aSqueakSinkObject; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } squeakSinkObject = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); ; value = 0; value = squeakSinkObject->fps_n; _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSinkGetHeight(void) { SqueakAudioVideoSinkPtr squeakSinkObject; sqInt value; sqInt aSqueakSinkObject; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } squeakSinkObject = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); ; value = 0; value = squeakSinkObject->height; _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSinkGetWidth(void) { SqueakAudioVideoSinkPtr squeakSinkObject; sqInt value; sqInt aSqueakSinkObject; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } squeakSinkObject = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); ; value = 0; value = squeakSinkObject->width; _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSinkVideo(void) { sqInt returnValue; SqueakAudioVideoSinkPtr sink; sqInt aSqueakSinkObject; sqInt aBitMap; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(1); aBitMap = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } sink = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); returnValue = 0; ; GST_LOCK(sink->owner); if (sink->allocbytes) { /* Got data, yes lets move that into Squeak object space */ /* Also turn the semaphore off */ memcpy(interpreterProxy->arrayValueOf(aBitMap), sink->copyToSendToSqueakVideo,sink->allocbytes); returnValue = sink->frame_ready; } sink->semaphoreWasSignaled = 0; sink->frame_ready = FALSE; GST_UNLOCK(sink->owner); _return_value = (returnValue) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSrc(void) { sqInt doesFrameExist; SqueakAudioVideoSinkPtr sink; sqInt aSqueakSinkObject; sqInt data; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(1); data = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } sink = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); ; doesFrameExist = 0; doesFrameExist = sink->frame_ready; if (doesFrameExist) { _return_value = (0) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } GST_LOCK(sink->owner); sink->actualbytes = interpreterProxy->byteSizeOf(data); if (sink->allocbytes && (sink->allocbytes >= sink->actualbytes)) { memcpy(sink->copyToSendToSqueakVideo,interpreterProxy->arrayValueOf(data),sink->actualbytes); sink->frame_ready = TRUE; } GST_UNLOCK(sink->owner); _return_value = (1) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSrcWithTime(void) { GstClockTime startTimeValue; GstClockTime durationValue; sqInt doesFrameExist; SqueakAudioVideoSinkPtr sink; sqInt aSqueakSinkObject; sqInt data; sqInt startTime; sqInt duration; sqInt _return_value; aSqueakSinkObject = interpreterProxy->stackValue(3); data = interpreterProxy->stackValue(2); startTime = interpreterProxy->stackValue(1); duration = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } sink = ((SqueakAudioVideoSinkPtr) (interpreterProxy->positive32BitValueOf(aSqueakSinkObject))); startTimeValue = ((GstClockTime) (interpreterProxy->positive64BitValueOf(startTime))); durationValue = ((GstClockTime) (interpreterProxy->positive64BitValueOf(duration))); ; ; ; doesFrameExist = 0; doesFrameExist = sink->frame_ready; if (doesFrameExist) { _return_value = (0) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } GST_LOCK(sink->owner); sink->actualbytes = interpreterProxy->byteSizeOf(data); if (sink->allocbytes && (sink->allocbytes >= sink->actualbytes)) { memcpy(sink->copyToSendToSqueakVideo,interpreterProxy->arrayValueOf(data),sink->actualbytes); sink->frame_ready = TRUE; sink->startTime = startTimeValue; sink->duration = durationValue; } GST_UNLOCK(sink->owner); _return_value = (1) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } EXPORT(sqInt) primitiveSqueakSrcAllocate(void) { SqueakAudioVideoSinkPtr squeaker; GstElement* gstElement; sqInt numberOfBytes; sqInt semaphoreIndex; sqInt gstElementOoop; sqInt _return_value; numberOfBytes = interpreterProxy->stackIntegerValue(2); semaphoreIndex = interpreterProxy->stackIntegerValue(1); gstElementOoop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); squeaker = 0; squeaker = g_malloc0(sizeof(SqueakAudioVideoSink)); squeaker->handler = squeakSrcHandOff; squeaker->owner = gstElement; squeaker->semaphoreIndexForSink = semaphoreIndex; squeaker->copyToSendToSqueakVideo = g_malloc(numberOfBytes); squeaker->allocbytes = numberOfBytes; squeaker->interpreterProxy = interpreterProxy; ; ; _return_value = interpreterProxy->positive32BitIntegerFor(squeaker); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitivecallbacksignalseenfor(void) { gboolean value; sqInt aIndex; sqInt _return_value; aIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } value = 0; if ((aIndex < 1) || (aIndex > 127)) { interpreterProxy->primitiveFail(); return null; } value = callbackForPadHookupElement[aIndex]; _return_value = (value) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegetinterpreterproxy(void) { sqInt _return_value; _return_value = interpreterProxy->positive32BitIntegerFor(interpreterProxy); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitivegetoop(void) { void *oopThing; sqInt aHopefullObject; aHopefullObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } oopThing = ((void *) (interpreterProxy->positive32BitValueOf(aHopefullObject))); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, oopThing); return null; } /* Returns an array element 1 is numer of properties, number 2 is array of GParamSpec* for all properties of a class. */ EXPORT(sqInt) primitivegobjectclasslistproperties(void) { GParamSpec ** propertyspecs; guint numproperties; sqInt propertyspecsOop; GstElement* element; sqInt arrayOop; sqInt numpropertiesOop; sqInt elementOop; elementOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } propertyspecs = null; numproperties = 0; element = ((GstElement*) (interpreterProxy->positive32BitValueOf(elementOop))); propertyspecs = g_object_class_list_properties(G_OBJECT_GET_CLASS (element), &numproperties);; ; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(numproperties)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(propertyspecs)); propertyspecsOop = interpreterProxy->popRemappableOop(); numpropertiesOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, numpropertiesOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, propertyspecsOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyboolatIndex(void) { sqInt defaultValueOop; sqInt boolValueOop; sqInt readable; gboolean defaultValue; GParamSpecBoolean *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; gboolean boolValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; boolValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_BOOLEAN (param); defaultValue = pstring->default_value; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); defaultValueOop = (defaultValue) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); interpreterProxy->pushRemappableOop(defaultValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); boolValue = g_value_get_boolean (&valueType); boolValueOop = (boolValue) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); } else { boolValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(boolValueOop); boolValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, boolValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertydoubleatIndex(void) { sqInt doubleValue; sqInt defaultValueOop; gdouble minimumValue; sqInt minimumValueOop; gdouble defaultValue; sqInt readable; sqInt maximumValueOop; GParamSpecDouble *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; sqInt doubleValueOop; sqInt longValueOop; GValue valueType = { 0, }; gdouble maximumValue; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; doubleValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_DOUBLE (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->floatObjectOf(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->floatObjectOf(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->floatObjectOf(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); doubleValue = g_value_get_double (&valueType); doubleValueOop = interpreterProxy->floatObjectOf(doubleValue); } else { doubleValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(doubleValueOop); longValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, longValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyenumatIndex(void) { long longValue; sqInt defaultValueOop; long defaultValue; sqInt readable; GParamSpecEnum *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; sqInt longValueOop; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; longValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_ENUM (param); defaultValue = pstring->default_value; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); defaultValueOop = interpreterProxy->positive32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); longValue = g_value_get_enum (&valueType); longValueOop = interpreterProxy->positive32BitIntegerFor(longValue); } else { longValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(longValueOop); longValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, longValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyfloatatIndex(void) { sqInt floatValueOop; sqInt defaultValueOop; gfloat minimumValue; gfloat floatValue; sqInt minimumValueOop; gfloat defaultValue; sqInt readable; sqInt maximumValueOop; GParamSpecFloat *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; gfloat maximumValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; floatValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_FLOAT (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->floatObjectOf(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->floatObjectOf(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->floatObjectOf(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); floatValue = g_value_get_float (&valueType); floatValueOop = interpreterProxy->floatObjectOf(floatValue); } else { floatValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(floatValueOop); floatValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, floatValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyintatIndex(void) { sqInt intValueOop; sqInt defaultValueOop; int minimumValue; int intValue; int defaultValue; sqInt readable; sqInt minimumValueOop; sqInt maximumValueOop; GParamSpecInt *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; int maximumValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; intValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_INT (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->signed32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->signed32BitIntegerFor(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->signed32BitIntegerFor(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); intValue = g_value_get_int (&valueType); intValueOop = interpreterProxy->signed32BitIntegerFor(intValue); } else { intValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(intValueOop); intValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, intValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertylongatIndex(void) { long longValue; sqInt defaultValueOop; long minimumValue; sqInt minimumValueOop; long defaultValue; sqInt readable; sqInt maximumValueOop; GParamSpecLong *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; sqInt longValueOop; GValue valueType = { 0, }; long maximumValue; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; longValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_LONG (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->signed32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->signed32BitIntegerFor(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->signed32BitIntegerFor(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); longValue = g_value_get_long (&valueType); longValueOop = interpreterProxy->signed32BitIntegerFor(longValue); } else { longValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(longValueOop); longValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, longValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertylonglongatIndex(void) { sqInt defaultValueOop; long long minimumValue; long long longlongValue; long long defaultValue; sqInt readable; sqInt minimumValueOop; sqInt maximumValueOop; GParamSpecInt64 *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; long long maximumValue; GValue valueType = { 0, }; sqInt longlongValueOop; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; longlongValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_INT64 (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = signed64BitIntegerForOverride(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = signed64BitIntegerForOverride(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = signed64BitIntegerForOverride(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); longlongValue = g_value_get_int64 (&valueType); longlongValueOop = signed64BitIntegerForOverride(longlongValue); } else { longlongValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(longlongValueOop); longlongValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, longlongValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertymetaDataatIndex(void) { sqInt valueCode; sqInt blurbOop; sqInt readwriteOop; char * name; sqInt nameOop; char * blurb; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; sqInt readwrite; GValue valueType = { 0, }; sqInt valueCodeOop; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = 0; ; param = propertyspecs[index]; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); g_value_init (&valueType, param->value_type); valueCode = G_VALUE_TYPE (&valueType); name = g_param_spec_get_name (param); blurb = g_param_spec_get_blurb (param);; nameOop = stringFromCString(name); interpreterProxy->pushRemappableOop(nameOop); blurbOop = stringFromCString(blurb); interpreterProxy->pushRemappableOop(blurbOop); readwrite = 0; if (param->flags & G_PARAM_READABLE) readwrite = 1; if (param->flags & G_PARAM_WRITABLE) readwrite = readwrite+2; if (param->flags & GST_PARAM_CONTROLLABLE) readwrite = readwrite+4;; ; interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(readwrite)); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(valueCode)); valueCodeOop = interpreterProxy->popRemappableOop(); readwriteOop = interpreterProxy->popRemappableOop(); blurbOop = interpreterProxy->popRemappableOop(); nameOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, nameOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, blurbOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, readwriteOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, valueCodeOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertypointeratIndex(void) { sqInt pointerValueOop; sqInt defaultValueOop; long defaultValue; sqInt readable; GObject *pointerValue; GParamSpecEnum *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; pointerValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_ENUM (param); defaultValue = pstring->default_value; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); defaultValueOop = interpreterProxy->positive32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); pointerValue = g_value_get_pointer (&valueType); pointerValueOop = interpreterProxy->positive32BitIntegerFor(pointerValue); } else { pointerValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(pointerValueOop); pointerValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, pointerValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertystringatIndex(void) { sqInt defaultValueOop; gchar * defaultValue; sqInt readable; GParamSpecString *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; char *stringValue; GValue valueType = { 0, }; sqInt stringValueOop; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; stringValue = null; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_STRING (param); defaultValue = pstring->default_value; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); if (defaultValue == 0) { defaultValueOop = interpreterProxy->nilObject(); } else { defaultValueOop = stringFromCString(defaultValue); } interpreterProxy->pushRemappableOop(defaultValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); stringValue = g_value_get_string (&valueType); stringValueOop = stringFromCString(stringValue); } else { stringValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(stringValueOop); stringValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, stringValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyuintatIndex(void) { sqInt defaultValueOop; unsigned int minimumValue; sqInt uintValueOop; unsigned int defaultValue; sqInt readable; unsigned int uintValue; sqInt minimumValueOop; sqInt maximumValueOop; GParamSpec *param; sqInt arrayOop; GParamSpecUInt *pstring; GParamSpec ** propertyspecs; unsigned int maximumValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; uintValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_UINT (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->positive32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->positive32BitIntegerFor(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->positive32BitIntegerFor(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); uintValue = g_value_get_uint (&valueType); uintValueOop = interpreterProxy->positive32BitIntegerFor(uintValue); } else { uintValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(uintValueOop); uintValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, uintValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyulongatIndex(void) { sqInt defaultValueOop; unsigned long minimumValue; unsigned long ulongValue; unsigned long defaultValue; sqInt readable; sqInt minimumValueOop; sqInt ulongValueOop; sqInt maximumValueOop; GParamSpec *param; sqInt arrayOop; GParamSpecULong *pstring; GParamSpec ** propertyspecs; unsigned long maximumValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; ulongValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_ULONG (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = interpreterProxy->positive32BitIntegerFor(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = interpreterProxy->positive32BitIntegerFor(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = interpreterProxy->positive32BitIntegerFor(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); ulongValue = g_value_get_ulong (&valueType); ulongValueOop = interpreterProxy->positive32BitIntegerFor(ulongValue); } else { ulongValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(ulongValueOop); ulongValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, ulongValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegobjectclasslistpropertyulonglongatIndex(void) { sqInt ulonglongValueOop; unsigned long long ulonglongValue; sqInt defaultValueOop; unsigned long long minimumValue; sqInt minimumValueOop; unsigned long long defaultValue; sqInt readable; sqInt maximumValueOop; GParamSpecUInt64 *pstring; GParamSpec *param; sqInt arrayOop; GParamSpec ** propertyspecs; unsigned long long maximumValue; GValue valueType = { 0, }; sqInt index; sqInt propertyspecsOop; index = interpreterProxy->stackIntegerValue(1); propertyspecsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } defaultValue = 0; ulonglongValue = 0; param = 0; ; pstring = 0; ; propertyspecs = ((GParamSpec **) (interpreterProxy->positive32BitValueOf(propertyspecsOop))); ; param = propertyspecs[index]; pstring = G_PARAM_SPEC_UINT64 (param); defaultValue = pstring->default_value; minimumValue = pstring->minimum; maximumValue = pstring->maximum; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4)); defaultValueOop = positive64BitIntegerForOverride(defaultValue); interpreterProxy->pushRemappableOop(defaultValueOop); minimumValueOop = positive64BitIntegerForOverride(minimumValue); interpreterProxy->pushRemappableOop(minimumValueOop); maximumValueOop = positive64BitIntegerForOverride(maximumValue); interpreterProxy->pushRemappableOop(maximumValueOop); readable = 0; if (param->flags & G_PARAM_READABLE) readable = 1; if (readable) { g_value_init (&valueType, param->value_type); ulonglongValue = g_value_get_uint64 (&valueType); ulonglongValueOop = positive64BitIntegerForOverride(ulonglongValue); } else { ulonglongValueOop = interpreterProxy->nilObject(); } ; interpreterProxy->pushRemappableOop(ulonglongValueOop); ulonglongValueOop = interpreterProxy->popRemappableOop(); maximumValueOop = interpreterProxy->popRemappableOop(); minimumValueOop = interpreterProxy->popRemappableOop(); defaultValueOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, defaultValueOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, ulonglongValueOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, minimumValueOop); interpreterProxy->storePointerofObjectwithValue(3, arrayOop, maximumValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } /* g_object free it */ EXPORT(sqInt) primitivegobjectfree(void) { gpointer gObject; sqInt obj; obj = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gObject = ((gpointer) (interpreterProxy->positive32BitValueOf(obj))); ; g_free(gObject); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitivegobjectgetboolfrom(void) { gpointer gstObject; gboolean value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = (value) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetdoublefrom(void) { gpointer gstObject; gdouble value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = interpreterProxy->floatObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetfloatfrom(void) { gpointer gstObject; gfloat value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = interpreterProxy->floatObjectOf(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetlongfrom(void) { gpointer gstObject; long value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = interpreterProxy->signed32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetlonglongfrom(void) { gpointer gstObject; long long value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = signed64BitIntegerForOverride(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetpointerfrom(void) { gpointer gstObject; gpointer value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetsmalltalkobject(void) { gpointer gstObject; gpointer value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); if (value == 0) { _return_value = interpreterProxy->nilObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, value); return null; } EXPORT(sqInt) primitivegobjectgetstringfrom(void) { gpointer gstObject; sqInt characterOop; char * value; sqInt aGstObject; char *aName; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; g_object_get(gstObject,aName,&value,NULL); characterOop = stringFromCString(value); g_free(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, characterOop); return null; } EXPORT(sqInt) primitivegobjectgetulongfrom(void) { gpointer gstObject; unsigned long value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectgetulonglongfrom(void) { gpointer gstObject; unsigned long long value; sqInt aGstObject; char *aName; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; g_object_get(gstObject,aName,&value,NULL); _return_value = positive64BitIntegerForOverride(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegobjectsetboolon(void) { gpointer gstObject; gboolean value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = aValue; ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetdoubleon(void) { gpointer gstObject; gdouble value; sqInt aGstObject; char *aName; double aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = aValue; ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetfloaton(void) { gpointer gstObject; gfloat value; sqInt aGstObject; char *aName; double aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = aValue; ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetlonglongon(void) { gpointer gstObject; long long value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = ((gint64) (signed64BitValueOfOverride(aValue))); ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetlongon(void) { gpointer gstObject; long value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = ((glong) (signed32BitValueOfOverride(aValue))); ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetpointeron(void) { gpointer gstObject; gpointer value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = ((gpointer) (interpreterProxy->positive32BitValueOf(aValue))); ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetstringon(void) { gpointer gstObject; sqInt aGstObject; char *aName; char *aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aValue = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); g_object_set(gstObject,aName,aValue,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetulonglongon(void) { gpointer gstObject; unsigned long long value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = ((guint64) (interpreterProxy->positive64BitValueOf(aValue))); ; ; g_object_set(gstObject,aName,value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegobjectsetulongon(void) { gpointer gstObject; unsigned long value; sqInt aGstObject; char *aName; sqInt aValue; aGstObject = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); aValue = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = ((gulong) (interpreterProxy->positive32BitValueOf(aValue))); ; ; g_object_set(gstObject,aName,&value,NULL); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitivegsignalconnect(void) { void* data; GstElement* gstElement; sqInt gstElementOoop; char *aString; sqInt dataOops; gstElementOoop = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); dataOops = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); data = ((void*) (interpreterProxy->positive32BitValueOf(dataOops))); ; ; g_signal_connect(gstElement,aString, ((SqueakAudioVideoSinkPtr)data)->handler, data); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* Adds the given element to the bin. Sets the element's parent, and thus takes ownership of the element. An element can only be added to one bin. If the element's pads are linked to other pads, the pads will be unlinked before the element is added to the bin. */ EXPORT(sqInt) primitivegstbinadd(void) { GstBin *bin; sqInt result; GstElement *element; sqInt binOop; sqInt elementOop; sqInt _return_value; binOop = interpreterProxy->stackValue(1); elementOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } result = 0; bin = 0; element = 0; bin = ((GstBin *) (interpreterProxy->positive32BitValueOf(binOop))); element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); result = gst_bin_add(bin,element); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Creates a new bin with the given name. */ EXPORT(sqInt) primitivegstbinnew(void) { GstElement* gstElement; char *name; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstElement = 0; gstElement = gst_bin_new(name); _return_value = interpreterProxy->positive32BitIntegerFor(gstElement); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstbushavepending(void) { gpointer gstObject; gboolean value; sqInt aGstObject; sqInt _return_value; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; value = gst_bus_have_pending(gstObject); _return_value = (value) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstbuspeek(void) { gpointer gstObject; gpointer value; sqInt aGstObject; sqInt _return_value; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; value = gst_bus_peek(gstObject); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstbuspop(void) { gpointer gstObject; gpointer value; sqInt aGstObject; sqInt _return_value; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; value = gst_bus_pop(gstObject); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstbuspopfilter(void) { gpointer gstObject; gpointer value; sqInt aGstObject; sqInt types; sqInt _return_value; aGstObject = interpreterProxy->stackValue(1); types = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; ; // value = gst_bus_pop_filtered(gstObject,types); _return_value = interpreterProxy->positive32BitIntegerFor(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstcapsfromstring(void) { GstCaps* gstObject; char *aString; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstObject = null; gstObject = gst_caps_from_string(aString); _return_value = interpreterProxy->positive32BitIntegerFor(gstObject); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstcapstostring(void) { GstCaps* gstObject; sqInt characterOop; char * value; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((GstCaps*) (interpreterProxy->positive32BitValueOf(aGstObject))); value = 0; ; value = gst_caps_to_string(gstObject); characterOop = stringFromCString(value); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, characterOop); return null; } EXPORT(sqInt) primitivegstelementadd(void) { GstPad* gstPad; sqInt result; GstElement* element; sqInt elementOop; sqInt padOop; sqInt _return_value; elementOop = interpreterProxy->stackValue(1); padOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); gstPad = ((GstPad *) (interpreterProxy->positive32BitValueOf(padOop))); ; ; result = 0; result = gst_element_add_pad(element, gstPad); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Create a new element of the type defined by the given elementfactory. It will be given the name supplied, since all elements require a name as their first argument. */ EXPORT(sqInt) primitivegstelementfactorycreate(void) { GstElement* gstElement; GstElementFactory* gstElementFactory; sqInt factory; char *name; sqInt _return_value; factory = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); gstElement = 0; ; gstElement = gst_element_factory_create(gstElementFactory, name); _return_value = interpreterProxy->positive32BitIntegerFor(gstElement); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Search for an element factory of the given name. Refs the returned element factory; caller is responsible for unreffing. */ EXPORT(sqInt) primitivegstelementfactoryfind(void) { GstElementFactory* gstElementFactory; char *name; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstElementFactory = 0; ; gstElementFactory = gst_element_factory_find (name); _return_value = interpreterProxy->positive32BitIntegerFor(gstElementFactory); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Gets the author for this factory */ EXPORT(sqInt) primitivegstelementfactorygetauthor(void) { gchar* author; sqInt authorOop; GstElementFactory* gstElementFactory; sqInt factory; factory = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } author = null; gstElementFactory = null; ; gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); author = gst_element_factory_get_author (gstElementFactory); authorOop = stringFromCString(author); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, authorOop); return null; } /* Gets the description for this factory */ EXPORT(sqInt) primitivegstelementfactorygetdescription(void) { gchar* description; sqInt descriptionOop; GstElementFactory* gstElementFactory; sqInt factory; factory = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } description = null; gstElementFactory = null; ; gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); description = gst_element_factory_get_description (gstElementFactory); descriptionOop = stringFromCString(description); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, descriptionOop); return null; } /* ets the longname for this factory */ EXPORT(sqInt) primitivegstelementfactorygetklass(void) { gchar* klass; GstElementFactory* gstElementFactory; sqInt klassOop; sqInt factory; factory = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } klass = null; gstElementFactory = null; ; gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); ; klass = gst_element_factory_get_klass (gstElementFactory); klassOop = stringFromCString(klass); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, klassOop); return null; } /* ets the longname for this factory */ EXPORT(sqInt) primitivegstelementfactorygetlongname(void) { gchar* longName; sqInt longNameOop; GstElementFactory* gstElementFactory; sqInt factory; factory = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } longName = null; gstElementFactory = null; ; gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); ; longName = gst_element_factory_get_longname (gstElementFactory); longNameOop = stringFromCString(longName); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, longNameOop); return null; } /* Gets the type of URIs the element supports or GST_URI_UNKNOWN if none. */ EXPORT(sqInt) primitivegstelementfactorygeturitype(void) { sqInt uriTypeCount; GstElementFactory* gstElementFactory; sqInt factory; sqInt _return_value; factory = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } uriTypeCount = null; gstElementFactory = null; ; gstElementFactory = ((GstElementFactory*) (interpreterProxy->positive32BitValueOf(factory))); ; uriTypeCount = gst_element_factory_get_uri_type (gstElementFactory); _return_value = interpreterProxy->integerObjectOf(uriTypeCount); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Create a new element of the type defined by the given element factory. If name is NULL, then the element will receive a guaranteed unique name, consisting of the element factory name and a number. If name is given, it will be given the name supplied. */ EXPORT(sqInt) primitivegstelementfactorymake(void) { GstElement* gstElement; char *factoryName; char *name; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); factoryName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstElement = null; ; gstElement = gst_element_factory_make(factoryName, name); _return_value = interpreterProxy->positive32BitIntegerFor(gstElement); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstelementgetcompatiblepad(void) { GstPad* gstPadFound; GstElement* gstElement; GstPad* gstPadValue; GstCaps* gstCapsValue; sqInt gstElementOoop; sqInt aPadOop; sqInt capsOop; sqInt _return_value; gstElementOoop = interpreterProxy->stackValue(2); aPadOop = interpreterProxy->stackValue(1); capsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(aPadOop))); gstCapsValue = ((GstCaps*) (interpreterProxy->positive32BitValueOf(capsOop))); gstPadFound = 0; ; ; ; gstPadFound = gst_element_get_compatible_pad (gstElement,gstPadValue,gstCapsValue); _return_value = interpreterProxy->positive32BitIntegerFor(gstPadFound); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitivegstelementgetrequestpad(void) { GstElement* gstElement; GstPad* gstPadValue; sqInt gstElementOoop; char *name; sqInt _return_value; gstElementOoop = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstPadValue = 0; gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); ; gstPadValue = gst_element_get_request_pad (gstElement,name); _return_value = interpreterProxy->positive32BitIntegerFor(gstPadValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Sets the state of the element. This function will try to set the requested state by going through all the intermediary states and calling the class's state change function for each. This function can return GST_STATE_CHANGE_ASYNC, in which case the element will perform the remainder of the state change asynchronously in another thread. An application can use gst_element_get_state() to wait for the completion of the state change or it can wait for a state change message on the bus. */ EXPORT(sqInt) primitivegstelementgetstate(void) { GstState state; sqInt result; sqInt arrayOop; GstElement* element; GstClockTime gstClockTime; GstState pending; sqInt elementOop; sqInt gstClockTimeOop; elementOop = interpreterProxy->stackValue(1); gstClockTimeOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); gstClockTime = ((GstClockTime) (interpreterProxy->positive64BitValueOf(gstClockTimeOop))); state = 0; pending = 0; result = 0; ; ; ; ; result = gst_element_get_state(element, &state, &pending, gstClockTime); arrayOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, ((result << 1) | 1)); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, ((state << 1) | 1)); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, ((pending << 1) | 1)); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegstelementgetstaticpad(void) { GstElement* gstElement; GstPad* gstPadValue; sqInt gstElementOoop; char *name; sqInt _return_value; gstElementOoop = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstPadValue = 0; gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); ; gstPadValue = gst_element_get_static_pad(gstElement,name); _return_value = interpreterProxy->positive32BitIntegerFor(gstPadValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Connects a GCallback function to a signal for a particular object. The handler will be called before the default handler of the signal. */ EXPORT(sqInt) primitivegstelementgsignalconnect(void) { sqInt i; sqInt dataPad; sqInt *callBackData; sqInt listLength; GstElement* element; sqInt elementOop; char *aSignalName; sqInt *data; elementOop = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); aSignalName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(0))); data = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); listLength = interpreterProxy->slotSizeOf((oopForPointer( data ) - BASE_HEADER_SIZE)); callBackData = 0; callBackData = (sqInt*) g_malloc0(sizeof(sqInt)*(1+listLength)); callBackData[0] = (((sqInt) listLength)); for (i = 0; i <= (listLength - 1); i += 1) { dataPad = ((sqInt) (data[i])); callBackData[i + 1] = dataPad; if (i < 128) { callbackForPadHookupElement[i + 1] = 0; } } ; ; ; ; g_signal_connect(element, aSignalName,G_CALLBACK (cbnewpad),callBackData); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } /* Links src to dest. The link must be from source to destination; the other direction will not be tried. The function looks for existing pads that aren't linked yet. It will request new pads if necessary. Such pads need to be released manualy when unlinking. If multiple links are possible, only one is established. Make sure you have added your elements to a bin or pipeline with gst_bin_add() before trying to link them. */ EXPORT(sqInt) primitivegstelementlink(void) { sqInt result; GstElement* dest; GstElement* src; sqInt srcOop; sqInt destOop; sqInt _return_value; srcOop = interpreterProxy->stackValue(1); destOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } src = ((GstElement *) (interpreterProxy->positive32BitValueOf(srcOop))); dest = ((GstElement *) (interpreterProxy->positive32BitValueOf(destOop))); ; ; result = gst_element_link(src, dest); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstelementlinkfiltered(void) { GstCaps* caps; sqInt result; GstElement* src; GstElement* dest; sqInt srcOop; sqInt destOop; sqInt capsOop; sqInt _return_value; srcOop = interpreterProxy->stackValue(2); destOop = interpreterProxy->stackValue(1); capsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } src = ((GstElement *) (interpreterProxy->positive32BitValueOf(srcOop))); dest = ((GstElement *) (interpreterProxy->positive32BitValueOf(destOop))); caps = ((GstCaps *) (interpreterProxy->positive32BitValueOf(destOop))); result = 0; ; ; ; result = gst_element_link_filtered(src, dest,caps); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* Queries an element for the stream position */ EXPORT(sqInt) primitivegstelementqueryconvert(void) { sqInt resultOop; sqInt arrayOop; gint64 destValue; sqInt destValueOop; GstFormat destformat; sqInt result; gint64 val; GstElement* element; sqInt elementOop; sqInt srcformat; sqInt valOop; sqInt destformatOop; elementOop = interpreterProxy->stackValue(3); srcformat = interpreterProxy->stackIntegerValue(2); valOop = interpreterProxy->stackValue(1); destformatOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); destformat = ((GstFormat) (interpreterProxy->positive32BitValueOf(destformatOop))); val = ((gint64) (signed64BitValueOfOverride(valOop))); ; ; ; result = 0; destValue = 0; result = gst_element_query_convert(element,srcformat,val,&destformat,&destValue); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); interpreterProxy->pushRemappableOop((result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject()); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(destValue)); destValueOop = interpreterProxy->popRemappableOop(); resultOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, resultOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, destValueOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, arrayOop); return null; } /* Queries an element for the stream position */ EXPORT(sqInt) primitivegstelementqueryduration(void) { sqInt resultOop; gint64 duration; sqInt durationOop; sqInt arrayOop; sqInt result; GstFormat format; sqInt formatOopReturn; GstElement* element; sqInt elementOop; sqInt formatOop; elementOop = interpreterProxy->stackValue(1); formatOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); format = ((GstFormat) (interpreterProxy->positive32BitValueOf(formatOop))); ; ; result = 0; duration = 0; result = gst_element_query_duration(element,&format,&duration); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3)); interpreterProxy->pushRemappableOop((result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject()); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(format)); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(duration)); durationOop = interpreterProxy->popRemappableOop(); formatOopReturn = interpreterProxy->popRemappableOop(); resultOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, resultOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, formatOopReturn); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, durationOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } /* Queries an element for the stream position */ EXPORT(sqInt) primitivegstelementqueryposition(void) { sqInt resultOop; sqInt curOop; sqInt arrayOop; gint64 cur; sqInt result; GstFormat format; sqInt formatOopReturn; GstElement* element; sqInt elementOop; sqInt formatOop; elementOop = interpreterProxy->stackValue(1); formatOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); format = ((GstFormat) (interpreterProxy->positive32BitValueOf(formatOop))); ; ; result = 0; cur = 0; result = gst_element_query_position(element,&format,&cur); interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3)); interpreterProxy->pushRemappableOop((result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject()); interpreterProxy->pushRemappableOop(interpreterProxy->integerObjectOf(format)); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(cur)); curOop = interpreterProxy->popRemappableOop(); formatOopReturn = interpreterProxy->popRemappableOop(); resultOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, resultOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, formatOopReturn); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, curOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, arrayOop); return null; } EXPORT(sqInt) primitivegstelementreleaserequestpad(void) { GstElement* gstElement; GstPad* gstPadValue; sqInt gstElementOoop; sqInt aPadOop; gstElementOoop = interpreterProxy->stackValue(1); aPadOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstElement = ((GstElement*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(aPadOop))); ; ; gst_element_release_request_pad(gstElement,gstPadValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Sends a seek event to an element. See gst_event_new_seek() for the details of the parameters. The seek event is sent to the element using gst_element_send_event(). */ EXPORT(sqInt) primitivegstelementseek(void) { gint64 stop; gint64 cur; gboolean result; GstElement* element; sqInt elementOop; double aRate; sqInt aFormat; sqInt aFlags; sqInt aCurrentType; sqInt curOop; sqInt aStopType; sqInt stopOop; sqInt _return_value; elementOop = interpreterProxy->stackValue(7); aRate = interpreterProxy->stackFloatValue(6); aFormat = interpreterProxy->stackIntegerValue(5); aFlags = interpreterProxy->stackIntegerValue(4); aCurrentType = interpreterProxy->stackIntegerValue(3); curOop = interpreterProxy->stackValue(2); aStopType = interpreterProxy->stackIntegerValue(1); stopOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); cur = ((gint64) (signed64BitValueOfOverride(curOop))); stop = ((gint64) (signed64BitValueOfOverride(stopOop))); ; ; ; result = 0; result = gst_element_seek(element, aRate, aFormat, aFlags, aCurrentType, cur, aStopType, stop); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(9, _return_value); return null; } /* Sends a seek event to an element. */ EXPORT(sqInt) primitivegstelementseeksimple(void) { gboolean result; GstElement* element; gint64 cur; sqInt elementOop; sqInt aFormat; sqInt aFlags; sqInt curOop; sqInt _return_value; elementOop = interpreterProxy->stackValue(3); aFormat = interpreterProxy->stackIntegerValue(2); aFlags = interpreterProxy->stackIntegerValue(1); curOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); cur = ((gint64) (signed64BitValueOfOverride(curOop))); ; ; result = 0; result = gst_element_seek_simple(element, aFormat, aFlags, cur); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, _return_value); return null; } /* Sets the state of the element. This function will try to set the requested state by going through all the intermediary states and calling the class's state change function for each. This function can return GST_STATE_CHANGE_ASYNC, in which case the element will perform the remainder of the state change asynchronously in another thread. An application can use gst_element_get_state() to wait for the completion of the state change or it can wait for a state change message on the bus. */ EXPORT(sqInt) primitivegstelementsetstate(void) { sqInt result; GstElement* element; sqInt elementOop; sqInt aControlValue; sqInt _return_value; elementOop = interpreterProxy->stackValue(1); aControlValue = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } element = ((GstElement *) (interpreterProxy->positive32BitValueOf(elementOop))); ; result = gst_element_set_state(element, aControlValue); _return_value = interpreterProxy->positive32BitIntegerFor(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstghostpadnew(void) { GstPad* gstPad; GstPad* newGstPad; sqInt gstElementOoop; char *name; sqInt _return_value; gstElementOoop = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } newGstPad = 0; gstPad = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstElementOoop))); ; newGstPad = gst_ghost_pad_new(name,gstPad); _return_value = interpreterProxy->positive32BitIntegerFor(newGstPad); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins. */ EXPORT(sqInt) primitivegstinitcheck(void) { gboolean initialize; sqInt _return_value; initialize = 0; initialize = gst_init_check(null,null,null); _return_value = (initialize? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitivegstmessageparsebuffering(void) { gpointer gstObject; sqInt percent; sqInt aGstObject; sqInt _return_value; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; percent = 0; gst_message_parse_buffering(gstObject,&percent); _return_value = interpreterProxy->positive32BitIntegerFor(percent); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstmessageparseduration(void) { sqInt positionOop; sqInt formatOop; sqInt arrayOop; gpointer gstObject; GstFormat format; gint64 position; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; format = 0; position = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_duration(gstObject,&format,&position); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(format)); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(position)); positionOop = interpreterProxy->popRemappableOop(); formatOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, formatOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, positionOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparseerror(void) { sqInt debugStringOop; char * errorMessage; sqInt arrayOop; gpointer gstObject; char * debugString; GError * errorString; sqInt errorStringOop; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; errorString = 0; debugString = 0; errorMessage = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_error(gstObject,&errorString,&debugString); errorMessage = errorString->message; errorStringOop = stringFromCString(errorMessage); interpreterProxy->pushRemappableOop(errorStringOop); g_error_free(errorString); if (debugString == 0) { debugStringOop = interpreterProxy->nilObject(); } else { debugStringOop = stringFromCString(debugString); g_free(debugString); } interpreterProxy->pushRemappableOop(debugStringOop); debugStringOop = interpreterProxy->popRemappableOop(); errorStringOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, errorStringOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, debugStringOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparseinfo(void) { sqInt debugStringOop; char * errorMessage; sqInt arrayOop; gpointer gstObject; char * debugString; GError * errorString; sqInt errorStringOop; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; errorString = 0; debugString = 0; errorMessage = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_info(gstObject,&errorString,&debugString); errorMessage = errorString->message; errorStringOop = stringFromCString(errorMessage); interpreterProxy->pushRemappableOop(errorStringOop); g_error_free(errorString); if (debugString == 0) { debugStringOop = interpreterProxy->nilObject(); } else { debugStringOop = stringFromCString(debugString); g_free(debugString); } interpreterProxy->pushRemappableOop(debugStringOop); debugStringOop = interpreterProxy->popRemappableOop(); errorStringOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, errorStringOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, debugStringOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparsesegmentdone(void) { sqInt positionOop; sqInt formatOop; sqInt arrayOop; gpointer gstObject; GstFormat format; gint64 position; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; format = 0; position = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_segment_done(gstObject,&format,&position); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(format)); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(position)); positionOop = interpreterProxy->popRemappableOop(); formatOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, formatOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, positionOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparsesegmentstart(void) { sqInt positionOop; sqInt formatOop; sqInt arrayOop; gpointer gstObject; GstFormat format; gint64 position; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; format = 0; position = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_segment_start(gstObject,&format,&position); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(format)); interpreterProxy->pushRemappableOop(signed64BitIntegerForOverride(position)); positionOop = interpreterProxy->popRemappableOop(); formatOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, formatOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, positionOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparsestatechanged(void) { sqInt newOop; GstState old; gpointer gstObject; GstState new; sqInt pendingOop; GstState pending; sqInt arrayOop; sqInt oldOop; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; old = new = pending = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3)); gst_message_parse_state_changed(gstObject,&old,&new,&pending); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(old)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(new)); interpreterProxy->pushRemappableOop(interpreterProxy->positive32BitIntegerFor(pending)); pendingOop = interpreterProxy->popRemappableOop(); newOop = interpreterProxy->popRemappableOop(); oldOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, oldOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, newOop); interpreterProxy->storePointerofObjectwithValue(2, arrayOop, pendingOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessageparsewarning(void) { sqInt debugStringOop; char * errorMessage; sqInt arrayOop; gpointer gstObject; char * debugString; GError * errorString; sqInt errorStringOop; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; errorString = 0; debugString = 0; errorMessage = 0; interpreterProxy->pushRemappableOop(interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2)); gst_message_parse_warning(gstObject,&errorString,&debugString); errorMessage = errorString->message; errorStringOop = stringFromCString(errorMessage); interpreterProxy->pushRemappableOop(errorStringOop); g_error_free(errorString); if (debugString == 0) { debugStringOop = interpreterProxy->nilObject(); } else { debugStringOop = stringFromCString(debugString); g_free(debugString); } interpreterProxy->pushRemappableOop(debugStringOop); debugStringOop = interpreterProxy->popRemappableOop(); errorStringOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, errorStringOop); interpreterProxy->storePointerofObjectwithValue(1, arrayOop, debugStringOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, arrayOop); return null; } EXPORT(sqInt) primitivegstmessagesrc(void) { gpointer gstObject; GstObject * gstSrcObject; sqInt aGstObject; sqInt _return_value; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); gstSrcObject = null; ; ; gstSrcObject = GST_MESSAGE_SRC(gstObject); _return_value = interpreterProxy->positive32BitIntegerFor(gstSrcObject); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstmessagetypestring(void) { gpointer gstObject; char * msgString; sqInt msgStringOop; sqInt value; sqInt aGstObject; aGstObject = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(aGstObject))); ; ; value = GST_MESSAGE_TYPE(gstObject); msgString = gst_message_type_get_name(value); msgStringOop = stringFromCString(msgString); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, msgStringOop); return null; } /* Convenience macro to decrease the reference count of the message, possibly freeing it. */ EXPORT(sqInt) primitivegstmessageunref(void) { gpointer gstObject; sqInt obj; obj = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(obj))); gst_message_unref(gstObject); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Decrements the reference count on object. If reference count hits zero, destroy object. This function does not take the lock on object as it relies on atomic refcounting. The unref method should never be called with the LOCK held since this might deadlock the dispose function. */ EXPORT(sqInt) primitivegstobjectunref(void) { gpointer gstObject; sqInt obj; obj = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstObject = ((gpointer) (interpreterProxy->positive32BitValueOf(obj))); gst_object_unref(gstObject); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitivegstpadacceptcaps(void) { sqInt result; GstPad* gstPadValue; GstCaps* gstCapsValue; sqInt gstPadOop; sqInt gstCapsOop; sqInt _return_value; gstPadOop = interpreterProxy->stackValue(1); gstCapsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstPadOop))); gstCapsValue = ((GstCaps*) (interpreterProxy->positive32BitValueOf(gstCapsOop))); ; ; result = 0; result = gst_pad_accept_caps (gstPadValue, gstCapsValue); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstpadgetcaps(void) { GstPad* gstPadValue; GstCaps* gstCapsValue; sqInt gstPadOop; sqInt _return_value; gstPadOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstCapsValue = 0; gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstPadOop))); ; gstCapsValue = gst_pad_get_caps (gstPadValue); _return_value = interpreterProxy->positive32BitIntegerFor(gstCapsValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstpadgetparentelement(void) { GstPad* gstPadValue; GstElement* gstEvementValue; sqInt gstPadOop; sqInt _return_value; gstPadOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstEvementValue = 0; gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstPadOop))); ; gstEvementValue = gst_pad_get_parent_element (gstPadValue); _return_value = interpreterProxy->positive32BitIntegerFor(gstEvementValue); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } EXPORT(sqInt) primitivegstpadlink(void) { sqInt result; GstPad* dest; GstPad* src; sqInt srcOop; sqInt destOop; sqInt _return_value; srcOop = interpreterProxy->stackValue(1); destOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } src = ((GstPad *) (interpreterProxy->positive32BitValueOf(srcOop))); dest = ((GstPad *) (interpreterProxy->positive32BitValueOf(destOop))); result = 0; ; ; result = gst_pad_link(src, dest); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstpadsetactive(void) { sqInt result; GstPad* gstPadValue; sqInt gstPadOop; sqInt aBoolean; sqInt _return_value; gstPadOop = interpreterProxy->stackValue(1); aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstPadOop))); ; result = 0; result = gst_pad_set_active (gstPadValue, aBoolean); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitivegstpadsetcaps(void) { sqInt result; GstPad* gstPadValue; GstCaps* gstCapsValue; sqInt gstPadOop; sqInt gstCapsOop; sqInt _return_value; gstPadOop = interpreterProxy->stackValue(1); gstCapsOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPadValue = ((GstPad*) (interpreterProxy->positive32BitValueOf(gstPadOop))); gstCapsValue = ((GstCaps*) (interpreterProxy->positive32BitValueOf(gstCapsOop))); ; ; result = 0; result = gst_pad_set_caps(gstPadValue, gstCapsValue); _return_value = (result) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Gets the gstClock of pipeline. */ EXPORT(sqInt) primitivegstpipelineautoclock(void) { GstPipeline* gstPipeline; sqInt gstPipelineOop; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); ; gst_pipeline_auto_clock(gstPipeline); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Usually, when a pipeline goes from READY to NULL state, it automatically flushes all pending messages on the bus, which is done for refcounting purposes, to break circular references. This means that applications that update state using (async) bus messages (e.g. do certain things when a pipeline goes from PAUSED to READY) might not get to see messages when the pipeline is shut down, because they might be flushed before they can be dispatched in the main thread. This behaviour can be disabled using this function. It is important that all messages on the bus are handled when the automatic flushing is disabled else memory leaks will be introduced. */ EXPORT(sqInt) primitivegstpipelinegetautoflushbus(void) { GstPipeline* gstPipeline; gboolean aBoolean; sqInt gstPipelineOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); aBoolean = 0; ; aBoolean = gst_pipeline_get_auto_flush_bus(gstPipeline); _return_value = (aBoolean) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Gets the GstBus of pipeline. */ EXPORT(sqInt) primitivegstpipelinegetbus(void) { GstBus* gstBus; GstPipeline* gstPipeline; sqInt gstPipelineOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstBus = 0; gstBus = gst_pipeline_get_bus(gstPipeline); _return_value = interpreterProxy->positive32BitIntegerFor(gstBus); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Gets the gstClock of pipeline. */ EXPORT(sqInt) primitivegstpipelinegetclock(void) { GstClock* gstClock; GstPipeline* gstPipeline; sqInt gstPipelineOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClock = 0; ; gstClock = gst_pipeline_get_clock(gstPipeline); _return_value = interpreterProxy->positive32BitIntegerFor(gstClock); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Get the configured delay (see gst_pipeline_set_delay()). */ EXPORT(sqInt) primitivegstpipelinegetdelay(void) { GstPipeline* gstPipeline; GstClockTime gstClockTime; sqInt gstPipelineOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClockTime = 0; ; gstClockTime = gst_pipeline_get_delay(gstPipeline); _return_value = positive64BitIntegerForOverride(gstClockTime); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Gets the last stream time of pipeline. If the pipeline is PLAYING, the returned time is the stream time used to configure the element's base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned time is the stream time when the pipeline was paused. This function returns GST_CLOCK_TIME_NONE if the pipeline was configured to not handle the management of the element's base time (see gst_pipeline_set_new_stream_time()). */ EXPORT(sqInt) primitivegstpipelinegetlaststreamtime(void) { GstPipeline* gstPipeline; GstClockTime gstClockTime; sqInt gstPipelineOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClockTime = 0; ; gstClockTime = gst_pipeline_get_last_stream_time(gstPipeline); _return_value = positive64BitIntegerForOverride(gstClockTime); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Create a new pipeline with the given name. */ EXPORT(sqInt) primitivegstpipelinenew(void) { GstElement* gstElement; char *name; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); name = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } gstElement = 0; gstElement = gst_pipeline_new(name); _return_value = interpreterProxy->positive32BitIntegerFor(gstElement); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* Usually, when a pipeline goes from READY to NULL state, it automatically flushes all pending messages on the bus, which is done for refcounting purposes, to break circular references. This means that applications that update state using (async) bus messages (e.g. do certain things when a pipeline goes from PAUSED to READY) might not get to see messages when the pipeline is shut down, because they might be flushed before they can be dispatched in the main thread. This behaviour can be disabled using this function. It is important that all messages on the bus are handled when the automatic flushing is disabled else memory leaks will be introduced. */ EXPORT(sqInt) primitivegstpipelinesetautoflushbus(void) { GstPipeline* gstPipeline; sqInt gstPipelineOop; sqInt aBoolean; gstPipelineOop = interpreterProxy->stackValue(1); aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); ; gst_pipeline_set_auto_flush_bus(gstPipeline,aBoolean); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Let pipeline select a clock automatically. This is the default behaviour. Use this function if you previous forced a fixed clock with gst_pipeline_use_clock() and want to restore the default pipeline clock selection algorithm. */ EXPORT(sqInt) primitivegstpipelinesetclock(void) { GstClock* gstClock; GstPipeline* gstPipeline; gboolean aResult; sqInt gstPipelineOop; sqInt aClockValueOop; sqInt _return_value; gstPipelineOop = interpreterProxy->stackValue(1); aClockValueOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClock = ((GstClock*) (interpreterProxy->positive32BitValueOf(aClockValueOop))); ; ; aResult = 0; aResult = gst_pipeline_set_clock(gstPipeline,gstClock); _return_value = (aResult) ? interpreterProxy->trueObject(): interpreterProxy->falseObject(); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* Set the expected delay needed for all elements to perform the PAUSED to PLAYING state change. delay will be added to the base time of the elements so that they wait an additional delay amount of time before starting to process buffers and cannot be GST_CLOCK_TIME_NONE. This option is used for tuning purposes and should normally not be used. */ EXPORT(sqInt) primitivegstpipelinesetdelay(void) { GstPipeline* gstPipeline; GstClockTime gstClockTime ; sqInt gstPipelineOop; sqInt aClockValueOop; gstPipelineOop = interpreterProxy->stackValue(1); aClockValueOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClockTime = ((GstClockTime) (interpreterProxy->positive64BitValueOf(aClockValueOop))); ; ; gst_pipeline_set_delay(gstPipeline,gstClockTime); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Set the new stream time of pipeline to time. The stream time is used to set the base time on the elements (see gst_element_set_base_time()) in the PAUSED->PLAYING state transition. Setting time to GST_CLOCK_TIME_NONE will disable the pipeline's management of element base time. The application will then be responsible for performing base time distribution. This is sometimes useful if you want to synchronize capture from multiple pipelines, and you can also ensure that the pipelines have the same clock. */ EXPORT(sqInt) primitivegstpipelinesetnewstreamtime(void) { GstPipeline* gstPipeline; GstClockTime gstClockTime ; sqInt gstPipelineOop; sqInt aClockValueOop; gstPipelineOop = interpreterProxy->stackValue(1); aClockValueOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClockTime = ((GstClockTime) (interpreterProxy->positive64BitValueOf(aClockValueOop))); ; ; gst_pipeline_set_new_stream_time(gstPipeline,gstClockTime); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Force pipeline to use the given clock. The pipeline will always use the given clock even if new clock providers are added to this pipeline. If clock is NULL all clocking will be disabled which will make the pipeline run as fast as possible. */ EXPORT(sqInt) primitivegstpipelineuseclock(void) { GstClock* gstClock; GstPipeline* gstPipeline; gboolean aResult; sqInt gstPipelineOop; sqInt aClockValueOop; gstPipelineOop = interpreterProxy->stackValue(1); aClockValueOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } gstPipeline = ((GstPipeline*) (interpreterProxy->positive32BitValueOf(gstPipelineOop))); gstClock = ((GstClock*) (interpreterProxy->positive32BitValueOf(aClockValueOop))); ; ; aResult = 0; gst_pipeline_use_clock(gstPipeline,gstClock); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Applications might want to disable/enable the usage of fork() when rebuilding the registry. See gst_registry_fork_is_enabled() for more information. On platforms without fork(), this function will have no effect on the return value of gst_registry_fork_is_enabled(). enabled†: whether rebuilding the registry may fork */ EXPORT(sqInt) primitivegstregistryforksetenabled(void) { gboolean on; sqInt aBoolean; aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } on = aBoolean; ; gst_registry_fork_set_enabled(on); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Some functions in the GStreamer core might install a custom SIGSEGV handler to better catch and report errors to the application. Currently this feature is enabled by default when loading plugins. Applications might want to disable this behaviour with the gst_segtrap_set_enabled() function. This is typically done if the application wants to install its own handler without GStreamer interfering. */ EXPORT(sqInt) primitivegstsegtrapisenabled(void) { gboolean on; sqInt _return_value; on = 0; on = gst_segtrap_is_enabled(); _return_value = (on? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } /* Some functions in the GStreamer core might install a custom SIGSEGV handler to better catch and report errors to the application. Currently this feature is enabled by default when loading plugins. Applications might want to disable this behaviour with the gst_segtrap_set_enabled() function. This is typically done if the application wants to install its own handler without GStreamer interfering. */ EXPORT(sqInt) primitivegstsegtrapsetenabled(void) { gboolean on; sqInt aBoolean; aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } on = aBoolean; ; gst_segtrap_set_enabled(on); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* This function returns a string that is useful for describing this version of GStreamer to the outside world: user agent strings, logging, ... */ EXPORT(sqInt) primitivegstversionstring(void) { gchar *version; sqInt versionOOp; version = gst_version_string(); versionOOp = stringFromCString(version); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, versionOOp); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt shutdownModule(void) { return 1; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a four-byte LargeInteger. */ static sqInt signed32BitValueOfOverride(sqInt oop) { sqInt largeClass; unsigned char *where; sqInt negative; sqInt value; sqInt sz; if ((oop & 1)) { return (oop >> 1); } largeClass = interpreterProxy->fetchClassOf(oop); if (largeClass == (interpreterProxy->classLargePositiveInteger())) { negative = 0; } else { if (largeClass == (interpreterProxy->classLargeNegativeInteger())) { negative = 1; } else { return interpreterProxy->primitiveFail(); } } sz = interpreterProxy->slotSizeOf(oop); if (!(sz == 4)) { return interpreterProxy->primitiveFail(); } where = interpreterProxy->firstIndexableField(oop); /* Filter out values out of range for the signed interpretation such as 16rFFFFFFFF (positive w/ bit 32 set) and -16rFFFFFFFF (negative w/ bit 32 set). Since the sign is implicit in the class we require that the high bit of the magnitude is not set which is a simple test here. */ value = (((where[0]) + ((where[1]) << 8)) + ((where[2]) << 16)) + ((where[3]) << 24); if (negative && (value == (1 << 31))) { return value; } if (value < 0) { return interpreterProxy->primitiveFail(); } if (negative) { return 0 - value; } else { return value; } } /* Return a Large Integer object for the given integer value */ static sqInt signed64BitIntegerForOverride(sqLong integerValue) { sqInt sz; sqInt i; sqInt newLargeInteger; sqInt intValue; sqLong magnitude; sqLong lowestIntegerValue; unsigned char*where; sqInt largeClass; usqInt highWord; lowestIntegerValue = 1; lowestIntegerValue = lowestIntegerValue << 63; if (integerValue == lowestIntegerValue) { /* newLargeInteger := self instantiateClass: largeClass indexableSize: 8. */ largeClass = interpreterProxy->classLargeNegativeInteger(); newLargeInteger = interpreterProxy->instantiateClassindexableSize(largeClass, 8); where = interpreterProxy->firstIndexableField(newLargeInteger); where[7] = 128; return newLargeInteger; } if (integerValue < 0) { largeClass = interpreterProxy->classLargeNegativeInteger(); magnitude = 0 - integerValue; } else { largeClass = interpreterProxy->classLargePositiveInteger(); magnitude = integerValue; } if (magnitude <= 2147483647U) { return interpreterProxy->signed32BitIntegerFor(integerValue); } /* shift is coerced to usqInt otherwise */ highWord = magnitude >> 32; if (highWord == 0) { sz = 4; } else { sz = 5; if ((highWord = ((usqInt) highWord) >> 8) > 0) { sz += 1; } if ((highWord = ((usqInt) highWord) >> 8) > 0) { sz += 1; } if ((highWord = ((usqInt) highWord) >> 8) > 0) { sz += 1; } } newLargeInteger = interpreterProxy->instantiateClassindexableSize(largeClass, sz); where = interpreterProxy->firstIndexableField(newLargeInteger); for (i = 0; i <= (sz - 1); i += 1) { /* self storeByte: i ofObject: newLargeInteger withValue: intValue */ intValue = (magnitude >> (i * 8)) & 255; where[i] = intValue; } return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargeInteger. */ static sqLong signed64BitValueOfOverride(sqInt oop) { sqInt negative; sqInt sz; sqInt i; sqLong lowestIntegerValue; unsigned char *where; sqInt largeClass; sqInt szsqLong; sqLong value; if ((oop & 1)) { return ((sqLong) ((oop >> 1))); } largeClass = interpreterProxy->fetchClassOf(oop); if (largeClass == (interpreterProxy->classLargePositiveInteger())) { negative = 0; } else { if (largeClass == (interpreterProxy->classLargeNegativeInteger())) { negative = 1; } else { return interpreterProxy->primitiveFail(); } } szsqLong = sizeof(sqLong); sz = interpreterProxy->slotSizeOf(oop); if (sz > szsqLong) { return interpreterProxy->primitiveFail(); } value = 0; where = interpreterProxy->firstIndexableField(oop); for (i = 0; i <= (sz - 1); i += 1) { value += (((sqLong) (where[i]))) << (i * 8); } lowestIntegerValue = 1; lowestIntegerValue = lowestIntegerValue << 63; if (negative && (value == lowestIntegerValue)) { return value; } if (value < 0) { return interpreterProxy->primitiveFail(); } if (negative) { return 0 - value; } else { return value; } } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char *aCString) { sqInt len; sqInt newString; if (aCString == null) { return interpreterProxy->nilObject(); } len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } #ifdef SQUEAK_BUILTIN_PLUGIN void* GStreamerPlugin_exports[][3] = { {"GStreamerPlugin", "primitivegstelementfactorygeturitype", (void*)primitivegstelementfactorygeturitype}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyulongatIndex", (void*)primitivegobjectclasslistpropertyulongatIndex}, {"GStreamerPlugin", "primitivegstpipelinesetdelay", (void*)primitivegstpipelinesetdelay}, {"GStreamerPlugin", "primitivegstmessageparsesegmentstart", (void*)primitivegstmessageparsesegmentstart}, {"GStreamerPlugin", "primitivegobjectgetlonglongfrom", (void*)primitivegobjectgetlonglongfrom}, {"GStreamerPlugin", "primitivegstpipelinesetnewstreamtime", (void*)primitivegstpipelinesetnewstreamtime}, {"GStreamerPlugin", "primitivegstelementfactorygetdescription", (void*)primitivegstelementfactorygetdescription}, {"GStreamerPlugin", "primitivegstregistryforksetenabled", (void*)primitivegstregistryforksetenabled}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyfloatatIndex", (void*)primitivegobjectclasslistpropertyfloatatIndex}, {"GStreamerPlugin", "primitivegstmessageparseerror", (void*)primitivegstmessageparseerror}, {"GStreamerPlugin", "primitivegstelementseek", (void*)primitivegstelementseek}, {"GStreamerPlugin", "primitivegstpadacceptcaps", (void*)primitivegstpadacceptcaps}, {"GStreamerPlugin", "primitivegstmessageunref", (void*)primitivegstmessageunref}, {"GStreamerPlugin", "primitiveSqueakSinkAudioGetData", (void*)primitiveSqueakSinkAudioGetData}, {"GStreamerPlugin", "primitiveSqueakSinkVideo", (void*)primitiveSqueakSinkVideo}, {"GStreamerPlugin", "primitivegstbuspopfilter", (void*)primitivegstbuspopfilter}, {"GStreamerPlugin", "primitivegobjectclasslistpropertypointeratIndex", (void*)primitivegobjectclasslistpropertypointeratIndex}, {"GStreamerPlugin", "primitivegobjectsetstringon", (void*)primitivegobjectsetstringon}, {"GStreamerPlugin", "primitiveSqueakSinkGetFrameRateNumerator", (void*)primitiveSqueakSinkGetFrameRateNumerator}, {"GStreamerPlugin", "primitivegobjectsetboolon", (void*)primitivegobjectsetboolon}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyenumatIndex", (void*)primitivegobjectclasslistpropertyenumatIndex}, {"GStreamerPlugin", "primitivegstelementgsignalconnect", (void*)primitivegstelementgsignalconnect}, {"GStreamerPlugin", "primitivegsignalconnect", (void*)primitivegsignalconnect}, {"GStreamerPlugin", "primitivegstpadsetactive", (void*)primitivegstpadsetactive}, {"GStreamerPlugin", "primitivegstmessagesrc", (void*)primitivegstmessagesrc}, {"GStreamerPlugin", "primitivegstsegtrapsetenabled", (void*)primitivegstsegtrapsetenabled}, {"GStreamerPlugin", "primitiveSqueakSinkGetWidth", (void*)primitiveSqueakSinkGetWidth}, {"GStreamerPlugin", "primitiveSqueakSinkGetFrameRateDenominator", (void*)primitiveSqueakSinkGetFrameRateDenominator}, {"GStreamerPlugin", "primitivegstpipelinegetlaststreamtime", (void*)primitivegstpipelinegetlaststreamtime}, {"GStreamerPlugin", "primitivegstcapstostring", (void*)primitivegstcapstostring}, {"GStreamerPlugin", "primitivegstelementgetstate", (void*)primitivegstelementgetstate}, {"GStreamerPlugin", "primitivegobjectgetdoublefrom", (void*)primitivegobjectgetdoublefrom}, {"GStreamerPlugin", "primitivegstelementgetcompatiblepad", (void*)primitivegstelementgetcompatiblepad}, {"GStreamerPlugin", "primitivegstbuspop", (void*)primitivegstbuspop}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyulonglongatIndex", (void*)primitivegobjectclasslistpropertyulonglongatIndex}, {"GStreamerPlugin", "primitivegstmessageparsestatechanged", (void*)primitivegstmessageparsestatechanged}, {"GStreamerPlugin", "primitivegstpipelinegetdelay", (void*)primitivegstpipelinegetdelay}, {"GStreamerPlugin", "primitivegstpipelinesetclock", (void*)primitivegstpipelinesetclock}, {"GStreamerPlugin", "primitivegstbushavepending", (void*)primitivegstbushavepending}, {"GStreamerPlugin", "primitivegobjectgetulongfrom", (void*)primitivegobjectgetulongfrom}, {"GStreamerPlugin", "primitivegobjectclasslistpropertydoubleatIndex", (void*)primitivegobjectclasslistpropertydoubleatIndex}, {"GStreamerPlugin", "primitivegstpadsetcaps", (void*)primitivegstpadsetcaps}, {"GStreamerPlugin", "primitivegstelementsetstate", (void*)primitivegstelementsetstate}, {"GStreamerPlugin", "primitivegstmessageparseinfo", (void*)primitivegstmessageparseinfo}, {"GStreamerPlugin", "primitiveSqueakSinkAllocate", (void*)primitiveSqueakSinkAllocate}, {"GStreamerPlugin", "primitivegobjectfree", (void*)primitivegobjectfree}, {"GStreamerPlugin", "primitivegobjectgetboolfrom", (void*)primitivegobjectgetboolfrom}, {"GStreamerPlugin", "primitiveSqueakSrcAllocate", (void*)primitiveSqueakSrcAllocate}, {"GStreamerPlugin", "primitivegstversionstring", (void*)primitivegstversionstring}, {"GStreamerPlugin", "primitivegstelementfactorygetklass", (void*)primitivegstelementfactorygetklass}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyboolatIndex", (void*)primitivegobjectclasslistpropertyboolatIndex}, {"GStreamerPlugin", "primitivegstmessageparseduration", (void*)primitivegstmessageparseduration}, {"GStreamerPlugin", "primitivegstelementfactoryfind", (void*)primitivegstelementfactoryfind}, {"GStreamerPlugin", "primitivegobjectsetfloaton", (void*)primitivegobjectsetfloaton}, {"GStreamerPlugin", "primitivegobjectgetlongfrom", (void*)primitivegobjectgetlongfrom}, {"GStreamerPlugin", "primitivegstmessageparsebuffering", (void*)primitivegstmessageparsebuffering}, {"GStreamerPlugin", "setInterpreter", (void*)setInterpreter}, {"GStreamerPlugin", "primitivegstelementseeksimple", (void*)primitivegstelementseeksimple}, {"GStreamerPlugin", "primitivegobjectclasslistpropertystringatIndex", (void*)primitivegobjectclasslistpropertystringatIndex}, {"GStreamerPlugin", "primitivegstpadlink", (void*)primitivegstpadlink}, {"GStreamerPlugin", "primitivegobjectgetulonglongfrom", (void*)primitivegobjectgetulonglongfrom}, {"GStreamerPlugin", "primitivegstpipelinegetclock", (void*)primitivegstpipelinegetclock}, {"GStreamerPlugin", "getModuleName", (void*)getModuleName}, {"GStreamerPlugin", "primitivegetoop", (void*)primitivegetoop}, {"GStreamerPlugin", "primitivegobjectgetsmalltalkobject", (void*)primitivegobjectgetsmalltalkobject}, {"GStreamerPlugin", "primitivegstbinadd", (void*)primitivegstbinadd}, {"GStreamerPlugin", "primitivegstelementfactorymake", (void*)primitivegstelementfactorymake}, {"GStreamerPlugin", "primitivegstpipelinegetbus", (void*)primitivegstpipelinegetbus}, {"GStreamerPlugin", "primitivegstpadgetparentelement", (void*)primitivegstpadgetparentelement}, {"GStreamerPlugin", "primitivegstelementgetrequestpad", (void*)primitivegstelementgetrequestpad}, {"GStreamerPlugin", "primitiveSqueakSrcWithTime", (void*)primitiveSqueakSrcWithTime}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyintatIndex", (void*)primitivegobjectclasslistpropertyintatIndex}, {"GStreamerPlugin", "primitivegstpipelinenew", (void*)primitivegstpipelinenew}, {"GStreamerPlugin", "primitivegobjectclasslistpropertymetaDataatIndex", (void*)primitivegobjectclasslistpropertymetaDataatIndex}, {"GStreamerPlugin", "primitivegstelementqueryduration", (void*)primitivegstelementqueryduration}, {"GStreamerPlugin", "primitivegstpipelinegetautoflushbus", (void*)primitivegstpipelinegetautoflushbus}, {"GStreamerPlugin", "primitivegobjectgetpointerfrom", (void*)primitivegobjectgetpointerfrom}, {"GStreamerPlugin", "primitivegstpipelinesetautoflushbus", (void*)primitivegstpipelinesetautoflushbus}, {"GStreamerPlugin", "primitivegstelementqueryconvert", (void*)primitivegstelementqueryconvert}, {"GStreamerPlugin", "primitivegobjectsetpointeron", (void*)primitivegobjectsetpointeron}, {"GStreamerPlugin", "primitivegobjectsetdoubleon", (void*)primitivegobjectsetdoubleon}, {"GStreamerPlugin", "primitivegobjectsetlongon", (void*)primitivegobjectsetlongon}, {"GStreamerPlugin", "primitivegstelementreleaserequestpad", (void*)primitivegstelementreleaserequestpad}, {"GStreamerPlugin", "primitivegobjectsetulongon", (void*)primitivegobjectsetulongon}, {"GStreamerPlugin", "primitivegstelementlink", (void*)primitivegstelementlink}, {"GStreamerPlugin", "primitivegstpadgetcaps", (void*)primitivegstpadgetcaps}, {"GStreamerPlugin", "primitivecallbacksignalseenfor", (void*)primitivecallbacksignalseenfor}, {"GStreamerPlugin", "primitivegstelementfactorycreate", (void*)primitivegstelementfactorycreate}, {"GStreamerPlugin", "primitiveSqueakSrc", (void*)primitiveSqueakSrc}, {"GStreamerPlugin", "primitivegobjectclasslistpropertylonglongatIndex", (void*)primitivegobjectclasslistpropertylonglongatIndex}, {"GStreamerPlugin", "primitivegstbinnew", (void*)primitivegstbinnew}, {"GStreamerPlugin", "primitivegstinitcheck", (void*)primitivegstinitcheck}, {"GStreamerPlugin", "primitivegstghostpadnew", (void*)primitivegstghostpadnew}, {"GStreamerPlugin", "primitivegstelementfactorygetauthor", (void*)primitivegstelementfactorygetauthor}, {"GStreamerPlugin", "primitivegstelementfactorygetlongname", (void*)primitivegstelementfactorygetlongname}, {"GStreamerPlugin", "primitivegobjectclasslistpropertyuintatIndex", (void*)primitivegobjectclasslistpropertyuintatIndex}, {"GStreamerPlugin", "primitiveSqueakSinkFree", (void*)primitiveSqueakSinkFree}, {"GStreamerPlugin", "primitivegstelementadd", (void*)primitivegstelementadd}, {"GStreamerPlugin", "primitivegstelementgetstaticpad", (void*)primitivegstelementgetstaticpad}, {"GStreamerPlugin", "primitivegobjectsetlonglongon", (void*)primitivegobjectsetlonglongon}, {"GStreamerPlugin", "primitivegstpipelineuseclock", (void*)primitivegstpipelineuseclock}, {"GStreamerPlugin", "primitivegobjectgetfloatfrom", (void*)primitivegobjectgetfloatfrom}, {"GStreamerPlugin", "primitivegstobjectunref", (void*)primitivegstobjectunref}, {"GStreamerPlugin", "primitivegobjectgetstringfrom", (void*)primitivegobjectgetstringfrom}, {"GStreamerPlugin", "primitivegobjectsetulonglongon", (void*)primitivegobjectsetulonglongon}, {"GStreamerPlugin", "primitivegstbuspeek", (void*)primitivegstbuspeek}, {"GStreamerPlugin", "primitivegobjectclasslistproperties", (void*)primitivegobjectclasslistproperties}, {"GStreamerPlugin", "primitivegstmessagetypestring", (void*)primitivegstmessagetypestring}, {"GStreamerPlugin", "primitivegstmessageparsesegmentdone", (void*)primitivegstmessageparsesegmentdone}, {"GStreamerPlugin", "primitivegobjectclasslistpropertylongatIndex", (void*)primitivegobjectclasslistpropertylongatIndex}, {"GStreamerPlugin", "primitivegstsegtrapisenabled", (void*)primitivegstsegtrapisenabled}, {"GStreamerPlugin", "primitivegstelementlinkfiltered", (void*)primitivegstelementlinkfiltered}, {"GStreamerPlugin", "primitivegstmessageparsewarning", (void*)primitivegstmessageparsewarning}, {"GStreamerPlugin", "primitivegstcapsfromstring", (void*)primitivegstcapsfromstring}, {"GStreamerPlugin", "primitivegetinterpreterproxy", (void*)primitivegetinterpreterproxy}, {"GStreamerPlugin", "primitiveSqueakSinkGetHeight", (void*)primitiveSqueakSinkGetHeight}, {"GStreamerPlugin", "primitivegstelementqueryposition", (void*)primitivegstelementqueryposition}, {"GStreamerPlugin", "primitivegstpipelineautoclock", (void*)primitivegstpipelineautoclock}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/HostWindowPlugin/HostWindowPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:56 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "HostWindowPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveCloseHostWindow(void); EXPORT(sqInt) primitiveCreateHostWindow(void); EXPORT(sqInt) primitiveHostWindowPosition(void); EXPORT(sqInt) primitiveHostWindowPositionSet(void); EXPORT(sqInt) primitiveHostWindowSize(void); EXPORT(sqInt) primitiveHostWindowSizeSet(void); EXPORT(sqInt) primitiveHostWindowTitle(void); EXPORT(sqInt) primitiveShowHostWindowRect(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "HostWindowPlugin 23 January 2011 (i)" #else "HostWindowPlugin 23 January 2011 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Close a host window. windowIndex is the SmallInt handle returned previously by primitiveCreateHostWindow. Fail if the index is invalid or the platform code fails */ EXPORT(sqInt) primitiveCloseHostWindow(void) { sqInt ok; sqInt windowIndex; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } ok = closeWindow(windowIndex); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* Create a host window of width 'w' pixels, height 'h' with the origin of the user area at 'x@y' from the topleft corner of the screen. Return the SmallInt value of the internal index to the window description block - which is whatever the host platform code needs it to be. */ EXPORT(sqInt) primitiveCreateHostWindow(void) { sqInt windowIndex; sqInt listLength; sqInt w; sqInt h; sqInt x; sqInt y; char *list; sqInt _return_value; w = interpreterProxy->stackIntegerValue(4); h = interpreterProxy->stackIntegerValue(3); x = interpreterProxy->stackIntegerValue(2); y = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); list = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } listLength = interpreterProxy->slotSizeOf((oopForPointer( list ) - BASE_HEADER_SIZE)); windowIndex = createWindowWidthheightoriginXyattrlength(w, h, x, y, list, listLength); if (windowIndex > 0) { _return_value = interpreterProxy->integerObjectOf(windowIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } else { interpreterProxy->primitiveFail(); return null; } } /* Return the origin position of the user area of the window in pixels from the topleft corner of the screen. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowPosition(void) { sqInt pos; sqInt windowIndex; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pos = ioPositionOfWindow(windowIndex); if (pos == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) pos) >> 16, pos & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } /* Set the origin position of the user area of the window in pixels from the topleft corner of the screen- return the position actually set by the OS/GUI/window manager. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowPositionSet(void) { sqInt pos; sqInt windowIndex; sqInt x; sqInt y; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } pos = ioPositionOfWindowSetxy(windowIndex, x, y); if (pos == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) pos) >> 16, pos & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } } /* Return the size of the user area of the window in pixels. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowSize(void) { sqInt size; sqInt windowIndex; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } size = ioSizeOfWindow(windowIndex); if (size == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) size) >> 16, size & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } } /* Set the size of the user area of the window in pixels - return what is actually set by the OS/GUI/window manager. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowSizeSet(void) { sqInt size; sqInt windowIndex; sqInt x; sqInt y; sqInt _return_value; windowIndex = interpreterProxy->stackIntegerValue(2); x = interpreterProxy->stackIntegerValue(1); y = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } size = ioSizeOfWindowSetxy(windowIndex, x, y); if (size == -1) { interpreterProxy->primitiveFail(); return null; } else { _return_value = interpreterProxy->makePointwithxValueyValue(((usqInt) size) >> 16, size & 65535); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } } /* Set the title bar label of the window. Fail if the windowIndex is invalid or the platform routine returns -1 to indicate failure */ EXPORT(sqInt) primitiveHostWindowTitle(void) { sqInt res; sqInt titleLength; sqInt id; char *titleString; id = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); titleString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } titleLength = interpreterProxy->slotSizeOf((oopForPointer( titleString ) - BASE_HEADER_SIZE)); res = ioSetTitleOfWindow(id, titleString, titleLength); if (res == -1) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* Host window analogue of DisplayScreen> primShowRectLeft:right:top:bottom: (Interpreter>primitiveShowDisplayRect) which takes the window index, bitmap details and the rectangle bounds. Fail if the windowIndex is invalid or the platform routine returns false to indicate failure */ EXPORT(sqInt) primitiveShowHostWindowRect(void) { sqInt ok; sqInt windowIndex; usqInt *dispBits; sqInt w; sqInt h; sqInt d; sqInt left; sqInt right; sqInt top; sqInt bottom; windowIndex = interpreterProxy->stackIntegerValue(8); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(7))); dispBits = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(7)))); w = interpreterProxy->stackIntegerValue(6); h = interpreterProxy->stackIntegerValue(5); d = interpreterProxy->stackIntegerValue(4); left = interpreterProxy->stackIntegerValue(3); right = interpreterProxy->stackIntegerValue(2); top = interpreterProxy->stackIntegerValue(1); bottom = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } ok = ioShowDisplayOnWindow(dispBits, w, h, d, left, right, top, bottom, windowIndex); if (!(ok)) { interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(9); return null; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } /* do any window related VM closing down work your platform requires. */ EXPORT(sqInt) shutdownModule(void) { return ioCloseAllWindows(); } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* HostWindowPlugin_exports[][3] = { {"HostWindowPlugin", "shutdownModule", (void*)shutdownModule}, {"HostWindowPlugin", "primitiveHostWindowSizeSet", (void*)primitiveHostWindowSizeSet}, {"HostWindowPlugin", "primitiveCreateHostWindow", (void*)primitiveCreateHostWindow}, {"HostWindowPlugin", "primitiveShowHostWindowRect", (void*)primitiveShowHostWindowRect}, {"HostWindowPlugin", "primitiveHostWindowPositionSet", (void*)primitiveHostWindowPositionSet}, {"HostWindowPlugin", "setInterpreter", (void*)setInterpreter}, {"HostWindowPlugin", "primitiveHostWindowPosition", (void*)primitiveHostWindowPosition}, {"HostWindowPlugin", "primitiveCloseHostWindow", (void*)primitiveCloseHostWindow}, {"HostWindowPlugin", "getModuleName", (void*)getModuleName}, {"HostWindowPlugin", "primitiveHostWindowTitle", (void*)primitiveHostWindowTitle}, {"HostWindowPlugin", "primitiveHostWindowSize", (void*)primitiveHostWindowSize}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/KedamaPlugin/KedamaPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:57 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static double degreesFromXy(double x, double y); static double degreesToRadians(double degrees); #pragma export on EXPORT(sqInt) drawTurtlesInArray(void); EXPORT(sqInt) getHeadingArrayInto(void); #pragma export off static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); EXPORT(sqInt) getScalarHeading(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt kedamaRandom2(sqInt range); static sqInt kedamaRandom(sqInt range); #pragma export on EXPORT(sqInt) kedamaSetRandomSeed(void); EXPORT(sqInt) makeMask(void); EXPORT(sqInt) makeMaskLog(void); EXPORT(sqInt) makeTurtlesMap(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primPixelAtXY(void); EXPORT(sqInt) primPixelAtXYPut(void); EXPORT(sqInt) primPixelsAtXY(void); EXPORT(sqInt) primScalarForward(void); EXPORT(sqInt) primSetPixelsAtXY(void); EXPORT(sqInt) primTurtlesForward(void); EXPORT(sqInt) primUpHill(void); EXPORT(sqInt) primitiveAddArrays(void); EXPORT(sqInt) primitiveAddScalar(void); EXPORT(sqInt) primitiveDivArrays(void); EXPORT(sqInt) primitiveDivScalar(void); EXPORT(sqInt) primitiveMulArrays(void); EXPORT(sqInt) primitiveMulScalar(void); EXPORT(sqInt) primitiveSubArrays(void); EXPORT(sqInt) primitiveSubScalar(void); #pragma export off static double radiansToDegrees(double radians); #pragma export on EXPORT(sqInt) randomIntoFloatArray(void); EXPORT(sqInt) randomIntoIntegerArray(void); EXPORT(sqInt) randomRange(void); EXPORT(sqInt) scalarGetAngleTo(void); EXPORT(sqInt) scalarGetDistanceTo(void); #pragma export off static sqInt scalarXAtxArrayheadingArrayvaluedestWidthleftEdgeModerightEdgeMode(sqInt index, float* xArray, float* headingArray, double val, double destWidth, sqInt leftEdgeMode, sqInt rightEdgeMode); static sqInt scalarYAtyArrayheadingArrayvaluedestHeighttopEdgeModebottomEdgeMode(sqInt index, float* yArray, float* headingArray, double val, double destHeight, sqInt topEdgeMode, sqInt bottomEdgeMode); #pragma export on EXPORT(sqInt) setHeadingArrayFrom(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) setScalarHeading(void); EXPORT(sqInt) shutdownModule(void); EXPORT(sqInt) turtleScalarSetX(void); EXPORT(sqInt) turtleScalarSetY(void); EXPORT(sqInt) turtlesSetX(void); EXPORT(sqInt) turtlesSetY(void); EXPORT(sqInt) vectorGetAngleTo(void); EXPORT(sqInt) vectorGetDistanceTo(void); EXPORT(sqInt) zoomBitmap(void); #pragma export off /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static unsigned int kedamaRandomSeed; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "KedamaPlugin 23 January 2011 (i)" #else "KedamaPlugin 23 January 2011 (e)" #endif ; static unsigned int randA; static unsigned int randM; static unsigned int randQ; static unsigned int randR; static double degreesFromXy(double x, double y) { double tanVal; double theta; if (x == 0.0) { if (y >= 0.0) { return 90.0; } else { return 270.0; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { return theta / 0.0174532925199433; } else { return 360.0 + (theta / 0.0174532925199433); } } else { return 180.0 + (theta / 0.0174532925199433); } } return 0.0; } static double degreesToRadians(double degrees) { double deg; double headingRadians; int q; deg = 90.0 - degrees; q = deg / 360.0; if (deg < 0.0) { q -= 1; } headingRadians = (deg - (q * 360.0)) * 0.0174532925199433; return headingRadians; } EXPORT(sqInt) drawTurtlesInArray(void) { sqInt bitsIndex; unsigned int *colorArray; sqInt colorOop; unsigned int *destBits; sqInt destHeight; sqInt destOop; sqInt destWidth; sqInt i; sqInt size; sqInt visible; unsigned char *visibleArray; sqInt visibleOop; sqInt x; float *xArray; sqInt xOop; sqInt y; float *yArray; sqInt yOop; visibleOop = interpreterProxy->stackValue(0); colorOop = interpreterProxy->stackValue(1); yOop = interpreterProxy->stackValue(2); xOop = interpreterProxy->stackValue(3); destHeight = interpreterProxy->stackIntegerValue(4); destWidth = interpreterProxy->stackIntegerValue(5); destOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(destOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(colorOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isBytes(visibleOop))) { interpreterProxy->primitiveFail(); return null; } if ((destHeight * destWidth) != (interpreterProxy->slotSizeOf(destOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(colorOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(visibleOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); colorArray = interpreterProxy->firstIndexableField(colorOop); visibleArray = interpreterProxy->firstIndexableField(visibleOop); destBits = interpreterProxy->firstIndexableField(destOop); for (i = 0; i <= (size - 1); i += 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; visible = visibleArray[i]; if ((visible != 0) && (((x >= 0) && (y >= 0)) && ((x < destWidth) && (y < destHeight)))) { bitsIndex = (y * destWidth) + x; destBits[bitsIndex] = (colorArray[i]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) getHeadingArrayInto(void) { double heading; float *headingArray; sqInt headingOop; sqInt i; float *resultArray; sqInt resultOop; sqInt size; resultOop = interpreterProxy->stackValue(0); headingOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(headingOop); if ((interpreterProxy->slotSizeOf(resultOop)) != size) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); resultArray = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (size - 1); i += 1) { heading = headingArray[i]; heading = heading / 0.0174532925199433; heading = 90.0 - heading; if (!(heading > 0.0)) { heading += 360.0; } resultArray[i] = heading; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } EXPORT(sqInt) getScalarHeading(void) { double heading; float *headingArray; sqInt headingOop; sqInt index; double deg; double degrees; headingOop = interpreterProxy->stackValue(0); index = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) < index) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); heading = headingArray[index - 1]; /* begin radiansToDegrees: */ degrees = heading / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } heading = deg; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); interpreterProxy->pushFloat(heading); } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { kedamaRandomSeed = 17; /* magic constant = 16807 */ randA = 16807; /* magic constant = 2147483647 */ randM = 2147483647U; randQ = randM / randA; randR = randM % randA; } static sqInt kedamaRandom2(sqInt range) { sqInt hi; sqInt lo; sqInt r; sqInt v; sqInt val; if (range < 0) { r = 0 - range; } else { r = range; } hi = kedamaRandomSeed / randQ; lo = kedamaRandomSeed % randQ; kedamaRandomSeed = (randA * lo) - (randR * hi); v = kedamaRandomSeed & 65535; val = ((usqInt) (v * (r + 1))) >> 16; if (range < 0) { return 0 - val; } else { return val; } } static sqInt kedamaRandom(sqInt range) { sqInt r; sqInt val; if (range < 0) { r = 0 - range; } else { r = range; } kedamaRandomSeed = ((kedamaRandomSeed * 1309) + 13849) & 65535; val = ((usqInt) (kedamaRandomSeed * (r + 1))) >> 16; if (range < 0) { return 0 - val; } else { return val; } } EXPORT(sqInt) kedamaSetRandomSeed(void) { sqInt seed; seed = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } kedamaRandomSeed = seed & 65536; interpreterProxy->pop(1); } EXPORT(sqInt) makeMask(void) { unsigned int alpha; unsigned int* dOrigin; sqInt data; sqInt dataBits; sqInt dataSize; unsigned int highMask; sqInt i; unsigned int* mOrigin; sqInt maskBits; sqInt maskSize; unsigned int pixel; sqInt shiftAmount; shiftAmount = interpreterProxy->stackIntegerValue(0); pixel = interpreterProxy->stackIntegerValue(1); maskBits = interpreterProxy->stackValue(2); dataBits = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } dataSize = interpreterProxy->slotSizeOf(dataBits); maskSize = interpreterProxy->slotSizeOf(maskBits); if (!(dataSize == maskSize)) { interpreterProxy->primitiveFail(); return null; } if (shiftAmount < -32) { interpreterProxy->primitiveFail(); return null; } if (shiftAmount > 8) { interpreterProxy->primitiveFail(); return null; } dOrigin = interpreterProxy->firstIndexableField(dataBits); mOrigin = interpreterProxy->firstIndexableField(maskBits); highMask = 4278190080U; for (i = 0; i <= (dataSize - 1); i += 1) { data = dOrigin[i]; alpha = ((shiftAmount < 0) ? ((usqInt) data >> -shiftAmount) : ((usqInt) data << shiftAmount)); if (alpha > 255) { alpha = 255; } if (alpha < 0) { alpha = 0; } mOrigin[i] = (((alpha << 24) & highMask) | pixel); } interpreterProxy->pop(4); } EXPORT(sqInt) makeMaskLog(void) { unsigned int alpha; unsigned int* dOrigin; sqInt data; sqInt dataBits; sqInt dataSize; unsigned int highMask; sqInt i; unsigned int* mOrigin; sqInt maskBits; sqInt maskSize; unsigned int max; unsigned int* maxFirst; double maxLog; sqInt maxOop; unsigned int pixel; maxOop = interpreterProxy->stackValue(0); pixel = interpreterProxy->stackIntegerValue(1); maskBits = interpreterProxy->stackValue(2); dataBits = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } maxFirst = interpreterProxy->firstIndexableField(maxOop); max = maxFirst[0]; if (interpreterProxy->failed()) { return null; } maxLog = log(max); dataSize = interpreterProxy->slotSizeOf(dataBits); maskSize = interpreterProxy->slotSizeOf(maskBits); if (!(dataSize == maskSize)) { interpreterProxy->primitiveFail(); return null; } dOrigin = interpreterProxy->firstIndexableField(dataBits); mOrigin = interpreterProxy->firstIndexableField(maskBits); highMask = 4278190080U; for (i = 0; i <= (dataSize - 1); i += 1) { data = dOrigin[i]; if (data == 0) { alpha = 0; } else { alpha = ((sqInt)((255.0 / maxLog) * (log(data)))); } if (alpha > 255) { alpha = 255; } mOrigin[i] = (((alpha << 24) & highMask) | pixel); } interpreterProxy->pop(4); } EXPORT(sqInt) makeTurtlesMap(void) { sqInt height; sqInt index; unsigned int *map; sqInt mapIndex; sqInt mapOop; sqInt size; unsigned int *whoArray; sqInt whoOop; sqInt width; sqInt x; float *xArray; sqInt xOop; sqInt y; float *yArray; sqInt yOop; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); yOop = interpreterProxy->stackValue(2); xOop = interpreterProxy->stackValue(3); whoOop = interpreterProxy->stackValue(4); mapOop = interpreterProxy->stackValue(5); if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(whoOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(mapOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(whoOop); if ((interpreterProxy->slotSizeOf(xOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(mapOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); whoArray = interpreterProxy->firstIndexableField(whoOop); map = interpreterProxy->firstIndexableField(mapOop); for (index = 0; index <= ((height * width) - 1); index += 1) { map[index] = 0; } for (index = 0; index <= (size - 1); index += 1) { x = xArray[index]; y = yArray[index]; mapIndex = (width * y) + x; if ((mapIndex >= 0) && (mapIndex < (height * width))) { map[mapIndex] = (whoArray[index]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primPixelAtXY(void) { unsigned int *bits; sqInt bitsOop; sqInt height; sqInt index; sqInt ret; sqInt width; sqInt x; double xPos; sqInt y; double yPos; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); yPos = interpreterProxy->stackFloatValue(2); xPos = interpreterProxy->stackFloatValue(3); bitsOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } x = xPos; y = yPos; bits = interpreterProxy->firstIndexableField(bitsOop); if ((((x >= 0) && (x < width)) && (y >= 0)) && (y < height)) { index = (y * width) + x; ret = bits[index]; } else { ret = 0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->pushInteger(ret); } EXPORT(sqInt) primPixelAtXYPut(void) { unsigned int *bits; sqInt bitsOop; sqInt height; sqInt index; sqInt v; sqInt value; sqInt width; sqInt x; double xPos; sqInt y; double yPos; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); value = interpreterProxy->stackIntegerValue(2); yPos = interpreterProxy->stackFloatValue(3); xPos = interpreterProxy->stackFloatValue(4); bitsOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } x = xPos; y = yPos; v = value; if (v > 1073741823) { v = 1073741823; } if (v < 0) { v = 0; } bits = interpreterProxy->firstIndexableField(bitsOop); if ((((x >= 0) && (x < width)) && (y >= 0)) && (y < height)) { index = (y * width) + x; bits[index] = v; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) primPixelsAtXY(void) { unsigned int *bits; sqInt bitsHeight; sqInt bitsIndex; sqInt bitsOop; sqInt bitsWidth; unsigned int *destWords; sqInt destWordsOop; sqInt i; sqInt size; sqInt x; float *xArray; sqInt xArrayOop; sqInt y; float *yArray; sqInt yArrayOop; destWordsOop = interpreterProxy->stackValue(0); bitsHeight = interpreterProxy->stackIntegerValue(1); bitsWidth = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); yArrayOop = interpreterProxy->stackValue(4); xArrayOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(destWordsOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((bitsHeight * bitsWidth) != (interpreterProxy->slotSizeOf(bitsOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xArrayOop); if ((interpreterProxy->slotSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(destWordsOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); destWords = interpreterProxy->firstIndexableField(destWordsOop); bits = interpreterProxy->firstIndexableField(bitsOop); for (i = 0; i <= (size - 1); i += 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; if (((x >= 0) && (y >= 0)) && ((x < bitsWidth) && (y < bitsHeight))) { bitsIndex = (y * bitsWidth) + x; destWords[i] = (bits[bitsIndex]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) primScalarForward(void) { sqInt bottomEdgeMode; double destHeight; double destWidth; double dist; float *headingArray; sqInt headingOop; sqInt i; sqInt index; sqInt leftEdgeMode; double newX; double newY; sqInt rightEdgeMode; sqInt size; sqInt topEdgeMode; double val; float *xArray; sqInt xOop; float *yArray; sqInt yOop; double headingRadians; double newX1; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); rightEdgeMode = interpreterProxy->stackIntegerValue(2); leftEdgeMode = interpreterProxy->stackIntegerValue(3); destHeight = interpreterProxy->stackFloatValue(4); destWidth = interpreterProxy->stackFloatValue(5); val = interpreterProxy->stackFloatValue(6); headingOop = interpreterProxy->stackValue(7); yOop = interpreterProxy->stackValue(8); xOop = interpreterProxy->stackValue(9); index = interpreterProxy->stackIntegerValue(10); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); dist = val; i = index - 1; newX = (xArray[i]) + (dist * (cos(headingArray[i]))); newY = (yArray[i]) - (dist * (sin(headingArray[i]))); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(11); } EXPORT(sqInt) primSetPixelsAtXY(void) { unsigned int *bits; sqInt bitsHeight; sqInt bitsIndex; sqInt bitsOop; sqInt bitsWidth; sqInt i; unsigned int intValue; sqInt isValueInt; sqInt size; unsigned int value; sqInt valueOop; unsigned int *wordsValue; sqInt x; float *xArray; sqInt xArrayOop; sqInt y; float *yArray; sqInt yArrayOop; valueOop = interpreterProxy->stackValue(0); bitsHeight = interpreterProxy->stackIntegerValue(1); bitsWidth = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); yArrayOop = interpreterProxy->stackValue(4); xArrayOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((bitsHeight * bitsWidth) != (interpreterProxy->slotSizeOf(bitsOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xArrayOop); if ((interpreterProxy->slotSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } isValueInt = (valueOop & 1); if (isValueInt) { intValue = (valueOop >> 1); } if (!(isValueInt)) { if (!(interpreterProxy->isMemberOf(valueOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(valueOop)) != size) { interpreterProxy->primitiveFail(); return null; } } xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); if (!(isValueInt)) { wordsValue = interpreterProxy->firstIndexableField(valueOop); } bits = interpreterProxy->firstIndexableField(bitsOop); if (isValueInt) { value = intValue; } for (i = 0; i <= (size - 1); i += 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; if (((x >= 0) && (y >= 0)) && ((x < bitsWidth) && (y < bitsHeight))) { bitsIndex = (y * bitsWidth) + x; if (!(isValueInt)) { value = wordsValue[i]; } bits[bitsIndex] = value; } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) primTurtlesForward(void) { sqInt bottomEdgeMode; double destHeight; double destWidth; double dist; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; sqInt leftEdgeMode; double newX; double newY; sqInt rightEdgeMode; sqInt size; sqInt topEdgeMode; double val; float *valArray; sqInt valOop; float *xArray; sqInt xOop; float *yArray; sqInt yOop; double headingRadians; double newX1; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); rightEdgeMode = interpreterProxy->stackIntegerValue(2); leftEdgeMode = interpreterProxy->stackIntegerValue(3); destHeight = interpreterProxy->stackFloatValue(4); destWidth = interpreterProxy->stackFloatValue(5); valOop = interpreterProxy->stackValue(6); headingOop = interpreterProxy->stackValue(7); yOop = interpreterProxy->stackValue(8); xOop = interpreterProxy->stackValue(9); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { valArray = interpreterProxy->firstIndexableField(valOop); } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if (isValVector) { dist = valArray[i]; } else { dist = val; } newX = (xArray[i]) + (dist * (cos(headingArray[i]))); newY = (yArray[i]) - (dist * (sin(headingArray[i]))); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(10); } EXPORT(sqInt) primUpHill(void) { unsigned int *bits; sqInt bitsOop; sqInt endX; sqInt endY; sqInt height; sqInt maxVal; sqInt maxValX; sqInt maxValY; double ret; sqInt rowOffset; sqInt sniffRange; sqInt startX; sqInt startY; double tH; double tX; double tY; sqInt thisVal; sqInt turtleX; sqInt turtleY; sqInt width; sqInt x; sqInt y; double deg; double degrees; sniffRange = interpreterProxy->stackIntegerValue(0); height = interpreterProxy->stackIntegerValue(1); width = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); tH = interpreterProxy->stackFloatValue(4); tY = interpreterProxy->stackFloatValue(5); tX = interpreterProxy->stackFloatValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } bits = interpreterProxy->firstIndexableField(bitsOop); turtleX = tX; turtleY = tY; turtleX = ((turtleX < 0) ? 0 : turtleX); turtleY = ((turtleY < 0) ? 0 : turtleY); turtleX = ((turtleX < (width - 1)) ? turtleX : (width - 1)); turtleY = ((turtleY < (height - 1)) ? turtleY : (height - 1)); startX = (((turtleX - sniffRange) < 0) ? 0 : (turtleX - sniffRange)); endX = (((turtleX + sniffRange) < (width - 1)) ? (turtleX + sniffRange) : (width - 1)); startY = (((turtleY - sniffRange) < 0) ? 0 : (turtleY - sniffRange)); endY = (((turtleY + sniffRange) < (height - 1)) ? (turtleY + sniffRange) : (height - 1)); maxVal = bits[(turtleY * width) + turtleX]; maxValX = -1; for (y = startY; y <= endY; y += 1) { rowOffset = y * width; for (x = startX; x <= endX; x += 1) { thisVal = bits[rowOffset + x]; if (thisVal > maxVal) { maxValX = x; maxValY = y; maxVal = thisVal; } } } if (-1 == maxValX) { /* begin radiansToDegrees: */ degrees = tH / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } ret = deg; } else { ret = (degreesFromXy(((double) (maxValX - turtleX)), ((double) (maxValY - turtleY)))) + 90.0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(8); interpreterProxy->pushFloat(ret); } EXPORT(sqInt) primitiveAddArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) + (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) + (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveAddScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) + intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) + floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveDivArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) / (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) / (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveDivScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) / intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) / floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveMulArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) * (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) * (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveMulScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) * intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) * floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveSubArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) - (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) - (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveSubScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) - intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) - floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } static double radiansToDegrees(double radians) { double deg; double degrees; degrees = radians / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } return deg; } EXPORT(sqInt) randomIntoFloatArray(void) { double factor; float *floatArray; sqInt floatArrayOop; sqInt from; sqInt index; sqInt range; sqInt size; sqInt to; factor = interpreterProxy->stackFloatValue(0); floatArrayOop = interpreterProxy->stackValue(1); to = interpreterProxy->stackIntegerValue(2); from = interpreterProxy->stackIntegerValue(3); range = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(floatArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(floatArrayOop); if (!((size >= to) && ((from >= 1) && (to >= from)))) { interpreterProxy->primitiveFail(); return null; } floatArray = interpreterProxy->firstIndexableField(floatArrayOop); if (interpreterProxy->failed()) { return null; } for (index = from; index <= to; index += 1) { floatArray[index - 1] = ((((double) (kedamaRandom2(range)))) * factor); } interpreterProxy->pop(5); } EXPORT(sqInt) randomIntoIntegerArray(void) { double factor; sqInt from; sqInt index; unsigned int *integerArray; sqInt integerArrayOop; sqInt range; sqInt size; sqInt to; factor = interpreterProxy->stackFloatValue(0); integerArrayOop = interpreterProxy->stackValue(1); to = interpreterProxy->stackIntegerValue(2); from = interpreterProxy->stackIntegerValue(3); range = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(integerArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(integerArrayOop); if (!((size >= to) && ((from >= 1) && (to >= from)))) { interpreterProxy->primitiveFail(); return null; } integerArray = interpreterProxy->firstIndexableField(integerArrayOop); if (interpreterProxy->failed()) { return null; } for (index = from; index <= to; index += 1) { integerArray[index - 1] = (((int) ((((double) (kedamaRandom2(range)))) * factor))); } interpreterProxy->pop(5); } EXPORT(sqInt) randomRange(void) { sqInt range; sqInt ret; sqInt hi; sqInt lo; sqInt r; sqInt v; sqInt val; range = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin kedamaRandom2: */ if (range < 0) { r = 0 - range; } else { r = range; } hi = kedamaRandomSeed / randQ; lo = kedamaRandomSeed % randQ; kedamaRandomSeed = (randA * lo) - (randR * hi); v = kedamaRandomSeed & 65535; val = ((usqInt) (v * (r + 1))) >> 16; if (range < 0) { ret = 0 - val; goto l1; } else { ret = val; goto l1; } l1: /* end kedamaRandom2: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); interpreterProxy->pushInteger(ret); } EXPORT(sqInt) scalarGetAngleTo(void) { double fromX; double fromY; double r; double toX; double toY; double x; double y; double tanVal; double theta; fromY = interpreterProxy->stackFloatValue(0); fromX = interpreterProxy->stackFloatValue(1); toY = interpreterProxy->stackFloatValue(2); toX = interpreterProxy->stackFloatValue(3); if (interpreterProxy->failed()) { return null; } x = toX - fromX; y = toY - fromY; /* begin degreesFromX:y: */ if (x == 0.0) { if (y >= 0.0) { r = 90.0; goto l1; } else { r = 270.0; goto l1; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { r = theta / 0.0174532925199433; goto l1; } else { r = 360.0 + (theta / 0.0174532925199433); goto l1; } } else { r = 180.0 + (theta / 0.0174532925199433); goto l1; } } r = 0.0; l1: /* end degreesFromX:y: */; r += 90.0; if (r > 360.0) { r -= 360.0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); interpreterProxy->pushFloat(r); } EXPORT(sqInt) scalarGetDistanceTo(void) { double fromX; double fromY; double r; double toX; double toY; double x; double y; fromY = interpreterProxy->stackFloatValue(0); fromX = interpreterProxy->stackFloatValue(1); toY = interpreterProxy->stackFloatValue(2); toX = interpreterProxy->stackFloatValue(3); if (interpreterProxy->failed()) { return null; } x = fromX - toX; y = fromY - toY; r = sqrt((x * x) + (y * y)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); interpreterProxy->pushFloat(r); } static sqInt scalarXAtxArrayheadingArrayvaluedestWidthleftEdgeModerightEdgeMode(sqInt index, float* xArray, float* headingArray, double val, double destWidth, sqInt leftEdgeMode, sqInt rightEdgeMode) { double headingRadians; double newX; newX = val; if (newX < 0.0) { if (leftEdgeMode == 1) { newX += destWidth; } if (leftEdgeMode == 2) { newX = 0.0; } if (leftEdgeMode == 3) { /* bounce */ newX = 0.0 - newX; headingRadians = headingArray[index]; if (headingRadians < 3.141592653589793) { headingArray[index] = (3.141592653589793 - headingRadians); } else { headingArray[index] = (9.42477796076938 - headingRadians); } } } if (newX >= destWidth) { if (rightEdgeMode == 1) { newX -= destWidth; } if (rightEdgeMode == 2) { newX = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX = (destWidth - 1.0e-6) - (newX - destWidth); headingRadians = headingArray[index]; if (headingRadians < 3.141592653589793) { headingArray[index] = (3.141592653589793 - headingRadians); } else { headingArray[index] = (9.42477796076938 - headingRadians); } } } xArray[index] = newX; } static sqInt scalarYAtyArrayheadingArrayvaluedestHeighttopEdgeModebottomEdgeMode(sqInt index, float* yArray, float* headingArray, double val, double destHeight, sqInt topEdgeMode, sqInt bottomEdgeMode) { double newY; newY = val; if (newY < 0.0) { if (topEdgeMode == 1) { newY += destHeight; } if (topEdgeMode == 2) { newY = 0.0; } if (topEdgeMode == 3) { /* bounce */ newY = 0.0 - newY; headingArray[index] = (6.283185307179586 - (headingArray[index])); } } if (newY >= destHeight) { if (bottomEdgeMode == 1) { newY -= destHeight; } if (bottomEdgeMode == 2) { newY = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY = (destHeight - 1.0e-6) - (newY - destHeight); headingArray[index] = (6.283185307179586 - (headingArray[index])); } } yArray[index] = newY; } EXPORT(sqInt) setHeadingArrayFrom(void) { double heading; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; float *resultArray; sqInt resultOop; sqInt size; double deg; double headingRadians; int q; double deg1; double headingRadians1; int q1; resultOop = interpreterProxy->stackValue(0); headingOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(headingOop); if (interpreterProxy->isFloatObject(resultOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(resultOop)) { if ((interpreterProxy->slotSizeOf(resultOop)) != size) { interpreterProxy->primitiveFail(); return null; } isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { resultArray = interpreterProxy->firstIndexableField(resultOop); } else { heading = interpreterProxy->floatValueOf(resultOop); /* begin degreesToRadians: */ deg = 90.0 - heading; q = deg / 360.0; if (deg < 0.0) { q -= 1; } headingRadians = (deg - (q * 360.0)) * 0.0174532925199433; heading = headingRadians; } for (i = 0; i <= (size - 1); i += 1) { if (isValVector) { heading = resultArray[i]; /* begin degreesToRadians: */ deg1 = 90.0 - heading; q1 = deg1 / 360.0; if (deg1 < 0.0) { q1 -= 1; } headingRadians1 = (deg1 - (q1 * 360.0)) * 0.0174532925199433; heading = headingRadians1; } headingArray[i] = heading; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) setScalarHeading(void) { double heading; float *headingArray; sqInt headingOop; sqInt index; heading = interpreterProxy->stackFloatValue(0); headingOop = interpreterProxy->stackValue(1); index = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) < index) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); headingArray[index - 1] = (degreesToRadians(heading)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); } EXPORT(sqInt) shutdownModule(void) { return 1; } EXPORT(sqInt) turtleScalarSetX(void) { double destWidth; float *headingArray; sqInt headingOop; sqInt leftEdgeMode; sqInt rightEdgeMode; sqInt size; double val; float *xArray; sqInt xIndex; sqInt xOop; double headingRadians; double newX; rightEdgeMode = interpreterProxy->stackIntegerValue(0); leftEdgeMode = interpreterProxy->stackIntegerValue(1); destWidth = interpreterProxy->stackFloatValue(2); val = interpreterProxy->stackFloatValue(3); headingOop = interpreterProxy->stackValue(4); xIndex = interpreterProxy->stackIntegerValue(5); xOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); headingArray = interpreterProxy->firstIndexableField(headingOop); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX = val; if (newX < 0.0) { if (leftEdgeMode == 1) { newX += destWidth; } if (leftEdgeMode == 2) { newX = 0.0; } if (leftEdgeMode == 3) { newX = 0.0 - newX; headingRadians = headingArray[xIndex - 1]; if (headingRadians < 3.141592653589793) { headingArray[xIndex - 1] = (3.141592653589793 - headingRadians); } else { headingArray[xIndex - 1] = (9.42477796076938 - headingRadians); } } } if (newX >= destWidth) { if (rightEdgeMode == 1) { newX -= destWidth; } if (rightEdgeMode == 2) { newX = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX = (destWidth - 1.0e-6) - (newX - destWidth); headingRadians = headingArray[xIndex - 1]; if (headingRadians < 3.141592653589793) { headingArray[xIndex - 1] = (3.141592653589793 - headingRadians); } else { headingArray[xIndex - 1] = (9.42477796076938 - headingRadians); } } } xArray[xIndex - 1] = newX; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) turtleScalarSetY(void) { sqInt bottomEdgeMode; double destHeight; float *headingArray; sqInt headingOop; sqInt size; sqInt topEdgeMode; double val; float *yArray; sqInt yIndex; sqInt yOop; double newY; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); destHeight = interpreterProxy->stackFloatValue(2); val = interpreterProxy->stackFloatValue(3); headingOop = interpreterProxy->stackValue(4); yIndex = interpreterProxy->stackIntegerValue(5); yOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(yOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY = val; if (newY < 0.0) { if (topEdgeMode == 1) { newY += destHeight; } if (topEdgeMode == 2) { newY = 0.0; } if (topEdgeMode == 3) { newY = 0.0 - newY; headingArray[yIndex - 1] = (6.283185307179586 - (headingArray[yIndex - 1])); } } if (newY >= destHeight) { if (bottomEdgeMode == 1) { newY -= destHeight; } if (bottomEdgeMode == 2) { newY = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY = (destHeight - 1.0e-6) - (newY - destHeight); headingArray[yIndex - 1] = (6.283185307179586 - (headingArray[yIndex - 1])); } } yArray[yIndex - 1] = newY; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) turtlesSetX(void) { double destWidth; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; sqInt leftEdgeMode; double newX; sqInt rightEdgeMode; sqInt size; double val; float *valArray; sqInt valOop; float *xArray; sqInt xOop; double headingRadians; double newX1; rightEdgeMode = interpreterProxy->stackIntegerValue(0); leftEdgeMode = interpreterProxy->stackIntegerValue(1); destWidth = interpreterProxy->stackFloatValue(2); valOop = interpreterProxy->stackValue(3); headingOop = interpreterProxy->stackValue(4); xOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } xArray = interpreterProxy->firstIndexableField(xOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { valArray = interpreterProxy->firstIndexableField(valOop); } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if (isValVector) { newX = valArray[i]; } else { newX = val; } /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) turtlesSetY(void) { sqInt bottomEdgeMode; double destHeight; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; double newY; sqInt size; sqInt topEdgeMode; double val; float *valArray; sqInt valOop; float *yArray; sqInt yOop; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); destHeight = interpreterProxy->stackFloatValue(2); valOop = interpreterProxy->stackValue(3); headingOop = interpreterProxy->stackValue(4); yOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(yOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { valArray = interpreterProxy->firstIndexableField(valOop); } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if (isValVector) { newY = valArray[i]; } else { newY = val; } /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) vectorGetAngleTo(void) { sqInt index; sqInt isVector; float *pX; sqInt pXOop; float *pY; sqInt pYOop; double ppx; double ppy; double r; float *result; sqInt resultOop; sqInt size; double x; float *xArray; sqInt xArrayOop; double y; float *yArray; sqInt yArrayOop; double tanVal; double theta; resultOop = interpreterProxy->stackValue(0); yArrayOop = interpreterProxy->stackValue(1); xArrayOop = interpreterProxy->stackValue(2); pYOop = interpreterProxy->stackValue(3); pXOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(resultOop); if (size < 0) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(xArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(pXOop)) { if (interpreterProxy->isFloatObject(pYOop)) { isVector = 0; } else { interpreterProxy->primitiveFail(); return null; } } else { if (interpreterProxy->isFloatObject(pYOop)) { interpreterProxy->primitiveFail(); return null; } else { isVector = 1; } } if (isVector) { if ((interpreterProxy->stSizeOf(pXOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(pYOop)) != size) { interpreterProxy->primitiveFail(); return null; } } result = interpreterProxy->firstIndexableField(resultOop); xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); if (isVector) { pX = interpreterProxy->firstIndexableField(pXOop); pY = interpreterProxy->firstIndexableField(pYOop); } if (!(isVector)) { ppx = interpreterProxy->floatValueOf(pXOop); ppy = interpreterProxy->floatValueOf(pYOop); } for (index = 0; index <= (size - 1); index += 1) { if (isVector) { ppx = pX[index]; ppy = pY[index]; } x = ppx - (xArray[index]); y = ppy - (yArray[index]); /* begin degreesFromX:y: */ if (x == 0.0) { if (y >= 0.0) { r = 90.0; goto l1; } else { r = 270.0; goto l1; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { r = theta / 0.0174532925199433; goto l1; } else { r = 360.0 + (theta / 0.0174532925199433); goto l1; } } else { r = 180.0 + (theta / 0.0174532925199433); goto l1; } } r = 0.0; l1: /* end degreesFromX:y: */; r += 90.0; if (r > 360.0) { r -= 360.0; } result[index] = r; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(resultOop); } EXPORT(sqInt) vectorGetDistanceTo(void) { sqInt index; sqInt isVector; float *pX; sqInt pXOop; float *pY; sqInt pYOop; double ppx; double ppy; float *result; sqInt resultOop; sqInt size; double x; float *xArray; sqInt xArrayOop; double y; float *yArray; sqInt yArrayOop; resultOop = interpreterProxy->stackValue(0); yArrayOop = interpreterProxy->stackValue(1); xArrayOop = interpreterProxy->stackValue(2); pYOop = interpreterProxy->stackValue(3); pXOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(resultOop); if (size < 0) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(xArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(pXOop)) { if (interpreterProxy->isFloatObject(pYOop)) { isVector = 0; } else { interpreterProxy->primitiveFail(); return null; } } else { if (interpreterProxy->isFloatObject(pYOop)) { interpreterProxy->primitiveFail(); return null; } else { isVector = 1; } } if (isVector) { if ((interpreterProxy->stSizeOf(pXOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(pYOop)) != size) { interpreterProxy->primitiveFail(); return null; } } result = interpreterProxy->firstIndexableField(resultOop); xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); if (isVector) { pX = interpreterProxy->firstIndexableField(pXOop); pY = interpreterProxy->firstIndexableField(pYOop); } if (!(isVector)) { ppx = interpreterProxy->floatValueOf(pXOop); ppy = interpreterProxy->floatValueOf(pYOop); } for (index = 0; index <= (size - 1); index += 1) { if (isVector) { ppx = pX[index]; ppy = pY[index]; } x = ppx - (xArray[index]); y = ppy - (yArray[index]); result[index] = (sqrt((x * x) + (y * y))); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(resultOop); } EXPORT(sqInt) zoomBitmap(void) { sqInt bit; unsigned int* dOrigin; sqInt dst; sqInt dstIndex; sqInt dstSize; sqInt dummy; sqInt sHeight; unsigned int* sOrigin; sqInt sWidth; sqInt src; sqInt srcIndex; sqInt srcOrigin; sqInt srcSize; sqInt sx; sqInt sy; sqInt xFactor; sqInt y; sqInt yFactor; yFactor = interpreterProxy->stackIntegerValue(0); xFactor = interpreterProxy->stackIntegerValue(1); sHeight = interpreterProxy->stackIntegerValue(2); sWidth = interpreterProxy->stackIntegerValue(3); dst = interpreterProxy->stackValue(4); src = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } srcSize = interpreterProxy->slotSizeOf(src); dstSize = interpreterProxy->slotSizeOf(dst); if (!((sWidth * sHeight) == srcSize)) { interpreterProxy->primitiveFail(); return null; } if (!(((srcSize * xFactor) * yFactor) == dstSize)) { interpreterProxy->primitiveFail(); return null; } sOrigin = interpreterProxy->firstIndexableField(src); dOrigin = interpreterProxy->firstIndexableField(dst); srcIndex = 0; srcOrigin = 0; dstIndex = 0; for (sy = 0; sy <= (sHeight - 1); sy += 1) { for (y = 0; y <= (yFactor - 1); y += 1) { for (sx = 0; sx <= (sWidth - 1); sx += 1) { bit = sOrigin[srcIndex]; srcIndex += 1; for (dummy = 0; dummy <= (xFactor - 1); dummy += 1) { dOrigin[dstIndex] = bit; dstIndex += 1; } } srcIndex = srcOrigin; } srcOrigin += sWidth; srcIndex = srcOrigin; } interpreterProxy->pop(6); } #ifdef SQUEAK_BUILTIN_PLUGIN void* KedamaPlugin_exports[][3] = { {"KedamaPlugin", "makeMaskLog", (void*)makeMaskLog}, {"KedamaPlugin", "vectorGetDistanceTo", (void*)vectorGetDistanceTo}, {"KedamaPlugin", "getScalarHeading", (void*)getScalarHeading}, {"KedamaPlugin", "shutdownModule", (void*)shutdownModule}, {"KedamaPlugin", "primitiveAddScalar", (void*)primitiveAddScalar}, {"KedamaPlugin", "primSetPixelsAtXY", (void*)primSetPixelsAtXY}, {"KedamaPlugin", "turtleScalarSetX", (void*)turtleScalarSetX}, {"KedamaPlugin", "primPixelAtXY", (void*)primPixelAtXY}, {"KedamaPlugin", "primUpHill", (void*)primUpHill}, {"KedamaPlugin", "primScalarForward", (void*)primScalarForward}, {"KedamaPlugin", "primitiveDivArrays", (void*)primitiveDivArrays}, {"KedamaPlugin", "getModuleName", (void*)getModuleName}, {"KedamaPlugin", "primitiveSubArrays", (void*)primitiveSubArrays}, {"KedamaPlugin", "scalarGetAngleTo", (void*)scalarGetAngleTo}, {"KedamaPlugin", "randomRange", (void*)randomRange}, {"KedamaPlugin", "setInterpreter", (void*)setInterpreter}, {"KedamaPlugin", "kedamaSetRandomSeed", (void*)kedamaSetRandomSeed}, {"KedamaPlugin", "drawTurtlesInArray", (void*)drawTurtlesInArray}, {"KedamaPlugin", "turtleScalarSetY", (void*)turtleScalarSetY}, {"KedamaPlugin", "randomIntoIntegerArray", (void*)randomIntoIntegerArray}, {"KedamaPlugin", "getHeadingArrayInto", (void*)getHeadingArrayInto}, {"KedamaPlugin", "makeTurtlesMap", (void*)makeTurtlesMap}, {"KedamaPlugin", "setHeadingArrayFrom", (void*)setHeadingArrayFrom}, {"KedamaPlugin", "turtlesSetX", (void*)turtlesSetX}, {"KedamaPlugin", "setScalarHeading", (void*)setScalarHeading}, {"KedamaPlugin", "makeMask", (void*)makeMask}, {"KedamaPlugin", "primitiveDivScalar", (void*)primitiveDivScalar}, {"KedamaPlugin", "primitiveSubScalar", (void*)primitiveSubScalar}, {"KedamaPlugin", "primPixelsAtXY", (void*)primPixelsAtXY}, {"KedamaPlugin", "vectorGetAngleTo", (void*)vectorGetAngleTo}, {"KedamaPlugin", "primitiveMulArrays", (void*)primitiveMulArrays}, {"KedamaPlugin", "primPixelAtXYPut", (void*)primPixelAtXYPut}, {"KedamaPlugin", "zoomBitmap", (void*)zoomBitmap}, {"KedamaPlugin", "initialiseModule", (void*)initialiseModule}, {"KedamaPlugin", "primitiveAddArrays", (void*)primitiveAddArrays}, {"KedamaPlugin", "scalarGetDistanceTo", (void*)scalarGetDistanceTo}, {"KedamaPlugin", "turtlesSetY", (void*)turtlesSetY}, {"KedamaPlugin", "randomIntoFloatArray", (void*)randomIntoFloatArray}, {"KedamaPlugin", "primTurtlesForward", (void*)primTurtlesForward}, {"KedamaPlugin", "primitiveMulScalar", (void*)primitiveMulScalar}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/KedamaPlugin2/KedamaPlugin2.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static double degreesFromXy(double x, double y); static double degreesToRadians(double degrees); #pragma export on EXPORT(sqInt) drawTurtlesInArray(void); EXPORT(sqInt) getHeadingArrayInto(void); #pragma export off static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); EXPORT(sqInt) getScalarHeading(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt kedamaRandom2(sqInt range); static sqInt kedamaRandom(sqInt range); #pragma export on EXPORT(sqInt) kedamaSetRandomSeed(void); EXPORT(sqInt) makeMask(void); EXPORT(sqInt) makeMaskLog(void); EXPORT(sqInt) makeTurtlesMap(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primPixelAtXY(void); EXPORT(sqInt) primPixelAtXYPut(void); EXPORT(sqInt) primPixelsAtXY(void); EXPORT(sqInt) primScalarForward(void); EXPORT(sqInt) primSetPixelsAtXY(void); EXPORT(sqInt) primTurtlesForward(void); EXPORT(sqInt) primUpHill(void); EXPORT(sqInt) primitiveAddArrays(void); EXPORT(sqInt) primitiveAddScalar(void); EXPORT(sqInt) primitiveAndByteArray(void); EXPORT(sqInt) primitiveDivArrays(void); EXPORT(sqInt) primitiveDivScalar(void); EXPORT(sqInt) primitiveEQArrays(void); EXPORT(sqInt) primitiveEQScalar(void); EXPORT(sqInt) primitiveGEArrays(void); EXPORT(sqInt) primitiveGEScalar(void); EXPORT(sqInt) primitiveGTArrays(void); EXPORT(sqInt) primitiveGTScalar(void); EXPORT(sqInt) primitiveLEArrays(void); EXPORT(sqInt) primitiveLEScalar(void); EXPORT(sqInt) primitiveLTArrays(void); EXPORT(sqInt) primitiveLTScalar(void); EXPORT(sqInt) primitiveMulArrays(void); EXPORT(sqInt) primitiveMulScalar(void); EXPORT(sqInt) primitiveNEArrays(void); EXPORT(sqInt) primitiveNEScalar(void); EXPORT(sqInt) primitiveNotByteArray(void); EXPORT(sqInt) primitiveOrByteArray(void); EXPORT(sqInt) primitivePredicateAtAllPutBoolean(void); EXPORT(sqInt) primitivePredicateAtAllPutColor(void); EXPORT(sqInt) primitivePredicateAtAllPutNumber(void); EXPORT(sqInt) primitivePredicateAtAllPutObject(void); EXPORT(sqInt) primitivePredicateReplaceBytes(void); EXPORT(sqInt) primitivePredicateReplaceWords(void); EXPORT(sqInt) primitiveRemArrays(void); EXPORT(sqInt) primitiveRemScalar(void); EXPORT(sqInt) primitiveSubArrays(void); EXPORT(sqInt) primitiveSubScalar(void); #pragma export off static double radiansToDegrees(double radians); #pragma export on EXPORT(sqInt) randomIntoFloatArray(void); EXPORT(sqInt) randomIntoIntegerArray(void); EXPORT(sqInt) randomRange(void); EXPORT(sqInt) scalarGetAngleTo(void); EXPORT(sqInt) scalarGetDistanceTo(void); #pragma export off static sqInt scalarXAtxArrayheadingArrayvaluedestWidthleftEdgeModerightEdgeMode(sqInt index, float* xArray, float* headingArray, double val, double destWidth, sqInt leftEdgeMode, sqInt rightEdgeMode); static sqInt scalarYAtyArrayheadingArrayvaluedestHeighttopEdgeModebottomEdgeMode(sqInt index, float* yArray, float* headingArray, double val, double destHeight, sqInt topEdgeMode, sqInt bottomEdgeMode); #pragma export on EXPORT(sqInt) setHeadingArrayFrom(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) setScalarHeading(void); EXPORT(sqInt) shutdownModule(void); EXPORT(sqInt) turtleScalarSetX(void); EXPORT(sqInt) turtleScalarSetY(void); EXPORT(sqInt) turtlesSetX(void); EXPORT(sqInt) turtlesSetY(void); EXPORT(sqInt) vectorGetAngleTo(void); EXPORT(sqInt) vectorGetDistanceTo(void); EXPORT(sqInt) zoomBitmap(void); #pragma export off /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static unsigned int kedamaRandomSeed; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "KedamaPlugin2 23 January 2011 (i)" #else "KedamaPlugin2 23 January 2011 (e)" #endif ; static unsigned int randA; static unsigned int randM; static unsigned int randQ; static unsigned int randR; static double degreesFromXy(double x, double y) { double tanVal; double theta; if (x == 0.0) { if (y >= 0.0) { return 90.0; } else { return 270.0; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { return theta / 0.0174532925199433; } else { return 360.0 + (theta / 0.0174532925199433); } } else { return 180.0 + (theta / 0.0174532925199433); } } return 0.0; } static double degreesToRadians(double degrees) { double deg; double headingRadians; int q; deg = 90.0 - degrees; q = deg / 360.0; if (deg < 0.0) { q -= 1; } headingRadians = (deg - (q * 360.0)) * 0.0174532925199433; return headingRadians; } EXPORT(sqInt) drawTurtlesInArray(void) { sqInt bitsIndex; unsigned int *colorArray; sqInt colorOop; unsigned int *destBits; sqInt destHeight; sqInt destOop; sqInt destWidth; sqInt i; sqInt size; sqInt visible; unsigned char *visibleArray; sqInt visibleOop; sqInt x; float *xArray; sqInt xOop; sqInt y; float *yArray; sqInt yOop; visibleOop = interpreterProxy->stackValue(0); colorOop = interpreterProxy->stackValue(1); yOop = interpreterProxy->stackValue(2); xOop = interpreterProxy->stackValue(3); destHeight = interpreterProxy->stackIntegerValue(4); destWidth = interpreterProxy->stackIntegerValue(5); destOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(destOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(colorOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isBytes(visibleOop))) { interpreterProxy->primitiveFail(); return null; } if ((destHeight * destWidth) != (interpreterProxy->slotSizeOf(destOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(colorOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(visibleOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); colorArray = interpreterProxy->firstIndexableField(colorOop); visibleArray = interpreterProxy->firstIndexableField(visibleOop); destBits = interpreterProxy->firstIndexableField(destOop); for (i = 0; i <= (size - 1); i += 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; visible = visibleArray[i]; if ((visible != 0) && (((x >= 0) && (y >= 0)) && ((x < destWidth) && (y < destHeight)))) { bitsIndex = (y * destWidth) + x; destBits[bitsIndex] = (colorArray[i]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) getHeadingArrayInto(void) { double heading; float *headingArray; sqInt headingOop; sqInt i; float *resultArray; sqInt resultOop; sqInt size; resultOop = interpreterProxy->stackValue(0); headingOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(headingOop); if ((interpreterProxy->slotSizeOf(resultOop)) != size) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); resultArray = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (size - 1); i += 1) { heading = headingArray[i]; heading = heading / 0.0174532925199433; heading = 90.0 - heading; if (!(heading > 0.0)) { heading += 360.0; } resultArray[i] = heading; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } EXPORT(sqInt) getScalarHeading(void) { double heading; float *headingArray; sqInt headingOop; sqInt index; double deg; double degrees; headingOop = interpreterProxy->stackValue(0); index = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) < index) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); heading = headingArray[index - 1]; /* begin radiansToDegrees: */ degrees = heading / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } heading = deg; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); interpreterProxy->pushFloat(heading); } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { kedamaRandomSeed = 17; /* magic constant = 16807 */ randA = 16807; /* magic constant = 2147483647 */ randM = 2147483647U; randQ = randM / randA; randR = randM % randA; } static sqInt kedamaRandom2(sqInt range) { sqInt hi; sqInt lo; sqInt r; sqInt v; sqInt val; if (range < 0) { r = 0 - range; } else { r = range; } hi = kedamaRandomSeed / randQ; lo = kedamaRandomSeed % randQ; kedamaRandomSeed = (randA * lo) - (randR * hi); v = kedamaRandomSeed & 65535; val = ((usqInt) (v * (r + 1))) >> 16; if (range < 0) { return 0 - val; } else { return val; } } static sqInt kedamaRandom(sqInt range) { sqInt r; sqInt val; if (range < 0) { r = 0 - range; } else { r = range; } kedamaRandomSeed = ((kedamaRandomSeed * 1309) + 13849) & 65535; val = ((usqInt) (kedamaRandomSeed * (r + 1))) >> 16; if (range < 0) { return 0 - val; } else { return val; } } EXPORT(sqInt) kedamaSetRandomSeed(void) { sqInt seed; seed = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } kedamaRandomSeed = seed & 65536; interpreterProxy->pop(1); } EXPORT(sqInt) makeMask(void) { unsigned int alpha; unsigned int* dOrigin; sqInt data; sqInt dataBits; sqInt dataSize; unsigned int highMask; sqInt i; unsigned int* mOrigin; sqInt maskBits; sqInt maskSize; unsigned int pixel; sqInt shiftAmount; shiftAmount = interpreterProxy->stackIntegerValue(0); pixel = interpreterProxy->stackIntegerValue(1); maskBits = interpreterProxy->stackValue(2); dataBits = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } dataSize = interpreterProxy->slotSizeOf(dataBits); maskSize = interpreterProxy->slotSizeOf(maskBits); if (!(dataSize == maskSize)) { interpreterProxy->primitiveFail(); return null; } if (shiftAmount < -32) { interpreterProxy->primitiveFail(); return null; } if (shiftAmount > 8) { interpreterProxy->primitiveFail(); return null; } dOrigin = interpreterProxy->firstIndexableField(dataBits); mOrigin = interpreterProxy->firstIndexableField(maskBits); highMask = 4278190080U; for (i = 0; i <= (dataSize - 1); i += 1) { data = dOrigin[i]; alpha = ((shiftAmount < 0) ? ((usqInt) data >> -shiftAmount) : ((usqInt) data << shiftAmount)); if (alpha > 255) { alpha = 255; } if (alpha < 0) { alpha = 0; } mOrigin[i] = (((alpha << 24) & highMask) | pixel); } interpreterProxy->pop(4); } EXPORT(sqInt) makeMaskLog(void) { unsigned int alpha; unsigned int* dOrigin; sqInt data; sqInt dataBits; sqInt dataSize; unsigned int highMask; sqInt i; unsigned int* mOrigin; sqInt maskBits; sqInt maskSize; unsigned int max; unsigned int* maxFirst; double maxLog; sqInt maxOop; unsigned int pixel; maxOop = interpreterProxy->stackValue(0); pixel = interpreterProxy->stackIntegerValue(1); maskBits = interpreterProxy->stackValue(2); dataBits = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } maxFirst = interpreterProxy->firstIndexableField(maxOop); max = maxFirst[0]; if (interpreterProxy->failed()) { return null; } maxLog = log(max); dataSize = interpreterProxy->slotSizeOf(dataBits); maskSize = interpreterProxy->slotSizeOf(maskBits); if (!(dataSize == maskSize)) { interpreterProxy->primitiveFail(); return null; } dOrigin = interpreterProxy->firstIndexableField(dataBits); mOrigin = interpreterProxy->firstIndexableField(maskBits); highMask = 4278190080U; for (i = 0; i <= (dataSize - 1); i += 1) { data = dOrigin[i]; if (data == 0) { alpha = 0; } else { alpha = ((sqInt)((255.0 / maxLog) * (log(data)))); } if (alpha > 255) { alpha = 255; } mOrigin[i] = (((alpha << 24) & highMask) | pixel); } interpreterProxy->pop(4); } EXPORT(sqInt) makeTurtlesMap(void) { sqInt height; sqInt index; unsigned int *map; sqInt mapIndex; sqInt mapOop; sqInt size; unsigned int *whoArray; sqInt whoOop; sqInt width; sqInt x; float *xArray; sqInt xOop; sqInt y; float *yArray; sqInt yOop; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); yOop = interpreterProxy->stackValue(2); xOop = interpreterProxy->stackValue(3); whoOop = interpreterProxy->stackValue(4); mapOop = interpreterProxy->stackValue(5); if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(whoOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(mapOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(whoOop); if ((interpreterProxy->slotSizeOf(xOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(mapOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); whoArray = interpreterProxy->firstIndexableField(whoOop); map = interpreterProxy->firstIndexableField(mapOop); for (index = 0; index <= ((height * width) - 1); index += 1) { map[index] = 0; } for (index = 0; index <= (size - 1); index += 1) { x = xArray[index]; y = yArray[index]; mapIndex = (width * y) + x; if ((mapIndex >= 0) && (mapIndex < (height * width))) { map[mapIndex] = (whoArray[index]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primPixelAtXY(void) { unsigned int *bits; sqInt bitsOop; sqInt height; sqInt index; sqInt ret; sqInt width; sqInt x; double xPos; sqInt y; double yPos; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); yPos = interpreterProxy->stackFloatValue(2); xPos = interpreterProxy->stackFloatValue(3); bitsOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } x = xPos; y = yPos; bits = interpreterProxy->firstIndexableField(bitsOop); if ((((x >= 0) && (x < width)) && (y >= 0)) && (y < height)) { index = (y * width) + x; ret = bits[index]; } else { ret = 0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->pushInteger(ret); } EXPORT(sqInt) primPixelAtXYPut(void) { unsigned int *bits; sqInt bitsOop; sqInt height; sqInt index; sqInt v; sqInt value; sqInt width; sqInt x; double xPos; sqInt y; double yPos; height = interpreterProxy->stackIntegerValue(0); width = interpreterProxy->stackIntegerValue(1); value = interpreterProxy->stackIntegerValue(2); yPos = interpreterProxy->stackFloatValue(3); xPos = interpreterProxy->stackFloatValue(4); bitsOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } x = xPos; y = yPos; v = value; if (v > 1073741823) { v = 1073741823; } if (v < 0) { v = 0; } bits = interpreterProxy->firstIndexableField(bitsOop); if ((((x >= 0) && (x < width)) && (y >= 0)) && (y < height)) { index = (y * width) + x; bits[index] = v; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) primPixelsAtXY(void) { unsigned int *bits; sqInt bitsHeight; sqInt bitsIndex; sqInt bitsOop; sqInt bitsWidth; unsigned int *destWords; sqInt destWordsOop; sqInt i; sqInt size; sqInt x; float *xArray; sqInt xArrayOop; sqInt y; float *yArray; sqInt yArrayOop; destWordsOop = interpreterProxy->stackValue(0); bitsHeight = interpreterProxy->stackIntegerValue(1); bitsWidth = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); yArrayOop = interpreterProxy->stackValue(4); xArrayOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(destWordsOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((bitsHeight * bitsWidth) != (interpreterProxy->slotSizeOf(bitsOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xArrayOop); if ((interpreterProxy->slotSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(destWordsOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); destWords = interpreterProxy->firstIndexableField(destWordsOop); bits = interpreterProxy->firstIndexableField(bitsOop); for (i = 0; i <= (size - 1); i += 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; if (((x >= 0) && (y >= 0)) && ((x < bitsWidth) && (y < bitsHeight))) { bitsIndex = (y * bitsWidth) + x; destWords[i] = (bits[bitsIndex]); } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); } EXPORT(sqInt) primScalarForward(void) { sqInt bottomEdgeMode; double destHeight; double destWidth; double dist; float *headingArray; sqInt headingOop; sqInt i; sqInt index; sqInt leftEdgeMode; double newX; double newY; sqInt rightEdgeMode; sqInt size; sqInt topEdgeMode; double val; float *xArray; sqInt xOop; float *yArray; sqInt yOop; double headingRadians; double newX1; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); rightEdgeMode = interpreterProxy->stackIntegerValue(2); leftEdgeMode = interpreterProxy->stackIntegerValue(3); destHeight = interpreterProxy->stackFloatValue(4); destWidth = interpreterProxy->stackFloatValue(5); val = interpreterProxy->stackFloatValue(6); headingOop = interpreterProxy->stackValue(7); yOop = interpreterProxy->stackValue(8); xOop = interpreterProxy->stackValue(9); index = interpreterProxy->stackIntegerValue(10); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); dist = val; i = index - 1; newX = (xArray[i]) + (dist * (cos(headingArray[i]))); newY = (yArray[i]) - (dist * (sin(headingArray[i]))); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(11); } EXPORT(sqInt) primSetPixelsAtXY(void) { unsigned int *bits; sqInt bitsHeight; sqInt bitsIndex; sqInt bitsOop; sqInt bitsWidth; float *floatsValue; sqInt fv; sqInt i; unsigned int intValue; sqInt isValueInt; sqInt isValueWordArray; unsigned char *pArray; sqInt pArrayOop; sqInt size; unsigned int value; sqInt valueOop; unsigned int *wordsValue; sqInt x; float *xArray; sqInt xArrayOop; sqInt y; float *yArray; sqInt yArrayOop; valueOop = interpreterProxy->stackValue(0); bitsHeight = interpreterProxy->stackIntegerValue(1); bitsWidth = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); yArrayOop = interpreterProxy->stackValue(4); xArrayOop = interpreterProxy->stackValue(5); pArrayOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(pArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((bitsHeight * bitsWidth) != (interpreterProxy->slotSizeOf(bitsOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xArrayOop); if ((interpreterProxy->slotSizeOf(pArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } pArray = interpreterProxy->firstIndexableField(pArrayOop); xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); isValueInt = (valueOop & 1); if (isValueInt) { intValue = (valueOop >> 1); value = intValue; } else { if ((interpreterProxy->slotSizeOf(valueOop)) != size) { interpreterProxy->primitiveFail(); return null; } isValueWordArray = interpreterProxy->isMemberOf(valueOop, "WordArray"); if (isValueWordArray) { wordsValue = interpreterProxy->firstIndexableField(valueOop); } else { floatsValue = interpreterProxy->firstIndexableField(valueOop); } } bits = interpreterProxy->firstIndexableField(bitsOop); for (i = 0; i <= (size - 1); i += 1) { if ((pArray[i]) == 1) { x = ((int) (xArray[i])); ; y = ((int) (yArray[i])); ; if (((x >= 0) && (y >= 0)) && ((x < bitsWidth) && (y < bitsHeight))) { bitsIndex = (y * bitsWidth) + x; if (isValueInt) { bits[bitsIndex] = value; } else { if (isValueWordArray) { bits[bitsIndex] = (wordsValue[i]); } else { fv = floatsValue[i]; ; bits[bitsIndex] = fv; } } } } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) primTurtlesForward(void) { sqInt bottomEdgeMode; double destHeight; double destWidth; double dist; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; sqInt leftEdgeMode; double newX; double newY; unsigned char *pArray; sqInt pOop; sqInt rightEdgeMode; sqInt size; sqInt topEdgeMode; double val; float *valArray; sqInt valOop; float *xArray; sqInt xOop; float *yArray; sqInt yOop; double headingRadians; double newX1; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); rightEdgeMode = interpreterProxy->stackIntegerValue(2); leftEdgeMode = interpreterProxy->stackIntegerValue(3); destHeight = interpreterProxy->stackFloatValue(4); destWidth = interpreterProxy->stackFloatValue(5); valOop = interpreterProxy->stackValue(6); headingOop = interpreterProxy->stackValue(7); yOop = interpreterProxy->stackValue(8); xOop = interpreterProxy->stackValue(9); pOop = interpreterProxy->stackValue(10); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(pOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(yOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(pOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } pArray = interpreterProxy->firstIndexableField(pOop); xArray = interpreterProxy->firstIndexableField(xOop); yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { valArray = interpreterProxy->firstIndexableField(valOop); } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if ((pArray[i]) == 1) { if (isValVector) { dist = valArray[i]; } else { dist = val; } newX = (xArray[i]) + (dist * (cos(headingArray[i]))); newY = (yArray[i]) - (dist * (sin(headingArray[i]))); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(11); } EXPORT(sqInt) primUpHill(void) { unsigned int *bits; sqInt bitsOop; sqInt endX; sqInt endY; sqInt height; sqInt maxVal; sqInt maxValX; sqInt maxValY; double ret; sqInt rowOffset; sqInt sniffRange; sqInt startX; sqInt startY; double tH; double tX; double tY; sqInt thisVal; sqInt turtleX; sqInt turtleY; sqInt width; sqInt x; sqInt y; double deg; double degrees; sniffRange = interpreterProxy->stackIntegerValue(0); height = interpreterProxy->stackIntegerValue(1); width = interpreterProxy->stackIntegerValue(2); bitsOop = interpreterProxy->stackValue(3); tH = interpreterProxy->stackFloatValue(4); tY = interpreterProxy->stackFloatValue(5); tX = interpreterProxy->stackFloatValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(bitsOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(bitsOop)) != (height * width)) { interpreterProxy->primitiveFail(); return null; } bits = interpreterProxy->firstIndexableField(bitsOop); turtleX = tX; turtleY = tY; turtleX = ((turtleX < 0) ? 0 : turtleX); turtleY = ((turtleY < 0) ? 0 : turtleY); turtleX = ((turtleX < (width - 1)) ? turtleX : (width - 1)); turtleY = ((turtleY < (height - 1)) ? turtleY : (height - 1)); startX = (((turtleX - sniffRange) < 0) ? 0 : (turtleX - sniffRange)); endX = (((turtleX + sniffRange) < (width - 1)) ? (turtleX + sniffRange) : (width - 1)); startY = (((turtleY - sniffRange) < 0) ? 0 : (turtleY - sniffRange)); endY = (((turtleY + sniffRange) < (height - 1)) ? (turtleY + sniffRange) : (height - 1)); maxVal = bits[(turtleY * width) + turtleX]; maxValX = -1; for (y = startY; y <= endY; y += 1) { rowOffset = y * width; for (x = startX; x <= endX; x += 1) { thisVal = bits[rowOffset + x]; if (thisVal > maxVal) { maxValX = x; maxValY = y; maxVal = thisVal; } } } if (-1 == maxValX) { /* begin radiansToDegrees: */ degrees = tH / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } ret = deg; } else { ret = (degreesFromXy(((double) (maxValX - turtleX)), ((double) (maxValY - turtleY)))) + 90.0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(8); interpreterProxy->pushFloat(ret); } EXPORT(sqInt) primitiveAddArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) + (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) + (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveAddScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) + intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) + floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) + floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveAndByteArray(void) { sqInt i; sqInt length; sqInt length1; sqInt length2; unsigned char *otherArray; sqInt otherOop; unsigned char *rcvrArray; sqInt rcvrOop; otherOop = interpreterProxy->stackObjectValue(0); rcvrOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isBytes(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(otherOop)); if (interpreterProxy->failed()) { return null; } length1 = interpreterProxy->stSizeOf(rcvrOop); length2 = interpreterProxy->stSizeOf(otherOop); if (interpreterProxy->failed()) { return null; } length = length1; if (length1 > length2) { length = length2; } otherArray = interpreterProxy->firstIndexableField(otherOop); rcvrArray = interpreterProxy->firstIndexableField(rcvrOop); for (i = 0; i <= (length - 1); i += 1) { rcvrArray[i] = (((rcvrArray[i]) + (otherArray[i])) == 2); } interpreterProxy->pop(1); } EXPORT(sqInt) primitiveDivArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) / (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) / (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveDivScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) / intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) / floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) / floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveEQArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) == (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) == (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) == (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) == (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveEQScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) == intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) == floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) == intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) == floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveGEArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) >= (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) >= (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) >= (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) >= (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveGEScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) >= intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) >= floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) >= intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) >= floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveGTArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) > (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) > (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) > (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) > (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveGTScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) > intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) > floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) > intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) > floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveLEArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) <= (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) <= (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) <= (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) <= (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveLEScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) <= intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) <= floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) <= intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) <= floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveLTArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) < (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) < (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) < (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) < (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveLTScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) < intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) < floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) < intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) < floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveMulArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) * (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) * (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveMulScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) * intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) * floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) * floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveNEArrays(void) { sqInt argOop; unsigned char *bytesResult; float *floatsArg; float *floatsRcvr; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) != (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) != (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) != (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) != (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveNEScalar(void) { sqInt argOop; unsigned char *bytesResult; double floatArg; float *floatsRcvr; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) != intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((wordsRcvr[i]) != floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) != intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); bytesResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { bytesResult[i] = ((floatsRcvr[i]) != floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveNotByteArray(void) { sqInt i; sqInt length; unsigned char *rcvrArray; sqInt rcvrOop; rcvrOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isBytes(rcvrOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); if (interpreterProxy->failed()) { return null; } rcvrArray = interpreterProxy->firstIndexableField(rcvrOop); for (i = 0; i <= (length - 1); i += 1) { if ((rcvrArray[i]) == 0) { rcvrArray[i] = 1; } else { rcvrArray[i] = 0; } } } EXPORT(sqInt) primitiveOrByteArray(void) { sqInt i; sqInt length; sqInt length1; sqInt length2; unsigned char *otherArray; sqInt otherOop; unsigned char *rcvrArray; sqInt rcvrOop; otherOop = interpreterProxy->stackObjectValue(0); rcvrOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isBytes(rcvrOop)); interpreterProxy->success(interpreterProxy->isBytes(otherOop)); if (interpreterProxy->failed()) { return null; } length1 = interpreterProxy->stSizeOf(rcvrOop); length2 = interpreterProxy->stSizeOf(otherOop); if (interpreterProxy->failed()) { return null; } length = length1; if (length1 > length2) { length = length2; } otherArray = interpreterProxy->firstIndexableField(otherOop); rcvrArray = interpreterProxy->firstIndexableField(rcvrOop); for (i = 0; i <= (length - 1); i += 1) { rcvrArray[i] = (((rcvrArray[i]) + (otherArray[i])) > 0); } interpreterProxy->pop(1); } EXPORT(sqInt) primitivePredicateAtAllPutBoolean(void) { sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt rcvrOop; sqInt val; sqInt valOop; unsigned char *values; sqInt valuesOop; valOop = interpreterProxy->stackValue(0); rcvrOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->isIntegerValue(valOop)) { val = (valOop >> 1); } else { val = interpreterProxy->booleanValueOf(valOop); } valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isBytes(valuesOop))) { interpreterProxy->primitiveFail(); return null; } values = interpreterProxy->firstIndexableField(valuesOop); predicates = interpreterProxy->firstIndexableField(predicatesOop); for (i = 0; i <= ((interpreterProxy->stSizeOf(valuesOop)) - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = val; } } interpreterProxy->pop(1); } EXPORT(sqInt) primitivePredicateAtAllPutColor(void) { sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt rcvrOop; unsigned int val; unsigned int *values; sqInt valuesOop; val = interpreterProxy->stackIntegerValue(0); rcvrOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } val = val | 4278190080U; valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(valuesOop))) { interpreterProxy->primitiveFail(); return null; } values = interpreterProxy->firstIndexableField(valuesOop); predicates = interpreterProxy->firstIndexableField(predicatesOop); for (i = 0; i <= ((interpreterProxy->stSizeOf(valuesOop)) - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = val; } } interpreterProxy->pop(1); } EXPORT(sqInt) primitivePredicateAtAllPutNumber(void) { sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt rcvrOop; float val; float *values; sqInt valuesOop; val = interpreterProxy->stackFloatValue(0); rcvrOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(valuesOop))) { interpreterProxy->primitiveFail(); return null; } values = interpreterProxy->firstIndexableField(valuesOop); predicates = interpreterProxy->firstIndexableField(predicatesOop); for (i = 0; i <= ((interpreterProxy->stSizeOf(valuesOop)) - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = val; } } interpreterProxy->pop(1); } EXPORT(sqInt) primitivePredicateAtAllPutObject(void) { sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt rcvrOop; sqInt valOop; int *values; sqInt valuesOop; valOop = interpreterProxy->stackValue(0); rcvrOop = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return null; } valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isPointers(valuesOop))) { interpreterProxy->primitiveFail(); return null; } values = interpreterProxy->firstIndexableField(valuesOop); predicates = interpreterProxy->firstIndexableField(predicatesOop); for (i = 0; i <= ((interpreterProxy->stSizeOf(valuesOop)) - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = valOop; } } interpreterProxy->pop(1); } EXPORT(sqInt) primitivePredicateReplaceBytes(void) { sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt predicatesSize; sqInt rcvrOop; sqInt repOop; sqInt repStart; unsigned char *replacement; sqInt replacementSize; sqInt start; sqInt stop; unsigned char *values; sqInt valuesOop; sqInt valuesSize; repStart = interpreterProxy->stackIntegerValue(0); repOop = interpreterProxy->stackObjectValue(1); stop = interpreterProxy->stackIntegerValue(2); start = interpreterProxy->stackIntegerValue(3); rcvrOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return null; } valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!((interpreterProxy->isBytes(valuesOop)) && (interpreterProxy->isBytes(repOop)))) { interpreterProxy->primitiveFail(); return null; } values = interpreterProxy->firstIndexableField(valuesOop); predicates = interpreterProxy->firstIndexableField(predicatesOop); replacement = interpreterProxy->firstIndexableField(repOop); valuesSize = interpreterProxy->stSizeOf(valuesOop); predicatesSize = interpreterProxy->stSizeOf(predicatesOop); replacementSize = interpreterProxy->stSizeOf(repOop); if (start > stop) { interpreterProxy->primitiveFail(); return null; } if (start < 1) { interpreterProxy->primitiveFail(); return null; } if (start > valuesSize) { interpreterProxy->primitiveFail(); return null; } if (start > predicatesSize) { interpreterProxy->primitiveFail(); return null; } if (stop > valuesSize) { interpreterProxy->primitiveFail(); return null; } if (stop > predicatesSize) { interpreterProxy->primitiveFail(); return null; } if (repStart < 1) { interpreterProxy->primitiveFail(); return null; } if (repStart > replacementSize) { interpreterProxy->primitiveFail(); return null; } if (((replacementSize - repStart) + 1) < ((stop - start) + 1)) { interpreterProxy->primitiveFail(); return null; } for (i = (start - 1); i <= (stop - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = (replacement[(repStart + i) - start]); } } interpreterProxy->pop(4); } EXPORT(sqInt) primitivePredicateReplaceWords(void) { float *floatReplacement; float *floatValues; unsigned int fv; sqInt i; unsigned char *predicates; sqInt predicatesOop; sqInt predicatesSize; sqInt rIsFloat; sqInt rcvrOop; sqInt repOop; sqInt repStart; unsigned int *replacement; sqInt replacementSize; sqInt start; sqInt stop; sqInt vIsFloat; unsigned int *values; sqInt valuesOop; sqInt valuesSize; repStart = interpreterProxy->stackIntegerValue(0); repOop = interpreterProxy->stackObjectValue(1); stop = interpreterProxy->stackIntegerValue(2); start = interpreterProxy->stackIntegerValue(3); rcvrOop = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return null; } valuesOop = interpreterProxy->fetchPointerofObject(1, rcvrOop); predicatesOop = interpreterProxy->fetchPointerofObject(0, rcvrOop); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(predicatesOop))) { interpreterProxy->primitiveFail(); return null; } if (!(((interpreterProxy->isWords(valuesOop)) && (interpreterProxy->isWords(repOop))) || ((interpreterProxy->isPointers(valuesOop)) && (interpreterProxy->isPointers(repOop))))) { interpreterProxy->primitiveFail(); return null; } predicates = interpreterProxy->firstIndexableField(predicatesOop); valuesSize = interpreterProxy->stSizeOf(valuesOop); predicatesSize = interpreterProxy->stSizeOf(predicatesOop); replacementSize = interpreterProxy->stSizeOf(repOop); if (start > stop) { interpreterProxy->primitiveFail(); return null; } if (start < 1) { interpreterProxy->primitiveFail(); return null; } if (start > valuesSize) { interpreterProxy->primitiveFail(); return null; } if (start > predicatesSize) { interpreterProxy->primitiveFail(); return null; } if (stop > valuesSize) { interpreterProxy->primitiveFail(); return null; } if (stop > predicatesSize) { interpreterProxy->primitiveFail(); return null; } if (repStart < 1) { interpreterProxy->primitiveFail(); return null; } if (repStart > replacementSize) { interpreterProxy->primitiveFail(); return null; } if (((replacementSize - repStart) + 1) < ((stop - start) + 1)) { interpreterProxy->primitiveFail(); return null; } vIsFloat = interpreterProxy->isMemberOf(valuesOop, "KedamaFloatArray"); rIsFloat = interpreterProxy->isMemberOf(repOop, "KedamaFloatArray"); if (vIsFloat && (rIsFloat)) { floatValues = interpreterProxy->firstIndexableField(valuesOop); floatReplacement = interpreterProxy->firstIndexableField(repOop); for (i = (start - 1); i <= (stop - 1); i += 1) { if ((predicates[i]) == 1) { floatValues[i] = (floatReplacement[(repStart + i) - start]); } } } if (vIsFloat && (!rIsFloat)) { floatValues = interpreterProxy->firstIndexableField(valuesOop); replacement = interpreterProxy->firstIndexableField(repOop); for (i = (start - 1); i <= (stop - 1); i += 1) { if ((predicates[i]) == 1) { floatValues[i] = (replacement[(repStart + i) - start]); } } } if ((!vIsFloat) && (rIsFloat)) { values = interpreterProxy->firstIndexableField(valuesOop); floatReplacement = interpreterProxy->firstIndexableField(repOop); for (i = (start - 1); i <= (stop - 1); i += 1) { if ((predicates[i]) == 1) { fv = ((unsigned int) (floatReplacement[(repStart + i) - start])); ; values[i] = fv; } } } if ((!vIsFloat) && (!rIsFloat)) { values = interpreterProxy->firstIndexableField(valuesOop); replacement = interpreterProxy->firstIndexableField(repOop); for (i = (start - 1); i <= (stop - 1); i += 1) { if ((predicates[i]) == 1) { values[i] = (replacement[(repStart + i) - start]); } } } interpreterProxy->pop(4); } EXPORT(sqInt) primitiveRemArrays(void) { sqInt argOop; double floatArg; double floatRcvr; double floatResult; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int wordArg; unsigned int wordRcvr; unsigned int wordResult; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordRcvr = wordsRcvr[i]; wordArg = wordsArg[i]; /* In this primitive, words are supposed to be unsigned. */ wordResult = wordRcvr % wordArg; wordsResult[i] = wordResult; } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordRcvr = wordsRcvr[i]; floatArg = floatsArg[i]; floatResult = wordRcvr / floatArg; floatResult = floor(floatResult); floatsResult[i] = (wordRcvr - (floatResult * floatArg)); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatRcvr = floatsRcvr[i]; wordArg = wordsArg[i]; floatResult = floatRcvr / wordArg; floatResult = floor(floatResult); floatsResult[i] = (floatRcvr - (floatResult * wordArg)); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatRcvr = floatsRcvr[i]; floatArg = floatsArg[i]; floatResult = floatRcvr / floatArg; floatResult = floor(floatResult); floatsResult[i] = (floatRcvr - (floatResult * floatArg)); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveRemScalar(void) { sqInt argOop; double floatArg; double floatRcvr; double floatResult; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int wordRcvr; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) % intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordRcvr = wordsRcvr[i]; floatResult = wordRcvr / floatArg; floatResult = floor(floatResult); floatsResult[i] = (wordRcvr - (floatResult * floatArg)); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatRcvr = floatsRcvr[i]; floatResult = floatRcvr / intArg; floatResult = floor(floatResult); floatsResult[i] = (floatRcvr - (floatResult * intArg)); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatRcvr = floatsRcvr[i]; floatResult = floatRcvr / floatArg; floatResult = floor(floatResult); floatsResult[i] = (floatRcvr - (floatResult * floatArg)); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveSubArrays(void) { sqInt argOop; float *floatsArg; float *floatsRcvr; float *floatsResult; sqInt i; sqInt isArgWords; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsArg; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackObjectValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(argOop)); interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(argOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(rcvrOop))); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgWords = interpreterProxy->isMemberOf(argOop, "WordArray"); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgWords && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgWords) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) - (wordsArg[i])); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) - (floatsArg[i])); } } } else { if (isArgWords) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); wordsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - (wordsArg[i])); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatsArg = interpreterProxy->firstIndexableField(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - (floatsArg[i])); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } EXPORT(sqInt) primitiveSubScalar(void) { sqInt argOop; double floatArg; float *floatsRcvr; float *floatsResult; sqInt i; int intArg; sqInt isArgInt; sqInt isRcvrWords; sqInt length; sqInt rcvrOop; sqInt resultOop; unsigned int *wordsRcvr; unsigned int *wordsResult; resultOop = interpreterProxy->stackObjectValue(0); argOop = interpreterProxy->stackValue(1); rcvrOop = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->success(interpreterProxy->isWords(rcvrOop)); interpreterProxy->success(interpreterProxy->isWords(resultOop)); if (interpreterProxy->failed()) { return null; } length = interpreterProxy->stSizeOf(rcvrOop); interpreterProxy->success(length == (interpreterProxy->stSizeOf(resultOop))); if (interpreterProxy->failed()) { return null; } isArgInt = (argOop & 1); isRcvrWords = interpreterProxy->isMemberOf(rcvrOop, "WordArray"); if (isArgInt && isRcvrWords) { if (!(interpreterProxy->isMemberOf(resultOop, "WordArray"))) { interpreterProxy->primitiveFail(); return null; } } else { if (!(interpreterProxy->isMemberOf(resultOop, "KedamaFloatArray"))) { interpreterProxy->primitiveFail(); return null; } } if (isRcvrWords) { if (isArgInt) { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); wordsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { wordsResult[i] = ((wordsRcvr[i]) - intArg); } } else { wordsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((wordsRcvr[i]) - floatArg); } } } else { if (isArgInt) { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); intArg = (argOop >> 1); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - intArg); } } else { floatsRcvr = interpreterProxy->firstIndexableField(rcvrOop); floatArg = interpreterProxy->floatValueOf(argOop); floatsResult = interpreterProxy->firstIndexableField(resultOop); for (i = 0; i <= (length - 1); i += 1) { floatsResult[i] = ((floatsRcvr[i]) - floatArg); } } } interpreterProxy->pop(4); interpreterProxy->push(resultOop); } static double radiansToDegrees(double radians) { double deg; double degrees; degrees = radians / 0.0174532925199433; deg = 90.0 - degrees; if (!(deg > 0.0)) { deg += 360.0; } return deg; } EXPORT(sqInt) randomIntoFloatArray(void) { double factor; float *floatArray; sqInt floatArrayOop; sqInt from; sqInt index; sqInt range; sqInt size; sqInt to; factor = interpreterProxy->stackFloatValue(0); floatArrayOop = interpreterProxy->stackValue(1); to = interpreterProxy->stackIntegerValue(2); from = interpreterProxy->stackIntegerValue(3); range = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(floatArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(floatArrayOop); if (!((size >= to) && ((from >= 1) && (to >= from)))) { interpreterProxy->primitiveFail(); return null; } floatArray = interpreterProxy->firstIndexableField(floatArrayOop); if (interpreterProxy->failed()) { return null; } for (index = from; index <= to; index += 1) { floatArray[index - 1] = ((((double) (kedamaRandom2(range)))) * factor); } interpreterProxy->pop(5); } EXPORT(sqInt) randomIntoIntegerArray(void) { double factor; sqInt from; sqInt index; unsigned int *integerArray; sqInt integerArrayOop; sqInt range; sqInt size; sqInt to; factor = interpreterProxy->stackFloatValue(0); integerArrayOop = interpreterProxy->stackValue(1); to = interpreterProxy->stackIntegerValue(2); from = interpreterProxy->stackIntegerValue(3); range = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(integerArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(integerArrayOop); if (!((size >= to) && ((from >= 1) && (to >= from)))) { interpreterProxy->primitiveFail(); return null; } integerArray = interpreterProxy->firstIndexableField(integerArrayOop); if (interpreterProxy->failed()) { return null; } for (index = from; index <= to; index += 1) { integerArray[index - 1] = (((int) ((((double) (kedamaRandom2(range)))) * factor))); } interpreterProxy->pop(5); } EXPORT(sqInt) randomRange(void) { sqInt range; sqInt ret; sqInt hi; sqInt lo; sqInt r; sqInt v; sqInt val; range = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } /* begin kedamaRandom2: */ if (range < 0) { r = 0 - range; } else { r = range; } hi = kedamaRandomSeed / randQ; lo = kedamaRandomSeed % randQ; kedamaRandomSeed = (randA * lo) - (randR * hi); v = kedamaRandomSeed & 65535; val = ((usqInt) (v * (r + 1))) >> 16; if (range < 0) { ret = 0 - val; goto l1; } else { ret = val; goto l1; } l1: /* end kedamaRandom2: */; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); interpreterProxy->pushInteger(ret); } EXPORT(sqInt) scalarGetAngleTo(void) { double fromX; double fromY; double r; double toX; double toY; double x; double y; double tanVal; double theta; fromY = interpreterProxy->stackFloatValue(0); fromX = interpreterProxy->stackFloatValue(1); toY = interpreterProxy->stackFloatValue(2); toX = interpreterProxy->stackFloatValue(3); if (interpreterProxy->failed()) { return null; } x = toX - fromX; y = toY - fromY; /* begin degreesFromX:y: */ if (x == 0.0) { if (y >= 0.0) { r = 90.0; goto l1; } else { r = 270.0; goto l1; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { r = theta / 0.0174532925199433; goto l1; } else { r = 360.0 + (theta / 0.0174532925199433); goto l1; } } else { r = 180.0 + (theta / 0.0174532925199433); goto l1; } } r = 0.0; l1: /* end degreesFromX:y: */; r += 90.0; if (r > 360.0) { r -= 360.0; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); interpreterProxy->pushFloat(r); } EXPORT(sqInt) scalarGetDistanceTo(void) { double fromX; double fromY; double r; double toX; double toY; double x; double y; fromY = interpreterProxy->stackFloatValue(0); fromX = interpreterProxy->stackFloatValue(1); toY = interpreterProxy->stackFloatValue(2); toX = interpreterProxy->stackFloatValue(3); if (interpreterProxy->failed()) { return null; } x = fromX - toX; y = fromY - toY; r = sqrt((x * x) + (y * y)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); interpreterProxy->pushFloat(r); } static sqInt scalarXAtxArrayheadingArrayvaluedestWidthleftEdgeModerightEdgeMode(sqInt index, float* xArray, float* headingArray, double val, double destWidth, sqInt leftEdgeMode, sqInt rightEdgeMode) { double headingRadians; double newX; newX = val; if (newX < 0.0) { if (leftEdgeMode == 1) { newX += destWidth; } if (leftEdgeMode == 2) { newX = 0.0; } if (leftEdgeMode == 3) { /* bounce */ newX = 0.0 - newX; headingRadians = headingArray[index]; if (headingRadians < 3.141592653589793) { headingArray[index] = (3.141592653589793 - headingRadians); } else { headingArray[index] = (9.42477796076938 - headingRadians); } } } if (newX >= destWidth) { if (rightEdgeMode == 1) { newX -= destWidth; } if (rightEdgeMode == 2) { newX = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX = (destWidth - 1.0e-6) - (newX - destWidth); headingRadians = headingArray[index]; if (headingRadians < 3.141592653589793) { headingArray[index] = (3.141592653589793 - headingRadians); } else { headingArray[index] = (9.42477796076938 - headingRadians); } } } xArray[index] = newX; } static sqInt scalarYAtyArrayheadingArrayvaluedestHeighttopEdgeModebottomEdgeMode(sqInt index, float* yArray, float* headingArray, double val, double destHeight, sqInt topEdgeMode, sqInt bottomEdgeMode) { double newY; newY = val; if (newY < 0.0) { if (topEdgeMode == 1) { newY += destHeight; } if (topEdgeMode == 2) { newY = 0.0; } if (topEdgeMode == 3) { /* bounce */ newY = 0.0 - newY; headingArray[index] = (6.283185307179586 - (headingArray[index])); } } if (newY >= destHeight) { if (bottomEdgeMode == 1) { newY -= destHeight; } if (bottomEdgeMode == 2) { newY = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY = (destHeight - 1.0e-6) - (newY - destHeight); headingArray[index] = (6.283185307179586 - (headingArray[index])); } } yArray[index] = newY; } EXPORT(sqInt) setHeadingArrayFrom(void) { double heading; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; unsigned char *pArray; sqInt pOop; float *resultArray; sqInt resultOop; sqInt size; double deg; double headingRadians; int q; double deg1; double headingRadians1; int q1; resultOop = interpreterProxy->stackValue(0); headingOop = interpreterProxy->stackValue(1); pOop = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(pOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(headingOop); if (interpreterProxy->isFloatObject(resultOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(resultOop)) { if ((interpreterProxy->slotSizeOf(resultOop)) != size) { interpreterProxy->primitiveFail(); return null; } isValVector = 1; } else { interpreterProxy->primitiveFail(); return null; } } pArray = interpreterProxy->firstIndexableField(pOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { resultArray = interpreterProxy->firstIndexableField(resultOop); } else { heading = interpreterProxy->floatValueOf(resultOop); /* begin degreesToRadians: */ deg = 90.0 - heading; q = deg / 360.0; if (deg < 0.0) { q -= 1; } headingRadians = (deg - (q * 360.0)) * 0.0174532925199433; heading = headingRadians; } for (i = 0; i <= (size - 1); i += 1) { if ((pArray[i]) == 1) { if (isValVector) { heading = resultArray[i]; /* begin degreesToRadians: */ deg1 = 90.0 - heading; q1 = deg1 / 360.0; if (deg1 < 0.0) { q1 -= 1; } headingRadians1 = (deg1 - (q1 * 360.0)) * 0.0174532925199433; heading = headingRadians1; } headingArray[i] = heading; } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) setScalarHeading(void) { double heading; float *headingArray; sqInt headingOop; sqInt index; heading = interpreterProxy->stackFloatValue(0); headingOop = interpreterProxy->stackValue(1); index = interpreterProxy->stackIntegerValue(2); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) < index) { interpreterProxy->primitiveFail(); return null; } headingArray = interpreterProxy->firstIndexableField(headingOop); headingArray[index - 1] = (degreesToRadians(heading)); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); } EXPORT(sqInt) shutdownModule(void) { return 1; } EXPORT(sqInt) turtleScalarSetX(void) { double destWidth; float *headingArray; sqInt headingOop; sqInt leftEdgeMode; sqInt rightEdgeMode; sqInt size; double val; float *xArray; sqInt xIndex; sqInt xOop; double headingRadians; double newX; rightEdgeMode = interpreterProxy->stackIntegerValue(0); leftEdgeMode = interpreterProxy->stackIntegerValue(1); destWidth = interpreterProxy->stackFloatValue(2); val = interpreterProxy->stackFloatValue(3); headingOop = interpreterProxy->stackValue(4); xIndex = interpreterProxy->stackIntegerValue(5); xOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } xArray = interpreterProxy->firstIndexableField(xOop); headingArray = interpreterProxy->firstIndexableField(headingOop); /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX = val; if (newX < 0.0) { if (leftEdgeMode == 1) { newX += destWidth; } if (leftEdgeMode == 2) { newX = 0.0; } if (leftEdgeMode == 3) { newX = 0.0 - newX; headingRadians = headingArray[xIndex - 1]; if (headingRadians < 3.141592653589793) { headingArray[xIndex - 1] = (3.141592653589793 - headingRadians); } else { headingArray[xIndex - 1] = (9.42477796076938 - headingRadians); } } } if (newX >= destWidth) { if (rightEdgeMode == 1) { newX -= destWidth; } if (rightEdgeMode == 2) { newX = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX = (destWidth - 1.0e-6) - (newX - destWidth); headingRadians = headingArray[xIndex - 1]; if (headingRadians < 3.141592653589793) { headingArray[xIndex - 1] = (3.141592653589793 - headingRadians); } else { headingArray[xIndex - 1] = (9.42477796076938 - headingRadians); } } } xArray[xIndex - 1] = newX; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) turtleScalarSetY(void) { sqInt bottomEdgeMode; double destHeight; float *headingArray; sqInt headingOop; sqInt size; sqInt topEdgeMode; double val; float *yArray; sqInt yIndex; sqInt yOop; double newY; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); destHeight = interpreterProxy->stackFloatValue(2); val = interpreterProxy->stackFloatValue(3); headingOop = interpreterProxy->stackValue(4); yIndex = interpreterProxy->stackIntegerValue(5); yOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->slotSizeOf(yOop); if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY = val; if (newY < 0.0) { if (topEdgeMode == 1) { newY += destHeight; } if (topEdgeMode == 2) { newY = 0.0; } if (topEdgeMode == 3) { newY = 0.0 - newY; headingArray[yIndex - 1] = (6.283185307179586 - (headingArray[yIndex - 1])); } } if (newY >= destHeight) { if (bottomEdgeMode == 1) { newY -= destHeight; } if (bottomEdgeMode == 2) { newY = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY = (destHeight - 1.0e-6) - (newY - destHeight); headingArray[yIndex - 1] = (6.283185307179586 - (headingArray[yIndex - 1])); } } yArray[yIndex - 1] = newY; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) turtlesSetX(void) { double destWidth; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; sqInt isWordVector; sqInt leftEdgeMode; double newX; unsigned char *pArray; sqInt pOop; sqInt rightEdgeMode; sqInt size; double val; float *valArray; sqInt valOop; unsigned int *wordValArray; float *xArray; sqInt xOop; double headingRadians; double newX1; rightEdgeMode = interpreterProxy->stackIntegerValue(0); leftEdgeMode = interpreterProxy->stackIntegerValue(1); destWidth = interpreterProxy->stackFloatValue(2); valOop = interpreterProxy->stackValue(3); headingOop = interpreterProxy->stackValue(4); xOop = interpreterProxy->stackValue(5); pOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(pOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; isWordVector = interpreterProxy->isMemberOf(valOop, "WordArray"); } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(xOop); if ((interpreterProxy->slotSizeOf(pOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } pArray = interpreterProxy->firstIndexableField(pOop); xArray = interpreterProxy->firstIndexableField(xOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { if (isWordVector) { wordValArray = interpreterProxy->firstIndexableField(valOop); } else { valArray = interpreterProxy->firstIndexableField(valOop); } } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if ((pArray[i]) == 1) { if (isValVector) { if (isWordVector) { newX = wordValArray[i]; ; } else { newX = valArray[i]; } } else { newX = val; } /* begin scalarXAt:xArray:headingArray:value:destWidth:leftEdgeMode:rightEdgeMode: */ newX1 = newX; if (newX1 < 0.0) { if (leftEdgeMode == 1) { newX1 += destWidth; } if (leftEdgeMode == 2) { newX1 = 0.0; } if (leftEdgeMode == 3) { newX1 = 0.0 - newX1; headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } if (newX1 >= destWidth) { if (rightEdgeMode == 1) { newX1 -= destWidth; } if (rightEdgeMode == 2) { newX1 = destWidth - 1.0e-6; } if (rightEdgeMode == 3) { newX1 = (destWidth - 1.0e-6) - (newX1 - destWidth); headingRadians = headingArray[i]; if (headingRadians < 3.141592653589793) { headingArray[i] = (3.141592653589793 - headingRadians); } else { headingArray[i] = (9.42477796076938 - headingRadians); } } } xArray[i] = newX1; } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) turtlesSetY(void) { sqInt bottomEdgeMode; double destHeight; float *headingArray; sqInt headingOop; sqInt i; sqInt isValVector; sqInt isWordVector; double newY; unsigned char *pArray; sqInt pOop; sqInt size; sqInt topEdgeMode; double val; float *valArray; sqInt valOop; unsigned int *wordValArray; float *yArray; sqInt yOop; double newY1; bottomEdgeMode = interpreterProxy->stackIntegerValue(0); topEdgeMode = interpreterProxy->stackIntegerValue(1); destHeight = interpreterProxy->stackFloatValue(2); valOop = interpreterProxy->stackValue(3); headingOop = interpreterProxy->stackValue(4); yOop = interpreterProxy->stackValue(5); pOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(pOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(headingOop))) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(valOop)) { isValVector = 0; } else { if (interpreterProxy->isWords(valOop)) { isValVector = 1; isWordVector = interpreterProxy->isMemberOf(valOop, "WordArray"); } else { interpreterProxy->primitiveFail(); return null; } } size = interpreterProxy->slotSizeOf(yOop); if ((interpreterProxy->slotSizeOf(pOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->slotSizeOf(headingOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (isValVector) { if ((interpreterProxy->slotSizeOf(valOop)) != size) { interpreterProxy->primitiveFail(); return null; } } pArray = interpreterProxy->firstIndexableField(pOop); yArray = interpreterProxy->firstIndexableField(yOop); headingArray = interpreterProxy->firstIndexableField(headingOop); if (isValVector) { if (isWordVector) { wordValArray = interpreterProxy->firstIndexableField(valOop); } else { valArray = interpreterProxy->firstIndexableField(valOop); } } else { val = interpreterProxy->floatValueOf(valOop); } for (i = 0; i <= (size - 1); i += 1) { if ((pArray[i]) == 1) { if (isValVector) { if (isWordVector) { newY = wordValArray[i]; ; } else { newY = valArray[i]; } } else { newY = val; } /* begin scalarYAt:yArray:headingArray:value:destHeight:topEdgeMode:bottomEdgeMode: */ newY1 = newY; if (newY1 < 0.0) { if (topEdgeMode == 1) { newY1 += destHeight; } if (topEdgeMode == 2) { newY1 = 0.0; } if (topEdgeMode == 3) { newY1 = 0.0 - newY1; headingArray[i] = (6.283185307179586 - (headingArray[i])); } } if (newY1 >= destHeight) { if (bottomEdgeMode == 1) { newY1 -= destHeight; } if (bottomEdgeMode == 2) { newY1 = destHeight - 1.0e-6; } if (bottomEdgeMode == 3) { newY1 = (destHeight - 1.0e-6) - (newY1 - destHeight); headingArray[i] = (6.283185307179586 - (headingArray[i])); } } yArray[i] = newY1; } } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); } EXPORT(sqInt) vectorGetAngleTo(void) { sqInt index; sqInt isVector; float *pX; sqInt pXOop; float *pY; sqInt pYOop; double ppx; double ppy; double r; float *result; sqInt resultOop; sqInt size; double x; float *xArray; sqInt xArrayOop; double y; float *yArray; sqInt yArrayOop; double tanVal; double theta; resultOop = interpreterProxy->stackValue(0); yArrayOop = interpreterProxy->stackValue(1); xArrayOop = interpreterProxy->stackValue(2); pYOop = interpreterProxy->stackValue(3); pXOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(resultOop); if (size < 0) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(xArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(pXOop)) { if (interpreterProxy->isFloatObject(pYOop)) { isVector = 0; } else { interpreterProxy->primitiveFail(); return null; } } else { if (interpreterProxy->isFloatObject(pYOop)) { interpreterProxy->primitiveFail(); return null; } else { isVector = 1; } } if (isVector) { if ((interpreterProxy->stSizeOf(pXOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(pYOop)) != size) { interpreterProxy->primitiveFail(); return null; } } result = interpreterProxy->firstIndexableField(resultOop); xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); if (isVector) { pX = interpreterProxy->firstIndexableField(pXOop); pY = interpreterProxy->firstIndexableField(pYOop); } if (!(isVector)) { ppx = interpreterProxy->floatValueOf(pXOop); ppy = interpreterProxy->floatValueOf(pYOop); } for (index = 0; index <= (size - 1); index += 1) { if (isVector) { ppx = pX[index]; ppy = pY[index]; } x = ppx - (xArray[index]); y = ppy - (yArray[index]); /* begin degreesFromX:y: */ if (x == 0.0) { if (y >= 0.0) { r = 90.0; goto l1; } else { r = 270.0; goto l1; } } else { tanVal = y / x; theta = atan(tanVal); if (x >= 0.0) { if (y >= 0.0) { r = theta / 0.0174532925199433; goto l1; } else { r = 360.0 + (theta / 0.0174532925199433); goto l1; } } else { r = 180.0 + (theta / 0.0174532925199433); goto l1; } } r = 0.0; l1: /* end degreesFromX:y: */; r += 90.0; if (r > 360.0) { r -= 360.0; } result[index] = r; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(resultOop); } EXPORT(sqInt) vectorGetDistanceTo(void) { sqInt index; sqInt isVector; float *pX; sqInt pXOop; float *pY; sqInt pYOop; double ppx; double ppy; float *result; sqInt resultOop; sqInt size; double x; float *xArray; sqInt xArrayOop; double y; float *yArray; sqInt yArrayOop; resultOop = interpreterProxy->stackValue(0); yArrayOop = interpreterProxy->stackValue(1); xArrayOop = interpreterProxy->stackValue(2); pYOop = interpreterProxy->stackValue(3); pXOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(resultOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(xArrayOop))) { interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(yArrayOop))) { interpreterProxy->primitiveFail(); return null; } size = interpreterProxy->stSizeOf(resultOop); if (size < 0) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(xArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(yArrayOop)) != size) { interpreterProxy->primitiveFail(); return null; } if (interpreterProxy->isFloatObject(pXOop)) { if (interpreterProxy->isFloatObject(pYOop)) { isVector = 0; } else { interpreterProxy->primitiveFail(); return null; } } else { if (interpreterProxy->isFloatObject(pYOop)) { interpreterProxy->primitiveFail(); return null; } else { isVector = 1; } } if (isVector) { if ((interpreterProxy->stSizeOf(pXOop)) != size) { interpreterProxy->primitiveFail(); return null; } if ((interpreterProxy->stSizeOf(pYOop)) != size) { interpreterProxy->primitiveFail(); return null; } } result = interpreterProxy->firstIndexableField(resultOop); xArray = interpreterProxy->firstIndexableField(xArrayOop); yArray = interpreterProxy->firstIndexableField(yArrayOop); if (isVector) { pX = interpreterProxy->firstIndexableField(pXOop); pY = interpreterProxy->firstIndexableField(pYOop); } if (!(isVector)) { ppx = interpreterProxy->floatValueOf(pXOop); ppy = interpreterProxy->floatValueOf(pYOop); } for (index = 0; index <= (size - 1); index += 1) { if (isVector) { ppx = pX[index]; ppy = pY[index]; } x = ppx - (xArray[index]); y = ppy - (yArray[index]); result[index] = (sqrt((x * x) + (y * y))); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); interpreterProxy->push(resultOop); } EXPORT(sqInt) zoomBitmap(void) { sqInt bit; unsigned int* dOrigin; sqInt dst; sqInt dstIndex; sqInt dstSize; sqInt dummy; sqInt sHeight; unsigned int* sOrigin; sqInt sWidth; sqInt src; sqInt srcIndex; sqInt srcOrigin; sqInt srcSize; sqInt sx; sqInt sy; sqInt xFactor; sqInt y; sqInt yFactor; yFactor = interpreterProxy->stackIntegerValue(0); xFactor = interpreterProxy->stackIntegerValue(1); sHeight = interpreterProxy->stackIntegerValue(2); sWidth = interpreterProxy->stackIntegerValue(3); dst = interpreterProxy->stackValue(4); src = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } srcSize = interpreterProxy->slotSizeOf(src); dstSize = interpreterProxy->slotSizeOf(dst); if (!((sWidth * sHeight) == srcSize)) { interpreterProxy->primitiveFail(); return null; } if (!(((srcSize * xFactor) * yFactor) == dstSize)) { interpreterProxy->primitiveFail(); return null; } sOrigin = interpreterProxy->firstIndexableField(src); dOrigin = interpreterProxy->firstIndexableField(dst); srcIndex = 0; srcOrigin = 0; dstIndex = 0; for (sy = 0; sy <= (sHeight - 1); sy += 1) { for (y = 0; y <= (yFactor - 1); y += 1) { for (sx = 0; sx <= (sWidth - 1); sx += 1) { bit = sOrigin[srcIndex]; srcIndex += 1; for (dummy = 0; dummy <= (xFactor - 1); dummy += 1) { dOrigin[dstIndex] = bit; dstIndex += 1; } } srcIndex = srcOrigin; } srcOrigin += sWidth; srcIndex = srcOrigin; } interpreterProxy->pop(6); } #ifdef SQUEAK_BUILTIN_PLUGIN void* KedamaPlugin2_exports[][3] = { {"KedamaPlugin2", "primitiveAddArrays", (void*)primitiveAddArrays}, {"KedamaPlugin2", "getModuleName", (void*)getModuleName}, {"KedamaPlugin2", "primitiveMulArrays", (void*)primitiveMulArrays}, {"KedamaPlugin2", "drawTurtlesInArray", (void*)drawTurtlesInArray}, {"KedamaPlugin2", "primitiveGTScalar", (void*)primitiveGTScalar}, {"KedamaPlugin2", "setScalarHeading", (void*)setScalarHeading}, {"KedamaPlugin2", "primitiveSubScalar", (void*)primitiveSubScalar}, {"KedamaPlugin2", "turtleScalarSetY", (void*)turtleScalarSetY}, {"KedamaPlugin2", "vectorGetAngleTo", (void*)vectorGetAngleTo}, {"KedamaPlugin2", "primitiveRemArrays", (void*)primitiveRemArrays}, {"KedamaPlugin2", "primitiveLTArrays", (void*)primitiveLTArrays}, {"KedamaPlugin2", "primitiveAddScalar", (void*)primitiveAddScalar}, {"KedamaPlugin2", "primPixelsAtXY", (void*)primPixelsAtXY}, {"KedamaPlugin2", "primitiveMulScalar", (void*)primitiveMulScalar}, {"KedamaPlugin2", "primSetPixelsAtXY", (void*)primSetPixelsAtXY}, {"KedamaPlugin2", "setHeadingArrayFrom", (void*)setHeadingArrayFrom}, {"KedamaPlugin2", "primPixelAtXYPut", (void*)primPixelAtXYPut}, {"KedamaPlugin2", "makeMaskLog", (void*)makeMaskLog}, {"KedamaPlugin2", "primitiveLTScalar", (void*)primitiveLTScalar}, {"KedamaPlugin2", "scalarGetAngleTo", (void*)scalarGetAngleTo}, {"KedamaPlugin2", "primitiveOrByteArray", (void*)primitiveOrByteArray}, {"KedamaPlugin2", "primitiveLEArrays", (void*)primitiveLEArrays}, {"KedamaPlugin2", "primitiveRemScalar", (void*)primitiveRemScalar}, {"KedamaPlugin2", "getHeadingArrayInto", (void*)getHeadingArrayInto}, {"KedamaPlugin2", "turtlesSetX", (void*)turtlesSetX}, {"KedamaPlugin2", "primitivePredicateReplaceBytes", (void*)primitivePredicateReplaceBytes}, {"KedamaPlugin2", "primitiveDivArrays", (void*)primitiveDivArrays}, {"KedamaPlugin2", "makeMask", (void*)makeMask}, {"KedamaPlugin2", "primitiveLEScalar", (void*)primitiveLEScalar}, {"KedamaPlugin2", "kedamaSetRandomSeed", (void*)kedamaSetRandomSeed}, {"KedamaPlugin2", "randomIntoIntegerArray", (void*)randomIntoIntegerArray}, {"KedamaPlugin2", "setInterpreter", (void*)setInterpreter}, {"KedamaPlugin2", "primitivePredicateAtAllPutColor", (void*)primitivePredicateAtAllPutColor}, {"KedamaPlugin2", "makeTurtlesMap", (void*)makeTurtlesMap}, {"KedamaPlugin2", "randomIntoFloatArray", (void*)randomIntoFloatArray}, {"KedamaPlugin2", "primUpHill", (void*)primUpHill}, {"KedamaPlugin2", "shutdownModule", (void*)shutdownModule}, {"KedamaPlugin2", "primitiveDivScalar", (void*)primitiveDivScalar}, {"KedamaPlugin2", "primitiveGEArrays", (void*)primitiveGEArrays}, {"KedamaPlugin2", "primitiveNotByteArray", (void*)primitiveNotByteArray}, {"KedamaPlugin2", "randomRange", (void*)randomRange}, {"KedamaPlugin2", "initialiseModule", (void*)initialiseModule}, {"KedamaPlugin2", "getScalarHeading", (void*)getScalarHeading}, {"KedamaPlugin2", "primPixelAtXY", (void*)primPixelAtXY}, {"KedamaPlugin2", "primitivePredicateAtAllPutNumber", (void*)primitivePredicateAtAllPutNumber}, {"KedamaPlugin2", "primitiveEQArrays", (void*)primitiveEQArrays}, {"KedamaPlugin2", "primitiveNEArrays", (void*)primitiveNEArrays}, {"KedamaPlugin2", "primScalarForward", (void*)primScalarForward}, {"KedamaPlugin2", "vectorGetDistanceTo", (void*)vectorGetDistanceTo}, {"KedamaPlugin2", "turtlesSetY", (void*)turtlesSetY}, {"KedamaPlugin2", "turtleScalarSetX", (void*)turtleScalarSetX}, {"KedamaPlugin2", "primTurtlesForward", (void*)primTurtlesForward}, {"KedamaPlugin2", "primitiveGEScalar", (void*)primitiveGEScalar}, {"KedamaPlugin2", "primitiveAndByteArray", (void*)primitiveAndByteArray}, {"KedamaPlugin2", "primitivePredicateReplaceWords", (void*)primitivePredicateReplaceWords}, {"KedamaPlugin2", "primitiveGTArrays", (void*)primitiveGTArrays}, {"KedamaPlugin2", "primitivePredicateAtAllPutObject", (void*)primitivePredicateAtAllPutObject}, {"KedamaPlugin2", "primitiveEQScalar", (void*)primitiveEQScalar}, {"KedamaPlugin2", "primitivePredicateAtAllPutBoolean", (void*)primitivePredicateAtAllPutBoolean}, {"KedamaPlugin2", "zoomBitmap", (void*)zoomBitmap}, {"KedamaPlugin2", "primitiveNEScalar", (void*)primitiveNEScalar}, {"KedamaPlugin2", "scalarGetDistanceTo", (void*)scalarGetDistanceTo}, {"KedamaPlugin2", "primitiveSubArrays", (void*)primitiveSubArrays}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/Mpeg3Plugin/Mpeg3Plugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:02 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "Mpeg3Plugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt checkFileEntry(mpeg3_t * aMpegFile); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt makeFileEntry(mpeg3_t * aMpegFile); static mpeg3_t * mpeg3tValueOf(sqInt mpeg3tHandle); static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveMPEG3AudioChannels(void); EXPORT(sqInt) primitiveMPEG3AudioSamples(void); EXPORT(sqInt) primitiveMPEG3CheckSig(void); EXPORT(sqInt) primitiveMPEG3Close(void); EXPORT(sqInt) primitiveMPEG3DropFrames(void); EXPORT(sqInt) primitiveMPEG3EndOfAudio(void); EXPORT(sqInt) primitiveMPEG3EndOfVideo(void); EXPORT(sqInt) primitiveMPEG3FrameRate(void); EXPORT(sqInt) primitiveMPEG3GenerateToc(void); EXPORT(sqInt) primitiveMPEG3GetFrame(void); EXPORT(sqInt) primitiveMPEG3GetSample(void); EXPORT(sqInt) primitiveMPEG3GetTime(void); EXPORT(sqInt) primitiveMPEG3HasAudio(void); EXPORT(sqInt) primitiveMPEG3HasVideo(void); EXPORT(sqInt) primitiveMPEG3Open(void); EXPORT(sqInt) primitiveMPEG3OpenABuffer(void); EXPORT(sqInt) primitiveMPEG3PreviousFrame(void); EXPORT(sqInt) primitiveMPEG3ReReadAudio(void); EXPORT(sqInt) primitiveMPEG3ReadAudio(void); EXPORT(sqInt) primitiveMPEG3ReadFrameBufferOffset(void); EXPORT(sqInt) primitiveMPEG3ReadFrame(void); EXPORT(sqInt) primitiveMPEG3SampleRate(void); EXPORT(sqInt) primitiveMPEG3SeekPercentage(void); EXPORT(sqInt) primitiveMPEG3SetCpus(void); EXPORT(sqInt) primitiveMPEG3SetFrame(void); EXPORT(sqInt) primitiveMPEG3SetMmx(void); EXPORT(sqInt) primitiveMPEG3SetSample(void); EXPORT(sqInt) primitiveMPEG3TellPercentage(void); EXPORT(sqInt) primitiveMPEG3TotalAStreams(void); EXPORT(sqInt) primitiveMPEG3TotalVStreams(void); EXPORT(sqInt) primitiveMPEG3VideoFrames(void); EXPORT(sqInt) primitiveMPEG3VideoHeight(void); EXPORT(sqInt) primitiveMPEG3VideoWidth(void); #pragma export off static sqInt removeFileEntry(mpeg3_t * aMpegFile); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static sqInt maximumNumberOfFilesToWatch; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Mpeg3Plugin 23 January 2011 (i)" #else "Mpeg3Plugin 23 January 2011 (e)" #endif ; static mpeg3_t *mpegFiles[1024+1]; static sqInt checkFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == aMpegFile) { return 1; } } return 0; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { sqInt i; maximumNumberOfFilesToWatch = 1024; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { mpegFiles[i] = 0; } return true; } static sqInt makeFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == 0) { mpegFiles[i] = aMpegFile; return 1; } } return 0; } /* Return a pointer to the first byte of of the mpeg3_t record within the given Smalltalk object, or nil if socketOop is not a mpeg3_t record. */ static mpeg3_t * mpeg3tValueOf(sqInt mpeg3tHandle) { mpeg3_t ** index; sqInt check; interpreterProxy->success((interpreterProxy->isBytes(mpeg3tHandle)) && ((interpreterProxy->byteSizeOf(mpeg3tHandle)) == 4)); if (interpreterProxy->failed()) { return null; } else { index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3tHandle))); check = checkFileEntry(*index); if (check == 0) { return null; } return *index; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* int mpeg3_audio_channels(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3AudioChannels(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber >= (mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_audio_channels(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* long mpeg3_audio_samples(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3AudioSamples(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_audio_samples(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_check_sig(char *path) */ EXPORT(sqInt) primitiveMPEG3CheckSig(void) { sqInt result; char storage[1024] ; sqInt sz; char *path; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } sz = interpreterProxy->byteSizeOf((oopForPointer( path ) - BASE_HEADER_SIZE)); interpreterProxy->ioFilenamefromStringofLengthresolveAliases(storage, path, sz, 1); result = mpeg3_check_sig(storage); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_close(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3Close(void) { mpeg3_t * file; mpeg3_t ** index; sqInt fileHandle; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } removeFileEntry(file); mpeg3_close(file); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(fileHandle))); *index = 0; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } /* int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream) */ EXPORT(sqInt) primitiveMPEG3DropFrames(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aFrameNumber; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aFrameNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } result = mpeg3_drop_frames(file,aFrameNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* int mpeg3_end_of_audio(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3EndOfAudio(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_end_of_audio(file,aNumber); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_end_of_video(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3EndOfVideo(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_end_of_video(file,aNumber); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* float mpeg3_frame_rate(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3FrameRate(void) { mpeg3_t * file; double result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_frame_rate(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_generate_toc_for_Squeak(FILE *output, char *path, int timecode_search, int print_streams, char *buffer) */ EXPORT(sqInt) primitiveMPEG3GenerateToc(void) { mpeg3_t * file; sqInt bufferSize; sqInt fileHandle; sqInt timecode; sqInt streams; char *aString; fileHandle = interpreterProxy->stackValue(3); timecode = interpreterProxy->stackIntegerValue(2); streams = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } bufferSize = interpreterProxy->slotSizeOf(interpreterProxy->stackValue(0)); mpeg3_generate_toc_for_Squeak(file,timecode,streams,aString,bufferSize); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } /* long mpeg3_get_frame(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3GetFrame(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_get_frame(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_width(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3GetSample(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_get_sample(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* double mpeg3_get_time(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3GetTime(void) { mpeg3_t * file; double result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_get_time(file); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_has_audio(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3HasAudio(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_has_audio(file); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_has_video(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3HasVideo(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_has_video(file); _return_value = (result? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* mpeg3_t* mpeg3_open(char *path) */ EXPORT(sqInt) primitiveMPEG3Open(void) { sqInt mpeg3Oop; mpeg3_t ** index; char storage[1024]; sqInt sz; char *path; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); if (interpreterProxy->failed()) { return null; } sz = interpreterProxy->byteSizeOf((oopForPointer( path ) - BASE_HEADER_SIZE)); interpreterProxy->ioFilenamefromStringofLengthresolveAliases(storage, path, sz, 1); mpeg3Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), 4); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3Oop))); *index = mpeg3_open(storage,0); makeFileEntry(*index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, mpeg3Oop); return null; } EXPORT(sqInt) primitiveMPEG3OpenABuffer(void) { sqInt mpeg3Oop; mpeg3_t ** index; char *path; sqInt size; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1))); path = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1)))); size = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } mpeg3Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), 4); index = ((mpeg3_t **) (interpreterProxy->firstIndexableField(mpeg3Oop))); *index = mpeg3_open(path,size); makeFileEntry(*index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, mpeg3Oop); return null; } /* int mpeg3_previous_frame(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3PreviousFrame(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (aNumber < 0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_previous_frame(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_reread_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) */ EXPORT(sqInt) primitiveMPEG3ReReadAudio(void) { mpeg3_t * file; short * arrayBase; sqInt result; sqInt fileHandle; sqInt *anArray; sqInt aChannelNumber; sqInt aSampleNumber; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(4); interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(3))); anArray = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); aChannelNumber = interpreterProxy->stackIntegerValue(2); aSampleNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } arrayBase = ((short *) anArray); if (interpreterProxy->failed()) { return null; } result = mpeg3_reread_audio(file,(float *) NULL,arrayBase,aChannelNumber,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } /* int mpeg3_read_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) */ EXPORT(sqInt) primitiveMPEG3ReadAudio(void) { mpeg3_t * file; short * arrayBase; sqInt result; sqInt fileHandle; sqInt *anArray; sqInt aChannelNumber; sqInt aSampleNumber; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(4); interpreterProxy->success(interpreterProxy->isIndexable(interpreterProxy->stackValue(3))); anArray = ((int *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3)))); aChannelNumber = interpreterProxy->stackIntegerValue(2); aSampleNumber = interpreterProxy->stackIntegerValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, 0); return null; } arrayBase = ((short *) anArray); if (interpreterProxy->failed()) { return null; } result = mpeg3_read_audio(file,(float *) NULL,arrayBase,aChannelNumber,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, _return_value); return null; } EXPORT(sqInt) primitiveMPEG3ReadFrameBufferOffset(void) { unsigned char ** outputRowsPtr; unsigned char *bufferBaseAddr; sqInt i; mpeg3_t * file; sqInt result; sqInt fileHandle; usqInt *aBuffer; sqInt aBufferOffset; sqInt xNumber; sqInt yNumber; sqInt width; sqInt height; sqInt outWidth; sqInt outHeight; sqInt model; sqInt aNumber; sqInt aByteNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(11); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(10))); aBuffer = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(10)))); aBufferOffset = interpreterProxy->stackIntegerValue(9); xNumber = interpreterProxy->stackIntegerValue(8); yNumber = interpreterProxy->stackIntegerValue(7); width = interpreterProxy->stackIntegerValue(6); height = interpreterProxy->stackIntegerValue(5); outWidth = interpreterProxy->stackIntegerValue(4); outHeight = interpreterProxy->stackIntegerValue(3); model = interpreterProxy->stackIntegerValue(2); aNumber = interpreterProxy->stackIntegerValue(1); aByteNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, 0); return null; } bufferBaseAddr = ((unsigned char *) aBuffer); outputRowsPtr = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * outHeight); for (i = 0; i <= (outHeight - 1); i += 1) { outputRowsPtr[i] = ((bufferBaseAddr + aBufferOffset) + (aByteNumber * i)); } result = mpeg3_read_frame(file,outputRowsPtr,xNumber,yNumber,width,height,outWidth,outHeight,model,aNumber); memoryFree(outputRowsPtr); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(13, _return_value); return null; } EXPORT(sqInt) primitiveMPEG3ReadFrame(void) { unsigned char ** outputRowsPtr; unsigned char *bufferBaseAddr; sqInt i; mpeg3_t * file; sqInt result; sqInt fileHandle; usqInt *aBuffer; sqInt xNumber; sqInt yNumber; sqInt width; sqInt height; sqInt outWidth; sqInt outHeight; sqInt model; sqInt aNumber; sqInt aByteNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(10); interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(9))); aBuffer = ((unsigned *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(9)))); xNumber = interpreterProxy->stackIntegerValue(8); yNumber = interpreterProxy->stackIntegerValue(7); width = interpreterProxy->stackIntegerValue(6); height = interpreterProxy->stackIntegerValue(5); outWidth = interpreterProxy->stackIntegerValue(4); outHeight = interpreterProxy->stackIntegerValue(3); model = interpreterProxy->stackIntegerValue(2); aNumber = interpreterProxy->stackIntegerValue(1); aByteNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, 0); return null; } bufferBaseAddr = ((unsigned char *) aBuffer); outputRowsPtr = (unsigned char **) memoryAllocate(1,sizeof(unsigned char*) * outHeight); for (i = 0; i <= (outHeight - 1); i += 1) { outputRowsPtr[i] = (bufferBaseAddr + (aByteNumber * i)); } result = mpeg3_read_frame(file,outputRowsPtr,xNumber,yNumber,width,height,outWidth,outHeight,model,aNumber); memoryFree(outputRowsPtr); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(12, _return_value); return null; } /* int mpeg3_sample_rate(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3SampleRate(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_sample_rate(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_seek_percentage(mpeg3_t *file, double percentage) */ EXPORT(sqInt) primitiveMPEG3SeekPercentage(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; double aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackFloatValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (aNumber < 0.0) { interpreterProxy->success(0); return null; } if (aNumber > 1.0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } result = mpeg3_seek_percentage(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_set_cpus(mpeg3_t *file, int cpus) */ EXPORT(sqInt) primitiveMPEG3SetCpus(void) { mpeg3_t * file; sqInt fileHandle; sqInt cpus; fileHandle = interpreterProxy->stackValue(1); cpus = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (cpus < 0) { interpreterProxy->success(0); return null; } if (file == null) { return null; } mpeg3_set_cpus(file,cpus); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* int mpeg3_set_frame(mpeg3_t *file, long frame, int stream) */ EXPORT(sqInt) primitiveMPEG3SetFrame(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; double aFrameNumber; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aFrameNumber = interpreterProxy->stackFloatValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } result = mpeg3_set_frame(file,(long) aFrameNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* int mpeg3_set_mmx(mpeg3_t *file, int use_mmx) */ EXPORT(sqInt) primitiveMPEG3SetMmx(void) { mpeg3_t * file; sqInt fileHandle; sqInt mmx; fileHandle = interpreterProxy->stackValue(1); mmx = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } mpeg3_set_mmx(file,mmx); if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } /* int mpeg3_set_sample(mpeg3_t *file, long sample, int stream) */ EXPORT(sqInt) primitiveMPEG3SetSample(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; double aSampleNumber; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(2); aSampleNumber = interpreterProxy->stackFloatValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_astreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, 0); return null; } if (aSampleNumber < 0) { interpreterProxy->success(0); return null; } result = mpeg3_set_sample(file,aSampleNumber,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } /* double mpeg3_tell_percentage(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TellPercentage(void) { mpeg3_t * file; double result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_tell_percentage(file); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_total_astreams(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TotalAStreams(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, 0); return null; } result = mpeg3_total_astreams(file); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* int mpeg3_total_vstreams(mpeg3_t *file) */ EXPORT(sqInt) primitiveMPEG3TotalVStreams(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt _return_value; fileHandle = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { return null; } result = mpeg3_total_vstreams(file); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(2, _return_value); return null; } /* long mpeg3_video_frames(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3VideoFrames(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_frames(file,aNumber); _return_value = interpreterProxy->floatObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_height(mpeg3_t *file,int stream) */ EXPORT(sqInt) primitiveMPEG3VideoHeight(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_height(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } /* int mpeg3_video_width(mpeg3_t *file, int stream) */ EXPORT(sqInt) primitiveMPEG3VideoWidth(void) { mpeg3_t * file; sqInt result; sqInt fileHandle; sqInt aNumber; sqInt _return_value; fileHandle = interpreterProxy->stackValue(1); aNumber = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } file = mpeg3tValueOf(fileHandle); if (file == null) { if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } if (aNumber < 0) { interpreterProxy->success(0); return null; } if (aNumber >= (result = mpeg3_total_vstreams(file))) { interpreterProxy->success(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, 0); return null; } result = mpeg3_video_width(file,aNumber); _return_value = interpreterProxy->integerObjectOf(result); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } static sqInt removeFileEntry(mpeg3_t * aMpegFile) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) == aMpegFile) { mpegFiles[i] = 0; return 1; } } return 0; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { sqInt i; for (i = 1; i <= maximumNumberOfFilesToWatch; i += 1) { if ((mpegFiles[i]) != 0) { mpeg3_close(mpegFiles[i]); mpegFiles[i] = 0; } } return true; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* Mpeg3Plugin_exports[][3] = { {"Mpeg3Plugin", "primitiveMPEG3Close", (void*)primitiveMPEG3Close}, {"Mpeg3Plugin", "primitiveMPEG3SeekPercentage", (void*)primitiveMPEG3SeekPercentage}, {"Mpeg3Plugin", "primitiveMPEG3VideoFrames", (void*)primitiveMPEG3VideoFrames}, {"Mpeg3Plugin", "primitiveMPEG3ReadFrame", (void*)primitiveMPEG3ReadFrame}, {"Mpeg3Plugin", "primitiveMPEG3HasVideo", (void*)primitiveMPEG3HasVideo}, {"Mpeg3Plugin", "primitiveMPEG3GetFrame", (void*)primitiveMPEG3GetFrame}, {"Mpeg3Plugin", "primitiveMPEG3VideoWidth", (void*)primitiveMPEG3VideoWidth}, {"Mpeg3Plugin", "shutdownModule", (void*)shutdownModule}, {"Mpeg3Plugin", "primitiveMPEG3ReReadAudio", (void*)primitiveMPEG3ReReadAudio}, {"Mpeg3Plugin", "primitiveMPEG3GetTime", (void*)primitiveMPEG3GetTime}, {"Mpeg3Plugin", "primitiveMPEG3SetCpus", (void*)primitiveMPEG3SetCpus}, {"Mpeg3Plugin", "primitiveMPEG3AudioSamples", (void*)primitiveMPEG3AudioSamples}, {"Mpeg3Plugin", "primitiveMPEG3ReadAudio", (void*)primitiveMPEG3ReadAudio}, {"Mpeg3Plugin", "getModuleName", (void*)getModuleName}, {"Mpeg3Plugin", "primitiveMPEG3SetSample", (void*)primitiveMPEG3SetSample}, {"Mpeg3Plugin", "primitiveMPEG3GenerateToc", (void*)primitiveMPEG3GenerateToc}, {"Mpeg3Plugin", "setInterpreter", (void*)setInterpreter}, {"Mpeg3Plugin", "primitiveMPEG3CheckSig", (void*)primitiveMPEG3CheckSig}, {"Mpeg3Plugin", "primitiveMPEG3SampleRate", (void*)primitiveMPEG3SampleRate}, {"Mpeg3Plugin", "primitiveMPEG3GetSample", (void*)primitiveMPEG3GetSample}, {"Mpeg3Plugin", "primitiveMPEG3OpenABuffer", (void*)primitiveMPEG3OpenABuffer}, {"Mpeg3Plugin", "primitiveMPEG3EndOfVideo", (void*)primitiveMPEG3EndOfVideo}, {"Mpeg3Plugin", "primitiveMPEG3VideoHeight", (void*)primitiveMPEG3VideoHeight}, {"Mpeg3Plugin", "primitiveMPEG3AudioChannels", (void*)primitiveMPEG3AudioChannels}, {"Mpeg3Plugin", "primitiveMPEG3TotalVStreams", (void*)primitiveMPEG3TotalVStreams}, {"Mpeg3Plugin", "primitiveMPEG3FrameRate", (void*)primitiveMPEG3FrameRate}, {"Mpeg3Plugin", "primitiveMPEG3TellPercentage", (void*)primitiveMPEG3TellPercentage}, {"Mpeg3Plugin", "primitiveMPEG3HasAudio", (void*)primitiveMPEG3HasAudio}, {"Mpeg3Plugin", "primitiveMPEG3SetFrame", (void*)primitiveMPEG3SetFrame}, {"Mpeg3Plugin", "primitiveMPEG3PreviousFrame", (void*)primitiveMPEG3PreviousFrame}, {"Mpeg3Plugin", "initialiseModule", (void*)initialiseModule}, {"Mpeg3Plugin", "primitiveMPEG3ReadFrameBufferOffset", (void*)primitiveMPEG3ReadFrameBufferOffset}, {"Mpeg3Plugin", "primitiveMPEG3SetMmx", (void*)primitiveMPEG3SetMmx}, {"Mpeg3Plugin", "primitiveMPEG3TotalAStreams", (void*)primitiveMPEG3TotalAStreams}, {"Mpeg3Plugin", "primitiveMPEG3DropFrames", (void*)primitiveMPEG3DropFrames}, {"Mpeg3Plugin", "primitiveMPEG3EndOfAudio", (void*)primitiveMPEG3EndOfAudio}, {"Mpeg3Plugin", "primitiveMPEG3Open", (void*)primitiveMPEG3Open}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/RomePlugin/RomePlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 6:31:55 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include #include #include #include "SurfacePlugin.h" #define NUM_OF(array) (sizeof (array) / sizeof *(array)) #define lastIndex(array) (NUM_OF(array) - 1) #define degrees(a) (a * 3.141592653589793 / 180.0) #define log(msg) fprintf(stderr, "Squeak-Rome: " msg "\n") #define logwith(msg, a) fprintf(stderr, "Squeak-Rome: " msg "\n", a) #define logwithwith(msg, a, b) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b) #define logwithwithwith(msg, a, b, c) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c) #define logwithwithwithwith(msg, a, b, c, d) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c, d) #define logwithwithwithwithwith(msg, a, b, c, d, e) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c, d, e) #define primFail interpreterProxy->primitiveFail() #define fail(msg) log(msg "!"); primFail #define failwith(msg, a) logwith(msg "!", a); primFail #define failwithwith(msg, a, b) logwithwith(msg "!", a, b); primFail #include "sqMemoryAccess.h" /*** Constants ***/ #define CairoExtendRepeat CAIRO_EXTEND_REPEAT #define CairoOperatorSource CAIRO_OPERATOR_SOURCE #define CanvasFlagFill 256 #define CanvasFlagStroke 255 #define CanvasFlagsIndex 2 #define CanvasHandleIndex 0 #define CanvasInstSize 8 #define CanvasStrokeColorIndex 3 #define CanvasTargetIndex 1 #define FormBitsIndex 0 #define FormDepthIndex 3 #define FormHeightIndex 2 #define FormInstSize 5 #define FormWidthIndex 1 #define PluginVersion 39 #define TextLineBottomIndex 3 #define TextLineEndIndex 5 #define TextLineInternalSpaceIndex 6 #define TextLineLeftIndex 0 #define TextLinePaddingWidthIndex 7 #define TextLineRightIndex 1 #define TextLineStartIndex 4 #define TextLineTopIndex 2 /*** Function Prototypes ***/ static sqInt addAlignmentinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList); static sqInt addColorinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList); static void addColorStopTooffsetrgbalpha(cairo_pattern_t*pattern, sqInt intOffset, sqInt rgb, sqInt alpha); static sqInt addDefaultInto(PangoAttrList *pangoAttrList); static sqInt addEmphasisinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList); static sqInt addFontinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList); static sqInt addLanguageinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList); static sqInt addSelectionAtpixelwith(PangoRectangle *rect, unsigned int c, cairo_t*context); static sqInt addSelectionFromtopixelinto(sqInt start, sqInt end, unsigned int c, PangoAttrList *pangoAttrList); static cairo_t* contextFrom(sqInt canvasOop); static sqInt createContextFor(sqInt canvasOop); static sqInt createSurfaceFor(sqInt formOop); static sqInt destroyContextFor(sqInt canvasOop); static sqInt destroySurface(sqInt surfaceID); static void fillOrStrokefrom(cairo_t*context, sqInt canvasOop); static cairo_surface_t* findSurface(sqInt surfaceID); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt getSurfaceFormatgetWgetHgetDgetMsb(cairo_surface_t *surfaceHandle, int*wReturn, int*hReturn, int*dReturn, int*mReturn); static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt leadingCharOf(unsigned int value); static sqInt loadSurfacePlugin(void); static unsigned char* lockSurfacegetPitchxywh(cairo_surface_t*surfaceHandle, int*pitchReturn, sqInt x, sqInt y, sqInt w, sqInt h); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); static void polyPathfrom(cairo_t*context, sqInt pointsOop); #pragma export on EXPORT(sqInt) primitivePangoBlockAtIndex(void); EXPORT(sqInt) primitiveClear(void); EXPORT(sqInt) primitiveClipRectangleLeftRightTopBottom(void); EXPORT(sqInt) primitiveClose(void); EXPORT(sqInt) primitivePangoComposeString(void); EXPORT(sqInt) primitivePangoComposeString2(void); EXPORT(sqInt) primitiveCreateFormHandle(void); EXPORT(sqInt) primitiveDestroyFormHandle(void); EXPORT(sqInt) primitiveDrawArcRadiusXYFromTo(void); EXPORT(sqInt) primitiveDrawCurveFromXYviaXYandXYtoXY(void); EXPORT(sqInt) primitiveDrawCurveFromXYviaXYtoXY(void); EXPORT(sqInt) primitiveDrawGeneralBezierShape(void); EXPORT(sqInt) primitiveDrawImageSrcLRTBDestLRTB(void); EXPORT(sqInt) primitiveDrawLineFromXYtoXY(void); EXPORT(sqInt) primitiveDrawOvalLeftRightTopBottom(void); EXPORT(sqInt) primitiveDrawPolygon(void); EXPORT(sqInt) primitiveDrawPolyline(void); EXPORT(sqInt) primitiveDrawRectangleLeftRightTopBottom(void); EXPORT(sqInt) primitiveDrawRoundRectLeftRightTopBottomRadiusCorner(void); EXPORT(sqInt) primitiveDrawZeroTerminatedUtf8StringXY(void); EXPORT(sqInt) primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage(void); EXPORT(sqInt) primitiveFillColorAlpha(void); EXPORT(sqInt) primitiveFillLinearOriginXYdirectionXYcolorStops(void); EXPORT(sqInt) primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops(void); EXPORT(sqInt) primitiveFontFace(void); EXPORT(sqInt) primitiveFontSize(void); EXPORT(sqInt) primitiveGetLineWidth(void); EXPORT(sqInt) primitivePangoFontDescriptionIndex(void); EXPORT(sqInt) primitiveGetTransform(void); EXPORT(sqInt) primitivePangoIndexAtPoint(void); EXPORT(sqInt) primitiveLanguageAttributes(void); EXPORT(sqInt) primitiveOpen(void); EXPORT(sqInt) primitivePangoIsAvailable(void); EXPORT(sqInt) primitivePluginVersion(void); EXPORT(sqInt) primitiveRestoreState(void); EXPORT(sqInt) primitiveRotateBy(void); EXPORT(sqInt) primitiveSaveState(void); EXPORT(sqInt) primitiveScaleBy(void); EXPORT(sqInt) primitiveSetLineWidth(void); EXPORT(sqInt) primitiveSetTransform(void); EXPORT(sqInt) primitivePangoShowString(void); EXPORT(sqInt) primitiveShowZeroTerminatedUtf8StringXY(void); EXPORT(sqInt) primitiveStencilImageSrcLRTBDestLRTB(void); EXPORT(sqInt) primitiveTransformBy(void); EXPORT(sqInt) primitiveTranslateBy(void); EXPORT(sqInt) primitiveUTF8StringWith2Indexes(void); EXPORT(sqInt) primitiveUTF8StringWithIndex(void); #pragma export off static sqInt putCharintoat(sqInt c, unsigned char*utf8String, sqInt utf8Index); static sqInt registerSurface(cairo_surface_t*surfaceHandle); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static void setSourcergbalpha(cairo_t*context, sqInt rgb, sqInt alpha); static sqInt showSurfacexywh(cairo_surface_t *surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h); #pragma export on EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); static sqInt sqCharCountInfromto(unsigned char* aString, sqInt from, sqInt to); static void strokefrom(cairo_t*context, sqInt canvasOop); static cairo_surface_t* surfaceFrom(sqInt formOop); static sqInt translateSqAttrsToPangoAttrsinto(sqInt sqAttrsArrayOop, PangoAttrList *pangoAttrList); static sqInt unlockSurfacexywh(cairo_surface_t*surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h); static sqInt unregisterSurface(sqInt surfaceID); static sqInt utf8CountFor(unsigned int value); /*** Variables ***/ static cairo_t* contexts[64]; static PangoFontDescription *defaultFontDescription; static fn_ioFindSurface findSurfaceFn; static PangoFontDescription *fontDescriptions[256]; static int formatToDepth[] = { 32, 32, 8, 1, 16}; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static sqInt maxSurfaceID; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "RomePlugin Aeneas.39 23 January 2011 (i)" #else "RomePlugin Aeneas.39 23 January 2011 (e)" #endif ; static fn_ioRegisterSurface registerSurfaceFn; static sqSurfaceDispatch surfaceDispatch = { 1, 0, (fn_getSurfaceFormat) getSurfaceFormatgetWgetHgetDgetMsb, (fn_lockSurface) lockSurfacegetPitchxywh, (fn_unlockSurface) unlockSurfacexywh, (fn_showSurface) showSurfacexywh }; static fn_ioUnregisterSurface unregisterSurfaceFn; static int utf8Headers[] = { 0, 192, 224, 240, 248, 252, 254, 255}; static sqInt addAlignmentinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) { sqInt start; sqInt alignment; int pangoAlignment; sqInt end; sqInt *attrArray; attrArray = interpreterProxy->firstIndexableField(attrArrayOop); start = ((attrArray[1]) >> 1); end = ((attrArray[2]) >> 1); alignment = ((attrArray[3]) >> 1); if (alignment == 0) { pangoAlignment = PANGO_ALIGN_LEFT; } if (alignment == 1) { pangoAlignment = PANGO_ALIGN_RIGHT; } if (alignment == 2) { pangoAlignment = PANGO_ALIGN_CENTER; } if (alignment == 3) { null; } } static sqInt addColorinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) { sqInt start; sqInt r; sqInt b; PangoAttribute *pangoAttr; sqInt end; sqInt g; sqInt alpha; sqInt *attrArray; unsigned int c; attrArray = interpreterProxy->firstIndexableField(attrArrayOop); start = ((attrArray[1]) >> 1); end = ((attrArray[2]) >> 1); /* self log: 'color: %u' with: c. */ c = interpreterProxy->positive32BitValueOf(attrArray[3]); alpha = ((usqInt) (c && 4278190080U)) >> 24; r = ((usqInt) (c & 16711680)) >> 16; g = ((usqInt) (c & 65280)) >> 8; b = c & 255; if (!(r == 0)) { r = r * 257; } if (!(g == 0)) { g = g * 257; } if (!(b == 0)) { b = b * 257; } pangoAttr = pango_attr_foreground_new(r, g, b); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } static void addColorStopTooffsetrgbalpha(cairo_pattern_t*pattern, sqInt intOffset, sqInt rgb, sqInt alpha) { sqInt b; sqInt r; sqInt g; r = (((usqInt) rgb) >> 20) & 1023; g = (((usqInt) rgb) >> 10) & 1023; b = (((usqInt) rgb) >> 0) & 1023; if (alpha == 255) { cairo_pattern_add_color_stop_rgb(pattern, intOffset / 65536.0, r / 1023.0, g / 1023.0, b / 1023.0); } else { cairo_pattern_add_color_stop_rgba(pattern, intOffset / 65536.0, r / 1023.0, g / 1023.0, b / 1023.0, alpha / 255.0); } } static sqInt addDefaultInto(PangoAttrList *pangoAttrList) { PangoAttribute *pangoAttr; PangoLanguage *lang; pangoAttr = pango_attr_foreground_new(0, 0, 1); pangoAttr->start_index = 0; pangoAttr->end_index = 0x7fffffff; pango_attr_list_insert(pangoAttrList, pangoAttr); pangoAttr = pango_attr_font_desc_new(defaultFontDescription); pangoAttr->start_index = 0; pangoAttr->end_index = 0x7fffffff; pango_attr_list_insert(pangoAttrList, pangoAttr); lang = pango_language_from_string("en-US"); pangoAttr = pango_attr_language_new(lang); pangoAttr->start_index = 0; pangoAttr->end_index = 0x7fffffff; pango_attr_list_insert(pangoAttrList, pangoAttr); } static sqInt addEmphasisinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) { sqInt start; PangoAttribute *pangoAttr; sqInt end; sqInt *attrArray; sqInt c; attrArray = interpreterProxy->firstIndexableField(attrArrayOop); start = ((attrArray[1]) >> 1); end = ((attrArray[2]) >> 1); c = ((attrArray[3]) >> 1); if (c & 1) { pangoAttr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } if (c & 2) { pangoAttr = pango_attr_style_new(PANGO_STYLE_OBLIQUE); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } if (c & 4) { pangoAttr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } if (c & 8) { pangoAttr = pango_attr_stretch_new(PANGO_STRETCH_CONDENSED); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } if (c & 16) { pangoAttr = pango_attr_strikethrough_new(1); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } } static sqInt addFontinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) { sqInt start; PangoFontDescription *desc; sqInt fontDescIndex; PangoAttribute *pangoAttr; sqInt end; sqInt *attrArray; attrArray = interpreterProxy->firstIndexableField(attrArrayOop); start = ((attrArray[1]) >> 1); end = ((attrArray[2]) >> 1); fontDescIndex = interpreterProxy->fetchIntegerofObject(5, attrArray[4]); if (fontDescIndex < 0) { return null; } if (fontDescIndex > 255) { return null; } desc = fontDescriptions[fontDescIndex]; if (desc == null) { return null; } pangoAttr = pango_attr_font_desc_new(desc); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } static sqInt addLanguageinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) { sqInt start; PangoAttribute *pangoAttr; sqInt end; sqInt lang; char *cLang; sqInt *attrArray; PangoLanguage *pangoLang; attrArray = interpreterProxy->firstIndexableField(attrArrayOop); start = ((attrArray[1]) >> 1); end = ((attrArray[2]) >> 1); lang = ((attrArray[3]) >> 1); if (lang == 0) { cLang = "en-US"; } if (lang == 5) { cLang = "ja-JP"; } if (lang == 6) { cLang = "zh-CN"; } if (lang == 7) { cLang = "ko-KR"; } if (lang == 9) { cLang = "zh-TW"; } if (lang == 13) { cLang = "el-EL"; } if (lang == 15) { cLang = "ne-NP"; } pangoLang = pango_language_from_string(cLang); pangoAttr = pango_attr_language_new(pangoLang); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } static sqInt addSelectionAtpixelwith(PangoRectangle *rect, unsigned int c, cairo_t*context) { sqInt a; sqInt r; sqInt b; sqInt g; a = ((usqInt) (c & 4278190080U)) >> 24; if (a == 0) { return null; } r = ((usqInt) (c & 16711680)) >> 16; g = ((usqInt) (c & 65280)) >> 8; b = c & 255; cairo_save(context); cairo_set_source_rgba(context, r / 255.0, g / 255.0, b / 255.0, a / 255.0); cairo_new_path(context); cairo_move_to(context, PANGO_PIXELS(rect->x) + 1, PANGO_PIXELS(rect->y)); cairo_line_to(context, PANGO_PIXELS(rect->x) + 1, PANGO_PIXELS(rect->y+rect->height)); cairo_stroke(context); cairo_restore(context); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } } static sqInt addSelectionFromtopixelinto(sqInt start, sqInt end, unsigned int c, PangoAttrList *pangoAttrList) { sqInt r; sqInt b; PangoAttribute *pangoAttr; sqInt g; sqInt alpha; alpha = ((usqInt) (c && 4278190080U)) >> 24; r = ((usqInt) (c & 16711680)) >> 16; g = ((usqInt) (c & 65280)) >> 8; b = c & 255; if ((alpha == 0) && ((r == 0) && ((g == 0) && (b == 0)))) { return null; } if (!(r == 0)) { r = r * 257; } if (!(g == 0)) { g = g * 257; } if (!(b == 0)) { b = b * 257; } pangoAttr = pango_attr_background_new(r, g, b); pangoAttr->start_index = start; pangoAttr->end_index = end; pango_attr_list_change(pangoAttrList, pangoAttr); } /* Get contexts[canvasOop's handle] */ static cairo_t* contextFrom(sqInt canvasOop) { cairo_t*context; sqInt contextIndex; sqInt targetOop; if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) { fail("canvas oop invalid"); return null; } contextIndex = interpreterProxy->fetchIntegerofObject(CanvasHandleIndex, canvasOop); if (interpreterProxy->failed()) { contextIndex = interpreterProxy->fetchPointerofObject(CanvasHandleIndex, canvasOop); if (!(contextIndex == (interpreterProxy->nilObject()))) { fail("canvas handle not an integer"); } return null; } if ((contextIndex < 0) || (contextIndex > (lastIndex(contexts)))) { failwith("canvas handle %i out of bounds", contextIndex); return null; } context = contexts[contextIndex]; if (context == null) { failwith("canvas handle %i invalid", contextIndex); return null; } if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } targetOop = interpreterProxy->fetchPointerofObject(CanvasTargetIndex, canvasOop); if (!((surfaceFrom(targetOop)) == (cairo_get_target(context)))) { failwith("canvas handle %i does not match target", contextIndex); return null; } return context; } static sqInt createContextFor(sqInt canvasOop) { sqInt i; cairo_surface_t*targetSurface; cairo_t*context; sqInt targetID; sqInt contextIndex; sqInt targetOop; if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) { fail("canvas oop invalid"); return null; } targetOop = interpreterProxy->fetchPointerofObject(CanvasTargetIndex, canvasOop); if ((interpreterProxy->slotSizeOf(targetOop)) <= FormBitsIndex) { fail("target oop invalid"); return null; } targetID = interpreterProxy->fetchIntegerofObject(FormBitsIndex, targetOop); if (interpreterProxy->failed()) { fail("target handle not an integer"); return null; } targetSurface = findSurface(targetID); if (!((targetSurface != null) && ((cairo_surface_status(targetSurface)) == 0))) { fail("target surface invalid"); return null; } contextIndex = -1; i = 0; while (i <= (lastIndex(contexts))) { if ((contexts[i]) == null) { contextIndex = i; i = lastIndex(contexts); } i += 1; } if (contextIndex < 0) { fail("too many canvases"); return null; } context = cairo_create(targetSurface); contexts[contextIndex] = context; /* missing DebugCode */; return contextIndex; } /* create a surface, register it in SurfacePlugin and answer its surface plugin ID */ static sqInt createSurfaceFor(sqInt formOop) { cairo_format_t format; sqInt bits; sqInt width; sqInt status; cairo_surface_t*surface; sqInt height; sqInt depth; if ((interpreterProxy->slotSizeOf(formOop)) < FormInstSize) { fail("form oop invalid"); return -1; } width = interpreterProxy->fetchIntegerofObject(FormWidthIndex, formOop); height = interpreterProxy->fetchIntegerofObject(FormHeightIndex, formOop); depth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, formOop); if (interpreterProxy->failed()) { fail("form fields are not integers"); return -1; } switch(depth) { case 32: format = CAIRO_FORMAT_ARGB32; break; case 24: format = CAIRO_FORMAT_RGB24; break; case 16: format = CAIRO_FORMAT_RGB16_565; break; case 8: format = CAIRO_FORMAT_A8; break; case 1: format = CAIRO_FORMAT_A1; break; default: format = -1; } if ((width <= 0) || ((height <= 0) || (format < 0))) { fail("form fields out of range"); return -1; } bits = interpreterProxy->fetchPointerofObject(FormBitsIndex, formOop); if (!(bits == (interpreterProxy->nilObject()))) { fail("form handle not nil"); return -1; } surface = cairo_image_surface_create(format, width, height); status = cairo_surface_status(surface); if (!(status == 0)) { failwith("failed to create surface - %s", cairo_status_to_string(status)); cairo_surface_destroy(surface); return -1; } return registerSurface(surface); } static sqInt destroyContextFor(sqInt canvasOop) { cairo_t*context; sqInt contextIndex; if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) { fail("canvas oop invalid"); return null; } contextIndex = interpreterProxy->fetchIntegerofObject(CanvasHandleIndex, canvasOop); if (interpreterProxy->failed()) { fail("canvas handle not an integer"); return null; } if ((contextIndex < 0) || (contextIndex > (lastIndex(contexts)))) { failwith("canvas handle %i out of bounds", contextIndex); return null; } context = contexts[contextIndex]; if (context == null) { failwith("canvas handle %i invalid", contextIndex); return null; } /* missing DebugCode */; cairo_destroy(context); contexts[contextIndex] = null; return null; } /* fetch surface from surfaceID, destroy it and unregister from SurfacePlugin */ static sqInt destroySurface(sqInt surfaceID) { cairo_surface_t*surface; surface = findSurface(surfaceID); if (surface == null) { failwith("could not find surface %i", surfaceID); return null; } cairo_surface_destroy(surface); unregisterSurface(surfaceID); return null; } /* fill or stroke depending on canvasOop's flags */ static void fillOrStrokefrom(cairo_t*context, sqInt canvasOop) { sqInt stroke; sqInt canvasFlags; sqInt fill; sqInt rgb; canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop); if (interpreterProxy->failed()) { fail("canvas flags not an integer"); } else { fill = canvasFlags & CanvasFlagFill; stroke = canvasFlags & CanvasFlagStroke; if (fill != 0) { if (stroke != 0) { cairo_fill_preserve(context); } else { cairo_fill(context); } } if (stroke != 0) { rgb = interpreterProxy->fetchIntegerofObject(CanvasStrokeColorIndex, canvasOop); cairo_save(context); setSourcergbalpha(context, rgb, stroke); cairo_stroke(context); cairo_restore(context); } } } /* Answer surface handle for surfaceID */ static cairo_surface_t* findSurface(sqInt surfaceID) { sqInt surfaceHandle; if (findSurfaceFn == null) { if (!(loadSurfacePlugin())) { return null; } } if (!((*findSurfaceFn)(surfaceID, &surfaceDispatch, &surfaceHandle))) { return null; } return ((cairo_surface_t*) surfaceHandle); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt getSurfaceFormatgetWgetHgetDgetMsb(cairo_surface_t *surfaceHandle, int*wReturn, int*hReturn, int*dReturn, int*mReturn) { sqInt msb; sqInt width; sqInt depth; sqInt height; /* missing DebugCode */; width = cairo_image_surface_get_width(surfaceHandle); height = cairo_image_surface_get_height(surfaceHandle); depth = formatToDepth[cairo_image_surface_get_format(surfaceHandle)]; msb = 1; *wReturn = width; *hReturn = height; *dReturn = depth; *mReturn = msb; return 1; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { sqInt i; for (i = 0; i <= (lastIndex(contexts)); i += 1) { contexts[i] = null; } for (i = 0; i <= (lastIndex(fontDescriptions)); i += 1) { fontDescriptions[i] = null; } defaultFontDescription = pango_font_description_from_string("Times New Roman 10"); registerSurfaceFn = null; unregisterSurfaceFn = null; findSurfaceFn = null; return 1; } static sqInt leadingCharOf(unsigned int value) { return ((usqInt) (value & 1069547520) >> 22); } /* Load the surface support plugin */ static sqInt loadSurfacePlugin(void) { sqInt found; registerSurfaceFn = ((fn_ioRegisterSurface) (interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface", "SurfacePlugin"))); unregisterSurfaceFn = ((fn_ioUnregisterSurface) (interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface", "SurfacePlugin"))); findSurfaceFn = ((fn_ioFindSurface) (interpreterProxy->ioLoadFunctionFrom("ioFindSurface", "SurfacePlugin"))); found = (registerSurfaceFn != null) && ((unregisterSurfaceFn != null) && (findSurfaceFn != null)); if (!(found)) { fail("could not load SurfacePlugin"); } maxSurfaceID = -1; return found; } static unsigned char* lockSurfacegetPitchxywh(cairo_surface_t*surfaceHandle, int*pitchReturn, sqInt x, sqInt y, sqInt w, sqInt h) { sqInt pitch; unsigned char*data; /* missing DebugCode */; cairo_surface_flush(surfaceHandle); data = cairo_image_surface_get_data(surfaceHandle); pitch = cairo_image_surface_get_stride(surfaceHandle); *pitchReturn = pitch; return data; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SurfacePlugin")) == 0) { registerSurfaceFn = null; unregisterSurfaceFn = null; findSurfaceFn = null; } return 1; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } static void polyPathfrom(cairo_t*context, sqInt pointsOop) { float*points; sqInt i; sqInt pointsCount; points = interpreterProxy->arrayValueOf(pointsOop); pointsCount = interpreterProxy->slotSizeOf(pointsOop); if (!(interpreterProxy->failed())) { if (pointsCount >= 2) { cairo_move_to(context, points[0], points[1]); for (i = 2; i <= (pointsCount - 1); i += 2) { cairo_line_to(context, points[i], points[i + 1]); } } } } EXPORT(sqInt) primitivePangoBlockAtIndex(void) { sqInt index; cairo_t*context; sqInt origin; unsigned char*aString; sqInt trailing; sqInt aStringOop; sqInt stringLength; PangoAttrList*attrList; sqInt atEnd; PangoLayout*layout; sqInt canvasOop; sqInt corner; sqInt charData; PangoRectangle pos; sqInt inStringOop; sqInt utf8Index; sqInt x; sqInt y; sqInt sqAttrArray; sqInt w; sqInt h; sqInt withWrap; sqInt cData; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(8), "Object")); inStringOop = interpreterProxy->stackValue(8); utf8Index = interpreterProxy->stackIntegerValue(7); x = interpreterProxy->stackIntegerValue(6); y = interpreterProxy->stackIntegerValue(5); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object")); sqAttrArray = interpreterProxy->stackValue(4); w = interpreterProxy->stackIntegerValue(3); h = interpreterProxy->stackIntegerValue(2); withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); cData = interpreterProxy->stackValue(0); ; canvasOop = interpreterProxy->stackValue(9); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } aStringOop = inStringOop; aString = interpreterProxy->firstIndexableField(aStringOop); layout = pango_cairo_create_layout(context); attrList = pango_attr_list_new(); translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList); pango_layout_set_text(layout, aString, strlen(aString)); pango_layout_set_attributes(layout, attrList); pango_layout_set_width(layout, w * (PANGO_SCALE)); if (withWrap) { pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); } cairo_translate(context, x, y); pango_cairo_update_layout(context, layout); stringLength = strlen(aString); if (utf8Index == (stringLength + 1)) { atEnd = 1; pango_layout_index_to_pos(layout, ((((((utf8Index - 1) < 0) ? 0 : (utf8Index - 1))) < stringLength) ? ((((utf8Index - 1) < 0) ? 0 : (utf8Index - 1))) : stringLength), &pos); pos.x = pos.x + pos.width; } else { atEnd = 0; pango_layout_index_to_pos(layout, (((((utf8Index < 0) ? 0 : utf8Index)) < stringLength) ? (((utf8Index < 0) ? 0 : utf8Index)) : stringLength), &pos); } pango_attr_list_unref(attrList); g_object_unref(layout); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } interpreterProxy->pushRemappableOop(aStringOop); interpreterProxy->pushRemappableOop(cData); origin = interpreterProxy->makePointwithxValueyValue((PANGO_PIXELS(pos.x)) + x, (PANGO_PIXELS(pos.y)) + y); interpreterProxy->pushRemappableOop(origin); corner = interpreterProxy->makePointwithxValueyValue((PANGO_PIXELS(pos.x+pos.width)) + x, (PANGO_PIXELS(pos.y+pos.height)) + y); origin = interpreterProxy->popRemappableOop(); charData = interpreterProxy->popRemappableOop(); aStringOop = interpreterProxy->popRemappableOop(); aString = interpreterProxy->firstIndexableField(aStringOop); interpreterProxy->storePointerofObjectwithValue(0, charData, origin); interpreterProxy->storePointerofObjectwithValue(1, charData, corner); index = sqCharCountInfromto(aString, 0, utf8Index); if (!(atEnd)) { index += 1; } interpreterProxy->storePointerofObjectwithValue(2, charData, ((index << 1) | 1)); _return_value = interpreterProxy->integerObjectOf(index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(10, _return_value); return null; } EXPORT(sqInt) primitiveClear(void) { sqInt op; sqInt canvasFlags; sqInt fill; cairo_t*context; sqInt canvasOop; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop); if (interpreterProxy->failed()) { fail("canvas flags not an integer"); return null; } fill = canvasFlags & CanvasFlagFill; if (!(fill)) { cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.0); } op = cairo_get_operator(context); cairo_set_operator(context, CairoOperatorSource); cairo_paint(context); cairo_set_operator(context, op); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitiveClipRectangleLeftRightTopBottom(void) { cairo_t*context; sqInt canvasOop; double left; double right; double top; double bottom; left = interpreterProxy->stackFloatValue(3); right = interpreterProxy->stackFloatValue(2); top = interpreterProxy->stackFloatValue(1); bottom = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); cairo_rectangle(context, left, top, right - left, bottom - top); cairo_clip(context); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } EXPORT(sqInt) primitiveClose(void) { sqInt canvasOop; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } destroyContextFor(canvasOop); if (!(interpreterProxy->failed())) { interpreterProxy->storePointerofObjectwithValue(CanvasHandleIndex, canvasOop, interpreterProxy->nilObject()); } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitivePangoComposeString(void) { cairo_t*context; sqInt linesSize; sqInt newW; sqInt sqStart; sqInt lineCount; PangoRectangle ink; sqInt start; sqInt lineIndex; PangoAttrList*attrList; sqInt sqEnd; sqInt baseline; PangoLayoutLine*line; PangoRectangle logical; sqInt totalY; sqInt prevBaseline; PangoLayout*layout; sqInt lastLine; sqInt canvasOop; sqInt addition; PangoLayoutIter*lineIter; sqInt next; char *aString; sqInt x; sqInt y; sqInt sqAttrArray; sqInt w; sqInt h; sqInt withWrap; sqInt lines; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(7))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(7)))); x = interpreterProxy->stackIntegerValue(6); y = interpreterProxy->stackIntegerValue(5); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object")); sqAttrArray = interpreterProxy->stackValue(4); w = interpreterProxy->stackIntegerValue(3); h = interpreterProxy->stackIntegerValue(2); withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); lines = interpreterProxy->stackValue(0); ; canvasOop = interpreterProxy->stackValue(8); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } layout = pango_cairo_create_layout(context); attrList = pango_attr_list_new(); translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList); pango_layout_set_text(layout, aString, strlen(aString)); pango_layout_set_attributes(layout, attrList); pango_layout_set_width(layout, w * (PANGO_SCALE)); if (withWrap) { pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); } cairo_translate(context, x, y); pango_cairo_update_layout(context, layout); lineCount = pango_layout_get_line_count(layout); lineIter = pango_layout_get_iter(layout); baseline = pango_layout_iter_get_baseline(lineIter); prevBaseline = 0; cairo_translate(context, 0, PANGO_PIXELS(baseline)); sqEnd = 0; totalY = 0; linesSize = interpreterProxy->stSizeOf(lines); lastLine = (((lineCount < linesSize) ? lineCount : linesSize)) - 1; for (lineIndex = 0; lineIndex <= lastLine; lineIndex += 1) { line = pango_layout_iter_get_line_readonly(lineIter); pango_layout_line_get_extents(line, &ink, &logical); sqStart = sqEnd + 1; start = line->start_index; /* self log: 'sqStart, sqEnd: %d %d' with: sqStart with: sqEnd. */ sqEnd = (sqStart + (sqCharCountInfromto(aString, start, start + (line->length)))) - 1; if (((start + (line->length)) < (interpreterProxy->stSizeOf(((int) aString)))) && ((aString[start + (line->length)]) == 13)) { sqEnd += 1; } interpreterProxy->storeIntegerofObjectwithValue(TextLineStartIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), sqStart); interpreterProxy->storeIntegerofObjectwithValue(TextLineEndIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), sqEnd); interpreterProxy->storeIntegerofObjectwithValue(TextLineLeftIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), (PANGO_PIXELS(logical.x)) + x); interpreterProxy->storeIntegerofObjectwithValue(TextLineRightIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), (PANGO_PIXELS(logical.x+logical.width)) + x); interpreterProxy->storeIntegerofObjectwithValue(TextLineTopIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), totalY + y); interpreterProxy->storeIntegerofObjectwithValue(TextLineInternalSpaceIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), ((0 << 1) | 1)); interpreterProxy->storeIntegerofObjectwithValue(TextLinePaddingWidthIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), ((0 << 1) | 1)); next = pango_layout_iter_next_line(lineIter); if (next) { addition = (logical.height) + (pango_layout_get_spacing(layout)); } else { addition = logical.height; } totalY += PANGO_PIXELS(addition); interpreterProxy->storeIntegerofObjectwithValue(TextLineBottomIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), totalY + y); } pango_layout_get_extents(layout, &ink, &logical); newW = PANGO_PIXELS(logical.width); pango_layout_iter_free(lineIter); pango_attr_list_unref(attrList); g_object_unref(layout); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } _return_value = interpreterProxy->integerObjectOf(newW); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(9, _return_value); return null; } EXPORT(sqInt) primitivePangoComposeString2(void) { cairo_t*context; sqInt newW; sqInt sqStart; sqInt lineCount; PangoRectangle ink; unsigned char*aString; unsigned char*inString; sqInt start; sqInt lineIndex; PangoAttrList*attrList; sqInt sqEnd; sqInt baseline; PangoLayoutLine*line; PangoRectangle logical; sqInt totalY; sqInt prevBaseline; sqInt arrayOop; sqInt retArrayOop; sqInt textLine; sqInt i; PangoLayout*layout; sqInt lastLine; sqInt canvasOop; sqInt addition; sqInt textLineClass; sqInt inStringSize; PangoLayoutIter*lineIter; sqInt next; sqInt inStringOop; sqInt x; sqInt y; sqInt sqAttrArray; sqInt w; sqInt h; sqInt withWrap; sqInt inTextLineClass; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(7), "Object")); inStringOop = interpreterProxy->stackValue(7); x = interpreterProxy->stackIntegerValue(6); y = interpreterProxy->stackIntegerValue(5); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object")); sqAttrArray = interpreterProxy->stackValue(4); w = interpreterProxy->stackIntegerValue(3); h = interpreterProxy->stackIntegerValue(2); withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); inTextLineClass = interpreterProxy->stackValue(0); ; canvasOop = interpreterProxy->stackValue(8); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } inStringSize = interpreterProxy->stSizeOf(inStringOop); if (inStringSize == 0) { primitiveFail(); return null; } aString = alloca(inStringSize); inString = interpreterProxy->firstIndexableField(inStringOop); strncpy(aString, inString, inStringSize); textLineClass = inTextLineClass; layout = pango_cairo_create_layout(context); attrList = pango_attr_list_new(); translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList); pango_layout_set_text(layout, aString, strlen(aString)); pango_layout_set_attributes(layout, attrList); pango_layout_set_width(layout, w * (PANGO_SCALE)); if (withWrap) { pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); } cairo_translate(context, x, y); pango_cairo_update_layout(context, layout); lineCount = pango_layout_get_line_count(layout); lineIter = pango_layout_get_iter(layout); baseline = pango_layout_iter_get_baseline(lineIter); prevBaseline = 0; cairo_translate(context, 0, PANGO_PIXELS(baseline)); sqEnd = 0; totalY = 0; interpreterProxy->pushRemappableOop(textLineClass); arrayOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), lineCount); textLineClass = interpreterProxy->popRemappableOop(); for (i = 0; i <= (lineCount - 1); i += 1) { interpreterProxy->pushRemappableOop(textLineClass); interpreterProxy->pushRemappableOop(arrayOop); textLine = interpreterProxy->instantiateClassindexableSize(textLineClass, 0); arrayOop = interpreterProxy->popRemappableOop(); textLineClass = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(i, arrayOop, textLine); } lastLine = lineCount - 1; for (lineIndex = 0; lineIndex <= lastLine; lineIndex += 1) { line = pango_layout_iter_get_line_readonly(lineIter); pango_layout_line_get_extents(line, &ink, &logical); sqStart = sqEnd + 1; start = line->start_index; /* self log: 'sqStart, sqEnd: %d %d' with: sqStart with: sqEnd. */ sqEnd = (sqStart + (sqCharCountInfromto(aString, start, start + (line->length)))) - 1; if (((start + (line->length)) < (interpreterProxy->stSizeOf(((int) aString)))) && ((aString[start + (line->length)]) == 13)) { sqEnd += 1; } interpreterProxy->storeIntegerofObjectwithValue(TextLineStartIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), sqStart); interpreterProxy->storeIntegerofObjectwithValue(TextLineEndIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), sqEnd); interpreterProxy->storeIntegerofObjectwithValue(TextLineLeftIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), (PANGO_PIXELS(logical.x)) + x); interpreterProxy->storeIntegerofObjectwithValue(TextLineRightIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), (PANGO_PIXELS(logical.x+logical.width)) + x); interpreterProxy->storeIntegerofObjectwithValue(TextLineTopIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), totalY + y); interpreterProxy->storeIntegerofObjectwithValue(TextLineInternalSpaceIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), ((0 << 1) | 1)); interpreterProxy->storeIntegerofObjectwithValue(TextLinePaddingWidthIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), ((0 << 1) | 1)); next = pango_layout_iter_next_line(lineIter); if (next) { addition = (logical.height) + (pango_layout_get_spacing(layout)); } else { addition = logical.height; } totalY += PANGO_PIXELS(addition); interpreterProxy->storeIntegerofObjectwithValue(TextLineBottomIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), totalY + y); } pango_layout_get_extents(layout, &ink, &logical); newW = PANGO_PIXELS(logical.width); pango_layout_iter_free(lineIter); pango_attr_list_unref(attrList); g_object_unref(layout); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } interpreterProxy->pushRemappableOop(arrayOop); retArrayOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); arrayOop = interpreterProxy->popRemappableOop(); interpreterProxy->storeIntegerofObjectwithValue(0, retArrayOop, newW); interpreterProxy->storePointerofObjectwithValue(1, retArrayOop, arrayOop); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(9, retArrayOop); return null; } EXPORT(sqInt) primitiveCreateFormHandle(void) { sqInt formOop; sqInt surfaceID; sqInt _return_value; formOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } surfaceID = createSurfaceFor(formOop); if (surfaceID < 0) { interpreterProxy->primitiveFail(); } if (!(interpreterProxy->failed())) { _return_value = interpreterProxy->integerObjectOf(surfaceID); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitiveDestroyFormHandle(void) { sqInt surfaceID; surfaceID = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->failed())) { destroySurface(surfaceID); } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveDrawArcRadiusXYFromTo(void) { cairo_t*context; sqInt canvasOop; double radius; double x; double y; double angle1; double angle2; radius = interpreterProxy->stackFloatValue(4); x = interpreterProxy->stackFloatValue(3); y = interpreterProxy->stackFloatValue(2); angle1 = interpreterProxy->stackFloatValue(1); angle2 = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); if (radius > 0.0) { cairo_arc(context, x, y, radius, angle1, angle2); } else { cairo_arc_negative(context, x, y, -1.0 * radius, angle1, angle2); } fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); return null; } EXPORT(sqInt) primitiveDrawCurveFromXYviaXYandXYtoXY(void) { cairo_t*context; sqInt canvasOop; double x0; double y0; double x1; double y1; double x2; double y2; double x3; double y3; x0 = interpreterProxy->stackFloatValue(7); y0 = interpreterProxy->stackFloatValue(6); x1 = interpreterProxy->stackFloatValue(5); y1 = interpreterProxy->stackFloatValue(4); x2 = interpreterProxy->stackFloatValue(3); y2 = interpreterProxy->stackFloatValue(2); x3 = interpreterProxy->stackFloatValue(1); y3 = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(8); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); cairo_move_to(context, x0, y0); cairo_curve_to(context, x1, y1, x2, y2, x3, y3); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(8); return null; } EXPORT(sqInt) primitiveDrawCurveFromXYviaXYtoXY(void) { cairo_t*context; sqInt canvasOop; double x0; double y0; double x1; double y1; double x2; double y2; x0 = interpreterProxy->stackFloatValue(5); y0 = interpreterProxy->stackFloatValue(4); x1 = interpreterProxy->stackFloatValue(3); y1 = interpreterProxy->stackFloatValue(2); x2 = interpreterProxy->stackFloatValue(1); y2 = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); cairo_move_to(context, x0, y0); cairo_curve_to(context, ((2.0 * x1) + x0) / 3.0, ((2.0 * y1) + y0) / 3.0, ((2.0 * x1) + x2) / 3.0, ((2.0 * y1) + y2) / 3.0, x2, y2); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); return null; } EXPORT(sqInt) primitiveDrawGeneralBezierShape(void) { cairo_t*context; sqInt shapeCount; sqInt segmentCount; short*seg; sqInt j; sqInt yVia; sqInt i; sqInt xFrom; sqInt contourOop; sqInt canvasOop; sqInt xTo; sqInt yTo; sqInt xVia; sqInt yFrom; sqInt shapeOop; shapeOop = interpreterProxy->stackValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } shapeCount = interpreterProxy->slotSizeOf(shapeOop); cairo_new_path(context); for (i = 0; i <= (shapeCount - 1); i += 1) { contourOop = interpreterProxy->fetchPointerofObject(i, shapeOop); if (!(interpreterProxy->isMemberOf(contourOop, "ShortPointArray"))) { failwith("bezier contour %i is no ShortPointArray", i + 1); return null; } segmentCount = (interpreterProxy->slotSizeOf(contourOop)) / 3; seg = interpreterProxy->arrayValueOf(contourOop); for (j = 0; j <= (segmentCount - 1); j += 1) { xFrom = seg[0]; yFrom = seg[1]; xVia = seg[2]; yVia = seg[3]; xTo = seg[4]; yTo = seg[5]; if (j == 0) { cairo_move_to(context, xFrom, yFrom); } if ((xFrom == xVia) && (yFrom == yVia)) { cairo_line_to(context, xTo, yTo); } else { cairo_curve_to(context, (xFrom + (2.0 * xVia)) / 3.0, (yFrom + (2.0 * yVia)) / 3.0, ((2.0 * xVia) + xTo) / 3.0, ((2.0 * yVia) + yTo) / 3.0, xTo, yTo); } seg += 6; } cairo_close_path(context); } fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveDrawImageSrcLRTBDestLRTB(void) { cairo_surface_t*srcSurface; cairo_t*context; sqInt canvasOop; sqInt formOop; double dstL; double dstR; double dstT; double dstB; double srcL; double srcR; double srcT; double srcB; formOop = interpreterProxy->stackValue(8); dstL = interpreterProxy->stackFloatValue(7); dstR = interpreterProxy->stackFloatValue(6); dstT = interpreterProxy->stackFloatValue(5); dstB = interpreterProxy->stackFloatValue(4); srcL = interpreterProxy->stackFloatValue(3); srcR = interpreterProxy->stackFloatValue(2); srcT = interpreterProxy->stackFloatValue(1); srcB = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(9); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } srcSurface = surfaceFrom(formOop); if (!((srcSurface != null) && ((cairo_surface_status(srcSurface)) == 0))) { fail("source surface invalid"); return null; } if ((srcR != srcL) && (srcT != srcB)) { cairo_save(context); cairo_translate(context, dstL, dstT); cairo_scale(context, (dstR - dstL) / (srcR - srcL), (dstB - dstT) / (srcB - srcT)); cairo_new_path(context); cairo_rectangle(context, 0.0, 0.0, srcR - srcL, srcB - srcT); cairo_set_source_surface(context, srcSurface, 0.0 - srcL, 0.0 - srcT); cairo_fill(context); cairo_restore(context); } if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(9); return null; } EXPORT(sqInt) primitiveDrawLineFromXYtoXY(void) { cairo_t*context; sqInt canvasOop; double fromX; double fromY; double toX; double toY; fromX = interpreterProxy->stackFloatValue(3); fromY = interpreterProxy->stackFloatValue(2); toX = interpreterProxy->stackFloatValue(1); toY = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); cairo_move_to(context, fromX, fromY); cairo_line_to(context, toX, toY); strokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } EXPORT(sqInt) primitiveDrawOvalLeftRightTopBottom(void) { cairo_t*context; sqInt canvasOop; double left; double right; double top; double bottom; left = interpreterProxy->stackFloatValue(3); right = interpreterProxy->stackFloatValue(2); top = interpreterProxy->stackFloatValue(1); bottom = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } if ((right != left) && (top != bottom)) { cairo_save(context); cairo_new_path(context); cairo_translate(context, (left + right) / 2.0, (top + bottom) / 2.0); cairo_scale(context, (right - left) / 2.0, (bottom - top) / 2.0); cairo_arc(context, 0.0, 0.0, 1.0, 0.0, degrees(360.0)); cairo_restore(context); fillOrStrokefrom(context, canvasOop); } if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } EXPORT(sqInt) primitiveDrawPolygon(void) { cairo_t*context; sqInt canvasOop; sqInt pointsOop; pointsOop = interpreterProxy->stackValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); polyPathfrom(context, pointsOop); cairo_close_path(context); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveDrawPolyline(void) { cairo_t*context; sqInt canvasOop; sqInt pointsOop; pointsOop = interpreterProxy->stackValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); polyPathfrom(context, pointsOop); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveDrawRectangleLeftRightTopBottom(void) { cairo_t*context; sqInt canvasOop; double left; double right; double top; double bottom; left = interpreterProxy->stackFloatValue(3); right = interpreterProxy->stackFloatValue(2); top = interpreterProxy->stackFloatValue(1); bottom = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(4); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_new_path(context); cairo_rectangle(context, left, top, right - left, bottom - top); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(4); return null; } /* x1 x2 x3 x4 y1 + / - \ + y2 / . . \ | | y3 \ . . / y4 + \ - / + */ EXPORT(sqInt) primitiveDrawRoundRectLeftRightTopBottomRadiusCorner(void) { cairo_t*context; double y3; double y2; double x3; double x2; sqInt canvasOop; double ry; double rx; double r; double x1; double x4; double y1; double y4; double radius; sqInt cornerFlags; x1 = interpreterProxy->stackFloatValue(5); x4 = interpreterProxy->stackFloatValue(4); y1 = interpreterProxy->stackFloatValue(3); y4 = interpreterProxy->stackFloatValue(2); radius = interpreterProxy->stackFloatValue(1); cornerFlags = interpreterProxy->stackIntegerValue(0); canvasOop = interpreterProxy->stackValue(6); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } rx = (x4 - x1) / 2.0; ry = (y4 - y1) / 2.0; r = (((((radius < rx) ? radius : rx)) < ry) ? (((radius < rx) ? radius : rx)) : ry); x2 = x1 + r; x3 = x4 - r; y2 = y1 + r; y3 = y4 - r; cairo_new_path(context); if (cornerFlags & 1) { cairo_arc(context, x2, y2, r, degrees(180), degrees(270)); } else { cairo_move_to(context, x1, y1); } if (cornerFlags & 8) { cairo_arc(context, x3, y2, r, degrees(270), degrees(360)); } else { cairo_line_to(context, x4, y1); } if (cornerFlags & 4) { cairo_arc(context, x3, y3, r, degrees(0), degrees(90)); } else { cairo_line_to(context, x4, y4); } if (cornerFlags & 2) { cairo_arc(context, x2, y3, r, degrees(90), degrees(180)); } else { cairo_line_to(context, x1, y4); } cairo_close_path(context); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(6); return null; } /* draw a string including its outline if selected */ EXPORT(sqInt) primitiveDrawZeroTerminatedUtf8StringXY(void) { cairo_t*context; sqInt canvasOop; char *aString; double x; double y; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); x = interpreterProxy->stackFloatValue(1); y = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_move_to(context, x, y); cairo_text_path(context, aString); fillOrStrokefrom(context, canvasOop); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage(void) { cairo_pattern_t*pattern; cairo_t*context; sqInt canvasOop; cairo_matrix_t*m; cairo_matrix_t mdata; cairo_surface_t*surface; double ox; double oy; double dx; double dy; double nx; double ny; sqInt aBoolean; sqInt formOop; ox = interpreterProxy->stackFloatValue(7); oy = interpreterProxy->stackFloatValue(6); dx = interpreterProxy->stackFloatValue(5); dy = interpreterProxy->stackFloatValue(4); nx = interpreterProxy->stackFloatValue(3); ny = interpreterProxy->stackFloatValue(2); aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); formOop = interpreterProxy->stackValue(0); m = &mdata; canvasOop = interpreterProxy->stackValue(8); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } surface = surfaceFrom(formOop); if (!((surface != null) && ((cairo_surface_status(surface)) == 0))) { fail("surface invalid"); return null; } pattern = cairo_pattern_create_for_surface(surface); cairo_matrix_init(m, dx, dy, nx, ny, ox, oy); cairo_matrix_invert(m); cairo_pattern_set_matrix(pattern, m); if (aBoolean) { cairo_pattern_set_extend(pattern, CairoExtendRepeat); } if (cairo_pattern_status(pattern)) { failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern))); return null; } cairo_set_source(context, pattern); cairo_pattern_destroy(pattern); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(8); return null; } EXPORT(sqInt) primitiveFillColorAlpha(void) { cairo_t*context; sqInt canvasOop; sqInt rgb; sqInt alpha; rgb = interpreterProxy->stackIntegerValue(1); alpha = interpreterProxy->stackIntegerValue(0); canvasOop = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } setSourcergbalpha(context, rgb, alpha); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveFillLinearOriginXYdirectionXYcolorStops(void) { cairo_pattern_t*pattern; int*colorStops; sqInt i; sqInt colorStopsCount; cairo_t*context; sqInt canvasOop; double ox; double oy; double dx; double dy; sqInt colorStopsOop; ox = interpreterProxy->stackFloatValue(4); oy = interpreterProxy->stackFloatValue(3); dx = interpreterProxy->stackFloatValue(2); dy = interpreterProxy->stackFloatValue(1); colorStopsOop = interpreterProxy->stackValue(0); canvasOop = interpreterProxy->stackValue(5); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } colorStops = interpreterProxy->arrayValueOf(colorStopsOop); colorStopsCount = interpreterProxy->slotSizeOf(colorStopsOop); if (interpreterProxy->failed()) { fail("bad colorStops array"); return null; } pattern = cairo_pattern_create_linear(ox, oy, ox + dx, oy + dy); if (cairo_pattern_status(pattern)) { failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern))); return null; } for (i = 0; i <= (colorStopsCount - 1); i += 3) { addColorStopTooffsetrgbalpha(pattern, colorStops[i], colorStops[i + 1], colorStops[i + 2]); } cairo_set_source(context, pattern); cairo_pattern_destroy(pattern); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(5); return null; } EXPORT(sqInt) primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops(void) { int*colorStops; cairo_t*context; sqInt colorStopsCount; cairo_matrix_t*m; cairo_matrix_t mdata; sqInt i; sqInt canvasOop; cairo_pattern_t*pattern; double ox; double oy; double dx; double dy; double nx; double ny; sqInt colorStopsOop; ox = interpreterProxy->stackFloatValue(6); oy = interpreterProxy->stackFloatValue(5); dx = interpreterProxy->stackFloatValue(4); dy = interpreterProxy->stackFloatValue(3); nx = interpreterProxy->stackFloatValue(2); ny = interpreterProxy->stackFloatValue(1); colorStopsOop = interpreterProxy->stackValue(0); m = &mdata; canvasOop = interpreterProxy->stackValue(7); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } colorStops = interpreterProxy->arrayValueOf(colorStopsOop); colorStopsCount = interpreterProxy->slotSizeOf(colorStopsOop); if (interpreterProxy->failed()) { fail("bad colorStops array"); return null; } pattern = cairo_pattern_create_radial(0.0, 0.0, 0.0, 0.0, 0.0, 1.0); cairo_matrix_init(m, dx, dy, nx, ny, ox, oy); cairo_matrix_invert(m); cairo_pattern_set_matrix(pattern, m); if (cairo_pattern_status(pattern)) { failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern))); return null; } for (i = 0; i <= (colorStopsCount - 1); i += 3) { addColorStopTooffsetrgbalpha(pattern, colorStops[i], colorStops[i + 1], colorStops[i + 2]); } cairo_set_source(context, pattern); cairo_pattern_destroy(pattern); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(7); return null; } EXPORT(sqInt) primitiveFontFace(void) { cairo_font_face_t*crFace; FT_Face ftFace; cairo_t*context; sqInt canvasOop; char *faceHandle; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0))); faceHandle = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0)))); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } ftFace = *(void**)faceHandle; crFace = cairo_ft_font_face_create_for_ft_face(ftFace, FT_LOAD_NO_HINTING); cairo_set_font_face(context, crFace); cairo_font_face_destroy(crFace); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveFontSize(void) { cairo_t*context; sqInt canvasOop; double size; size = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_set_font_size(context, size); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveGetLineWidth(void) { double width; cairo_t*context; sqInt canvasOop; sqInt _return_value; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } width = cairo_get_line_width(context); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } _return_value = interpreterProxy->floatObjectOf(width); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitivePangoFontDescriptionIndex(void) { sqInt familyNameSize; sqInt newInd; PangoFontDescription *desc; sqInt i; sqInt ind; char cFamilyName[128]; sqInt size; sqInt pangoStyle; char *familyName; sqInt isAbsolute; sqInt familyNameOop; sqInt ptSize; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object")); familyNameOop = interpreterProxy->stackValue(1); ptSize = interpreterProxy->stackIntegerValue(0); ; if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { return null; } familyNameSize = interpreterProxy->stSizeOf(familyNameOop); if (familyNameSize > 127) { return null; } if ((ptSize < 0) || (ptSize > 1000000)) { _return_value = ((-1 << 1) | 1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } familyName = interpreterProxy->firstIndexableField(familyNameOop); for (i = 0; i <= (familyNameSize - 1); i += 1) { cFamilyName[i] = (familyName[i]); } cFamilyName[familyNameSize] = 0; newInd = -1; ind = 0; desc = null; while (newInd == -1) { desc = fontDescriptions[ind]; if (desc == null) { newInd = ind; } else { isAbsolute = pango_font_description_get_size_is_absolute(desc); size = pango_font_description_get_size(desc); if (isAbsolute) { size = size; } if (((strcmp(cFamilyName, pango_font_description_get_family(desc))) == 0) && (size == (ptSize * (PANGO_SCALE)))) { newInd = ind; } } ind += 1; if (ind > 255) { newInd = 256; } } if (newInd == 256) { _return_value = ((-1 << 1) | 1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } if (desc == null) { null; } else { _return_value = ((newInd << 1) | 1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } desc = pango_font_description_new(); pango_font_description_set_family(desc, cFamilyName); pangoStyle = PANGO_STYLE_NORMAL; pango_font_description_set_style(desc, pangoStyle); pango_font_description_set_size(desc, ptSize * (PANGO_SCALE)); fontDescriptions[newInd] = desc; _return_value = ((newInd << 1) | 1); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(3, _return_value); return null; } EXPORT(sqInt) primitiveGetTransform(void) { cairo_t*context; sqInt canvasOop; cairo_matrix_t m; float *aTransform; aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0)))); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_get_matrix(context, &m); aTransform[0] = (m.xx); aTransform[1] = (m.xy); aTransform[2] = (m.x0); aTransform[3] = (m.yx); aTransform[4] = (m.yy); aTransform[5] = (m.y0); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitivePangoIndexAtPoint(void) { sqInt index; cairo_t*context; sqInt origin; unsigned char*aString; sqInt trailing; sqInt aStringOop; sqInt lineIndex; sqInt inside; PangoAttrList*attrList; PangoLayoutLine*line; sqInt xPos; PangoLayout*layout; sqInt canvasOop; sqInt corner; sqInt charData; PangoRectangle pos; sqInt inStringOop; sqInt x; sqInt y; sqInt sqAttrArray; sqInt w; sqInt h; sqInt withWrap; sqInt cData; sqInt _return_value; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(7), "Object")); inStringOop = interpreterProxy->stackValue(7); x = interpreterProxy->stackIntegerValue(6); y = interpreterProxy->stackIntegerValue(5); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object")); sqAttrArray = interpreterProxy->stackValue(4); w = interpreterProxy->stackIntegerValue(3); h = interpreterProxy->stackIntegerValue(2); withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1)); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); cData = interpreterProxy->stackValue(0); ; canvasOop = interpreterProxy->stackValue(8); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } aStringOop = inStringOop; aString = interpreterProxy->firstIndexableField(aStringOop); layout = pango_cairo_create_layout(context); attrList = pango_attr_list_new(); translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList); pango_layout_set_text(layout, aString, strlen(aString)); pango_layout_set_attributes(layout, attrList); pango_layout_set_width(layout, w * (PANGO_SCALE)); if (withWrap) { pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); } cairo_translate(context, x, y); pango_cairo_update_layout(context, layout); inside = pango_layout_xy_to_index(layout, x * (PANGO_SCALE), y * (PANGO_SCALE), &index, &trailing); pango_layout_index_to_pos(layout, index, &pos); line = null; if (!(inside)) { pango_layout_index_to_line_x(layout, index, trailing, &lineIndex, &xPos); /* self log: 'lineIndex %x' with: line. */ line = pango_layout_get_line_readonly(layout, ((lineIndex < 0) ? 0 : lineIndex)); if (line == null) { index = strlen(aString); } else { pango_layout_line_ref(line); /* self log: 'line->length %d' with: (self cCode: 'line->length'). */ index = line->start_index; index += line->length; if (trailing > 0) { trailing = 1; } } } pango_attr_list_unref(attrList); g_object_unref(layout); if (!(line == null)) { pango_layout_line_unref(line); } if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } interpreterProxy->pushRemappableOop(aStringOop); interpreterProxy->pushRemappableOop(cData); origin = interpreterProxy->makePointwithxValueyValue(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.y)); interpreterProxy->pushRemappableOop(origin); corner = interpreterProxy->makePointwithxValueyValue(PANGO_PIXELS(pos.x+pos.width), PANGO_PIXELS(pos.y+pos.height)); origin = interpreterProxy->popRemappableOop(); charData = interpreterProxy->popRemappableOop(); aStringOop = interpreterProxy->popRemappableOop(); aString = interpreterProxy->firstIndexableField(aStringOop); interpreterProxy->storePointerofObjectwithValue(0, charData, origin); interpreterProxy->storePointerofObjectwithValue(1, charData, corner); index = sqCharCountInfromto(aString, 0, (((index + trailing) < (1 + (strlen(aString)))) ? (index + trailing) : (1 + (strlen(aString))))); if (inside || (xPos <= 0)) { index += 1; } interpreterProxy->storePointerofObjectwithValue(2, charData, ((index << 1) | 1)); _return_value = interpreterProxy->integerObjectOf(index); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(9, _return_value); return null; } EXPORT(sqInt) primitiveLanguageAttributes(void) { sqInt arraySize; sqInt array4Oop; sqInt lOop; sqInt currentStart; sqInt ws; sqInt stringOop; int *array; int *array4; unsigned int *string; sqInt currentTag; sqInt leadingChar; sqInt arrayOop; sqInt i; sqInt arrayIndex; sqInt stringSize; sqInt currentEnd; sqInt oStringOop; sqInt oLOop; sqInt oArrayOop; sqInt _return_value; sqInt v; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Object")); oStringOop = interpreterProxy->stackValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object")); oLOop = interpreterProxy->stackValue(1); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); oArrayOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { return null; } lOop = oLOop; arrayOop = oArrayOop; stringOop = oStringOop; if (interpreterProxy->isBytes(stringOop)) { _return_value = interpreterProxy->integerObjectOf(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } if (!(interpreterProxy->isWords(stringOop))) { primitiveFail(); return null; } arraySize = interpreterProxy->stSizeOf(arrayOop); if (arraySize <= 0) { primitiveFail(); return null; } stringSize = interpreterProxy->stSizeOf(stringOop); if (stringSize == 0) { _return_value = interpreterProxy->integerObjectOf(0); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } string = interpreterProxy->firstIndexableField(stringOop); array = interpreterProxy->firstIndexableField(arrayOop); ws = string[0]; currentTag = ((usqInt) (ws & 1069547520) >> 22); leadingChar = -1; currentStart = 0; /* begin utf8CountFor: */ v = ws & 2097151; if ((0 <= v) && (v <= 127)) { currentEnd = 1; goto l1; } if ((128 <= v) && (v <= 2047)) { currentEnd = 2; goto l1; } if ((2048 <= v) && (v <= 55295)) { currentEnd = 3; goto l1; } if ((57344 <= v) && (v <= 65535)) { currentEnd = 3; goto l1; } if ((65536 <= v) && (v <= 1114111)) { currentEnd = 4; goto l1; } currentEnd = 0; l1: /* end utf8CountFor: */; arrayIndex = 0; for (i = 1; i <= (stringSize - 1); i += 1) { ws = string[i]; leadingChar = ((usqInt) (ws & 1069547520) >> 22); if (leadingChar != currentTag) { interpreterProxy->pushRemappableOop(stringOop); interpreterProxy->pushRemappableOop(arrayOop); interpreterProxy->pushRemappableOop(lOop); array4Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); lOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); stringOop = interpreterProxy->popRemappableOop(); array = interpreterProxy->firstIndexableField(arrayOop); string = interpreterProxy->firstIndexableField(stringOop); array4 = interpreterProxy->firstIndexableField(array4Oop); array4[0] = lOop; array4[1] = (((currentStart << 1) | 1)); array4[2] = (((currentEnd << 1) | 1)); array4[3] = (((currentTag << 1) | 1)); array[arrayIndex] = array4Oop; arrayIndex += 1; if (arrayIndex >= arraySize) { primitiveFail(); return null; } currentTag = leadingChar; currentStart = currentEnd; } currentEnd += utf8CountFor(ws); } interpreterProxy->pushRemappableOop(stringOop); interpreterProxy->pushRemappableOop(arrayOop); interpreterProxy->pushRemappableOop(lOop); array4Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); lOop = interpreterProxy->popRemappableOop(); arrayOop = interpreterProxy->popRemappableOop(); stringOop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, array4Oop, lOop); interpreterProxy->storeIntegerofObjectwithValue(1, array4Oop, currentStart); interpreterProxy->storeIntegerofObjectwithValue(2, array4Oop, currentEnd); interpreterProxy->storeIntegerofObjectwithValue(3, array4Oop, currentTag); interpreterProxy->storePointerofObjectwithValue(arrayIndex, arrayOop, array4Oop); arrayIndex += 1; _return_value = interpreterProxy->integerObjectOf(arrayIndex); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(4, _return_value); return null; } EXPORT(sqInt) primitiveOpen(void) { sqInt handleOop; sqInt contextIndex; sqInt canvasOop; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } contextIndex = createContextFor(canvasOop); if (!(interpreterProxy->failed())) { handleOop = interpreterProxy->integerObjectOf(contextIndex); interpreterProxy->storePointerofObjectwithValue(CanvasHandleIndex, canvasOop, handleOop); } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitivePangoIsAvailable(void) { PangoLayout*layout; cairo_t*context; sqInt canvasOop; sqInt _return_value; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } layout = pango_cairo_create_layout(context); if (layout == null) { _return_value = interpreterProxy->integerObjectOf(2); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } g_object_unref(layout); _return_value = (1? interpreterProxy->trueObject(): interpreterProxy->falseObject()); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitivePluginVersion(void) { sqInt _return_value; _return_value = interpreterProxy->integerObjectOf(PluginVersion); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(1, _return_value); return null; } EXPORT(sqInt) primitiveRestoreState(void) { cairo_t*context; sqInt canvasOop; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_restore(context); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitiveRotateBy(void) { cairo_t*context; sqInt canvasOop; double angle; angle = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_rotate(context, angle); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSaveState(void) { cairo_t*context; sqInt canvasOop; canvasOop = interpreterProxy->stackValue(0); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_save(context); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } return null; } EXPORT(sqInt) primitiveScaleBy(void) { cairo_t*context; sqInt canvasOop; double x; double y; x = interpreterProxy->stackFloatValue(1); y = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_scale(context, x, y); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveSetLineWidth(void) { cairo_t*context; sqInt canvasOop; double width; width = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_set_line_width(context, width); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveSetTransform(void) { cairo_t*context; sqInt canvasOop; cairo_matrix_t m; float *aTransform; aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0)))); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_matrix_init(&m, aTransform[0], aTransform[3], aTransform[1], aTransform[4], aTransform[2], aTransform[5]); cairo_set_matrix(context, &m); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitivePangoShowString(void) { cairo_t*context; sqInt newW; sqInt lineCount; PangoRectangle ink; unsigned int cursorColor; PangoAttrList*attrList; PangoLayoutLine*line; PangoRectangle logical; sqInt prevBaseline; PangoLayout*layout; PangoRectangle startRect; sqInt canvasOop; PangoLayoutIter*lineIter; sqInt indexToX; char *aString; sqInt x; sqInt y; sqInt sqAttrArray; sqInt w; sqInt h; sqInt withWrap; sqInt selStart; sqInt selEnd; sqInt cPixel; sqInt _return_value; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(9))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(9)))); x = interpreterProxy->stackIntegerValue(8); y = interpreterProxy->stackIntegerValue(7); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(6), "Object")); sqAttrArray = interpreterProxy->stackValue(6); w = interpreterProxy->stackIntegerValue(5); h = interpreterProxy->stackIntegerValue(4); withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(3)); selStart = interpreterProxy->stackIntegerValue(2); selEnd = interpreterProxy->stackIntegerValue(1); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object")); cPixel = interpreterProxy->stackValue(0); ; canvasOop = interpreterProxy->stackValue(10); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); cursorColor = interpreterProxy->positive32BitValueOf(cPixel); if (interpreterProxy->failed()) { return null; } layout = pango_cairo_create_layout(context); attrList = pango_attr_list_new(); translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList); if (!(selStart == selEnd)) { if ((selStart >= 0) && (selEnd >= 0)) { addSelectionFromtopixelinto(selStart, selEnd, cursorColor, attrList); } } pango_layout_set_text(layout, aString, strlen(aString)); pango_layout_set_attributes(layout, attrList); pango_layout_set_width(layout, w * (PANGO_SCALE)); if (withWrap) { pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); } cairo_translate(context, x, y); pango_cairo_update_layout(context, layout); /* lineIter := self pangoLayoutGetIter: layout. baseline := self pangoLayoutIterGetBaseline: lineIter. prevBaseline := 0. */ lineCount = pango_layout_get_line_count(layout); if (1) { pango_cairo_show_layout(context, layout); } else { null; } if (selStart == selEnd) { if ((selStart >= 0) && (selEnd >= 0)) { pango_layout_index_to_pos(layout, selStart, &startRect); addSelectionAtpixelwith(&startRect, cursorColor, context); } } pango_layout_get_extents(layout, &ink, &logical); /* self pangoLayoutIterFree: lineIter. */ newW = PANGO_PIXELS(logical.width); pango_attr_list_unref(attrList); g_object_unref(layout); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } _return_value = interpreterProxy->integerObjectOf(newW); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(11, _return_value); return null; } /* Show a string - ignores outline (use drawString primitive for outlines) */ EXPORT(sqInt) primitiveShowZeroTerminatedUtf8StringXY(void) { cairo_t*context; sqInt canvasOop; char *aString; double x; double y; interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2))); aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2)))); x = interpreterProxy->stackFloatValue(1); y = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(3); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_move_to(context, x, y); cairo_show_text(context, aString); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(3); return null; } EXPORT(sqInt) primitiveStencilImageSrcLRTBDestLRTB(void) { cairo_surface_t*srcSurface; cairo_t*context; sqInt canvasOop; sqInt formOop; double dstL; double dstR; double dstT; double dstB; double srcL; double srcR; double srcT; double srcB; formOop = interpreterProxy->stackValue(8); dstL = interpreterProxy->stackFloatValue(7); dstR = interpreterProxy->stackFloatValue(6); dstT = interpreterProxy->stackFloatValue(5); dstB = interpreterProxy->stackFloatValue(4); srcL = interpreterProxy->stackFloatValue(3); srcR = interpreterProxy->stackFloatValue(2); srcT = interpreterProxy->stackFloatValue(1); srcB = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(9); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } srcSurface = surfaceFrom(formOop); if (!((srcSurface != null) && ((cairo_surface_status(srcSurface)) == 0))) { fail("source surface invalid"); return null; } if ((srcR != srcL) && (srcT != srcB)) { cairo_save(context); cairo_translate(context, dstL, dstT); cairo_scale(context, (dstR - dstL) / (srcR - srcL), (dstB - dstT) / (srcB - srcT)); cairo_new_path(context); cairo_rectangle(context, 0.0, 0.0, srcR - srcL, srcB - srcT); cairo_clip(context); cairo_mask_surface(context, srcSurface, 0.0 - srcL, 0.0 - srcT); cairo_restore(context); } if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(9); return null; } EXPORT(sqInt) primitiveTransformBy(void) { cairo_t*context; sqInt canvasOop; cairo_matrix_t m; float *aTransform; aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0)))); canvasOop = interpreterProxy->stackValue(1); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_matrix_init(&m, aTransform[0], aTransform[3], aTransform[1], aTransform[4], aTransform[2], aTransform[5]); cairo_transform(context, &m); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(1); return null; } EXPORT(sqInt) primitiveTranslateBy(void) { cairo_t*context; sqInt canvasOop; double x; double y; x = interpreterProxy->stackFloatValue(1); y = interpreterProxy->stackFloatValue(0); canvasOop = interpreterProxy->stackValue(2); if (interpreterProxy->failed()) { return null; } context = contextFrom(canvasOop); if (interpreterProxy->failed()) { return null; } cairo_translate(context, x, y); if (cairo_status(context)) { failwith("cairo error: %s", cairo_status_to_string(cairo_status(context))); return null; } if (interpreterProxy->failed()) { return null; } interpreterProxy->pop(2); return null; } EXPORT(sqInt) primitiveUTF8StringWith2Indexes(void) { sqInt utf8StringOop; sqInt size; sqInt bytes; sqInt mult; unsigned char *byteString; sqInt stringOop; sqInt utf8Index; sqInt arrayOop; sqInt i; sqInt newIndex2; sqInt realutf8StringOop; sqInt newIndex1; unsigned int *wideString; unsigned char *realutf8String; sqInt val; unsigned int c; unsigned char *utf8String; sqInt oStringOop; sqInt sqIndex1; sqInt sqIndex2; sqInt oArrayOop; sqInt nullFlag; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object")); oStringOop = interpreterProxy->stackValue(4); sqIndex1 = interpreterProxy->stackIntegerValue(3); sqIndex2 = interpreterProxy->stackIntegerValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object")); oArrayOop = interpreterProxy->stackValue(1); nullFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { return null; } arrayOop = oArrayOop; stringOop = oStringOop; if (interpreterProxy->isPointers(stringOop)) { primitiveFail(); return null; } bytes = interpreterProxy->isBytes(stringOop); size = interpreterProxy->stSizeOf(stringOop); if (bytes) { mult = 2; } else { mult = 4; } interpreterProxy->pushRemappableOop(stringOop); interpreterProxy->pushRemappableOop(arrayOop); utf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), (size * mult) + 1); arrayOop = interpreterProxy->popRemappableOop(); stringOop = interpreterProxy->popRemappableOop(); if (bytes) { byteString = interpreterProxy->firstIndexableField(stringOop); } else { wideString = interpreterProxy->firstIndexableField(stringOop); } utf8Index = 0; newIndex1 = -1; newIndex2 = -1; utf8String = interpreterProxy->firstIndexableField(utf8StringOop); if (bytes) { for (i = 0; i <= (size - 1); i += 1) { c = byteString[i]; if ((i + 1) == sqIndex1) { newIndex1 = utf8Index; } if ((i + 1) == sqIndex2) { newIndex2 = utf8Index; } utf8Index = putCharintoat(c, utf8String, utf8Index); } } else { for (i = 0; i <= (size - 1); i += 1) { c = wideString[i]; if ((i + 1) == sqIndex1) { newIndex1 = utf8Index; } if ((i + 1) == sqIndex2) { newIndex2 = utf8Index; } utf8Index = putCharintoat(c, utf8String, utf8Index); } } if (nullFlag) { utf8String[utf8Index] = 0; utf8Index += 1; } interpreterProxy->pushRemappableOop(utf8StringOop); interpreterProxy->pushRemappableOop(arrayOop); realutf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), utf8Index); arrayOop = interpreterProxy->popRemappableOop(); utf8StringOop = interpreterProxy->popRemappableOop(); utf8String = interpreterProxy->firstIndexableField(utf8StringOop); realutf8String = interpreterProxy->firstIndexableField(realutf8StringOop); memcpy(realutf8String, utf8String, utf8Index); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, realutf8StringOop); if (newIndex1 == -1) { if (sqIndex1 == -1) { val = -1; } else { val = utf8Index; } } else { val = newIndex1; } interpreterProxy->storeIntegerofObjectwithValue(1, arrayOop, val); if (newIndex2 == -1) { if (sqIndex2 == -1) { val = -1; } else { val = utf8Index; } } else { val = newIndex2; } interpreterProxy->storeIntegerofObjectwithValue(2, arrayOop, val); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(6, arrayOop); return null; } EXPORT(sqInt) primitiveUTF8StringWithIndex(void) { sqInt utf8StringOop; sqInt size; sqInt bytes; sqInt mult; unsigned char *byteString; sqInt stringOop; sqInt utf8Index; sqInt arrayOop; sqInt i; sqInt realutf8StringOop; unsigned int *wideString; unsigned char *realutf8String; sqInt val; unsigned int c; sqInt newIndex; unsigned char *utf8String; sqInt oStringOop; sqInt sqIndex; sqInt oArrayOop; sqInt nullFlag; interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(3), "Object")); oStringOop = interpreterProxy->stackValue(3); sqIndex = interpreterProxy->stackIntegerValue(2); interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object")); oArrayOop = interpreterProxy->stackValue(1); nullFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } if (interpreterProxy->failed()) { return null; } arrayOop = oArrayOop; stringOop = oStringOop; if (interpreterProxy->isPointers(stringOop)) { primitiveFail(); return null; } bytes = interpreterProxy->isBytes(stringOop); size = interpreterProxy->stSizeOf(stringOop); if (bytes) { mult = 2; } else { mult = 4; } interpreterProxy->pushRemappableOop(stringOop); interpreterProxy->pushRemappableOop(arrayOop); utf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), (size * mult) + 1); arrayOop = interpreterProxy->popRemappableOop(); stringOop = interpreterProxy->popRemappableOop(); if (bytes) { byteString = interpreterProxy->firstIndexableField(stringOop); } else { wideString = interpreterProxy->firstIndexableField(stringOop); } utf8Index = 0; newIndex = -1; utf8String = interpreterProxy->firstIndexableField(utf8StringOop); if (bytes) { for (i = 0; i <= (size - 1); i += 1) { c = byteString[i]; if ((i + 1) == sqIndex) { newIndex = utf8Index; } utf8Index = putCharintoat(c, utf8String, utf8Index); } } else { for (i = 0; i <= (size - 1); i += 1) { c = wideString[i]; if ((i + 1) == sqIndex) { newIndex = utf8Index; } utf8Index = putCharintoat(c, utf8String, utf8Index); } } if (nullFlag) { utf8String[utf8Index] = 0; utf8Index += 1; } interpreterProxy->pushRemappableOop(utf8StringOop); interpreterProxy->pushRemappableOop(arrayOop); realutf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), utf8Index); arrayOop = interpreterProxy->popRemappableOop(); utf8StringOop = interpreterProxy->popRemappableOop(); utf8String = interpreterProxy->firstIndexableField(utf8StringOop); realutf8String = interpreterProxy->firstIndexableField(realutf8StringOop); memcpy(realutf8String, utf8String, utf8Index); interpreterProxy->storePointerofObjectwithValue(0, arrayOop, realutf8StringOop); if (newIndex == -1) { if (sqIndex == -1) { val = -1; } else { val = utf8Index; } } else { val = newIndex; } interpreterProxy->storeIntegerofObjectwithValue(1, arrayOop, val); if (interpreterProxy->failed()) { return null; } interpreterProxy->popthenPush(5, arrayOop); return null; } static sqInt putCharintoat(sqInt c, unsigned char*utf8String, sqInt utf8Index) { unsigned int val; sqInt nBytes; sqInt mask; sqInt i; sqInt index; sqInt shift; sqInt v; val = c & 2097151; index = utf8Index; if ((0 <= val) && (val <= 127)) { utf8String[index] = val; return utf8Index + 1; } /* begin utf8CountFor: */ v = c & 2097151; if ((0 <= v) && (v <= 127)) { nBytes = 1; goto l1; } if ((128 <= v) && (v <= 2047)) { nBytes = 2; goto l1; } if ((2048 <= v) && (v <= 55295)) { nBytes = 3; goto l1; } if ((57344 <= v) && (v <= 65535)) { nBytes = 3; goto l1; } if ((65536 <= v) && (v <= 1114111)) { nBytes = 4; goto l1; } nBytes = 0; l1: /* end utf8CountFor: */; mask = utf8Headers[nBytes - 1]; shift = (nBytes - 1) * -6; utf8String[index] = ((((shift < 0) ? ((usqInt) val >> -shift) : ((usqInt) val << shift))) | mask); index += 1; for (i = 2; i <= nBytes; i += 1) { shift += 6; utf8String[index] = (((((shift < 0) ? ((usqInt) val >> -shift) : ((usqInt) val << shift))) & 63) + 128); index += 1; } return utf8Index + nBytes; } /* Register the given surface, answer an ID or -1 on failure */ static sqInt registerSurface(cairo_surface_t*surfaceHandle) { sqInt surfaceID; if (registerSurfaceFn == null) { if (!(loadSurfacePlugin())) { return -1; } } if (!((*registerSurfaceFn)((int)surfaceHandle, &surfaceDispatch, &surfaceID))) { fail("could not register surface"); return -1; } /* missing DebugCode */; if (surfaceID > maxSurfaceID) { maxSurfaceID = surfaceID; } return surfaceID; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void setSourcergbalpha(cairo_t*context, sqInt rgb, sqInt alpha) { sqInt b; sqInt r; sqInt g; r = (((usqInt) rgb) >> 20) & 1023; g = (((usqInt) rgb) >> 10) & 1023; b = (((usqInt) rgb) >> 0) & 1023; if (alpha == 255) { cairo_set_source_rgb(context, r / 1023.0, g / 1023.0, b / 1023.0); } else { cairo_set_source_rgba(context, r / 1023.0, g / 1023.0, b / 1023.0, alpha / 255.0); } } static sqInt showSurfacexywh(cairo_surface_t *surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h) { return 0; } EXPORT(sqInt) shutdownModule(void) { PangoFontDescription*desc; sqInt i; sqInt id; cairo_surface_t*surface; for (i = 0; i <= (lastIndex(contexts)); i += 1) { if (!((contexts[i]) == null)) { logwith("context %i still active when unloading module!", i); cairo_destroy(contexts[i]); contexts[i] = null; } } for (id = 0; id <= maxSurfaceID; id += 1) { surface = findSurface(id); if (surface != null) { logwith("surface %i still active when unloading module!", id); destroySurface(id); } } for (i = 0; i <= 255; i += 1) { desc = fontDescriptions[i]; if (desc != null) { pango_font_description_free(desc); fontDescriptions[i] = null; } } if (defaultFontDescription != null) { pango_font_description_free(defaultFontDescription); defaultFontDescription = null; } return 1; } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } static sqInt sqCharCountInfromto(unsigned char* aString, sqInt from, sqInt to) { sqInt sqCount; sqInt aChar; sqInt index; index = from; sqCount = 0; while (index < to) { aChar = aString[index]; if (aChar < 128) { index += 1; } else { if (aChar < 224) { index += 2; } else { if (aChar < 240) { index += 3; } else { if (aChar < 248) { index += 4; } else { if (aChar < 252) { index += 5; } else { if (aChar >= 252) { index += 6; } } } } } } sqCount += 1; } return sqCount; } /* stroke depending on canvasOop's stroke flag */ static void strokefrom(cairo_t*context, sqInt canvasOop) { sqInt stroke; sqInt canvasFlags; sqInt rgb; canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop); if (interpreterProxy->failed()) { fail("canvas flags not an integer"); } else { stroke = canvasFlags & CanvasFlagStroke; if (stroke != 0) { rgb = interpreterProxy->fetchIntegerofObject(CanvasStrokeColorIndex, canvasOop); cairo_save(context); setSourcergbalpha(context, rgb, stroke); cairo_stroke(context); cairo_restore(context); } } } /* answer a surface by looking up its surface plugin ID stored as bits in formOop */ static cairo_surface_t* surfaceFrom(sqInt formOop) { sqInt surfaceID; if ((interpreterProxy->slotSizeOf(formOop)) < FormInstSize) { fail("form oop invalid"); return null; } surfaceID = interpreterProxy->fetchIntegerofObject(FormBitsIndex, formOop); if (interpreterProxy->failed()) { fail("form handle not an integer"); return null; } return findSurface(surfaceID); } static sqInt translateSqAttrsToPangoAttrsinto(sqInt sqAttrsArrayOop, PangoAttrList *pangoAttrList) { sqInt ind; sqInt symbolOop; sqInt *sqAttrsArray; char *symbol; sqInt sqAttrsSize; sqInt attrArray; sqAttrsSize = interpreterProxy->stSizeOf(sqAttrsArrayOop); sqAttrsArray = interpreterProxy->firstIndexableField(sqAttrsArrayOop); addDefaultInto(pangoAttrList); for (ind = 0; ind <= (sqAttrsSize - 1); ind += 1) { attrArray = sqAttrsArray[ind]; symbolOop = interpreterProxy->fetchPointerofObject(0, attrArray); symbol = interpreterProxy->firstIndexableField(symbolOop); if ((symbol[0]) == 65) { addAlignmentinto(attrArray, pangoAttrList); } if ((symbol[0]) == 67) { addColorinto(attrArray, pangoAttrList); } if ((symbol[0]) == 69) { addEmphasisinto(attrArray, pangoAttrList); } if ((symbol[0]) == 70) { addFontinto(attrArray, pangoAttrList); } if ((symbol[0]) == 76) { addLanguageinto(attrArray, pangoAttrList); } } return 1; } static sqInt unlockSurfacexywh(cairo_surface_t*surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h) { /* missing DebugCode */; if ((w > 0) && (h > 0)) { cairo_surface_mark_dirty_rectangle(surfaceHandle, x, y, w, h); } return 1; } /* Unregister the surface, answer true if successful */ static sqInt unregisterSurface(sqInt surfaceID) { if (unregisterSurfaceFn == null) { if (!(loadSurfacePlugin())) { return 0; } } /* missing DebugCode */; if (!((*unregisterSurfaceFn)(surfaceID))) { failwith("could not unregister surface %i", surfaceID); return 0; } return 1; } static sqInt utf8CountFor(unsigned int value) { sqInt v; v = value & 2097151; if ((0 <= v) && (v <= 127)) { return 1; } if ((128 <= v) && (v <= 2047)) { return 2; } if ((2048 <= v) && (v <= 55295)) { return 3; } if ((57344 <= v) && (v <= 65535)) { return 3; } if ((65536 <= v) && (v <= 1114111)) { return 4; } return 0; } #ifdef SQUEAK_BUILTIN_PLUGIN void* RomePlugin_exports[][3] = { {"RomePlugin", "primitivePangoBlockAtIndex", (void*)primitivePangoBlockAtIndex}, {"RomePlugin", "primitiveDrawImageSrcLRTBDestLRTB", (void*)primitiveDrawImageSrcLRTBDestLRTB}, {"RomePlugin", "primitiveDrawGeneralBezierShape", (void*)primitiveDrawGeneralBezierShape}, {"RomePlugin", "initialiseModule", (void*)initialiseModule}, {"RomePlugin", "primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops", (void*)primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops}, {"RomePlugin", "primitiveFillColorAlpha", (void*)primitiveFillColorAlpha}, {"RomePlugin", "primitiveFillLinearOriginXYdirectionXYcolorStops", (void*)primitiveFillLinearOriginXYdirectionXYcolorStops}, {"RomePlugin", "primitiveDestroyFormHandle", (void*)primitiveDestroyFormHandle}, {"RomePlugin", "primitiveClear", (void*)primitiveClear}, {"RomePlugin", "primitiveTransformBy", (void*)primitiveTransformBy}, {"RomePlugin", "primitiveDrawOvalLeftRightTopBottom", (void*)primitiveDrawOvalLeftRightTopBottom}, {"RomePlugin", "primitiveDrawPolygon", (void*)primitiveDrawPolygon}, {"RomePlugin", "primitivePluginVersion", (void*)primitivePluginVersion}, {"RomePlugin", "primitiveShowZeroTerminatedUtf8StringXY", (void*)primitiveShowZeroTerminatedUtf8StringXY}, {"RomePlugin", "primitiveFontFace", (void*)primitiveFontFace}, {"RomePlugin", "primitiveClipRectangleLeftRightTopBottom", (void*)primitiveClipRectangleLeftRightTopBottom}, {"RomePlugin", "getModuleName", (void*)getModuleName}, {"RomePlugin", "primitiveFontSize", (void*)primitiveFontSize}, {"RomePlugin", "primitivePangoIndexAtPoint", (void*)primitivePangoIndexAtPoint}, {"RomePlugin", "primitiveDrawPolyline", (void*)primitiveDrawPolyline}, {"RomePlugin", "primitiveDrawCurveFromXYviaXYandXYtoXY", (void*)primitiveDrawCurveFromXYviaXYandXYtoXY}, {"RomePlugin", "primitiveRotateBy", (void*)primitiveRotateBy}, {"RomePlugin", "primitiveDrawRoundRectLeftRightTopBottomRadiusCorner", (void*)primitiveDrawRoundRectLeftRightTopBottomRadiusCorner}, {"RomePlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"RomePlugin", "primitiveDrawLineFromXYtoXY", (void*)primitiveDrawLineFromXYtoXY}, {"RomePlugin", "primitivePangoShowString", (void*)primitivePangoShowString}, {"RomePlugin", "primitiveDrawArcRadiusXYFromTo", (void*)primitiveDrawArcRadiusXYFromTo}, {"RomePlugin", "primitiveDrawZeroTerminatedUtf8StringXY", (void*)primitiveDrawZeroTerminatedUtf8StringXY}, {"RomePlugin", "primitiveSetLineWidth", (void*)primitiveSetLineWidth}, {"RomePlugin", "primitivePangoComposeString", (void*)primitivePangoComposeString}, {"RomePlugin", "primitiveUTF8StringWithIndex", (void*)primitiveUTF8StringWithIndex}, {"RomePlugin", "primitiveStencilImageSrcLRTBDestLRTB", (void*)primitiveStencilImageSrcLRTBDestLRTB}, {"RomePlugin", "setInterpreter", (void*)setInterpreter}, {"RomePlugin", "primitiveRestoreState", (void*)primitiveRestoreState}, {"RomePlugin", "primitiveScaleBy", (void*)primitiveScaleBy}, {"RomePlugin", "primitivePangoComposeString2", (void*)primitivePangoComposeString2}, {"RomePlugin", "primitiveDrawRectangleLeftRightTopBottom", (void*)primitiveDrawRectangleLeftRightTopBottom}, {"RomePlugin", "primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage", (void*)primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage}, {"RomePlugin", "primitiveSetTransform", (void*)primitiveSetTransform}, {"RomePlugin", "primitiveSaveState", (void*)primitiveSaveState}, {"RomePlugin", "primitiveLanguageAttributes", (void*)primitiveLanguageAttributes}, {"RomePlugin", "primitiveGetTransform", (void*)primitiveGetTransform}, {"RomePlugin", "primitivePangoFontDescriptionIndex", (void*)primitivePangoFontDescriptionIndex}, {"RomePlugin", "primitiveUTF8StringWith2Indexes", (void*)primitiveUTF8StringWith2Indexes}, {"RomePlugin", "primitiveCreateFormHandle", (void*)primitiveCreateFormHandle}, {"RomePlugin", "primitivePangoIsAvailable", (void*)primitivePangoIsAvailable}, {"RomePlugin", "primitiveClose", (void*)primitiveClose}, {"RomePlugin", "primitiveOpen", (void*)primitiveOpen}, {"RomePlugin", "primitiveDrawCurveFromXYviaXYtoXY", (void*)primitiveDrawCurveFromXYviaXYtoXY}, {"RomePlugin", "primitiveGetLineWidth", (void*)primitiveGetLineWidth}, {"RomePlugin", "shutdownModule", (void*)shutdownModule}, {"RomePlugin", "primitiveTranslateBy", (void*)primitiveTranslateBy}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/Squeak3D/Squeak3D.c ================================================ /* Automatically generated from Squeak on 23 January 2011 6:34:03 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "b3d.h" #include "b3d.h" #include "sqMemoryAccess.h" /*** Constants ***/ #define AmbientPart 0 #define DiffusePart 4 #define EmissionAlpha 15 #define EmissionBlue 14 #define EmissionGreen 13 #define EmissionRed 12 #define FlagAmbientPart 256 #define FlagAttenuated 4 #define FlagDiffusePart 512 #define FlagDirectional 2 #define FlagHasSpot 8 #define FlagM44Identity 1 #define FlagM44NoPerspective 2 #define FlagM44NoTranslation 4 #define FlagPositional 1 #define FlagSpecularPart 1024 #define InAllMask 1365 #define InBackBit 1024 #define InBottomBit 64 #define InFrontBit 256 #define InLeftBit 1 #define InRightBit 4 #define InTopBit 16 #define MaterialShininess 16 #define MaterialSize 17 #define OutAllMask 2730 #define OutBackBit 2048 #define OutBottomBit 128 #define OutFrontBit 512 #define OutLeftBit 2 #define OutRightBit 8 #define OutTopBit 32 #define PrimLightAttenuationConstant 18 #define PrimLightAttenuationLinear 19 #define PrimLightAttenuationSquared 20 #define PrimLightDirection 15 #define PrimLightDirectionX 15 #define PrimLightDirectionY 16 #define PrimLightDirectionZ 17 #define PrimLightFlags 21 #define PrimLightPositionX 12 #define PrimLightPositionY 13 #define PrimLightPositionZ 14 #define PrimLightSize 32 #define PrimTypeMax 6 #define PrimVertexSize 16 #define PrimVtxClipFlags 13 #define PrimVtxColor32 12 #define PrimVtxNormal 3 #define PrimVtxNormalX 3 #define PrimVtxNormalY 4 #define PrimVtxNormalZ 5 #define PrimVtxPosition 0 #define PrimVtxPositionX 0 #define PrimVtxPositionY 1 #define PrimVtxPositionZ 2 #define PrimVtxRasterPosW 11 #define PrimVtxRasterPosX 8 #define PrimVtxRasterPosY 9 #define PrimVtxRasterPosZ 10 #define PrimVtxTexCoordU 6 #define PrimVtxTexCoordV 7 #define PrimVtxTexCoords 6 #define SpecularPart 8 #define SpotLightDeltaCos 24 #define SpotLightExponent 25 #define SpotLightMinCos 22 #define VBTrackAmbient 1 #define VBTrackDiffuse 2 #define VBTrackEmission 8 #define VBTrackSpecular 4 #define VBTwoSidedLighting 64 #define VBUseLocalViewer 128 #define VBVtxHasNormals 16 /*** Function Prototypes ***/ static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale); static sqInt analyzeMatrix3x3Length(float *m); static sqInt analyzeMatrix(float *m); #pragma export on EXPORT(sqInt) b3dClipPolygon(void); EXPORT(sqInt) b3dComputeMinIndexZ(void); EXPORT(sqInt) b3dComputeMinZ(void); EXPORT(sqInt) b3dDetermineClipFlags(void); EXPORT(sqInt) b3dInitPrimitiveObject(void); EXPORT(sqInt) b3dInitializeRasterizerState(void); EXPORT(sqInt) b3dInplaceHouseHolderInvert(void); EXPORT(sqInt) b3dLoadIndexArray(void); EXPORT(sqInt) b3dLoadVertexBuffer(void); EXPORT(sqInt) b3dMapVertexBuffer(void); EXPORT(sqInt) b3dOrthoNormInverseMatrix(void); EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void); EXPORT(sqInt) b3dPrimitiveObjectSize(void); EXPORT(sqInt) b3dPrimitiveTextureSize(void); EXPORT(sqInt) b3dRasterizerVersion(void); EXPORT(sqInt) b3dShadeVertexBuffer(void); EXPORT(sqInt) b3dShaderVersion(void); EXPORT(sqInt) b3dStartRasterizer(void); EXPORT(sqInt) b3dTransformDirection(void); EXPORT(sqInt) b3dTransformMatrixWithInto(void); EXPORT(sqInt) b3dTransformPoint(void); EXPORT(sqInt) b3dTransformPrimitiveNormal(void); EXPORT(sqInt) b3dTransformPrimitivePosition(void); EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void); EXPORT(sqInt) b3dTransformVertexBuffer(void); EXPORT(sqInt) b3dTransformerVersion(void); EXPORT(sqInt) b3dTransposeMatrix(void); #pragma export off static double backClipValueFromto(sqInt last, sqInt next); static double bottomClipValueFromto(sqInt last, sqInt next); static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask); static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n); static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n); static sqInt computeAttenuation(void); static sqInt computeDirection(void); static sqInt computeSpecularDirection(void); static double computeSpotFactor(void); static sqInt determineClipFlagscount(void *vtxArray, sqInt count); static double dotProductOfFloatwithDouble(float * v1, double *v2); static void* fetchLightSourceofObject(sqInt index, sqInt anArray); static double frontClipValueFromto(sqInt last, sqInt next); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out); static double inverseLengthOfDouble(double * aVector); static double inverseLengthOfFloat(float * aVector); static double leftClipValueFromto(sqInt last, sqInt next); static sqInt loadObjectsFrom(sqInt stackIndex); static sqInt loadPrimitiveLightSource(void); static sqInt loadPrimitiveVertex(void); static sqInt loadRasterizerState(sqInt stackIndex); static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr); static sqInt loadTexturesFrom(sqInt stackIndex); static sqInt loadViewportFrom(sqInt stackIndex); static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveSetBitBltPlugin(void); #pragma export off static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize); static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize); static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize); static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize); static double rightClipValueFromto(sqInt last, sqInt next); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static sqInt shadeVertex(void); static sqInt stackLightArrayValue(sqInt stackIndex); static void * stackMaterialValue(sqInt stackIndex); static void* stackMatrix(sqInt index); static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex); static void* stackPrimitiveVertex(sqInt index); static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems); static sqInt storeObjectsInto(sqInt stackIndex); static sqInt storePrimitiveVertex(void); static double topClipValueFromto(sqInt last, sqInt next); static sqInt transformMatrixwithinto(float *src, float *arg, float *dst); static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale); static sqInt transformPrimitivePositionby(float *pVertex, float *matrix); static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix); static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix); static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix); static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags); static void* vbLoadArraysize(sqInt oop, sqInt count); /*** Variables ***/ static char bbPluginName[256] = "BitBltPlugin"; static sqInt copyBitsFn; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static double l2vDirection[3]; static double l2vDistance; static double l2vSpecDir[3]; static sqInt lightFlags; static double lightScale; static float* litVertex; static sqInt loadBBFn; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "Squeak3D 23 January 2011 (i)" #else "Squeak3D 23 January 2011 (e)" #endif ; static float* primLight; static float* primMaterial; static B3DRasterizerState state; static sqInt vbFlags; static B3DPrimitiveViewport viewport; static double vtxInColor[4]; static double vtxOutColor[4]; /* Add the given light part to the output color, scaled by the given scale factor. If the given flag is set in vbFlags then load the part from the primitive vertex */ static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale) { double aPart; double bPart; double gPart; double rPart; if (vbFlags & vbTrackFlag) { rPart = ((vtxInColor[0]) * (lightPart[0])) * scale; gPart = ((vtxInColor[1]) * (lightPart[1])) * scale; bPart = ((vtxInColor[2]) * (lightPart[2])) * scale; aPart = ((vtxInColor[3]) * (lightPart[3])) * scale; } else { /* Note: This should be pre-computed. */ rPart = ((materialPart[0]) * (lightPart[0])) * scale; gPart = ((materialPart[1]) * (lightPart[1])) * scale; bPart = ((materialPart[2]) * (lightPart[2])) * scale; aPart = ((materialPart[3]) * (lightPart[3])) * scale; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart); vtxOutColor[1] = ((vtxOutColor[1]) + gPart); vtxOutColor[2] = ((vtxOutColor[2]) + bPart); vtxOutColor[3] = ((vtxOutColor[3]) + aPart); } /* Check if the matrix scales normals to non-unit length. */ static sqInt analyzeMatrix3x3Length(float *m) { double det; det = (((((((m[0]) * (m[5])) * (m[10])) - (((m[2]) * (m[5])) * (m[8]))) + (((m[4]) * (m[9])) * (m[2]))) - (((m[6]) * (m[9])) * (m[0]))) + (((m[8]) * (m[1])) * (m[6]))) - (((m[10]) * (m[1])) * (m[4])); return (det < 0.99) || (det > 1.01); } /* Analyze the matrix and return the appropriate flags */ static sqInt analyzeMatrix(float *m) { sqInt flags; flags = 0; if (((m[12]) == 0.0) && (((m[13]) == 0.0) && (((m[14]) == 0.0) && ((m[15]) == 1.0)))) { /* Check translation */ flags = flags | FlagM44NoPerspective; if (((m[3]) == 0.0) && (((m[7]) == 0.0) && ((m[11]) == 0.0))) { /* Check for identity */ flags = flags | FlagM44NoTranslation; if (((m[0]) == 1.0) && (((m[5]) == 1.0) && (((m[10]) == 1.0) && (((m[1]) == 0.0) && (((m[2]) == 0.0) && (((m[4]) == 0.0) && (((m[6]) == 0.0) && (((m[8]) == 0.0) && ((m[9]) == 0.0))))))))) { flags = flags | FlagM44Identity; } } } return flags; } /* Primitive. Clip the polygon given in the vertexArray using the temporary vertex array which is assumed to have sufficient size. */ EXPORT(sqInt) b3dClipPolygon(void) { sqInt count; sqInt outMask; int *tempVtxArray; int *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 4)) { return interpreterProxy->primitiveFail(); } outMask = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount + 4); tempVtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount + 4); if ((vtxArray == null) || ((tempVtxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } vtxArray -= PrimVertexSize; tempVtxArray -= PrimVertexSize; count = clipPolygoncountwithmask(vtxArray, vtxCount, tempVtxArray, outMask); interpreterProxy->pop(5); interpreterProxy->pushInteger(count); } /* Primitive. Compute and return the index for the minimal z value of all objects in the vertex buffer. */ EXPORT(sqInt) b3dComputeMinIndexZ(void) { int *idxArray; sqInt idxSize; sqInt minIndex; sqInt primType; float *vtxArray; sqInt vtxSize; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(0); vtxSize = interpreterProxy->stackIntegerValue(2); primType = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if ((primType < 1) || (primType > 6)) { return interpreterProxy->primitiveFail(); } if (primType <= 3) { minIndex = processNonIndexedIDXofSize(vtxArray, vtxSize); } else { minIndex = processIndexedIDXofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(6); interpreterProxy->pushInteger(minIndex); } } /* Primitive. Compute and return the minimal z value of all objects in the vertex buffer. */ EXPORT(sqInt) b3dComputeMinZ(void) { int *idxArray; sqInt idxSize; double minZ; sqInt primType; float *vtxArray; sqInt vtxSize; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(0); vtxSize = interpreterProxy->stackIntegerValue(2); primType = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if ((primType < 1) || (primType > 6)) { return interpreterProxy->primitiveFail(); } if (primType <= 3) { minZ = processNonIndexedofSize(vtxArray, vtxSize); } else { minZ = processIndexedofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize); } if (!(interpreterProxy->failed())) { interpreterProxy->pop(6); interpreterProxy->pushFloat(minZ); } } /* Primitive. Determine the clipping flags for all vertices. */ EXPORT(sqInt) b3dDetermineClipFlags(void) { sqInt result; void *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } vtxCount = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount); if ((vtxArray == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } result = determineClipFlagscount(vtxArray, vtxCount); if (!(interpreterProxy->failed())) { interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } } EXPORT(sqInt) b3dInitPrimitiveObject(void) { int *idxArray; sqInt idxSize; void *primObj; sqInt primOop; sqInt primSize; sqInt primitive; sqInt textureIndex; int *vtxArray; sqInt vtxSize; if (!((interpreterProxy->methodArgumentCount()) == 8)) { return interpreterProxy->primitiveFail(); } textureIndex = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } loadViewportFrom(1); if (interpreterProxy->failed()) { return null; } vtxSize = interpreterProxy->stackIntegerValue(4); vtxArray = stackPrimitiveVertexArrayofSize(5, vtxSize); if (vtxArray == null) { return interpreterProxy->primitiveFail(); } idxSize = interpreterProxy->stackIntegerValue(2); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(3, idxSize, 1, vtxSize); if (idxArray == null) { return interpreterProxy->primitiveFail(); } primitive = interpreterProxy->stackIntegerValue(6); if ((primitive < 1) || (primitive > PrimTypeMax)) { return interpreterProxy->primitiveFail(); } if (!((primitive == 3) || ((primitive == 5) || (primitive == 6)))) { return interpreterProxy->primitiveFail(); } primOop = interpreterProxy->stackObjectValue(7); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(primOop))) { return interpreterProxy->primitiveFail(); } primObj = interpreterProxy->firstIndexableField(primOop); /* Do the work */ primSize = interpreterProxy->byteSizeOf(primOop); if (primitive == 3) { if (b3dAddPolygonObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } if (primitive == 5) { if (b3dAddIndexedTriangleObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputFace*) idxArray, idxSize / 3, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } if (primitive == 6) { if (b3dAddIndexedQuadObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputQuad*) idxArray, idxSize / 4, &viewport) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(9); interpreterProxy->push(primOop); } /* Primitive. Initialize the primitive level objects of the given rasterizer. */ EXPORT(sqInt) b3dInitializeRasterizerState(void) { void *obj; sqInt objLen; sqInt objOop; sqInt stateOop; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } stateOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 7))) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(0, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeFaceAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(1, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeEdgeAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(2, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeAttrAllocator(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(3, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeAET(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(4, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeEdgeList(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } objOop = interpreterProxy->fetchPointerofObject(5, stateOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objLen = interpreterProxy->byteSizeOf(objOop); obj = interpreterProxy->firstIndexableField(objOop); if (b3dInitializeFillList(obj, objLen) != B3D_NO_ERROR) { return interpreterProxy->primitiveFail(); } } /* Primitive. Perform an inplace house holder matrix inversion */ EXPORT(sqInt) b3dInplaceHouseHolderInvert(void) { double beta; double d[4][4]; sqInt i; sqInt j; sqInt k; double m[4][4]; sqInt r; float *rcvr; double s; double sigma; double sum; double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; ; rcvr = stackMatrix(0); for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { (m[i])[j] = (rcvr[(i * 4) + j]); } } for (j = 0; j <= 3; j += 1) { sigma = 0.0; for (i = j; i <= 3; i += 1) { sigma += ((m[i])[j]) * ((m[i])[j]); } if (sigma < 1.0e-10) { return interpreterProxy->primitiveFail(); } if (((m[j])[j]) < 0.0) { s = sqrt(sigma); } else { s = 0.0 - (sqrt(sigma)); } for (r = 0; r <= 3; r += 1) { (d[j])[r] = s; } beta = 1.0 / ((s * ((m[j])[j])) - sigma); (m[j])[j] = (((m[j])[j]) - s); for (k = (j + 1); k <= 3; k += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((m[i])[j]) * ((m[i])[k]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (m[i])[k] = (((m[i])[k]) + (((m[i])[j]) * sum)); } } for (r = 0; r <= 3; r += 1) { sum = 0.0; for (i = j; i <= 3; i += 1) { sum += ((x[i])[r]) * ((m[i])[j]); } sum = sum * beta; for (i = j; i <= 3; i += 1) { (x[i])[r] = (((x[i])[r]) + (sum * ((m[i])[j]))); } } } for (r = 0; r <= 3; r += 1) { for (i = 3; i >= 0; i += -1) { for (j = (i + 1); j <= 3; j += 1) { (x[i])[r] = (((x[i])[r]) - (((x[j])[r]) * ((m[i])[j]))); } (x[i])[r] = (((x[i])[r]) / ((d[i])[r])); } } for (i = 0; i <= 3; i += 1) { for (j = 0; j <= 3; j += 1) { rcvr[(i * 4) + j] = (((float) ((x[i])[j]))); } } } /* Primitive. Load the given index array into the receiver. NOTE: dstStart is a zero-based index. */ EXPORT(sqInt) b3dLoadIndexArray(void) { sqInt count; sqInt dstArray; int *dstPtr; sqInt dstSize; sqInt dstStart; sqInt i; sqInt idx; sqInt maxValue; sqInt srcArray; int *srcPtr; sqInt vtxOffset; vtxOffset = interpreterProxy->stackIntegerValue(0); maxValue = interpreterProxy->stackIntegerValue(1); count = interpreterProxy->stackIntegerValue(2); srcArray = interpreterProxy->stackObjectValue(3); dstStart = interpreterProxy->stackIntegerValue(4); dstArray = interpreterProxy->stackObjectValue(5); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isWords(srcArray))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(srcArray)) < count) { return interpreterProxy->primitiveFail(); } /* Check dstArray */ srcPtr = ((int*) (interpreterProxy->firstIndexableField(srcArray))); /* Check if there is enough room left in dstArray */ dstSize = interpreterProxy->slotSizeOf(dstArray); if ((dstStart + count) > dstSize) { return interpreterProxy->primitiveFail(); } /* Do the actual work */ dstPtr = ((int *) (interpreterProxy->firstIndexableField(dstArray))); for (i = 0; i <= (count - 1); i += 1) { idx = srcPtr[i]; if ((idx < 1) || (idx > maxValue)) { return interpreterProxy->primitiveFail(); } dstPtr[dstStart + i] = (idx + vtxOffset); } interpreterProxy->pop(7); interpreterProxy->pushInteger(count); } /* Primitive. Load the data into the given vertex buffer. NOTE: dstStart is a zero-based index. */ EXPORT(sqInt) b3dLoadVertexBuffer(void) { int *colorPtr; sqInt count; int *defaultColor; int *defaultNormal; int *defaultTexCoords; int *defaultVtx; int *dstPtr; sqInt dstStart; sqInt i; int *normalPtr; int *pVtx; int *texPtr; int *vtxPtr; defaultVtx = stackPrimitiveVertex(0); count = interpreterProxy->stackIntegerValue(1); texPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(2), 2 * count); colorPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(3), count); normalPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(4), 3 * count); vtxPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(5), 3 * count); dstStart = interpreterProxy->stackIntegerValue(6); /* Check for all problems above */ dstPtr = stackPrimitiveVertexArrayofSize(7, dstStart + count); if ((dstPtr == null) || ((defaultVtx == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } if (normalPtr == null) { defaultNormal = defaultVtx + PrimVtxNormal; } else { defaultNormal = normalPtr; } if (texPtr == null) { defaultTexCoords = defaultVtx + PrimVtxTexCoords; } else { defaultTexCoords = texPtr; } if (colorPtr == null) { defaultColor = defaultVtx + PrimVtxColor32; } else { defaultColor = colorPtr; } pVtx = dstPtr + (dstStart * PrimVertexSize); for (i = 0; i <= (count - 1); i += 1) { pVtx[PrimVtxPositionX] = (vtxPtr[0]); pVtx[PrimVtxPositionY] = (vtxPtr[1]); pVtx[PrimVtxPositionZ] = (vtxPtr[2]); pVtx[PrimVtxNormalX] = (defaultNormal[0]); pVtx[PrimVtxNormalY] = (defaultNormal[1]); pVtx[PrimVtxNormalZ] = (defaultNormal[2]); pVtx[PrimVtxColor32] = (defaultColor[0]); pVtx[PrimVtxTexCoordU] = (defaultTexCoords[0]); pVtx[PrimVtxTexCoordV] = (defaultTexCoords[1]); pVtx += PrimVertexSize; vtxPtr += 3; if (!(normalPtr == null)) { defaultNormal += 3; } if (!(colorPtr == null)) { defaultColor += 1; } if (!(texPtr == null)) { defaultTexCoords += 2; } } interpreterProxy->pop(9); interpreterProxy->pushInteger(count); } /* Primitive. Determine the bounds for all vertices in the vertex buffer. */ EXPORT(sqInt) b3dMapVertexBuffer(void) { sqInt boxArray; void *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } boxArray = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(((interpreterProxy->fetchClassOf(boxArray)) == (interpreterProxy->classArray())) && ((interpreterProxy->slotSizeOf(boxArray)) == 4))) { return interpreterProxy->primitiveFail(); } vtxCount = interpreterProxy->stackIntegerValue(1); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(2, vtxCount); if ((vtxArray == null) || (interpreterProxy->failed())) { return interpreterProxy->primitiveFail(); } mapVBofSizeinto(vtxArray, vtxCount, boxArray); if (!(interpreterProxy->failed())) { interpreterProxy->pop(3); } } EXPORT(sqInt) b3dOrthoNormInverseMatrix(void) { float *dst; sqInt dstOop; double rx; double ry; double rz; float *src; sqInt srcOop; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* Transpose upper 3x3 matrix */ /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[4] = (src[1]); dst[6] = (src[9]); dst[8] = (src[2]); dst[9] = (src[6]); x = src[3]; y = src[7]; z = src[11]; rx = ((x * (dst[0])) + (y * (dst[1]))) + (z * (dst[2])); ry = ((x * (dst[4])) + (y * (dst[5]))) + (z * (dst[6])); rz = ((x * (dst[8])) + (y * (dst[9]))) + (z * (dst[10])); dst[3] = (((float) (0.0 - rx))); dst[7] = (((float) (0.0 - ry))); dst[11] = (((float) (0.0 - rz))); interpreterProxy->pop(1); interpreterProxy->push(dstOop); } /* Primitive. Return the next clipped triangle from the vertex buffer and return its index. */ EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void) { sqInt firstIndex; sqInt i; sqInt idx1; sqInt idx2; sqInt idx3; int *idxArray; sqInt idxCount; sqInt triMask; int *vtxArray; sqInt vtxCount; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } idxCount = interpreterProxy->stackIntegerValue(0); vtxCount = interpreterProxy->stackIntegerValue(2); firstIndex = interpreterProxy->stackIntegerValue(4); if (interpreterProxy->failed()) { return null; } vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount); idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxCount, 1, vtxCount); if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } idxArray -= 1; vtxArray -= PrimVertexSize; for (i = firstIndex; i <= idxCount; i += 3) { idx1 = idxArray[i]; idx2 = idxArray[i + 1]; idx3 = idxArray[i + 2]; if (!((idx1 == 0) || ((idx2 == 0) || (idx3 == 0)))) { /* Check if tri is completely inside */ triMask = (vtxArray[(idx1 * PrimVertexSize) + PrimVtxClipFlags]) & ((vtxArray[(idx2 * PrimVertexSize) + PrimVtxClipFlags]) & (vtxArray[(idx3 * PrimVertexSize) + PrimVtxClipFlags])); if (!((InAllMask & triMask) == InAllMask)) { if (triMask & OutAllMask) { idxArray[i] = 0; idxArray[i + 1] = 0; idxArray[i + 2] = 0; } else { interpreterProxy->pop(6); interpreterProxy->pushInteger(i); return null; } } } } interpreterProxy->pop(6); interpreterProxy->pushInteger(0); } /* Primitive. Return the minimal number of words needed for a primitive object. */ EXPORT(sqInt) b3dPrimitiveObjectSize(void) { sqInt objSize; objSize = (((sqInt) (sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex)) >> 2)) + 1; interpreterProxy->pop(1); interpreterProxy->pushInteger(objSize); } /* Primitive. Return the minimal number of words needed for a primitive object. */ EXPORT(sqInt) b3dPrimitiveTextureSize(void) { sqInt objSize; objSize = (((sqInt) (sizeof(B3DTexture)) >> 2)) + 1; interpreterProxy->pop(1); interpreterProxy->pushInteger(objSize); } /* Primitive. Return the version of the rasterizer. */ EXPORT(sqInt) b3dRasterizerVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } /* Primitive. Shade all the vertices in the vertex buffer using the given array of primitive light sources. Return true on success. */ EXPORT(sqInt) b3dShadeVertexBuffer(void) { sqInt i; sqInt j; sqInt lightArray; sqInt lightCount; float *vtxArray; sqInt vtxCount; sqInt lightOop; sqInt rgba; sqInt a; sqInt b; sqInt g; sqInt r; vbFlags = interpreterProxy->stackIntegerValue(0); primMaterial = stackMaterialValue(1); lightArray = stackLightArrayValue(2); vtxCount = interpreterProxy->stackIntegerValue(3); vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount); if ((vtxArray == null) || ((primMaterial == null) || (interpreterProxy->failed()))) { return interpreterProxy->primitiveFail(); } litVertex = vtxArray; /* Go over all vertices */ lightCount = interpreterProxy->slotSizeOf(lightArray); for (i = 1; i <= vtxCount; i += 1) { /* begin loadPrimitiveVertex */ rgba = (((int*) litVertex))[PrimVtxColor32]; vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0)); if (vbFlags & VBTrackEmission) { vtxOutColor[0] = ((vtxInColor[0]) + (primMaterial[EmissionRed])); vtxOutColor[1] = ((vtxInColor[1]) + (primMaterial[EmissionGreen])); vtxOutColor[2] = ((vtxInColor[2]) + (primMaterial[EmissionBlue])); vtxOutColor[3] = ((vtxInColor[3]) + (primMaterial[EmissionAlpha])); } else { vtxOutColor[0] = (primMaterial[EmissionRed]); vtxOutColor[1] = (primMaterial[EmissionGreen]); vtxOutColor[2] = (primMaterial[EmissionBlue]); vtxOutColor[3] = (primMaterial[EmissionAlpha]); } for (j = 0; j <= (lightCount - 1); j += 1) { /* begin fetchLightSource:ofObject: */ lightOop = interpreterProxy->fetchPointerofObject(j, lightArray); primLight = interpreterProxy->firstIndexableField(lightOop); /* begin loadPrimitiveLightSource */ lightFlags = (((int*) primLight))[PrimLightFlags]; shadeVertex(); } /* begin storePrimitiveVertex */ r = ((sqInt)((vtxOutColor[0]) * 255)); r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255))); g = ((sqInt)((vtxOutColor[1]) * 255)); g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255))); b = ((sqInt)((vtxOutColor[2]) * 255)); b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255))); a = ((sqInt)((vtxOutColor[3]) * 255)); a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255))); (((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8)); litVertex += PrimVertexSize; } interpreterProxy->pop(6); interpreterProxy->pushBool(1); } /* Return the current shader version. */ EXPORT(sqInt) b3dShaderVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } /* Primitive. Start the rasterizer. */ EXPORT(sqInt) b3dStartRasterizer(void) { sqInt errCode; if (!((interpreterProxy->methodArgumentCount()) == 3)) { return interpreterProxy->primitiveFail(); } if (!(loadRasterizerState(2))) { return interpreterProxy->primitiveFail(); } loadTexturesFrom(0); if (interpreterProxy->failed()) { return null; } loadObjectsFrom(1); if (interpreterProxy->failed()) { return null; } errCode = b3dMainLoop(&state, B3D_NO_ERROR); storeObjectsInto(1); interpreterProxy->pop(4); interpreterProxy->pushInteger(errCode); } EXPORT(sqInt) b3dTransformDirection(void) { float *matrix; double rx; double ry; double rz; sqInt v3Oop; float *vertex; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); interpreterProxy->pop(2); interpreterProxy->push(v3Oop); } /* Transform two matrices into the third */ EXPORT(sqInt) b3dTransformMatrixWithInto(void) { float *m1; float *m2; float *m3; m3 = stackMatrix(0); m2 = stackMatrix(1); m1 = stackMatrix(2); if (((m1 == null) || (m2 == null)) || (m3 == null)) { return interpreterProxy->primitiveFail(); } if (m2 == m3) { return interpreterProxy->primitiveFail(); } transformMatrixwithinto(m1, m2, m3); interpreterProxy->pop(3); } EXPORT(sqInt) b3dTransformPoint(void) { float *matrix; double rw; double rx; double ry; double rz; sqInt v3Oop; float *vertex; double x; double y; double z; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } v3Oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) { return interpreterProxy->primitiveFail(); } vertex = interpreterProxy->firstIndexableField(v3Oop); matrix = stackMatrix(1); if (matrix == null) { return interpreterProxy->primitiveFail(); } x = vertex[0]; y = vertex[1]; z = vertex[2]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); v3Oop = interpreterProxy->clone(v3Oop); vertex = interpreterProxy->firstIndexableField(v3Oop); if (rw == 1.0) { vertex[0] = (((float) rx)); vertex[1] = (((float) ry)); vertex[2] = (((float) rz)); } else { if (rw == 0.0) { rw = 0.0; } else { rw = 1.0 / rw; } vertex[0] = (((float) (rx * rw))); vertex[1] = (((float) (ry * rw))); vertex[2] = (((float) (rz * rw))); } interpreterProxy->pop(2); interpreterProxy->push(v3Oop); } /* Transform the normal of the given primitive vertex using the argument matrix and rescale the normal if necessary. */ EXPORT(sqInt) b3dTransformPrimitiveNormal(void) { float *matrix; float *pVertex; sqInt rescale; rescale = interpreterProxy->stackValue(0); if (!(rescale == (interpreterProxy->nilObject()))) { rescale = interpreterProxy->booleanValueOf(rescale); } matrix = stackMatrix(1); pVertex = stackPrimitiveVertex(2); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } if ((rescale != 1) && (rescale != 0)) { rescale = analyzeMatrix3x3Length(matrix); } transformPrimitiveNormalbyrescale(pVertex, matrix, rescale); interpreterProxy->pop(3); } /* Transform the position of the given primitive vertex the given matrix and store the result back inplace. */ EXPORT(sqInt) b3dTransformPrimitivePosition(void) { float *matrix; float *pVertex; matrix = stackMatrix(0); pVertex = stackPrimitiveVertex(1); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } transformPrimitivePositionby(pVertex, matrix); interpreterProxy->pop(2); } /* Transform the position of the given primitive vertex the given matrix and store the result in homogenous coordinates at rasterPos. */ EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void) { float *matrix; float *pVertex; matrix = stackMatrix(0); pVertex = stackPrimitiveVertex(1); if ((matrix == null) || (pVertex == null)) { return interpreterProxy->primitiveFail(); } transformPrimitiveRasterPositionby(pVertex, matrix); interpreterProxy->pop(2); } /* Transform an entire vertex buffer using the supplied modelview and projection matrix. */ EXPORT(sqInt) b3dTransformVertexBuffer(void) { sqInt flags; float *modelViewMatrix; float *projectionMatrix; float *vtxArray; sqInt vtxCount; flags = interpreterProxy->stackIntegerValue(0); projectionMatrix = stackMatrix(1); modelViewMatrix = stackMatrix(2); vtxCount = interpreterProxy->stackIntegerValue(3); vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount); if (((projectionMatrix == null) || (modelViewMatrix == null)) || (vtxArray == null)) { return interpreterProxy->primitiveFail(); } if (interpreterProxy->failed()) { return null; } transformVBcountbyandflags(vtxArray, vtxCount, modelViewMatrix, projectionMatrix, flags); interpreterProxy->pop(5); } /* Return the current version of the transformer */ EXPORT(sqInt) b3dTransformerVersion(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(1); } EXPORT(sqInt) b3dTransposeMatrix(void) { float *dst; sqInt dstOop; float *src; sqInt srcOop; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } srcOop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) { return interpreterProxy->primitiveFail(); } /* reload srcOop in case of GC */ dstOop = interpreterProxy->clone(srcOop); srcOop = interpreterProxy->stackObjectValue(0); src = interpreterProxy->firstIndexableField(srcOop); /* dst at: 0 put: (src at: 0). */ dst = interpreterProxy->firstIndexableField(dstOop); dst[1] = (src[4]); dst[2] = (src[8]); dst[3] = (src[12]); dst[4] = (src[1]); dst[6] = (src[9]); dst[7] = (src[13]); dst[8] = (src[2]); dst[9] = (src[6]); dst[11] = (src[14]); dst[12] = (src[3]); dst[13] = (src[7]); dst[14] = (src[11]); interpreterProxy->pop(1); interpreterProxy->push(dstOop); } static double backClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); } static double bottomClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); } static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask) { sqInt count; if (outMask == OutLeftBit) { return clipPolygonLeftFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutRightBit) { return clipPolygonRightFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutTopBit) { return clipPolygonTopFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutBottomBit) { return clipPolygonBottomFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutFrontBit) { return clipPolygonFrontFromtocount(tempVtxArray, vtxArray, vtxCount); } if (outMask == OutBackBit) { return clipPolygonBackFromtocount(tempVtxArray, vtxArray, vtxCount); } count = vtxCount; count = clipPolygonLeftFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonRightFromtocount(tempVtxArray, vtxArray, count); if (count == 0) { return 0; } count = clipPolygonTopFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonBottomFromtocount(tempVtxArray, vtxArray, count); if (count == 0) { return 0; } count = clipPolygonFrontFromtocount(vtxArray, tempVtxArray, count); if (count == 0) { return 0; } count = clipPolygonBackFromtocount(tempVtxArray, vtxArray, count); return count; } static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InBackBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InBackBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InBottomBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InBottomBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InFrontBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InFrontBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InLeftBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InLeftBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InRightBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InRightBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n) { sqInt i; sqInt inLast; sqInt inNext; sqInt j; int *last; int *next; sqInt outIndex; double t; outIndex = 0; last = buf1 + (n * PrimVertexSize); next = buf1 + PrimVertexSize; inLast = (last[PrimVtxClipFlags]) & InTopBit; for (i = 1; i <= n; i += 1) { inNext = (next[PrimVtxClipFlags]) & InTopBit; if (!(inLast == inNext)) { /* Passes clip boundary */ t = (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); outIndex += 1; interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize)))); } if (inNext) { outIndex += 1; for (j = 0; j <= (PrimVertexSize - 1); j += 1) { buf2[(outIndex * PrimVertexSize) + j] = (next[j]); } } last = next; inLast = inNext; next += PrimVertexSize; } return outIndex; } /* Compute the attenuation for the current light and vertex */ static sqInt computeAttenuation(void) { lightScale = 1.0; if (lightFlags & FlagAttenuated) { lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared]))))); } } /* Compute the direction for the current light and vertex */ static sqInt computeDirection(void) { double scale; if (lightFlags & FlagPositional) { l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX])); l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY])); l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ])); l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2])); if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) { l2vDistance = sqrt(l2vDistance); scale = -1.0 / l2vDistance; } l2vDirection[0] = ((l2vDirection[0]) * scale); l2vDirection[1] = ((l2vDirection[1]) * scale); l2vDirection[2] = ((l2vDirection[2]) * scale); } else { if (lightFlags & FlagDirectional) { l2vDirection[0] = (primLight[PrimLightDirectionX]); l2vDirection[1] = (primLight[PrimLightDirectionY]); l2vDirection[2] = (primLight[PrimLightDirectionZ]); } } } /* Computes l2vSpecDir _ l2vSpecDir - vtx position safelyNormalized. */ static sqInt computeSpecularDirection(void) { double scale; scale = inverseLengthOfFloat(litVertex + PrimVtxPosition); l2vSpecDir[0] = ((l2vSpecDir[0]) - ((litVertex[PrimVtxPositionX]) * scale)); l2vSpecDir[1] = ((l2vSpecDir[1]) - ((litVertex[PrimVtxPositionY]) * scale)); l2vSpecDir[2] = ((l2vSpecDir[2]) - ((litVertex[PrimVtxPositionZ]) * scale)); } /* Compute the spot factor for a spot light */ static double computeSpotFactor(void) { double cosAngle; double deltaCos; double minCos; cosAngle = dotProductOfFloatwithDouble(primLight + PrimLightDirection, l2vDirection); cosAngle = 0.0 - cosAngle; minCos = primLight[SpotLightMinCos]; if (cosAngle < minCos) { return 0.0; } deltaCos = primLight[SpotLightDeltaCos]; if (deltaCos <= 1.0e-5) { return 1.0; } cosAngle = (cosAngle - minCos) / deltaCos; return pow(cosAngle,(primLight[SpotLightExponent])); } static sqInt determineClipFlagscount(void *vtxArray, sqInt count) { sqInt flags; sqInt fullMask; sqInt i; float *vtxPtr; double w; double w2; double x; double y; double z; vtxPtr = ((float *) vtxArray); fullMask = InAllMask + OutAllMask; for (i = 1; i <= count; i += 1) { w = vtxPtr[PrimVtxRasterPosW]; w2 = 0.0 - w; flags = 0; x = vtxPtr[PrimVtxRasterPosX]; if (x >= w2) { flags = flags | InLeftBit; } else { flags = flags | OutLeftBit; } if (x <= w) { flags = flags | InRightBit; } else { flags = flags | OutRightBit; } y = vtxPtr[PrimVtxRasterPosY]; if (y >= w2) { flags = flags | InBottomBit; } else { flags = flags | OutBottomBit; } if (y <= w) { flags = flags | InTopBit; } else { flags = flags | OutTopBit; } z = vtxPtr[PrimVtxRasterPosZ]; if (z >= w2) { flags = flags | InFrontBit; } else { flags = flags | OutFrontBit; } if (z <= w) { flags = flags | InBackBit; } else { flags = flags | OutBackBit; } fullMask = fullMask & flags; (((int *) vtxPtr))[PrimVtxClipFlags] = flags; vtxPtr += PrimVertexSize; } return fullMask; } static double dotProductOfFloatwithDouble(float * v1, double *v2) { return (((v1[0]) * (v2[0])) + ((v1[1]) * (v2[1]))) + ((v1[2]) * (v2[2])); } /* Fetch the primitive light source from the given array. Note: No checks are done within here - that happened in stackLightArrayValue: */ static void* fetchLightSourceofObject(sqInt index, sqInt anArray) { sqInt lightOop; lightOop = interpreterProxy->fetchPointerofObject(index, anArray); return interpreterProxy->firstIndexableField(lightOop); } static double frontClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ]))); } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { loadBBFn = interpreterProxy->ioLoadFunctionFrom("loadBitBltFrom", bbPluginName); copyBitsFn = interpreterProxy->ioLoadFunctionFrom("copyBitsFromtoat", bbPluginName); return (loadBBFn != 0) && (copyBitsFn != 0); } /* Interpolate the primitive vertices last/next at the parameter t */ static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out) { double delta; sqInt flags; unsigned int lastValue; unsigned int newValue; unsigned int nextValue; unsigned int rgbaLast; unsigned int rgbaNext; double w; double w2; double x; double y; double z; delta = (next[PrimVtxRasterPosX]) - (last[PrimVtxRasterPosX]); x = (last[PrimVtxRasterPosX]) + (delta * t); out[PrimVtxRasterPosX] = (((float) x)); delta = (next[PrimVtxRasterPosY]) - (last[PrimVtxRasterPosY]); y = (last[PrimVtxRasterPosY]) + (delta * t); out[PrimVtxRasterPosY] = (((float) y)); delta = (next[PrimVtxRasterPosZ]) - (last[PrimVtxRasterPosZ]); z = (last[PrimVtxRasterPosZ]) + (delta * t); out[PrimVtxRasterPosZ] = (((float) z)); delta = (next[PrimVtxRasterPosW]) - (last[PrimVtxRasterPosW]); w = (last[PrimVtxRasterPosW]) + (delta * t); out[PrimVtxRasterPosW] = (((float) w)); w2 = 0.0 - w; flags = 0; if (x >= w2) { flags = flags | InLeftBit; } else { flags = flags | OutLeftBit; } if (x <= w) { flags = flags | InRightBit; } else { flags = flags | OutRightBit; } if (y >= w2) { flags = flags | InBottomBit; } else { flags = flags | OutBottomBit; } if (y <= w) { flags = flags | InTopBit; } else { flags = flags | OutTopBit; } if (z >= w2) { flags = flags | InFrontBit; } else { flags = flags | OutFrontBit; } if (z <= w) { flags = flags | InBackBit; } else { flags = flags | OutBackBit; } (((int *) out))[PrimVtxClipFlags] = flags; rgbaLast = (((unsigned int *) last))[PrimVtxColor32]; lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; rgbaNext = (((unsigned int *) next))[PrimVtxColor32]; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue = ((sqInt)(lastValue + delta)); lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt)(lastValue + delta))) << 8; lastValue = rgbaLast & 255; rgbaLast = ((usqInt) rgbaLast) >> 8; nextValue = rgbaNext & 255; rgbaNext = ((usqInt) rgbaNext) >> 8; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt)(lastValue + delta))) << 16; lastValue = rgbaLast & 255; nextValue = rgbaNext & 255; delta = (((int) (nextValue - lastValue))) * t; newValue += (((sqInt)(lastValue + delta))) << 24; (((unsigned int*) out))[PrimVtxColor32] = newValue; delta = (next[PrimVtxTexCoordU]) - (last[PrimVtxTexCoordU]); out[PrimVtxTexCoordU] = (((float) ((last[PrimVtxTexCoordU]) + (delta * t)))); delta = (next[PrimVtxTexCoordV]) - (last[PrimVtxTexCoordV]); out[PrimVtxTexCoordV] = (((float) ((last[PrimVtxTexCoordV]) + (delta * t)))); } static double inverseLengthOfDouble(double * aVector) { double scale; scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2])); if ((scale == 0.0) || (scale == 1.0)) { return scale; } return 1.0 / (sqrt(scale)); } static double inverseLengthOfFloat(float * aVector) { double scale; scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2])); if ((scale == 0.0) || (scale == 1.0)) { return scale; } return 1.0 / (sqrt(scale)); } static double leftClipValueFromto(sqInt last, sqInt next) { return (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); } static sqInt loadObjectsFrom(sqInt stackIndex) { sqInt arrayOop; sqInt arraySize; sqInt i; B3DPrimitiveObject **objArray; sqInt objOop; B3DPrimitiveObject *objPtr; arrayOop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(arrayOop); if (arraySize > (state.nObjects)) { return interpreterProxy->primitiveFail(); } objArray = state.objects; for (i = 0; i <= (arraySize - 1); i += 1) { objOop = interpreterProxy->fetchPointerofObject(i, arrayOop); if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) { return interpreterProxy->primitiveFail(); } objPtr = ((B3DPrimitiveObject*) (interpreterProxy->firstIndexableField(objOop))); if (objPtr->magic != B3D_PRIMITIVE_OBJECT_MAGIC) { return interpreterProxy->primitiveFail(); } objPtr->__oop__ = objOop; objArray[i] = objPtr; } } static sqInt loadPrimitiveLightSource(void) { lightFlags = (((int*) primLight))[PrimLightFlags]; } /* Load the necessary values from the current primitive vertex */ static sqInt loadPrimitiveVertex(void) { sqInt rgba; rgba = (((int*) litVertex))[PrimVtxColor32]; vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0)); rgba = ((usqInt) rgba) >> 8; vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0)); } /* Load the rasterizer state from the given stack index. */ static sqInt loadRasterizerState(sqInt stackIndex) { sqInt obj; sqInt objLen; void *objPtr; sqInt stateOop; if ((copyBitsFn == 0) || (loadBBFn == 0)) { if (!(initialiseModule())) { return 0; } } stateOop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return 0; } if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 10))) { return 0; } obj = interpreterProxy->fetchPointerofObject(0, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.faceAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(1, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.edgeAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(2, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.attrAlloc = objPtr; obj = interpreterProxy->fetchPointerofObject(3, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.aet = objPtr; obj = interpreterProxy->fetchPointerofObject(4, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.addedEdges = objPtr; obj = interpreterProxy->fetchPointerofObject(5, stateOop); if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objPtr = interpreterProxy->firstIndexableField(obj); state.fillList = objPtr; obj = interpreterProxy->fetchPointerofObject(6, stateOop); if (obj == (interpreterProxy->nilObject())) { state.nObjects = 0; state.objects = NULL; } else { if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objLen = interpreterProxy->slotSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.objects = (B3DPrimitiveObject **)objPtr; state.nObjects = objLen; } obj = interpreterProxy->fetchPointerofObject(7, stateOop); if (obj == (interpreterProxy->nilObject())) { state.nTextures = 0; state.textures = NULL; } else { if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) { return 0; } objLen = interpreterProxy->byteSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.textures = (B3DTexture *)objPtr; state.nTextures = objLen / sizeof(B3DTexture); } obj = interpreterProxy->fetchPointerofObject(8, stateOop); if (obj == (interpreterProxy->nilObject())) { state.spanSize = 0; state.spanBuffer = NULL; } else { if (!((interpreterProxy->fetchClassOf(obj)) == (interpreterProxy->classBitmap()))) { return 0; } objLen = interpreterProxy->slotSizeOf(obj); objPtr = interpreterProxy->firstIndexableField(obj); state.spanBuffer = (unsigned int *)objPtr; state.spanSize = objLen; } obj = interpreterProxy->fetchPointerofObject(9, stateOop); if (obj == (interpreterProxy->nilObject())) { state.spanDrawer = NULL; } else { if (!(((int (*) (int))loadBBFn)(obj))) { return 0; } state.spanDrawer = (b3dDrawBufferFunction) copyBitsFn; } return !(interpreterProxy->failed()); } /* Note: This still uses the old-style textures */ static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr) { void *bitsPtr; sqInt form; sqInt formBits; sqInt formDepth; sqInt formHeight; sqInt formWidth; sqInt texEnvMode; sqInt texInterpolate; sqInt texWrap; form = textureOop; if (!(interpreterProxy->isPointers(form))) { return 0; } if ((interpreterProxy->slotSizeOf(form)) < 8) { return 0; } formBits = interpreterProxy->fetchPointerofObject(0, form); formWidth = interpreterProxy->fetchIntegerofObject(1, form); formHeight = interpreterProxy->fetchIntegerofObject(2, form); formDepth = interpreterProxy->fetchIntegerofObject(3, form); texWrap = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(5, form)); texInterpolate = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(6, form)); texEnvMode = interpreterProxy->fetchIntegerofObject(7, form); if (interpreterProxy->failed()) { return 0; } if ((formWidth < 1) || ((formHeight < 1) || (formDepth != 32))) { return 0; } if (!((interpreterProxy->fetchClassOf(formBits)) == (interpreterProxy->classBitmap()))) { return 0; } if (!((interpreterProxy->byteSizeOf(formBits)) == ((formWidth * formHeight) * 4))) { return 0; } if ((texEnvMode < 0) || (texEnvMode > 1)) { return 0; } /* Set the texture parameters */ bitsPtr = interpreterProxy->firstIndexableField(formBits); return b3dLoadTexture(destPtr, formWidth, formHeight, formDepth, (unsigned int*) bitsPtr, 0, NULL) == B3D_NO_ERROR; } static sqInt loadTexturesFrom(sqInt stackIndex) { sqInt arrayOop; B3DTexture *destPtr; sqInt i; sqInt n; sqInt textureOop; arrayOop = interpreterProxy->stackObjectValue(stackIndex); if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } n = interpreterProxy->slotSizeOf(arrayOop); n = ((n < (state.nTextures)) ? n : (state.nTextures)); for (i = 0; i <= (n - 1); i += 1) { destPtr = state.textures + i; textureOop = interpreterProxy->fetchPointerofObject(i, arrayOop); if (!(loadTextureinto(textureOop, destPtr))) { return interpreterProxy->primitiveFail(); } } return 0; } /* Load the viewport from the given stack index */ static sqInt loadViewportFrom(sqInt stackIndex) { sqInt oop; sqInt p1; sqInt p2; sqInt x0; sqInt x1; sqInt y0; sqInt y1; oop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isPointers(oop))) { return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(oop)) < 2) { return interpreterProxy->primitiveFail(); } p1 = interpreterProxy->fetchPointerofObject(0, oop); p2 = interpreterProxy->fetchPointerofObject(1, oop); if (!((interpreterProxy->fetchClassOf(p1)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->fetchClassOf(p2)) == (interpreterProxy->classPoint()))) { return interpreterProxy->primitiveFail(); } x0 = interpreterProxy->fetchIntegerofObject(0, p1); y0 = interpreterProxy->fetchIntegerofObject(1, p1); x1 = interpreterProxy->fetchIntegerofObject(0, p2); y1 = interpreterProxy->fetchIntegerofObject(1, p2); if (interpreterProxy->failed()) { return null; } viewport.x0 = x0; viewport.y0 = y0; viewport.x1 = x1; viewport.y1 = y1; return 0; } static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray) { double bottom; sqInt flags; sqInt floatOop; sqInt i; double left; sqInt oop; double right; double top; float *vtxPtr; double w; double x; double y; vtxPtr = ((float *) vtxArray); for (i = 1; i <= vtxCount; i += 1) { flags = (((int *) vtxPtr))[PrimVtxClipFlags]; w = vtxPtr[PrimVtxRasterPosW]; if (!(w == 0.0)) { w = 1.0 / w; } if ((flags & OutLeftBit) != 0) { x = -1.0; } else { if ((flags & OutRightBit) != 0) { x = 1.0; } else { x = (vtxPtr[PrimVtxRasterPosX]) * w; } } if ((flags & OutTopBit) != 0) { y = -1.0; } else { if ((flags & OutBottomBit) != 0) { y = 1.0; } else { y = (vtxPtr[PrimVtxRasterPosY]) * w; } } if (i == 1) { left = right = x; top = bottom = y; } if (x < left) { left = x; } if (x > right) { right = x; } if (y < top) { top = y; } if (y > bottom) { bottom = y; } vtxPtr += PrimVertexSize; } oop = boxArray; interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(left); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(top); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(right); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(2, oop, floatOop); interpreterProxy->pushRemappableOop(oop); floatOop = interpreterProxy->floatObjectOf(bottom); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(3, oop, floatOop); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, bbPluginName)) == 0) { /* BitBlt just shut down. How nasty. */ loadBBFn = 0; copyBitsFn = 0; } } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Primitive. Set the BitBlt plugin to use. */ EXPORT(sqInt) primitiveSetBitBltPlugin(void) { sqInt i; sqInt length; sqInt needReload; sqInt pluginName; char *ptr; /* Must be string to work */ pluginName = interpreterProxy->stackValue(0); if (!(interpreterProxy->isBytes(pluginName))) { return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(pluginName); if (length >= 256) { return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(pluginName); needReload = 0; for (i = 0; i <= (length - 1); i += 1) { if (!((bbPluginName[i]) == (ptr[i]))) { bbPluginName[i] = (ptr[i]); needReload = 1; } } if (!((bbPluginName[length]) == 0)) { bbPluginName[length] = 0; needReload = 1; } if (needReload) { if (!(initialiseModule())) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(1); } static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) { sqInt i; sqInt index; double minZ; float *vtxPtr; double wValue; double zValue; minZ = 10.0; for (i = 1; i <= idxSize; i += 1) { index = idxArray[i]; if (index > 0) { vtxPtr = vtxArray + ((index - 1) * PrimVertexSize); zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if (zValue < minZ) { minZ = zValue; } } } return minZ; } static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) { sqInt i; sqInt index; sqInt minIndex; double minZ; float *vtxPtr; double wValue; double zValue; minZ = 10.0; minIndex = 0; for (i = 1; i <= idxSize; i += 1) { index = idxArray[i]; if (index > 0) { vtxPtr = vtxArray + ((index - 1) * PrimVertexSize); zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if ((minIndex == 0) || (zValue < minZ)) { minIndex = i; minZ = zValue; } } } return minIndex; } static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize) { sqInt i; double minZ; float *vtxPtr; double wValue; double zValue; minZ = 10.0; vtxPtr = vtxArray; for (i = 1; i <= vtxSize; i += 1) { zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if (zValue < minZ) { minZ = zValue; } } return minZ; } static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize) { sqInt i; sqInt minIndex; double minZ; float *vtxPtr; double wValue; double zValue; minZ = 10.0; minIndex = 0; vtxPtr = vtxArray; for (i = 1; i <= vtxSize; i += 1) { zValue = vtxPtr[PrimVtxRasterPosZ]; wValue = vtxPtr[PrimVtxRasterPosW]; if (!(wValue == 0.0)) { zValue = zValue / wValue; } if ((minIndex == 0) || (zValue < minZ)) { minIndex = i; minZ = zValue; } } return minIndex; } static double rightClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX]))); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static sqInt shadeVertex(void) { double cosAngle; double specularFactor; double aPart; double bPart; double gPart; double rPart; double aPart1; double bPart1; double gPart1; double rPart1; double aPart2; double bPart2; double gPart2; double rPart2; double scale; /* begin computeDirection */ if (lightFlags & FlagPositional) { l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX])); l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY])); l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ])); l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2])); if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) { l2vDistance = sqrt(l2vDistance); scale = -1.0 / l2vDistance; } l2vDirection[0] = ((l2vDirection[0]) * scale); l2vDirection[1] = ((l2vDirection[1]) * scale); l2vDirection[2] = ((l2vDirection[2]) * scale); } else { if (lightFlags & FlagDirectional) { l2vDirection[0] = (primLight[PrimLightDirectionX]); l2vDirection[1] = (primLight[PrimLightDirectionY]); l2vDirection[2] = (primLight[PrimLightDirectionZ]); } } /* begin computeAttenuation */ lightScale = 1.0; if (lightFlags & FlagAttenuated) { lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared]))))); } if (lightFlags & FlagHasSpot) { lightScale = lightScale * (computeSpotFactor()); } if (lightScale > 0.001) { if (lightFlags & FlagAmbientPart) { /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackAmbient) { rPart = ((vtxInColor[0]) * ((primLight + AmbientPart)[0])) * lightScale; gPart = ((vtxInColor[1]) * ((primLight + AmbientPart)[1])) * lightScale; bPart = ((vtxInColor[2]) * ((primLight + AmbientPart)[2])) * lightScale; aPart = ((vtxInColor[3]) * ((primLight + AmbientPart)[3])) * lightScale; } else { rPart = (((primMaterial + AmbientPart)[0]) * ((primLight + AmbientPart)[0])) * lightScale; gPart = (((primMaterial + AmbientPart)[1]) * ((primLight + AmbientPart)[1])) * lightScale; bPart = (((primMaterial + AmbientPart)[2]) * ((primLight + AmbientPart)[2])) * lightScale; aPart = (((primMaterial + AmbientPart)[3]) * ((primLight + AmbientPart)[3])) * lightScale; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart); vtxOutColor[1] = ((vtxOutColor[1]) + gPart); vtxOutColor[2] = ((vtxOutColor[2]) + bPart); vtxOutColor[3] = ((vtxOutColor[3]) + aPart); } if (lightFlags & FlagDiffusePart) { /* Compute angle from light->vertex to vertex normal */ /* For one-sided lighting negate cosAngle if necessary */ cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vDirection); if (((vbFlags & VBTwoSidedLighting) == 0) && (cosAngle < 0.0)) { cosAngle = 0.0 - cosAngle; } if (cosAngle > 0.0) { /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackDiffuse) { rPart1 = ((vtxInColor[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle); gPart1 = ((vtxInColor[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle); bPart1 = ((vtxInColor[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle); aPart1 = ((vtxInColor[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle); } else { rPart1 = (((primMaterial + DiffusePart)[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle); gPart1 = (((primMaterial + DiffusePart)[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle); bPart1 = (((primMaterial + DiffusePart)[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle); aPart1 = (((primMaterial + DiffusePart)[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle); } vtxOutColor[0] = ((vtxOutColor[0]) + rPart1); vtxOutColor[1] = ((vtxOutColor[1]) + gPart1); vtxOutColor[2] = ((vtxOutColor[2]) + bPart1); vtxOutColor[3] = ((vtxOutColor[3]) + aPart1); } } } if ((lightFlags & FlagSpecularPart) && ((primMaterial[MaterialShininess]) > 0.0)) { l2vSpecDir[0] = (l2vDirection[0]); l2vSpecDir[1] = (l2vDirection[1]); l2vSpecDir[2] = (l2vDirection[2]); if (vbFlags & VBUseLocalViewer) { computeSpecularDirection(); } else { l2vSpecDir[2] = ((l2vSpecDir[2]) - 1.0); } cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vSpecDir); if (cosAngle > 0.0) { /* Normalize the angle */ /* cosAngle should be somewhere between 0 and 1. If not, then the vertex normal was not normalized */ cosAngle = cosAngle * (inverseLengthOfDouble(l2vSpecDir)); if (cosAngle > 1.0) { specularFactor = pow(cosAngle,(primMaterial[MaterialShininess])); } else { if (cosAngle == 0.0) { specularFactor = 1.0; } else { specularFactor = pow(cosAngle,(primMaterial[MaterialShininess])); } } /* begin addPart:from:trackFlag:scale: */ if (vbFlags & VBTrackSpecular) { rPart2 = ((vtxInColor[0]) * ((primLight + SpecularPart)[0])) * specularFactor; gPart2 = ((vtxInColor[1]) * ((primLight + SpecularPart)[1])) * specularFactor; bPart2 = ((vtxInColor[2]) * ((primLight + SpecularPart)[2])) * specularFactor; aPart2 = ((vtxInColor[3]) * ((primLight + SpecularPart)[3])) * specularFactor; } else { rPart2 = (((primMaterial + SpecularPart)[0]) * ((primLight + SpecularPart)[0])) * specularFactor; gPart2 = (((primMaterial + SpecularPart)[1]) * ((primLight + SpecularPart)[1])) * specularFactor; bPart2 = (((primMaterial + SpecularPart)[2]) * ((primLight + SpecularPart)[2])) * specularFactor; aPart2 = (((primMaterial + SpecularPart)[3]) * ((primLight + SpecularPart)[3])) * specularFactor; } vtxOutColor[0] = ((vtxOutColor[0]) + rPart2); vtxOutColor[1] = ((vtxOutColor[1]) + gPart2); vtxOutColor[2] = ((vtxOutColor[2]) + bPart2); vtxOutColor[3] = ((vtxOutColor[3]) + aPart2); } } } /* Load an Array of B3DPrimitiveLights from the given stack index */ static sqInt stackLightArrayValue(sqInt stackIndex) { sqInt array; sqInt arraySize; sqInt i; sqInt oop; array = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) { return interpreterProxy->primitiveFail(); } arraySize = interpreterProxy->slotSizeOf(array); for (i = 0; i <= (arraySize - 1); i += 1) { oop = interpreterProxy->fetchPointerofObject(i, array); if ((oop & 1)) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimLightSize))) { return interpreterProxy->primitiveFail(); } } return array; } /* Load a B3DMaterial from the given stack index */ static void * stackMaterialValue(sqInt stackIndex) { sqInt oop; oop = interpreterProxy->stackObjectValue(stackIndex); if (interpreterProxy->failed()) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == MaterialSize)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a 4x4 transformation matrix from the interpreter stack. Return a pointer to the matrix data if successful, nil otherwise. */ static void* stackMatrix(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive index array from the interpreter stack. If aBool is true then check that all the indexes are in the range (1,maxIndex). Return a pointer to the index data if successful, nil otherwise. */ static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex) { sqInt i; int *idxPtr; sqInt index; sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(stackIndex); if (oop == null) { return null; } if (!(interpreterProxy->isWords(oop))) { return null; } oopSize = interpreterProxy->slotSizeOf(oop); if (oopSize < nItems) { return null; } idxPtr = ((int *) (interpreterProxy->firstIndexableField(oop))); if (aBool) { for (i = 0; i <= (nItems - 1); i += 1) { index = idxPtr[i]; if ((index < 0) || (index > maxIndex)) { return null; } } } return idxPtr; } /* Load a primitive vertex from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertex(sqInt index) { sqInt oop; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimVertexSize)) { return interpreterProxy->firstIndexableField(oop); } return null; } /* Load a primitive vertex array from the interpreter stack. Return a pointer to the vertex data if successful, nil otherwise. */ static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems) { sqInt oop; sqInt oopSize; oop = interpreterProxy->stackObjectValue(index); if (oop == null) { return null; } if (interpreterProxy->isWords(oop)) { oopSize = interpreterProxy->slotSizeOf(oop); if (((oopSize >= nItems) * PrimVertexSize) && ((oopSize % PrimVertexSize) == 0)) { return interpreterProxy->firstIndexableField(oop); } } return null; } static sqInt storeObjectsInto(sqInt stackIndex) { sqInt arrayOop; sqInt arraySize; sqInt i; sqInt objOop; arrayOop = interpreterProxy->stackObjectValue(stackIndex); arraySize = state.nObjects; for (i = 0; i <= (arraySize - 1); i += 1) { objOop = state.objects[i]->__oop__; interpreterProxy->storePointerofObjectwithValue(i, arrayOop, objOop); } } /* Store the computed output color back into the current primitive vertex. Clamp the r,g,b,a part to be in the range 0-255. */ static sqInt storePrimitiveVertex(void) { sqInt a; sqInt b; sqInt g; sqInt r; r = ((sqInt)((vtxOutColor[0]) * 255)); r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255))); g = ((sqInt)((vtxOutColor[1]) * 255)); g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255))); b = ((sqInt)((vtxOutColor[2]) * 255)); b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255))); a = ((sqInt)((vtxOutColor[3]) * 255)); /* The following is equal to b + (g << 8) + (r << 16) + (a << 24) */ a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255))); (((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8)); } static double topClipValueFromto(sqInt last, sqInt next) { return (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY]))); } /* Transform src with arg into dst. It is allowed that src == dst but not arg == dst */ static sqInt transformMatrixwithinto(float *src, float *arg, float *dst) { float c1; float c2; float c3; float c4; sqInt i; float *m1; float *m2; float *m3; m1 = ((float *) src); m2 = ((float *) arg); m3 = ((float *) dst); for (i = 0; i <= 3; i += 1) { /* Compute next row */ c1 = ((((m1[0]) * (m2[0])) + ((m1[1]) * (m2[4]))) + ((m1[2]) * (m2[8]))) + ((m1[3]) * (m2[12])); c2 = ((((m1[0]) * (m2[1])) + ((m1[1]) * (m2[5]))) + ((m1[2]) * (m2[9]))) + ((m1[3]) * (m2[13])); c3 = ((((m1[0]) * (m2[2])) + ((m1[1]) * (m2[6]))) + ((m1[2]) * (m2[10]))) + ((m1[3]) * (m2[14])); /* Store result */ c4 = ((((m1[0]) * (m2[3])) + ((m1[1]) * (m2[7]))) + ((m1[2]) * (m2[11]))) + ((m1[3]) * (m2[15])); m3[0] = c1; m3[1] = c2; m3[2] = c3; m3[3] = c4; m1 += 4; m3 += 4; } } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale) { double dot; double rx; double ry; double rz; double x; double y; double z; x = pVertex[PrimVtxNormalX]; y = pVertex[PrimVtxNormalY]; z = pVertex[PrimVtxNormalZ]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); if (rescale) { dot = ((rx * rx) + (ry * ry)) + (rz * rz); if (dot < 1.0e-20) { rx = ry = rz = 0.0; } else { if (!(dot == 1.0)) { dot = 1.0 / (sqrt(dot)); rx = rx * dot; ry = ry * dot; rz = rz * dot; } } } pVertex[PrimVtxNormalX] = (((float) rx)); pVertex[PrimVtxNormalY] = (((float) ry)); pVertex[PrimVtxNormalZ] = (((float) rz)); } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitivePositionby(float *pVertex, float *matrix) { double rw; double rx; double ry; double rz; double x; double y; double z; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); if (rw == 1.0) { pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } else { if (rw == 0.0) { rw = 0.0; } else { rw = 1.0 / rw; } pVertex[PrimVtxPositionX] = (((float) (rx * rw))); pVertex[PrimVtxPositionY] = (((float) (ry * rw))); pVertex[PrimVtxPositionZ] = (((float) (rz * rw))); } } /* Transform the position of the given primitive vertex assuming that matrix a41 = a42 = a43 = 0.0 and a44 = 1.0 */ static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix) { double rx; double ry; double rz; double x; double y; double z; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } /* Transform the position of the given primitive vertex assuming that matrix a14 = a24 = a34 = a41 = a42 = a43 = 0.0 and a44 = 1.0 */ static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix) { double rx; double ry; double rz; double x; double y; double z; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2])); ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6])); rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10])); pVertex[PrimVtxPositionX] = (((float) rx)); pVertex[PrimVtxPositionY] = (((float) ry)); pVertex[PrimVtxPositionZ] = (((float) rz)); } /* Transform the normal of the given primitive vertex */ static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix) { double rw; double rx; double ry; double rz; double x; double y; double z; x = pVertex[PrimVtxPositionX]; y = pVertex[PrimVtxPositionY]; z = pVertex[PrimVtxPositionZ]; rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]); ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]); rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]); rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]); pVertex[PrimVtxRasterPosX] = (((float) rx)); pVertex[PrimVtxRasterPosY] = (((float) ry)); pVertex[PrimVtxRasterPosZ] = (((float) rz)); pVertex[PrimVtxRasterPosW] = (((float) rw)); } /* Transform the entire vertex array by the given matrices */ /* TODO: Check the actual trade-offs between vtxCount and analyzing */ static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags) { sqInt hasNormals; sqInt i; sqInt mvFlags; float *pVertex; sqInt prFlags; sqInt rescale; mvFlags = analyzeMatrix(modelViewMatrix); prFlags = analyzeMatrix(projectionMatrix); pVertex = ((float *) vtxArray); /* Check if we have to rescale the normals */ hasNormals = flags & VBVtxHasNormals; if (hasNormals) { if (mvFlags & FlagM44Identity) { rescale = 0; } else { rescale = analyzeMatrix3x3Length(modelViewMatrix); } } if ((mvFlags & FlagM44NoPerspective) && (prFlags == 0)) { if ((mvFlags == FlagM44NoTranslation) == 0) { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionFastby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } else { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionFasterby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } return null; } if ((mvFlags & prFlags) & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]); pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]); pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]); pVertex[PrimVtxRasterPosW] = 1.0; pVertex += PrimVertexSize; } return null; } if (mvFlags & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } return null; } if (prFlags & FlagM44Identity) { for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } if (mvFlags == (FlagM44NoPerspective + FlagM44NoPerspective)) { transformPrimitivePositionFasterby(pVertex, modelViewMatrix); } else { if (mvFlags == FlagM44NoPerspective) { transformPrimitivePositionFastby(pVertex, modelViewMatrix); } else { transformPrimitivePositionby(pVertex, modelViewMatrix); } } pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]); pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]); pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]); pVertex[PrimVtxRasterPosW] = 1.0; pVertex += PrimVertexSize; } return null; } for (i = 1; i <= vtxCount; i += 1) { if (hasNormals) { transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale); } transformPrimitivePositionby(pVertex, modelViewMatrix); transformPrimitiveRasterPositionby(pVertex, projectionMatrix); pVertex += PrimVertexSize; } } /* Load the word based array of size count from the given oop */ static void* vbLoadArraysize(sqInt oop, sqInt count) { if (oop == null) { interpreterProxy->primitiveFail(); return null; } if (oop == (interpreterProxy->nilObject())) { return null; } if (!(interpreterProxy->isWords(oop))) { interpreterProxy->primitiveFail(); return null; } if (!((interpreterProxy->slotSizeOf(oop)) == count)) { interpreterProxy->primitiveFail(); return null; } return interpreterProxy->firstIndexableField(oop); } #ifdef SQUEAK_BUILTIN_PLUGIN void* Squeak3D_exports[][3] = { {"Squeak3D", "b3dShaderVersion", (void*)b3dShaderVersion}, {"Squeak3D", "b3dTransformPrimitiveNormal", (void*)b3dTransformPrimitiveNormal}, {"Squeak3D", "b3dClipPolygon", (void*)b3dClipPolygon}, {"Squeak3D", "b3dOrthoNormInverseMatrix", (void*)b3dOrthoNormInverseMatrix}, {"Squeak3D", "b3dTransformVertexBuffer", (void*)b3dTransformVertexBuffer}, {"Squeak3D", "b3dComputeMinZ", (void*)b3dComputeMinZ}, {"Squeak3D", "b3dInitializeRasterizerState", (void*)b3dInitializeRasterizerState}, {"Squeak3D", "b3dDetermineClipFlags", (void*)b3dDetermineClipFlags}, {"Squeak3D", "getModuleName", (void*)getModuleName}, {"Squeak3D", "setInterpreter", (void*)setInterpreter}, {"Squeak3D", "b3dTransformPrimitiveRasterPosition", (void*)b3dTransformPrimitiveRasterPosition}, {"Squeak3D", "primitiveSetBitBltPlugin", (void*)primitiveSetBitBltPlugin}, {"Squeak3D", "b3dTransformMatrixWithInto", (void*)b3dTransformMatrixWithInto}, {"Squeak3D", "b3dStartRasterizer", (void*)b3dStartRasterizer}, {"Squeak3D", "b3dShadeVertexBuffer", (void*)b3dShadeVertexBuffer}, {"Squeak3D", "b3dRasterizerVersion", (void*)b3dRasterizerVersion}, {"Squeak3D", "b3dInitPrimitiveObject", (void*)b3dInitPrimitiveObject}, {"Squeak3D", "b3dLoadVertexBuffer", (void*)b3dLoadVertexBuffer}, {"Squeak3D", "b3dTransformDirection", (void*)b3dTransformDirection}, {"Squeak3D", "moduleUnloaded", (void*)moduleUnloaded}, {"Squeak3D", "b3dPrimitiveTextureSize", (void*)b3dPrimitiveTextureSize}, {"Squeak3D", "b3dComputeMinIndexZ", (void*)b3dComputeMinIndexZ}, {"Squeak3D", "b3dMapVertexBuffer", (void*)b3dMapVertexBuffer}, {"Squeak3D", "initialiseModule", (void*)initialiseModule}, {"Squeak3D", "b3dTransformerVersion", (void*)b3dTransformerVersion}, {"Squeak3D", "b3dTransposeMatrix", (void*)b3dTransposeMatrix}, {"Squeak3D", "b3dPrimitiveNextClippedTriangle", (void*)b3dPrimitiveNextClippedTriangle}, {"Squeak3D", "b3dTransformPoint", (void*)b3dTransformPoint}, {"Squeak3D", "b3dTransformPrimitivePosition", (void*)b3dTransformPrimitivePosition}, {"Squeak3D", "b3dPrimitiveObjectSize", (void*)b3dPrimitiveObjectSize}, {"Squeak3D", "b3dLoadIndexArray", (void*)b3dLoadIndexArray}, {"Squeak3D", "b3dInplaceHouseHolderInvert", (void*)b3dInplaceHouseHolderInvert}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:52 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "sqFFI.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static sqInt atomicTypeOf(sqInt value); static sqInt ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize); static sqInt ffiArgByValue(sqInt oop); static sqInt ffiArgumentSpecClass(sqInt oop, sqInt argSpec, sqInt argClass); static sqInt ffiAtomicArgByReferenceClass(sqInt oop, sqInt oopClass); static sqInt ffiAtomicStructByReferenceClass(sqInt oop, sqInt oopClass); static sqInt ffiCallWithFlagsAndTypes(sqInt address, sqInt callType, sqInt argTypeArray); static sqInt ffiCallWithFlagsArgsAndTypesOfSize(sqInt address, sqInt callType, sqInt argArray, sqInt argTypeArray, sqInt nArgs); static sqInt ffiCalloutToWithFlags(sqInt address, sqInt callType); static sqInt ffiCheckReturnWith(sqInt retSpec, sqInt retClass); static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode); static sqInt ffiCreateLongLongReturn(sqInt isSigned); static sqInt ffiCreateReturn(sqInt retVal); static sqInt ffiCreateReturnOop(sqInt retVal); static sqInt ffiCreateReturnPointer(sqInt retVal); static sqInt ffiCreateReturnStruct(void); static sqInt ffiFail(sqInt reason); static double ffiFloatValueOf(sqInt oop); static sqInt ffiGetLastError(void); static sqInt ffiIntegerValueOf(sqInt oop); static sqInt ffiLoadCalloutAddress(sqInt lit); static sqInt ffiLoadCalloutAddressFrom(sqInt oop); static sqInt ffiLoadCalloutModule(sqInt module); static sqInt ffiPushPointerContentsOf(sqInt oop); static sqInt ffiPushSignedLongLongOop(sqInt oop); static sqInt ffiPushStructureContentsOf(sqInt oop); static sqInt ffiPushUnsignedLongLongOop(sqInt oop); static sqInt ffiPushVoid(sqInt ignored); static sqInt ffiReturnCStringFrom(sqInt cPointer); static sqInt ffiSetLastError(sqInt errCode); static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt isAtomicType(sqInt typeSpec); static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveCallout(void); EXPORT(sqInt) primitiveCalloutWithArgs(void); EXPORT(sqInt) primitiveCreateManualSurface(void); EXPORT(sqInt) primitiveDestroyManualSurface(void); EXPORT(sqInt) primitiveFFIAllocate(void); EXPORT(sqInt) primitiveFFIDoubleAt(void); EXPORT(sqInt) primitiveFFIDoubleAtPut(void); EXPORT(sqInt) primitiveFFIFloatAt(void); EXPORT(sqInt) primitiveFFIFloatAtPut(void); EXPORT(sqInt) primitiveFFIFree(void); EXPORT(sqInt) primitiveFFIGetLastError(void); EXPORT(sqInt) primitiveFFIIntegerAt(void); EXPORT(sqInt) primitiveFFIIntegerAtPut(void); EXPORT(sqInt) primitiveForceLoad(void); EXPORT(sqInt) primitiveSetManualSurfacePointer(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off /*** Variables ***/ static sqInt ffiArgClass; static sqInt ffiArgHeader; static sqInt ffiArgSpec; static sqInt ffiArgSpecSize; static sqInt ffiLastError; static sqInt ffiRetClass; static sqInt ffiRetHeader; static sqInt ffiRetOop; static sqInt ffiRetSpec; static sqInt ffiRetSpecSize; #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "SqueakFFIPrims 23 January 2011 (i)" #else "SqueakFFIPrims 23 January 2011 (e)" #endif ; static sqInt atomicTypeOf(sqInt value) { return ((usqInt) (value & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; } /* return an int of the address of the byteSize slot (byte, short, int, whatever) at byteOffset in rcvr. Nominally intended for use with ExternalAddress objects, this code will work (for obscure historical reasons) with plain Byte or Word Arrays as well. */ static sqInt ffiAddressOfstartingAtsize(sqInt rcvr, sqInt byteOffset, sqInt byteSize) { sqInt addr; sqInt rcvrClass; sqInt rcvrSize; if (!(interpreterProxy->isBytes(rcvr))) { return interpreterProxy->primitiveFail(); } if (!(byteOffset > 0)) { return interpreterProxy->primitiveFail(); } rcvrClass = interpreterProxy->fetchClassOf(rcvr); rcvrSize = interpreterProxy->byteSizeOf(rcvr); if (rcvrClass == (interpreterProxy->classExternalAddress())) { if (!(rcvrSize == 4)) { return interpreterProxy->primitiveFail(); } /* don't you dare to read from object memory! */ addr = interpreterProxy->fetchPointerofObject(0, rcvr); if ((addr == 0) || (interpreterProxy->isInMemory(addr))) { return interpreterProxy->primitiveFail(); } } else { if (!(((byteOffset + byteSize) - 1) <= rcvrSize)) { return interpreterProxy->primitiveFail(); } addr = ((int) (interpreterProxy->firstIndexableField(rcvr))); } addr = (addr + byteOffset) - 1; return addr; } /* Support for generic callout. Prepare an argument by value for a callout. */ static sqInt ffiArgByValue(sqInt oop) { sqInt atomicType; double floatValue; sqInt intValue; sqInt oopClass; sqInt oopClass1; sqInt reason; sqInt reason1; sqInt reason2; /* check if the range is valid */ atomicType = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType < 0) || (atomicType > FFITypeDoubleFloat)) { /* begin ffiFail: */ reason = FFIErrorBadAtomicType; ffiLastError = reason; return interpreterProxy->primitiveFail(); } if (atomicType < FFITypeSingleFloat) { if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { /* integer types */ /* ffi support code must coerce longlong */ intValue = oop; } else { /* begin ffiIntegerValueOf: */ if ((oop & 1)) { intValue = (oop >> 1); goto l1; } if (oop == (interpreterProxy->nilObject())) { intValue = 0; goto l1; } if (oop == (interpreterProxy->falseObject())) { intValue = 0; goto l1; } if (oop == (interpreterProxy->trueObject())) { intValue = 1; goto l1; } oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { intValue = ((sqInt)(interpreterProxy->floatValueOf(oop))); goto l1; } if (oopClass == (interpreterProxy->classCharacter())) { intValue = interpreterProxy->fetchIntegerofObject(0, oop); goto l1; } if (oopClass == (interpreterProxy->classLargePositiveInteger())) { intValue = interpreterProxy->positive32BitValueOf(oop); goto l1; } intValue = interpreterProxy->signed32BitValueOf(oop); l1: /* end ffiIntegerValueOf: */; } if (interpreterProxy->failed()) { /* begin ffiFail: */ reason1 = FFIErrorCoercionFailed; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } switch (atomicType) { case 0: ffiFail(FFIErrorAttemptToPassVoid); break; case 1: ffiPushUnsignedInt(intValue); break; case 2: ffiPushUnsignedByte(intValue); break; case 3: ffiPushSignedByte(intValue); break; case 4: ffiPushUnsignedShort(intValue); break; case 5: ffiPushSignedShort(intValue); break; case 6: ffiPushUnsignedInt(intValue); break; case 7: ffiPushSignedInt(intValue); break; case 8: ffiPushUnsignedLongLongOop(intValue); break; case 9: ffiPushSignedLongLongOop(intValue); break; case 10: ffiPushUnsignedChar(intValue); break; case 11: ffiPushSignedChar(intValue); break; } } else { /* begin ffiFloatValueOf: */ oopClass1 = interpreterProxy->fetchClassOf(oop); if (oopClass1 == (interpreterProxy->classFloat())) { floatValue = interpreterProxy->floatValueOf(oop); goto l2; } floatValue = ((double) (ffiIntegerValueOf(oop)) ); l2: /* end ffiFloatValueOf: */; if (interpreterProxy->failed()) { /* begin ffiFail: */ reason2 = FFIErrorCoercionFailed; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } if (atomicType == FFITypeSingleFloat) { ffiPushSingleFloat(floatValue); } else { ffiPushDoubleFloat(floatValue); } } return 0; } /* Callout support. Prepare the given oop as argument. argSpec defines the compiled spec for the argument. argClass (if non-nil) defines the required (super)class for the argument. */ static sqInt ffiArgumentSpecClass(sqInt oop, sqInt argSpec, sqInt argClass) { sqInt isStruct; sqInt nilOop; sqInt oopClass; sqInt valueOop; sqInt ptrAddress; sqInt ptrClass; sqInt ptrValue; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt reason6; sqInt reason7; sqInt reason8; sqInt reason9; sqInt reason10; sqInt reason11; sqInt reason12; sqInt reason13; sqInt atomicType; sqInt valueOop1; sqInt atomicType1; sqInt isString; sqInt reason14; sqInt reason15; sqInt reason16; sqInt ptrType; sqInt spec; sqInt specOop; sqInt specType; sqInt reason17; sqInt reason18; sqInt reason21; sqInt reason31; sqInt reason41; sqInt reason51; sqInt reason61; sqInt reason71; sqInt reason81; sqInt reason19; sqInt reason20; sqInt reason22; sqInt atomicType2; double floatValue; sqInt intValue; sqInt oopClass2; sqInt oopClass1; sqInt reason23; sqInt reason110; sqInt reason24; /* Prefetch class (we'll need it) */ oopClass = interpreterProxy->fetchClassOf(oop); /* Do the necessary type checks */ nilOop = interpreterProxy->nilObject(); if (!(argClass == nilOop)) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason = FFIErrorWrongType; ffiLastError = reason; return interpreterProxy->primitiveFail(); } if (!((nilOop == oop) || (interpreterProxy->includesBehaviorThatOf(oopClass, argClass)))) { /* begin ffiFail: */ reason1 = FFIErrorCoercionFailed; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } } isStruct = 0; if (!(((oop & 1)) || (oop == nilOop))) { if (interpreterProxy->isPointers(oop)) { /* #isPointers: will fail if oop is SmallInteger so don't even attempt to use it */ isStruct = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classExternalStructure()); if (!((argClass == nilOop) || (isStruct))) { /* begin ffiFail: */ reason2 = FFIErrorCoercionFailed; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } } } if (isStruct) { valueOop = interpreterProxy->fetchPointerofObject(0, oop); } else { valueOop = oop; } /* Fetch and check the contents of the compiled spec */ ffiArgClass = argClass; if ((argSpec & 1)) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(argSpec))) { /* begin ffiFail: */ reason4 = FFIErrorWrongType; ffiLastError = reason4; interpreterProxy->primitiveFail(); return null; } ffiArgSpecSize = interpreterProxy->slotSizeOf(argSpec); if (ffiArgSpecSize == 0) { /* begin ffiFail: */ reason5 = FFIErrorWrongType; ffiLastError = reason5; interpreterProxy->primitiveFail(); return null; } ffiArgSpec = ((int) (interpreterProxy->firstIndexableField(argSpec))); /* Do the actual preparation of the argument */ /* Note: Order is important since FFIFlagStructure + FFIFlagPointer is used to represent 'typedef void* VoidPointer' and VoidPointer really is *struct* not pointer. */ ffiArgHeader = longAt(ffiArgSpec); if (ffiArgHeader & FFIFlagStructure) { if (!(isStruct)) { /* begin ffiFail: */ reason6 = FFIErrorCoercionFailed; ffiLastError = reason6; return interpreterProxy->primitiveFail(); } if (ffiArgHeader & FFIFlagAtomic) { /* begin ffiFail: */ reason7 = FFIErrorWrongType; ffiLastError = reason7; return interpreterProxy->primitiveFail(); } /* begin ffiPushStructureContentsOf: */ ptrValue = valueOop; ptrClass = interpreterProxy->fetchClassOf(ptrValue); if (ptrClass == (interpreterProxy->classExternalAddress())) { ptrAddress = interpreterProxy->fetchPointerofObject(0, ptrValue); if (interpreterProxy->isInMemory(ptrAddress)) { /* begin ffiFail: */ reason8 = FFIErrorInvalidPointer; ffiLastError = reason8; return interpreterProxy->primitiveFail(); } return ffiPushStructureOfLength(ptrAddress, ((int*) ffiArgSpec), ffiArgSpecSize); } if (ptrClass == (interpreterProxy->classByteArray())) { if (!((interpreterProxy->byteSizeOf(ptrValue)) == (ffiArgHeader & FFIStructSizeMask))) { /* begin ffiFail: */ reason9 = FFIErrorStructSize; ffiLastError = reason9; return interpreterProxy->primitiveFail(); } ptrAddress = ((int) (interpreterProxy->firstIndexableField(ptrValue))); if (!(ffiArgHeader & FFIFlagPointer)) { return ffiPushStructureOfLength(ptrAddress, ((int*) ffiArgSpec), ffiArgSpecSize); } if (!((ffiArgHeader & FFIStructSizeMask) == 4)) { /* begin ffiFail: */ reason10 = FFIErrorStructSize; ffiLastError = reason10; return interpreterProxy->primitiveFail(); } ptrAddress = interpreterProxy->fetchPointerofObject(0, ptrValue); if (interpreterProxy->isInMemory(ptrAddress)) { /* begin ffiFail: */ reason11 = FFIErrorInvalidPointer; ffiLastError = reason11; return interpreterProxy->primitiveFail(); } return ffiPushPointer(ptrAddress); } /* begin ffiFail: */ reason12 = FFIErrorBadArg; ffiLastError = reason12; return interpreterProxy->primitiveFail(); } if (ffiArgHeader & FFIFlagPointer) { if ((oop & 1)) { /* begin ffiFail: */ reason13 = FFIErrorIntAsPointer; ffiLastError = reason13; return interpreterProxy->primitiveFail(); } if (oop == (interpreterProxy->nilObject())) { return ffiPushPointer(null); } if (ffiArgHeader & FFIFlagAtomic) { if (isStruct) { /* begin ffiAtomicStructByReference:Class: */ if (!(oopClass == (interpreterProxy->classExternalData()))) { /* begin ffiFail: */ reason16 = FFIErrorCoercionFailed; ffiLastError = reason16; return interpreterProxy->primitiveFail(); } atomicType = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType != FFITypeVoid) { /* begin ffiValidateExternalData:AtomicType: */ ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { /* begin ffiFail: */ reason17 = FFIErrorWrongType; ffiLastError = reason17; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isPointers(ptrType))) { /* begin ffiFail: */ reason18 = FFIErrorWrongType; ffiLastError = reason18; interpreterProxy->primitiveFail(); goto l1; } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { /* begin ffiFail: */ reason21 = FFIErrorWrongType; ffiLastError = reason21; interpreterProxy->primitiveFail(); goto l1; } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { /* begin ffiFail: */ reason31 = FFIErrorWrongType; ffiLastError = reason31; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isWords(specOop))) { /* begin ffiFail: */ reason41 = FFIErrorWrongType; ffiLastError = reason41; interpreterProxy->primitiveFail(); goto l1; } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { /* begin ffiFail: */ reason51 = FFIErrorWrongType; ffiLastError = reason51; interpreterProxy->primitiveFail(); goto l1; } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { /* begin ffiFail: */ reason61 = FFIErrorWrongType; ffiLastError = reason61; interpreterProxy->primitiveFail(); goto l1; } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { /* begin ffiFail: */ reason71 = FFIErrorCoercionFailed; ffiLastError = reason71; interpreterProxy->primitiveFail(); goto l1; } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { /* begin ffiFail: */ reason81 = FFIErrorCoercionFailed; ffiLastError = reason81; interpreterProxy->primitiveFail(); goto l1; } } l1: /* end ffiValidateExternalData:AtomicType: */; if (interpreterProxy->failed()) { return null; } } valueOop1 = interpreterProxy->fetchPointerofObject(0, oop); return ffiPushPointerContentsOf(valueOop1); } else { /* begin ffiAtomicArgByReference:Class: */ atomicType1 = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType1 == FFITypeBool) { /* begin ffiFail: */ reason19 = FFIErrorCoercionFailed; ffiLastError = reason19; return interpreterProxy->primitiveFail(); } if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString()); if (isString) { return ffiPushStringOfLength(((int) (interpreterProxy->firstIndexableField(oop))), interpreterProxy->byteSizeOf(oop)); } atomicType1 = FFITypeUnsignedByte; } if ((atomicType1 == FFITypeVoid) || ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) { if (oopClass == (interpreterProxy->classByteArray())) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString()); if (isString) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } if (!(atomicType1 == FFITypeVoid)) { /* begin ffiFail: */ reason20 = FFIErrorCoercionFailed; ffiLastError = reason20; return interpreterProxy->primitiveFail(); } } if ((atomicType1 <= FFITypeSignedInt) || (atomicType1 == FFITypeSingleFloat)) { if (interpreterProxy->isWords(oop)) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } } /* begin ffiFail: */ reason22 = FFIErrorCoercionFailed; ffiLastError = reason22; return interpreterProxy->primitiveFail(); } } if (!(isStruct)) { /* begin ffiFail: */ reason14 = FFIErrorCoercionFailed; ffiLastError = reason14; return interpreterProxy->primitiveFail(); } return ffiPushPointerContentsOf(valueOop); } if (ffiArgHeader & FFIFlagAtomic) { /* begin ffiArgByValue: */ atomicType2 = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((atomicType2 < 0) || (atomicType2 > FFITypeDoubleFloat)) { /* begin ffiFail: */ reason23 = FFIErrorBadAtomicType; ffiLastError = reason23; interpreterProxy->primitiveFail(); goto l4; } if (atomicType2 < FFITypeSingleFloat) { if ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { intValue = valueOop; } else { /* begin ffiIntegerValueOf: */ if ((valueOop & 1)) { intValue = (valueOop >> 1); goto l3; } if (valueOop == (interpreterProxy->nilObject())) { intValue = 0; goto l3; } if (valueOop == (interpreterProxy->falseObject())) { intValue = 0; goto l3; } if (valueOop == (interpreterProxy->trueObject())) { intValue = 1; goto l3; } oopClass2 = interpreterProxy->fetchClassOf(valueOop); if (oopClass2 == (interpreterProxy->classFloat())) { intValue = ((sqInt)(interpreterProxy->floatValueOf(valueOop))); goto l3; } if (oopClass2 == (interpreterProxy->classCharacter())) { intValue = interpreterProxy->fetchIntegerofObject(0, valueOop); goto l3; } if (oopClass2 == (interpreterProxy->classLargePositiveInteger())) { intValue = interpreterProxy->positive32BitValueOf(valueOop); goto l3; } intValue = interpreterProxy->signed32BitValueOf(valueOop); l3: /* end ffiIntegerValueOf: */; } if (interpreterProxy->failed()) { /* begin ffiFail: */ reason110 = FFIErrorCoercionFailed; ffiLastError = reason110; interpreterProxy->primitiveFail(); goto l4; } switch (atomicType2) { case 0: ffiFail(FFIErrorAttemptToPassVoid); break; case 1: ffiPushUnsignedInt(intValue); break; case 2: ffiPushUnsignedByte(intValue); break; case 3: ffiPushSignedByte(intValue); break; case 4: ffiPushUnsignedShort(intValue); break; case 5: ffiPushSignedShort(intValue); break; case 6: ffiPushUnsignedInt(intValue); break; case 7: ffiPushSignedInt(intValue); break; case 8: ffiPushUnsignedLongLongOop(intValue); break; case 9: ffiPushSignedLongLongOop(intValue); break; case 10: ffiPushUnsignedChar(intValue); break; case 11: ffiPushSignedChar(intValue); break; } } else { /* begin ffiFloatValueOf: */ oopClass1 = interpreterProxy->fetchClassOf(valueOop); if (oopClass1 == (interpreterProxy->classFloat())) { floatValue = interpreterProxy->floatValueOf(valueOop); goto l2; } floatValue = ((double) (ffiIntegerValueOf(valueOop)) ); l2: /* end ffiFloatValueOf: */; if (interpreterProxy->failed()) { /* begin ffiFail: */ reason24 = FFIErrorCoercionFailed; ffiLastError = reason24; interpreterProxy->primitiveFail(); goto l4; } if (atomicType2 == FFITypeSingleFloat) { ffiPushSingleFloat(floatValue); } else { ffiPushDoubleFloat(floatValue); } } l4: /* end ffiArgByValue: */; return 0; } /* begin ffiFail: */ reason15 = FFIErrorWrongType; ffiLastError = reason15; return interpreterProxy->primitiveFail(); } /* Support for generic callout. Prepare a pointer reference to an atomic type for callout. Note: for type 'void*' we allow either one of ByteArray/String/Symbol or wordVariableSubclass. */ static sqInt ffiAtomicArgByReferenceClass(sqInt oop, sqInt oopClass) { sqInt atomicType; sqInt isString; sqInt reason; sqInt reason1; sqInt reason2; atomicType = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType == FFITypeBool) { /* begin ffiFail: */ reason = FFIErrorCoercionFailed; ffiLastError = reason; return interpreterProxy->primitiveFail(); } if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { /* string value (char*) */ /* note: the only types allowed for passing into char* types are ByteArray, String, Symbol and *no* other byte indexed objects (e.g., CompiledMethod, LargeInteger). We only check for strings here and fall through to the byte* check otherwise. */ isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString()); if (isString) { return ffiPushStringOfLength(((int) (interpreterProxy->firstIndexableField(oop))), interpreterProxy->byteSizeOf(oop)); } atomicType = FFITypeUnsignedByte; } if ((atomicType == FFITypeVoid) || ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) { if (oopClass == (interpreterProxy->classByteArray())) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } isString = interpreterProxy->includesBehaviorThatOf(oopClass, interpreterProxy->classString()); if (isString) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } if (!(atomicType == FFITypeVoid)) { /* begin ffiFail: */ reason1 = FFIErrorCoercionFailed; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } } if ((atomicType <= FFITypeSignedInt) || (atomicType == FFITypeSingleFloat)) { if (interpreterProxy->isWords(oop)) { return ffiPushPointer(((int) (interpreterProxy->firstIndexableField(oop)))); } } /* begin ffiFail: */ reason2 = FFIErrorCoercionFailed; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } /* Support for generic callout. Prepare an external pointer reference to an atomic type for callout. */ static sqInt ffiAtomicStructByReferenceClass(sqInt oop, sqInt oopClass) { sqInt atomicType; sqInt valueOop; sqInt reason; sqInt ptrType; sqInt spec; sqInt specOop; sqInt specType; sqInt reason9; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt reason6; sqInt reason7; sqInt reason8; if (!(oopClass == (interpreterProxy->classExternalData()))) { /* begin ffiFail: */ reason = FFIErrorCoercionFailed; ffiLastError = reason; return interpreterProxy->primitiveFail(); } /* no type checks for void pointers */ atomicType = ((usqInt) (ffiArgHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType != FFITypeVoid) { /* begin ffiValidateExternalData:AtomicType: */ ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { /* begin ffiFail: */ reason9 = FFIErrorWrongType; ffiLastError = reason9; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isPointers(ptrType))) { /* begin ffiFail: */ reason1 = FFIErrorWrongType; ffiLastError = reason1; interpreterProxy->primitiveFail(); goto l1; } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { /* begin ffiFail: */ reason2 = FFIErrorWrongType; ffiLastError = reason2; interpreterProxy->primitiveFail(); goto l1; } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isWords(specOop))) { /* begin ffiFail: */ reason4 = FFIErrorWrongType; ffiLastError = reason4; interpreterProxy->primitiveFail(); goto l1; } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { /* begin ffiFail: */ reason5 = FFIErrorWrongType; ffiLastError = reason5; interpreterProxy->primitiveFail(); goto l1; } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { /* begin ffiFail: */ reason6 = FFIErrorWrongType; ffiLastError = reason6; interpreterProxy->primitiveFail(); goto l1; } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { /* begin ffiFail: */ reason7 = FFIErrorCoercionFailed; ffiLastError = reason7; interpreterProxy->primitiveFail(); goto l1; } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { /* begin ffiFail: */ reason8 = FFIErrorCoercionFailed; ffiLastError = reason8; interpreterProxy->primitiveFail(); goto l1; } } l1: /* end ffiValidateExternalData:AtomicType: */; if (interpreterProxy->failed()) { return null; } } valueOop = interpreterProxy->fetchPointerofObject(0, oop); return ffiPushPointerContentsOf(valueOop); } /* Generic callout. Does the actual work. */ static sqInt ffiCallWithFlagsAndTypes(sqInt address, sqInt callType, sqInt argTypeArray) { sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypes; sqInt i; sqInt nArgs; sqInt oop; sqInt stackIndex; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt reason6; if (!(ffiSupportsCallingConvention(callType))) { /* begin ffiFail: */ reason = FFIErrorCallType; ffiLastError = reason; return interpreterProxy->primitiveFail(); } /* Fetch return type and args */ argTypes = argTypeArray; argType = interpreterProxy->fetchPointerofObject(0, argTypes); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); /* begin ffiCheckReturn:With: */ if (!(argClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason1 = FFIErrorBadReturn; ffiLastError = reason1; interpreterProxy->primitiveFail(); goto l1; } } ffiRetClass = argClass; if ((argSpec & 1)) { /* begin ffiFail: */ reason2 = FFIErrorWrongType; ffiLastError = reason2; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isWords(argSpec))) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; interpreterProxy->primitiveFail(); goto l1; } ffiRetSpecSize = interpreterProxy->slotSizeOf(argSpec); if (ffiRetSpecSize == 0) { /* begin ffiFail: */ reason4 = FFIErrorWrongType; ffiLastError = reason4; interpreterProxy->primitiveFail(); goto l1; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(argSpec))); ffiRetHeader = longAt(ffiRetSpec); if (!(ffiRetHeader & FFIFlagAtomic)) { if (ffiRetClass == (interpreterProxy->nilObject())) { /* begin ffiFail: */ reason5 = FFIErrorBadReturn; ffiLastError = reason5; interpreterProxy->primitiveFail(); goto l1; } } if (!(ffiCanReturn(((int*) ffiRetSpec), ffiRetSpecSize))) { /* begin ffiFail: */ reason6 = FFIErrorBadReturn; ffiLastError = reason6; interpreterProxy->primitiveFail(); } l1: /* end ffiCheckReturn:With: */; if (interpreterProxy->failed()) { return 0; } ffiRetOop = argType; nArgs = interpreterProxy->methodArgumentCount(); /* stack index goes downwards */ stackIndex = nArgs - 1; for (i = 1; i <= nArgs; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypes); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = interpreterProxy->stackValue(stackIndex); ffiArgumentSpecClass(oop, argSpec, argClass); if (interpreterProxy->failed()) { return 0; } stackIndex -= 1; } return ffiCalloutToWithFlags(address, callType); } /* Generic callout. Does the actual work. */ static sqInt ffiCallWithFlagsArgsAndTypesOfSize(sqInt address, sqInt callType, sqInt argArray, sqInt argTypeArray, sqInt nArgs) { sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypes; sqInt i; sqInt oop; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt reason6; if (!(ffiSupportsCallingConvention(callType))) { /* begin ffiFail: */ reason = FFIErrorCallType; ffiLastError = reason; return interpreterProxy->primitiveFail(); } /* Fetch return type and args */ argTypes = argTypeArray; argType = interpreterProxy->fetchPointerofObject(0, argTypes); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); /* begin ffiCheckReturn:With: */ if (!(argClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason1 = FFIErrorBadReturn; ffiLastError = reason1; interpreterProxy->primitiveFail(); goto l1; } } ffiRetClass = argClass; if ((argSpec & 1)) { /* begin ffiFail: */ reason2 = FFIErrorWrongType; ffiLastError = reason2; interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isWords(argSpec))) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; interpreterProxy->primitiveFail(); goto l1; } ffiRetSpecSize = interpreterProxy->slotSizeOf(argSpec); if (ffiRetSpecSize == 0) { /* begin ffiFail: */ reason4 = FFIErrorWrongType; ffiLastError = reason4; interpreterProxy->primitiveFail(); goto l1; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(argSpec))); ffiRetHeader = longAt(ffiRetSpec); if (!(ffiRetHeader & FFIFlagAtomic)) { if (ffiRetClass == (interpreterProxy->nilObject())) { /* begin ffiFail: */ reason5 = FFIErrorBadReturn; ffiLastError = reason5; interpreterProxy->primitiveFail(); goto l1; } } if (!(ffiCanReturn(((int*) ffiRetSpec), ffiRetSpecSize))) { /* begin ffiFail: */ reason6 = FFIErrorBadReturn; ffiLastError = reason6; interpreterProxy->primitiveFail(); } l1: /* end ffiCheckReturn:With: */; if (interpreterProxy->failed()) { return 0; } ffiRetOop = argType; for (i = 1; i <= nArgs; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypes); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = interpreterProxy->fetchPointerofObject(i - 1, argArray); ffiArgumentSpecClass(oop, argSpec, argClass); if (interpreterProxy->failed()) { return 0; } } return ffiCalloutToWithFlags(address, callType); } /* Go out, call this guy and create the return value */ static sqInt ffiCalloutToWithFlags(sqInt address, sqInt callType) { sqInt retVal; sqInt oop; sqInt retOop; sqInt structSize; sqInt atomicType; sqInt oop1; sqInt retOop1; sqInt atomicType1; sqInt byteSize; sqInt mask; sqInt shift; sqInt value; if (ffiRetHeader & FFIFlagPointer) { /* Note: Order is important here since FFIFlagPointer + FFIFlagStructure is used to represent 'typedef void* VoidPointer' and VoidPointer must be returned as pointer *not* as struct */ retVal = ffiCallAddressOfWithPointerReturn(address, callType); return ffiCreateReturnPointer(retVal); } if (ffiRetHeader & FFIFlagStructure) { ffiCallAddressOfWithStructReturn(address, callType, ((int*) ffiRetSpec), ffiRetSpecSize); /* begin ffiCreateReturnStruct */ if (interpreterProxy->failed()) { return null; } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); structSize = ffiRetHeader & FFIStructSizeMask; interpreterProxy->pushRemappableOop(ffiRetClass); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), structSize); ffiStoreStructure(((int) (interpreterProxy->firstIndexableField(oop))), structSize); ffiRetClass = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(ffiRetClass, 0); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->push(retOop); } retVal = ffiCallAddressOfWithReturnType(address, callType, ffiRetHeader); /* begin ffiCreateReturn: */ if (interpreterProxy->failed()) { return null; } atomicType = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType <= FFITypeVoid) { return interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushRemappableOop(ffiRetClass); /* begin ffiCreateReturnOop: */ atomicType1 = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType1 == FFITypeBool) { byteSize = ffiRetHeader & FFIStructSizeMask; if (byteSize == 4) { value = retVal; } else { value = retVal & ((1 << (byteSize * 8)) - 1); } if (value == 0) { retOop1 = interpreterProxy->falseObject(); goto l1; } else { retOop1 = interpreterProxy->trueObject(); goto l1; } } if (atomicType1 <= FFITypeSignedInt) { if (atomicType1 <= FFITypeSignedShort) { shift = (((usqInt) atomicType1) >> 1) * 8; value = retVal & ((1 << shift) - 1); if (atomicType1 & 1) { mask = 1 << (shift - 1); value = (value & (mask - 1)) - (value & mask); } retOop1 = ((value << 1) | 1); goto l1; } if (atomicType1 & 1) { retOop1 = interpreterProxy->signed32BitIntegerFor(retVal); goto l1; } else { retOop1 = interpreterProxy->positive32BitIntegerFor(retVal); goto l1; } } if (atomicType1 < FFITypeSingleFloat) { if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { retOop1 = ffiCreateLongLongReturn(atomicType1 & 1); goto l1; } else { retOop1 = interpreterProxy->fetchPointerofObject(retVal & 255, interpreterProxy->characterTable()); goto l1; } } retOop1 = interpreterProxy->floatObjectOf(ffiReturnFloatValue()); l1: /* end ffiCreateReturnOop: */; ffiRetClass = interpreterProxy->popRemappableOop(); if (ffiRetClass == (interpreterProxy->nilObject())) { return interpreterProxy->push(retOop1); } interpreterProxy->pushRemappableOop(retOop1); retOop1 = interpreterProxy->instantiateClassindexableSize(ffiRetClass, 0); oop1 = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1); return interpreterProxy->push(retOop1); } /* Make sure we can return an object of the given type */ static sqInt ffiCheckReturnWith(sqInt retSpec, sqInt retClass) { sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; if (!(retClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(retClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason = FFIErrorBadReturn; ffiLastError = reason; return interpreterProxy->primitiveFail(); } } ffiRetClass = retClass; if ((retSpec & 1)) { /* begin ffiFail: */ reason1 = FFIErrorWrongType; ffiLastError = reason1; interpreterProxy->primitiveFail(); return null; } if (!(interpreterProxy->isWords(retSpec))) { /* begin ffiFail: */ reason2 = FFIErrorWrongType; ffiLastError = reason2; interpreterProxy->primitiveFail(); return null; } ffiRetSpecSize = interpreterProxy->slotSizeOf(retSpec); if (ffiRetSpecSize == 0) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; interpreterProxy->primitiveFail(); return null; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(retSpec))); ffiRetHeader = longAt(ffiRetSpec); if (!(ffiRetHeader & FFIFlagAtomic)) { if (ffiRetClass == (interpreterProxy->nilObject())) { /* begin ffiFail: */ reason4 = FFIErrorBadReturn; ffiLastError = reason4; return interpreterProxy->primitiveFail(); } } if (!(ffiCanReturn(((int*) ffiRetSpec), ffiRetSpecSize))) { /* begin ffiFail: */ reason5 = FFIErrorBadReturn; ffiLastError = reason5; interpreterProxy->primitiveFail(); } return 0; } /* Make sure that the given oop is a valid external handle */ static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode) { if ((oop & 1)) { /* begin ffiFail: */ ffiLastError = errCode; return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(oop))) { /* begin ffiFail: */ ffiLastError = errCode; return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->byteSizeOf(oop)) == 4)) { /* begin ffiFail: */ ffiLastError = errCode; return interpreterProxy->primitiveFail(); } return interpreterProxy->fetchPointerofObject(0, oop); } /* Create a longlong return value from a previous call out */ static sqInt ffiCreateLongLongReturn(sqInt isSigned) { sqInt highWord; sqInt i; sqInt largeClass; sqInt largeInt; sqInt lowWord; sqInt nBytes; unsigned char *ptr; sqInt reason; lowWord = ffiLongLongResultLow(); highWord = ffiLongLongResultHigh(); if (isSigned) { if ((highWord == 0) && (lowWord >= 0)) { return interpreterProxy->signed32BitIntegerFor(lowWord); } if ((highWord == -1) && (lowWord < 0)) { return interpreterProxy->signed32BitIntegerFor(lowWord); } if (highWord < 0) { largeClass = interpreterProxy->classLargeNegativeInteger(); lowWord = ~lowWord; highWord = ~highWord; if (lowWord == -1) { /* e.g., overflow when adding one */ highWord += 1; } lowWord += 1; } else { largeClass = interpreterProxy->classLargePositiveInteger(); } } else { if (highWord == 0) { return interpreterProxy->positive32BitIntegerFor(lowWord); } largeClass = interpreterProxy->classLargePositiveInteger(); } nBytes = 8; if (!(highWord & (255 << 24))) { nBytes = 7; if (highWord < (1 << 16)) { nBytes = 6; } if (highWord < (1 << 8)) { nBytes = 5; } if (highWord == 0) { nBytes = 4; } } largeInt = interpreterProxy->instantiateClassindexableSize(largeClass, nBytes); if (!(interpreterProxy->isBytes(largeInt))) { /* begin ffiFail: */ reason = FFIErrorBadReturn; ffiLastError = reason; return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(largeInt); for (i = 4; i <= (nBytes - 1); i += 1) { ptr[i] = ((((usqInt) highWord) >> ((i - 4) * 8)) & 255); } ptr[3] = ((((usqInt) lowWord) >> 24) & 255); ptr[2] = ((((usqInt) lowWord) >> 16) & 255); ptr[1] = ((((usqInt) lowWord) >> 8) & 255); ptr[0] = (lowWord & 255); return largeInt; } /* Generic callout support. Create an atomic return value from an external function call */ static sqInt ffiCreateReturn(sqInt retVal) { sqInt atomicType; sqInt oop; sqInt retOop; sqInt atomicType1; sqInt byteSize; sqInt mask; sqInt shift; sqInt value; if (interpreterProxy->failed()) { return null; } /* void returns self */ atomicType = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType <= FFITypeVoid) { return interpreterProxy->pop(interpreterProxy->methodArgumentCount()); } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); interpreterProxy->pushRemappableOop(ffiRetClass); /* begin ffiCreateReturnOop: */ atomicType1 = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType1 == FFITypeBool) { byteSize = ffiRetHeader & FFIStructSizeMask; if (byteSize == 4) { value = retVal; } else { value = retVal & ((1 << (byteSize * 8)) - 1); } if (value == 0) { retOop = interpreterProxy->falseObject(); goto l1; } else { retOop = interpreterProxy->trueObject(); goto l1; } } if (atomicType1 <= FFITypeSignedInt) { if (atomicType1 <= FFITypeSignedShort) { shift = (((usqInt) atomicType1) >> 1) * 8; value = retVal & ((1 << shift) - 1); if (atomicType1 & 1) { mask = 1 << (shift - 1); value = (value & (mask - 1)) - (value & mask); } retOop = ((value << 1) | 1); goto l1; } if (atomicType1 & 1) { retOop = interpreterProxy->signed32BitIntegerFor(retVal); goto l1; } else { retOop = interpreterProxy->positive32BitIntegerFor(retVal); goto l1; } } if (atomicType1 < FFITypeSingleFloat) { if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { retOop = ffiCreateLongLongReturn(atomicType1 & 1); goto l1; } else { retOop = interpreterProxy->fetchPointerofObject(retVal & 255, interpreterProxy->characterTable()); goto l1; } } retOop = interpreterProxy->floatObjectOf(ffiReturnFloatValue()); l1: /* end ffiCreateReturnOop: */; ffiRetClass = interpreterProxy->popRemappableOop(); if (ffiRetClass == (interpreterProxy->nilObject())) { return interpreterProxy->push(retOop); } interpreterProxy->pushRemappableOop(retOop); retOop = interpreterProxy->instantiateClassindexableSize(ffiRetClass, 0); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->push(retOop); } /* Callout support. Return the appropriate oop for the given atomic value */ static sqInt ffiCreateReturnOop(sqInt retVal) { sqInt atomicType; sqInt byteSize; sqInt mask; sqInt shift; sqInt value; atomicType = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (atomicType == FFITypeBool) { /* Make sure bool honors the byte size requested */ byteSize = ffiRetHeader & FFIStructSizeMask; if (byteSize == 4) { value = retVal; } else { value = retVal & ((1 << (byteSize * 8)) - 1); } if (value == 0) { return interpreterProxy->falseObject(); } else { return interpreterProxy->trueObject(); } } if (atomicType <= FFITypeSignedInt) { if (atomicType <= FFITypeSignedShort) { /* these are all generall integer returns */ /* byte/short. first extract partial word, then sign extend */ /* # of significant bits */ shift = (((usqInt) atomicType) >> 1) * 8; value = retVal & ((1 << shift) - 1); if (atomicType & 1) { /* make the guy signed */ mask = 1 << (shift - 1); value = (value & (mask - 1)) - (value & mask); } return ((value << 1) | 1); } if (atomicType & 1) { return interpreterProxy->signed32BitIntegerFor(retVal); } else { return interpreterProxy->positive32BitIntegerFor(retVal); } } if (atomicType < FFITypeSingleFloat) { if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedLongLong) >> 1)) { return ffiCreateLongLongReturn(atomicType & 1); } else { return interpreterProxy->fetchPointerofObject(retVal & 255, interpreterProxy->characterTable()); } } return interpreterProxy->floatObjectOf(ffiReturnFloatValue()); } /* Generic callout support. Create a pointer return value from an external function call */ static sqInt ffiCreateReturnPointer(sqInt retVal) { sqInt atomicType; sqInt classOop; sqInt oop; int *ptr; sqInt retOop; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); if (ffiRetClass == (interpreterProxy->nilObject())) { /* Create ExternalData upon return */ atomicType = ((usqInt) (ffiRetHeader & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) { return ffiReturnCStringFrom(retVal); } interpreterProxy->pushRemappableOop(ffiRetOop); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = retVal; interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0); /* external address */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); /* return type */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(1, retOop, oop); return interpreterProxy->push(retOop); } interpreterProxy->pushRemappableOop(ffiRetClass); if (ffiRetHeader & FFIFlagStructure) { classOop = interpreterProxy->classByteArray(); } else { classOop = interpreterProxy->classExternalAddress(); } oop = interpreterProxy->instantiateClassindexableSize(classOop, 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = retVal; /* return class */ ffiRetClass = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(ffiRetClass, 0); /* external address */ oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->push(retOop); } /* Generic callout support. Create a structure return value from an external function call */ static sqInt ffiCreateReturnStruct(void) { sqInt oop; sqInt retOop; sqInt structSize; if (interpreterProxy->failed()) { return null; } interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1); structSize = ffiRetHeader & FFIStructSizeMask; interpreterProxy->pushRemappableOop(ffiRetClass); oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), structSize); ffiStoreStructure(((int) (interpreterProxy->firstIndexableField(oop))), structSize); ffiRetClass = interpreterProxy->popRemappableOop(); interpreterProxy->pushRemappableOop(oop); retOop = interpreterProxy->instantiateClassindexableSize(ffiRetClass, 0); oop = interpreterProxy->popRemappableOop(); interpreterProxy->storePointerofObjectwithValue(0, retOop, oop); return interpreterProxy->push(retOop); } static sqInt ffiFail(sqInt reason) { ffiLastError = reason; return interpreterProxy->primitiveFail(); } /* Support for generic callout. Return a float value that is coerced as C would do. */ static double ffiFloatValueOf(sqInt oop) { sqInt oopClass; oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { return interpreterProxy->floatValueOf(oop); } return ((double) (ffiIntegerValueOf(oop)) ); } static sqInt ffiGetLastError(void) { return ffiLastError; } /* Support for generic callout. Return an integer value that is coerced as C would do. */ static sqInt ffiIntegerValueOf(sqInt oop) { sqInt oopClass; if ((oop & 1)) { return (oop >> 1); } if (oop == (interpreterProxy->nilObject())) { return 0; } if (oop == (interpreterProxy->falseObject())) { return 0; } if (oop == (interpreterProxy->trueObject())) { return 1; } oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classFloat())) { return ((sqInt)(interpreterProxy->floatValueOf(oop))); } if (oopClass == (interpreterProxy->classCharacter())) { return interpreterProxy->fetchIntegerofObject(0, oop); } if (oopClass == (interpreterProxy->classLargePositiveInteger())) { return interpreterProxy->positive32BitValueOf(oop); } return interpreterProxy->signed32BitValueOf(oop); } /* Load the address of the foreign function from the given object */ static sqInt ffiLoadCalloutAddress(sqInt lit) { sqInt address; sqInt addressPtr; int *ptr; sqInt errCode; sqInt reason; /* Lookup the address */ /* Make sure it's an external handle */ addressPtr = interpreterProxy->fetchPointerofObject(0, lit); /* begin ffiContentsOfHandle:errCode: */ errCode = FFIErrorBadAddress; if ((addressPtr & 1)) { /* begin ffiFail: */ ffiLastError = errCode; address = interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isBytes(addressPtr))) { /* begin ffiFail: */ ffiLastError = errCode; address = interpreterProxy->primitiveFail(); goto l1; } if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) { /* begin ffiFail: */ ffiLastError = errCode; address = interpreterProxy->primitiveFail(); goto l1; } address = interpreterProxy->fetchPointerofObject(0, addressPtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } if (address == 0) { if ((interpreterProxy->slotSizeOf(lit)) < 5) { /* begin ffiFail: */ reason = FFIErrorNoModule; ffiLastError = reason; return interpreterProxy->primitiveFail(); } address = ffiLoadCalloutAddressFrom(lit); if (interpreterProxy->failed()) { return 0; } ptr = interpreterProxy->firstIndexableField(addressPtr); ptr[0] = address; } return address; } /* Load the function address for a call out to an external function */ static sqInt ffiLoadCalloutAddressFrom(sqInt oop) { sqInt address; sqInt functionLength; sqInt functionName; sqInt module; sqInt moduleHandle; sqInt reason; sqInt reason1; /* First find and load the module */ module = interpreterProxy->fetchPointerofObject(4, oop); moduleHandle = ffiLoadCalloutModule(module); if (interpreterProxy->failed()) { return 0; } functionName = interpreterProxy->fetchPointerofObject(3, oop); if (!(interpreterProxy->isBytes(functionName))) { /* begin ffiFail: */ reason = FFIErrorBadExternalFunction; ffiLastError = reason; return interpreterProxy->primitiveFail(); } functionLength = interpreterProxy->byteSizeOf(functionName); address = interpreterProxy->ioLoadSymbolOfLengthFromModule(((int) (interpreterProxy->firstIndexableField(functionName))), functionLength, moduleHandle); if ((interpreterProxy->failed()) || (address == 0)) { /* begin ffiFail: */ reason1 = FFIErrorAddressNotFound; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } return address; } /* Load the given module and return its handle */ static sqInt ffiLoadCalloutModule(sqInt module) { sqInt ffiModuleName; sqInt moduleHandle; sqInt moduleHandlePtr; sqInt moduleLength; int *ptr; sqInt rcvr; sqInt theClass; sqInt errCode; sqInt reason; sqInt reason1; sqInt reason2; if (interpreterProxy->isBytes(module)) { /* plain module name */ ffiModuleName = module; moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if (interpreterProxy->failed()) { /* begin ffiFail: */ reason = FFIErrorModuleNotFound; ffiLastError = reason; return interpreterProxy->primitiveFail(); } return moduleHandle; } rcvr = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); theClass = interpreterProxy->fetchClassOf(rcvr); if (!(interpreterProxy->includesBehaviorThatOf(theClass, interpreterProxy->classExternalLibrary()))) { return 0; } moduleHandlePtr = interpreterProxy->fetchPointerofObject(0, rcvr); /* begin ffiContentsOfHandle:errCode: */ errCode = FFIErrorBadExternalLibrary; if ((moduleHandlePtr & 1)) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isBytes(moduleHandlePtr))) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } if (!((interpreterProxy->byteSizeOf(moduleHandlePtr)) == 4)) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } moduleHandle = interpreterProxy->fetchPointerofObject(0, moduleHandlePtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } if (moduleHandle == 0) { /* need to reload module */ ffiModuleName = interpreterProxy->fetchPointerofObject(1, rcvr); if (!(interpreterProxy->isBytes(ffiModuleName))) { /* begin ffiFail: */ reason1 = FFIErrorBadExternalLibrary; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if (interpreterProxy->failed()) { /* begin ffiFail: */ reason2 = FFIErrorModuleNotFound; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(moduleHandlePtr); ptr[0] = moduleHandle; } return moduleHandle; } /* Push the contents of the given external structure */ static sqInt ffiPushPointerContentsOf(sqInt oop) { sqInt ptrAddress; sqInt ptrClass; sqInt ptrValue; sqInt reason; sqInt reason1; ptrValue = oop; ptrClass = interpreterProxy->fetchClassOf(ptrValue); if (ptrClass == (interpreterProxy->classExternalAddress())) { /* Don't you dare to pass pointers into object memory */ ptrAddress = interpreterProxy->fetchPointerofObject(0, ptrValue); if (interpreterProxy->isInMemory(ptrAddress)) { /* begin ffiFail: */ reason = FFIErrorInvalidPointer; ffiLastError = reason; return interpreterProxy->primitiveFail(); } return ffiPushPointer(ptrAddress); } if (ptrClass == (interpreterProxy->classByteArray())) { ptrAddress = ((int) (interpreterProxy->firstIndexableField(ptrValue))); return ffiPushPointer(ptrAddress); } /* begin ffiFail: */ reason1 = FFIErrorBadArg; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } /* Push a longlong type (e.g., a 64bit integer). Note: Coercions from float are *not* supported. */ static sqInt ffiPushSignedLongLongOop(sqInt oop) { sqInt highWord; sqInt i; sqInt length; sqInt lowWord; sqInt negative; sqInt oopClass; unsigned char *ptr; sqInt reason; sqInt reason1; sqInt reason2; if (oop == (interpreterProxy->nilObject())) { return ffiPushSignedLongLong(0, 0); } if (oop == (interpreterProxy->falseObject())) { return ffiPushSignedLongLong(0, 0); } if (oop == (interpreterProxy->trueObject())) { return ffiPushSignedLongLong(0, 1); } if ((oop & 1)) { lowWord = (oop >> 1); if (lowWord < 0) { highWord = -1; } else { highWord = 0; } } else { oopClass = interpreterProxy->fetchClassOf(oop); if (oopClass == (interpreterProxy->classLargePositiveInteger())) { negative = 0; } else { if (oopClass == (interpreterProxy->classLargeNegativeInteger())) { negative = 1; } else { /* begin ffiFail: */ reason = FFIErrorCoercionFailed; ffiLastError = reason; return interpreterProxy->primitiveFail(); } } if (!(interpreterProxy->isBytes(oop))) { /* begin ffiFail: */ reason1 = FFIErrorCoercionFailed; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(oop); if (length > 8) { /* begin ffiFail: */ reason2 = FFIErrorCoercionFailed; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } lowWord = highWord = 0; ptr = interpreterProxy->firstIndexableField(oop); for (i = 0; i <= ((((length < 4) ? length : 4)) - 1); i += 1) { lowWord += (ptr[i]) << (i * 8); } for (i = 0; i <= (length - 5); i += 1) { highWord += (ptr[i + 4]) << (i * 8); } if (negative) { lowWord = ~lowWord; highWord = ~highWord; if (lowWord == -1) { /* e.g., will overflow when adding one */ highWord += 1; } lowWord += 1; } } return ffiPushSignedLongLong(lowWord, highWord); } /* Push the contents of the given external structure */ static sqInt ffiPushStructureContentsOf(sqInt oop) { sqInt ptrAddress; sqInt ptrClass; sqInt ptrValue; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; ptrValue = oop; ptrClass = interpreterProxy->fetchClassOf(ptrValue); if (ptrClass == (interpreterProxy->classExternalAddress())) { /* There is no way we can make sure the structure is valid. But we can at least check for attempts to pass pointers to ST memory. */ ptrAddress = interpreterProxy->fetchPointerofObject(0, ptrValue); if (interpreterProxy->isInMemory(ptrAddress)) { /* begin ffiFail: */ reason = FFIErrorInvalidPointer; ffiLastError = reason; return interpreterProxy->primitiveFail(); } return ffiPushStructureOfLength(ptrAddress, ((int*) ffiArgSpec), ffiArgSpecSize); } if (ptrClass == (interpreterProxy->classByteArray())) { if (!((interpreterProxy->byteSizeOf(ptrValue)) == (ffiArgHeader & FFIStructSizeMask))) { /* begin ffiFail: */ reason1 = FFIErrorStructSize; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } ptrAddress = ((int) (interpreterProxy->firstIndexableField(ptrValue))); if (!(ffiArgHeader & FFIFlagPointer)) { return ffiPushStructureOfLength(ptrAddress, ((int*) ffiArgSpec), ffiArgSpecSize); } if (!((ffiArgHeader & FFIStructSizeMask) == 4)) { /* begin ffiFail: */ reason2 = FFIErrorStructSize; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } ptrAddress = interpreterProxy->fetchPointerofObject(0, ptrValue); if (interpreterProxy->isInMemory(ptrAddress)) { /* begin ffiFail: */ reason3 = FFIErrorInvalidPointer; ffiLastError = reason3; return interpreterProxy->primitiveFail(); } return ffiPushPointer(ptrAddress); } /* begin ffiFail: */ reason4 = FFIErrorBadArg; ffiLastError = reason4; return interpreterProxy->primitiveFail(); } /* Push a longlong type (e.g., a 64bit integer). Note: Coercions from float are *not* supported. */ static sqInt ffiPushUnsignedLongLongOop(sqInt oop) { sqInt highWord; sqInt i; sqInt length; sqInt lowWord; unsigned char *ptr; sqInt reason; sqInt reason1; sqInt reason2; if (oop == (interpreterProxy->nilObject())) { return ffiPushUnsignedLongLong(0, 0); } if (oop == (interpreterProxy->falseObject())) { return ffiPushUnsignedLongLong(0, 0); } if (oop == (interpreterProxy->trueObject())) { return ffiPushUnsignedLongLong(0, 1); } if ((oop & 1)) { lowWord = (oop >> 1); if (lowWord < 0) { /* begin ffiFail: */ reason = FFIErrorCoercionFailed; ffiLastError = reason; return interpreterProxy->primitiveFail(); } highWord = 0; } else { if (!((interpreterProxy->fetchClassOf(oop)) == (interpreterProxy->classLargePositiveInteger()))) { return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isBytes(oop))) { /* begin ffiFail: */ reason1 = FFIErrorCoercionFailed; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } length = interpreterProxy->byteSizeOf(oop); if (length > 8) { /* begin ffiFail: */ reason2 = FFIErrorCoercionFailed; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } lowWord = highWord = 0; ptr = interpreterProxy->firstIndexableField(oop); for (i = 0; i <= ((((length < 4) ? length : 4)) - 1); i += 1) { lowWord += (ptr[i]) << (i * 8); } for (i = 0; i <= (length - 5); i += 1) { highWord += (ptr[i + 4]) << (i * 8); } } return ffiPushUnsignedLongLong(lowWord, highWord); } /* This is a fallback in case somebody tries to pass a 'void' value. We could simply ignore the argument but I think it's better to let the caller know what he did */ static sqInt ffiPushVoid(sqInt ignored) { sqInt reason; /* begin ffiFail: */ reason = FFIErrorAttemptToPassVoid; ffiLastError = reason; return interpreterProxy->primitiveFail(); } /* Create a Smalltalk string from a zero terminated C string */ static sqInt ffiReturnCStringFrom(sqInt cPointer) { char *cString; sqInt i; sqInt strLen; sqInt strOop; char *strPtr; if (cPointer == null) { return interpreterProxy->push(interpreterProxy->nilObject()); } cString = ((char *) cPointer); strLen = 0; while (!((cString[strLen]) == 0)) { strLen += 1; } strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen); strPtr = interpreterProxy->firstIndexableField(strOop); for (i = 0; i <= (strLen - 1); i += 1) { strPtr[i] = (cString[i]); } return interpreterProxy->push(strOop); } static sqInt ffiSetLastError(sqInt errCode) { return ffiLastError = errCode; } /* Validate if the given oop (an instance of ExternalData) can be passed as a pointer to the given atomic type. */ static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType) { sqInt ptrType; sqInt spec; sqInt specOop; sqInt specType; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt reason6; sqInt reason7; sqInt reason8; ptrType = interpreterProxy->fetchPointerofObject(1, oop); if ((ptrType & 1)) { /* begin ffiFail: */ reason = FFIErrorWrongType; ffiLastError = reason; return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isPointers(ptrType))) { /* begin ffiFail: */ reason1 = FFIErrorWrongType; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(ptrType)) < 2) { /* begin ffiFail: */ reason2 = FFIErrorWrongType; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } specOop = interpreterProxy->fetchPointerofObject(0, ptrType); if ((specOop & 1)) { /* begin ffiFail: */ reason3 = FFIErrorWrongType; ffiLastError = reason3; return interpreterProxy->primitiveFail(); } if (!(interpreterProxy->isWords(specOop))) { /* begin ffiFail: */ reason4 = FFIErrorWrongType; ffiLastError = reason4; return interpreterProxy->primitiveFail(); } if ((interpreterProxy->slotSizeOf(specOop)) == 0) { /* begin ffiFail: */ reason5 = FFIErrorWrongType; ffiLastError = reason5; return interpreterProxy->primitiveFail(); } spec = interpreterProxy->fetchPointerofObject(0, specOop); if (!(spec & FFIFlagAtomic)) { /* begin ffiFail: */ reason6 = FFIErrorWrongType; ffiLastError = reason6; return interpreterProxy->primitiveFail(); } specType = ((usqInt) (spec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift; if (specType != atomicType) { if (!((atomicType > FFITypeBool) && (atomicType < FFITypeSingleFloat))) { /* begin ffiFail: */ reason7 = FFIErrorCoercionFailed; ffiLastError = reason7; return interpreterProxy->primitiveFail(); } if (!((((usqInt) atomicType) >> 1) == (((usqInt) specType) >> 1))) { /* begin ffiFail: */ reason8 = FFIErrorCoercionFailed; ffiLastError = reason8; return interpreterProxy->primitiveFail(); } } return 0; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { initSurfacePluginFunctionPointers(); } static sqInt isAtomicType(sqInt typeSpec) { return typeSpec & FFIFlagAtomic; } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* IMPORTANT: IF YOU CHANGE THE NAME OF THIS METHOD YOU MUST CHANGE Interpreter>>primitiveCalloutToFFI TO REFLECT THE CHANGE. */ /* Perform a function call to a foreign function. Only invoked from method containing explicit external call spec. */ EXPORT(sqInt) primitiveCallout(void) { sqInt address; sqInt argTypes; sqInt flags; sqInt lit; sqInt litClass; sqInt meth; sqInt nArgs; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypes1; sqInt i; sqInt nArgs1; sqInt oop; sqInt stackIndex; sqInt reason4; sqInt reason6; sqInt reason11; sqInt reason21; sqInt reason31; sqInt reason41; sqInt reason5; ffiLastError = FFIErrorGenericError; /* Look if the method is itself a callout function */ lit = null; meth = interpreterProxy->primitiveMethod(); if (!((interpreterProxy->literalCountOf(meth)) > 0)) { return interpreterProxy->primitiveFail(); } lit = interpreterProxy->literalofMethod(0, meth); litClass = interpreterProxy->fetchClassOf(lit); if (!(interpreterProxy->includesBehaviorThatOf(litClass, interpreterProxy->classExternalFunction()))) { /* begin ffiFail: */ reason = FFIErrorNotFunction; ffiLastError = reason; return interpreterProxy->primitiveFail(); } address = ffiLoadCalloutAddress(lit); if (interpreterProxy->failed()) { return 0; } flags = interpreterProxy->fetchIntegerofObject(1, lit); if (interpreterProxy->failed()) { /* begin ffiFail: */ reason1 = FFIErrorBadArgs; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } /* must be array of arg types */ argTypes = interpreterProxy->fetchPointerofObject(2, lit); if (!(interpreterProxy->isArray(argTypes))) { /* begin ffiFail: */ reason2 = FFIErrorBadArgs; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } /* must be argumentCount+1 arg types */ nArgs = interpreterProxy->slotSizeOf(argTypes); if (!(nArgs == ((interpreterProxy->methodArgumentCount()) + 1))) { /* begin ffiFail: */ reason3 = FFIErrorBadArgs; ffiLastError = reason3; return interpreterProxy->primitiveFail(); } ffiInitialize(); /* begin ffiCall:WithFlags:AndTypes: */ if (!(ffiSupportsCallingConvention(flags))) { /* begin ffiFail: */ reason4 = FFIErrorCallType; ffiLastError = reason4; interpreterProxy->primitiveFail(); goto l1; } argTypes1 = argTypes; argType = interpreterProxy->fetchPointerofObject(0, argTypes1); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); /* begin ffiCheckReturn:With: */ if (!(argClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason6 = FFIErrorBadReturn; ffiLastError = reason6; interpreterProxy->primitiveFail(); goto l2; } } ffiRetClass = argClass; if ((argSpec & 1)) { /* begin ffiFail: */ reason11 = FFIErrorWrongType; ffiLastError = reason11; interpreterProxy->primitiveFail(); goto l2; } if (!(interpreterProxy->isWords(argSpec))) { /* begin ffiFail: */ reason21 = FFIErrorWrongType; ffiLastError = reason21; interpreterProxy->primitiveFail(); goto l2; } ffiRetSpecSize = interpreterProxy->slotSizeOf(argSpec); if (ffiRetSpecSize == 0) { /* begin ffiFail: */ reason31 = FFIErrorWrongType; ffiLastError = reason31; interpreterProxy->primitiveFail(); goto l2; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(argSpec))); ffiRetHeader = longAt(ffiRetSpec); if (!(ffiRetHeader & FFIFlagAtomic)) { if (ffiRetClass == (interpreterProxy->nilObject())) { /* begin ffiFail: */ reason41 = FFIErrorBadReturn; ffiLastError = reason41; interpreterProxy->primitiveFail(); goto l2; } } if (!(ffiCanReturn(((int*) ffiRetSpec), ffiRetSpecSize))) { /* begin ffiFail: */ reason5 = FFIErrorBadReturn; ffiLastError = reason5; interpreterProxy->primitiveFail(); } l2: /* end ffiCheckReturn:With: */; if (interpreterProxy->failed()) { goto l1; } ffiRetOop = argType; nArgs1 = interpreterProxy->methodArgumentCount(); stackIndex = nArgs1 - 1; for (i = 1; i <= nArgs1; i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypes1); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = interpreterProxy->stackValue(stackIndex); ffiArgumentSpecClass(oop, argSpec, argClass); if (interpreterProxy->failed()) { goto l1; } stackIndex -= 1; } ffiCalloutToWithFlags(address, flags); l1: /* end ffiCall:WithFlags:AndTypes: */; ffiCleanup(); return 0; } /* Perform a function call to a foreign function. Only invoked from ExternalFunction>>invokeWithArguments: */ EXPORT(sqInt) primitiveCalloutWithArgs(void) { sqInt address; sqInt argArray; sqInt argTypes; sqInt flags; sqInt lit; sqInt litClass; sqInt nArgs; sqInt reason; sqInt reason1; sqInt reason2; sqInt reason3; sqInt reason4; sqInt reason5; sqInt argClass; sqInt argSpec; sqInt argType; sqInt argTypes1; sqInt i; sqInt oop; sqInt reason6; sqInt reason7; sqInt reason11; sqInt reason21; sqInt reason31; sqInt reason41; sqInt reason51; ffiLastError = FFIErrorGenericError; /* Look if the method is itself a callout function */ lit = null; lit = interpreterProxy->stackValue(interpreterProxy->methodArgumentCount()); litClass = interpreterProxy->fetchClassOf(lit); if (!(interpreterProxy->includesBehaviorThatOf(litClass, interpreterProxy->classExternalFunction()))) { /* begin ffiFail: */ reason = FFIErrorNotFunction; ffiLastError = reason; return interpreterProxy->primitiveFail(); } address = ffiLoadCalloutAddress(lit); if (interpreterProxy->failed()) { return null; } flags = interpreterProxy->fetchIntegerofObject(1, lit); if (interpreterProxy->failed()) { /* begin ffiFail: */ reason1 = FFIErrorBadArgs; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } /* must be array of arg types */ argTypes = interpreterProxy->fetchPointerofObject(2, lit); if (!(interpreterProxy->isArray(argTypes))) { /* begin ffiFail: */ reason2 = FFIErrorBadArgs; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } nArgs = interpreterProxy->slotSizeOf(argTypes); if (!((interpreterProxy->methodArgumentCount()) == 1)) { /* begin ffiFail: */ reason3 = FFIErrorBadArgs; ffiLastError = reason3; return interpreterProxy->primitiveFail(); } argArray = interpreterProxy->stackValue(0); if (!(interpreterProxy->isArray(argArray))) { /* begin ffiFail: */ reason4 = FFIErrorBadArgs; ffiLastError = reason4; return interpreterProxy->primitiveFail(); } if (!(nArgs == ((interpreterProxy->slotSizeOf(argArray)) + 1))) { /* begin ffiFail: */ reason5 = FFIErrorBadArgs; ffiLastError = reason5; return interpreterProxy->primitiveFail(); } ffiInitialize(); /* begin ffiCall:WithFlags:Args:AndTypes:OfSize: */ if (!(ffiSupportsCallingConvention(flags))) { /* begin ffiFail: */ reason6 = FFIErrorCallType; ffiLastError = reason6; interpreterProxy->primitiveFail(); goto l1; } argTypes1 = argTypes; argType = interpreterProxy->fetchPointerofObject(0, argTypes1); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); /* begin ffiCheckReturn:With: */ if (!(argClass == (interpreterProxy->nilObject()))) { if (!(interpreterProxy->includesBehaviorThatOf(argClass, interpreterProxy->classExternalStructure()))) { /* begin ffiFail: */ reason7 = FFIErrorBadReturn; ffiLastError = reason7; interpreterProxy->primitiveFail(); goto l2; } } ffiRetClass = argClass; if ((argSpec & 1)) { /* begin ffiFail: */ reason11 = FFIErrorWrongType; ffiLastError = reason11; interpreterProxy->primitiveFail(); goto l2; } if (!(interpreterProxy->isWords(argSpec))) { /* begin ffiFail: */ reason21 = FFIErrorWrongType; ffiLastError = reason21; interpreterProxy->primitiveFail(); goto l2; } ffiRetSpecSize = interpreterProxy->slotSizeOf(argSpec); if (ffiRetSpecSize == 0) { /* begin ffiFail: */ reason31 = FFIErrorWrongType; ffiLastError = reason31; interpreterProxy->primitiveFail(); goto l2; } ffiRetSpec = ((int) (interpreterProxy->firstIndexableField(argSpec))); ffiRetHeader = longAt(ffiRetSpec); if (!(ffiRetHeader & FFIFlagAtomic)) { if (ffiRetClass == (interpreterProxy->nilObject())) { /* begin ffiFail: */ reason41 = FFIErrorBadReturn; ffiLastError = reason41; interpreterProxy->primitiveFail(); goto l2; } } if (!(ffiCanReturn(((int*) ffiRetSpec), ffiRetSpecSize))) { /* begin ffiFail: */ reason51 = FFIErrorBadReturn; ffiLastError = reason51; interpreterProxy->primitiveFail(); } l2: /* end ffiCheckReturn:With: */; if (interpreterProxy->failed()) { goto l1; } ffiRetOop = argType; for (i = 1; i <= (nArgs - 1); i += 1) { argType = interpreterProxy->fetchPointerofObject(i, argTypes1); argSpec = interpreterProxy->fetchPointerofObject(0, argType); argClass = interpreterProxy->fetchPointerofObject(1, argType); oop = interpreterProxy->fetchPointerofObject(i - 1, argArray); ffiArgumentSpecClass(oop, argSpec, argClass); if (interpreterProxy->failed()) { goto l1; } } ffiCalloutToWithFlags(address, flags); l1: /* end ffiCall:WithFlags:Args:AndTypes:OfSize: */; ffiCleanup(); return 0; } /* arguments: name(type, stack offset) width(Integer, 4) height(Integer, 3) rowPitch(Integer, 2) depth(Integer, 1) isMSB(Boolean, 0) */ EXPORT(sqInt) primitiveCreateManualSurface(void) { sqInt depth; sqInt height; sqInt isMSB; sqInt result; sqInt rowPitch; sqInt width; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } width = interpreterProxy->stackIntegerValue(4); height = interpreterProxy->stackIntegerValue(3); rowPitch = interpreterProxy->stackIntegerValue(2); depth = interpreterProxy->stackIntegerValue(1); isMSB = interpreterProxy->stackObjectValue(0); isMSB = interpreterProxy->booleanValueOf(isMSB); if (interpreterProxy->failed()) { return null; } ; ; ; ; ; result = createManualSurface(width, height, rowPitch, depth, isMSB); if (result < 0) { return interpreterProxy->primitiveFail(); } result = interpreterProxy->signed32BitIntegerFor(result); return interpreterProxy->popthenPush(6, result); } /* arguments: name(type, stack offset) surfaceID(Integer, 0) */ EXPORT(sqInt) primitiveDestroyManualSurface(void) { sqInt result; sqInt surfaceID; if (!((interpreterProxy->methodArgumentCount()) == 1)) { return interpreterProxy->primitiveFail(); } surfaceID = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } result = destroyManualSurface(surfaceID); if (result == 0) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(1); } /* Primitive. Allocate an object on the external heap. */ EXPORT(sqInt) primitiveFFIAllocate(void) { sqInt addr; sqInt byteSize; sqInt oop; int *ptr; byteSize = interpreterProxy->stackIntegerValue(0); if (interpreterProxy->failed()) { return null; } addr = ffiAlloc(byteSize); if (addr == 0) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4); ptr = interpreterProxy->firstIndexableField(oop); ptr[0] = addr; interpreterProxy->pop(2); return interpreterProxy->push(oop); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIDoubleAt(void) { sqInt addr; sqInt byteOffset; double floatValue; sqInt rcvr; byteOffset = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 8); if (interpreterProxy->failed()) { return 0; } ((int*)(&floatValue))[0] = ((int*)addr)[0]; ((int*)(&floatValue))[1] = ((int*)addr)[1]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIDoubleAtPut(void) { sqInt addr; sqInt byteOffset; sqInt floatOop; double floatValue; sqInt rcvr; floatOop = interpreterProxy->stackValue(0); if ((floatOop & 1)) { floatValue = ((double) ((floatOop >> 1))); } else { floatValue = ((double) (interpreterProxy->floatValueOf(floatOop))); } byteOffset = interpreterProxy->stackIntegerValue(1); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 8); if (interpreterProxy->failed()) { return 0; } ((int*)addr)[0] = ((int*)(&floatValue))[0]; ((int*)addr)[1] = ((int*)(&floatValue))[1]; interpreterProxy->pop(3); return interpreterProxy->push(floatOop); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIFloatAt(void) { sqInt addr; sqInt byteOffset; float floatValue; sqInt rcvr; byteOffset = interpreterProxy->stackIntegerValue(0); rcvr = interpreterProxy->stackObjectValue(1); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 4); if (interpreterProxy->failed()) { return 0; } ((int*)(&floatValue))[0] = ((int*)addr)[0]; interpreterProxy->pop(2); return interpreterProxy->pushFloat(floatValue); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIFloatAtPut(void) { sqInt addr; sqInt byteOffset; sqInt floatOop; float floatValue; sqInt rcvr; floatOop = interpreterProxy->stackValue(0); if ((floatOop & 1)) { floatValue = ((float) ((floatOop >> 1))); } else { floatValue = ((float) (interpreterProxy->floatValueOf(floatOop))); } byteOffset = interpreterProxy->stackIntegerValue(1); rcvr = interpreterProxy->stackObjectValue(2); if (interpreterProxy->failed()) { return 0; } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, 4); if (interpreterProxy->failed()) { return 0; } ((int*)addr)[0] = ((int*)(&floatValue))[0]; interpreterProxy->pop(3); return interpreterProxy->push(floatOop); } /* Primitive. Free the object pointed to on the external heap. */ EXPORT(sqInt) primitiveFFIFree(void) { sqInt addr; sqInt oop; int *ptr; oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!((interpreterProxy->fetchClassOf(oop)) == (interpreterProxy->classExternalAddress()))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->byteSizeOf(oop)) == 4)) { return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(oop); /* Don't you dare to free Squeak's memory! */ addr = ptr[0]; if ((addr == 0) || (interpreterProxy->isInMemory(addr))) { return interpreterProxy->primitiveFail(); } ffiFree(addr); return ptr[0] = 0; } /* Primitive. Return the error code from a failed call to the foreign function interface. */ EXPORT(sqInt) primitiveFFIGetLastError(void) { interpreterProxy->pop(1); return interpreterProxy->pushInteger(ffiLastError); } /* Return a (signed or unsigned) n byte integer from the given byte offset. */ EXPORT(sqInt) primitiveFFIIntegerAt(void) { sqInt addr; sqInt byteOffset; sqInt byteSize; sqInt isSigned; sqInt mask; sqInt rcvr; sqInt value; isSigned = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); byteSize = interpreterProxy->stackIntegerValue(1); byteOffset = interpreterProxy->stackIntegerValue(2); rcvr = interpreterProxy->stackObjectValue(3); if (interpreterProxy->failed()) { return 0; } if (!((byteOffset > 0) && ((byteSize == 1) || ((byteSize == 2) || (byteSize == 4))))) { return interpreterProxy->primitiveFail(); } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, byteSize); if (interpreterProxy->failed()) { return 0; } if (byteSize < 4) { if (byteSize == 1) { /* short/byte */ value = byteAt(addr); } else { value = *((unsigned short int *) addr); } if (isSigned) { /* sign extend value */ mask = 1 << ((byteSize * 8) - 1); value = (value & (mask - 1)) - (value & mask); } value = ((value << 1) | 1); } else { /* general 32 bit integer */ value = longAt(addr); if (isSigned) { value = interpreterProxy->signed32BitIntegerFor(value); } else { value = interpreterProxy->positive32BitIntegerFor(value); } } interpreterProxy->pop(4); return interpreterProxy->push(value); } /* Store a (signed or unsigned) n byte integer at the given byte offset. */ EXPORT(sqInt) primitiveFFIIntegerAtPut(void) { sqInt addr; sqInt byteOffset; sqInt byteSize; sqInt isSigned; sqInt max; sqInt rcvr; sqInt value; sqInt valueOop; isSigned = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0)); byteSize = interpreterProxy->stackIntegerValue(1); valueOop = interpreterProxy->stackValue(2); byteOffset = interpreterProxy->stackIntegerValue(3); rcvr = interpreterProxy->stackObjectValue(4); if (interpreterProxy->failed()) { return 0; } if (!((byteOffset > 0) && ((byteSize == 1) || ((byteSize == 2) || (byteSize == 4))))) { return interpreterProxy->primitiveFail(); } addr = ffiAddressOfstartingAtsize(rcvr, byteOffset, byteSize); if (interpreterProxy->failed()) { return 0; } if (isSigned) { value = interpreterProxy->signed32BitValueOf(valueOop); } else { value = interpreterProxy->positive32BitValueOf(valueOop); } if (interpreterProxy->failed()) { return 0; } if (byteSize < 4) { if (isSigned) { max = 1 << ((8 * byteSize) - 1); if (value >= max) { return interpreterProxy->primitiveFail(); } if (value < (0 - max)) { return interpreterProxy->primitiveFail(); } } else { if (value >= (1 << (8 * byteSize))) { return interpreterProxy->primitiveFail(); } } if (byteSize == 1) { byteAtput(addr, value); } else { *((short int *) addr) = value; } } else { longAtput(addr, value); } interpreterProxy->pop(5); return interpreterProxy->push(valueOop); } /* Primitive. Force loading the receiver (an instance of ExternalLibrary). */ EXPORT(sqInt) primitiveForceLoad(void) { sqInt ffiModuleName; sqInt moduleHandle; sqInt moduleHandlePtr; sqInt moduleLength; int *ptr; sqInt rcvr; sqInt theClass; sqInt reason; sqInt reason1; sqInt reason2; sqInt errCode; ffiLastError = FFIErrorGenericError; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } rcvr = interpreterProxy->stackValue(0); theClass = interpreterProxy->fetchClassOf(rcvr); if (!(interpreterProxy->includesBehaviorThatOf(theClass, interpreterProxy->classExternalLibrary()))) { /* begin ffiFail: */ reason = FFIErrorBadExternalLibrary; ffiLastError = reason; return interpreterProxy->primitiveFail(); } moduleHandlePtr = interpreterProxy->fetchPointerofObject(0, rcvr); /* begin ffiContentsOfHandle:errCode: */ errCode = FFIErrorBadExternalLibrary; if ((moduleHandlePtr & 1)) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } if (!(interpreterProxy->isBytes(moduleHandlePtr))) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } if (!((interpreterProxy->byteSizeOf(moduleHandlePtr)) == 4)) { /* begin ffiFail: */ ffiLastError = errCode; moduleHandle = interpreterProxy->primitiveFail(); goto l1; } moduleHandle = interpreterProxy->fetchPointerofObject(0, moduleHandlePtr); l1: /* end ffiContentsOfHandle:errCode: */; if (interpreterProxy->failed()) { return 0; } ffiModuleName = interpreterProxy->fetchPointerofObject(1, rcvr); if (!(interpreterProxy->isBytes(ffiModuleName))) { /* begin ffiFail: */ reason1 = FFIErrorBadExternalLibrary; ffiLastError = reason1; return interpreterProxy->primitiveFail(); } moduleLength = interpreterProxy->byteSizeOf(ffiModuleName); moduleHandle = interpreterProxy->ioLoadModuleOfLength(((int) (interpreterProxy->firstIndexableField(ffiModuleName))), moduleLength); if (interpreterProxy->failed()) { /* begin ffiFail: */ reason2 = FFIErrorModuleNotFound; ffiLastError = reason2; return interpreterProxy->primitiveFail(); } ptr = interpreterProxy->firstIndexableField(moduleHandlePtr); ptr[0] = moduleHandle; return 0; } /* Create a 'manual surface' data-structure. See the ExternalForm class in the FFI package for example usage. */ /* arguments: name(type, stack offset) surfaceID(Integer, 1) ptr(uint32, 0) */ EXPORT(sqInt) primitiveSetManualSurfacePointer(void) { unsigned int ptr; sqInt result; sqInt surfaceID; if (!((interpreterProxy->methodArgumentCount()) == 2)) { return interpreterProxy->primitiveFail(); } surfaceID = interpreterProxy->stackIntegerValue(1); ptr = interpreterProxy->positive32BitValueOf(interpreterProxy->stackValue(0)); if (interpreterProxy->failed()) { return null; } ; ; result = setManualSurfacePointer(surfaceID, (void*)ptr); if (result == 0) { return interpreterProxy->primitiveFail(); } return interpreterProxy->pop(2); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SqueakFFIPrims_exports[][3] = { {"SqueakFFIPrims", "primitiveFFIIntegerAtPut", (void*)primitiveFFIIntegerAtPut}, {"SqueakFFIPrims", "primitiveFFIAllocate", (void*)primitiveFFIAllocate}, {"SqueakFFIPrims", "primitiveCalloutWithArgs", (void*)primitiveCalloutWithArgs}, {"SqueakFFIPrims", "primitiveFFIFloatAt", (void*)primitiveFFIFloatAt}, {"SqueakFFIPrims", "primitiveFFIFree", (void*)primitiveFFIFree}, {"SqueakFFIPrims", "primitiveFFIIntegerAt", (void*)primitiveFFIIntegerAt}, {"SqueakFFIPrims", "primitiveSetManualSurfacePointer", (void*)primitiveSetManualSurfacePointer}, {"SqueakFFIPrims", "primitiveCreateManualSurface", (void*)primitiveCreateManualSurface}, {"SqueakFFIPrims", "primitiveFFIDoubleAt", (void*)primitiveFFIDoubleAt}, {"SqueakFFIPrims", "primitiveDestroyManualSurface", (void*)primitiveDestroyManualSurface}, {"SqueakFFIPrims", "primitiveCallout", (void*)primitiveCallout}, {"SqueakFFIPrims", "setInterpreter", (void*)setInterpreter}, {"SqueakFFIPrims", "primitiveFFIDoubleAtPut", (void*)primitiveFFIDoubleAtPut}, {"SqueakFFIPrims", "initialiseModule", (void*)initialiseModule}, {"SqueakFFIPrims", "getModuleName", (void*)getModuleName}, {"SqueakFFIPrims", "primitiveFFIFloatAtPut", (void*)primitiveFFIFloatAtPut}, {"SqueakFFIPrims", "primitiveFFIGetLastError", (void*)primitiveFFIGetLastError}, {"SqueakFFIPrims", "primitiveForceLoad", (void*)primitiveForceLoad}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/UUIDPlugin/UUIDPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:02 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include "UUIDPlugin.h" #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveMakeUUID(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sqAssert(sqInt aBool); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "UUIDPlugin 23 January 2011 (i)" #else "UUIDPlugin 23 January 2011 (e)" #endif ; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { return sqUUIDInit(); } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } EXPORT(sqInt) primitiveMakeUUID(void) { sqInt oop; char*location; if (!((interpreterProxy->methodArgumentCount()) == 0)) { return interpreterProxy->primitiveFail(); } oop = interpreterProxy->stackObjectValue(0); if (interpreterProxy->failed()) { return null; } if (!(interpreterProxy->isBytes(oop))) { return interpreterProxy->primitiveFail(); } if (!((interpreterProxy->byteSizeOf(oop)) == 16)) { return interpreterProxy->primitiveFail(); } location = interpreterProxy->firstIndexableField(oop); return MakeUUID(location); } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { return sqUUIDShutdown(); } static sqInt sqAssert(sqInt aBool) { /* missing DebugCode */; } #ifdef SQUEAK_BUILTIN_PLUGIN void* UUIDPlugin_exports[][3] = { {"UUIDPlugin", "shutdownModule", (void*)shutdownModule}, {"UUIDPlugin", "setInterpreter", (void*)setInterpreter}, {"UUIDPlugin", "initialiseModule", (void*)initialiseModule}, {"UUIDPlugin", "primitiveMakeUUID", (void*)primitiveMakeUUID}, {"UUIDPlugin", "getModuleName", (void*)getModuleName}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:04 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include /* D T Lewis - UnixOSProcessPlugin.c translated from class UnixOSProcessPlugin of OSProcessPlugin version 4.3.3 */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #define FILEHANDLETYPE FILE * /* the type of low level stream to be used in a struct SQFile */ #ifndef SQAIO_H # define SQAIO_H "aio.h" /* aio.h has been renamed to sqaio.h */ #endif #include SQAIO_H #include "FilePlugin.h" #include "SocketPlugin.h" #define SESSIONIDENTIFIERTYPE int #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static void aioForwardwithDataandFlags(int fd, void *data, int flags); static char * cStringFromString(sqInt aString); static void * callocWrappersize(sqInt count, sqInt objectSize); static sqInt copyBytesFromtolength(void *charArray1, void *charArray2, sqInt len); static sqInt createPipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr); static sqInt descriptorTableSize(void); static void dupToStdErr(sqInt anSQFileDataStructure); static void dupToStdIn(sqInt anSQFileDataStructure); static void dupToStdOut(sqInt anSQFileDataStructure); static sqInt fileDescriptorFrom(sqInt aSQFileByteArray); static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray); static sqInt fileRecordSize(void); static SQFile * fileValueOf(sqInt anSQFileRecord); static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count); static sqInt forkAndExecInDirectory(sqInt useSignalHandler); #pragma export on EXPORT(pid_t) forkSqueak(sqInt useSignalHandler); #pragma export off static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex); static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt getThisSessionIdentifier(void); static sqInt halt(void); static void handleSignal(int sigNum); static void * handleSignalFunctionAddress(void); #pragma export on EXPORT(sqInt) initialiseModule(void); #pragma export off static sqInt initializeModuleForPlatform(void); static sqInt isNonNullSQFile(sqInt objectPointer); static sqInt isNullSQSocket(sqInt objectPointer); static sqInt isSQFileObject(sqInt objectPointer); static sqInt isSQSocketObject(sqInt objectPointer); static sqInt isValidFileSession(sqInt objectPointer); static sqInt isVmThread(void); static sqInt makePipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr); static sqInt maskForThisThreadAndResend(int sigNum); static sqInt maskSignalForThisThread(int sigNum); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); static sqInt newPthreadTypeByteArray(sqInt aPthreadType); static sqInt newSQFileByteArray(void); static sqInt newSQSocketByteArray(void); static void ** originalSignalHandlers(void); static void * pointerFrom(sqInt aByteArray); #pragma export on EXPORT(sqInt) primitiveAioDisable(void); EXPORT(sqInt) primitiveAioEnable(void); EXPORT(sqInt) primitiveAioHandle(void); EXPORT(sqInt) primitiveAioSuspend(void); EXPORT(sqInt) primitiveArgumentAt(void); EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid); EXPORT(sqInt) primitiveChdir(void); EXPORT(sqInt) primitiveCreatePipe(void); EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveDupTo(sqInt oldFileDescriptor, sqInt newFileDescriptor); EXPORT(sqInt) primitiveEnvironmentAt(void); EXPORT(sqInt) primitiveEnvironmentAtSymbol(void); EXPORT(sqInt) primitiveErrorMessageAt(void); EXPORT(sqInt) primitiveFileProtectionMask(void); EXPORT(sqInt) primitiveFileStat(void); EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void); EXPORT(sqInt) primitiveForkAndExecInDirectory(void); EXPORT(sqInt) primitiveForkExec(void); EXPORT(sqInt) primitiveForkSqueak(void); EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void); EXPORT(sqInt) primitiveForwardSignalToSemaphore(void); EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void); EXPORT(sqInt) primitiveGetEGid(void); EXPORT(sqInt) primitiveGetEUid(void); EXPORT(sqInt) primitiveGetGid(void); EXPORT(sqInt) primitiveGetPGid(void); EXPORT(sqInt) primitiveGetPGrp(void); EXPORT(sqInt) primitiveGetPPid(void); EXPORT(sqInt) primitiveGetPid(void); EXPORT(sqInt) primitiveGetSession(void); EXPORT(sqInt) primitiveGetStdErrHandle(void); EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdInHandle(void); EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetStdOutHandle(void); EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void); EXPORT(sqInt) primitiveGetThreadID(void); EXPORT(sqInt) primitiveGetUid(void); EXPORT(sqInt) primitiveIsAtEndOfFile(void); EXPORT(sqInt) primitiveKillOnExit(void); EXPORT(sqInt) primitiveLockFileRegion(void); EXPORT(sqInt) primitiveMakePipe(void); EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void); EXPORT(sqInt) primitiveModuleName(void); EXPORT(sqInt) primitiveNice(void); EXPORT(sqInt) primitivePutEnv(void); EXPORT(sqInt) primitiveRealpath(void); EXPORT(sqInt) primitiveReapChildProcess(void); EXPORT(sqInt) primitiveSQFileFlush(void); EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetBlocking(void); EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetNonBlocking(void); EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void); EXPORT(sqInt) primitiveSQFileSetUnbuffered(void); EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void); EXPORT(sqInt) primitiveSemaIndexFor(void); EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid); EXPORT(sqInt) primitiveSetPGid(void); EXPORT(sqInt) primitiveSetPGrp(void); EXPORT(sqInt) primitiveSetSemaIndex(void); EXPORT(sqInt) primitiveSetSid(void); EXPORT(sqInt) primitiveSigChldNumber(void); EXPORT(sqInt) primitiveSigHupNumber(void); EXPORT(sqInt) primitiveSigIntNumber(void); EXPORT(sqInt) primitiveSigKillNumber(void); EXPORT(sqInt) primitiveSigPipeNumber(void); EXPORT(sqInt) primitiveSigQuitNumber(void); EXPORT(sqInt) primitiveSigTermNumber(void); EXPORT(sqInt) primitiveSigUsr1Number(void); EXPORT(sqInt) primitiveSigUsr2Number(void); EXPORT(sqInt) primitiveSizeOfInt(void); EXPORT(sqInt) primitiveSizeOfPointer(void); EXPORT(sqInt) primitiveTestEndOfFileFlag(void); EXPORT(sqInt) primitiveTestLockableFileRegion(void); EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber); EXPORT(sqInt) primitiveUnixFileNumber(void); EXPORT(sqInt) primitiveUnlockFileRegion(void); EXPORT(sqInt) primitiveUnsetEnv(void); EXPORT(sqInt) primitiveVersionString(void); #pragma export off static void reapChildProcess(int sigNum); static sqInt resendSignal(int sigNum); static void restoreDefaultSignalHandlers(void); static sqInt sandboxSecurity(void); static sqInt securityHeurisitic(void); static unsigned char * semaphoreIndices(void); static sqInt sendSignaltoPid(sqInt sig, sqInt pid); static void sendSignalToPids(void); static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray); static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); #pragma export off static void setSigChldDefaultHandler(void); static void setSigChldHandler(void); static void setSigIntDefaultHandler(void); static void setSigIntIgnore(void); static void setSigPipeDefaultHandler(void); static sqInt setSigPipeHandler(void); static void setSigPipeIgnore(void); static void * setSignalNumberhandler(sqInt anInteger, void *signalHandlerAddress); #pragma export on EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt sigAbrtNumber(void); static sqInt sigAlrmNumber(void); static sqInt sigChldNumber(void); static sqInt sigContNumber(void); static void * sigDefaultNumber(void); static void * sigErrorNumber(void); static sqInt sigHupNumber(void); static void * sigIgnoreNumber(void); static sqInt sigIntNumber(void); static sqInt sigKillNumber(void); static sqInt sigPipeNumber(void); static sqInt sigQuitNumber(void); static sqInt sigStopNumber(void); static sqInt sigTermNumber(void); static sqInt sigUsr1Number(void); static sqInt sigUsr2Number(void); static sqInt signalArraySize(void); static void ** signalHandlers(void); static sqInt sizeOfInt(void); static sqInt sizeOfPointer(void); static sqInt sizeOfSession(void); static int socketDescriptorFrom(sqInt sqSocketOop); static sqInt socketRecordSize(void); static SQSocket * socketValueOf(sqInt anSQSocketRecord); static sqInt stringFromCString(const char *aCString); static char * transientCStringFromString(sqInt aString); static int unixFileNumber(FILEHANDLETYPE fileHandle); static char * versionString(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "UnixOSProcessPlugin 23 January 2011 (i)" #else "UnixOSProcessPlugin 23 January 2011 (e)" #endif ; static void *originalSigHandlers[NSIG]; static int osprocessSandboxSecurity; static pid_t *pidArray = NULL; static sqInt pidCount; static unsigned char semaIndices[NSIG]; static sqInt sigChldSemaIndex; static void *sigHandlers[NSIG]; static int sigNumToSend = SIGTERM; static pthread_t vmThread; /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* This function is called to signal a Smalltalk Semaphore when an asynchronous event is detected. When translated to C, the name of this method is aioForwardwithDataandFlags. The event handler is set up by #primitiveAioHandle. */ static void aioForwardwithDataandFlags(int fd, void *data, int flags) { sqInt *pfd; sqInt semaIndex; pfd = data; semaIndex = *pfd; interpreterProxy->signalSemaphoreWithIndex(semaIndex); } /* Answer a new null-terminated C string copied from aString. The C string is allocated from the C runtime heap. See transientCStringFromString for a version which allocates from object memory. Caution: This may invoke the garbage collector. */ static char * cStringFromString(sqInt aString) { char *cString; sqInt len; char *sPtr; sPtr = interpreterProxy->arrayValueOf(aString); len = interpreterProxy->sizeOfSTArrayFromCPrimitive(sPtr); /* Space for a null terminated C string. */ cString = callocWrappersize(len + 1, 1); (char *) strncpy (cString, sPtr, len); return cString; } /* Using malloc() and calloc() is something I would like to avoid, since it is likely to cause problems some time in the future if somebody redesigns object memory allocation. This wrapper just makes it easy to find senders of calloc() in my code. -dtl */ static void * callocWrappersize(sqInt count, sqInt objectSize) { return calloc(count, objectSize); } /* self cCode: 'memcpy(charArray2, charArray1, len' */ static sqInt copyBytesFromtolength(void *charArray1, void *charArray2, sqInt len) { memcpy(charArray2, charArray1, len); } /* Create a pipe and populate the readerIOStream and writerIOStream variables. The SIGPIPE handler must have been set before creating the pipe. Answer true for success, else false. */ static sqInt createPipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr) { int filedes[2]; if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } /* Answer the size of the file descriptor table for a process. I am not sure of the most portable way to do this. If this implementation does not work on your Unix platform, try changing it to answer the value of FOPEN:=MAX, which will hopefully be defined in stdio.h. If all else fails, just hard code it to answer 20, which would be safe for any Unix. */ static sqInt descriptorTableSize(void) { return getdtablesize(); } /* Dup a file descriptor to allow it to be attached as the standard error when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdErr(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 2)) { fflush(stderr); dup2(filenoToDup, 2); } } } /* Dup a file descriptor to allow it to be attached as the standard input when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdIn(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 0)) { fflush(stdin); dup2(filenoToDup, 0); rewind(stdin); } } } /* Dup a file descriptor to allow it to be attached as the standard output when we exec() a new executable. This is Unix specific, in that it assumes that file descriptor 0 is stdin, 1 is stdout, and 2 is stderr. The dup2() call is used to copy the open file descriptors into file descriptors 0, 1 and 2 so that the image which we execute will use them as stdin, stdout, and stderr. */ static void dupToStdOut(sqInt anSQFileDataStructure) { sqInt filenoToDup; /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(anSQFileDataStructure)) && ((interpreterProxy->byteSizeOf(anSQFileDataStructure)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(anSQFileDataStructure))))) && (isNonNullSQFile(anSQFileDataStructure)))) { filenoToDup = -1; goto l1; } filenoToDup = fileno(fileHandleFrom(anSQFileDataStructure)); l1: /* end fileDescriptorFrom: */; if (!(filenoToDup < 0)) { if (!(filenoToDup == 1)) { fflush(stdout); dup2(filenoToDup, 1); } } } /* Answer the OS file descriptor, an integer value, from a SQFile data structure byte array, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). */ /* return type should be int, but skip the declaration to permit inlining */ static sqInt fileDescriptorFrom(sqInt aSQFileByteArray) { if (!((((interpreterProxy->isBytes(aSQFileByteArray)) && ((interpreterProxy->byteSizeOf(aSQFileByteArray)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(aSQFileByteArray))))) && (isNonNullSQFile(aSQFileByteArray)))) { return -1; } return fileno(fileHandleFrom(aSQFileByteArray)); } /* Answer a file handle from a SQFile structure. On most platforms, this will be a (FILE *). On Win32, it is a HANDLE. */ static FILEHANDLETYPE fileHandleFrom(sqInt sqFileStructByteArray) { SQFile *sqFile; sqFile = interpreterProxy->arrayValueOf(sqFileStructByteArray); return sqFile->file; } /* Answer the size of a SQFile data structure in bytes. */ static sqInt fileRecordSize(void) { return sizeof(SQFile); } /* Return a pointer to the first byte of of the SQFile data structure file record within anSQFileRecord, which is expected to be a ByteArray of size self>>fileRecordSize. */ static SQFile * fileValueOf(sqInt anSQFileRecord) { return interpreterProxy->arrayValueOf(anSQFileRecord); } /* Use the address offsets in offsetArray to fix up the pointers in cStringArray. The result is a C array of pointers to char, used for argv and env vectors. */ static sqInt fixPointersInArrayOfStringswithOffsetscount(char *flattenedArrayOfStrings, sqInt *offsetArray, sqInt count) { sqInt idx; char **ptr; ptr = ((char **) flattenedArrayOfStrings); idx = 0; while (idx < count) { ptr[idx] = (flattenedArrayOfStrings + (((offsetArray[idx]) >> 1))); idx += 1; } } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. If useSignalHandler is true, set the signal handler for SIGCHLD. Otherwise, assume that death of child events are handled through some other mechanism. In this implementation, memory for the argument and environment arrays is allocated in the image prior to calling this primitive. This allows us to avoid invoking the garbage collector in this primitive (thereby moving the locations of environment and argument memory), but comes at the cost of twiddling C pointers here in the primitive. An alternative to this whole mess is just to malloc the environment and argument vectors, but I think it is a good idea to avoid malloc as much as possible so as not to limit future ObjectMemory implementations. This primitive replaces #primitiveForkAndExec from earlier versions of the plugin. The new name permits backward compatibility for an image running on a VM which does not yet have the updated plugin. This implementation uses a different argument format on the stack, and differs functionally in that the child now closes all file descriptors (including sockets) not required (that is, everything except stdin, stdout, and stderr on descriptors 0, 1 and 2). This eliminates some flakey behavior in child processes connected to Squeak by pipes, which failed to exit at expected times due to the old file descriptors remaining open. This is also cleaner in that garbage descriptors are not left hanging around the the child. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ static sqInt forkAndExecInDirectory(sqInt useSignalHandler) { sqInt argCount; sqInt *argOffsetPtr; sqInt argOffsets; sqInt argVecBuffer; char **args; char *argsPtr; char **env; sqInt envCount; sqInt *envOffsetPtr; sqInt envOffsets; char *envPtr; extern char **envVec; sqInt envVecBuffer; sqInt executableFile; sqInt handleCount; sqInt idx; struct itimerval intervalTimer; pid_t pid; char *progNamePtr; sqInt pwd; char *pwdPtr; struct itimerval saveIntervalTimer; sqInt stdErr; sqInt stdIn; sqInt stdOut; sqInt workingDir; sqInt sigNum; if (useSignalHandler) { setSigChldHandler(); } if ((sandboxSecurity()) == 1) { interpreterProxy->pop(10); interpreterProxy->pushInteger(-1); } else { intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if ((pid = vfork()) == 0) { /* This is the new child process */ workingDir = interpreterProxy->stackObjectValue(0); envOffsets = interpreterProxy->stackObjectValue(1); envVecBuffer = interpreterProxy->stackObjectValue(2); argOffsets = interpreterProxy->stackObjectValue(3); argVecBuffer = interpreterProxy->stackObjectValue(4); stdErr = interpreterProxy->stackObjectValue(5); stdOut = interpreterProxy->stackObjectValue(6); stdIn = interpreterProxy->stackObjectValue(7); /* If a new working directory has been specified, try to chdir() to it. */ executableFile = interpreterProxy->stackObjectValue(8); if (workingDir != (interpreterProxy->nilObject())) { pwdPtr = interpreterProxy->firstIndexableField(workingDir); if (pwdPtr == 0) { fprintf(stderr, "bad workingDir parameter\n"); _exit(-1); } else { pwd = chdir(pwdPtr); if (pwd != 0) { perror("chdir"); _exit(-1); } } } /* Dup the file handles to attach the new child process to the right streams on descriptors 0, 1 and 2. */ progNamePtr = interpreterProxy->arrayValueOf(executableFile); if (!(stdErr == (interpreterProxy->nilObject()))) { dupToStdErr(stdErr); } if (!(stdOut == (interpreterProxy->nilObject()))) { dupToStdOut(stdOut); } if (!(stdIn == (interpreterProxy->nilObject()))) { dupToStdIn(stdIn); } /* First Unix file descriptor after stdin, stdout, stderr. */ idx = 3; handleCount = descriptorTableSize(); while (idx < handleCount) { close(idx); idx += 1; } if (envVecBuffer == (interpreterProxy->nilObject())) { env = envVec; } else { envCount = interpreterProxy->stSizeOf(envOffsets); envPtr = interpreterProxy->arrayValueOf(envVecBuffer); envOffsetPtr = interpreterProxy->firstIndexableField(envOffsets); fixPointersInArrayOfStringswithOffsetscount(envPtr, envOffsetPtr, envCount); env = ((char **) envPtr); } argCount = interpreterProxy->stSizeOf(argOffsets); argsPtr = interpreterProxy->arrayValueOf(argVecBuffer); argOffsetPtr = interpreterProxy->firstIndexableField(argOffsets); fixPointersInArrayOfStringswithOffsetscount(argsPtr, argOffsetPtr, argCount); /* Clean things up before clobbering the running image. */ /* Note: If any file descriptors, signal handlers, or other references to external resources need to be cleaned up, do it here. */ args = ((char **) argsPtr); /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } if ((execve(progNamePtr, args, env)) == -1) { perror(progNamePtr); _exit(-1); } else { /* Can't get here from there */; } } else { setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); interpreterProxy->pop(10); interpreterProxy->pushInteger(pid); } } } /* Fork a child process, and continue running squeak in the child process. Answer the result of the fork() call, either the child pid or zero. After calling fork(), two OS processes exist, one of which is the child of the other. On systems which implement copy-on-write memory management, and which support the fork() system call, both processes will be running Smalltalk images, and will be sharing the same memory space. In the original OS process, the resulting value of pid is the process id of the child process (a non-zero integer). In the child process, the value of pid is zero. The child recreates sufficient external resources to continue running. This is done by attaching to a new X session. The child is otherwise a copy of the parent process, and will continue executing the Smalltalk image at the same point as its parent. The return value of this primitive may be used by the two running Smalltalk images to determine which is the parent and which is the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. The new child image does not start itself from the image in the file system; rather it is a clone of the parent image as it existed at the time of primitiveForkSqueak. For this reason, the parent and child should agree in advance as to whom is allowed to save the image to the file system, otherwise one Smalltalk may overwrite the image of the other. This is a simple call to fork(), rather than the more common idiom of vfork() followed by exec(). The vfork() call cannot be used here because it is designed to be followed by an exec(), and its semantics require the parent process to wait for the child to exit. See the BSD programmers documentation for details. */ EXPORT(pid_t) forkSqueak(sqInt useSignalHandler) { struct itimerval intervalTimer; pid_t pid; struct itimerval saveIntervalTimer; intervalTimer.it_interval.tv_sec = 0; intervalTimer.it_interval.tv_usec = 0; intervalTimer.it_value.tv_sec = 0; intervalTimer.it_value.tv_usec = 0; setitimer (ITIMER_REAL, &intervalTimer, &saveIntervalTimer); if (useSignalHandler) { setSigChldHandler(); } /* Enable the timer again before resuming Smalltalk. */ pid = fork(); setitimer (ITIMER_REAL, &saveIntervalTimer, 0L); return pid; } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero, the handler is unregistered, and the VM returns to its default behavior for handling that signal. A handler must be unregistered before it can be registered again. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ static void * forwardSignaltoSemaphoreAt(sqInt sigNum, sqInt semaphoreIndex) { void *oldHandler; if (semaphoreIndex == 0) { if ((semaIndices[sigNum]) > 0) { /* Disable the handler */ oldHandler = originalSigHandlers[sigNum]; setSignalNumberhandler(sigNum, oldHandler); semaIndices[sigNum] = 0; return oldHandler; } else { return sigErrorNumber(); } } if ((semaIndices[sigNum]) > 0) { return sigErrorNumber(); } oldHandler = setSignalNumberhandler(sigNum, handleSignalFunctionAddress()); if (oldHandler != (sigErrorNumber())) { originalSigHandlers[sigNum] = oldHandler; semaIndices[sigNum] = semaphoreIndex; } return oldHandler; } /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt getThisSessionIdentifier(void) { return interpreterProxy->getThisSessionID(); } static sqInt halt(void) { ; } /* This is a signal handler function which runs when a signal is received from the operating system. When the signal is received, a Smalltalk Semaphore is signaled. This effectively passes the external signal to Squeak to allow it to be handled in Smalltalk. */ static void handleSignal(int sigNum) { sqInt semaIndex; semaIndex = semaIndices[sigNum]; forwardSignaltoSemaphoreAt(sigNum, semaIndex); if (isVmThread()) { if (semaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(semaIndex); } } else { maskForThisThreadAndResend(sigNum); } } static void * handleSignalFunctionAddress(void) { return handleSignal; } EXPORT(sqInt) initialiseModule(void) { osprocessSandboxSecurity = -1; initializeModuleForPlatform(); return 1; } /* Platform specific initialization */ static sqInt initializeModuleForPlatform(void) { pidCount = 0; atexit(sendSignalToPids); vmThread = pthread_self(); } /* Check for the common failure mode of a SQFile record with all zeros. */ static sqInt isNonNullSQFile(sqInt objectPointer) { sqInt idx; unsigned char *sqFileBytes; sqFileBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (fileRecordSize())) { if ((sqFileBytes[idx]) != 0) { return 1; } idx += 1; } return 0; } /* Check for the common failure mode of a SQSocket record with all zeros. */ static sqInt isNullSQSocket(sqInt objectPointer) { sqInt idx; unsigned char *sqSocketBytes; sqSocketBytes = interpreterProxy->arrayValueOf(objectPointer); idx = 0; while (idx < (socketRecordSize())) { if ((sqSocketBytes[idx]) != 0) { return 0; } idx += 1; } return 1; } /* Answer true if objectPointer appears to be a valid SQFile ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid file reference. */ static sqInt isSQFileObject(sqInt objectPointer) { return (((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))))) && (isNonNullSQFile(objectPointer)); } /* Answer true if objectPointer appears to be a valid SQSocket ByteArray. This check is appropriate if objectPointer has been passed as a parameter to a primitive, and is expected to represent a valid socket reference. */ static sqInt isSQSocketObject(sqInt objectPointer) { return ((interpreterProxy->isBytes(objectPointer)) && ((interpreterProxy->byteSizeOf(objectPointer)) == (socketRecordSize()))) && (!(isNullSQSocket(objectPointer))); } /* Answer true if the file session matches the current interpreter session identifier. */ static sqInt isValidFileSession(sqInt objectPointer) { return (interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(objectPointer))); } /* Answer true if this method is executing in the context of the pthread in which the interpreter executes. */ static sqInt isVmThread(void) { pthread_t thisThread; thisThread = pthread_self(); return pthread_equal(thisThread, vmThread); } /* Create a pipe and populate the readerIOStream and writerIOStream variables. Make sure the SIGPIPE handler is set before creating the pipe. Answer true for success, else false */ static sqInt makePipeForReaderwriter(FILEHANDLETYPE *readerIOStreamPtr, FILEHANDLETYPE *writerIOStreamPtr) { int filedes[2]; /* begin setSigPipeHandler */ /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); if ((pipe(filedes)) == -1) { return 0; } else { *writerIOStreamPtr= (FILE *) fdopen (filedes[1], "a"); *readerIOStreamPtr= (FILE *) fdopen (filedes[0], "r"); return 1; } } /* Prevent any future instances of signal sigNum from being delivered to this pthread, and reschedule the current signal to be delivered to this OS process. Any pthread other than the interpreter thread will call this method. Eventually the signal will be delivered to the interpreter thread, which will handle it in the context of the interpreter thread. */ static sqInt maskForThisThreadAndResend(int sigNum) { maskSignalForThisThread(sigNum); resendSignal(sigNum); } /* Prevent future invocations of signal sigNum from being delivered to this pthread. */ static sqInt maskSignalForThisThread(int sigNum) { sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, sigNum); pthread_sigmask(SIG_BLOCK, &sigset, NULL); } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* A pthread_t is an unsigned long, which may be 8 bytes on some 64 bit platforms. This stores the value in a byte array that can be easily passed to the image. */ static sqInt newPthreadTypeByteArray(sqInt aPthreadType) { sqInt byteArray; sqInt len; pthread_t *ptr; len = sizeof(pthread_t); byteArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), len); ptr = interpreterProxy->arrayValueOf(byteArray); *ptr = aPthreadType; return byteArray; } /* Answer a new ByteArray sized to contain a SQFile data structure. */ static sqInt newSQFileByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); } /* Answer a new ByteArray sized to contain a SQSocket data structure. */ static sqInt newSQSocketByteArray(void) { return interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), socketRecordSize()); } /* An array of signal handler function addresses, one for each signal type. The value at each entry is the address of the original signal handler function prior to having set a handler. */ static void ** originalSignalHandlers(void) { return originalSigHandlers; } /* Answer the pointer represented by aByteArray. */ static void * pointerFrom(sqInt aByteArray) { sqInt idx; union {void *address; unsigned char bytes[sizeof(void *)];} pointerUnion; unsigned char *ptr; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfPointer())))) { return null; } ptr = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfPointer())) { pointerUnion.bytes[idx] = ptr[idx]; idx += 1; } return pointerUnion.address; } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Definitively disable asynchronous event notification for a descriptor. The parameter is a sqFile ByteArray representing the ioHandle for a file. */ EXPORT(sqInt) primitiveAioDisable(void) { int fd; sqInt sqFile; sqFile = interpreterProxy->stackObjectValue(0); /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } aioDisable(fd); interpreterProxy->pop(2); interpreterProxy->pushInteger(fd); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Enable asynchronous notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, the second parameter is the index of a Semaphore to be notified, and the third parameter is a flag indicating that sqFile represents an external object and should not be closed on termination of aio handling. Answer the semaphore index. */ EXPORT(sqInt) primitiveAioEnable(void) { static int eventSemaphoreIndices[FD_SETSIZE]; sqInt externalObject; int fd; int flags; sqInt semaIndex; sqInt sqFile; sqFile = interpreterProxy->stackObjectValue(2); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } semaIndex = interpreterProxy->stackIntegerValue(1); eventSemaphoreIndices[semaIndex] = semaIndex; externalObject = interpreterProxy->stackObjectValue(0); if (externalObject == (interpreterProxy->trueObject())) { flags = AIO_EXT; } else { flags = 0; } aioEnable(fd, &(eventSemaphoreIndices[semaIndex]), flags); interpreterProxy->pop(4); interpreterProxy->pushInteger(semaIndex); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Handle asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioHandle(void) { sqInt exceptionWatch; int fd; int flags; sqInt readWatch; sqInt sqFile; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioHandle(fd, aioForwardwithDataandFlags, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Deprecated. This primitive has been replaced by a similar implementation in AioPlugin. */ /* Temporarily suspend asynchronous event notification for a descriptor. The first parameter is a sqFile ByteArray representing the ioHandle for a file, and the remaining three parameters are Boolean flags representing the types of events for which notification is being requested: handle exceptions, handle for read, and handle for write. Flags are defined in the aio.h source as: AIO_X (1<<0) handle for exceptions AIO_R (1<<1) handle for read AIO_W (1<<2) handle for write */ EXPORT(sqInt) primitiveAioSuspend(void) { sqInt exceptionWatch; int fd; int flags; sqInt readWatch; sqInt sqFile; sqInt writeWatch; sqFile = interpreterProxy->stackObjectValue(3); if (!((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->stSizeOf(sqFile)) == (fileRecordSize())))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFile)) && ((interpreterProxy->byteSizeOf(sqFile)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFile))))) && (isNonNullSQFile(sqFile)))) { fd = -1; goto l1; } fd = fileno(fileHandleFrom(sqFile)); l1: /* end fileDescriptorFrom: */; if (fd < 0) { return interpreterProxy->primitiveFail(); } exceptionWatch = interpreterProxy->stackObjectValue(2); readWatch = interpreterProxy->stackObjectValue(1); writeWatch = interpreterProxy->stackObjectValue(0); flags = 0; if (exceptionWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_X); } if (readWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (interpreterProxy->trueObject())) { flags = flags | (AIO_W); } aioSuspend(fd, flags); interpreterProxy->pop(5); interpreterProxy->pushInteger(flags); } /* Answer a string containing the OS process argument at index (an Integer) in the argument list. */ EXPORT(sqInt) primitiveArgumentAt(void) { extern int argCnt; extern char **argVec; sqInt index; sqInt s; char *sPtr; index = interpreterProxy->stackIntegerValue(0); if ((index > argCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = argVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Send a null signal to the OS process identified by anIntegerPid. Answer false for a bad parameter on the stack (the common case is for anIntegerPid equal to nil, for which case we should answer false). Answer true if the process exists and can receive signals from this process, otherwise false. This test is useful for determining if a child process still exists following a Squeak image restart. */ EXPORT(sqInt) primitiveCanReceiveSignals(sqInt anIntegerPid) { pid_t pidToSignal; int result; if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); result = kill(pidToSignal, 0); interpreterProxy->pop(2); if (result == 0) { interpreterProxy->push(interpreterProxy->trueObject()); } else { interpreterProxy->push(interpreterProxy->falseObject()); } } else { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->falseObject()); } } /* Call chdir(2) to change current working directory to the specified path string. Answer nil for success, or errno on failure. */ EXPORT(sqInt) primitiveChdir(void) { extern int errno; char *path; path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); if (chdir(path)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipe(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveCreatePipeWithSessionIdentifier(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(createPipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Call dup2() to duplicate a file descriptor. Answer the duplicated file descriptor or -1 on failure. */ EXPORT(sqInt) primitiveDupTo(sqInt oldFileDescriptor, sqInt newFileDescriptor) { int newfd; int oldfd; int result; newfd = interpreterProxy->stackIntegerValue(0); oldfd = interpreterProxy->stackIntegerValue(1); result = dup2(oldfd, newfd); interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } /* Answer a string containing the OS process environment string at index (an Integer) in the environment list. */ EXPORT(sqInt) primitiveEnvironmentAt(void) { sqInt envCnt; extern char **envVec; sqInt index; char **p; sqInt s; char *sPtr; p = envVec; envCnt = 0; while (*p++) envCnt++; index = interpreterProxy->stackIntegerValue(0); if ((index > envCnt) || (index < 1)) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { sPtr = envVec[index - 1]; s = stringFromCString(sPtr); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Answer the value of an environment variable keyed by a Symbol. */ EXPORT(sqInt) primitiveEnvironmentAtSymbol(void) { char * getenvResult; getenvResult = getenv(transientCStringFromString(interpreterProxy->stackObjectValue(0))); if (getenvResult == 0) { return interpreterProxy->primitiveFail(); } else { interpreterProxy->pop(2); interpreterProxy->push(stringFromCString(getenvResult)); } } /* Answer a string describing an error message */ EXPORT(sqInt) primitiveErrorMessageAt(void) { sqInt errMessage; sqInt index; char *p; index = interpreterProxy->stackIntegerValue(0); p = ((char *) (strerror(index))); errMessage = stringFromCString(p); interpreterProxy->pop(2); interpreterProxy->push(errMessage); } /* Call stat(2) to obtain the file protection mask for a file. Answer an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileProtectionMask(void) { sqInt buffer; extern int errno; sqInt mode; char *path; sqInt result; struct stat *statBuf; buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); interpreterProxy->stObjectatput(result, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(result, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* Call stat(2) to obtain the file protection mask for a file. Answer errno on failure, or on success answer an array with: UID with: GID with: protectionMask. The protectionMask is an Array of four integers representing the protection mask, or answer errno on failure. The protection mask is four Integers, each of which may be considered an octal digit (0-7), with bit values 4, 2, and 1. The first digit selects the set user ID (4) and set group ID (2) and save text image (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file's group, with the same values; and the fourth for other users not in the file's group, with the same values. */ EXPORT(sqInt) primitiveFileStat(void) { sqInt buffer; extern int errno; sqInt gid; sqInt mask; sqInt mode; char *path; sqInt result; struct stat *statBuf; sqInt uid; result = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 3); uid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(uid_t)); gid = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(gid_t)); mask = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4); buffer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(struct stat)); statBuf = interpreterProxy->arrayValueOf(buffer); path = transientCStringFromString(interpreterProxy->stackObjectValue(0)); mode = stat(path, statBuf); if (mode == 0) { mode = statBuf->st_mode; interpreterProxy->stObjectatput(mask, 4, (((mode & 07) << 1) | 1)); interpreterProxy->stObjectatput(mask, 3, ((((mode & 070) >> 3) << 1) | 1)); interpreterProxy->stObjectatput(mask, 2, ((((mode & 0700) >> 6) << 1) | 1)); interpreterProxy->stObjectatput(mask, 1, ((((mode & 07000) >> 9) << 1) | 1)); interpreterProxy->stObjectatput(result, 3, mask); interpreterProxy->stObjectatput(result, 2, (((statBuf->st_gid) << 1) | 1)); interpreterProxy->stObjectatput(result, 1, (((statBuf->st_uid) << 1) | 1)); interpreterProxy->pop(2); interpreterProxy->push(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(errno); } } /* This primitive exists only for purposes of testing the fixPointersInArrayOfStrings:withOffsets:count: method. I believe it to be reasonably machine and compiler independent, but have no way of verifying this on a variety of machines, so I'll leave this test method here in case someone runs into problems on other hardware or compilers. -dtl */ EXPORT(sqInt) primitiveFixPointersInArrayOfStrings(void) { sqInt cStringArray; sqInt count; char *flattenedArrayOfStrings; sqInt offsetArray; sqInt *offsets; count = interpreterProxy->stackIntegerValue(0); offsetArray = interpreterProxy->stackObjectValue(1); cStringArray = interpreterProxy->stackObjectValue(2); offsets = interpreterProxy->firstIndexableField(offsetArray); flattenedArrayOfStrings = interpreterProxy->arrayValueOf(cStringArray); fixPointersInArrayOfStringswithOffsetscount(flattenedArrayOfStrings, offsets, count); interpreterProxy->pop(4); interpreterProxy->push(cStringArray); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkAndExecInDirectory(void) { return forkAndExecInDirectory(1); } /* Fork a child OS process, and do an exec in the child. The parent continues on in Smalltalk, and this method answers the pid of the child which was created. On entry, the stack contains: 0: workingDir, a null terminated string specifying the working directory to use, or nil. 1: envOffsets, an array of integers for calculating environment string address offsets. 2: envVecBuffer, a String buffer containing environment strings arranged to look like char **. 3: argOffsets, an array of integers for calculating argument string address offsets. 4: argVecBuffer, a String buffer containing argument strings arranged to look like char **. 5: stdErr, a ByteArray handle. 6: stdOut, a ByteArray handle. 7: stdIn, a ByteArray handle. 8: executableFile, a null terminated string with the name of the file to execute. 9: the sender */ EXPORT(sqInt) primitiveForkExec(void) { return forkAndExecInDirectory(0); } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueak(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(1); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Fork a child process, and continue running squeak in the child process. Leave the X session connected to the parent process, but close its file descriptor for the child process. Open a new X session for the child. The child should not depend on using existing connections to external resources. For example, the child may lose its connections to stdin, stdout, and stderr after its parent exits. */ EXPORT(sqInt) primitiveForkSqueakWithoutSigHandler(void) { pid_t pid; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(1); interpreterProxy->pushInteger(-1); } else { pid = forkSqueak(0); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } } /* Set a signal handler in the VM which will signal a Smalltalk semaphore at semaphoreIndex whenever an external signal sigNum is received. Answer the prior value of the signal handler. If semaphoreIndex is zero or nil, the handler is unregistered, and the VM returns to its default behavior for handling that signal. The Smalltalk semaphore is expected to be kept at the same index location indefinitely during the lifetime of a Squeak session. If that is not the case, the handler must be unregistered prior to unregistering the Smalltalk semaphore. */ EXPORT(sqInt) primitiveForwardSignalToSemaphore(void) { char *hPtr; void *handler; sqInt idx; sqInt index; union {void *handler; unsigned char bytes[sizeof(void *)];} priorHandler; sqInt priorHandlerObject; sqInt semaphoreIndex; sqInt sigNum; index = interpreterProxy->stackValue(0); if (index == (interpreterProxy->nilObject())) { semaphoreIndex = 0; } else { if ((index & 1)) { semaphoreIndex = interpreterProxy->stackIntegerValue(0); } else { return interpreterProxy->primitiveFail(); } } sigNum = interpreterProxy->stackIntegerValue(1); handler = forwardSignaltoSemaphoreAt(sigNum, semaphoreIndex); if (handler == (sigErrorNumber())) { return interpreterProxy->primitiveFail(); } priorHandlerObject = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeOfPointer()); hPtr = interpreterProxy->arrayValueOf(priorHandlerObject); priorHandler.handler = handler; idx = 0; while (idx < (sizeOfPointer())) { hPtr[idx] = priorHandler.bytes[idx]; idx += 1; } interpreterProxy->popthenPush(3, priorHandlerObject); } /* Answer a string containing the current working directory. */ EXPORT(sqInt) primitiveGetCurrentWorkingDirectory(void) { char *buffer; sqInt bufferSize; char *cwd; sqInt cwdString; sqInt incrementBy; sqInt maxSize; bufferSize = 100; incrementBy = 100; maxSize = 5000; while (1) { cwdString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); buffer = interpreterProxy->arrayValueOf(cwdString); /* getcwd(buffer, bufferSize) */ cwd = getcwd(buffer, bufferSize); if (!((cwd == 0) && (bufferSize < maxSize))) break; bufferSize += incrementBy; } if (cwd == 0) { return interpreterProxy->primitiveFail(); } else { cwdString = stringFromCString(cwd); interpreterProxy->pop(1); interpreterProxy->push(cwdString); } } /* Answer the effective group ID of my OS process */ EXPORT(sqInt) primitiveGetEGid(void) { gid_t eGid; eGid = getegid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eGid); } /* Answer the effective user ID of my OS process */ EXPORT(sqInt) primitiveGetEUid(void) { uid_t eUid; eUid = geteuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(eUid); } /* Answer the group ID of my OS process */ EXPORT(sqInt) primitiveGetGid(void) { gid_t gid; gid = getgid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(gid); } /* Answer the process group ID of the process identified by pid */ EXPORT(sqInt) primitiveGetPGid(void) { pid_t pgid; pid_t pid; pid = interpreterProxy->stackIntegerValue(0); pgid = getpgid(pid); if (pgid == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); interpreterProxy->pushInteger(pgid); } /* Answer the process group ID of this OS process */ EXPORT(sqInt) primitiveGetPGrp(void) { pid_t pgid; pgid = getpgrp(); if (pgid == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); interpreterProxy->pushInteger(pgid); } /* Answer the process ID of the parent process of my OS process */ EXPORT(sqInt) primitiveGetPPid(void) { pid_t ppid; ppid = getppid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(ppid); } /* Answer the process ID of my OS process */ EXPORT(sqInt) primitiveGetPid(void) { pid_t pid; pid = getpid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(pid); } /* Answer the unique session identifier for this Smalltalk instance running in this OS process. The C integer value is coerced into a Smalltalk ByteArray to preserve the full range of possible values. */ EXPORT(sqInt) primitiveGetSession(void) { unsigned char *sessionByteArrayPointer; sqInt sessionIDSize; sqInt sessionOop; SESSIONIDENTIFIERTYPE thisSessionID; thisSessionID = interpreterProxy->getThisSessionID(); sessionIDSize = sizeof(thisSessionID); sessionOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sessionIDSize); sessionByteArrayPointer = interpreterProxy->arrayValueOf(sessionOop); if (thisSessionID == null) { return interpreterProxy->primitiveFail(); } copyBytesFromtolength((unsigned char *)&thisSessionID, sessionByteArrayPointer, sessionIDSize); interpreterProxy->pop(1); interpreterProxy->push(sessionOop); } /* Answer the file handle for standard error of my OS process */ EXPORT(sqInt) primitiveGetStdErrHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard error of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdErrHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stderr; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process */ EXPORT(sqInt) primitiveGetStdInHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard input of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdInHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdin; file->sessionID = thisSession; file->writable = 0; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process */ EXPORT(sqInt) primitiveGetStdOutHandle(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = interpreterProxy->getThisSessionID(); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(1); interpreterProxy->push(fileOop); } /* Answer the file handle for standard output of my OS process. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveGetStdOutHandleWithSessionIdentifier(void) { SQFile *file; sqInt fileOop; SESSIONIDENTIFIERTYPE thisSession; fileOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); file = interpreterProxy->arrayValueOf(fileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); file->file = stdout; file->sessionID = thisSession; file->writable = 1; file->lastOp = 0; interpreterProxy->pop(2); interpreterProxy->push(fileOop); } /* Answer the ID of the pthread that is currently executing (the interpreter thread). A thread ID may be a 64 bit value on some platforms, so answer a byte array containing the value in machine-dependent byte order. */ EXPORT(sqInt) primitiveGetThreadID(void) { interpreterProxy->popthenPush(1, newPthreadTypeByteArray(vmThread)); } /* Answer the user ID of my OS process */ EXPORT(sqInt) primitiveGetUid(void) { uid_t uid; uid = getuid(); interpreterProxy->pop(1); interpreterProxy->pushInteger(uid); } /* Take a struct SQFile from the stack, and call feof(3) to determine if the file has reached end of file. */ /* Deprecated. The return values are reversed. Use primitiveTestEndOfFileFlag. */ EXPORT(sqInt) primitiveIsAtEndOfFile(void) { FILEHANDLETYPE file; sqInt result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); if (file == 0) { return primitiveFail(); } if (feof(file)) { result = interpreterProxy->trueObject(); } else { result = interpreterProxy->falseObject(); } interpreterProxy->pop(2); interpreterProxy->push(result); } /* Set a list of pids to kill with signum when VM exits. If the signum parameter is nil, the default value of SIGTERM will be used. */ EXPORT(sqInt) primitiveKillOnExit(void) { sqInt count; pid_t *p; pid_t pid; sqInt *pidPointer; sqInt pids; sqInt signum; pids = interpreterProxy->stackValue(1); signum = interpreterProxy->stackValue(0); pidCount = interpreterProxy->stSizeOf(pids); if (interpreterProxy->failed()) { return null; } if (!(pidArray == 0)) { free(pidArray); } pidArray = malloc(pidCount * sizeof(pid_t)); if (pidArray == 0) { pidCount = 0; return interpreterProxy->primitiveFail(); } pidPointer = interpreterProxy->firstIndexableField(pids); count = 0; p = pidArray; while (count <= pidCount) { pid = ((*pidPointer++) >> 1); *p++ = pid; count += 1; } if (!(signum == (interpreterProxy->nilObject()))) { sigNumToSend = interpreterProxy->checkedIntegerValueOf(signum); } if (interpreterProxy->failed()) { pidCount = 0; } interpreterProxy->pop(2); } /* Take a struct SQFile from the stack, and request a lock on the specified region. If the exclusive flag is true, then request an exclusive (F_WRLCK) lock on the file. Otherwise, request a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). Answer the result of the call to fcntl(). If length is zero, then the entire file will be locked, including region extents that have not yet been allocated for the file. */ EXPORT(sqInt) primitiveLockFileRegion(void) { sqInt exclusive; int fileNo; sqInt len; struct flock lockStruct; int result; sqInt sqFileOop; sqInt start; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipe(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = interpreterProxy->getThisSessionID(); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(1); interpreterProxy->push(arrayResult); } /* Create a pipe, and answer an array of two file handles for the pipe writer and reader. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). The readerIOStream and writerIOStream variables represent the low level pipe streams, which will be of type (FILE *) or HANDLE, depending on what the FilePlugin support code is using to represent file streams. FILEHANDLETYPE is defined in my subclasses in the #declareCVarsIn: class method. */ EXPORT(sqInt) primitiveMakePipeWithSessionIdentifier(void) { sqInt arrayResult; sqInt reader; FILEHANDLETYPE readerIOStream; FILEHANDLETYPE *readerIOStreamPtr; SQFile *readerPtr; SESSIONIDENTIFIERTYPE thisSession; sqInt writer; FILEHANDLETYPE writerIOStream; FILEHANDLETYPE *writerIOStreamPtr; SQFile *writerPtr; /* Create the anonymous OS pipe */ thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); readerIOStreamPtr = &readerIOStream; writerIOStreamPtr = &writerIOStream; if (!(makePipeForReaderwriter(readerIOStreamPtr, writerIOStreamPtr))) { return interpreterProxy->primitiveFail(); } writer = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); writerPtr = interpreterProxy->arrayValueOf(writer); writerPtr->file = writerIOStream; writerPtr->sessionID = thisSession; writerPtr->writable = 1; writerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(writer); reader = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), fileRecordSize()); readerPtr = interpreterProxy->arrayValueOf(reader); readerPtr->file = readerIOStream; readerPtr->sessionID = thisSession; readerPtr->writable = 0; readerPtr->lastOp = 0; interpreterProxy->pushRemappableOop(reader); arrayResult = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); interpreterProxy->stObjectatput(arrayResult, 1, interpreterProxy->popRemappableOop()); interpreterProxy->stObjectatput(arrayResult, 2, interpreterProxy->popRemappableOop()); interpreterProxy->pop(2); interpreterProxy->push(arrayResult); } /* Answer a string containing the module name string for this plugin. */ EXPORT(sqInt) primitiveModuleName(void) { interpreterProxy->popthenPush(1, stringFromCString(moduleName)); } /* Change the scheduling priority of this process by the given nice increment. A positive increment decreases the priority. Only the superuser can specify a negative value (to increase the priority). See man(2) nice. Different versions of Unix are inconsistent in their return values. The only reliable test for success is to clear errno prior to the call, and test its value if the result of nice() is -1. */ EXPORT(sqInt) primitiveNice(void) { extern int errno; int niceIncrement; sqInt result; niceIncrement = interpreterProxy->stackIntegerValue(0); errno = 0; result = nice(niceIncrement); if (result == -1) { if (!(errno == 0)) { return interpreterProxy->primitiveFail(); } } interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Set an environment variable using a string of the form 'KEY=value'. This implementation allocates a C string using malloc to allocate from the C heap (using cStringFromString rather than transientCStringFromString). This is necessary because the C runtime library does not make a copy of the string into separately allocated environment memory. */ EXPORT(sqInt) primitivePutEnv(void) { char *cStringPtr; sqInt keyValueString; keyValueString = interpreterProxy->stackObjectValue(0); cStringPtr = cStringFromString(keyValueString); if ((putenv(cStringPtr)) == 0) { interpreterProxy->pop(2); interpreterProxy->push(keyValueString); } else { return interpreterProxy->primitiveFail(); } } /* Answer the real path for a path string as determined by realpath(). */ EXPORT(sqInt) primitiveRealpath(void) { char *buffer; sqInt bufferSize; sqInt newPathString; char *pathString; char * realpathResult; sqInt s; bufferSize = 1024; newPathString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), bufferSize); interpreterProxy->pushRemappableOop(newPathString); pathString = transientCStringFromString(interpreterProxy->stackObjectValue(0)); newPathString = interpreterProxy->popRemappableOop(); buffer = interpreterProxy->arrayValueOf(newPathString); realpathResult = realpath(pathString, buffer); if (realpathResult == 0) { return interpreterProxy->primitiveFail(); } else { if ((strlen(realpathResult)) >= 1024) { perror("warning: statically allocated array exceeded in UnixOSProcessPlugin>>primitiveRealPath, object memory may have been corrupted"); return interpreterProxy->primitiveFail(); } s = stringFromCString(realpathResult); interpreterProxy->pop(2); interpreterProxy->push(s); } } /* Clean up after the death of a child, and answer an array with the pid and the exit status of the child process. Answer nil if the pidToHandle does not exist. */ EXPORT(sqInt) primitiveReapChildProcess(void) { sqInt *arrayPtr; int exitStatus; pid_t pidResult; sqInt pidToHandle; sqInt resultArray; /* Force C code translator to declare the variable */ exitStatus = 0; pidToHandle = interpreterProxy->stackIntegerValue(0); pidResult = waitpid ( pidToHandle, &exitStatus, WNOHANG ); if (pidResult <= 0) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->nilObject()); } else { /* Answer an array with pid and result status */ resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2); arrayPtr = interpreterProxy->firstIndexableField(resultArray); arrayPtr[0] = integerObjectOf(pidResult); arrayPtr[1] = integerObjectOf(exitStatus); interpreterProxy->pop(2); interpreterProxy->push(resultArray); } } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. */ EXPORT(sqInt) primitiveSQFileFlush(void) { int result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } result = fflush(fileHandleFrom(sqFileOop)); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and call fflush() to flush the OS stream. This flushes the file stream in the C library, not the stream in Smalltalk. For output streams, consider setting the OS stream (C library) to unbuffered output, and letting Smalltalk do all the buffering. The session identifier is passed as the parameter to this primitive. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileFlushWithSessionIdentifier(void) { int result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } result = fflush(fileHandleFrom(sqFileOop)); interpreterProxy->pop(3); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetBlocking(void) { sqInt descriptor; int flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor == -1) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file for blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetBlockingWithSessionIdentifier(void) { sqInt descriptor; sqInt flags; sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags & ~O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. */ EXPORT(sqInt) primitiveSQFileSetNonBlocking(void) { sqInt descriptor; int flags; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call fcntl() to set the file non-blocking I/O. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetNonBlockingWithSessionIdentifier(void) { sqInt descriptor; sqInt flags; sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { /* begin fileDescriptorFrom: */ if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { descriptor = -1; goto l1; } descriptor = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; if (descriptor < 0) { return interpreterProxy->primitiveFail(); } flags = fcntl(descriptor, F_GETFL); retVal = fcntl(descriptor, F_SETFL, flags | O_NONBLOCK); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. */ EXPORT(sqInt) primitiveSQFileSetUnbuffered(void) { FILEHANDLETYPE file; sqInt retVal; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); retVal = fflush(file); setbuf(file, 0); interpreterProxy->pop(2); interpreterProxy->pushInteger(retVal); } /* Take a struct SQFile from the stack, and call setbuf() to set the OS file stream (implemented in the C library) for unbuffered I/O. Answers the result of a fflush() call, not the result of the setbuf() call (which is type void). This is nearly useless, but may at least provide an indicator that we are operating on a valid file stream. Use this variant if the session identifier is not available directly in the VM (as may be the case if it is not possible to link from this plugin to a variable elsewhere in the VM). */ EXPORT(sqInt) primitiveSQFileSetUnbufferedWithSessionIdentifier(void) { sqInt retVal; SQFile *sqFile; sqInt sqFileOop; SESSIONIDENTIFIERTYPE thisSession; sqFileOop = interpreterProxy->stackValue(1); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } sqFile = interpreterProxy->arrayValueOf(sqFileOop); thisSession = sessionIdentifierFrom(interpreterProxy->stackObjectValue(0)); if (thisSession == (sqFile->sessionID)) { retVal = fflush(sqFile->file); setbuf(sqFile->file, NULL); interpreterProxy->pop(3); interpreterProxy->pushInteger(retVal); } else { return interpreterProxy->primitiveFail(); } } /* Answer the registration index of the semaphore currently associated with the signal handler for sigNum. */ EXPORT(sqInt) primitiveSemaIndexFor(void) { sqInt index; sqInt sigNum; sigNum = interpreterProxy->stackIntegerValue(0); index = semaIndices[sigNum]; interpreterProxy->pop(2); interpreterProxy->pushInteger(index); } /* Send SIGABRT (abort) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigabrtTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigAbrtNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGALRM (alarm clock) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigalrmTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigAlrmNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCHLD (child status has changed, usually death of child) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigchldTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigChldNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGCONT (continue) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigcontTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigContNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGHUP (hangup) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSighupTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigHupNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGINT (interrupt) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigintTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigIntNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGKILL (kill, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigkillTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigKillNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGPIPE (broken pipe) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigpipeTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigPipeNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGQUIT (quit) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigquitTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigQuitNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGSTOP (stop, unblockable) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigstopTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigStopNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGTERM (termination) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigtermTo(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigTermNumber(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR1 (User-defined signal 1) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr1To(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigUsr1Number(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Send SIGUSR2 (User-defined signal 2) to the OS process identified by anIntegerPid. Use an explicit check for isIntegerObject so we can return -1 on error (the stackIntegerValue: method answers 1 on error, and 1 is a valid pid number). */ EXPORT(sqInt) primitiveSendSigusr2To(sqInt anIntegerPid) { pid_t pidToSignal; int result; sqInt sig; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { if (((interpreterProxy->stackValue(0)) & 1)) { pidToSignal = interpreterProxy->stackIntegerValue(0); /* begin sendSignal:toPid: */ sig = sigUsr2Number(); result = kill(pidToSignal, sig); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } else { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } } } /* Set the process group ID of the process identified by pid to a new process group ID. */ EXPORT(sqInt) primitiveSetPGid(void) { pid_t pgid; pid_t pid; pid = interpreterProxy->stackIntegerValue(1); pgid = interpreterProxy->stackIntegerValue(0); if ((setpgid(pid, pgid)) == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(2); } /* Set a new process group for this OS process. Newly created child processes will be members of the new process group. Note: Use setpgid(0,0) rather than the equivalent setpgrp() because setpgrp() is implemented differently on some flavors of Unix. */ EXPORT(sqInt) primitiveSetPGrp(void) { if ((setpgid(0, 0)) == -1) { return interpreterProxy->primitiveFail(); } } /* Set the index of the semaphore used by the OSProcess with which I collaborate. My OSProcess should set this value so that I can use it when handling SIGCHLD signals (death of child). In the C translation this is a static int which would be shared by all instances of UnixOSProcessPlugin, which is expected to be a singleton. Answer the value of the semaphore index. */ EXPORT(sqInt) primitiveSetSemaIndex(void) { sigChldSemaIndex = interpreterProxy->stackIntegerValue(0); interpreterProxy->pop(2); interpreterProxy->pushInteger(sigChldSemaIndex); } /* Quoted from Linux man pages: setsid() creates a new session if the calling process is not a process group leader. The calling process is the leader of the new session, the process group leader of the new process group, and has no controlling tty. The process group ID and session ID of the calling process are set to the PID of the calling process. The calling process will be the only process in this new process group and in this new session. */ EXPORT(sqInt) primitiveSetSid(void) { pid_t sessionId; sessionId = setsid(); if (sessionId == -1) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(1); interpreterProxy->pushInteger(sessionId); } /* Integer value corresponding to SIGCHLD */ EXPORT(sqInt) primitiveSigChldNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigChldNumber()); } /* Integer value corresponding to SIGHUP */ EXPORT(sqInt) primitiveSigHupNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigHupNumber()); } /* Integer value corresponding to SIGINT */ EXPORT(sqInt) primitiveSigIntNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigIntNumber()); } /* Integer value corresponding to SIGKILL */ EXPORT(sqInt) primitiveSigKillNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigKillNumber()); } /* Integer value corresponding to SIGPIPE */ EXPORT(sqInt) primitiveSigPipeNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigPipeNumber()); } /* Integer value corresponding to SIGQUIT */ EXPORT(sqInt) primitiveSigQuitNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigQuitNumber()); } /* Integer value corresponding to SIGTERM */ EXPORT(sqInt) primitiveSigTermNumber(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigTermNumber()); } /* Integer value corresponding to SIGUSR1 */ EXPORT(sqInt) primitiveSigUsr1Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr1Number()); } /* Integer value corresponding to SIGUSR2 */ EXPORT(sqInt) primitiveSigUsr2Number(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sigUsr2Number()); } /* Size in bytes of an integer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfInt(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfInt()); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ EXPORT(sqInt) primitiveSizeOfPointer(void) { interpreterProxy->pop(1); interpreterProxy->pushInteger(sizeOfPointer()); } /* Take a struct SQFile from the stack, and call feof(3) to determine if the file has reached end of file. The flag is set only by a previous read operation, so end of file is not detected until an actual EOF condition has been detected by a read attempt. */ EXPORT(sqInt) primitiveTestEndOfFileFlag(void) { FILEHANDLETYPE file; sqInt result; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } file = fileHandleFrom(sqFileOop); if (file == 0) { return primitiveFail(); } if (feof(file)) { result = interpreterProxy->trueObject(); } else { result = interpreterProxy->falseObject(); } interpreterProxy->pop(2); interpreterProxy->push(result); } /* Take a struct SQFile from the stack, and check for ability to lock the specified region. If the exclusive flag is true, then specify an exclusive (F_WRLCK) lock on the file. Otherwise, specify a shared (F_RDLCK) lock. Any number of Unix processes may hold a read lock (shared lock) on a file region, but only one process may hold a write lock (exclusive lock). If length is zero, then the request is for the entire file to be locked, including region extents that have not yet been allocated for the file. If the fcntl() call fails, answer -1 (the result of the failed call). Otherwise, answer an array with the following six fields: lockable (true or false) l_pid (pid of the process preventing this lock request, or nil) l_type (request type F_WRLCK or F_RDLOCK of the process preventing this lock request) l_whence (the SEEK_SET, SEEK_CUR, or SEEK_END value of the lock preventing this lock request). l_start (offset of the region lock preventing this lock request) l_len (length of the region lock preventing this lock request) */ EXPORT(sqInt) primitiveTestLockableFileRegion(void) { sqInt canObtainLock; sqInt exclusive; int fileNo; sqInt len; struct flock lockStruct; int result; sqInt resultArray; sqInt sqFileOop; sqInt start; exclusive = (interpreterProxy->stackValue(0)) == (interpreterProxy->trueObject()); len = interpreterProxy->stackIntegerValue(1); start = interpreterProxy->stackIntegerValue(2); sqFileOop = interpreterProxy->stackValue(3); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); if (exclusive) { lockStruct.l_type = F_WRLCK; } else { lockStruct.l_type = F_RDLCK; } lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_GETLK, &lockStruct); if (result == -1) { interpreterProxy->pop(5); interpreterProxy->pushInteger(result); } else { if (lockStruct.l_type == F_UNLCK) { canObtainLock = interpreterProxy->trueObject(); } else { canObtainLock = interpreterProxy->falseObject(); } resultArray = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 6); interpreterProxy->stObjectatput(resultArray, 1, canObtainLock); interpreterProxy->stObjectatput(resultArray, 2, (((lockStruct.l_pid) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 3, (((lockStruct.l_type) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 4, (((lockStruct.l_whence) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 5, (((lockStruct.l_start) << 1) | 1)); interpreterProxy->stObjectatput(resultArray, 6, (((lockStruct.l_len) << 1) | 1)); interpreterProxy->popthenPush(5, resultArray); } } /* Close a file handle at the close(2) level, using a handle returned by #primitiveUnixFileNumber. */ EXPORT(sqInt) primitiveUnixFileClose(sqInt anIntegerFileNumber) { int handle; int result; handle = interpreterProxy->stackIntegerValue(0); result = close(handle); interpreterProxy->pop(2); interpreterProxy->pushInteger(result); } /* Take a struct SQFile from the stack, and answer the value of its Unix file number. The Unix file number is not directly useful to Squeak, but may be interesting for debugging problems involving failure to close unused file handles. */ EXPORT(sqInt) primitiveUnixFileNumber(void) { int fileNo; sqInt sqFileOop; sqFileOop = interpreterProxy->stackValue(0); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); interpreterProxy->pop(2); interpreterProxy->pushInteger(fileNo); } /* Take a struct SQFile from the stack, and unlock the specified region. Answer the result of the call to fcntl(). If the region is in the file lock cache, remove it, but otherwise ignore the cache. The cache supports Win32 semantics within a single Squeak image, but not across separate images, therefore the unlock should be attempted regardless of whether this image thinks that the region has previously been locked. Answer the result of the call to fcntl(). */ EXPORT(sqInt) primitiveUnlockFileRegion(void) { int fileNo; sqInt len; struct flock lockStruct; int result; sqInt sqFileOop; sqInt start; len = interpreterProxy->stackIntegerValue(0); start = interpreterProxy->stackIntegerValue(1); sqFileOop = interpreterProxy->stackValue(2); if (!((((interpreterProxy->isBytes(sqFileOop)) && ((interpreterProxy->byteSizeOf(sqFileOop)) == (fileRecordSize()))) && ((interpreterProxy->getThisSessionID()) == (sessionIdentifierFromSqFile(interpreterProxy->arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return interpreterProxy->primitiveFail(); } /* Set up the flock structure parameter for fcntl() */ fileNo = unixFileNumber(fileHandleFrom(sqFileOop)); lockStruct.l_type = F_UNLCK; lockStruct.l_whence = SEEK_SET; lockStruct.l_start = start; lockStruct.l_len = len; lockStruct.l_pid = 0; result = fcntl(fileNo, F_SETLK, &lockStruct); interpreterProxy->pop(4); interpreterProxy->pushInteger(result); } /* Unset an environment variable. */ /* FIXME: unsetenv() is not portable. For Solaris or any other system which does not support unsetenv(), just comment it out in this method and rebuild the plugin. */ EXPORT(sqInt) primitiveUnsetEnv(void) { unsetenv(transientCStringFromString(interpreterProxy->stackObjectValue(0))); interpreterProxy->pop(1); } /* Answer a string containing the version string for this plugin. */ EXPORT(sqInt) primitiveVersionString(void) { interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(versionString())); } /* This is a signal handler for SIGCHLD. It is not meant to be called from Smalltalk, and should only be called indirectly as a result of a death of child signal from the operating system. Child processes must be cleaned up by the parent, otherwise they continue to exist as zombies until the parent exits. This handler resets the signal handler to catch the next SIGCHLD signal, then sets a semaphore to notify the system that a child process needs to be cleaned up. The actual clean up is done by a Smalltalk process which waits on the semaphore, then calls primitiveReapChildProcess. Note: If child processes die faster than we can clean them up, signals will be lost and child processes will remain as zombies. */ static void reapChildProcess(int sigNum) { setSigChldHandler(); if (sigChldSemaIndex > 0) { interpreterProxy->signalSemaphoreWithIndex(sigChldSemaIndex); } } /* Signal sigNum has been caught by a thread other than the pthread in which the interpreter is executing. Rather than handling it in this thread, resend it to the interpreter thread. */ static sqInt resendSignal(int sigNum) { pthread_kill(vmThread, sigNum); } /* Restore signal handlers to their original behaviors. */ static void restoreDefaultSignalHandlers(void) { sqInt sigNum; sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Answer 1 if running in secure mode, else 0. The osprocessSandboxSecurity variable is initialized to -1. On the first call to this method, set its value to either 0 (user has full access to the plugin) or 1 (user is not permitted to do dangerous things). */ static sqInt sandboxSecurity(void) { if (osprocessSandboxSecurity < 0) { osprocessSandboxSecurity = securityHeurisitic(); } return osprocessSandboxSecurity; } /* Answer 0 to permit full access to OSProcess functions, or 1 if access should be restricted for dangerous functions. The rules are: - If the security plugin is not present, grant full access - If the security plugin can be loaded, restrict access unless user has all of secCanWriteImage, secHasFileAccess and secHasSocketAccess */ /* FIXME: This function has not been tested. -dtl */ /* If the security plugin can be loaded, use it to check. If not, assume it's ok */ static sqInt securityHeurisitic(void) { sqInt canWriteImage; sqInt hasFileAccess; sqInt hasSocketAccess; void (*sCWIfn)(void); void (*sHFAfn)(void); void (*sHSAfn)(void); sCWIfn = interpreterProxy->ioLoadFunctionFrom("secCanWriteImage", "SecurityPlugin"); if (sCWIfn == 0) { return 0; } canWriteImage = ((int (*) (void)) sCWIfn)(); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); if (sHFAfn == 0) { return 0; } hasFileAccess = ((int (*) (void)) sHFAfn)(); sHSAfn = interpreterProxy->ioLoadFunctionFrom("secHasSocketAccess", "SecurityPlugin"); if (sHSAfn == 0) { return 0; } hasSocketAccess = ((int (*) (void)) sHSAfn)(); if ((canWriteImage && (hasFileAccess)) && (hasSocketAccess)) { return 0; } else { return 1; } } /* An array of Smalltalk Semaphore indices, one for each signal type for which a handler has been set. If an entry is zero, then no handler is active. */ static unsigned char * semaphoreIndices(void) { return semaIndices; } /* kill(pid, sig) */ static sqInt sendSignaltoPid(sqInt sig, sqInt pid) { return kill(pid, sig); } /* Exit function to be registered with atexit() to signal child processes on VM exit. */ static void sendSignalToPids(void) { sqInt count; pid_t pid; sqInt sig; count = 0; while (count < pidCount) { pid = pidArray[count]; /* begin sendSignal:toPid: */ sig = sigNumToSend; kill(pid, sig); count += 1; } } /* Answer a session ID represented by aByteArray. The session ID is used in the SQFile structure. If that data structure changes, we should see compiler warnings about type mismatch with SESSIONIDENTIFIERTYPE. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFrom(sqInt aByteArray) { sqInt idx; unsigned char *session; union {SESSIONIDENTIFIERTYPE session; unsigned char bytes[sizeof(SESSIONIDENTIFIERTYPE)];} sessionUnion; if (!((interpreterProxy->isBytes(aByteArray)) && ((interpreterProxy->stSizeOf(aByteArray)) == (sizeOfSession())))) { return null; } session = interpreterProxy->arrayValueOf(aByteArray); idx = 0; while (idx < (sizeOfSession())) { sessionUnion.bytes[idx] = session[idx]; idx += 1; } return sessionUnion.session; } /* Answer the session identifier from a SQFile structure. For a valid file reference, this identifier will match the session identifier supplied by the interpreter. */ static SESSIONIDENTIFIERTYPE sessionIdentifierFromSqFile(SQFile *sqFile) { return sqFile->sessionID; } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } static void setSigChldDefaultHandler(void) { setSignalNumberhandler(sigChldNumber(), sigDefaultNumber()); } /* Set the SIGCHLD signal handler in the virtual machine. */ static void setSigChldHandler(void) { if ((signal(SIGCHLD, reapChildProcess)) == (sigErrorNumber())) { perror("signal"); } } static void setSigIntDefaultHandler(void) { setSignalNumberhandler(sigIntNumber(), sigDefaultNumber()); } /* Set the SIGINT signal handler in the virtual machine to ignore interrupts. */ static void setSigIntIgnore(void) { setSignalNumberhandler(sigIntNumber(), sigIgnoreNumber()); } static void setSigPipeDefaultHandler(void) { setSignalNumberhandler(sigPipeNumber(), sigDefaultNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. If a pipe is opened to a child process, and the child exits, then subsequent writes to the pipe generate a SIGPIPE signal. If this signal is not handled, the VM will exit without warning. */ static sqInt setSigPipeHandler(void) { /* begin setSigPipeIgnore */ setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } /* Set the SIGPIPE signal handler in the virtual machine to ignore pipe error signals. */ static void setSigPipeIgnore(void) { setSignalNumberhandler(sigPipeNumber(), sigIgnoreNumber()); } /* Set a signal handler. The C code translator will convert #sig:nal: into 'signal(parm1, parm2)' */ static void * setSignalNumberhandler(sqInt anInteger, void *signalHandlerAddress) { return signal(anInteger, signalHandlerAddress); } EXPORT(sqInt) shutdownModule(void) { sqInt sigNum; /* begin restoreDefaultSignalHandlers */ sigNum = 1; while (sigNum <= (signalArraySize())) { if ((semaIndices[sigNum]) > 0) { setSignalNumberhandler(sigNum, originalSigHandlers[sigNum]); } sigNum += 1; } } /* Abort signal from abort(3) */ static sqInt sigAbrtNumber(void) { return SIGABRT; } /* Timer signal from alarm(2) */ static sqInt sigAlrmNumber(void) { return SIGALRM; } /* Child status has changed (POSIX). */ static sqInt sigChldNumber(void) { return SIGCHLD; } /* Continue if stopped */ static sqInt sigContNumber(void) { return SIGCONT; } /* Default action for a signal */ static void * sigDefaultNumber(void) { return SIG_DFL; } /* Error return from signal() */ static void * sigErrorNumber(void) { return SIG_ERR; } /* Hangup detected on controlling terminal or death of controlling process */ static sqInt sigHupNumber(void) { return SIGHUP; } /* Ignore action for a signal */ static void * sigIgnoreNumber(void) { return SIG_IGN; } /* Interrupt (ANSI). */ static sqInt sigIntNumber(void) { return SIGINT; } /* Kill signal */ static sqInt sigKillNumber(void) { return SIGKILL; } /* Broken pipe (POSIX). */ static sqInt sigPipeNumber(void) { return SIGPIPE; } /* Quit from keyboard */ static sqInt sigQuitNumber(void) { return SIGQUIT; } /* Stop process */ static sqInt sigStopNumber(void) { return SIGSTOP; } /* Termination signal. This is the default signal sent by the unix kill(1) command. */ static sqInt sigTermNumber(void) { return SIGTERM; } /* User defined signal number 1. This is value is platform-dependent, so the inSmalltalk default of 10 may be wrong on some platforms. */ static sqInt sigUsr1Number(void) { return SIGUSR1; } /* User defined signal number 2. This is value is platform-dependent, so the inSmalltalk default of 12 may be wrong on some platforms. */ static sqInt sigUsr2Number(void) { return SIGUSR2; } /* Number of possible signals for this OS plus one. The signal handler arrays declared in #declareCVarsIn: are this size. */ static sqInt signalArraySize(void) { return NSIG; } /* An array of signal handler function addresses, with each entry corresponding to a signal type. */ static void ** signalHandlers(void) { return sigHandlers; } /* Size in bytes of an integer, for this C compiler on this machine. */ static sqInt sizeOfInt(void) { return sizeof(int); } /* Size in bytes of a void pointer, for this C compiler on this machine. */ static sqInt sizeOfPointer(void) { return sizeof(void *); } /* Size of a SESSIONIDENTIFIERTYPE. Should match usage in the SQFile data structure, otherwise we should get compiler warnings. */ static sqInt sizeOfSession(void) { return sizeof(SESSIONIDENTIFIERTYPE); } /* Answer the OS file descriptor, an integer value, from a SQSocket data structure, or answer -1 if unable to obtain the file descriptor (probably due to receiving an incorrect type of object as aFileHandle). Warning: The first element of privateSocketStruct happens to be the Unix file number of the socket. See sqUnixSocket.c for the definition. This method takes advantage of this, and will break if anyone ever redefines the data structure. */ static int socketDescriptorFrom(sqInt sqSocketOop) { void *privateSocketStruct; SQSocket *sqSocket; sqSocket = interpreterProxy->arrayValueOf(sqSocketOop); privateSocketStruct = sqSocket->privateSocketPtr; if (privateSocketStruct == 0) { return -1; } return * (int *) privateSocketStruct; } /* Answer the size of a SQSocket data structure in bytes. */ static sqInt socketRecordSize(void) { return sizeof(SQSocket); } /* Return a pointer to the first byte of of the SQsocket data structure socket record within anSQSocketRecord, which is expected to be a ByteArray of size self>>socketRecordSize. */ static SQSocket * socketValueOf(sqInt anSQSocketRecord) { return interpreterProxy->arrayValueOf(anSQSocketRecord); } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char *aCString) { sqInt len; sqInt newString; len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } /* Answer a new null-terminated C string copied from aString. The string is allocated in object memory, and will be moved without warning by the garbage collector. Any C pointer reference the the result is valid only until the garbage collector next runs. Therefore, this method should only be used within a single primitive in a section of code in which the garbage collector is guaranteed not to run. Note also that this method may itself invoke the garbage collector prior to allocating the new C string. Warning: The result of this method will be invalidated by the next garbage collection, including a GC triggered by creation of a new object within a primitive. Do not call this method twice to obtain two string pointers. */ static char * transientCStringFromString(sqInt aString) { char *cString; sqInt len; sqInt newString; char *stringPtr; /* Allocate space for a null terminated C string. */ len = interpreterProxy->sizeOfSTArrayFromCPrimitive(interpreterProxy->arrayValueOf(aString)); interpreterProxy->pushRemappableOop(aString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len + 1); stringPtr = interpreterProxy->arrayValueOf(interpreterProxy->popRemappableOop()); /* Point to the actual C string. */ cString = interpreterProxy->arrayValueOf(newString); (char *)strncpy(cString, stringPtr, len); cString[len] = 0; return cString; } /* Answer the integer Unix file number corresponding to a file handle (FILE* ). */ static int unixFileNumber(FILEHANDLETYPE fileHandle) { return fileno(fileHandle); } /* Answer a string containing the version string for this plugin. Handle MNU errors, which can occur if class InterpreterPlugin has been removed from the system. Important: When this method is changed, the class side method must also be changed to match. */ /* 4.0 supports 64bit code base */ static char * versionString(void) { static char version[]= "4.3.3"; return version; } #ifdef SQUEAK_BUILTIN_PLUGIN void* UnixOSProcessPlugin_exports[][3] = { {"UnixOSProcessPlugin", "primitiveSQFileSetBlocking", (void*)primitiveSQFileSetBlocking}, {"UnixOSProcessPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"UnixOSProcessPlugin", "primitiveSigTermNumber", (void*)primitiveSigTermNumber}, {"UnixOSProcessPlugin", "primitiveSigQuitNumber", (void*)primitiveSigQuitNumber}, {"UnixOSProcessPlugin", "primitiveSigHupNumber", (void*)primitiveSigHupNumber}, {"UnixOSProcessPlugin", "primitiveSendSigquitTo", (void*)primitiveSendSigquitTo}, {"UnixOSProcessPlugin", "forkSqueak", (void*)forkSqueak}, {"UnixOSProcessPlugin", "primitiveFileStat", (void*)primitiveFileStat}, {"UnixOSProcessPlugin", "primitiveFileProtectionMask", (void*)primitiveFileProtectionMask}, {"UnixOSProcessPlugin", "primitiveSQFileFlush", (void*)primitiveSQFileFlush}, {"UnixOSProcessPlugin", "primitiveForkSqueak", (void*)primitiveForkSqueak}, {"UnixOSProcessPlugin", "primitiveGetPid", (void*)primitiveGetPid}, {"UnixOSProcessPlugin", "shutdownModule", (void*)shutdownModule}, {"UnixOSProcessPlugin", "primitiveVersionString", (void*)primitiveVersionString}, {"UnixOSProcessPlugin", "primitiveGetCurrentWorkingDirectory", (void*)primitiveGetCurrentWorkingDirectory}, {"UnixOSProcessPlugin", "primitiveForkExec", (void*)primitiveForkExec}, {"UnixOSProcessPlugin", "primitiveTestEndOfFileFlag", (void*)primitiveTestEndOfFileFlag}, {"UnixOSProcessPlugin", "primitiveGetPGrp", (void*)primitiveGetPGrp}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandleWithSessionIdentifier", (void*)primitiveGetStdOutHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetStdInHandleWithSessionIdentifier", (void*)primitiveGetStdInHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSigUsr1Number", (void*)primitiveSigUsr1Number}, {"UnixOSProcessPlugin", "primitiveGetGid", (void*)primitiveGetGid}, {"UnixOSProcessPlugin", "primitiveForkSqueakWithoutSigHandler", (void*)primitiveForkSqueakWithoutSigHandler}, {"UnixOSProcessPlugin", "primitiveSendSigabrtTo", (void*)primitiveSendSigabrtTo}, {"UnixOSProcessPlugin", "primitivePutEnv", (void*)primitivePutEnv}, {"UnixOSProcessPlugin", "primitiveGetEGid", (void*)primitiveGetEGid}, {"UnixOSProcessPlugin", "primitiveSigIntNumber", (void*)primitiveSigIntNumber}, {"UnixOSProcessPlugin", "primitiveSigKillNumber", (void*)primitiveSigKillNumber}, {"UnixOSProcessPlugin", "primitiveTestLockableFileRegion", (void*)primitiveTestLockableFileRegion}, {"UnixOSProcessPlugin", "primitiveSetPGid", (void*)primitiveSetPGid}, {"UnixOSProcessPlugin", "primitiveSetSemaIndex", (void*)primitiveSetSemaIndex}, {"UnixOSProcessPlugin", "primitiveLockFileRegion", (void*)primitiveLockFileRegion}, {"UnixOSProcessPlugin", "primitiveSendSigusr1To", (void*)primitiveSendSigusr1To}, {"UnixOSProcessPlugin", "primitiveAioHandle", (void*)primitiveAioHandle}, {"UnixOSProcessPlugin", "primitiveGetThreadID", (void*)primitiveGetThreadID}, {"UnixOSProcessPlugin", "primitiveSendSigalrmTo", (void*)primitiveSendSigalrmTo}, {"UnixOSProcessPlugin", "primitiveMakePipe", (void*)primitiveMakePipe}, {"UnixOSProcessPlugin", "primitiveGetSession", (void*)primitiveGetSession}, {"UnixOSProcessPlugin", "primitiveForkAndExecInDirectory", (void*)primitiveForkAndExecInDirectory}, {"UnixOSProcessPlugin", "primitiveGetUid", (void*)primitiveGetUid}, {"UnixOSProcessPlugin", "primitiveSigPipeNumber", (void*)primitiveSigPipeNumber}, {"UnixOSProcessPlugin", "primitiveSizeOfInt", (void*)primitiveSizeOfInt}, {"UnixOSProcessPlugin", "primitiveChdir", (void*)primitiveChdir}, {"UnixOSProcessPlugin", "primitiveSendSighupTo", (void*)primitiveSendSighupTo}, {"UnixOSProcessPlugin", "primitiveSendSigchldTo", (void*)primitiveSendSigchldTo}, {"UnixOSProcessPlugin", "primitiveForwardSignalToSemaphore", (void*)primitiveForwardSignalToSemaphore}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlocking", (void*)primitiveSQFileSetNonBlocking}, {"UnixOSProcessPlugin", "primitiveSetSid", (void*)primitiveSetSid}, {"UnixOSProcessPlugin", "primitiveRealpath", (void*)primitiveRealpath}, {"UnixOSProcessPlugin", "primitiveSendSigpipeTo", (void*)primitiveSendSigpipeTo}, {"UnixOSProcessPlugin", "primitiveGetStdOutHandle", (void*)primitiveGetStdOutHandle}, {"UnixOSProcessPlugin", "primitiveSendSigintTo", (void*)primitiveSendSigintTo}, {"UnixOSProcessPlugin", "primitiveAioSuspend", (void*)primitiveAioSuspend}, {"UnixOSProcessPlugin", "primitiveSendSigtermTo", (void*)primitiveSendSigtermTo}, {"UnixOSProcessPlugin", "setInterpreter", (void*)setInterpreter}, {"UnixOSProcessPlugin", "primitiveSQFileSetBlockingWithSessionIdentifier", (void*)primitiveSQFileSetBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetPPid", (void*)primitiveGetPPid}, {"UnixOSProcessPlugin", "initialiseModule", (void*)initialiseModule}, {"UnixOSProcessPlugin", "primitiveSigUsr2Number", (void*)primitiveSigUsr2Number}, {"UnixOSProcessPlugin", "primitiveSendSigusr2To", (void*)primitiveSendSigusr2To}, {"UnixOSProcessPlugin", "primitiveSendSigkillTo", (void*)primitiveSendSigkillTo}, {"UnixOSProcessPlugin", "primitiveSemaIndexFor", (void*)primitiveSemaIndexFor}, {"UnixOSProcessPlugin", "primitiveReapChildProcess", (void*)primitiveReapChildProcess}, {"UnixOSProcessPlugin", "primitiveErrorMessageAt", (void*)primitiveErrorMessageAt}, {"UnixOSProcessPlugin", "primitiveArgumentAt", (void*)primitiveArgumentAt}, {"UnixOSProcessPlugin", "primitiveGetPGid", (void*)primitiveGetPGid}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandle", (void*)primitiveGetStdErrHandle}, {"UnixOSProcessPlugin", "primitiveUnixFileClose", (void*)primitiveUnixFileClose}, {"UnixOSProcessPlugin", "primitiveSQFileSetNonBlockingWithSessionIdentifier", (void*)primitiveSQFileSetNonBlockingWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveAioEnable", (void*)primitiveAioEnable}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbuffered", (void*)primitiveSQFileSetUnbuffered}, {"UnixOSProcessPlugin", "primitiveUnixFileNumber", (void*)primitiveUnixFileNumber}, {"UnixOSProcessPlugin", "primitiveGetStdErrHandleWithSessionIdentifier", (void*)primitiveGetStdErrHandleWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveKillOnExit", (void*)primitiveKillOnExit}, {"UnixOSProcessPlugin", "primitiveCanReceiveSignals", (void*)primitiveCanReceiveSignals}, {"UnixOSProcessPlugin", "primitiveMakePipeWithSessionIdentifier", (void*)primitiveMakePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveGetEUid", (void*)primitiveGetEUid}, {"UnixOSProcessPlugin", "primitiveSQFileSetUnbufferedWithSessionIdentifier", (void*)primitiveSQFileSetUnbufferedWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveSizeOfPointer", (void*)primitiveSizeOfPointer}, {"UnixOSProcessPlugin", "primitiveDupTo", (void*)primitiveDupTo}, {"UnixOSProcessPlugin", "primitiveSigChldNumber", (void*)primitiveSigChldNumber}, {"UnixOSProcessPlugin", "primitiveGetStdInHandle", (void*)primitiveGetStdInHandle}, {"UnixOSProcessPlugin", "primitiveCreatePipe", (void*)primitiveCreatePipe}, {"UnixOSProcessPlugin", "primitiveUnlockFileRegion", (void*)primitiveUnlockFileRegion}, {"UnixOSProcessPlugin", "primitiveModuleName", (void*)primitiveModuleName}, {"UnixOSProcessPlugin", "primitiveFixPointersInArrayOfStrings", (void*)primitiveFixPointersInArrayOfStrings}, {"UnixOSProcessPlugin", "primitiveUnsetEnv", (void*)primitiveUnsetEnv}, {"UnixOSProcessPlugin", "primitiveNice", (void*)primitiveNice}, {"UnixOSProcessPlugin", "primitiveSendSigcontTo", (void*)primitiveSendSigcontTo}, {"UnixOSProcessPlugin", "primitiveEnvironmentAt", (void*)primitiveEnvironmentAt}, {"UnixOSProcessPlugin", "primitiveSendSigstopTo", (void*)primitiveSendSigstopTo}, {"UnixOSProcessPlugin", "primitiveEnvironmentAtSymbol", (void*)primitiveEnvironmentAtSymbol}, {"UnixOSProcessPlugin", "primitiveSetPGrp", (void*)primitiveSetPGrp}, {"UnixOSProcessPlugin", "primitiveCreatePipeWithSessionIdentifier", (void*)primitiveCreatePipeWithSessionIdentifier}, {"UnixOSProcessPlugin", "primitiveIsAtEndOfFile", (void*)primitiveIsAtEndOfFile}, {"UnixOSProcessPlugin", "getModuleName", (void*)getModuleName}, {"UnixOSProcessPlugin", "primitiveAioDisable", (void*)primitiveAioDisable}, {"UnixOSProcessPlugin", "primitiveSQFileFlushWithSessionIdentifier", (void*)primitiveSQFileFlushWithSessionIdentifier}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:56:05 pm by VMMaker 4.4.7 */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType /* Do not include the entire sq.h file but just those parts needed. */ /* The virtual machine proxy definition */ #include "sqVirtualMachine.h" /* Configuration options */ #include "sqConfig.h" /* Platform specific definitions */ #include "sqPlatformSpecific.h" #define true 1 #define false 0 #define null 0 /* using 'null' because nil is predefined in Think C */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT // was #undef EXPORT(returnType) but screws NorCroft cc #define EXPORT(returnType) static returnType #endif #include #include "sqMemoryAccess.h" /*** Constants ***/ /*** Function Prototypes ***/ static VirtualMachine * getInterpreter(void); #pragma export on EXPORT(const char*) getModuleName(void); #pragma export off static sqInt halt(void); #pragma export on EXPORT(sqInt) initialiseModule(void); EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off static sqInt msg(char *s); #pragma export on EXPORT(sqInt) primitiveCanConnectToDisplay(void); EXPORT(sqInt) primitiveDisconnectDisplay(void); EXPORT(sqInt) primitiveFlushDisplay(void); EXPORT(sqInt) primitiveGetDisplayName(void); EXPORT(sqInt) primitiveIsConnectedToDisplay(void); EXPORT(sqInt) primitiveKillDisplay(void); EXPORT(sqInt) primitiveModuleName(void); EXPORT(sqInt) primitiveOpenDisplay(void); EXPORT(sqInt) primitiveSetDisplayName(void); EXPORT(sqInt) primitiveVersionString(void); #pragma export off static sqInt sandboxSecurity(void); static sqInt securityHeurisitic(void); #pragma export on EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); EXPORT(sqInt) shutdownModule(void); #pragma export off static sqInt stringFromCString(const char *aCString); static char * transientCStringFromString(sqInt aString); static char * versionString(void); /*** Variables ***/ #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; static const char *moduleName = #ifdef SQUEAK_BUILTIN_PLUGIN "XDisplayControlPlugin 23 January 2011 (i)" #else "XDisplayControlPlugin 23 January 2011 (e)" #endif ; static int osprocessSandboxSecurity; /* Note: This is coded so that plugins can be run from Squeak. */ static VirtualMachine * getInterpreter(void) { return interpreterProxy; } /* Note: This is hardcoded so it can be run from Squeak. The module name is used for validating a module *after* it is loaded to check if it does really contain the module we're thinking it contains. This is important! */ EXPORT(const char*) getModuleName(void) { return moduleName; } static sqInt halt(void) { ; } EXPORT(sqInt) initialiseModule(void) { osprocessSandboxSecurity = -1; return 1; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { } static sqInt msg(char *s) { fprintf(stderr, "\n%s: %s", moduleName, s); } /* Open and close a connection to displayName. It the connection was successfully opened, answer true; otherwise false. This is intended to check for the ability to open an X display prior to actually making the attempt. */ EXPORT(sqInt) primitiveCanConnectToDisplay(void) { Display *d; sqInt name; char * namePtr; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->falseObject()); } else { name = interpreterProxy->stackObjectValue(0); namePtr = transientCStringFromString(name); d = XOpenDisplay(namePtr); if (d == 0) { interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->falseObject()); } else { XCloseDisplay(d); interpreterProxy->pop(2); interpreterProxy->push(interpreterProxy->trueObject()); } } } /* Call an internal function which will disconnect the X display session. The actual Squeak window on the X server is not effected, but this instance of Squeak will not have any further interaction with it. */ EXPORT(sqInt) primitiveDisconnectDisplay(void) { if (!((sandboxSecurity()) == 1)) { forgetXDisplay(); } } /* Call an internal function to synchronize output to the X display. */ EXPORT(sqInt) primitiveFlushDisplay(void) { synchronizeXDisplay(); } /* Answer a string containing the name for the X display, or nil if the display was opened using the $DISPLAY environment variable. This answers the name of the X display as of the time it was last opened, which may be different from the current setting of $DISPLAY. */ EXPORT(sqInt) primitiveGetDisplayName(void) { extern char *displayName; if (displayName == 0) { interpreterProxy->pop(1); interpreterProxy->push(interpreterProxy->nilObject()); } else { interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(displayName)); } } /* Answer true if VM is currently connected to an X server. */ EXPORT(sqInt) primitiveIsConnectedToDisplay(void) { extern int isConnectedToXServer; if (isConnectedToXServer != 0) { interpreterProxy->pop(1); interpreterProxy->push(interpreterProxy->trueObject()); } else { interpreterProxy->pop(1); interpreterProxy->push(interpreterProxy->falseObject()); } } /* Call an internal function to disconnect the X display session and destroy the Squeak window on the X display. */ EXPORT(sqInt) primitiveKillDisplay(void) { if (!((sandboxSecurity()) == 1)) { disconnectXDisplay(); } } /* Answer a string containing the module name string for this plugin. */ EXPORT(sqInt) primitiveModuleName(void) { interpreterProxy->popthenPush(1, stringFromCString(moduleName)); } /* Call an internal function which will open the X display session. */ EXPORT(sqInt) primitiveOpenDisplay(void) { if (!((sandboxSecurity()) == 1)) { openXDisplay(); } } /* Set the name for the X display for use in the next call to primitiveOpenXDisplay. Expects one parameter which must be either a String or nil. */ EXPORT(sqInt) primitiveSetDisplayName(void) { extern char *displayName; sqInt name; static char nameBuffer[501]; char * namePtr; if ((sandboxSecurity()) == 1) { interpreterProxy->pop(2); interpreterProxy->pushInteger(-1); } else { name = interpreterProxy->stackObjectValue(0); if (name == (interpreterProxy->nilObject())) { displayName = 0; } else { namePtr = transientCStringFromString(name); strncpy(nameBuffer, namePtr, 500); nameBuffer[500] = 0; displayName = nameBuffer; } interpreterProxy->pop(1); } } /* Answer a string containing the version string for this plugin. */ EXPORT(sqInt) primitiveVersionString(void) { interpreterProxy->pop(1); interpreterProxy->push(stringFromCString(versionString())); } /* Answer 1 if running in secure mode, else 0. The osprocessSandboxSecurity variable is initialized to -1. On the first call to this method, set its value to either 0 (user has full access to the plugin) or 1 (user is not permitted to do dangerous things). */ static sqInt sandboxSecurity(void) { if (osprocessSandboxSecurity < 0) { osprocessSandboxSecurity = securityHeurisitic(); } return osprocessSandboxSecurity; } /* Answer 0 to permit full access to OSProcess functions, or 1 if access should be restricted for dangerous functions. The rules are: - If the security plugin is not present, grant full access - If the security plugin can be loaded, restrict access unless user has all of secCanWriteImage, secHasFileAccess and secHasSocketAccess */ /* FIXME: This function has not been tested. -dtl */ /* If the security plugin can be loaded, use it to check. If not, assume it's ok */ static sqInt securityHeurisitic(void) { sqInt canWriteImage; sqInt hasFileAccess; sqInt hasSocketAccess; void (*sCWIfn)(void); void (*sHFAfn)(void); void (*sHSAfn)(void); sCWIfn = interpreterProxy->ioLoadFunctionFrom("secCanWriteImage", "SecurityPlugin"); if (sCWIfn == 0) { return 0; } canWriteImage = ((int (*) (void)) sCWIfn)(); sHFAfn = interpreterProxy->ioLoadFunctionFrom("secHasFileAccess", "SecurityPlugin"); if (sHFAfn == 0) { return 0; } hasFileAccess = ((int (*) (void)) sHFAfn)(); sHSAfn = interpreterProxy->ioLoadFunctionFrom("secHasSocketAccess", "SecurityPlugin"); if (sHSAfn == 0) { return 0; } hasSocketAccess = ((int (*) (void)) sHSAfn)(); if ((canWriteImage && (hasFileAccess)) && (hasSocketAccess)) { return 0; } else { return 1; } } /* Note: This is coded so that is can be run from Squeak. */ EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) { sqInt ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(sqInt) shutdownModule(void) { } /* Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector. */ static sqInt stringFromCString(const char *aCString) { sqInt len; sqInt newString; len = strlen(aCString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len); strncpy(interpreterProxy->arrayValueOf(newString), aCString, len); return newString; } /* Answer a new null-terminated C string copied from aString. The string is allocated in object memory, and will be moved without warning by the garbage collector. Any C pointer reference the the result is valid only until the garbage collector next runs. Therefore, this method should only be used within a single primitive in a section of code in which the garbage collector is guaranteed not to run. Note also that this method may itself invoke the garbage collector prior to allocating the new C string. Warning: The result of this method will be invalidated by the next garbage collection, including a GC triggered by creation of a new object within a primitive. Do not call this method twice to obtain two string pointers. */ static char * transientCStringFromString(sqInt aString) { char *cString; sqInt len; sqInt newString; char *stringPtr; /* Allocate space for a null terminated C string. */ len = interpreterProxy->sizeOfSTArrayFromCPrimitive(interpreterProxy->arrayValueOf(aString)); interpreterProxy->pushRemappableOop(aString); newString = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), len + 1); stringPtr = interpreterProxy->arrayValueOf(interpreterProxy->popRemappableOop()); /* Point to the actual C string. */ cString = interpreterProxy->arrayValueOf(newString); (char *)strncpy(cString, stringPtr, len); cString[len] = 0; return cString; } /* Answer a string containing the version string for this plugin. Handle MNU errors, which can occur if class InterpreterPlugin has been removed from the system. Important: When this method is changed, the class side method must also be changed to match. */ /* 2.0 supports 64bit code base */ static char * versionString(void) { static char version[]= "2.1.4"; return version; } #ifdef SQUEAK_BUILTIN_PLUGIN void* XDisplayControlPlugin_exports[][3] = { {"XDisplayControlPlugin", "initialiseModule", (void*)initialiseModule}, {"XDisplayControlPlugin", "getModuleName", (void*)getModuleName}, {"XDisplayControlPlugin", "primitiveFlushDisplay", (void*)primitiveFlushDisplay}, {"XDisplayControlPlugin", "primitiveIsConnectedToDisplay", (void*)primitiveIsConnectedToDisplay}, {"XDisplayControlPlugin", "primitiveKillDisplay", (void*)primitiveKillDisplay}, {"XDisplayControlPlugin", "primitiveDisconnectDisplay", (void*)primitiveDisconnectDisplay}, {"XDisplayControlPlugin", "primitiveVersionString", (void*)primitiveVersionString}, {"XDisplayControlPlugin", "moduleUnloaded", (void*)moduleUnloaded}, {"XDisplayControlPlugin", "primitiveModuleName", (void*)primitiveModuleName}, {"XDisplayControlPlugin", "setInterpreter", (void*)setInterpreter}, {"XDisplayControlPlugin", "shutdownModule", (void*)shutdownModule}, {"XDisplayControlPlugin", "primitiveOpenDisplay", (void*)primitiveOpenDisplay}, {"XDisplayControlPlugin", "primitiveCanConnectToDisplay", (void*)primitiveCanConnectToDisplay}, {"XDisplayControlPlugin", "primitiveGetDisplayName", (void*)primitiveGetDisplayName}, {"XDisplayControlPlugin", "primitiveSetDisplayName", (void*)primitiveSetDisplayName}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */ ================================================ FILE: vm/src/from_squeak/unix/src/plugins.ext ================================================ # Automatically generated makefile include for external plugins EXTERNAL_PLUGINS = B3DAcceleratorPlugin Squeak3D ClipboardExtendedPlugin DBusPlugin SqueakFFIPrims FileCopyPlugin GStreamerPlugin HostWindowPlugin KedamaPlugin KedamaPlugin2 MIDIPlugin Mpeg3Plugin RomePlugin UUIDPlugin AioPlugin UnixOSProcessPlugin XDisplayControlPlugin ================================================ FILE: vm/src/from_squeak/unix/src/plugins.int ================================================ # Automatically generated makefile include for internal plugins INTERNAL_PLUGINS = ADPCMCodecPlugin AsynchFilePlugin BMPReadWriterPlugin B2DPlugin BitBltPlugin CroquetPlugin DSAPrims ZipPlugin DropPlugin FFTPlugin FT2Plugin FilePlugin FloatArrayPlugin FloatMathPlugin GeniePlugin JPEGReadWriter2Plugin JPEGReaderPlugin JoystickTabletPlugin Klatt LargeIntegers LocalePlugin Matrix2x3Plugin MiscPrimitivePlugin RePlugin SecurityPlugin SerialPlugin SlangTestSupportPlugin SocketPlugin SoundCodecPrims SoundGenerationPlugin SoundPlugin StarSqueakPlugin SurfacePlugin ================================================ FILE: vm/src/from_squeak/unix/src/vm/interp.c ================================================ /* Automatically generated from Squeak on 23 January 2011 3:55:17 pm by VMMaker 4.4.7 */ #define SQ_USE_GLOBAL_STRUCT 1 #include "sq.h" #include #ifndef allocateMemoryMinimumImageFileHeaderSize /* Called by Interpreter>>allocateMemory:minimum:imageFile:headerSize: */ /* Default definition if not previously defined in config.h */ #define allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, fileStream, headerSize) \ sqAllocateMemory(minimumMemory, heapSize) #endif #ifndef sqImageFileReadEntireImage /* Called by Interpreter>>sqImage:read:size:length: */ /* Default definition if not previously defined in config.h */ #define sqImageFileReadEntireImage(memoryAddress, elementSize, length, fileStream) \ sqImageFileRead(memoryAddress, elementSize, length, fileStream) #endif #ifndef error /* error() function called from Interpreter */ /* Default definition if not previously defined in config.h */ #define error(str) defaultErrorProc(str) #endif #ifndef ioMicroSecondClock /* Called by Interpreter>>primitiveMicrosecondClock and GC methods */ /* Default definition if not previously defined in config.h */ #define ioMicroSecondClock ioMSecs #endif #ifndef ioUtcWithOffset /* Called by Interpreter>>primitiveUtcWithOffset */ /* Default definition if not previously defined in config.h */ #define ioUtcWithOffset(clock, offset) setMicroSecondsandOffset(clock, offset) #endif #include "sqMemoryAccess.h" sqInt printCallStack(void); void defaultErrorProc(char *s) { /* Print an error message and exit. */ static sqInt printingStack = false; printf("\n%s\n\n", s); if (!printingStack) { /* flag prevents recursive error when trying to print a broken stack */ printingStack = true; printCallStack(); } exit(-1); } /*** Constants ***/ #define ActiveProcessIndex 1 #define AtCacheFixedFields 4 #define AtCacheFmt 3 #define AtCacheMask 28 #define AtCacheOop 1 #define AtCacheSize 2 #define AtCacheTotalSize 64 #define AtPutBase 32 #define BlockArgumentCountIndex 3 #define Byte0Mask 255 #define Byte1Mask 65280 #define Byte1Shift 8 #define Byte1ShiftNegated -8 #define Byte2Mask 16711680 #define Byte3Mask 4278190080U #define Byte3Shift 24 #define Byte3ShiftNegated -24 #define Byte4Mask 1095216660480U #define Byte4Shift 32 #define Byte4ShiftNegated -32 #define Byte5Mask 280375465082880U #define Byte5Shift 40 #define Byte5ShiftNegated -40 #define Byte6Mask 71776119061217280U #define Byte7Mask 18374686479671623680U #define Byte7Shift 56 #define Byte7ShiftNegated -56 #define Bytes3to0Mask 4294967295U #define Bytes7to4Mask 18446744069414584320U #define CacheProbeMax 3 #define CallerIndex 0 #define CharacterTable 24 #define CharacterValueIndex 0 #define ClassAlien 52 #define ClassArray 7 #define ClassBitmap 4 #define ClassBlockClosure 36 #define ClassBlockContext 11 #define ClassByteArray 26 #define ClassCharacter 19 #define ClassExternalAddress 43 #define ClassExternalData 45 #define ClassExternalFunction 46 #define ClassExternalLibrary 47 #define ClassExternalStructure 44 #define ClassFloat 9 #define ClassInteger 5 #define ClassLargeNegativeInteger 42 #define ClassLargePositiveInteger 13 #define ClassMessage 15 #define ClassMethodContext 10 #define ClassPoint 12 #define ClassSemaphore 18 #define ClassString 6 #define ClassUnsafeAlien 54 #define ClassWeakFinalizer 55 #define ClosureFirstCopiedValueIndex 3 #define ClosureIndex 4 #define ClosureNumArgsIndex 2 #define ClosureOuterContextIndex 0 #define ClosureStartPCIndex 1 #define CompactClassMask 126976 #define CompactClasses 28 #define ConstMinusOne -1 #define ConstOne 3 #define ConstTwo 5 #define ConstZero 1 #define ContextFixedSizePlusHeader 7 #define CrossedX 258 #define CtxtTempFrameStart 6 #define DoAssertionChecks 0 #define DoBalanceChecks 0 #define Done 4 #define EndOfRun 257 #define ExcessSignalsIndex 2 #define ExternalObjectsArray 38 #define ExtraRootSize 2048 #define FalseObject 1 #define FirstLinkIndex 0 #define GCTopMarker 3 #define HashBits 536739840 #define HashBitsOffset 17 #define HeaderIndex 0 #define HeaderTypeClass 1 #define HeaderTypeFree 2 #define HeaderTypeGC 2 #define HeaderTypeShort 3 #define HeaderTypeSizeAndClass 0 #define HomeIndex 5 #define InitialIPIndex 4 #define InstanceSpecificationIndex 2 #define InstructionPointerIndex 1 #define InterpreterSourceVersion "4.4.7" #define InvokeCallbackSelector 53 #define LargeContextBit 262144 #define LastLinkIndex 1 #define LiteralStart 1 #define MaxExternalPrimitiveTableSize 4096 #define MaxJumpBuf 32 #define MaxPrimitiveIndex 575 #define MessageArgumentsIndex 1 #define MessageDictionaryIndex 1 #define MessageLookupClassIndex 2 #define MessageSelectorIndex 0 #define MethodArrayIndex 1 #define MethodCacheClass 2 #define MethodCacheEntries 512 #define MethodCacheEntrySize 8 #define MethodCacheMask 4088 #define MethodCacheMethod 3 #define MethodCacheNative 5 #define MethodCachePrim 4 #define MethodCachePrimFunction 6 #define MethodCacheSelector 1 #define MethodCacheSize 4096 #define MethodIndex 3 #define MillisecondClockMask 536870911 #define MyListIndex 3 #define NextLinkIndex 0 #define NilContext 1 #define NilObject 0 #define PrimitiveExternalCallIndex 117 #define PriorityIndex 2 #define ProcessListsIndex 0 #define ProcessSignalingLowSpace 22 #define ReceiverIndex 5 #define RootTableRedZone 2400 #define RootTableSize 2500 #define SchedulerAssociation 3 #define SelectorAboutToReturn 48 #define SelectorCannotInterpret 34 #define SelectorCannotReturn 21 #define SelectorDoesNotUnderstand 20 #define SelectorMustBeBoolean 25 #define SelectorRunWithIn 49 #define SelectorStart 2 #define SemaphoresToSignalSize 500 #define SenderIndex 0 #define SpecialSelectors 23 #define StackPointerIndex 2 #define StartField 1 #define StartObj 2 #define SuperclassIndex 0 #define SuspendedContextIndex 1 #define TempFrameStart 6 #define TheDisplay 14 #define TheFinalizationSemaphore 41 #define TheInterruptSemaphore 30 #define TheLowSpaceSemaphore 17 #define TheTimerSemaphore 29 #define TrueObject 2 #define TypeMask 3 #define Upward 3 #define ValueIndex 1 #define XIndex 0 #define YIndex 1 /*** Function Prototypes ***/ sqInt accessibleObjectAfter(sqInt oop); sqInt activateNewClosureMethod(sqInt blockClosure); sqInt activateNewMethod(void); #pragma export on EXPORT(sqInt) addGCRoot(sqInt *varLoc); #pragma export off sqInt addNewMethodToCache(void); sqInt addToExternalPrimitiveTable(void *functionAddress); sqInt adjustAllOopsBy(sqInt bytesToShift); sqInt allYoungand(sqInt array1, sqInt array2); sqInt allocateChunk(sqInt byteSize); sqInt allocateOrRecycleContext(sqInt needsLarge); sqInt argumentCountOf(sqInt methodPointer); void * arrayValueOf(sqInt arrayOop); sqInt asciiOfCharacter(sqInt characterObj); sqInt balancedStackafterPrimitivewithArgs(sqInt delta, sqInt primIdx, sqInt nArgs); sqInt baseHeaderSize(void); sqInt beRootIfOld(sqInt oop); sqInt beRootWhileForwarding(sqInt oop); sqInt becomewith(sqInt array1, sqInt array2); sqInt becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag); sqInt biasToGrow(void); sqInt booleanValueOf(sqInt obj); sqInt byteSizeOf(sqInt oop); sqInt byteSwapByteObjectsFromto(sqInt startOop, sqInt stopAddr); sqInt byteSwapped(sqInt w); sqInt bytesPerWord(void); sqInt callExternalPrimitive(void *functionID); #pragma export on EXPORT(sqInt) callInterpreter(void); EXPORT(sqInt) callbackEnter(sqInt *callbackID); EXPORT(sqInt) callbackLeave(sqInt cbID); #pragma export off sqInt changeClassOfto(sqInt rcvr, sqInt argClass); sqInt characterForAscii(sqInt ascii); sqInt characterTable(void); sqInt checkForInterrupts(void); sqInt checkImageVersionFromstartingAt(sqImageFile f, squeakFileOffsetType imageOffset); sqInt checkedIntegerValueOf(sqInt intOop); sqInt checkedLongAt(sqInt byteAddress); sqInt classAlien(void); sqInt classArray(void); sqInt classBitmap(void); sqInt classByteArray(void); sqInt classCharacter(void); sqInt classExternalAddress(void); sqInt classExternalData(void); sqInt classExternalFunction(void); sqInt classExternalLibrary(void); sqInt classExternalStructure(void); sqInt classFloat(void); sqInt classLargeNegativeInteger(void); sqInt classLargePositiveInteger(void); sqInt classNameOfIs(sqInt aClass, char *className); sqInt classPoint(void); sqInt classSemaphore(void); sqInt classSmallInteger(void); sqInt classString(void); sqInt classUnsafeAlien(void); sqInt clone(sqInt oop); sqInt commonAt(sqInt stringy); sqInt commonAtPut(sqInt stringy); sqInt commonVariableatcacheIndex(sqInt rcvr, sqInt index, sqInt atIx); sqInt compare31or32Bitsequal(sqInt obj1, sqInt obj2); sqInt compilerCreateActualMessagestoringArgs(sqInt aMessage, sqInt argArray); sqInt compilerFlushCache(sqInt aCompiledMethod); sqInt compilerMapFromto(sqInt memStart, sqInt memEnd); sqInt compilerMark(void); sqInt compilerPostGC(void); sqInt compilerPostSnapshot(void); sqInt compilerPreGC(sqInt fullGCFlag); sqInt compilerPreSnapshot(void); sqInt compilerProcessChange(void); sqInt compilerProcessChangeto(sqInt oldProc, sqInt newProc); sqInt compilerTranslateMethod(void); sqInt containOnlyOopsand(sqInt array1, sqInt array2); sqInt contexthasSender(sqInt thisCntx, sqInt aContext); sqInt copyBits(void); sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt y); sqInt copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(sqInt oop, sqInt segmentWordArray, sqInt lastSeg, sqInt stopAddr, sqInt oopPtr, sqInt hdrPtr); sqInt createActualMessageTo(sqInt aClass); sqInt dispatchFunctionPointer(void *aFunctionPointer); sqInt dispatchFunctionPointerOnin(sqInt primIdx, void *primTable[]); sqInt displayBitsOfLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt displayObject(void); sqInt doPrimitiveDivby(sqInt rcvr, sqInt arg); sqInt doPrimitiveModby(sqInt rcvr, sqInt arg); sqInt dummyReferToProxy(void); #pragma export on EXPORT(sqInt) dumpImage(char *fileName); #pragma export off sqInt executeNewMethodFromCache(void); #pragma export on EXPORT(sqInt) extraHeaderBytes(sqInt oopOrChunk); #pragma export off sqInt failed(void); sqInt falseObject(void); void * fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchClassOf(sqInt oop); sqInt fetchClassOfNonInt(sqInt oop); double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer); sqInt fetchLong32ofObject(sqInt fieldIndex, sqInt oop); sqInt fetchPointerofObject(sqInt fieldIndex, sqInt oop); sqInt fetchStackPointerOf(sqInt aContext); sqInt fetchWordLengthOf(sqInt objectPointer); sqInt finalizeReference(usqInt oop); sqInt findClassOfMethodforReceiver(sqInt meth, sqInt rcvr); sqInt findNewMethodInClass(sqInt class); sqInt findSelectorOfMethodforReceiver(sqInt meth, sqInt rcvr); sqInt firstAccessibleObject(void); char * firstFixedField(sqInt oop); char * firstIndexableField(sqInt oop); sqInt floatObjectOf(double aFloat); double floatValueOf(sqInt oop); sqInt flushExternalPrimitiveOf(sqInt methodPtr); sqInt flushExternalPrimitives(void); sqInt forceInterruptCheck(void); sqInt fullDisplayUpdate(void); sqInt fullGC(void); sqInt fwdTableInit(sqInt blkSize); sqInt fwdTableSize(sqInt blkSize); sqInt getCurrentBytecode(void); sqInt getFullScreenFlag(void); sqInt getInterruptCheckCounter(void); sqInt getInterruptKeycode(void); sqInt getInterruptPending(void); sqInt getLongFromFileswap(sqImageFile aFile, sqInt swapFlag); sqInt getNextWakeupTick(void); sqInt getSavedWindowSize(void); #pragma export on EXPORT(sqInt) getStackPointer(void); #pragma export off sqInt getThisSessionID(void); sqInt growObjectMemory(usqInt delta); sqInt headerOf(sqInt methodPointer); sqInt imageSegmentVersion(void); sqInt incCompBody(void); sqInt incCompMakeFwd(void); sqInt incCompMove(sqInt bytesFreed); sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperclass); sqInt incrementalGC(void); sqInt initCompilerHooks(void); sqInt initializeImageFormatVersionIfNeeded(void); sqInt initializeInterpreter(sqInt bytesToShift); sqInt initializeMemoryFirstFree(usqInt firstFree); sqInt initializeObjectMemory(sqInt bytesToShift); sqInt installinAtCacheatstring(sqInt rcvr, sqInt *cache, sqInt atIx, sqInt stringy); sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size); sqInt instantiateContextsizeInBytes(sqInt classPointer, sqInt sizeInBytes); sqInt instantiateSmallClasssizeInBytes(sqInt classPointer, sqInt sizeInBytes); sqInt integerObjectOf(sqInt value); sqInt integerValueOf(sqInt objectPointer); #pragma export on EXPORT(sqInt) internalIsImmutable(sqInt oop); EXPORT(sqInt) internalIsMutable(sqInt oop); #pragma export off sqInt interpret(void); sqInt ioFilenamefromStringofLengthresolveAliases(char *aCharBuffer, char *aFilenameString, sqInt filenameLength, sqInt aBoolean); sqInt isKindOf(sqInt oop, char *className); sqInt isMemberOf(sqInt oop, char *className); sqInt isArray(sqInt oop); sqInt isBigEnder(void); sqInt isBytes(sqInt oop); sqInt isExcessiveAllocationRequestshift(sqInt size, sqInt bits); sqInt isFloatObject(sqInt oop); sqInt isHandlerMarked(sqInt aContext); sqInt isInMemory(sqInt address); sqInt isIndexable(sqInt oop); sqInt isIntegerObject(sqInt objectPointer); sqInt isIntegerValue(sqInt intValue); sqInt isPointers(sqInt oop); sqInt isWeak(sqInt oop); sqInt isWords(sqInt oop); sqInt isWordsOrBytes(sqInt oop); sqInt isWordsOrBytesNonInt(sqInt oop); sqInt lastPointerOf(sqInt oop); sqInt lengthOf(sqInt oop); sqInt literalofMethod(sqInt offset, sqInt methodPointer); sqInt literalCountOf(sqInt methodPointer); sqInt literalCountOfHeader(sqInt headerPointer); sqInt loadBitBltFrom(sqInt bb); sqInt loadInitialContext(void); sqInt lookupInMethodCacheSelclass(sqInt selector, sqInt class); sqInt lookupMethodInClass(sqInt class); sqInt lookupMethodInDictionary(sqInt dictionary); sqInt lookupMethodNoMNUEtcInClass(sqInt class); sqInt lowestFreeAfter(sqInt chunk); sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue); sqInt mapPointersInObjectsFromto(sqInt memStart, sqInt memEnd); sqInt markAndTrace(sqInt oop); sqInt markAndTraceInterpreterOops(void); sqInt markPhase(void); sqInt methodArgumentCount(void); sqInt methodPrimitiveIndex(void); #pragma export on EXPORT(sqInt) moduleUnloaded(char *aModuleName); #pragma export off sqInt nilObject(void); sqInt nonWeakFieldsOf(sqInt oop); sqInt normalizeFloatOrderingInImage(void); sqInt noteAsRootheaderLoc(sqInt oop, sqInt headerLoc); sqInt nullCompilerHook(void); sqInt objectAfter(sqInt oop); sqInt obsoleteDontUseThisFetchWordofObject(sqInt fieldIndex, sqInt oop); sqInt okayFields(sqInt oop); sqInt okayOop(sqInt signedOop); sqInt oopisGreaterThan(sqInt anOop, sqInt otherOop); sqInt oopisGreaterThanOrEqualTo(sqInt anOop, sqInt otherOop); sqInt oopisLessThan(sqInt anOop, sqInt otherOop); sqInt oopHasAcceptableClass(sqInt signedOop); sqInt oopHasOkayClass(sqInt signedOop); sqInt pop(sqInt nItems); sqInt popthenPush(sqInt nItems, sqInt oop); double popFloat(void); sqInt popRemappableOop(void); sqInt popStack(void); sqInt positive32BitIntegerFor(sqInt integerValue); sqInt positive32BitValueOf(sqInt oop); sqInt positive64BitIntegerFor(sqLong integerValue); sqLong positive64BitValueOf(sqInt oop); sqInt possibleRootStoreIntovalue(sqInt oop, sqInt valueObj); sqInt postGCAction(void); sqInt prepareForwardingTableForBecomingwithtwoWay(sqInt array1, sqInt array2, sqInt twoWayFlag); sqInt primitiveAdd(void); #pragma export on EXPORT(sqInt) primitiveAddLargeIntegers(void); #pragma export off sqInt primitiveAdoptInstance(void); sqInt primitiveArctan(void); sqInt primitiveArrayBecome(void); sqInt primitiveArrayBecomeOneWay(void); sqInt primitiveArrayBecomeOneWayCopyHash(void); sqInt primitiveAsFloat(void); sqInt primitiveAsOop(void); sqInt primitiveAt(void); sqInt primitiveAtPut(void); sqInt primitiveBeCursor(void); sqInt primitiveBeDisplay(void); sqInt primitiveBeep(void); sqInt primitiveBitAnd(void); #pragma export on EXPORT(sqInt) primitiveBitAndLargeIntegers(void); #pragma export off sqInt primitiveBitOr(void); #pragma export on EXPORT(sqInt) primitiveBitOrLargeIntegers(void); #pragma export off sqInt primitiveBitShift(void); #pragma export on EXPORT(sqInt) primitiveBitShiftLargeIntegers(void); #pragma export off sqInt primitiveBitXor(void); #pragma export on EXPORT(sqInt) primitiveBitXorLargeIntegers(void); #pragma export off sqInt primitiveBlockCopy(void); sqInt primitiveBytesLeft(void); sqInt primitiveCalloutToFFI(void); sqInt primitiveChangeClass(void); #pragma export on EXPORT(sqInt) primitiveChangeClassWithClass(void); #pragma export off sqInt primitiveClass(void); sqInt primitiveClipboardText(void); sqInt primitiveClone(void); sqInt primitiveClosureCopyWithCopiedValues(void); sqInt primitiveClosureValue(void); sqInt primitiveClosureValueNoContextSwitch(void); sqInt primitiveClosureValueWithArgs(void); sqInt primitiveConstantFill(void); sqInt primitiveCopyObject(void); sqInt primitiveDeferDisplayUpdates(void); #pragma export on EXPORT(sqInt) primitiveDisablePowerManager(void); #pragma export off sqInt primitiveDiv(void); #pragma export on EXPORT(sqInt) primitiveDivLargeIntegers(void); #pragma export off sqInt primitiveDivide(void); #pragma export on EXPORT(sqInt) primitiveDivideLargeIntegers(void); #pragma export off sqInt primitiveDoPrimitiveWithArgs(void); sqInt primitiveEqual(void); #pragma export on EXPORT(sqInt) primitiveEqualLargeIntegers(void); #pragma export off sqInt primitiveEquivalent(void); sqInt primitiveExecuteMethod(void); sqInt primitiveExecuteMethodArgsArray(void); sqInt primitiveExitToDebugger(void); sqInt primitiveExp(void); sqInt primitiveExponent(void); sqInt primitiveExternalCall(void); sqInt primitiveFail(void); sqInt primitiveFailFor(sqInt reasonCode); sqInt primitiveFindHandlerContext(void); sqInt primitiveFindNextUnwindContext(void); sqInt primitiveFloatAdd(void); sqInt primitiveFloatAddtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatDivide(void); sqInt primitiveFloatDividebyArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatEqual(void); sqInt primitiveFloatEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterthanArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterOrEqual(void); sqInt primitiveFloatGreaterOrEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatGreaterThan(void); sqInt primitiveFloatLessthanArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatLessOrEqual(void); sqInt primitiveFloatLessOrEqualtoArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatLessThan(void); sqInt primitiveFloatMultiply(void); sqInt primitiveFloatMultiplybyArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFloatNotEqual(void); sqInt primitiveFloatSubtract(void); sqInt primitiveFloatSubtractfromArg(sqInt rcvrOop, sqInt argOop); sqInt primitiveFlushCache(void); sqInt primitiveFlushCacheByMethod(void); sqInt primitiveFlushCacheSelective(void); sqInt primitiveFlushExternalPrimitives(void); sqInt primitiveForceDisplayUpdate(void); #pragma export on EXPORT(sqInt) primitiveForceTenure(void); #pragma export off sqInt primitiveFormPrint(void); sqInt primitiveFractionalPart(void); sqInt primitiveFullGC(void); sqInt primitiveGetAttribute(void); sqInt primitiveGetNextEvent(void); sqInt primitiveGreaterOrEqual(void); #pragma export on EXPORT(sqInt) primitiveGreaterOrEqualLargeIntegers(void); #pragma export off sqInt primitiveGreaterThan(void); #pragma export on EXPORT(sqInt) primitiveGreaterThanLargeIntegers(void); EXPORT(sqInt) primitiveImageFormatVersion(void); #pragma export off sqInt primitiveImageName(void); sqInt primitiveIncrementalGC(void); sqInt primitiveIndexOf(sqInt methodPointer); sqInt primitiveInputSemaphore(void); sqInt primitiveInputWord(void); sqInt primitiveInstVarAt(void); sqInt primitiveInstVarAtPut(void); sqInt primitiveInstVarsPutFromStack(void); sqInt primitiveIntegerAt(void); sqInt primitiveIntegerAtPut(void); #pragma export on EXPORT(sqInt) primitiveInterpreterSourceVersion(void); #pragma export off sqInt primitiveInterruptSemaphore(void); sqInt primitiveInvokeObjectAsMethod(void); #pragma export on EXPORT(sqInt) primitiveIsRoot(void); EXPORT(sqInt) primitiveIsYoung(void); #pragma export off sqInt primitiveKbdNext(void); sqInt primitiveKbdPeek(void); sqInt primitiveLessOrEqual(void); #pragma export on EXPORT(sqInt) primitiveLessOrEqualLargeIntegers(void); #pragma export off sqInt primitiveLessThan(void); #pragma export on EXPORT(sqInt) primitiveLessThanLargeIntegers(void); #pragma export off sqInt primitiveListBuiltinModule(void); sqInt primitiveListExternalModule(void); sqInt primitiveLoadImageSegment(void); sqInt primitiveLoadInstVar(void); sqInt primitiveLogN(void); sqInt primitiveLowSpaceSemaphore(void); sqInt primitiveMakePoint(void); sqInt primitiveMarkHandlerMethod(void); sqInt primitiveMarkUnwindMethod(void); sqInt primitiveMethod(void); #pragma export on EXPORT(sqInt) primitiveMicrosecondClock(void); #pragma export off sqInt primitiveMillisecondClock(void); sqInt primitiveMod(void); #pragma export on EXPORT(sqInt) primitiveModLargeIntegers(void); #pragma export off sqInt primitiveMouseButtons(void); sqInt primitiveMousePoint(void); sqInt primitiveMultiply(void); #pragma export on EXPORT(sqInt) primitiveMultiplyLargeIntegers(void); #pragma export off sqInt primitiveNew(void); sqInt primitiveNewMethod(void); sqInt primitiveNewWithArg(void); sqInt primitiveNextInstance(void); sqInt primitiveNextObject(void); sqInt primitiveNoop(void); sqInt primitiveNotEqual(void); #pragma export on EXPORT(sqInt) primitiveNotEqualLargeIntegers(void); #pragma export off sqInt primitiveObjectAt(void); sqInt primitiveObjectAtPut(void); sqInt primitiveObjectPointsTo(void); sqInt primitivePerform(void); sqInt primitivePerformAt(sqInt lookupClass); sqInt primitivePerformInSuperclass(void); sqInt primitivePerformWithArgs(void); #pragma export on EXPORT(sqInt) primitivePlatformSourceVersion(void); #pragma export off sqInt primitivePushFalse(void); sqInt primitivePushMinusOne(void); sqInt primitivePushNil(void); sqInt primitivePushOne(void); sqInt primitivePushSelf(void); sqInt primitivePushTrue(void); sqInt primitivePushTwo(void); sqInt primitivePushZero(void); sqInt primitiveQuit(void); sqInt primitiveQuo(void); #pragma export on EXPORT(sqInt) primitiveQuoLargeIntegers(void); #pragma export off sqInt primitiveRelinquishProcessor(void); sqInt primitiveResponse(void); sqInt primitiveResume(void); #pragma export on EXPORT(sqInt) primitiveRootTable(void); EXPORT(sqInt) primitiveRootTableAt(void); #pragma export off sqInt primitiveScanCharacters(void); #pragma export on EXPORT(sqInt) primitiveScreenDepth(void); #pragma export off sqInt primitiveScreenSize(void); sqInt primitiveSecondsClock(void); sqInt primitiveSetDisplayMode(void); sqInt primitiveSetFullScreen(void); #pragma export on EXPORT(sqInt) primitiveSetGCBiasToGrow(void); EXPORT(sqInt) primitiveSetGCBiasToGrowGCLimit(void); EXPORT(sqInt) primitiveSetGCSemaphore(void); #pragma export off sqInt primitiveSetInterruptKey(void); sqInt primitiveShortAt(void); sqInt primitiveShortAtPut(void); sqInt primitiveShowDisplayRect(void); sqInt primitiveSignal(void); sqInt primitiveSignalAtBytesLeft(void); sqInt primitiveSignalAtMilliseconds(void); sqInt primitiveSine(void); sqInt primitiveSize(void); sqInt primitiveSnapshot(void); sqInt primitiveSnapshotEmbedded(void); sqInt primitiveSomeInstance(void); sqInt primitiveSomeObject(void); sqInt primitiveSpecialObjectsOop(void); sqInt primitiveSquareRoot(void); sqInt primitiveStoreImageSegment(void); sqInt primitiveStoreStackp(void); sqInt primitiveStringAt(void); sqInt primitiveStringAtPut(void); sqInt primitiveStringReplace(void); sqInt primitiveSubtract(void); #pragma export on EXPORT(sqInt) primitiveSubtractLargeIntegers(void); #pragma export off sqInt primitiveSuspend(void); sqInt primitiveTerminateTo(void); sqInt primitiveTestDisplayDepth(void); sqInt primitiveTimesTwoPower(void); sqInt primitiveTruncated(void); sqInt primitiveUnloadModule(void); #pragma export on EXPORT(sqInt) primitiveUtcWithOffset(void); #pragma export off sqInt primitiveVMParameter(void); sqInt primitiveVMPath(void); #pragma export on EXPORT(sqInt) primitiveVMVersion(void); #pragma export off sqInt primitiveValue(void); sqInt primitiveValueUninterruptably(void); sqInt primitiveValueWithArgs(void); sqInt primitiveWait(void); sqInt primitiveYield(void); sqInt print(char *s); #pragma export on EXPORT(sqInt) printAllStacks(void); #pragma export off sqInt printCallStack(void); sqInt printCallStackOf(sqInt aContext); sqInt printNameOfClasscount(sqInt classOop, sqInt cnt); sqInt printNum(sqInt n); sqInt printStringOf(sqInt oop); sqInt printUnbalancedStack(sqInt primIdx); sqInt push(sqInt object); sqInt pushBool(sqInt trueOrFalse); sqInt pushFloat(double f); sqInt pushInteger(sqInt integerValue); sqInt pushRemappableOop(sqInt oop); sqInt putLongtoFile(sqInt aWord, sqImageFile aFile); #pragma export on EXPORT(sqInt) readImageFormatFromFileStartingAt(sqImageFile f, squeakFileOffsetType imageOffset); #pragma export off sqInt readImageFromFileHeapSizeStartingAt(sqImageFile f, usqInt desiredHeapSize, squeakFileOffsetType imageOffset); sqInt readableFormat(sqInt imageVersion); #pragma export on EXPORT(sqInt) reestablishContextPriorToCallback(sqInt callbackContext); #pragma export off sqInt remap(sqInt oop); sqInt removeFirstLinkOfList(sqInt aList); #pragma export on EXPORT(sqInt) removeGCRoot(sqInt *varLoc); #pragma export off sqInt restoreHeaderOf(sqInt oop); sqInt restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut); sqInt resume(sqInt aProcess); sqInt reverseDisplayFromto(sqInt startIndex, sqInt endIndex); sqInt rewriteMethodCacheSelclassprimIndex(sqInt selector, sqInt class, sqInt localPrimIndex); sqInt rewriteMethodCacheSelclassprimIndexprimFunction(sqInt selector, sqInt class, sqInt localPrimIndex, void *localPrimAddress); #pragma export on EXPORT(sqInt) sendInvokeCallbackStackRegistersJmpbuf(sqInt thunkPtr, sqInt stackPtr, sqInt regsPtr, sqInt jmpBufPtr); #pragma export off sqInt setCompilerInitialized(sqInt newFlag); sqInt setFullScreenFlag(sqInt value); sqInt setInterruptCheckCounter(sqInt value); sqInt setInterruptKeycode(sqInt value); sqInt setInterruptPending(sqInt value); sqInt setMicroSecondsandOffset(sqLong *microSeconds, int *utcOffset); sqInt setNextWakeupTick(sqInt value); sqInt setSavedWindowSize(sqInt value); sqInt showDisplayBitsLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); sqInt signalSemaphoreWithIndex(sqInt index); sqInt signed32BitIntegerFor(int integerValue); int signed32BitValueOf(sqInt oop); sqInt signed64BitIntegerFor(sqLong integerValue); sqLong signed64BitValueOf(sqInt oop); sqInt sizeBitsOf(sqInt oop); sqInt sizeOfSTArrayFromCPrimitive(void *cPtr); sqInt slotSizeOf(sqInt oop); sqInt snapshot(sqInt embedded); sqInt splObj(sqInt index); sqInt stObjectat(sqInt array, sqInt index); sqInt stObjectatput(sqInt array, sqInt index, sqInt value); sqInt stSizeOf(sqInt oop); double stackFloatValue(sqInt offset); sqInt stackIntegerValue(sqInt offset); sqInt stackObjectValue(sqInt offset); sqInt stackValue(sqInt offset); sqInt storeIntegerofObjectwithValue(sqInt fieldIndex, sqInt objectPointer, sqInt integerValue); sqInt storePointerofObjectwithValue(sqInt fieldIndex, sqInt oop, sqInt valuePointer); sqInt success(sqInt successValue); sqInt sufficientSpaceAfterGC(usqInt minFree); sqInt sufficientSpaceToAllocate(usqInt bytes); sqInt superclassOf(sqInt classPointer); sqInt sweepPhase(void); sqInt synchronousSignal(sqInt aSemaphore); sqInt transferTo(sqInt aProc); sqInt trueObject(void); sqInt updatePointersInRangeFromto(sqInt memStart, sqInt memEnd); sqInt updatePointersInRootObjectsFromto(sqInt memStart, sqInt memEnd); sqInt validateRoots(void); sqInt verifyCleanHeaders(void); sqInt vmEndianness(void); sqInt wakeHighestPriority(void); sqInt wordSwapped(sqInt w); sqInt writeImageFile(sqInt imageBytes); sqInt writeImageFileIO(sqInt imageBytes); /*** Variables ***/ static struct foo { sqInt successFlag; sqInt specialObjectsOop; sqInt nilObj; sqInt argumentCount; sqInt falseObj; sqInt trueObj; sqInt interruptCheckCounter; sqInt remapBufferCount; sqInt nextPollTick; sqInt primitiveIndex; sqInt messageSelector; sqInt rootTableCount; sqInt compilerInitialized; sqInt allocationCount; sqInt receiver; sqInt lkupClass; sqInt allocationsBetweenGCs; sqInt lowSpaceThreshold; sqInt signalLowSpace; sqInt lastHash; sqInt reclaimableContextCount; sqInt freeContexts; sqInt pendingFinalizationSignals; sqInt freeLargeContexts; sqInt newNativeMethod; sqInt methodClass; sqInt jmpDepth; sqInt statMarkCount; sqInt extraRootCount; sqInt nextWakeupTick; sqInt interruptKeycode; sqInt semaphoresToSignalCountA; sqInt receiverClass; sqInt interruptPending; sqInt semaphoresToSignalCountB; sqInt fullScreenFlag; sqInt statCompMoveCount; sqInt statSweepCount; sqInt statMkFwdCount; sqInt semaphoresUseBufferA; sqInt tenuringThreshold; sqInt gcBiasToGrow; sqInt statRootTableOverflows; sqInt statFullGCs; sqInt gcBiasToGrowGCLimit; sqInt statTenures; sqInt statIncrGCs; sqInt statGrowMemory; sqInt savedWindowSize; sqInt deferDisplayUpdates; sqInt statShrinkMemory; sqInt statpendingFinalizationSignals; sqInt forceTenureFlag; sqInt totalObjectCount; sqInt interruptChecksEveryNms; sqInt gcSemaphoreIndex; sqInt statAllocationCount; sqInt lastTick; sqInt weakRootCount; sqInt jmpMax; sqInt interruptCheckCounterFeedBackReset; sqInt statSpecialMarkCount; sqInt globalSessionID; sqInt statSurvivorCount; sqInt statRootTableCount; sqLong statGCTime; sqLong statIGCDeltaTime; sqLong statIncrGCMSecs; usqInt shrinkThreshold; sqLong statFullGCMSecs; usqInt gcBiasToGrowThreshold; sqInt headerTypeBytes[4]; sqInt remapBuffer[26]; usqInt growHeadroom; sqInt processSignalingLowSpace; sqInt semaphoresToSignalB[501]; sqInt semaphoresToSignalA[501]; sqInt atCache[65]; usqInt method; usqInt theHomeContext; usqInt stackPointer; usqInt instructionPointer; void *primitiveFunctionPointer; usqInt newMethod; void *externalPrimitiveTable[4097]; long methodCache[4097]; usqInt endOfMemory; sqInt weakRoots[2625]; sqInt* extraRoots[2049]; usqInt compStart; usqInt freeBlock; usqInt fwdTableNext; usqInt compEnd; sqInt rootTable[2501]; usqInt memoryLimit; usqInt fwdTableLast; sqInt suspendedCallbacks[33]; jmp_buf jmpBuf[33]; sqInt suspendedMethods[33]; usqInt youngStart; usqInt activeContext; } fum; struct foo * foo = &fum; sqInt extraVMMemory; const char *interpreterVersion = "Squeak4.1 of 17 April 2010 [latest update: #9957]"; sqInt (*compilerHooks[16])(); struct VirtualMachine* interpreterProxy; sqInt imageFormatVersionNumber = 0; void* showSurfaceFn; sqInt imageFormatInitialVersion = 0; usqInt memory; void *primitiveTable[577] = { /* 0*/ (void *)primitiveFail, /* 1*/ (void *)primitiveAdd, /* 2*/ (void *)primitiveSubtract, /* 3*/ (void *)primitiveLessThan, /* 4*/ (void *)primitiveGreaterThan, /* 5*/ (void *)primitiveLessOrEqual, /* 6*/ (void *)primitiveGreaterOrEqual, /* 7*/ (void *)primitiveEqual, /* 8*/ (void *)primitiveNotEqual, /* 9*/ (void *)primitiveMultiply, /* 10*/ (void *)primitiveDivide, /* 11*/ (void *)primitiveMod, /* 12*/ (void *)primitiveDiv, /* 13*/ (void *)primitiveQuo, /* 14*/ (void *)primitiveBitAnd, /* 15*/ (void *)primitiveBitOr, /* 16*/ (void *)primitiveBitXor, /* 17*/ (void *)primitiveBitShift, /* 18*/ (void *)primitiveMakePoint, /* 19*/ (void *)primitiveFail, /* 20*/ (void *)primitiveFail, /* 21*/ (void *)primitiveAddLargeIntegers, /* 22*/ (void *)primitiveSubtractLargeIntegers, /* 23*/ (void *)primitiveLessThanLargeIntegers, /* 24*/ (void *)primitiveGreaterThanLargeIntegers, /* 25*/ (void *)primitiveLessOrEqualLargeIntegers, /* 26*/ (void *)primitiveGreaterOrEqualLargeIntegers, /* 27*/ (void *)primitiveEqualLargeIntegers, /* 28*/ (void *)primitiveNotEqualLargeIntegers, /* 29*/ (void *)primitiveMultiplyLargeIntegers, /* 30*/ (void *)primitiveDivideLargeIntegers, /* 31*/ (void *)primitiveModLargeIntegers, /* 32*/ (void *)primitiveDivLargeIntegers, /* 33*/ (void *)primitiveQuoLargeIntegers, /* 34*/ (void *)primitiveBitAndLargeIntegers, /* 35*/ (void *)primitiveBitOrLargeIntegers, /* 36*/ (void *)primitiveBitXorLargeIntegers, /* 37*/ (void *)primitiveBitShiftLargeIntegers, /* 38*/ (void *)primitiveFail, /* 39*/ (void *)primitiveFail, /* 40*/ (void *)primitiveAsFloat, /* 41*/ (void *)primitiveFloatAdd, /* 42*/ (void *)primitiveFloatSubtract, /* 43*/ (void *)primitiveFloatLessThan, /* 44*/ (void *)primitiveFloatGreaterThan, /* 45*/ (void *)primitiveFloatLessOrEqual, /* 46*/ (void *)primitiveFloatGreaterOrEqual, /* 47*/ (void *)primitiveFloatEqual, /* 48*/ (void *)primitiveFloatNotEqual, /* 49*/ (void *)primitiveFloatMultiply, /* 50*/ (void *)primitiveFloatDivide, /* 51*/ (void *)primitiveTruncated, /* 52*/ (void *)primitiveFractionalPart, /* 53*/ (void *)primitiveExponent, /* 54*/ (void *)primitiveTimesTwoPower, /* 55*/ (void *)primitiveSquareRoot, /* 56*/ (void *)primitiveSine, /* 57*/ (void *)primitiveArctan, /* 58*/ (void *)primitiveLogN, /* 59*/ (void *)primitiveExp, /* 60*/ (void *)primitiveAt, /* 61*/ (void *)primitiveAtPut, /* 62*/ (void *)primitiveSize, /* 63*/ (void *)primitiveStringAt, /* 64*/ (void *)primitiveStringAtPut, /* 65*/ (void *)primitiveFail, /* 66*/ (void *)primitiveFail, /* 67*/ (void *)primitiveFail, /* 68*/ (void *)primitiveObjectAt, /* 69*/ (void *)primitiveObjectAtPut, /* 70*/ (void *)primitiveNew, /* 71*/ (void *)primitiveNewWithArg, /* 72*/ (void *)primitiveArrayBecomeOneWay, /* 73*/ (void *)primitiveInstVarAt, /* 74*/ (void *)primitiveInstVarAtPut, /* 75*/ (void *)primitiveAsOop, /* 76*/ (void *)primitiveStoreStackp, /* 77*/ (void *)primitiveSomeInstance, /* 78*/ (void *)primitiveNextInstance, /* 79*/ (void *)primitiveNewMethod, /* 80*/ (void *)primitiveBlockCopy, /* 81*/ (void *)primitiveValue, /* 82*/ (void *)primitiveValueWithArgs, /* 83*/ (void *)primitivePerform, /* 84*/ (void *)primitivePerformWithArgs, /* 85*/ (void *)primitiveSignal, /* 86*/ (void *)primitiveWait, /* 87*/ (void *)primitiveResume, /* 88*/ (void *)primitiveSuspend, /* 89*/ (void *)primitiveFlushCache, /* 90*/ (void *)primitiveMousePoint, /* 91*/ (void *)primitiveTestDisplayDepth, /* 92*/ (void *)primitiveSetDisplayMode, /* 93*/ (void *)primitiveInputSemaphore, /* 94*/ (void *)primitiveGetNextEvent, /* 95*/ (void *)primitiveInputWord, /* 96*/ (void *)primitiveFail, /* 97*/ (void *)primitiveSnapshot, /* 98*/ (void *)primitiveStoreImageSegment, /* 99*/ (void *)primitiveLoadImageSegment, /* 100*/ (void *)primitivePerformInSuperclass, /* 101*/ (void *)primitiveBeCursor, /* 102*/ (void *)primitiveBeDisplay, /* 103*/ (void *)primitiveScanCharacters, /* 104*/ (void *)primitiveFail, /* 105*/ (void *)primitiveStringReplace, /* 106*/ (void *)primitiveScreenSize, /* 107*/ (void *)primitiveMouseButtons, /* 108*/ (void *)primitiveKbdNext, /* 109*/ (void *)primitiveKbdPeek, /* 110*/ (void *)primitiveEquivalent, /* 111*/ (void *)primitiveClass, /* 112*/ (void *)primitiveBytesLeft, /* 113*/ (void *)primitiveQuit, /* 114*/ (void *)primitiveExitToDebugger, /* 115*/ (void *)primitiveChangeClass, /* 116*/ (void *)primitiveFlushCacheByMethod, /* 117*/ (void *)primitiveExternalCall, /* 118*/ (void *)primitiveDoPrimitiveWithArgs, /* 119*/ (void *)primitiveFlushCacheSelective, /* 120*/ (void *)primitiveCalloutToFFI, /* 121*/ (void *)primitiveImageName, /* 122*/ (void *)primitiveNoop, /* 123*/ (void *)primitiveValueUninterruptably, /* 124*/ (void *)primitiveLowSpaceSemaphore, /* 125*/ (void *)primitiveSignalAtBytesLeft, /* 126*/ (void *)primitiveDeferDisplayUpdates, /* 127*/ (void *)primitiveShowDisplayRect, /* 128*/ (void *)primitiveArrayBecome, /* 129*/ (void *)primitiveSpecialObjectsOop, /* 130*/ (void *)primitiveFullGC, /* 131*/ (void *)primitiveIncrementalGC, /* 132*/ (void *)primitiveObjectPointsTo, /* 133*/ (void *)primitiveSetInterruptKey, /* 134*/ (void *)primitiveInterruptSemaphore, /* 135*/ (void *)primitiveMillisecondClock, /* 136*/ (void *)primitiveSignalAtMilliseconds, /* 137*/ (void *)primitiveSecondsClock, /* 138*/ (void *)primitiveSomeObject, /* 139*/ (void *)primitiveNextObject, /* 140*/ (void *)primitiveBeep, /* 141*/ (void *)primitiveClipboardText, /* 142*/ (void *)primitiveVMPath, /* 143*/ (void *)primitiveShortAt, /* 144*/ (void *)primitiveShortAtPut, /* 145*/ (void *)primitiveConstantFill, /* 146*/ (void *)primitiveFail, /* 147*/ (void *)primitiveFail, /* 148*/ (void *)primitiveClone, /* 149*/ (void *)primitiveGetAttribute, /* 150*/ (void *)primitiveFail, /* 151*/ (void *)primitiveFail, /* 152*/ (void *)primitiveFail, /* 153*/ (void *)primitiveFail, /* 154*/ (void *)primitiveFail, /* 155*/ (void *)primitiveFail, /* 156*/ (void *)primitiveFail, /* 157*/ (void *)primitiveFail, /* 158*/ (void *)primitiveFail, /* 159*/ (void *)primitiveFail, /* 160*/ (void *)primitiveAdoptInstance, /* 161*/ (void *)primitiveFail, /* 162*/ (void *)primitiveFail, /* 163*/ (void *)primitiveFail, /* 164*/ (void *)primitiveFail, /* 165*/ (void *)primitiveIntegerAt, /* 166*/ (void *)primitiveIntegerAtPut, /* 167*/ (void *)primitiveYield, /* 168*/ (void *)primitiveCopyObject, /* 169*/ (void *)primitiveFail, /* 170*/ (void *)primitiveFail, /* 171*/ (void *)primitiveFail, /* 172*/ (void *)primitiveFail, /* 173*/ (void *)primitiveFail, /* 174*/ (void *)primitiveFail, /* 175*/ (void *)primitiveFail, /* 176*/ (void *)primitiveFail, /* 177*/ (void *)primitiveFail, /* 178*/ (void *)primitiveFail, /* 179*/ (void *)primitiveFail, /* 180*/ (void *)primitiveFail, /* 181*/ (void *)primitiveFail, /* 182*/ (void *)primitiveFail, /* 183*/ (void *)primitiveFail, /* 184*/ (void *)primitiveFail, /* 185*/ (void *)primitiveFail, /* 186*/ (void *)primitiveFail, /* 187*/ (void *)primitiveFail, /* 188*/ (void *)primitiveExecuteMethodArgsArray, /* 189*/ (void *)primitiveExecuteMethod, /* 190*/ (void *)primitiveFail, /* 191*/ (void *)primitiveFail, /* 192*/ (void *)primitiveFail, /* 193*/ (void *)primitiveFail, /* 194*/ (void *)primitiveFail, /* 195*/ (void *)primitiveFindNextUnwindContext, /* 196*/ (void *)primitiveTerminateTo, /* 197*/ (void *)primitiveFindHandlerContext, /* 198*/ (void *)primitiveMarkUnwindMethod, /* 199*/ (void *)primitiveMarkHandlerMethod, /* 200*/ (void *)primitiveClosureCopyWithCopiedValues, /* 201*/ (void *)primitiveClosureValue, /* 202*/ (void *)primitiveClosureValue, /* 203*/ (void *)primitiveClosureValue, /* 204*/ (void *)primitiveClosureValue, /* 205*/ (void *)primitiveClosureValue, /* 206*/ (void *)primitiveClosureValueWithArgs, /* 207*/ (void *)primitiveFail, /* 208*/ (void *)primitiveFail, /* 209*/ (void *)primitiveFail, /* 210*/ (void *)primitiveAt, /* 211*/ (void *)primitiveAtPut, /* 212*/ (void *)primitiveSize, /* 213*/ (void *)primitiveFail, /* 214*/ (void *)primitiveFail, /* 215*/ (void *)primitiveFail, /* 216*/ (void *)primitiveFail, /* 217*/ (void *)primitiveFail, /* 218*/ (void *)primitiveFail, /* 219*/ (void *)primitiveFail, /* 220*/ (void *)primitiveFail, /* 221*/ (void *)primitiveClosureValueNoContextSwitch, /* 222*/ (void *)primitiveClosureValueNoContextSwitch, /* 223*/ (void *)primitiveFail, /* 224*/ (void *)primitiveFail, /* 225*/ (void *)primitiveFail, /* 226*/ (void *)primitiveFail, /* 227*/ (void *)primitiveFail, /* 228*/ (void *)primitiveFail, /* 229*/ (void *)primitiveFail, /* 230*/ (void *)primitiveRelinquishProcessor, /* 231*/ (void *)primitiveForceDisplayUpdate, /* 232*/ (void *)primitiveFormPrint, /* 233*/ (void *)primitiveSetFullScreen, /* 234*/ (void *)primitiveFail, /* 235*/ (void *)primitiveFail, /* 236*/ (void *)primitiveFail, /* 237*/ (void *)primitiveFail, /* 238*/ (void *)primitiveFail, /* 239*/ (void *)primitiveFail, /* 240*/ (void *)primitiveFail, /* 241*/ (void *)primitiveFail, /* 242*/ (void *)primitiveFail, /* 243*/ (void *)primitiveFail, /* 244*/ (void *)primitiveFail, /* 245*/ (void *)primitiveFail, /* 246*/ (void *)primitiveFail, /* 247*/ (void *)primitiveSnapshotEmbedded, /* 248*/ (void *)primitiveInvokeObjectAsMethod, /* 249*/ (void *)primitiveArrayBecomeOneWayCopyHash, /* 250*/ (void *)clearProfile, /* 251*/ (void *)dumpProfile, /* 252*/ (void *)startProfiling, /* 253*/ (void *)stopProfiling, /* 254*/ (void *)primitiveVMParameter, /* 255*/ (void *)primitiveInstVarsPutFromStack, /* 256*/ (void *)primitivePushSelf, /* 257*/ (void *)primitivePushTrue, /* 258*/ (void *)primitivePushFalse, /* 259*/ (void *)primitivePushNil, /* 260*/ (void *)primitivePushMinusOne, /* 261*/ (void *)primitivePushZero, /* 262*/ (void *)primitivePushOne, /* 263*/ (void *)primitivePushTwo, /* 264*/ (void *)primitiveLoadInstVar, /* 265*/ (void *)primitiveLoadInstVar, /* 266*/ (void *)primitiveLoadInstVar, /* 267*/ (void *)primitiveLoadInstVar, /* 268*/ (void *)primitiveLoadInstVar, /* 269*/ (void *)primitiveLoadInstVar, /* 270*/ (void *)primitiveLoadInstVar, /* 271*/ (void *)primitiveLoadInstVar, /* 272*/ (void *)primitiveLoadInstVar, /* 273*/ (void *)primitiveLoadInstVar, /* 274*/ (void *)primitiveLoadInstVar, /* 275*/ (void *)primitiveLoadInstVar, /* 276*/ (void *)primitiveLoadInstVar, /* 277*/ (void *)primitiveLoadInstVar, /* 278*/ (void *)primitiveLoadInstVar, /* 279*/ (void *)primitiveLoadInstVar, /* 280*/ (void *)primitiveLoadInstVar, /* 281*/ (void *)primitiveLoadInstVar, /* 282*/ (void *)primitiveLoadInstVar, /* 283*/ (void *)primitiveLoadInstVar, /* 284*/ (void *)primitiveLoadInstVar, /* 285*/ (void *)primitiveLoadInstVar, /* 286*/ (void *)primitiveLoadInstVar, /* 287*/ (void *)primitiveLoadInstVar, /* 288*/ (void *)primitiveLoadInstVar, /* 289*/ (void *)primitiveLoadInstVar, /* 290*/ (void *)primitiveLoadInstVar, /* 291*/ (void *)primitiveLoadInstVar, /* 292*/ (void *)primitiveLoadInstVar, /* 293*/ (void *)primitiveLoadInstVar, /* 294*/ (void *)primitiveLoadInstVar, /* 295*/ (void *)primitiveLoadInstVar, /* 296*/ (void *)primitiveLoadInstVar, /* 297*/ (void *)primitiveLoadInstVar, /* 298*/ (void *)primitiveLoadInstVar, /* 299*/ (void *)primitiveLoadInstVar, /* 300*/ (void *)primitiveLoadInstVar, /* 301*/ (void *)primitiveLoadInstVar, /* 302*/ (void *)primitiveLoadInstVar, /* 303*/ (void *)primitiveLoadInstVar, /* 304*/ (void *)primitiveLoadInstVar, /* 305*/ (void *)primitiveLoadInstVar, /* 306*/ (void *)primitiveLoadInstVar, /* 307*/ (void *)primitiveLoadInstVar, /* 308*/ (void *)primitiveLoadInstVar, /* 309*/ (void *)primitiveLoadInstVar, /* 310*/ (void *)primitiveLoadInstVar, /* 311*/ (void *)primitiveLoadInstVar, /* 312*/ (void *)primitiveLoadInstVar, /* 313*/ (void *)primitiveLoadInstVar, /* 314*/ (void *)primitiveLoadInstVar, /* 315*/ (void *)primitiveLoadInstVar, /* 316*/ (void *)primitiveLoadInstVar, /* 317*/ (void *)primitiveLoadInstVar, /* 318*/ (void *)primitiveLoadInstVar, /* 319*/ (void *)primitiveLoadInstVar, /* 320*/ (void *)primitiveLoadInstVar, /* 321*/ (void *)primitiveLoadInstVar, /* 322*/ (void *)primitiveLoadInstVar, /* 323*/ (void *)primitiveLoadInstVar, /* 324*/ (void *)primitiveLoadInstVar, /* 325*/ (void *)primitiveLoadInstVar, /* 326*/ (void *)primitiveLoadInstVar, /* 327*/ (void *)primitiveLoadInstVar, /* 328*/ (void *)primitiveLoadInstVar, /* 329*/ (void *)primitiveLoadInstVar, /* 330*/ (void *)primitiveLoadInstVar, /* 331*/ (void *)primitiveLoadInstVar, /* 332*/ (void *)primitiveLoadInstVar, /* 333*/ (void *)primitiveLoadInstVar, /* 334*/ (void *)primitiveLoadInstVar, /* 335*/ (void *)primitiveLoadInstVar, /* 336*/ (void *)primitiveLoadInstVar, /* 337*/ (void *)primitiveLoadInstVar, /* 338*/ (void *)primitiveLoadInstVar, /* 339*/ (void *)primitiveLoadInstVar, /* 340*/ (void *)primitiveLoadInstVar, /* 341*/ (void *)primitiveLoadInstVar, /* 342*/ (void *)primitiveLoadInstVar, /* 343*/ (void *)primitiveLoadInstVar, /* 344*/ (void *)primitiveLoadInstVar, /* 345*/ (void *)primitiveLoadInstVar, /* 346*/ (void *)primitiveLoadInstVar, /* 347*/ (void *)primitiveLoadInstVar, /* 348*/ (void *)primitiveLoadInstVar, /* 349*/ (void *)primitiveLoadInstVar, /* 350*/ (void *)primitiveLoadInstVar, /* 351*/ (void *)primitiveLoadInstVar, /* 352*/ (void *)primitiveLoadInstVar, /* 353*/ (void *)primitiveLoadInstVar, /* 354*/ (void *)primitiveLoadInstVar, /* 355*/ (void *)primitiveLoadInstVar, /* 356*/ (void *)primitiveLoadInstVar, /* 357*/ (void *)primitiveLoadInstVar, /* 358*/ (void *)primitiveLoadInstVar, /* 359*/ (void *)primitiveLoadInstVar, /* 360*/ (void *)primitiveLoadInstVar, /* 361*/ (void *)primitiveLoadInstVar, /* 362*/ (void *)primitiveLoadInstVar, /* 363*/ (void *)primitiveLoadInstVar, /* 364*/ (void *)primitiveLoadInstVar, /* 365*/ (void *)primitiveLoadInstVar, /* 366*/ (void *)primitiveLoadInstVar, /* 367*/ (void *)primitiveLoadInstVar, /* 368*/ (void *)primitiveLoadInstVar, /* 369*/ (void *)primitiveLoadInstVar, /* 370*/ (void *)primitiveLoadInstVar, /* 371*/ (void *)primitiveLoadInstVar, /* 372*/ (void *)primitiveLoadInstVar, /* 373*/ (void *)primitiveLoadInstVar, /* 374*/ (void *)primitiveLoadInstVar, /* 375*/ (void *)primitiveLoadInstVar, /* 376*/ (void *)primitiveLoadInstVar, /* 377*/ (void *)primitiveLoadInstVar, /* 378*/ (void *)primitiveLoadInstVar, /* 379*/ (void *)primitiveLoadInstVar, /* 380*/ (void *)primitiveLoadInstVar, /* 381*/ (void *)primitiveLoadInstVar, /* 382*/ (void *)primitiveLoadInstVar, /* 383*/ (void *)primitiveLoadInstVar, /* 384*/ (void *)primitiveLoadInstVar, /* 385*/ (void *)primitiveLoadInstVar, /* 386*/ (void *)primitiveLoadInstVar, /* 387*/ (void *)primitiveLoadInstVar, /* 388*/ (void *)primitiveLoadInstVar, /* 389*/ (void *)primitiveLoadInstVar, /* 390*/ (void *)primitiveLoadInstVar, /* 391*/ (void *)primitiveLoadInstVar, /* 392*/ (void *)primitiveLoadInstVar, /* 393*/ (void *)primitiveLoadInstVar, /* 394*/ (void *)primitiveLoadInstVar, /* 395*/ (void *)primitiveLoadInstVar, /* 396*/ (void *)primitiveLoadInstVar, /* 397*/ (void *)primitiveLoadInstVar, /* 398*/ (void *)primitiveLoadInstVar, /* 399*/ (void *)primitiveLoadInstVar, /* 400*/ (void *)primitiveLoadInstVar, /* 401*/ (void *)primitiveLoadInstVar, /* 402*/ (void *)primitiveLoadInstVar, /* 403*/ (void *)primitiveLoadInstVar, /* 404*/ (void *)primitiveLoadInstVar, /* 405*/ (void *)primitiveLoadInstVar, /* 406*/ (void *)primitiveLoadInstVar, /* 407*/ (void *)primitiveLoadInstVar, /* 408*/ (void *)primitiveLoadInstVar, /* 409*/ (void *)primitiveLoadInstVar, /* 410*/ (void *)primitiveLoadInstVar, /* 411*/ (void *)primitiveLoadInstVar, /* 412*/ (void *)primitiveLoadInstVar, /* 413*/ (void *)primitiveLoadInstVar, /* 414*/ (void *)primitiveLoadInstVar, /* 415*/ (void *)primitiveLoadInstVar, /* 416*/ (void *)primitiveLoadInstVar, /* 417*/ (void *)primitiveLoadInstVar, /* 418*/ (void *)primitiveLoadInstVar, /* 419*/ (void *)primitiveLoadInstVar, /* 420*/ (void *)primitiveLoadInstVar, /* 421*/ (void *)primitiveLoadInstVar, /* 422*/ (void *)primitiveLoadInstVar, /* 423*/ (void *)primitiveLoadInstVar, /* 424*/ (void *)primitiveLoadInstVar, /* 425*/ (void *)primitiveLoadInstVar, /* 426*/ (void *)primitiveLoadInstVar, /* 427*/ (void *)primitiveLoadInstVar, /* 428*/ (void *)primitiveLoadInstVar, /* 429*/ (void *)primitiveLoadInstVar, /* 430*/ (void *)primitiveLoadInstVar, /* 431*/ (void *)primitiveLoadInstVar, /* 432*/ (void *)primitiveLoadInstVar, /* 433*/ (void *)primitiveLoadInstVar, /* 434*/ (void *)primitiveLoadInstVar, /* 435*/ (void *)primitiveLoadInstVar, /* 436*/ (void *)primitiveLoadInstVar, /* 437*/ (void *)primitiveLoadInstVar, /* 438*/ (void *)primitiveLoadInstVar, /* 439*/ (void *)primitiveLoadInstVar, /* 440*/ (void *)primitiveLoadInstVar, /* 441*/ (void *)primitiveLoadInstVar, /* 442*/ (void *)primitiveLoadInstVar, /* 443*/ (void *)primitiveLoadInstVar, /* 444*/ (void *)primitiveLoadInstVar, /* 445*/ (void *)primitiveLoadInstVar, /* 446*/ (void *)primitiveLoadInstVar, /* 447*/ (void *)primitiveLoadInstVar, /* 448*/ (void *)primitiveLoadInstVar, /* 449*/ (void *)primitiveLoadInstVar, /* 450*/ (void *)primitiveLoadInstVar, /* 451*/ (void *)primitiveLoadInstVar, /* 452*/ (void *)primitiveLoadInstVar, /* 453*/ (void *)primitiveLoadInstVar, /* 454*/ (void *)primitiveLoadInstVar, /* 455*/ (void *)primitiveLoadInstVar, /* 456*/ (void *)primitiveLoadInstVar, /* 457*/ (void *)primitiveLoadInstVar, /* 458*/ (void *)primitiveLoadInstVar, /* 459*/ (void *)primitiveLoadInstVar, /* 460*/ (void *)primitiveLoadInstVar, /* 461*/ (void *)primitiveLoadInstVar, /* 462*/ (void *)primitiveLoadInstVar, /* 463*/ (void *)primitiveLoadInstVar, /* 464*/ (void *)primitiveLoadInstVar, /* 465*/ (void *)primitiveLoadInstVar, /* 466*/ (void *)primitiveLoadInstVar, /* 467*/ (void *)primitiveLoadInstVar, /* 468*/ (void *)primitiveLoadInstVar, /* 469*/ (void *)primitiveLoadInstVar, /* 470*/ (void *)primitiveLoadInstVar, /* 471*/ (void *)primitiveLoadInstVar, /* 472*/ (void *)primitiveLoadInstVar, /* 473*/ (void *)primitiveLoadInstVar, /* 474*/ (void *)primitiveLoadInstVar, /* 475*/ (void *)primitiveLoadInstVar, /* 476*/ (void *)primitiveLoadInstVar, /* 477*/ (void *)primitiveLoadInstVar, /* 478*/ (void *)primitiveLoadInstVar, /* 479*/ (void *)primitiveLoadInstVar, /* 480*/ (void *)primitiveLoadInstVar, /* 481*/ (void *)primitiveLoadInstVar, /* 482*/ (void *)primitiveLoadInstVar, /* 483*/ (void *)primitiveLoadInstVar, /* 484*/ (void *)primitiveLoadInstVar, /* 485*/ (void *)primitiveLoadInstVar, /* 486*/ (void *)primitiveLoadInstVar, /* 487*/ (void *)primitiveLoadInstVar, /* 488*/ (void *)primitiveLoadInstVar, /* 489*/ (void *)primitiveLoadInstVar, /* 490*/ (void *)primitiveLoadInstVar, /* 491*/ (void *)primitiveLoadInstVar, /* 492*/ (void *)primitiveLoadInstVar, /* 493*/ (void *)primitiveLoadInstVar, /* 494*/ (void *)primitiveLoadInstVar, /* 495*/ (void *)primitiveLoadInstVar, /* 496*/ (void *)primitiveLoadInstVar, /* 497*/ (void *)primitiveLoadInstVar, /* 498*/ (void *)primitiveLoadInstVar, /* 499*/ (void *)primitiveLoadInstVar, /* 500*/ (void *)primitiveLoadInstVar, /* 501*/ (void *)primitiveLoadInstVar, /* 502*/ (void *)primitiveLoadInstVar, /* 503*/ (void *)primitiveLoadInstVar, /* 504*/ (void *)primitiveLoadInstVar, /* 505*/ (void *)primitiveLoadInstVar, /* 506*/ (void *)primitiveLoadInstVar, /* 507*/ (void *)primitiveLoadInstVar, /* 508*/ (void *)primitiveLoadInstVar, /* 509*/ (void *)primitiveLoadInstVar, /* 510*/ (void *)primitiveLoadInstVar, /* 511*/ (void *)primitiveLoadInstVar, /* 512*/ (void *)primitiveLoadInstVar, /* 513*/ (void *)primitiveLoadInstVar, /* 514*/ (void *)primitiveLoadInstVar, /* 515*/ (void *)primitiveLoadInstVar, /* 516*/ (void *)primitiveLoadInstVar, /* 517*/ (void *)primitiveLoadInstVar, /* 518*/ (void *)primitiveLoadInstVar, /* 519*/ (void *)primitiveLoadInstVar, /* 520*/ (void *)primitiveFail, /* 521*/ (void *)primitiveFail, /* 522*/ (void *)primitiveFail, /* 523*/ (void *)primitiveFail, /* 524*/ (void *)primitiveFail, /* 525*/ (void *)primitiveFail, /* 526*/ (void *)primitiveFail, /* 527*/ (void *)primitiveFail, /* 528*/ (void *)primitiveFail, /* 529*/ (void *)primitiveFail, /* 530*/ (void *)primitiveFail, /* 531*/ (void *)primitiveFail, /* 532*/ (void *)primitiveFail, /* 533*/ (void *)primitiveFail, /* 534*/ (void *)primitiveFail, /* 535*/ (void *)primitiveFail, /* 536*/ (void *)primitiveFail, /* 537*/ (void *)primitiveFail, /* 538*/ (void *)primitiveFail, /* 539*/ (void *)primitiveFail, /* 540*/ (void *)primitiveFail, /* 541*/ (void *)primitiveFail, /* 542*/ (void *)primitiveFail, /* 543*/ (void *)primitiveFail, /* 544*/ (void *)primitiveFail, /* 545*/ (void *)primitiveFail, /* 546*/ (void *)primitiveFail, /* 547*/ (void *)primitiveFail, /* 548*/ (void *)primitiveFail, /* 549*/ (void *)primitiveFail, /* 550*/ (void *)primitiveFail, /* 551*/ (void *)primitiveFail, /* 552*/ (void *)primitiveFail, /* 553*/ (void *)primitiveFail, /* 554*/ (void *)primitiveFail, /* 555*/ (void *)primitiveFail, /* 556*/ (void *)primitiveFail, /* 557*/ (void *)primitiveFail, /* 558*/ (void *)primitiveFail, /* 559*/ (void *)primitiveFail, /* 560*/ (void *)primitiveFail, /* 561*/ (void *)primitiveFail, /* 562*/ (void *)primitiveFail, /* 563*/ (void *)primitiveFail, /* 564*/ (void *)primitiveFail, /* 565*/ (void *)primitiveFail, /* 566*/ (void *)primitiveFail, /* 567*/ (void *)primitiveFail, /* 568*/ (void *)primitiveFail, /* 569*/ (void *)primitiveFail, /* 570*/ (void *)primitiveFlushExternalPrimitives, /* 571*/ (void *)primitiveUnloadModule, /* 572*/ (void *)primitiveListBuiltinModule, /* 573*/ (void *)primitiveListExternalModule, /* 574*/ (void *)primitiveFail, /* 575*/ (void *)primitiveFail, 0 }; /* Return the accessible object following the given object or free chunk in the heap. Return nil when heap is exhausted. */ sqInt accessibleObjectAfter(sqInt oop) { register struct foo * foo = &fum; sqInt obj; sqInt sz; sqInt header; sqInt sz1; sqInt header1; /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } obj = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { return obj; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } return null; } /* Similar to activateNewMethod but for Closure and newMethod. */ sqInt activateNewClosureMethod(sqInt blockClosure) { register struct foo * foo = &fum; sqInt closureMethod; sqInt i; sqInt methodHeader; sqInt newContext; sqInt numCopied; sqInt outerContext; sqInt theBlockClosure; sqInt where; sqInt oop; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; if (DoAssertionChecks) { okayOop(blockClosure); } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (DoAssertionChecks) { okayOop(outerContext); } closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); methodHeader = longAt((closureMethod + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = blockClosure; /* All for one, and one for all! */ /* allocateOrRecycleContext: may cause a GC; restore blockClosure and refetch outerContext et al */ newContext = allocateOrRecycleContext(methodHeader & LargeContextBit); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; theBlockClosure = oop; outerContext = longAt((theBlockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); /* Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores. */ numCopied = (fetchWordLengthOf(theBlockClosure)) - ClosureFirstCopiedValueIndex; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), longAt((theBlockClosure + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)))); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), (((foo->argumentCount + numCopied) << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), theBlockClosure); longAtput(where + (ReceiverIndex << (SHIFT_FOR_WORD)), longAt((outerContext + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD)))); for (i = 1; i <= foo->argumentCount; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAt(foo->stackPointer - ((foo->argumentCount - i) * (BYTES_PER_WORD)))); } where = (newContext + (BASE_HEADER_SIZE)) + (((ReceiverIndex + 1) + foo->argumentCount) << (SHIFT_FOR_WORD)); for (i = 0; i <= (numCopied - 1); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), longAt((theBlockClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)))); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin fetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } sqInt activateNewMethod(void) { register struct foo * foo = &fum; sqInt i; sqInt initialIP; sqInt methodHeader; sqInt newContext; sqInt nilOop; sqInt tempCount; sqInt where; sqInt methodPointer; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; /* begin headerOf: */ methodPointer = foo->newMethod; methodHeader = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); newContext = allocateOrRecycleContext(methodHeader & LargeContextBit); initialIP = ((LiteralStart + ((((usqInt) methodHeader) >> 10) & 255)) * (BYTES_PER_WORD)) + 1; /* Assume: newContext will be recorded as a root if necessary by the call to newActiveContext: below, so we can use unchecked stores. */ tempCount = (((usqInt) methodHeader) >> 19) & 63; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), ((tempCount << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), foo->newMethod); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), foo->nilObj); for (i = 0; i <= foo->argumentCount; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAt(foo->stackPointer - ((foo->argumentCount - i) * (BYTES_PER_WORD)))); } nilOop = foo->nilObj; for (i = ((foo->argumentCount + 1) + ReceiverIndex); i <= (tempCount + ReceiverIndex); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), nilOop); } /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); foo->reclaimableContextCount += 1; /* begin newActiveContext: */ /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin fetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); } /* Add the given variable location to the extra roots table */ EXPORT(sqInt) addGCRoot(sqInt *varLoc) { register struct foo * foo = &fum; if (foo->extraRootCount >= ExtraRootSize) { return 0; } foo->extraRoots[(foo->extraRootCount += 1)] = varLoc; return 1; } /* Add the given entry to the method cache. The policy is as follows: Look for an empty entry anywhere in the reprobe chain. If found, install the new entry there. If not found, then install the new entry at the first probe position and delete the entries in the rest of the reprobe chain. This has two useful purposes: If there is active contention over the first slot, the second or third will likely be free for reentry after ejection. Also, flushing is good when reprobe chains are getting full. */ sqInt addNewMethodToCache(void) { register struct foo * foo = &fum; sqInt hash; sqInt p; sqInt probe; foo->compilerInitialized && (compilerTranslateMethod()); /* drop low-order zeros from addresses */ hash = foo->messageSelector ^ foo->lkupClass; foo->primitiveFunctionPointer = primitiveTable[foo->primitiveIndex]; for (p = 0; p <= (CacheProbeMax - 1); p += 1) { probe = (((usqInt) hash) >> p) & MethodCacheMask; if ((foo->methodCache[probe + MethodCacheSelector]) == 0) { foo->methodCache[probe + MethodCacheSelector] = foo->messageSelector; foo->methodCache[probe + MethodCacheClass] = foo->lkupClass; foo->methodCache[probe + MethodCacheMethod] = foo->newMethod; foo->methodCache[probe + MethodCachePrim] = foo->primitiveIndex; foo->methodCache[probe + MethodCacheNative] = foo->newNativeMethod; foo->methodCache[probe + MethodCachePrimFunction] = (((long) foo->primitiveFunctionPointer)); return null; } } /* first probe */ probe = hash & MethodCacheMask; foo->methodCache[probe + MethodCacheSelector] = foo->messageSelector; foo->methodCache[probe + MethodCacheClass] = foo->lkupClass; foo->methodCache[probe + MethodCacheMethod] = foo->newMethod; foo->methodCache[probe + MethodCachePrim] = foo->primitiveIndex; foo->methodCache[probe + MethodCacheNative] = foo->newNativeMethod; foo->methodCache[probe + MethodCachePrimFunction] = (((long) foo->primitiveFunctionPointer)); for (p = 1; p <= (CacheProbeMax - 1); p += 1) { probe = (((usqInt) hash) >> p) & MethodCacheMask; foo->methodCache[probe + MethodCacheSelector] = 0; } } /* Add the given function address to the external primitive table and return the index where it's stored. This function doesn't need to be fast since it is only called when an external primitive has been looked up (which takes quite a bit of time itself). So there's nothing specifically complicated here. Note: Return index will be one-based (ST convention) */ sqInt addToExternalPrimitiveTable(void *functionAddress) { register struct foo * foo = &fum; sqInt i; for (i = 0; i <= (MaxExternalPrimitiveTableSize - 1); i += 1) { if ((foo->externalPrimitiveTable[i]) == 0) { foo->externalPrimitiveTable[i] = functionAddress; return i + 1; } } return 0; } /* Adjust all oop references by the given number of bytes. This is done just after reading in an image when the new base address of the object heap is different from the base address in the image. */ /* di 11/18/2000 - return number of objects found */ sqInt adjustAllOopsBy(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt oop; sqInt totalObjects; sqInt classHeader; sqInt fieldAddr; sqInt fieldOop; sqInt newClassOop; sqInt sz; sqInt header; if (bytesToShift == 0) { return 300000; } totalObjects = 0; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { totalObjects += 1; /* begin adjustFieldsAndClassOf:by: */ if (bytesToShift == 0) { goto l1; } fieldAddr = oop + (lastPointerOf(oop)); while ((((usqInt) fieldAddr)) > (((usqInt) oop))) { fieldOop = longAt(fieldAddr); if (!((fieldOop & 1))) { longAtput(fieldAddr, fieldOop + bytesToShift); } fieldAddr -= BYTES_PER_WORD; } if (((longAt(oop)) & TypeMask) != HeaderTypeShort) { classHeader = longAt(oop - (BYTES_PER_WORD)); newClassOop = (classHeader & (ALL_BUT_TYPE_MASK)) + bytesToShift; longAtput(oop - (BYTES_PER_WORD), newClassOop | (classHeader & TypeMask)); } l1: /* end adjustFieldsAndClassOf:by: */; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } return totalObjects; } /* Return true if all the oops in both arrays, and the arrays themselves, are in the young object space. */ sqInt allYoungand(sqInt array1, sqInt array2) { register struct foo * foo = &fum; sqInt fieldOffset; sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; if ((((usqInt) array1)) < (((usqInt) foo->youngStart))) { return 0; } if ((((usqInt) array2)) < (((usqInt) foo->youngStart))) { return 0; } /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l4; } else { sz = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { fieldOffset = 0; goto l2; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { if ((((usqInt) (longAt(array1 + fieldOffset)))) < (((usqInt) foo->youngStart))) { return 0; } if ((((usqInt) (longAt(array2 + fieldOffset)))) < (((usqInt) foo->youngStart))) { return 0; } fieldOffset -= BYTES_PER_WORD; } return 1; } /* Allocate a chunk of the given size. Sender must be sure that the requested size includes enough space for the header word(s). */ /* Details: To limit the time per incremental GC, do one every so many allocations. The number is settable via primitiveVMParameter to tune your memory system */ sqInt allocateChunk(sqInt byteSize) { register struct foo * foo = &fum; sqInt enoughSpace; sqInt newChunk; sqInt newFreeSize; usqInt minFree; sqInt currentProc; sqInt lastSavedProcess; sqInt sched; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + byteSize) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { /* signal that space is running low, but proceed with allocation if possible */ foo->signalLowSpace = 1; /* disable additional interrupts until lowSpaceThreshold is reset by image */ foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; lastSavedProcess = longAt((oop2 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, currentProc); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), byteSize + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - byteSize; newChunk = foo->freeBlock; /* Assume: client will initialize object header of free chunk, so following is not needed: */ /* self setSizeOfFree: newChunk to: byteSize. */ foo->freeBlock += byteSize; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; return newChunk; } /* Return a recycled context or a newly allocated one if none is available for recycling. */ sqInt allocateOrRecycleContext(sqInt needsLarge) { register struct foo * foo = &fum; sqInt cntxt; sqInt valuePointer; if (needsLarge == 0) { if (foo->freeContexts != NilContext) { cntxt = foo->freeContexts; foo->freeContexts = longAt((cntxt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); return cntxt; } } else { if (foo->freeLargeContexts != NilContext) { cntxt = foo->freeLargeContexts; foo->freeLargeContexts = longAt((cntxt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); return cntxt; } } if (needsLarge == 0) { cntxt = instantiateContextsizeInBytes(fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop), SMALL_CONTEXT_SIZE); } else { cntxt = instantiateContextsizeInBytes(fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop), LARGE_CONTEXT_SIZE); } /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->nilObj; longAtput((cntxt + (BASE_HEADER_SIZE)) + (4 << (SHIFT_FOR_WORD)), valuePointer); return cntxt; } sqInt argumentCountOf(sqInt methodPointer) { return (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 25) & 15; } /* Return the address of first indexable field of resulting array object, or fail if the instance variable does not contain an indexable bytes or words object. */ /* Note: May be called by translated primitive code. */ void * arrayValueOf(sqInt arrayOop) { if ((!((arrayOop & 1))) && (((arrayOop & 1) == 0) && (isWordsOrBytesNonInt(arrayOop)))) { return pointerForOop(arrayOop + (BASE_HEADER_SIZE)); } /* begin primitiveFail */ foo->successFlag = 0; } /* Returns an integer object */ sqInt asciiOfCharacter(sqInt characterObj) { register struct foo * foo = &fum; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop; /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassCharacter << (SHIFT_FOR_WORD))); if ((characterObj & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(characterObj))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(characterObj - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { return longAt((characterObj + (BASE_HEADER_SIZE)) + (CharacterValueIndex << (SHIFT_FOR_WORD))); } else { return ConstZero; } } /* Return true if the stack is still balanced after executing primitive primIndex with nArgs args. Delta is 'stackPointer - activeContext' which is a relative measure for the stack pointer (so we don't have to relocate it during the primitive) */ sqInt balancedStackafterPrimitivewithArgs(sqInt delta, sqInt primIdx, sqInt nArgs) { register struct foo * foo = &fum; if ((primIdx >= 81) && (primIdx <= 88)) { return 1; } if (foo->successFlag) { return ((foo->stackPointer - foo->activeContext) + (nArgs * (BYTES_PER_WORD))) == delta; } return (foo->stackPointer - foo->activeContext) == delta; } /* Answer the size of an object memory header word in bytes. */ sqInt baseHeaderSize(void) { return BASE_HEADER_SIZE; } /* If this object is old, mark it as a root (because a new object may be stored into it) */ sqInt beRootIfOld(sqInt oop) { register struct foo * foo = &fum; sqInt header; if (((((usqInt) oop)) < (((usqInt) foo->youngStart))) && (!((oop & 1)))) { /* begin noteAsRoot:headerLoc: */ header = longAt(oop); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } /* Record that the given oop in the old object area points to an object in the young area when oop may be forwarded. */ /* Warning: No young objects should be recorded as roots. Callers are responsible for ensuring this constraint is not violated. */ sqInt beRootWhileForwarding(sqInt oop) { register struct foo * foo = &fum; sqInt fwdBlock; sqInt header; sqInt header1; sqInt header2; header = longAt(oop); if ((header & (MARK_BIT)) != 0) { /* This oop is forwarded */ fwdBlock = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } /* begin noteAsRoot:headerLoc: */ header1 = longAt(fwdBlock + (BYTES_PER_WORD)); if ((header1 & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(fwdBlock + (BYTES_PER_WORD), header1 | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(fwdBlock + (BYTES_PER_WORD), header1 | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } else { /* begin noteAsRoot:headerLoc: */ header2 = longAt(oop); if ((header2 & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header2 | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header2 | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } sqInt becomewith(sqInt array1, sqInt array2) { return becomewithtwoWaycopyHash(array1, array2, 1, 1); } /* All references to each object in array1 are swapped with all references to the corresponding object in array2. That is, all pointers to one object are replaced with with pointers to the other. The arguments must be arrays of the same length. Returns true if the primitive succeeds. */ /* Implementation: Uses forwarding blocks to update references as done in compaction. */ sqInt becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag) { register struct foo * foo = &fum; sqInt fieldOffset; sqInt hdr1; sqInt hdr2; sqInt oop1; sqInt oop2; sqInt fwdBlock; sqInt hdr11; sqInt hdr21; sqInt oop11; sqInt oop21; sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; if (!(((array1 & 1) == 0) && (((((usqInt) (longAt(array1))) >> 8) & 15) == 2))) { return 0; } if (!(((array2 & 1) == 0) && (((((usqInt) (longAt(array2))) >> 8) & 15) == 2))) { return 0; } if (!((lastPointerOf(array1)) == (lastPointerOf(array2)))) { return 0; } if (!(containOnlyOopsand(array1, array2))) { return 0; } if (!(prepareForwardingTableForBecomingwithtwoWay(array1, array2, twoWayFlag))) { return 0; } if (allYoungand(array1, array2)) { mapPointersInObjectsFromto(foo->youngStart, foo->endOfMemory); } else { mapPointersInObjectsFromto(memory, foo->endOfMemory); } if (twoWayFlag) { /* begin restoreHeadersAfterBecoming:with: */ /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l4; } else { sz = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { fieldOffset = 0; goto l2; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { oop1 = longAt(array1 + fieldOffset); oop2 = longAt(array2 + fieldOffset); if (!(oop1 == oop2)) { restoreHeaderOf(oop1); restoreHeaderOf(oop2); hdr1 = longAt(oop1); hdr2 = longAt(oop2); longAtput(oop1, (hdr1 & (ALL_BUT_HASH_BITS)) | (hdr2 & HashBits)); longAtput(oop2, (hdr2 & (ALL_BUT_HASH_BITS)) | (hdr1 & HashBits)); } fieldOffset -= BYTES_PER_WORD; } } else { /* begin restoreHeadersAfterForwardBecome: */ fwdBlock = ((foo->endOfMemory + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); fwdBlock += (BYTES_PER_WORD) * 4; while ((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) { oop11 = longAt(fwdBlock + ((BYTES_PER_WORD) * 2)); oop21 = longAt(fwdBlock); restoreHeaderOf(oop11); if (copyHashFlag) { hdr11 = longAt(oop11); hdr21 = longAt(oop21); longAtput(oop21, (hdr21 & (ALL_BUT_HASH_BITS)) | (hdr11 & HashBits)); } fwdBlock += (BYTES_PER_WORD) * 4; } } initializeMemoryFirstFree(foo->freeBlock); /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; return 1; } sqInt biasToGrow(void) { register struct foo * foo = &fum; usqInt growSize; growSize = (((sqInt) (foo->growHeadroom * 3) >> 1)) - ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)); if (growSize > 0) { growObjectMemory(growSize); } } /* convert true and false (Smalltalk) to true or false(C) */ sqInt booleanValueOf(sqInt obj) { register struct foo * foo = &fum; if (obj == foo->trueObj) { return 1; } if (obj == foo->falseObj) { return 0; } foo->successFlag = 0; return null; } sqInt byteSizeOf(sqInt oop) { sqInt slots; sqInt header; sqInt sz; flag("Dan"); if ((oop & 1)) { return 0; } /* begin slotSizeOf: */ if ((oop & 1)) { slots = 0; goto l1; } /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { slots = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { slots = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { slots = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; l1: /* end slotSizeOf: */; if (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8) { return slots; } else { return slots * 4; } } /* Byte-swap the words of all bytes objects in a range of the image, including Strings, ByteArrays, and CompiledMethods. This returns these objects to their original byte ordering after blindly byte-swapping the entire image. For compiled methods, byte-swap only their bytecodes part. */ sqInt byteSwapByteObjectsFromto(sqInt startOop, sqInt stopAddr) { register struct foo * foo = &fum; sqInt fmt; sqInt methodHeader; sqInt oop; sqInt wordAddr; sqInt stopAddr1; sqInt addr; sqInt stopAddr2; sqInt addr1; sqInt sz; sqInt header; oop = startOop; while ((((usqInt) oop)) < (((usqInt) stopAddr))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { fmt = (((usqInt) (longAt(oop))) >> 8) & 15; if (fmt >= 8) { /* oop contains bytes */ wordAddr = oop + (BASE_HEADER_SIZE); if (fmt >= 12) { /* compiled method; start after methodHeader and literals */ methodHeader = longAt(oop + (BASE_HEADER_SIZE)); wordAddr = (wordAddr + (BYTES_PER_WORD)) + (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)); } /* begin reverseBytesFrom:to: */ stopAddr1 = oop + (sizeBitsOf(oop)); flag("Dan"); addr = wordAddr; while ((((usqInt) addr)) < (((usqInt) stopAddr1))) { longAtput(addr, byteSwapped(longAt(addr))); addr += BYTES_PER_WORD; } } if ((fmt == 6) && ((BYTES_PER_WORD) == 8)) { /* Object contains 32-bit half-words packed into 64-bit machine words. */ wordAddr = oop + (BASE_HEADER_SIZE); /* begin reverseWordsFrom:to: */ stopAddr2 = oop + (sizeBitsOf(oop)); addr1 = wordAddr; while ((((usqInt) addr1)) < (((usqInt) stopAddr2))) { longAtput(addr1, wordSwapped(longAt(addr1))); addr1 += BYTES_PER_WORD; } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } } /* Answer the given integer with its bytes in the reverse order. */ sqInt byteSwapped(sqInt w) { # if (BYTES_PER_WORD == 4) // swap bytes in an object word return ((((((usqInt) w >> 24)) & Byte0Mask) + ((((usqInt) w >> 8)) & Byte1Mask)) + ((((usqInt) w << 8)) & Byte2Mask)) + ((((usqInt) w << 24)) & Byte3Mask); # else return ((((((((((usqInt) w >> 56)) & Byte0Mask) + ((((usqInt) w >> 40)) & Byte1Mask)) + ((((usqInt) w >> 24)) & Byte2Mask)) + ((((usqInt) w >> 8)) & Byte3Mask)) + ((((usqInt) w << 8)) & Byte4Mask)) + ((((usqInt) w << 24)) & Byte5Mask)) + ((((usqInt) w << 40)) & Byte6Mask)) + ((((usqInt) w << 56)) & Byte7Mask); # endif // BYTES_PER_WORD == 4 } /* Answer the size of an object memory word in bytes. */ sqInt bytesPerWord(void) { return BYTES_PER_WORD; } /* Call the external plugin function identified. In the VM this is an address, see InterpreterSimulator for it's version. */ sqInt callExternalPrimitive(void *functionID) { dispatchFunctionPointer(functionID); } /* External call into the interpreter */ EXPORT(sqInt) callInterpreter(void) { interpret(); } /* Re-enter the interpreter for executing a callback */ EXPORT(sqInt) callbackEnter(sqInt *callbackID) { register struct foo * foo = &fum; sqInt activeProc; sqInt result; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; sqInt priority; sqInt processList; sqInt processLists; sqInt oop6; sqInt oop11; sqInt lastLink; sqInt oop21; if (foo->primitiveIndex == 0) { return 0; } if (foo->jmpDepth >= foo->jmpMax) { return 0; } /* Suspend the currently active process */ foo->jmpDepth += 1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop2 = longAt((oop4 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->suspendedCallbacks[foo->jmpDepth] = activeProc; foo->suspendedMethods[foo->jmpDepth] = foo->newMethod; transferTo(wakeHighestPriority()); /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; result = setjmp(foo->jmpBuf[foo->jmpDepth]); if (result == 0) { callbackID[0] = foo->jmpDepth; interpret(); } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop1 = longAt((oop3 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); activeProc = longAt((oop1 + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin putToSleep: */ priority = ((longAt((activeProc + (BASE_HEADER_SIZE)) + (PriorityIndex << (SHIFT_FOR_WORD)))) >> 1); /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); oop6 = longAt((oop11 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); processLists = longAt((oop6 + (BASE_HEADER_SIZE)) + (ProcessListsIndex << (SHIFT_FOR_WORD))); processList = longAt((processLists + (BASE_HEADER_SIZE)) + ((priority - 1) << (SHIFT_FOR_WORD))); /* begin addLastLink:toList: */ if ((longAt((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)))) == foo->nilObj) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (FirstLinkIndex << (SHIFT_FOR_WORD)), activeProc); } else { lastLink = longAt((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) lastLink)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(lastLink, activeProc); } longAtput((lastLink + (BASE_HEADER_SIZE)) + (NextLinkIndex << (SHIFT_FOR_WORD)), activeProc); } /* begin storePointer:ofObject:withValue: */ if ((((usqInt) processList)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(processList, activeProc); } longAtput((processList + (BASE_HEADER_SIZE)) + (LastLinkIndex << (SHIFT_FOR_WORD)), activeProc); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) activeProc)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(activeProc, processList); } longAtput((activeProc + (BASE_HEADER_SIZE)) + (MyListIndex << (SHIFT_FOR_WORD)), processList); activeProc = foo->suspendedCallbacks[foo->jmpDepth]; /* see comment above */ foo->newMethod = foo->suspendedMethods[foo->jmpDepth]; transferTo(activeProc); foo->jmpDepth -= 1; return 1; } /* Leave from a previous callback */ /* For now, do not allow a callback unless we're in a primitiveResponse */ EXPORT(sqInt) callbackLeave(sqInt cbID) { register struct foo * foo = &fum; if (foo->primitiveIndex == 0) { return 0; } if (!(cbID == foo->jmpDepth)) { return 0; } if (cbID < 1) { return 0; } longjmp(foo->jmpBuf[foo->jmpDepth], 1); } /* Change the class of the receiver into the class specified by the argument given that the format of the receiver matches the format of the argument. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ /* Check what the format of the class says */ sqInt changeClassOfto(sqInt rcvr, sqInt argClass) { register struct foo * foo = &fum; sqInt argFormat; sqInt byteSize; sqInt ccIndex; sqInt classHdr; sqInt rcvrFormat; sqInt sizeHiBits; sqInt i; sqInt i1; /* Low 2 bits are 0 */ /* Compute the size of instances of the class (used for fixed field classes only) */ classHdr = (longAt((argClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; sizeHiBits = ((usqInt) (classHdr & 393216)) >> 9; classHdr = classHdr & 131071; /* size in bytes -- low 2 bits are 0 */ /* Check the receiver's format against that of the class */ byteSize = (classHdr & (SIZE_MASK)) + sizeHiBits; argFormat = (((usqInt) classHdr) >> 8) & 15; rcvrFormat = (((usqInt) (longAt(rcvr))) >> 8) & 15; if (!(argFormat == rcvrFormat)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (argFormat < 2) { if (!((byteSize - (BASE_HEADER_SIZE)) == (byteSizeOf(rcvr)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } if (((longAt(rcvr)) & TypeMask) == HeaderTypeShort) { /* Compact classes. Check if the arg's class is compact and exchange ccIndex */ ccIndex = classHdr & CompactClassMask; if (ccIndex == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } longAtput(rcvr, ((longAt(rcvr)) & (~CompactClassMask)) | ccIndex); } else { longAtput(rcvr - (BASE_HEADER_SIZE), argClass | ((longAt(rcvr)) & TypeMask)); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, argClass); } } /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } /* begin flushAtCache */ for (i1 = 1; i1 <= AtCacheTotalSize; i1 += 1) { foo->atCache[i1] = 0; } } /* Arg must lie in range 0-255! */ sqInt characterForAscii(sqInt ascii) { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); return longAt((oop + (BASE_HEADER_SIZE)) + (ascii << (SHIFT_FOR_WORD))); } sqInt characterTable(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); } /* Check for possible interrupts and handle one if necessary. */ sqInt checkForInterrupts(void) { register struct foo * foo = &fum; sqInt now; sqInt sema; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt i; sqInt index; sqInt sema1; sqInt xArray; sqInt xSize; sqInt oop4; /* Mask so same wrapping as primitiveMillisecondClock */ now = (ioMSecs()) & MillisecondClockMask; if (!(foo->interruptCheckCounter < -100)) { if ((now - foo->lastTick) < foo->interruptChecksEveryNms) { /* don't play with the feedback if we forced a check. It only makes life difficult */ /* wrapping is not a concern, it'll get caught quickly enough. This clause is trying to keep a reasonable guess of how many times per interruptChecksEveryNms we are calling quickCheckForInterrupts. Not sure how effective it really is. */ foo->interruptCheckCounterFeedBackReset += 10; } else { if (foo->interruptCheckCounterFeedBackReset <= 1000) { foo->interruptCheckCounterFeedBackReset = 1000; } else { foo->interruptCheckCounterFeedBackReset -= 12; } } } foo->interruptCheckCounter = foo->interruptCheckCounterFeedBackReset; if (foo->signalLowSpace) { /* reset flag */ foo->signalLowSpace = 0; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; sema = longAt((oop + (BASE_HEADER_SIZE)) + (TheLowSpaceSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } if (now < foo->lastTick) { /* millisecond clock wrapped so correct the nextPollTick */ foo->nextPollTick = (foo->nextPollTick - MillisecondClockMask) - 1; } if (now >= foo->nextPollTick) { ioProcessEvents(); /* msecs to wait before next call to ioProcessEvents. Note that strictly speaking we might need to update 'now' at this point since ioProcessEvents could take a very long time on some platforms */ foo->nextPollTick = now + 200; } if (foo->interruptPending) { /* reset interrupt flag */ foo->interruptPending = 0; /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; sema = longAt((oop1 + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } if (foo->nextWakeupTick != 0) { if (now < foo->lastTick) { /* the clock has wrapped. Subtract the wrap interval from nextWakeupTick - this might just possibly result in 0. Since this is used as a flag value for 'no timer' we do the 0 check above */ foo->nextWakeupTick = (foo->nextWakeupTick - MillisecondClockMask) - 1; } if (now >= foo->nextWakeupTick) { /* set timer interrupt to 0 for 'no timer' */ foo->nextWakeupTick = 0; /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; sema = longAt((oop2 + (BASE_HEADER_SIZE)) + (TheTimerSemaphore << (SHIFT_FOR_WORD))); if (!(sema == foo->nilObj)) { synchronousSignal(sema); } } } if (foo->pendingFinalizationSignals > 0) { /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; sema = longAt((oop3 + (BASE_HEADER_SIZE)) + (TheFinalizationSemaphore << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema); } foo->pendingFinalizationSignals = 0; } if ((foo->semaphoresToSignalCountA > 0) || (foo->semaphoresToSignalCountB > 0)) { /* begin signalExternalSemaphores */ foo->semaphoresUseBufferA = !foo->semaphoresUseBufferA; /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; xArray = longAt((oop4 + (BASE_HEADER_SIZE)) + (ExternalObjectsArray << (SHIFT_FOR_WORD))); xSize = stSizeOf(xArray); if (foo->semaphoresUseBufferA) { for (i = 1; i <= foo->semaphoresToSignalCountB; i += 1) { index = foo->semaphoresToSignalB[i]; if (index <= xSize) { sema1 = longAt((xArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema1)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema1); } } } foo->semaphoresToSignalCountB = 0; } else { for (i = 1; i <= foo->semaphoresToSignalCountA; i += 1) { index = foo->semaphoresToSignalA[i]; if (index <= xSize) { sema1 = longAt((xArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); if ((fetchClassOf(sema1)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { synchronousSignal(sema1); } } } foo->semaphoresToSignalCountA = 0; } } foo->lastTick = now; } /* Read and verify the image file version number and return true if the the given image file needs to be byte-swapped. As a side effect, position the file stream just after the version number of the image header. This code prints a warning and does a hard-exit if it cannot find a valid version number. */ /* This code is based on C code by Ian Piumarta. */ sqInt checkImageVersionFromstartingAt(sqImageFile f, squeakFileOffsetType imageOffset) { sqInt firstVersion; sqImageFileSeek(f, imageOffset); imageFormatInitialVersion = firstVersion = getLongFromFileswap(f, 0); if (readableFormat(imageFormatInitialVersion)) { return 0; } sqImageFileSeek(f, imageOffset); imageFormatInitialVersion = getLongFromFileswap(f, 1); if (readableFormat(imageFormatInitialVersion)) { return 1; } if (imageOffset == 0) { sqImageFileSeek(f, 512); imageFormatInitialVersion = getLongFromFileswap(f, 0); if (readableFormat(imageFormatInitialVersion)) { return 0; } sqImageFileSeek(f, 512); imageFormatInitialVersion = getLongFromFileswap(f, 1); if (readableFormat(imageFormatInitialVersion)) { return 1; } } print("This interpreter (vers. "); printNum(imageFormatVersionNumber); print(") cannot read image file (vers. "); printNum(firstVersion); print(")."); /* begin cr */ printf("\n"); print("Press CR to quit..."); getchar(); ioExit(); } /* Note: May be called by translated primitive code. */ sqInt checkedIntegerValueOf(sqInt intOop) { if ((intOop & 1)) { return (intOop >> 1); } else { /* begin primitiveFail */ foo->successFlag = 0; return 0; } } /* Assumes zero-based array indexing. For testing in Smalltalk, this method should be overridden in a subclass. */ sqInt checkedLongAt(sqInt byteAddress) { register struct foo * foo = &fum; /* begin checkAddress: */ if ((((usqInt) byteAddress)) < (((usqInt) memory))) { error("bad address: negative"); } if ((((usqInt) byteAddress)) >= (((usqInt) foo->memoryLimit))) { error("bad address: past end of heap"); } /* begin checkAddress: */ if ((((usqInt) (byteAddress + 3))) < (((usqInt) memory))) { error("bad address: negative"); } if ((((usqInt) (byteAddress + 3))) >= (((usqInt) foo->memoryLimit))) { error("bad address: past end of heap"); } return longAt(byteAddress); } sqInt classAlien(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassAlien << (SHIFT_FOR_WORD))); } sqInt classArray(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassArray << (SHIFT_FOR_WORD))); } sqInt classBitmap(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassBitmap << (SHIFT_FOR_WORD))); } sqInt classByteArray(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassByteArray << (SHIFT_FOR_WORD))); } sqInt classCharacter(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassCharacter << (SHIFT_FOR_WORD))); } sqInt classExternalAddress(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalAddress << (SHIFT_FOR_WORD))); } sqInt classExternalData(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalData << (SHIFT_FOR_WORD))); } sqInt classExternalFunction(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalFunction << (SHIFT_FOR_WORD))); } sqInt classExternalLibrary(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalLibrary << (SHIFT_FOR_WORD))); } sqInt classExternalStructure(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassExternalStructure << (SHIFT_FOR_WORD))); } sqInt classFloat(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); } sqInt classLargeNegativeInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD))); } sqInt classLargePositiveInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); } /* Check if aClass's name is className */ sqInt classNameOfIs(sqInt aClass, char *className) { sqInt i; sqInt length; sqInt name; char *srcName; if ((lengthOf(aClass)) <= 6) { return 0; } name = longAt((aClass + (BASE_HEADER_SIZE)) + (6 << (SHIFT_FOR_WORD))); if (!(((name & 1) == 0) && (((((usqInt) (longAt(name))) >> 8) & 15) >= 8))) { return 0; } length = stSizeOf(name); srcName = ((char *) (arrayValueOf(name))); for (i = 0; i <= (length - 1); i += 1) { if (!((srcName[i]) == (className[i]))) { return 0; } } return (className[length]) == 0; } sqInt classPoint(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); } sqInt classSemaphore(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassSemaphore << (SHIFT_FOR_WORD))); } sqInt classSmallInteger(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } sqInt classString(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassString << (SHIFT_FOR_WORD))); } sqInt classUnsafeAlien(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (ClassUnsafeAlien << (SHIFT_FOR_WORD))); } /* Return a shallow copy of the given object. May cause GC */ /* Assume: Oop is a real object, not a small integer. */ sqInt clone(sqInt oop) { register struct foo * foo = &fum; usqInt bytes; sqInt extraHdrBytes; usqInt fromIndex; sqInt hash; sqInt header; usqInt lastFrom; sqInt newChunk; sqInt newOop; sqInt remappedOop; sqInt toIndex; sqInt header1; sqInt enoughSpace; sqInt newChunk1; sqInt newFreeSize; usqInt minFree; sqInt oop1; sqInt currentProc; sqInt lastSavedProcess; sqInt sched; sqInt oop4; sqInt oop11; sqInt oop2; sqInt oop3; extraHdrBytes = foo->headerTypeBytes[(longAt(oop)) & TypeMask]; /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { bytes = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { bytes = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; /* allocate space for the copy, remapping oop in case of a GC */ bytes += extraHdrBytes; /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = oop; if (!(sufficientSpaceToAllocate(2500 + bytes))) { return 0; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + bytes) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l2; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l2; } l2: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; lastSavedProcess = longAt((oop2 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop4 = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop11 = foo->specialObjectsOop; if ((((usqInt) oop11)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop11, currentProc); } longAtput((oop11 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), bytes + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - bytes; newChunk1 = foo->freeBlock; foo->freeBlock += bytes; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newChunk = newChunk1; /* begin popRemappableOop */ oop1 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedOop = oop1; /* loop below uses pre-increment */ toIndex = newChunk - (BYTES_PER_WORD); fromIndex = (remappedOop - extraHdrBytes) - (BYTES_PER_WORD); lastFrom = fromIndex + bytes; while (fromIndex < lastFrom) { longAtput(toIndex += BYTES_PER_WORD, longAt(fromIndex += BYTES_PER_WORD)); } /* convert from chunk to oop */ /* fix base header: compute new hash and clear Mark and Root bits */ newOop = newChunk + extraHdrBytes; /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; /* use old ccIndex, format, size, and header-type fields */ header = (longAt(newOop)) & 131071; header = header | ((hash << 17) & 536739840); longAtput(newOop, header); return newOop; } /* This code is called if the receiver responds primitively to at:. If this is so, it will be installed in the atCache so that subsequent calls of at: or next may be handled immediately in bytecode primitive routines. */ sqInt commonAt(sqInt stringy) { register struct foo * foo = &fum; sqInt atIx; sqInt index; sqInt rcvr; sqInt result; sqInt sp; sqInt oop; sqInt sp1; sqInt oop1; /* Sets successFlag */ index = positive32BitValueOf(longAt(foo->stackPointer)); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (!(foo->successFlag && (!((rcvr & 1))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((foo->messageSelector == (fetchPointerofObject(16 * 2, fetchPointerofObject(SpecialSelectors, foo->specialObjectsOop)))) && (foo->lkupClass == (fetchClassOfNonInt(rcvr)))) { /* OK -- look in the at-cache */ /* Index into atCache = 4N, for N = 0 ... 7 */ atIx = rcvr & AtCacheMask; if (!((foo->atCache[atIx + AtCacheOop]) == rcvr)) { installinAtCacheatstring(rcvr, foo->atCache, atIx, stringy); } if (foo->successFlag) { result = commonVariableatcacheIndex(rcvr, index, atIx); } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp; return null; } } foo->successFlag = 1; result = stObjectat(rcvr, index); if (foo->successFlag) { if (stringy) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); result = longAt((oop + (BASE_HEADER_SIZE)) + (((result >> 1)) << (SHIFT_FOR_WORD))); } /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), result); foo->stackPointer = sp1; return null; } } /* This code is called if the receiver responds primitively to at:Put:. If this is so, it will be installed in the atPutCache so that subsequent calls of at: or next may be handled immediately in bytecode primitive routines. */ sqInt commonAtPut(sqInt stringy) { register struct foo * foo = &fum; sqInt atIx; sqInt index; sqInt rcvr; sqInt value; sqInt sp; sqInt sp1; sqInt fixedFields; sqInt fmt; sqInt stSize; sqInt valToPut; value = longAt(foo->stackPointer); /* Sets successFlag */ index = positive32BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if (!(foo->successFlag && (!((rcvr & 1))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if ((foo->messageSelector == (fetchPointerofObject(17 * 2, fetchPointerofObject(SpecialSelectors, foo->specialObjectsOop)))) && (foo->lkupClass == (fetchClassOfNonInt(rcvr)))) { /* OK -- look in the at-cache */ /* Index into atPutCache */ atIx = (rcvr & AtCacheMask) + AtPutBase; if (!((foo->atCache[atIx + AtCacheOop]) == rcvr)) { installinAtCacheatstring(rcvr, foo->atCache, atIx, stringy); } if (foo->successFlag) { /* begin commonVariable:at:put:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, value); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); goto l1; } if (fmt < 8) { valToPut = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2), valToPut); } goto l1; } if (fmt >= 16) { valToPut = asciiOfCharacter(value); if (!(foo->successFlag)) { goto l1; } } else { valToPut = value; } if ((valToPut & 1)) { valToPut = (valToPut >> 1); if (!((valToPut >= 0) && (valToPut <= 255))) { /* begin primitiveFail */ foo->successFlag = 0; goto l1; } byteAtput((rcvr + (BASE_HEADER_SIZE)) + (index - 1), valToPut); goto l1; } } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end commonVariable:at:put:cacheIndex: */; } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp; return null; } } foo->successFlag = 1; if (stringy) { stObjectatput(rcvr, index, asciiOfCharacter(value)); } else { stObjectatput(rcvr, index, value); } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp1 = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp1; return null; } } /* This code assumes the receiver has been identified at location atIx in the atCache. */ sqInt commonVariableatcacheIndex(sqInt rcvr, sqInt index, sqInt atIx) { register struct foo * foo = &fum; sqInt fixedFields; sqInt fmt; sqInt result; sqInt stSize; sqInt oop; sqInt oop1; stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) index)) >= (((usqInt) 1))) && ((((usqInt) index)) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; return longAt((rcvr + (BASE_HEADER_SIZE)) + (((index + fixedFields) - 1) << (SHIFT_FOR_WORD))); } if (fmt < 8) { /* Bitmap */ result = long32At((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2)); result = positive32BitIntegerFor(result); return result; } if (fmt >= 16) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); return longAt((oop + (BASE_HEADER_SIZE)) + ((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << (SHIFT_FOR_WORD))); } else { return (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << 1) | 1); } } /* begin primitiveFail */ foo->successFlag = 0; } /* May set success to false */ /* First compare two ST integers... */ sqInt compare31or32Bitsequal(sqInt obj1, sqInt obj2) { if (((obj1 & 1)) && ((obj2 & 1))) { return obj1 == obj2; } return (positive32BitValueOf(obj1)) == (positive32BitValueOf(obj2)); } sqInt compilerCreateActualMessagestoringArgs(sqInt aMessage, sqInt argArray) { return compilerHooks[14](aMessage, argArray); } sqInt compilerFlushCache(sqInt aCompiledMethod) { return compilerHooks[2](aCompiledMethod); } sqInt compilerMapFromto(sqInt memStart, sqInt memEnd) { return compilerHooks[4](memStart, memEnd); } sqInt compilerMark(void) { return compilerHooks[9](); } sqInt compilerPostGC(void) { return compilerHooks[5](); } sqInt compilerPostSnapshot(void) { return compilerHooks[8](); } sqInt compilerPreGC(sqInt fullGCFlag) { return compilerHooks[3](fullGCFlag); } sqInt compilerPreSnapshot(void) { return compilerHooks[7](); } sqInt compilerProcessChange(void) { return compilerHooks[6](); } sqInt compilerProcessChangeto(sqInt oldProc, sqInt newProc) { return compilerHooks[6](oldProc, newProc); } sqInt compilerTranslateMethod(void) { return compilerHooks[1](); } /* Return true if neither array contains a small integer. You can't become: integers! */ sqInt containOnlyOopsand(sqInt array1, sqInt array2) { sqInt fieldOffset; sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l4; } else { sz = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { fieldOffset = 0; goto l2; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { if (((longAt(array1 + fieldOffset)) & 1)) { return 0; } if (((longAt(array2 + fieldOffset)) & 1)) { return 0; } fieldOffset -= BYTES_PER_WORD; } return 1; } /* Does thisCntx have aContext in its sender chain? */ sqInt contexthasSender(sqInt thisCntx, sqInt aContext) { sqInt nilOop; sqInt s; if (thisCntx == aContext) { return 0; } nilOop = foo->nilObj; s = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); while (!(s == nilOop)) { if (s == aContext) { return 1; } s = longAt((s + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } return 0; } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=copyBits and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt copyBits(void) { void *fn; fn = ioLoadFunctionFrom("copyBits", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(void))fn)(); } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=copyBitsFrom:to:at: and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt copyBitsFromtoat(sqInt x0, sqInt x1, sqInt y) { void *fn; fn = ioLoadFunctionFrom("copyBitsFromtoat", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(sqInt, sqInt, sqInt))fn)(x0, x1, y); } /* Copy this object into the segment beginning at lastSeg. Install a forwarding pointer, and save oop and header. Fail if out of space. Return the next segmentAddr if successful. */ /* Copy the object... */ sqInt copyObjtoSegmentaddrstopAtsaveOopAtheaderAt(sqInt oop, sqInt segmentWordArray, sqInt lastSeg, sqInt stopAddr, sqInt oopPtr, sqInt hdrPtr) { register struct foo * foo = &fum; sqInt bodySize; sqInt extraSize; sqInt hdrAddr; sqInt header; sqInt in; sqInt lastIn; sqInt out; flag("Dan"); if (!(foo->successFlag)) { return lastSeg; } extraSize = foo->headerTypeBytes[(longAt(oop)) & TypeMask]; /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { bodySize = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { bodySize = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; if ((((usqInt) ((lastSeg + extraSize) + bodySize))) >= (((usqInt) stopAddr))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin transfer:from:to: */ flag("Dan"); in = (oop - extraSize) - (BYTES_PER_WORD); lastIn = in + (((extraSize + bodySize) / (BYTES_PER_WORD)) * (BYTES_PER_WORD)); out = (lastSeg + (BYTES_PER_WORD)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } hdrAddr = (lastSeg + (BYTES_PER_WORD)) + extraSize; longAtput(hdrAddr, (longAt(hdrAddr)) & ((ALL_BUT_ROOT_BIT) - (MARK_BIT))); /* begin forward:to:savingOopAt:andHeaderAt: */ longAtput(oopPtr, oop); longAtput(hdrPtr, longAt(oop)); longAtput(oop, (((lastSeg + (BYTES_PER_WORD)) + extraSize) - segmentWordArray) + HeaderTypeFree); return (lastSeg + extraSize) + bodySize; } /* Bundle up the selector, arguments and lookupClass into a Message object. In the process it pops the arguments off the stack, and pushes the message object. This can then be presented as the argument of e.g. #doesNotUnderstand:. ikp 11/20/1999 03:59 -- added hook for external runtime compilers. */ /* remap lookupClass in case GC happens during allocation */ sqInt createActualMessageTo(sqInt aClass) { register struct foo * foo = &fum; sqInt argumentArray; sqInt lookupClass; sqInt message; sqInt sp; sqInt oop; sqInt oop1; sqInt count; sqInt src; sqInt in; sqInt lastIn; sqInt out; sqInt valuePointer; /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = aClass; /* remap argumentArray in case GC happens during allocation */ argumentArray = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), foo->argumentCount); /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = argumentArray; message = instantiateClassindexableSize(fetchPointerofObject(ClassMessage, foo->specialObjectsOop), 0); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; argumentArray = oop; /* begin popRemappableOop */ oop1 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; lookupClass = oop1; beRootIfOld(argumentArray); if (foo->compilerInitialized) { compilerCreateActualMessagestoringArgs(message, argumentArray); } else { /* begin transfer:from:to: */ count = foo->argumentCount; src = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)); flag("Dan"); in = src - (BYTES_PER_WORD); lastIn = in + (count * (BYTES_PER_WORD)); out = (argumentArray + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)), message); foo->stackPointer = sp; } foo->argumentCount = 1; /* begin storePointer:ofObject:withValue: */ valuePointer = foo->messageSelector; if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, valuePointer); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageSelectorIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, argumentArray); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageArgumentsIndex << (SHIFT_FOR_WORD)), argumentArray); if ((lastPointerOf(message)) >= ((MessageLookupClassIndex * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE))) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) message)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(message, lookupClass); } longAtput((message + (BASE_HEADER_SIZE)) + (MessageLookupClassIndex << (SHIFT_FOR_WORD)), lookupClass); } } sqInt dispatchFunctionPointer(void *aFunctionPointer) { ((void (*)(void))aFunctionPointer)(); } /* Call the primitive at index primIdx in the primitiveTable. */ sqInt dispatchFunctionPointerOnin(sqInt primIdx, void *primTable[]) { return dispatchFunctionPointer(primTable[primIdx]); } /* Repaint the portion of the Smalltalk screen bounded by the affected rectangle. Used to synchronize the screen after a Bitblt to the Smalltalk Display object. */ sqInt displayBitsOfLeftTopRightBottom(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b) { register struct foo * foo = &fum; sqInt bottom; sqInt d; sqInt dispBits; sqInt dispBitsIndex; sqInt displayObj; sqInt h; sqInt left; sqInt right; sqInt surfaceHandle; sqInt top; sqInt w; sqInt oop; sqInt successValue; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; displayObj = longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); if (!(aForm == displayObj)) { return null; } /* begin success: */ successValue = (((displayObj & 1) == 0) && (((((usqInt) (longAt(displayObj))) >> 8) & 15) <= 4)) && ((lengthOf(displayObj)) >= 4); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { dispBits = longAt((displayObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); w = fetchIntegerofObject(1, displayObj); h = fetchIntegerofObject(2, displayObj); d = fetchIntegerofObject(3, displayObj); } if (l < 0) { left = 0; } else { left = l; } if (r > w) { right = w; } else { right = r; } if (t < 0) { top = 0; } else { top = t; } if (b > h) { bottom = h; } else { bottom = b; } if (!((left <= right) && (top <= bottom))) { return null; } if (foo->successFlag) { if ((dispBits & 1)) { surfaceHandle = (dispBits >> 1); if (showSurfaceFn == 0) { showSurfaceFn = ioLoadFunctionFrom("ioShowSurface", "SurfacePlugin"); if (showSurfaceFn == 0) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } } ((sqInt (*)(sqInt, sqInt, sqInt, sqInt, sqInt))showSurfaceFn)(surfaceHandle, left, top, right-left, bottom-top); } else { /* index in memory byte array */ dispBitsIndex = dispBits + (BASE_HEADER_SIZE); ioShowDisplay(dispBitsIndex, w, h, d, left, right, top, bottom); } } } sqInt displayObject(void) { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; return longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); } /* Rounds negative results towards negative infinity, rather than zero. */ sqInt doPrimitiveDivby(sqInt rcvr, sqInt arg) { register struct foo * foo = &fum; sqInt integerArg; sqInt integerRcvr; sqInt posArg; sqInt posRcvr; sqInt result; sqInt successValue; if (((rcvr & arg) & 1) != 0) { integerRcvr = (rcvr >> 1); integerArg = (arg >> 1); /* begin success: */ foo->successFlag = (integerArg != 0) && foo->successFlag; } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return 1; } if (integerRcvr > 0) { if (integerArg > 0) { result = integerRcvr / integerArg; } else { /* round negative result toward negative infinity */ posArg = 0 - integerArg; result = 0 - ((integerRcvr + (posArg - 1)) / posArg); } } else { posRcvr = 0 - integerRcvr; if (integerArg > 0) { /* round negative result toward negative infinity */ result = 0 - ((posRcvr + (integerArg - 1)) / integerArg); } else { posArg = 0 - integerArg; result = posRcvr / posArg; } } /* begin success: */ successValue = # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ; foo->successFlag = successValue && foo->successFlag; return result; } sqInt doPrimitiveModby(sqInt rcvr, sqInt arg) { register struct foo * foo = &fum; sqInt integerArg; sqInt integerRcvr; sqInt integerResult; sqInt successValue; if (((rcvr & arg) & 1) != 0) { integerRcvr = (rcvr >> 1); integerArg = (arg >> 1); /* begin success: */ foo->successFlag = (integerArg != 0) && foo->successFlag; } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return 1; } /* ensure that the result has the same sign as the integerArg */ integerResult = integerRcvr % integerArg; if (integerArg < 0) { if (integerResult > 0) { integerResult += integerArg; } } else { if (integerResult < 0) { integerResult += integerArg; } } /* begin success: */ successValue = # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ; foo->successFlag = successValue && foo->successFlag; return integerResult; } sqInt dummyReferToProxy(void) { interpreterProxy = interpreterProxy; } /* Dump the entire image out to the given file. Intended for debugging only. */ EXPORT(sqInt) dumpImage(char *fileName) { sqInt dataSize; sqImageFile f; sqInt result; f = sqImageFileOpen(fileName, "wb"); if (f == null) { return -1; } dataSize = foo->endOfMemory - memory; result = sqImageFileWrite(pointerForOop(memory), sizeof(unsigned char), dataSize, f); sqImageFileClose(f); return result; } /* execute a method found in the mCache - which means that primitiveIndex & primitiveFunctionPointer are already set. Any sender needs to have previously sent findMethodInClass: or equivalent */ sqInt executeNewMethodFromCache(void) { register struct foo * foo = &fum; sqInt delta; sqInt nArgs; if (foo->primitiveIndex > 0) { if (DoBalanceChecks) { /* check stack balance */ nArgs = foo->argumentCount; delta = foo->stackPointer - foo->activeContext; } foo->successFlag = 1; dispatchFunctionPointer(foo->primitiveFunctionPointer); if (DoBalanceChecks) { if (!(balancedStackafterPrimitivewithArgs(delta, foo->primitiveIndex, nArgs))) { printUnbalancedStack(foo->primitiveIndex); } } if (foo->successFlag) { return null; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } /* Return the number of extra bytes used by the given object's header. */ /* Warning: This method should not be used during marking, when the header type bits of an object may be incorrect. */ /* JMM should be an array lookup! */ EXPORT(sqInt) extraHeaderBytes(sqInt oopOrChunk) { return foo->headerTypeBytes[(longAt(oopOrChunk)) & TypeMask]; } sqInt failed(void) { return !foo->successFlag; } sqInt falseObject(void) { return foo->falseObj; } /* Fetch the instance variable at the given index of the given object. Return the address of first indexable field of resulting array object, or fail if the instance variable does not contain an indexable bytes or words object. */ /* Note: May be called by translated primitive code. */ void * fetchArrayofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt arrayOop; arrayOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); /* begin arrayValueOf: */ if ((!((arrayOop & 1))) && (((arrayOop & 1) == 0) && (isWordsOrBytesNonInt(arrayOop)))) { return pointerForOop(arrayOop + (BASE_HEADER_SIZE)); } /* begin primitiveFail */ foo->successFlag = 0; return null; } sqInt fetchClassOf(sqInt oop) { register struct foo * foo = &fum; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; return longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { return (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } } sqInt fetchClassOfNonInt(sqInt oop) { sqInt ccIndex; sqInt oop1; sqInt oop2; ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { return (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } } /* Fetch the instance variable at the given index of the given object. Return the C double precision floating point value of that instance variable, or fail if it is not a Float. */ /* Note: May be called by translated primitive code. */ double fetchFloatofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt floatOop; floatOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); return floatValueOf(floatOop); } /* Note: May be called by translated primitive code. */ sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer) { sqInt intOop; intOop = longAt((objectPointer + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((intOop & 1)) { return (intOop >> 1); } else { /* begin primitiveFail */ foo->successFlag = 0; return 0; } return null; } /* index by 32-bit units, and return a 32-bit value. Intended to replace fetchWord:ofObject: */ sqInt fetchLong32ofObject(sqInt fieldIndex, sqInt oop) { return long32At((oop + (BASE_HEADER_SIZE)) + (fieldIndex << 2)); } /* index by word size, and return a pointer as long as the word size */ sqInt fetchPointerofObject(sqInt fieldIndex, sqInt oop) { return longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); } /* Return the stackPointer of a Context or BlockContext. */ sqInt fetchStackPointerOf(sqInt aContext) { sqInt sp; sp = longAt((aContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { return 0; } return (sp >> 1); } /* NOTE: this gives size appropriate for fetchPointer: n, but not in general for, eg, fetchLong32, etc. */ sqInt fetchWordLengthOf(sqInt objectPointer) { sqInt sz; sqInt header; /* begin sizeBitsOf: */ header = longAt(objectPointer); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } /* During sweep phase we have encountered a weak reference. Check if its object has gone away (or is about to) and if so, signal a semaphore. */ /* Do *not* inline this in sweepPhase - it is quite an unlikely case to run into a weak reference */ sqInt finalizeReference(usqInt oop) { register struct foo * foo = &fum; sqInt chunk; sqInt firstField; sqInt i; sqInt lastField; sqInt nonWeakCnt; sqInt oopGone; usqInt weakOop; sqInt listItemOop; sqInt listOop; sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; nonWeakCnt = nonWeakFieldsOf(oop); firstField = (BASE_HEADER_SIZE) + (nonWeakCnt << (SHIFT_FOR_WORD)); /* begin lastPointerOf: */ header = longAt(oop); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; lastField = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } /* begin sizeBitsOfSafe: */ header1 = longAt(oop); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l3; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l3; } else { type = HeaderTypeShort; goto l3; } } l3: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l4; } else { sz = header1 & (SIZE_MASK); goto l4; } l4: /* end sizeBitsOfSafe: */; lastField = sz - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { lastField = 0; goto l2; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); lastField = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerOf: */; for (i = firstField; i <= lastField; i += (BYTES_PER_WORD)) { /* ar 1/18/2005: Added oop < youngStart test to make sure we're not testing objects in non-GCable region. This could lead to a forward reference in old space with the oop pointed to not being marked and thus treated as free. */ weakOop = longAt(oop + i); if (!((weakOop == foo->nilObj) || (((weakOop & 1)) || (weakOop < foo->youngStart)))) { if (weakOop < oop) { /* Check if the object is being collected. If the weak reference points * backward: check if the weakOops chunk is free * forward: check if the weakOoop has been marked by GC */ chunk = weakOop - (foo->headerTypeBytes[(longAt(weakOop)) & TypeMask]); oopGone = ((longAt(chunk)) & TypeMask) == HeaderTypeFree; } else { oopGone = ((longAt(weakOop)) & (MARK_BIT)) == 0; } if (oopGone) { longAtput(oop + i, foo->nilObj); if (nonWeakCnt >= 2) { /* begin weakFinalizerCheck: */ listOop = longAt((oop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if ((fetchClassOf(listOop)) == (fetchPointerofObject(ClassWeakFinalizer, foo->specialObjectsOop))) { listItemOop = longAt((listOop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, listItemOop); } longAtput((oop + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), listItemOop); /* begin storePointer:ofObject:withValue: */ if ((((usqInt) listOop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(listOop, oop); } longAtput((listOop + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), oop); } } /* begin signalFinalization: */ /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; foo->pendingFinalizationSignals += 1; } } } } sqInt findClassOfMethodforReceiver(sqInt meth, sqInt rcvr) { register struct foo * foo = &fum; sqInt classDict; sqInt classDictSize; sqInt currClass; sqInt done; sqInt i; sqInt methodArray; sqInt sz; sqInt ccIndex; sqInt ccIndex1; sqInt oop; sqInt oop1; sqInt header; sqInt oop2; sqInt oop3; sqInt oop4; sqInt oop5; /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; currClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop1 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; done = 0; while (!(done)) { classDict = longAt((currClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(classDict); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(classDict - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; classDictSize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray = longAt((classDict + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i = 0; while (i < (classDictSize - SelectorStart)) { if (meth == (longAt((methodArray + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))))) { return currClass; } i += 1; } currClass = longAt((currClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done = currClass == foo->nilObj; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; return longAt((oop2 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); } ccIndex1 = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex1 == 0) { return (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop5 = foo->specialObjectsOop; oop3 = longAt((oop5 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); return longAt((oop3 + (BASE_HEADER_SIZE)) + ((ccIndex1 - 1) << (SHIFT_FOR_WORD))); } return null; } /* Find the compiled method to be run when the current messageSelector is sent to the given class, setting the values of 'newMethod' and 'primitiveIndex'. */ sqInt findNewMethodInClass(sqInt class) { register struct foo * foo = &fum; sqInt ok; sqInt hash; sqInt probe; /* begin lookupInMethodCacheSel:class: */ hash = foo->messageSelector ^ class; probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l1; } ok = 0; l1: /* end lookupInMethodCacheSel:class: */; if (!(ok)) { lookupMethodInClass(class); foo->lkupClass = class; addNewMethodToCache(); } } sqInt findSelectorOfMethodforReceiver(sqInt meth, sqInt rcvr) { register struct foo * foo = &fum; sqInt classDict; sqInt classDictSize; sqInt currClass; sqInt done; sqInt i; sqInt methodArray; sqInt sz; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt header; sqInt oop2; /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; currClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { currClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); currClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; done = 0; while (!(done)) { classDict = longAt((currClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(classDict); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(classDict - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; classDictSize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); methodArray = longAt((classDict + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); i = 0; while (i <= (classDictSize - SelectorStart)) { if (meth == (longAt((methodArray + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))))) { return longAt((classDict + (BASE_HEADER_SIZE)) + ((i + SelectorStart) << (SHIFT_FOR_WORD))); } i += 1; } currClass = longAt((currClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); done = currClass == foo->nilObj; } return foo->nilObj; } /* Return the first accessible object in the heap. */ sqInt firstAccessibleObject(void) { register struct foo * foo = &fum; sqInt obj; sqInt sz; sqInt header; obj = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { return obj; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } error("heap is empty"); } char * firstFixedField(sqInt oop) { return pointerForOop(oop + (BASE_HEADER_SIZE)); } /* NOTE: copied in InterpreterSimulator, so please duplicate any changes */ char * firstIndexableField(sqInt oop) { register struct foo * foo = &fum; sqInt fixedFields; sqInt fmt; sqInt hdr; sqInt totalLength; sqInt sz; sqInt class; sqInt classFormat; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(oop); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l3; } if (fmt < 2) { fixedFields = totalLength; goto l3; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l3: /* end fixedFieldsOf:format:length: */; if (fmt < 8) { if (fmt == 6) { return pointerForOop((oop + (BASE_HEADER_SIZE)) + (fixedFields << 2)); } return pointerForOop((oop + (BASE_HEADER_SIZE)) + (fixedFields << (SHIFT_FOR_WORD))); } else { return pointerForOop((oop + (BASE_HEADER_SIZE)) + fixedFields); } } sqInt floatObjectOf(double aFloat) { sqInt newFloatObj; flag("Dan"); newFloatObj = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassFloat, foo->specialObjectsOop), 8 + (BASE_HEADER_SIZE)); storeFloatAtfrom(newFloatObj + (BASE_HEADER_SIZE), aFloat); return newFloatObj; } /* Fetch the instance variable at the given index of the given object. Return the C double precision floating point value of that instance variable, or fail if it is not a Float. */ /* Note: May be called by translated primitive code. */ double floatValueOf(sqInt oop) { register struct foo * foo = &fum; double result; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop3; flag("Dan"); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { ; fetchFloatAtinto(oop + (BASE_HEADER_SIZE), result); } else { result = 0.0; } return result; } /* methodPtr is a CompiledMethod containing an external primitive. Flush the function address and session ID of the CM */ sqInt flushExternalPrimitiveOf(sqInt methodPtr) { sqInt lit; if (!((literalCountOfHeader(longAt((methodPtr + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) > 0)) { return null; } lit = longAt((methodPtr + (BASE_HEADER_SIZE)) + ((0 + LiteralStart) << (SHIFT_FOR_WORD))); if (!((((lit & 1) == 0) && (((((usqInt) (longAt(lit))) >> 8) & 15) == 2)) && ((lengthOf(lit)) == 4))) { return null; } longAtput((lit + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD)), ConstZero); longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ConstZero); } /* Flush the references to external functions from plugin primitives. This will force a reload of those primitives when accessed next. Note: We must flush the method cache here so that any failed primitives are looked up again. */ sqInt flushExternalPrimitives(void) { register struct foo * foo = &fum; sqInt oop; sqInt primIdx; sqInt primBits; sqInt i; sqInt i1; sqInt i2; sqInt sz; sqInt header; oop = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { if (((((usqInt) (longAt(oop))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((oop + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; primIdx = (primBits & 511) + (((usqInt) primBits) >> 19); if (primIdx == PrimitiveExternalCallIndex) { flushExternalPrimitiveOf(oop); } } } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } /* begin flushAtCache */ for (i1 = 1; i1 <= AtCacheTotalSize; i1 += 1) { foo->atCache[i1] = 0; } /* begin flushExternalPrimitiveTable */ for (i2 = 0; i2 <= (MaxExternalPrimitiveTableSize - 1); i2 += 1) { foo->externalPrimitiveTable[i2] = 0; } } /* force an interrupt check ASAP - setting interruptCheckCounter to a large -ve number is used as a flag to skip messing with the feedback mechanism and nextPollTick resetting makes sure that ioProcess gets called as near immediately as we can manage */ sqInt forceInterruptCheck(void) { register struct foo * foo = &fum; foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } /* Repaint the entire smalltalk screen, ignoring the affected rectangle. Used in some platform's code when the Smalltalk window is brought to the front or uncovered. */ sqInt fullDisplayUpdate(void) { sqInt displayObj; sqInt h; sqInt w; sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; displayObj = longAt((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD))); if ((((displayObj & 1) == 0) && (((((usqInt) (longAt(displayObj))) >> 8) & 15) <= 4)) && ((lengthOf(displayObj)) >= 4)) { w = fetchIntegerofObject(1, displayObj); h = fetchIntegerofObject(2, displayObj); displayBitsOfLeftTopRightBottom(displayObj, 0, 0, w, h); ioForceDisplayUpdate(); } } /* Do a mark/sweep garbage collection of the entire object memory. Free inaccessible objects but do not move them. */ sqInt fullGC(void) { register struct foo * foo = &fum; sqLong startTime; sqInt i; sqInt oop; sqInt sz; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; if (DoAssertionChecks) { reverseDisplayFromto(0, 7); } /* begin preGCAction: */ if (foo->compilerInitialized) { compilerPreGC(1); } else { /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); } startTime = ioMicroSecondClock(); foo->statSweepCount = foo->statMarkCount = foo->statMkFwdCount = foo->statCompMoveCount = 0; /* begin clearRootsTable */ for (i = 1; i <= foo->rootTableCount; i += 1) { oop = foo->rootTable[i]; longAtput(oop, (longAt(oop)) & (ALL_BUT_ROOT_BIT)); foo->rootTable[i] = 0; } foo->rootTableCount = 0; /* process all of memory */ foo->youngStart = memory; markPhase(); foo->totalObjectCount = sweepPhase(); /* begin fullCompaction */ foo->compStart = lowestFreeAfter(memory); if (foo->compStart == foo->freeBlock) { initializeMemoryFirstFree(foo->freeBlock); goto l1; } if ((sz = fwdTableSize(8)) < foo->totalObjectCount) { growObjectMemory(((foo->totalObjectCount - sz) + 10000) * 8); } while (foo->compStart < foo->freeBlock) { foo->compStart = incCompBody(); } l1: /* end fullCompaction */; foo->allocationCount = 0; foo->statFullGCs += 1; foo->statGCTime = ioMicroSecondClock(); foo->statFullGCMSecs += foo->statGCTime - startTime; /* begin capturePendingFinalizationSignals */ foo->statpendingFinalizationSignals = foo->pendingFinalizationSignals; /* reset the young object boundary */ foo->youngStart = foo->freeBlock; postGCAction(); if (DoAssertionChecks) { reverseDisplayFromto(0, 7); } } /* Set the limits for a table of two- or three-word forwarding blocks above the last used oop. The pointer fwdTableNext moves up to fwdTableLast. Used for compaction of memory and become-ing objects. Returns the number of forwarding blocks available. */ sqInt fwdTableInit(sqInt blkSize) { register struct foo * foo = &fum; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); /* make a fake free chunk at endOfMemory for use as a sentinal in memory scans */ foo->endOfMemory = foo->freeBlock + (BASE_HEADER_SIZE); /* begin setSizeOfFree:to: */ longAtput(foo->endOfMemory, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->fwdTableNext = ((foo->endOfMemory + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); /* last forwarding table entry */ /* return the number of forwarding blocks available */ foo->fwdTableLast = foo->memoryLimit - blkSize; return (foo->fwdTableLast - foo->fwdTableNext) / blkSize; } /* Estimate the number of forwarding blocks available for compaction */ sqInt fwdTableSize(sqInt blkSize) { register struct foo * foo = &fum; sqInt eom; sqInt fwdFirst; sqInt fwdLast; /* use all memory free between freeBlock and memoryLimit for forwarding table */ /* Note: Forward blocks must be quadword aligned. */ eom = foo->freeBlock + (BASE_HEADER_SIZE); fwdFirst = ((eom + (BASE_HEADER_SIZE)) + 7) & ((WORD_MASK) - 7); flag("Dan"); /* last forwarding table entry */ /* return the number of forwarding blocks available */ fwdLast = foo->memoryLimit - blkSize; return (fwdLast - fwdFirst) / blkSize; } /* currentBytecode will be private to the main dispatch loop in the generated code. This method allows the currentBytecode to be retrieved from global variables. */ sqInt getCurrentBytecode(void) { return byteAt(foo->instructionPointer); } sqInt getFullScreenFlag(void) { return foo->fullScreenFlag; } sqInt getInterruptCheckCounter(void) { return foo->interruptCheckCounter; } sqInt getInterruptKeycode(void) { return foo->interruptKeycode; } sqInt getInterruptPending(void) { return foo->interruptPending; } /* Answer the next word read from aFile, byte-swapped according to the swapFlag. */ sqInt getLongFromFileswap(sqImageFile aFile, sqInt swapFlag) { sqInt w; w = 0; sqImageFileRead(&w, sizeof(w), 1, aFile); if (swapFlag) { /* begin byteSwapped: */ # if (BYTES_PER_WORD == 4) // swap bytes in an object word return ((((((usqInt) w >> 24)) & Byte0Mask) + ((((usqInt) w >> 8)) & Byte1Mask)) + ((((usqInt) w << 8)) & Byte2Mask)) + ((((usqInt) w << 24)) & Byte3Mask); # else return ((((((((((usqInt) w >> 56)) & Byte0Mask) + ((((usqInt) w >> 40)) & Byte1Mask)) + ((((usqInt) w >> 24)) & Byte2Mask)) + ((((usqInt) w >> 8)) & Byte3Mask)) + ((((usqInt) w << 8)) & Byte4Mask)) + ((((usqInt) w << 24)) & Byte5Mask)) + ((((usqInt) w << 40)) & Byte6Mask)) + ((((usqInt) w << 56)) & Byte7Mask); # endif // BYTES_PER_WORD == 4 return null; } else { return w; } } sqInt getNextWakeupTick(void) { return foo->nextWakeupTick; } sqInt getSavedWindowSize(void) { return foo->savedWindowSize; } /* For Newsqueak FFI */ EXPORT(sqInt) getStackPointer(void) { return foo->stackPointer; } /* return the global session ID value */ sqInt getThisSessionID(void) { return foo->globalSessionID; } /* Attempt to grow the object memory by the given delta amount */ sqInt growObjectMemory(usqInt delta) { register struct foo * foo = &fum; usqInt limit; if (!(isExcessiveAllocationRequestshift(delta, 0))) { foo->statGrowMemory += 1; limit = sqGrowMemoryBy(foo->memoryLimit, delta); if (!(limit == foo->memoryLimit)) { /* remove a tad for safety */ foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } } } sqInt headerOf(sqInt methodPointer) { return longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); } /* a more complex version that tells both the word reversal and the endianness of the machine it came from. Low half of word is 6502. Top byte is top byte of #doesNotUnderstand: on this machine. ($d on the Mac or $s on the PC) */ sqInt imageSegmentVersion(void) { sqInt wholeWord; /* first data word, 'does' */ wholeWord = longAt((fetchPointerofObject(SelectorDoesNotUnderstand, foo->specialObjectsOop)) + (BASE_HEADER_SIZE)); return imageFormatVersionNumber | (wholeWord & 4278190080U); } /* Move objects to consolidate free space into one big chunk. Return the newly created free chunk. */ sqInt incCompBody(void) { register struct foo * foo = &fum; sqInt bytesFreed; fwdTableInit((BYTES_PER_WORD) * 2); /* update pointers to point at new oops */ bytesFreed = incCompMakeFwd(); mapPointersInObjectsFromto(foo->youngStart, foo->endOfMemory); return incCompMove(bytesFreed); } /* Create and initialize forwarding blocks for all non-free objects following compStart. If the supply of forwarding blocks is exhausted, set compEnd to the first chunk above the area to be compacted; otherwise, set it to endOfMemory. Return the number of bytes to be freed. */ sqInt incCompMakeFwd(void) { register struct foo * foo = &fum; sqInt bytesFreed; sqInt fwdBlock; sqInt newOop; sqInt oop; sqInt originalHeader; sqInt originalHeaderType; sqInt fwdBlock1; sqInt header; sqInt realHeader; sqInt sz; sqInt sz1; sqInt header1; bytesFreed = 0; oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { foo->statMkFwdCount += 1; if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { bytesFreed += (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin fwdBlockGet: */ foo->fwdTableNext += (BYTES_PER_WORD) * 2; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l1; } else { fwdBlock = null; goto l1; } l1: /* end fwdBlockGet: */; if (fwdBlock == null) { /* stop; we have used all available forwarding blocks */ foo->compEnd = oop - (foo->headerTypeBytes[(longAt(oop)) & TypeMask]); return bytesFreed; } newOop = oop - bytesFreed; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader = longAt(oop); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType = originalHeader & TypeMask; longAtput(fwdBlock, newOop); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader); if (0) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop); } longAtput(oop, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType)); } /* begin objectAfterWhileForwarding: */ header = longAt(oop); if ((header & (MARK_BIT)) == 0) { /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz1 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l3; } else { sz1 = header1 & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOf: */; } oop = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); goto l2; } fwdBlock1 = (header & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } realHeader = longAt(fwdBlock1 + (BYTES_PER_WORD)); if ((realHeader & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = realHeader & (SIZE_MASK); } oop = (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); l2: /* end objectAfterWhileForwarding: */; } foo->compEnd = foo->endOfMemory; return bytesFreed; } /* Move all non-free objects between compStart and compEnd to their new locations, restoring their headers in the process. Create a new free block at the end of memory. Return the newly created free chunk. */ /* Note: The free block used by the allocator always must be the last free block in memory. It may take several compaction passes to make all free space bubble up to the end of memory. */ sqInt incCompMove(sqInt bytesFreed) { register struct foo * foo = &fum; sqInt bytesToMove; usqInt firstWord; sqInt fwdBlock; sqInt header; usqInt lastWord; sqInt newFreeChunk; sqInt newOop; sqInt next; sqInt oop; sqInt sz; sqInt target; usqInt w; sqInt header1; sqInt fwdBlock1; sqInt header2; sqInt realHeader; sqInt sz1; sqInt sz2; sqInt header3; newOop = null; oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->compEnd))) { foo->statCompMoveCount += 1; /* begin objectAfterWhileForwarding: */ header2 = longAt(oop); if ((header2 & (MARK_BIT)) == 0) { /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz2 = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header3 = longAt(oop); if ((header3 & TypeMask) == HeaderTypeSizeAndClass) { sz2 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l3; } else { sz2 = header3 & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOf: */; } next = (oop + sz2) + (foo->headerTypeBytes[(longAt(oop + sz2)) & TypeMask]); goto l2; } fwdBlock1 = (header2 & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock1)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock1)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock1 & 3) == 0)))) { error("invalid fwd table entry"); } } realHeader = longAt(fwdBlock1 + (BYTES_PER_WORD)); if ((realHeader & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = realHeader & (SIZE_MASK); } next = (oop + sz1) + (foo->headerTypeBytes[(longAt(oop + sz1)) & TypeMask]); l2: /* end objectAfterWhileForwarding: */; if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { /* a moving object; unwind its forwarding block */ fwdBlock = ((longAt(oop)) & (ALL_BUT_MARK_BIT_AND_TYPE_MASK)) << 1; if (DoAssertionChecks) { /* begin fwdBlockValidate: */ if (!(((((usqInt) fwdBlock)) > (((usqInt) foo->endOfMemory))) && (((((usqInt) fwdBlock)) <= (((usqInt) foo->fwdTableNext))) && ((fwdBlock & 3) == 0)))) { error("invalid fwd table entry"); } } newOop = longAt(fwdBlock); header = longAt(fwdBlock + (BYTES_PER_WORD)); longAtput(oop, header); /* move the oop (including any extra header words) */ bytesToMove = oop - newOop; /* begin sizeBitsOf: */ header1 = longAt(oop); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header1 & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; firstWord = oop - (foo->headerTypeBytes[(longAt(oop)) & TypeMask]); lastWord = (oop + sz) - (BASE_HEADER_SIZE); target = firstWord - bytesToMove; for (w = firstWord; w <= lastWord; w += (BYTES_PER_WORD)) { longAtput(target, longAt(w)); target += BYTES_PER_WORD; } } oop = next; } if (newOop == null) { /* no objects moved */ oop = foo->compStart + (foo->headerTypeBytes[(longAt(foo->compStart)) & TypeMask]); if ((((longAt(oop)) & TypeMask) == HeaderTypeFree) && ((objectAfter(oop)) == (foo->compEnd + (foo->headerTypeBytes[(longAt(foo->compEnd)) & TypeMask])))) { newFreeChunk = oop; } else { newFreeChunk = foo->freeBlock; } } else { /* initialize the newly freed memory chunk */ /* newOop is the last object moved; free chunk starts right after it */ newFreeChunk = newOop + (sizeBitsOf(newOop)); /* begin setSizeOfFree:to: */ longAtput(newFreeChunk, (bytesFreed & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); } if (DoAssertionChecks) { if (!((objectAfter(newFreeChunk)) == (foo->compEnd + (foo->headerTypeBytes[(longAt(foo->compEnd)) & TypeMask])))) { error("problem creating free chunk after compaction"); } } if ((objectAfter(newFreeChunk)) == foo->endOfMemory) { initializeMemoryFirstFree(newFreeChunk); } else { initializeMemoryFirstFree(foo->freeBlock); } return newFreeChunk; } /* Return the equivalent of aClass includesBehavior: aSuperclass. Note: written for efficiency and better inlining (only 1 temp) */ sqInt includesBehaviorThatOf(sqInt aClass, sqInt aSuperclass) { register struct foo * foo = &fum; sqInt theClass; if (((theClass = aClass) == aSuperclass) || (aSuperclass == foo->nilObj)) { return 1; } do { if ((theClass = longAt((theClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD)))) == aSuperclass) { return 1; } } while(theClass != foo->nilObj); return 0; } /* Do a mark/sweep garbage collection of just the young object area of object memory (i.e., objects above youngStart), using the root table to identify objects containing pointers to young objects from the old object area. */ sqInt incrementalGC(void) { register struct foo * foo = &fum; sqInt i; sqLong startTime; sqInt survivorCount; sqInt weDidGrow; sqInt growth; sqInt i1; sqInt oop; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; if (foo->rootTableCount >= RootTableSize) { /* root table overflow; cannot do an incremental GC (this should be very rare) */ foo->statRootTableOverflows += 1; return fullGC(); } if (DoAssertionChecks) { reverseDisplayFromto(8, 15); validateRoots(); /* begin validate */ } /* begin preGCAction: */ if (foo->compilerInitialized) { compilerPreGC(0); } else { /* begin storeContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = ((((foo->instructionPointer - foo->method) - ((BASE_HEADER_SIZE) - 2)) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); } startTime = ioMicroSecondClock(); foo->weakRootCount = 0; foo->statSweepCount = foo->statMarkCount = foo->statMkFwdCount = foo->statCompMoveCount = 0; markPhase(); for (i = 1; i <= foo->weakRootCount; i += 1) { finalizeReference(foo->weakRoots[i]); } survivorCount = sweepPhase(); /* begin incrementalCompaction */ if (foo->compStart == foo->freeBlock) { initializeMemoryFirstFree(foo->freeBlock); } else { incCompBody(); } foo->statAllocationCount = foo->allocationCount; foo->allocationCount = 0; foo->statIncrGCs += 1; foo->statGCTime = ioMicroSecondClock(); foo->statIGCDeltaTime = foo->statGCTime - startTime; foo->statIncrGCMSecs += foo->statIGCDeltaTime; /* begin capturePendingFinalizationSignals */ foo->statpendingFinalizationSignals = foo->pendingFinalizationSignals; /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; foo->statRootTableCount = foo->rootTableCount; foo->statSurvivorCount = survivorCount; weDidGrow = 0; if (((survivorCount > foo->tenuringThreshold) || (foo->rootTableCount >= RootTableRedZone)) || (foo->forceTenureFlag == 1)) { /* move up the young space boundary if * there are too many survivors: this limits the number of objects that must be processed on future incremental GC's * we're about to overflow the roots table this limits the number of full GCs that may be caused by root table overflows in the near future */ foo->forceTenureFlag = 0; foo->statTenures += 1; /* begin clearRootsTable */ for (i1 = 1; i1 <= foo->rootTableCount; i1 += 1) { oop = foo->rootTable[i1]; longAtput(oop, (longAt(oop)) & (ALL_BUT_ROOT_BIT)); foo->rootTable[i1] = 0; } foo->rootTableCount = 0; if ((foo->freeBlock < foo->growHeadroom) && (foo->gcBiasToGrow > 0)) { biasToGrow(); weDidGrow = 1; } foo->youngStart = foo->freeBlock; } postGCAction(); if (DoAssertionChecks) { validateRoots(); /* begin validate */ reverseDisplayFromto(8, 15); } if (weDidGrow) { /* begin biasToGrowCheckGCLimit */ growth = (foo->youngStart - memory) - foo->gcBiasToGrowThreshold; if (growth < 0) { foo->gcBiasToGrowThreshold = foo->youngStart - memory; } if (growth > foo->gcBiasToGrowGCLimit) { fullGC(); foo->gcBiasToGrowThreshold = foo->youngStart - memory; } } } /* Initialize hooks for the 'null compiler' */ sqInt initCompilerHooks(void) { compilerHooks[1]= nullCompilerHook; compilerHooks[2]= nullCompilerHook; compilerHooks[3]= nullCompilerHook; compilerHooks[4]= nullCompilerHook; compilerHooks[5]= nullCompilerHook; compilerHooks[6]= nullCompilerHook; compilerHooks[7]= nullCompilerHook; compilerHooks[8]= nullCompilerHook; compilerHooks[9]= nullCompilerHook; compilerHooks[10]= nullCompilerHook; compilerHooks[11]= nullCompilerHook; compilerHooks[12]= nullCompilerHook; compilerHooks[13]= nullCompilerHook; compilerHooks[14]= nullCompilerHook; foo->compilerInitialized = 0; } /* Set the imageFormatVersionNumber to a default value for this word size. Normally this will have been set at image load time, but set it to a reasonable default if this has not been done. */ sqInt initializeImageFormatVersionIfNeeded(void) { if (imageFormatVersionNumber == 0) { if ((BYTES_PER_WORD) == 8) { imageFormatVersionNumber = 68000; } else { imageFormatVersionNumber = 6502; } } } /* Initialize Interpreter state before starting execution of a new image. */ sqInt initializeInterpreter(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt i; sqInt i1; sqInt proc; sqInt sched; sqInt oop; sqInt oop1; sqInt activeCntx; sqInt tmp; interpreterProxy = sqGetInterpreterProxy(); dummyReferToProxy(); initializeObjectMemory(bytesToShift); initCompilerHooks(); foo->activeContext = foo->nilObj; foo->theHomeContext = foo->nilObj; foo->method = foo->nilObj; foo->receiver = foo->nilObj; foo->messageSelector = foo->nilObj; foo->newMethod = foo->nilObj; foo->methodClass = foo->nilObj; foo->lkupClass = foo->nilObj; foo->receiverClass = foo->nilObj; foo->newNativeMethod = foo->nilObj; /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } /* begin flushAtCache */ for (i1 = 1; i1 <= AtCacheTotalSize; i1 += 1) { foo->atCache[i1] = 0; } /* begin loadInitialContext */ /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); proc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->activeContext = longAt((proc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } /* begin fetchContextRegisters: */ activeCntx = foo->activeContext; tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = activeCntx; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (activeCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); foo->reclaimableContextCount = 0; /* begin initialCleanup */ if (((longAt(foo->activeContext)) & (ROOT_BIT)) == 0) { goto l1; } longAtput(foo->activeContext, (longAt(foo->activeContext)) & (ALL_BUT_ROOT_BIT)); flushExternalPrimitives(); l1: /* end initialCleanup */; foo->interruptCheckCounter = 0; foo->interruptCheckCounterFeedBackReset = 1000; foo->interruptChecksEveryNms = 1; foo->nextPollTick = 0; foo->nextWakeupTick = 0; foo->lastTick = 0; /* cmd-. as used for Mac but no other OS */ foo->interruptKeycode = 2094; foo->interruptPending = 0; foo->semaphoresUseBufferA = 1; foo->semaphoresToSignalCountA = 0; foo->semaphoresToSignalCountB = 0; foo->deferDisplayUpdates = 0; foo->pendingFinalizationSignals = 0; foo->globalSessionID = 0; while (foo->globalSessionID == 0) { foo->globalSessionID = time(NULL) + ioMSecs(); } foo->jmpDepth = 0; foo->jmpMax = MaxJumpBuf; } /* Initialize endOfMemory to the top of oop storage space, reserving some space for forwarding blocks, and create the freeBlock from which space is allocated. Also create a fake free chunk at endOfMemory to act as a sentinal for memory scans. */ /* Note: The amount of space reserved for forwarding blocks should be chosen to ensure that incremental compactions can usually be done in a single pass. However, there should be enough forwarding blocks so a full compaction can be done in a reasonable number of passes, say ten. (A full compaction requires N object-moving passes, where N = number of non-garbage objects / number of forwarding blocks). di 11/18/2000 Re totalObjectCount: Provide a margin of one byte per object to be used for forwarding pointers at GC time. Since fwd blocks are 8 bytes, this means an absolute worst case of 8 passes to compact memory. In most cases it will be adequate to do compaction in a single pass. */ sqInt initializeMemoryFirstFree(usqInt firstFree) { register struct foo * foo = &fum; usqInt fwdBlockBytes; /* reserve space for forwarding blocks */ fwdBlockBytes = foo->totalObjectCount & (((WORD_MASK) - (BYTES_PER_WORD)) + 1); if (!((((usqInt) (foo->memoryLimit - fwdBlockBytes))) >= (((usqInt) (firstFree + (BASE_HEADER_SIZE)))))) { /* reserve enough space for a minimal free block of BaseHeaderSize bytes */ fwdBlockBytes = foo->memoryLimit - (firstFree + (BASE_HEADER_SIZE)); } foo->endOfMemory = foo->memoryLimit - fwdBlockBytes; foo->freeBlock = firstFree; /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, ((foo->endOfMemory - firstFree) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); /* begin setSizeOfFree:to: */ longAtput(foo->endOfMemory, ((BASE_HEADER_SIZE) & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); if (DoAssertionChecks) { if (!((foo->freeBlock < foo->endOfMemory) && (foo->endOfMemory < foo->memoryLimit))) { error("error in free space computation"); } if (!((foo->endOfMemory + (foo->headerTypeBytes[(longAt(foo->endOfMemory)) & TypeMask])) == foo->endOfMemory)) { error("header format must have changed"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("free block not properly initialized"); } } } /* Initialize object memory variables at startup time. Assume endOfMemory is initially set (by the image-reading code) to the end of the last object in the image. Initialization redefines endOfMemory to be the end of the object allocation area based on the total available memory, but reserving some space for forwarding blocks. */ /* Assume: image reader initializes the following variables: memory endOfMemory memoryLimit specialObjectsOop lastHash */ /* di 11/18/2000 fix slow full GC */ /* set the start of the young object space */ sqInt initializeObjectMemory(sqInt bytesToShift) { register struct foo * foo = &fum; sqInt oop; sqInt oop1; sqInt oop2; /* image may be at a different address; adjust oops for new location */ foo->youngStart = foo->endOfMemory; foo->totalObjectCount = adjustAllOopsBy(bytesToShift); initializeMemoryFirstFree(foo->endOfMemory); /* heavily used special objects */ foo->specialObjectsOop += bytesToShift; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->nilObj = longAt((oop + (BASE_HEADER_SIZE)) + (NilObject << (SHIFT_FOR_WORD))); /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->falseObj = longAt((oop1 + (BASE_HEADER_SIZE)) + (FalseObject << (SHIFT_FOR_WORD))); /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; foo->trueObj = longAt((oop2 + (BASE_HEADER_SIZE)) + (TrueObject << (SHIFT_FOR_WORD))); foo->rootTableCount = 0; foo->freeContexts = NilContext; foo->freeLargeContexts = NilContext; foo->allocationCount = 0; foo->lowSpaceThreshold = 0; foo->signalLowSpace = 0; foo->compStart = 0; foo->compEnd = 0; foo->fwdTableNext = 0; foo->fwdTableLast = 0; foo->remapBufferCount = 0; /* do incremental GC after this many allocations */ foo->allocationsBetweenGCs = 4000; /* tenure all suriving objects if count is over this threshold */ foo->tenuringThreshold = 2000; /* four megabyte of headroom when growing */ foo->growHeadroom = (4 * 1024) * 1024; /* eight megabyte of free space before shrinking */ /* garbage collection statistics */ foo->shrinkThreshold = (8 * 1024) * 1024; foo->statFullGCs = 0; foo->statFullGCMSecs = 0; foo->statIncrGCs = 0; foo->statIncrGCMSecs = 0; foo->statTenures = 0; foo->statRootTableOverflows = 0; foo->statGrowMemory = 0; foo->statShrinkMemory = 0; foo->forceTenureFlag = 0; foo->gcBiasToGrow = 0; foo->gcBiasToGrowGCLimit = 0; foo->extraRootCount = 0; } /* Install the oop of this object in the given cache (at or atPut), along with its size, format and fixedSize */ sqInt installinAtCacheatstring(sqInt rcvr, sqInt *cache, sqInt atIx, sqInt stringy) { register struct foo * foo = &fum; sqInt fixedFields; sqInt fmt; sqInt hdr; sqInt totalLength; sqInt sz; sqInt class; sqInt classFormat; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; if ((fmt == 3) && ((((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l3; } if (fmt < 2) { fixedFields = totalLength; goto l3; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l2; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l2; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l2; } l2: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l3: /* end fixedFieldsOf:format:length: */; cache[atIx + AtCacheOop] = rcvr; if (stringy) { cache[atIx + AtCacheFmt] = (fmt + 16); } else { cache[atIx + AtCacheFmt] = fmt; } cache[atIx + AtCacheFixedFields] = fixedFields; cache[atIx + AtCacheSize] = (totalLength - fixedFields); } /* NOTE: This method supports the backward-compatible split instSize field of the class format word. The sizeHiBits will go away and other shifts change by 2 when the split fields get merged in an (incompatible) image change. */ sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size) { register struct foo * foo = &fum; sqInt binc; sqInt bm1; sqInt byteSize; sqInt cClass; sqInt classFormat; sqInt fillWord; sqInt format; sqInt hash; sqInt hdrSize; sqInt header1; sqInt header2; sqInt header3; sqInt newObj; sqInt sizeHiBits; usqInt end; usqInt i; sqInt newObj1; sqInt remappedClassOop; sqInt enoughSpace; sqInt newChunk; sqInt newFreeSize; sqInt oop; usqInt minFree; sqInt currentProc; sqInt lastSavedProcess; sqInt sched; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; if (DoAssertionChecks) { if (size < 0) { error("cannot have a negative indexable field count"); } } /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; /* Low 2 bits are 0 */ classFormat = (longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; header1 = (classFormat & 130816) | ((hash << HashBitsOffset) & HashBits); header2 = classPointer; header3 = 0; sizeHiBits = ((usqInt) (classFormat & 393216)) >> 9; /* compact class field from format word */ cClass = header1 & CompactClassMask; /* size in bytes -- low 2 bits are 0 */ /* Note this byteSize comes from the format word of the class which is pre-shifted to 4 bytes per field. Need another shift for 8 bytes per word... */ byteSize = (classFormat & ((SIZE_MASK) + (SIZE_4_BIT))) + sizeHiBits; byteSize = byteSize << ((SHIFT_FOR_WORD) - 2); format = (((usqInt) classFormat) >> 8) & 15; flag("sizeLowBits"); if (format < 8) { if (format == 6) { /* long32 bitmaps */ bm1 = (BYTES_PER_WORD) - 1; /* round up */ byteSize = ((byteSize + (size * 4)) + bm1) & (LONG_SIZE_MASK); /* odd bytes */ /* extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits) */ binc = bm1 - (((size * 4) + bm1) & bm1); header1 = header1 | (binc & 4); } else { /* Arrays and 64-bit bitmaps */ byteSize += size * (BYTES_PER_WORD); } } else { /* Strings and Methods */ bm1 = (BYTES_PER_WORD) - 1; /* round up */ byteSize = ((byteSize + size) + bm1) & (LONG_SIZE_MASK); /* odd bytes */ /* low bits of byte size go in format field */ binc = bm1 - ((size + bm1) & bm1); /* extra low bit (4) for 64-bit VM goes in 4-bit (betw hdr bits and sizeBits) */ header1 = header1 | ((binc & 3) << 8); header1 = header1 | (binc & 4); } if (byteSize > 255) { /* requires size header word */ header3 = byteSize; header1 = header1; } else { header1 = header1 | byteSize; } if (header3 > 0) { /* requires full header */ hdrSize = 3; } else { if (cClass == 0) { hdrSize = 2; } else { hdrSize = 1; } } if (format <= 4) { /* if pointers, fill with nil oop */ fillWord = foo->nilObj; } else { fillWord = 0; } /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; lastSavedProcess = longAt((oop2 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop4 = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, currentProc); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (byteSize + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += byteSize + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj1 = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj1, header3 | HeaderTypeSizeAndClass); longAtput(newObj1 + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj1 + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj1 += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj1, remappedClassOop | HeaderTypeClass); longAtput(newObj1 + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj1 += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj1, header1 | HeaderTypeShort); } if (1) { end = newObj1 + byteSize; i = newObj1 + (BYTES_PER_WORD); while (i < end) { longAtput(i, fillWord); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj1); oopHasOkayClass(newObj1); if (!((objectAfter(newObj1)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } newObj = newObj1; return newObj; } /* This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include four bytes for the base header word. */ sqInt instantiateContextsizeInBytes(sqInt classPointer, sqInt sizeInBytes) { register struct foo * foo = &fum; sqInt hash; sqInt hdrSize; sqInt header1; sqInt header2; sqInt extendedSize; usqInt end; usqInt i; sqInt newObj; sqInt remappedClassOop; sqInt enoughSpace; sqInt newChunk; sqInt newFreeSize; sqInt oop; usqInt minFree; sqInt currentProc; sqInt lastSavedProcess; sqInt sched; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; header1 = ((hash << HashBitsOffset) & HashBits) | ((longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1); header2 = classPointer; if ((header1 & CompactClassMask) > 0) { /* are contexts compact? */ hdrSize = 1; } else { hdrSize = 2; } if (sizeInBytes <= (SIZE_MASK)) { /* OR size into header1. Must not do this if size > SizeMask */ header1 += sizeInBytes - (header1 & (SIZE_MASK)); } else { /* Zero the size field of header1 if large */ hdrSize = 3; header1 -= header1 & (SIZE_MASK); } flag("Dan"); /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ extendedSize = LARGE_CONTEXT_SIZE; if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; lastSavedProcess = longAt((oop2 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop4 = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, currentProc); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj, extendedSize | HeaderTypeSizeAndClass); longAtput(newObj + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj, remappedClassOop | HeaderTypeClass); longAtput(newObj + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj, header1 | HeaderTypeShort); } if (0) { end = newObj + sizeInBytes; i = newObj + (BYTES_PER_WORD); while (i < end) { longAtput(i, 0); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj); oopHasOkayClass(newObj); if (!((objectAfter(newObj)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } return newObj; } /* This version of instantiateClass assumes that the total object size is under 256 bytes, the limit for objects with only one or two header words. Note that the size is specified in bytes and should include 4 or 8 bytes for the base header word. NOTE this code will only work for sizes that are an integral number of words (like not a 32-bit LargeInteger in a 64-bit system). May cause a GC. Note that the created small object IS NOT FILLED and must be completed before returning it to Squeak. Since this call is used in routines that do jsut that we are safe. Break this rule and die. */ sqInt instantiateSmallClasssizeInBytes(sqInt classPointer, sqInt sizeInBytes) { register struct foo * foo = &fum; sqInt hash; sqInt hdrSize; sqInt header1; sqInt header2; usqInt end; usqInt i; sqInt newObj; sqInt remappedClassOop; sqInt enoughSpace; sqInt newChunk; sqInt newFreeSize; sqInt oop; usqInt minFree; sqInt currentProc; sqInt lastSavedProcess; sqInt sched; sqInt oop4; sqInt oop1; sqInt oop2; sqInt oop3; if (!((sizeInBytes & ((BYTES_PER_WORD) - 1)) == 0)) { error("size must be integral number of words"); } /* begin newObjectHash */ foo->lastHash = (13849 + (27181 * foo->lastHash)) & 65535; hash = foo->lastHash; header1 = ((hash << HashBitsOffset) & HashBits) | ((longAt((classPointer + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1); header2 = classPointer; if ((header1 & CompactClassMask) > 0) { /* is this a compact class */ hdrSize = 1; } else { hdrSize = 2; } header1 += sizeInBytes - (header1 & ((SIZE_MASK) + (SIZE_4_BIT))); /* begin allocate:headerSize:h1:h2:h3:doFill:with: */ if (hdrSize > 1) { /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = header2; } /* begin allocateChunk: */ if (foo->allocationCount >= foo->allocationsBetweenGCs) { incrementalGC(); } /* begin sufficientSpaceToAllocate: */ minFree = (foo->lowSpaceThreshold + (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)))) + (BASE_HEADER_SIZE); if (oopisGreaterThanOrEqualTo((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), minFree)) { enoughSpace = 1; goto l1; } else { enoughSpace = sufficientSpaceAfterGC(minFree); goto l1; } l1: /* end sufficientSpaceToAllocate: */; if (!(enoughSpace)) { foo->signalLowSpace = 1; foo->lowSpaceThreshold = 0; /* begin saveProcessSignalingLowSpace */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; lastSavedProcess = longAt((oop2 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD))); if (lastSavedProcess == foo->nilObj) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop4 = longAt((oop3 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); currentProc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, currentProc); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (ProcessSignalingLowSpace << (SHIFT_FOR_WORD)), currentProc); } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; } if (oopisLessThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))) + (BASE_HEADER_SIZE))) { error("out of memory"); } newFreeSize = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - (sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD))); newChunk = foo->freeBlock; foo->freeBlock += sizeInBytes + ((hdrSize - 1) * (BYTES_PER_WORD)); /* begin setSizeOfFree:to: */ longAtput(foo->freeBlock, (newFreeSize & (ALL_BUT_TYPE_MASK)) | HeaderTypeFree); foo->allocationCount += 1; newObj = newChunk; if (hdrSize > 1) { /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; remappedClassOop = oop; } if (hdrSize == 3) { longAtput(newObj, 0 | HeaderTypeSizeAndClass); longAtput(newObj + (BYTES_PER_WORD), remappedClassOop | HeaderTypeSizeAndClass); longAtput(newObj + ((BYTES_PER_WORD) * 2), header1 | HeaderTypeSizeAndClass); newObj += (BYTES_PER_WORD) * 2; } if (hdrSize == 2) { longAtput(newObj, remappedClassOop | HeaderTypeClass); longAtput(newObj + (BYTES_PER_WORD), header1 | HeaderTypeClass); newObj += BYTES_PER_WORD; } if (hdrSize == 1) { longAtput(newObj, header1 | HeaderTypeShort); } if (0) { end = newObj + sizeInBytes; i = newObj + (BYTES_PER_WORD); while (i < end) { longAtput(i, 0); i += BYTES_PER_WORD; } } if (DoAssertionChecks) { okayOop(newObj); oopHasOkayClass(newObj); if (!((objectAfter(newObj)) == foo->freeBlock)) { error("allocate bug: did not set header of new oop correctly"); } if (!((objectAfter(foo->freeBlock)) == foo->endOfMemory)) { error("allocate bug: did not set header of freeBlock correctly"); } } return newObj; } sqInt integerObjectOf(sqInt value) { return (value << 1) + 1; } /* Translator produces 'objectPointer >> 1' */ sqInt integerValueOf(sqInt objectPointer) { if ((objectPointer & 2147483648U) != 0) { return ((((usqInt) (objectPointer & 2147483647U)) >> 1) - 1073741823) - 1; } else { return ((usqInt) objectPointer) >> 1; } } EXPORT(sqInt) internalIsImmutable(sqInt oop) { return 0; } EXPORT(sqInt) internalIsMutable(sqInt oop) { return 1; } /* This is the main interpreter loop. It normally loops forever, fetching and executing bytecodes. When running in the context of a browser plugin VM, however, it must return control to the browser periodically. This should done only when the state of the currently running Squeak thread is safely stored in the object heap. Since this is the case at the moment that a check for interrupts is performed, that is when we return to the browser if it is time to do so. Interrupt checks happen quite frequently. */ /* should not be inlined into any senders */ /* record entry time when running as a browser plug-in */ sqInt interpret(void) { register struct foo * foo = &fum; sqInt localReturnValue; sqInt localReturnContext; sqInt localHomeContext; char* localSP; char* localIP; sqInt currentBytecode; browserPluginInitialiseIfNeeded(); initializeImageFormatVersionIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); while (1) { switch (currentBytecode) { case 0: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 0 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 1: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 1 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 2: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 2 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 3: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 3 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 4: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 4 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 5: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 5 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 6: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 6 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 7: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 7 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 8: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 8 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 9: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 9 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 10: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 10 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 11: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 11 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 12: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 12 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 13: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 13 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 14: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 14 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 15: /* pushReceiverVariableBytecode */ { sqInt fieldIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushReceiverVariable: */ fieldIndex = 15 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 16: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 16 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 17: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 17 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 18: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 18 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 19: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 19 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 20: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 20 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 21: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 21 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 22: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 22 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 23: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 23 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 24: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 24 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 25: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 25 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 26: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 26 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 27: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 27 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 28: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 28 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 29: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 29 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 30: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 30 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 31: /* pushTemporaryVariableBytecode */ { sqInt temporaryIndex; sqInt object; sqInt oop; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushTemporaryVariable: */ temporaryIndex = 31 & 15; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; object = longAt((oop + (BASE_HEADER_SIZE)) + ((temporaryIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 32: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 32 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 33: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 33 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 34: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 34 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 35: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 35 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 36: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 36 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 37: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 37 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 38: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 38 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 39: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 39 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 40: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 40 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 41: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 41 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 42: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 42 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 43: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 43 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 44: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 44 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 45: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 45 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 46: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 46 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 47: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 47 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 48: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 48 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 49: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 49 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 50: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 50 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 51: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 51 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 52: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 52 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 53: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 53 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 54: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 54 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 55: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 55 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 56: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 56 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 57: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 57 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 58: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 58 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 59: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 59 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 60: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 60 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 61: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 61 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 62: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 62 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 63: /* pushLiteralConstantBytecode */ { sqInt literalIndex; sqInt object; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralConstant: */ literalIndex = 63 & 31; /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 64: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 64 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 65: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 65 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 66: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 66 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 67: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 67 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 68: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 68 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 69: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 69 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 70: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 70 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 71: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 71 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 72: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 72 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 73: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 73 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 74: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 74 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 75: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 75 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 76: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 76 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 77: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 77 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 78: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 78 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 79: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 79 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 80: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 80 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 81: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 81 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 82: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 82 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 83: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 83 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 84: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 84 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 85: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 85 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 86: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 86 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 87: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 87 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 88: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 88 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 89: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 89 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 90: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 90 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 91: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 91 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 92: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 92 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 93: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 93 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 94: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 94 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 95: /* pushLiteralVariableBytecode */ { sqInt literalIndex; sqInt object; sqInt oop; sqInt methodPointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushLiteralVariable: */ literalIndex = 95 & 31; /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer = foo->method; oop = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((literalIndex + LiteralStart) << (SHIFT_FOR_WORD))); object = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 96: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 96 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 97: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 97 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 98: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 98 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 99: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 99 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 100: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 100 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 101: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 101 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 102: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 102 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 103: /* storeAndPopReceiverVariableBytecode */ { sqInt rcvr; sqInt top; sqInt fieldIndex; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); rcvr = foo->receiver; top = longAtPointer(localSP); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, top); } /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = 103 & 7; longAtput((rcvr + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), top); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 104: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (104 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 105: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (105 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 106: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (106 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 107: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (107 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 108: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (108 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 109: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (109 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 110: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (110 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 111: /* storeAndPopTemporaryVariableBytecode */ { sqInt fieldIndex; sqInt oop; sqInt valuePointer; flag("requires currentBytecode to be expanded to a constant"); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storePointerUnchecked:ofObject:withValue: */ fieldIndex = (111 & 7) + TempFrameStart; oop = localHomeContext; valuePointer = longAtPointer(localSP); longAtput((oop + (BASE_HEADER_SIZE)) + (fieldIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 112: /* pushReceiverBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->receiver); } ; break; case 113: /* pushConstantTrueBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } ; break; case 114: /* pushConstantFalseBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } ; break; case 115: /* pushConstantNilBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->nilObj); } ; break; case 116: /* pushConstantMinusOneBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstMinusOne); } ; break; case 117: /* pushConstantZeroBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstZero); } ; break; case 118: /* pushConstantOneBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstOne); } ; break; case 119: /* pushConstantTwoBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, ConstTwo); } ; break; case 120: /* returnReceiver */ { sqInt closureOrNil; sqInt context; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->receiver; /* goto commonReturn */ } ; commonReturn: /* commonReturn */ { sqInt contextOfCaller; sqInt localCntx; sqInt localVal; sqInt nilOop; sqInt thisCntx; sqInt unwindMarked; sqInt header; sqInt meth; sqInt pIndex; sqInt header1; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt primBits; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; nilOop = foo->nilObj; thisCntx = foo->activeContext; localCntx = localReturnContext; localVal = localReturnValue; if ((localCntx == nilOop) || ((longAt((localCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) == nilOop)) { /* begin internalCannotReturn: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + (SelectorCannotReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l42; } /* begin fetchPointer:ofObject: */ oop = foo->activeContext; thisCntx = longAt((oop + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); while (!(thisCntx == localCntx)) { if (thisCntx == nilOop) { /* begin internalCannotReturn: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; foo->messageSelector = longAt((oop2 + (BASE_HEADER_SIZE)) + (SelectorCannotReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l42; } /* begin isUnwindMarked: */ header = longAt(thisCntx); if (!(((((usqInt) header) >> 12) & 31) == 14)) { unwindMarked = 0; goto l43; } meth = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); unwindMarked = pIndex == 198; l43: /* end isUnwindMarked: */; if (unwindMarked) { /* begin internalAboutToReturn:through: */ /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, thisCntx); /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; foo->messageSelector = longAt((oop3 + (BASE_HEADER_SIZE)) + (SelectorAboutToReturn << (SHIFT_FOR_WORD))); foo->argumentCount = 2; goto normalSend; goto l42; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } thisCntx = foo->activeContext; while (!(thisCntx == localCntx)) { contextOfCaller = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); longAtput((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), nilOop); longAtput((thisCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), nilOop); if (foo->reclaimableContextCount > 0) { foo->reclaimableContextCount -= 1; /* begin recycleContextIfPossible: */ if ((((usqInt) thisCntx)) >= (((usqInt) foo->youngStart))) { header1 = longAt(thisCntx); if (((((usqInt) header1) >> 12) & 31) == 14) { if ((header1 & (SIZE_MASK)) == (SMALL_CONTEXT_SIZE)) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = foo->freeContexts; longAtput((thisCntx + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer); foo->freeContexts = thisCntx; } if ((header1 & (SIZE_MASK)) == (LARGE_CONTEXT_SIZE)) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->freeLargeContexts; longAtput((thisCntx + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer1); foo->freeLargeContexts = thisCntx; } } } } thisCntx = contextOfCaller; } foo->activeContext = thisCntx; if ((((usqInt) thisCntx)) < (((usqInt) foo->youngStart))) { beRootIfOld(thisCntx); } /* begin internalFetchContextRegisters: */ tmp = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((thisCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = thisCntx; } localHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((thisCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localIP = pointerForOop(((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2); tmp = ((longAt((thisCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localSP = pointerForOop((thisCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD))); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, localVal); } ; l42: /* end case */; break; case 121: /* returnTrue */ { sqInt closureOrNil; sqInt context; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->trueObj; goto commonReturn; } ; break; case 122: /* returnFalse */ { sqInt closureOrNil; sqInt context; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->falseObj; goto commonReturn; } ; break; case 123: /* returnNil */ { sqInt closureOrNil; sqInt context; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = foo->nilObj; goto commonReturn; } ; break; case 124: /* returnTopFromMethod */ { sqInt closureOrNil; sqInt context; /* begin sender */ context = localHomeContext; while ((closureOrNil = longAt((context + (BASE_HEADER_SIZE)) + (ClosureIndex << (SHIFT_FOR_WORD)))) != foo->nilObj) { context = longAt((closureOrNil + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); } localReturnContext = longAt((context + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); localReturnValue = longAtPointer(localSP); goto commonReturn; } ; break; case 125: /* returnTopFromBlock */ { sqInt oop; /* begin fetchPointer:ofObject: */ oop = foo->activeContext; localReturnContext = longAt((oop + (BASE_HEADER_SIZE)) + (CallerIndex << (SHIFT_FOR_WORD))); localReturnValue = longAtPointer(localSP); goto commonReturn; } ; break; case 126: case 127: /* unknownBytecode */ { error("Unknown bytecode"); } ; break; case 128: /* extendedPushBytecode */ { sqInt descriptor; sqInt variableIndex; sqInt variableType; sqInt object; sqInt oop; sqInt object1; sqInt oop1; sqInt object2; sqInt methodPointer; sqInt object3; sqInt oop2; sqInt methodPointer1; descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin pushReceiverVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop = foo->receiver; object = longAt((oop + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); goto l1; } if (variableType == 1) { /* begin pushTemporaryVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop1 = localHomeContext; object1 = longAt((oop1 + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object1); goto l1; } if (variableType == 2) { /* begin pushLiteralConstant: */ /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer = foo->method; object2 = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object2); goto l1; } if (variableType == 3) { /* begin pushLiteralVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer1 = foo->method; oop2 = longAt((methodPointer1 + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); object3 = longAt((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object3); goto l1; } } ; l1: /* end case */; break; case 129: /* extendedStoreBytecode */ { sqInt association; sqInt descriptor; sqInt variableIndex; sqInt variableType; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt valuePointer1; sqInt methodPointer; sqInt valuePointer2; descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin storePointer:ofObject:withValue: */ oop = foo->receiver; valuePointer = longAtPointer(localSP); if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, valuePointer); } longAtput((oop + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD)), valuePointer); goto l2; } if (variableType == 1) { /* begin storePointerUnchecked:ofObject:withValue: */ oop1 = localHomeContext; valuePointer1 = longAtPointer(localSP); longAtput((oop1 + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD)), valuePointer1); goto l2; } if (variableType == 2) { error("illegal store"); } if (variableType == 3) { /* begin literal:ofMethod: */ methodPointer = foo->method; association = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAtPointer(localSP); if ((((usqInt) association)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(association, valuePointer2); } longAtput((association + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), valuePointer2); goto l2; } } ; l2: /* end case */; break; case 130: /* extendedStoreAndPopBytecode */ { sqInt association; sqInt descriptor; sqInt variableIndex; sqInt variableType; sqInt oop; sqInt valuePointer; sqInt oop1; sqInt valuePointer1; sqInt methodPointer; sqInt valuePointer2; /* begin extendedStoreBytecode */ descriptor = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); variableType = (((usqInt) descriptor) >> 6) & 3; variableIndex = descriptor & 63; if (variableType == 0) { /* begin storePointer:ofObject:withValue: */ oop = foo->receiver; valuePointer = longAtPointer(localSP); if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, valuePointer); } longAtput((oop + (BASE_HEADER_SIZE)) + (variableIndex << (SHIFT_FOR_WORD)), valuePointer); goto l3; } if (variableType == 1) { /* begin storePointerUnchecked:ofObject:withValue: */ oop1 = localHomeContext; valuePointer1 = longAtPointer(localSP); longAtput((oop1 + (BASE_HEADER_SIZE)) + ((variableIndex + TempFrameStart) << (SHIFT_FOR_WORD)), valuePointer1); goto l3; } if (variableType == 2) { error("illegal store"); } if (variableType == 3) { /* begin literal:ofMethod: */ methodPointer = foo->method; association = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((variableIndex + LiteralStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAtPointer(localSP); if ((((usqInt) association)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(association, valuePointer2); } longAtput((association + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), valuePointer2); goto l3; } l3: /* end extendedStoreBytecode */; /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 131: /* singleExtendedSendBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 31) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 5; /* goto normalSend */ } ; normalSend: /* normalSend */ { sqInt rcvr; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; rcvr = longAtPointer(localSP - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->lkupClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l44; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { foo->lkupClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l44; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); foo->lkupClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l44; } l44: /* end fetchClassOf: */; foo->receiverClass = foo->lkupClass; /* goto commonSend */ } ; commonSend: /* commonSend */ { sqInt ok; sqInt hash; sqInt probe; sqInt delta; sqInt localPrimIndex; sqInt nArgs; sqInt oop; sqInt oop1; sqInt argCount2; sqInt i; sqInt methodHeader; sqInt needsLarge; sqInt newContext; sqInt tempCount; sqInt where; sqInt methodPointer; sqInt activeCntx; sqInt valuePointer; sqInt valuePointer1; sqInt tmp; /* begin internalFindNewMethod */ /* begin lookupInMethodCacheSel:class: */ hash = foo->messageSelector ^ foo->lkupClass; probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == foo->messageSelector) && ((foo->methodCache[probe + MethodCacheClass]) == foo->lkupClass)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); ok = 1; goto l45; } ok = 0; l45: /* end lookupInMethodCacheSel:class: */; if (!(ok)) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; lookupMethodInClass(foo->lkupClass); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; addNewMethodToCache(); } /* begin internalExecuteNewMethod */ localPrimIndex = foo->primitiveIndex; if (localPrimIndex > 0) { if ((localPrimIndex > 255) && (localPrimIndex < 520)) { if (localPrimIndex >= 264) { /* begin internalPop:thenPush: */ /* begin fetchPointer:ofObject: */ oop1 = longAtPointer(localSP); oop = longAt((oop1 + (BASE_HEADER_SIZE)) + ((localPrimIndex - 264) << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); goto l46; } else { if (localPrimIndex == 256) { goto l46; } if (localPrimIndex == 257) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->trueObj); goto l46; } if (localPrimIndex == 258) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->falseObj); goto l46; } if (localPrimIndex == 259) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), foo->nilObj); goto l46; } /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), (((localPrimIndex - 261) << 1) | 1)); goto l46; } } else { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; if (DoBalanceChecks) { nArgs = foo->argumentCount; delta = foo->stackPointer - foo->activeContext; } foo->successFlag = 1; dispatchFunctionPointer(foo->primitiveFunctionPointer); if (DoBalanceChecks) { if (!(balancedStackafterPrimitivewithArgs(delta, localPrimIndex, nArgs))) { printUnbalancedStack(localPrimIndex); } } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { browserPluginReturnIfNeeded(); goto l46; } } } /* begin internalActivateNewMethod */ /* begin headerOf: */ methodPointer = foo->newMethod; methodHeader = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); needsLarge = methodHeader & LargeContextBit; if ((needsLarge == 0) && (foo->freeContexts != NilContext)) { newContext = foo->freeContexts; foo->freeContexts = longAt((newContext + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); } else { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; newContext = allocateOrRecycleContext(needsLarge); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } tempCount = (((usqInt) methodHeader) >> 19) & 63; where = newContext + (BASE_HEADER_SIZE); longAtput(where + (SenderIndex << (SHIFT_FOR_WORD)), foo->activeContext); longAtput(where + (InstructionPointerIndex << (SHIFT_FOR_WORD)), (((((LiteralStart + ((((usqInt) methodHeader) >> 10) & 255)) * (BYTES_PER_WORD)) + 1) << 1) | 1)); longAtput(where + (StackPointerIndex << (SHIFT_FOR_WORD)), ((tempCount << 1) | 1)); longAtput(where + (MethodIndex << (SHIFT_FOR_WORD)), foo->newMethod); longAtput(where + (ClosureIndex << (SHIFT_FOR_WORD)), foo->nilObj); argCount2 = foo->argumentCount; for (i = 0; i <= argCount2; i += 1) { longAtput(where + ((ReceiverIndex + i) << (SHIFT_FOR_WORD)), longAtPointer(localSP - ((argCount2 - i) * (BYTES_PER_WORD)))); } methodHeader = foo->nilObj; for (i = ((argCount2 + 1) + ReceiverIndex); i <= (tempCount + ReceiverIndex); i += 1) { longAtput(where + (i << (SHIFT_FOR_WORD)), methodHeader); } /* begin internalPop: */ localSP -= (argCount2 + 1) * (BYTES_PER_WORD); foo->reclaimableContextCount += 1; /* begin internalNewActiveContext: */ /* begin internalStoreContextRegisters: */ activeCntx = foo->activeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = (((((oopForPointer(localIP)) + 2) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = (((((((usqInt) ((oopForPointer(localSP)) - (activeCntx + (BASE_HEADER_SIZE)))) >> (SHIFT_FOR_WORD)) - TempFrameStart) + 1) << 1) | 1); longAtput((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), valuePointer1); if ((((usqInt) newContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(newContext); } foo->activeContext = newContext; /* begin internalFetchContextRegisters: */ tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = newContext; } localHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localIP = pointerForOop(((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2); tmp = ((longAt((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); localSP = pointerForOop((newContext + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD))); /* begin internalQuickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; checkForInterrupts(); browserPluginReturnIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } l46: /* end internalExecuteNewMethod */; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; break; case 132: /* doubleExtendedDoAnythingBytecode */ { sqInt byte2; sqInt byte3; sqInt opType; sqInt top; sqInt methodPointer; sqInt methodPointer1; sqInt oop; sqInt oop1; sqInt oop2; sqInt object; sqInt oop3; sqInt methodPointer2; sqInt object1; sqInt methodPointer3; sqInt object2; sqInt oop4; sqInt methodPointer4; byte2 = byteAtPointer(++localIP); byte3 = byteAtPointer(++localIP); opType = ((usqInt) byte2) >> 5; if (opType == 0) { /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = byte2 & 31; goto normalSend; goto l4; } if (opType == 1) { /* begin literal:ofMethod: */ methodPointer1 = foo->method; foo->messageSelector = longAt((methodPointer1 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = byte2 & 31; goto commonSupersend; goto l4; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (opType == 2) { /* begin pushReceiverVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ oop3 = foo->receiver; object = longAt((oop3 + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); goto l4; } if (opType == 3) { /* begin pushLiteralConstant: */ /* begin internalPush: */ /* begin literal:ofMethod: */ methodPointer3 = foo->method; object1 = longAt((methodPointer3 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object1); goto l4; } if (opType == 4) { /* begin pushLiteralVariable: */ /* begin internalPush: */ /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ methodPointer4 = foo->method; oop4 = longAt((methodPointer4 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); object2 = longAt((oop4 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object2); goto l4; } if (opType == 5) { top = longAtPointer(localSP); /* begin storePointer:ofObject:withValue: */ oop = foo->receiver; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, top); } longAtput((oop + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD)), top); goto l4; } if (opType == 6) { top = longAtPointer(localSP); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); /* begin storePointer:ofObject:withValue: */ oop1 = foo->receiver; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, top); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (byte3 << (SHIFT_FOR_WORD)), top); goto l4; } if (opType == 7) { top = longAtPointer(localSP); /* begin storePointer:ofObject:withValue: */ /* begin literal:ofMethod: */ methodPointer2 = foo->method; oop2 = longAt((methodPointer2 + (BASE_HEADER_SIZE)) + ((byte3 + LiteralStart) << (SHIFT_FOR_WORD))); if ((((usqInt) oop2)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop2, top); } longAtput((oop2 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD)), top); goto l4; } } ; l4: /* end case */; break; case 133: /* singleExtendedSuperBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 31) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 5; /* goto commonSupersend */ } ; commonSupersend: /* superclassSend */ { sqInt rcvr; sqInt classPointer; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt methodPointer; sqInt oop3; sqInt offset; /* begin superclassOf: */ /* begin methodClassOf: */ methodPointer = foo->method; /* begin fetchPointer:ofObject: */ /* begin literal:ofMethod: */ offset = (literalCountOfHeader(longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) - 1; oop3 = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); classPointer = longAt((oop3 + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); foo->lkupClass = longAt((classPointer + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); rcvr = longAtPointer(localSP - (foo->argumentCount * (BYTES_PER_WORD))); /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->receiverClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l47; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { foo->receiverClass = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l47; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); foo->receiverClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l47; } l47: /* end fetchClassOf: */; goto commonSend; } ; break; case 134: /* secondExtendedSendBytecode */ { sqInt descriptor; sqInt methodPointer; descriptor = byteAtPointer(++localIP); /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + (((descriptor & 63) + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((usqInt) descriptor) >> 6; goto normalSend; } ; break; case 135: /* popStackBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 136: /* duplicateTopBytecode */ { sqInt object; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ object = longAtPointer(localSP); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 137: /* pushActiveContextBytecode */ { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); foo->reclaimableContextCount = 0; /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->activeContext); } ; break; case 138: /* pushNewArrayBytecode */ { sqInt array; sqInt i; sqInt popValues; sqInt size; sqInt valuePointer; size = byteAtPointer(++localIP); popValues = size > 127; size = size & 127; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; array = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), size); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (popValues) { for (i = 0; i <= (size - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAtPointer(localSP - (((size - i) - 1) * (BYTES_PER_WORD))); longAtput((array + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); } /* begin internalPop: */ localSP -= size * (BYTES_PER_WORD); } /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, array); } ; break; case 139: /* unknownBytecode */ { error("Unknown bytecode"); } ; break; case 140: /* pushRemoteTempLongBytecode */ { sqInt remoteTempIndex; sqInt tempVectorIndex; sqInt tempVector; sqInt oop; sqInt object; remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin pushRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin internalPush: */ object = longAt((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP += BYTES_PER_WORD, object); } ; break; case 141: /* storeRemoteTempLongBytecode */ { sqInt remoteTempIndex; sqInt tempVectorIndex; sqInt tempVector; sqInt oop; sqInt valuePointer; remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storeRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer = longAtPointer(localSP); if ((((usqInt) tempVector)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(tempVector, valuePointer); } longAtput((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD)), valuePointer); } ; break; case 142: /* storeAndPopRemoteTempLongBytecode */ { sqInt remoteTempIndex; sqInt tempVectorIndex; sqInt tempVector; sqInt oop; sqInt valuePointer; /* begin storeRemoteTempLongBytecode */ remoteTempIndex = byteAtPointer(++localIP); tempVectorIndex = byteAtPointer(++localIP); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin storeRemoteTemp:inVectorAt: */ /* begin fetchPointer:ofObject: */ oop = localHomeContext; tempVector = longAt((oop + (BASE_HEADER_SIZE)) + ((tempVectorIndex + TempFrameStart) << (SHIFT_FOR_WORD))); /* begin storePointer:ofObject:withValue: */ valuePointer = longAtPointer(localSP); if ((((usqInt) tempVector)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(tempVector, valuePointer); } longAtput((tempVector + (BASE_HEADER_SIZE)) + (remoteTempIndex << (SHIFT_FOR_WORD)), valuePointer); /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); } ; break; case 143: /* pushClosureCopyCopiedValuesBytecode */ { sqInt blockSize; sqInt i; sqInt newClosure; sqInt numArgs; sqInt numArgsNumCopied; sqInt numCopied; sqInt valuePointer; sqInt initialIP; sqInt newClosure1; sqInt valuePointer1; if ((BYTES_PER_WORD) == 4) { imageFormatVersionNumber = 6504; } else { imageFormatVersionNumber = 68002; } numArgsNumCopied = byteAtPointer(++localIP); numArgs = numArgsNumCopied & 15; numCopied = ((usqInt) numArgsNumCopied >> 4); blockSize = (byteAtPointer(++localIP)) << 8; blockSize += byteAtPointer(++localIP); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin closureNumArgs:instructionPointer:numCopiedValues: */ initialIP = ((oopForPointer(localIP)) + 2) - (foo->method + (BASE_HEADER_SIZE)); newClosure1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop), ((BYTES_PER_WORD) * (ClosureFirstCopiedValueIndex + numCopied)) + (BASE_HEADER_SIZE)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)), ((numArgs << 1) | 1)); newClosure = newClosure1; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->activeContext; longAtput((newClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD)), valuePointer1); foo->reclaimableContextCount = 0; if (numCopied > 0) { for (i = 0; i <= (numCopied - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAtPointer(localSP - (((numCopied - i) - 1) * (BYTES_PER_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)), valuePointer); } /* begin internalPop: */ localSP -= numCopied * (BYTES_PER_WORD); } localIP += blockSize; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, newClosure); } ; break; case 144: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (144 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 145: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (145 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 146: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (146 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 147: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (147 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 148: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (148 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 149: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (149 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 150: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (150 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 151: /* shortUnconditionalJump */ { sqInt offset; /* begin jump: */ offset = (151 & 7) + 1; localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } ; break; case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: /* shortConditionalJump */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfFalseBy: */ offset = (currentBytecode & 7) + 1; boolean = longAtPointer(localSP); if (boolean == foo->falseObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->trueObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l5; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l5: /* end jumplfFalseBy: */; } ; break; case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: /* longUnconditionalJump */ { sqInt offset; offset = (((currentBytecode & 7) - 4) * 256) + (byteAtPointer(++localIP)); localIP += offset; if (offset < 0) { /* begin internalQuickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; checkForInterrupts(); browserPluginReturnIfNeeded(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; break; case 168: case 169: case 170: case 171: /* longJumpIfTrue */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfTrueBy: */ offset = ((currentBytecode & 3) * 256) + (byteAtPointer(++localIP)); boolean = longAtPointer(localSP); if (boolean == foo->trueObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->falseObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l6; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l6: /* end jumplfTrueBy: */; } ; break; case 172: case 173: case 174: case 175: /* longJumpIfFalse */ { sqInt offset; sqInt boolean; sqInt oop; /* begin jumplfFalseBy: */ offset = ((currentBytecode & 3) * 256) + (byteAtPointer(++localIP)); boolean = longAtPointer(localSP); if (boolean == foo->falseObj) { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); } else { if (!(boolean == foo->trueObj)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorMustBeBoolean << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; goto l7; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } /* begin internalPop: */ localSP -= 1 * (BYTES_PER_WORD); l7: /* end jumplfFalseBy: */; } ; break; case 176: /* bytecodePrimAdd */ { sqInt arg; sqInt rcvr; sqInt result; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { result = ((rcvr >> 1)) + ((arg >> 1)); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l8; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatAddtoArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l8; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((0 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l8: /* end case */; break; case 177: /* bytecodePrimSubtract */ { sqInt arg; sqInt rcvr; sqInt result; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { result = ((rcvr >> 1)) - ((arg >> 1)); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l9; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatSubtractfromArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l9; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((1 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l9: /* end case */; break; case 178: /* bytecodePrimLessThan */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr < arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr < arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr < arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l10; } foo->successFlag = 1; aBool = primitiveFloatLessthanArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l10; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l10; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l10; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((2 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l10: /* end case */; break; case 179: /* bytecodePrimGreaterThan */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr > arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr > arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr > arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l11; } foo->successFlag = 1; aBool = primitiveFloatGreaterthanArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l11; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l11; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l11; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((3 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l11: /* end case */; break; case 180: /* bytecodePrimLessOrEqual */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr <= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr <= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr <= arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l12; } foo->successFlag = 1; aBool = primitiveFloatLessOrEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l12; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l12; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l12; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((4 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l12: /* end case */; break; case 181: /* bytecodePrimGreaterOrEqual */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt bytecode2; sqInt offset2; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { ; /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (rcvr >= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (rcvr >= arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr >= arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l13; } foo->successFlag = 1; aBool = primitiveFloatGreaterOrEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode2 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode2 < 160) && (bytecode2 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + (bytecode2 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } if (bytecode2 == 172) { offset2 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l13; } else { /* begin jump: */ localIP = (localIP + offset2) + 1; currentBytecode = byteAtPointer(localIP); goto l13; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l13; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((5 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l13: /* end case */; break; case 182: /* bytecodePrimEqual */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr == arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l14; } foo->successFlag = 1; aBool = primitiveFloatEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l14; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l14; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l14; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((6 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l14: /* end case */; break; case 183: /* bytecodePrimNotEqual */ { sqInt aBool; sqInt arg; sqInt rcvr; sqInt oop; sqInt bytecode; sqInt offset; sqInt bytecode1; sqInt offset1; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr != arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr != arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr != arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l15; } foo->successFlag = 1; aBool = primitiveFloatEqualtoArg(rcvr, arg); if (foo->successFlag) { /* begin booleanCheat: */ bytecode1 = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode1 < 160) && (bytecode1 > 151)) { if (!aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + (bytecode1 - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } if (bytecode1 == 172) { offset1 = byteAtPointer(++localIP); if (!aBool) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l15; } else { /* begin jump: */ localIP = (localIP + offset1) + 1; currentBytecode = byteAtPointer(localIP); goto l15; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (!aBool) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } goto l15; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((7 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l15: /* end case */; break; case 184: /* bytecodePrimMultiply */ { sqInt arg; sqInt rcvr; sqInt result; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { rcvr = (rcvr >> 1); arg = (arg >> 1); result = rcvr * arg; if (((arg == 0) || ((result / arg) == rcvr)) && ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 )) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l16; } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatMultiplybyArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l16; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((8 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l16: /* end case */; break; case 185: /* bytecodePrimDivide */ { sqInt arg; sqInt rcvr; sqInt result; sqInt oop; sqInt oop1; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); if (((rcvr & arg) & 1) != 0) { rcvr = (rcvr >> 1); arg = (arg >> 1); if ((arg != 0) && ((rcvr % arg) == 0)) { result = rcvr / arg; if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) result)) ^ ((((int) result)) << 1)) >= 0) # else ((result >= -1073741824) && (result <= 1073741823)) # endif // SQ_HOST32 ) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l17; } } } else { foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveFloatDividebyArg(rcvr, arg); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l17; } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((9 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l17: /* end case */; break; case 186: /* bytecodePrimMod */ { sqInt mod; sqInt oop; sqInt oop1; foo->successFlag = 1; mod = doPrimitiveModby(longAtPointer(localSP - (1 * (BYTES_PER_WORD))), longAtPointer(localSP - (0 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((mod << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l18; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((10 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l18: /* end case */; break; case 187: /* bytecodePrimMakePoint */ { sqInt oop; sqInt oop1; sqInt argument; sqInt pt; sqInt rcvr; sqInt sp; sqInt pointResult; sqInt pointResult1; sqInt valuePointer; sqInt pointResult2; sqInt valuePointer1; sqInt valuePointer2; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveMakePoint */ argument = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((rcvr & 1)) { if ((argument & 1)) { /* begin makePointwithxValue:yValue: */ pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((((argument >> 1)) << 1) | 1)); pt = pointResult; } else { /* begin makePointwithxValue:yValue: */ pointResult1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((((rcvr >> 1)) << 1) | 1)); longAtput((pointResult1 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult1; /* begin storePointer:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer); } } else { if (!((fetchClassOf(rcvr)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; goto l20; } /* begin makePointwithxValue:yValue: */ pointResult2 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); longAtput((pointResult2 + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); pt = pointResult2; /* begin storePointer:ofObject:withValue: */ valuePointer1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer1); } longAtput((pt + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), valuePointer1); /* begin storePointer:ofObject:withValue: */ valuePointer2 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((((usqInt) pt)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(pt, valuePointer2); } longAtput((pt + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), valuePointer2); } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), pt); foo->stackPointer = sp; l20: /* end primitiveMakePoint */; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l19; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((11 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l19: /* end case */; break; case 188: /* bytecodePrimBitShift */ { sqInt oop; sqInt oop1; sqInt integerArgument; sqInt integerReceiver; sqInt shifted; sqInt top; sqInt object; sqInt sp; sqInt top1; sqInt integerPointer; sqInt top2; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitShift */ /* begin popInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top2; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l22; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l22; } integerArgument = null; l22: /* end popInteger */; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerReceiver = positive32BitValueOf(top); if (foo->successFlag) { if (integerArgument >= 0) { /* begin success: */ foo->successFlag = (integerArgument <= 31) && foo->successFlag; shifted = integerReceiver << integerArgument; /* begin success: */ foo->successFlag = ((((usqInt) shifted) >> integerArgument) == integerReceiver) && foo->successFlag; } else { /* begin success: */ foo->successFlag = (integerArgument >= -31) && foo->successFlag; shifted = ((integerArgument < 0) ? ((usqInt) integerReceiver >> -integerArgument) : ((usqInt) integerReceiver << integerArgument)); } } if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(shifted); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l21; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((12 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l21: /* end case */; break; case 189: /* bytecodePrimDiv */ { sqInt quotient; sqInt oop; sqInt oop1; foo->successFlag = 1; quotient = doPrimitiveDivby(longAtPointer(localSP - (1 * (BYTES_PER_WORD))), longAtPointer(localSP - (0 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), ((quotient << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l23; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((13 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l23: /* end case */; break; case 190: /* bytecodePrimBitAnd */ { sqInt oop; sqInt integerArgument; sqInt integerReceiver; sqInt top; sqInt top1; sqInt object; sqInt sp; sqInt top2; sqInt top3; sqInt oop1; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitAnd */ /* begin popPos32BitInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top2; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top3 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top1 = top3; integerReceiver = positive32BitValueOf(top1); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver & integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l24; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((14 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l24: /* end case */; break; case 191: /* bytecodePrimBitOr */ { sqInt oop; sqInt integerArgument; sqInt integerReceiver; sqInt top; sqInt top1; sqInt object; sqInt sp; sqInt top2; sqInt top3; sqInt oop1; foo->successFlag = 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBitOr */ /* begin popPos32BitInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top2; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top3 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top1 = top3; integerReceiver = positive32BitValueOf(top1); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver | integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l25; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((15 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l25: /* end case */; break; case 192: /* bytecodePrimAt */ { sqInt atIx; sqInt index; sqInt rcvr; sqInt result; sqInt oop; sqInt oop1; sqInt fixedFields; sqInt fmt; sqInt result1; sqInt stSize; sqInt oop2; sqInt oop11; index = longAtPointer(localSP); rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->successFlag = (!((rcvr & 1))) && ((index & 1)); if (foo->successFlag) { atIx = rcvr & AtCacheMask; if ((foo->atCache[atIx + AtCacheOop]) == rcvr) { /* begin commonVariableInternal:at:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) ((index >> 1)))) >= (((usqInt) 1))) && ((((usqInt) ((index >> 1)))) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; result = longAt((rcvr + (BASE_HEADER_SIZE)) + (((((index >> 1)) + fixedFields) - 1) << (SHIFT_FOR_WORD))); goto l27; } if (fmt < 8) { result1 = long32At((rcvr + (BASE_HEADER_SIZE)) + ((((index >> 1)) - 1) << 2)); /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; result1 = positive32BitIntegerFor(result1); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; result = result1; goto l27; } if (fmt >= 16) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop11 = foo->specialObjectsOop; oop2 = longAt((oop11 + (BASE_HEADER_SIZE)) + (CharacterTable << (SHIFT_FOR_WORD))); result = longAt((oop2 + (BASE_HEADER_SIZE)) + ((byteAt((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1))) << (SHIFT_FOR_WORD))); goto l27; } else { result = (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1))) << 1) | 1); goto l27; } } /* begin primitiveFail */ foo->successFlag = 0; l27: /* end commonVariableInternal:at:cacheIndex: */; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (2 - 1) * (BYTES_PER_WORD), result); goto l26; } } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((16 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; l26: /* end case */; break; case 193: /* bytecodePrimAtPut */ { sqInt atIx; sqInt index; sqInt rcvr; sqInt value; sqInt oop; sqInt oop1; sqInt fixedFields; sqInt fmt; sqInt stSize; sqInt valToPut; value = longAtPointer(localSP); index = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); rcvr = longAtPointer(localSP - (2 * (BYTES_PER_WORD))); foo->successFlag = (!((rcvr & 1))) && ((index & 1)); if (foo->successFlag) { atIx = (rcvr & AtCacheMask) + AtPutBase; if ((foo->atCache[atIx + AtCacheOop]) == rcvr) { /* begin commonVariable:at:put:cacheIndex: */ stSize = foo->atCache[atIx + AtCacheSize]; if (((((usqInt) ((index >> 1)))) >= (((usqInt) 1))) && ((((usqInt) ((index >> 1)))) <= (((usqInt) stSize)))) { fmt = foo->atCache[atIx + AtCacheFmt]; if (fmt <= 4) { fixedFields = foo->atCache[atIx + AtCacheFixedFields]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, value); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (((((index >> 1)) + fixedFields) - 1) << (SHIFT_FOR_WORD)), value); goto l29; } if (fmt < 8) { valToPut = positive32BitValueOf(value); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((((index >> 1)) - 1) << 2), valToPut); } goto l29; } if (fmt >= 16) { valToPut = asciiOfCharacter(value); if (!(foo->successFlag)) { goto l29; } } else { valToPut = value; } if ((valToPut & 1)) { valToPut = (valToPut >> 1); if (!((valToPut >= 0) && (valToPut <= 255))) { /* begin primitiveFail */ foo->successFlag = 0; goto l29; } byteAtput((rcvr + (BASE_HEADER_SIZE)) + (((index >> 1)) - 1), valToPut); goto l29; } } /* begin primitiveFail */ foo->successFlag = 0; l29: /* end commonVariable:at:put:cacheIndex: */; if (foo->successFlag) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); /* begin internalPop:thenPush: */ longAtPointerput(localSP -= (3 - 1) * (BYTES_PER_WORD), value); goto l28; } } } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((17 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 2; goto normalSend; } ; l28: /* end case */; break; case 194: /* bytecodePrimSize */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((18 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; break; case 195: /* bytecodePrimNext */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((19 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; break; case 196: /* bytecodePrimNextPut */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((20 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; break; case 197: /* bytecodePrimAtEnd */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((21 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; break; case 198: /* bytecodePrimEquivalent */ { sqInt arg; sqInt rcvr; sqInt bytecode; sqInt offset; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); arg = longAtPointer(localSP - (0 * (BYTES_PER_WORD))); /* begin booleanCheat: */ bytecode = byteAtPointer(++localIP); /* begin internalPop: */ localSP -= 2 * (BYTES_PER_WORD); if ((bytecode < 160) && (bytecode > 151)) { if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l30; } else { /* begin jump: */ localIP = (localIP + (bytecode - 151)) + 1; currentBytecode = byteAtPointer(localIP); goto l30; } } if (bytecode == 172) { offset = byteAtPointer(++localIP); if (rcvr == arg) { /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l30; } else { /* begin jump: */ localIP = (localIP + offset) + 1; currentBytecode = byteAtPointer(localIP); goto l30; } } localIP -= 1; /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); if (rcvr == arg) { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->trueObj); } else { /* begin internalPush: */ longAtPointerput(localSP += BYTES_PER_WORD, foo->falseObj); } l30: /* end booleanCheat: */; } ; break; case 199: /* bytecodePrimClass */ { sqInt rcvr; sqInt oop; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; rcvr = longAtPointer(localSP); /* begin internalPop:thenPush: */ /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l31; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { oop = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l31; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l31; } l31: /* end fetchClassOf: */; longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; break; case 200: /* bytecodePrimBlockCopy */ { sqInt hdr; sqInt rcvr; sqInt oop; sqInt successValue; sqInt oop1; sqInt context; sqInt contextSize; sqInt initialIP; sqInt methodContext; sqInt newContext; sqInt header; sqInt oop2; sqInt valuePointer; sqInt valuePointer1; sqInt sp; rcvr = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->successFlag = 1; hdr = longAt(rcvr); /* begin success: */ successValue = (((((usqInt) hdr) >> 12) & 31) == 13) || ((((((usqInt) hdr) >> 12) & 31) == 14) || (((((usqInt) hdr) >> 12) & 31) == 4)); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; /* begin primitiveBlockCopy */ context = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (((longAt((context + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))) & 1)) { methodContext = longAt((context + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); } else { methodContext = context; } /* begin sizeBitsOf: */ header = longAt(methodContext); if ((header & TypeMask) == HeaderTypeSizeAndClass) { contextSize = (longAt(methodContext - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l33; } else { contextSize = header & (SIZE_MASK); goto l33; } l33: /* end sizeBitsOf: */; context = null; /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = methodContext; newContext = instantiateContextsizeInBytes(fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop), contextSize); /* begin popRemappableOop */ oop2 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; methodContext = oop2; initialIP = (((((foo->instructionPointer + 1) + 3) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((newContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD)), initialIP); longAtput((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ longAtput((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); longAtput((newContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD)), valuePointer); longAtput((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD)), methodContext); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->nilObj; longAtput((newContext + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), valuePointer1); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), newContext); foo->stackPointer = sp; /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((24 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; goto l32; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l32: /* end case */; break; case 201: /* bytecodePrimValue */ { sqInt maybeBlock; sqInt rcvrClass; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; maybeBlock = longAtPointer(localSP); foo->argumentCount = 0; foo->successFlag = 1; if ((maybeBlock & 1) == 0) { /* begin fetchClassOfNonInt: */ ccIndex = (((usqInt) (longAt(maybeBlock))) >> 12) & 31; if (ccIndex == 0) { rcvrClass = (longAt(maybeBlock - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l35; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop1 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); rcvrClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l35; } l35: /* end fetchClassOfNonInt: */; if (rcvrClass == (fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveClosureValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { if (rcvrClass == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { foo->successFlag = 0; } } } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((25 * 2) << (SHIFT_FOR_WORD))); goto normalSend; goto l34; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l34: /* end case */; break; case 202: /* bytecodePrimValueWithArg */ { sqInt maybeBlock; sqInt rcvrClass; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; maybeBlock = longAtPointer(localSP - (1 * (BYTES_PER_WORD))); foo->argumentCount = 1; foo->successFlag = 1; if ((maybeBlock & 1) == 0) { /* begin fetchClassOfNonInt: */ ccIndex = (((usqInt) (longAt(maybeBlock))) >> 12) & 31; if (ccIndex == 0) { rcvrClass = (longAt(maybeBlock - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l37; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop1 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); rcvrClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l37; } l37: /* end fetchClassOfNonInt: */; if (rcvrClass == (fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveClosureValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { if (rcvrClass == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop))) { /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; primitiveValue(); /* begin internalizeIPandSP */ localIP = pointerForOop(foo->instructionPointer); localSP = pointerForOop(foo->stackPointer); localHomeContext = foo->theHomeContext; } else { foo->successFlag = 0; } } } if (!(foo->successFlag)) { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((26 * 2) << (SHIFT_FOR_WORD))); goto normalSend; goto l36; } /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); } ; l36: /* end case */; break; case 203: /* bytecodePrimDo */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((27 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; break; case 204: /* bytecodePrimNew */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((28 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; break; case 205: /* bytecodePrimNewWithArg */ { sqInt oop; sqInt oop1; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + ((29 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 1; goto normalSend; } ; break; case 206: /* bytecodePrimPointX */ { sqInt rcvr; sqInt oop; sqInt oop1; sqInt oop2; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop11; sqInt oop21; sqInt oop3; foo->successFlag = 1; rcvr = longAtPointer(localSP); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); if ((rcvr & 1)) { foo->successFlag = 0; goto l39; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l39: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin internalPop:thenPush: */ oop = longAt((rcvr + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l38; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + ((30 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; l38: /* end case */; break; case 207: /* bytecodePrimPointY */ { sqInt rcvr; sqInt oop; sqInt oop1; sqInt oop2; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop11; sqInt oop21; sqInt oop3; foo->successFlag = 1; rcvr = longAtPointer(localSP); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassPoint << (SHIFT_FOR_WORD))); if ((rcvr & 1)) { foo->successFlag = 0; goto l41; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop21 = foo->specialObjectsOop; oop11 = longAt((oop21 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop11 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l41: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin internalPop:thenPush: */ oop = longAt((rcvr + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD))); longAtPointerput(localSP -= (1 - 1) * (BYTES_PER_WORD), oop); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP); goto l40; } /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (SpecialSelectors << (SHIFT_FOR_WORD))); foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + ((31 * 2) << (SHIFT_FOR_WORD))); foo->argumentCount = 0; goto normalSend; } ; l40: /* end case */; break; case 208: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 208 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 208) >> 4) & 3) - 1; goto normalSend; } ; break; case 209: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 209 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 209) >> 4) & 3) - 1; goto normalSend; } ; break; case 210: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 210 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 210) >> 4) & 3) - 1; goto normalSend; } ; break; case 211: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 211 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 211) >> 4) & 3) - 1; goto normalSend; } ; break; case 212: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 212 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 212) >> 4) & 3) - 1; goto normalSend; } ; break; case 213: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 213 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 213) >> 4) & 3) - 1; goto normalSend; } ; break; case 214: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 214 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 214) >> 4) & 3) - 1; goto normalSend; } ; break; case 215: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 215 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 215) >> 4) & 3) - 1; goto normalSend; } ; break; case 216: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 216 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 216) >> 4) & 3) - 1; goto normalSend; } ; break; case 217: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 217 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 217) >> 4) & 3) - 1; goto normalSend; } ; break; case 218: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 218 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 218) >> 4) & 3) - 1; goto normalSend; } ; break; case 219: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 219 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 219) >> 4) & 3) - 1; goto normalSend; } ; break; case 220: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 220 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 220) >> 4) & 3) - 1; goto normalSend; } ; break; case 221: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 221 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 221) >> 4) & 3) - 1; goto normalSend; } ; break; case 222: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 222 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 222) >> 4) & 3) - 1; goto normalSend; } ; break; case 223: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 223 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 223) >> 4) & 3) - 1; goto normalSend; } ; break; case 224: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 224 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 224) >> 4) & 3) - 1; goto normalSend; } ; break; case 225: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 225 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 225) >> 4) & 3) - 1; goto normalSend; } ; break; case 226: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 226 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 226) >> 4) & 3) - 1; goto normalSend; } ; break; case 227: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 227 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 227) >> 4) & 3) - 1; goto normalSend; } ; break; case 228: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 228 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 228) >> 4) & 3) - 1; goto normalSend; } ; break; case 229: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 229 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 229) >> 4) & 3) - 1; goto normalSend; } ; break; case 230: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 230 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 230) >> 4) & 3) - 1; goto normalSend; } ; break; case 231: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 231 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 231) >> 4) & 3) - 1; goto normalSend; } ; break; case 232: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 232 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 232) >> 4) & 3) - 1; goto normalSend; } ; break; case 233: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 233 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 233) >> 4) & 3) - 1; goto normalSend; } ; break; case 234: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 234 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 234) >> 4) & 3) - 1; goto normalSend; } ; break; case 235: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 235 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 235) >> 4) & 3) - 1; goto normalSend; } ; break; case 236: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 236 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 236) >> 4) & 3) - 1; goto normalSend; } ; break; case 237: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 237 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 237) >> 4) & 3) - 1; goto normalSend; } ; break; case 238: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 238 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 238) >> 4) & 3) - 1; goto normalSend; } ; break; case 239: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 239 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 239) >> 4) & 3) - 1; goto normalSend; } ; break; case 240: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 240 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 240) >> 4) & 3) - 1; goto normalSend; } ; break; case 241: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 241 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 241) >> 4) & 3) - 1; goto normalSend; } ; break; case 242: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 242 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 242) >> 4) & 3) - 1; goto normalSend; } ; break; case 243: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 243 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 243) >> 4) & 3) - 1; goto normalSend; } ; break; case 244: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 244 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 244) >> 4) & 3) - 1; goto normalSend; } ; break; case 245: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 245 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 245) >> 4) & 3) - 1; goto normalSend; } ; break; case 246: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 246 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 246) >> 4) & 3) - 1; goto normalSend; } ; break; case 247: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 247 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 247) >> 4) & 3) - 1; goto normalSend; } ; break; case 248: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 248 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 248) >> 4) & 3) - 1; goto normalSend; } ; break; case 249: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 249 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 249) >> 4) & 3) - 1; goto normalSend; } ; break; case 250: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 250 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 250) >> 4) & 3) - 1; goto normalSend; } ; break; case 251: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 251 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 251) >> 4) & 3) - 1; goto normalSend; } ; break; case 252: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 252 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 252) >> 4) & 3) - 1; goto normalSend; } ; break; case 253: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 253 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 253) >> 4) & 3) - 1; goto normalSend; } ; break; case 254: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 254 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 254) >> 4) & 3) - 1; goto normalSend; } ; break; case 255: /* sendLiteralSelectorBytecode */ { sqInt offset; sqInt methodPointer; /* begin literal: */ offset = 255 & 15; /* begin literal:ofMethod: */ methodPointer = foo->method; foo->messageSelector = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); foo->argumentCount = ((((usqInt) 255) >> 4) & 3) - 1; goto normalSend; } ; break; } } /* undo the pre-increment of IP before returning */ localIP -= 1; /* begin externalizeIPandSP */ foo->instructionPointer = oopForPointer(localIP); foo->stackPointer = oopForPointer(localSP); foo->theHomeContext = localHomeContext; } /* the vm has to convert aFilenameString via any canonicalization and char-mapping and put the result in aCharBuffer. Note the resolveAliases flag - this is an awful artefact of OSX and Apples demented alias handling. When opening a file, the flag must be true, when closing or renaming it must be false. Sigh. */ sqInt ioFilenamefromStringofLengthresolveAliases(char *aCharBuffer, char *aFilenameString, sqInt filenameLength, sqInt aBoolean) { sqGetFilenameFromString(aCharBuffer, aFilenameString, filenameLength, aBoolean); } /* Support for external primitives. */ sqInt isKindOf(sqInt oop, char *className) { register struct foo * foo = &fum; sqInt oopClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oopClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { oopClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oopClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; while (!(oopClass == foo->nilObj)) { if (classNameOfIs(oopClass, className)) { return 1; } oopClass = longAt((oopClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } return 0; } /* Support for external primitives */ sqInt isMemberOf(sqInt oop, char *className) { register struct foo * foo = &fum; sqInt oopClass; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oopClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { oopClass = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oopClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; return classNameOfIs(oopClass, className); } /* Answer true if this is an indexable object with pointer elements, e.g., an array */ sqInt isArray(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 2); } /* Answer true (non-zero) if running on a big endian machine. */ sqInt isBigEnder(void) { sqInt anInt; char *cString; static sqInt endianness = -1; sqInt i; sqInt len; if (!(endianness == -1)) { return endianness; } len = sizeof(anInt); cString = (char *) &anInt; i = 0; while (i < len) { cString[i] = i; i += 1; } endianness = anInt & 255; return endianness; } /* Answer true if the argument contains indexable bytes. See comment in formatOf: */ /* Note: Includes CompiledMethods. */ sqInt isBytes(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8); } /* Answer true if size is greater than (((2 raisedTo: 31) - 1) >> bits). Used to limit size of allocation requests to 31 bit integer maximum to prevent arithmetic overflow in subsequent calculations. Always answers false in interpreter simulation. In the case of a 64-bit object memory running on a 64-bit host platform, allow larger allocation requests. Assumes that sizeof(int) is 4 for all platforms. */ sqInt isExcessiveAllocationRequestshift(sqInt size, sqInt bits) { int int32; sqInt int64; sqInt shiftCount; # ifdef SQ_IMAGE64 // a 64-bit object memory word size # ifdef SQ_HOST64 // running on a 64-bit host platform /* use 64 bit check if both image and host are 64 bits */ int64 = size; shiftCount = 0; if (int64 < 0) { return 1; } while (shiftCount < bits) { int64 = int64 << 1; if (int64 < 0) { return 1; } shiftCount += 1; } return 0; # else if (size > 4294967295U) { return 0; } # endif // SQ_HOST64 # else /* common case of 32 bit image on either 32 or 64 bit host */ int32 = size; shiftCount = 0; if (int32 < 0) { return 1; } while (shiftCount < bits) { int32 = int32 << 1; if (int32 < 0) { return 1; } shiftCount += 1; } return 0; # endif // SQ_IMAGE64 } sqInt isFloatObject(sqInt oop) { return (fetchClassOf(oop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop)); } /* Is this a MethodContext whose meth has a primitive number of 199? */ /* NB: the use of a primitive number for marking the method is pretty grungy, but it is simple to use for a test sytem, not too expensive and we don't actually have the two spare method header bits we need. We can probably obtain them when the method format is changed. NB 2: actually, the jitter will probably implement the prim to actually mark the volatile frame by changing the return function pointer. */ sqInt isHandlerMarked(sqInt aContext) { sqInt header; sqInt meth; sqInt pIndex; sqInt primBits; header = longAt(aContext); if (!(((((usqInt) header) >> 12) & 31) == 14)) { return 0; } meth = longAt((aContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); return pIndex == 199; } /* Return true if the given address is in ST object memory */ sqInt isInMemory(sqInt address) { return ((((usqInt) address)) >= (((usqInt) memory))) && ((((usqInt) address)) < (((usqInt) foo->endOfMemory))); } sqInt isIndexable(sqInt oop) { return ((((usqInt) (longAt(oop))) >> 8) & 15) >= 2; } sqInt isIntegerObject(sqInt objectPointer) { return (objectPointer & 1) > 0; } /* Return true if the given value can be represented as a Smalltalk integer value. */ /* Use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits. Operands are coerced to machine integer size so the test will work with 64 bit images on 32 bit hosts. When running on a 32 bit host, the cast to int has little or no performance impact for either 32 bit or 64 bit images. On a 64 bit host, the shift and XOR test is replaced by an explicit range check, which provides the best performance for both 32 bit and 64 bit images. If the range of small integers is enlarged for 64 bit images, this method must be updated accordingly. */ sqInt isIntegerValue(sqInt intValue) { return # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) intValue)) ^ ((((int) intValue)) << 1)) >= 0) # else ((intValue >= -1073741824) && (intValue <= 1073741823)) # endif // SQ_HOST32 ; } /* Answer true if the argument has only fields that can hold oops. See comment in formatOf: */ sqInt isPointers(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) <= 4); } /* Answer true if the argument has only weak fields that can hold oops. See comment in formatOf: */ sqInt isWeak(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 4); } /* Answer true if the argument contains only indexable words (no oops). See comment in formatOf: */ sqInt isWords(sqInt oop) { return ((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) == 6); } /* Answer true if the contains only indexable words or bytes (no oops). See comment in formatOf: */ /* Note: Excludes CompiledMethods. */ sqInt isWordsOrBytes(sqInt oop) { return ((oop & 1) == 0) && (isWordsOrBytesNonInt(oop)); } /* Answer true if the contains only indexable words or bytes (no oops). See comment in formatOf: */ /* Note: Excludes CompiledMethods. */ sqInt isWordsOrBytesNonInt(sqInt oop) { sqInt fmt; fmt = (((usqInt) (longAt(oop))) >> 8) & 15; return (fmt == 6) || ((fmt >= 8) && (fmt <= 11)); } /* Return the byte offset of the last pointer field of the given object. Works with CompiledMethods, as well as ordinary objects. Can be used even when the type bits are not correct. */ sqInt lastPointerOf(sqInt oop) { sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; header = longAt(oop); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; return (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); } /* begin sizeBitsOfSafe: */ header1 = longAt(oop); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l2; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l2; } else { type = HeaderTypeShort; goto l2; } } l2: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l3; } else { sz = header1 & (SIZE_MASK); goto l3; } l3: /* end sizeBitsOfSafe: */; return sz - (BASE_HEADER_SIZE); } if (fmt < 12) { return 0; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); return (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); } /* Return the number of indexable bytes or words in the given object. Assume the argument is not an integer. For a CompiledMethod, the size of the method header (in bytes) should be subtracted from the result. */ sqInt lengthOf(sqInt oop) { sqInt header; sqInt sz; header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); } if (((((usqInt) header) >> 8) & 15) < 8) { return ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; } else { return (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); } return null; } sqInt literalofMethod(sqInt offset, sqInt methodPointer) { return longAt((methodPointer + (BASE_HEADER_SIZE)) + ((offset + LiteralStart) << (SHIFT_FOR_WORD))); } sqInt literalCountOf(sqInt methodPointer) { sqInt headerPointer; /* begin literalCountOfHeader: */ headerPointer = longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))); return (((usqInt) headerPointer) >> 10) & 255; } sqInt literalCountOfHeader(sqInt headerPointer) { return (((usqInt) headerPointer) >> 10) & 255; } /* This entry point needs to be implemented for the interpreter proxy. Since BitBlt is now a plugin we need to look up BitBltPlugin:=loadBitBltFrom and call it. This entire mechanism should eventually go away and be replaced with a dynamic lookup from BitBltPlugin itself but for backward compatibility this stub is provided */ sqInt loadBitBltFrom(sqInt bb) { void *fn; fn = ioLoadFunctionFrom("loadBitBltFrom", "BitBltPlugin"); if (fn == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return ((sqInt (*)(sqInt))fn)(bb); } sqInt loadInitialContext(void) { register struct foo * foo = &fum; sqInt proc; sqInt sched; sqInt oop; sqInt oop1; sqInt activeCntx; sqInt tmp; /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (SchedulerAssociation << (SHIFT_FOR_WORD))); sched = longAt((oop + (BASE_HEADER_SIZE)) + (ValueIndex << (SHIFT_FOR_WORD))); proc = longAt((sched + (BASE_HEADER_SIZE)) + (ActiveProcessIndex << (SHIFT_FOR_WORD))); foo->activeContext = longAt((proc + (BASE_HEADER_SIZE)) + (SuspendedContextIndex << (SHIFT_FOR_WORD))); if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } /* begin fetchContextRegisters: */ activeCntx = foo->activeContext; tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if ((tmp & 1)) { tmp = longAt((activeCntx + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); if ((((usqInt) tmp)) < (((usqInt) foo->youngStart))) { beRootIfOld(tmp); } } else { tmp = activeCntx; } foo->theHomeContext = tmp; foo->receiver = longAt((tmp + (BASE_HEADER_SIZE)) + (ReceiverIndex << (SHIFT_FOR_WORD))); foo->method = longAt((tmp + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->instructionPointer = ((foo->method + tmp) + (BASE_HEADER_SIZE)) - 2; tmp = ((longAt((activeCntx + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)))) >> 1); foo->stackPointer = (activeCntx + (BASE_HEADER_SIZE)) + (((TempFrameStart + tmp) - 1) * (BYTES_PER_WORD)); foo->reclaimableContextCount = 0; } /* This method implements a simple method lookup cache. If an entry for the given selector and class is found in the cache, set the values of 'newMethod' and 'primitiveIndex' and return true. Otherwise, return false. */ /* About the re-probe scheme: The hash is the low bits of the XOR of two large addresses, minus their useless lowest two bits. If a probe doesn't get a hit, the hash is shifted right one bit to compute the next probe, introducing a new randomish bit. The cache is probed CacheProbeMax times before giving up. */ /* WARNING: Since the hash computation is based on the object addresses of the class and selector, we must rehash or flush when compacting storage. We've chosen to flush, since that also saves the trouble of updating the addresses of the objects in the cache. */ sqInt lookupInMethodCacheSelclass(sqInt selector, sqInt class) { register struct foo * foo = &fum; sqInt hash; sqInt probe; /* shift drops two low-order zeros from addresses */ hash = selector ^ class; /* first probe */ probe = hash & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } /* second probe */ probe = (((usqInt) hash) >> 1) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } probe = (((usqInt) hash) >> 2) & MethodCacheMask; if (((foo->methodCache[probe + MethodCacheSelector]) == selector) && ((foo->methodCache[probe + MethodCacheClass]) == class)) { foo->newMethod = foo->methodCache[probe + MethodCacheMethod]; foo->primitiveIndex = foo->methodCache[probe + MethodCachePrim]; foo->newNativeMethod = foo->methodCache[probe + MethodCacheNative]; foo->primitiveFunctionPointer = ((void *) (foo->methodCache[probe + MethodCachePrimFunction])); return 1; } return 0; } sqInt lookupMethodInClass(sqInt class) { register struct foo * foo = &fum; sqInt currentClass; sqInt dictionary; sqInt found; sqInt rclass; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt index; sqInt length; sqInt mask; sqInt methodArray; sqInt nextSelector; sqInt wrapAround; sqInt sz; sqInt methodPointer; sqInt primBits; sqInt header; currentClass = class; while (currentClass != foo->nilObj) { dictionary = longAt((currentClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); if (dictionary == foo->nilObj) { /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = currentClass; createActualMessageTo(class); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; currentClass = oop; /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; foo->messageSelector = longAt((oop1 + (BASE_HEADER_SIZE)) + (SelectorCannotInterpret << (SHIFT_FOR_WORD))); return lookupMethodInClass(longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD)))); } /* begin lookupMethodInDictionary: */ /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(dictionary); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(dictionary - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); mask = (length - SelectorStart) - 1; if ((foo->messageSelector & 1)) { index = (mask & ((foo->messageSelector >> 1))) + SelectorStart; } else { index = (mask & ((((usqInt) (longAt(foo->messageSelector))) >> 17) & 4095)) + SelectorStart; } wrapAround = 0; while (1) { nextSelector = longAt((dictionary + (BASE_HEADER_SIZE)) + (index << (SHIFT_FOR_WORD))); if (nextSelector == foo->nilObj) { found = 0; goto l2; } if (nextSelector == foo->messageSelector) { methodArray = longAt((dictionary + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); foo->newMethod = longAt((methodArray + (BASE_HEADER_SIZE)) + ((index - SelectorStart) << (SHIFT_FOR_WORD))); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); if (foo->primitiveIndex > MaxPrimitiveIndex) { foo->primitiveIndex = 0; } } else { foo->primitiveIndex = 248; } found = 1; goto l2; } index += 1; if (index == length) { if (wrapAround) { found = 0; goto l2; } wrapAround = 1; index = SelectorStart; } } l2: /* end lookupMethodInDictionary: */; if (found) { return foo->methodClass = currentClass; } currentClass = longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } if (foo->messageSelector == (fetchPointerofObject(SelectorDoesNotUnderstand, foo->specialObjectsOop))) { error("Recursive not understood error encountered"); } /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = class; createActualMessageTo(class); /* begin popRemappableOop */ oop2 = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; rclass = oop2; /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; foo->messageSelector = longAt((oop3 + (BASE_HEADER_SIZE)) + (SelectorDoesNotUnderstand << (SHIFT_FOR_WORD))); return lookupMethodInClass(rclass); } /* This method lookup tolerates integers as Dictionary keys to support execution of images in which Symbols have been compacted out */ sqInt lookupMethodInDictionary(sqInt dictionary) { register struct foo * foo = &fum; sqInt index; sqInt length; sqInt mask; sqInt methodArray; sqInt nextSelector; sqInt wrapAround; sqInt sz; sqInt methodPointer; sqInt primBits; sqInt header; /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(dictionary); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(dictionary - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); mask = (length - SelectorStart) - 1; if ((foo->messageSelector & 1)) { index = (mask & ((foo->messageSelector >> 1))) + SelectorStart; } else { index = (mask & ((((usqInt) (longAt(foo->messageSelector))) >> 17) & 4095)) + SelectorStart; } wrapAround = 0; while (1) { nextSelector = longAt((dictionary + (BASE_HEADER_SIZE)) + (index << (SHIFT_FOR_WORD))); if (nextSelector == foo->nilObj) { return 0; } if (nextSelector == foo->messageSelector) { methodArray = longAt((dictionary + (BASE_HEADER_SIZE)) + (MethodArrayIndex << (SHIFT_FOR_WORD))); /* Check if newMethod is a CompiledMethod. */ foo->newMethod = longAt((methodArray + (BASE_HEADER_SIZE)) + ((index - SelectorStart) << (SHIFT_FOR_WORD))); if (((((usqInt) (longAt(foo->newMethod))) >> 8) & 15) >= 12) { /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); if (foo->primitiveIndex > MaxPrimitiveIndex) { /* If primitiveIndex is out of range, set to zero before putting in cache. This is equiv to primFail, and avoids the need to check on every send. */ foo->primitiveIndex = 0; } } else { /* indicate that this is no compiled method - use primitiveInvokeObjectAsMethod */ foo->primitiveIndex = 248; } return 1; } index += 1; if (index == length) { if (wrapAround) { return 0; } wrapAround = 1; index = SelectorStart; } } } /* Lookup. Answer false on failure father than performing MNU processing etc. */ sqInt lookupMethodNoMNUEtcInClass(sqInt class) { register struct foo * foo = &fum; sqInt currentClass; sqInt dictionary; currentClass = class; while (currentClass != foo->nilObj) { dictionary = longAt((currentClass + (BASE_HEADER_SIZE)) + (MessageDictionaryIndex << (SHIFT_FOR_WORD))); if ((dictionary != foo->nilObj) && (lookupMethodInDictionary(dictionary))) { foo->methodClass = currentClass; return 1; } currentClass = longAt((currentClass + (BASE_HEADER_SIZE)) + (SuperclassIndex << (SHIFT_FOR_WORD))); } return 0; } /* Return the first free block after the given chunk in memory. */ sqInt lowestFreeAfter(sqInt chunk) { register struct foo * foo = &fum; sqInt oop; sqInt oopHeader; sqInt oopHeaderType; sqInt oopSize; oop = chunk + (foo->headerTypeBytes[(longAt(chunk)) & TypeMask]); while ((((usqInt) oop)) < (((usqInt) foo->endOfMemory))) { oopHeader = longAt(oop); oopHeaderType = oopHeader & TypeMask; if (oopHeaderType == HeaderTypeFree) { return oop; } else { if (oopHeaderType == HeaderTypeSizeAndClass) { oopSize = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { oopSize = oopHeader & (SIZE_MASK); } } oop = (oop + oopSize) + (foo->headerTypeBytes[(longAt(oop + oopSize)) & TypeMask]); } error("expected to find at least one free object"); } /* make a Point xValue@yValue. We know both will be integers so no value nor root checking is needed */ sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue) { sqInt pointResult; pointResult = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassPoint, foo->specialObjectsOop), 3 * (BYTES_PER_WORD)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (XIndex << (SHIFT_FOR_WORD)), ((xValue << 1) | 1)); longAtput((pointResult + (BASE_HEADER_SIZE)) + (YIndex << (SHIFT_FOR_WORD)), ((yValue << 1) | 1)); return pointResult; } /* Use the forwarding table to update the pointers of all non-free objects in the given range of memory. Also remap pointers in root objects which may contains pointers into the given memory range, and don't forget to flush the method cache based on the range */ sqInt mapPointersInObjectsFromto(sqInt memStart, sqInt memEnd) { register struct foo * foo = &fum; sqInt i; sqInt oop; sqInt i1; sqInt oop1; sqInt i2; sqInt probe; /* begin compilerMapHookFrom:to: */ if (foo->compilerInitialized) { compilerMapFromto(memStart, memEnd); } /* begin mapInterpreterOops */ foo->nilObj = remap(foo->nilObj); foo->falseObj = remap(foo->falseObj); foo->trueObj = remap(foo->trueObj); foo->specialObjectsOop = remap(foo->specialObjectsOop); if (!(foo->compilerInitialized)) { foo->stackPointer -= foo->activeContext; foo->activeContext = remap(foo->activeContext); foo->stackPointer += foo->activeContext; foo->theHomeContext = remap(foo->theHomeContext); } foo->instructionPointer -= foo->method; foo->method = remap(foo->method); foo->instructionPointer += foo->method; foo->receiver = remap(foo->receiver); foo->messageSelector = remap(foo->messageSelector); foo->newMethod = remap(foo->newMethod); foo->methodClass = remap(foo->methodClass); foo->lkupClass = remap(foo->lkupClass); foo->receiverClass = remap(foo->receiverClass); for (i1 = 1; i1 <= foo->remapBufferCount; i1 += 1) { oop1 = foo->remapBuffer[i1]; if (!((oop1 & 1))) { foo->remapBuffer[i1] = (remap(oop1)); } } for (i1 = 1; i1 <= foo->jmpDepth; i1 += 1) { oop1 = foo->suspendedCallbacks[i1]; if (!((oop1 & 1))) { foo->suspendedCallbacks[i1] = (remap(oop1)); } oop1 = foo->suspendedMethods[i1]; if (!((oop1 & 1))) { foo->suspendedMethods[i1] = (remap(oop1)); } } for (i = 1; i <= foo->extraRootCount; i += 1) { oop = (foo->extraRoots[i])[0]; if (!((oop & 1))) { (foo->extraRoots[i])[0] = (remap(oop)); } } /* begin flushMethodCacheFrom:to: */ probe = 0; for (i2 = 1; i2 <= MethodCacheEntries; i2 += 1) { if (!((foo->methodCache[probe + MethodCacheSelector]) == 0)) { if ((((((((usqInt) (foo->methodCache[probe + MethodCacheSelector]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheSelector]))) < (((usqInt) memEnd)))) || (((((usqInt) (foo->methodCache[probe + MethodCacheClass]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheClass]))) < (((usqInt) memEnd))))) || (((((usqInt) (foo->methodCache[probe + MethodCacheMethod]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheMethod]))) < (((usqInt) memEnd))))) || (((((usqInt) (foo->methodCache[probe + MethodCacheNative]))) >= (((usqInt) memStart))) && ((((usqInt) (foo->methodCache[probe + MethodCacheNative]))) < (((usqInt) memEnd))))) { foo->methodCache[probe + MethodCacheSelector] = 0; } } probe += MethodCacheEntrySize; } for (i2 = 1; i2 <= AtCacheTotalSize; i2 += 1) { foo->atCache[i2] = 0; } updatePointersInRootObjectsFromto(memStart, memEnd); updatePointersInRangeFromto(memStart, memEnd); } /* Mark all objects reachable from the given one. Trace from the given object even if it is old. Do not trace if it is already marked. Mark it only if it is a young object. */ /* Tracer state variables: child object being examined field next field of child to examine parentField field where child was stored in its referencing object */ sqInt markAndTrace(sqInt oop) { register struct foo * foo = &fum; sqInt action; sqInt header; sqInt lastFieldOffset; sqInt statMarkCountLocal; sqInt contextSize; sqInt fmt; sqInt header1; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header2; sqInt lastFieldOffset1; sqInt oop1; sqInt header3; sqInt type; sqInt childType; sqInt typeBits; sqInt contextSize1; sqInt fmt1; sqInt header4; sqInt methodHeader1; sqInt sz1; sqInt sp1; sqInt header11; sqInt type1; sqInt header5; sqInt type2; sqInt child; usqInt youngStartLocal; sqInt parentField; sqInt field; header = longAt(oop); if (!((header & (MARK_BIT)) == 0)) { return 0; } header = (header & (ALL_BUT_TYPE_MASK)) | HeaderTypeGC; if ((((usqInt) oop)) >= (((usqInt) foo->youngStart))) { header = header | (MARK_BIT); } longAtput(oop, header); parentField = GCTopMarker; child = oop; if (((((usqInt) (longAt(oop))) >> 8) & 15) == 4) { /* Set lastFieldOffset before the weak fields in the receiver */ /* And remember as weak root */ lastFieldOffset = (nonWeakFieldsOf(oop)) << (SHIFT_FOR_WORD); foo->weakRootCount += 1; foo->weakRoots[foo->weakRootCount] = oop; } else { /* begin lastPointerOf: */ header1 = longAt(oop); fmt = (((usqInt) header1) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header1) >> 12) & 31) == 13) || ((((((usqInt) header1) >> 12) & 31) == 14) || (((((usqInt) header1) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((oop + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l1; } contextSize = (sp >> 1); l1: /* end fetchStackPointerOf: */; lastFieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l2; } /* begin sizeBitsOfSafe: */ header3 = longAt(oop); /* begin rightType: */ if ((header3 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l4; } else { if ((header3 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l4; } else { type = HeaderTypeShort; goto l4; } } l4: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l5; } else { sz = header3 & (SIZE_MASK); goto l5; } l5: /* end sizeBitsOfSafe: */; lastFieldOffset = sz - (BASE_HEADER_SIZE); goto l2; } if (fmt < 12) { lastFieldOffset = 0; goto l2; } methodHeader = longAt(oop + (BASE_HEADER_SIZE)); lastFieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l2: /* end lastPointerOf: */; } field = oop + lastFieldOffset; action = StartField; youngStartLocal = foo->youngStart; /* run the tracer state machine until all objects reachable from oop are marked */ statMarkCountLocal = foo->statMarkCount; while (!(action == Done)) { statMarkCountLocal += 1; if (action == StartField) { /* begin startField */ child = longAt(field); typeBits = child & TypeMask; if ((typeBits & 1) == 1) { field -= BYTES_PER_WORD; action = StartField; goto l7; } if (typeBits == 0) { longAtput(field, parentField); parentField = field; action = StartObj; goto l7; } if (typeBits == 2) { if ((child & CompactClassMask) != 0) { child = child & (ALL_BUT_TYPE_MASK); /* begin rightType: */ if ((child & (SIZE_MASK)) == 0) { childType = HeaderTypeSizeAndClass; goto l6; } else { if ((child & CompactClassMask) == 0) { childType = HeaderTypeClass; goto l6; } else { childType = HeaderTypeShort; goto l6; } } l6: /* end rightType: */; longAtput(field, child | childType); action = Upward; goto l7; } else { child = longAt(field - (BYTES_PER_WORD)); child = child & (ALL_BUT_TYPE_MASK); longAtput(field - (BYTES_PER_WORD), parentField); parentField = (field - (BYTES_PER_WORD)) | 1; action = StartObj; goto l7; } } l7: /* end startField */; } if (action == StartObj) { /* begin startObj */ oop1 = child; if ((((usqInt) oop1)) < (((usqInt) youngStartLocal))) { field = oop1; action = Upward; goto l3; } header2 = longAt(oop1); if ((header2 & (MARK_BIT)) == 0) { if (((((usqInt) (longAt(oop1))) >> 8) & 15) == 4) { lastFieldOffset1 = (nonWeakFieldsOf(oop1)) << (SHIFT_FOR_WORD); } else { /* begin lastPointerOf: */ header4 = longAt(oop1); fmt1 = (((usqInt) header4) >> 8) & 15; if (fmt1 <= 4) { if ((fmt1 == 3) && ((((((usqInt) header4) >> 12) & 31) == 13) || ((((((usqInt) header4) >> 12) & 31) == 14) || (((((usqInt) header4) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp1 = longAt((oop1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp1 & 1))) { contextSize1 = 0; goto l8; } contextSize1 = (sp1 >> 1); l8: /* end fetchStackPointerOf: */; lastFieldOffset1 = (CtxtTempFrameStart + contextSize1) * (BYTES_PER_WORD); goto l11; } /* begin sizeBitsOfSafe: */ header11 = longAt(oop1); /* begin rightType: */ if ((header11 & (SIZE_MASK)) == 0) { type1 = HeaderTypeSizeAndClass; goto l9; } else { if ((header11 & CompactClassMask) == 0) { type1 = HeaderTypeClass; goto l9; } else { type1 = HeaderTypeShort; goto l9; } } l9: /* end rightType: */; if (type1 == HeaderTypeSizeAndClass) { sz1 = (longAt(oop1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l10; } else { sz1 = header11 & (SIZE_MASK); goto l10; } l10: /* end sizeBitsOfSafe: */; lastFieldOffset1 = sz1 - (BASE_HEADER_SIZE); goto l11; } if (fmt1 < 12) { lastFieldOffset1 = 0; goto l11; } methodHeader1 = longAt(oop1 + (BASE_HEADER_SIZE)); lastFieldOffset1 = (((((usqInt) methodHeader1) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l11: /* end lastPointerOf: */; } header2 = header2 & (ALL_BUT_TYPE_MASK); header2 = (header2 | (MARK_BIT)) | HeaderTypeGC; longAtput(oop1, header2); field = oop1 + lastFieldOffset1; action = StartField; goto l3; } else { field = oop1; action = Upward; goto l3; } l3: /* end startObj */; } if (action == Upward) { /* begin upward */ if ((parentField & 1) == 1) { if (parentField == GCTopMarker) { header5 = (longAt(field)) & (ALL_BUT_TYPE_MASK); /* begin rightType: */ if ((header5 & (SIZE_MASK)) == 0) { type2 = HeaderTypeSizeAndClass; goto l12; } else { if ((header5 & CompactClassMask) == 0) { type2 = HeaderTypeClass; goto l12; } else { type2 = HeaderTypeShort; goto l12; } } l12: /* end rightType: */; longAtput(field, header5 | type2); action = Done; goto l14; } else { child = field; field = parentField - 1; parentField = longAt(field); header5 = longAt(field + (BYTES_PER_WORD)); /* begin rightType: */ if ((header5 & (SIZE_MASK)) == 0) { type2 = HeaderTypeSizeAndClass; goto l13; } else { if ((header5 & CompactClassMask) == 0) { type2 = HeaderTypeClass; goto l13; } else { type2 = HeaderTypeShort; goto l13; } } l13: /* end rightType: */; longAtput(field, child | type2); field += BYTES_PER_WORD; header5 = header5 & (ALL_BUT_TYPE_MASK); longAtput(field, header5 | type2); action = Upward; goto l14; } } else { child = field; field = parentField; parentField = longAt(field); longAtput(field, child); field -= BYTES_PER_WORD; action = StartField; goto l14; } l14: /* end upward */; } } foo->statMarkCount = statMarkCountLocal; } /* Mark and trace all oops in the interpreter's state. */ /* Assume: All traced variables contain valid oops. */ sqInt markAndTraceInterpreterOops(void) { register struct foo * foo = &fum; sqInt i; sqInt oop; /* begin compilerMarkHook */ if (foo->compilerInitialized) { compilerMark(); } markAndTrace(foo->specialObjectsOop); if (foo->compilerInitialized) { markAndTrace(foo->receiver); markAndTrace(foo->method); } else { markAndTrace(foo->activeContext); } markAndTrace(foo->messageSelector); markAndTrace(foo->newMethod); markAndTrace(foo->methodClass); markAndTrace(foo->lkupClass); markAndTrace(foo->receiverClass); for (i = 1; i <= foo->remapBufferCount; i += 1) { oop = foo->remapBuffer[i]; if (!((oop & 1))) { markAndTrace(oop); } } for (i = 1; i <= foo->jmpDepth; i += 1) { oop = foo->suspendedCallbacks[i]; if (!((oop & 1))) { markAndTrace(oop); } oop = foo->suspendedMethods[i]; if (!((oop & 1))) { markAndTrace(oop); } } } /* Mark phase of the mark and sweep garbage collector. Set the mark bits of all reachable objects. Free chunks are untouched by this process. */ /* Assume: All non-free objects are initially unmarked. Root objects were unmarked when they were made roots. (Make sure this stays true!!). */ sqInt markPhase(void) { register struct foo * foo = &fum; sqInt i; sqInt oop; /* clear the recycled context lists */ foo->freeContexts = NilContext; /* trace the interpreter's objects, including the active stack and special objects array */ foo->freeLargeContexts = NilContext; markAndTraceInterpreterOops(); /* trace the roots */ foo->statSpecialMarkCount = foo->statMarkCount; for (i = 1; i <= foo->rootTableCount; i += 1) { oop = foo->rootTable[i]; markAndTrace(oop); } for (i = 1; i <= foo->extraRootCount; i += 1) { oop = (foo->extraRoots[i])[0]; if (!((oop & 1))) { markAndTrace(oop); } } } sqInt methodArgumentCount(void) { return foo->argumentCount; } sqInt methodPrimitiveIndex(void) { return foo->primitiveIndex; } /* The module with the given name was just unloaded. Make sure we have no dangling references. */ EXPORT(sqInt) moduleUnloaded(char *aModuleName) { if ((strcmp(aModuleName, "SurfacePlugin")) == 0) { /* Surface plugin went away. Should never happen. But then, who knows */ showSurfaceFn = 0; } } /* For access from BitBlt module */ sqInt nilObject(void) { return foo->nilObj; } /* Return the number of non-weak fields in oop (i.e. the number of fixed fields). Note: The following is copied from fixedFieldsOf:format:length: since we do know the format of the oop (e.g. format = 4) and thus don't need the length. */ sqInt nonWeakFieldsOf(sqInt oop) { register struct foo * foo = &fum; sqInt class; sqInt classFormat; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if (!(((((usqInt) (longAt(oop))) >> 8) & 15) == 4)) { error("Called fixedFieldsOfWeak: with a non-weak oop"); } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; return (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; } /* Float objects were saved in platform word ordering. Reorder them into the traditional object format. */ sqInt normalizeFloatOrderingInImage(void) { register struct foo * foo = &fum; unsigned int *floatData; sqInt oop; unsigned int val; sqInt obj; sqInt sz; sqInt header; if (!(isBigEnder())) { /* begin firstAccessibleObject */ obj = memory + (foo->headerTypeBytes[(longAt(memory)) & TypeMask]); while ((((usqInt) obj)) < (((usqInt) foo->endOfMemory))) { if (!(((longAt(obj)) & TypeMask) == HeaderTypeFree)) { oop = obj; goto l1; } /* begin objectAfter: */ if (DoAssertionChecks) { if ((((usqInt) obj)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(obj)) & TypeMask) == HeaderTypeFree) { sz = (longAt(obj)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(obj); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(obj - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz = header & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; } obj = (obj + sz) + (foo->headerTypeBytes[(longAt(obj + sz)) & TypeMask]); } error("heap is empty"); l1: /* end firstAccessibleObject */; while (!(oop == null)) { if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) { if ((fetchClassOf(oop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { floatData = ((unsigned int *) (firstIndexableField(oop))); val = floatData[0]; floatData[0] = (floatData[1]); floatData[1] = val; } oop = accessibleObjectAfter(oop); } } } } /* Record that the given oop in the old object area points to an object in the young area. HeaderLoc is usually = oop, but may be an addr in a forwarding block. */ sqInt noteAsRootheaderLoc(sqInt oop, sqInt headerLoc) { register struct foo * foo = &fum; sqInt header; header = longAt(headerLoc); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { /* record oop as root only if not already recorded */ /* record root if there is enough room in the roots table */ foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(headerLoc, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { /* we're getting in the red zone */ /* but there's still space to record it */ foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(headerLoc, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } /* This should never be called: either the compiler is uninitialised (in which case the hooks should never be reached) or the compiler initialisation should have replaced all the hook with their external implementations. */ sqInt nullCompilerHook(void) { error("uninitialised compiler hook called"); return 0; } /* Return the object or free chunk immediately following the given object or free chunk in memory. Return endOfMemory when enumeration is complete. */ sqInt objectAfter(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt header; if (DoAssertionChecks) { if ((((usqInt) oop)) >= (((usqInt) foo->endOfMemory))) { error("no objects after the end of memory"); } } if (((longAt(oop)) & TypeMask) == HeaderTypeFree) { sz = (longAt(oop)) & (ALL_BUT_TYPE_MASK); } else { /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; } return (oop + sz) + (foo->headerTypeBytes[(longAt(oop + sz)) & TypeMask]); } /* This message is deprecated but supported for a while via a tweak to sqVirtualMachine.[ch] Use fetchLong32, fetchLong64 or fetchPointer instead for new code */ sqInt obsoleteDontUseThisFetchWordofObject(sqInt fieldIndex, sqInt oop) { return long32At((oop + (BASE_HEADER_SIZE)) + (fieldIndex << 2)); } /* If this is a pointers object, check that its fields are all okay oops. */ sqInt okayFields(sqInt oop) { register struct foo * foo = &fum; sqInt c; sqInt fieldOop; sqInt i; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop == null) || (oop == 0)) { return 1; } if ((oop & 1)) { return 1; } okayOop(oop); oopHasOkayClass(oop); if (!(((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) <= 4))) { return 1; } /* begin fetchClassOf: */ if ((oop & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; c = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { c = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); c = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; if ((c == (fetchPointerofObject(ClassMethodContext, foo->specialObjectsOop))) || (c == (fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop)))) { i = (CtxtTempFrameStart + (fetchStackPointerOf(oop))) - 1; } else { i = (lengthOf(oop)) - 1; } while (i >= 0) { fieldOop = longAt((oop + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); if (!((fieldOop & 1))) { okayOop(fieldOop); oopHasOkayClass(fieldOop); } i -= 1; } } /* Verify that the given oop is legitimate. Check address, header, and size but not class. */ sqInt okayOop(sqInt signedOop) { register struct foo * foo = &fum; sqInt fmt; usqInt oop; sqInt sz; sqInt type; sqInt unusedBit; sqInt header; /* address and size checks */ oop = ((usqInt) signedOop); if ((oop & 1)) { return 1; } if (!(oop < foo->endOfMemory)) { error("oop is not a valid address"); } if (!((oop % (BYTES_PER_WORD)) == 0)) { error("oop is not a word-aligned address"); } /* begin sizeBitsOf: */ header = longAt(oop); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; if (!((oop + sz) < foo->endOfMemory)) { error("oop size would make it extend beyond the end of memory"); } type = (longAt(oop)) & TypeMask; if (type == HeaderTypeFree) { error("oop is a free chunk, not an object"); } if (type == HeaderTypeShort) { if (((((usqInt) (longAt(oop))) >> 12) & 31) == 0) { error("cannot have zero compact class field in a short header"); } } if (type == HeaderTypeClass) { if (!((oop >= (BYTES_PER_WORD)) && (((longAt(oop - (BYTES_PER_WORD))) & TypeMask) == type))) { error("class header word has wrong type"); } } if (type == HeaderTypeSizeAndClass) { if (!((oop >= ((BYTES_PER_WORD) * 2)) && ((((longAt(oop - ((BYTES_PER_WORD) * 2))) & TypeMask) == type) && (((longAt(oop - (BYTES_PER_WORD))) & TypeMask) == type)))) { error("class header word has wrong type"); } } fmt = (((usqInt) (longAt(oop))) >> 8) & 15; if ((fmt == 5) || (fmt == 7)) { error("oop has an unknown format type"); } unusedBit = 536870912; if ((BYTES_PER_WORD) == 8) { unusedBit = unusedBit << 16; unusedBit = unusedBit << 16; } if (!(((longAt(oop)) & unusedBit) == 0)) { error("unused header bit 30 is set; should be zero"); } if ((((longAt(oop)) & (ROOT_BIT)) == 1) && (oop >= foo->youngStart)) { error("root bit is set in a young object"); } return 1; } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisGreaterThan(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) > (((usqInt) otherOop)); } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisGreaterThanOrEqualTo(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) >= (((usqInt) otherOop)); } /* Compare two oop values, treating them as object memory locations. Use #cCoerce:to: to ensure comparison of unsigned magnitudes. This method will be inlined during C translation. */ sqInt oopisLessThan(sqInt anOop, sqInt otherOop) { return (((usqInt) anOop)) < (((usqInt) otherOop)); } /* Similar to oopHasOkayClass:, except that it only returns true or false. */ sqInt oopHasAcceptableClass(sqInt signedOop) { register struct foo * foo = &fum; sqInt behaviorFormatBits; sqInt formatMask; usqInt oop; usqInt oopClass; sqInt oopFormatBits; if ((signedOop & 1)) { return 1; } oop = ((usqInt) signedOop); if (!(oop < foo->endOfMemory)) { return 0; } if (!((oop % (BYTES_PER_WORD)) == 0)) { return 0; } if (!((oop + (sizeBitsOf(oop))) < foo->endOfMemory)) { return 0; } oopClass = ((usqInt) (fetchClassOf(oop))); if ((oopClass & 1)) { return 0; } if (!(oopClass < foo->endOfMemory)) { return 0; } if (!((oopClass % (BYTES_PER_WORD)) == 0)) { return 0; } if (!((oopClass + (sizeBitsOf(oopClass))) < foo->endOfMemory)) { return 0; } if (!((((oopClass & 1) == 0) && (((((usqInt) (longAt(oopClass))) >> 8) & 15) <= 4)) && ((lengthOf(oopClass)) >= 3))) { return 0; } if (((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8)) { /* ignore extra bytes size bits */ formatMask = 3072; } else { formatMask = 3840; } behaviorFormatBits = ((longAt((oopClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1) & formatMask; oopFormatBits = (longAt(oop)) & formatMask; if (!(behaviorFormatBits == oopFormatBits)) { return 0; } return 1; } /* Attempt to verify that the given oop has a reasonable behavior. The class must be a valid, non-integer oop and must not be nilObj. It must be a pointers object with three or more fields. Finally, the instance specification field of the behavior must match that of the instance. */ sqInt oopHasOkayClass(sqInt signedOop) { sqInt behaviorFormatBits; sqInt formatMask; usqInt oop; usqInt oopClass; sqInt oopFormatBits; oop = ((usqInt) signedOop); okayOop(oop); oopClass = ((usqInt) (fetchClassOf(oop))); if ((oopClass & 1)) { error("a SmallInteger is not a valid class or behavior"); } okayOop(oopClass); if (!((((oopClass & 1) == 0) && (((((usqInt) (longAt(oopClass))) >> 8) & 15) <= 4)) && ((lengthOf(oopClass)) >= 3))) { error("a class (behavior) must be a pointers object of size >= 3"); } if (((oop & 1) == 0) && (((((usqInt) (longAt(oop))) >> 8) & 15) >= 8)) { /* ignore extra bytes size bits */ formatMask = 3072; } else { formatMask = 3840; } behaviorFormatBits = ((longAt((oopClass + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1) & formatMask; oopFormatBits = (longAt(oop)) & formatMask; if (!(behaviorFormatBits == oopFormatBits)) { error("object and its class (behavior) formats differ"); } return 1; } /* Note: May be called by translated primitive code. */ sqInt pop(sqInt nItems) { register struct foo * foo = &fum; foo->stackPointer -= nItems * (BYTES_PER_WORD); } sqInt popthenPush(sqInt nItems, sqInt oop) { register struct foo * foo = &fum; sqInt sp; longAtput(sp = foo->stackPointer - ((nItems - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* Note: May be called by translated primitive code. */ double popFloat(void) { register struct foo * foo = &fum; double result; sqInt top; sqInt top1; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassFloat << (SHIFT_FOR_WORD))); if ((top & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(top))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(top - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { ; fetchFloatAtinto(top + (BASE_HEADER_SIZE), result); } return result; } /* Pop and return the possibly remapped object from the remap buffer. */ sqInt popRemappableOop(void) { register struct foo * foo = &fum; sqInt oop; oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; return oop; } sqInt popStack(void) { register struct foo * foo = &fum; sqInt top; top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; return top; } /* Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:. */ sqInt positive32BitIntegerFor(sqInt integerValue) { register struct foo * foo = &fum; sqInt newLargeInteger; if (integerValue >= 0) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerValue)) ^ ((((int) integerValue)) << 1)) >= 0) # else ((integerValue >= -1073741824) && (integerValue <= 1073741823)) # endif // SQ_HOST32 ) { return ((integerValue << 1) | 1); } } if ((BYTES_PER_WORD) == 4) { /* Faster instantiateSmallClass: currently only works with integral word size. */ newLargeInteger = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), (BASE_HEADER_SIZE) + 4); } else { /* Cant use instantiateSmallClass: due to integral word requirement. */ newLargeInteger = instantiateClassindexableSize(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), 4); } byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 3, (((usqInt) integerValue) >> 24) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 2, (((usqInt) integerValue) >> 16) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 1, (((usqInt) integerValue) >> 8) & 255); byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + 0, integerValue & 255); return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a four-byte LargePositiveInteger. */ sqInt positive32BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt sz; sqInt value; sqInt header; sqInt sz1; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { value = (oop >> 1); if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return value; } /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l2: /* end assertClassOf:is: */; if (foo->successFlag) { /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; if (!(sz == 4)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } if (foo->successFlag) { return (((byteAt((oop + (BASE_HEADER_SIZE)) + 0)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 1)) << 8)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 2)) << 16)) + ((byteAt((oop + (BASE_HEADER_SIZE)) + 3)) << 24); } } /* Note - integerValue is interpreted as POSITIVE, eg, as the result of Bitmap>at:, or integer>bitAnd:. */ sqInt positive64BitIntegerFor(sqLong integerValue) { sqInt highWord; sqInt i; sqInt newLargeInteger; sqInt sz; sqInt value; if ((sizeof(integerValue)) == 4) { return positive32BitIntegerFor(integerValue); } /* shift is coerced to usqInt otherwise */ highWord = integerValue >> 32; if (highWord == 0) { return positive32BitIntegerFor(integerValue); } sz = 5; if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } if (!((highWord = ((usqInt) highWord) >> 8) == 0)) { sz += 1; } newLargeInteger = instantiateClassindexableSize(fetchPointerofObject(ClassLargePositiveInteger, foo->specialObjectsOop), sz); for (i = 0; i <= (sz - 1); i += 1) { value = (integerValue >> (i * 8)) & 255; byteAtput((newLargeInteger + (BASE_HEADER_SIZE)) + i, value); } return newLargeInteger; } /* Convert the given object into an integer value. The object may be either a positive ST integer or a eight-byte LargePositiveInteger. */ sqLong positive64BitValueOf(sqInt oop) { register struct foo * foo = &fum; sqInt i; sqInt sz; sqInt szsqLong; sqLong value; sqInt header; sqInt sz1; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop3; if ((oop & 1)) { value = (oop >> 1); if (value < 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } return value; } /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; classOop = longAt((oop3 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))); if ((oop & 1)) { foo->successFlag = 0; goto l2; } ccIndex = (((usqInt) (longAt(oop))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(oop - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l2: /* end assertClassOf:is: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } szsqLong = sizeof(sqLong); /* begin lengthOf: */ header = longAt(oop); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(oop - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; if (sz > szsqLong) { /* begin primitiveFail */ foo->successFlag = 0; return null; } value = 0; for (i = 0; i <= (sz - 1); i += 1) { value += (((sqLong) (byteAt((oop + (BASE_HEADER_SIZE)) + i)))) << (i * 8); } return value; } /* oop is an old object. If valueObj is young, mark the object as a root. */ sqInt possibleRootStoreIntovalue(sqInt oop, sqInt valueObj) { register struct foo * foo = &fum; sqInt header; if (((((usqInt) valueObj)) >= (((usqInt) foo->youngStart))) && (!((valueObj & 1)))) { /* begin noteAsRoot:headerLoc: */ header = longAt(oop); if ((header & (ROOT_BIT)) == 0) { if (foo->rootTableCount < RootTableRedZone) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); } else { if (foo->rootTableCount < RootTableSize) { foo->rootTableCount += 1; foo->rootTable[foo->rootTableCount] = oop; longAtput(oop, header | (ROOT_BIT)); foo->allocationCount = foo->allocationsBetweenGCs + 1; } } } } } /* Mark the active and home contexts as roots if old. This allows the interpreter to use storePointerUnchecked to store into them. */ sqInt postGCAction(void) { register struct foo * foo = &fum; sqInt delta; sqInt limit; if (foo->compilerInitialized) { compilerPostGC(); } else { if ((((usqInt) foo->activeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->activeContext); } if ((((usqInt) foo->theHomeContext)) < (((usqInt) foo->youngStart))) { beRootIfOld(foo->theHomeContext); } } if (oopisGreaterThan((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK), foo->shrinkThreshold)) { /* begin shrinkObjectMemory: */ delta = ((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) - foo->growHeadroom; foo->statShrinkMemory += 1; limit = sqShrinkMemoryBy(foo->memoryLimit, delta); if (!(limit == foo->memoryLimit)) { foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } } /* begin signalSemaphoreWithIndex: */ if (foo->gcSemaphoreIndex <= 0) { goto l1; } if (foo->semaphoresUseBufferA) { if (foo->semaphoresToSignalCountA < SemaphoresToSignalSize) { foo->semaphoresToSignalCountA += 1; foo->semaphoresToSignalA[foo->semaphoresToSignalCountA] = foo->gcSemaphoreIndex; } } else { if (foo->semaphoresToSignalCountB < SemaphoresToSignalSize) { foo->semaphoresToSignalCountB += 1; foo->semaphoresToSignalB[foo->semaphoresToSignalCountB] = foo->gcSemaphoreIndex; } } /* begin forceInterruptCheck */ foo->interruptCheckCounter = -1000; foo->nextPollTick = 0; l1: /* end signalSemaphoreWithIndex: */; } /* Ensure that there are enough forwarding blocks to accomodate this become, then prepare forwarding blocks for the pointer swap. Return true if successful. */ /* Details: Doing a GC might generate enough space for forwarding blocks if we're short. However, this is an uncommon enough case that it is better handled by primitive fail code at the Smalltalk level. */ /* Important note on multiple references to same object - since the preparation of fwdBlocks is NOT idempotent we get VM crashes if the same object is referenced more than once in such a way as to require multiple fwdBlocks. oop1 forwardBecome: oop1 is ok since only a single fwdBlock is needed. oop1 become: oop1 would fail because the second fwdBlock woudl not have the actual object header but rather the mutated ref to the first fwdBlock. Further problems can arise with an array1 or array2 that refer multiply to the same object. This would notbe expected input for programmer writen code but might arise from automatic usage such as in ImageSegment loading. To avoid the simple and rather common case of oop1 become*: oop1, we skip such pairs and simply avoid making fwdBlocks - it is redundant anyway */ sqInt prepareForwardingTableForBecomingwithtwoWay(sqInt array1, sqInt array2, sqInt twoWayFlag) { register struct foo * foo = &fum; sqInt entriesAvailable; sqInt entriesNeeded; sqInt fieldOffset; sqInt fwdBlkSize; sqInt fwdBlock; sqInt oop1; sqInt oop2; sqInt originalHeader; sqInt originalHeaderType; sqInt originalHeader1; sqInt originalHeaderType1; sqInt contextSize; sqInt fmt; sqInt header; sqInt methodHeader; sqInt sz; sqInt sp; sqInt header1; sqInt type; /* need enough entries for all oops */ /* Note: Forward blocks must be quadword aligned - see fwdTableInit:. */ entriesNeeded = (lastPointerOf(array1)) / (BYTES_PER_WORD); if (twoWayFlag) { /* Double the number of blocks for two-way become */ entriesNeeded = entriesNeeded * 2; fwdBlkSize = (BYTES_PER_WORD) * 2; } else { /* One-way become needs backPointers in fwd blocks. */ fwdBlkSize = (BYTES_PER_WORD) * 4; } entriesAvailable = fwdTableInit(fwdBlkSize); if (entriesAvailable < entriesNeeded) { initializeMemoryFirstFree(foo->freeBlock); return 0; } /* begin lastPointerOf: */ header = longAt(array1); fmt = (((usqInt) header) >> 8) & 15; if (fmt <= 4) { if ((fmt == 3) && ((((((usqInt) header) >> 12) & 31) == 13) || ((((((usqInt) header) >> 12) & 31) == 14) || (((((usqInt) header) >> 12) & 31) == 4)))) { /* begin fetchStackPointerOf: */ sp = longAt((array1 + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD))); if (!((sp & 1))) { contextSize = 0; goto l3; } contextSize = (sp >> 1); l3: /* end fetchStackPointerOf: */; fieldOffset = (CtxtTempFrameStart + contextSize) * (BYTES_PER_WORD); goto l4; } /* begin sizeBitsOfSafe: */ header1 = longAt(array1); /* begin rightType: */ if ((header1 & (SIZE_MASK)) == 0) { type = HeaderTypeSizeAndClass; goto l5; } else { if ((header1 & CompactClassMask) == 0) { type = HeaderTypeClass; goto l5; } else { type = HeaderTypeShort; goto l5; } } l5: /* end rightType: */; if (type == HeaderTypeSizeAndClass) { sz = (longAt(array1 - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); goto l6; } else { sz = header1 & (SIZE_MASK); goto l6; } l6: /* end sizeBitsOfSafe: */; fieldOffset = sz - (BASE_HEADER_SIZE); goto l4; } if (fmt < 12) { fieldOffset = 0; goto l4; } methodHeader = longAt(array1 + (BASE_HEADER_SIZE)); fieldOffset = (((((usqInt) methodHeader) >> 10) & 255) * (BYTES_PER_WORD)) + (BASE_HEADER_SIZE); l4: /* end lastPointerOf: */; while (fieldOffset >= (BASE_HEADER_SIZE)) { oop1 = longAt(array1 + fieldOffset); /* if oop1 == oop2, no need to do any work for this pair. May still be other entries in the arrays though so keep looking */ oop2 = longAt(array2 + fieldOffset); if (!(oop1 == oop2)) { /* begin fwdBlockGet: */ foo->fwdTableNext += fwdBlkSize; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l2; } else { fwdBlock = null; goto l2; } l2: /* end fwdBlockGet: */; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader1 = longAt(oop1); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader1 & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType1 = originalHeader1 & TypeMask; longAtput(fwdBlock, oop2); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader1); if (!twoWayFlag) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop1); } longAtput(oop1, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType1)); if (twoWayFlag) { /* begin fwdBlockGet: */ foo->fwdTableNext += fwdBlkSize; if (foo->fwdTableNext <= foo->fwdTableLast) { fwdBlock = foo->fwdTableNext; goto l1; } else { fwdBlock = null; goto l1; } l1: /* end fwdBlockGet: */; /* begin initForwardBlock:mapping:to:withBackPtr: */ originalHeader = longAt(oop2); if (DoAssertionChecks) { if (fwdBlock == null) { error("ran out of forwarding blocks in become"); } if ((originalHeader & (MARK_BIT)) != 0) { error("object already has a forwarding table entry"); } } originalHeaderType = originalHeader & TypeMask; longAtput(fwdBlock, oop1); longAtput(fwdBlock + (BYTES_PER_WORD), originalHeader); if (!twoWayFlag) { longAtput(fwdBlock + ((BYTES_PER_WORD) * 2), oop2); } longAtput(oop2, (((usqInt) fwdBlock) >> 1) | ((MARK_BIT) | originalHeaderType)); } } fieldOffset -= BYTES_PER_WORD; } return 1; } sqInt primitiveAdd(void) { register struct foo * foo = &fum; sqInt integerResult; sqInt sp; /* begin pop2AndPushIntegerIfOK: */ integerResult = (stackIntegerValue(1)) + (stackIntegerValue(0)); if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) integerResult)) ^ ((((int) integerResult)) << 1)) >= 0) # else ((integerResult >= -1073741824) && (integerResult <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((integerResult << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } /* Primitive arithmetic operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveAddLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqLong result; sqInt sp; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (!(foo->successFlag)) { return null; } /* Now check overflow conditions. First is whether rcvr and arg are of the same sign. If they are we need to check for overflow more carefully. */ result = integerRcvr + integerArg; if (!((integerRcvr ^ integerArg) < 0)) { if ((integerRcvr ^ result) < 0) { /* begin primitiveFail */ foo->successFlag = 0; } } if (!(foo->successFlag)) { return null; } oopResult = signed64BitIntegerFor(result); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } /* Primitive. Change the class of the argument to make it an instance of the receiver given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ sqInt primitiveAdoptInstance(void) { register struct foo * foo = &fum; sqInt arg; sqInt err; sqInt rcvr; sqInt i; sqInt oop; sqInt oop1; /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; arg = null; goto l1; } arg = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; err = changeClassOfto(arg, rcvr); if (err == 0) { /* begin flushAtCache */ for (i = 1; i <= AtCacheTotalSize; i += 1) { foo->atCache[i] = 0; } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } else { /* begin primitiveFail */ foo->successFlag = 0; } return null; } sqInt primitiveArctan(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(atan(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* We must flush the method cache here, to eliminate stale references to mutated classes and/or selectors. */ sqInt primitiveArrayBecome(void) { register struct foo * foo = &fum; sqInt arg; sqInt rcvr; sqInt successValue; arg = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 1, 1); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* We must flush the method cache here, to eliminate stale references to mutated classes and/or selectors. */ sqInt primitiveArrayBecomeOneWay(void) { register struct foo * foo = &fum; sqInt arg; sqInt rcvr; sqInt successValue; arg = longAt(foo->stackPointer); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 0, 1); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Similar to primitiveArrayBecomeOneWay but accepts a third argument whether to copy the receiver's identity hash over the argument's identity hash. */ sqInt primitiveArrayBecomeOneWayCopyHash(void) { register struct foo * foo = &fum; sqInt arg; sqInt copyHashFlag; sqInt rcvr; sqInt successValue; /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { copyHashFlag = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { copyHashFlag = 0; goto l1; } foo->successFlag = 0; copyHashFlag = null; l1: /* end booleanValueOf: */; arg = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); /* begin success: */ successValue = becomewithtwoWaycopyHash(rcvr, arg, 0, copyHashFlag); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); } } sqInt primitiveAsFloat(void) { register struct foo * foo = &fum; sqInt arg; sqInt integerPointer; sqInt top; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { arg = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; arg = 0; goto l1; } arg = null; l1: /* end popInteger */; if (foo->successFlag) { pushFloat(((double) arg)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } sqInt primitiveAsOop(void) { register struct foo * foo = &fum; sqInt thisReceiver; sqInt sp; thisReceiver = longAt(foo->stackPointer); /* begin success: */ foo->successFlag = (!((thisReceiver & 1))) && foo->successFlag; if (foo->successFlag) { /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((((((usqInt) (longAt(thisReceiver))) >> 17) & 4095) << 1) | 1)); foo->stackPointer = sp; } } sqInt primitiveAt(void) { commonAt(0); } sqInt primitiveAtPut(void) { commonAtPut(0); } /* Set the cursor to the given shape. The Mac only supports 16x16 pixel cursors. Cursor offsets are handled by Smalltalk. */ sqInt primitiveBeCursor(void) { register struct foo * foo = &fum; sqInt bitsObj; sqInt cursorBitsIndex; sqInt cursorObj; sqInt depth; sqInt extentX; sqInt extentY; sqInt i; sqInt maskBitsIndex; sqInt maskObj; sqInt offsetObj; sqInt offsetX; sqInt offsetY; sqInt ourCursor; sqInt successValue; sqInt successValue1; sqInt successValue2; sqInt successValue3; sqInt successValue4; sqInt successValue5; sqInt successValue6; sqInt successValue7; sqInt successValue8; sqInt successValue9; sqInt successValue10; sqInt successValue11; sqInt successValue12; flag("Dan"); if ((BYTES_PER_WORD) == 8) { /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); return null; } if (foo->argumentCount == 0) { cursorObj = longAt(foo->stackPointer); maskBitsIndex = null; } if (foo->argumentCount == 1) { cursorObj = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); maskObj = longAt(foo->stackPointer); } /* begin success: */ foo->successFlag = (foo->argumentCount < 2) && foo->successFlag; /* begin success: */ successValue11 = (((cursorObj & 1) == 0) && (((((usqInt) (longAt(cursorObj))) >> 8) & 15) <= 4)) && ((lengthOf(cursorObj)) >= 5); foo->successFlag = successValue11 && foo->successFlag; if (foo->successFlag) { bitsObj = longAt((cursorObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); extentX = fetchIntegerofObject(1, cursorObj); extentY = fetchIntegerofObject(2, cursorObj); depth = fetchIntegerofObject(3, cursorObj); offsetObj = longAt((cursorObj + (BASE_HEADER_SIZE)) + (4 << (SHIFT_FOR_WORD))); } /* begin success: */ successValue12 = (((offsetObj & 1) == 0) && (((((usqInt) (longAt(offsetObj))) >> 8) & 15) <= 4)) && ((lengthOf(offsetObj)) >= 2); foo->successFlag = successValue12 && foo->successFlag; if (foo->successFlag) { offsetX = fetchIntegerofObject(0, offsetObj); offsetY = fetchIntegerofObject(1, offsetObj); if ((foo->argumentCount == 0) && (depth == 32)) { /* begin success: */ successValue = (extentX > 0) && (extentY > 0); foo->successFlag = successValue && foo->successFlag; /* begin success: */ successValue1 = (offsetX >= (extentX * -1)) && (offsetX <= 0); foo->successFlag = successValue1 && foo->successFlag; /* begin success: */ successValue2 = (offsetY >= (extentY * -1)) && (offsetY <= 0); foo->successFlag = successValue2 && foo->successFlag; cursorBitsIndex = bitsObj + (BASE_HEADER_SIZE); /* begin success: */ successValue3 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == (extentX * extentY)); foo->successFlag = successValue3 && foo->successFlag; ; } else { /* begin success: */ successValue4 = (extentX == 16) && ((extentY == 16) && (depth == 1)); foo->successFlag = successValue4 && foo->successFlag; /* begin success: */ successValue5 = (offsetX >= -16) && (offsetX <= 0); foo->successFlag = successValue5 && foo->successFlag; /* begin success: */ successValue6 = (offsetY >= -16) && (offsetY <= 0); foo->successFlag = successValue6 && foo->successFlag; /* begin success: */ successValue7 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == 16); foo->successFlag = successValue7 && foo->successFlag; cursorBitsIndex = bitsObj + (BASE_HEADER_SIZE); ; } } if (foo->argumentCount == 1) { /* begin success: */ successValue10 = (((maskObj & 1) == 0) && (((((usqInt) (longAt(maskObj))) >> 8) & 15) <= 4)) && ((lengthOf(maskObj)) >= 5); foo->successFlag = successValue10 && foo->successFlag; if (foo->successFlag) { bitsObj = longAt((maskObj + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); extentX = fetchIntegerofObject(1, maskObj); extentY = fetchIntegerofObject(2, maskObj); depth = fetchIntegerofObject(3, maskObj); } if (foo->successFlag) { /* begin success: */ successValue8 = (extentX == 16) && ((extentY == 16) && (depth == 1)); foo->successFlag = successValue8 && foo->successFlag; /* begin success: */ successValue9 = (((bitsObj & 1) == 0) && (((((usqInt) (longAt(bitsObj))) >> 8) & 15) == 6)) && ((lengthOf(bitsObj)) == 16); foo->successFlag = successValue9 && foo->successFlag; maskBitsIndex = bitsObj + (BASE_HEADER_SIZE); } } if (foo->successFlag) { if (foo->argumentCount == 0) { if (depth == 32) { if (!(ioSetCursorARGB(cursorBitsIndex, extentX, extentY, offsetX, offsetY))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } } else { ioSetCursor(cursorBitsIndex, offsetX, offsetY); } } else { ioSetCursorWithMask(cursorBitsIndex, maskBitsIndex, offsetX, offsetY); } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } } /* Record the system Display object in the specialObjectsTable. */ sqInt primitiveBeDisplay(void) { register struct foo * foo = &fum; sqInt rcvr; sqInt successValue; sqInt oop; rcvr = longAt(foo->stackPointer); /* begin success: */ successValue = (((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4)) && ((lengthOf(rcvr)) >= 4); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, rcvr); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheDisplay << (SHIFT_FOR_WORD)), rcvr); } } /* make the basic beep noise */ sqInt primitiveBeep(void) { ioBeep(); } sqInt primitiveBitAnd(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt top; sqInt top1; sqInt object; sqInt sp; sqInt top2; sqInt top3; /* begin popPos32BitInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top2; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top3 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top1 = top3; integerReceiver = positive32BitValueOf(top1); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver & integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive logical operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveBitAndLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqInt sp; integerArg = positive64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = positive64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (!(foo->successFlag)) { return null; } oopResult = positive64BitIntegerFor(integerRcvr & integerArg); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveBitOr(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt top; sqInt top1; sqInt object; sqInt sp; sqInt top2; sqInt top3; /* begin popPos32BitInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top2; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top3 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top1 = top3; integerReceiver = positive32BitValueOf(top1); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver | integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive logical operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveBitOrLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqInt sp; integerArg = positive64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = positive64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (!(foo->successFlag)) { return null; } oopResult = positive64BitIntegerFor(integerRcvr | integerArg); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveBitShift(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt shifted; sqInt top; sqInt object; sqInt sp; sqInt top1; sqInt integerPointer; sqInt top2; /* begin popInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top2; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } integerArgument = null; l1: /* end popInteger */; /* begin popPos32BitInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top1; integerReceiver = positive32BitValueOf(top); if (foo->successFlag) { if (integerArgument >= 0) { /* begin success: */ foo->successFlag = (integerArgument <= 31) && foo->successFlag; shifted = integerReceiver << integerArgument; /* begin success: */ foo->successFlag = ((((usqInt) shifted) >> integerArgument) == integerReceiver) && foo->successFlag; } else { /* begin success: */ foo->successFlag = (integerArgument >= -31) && foo->successFlag; shifted = ((integerArgument < 0) ? ((usqInt) integerReceiver >> -integerArgument) : ((usqInt) integerReceiver << integerArgument)); } } if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(shifted); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive logical operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveBitShiftLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqLong shifted; sqInt sp; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArg = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArg = 0; goto l1; } integerArg = null; l1: /* end stackIntegerValue: */; integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (foo->successFlag) { if (integerArg >= 0) { /* begin success: */ foo->successFlag = (integerArg < 64) && foo->successFlag; shifted = integerRcvr << integerArg; /* begin success: */ foo->successFlag = ((shifted >> integerArg) == integerRcvr) && foo->successFlag; } else { /* begin success: */ foo->successFlag = (integerArg > -64) && foo->successFlag; shifted = integerRcvr >> (0 - integerArg); } } if (!(foo->successFlag)) { return null; } oopResult = signed64BitIntegerFor(shifted); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveBitXor(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt top; sqInt top1; sqInt object; sqInt sp; sqInt top2; sqInt top3; /* begin popPos32BitInteger */ /* begin popStack */ top2 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top = top2; integerArgument = positive32BitValueOf(top); /* begin popPos32BitInteger */ /* begin popStack */ top3 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; top1 = top3; integerReceiver = positive32BitValueOf(top1); if (foo->successFlag) { /* begin push: */ object = positive32BitIntegerFor(integerReceiver ^ integerArgument); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive logical operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveBitXorLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqInt sp; integerArg = positive64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = positive64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (!(foo->successFlag)) { return null; } oopResult = positive64BitIntegerFor(integerRcvr ^ integerArg); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveBlockCopy(void) { register struct foo * foo = &fum; sqInt context; sqInt contextSize; sqInt initialIP; sqInt methodContext; sqInt newContext; sqInt header; sqInt oop; sqInt valuePointer; sqInt valuePointer1; sqInt sp; context = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (((longAt((context + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD)))) & 1)) { /* context is a block; get the context of its enclosing method */ methodContext = longAt((context + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD))); } else { methodContext = context; } /* begin sizeBitsOf: */ header = longAt(methodContext); if ((header & TypeMask) == HeaderTypeSizeAndClass) { contextSize = (longAt(methodContext - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { contextSize = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; /* context is no longer needed and is not preserved across allocation */ /* remap methodContext in case GC happens during allocation */ context = null; /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = methodContext; newContext = instantiateContextsizeInBytes(fetchPointerofObject(ClassBlockContext, foo->specialObjectsOop), contextSize); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; methodContext = oop; /* Was instructionPointer + 3, but now it's greater by 1 due to preIncrement */ /* Assume: have just allocated a new context; it must be young. Thus, can use uncheck stores. See the comment in fetchContextRegisters. */ initialIP = (((((foo->instructionPointer + 1) + 3) - (foo->method + (BASE_HEADER_SIZE))) << 1) | 1); longAtput((newContext + (BASE_HEADER_SIZE)) + (InitialIPIndex << (SHIFT_FOR_WORD)), initialIP); longAtput((newContext + (BASE_HEADER_SIZE)) + (InstructionPointerIndex << (SHIFT_FOR_WORD)), initialIP); /* begin storeStackPointerValue:inContext: */ longAtput((newContext + (BASE_HEADER_SIZE)) + (StackPointerIndex << (SHIFT_FOR_WORD)), ((0 << 1) | 1)); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); longAtput((newContext + (BASE_HEADER_SIZE)) + (BlockArgumentCountIndex << (SHIFT_FOR_WORD)), valuePointer); longAtput((newContext + (BASE_HEADER_SIZE)) + (HomeIndex << (SHIFT_FOR_WORD)), methodContext); /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = foo->nilObj; longAtput((newContext + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD)), valuePointer1); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), newContext); foo->stackPointer = sp; } /* Reports bytes available at this moment. For more meaningful results, calls to this primitive should be preceeded by a full or incremental garbage collection. */ sqInt primitiveBytesLeft(void) { register struct foo * foo = &fum; sqInt aBool; sqInt oop; sqInt sp; sqInt oop1; sqInt sp1; if (foo->argumentCount == 0) { /* begin pop:thenPush: */ oop = positive64BitIntegerFor((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; return null; } if (foo->argumentCount == 1) { /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { aBool = 1; goto l1; } if ((longAt(foo->stackPointer)) == foo->falseObj) { aBool = 0; goto l1; } foo->successFlag = 0; aBool = null; l1: /* end booleanValueOf: */; if (!(foo->successFlag)) { return null; } /* begin pop:thenPush: */ oop1 = positive64BitIntegerFor(((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(aBool))); longAtput(sp1 = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oop1); foo->stackPointer = sp1; return null; } /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Perform a function call to a foreign function. Only invoked from method containing explicit external call spec. Due to this we use the pluggable prim mechanism explicitly here (the first literal of any FFI spec'ed method is an ExternalFunction and not an array as used in the pluggable primitive mechanism). */ sqInt primitiveCalloutToFFI(void) { static void *function = 0; static char *functionName = "primitiveCallout"; static char *moduleName = "SqueakFFIPrims"; if (function == 0) { function = ioLoadExternalFunctionOfLengthFromModuleOfLength(oopForPointer(functionName), 16, oopForPointer(moduleName), 14); if (function == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } return ((sqInt (*)(void))function)(); } /* Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ sqInt primitiveChangeClass(void) { register struct foo * foo = &fum; sqInt arg; sqInt argClass; sqInt rcvr; sqInt ccIndex; sqInt oop; sqInt oop1; sqInt oop2; sqInt oop3; sqInt oop4; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop2 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop2 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; arg = null; goto l2; } arg = oop2; l2: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop3 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop3 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l3; } rcvr = oop3; l3: /* end stackObjectValue: */; /* begin fetchClassOf: */ if ((arg & 1)) { /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; argClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(arg))) >> 12) & 31; if (ccIndex == 0) { argClass = (longAt(arg - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop4 = foo->specialObjectsOop; oop1 = longAt((oop4 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); argClass = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; changeClassOfto(rcvr, argClass); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } /* Primitive. Change the class of the receiver into the class of the argument given that the format of the receiver matches the format of the argument's class. Fail if receiver or argument are SmallIntegers, or the receiver is an instance of a compact class and the argument isn't, or when the argument's class is compact and the receiver isn't, or when the format of the receiver is different from the format of the argument's class, or when the arguments class is fixed and the receiver's size differs from the size that an instance of the argument's class should have. */ EXPORT(sqInt) primitiveChangeClassWithClass(void) { register struct foo * foo = &fum; sqInt argClass; sqInt rcvr; sqInt oop; sqInt oop1; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; argClass = null; goto l1; } argClass = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; changeClassOfto(rcvr, argClass); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } sqInt primitiveClass(void) { register struct foo * foo = &fum; sqInt instance; sqInt oop; sqInt sp; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; instance = longAt(foo->stackPointer); /* begin pop:thenPush: */ /* begin fetchClassOf: */ if ((instance & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; oop = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(instance))) >> 12) & 31; if (ccIndex == 0) { oop = (longAt(instance - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); oop = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* When called with a single string argument, post the string to the clipboard. When called with zero arguments, return a string containing the current clipboard contents. */ sqInt primitiveClipboardText(void) { register struct foo * foo = &fum; sqInt s; sqInt sz; sqInt sp; if (foo->argumentCount == 1) { s = longAt(foo->stackPointer); if (!(((s & 1) == 0) && (((((usqInt) (longAt(s))) >> 8) & 15) >= 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (foo->successFlag) { sz = stSizeOf(s); clipboardWriteFromAt(sz, s + (BASE_HEADER_SIZE), 0); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } else { sz = clipboardSize(); if (!(sufficientSpaceToAllocate(sz))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); clipboardReadIntoAt(sz, s + (BASE_HEADER_SIZE), 0); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), s); foo->stackPointer = sp; } } /* Return a shallow copy of the receiver. */ sqInt primitiveClone(void) { register struct foo * foo = &fum; sqInt newCopy; sqInt sp; newCopy = clone(longAt(foo->stackPointer)); if (newCopy == 0) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), newCopy); foo->stackPointer = sp; } sqInt primitiveClosureCopyWithCopiedValues(void) { register struct foo * foo = &fum; sqInt copiedValues; sqInt i; sqInt newClosure; sqInt numArgs; sqInt numCopiedValues; sqInt successValue; sqInt sz; sqInt sp; sqInt valuePointer; sqInt header; sqInt initialIP; sqInt newClosure1; sqInt valuePointer1; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { numArgs = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; numArgs = 0; goto l2; } numArgs = null; l2: /* end stackIntegerValue: */; copiedValues = longAt(foo->stackPointer); /* begin success: */ successValue = (fetchClassOf(copiedValues)) == (fetchPointerofObject(ClassArray, foo->specialObjectsOop)); foo->successFlag = successValue && foo->successFlag; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(copiedValues); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(copiedValues - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; numCopiedValues = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin closureNumArgs:instructionPointer:numCopiedValues: */ initialIP = (foo->instructionPointer + 2) - (foo->method + (BASE_HEADER_SIZE)); newClosure1 = instantiateSmallClasssizeInBytes(fetchPointerofObject(ClassBlockClosure, foo->specialObjectsOop), ((BYTES_PER_WORD) * (ClosureFirstCopiedValueIndex + numCopiedValues)) + (BASE_HEADER_SIZE)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureStartPCIndex << (SHIFT_FOR_WORD)), ((initialIP << 1) | 1)); longAtput((newClosure1 + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)), ((numArgs << 1) | 1)); newClosure = newClosure1; /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer1 = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD)), valuePointer1); if (numCopiedValues > 0) { /* Allocation may have done a GC and copiedValues may have moved. */ copiedValues = longAt(foo->stackPointer); for (i = 0; i <= (numCopiedValues - 1); i += 1) { /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt((copiedValues + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); longAtput((newClosure + (BASE_HEADER_SIZE)) + ((i + ClosureFirstCopiedValueIndex) << (SHIFT_FOR_WORD)), valuePointer); } } /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), newClosure); foo->stackPointer = sp; } sqInt primitiveClosureValue(void) { register struct foo * foo = &fum; sqInt blockArgumentCount; sqInt blockClosure; sqInt closureMethod; sqInt outerContext; blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(foo->argumentCount == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } activateNewClosureMethod(blockClosure); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } /* An exact clone of primitiveClosureValue except that this version will not check for interrupts on stack overflow. */ sqInt primitiveClosureValueNoContextSwitch(void) { register struct foo * foo = &fum; sqInt blockArgumentCount; sqInt blockClosure; sqInt closureMethod; sqInt outerContext; blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(foo->argumentCount == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } activateNewClosureMethod(blockClosure); } sqInt primitiveClosureValueWithArgs(void) { register struct foo * foo = &fum; sqInt argumentArray; sqInt arraySize; sqInt blockArgumentCount; sqInt blockClosure; sqInt closureMethod; sqInt cntxSize; sqInt index; sqInt outerContext; sqInt object; sqInt sp; sqInt sz; sqInt header; sqInt objectPointer; sqInt sz1; sqInt header1; sqInt top; argumentArray = longAt(foo->stackPointer); if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin fetchWordLengthOf: */ objectPointer = foo->activeContext; /* begin sizeBitsOf: */ header1 = longAt(objectPointer); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; cntxSize = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); if (!(((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) < cntxSize)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } blockClosure = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); blockArgumentCount = ((longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureNumArgsIndex << (SHIFT_FOR_WORD)))) >> 1); if (!(arraySize == blockArgumentCount)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } outerContext = longAt((blockClosure + (BASE_HEADER_SIZE)) + (ClosureOuterContextIndex << (SHIFT_FOR_WORD))); if (!(((outerContext & 1) == 0) && ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 13) || ((((((usqInt) (longAt(outerContext))) >> 12) & 31) == 14) || (((((usqInt) (longAt(outerContext))) >> 12) & 31) == 4))))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* Check if the closure's method is actually a CompiledMethod. */ closureMethod = longAt((outerContext + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); if (!(((closureMethod & 1) == 0) && (((((usqInt) (longAt(closureMethod))) >> 8) & 15) >= 12))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; index = 1; while (index <= arraySize) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } foo->argumentCount = arraySize; activateNewClosureMethod(blockClosure); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } } /* Fill the receiver, which must be an indexable bytes or words objects, with the given integer value. */ sqInt primitiveConstantFill(void) { register struct foo * foo = &fum; usqInt end; sqInt fillValue; usqInt i; sqInt rcvr; sqInt rcvrIsBytes; sqInt successValue; sqInt successValue1; fillValue = positive32BitValueOf(longAt(foo->stackPointer)); rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin success: */ successValue1 = ((rcvr & 1) == 0) && (isWordsOrBytesNonInt(rcvr)); foo->successFlag = successValue1 && foo->successFlag; rcvrIsBytes = ((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) >= 8); if (rcvrIsBytes) { /* begin success: */ successValue = (fillValue >= 0) && (fillValue <= 255); foo->successFlag = successValue && foo->successFlag; } if (foo->successFlag) { end = rcvr + (sizeBitsOf(rcvr)); i = rcvr + (BASE_HEADER_SIZE); if (rcvrIsBytes) { while (i < end) { byteAtput(i, fillValue); i += 1; } } else { while (i < end) { long32Atput(i, fillValue); i += 4; } } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Primitive. Copy the state of the receiver from the argument. Fail if receiver and argument are of a different class. Fail if the receiver or argument are non-pointer objects. Fail if receiver and argument have different lengths (for indexable objects). */ sqInt primitiveCopyObject(void) { register struct foo * foo = &fum; sqInt arg; sqInt i; sqInt length; sqInt rcvr; sqInt header; sqInt valuePointer; sqInt oop; sqInt oop1; sqInt sz; if (!(foo->argumentCount == 1)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackObjectValue: */ oop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop & 1)) { /* begin primitiveFail */ foo->successFlag = 0; arg = null; goto l1; } arg = oop; l1: /* end stackObjectValue: */; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; rcvr = null; goto l2; } rcvr = oop1; l2: /* end stackObjectValue: */; if (!foo->successFlag) { return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } if (!((fetchClassOf(rcvr)) == (fetchClassOf(arg)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l3; } if (((((usqInt) header) >> 8) & 15) < 8) { length = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l3; } else { length = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l3; } l3: /* end lengthOf:baseHeader:format: */; if (!(length == (lengthOf(arg)))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } for (i = 0; i <= (length - 1); i += 1) { /* begin storePointer:ofObject:withValue: */ valuePointer = longAt((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD))); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, valuePointer); } longAtput((rcvr + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), valuePointer); } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } /* Set or clear the flag that controls whether modifications of the Display object are propagated to the underlying platform's screen. */ sqInt primitiveDeferDisplayUpdates(void) { register struct foo * foo = &fum; sqInt flag; flag = longAt(foo->stackPointer); if (flag == foo->trueObj) { foo->deferDisplayUpdates = 1; } else { if (flag == foo->falseObj) { foo->deferDisplayUpdates = 0; } else { /* begin primitiveFail */ foo->successFlag = 0; } } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } /* Pass in a non-negative value to disable the architectures powermanager if any, zero to enable. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveDisablePowerManager(void) { register struct foo * foo = &fum; sqInt integer; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integer = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integer = 0; goto l1; } integer = null; l1: /* end stackIntegerValue: */; if (foo->successFlag) { ioDisablePowerManager(integer); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } sqInt primitiveDiv(void) { register struct foo * foo = &fum; sqInt quotient; sqInt sp; quotient = doPrimitiveDivby(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) quotient)) ^ ((((int) quotient)) << 1)) >= 0) # else ((quotient >= -1073741824) && (quotient <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), ((quotient << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } /* Primitive arithmetic operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveDivLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqLong posArg; sqLong posRcvr; sqLong result; sqInt sp; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (integerArg == 0) { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } if (integerRcvr > 0) { if (integerArg > 0) { result = integerRcvr / integerArg; } else { /* round negative result toward negative infinity */ posArg = 0 - integerArg; /* can overflow! */ posRcvr = integerRcvr + (posArg - 1); if (posRcvr < 0) { /* begin primitiveFail */ foo->successFlag = 0; } result = 0 - (posRcvr / posArg); } } else { posRcvr = 0 - integerRcvr; if (integerArg > 0) { /* round negative result toward negative infinity */ /* can overflow! */ posRcvr += integerArg - 1; if (posRcvr < 0) { /* begin primitiveFail */ foo->successFlag = 0; } result = 0 - (posRcvr / integerArg); } else { posArg = 0 - integerArg; result = posRcvr / posArg; } } if (foo->successFlag) { oopResult = signed64BitIntegerFor(result); } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveDivide(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt sp; sqInt integerPointer; sqInt integerPointer1; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerReceiver = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l1; } integerReceiver = null; l1: /* end stackIntegerValue: */; /* begin stackIntegerValue: */ integerPointer1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerArgument = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l2; } integerArgument = null; l2: /* end stackIntegerValue: */; if ((integerArgument != 0) && ((integerReceiver % integerArgument) == 0)) { /* begin pop2AndPushIntegerIfOK: */ if (foo->successFlag) { if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (integerReceiver / integerArgument))) ^ ((((int) (integerReceiver / integerArgument))) << 1)) >= 0) # else (((integerReceiver / integerArgument) >= -1073741824) && ((integerReceiver / integerArgument) <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), (((integerReceiver / integerArgument) << 1) | 1)); foo->stackPointer = sp; } else { foo->successFlag = 0; } } } else { /* begin primitiveFail */ foo->successFlag = 0; } } /* Primitive arithmetic operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveDivideLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt oopResult; sqLong result; sqInt sp; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (!((integerArg != 0) && ((integerRcvr % integerArg) == 0))) { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } result = integerRcvr / integerArg; oopResult = signed64BitIntegerFor(result); if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), oopResult); foo->stackPointer = sp; } } sqInt primitiveDoPrimitiveWithArgs(void) { register struct foo * foo = &fum; sqInt argumentArray; sqInt arraySize; sqInt cntxSize; sqInt index; sqInt primIdx; sqInt object; sqInt sp; sqInt sp1; sqInt sp2; sqInt sz; sqInt header; sqInt objectPointer; sqInt sz1; sqInt header1; sqInt successValue; sqInt oop; sqInt integerPointer; argumentArray = longAt(foo->stackPointer); /* begin fetchWordLengthOf: */ /* begin sizeBitsOf: */ header = longAt(argumentArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(argumentArray - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l1; } else { sz = header & (SIZE_MASK); goto l1; } l1: /* end sizeBitsOf: */; arraySize = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin fetchWordLengthOf: */ objectPointer = foo->activeContext; /* begin sizeBitsOf: */ header1 = longAt(objectPointer); if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(objectPointer - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); goto l2; } else { sz1 = header1 & (SIZE_MASK); goto l2; } l2: /* end sizeBitsOf: */; cntxSize = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); /* begin success: */ successValue = ((((usqInt) ((foo->stackPointer - foo->activeContext) - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD)) + arraySize) < cntxSize; foo->successFlag = successValue && foo->successFlag; if (!(((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { primIdx = (integerPointer >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; primIdx = 0; goto l3; } primIdx = null; l3: /* end stackIntegerValue: */; if (!(foo->successFlag)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); foo->primitiveIndex = primIdx; foo->argumentCount = arraySize; index = 1; while (index <= foo->argumentCount) { /* begin push: */ object = longAt((argumentArray + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; index += 1; } /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = argumentArray; foo->lkupClass = foo->nilObj; primitiveResponse(); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; argumentArray = oop; if (!(foo->successFlag)) { /* begin pop: */ foo->stackPointer -= arraySize * (BYTES_PER_WORD); /* begin pushInteger: */ /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), ((primIdx << 1) | 1)); foo->stackPointer = sp1; /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), argumentArray); foo->stackPointer = sp2; foo->argumentCount = 2; } } sqInt primitiveEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt result; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerArgument = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerReceiver = top1; /* begin compare31or32Bits:equal: */ if (((integerReceiver & 1)) && ((integerArgument & 1))) { result = integerReceiver == integerArgument; goto l1; } result = (positive32BitValueOf(integerReceiver)) == (positive32BitValueOf(integerArgument)); l1: /* end compare31or32Bits:equal: */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (result) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive comparison operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveEqualLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt sp; sqInt sp1; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (integerRcvr == integerArg) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* is the receiver the same object as the argument? */ sqInt primitiveEquivalent(void) { register struct foo * foo = &fum; sqInt otherObject; sqInt thisObject; sqInt top; sqInt top1; sqInt sp; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; otherObject = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisObject = top1; /* begin pushBool: */ if (thisObject == otherObject) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } /* receiver, args, then method are on top of stack. Execute method against receiver and args */ sqInt primitiveExecuteMethod(void) { register struct foo * foo = &fum; sqInt top; sqInt successValue; sqInt methodPointer; sqInt primBits; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; foo->newMethod = top; /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); /* begin success: */ successValue = (foo->argumentCount - 1) == (argumentCountOf(foo->newMethod)); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { foo->argumentCount -= 1; /* begin executeNewMethod */ if (foo->primitiveIndex > 0) { primitiveResponse(); if (foo->successFlag) { goto l1; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } l1: /* end executeNewMethod */; } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* receiver, argsArray, then method are on top of stack. Execute method against receiver and args */ sqInt primitiveExecuteMethodArgsArray(void) { register struct foo * foo = &fum; sqInt argCnt; sqInt argumentArray; sqInt methodArgument; sqInt top; sqInt top1; sqInt dst; sqInt in; sqInt lastIn; sqInt out; sqInt methodPointer; sqInt primBits; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; methodArgument = top; /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; argumentArray = top1; if (!((((methodArgument & 1) == 0) && (((((usqInt) (longAt(methodArgument))) >> 8) & 15) >= 12)) && (((argumentArray & 1) == 0) && (((((usqInt) (longAt(argumentArray))) >> 8) & 15) == 2)))) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); /* begin primitiveFail */ foo->successFlag = 0; return null; } argCnt = (((usqInt) (longAt((methodArgument + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 25) & 15; if (!(argCnt == (fetchWordLengthOf(argumentArray)))) { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); /* begin primitiveFail */ foo->successFlag = 0; return null; } /* begin transfer:from:to: */ dst = foo->stackPointer + (BYTES_PER_WORD); flag("Dan"); in = (argumentArray + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); lastIn = in + (argCnt * (BYTES_PER_WORD)); out = dst - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } /* begin unPop: */ foo->stackPointer += argCnt * (BYTES_PER_WORD); foo->newMethod = methodArgument; /* begin primitiveIndexOf: */ methodPointer = foo->newMethod; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; foo->primitiveIndex = (primBits & 511) + (((usqInt) primBits) >> 19); foo->argumentCount = argCnt; /* begin executeNewMethod */ if (foo->primitiveIndex > 0) { primitiveResponse(); if (foo->successFlag) { goto l1; } } activateNewMethod(); /* begin quickCheckForInterrupts */ if ((foo->interruptCheckCounter -= 1) <= 0) { checkForInterrupts(); } l1: /* end executeNewMethod */; foo->successFlag = 1; } sqInt primitiveExitToDebugger(void) { error("Exit to debugger at user request"); } /* Computes E raised to the receiver power. */ sqInt primitiveExp(void) { register struct foo * foo = &fum; double rcvr; rcvr = popFloat(); if (foo->successFlag) { pushFloat(exp(rcvr)); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Exponent part of this float. */ sqInt primitiveExponent(void) { register struct foo * foo = &fum; double frac; int pwr; double rcvr; sqInt sp; rcvr = popFloat(); if (foo->successFlag) { frac = frexp(rcvr, &pwr); /* begin pushInteger: */ /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), (((pwr - 1) << 1) | 1)); foo->stackPointer = sp; } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Call an external primitive. The external primitive methods contain as first literal an array consisting of: * The module name (String | Symbol) * The function name (String | Symbol) * The session ID (SmallInteger) [OBSOLETE] * The function index (Integer) in the externalPrimitiveTable For fast failures the primitive index of any method where the external prim is not found is rewritten in the method cache with zero. This allows for ultra fast responses as long as the method stays in the cache. The fast failure response relies on lkupClass being properly set. This is done in #addToMethodCacheSel:class:method:primIndex: to compensate for execution of methods that are looked up in a superclass (such as in primitivePerformAt). With the latest modifications (e.g., actually flushing the function addresses from the VM), the session ID is obsolete. But for backward compatibility it is still kept around. Also, a failed lookup is reported specially. If a method has been looked up and not been found, the function address is stored as -1 (e.g., the SmallInteger -1 to distinguish from 16rFFFFFFFF which may be returned from the lookup). It is absolutely okay to remove the rewrite if we run into any problems later on. It has an approximate speed difference of 30% per failed primitive call which may be noticable but if, for any reasons, we run into problems (like with J3) we can always remove the rewrite. */ sqInt primitiveExternalCall(void) { register struct foo * foo = &fum; void *addr; sqInt functionLength; sqInt functionName; sqInt index; sqInt lit; sqInt moduleLength; sqInt moduleName; sqInt successValue; sqInt header; sqInt successValue1; sqInt methodPointer; sqInt successValue2; sqInt successValue3; sqInt header1; sqInt sz; sqInt sz1; /* begin success: */ successValue1 = (literalCountOf(foo->newMethod)) > 0; foo->successFlag = successValue1 && foo->successFlag; if (!(foo->successFlag)) { return null; } /* begin literal:ofMethod: */ methodPointer = foo->newMethod; lit = longAt((methodPointer + (BASE_HEADER_SIZE)) + ((0 + LiteralStart) << (SHIFT_FOR_WORD))); /* begin success: */ successValue2 = (((lit & 1) == 0) && (((((usqInt) (longAt(lit))) >> 8) & 15) == 2)) && ((lengthOf(lit)) == 4); foo->successFlag = successValue2 && foo->successFlag; if (!(foo->successFlag)) { return null; } index = longAt((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD))); /* begin checkedIntegerValueOf: */ if ((index & 1)) { index = (index >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l1; } l1: /* end checkedIntegerValueOf: */; if (!(foo->successFlag)) { return null; } if (index < 0) { rewriteMethodCacheSelclassprimIndex(foo->messageSelector, foo->lkupClass, 0); /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if ((index > 0) && (index <= MaxExternalPrimitiveTableSize)) { addr = foo->externalPrimitiveTable[index - 1]; if (addr != 0) { rewriteMethodCacheSelclassprimIndexprimFunction(foo->messageSelector, foo->lkupClass, 1000 + index, addr); callExternalPrimitive(addr); return null; } /* begin primitiveFail */ foo->successFlag = 0; return null; } longAtput((lit + (BASE_HEADER_SIZE)) + (2 << (SHIFT_FOR_WORD)), ConstZero); longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ConstZero); moduleName = longAt((lit + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); if (moduleName == foo->nilObj) { moduleLength = 0; } else { /* begin success: */ successValue = ((moduleName & 1) == 0) && (((((usqInt) (longAt(moduleName))) >> 8) & 15) >= 8); foo->successFlag = successValue && foo->successFlag; /* begin lengthOf: */ header = longAt(moduleName); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(moduleName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = header & (SIZE_MASK); } sz -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { moduleLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l2; } if (((((usqInt) header) >> 8) & 15) < 8) { moduleLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l2; } else { moduleLength = (sz - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l2; } l2: /* end lengthOf:baseHeader:format: */; ; } functionName = longAt((lit + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD))); /* begin success: */ successValue3 = ((functionName & 1) == 0) && (((((usqInt) (longAt(functionName))) >> 8) & 15) >= 8); foo->successFlag = successValue3 && foo->successFlag; /* begin lengthOf: */ header1 = longAt(functionName); /* begin lengthOf:baseHeader:format: */ if ((header1 & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(functionName - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header1 & (SIZE_MASK); } sz1 -= header1 & (SIZE_4_BIT); if (((((usqInt) header1) >> 8) & 15) <= 4) { functionLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l3; } if (((((usqInt) header1) >> 8) & 15) < 8) { functionLength = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l3; } else { functionLength = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header1) >> 8) & 15) & 3); goto l3; } l3: /* end lengthOf:baseHeader:format: */; if (!(foo->successFlag)) { return null; } addr = ioLoadExternalFunctionOfLengthFromModuleOfLength(functionName + (BASE_HEADER_SIZE), functionLength, moduleName + (BASE_HEADER_SIZE), moduleLength); if (addr == 0) { index = -1; } else { /* add the function to the external primitive table */ index = addToExternalPrimitiveTable(addr); } /* begin success: */ foo->successFlag = (index >= 0) && foo->successFlag; longAtput((lit + (BASE_HEADER_SIZE)) + (3 << (SHIFT_FOR_WORD)), ((index << 1) | 1)); if (foo->successFlag && (addr != 0)) { rewriteMethodCacheSelclassprimIndexprimFunction(foo->messageSelector, foo->lkupClass, 1000 + index, addr); callExternalPrimitive(addr); } else { rewriteMethodCacheSelclassprimIndex(foo->messageSelector, foo->lkupClass, 0); } } sqInt primitiveFail(void) { foo->successFlag = 0; } /* Set specific primitive failure. */ sqInt primitiveFailFor(sqInt reasonCode) { register struct foo * foo = &fum; sqInt primFailCode; primFailCode = reasonCode; /* begin primitiveFail */ foo->successFlag = 0; } /* Primitive. Search up the context stack for the next method context marked for exception handling starting at the receiver. Return nil if none found */ sqInt primitiveFindHandlerContext(void) { register struct foo * foo = &fum; sqInt nilOop; sqInt thisCntx; sqInt sp; sqInt top; sqInt sp1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; thisCntx = top; nilOop = foo->nilObj; do { if (isHandlerMarked(thisCntx)) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), thisCntx); foo->stackPointer = sp; return null; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } while(!(thisCntx == nilOop)); /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->nilObj); foo->stackPointer = sp1; return null; } /* Primitive. Search up the context stack for the next method context marked for unwind handling from the receiver up to but not including the argument. Return nil if none found. */ sqInt primitiveFindNextUnwindContext(void) { register struct foo * foo = &fum; sqInt aContext; sqInt nilOop; sqInt thisCntx; sqInt unwindMarked; sqInt sp; sqInt header; sqInt meth; sqInt pIndex; sqInt top; sqInt oop; sqInt sp1; sqInt primBits; sqInt top1; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; aContext = top; /* begin fetchPointer:ofObject: */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; oop = top1; thisCntx = longAt((oop + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); nilOop = foo->nilObj; while (!((thisCntx == aContext) || (thisCntx == nilOop))) { /* begin isUnwindMarked: */ header = longAt(thisCntx); if (!(((((usqInt) header) >> 12) & 31) == 14)) { unwindMarked = 0; goto l1; } meth = longAt((thisCntx + (BASE_HEADER_SIZE)) + (MethodIndex << (SHIFT_FOR_WORD))); /* begin primitiveIndexOf: */ primBits = (((usqInt) (longAt((meth + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; pIndex = (primBits & 511) + (((usqInt) primBits) >> 19); unwindMarked = pIndex == 198; l1: /* end isUnwindMarked: */; if (unwindMarked) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), thisCntx); foo->stackPointer = sp; return null; } thisCntx = longAt((thisCntx + (BASE_HEADER_SIZE)) + (SenderIndex << (SHIFT_FOR_WORD))); } /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), nilOop); foo->stackPointer = sp1; return null; } sqInt primitiveFloatAdd(void) { register struct foo * foo = &fum; return primitiveFloatAddtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatAddtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr + arg); } } sqInt primitiveFloatDivide(void) { register struct foo * foo = &fum; return primitiveFloatDividebyArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatDividebyArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin success: */ foo->successFlag = (arg != 0.0) && foo->successFlag; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr / arg); } } } sqInt primitiveFloatEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr == arg; } } sqInt primitiveFloatGreaterthanArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr > arg; } } sqInt primitiveFloatGreaterOrEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatGreaterOrEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatGreaterOrEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr >= arg; } } sqInt primitiveFloatGreaterThan(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatGreaterthanArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatLessthanArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr < arg; } } sqInt primitiveFloatLessOrEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatLessOrEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatLessOrEqualtoArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { return rcvr <= arg; } } sqInt primitiveFloatLessThan(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatLessthanArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatMultiply(void) { register struct foo * foo = &fum; return primitiveFloatMultiplybyArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatMultiplybyArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr * arg); } } sqInt primitiveFloatNotEqual(void) { register struct foo * foo = &fum; sqInt aBool; sqInt sp; sqInt sp1; aBool = primitiveFloatEqualtoArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (!aBool) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveFloatSubtract(void) { register struct foo * foo = &fum; return primitiveFloatSubtractfromArg(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))), longAt(foo->stackPointer)); } sqInt primitiveFloatSubtractfromArg(sqInt rcvrOop, sqInt argOop) { register struct foo * foo = &fum; double arg; double rcvr; /* begin loadFloatOrIntFrom: */ if ((rcvrOop & 1)) { rcvr = ((double) ((rcvrOop >> 1)) ); goto l1; } if ((fetchClassOfNonInt(rcvrOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { rcvr = floatValueOf(rcvrOop); goto l1; } foo->successFlag = 0; l1: /* end loadFloatOrIntFrom: */; /* begin loadFloatOrIntFrom: */ if ((argOop & 1)) { arg = ((double) ((argOop >> 1)) ); goto l2; } if ((fetchClassOfNonInt(argOop)) == (fetchPointerofObject(ClassFloat, foo->specialObjectsOop))) { arg = floatValueOf(argOop); goto l2; } foo->successFlag = 0; l2: /* end loadFloatOrIntFrom: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); pushFloat(rcvr - arg); } } /* Clear the method lookup cache. This must be done after every programming change. */ sqInt primitiveFlushCache(void) { register struct foo * foo = &fum; sqInt aCompiledMethod; sqInt i; sqInt i1; /* begin flushMethodCache */ for (i = 1; i <= MethodCacheSize; i += 1) { foo->methodCache[i] = 0; } /* begin flushAtCache */ for (i1 = 1; i1 <= AtCacheTotalSize; i1 += 1) { foo->atCache[i1] = 0; } /* begin compilerFlushCacheHook: */ aCompiledMethod = null; if (foo->compilerInitialized) { compilerFlushCache(aCompiledMethod); } } /* The receiver is a compiledMethod. Clear all entries in the method lookup cache that refer to this method, presumably because it has been redefined, overridden or removed. */ sqInt primitiveFlushCacheByMethod(void) { register struct foo * foo = &fum; sqInt i; sqInt oldMethod; sqInt probe; oldMethod = longAt(foo->stackPointer); probe = 0; for (i = 1; i <= MethodCacheEntries; i += 1) { if ((foo->methodCache[probe + MethodCacheMethod]) == oldMethod) { foo->methodCache[probe + MethodCacheSelector] = 0; } probe += MethodCacheEntrySize; } /* begin compilerFlushCacheHook: */ if (foo->compilerInitialized) { compilerFlushCache(oldMethod); } } /* The receiver is a message selector. Clear all entries in the method lookup cache with this selector, presumably because an associated method has been redefined. */ sqInt primitiveFlushCacheSelective(void) { register struct foo * foo = &fum; sqInt i; sqInt probe; sqInt selector; selector = longAt(foo->stackPointer); probe = 0; for (i = 1; i <= MethodCacheEntries; i += 1) { if ((foo->methodCache[probe + MethodCacheSelector]) == selector) { foo->methodCache[probe + MethodCacheSelector] = 0; } probe += MethodCacheEntrySize; } } /* Primitive. Flush all the existing external primitives in the image thus forcing a reload on next invokation. */ sqInt primitiveFlushExternalPrimitives(void) { return flushExternalPrimitives(); } /* On some platforms, this primitive forces enqueued display updates to be processed immediately. On others, it does nothing. */ sqInt primitiveForceDisplayUpdate(void) { ioForceDisplayUpdate(); } /* Set force tenure flag to true, this forces a tenure operation on the next incremental GC */ EXPORT(sqInt) primitiveForceTenure(void) { foo->forceTenureFlag = 1; } /* On platforms that support it, this primitive prints the receiver, assumed to be a Form, to the default printer. */ sqInt primitiveFormPrint(void) { register struct foo * foo = &fum; sqInt bitsArray; sqInt bitsArraySize; sqInt depth; sqInt h; double hScale; sqInt landscapeFlag; sqInt ok; sqInt pixelsPerWord; sqInt rcvr; double vScale; sqInt w; sqInt wordsPerLine; sqInt fmt; sqInt header; sqInt sz; /* begin booleanValueOf: */ if ((longAt(foo->stackPointer)) == foo->trueObj) { landscapeFlag = 1; goto l2; } if ((longAt(foo->stackPointer)) == foo->falseObj) { landscapeFlag = 0; goto l2; } foo->successFlag = 0; landscapeFlag = null; l2: /* end booleanValueOf: */; vScale = floatValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); hScale = floatValueOf(longAt(foo->stackPointer - (2 * (BYTES_PER_WORD)))); rcvr = longAt(foo->stackPointer - (3 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } if (foo->successFlag) { if (!((((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) <= 4)) && ((lengthOf(rcvr)) >= 4))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } } if (foo->successFlag) { bitsArray = longAt((rcvr + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD))); w = fetchIntegerofObject(1, rcvr); h = fetchIntegerofObject(2, rcvr); depth = fetchIntegerofObject(3, rcvr); if (!((w > 0) && (h > 0))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } pixelsPerWord = 32 / depth; wordsPerLine = (w + (pixelsPerWord - 1)) / pixelsPerWord; if ((!((rcvr & 1))) && (((bitsArray & 1) == 0) && (isWordsOrBytesNonInt(bitsArray)))) { /* begin byteLengthOf: */ header = longAt(bitsArray); if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(bitsArray - ((BYTES_PER_WORD) * 2))) & (ALL_BUT_TYPE_MASK); } else { sz = header & (SIZE_MASK); } fmt = (((usqInt) header) >> 8) & 15; if (fmt < 8) { bitsArraySize = sz - (BASE_HEADER_SIZE); goto l1; } else { bitsArraySize = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end byteLengthOf: */; /* begin success: */ foo->successFlag = (bitsArraySize == ((wordsPerLine * h) * 4)) && foo->successFlag; } else { /* begin success: */ foo->successFlag = 0 && foo->successFlag; } } if (foo->successFlag) { if ((BYTES_PER_WORD) == 8) { ok = ioFormPrint(bitsArray + 8, w, h, depth, hScale, vScale, landscapeFlag); } else { ok = ioFormPrint(bitsArray + 4, w, h, depth, hScale, vScale, landscapeFlag); } /* begin success: */ foo->successFlag = ok && foo->successFlag; } if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 3 * (BYTES_PER_WORD); } } sqInt primitiveFractionalPart(void) { register struct foo * foo = &fum; double frac; double rcvr; double trunc; rcvr = popFloat(); if (foo->successFlag) { frac = modf(rcvr, &trunc); pushFloat(frac); } else { /* begin unPop: */ foo->stackPointer += 1 * (BYTES_PER_WORD); } } /* Do a full garbage collection and return the number of bytes available (including swap space if dynamic memory management is supported). */ sqInt primitiveFullGC(void) { register struct foo * foo = &fum; sqInt object; sqInt sp; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); incrementalGC(); fullGC(); /* begin push: */ object = positive64BitIntegerFor(((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(1))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } /* Fetch the system attribute with the given integer ID. The result is a string, which will be empty if the attribute is not defined. */ sqInt primitiveGetAttribute(void) { register struct foo * foo = &fum; sqInt attr; sqInt s; sqInt sz; sqInt sp; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { attr = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; attr = 0; goto l1; } attr = null; l1: /* end stackIntegerValue: */; if (foo->successFlag) { sz = attributeSize(attr); } if (foo->successFlag) { s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); getAttributeIntoLength(attr, s + (BASE_HEADER_SIZE), sz); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((2 - 1) * (BYTES_PER_WORD)), s); foo->stackPointer = sp; } } /* Primitive. Return the next input event from the VM event queue. */ sqInt primitiveGetNextEvent(void) { register struct foo * foo = &fum; sqInt arg; sqInt eventTypeIs; int evtBuf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; sqInt i; sqInt value; sqInt oop; ; arg = longAt(foo->stackPointer); if (!((((arg & 1) == 0) && (((((usqInt) (longAt(arg))) >> 8) & 15) == 2)) && ((slotSizeOf(arg)) == 8))) { /* begin primitiveFail */ foo->successFlag = 0; return null; } ioGetNextEvent(((sqInputEvent*) evtBuf)); if (!(foo->successFlag)) { return null; } eventTypeIs = evtBuf[0]; /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) (evtBuf[0]))) ^ ((((int) (evtBuf[0]))) << 1)) >= 0) # else (((evtBuf[0]) >= -1073741824) && ((evtBuf[0]) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (0 << (SHIFT_FOR_WORD)), (((evtBuf[0]) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } if (eventTypeIs == 6) { for (i = 1; i <= 7; i += 1) { value = evtBuf[i]; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) arg)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(arg, value); } longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), value); } } else { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) ((evtBuf[1]) & MillisecondClockMask))) ^ ((((int) ((evtBuf[1]) & MillisecondClockMask))) << 1)) >= 0) # else ((((evtBuf[1]) & MillisecondClockMask) >= -1073741824) && (((evtBuf[1]) & MillisecondClockMask) <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (1 << (SHIFT_FOR_WORD)), ((((evtBuf[1]) & MillisecondClockMask) << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } if (!(foo->successFlag)) { return null; } for (i = 2; i <= 7; i += 1) { value = evtBuf[i]; if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { /* begin storeInteger:ofObject:withValue: */ if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), ((value << 1) | 1)); } else { /* begin primitiveFail */ foo->successFlag = 0; } } else { /* begin pushRemappableOop: */ foo->remapBuffer[(foo->remapBufferCount += 1)] = arg; value = positive32BitIntegerFor(value); /* begin popRemappableOop */ oop = foo->remapBuffer[foo->remapBufferCount]; foo->remapBufferCount -= 1; arg = oop; /* begin storePointer:ofObject:withValue: */ if ((((usqInt) arg)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(arg, value); } longAtput((arg + (BASE_HEADER_SIZE)) + (i << (SHIFT_FOR_WORD)), value); } } } if (!(foo->successFlag)) { return null; } /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } sqInt primitiveGreaterOrEqual(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt sp; sqInt sp1; sqInt integerPointer; sqInt top; sqInt integerPointer1; sqInt top1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } integerArgument = null; l1: /* end popInteger */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } integerReceiver = null; l2: /* end popInteger */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver >= integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive comparison operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveGreaterOrEqualLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt sp; sqInt sp1; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (integerRcvr >= integerArg) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } sqInt primitiveGreaterThan(void) { register struct foo * foo = &fum; sqInt integerArgument; sqInt integerReceiver; sqInt sp; sqInt sp1; sqInt integerPointer; sqInt top; sqInt integerPointer1; sqInt top1; /* begin popInteger */ /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer = top; /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { integerArgument = (integerPointer >> 1); goto l1; } else { /* begin primitiveFail */ foo->successFlag = 0; integerArgument = 0; goto l1; } integerArgument = null; l1: /* end popInteger */; /* begin popInteger */ /* begin popStack */ top1 = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; integerPointer1 = top1; /* begin checkedIntegerValueOf: */ if ((integerPointer1 & 1)) { integerReceiver = (integerPointer1 >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; integerReceiver = 0; goto l2; } integerReceiver = null; l2: /* end popInteger */; /* begin checkBooleanResult: */ if (foo->successFlag) { /* begin pushBool: */ if (integerReceiver > integerArgument) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } else { /* begin unPop: */ foo->stackPointer += 2 * (BYTES_PER_WORD); } } /* Primitive comparison operations for large integers in 64 bit range */ EXPORT(sqInt) primitiveGreaterThanLargeIntegers(void) { register struct foo * foo = &fum; sqLong integerArg; sqLong integerRcvr; sqInt sp; sqInt sp1; integerArg = signed64BitValueOf(longAt(foo->stackPointer - (0 * (BYTES_PER_WORD)))); integerRcvr = signed64BitValueOf(longAt(foo->stackPointer - (1 * (BYTES_PER_WORD)))); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); /* begin pushBool: */ if (integerRcvr > integerArg) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* Answer an integer identifying the type of image. The image version number may identify the format of the image (e.g. 32 or 64-bit word size) or specific requirements of the image (e.g. block closure support required). This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveImageFormatVersion(void) { register struct foo * foo = &fum; sqInt oop; sqInt sp; /* begin pop:thenPush: */ oop = positive32BitIntegerFor(imageFormatVersionNumber); longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), oop); foo->stackPointer = sp; } /* When called with a single string argument, record the string as the current image file name. When called with zero arguments, return a string containing the current image file name. */ sqInt primitiveImageName(void) { register struct foo * foo = &fum; sqInt okToRename; sqInt s; void *sCRIfn; sqInt sz; sqInt sp; sqInt classOop; sqInt ccIndex; sqInt cl; sqInt oop1; sqInt oop2; sqInt oop; if (foo->argumentCount == 1) { /* If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok */ sCRIfn = ioLoadFunctionFrom("secCanRenameImage", "SecurityPlugin"); if (sCRIfn != 0) { okToRename = ((sqInt (*)(void))sCRIfn)(); if (!(okToRename)) { /* begin primitiveFail */ foo->successFlag = 0; return null; } } s = longAt(foo->stackPointer); /* begin assertClassOf:is: */ /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; classOop = longAt((oop + (BASE_HEADER_SIZE)) + (ClassString << (SHIFT_FOR_WORD))); if ((s & 1)) { foo->successFlag = 0; goto l1; } ccIndex = (((usqInt) (longAt(s))) >> 12) & 31; if (ccIndex == 0) { cl = (longAt(s - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop2 = foo->specialObjectsOop; oop1 = longAt((oop2 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); cl = longAt((oop1 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); } /* begin success: */ foo->successFlag = (cl == classOop) && foo->successFlag; l1: /* end assertClassOf:is: */; if (foo->successFlag) { sz = stSizeOf(s); imageNamePutLength(s + (BASE_HEADER_SIZE), sz); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } } else { sz = imageNameSize(); s = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), sz); imageNameGetLength(s + (BASE_HEADER_SIZE), sz); /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), s); foo->stackPointer = sp; } } /* Do a quick, incremental garbage collection and return the number of bytes immediately available. (Note: more space may be made available by doing a full garbage collection. */ sqInt primitiveIncrementalGC(void) { register struct foo * foo = &fum; sqInt object; sqInt sp; /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); incrementalGC(); /* begin push: */ object = positive64BitIntegerFor(((longAt(foo->freeBlock)) & (ALL_BUT_TYPE_MASK)) + (sqMemoryExtraBytesLeft(0))); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } /* Note: We now have 10 bits of primitive index, but they are in two places for temporary backward compatibility. The time to unpack is negligible, since the reconstituted full index is stored in the method cache. */ sqInt primitiveIndexOf(sqInt methodPointer) { sqInt primBits; primBits = (((usqInt) (longAt((methodPointer + (BASE_HEADER_SIZE)) + (HeaderIndex << (SHIFT_FOR_WORD))))) >> 1) & 268435967; return (primBits & 511) + (((usqInt) primBits) >> 19); } /* Register the input semaphore. The argument is an index into the ExternalObjectsArray part of the specialObjectsArray and must have been allocated via 'Smalltalk registerExternalObject: the Semaphore' */ sqInt primitiveInputSemaphore(void) { register struct foo * foo = &fum; sqInt arg; arg = longAt(foo->stackPointer); if ((arg & 1)) { ioSetInputSemaphore((arg >> 1)); if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= 1 * (BYTES_PER_WORD); } return null; } } /* Return an integer indicating the reason for the most recent input interrupt. */ sqInt primitiveInputWord(void) { register struct foo * foo = &fum; sqInt sp; /* begin pop:thenPushInteger: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), ((0 << 1) | 1)); foo->stackPointer = sp; } sqInt primitiveInstVarAt(void) { register struct foo * foo = &fum; sqInt fixedFields; sqInt fmt; sqInt hdr; sqInt index; sqInt rcvr; sqInt totalLength; sqInt value; sqInt sp; sqInt sz; sqInt integerPointer; sqInt class; sqInt classFormat; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l3; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l3; } index = null; l3: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if (foo->successFlag) { hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l5; } if (fmt < 2) { fixedFields = totalLength; goto l5; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l4; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l4; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l4; } l4: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l5: /* end fixedFieldsOf:format:length: */; if (!((index >= 1) && (index <= fixedFields))) { foo->successFlag = 0; } } if (foo->successFlag) { /* begin subscript:with:format: */ if (fmt <= 4) { value = longAt((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD))); goto l2; } if (fmt < 8) { value = positive32BitIntegerFor(long32At((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2))); goto l2; } else { value = (((byteAt((rcvr + (BASE_HEADER_SIZE)) + (index - 1))) << 1) | 1); goto l2; } l2: /* end subscript:with:format: */; } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), value); foo->stackPointer = sp; } } sqInt primitiveInstVarAtPut(void) { register struct foo * foo = &fum; sqInt fixedFields; sqInt fmt; sqInt hdr; sqInt index; sqInt newValue; sqInt rcvr; sqInt totalLength; sqInt sp; sqInt sz; sqInt valueToStore; sqInt integerPointer; sqInt class; sqInt classFormat; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt oop3; newValue = longAt(foo->stackPointer); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l2; } index = null; l2: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if (foo->successFlag) { hdr = longAt(rcvr); fmt = (((usqInt) hdr) >> 8) & 15; /* begin lengthOf:baseHeader:format: */ if ((hdr & TypeMask) == HeaderTypeSizeAndClass) { sz = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz = hdr & (SIZE_MASK); } sz -= hdr & (SIZE_4_BIT); if (fmt <= 4) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (fmt < 8) { totalLength = ((usqInt) (sz - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { totalLength = (sz - (BASE_HEADER_SIZE)) - (fmt & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin fixedFieldsOf:format:length: */ if ((fmt > 4) || (fmt == 2)) { fixedFields = 0; goto l4; } if (fmt < 2) { fixedFields = totalLength; goto l4; } /* begin fetchClassOf: */ if ((rcvr & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; class = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l3; } ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31; if (ccIndex == 0) { class = (longAt(rcvr - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l3; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); class = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l3; } l3: /* end fetchClassOf: */; classFormat = (longAt((class + (BASE_HEADER_SIZE)) + (InstanceSpecificationIndex << (SHIFT_FOR_WORD)))) - 1; fixedFields = (((((usqInt) classFormat) >> 11) & 192) + ((((usqInt) classFormat) >> 2) & 63)) - 1; l4: /* end fixedFieldsOf:format:length: */; if (!((index >= 1) && (index <= fixedFields))) { foo->successFlag = 0; } } if (foo->successFlag) { /* begin subscript:with:storing:format: */ if (fmt <= 4) { /* begin storePointer:ofObject:withValue: */ if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(rcvr, newValue); } longAtput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << (SHIFT_FOR_WORD)), newValue); } else { if (fmt < 8) { valueToStore = positive32BitValueOf(newValue); if (foo->successFlag) { long32Atput((rcvr + (BASE_HEADER_SIZE)) + ((index - 1) << 2), valueToStore); } } else { if (!((newValue & 1))) { foo->successFlag = 0; } valueToStore = (newValue >> 1); if (!((valueToStore >= 0) && (valueToStore <= 255))) { foo->successFlag = 0; } if (foo->successFlag) { byteAtput((rcvr + (BASE_HEADER_SIZE)) + (index - 1), valueToStore); } } } } if (foo->successFlag) { /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - (((foo->argumentCount + 1) - 1) * (BYTES_PER_WORD)), newValue); foo->stackPointer = sp; } } /* Note: this primitive has been decommissioned. It is only here for short-term compatibility with an internal 2.3beta-d image that used this. It did not save much time and it complicated several things. Plus Jitter will do it right anyway. */ sqInt primitiveInstVarsPutFromStack(void) { register struct foo * foo = &fum; sqInt i; sqInt offsetBits; sqInt rcvr; sqInt valuePointer; /* Mark dirty so stores below can be unchecked */ rcvr = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); if ((((usqInt) rcvr)) < (((usqInt) foo->youngStart))) { beRootIfOld(rcvr); } for (i = 0; i <= (foo->argumentCount - 1); i += 1) { if ((i & 3) == 0) { offsetBits = positive32BitValueOf(literalofMethod(((sqInt) i >> 2), foo->newMethod)); } /* begin storePointerUnchecked:ofObject:withValue: */ valuePointer = longAt(foo->stackPointer - (i * (BYTES_PER_WORD))); longAtput((rcvr + (BASE_HEADER_SIZE)) + ((offsetBits & 255) << (SHIFT_FOR_WORD)), valuePointer); offsetBits = ((usqInt) offsetBits) >> 8; } /* begin pop: */ foo->stackPointer -= foo->argumentCount * (BYTES_PER_WORD); } /* Return the 32bit signed integer contents of a words receiver */ sqInt primitiveIntegerAt(void) { register struct foo * foo = &fum; sqInt addr; sqInt index; int intValue; sqInt rcvr; sqInt sz; sqInt value; sqInt object; sqInt sp; sqInt header; sqInt successValue; sqInt sp1; sqInt sz1; sqInt integerPointer; /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l2; } index = null; l2: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) == 6))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; /* begin success: */ successValue = (index >= 1) && (index <= sz); foo->successFlag = successValue && foo->successFlag; if (foo->successFlag) { /* for zero indexing */ addr = ((rcvr + (BASE_HEADER_SIZE)) - 4) + (index * 4); value = intAt(addr); /* begin pop: */ foo->stackPointer -= 2 * (BYTES_PER_WORD); if ( # ifdef SQ_HOST32 // cast to int for 64 bit image on 32 bit host (((((int) value)) ^ ((((int) value)) << 1)) >= 0) # else ((value >= -1073741824) && (value <= 1073741823)) # endif // SQ_HOST32 ) { /* begin pushInteger: */ /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), ((value << 1) | 1)); foo->stackPointer = sp1; } else { /* 32 bit int may have been stored in 32 or 64 bit sqInt */ intValue = value; /* begin push: */ object = signed32BitIntegerFor(intValue); longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), object); foo->stackPointer = sp; } } } /* Return the 32bit signed integer contents of a words receiver */ sqInt primitiveIntegerAtPut(void) { register struct foo * foo = &fum; sqInt addr; sqInt index; sqInt rcvr; sqInt sz; sqInt value; sqInt valueOop; sqInt sp; sqInt header; sqInt sz1; sqInt integerPointer; valueOop = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); /* begin stackIntegerValue: */ integerPointer = longAt(foo->stackPointer - (1 * (BYTES_PER_WORD))); /* begin checkedIntegerValueOf: */ if ((integerPointer & 1)) { index = (integerPointer >> 1); goto l2; } else { /* begin primitiveFail */ foo->successFlag = 0; index = 0; goto l2; } index = null; l2: /* end stackIntegerValue: */; rcvr = longAt(foo->stackPointer - (2 * (BYTES_PER_WORD))); if ((rcvr & 1)) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if (!(((rcvr & 1) == 0) && (((((usqInt) (longAt(rcvr))) >> 8) & 15) == 6))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } /* begin lengthOf: */ header = longAt(rcvr); /* begin lengthOf:baseHeader:format: */ if ((header & TypeMask) == HeaderTypeSizeAndClass) { sz1 = (longAt(rcvr - ((BYTES_PER_WORD) * 2))) & (LONG_SIZE_MASK); } else { sz1 = header & (SIZE_MASK); } sz1 -= header & (SIZE_4_BIT); if (((((usqInt) header) >> 8) & 15) <= 4) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> (SHIFT_FOR_WORD); goto l1; } if (((((usqInt) header) >> 8) & 15) < 8) { sz = ((usqInt) (sz1 - (BASE_HEADER_SIZE))) >> 2; goto l1; } else { sz = (sz1 - (BASE_HEADER_SIZE)) - (((((usqInt) header) >> 8) & 15) & 3); goto l1; } l1: /* end lengthOf:baseHeader:format: */; if (!((index >= 1) && (index <= sz))) { /* begin success: */ foo->successFlag = 0 && foo->successFlag; return null; } if ((valueOop & 1)) { value = (valueOop >> 1); } else { value = signed32BitValueOf(valueOop); } if (foo->successFlag) { /* for zero indexing */ addr = ((rcvr + (BASE_HEADER_SIZE)) - 4) + (index * 4); value = intAtput(addr, value); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((3 - 1) * (BYTES_PER_WORD)), valueOop); foo->stackPointer = sp; } } /* Answer a string corresponding to the version of the interpreter source. This represents the version level of the Smalltalk source code (interpreter and various plugins) that is translated to C by a CCodeGenerator, as distinct from the external platform source code, typically written in C and managed separately for each platform. This is a named (not numbered) primitive in the null module (ie the VM) */ EXPORT(sqInt) primitiveInterpreterSourceVersion(void) { register struct foo * foo = &fum; char *cString; sqInt len; void * p; sqInt versionString; sqInt sp; cString = InterpreterSourceVersion; len = strlen(cString); versionString = instantiateClassindexableSize(fetchPointerofObject(ClassString, foo->specialObjectsOop), len); /* begin arrayValueOf: */ if ((!((versionString & 1))) && (((versionString & 1) == 0) && (isWordsOrBytesNonInt(versionString)))) { p = pointerForOop(versionString + (BASE_HEADER_SIZE)); goto l1; } /* begin primitiveFail */ foo->successFlag = 0; l1: /* end arrayValueOf: */; strncpy(p, cString, len); /* begin pop:thenPush: */ longAtput(sp = foo->stackPointer - ((1 - 1) * (BYTES_PER_WORD)), versionString); foo->stackPointer = sp; } /* Register the user interrupt semaphore. If the argument is not a Semaphore, unregister the current interrupt semaphore. */ sqInt primitiveInterruptSemaphore(void) { register struct foo * foo = &fum; sqInt arg; sqInt top; sqInt oop; sqInt oop1; sqInt valuePointer; /* begin popStack */ top = longAt(foo->stackPointer); foo->stackPointer -= BYTES_PER_WORD; arg = top; if ((fetchClassOf(arg)) == (fetchPointerofObject(ClassSemaphore, foo->specialObjectsOop))) { /* begin storePointer:ofObject:withValue: */ oop = foo->specialObjectsOop; if ((((usqInt) oop)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop, arg); } longAtput((oop + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD)), arg); } else { /* begin storePointer:ofObject:withValue: */ oop1 = foo->specialObjectsOop; valuePointer = foo->nilObj; if ((((usqInt) oop1)) < (((usqInt) foo->youngStart))) { possibleRootStoreIntovalue(oop1, valuePointer); } longAtput((oop1 + (BASE_HEADER_SIZE)) + (TheInterruptSemaphore << (SHIFT_FOR_WORD)), valuePointer); } } /* Primitive. 'Invoke' an object like a function, sending the special message run: originalSelector with: arguments in: aReceiver. */ sqInt primitiveInvokeObjectAsMethod(void) { register struct foo * foo = &fum; sqInt lookupClass; sqInt newReceiver; sqInt runArgs; sqInt runReceiver; sqInt runSelector; sqInt oop; sqInt sp; sqInt sp1; sqInt sp2; sqInt sp3; sqInt ccIndex; sqInt oop1; sqInt oop2; sqInt count; sqInt src; sqInt in; sqInt lastIn; sqInt out; sqInt oop3; runArgs = instantiateClassindexableSize(fetchPointerofObject(ClassArray, foo->specialObjectsOop), foo->argumentCount); beRootIfOld(runArgs); /* begin transfer:from:to: */ count = foo->argumentCount; src = foo->stackPointer - ((foo->argumentCount - 1) * (BYTES_PER_WORD)); flag("Dan"); in = src - (BYTES_PER_WORD); lastIn = in + (count * (BYTES_PER_WORD)); out = (runArgs + (BASE_HEADER_SIZE)) - (BYTES_PER_WORD); while ((((usqInt) in)) < (((usqInt) lastIn))) { longAtput(out += BYTES_PER_WORD, longAt(in += BYTES_PER_WORD)); } runSelector = foo->messageSelector; runReceiver = longAt(foo->stackPointer - (foo->argumentCount * (BYTES_PER_WORD))); /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); newReceiver = foo->newMethod; /* begin fetchPointer:ofObject: */ oop = foo->specialObjectsOop; foo->messageSelector = longAt((oop + (BASE_HEADER_SIZE)) + (SelectorRunWithIn << (SHIFT_FOR_WORD))); foo->argumentCount = 3; /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), newReceiver); foo->stackPointer = sp; /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), runSelector); foo->stackPointer = sp1; /* begin push: */ longAtput(sp2 = foo->stackPointer + (BYTES_PER_WORD), runArgs); foo->stackPointer = sp2; /* begin push: */ longAtput(sp3 = foo->stackPointer + (BYTES_PER_WORD), runReceiver); foo->stackPointer = sp3; /* begin fetchClassOf: */ if ((newReceiver & 1)) { /* begin fetchPointer:ofObject: */ oop1 = foo->specialObjectsOop; lookupClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassInteger << (SHIFT_FOR_WORD))); goto l1; } ccIndex = (((usqInt) (longAt(newReceiver))) >> 12) & 31; if (ccIndex == 0) { lookupClass = (longAt(newReceiver - (BASE_HEADER_SIZE))) & (ALL_BUT_TYPE_MASK); goto l1; } else { /* begin fetchPointer:ofObject: */ /* begin fetchPointer:ofObject: */ oop3 = foo->specialObjectsOop; oop2 = longAt((oop3 + (BASE_HEADER_SIZE)) + (CompactClasses << (SHIFT_FOR_WORD))); lookupClass = longAt((oop2 + (BASE_HEADER_SIZE)) + ((ccIndex - 1) << (SHIFT_FOR_WORD))); goto l1; } l1: /* end fetchClassOf: */; findNewMethodInClass(lookupClass); executeNewMethodFromCache(); foo->successFlag = 1; } /* Primitive. Answer whether the argument to the primitive is a root for young space */ EXPORT(sqInt) primitiveIsRoot(void) { register struct foo * foo = &fum; sqInt oop; sqInt trueOrFalse; sqInt sp; sqInt sp1; sqInt oop1; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; oop = null; goto l1; } oop = oop1; l1: /* end stackObjectValue: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin pushBool: */ trueOrFalse = (longAt(oop)) & (ROOT_BIT); if (trueOrFalse) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* Primitive. Answer whether the argument to the primitive resides in young space. */ EXPORT(sqInt) primitiveIsYoung(void) { register struct foo * foo = &fum; sqInt oop; sqInt trueOrFalse; sqInt sp; sqInt sp1; sqInt oop1; /* begin stackObjectValue: */ oop1 = longAt(foo->stackPointer - (0 * (BYTES_PER_WORD))); if ((oop1 & 1)) { /* begin primitiveFail */ foo->successFlag = 0; oop = null; goto l1; } oop = oop1; l1: /* end stackObjectValue: */; if (foo->successFlag) { /* begin pop: */ foo->stackPointer -= (foo->argumentCount + 1) * (BYTES_PER_WORD); /* begin pushBool: */ trueOrFalse = (((usqInt) oop)) >= (((usqInt) foo->youngStart)); if (trueOrFalse) { /* begin push: */ longAtput(sp = foo->stackPointer + (BYTES_PER_WORD), foo->trueObj); foo->stackPointer = sp; } else { /* begin push: */ longAtput(sp1 = foo->stackPointer + (BYTES_PER_WORD), foo->falseObj); foo->stackPointer = sp1; } } } /* Obsolete on virtually all platforms; old style input polling code. Return the next keycode and remove it from the input buffer. The low byte is the 8-bit ISO character. The next four bits are the Smalltalk modifier bits

Welcome to Unix Squeak!
(Mac OS X edition)

Preface

The help viewer is buggy (at least mine is). This document is more than a page long, but there's no scroll bar. To get a scroll bar, resize the window slightly.

Introduction

This software is still very much in alpha test. This means that it will crash (frequently) at random times for no obvious reason. By continuing to use this software you agree implicitly to act as an alpha tester and hence to the following:
Subsequent to any and all crashes you will send the contents of the file Library/Logs/CrashReporter/squeak.crash.log (relative to your home directory), along with a brief description of what you were doing at the time, by email to: ian.piumarta@squeakland.org  (If you can also concoct a recipe to reproduce the crash reliably then you'll [probably] win a faster resolution of the problem.)

Installing Squeak

The '.app' bundle does not come with '.image/.changes' or '.sources' files. You will have to get these from elsewhere (at the Squeak Foundation ftp site, for example). If you keep the '.sources' file (or a link to it) in the same directory as your image(s) you'll be fine. Otherwise you can put it (or a link to it) in the 'Contents/MacOS' folder of the app bundle. You can also put the distributed '.image/.changes' files in the 'Contents/Resources' folder too, if you want a convenient place from which to begin working in a fresh image (see Providing a default image below).

Starting Squeak

Squeak can be started either from the Finder (by double-clicking on the VM or an image file) or from the command line in a terminal window. If it is started from the command line then various features (that are not available when launching it from the Finder) become available through command line options, such as running without a window (useful if the application is a Swiki or some other kind of server, for example). (Some of these options will soon be available via a preferences panel in Quartz, when I get round to implementing it.) A list of the available options is available by running Squeak from the command line and giving it the option `-help'.

If X11 is installed then display can be via X11 or via Quartz. The default is X11 if the environment variable DISPLAY is set and Quartz if Squeak is launched from the Finder. To force one or the other, Squeak can be run from the command line with the option `-quartz' or `-display <your-display>' as desired.

Note that to run Squeak in a remote window the X11 libraries must be installed on the client machine, i.e., the one on which Squeak is running. (More accurately, Squeak requires at least libX11 and libXext installed for it to be able to connect to a remote display server).

Note also that options relating to the display are only recognised after Squeak has been told which kind of display is to be used. This applies even to the `-help' option. For example, to see a list of options that includes those specific to Quartz, Squeak must be run with the options `-quartz -help', in that order.

Providing a default image

When launched from the Finder, if Squeak cannot find a default image to run in the current directory then it looks for the files squeak.image and squeak.changes in the Squeak.app/Contents/Resources directory. If these files exist then Squeak will offer to copy them (with a dialogue to choose the destination) before launching. (If these files do not exist and there is no obvious default image to run in the current directory, then double-clicking the VM will enter an `open' dialogue to locate an existing image to use.)

Known bugs, limitiations and quirks

  • Croquet requires some new support code (containing GLX classes appropriate for Quartz and big-endian X11). If these haven't been filed-in then Croquet probably won't work. (Forgetfulness on my part not withstanding, a copy of the required changeset should be in the Squeak.app/Contents/Resources directory, for convenience.)
  • The Squeak window will refuse to resize if there are any TeapotMorphs open. This is to avoid a very nasty bug (that freezes the entire machine) in Mac OS X, which cannot cope with the VM thread updating OpenGL content while the (separate) UI thread is trying to invalidate the corresponding graphics state during window resizing. (Switching to/from fullscreen mode with open TeapotMorphs does work properly.)
  • Croquet might run slower than normal since there is no MatrixPlugin included with Unix Squeak. The plugin is not included since I do not have (nor can I find anywhere) the sources for it.
  • In order to support Croquet under Mac OS X (which has no way to associate a default memory size with an application) Squeak will determine how much virtual memory is available (up to a maximum of 1 gigabyte) and reserve that amount for dynamically growing the object memory. (This memory will only be physically allocated if/when the image tries to grow disproportionately, so this behaviour shouldn't rattle the disk under normal circumstances.)
  • To display Croquet in an X11 window it is currently necessary to set the environment variable LD_LIBRARY_PATH=/usr/X11R6/lib:/usr/lib:/lib before starting the VM. (This is necessary because of a bug in the Mac OS X dynamic linker, although a subsequent version of Unix Squeak might elect to cure this problem by brute force inside the VM.)
  • There must be a SqueakV3.sources file (or a link/alias to one) in the same directory as the image. There is currently no start-up dialogue to locate a sources file in an alternate location. (This is fairly high on the to-do list. If it becomes a nuisance then placing a copy/link/alias of/to the sources file in the Squeak.app/Contents/MacOS directory will probably do the trick.)
  • Command-tab (fullscreen switch) does not work. There appears to be no way in Mac OS X to intercept the corresponding key event before it's snarfed by the dock (to cycle the key window between the currently active applications).
  • When starting sound recording, input will revert to the default device. This is almost certainly not the device from which you wanted to record. (The input can be pointed back to a more suitable source using the sound pane in the system preferences, after the sound recorder has been started in Squeak.)
  • There is currently no support for MIDI, tablets or joysticks.
  • Printing from the File menu is not yet implemented (although the menu items are already there as placeholders).
  • Printing a Form from within Squeak is only partially implemented. (The output is monochrome and scaling/orientation options are ignored.)
  • The Squeak window does not accept `first click'. (In other words, clicking in the window while it's inactive will activate Squeak but the click will otherwise be ignored.) If this bothers you, then it shouldn't.
  • There is (currently) no way to open multiple images at the same time from the Finder. (Squeak can be run multiple times from the command line if working with more than one image at the same time is required.)
  • If the VM locks up for any reason while in fullscreen mode there is a chance that Option-Command-Escape will not work. (The `Force Quit' dialog is actually there, it's just completely obscured by the Squeak window which is at a higher level [in fact, the highest] in the display order.) If this occurs then the first thing to try is pressing RETURN twice (after pressing Option-Command-Escape). If that doesn't kill Squeak then the only other escape route is to log in to the machine remotely and kill the Squeak process by hand. (An `emergency exit' key combination will soon be implemented by the VM itself to cater for this situation. This is right at the top of the to-do list.)
  • There is a small danger of the Window Server becoming catatonic while running Croquet (since there may be outstanding issues with multithreaded OpenGL that I've not yet caught and eliminated). The symptoms are a spinning `coloured carousel' cursor and absolutely no response whatsoever from any window on the screen. If this happens, the only way out is logging in to the machine remotely (as root) and then typing: sync; reboot  (There could well be a several-minute delay while the kernel tries to kill an already undead Window Server before the reboot actually happens.)
  • Enabling (or disabling) the command keys via the Window menu causes the Squeak menu title to lose boldface. This is a bit of a mystery...
  • Help is only available when Squeak is launched from the Finder. (I haven't figured out why it behaves that way, but it's on the list.)
  • The Squeak Help Book (this document) has not yet been written.
  • As you've no doubt just discovered, the Help Viewer refuses to display a scroll bar when the content is too large until you try to resize the window. It's also incapable of scrolling in response to the arrow keys. Ho hum.

Support

The
Squeak home page contains useful information and links to various resources.

The Unix Squeak home page has further information, source code, and the latest downloads specific to Unix and MacOSX.

If you have problems, questions, bugs to report, or specific feature requests concerning the Unix Squeak VM, contact me directly. ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/Squeak.h ================================================ // -*- ObjC -*- @interface Squeak : NSApplication - (void) applicationDidFinishLaunching: (NSNotification *)note; - (void) applicationDidChangeScreenParameters: (NSNotification *)note; - (void) unhideAllApplications: (id)sender; - (BOOL) windowShouldClose: (id)sender; - (void) maybeTerminate: (id)sender; - (void) terminate: (id)sender; - (void) performEnableKeys: (id)sender; - (void) performDisableKeys: (id)sender; @end ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/Squeak.m ================================================ #import @implementation Squeak + (void) initialize { NSMutableDictionary *dict; NSUserDefaults *defaults; defaults= [NSUserDefaults standardUserDefaults]; dict= [NSMutableDictionary dictionary]; [dict setObject: @"YES" forKey: @"AppleDockIconEnabled"]; [defaults registerDefaults: dict]; } static char *documentName= 0; -(BOOL) application: (NSApplication *) theApplication openFile: (NSString *) filename { if (fromFinder) documentName= strdup([filename cString]); return YES; } -(void) applicationDidFinishLaunching: (NSNotification *)note { int fds[2]; // this saves an awful lot of tedious mutex contention (and besides // is essentially free, since there's no way to avoid writing a // socket to inform aio of the availability of the event) #if 0 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0) { perror("socketpair"); exit(1); } osXfd= fds[0]; stXfd= fds[1]; #else if (pipe(fds)) { perror("pipe"); exit(1); } stXfd= fds[0]; osXfd= fds[1]; #endif aioEnable(stXfd, 0, 0); aioHandle(stXfd, evtHandler, AIO_RX); #if (!USE_SPINLOCK) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); # ifndef NDEBUG pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); # endif if (pthread_mutex_init(&displayMx, &attr)) { perror("pthread_mutex_init"); exit(1); } pthread_mutexattr_destroy(&attr); } #endif if (fromFinder) { char *ptr= 0; strncpy(resourcePath, argVec[0], sizeof(resourcePath)); // .app/Contents/MacOS/squeak if ((ptr= strrchr(resourcePath, '/'))) { *ptr= '\0'; // .app/Contents/MacOS if ((ptr= strrchr(resourcePath, '/'))) { *ptr= '\0'; // .app/Contents strcpy(ptr, "/Resources/"); // .app/Contents/Resources/ } else resourcePath[0]= '\0'; } else resourcePath[0]= '\0'; } imgInit(); // vmPath has been set to the realpath() of the VM, which might be // bogus (since the more cultivated OS X user will make it a symlink // to /usr/local/bin/squeak). put it back where it should be. note // that we would also like to pick up the sources file from // resourcePath/SqueakV*.sources, but I guess the stupid image is // going to look for it in the vmPath. ho hum. { char *ptr; assert(strlen(argVec[0]) < MAXPATHLEN); strcpy(vmPath, argVec[0]); if ((ptr= strrchr(vmPath, '/'))) ptr[1]= '\0'; } setUpDisplay(); printf("fullScreenFlag %d\n", getFullScreenFlag()); setUpWindow(fullscreen= getFullScreenFlag()); [NSThread detachNewThreadSelector: @selector(interpret:) toTarget: self withObject: nil]; } - (void) interpret: (id)context { [[NSAutoreleasePool alloc] init]; // running in new thread interpret(); (void)recordMouseEvent; (void)recordKeyboardEvent; (void)recordDragEvent; } - (void) applicationDidChangeScreenParameters: (NSNotification *)note { //xxx this one might be tricky in the absence of appWillChangeScreenParams: fprintf(stderr, "\nDISPLAY PARAMETERS CHANGED\n\n"); // lock(display); pixWidth= pixHeight= pixDepth= 0; setUpDisplay(); //setUpWindow(getFullScreenFlag()); updatePix(); // unlock(display); //setUpMenus(); fullDisplayUpdate(); } - (void) unhideAllApplications: (id)sender { [super unhideAllApplications: sender]; [win orderFront: self]; // so that unhinding once more will reveal the Sq window } - (BOOL) windowShouldClose: (id)sender { return NO; } - (void) terminate: (id)sender { [super terminate: sender]; exit(0); } - (void) maybeTerminate: (id)sender { switch (NSRunAlertPanel(@"Really quit?", @"All changes since your last save will be lost.\n\nIf you want to save your changes, press `Cancel' and then choose `save and quit' from the background menu in the Squeak window.", @"Quit", @"Cancel", nil)) { case NSAlertDefaultReturn: [self terminate: self]; } } - (void) performAbout: (id)sender { extern char *getVersionInfo(int verbose); char *info= getVersionInfo(1); NSPanel *panel= NSGetInformationalAlertPanel(@"About Squeak", @"%s", @"Dismiss", nil, nil, info); NSRect frame= [panel frame]; frame.size.width *= 1.5; [panel setFrame: frame display: NO]; [NSApp runModalForWindow: panel]; [panel close]; free(info); } //xxx why does rebuilding the menu lose boldface on the Apple menu item??? - (void) performEnableKeys: (id)sender { cmdKeys= 1; setUpMenus(); } - (void) performDisableKeys: (id)sender { cmdKeys= 0; setUpMenus(); } - (void) windowWillMove: (NSNotification *)note { //xxx FIXME SOON: there are other ways to enter this (and ways other than // noteEvent to escape from it) inModalLoop= 1; } - (NSSize) windowWillResize: (NSWindow *)sender toSize: (NSSize)size { return glActive ? [sender frame].size : size; } - (void) windowDidResize: (NSNotification *)note { reframeRenderers(); } -(void) sendEvent: (NSEvent *)event { int type= [event type]; NSPoint loc= [event locationInWindow]; NSWindow *evtWin= [event window]; #if 0 NSPoint loc= (fullscreen ? [NSEvent mouseLocation] //xxx should use deltas : [event locationInWindow]); #endif if (evtWin && ((NSWindow *)win != [event window])) { [super sendEvent: event]; return; } switch (type) { # define down buttonState |= qz2sqButton([event buttonNumber]) # define move # define up buttonState &= ~qz2sqButton([event buttonNumber]) # define recordEvent(delta) \ if (fullscreen || NSPointInRect(loc, [view frame])) \ { \ noteMousePoint(loc); \ delta; \ modifierState= qz2sqModifiers([event modifierFlags]); \ noteMouseEvent(); \ } \ else \ [super sendEvent: event] // don't track outside window case NSLeftMouseDown: case NSOtherMouseDown: case NSRightMouseDown: if ((!active) || NSPointInRect(loc, resizeRect)) [super sendEvent: event]; // first click, or start resize else recordEvent(down); break; case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: if (!(buttonState & qz2sqButton([event buttonNumber]))) { [super sendEvent: event]; // already tracking window move break; } // fall through... case NSMouseMoved: recordEvent(move); break; case NSLeftMouseUp: case NSOtherMouseUp: case NSRightMouseUp: recordEvent(up); break; # undef recordEvent # undef down # undef move # undef up case NSKeyDown: { int keyCode; modifierState= qz2sqModifiers([event modifierFlags]); keyCode= [view composeKeyDown: event]; //qz2sqKey(event); if (keyCode >= 0) { if (cmdKeys) { if ((modifierState == CommandKeyBit) || (modifierState == CommandKeyBit + ShiftKeyBit)) switch (keyCode) { case '?': [NSApp showHelp: self]; keyCode= -1; break; case 'h': [NSApp hide: self]; keyCode= -1; break; case 'k': [NSApp performDisableKeys: self]; keyCode= -1; break; case 'm': [win performMiniaturize: self]; keyCode= -1; break; case 'q': [NSApp maybeTerminate: self]; keyCode= -1; break; } else if (modifierState == CommandKeyBit + OptionKeyBit) switch (keyCode) { case 'h': [NSApp hideOtherApplications: self]; keyCode= -1; break; } } if (keyCode >= 0) { if (![event isARepeat]) noteKeyboardEvent(keyCode, EventKeyDown, modifierState); noteKeyboardEvent(keyCode, EventKeyChar, modifierState); recordKeystroke(keyCode); /* DEPRECATED */ } else // key up not interesting [view composeKeyUp: event]; } } break; case NSKeyUp: { int keyCode; modifierState= qz2sqModifiers([event modifierFlags]); keyCode= [view composeKeyUp: event]; //qz2sqKey(event); if (keyCode >= 0) { noteKeyboardEvent(keyCode, EventKeyUp, modifierState); //accentMap= 0; } } break; case NSScrollWheel: { int keyCode= ([event deltaY] >= 0.0) ? 30 : 31; noteKeyboardEvent(keyCode, EventKeyDown, modifierState); noteKeyboardEvent(keyCode, EventKeyChar, modifierState); noteKeyboardEvent(keyCode, EventKeyUp, modifierState); } break; case NSAppKitDefined: switch ([event subtype]) { case NSApplicationActivatedEventType: active= 1; break; case NSApplicationDeactivatedEventType: active= 0; break; // case NSScreenChangedEventType: //xxx this means the window // changed to a different physical screen, which is useless // info (we'd far rather be informed that the current screen's // depth has changed) } //DPRINTF(("AppKitDefinedEvent subtype %d\n", [event subtype])); [super sendEvent: event]; break; // case NSFlagsChanged: // case NSApplicationDefined: break; // case NSPeriodic: break; // case NSCursorUpdate: break; default: // almost always NSSystemDefined //DPRINTF(("Event type %d subtype %d\n", [event type], [event subtype])); [super sendEvent: event]; } } @end // Squeak ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/SqueakView.h ================================================ // -*- ObjC -*- // Why QDView? Well... // // 1) we can trivially obtain a raw pointer to its backing store, so // 2) no need to putz around with the lockFocus/DataProvider/ImageRep crap; plus // 3) its buffer's coordinate system is already the right way up for Squeak, so // 4) we avoid potential recopy (just to have CG recopy again); besides // 5) QDFlushBuffer is _blindingly_ fast (even compared to drawing directly on // the framebuffer [go measure it if you don't believe me]); but most importantly // 6) the QD API is completely free of ObjC and attendant inefficiencies. @interface SqueakView : NSQuickDrawView - (BOOL) acceptsFirstResponder; - (BOOL) becomeFirstResponder; - (BOOL) isOpaque; - (BOOL) isFlipped; - (id) initWithFrame: (NSRect)frame; - (void) setFrame: (NSRect)rect; - (void) drawRect: (NSRect)rect; - (void) viewWillStartLiveResize; - (void) viewDidEndLiveResize; - (int) draggingEntered: (id)sender; - (int) draggingUpdated: (id)sender; - (void) draggingExited: (id)sender; - (BOOL) performDragOperation: (id)sender; - (int) composeKeyDown: (NSEvent *)event; - (int) composeKeyUp: (NSEvent *)event; @end ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/SqueakView.m ================================================ @implementation SqueakView - (BOOL) isOpaque { return YES; } - (BOOL) isFlipped { return YES; } - (BOOL) acceptsFirstResponder { return YES; } - (BOOL) becomeFirstResponder { return YES; } - (BOOL) resignFirstResponder { return NO; } - (void) renewGState { printf("\nRENEW GSTATE\n\n"); [super renewGState]; } static NSRange inputMark; static NSRange inputSelection; static int inputCharCode; - (id) initWithFrame: (NSRect)frame { id result= [super initWithFrame: frame]; if (self == result) [self registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; inputCharCode= -1; inputMark= NSMakeRange(NSNotFound, 0); inputSelection= NSMakeRange(0, 0); return result; } - (void) setFrame: (NSRect)rect { lock(display); [super setFrame: rect]; if ([self inLiveResize]) { # if (RESIZE_IN_TITLE) display_winSetName(shortImageName); # endif } else if ([self qdPort]) updatePix(); unlock(display); } - (void) drawRect: (NSRect)rect // view already has focus { printf("drawRect:\n"); if ([self inLiveResize]) { [[NSColor whiteColor] set]; NSRectFill(rect); drawImage([[NSGraphicsContext currentContext] graphicsPort], 0); } else { if (!pixBase) { printf("drawRect: calling updatePix\n"); assert([self qdPort]); updatePix(); } fullDisplayUpdate(); } } - (void) viewWillStartLiveResize { captureImage(1); [win setShowsResizeIndicator: YES]; #if (RESIZE_IN_TITLE) showExtent= 1; display_winSetName(shortImageName); #endif pixWidth= 0; pixHeight= 0; } - (void) viewDidEndLiveResize { releaseImage(1); [win setShowsResizeIndicator: NO]; #if (RESIZE_IN_TITLE) showExtent= 0; display_winSetName(shortImageName); #endif updatePix(); fullDisplayUpdate(); // gets rid of the resize icon if window didn't resize } - (int) draggingEntered: (id)info { if ((dragCount == 0) // cannot drag again until previous drag completes && ([info draggingSourceOperationMask] & NSDragOperationCopy)) { int count= [[[info draggingPasteboard] propertyListForType: NSFilenamesPboardType] count]; noteMousePoint([info draggingLocation]); noteDragEvent(DragEnter, dragCount= count); return NSDragOperationCopy; } return NSDragOperationNone; } - (int) draggingUpdated: (id)info { noteMousePoint([info draggingLocation]); noteDragEvent(DragMove, dragCount); return NSDragOperationCopy; } - (void) draggingExited: (id)info { noteMousePoint([info draggingLocation]); noteDragEvent(DragLeave, dragCount); dragCount= 0; } - (BOOL) performDragOperation: (id)info { NSPasteboard *pboard= [info draggingPasteboard]; noteMousePoint([info draggingLocation]); if ([[pboard types] containsObject: NSFilenamesPboardType]) { NSArray *files= [pboard propertyListForType: NSFilenamesPboardType]; int i; if (uxDropFileCount) { assert(uxDropFileNames); for (i= 0; i < uxDropFileCount; ++i) free(uxDropFileNames[i]); free(uxDropFileNames); uxDropFileNames= 0; } if (( (!(uxDropFileCount= [files count]))) || (!(uxDropFileNames= (char **)malloc(uxDropFileCount * sizeof(char *))))) { uxDropFileCount= 0; return NO; } for (i= 0; i < uxDropFileCount; ++i) uxDropFileNames[i]= strdup([[files objectAtIndex: i] cString]); } noteDragEvent(DragDrop, uxDropFileCount); dragCount= 0; return YES; // under some duress, I might add (see sqUxDragDrop.c) } enum { KeyMapSize= 32 }; typedef struct { int keyCode; int keyChar; } KeyMapping; static KeyMapping keyMap[KeyMapSize]; static int keyMapSize= 0; static int inputCharCode= -1; static int addToKeyMap(int keyCode, int keyChar) { if (keyMapSize > KeyMapSize) { fprintf(stderr, "keymap overflow\n"); return -1; } keyMap[keyMapSize++]= (KeyMapping){ keyCode, keyChar }; return keyChar; } static int indexInKeyMap(int keyCode) { int i; for (i= 0; i < keyMapSize; ++i) if (keyMap[i].keyCode == keyCode) return i; return -1; } static int findInKeyMap(int keyCode) { int idx= indexInKeyMap(keyCode); return (idx >= 0) ? keyMap[idx].keyChar : -1; } static int removeFromKeyMap(int keyCode) { int idx= indexInKeyMap(keyCode); int keyChar= -1; if (idx < 0) { fprintf(stderr, "keymap underflow\n"); return -1; } keyChar= keyMap[idx].keyChar; for (; idx < keyMapSize - 1; ++idx) keyMap[idx]= keyMap[idx + 1]; --keyMapSize; return keyChar; } // the following (to @end) must be installed in the first responder - (int) composeKeyDown: (NSEvent *)event { int keyCode= [event keyCode]; inputCharCode= -1; if (modifierState & CommandKeyBit) inputCharCode= qz2sqKey(event); else { if ([event isARepeat]) { int keyChar= findInKeyMap(keyCode); //printf("%d REP keyCode %x -> keyChar %x\n", keyMapSize, keyCode, keyChar); return keyChar; } else { [self interpretKeyEvents: [NSArray arrayWithObject: event]]; if (inputCharCode < 0) inputCharCode= qz2sqKey(event); } } if (inputCharCode >= 0) { //printf("%d ADD keyCode %x -> keyChar %x\n", keyMapSize, keyCode, inputCharCode); addToKeyMap(keyCode, inputCharCode); } return inputCharCode; } - (int) composeKeyUp: (NSEvent *)event { int keyCode= [event keyCode]; int keyChar= removeFromKeyMap(keyCode); //printf("%d DEL keyCode %x -> charCode %x\n", keyMapSize, keyCode, keyChar); return keyChar; } - (void) insertText: (NSString *)text { //printf("insertText\n"); inputMark= NSMakeRange(NSNotFound, 0); inputSelection= NSMakeRange(0, 0); if ([text length]) { UInt8 buf[4]; CFIndex nUsed; if (CFStringGetBytes((CFStringRef)text, CFRangeMake(0, CFStringGetLength((CFStringRef)text)), kCFStringEncodingMacRoman, 0, FALSE, buf, sizeof(buf), &nUsed)) inputCharCode= buf[0]; } } // ParagraphEditor's map looks like this: // // 0 noop cursorHome noop noop cursorEnd noop noop noop // 8 backspace noop noop cursorPageUp cursorPageDown crWithIndent noop noop // 16 noop noop noop noop noop noop noop noop // 24 noop noop noop offerMenuFromEsc cursorLeft cursorRight cursorUp cursorDown // 127 forwardDelete - (void) doCommandBySelector: (SEL)aSelector { // why doesn't @selector() reduce to a constant?? # define encode(c, s) if (aSelector == @selector(s)) inputCharCode= c // my (subjective) approximation of usage frequency... encode( 8, deleteBackward:); else encode( 13, insertNewline:); else encode( 9, insertTab:); else encode( 28, moveLeft:); else encode( 29, moveRight:); else encode( 30, moveUp:); else encode( 31, moveDown:); else encode( 11, pageUp:); else encode( 12, pageDown:); else encode( 1, moveToBeginningOfDocument:); else encode( 4, moveToEndOfDocument:); else encode(127, deleteForward:); else encode( 27, _cancelKey:); else printf("doCommandBySelector: %s\n", sel_getName(aSelector)); # undef encode } - (void) setMarkedText: (id)aString selectedRange: (NSRange)selRange { inputMark= NSMakeRange(0, 1); inputSelection= NSMakeRange(NSNotFound, 0); } - (void) unmarkText { inputMark= NSMakeRange(NSNotFound, 0); } - (BOOL) hasMarkedText { return inputMark.location != NSNotFound; } - (long) conversationIdentifier { return (long)self; } - (NSAttributedString *) attributedSubstringFromRange: (NSRange)theRange { return nil; } - (NSRange) markedRange { return inputMark; } - (NSRange) selectedRange { return inputSelection; } - (NSRect) firstRectForCharacterRange: (NSRange)theRange { return NSMakeRect(0,0, 0,0); } - (unsigned int) characterIndexForPoint: (NSPoint)thePoint { return 0; } - (NSArray *) validAttributesForMarkedText { return nil; } @end ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/SqueakWindow.h ================================================ // -*- ObjC -*- @interface SqueakWindow : NSWindow { NSImage *icon; } - (BOOL) isOpaque; - (BOOL) canBecomeKeyWindow; - (void) setIcon; - (void) performMiniaturize: (id)sender; - (void) miniaturize: (id)sender; @end ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/SqueakWindow.m ================================================ @implementation SqueakWindow - (BOOL) isOpaque { return YES; } - (BOOL) canBecomeKeyWindow { return YES; } - (void) setIcon { /////////////xxxxxxxxxxxxxxxxxxxxxxxxxx REMOVE icon= [[NSImage alloc] initWithContentsOfFile: @"transp.icns"]; if (icon) [NSApp setApplicationIconImage: icon]; } - (NSImage *) dockImage { NSBitmapImageRep *rep= [NSBitmapImageRep alloc]; if ([rep initWithFocusedViewRect: topRect]) { NSImage *image= [[NSImage alloc] init]; [image addRepresentation: rep]; if (icon) { [image lockFocus]; [icon drawInRect: NSMakeRect(0, 0, [image size].width, [image size].height) fromRect: NSMakeRect(0, 0, [icon size].width, [icon size].height) operation: NSCompositeSourceOver fraction: 1.0]; [image unlockFocus]; } return image; } return nil; } - (void) performMiniaturize: (id)sender { if (!glActive) [super performMiniaturize: sender]; } - (void) miniaturize: (id)sender { NSImage *image= [self dockImage]; if (image) [self setMiniwindowImage: image]; [image release]; [super miniaturize: sender]; } @end ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/acinclude.m4 ================================================ # -*- sh -*- AC_ARG_WITH(quartz, [ --without-quartz disable MacOSX Window System support [default=enabled]], [have_quartz="$withval"], [have_quartz="yes"]) case $host_os in darwin*) ;; *) have_quartz="no";; esac if test "$have_quartz" = "yes"; then AC_DEFINE(USE_QUARTZ, [1]) if test "$have_gl" = ""; then have_gl="no"; fi AC_CHECK_HEADERS(OpenGL/gl.h, [ have_gl=yes AC_DEFINE(USE_QUARTZ_CGL, [1]) ]) else AC_PLUGIN_DISABLE fi ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/build.cmake ================================================ EXPECT_UNDEFINED_SYMBOLS () ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/config.cmake ================================================ IF (NOT APPLE) PLUGIN_DISABLE () ELSE () PLUGIN_INCLUDE_DIRECTORIES (${cross}/plugins/B3DAcceleratorPlugin ${AGL_INCLUDE_DIR}) PLUGIN_LINK_LIBRARIES (${AGL_LIBRARIES} "-framework Cocoa") ENDIF (NOT APPLE) ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/mkinfo ================================================ #!/bin/sh IN=$1; shift OUT=$1; shift BNDL_VERSION="$@" sed "s%\@BNDL_VERSION@%${BNDL_VERSION}%g" < ${IN} > ${OUT} ================================================ FILE: vm/src/from_squeak/unix/vm-display-Quartz/sqUnixQuartz.m ================================================ /* sqUnixQuartz.m -- display via native windows on Mac OS X -*- ObjC -*- * * Author: Ian Piumarta * * Copyright (C) 1996-2005 by Ian Piumarta and other authors/contributors * listed elsewhere in this file. * All rights reserved. * * This file is part of Unix Squeak. * * You are NOT ALLOWED to distribute modified versions of this file * under its original name. If you modify this file then you MUST * rename it before making your modifications available publicly. * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You may use and/or distribute this file ONLY as part of Squeak, under * the terms of the Squeak License as described in `LICENSE' in the base of * this distribution, subject to the following additional restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment to the original author(s) (and any * other contributors mentioned herein) in the product documentation * would be appreciated but is not required. * * 2. You must not distribute (or make publicly available by any * means) a modified copy of this file unless you first rename it. * * 3. This notice must not be removed or altered in any source distribution. * * Using (or modifying this file for use) in any context other than Squeak * changes these copyright conditions. Read the file `COPYING' in the * directory `platforms/unix/doc' before proceeding with any such use. * * Last edited: 2006-04-17 16:56:53 by piumarta on margaux.local */ //xxx ... // // check use of winRect and titleRect. reduce to (int)winHeight and // (int)titleHeight in setRects. // // investigate creating sq events in the UI thread and then sending // them down the notification pipe, instead of locking the event // queue. #import #include "sqUnixMain.h" #include "sqUnixGlobals.h" #include "sqUnixCharConv.h" #include "sq.h" #include "sqaio.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "config.h" #undef HAVE_GL_GL_H #include "SqDisplay.h" /// /// Things you can tweak, if you're curious/bored enough to want to... /// // do we draw the current screen extent (width x height) in the title // bar during live resize? // #define RESIZE_IN_TITLE 1 // how large a (square) area, in the lower right of the window, should // respond to mouse down by initiating window resize? (the resize // icon itself is, when we allow it to be shown, 13x13 pixels.) // #define RESIZE_EXTENT 8 // do we fade the screen out and back in gently when changing to // fullscreen mode, or just switch with one big violent click? if // this is defined then it represents the incr/decrement per // millisecond of the gamma multiplier (1.0 to 0.0 and back); if // undefined then the switch is immediate. // #undef FULLSCREEN_FADE 0.02 /// /// No more user-serviceable parts in this file. Stop Tweaking Now! /// #define USE_SPINLOCK 1 #define USE_OWN_ICON 0 static inline int min(int x, int y) { return x < y ? x : y; } static inline int max(int x, int y) { return x > y ? x : y; } // -*- ObjC -*- @interface Squeak : NSApplication - (void) applicationDidFinishLaunching: (NSNotification *)note; - (void) applicationDidChangeScreenParameters: (NSNotification *)note; - (void) unhideAllApplications: (id)sender; - (BOOL) windowShouldClose: (id)sender; - (void) maybeTerminate: (id)sender; - (void) terminate: (id)sender; - (void) performEnableKeys: (id)sender; - (void) performDisableKeys: (id)sender; @end @interface SqueakWindow : NSWindow { NSImage *icon; } - (BOOL) isOpaque; - (BOOL) canBecomeKeyWindow; - (void) setIcon; #if 0 - (NSImage *) dockImage - (void) miniaturize: (id)sender; #endif - (void) performMiniaturize: (id)sender; @end // Why QDView? Well... // // 1) we can trivially obtain a raw pointer to its backing store, so // 2) no need to putz around with the lockFocus/DataProvider/ImageRep crap; plus // 3) its buffer's coordinate system is already the right way up for Squeak, so // 4) we avoid potential recopy (just to have CG recopy again); besides // 5) QDFlushBuffer is _blindingly_ fast (even compared to drawing directly on // the framebuffer [go measure it if you don't believe me]); but most importantly // 6) the QD API is completely free of ObjC and attendant inefficiencies. @interface SqueakView : NSQuickDrawView - (BOOL) acceptsFirstResponder; - (BOOL) becomeFirstResponder; - (BOOL) isOpaque; - (BOOL) isFlipped; - (id) initWithFrame: (NSRect)frame; - (void) setFrame: (NSRect)rect; - (void) drawRect: (NSRect)rect; - (void) viewWillStartLiveResize; - (void) viewDidEndLiveResize; - (int) draggingEntered: (id)sender; - (int) draggingUpdated: (id)sender; - (void) draggingExited: (id)sender; - (BOOL) performDragOperation: (id)sender; - (int) composeKeyDown: (NSEvent *)event; - (int) composeKeyUp: (NSEvent *)event; @end static SqueakView *view = 0; /* app view (occupies topRect) */ @interface TopView : NSView - (void) setFrame: (NSRect)rect; @end @implementation TopView - (void) setFrame: (NSRect)rect { [super setFrame: rect]; if (view) [view setFrame: rect]; } @end static int styleMask = 0; /* window style mask */ static int dragCount = 0; /* number of items during drag/drop */ static int showExtent = 0; /* 1 if title bar shows view extent */ int inModalLoop= 0; /* 1 when WS is in tracking loop */ static int active = 0; /* 1 when app window is active */ //static CFArrayRef dpyModes = 0; /* one of these days... */ static CGDirectDisplayID dpy = 0; static NSDictionary *dpyMode = 0; static int dpyWidth = 0; static int dpyHeight = 0; static int dpyDepth = 0; char *dpyPixels = 0; int dpyPitch = 0; static SqueakWindow *win = 0; /* main application window */ static NSRect topRect; /* main window frame (excl. decoration) */ static NSRect titleRect; /* decoration area (above topRect) */ static NSRect resizeRect; /* area sensitive to resize */ static TopView *topView = 0; /* top view (occupies topRect) */ static char *pixBase = 0; static int pixWidth = 0; /* pixmap width (pixels) */ static int pixHeight = 0; /* pixmap height */ static int pixDepth = 0; /* pixmap depth */ static int pixPitch = 0; static RgnHandle pixRegion = 0; static int cmdKeys = 0; /* 1 if app command keys enabled */ static int fromFinder = 0; /* 1 if app launched from finder */ static int noTitle = 0; /* 1 if app window is undecorated */ static int headless = 0; /* 1 if app has no window */ static int noDock = 0; /* 1 if app window is undocked */ static int fullscreen = 0; /* 1 if window fullscreen and on top */ static char *clipboard = 0; static int stXfd = -1; static int osXfd = -1; #if (USE_SPINLOCK) static int displayMx = 0; #else static pthread_mutex_t displayMx = PTHREAD_MUTEX_INITIALIZER; #endif static char resourcePath[MAXPATHLEN]; static int glActive= 0; static void reframeRenderers(void); static void updateRenderers(void); #if 0 //xxx REMOVE ME #define RED 0xff0000 #define GREEN 0x00ff00 #define BLUE 0x0000ff #define WHITE 0xffffff #define BLACK 0x000000 void feedback(int offset, int pixel) { const int width= 4, height= 4; long *base= CGDisplayBaseAddress(dpy); int pitch= CGDisplayBytesPerRow(dpy); int x, y; base= base + width * offset; for (y= 0; y < height; ++y) { for (x= 0; x < width; ++x) base[x]= pixel; base= (long *)((char *)base + pitch); } } #endif #if (USE_SPINLOCK) extern inline int testAndSet(int *lock) { int valu; asm volatile(" lwarx %0, 0, %1 \n" " cmpwi %0, 0 \n" " bne- 1f \n" " li %0, 1 \n" " stwcx. %0, 0, %1 \n" " bne- 1f \n" " li %0, 0 \n" "1: \n" : "=&r"(valu) : "r"(lock) : "cr0","memory"); return valu; } extern inline int doLock(int *lock, const char *who) { while (testAndSet(lock)) ; return 1; } extern inline void doUnlock(int *lock) { *lock= 0; } #else //xxx FIXME SOON: check all uses of lock() and conditionalise the // sections where failure could cause SEGV (rather than just // inconsistent geometry or whatever) static int doLock(pthread_mutex_t *mx, char *who) { static char *owner= ""; int backoff, i= 0; // wait about 1 second before giving up (10000 == timeslice quantum) for (backoff= 10000; backoff < 1280000; ++i, backoff <<= 1) if (0 == pthread_mutex_trylock(mx)) { owner= who; return 1; } else { # ifndef NDEBUG fprintf(stderr, "lock %d: %s waiting for %-20s\n", i, who, owner); # endif usleep(backoff); } perror("pthread_mutex_trylock"); return 0; } static void doUnlock(pthread_mutex_t *mx) { if (pthread_mutex_unlock(mx)) perror("pthread_mutex_unlock"); } #endif #define lock(MX) doLock(&MX##Mx, __FUNCTION__) #define unlock(MX) doUnlock(&MX##Mx) #include "sqUnixEvent.c" //xxx FIXME: this is currently monochrome static sqInt display_ioFormPrint(sqInt bitsAddr, sqInt width, sqInt height, sqInt depth, double hScale, double vScale, sqInt landscapeFlag) { //xxx hScale and vScale are ppi. is there a way to use this // meaningfully with PrintInfo or NSPrinter? NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; int opp= depth / 8; int success= 1; DPRINTF(("ioFormPrint %f %f\n", hScale, vScale)); { unsigned char *planes[1]= { (unsigned char *)pointerForOop(bitsAddr) }; NSBitmapImageRep *bitmap= 0; NSImage *image= 0; NSImageView *view= 0; bitmap= [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: planes pixelsWide: width pixelsHigh: height bitsPerSample: depth samplesPerPixel: 1 hasAlpha: NO isPlanar: NO colorSpaceName: NSCalibratedBlackColorSpace bytesPerRow: width * opp bitsPerPixel: depth]; if (!bitmap) { DPRINTF(("bitmap fail\n")); success= 0; goto done; } image= [NSImage alloc]; //[image setSize: NSMakeSize(width, height)]; [image addRepresentation: bitmap]; if (!image) { DPRINTF(("image fail\n")); success= 0; goto done; } view= [[NSImageView alloc] initWithFrame: NSMakeRect(0, 0, width, height)]; [view setImage: image]; { NSPrintOperation *op= [NSPrintOperation printOperationWithView: view]; [op setShowPanels: YES]; DPRINTF(("launch print operation\n")); [op runOperation]; } } done: DPRINTF(("ioFormPrint done.\n")); [pool release]; return success; } static sqInt display_ioBeep(void) { NSBeep(); return 0; } static sqInt display_ioRelinquishProcessorForMicroseconds(sqInt microSeconds) { aioSleepForUsecs(microSeconds); return 0; } /// /// events /// static unsigned int qz2sqModifiers(unsigned int qz) { return ( ((qz & (NSShiftKeyMask | NSAlphaShiftKeyMask)) ? ShiftKeyBit : 0)) | ((qz & NSControlKeyMask) ? CtrlKeyBit : 0) | ((qz & NSAlternateKeyMask) ? OptionKeyBit : 0) | ((qz & NSCommandKeyMask) ? CommandKeyBit : 0); } static unsigned int qz2sqButton(unsigned int button) { // the image has blue and yellow back-to-front. fix that here... switch (button) { case 0: return RedButtonBit; case 1: return (swapBtn ? YellowButtonBit : BlueButtonBit); case 2: return (swapBtn ? BlueButtonBit : YellowButtonBit); } DPRINTF(("unknown mouse button %d\n", button)); return RedButtonBit; } static unsigned int qz2sqKey(NSEvent *event) { NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; NSString *chars= [event characters]; UInt32 enc= CFStringConvertEncodingToNSStringEncoding((CFStringEncoding)sqTextEncoding); NSData *data= [chars dataUsingEncoding: enc allowLossyConversion: NO]; int keyCode= -1; # define returnKey(N) keyCode= (N); goto done if ([data length]) { keyCode= ((unsigned char *)[data bytes])[0]; if (keyCode == 127) keyCode= 8; goto done; } if ([chars length]) { keyCode= [chars characterAtIndex: 0]; switch (keyCode) { case NSDeleteFunctionKey: returnKey( 8); case NSUpArrowFunctionKey: returnKey(30); case NSDownArrowFunctionKey: returnKey(31); case NSLeftArrowFunctionKey: returnKey(28); case NSRightArrowFunctionKey: returnKey(29); case NSHomeFunctionKey: returnKey( 1); case NSEndFunctionKey: returnKey( 4); case NSPageUpFunctionKey: returnKey(11); case NSPageDownFunctionKey: returnKey(12); /* -- these should probably be implemented -- */ # define unknown(KEY) printf(KEY"\n"); returnKey(-1) case NSClearLineFunctionKey: unknown("Clear/Num Lock"); case NSHelpFunctionKey: unknown("Help"); /* -- the rest are missing on most mac keyboards -- */ case NSBeginFunctionKey: unknown("Begin"); case NSPrintScreenFunctionKey: unknown("Print Screen"); case NSScrollLockFunctionKey: unknown("Scroll Lock"); case NSPauseFunctionKey: unknown("Pause"); case NSSysReqFunctionKey: unknown("System Request"); case NSBreakFunctionKey: unknown("Break"); case NSResetFunctionKey: unknown("Reset"); case NSStopFunctionKey: unknown("Stop"); case NSMenuFunctionKey: unknown("Menu"); case NSUserFunctionKey: unknown("User"); case NSSystemFunctionKey: unknown("System"); case NSPrintFunctionKey: unknown("Print"); case NSClearDisplayFunctionKey: unknown("Clear Display"); case NSInsertLineFunctionKey: unknown("Insert Line"); case NSDeleteLineFunctionKey: unknown("Delete Line"); case NSInsertCharFunctionKey: unknown("Insert Character"); case NSDeleteCharFunctionKey: unknown("Delete Character"); case NSPrevFunctionKey: unknown("Previous"); case NSNextFunctionKey: unknown("Next"); case NSSelectFunctionKey: unknown("Select"); case NSExecuteFunctionKey: unknown("Execute"); case NSUndoFunctionKey: unknown("Undo"); case NSRedoFunctionKey: unknown("Redo"); case NSFindFunctionKey: unknown("Find"); case NSModeSwitchFunctionKey: unknown("Mode Switch"); # undef unknown } if (keyCode & 0xff00) keyCode= -1; } done: [pool release]; return keyCode; } static inline void noteMousePoint(NSPoint loc) { int x= (int)loc.x; int y= (int)topRect.size.height - (int)loc.y; // mouse motion/up is tracked outside of topRect when active, so // clamp it explicitly // (note: there's a race here, but it's benign) mousePosition.x= max(0, min(x, pixWidth - 1)); mousePosition.y= max(0, min(y, pixHeight - 1)); } static void evtHandler(int fd, void *data, int flags) { for (;;) { sqInputEvent evt; int n= read(fd, (void *)&evt, sizeof(evt)); if (n < 0) { if ((EINTR == errno) || (EAGAIN == errno)) break; perror("evtHandler: read"); } else if (n == 0) break; else if (n != sizeof(evt)) fprintf(stderr, "evtHandler: read returned %d -- why?\n", n); else { sqInputEvent *evp= allocateInputEvent(0); *evp= evt; signalInputEvent(); } } aioHandle(fd, evtHandler, AIO_RX); } static void sendEvent(sqInputEvent *evt) { if (inModalLoop) //xxx there are other ways to escape from one of these inModalLoop= 0; if (sizeof(*evt) != write(osXfd, evt, sizeof(*evt))) perror("sendEvent: write"); } static int makeButtonState(void) { int btn= buttonState; int mod= modifierState; if (btn == RedButtonBit) switch (mod) { case OptionKeyBit: btn= YellowButtonBit; mod= 0; break; case CommandKeyBit: btn= BlueButtonBit; mod= 0; break; } return (mod << 3) | btn; } static void noteMouseEvent(void) { int state= makeButtonState(); sqMouseEvent evt; evt.type= EventTypeMouse; evt.timeStamp= ioMSecs(); evt.x= mousePosition.x; evt.y= mousePosition.y; evt.buttons= (state & 0x7); evt.modifiers= (state >> 3); evt.reserved1= 0; evt.windowIndex= 0; #ifdef DEBUG_EVENTS printf("EVENT: mouse (%d,%d)", mousePosition.x, mousePosition.y); printModifiers(state >> 3); printButtons(state & 7); printf("\n"); #endif sendEvent((sqInputEvent *)&evt); } static void noteKeyboardEvent(int keyCode, int pressCode, int modifiers) { sqKeyboardEvent evt; evt.type= EventTypeKeyboard; evt.timeStamp= ioMSecs(); evt.charCode= keyCode; evt.pressCode= pressCode; evt.modifiers= modifiers; evt.utf32Code= 0; /* xxx TODO xxx */ evt.reserved1= 0; evt.windowIndex= 0; #ifdef DEBUG_EVENTS printf("EVENT: keyboard"); printModifiers(modifiers); printKey(keyCode); printf("\n"); #endif sendEvent((sqInputEvent *)&evt); } static void noteDragEvent(int dragType, int numFiles) { int state= makeButtonState(); sqDragDropFilesEvent evt; evt.type= EventTypeDragDropFiles; evt.timeStamp= ioMSecs(); evt.dragType= dragType; evt.x= mousePosition.x; evt.y= mousePosition.y; evt.modifiers= (state >> 3); evt.numFiles= numFiles; evt.windowIndex= 0; sendEvent((sqInputEvent *)&evt); } static sqInt display_ioProcessEvents(void) { return aioPoll(0); } static sqInt display_ioScreenDepth(void) { return headless ? 1 : dpyDepth; } static int displayChanged= 0; static sqInt display_ioScreenSize(void) { int size; if (headless) return ((16 << 16) | 16); if (displayChanged) { displayChanged= 0; [win setFrame: [win frame] display: YES]; return 0; } lock(display); size= getSavedWindowSize(); unlock(display); return size; } static sqInt display_ioSetCursorWithMask(sqInt cursorBitsIndex, sqInt cursorMaskIndex, sqInt offsetX, sqInt offsetY) { if (headless) return 0; if ([view lockFocusIfCanDraw]) { NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; NSBitmapImageRep *bitmap= 0; NSImage *image= 0; NSCursor *cursor= 0; if (cursorMaskIndex == 0) cursorMaskIndex= cursorBitsIndex; bitmap= [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: 0 pixelsWide: 16 pixelsHigh: 16 bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSCalibratedBlackColorSpace bytesPerRow: 2 bitsPerPixel: 0]; { unsigned char *planes[5]; [bitmap getBitmapDataPlanes: planes]; { unsigned char *data= planes[0]; unsigned char *mask= planes[1]; int i; for (i= 0; i < 16; ++i) { unsigned int word= ((unsigned int *)pointerForOop(cursorBitsIndex))[i]; data[i*2 + 0]= (word >> 24) & 0xFF; data[i*2 + 1]= (word >> 16) & 0xFF; word= ((unsigned int *)pointerForOop(cursorMaskIndex))[i]; mask[i*2 + 0]= (word >> 24) & 0xFF; mask[i*2 + 1]= (word >> 16) & 0xFF; } } } image= [[NSImage alloc] init]; [image addRepresentation: bitmap]; { NSPoint hotSpot= { -offsetX, -offsetY }; cursor= [[NSCursor alloc] initWithImage: image hotSpot: hotSpot]; } [cursor set]; [pool release]; [view unlockFocus]; } return 1; } #if 0 static sqInt display_ioSetCursor(sqInt cursorBitsIndex, sqInt offsetX, sqInt offsetY) { return ioSetCursorWithMask(cursorBitsIndex, cursorBitsIndex, offsetX, offsetY); } #endif static sqInt display_ioForceDisplayUpdate(void) { return 0; } #if 0 static void setRects(int w, int h) { DPRINTF(("setRects %d %d\n", w, h)); topRect= NSMakeRect(0,0, w,h); if (fullscreen) { titleRect= NSMakeRect(0, dpyHeight, dpyWidth, 0); resizeRect= NSMakeRect(dpyWidth, 0, 0, 0); } else { void *port= [view qdPort]; titleRect = [NSWindow frameRectForContentRect: topRect styleMask: styleMask]; titleRect.origin.y += h; titleRect.size.height -= h; resizeRect= NSMakeRect(pixWidth - RESIZE_EXTENT, 0, RESIZE_EXTENT, RESIZE_EXTENT); if (port) // no port while window is deferred { PixMapHandle pix; LockPortBits(port); { pix = GetPortPixMap(port); pixPitch = GetPixRowBytes(pix); pixBase = ((char *)GetPixBaseAddr(pix) + ((int)titleRect.size.height * pixPitch)); } UnlockPortBits(port); } } setSavedWindowSize((w << 16) | h); // assume this is atomic } #endif static char *updatePix(void) { void *port= [view qdPort]; assert(win); assert(topView); assert(view); if (port) // no port while window is deferred { int w, h; NSRect winRect= [win frame]; winRect.origin= NSMakePoint(0, 0); // window coordinates topRect= [NSWindow contentRectForFrameRect: winRect styleMask: styleMask]; w= NSWidth(topRect); h= NSHeight(topRect); DPRINTF(("updatePix w=%d h=%d\n", w, h)); setSavedWindowSize((w << 16) | h); // assume this is atomic if (fullscreen) { titleRect= NSMakeRect(0, dpyHeight, dpyWidth, 0); // empty & offscreen resizeRect= NSMakeRect(dpyWidth, 0, 0, 0); // empty & offscreen } else { titleRect= winRect; titleRect.origin.y += h; titleRect.size.height -= h; resizeRect= NSMakeRect(w - RESIZE_EXTENT, 0, RESIZE_EXTENT, RESIZE_EXTENT); } pixWidth= w; pixHeight= h; LockPortBits(port); { PixMapHandle pix= GetPortPixMap(port); pixDepth= GetPixDepth(pix); pixPitch= GetPixRowBytes(pix); assert(pixPitch); assert(pixPitch >= w * (pixDepth / 8)); pixBase= ((char *)GetPixBaseAddr(pix) + ((int)NSHeight(titleRect) * pixPitch)); assert(pixBase); } UnlockPortBits(port); } else { DPRINTF(("updatePix: NO PORT!\n")); pixBase= 0; } DPRINTF(("pixBase %p, width %d, height %d, depth %d, pitch %d\n", pixBase, pixWidth, pixHeight, pixDepth, pixPitch)); return pixBase; } #define bytesPerLine(width, depth) ((((width)*(depth) + 31) >> 5) << 2) static sqInt display_ioShowDisplay(sqInt dispBitsIndex, sqInt width, sqInt height, sqInt depth, sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB) { int affectedW, affectedH; if (headless || (width != pixWidth) || (width < 1) || (height != pixHeight) || (height < 1) || (depth != pixDepth) || ((!pixBase) && !updatePix()) || (displayChanged) || (![view lockFocusIfCanDraw])) { DPRINTF(("ioShowDisplay squashed: dpy %dx%dx%d pix %dx%dx%d\n", (int)width, (int)height, (int)depth, (int)pixWidth, (int)pixHeight, (int)pixDepth)); return 0; } DPRINTF(("ioShowDisplay %p %ldx%ldx%ld %ld,%ld-%ld,%ld\n", (void *)dispBitsIndex, width, height, depth, affectedL, affectedR, affectedT, affectedB)); lock(display); affectedR= min(affectedR, min(width, pixWidth )); affectedB= min(affectedB, min(height, pixHeight)); affectedW= affectedR - affectedL; affectedH= affectedB - affectedT; if ((affectedW > 0) && (affectedH > 0)) { int opp= depth / 8; // octets per pixel char *out= pixBase; int outPitch= pixPitch; void *port= [view qdPort]; LockPortBits(port); //xxx FIXME SOON: cope with dpy depth mismatch (share the code // used by the other types of Unix display) { int pitch= bytesPerLine(width, depth); char *in= pointerForOop(dispBitsIndex) + affectedL * opp + affectedT * pitch; int lines= affectedH; int bytes= affectedW * opp; out += (affectedL * opp) + (affectedT * outPitch); if ((bytes == pitch) && (bytes == outPitch)) memcpy(out, in, bytes * lines); else if (bytes < 9) // empirical while (lines--) { register char *to= out; register char *from= in; register int count= bytes; while (count--) *to++= *from++; in += pitch; out += outPitch; } else while (lines--) { memcpy((void *)out, (void *)in, bytes); in += pitch; out += outPitch; } } SetRectRgn(pixRegion, affectedL, affectedT, affectedR, affectedB); QDFlushPortBuffer([view qdPort], pixRegion); UnlockPortBits(port); } unlock(display); [view unlockFocus]; return 0; } #if 0 static void display_ioFlushDisplay(void) { void *port; lock(display); port= [view qdPort]; LockPortBits(port); SetRectRgn(pixRegion, 0, 0, pixWidth, pixHeight); QDFlushPortBuffer([view qdPort], pixRegion); UnlockPortBits(port); unlock(display); } #endif static sqInt display_ioHasDisplayDepth(sqInt i) { return i == (headless ? 1 : dpyDepth); } static sqInt display_ioSetDisplayMode(sqInt width, sqInt height, sqInt depth, sqInt fullscreenFlag) { if (headless) return 0; printf("ioSetDisplayMode: IMPLEMENT ME\n"); return ((width == dpyWidth) && (height == dpyHeight) && (depth == dpyDepth)); } static void *display_ioGetDisplay(void) { if (headless) return 0; DPRINTF(("ioGetDisplay: WARNING: check the client to see it knows what it's doing\n")); return dpy; } static void *display_ioGetWindow(void) { if (headless) return 0; printf("ioGetWindow: WARNING: check the client to see it knows what it's doing\n"); return 0; } static sqInt display_clipboardWriteFromAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex) { NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; NSPasteboard *pboard= [NSPasteboard generalPasteboard]; char *buf= malloc(count * 2); int len= sq2uxText(pointerForOop(byteArrayIndex) + startIndex, count, buf, count * 2, 1); NSString *string= [NSString stringWithCString: buf length: len]; [pboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: nil]; [pboard setString: string forType: NSStringPboardType]; free(buf); [pool release]; return 0; } static sqInt display_clipboardSize(void) { NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init]; NSPasteboard *pboard= [NSPasteboard generalPasteboard]; NSString *type= [pboard availableTypeFromArray: [NSArray arrayWithObject: NSStringPboardType]]; int clipSize= 0; if (clipboard) free(clipboard); clipboard= 0; if (type != nil) { NSString *contents= [pboard stringForType: type]; if (contents != nil) { const char *cString= [contents cString]; int len= [contents length]; if (len) { clipboard= (char *)malloc(len * 2); if (!clipboard) fprintf(stderr, "could not allocate clipboard\n"); else clipSize= ux2sqText((char *)cString, len, clipboard, len * 2, 1); } } } [pool release]; return clipSize; } static sqInt display_clipboardReadIntoAt(sqInt count, sqInt byteArrayIndex, sqInt startIndex) { if (clipboard) { memcpy(pointerForOop(byteArrayIndex) + startIndex, clipboard, count); return count; } return 0; } static void display_winExit(void) { [win close]; } static void display_winSetName(char *title) { char *base= strrchr(title, '/'); if (base) title= base + 1; #if (RESIZE_IN_TITLE) if (showExtent) { char buf[NAME_MAX]; NSRect frame= [view frame]; sprintf(buf, "%s (%dx%d)", title, (int)NSWidth(frame), (int)NSHeight(frame)); title= buf; } #endif [win setTitle: [NSString stringWithCString: title]]; } static void display_parseEnvironment(void) {} static int display_parseArgument(int argc, char **argv) { if (!strncmp(*argv, "-psn_", 5)) return fromFinder= 1; else if (!strcmp(*argv, "-quartz")) return 1; else if (!strcmp(*argv, "-fullscreen")) return fullscreen= 1; else if (!strcmp(*argv, "-headless")) return headless= 1; else if (!strcmp(*argv, "-notitle")) return noTitle= 1; else if (!strcmp(*argv, "-nodock")) return noDock= 1; else if (!strcmp(*argv, "-swapbtn")) return swapBtn= 1; return 0; } static void display_printUsage(void) { printf("\nQuartz/Aqua